aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--CREDITS22
-rw-r--r--Documentation/00-INDEX24
-rw-r--r--Documentation/CodingStyle7
-rw-r--r--Documentation/DMA-mapping.txt24
-rw-r--r--Documentation/DocBook/Makefile2
-rw-r--r--Documentation/DocBook/deviceiobook.tmpl10
-rw-r--r--Documentation/DocBook/filesystems.tmpl36
-rw-r--r--Documentation/DocBook/gadget.tmpl6
-rw-r--r--Documentation/DocBook/kernel-api.tmpl7
-rw-r--r--Documentation/DocBook/mtdnand.tmpl6
-rw-r--r--Documentation/HOWTO4
-rw-r--r--Documentation/IPMI.txt25
-rw-r--r--Documentation/Intel-IOMMU.txt115
-rw-r--r--Documentation/RCU/00-INDEX22
-rw-r--r--Documentation/SM501.txt5
-rw-r--r--Documentation/SubmitChecklist2
-rw-r--r--Documentation/SubmittingDrivers3
-rw-r--r--Documentation/SubmittingPatches4
-rw-r--r--Documentation/accounting/cgroupstats.txt27
-rw-r--r--Documentation/accounting/getdelays.c44
-rw-r--r--Documentation/arm/00-INDEX22
-rw-r--r--Documentation/arm/Samsung-S3C24XX/DMA.txt18
-rw-r--r--Documentation/atomic_ops.txt73
-rw-r--r--Documentation/block/00-INDEX20
-rw-r--r--Documentation/block/as-iosched.txt21
-rw-r--r--Documentation/block/biodoc.txt4
-rw-r--r--Documentation/block/deadline-iosched.txt25
-rw-r--r--Documentation/block/ioprio.txt2
-rw-r--r--Documentation/block/request.txt2
-rw-r--r--Documentation/block/switching-sched.txt21
-rw-r--r--Documentation/cachetlb.txt33
-rw-r--r--Documentation/cdrom/cdrom-standard.tex2
-rw-r--r--Documentation/cgroups.txt545
-rw-r--r--Documentation/cpu-hotplug.txt4
-rw-r--r--Documentation/cpusets.txt250
-rw-r--r--Documentation/device-mapper/dm-uevent.txt97
-rw-r--r--Documentation/devices.txt2
-rw-r--r--Documentation/dontdiff8
-rw-r--r--Documentation/driver-model/devres.txt4
-rw-r--r--Documentation/early-userspace/README6
-rw-r--r--Documentation/email-clients.txt217
-rw-r--r--Documentation/fb/00-INDEX46
-rw-r--r--Documentation/fb/deferred_io.txt4
-rw-r--r--Documentation/fb/uvesafb.txt188
-rw-r--r--Documentation/feature-removal-schedule.txt100
-rw-r--r--Documentation/filesystems/00-INDEX10
-rw-r--r--Documentation/filesystems/9p.txt32
-rw-r--r--Documentation/filesystems/Exporting115
-rw-r--r--Documentation/filesystems/Locking11
-rw-r--r--Documentation/filesystems/ext3.txt14
-rw-r--r--Documentation/filesystems/files.txt6
-rw-r--r--Documentation/filesystems/locks.txt (renamed from Documentation/locks.txt)10
-rw-r--r--Documentation/filesystems/mandatory-locking.txt (renamed from Documentation/mandatory.txt)21
-rw-r--r--Documentation/filesystems/proc.txt37
-rw-r--r--Documentation/filesystems/quota.txt59
-rw-r--r--Documentation/filesystems/ramfs-rootfs-initramfs.txt14
-rw-r--r--Documentation/filesystems/sysfs.txt2
-rw-r--r--Documentation/filesystems/vfs.txt53
-rw-r--r--Documentation/firmware_class/firmware_sample_firmware_class.c10
-rw-r--r--Documentation/hwmon/sysfs-interface31
-rw-r--r--Documentation/i2c/i2c-protocol2
-rw-r--r--Documentation/i386/boot.txt72
-rw-r--r--Documentation/i386/zero-page.txt122
-rw-r--r--Documentation/ia64/err_inject.txt6
-rw-r--r--Documentation/ide.txt6
-rw-r--r--Documentation/initrd.txt12
-rw-r--r--Documentation/input/atarikbd.txt8
-rw-r--r--Documentation/input/ff.txt2
-rw-r--r--Documentation/input/iforce-protocol.txt20
-rw-r--r--Documentation/input/input-programming.txt17
-rw-r--r--Documentation/isdn/CREDITS2
-rw-r--r--Documentation/isdn/README.concap2
-rw-r--r--Documentation/ja_JP/SubmittingPatches556
-rw-r--r--Documentation/java.txt2
-rw-r--r--Documentation/kbuild/kconfig-language.txt14
-rw-r--r--Documentation/kbuild/makefiles.txt84
-rw-r--r--Documentation/kdump/kdump.txt89
-rw-r--r--Documentation/kernel-docs.txt4
-rw-r--r--Documentation/kernel-parameters.txt124
-rw-r--r--Documentation/keys-request-key.txt25
-rw-r--r--Documentation/keys.txt93
-rw-r--r--Documentation/lguest/Makefile26
-rw-r--r--Documentation/lguest/lguest.c1722
-rw-r--r--Documentation/lguest/lguest.txt72
-rw-r--r--Documentation/local_ops.txt48
-rw-r--r--Documentation/m68k/kernel-options.txt9
-rw-r--r--Documentation/make/headers_install.txt46
-rw-r--r--Documentation/markers.txt83
-rw-r--r--Documentation/memory-barriers.txt14
-rw-r--r--Documentation/memory-hotplug.txt58
-rw-r--r--Documentation/mips/00-INDEX6
-rw-r--r--Documentation/mips/AU1xxx_IDE.README2
-rw-r--r--Documentation/mips/time.README173
-rw-r--r--Documentation/mutex-design.txt7
-rw-r--r--Documentation/networking/00-INDEX12
-rw-r--r--Documentation/networking/3c505.txt3
-rw-r--r--Documentation/networking/Configurable34
-rw-r--r--Documentation/networking/bcm43xx.txt2
-rw-r--r--Documentation/networking/bonding.txt33
-rw-r--r--Documentation/networking/comx.txt248
-rw-r--r--Documentation/networking/ip-sysctl.txt8
-rw-r--r--Documentation/networking/ncsa-telnet16
-rw-r--r--Documentation/networking/net-modules.txt315
-rw-r--r--Documentation/networking/proc_net_tcp.txt5
-rw-r--r--Documentation/networking/pt.txt58
-rw-r--r--Documentation/networking/routing.txt46
-rw-r--r--Documentation/networking/rxrpc.txt9
-rw-r--r--Documentation/networking/slicecom.hun371
-rw-r--r--Documentation/networking/slicecom.txt369
-rw-r--r--Documentation/networking/tc-actions-env-rules.txt29
-rw-r--r--Documentation/networking/udplite.txt6
-rw-r--r--Documentation/parport-lowlevel.txt29
-rw-r--r--Documentation/power/00-INDEX34
-rw-r--r--Documentation/power/basic-pm-debugging.txt4
-rw-r--r--Documentation/power/drivers-testing.txt4
-rw-r--r--Documentation/power/freezing-of-tasks.txt44
-rw-r--r--Documentation/power/interface.txt2
-rw-r--r--Documentation/power/swsusp-and-swap-files.txt2
-rw-r--r--Documentation/powerpc/00-INDEX4
-rw-r--r--Documentation/powerpc/booting-without-of.txt275
-rw-r--r--Documentation/powerpc/eeh-pci-error-recovery.txt4
-rw-r--r--Documentation/powerpc/mpc52xx-device-tree-bindings.txt16
-rw-r--r--Documentation/ramdisk.txt18
-rw-r--r--Documentation/rtc.txt7
-rw-r--r--Documentation/scsi/ChangeLog.ncr53c8xx6
-rw-r--r--Documentation/scsi/aic79xx.txt2
-rw-r--r--Documentation/scsi/aic7xxx.txt6
-rw-r--r--Documentation/scsi/arcmsr_spec.txt2
-rw-r--r--Documentation/scsi/ibmmca.txt60
-rw-r--r--Documentation/scsi/link_power_management_policy.txt19
-rw-r--r--Documentation/scsi/ncr53c8xx.txt14
-rw-r--r--Documentation/scsi/sym53c8xx_2.txt21
-rw-r--r--Documentation/sharedsubtree.txt1
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt115
-rw-r--r--Documentation/sound/alsa/CMIPCI.txt17
-rw-r--r--Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl184
-rw-r--r--Documentation/sound/alsa/OSS-Emulation.txt7
-rw-r--r--Documentation/sound/alsa/hda_codec.txt49
-rw-r--r--Documentation/sound/alsa/powersave.txt41
-rw-r--r--Documentation/sound/alsa/soc/DAI.txt8
-rw-r--r--Documentation/sound/alsa/soc/clocking.txt10
-rw-r--r--Documentation/sound/alsa/soc/codec.txt6
-rw-r--r--Documentation/sound/alsa/soc/dapm.txt4
-rw-r--r--Documentation/sound/alsa/soc/overview.txt17
-rw-r--r--Documentation/sound/alsa/soc/platform.txt2
-rw-r--r--Documentation/sound/alsa/soc/pops_clicks.txt6
-rw-r--r--Documentation/sound/oss/es137164
-rw-r--r--Documentation/spi/pxa2xx2
-rw-r--r--Documentation/spi/spi-summary25
-rw-r--r--Documentation/spi/spidev_test.c6
-rw-r--r--Documentation/sysctl/00-INDEX16
-rw-r--r--Documentation/sysctl/kernel.txt8
-rw-r--r--Documentation/sysctl/vm.txt28
-rw-r--r--Documentation/telephony/00-INDEX4
-rw-r--r--Documentation/thinkpad-acpi.txt29
-rw-r--r--Documentation/usb/usb-serial.txt2
-rw-r--r--Documentation/video4linux/CARDLIST.em28xx3
-rw-r--r--Documentation/vm/00-INDEX20
-rw-r--r--Documentation/vm/numa_memory_policy.txt33
-rw-r--r--Documentation/vm/slabinfo.c27
-rw-r--r--Documentation/w1/00-INDEX8
-rw-r--r--Documentation/w1/masters/00-INDEX6
-rw-r--r--Documentation/w1/masters/ds24822
-rw-r--r--Documentation/w1/masters/ds24902
-rw-r--r--Documentation/watchdog/src/watchdog-simple.c18
-rw-r--r--Documentation/x86_64/mm.txt1
-rw-r--r--Documentation/xterm-linux.xpm61
-rw-r--r--MAINTAINERS159
-rw-r--r--Makefile176
-rw-r--r--README2
-rw-r--r--arch/alpha/Kconfig2
-rw-r--r--arch/alpha/Makefile81
-rw-r--r--arch/alpha/kernel/Makefile2
-rw-r--r--arch/alpha/kernel/entry.S9
-rw-r--r--arch/alpha/kernel/err_marvel.c2
-rw-r--r--arch/alpha/kernel/err_titan.c2
-rw-r--r--arch/alpha/kernel/osf_sys.c2
-rw-r--r--arch/alpha/kernel/pci_iommu.c3
-rw-r--r--arch/alpha/kernel/ptrace.c46
-rw-r--r--arch/alpha/kernel/semaphore.c16
-rw-r--r--arch/alpha/kernel/smp.c1
-rw-r--r--arch/alpha/kernel/sys_alcor.c2
-rw-r--r--arch/alpha/kernel/sys_sio.c2
-rw-r--r--arch/alpha/kernel/traps.c6
-rw-r--r--arch/alpha/kernel/vmlinux.lds.S260
-rw-r--r--arch/alpha/lib/Makefile2
-rw-r--r--arch/alpha/lib/checksum.c2
-rw-r--r--arch/alpha/lib/csum_partial_copy.c2
-rw-r--r--arch/alpha/lib/fls.c2
-rw-r--r--arch/alpha/mm/fault.c6
-rw-r--r--arch/alpha/mm/init.c2
-rw-r--r--arch/alpha/oprofile/Kconfig23
-rw-r--r--arch/alpha/oprofile/op_impl.h2
-rw-r--r--arch/arm/Kconfig29
-rw-r--r--arch/arm/Kconfig-nommu2
-rw-r--r--arch/arm/Makefile16
-rw-r--r--arch/arm/boot/compressed/Makefile2
-rw-r--r--arch/arm/boot/compressed/head-xscale.S4
-rw-r--r--arch/arm/common/Makefile1
-rw-r--r--arch/arm/common/dmabounce.c7
-rw-r--r--arch/arm/common/it8152.c387
-rw-r--r--arch/arm/common/sharpsl_pm.c9
-rw-r--r--arch/arm/configs/cm_x270_defconfig1410
-rw-r--r--arch/arm/configs/omap_h2_1610_defconfig399
-rw-r--r--arch/arm/configs/omap_osk_5912_defconfig1073
-rw-r--r--arch/arm/configs/zylonite_defconfig736
-rw-r--r--arch/arm/kernel/bios32.c28
-rw-r--r--arch/arm/kernel/calls.S1
-rw-r--r--arch/arm/kernel/process.c2
-rw-r--r--arch/arm/kernel/ptrace.c12
-rw-r--r--arch/arm/kernel/relocate_kernel.S29
-rw-r--r--arch/arm/kernel/setup.c51
-rw-r--r--arch/arm/kernel/sys_arm.c2
-rw-r--r--arch/arm/kernel/sys_oabi-compat.c2
-rw-r--r--arch/arm/kernel/traps.c10
-rw-r--r--arch/arm/mach-at91/Kconfig25
-rw-r--r--arch/arm/mach-at91/Makefile5
-rw-r--r--arch/arm/mach-at91/at91rm9200_time.c195
-rw-r--r--arch/arm/mach-at91/at91x40.c67
-rw-r--r--arch/arm/mach-at91/at91x40_time.c80
-rw-r--r--arch/arm/mach-at91/board-eb01.c44
-rw-r--r--arch/arm/mach-at91/generic.h3
-rw-r--r--arch/arm/mach-at91/gpio.c2
-rw-r--r--arch/arm/mach-at91/pm.c7
-rw-r--r--arch/arm/mach-clps7500/core.c6
-rw-r--r--arch/arm/mach-ep93xx/Kconfig6
-rw-r--r--arch/arm/mach-ep93xx/Makefile1
-rw-r--r--arch/arm/mach-ep93xx/edb9307.c91
-rw-r--r--arch/arm/mach-footbridge/cats-hw.c6
-rw-r--r--arch/arm/mach-footbridge/isa.c45
-rw-r--r--arch/arm/mach-iop32x/n2100.c11
-rw-r--r--arch/arm/mach-ixp2000/Kconfig2
-rw-r--r--arch/arm/mach-netx/xc.c6
-rw-r--r--arch/arm/mach-ns9xxx/Makefile2
-rw-r--r--arch/arm/mach-ns9xxx/board-a9m9750dev.c70
-rw-r--r--arch/arm/mach-ns9xxx/gpio.c190
-rw-r--r--arch/arm/mach-ns9xxx/irq.c50
-rw-r--r--arch/arm/mach-ns9xxx/time.c172
-rw-r--r--arch/arm/mach-omap1/Kconfig38
-rw-r--r--arch/arm/mach-omap1/Makefile3
-rw-r--r--arch/arm/mach-omap1/board-ams-delta.c120
-rw-r--r--arch/arm/mach-omap1/board-h2.c83
-rw-r--r--arch/arm/mach-omap1/board-h3.c41
-rw-r--r--arch/arm/mach-omap1/board-nokia770.c98
-rw-r--r--arch/arm/mach-omap1/board-osk.c55
-rw-r--r--arch/arm/mach-omap1/board-palmte.c377
-rw-r--r--arch/arm/mach-omap1/board-palmtt.c357
-rw-r--r--arch/arm/mach-omap1/board-palmz71.c383
-rw-r--r--arch/arm/mach-omap1/board-sx1.c494
-rw-r--r--arch/arm/mach-omap1/board-voiceblue.c2
-rw-r--r--arch/arm/mach-omap1/clock.c34
-rw-r--r--arch/arm/mach-omap1/clock.h35
-rw-r--r--arch/arm/mach-omap1/irq.c2
-rw-r--r--arch/arm/mach-omap1/leds-innovator.c3
-rw-r--r--arch/arm/mach-omap1/mux.c24
-rw-r--r--arch/arm/mach-omap1/pm.c34
-rw-r--r--arch/arm/mach-omap2/Kconfig11
-rw-r--r--arch/arm/mach-omap2/Makefile1
-rw-r--r--arch/arm/mach-omap2/board-2430sdp.c218
-rw-r--r--arch/arm/mach-omap2/board-apollon.c99
-rw-r--r--arch/arm/mach-omap2/board-h4.c46
-rw-r--r--arch/arm/mach-omap2/clock.c2
-rw-r--r--arch/arm/mach-omap2/devices.c6
-rw-r--r--arch/arm/mach-omap2/gpmc.c47
-rw-r--r--arch/arm/mach-omap2/id.c6
-rw-r--r--arch/arm/mach-omap2/io.c22
-rw-r--r--arch/arm/mach-omap2/irq.c19
-rw-r--r--arch/arm/mach-omap2/memory.c18
-rw-r--r--arch/arm/mach-omap2/mux.c38
-rw-r--r--arch/arm/mach-omap2/pm.c35
-rw-r--r--arch/arm/mach-omap2/timer-gp.c2
-rw-r--r--arch/arm/mach-omap2/usb-tusb6010.c349
-rw-r--r--arch/arm/mach-pnx4008/pm.c6
-rw-r--r--arch/arm/mach-pxa/Kconfig34
-rw-r--r--arch/arm/mach-pxa/Makefile47
-rw-r--r--arch/arm/mach-pxa/clock.c79
-rw-r--r--arch/arm/mach-pxa/clock.h43
-rw-r--r--arch/arm/mach-pxa/cm-x270-pci.c218
-rw-r--r--arch/arm/mach-pxa/cm-x270-pci.h13
-rw-r--r--arch/arm/mach-pxa/cm-x270.c645
-rw-r--r--arch/arm/mach-pxa/devices.h3
-rw-r--r--arch/arm/mach-pxa/generic.c184
-rw-r--r--arch/arm/mach-pxa/generic.h26
-rw-r--r--arch/arm/mach-pxa/irq.c80
-rw-r--r--arch/arm/mach-pxa/lubbock.c19
-rw-r--r--arch/arm/mach-pxa/mainstone.c19
-rw-r--r--arch/arm/mach-pxa/mfp.c235
-rw-r--r--arch/arm/mach-pxa/pm.c4
-rw-r--r--arch/arm/mach-pxa/pxa25x.c94
-rw-r--r--arch/arm/mach-pxa/pxa27x.c129
-rw-r--r--arch/arm/mach-pxa/pxa300.c95
-rw-r--r--arch/arm/mach-pxa/pxa320.c88
-rw-r--r--arch/arm/mach-pxa/pxa3xx.c216
-rw-r--r--arch/arm/mach-pxa/time.c79
-rw-r--r--arch/arm/mach-pxa/zylonite.c184
-rw-r--r--arch/arm/mach-pxa/zylonite_pxa300.c188
-rw-r--r--arch/arm/mach-pxa/zylonite_pxa320.c173
-rw-r--r--arch/arm/mach-s3c2410/clock.c2
-rw-r--r--arch/arm/mach-s3c2410/dma.c2
-rw-r--r--arch/arm/mach-s3c2410/mach-amlm5900.c54
-rw-r--r--arch/arm/mach-s3c2410/mach-bast.c83
-rw-r--r--arch/arm/mach-s3c2410/mach-h1940.c56
-rw-r--r--arch/arm/mach-s3c2410/mach-qt2410.c219
-rw-r--r--arch/arm/mach-s3c2412/clock.c2
-rw-r--r--arch/arm/mach-s3c2412/dma.c2
-rw-r--r--arch/arm/mach-s3c2412/irq.c58
-rw-r--r--arch/arm/mach-s3c2412/s3c2412.c5
-rw-r--r--arch/arm/mach-s3c2440/dma.c2
-rw-r--r--arch/arm/mach-s3c2440/mach-rx3715.c72
-rw-r--r--arch/arm/mach-s3c2440/mach-smdk2440.c78
-rw-r--r--arch/arm/mach-s3c2443/clock.c2
-rw-r--r--arch/arm/mach-s3c2443/dma.c2
-rw-r--r--arch/arm/mach-s3c2443/irq.c4
-rw-r--r--arch/arm/mach-sa1100/pm.c6
-rw-r--r--arch/arm/mm/Kconfig4
-rw-r--r--arch/arm/mm/alignment.c2
-rw-r--r--arch/arm/mm/consistent.c4
-rw-r--r--arch/arm/mm/fault.c4
-rw-r--r--arch/arm/mm/proc-arm926.S4
-rw-r--r--arch/arm/nwfpe/ARM-gcc.h2
-rw-r--r--arch/arm/nwfpe/entry.S25
-rw-r--r--arch/arm/nwfpe/fpa11.inl8
-rw-r--r--arch/arm/nwfpe/fpopcode.h40
-rw-r--r--arch/arm/oprofile/Kconfig42
-rw-r--r--arch/arm/plat-omap/Kconfig9
-rw-r--r--arch/arm/plat-omap/Makefile1
-rw-r--r--arch/arm/plat-omap/debug-devices.c86
-rw-r--r--arch/arm/plat-omap/dma.c8
-rw-r--r--arch/arm/plat-omap/fb.c2
-rw-r--r--arch/arm/plat-omap/gpio.c2
-rw-r--r--arch/arm/plat-s3c24xx/dma.c4
-rw-r--r--arch/arm/plat-s3c24xx/pm.c6
-rw-r--r--arch/arm/plat-s3c24xx/sleep.S8
-rw-r--r--arch/arm/vfp/Makefile2
-rw-r--r--arch/arm/vfp/vfpdouble.c8
-rw-r--r--arch/arm/vfp/vfpmodule.c2
-rw-r--r--arch/avr32/Kconfig5
-rw-r--r--arch/avr32/Makefile8
-rw-r--r--arch/avr32/boards/atstk1000/atstk1002.c58
-rw-r--r--arch/avr32/kernel/kprobes.c2
-rw-r--r--arch/avr32/kernel/ptrace.c5
-rw-r--r--arch/avr32/kernel/traps.c2
-rw-r--r--arch/avr32/mach-at32ap/at32ap7000.c348
-rw-r--r--arch/avr32/mach-at32ap/extint.c2
-rw-r--r--arch/avr32/mach-at32ap/hsmc.c1
-rw-r--r--arch/avr32/mach-at32ap/intc.c4
-rw-r--r--arch/avr32/mach-at32ap/pm.h4
-rw-r--r--arch/avr32/mach-at32ap/time-tc.c2
-rw-r--r--arch/avr32/mm/dma-coherent.c6
-rw-r--r--arch/avr32/mm/fault.c8
-rw-r--r--arch/blackfin/Kconfig149
-rw-r--r--arch/blackfin/Makefile27
-rw-r--r--arch/blackfin/boot/Makefile3
-rw-r--r--arch/blackfin/boot/install.sh57
-rw-r--r--arch/blackfin/configs/BF527-EZKIT_defconfig1241
-rw-r--r--arch/blackfin/configs/BF533-EZKIT_defconfig2
-rw-r--r--arch/blackfin/configs/BF533-STAMP_defconfig2
-rw-r--r--arch/blackfin/configs/BF537-STAMP_defconfig2
-rw-r--r--arch/blackfin/configs/BF548-EZKIT_defconfig288
-rw-r--r--arch/blackfin/configs/BF561-EZKIT_defconfig2
-rw-r--r--arch/blackfin/configs/PNAV-10_defconfig2
-rw-r--r--arch/blackfin/kernel/Makefile1
-rw-r--r--arch/blackfin/kernel/bfin_dma_5xx.c26
-rw-r--r--arch/blackfin/kernel/bfin_gpio.c35
-rw-r--r--arch/blackfin/kernel/dma-mapping.c4
-rw-r--r--arch/blackfin/kernel/entry.S6
-rw-r--r--arch/blackfin/kernel/fixed_code.S14
-rw-r--r--arch/blackfin/kernel/gptimers.c283
-rw-r--r--arch/blackfin/kernel/ptrace.c6
-rw-r--r--arch/blackfin/kernel/reboot.c2
-rw-r--r--arch/blackfin/kernel/setup.c129
-rw-r--r--arch/blackfin/kernel/traps.c338
-rw-r--r--arch/blackfin/kernel/vmlinux.lds.S11
-rw-r--r--arch/blackfin/lib/Makefile2
-rw-r--r--arch/blackfin/lib/udivdi3.S375
-rw-r--r--arch/blackfin/mach-bf527/Kconfig251
-rw-r--r--arch/blackfin/mach-bf527/Makefile9
-rw-r--r--arch/blackfin/mach-bf527/boards/Makefile7
-rw-r--r--arch/blackfin/mach-bf527/boards/eth_mac.c50
-rw-r--r--arch/blackfin/mach-bf527/boards/ezkit.c790
-rw-r--r--arch/blackfin/mach-bf527/cpu.c161
-rw-r--r--arch/blackfin/mach-bf527/dma.c115
-rw-r--r--arch/blackfin/mach-bf527/head.S456
-rw-r--r--arch/blackfin/mach-bf527/ints-priority.c100
-rw-r--r--arch/blackfin/mach-bf533/boards/H8606.c345
-rw-r--r--arch/blackfin/mach-bf533/boards/Makefile1
-rw-r--r--arch/blackfin/mach-bf533/boards/cm_bf533.c44
-rw-r--r--arch/blackfin/mach-bf533/boards/ezkit.c2
-rw-r--r--arch/blackfin/mach-bf533/boards/generic_board.c2
-rw-r--r--arch/blackfin/mach-bf533/boards/stamp.c6
-rw-r--r--arch/blackfin/mach-bf537/boards/cm_bf537.c6
-rw-r--r--arch/blackfin/mach-bf537/boards/generic_board.c2
-rw-r--r--arch/blackfin/mach-bf537/boards/pnav10.c2
-rw-r--r--arch/blackfin/mach-bf537/boards/stamp.c8
-rw-r--r--arch/blackfin/mach-bf548/boards/ezkit.c10
-rw-r--r--arch/blackfin/mach-bf548/dma.c1
-rw-r--r--arch/blackfin/mach-bf561/boards/cm_bf561.c2
-rw-r--r--arch/blackfin/mach-bf561/boards/ezkit.c2
-rw-r--r--arch/blackfin/mach-bf561/boards/generic_board.c2
-rw-r--r--arch/blackfin/mach-bf561/boards/tepla.c2
-rw-r--r--arch/blackfin/mach-common/entry.S2
-rw-r--r--arch/blackfin/mach-common/ints-priority-dc.c8
-rw-r--r--arch/blackfin/mach-common/ints-priority-sc.c55
-rw-r--r--arch/blackfin/mach-common/pm.c59
-rw-r--r--arch/blackfin/oprofile/Kconfig29
-rw-r--r--arch/cris/Kconfig21
-rw-r--r--arch/cris/Makefile10
-rw-r--r--arch/cris/arch-v10/Kconfig2
-rw-r--r--arch/cris/arch-v10/boot/compressed/misc.c2
-rw-r--r--arch/cris/arch-v10/defconfig2
-rw-r--r--arch/cris/arch-v10/drivers/Kconfig3
-rw-r--r--arch/cris/arch-v10/drivers/axisflashmap.c8
-rw-r--r--arch/cris/arch-v10/drivers/gpio.c15
-rw-r--r--arch/cris/arch-v10/drivers/pcf8563.c2
-rw-r--r--arch/cris/arch-v10/kernel/debugport.c2
-rw-r--r--arch/cris/arch-v10/kernel/entry.S79
-rw-r--r--arch/cris/arch-v10/kernel/fasttimer.c327
-rw-r--r--arch/cris/arch-v10/kernel/io_interface_mux.c2
-rw-r--r--arch/cris/arch-v10/kernel/irq.c61
-rw-r--r--arch/cris/arch-v10/kernel/kgdb.c2
-rw-r--r--arch/cris/arch-v10/kernel/process.c2
-rw-r--r--arch/cris/arch-v10/kernel/ptrace.c4
-rw-r--r--arch/cris/arch-v10/kernel/setup.c5
-rw-r--r--arch/cris/arch-v10/kernel/shadows.c2
-rw-r--r--arch/cris/arch-v10/kernel/time.c19
-rw-r--r--arch/cris/arch-v10/lib/dram_init.S4
-rw-r--r--arch/cris/arch-v10/lib/memset.c82
-rw-r--r--arch/cris/arch-v10/lib/string.c56
-rw-r--r--arch/cris/arch-v10/lib/usercopy.c320
-rw-r--r--arch/cris/arch-v32/boot/compressed/misc.c6
-rw-r--r--arch/cris/arch-v32/drivers/Kconfig2
-rw-r--r--arch/cris/arch-v32/drivers/axisflashmap.c11
-rw-r--r--arch/cris/arch-v32/drivers/i2c.c2
-rw-r--r--arch/cris/arch-v32/drivers/nandflash.c2
-rw-r--r--arch/cris/arch-v32/drivers/pcf8563.c2
-rw-r--r--arch/cris/arch-v32/drivers/sync_serial.c2
-rw-r--r--arch/cris/arch-v32/kernel/cache.c33
-rw-r--r--arch/cris/arch-v32/kernel/cacheflush.S94
-rw-r--r--arch/cris/arch-v32/kernel/fasttimer.c2
-rw-r--r--arch/cris/arch-v32/kernel/io.c2
-rw-r--r--arch/cris/arch-v32/kernel/irq.c8
-rw-r--r--arch/cris/arch-v32/kernel/process.c2
-rw-r--r--arch/cris/arch-v32/kernel/ptrace.c4
-rw-r--r--arch/cris/arch-v32/kernel/setup.c6
-rw-r--r--arch/cris/arch-v32/kernel/signal.c4
-rw-r--r--arch/cris/arch-v32/kernel/smp.c10
-rw-r--r--arch/cris/arch-v32/kernel/time.c2
-rw-r--r--arch/cris/arch-v32/kernel/traps.c2
-rw-r--r--arch/cris/arch-v32/lib/dram_init.S2
-rw-r--r--arch/cris/arch-v32/lib/string.c2
-rw-r--r--arch/cris/arch-v32/lib/usercopy.c6
-rw-r--r--arch/cris/arch-v32/mm/tlb.c6
-rw-r--r--arch/cris/defconfig78
-rw-r--r--arch/cris/kernel/crisksyms.c17
-rw-r--r--arch/cris/kernel/irq.c14
-rw-r--r--arch/cris/kernel/process.c5
-rw-r--r--arch/cris/kernel/ptrace.c6
-rw-r--r--arch/cris/kernel/sys_cris.c3
-rw-r--r--arch/cris/kernel/time.c10
-rw-r--r--arch/cris/mm/fault.c6
-rw-r--r--arch/cris/mm/init.c2
-rw-r--r--arch/cris/mm/tlb.c2
-rw-r--r--arch/frv/Kconfig2
-rw-r--r--arch/frv/Makefile32
-rw-r--r--arch/frv/kernel/irq-mb93091.c2
-rw-r--r--arch/frv/kernel/irq-mb93093.c2
-rw-r--r--arch/frv/kernel/irq-mb93493.c2
-rw-r--r--arch/frv/kernel/irq.c4
-rw-r--r--arch/frv/kernel/semaphore.c2
-rw-r--r--arch/frv/kernel/sys_frv.c2
-rw-r--r--arch/frv/kernel/time.c9
-rw-r--r--arch/frv/mb93090-mb00/pci-dma.c3
-rw-r--r--arch/frv/mm/fault.c2
-rw-r--r--arch/frv/mm/init.c2
-rw-r--r--arch/h8300/Kconfig4
-rw-r--r--arch/h8300/Kconfig.debug6
-rw-r--r--arch/h8300/Makefile14
-rw-r--r--arch/h8300/kernel/irq.c2
-rw-r--r--arch/h8300/kernel/sys_h8300.c2
-rw-r--r--arch/h8300/kernel/time.c2
-rw-r--r--arch/h8300/kernel/traps.c2
-rw-r--r--arch/h8300/lib/Makefile3
-rw-r--r--arch/h8300/platform/h8s/ints.c2
-rw-r--r--arch/h8300/platform/h8s/ints_h8s.c2
-rw-r--r--arch/ia64/Kconfig33
-rw-r--r--arch/ia64/Makefile4
-rw-r--r--arch/ia64/configs/sn2_defconfig107
-rw-r--r--arch/ia64/hp/common/sba_iommu.c18
-rw-r--r--arch/ia64/hp/sim/boot/fw-emu.c2
-rw-r--r--arch/ia64/hp/sim/simscsi.c5
-rw-r--r--arch/ia64/ia32/binfmt_elf32.c2
-rw-r--r--arch/ia64/ia32/elfcore32.h1
-rw-r--r--arch/ia64/ia32/ia32priv.h1
-rw-r--r--arch/ia64/ia32/sys_ia32.c6
-rw-r--r--arch/ia64/kernel/.gitignore1
-rw-r--r--arch/ia64/kernel/acpi.c8
-rw-r--r--arch/ia64/kernel/efi.c21
-rw-r--r--arch/ia64/kernel/gate.lds.S138
-rw-r--r--arch/ia64/kernel/iosapic.c18
-rw-r--r--arch/ia64/kernel/irq.c6
-rw-r--r--arch/ia64/kernel/kprobes.c2
-rw-r--r--arch/ia64/kernel/machine_kexec.c30
-rw-r--r--arch/ia64/kernel/mca.c2
-rw-r--r--arch/ia64/kernel/msi_ia64.c2
-rw-r--r--arch/ia64/kernel/palinfo.c91
-rw-r--r--arch/ia64/kernel/patch.c3
-rw-r--r--arch/ia64/kernel/perfmon.c165
-rw-r--r--arch/ia64/kernel/perfmon_default_smpl.c8
-rw-r--r--arch/ia64/kernel/process.c3
-rw-r--r--arch/ia64/kernel/setup.c165
-rw-r--r--arch/ia64/kernel/signal.c4
-rw-r--r--arch/ia64/kernel/smpboot.c39
-rw-r--r--arch/ia64/kernel/time.c5
-rw-r--r--arch/ia64/kernel/traps.c6
-rw-r--r--arch/ia64/kernel/unaligned.c5
-rw-r--r--arch/ia64/kernel/uncached.c4
-rw-r--r--arch/ia64/mm/contig.c74
-rw-r--r--arch/ia64/mm/discontig.c10
-rw-r--r--arch/ia64/mm/fault.c4
-rw-r--r--arch/ia64/mm/hugetlbpage.c4
-rw-r--r--arch/ia64/mm/init.c26
-rw-r--r--arch/ia64/oprofile/Kconfig20
-rw-r--r--arch/ia64/scripts/check-segrel.lds1
-rw-r--r--arch/ia64/sn/kernel/Makefile2
-rw-r--r--arch/ia64/sn/kernel/irq.c8
-rw-r--r--arch/ia64/sn/kernel/mca.c1
-rw-r--r--arch/ia64/sn/kernel/sn2/Makefile2
-rw-r--r--arch/ia64/sn/kernel/xpc_main.c12
-rw-r--r--arch/ia64/sn/kernel/xpnet.c13
-rw-r--r--arch/ia64/sn/pci/Makefile2
-rw-r--r--arch/ia64/sn/pci/pci_dma.c13
-rw-r--r--arch/ia64/sn/pci/pcibr/Makefile2
-rw-r--r--arch/m32r/Kconfig2
-rw-r--r--arch/m32r/Makefile8
-rw-r--r--arch/m32r/kernel/irq.c2
-rw-r--r--arch/m32r/kernel/ptrace.c50
-rw-r--r--arch/m32r/kernel/signal.c2
-rw-r--r--arch/m32r/kernel/smp.c18
-rw-r--r--arch/m32r/kernel/smpboot.c6
-rw-r--r--arch/m32r/kernel/sys_m32r.c4
-rw-r--r--arch/m32r/kernel/time.c8
-rw-r--r--arch/m32r/kernel/traps.c2
-rw-r--r--arch/m32r/mm/fault.c4
-rw-r--r--arch/m32r/oprofile/Kconfig23
-rw-r--r--arch/m68k/Kconfig2
-rw-r--r--arch/m68k/Makefile8
-rw-r--r--arch/m68k/amiga/pcmcia.c2
-rw-r--r--arch/m68k/ifpsp060/CHANGES2
-rw-r--r--arch/m68k/ifpsp060/MISC2
-rw-r--r--arch/m68k/ifpsp060/README2
-rw-r--r--arch/m68k/ifpsp060/TEST.DOC2
-rw-r--r--arch/m68k/ifpsp060/fplsp.doc2
-rw-r--r--arch/m68k/ifpsp060/fpsp.doc2
-rw-r--r--arch/m68k/ifpsp060/fskeleton.S2
-rw-r--r--arch/m68k/ifpsp060/ilsp.doc2
-rw-r--r--arch/m68k/ifpsp060/iskeleton.S2
-rw-r--r--arch/m68k/ifpsp060/isp.doc2
-rw-r--r--arch/m68k/ifpsp060/os.S2
-rw-r--r--arch/m68k/ifpsp060/src/fplsp.S2
-rw-r--r--arch/m68k/ifpsp060/src/fpsp.S2
-rw-r--r--arch/m68k/ifpsp060/src/ftest.S2
-rw-r--r--arch/m68k/ifpsp060/src/ilsp.S2
-rw-r--r--arch/m68k/ifpsp060/src/isp.S2
-rw-r--r--arch/m68k/ifpsp060/src/itest.S2
-rw-r--r--arch/m68k/ifpsp060/src/pfpsp.S2
-rw-r--r--arch/m68k/kernel/dma.c4
-rw-r--r--arch/m68k/kernel/ptrace.c4
-rw-r--r--arch/m68k/kernel/sys_m68k.c2
-rw-r--r--arch/m68k/kernel/traps.c4
-rw-r--r--arch/m68k/mac/config.c4
-rw-r--r--arch/m68k/mac/iop.c4
-rw-r--r--arch/m68k/mac/oss.c2
-rw-r--r--arch/m68k/mac/via.c2
-rw-r--r--arch/m68k/math-emu/fp_log.c2
-rw-r--r--arch/m68k/mm/fault.c4
-rw-r--r--arch/m68k/q40/q40ints.c4
-rw-r--r--arch/m68k/sun3/mmu_emu.c2
-rw-r--r--arch/m68k/tools/amiga/dmesg.c2
-rw-r--r--arch/m68knommu/Kconfig15
-rw-r--r--arch/m68knommu/Makefile11
-rw-r--r--arch/m68knommu/defconfig325
-rw-r--r--arch/m68knommu/kernel/setup.c32
-rw-r--r--arch/m68knommu/kernel/signal.c10
-rw-r--r--arch/m68knommu/kernel/sys_m68k.c2
-rw-r--r--arch/m68knommu/kernel/time.c22
-rw-r--r--arch/m68knommu/mm/init.c4
-rw-r--r--arch/m68knommu/platform/5206/Makefile2
-rw-r--r--arch/m68knommu/platform/5206/config.c9
-rw-r--r--arch/m68knommu/platform/5206e/Makefile2
-rw-r--r--arch/m68knommu/platform/5206e/config.c10
-rw-r--r--arch/m68knommu/platform/520x/Makefile2
-rw-r--r--arch/m68knommu/platform/520x/config.c8
-rw-r--r--arch/m68knommu/platform/523x/Makefile2
-rw-r--r--arch/m68knommu/platform/523x/config.c8
-rw-r--r--arch/m68knommu/platform/5249/Makefile2
-rw-r--r--arch/m68knommu/platform/5249/config.c10
-rw-r--r--arch/m68knommu/platform/5272/Makefile2
-rw-r--r--arch/m68knommu/platform/5272/config.c10
-rw-r--r--arch/m68knommu/platform/527x/Makefile2
-rw-r--r--arch/m68knommu/platform/527x/config.c8
-rw-r--r--arch/m68knommu/platform/528x/Makefile2
-rw-r--r--arch/m68knommu/platform/528x/config.c8
-rw-r--r--arch/m68knommu/platform/5307/Makefile2
-rw-r--r--arch/m68knommu/platform/5307/config.c10
-rw-r--r--arch/m68knommu/platform/5307/entry.S5
-rw-r--r--arch/m68knommu/platform/5307/pit.c17
-rw-r--r--arch/m68knommu/platform/5307/timers.c19
-rw-r--r--arch/m68knommu/platform/532x/Makefile2
-rw-r--r--arch/m68knommu/platform/532x/config.c10
-rw-r--r--arch/m68knommu/platform/5407/Makefile2
-rw-r--r--arch/m68knommu/platform/5407/config.c10
-rw-r--r--arch/m68knommu/platform/68328/config.c24
-rw-r--r--arch/m68knommu/platform/68328/timers.c27
-rw-r--r--arch/m68knommu/platform/68360/config.c51
-rw-r--r--arch/m68knommu/platform/68EZ328/config.c19
-rw-r--r--arch/m68knommu/platform/68VZ328/config.c12
-rw-r--r--arch/mips/Kconfig64
-rw-r--r--arch/mips/Kconfig.debug12
-rw-r--r--arch/mips/Makefile27
-rw-r--r--arch/mips/au1000/Kconfig2
-rw-r--r--arch/mips/au1000/common/au1xxx_irqmap.c2
-rw-r--r--arch/mips/au1000/common/dbdma.c2
-rw-r--r--arch/mips/au1000/common/irq.c753
-rw-r--r--arch/mips/au1000/common/power.c7
-rw-r--r--arch/mips/au1000/common/prom.c61
-rw-r--r--arch/mips/au1000/common/setup.c5
-rw-r--r--arch/mips/au1000/common/time.c22
-rw-r--r--arch/mips/au1000/db1x00/init.c10
-rw-r--r--arch/mips/au1000/db1x00/irqmap.c2
-rw-r--r--arch/mips/au1000/mtx-1/Makefile3
-rw-r--r--arch/mips/au1000/mtx-1/init.c6
-rw-r--r--arch/mips/au1000/mtx-1/irqmap.c2
-rw-r--r--arch/mips/au1000/mtx-1/platform.c77
-rw-r--r--arch/mips/au1000/pb1000/init.c10
-rw-r--r--arch/mips/au1000/pb1000/irqmap.c2
-rw-r--r--arch/mips/au1000/pb1100/init.c10
-rw-r--r--arch/mips/au1000/pb1100/irqmap.c2
-rw-r--r--arch/mips/au1000/pb1200/Makefile2
-rw-r--r--arch/mips/au1000/pb1200/board_setup.c12
-rw-r--r--arch/mips/au1000/pb1200/init.c10
-rw-r--r--arch/mips/au1000/pb1200/irqmap.c106
-rw-r--r--arch/mips/au1000/pb1500/init.c10
-rw-r--r--arch/mips/au1000/pb1500/irqmap.c2
-rw-r--r--arch/mips/au1000/pb1550/init.c10
-rw-r--r--arch/mips/au1000/pb1550/irqmap.c2
-rw-r--r--arch/mips/au1000/xxs1500/init.c10
-rw-r--r--arch/mips/au1000/xxs1500/irqmap.c2
-rw-r--r--arch/mips/basler/excite/excite_irq.c2
-rw-r--r--arch/mips/basler/excite/excite_setup.c21
-rw-r--r--arch/mips/bcm47xx/time.c7
-rw-r--r--arch/mips/cobalt/Makefile2
-rw-r--r--arch/mips/cobalt/setup.c24
-rw-r--r--arch/mips/cobalt/time.c35
-rw-r--r--arch/mips/configs/db1000_defconfig1
-rw-r--r--arch/mips/configs/db1100_defconfig1
-rw-r--r--arch/mips/configs/db1200_defconfig1
-rw-r--r--arch/mips/configs/db1500_defconfig1
-rw-r--r--arch/mips/configs/db1550_defconfig1
-rw-r--r--arch/mips/configs/ip27_defconfig1
-rw-r--r--arch/mips/configs/mipssim_defconfig532
-rw-r--r--arch/mips/configs/mtx1_defconfig2
-rw-r--r--arch/mips/configs/pb1100_defconfig1
-rw-r--r--arch/mips/configs/pb1500_defconfig1
-rw-r--r--arch/mips/configs/pb1550_defconfig1
-rw-r--r--arch/mips/configs/sb1250-swarm_defconfig3
-rw-r--r--arch/mips/emma2rh/markeins/setup.c6
-rw-r--r--arch/mips/gt64120/wrppmc/time.c6
-rw-r--r--arch/mips/jazz/irq.c33
-rw-r--r--arch/mips/jazz/setup.c8
-rw-r--r--arch/mips/jmr3927/rbhma3100/setup.c71
-rw-r--r--arch/mips/kernel/Makefile10
-rw-r--r--arch/mips/kernel/cevt-bcm1480.c153
-rw-r--r--arch/mips/kernel/cevt-gt641xx.c142
-rw-r--r--arch/mips/kernel/cevt-r4k.c290
-rw-r--r--arch/mips/kernel/cevt-sb1250.c152
-rw-r--r--arch/mips/kernel/cevt-txx9.c171
-rw-r--r--arch/mips/kernel/cpu-probe.c5
-rw-r--r--arch/mips/kernel/csrc-bcm1480.c54
-rw-r--r--arch/mips/kernel/csrc-sb1250.c70
-rw-r--r--arch/mips/kernel/genex.S2
-rw-r--r--arch/mips/kernel/head.S20
-rw-r--r--arch/mips/kernel/i8253.c25
-rw-r--r--arch/mips/kernel/irixelf.c16
-rw-r--r--arch/mips/kernel/irixsig.c11
-rw-r--r--arch/mips/kernel/irq-rm7000.c2
-rw-r--r--arch/mips/kernel/irq-rm9000.c2
-rw-r--r--arch/mips/kernel/irq_cpu.c2
-rw-r--r--arch/mips/kernel/linux32.c2
-rw-r--r--arch/mips/kernel/module.c2
-rw-r--r--arch/mips/kernel/proc.c2
-rw-r--r--arch/mips/kernel/ptrace.c22
-rw-r--r--arch/mips/kernel/ptrace32.c4
-rw-r--r--arch/mips/kernel/scall64-n32.S2
-rw-r--r--arch/mips/kernel/smtc.c57
-rw-r--r--arch/mips/kernel/syscall.c11
-rw-r--r--arch/mips/kernel/sysirix.c4
-rw-r--r--arch/mips/kernel/time.c385
-rw-r--r--arch/mips/kernel/traps.c266
-rw-r--r--arch/mips/kernel/vmlinux.lds.S47
-rw-r--r--arch/mips/kernel/vpe.c45
-rw-r--r--arch/mips/lasat/interrupt.c26
-rw-r--r--arch/mips/lasat/setup.c7
-rw-r--r--arch/mips/lemote/lm2e/setup.c5
-rw-r--r--arch/mips/mips-boards/generic/time.c65
-rw-r--r--arch/mips/mipssim/sim_cmdline.c5
-rw-r--r--arch/mips/mipssim/sim_time.c52
-rw-r--r--arch/mips/mm/c-r3k.c60
-rw-r--r--arch/mips/mm/c-r4k.c38
-rw-r--r--arch/mips/mm/cache.c2
-rw-r--r--arch/mips/mm/cerr-sb1.c6
-rw-r--r--arch/mips/mm/dma-default.c17
-rw-r--r--arch/mips/mm/fault.c4
-rw-r--r--arch/mips/mm/init.c21
-rw-r--r--arch/mips/oprofile/Kconfig23
-rw-r--r--arch/mips/pci/fixup-pmcmsp.c2
-rw-r--r--arch/mips/pci/fixup-sni.c23
-rw-r--r--arch/mips/pci/fixup-tb0219.c2
-rw-r--r--arch/mips/pci/ops-pmcmsp.c4
-rw-r--r--arch/mips/pci/pci-excite.c2
-rw-r--r--arch/mips/pci/pci-lasat.c31
-rw-r--r--arch/mips/pci/pci-vr41xx.c1
-rw-r--r--arch/mips/pmc-sierra/Kconfig2
-rw-r--r--arch/mips/pmc-sierra/msp71xx/msp_serial.c2
-rw-r--r--arch/mips/pmc-sierra/msp71xx/msp_time.c3
-rw-r--r--arch/mips/pmc-sierra/yosemite/setup.c5
-rw-r--r--arch/mips/qemu/Makefile3
-rw-r--r--arch/mips/qemu/q-console.c26
-rw-r--r--arch/mips/qemu/q-firmware.c6
-rw-r--r--arch/mips/qemu/q-irq.c1
-rw-r--r--arch/mips/qemu/q-setup.c3
-rw-r--r--arch/mips/sgi-ip22/Makefile2
-rw-r--r--arch/mips/sgi-ip22/ip22-reset.c9
-rw-r--r--arch/mips/sgi-ip22/ip22-time.c9
-rw-r--r--arch/mips/sgi-ip27/ip27-init.c2
-rw-r--r--arch/mips/sgi-ip27/ip27-irq.c5
-rw-r--r--arch/mips/sgi-ip27/ip27-timer.c186
-rw-r--r--arch/mips/sgi-ip32/ip32-irq.c272
-rw-r--r--arch/mips/sgi-ip32/ip32-platform.c2
-rw-r--r--arch/mips/sgi-ip32/ip32-setup.c6
-rw-r--r--arch/mips/sibyte/Kconfig14
-rw-r--r--arch/mips/sibyte/bcm1480/irq.c110
-rw-r--r--arch/mips/sibyte/bcm1480/smp.c9
-rw-r--r--arch/mips/sibyte/bcm1480/time.c157
-rw-r--r--arch/mips/sibyte/sb1250/irq.c101
-rw-r--r--arch/mips/sibyte/sb1250/smp.c9
-rw-r--r--arch/mips/sibyte/sb1250/time.c248
-rw-r--r--arch/mips/sibyte/swarm/setup.c25
-rw-r--r--arch/mips/sni/pcimt.c4
-rw-r--r--arch/mips/sni/time.c105
-rw-r--r--arch/mips/tx4927/common/tx4927_setup.c16
-rw-r--r--arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c29
-rw-r--r--arch/mips/tx4938/common/setup.c7
-rw-r--r--arch/mips/tx4938/toshiba_rbtx4938/setup.c19
-rw-r--r--arch/mips/vr41xx/Kconfig6
-rw-r--r--arch/mips/vr41xx/common/icu.c2
-rw-r--r--arch/mips/vr41xx/common/init.c5
-rw-r--r--arch/parisc/Kconfig2
-rw-r--r--arch/parisc/Makefile60
-rw-r--r--arch/parisc/configs/712_defconfig446
-rw-r--r--arch/parisc/configs/a500_defconfig646
-rw-r--r--arch/parisc/configs/b180_defconfig474
-rw-r--r--arch/parisc/configs/c3000_defconfig582
-rw-r--r--arch/parisc/defconfig615
-rw-r--r--arch/parisc/hpux/gate.S4
-rw-r--r--arch/parisc/kernel/asm-offsets.c3
-rw-r--r--arch/parisc/kernel/entry.S41
-rw-r--r--arch/parisc/kernel/head.S6
-rw-r--r--arch/parisc/kernel/hpmc.S4
-rw-r--r--arch/parisc/kernel/init_task.c1
-rw-r--r--arch/parisc/kernel/pacache.S8
-rw-r--r--arch/parisc/kernel/parisc_ksyms.c22
-rw-r--r--arch/parisc/kernel/pci-dma.c10
-rw-r--r--arch/parisc/kernel/pci.c42
-rw-r--r--arch/parisc/kernel/processor.c7
-rw-r--r--arch/parisc/kernel/ptrace.c4
-rw-r--r--arch/parisc/kernel/signal.c2
-rw-r--r--arch/parisc/kernel/smp.c12
-rw-r--r--arch/parisc/kernel/sys_parisc32.c7
-rw-r--r--arch/parisc/kernel/syscall.S13
-rw-r--r--arch/parisc/kernel/syscall_table.S1
-rw-r--r--arch/parisc/kernel/time.c6
-rw-r--r--arch/parisc/kernel/traps.c10
-rw-r--r--arch/parisc/kernel/unaligned.c2
-rw-r--r--arch/parisc/kernel/unwind.c4
-rw-r--r--arch/parisc/kernel/vmlinux.lds.S313
-rw-r--r--arch/parisc/lib/Makefile2
-rw-r--r--arch/parisc/lib/libgcc/Makefile4
-rw-r--r--arch/parisc/lib/libgcc/__ashldi3.c19
-rw-r--r--arch/parisc/lib/libgcc/__ashrdi3.c19
-rw-r--r--arch/parisc/lib/libgcc/__clzsi2.c30
-rw-r--r--arch/parisc/lib/libgcc/__divdi3.c23
-rw-r--r--arch/parisc/lib/libgcc/__divsi3.c23
-rw-r--r--arch/parisc/lib/libgcc/__lshrdi3.c19
-rw-r--r--arch/parisc/lib/libgcc/__moddi3.c23
-rw-r--r--arch/parisc/lib/libgcc/__modsi3.c23
-rw-r--r--arch/parisc/lib/libgcc/__muldi3.c22
-rw-r--r--arch/parisc/lib/libgcc/__udivdi3.c7
-rw-r--r--arch/parisc/lib/libgcc/__udivmoddi4.c31
-rw-r--r--arch/parisc/lib/libgcc/__udivmodsi4.c31
-rw-r--r--arch/parisc/lib/libgcc/__udivsi3.c7
-rw-r--r--arch/parisc/lib/libgcc/__umoddi3.c10
-rw-r--r--arch/parisc/lib/libgcc/__umodsi3.c10
-rw-r--r--arch/parisc/lib/libgcc/__umulsidi3.c46
-rw-r--r--arch/parisc/lib/libgcc/libgcc.h32
-rw-r--r--arch/parisc/lib/memcpy.c4
-rw-r--r--arch/parisc/lib/milli/Makefile1
-rw-r--r--arch/parisc/lib/milli/divI.S254
-rw-r--r--arch/parisc/lib/milli/divU.S235
-rw-r--r--arch/parisc/lib/milli/div_const.S682
-rw-r--r--arch/parisc/lib/milli/dyncall.S32
-rw-r--r--arch/parisc/lib/milli/milli.S2071
-rw-r--r--arch/parisc/lib/milli/milli.h165
-rw-r--r--arch/parisc/lib/milli/mulI.S474
-rw-r--r--arch/parisc/lib/milli/remI.S185
-rw-r--r--arch/parisc/lib/milli/remU.S148
-rw-r--r--arch/parisc/math-emu/Makefile2
-rw-r--r--arch/parisc/mm/fault.c4
-rw-r--r--arch/parisc/mm/init.c2
-rw-r--r--arch/parisc/oprofile/Kconfig23
-rw-r--r--arch/powerpc/Kconfig21
-rw-r--r--arch/powerpc/Kconfig.debug7
-rw-r--r--arch/powerpc/Makefile33
-rw-r--r--arch/powerpc/boot/dts/bamboo.dts10
-rw-r--r--arch/powerpc/boot/dts/lite5200.dts26
-rw-r--r--arch/powerpc/boot/dts/lite5200b.dts44
-rw-r--r--arch/powerpc/boot/dts/sequoia.dts14
-rw-r--r--arch/powerpc/boot/dts/walnut.dts16
-rw-r--r--arch/powerpc/boot/treeboot-walnut.c6
-rwxr-xr-xarch/powerpc/boot/wrapper43
-rw-r--r--arch/powerpc/configs/bamboo_defconfig121
-rw-r--r--arch/powerpc/configs/cell_defconfig1
-rw-r--r--arch/powerpc/configs/celleb_defconfig7
-rw-r--r--arch/powerpc/configs/chrp32_defconfig7
-rw-r--r--arch/powerpc/configs/ebony_defconfig122
-rw-r--r--arch/powerpc/configs/g5_defconfig7
-rw-r--r--arch/powerpc/configs/holly_defconfig7
-rw-r--r--arch/powerpc/configs/iseries_defconfig7
-rw-r--r--arch/powerpc/configs/kilauea_defconfig7
-rw-r--r--arch/powerpc/configs/linkstation_defconfig7
-rw-r--r--arch/powerpc/configs/lite5200_defconfig7
-rw-r--r--arch/powerpc/configs/maple_defconfig8
-rw-r--r--arch/powerpc/configs/mpc7448_hpc2_defconfig5
-rw-r--r--arch/powerpc/configs/mpc8272_ads_defconfig7
-rw-r--r--arch/powerpc/configs/mpc8313_rdb_defconfig7
-rw-r--r--arch/powerpc/configs/mpc832x_mds_defconfig5
-rw-r--r--arch/powerpc/configs/mpc832x_rdb_defconfig5
-rw-r--r--arch/powerpc/configs/mpc834x_itx_defconfig5
-rw-r--r--arch/powerpc/configs/mpc834x_itxgp_defconfig5
-rw-r--r--arch/powerpc/configs/mpc834x_mds_defconfig5
-rw-r--r--arch/powerpc/configs/mpc836x_mds_defconfig5
-rw-r--r--arch/powerpc/configs/mpc8540_ads_defconfig7
-rw-r--r--arch/powerpc/configs/mpc8544_ds_defconfig7
-rw-r--r--arch/powerpc/configs/mpc8560_ads_defconfig7
-rw-r--r--arch/powerpc/configs/mpc8568mds_defconfig7
-rw-r--r--arch/powerpc/configs/mpc8572_ds_defconfig7
-rw-r--r--arch/powerpc/configs/mpc85xx_cds_defconfig7
-rw-r--r--arch/powerpc/configs/mpc8610_hpcd_defconfig7
-rw-r--r--arch/powerpc/configs/mpc8641_hpcn_defconfig7
-rw-r--r--arch/powerpc/configs/mpc866_ads_defconfig5
-rw-r--r--arch/powerpc/configs/pasemi_defconfig315
-rw-r--r--arch/powerpc/configs/pmac32_defconfig8
-rw-r--r--arch/powerpc/configs/ppc64_defconfig259
-rw-r--r--arch/powerpc/configs/pq2fads_defconfig7
-rw-r--r--arch/powerpc/configs/prpmc2800_defconfig5
-rw-r--r--arch/powerpc/configs/ps3_defconfig7
-rw-r--r--arch/powerpc/configs/pseries_defconfig12
-rw-r--r--arch/powerpc/configs/sequoia_defconfig7
-rw-r--r--arch/powerpc/configs/walnut_defconfig101
-rw-r--r--arch/powerpc/kernel/asm-offsets.c1
-rw-r--r--arch/powerpc/kernel/binfmt_elf32.c67
-rw-r--r--arch/powerpc/kernel/btext.c4
-rw-r--r--arch/powerpc/kernel/cpu_setup_6xx.S2
-rw-r--r--arch/powerpc/kernel/cputable.c36
-rw-r--r--arch/powerpc/kernel/dma_64.c8
-rw-r--r--arch/powerpc/kernel/entry_32.S29
-rw-r--r--arch/powerpc/kernel/entry_64.S6
-rw-r--r--arch/powerpc/kernel/head_64.S2
-rw-r--r--arch/powerpc/kernel/ibmebus.c273
-rw-r--r--arch/powerpc/kernel/idle.c2
-rw-r--r--arch/powerpc/kernel/iommu.c25
-rw-r--r--arch/powerpc/kernel/irq.c2
-rw-r--r--arch/powerpc/kernel/kprobes.c2
-rw-r--r--arch/powerpc/kernel/l2cr_6xx.S2
-rw-r--r--arch/powerpc/kernel/machine_kexec.c54
-rw-r--r--arch/powerpc/kernel/misc_32.S32
-rw-r--r--arch/powerpc/kernel/of_device.c80
-rw-r--r--arch/powerpc/kernel/of_platform.c70
-rw-r--r--arch/powerpc/kernel/process.c32
-rw-r--r--arch/powerpc/kernel/prom.c12
-rw-r--r--arch/powerpc/kernel/prom_init.c2
-rw-r--r--arch/powerpc/kernel/ptrace.c4
-rw-r--r--arch/powerpc/kernel/rtas_flash.c2
-rw-r--r--arch/powerpc/kernel/setup-common.c20
-rw-r--r--arch/powerpc/kernel/setup_64.c35
-rw-r--r--arch/powerpc/kernel/smp.c4
-rw-r--r--arch/powerpc/kernel/swsusp_32.S2
-rw-r--r--arch/powerpc/kernel/sys_ppc32.c2
-rw-r--r--arch/powerpc/kernel/syscalls.c1
-rw-r--r--arch/powerpc/kernel/time.c67
-rw-r--r--arch/powerpc/kernel/traps.c4
-rw-r--r--arch/powerpc/kernel/vdso32/vdso32.lds.S219
-rw-r--r--arch/powerpc/kernel/vdso64/sigtramp.S11
-rw-r--r--arch/powerpc/kernel/vdso64/vdso64.lds.S225
-rw-r--r--arch/powerpc/kernel/vmlinux.lds.S3
-rw-r--r--arch/powerpc/lib/Makefile5
-rw-r--r--arch/powerpc/lib/rheap.c15
-rw-r--r--arch/powerpc/math-emu/math.c13
-rw-r--r--arch/powerpc/mm/40x_mmu.c17
-rw-r--r--arch/powerpc/mm/44x_mmu.c1
-rw-r--r--arch/powerpc/mm/fault.c4
-rw-r--r--arch/powerpc/mm/hash_low_64.S5
-rw-r--r--arch/powerpc/mm/hash_utils_64.c10
-rw-r--r--arch/powerpc/mm/hugetlbpage.c2
-rw-r--r--arch/powerpc/mm/init_64.c82
-rw-r--r--arch/powerpc/mm/mem.c45
-rw-r--r--arch/powerpc/mm/mmu_decl.h4
-rw-r--r--arch/powerpc/mm/slb.c38
-rw-r--r--arch/powerpc/mm/slice.c2
-rw-r--r--arch/powerpc/mm/tlb_64.c2
-rw-r--r--arch/powerpc/oprofile/Kconfig24
-rw-r--r--arch/powerpc/platforms/40x/Kconfig1
-rw-r--r--arch/powerpc/platforms/44x/Kconfig8
-rw-r--r--arch/powerpc/platforms/52xx/lite5200.c4
-rw-r--r--arch/powerpc/platforms/52xx/lite5200_pm.c34
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_common.c71
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_pm.c15
-rw-r--r--arch/powerpc/platforms/Kconfig8
-rw-r--r--arch/powerpc/platforms/Kconfig.cputype2
-rw-r--r--arch/powerpc/platforms/cell/axon_msi.c11
-rw-r--r--arch/powerpc/platforms/cell/cbe_cpufreq.c2
-rw-r--r--arch/powerpc/platforms/cell/interrupt.c24
-rw-r--r--arch/powerpc/platforms/cell/smp.c1
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c2
-rw-r--r--arch/powerpc/platforms/cell/spufs/inode.c2
-rw-r--r--arch/powerpc/platforms/celleb/scc_uhc.c2
-rw-r--r--arch/powerpc/platforms/celleb/setup.c1
-rw-r--r--arch/powerpc/platforms/iseries/htab.c4
-rw-r--r--arch/powerpc/platforms/iseries/irq.h4
-rw-r--r--arch/powerpc/platforms/iseries/setup.c4
-rw-r--r--arch/powerpc/platforms/iseries/vio.c12
-rw-r--r--arch/powerpc/platforms/maple/setup.c2
-rw-r--r--arch/powerpc/platforms/pasemi/setup.c56
-rw-r--r--arch/powerpc/platforms/ps3/system-bus.c12
-rw-r--r--arch/powerpc/platforms/pseries/eeh.c13
-rw-r--r--arch/powerpc/platforms/pseries/eeh_driver.c18
-rw-r--r--arch/powerpc/platforms/pseries/firmware.c1
-rw-r--r--arch/powerpc/platforms/pseries/msi.c6
-rw-r--r--arch/powerpc/platforms/pseries/ras.c2
-rw-r--r--arch/powerpc/sysdev/Makefile1
-rw-r--r--arch/powerpc/sysdev/bestcomm/Kconfig39
-rw-r--r--arch/powerpc/sysdev/bestcomm/Makefile14
-rw-r--r--arch/powerpc/sysdev/bestcomm/ata.c154
-rw-r--r--arch/powerpc/sysdev/bestcomm/ata.h37
-rw-r--r--arch/powerpc/sysdev/bestcomm/bcom_ata_task.c67
-rw-r--r--arch/powerpc/sysdev/bestcomm/bcom_fec_rx_task.c78
-rw-r--r--arch/powerpc/sysdev/bestcomm/bcom_fec_tx_task.c91
-rw-r--r--arch/powerpc/sysdev/bestcomm/bcom_gen_bd_rx_task.c63
-rw-r--r--arch/powerpc/sysdev/bestcomm/bcom_gen_bd_tx_task.c69
-rw-r--r--arch/powerpc/sysdev/bestcomm/bestcomm.c531
-rw-r--r--arch/powerpc/sysdev/bestcomm/bestcomm.h190
-rw-r--r--arch/powerpc/sysdev/bestcomm/bestcomm_priv.h334
-rw-r--r--arch/powerpc/sysdev/bestcomm/fec.c270
-rw-r--r--arch/powerpc/sysdev/bestcomm/fec.h61
-rw-r--r--arch/powerpc/sysdev/bestcomm/gen_bd.c260
-rw-r--r--arch/powerpc/sysdev/bestcomm/gen_bd.h48
-rw-r--r--arch/powerpc/sysdev/bestcomm/sram.c177
-rw-r--r--arch/powerpc/sysdev/bestcomm/sram.h54
-rw-r--r--arch/powerpc/sysdev/cpm_common.c4
-rw-r--r--arch/powerpc/sysdev/dcr.c4
-rw-r--r--arch/powerpc/sysdev/fsl_pci.c2
-rw-r--r--arch/powerpc/sysdev/i8259.c1
-rw-r--r--arch/powerpc/sysdev/mpic.c4
-rw-r--r--arch/powerpc/sysdev/mv64x60_pci.c10
-rw-r--r--arch/ppc/Kconfig8
-rw-r--r--arch/ppc/Makefile16
-rw-r--r--arch/ppc/boot/Makefile3
-rw-r--r--arch/ppc/kernel/entry.S29
-rw-r--r--arch/ppc/kernel/misc.S31
-rw-r--r--arch/ppc/kernel/traps.c2
-rw-r--r--arch/ppc/mm/44x_mmu.c1
-rw-r--r--arch/ppc/mm/4xx_mmu.c17
-rw-r--r--arch/ppc/mm/fault.c6
-rw-r--r--arch/ppc/mm/mmu_decl.h4
-rw-r--r--arch/ppc/platforms/4xx/ebony.c2
-rw-r--r--arch/ppc/platforms/4xx/luan.c7
-rw-r--r--arch/ppc/platforms/4xx/ocotea.c2
-rw-r--r--arch/ppc/platforms/4xx/taishan.c2
-rw-r--r--arch/ppc/platforms/chestnut.c1
-rw-r--r--arch/ppc/syslib/i8259.c1
-rw-r--r--arch/ppc/syslib/m8260_setup.c13
-rw-r--r--arch/s390/Kconfig18
-rw-r--r--arch/s390/Makefile14
-rw-r--r--arch/s390/defconfig131
-rw-r--r--arch/s390/kernel/compat_linux.c2
-rw-r--r--arch/s390/kernel/early.c4
-rw-r--r--arch/s390/kernel/ipl.c2
-rw-r--r--arch/s390/kernel/kprobes.c2
-rw-r--r--arch/s390/kernel/process.c26
-rw-r--r--arch/s390/kernel/ptrace.c5
-rw-r--r--arch/s390/kernel/smp.c65
-rw-r--r--arch/s390/kernel/sys_s390.c2
-rw-r--r--arch/s390/kernel/time.c6
-rw-r--r--arch/s390/kernel/vtime.c8
-rw-r--r--arch/s390/lib/uaccess_pt.c92
-rw-r--r--arch/s390/mm/Makefile2
-rw-r--r--arch/s390/mm/cmm.c1
-rw-r--r--arch/s390/mm/fault.c4
-rw-r--r--arch/s390/mm/init.c32
-rw-r--r--arch/s390/mm/pgtable.c94
-rw-r--r--arch/s390/mm/vmem.c53
-rw-r--r--arch/s390/oprofile/Kconfig22
-rw-r--r--arch/sh/Kconfig20
-rw-r--r--arch/sh/Kconfig.debug11
-rw-r--r--arch/sh/Makefile8
-rw-r--r--arch/sh/boards/hp6xx/pm.c6
-rw-r--r--arch/sh/boards/renesas/hs7751rvoip/irq.c1
-rw-r--r--arch/sh/boards/renesas/hs7751rvoip/setup.c19
-rw-r--r--arch/sh/boards/renesas/r7780rp/setup.c71
-rw-r--r--arch/sh/boards/renesas/sh7710voipgw/setup.c1
-rw-r--r--arch/sh/boards/se/7206/irq.c1
-rw-r--r--arch/sh/boards/se/770x/setup.c1
-rw-r--r--arch/sh/boards/se/7722/setup.c12
-rw-r--r--arch/sh/boards/se/7780/setup.c8
-rw-r--r--arch/sh/boards/snapgear/Makefile3
-rw-r--r--arch/sh/boards/snapgear/rtc.c309
-rw-r--r--arch/sh/boards/snapgear/setup.c16
-rw-r--r--arch/sh/boot/Makefile2
-rw-r--r--arch/sh/boot/compressed/Makefile2
-rw-r--r--arch/sh/cchips/hd6446x/Makefile2
-rw-r--r--arch/sh/cchips/voyagergx/Makefile1
-rw-r--r--arch/sh/configs/r7785rp_defconfig299
-rw-r--r--arch/sh/drivers/pci/Makefile1
-rw-r--r--arch/sh/drivers/pci/dma-dreamcast.c2
-rw-r--r--arch/sh/drivers/pci/pci-st40.c488
-rw-r--r--arch/sh/drivers/pci/pci-st40.h136
-rw-r--r--arch/sh/kernel/Makefile3
-rw-r--r--arch/sh/kernel/cpu/irq/ipr.c9
-rw-r--r--arch/sh/kernel/cpu/sh3/ex.S2
-rw-r--r--arch/sh/kernel/cpu/sh4/probe.c8
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7722.c27
-rw-r--r--arch/sh/kernel/irq.c9
-rw-r--r--arch/sh/kernel/kgdb_stub.c9
-rw-r--r--arch/sh/kernel/machine_kexec.c21
-rw-r--r--arch/sh/kernel/process.c2
-rw-r--r--arch/sh/kernel/ptrace.c4
-rw-r--r--arch/sh/kernel/setup.c85
-rw-r--r--arch/sh/kernel/sh_ksyms.c2
-rw-r--r--arch/sh/kernel/signal.c4
-rw-r--r--arch/sh/kernel/sys_sh.c2
-rw-r--r--arch/sh/kernel/traps.c7
-rw-r--r--arch/sh/kernel/vmlinux.lds.S201
-rw-r--r--arch/sh/kernel/vsyscall/vsyscall.lds.S80
-rw-r--r--arch/sh/lib/Makefile2
-rw-r--r--arch/sh/mm/Kconfig21
-rw-r--r--arch/sh/mm/Makefile2
-rw-r--r--arch/sh/mm/clear_page.S45
-rw-r--r--arch/sh/mm/consistent.c8
-rw-r--r--arch/sh/mm/copy_page.S65
-rw-r--r--arch/sh/mm/fault.c4
-rw-r--r--arch/sh/mm/init.c6
-rw-r--r--arch/sh/mm/pg-sh4.c75
-rw-r--r--arch/sh/mm/pmb.c3
-rw-r--r--arch/sh/oprofile/Kconfig23
-rw-r--r--arch/sh/oprofile/Makefile1
-rw-r--r--arch/sh/oprofile/op_model_sh7750.c22
-rw-r--r--arch/sh/tools/mach-types29
-rw-r--r--arch/sh64/Kconfig4
-rw-r--r--arch/sh64/Makefile4
-rw-r--r--arch/sh64/configs/cayman_defconfig140
-rw-r--r--arch/sh64/configs/harp_defconfig105
-rw-r--r--arch/sh64/configs/sim_defconfig68
-rw-r--r--arch/sh64/kernel/pci_sh5.c2
-rw-r--r--arch/sh64/kernel/process.c10
-rw-r--r--arch/sh64/kernel/ptrace.c4
-rw-r--r--arch/sh64/kernel/sys_sh64.c2
-rw-r--r--arch/sh64/kernel/traps.c9
-rw-r--r--arch/sh64/mm/consistent.c3
-rw-r--r--arch/sh64/mm/fault.c12
-rw-r--r--arch/sh64/oprofile/Kconfig23
-rw-r--r--arch/sparc/Kconfig7
-rw-r--r--arch/sparc/Makefile8
-rw-r--r--arch/sparc/kernel/ioport.c42
-rw-r--r--arch/sparc/kernel/irq.c5
-rw-r--r--arch/sparc/kernel/of_device.c20
-rw-r--r--arch/sparc/kernel/pcic.c2
-rw-r--r--arch/sparc/kernel/process.c7
-rw-r--r--arch/sparc/kernel/ptrace.c4
-rw-r--r--arch/sparc/kernel/sys_sparc.c4
-rw-r--r--arch/sparc/kernel/sys_sunos.c2
-rw-r--r--arch/sparc/kernel/time.c9
-rw-r--r--arch/sparc/kernel/traps.c4
-rw-r--r--arch/sparc/mm/btfixup.c5
-rw-r--r--arch/sparc/mm/fault.c2
-rw-r--r--arch/sparc/mm/io-unit.c12
-rw-r--r--arch/sparc/mm/iommu.c18
-rw-r--r--arch/sparc/mm/sun4c.c25
-rw-r--r--arch/sparc/oprofile/Kconfig17
-rw-r--r--arch/sparc64/Kconfig26
-rw-r--r--arch/sparc64/Makefile12
-rw-r--r--arch/sparc64/defconfig158
-rw-r--r--arch/sparc64/kernel/Makefile9
-rw-r--r--arch/sparc64/kernel/binfmt_aout32.c17
-rw-r--r--arch/sparc64/kernel/binfmt_elf32.c4
-rw-r--r--arch/sparc64/kernel/central.c9
-rw-r--r--arch/sparc64/kernel/ds.c1
-rw-r--r--arch/sparc64/kernel/iommu.c53
-rw-r--r--arch/sparc64/kernel/iommu_common.c67
-rw-r--r--arch/sparc64/kernel/iommu_common.h1
-rw-r--r--arch/sparc64/kernel/irq.c93
-rw-r--r--arch/sparc64/kernel/kprobes.c2
-rw-r--r--arch/sparc64/kernel/ktlb.S16
-rw-r--r--arch/sparc64/kernel/ldc.c4
-rw-r--r--arch/sparc64/kernel/module.c1
-rw-r--r--arch/sparc64/kernel/of_device.c20
-rw-r--r--arch/sparc64/kernel/pci.c3
-rw-r--r--arch/sparc64/kernel/pci_common.c7
-rw-r--r--arch/sparc64/kernel/pci_msi.c14
-rw-r--r--arch/sparc64/kernel/pci_sun4v.c43
-rw-r--r--arch/sparc64/kernel/semaphore.c5
-rw-r--r--arch/sparc64/kernel/smp.c21
-rw-r--r--arch/sparc64/kernel/sparc64_ksyms.c2
-rw-r--r--arch/sparc64/kernel/sys_sparc.c3
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c2
-rw-r--r--arch/sparc64/kernel/sys_sunos32.c3
-rw-r--r--arch/sparc64/kernel/time.c4
-rw-r--r--arch/sparc64/kernel/traps.c11
-rw-r--r--arch/sparc64/lib/atomic.S38
-rw-r--r--arch/sparc64/lib/bitops.S30
-rw-r--r--arch/sparc64/math-emu/Makefile2
-rw-r--r--arch/sparc64/mm/fault.c2
-rw-r--r--arch/sparc64/mm/init.c61
-rw-r--r--arch/sparc64/mm/tsb.c4
-rw-r--r--arch/sparc64/mm/ultra.S7
-rw-r--r--arch/sparc64/oprofile/Kconfig17
-rw-r--r--arch/sparc64/prom/console.c9
-rw-r--r--arch/sparc64/prom/tree.c49
-rw-r--r--arch/sparc64/solaris/ipc.c2
-rw-r--r--arch/sparc64/solaris/misc.c4
-rw-r--r--arch/um/Kconfig248
-rw-r--r--arch/um/Kconfig.char141
-rw-r--r--arch/um/Kconfig.debug47
-rw-r--r--arch/um/Kconfig.i38616
-rw-r--r--arch/um/Kconfig.net22
-rw-r--r--arch/um/Kconfig.x86_6414
-rw-r--r--arch/um/Makefile60
-rw-r--r--arch/um/Makefile-i38621
-rw-r--r--arch/um/Makefile-os-Linux2
-rw-r--r--arch/um/Makefile-x86_6411
-rw-r--r--arch/um/defconfig11
-rw-r--r--arch/um/drivers/Makefile13
-rw-r--r--arch/um/drivers/chan_kern.c211
-rw-r--r--arch/um/drivers/chan_user.c211
-rw-r--r--arch/um/drivers/cow_user.c133
-rw-r--r--arch/um/drivers/daemon.h20
-rw-r--r--arch/um/drivers/daemon_kern.c34
-rw-r--r--arch/um/drivers/daemon_user.c92
-rw-r--r--arch/um/drivers/fd.c69
-rw-r--r--arch/um/drivers/harddog_kern.c2
-rw-r--r--arch/um/drivers/harddog_user.c58
-rw-r--r--arch/um/drivers/hostaudio_kern.c118
-rw-r--r--arch/um/drivers/line.c239
-rw-r--r--arch/um/drivers/mcast.h16
-rw-r--r--arch/um/drivers/mcast_kern.c56
-rw-r--r--arch/um/drivers/mcast_user.c73
-rw-r--r--arch/um/drivers/mconsole_kern.c289
-rw-r--r--arch/um/drivers/mconsole_user.c119
-rw-r--r--arch/um/drivers/mmapper_kern.c64
-rw-r--r--arch/um/drivers/net_kern.c292
-rw-r--r--arch/um/drivers/net_user.c126
-rw-r--r--arch/um/drivers/null.c30
-rw-r--r--arch/um/drivers/pcap_kern.c38
-rw-r--r--arch/um/drivers/pcap_user.c58
-rw-r--r--arch/um/drivers/port_kern.c86
-rw-r--r--arch/um/drivers/port_user.c73
-rw-r--r--arch/um/drivers/pty.c30
-rw-r--r--arch/um/drivers/slip_kern.c42
-rw-r--r--arch/um/drivers/slip_user.c129
-rw-r--r--arch/um/drivers/slirp_kern.c63
-rw-r--r--arch/um/drivers/slirp_user.c74
-rw-r--r--arch/um/drivers/stderr_console.c2
-rw-r--r--arch/um/drivers/tty.c37
-rw-r--r--arch/um/drivers/ubd_kern.c6
-rw-r--r--arch/um/drivers/vde.h32
-rw-r--r--arch/um/drivers/vde_kern.c129
-rw-r--r--arch/um/drivers/vde_user.c127
-rw-r--r--arch/um/drivers/xterm.c28
-rw-r--r--arch/um/include/arch.h4
-rw-r--r--arch/um/include/as-layout.h27
-rw-r--r--arch/um/include/choose-mode.h38
-rw-r--r--arch/um/include/common-offsets.h10
-rw-r--r--arch/um/include/irq_user.h10
-rw-r--r--arch/um/include/kern_util.h30
-rw-r--r--arch/um/include/mconsole.h15
-rw-r--r--arch/um/include/mem.h21
-rw-r--r--arch/um/include/mode.h30
-rw-r--r--arch/um/include/mode_kern.h17
-rw-r--r--arch/um/include/net_kern.h13
-rw-r--r--arch/um/include/net_user.h4
-rw-r--r--arch/um/include/os.h69
-rw-r--r--arch/um/include/registers.h10
-rw-r--r--arch/um/include/skas/mmu-skas.h23
-rw-r--r--arch/um/include/skas/mode-skas.h9
-rw-r--r--arch/um/include/skas/mode_kern_skas.h41
-rw-r--r--arch/um/include/skas/skas.h5
-rw-r--r--arch/um/include/skas/uaccess-skas.h21
-rw-r--r--arch/um/include/sysdep-i386/kernel-offsets.h1
-rw-r--r--arch/um/include/sysdep-i386/ptrace.h133
-rw-r--r--arch/um/include/sysdep-i386/sigcontext.h30
-rw-r--r--arch/um/include/sysdep-i386/stub.h14
-rw-r--r--arch/um/include/sysdep-i386/thread.h11
-rw-r--r--arch/um/include/sysdep-x86_64/ptrace.h277
-rw-r--r--arch/um/include/sysdep-x86_64/sigcontext.h28
-rw-r--r--arch/um/include/sysdep-x86_64/stub.h13
-rw-r--r--arch/um/include/sysdep-x86_64/thread.h10
-rw-r--r--arch/um/include/task.h2
-rw-r--r--arch/um/include/tlb.h27
-rw-r--r--arch/um/include/tt/debug.h18
-rw-r--r--arch/um/include/tt/mmu-tt.h12
-rw-r--r--arch/um/include/tt/mode-tt.h23
-rw-r--r--arch/um/include/tt/mode_kern_tt.h40
-rw-r--r--arch/um/include/tt/tt.h37
-rw-r--r--arch/um/include/tt/uaccess-tt.h46
-rw-r--r--arch/um/include/um_mmu.h40
-rw-r--r--arch/um/include/um_uaccess.h64
-rw-r--r--arch/um/include/uml_uaccess.h24
-rw-r--r--arch/um/include/user.h21
-rw-r--r--arch/um/kernel/Makefile7
-rw-r--r--arch/um/kernel/dyn.lds.S2
-rw-r--r--arch/um/kernel/exec.c58
-rw-r--r--arch/um/kernel/gmon_syms.c4
-rw-r--r--arch/um/kernel/init_task.c13
-rw-r--r--arch/um/kernel/irq.c128
-rw-r--r--arch/um/kernel/ksyms.c41
-rw-r--r--arch/um/kernel/mem.c4
-rw-r--r--arch/um/kernel/physmem.c69
-rw-r--r--arch/um/kernel/process.c226
-rw-r--r--arch/um/kernel/ptrace.c143
-rw-r--r--arch/um/kernel/reboot.c57
-rw-r--r--arch/um/kernel/signal.c59
-rw-r--r--arch/um/kernel/skas/Makefile4
-rw-r--r--arch/um/kernel/skas/clone.c7
-rw-r--r--arch/um/kernel/skas/exec.c40
-rw-r--r--arch/um/kernel/skas/mem.c22
-rw-r--r--arch/um/kernel/skas/mmu.c81
-rw-r--r--arch/um/kernel/skas/process.c187
-rw-r--r--arch/um/kernel/skas/syscall.c21
-rw-r--r--arch/um/kernel/skas/tlb.c164
-rw-r--r--arch/um/kernel/skas/uaccess.c146
-rw-r--r--arch/um/kernel/smp.c36
-rw-r--r--arch/um/kernel/syscall.c40
-rw-r--r--arch/um/kernel/time.c223
-rw-r--r--arch/um/kernel/tlb.c418
-rw-r--r--arch/um/kernel/trap.c131
-rw-r--r--arch/um/kernel/tt/Makefile14
-rw-r--r--arch/um/kernel/tt/exec_kern.c84
-rw-r--r--arch/um/kernel/tt/exec_user.c56
-rw-r--r--arch/um/kernel/tt/gdb.c280
-rw-r--r--arch/um/kernel/tt/gdb_kern.c40
-rw-r--r--arch/um/kernel/tt/include/mode-tt.h34
-rw-r--r--arch/um/kernel/tt/ksyms.c29
-rw-r--r--arch/um/kernel/tt/mem.c34
-rw-r--r--arch/um/kernel/tt/mem_user.c49
-rw-r--r--arch/um/kernel/tt/process_kern.c461
-rw-r--r--arch/um/kernel/tt/ptproxy/Makefile10
-rw-r--r--arch/um/kernel/tt/ptproxy/proxy.c377
-rw-r--r--arch/um/kernel/tt/ptproxy/ptproxy.h61
-rw-r--r--arch/um/kernel/tt/ptproxy/ptrace.c237
-rw-r--r--arch/um/kernel/tt/ptproxy/sysdep.c70
-rw-r--r--arch/um/kernel/tt/ptproxy/sysdep.h25
-rw-r--r--arch/um/kernel/tt/ptproxy/wait.c85
-rw-r--r--arch/um/kernel/tt/ptproxy/wait.h15
-rw-r--r--arch/um/kernel/tt/syscall_kern.c46
-rw-r--r--arch/um/kernel/tt/syscall_user.c60
-rw-r--r--arch/um/kernel/tt/tlb.c120
-rw-r--r--arch/um/kernel/tt/tracer.c461
-rw-r--r--arch/um/kernel/tt/trap_user.c70
-rw-r--r--arch/um/kernel/tt/uaccess.c73
-rw-r--r--arch/um/kernel/tt/uaccess_user.c105
-rw-r--r--arch/um/kernel/uaccess.c2
-rw-r--r--arch/um/kernel/um_arch.c217
-rw-r--r--arch/um/kernel/uml.lds.S7
-rw-r--r--arch/um/os-Linux/Makefile15
-rw-r--r--arch/um/os-Linux/aio.c122
-rw-r--r--arch/um/os-Linux/drivers/etap.h16
-rw-r--r--arch/um/os-Linux/drivers/ethertap_kern.c52
-rw-r--r--arch/um/os-Linux/drivers/ethertap_user.c132
-rw-r--r--arch/um/os-Linux/drivers/tuntap.h13
-rw-r--r--arch/um/os-Linux/drivers/tuntap_kern.c35
-rw-r--r--arch/um/os-Linux/drivers/tuntap_user.c102
-rw-r--r--arch/um/os-Linux/file.c133
-rw-r--r--arch/um/os-Linux/helper.c8
-rw-r--r--arch/um/os-Linux/irq.c6
-rw-r--r--arch/um/os-Linux/main.c120
-rw-r--r--arch/um/os-Linux/mem.c6
-rw-r--r--arch/um/os-Linux/process.c175
-rw-r--r--arch/um/os-Linux/registers.c57
-rw-r--r--arch/um/os-Linux/signal.c131
-rw-r--r--arch/um/os-Linux/skas/mem.c109
-rw-r--r--arch/um/os-Linux/skas/process.c316
-rw-r--r--arch/um/os-Linux/skas/trap.c51
-rw-r--r--arch/um/os-Linux/start_up.c218
-rw-r--r--arch/um/os-Linux/sys-i386/Makefile4
-rw-r--r--arch/um/os-Linux/sys-i386/registers.c129
-rw-r--r--arch/um/os-Linux/sys-x86_64/Makefile4
-rw-r--r--arch/um/os-Linux/sys-x86_64/registers.c75
-rw-r--r--arch/um/os-Linux/time.c111
-rw-r--r--arch/um/os-Linux/tls.c40
-rw-r--r--arch/um/os-Linux/trap.c23
-rw-r--r--arch/um/os-Linux/tt.c196
-rw-r--r--arch/um/os-Linux/uaccess.c2
-rw-r--r--arch/um/os-Linux/umid.c137
-rw-r--r--arch/um/os-Linux/util.c38
-rw-r--r--arch/um/scripts/Makefile.rules2
-rw-r--r--arch/um/sys-i386/Makefile14
-rw-r--r--arch/um/sys-i386/bug.c2
-rw-r--r--arch/um/sys-i386/bugs.c108
-rw-r--r--arch/um/sys-i386/fault.c10
-rw-r--r--arch/um/sys-i386/ldt.c306
-rw-r--r--arch/um/sys-i386/ptrace.c368
-rw-r--r--arch/um/sys-i386/ptrace_user.c100
-rw-r--r--arch/um/sys-i386/sigcontext.c71
-rw-r--r--arch/um/sys-i386/signal.c409
-rw-r--r--arch/um/sys-i386/stub.S9
-rw-r--r--arch/um/sys-i386/stub_segv.c4
-rw-r--r--arch/um/sys-i386/syscalls.c2
-rw-r--r--arch/um/sys-i386/tls.c103
-rw-r--r--arch/um/sys-i386/unmap.c25
-rw-r--r--arch/um/sys-i386/user-offsets.c6
-rw-r--r--arch/um/sys-ppc/Makefile6
-rw-r--r--arch/um/sys-x86_64/Makefile11
-rw-r--r--arch/um/sys-x86_64/bug.c2
-rw-r--r--arch/um/sys-x86_64/bugs.c2
-rw-r--r--arch/um/sys-x86_64/fault.c9
-rw-r--r--arch/um/sys-x86_64/ptrace.c154
-rw-r--r--arch/um/sys-x86_64/sigcontext.c39
-rw-r--r--arch/um/sys-x86_64/signal.c297
-rw-r--r--arch/um/sys-x86_64/stub.S9
-rw-r--r--arch/um/sys-x86_64/stub_segv.c3
-rw-r--r--arch/um/sys-x86_64/syscalls.c108
-rw-r--r--arch/um/sys-x86_64/sysrq.c4
-rw-r--r--arch/um/sys-x86_64/tls.c4
-rw-r--r--arch/um/sys-x86_64/unmap.c25
-rw-r--r--arch/um/sys-x86_64/user-offsets.c9
-rw-r--r--arch/v850/Kconfig2
-rw-r--r--arch/v850/Makefile8
-rw-r--r--arch/v850/kernel/fpga85e2c.c5
-rw-r--r--arch/v850/kernel/me2.c4
-rw-r--r--arch/v850/kernel/rte_mb_a_pci.c4
-rw-r--r--arch/v850/kernel/syscalls.c1
-rw-r--r--arch/v850/kernel/time.c11
-rw-r--r--arch/x86/Kconfig (renamed from arch/i386/Kconfig)645
-rw-r--r--arch/x86/Kconfig.cpu (renamed from arch/i386/Kconfig.cpu)155
-rw-r--r--arch/x86/Kconfig.debug (renamed from arch/i386/Kconfig.debug)49
-rw-r--r--arch/x86/Makefile20
-rw-r--r--arch/x86/Makefile_32 (renamed from arch/i386/Makefile)44
-rw-r--r--arch/x86/Makefile_32.cpu (renamed from arch/i386/Makefile.cpu)0
-rw-r--r--arch/x86/Makefile_64 (renamed from arch/x86_64/Makefile)39
-rw-r--r--arch/x86/boot/Makefile17
-rw-r--r--arch/x86/boot/boot.h10
-rw-r--r--arch/x86/boot/compressed/Makefile_322
-rw-r--r--arch/x86/boot/compressed/Makefile_644
-rw-r--r--arch/x86/boot/compressed/head_32.S7
-rw-r--r--arch/x86/boot/compressed/head_64.S7
-rw-r--r--arch/x86/boot/compressed/misc_32.c7
-rw-r--r--arch/x86/boot/compressed/misc_64.c4
-rw-r--r--arch/x86/boot/compressed/relocs.c6
-rw-r--r--arch/x86/boot/cpucheck.c6
-rw-r--r--arch/x86/boot/header.S69
-rw-r--r--arch/x86/boot/main.c2
-rw-r--r--arch/x86/boot/pmjump.S8
-rw-r--r--arch/x86/boot/video-bios.c2
-rw-r--r--arch/x86/boot/video-vesa.c2
-rw-r--r--arch/x86/boot/video.c2
-rw-r--r--arch/x86/configs/i386_defconfig (renamed from arch/i386/defconfig)0
-rw-r--r--arch/x86/configs/x86_64_defconfig (renamed from arch/x86_64/defconfig)2
-rw-r--r--arch/x86/crypto/Makefile20
-rw-r--r--arch/x86/crypto/Makefile_3212
-rw-r--r--arch/x86/crypto/Makefile_6412
-rw-r--r--arch/x86/ia32/Makefile25
-rw-r--r--arch/x86/ia32/ia32_aout.c12
-rw-r--r--arch/x86/ia32/ia32_binfmt.c131
-rw-r--r--arch/x86/ia32/ia32entry.S19
-rw-r--r--arch/x86/ia32/ipc32.c2
-rw-r--r--arch/x86/kernel/.gitignore1
-rw-r--r--arch/x86/kernel/Makefile4
-rw-r--r--arch/x86/kernel/Makefile_3210
-rw-r--r--arch/x86/kernel/Makefile_6427
-rw-r--r--arch/x86/kernel/acpi/Makefile10
-rw-r--r--arch/x86/kernel/acpi/Makefile_3210
-rw-r--r--arch/x86/kernel/acpi/Makefile_647
-rw-r--r--arch/x86/kernel/acpi/boot.c10
-rw-r--r--arch/x86/kernel/acpi/cstate.c4
-rw-r--r--arch/x86/kernel/acpi/earlyquirk_32.c84
-rw-r--r--arch/x86/kernel/acpi/processor.c3
-rw-r--r--arch/x86/kernel/acpi/wakeup_32.S12
-rw-r--r--arch/x86/kernel/acpi/wakeup_64.S133
-rw-r--r--arch/x86/kernel/alternative.c71
-rw-r--r--arch/x86/kernel/aperture_64.c15
-rw-r--r--arch/x86/kernel/apic_32.c5
-rw-r--r--arch/x86/kernel/apic_64.c18
-rw-r--r--arch/x86/kernel/apm_32.c2
-rw-r--r--arch/x86/kernel/asm-offsets_32.c22
-rw-r--r--arch/x86/kernel/asm-offsets_64.c38
-rw-r--r--arch/x86/kernel/cpu/Makefile24
-rw-r--r--arch/x86/kernel/cpu/amd.c17
-rw-r--r--arch/x86/kernel/cpu/centaur.c4
-rw-r--r--arch/x86/kernel/cpu/common.c2
-rw-r--r--arch/x86/kernel/cpu/cpufreq/Kconfig69
-rw-r--r--arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c6
-rw-r--r--arch/x86/kernel/cpu/cpufreq/cpufreq-nforce2.c2
-rw-r--r--arch/x86/kernel/cpu/cpufreq/e_powersaver.c2
-rw-r--r--arch/x86/kernel/cpu/cpufreq/elanfreq.c4
-rw-r--r--arch/x86/kernel/cpu/cpufreq/gx-suspmod.c8
-rw-r--r--arch/x86/kernel/cpu/cpufreq/longhaul.c4
-rw-r--r--arch/x86/kernel/cpu/cpufreq/longrun.c4
-rw-r--r--arch/x86/kernel/cpu/cpufreq/p4-clockmod.c6
-rw-r--r--arch/x86/kernel/cpu/cpufreq/powernow-k6.c4
-rw-r--r--arch/x86/kernel/cpu/cpufreq/powernow-k7.c4
-rw-r--r--arch/x86/kernel/cpu/cpufreq/powernow-k8.c12
-rw-r--r--arch/x86/kernel/cpu/cpufreq/powernow-k8.h4
-rw-r--r--arch/x86/kernel/cpu/cpufreq/sc520_freq.c4
-rw-r--r--arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c6
-rw-r--r--arch/x86/kernel/cpu/cpufreq/speedstep-ich.c2
-rw-r--r--arch/x86/kernel/cpu/cpufreq/speedstep-lib.c2
-rw-r--r--arch/x86/kernel/cpu/cyrix.c10
-rw-r--r--arch/x86/kernel/cpu/intel.c17
-rw-r--r--arch/x86/kernel/cpu/intel_cacheinfo.c89
-rw-r--r--arch/x86/kernel/cpu/mcheck/Makefile8
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_32.c (renamed from arch/x86/kernel/cpu/mcheck/mce.c)0
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_64.c (renamed from arch/x86/kernel/mce_64.c)213
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_amd_64.c (renamed from arch/x86/kernel/mce_amd_64.c)11
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_intel_64.c (renamed from arch/x86/kernel/mce_intel_64.c)1
-rw-r--r--arch/x86/kernel/cpu/mcheck/p4.c1
-rw-r--r--arch/x86/kernel/cpu/mcheck/therm_throt.c12
-rw-r--r--arch/x86/kernel/cpu/mtrr/cyrix.c4
-rw-r--r--arch/x86/kernel/cpu/mtrr/generic.c2
-rw-r--r--arch/x86/kernel/cpu/mtrr/main.c16
-rw-r--r--arch/x86/kernel/cpu/perfctr-watchdog.c30
-rw-r--r--arch/x86/kernel/cpu/proc.c24
-rw-r--r--arch/x86/kernel/cpufreq/Kconfig108
-rw-r--r--arch/x86/kernel/cpuid.c60
-rw-r--r--arch/x86/kernel/crash.c (renamed from arch/x86/kernel/crash_32.c)11
-rw-r--r--arch/x86/kernel/crash_64.c135
-rw-r--r--arch/x86/kernel/crash_dump_32.c1
-rw-r--r--arch/x86/kernel/e820_32.c23
-rw-r--r--arch/x86/kernel/e820_64.c44
-rw-r--r--arch/x86/kernel/early-quirks.c (renamed from arch/x86/kernel/early-quirks_64.c)29
-rw-r--r--arch/x86/kernel/early_printk.c15
-rw-r--r--arch/x86/kernel/efi_32.c19
-rw-r--r--arch/x86/kernel/entry_32.S2
-rw-r--r--arch/x86/kernel/entry_64.S2
-rw-r--r--arch/x86/kernel/genapic_64.c17
-rw-r--r--arch/x86/kernel/genapic_flat_64.c3
-rw-r--r--arch/x86/kernel/head64.c22
-rw-r--r--arch/x86/kernel/head_32.S72
-rw-r--r--arch/x86/kernel/hpet.c5
-rw-r--r--arch/x86/kernel/i386_ksyms_32.c1
-rw-r--r--arch/x86/kernel/i387_64.c9
-rw-r--r--arch/x86/kernel/i8253.c2
-rw-r--r--arch/x86/kernel/i8259_32.c9
-rw-r--r--arch/x86/kernel/i8259_64.c6
-rw-r--r--arch/x86/kernel/init_task.c (renamed from arch/x86/kernel/init_task_32.c)11
-rw-r--r--arch/x86/kernel/init_task_64.c54
-rw-r--r--arch/x86/kernel/io_apic_32.c26
-rw-r--r--arch/x86/kernel/io_apic_64.c74
-rw-r--r--arch/x86/kernel/irq_32.c49
-rw-r--r--arch/x86/kernel/irq_64.c48
-rw-r--r--arch/x86/kernel/kprobes_32.c17
-rw-r--r--arch/x86/kernel/kprobes_64.c15
-rw-r--r--arch/x86/kernel/ldt_32.c14
-rw-r--r--arch/x86/kernel/ldt_64.c14
-rw-r--r--arch/x86/kernel/machine_kexec_32.c29
-rw-r--r--arch/x86/kernel/machine_kexec_64.c32
-rw-r--r--arch/x86/kernel/microcode.c6
-rw-r--r--arch/x86/kernel/mpparse_32.c2
-rw-r--r--arch/x86/kernel/mpparse_64.c17
-rw-r--r--arch/x86/kernel/msr.c39
-rw-r--r--arch/x86/kernel/nmi_32.c4
-rw-r--r--arch/x86/kernel/paravirt_32.c224
-rw-r--r--arch/x86/kernel/pci-calgary_64.c77
-rw-r--r--arch/x86/kernel/pci-dma_32.c1
-rw-r--r--arch/x86/kernel/pci-dma_64.c25
-rw-r--r--arch/x86/kernel/pci-gart_64.c94
-rw-r--r--arch/x86/kernel/pci-nommu_64.c11
-rw-r--r--arch/x86/kernel/pci-swiotlb_64.c2
-rw-r--r--arch/x86/kernel/process_32.c56
-rw-r--r--arch/x86/kernel/process_64.c2
-rw-r--r--arch/x86/kernel/ptrace_32.c11
-rw-r--r--arch/x86/kernel/ptrace_64.c9
-rw-r--r--arch/x86/kernel/quirks.c165
-rw-r--r--arch/x86/kernel/reboot_64.c5
-rw-r--r--arch/x86/kernel/reboot_fixups_32.c8
-rw-r--r--arch/x86/kernel/setup64.c14
-rw-r--r--arch/x86/kernel/setup_32.c129
-rw-r--r--arch/x86/kernel/setup_64.c143
-rw-r--r--arch/x86/kernel/signal_32.c8
-rw-r--r--arch/x86/kernel/signal_64.c2
-rw-r--r--arch/x86/kernel/smp_32.c12
-rw-r--r--arch/x86/kernel/smp_64.c122
-rw-r--r--arch/x86/kernel/smpboot_32.c163
-rw-r--r--arch/x86/kernel/smpboot_64.c131
-rw-r--r--arch/x86/kernel/stacktrace.c2
-rw-r--r--arch/x86/kernel/summit_32.c2
-rw-r--r--arch/x86/kernel/suspend_64.c120
-rw-r--r--arch/x86/kernel/suspend_asm_64.S117
-rw-r--r--arch/x86/kernel/sys_i386_32.c2
-rw-r--r--arch/x86/kernel/tce_64.c4
-rw-r--r--arch/x86/kernel/topology.c6
-rw-r--r--arch/x86/kernel/trampoline_32.S4
-rw-r--r--arch/x86/kernel/trampoline_64.S7
-rw-r--r--arch/x86/kernel/traps_32.c97
-rw-r--r--arch/x86/kernel/traps_64.c24
-rw-r--r--arch/x86/kernel/tsc_32.c57
-rw-r--r--arch/x86/kernel/tsc_64.c4
-rw-r--r--arch/x86/kernel/vmi_32.c201
-rw-r--r--arch/x86/kernel/vsyscall_64.c32
-rw-r--r--arch/x86/lguest/Kconfig14
-rw-r--r--arch/x86/lguest/Makefile1
-rw-r--r--arch/x86/lguest/boot.c (renamed from drivers/lguest/lguest.c)349
-rw-r--r--arch/x86/lguest/i386_head.S (renamed from drivers/lguest/lguest_asm.S)48
-rw-r--r--arch/x86/lib/bitstr_64.c2
-rw-r--r--arch/x86/lib/delay_32.c5
-rw-r--r--arch/x86/lib/delay_64.c14
-rw-r--r--arch/x86/lib/msr-on-cpu.c62
-rw-r--r--arch/x86/lib/rwlock_64.S2
-rw-r--r--arch/x86/lib/semaphore_32.S4
-rw-r--r--arch/x86/lib/string_32.c20
-rw-r--r--arch/x86/lib/usercopy_32.c2
-rw-r--r--arch/x86/mach-default/setup.c22
-rw-r--r--arch/x86/mach-es7000/es7000plat.c32
-rw-r--r--arch/x86/mach-generic/default.c2
-rw-r--r--arch/x86/mach-generic/probe.c4
-rw-r--r--arch/x86/mach-visws/setup.c2
-rw-r--r--arch/x86/mach-voyager/setup.c20
-rw-r--r--arch/x86/mach-voyager/voyager_smp.c31
-rw-r--r--arch/x86/mach-voyager/voyager_thread.c2
-rw-r--r--arch/x86/math-emu/Makefile3
-rw-r--r--arch/x86/mm/boot_ioremap_32.c2
-rw-r--r--arch/x86/mm/discontig_32.c21
-rw-r--r--arch/x86/mm/fault_32.c80
-rw-r--r--arch/x86/mm/fault_64.c71
-rw-r--r--arch/x86/mm/init_32.c38
-rw-r--r--arch/x86/mm/init_64.c57
-rw-r--r--arch/x86/mm/numa_64.c8
-rw-r--r--arch/x86/mm/pageattr_32.c4
-rw-r--r--arch/x86/mm/pageattr_64.c18
-rw-r--r--arch/x86/mm/pgtable_32.c8
-rw-r--r--arch/x86/mm/srat_64.c6
-rw-r--r--arch/x86/oprofile/Kconfig17
-rw-r--r--arch/x86/oprofile/backtrace.c110
-rw-r--r--arch/x86/oprofile/nmi_int.c2
-rw-r--r--arch/x86/oprofile/op_model_p4.c2
-rw-r--r--arch/x86/oprofile/op_x86_model.h2
-rw-r--r--arch/x86/pci/common.c16
-rw-r--r--arch/x86/pci/irq.c4
-rw-r--r--arch/x86/vdso/Makefile23
-rw-r--r--arch/x86/vdso/vdso.lds.S16
-rw-r--r--arch/x86/vdso/vvar.c2
-rw-r--r--arch/x86/xen/Kconfig5
-rw-r--r--arch/x86/xen/enlighten.c240
-rw-r--r--arch/x86/xen/events.c4
-rw-r--r--arch/x86/xen/mmu.c145
-rw-r--r--arch/x86/xen/multicalls.c52
-rw-r--r--arch/x86/xen/multicalls.h5
-rw-r--r--arch/x86/xen/smp.c33
-rw-r--r--arch/x86/xen/time.c6
-rw-r--r--arch/x86/xen/xen-ops.h10
-rw-r--r--arch/x86_64/Kconfig819
-rw-r--r--arch/x86_64/Kconfig.debug61
-rw-r--r--arch/xtensa/Kconfig4
-rw-r--r--arch/xtensa/Makefile8
-rw-r--r--arch/xtensa/boot/Makefile6
-rw-r--r--arch/xtensa/boot/boot-redboot/Makefile2
-rw-r--r--arch/xtensa/kernel/ptrace.c4
-rw-r--r--arch/xtensa/kernel/traps.c6
-rw-r--r--arch/xtensa/mm/fault.c4
-rw-r--r--arch/xtensa/platform-iss/network.c2
-rw-r--r--block/blktrace.c2
-rw-r--r--block/bsg.c2
-rw-r--r--block/cfq-iosched.c41
-rw-r--r--block/compat_ioctl.c2
-rw-r--r--block/deadline-iosched.c53
-rw-r--r--block/elevator.c19
-rw-r--r--block/ll_rw_blk.c433
-rw-r--r--crypto/anubis.c1
-rw-r--r--crypto/api.c2
-rw-r--r--crypto/blowfish.c1
-rw-r--r--crypto/compress.c1
-rw-r--r--crypto/crypto_null.c1
-rw-r--r--crypto/digest.c4
-rw-r--r--crypto/fcrypt.c2
-rw-r--r--crypto/hmac.c12
-rw-r--r--crypto/khazad.c1
-rw-r--r--crypto/scatterwalk.c4
-rw-r--r--crypto/scatterwalk.h8
-rw-r--r--crypto/sha1_generic.c1
-rw-r--r--crypto/sha256_generic.c1
-rw-r--r--crypto/sha512.c1
-rw-r--r--crypto/tcrypt.c24
-rw-r--r--crypto/tea.c1
-rw-r--r--crypto/tgr192.c1
-rw-r--r--crypto/wp512.c1
-rw-r--r--crypto/xcbc.c2
-rw-r--r--drivers/Kconfig6
-rw-r--r--drivers/Makefile6
-rw-r--r--drivers/acorn/char/defkeymap-l7200.c2
-rw-r--r--drivers/acpi/Kconfig18
-rw-r--r--drivers/acpi/Makefile1
-rw-r--r--drivers/acpi/ac.c73
-rw-r--r--drivers/acpi/battery.c1058
-rw-r--r--drivers/acpi/bus.c31
-rw-r--r--drivers/acpi/button.c43
-rw-r--r--drivers/acpi/ec.c239
-rw-r--r--drivers/acpi/events/evevent.c6
-rw-r--r--drivers/acpi/fan.c72
-rw-r--r--drivers/acpi/hardware/hwregs.c89
-rw-r--r--drivers/acpi/hardware/hwsleep.c40
-rw-r--r--drivers/acpi/osl.c8
-rw-r--r--drivers/acpi/power.c63
-rw-r--r--drivers/acpi/processor_core.c30
-rw-r--r--drivers/acpi/processor_idle.c488
-rw-r--r--drivers/acpi/sbs.c1869
-rw-r--r--drivers/acpi/sbshc.c309
-rw-r--r--drivers/acpi/sbshc.h27
-rw-r--r--drivers/acpi/sleep/main.c48
-rw-r--r--drivers/acpi/sleep/proc.c66
-rw-r--r--drivers/acpi/sleep/sleep.h1
-rw-r--r--drivers/acpi/sleep/wakeup.c117
-rw-r--r--drivers/acpi/tables/tbutils.c2
-rw-r--r--drivers/acpi/thermal.c28
-rw-r--r--drivers/acpi/toshiba_acpi.c3
-rw-r--r--drivers/acpi/video.c30
-rw-r--r--drivers/ata/Kconfig25
-rw-r--r--drivers/ata/Makefile2
-rw-r--r--drivers/ata/ahci.c346
-rw-r--r--drivers/ata/ata_piix.c72
-rw-r--r--drivers/ata/libata-acpi.c26
-rw-r--r--drivers/ata/libata-core.c629
-rw-r--r--drivers/ata/libata-eh.c217
-rw-r--r--drivers/ata/libata-scsi.c351
-rw-r--r--drivers/ata/libata-sff.c8
-rw-r--r--drivers/ata/libata.h2
-rw-r--r--drivers/ata/pata_acpi.c6
-rw-r--r--drivers/ata/pata_bf54x.c77
-rw-r--r--drivers/ata/pata_cmd64x.c2
-rw-r--r--drivers/ata/pata_cs5530.c2
-rw-r--r--drivers/ata/pata_cs5535.c2
-rw-r--r--drivers/ata/pata_cs5536.c344
-rw-r--r--drivers/ata/pata_hpt37x.c49
-rw-r--r--drivers/ata/pata_icside.c42
-rw-r--r--drivers/ata/pata_it821x.c4
-rw-r--r--drivers/ata/pata_mpiix.c2
-rw-r--r--drivers/ata/pata_ns87410.c2
-rw-r--r--drivers/ata/pata_ns87415.c12
-rw-r--r--drivers/ata/pata_oldpiix.c2
-rw-r--r--drivers/ata/pata_optidma.c2
-rw-r--r--drivers/ata/pata_pcmcia.c14
-rw-r--r--drivers/ata/pata_pdc2027x.c2
-rw-r--r--drivers/ata/pata_pdc202xx_old.c4
-rw-r--r--drivers/ata/pata_platform.c35
-rw-r--r--drivers/ata/pata_radisys.c2
-rw-r--r--drivers/ata/pata_sc1200.c2
-rw-r--r--drivers/ata/pata_scc.c13
-rw-r--r--drivers/ata/pata_serverworks.c11
-rw-r--r--drivers/ata/pata_sil680.c63
-rw-r--r--drivers/ata/pata_via.c4
-rw-r--r--drivers/ata/pata_winbond.c2
-rw-r--r--drivers/ata/pdc_adma.c21
-rw-r--r--drivers/ata/sata_fsl.c1395
-rw-r--r--drivers/ata/sata_inic162x.c4
-rw-r--r--drivers/ata/sata_mv.c56
-rw-r--r--drivers/ata/sata_nv.c1027
-rw-r--r--drivers/ata/sata_promise.c142
-rw-r--r--drivers/ata/sata_qstor.c117
-rw-r--r--drivers/ata/sata_sil.c11
-rw-r--r--drivers/ata/sata_sil24.c26
-rw-r--r--drivers/ata/sata_sis.c77
-rw-r--r--drivers/ata/sata_svw.c10
-rw-r--r--drivers/ata/sata_sx4.c181
-rw-r--r--drivers/ata/sata_uli.c18
-rw-r--r--drivers/ata/sata_via.c20
-rw-r--r--drivers/ata/sata_vsc.c15
-rw-r--r--drivers/atm/Makefile2
-rw-r--r--drivers/atm/firestream.c2
-rw-r--r--drivers/atm/horizon.c5
-rw-r--r--drivers/base/core.c6
-rw-r--r--drivers/base/dmapool.c5
-rw-r--r--drivers/base/memory.c15
-rw-r--r--drivers/base/node.c91
-rw-r--r--drivers/base/power/trace.c2
-rw-r--r--drivers/base/topology.c11
-rw-r--r--drivers/block/DAC960.c3
-rw-r--r--drivers/block/Kconfig27
-rw-r--r--drivers/block/Makefile2
-rw-r--r--drivers/block/aoe/aoe.h9
-rw-r--r--drivers/block/aoe/aoecmd.c14
-rw-r--r--drivers/block/aoe/aoenet.c2
-rw-r--r--drivers/block/cciss.c164
-rw-r--r--drivers/block/cciss_scsi.c14
-rw-r--r--drivers/block/cciss_scsi.h14
-rw-r--r--drivers/block/cpqarray.c7
-rw-r--r--drivers/block/cryptoloop.c17
-rw-r--r--drivers/block/floppy.c167
-rw-r--r--drivers/block/lguest_blk.c421
-rw-r--r--drivers/block/loop.c77
-rw-r--r--drivers/block/nbd.c118
-rw-r--r--drivers/block/paride/pf.c25
-rw-r--r--drivers/block/paride/pt.c2
-rw-r--r--drivers/block/pktcdvd.c16
-rw-r--r--drivers/block/ps3disk.c21
-rw-r--r--drivers/block/rd.c42
-rw-r--r--drivers/block/sunvdc.c2
-rw-r--r--drivers/block/sx8.c2
-rw-r--r--drivers/block/ub.c18
-rw-r--r--drivers/block/viodasd.c2
-rw-r--r--drivers/block/virtio_blk.c310
-rw-r--r--drivers/block/xsysace.c4
-rw-r--r--drivers/bluetooth/Kconfig35
-rw-r--r--drivers/bluetooth/Makefile4
-rw-r--r--drivers/bluetooth/bluecard_cs.c5
-rw-r--r--drivers/bluetooth/bpa10x.c624
-rw-r--r--drivers/bluetooth/bt3c_cs.c5
-rw-r--r--drivers/bluetooth/btsdio.c406
-rw-r--r--drivers/bluetooth/btuart_cs.c5
-rw-r--r--drivers/bluetooth/btusb.c564
-rw-r--r--drivers/bluetooth/dtl1_cs.c5
-rw-r--r--drivers/bluetooth/hci_bcsp.c3
-rw-r--r--drivers/bluetooth/hci_ldisc.c8
-rw-r--r--drivers/bluetooth/hci_ll.c531
-rw-r--r--drivers/bluetooth/hci_uart.h8
-rw-r--r--drivers/cdrom/cdrom.c48
-rw-r--r--drivers/cdrom/viocd.c3
-rw-r--r--drivers/char/Kconfig14
-rw-r--r--drivers/char/Makefile2
-rw-r--r--drivers/char/agp/Kconfig6
-rw-r--r--drivers/char/agp/amd64-agp.c2
-rw-r--r--drivers/char/agp/efficeon-agp.c11
-rw-r--r--drivers/char/agp/hp-agp.c9
-rw-r--r--drivers/char/agp/i460-agp.c5
-rw-r--r--drivers/char/agp/parisc-agp.c7
-rw-r--r--drivers/char/apm-emulation.c2
-rw-r--r--drivers/char/consolemap.c25
-rw-r--r--drivers/char/cyclades.c771
-rw-r--r--drivers/char/defkeymap.c_shipped2
-rw-r--r--drivers/char/drm/Kconfig2
-rw-r--r--drivers/char/drm/drmP.h2
-rw-r--r--drivers/char/drm/drm_bufs.c2
-rw-r--r--drivers/char/drm/drm_drv.c2
-rw-r--r--drivers/char/drm/drm_fops.c7
-rw-r--r--drivers/char/drm/drm_hashtab.c2
-rw-r--r--drivers/char/drm/drm_hashtab.h2
-rw-r--r--drivers/char/drm/drm_ioctl.c2
-rw-r--r--drivers/char/drm/drm_lock.c6
-rw-r--r--drivers/char/drm/drm_mm.c2
-rw-r--r--drivers/char/drm/drm_os_linux.h10
-rw-r--r--drivers/char/drm/drm_pci.c4
-rw-r--r--drivers/char/drm/drm_sarea.h2
-rw-r--r--drivers/char/drm/drm_sman.c2
-rw-r--r--drivers/char/drm/drm_sman.h2
-rw-r--r--drivers/char/drm/i810_dma.c2
-rw-r--r--drivers/char/drm/i830_dma.c2
-rw-r--r--drivers/char/drm/r128_drv.h2
-rw-r--r--drivers/char/drm/radeon_cp.c5
-rw-r--r--drivers/char/drm/radeon_drv.h1
-rw-r--r--drivers/char/drm/radeon_irq.c6
-rw-r--r--drivers/char/drm/radeon_state.c2
-rw-r--r--drivers/char/drm/savage_bci.c3
-rw-r--r--drivers/char/drm/sis_mm.c3
-rw-r--r--drivers/char/drm/via_mm.c2
-rw-r--r--drivers/char/drm/via_verifier.h2
-rw-r--r--drivers/char/ec3104_keyb.c457
-rw-r--r--drivers/char/epca.c2611
-rw-r--r--drivers/char/esp.c4
-rw-r--r--drivers/char/hvc_console.c56
-rw-r--r--drivers/char/hvc_lguest.c177
-rw-r--r--drivers/char/hw_random/omap-rng.c2
-rw-r--r--drivers/char/i8k.c14
-rw-r--r--drivers/char/ip2/ip2main.c80
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c27
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c29
-rw-r--r--drivers/char/ipmi/ipmi_watchdog.c268
-rw-r--r--drivers/char/isicom.c10
-rw-r--r--drivers/char/keyboard.c85
-rw-r--r--drivers/char/lp.c17
-rw-r--r--drivers/char/mbcs.c1
-rw-r--r--drivers/char/mem.c134
-rw-r--r--drivers/char/moxa.c148
-rw-r--r--drivers/char/mspec.c2
-rw-r--r--drivers/char/mxser.c25
-rw-r--r--drivers/char/mxser.h3
-rw-r--r--drivers/char/mxser_new.c122
-rw-r--r--drivers/char/n_hdlc.c2
-rw-r--r--drivers/char/n_tty.c4
-rw-r--r--drivers/char/pcmcia/cm4000_cs.c2
-rw-r--r--drivers/char/pcmcia/cm4040_cs.c2
-rw-r--r--drivers/char/pcmcia/synclink_cs.c706
-rw-r--r--drivers/char/ppdev.c5
-rw-r--r--drivers/char/pty.c24
-rw-r--r--drivers/char/random.c8
-rw-r--r--drivers/char/riscom8.c16
-rw-r--r--drivers/char/rocket.c93
-rw-r--r--drivers/char/rocket_int.h7
-rw-r--r--drivers/char/rtc.c52
-rw-r--r--drivers/char/sonypi.c10
-rw-r--r--drivers/char/sx.c2
-rw-r--r--drivers/char/synclink.c4
-rw-r--r--drivers/char/sysrq.c7
-rw-r--r--drivers/char/tpm/tpm_tis.c26
-rw-r--r--drivers/char/tty_io.c25
-rw-r--r--drivers/char/tty_ioctl.c265
-rw-r--r--drivers/char/virtio_console.c225
-rw-r--r--drivers/char/vt.c60
-rw-r--r--drivers/char/vt_ioctl.c63
-rw-r--r--drivers/connector/connector.c5
-rw-r--r--drivers/cpuidle/Kconfig20
-rw-r--r--drivers/cpuidle/Makefile5
-rw-r--r--drivers/cpuidle/cpuidle.c294
-rw-r--r--drivers/cpuidle/cpuidle.h33
-rw-r--r--drivers/cpuidle/driver.c56
-rw-r--r--drivers/cpuidle/governor.c138
-rw-r--r--drivers/cpuidle/governors/Makefile6
-rw-r--r--drivers/cpuidle/governors/ladder.c166
-rw-r--r--drivers/cpuidle/governors/menu.c137
-rw-r--r--drivers/cpuidle/sysfs.c361
-rw-r--r--drivers/crypto/geode-aes.c3
-rw-r--r--drivers/crypto/padlock-sha.c4
-rw-r--r--drivers/dca/Kconfig7
-rw-r--r--drivers/dca/Makefile2
-rw-r--r--drivers/dca/dca-core.c200
-rw-r--r--drivers/dca/dca-sysfs.c88
-rw-r--r--drivers/dma/Kconfig61
-rw-r--r--drivers/dma/Makefile1
-rw-r--r--drivers/dma/dmaengine.c17
-rw-r--r--drivers/dma/ioat.c211
-rw-r--r--drivers/dma/ioat_dca.c427
-rw-r--r--drivers/dma/ioat_dma.c1383
-rw-r--r--drivers/dma/ioatdma.c817
-rw-r--r--drivers/dma/ioatdma.h69
-rw-r--r--drivers/dma/ioatdma_hw.h33
-rw-r--r--drivers/dma/ioatdma_registers.h110
-rw-r--r--drivers/dma/iop-adma.c9
-rw-r--r--drivers/edac/edac_core.h2
-rw-r--r--drivers/edac/i5000_edac.c2
-rw-r--r--drivers/edac/pasemi_edac.c1
-rw-r--r--drivers/fc4/Kconfig81
-rw-r--r--drivers/fc4/Makefile9
-rw-r--r--drivers/fc4/fc-al.h27
-rw-r--r--drivers/fc4/fc.c1146
-rw-r--r--drivers/fc4/fc.h230
-rw-r--r--drivers/fc4/fc_syms.c30
-rw-r--r--drivers/fc4/fcp.h94
-rw-r--r--drivers/fc4/fcp_impl.h164
-rw-r--r--drivers/fc4/soc.c764
-rw-r--r--drivers/fc4/soc.h301
-rw-r--r--drivers/fc4/socal.c904
-rw-r--r--drivers/fc4/socal.h314
-rw-r--r--drivers/firewire/fw-cdev.c52
-rw-r--r--drivers/firewire/fw-device.h5
-rw-r--r--drivers/firewire/fw-ohci.c91
-rw-r--r--drivers/firewire/fw-ohci.h2
-rw-r--r--drivers/firewire/fw-sbp2.c650
-rw-r--r--drivers/firewire/fw-topology.c10
-rw-r--r--drivers/firewire/fw-topology.h6
-rw-r--r--drivers/firewire/fw-transaction.c14
-rw-r--r--drivers/firmware/dcdbas.h1
-rw-r--r--drivers/hid/hid-input.c22
-rw-r--r--drivers/hid/hidraw.c4
-rw-r--r--drivers/hid/usbhid/hid-ff.c2
-rw-r--r--drivers/hid/usbhid/hid-quirks.c8
-rw-r--r--drivers/hid/usbhid/hiddev.c2
-rw-r--r--drivers/hid/usbhid/usbkbd.c7
-rw-r--r--drivers/hid/usbhid/usbmouse.c12
-rw-r--r--drivers/hwmon/Kconfig13
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/abituguru3.c56
-rw-r--r--drivers/hwmon/adm1026.c2
-rw-r--r--drivers/hwmon/ams/ams-input.c76
-rw-r--r--drivers/hwmon/ams/ams.h5
-rw-r--r--drivers/hwmon/applesmc.c190
-rw-r--r--drivers/hwmon/coretemp.c6
-rw-r--r--drivers/hwmon/f75375s.c170
-rw-r--r--drivers/hwmon/gl520sm.c4
-rw-r--r--drivers/hwmon/hdaps.c55
-rw-r--r--drivers/hwmon/hwmon-vid.c2
-rw-r--r--drivers/hwmon/i5k_amb.c552
-rw-r--r--drivers/hwmon/ibmpex.c48
-rw-r--r--drivers/hwmon/lm63.c2
-rw-r--r--drivers/hwmon/lm70.c11
-rw-r--r--drivers/hwmon/sis5595.c61
-rw-r--r--drivers/hwmon/via686a.c4
-rw-r--r--drivers/hwmon/vt1211.c2
-rw-r--r--drivers/hwmon/w83627hf.c155
-rw-r--r--drivers/hwmon/w83781d.c3
-rw-r--r--drivers/hwmon/w83791d.c2
-rw-r--r--drivers/hwmon/w83792d.c4
-rw-r--r--drivers/i2c/algos/i2c-algo-bit.c2
-rw-r--r--drivers/i2c/algos/i2c-algo-pca.c2
-rw-r--r--drivers/i2c/algos/i2c-algo-pcf.c2
-rw-r--r--drivers/i2c/busses/Kconfig10
-rw-r--r--drivers/i2c/busses/i2c-elektor.c2
-rw-r--r--drivers/i2c/busses/i2c-hydra.c2
-rw-r--r--drivers/i2c/busses/i2c-ibm_iic.c2
-rw-r--r--drivers/i2c/busses/i2c-omap.c2
-rw-r--r--drivers/i2c/busses/i2c-parport-light.c2
-rw-r--r--drivers/i2c/busses/i2c-parport.c2
-rw-r--r--drivers/i2c/busses/i2c-pasemi.c7
-rw-r--r--drivers/i2c/busses/i2c-pmcmsp.c8
-rw-r--r--drivers/i2c/busses/i2c-pnx.c2
-rw-r--r--drivers/i2c/busses/i2c-pxa.c99
-rw-r--r--drivers/i2c/busses/i2c-via.c4
-rw-r--r--drivers/i2c/busses/i2c-viapro.c2
-rw-r--r--drivers/i2c/chips/eeprom.c37
-rw-r--r--drivers/i2c/chips/menelaus.c12
-rw-r--r--drivers/i2c/i2c-core.c5
-rw-r--r--drivers/i2c/i2c-dev.c86
-rw-r--r--drivers/ide/Kconfig47
-rw-r--r--drivers/ide/arm/bast-ide.c2
-rw-r--r--drivers/ide/arm/icside.c80
-rw-r--r--drivers/ide/arm/ide_arm.c2
-rw-r--r--drivers/ide/arm/rapide.c37
-rw-r--r--drivers/ide/cris/ide-cris.c28
-rw-r--r--drivers/ide/h8300/ide-h8300.c3
-rw-r--r--drivers/ide/ide-acpi.c2
-rw-r--r--drivers/ide/ide-cd.c6
-rw-r--r--drivers/ide/ide-disk.c61
-rw-r--r--drivers/ide/ide-dma.c120
-rw-r--r--drivers/ide/ide-io.c117
-rw-r--r--drivers/ide/ide-iops.c41
-rw-r--r--drivers/ide/ide-lib.c16
-rw-r--r--drivers/ide/ide-pnp.c3
-rw-r--r--drivers/ide/ide-probe.c114
-rw-r--r--drivers/ide/ide-proc.c2
-rw-r--r--drivers/ide/ide-tape.c3
-rw-r--r--drivers/ide/ide-taskfile.c58
-rw-r--r--drivers/ide/ide.c96
-rw-r--r--drivers/ide/legacy/ali14xx.c13
-rw-r--r--drivers/ide/legacy/buddha.c4
-rw-r--r--drivers/ide/legacy/dtc2278.c16
-rw-r--r--drivers/ide/legacy/falconide.c2
-rw-r--r--drivers/ide/legacy/gayle.c2
-rw-r--r--drivers/ide/legacy/ht6560b.c33
-rw-r--r--drivers/ide/legacy/ide-cs.c14
-rw-r--r--drivers/ide/legacy/ide_platform.c43
-rw-r--r--drivers/ide/legacy/macide.c6
-rw-r--r--drivers/ide/legacy/q40ide.c7
-rw-r--r--drivers/ide/legacy/qd65xx.c64
-rw-r--r--drivers/ide/legacy/umc8672.c9
-rw-r--r--drivers/ide/mips/au1xxx-ide.c68
-rw-r--r--drivers/ide/mips/swarm.c14
-rw-r--r--drivers/ide/pci/aec62xx.c146
-rw-r--r--drivers/ide/pci/alim15x3.c155
-rw-r--r--drivers/ide/pci/amd74xx.c241
-rw-r--r--drivers/ide/pci/atiixp.c115
-rw-r--r--drivers/ide/pci/cmd640.c42
-rw-r--r--drivers/ide/pci/cmd64x.c121
-rw-r--r--drivers/ide/pci/cs5520.c80
-rw-r--r--drivers/ide/pci/cs5530.c68
-rw-r--r--drivers/ide/pci/cs5535.c45
-rw-r--r--drivers/ide/pci/cy82c693.c36
-rw-r--r--drivers/ide/pci/delkin_cb.c2
-rw-r--r--drivers/ide/pci/generic.c196
-rw-r--r--drivers/ide/pci/hpt34x.c78
-rw-r--r--drivers/ide/pci/hpt366.c433
-rw-r--r--drivers/ide/pci/it8213.c102
-rw-r--r--drivers/ide/pci/it821x.c81
-rw-r--r--drivers/ide/pci/jmicron.c49
-rw-r--r--drivers/ide/pci/ns87415.c17
-rw-r--r--drivers/ide/pci/opti621.c44
-rw-r--r--drivers/ide/pci/pdc202xx_new.c238
-rw-r--r--drivers/ide/pci/pdc202xx_old.c177
-rw-r--r--drivers/ide/pci/piix.c291
-rw-r--r--drivers/ide/pci/rz1000.c16
-rw-r--r--drivers/ide/pci/sc1200.c57
-rw-r--r--drivers/ide/pci/scc_pata.c66
-rw-r--r--drivers/ide/pci/serverworks.c128
-rw-r--r--drivers/ide/pci/sgiioc4.c52
-rw-r--r--drivers/ide/pci/siimage.c167
-rw-r--r--drivers/ide/pci/sis5513.c479
-rw-r--r--drivers/ide/pci/sl82c105.c46
-rw-r--r--drivers/ide/pci/slc90e66.c84
-rw-r--r--drivers/ide/pci/tc86c001.c49
-rw-r--r--drivers/ide/pci/triflex.c35
-rw-r--r--drivers/ide/pci/trm290.c21
-rw-r--r--drivers/ide/pci/via82cxxx.c120
-rw-r--r--drivers/ide/ppc/mpc8xx.c4
-rw-r--r--drivers/ide/ppc/pmac.c50
-rw-r--r--drivers/ide/setup-pci.c311
-rw-r--r--drivers/ieee1394/csr1212.c57
-rw-r--r--drivers/ieee1394/csr1212.h6
-rw-r--r--drivers/ieee1394/dma.c9
-rw-r--r--drivers/ieee1394/eth1394.c16
-rw-r--r--drivers/ieee1394/ieee1394_core.c2
-rw-r--r--drivers/ieee1394/ieee1394_transactions.c2
-rw-r--r--drivers/ieee1394/nodemgr.c22
-rw-r--r--drivers/ieee1394/pcilynx.c29
-rw-r--r--drivers/ieee1394/sbp2.c19
-rw-r--r--drivers/infiniband/core/cma.c165
-rw-r--r--drivers/infiniband/core/fmr_pool.c8
-rw-r--r--drivers/infiniband/core/umem.c13
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c8
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_provider.c1
-rw-r--r--drivers/infiniband/hw/ehca/ehca_av.c48
-rw-r--r--drivers/infiniband/hw/ehca/ehca_classes.h4
-rw-r--r--drivers/infiniband/hw/ehca/ehca_eq.c6
-rw-r--r--drivers/infiniband/hw/ehca/ehca_hca.c21
-rw-r--r--drivers/infiniband/hw/ehca/ehca_iverbs.h3
-rw-r--r--drivers/infiniband/hw/ehca/ehca_main.c59
-rw-r--r--drivers/infiniband/hw/ehca/ehca_mrmw.c63
-rw-r--r--drivers/infiniband/hw/ehca/ehca_qp.c33
-rw-r--r--drivers/infiniband/hw/ehca/hipz_hw.h6
-rw-r--r--drivers/infiniband/hw/ipath/ipath_cq.c11
-rw-r--r--drivers/infiniband/hw/ipath/ipath_dma.c12
-rw-r--r--drivers/infiniband/hw/ipath/ipath_eeprom.c10
-rw-r--r--drivers/infiniband/hw/ipath/ipath_intr.c18
-rw-r--r--drivers/infiniband/hw/ipath/ipath_mr.c2
-rw-r--r--drivers/infiniband/hw/ipath/ipath_rc.c5
-rw-r--r--drivers/infiniband/hw/ipath/ipath_ruc.c14
-rw-r--r--drivers/infiniband/hw/mlx4/qp.c20
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cq.c53
-rw-r--r--drivers/infiniband/hw/mthca/mthca_doorbell.h13
-rw-r--r--drivers/infiniband/hw/mthca/mthca_eq.c21
-rw-r--r--drivers/infiniband/hw/mthca/mthca_memfree.c29
-rw-r--r--drivers/infiniband/hw/mthca/mthca_qp.c45
-rw-r--r--drivers/infiniband/hw/mthca/mthca_srq.c11
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h19
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_cm.c116
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c52
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c33
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c3
-rw-r--r--drivers/infiniband/ulp/iser/iser_memory.c75
-rw-r--r--drivers/input/Kconfig22
-rw-r--r--drivers/input/Makefile1
-rw-r--r--drivers/input/evdev.c720
-rw-r--r--drivers/input/fixp-arith.h2
-rw-r--r--drivers/input/gameport/gameport.c6
-rw-r--r--drivers/input/input-polldev.c7
-rw-r--r--drivers/input/input.c670
-rw-r--r--drivers/input/joydev.c759
-rw-r--r--drivers/input/joystick/a3d.c28
-rw-r--r--drivers/input/joystick/adi.c2
-rw-r--r--drivers/input/joystick/amijoy.c7
-rw-r--r--drivers/input/joystick/analog.c2
-rw-r--r--drivers/input/joystick/cobra.c2
-rw-r--r--drivers/input/joystick/db9.c4
-rw-r--r--drivers/input/joystick/gamecon.c4
-rw-r--r--drivers/input/joystick/gf2k.c2
-rw-r--r--drivers/input/joystick/grip.c2
-rw-r--r--drivers/input/joystick/grip_mp.c2
-rw-r--r--drivers/input/joystick/guillemot.c2
-rw-r--r--drivers/input/joystick/iforce/Makefile2
-rw-r--r--drivers/input/joystick/iforce/iforce-main.c3
-rw-r--r--drivers/input/joystick/iforce/iforce.h4
-rw-r--r--drivers/input/joystick/interact.c2
-rw-r--r--drivers/input/joystick/magellan.c2
-rw-r--r--drivers/input/joystick/sidewinder.c2
-rw-r--r--drivers/input/joystick/spaceball.c17
-rw-r--r--drivers/input/joystick/spaceorb.c2
-rw-r--r--drivers/input/joystick/stinger.c9
-rw-r--r--drivers/input/joystick/tmdc.c2
-rw-r--r--drivers/input/joystick/turbografx.c2
-rw-r--r--drivers/input/joystick/twidjoy.c2
-rw-r--r--drivers/input/joystick/warrior.c8
-rw-r--r--drivers/input/joystick/xpad.c59
-rw-r--r--drivers/input/keyboard/Kconfig40
-rw-r--r--drivers/input/keyboard/Makefile5
-rw-r--r--drivers/input/keyboard/aaed2000_kbd.c2
-rw-r--r--drivers/input/keyboard/amikbd.c2
-rw-r--r--drivers/input/keyboard/atakbd.c2
-rw-r--r--drivers/input/keyboard/atkbd.c21
-rw-r--r--drivers/input/keyboard/bf54x-keys.c381
-rw-r--r--drivers/input/keyboard/corgikbd.c3
-rw-r--r--drivers/input/keyboard/gpio_keys.c83
-rw-r--r--drivers/input/keyboard/hil_kbd.c5
-rw-r--r--drivers/input/keyboard/hilkbd.c5
-rw-r--r--drivers/input/keyboard/jornada680_kbd.c277
-rw-r--r--drivers/input/keyboard/jornada720_kbd.c185
-rw-r--r--drivers/input/keyboard/locomokbd.c2
-rw-r--r--drivers/input/keyboard/maple_keyb.c252
-rw-r--r--drivers/input/keyboard/newtonkbd.c2
-rw-r--r--drivers/input/keyboard/omap-keypad.c26
-rw-r--r--drivers/input/keyboard/pxa27x_keyboard.c30
-rw-r--r--drivers/input/keyboard/spitzkbd.c3
-rw-r--r--drivers/input/keyboard/stowaway.c2
-rw-r--r--drivers/input/keyboard/sunkbd.c8
-rw-r--r--drivers/input/keyboard/xtkbd.c2
-rw-r--r--drivers/input/misc/Kconfig6
-rw-r--r--drivers/input/misc/ati_remote.c8
-rw-r--r--drivers/input/misc/ati_remote2.c7
-rw-r--r--drivers/input/misc/atlas_btns.c2
-rw-r--r--drivers/input/misc/cobalt_btns.c2
-rw-r--r--drivers/input/misc/ixp4xx-beeper.c4
-rw-r--r--drivers/input/misc/keyspan_remote.c2
-rw-r--r--drivers/input/misc/m68kspkr.c4
-rw-r--r--drivers/input/misc/pcspkr.c6
-rw-r--r--drivers/input/misc/powermate.c9
-rw-r--r--drivers/input/misc/sparcspkr.c4
-rw-r--r--drivers/input/misc/yealink.c2
-rw-r--r--drivers/input/mouse/alps.c28
-rw-r--r--drivers/input/mouse/amimouse.c7
-rw-r--r--drivers/input/mouse/appletouch.c119
-rw-r--r--drivers/input/mouse/atarimouse.c7
-rw-r--r--drivers/input/mouse/hil_ptr.c6
-rw-r--r--drivers/input/mouse/inport.c9
-rw-r--r--drivers/input/mouse/lifebook.c21
-rw-r--r--drivers/input/mouse/logibm.c9
-rw-r--r--drivers/input/mouse/pc110pad.c6
-rw-r--r--drivers/input/mouse/psmouse-base.c14
-rw-r--r--drivers/input/mouse/rpcmouse.c7
-rw-r--r--drivers/input/mouse/sermouse.c7
-rw-r--r--drivers/input/mouse/touchkit_ps2.c2
-rw-r--r--drivers/input/mouse/vsxxxaa.c2
-rw-r--r--drivers/input/mousedev.c762
-rw-r--r--drivers/input/serio/hp_sdc.c4
-rw-r--r--drivers/input/serio/i8042.c8
-rw-r--r--drivers/input/serio/i8042.h22
-rw-r--r--drivers/input/serio/parkbd.c2
-rw-r--r--drivers/input/serio/serio.c3
-rw-r--r--drivers/input/tablet/acecad.c12
-rw-r--r--drivers/input/tablet/gtco.c6
-rw-r--r--drivers/input/tablet/kbtab.c11
-rw-r--r--drivers/input/tablet/wacom_sys.c58
-rw-r--r--drivers/input/touchscreen/Kconfig27
-rw-r--r--drivers/input/touchscreen/Makefile1
-rw-r--r--drivers/input/touchscreen/ads7846.c4
-rw-r--r--drivers/input/touchscreen/corgi_ts.c4
-rw-r--r--drivers/input/touchscreen/elo.c4
-rw-r--r--drivers/input/touchscreen/fujitsu_ts.c4
-rw-r--r--drivers/input/touchscreen/gunze.c4
-rw-r--r--drivers/input/touchscreen/h3600_ts_input.c5
-rw-r--r--drivers/input/touchscreen/hp680_ts_input.c4
-rw-r--r--drivers/input/touchscreen/jornada720_ts.c182
-rw-r--r--drivers/input/touchscreen/mk712.c4
-rw-r--r--drivers/input/touchscreen/mtouch.c4
-rw-r--r--drivers/input/touchscreen/penmount.c4
-rw-r--r--drivers/input/touchscreen/touchright.c4
-rw-r--r--drivers/input/touchscreen/touchwin.c4
-rw-r--r--drivers/input/touchscreen/ucb1400_ts.c8
-rw-r--r--drivers/input/touchscreen/usbtouchscreen.c131
-rw-r--r--drivers/input/tsdev.c533
-rw-r--r--drivers/isdn/act2000/act2000_isa.c14
-rw-r--r--drivers/isdn/capi/capidrv.c30
-rw-r--r--drivers/isdn/capi/kcapi.c2
-rw-r--r--drivers/isdn/gigaset/bas-gigaset.c9
-rw-r--r--drivers/isdn/gigaset/common.c3
-rw-r--r--drivers/isdn/gigaset/i4l.c12
-rw-r--r--drivers/isdn/gigaset/proc.c8
-rw-r--r--drivers/isdn/gigaset/usb-gigaset.c7
-rw-r--r--drivers/isdn/hardware/avm/b1.c28
-rw-r--r--drivers/isdn/hardware/avm/b1dma.c28
-rw-r--r--drivers/isdn/hardware/avm/c4.c16
-rw-r--r--drivers/isdn/hardware/avm/t1isa.c28
-rw-r--r--drivers/isdn/hardware/eicon/capifunc.c4
-rw-r--r--drivers/isdn/hisax/Kconfig18
-rw-r--r--drivers/isdn/hisax/amd7930_fn.c2
-rw-r--r--drivers/isdn/hisax/avm_pci.c4
-rw-r--r--drivers/isdn/hisax/diva.c6
-rw-r--r--drivers/isdn/hisax/elsa.c6
-rw-r--r--drivers/isdn/hisax/enternow_pci.c18
-rw-r--r--drivers/isdn/hisax/gazel.c4
-rw-r--r--drivers/isdn/hisax/hfc_pci.c2
-rw-r--r--drivers/isdn/hisax/isdnhdlc.c4
-rw-r--r--drivers/isdn/hisax/isdnhdlc.h2
-rw-r--r--drivers/isdn/hisax/jade.c2
-rw-r--r--drivers/isdn/hisax/niccy.c7
-rw-r--r--drivers/isdn/hisax/sedlbauer.c4
-rw-r--r--drivers/isdn/i4l/isdn_common.c26
-rw-r--r--drivers/isdn/i4l/isdn_net.c146
-rw-r--r--drivers/isdn/i4l/isdn_ppp.c9
-rw-r--r--drivers/isdn/pcbit/capi.c4
-rw-r--r--drivers/isdn/sc/card.h2
-rw-r--r--drivers/isdn/sc/debug.h19
-rw-r--r--drivers/isdn/sc/includes.h1
-rw-r--r--drivers/isdn/sc/init.c5
-rw-r--r--drivers/isdn/sc/interrupt.c17
-rw-r--r--drivers/isdn/sc/packet.c2
-rw-r--r--drivers/isdn/sc/shmem.c9
-rw-r--r--drivers/kvm/Kconfig4
-rw-r--r--drivers/kvm/kvm_main.c37
-rw-r--r--drivers/kvm/lapic.c38
-rw-r--r--drivers/kvm/mmu.c3
-rw-r--r--drivers/kvm/svm.c18
-rw-r--r--drivers/kvm/vmx.c16
-rw-r--r--drivers/kvm/x86_emulate.c103
-rw-r--r--drivers/leds/Kconfig8
-rw-r--r--drivers/leds/Makefile1
-rw-r--r--drivers/leds/leds-cm-x270.c122
-rw-r--r--drivers/leds/leds-gpio.c20
-rw-r--r--drivers/leds/leds-s3c24xx.c2
-rw-r--r--drivers/lguest/Kconfig13
-rw-r--r--drivers/lguest/Makefile10
-rw-r--r--drivers/lguest/core.c575
-rw-r--r--drivers/lguest/hypercalls.c186
-rw-r--r--drivers/lguest/interrupts_and_traps.c160
-rw-r--r--drivers/lguest/io.c626
-rw-r--r--drivers/lguest/lg.h194
-rw-r--r--drivers/lguest/lguest_bus.c218
-rw-r--r--drivers/lguest/lguest_device.c377
-rw-r--r--drivers/lguest/lguest_user.c163
-rw-r--r--drivers/lguest/page_tables.c361
-rw-r--r--drivers/lguest/segments.c76
-rw-r--r--drivers/lguest/x86/core.c581
-rw-r--r--drivers/lguest/x86/switcher_32.S (renamed from drivers/lguest/switcher.S)78
-rw-r--r--drivers/macintosh/Kconfig1
-rw-r--r--drivers/macintosh/adbhid.c77
-rw-r--r--drivers/macintosh/mac_hid.c7
-rw-r--r--drivers/macintosh/mediabay.c2
-rw-r--r--drivers/macintosh/via-pmu.c2
-rw-r--r--drivers/macintosh/windfarm_core.c10
-rw-r--r--drivers/md/Kconfig12
-rw-r--r--drivers/md/Makefile6
-rw-r--r--drivers/md/bitmap.c5
-rw-r--r--drivers/md/dm-bio-list.h5
-rw-r--r--drivers/md/dm-crypt.c222
-rw-r--r--drivers/md/dm-delay.c23
-rw-r--r--drivers/md/dm-emc.c8
-rw-r--r--drivers/md/dm-hw-handler.c6
-rw-r--r--drivers/md/dm-hw-handler.h1
-rw-r--r--drivers/md/dm-ioctl.c40
-rw-r--r--drivers/md/dm-log.c2
-rw-r--r--drivers/md/dm-log.h3
-rw-r--r--drivers/md/dm-mpath-hp-sw.c248
-rw-r--r--drivers/md/dm-mpath-rdac.c15
-rw-r--r--drivers/md/dm-mpath.c88
-rw-r--r--drivers/md/dm-path-selector.c6
-rw-r--r--drivers/md/dm-raid1.c35
-rw-r--r--drivers/md/dm-snap.c3
-rw-r--r--drivers/md/dm-stripe.c3
-rw-r--r--drivers/md/dm-table.c41
-rw-r--r--drivers/md/dm-target.c6
-rw-r--r--drivers/md/dm-uevent.c222
-rw-r--r--drivers/md/dm-uevent.h59
-rw-r--r--drivers/md/dm.c93
-rw-r--r--drivers/md/dm.h1
-rw-r--r--drivers/md/kcopyd.c8
-rw-r--r--drivers/md/linear.c23
-rw-r--r--drivers/md/md.c58
-rw-r--r--drivers/md/multipath.c33
-rw-r--r--drivers/md/raid0.c34
-rw-r--r--drivers/md/raid1.c39
-rw-r--r--drivers/md/raid10.c34
-rw-r--r--drivers/md/raid5.c67
-rw-r--r--drivers/md/raid6algos.c4
-rw-r--r--drivers/md/raid6mmx.c2
-rw-r--r--drivers/md/raid6sse1.c2
-rw-r--r--drivers/md/raid6sse2.c4
-rw-r--r--drivers/md/raid6x86.h2
-rw-r--r--drivers/media/Kconfig1
-rw-r--r--drivers/media/common/ir-keymaps.c70
-rw-r--r--drivers/media/common/saa7146_core.c74
-rw-r--r--drivers/media/common/saa7146_hlp.c2
-rw-r--r--drivers/media/dvb/bt8xx/bt878.c2
-rw-r--r--drivers/media/dvb/cinergyT2/cinergyT2.c46
-rw-r--r--drivers/media/dvb/dvb-core/dvb_ca_en50221.c2
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.c3
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700_devices.c2
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-remote.c2
-rw-r--r--drivers/media/dvb/frontends/mt2131.c2
-rw-r--r--drivers/media/dvb/frontends/s5h1409.c96
-rw-r--r--drivers/media/dvb/frontends/stv0297.c22
-rw-r--r--drivers/media/dvb/frontends/tda10021.c6
-rw-r--r--drivers/media/dvb/frontends/ves1820.c2
-rw-r--r--drivers/media/dvb/ttpci/Kconfig2
-rw-r--r--drivers/media/dvb/ttpci/av7110_ir.c2
-rw-r--r--drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c2
-rw-r--r--drivers/media/dvb/ttusb-dec/ttusb_dec.c2
-rw-r--r--drivers/media/radio/miropcm20-radio.c1
-rw-r--r--drivers/media/radio/radio-gemtek.c1
-rw-r--r--drivers/media/video/Kconfig2
-rw-r--r--drivers/media/video/arv.c1
-rw-r--r--drivers/media/video/bt8xx/bttv-cards.c26
-rw-r--r--drivers/media/video/bt8xx/bttv-driver.c9
-rw-r--r--drivers/media/video/bt8xx/bttvp.h2
-rw-r--r--drivers/media/video/bw-qcam.c1
-rw-r--r--drivers/media/video/c-qcam.c1
-rw-r--r--drivers/media/video/cafe_ccic.c6
-rw-r--r--drivers/media/video/cpia.c5
-rw-r--r--drivers/media/video/cpia2/cpia2_v4l.c5
-rw-r--r--drivers/media/video/cx23885/Kconfig2
-rw-r--r--drivers/media/video/cx23885/cx23885-core.c6
-rw-r--r--drivers/media/video/cx88/Kconfig2
-rw-r--r--drivers/media/video/cx88/cx88-alsa.c88
-rw-r--r--drivers/media/video/cx88/cx88-blackbird.c57
-rw-r--r--drivers/media/video/cx88/cx88-dvb.c3
-rw-r--r--drivers/media/video/cx88/cx88-mpeg.c133
-rw-r--r--drivers/media/video/cx88/cx88-video.c1
-rw-r--r--drivers/media/video/cx88/cx88-vp3054-i2c.c16
-rw-r--r--drivers/media/video/cx88/cx88.h24
-rw-r--r--drivers/media/video/em28xx/Kconfig2
-rw-r--r--drivers/media/video/em28xx/em28xx-core.c3
-rw-r--r--drivers/media/video/em28xx/em28xx-i2c.c6
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c5
-rw-r--r--drivers/media/video/et61x251/et61x251_core.c1
-rw-r--r--drivers/media/video/ir-kbd-i2c.c1
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.c11
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.h1
-rw-r--r--drivers/media/video/ivtv/ivtv-fileops.c8
-rw-r--r--drivers/media/video/ivtv/ivtv-i2c.c2
-rw-r--r--drivers/media/video/ivtv/ivtv-i2c.h2
-rw-r--r--drivers/media/video/ivtv/ivtv-ioctl.c13
-rw-r--r--drivers/media/video/ivtv/ivtv-streams.c116
-rw-r--r--drivers/media/video/ivtv/ivtv-streams.h1
-rw-r--r--drivers/media/video/ivtv/ivtv-udma.c6
-rw-r--r--drivers/media/video/ivtv/ivtv-yuv.c160
-rw-r--r--drivers/media/video/ivtv/ivtv-yuv.h1
-rw-r--r--drivers/media/video/ivtv/ivtvfb.c92
-rw-r--r--drivers/media/video/meye.c3
-rw-r--r--drivers/media/video/meye.h2
-rw-r--r--drivers/media/video/ov511.c1
-rw-r--r--drivers/media/video/planb.c9
-rw-r--r--drivers/media/video/pms.c1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-ctrl.c2
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-encoder.c6
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h11
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw.c3
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-main.c5
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-sysfs.c8
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-v4l2.c3
-rw-r--r--drivers/media/video/pwc/pwc-if.c1
-rw-r--r--drivers/media/video/saa5246a.c4
-rw-r--r--drivers/media/video/saa5249.c4
-rw-r--r--drivers/media/video/saa7134/Kconfig2
-rw-r--r--drivers/media/video/saa7134/saa6752hs.c111
-rw-r--r--drivers/media/video/saa7134/saa7134-alsa.c16
-rw-r--r--drivers/media/video/saa7134/saa7134-cards.c4
-rw-r--r--drivers/media/video/saa7134/saa7134-core.c44
-rw-r--r--drivers/media/video/saa7134/saa7134-empress.c12
-rw-r--r--drivers/media/video/saa7134/saa7134-input.c29
-rw-r--r--drivers/media/video/saa7134/saa7134-tvaudio.c32
-rw-r--r--drivers/media/video/saa7134/saa7134-video.c28
-rw-r--r--drivers/media/video/saa7134/saa7134.h7
-rw-r--r--drivers/media/video/se401.c1
-rw-r--r--drivers/media/video/sn9c102/sn9c102_core.c1
-rw-r--r--drivers/media/video/stradis.c1
-rw-r--r--drivers/media/video/stv680.c1
-rw-r--r--drivers/media/video/tuner-core.c8
-rw-r--r--drivers/media/video/tvp5150.c16
-rw-r--r--drivers/media/video/usbvideo/konicawc.c4
-rw-r--r--drivers/media/video/usbvideo/quickcam_messenger.c4
-rw-r--r--drivers/media/video/usbvideo/usbvideo.c1
-rw-r--r--drivers/media/video/usbvideo/vicam.c3
-rw-r--r--drivers/media/video/usbvision/usbvision-video.c3
-rw-r--r--drivers/media/video/v4l1-compat.c2
-rw-r--r--drivers/media/video/v4l2-common.c4
-rw-r--r--drivers/media/video/videobuf-core.c2
-rw-r--r--drivers/media/video/videobuf-dma-sg.c13
-rw-r--r--drivers/media/video/videocodec.c4
-rw-r--r--drivers/media/video/videodev.c42
-rw-r--r--drivers/media/video/vivi.c1
-rw-r--r--drivers/media/video/w9966.c1
-rw-r--r--drivers/media/video/w9968cf.c1
-rw-r--r--drivers/media/video/zc0301/zc0301_core.c1
-rw-r--r--drivers/media/video/zoran_card.c10
-rw-r--r--drivers/media/video/zoran_driver.c6
-rw-r--r--drivers/message/fusion/mptscsih.c16
-rw-r--r--drivers/message/i2o/README4
-rw-r--r--drivers/message/i2o/exec-osm.c98
-rw-r--r--drivers/message/i2o/i2o_block.c29
-rw-r--r--drivers/message/i2o/i2o_config.c6
-rw-r--r--drivers/message/i2o/i2o_proc.c4
-rw-r--r--drivers/message/i2o/iop.c4
-rw-r--r--drivers/message/i2o/pci.c4
-rw-r--r--drivers/mfd/Kconfig4
-rw-r--r--drivers/misc/Kconfig33
-rw-r--r--drivers/misc/Makefile2
-rw-r--r--drivers/misc/atmel-ssc.c174
-rw-r--r--drivers/misc/fujitsu-laptop.c355
-rw-r--r--drivers/misc/ibmasm/remote.c10
-rw-r--r--drivers/misc/ioc4.c10
-rw-r--r--drivers/misc/phantom.c97
-rw-r--r--drivers/misc/sony-laptop.c214
-rw-r--r--drivers/misc/thinkpad_acpi.c223
-rw-r--r--drivers/misc/thinkpad_acpi.h37
-rw-r--r--drivers/mmc/card/queue.c13
-rw-r--r--drivers/mmc/core/core.c1
-rw-r--r--drivers/mmc/core/mmc.c3
-rw-r--r--drivers/mmc/core/mmc_ops.c23
-rw-r--r--drivers/mmc/core/sd_ops.c5
-rw-r--r--drivers/mmc/core/sdio_ops.c1
-rw-r--r--drivers/mmc/host/at91_mci.c12
-rw-r--r--drivers/mmc/host/au1xmmc.c17
-rw-r--r--drivers/mmc/host/imxmmc.c2
-rw-r--r--drivers/mmc/host/mmc_spi.c65
-rw-r--r--drivers/mmc/host/mmci.c6
-rw-r--r--drivers/mmc/host/mmci.h2
-rw-r--r--drivers/mmc/host/omap.c4
-rw-r--r--drivers/mmc/host/pxamci.c51
-rw-r--r--drivers/mmc/host/pxamci.h14
-rw-r--r--drivers/mmc/host/sdhci.c7
-rw-r--r--drivers/mmc/host/tifm_sd.c8
-rw-r--r--drivers/mmc/host/wbsd.c8
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0001.c146
-rw-r--r--drivers/mtd/maps/Kconfig10
-rw-r--r--drivers/mtd/nand/Kconfig2
-rw-r--r--drivers/mtd/nand/diskonchip.c4
-rw-r--r--drivers/mtd/nand/nand_base.c6
-rw-r--r--drivers/mtd/nand/nand_ecc.c2
-rw-r--r--drivers/mtd/nand/nandsim.c2
-rw-r--r--drivers/mtd/nand/s3c2410.c16
-rw-r--r--drivers/mtd/onenand/onenand_base.c2
-rw-r--r--drivers/mtd/onenand/onenand_sim.c50
-rw-r--r--drivers/mtd/ubi/eba.c3
-rw-r--r--drivers/mtd/ubi/wl.c2
-rw-r--r--drivers/net/3c59x.c10
-rw-r--r--drivers/net/8139too.c2
-rw-r--r--drivers/net/82596.c3
-rw-r--r--drivers/net/Kconfig324
-rw-r--r--drivers/net/Makefile7
-rw-r--r--drivers/net/amd8111e.c2
-rw-r--r--drivers/net/arcnet/Kconfig15
-rw-r--r--drivers/net/ariadne.c2
-rw-r--r--drivers/net/ariadne.h2
-rw-r--r--drivers/net/arm/ep93xx_eth.c2
-rw-r--r--drivers/net/au1000_eth.c30
-rw-r--r--drivers/net/ax88796.c2
-rw-r--r--drivers/net/bfin_mac.c2
-rw-r--r--drivers/net/bnx2.c36
-rw-r--r--drivers/net/bnx2_fw2.h7833
-rw-r--r--drivers/net/bonding/bond_3ad.c38
-rw-r--r--drivers/net/bonding/bond_3ad.h14
-rw-r--r--drivers/net/bonding/bond_alb.c110
-rw-r--r--drivers/net/bonding/bond_alb.h2
-rw-r--r--drivers/net/bonding/bond_main.c538
-rw-r--r--drivers/net/bonding/bond_sysfs.c157
-rw-r--r--drivers/net/bonding/bonding.h25
-rw-r--r--drivers/net/cassini.c2
-rw-r--r--drivers/net/chelsio/sge.c2
-rw-r--r--drivers/net/cpmac.c1196
-rw-r--r--drivers/net/cris/eth_v10.c442
-rw-r--r--drivers/net/cxgb3/adapter.h6
-rw-r--r--drivers/net/cxgb3/sge.c2
-rw-r--r--drivers/net/defxx.c2
-rw-r--r--drivers/net/dm9000.c6
-rw-r--r--drivers/net/e100.c2
-rw-r--r--drivers/net/e1000/e1000.h8
-rw-r--r--drivers/net/e1000/e1000_ethtool.c29
-rw-r--r--drivers/net/e1000/e1000_hw.c4
-rw-r--r--drivers/net/e1000/e1000_main.c22
-rw-r--r--drivers/net/e1000/e1000_param.c23
-rw-r--r--drivers/net/e1000e/82571.c2
-rw-r--r--drivers/net/e1000e/e1000.h5
-rw-r--r--drivers/net/e1000e/ethtool.c39
-rw-r--r--drivers/net/e1000e/hw.h2
-rw-r--r--drivers/net/e1000e/netdev.c425
-rw-r--r--drivers/net/e1000e/param.c35
-rw-r--r--drivers/net/eexpress.c2
-rw-r--r--drivers/net/ehea/ehea.h4
-rw-r--r--drivers/net/ehea/ehea_main.c100
-rw-r--r--drivers/net/eth16i.c1
-rw-r--r--drivers/net/fealnx.c1
-rw-r--r--drivers/net/fec.c24
-rw-r--r--drivers/net/fec_mpc52xx.c1112
-rw-r--r--drivers/net/fec_mpc52xx.h313
-rw-r--r--drivers/net/fec_mpc52xx_phy.c198
-rw-r--r--drivers/net/forcedeth.c211
-rw-r--r--drivers/net/fs_enet/Kconfig11
-rw-r--r--drivers/net/fs_enet/Makefile15
-rw-r--r--drivers/net/fs_enet/fs_enet-main.c28
-rw-r--r--drivers/net/fs_enet/fs_enet.h1
-rw-r--r--drivers/net/gianfar.c25
-rw-r--r--drivers/net/gianfar.h1
-rw-r--r--drivers/net/hamradio/6pack.c28
-rw-r--r--drivers/net/hamradio/Kconfig2
-rw-r--r--drivers/net/hamradio/baycom_epp.c8
-rw-r--r--drivers/net/hamradio/baycom_par.c4
-rw-r--r--drivers/net/hamradio/dmascc.c2
-rw-r--r--drivers/net/hp100.c4
-rw-r--r--drivers/net/ibm_emac/ibm_emac_mal.c5
-rw-r--r--drivers/net/ibm_emac/ibm_emac_mal.h5
-rw-r--r--drivers/net/ibm_newemac/mal.c34
-rw-r--r--drivers/net/ibm_newemac/mal.h5
-rw-r--r--drivers/net/ipg.c22
-rw-r--r--drivers/net/ipg.h20
-rw-r--r--drivers/net/irda/actisys-sir.c2
-rw-r--r--drivers/net/irda/actisys.c2
-rw-r--r--drivers/net/irda/au1k_ir.c11
-rw-r--r--drivers/net/irda/donauboe.c4
-rw-r--r--drivers/net/irda/girbil-sir.c2
-rw-r--r--drivers/net/irda/girbil.c2
-rw-r--r--drivers/net/irda/irport.h2
-rw-r--r--drivers/net/irda/irtty-sir.c9
-rw-r--r--drivers/net/irda/nsc-ircc.c2
-rw-r--r--drivers/net/irda/nsc-ircc.h2
-rw-r--r--drivers/net/irda/pxaficp_ir.c51
-rw-r--r--drivers/net/irda/tekram-sir.c2
-rw-r--r--drivers/net/irda/tekram.c2
-rw-r--r--drivers/net/irda/w83977af_ir.h2
-rw-r--r--drivers/net/ixgb/ixgb.h7
-rw-r--r--drivers/net/ixgb/ixgb_ethtool.c7
-rw-r--r--drivers/net/ixgb/ixgb_hw.c4
-rw-r--r--drivers/net/ixgb/ixgb_main.c15
-rw-r--r--drivers/net/ixgb/ixgb_param.c43
-rw-r--r--drivers/net/ixgbe/ixgbe.h2
-rw-r--r--drivers/net/ixgbe/ixgbe_82598.c3
-rw-r--r--drivers/net/ixgbe/ixgbe_main.c9
-rw-r--r--drivers/net/jazzsonic.c1
-rw-r--r--drivers/net/lguest_net.c555
-rw-r--r--drivers/net/lib82596.c8
-rw-r--r--drivers/net/loopback.c11
-rw-r--r--drivers/net/mac89x0.c2
-rw-r--r--drivers/net/meth.c1
-rw-r--r--drivers/net/meth.h3
-rw-r--r--drivers/net/mipsnet.c77
-rw-r--r--drivers/net/mipsnet.h83
-rw-r--r--drivers/net/mlx4/alloc.c7
-rw-r--r--drivers/net/mlx4/fw.c2
-rw-r--r--drivers/net/mlx4/icm.c16
-rw-r--r--drivers/net/mlx4/qp.c2
-rw-r--r--drivers/net/mv643xx_eth.c807
-rw-r--r--drivers/net/mv643xx_eth.h370
-rw-r--r--drivers/net/myri10ge/myri10ge.c109
-rw-r--r--drivers/net/myri10ge/myri10ge_mcp.h90
-rw-r--r--drivers/net/myri_sbus.c2
-rw-r--r--drivers/net/natsemi.c23
-rw-r--r--drivers/net/ne-h8300.c4
-rw-r--r--drivers/net/netx-eth.c6
-rw-r--r--drivers/net/netxen/netxen_nic_main.c14
-rw-r--r--drivers/net/ni5010.c2
-rw-r--r--drivers/net/niu.c53
-rw-r--r--drivers/net/pasemi_mac.c20
-rw-r--r--drivers/net/pcmcia/3c574_cs.c2
-rw-r--r--drivers/net/pcmcia/3c589_cs.c2
-rw-r--r--drivers/net/pcmcia/axnet_cs.c2
-rw-r--r--drivers/net/pcmcia/fmvj18x_cs.c2
-rw-r--r--drivers/net/pcmcia/pcnet_cs.c2
-rw-r--r--drivers/net/pcmcia/smc91c92_cs.c2
-rw-r--r--drivers/net/pcmcia/xirc2ps_cs.c2
-rw-r--r--drivers/net/pcnet32.c58
-rw-r--r--drivers/net/phy/marvell.c23
-rw-r--r--drivers/net/phy/mdio-bitbang.c2
-rw-r--r--drivers/net/phy/phy_device.c2
-rw-r--r--drivers/net/plip.c6
-rw-r--r--drivers/net/ppp_async.c44
-rw-r--r--drivers/net/ppp_generic.c126
-rw-r--r--drivers/net/ppp_mppe.c14
-rw-r--r--drivers/net/ppp_synctty.c37
-rw-r--r--drivers/net/pppoe.c2
-rw-r--r--drivers/net/pppol2tp.c27
-rw-r--r--drivers/net/qla3xxx.c42
-rw-r--r--drivers/net/qla3xxx.h1
-rw-r--r--drivers/net/r8169.c414
-rw-r--r--drivers/net/rrunner.c20
-rw-r--r--drivers/net/s2io-regs.h632
-rw-r--r--drivers/net/s2io.c126
-rw-r--r--drivers/net/s2io.h84
-rw-r--r--drivers/net/saa9730.c9
-rw-r--r--drivers/net/skge.c434
-rw-r--r--drivers/net/skge.h17
-rw-r--r--drivers/net/sky2.c164
-rw-r--r--drivers/net/sky2.h3
-rw-r--r--drivers/net/slip.c8
-rw-r--r--drivers/net/smc911x.c2
-rw-r--r--drivers/net/smc91x.c55
-rw-r--r--drivers/net/smc91x.h79
-rw-r--r--drivers/net/spider_net.c4
-rw-r--r--drivers/net/spider_net.h3
-rw-r--r--drivers/net/sungem.c11
-rw-r--r--drivers/net/sunhme.c13
-rw-r--r--drivers/net/tc35815.c5
-rw-r--r--drivers/net/tehuti.c11
-rw-r--r--drivers/net/tg3.c290
-rw-r--r--drivers/net/tg3.h55
-rw-r--r--drivers/net/tokenring/3c359.c2
-rw-r--r--drivers/net/tsi108_eth.c2
-rw-r--r--drivers/net/tulip/Kconfig35
-rw-r--r--drivers/net/tulip/de4x5.c4
-rw-r--r--drivers/net/tulip/uli526x.c2
-rw-r--r--drivers/net/tulip/winbond-840.c2
-rw-r--r--drivers/net/typhoon.c2
-rw-r--r--drivers/net/ucc_geth.c22
-rw-r--r--drivers/net/usb/Kconfig11
-rw-r--r--drivers/net/usb/dm9601.c4
-rw-r--r--drivers/net/usb/mcs7830.c16
-rw-r--r--drivers/net/usb/rndis_host.c18
-rw-r--r--drivers/net/usb/usbnet.c7
-rw-r--r--drivers/net/via-velocity.c7
-rw-r--r--drivers/net/virtio_net.c438
-rw-r--r--drivers/net/wan/lmc/lmc_main.c55
-rw-r--r--drivers/net/wan/sbni.c4
-rw-r--r--drivers/net/wan/sdla.c8
-rw-r--r--drivers/net/wan/x25_asy.c6
-rw-r--r--drivers/net/wireless/Kconfig8
-rw-r--r--drivers/net/wireless/b43/Kconfig10
-rw-r--r--drivers/net/wireless/b43/debugfs.c2
-rw-r--r--drivers/net/wireless/b43/main.c26
-rw-r--r--drivers/net/wireless/b43/pcmcia.c52
-rw-r--r--drivers/net/wireless/b43/rfkill.c115
-rw-r--r--drivers/net/wireless/b43/rfkill.h14
-rw-r--r--drivers/net/wireless/b43legacy/debugfs.c2
-rw-r--r--drivers/net/wireless/b43legacy/main.c25
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_leds.c2
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_xmit.h2
-rw-r--r--drivers/net/wireless/hostap/hostap_common.h3
-rw-r--r--drivers/net/wireless/hostap/hostap_ioctl.c2
-rw-r--r--drivers/net/wireless/hostap/hostap_pci.c6
-rw-r--r--drivers/net/wireless/ipw2100.c85
-rw-r--r--drivers/net/wireless/ipw2100.h6
-rw-r--r--drivers/net/wireless/ipw2200.c8
-rw-r--r--drivers/net/wireless/iwlwifi/Kconfig8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-rs.c59
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-rs.h29
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c127
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965-rs.c13
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c109
-rw-r--r--drivers/net/wireless/iwlwifi/iwl4965-base.c118
-rw-r--r--drivers/net/wireless/iwlwifi/iwlwifi.h7
-rw-r--r--drivers/net/wireless/libertas/Makefile2
-rw-r--r--drivers/net/wireless/libertas/cmd.c10
-rw-r--r--drivers/net/wireless/libertas/defs.h2
-rw-r--r--drivers/net/wireless/libertas/if_cs.c7
-rw-r--r--drivers/net/wireless/libertas/if_sdio.c1081
-rw-r--r--drivers/net/wireless/libertas/if_sdio.h45
-rw-r--r--drivers/net/wireless/netwave_cs.c8
-rw-r--r--drivers/net/wireless/p54common.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c4
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c4
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h8
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00lib.h2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c8
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c3
-rw-r--r--drivers/net/wireless/rtl8187_dev.c55
-rw-r--r--drivers/net/wireless/strip.c10
-rw-r--r--drivers/net/wireless/zd1201.c4
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.c7
-rw-r--r--drivers/net/xen-netfront.c37
-rw-r--r--drivers/of/platform.c21
-rw-r--r--drivers/oprofile/cpu_buffer.c7
-rw-r--r--drivers/oprofile/cpu_buffer.h1
-rw-r--r--drivers/oprofile/oprofile_stats.c4
-rw-r--r--drivers/parisc/ccio-dma.c1
-rw-r--r--drivers/parisc/lba_pci.c51
-rw-r--r--drivers/parisc/pdc_stable.c11
-rw-r--r--drivers/parisc/sba_iommu.c5
-rw-r--r--drivers/parisc/superio.c4
-rw-r--r--drivers/parport/daisy.c42
-rw-r--r--drivers/parport/ieee1284.c2
-rw-r--r--drivers/parport/parport_amiga.c9
-rw-r--r--drivers/parport/parport_atari.c9
-rw-r--r--drivers/parport/parport_ax88796.c10
-rw-r--r--drivers/parport/parport_gsc.c8
-rw-r--r--drivers/parport/parport_ip32.c6
-rw-r--r--drivers/parport/parport_mfc3.c2
-rw-r--r--drivers/parport/parport_pc.c9
-rw-r--r--drivers/parport/parport_sunbpp.c8
-rw-r--r--drivers/parport/probe.c3
-rw-r--r--drivers/parport/procfs.c38
-rw-r--r--drivers/parport/share.c12
-rw-r--r--drivers/pci/Kconfig11
-rw-r--r--drivers/pci/Makefile3
-rw-r--r--drivers/pci/dmar.c329
-rw-r--r--drivers/pci/hotplug/Kconfig6
-rw-r--r--drivers/pci/hotplug/cpqphp_ctrl.c16
-rw-r--r--drivers/pci/intel-iommu.c2270
-rw-r--r--drivers/pci/intel-iommu.h325
-rw-r--r--drivers/pci/iova.c394
-rw-r--r--drivers/pci/iova.h63
-rw-r--r--drivers/pci/msi.c18
-rw-r--r--drivers/pci/pci-driver.c5
-rw-r--r--drivers/pci/pci.h1
-rw-r--r--drivers/pci/probe.c14
-rw-r--r--drivers/pci/quirks.c53
-rw-r--r--drivers/pci/search.c43
-rw-r--r--drivers/pcmcia/Kconfig13
-rw-r--r--drivers/pcmcia/Makefile2
-rw-r--r--drivers/pcmcia/au1000_xxs1500.c5
-rw-r--r--drivers/pcmcia/cistpl.c48
-rw-r--r--drivers/pcmcia/ds.c4
-rw-r--r--drivers/pcmcia/electra_cf.c377
-rw-r--r--drivers/pcmcia/m32r_pcc.c2
-rw-r--r--drivers/pcmcia/m8xx_pcmcia.c2
-rw-r--r--drivers/pcmcia/pxa2xx_base.c2
-rw-r--r--drivers/pcmcia/pxa2xx_cm_x270.c175
-rw-r--r--drivers/pcmcia/pxa2xx_lubbock.c31
-rw-r--r--drivers/pcmcia/pxa2xx_mainstone.c18
-rw-r--r--drivers/pnp/Makefile4
-rw-r--r--drivers/pnp/card.c71
-rw-r--r--drivers/pnp/core.c28
-rw-r--r--drivers/pnp/driver.c5
-rw-r--r--drivers/pnp/interface.c5
-rw-r--r--drivers/pnp/isapnp/core.c4
-rw-r--r--drivers/pnp/isapnp/proc.c2
-rw-r--r--drivers/pnp/manager.c58
-rw-r--r--drivers/pnp/pnpacpi/core.c16
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c10
-rw-r--r--drivers/pnp/pnpbios/core.c28
-rw-r--r--drivers/pnp/pnpbios/proc.c5
-rw-r--r--drivers/pnp/quirks.c12
-rw-r--r--drivers/pnp/resource.c4
-rw-r--r--drivers/pnp/system.c29
-rw-r--r--drivers/power/apm_power.c141
-rw-r--r--drivers/power/ds2760_battery.c2
-rw-r--r--drivers/ps3/ps3av.c383
-rw-r--r--drivers/ps3/ps3av_cmd.c83
-rw-r--r--drivers/ps3/ps3stor_lib.c2
-rw-r--r--drivers/ps3/vuart.c2
-rw-r--r--drivers/rtc/Kconfig21
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/class.c1
-rw-r--r--drivers/rtc/hctosys.c4
-rw-r--r--drivers/rtc/interface.c122
-rw-r--r--drivers/rtc/rtc-cmos.c67
-rw-r--r--drivers/rtc/rtc-dev.c44
-rw-r--r--drivers/rtc/rtc-ds1307.c93
-rw-r--r--drivers/rtc/rtc-ds1374.c449
-rw-r--r--drivers/rtc/rtc-ds1553.c4
-rw-r--r--drivers/rtc/rtc-ds1742.c7
-rw-r--r--drivers/rtc/rtc-m48t59.c9
-rw-r--r--drivers/rtc/rtc-pcf8583.c3
-rw-r--r--drivers/rtc/rtc-pl031.c2
-rw-r--r--drivers/rtc/rtc-s3c.c2
-rw-r--r--drivers/rtc/rtc-sa1100.c2
-rw-r--r--drivers/rtc/rtc-sh.c6
-rw-r--r--drivers/rtc/rtc-stk17ta8.c2
-rw-r--r--drivers/rtc/rtc-sysfs.c29
-rw-r--r--drivers/s390/block/dasd_3990_erp.c4
-rw-r--r--drivers/s390/block/dcssblk.c9
-rw-r--r--drivers/s390/char/defkeymap.c2
-rw-r--r--drivers/s390/char/keyboard.c66
-rw-r--r--drivers/s390/char/keyboard.h4
-rw-r--r--drivers/s390/char/raw3270.c26
-rw-r--r--drivers/s390/char/sclp_cpi.c2
-rw-r--r--drivers/s390/char/tape_class.c19
-rw-r--r--drivers/s390/char/tape_class.h4
-rw-r--r--drivers/s390/char/vmlogrdr.c15
-rw-r--r--drivers/s390/cio/chp.c12
-rw-r--r--drivers/s390/cio/cmf.c6
-rw-r--r--drivers/s390/cio/css.c9
-rw-r--r--drivers/s390/cio/device.c2
-rw-r--r--drivers/s390/cio/idset.c2
-rw-r--r--drivers/s390/net/claw.c2
-rw-r--r--drivers/s390/net/ctcmain.c10
-rw-r--r--drivers/s390/net/qeth_main.c3
-rw-r--r--drivers/s390/net/smsgiucv.c4
-rw-r--r--drivers/s390/scsi/zfcp_aux.c13
-rw-r--r--drivers/s390/scsi/zfcp_def.h9
-rw-r--r--drivers/s390/scsi/zfcp_erp.c17
-rw-r--r--drivers/s390/scsi/zfcp_qdio.c6
-rw-r--r--drivers/sbus/char/vfc.h2
-rw-r--r--drivers/sbus/char/vfc_dev.c7
-rw-r--r--drivers/scsi/3w-9xxx.c5
-rw-r--r--drivers/scsi/3w-xxxx.c3
-rw-r--r--drivers/scsi/BusLogic.c1
-rw-r--r--drivers/scsi/FlashPoint.c83
-rw-r--r--drivers/scsi/Kconfig8
-rw-r--r--drivers/scsi/Makefile2
-rw-r--r--drivers/scsi/NCR5380.c6
-rw-r--r--drivers/scsi/NCR53C9x.c4
-rw-r--r--drivers/scsi/NCR53c406a.c9
-rw-r--r--drivers/scsi/a100u2w.c1
-rw-r--r--drivers/scsi/aacraid/aachba.c2
-rw-r--r--drivers/scsi/aacraid/aacraid.h2
-rw-r--r--drivers/scsi/aacraid/commctrl.c12
-rw-r--r--drivers/scsi/aacraid/comminit.c2
-rw-r--r--drivers/scsi/aacraid/dpcsup.c2
-rw-r--r--drivers/scsi/aacraid/linit.c1
-rw-r--r--drivers/scsi/aha152x.c8
-rw-r--r--drivers/scsi/aha1542.c34
-rw-r--r--drivers/scsi/aha1740.c1
-rw-r--r--drivers/scsi/aic7xxx/aic7770.c16
-rw-r--r--drivers/scsi/aic7xxx/aic79xx.h11
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_core.c7
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c5
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm_pci.c50
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_pci.c27
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx.h11
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.c5
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm_pci.c46
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_pci.c16
-rw-r--r--drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l3
-rw-r--r--drivers/scsi/aic7xxx/cam.h2
-rw-r--r--drivers/scsi/aic7xxx_old.c3
-rw-r--r--drivers/scsi/aic94xx/aic94xx_sds.c4
-rw-r--r--drivers/scsi/aic94xx/aic94xx_task.c6
-rw-r--r--drivers/scsi/arcmsr/arcmsr.h39
-rw-r--r--drivers/scsi/arcmsr/arcmsr_attr.c6
-rw-r--r--drivers/scsi/arcmsr/arcmsr_hba.c210
-rw-r--r--drivers/scsi/arm/scsi.h8
-rw-r--r--drivers/scsi/atari_NCR5380.c11
-rw-r--r--drivers/scsi/dc395x.c7
-rw-r--r--drivers/scsi/dpt_i2o.c1
-rw-r--r--drivers/scsi/eata.c3
-rw-r--r--drivers/scsi/eata_pio.c4
-rw-r--r--drivers/scsi/fcal.c317
-rw-r--r--drivers/scsi/fcal.h27
-rw-r--r--drivers/scsi/fd_mcs.c6
-rw-r--r--drivers/scsi/fdomain.c7
-rw-r--r--drivers/scsi/gdth.c12
-rw-r--r--drivers/scsi/hosts.c7
-rw-r--r--drivers/scsi/hptiop.c6
-rw-r--r--drivers/scsi/ibmmca.c3
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c20
-rw-r--r--drivers/scsi/ide-scsi.c46
-rw-r--r--drivers/scsi/imm.c8
-rw-r--r--drivers/scsi/in2000.c4
-rw-r--r--drivers/scsi/initio.c7
-rw-r--r--drivers/scsi/ipr.c30
-rw-r--r--drivers/scsi/ips.c20
-rw-r--r--drivers/scsi/iscsi_tcp.c22
-rw-r--r--drivers/scsi/libsas/sas_discover.c8
-rw-r--r--drivers/scsi/lpfc/lpfc_debugfs.c2
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c7
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c8
-rw-r--r--drivers/scsi/mac53c94.c1
-rw-r--r--drivers/scsi/mac_scsi.c9
-rw-r--r--drivers/scsi/megaraid.c9
-rw-r--r--drivers/scsi/megaraid/megaraid_mbox.c15
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.c1
-rw-r--r--drivers/scsi/mesh.c1
-rw-r--r--drivers/scsi/nsp32.c1
-rw-r--r--drivers/scsi/nsp32.h5
-rw-r--r--drivers/scsi/oktagon_esp.c6
-rw-r--r--drivers/scsi/osst.c40
-rw-r--r--drivers/scsi/pcmcia/nsp_cs.h3
-rw-r--r--drivers/scsi/pcmcia/sym53c500_cs.c7
-rw-r--r--drivers/scsi/pluto.c349
-rw-r--r--drivers/scsi/pluto.h47
-rw-r--r--drivers/scsi/ppa.c7
-rw-r--r--drivers/scsi/ps3rom.c6
-rw-r--r--drivers/scsi/qla1280.c74
-rw-r--r--drivers/scsi/qla1280.h4
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c9
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h1
-rw-r--r--drivers/scsi/qla2xxx/qla_devtbl.h7
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c8
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c52
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c30
-rw-r--r--drivers/scsi/qla2xxx/qla_version.h2
-rw-r--r--drivers/scsi/qla4xxx/ql4_fw.h2
-rw-r--r--drivers/scsi/qla4xxx/ql4_init.c2
-rw-r--r--drivers/scsi/qla4xxx/ql4_iocb.c2
-rw-r--r--drivers/scsi/qla4xxx/ql4_os.c3
-rw-r--r--drivers/scsi/qlogicfas.c1
-rw-r--r--drivers/scsi/qlogicfas408.c2
-rw-r--r--drivers/scsi/qlogicpti.c15
-rw-r--r--drivers/scsi/scsi_debug.c30
-rw-r--r--drivers/scsi/scsi_error.c1
-rw-r--r--drivers/scsi/scsi_lib.c381
-rw-r--r--drivers/scsi/scsi_scan.c3
-rw-r--r--drivers/scsi/scsi_sysfs.c57
-rw-r--r--drivers/scsi/scsi_tgt_lib.c4
-rw-r--r--drivers/scsi/sd.c24
-rw-r--r--drivers/scsi/seagate.c8
-rw-r--r--drivers/scsi/sg.c52
-rw-r--r--drivers/scsi/st.c16
-rw-r--r--drivers/scsi/stex.c1
-rw-r--r--drivers/scsi/sun3_NCR5380.c5
-rw-r--r--drivers/scsi/sun3x_esp.c4
-rw-r--r--drivers/scsi/sym53c416.c3
-rw-r--r--drivers/scsi/sym53c8xx_2/sym53c8xx.h1
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_fw.c18
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_fw.h2
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_fw2.h2
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.c582
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.h16
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.c159
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.h22
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_nvram.c2
-rw-r--r--drivers/scsi/tmscsim.c5
-rw-r--r--drivers/scsi/u14-34f.c3
-rw-r--r--drivers/scsi/ultrastor.c3
-rw-r--r--drivers/scsi/wd33c93.c6
-rw-r--r--drivers/scsi/wd33c93.h2
-rw-r--r--drivers/scsi/wd7000.c3
-rw-r--r--drivers/serial/8250_early.c4
-rw-r--r--drivers/serial/8250_pci.c125
-rw-r--r--drivers/serial/8250_pnp.c12
-rw-r--r--drivers/serial/Kconfig8
-rw-r--r--drivers/serial/amba-pl011.c26
-rw-r--r--drivers/serial/atmel_serial.c9
-rw-r--r--drivers/serial/crisv10.c1340
-rw-r--r--drivers/serial/crisv10.h146
-rw-r--r--drivers/serial/jsm/jsm_tty.c43
-rw-r--r--drivers/serial/m32r_sio.c2
-rw-r--r--drivers/serial/m32r_sio.h6
-rw-r--r--drivers/serial/mcf.c653
-rw-r--r--drivers/serial/pxa.c163
-rw-r--r--drivers/serial/s3c2410.c4
-rw-r--r--drivers/serial/serial_core.c71
-rw-r--r--drivers/serial/serial_cs.c3
-rw-r--r--drivers/serial/serial_txx9.c40
-rw-r--r--drivers/serial/sh-sci.h19
-rw-r--r--drivers/serial/uartlite.c10
-rw-r--r--drivers/sh/maple/maple.c3
-rw-r--r--drivers/sh/superhyway/superhyway.c7
-rw-r--r--drivers/spi/Kconfig13
-rw-r--r--drivers/spi/atmel_spi.c14
-rw-r--r--drivers/spi/mpc52xx_psc_spi.c4
-rw-r--r--drivers/spi/omap2_mcspi.c4
-rw-r--r--drivers/spi/omap_uwire.c9
-rw-r--r--drivers/spi/pxa2xx_spi.c14
-rw-r--r--drivers/spi/spi.c42
-rw-r--r--drivers/spi/spi_bfin5xx.c5
-rw-r--r--drivers/spi/spi_bitbang.c2
-rw-r--r--drivers/spi/spi_imx.c17
-rw-r--r--drivers/spi/spi_lm70llp.c2
-rw-r--r--drivers/spi/spi_mpc83xx.c7
-rw-r--r--drivers/spi/spi_s3c24xx.c9
-rw-r--r--drivers/spi/spi_txx9.c42
-rw-r--r--drivers/spi/spidev.c6
-rw-r--r--drivers/spi/tle62x0.c5
-rw-r--r--drivers/ssb/Kconfig4
-rw-r--r--drivers/ssb/driver_mipscore.c3
-rw-r--r--drivers/ssb/main.c6
-rw-r--r--drivers/ssb/pcmcia.c56
-rw-r--r--drivers/tc/.gitignore1
-rw-r--r--drivers/tc/Makefile15
-rw-r--r--drivers/tc/lk201-map.c_shipped265
-rw-r--r--drivers/tc/lk201-map.map356
-rw-r--r--drivers/tc/lk201-remap.c172
-rw-r--r--drivers/tc/lk201.c439
-rw-r--r--drivers/tc/lk201.h125
-rw-r--r--drivers/telephony/Kconfig2
-rw-r--r--drivers/telephony/phonedev.c5
-rw-r--r--drivers/usb/class/cdc-acm.c34
-rw-r--r--drivers/usb/core/buffer.c1
-rw-r--r--drivers/usb/core/devio.c2
-rw-r--r--drivers/usb/core/endpoint.c2
-rw-r--r--drivers/usb/core/hcd.c1
-rw-r--r--drivers/usb/core/hub.c9
-rw-r--r--drivers/usb/core/message.c22
-rw-r--r--drivers/usb/core/urb.c2
-rw-r--r--drivers/usb/core/usb.c3
-rw-r--r--drivers/usb/gadget/amd5536udc.c2
-rw-r--r--drivers/usb/gadget/file_storage.c2
-rw-r--r--drivers/usb/gadget/lh7a40x_udc.c2
-rw-r--r--drivers/usb/gadget/pxa2xx_udc.c68
-rw-r--r--drivers/usb/gadget/pxa2xx_udc.h1
-rw-r--r--drivers/usb/host/Kconfig2
-rw-r--r--drivers/usb/host/ehci-hub.c2
-rw-r--r--drivers/usb/host/ohci-hcd.c9
-rw-r--r--drivers/usb/host/ohci-s3c2410.c2
-rw-r--r--drivers/usb/host/sl811-hcd.c2
-rw-r--r--drivers/usb/host/uhci-q.c19
-rw-r--r--drivers/usb/image/Kconfig2
-rw-r--r--drivers/usb/image/microtek.c5
-rw-r--r--drivers/usb/misc/adutux.c4
-rw-r--r--drivers/usb/misc/cytherm.c6
-rw-r--r--drivers/usb/misc/emi26.c8
-rw-r--r--drivers/usb/misc/emi62.c8
-rw-r--r--drivers/usb/misc/ftdi-elan.c130
-rw-r--r--drivers/usb/misc/idmouse.c45
-rw-r--r--drivers/usb/misc/iowarrior.c19
-rw-r--r--drivers/usb/misc/legousbtower.c14
-rw-r--r--drivers/usb/misc/phidgetmotorcontrol.c2
-rw-r--r--drivers/usb/misc/rio500.c15
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb_con.c3
-rw-r--r--drivers/usb/misc/usblcd.c11
-rw-r--r--drivers/usb/misc/usbtest.c4
-rw-r--r--drivers/usb/misc/uss720.c4
-rw-r--r--drivers/usb/mon/mon_text.c4
-rw-r--r--drivers/usb/serial/ChangeLog.history2
-rw-r--r--drivers/usb/serial/Kconfig2
-rw-r--r--drivers/usb/serial/ark3116.c13
-rw-r--r--drivers/usb/serial/ch341.c8
-rw-r--r--drivers/usb/serial/console.c4
-rw-r--r--drivers/usb/serial/cp2101.c48
-rw-r--r--drivers/usb/serial/digi_acceleport.c16
-rw-r--r--drivers/usb/serial/empeg.c23
-rw-r--r--drivers/usb/serial/ftdi_sio.c39
-rw-r--r--drivers/usb/serial/ftdi_sio.h6
-rw-r--r--drivers/usb/serial/generic.c7
-rw-r--r--drivers/usb/serial/io_edgeport.c20
-rw-r--r--drivers/usb/serial/ipaq.c4
-rw-r--r--drivers/usb/serial/ipw.c18
-rw-r--r--drivers/usb/serial/ir-usb.c11
-rw-r--r--drivers/usb/serial/keyspan.c54
-rw-r--r--drivers/usb/serial/kobil_sct.c5
-rw-r--r--drivers/usb/serial/mos7720.c4
-rw-r--r--drivers/usb/serial/mos7840.c23
-rw-r--r--drivers/usb/serial/option.c5
-rw-r--r--drivers/usb/serial/oti6858.c2
-rw-r--r--drivers/usb/serial/pl2303.c12
-rw-r--r--drivers/usb/serial/pl2303.h1
-rw-r--r--drivers/usb/serial/sierra.c12
-rw-r--r--drivers/usb/serial/usb-serial.c6
-rw-r--r--drivers/usb/serial/whiteheat.c11
-rw-r--r--drivers/usb/storage/Kconfig1
-rw-r--r--drivers/usb/storage/alauda.c16
-rw-r--r--drivers/usb/storage/datafab.c10
-rw-r--r--drivers/usb/storage/isd200.c107
-rw-r--r--drivers/usb/storage/jumpshot.c10
-rw-r--r--drivers/usb/storage/libusual.c4
-rw-r--r--drivers/usb/storage/protocol.c22
-rw-r--r--drivers/usb/storage/protocol.h2
-rw-r--r--drivers/usb/storage/sddr09.c16
-rw-r--r--drivers/usb/storage/sddr55.c16
-rw-r--r--drivers/usb/storage/shuttle_usbat.c17
-rw-r--r--drivers/usb/storage/unusual_devs.h4
-rw-r--r--drivers/usb/storage/usb.c5
-rw-r--r--drivers/video/Kconfig70
-rw-r--r--drivers/video/Makefile2
-rw-r--r--drivers/video/amifb.c16
-rw-r--r--drivers/video/arcfb.c2
-rw-r--r--drivers/video/atafb.c2
-rw-r--r--drivers/video/aty/ati_ids.h1
-rw-r--r--drivers/video/aty/aty128fb.c2
-rw-r--r--drivers/video/aty/atyfb.h1
-rw-r--r--drivers/video/aty/atyfb_base.c8
-rw-r--r--drivers/video/aty/mach64_cursor.c1
-rw-r--r--drivers/video/aty/radeon_base.c5
-rw-r--r--drivers/video/aty/radeon_pm.c4
-rw-r--r--drivers/video/aty/radeonfb.h4
-rw-r--r--drivers/video/au1100fb.c2
-rw-r--r--drivers/video/backlight/cr_bllcd.c1
-rw-r--r--drivers/video/backlight/progear_bl.c1
-rw-r--r--drivers/video/bf54x-lq043fb.c786
-rw-r--r--drivers/video/cfbcopyarea.c103
-rw-r--r--drivers/video/cfbfillrect.c20
-rw-r--r--drivers/video/cfbimgblt.c17
-rw-r--r--drivers/video/cirrusfb.c2052
-rw-r--r--drivers/video/clps711xfb.c2
-rw-r--r--drivers/video/console/Kconfig2
-rw-r--r--drivers/video/console/dummycon.c4
-rw-r--r--drivers/video/console/fbcon.c5
-rw-r--r--drivers/video/console/font_10x18.c14
-rw-r--r--drivers/video/console/font_6x11.c13
-rw-r--r--drivers/video/console/font_7x14.c12
-rw-r--r--drivers/video/console/font_8x16.c14
-rw-r--r--drivers/video/console/font_8x8.c12
-rw-r--r--drivers/video/console/font_acorn_8x8.c14
-rw-r--r--drivers/video/console/font_mini_4x6.c12
-rw-r--r--drivers/video/console/font_pearl_8x8.c12
-rw-r--r--drivers/video/console/font_sun12x22.c14
-rw-r--r--drivers/video/console/font_sun8x16.c14
-rw-r--r--drivers/video/console/newport_con.c20
-rw-r--r--drivers/video/console/softcursor.c1
-rw-r--r--drivers/video/console/vgacon.c58
-rw-r--r--drivers/video/cyber2000fb.c239
-rw-r--r--drivers/video/epson1355fb.c2
-rw-r--r--drivers/video/fb_defio.c1
-rw-r--r--drivers/video/fb_draw.h94
-rw-r--r--drivers/video/fb_sys_fops.c2
-rw-r--r--drivers/video/fbcmap.c3
-rw-r--r--drivers/video/fbmem.c5
-rw-r--r--drivers/video/fbmon.c4
-rw-r--r--drivers/video/gbefb.c4
-rw-r--r--drivers/video/geode/lxfb.h2
-rw-r--r--drivers/video/geode/lxfb_core.c7
-rw-r--r--drivers/video/geode/video_gx.c2
-rw-r--r--drivers/video/gxt4500.c2
-rw-r--r--drivers/video/hecubafb.c2
-rw-r--r--drivers/video/imsttfb.c2
-rw-r--r--drivers/video/imxfb.c4
-rw-r--r--drivers/video/intelfb/intelfb.h17
-rw-r--r--drivers/video/intelfb/intelfb_i2c.c60
-rw-r--r--drivers/video/intelfb/intelfbdrv.c185
-rw-r--r--drivers/video/intelfb/intelfbhw.c320
-rw-r--r--drivers/video/intelfb/intelfbhw.h52
-rw-r--r--drivers/video/kyro/fbdev.c2
-rw-r--r--drivers/video/logo/logo.c17
-rw-r--r--drivers/video/matrox/matroxfb_base.c2
-rw-r--r--drivers/video/matrox/matroxfb_crtc2.c2
-rw-r--r--drivers/video/matrox/matroxfb_g450.c1
-rw-r--r--drivers/video/matrox/matroxfb_maven.c1
-rw-r--r--drivers/video/mbx/mbxfb.c344
-rw-r--r--drivers/video/mbx/reg_bits.h87
-rw-r--r--drivers/video/mbx/regs.h2
-rw-r--r--drivers/video/modedb.c60
-rw-r--r--drivers/video/neofb.c1
-rw-r--r--drivers/video/nvidia/nv_i2c.c10
-rw-r--r--drivers/video/nvidia/nv_type.h1
-rw-r--r--drivers/video/nvidia/nvidia.c6
-rw-r--r--drivers/video/omap/Kconfig4
-rw-r--r--drivers/video/omap/blizzard.c2
-rw-r--r--drivers/video/omap/dispc.c6
-rw-r--r--drivers/video/omap/hwa742.c2
-rw-r--r--drivers/video/omap/lcd_h3.c6
-rw-r--r--drivers/video/omap/lcd_inn1610.c6
-rw-r--r--drivers/video/omap/rfbi.c4
-rw-r--r--drivers/video/pm2fb.c883
-rw-r--r--drivers/video/pm3fb.c557
-rw-r--r--drivers/video/pmag-ba-fb.c34
-rw-r--r--drivers/video/pmagb-b-fb.c34
-rw-r--r--drivers/video/pnx4008/pnxrgbfb.c1
-rw-r--r--drivers/video/pnx4008/sdum.h3
-rw-r--r--drivers/video/ps3fb.c513
-rw-r--r--drivers/video/pvr2fb.c2
-rw-r--r--drivers/video/pxafb.c101
-rw-r--r--drivers/video/pxafb.h3
-rw-r--r--drivers/video/s1d13xxxfb.c5
-rw-r--r--drivers/video/s3c2410fb.c787
-rw-r--r--drivers/video/s3c2410fb.h13
-rw-r--r--drivers/video/s3fb.c24
-rw-r--r--drivers/video/sa1100fb.c1
-rw-r--r--drivers/video/savage/savagefb_driver.c1
-rw-r--r--drivers/video/sis/sis_main.c5
-rw-r--r--drivers/video/skeletonfb.c2
-rw-r--r--drivers/video/sm501fb.c49
-rw-r--r--drivers/video/sstfb.c2
-rw-r--r--drivers/video/svgalib.c47
-rw-r--r--drivers/video/tdfxfb.c1255
-rw-r--r--drivers/video/tgafb.c20
-rw-r--r--drivers/video/tridentfb.c1075
-rw-r--r--drivers/video/uvesafb.c2068
-rw-r--r--drivers/video/vermilion/vermilion.c5
-rw-r--r--drivers/video/vermilion/vermilion.h2
-rw-r--r--drivers/video/vfb.c79
-rw-r--r--drivers/video/vga16fb.c2
-rw-r--r--drivers/virtio/Kconfig8
-rw-r--r--drivers/virtio/Makefile2
-rw-r--r--drivers/virtio/config.c13
-rw-r--r--drivers/virtio/virtio.c189
-rw-r--r--drivers/virtio/virtio_ring.c319
-rw-r--r--drivers/w1/Kconfig3
-rw-r--r--drivers/w1/masters/ds1wm.c2
-rw-r--r--drivers/w1/masters/ds2490.c2
-rw-r--r--drivers/w1/masters/matrox_w1.c1
-rw-r--r--drivers/watchdog/Kconfig (renamed from drivers/char/watchdog/Kconfig)17
-rw-r--r--drivers/watchdog/Makefile (renamed from drivers/char/watchdog/Makefile)1
-rw-r--r--drivers/watchdog/acquirewdt.c (renamed from drivers/char/watchdog/acquirewdt.c)0
-rw-r--r--drivers/watchdog/advantechwdt.c (renamed from drivers/char/watchdog/advantechwdt.c)0
-rw-r--r--drivers/watchdog/alim1535_wdt.c (renamed from drivers/char/watchdog/alim1535_wdt.c)4
-rw-r--r--drivers/watchdog/alim7101_wdt.c (renamed from drivers/char/watchdog/alim7101_wdt.c)0
-rw-r--r--drivers/watchdog/ar7_wdt.c349
-rw-r--r--drivers/watchdog/at32ap700x_wdt.c (renamed from drivers/char/watchdog/at32ap700x_wdt.c)0
-rw-r--r--drivers/watchdog/at91rm9200_wdt.c (renamed from drivers/char/watchdog/at91rm9200_wdt.c)2
-rw-r--r--drivers/watchdog/bfin_wdt.c (renamed from drivers/char/watchdog/bfin_wdt.c)0
-rw-r--r--drivers/watchdog/booke_wdt.c (renamed from drivers/char/watchdog/booke_wdt.c)0
-rw-r--r--drivers/watchdog/cpu5wdt.c (renamed from drivers/char/watchdog/cpu5wdt.c)0
-rw-r--r--drivers/watchdog/davinci_wdt.c (renamed from drivers/char/watchdog/davinci_wdt.c)6
-rw-r--r--drivers/watchdog/ep93xx_wdt.c (renamed from drivers/char/watchdog/ep93xx_wdt.c)0
-rw-r--r--drivers/watchdog/eurotechwdt.c (renamed from drivers/char/watchdog/eurotechwdt.c)0
-rw-r--r--drivers/watchdog/i6300esb.c (renamed from drivers/char/watchdog/i6300esb.c)10
-rw-r--r--drivers/watchdog/iTCO_vendor_support.c (renamed from drivers/char/watchdog/iTCO_vendor_support.c)2
-rw-r--r--drivers/watchdog/iTCO_wdt.c (renamed from drivers/char/watchdog/iTCO_wdt.c)114
-rw-r--r--drivers/watchdog/ib700wdt.c (renamed from drivers/char/watchdog/ib700wdt.c)4
-rw-r--r--drivers/watchdog/ibmasr.c (renamed from drivers/char/watchdog/ibmasr.c)0
-rw-r--r--drivers/watchdog/indydog.c (renamed from drivers/char/watchdog/indydog.c)0
-rw-r--r--drivers/watchdog/iop_wdt.c (renamed from drivers/char/watchdog/iop_wdt.c)0
-rw-r--r--drivers/watchdog/ixp2000_wdt.c (renamed from drivers/char/watchdog/ixp2000_wdt.c)0
-rw-r--r--drivers/watchdog/ixp4xx_wdt.c (renamed from drivers/char/watchdog/ixp4xx_wdt.c)0
-rw-r--r--drivers/watchdog/ks8695_wdt.c (renamed from drivers/char/watchdog/ks8695_wdt.c)2
-rw-r--r--drivers/watchdog/machzwd.c (renamed from drivers/char/watchdog/machzwd.c)7
-rw-r--r--drivers/watchdog/mixcomwd.c (renamed from drivers/char/watchdog/mixcomwd.c)0
-rw-r--r--drivers/watchdog/mpc5200_wdt.c (renamed from drivers/char/watchdog/mpc5200_wdt.c)3
-rw-r--r--drivers/watchdog/mpc83xx_wdt.c (renamed from drivers/char/watchdog/mpc83xx_wdt.c)5
-rw-r--r--drivers/watchdog/mpc8xx_wdt.c (renamed from drivers/char/watchdog/mpc8xx_wdt.c)0
-rw-r--r--drivers/watchdog/mpcore_wdt.c (renamed from drivers/char/watchdog/mpcore_wdt.c)0
-rw-r--r--drivers/watchdog/mtx-1_wdt.c (renamed from drivers/char/watchdog/mtx-1_wdt.c)0
-rw-r--r--drivers/watchdog/mv64x60_wdt.c (renamed from drivers/char/watchdog/mv64x60_wdt.c)0
-rw-r--r--drivers/watchdog/omap_wdt.c (renamed from drivers/char/watchdog/omap_wdt.c)2
-rw-r--r--drivers/watchdog/omap_wdt.h (renamed from drivers/char/watchdog/omap_wdt.h)0
-rw-r--r--drivers/watchdog/pc87413_wdt.c (renamed from drivers/char/watchdog/pc87413_wdt.c)4
-rw-r--r--drivers/watchdog/pcwd.c (renamed from drivers/char/watchdog/pcwd.c)0
-rw-r--r--drivers/watchdog/pcwd_pci.c (renamed from drivers/char/watchdog/pcwd_pci.c)0
-rw-r--r--drivers/watchdog/pcwd_usb.c (renamed from drivers/char/watchdog/pcwd_usb.c)0
-rw-r--r--drivers/watchdog/pnx4008_wdt.c (renamed from drivers/char/watchdog/pnx4008_wdt.c)6
-rw-r--r--drivers/watchdog/rm9k_wdt.c (renamed from drivers/char/watchdog/rm9k_wdt.c)0
-rw-r--r--drivers/watchdog/s3c2410_wdt.c (renamed from drivers/char/watchdog/s3c2410_wdt.c)0
-rw-r--r--drivers/watchdog/sa1100_wdt.c (renamed from drivers/char/watchdog/sa1100_wdt.c)2
-rw-r--r--drivers/watchdog/sbc60xxwdt.c (renamed from drivers/char/watchdog/sbc60xxwdt.c)0
-rw-r--r--drivers/watchdog/sbc8360.c (renamed from drivers/char/watchdog/sbc8360.c)3
-rw-r--r--drivers/watchdog/sbc_epx_c3.c (renamed from drivers/char/watchdog/sbc_epx_c3.c)0
-rw-r--r--drivers/watchdog/sc1200wdt.c (renamed from drivers/char/watchdog/sc1200wdt.c)3
-rw-r--r--drivers/watchdog/sc520_wdt.c (renamed from drivers/char/watchdog/sc520_wdt.c)4
-rw-r--r--drivers/watchdog/scx200_wdt.c (renamed from drivers/char/watchdog/scx200_wdt.c)0
-rw-r--r--drivers/watchdog/shwdt.c (renamed from drivers/char/watchdog/shwdt.c)0
-rw-r--r--drivers/watchdog/smsc37b787_wdt.c (renamed from drivers/char/watchdog/smsc37b787_wdt.c)4
-rw-r--r--drivers/watchdog/softdog.c (renamed from drivers/char/watchdog/softdog.c)0
-rw-r--r--drivers/watchdog/w83627hf_wdt.c (renamed from drivers/char/watchdog/w83627hf_wdt.c)4
-rw-r--r--drivers/watchdog/w83697hf_wdt.c (renamed from drivers/char/watchdog/w83697hf_wdt.c)6
-rw-r--r--drivers/watchdog/w83877f_wdt.c (renamed from drivers/char/watchdog/w83877f_wdt.c)4
-rw-r--r--drivers/watchdog/w83977f_wdt.c (renamed from drivers/char/watchdog/w83977f_wdt.c)4
-rw-r--r--drivers/watchdog/wafer5823wdt.c (renamed from drivers/char/watchdog/wafer5823wdt.c)4
-rw-r--r--drivers/watchdog/wd501p.h (renamed from drivers/char/watchdog/wd501p.h)0
-rw-r--r--drivers/watchdog/wdrtas.c (renamed from drivers/char/watchdog/wdrtas.c)0
-rw-r--r--drivers/watchdog/wdt.c (renamed from drivers/char/watchdog/wdt.c)3
-rw-r--r--drivers/watchdog/wdt285.c (renamed from drivers/char/watchdog/wdt285.c)0
-rw-r--r--drivers/watchdog/wdt977.c (renamed from drivers/char/watchdog/wdt977.c)4
-rw-r--r--drivers/watchdog/wdt_pci.c (renamed from drivers/char/watchdog/wdt_pci.c)6
-rw-r--r--drivers/xen/xenbus/xenbus_probe.c5
-rw-r--r--drivers/zorro/zorro.ids2
-rw-r--r--fs/9p/fid.c157
-rw-r--r--fs/9p/v9fs.c194
-rw-r--r--fs/9p/v9fs.h38
-rw-r--r--fs/9p/vfs_file.c8
-rw-r--r--fs/9p/vfs_inode.c54
-rw-r--r--fs/9p/vfs_super.c22
-rw-r--r--fs/Kconfig71
-rw-r--r--fs/Makefile2
-rw-r--r--fs/adfs/inode.c14
-rw-r--r--fs/adfs/super.c2
-rw-r--r--fs/affs/bitmap.c2
-rw-r--r--fs/affs/file.c101
-rw-r--r--fs/affs/super.c2
-rw-r--r--fs/afs/callback.c2
-rw-r--r--fs/afs/cell.c19
-rw-r--r--fs/afs/cmservice.c2
-rw-r--r--fs/afs/flock.c3
-rw-r--r--fs/afs/internal.h1
-rw-r--r--fs/afs/mntpt.c2
-rw-r--r--fs/afs/proc.c2
-rw-r--r--fs/afs/rxrpc.c3
-rw-r--r--fs/afs/server.c2
-rw-r--r--fs/afs/super.c6
-rw-r--r--fs/afs/vlocation.c8
-rw-r--r--fs/afs/write.c8
-rw-r--r--fs/aio.c22
-rw-r--r--fs/anon_inodes.c25
-rw-r--r--fs/attr.c35
-rw-r--r--fs/autofs/inode.c2
-rw-r--r--fs/autofs/root.c6
-rw-r--r--fs/autofs/waitq.c2
-rw-r--r--fs/autofs4/autofs_i.h2
-rw-r--r--fs/autofs4/inode.c8
-rw-r--r--fs/autofs4/root.c4
-rw-r--r--fs/autofs4/waitq.c2
-rw-r--r--fs/befs/linuxvfs.c2
-rw-r--r--fs/bfs/bfs.h4
-rw-r--r--fs/bfs/dir.c146
-rw-r--r--fs/bfs/file.c74
-rw-r--r--fs/bfs/inode.c129
-rw-r--r--fs/binfmt_aout.c16
-rw-r--r--fs/binfmt_elf.c136
-rw-r--r--fs/binfmt_elf_fdpic.c31
-rw-r--r--fs/binfmt_em86.c2
-rw-r--r--fs/binfmt_flat.c18
-rw-r--r--fs/binfmt_misc.c2
-rw-r--r--fs/binfmt_script.c2
-rw-r--r--fs/binfmt_som.c2
-rw-r--r--fs/bio.c23
-rw-r--r--fs/block_dev.c26
-rw-r--r--fs/buffer.c725
-rw-r--r--fs/char_dev.c1
-rw-r--r--fs/cifs/CHANGES30
-rw-r--r--fs/cifs/Makefile7
-rw-r--r--fs/cifs/asn1.c45
-rw-r--r--fs/cifs/cifs_debug.c28
-rw-r--r--fs/cifs/cifs_spnego.c128
-rw-r--r--fs/cifs/cifs_spnego.h46
-rw-r--r--fs/cifs/cifsacl.c531
-rw-r--r--fs/cifs/cifsacl.h61
-rw-r--r--fs/cifs/cifsencrypt.c14
-rw-r--r--fs/cifs/cifsfs.c57
-rw-r--r--fs/cifs/cifsfs.h11
-rw-r--r--fs/cifs/cifsglob.h31
-rw-r--r--fs/cifs/cifspdu.h60
-rw-r--r--fs/cifs/cifsproto.h17
-rw-r--r--fs/cifs/cifssmb.c216
-rw-r--r--fs/cifs/connect.c270
-rw-r--r--fs/cifs/dir.c11
-rw-r--r--fs/cifs/export.c3
-rw-r--r--fs/cifs/file.c117
-rw-r--r--fs/cifs/inode.c72
-rw-r--r--fs/cifs/link.c2
-rw-r--r--fs/cifs/md5.c8
-rw-r--r--fs/cifs/misc.c11
-rw-r--r--fs/cifs/netmisc.c87
-rw-r--r--fs/cifs/readdir.c18
-rw-r--r--fs/cifs/sess.c103
-rw-r--r--fs/cifs/smbencrypt.c18
-rw-r--r--fs/cifs/smberr.h5
-rw-r--r--fs/cifs/transport.c34
-rw-r--r--fs/cifs/xattr.c28
-rw-r--r--fs/coda/inode.c2
-rw-r--r--fs/coda/upcall.c2
-rw-r--r--fs/compat_ioctl.c5
-rw-r--r--fs/configfs/configfs_internal.h2
-rw-r--r--fs/configfs/dir.c5
-rw-r--r--fs/configfs/inode.c12
-rw-r--r--fs/configfs/mount.c9
-rw-r--r--fs/cramfs/inode.c20
-rw-r--r--fs/dcache.c50
-rw-r--r--fs/debugfs/file.c41
-rw-r--r--fs/debugfs/inode.c2
-rw-r--r--fs/direct-io.c4
-rw-r--r--fs/dlm/Kconfig8
-rw-r--r--fs/dlm/lowcomms.c6
-rw-r--r--fs/dlm/user.c2
-rw-r--r--fs/dquot.c144
-rw-r--r--fs/ecryptfs/Makefile2
-rw-r--r--fs/ecryptfs/crypto.c1048
-rw-r--r--fs/ecryptfs/debug.c2
-rw-r--r--fs/ecryptfs/ecryptfs_kernel.h183
-rw-r--r--fs/ecryptfs/file.c97
-rw-r--r--fs/ecryptfs/inode.c239
-rw-r--r--fs/ecryptfs/keystore.c1079
-rw-r--r--fs/ecryptfs/main.c265
-rw-r--r--fs/ecryptfs/messaging.c5
-rw-r--r--fs/ecryptfs/mmap.c704
-rw-r--r--fs/ecryptfs/read_write.c358
-rw-r--r--fs/ecryptfs/super.c39
-rw-r--r--fs/efs/namei.c36
-rw-r--r--fs/efs/super.c7
-rw-r--r--fs/eventpoll.c7
-rw-r--r--fs/exec.c187
-rw-r--r--fs/exportfs/expfs.c360
-rw-r--r--fs/ext2/balloc.c1317
-rw-r--r--fs/ext2/dir.c95
-rw-r--r--fs/ext2/ext2.h39
-rw-r--r--fs/ext2/file.c7
-rw-r--r--fs/ext2/ialloc.c31
-rw-r--r--fs/ext2/inode.c566
-rw-r--r--fs/ext2/ioctl.c50
-rw-r--r--fs/ext2/super.c158
-rw-r--r--fs/ext2/xattr.c3
-rw-r--r--fs/ext3/balloc.c12
-rw-r--r--fs/ext3/bitmap.c2
-rw-r--r--fs/ext3/dir.c21
-rw-r--r--fs/ext3/fsync.c2
-rw-r--r--fs/ext3/ialloc.c17
-rw-r--r--fs/ext3/inode.c167
-rw-r--r--fs/ext3/ioctl.c5
-rw-r--r--fs/ext3/namei.c111
-rw-r--r--fs/ext3/resize.c61
-rw-r--r--fs/ext3/super.c140
-rw-r--r--fs/ext3/xattr.c3
-rw-r--r--fs/ext4/balloc.c135
-rw-r--r--fs/ext4/bitmap.c2
-rw-r--r--fs/ext4/dir.c11
-rw-r--r--fs/ext4/extents.c14
-rw-r--r--fs/ext4/fsync.c2
-rw-r--r--fs/ext4/group.h27
-rw-r--r--fs/ext4/ialloc.c168
-rw-r--r--fs/ext4/inode.c192
-rw-r--r--fs/ext4/ioctl.c5
-rw-r--r--fs/ext4/namei.c20
-rw-r--r--fs/ext4/resize.c63
-rw-r--r--fs/ext4/super.c241
-rw-r--r--fs/ext4/xattr.c7
-rw-r--r--fs/fat/cache.c2
-rw-r--r--fs/fat/inode.c55
-rw-r--r--fs/fcntl.c17
-rw-r--r--fs/file_table.c70
-rw-r--r--fs/fs-writeback.c166
-rw-r--r--fs/fuse/dev.c68
-rw-r--r--fs/fuse/dir.c347
-rw-r--r--fs/fuse/file.c244
-rw-r--r--fs/fuse/fuse_i.h62
-rw-r--r--fs/fuse/inode.c89
-rw-r--r--fs/gfs2/main.c4
-rw-r--r--fs/gfs2/ops_address.c211
-rw-r--r--fs/gfs2/ops_export.c83
-rw-r--r--fs/gfs2/ops_file.c6
-rw-r--r--fs/gfs2/ops_fstype.h2
-rw-r--r--fs/hfs/extent.c19
-rw-r--r--fs/hfs/inode.c18
-rw-r--r--fs/hfs/super.c2
-rw-r--r--fs/hfsplus/extents.c21
-rw-r--r--fs/hfsplus/inode.c18
-rw-r--r--fs/hfsplus/super.c2
-rw-r--r--fs/hostfs/hostfs.h9
-rw-r--r--fs/hostfs/hostfs_kern.c301
-rw-r--r--fs/hostfs/hostfs_user.c141
-rw-r--r--fs/hpfs/file.c18
-rw-r--r--fs/hpfs/super.c2
-rw-r--r--fs/hugetlbfs/inode.c195
-rw-r--r--fs/inode.c46
-rw-r--r--fs/inotify.c43
-rw-r--r--fs/inotify_user.c4
-rw-r--r--fs/ioprio.c13
-rw-r--r--fs/isofs/compress.c25
-rw-r--r--fs/isofs/export.c69
-rw-r--r--fs/isofs/inode.c4
-rw-r--r--fs/isofs/isofs.h2
-rw-r--r--fs/isofs/namei.c3
-rw-r--r--fs/jbd/commit.c14
-rw-r--r--fs/jbd/journal.c177
-rw-r--r--fs/jbd/recovery.c6
-rw-r--r--fs/jbd/revoke.c6
-rw-r--r--fs/jbd/transaction.c25
-rw-r--r--fs/jbd2/commit.c16
-rw-r--r--fs/jbd2/journal.c128
-rw-r--r--fs/jbd2/recovery.c2
-rw-r--r--fs/jbd2/revoke.c4
-rw-r--r--fs/jbd2/transaction.c19
-rw-r--r--fs/jffs2/acl.c103
-rw-r--r--fs/jffs2/acl.h12
-rw-r--r--fs/jffs2/debug.h8
-rw-r--r--fs/jffs2/dir.c35
-rw-r--r--fs/jffs2/file.c114
-rw-r--r--fs/jffs2/fs.c21
-rw-r--r--fs/jffs2/os-linux.h4
-rw-r--r--fs/jffs2/super.c2
-rw-r--r--fs/jffs2/write.c8
-rw-r--r--fs/jfs/inode.c16
-rw-r--r--fs/jfs/ioctl.c3
-rw-r--r--fs/jfs/jfs_dtree.c2
-rw-r--r--fs/jfs/jfs_inode.h7
-rw-r--r--fs/jfs/jfs_metapage.c2
-rw-r--r--fs/jfs/jfs_txnmgr.c9
-rw-r--r--fs/jfs/namei.c35
-rw-r--r--fs/jfs/super.c9
-rw-r--r--fs/libfs.c137
-rw-r--r--fs/locks.c205
-rw-r--r--fs/mbcache.c2
-rw-r--r--fs/minix/bitmap.c2
-rw-r--r--fs/minix/dir.c49
-rw-r--r--fs/minix/inode.c25
-rw-r--r--fs/minix/itree_v1.c9
-rw-r--r--fs/minix/itree_v2.c9
-rw-r--r--fs/minix/minix.h3
-rw-r--r--fs/mpage.c10
-rw-r--r--fs/namei.c169
-rw-r--r--fs/namespace.c26
-rw-r--r--fs/ncpfs/inode.c2
-rw-r--r--fs/nfs/client.c6
-rw-r--r--fs/nfs/delegation.c3
-rw-r--r--fs/nfs/dir.c14
-rw-r--r--fs/nfs/direct.c6
-rw-r--r--fs/nfs/file.c85
-rw-r--r--fs/nfs/inode.c31
-rw-r--r--fs/nfs/nfs4_fs.h4
-rw-r--r--fs/nfs/nfs4proc.c19
-rw-r--r--fs/nfs/nfs4state.c14
-rw-r--r--fs/nfs/nfsroot.c2
-rw-r--r--fs/nfs/proc.c1
-rw-r--r--fs/nfs/unlink.c117
-rw-r--r--fs/nfs/write.c28
-rw-r--r--fs/nfsd/export.c25
-rw-r--r--fs/nfsd/nfs2acl.c2
-rw-r--r--fs/nfsd/nfs3acl.c2
-rw-r--r--fs/nfsd/nfs4recover.c10
-rw-r--r--fs/nfsd/nfs4state.c2
-rw-r--r--fs/nfsd/nfsfh.c110
-rw-r--r--fs/nfsd/vfs.c57
-rw-r--r--fs/nls/Kconfig50
-rw-r--r--fs/nls/nls_ascii.c12
-rw-r--r--fs/nls/nls_base.c20
-rw-r--r--fs/nls/nls_cp1250.c20
-rw-r--r--fs/nls/nls_cp1251.c18
-rw-r--r--fs/nls/nls_cp1255.c22
-rw-r--r--fs/nls/nls_cp437.c24
-rw-r--r--fs/nls/nls_cp737.c20
-rw-r--r--fs/nls/nls_cp775.c20
-rw-r--r--fs/nls/nls_cp850.c18
-rw-r--r--fs/nls/nls_cp852.c18
-rw-r--r--fs/nls/nls_cp855.c18
-rw-r--r--fs/nls/nls_cp857.c16
-rw-r--r--fs/nls/nls_cp860.c22
-rw-r--r--fs/nls/nls_cp861.c24
-rw-r--r--fs/nls/nls_cp862.c26
-rw-r--r--fs/nls/nls_cp863.c24
-rw-r--r--fs/nls/nls_cp864.c22
-rw-r--r--fs/nls/nls_cp865.c24
-rw-r--r--fs/nls/nls_cp866.c20
-rw-r--r--fs/nls/nls_cp869.c18
-rw-r--r--fs/nls/nls_cp874.c16
-rw-r--r--fs/nls/nls_cp932.c300
-rw-r--r--fs/nls/nls_cp936.c470
-rw-r--r--fs/nls/nls_cp949.c552
-rw-r--r--fs/nls/nls_cp950.c384
-rw-r--r--fs/nls/nls_euc-jp.c4
-rw-r--r--fs/nls/nls_iso8859-1.c12
-rw-r--r--fs/nls/nls_iso8859-13.c16
-rw-r--r--fs/nls/nls_iso8859-14.c16
-rw-r--r--fs/nls/nls_iso8859-15.c16
-rw-r--r--fs/nls/nls_iso8859-2.c16
-rw-r--r--fs/nls/nls_iso8859-3.c16
-rw-r--r--fs/nls/nls_iso8859-4.c16
-rw-r--r--fs/nls/nls_iso8859-5.c16
-rw-r--r--fs/nls/nls_iso8859-6.c14
-rw-r--r--fs/nls/nls_iso8859-7.c18
-rw-r--r--fs/nls/nls_iso8859-9.c14
-rw-r--r--fs/nls/nls_koi8-r.c20
-rw-r--r--fs/nls/nls_koi8-u.c20
-rw-r--r--fs/ntfs/ChangeLog4
-rw-r--r--fs/ntfs/aops.c10
-rw-r--r--fs/ntfs/attrib.c5
-rw-r--r--fs/ntfs/compress.c10
-rw-r--r--fs/ntfs/file.c2
-rw-r--r--fs/ntfs/namei.c77
-rw-r--r--fs/ntfs/ntfs.h2
-rw-r--r--fs/ntfs/super.c7
-rw-r--r--fs/ntfs/sysctl.c2
-rw-r--r--fs/ntfs/sysctl.h2
-rw-r--r--fs/ocfs2/alloc.c2
-rw-r--r--fs/ocfs2/aops.c36
-rw-r--r--fs/ocfs2/aops.h8
-rw-r--r--fs/ocfs2/cluster/heartbeat.c4
-rw-r--r--fs/ocfs2/cluster/masklog.h2
-rw-r--r--fs/ocfs2/cluster/tcp.c4
-rw-r--r--fs/ocfs2/dcache.c4
-rw-r--r--fs/ocfs2/dir.c16
-rw-r--r--fs/ocfs2/dlm/dlmfs.c14
-rw-r--r--fs/ocfs2/dlm/dlmrecovery.c10
-rw-r--r--fs/ocfs2/dlmglue.c25
-rw-r--r--fs/ocfs2/export.c67
-rw-r--r--fs/ocfs2/export.h2
-rw-r--r--fs/ocfs2/file.c286
-rw-r--r--fs/ocfs2/namei.c13
-rw-r--r--fs/ocfs2/super.c4
-rw-r--r--fs/open.c15
-rw-r--r--fs/openpromfs/inode.c2
-rw-r--r--fs/pnode.h1
-rw-r--r--fs/proc/array.c38
-rw-r--r--fs/proc/base.c351
-rw-r--r--fs/proc/generic.c41
-rw-r--r--fs/proc/inode.c8
-rw-r--r--fs/proc/internal.h2
-rw-r--r--fs/proc/mmu.c21
-rw-r--r--fs/proc/proc_misc.c39
-rw-r--r--fs/proc/proc_net.c9
-rw-r--r--fs/proc/proc_sysctl.c6
-rw-r--r--fs/proc/root.c85
-rw-r--r--fs/qnx4/inode.c22
-rw-r--r--fs/ramfs/Makefile2
-rw-r--r--fs/ramfs/file-mmu.c4
-rw-r--r--fs/ramfs/file-nommu.c4
-rw-r--r--fs/ramfs/inode.c12
-rw-r--r--fs/read_write.c4
-rw-r--r--fs/reiserfs/bitmap.c168
-rw-r--r--fs/reiserfs/dir.c10
-rw-r--r--fs/reiserfs/file.c1240
-rw-r--r--fs/reiserfs/inode.c267
-rw-r--r--fs/reiserfs/ioctl.c13
-rw-r--r--fs/reiserfs/journal.c169
-rw-r--r--fs/reiserfs/prints.c10
-rw-r--r--fs/reiserfs/resize.c15
-rw-r--r--fs/reiserfs/stree.c9
-rw-r--r--fs/reiserfs/super.c43
-rw-r--r--fs/reiserfs/xattr.c21
-rw-r--r--fs/romfs/inode.c6
-rw-r--r--fs/select.c138
-rw-r--r--fs/signalfd.c44
-rw-r--r--fs/smbfs/file.c39
-rw-r--r--fs/smbfs/inode.c4
-rw-r--r--fs/smbfs/proc.c2
-rw-r--r--fs/smbfs/smbiod.c2
-rw-r--r--fs/splice.c86
-rw-r--r--fs/super.c39
-rw-r--r--fs/sysfs/dir.c11
-rw-r--r--fs/sysfs/file.c2
-rw-r--r--fs/sysfs/inode.c9
-rw-r--r--fs/sysfs/mount.c4
-rw-r--r--fs/sysfs/sysfs.h3
-rw-r--r--fs/sysv/dir.c50
-rw-r--r--fs/sysv/inode.c2
-rw-r--r--fs/sysv/itree.c23
-rw-r--r--fs/sysv/sysv.h3
-rw-r--r--fs/udf/balloc.c2
-rw-r--r--fs/udf/file.c35
-rw-r--r--fs/udf/inode.c13
-rw-r--r--fs/udf/super.c53
-rw-r--r--fs/udf/udftime.c8
-rw-r--r--fs/ufs/balloc.c1
-rw-r--r--fs/ufs/cylinder.c1
-rw-r--r--fs/ufs/dir.c56
-rw-r--r--fs/ufs/file.c3
-rw-r--r--fs/ufs/ialloc.c1
-rw-r--r--fs/ufs/inode.c24
-rw-r--r--fs/ufs/namei.c3
-rw-r--r--fs/ufs/super.c89
-rw-r--r--fs/ufs/symlink.c2
-rw-r--r--fs/ufs/truncate.c1
-rw-r--r--fs/ufs/ufs.h157
-rw-r--r--fs/ufs/util.c1
-rw-r--r--fs/ufs/util.h53
-rw-r--r--fs/utimes.c13
-rw-r--r--fs/xattr.c8
-rw-r--r--fs/xfs/Makefile-linux-2.63
-rw-r--r--fs/xfs/linux-2.6/kmem.h2
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c81
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.h2
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.c26
-rw-r--r--fs/xfs/linux-2.6/xfs_export.c222
-rw-r--r--fs/xfs/linux-2.6/xfs_export.h50
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c174
-rw-r--r--fs/xfs/linux-2.6/xfs_fs_subr.c54
-rw-r--r--fs/xfs/linux-2.6/xfs_fs_subr.h4
-rw-r--r--fs/xfs/linux-2.6/xfs_globals.c5
-rw-r--r--fs/xfs/linux-2.6/xfs_globals.h1
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl.c266
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl32.c8
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.c200
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.h8
-rw-r--r--fs/xfs/linux-2.6/xfs_linux.h3
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.c139
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.h23
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c301
-rw-r--r--fs/xfs/linux-2.6/xfs_super.h7
-rw-r--r--fs/xfs/linux-2.6/xfs_vfs.c327
-rw-r--r--fs/xfs/linux-2.6/xfs_vfs.h168
-rw-r--r--fs/xfs/linux-2.6/xfs_vnode.c100
-rw-r--r--fs/xfs/linux-2.6/xfs_vnode.h345
-rw-r--r--fs/xfs/quota/xfs_qm.c51
-rw-r--r--fs/xfs/quota/xfs_qm.h6
-rw-r--r--fs/xfs/quota/xfs_qm_bhv.c239
-rw-r--r--fs/xfs/quota/xfs_qm_syscalls.c21
-rw-r--r--fs/xfs/support/move.c51
-rw-r--r--fs/xfs/support/move.h70
-rw-r--r--fs/xfs/xfs_acl.c33
-rw-r--r--fs/xfs/xfs_acl.h19
-rw-r--r--fs/xfs/xfs_ag.h4
-rw-r--r--fs/xfs/xfs_attr.c50
-rw-r--r--fs/xfs/xfs_attr.h17
-rw-r--r--fs/xfs/xfs_behavior.c183
-rw-r--r--fs/xfs/xfs_behavior.h185
-rw-r--r--fs/xfs/xfs_bmap.c150
-rw-r--r--fs/xfs/xfs_bmap.h4
-rw-r--r--fs/xfs/xfs_bmap_btree.c255
-rw-r--r--fs/xfs/xfs_bmap_btree.h68
-rw-r--r--fs/xfs/xfs_buf_item.c1
-rw-r--r--fs/xfs/xfs_clnt.h1
-rw-r--r--fs/xfs/xfs_dfrag.c6
-rw-r--r--fs/xfs/xfs_dinode.h65
-rw-r--r--fs/xfs/xfs_dir2.c117
-rw-r--r--fs/xfs/xfs_dir2.h17
-rw-r--r--fs/xfs/xfs_dir2_block.c64
-rw-r--r--fs/xfs/xfs_dir2_block.h5
-rw-r--r--fs/xfs/xfs_dir2_data.c1
-rw-r--r--fs/xfs/xfs_dir2_leaf.c76
-rw-r--r--fs/xfs/xfs_dir2_leaf.h6
-rw-r--r--fs/xfs/xfs_dir2_node.c1
-rw-r--r--fs/xfs/xfs_dir2_sf.c122
-rw-r--r--fs/xfs/xfs_dir2_sf.h5
-rw-r--r--fs/xfs/xfs_dmapi.h17
-rw-r--r--fs/xfs/xfs_dmops.c30
-rw-r--r--fs/xfs/xfs_error.c21
-rw-r--r--fs/xfs/xfs_error.h5
-rw-r--r--fs/xfs/xfs_extfree_item.c1
-rw-r--r--fs/xfs/xfs_fs.h29
-rw-r--r--fs/xfs/xfs_fsops.c17
-rw-r--r--fs/xfs/xfs_ialloc.c6
-rw-r--r--fs/xfs/xfs_ialloc.h7
-rw-r--r--fs/xfs/xfs_iget.c605
-rw-r--r--fs/xfs/xfs_inode.c383
-rw-r--r--fs/xfs/xfs_inode.h158
-rw-r--r--fs/xfs/xfs_iocore.c4
-rw-r--r--fs/xfs/xfs_iomap.c8
-rw-r--r--fs/xfs/xfs_iomap.h1
-rw-r--r--fs/xfs/xfs_itable.c78
-rw-r--r--fs/xfs/xfs_log.c100
-rw-r--r--fs/xfs/xfs_log_priv.h21
-rw-r--r--fs/xfs/xfs_log_recover.c32
-rw-r--r--fs/xfs/xfs_mount.c242
-rw-r--r--fs/xfs/xfs_mount.h176
-rw-r--r--fs/xfs/xfs_qmops.c32
-rw-r--r--fs/xfs/xfs_quota.h10
-rw-r--r--fs/xfs/xfs_rename.c38
-rw-r--r--fs/xfs/xfs_rw.c5
-rw-r--r--fs/xfs/xfs_rw.h34
-rw-r--r--fs/xfs/xfs_sb.h68
-rw-r--r--fs/xfs/xfs_trans.c76
-rw-r--r--fs/xfs/xfs_trans_ail.c1
-rw-r--r--fs/xfs/xfs_trans_extfree.c1
-rw-r--r--fs/xfs/xfs_types.h12
-rw-r--r--fs/xfs/xfs_utils.c9
-rw-r--r--fs/xfs/xfs_utils.h6
-rw-r--r--fs/xfs/xfs_vfsops.c360
-rw-r--r--fs/xfs/xfs_vfsops.h28
-rw-r--r--fs/xfs/xfs_vnodeops.c756
-rw-r--r--fs/xfs/xfs_vnodeops.h86
-rw-r--r--include/Kbuild1
-rw-r--r--include/acpi/achware.h4
-rw-r--r--include/acpi/acpi_bus.h5
-rw-r--r--include/acpi/acpixf.h2
-rw-r--r--include/acpi/actbl1.h27
-rw-r--r--include/acpi/processor.h5
-rw-r--r--include/asm-alpha/bitops.h55
-rw-r--r--include/asm-alpha/elf.h1
-rw-r--r--include/asm-alpha/floppy.h2
-rw-r--r--include/asm-alpha/ide.h1
-rw-r--r--include/asm-alpha/io.h6
-rw-r--r--include/asm-alpha/page.h3
-rw-r--r--include/asm-alpha/ptrace.h2
-rw-r--r--include/asm-alpha/scatterlist.h5
-rw-r--r--include/asm-alpha/semaphore.h1
-rw-r--r--include/asm-alpha/system.h1
-rw-r--r--include/asm-alpha/tlbflush.h11
-rw-r--r--include/asm-arm/arch-aaec2000/aaec2000.h4
-rw-r--r--include/asm-arm/arch-at91/board.h3
-rw-r--r--include/asm-arm/arch-davinci/gpio.h3
-rw-r--r--include/asm-arm/arch-imx/imxfb.h1
-rw-r--r--include/asm-arm/arch-ixp23xx/platform.h6
-rw-r--r--include/asm-arm/arch-ixp4xx/io.h3
-rw-r--r--include/asm-arm/arch-ns9xxx/clock.h6
-rw-r--r--include/asm-arm/arch-ns9xxx/gpio.h47
-rw-r--r--include/asm-arm/arch-ns9xxx/hardware.h47
-rw-r--r--include/asm-arm/arch-ns9xxx/regs-board-a9m9750dev.h4
-rw-r--r--include/asm-arm/arch-ns9xxx/system.h4
-rw-r--r--include/asm-arm/arch-omap/blizzard.h12
-rw-r--r--include/asm-arm/arch-omap/board-2430sdp.h44
-rw-r--r--include/asm-arm/arch-omap/board-palmte.h34
-rw-r--r--include/asm-arm/arch-omap/board-palmtt.h23
-rw-r--r--include/asm-arm/arch-omap/board-palmz71.h26
-rw-r--r--include/asm-arm/arch-omap/board-sx1.h46
-rw-r--r--include/asm-arm/arch-omap/board.h4
-rw-r--r--include/asm-arm/arch-omap/dma.h1
-rw-r--r--include/asm-arm/arch-omap/eac.h101
-rw-r--r--include/asm-arm/arch-omap/gpmc.h5
-rw-r--r--include/asm-arm/arch-omap/hardware.h20
-rw-r--r--include/asm-arm/arch-omap/io.h10
-rw-r--r--include/asm-arm/arch-omap/menelaus.h20
-rw-r--r--include/asm-arm/arch-omap/mmc.h66
-rw-r--r--include/asm-arm/arch-omap/mux.h23
-rw-r--r--include/asm-arm/arch-omap/omap24xx.h12
-rw-r--r--include/asm-arm/arch-omap/onenand.h21
-rw-r--r--include/asm-arm/arch-pxa/cm-x270.h50
-rw-r--r--include/asm-arm/arch-pxa/dma.h4
-rw-r--r--include/asm-arm/arch-pxa/gpio.h12
-rw-r--r--include/asm-arm/arch-pxa/hardware.h99
-rw-r--r--include/asm-arm/arch-pxa/irqs.h27
-rw-r--r--include/asm-arm/arch-pxa/memory.h10
-rw-r--r--include/asm-arm/arch-pxa/mfp-pxa300.h574
-rw-r--r--include/asm-arm/arch-pxa/mfp-pxa320.h446
-rw-r--r--include/asm-arm/arch-pxa/mfp.h576
-rw-r--r--include/asm-arm/arch-pxa/pm.h2
-rw-r--r--include/asm-arm/arch-pxa/pxa-regs.h13
-rw-r--r--include/asm-arm/arch-pxa/pxa3xx-regs.h75
-rw-r--r--include/asm-arm/arch-pxa/pxafb.h7
-rw-r--r--include/asm-arm/arch-pxa/timex.h2
-rw-r--r--include/asm-arm/arch-pxa/zylonite.h35
-rw-r--r--include/asm-arm/arch-rpc/uncompress.h72
-rw-r--r--include/asm-arm/arch-s3c2410/fb.h42
-rw-r--r--include/asm-arm/arch-s3c2410/irqs.h7
-rw-r--r--include/asm-arm/arch-s3c2410/regs-gpio.h10
-rw-r--r--include/asm-arm/arch-s3c2410/regs-power.h5
-rw-r--r--include/asm-arm/arch-s3c2410/regs-s3c2412.h2
-rw-r--r--include/asm-arm/arch-sa1100/SA-1101.h4
-rw-r--r--include/asm-arm/bitops.h5
-rw-r--r--include/asm-arm/dma-mapping.h26
-rw-r--r--include/asm-arm/flat.h3
-rw-r--r--include/asm-arm/floppy.h2
-rw-r--r--include/asm-arm/hardware/iop3xx.h2
-rw-r--r--include/asm-arm/hardware/it8152.h99
-rw-r--r--include/asm-arm/ide.h1
-rw-r--r--include/asm-arm/ipc.h1
-rw-r--r--include/asm-arm/kexec.h2
-rw-r--r--include/asm-arm/pci.h7
-rw-r--r--include/asm-arm/pgtable.h2
-rw-r--r--include/asm-arm/plat-s3c/regs-nand.h2
-rw-r--r--include/asm-arm/scatterlist.h5
-rw-r--r--include/asm-arm/semaphore.h1
-rw-r--r--include/asm-arm/tlbflush.h5
-rw-r--r--include/asm-arm/types.h6
-rw-r--r--include/asm-arm/unistd.h1
-rw-r--r--include/asm-avr32/arch-at32ap/board.h23
-rw-r--r--include/asm-avr32/bitops.h5
-rw-r--r--include/asm-avr32/dma-mapping.h9
-rw-r--r--include/asm-avr32/io.h7
-rw-r--r--include/asm-avr32/kdebug.h16
-rw-r--r--include/asm-avr32/kprobes.h2
-rw-r--r--include/asm-avr32/scatterlist.h5
-rw-r--r--include/asm-avr32/semaphore.h1
-rw-r--r--include/asm-avr32/sysreg.h2
-rw-r--r--include/asm-avr32/tlbflush.h7
-rw-r--r--include/asm-avr32/types.h6
-rw-r--r--include/asm-blackfin/bf5xx_timers.h209
-rw-r--r--include/asm-blackfin/bfin-global.h5
-rw-r--r--include/asm-blackfin/bitops.h5
-rw-r--r--include/asm-blackfin/dma.h7
-rw-r--r--include/asm-blackfin/fixed_code.h4
-rw-r--r--include/asm-blackfin/gpio.h3
-rw-r--r--include/asm-blackfin/gptimers.h212
-rw-r--r--include/asm-blackfin/ide.h1
-rw-r--r--include/asm-blackfin/io.h4
-rw-r--r--include/asm-blackfin/ipc.h1
-rw-r--r--include/asm-blackfin/mach-bf527/anomaly.h8
-rw-r--r--include/asm-blackfin/mach-bf527/bf527.h127
-rw-r--r--include/asm-blackfin/mach-bf527/bfin_serial_5xx.h152
-rw-r--r--include/asm-blackfin/mach-bf527/blackfin.h78
-rw-r--r--include/asm-blackfin/mach-bf527/cdefBF52x_base.h19
-rw-r--r--include/asm-blackfin/mach-bf527/defBF527.h4
-rw-r--r--include/asm-blackfin/mach-bf527/defBF52x_base.h95
-rw-r--r--include/asm-blackfin/mach-bf527/dma.h65
-rw-r--r--include/asm-blackfin/mach-bf527/irq.h263
-rw-r--r--include/asm-blackfin/mach-bf527/mem_init.h337
-rw-r--r--include/asm-blackfin/mach-bf527/mem_map.h98
-rw-r--r--include/asm-blackfin/mach-bf527/portmux.h205
-rw-r--r--include/asm-blackfin/mach-bf548/bf54x-lq043.h30
-rw-r--r--include/asm-blackfin/mach-bf548/bf54x_keys.h17
-rw-r--r--include/asm-blackfin/mach-bf548/defBF549.h4
-rw-r--r--include/asm-blackfin/mach-bf548/defBF54x_base.h13
-rw-r--r--include/asm-blackfin/mach-bf548/dma.h2
-rw-r--r--include/asm-blackfin/mach-bf548/portmux.h14
-rw-r--r--include/asm-blackfin/mach-bf561/defBF561.h3
-rw-r--r--include/asm-blackfin/processor.h4
-rw-r--r--include/asm-blackfin/scatterlist.h6
-rw-r--r--include/asm-blackfin/semaphore.h1
-rw-r--r--include/asm-blackfin/system.h4
-rw-r--r--include/asm-blackfin/tlbflush.h6
-rw-r--r--include/asm-blackfin/types.h6
-rw-r--r--include/asm-cris/arch-v32/ide.h2
-rw-r--r--include/asm-cris/atomic.h2
-rw-r--r--include/asm-cris/bitops.h5
-rw-r--r--include/asm-cris/checksum.h2
-rw-r--r--include/asm-cris/ethernet.h3
-rw-r--r--include/asm-cris/fasttimer.h16
-rw-r--r--include/asm-cris/hardirq.h1
-rw-r--r--include/asm-cris/ipc.h1
-rw-r--r--include/asm-cris/irq_regs.h1
-rw-r--r--include/asm-cris/posix_types.h1
-rw-r--r--include/asm-cris/scatterlist.h5
-rw-r--r--include/asm-cris/semaphore.h1
-rw-r--r--include/asm-cris/termbits.h13
-rw-r--r--include/asm-cris/thread_info.h9
-rw-r--r--include/asm-cris/tlb.h2
-rw-r--r--include/asm-cris/tlbflush.h7
-rw-r--r--include/asm-cris/types.h6
-rw-r--r--include/asm-cris/unistd.h39
-rw-r--r--include/asm-frv/bitops.h5
-rw-r--r--include/asm-frv/ipc.h1
-rw-r--r--include/asm-frv/irq.h3
-rw-r--r--include/asm-frv/scatterlist.h14
-rw-r--r--include/asm-frv/semaphore.h1
-rw-r--r--include/asm-frv/thread_info.h5
-rw-r--r--include/asm-frv/tlbflush.h3
-rw-r--r--include/asm-frv/types.h6
-rw-r--r--include/asm-generic/Kbuild1
-rw-r--r--include/asm-generic/Kbuild.asm1
-rw-r--r--include/asm-generic/bitops.h5
-rw-r--r--include/asm-generic/bitops/atomic.h27
-rw-r--r--include/asm-generic/bitops/lock.h45
-rw-r--r--include/asm-generic/bitops/non-atomic.h29
-rw-r--r--include/asm-generic/ipc.h31
-rw-r--r--include/asm-generic/memory_model.h6
-rw-r--r--include/asm-generic/pgtable.h4
-rw-r--r--include/asm-generic/vmlinux.lds.h7
-rw-r--r--include/asm-h8300/bitops.h6
-rw-r--r--include/asm-h8300/io.h6
-rw-r--r--include/asm-h8300/ipc.h1
-rw-r--r--include/asm-h8300/scatterlist.h5
-rw-r--r--include/asm-h8300/semaphore.h1
-rw-r--r--include/asm-h8300/system.h3
-rw-r--r--include/asm-h8300/tlbflush.h6
-rw-r--r--include/asm-h8300/types.h6
-rw-r--r--include/asm-ia64/bitops.h45
-rw-r--r--include/asm-ia64/cacheflush.h2
-rw-r--r--include/asm-ia64/dma-mapping.h1
-rw-r--r--include/asm-ia64/elf.h1
-rw-r--r--include/asm-ia64/ide.h1
-rw-r--r--include/asm-ia64/io.h4
-rw-r--r--include/asm-ia64/kdebug.h15
-rw-r--r--include/asm-ia64/kprobes.h2
-rw-r--r--include/asm-ia64/meminit.h2
-rw-r--r--include/asm-ia64/numa.h1
-rw-r--r--include/asm-ia64/pal.h5
-rw-r--r--include/asm-ia64/percpu.h2
-rw-r--r--include/asm-ia64/pgtable.h52
-rw-r--r--include/asm-ia64/scatterlist.h7
-rw-r--r--include/asm-ia64/semaphore.h1
-rw-r--r--include/asm-ia64/smp.h5
-rw-r--r--include/asm-ia64/spinlock.h2
-rw-r--r--include/asm-ia64/system.h2
-rw-r--r--include/asm-ia64/tlbflush.h13
-rw-r--r--include/asm-ia64/topology.h2
-rw-r--r--include/asm-m32r/bitops.h5
-rw-r--r--include/asm-m32r/ide.h1
-rw-r--r--include/asm-m32r/ipc.h1
-rw-r--r--include/asm-m32r/pgtable.h2
-rw-r--r--include/asm-m32r/ptrace.h5
-rw-r--r--include/asm-m32r/scatterlist.h5
-rw-r--r--include/asm-m32r/semaphore.h1
-rw-r--r--include/asm-m32r/thread_info.h5
-rw-r--r--include/asm-m32r/tlbflush.h3
-rw-r--r--include/asm-m32r/types.h6
-rw-r--r--include/asm-m68k/bitops.h5
-rw-r--r--include/asm-m68k/floppy.h3
-rw-r--r--include/asm-m68k/ide.h2
-rw-r--r--include/asm-m68k/io.h6
-rw-r--r--include/asm-m68k/ipc.h1
-rw-r--r--include/asm-m68k/scatterlist.h5
-rw-r--r--include/asm-m68k/semaphore.h1
-rw-r--r--include/asm-m68k/tlbflush.h10
-rw-r--r--include/asm-m68k/types.h6
-rw-r--r--include/asm-m68knommu/bitops.h5
-rw-r--r--include/asm-m68knommu/dma.h2
-rw-r--r--include/asm-m68knommu/io.h6
-rw-r--r--include/asm-m68knommu/ipc.h1
-rw-r--r--include/asm-m68knommu/machdep.h11
-rw-r--r--include/asm-m68knommu/mcfuart.h10
-rw-r--r--include/asm-m68knommu/module.h12
-rw-r--r--include/asm-m68knommu/scatterlist.h6
-rw-r--r--include/asm-m68knommu/semaphore.h1
-rw-r--r--include/asm-m68knommu/system.h6
-rw-r--r--include/asm-m68knommu/tlbflush.h6
-rw-r--r--include/asm-m68knommu/uaccess.h4
-rw-r--r--include/asm-m68knommu/unistd.h4
-rw-r--r--include/asm-mips/bitops.h106
-rw-r--r--include/asm-mips/cpu-info.h1
-rw-r--r--include/asm-mips/floppy.h2
-rw-r--r--include/asm-mips/fpu.h2
-rw-r--r--include/asm-mips/gt64120.h5
-rw-r--r--include/asm-mips/i8253.h23
-rw-r--r--include/asm-mips/io.h2
-rw-r--r--include/asm-mips/ip32/crime.h3
-rw-r--r--include/asm-mips/ip32/ip32_ints.h160
-rw-r--r--include/asm-mips/ip32/mace.h3
-rw-r--r--include/asm-mips/ipc.h1
-rw-r--r--include/asm-mips/jmr3927/jmr3927.h9
-rw-r--r--include/asm-mips/jmr3927/tx3927.h4
-rw-r--r--include/asm-mips/jmr3927/txx927.h37
-rw-r--r--include/asm-mips/lasat/lasatint.h4
-rw-r--r--include/asm-mips/mach-au1x00/au1000.h647
-rw-r--r--include/asm-mips/mach-au1x00/prom.h13
-rw-r--r--include/asm-mips/mach-au1x00/timex.h13
-rw-r--r--include/asm-mips/mach-cobalt/irq.h3
-rw-r--r--include/asm-mips/mach-db1x00/db1200.h49
-rw-r--r--include/asm-mips/mach-generic/ide.h1
-rw-r--r--include/asm-mips/mach-generic/timex.h13
-rw-r--r--include/asm-mips/mach-ip27/kernel-entry-init.h9
-rw-r--r--include/asm-mips/mach-jazz/timex.h16
-rw-r--r--include/asm-mips/mach-lasat/irq.h13
-rw-r--r--include/asm-mips/mach-pb1x00/pb1200.h52
-rw-r--r--include/asm-mips/mach-qemu/timex.h16
-rw-r--r--include/asm-mips/mach-rm/timex.h13
-rw-r--r--include/asm-mips/pci/bridge.h2
-rw-r--r--include/asm-mips/pmc-sierra/msp71xx/war.h28
-rw-r--r--include/asm-mips/ptrace.h4
-rw-r--r--include/asm-mips/scatterlist.h5
-rw-r--r--include/asm-mips/semaphore.h1
-rw-r--r--include/asm-mips/sibyte/sb1250.h2
-rw-r--r--include/asm-mips/sni.h2
-rw-r--r--include/asm-mips/time.h32
-rw-r--r--include/asm-mips/timex.h27
-rw-r--r--include/asm-mips/tlbflush.h7
-rw-r--r--include/asm-mips/tx4927/tx4927_pci.h3
-rw-r--r--include/asm-mips/tx4938/tx4938.h1
-rw-r--r--include/asm-mips/txx9tmr.h67
-rw-r--r--include/asm-mips/types.h6
-rw-r--r--include/asm-mips/xxs1500.h35
-rw-r--r--include/asm-parisc/Kbuild2
-rw-r--r--include/asm-parisc/bitops.h5
-rw-r--r--include/asm-parisc/floppy.h4
-rw-r--r--include/asm-parisc/ide.h1
-rw-r--r--include/asm-parisc/io.h7
-rw-r--r--include/asm-parisc/page.h4
-rw-r--r--include/asm-parisc/pci.h2
-rw-r--r--include/asm-parisc/pdc.h308
-rw-r--r--include/asm-parisc/pgtable.h42
-rw-r--r--include/asm-parisc/prefetch.h4
-rw-r--r--include/asm-parisc/rtc.h4
-rw-r--r--include/asm-parisc/scatterlist.h7
-rw-r--r--include/asm-parisc/semaphore.h11
-rw-r--r--include/asm-parisc/tlbflush.h4
-rw-r--r--include/asm-parisc/types.h6
-rw-r--r--include/asm-parisc/unistd.h3
-rw-r--r--include/asm-powerpc/Kbuild2
-rw-r--r--include/asm-powerpc/bitops.h49
-rw-r--r--include/asm-powerpc/commproc.h2
-rw-r--r--include/asm-powerpc/cputable.h25
-rw-r--r--include/asm-powerpc/dcr-mmio.h6
-rw-r--r--include/asm-powerpc/dcr-native.h6
-rw-r--r--include/asm-powerpc/dma-mapping.h27
-rw-r--r--include/asm-powerpc/elf.h47
-rw-r--r--include/asm-powerpc/floppy.h2
-rw-r--r--include/asm-powerpc/ibmebus.h38
-rw-r--r--include/asm-powerpc/ide.h3
-rw-r--r--include/asm-powerpc/io.h19
-rw-r--r--include/asm-powerpc/iommu.h2
-rw-r--r--include/asm-powerpc/ipc.h1
-rw-r--r--include/asm-powerpc/kdebug.h19
-rw-r--r--include/asm-powerpc/kprobes.h2
-rw-r--r--include/asm-powerpc/mmu_context.h2
-rw-r--r--include/asm-powerpc/mpc52xx.h15
-rw-r--r--include/asm-powerpc/of_device.h4
-rw-r--r--include/asm-powerpc/paca.h5
-rw-r--r--include/asm-powerpc/pgtable-ppc32.h13
-rw-r--r--include/asm-powerpc/pgtable-ppc64.h8
-rw-r--r--include/asm-powerpc/ps3av.h33
-rw-r--r--include/asm-powerpc/scatterlist.h7
-rw-r--r--include/asm-powerpc/semaphore.h1
-rw-r--r--include/asm-powerpc/smp.h4
-rw-r--r--include/asm-powerpc/systbl.h2
-rw-r--r--include/asm-powerpc/system.h1
-rw-r--r--include/asm-powerpc/time.h20
-rw-r--r--include/asm-powerpc/tlbflush.h23
-rw-r--r--include/asm-powerpc/topology.h2
-rw-r--r--include/asm-powerpc/types.h6
-rw-r--r--include/asm-ppc/floppy.h2
-rw-r--r--include/asm-ppc/io.h17
-rw-r--r--include/asm-ppc/irq_regs.h1
-rw-r--r--include/asm-ppc/mmu_context.h3
-rw-r--r--include/asm-ppc/mpc52xx_psc.h10
-rw-r--r--include/asm-ppc/system.h1
-rw-r--r--include/asm-ppc/time.h2
-rw-r--r--include/asm-s390/bitops.h5
-rw-r--r--include/asm-s390/cpu.h25
-rw-r--r--include/asm-s390/ipc.h1
-rw-r--r--include/asm-s390/kdebug.h15
-rw-r--r--include/asm-s390/kprobes.h2
-rw-r--r--include/asm-s390/mmu_context.h50
-rw-r--r--include/asm-s390/page.h4
-rw-r--r--include/asm-s390/pgalloc.h250
-rw-r--r--include/asm-s390/pgtable.h429
-rw-r--r--include/asm-s390/processor.h20
-rw-r--r--include/asm-s390/scatterlist.h5
-rw-r--r--include/asm-s390/semaphore.h1
-rw-r--r--include/asm-s390/tlb.h129
-rw-r--r--include/asm-s390/tlbflush.h159
-rw-r--r--include/asm-s390/types.h6
-rw-r--r--include/asm-sh/bitops.h6
-rw-r--r--include/asm-sh/cache.h3
-rw-r--r--include/asm-sh/cacheflush.h18
-rw-r--r--include/asm-sh/cpu-sh3/timer.h6
-rw-r--r--include/asm-sh/dma-mapping.h12
-rw-r--r--include/asm-sh/elf.h1
-rw-r--r--include/asm-sh/floppy.h6
-rw-r--r--include/asm-sh/io.h25
-rw-r--r--include/asm-sh/ipc.h1
-rw-r--r--include/asm-sh/irq.h2
-rw-r--r--include/asm-sh/kdebug.h2
-rw-r--r--include/asm-sh/page.h12
-rw-r--r--include/asm-sh/pgtable.h6
-rw-r--r--include/asm-sh/processor.h4
-rw-r--r--include/asm-sh/ptrace.h3
-rw-r--r--include/asm-sh/scatterlist.h5
-rw-r--r--include/asm-sh/se7751.h2
-rw-r--r--include/asm-sh/semaphore.h1
-rw-r--r--include/asm-sh/setup.h14
-rw-r--r--include/asm-sh/system.h1
-rw-r--r--include/asm-sh/systemh7751.h2
-rw-r--r--include/asm-sh/tlbflush.h6
-rw-r--r--include/asm-sh/types.h6
-rw-r--r--include/asm-sh/vga.h6
-rw-r--r--include/asm-sh64/bitops.h6
-rw-r--r--include/asm-sh64/dma-mapping.h19
-rw-r--r--include/asm-sh64/ide.h1
-rw-r--r--include/asm-sh64/io.h48
-rw-r--r--include/asm-sh64/ipc.h1
-rw-r--r--include/asm-sh64/pci.h9
-rw-r--r--include/asm-sh64/ptrace.h2
-rw-r--r--include/asm-sh64/scatterlist.h14
-rw-r--r--include/asm-sh64/semaphore.h1
-rw-r--r--include/asm-sh64/system.h3
-rw-r--r--include/asm-sh64/tlbflush.h4
-rw-r--r--include/asm-sh64/types.h6
-rw-r--r--include/asm-sparc/atomic.h4
-rw-r--r--include/asm-sparc/bitops.h5
-rw-r--r--include/asm-sparc/dma.h9
-rw-r--r--include/asm-sparc/floppy.h16
-rw-r--r--include/asm-sparc/ide.h10
-rw-r--r--include/asm-sparc/io.h7
-rw-r--r--include/asm-sparc/ioctls.h4
-rw-r--r--include/asm-sparc/ipc.h1
-rw-r--r--include/asm-sparc/of_platform.h5
-rw-r--r--include/asm-sparc/posix_types.h8
-rw-r--r--include/asm-sparc/scatterlist.h7
-rw-r--r--include/asm-sparc/semaphore.h1
-rw-r--r--include/asm-sparc/system.h6
-rw-r--r--include/asm-sparc/termbits.h15
-rw-r--r--include/asm-sparc/termios.h48
-rw-r--r--include/asm-sparc/tlbflush.h6
-rw-r--r--include/asm-sparc64/Kbuild1
-rw-r--r--include/asm-sparc64/atomic.h7
-rw-r--r--include/asm-sparc64/backoff.h30
-rw-r--r--include/asm-sparc64/bitops.h5
-rw-r--r--include/asm-sparc64/byteorder.h7
-rw-r--r--include/asm-sparc64/floppy.h4
-rw-r--r--include/asm-sparc64/fpumacro.h4
-rw-r--r--include/asm-sparc64/futex.h6
-rw-r--r--include/asm-sparc64/ide.h1
-rw-r--r--include/asm-sparc64/io.h35
-rw-r--r--include/asm-sparc64/ioctls.h4
-rw-r--r--include/asm-sparc64/ipc.h1
-rw-r--r--include/asm-sparc64/irq.h11
-rw-r--r--include/asm-sparc64/kdebug.h18
-rw-r--r--include/asm-sparc64/kprobes.h3
-rw-r--r--include/asm-sparc64/mostek.h9
-rw-r--r--include/asm-sparc64/ns87303.h5
-rw-r--r--include/asm-sparc64/of_platform.h5
-rw-r--r--include/asm-sparc64/parport.h21
-rw-r--r--include/asm-sparc64/pgtable.h3
-rw-r--r--include/asm-sparc64/posix_types.h8
-rw-r--r--include/asm-sparc64/sbus.h4
-rw-r--r--include/asm-sparc64/scatterlist.h7
-rw-r--r--include/asm-sparc64/semaphore.h1
-rw-r--r--include/asm-sparc64/shmparam.h2
-rw-r--r--include/asm-sparc64/smp.h5
-rw-r--r--include/asm-sparc64/spitfire.h53
-rw-r--r--include/asm-sparc64/system.h13
-rw-r--r--include/asm-sparc64/termbits.h17
-rw-r--r--include/asm-sparc64/termios.h42
-rw-r--r--include/asm-sparc64/tlbflush.h7
-rw-r--r--include/asm-sparc64/topology.h2
-rw-r--r--include/asm-sparc64/uaccess.h6
-rw-r--r--include/asm-sparc64/upa.h17
-rw-r--r--include/asm-sparc64/vio.h4
-rw-r--r--include/asm-sparc64/visasm.h3
-rw-r--r--include/asm-um/a.out.h12
-rw-r--r--include/asm-um/alternative-asm.h (renamed from include/asm-um/alternative-asm.i)2
-rw-r--r--include/asm-um/bitops.h4
-rw-r--r--include/asm-um/elf-i386.h12
-rw-r--r--include/asm-um/elf-x86_64.h56
-rw-r--r--include/asm-um/frame.h (renamed from include/asm-um/frame.i)2
-rw-r--r--include/asm-um/ipc.h1
-rw-r--r--include/asm-um/ldt.h4
-rw-r--r--include/asm-um/mmu_context.h43
-rw-r--r--include/asm-um/page.h1
-rw-r--r--include/asm-um/pgalloc.h2
-rw-r--r--include/asm-um/pgtable-3level.h4
-rw-r--r--include/asm-um/processor-generic.h48
-rw-r--r--include/asm-um/processor-x86_64.h2
-rw-r--r--include/asm-um/ptrace-generic.h17
-rw-r--r--include/asm-um/ptrace-i386.h42
-rw-r--r--include/asm-um/ptrace-x86_64.h13
-rw-r--r--include/asm-um/smp.h2
-rw-r--r--include/asm-um/tlbflush.h25
-rw-r--r--include/asm-um/uaccess.h2
-rw-r--r--include/asm-um/unistd.h1
-rw-r--r--include/asm-v850/bitops.h4
-rw-r--r--include/asm-v850/ipc.h1
-rw-r--r--include/asm-v850/irq_regs.h1
-rw-r--r--include/asm-v850/scatterlist.h5
-rw-r--r--include/asm-v850/semaphore.h1
-rw-r--r--include/asm-v850/system.h3
-rw-r--r--include/asm-v850/tlbflush.h6
-rw-r--r--include/asm-v850/types.h6
-rw-r--r--include/asm-x86/Kbuild67
-rw-r--r--include/asm-x86/a.out.h33
-rw-r--r--include/asm-x86/a.out_32.h27
-rw-r--r--include/asm-x86/a.out_64.h28
-rw-r--r--include/asm-x86/acpi_32.h6
-rw-r--r--include/asm-x86/agp.h43
-rw-r--r--include/asm-x86/agp_32.h36
-rw-r--r--include/asm-x86/agp_64.h34
-rw-r--r--include/asm-x86/alternative-asm.h22
-rw-r--r--include/asm-x86/alternative-asm.i5
-rw-r--r--include/asm-x86/alternative-asm_32.i12
-rw-r--r--include/asm-x86/alternative-asm_64.i12
-rw-r--r--include/asm-x86/apic_64.h1
-rw-r--r--include/asm-x86/atomic_64.h2
-rw-r--r--include/asm-x86/auxvec.h23
-rw-r--r--include/asm-x86/auxvec_32.h11
-rw-r--r--include/asm-x86/auxvec_64.h6
-rw-r--r--include/asm-x86/bitops_32.h49
-rw-r--r--include/asm-x86/bitops_64.h100
-rw-r--r--include/asm-x86/bootparam.h112
-rw-r--r--include/asm-x86/bootsetup.h40
-rw-r--r--include/asm-x86/bug.h41
-rw-r--r--include/asm-x86/bug_32.h37
-rw-r--r--include/asm-x86/bug_64.h34
-rw-r--r--include/asm-x86/bugs.h11
-rw-r--r--include/asm-x86/bugs_32.h12
-rw-r--r--include/asm-x86/bugs_64.h6
-rw-r--r--include/asm-x86/byteorder.h81
-rw-r--r--include/asm-x86/byteorder_32.h58
-rw-r--r--include/asm-x86/byteorder_64.h33
-rw-r--r--include/asm-x86/cache.h23
-rw-r--r--include/asm-x86/cache_32.h14
-rw-r--r--include/asm-x86/cache_64.h26
-rw-r--r--include/asm-x86/cacheflush.h44
-rw-r--r--include/asm-x86/cacheflush_32.h39
-rw-r--r--include/asm-x86/cacheflush_64.h35
-rw-r--r--include/asm-x86/compat.h6
-rw-r--r--include/asm-x86/cpu.h3
-rw-r--r--include/asm-x86/cpufeature_32.h1
-rw-r--r--include/asm-x86/cputime.h6
-rw-r--r--include/asm-x86/cputime_32.h6
-rw-r--r--include/asm-x86/cputime_64.h6
-rw-r--r--include/asm-x86/debugreg.h79
-rw-r--r--include/asm-x86/debugreg_32.h64
-rw-r--r--include/asm-x86/debugreg_64.h65
-rw-r--r--include/asm-x86/delay.h36
-rw-r--r--include/asm-x86/delay_32.h31
-rw-r--r--include/asm-x86/delay_64.h30
-rw-r--r--include/asm-x86/desc_64.h30
-rw-r--r--include/asm-x86/device.h16
-rw-r--r--include/asm-x86/device_32.h15
-rw-r--r--include/asm-x86/device_64.h15
-rw-r--r--include/asm-x86/div64.h60
-rw-r--r--include/asm-x86/div64_32.h52
-rw-r--r--include/asm-x86/div64_64.h1
-rw-r--r--include/asm-x86/dma-mapping_32.h13
-rw-r--r--include/asm-x86/dma-mapping_64.h3
-rw-r--r--include/asm-x86/dmi.h36
-rw-r--r--include/asm-x86/dmi_32.h11
-rw-r--r--include/asm-x86/dmi_64.h24
-rw-r--r--include/asm-x86/e820.h28
-rw-r--r--include/asm-x86/e820_32.h21
-rw-r--r--include/asm-x86/e820_64.h20
-rw-r--r--include/asm-x86/edac.h21
-rw-r--r--include/asm-x86/edac_32.h18
-rw-r--r--include/asm-x86/edac_64.h18
-rw-r--r--include/asm-x86/elf.h299
-rw-r--r--include/asm-x86/elf_32.h163
-rw-r--r--include/asm-x86/elf_64.h180
-rw-r--r--include/asm-x86/errno.h14
-rw-r--r--include/asm-x86/errno_32.h6
-rw-r--r--include/asm-x86/errno_64.h6
-rw-r--r--include/asm-x86/fb.h20
-rw-r--r--include/asm-x86/fb_32.h17
-rw-r--r--include/asm-x86/fb_64.h19
-rw-r--r--include/asm-x86/floppy.h281
-rw-r--r--include/asm-x86/floppy_32.h284
-rw-r--r--include/asm-x86/floppy_64.h283
-rw-r--r--include/asm-x86/frame.h (renamed from include/asm-x86/frame.i)4
-rw-r--r--include/asm-x86/gart.h29
-rw-r--r--include/asm-x86/geode.h2
-rw-r--r--include/asm-x86/hardirq_32.h6
-rw-r--r--include/asm-x86/hpet.h7
-rw-r--r--include/asm-x86/hw_irq_64.h35
-rw-r--r--include/asm-x86/i387_64.h5
-rw-r--r--include/asm-x86/ide.h1
-rw-r--r--include/asm-x86/intel_arch_perfmon.h36
-rw-r--r--include/asm-x86/intel_arch_perfmon_32.h31
-rw-r--r--include/asm-x86/intel_arch_perfmon_64.h31
-rw-r--r--include/asm-x86/io_32.h28
-rw-r--r--include/asm-x86/io_64.h6
-rw-r--r--include/asm-x86/io_apic_64.h2
-rw-r--r--include/asm-x86/ioctls.h98
-rw-r--r--include/asm-x86/ioctls_32.h87
-rw-r--r--include/asm-x86/ioctls_64.h86
-rw-r--r--include/asm-x86/iommu.h4
-rw-r--r--include/asm-x86/ipc.h1
-rw-r--r--include/asm-x86/ipcbuf.h42
-rw-r--r--include/asm-x86/ipcbuf_32.h29
-rw-r--r--include/asm-x86/ipcbuf_64.h29
-rw-r--r--include/asm-x86/ipi.h2
-rw-r--r--include/asm-x86/irq_32.h3
-rw-r--r--include/asm-x86/irqflags_32.h21
-rw-r--r--include/asm-x86/irqflags_64.h20
-rw-r--r--include/asm-x86/ist.h12
-rw-r--r--include/asm-x86/kdebug.h36
-rw-r--r--include/asm-x86/kdebug_32.h33
-rw-r--r--include/asm-x86/kdebug_64.h36
-rw-r--r--include/asm-x86/kmap_types.h30
-rw-r--r--include/asm-x86/kmap_types_32.h30
-rw-r--r--include/asm-x86/kmap_types_64.h19
-rw-r--r--include/asm-x86/kprobes_32.h4
-rw-r--r--include/asm-x86/kprobes_64.h2
-rw-r--r--include/asm-x86/ldt.h51
-rw-r--r--include/asm-x86/ldt_32.h32
-rw-r--r--include/asm-x86/ldt_64.h36
-rw-r--r--include/asm-x86/lguest.h86
-rw-r--r--include/asm-x86/lguest_hcall.h68
-rw-r--r--include/asm-x86/mach-default/mach_apicdef.h8
-rw-r--r--include/asm-x86/mach-visws/cobalt.h8
-rw-r--r--include/asm-x86/mach-visws/lithium.h8
-rw-r--r--include/asm-x86/mach-voyager/setup_arch.h4
-rw-r--r--include/asm-x86/mce.h128
-rw-r--r--include/asm-x86/mce_32.h11
-rw-r--r--include/asm-x86/mce_64.h115
-rw-r--r--include/asm-x86/mman.h32
-rw-r--r--include/asm-x86/mman_32.h17
-rw-r--r--include/asm-x86/mman_64.h19
-rw-r--r--include/asm-x86/mmu.h26
-rw-r--r--include/asm-x86/mmu_32.h18
-rw-r--r--include/asm-x86/mmu_64.h21
-rw-r--r--include/asm-x86/msgbuf.h50
-rw-r--r--include/asm-x86/msgbuf_32.h31
-rw-r--r--include/asm-x86/msgbuf_64.h27
-rw-r--r--include/asm-x86/msr-index.h36
-rw-r--r--include/asm-x86/msr.h357
-rw-r--r--include/asm-x86/msr_32.h161
-rw-r--r--include/asm-x86/msr_64.h187
-rw-r--r--include/asm-x86/mtrr.h175
-rw-r--r--include/asm-x86/mtrr_32.h115
-rw-r--r--include/asm-x86/mtrr_64.h152
-rw-r--r--include/asm-x86/namei.h16
-rw-r--r--include/asm-x86/namei_32.h17
-rw-r--r--include/asm-x86/namei_64.h11
-rw-r--r--include/asm-x86/numa_64.h3
-rw-r--r--include/asm-x86/page_64.h1
-rw-r--r--include/asm-x86/param.h31
-rw-r--r--include/asm-x86/param_32.h22
-rw-r--r--include/asm-x86/param_64.h22
-rw-r--r--include/asm-x86/paravirt.h487
-rw-r--r--include/asm-x86/parport.h15
-rw-r--r--include/asm-x86/parport_32.h18
-rw-r--r--include/asm-x86/parport_64.h18
-rw-r--r--include/asm-x86/pci_64.h2
-rw-r--r--include/asm-x86/pda.h6
-rw-r--r--include/asm-x86/pgtable-3level-defs.h2
-rw-r--r--include/asm-x86/pgtable_32.h7
-rw-r--r--include/asm-x86/pgtable_64.h3
-rw-r--r--include/asm-x86/processor_32.h47
-rw-r--r--include/asm-x86/processor_64.h43
-rw-r--r--include/asm-x86/proto.h2
-rw-r--r--include/asm-x86/ptrace-abi.h90
-rw-r--r--include/asm-x86/ptrace-abi_32.h39
-rw-r--r--include/asm-x86/ptrace-abi_64.h51
-rw-r--r--include/asm-x86/ptrace.h151
-rw-r--r--include/asm-x86/ptrace_32.h63
-rw-r--r--include/asm-x86/ptrace_64.h78
-rw-r--r--include/asm-x86/required-features.h73
-rw-r--r--include/asm-x86/required-features_32.h55
-rw-r--r--include/asm-x86/required-features_64.h46
-rw-r--r--include/asm-x86/resource.h14
-rw-r--r--include/asm-x86/resource_32.h6
-rw-r--r--include/asm-x86/resource_64.h6
-rw-r--r--include/asm-x86/rtc.h6
-rw-r--r--include/asm-x86/rtc_32.h10
-rw-r--r--include/asm-x86/rtc_64.h10
-rw-r--r--include/asm-x86/rwlock.h14
-rw-r--r--include/asm-x86/rwlock_32.h25
-rw-r--r--include/asm-x86/rwlock_64.h26
-rw-r--r--include/asm-x86/scatterlist_32.h7
-rw-r--r--include/asm-x86/scatterlist_64.h7
-rw-r--r--include/asm-x86/sections.h6
-rw-r--r--include/asm-x86/sections_32.h7
-rw-r--r--include/asm-x86/sections_64.h7
-rw-r--r--include/asm-x86/semaphore_32.h1
-rw-r--r--include/asm-x86/semaphore_64.h1
-rw-r--r--include/asm-x86/sembuf.h37
-rw-r--r--include/asm-x86/sembuf_32.h25
-rw-r--r--include/asm-x86/sembuf_64.h25
-rw-r--r--include/asm-x86/serial.h30
-rw-r--r--include/asm-x86/serial_32.h29
-rw-r--r--include/asm-x86/serial_64.h29
-rw-r--r--include/asm-x86/setup.h72
-rw-r--r--include/asm-x86/setup_32.h92
-rw-r--r--include/asm-x86/setup_64.h6
-rw-r--r--include/asm-x86/shmbuf.h62
-rw-r--r--include/asm-x86/shmbuf_32.h42
-rw-r--r--include/asm-x86/shmbuf_64.h38
-rw-r--r--include/asm-x86/shmparam.h19
-rw-r--r--include/asm-x86/shmparam_32.h6
-rw-r--r--include/asm-x86/shmparam_64.h6
-rw-r--r--include/asm-x86/sigcontext.h149
-rw-r--r--include/asm-x86/sigcontext_32.h85
-rw-r--r--include/asm-x86/sigcontext_64.h55
-rw-r--r--include/asm-x86/siginfo.h21
-rw-r--r--include/asm-x86/siginfo_32.h6
-rw-r--r--include/asm-x86/siginfo_64.h8
-rw-r--r--include/asm-x86/signal.h273
-rw-r--r--include/asm-x86/signal_32.h232
-rw-r--r--include/asm-x86/signal_64.h181
-rw-r--r--include/asm-x86/smp_32.h12
-rw-r--r--include/asm-x86/smp_64.h25
-rw-r--r--include/asm-x86/sockios.h26
-rw-r--r--include/asm-x86/sockios_32.h13
-rw-r--r--include/asm-x86/sockios_64.h13
-rw-r--r--include/asm-x86/stacktrace.h2
-rw-r--r--include/asm-x86/stat.h123
-rw-r--r--include/asm-x86/stat_32.h77
-rw-r--r--include/asm-x86/stat_64.h44
-rw-r--r--include/asm-x86/statfs.h72
-rw-r--r--include/asm-x86/statfs_32.h6
-rw-r--r--include/asm-x86/statfs_64.h58
-rw-r--r--include/asm-x86/string_32.h3
-rw-r--r--include/asm-x86/suspend_64.h25
-rw-r--r--include/asm-x86/system_32.h8
-rw-r--r--include/asm-x86/system_64.h16
-rw-r--r--include/asm-x86/termbits.h211
-rw-r--r--include/asm-x86/termbits_32.h198
-rw-r--r--include/asm-x86/termbits_64.h198
-rw-r--r--include/asm-x86/termios.h108
-rw-r--r--include/asm-x86/termios_32.h90
-rw-r--r--include/asm-x86/termios_64.h90
-rw-r--r--include/asm-x86/tlb.h14
-rw-r--r--include/asm-x86/tlb_32.h20
-rw-r--r--include/asm-x86/tlb_64.h13
-rw-r--r--include/asm-x86/tlbflush_32.h7
-rw-r--r--include/asm-x86/tlbflush_64.h9
-rw-r--r--include/asm-x86/topology_32.h8
-rw-r--r--include/asm-x86/topology_64.h10
-rw-r--r--include/asm-x86/types.h77
-rw-r--r--include/asm-x86/types_32.h64
-rw-r--r--include/asm-x86/types_64.h55
-rw-r--r--include/asm-x86/ucontext.h25
-rw-r--r--include/asm-x86/ucontext_32.h12
-rw-r--r--include/asm-x86/ucontext_64.h12
-rw-r--r--include/asm-x86/unaligned.h42
-rw-r--r--include/asm-x86/unaligned_32.h37
-rw-r--r--include/asm-x86/unaligned_64.h37
-rw-r--r--include/asm-x86/unistd_64.h619
-rw-r--r--include/asm-x86/unwind.h18
-rw-r--r--include/asm-x86/unwind_32.h13
-rw-r--r--include/asm-x86/unwind_64.h12
-rw-r--r--include/asm-xtensa/bitops.h5
-rw-r--r--include/asm-xtensa/dma-mapping.h15
-rw-r--r--include/asm-xtensa/scatterlist.h5
-rw-r--r--include/asm-xtensa/semaphore.h1
-rw-r--r--include/asm-xtensa/tlbflush.h11
-rw-r--r--include/asm-xtensa/types.h6
-rw-r--r--include/keys/rxrpc-type.h2
-rw-r--r--include/linux/Kbuild13
-rw-r--r--include/linux/acpi.h26
-rw-r--r--include/linux/aio.h12
-rw-r--r--include/linux/apm_bios.h30
-rw-r--r--include/linux/ata.h45
-rw-r--r--include/linux/atmel-ssc.h312
-rw-r--r--include/linux/audit.h19
-rw-r--r--include/linux/auxvec.h4
-rw-r--r--include/linux/backing-dev.h94
-rw-r--r--include/linux/binfmts.h9
-rw-r--r--include/linux/bio.h19
-rw-r--r--include/linux/bit_spinlock.h26
-rw-r--r--include/linux/bitmap.h1
-rw-r--r--include/linux/bitops.h14
-rw-r--r--include/linux/blkdev.h11
-rw-r--r--include/linux/bootmem.h1
-rw-r--r--include/linux/buffer_head.h26
-rw-r--r--include/linux/capability.h48
-rw-r--r--include/linux/cdrom.h6
-rw-r--r--include/linux/cgroup.h327
-rw-r--r--include/linux/cgroup_subsys.h32
-rw-r--r--include/linux/cgroupstats.h70
-rw-r--r--include/linux/clocksource.h5
-rw-r--r--include/linux/compiler-gcc.h16
-rw-r--r--include/linux/compiler-gcc3.h4
-rw-r--r--include/linux/compiler-gcc4.h4
-rw-r--r--include/linux/compiler-intel.h4
-rw-r--r--include/linux/compiler.h20
-rw-r--r--include/linux/completion.h18
-rw-r--r--include/linux/connector.h7
-rw-r--r--include/linux/console.h10
-rw-r--r--include/linux/console_struct.h1
-rw-r--r--include/linux/consolemap.h1
-rw-r--r--include/linux/cpu.h5
-rw-r--r--include/linux/cpuidle.h180
-rw-r--r--include/linux/cpuset.h25
-rw-r--r--include/linux/cramfs_fs.h1
-rw-r--r--include/linux/crypto.h2
-rw-r--r--include/linux/cyclades.h27
-rw-r--r--include/linux/dca.h47
-rw-r--r--include/linux/dcache.h1
-rw-r--r--include/linux/dccp.h12
-rw-r--r--include/linux/delayacct.h13
-rw-r--r--include/linux/device-mapper.h4
-rw-r--r--include/linux/dm-ioctl.h5
-rw-r--r--include/linux/dma-mapping.h37
-rw-r--r--include/linux/dmar.h86
-rw-r--r--include/linux/edd.h137
-rw-r--r--include/linux/efi.h2
-rw-r--r--include/linux/efs_fs.h6
-rw-r--r--include/linux/elf.h2
-rw-r--r--include/linux/elfcore-compat.h55
-rw-r--r--include/linux/eventpoll.h7
-rw-r--r--include/linux/exportfs.h141
-rw-r--r--include/linux/ext2_fs.h24
-rw-r--r--include/linux/ext2_fs_sb.h51
-rw-r--r--include/linux/ext3_fs.h38
-rw-r--r--include/linux/ext3_fs_sb.h1
-rw-r--r--include/linux/ext4_fs.h103
-rw-r--r--include/linux/ext4_fs_extents.h4
-rw-r--r--include/linux/ext4_fs_i.h5
-rw-r--r--include/linux/ext4_fs_sb.h4
-rw-r--r--include/linux/ext4_jbd2.h6
-rw-r--r--include/linux/f75375s.h21
-rw-r--r--include/linux/fb.h3
-rw-r--r--include/linux/fcntl.h15
-rw-r--r--include/linux/file.h9
-rw-r--r--include/linux/filter.h1
-rw-r--r--include/linux/firewire-cdev.h15
-rw-r--r--include/linux/freezer.h38
-rw-r--r--include/linux/fs.h198
-rw-r--r--include/linux/fsnotify.h9
-rw-r--r--include/linux/fuse.h65
-rw-r--r--include/linux/futex.h4
-rw-r--r--include/linux/gfp.h62
-rw-r--r--include/linux/gpio_keys.h1
-rw-r--r--include/linux/hid.h4
-rw-r--r--include/linux/hrtimer.h2
-rw-r--r--include/linux/hugetlb.h11
-rw-r--r--include/linux/i2c-id.h1
-rw-r--r--include/linux/i2c.h5
-rw-r--r--include/linux/i2o.h3
-rw-r--r--include/linux/i8042.h35
-rw-r--r--include/linux/ide.h196
-rw-r--r--include/linux/if_bridge.h2
-rw-r--r--include/linux/if_fddi.h2
-rw-r--r--include/linux/init.h4
-rw-r--r--include/linux/init_task.h14
-rw-r--r--include/linux/inotify.h2
-rw-r--r--include/linux/input.h166
-rw-r--r--include/linux/interrupt.h31
-rw-r--r--include/linux/ioport.h3
-rw-r--r--include/linux/ipc.h31
-rw-r--r--include/linux/ipmi.h10
-rw-r--r--include/linux/ipmi_smi.h38
-rw-r--r--include/linux/isdn.h4
-rw-r--r--include/linux/jbd.h34
-rw-r--r--include/linux/jbd2.h49
-rw-r--r--include/linux/jiffies.h2
-rw-r--r--include/linux/kallsyms.h1
-rw-r--r--include/linux/kbd_diacr.h2
-rw-r--r--include/linux/kd.h10
-rw-r--r--include/linux/kernel.h36
-rw-r--r--include/linux/kernel_stat.h2
-rw-r--r--include/linux/kexec.h35
-rw-r--r--include/linux/key-type.h112
-rw-r--r--include/linux/key.h99
-rw-r--r--include/linux/keyboard.h15
-rw-r--r--include/linux/kprobes.h6
-rw-r--r--include/linux/lguest.h84
-rw-r--r--include/linux/lguest_bus.h51
-rw-r--r--include/linux/lguest_launcher.h136
-rw-r--r--include/linux/libata.h80
-rw-r--r--include/linux/linkage.h6
-rw-r--r--include/linux/list.h11
-rw-r--r--include/linux/lockdep.h8
-rw-r--r--include/linux/log2.h25
-rw-r--r--include/linux/magic.h4
-rw-r--r--include/linux/marker.h129
-rw-r--r--include/linux/mc146818rtc.h3
-rw-r--r--include/linux/memory.h31
-rw-r--r--include/linux/memory_hotplug.h18
-rw-r--r--include/linux/mempolicy.h19
-rw-r--r--include/linux/mlx4/doorbell.h11
-rw-r--r--include/linux/mm.h99
-rw-r--r--include/linux/mm_types.h163
-rw-r--r--include/linux/mmc/sdio_ids.h6
-rw-r--r--include/linux/mmzone.h110
-rw-r--r--include/linux/mod_devicetable.h6
-rw-r--r--include/linux/module.h30
-rw-r--r--include/linux/moduleparam.h18
-rw-r--r--include/linux/mroute.h12
-rw-r--r--include/linux/msg.h1
-rw-r--r--include/linux/mutex.h3
-rw-r--r--include/linux/mv643xx.h328
-rw-r--r--include/linux/mv643xx_eth.h34
-rw-r--r--include/linux/namei.h4
-rw-r--r--include/linux/nbd.h2
-rw-r--r--include/linux/net.h12
-rw-r--r--include/linux/netdevice.h43
-rw-r--r--include/linux/netfilter.h26
-rw-r--r--include/linux/netfilter/Kbuild18
-rw-r--r--include/linux/netfilter/nf_conntrack_amanda.h2
-rw-r--r--include/linux/netfilter/nf_conntrack_ftp.h2
-rw-r--r--include/linux/netfilter/nf_conntrack_h323.h18
-rw-r--r--include/linux/netfilter/nf_conntrack_irc.h2
-rw-r--r--include/linux/netfilter/nf_conntrack_pptp.h4
-rw-r--r--include/linux/netfilter/nf_conntrack_sip.h4
-rw-r--r--include/linux/netfilter/nf_conntrack_tftp.h2
-rw-r--r--include/linux/netfilter/x_tables.h2
-rw-r--r--include/linux/netfilter/xt_sctp.h13
-rw-r--r--include/linux/netfilter_arp/arp_tables.h2
-rw-r--r--include/linux/netfilter_bridge/ebtables.h4
-rw-r--r--include/linux/netfilter_ipv4.h4
-rw-r--r--include/linux/netfilter_ipv4/Kbuild28
-rw-r--r--include/linux/netfilter_ipv4/ip_tables.h2
-rw-r--r--include/linux/netfilter_ipv6/Kbuild2
-rw-r--r--include/linux/netfilter_ipv6/ip6_tables.h2
-rw-r--r--include/linux/netlink.h2
-rw-r--r--include/linux/nfs_fs.h8
-rw-r--r--include/linux/nfsd/export.h11
-rw-r--r--include/linux/nls.h8
-rw-r--r--include/linux/nodemask.h94
-rw-r--r--include/linux/notifier.h17
-rw-r--r--include/linux/nsproxy.h51
-rw-r--r--include/linux/of.h2
-rw-r--r--include/linux/of_device.h5
-rw-r--r--include/linux/of_platform.h4
-rw-r--r--include/linux/oom.h26
-rw-r--r--include/linux/page-isolation.h37
-rw-r--r--include/linux/pageblock-flags.h75
-rw-r--r--include/linux/pagemap.h36
-rw-r--r--include/linux/parport.h23
-rw-r--r--include/linux/pci.h16
-rw-r--r--include/linux/pci_ids.h19
-rw-r--r--include/linux/percpu_counter.h55
-rw-r--r--include/linux/phantom.h6
-rw-r--r--include/linux/pid.h61
-rw-r--r--include/linux/pid_namespace.h49
-rw-r--r--include/linux/pm.h98
-rw-r--r--include/linux/pnp.h6
-rw-r--r--include/linux/poison.h3
-rw-r--r--include/linux/prefetch.h9
-rw-r--r--include/linux/prio_heap.h58
-rw-r--r--include/linux/proc_fs.h22
-rw-r--r--include/linux/profile.h3
-rw-r--r--include/linux/proportions.h119
-rw-r--r--include/linux/quota.h31
-rw-r--r--include/linux/radix-tree.h40
-rw-r--r--include/linux/raid/bitmap.h2
-rw-r--r--include/linux/rcupdate.h14
-rw-r--r--include/linux/reiserfs_fs.h47
-rw-r--r--include/linux/reiserfs_fs_sb.h4
-rw-r--r--include/linux/rtnetlink.h2
-rw-r--r--include/linux/scatterlist.h266
-rw-r--r--include/linux/sched.h360
-rw-r--r--include/linux/screen_info.h90
-rw-r--r--include/linux/security.h1269
-rw-r--r--include/linux/selection.h1
-rw-r--r--include/linux/sem.h1
-rw-r--r--include/linux/seq_file.h2
-rw-r--r--include/linux/serial_core.h6
-rw-r--r--include/linux/shm.h3
-rw-r--r--include/linux/signalfd.h32
-rw-r--r--include/linux/skbuff.h29
-rw-r--r--include/linux/slab.h6
-rw-r--r--include/linux/slub_def.h73
-rw-r--r--include/linux/sm501-regs.h18
-rw-r--r--include/linux/smp.h7
-rw-r--r--include/linux/socket.h1
-rw-r--r--include/linux/spi/at73c213.h25
-rw-r--r--include/linux/spi/spi.h12
-rw-r--r--include/linux/string.h12
-rw-r--r--include/linux/sunrpc/rpc_rdma.h32
-rw-r--r--include/linux/suspend.h169
-rw-r--r--include/linux/swap.h5
-rw-r--r--include/linux/sysctl.h58
-rw-r--r--include/linux/taskstats.h7
-rw-r--r--include/linux/tcp.h2
-rw-r--r--include/linux/tick.h9
-rw-r--r--include/linux/time.h2
-rw-r--r--include/linux/tty.h12
-rw-r--r--include/linux/types.h5
-rw-r--r--include/linux/ufs_fs.h179
-rw-r--r--include/linux/ufs_fs_i.h33
-rw-r--r--include/linux/ufs_fs_sb.h37
-rw-r--r--include/linux/uinput.h4
-rw-r--r--include/linux/usb/gadget.h4
-rw-r--r--include/linux/videodev.h42
-rw-r--r--include/linux/videodev2.h92
-rw-r--r--include/linux/virtio.h110
-rw-r--r--include/linux/virtio_9p.h10
-rw-r--r--include/linux/virtio_blk.h51
-rw-r--r--include/linux/virtio_config.h111
-rw-r--r--include/linux/virtio_console.h12
-rw-r--r--include/linux/virtio_net.h36
-rw-r--r--include/linux/virtio_ring.h122
-rw-r--r--include/linux/vt.h12
-rw-r--r--include/linux/vt_kern.h1
-rw-r--r--include/linux/workqueue.h49
-rw-r--r--include/linux/writeback.h13
-rw-r--r--include/media/saa7146.h1
-rw-r--r--include/media/v4l2-dev.h5
-rw-r--r--include/net/9p/9p.h25
-rw-r--r--include/net/9p/client.h9
-rw-r--r--include/net/9p/conn.h4
-rw-r--r--include/net/9p/transport.h27
-rw-r--r--include/net/af_unix.h2
-rw-r--r--include/net/bluetooth/hci.h604
-rw-r--r--include/net/bluetooth/hci_core.h13
-rw-r--r--include/net/bluetooth/l2cap.h37
-rw-r--r--include/net/dst.h7
-rw-r--r--include/net/esp.h2
-rw-r--r--include/net/fib_rules.h3
-rw-r--r--include/net/inet_common.h4
-rw-r--r--include/net/inet_frag.h67
-rw-r--r--include/net/inet_hashtables.h78
-rw-r--r--include/net/inet_sock.h7
-rw-r--r--include/net/inetpeer.h2
-rw-r--r--include/net/ip.h13
-rw-r--r--include/net/ip_fib.h15
-rw-r--r--include/net/ip_vs.h21
-rw-r--r--include/net/ipv6.h32
-rw-r--r--include/net/irda/ircomm_tty.h1
-rw-r--r--include/net/irda/irttp.h4
-rw-r--r--include/net/mac80211.h26
-rw-r--r--include/net/net_namespace.h33
-rw-r--r--include/net/netfilter/ipv6/nf_conntrack_ipv6.h5
-rw-r--r--include/net/netfilter/nf_conntrack_core.h10
-rw-r--r--include/net/netfilter/nf_conntrack_helper.h2
-rw-r--r--include/net/netfilter/nf_nat_core.h4
-rw-r--r--include/net/netfilter/nf_nat_helper.h6
-rw-r--r--include/net/netfilter/nf_nat_protocol.h2
-rw-r--r--include/net/netfilter/nf_nat_rule.h2
-rw-r--r--include/net/protocol.h2
-rw-r--r--include/net/request_sock.h18
-rw-r--r--include/net/sch_generic.h15
-rw-r--r--include/net/scm.h4
-rw-r--r--include/net/sctp/auth.h3
-rw-r--r--include/net/sctp/command.h1
-rw-r--r--include/net/sctp/constants.h3
-rw-r--r--include/net/sctp/sctp.h6
-rw-r--r--include/net/sctp/structs.h22
-rw-r--r--include/net/sock.h111
-rw-r--r--include/net/tcp.h2
-rw-r--r--include/net/xfrm.h37
-rw-r--r--include/pcmcia/cs_types.h2
-rw-r--r--include/pcmcia/ds.h1
-rw-r--r--include/rdma/ib_verbs.h2
-rw-r--r--include/scsi/Kbuild4
-rw-r--r--include/scsi/libsas.h2
-rw-r--r--include/scsi/scsi.h7
-rw-r--r--include/scsi/scsi_cmnd.h7
-rw-r--r--include/scsi/scsi_device.h25
-rw-r--r--include/scsi/scsi_eh.h2
-rw-r--r--include/scsi/scsi_host.h13
-rw-r--r--include/sound/ac97_codec.h8
-rw-r--r--include/sound/ad1848.h5
-rw-r--r--include/sound/ainstr_gf1.h2
-rw-r--r--include/sound/ainstr_iw.h2
-rw-r--r--include/sound/ainstr_simple.h2
-rw-r--r--include/sound/ak4114.h2
-rw-r--r--include/sound/ak4117.h2
-rw-r--r--include/sound/ak4531_codec.h2
-rw-r--r--include/sound/ak4xxx-adda.h2
-rw-r--r--include/sound/asequencer.h2
-rw-r--r--include/sound/asound.h3
-rw-r--r--include/sound/asound_fm.h2
-rw-r--r--include/sound/asoundef.h2
-rw-r--r--include/sound/control.h10
-rw-r--r--include/sound/core.h2
-rw-r--r--include/sound/cs4231-regs.h180
-rw-r--r--include/sound/cs4231.h159
-rw-r--r--include/sound/cs46xx.h2
-rw-r--r--include/sound/cs46xx_dsp_scb_types.h2
-rw-r--r--include/sound/cs46xx_dsp_spos.h2
-rw-r--r--include/sound/cs46xx_dsp_task_types.h2
-rw-r--r--include/sound/cs8403.h2
-rw-r--r--include/sound/cs8427.h2
-rw-r--r--include/sound/driver.h2
-rw-r--r--include/sound/emu10k1.h15
-rw-r--r--include/sound/es1688.h2
-rw-r--r--include/sound/gus.h2
-rw-r--r--include/sound/hda_hwdep.h44
-rw-r--r--include/sound/hdspm.h16
-rw-r--r--include/sound/hwdep.h2
-rw-r--r--include/sound/info.h2
-rw-r--r--include/sound/initval.h2
-rw-r--r--include/sound/memalloc.h2
-rw-r--r--include/sound/mixer_oss.h2
-rw-r--r--include/sound/mpu401.h3
-rw-r--r--include/sound/opl3.h2
-rw-r--r--include/sound/pcm-indirect.h2
-rw-r--r--include/sound/pcm.h13
-rw-r--r--include/sound/pcm_oss.h2
-rw-r--r--include/sound/rawmidi.h2
-rw-r--r--include/sound/sb.h2
-rw-r--r--include/sound/seq_instr.h2
-rw-r--r--include/sound/seq_midi_event.h2
-rw-r--r--include/sound/seq_virmidi.h2
-rw-r--r--include/sound/soc.h3
-rw-r--r--include/sound/tea575x-tuner.h2
-rw-r--r--include/sound/timer.h2
-rw-r--r--include/sound/tlv.h2
-rw-r--r--include/sound/version.h4
-rw-r--r--include/sound/ymfpci.h2
-rw-r--r--include/video/Kbuild3
-rw-r--r--include/video/edid.h9
-rw-r--r--include/video/mbxfb.h53
-rw-r--r--include/video/permedia2.h17
-rw-r--r--include/video/pm3fb.h1272
-rw-r--r--include/video/sstfb.h1
-rw-r--r--include/video/tdfx.h270
-rw-r--r--include/video/uvesafb.h193
-rw-r--r--include/xen/interface/vcpu.h5
-rw-r--r--init/Kconfig64
-rw-r--r--init/Makefile2
-rw-r--r--init/calibrate.c2
-rw-r--r--init/do_mounts_rd.c6
-rw-r--r--init/main.c17
-rw-r--r--ipc/ipc_sysctl.c4
-rw-r--r--ipc/mqueue.c33
-rw-r--r--ipc/msg.c253
-rw-r--r--ipc/sem.c308
-rw-r--r--ipc/shm.c334
-rw-r--r--ipc/util.c506
-rw-r--r--ipc/util.h168
-rw-r--r--kernel/Kconfig.instrumentation49
-rw-r--r--kernel/Kconfig.preempt3
-rw-r--r--kernel/Makefile10
-rw-r--r--kernel/acct.c66
-rw-r--r--kernel/audit.c101
-rw-r--r--kernel/audit.h34
-rw-r--r--kernel/audit_tree.c903
-rw-r--r--kernel/auditfilter.c68
-rw-r--r--kernel/auditsc.c240
-rw-r--r--kernel/capability.c204
-rw-r--r--kernel/cgroup.c2803
-rw-r--r--kernel/cgroup_debug.c97
-rw-r--r--kernel/compat.c117
-rw-r--r--kernel/cpu.c14
-rw-r--r--kernel/cpuset.c1736
-rw-r--r--kernel/delayacct.c6
-rw-r--r--kernel/die_notifier.c38
-rw-r--r--kernel/dma.c8
-rw-r--r--kernel/exec_domain.c2
-rw-r--r--kernel/exit.c270
-rw-r--r--kernel/fork.c179
-rw-r--r--kernel/futex.c44
-rw-r--r--kernel/futex_compat.c29
-rw-r--r--kernel/hrtimer.c35
-rw-r--r--kernel/irq/chip.c3
-rw-r--r--kernel/irq/handle.c8
-rw-r--r--kernel/irq/manage.c51
-rw-r--r--kernel/itimer.c4
-rw-r--r--kernel/kexec.c285
-rw-r--r--kernel/kprobes.c62
-rw-r--r--kernel/ksysfs.c10
-rw-r--r--kernel/lockdep.c26
-rw-r--r--kernel/marker.c518
-rw-r--r--kernel/module.c198
-rw-r--r--kernel/notifier.c539
-rw-r--r--kernel/ns_cgroup.c100
-rw-r--r--kernel/nsproxy.c65
-rw-r--r--kernel/panic.c12
-rw-r--r--kernel/params.c26
-rw-r--r--kernel/pid.c355
-rw-r--r--kernel/posix-cpu-timers.c12
-rw-r--r--kernel/posix-timers.c24
-rw-r--r--kernel/power/Kconfig11
-rw-r--r--kernel/power/disk.c168
-rw-r--r--kernel/power/main.c48
-rw-r--r--kernel/power/power.h21
-rw-r--r--kernel/power/process.c141
-rw-r--r--kernel/power/snapshot.c62
-rw-r--r--kernel/power/swsusp.c33
-rw-r--r--kernel/power/user.c4
-rw-r--r--kernel/printk.c127
-rw-r--r--kernel/profile.c11
-rw-r--r--kernel/ptrace.c18
-rw-r--r--kernel/rcupdate.c1
-rw-r--r--kernel/rcutorture.c10
-rw-r--r--kernel/relay.c6
-rw-r--r--kernel/resource.c26
-rw-r--r--kernel/rtmutex-debug.c22
-rw-r--r--kernel/rtmutex.c2
-rw-r--r--kernel/sched.c829
-rw-r--r--kernel/sched_debug.c9
-rw-r--r--kernel/sched_fair.c152
-rw-r--r--kernel/sched_idletask.c18
-rw-r--r--kernel/sched_rt.c32
-rw-r--r--kernel/sched_stats.h19
-rw-r--r--kernel/signal.c97
-rw-r--r--kernel/softlockup.c54
-rw-r--r--kernel/sys.c587
-rw-r--r--kernel/sys_ni.c8
-rw-r--r--kernel/sysctl.c359
-rw-r--r--kernel/sysctl_check.c1589
-rw-r--r--kernel/taskstats.c70
-rw-r--r--kernel/time.c21
-rw-r--r--kernel/time/clocksource.c22
-rw-r--r--kernel/time/tick-broadcast.c37
-rw-r--r--kernel/time/tick-sched.c18
-rw-r--r--kernel/time/timekeeping.c12
-rw-r--r--kernel/time/timer_list.c6
-rw-r--r--kernel/timer.c29
-rw-r--r--kernel/tsacct.c4
-rw-r--r--kernel/user.c40
-rw-r--r--kernel/workqueue.c38
-rw-r--r--lib/Kconfig.debug38
-rw-r--r--lib/Makefile7
-rw-r--r--lib/argv_split.c7
-rw-r--r--lib/bitmap.c4
-rw-r--r--lib/bust_spinlocks.c6
-rw-r--r--lib/crc32.c12
-rw-r--r--lib/hweight.c2
-rw-r--r--lib/idr.c3
-rw-r--r--lib/iomap.c2
-rw-r--r--lib/ioremap.c1
-rw-r--r--lib/kernel_lock.c2
-rw-r--r--lib/kobject.c13
-rw-r--r--lib/kobject_uevent.c2
-rw-r--r--lib/libcrc32c.c13
-rw-r--r--lib/percpu_counter.c53
-rw-r--r--lib/prio_heap.c70
-rw-r--r--lib/proportions.c384
-rw-r--r--lib/radix-tree.c148
-rw-r--r--lib/reed_solomon/decode_rs.c5
-rw-r--r--lib/reed_solomon/reed_solomon.c2
-rw-r--r--lib/sort.c2
-rw-r--r--lib/spinlock_debug.c8
-rw-r--r--lib/swiotlb.c23
-rw-r--r--mm/Kconfig21
-rw-r--r--mm/Makefile3
-rw-r--r--mm/backing-dev.c47
-rw-r--r--mm/bounce.c6
-rw-r--r--mm/filemap.c814
-rw-r--r--mm/filemap.h103
-rw-r--r--mm/filemap_xip.c17
-rw-r--r--mm/fremap.c26
-rw-r--r--mm/hugetlb.c471
-rw-r--r--mm/internal.h10
-rw-r--r--mm/memory.c171
-rw-r--r--mm/memory_hotplug.c358
-rw-r--r--mm/mempolicy.c86
-rw-r--r--mm/mempool.c2
-rw-r--r--mm/migrate.c9
-rw-r--r--mm/mmap.c17
-rw-r--r--mm/mprotect.c7
-rw-r--r--mm/mremap.c4
-rw-r--r--mm/nommu.c5
-rw-r--r--mm/oom_kill.c131
-rw-r--r--mm/page-writeback.c331
-rw-r--r--mm/page_alloc.c742
-rw-r--r--mm/page_isolation.c138
-rw-r--r--mm/prio_tree.c2
-rw-r--r--mm/readahead.c94
-rw-r--r--mm/rmap.c12
-rw-r--r--mm/shmem.c134
-rw-r--r--mm/slab.c350
-rw-r--r--mm/slob.c16
-rw-r--r--mm/slub.c652
-rw-r--r--mm/sparse-vmemmap.c149
-rw-r--r--mm/sparse.c110
-rw-r--r--mm/swap.c113
-rw-r--r--mm/swap_state.c5
-rw-r--r--mm/tiny-shmem.c19
-rw-r--r--mm/truncate.c3
-rw-r--r--mm/util.c10
-rw-r--r--mm/vmalloc.c11
-rw-r--r--mm/vmscan.c103
-rw-r--r--mm/vmstat.c307
-rw-r--r--net/8021q/vlan.c6
-rw-r--r--net/8021q/vlan.h1
-rw-r--r--net/8021q/vlan_dev.c26
-rw-r--r--net/9p/Kconfig19
-rw-r--r--net/9p/Makefile9
-rw-r--r--net/9p/client.c13
-rw-r--r--net/9p/conv.c32
-rw-r--r--net/9p/mod.c71
-rw-r--r--net/9p/mux.c9
-rw-r--r--net/9p/sysctl.c81
-rw-r--r--net/9p/trans_fd.c420
-rw-r--r--net/9p/trans_virtio.c353
-rw-r--r--net/appletalk/ddp.c2
-rw-r--r--net/atm/br2684.c121
-rw-r--r--net/atm/common.c2
-rw-r--r--net/ax25/af_ax25.c6
-rw-r--r--net/ax25/ax25_ds_in.c2
-rw-r--r--net/ax25/ax25_ds_subr.c2
-rw-r--r--net/bluetooth/bnep/core.c2
-rw-r--r--net/bluetooth/bnep/netdev.c2
-rw-r--r--net/bluetooth/bnep/sock.c2
-rw-r--r--net/bluetooth/cmtp/sock.c2
-rw-r--r--net/bluetooth/hci_conn.c82
-rw-r--r--net/bluetooth/hci_core.c70
-rw-r--r--net/bluetooth/hci_event.c1651
-rw-r--r--net/bluetooth/hci_sock.c4
-rw-r--r--net/bluetooth/hci_sysfs.c37
-rw-r--r--net/bluetooth/hidp/core.c14
-rw-r--r--net/bluetooth/hidp/sock.c2
-rw-r--r--net/bluetooth/l2cap.c308
-rw-r--r--net/bluetooth/rfcomm/core.c60
-rw-r--r--net/bluetooth/rfcomm/sock.c2
-rw-r--r--net/bluetooth/rfcomm/tty.c25
-rw-r--r--net/bluetooth/sco.c14
-rw-r--r--net/bridge/br.c2
-rw-r--r--net/bridge/br_input.c6
-rw-r--r--net/bridge/br_netfilter.c39
-rw-r--r--net/bridge/netfilter/ebt_arp.c2
-rw-r--r--net/bridge/netfilter/ebt_arpreply.c3
-rw-r--r--net/bridge/netfilter/ebt_dnat.c17
-rw-r--r--net/bridge/netfilter/ebt_mark.c10
-rw-r--r--net/bridge/netfilter/ebt_redirect.c21
-rw-r--r--net/bridge/netfilter/ebt_snat.c23
-rw-r--r--net/bridge/netfilter/ebtable_broute.c4
-rw-r--r--net/bridge/netfilter/ebtable_filter.c4
-rw-r--r--net/bridge/netfilter/ebtable_nat.c8
-rw-r--r--net/bridge/netfilter/ebtables.c14
-rw-r--r--net/core/dev.c261
-rw-r--r--net/core/dev_mcast.c14
-rw-r--r--net/core/dst.c1
-rw-r--r--net/core/fib_rules.c22
-rw-r--r--net/core/filter.c59
-rw-r--r--net/core/flow.c5
-rw-r--r--net/core/gen_estimator.c2
-rw-r--r--net/core/neighbour.c82
-rw-r--r--net/core/net-sysfs.c2
-rw-r--r--net/core/net-sysfs.h8
-rw-r--r--net/core/net_namespace.c182
-rw-r--r--net/core/netpoll.c41
-rw-r--r--net/core/pktgen.c20
-rw-r--r--net/core/request_sock.c35
-rw-r--r--net/core/rtnetlink.c10
-rw-r--r--net/core/scm.c4
-rw-r--r--net/core/skbuff.c213
-rw-r--r--net/core/sock.c195
-rw-r--r--net/core/sysctl_net_core.c17
-rw-r--r--net/dccp/ccids/ccid2.c4
-rw-r--r--net/dccp/ccids/ccid3.c15
-rw-r--r--net/dccp/diag.c1
-rw-r--r--net/dccp/input.c51
-rw-r--r--net/dccp/ipv4.c13
-rw-r--r--net/dccp/ipv6.c14
-rw-r--r--net/dccp/options.c33
-rw-r--r--net/dccp/proto.c42
-rw-r--r--net/dccp/sysctl.c3
-rw-r--r--net/decnet/af_decnet.c2
-rw-r--r--net/decnet/dn_dev.c2
-rw-r--r--net/decnet/dn_route.c16
-rw-r--r--net/decnet/dn_rules.c13
-rw-r--r--net/decnet/netfilter/dn_rtmsg.c4
-rw-r--r--net/econet/af_econet.c2
-rw-r--r--net/ethernet/eth.c9
-rw-r--r--net/ieee80211/ieee80211_crypt_ccmp.c1
-rw-r--r--net/ieee80211/ieee80211_crypt_tkip.c22
-rw-r--r--net/ieee80211/ieee80211_crypt_wep.c10
-rw-r--r--net/ieee80211/ieee80211_wx.c2
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_wx.c2
-rw-r--r--net/ipv4/Kconfig2
-rw-r--r--net/ipv4/Makefile3
-rw-r--r--net/ipv4/af_inet.c2
-rw-r--r--net/ipv4/ah4.c1
-rw-r--r--net/ipv4/cipso_ipv4.c39
-rw-r--r--net/ipv4/esp4.c13
-rw-r--r--net/ipv4/fib_frontend.c27
-rw-r--r--net/ipv4/fib_rules.c51
-rw-r--r--net/ipv4/fib_trie.c2
-rw-r--r--net/ipv4/icmp.c1
-rw-r--r--net/ipv4/inet_connection_sock.c2
-rw-r--r--net/ipv4/inet_diag.c16
-rw-r--r--net/ipv4/inet_fragment.c261
-rw-r--r--net/ipv4/inet_hashtables.c9
-rw-r--r--net/ipv4/inet_timewait_sock.c13
-rw-r--r--net/ipv4/inetpeer.c42
-rw-r--r--net/ipv4/ip_forward.c2
-rw-r--r--net/ipv4/ip_fragment.c514
-rw-r--r--net/ipv4/ip_gre.c14
-rw-r--r--net/ipv4/ip_input.c10
-rw-r--r--net/ipv4/ip_output.c32
-rw-r--r--net/ipv4/ip_sockglue.c39
-rw-r--r--net/ipv4/ipcomp.c4
-rw-r--r--net/ipv4/ipip.c2
-rw-r--r--net/ipv4/ipvs/ip_vs_app.c33
-rw-r--r--net/ipv4/ipvs/ip_vs_conn.c18
-rw-r--r--net/ipv4/ipvs/ip_vs_core.c124
-rw-r--r--net/ipv4/ipvs/ip_vs_ctl.c25
-rw-r--r--net/ipv4/ipvs/ip_vs_ftp.c19
-rw-r--r--net/ipv4/ipvs/ip_vs_lblcr.c76
-rw-r--r--net/ipv4/ipvs/ip_vs_proto_tcp.c51
-rw-r--r--net/ipv4/ipvs/ip_vs_proto_udp.c51
-rw-r--r--net/ipv4/ipvs/ip_vs_sync.c35
-rw-r--r--net/ipv4/ipvs/ip_vs_xmit.c8
-rw-r--r--net/ipv4/netfilter.c77
-rw-r--r--net/ipv4/netfilter/Kconfig4
-rw-r--r--net/ipv4/netfilter/Makefile20
-rw-r--r--net/ipv4/netfilter/arp_tables.c20
-rw-r--r--net/ipv4/netfilter/arpt_mangle.c28
-rw-r--r--net/ipv4/netfilter/arptable_filter.c4
-rw-r--r--net/ipv4/netfilter/ip_queue.c61
-rw-r--r--net/ipv4/netfilter/ip_tables.c20
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c14
-rw-r--r--net/ipv4/netfilter/ipt_ECN.c27
-rw-r--r--net/ipv4/netfilter/ipt_LOG.c4
-rw-r--r--net/ipv4/netfilter/ipt_MASQUERADE.c6
-rw-r--r--net/ipv4/netfilter/ipt_NETMAP.c8
-rw-r--r--net/ipv4/netfilter/ipt_REDIRECT.c6
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c22
-rw-r--r--net/ipv4/netfilter/ipt_SAME.c4
-rw-r--r--net/ipv4/netfilter/ipt_TOS.c8
-rw-r--r--net/ipv4/netfilter/ipt_TTL.c6
-rw-r--r--net/ipv4/netfilter/ipt_ULOG.c4
-rw-r--r--net/ipv4/netfilter/iptable_filter.c12
-rw-r--r--net/ipv4/netfilter/iptable_mangle.c22
-rw-r--r--net/ipv4/netfilter/iptable_raw.c12
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c48
-rw-r--r--net/ipv4/netfilter/nf_conntrack_proto_icmp.c2
-rw-r--r--net/ipv4/netfilter/nf_nat_amanda.c6
-rw-r--r--net/ipv4/netfilter/nf_nat_core.c52
-rw-r--r--net/ipv4/netfilter/nf_nat_ftp.c20
-rw-r--r--net/ipv4/netfilter/nf_nat_h323.c76
-rw-r--r--net/ipv4/netfilter/nf_nat_helper.c118
-rw-r--r--net/ipv4/netfilter/nf_nat_irc.c6
-rw-r--r--net/ipv4/netfilter/nf_nat_pptp.c16
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_gre.c8
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_icmp.c10
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_tcp.c16
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_udp.c16
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_unknown.c2
-rw-r--r--net/ipv4/netfilter/nf_nat_rule.c14
-rw-r--r--net/ipv4/netfilter/nf_nat_sip.c60
-rw-r--r--net/ipv4/netfilter/nf_nat_snmp_basic.c14
-rw-r--r--net/ipv4/netfilter/nf_nat_standalone.c62
-rw-r--r--net/ipv4/netfilter/nf_nat_tftp.c4
-rw-r--r--net/ipv4/proc.c33
-rw-r--r--net/ipv4/raw.c3
-rw-r--r--net/ipv4/route.c20
-rw-r--r--net/ipv4/sysctl_net_ipv4.c15
-rw-r--r--net/ipv4/tcp.c8
-rw-r--r--net/ipv4/tcp_diag.c1
-rw-r--r--net/ipv4/tcp_input.c193
-rw-r--r--net/ipv4/tcp_ipv4.c29
-rw-r--r--net/ipv4/tcp_vegas.c37
-rw-r--r--net/ipv4/tunnel4.c24
-rw-r--r--net/ipv4/udp.c10
-rw-r--r--net/ipv4/udplite.c3
-rw-r--r--net/ipv4/xfrm4_input.c40
-rw-r--r--net/ipv4/xfrm4_mode_beet.c1
-rw-r--r--net/ipv4/xfrm4_mode_tunnel.c1
-rw-r--r--net/ipv4/xfrm4_output.c6
-rw-r--r--net/ipv4/xfrm4_policy.c27
-rw-r--r--net/ipv4/xfrm4_state.c1
-rw-r--r--net/ipv4/xfrm4_tunnel.c11
-rw-r--r--net/ipv6/addrconf.c14
-rw-r--r--net/ipv6/af_inet6.c3
-rw-r--r--net/ipv6/ah6.c13
-rw-r--r--net/ipv6/esp6.c23
-rw-r--r--net/ipv6/exthdrs.c64
-rw-r--r--net/ipv6/fib6_rules.c37
-rw-r--r--net/ipv6/icmp.c5
-rw-r--r--net/ipv6/inet6_connection_sock.c2
-rw-r--r--net/ipv6/inet6_hashtables.c21
-rw-r--r--net/ipv6/ip6_flowlabel.c57
-rw-r--r--net/ipv6/ip6_input.c6
-rw-r--r--net/ipv6/ip6_output.c40
-rw-r--r--net/ipv6/ip6_tunnel.c2
-rw-r--r--net/ipv6/ipcomp6.c13
-rw-r--r--net/ipv6/ndisc.c25
-rw-r--r--net/ipv6/netfilter.c6
-rw-r--r--net/ipv6/netfilter/Makefile28
-rw-r--r--net/ipv6/netfilter/ip6_queue.c57
-rw-r--r--net/ipv6/netfilter/ip6_tables.c16
-rw-r--r--net/ipv6/netfilter/ip6t_HL.c6
-rw-r--r--net/ipv6/netfilter/ip6t_LOG.c5
-rw-r--r--net/ipv6/netfilter/ip6t_REJECT.c14
-rw-r--r--net/ipv6/netfilter/ip6table_filter.c12
-rw-r--r--net/ipv6/netfilter/ip6table_mangle.c32
-rw-r--r--net/ipv6/netfilter/ip6table_raw.c4
-rw-r--r--net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c52
-rw-r--r--net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c1
-rw-r--r--net/ipv6/netfilter/nf_conntrack_reasm.c368
-rw-r--r--net/ipv6/proc.c21
-rw-r--r--net/ipv6/raw.c3
-rw-r--r--net/ipv6/reassembly.c432
-rw-r--r--net/ipv6/route.c175
-rw-r--r--net/ipv6/sit.c2
-rw-r--r--net/ipv6/sysctl_net_ipv6.c9
-rw-r--r--net/ipv6/tcp_ipv6.c23
-rw-r--r--net/ipv6/tunnel6.c6
-rw-r--r--net/ipv6/udp.c15
-rw-r--r--net/ipv6/udp_impl.h2
-rw-r--r--net/ipv6/udplite.c7
-rw-r--r--net/ipv6/xfrm6_input.c16
-rw-r--r--net/ipv6/xfrm6_mode_beet.c1
-rw-r--r--net/ipv6/xfrm6_mode_ro.c9
-rw-r--r--net/ipv6/xfrm6_mode_tunnel.c1
-rw-r--r--net/ipv6/xfrm6_output.c6
-rw-r--r--net/ipv6/xfrm6_policy.c17
-rw-r--r--net/ipv6/xfrm6_state.c7
-rw-r--r--net/ipv6/xfrm6_tunnel.c4
-rw-r--r--net/ipx/af_ipx.c24
-rw-r--r--net/irda/af_irda.c2
-rw-r--r--net/irda/discovery.c2
-rw-r--r--net/irda/ircomm/ircomm_tty.c2
-rw-r--r--net/irda/ircomm/ircomm_tty_attach.c15
-rw-r--r--net/irda/iriap.c2
-rw-r--r--net/irda/iriap_event.c2
-rw-r--r--net/irda/irias_object.c2
-rw-r--r--net/irda/irlan/irlan_client.c2
-rw-r--r--net/irda/irlan/irlan_client_event.c2
-rw-r--r--net/irda/irlan/irlan_common.c2
-rw-r--r--net/irda/irlan/irlan_eth.c2
-rw-r--r--net/irda/irlan/irlan_event.c2
-rw-r--r--net/irda/irlan/irlan_filter.c2
-rw-r--r--net/irda/irlan/irlan_provider.c2
-rw-r--r--net/irda/irlan/irlan_provider_event.c2
-rw-r--r--net/irda/irlap_event.c2
-rw-r--r--net/irda/irlap_frame.c2
-rw-r--r--net/irda/irlmp.c2
-rw-r--r--net/irda/irlmp_event.c2
-rw-r--r--net/irda/irlmp_frame.c2
-rw-r--r--net/irda/irmod.c2
-rw-r--r--net/irda/irnet/irnet_ppp.c10
-rw-r--r--net/irda/irqueue.c2
-rw-r--r--net/irda/irsysctl.c36
-rw-r--r--net/irda/irttp.c2
-rw-r--r--net/irda/timer.c2
-rw-r--r--net/irda/wrapper.c2
-rw-r--r--net/iucv/af_iucv.c2
-rw-r--r--net/iucv/iucv.c2
-rw-r--r--net/key/af_key.c6
-rw-r--r--net/llc/af_llc.c2
-rw-r--r--net/llc/llc_conn.c2
-rw-r--r--net/mac80211/Kconfig12
-rw-r--r--net/mac80211/Makefile3
-rw-r--r--net/mac80211/aes_ccm.c1
-rw-r--r--net/mac80211/ieee80211.c16
-rw-r--r--net/mac80211/ieee80211_common.h91
-rw-r--r--net/mac80211/ieee80211_i.h6
-rw-r--r--net/mac80211/ieee80211_ioctl.c37
-rw-r--r--net/mac80211/ieee80211_rate.c24
-rw-r--r--net/mac80211/ieee80211_rate.h3
-rw-r--r--net/mac80211/ieee80211_sta.c155
-rw-r--r--net/mac80211/rc80211_simple.c25
-rw-r--r--net/mac80211/rx.c2
-rw-r--r--net/mac80211/wep.c12
-rw-r--r--net/mac80211/wpa.c18
-rw-r--r--net/netfilter/Kconfig2
-rw-r--r--net/netfilter/Makefile14
-rw-r--r--net/netfilter/core.c48
-rw-r--r--net/netfilter/nf_conntrack_amanda.c20
-rw-r--r--net/netfilter/nf_conntrack_core.c32
-rw-r--r--net/netfilter/nf_conntrack_extend.c2
-rw-r--r--net/netfilter/nf_conntrack_ftp.c18
-rw-r--r--net/netfilter/nf_conntrack_h323_main.c236
-rw-r--r--net/netfilter/nf_conntrack_irc.c16
-rw-r--r--net/netfilter/nf_conntrack_netbios_ns.c10
-rw-r--r--net/netfilter/nf_conntrack_pptp.c28
-rw-r--r--net/netfilter/nf_conntrack_proto_generic.c2
-rw-r--r--net/netfilter/nf_conntrack_proto_sctp.c14
-rw-r--r--net/netfilter/nf_conntrack_proto_tcp.c29
-rw-r--r--net/netfilter/nf_conntrack_proto_udp.c4
-rw-r--r--net/netfilter/nf_conntrack_sane.c10
-rw-r--r--net/netfilter/nf_conntrack_sip.c24
-rw-r--r--net/netfilter/nf_conntrack_tftp.c8
-rw-r--r--net/netfilter/nf_internals.h2
-rw-r--r--net/netfilter/nf_queue.c4
-rw-r--r--net/netfilter/nf_sockopt.c117
-rw-r--r--net/netfilter/nfnetlink_queue.c20
-rw-r--r--net/netfilter/xt_CLASSIFY.c4
-rw-r--r--net/netfilter/xt_CONNMARK.c16
-rw-r--r--net/netfilter/xt_CONNSECMARK.c3
-rw-r--r--net/netfilter/xt_DSCP.c16
-rw-r--r--net/netfilter/xt_MARK.c12
-rw-r--r--net/netfilter/xt_NFLOG.c4
-rw-r--r--net/netfilter/xt_NFQUEUE.c2
-rw-r--r--net/netfilter/xt_NOTRACK.c10
-rw-r--r--net/netfilter/xt_SECMARK.c4
-rw-r--r--net/netfilter/xt_TCPMSS.c58
-rw-r--r--net/netfilter/xt_TRACE.c4
-rw-r--r--net/netfilter/xt_connbytes.c2
-rw-r--r--net/netfilter/xt_connlimit.c5
-rw-r--r--net/netfilter/xt_connmark.c2
-rw-r--r--net/netfilter/xt_limit.c4
-rw-r--r--net/netfilter/xt_sctp.c18
-rw-r--r--net/netfilter/xt_time.c5
-rw-r--r--net/netfilter/xt_u32.c5
-rw-r--r--net/netlabel/netlabel_domainhash.c37
-rw-r--r--net/netlabel/netlabel_mgmt.c4
-rw-r--r--net/netlabel/netlabel_unlabeled.c4
-rw-r--r--net/netlink/af_netlink.c30
-rw-r--r--net/netrom/af_netrom.c6
-rw-r--r--net/packet/af_packet.c38
-rw-r--r--net/rfkill/rfkill-input.c12
-rw-r--r--net/rfkill/rfkill.c37
-rw-r--r--net/rose/af_rose.c6
-rw-r--r--net/rxrpc/af_rxrpc.c3
-rw-r--r--net/rxrpc/ar-key.c32
-rw-r--r--net/rxrpc/ar-local.c4
-rw-r--r--net/rxrpc/rxkad.c61
-rw-r--r--net/sched/Kconfig10
-rw-r--r--net/sched/act_ipt.c6
-rw-r--r--net/sched/act_mirred.c2
-rw-r--r--net/sched/cls_u32.c14
-rw-r--r--net/sched/em_meta.c2
-rw-r--r--net/sched/sch_generic.c38
-rw-r--r--net/sched/sch_ingress.c5
-rw-r--r--net/sched/sch_prio.c4
-rw-r--r--net/sched/sch_teql.c9
-rw-r--r--net/sctp/associola.c10
-rw-r--r--net/sctp/auth.c14
-rw-r--r--net/sctp/bind_addr.c13
-rw-r--r--net/sctp/crc32c.c2
-rw-r--r--net/sctp/endpointola.c35
-rw-r--r--net/sctp/input.c43
-rw-r--r--net/sctp/inqueue.c4
-rw-r--r--net/sctp/ipv6.c6
-rw-r--r--net/sctp/outqueue.c41
-rw-r--r--net/sctp/proc.c6
-rw-r--r--net/sctp/protocol.c11
-rw-r--r--net/sctp/sm_make_chunk.c180
-rw-r--r--net/sctp/sm_sideeffect.c10
-rw-r--r--net/sctp/sm_statefuns.c12
-rw-r--r--net/sctp/socket.c22
-rw-r--r--net/sctp/sysctl.c9
-rw-r--r--net/sctp/transport.c5
-rw-r--r--net/sctp/ulpqueue.c36
-rw-r--r--net/socket.c31
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_crypto.c48
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_seal.c1
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_wrap.c1
-rw-r--r--net/sunrpc/auth_gss/gss_spkm3_seal.c2
-rw-r--r--net/sunrpc/rpc_pipe.c2
-rw-r--r--net/sunrpc/sched.c2
-rw-r--r--net/sunrpc/sysctl.c7
-rw-r--r--net/sunrpc/xdr.c6
-rw-r--r--net/sunrpc/xprtrdma/rpc_rdma.c34
-rw-r--r--net/sunrpc/xprtrdma/transport.c2
-rw-r--r--net/sunrpc/xprtrdma/verbs.c3
-rw-r--r--net/tipc/socket.c2
-rw-r--r--net/unix/af_unix.c17
-rw-r--r--net/unix/garbage.c26
-rw-r--r--net/x25/af_x25.c2
-rw-r--r--net/xfrm/xfrm_algo.c12
-rw-r--r--net/xfrm/xfrm_input.c5
-rw-r--r--net/xfrm/xfrm_output.c4
-rw-r--r--net/xfrm/xfrm_policy.c179
-rw-r--r--net/xfrm/xfrm_state.c206
-rw-r--r--samples/Kconfig16
-rw-r--r--samples/Makefile3
-rw-r--r--samples/markers/Makefile4
-rw-r--r--samples/markers/marker-example.c55
-rw-r--r--samples/markers/probe-example.c98
-rw-r--r--scripts/Kbuild.include19
-rw-r--r--scripts/Makefile.build45
-rw-r--r--scripts/Makefile.clean2
-rw-r--r--scripts/Makefile.lib30
-rw-r--r--scripts/basic/Makefile8
-rw-r--r--scripts/basic/docproc.c45
-rwxr-xr-xscripts/checkkconfigsymbols.sh59
-rwxr-xr-xscripts/checkpatch.pl580
-rwxr-xr-xscripts/checkstack.pl8
-rw-r--r--scripts/export_report.pl10
-rw-r--r--scripts/gcc-version.sh8
-rw-r--r--scripts/genksyms/Makefile8
-rw-r--r--scripts/genksyms/keywords.c_shipped180
-rw-r--r--scripts/genksyms/keywords.gperf1
-rw-r--r--scripts/genksyms/lex.c_shipped1802
-rw-r--r--scripts/genksyms/parse.c_shipped2088
-rw-r--r--scripts/genksyms/parse.h_shipped159
-rw-r--r--scripts/genksyms/parse.y5
-rw-r--r--scripts/kconfig/Makefile42
-rwxr-xr-xscripts/kconfig/check.sh14
-rw-r--r--scripts/kconfig/conf.c1
-rw-r--r--scripts/kconfig/confdata.c146
-rw-r--r--scripts/kconfig/lex.zconf.c_shipped25
-rw-r--r--scripts/kconfig/lkc_proto.h1
-rw-r--r--scripts/kconfig/mconf.c36
-rw-r--r--scripts/kconfig/qconf.cc4
-rw-r--r--scripts/kconfig/util.c13
-rw-r--r--scripts/kconfig/zconf.gperf2
-rw-r--r--scripts/kconfig/zconf.hash.c_shipped220
-rw-r--r--scripts/kconfig/zconf.tab.c_shipped1406
-rw-r--r--scripts/kconfig/zconf.y11
-rwxr-xr-xscripts/kernel-doc41
-rwxr-xr-xscripts/makelst4
-rw-r--r--scripts/mkmakefile8
-rw-r--r--scripts/mod/file2alias.c58
-rw-r--r--scripts/mod/modpost.c9
-rw-r--r--scripts/mod/modpost.h4
-rw-r--r--scripts/package/builddeb2
-rwxr-xr-xscripts/ver_linux9
-rw-r--r--security/Kconfig16
-rw-r--r--security/capability.c30
-rw-r--r--security/commoncap.c333
-rw-r--r--security/dummy.c47
-rw-r--r--security/inode.c8
-rw-r--r--security/keys/internal.h35
-rw-r--r--security/keys/key.c34
-rw-r--r--security/keys/process_keys.c16
-rw-r--r--security/keys/request_key.c556
-rw-r--r--security/keys/request_key_auth.c11
-rw-r--r--security/root_plug.c31
-rw-r--r--security/security.c1012
-rw-r--r--security/selinux/avc.c5
-rw-r--r--security/selinux/hooks.c166
-rw-r--r--security/selinux/include/avc.h2
-rw-r--r--security/selinux/include/objsec.h2
-rw-r--r--security/selinux/include/security.h2
-rw-r--r--security/selinux/selinuxfs.c26
-rw-r--r--security/selinux/ss/avtab.c123
-rw-r--r--security/selinux/ss/avtab.h21
-rw-r--r--security/selinux/ss/conditional.c7
-rw-r--r--security/selinux/ss/ebitmap.c280
-rw-r--r--security/selinux/ss/ebitmap.h89
-rw-r--r--security/selinux/ss/mls.c204
-rw-r--r--security/selinux/ss/mls.h2
-rw-r--r--security/selinux/ss/policydb.c56
-rw-r--r--security/selinux/ss/policydb.h11
-rw-r--r--security/selinux/ss/services.c91
-rw-r--r--security/selinux/xfrm.c16
-rw-r--r--sound/Kconfig4
-rw-r--r--sound/Makefile3
-rw-r--r--sound/aoa/codecs/snd-aoa-codec-onyx.c20
-rw-r--r--sound/aoa/codecs/snd-aoa-codec-tas.c29
-rw-r--r--sound/aoa/fabrics/snd-aoa-fabric-layout.c10
-rw-r--r--sound/arm/aaci.c4
-rw-r--r--sound/arm/sa11xx-uda1341.c35
-rw-r--r--sound/core/Makefile15
-rw-r--r--sound/core/control.c38
-rw-r--r--sound/core/device.c2
-rw-r--r--sound/core/hwdep.c4
-rw-r--r--sound/core/info.c2
-rw-r--r--sound/core/info_oss.c2
-rw-r--r--sound/core/init.c2
-rw-r--r--sound/core/isadma.c2
-rw-r--r--sound/core/memalloc.c10
-rw-r--r--sound/core/memory.c2
-rw-r--r--sound/core/misc.c2
-rw-r--r--sound/core/oss/Makefile7
-rw-r--r--sound/core/oss/copy.c5
-rw-r--r--sound/core/oss/io.c7
-rw-r--r--sound/core/oss/linear.c91
-rw-r--r--sound/core/oss/mixer_oss.c4
-rw-r--r--sound/core/oss/mulaw.c90
-rw-r--r--sound/core/oss/pcm_oss.c39
-rw-r--r--sound/core/oss/pcm_plugin.c63
-rw-r--r--sound/core/oss/pcm_plugin.h2
-rw-r--r--sound/core/oss/plugin_ops.h370
-rw-r--r--sound/core/oss/rate.c7
-rw-r--r--sound/core/oss/route.c5
-rw-r--r--sound/core/pcm.c4
-rw-r--r--sound/core/pcm_lib.c2
-rw-r--r--sound/core/pcm_memory.c2
-rw-r--r--sound/core/pcm_misc.c65
-rw-r--r--sound/core/pcm_native.c10
-rw-r--r--sound/core/pcm_timer.c2
-rw-r--r--sound/core/rawmidi.c5
-rw-r--r--sound/core/seq/Makefile2
-rw-r--r--sound/core/seq/instr/Makefile2
-rw-r--r--sound/core/seq/instr/ainstr_gf1.c4
-rw-r--r--sound/core/seq/instr/ainstr_iw.c4
-rw-r--r--sound/core/seq/instr/ainstr_simple.c4
-rw-r--r--sound/core/seq/oss/Makefile2
-rw-r--r--sound/core/seq/oss/seq_oss_init.c40
-rw-r--r--sound/core/seq/oss/seq_oss_writeq.c6
-rw-r--r--sound/core/seq/seq.c2
-rw-r--r--sound/core/seq/seq_clientmgr.c2
-rw-r--r--sound/core/seq/seq_instr.c14
-rw-r--r--sound/core/seq/seq_memory.c2
-rw-r--r--sound/core/seq/seq_midi.c4
-rw-r--r--sound/core/seq/seq_midi_emul.c8
-rw-r--r--sound/core/seq/seq_midi_event.c101
-rw-r--r--sound/core/seq/seq_ports.c2
-rw-r--r--sound/core/seq/seq_timer.c2
-rw-r--r--sound/core/sound.c12
-rw-r--r--sound/core/sound_oss.c2
-rw-r--r--sound/core/timer.c4
-rw-r--r--sound/drivers/Makefile2
-rw-r--r--sound/drivers/dummy.c14
-rw-r--r--sound/drivers/mpu401/Makefile2
-rw-r--r--sound/drivers/mpu401/mpu401.c10
-rw-r--r--sound/drivers/mpu401/mpu401_uart.c7
-rw-r--r--sound/drivers/mts64.c12
-rw-r--r--sound/drivers/opl3/Makefile8
-rw-r--r--sound/drivers/opl3/opl3_lib.c4
-rw-r--r--sound/drivers/opl3/opl3_midi.c2
-rw-r--r--sound/drivers/opl4/Makefile2
-rw-r--r--sound/drivers/portman2x4.c2
-rw-r--r--sound/drivers/serial-u16550.c2
-rw-r--r--sound/drivers/vx/Makefile2
-rw-r--r--sound/drivers/vx/vx_mixer.c18
-rw-r--r--sound/i2c/Makefile6
-rw-r--r--sound/i2c/cs8427.c10
-rw-r--r--sound/i2c/i2c.c4
-rw-r--r--sound/i2c/other/Makefile2
-rw-r--r--sound/i2c/other/ak4114.c14
-rw-r--r--sound/i2c/other/ak4117.c14
-rw-r--r--sound/i2c/other/ak4xxx-adda.c14
-rw-r--r--sound/i2c/other/pt2258.c10
-rw-r--r--sound/i2c/other/tea575x-tuner.c5
-rw-r--r--sound/i2c/tea6330t.c14
-rw-r--r--sound/isa/Kconfig22
-rw-r--r--sound/isa/Makefile4
-rw-r--r--sound/isa/ad1816a/Makefile2
-rw-r--r--sound/isa/ad1816a/ad1816a_lib.c2
-rw-r--r--sound/isa/ad1848/Makefile9
-rw-r--r--sound/isa/ad1848/ad1848.c6
-rw-r--r--sound/isa/ad1848/ad1848_lib.c140
-rw-r--r--sound/isa/cs423x/Makefile19
-rw-r--r--sound/isa/cs423x/cs4231.c4
-rw-r--r--sound/isa/cs423x/cs4231_lib.c115
-rw-r--r--sound/isa/cs423x/cs4236.c4
-rw-r--r--sound/isa/cs423x/cs4236_lib.c4
-rw-r--r--sound/isa/es1688/Makefile2
-rw-r--r--sound/isa/es1688/es1688.c4
-rw-r--r--sound/isa/es1688/es1688_lib.c4
-rw-r--r--sound/isa/es18xx.c23
-rw-r--r--sound/isa/gus/Makefile2
-rw-r--r--sound/isa/gus/gus_dma.c2
-rw-r--r--sound/isa/gus/gus_dram.c2
-rw-r--r--sound/isa/gus/gus_instr.c2
-rw-r--r--sound/isa/gus/gus_io.c2
-rw-r--r--sound/isa/gus/gus_irq.c20
-rw-r--r--sound/isa/gus/gus_main.c22
-rw-r--r--sound/isa/gus/gus_mem.c2
-rw-r--r--sound/isa/gus/gus_mem_proc.c2
-rw-r--r--sound/isa/gus/gus_mixer.c11
-rw-r--r--sound/isa/gus/gus_pcm.c2
-rw-r--r--sound/isa/gus/gus_reset.c2
-rw-r--r--sound/isa/gus/gus_sample.c2
-rw-r--r--sound/isa/gus/gus_simple.c2
-rw-r--r--sound/isa/gus/gus_synth.c4
-rw-r--r--sound/isa/gus/gus_tables.h2
-rw-r--r--sound/isa/gus/gus_timer.c2
-rw-r--r--sound/isa/gus/gus_uart.c2
-rw-r--r--sound/isa/gus/gus_volume.c2
-rw-r--r--sound/isa/gus/gusclassic.c4
-rw-r--r--sound/isa/gus/gusextreme.c4
-rw-r--r--sound/isa/gus/gusmax.c4
-rw-r--r--sound/isa/gus/interwave.c4
-rw-r--r--sound/isa/opl3sa2.c5
-rw-r--r--sound/isa/opti9xx/Makefile2
-rw-r--r--sound/isa/opti9xx/miro.c18
-rw-r--r--sound/isa/opti9xx/opti92x-ad1848.c14
-rw-r--r--sound/isa/sb/Makefile2
-rw-r--r--sound/isa/sb/emu8000.c2
-rw-r--r--sound/isa/sb/emu8000_synth.c2
-rw-r--r--sound/isa/sb/sb16.c4
-rw-r--r--sound/isa/sb/sb16_csp.c9
-rw-r--r--sound/isa/sb/sb16_main.c4
-rw-r--r--sound/isa/sb/sb8.c4
-rw-r--r--sound/isa/sb/sb8_main.c4
-rw-r--r--sound/isa/sb/sb8_midi.c2
-rw-r--r--sound/isa/sb/sb_common.c8
-rw-r--r--sound/isa/sb/sb_mixer.c2
-rw-r--r--sound/isa/sc6000.c656
-rw-r--r--sound/isa/sscape.c354
-rw-r--r--sound/isa/wavefront/Makefile2
-rw-r--r--sound/isa/wavefront/wavefront_synth.c130
-rw-r--r--sound/last.c2
-rw-r--r--sound/mips/au1x00.c8
-rw-r--r--sound/oss/Makefile1
-rw-r--r--sound/oss/dmasound/Makefile6
-rw-r--r--sound/oss/dmasound/awacs_defs.h251
-rw-r--r--sound/oss/dmasound/dac3550a.c209
-rw-r--r--sound/oss/dmasound/dmasound.h13
-rw-r--r--sound/oss/dmasound/dmasound_awacs.c3215
-rw-r--r--sound/oss/dmasound/dmasound_core.c287
-rw-r--r--sound/oss/dmasound/tas3001c.c849
-rw-r--r--sound/oss/dmasound/tas3001c.h64
-rw-r--r--sound/oss/dmasound/tas3001c_tables.c375
-rw-r--r--sound/oss/dmasound/tas3004.c1138
-rw-r--r--sound/oss/dmasound/tas3004.h77
-rw-r--r--sound/oss/dmasound/tas3004_tables.c301
-rw-r--r--sound/oss/dmasound/tas_common.c214
-rw-r--r--sound/oss/dmasound/tas_common.h284
-rw-r--r--sound/oss/dmasound/tas_eq_prefs.h24
-rw-r--r--sound/oss/dmasound/tas_ioctl.h23
-rw-r--r--sound/oss/dmasound/trans_16.c898
-rw-r--r--sound/oss/es1371.c3131
-rw-r--r--sound/pci/Kconfig111
-rw-r--r--sound/pci/Makefile2
-rw-r--r--sound/pci/ac97/Makefile2
-rw-r--r--sound/pci/ac97/ac97_codec.c40
-rw-r--r--sound/pci/ac97/ac97_id.h3
-rw-r--r--sound/pci/ac97/ac97_local.h2
-rw-r--r--sound/pci/ac97/ac97_patch.c162
-rw-r--r--sound/pci/ac97/ac97_patch.h2
-rw-r--r--sound/pci/ac97/ac97_pcm.c2
-rw-r--r--sound/pci/ac97/ac97_proc.c10
-rw-r--r--sound/pci/ac97/ak4531_codec.c4
-rw-r--r--sound/pci/ali5451/Makefile2
-rw-r--r--sound/pci/ali5451/ali5451.c10
-rw-r--r--sound/pci/als4000.c2
-rw-r--r--sound/pci/au88x0/au88x0.c3
-rw-r--r--sound/pci/au88x0/au88x0_eq.c10
-rw-r--r--sound/pci/au88x0/au88x0_mpu401.c2
-rw-r--r--sound/pci/au88x0/au88x0_synth.c4
-rw-r--r--sound/pci/bt87x.c219
-rw-r--r--sound/pci/ca0106/ca0106.h98
-rw-r--r--sound/pci/ca0106/ca0106_main.c103
-rw-r--r--sound/pci/ca0106/ca0106_mixer.c98
-rw-r--r--sound/pci/ca0106/ca_midi.c2
-rw-r--r--sound/pci/ca0106/ca_midi.h6
-rw-r--r--sound/pci/cmipci.c537
-rw-r--r--sound/pci/cs4281.c28
-rw-r--r--sound/pci/cs46xx/Makefile8
-rw-r--r--sound/pci/cs46xx/cs46xx.c4
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.c12
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.h2
-rw-r--r--sound/pci/cs46xx/dsp_spos.h2
-rw-r--r--sound/pci/cs46xx/dsp_spos_scb_lib.c2
-rw-r--r--sound/pci/cs5535audio/Makefile7
-rw-r--r--sound/pci/cs5535audio/cs5535audio.c24
-rw-r--r--sound/pci/cs5535audio/cs5535audio.h42
-rw-r--r--sound/pci/cs5535audio/cs5535audio_pcm.c10
-rw-r--r--sound/pci/cs5535audio/cs5535audio_pm.c26
-rw-r--r--sound/pci/echoaudio/echoaudio.c33
-rw-r--r--sound/pci/echoaudio/echoaudio_dsp.c4
-rw-r--r--sound/pci/echoaudio/echoaudio_dsp.h15
-rw-r--r--sound/pci/emu10k1/Makefile2
-rw-r--r--sound/pci/emu10k1/emu10k1.c4
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c130
-rw-r--r--sound/pci/emu10k1/emu10k1x.c9
-rw-r--r--sound/pci/emu10k1/emufx.c251
-rw-r--r--sound/pci/emu10k1/emumixer.c86
-rw-r--r--sound/pci/emu10k1/emumpu401.c2
-rw-r--r--sound/pci/emu10k1/emupcm.c2
-rw-r--r--sound/pci/emu10k1/emuproc.c58
-rw-r--r--sound/pci/emu10k1/io.c12
-rw-r--r--sound/pci/emu10k1/irq.c2
-rw-r--r--sound/pci/emu10k1/memory.c2
-rw-r--r--sound/pci/emu10k1/p16v.c19
-rw-r--r--sound/pci/emu10k1/voice.c2
-rw-r--r--sound/pci/ens1370.c44
-rw-r--r--sound/pci/es1938.c22
-rw-r--r--sound/pci/es1968.c28
-rw-r--r--sound/pci/fm801.c4
-rw-r--r--sound/pci/hda/Makefile27
-rw-r--r--sound/pci/hda/hda_codec.c730
-rw-r--r--sound/pci/hda/hda_codec.h113
-rw-r--r--sound/pci/hda/hda_generic.c100
-rw-r--r--sound/pci/hda/hda_hwdep.c122
-rw-r--r--sound/pci/hda/hda_intel.c382
-rw-r--r--sound/pci/hda/hda_local.h205
-rw-r--r--sound/pci/hda/hda_patch.h16
-rw-r--r--sound/pci/hda/hda_proc.c30
-rw-r--r--sound/pci/hda/patch_analog.c527
-rw-r--r--sound/pci/hda/patch_atihdmi.c16
-rw-r--r--sound/pci/hda/patch_cmedia.c27
-rw-r--r--sound/pci/hda/patch_conexant.c191
-rw-r--r--sound/pci/hda/patch_realtek.c1841
-rw-r--r--sound/pci/hda/patch_si3054.c20
-rw-r--r--sound/pci/hda/patch_sigmatel.c1006
-rw-r--r--sound/pci/hda/patch_via.c82
-rw-r--r--sound/pci/ice1712/Makefile2
-rw-r--r--sound/pci/ice1712/ak4xxx.c4
-rw-r--r--sound/pci/ice1712/amp.c2
-rw-r--r--sound/pci/ice1712/amp.h2
-rw-r--r--sound/pci/ice1712/aureon.c45
-rw-r--r--sound/pci/ice1712/delta.c13
-rw-r--r--sound/pci/ice1712/delta.h2
-rw-r--r--sound/pci/ice1712/envy24ht.h2
-rw-r--r--sound/pci/ice1712/ews.c20
-rw-r--r--sound/pci/ice1712/ews.h2
-rw-r--r--sound/pci/ice1712/hoontech.c2
-rw-r--r--sound/pci/ice1712/hoontech.h2
-rw-r--r--sound/pci/ice1712/ice1712.c52
-rw-r--r--sound/pci/ice1712/ice1712.h5
-rw-r--r--sound/pci/ice1712/ice1724.c54
-rw-r--r--sound/pci/ice1712/juli.c2
-rw-r--r--sound/pci/ice1712/phase.c23
-rw-r--r--sound/pci/ice1712/pontis.c27
-rw-r--r--sound/pci/ice1712/prodigy192.c27
-rw-r--r--sound/pci/ice1712/wtm.c29
-rw-r--r--sound/pci/intel8x0.c4
-rw-r--r--sound/pci/intel8x0m.c4
-rw-r--r--sound/pci/korg1212/Makefile2
-rw-r--r--sound/pci/korg1212/korg1212.c4
-rw-r--r--sound/pci/maestro3.c2
-rw-r--r--sound/pci/mixart/Makefile2
-rw-r--r--sound/pci/mixart/mixart.c10
-rw-r--r--sound/pci/mixart/mixart_mixer.c9
-rw-r--r--sound/pci/nm256/Makefile2
-rw-r--r--sound/pci/nm256/nm256.c1
-rw-r--r--sound/pci/pcxhr/pcxhr.c5
-rw-r--r--sound/pci/pcxhr/pcxhr_mixer.c15
-rw-r--r--sound/pci/rme32.c33
-rw-r--r--sound/pci/rme96.c41
-rw-r--r--sound/pci/rme9652/Makefile2
-rw-r--r--sound/pci/rme9652/hdsp.c90
-rw-r--r--sound/pci/rme9652/hdspm.c723
-rw-r--r--sound/pci/rme9652/rme9652.c27
-rw-r--r--sound/pci/sonicvibes.c4
-rw-r--r--sound/pci/trident/Makefile2
-rw-r--r--sound/pci/trident/trident.c2
-rw-r--r--sound/pci/trident/trident_main.c22
-rw-r--r--sound/pci/trident/trident_memory.c2
-rw-r--r--sound/pci/via82xx.c19
-rw-r--r--sound/pci/via82xx_modem.c8
-rw-r--r--sound/pci/vx222/Makefile2
-rw-r--r--sound/pci/ymfpci/Makefile2
-rw-r--r--sound/pci/ymfpci/ymfpci.c4
-rw-r--r--sound/pci/ymfpci/ymfpci_main.c108
-rw-r--r--sound/pcmcia/Makefile2
-rw-r--r--sound/pcmcia/pdaudiocf/Makefile2
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf.c4
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf.h2
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf_core.c2
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf_irq.c2
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c2
-rw-r--r--sound/pcmcia/vx/Makefile2
-rw-r--r--sound/pcmcia/vx/vxp_mixer.c9
-rw-r--r--sound/ppc/Makefile2
-rw-r--r--sound/ppc/beep.c4
-rw-r--r--sound/ppc/daca.c10
-rw-r--r--sound/ppc/pmac.c57
-rw-r--r--sound/ppc/pmac.h4
-rw-r--r--sound/ppc/snd_ps3.c1
-rw-r--r--sound/sh/aica.c41
-rw-r--r--sound/soc/codecs/Kconfig20
-rw-r--r--sound/soc/codecs/Makefile2
-rw-r--r--sound/soc/codecs/cs4270.c805
-rw-r--r--sound/soc/codecs/cs4270.h28
-rw-r--r--sound/soc/pxa/spitz.c1
-rw-r--r--sound/soc/s3c24xx/Kconfig2
-rw-r--r--sound/soc/s3c24xx/s3c24xx-i2s.c1
-rw-r--r--sound/soc/s3c24xx/s3c24xx-pcm.c22
-rw-r--r--sound/soc/soc-core.c22
-rw-r--r--sound/soc/soc-dapm.c4
-rw-r--r--sound/sparc/cs4231.c816
-rw-r--r--sound/sparc/dbri.c581
-rw-r--r--sound/spi/Kconfig31
-rw-r--r--sound/spi/Makefile5
-rw-r--r--sound/spi/at73c213.c1129
-rw-r--r--sound/spi/at73c213.h119
-rw-r--r--sound/synth/Makefile2
-rw-r--r--sound/synth/emux/Makefile2
-rw-r--r--sound/synth/emux/emux_synth.c2
-rw-r--r--sound/synth/util_mem.c2
-rw-r--r--sound/usb/Kconfig2
-rw-r--r--sound/usb/caiaq/caiaq-audio.c1
-rw-r--r--sound/usb/caiaq/caiaq-device.c18
-rw-r--r--sound/usb/caiaq/caiaq-device.h1
-rw-r--r--sound/usb/caiaq/caiaq-input.c37
-rw-r--r--sound/usb/usbaudio.c46
-rw-r--r--sound/usb/usbmidi.c46
-rw-r--r--sound/usb/usbmixer.c11
-rw-r--r--sound/usb/usbquirks.h109
5652 files changed, 189501 insertions, 135509 deletions
diff --git a/.gitignore b/.gitignore
index 27c3e839b54e..8d14531846b9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,6 +12,7 @@
*.s
*.ko
*.so
+*.so.dbg
*.mod.c
*.i
*.lst
@@ -26,6 +27,7 @@ vmlinux*
!vmlinux.lds.S
System.map
Module.symvers
+!.gitignore
#
# Generated include files
diff --git a/CREDITS b/CREDITS
index 550bb2b9fe8b..ee909f2cc49e 100644
--- a/CREDITS
+++ b/CREDITS
@@ -959,7 +959,7 @@ S: 2037 Walnut #6
S: Boulder, Colorado 80302
S: USA
-N: Heiko Eissfeldt
+N: Heiko Eißfeldt
E: heiko@colossus.escape.de heiko@unifix.de
D: verify_area stuff, generic SCSI fixes
D: SCSI Programming HOWTO
@@ -1165,6 +1165,12 @@ S: 600 North Bell Avenue, Suite 160
S: Carnegie, Pennsylvania 15106-4304
S: USA
+N: Kai Germaschewski
+E: kai@germaschewski.name
+D: Major kbuild rework during the 2.5 cycle
+D: ISDN Maintainer
+S: USA
+
N: Philip Gladstone
E: philip@gladstonefamily.net
D: Kernel / timekeeping stuff
@@ -1933,7 +1939,7 @@ M: seasons@makosteszta.sote.hu
D: Original author of software suspend
N: Jaroslav Kysela
-E: perex@suse.cz
+E: perex@perex.cz
W: http://www.perex.cz
D: Original Author and Maintainer for HP 10/100 Mbit Network Adapters
D: ISA PnP
@@ -1982,8 +1988,8 @@ N: Volker Lendecke
E: vl@kki.org
D: Kernel smbfs (to mount WfW, NT and OS/2 network drives.)
D: NCP filesystem support (to mount NetWare volumes)
-S: Von Ossietzky Str. 12
-S: 37085 Goettingen
+S: Von-Ossietzky-Str. 12
+S: 37085 Göttingen
S: Germany
N: Kevin Lentin
@@ -2425,11 +2431,11 @@ S: 12725 SW Millikan Way, Suite 400
S: Beaverton, Oregon 97005
S: USA
-N: Eberhard Moenkeberg
+N: Eberhard Mönkeberg
E: emoenke@gwdg.de
D: CDROM driver "sbpcd" (Matsushita/Panasonic/Soundblaster)
-S: Ruhstrathoehe 2 b.
-S: D-37085 Goettingen
+S: Ruhstrathöhe 2 b.
+S: D-37085 Göttingen
S: Germany
N: Thomas Molina
@@ -2702,7 +2708,7 @@ S: Canada K2P 0X8
N: Mikael Pettersson
E: mikpe@it.uu.se
-W: http://www.csd.uu.se/~mikpe/
+W: http://user.it.uu.se/~mikpe/linux/
D: Miscellaneous fixes
N: Reed H. Petty
diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX
index 43e89b1537d9..299615d821ac 100644
--- a/Documentation/00-INDEX
+++ b/Documentation/00-INDEX
@@ -22,6 +22,8 @@ CodingStyle
- how the boss likes the C code in the kernel to look.
DMA-API.txt
- DMA API, pci_ API & extensions for non-consistent memory machines.
+DMA-ISA-LPC.txt
+ - How to do DMA with ISA (and LPC) devices.
DMA-mapping.txt
- info for PCI drivers using DMA portably across all platforms.
DocBook/
@@ -50,6 +52,8 @@ README.cycladesZ
- info on Cyclades-Z firmware loading.
SAK.txt
- info on Secure Attention Keys.
+SM501.txt
+ - Silicon Motion SM501 multimedia companion chip
SecurityBugs
- procedure for reporting security bugs found in the kernel.
SubmitChecklist
@@ -145,7 +149,7 @@ fb/
feature-removal-schedule.txt
- list of files and features that are going to be removed.
filesystems/
- - directory with info on the various filesystems that Linux supports.
+ - info on the vfs and the various filesystems that Linux supports.
firmware_class/
- request_firmware() hotplug interface info.
floppy.txt
@@ -230,8 +234,6 @@ local_ops.txt
- semantics and behavior of local atomic operations.
lockdep-design.txt
- documentation on the runtime locking correctness validator.
-locks.txt
- - info on file locking implementations, flock() vs. fcntl(), etc.
logo.gif
- full colour GIF image of Linux logo (penguin - Tux).
logo.txt
@@ -240,14 +242,14 @@ m68k/
- directory with info about Linux on Motorola 68k architecture.
magic-number.txt
- list of magic numbers used to mark/protect kernel data structures.
-mandatory.txt
- - info on the Linux implementation of Sys V mandatory file locking.
mca.txt
- info on supporting Micro Channel Architecture (e.g. PS/2) systems.
md.txt
- info on boot arguments for the multiple devices driver.
memory-barriers.txt
- info on Linux kernel memory barriers.
+memory-hotplug.txt
+ - Hotpluggable memory support, how to use and current status.
memory.txt
- info on typical Linux memory problems.
mips/
@@ -298,6 +300,8 @@ pm.txt
- info on Linux power management support.
pnp.txt
- Linux Plug and Play documentation.
+power_supply_class.txt
+ - Tells userspace about battery, UPS, AC or DC power supply properties
power/
- directory with info on Linux PCI power management.
powerpc/
@@ -334,8 +338,12 @@ sched-coding.txt
- reference for various scheduler-related methods in the O(1) scheduler.
sched-design.txt
- goals, design and implementation of the Linux O(1) scheduler.
+sched-design-CFS.txt
+ - goals, design and implementation of the Complete Fair Scheduler.
sched-domains.txt
- information on scheduling domains.
+sched-nice-design.txt
+ - How and why the scheduler's nice levels are implemented.
sched-stats.txt
- information on schedstats (Linux Scheduler Statistics).
scsi/
@@ -380,6 +388,8 @@ stallion.txt
- info on using the Stallion multiport serial driver.
svga.txt
- short guide on selecting video modes at boot via VGA BIOS.
+sysfs-rules.txt
+ - How not to use sysfs.
sx.txt
- info on the Specialix SX/SI multiport serial driver.
sysctl/
@@ -410,6 +420,8 @@ video4linux/
- directory with info regarding video/TV/radio cards and linux.
vm/
- directory with info on the Linux vm code.
+volatile-considered-harmful.txt
+ - Why the "volatile" type class should not be used
voyager.txt
- guide to running Linux on the Voyager architecture.
w1/
@@ -418,7 +430,5 @@ watchdog/
- how to auto-reboot Linux if it has "fallen and can't get up". ;-)
x86_64/
- directory with info on Linux support for AMD x86-64 (Hammer) machines.
-xterm-linux.xpm
- - XPM image of penguin logo (see logo.txt) sitting on an xterm.
zorro.txt
- info on writing drivers for Zorro bus devices found on Amigas.
diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle
index 7f1730f1a1ae..6caa14615578 100644
--- a/Documentation/CodingStyle
+++ b/Documentation/CodingStyle
@@ -77,12 +77,15 @@ Get a decent editor and don't leave whitespace at the end of lines.
Coding style is all about readability and maintainability using commonly
available tools.
-The limit on the length of lines is 80 columns and this is a hard limit.
+The limit on the length of lines is 80 columns and this is a strongly
+preferred limit.
Statements longer than 80 columns will be broken into sensible chunks.
Descendants are always substantially shorter than the parent and are placed
substantially to the right. The same applies to function headers with a long
-argument list. Long strings are as well broken into shorter strings.
+argument list. Long strings are as well broken into shorter strings. The
+only exception to this is where exceeding 80 columns significantly increases
+readability and does not hide information.
void fun(int a, int b, int c)
{
diff --git a/Documentation/DMA-mapping.txt b/Documentation/DMA-mapping.txt
index e07f2530326b..d84f89dbf921 100644
--- a/Documentation/DMA-mapping.txt
+++ b/Documentation/DMA-mapping.txt
@@ -189,12 +189,6 @@ smaller mask as pci_set_dma_mask(). However for the rare case that a
device driver only uses consistent allocations, one would have to
check the return value from pci_set_consistent_dma_mask().
-If your 64-bit device is going to be an enormous consumer of DMA
-mappings, this can be problematic since the DMA mappings are a
-finite resource on many platforms. Please see the "DAC Addressing
-for Address Space Hungry Devices" section near the end of this
-document for how to handle this case.
-
Finally, if your device can only drive the low 24-bits of
address during PCI bus mastering you might do something like:
@@ -203,8 +197,6 @@ address during PCI bus mastering you might do something like:
"mydev: 24-bit DMA addressing not available.\n");
goto ignore_this_device;
}
-[Better use DMA_24BIT_MASK instead of 0x00ffffff.
-See linux/include/dma-mapping.h for reference.]
When pci_set_dma_mask() is successful, and returns zero, the PCI layer
saves away this mask you have provided. The PCI layer will use this
@@ -514,7 +506,7 @@ With scatterlists, you map a region gathered from several regions by:
int i, count = pci_map_sg(dev, sglist, nents, direction);
struct scatterlist *sg;
- for (i = 0, sg = sglist; i < count; i++, sg++) {
+ for_each_sg(sglist, sg, count, i) {
hw_address[i] = sg_dma_address(sg);
hw_len[i] = sg_dma_len(sg);
}
@@ -652,18 +644,6 @@ It is planned to completely remove virt_to_bus() and bus_to_virt() as
they are entirely deprecated. Some ports already do not provide these
as it is impossible to correctly support them.
- 64-bit DMA and DAC cycle support
-
-Do you understand all of the text above? Great, then you already
-know how to use 64-bit DMA addressing under Linux. Simply make
-the appropriate pci_set_dma_mask() calls based upon your cards
-capabilities, then use the mapping APIs above.
-
-It is that simple.
-
-Well, not for some odd devices. See the next section for information
-about that.
-
Optimizing Unmap State Space Consumption
On many platforms, pci_unmap_{single,page}() is simply a nop.
@@ -782,5 +762,5 @@ following people:
Jay Estabrook <Jay.Estabrook@compaq.com>
Thomas Sailer <sailer@ife.ee.ethz.ch>
Andrea Arcangeli <andrea@suse.de>
- Jens Axboe <axboe@suse.de>
+ Jens Axboe <jens.axboe@oracle.com>
David Mosberger-Tang <davidm@hpl.hp.com>
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index 1a7f53068ec2..054a7ecf64c6 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -165,7 +165,7 @@ quiet_cmd_db2man = MAN $@
@touch $@
###
-# Rules to generate postscripts and PNG imgages from .fig format files
+# Rules to generate postscripts and PNG images from .fig format files
quiet_cmd_fig2eps = FIG2EPS $@
cmd_fig2eps = fig2dev -Leps $< $@
diff --git a/Documentation/DocBook/deviceiobook.tmpl b/Documentation/DocBook/deviceiobook.tmpl
index 361c884d860d..9ee6f3cbb414 100644
--- a/Documentation/DocBook/deviceiobook.tmpl
+++ b/Documentation/DocBook/deviceiobook.tmpl
@@ -85,7 +85,7 @@
<chapter id="mmio">
<title>Memory Mapped IO</title>
- <sect1>
+ <sect1 id="getting_access_to_the_device">
<title>Getting Access to the Device</title>
<para>
The most widely supported form of IO is memory mapped IO.
@@ -114,7 +114,7 @@
</para>
</sect1>
- <sect1>
+ <sect1 id="accessing_the_device">
<title>Accessing the device</title>
<para>
The part of the interface most used by drivers is reading and
@@ -272,9 +272,9 @@ CPU B: spin_unlock_irqrestore(&amp;dev_lock, flags)
</chapter>
- <chapter>
+ <chapter id="port_space_accesses">
<title>Port Space Accesses</title>
- <sect1>
+ <sect1 id="port_space_explained">
<title>Port Space Explained</title>
<para>
@@ -291,7 +291,7 @@ CPU B: spin_unlock_irqrestore(&amp;dev_lock, flags)
</para>
</sect1>
- <sect1>
+ <sect1 id="accessing_port_space">
<title>Accessing Port Space</title>
<para>
Accesses to this space are provided through a set of functions
diff --git a/Documentation/DocBook/filesystems.tmpl b/Documentation/DocBook/filesystems.tmpl
index 39fa2aba7f9b..5eaef87e8f1b 100644
--- a/Documentation/DocBook/filesystems.tmpl
+++ b/Documentation/DocBook/filesystems.tmpl
@@ -40,25 +40,25 @@
<chapter id="vfs">
<title>The Linux VFS</title>
- <sect1><title>The Filesystem types</title>
+ <sect1 id="the_filesystem_types"><title>The Filesystem types</title>
!Iinclude/linux/fs.h
</sect1>
- <sect1><title>The Directory Cache</title>
+ <sect1 id="the_directory_cache"><title>The Directory Cache</title>
!Efs/dcache.c
!Iinclude/linux/dcache.h
</sect1>
- <sect1><title>Inode Handling</title>
+ <sect1 id="inode_handling"><title>Inode Handling</title>
!Efs/inode.c
!Efs/bad_inode.c
</sect1>
- <sect1><title>Registration and Superblocks</title>
+ <sect1 id="registration_and_superblocks"><title>Registration and Superblocks</title>
!Efs/super.c
</sect1>
- <sect1><title>File Locks</title>
+ <sect1 id="file_locks"><title>File Locks</title>
!Efs/locks.c
!Ifs/locks.c
</sect1>
- <sect1><title>Other Functions</title>
+ <sect1 id="other_functions"><title>Other Functions</title>
!Efs/mpage.c
!Efs/namei.c
!Efs/buffer.c
@@ -73,11 +73,11 @@
<chapter id="proc">
<title>The proc filesystem</title>
- <sect1><title>sysctl interface</title>
+ <sect1 id="sysctl_interface"><title>sysctl interface</title>
!Ekernel/sysctl.c
</sect1>
- <sect1><title>proc filesystem interface</title>
+ <sect1 id="proc_filesystem_interface"><title>proc filesystem interface</title>
!Ifs/proc/base.c
</sect1>
</chapter>
@@ -92,7 +92,7 @@
<chapter id="debugfs">
<title>The debugfs filesystem</title>
- <sect1><title>debugfs interface</title>
+ <sect1 id="debugfs_interface"><title>debugfs interface</title>
!Efs/debugfs/inode.c
!Efs/debugfs/file.c
</sect1>
@@ -134,9 +134,9 @@
<title>The Linux Journalling API</title>
- <sect1>
+ <sect1 id="journaling_overview">
<title>Overview</title>
- <sect2>
+ <sect2 id="journaling_details">
<title>Details</title>
<para>
The journalling layer is easy to use. You need to
@@ -307,7 +307,7 @@ particular inode.
</sect2>
- <sect2>
+ <sect2 id="jbd_summary">
<title>Summary</title>
<para>
Using the journal is a matter of wrapping the different context changes,
@@ -349,7 +349,7 @@ an example.
</sect1>
- <sect1>
+ <sect1 id="data_types">
<title>Data Types</title>
<para>
The journalling layer uses typedefs to 'hide' the concrete definitions
@@ -358,27 +358,27 @@ an example.
Obviously the hiding is not enforced as this is 'C'.
</para>
- <sect2><title>Structures</title>
+ <sect2 id="structures"><title>Structures</title>
!Iinclude/linux/jbd.h
</sect2>
</sect1>
- <sect1>
+ <sect1 id="functions">
<title>Functions</title>
<para>
The functions here are split into two groups those that
affect a journal as a whole, and those which are used to
manage transactions
</para>
- <sect2><title>Journal Level</title>
+ <sect2 id="journal_level"><title>Journal Level</title>
!Efs/jbd/journal.c
!Ifs/jbd/recovery.c
</sect2>
- <sect2><title>Transasction Level</title>
+ <sect2 id="transaction_level"><title>Transasction Level</title>
!Efs/jbd/transaction.c
</sect2>
</sect1>
- <sect1>
+ <sect1 id="see_also">
<title>See also</title>
<para>
<citation>
diff --git a/Documentation/DocBook/gadget.tmpl b/Documentation/DocBook/gadget.tmpl
index 6996d977bf8f..5a8ffa761e09 100644
--- a/Documentation/DocBook/gadget.tmpl
+++ b/Documentation/DocBook/gadget.tmpl
@@ -144,7 +144,7 @@ with the lowest level (which directly handles hardware).
<para>This is the lowest software level.
It is the only layer that talks to hardware,
through registers, fifos, dma, irqs, and the like.
- The <filename>&lt;linux/usb_gadget.h&gt;</filename> API abstracts
+ The <filename>&lt;linux/usb/gadget.h&gt;</filename> API abstracts
the peripheral controller endpoint hardware.
That hardware is exposed through endpoint objects, which accept
streams of IN/OUT buffers, and through callbacks that interact
@@ -494,7 +494,7 @@ side drivers (and usbcore).
<sect1 id="core"><title>Core Objects and Methods</title>
<para>These are declared in
-<filename>&lt;linux/usb_gadget.h&gt;</filename>,
+<filename>&lt;linux/usb/gadget.h&gt;</filename>,
and are used by gadget drivers to interact with
USB peripheral controller drivers.
</para>
@@ -509,7 +509,7 @@ USB peripheral controller drivers.
unless the explanations are trivial.
-->
-!Iinclude/linux/usb_gadget.h
+!Iinclude/linux/usb/gadget.h
</sect1>
<sect1 id="utils"><title>Optional Utilities</title>
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index 230cbf753782..aa38cc5692a0 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -46,7 +46,7 @@
<sect1><title>Atomic and pointer manipulation</title>
!Iinclude/asm-x86/atomic_32.h
-!Iinclude/asm-x86/unaligned_32.h
+!Iinclude/asm-x86/unaligned.h
</sect1>
<sect1><title>Delaying, scheduling, and timer routines</title>
@@ -340,7 +340,7 @@ X!Earch/x86/kernel/mca_32.c
<chapter id="security">
<title>Security Framework</title>
-!Esecurity/security.c
+!Isecurity/security.c
</chapter>
<chapter id="audit">
@@ -386,8 +386,7 @@ X!Edrivers/base/interface.c
!Edrivers/base/bus.c
</sect1>
<sect1><title>Device Drivers Power Management</title>
-!Edrivers/base/power/resume.c
-!Edrivers/base/power/suspend.c
+!Edrivers/base/power/main.c
</sect1>
<sect1><title>Device Drivers ACPI Support</title>
<!-- Internal functions only
diff --git a/Documentation/DocBook/mtdnand.tmpl b/Documentation/DocBook/mtdnand.tmpl
index 6fbc41d98c1e..957cf5c26831 100644
--- a/Documentation/DocBook/mtdnand.tmpl
+++ b/Documentation/DocBook/mtdnand.tmpl
@@ -282,7 +282,7 @@ int __init board_init (void)
goto out;
}
- /* map physical adress */
+ /* map physical address */
baseaddr = (unsigned long)ioremap(CHIP_PHYSICAL_ADDRESS, 1024);
if(!baseaddr){
printk("Ioremap to access NAND chip failed\n");
@@ -306,7 +306,7 @@ int __init board_init (void)
this->dev_ready = board_dev_ready;
this->eccmode = NAND_ECC_SOFT;
- /* Scan to find existance of the device */
+ /* Scan to find existence of the device */
if (nand_scan (board_mtd, 1)) {
err = -ENXIO;
goto out_ior;
@@ -340,7 +340,7 @@ static void __exit board_cleanup (void)
/* Release resources, unregister device */
nand_release (board_mtd);
- /* unmap physical adress */
+ /* unmap physical address */
iounmap((void *)baseaddr);
/* Free the MTD device structure */
diff --git a/Documentation/HOWTO b/Documentation/HOWTO
index c64e969dc33b..54835610b3d6 100644
--- a/Documentation/HOWTO
+++ b/Documentation/HOWTO
@@ -77,7 +77,7 @@ documentation files are also added which explain how to use the feature.
When a kernel change causes the interface that the kernel exposes to
userspace to change, it is recommended that you send the information or
a patch to the manual pages explaining the change to the manual pages
-maintainer at mtk-manpages@gmx.net.
+maintainer at mtk.manpages@gmail.com.
Here is a list of files that are in the kernel source tree that are
required reading:
@@ -330,7 +330,7 @@ Here is a list of some of the different kernel trees available:
- ACPI development tree, Len Brown <len.brown@intel.com>
git.kernel.org:/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git
- - Block development tree, Jens Axboe <axboe@suse.de>
+ - Block development tree, Jens Axboe <jens.axboe@oracle.com>
git.kernel.org:/pub/scm/linux/kernel/git/axboe/linux-2.6-block.git
- DRM development tree, Dave Airlie <airlied@linux.ie>
diff --git a/Documentation/IPMI.txt b/Documentation/IPMI.txt
index 24dc3fcf1594..bc38283379f0 100644
--- a/Documentation/IPMI.txt
+++ b/Documentation/IPMI.txt
@@ -441,17 +441,20 @@ ACPI, and if none of those then a KCS device at the spec-specified
0xca2. If you want to turn this off, set the "trydefaults" option to
false.
-If you have high-res timers compiled into the kernel, the driver will
-use them to provide much better performance. Note that if you do not
-have high-res timers enabled in the kernel and you don't have
-interrupts enabled, the driver will run VERY slowly. Don't blame me,
+If your IPMI interface does not support interrupts and is a KCS or
+SMIC interface, the IPMI driver will start a kernel thread for the
+interface to help speed things up. This is a low-priority kernel
+thread that constantly polls the IPMI driver while an IPMI operation
+is in progress. The force_kipmid module parameter will all the user to
+force this thread on or off. If you force it off and don't have
+interrupts, the driver will run VERY slowly. Don't blame me,
these interfaces suck.
The driver supports a hot add and remove of interfaces. This way,
interfaces can be added or removed after the kernel is up and running.
-This is done using /sys/modules/ipmi_si/hotmod, which is a write-only
-parameter. You write a string to this interface. The string has the
-format:
+This is done using /sys/modules/ipmi_si/parameters/hotmod, which is a
+write-only parameter. You write a string to this interface. The string
+has the format:
<op1>[:op2[:op3...]]
The "op"s are:
add|remove,kcs|bt|smic,mem|i/o,<address>[,<opt1>[,<opt2>[,...]]]
@@ -581,9 +584,11 @@ The watchdog will panic and start a 120 second reset timeout if it
gets a pre-action. During a panic or a reboot, the watchdog will
start a 120 timer if it is running to make sure the reboot occurs.
-Note that if you use the NMI preaction for the watchdog, you MUST
-NOT use nmi watchdog mode 1. If you use the NMI watchdog, you
-must use mode 2.
+Note that if you use the NMI preaction for the watchdog, you MUST NOT
+use the nmi watchdog. There is no reasonable way to tell if an NMI
+comes from the IPMI controller, so it must assume that if it gets an
+otherwise unhandled NMI, it must be from IPMI and it will panic
+immediately.
Once you open the watchdog timer, you must write a 'V' character to the
device to close it, or the timer will not stop. This is a new semantic
diff --git a/Documentation/Intel-IOMMU.txt b/Documentation/Intel-IOMMU.txt
new file mode 100644
index 000000000000..c2321903aa09
--- /dev/null
+++ b/Documentation/Intel-IOMMU.txt
@@ -0,0 +1,115 @@
+Linux IOMMU Support
+===================
+
+The architecture spec can be obtained from the below location.
+
+http://www.intel.com/technology/virtualization/
+
+This guide gives a quick cheat sheet for some basic understanding.
+
+Some Keywords
+
+DMAR - DMA remapping
+DRHD - DMA Engine Reporting Structure
+RMRR - Reserved memory Region Reporting Structure
+ZLR - Zero length reads from PCI devices
+IOVA - IO Virtual address.
+
+Basic stuff
+-----------
+
+ACPI enumerates and lists the different DMA engines in the platform, and
+device scope relationships between PCI devices and which DMA engine controls
+them.
+
+What is RMRR?
+-------------
+
+There are some devices the BIOS controls, for e.g USB devices to perform
+PS2 emulation. The regions of memory used for these devices are marked
+reserved in the e820 map. When we turn on DMA translation, DMA to those
+regions will fail. Hence BIOS uses RMRR to specify these regions along with
+devices that need to access these regions. OS is expected to setup
+unity mappings for these regions for these devices to access these regions.
+
+How is IOVA generated?
+---------------------
+
+Well behaved drivers call pci_map_*() calls before sending command to device
+that needs to perform DMA. Once DMA is completed and mapping is no longer
+required, device performs a pci_unmap_*() calls to unmap the region.
+
+The Intel IOMMU driver allocates a virtual address per domain. Each PCIE
+device has its own domain (hence protection). Devices under p2p bridges
+share the virtual address with all devices under the p2p bridge due to
+transaction id aliasing for p2p bridges.
+
+IOVA generation is pretty generic. We used the same technique as vmalloc()
+but these are not global address spaces, but separate for each domain.
+Different DMA engines may support different number of domains.
+
+We also allocate gaurd pages with each mapping, so we can attempt to catch
+any overflow that might happen.
+
+
+Graphics Problems?
+------------------
+If you encounter issues with graphics devices, you can try adding
+option intel_iommu=igfx_off to turn off the integrated graphics engine.
+
+If it happens to be a PCI device included in the INCLUDE_ALL Engine,
+then try enabling CONFIG_DMAR_GFX_WA to setup a 1-1 map. We hear
+graphics drivers may be in process of using DMA api's in the near
+future and at that time this option can be yanked out.
+
+Some exceptions to IOVA
+-----------------------
+Interrupt ranges are not address translated, (0xfee00000 - 0xfeefffff).
+The same is true for peer to peer transactions. Hence we reserve the
+address from PCI MMIO ranges so they are not allocated for IOVA addresses.
+
+
+Fault reporting
+---------------
+When errors are reported, the DMA engine signals via an interrupt. The fault
+reason and device that caused it with fault reason is printed on console.
+
+See below for sample.
+
+
+Boot Message Sample
+-------------------
+
+Something like this gets printed indicating presence of DMAR tables
+in ACPI.
+
+ACPI: DMAR (v001 A M I OEMDMAR 0x00000001 MSFT 0x00000097) @ 0x000000007f5b5ef0
+
+When DMAR is being processed and initialized by ACPI, prints DMAR locations
+and any RMRR's processed.
+
+ACPI DMAR:Host address width 36
+ACPI DMAR:DRHD (flags: 0x00000000)base: 0x00000000fed90000
+ACPI DMAR:DRHD (flags: 0x00000000)base: 0x00000000fed91000
+ACPI DMAR:DRHD (flags: 0x00000001)base: 0x00000000fed93000
+ACPI DMAR:RMRR base: 0x00000000000ed000 end: 0x00000000000effff
+ACPI DMAR:RMRR base: 0x000000007f600000 end: 0x000000007fffffff
+
+When DMAR is enabled for use, you will notice..
+
+PCI-DMA: Using DMAR IOMMU
+
+Fault reporting
+---------------
+
+DMAR:[DMA Write] Request device [00:02.0] fault addr 6df084000
+DMAR:[fault reason 05] PTE Write access is not set
+DMAR:[DMA Write] Request device [00:02.0] fault addr 6df084000
+DMAR:[fault reason 05] PTE Write access is not set
+
+TBD
+----
+
+- For compatibility testing, could use unity map domain for all devices, just
+ provide a 1-1 for all useful memory under a single domain for all devices.
+- API for paravirt ops for abstracting functionlity for VMM folks.
diff --git a/Documentation/RCU/00-INDEX b/Documentation/RCU/00-INDEX
new file mode 100644
index 000000000000..461481dfb7c3
--- /dev/null
+++ b/Documentation/RCU/00-INDEX
@@ -0,0 +1,22 @@
+00-INDEX
+ - This file
+arrayRCU.txt
+ - Using RCU to Protect Read-Mostly Arrays
+checklist.txt
+ - Review Checklist for RCU Patches
+listRCU.txt
+ - Using RCU to Protect Read-Mostly Linked Lists
+NMI-RCU.txt
+ - Using RCU to Protect Dynamic NMI Handlers
+rcuref.txt
+ - Reference-count design for elements of lists/arrays protected by RCU
+rcu.txt
+ - RCU Concepts
+RTFP.txt
+ - List of RCU papers (bibliography) going back to 1980.
+torture.txt
+ - RCU Torture Test Operation (CONFIG_RCU_TORTURE_TEST)
+UP.txt
+ - RCU on Uniprocessor Systems
+whatisRCU.txt
+ - What is RCU?
diff --git a/Documentation/SM501.txt b/Documentation/SM501.txt
index 3a1bd95d3767..6fc656035925 100644
--- a/Documentation/SM501.txt
+++ b/Documentation/SM501.txt
@@ -3,6 +3,11 @@
Copyright 2006, 2007 Simtec Electronics
+The Silicon Motion SM501 multimedia companion chip is a multifunction device
+which may provide numerous interfaces including USB host controller USB gadget,
+Asyncronous Serial ports, Audio functions and a dual display video interface.
+The device may be connected by PCI or local bus with varying functions enabled.
+
Core
----
diff --git a/Documentation/SubmitChecklist b/Documentation/SubmitChecklist
index 19e7f65c269f..34e06d2f194f 100644
--- a/Documentation/SubmitChecklist
+++ b/Documentation/SubmitChecklist
@@ -67,7 +67,7 @@ kernel patches.
20: Check that it all passes `make headers_check'.
21: Has been checked with injection of at least slab and page-allocation
- fauilures. See Documentation/fault-injection/.
+ failures. See Documentation/fault-injection/.
If the new code is substantial, addition of subsystem-specific fault
injection might be appropriate.
diff --git a/Documentation/SubmittingDrivers b/Documentation/SubmittingDrivers
index d7e26427e426..24f2eb40cae5 100644
--- a/Documentation/SubmittingDrivers
+++ b/Documentation/SubmittingDrivers
@@ -36,8 +36,7 @@ Linux 2.4:
If the code area has a general maintainer then please submit it to
the maintainer listed in MAINTAINERS in the kernel file. If the
maintainer does not respond or you cannot find the appropriate
- maintainer then please contact Marcelo Tosatti
- <marcelo.tosatti@cyclades.com>.
+ maintainer then please contact Willy Tarreau <w@1wt.eu>.
Linux 2.6:
The same rules apply as 2.4 except that you should follow linux-kernel
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index a30dd4480ad4..681e2b36195c 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -464,8 +464,8 @@ section Linus Computer Science 101.
Nuff said. If your code deviates too much from this, it is likely
to be rejected without further review, and without comment.
-Once significant exception is when moving code from one file to
-another in this case you should not modify the moved code at all in
+One significant exception is when moving code from one file to
+another -- in this case you should not modify the moved code at all in
the same patch which moves it. This clearly delineates the act of
moving the code and your changes. This greatly aids review of the
actual differences and allows tools to better track the history of
diff --git a/Documentation/accounting/cgroupstats.txt b/Documentation/accounting/cgroupstats.txt
new file mode 100644
index 000000000000..eda40fd39cad
--- /dev/null
+++ b/Documentation/accounting/cgroupstats.txt
@@ -0,0 +1,27 @@
+Control Groupstats is inspired by the discussion at
+http://lkml.org/lkml/2007/4/11/187 and implements per cgroup statistics as
+suggested by Andrew Morton in http://lkml.org/lkml/2007/4/11/263.
+
+Per cgroup statistics infrastructure re-uses code from the taskstats
+interface. A new set of cgroup operations are registered with commands
+and attributes specific to cgroups. It should be very easy to
+extend per cgroup statistics, by adding members to the cgroupstats
+structure.
+
+The current model for cgroupstats is a pull, a push model (to post
+statistics on interesting events), should be very easy to add. Currently
+user space requests for statistics by passing the cgroup path.
+Statistics about the state of all the tasks in the cgroup is returned to
+user space.
+
+NOTE: We currently rely on delay accounting for extracting information
+about tasks blocked on I/O. If CONFIG_TASK_DELAY_ACCT is disabled, this
+information will not be available.
+
+To extract cgroup statistics a utility very similar to getdelays.c
+has been developed, the sample output of the utility is shown below
+
+~/balbir/cgroupstats # ./getdelays -C "/cgroup/a"
+sleeping 1, blocked 0, running 1, stopped 0, uninterruptible 0
+~/balbir/cgroupstats # ./getdelays -C "/cgroup"
+sleeping 155, blocked 0, running 1, stopped 0, uninterruptible 2
diff --git a/Documentation/accounting/getdelays.c b/Documentation/accounting/getdelays.c
index cbee3a27f768..d6cb1a86fd61 100644
--- a/Documentation/accounting/getdelays.c
+++ b/Documentation/accounting/getdelays.c
@@ -21,11 +21,11 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
-#include <sys/types.h>
#include <signal.h>
#include <linux/genetlink.h>
#include <linux/taskstats.h>
+#include <linux/cgroupstats.h>
/*
* Generic macros for dealing with netlink sockets. Might be duplicated
@@ -79,6 +79,7 @@ static void usage(void)
fprintf(stderr, " -i: print IO accounting (works only with -p)\n");
fprintf(stderr, " -l: listen forever\n");
fprintf(stderr, " -v: debug on\n");
+ fprintf(stderr, " -C: container path\n");
}
/*
@@ -213,6 +214,14 @@ void task_context_switch_counts(struct taskstats *t)
t->nvcsw, t->nivcsw);
}
+void print_cgroupstats(struct cgroupstats *c)
+{
+ printf("sleeping %llu, blocked %llu, running %llu, stopped %llu, "
+ "uninterruptible %llu\n", c->nr_sleeping, c->nr_io_wait,
+ c->nr_running, c->nr_stopped, c->nr_uninterruptible);
+}
+
+
void print_ioacct(struct taskstats *t)
{
printf("%s: read=%llu, write=%llu, cancelled_write=%llu\n",
@@ -240,11 +249,14 @@ int main(int argc, char *argv[])
int maskset = 0;
char *logfile = NULL;
int loop = 0;
+ int containerset = 0;
+ char containerpath[1024];
+ int cfd = 0;
struct msgtemplate msg;
while (1) {
- c = getopt(argc, argv, "qdiw:r:m:t:p:vl");
+ c = getopt(argc, argv, "qdiw:r:m:t:p:vlC:");
if (c < 0)
break;
@@ -261,6 +273,10 @@ int main(int argc, char *argv[])
printf("printing task/process context switch rates\n");
print_task_context_switch_counts = 1;
break;
+ case 'C':
+ containerset = 1;
+ strncpy(containerpath, optarg, strlen(optarg) + 1);
+ break;
case 'w':
logfile = strdup(optarg);
printf("write to file %s\n", logfile);
@@ -335,6 +351,11 @@ int main(int argc, char *argv[])
}
}
+ if (tid && containerset) {
+ fprintf(stderr, "Select either -t or -C, not both\n");
+ goto err;
+ }
+
if (tid) {
rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET,
cmd_type, &tid, sizeof(__u32));
@@ -345,6 +366,20 @@ int main(int argc, char *argv[])
}
}
+ if (containerset) {
+ cfd = open(containerpath, O_RDONLY);
+ if (cfd < 0) {
+ perror("error opening container file");
+ goto err;
+ }
+ rc = send_cmd(nl_sd, id, mypid, CGROUPSTATS_CMD_GET,
+ CGROUPSTATS_CMD_ATTR_FD, &cfd, sizeof(__u32));
+ if (rc < 0) {
+ perror("error sending cgroupstats command");
+ goto err;
+ }
+ }
+
do {
int i;
@@ -423,6 +458,9 @@ int main(int argc, char *argv[])
}
break;
+ case CGROUPSTATS_TYPE_CGROUP_STATS:
+ print_cgroupstats(NLA_DATA(na));
+ break;
default:
fprintf(stderr, "Unknown nla_type %d\n",
na->nla_type);
@@ -444,5 +482,7 @@ err:
close(nl_sd);
if (fd)
close(fd);
+ if (cfd)
+ close(cfd);
return 0;
}
diff --git a/Documentation/arm/00-INDEX b/Documentation/arm/00-INDEX
index 2c6a3b38967e..82e418d648d0 100644
--- a/Documentation/arm/00-INDEX
+++ b/Documentation/arm/00-INDEX
@@ -4,19 +4,29 @@ Booting
- requirements for booting
Interrupts
- ARM Interrupt subsystem documentation
+IXP2000
+ - Release Notes for Linux on Intel's IXP2000 Network Processor
Netwinder
- Netwinder specific documentation
+Porting
+ - Symbol definitions for porting Linux to a new ARM machine.
+Setup
+ - Kernel initialization parameters on ARM Linux
README
- General ARM documentation
-SA1100
+SA1100/
- SA1100 documentation
-XScale
- - XScale documentation
-empeg
- - Empeg documentation
+Samsung-S3C24XX
+ - S3C24XX ARM Linux Overview
+Sharp-LH
+ - Linux on Sharp LH79524 and LH7A40X System On a Chip (SOC)
+VFP/
+ - Release notes for Linux Kernel Vector Floating Point support code
+empeg/
+ - Ltd's Empeg MP3 Car Audio Player
mem_alignment
- alignment abort handler documentation
memory.txt
- description of the virtual memory layout
-nwfpe
+nwfpe/
- NWFPE floating point emulator documentation
diff --git a/Documentation/arm/Samsung-S3C24XX/DMA.txt b/Documentation/arm/Samsung-S3C24XX/DMA.txt
index 37f4edcc5d87..3ed82383efea 100644
--- a/Documentation/arm/Samsung-S3C24XX/DMA.txt
+++ b/Documentation/arm/Samsung-S3C24XX/DMA.txt
@@ -5,7 +5,7 @@ Introduction
------------
The kernel provides an interface to manage DMA transfers
- using the DMA channels in the cpu, so that the central
+ using the DMA channels in the CPU, so that the central
duty of managing channel mappings, and programming the
channel generators is in one place.
@@ -17,24 +17,24 @@ DMA Channel Ordering
channels to all sources, which means that some devices
have a restricted number of channels that can be used.
- To allow flexibilty for each cpu type and board, the
- dma code can be given an dma ordering structure which
+ To allow flexibility for each CPU type and board, the
+ DMA code can be given a DMA ordering structure which
allows the order of channel search to be specified, as
well as allowing the prohibition of certain claims.
struct s3c24xx_dma_order has a list of channels, and
- each channel within has a slot for a list of dma
- channel numbers. The slots are searched in order, for
- the presence of a dma channel number with DMA_CH_VALID
- orred in.
+ each channel within has a slot for a list of DMA
+ channel numbers. The slots are searched in order for
+ the presence of a DMA channel number with DMA_CH_VALID
+ or-ed in.
If the order has the flag DMA_CH_NEVER set, then after
checking the channel list, the system will return no
found channel, thus denying the request.
A board support file can call s3c24xx_dma_order_set()
- to register an complete ordering set. The routine will
- copy the data, so the original can be discared with
+ to register a complete ordering set. The routine will
+ copy the data, so the original can be discarded with
__initdata.
diff --git a/Documentation/atomic_ops.txt b/Documentation/atomic_ops.txt
index 05851e9982ed..f20c10c2858f 100644
--- a/Documentation/atomic_ops.txt
+++ b/Documentation/atomic_ops.txt
@@ -14,8 +14,15 @@ suffice:
typedef struct { volatile int counter; } atomic_t;
- The first operations to implement for atomic_t's are the
-initializers and plain reads.
+Historically, counter has been declared volatile. This is now discouraged.
+See Documentation/volatile-considered-harmful.txt for the complete rationale.
+
+local_t is very similar to atomic_t. If the counter is per CPU and only
+updated by one CPU, local_t is probably more appropriate. Please see
+Documentation/local_ops.txt for the semantics of local_t.
+
+The first operations to implement for atomic_t's are the initializers and
+plain reads.
#define ATOMIC_INIT(i) { (i) }
#define atomic_set(v, i) ((v)->counter = (i))
@@ -24,6 +31,12 @@ The first macro is used in definitions, such as:
static atomic_t my_counter = ATOMIC_INIT(1);
+The initializer is atomic in that the return values of the atomic operations
+are guaranteed to be correct reflecting the initialized value if the
+initializer is used before runtime. If the initializer is used at runtime, a
+proper implicit or explicit read memory barrier is needed before reading the
+value with atomic_read from another thread.
+
The second interface can be used at runtime, as in:
struct foo { atomic_t counter; };
@@ -36,13 +49,43 @@ The second interface can be used at runtime, as in:
return -ENOMEM;
atomic_set(&k->counter, 0);
+The setting is atomic in that the return values of the atomic operations by
+all threads are guaranteed to be correct reflecting either the value that has
+been set with this operation or set with another operation. A proper implicit
+or explicit memory barrier is needed before the value set with the operation
+is guaranteed to be readable with atomic_read from another thread.
+
Next, we have:
#define atomic_read(v) ((v)->counter)
-which simply reads the current value of the counter.
-
-Now, we move onto the actual atomic operation interfaces.
+which simply reads the counter value currently visible to the calling thread.
+The read is atomic in that the return value is guaranteed to be one of the
+values initialized or modified with the interface operations if a proper
+implicit or explicit memory barrier is used after possible runtime
+initialization by any other thread and the value is modified only with the
+interface operations. atomic_read does not guarantee that the runtime
+initialization by any other thread is visible yet, so the user of the
+interface must take care of that with a proper implicit or explicit memory
+barrier.
+
+*** WARNING: atomic_read() and atomic_set() DO NOT IMPLY BARRIERS! ***
+
+Some architectures may choose to use the volatile keyword, barriers, or inline
+assembly to guarantee some degree of immediacy for atomic_read() and
+atomic_set(). This is not uniformly guaranteed, and may change in the future,
+so all users of atomic_t should treat atomic_read() and atomic_set() as simple
+C statements that may be reordered or optimized away entirely by the compiler
+or processor, and explicitly invoke the appropriate compiler and/or memory
+barrier for each use case. Failure to do so will result in code that may
+suddenly break when used with different architectures or compiler
+optimizations, or even changes in unrelated code which changes how the
+compiler optimizes the section accessing atomic_t variables.
+
+*** YOU HAVE BEEN WARNED! ***
+
+Now, we move onto the atomic operation interfaces typically implemented with
+the help of assembly code.
void atomic_add(int i, atomic_t *v);
void atomic_sub(int i, atomic_t *v);
@@ -117,6 +160,12 @@ operation.
Then:
+ int atomic_xchg(atomic_t *v, int new);
+
+This performs an atomic exchange operation on the atomic variable v, setting
+the given new value. It returns the old value that the atomic variable v had
+just before the operation.
+
int atomic_cmpxchg(atomic_t *v, int old, int new);
This performs an atomic compare exchange operation on the atomic value v,
@@ -369,6 +418,20 @@ brothers:
*/
smp_mb__after_clear_bit();
+There are two special bitops with lock barrier semantics (acquire/release,
+same as spinlocks). These operate in the same way as their non-_lock/unlock
+postfixed variants, except that they are to provide acquire/release semantics,
+respectively. This means they can be used for bit_spin_trylock and
+bit_spin_unlock type operations without specifying any more barriers.
+
+ int test_and_set_bit_lock(unsigned long nr, unsigned long *addr);
+ void clear_bit_unlock(unsigned long nr, unsigned long *addr);
+ void __clear_bit_unlock(unsigned long nr, unsigned long *addr);
+
+The __clear_bit_unlock version is non-atomic, however it still implements
+unlock barrier semantics. This can be useful if the lock itself is protecting
+the other bits in the word.
+
Finally, there are non-atomic versions of the bitmask operations
provided. They are used in contexts where some other higher-level SMP
locking scheme is being used to protect the bitmask, and thus less
diff --git a/Documentation/block/00-INDEX b/Documentation/block/00-INDEX
new file mode 100644
index 000000000000..961a0513f8c3
--- /dev/null
+++ b/Documentation/block/00-INDEX
@@ -0,0 +1,20 @@
+00-INDEX
+ - This file
+as-iosched.txt
+ - Anticipatory IO scheduler
+barrier.txt
+ - I/O Barriers
+biodoc.txt
+ - Notes on the Generic Block Layer Rewrite in Linux 2.5
+capability.txt
+ - Generic Block Device Capability (/sys/block/<disk>/capability)
+deadline-iosched.txt
+ - Deadline IO scheduler tunables
+ioprio.txt
+ - Block io priorities (in CFQ scheduler)
+request.txt
+ - The members of struct request (in include/linux/blkdev.h)
+stat.txt
+ - Block layer statistics in /sys/block/<dev>/stat
+switching-sched.txt
+ - Switching I/O schedulers at runtime
diff --git a/Documentation/block/as-iosched.txt b/Documentation/block/as-iosched.txt
index a598fe10a297..738b72be128e 100644
--- a/Documentation/block/as-iosched.txt
+++ b/Documentation/block/as-iosched.txt
@@ -20,15 +20,10 @@ actually has a head for each physical device in the logical RAID device.
However, setting the antic_expire (see tunable parameters below) produces
very similar behavior to the deadline IO scheduler.
-
Selecting IO schedulers
-----------------------
-To choose IO schedulers at boot time, use the argument 'elevator=deadline'.
-'noop', 'as' and 'cfq' (the default) are also available. IO schedulers are
-assigned globally at boot time only presently. It's also possible to change
-the IO scheduler for a determined device on the fly, as described in
-Documentation/block/switching-sched.txt.
-
+Refer to Documentation/block/switching-sched.txt for information on
+selecting an io scheduler on a per-device basis.
Anticipatory IO scheduler Policies
----------------------------------
@@ -115,7 +110,7 @@ statistics (average think time, average seek distance) on the process
that submitted the just completed request are examined. If it seems
likely that that process will submit another request soon, and that
request is likely to be near the just completed request, then the IO
-scheduler will stop dispatching more read requests for up time (antic_expire)
+scheduler will stop dispatching more read requests for up to (antic_expire)
milliseconds, hoping that process will submit a new request near the one
that just completed. If such a request is made, then it is dispatched
immediately. If the antic_expire wait time expires, then the IO scheduler
@@ -165,3 +160,13 @@ The parameters are:
for big seek time devices though not a linear correspondence - most
processes have only a few ms thinktime.
+In addition to the tunables above there is a read-only file named est_time
+which, when read, will show:
+
+ - The probability of a task exiting without a cooperating task
+ submitting an anticipated IO.
+
+ - The current mean think time.
+
+ - The seek distance used to determine if an incoming IO is better.
+
diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt
index dc3f49e3e539..93f223b9723f 100644
--- a/Documentation/block/biodoc.txt
+++ b/Documentation/block/biodoc.txt
@@ -2,7 +2,7 @@
=====================================================
Notes Written on Jan 15, 2002:
- Jens Axboe <axboe@suse.de>
+ Jens Axboe <jens.axboe@oracle.com>
Suparna Bhattacharya <suparna@in.ibm.com>
Last Updated May 2, 2002
@@ -21,7 +21,7 @@ Credits:
---------
2.5 bio rewrite:
- Jens Axboe <axboe@suse.de>
+ Jens Axboe <jens.axboe@oracle.com>
Many aspects of the generic block layer redesign were driven by and evolved
over discussions, prior patches and the collective experience of several
diff --git a/Documentation/block/deadline-iosched.txt b/Documentation/block/deadline-iosched.txt
index be08ffd1e9b8..c23cab13c3d1 100644
--- a/Documentation/block/deadline-iosched.txt
+++ b/Documentation/block/deadline-iosched.txt
@@ -5,16 +5,10 @@ This little file attempts to document how the deadline io scheduler works.
In particular, it will clarify the meaning of the exposed tunables that may be
of interest to power users.
-Each io queue has a set of io scheduler tunables associated with it. These
-tunables control how the io scheduler works. You can find these entries
-in:
-
-/sys/block/<device>/queue/iosched
-
-assuming that you have sysfs mounted on /sys. If you don't have sysfs mounted,
-you can do so by typing:
-
-# mount none /sys -t sysfs
+Selecting IO schedulers
+-----------------------
+Refer to Documentation/block/switching-sched.txt for information on
+selecting an io scheduler on a per-device basis.
********************************************************************************
@@ -41,14 +35,11 @@ fifo_batch
When a read request expires its deadline, we must move some requests from
the sorted io scheduler list to the block device dispatch queue. fifo_batch
-controls how many requests we move, based on the cost of each request. A
-request is either qualified as a seek or a stream. The io scheduler knows
-the last request that was serviced by the drive (or will be serviced right
-before this one). See seek_cost and stream_unit.
+controls how many requests we move.
-write_starved (number of dispatches)
--------------
+writes_starved (number of dispatches)
+--------------
When we have to move requests from the io scheduler queue to the block
device dispatch queue, we always give a preference to reads. However, we
@@ -73,6 +64,6 @@ that comes at basically 0 cost we leave that on. We simply disable the
rbtree front sector lookup when the io scheduler merge function is called.
-Nov 11 2002, Jens Axboe <axboe@suse.de>
+Nov 11 2002, Jens Axboe <jens.axboe@oracle.com>
diff --git a/Documentation/block/ioprio.txt b/Documentation/block/ioprio.txt
index 35e516b0b8a9..8ed8c59380b4 100644
--- a/Documentation/block/ioprio.txt
+++ b/Documentation/block/ioprio.txt
@@ -180,4 +180,4 @@ int main(int argc, char *argv[])
---> snip ionice.c tool <---
-March 11 2005, Jens Axboe <axboe@suse.de>
+March 11 2005, Jens Axboe <jens.axboe@oracle.com>
diff --git a/Documentation/block/request.txt b/Documentation/block/request.txt
index fff58acb40a3..754e104ed369 100644
--- a/Documentation/block/request.txt
+++ b/Documentation/block/request.txt
@@ -1,7 +1,7 @@
struct request documentation
-Jens Axboe <axboe@suse.de> 27/05/02
+Jens Axboe <jens.axboe@oracle.com> 27/05/02
1.0
Index
diff --git a/Documentation/block/switching-sched.txt b/Documentation/block/switching-sched.txt
index 5fa130a67531..634c952e1964 100644
--- a/Documentation/block/switching-sched.txt
+++ b/Documentation/block/switching-sched.txt
@@ -1,3 +1,18 @@
+To choose IO schedulers at boot time, use the argument 'elevator=deadline'.
+'noop', 'as' and 'cfq' (the default) are also available. IO schedulers are
+assigned globally at boot time only presently.
+
+Each io queue has a set of io scheduler tunables associated with it. These
+tunables control how the io scheduler works. You can find these entries
+in:
+
+/sys/block/<device>/queue/iosched
+
+assuming that you have sysfs mounted on /sys. If you don't have sysfs mounted,
+you can do so by typing:
+
+# mount none /sys -t sysfs
+
As of the Linux 2.6.10 kernel, it is now possible to change the
IO scheduler for a given block device on the fly (thus making it possible,
for instance, to set the CFQ scheduler for the system default, but
@@ -20,3 +35,9 @@ noop anticipatory deadline [cfq]
# echo anticipatory > /sys/block/hda/queue/scheduler
# cat /sys/block/hda/queue/scheduler
noop [anticipatory] deadline cfq
+
+Each io queue has a set of io scheduler tunables associated with it. These
+tunables control how the io scheduler works. You can find these entries
+in:
+
+/sys/block/<device>/queue/iosched
diff --git a/Documentation/cachetlb.txt b/Documentation/cachetlb.txt
index 866b76139420..da42ab414c48 100644
--- a/Documentation/cachetlb.txt
+++ b/Documentation/cachetlb.txt
@@ -87,30 +87,7 @@ changes occur:
This is used primarily during fault processing.
-5) void flush_tlb_pgtables(struct mm_struct *mm,
- unsigned long start, unsigned long end)
-
- The software page tables for address space 'mm' for virtual
- addresses in the range 'start' to 'end-1' are being torn down.
-
- Some platforms cache the lowest level of the software page tables
- in a linear virtually mapped array, to make TLB miss processing
- more efficient. On such platforms, since the TLB is caching the
- software page table structure, it needs to be flushed when parts
- of the software page table tree are unlinked/freed.
-
- Sparc64 is one example of a platform which does this.
-
- Usually, when munmap()'ing an area of user virtual address
- space, the kernel leaves the page table parts around and just
- marks the individual pte's as invalid. However, if very large
- portions of the address space are unmapped, the kernel frees up
- those portions of the software page tables to prevent potential
- excessive kernel memory usage caused by erratic mmap/mmunmap
- sequences. It is at these times that flush_tlb_pgtables will
- be invoked.
-
-6) void update_mmu_cache(struct vm_area_struct *vma,
+5) void update_mmu_cache(struct vm_area_struct *vma,
unsigned long address, pte_t pte)
At the end of every page fault, this routine is invoked to
@@ -123,7 +100,7 @@ changes occur:
translations for software managed TLB configurations.
The sparc64 port currently does this.
-7) void tlb_migrate_finish(struct mm_struct *mm)
+6) void tlb_migrate_finish(struct mm_struct *mm)
This interface is called at the end of an explicit
process migration. This interface provides a hook
@@ -133,12 +110,6 @@ changes occur:
The ia64 sn2 platform is one example of a platform
that uses this interface.
-8) void lazy_mmu_prot_update(pte_t pte)
- This interface is called whenever the protection on
- any user PTEs change. This interface provides a notification
- to architecture specific code to take appropriate action.
-
-
Next, we have the cache flushing interfaces. In general, when Linux
is changing an existing virtual-->physical mapping to a new value,
the sequence will be in one of the following forms:
diff --git a/Documentation/cdrom/cdrom-standard.tex b/Documentation/cdrom/cdrom-standard.tex
index 92f94e597582..c713aeb020c4 100644
--- a/Documentation/cdrom/cdrom-standard.tex
+++ b/Documentation/cdrom/cdrom-standard.tex
@@ -1009,7 +1009,7 @@ taken over the torch in maintaining \cdromc\ and integrating much
\cdrom-related code in the 2.1-kernel. Thanks to Scott Snyder and
Gerd Knorr, who were the first to implement this interface for SCSI
and IDE-CD drivers and added many ideas for extension of the data
-structures relative to kernel~2.0. Further thanks to Heiko Eissfeldt,
+structures relative to kernel~2.0. Further thanks to Heiko Ei{\sz}feldt,
Thomas Quinot, Jon Tombs, Ken Pizzini, Eberhard M\"onkeberg and Andrew
Kroll, the \linux\ \cdrom\ device driver developers who were kind
enough to give suggestions and criticisms during the writing. Finally
diff --git a/Documentation/cgroups.txt b/Documentation/cgroups.txt
new file mode 100644
index 000000000000..98a26f81fa75
--- /dev/null
+++ b/Documentation/cgroups.txt
@@ -0,0 +1,545 @@
+ CGROUPS
+ -------
+
+Written by Paul Menage <menage@google.com> based on Documentation/cpusets.txt
+
+Original copyright statements from cpusets.txt:
+Portions Copyright (C) 2004 BULL SA.
+Portions Copyright (c) 2004-2006 Silicon Graphics, Inc.
+Modified by Paul Jackson <pj@sgi.com>
+Modified by Christoph Lameter <clameter@sgi.com>
+
+CONTENTS:
+=========
+
+1. Control Groups
+ 1.1 What are cgroups ?
+ 1.2 Why are cgroups needed ?
+ 1.3 How are cgroups implemented ?
+ 1.4 What does notify_on_release do ?
+ 1.5 How do I use cgroups ?
+2. Usage Examples and Syntax
+ 2.1 Basic Usage
+ 2.2 Attaching processes
+3. Kernel API
+ 3.1 Overview
+ 3.2 Synchronization
+ 3.3 Subsystem API
+4. Questions
+
+1. Control Groups
+==========
+
+1.1 What are cgroups ?
+----------------------
+
+Control Groups provide a mechanism for aggregating/partitioning sets of
+tasks, and all their future children, into hierarchical groups with
+specialized behaviour.
+
+Definitions:
+
+A *cgroup* associates a set of tasks with a set of parameters for one
+or more subsystems.
+
+A *subsystem* is a module that makes use of the task grouping
+facilities provided by cgroups to treat groups of tasks in
+particular ways. A subsystem is typically a "resource controller" that
+schedules a resource or applies per-cgroup limits, but it may be
+anything that wants to act on a group of processes, e.g. a
+virtualization subsystem.
+
+A *hierarchy* is a set of cgroups arranged in a tree, such that
+every task in the system is in exactly one of the cgroups in the
+hierarchy, and a set of subsystems; each subsystem has system-specific
+state attached to each cgroup in the hierarchy. Each hierarchy has
+an instance of the cgroup virtual filesystem associated with it.
+
+At any one time there may be multiple active hierachies of task
+cgroups. Each hierarchy is a partition of all tasks in the system.
+
+User level code may create and destroy cgroups by name in an
+instance of the cgroup virtual file system, specify and query to
+which cgroup a task is assigned, and list the task pids assigned to
+a cgroup. Those creations and assignments only affect the hierarchy
+associated with that instance of the cgroup file system.
+
+On their own, the only use for cgroups is for simple job
+tracking. The intention is that other subsystems hook into the generic
+cgroup support to provide new attributes for cgroups, such as
+accounting/limiting the resources which processes in a cgroup can
+access. For example, cpusets (see Documentation/cpusets.txt) allows
+you to associate a set of CPUs and a set of memory nodes with the
+tasks in each cgroup.
+
+1.2 Why are cgroups needed ?
+----------------------------
+
+There are multiple efforts to provide process aggregations in the
+Linux kernel, mainly for resource tracking purposes. Such efforts
+include cpusets, CKRM/ResGroups, UserBeanCounters, and virtual server
+namespaces. These all require the basic notion of a
+grouping/partitioning of processes, with newly forked processes ending
+in the same group (cgroup) as their parent process.
+
+The kernel cgroup patch provides the minimum essential kernel
+mechanisms required to efficiently implement such groups. It has
+minimal impact on the system fast paths, and provides hooks for
+specific subsystems such as cpusets to provide additional behaviour as
+desired.
+
+Multiple hierarchy support is provided to allow for situations where
+the division of tasks into cgroups is distinctly different for
+different subsystems - having parallel hierarchies allows each
+hierarchy to be a natural division of tasks, without having to handle
+complex combinations of tasks that would be present if several
+unrelated subsystems needed to be forced into the same tree of
+cgroups.
+
+At one extreme, each resource controller or subsystem could be in a
+separate hierarchy; at the other extreme, all subsystems
+would be attached to the same hierarchy.
+
+As an example of a scenario (originally proposed by vatsa@in.ibm.com)
+that can benefit from multiple hierarchies, consider a large
+university server with various users - students, professors, system
+tasks etc. The resource planning for this server could be along the
+following lines:
+
+ CPU : Top cpuset
+ / \
+ CPUSet1 CPUSet2
+ | |
+ (Profs) (Students)
+
+ In addition (system tasks) are attached to topcpuset (so
+ that they can run anywhere) with a limit of 20%
+
+ Memory : Professors (50%), students (30%), system (20%)
+
+ Disk : Prof (50%), students (30%), system (20%)
+
+ Network : WWW browsing (20%), Network File System (60%), others (20%)
+ / \
+ Prof (15%) students (5%)
+
+Browsers like firefox/lynx go into the WWW network class, while (k)nfsd go
+into NFS network class.
+
+At the same time firefox/lynx will share an appropriate CPU/Memory class
+depending on who launched it (prof/student).
+
+With the ability to classify tasks differently for different resources
+(by putting those resource subsystems in different hierarchies) then
+the admin can easily set up a script which receives exec notifications
+and depending on who is launching the browser he can
+
+ # echo browser_pid > /mnt/<restype>/<userclass>/tasks
+
+With only a single hierarchy, he now would potentially have to create
+a separate cgroup for every browser launched and associate it with
+approp network and other resource class. This may lead to
+proliferation of such cgroups.
+
+Also lets say that the administrator would like to give enhanced network
+access temporarily to a student's browser (since it is night and the user
+wants to do online gaming :) OR give one of the students simulation
+apps enhanced CPU power,
+
+With ability to write pids directly to resource classes, its just a
+matter of :
+
+ # echo pid > /mnt/network/<new_class>/tasks
+ (after some time)
+ # echo pid > /mnt/network/<orig_class>/tasks
+
+Without this ability, he would have to split the cgroup into
+multiple separate ones and then associate the new cgroups with the
+new resource classes.
+
+
+
+1.3 How are cgroups implemented ?
+---------------------------------
+
+Control Groups extends the kernel as follows:
+
+ - Each task in the system has a reference-counted pointer to a
+ css_set.
+
+ - A css_set contains a set of reference-counted pointers to
+ cgroup_subsys_state objects, one for each cgroup subsystem
+ registered in the system. There is no direct link from a task to
+ the cgroup of which it's a member in each hierarchy, but this
+ can be determined by following pointers through the
+ cgroup_subsys_state objects. This is because accessing the
+ subsystem state is something that's expected to happen frequently
+ and in performance-critical code, whereas operations that require a
+ task's actual cgroup assignments (in particular, moving between
+ cgroups) are less common. A linked list runs through the cg_list
+ field of each task_struct using the css_set, anchored at
+ css_set->tasks.
+
+ - A cgroup hierarchy filesystem can be mounted for browsing and
+ manipulation from user space.
+
+ - You can list all the tasks (by pid) attached to any cgroup.
+
+The implementation of cgroups requires a few, simple hooks
+into the rest of the kernel, none in performance critical paths:
+
+ - in init/main.c, to initialize the root cgroups and initial
+ css_set at system boot.
+
+ - in fork and exit, to attach and detach a task from its css_set.
+
+In addition a new file system, of type "cgroup" may be mounted, to
+enable browsing and modifying the cgroups presently known to the
+kernel. When mounting a cgroup hierarchy, you may specify a
+comma-separated list of subsystems to mount as the filesystem mount
+options. By default, mounting the cgroup filesystem attempts to
+mount a hierarchy containing all registered subsystems.
+
+If an active hierarchy with exactly the same set of subsystems already
+exists, it will be reused for the new mount. If no existing hierarchy
+matches, and any of the requested subsystems are in use in an existing
+hierarchy, the mount will fail with -EBUSY. Otherwise, a new hierarchy
+is activated, associated with the requested subsystems.
+
+It's not currently possible to bind a new subsystem to an active
+cgroup hierarchy, or to unbind a subsystem from an active cgroup
+hierarchy. This may be possible in future, but is fraught with nasty
+error-recovery issues.
+
+When a cgroup filesystem is unmounted, if there are any
+child cgroups created below the top-level cgroup, that hierarchy
+will remain active even though unmounted; if there are no
+child cgroups then the hierarchy will be deactivated.
+
+No new system calls are added for cgroups - all support for
+querying and modifying cgroups is via this cgroup file system.
+
+Each task under /proc has an added file named 'cgroup' displaying,
+for each active hierarchy, the subsystem names and the cgroup name
+as the path relative to the root of the cgroup file system.
+
+Each cgroup is represented by a directory in the cgroup file system
+containing the following files describing that cgroup:
+
+ - tasks: list of tasks (by pid) attached to that cgroup
+ - notify_on_release flag: run /sbin/cgroup_release_agent on exit?
+
+Other subsystems such as cpusets may add additional files in each
+cgroup dir
+
+New cgroups are created using the mkdir system call or shell
+command. The properties of a cgroup, such as its flags, are
+modified by writing to the appropriate file in that cgroups
+directory, as listed above.
+
+The named hierarchical structure of nested cgroups allows partitioning
+a large system into nested, dynamically changeable, "soft-partitions".
+
+The attachment of each task, automatically inherited at fork by any
+children of that task, to a cgroup allows organizing the work load
+on a system into related sets of tasks. A task may be re-attached to
+any other cgroup, if allowed by the permissions on the necessary
+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.
+
+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;
+each cg_cgroup_link is linked into a list of cg_cgroup_links for
+a single cgroup on its cont_link_list field, and a list of
+cg_cgroup_links for a single css_set on its cg_link_list.
+
+Thus the set of tasks in a cgroup can be listed by iterating over
+each css_set that references the cgroup, and sub-iterating over
+each css_set's task set.
+
+The use of a Linux virtual file system (vfs) to represent the
+cgroup hierarchy provides for a familiar permission and name space
+for cgroups, with a minimum of additional kernel code.
+
+1.4 What does notify_on_release do ?
+------------------------------------
+
+*** notify_on_release is disabled in the current patch set. It will be
+*** reactivated in a future patch in a less-intrusive manner
+
+If the notify_on_release flag is enabled (1) in a cgroup, then
+whenever the last task in the cgroup leaves (exits or attaches to
+some other cgroup) and the last child cgroup of that cgroup
+is removed, then the kernel runs the command specified by the contents
+of the "release_agent" file in that hierarchy's root directory,
+supplying the pathname (relative to the mount point of the cgroup
+file system) of the abandoned cgroup. This enables automatic
+removal of abandoned cgroups. The default value of
+notify_on_release in the root cgroup at system boot is disabled
+(0). The default value of other cgroups at creation is the current
+value of their parents notify_on_release setting. The default value of
+a cgroup hierarchy's release_agent path is empty.
+
+1.5 How do I use cgroups ?
+--------------------------
+
+To start a new job that is to be contained within a cgroup, using
+the "cpuset" cgroup subsystem, the steps are something like:
+
+ 1) mkdir /dev/cgroup
+ 2) mount -t cgroup -ocpuset cpuset /dev/cgroup
+ 3) Create the new cgroup by doing mkdir's and write's (or echo's) in
+ the /dev/cgroup virtual file system.
+ 4) Start a task that will be the "founding father" of the new job.
+ 5) Attach that task to the new cgroup by writing its pid to the
+ /dev/cgroup tasks file for that cgroup.
+ 6) fork, exec or clone the job tasks from this founding father task.
+
+For example, the following sequence of commands will setup a cgroup
+named "Charlie", containing just CPUs 2 and 3, and Memory Node 1,
+and then start a subshell 'sh' in that cgroup:
+
+ mount -t cgroup cpuset -ocpuset /dev/cgroup
+ cd /dev/cgroup
+ mkdir Charlie
+ cd Charlie
+ /bin/echo 2-3 > cpus
+ /bin/echo 1 > mems
+ /bin/echo $$ > tasks
+ sh
+ # The subshell 'sh' is now running in cgroup Charlie
+ # The next line should display '/Charlie'
+ cat /proc/self/cgroup
+
+2. Usage Examples and Syntax
+============================
+
+2.1 Basic Usage
+---------------
+
+Creating, modifying, using the cgroups can be done through the cgroup
+virtual filesystem.
+
+To mount a cgroup hierarchy will all available subsystems, type:
+# mount -t cgroup xxx /dev/cgroup
+
+The "xxx" is not interpreted by the cgroup code, but will appear in
+/proc/mounts so may be any useful identifying string that you like.
+
+To mount a cgroup hierarchy with just the cpuset and numtasks
+subsystems, type:
+# mount -t cgroup -o cpuset,numtasks hier1 /dev/cgroup
+
+To change the set of subsystems bound to a mounted hierarchy, just
+remount with different options:
+
+# mount -o remount,cpuset,ns /dev/cgroup
+
+Note that changing the set of subsystems is currently only supported
+when the hierarchy consists of a single (root) cgroup. Supporting
+the ability to arbitrarily bind/unbind subsystems from an existing
+cgroup hierarchy is intended to be implemented in the future.
+
+Then under /dev/cgroup you can find a tree that corresponds to the
+tree of the cgroups in the system. For instance, /dev/cgroup
+is the cgroup that holds the whole system.
+
+If you want to create a new cgroup under /dev/cgroup:
+# cd /dev/cgroup
+# mkdir my_cgroup
+
+Now you want to do something with this cgroup.
+# cd my_cgroup
+
+In this directory you can find several files:
+# ls
+notify_on_release release_agent tasks
+(plus whatever files are added by the attached subsystems)
+
+Now attach your shell to this cgroup:
+# /bin/echo $$ > tasks
+
+You can also create cgroups inside your cgroup by using mkdir in this
+directory.
+# mkdir my_sub_cs
+
+To remove a cgroup, just use rmdir:
+# rmdir my_sub_cs
+
+This will fail if the cgroup is in use (has cgroups inside, or
+has processes attached, or is held alive by other subsystem-specific
+reference).
+
+2.2 Attaching processes
+-----------------------
+
+# /bin/echo PID > tasks
+
+Note that it is PID, not PIDs. You can only attach ONE task at a time.
+If you have several tasks to attach, you have to do it one after another:
+
+# /bin/echo PID1 > tasks
+# /bin/echo PID2 > tasks
+ ...
+# /bin/echo PIDn > tasks
+
+3. Kernel API
+=============
+
+3.1 Overview
+------------
+
+Each kernel subsystem that wants to hook into the generic cgroup
+system needs to create a cgroup_subsys object. This contains
+various methods, which are callbacks from the cgroup system, along
+with a subsystem id which will be assigned by the cgroup system.
+
+Other fields in the cgroup_subsys object include:
+
+- subsys_id: a unique array index for the subsystem, indicating which
+ entry in cgroup->subsys[] this subsystem should be
+ managing. Initialized by cgroup_register_subsys(); prior to this
+ it should be initialized to -1
+
+- hierarchy: an index indicating which hierarchy, if any, this
+ subsystem is currently attached to. If this is -1, then the
+ subsystem is not attached to any hierarchy, and all tasks should be
+ considered to be members of the subsystem's top_cgroup. It should
+ be initialized to -1.
+
+- name: should be initialized to a unique subsystem name prior to
+ calling cgroup_register_subsystem. Should be no longer than
+ MAX_CGROUP_TYPE_NAMELEN
+
+Each cgroup object created by the system has an array of pointers,
+indexed by subsystem id; this pointer is entirely managed by the
+subsystem; the generic cgroup code will never touch this pointer.
+
+3.2 Synchronization
+-------------------
+
+There is a global mutex, cgroup_mutex, used by the cgroup
+system. This should be taken by anything that wants to modify a
+cgroup. It may also be taken to prevent cgroups from being
+modified, but more specific locks may be more appropriate in that
+situation.
+
+See kernel/cgroup.c for more details.
+
+Subsystems can take/release the cgroup_mutex via the functions
+cgroup_lock()/cgroup_unlock(), and can
+take/release the callback_mutex via the functions
+cgroup_lock()/cgroup_unlock().
+
+Accessing a task's cgroup pointer may be done in the following ways:
+- while holding cgroup_mutex
+- while holding the task's alloc_lock (via task_lock())
+- inside an rcu_read_lock() section via rcu_dereference()
+
+3.3 Subsystem API
+--------------------------
+
+Each subsystem should:
+
+- add an entry in linux/cgroup_subsys.h
+- define a cgroup_subsys object called <name>_subsys
+
+Each subsystem may export the following methods. The only mandatory
+methods are create/destroy. Any others that are null are presumed to
+be successful no-ops.
+
+struct cgroup_subsys_state *create(struct cgroup *cont)
+LL=cgroup_mutex
+
+Called to create a subsystem state object for a cgroup. The
+subsystem should allocate its subsystem state object for the passed
+cgroup, returning a pointer to the new object on success or a
+negative error code. On success, the subsystem pointer should point to
+a structure of type cgroup_subsys_state (typically embedded in a
+larger subsystem-specific object), which will be initialized by the
+cgroup system. Note that this will be called at initialization to
+create the root subsystem state for this subsystem; this case can be
+identified by the passed cgroup object having a NULL parent (since
+it's the root of the hierarchy) and may be an appropriate place for
+initialization code.
+
+void destroy(struct cgroup *cont)
+LL=cgroup_mutex
+
+The cgroup system is about to destroy the passed cgroup; the
+subsystem should do any necessary cleanup
+
+int can_attach(struct cgroup_subsys *ss, struct cgroup *cont,
+ struct task_struct *task)
+LL=cgroup_mutex
+
+Called prior to moving a task into a cgroup; if the subsystem
+returns an error, this will abort the attach operation. If a NULL
+task is passed, then a successful result indicates that *any*
+unspecified task can be moved into the cgroup. Note that this isn't
+called on a fork. If this method returns 0 (success) then this should
+remain valid while the caller holds cgroup_mutex.
+
+void attach(struct cgroup_subsys *ss, struct cgroup *cont,
+ struct cgroup *old_cont, struct task_struct *task)
+LL=cgroup_mutex
+
+
+Called after the task has been attached to the cgroup, to allow any
+post-attachment activity that requires memory allocations or blocking.
+
+void fork(struct cgroup_subsy *ss, struct task_struct *task)
+LL=callback_mutex, maybe read_lock(tasklist_lock)
+
+Called when a task is forked into a cgroup. Also called during
+registration for all existing tasks.
+
+void exit(struct cgroup_subsys *ss, struct task_struct *task)
+LL=callback_mutex
+
+Called during task exit
+
+int populate(struct cgroup_subsys *ss, struct cgroup *cont)
+LL=none
+
+Called after creation of a cgroup to allow a subsystem to populate
+the cgroup directory with file entries. The subsystem should make
+calls to cgroup_add_file() with objects of type cftype (see
+include/linux/cgroup.h for details). Note that although this
+method can return an error code, the error code is currently not
+always handled well.
+
+void post_clone(struct cgroup_subsys *ss, struct cgroup *cont)
+
+Called at the end of cgroup_clone() to do any paramater
+initialization which might be required before a task could attach. For
+example in cpusets, no task may attach before 'cpus' and 'mems' are set
+up.
+
+void bind(struct cgroup_subsys *ss, struct cgroup *root)
+LL=callback_mutex
+
+Called when a cgroup subsystem is rebound to a different hierarchy
+and root cgroup. Currently this will only involve movement between
+the default hierarchy (which never has sub-cgroups) and a hierarchy
+that is being created/destroyed (and hence has no sub-cgroups).
+
+4. Questions
+============
+
+Q: what's up with this '/bin/echo' ?
+A: bash's builtin 'echo' command does not check calls to write() against
+ errors. If you use it in the cgroup file system, you won't be
+ able to tell whether a command succeeded or failed.
+
+Q: When I attach processes, only the first of the line gets really attached !
+A: We can only return one error code per call to write(). So you should also
+ put only ONE pid.
+
diff --git a/Documentation/cpu-hotplug.txt b/Documentation/cpu-hotplug.txt
index b6d24c22274b..a741f658a3c9 100644
--- a/Documentation/cpu-hotplug.txt
+++ b/Documentation/cpu-hotplug.txt
@@ -220,7 +220,9 @@ A: The following happen, listed in no particular order :-)
CPU_DOWN_PREPARE or CPU_DOWN_PREPARE_FROZEN, depending on whether or not the
CPU is being offlined while tasks are frozen due to a suspend operation in
progress
-- All process is migrated away from this outgoing CPU to a new CPU
+- All processes are migrated away from this outgoing CPU to new CPUs.
+ The new CPU is chosen from each process' current cpuset, which may be
+ a subset of all online CPUs.
- All interrupts targeted to this CPU is migrated to a new CPU
- timers/bottom half/task lets are also migrated to a new CPU
- Once all services are migrated, kernel calls an arch specific routine
diff --git a/Documentation/cpusets.txt b/Documentation/cpusets.txt
index f2c0a6842930..141bef1c8599 100644
--- a/Documentation/cpusets.txt
+++ b/Documentation/cpusets.txt
@@ -7,6 +7,7 @@ Written by Simon.Derr@bull.net
Portions Copyright (c) 2004-2006 Silicon Graphics, Inc.
Modified by Paul Jackson <pj@sgi.com>
Modified by Christoph Lameter <clameter@sgi.com>
+Modified by Paul Menage <menage@google.com>
CONTENTS:
=========
@@ -16,9 +17,9 @@ CONTENTS:
1.2 Why are cpusets needed ?
1.3 How are cpusets implemented ?
1.4 What are exclusive cpusets ?
- 1.5 What does notify_on_release do ?
- 1.6 What is memory_pressure ?
- 1.7 What is memory spread ?
+ 1.5 What is memory_pressure ?
+ 1.6 What is memory spread ?
+ 1.7 What is sched_load_balance ?
1.8 How do I use cpusets ?
2. Usage Examples and Syntax
2.1 Basic Usage
@@ -35,7 +36,8 @@ CONTENTS:
----------------------
Cpusets provide a mechanism for assigning a set of CPUs and Memory
-Nodes to a set of tasks.
+Nodes to a set of tasks. In this document "Memory Node" refers to
+an on-line node that contains memory.
Cpusets constrain the CPU and Memory placement of tasks to only
the resources within a tasks current cpuset. They form a nested
@@ -43,18 +45,19 @@ hierarchy visible in a virtual file system. These are the essential
hooks, beyond what is already present, required to manage dynamic
job placement on large systems.
-Each task has a pointer to a cpuset. Multiple tasks may reference
-the same cpuset. Requests by a task, using the sched_setaffinity(2)
-system call to include CPUs in its CPU affinity mask, and using the
-mbind(2) and set_mempolicy(2) system calls to include Memory Nodes
-in its memory policy, are both filtered through that tasks cpuset,
-filtering out any CPUs or Memory Nodes not in that cpuset. The
-scheduler will not schedule a task on a CPU that is not allowed in
-its cpus_allowed vector, and the kernel page allocator will not
-allocate a page on a node that is not allowed in the requesting tasks
-mems_allowed vector.
-
-User level code may create and destroy cpusets by name in the cpuset
+Cpusets use the generic cgroup subsystem described in
+Documentation/cgroup.txt.
+
+Requests by a task, using the sched_setaffinity(2) system call to
+include CPUs in its CPU affinity mask, and using the mbind(2) and
+set_mempolicy(2) system calls to include Memory Nodes in its memory
+policy, are both filtered through that tasks cpuset, filtering out any
+CPUs or Memory Nodes not in that cpuset. The scheduler will not
+schedule a task on a CPU that is not allowed in its cpus_allowed
+vector, and the kernel page allocator will not allocate a page on a
+node that is not allowed in the requesting tasks mems_allowed vector.
+
+User level code may create and destroy cpusets by name in the cgroup
virtual file system, manage the attributes and permissions of these
cpusets and which CPUs and Memory Nodes are assigned to each cpuset,
specify and query to which cpuset a task is assigned, and list the
@@ -86,9 +89,6 @@ This can be especially valuable on:
and a database), or
* NUMA systems running large HPC applications with demanding
performance characteristics.
- * Also cpu_exclusive cpusets are useful for servers running orthogonal
- workloads such as RT applications requiring low latency and HPC
- applications that are throughput sensitive
These subsets, or "soft partitions" must be able to be dynamically
adjusted, as the job mix changes, without impacting other concurrently
@@ -117,7 +117,7 @@ Cpusets extends these two mechanisms as follows:
- Cpusets are sets of allowed CPUs and Memory Nodes, known to the
kernel.
- Each task in the system is attached to a cpuset, via a pointer
- in the task structure to a reference counted cpuset structure.
+ in the task structure to a reference counted cgroup structure.
- Calls to sched_setaffinity are filtered to just those CPUs
allowed in that tasks cpuset.
- Calls to mbind and set_mempolicy are filtered to just
@@ -131,8 +131,6 @@ Cpusets extends these two mechanisms as follows:
- A cpuset may be marked exclusive, which ensures that no other
cpuset (except direct ancestors and descendents) may contain
any overlapping CPUs or Memory Nodes.
- Also a cpu_exclusive cpuset would be associated with a sched
- domain.
- You can list all the tasks (by pid) attached to any cpuset.
The implementation of cpusets requires a few, simple hooks
@@ -144,23 +142,15 @@ into the rest of the kernel, none in performance critical paths:
allowed in that tasks cpuset.
- in sched.c migrate_all_tasks(), to keep migrating tasks within
the CPUs allowed by their cpuset, if possible.
- - in sched.c, a new API partition_sched_domains for handling
- sched domain changes associated with cpu_exclusive cpusets
- and related changes in both sched.c and arch/ia64/kernel/domain.c
- in the mbind and set_mempolicy system calls, to mask the requested
Memory Nodes by what's allowed in that tasks cpuset.
- in page_alloc.c, to restrict memory to allowed nodes.
- in vmscan.c, to restrict page recovery to the current cpuset.
-In addition a new file system, of type "cpuset" may be mounted,
-typically at /dev/cpuset, to enable browsing and modifying the cpusets
-presently known to the kernel. No new system calls are added for
-cpusets - all support for querying and modifying cpusets is via
-this cpuset file system.
-
-Each task under /proc has an added file named 'cpuset', displaying
-the cpuset name, as the path relative to the root of the cpuset file
-system.
+You should mount the "cgroup" filesystem type in order to enable
+browsing and modifying the cpusets presently known to the kernel. No
+new system calls are added for cpusets - all support for querying and
+modifying cpusets is via this cpuset file system.
The /proc/<pid>/status file for each task has two added lines,
displaying the tasks cpus_allowed (on which CPUs it may be scheduled)
@@ -170,16 +160,15 @@ in the format seen in the following example:
Cpus_allowed: ffffffff,ffffffff,ffffffff,ffffffff
Mems_allowed: ffffffff,ffffffff
-Each cpuset is represented by a directory in the cpuset file system
-containing the following files describing that cpuset:
+Each cpuset is represented by a directory in the cgroup file system
+containing (on top of the standard cgroup files) the following
+files describing that cpuset:
- cpus: list of CPUs in that cpuset
- mems: list of Memory Nodes in that cpuset
- memory_migrate flag: if set, move pages to cpusets nodes
- cpu_exclusive flag: is cpu placement exclusive?
- mem_exclusive flag: is memory placement exclusive?
- - tasks: list of tasks (by pid) attached to that cpuset
- - notify_on_release flag: run /sbin/cpuset_release_agent on exit?
- memory_pressure: measure of how much paging pressure in cpuset
In addition, the root cpuset only has the following file:
@@ -220,8 +209,8 @@ and name space for cpusets, with a minimum of additional kernel code.
The cpus and mems files in the root (top_cpuset) cpuset are
read-only. The cpus file automatically tracks the value of
cpu_online_map using a CPU hotplug notifier, and the mems file
-automatically tracks the value of node_online_map using the
-cpuset_track_online_nodes() hook.
+automatically tracks the value of node_states[N_MEMORY]--i.e.,
+nodes with memory--using the cpuset_track_online_nodes() hook.
1.4 What are exclusive cpusets ?
@@ -231,15 +220,6 @@ If a cpuset is cpu or mem exclusive, no other cpuset, other than
a direct ancestor or descendent, may share any of the same CPUs or
Memory Nodes.
-A cpuset that is cpu_exclusive has a scheduler (sched) domain
-associated with it. The sched domain consists of all CPUs in the
-current cpuset that are not part of any exclusive child cpusets.
-This ensures that the scheduler load balancing code only balances
-against the CPUs that are in the sched domain as defined above and
-not all of the CPUs in the system. This removes any overhead due to
-load balancing code trying to pull tasks outside of the cpu_exclusive
-cpuset only to be prevented by the tasks' cpus_allowed mask.
-
A cpuset that is mem_exclusive restricts kernel allocations for
page, buffer and other data commonly shared by the kernel across
multiple users. All cpusets, whether mem_exclusive or not, restrict
@@ -253,21 +233,7 @@ such as requests from interrupt handlers, is allowed to be taken
outside even a mem_exclusive cpuset.
-1.5 What does notify_on_release do ?
-------------------------------------
-
-If the notify_on_release flag is enabled (1) in a cpuset, then whenever
-the last task in the cpuset leaves (exits or attaches to some other
-cpuset) and the last child cpuset of that cpuset is removed, then
-the kernel runs the command /sbin/cpuset_release_agent, supplying the
-pathname (relative to the mount point of the cpuset file system) of the
-abandoned cpuset. This enables automatic removal of abandoned cpusets.
-The default value of notify_on_release in the root cpuset at system
-boot is disabled (0). The default value of other cpusets at creation
-is the current value of their parents notify_on_release setting.
-
-
-1.6 What is memory_pressure ?
+1.5 What is memory_pressure ?
-----------------------------
The memory_pressure of a cpuset provides a simple per-cpuset metric
of the rate that the tasks in a cpuset are attempting to free up in
@@ -324,7 +290,7 @@ the tasks in the cpuset, in units of reclaims attempted per second,
times 1000.
-1.7 What is memory spread ?
+1.6 What is memory spread ?
---------------------------
There are two boolean flag files per cpuset that control where the
kernel allocates pages for the file system buffers and related in
@@ -394,6 +360,142 @@ policy, especially for jobs that might have one thread reading in the
data set, the memory allocation across the nodes in the jobs cpuset
can become very uneven.
+1.7 What is sched_load_balance ?
+--------------------------------
+
+The kernel scheduler (kernel/sched.c) automatically load balances
+tasks. If one CPU is underutilized, kernel code running on that
+CPU will look for tasks on other more overloaded CPUs and move those
+tasks to itself, within the constraints of such placement mechanisms
+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
+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
+domain and hence won't be load balanced.
+
+Put simply, it costs less to balance between two smaller sched domains
+than one big one, but doing so means that overloads in one of the
+two domains won't be load balanced to the other one.
+
+By default, there is one sched domain covering all CPUs, except those
+marked isolated using the kernel boot time "isolcpus=" argument.
+
+This default load balancing across all CPUs is not well suited for
+the following two situations:
+ 1) On large systems, load balancing across many CPUs is expensive.
+ If the system is managed using cpusets to place independent jobs
+ on separate sets of CPUs, full load balancing is unnecessary.
+ 2) Systems supporting realtime on some CPUs need to minimize
+ system overhead on those CPUs, including avoiding task load
+ balancing if that is not needed.
+
+When the per-cpuset flag "sched_load_balance" is enabled (the default
+setting), it requests that all the CPUs in that cpusets allowed 'cpus'
+be contained in a single sched domain, ensuring that load balancing
+can move a task (not otherwised pinned, as by sched_setaffinity)
+from any CPU in that cpuset to any other.
+
+When the per-cpuset flag "sched_load_balance" is disabled, then the
+scheduler will avoid load balancing across the CPUs in that cpuset,
+--except-- in so far as is necessary because some overlapping cpuset
+has "sched_load_balance" enabled.
+
+So, for example, if the top cpuset has the flag "sched_load_balance"
+enabled, then the scheduler will have one sched domain covering all
+CPUs, and the setting of the "sched_load_balance" flag in any other
+cpusets won't matter, as we're already fully load balancing.
+
+Therefore in the above two situations, the top cpuset flag
+"sched_load_balance" should be disabled, and only some of the smaller,
+child cpusets have this flag enabled.
+
+When doing this, you don't usually want to leave any unpinned tasks in
+the top cpuset that might use non-trivial amounts of CPU, as such tasks
+may be artificially constrained to some subset of CPUs, depending on
+the particulars of this flag setting in descendent cpusets. Even if
+such a task could use spare CPU cycles in some other CPUs, the kernel
+scheduler might not consider the possibility of load balancing that
+task to that underused CPU.
+
+Of course, tasks pinned to a particular CPU can be left in a cpuset
+that disables "sched_load_balance" as those tasks aren't going anywhere
+else anyway.
+
+There is an impedance mismatch here, between cpusets and sched domains.
+Cpusets are hierarchical and nest. Sched domains are flat; they don't
+overlap and each CPU is in at most one sched domain.
+
+It is necessary for sched domains to be flat because load balancing
+across partially overlapping sets of CPUs would risk unstable dynamics
+that would be beyond our understanding. So if each of two partially
+overlapping cpusets enables the flag 'sched_load_balance', then we
+form a single sched domain that is a superset of both. We won't move
+a task to a CPU outside it cpuset, but the scheduler load balancing
+code might waste some compute cycles considering that possibility.
+
+This mismatch is why there is not a simple one-to-one relation
+between which cpusets have the flag "sched_load_balance" enabled,
+and the sched domain configuration. If a cpuset enables the flag, it
+will get balancing across all its CPUs, but if it disables the flag,
+it will only be assured of no load balancing if no other overlapping
+cpuset enables the flag.
+
+If two cpusets have partially overlapping 'cpus' allowed, and only
+one of them has this flag enabled, then the other may find its
+tasks only partially load balanced, just on the overlapping CPUs.
+This is just the general case of the top_cpuset example given a few
+paragraphs above. In the general case, as in the top cpuset case,
+don't leave tasks that might use non-trivial amounts of CPU in
+such partially load balanced cpusets, as they may be artificially
+constrained to some subset of the CPUs allowed to them, for lack of
+load balancing to the other CPUs.
+
+1.7.1 sched_load_balance implementation details.
+------------------------------------------------
+
+The per-cpuset flag 'sched_load_balance' defaults to enabled (contrary
+to most cpuset flags.) When enabled for a cpuset, the kernel will
+ensure that it can load balance across all the CPUs in that cpuset
+(makes sure that all the CPUs in the cpus_allowed of that cpuset are
+in the same sched domain.)
+
+If two overlapping cpusets both have 'sched_load_balance' enabled,
+then they will be (must be) both in the same sched domain.
+
+If, as is the default, the top cpuset has 'sched_load_balance' enabled,
+then by the above that means there is a single sched domain covering
+the whole system, regardless of any other cpuset settings.
+
+The kernel commits to user space that it will avoid load balancing
+where it can. It will pick as fine a granularity partition of sched
+domains as it can while still providing load balancing for any set
+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.
+
+This partition exactly defines what sched domains the scheduler should
+setup - one sched domain for each element (cpumask_t) in the partition.
+
+The scheduler remembers the currently active sched domain partitions.
+When the scheduler routine partition_sched_domains() is invoked from
+the cpuset code to update these sched domains, it compares the new
+partition requested with the current, and updates its sched domains,
+removing the old and adding the new, for each change.
1.8 How do I use cpusets ?
--------------------------
@@ -485,7 +587,7 @@ than stress the kernel.
To start a new job that is to be contained within a cpuset, the steps are:
1) mkdir /dev/cpuset
- 2) mount -t cpuset none /dev/cpuset
+ 2) mount -t cgroup -ocpuset cpuset /dev/cpuset
3) Create the new cpuset by doing mkdir's and write's (or echo's) in
the /dev/cpuset virtual file system.
4) Start a task that will be the "founding father" of the new job.
@@ -497,7 +599,7 @@ For example, the following sequence of commands will setup a cpuset
named "Charlie", containing just CPUs 2 and 3, and Memory Node 1,
and then start a subshell 'sh' in that cpuset:
- mount -t cpuset none /dev/cpuset
+ mount -t cgroup -ocpuset cpuset /dev/cpuset
cd /dev/cpuset
mkdir Charlie
cd Charlie
@@ -529,7 +631,7 @@ Creating, modifying, using the cpusets can be done through the cpuset
virtual filesystem.
To mount it, type:
-# mount -t cpuset none /dev/cpuset
+# mount -t cgroup -o cpuset cpuset /dev/cpuset
Then under /dev/cpuset you can find a tree that corresponds to the
tree of the cpusets in the system. For instance, /dev/cpuset
@@ -572,6 +674,18 @@ To remove a cpuset, just use rmdir:
This will fail if the cpuset is in use (has cpusets inside, or has
processes attached).
+Note that for legacy reasons, the "cpuset" filesystem exists as a
+wrapper around the cgroup filesystem.
+
+The command
+
+mount -t cpuset X /dev/cpuset
+
+is equivalent to
+
+mount -t cgroup -ocpuset X /dev/cpuset
+echo "/sbin/cpuset_release_agent" > /dev/cpuset/release_agent
+
2.2 Adding/removing cpus
------------------------
diff --git a/Documentation/device-mapper/dm-uevent.txt b/Documentation/device-mapper/dm-uevent.txt
new file mode 100644
index 000000000000..07edbd85c714
--- /dev/null
+++ b/Documentation/device-mapper/dm-uevent.txt
@@ -0,0 +1,97 @@
+The device-mapper uevent code adds the capability to device-mapper to create
+and send kobject uevents (uevents). Previously device-mapper events were only
+available through the ioctl interface. The advantage of the uevents interface
+is the event contains environment attributes providing increased context for
+the event avoiding the need to query the state of the device-mapper device after
+the event is received.
+
+There are two functions currently for device-mapper events. The first function
+listed creates the event and the second function sends the event(s).
+
+void dm_path_uevent(enum dm_uevent_type event_type, struct dm_target *ti,
+ const char *path, unsigned nr_valid_paths)
+
+void dm_send_uevents(struct list_head *events, struct kobject *kobj)
+
+
+The variables added to the uevent environment are:
+
+Variable Name: DM_TARGET
+Uevent Action(s): KOBJ_CHANGE
+Type: string
+Description:
+Value: Name of device-mapper target that generated the event.
+
+Variable Name: DM_ACTION
+Uevent Action(s): KOBJ_CHANGE
+Type: string
+Description:
+Value: Device-mapper specific action that caused the uevent action.
+ PATH_FAILED - A path has failed.
+ PATH_REINSTATED - A path has been reinstated.
+
+Variable Name: DM_SEQNUM
+Uevent Action(s): KOBJ_CHANGE
+Type: unsigned integer
+Description: A sequence number for this specific device-mapper device.
+Value: Valid unsigned integer range.
+
+Variable Name: DM_PATH
+Uevent Action(s): KOBJ_CHANGE
+Type: string
+Description: Major and minor number of the path device pertaining to this
+event.
+Value: Path name in the form of "Major:Minor"
+
+Variable Name: DM_NR_VALID_PATHS
+Uevent Action(s): KOBJ_CHANGE
+Type: unsigned integer
+Description:
+Value: Valid unsigned integer range.
+
+Variable Name: DM_NAME
+Uevent Action(s): KOBJ_CHANGE
+Type: string
+Description: Name of the device-mapper device.
+Value: Name
+
+Variable Name: DM_UUID
+Uevent Action(s): KOBJ_CHANGE
+Type: string
+Description: UUID of the device-mapper device.
+Value: UUID. (Empty string if there isn't one.)
+
+An example of the uevents generated as captured by udevmonitor is shown
+below.
+
+1.) Path failure.
+UEVENT[1192521009.711215] change@/block/dm-3
+ACTION=change
+DEVPATH=/block/dm-3
+SUBSYSTEM=block
+DM_TARGET=multipath
+DM_ACTION=PATH_FAILED
+DM_SEQNUM=1
+DM_PATH=8:32
+DM_NR_VALID_PATHS=0
+DM_NAME=mpath2
+DM_UUID=mpath-35333333000002328
+MINOR=3
+MAJOR=253
+SEQNUM=1130
+
+2.) Path reinstate.
+UEVENT[1192521132.989927] change@/block/dm-3
+ACTION=change
+DEVPATH=/block/dm-3
+SUBSYSTEM=block
+DM_TARGET=multipath
+DM_ACTION=PATH_REINSTATED
+DM_SEQNUM=2
+DM_PATH=8:32
+DM_NR_VALID_PATHS=1
+DM_NAME=mpath2
+DM_UUID=mpath-35333333000002328
+MINOR=3
+MAJOR=253
+SEQNUM=1131
diff --git a/Documentation/devices.txt b/Documentation/devices.txt
index 6c46730c631a..e6244cde26e9 100644
--- a/Documentation/devices.txt
+++ b/Documentation/devices.txt
@@ -2188,7 +2188,7 @@ Your cooperation is appreciated.
136-143 char Unix98 PTY slaves
0 = /dev/pts/0 First Unix98 pseudo-TTY
- 1 = /dev/pts/1 Second Unix98 pesudo-TTY
+ 1 = /dev/pts/1 Second Unix98 pseudo-TTY
...
These device nodes are automatically generated with
diff --git a/Documentation/dontdiff b/Documentation/dontdiff
index 7b9551fc6fe3..f2d658a6a942 100644
--- a/Documentation/dontdiff
+++ b/Documentation/dontdiff
@@ -42,6 +42,9 @@
*.9.gz
.*
.cscope
+.gitignore
+.mailmap
+.mm
53c700_d.h
53c7xx_d.h
53c7xx_u.h
@@ -121,7 +124,6 @@ kxgettext
lkc_defs.h
lex.c*
lex.*.c
-lk201-map.c
logo_*.c
logo_*_clut224.c
logo_*_mono.c
@@ -176,11 +178,13 @@ times.h*
tkparse
trix_boot.h
utsrelease.h*
+vdso.lds
version.h*
vmlinux
vmlinux-*
vmlinux.aout
-vmlinux.lds
+vmlinux*.lds*
+vmlinux*.scr
vsyscall.lds
wanxlfw.inc
uImage
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
index 8569072fa387..387b8a720f4a 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -32,7 +32,7 @@ braindamaged document, if it's finally working, well, it's working.
For one reason or another, low level drivers don't receive as much
attention or testing as core code, and bugs on driver detach or
-initilaization failure doesn't happen often enough to be noticeable.
+initialization failure don't happen often enough to be noticeable.
Init failure path is worse because it's much less travelled while
needs to handle multiple entry points.
@@ -160,7 +160,7 @@ resources on failure. For example,
devres_release_group(dev, NULL);
return err_code;
-As resource acquision failure usually means probe failure, constructs
+As resource acquisition failure usually means probe failure, constructs
like above are usually useful in midlayer driver (e.g. libata core
layer) where interface function shouldn't have side effect on failure.
For LLDs, just returning error code suffices in most cases.
diff --git a/Documentation/early-userspace/README b/Documentation/early-userspace/README
index cddbac456c29..766d320c8eb6 100644
--- a/Documentation/early-userspace/README
+++ b/Documentation/early-userspace/README
@@ -19,7 +19,7 @@ It consists of several major infrastructure components:
- klibc, a userspace C library, currently packaged separately, that is
optimized for correctness and small size.
-The cpio file format used by initramfs is the "newc" (aka "cpio -c")
+The cpio file format used by initramfs is the "newc" (aka "cpio -H newc")
format, and is documented in the file "buffer-format.txt". There are
two ways to add an early userspace image: specify an existing cpio
archive to be used as the image or have the kernel build process build
@@ -44,7 +44,7 @@ The image is specified as one or more sources in
CONFIG_INITRAMFS_SOURCE. Sources can be either directories or files -
cpio archives are *not* allowed when building from sources.
-A source directory will have it and all of it's contents packaged. The
+A source directory will have it and all of its contents packaged. The
specified directory name will be mapped to '/'. When packaging a
directory, limited user and group ID translation can be performed.
INITRAMFS_ROOT_UID can be set to a user ID that needs to be mapped to
@@ -144,7 +144,7 @@ c) using initramfs. The call to prepare_namespace() must be skipped.
initrd format, an cpio archive. It must be called "/init". This binary
is responsible to do all the things prepare_namespace() would do.
- To remain backwards compatibility, the /init binary will only run if it
+ To maintain backwards compatibility, the /init binary will only run if it
comes via an initramfs cpio archive. If this is not the case,
init/main.c:init() will run prepare_namespace() to mount the final root
and exec one of the predefined init binaries.
diff --git a/Documentation/email-clients.txt b/Documentation/email-clients.txt
new file mode 100644
index 000000000000..113165b48305
--- /dev/null
+++ b/Documentation/email-clients.txt
@@ -0,0 +1,217 @@
+Email clients info for Linux
+======================================================================
+
+General Preferences
+----------------------------------------------------------------------
+Patches for the Linux kernel are submitted via email, preferably as
+inline text in the body of the email. Some maintainers accept
+attachments, but then the attachments should have content-type
+"text/plain". However, attachments are generally frowned upon because
+it makes quoting portions of the patch more difficult in the patch
+review process.
+
+Email clients that are used for Linux kernel patches should send the
+patch text untouched. For example, they should not modify or delete tabs
+or spaces, even at the beginning or end of lines.
+
+Don't send patches with "format=flowed". This can cause unexpected
+and unwanted line breaks.
+
+Don't let your email client do automatic word wrapping for you.
+This can also corrupt your patch.
+
+Email clients should not modify the character set encoding of the text.
+Emailed patches should be in ASCII or UTF-8 encoding only.
+If you configure your email client to send emails with UTF-8 encoding,
+you avoid some possible charset problems.
+
+Email clients should generate and maintain References: or In-Reply-To:
+headers so that mail threading is not broken.
+
+Copy-and-paste (or cut-and-paste) usually does not work for patches
+because tabs are converted to spaces. Using xclipboard, xclip, and/or
+xcutsel may work, but it's best to test this for yourself or just avoid
+copy-and-paste.
+
+Don't use PGP/GPG signatures in mail that contains patches.
+This breaks many scripts that read and apply the patches.
+(This should be fixable.)
+
+It's a good idea to send a patch to yourself, save the received message,
+and successfully apply it with 'patch' before sending patches to Linux
+mailing lists.
+
+
+Some email client (MUA) hints
+----------------------------------------------------------------------
+Here are some specific MUA configuration hints for editing and sending
+patches for the Linux kernel. These are not meant to be complete
+software package configuration summaries.
+
+Legend:
+TUI = text-based user interface
+GUI = graphical user interface
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Alpine (TUI)
+
+Config options:
+In the "Sending Preferences" section:
+
+- "Do Not Send Flowed Text" must be enabled
+- "Strip Whitespace Before Sending" must be disabled
+
+When composing the message, the cursor should be placed where the patch
+should appear, and then pressing CTRL-R let you specify the patch file
+to insert into the message.
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Evolution (GUI)
+
+Some people use this successfully for patches.
+
+When composing mail select: Preformat
+ from Format->Heading->Preformatted (Ctrl-7)
+ or the toolbar
+
+Then use:
+ Insert->Text File... (Alt-n x)
+to insert the patch.
+
+You can also "diff -Nru old.c new.c | xclip", select Preformat, then
+paste with the middle button.
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Kmail (GUI)
+
+Some people use Kmail successfully for patches.
+
+The default setting of not composing in HTML is appropriate; do not
+enable it.
+
+When composing an email, under options, uncheck "word wrap". The only
+disadvantage is any text you type in the email will not be word-wrapped
+so you will have to manually word wrap text before the patch. The easiest
+way around this is to compose your email with word wrap enabled, then save
+it as a draft. Once you pull it up again from your drafts it is now hard
+word-wrapped and you can uncheck "word wrap" without losing the existing
+wrapping.
+
+At the bottom of your email, put the commonly-used patch delimiter before
+inserting your patch: three hyphens (---).
+
+Then from the "Message" menu item, select insert file and choose your patch.
+As an added bonus you can customise the message creation toolbar menu
+and put the "insert file" icon there.
+
+You can safely GPG sign attachments, but inlined text is preferred for
+patches so do not GPG sign them. Signing patches that have been inserted
+as inlined text will make them tricky to extract from their 7-bit encoding.
+
+If you absolutely must send patches as attachments instead of inlining
+them as text, right click on the attachment and select properties, and
+highlight "Suggest automatic display" to make the attachment inlined to
+make it more viewable.
+
+When saving patches that are sent as inlined text, select the email that
+contains the patch from the message list pane, right click and select
+"save as". You can use the whole email unmodified as a patch if it was
+properly composed. There is no option currently to save the email when you
+are actually viewing it in its own window -- there has been a request filed
+at kmail's bugzilla and hopefully this will be addressed. Emails are saved
+as read-write for user only so you will have to chmod them to make them
+group and world readable if you copy them elsewhere.
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Lotus Notes (GUI)
+
+Run away from it.
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Mutt (TUI)
+
+Plenty of Linux developers use mutt, so it must work pretty well.
+
+Mutt doesn't come with an editor, so whatever editor you use should be
+used in a way that there are no automatic linebreaks. Most editors have
+an "insert file" option that inserts the contents of a file unaltered.
+
+To use 'vim' with mutt:
+ set editor="vi"
+
+ If using xclip, type the command
+ :set paste
+ before middle button or shift-insert or use
+ :r filename
+
+if you want to include the patch inline.
+(a)ttach works fine without "set paste".
+
+Config options:
+It should work with default settings.
+However, it's a good idea to set the "send_charset" to:
+ set send_charset="us-ascii:utf-8"
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Pine (TUI)
+
+Pine has had some whitespace truncation issues in the past, but these
+should all be fixed now.
+
+Use alpine (pine's successor) if you can.
+
+Config options:
+- quell-flowed-text is needed for recent versions
+- the "no-strip-whitespace-before-send" option is needed
+
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Sylpheed (GUI)
+
+- Works well for inlining text (or using attachments).
+- Allows use of an external editor.
+- Not good for IMAP.
+- Is slow on large folders.
+- Won't do TLS SMTP auth over a non-SSL connection.
+- Has a helpful ruler bar in the compose window.
+- Adding addresses to address book doesn't understand the display name
+ properly.
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Thunderbird (GUI)
+
+By default, thunderbird likes to mangle text, but there are ways to
+coerce it into being nice.
+
+- Under account settings, composition and addressing, uncheck "Compose
+ messages in HTML format".
+
+- Edit your Thunderbird config settings to tell it not to wrap lines:
+ user_pref("mailnews.wraplength", 0);
+
+- Edit your Thunderbird config settings so that it won't use format=flowed:
+ user_pref("mailnews.send_plaintext_flowed", false);
+
+- You need to get Thunderbird into preformat mode:
+. If you compose HTML messages by default, it's not too hard. Just select
+ "Preformat" from the drop-down box just under the subject line.
+. If you compose in text by default, you have to tell it to compose a new
+ message in HTML (just as a one-off), and then force it from there back to
+ text, else it will wrap lines. To do this, use shift-click on the Write
+ icon to compose to get HTML compose mode, then select "Preformat" from
+ the drop-down box just under the subject line.
+
+- Allows use of an external editor:
+ The easiest thing to do with Thunderbird and patches is to use an
+ "external editor" extension and then just use your favorite $EDITOR
+ for reading/merging patches into the body text. To do this, download
+ and install the extension, then add a button for it using
+ View->Toolbars->Customize... and finally just click on it when in the
+ Compose dialog.
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+TkRat (GUI)
+
+Works. Use "Insert file..." or external editor.
+
+ ###
diff --git a/Documentation/fb/00-INDEX b/Documentation/fb/00-INDEX
index 92e89aeef52e..caabbd395e61 100644
--- a/Documentation/fb/00-INDEX
+++ b/Documentation/fb/00-INDEX
@@ -5,21 +5,49 @@ please mail me.
00-INDEX
- this file
+arkfb.txt
+ - info on the fbdev driver for ARK Logic chips.
+aty128fb.txt
+ - info on the ATI Rage128 frame buffer driver.
+cirrusfb.txt
+ - info on the driver for Cirrus Logic chipsets.
+cyblafb/
+ - directory with documentation files related to the cyblafb driver.
+deferred_io.txt
+ - an introduction to deferred IO.
+fbcon.txt
+ - intro to and usage guide for the framebuffer console (fbcon).
framebuffer.txt
- - introduction to frame buffer devices
+ - introduction to frame buffer devices.
+imacfb.txt
+ - info on the generic EFI platform driver for Intel based Macs.
+intel810.txt
+ - documentation for the Intel 810/815 framebuffer driver.
+intelfb.txt
+ - docs for Intel 830M/845G/852GM/855GM/865G/915G/945G fb driver.
internals.txt
- - quick overview of frame buffer device internals
+ - quick overview of frame buffer device internals.
+matroxfb.txt
+ - info on the Matrox framebuffer driver for Alpha, Intel and PPC.
modedb.txt
- - info on the video mode database
-aty128fb.txt
- - info on the ATI Rage128 frame buffer driver
-clgenfb.txt
- - info on the Cirrus Logic frame buffer driver
+ - info on the video mode database.
matroxfb.txt
- - info on the Matrox frame buffer driver
+ - info on the Matrox frame buffer driver.
pvr2fb.txt
- - info on the PowerVR 2 frame buffer driver
+ - info on the PowerVR 2 frame buffer driver.
+pxafb.txt
+ - info on the driver for the PXA25x LCD controller.
+s3fb.txt
+ - info on the fbdev driver for S3 Trio/Virge chips.
+sa1100fb.txt
+ - information about the driver for the SA-1100 LCD controller.
+sisfb.txt
+ - info on the framebuffer device driver for various SiS chips.
+sstfb.txt
+ - info on the frame buffer driver for 3dfx' Voodoo Graphics boards.
tgafb.txt
- info on the TGA (DECChip 21030) frame buffer driver
vesafb.txt
- info on the VESA frame buffer device
+vt8623fb.txt
+ - info on the fb driver for the graphics core in VIA VT8623 chipsets.
diff --git a/Documentation/fb/deferred_io.txt b/Documentation/fb/deferred_io.txt
index 73cf9fb7cf60..63883a892120 100644
--- a/Documentation/fb/deferred_io.txt
+++ b/Documentation/fb/deferred_io.txt
@@ -3,7 +3,7 @@ Deferred IO
Deferred IO is a way to delay and repurpose IO. It uses host memory as a
buffer and the MMU pagefault as a pretrigger for when to perform the device
-IO. The following example may be a useful explaination of how one such setup
+IO. The following example may be a useful explanation of how one such setup
works:
- userspace app like Xfbdev mmaps framebuffer
@@ -28,7 +28,7 @@ a relatively more expensive operation.
For some types of nonvolatile high latency displays, the desired image is
the final image rather than the intermediate stages which is why it's okay
-to not update for each write that is occuring.
+to not update for each write that is occurring.
It may be the case that this is useful in other scenarios as well. Paul Mundt
has mentioned a case where it is beneficial to use the page count to decide
diff --git a/Documentation/fb/uvesafb.txt b/Documentation/fb/uvesafb.txt
new file mode 100644
index 000000000000..bcfc233a0080
--- /dev/null
+++ b/Documentation/fb/uvesafb.txt
@@ -0,0 +1,188 @@
+
+uvesafb - A Generic Driver for VBE2+ compliant video cards
+==========================================================
+
+1. Requirements
+---------------
+
+uvesafb should work with any video card that has a Video BIOS compliant
+with the VBE 2.0 standard.
+
+Unlike other drivers, uvesafb makes use of a userspace helper called
+v86d. v86d is used to run the x86 Video BIOS code in a simulated and
+controlled environment. This allows uvesafb to function on arches other
+than x86. Check the v86d documentation for a list of currently supported
+arches.
+
+v86d source code can be downloaded from the following website:
+ http://dev.gentoo.org/~spock/projects/uvesafb
+
+Please refer to the v86d documentation for detailed configuration and
+installation instructions.
+
+Note that the v86d userspace helper has to be available at all times in
+order for uvesafb to work properly. If you want to use uvesafb during
+early boot, you will have to include v86d into an initramfs image, and
+either compile it into the kernel or use it as an initrd.
+
+2. Caveats and limitations
+--------------------------
+
+uvesafb is a _generic_ driver which supports a wide variety of video
+cards, but which is ultimately limited by the Video BIOS interface.
+The most important limitations are:
+
+- Lack of any type of acceleration.
+- A strict and limited set of supported video modes. Often the native
+ or most optimal resolution/refresh rate for your setup will not work
+ with uvesafb, simply because the Video BIOS doesn't support the
+ video mode you want to use. This can be especially painful with
+ widescreen panels, where native video modes don't have the 4:3 aspect
+ ratio, which is what most BIOS-es are limited to.
+- Adjusting the refresh rate is only possible with a VBE 3.0 compliant
+ Video BIOS. Note that many nVidia Video BIOS-es claim to be VBE 3.0
+ compliant, while they simply ignore any refresh rate settings.
+
+3. Configuration
+----------------
+
+uvesafb can be compiled either as a module, or directly into the kernel.
+In both cases it supports the same set of configuration options, which
+are either given on the kernel command line or as module parameters, e.g.:
+
+ video=uvesafb:1024x768-32,mtrr:3,ywrap (compiled into the kernel)
+
+ # modprobe uvesafb mode=1024x768-32 mtrr=3 scroll=ywrap (module)
+
+Accepted options:
+
+ypan Enable display panning using the VESA protected mode
+ interface. The visible screen is just a window of the
+ video memory, console scrolling is done by changing the
+ start of the window. Available on x86 only.
+
+ywrap Same as ypan, but assumes your gfx board can wrap-around
+ the video memory (i.e. starts reading from top if it
+ reaches the end of video memory). Faster than ypan.
+ Available on x86 only.
+
+redraw Scroll by redrawing the affected part of the screen, this
+ is the safe (and slow) default.
+
+(If you're using uvesafb as a module, the above three options are
+ used a parameter of the scroll option, e.g. scroll=ypan.)
+
+vgapal Use the standard VGA registers for palette changes.
+
+pmipal Use the protected mode interface for palette changes.
+ This is the default if the protected mode interface is
+ available. Available on x86 only.
+
+mtrr:n Setup memory type range registers for the framebuffer
+ where n:
+ 0 - disabled (equivalent to nomtrr) (default)
+ 1 - uncachable
+ 2 - write-back
+ 3 - write-combining
+ 4 - write-through
+
+ If you see the following in dmesg, choose the type that matches
+ the old one. In this example, use "mtrr:2".
+...
+mtrr: type mismatch for e0000000,8000000 old: write-back new: write-combining
+...
+
+nomtrr Do not use memory type range registers.
+
+vremap:n
+ Remap 'n' MiB of video RAM. If 0 or not specified, remap memory
+ according to video mode.
+
+vtotal:n
+ If the video BIOS of your card incorrectly determines the total
+ amount of video RAM, use this option to override the BIOS (in MiB).
+
+<mode> The mode you want to set, in the standard modedb format. Refer to
+ modedb.txt for a detailed description. When uvesafb is compiled as
+ a module, the mode string should be provided as a value of the
+ 'mode' option.
+
+vbemode:x
+ Force the use of VBE mode x. The mode will only be set if it's
+ found in the VBE-provided list of supported modes.
+ NOTE: The mode number 'x' should be specified in VESA mode number
+ notation, not the Linux kernel one (eg. 257 instead of 769).
+ HINT: If you use this option because normal <mode> parameter does
+ not work for you and you use a X server, you'll probably want to
+ set the 'nocrtc' option to ensure that the video mode is properly
+ restored after console <-> X switches.
+
+nocrtc Do not use CRTC timings while setting the video mode. This option
+ has any effect only if the Video BIOS is VBE 3.0 compliant. Use it
+ if you have problems with modes set the standard way. Note that
+ using this option implies that any refresh rate adjustments will
+ be ignored and the refresh rate will stay at your BIOS default (60 Hz).
+
+noedid Do not try to fetch and use EDID-provided modes.
+
+noblank Disable hardware blanking.
+
+v86d:path
+ Set path to the v86d executable. This option is only available as
+ a module parameter, and not as a part of the video= string. If you
+ need to use it and have uvesafb built into the kernel, use
+ uvesafb.v86d="path".
+
+Additionally, the following parameters may be provided. They all override the
+EDID-provided values and BIOS defaults. Refer to your monitor's specs to get
+the correct values for maxhf, maxvf and maxclk for your hardware.
+
+maxhf:n Maximum horizontal frequency (in kHz).
+maxvf:n Maximum vertical frequency (in Hz).
+maxclk:n Maximum pixel clock (in MHz).
+
+4. The sysfs interface
+----------------------
+
+uvesafb provides several sysfs nodes for configurable parameters and
+additional information.
+
+Driver attributes:
+
+/sys/bus/platform/drivers/uvesafb
+ - v86d (default: /sbin/v86d)
+ Path to the v86d executable. v86d is started by uvesafb
+ if an instance of the daemon isn't already running.
+
+Device attributes:
+
+/sys/bus/platform/drivers/uvesafb/uvesafb.0
+ - nocrtc
+ Use the default refresh rate (60 Hz) if set to 1.
+
+ - oem_product_name
+ - oem_product_rev
+ - oem_string
+ - oem_vendor
+ Information about the card and its maker.
+
+ - vbe_modes
+ A list of video modes supported by the Video BIOS along with their
+ VBE mode numbers in hex.
+
+ - vbe_version
+ A BCD value indicating the implemented VBE standard.
+
+5. Miscellaneous
+----------------
+
+Uvesafb will set a video mode with the default refresh rate and timings
+from the Video BIOS if you set pixclock to 0 in fb_var_screeninfo.
+
+
+--
+ Michal Januszewski <spock@gentoo.org>
+ Last updated: 2007-06-16
+
+ Documentation of the uvesafb options is loosely based on vesafb.txt.
+
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 63df2262d41a..20c4c8bac9d7 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -14,18 +14,6 @@ Who: Jiri Slaby <jirislaby@gmail.com>
---------------------------
-What: V4L2 VIDIOC_G_MPEGCOMP and VIDIOC_S_MPEGCOMP
-When: October 2007
-Why: Broken attempt to set MPEG compression parameters. These ioctls are
- not able to implement the wide variety of parameters that can be set
- by hardware MPEG encoders. A new MPEG control mechanism was created
- in kernel 2.6.18 that replaces these ioctls. See the V4L2 specification
- (section 1.9: Extended controls) for more information on this topic.
-Who: Hans Verkuil <hverkuil@xs4all.nl> and
- Mauro Carvalho Chehab <mchehab@infradead.org>
-
----------------------------
-
What: dev->power.power_state
When: July 2007
Why: Broken design for runtime control over driver power states, confusing
@@ -49,10 +37,10 @@ Who: David Miller <davem@davemloft.net>
---------------------------
What: Video4Linux API 1 ioctls and video_decoder.h from Video devices.
-When: December 2006
-Files: include/linux/video_decoder.h
-Check: include/linux/video_decoder.h
-Why: V4L1 AP1 was replaced by V4L2 API. during migration from 2.4 to 2.6
+When: December 2008
+Files: include/linux/video_decoder.h include/linux/videodev.h
+Check: include/linux/video_decoder.h include/linux/videodev.h
+Why: V4L1 AP1 was replaced by V4L2 API during migration from 2.4 to 2.6
series. The old API have lots of drawbacks and don't provide enough
means to work with all video and audio standards. The newer API is
already available on the main drivers and should be used instead.
@@ -61,7 +49,9 @@ Why: V4L1 AP1 was replaced by V4L2 API. during migration from 2.4 to 2.6
Decoder iocts are using internally to allow video drivers to
communicate with video decoders. This should also be improved to allow
V4L2 calls being translated into compatible internal ioctls.
-Who: Mauro Carvalho Chehab <mchehab@brturbo.com.br>
+ Compatibility ioctls will be provided, for a while, via
+ v4l1-compat module.
+Who: Mauro Carvalho Chehab <mchehab@infradead.org>
---------------------------
@@ -82,6 +72,52 @@ Who: Dominik Brodowski <linux@brodo.de>
---------------------------
+What: sys_sysctl
+When: September 2010
+Option: CONFIG_SYSCTL_SYSCALL
+Why: The same information is available in a more convenient from
+ /proc/sys, and none of the sysctl variables appear to be
+ important performance wise.
+
+ Binary sysctls are a long standing source of subtle kernel
+ bugs and security issues.
+
+ When I looked several months ago all I could find after
+ searching several distributions were 5 user space programs and
+ glibc (which falls back to /proc/sys) using this syscall.
+
+ The man page for sysctl(2) documents it as unusable for user
+ space programs.
+
+ sysctl(2) is not generally ABI compatible to a 32bit user
+ space application on a 64bit and a 32bit kernel.
+
+ For the last several months the policy has been no new binary
+ sysctls and no one has put forward an argument to use them.
+
+ Binary sysctls issues seem to keep happening appearing so
+ properly deprecating them (with a warning to user space) and a
+ 2 year grace warning period will mean eventually we can kill
+ them and end the pain.
+
+ In the mean time individual binary sysctls can be dealt with
+ in a piecewise fashion.
+
+Who: Eric Biederman <ebiederm@xmission.com>
+
+---------------------------
+
+What: a.out interpreter support for ELF executables
+When: 2.6.25
+Files: fs/binfmt_elf.c
+Why: Using a.out interpreters for ELF executables was a feature for
+ transition from a.out to ELF. But now it is unlikely to be still
+ needed anymore and removing it would simplify the hairy ELF
+ loader code.
+Who: Andi Kleen <ak@suse.de>
+
+---------------------------
+
What: remove EXPORT_SYMBOL(kernel_thread)
When: August 2006
Files: arch/*/kernel/*_ksyms.c
@@ -145,15 +181,6 @@ Who: Nick Piggin <npiggin@suse.de>
---------------------------
-What: Interrupt only SA_* flags
-When: September 2007
-Why: The interrupt related SA_* flags are replaced by IRQF_* to move them
- out of the signal namespace.
-
-Who: Thomas Gleixner <tglx@linutronix.de>
-
----------------------------
-
What: PHYSDEVPATH, PHYSDEVBUS, PHYSDEVDRIVER in the uevent environment
When: October 2008
Why: The stacking of class devices makes these values misleading and
@@ -173,13 +200,6 @@ Who: Jean Delvare <khali@linux-fr.org>,
---------------------------
-What: drivers depending on OBSOLETE_OSS
-When: options in 2.6.22, code in 2.6.24
-Why: OSS drivers with ALSA replacements
-Who: Adrian Bunk <bunk@stusta.de>
-
----------------------------
-
What: ACPI procfs interface
When: July 2008
Why: ACPI sysfs conversion should be finished by January 2008.
@@ -205,20 +225,6 @@ Who: Len Brown <len.brown@intel.com>
---------------------------
-What: Compaq touchscreen device emulation
-When: Oct 2007
-Files: drivers/input/tsdev.c
-Why: The code says it was obsolete when it was written in 2001.
- tslib is a userspace library which does anything tsdev can do and
- much more besides in userspace where this code belongs. There is no
- longer any need for tsdev and applications should have converted to
- use tslib by now.
- The name "tsdev" is also extremely confusing and lots of people have
- it loaded when they don't need/use it.
-Who: Richard Purdie <rpurdie@rpsys.net>
-
----------------------------
-
What: i2c-ixp2000, i2c-ixp4xx and scx200_i2c drivers
When: September 2007
Why: Obsolete. The new i2c-gpio driver replaces all hardware-specific
diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX
index 59db1bca7027..1de155e2dc36 100644
--- a/Documentation/filesystems/00-INDEX
+++ b/Documentation/filesystems/00-INDEX
@@ -44,14 +44,24 @@ files.txt
- info on file management in the Linux kernel.
fuse.txt
- info on the Filesystem in User SpacE including mount options.
+gfs2.txt
+ - info on the Global File System 2.
hfs.txt
- info on the Macintosh HFS Filesystem for Linux.
+hfsplus.txt
+ - info on the Macintosh HFSPlus Filesystem for Linux.
hpfs.txt
- info and mount options for the OS/2 HPFS.
+inotify.txt
+ - info on the powerful yet simple file change notification system.
isofs.txt
- info and mount options for the ISO 9660 (CDROM) filesystem.
jfs.txt
- info and mount options for the JFS filesystem.
+locks.txt
+ - info on file locking implementations, flock() vs. fcntl(), etc.
+mandatory-locking.txt
+ - info on the Linux implementation of Sys V mandatory file locking.
ncpfs.txt
- info on Novell Netware(tm) filesystem using NCP protocol.
ntfs.txt
diff --git a/Documentation/filesystems/9p.txt b/Documentation/filesystems/9p.txt
index cda6905cbe49..bf8080640eba 100644
--- a/Documentation/filesystems/9p.txt
+++ b/Documentation/filesystems/9p.txt
@@ -35,17 +35,19 @@ For remote file server:
For Plan 9 From User Space applications (http://swtch.com/plan9)
- mount -t 9p `namespace`/acme /mnt/9 -o proto=unix,uname=$USER
+ mount -t 9p `namespace`/acme /mnt/9 -o trans=unix,uname=$USER
OPTIONS
=======
- proto=name select an alternative transport. Valid options are
+ trans=name select an alternative transport. Valid options are
currently:
- unix - specifying a named pipe mount point
- tcp - specifying a normal TCP/IP connection
- fd - used passed file descriptors for connection
+ unix - specifying a named pipe mount point
+ tcp - specifying a normal TCP/IP connection
+ fd - used passed file descriptors for connection
(see rfdno and wfdno)
+ virtio - connect to the next virtio channel available
+ (from lguest or KVM with trans_virtio module)
uname=name user name to attempt mount as on the remote server. The
server may override or ignore this value. Certain user
@@ -54,7 +56,7 @@ OPTIONS
aname=name aname specifies the file tree to access when the server is
offering several exported file systems.
- cache=mode specifies a cacheing policy. By default, no caches are used.
+ cache=mode specifies a caching policy. By default, no caches are used.
loose = no attempts are made at consistency,
intended for exclusive, read-only mounts
@@ -68,9 +70,9 @@ OPTIONS
0x40 = display transport debug
0x80 = display allocation debug
- rfdno=n the file descriptor for reading with proto=fd
+ rfdno=n the file descriptor for reading with trans=fd
- wfdno=n the file descriptor for writing with proto=fd
+ wfdno=n the file descriptor for writing with trans=fd
maxdata=n the number of bytes to use for 9p packet payload (msize)
@@ -78,9 +80,9 @@ OPTIONS
noextend force legacy mode (no 9p2000.u semantics)
- uid attempt to mount as a particular uid
+ dfltuid attempt to mount as a particular uid
- gid attempt to mount with a particular gid
+ dfltgid attempt to mount with a particular gid
afid security channel - used by Plan 9 authentication protocols
@@ -88,6 +90,16 @@ OPTIONS
This can be used to share devices/named pipes/sockets between
hosts. This functionality will be expanded in later versions.
+ access there are three access modes.
+ user = if a user tries to access a file on v9fs
+ filesystem for the first time, v9fs sends an
+ attach command (Tattach) for that user.
+ This is the default mode.
+ <uid> = allows only user with uid=<uid> to access
+ the files on the mounted filesystem
+ any = v9fs does single attach and performs all
+ operations as one user
+
RESOURCES
=========
diff --git a/Documentation/filesystems/Exporting b/Documentation/filesystems/Exporting
index 31047e0fe14b..87019d2b5981 100644
--- a/Documentation/filesystems/Exporting
+++ b/Documentation/filesystems/Exporting
@@ -2,9 +2,12 @@
Making Filesystems Exportable
=============================
-Most filesystem operations require a dentry (or two) as a starting
+Overview
+--------
+
+All filesystem operations require a dentry (or two) as a starting
point. Local applications have a reference-counted hold on suitable
-dentrys via open file descriptors or cwd/root. However remote
+dentries via open file descriptors or cwd/root. However remote
applications that access a filesystem via a remote filesystem protocol
such as NFS may not be able to hold such a reference, and so need a
different way to refer to a particular dentry. As the alternative
@@ -13,14 +16,14 @@ server-reboot (among other things, though these tend to be the most
problematic), there is no simple answer like 'filename'.
The mechanism discussed here allows each filesystem implementation to
-specify how to generate an opaque (out side of the filesystem) byte
+specify how to generate an opaque (outside of the filesystem) byte
string for any dentry, and how to find an appropriate dentry for any
given opaque byte string.
This byte string will be called a "filehandle fragment" as it
corresponds to part of an NFS filehandle.
A filesystem which supports the mapping between filehandle fragments
-and dentrys will be termed "exportable".
+and dentries will be termed "exportable".
@@ -89,11 +92,9 @@ For a filesystem to be exportable it must:
1/ provide the filehandle fragment routines described below.
2/ make sure that d_splice_alias is used rather than d_add
when ->lookup finds an inode for a given parent and name.
- Typically the ->lookup routine will end:
- if (inode)
- return d_splice(inode, dentry);
- d_add(dentry, inode);
- return NULL;
+ Typically the ->lookup routine will end with a:
+
+ return d_splice_alias(inode, dentry);
}
@@ -101,67 +102,39 @@ For a filesystem to be exportable it must:
A file system implementation declares that instances of the filesystem
are exportable by setting the s_export_op field in the struct
super_block. This field must point to a "struct export_operations"
-struct which could potentially be full of NULLs, though normally at
-least get_parent will be set.
-
- The primary operations are decode_fh and encode_fh.
-decode_fh takes a filehandle fragment and tries to find or create a
-dentry for the object referred to by the filehandle.
-encode_fh takes a dentry and creates a filehandle fragment which can
-later be used to find/create a dentry for the same object.
-
-decode_fh will probably make use of "find_exported_dentry".
-This function lives in the "exportfs" module which a filesystem does
-not need unless it is being exported. So rather that calling
-find_exported_dentry directly, each filesystem should call it through
-the find_exported_dentry pointer in it's export_operations table.
-This field is set correctly by the exporting agent (e.g. nfsd) when a
-filesystem is exported, and before any export operations are called.
-
-find_exported_dentry needs three support functions from the
-filesystem:
- get_name. When given a parent dentry and a child dentry, this
- should find a name in the directory identified by the parent
- dentry, which leads to the object identified by the child dentry.
- If no get_name function is supplied, a default implementation is
- provided which uses vfs_readdir to find potential names, and
- matches inode numbers to find the correct match.
-
- get_parent. When given a dentry for a directory, this should return
- a dentry for the parent. Quite possibly the parent dentry will
- have been allocated by d_alloc_anon.
- The default get_parent function just returns an error so any
- filehandle lookup that requires finding a parent will fail.
- ->lookup("..") is *not* used as a default as it can leave ".."
- entries in the dcache which are too messy to work with.
-
- get_dentry. When given an opaque datum, this should find the
- implied object and create a dentry for it (possibly with
- d_alloc_anon).
- The opaque datum is whatever is passed down by the decode_fh
- function, and is often simply a fragment of the filehandle
- fragment.
- decode_fh passes two datums through find_exported_dentry. One that
- should be used to identify the target object, and one that can be
- used to identify the object's parent, should that be necessary.
- The default get_dentry function assumes that the datum contains an
- inode number and a generation number, and it attempts to get the
- inode using "iget" and check it's validity by matching the
- generation number. A filesystem should only depend on the default
- if iget can safely be used this way.
-
-If decode_fh and/or encode_fh are left as NULL, then default
-implementations are used. These defaults are suitable for ext2 and
-extremely similar filesystems (like ext3).
-
-The default encode_fh creates a filehandle fragment from the inode
-number and generation number of the target together with the inode
-number and generation number of the parent (if the parent is
-required).
-
-The default decode_fh extract the target and parent datums from the
-filehandle assuming the format used by the default encode_fh and
-passed them to find_exported_dentry.
+struct which has the following members:
+
+ encode_fh (optional)
+ Takes a dentry and creates a filehandle fragment which can later be used
+ to find or create a dentry for the same object. The default
+ implementation creates a filehandle fragment that encodes a 32bit inode
+ and generation number for the inode encoded, and if necessary the
+ same information for the parent.
+
+ fh_to_dentry (mandatory)
+ Given a filehandle fragment, this should find the implied object and
+ create a dentry for it (possibly with d_alloc_anon).
+
+ fh_to_parent (optional but strongly recommended)
+ Given a filehandle fragment, this should find the parent of the
+ implied object and create a dentry for it (possibly with d_alloc_anon).
+ May fail if the filehandle fragment is too small.
+
+ get_parent (optional but strongly recommended)
+ When given a dentry for a directory, this should return a dentry for
+ the parent. Quite possibly the parent dentry will have been allocated
+ by d_alloc_anon. The default get_parent function just returns an error
+ so any filehandle lookup that requires finding a parent will fail.
+ ->lookup("..") is *not* used as a default as it can leave ".." entries
+ in the dcache which are too messy to work with.
+
+ get_name (optional)
+ When given a parent dentry and a child dentry, this should find a name
+ in the directory identified by the parent dentry, which leads to the
+ object identified by the child dentry. If no get_name function is
+ supplied, a default implementation is provided which uses vfs_readdir
+ to find potential names, and matches inode numbers to find the correct
+ match.
A filehandle fragment consists of an array of 1 or more 4byte words,
@@ -172,5 +145,3 @@ generated by encode_fh, in which case it will have been padded with
nuls. Rather, the encode_fh routine should choose a "type" which
indicates the decode_fh how much of the filehandle is valid, and how
it should be interpreted.
-
-
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index f0f825808ca4..37c10cba7177 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -178,15 +178,18 @@ prototypes:
locking rules:
All except set_page_dirty may block
- BKL PageLocked(page)
+ BKL PageLocked(page) i_sem
writepage: no yes, unlocks (see below)
readpage: no yes, unlocks
sync_page: no maybe
writepages: no
set_page_dirty no no
readpages: no
-prepare_write: no yes
-commit_write: no yes
+prepare_write: no yes yes
+commit_write: no yes yes
+write_begin: no locks the page yes
+write_end: no yes, unlocks yes
+perform_write: no n/a yes
bmap: yes
invalidatepage: no yes
releasepage: no yes
@@ -221,7 +224,7 @@ against the page the filesystem should redirty the page with
redirty_page_for_writepage(), then unlock the page and return zero.
This may also be done to avoid internal deadlocks, but rarely.
-If the filesytem is called for sync then it must wait on any
+If the filesystem is called for sync then it must wait on any
in-progress I/O and then start new I/O.
The filesystem should unlock the page synchronously, before returning to the
diff --git a/Documentation/filesystems/ext3.txt b/Documentation/filesystems/ext3.txt
index 4aecc9bdb273..b45f3c1b8b43 100644
--- a/Documentation/filesystems/ext3.txt
+++ b/Documentation/filesystems/ext3.txt
@@ -130,12 +130,12 @@ Device layer.
Journaling Block Device layer
-----------------------------
-The Journaling Block Device layer (JBD) isn't ext3 specific. It was design to
-add journaling capabilities on a block device. The ext3 filesystem code will
-inform the JBD of modifications it is performing (called a transaction). The
-journal supports the transactions start and stop, and in case of crash, the
-journal can replayed the transactions to put the partition back in a
-consistent state fast.
+The Journaling Block Device layer (JBD) isn't ext3 specific. It was designed
+to add journaling capabilities to a block device. The ext3 filesystem code
+will inform the JBD of modifications it is performing (called a transaction).
+The journal supports the transactions start and stop, and in case of a crash,
+the journal can replay the transactions to quickly put the partition back into
+a consistent state.
Handles represent a single atomic update to a filesystem. JBD can handle an
external journal on a block device.
@@ -164,7 +164,7 @@ written to the journal first, and then to its final location.
In the event of a crash, the journal can be replayed, bringing both data and
metadata into a consistent state. This mode is the slowest except when data
needs to be read from and written to disk at the same time where it
-outperforms all others modes.
+outperforms all other modes.
Compatibility
-------------
diff --git a/Documentation/filesystems/files.txt b/Documentation/filesystems/files.txt
index 133e213ebb72..bb0142f61084 100644
--- a/Documentation/filesystems/files.txt
+++ b/Documentation/filesystems/files.txt
@@ -76,13 +76,13 @@ the fdtable structure -
5. Handling of the file structures is special. Since the look-up
of the fd (fget()/fget_light()) are lock-free, it is possible
that look-up may race with the last put() operation on the
- file structure. This is avoided using the rcuref APIs
+ file structure. This is avoided using atomic_inc_not_zero()
on ->f_count :
rcu_read_lock();
file = fcheck_files(files, fd);
if (file) {
- if (rcuref_inc_lf(&file->f_count))
+ if (atomic_inc_not_zero(&file->f_count))
*fput_needed = 1;
else
/* Didn't get the reference, someone's freed */
@@ -92,7 +92,7 @@ the fdtable structure -
....
return file;
- rcuref_inc_lf() detects if refcounts is already zero or
+ atomic_inc_not_zero() detects if refcounts is already zero or
goes to zero during increment. If it does, we fail
fget()/fget_light().
diff --git a/Documentation/locks.txt b/Documentation/filesystems/locks.txt
index e3b402ef33bd..fab857accbd6 100644
--- a/Documentation/locks.txt
+++ b/Documentation/filesystems/locks.txt
@@ -53,11 +53,11 @@ fcntl(), with all the problems that implies.
1.3 Mandatory Locking As A Mount Option
---------------------------------------
-Mandatory locking, as described in 'Documentation/mandatory.txt' was prior
-to this release a general configuration option that was valid for all
-mounted filesystems. This had a number of inherent dangers, not the least
-of which was the ability to freeze an NFS server by asking it to read a
-file for which a mandatory lock existed.
+Mandatory locking, as described in 'Documentation/filesystems/mandatory.txt'
+was prior to this release a general configuration option that was valid for
+all mounted filesystems. This had a number of inherent dangers, not the
+least of which was the ability to freeze an NFS server by asking it to read
+a file for which a mandatory lock existed.
From this release of the kernel, mandatory locking can be turned on and off
on a per-filesystem basis, using the mount options 'mand' and 'nomand'.
diff --git a/Documentation/mandatory.txt b/Documentation/filesystems/mandatory-locking.txt
index bc449d49eee5..0979d1d2ca8b 100644
--- a/Documentation/mandatory.txt
+++ b/Documentation/filesystems/mandatory-locking.txt
@@ -3,7 +3,26 @@
Andy Walker <andy@lysaker.kvaerner.no>
15 April 1996
-
+ (Updated September 2007)
+
+0. Why you should avoid mandatory locking
+-----------------------------------------
+
+The Linux implementation is prey to a number of difficult-to-fix race
+conditions which in practice make it not dependable:
+
+ - The write system call checks for a mandatory lock only once
+ at its start. It is therefore possible for a lock request to
+ be granted after this check but before the data is modified.
+ A process may then see file data change even while a mandatory
+ lock was held.
+ - Similarly, an exclusive lock may be granted on a file after
+ the kernel has decided to proceed with a read, but before the
+ read has actually completed, and the reading process may see
+ the file data in a state which should not have been visible
+ to it.
+ - Similar races make the claimed mutual exclusion between lock
+ and mmap similarly unreliable.
1. What is mandatory locking?
------------------------------
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index 4a37e25e694c..dec99455321f 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -347,7 +347,35 @@ connects the CPUs in a SMP system. This means that an error has been detected,
the IO-APIC automatically retry the transmission, so it should not be a big
problem, but you should read the SMP-FAQ.
-In this context it could be interesting to note the new irq directory in 2.4.
+In 2.6.2* /proc/interrupts was expanded again. This time the goal was for
+/proc/interrupts to display every IRQ vector in use by the system, not
+just those considered 'most important'. The new vectors are:
+
+ THR -- interrupt raised when a machine check threshold counter
+ (typically counting ECC corrected errors of memory or cache) exceeds
+ a configurable threshold. Only available on some systems.
+
+ TRM -- a thermal event interrupt occurs when a temperature threshold
+ has been exceeded for the CPU. This interrupt may also be generated
+ when the temperature drops back to normal.
+
+ SPU -- a spurious interrupt is some interrupt that was raised then lowered
+ by some IO device before it could be fully processed by the APIC. Hence
+ the APIC sees the interrupt but does not know what device it came from.
+ For this case the APIC will generate the interrupt with a IRQ vector
+ of 0xff. This might also be generated by chipset bugs.
+
+ RES, CAL, TLB -- rescheduling, call and TLB flush interrupts are
+ sent from one CPU to another per the needs of the OS. Typically,
+ their statistics are used by kernel developers and interested users to
+ determine the occurance of interrupt of the given type.
+
+The above IRQ vectors are displayed only when relevent. For example,
+the threshold vector does not exist on x86_64 platforms. Others are
+suppressed when the system is a uniprocessor. As of this writing, only
+i386 and x86_64 platforms support the new IRQ vector displays.
+
+Of some interest is the introduction of the /proc/irq directory to 2.4.
It could be used to set IRQ to CPU affinity, this means that you can "hook" an
IRQ to only one CPU, or to exclude a CPU of handling IRQs. The contents of the
irq subdir is one subdir for each IRQ, and one file; prof_cpu_mask
@@ -785,9 +813,9 @@ Various pieces of information about kernel activity are available in the
since the system first booted. For a quick look, simply cat the file:
> cat /proc/stat
- cpu 2255 34 2290 22625563 6290 127 456
- cpu0 1132 34 1441 11311718 3675 127 438
- cpu1 1123 0 849 11313845 2614 0 18
+ cpu 2255 34 2290 22625563 6290 127 456 0
+ cpu0 1132 34 1441 11311718 3675 127 438 0
+ cpu1 1123 0 849 11313845 2614 0 18 0
intr 114930548 113199788 3 0 5 263 0 4 [... lots more numbers ...]
ctxt 1990473
btime 1062191376
@@ -807,6 +835,7 @@ second). The meanings of the columns are as follows, from left to right:
- iowait: waiting for I/O to complete
- irq: servicing interrupts
- softirq: servicing softirqs
+- steal: involuntary wait
The "intr" line gives counts of interrupts serviced since boot time, for each
of the possible system interrupts. The first column is the total of all
diff --git a/Documentation/filesystems/quota.txt b/Documentation/filesystems/quota.txt
new file mode 100644
index 000000000000..a590c4093eff
--- /dev/null
+++ b/Documentation/filesystems/quota.txt
@@ -0,0 +1,59 @@
+
+Quota subsystem
+===============
+
+Quota subsystem allows system administrator to set limits on used space and
+number of used inodes (inode is a filesystem structure which is associated
+with each file or directory) for users and/or groups. For both used space and
+number of used inodes there are actually two limits. The first one is called
+softlimit and the second one hardlimit. An user can never exceed a hardlimit
+for any resource. User is allowed to exceed softlimit but only for limited
+period of time. This period is called "grace period" or "grace time". When
+grace time is over, user is not able to allocate more space/inodes until he
+frees enough of them to get below softlimit.
+
+Quota limits (and amount of grace time) are set independently for each
+filesystem.
+
+For more details about quota design, see the documentation in quota-tools package
+(http://sourceforge.net/projects/linuxquota).
+
+Quota netlink interface
+=======================
+When user exceeds a softlimit, runs out of grace time or reaches hardlimit,
+quota subsystem traditionally printed a message to the controlling terminal of
+the process which caused the excess. This method has the disadvantage that
+when user is using a graphical desktop he usually cannot see the message.
+Thus quota netlink interface has been designed to pass information about
+the above events to userspace. There they can be captured by an application
+and processed accordingly.
+
+The interface uses generic netlink framework (see
+http://lwn.net/Articles/208755/ and http://people.suug.ch/~tgr/libnl/ for more
+details about this layer). The name of the quota generic netlink interface
+is "VFS_DQUOT". Definitions of constants below are in <linux/quota.h>.
+ Currently, the interface supports only one message type QUOTA_NL_C_WARNING.
+This command is used to send a notification about any of the above mentioned
+events. Each message has six attributes. These are (type of the argument is
+in parentheses):
+ QUOTA_NL_A_QTYPE (u32)
+ - type of quota being exceeded (one of USRQUOTA, GRPQUOTA)
+ QUOTA_NL_A_EXCESS_ID (u64)
+ - UID/GID (depends on quota type) of user / group whose limit
+ is being exceeded.
+ QUOTA_NL_A_CAUSED_ID (u64)
+ - UID of a user who caused the event
+ QUOTA_NL_A_WARNING (u32)
+ - what kind of limit is exceeded:
+ QUOTA_NL_IHARDWARN - inode hardlimit
+ QUOTA_NL_ISOFTLONGWARN - inode softlimit is exceeded longer
+ than given grace period
+ QUOTA_NL_ISOFTWARN - inode softlimit
+ QUOTA_NL_BHARDWARN - space (block) hardlimit
+ QUOTA_NL_BSOFTLONGWARN - space (block) softlimit is exceeded
+ longer than given grace period.
+ QUOTA_NL_BSOFTWARN - space (block) softlimit
+ QUOTA_NL_A_DEV_MAJOR (u32)
+ - major number of a device with the affected filesystem
+ QUOTA_NL_A_DEV_MINOR (u32)
+ - minor number of a device with the affected filesystem
diff --git a/Documentation/filesystems/ramfs-rootfs-initramfs.txt b/Documentation/filesystems/ramfs-rootfs-initramfs.txt
index 25981e2e51be..339c6a4f220e 100644
--- a/Documentation/filesystems/ramfs-rootfs-initramfs.txt
+++ b/Documentation/filesystems/ramfs-rootfs-initramfs.txt
@@ -8,7 +8,7 @@ What is ramfs?
Ramfs is a very simple filesystem that exports Linux's disk caching
mechanisms (the page cache and dentry cache) as a dynamically resizable
-ram-based filesystem.
+RAM-based filesystem.
Normally all files are cached in memory by Linux. Pages of data read from
backing store (usually the block device the filesystem is mounted on) are kept
@@ -34,7 +34,7 @@ ramfs and ramdisk:
------------------
The older "ram disk" mechanism created a synthetic block device out of
-an area of ram and used it as backing store for a filesystem. This block
+an area of RAM and used it as backing store for a filesystem. This block
device was of fixed size, so the filesystem mounted on it was of fixed
size. Using a ram disk also required unnecessarily copying memory from the
fake block device into the page cache (and copying changes back out), as well
@@ -46,8 +46,8 @@ unnecessary work for the CPU, and pollutes the CPU caches. (There are tricks
to avoid this copying by playing with the page tables, but they're unpleasantly
complicated and turn out to be about as expensive as the copying anyway.)
More to the point, all the work ramfs is doing has to happen _anyway_,
-since all file access goes through the page and dentry caches. The ram
-disk is simply unnecessary, ramfs is internally much simpler.
+since all file access goes through the page and dentry caches. The RAM
+disk is simply unnecessary; ramfs is internally much simpler.
Another reason ramdisks are semi-obsolete is that the introduction of
loopback devices offered a more flexible and convenient way to create
@@ -103,7 +103,7 @@ All this differs from the old initrd in several ways:
initramfs archive is a gzipped cpio archive (like tar only simpler,
see cpio(1) and Documentation/early-userspace/buffer-format.txt). The
kernel's cpio extraction code is not only extremely small, it's also
- __init data that can be discarded during the boot process.
+ __init text and data that can be discarded during the boot process.
- The program run by the old initrd (which was called /initrd, not /init) did
some setup and then returned to the kernel, while the init program from
@@ -220,7 +220,7 @@ device) but the separate packaging of initrd (which is nice if you have
non-GPL code you'd like to run from initramfs, without conflating it with
the GPL licensed Linux kernel binary).
-It can also be used to supplement the kernel's built-in initamfs image. The
+It can also be used to supplement the kernel's built-in initramfs image. The
files in the external archive will overwrite any conflicting files in
the built-in initramfs archive. Some distributors also prefer to customize
a single kernel image with task-specific initramfs images, without recompiling.
@@ -339,7 +339,7 @@ smooth transition and allowing early boot functionality to gradually move to
The move to early userspace is necessary because finding and mounting the real
root device is complex. Root partitions can span multiple devices (raid or
separate journal). They can be out on the network (requiring dhcp, setting a
-specific mac address, logging into a server, etc). They can live on removable
+specific MAC address, logging into a server, etc). They can live on removable
media, with dynamically allocated major/minor numbers and persistent naming
issues requiring a full udev implementation to sort out. They can be
compressed, encrypted, copy-on-write, loopback mounted, strangely partitioned,
diff --git a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt
index 4b5ca26e5048..4598ef7b622b 100644
--- a/Documentation/filesystems/sysfs.txt
+++ b/Documentation/filesystems/sysfs.txt
@@ -51,7 +51,7 @@ for the attributes, providing a means to read and write kernel
attributes.
Attributes should be ASCII text files, preferably with only one value
-per file. It is noted that it may not be efficient to contain only
+per file. It is noted that it may not be efficient to contain only one
value per file, so it is socially acceptable to express an array of
values of the same type.
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index 045f3e055a28..9d019d35728f 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -537,6 +537,12 @@ struct address_space_operations {
struct list_head *pages, unsigned nr_pages);
int (*prepare_write)(struct file *, struct page *, unsigned, unsigned);
int (*commit_write)(struct file *, struct page *, unsigned, unsigned);
+ int (*write_begin)(struct file *, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata);
+ int (*write_end)(struct file *, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata);
sector_t (*bmap)(struct address_space *, sector_t);
int (*invalidatepage) (struct page *, unsigned long);
int (*releasepage) (struct page *, int);
@@ -615,11 +621,7 @@ struct address_space_operations {
any basic-blocks on storage, then those blocks should be
pre-read (if they haven't been read already) so that the
updated blocks can be written out properly.
- The page will be locked. If prepare_write wants to unlock the
- page it, like readpage, may do so and return
- AOP_TRUNCATED_PAGE.
- In this case the prepare_write will be retried one the lock is
- regained.
+ The page will be locked.
Note: the page _must not_ be marked uptodate in this function
(or anywhere else) unless it actually is uptodate right now. As
@@ -633,6 +635,45 @@ struct address_space_operations {
operations. It should avoid returning an error if possible -
errors should have been handled by prepare_write.
+ write_begin: This is intended as a replacement for prepare_write. The
+ key differences being that:
+ - it returns a locked page (in *pagep) rather than being
+ given a pre locked page;
+ - it must be able to cope with short writes (where the
+ length passed to write_begin is greater than the number
+ of bytes copied into the page).
+
+ Called by the generic buffered write code to ask the filesystem to
+ prepare to write len bytes at the given offset in the file. The
+ address_space should check that the write will be able to complete,
+ by allocating space if necessary and doing any other internal
+ housekeeping. If the write will update parts of any basic-blocks on
+ storage, then those blocks should be pre-read (if they haven't been
+ read already) so that the updated blocks can be written out properly.
+
+ The filesystem must return the locked pagecache page for the specified
+ offset, in *pagep, for the caller to write into.
+
+ flags is a field for AOP_FLAG_xxx flags, described in
+ include/linux/fs.h.
+
+ A void * may be returned in fsdata, which then gets passed into
+ write_end.
+
+ Returns 0 on success; < 0 on failure (which is the error code), in
+ which case write_end is not called.
+
+ write_end: After a successful write_begin, and data copy, write_end must
+ be called. len is the original len passed to write_begin, and copied
+ is the amount that was able to be copied (copied == len is always true
+ if write_begin was called with the AOP_FLAG_UNINTERRUPTIBLE flag).
+
+ The filesystem must take care of unlocking the page and releasing it
+ refcount, and updating i_size.
+
+ Returns < 0 on failure, otherwise the number of bytes (<= 'copied')
+ that were able to be copied into pagecache.
+
bmap: called by the VFS to map a logical block offset within object to
physical block number. This method is used by the FIBMAP
ioctl and for working with swap-files. To be able to swap to
@@ -665,7 +706,7 @@ struct address_space_operations {
wants to make it a free page. If ->releasepage succeeds, the
page will be removed from the address_space and become free.
- The second case if when a request has been made to invalidate
+ The second case is when a request has been made to invalidate
some or all pages in an address_space. This can happen
through the fadvice(POSIX_FADV_DONTNEED) system call or by the
filesystem explicitly requesting it as nfs and 9fs do (when
diff --git a/Documentation/firmware_class/firmware_sample_firmware_class.c b/Documentation/firmware_class/firmware_sample_firmware_class.c
index fba943aacf93..2de62854f0e5 100644
--- a/Documentation/firmware_class/firmware_sample_firmware_class.c
+++ b/Documentation/firmware_class/firmware_sample_firmware_class.c
@@ -109,15 +109,15 @@ static int fw_setup_class_device(struct class_device *class_dev,
const char *fw_name,
struct device *device)
{
- int retval = 0;
- struct firmware_priv *fw_priv = kmalloc(sizeof(struct firmware_priv),
- GFP_KERNEL);
+ int retval;
+ struct firmware_priv *fw_priv;
- if(!fw_priv){
+ fw_priv = kzalloc(sizeof(struct firmware_priv), GFP_KERNEL);
+ if (!fw_priv) {
retval = -ENOMEM;
goto out;
}
- memset(fw_priv, 0, sizeof(*fw_priv));
+
memset(class_dev, 0, sizeof(*class_dev));
strncpy(fw_priv->fw_id, fw_name, FIRMWARE_NAME_MAX);
diff --git a/Documentation/hwmon/sysfs-interface b/Documentation/hwmon/sysfs-interface
index a17b692d2679..f4a8ebc1ef1a 100644
--- a/Documentation/hwmon/sysfs-interface
+++ b/Documentation/hwmon/sysfs-interface
@@ -328,6 +328,37 @@ curr[1-*]_input Current input value
Unit: milliampere
RO
+*********
+* Power *
+*********
+
+power[1-*]_average Average power use
+ Unit: microWatt
+ RO
+
+power[1-*]_average_highest Historical average maximum power use
+ Unit: microWatt
+ RO
+
+power[1-*]_average_lowest Historical average minimum power use
+ Unit: microWatt
+ RO
+
+power[1-*]_input Instantaneous power use
+ Unit: microWatt
+ RO
+
+power[1-*]_input_highest Historical maximum power use
+ Unit: microWatt
+ RO
+
+power[1-*]_input_lowest Historical minimum power use
+ Unit: microWatt
+ RO
+
+power[1-*]_reset_history Reset input_highest, input_lowest,
+ average_highest and average_lowest.
+ WO
**********
* Alarms *
diff --git a/Documentation/i2c/i2c-protocol b/Documentation/i2c/i2c-protocol
index 579b92d5f3a3..10518dd58814 100644
--- a/Documentation/i2c/i2c-protocol
+++ b/Documentation/i2c/i2c-protocol
@@ -68,7 +68,7 @@ We have found some I2C devices that needs the following modifications:
Flags I2C_M_IGNORE_NAK
Normally message is interrupted immediately if there is [NA] from the
- client. Setting this flag treats any [NA] as [A], and all of
+ client. Setting this flag treats any [NA] as [A], and all of
message is sent.
These messages may still fail to SCL lo->hi timeout.
diff --git a/Documentation/i386/boot.txt b/Documentation/i386/boot.txt
index 35985b34d5a6..fc49b79bc1ab 100644
--- a/Documentation/i386/boot.txt
+++ b/Documentation/i386/boot.txt
@@ -168,6 +168,8 @@ Offset Proto Name Meaning
0234/1 2.05+ relocatable_kernel Whether kernel is relocatable or not
0235/3 N/A pad2 Unused
0238/4 2.06+ cmdline_size Maximum size of the kernel command line
+023C/4 2.07+ hardware_subarch Hardware subarchitecture
+0240/8 2.07+ hardware_subarch_data Subarchitecture-specific data
(1) For backwards compatibility, if the setup_sects field contains 0, the
real value is 4.
@@ -204,7 +206,7 @@ boot loaders can ignore those fields.
The byte order of all fields is littleendian (this is x86, after all.)
-Field name: setup_secs
+Field name: setup_sects
Type: read
Offset/size: 0x1f1/1
Protocol: ALL
@@ -356,6 +358,13 @@ Protocol: 2.00+
- If 0, the protected-mode code is loaded at 0x10000.
- If 1, the protected-mode code is loaded at 0x100000.
+ Bit 6 (write): KEEP_SEGMENTS
+ Protocol: 2.07+
+ - if 0, reload the segment registers in the 32bit entry point.
+ - if 1, do not reload the segment registers in the 32bit entry point.
+ Assume that %cs %ds %ss %es are all set to flat segments with
+ a base of 0 (or the equivalent for their environment).
+
Bit 7 (write): CAN_USE_HEAP
Set this bit to 1 to indicate that the value entered in the
heap_end_ptr is valid. If this field is clear, some setup code
@@ -480,6 +489,29 @@ Protocol: 2.06+
cmdline_size characters. With protocol version 2.05 and earlier, the
maximum size was 255.
+Field name: hardware_subarch
+Type: write
+Offset/size: 0x23c/4
+Protocol: 2.07+
+
+ In a paravirtualized environment the hardware low level architectural
+ pieces such as interrupt handling, page table handling, and
+ accessing process control registers needs to be done differently.
+
+ This field allows the bootloader to inform the kernel we are in one
+ one of those environments.
+
+ 0x00000000 The default x86/PC environment
+ 0x00000001 lguest
+ 0x00000002 Xen
+
+Field name: hardware_subarch_data
+Type: write
+Offset/size: 0x240/8
+Protocol: 2.07+
+
+ A pointer to data that is specific to hardware subarch
+
**** THE KERNEL COMMAND LINE
@@ -753,3 +785,41 @@ IMPORTANT: All the hooks are required to preserve %esp, %ebp, %esi and
After completing your hook, you should jump to the address
that was in this field before your boot loader overwrote it
(relocated, if appropriate.)
+
+
+**** 32-bit BOOT PROTOCOL
+
+For machine with some new BIOS other than legacy BIOS, such as EFI,
+LinuxBIOS, etc, and kexec, the 16-bit real mode setup code in kernel
+based on legacy BIOS can not be used, so a 32-bit boot protocol needs
+to be defined.
+
+In 32-bit boot protocol, the first step in loading a Linux kernel
+should be to setup the boot parameters (struct boot_params,
+traditionally known as "zero page"). The memory for struct boot_params
+should be allocated and initialized to all zero. Then the setup header
+from offset 0x01f1 of kernel image on should be loaded into struct
+boot_params and examined. The end of setup header can be calculated as
+follow:
+
+ 0x0202 + byte value at offset 0x0201
+
+In addition to read/modify/write the setup header of the struct
+boot_params as that of 16-bit boot protocol, the boot loader should
+also fill the additional fields of the struct boot_params as that
+described in zero-page.txt.
+
+After setupping the struct boot_params, the boot loader can load the
+32/64-bit kernel in the same way as that of 16-bit boot protocol.
+
+In 32-bit boot protocol, the kernel is started by jumping to the
+32-bit kernel entry point, which is the start address of loaded
+32/64-bit kernel.
+
+At entry, the CPU must be in 32-bit protected mode with paging
+disabled; a GDT must be loaded with the descriptors for selectors
+__BOOT_CS(0x10) and __BOOT_DS(0x18); both descriptors must be 4G flat
+segment; __BOOS_CS must have execute/read permission, and __BOOT_DS
+must have read/write permission; CS must be __BOOT_CS and DS, ES, SS
+must be __BOOT_DS; interrupt must be disabled; %esi must hold the base
+address of the struct boot_params; %ebp, %edi and %ebx must be zero.
diff --git a/Documentation/i386/zero-page.txt b/Documentation/i386/zero-page.txt
index 6c0817c45683..169ad423a3d1 100644
--- a/Documentation/i386/zero-page.txt
+++ b/Documentation/i386/zero-page.txt
@@ -1,99 +1,31 @@
----------------------------------------------------------------------------
-!!!!!!!!!!!!!!!WARNING!!!!!!!!
-The zero page is a kernel internal data structure, not a stable ABI. It might change
-without warning and the kernel has no way to detect old version of it.
-If you're writing some external code like a boot loader you should only use
-the stable versioned real mode boot protocol described in boot.txt. Otherwise the kernel
-might break you at any time.
-!!!!!!!!!!!!!WARNING!!!!!!!!!!!
-----------------------------------------------------------------------------
+The additional fields in struct boot_params as a part of 32-bit boot
+protocol of kernel. These should be filled by bootloader or 16-bit
+real-mode setup code of the kernel. References/settings to it mainly
+are in:
-Summary of boot_params layout (kernel point of view)
- ( collected by Hans Lermen and Martin Mares )
-
-The contents of boot_params are used to pass parameters from the
-16-bit realmode code of the kernel to the 32-bit part. References/settings
-to it mainly are in:
+ include/asm-x86/bootparam.h
- arch/i386/boot/setup.S
- arch/i386/boot/video.S
- arch/i386/kernel/head.S
- arch/i386/kernel/setup.c
-
-Offset Type Description
------- ---- -----------
- 0 32 bytes struct screen_info, SCREEN_INFO
- ATTENTION, overlaps the following !!!
- 2 unsigned short EXT_MEM_K, extended memory size in Kb (from int 0x15)
- 0x20 unsigned short CL_MAGIC, commandline magic number (=0xA33F)
- 0x22 unsigned short CL_OFFSET, commandline offset
- Address of commandline is calculated:
- 0x90000 + contents of CL_OFFSET
- (only taken, when CL_MAGIC = 0xA33F)
- 0x40 20 bytes struct apm_bios_info, APM_BIOS_INFO
- 0x60 16 bytes Intel SpeedStep (IST) BIOS support information
- 0x80 16 bytes hd0-disk-parameter from intvector 0x41
- 0x90 16 bytes hd1-disk-parameter from intvector 0x46
+Offset Proto Name Meaning
+/Size
- 0xa0 16 bytes System description table truncated to 16 bytes.
- ( struct sys_desc_table_struct )
- 0xb0 - 0x13f Free. Add more parameters here if you really need them.
- 0x140- 0x1be EDID_INFO Video mode setup
-
-0x1c4 unsigned long EFI system table pointer
-0x1c8 unsigned long EFI memory descriptor size
-0x1cc unsigned long EFI memory descriptor version
-0x1d0 unsigned long EFI memory descriptor map pointer
-0x1d4 unsigned long EFI memory descriptor map size
-0x1e0 unsigned long ALT_MEM_K, alternative mem check, in Kb
-0x1e4 unsigned long Scratch field for the kernel setup code
-0x1e8 char number of entries in E820MAP (below)
-0x1e9 unsigned char number of entries in EDDBUF (below)
-0x1ea unsigned char number of entries in EDD_MBR_SIG_BUFFER (below)
-0x1f1 char size of setup.S, number of sectors
-0x1f2 unsigned short MOUNT_ROOT_RDONLY (if !=0)
-0x1f4 unsigned short size of compressed kernel-part in the
- (b)zImage-file (in 16 byte units, rounded up)
-0x1f6 unsigned short swap_dev (unused AFAIK)
-0x1f8 unsigned short RAMDISK_FLAGS
-0x1fa unsigned short VGA-Mode (old one)
-0x1fc unsigned short ORIG_ROOT_DEV (high=Major, low=minor)
-0x1ff char AUX_DEVICE_INFO
-
-0x200 short jump to start of setup code aka "reserved" field.
-0x202 4 bytes Signature for SETUP-header, ="HdrS"
-0x206 unsigned short Version number of header format
- Current version is 0x0201...
-0x208 8 bytes (used by setup.S for communication with boot loaders,
- look there)
-0x210 char LOADER_TYPE, = 0, old one
- else it is set by the loader:
- 0xTV: T=0 for LILO
- 1 for Loadlin
- 2 for bootsect-loader
- 3 for SYSLINUX
- 4 for ETHERBOOT
- 5 for ELILO
- 7 for GRuB
- 8 for U-BOOT
- 9 for Xen
- V = version
-0x211 char loadflags:
- bit0 = 1: kernel is loaded high (bzImage)
- bit7 = 1: Heap and pointer (see below) set by boot
- loader.
-0x212 unsigned short (setup.S)
-0x214 unsigned long KERNEL_START, where the loader started the kernel
-0x218 unsigned long INITRD_START, address of loaded ramdisk image
-0x21c unsigned long INITRD_SIZE, size in bytes of ramdisk image
-0x220 4 bytes (setup.S)
-0x224 unsigned short setup.S heap end pointer
-0x226 unsigned short zero_pad
-0x228 unsigned long cmd_line_ptr
-0x22c unsigned long ramdisk_max
-0x230 16 bytes trampoline
-0x290 - 0x2cf EDD_MBR_SIG_BUFFER (edd.S)
-0x2d0 - 0xd00 E820MAP
-0xd00 - 0xeff EDDBUF (edd.S) for disk signature read sector
-0xd00 - 0xeeb EDDBUF (edd.S) for edd data
+000/040 ALL screen_info Text mode or frame buffer information
+ (struct screen_info)
+040/014 ALL apm_bios_info APM BIOS information (struct apm_bios_info)
+060/010 ALL ist_info Intel SpeedStep (IST) BIOS support information
+ (struct ist_info)
+080/010 ALL hd0_info hd0 disk parameter, OBSOLETE!!
+090/010 ALL hd1_info hd1 disk parameter, OBSOLETE!!
+0A0/010 ALL sys_desc_table System description table (struct sys_desc_table)
+140/080 ALL edid_info Video mode setup (struct edid_info)
+1C0/020 ALL efi_info EFI 32 information (struct efi_info)
+1E0/004 ALL alk_mem_k Alternative mem check, in KB
+1E4/004 ALL scratch Scratch field for the kernel setup code
+1E8/001 ALL e820_entries Number of entries in e820_map (below)
+1E9/001 ALL eddbuf_entries Number of entries in eddbuf (below)
+1EA/001 ALL edd_mbr_sig_buf_entries Number of entries in edd_mbr_sig_buffer
+ (below)
+290/040 ALL edd_mbr_sig_buffer EDD MBR signatures
+2D0/A00 ALL e820_map E820 memory map table
+ (array of struct e820entry)
+D00/1EC ALL eddbuf EDD data (array of struct edd_info)
diff --git a/Documentation/ia64/err_inject.txt b/Documentation/ia64/err_inject.txt
index 6449a7090dbb..223e4f0582d0 100644
--- a/Documentation/ia64/err_inject.txt
+++ b/Documentation/ia64/err_inject.txt
@@ -21,10 +21,10 @@ software test suits to do stressful testing on IPF.
Below is a sample application as part of the whole tool. The sample
can be used as a working test tool. Or it can be expanded to include
-more features. It also can be a integrated into a libary or other user
+more features. It also can be a integrated into a library or other user
application to have more thorough test.
-The sample application takes err.conf as error configuation input. Gcc
+The sample application takes err.conf as error configuration input. GCC
compiles the code. After you install err_inject driver, you can run
this sample application to inject errors.
@@ -809,7 +809,7 @@ int err_inj()
}
/* Create semaphore: If one_lock, one semaphore for all processors.
- Otherwise, one sempaphore for each processor. */
+ Otherwise, one semaphore for each processor. */
if (one_lock) {
if (create_sem(0)) {
printf("Can not create semaphore...exit\n");
diff --git a/Documentation/ide.txt b/Documentation/ide.txt
index 3bb9f9c98611..1d50f23a5cab 100644
--- a/Documentation/ide.txt
+++ b/Documentation/ide.txt
@@ -242,6 +242,8 @@ Summary of ide driver parameters for kernel command line
and quite likely to cause trouble with
older/odd IDE drives.
+ "hdx=nodma" : disallow DMA
+
"hdx=swapdata" : when the drive is a disk, byte swap all data
"hdx=bswap" : same as above..........
@@ -278,8 +280,6 @@ Summary of ide driver parameters for kernel command line
"idex=four" : four drives on idex and ide(x^1) share same ports
"idex=reset" : reset interface after probe
-
- "idex=dma" : automatically configure/use DMA if possible.
"idex=ata66" : informs the interface that it has an 80c cable
for chipsets that are ATA-66 capable, but the
@@ -288,8 +288,6 @@ Summary of ide driver parameters for kernel command line
"ide=reverse" : formerly called to pci sub-system, but now local.
- "ide=nodma" : disable DMA globally for the IDE subsystem.
-
The following are valid ONLY on ide0, which usually corresponds
to the first ATA interface found on the particular host, and the defaults for
the base,ctl ports must not be altered.
diff --git a/Documentation/initrd.txt b/Documentation/initrd.txt
index d3dc505104da..74f68b35f7c1 100644
--- a/Documentation/initrd.txt
+++ b/Documentation/initrd.txt
@@ -80,8 +80,8 @@ Compressed cpio images
----------------------
Recent kernels have support for populating a ramdisk from a compressed cpio
-archive, on such systems, the creation of a ramdisk image doesn't need to
-involve special block devices or loopbacks, you merely create a directory on
+archive. On such systems, the creation of a ramdisk image doesn't need to
+involve special block devices or loopbacks; you merely create a directory on
disk with the desired initrd content, cd to that directory, and run (as an
example):
@@ -293,7 +293,7 @@ information as small as possible. In this case, a common initrd could be
generated with all the necessary modules. Then, only /sbin/init or a file
read by it would have to be different.
-A third scenario are more convenient recovery disks, because information
+A third scenario is more convenient recovery disks, because information
like the location of the root FS partition doesn't have to be provided at
boot time, but the system loaded from initrd can invoke a user-friendly
dialog and it can also perform some sanity checks (or even some form of
@@ -339,8 +339,8 @@ the new, supported mechanism is called "pivot_root".
Mixed change_root and pivot_root mechanism
------------------------------------------
-In case you did not want to use root=/dev/ram0 to trig the pivot_root mechanism,
-you may create both /linuxrc and /sbin/init in your initrd image.
+In case you did not want to use root=/dev/ram0 to trigger the pivot_root
+mechanism, you may create both /linuxrc and /sbin/init in your initrd image.
/linuxrc would contain only the following:
@@ -350,7 +350,7 @@ echo 0x0100 >/proc/sys/kernel/real-root-dev
umount -n /proc
Once linuxrc exited, the kernel would mount again your initrd as root,
-this time executing /sbin/init. Again, it would be duty of this init
+this time executing /sbin/init. Again, it would be the duty of this init
to build the right environment (maybe using the root= device passed on
the cmdline) before the final execution of the real /sbin/init.
diff --git a/Documentation/input/atarikbd.txt b/Documentation/input/atarikbd.txt
index ab050621e20f..f3a3ba8847ba 100644
--- a/Documentation/input/atarikbd.txt
+++ b/Documentation/input/atarikbd.txt
@@ -170,7 +170,7 @@ major controller faults (ROM checksum and RAM test) and such things as stuck
keys. Any keys down at power-up are presumed to be stuck, and their BREAK
(sic) code is returned (which without the preceding MAKE code is a flag for a
keyboard error). If the controller self-test completes without error, the code
-0xF0 is returned. (This code will be used to indicate the version/rlease of
+0xF0 is returned. (This code will be used to indicate the version/release of
the ikbd controller. The first release of the ikbd is version 0xF0, should
there be a second release it will be 0xF1, and so on.)
The ikbd defaults to a mouse position reporting with threshold of 1 unit in
@@ -413,7 +413,7 @@ INTERROGATION MODE.
%nnnnmmmm ; where m is JOYSTICK1 state
; and n is JOYSTICK0 state
-Sets the ikbd to do nothing but monitor the serial command lne, maintain the
+Sets the ikbd to do nothing but monitor the serial command line, maintain the
time-of-day clock, and monitor the joystick. The rate sets the interval
between joystick samples.
N.B. The user should not set the rate higher than the serial communications
@@ -446,10 +446,10 @@ The sample interval should be as constant as possible.
; until vertical cursor key is generated before RY
; has elapsed
VX ; length (in tenths of seconds) of joystick closure
- ; until horizontal cursor keystokes are generated
+ ; until horizontal cursor keystrokes are generated
; after RX has elapsed
VY ; length (in tenths of seconds) of joystick closure
- ; until vertical cursor keystokes are generated
+ ; until vertical cursor keystrokes are generated
; after RY has elapsed
In this mode, joystick 0 is scanned in a way that simulates cursor keystrokes.
diff --git a/Documentation/input/ff.txt b/Documentation/input/ff.txt
index 085eb15b45b7..ded4d5f53109 100644
--- a/Documentation/input/ff.txt
+++ b/Documentation/input/ff.txt
@@ -1,5 +1,5 @@
Force feedback for Linux.
-By Johann Deneux <deneux@ifrance.com> on 2001/04/22.
+By Johann Deneux <johann.deneux@gmail.com> on 2001/04/22.
Updated by Anssi Hannula <anssi.hannula@gmail.com> on 2006/04/09.
You may redistribute this file. Please remember to include shape.fig and
interactive.fig as well.
diff --git a/Documentation/input/iforce-protocol.txt b/Documentation/input/iforce-protocol.txt
index 8777d2d321e3..3ac92413c874 100644
--- a/Documentation/input/iforce-protocol.txt
+++ b/Documentation/input/iforce-protocol.txt
@@ -4,10 +4,10 @@ specify force effects to I-Force 2.0 devices. None of this information comes
from Immerse. That's why you should not trust what is written in this
document. This document is intended to help understanding the protocol.
This is not a reference. Comments and corrections are welcome. To contact me,
-send an email to: deneux@ifrance.com
+send an email to: johann.deneux@gmail.com
** WARNING **
-I may not be held responsible for any dammage or harm caused if you try to
+I shall not be held responsible for any damage or harm caused if you try to
send data to your I-Force device based on what you read in this document.
** Preliminary Notes:
@@ -151,13 +151,13 @@ OP= ff
Query command. Length varies according to the query type.
The general format of this packet is:
ff 01 QUERY [INDEX] CHECKSUM
-reponses are of the same form:
+responses are of the same form:
FF LEN QUERY VALUE_QUERIED CHECKSUM2
where LEN = 1 + length(VALUE_QUERIED)
**** Query ram size ****
QUERY = 42 ('B'uffer size)
-The device should reply with the same packet plus two additionnal bytes
+The device should reply with the same packet plus two additional bytes
containing the size of the memory:
ff 03 42 03 e8 CS would mean that the device has 1000 bytes of ram available.
@@ -234,19 +234,23 @@ is the amount of memory apparently needed for every set of parameters:
** Appendix: How to study the protocol ? **
-1. Generate effects using the force editor provided with the DirectX SDK, or use Immersion Studio (freely available at their web site in the developer section: www.immersion.com)
-2. Start a soft spying RS232 or USB (depending on where you connected your joystick/wheel). I used ComPortSpy from fCoder (alpha version!)
+1. Generate effects using the force editor provided with the DirectX SDK, or
+use Immersion Studio (freely available at their web site in the developer section:
+www.immersion.com)
+2. Start a soft spying RS232 or USB (depending on where you connected your
+joystick/wheel). I used ComPortSpy from fCoder (alpha version!)
3. Play the effect, and watch what happens on the spy screen.
A few words about ComPortSpy:
-At first glance, this soft seems, hum, well... buggy. In fact, data appear with a few seconds latency. Personnaly, I restart it every time I play an effect.
+At first glance, this software seems, hum, well... buggy. In fact, data appear with a
+few seconds latency. Personally, I restart it every time I play an effect.
Remember it's free (as in free beer) and alpha!
** URLS **
Check www.immerse.com for Immersion Studio, and www.fcoder.com for ComPortSpy.
** Author of this document **
-Johann Deneux <deneux@ifrance.com>
+Johann Deneux <johann.deneux@gmail.com>
Home page at http://www.esil.univ-mrs.fr/~jdeneux/projects/ff/
Additions by Vojtech Pavlik.
diff --git a/Documentation/input/input-programming.txt b/Documentation/input/input-programming.txt
index d9d523099bb7..47fc86830cd7 100644
--- a/Documentation/input/input-programming.txt
+++ b/Documentation/input/input-programming.txt
@@ -42,8 +42,8 @@ static int __init button_init(void)
goto err_free_irq;
}
- button_dev->evbit[0] = BIT(EV_KEY);
- button_dev->keybit[LONG(BTN_0)] = BIT(BTN_0);
+ button_dev->evbit[0] = BIT_MASK(EV_KEY);
+ button_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0);
error = input_register_device(button_dev);
if (error) {
@@ -79,7 +79,7 @@ In the _init function, which is called either upon module load or when
booting the kernel, it grabs the required resources (it should also check
for the presence of the device).
-Then it allocates a new input device structure with input_aloocate_device()
+Then it allocates a new input device structure with input_allocate_device()
and sets up input bitfields. This way the device driver tells the other
parts of the input systems what it is - what events can be generated or
accepted by this input device. Our example device can only generate EV_KEY
@@ -217,14 +217,15 @@ If you don't need absfuzz and absflat, you can set them to zero, which mean
that the thing is precise and always returns to exactly the center position
(if it has any).
-1.4 NBITS(), LONG(), BIT()
+1.4 BITS_TO_LONGS(), BIT_WORD(), BIT_MASK()
~~~~~~~~~~~~~~~~~~~~~~~~~~
-These three macros from input.h help some bitfield computations:
+These three macros from bitops.h help some bitfield computations:
- NBITS(x) - returns the length of a bitfield array in longs for x bits
- LONG(x) - returns the index in the array in longs for bit x
- BIT(x) - returns the index in a long for bit x
+ BITS_TO_LONGS(x) - returns the length of a bitfield array in longs for
+ x bits
+ BIT_WORD(x) - returns the index in the array in longs for bit x
+ BIT_MASK(x) - returns the index in a long for bit x
1.5 The id* and name fields
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/Documentation/isdn/CREDITS b/Documentation/isdn/CREDITS
index 7c17c837064f..8cac6c2f23ee 100644
--- a/Documentation/isdn/CREDITS
+++ b/Documentation/isdn/CREDITS
@@ -40,7 +40,7 @@ Andreas Kool (akool@Kool.f.EUnet.de)
Pedro Roque Marques (roque@di.fc.ul.pt)
For lot of new ideas and the pcbit driver.
-Eberhard Moenkeberg (emoenke@gwdg.de)
+Eberhard Mönkeberg (emoenke@gwdg.de)
For testing and help to get into kernel.
Thomas Neumann (tn@ruhr.de)
diff --git a/Documentation/isdn/README.concap b/Documentation/isdn/README.concap
index 2f114babe4b6..a76d74845a4c 100644
--- a/Documentation/isdn/README.concap
+++ b/Documentation/isdn/README.concap
@@ -111,7 +111,7 @@ struct concap_proto_ops{
struct concap_proto * (*proto_new) (void);
/* delete encapsulation protocol instance and free all its resources.
- cprot may no loger be referenced after calling this */
+ cprot may no longer be referenced after calling this */
void (*proto_del)(struct concap_proto *cprot);
/* initialize the protocol's data. To be called at interface startup
diff --git a/Documentation/ja_JP/SubmittingPatches b/Documentation/ja_JP/SubmittingPatches
new file mode 100644
index 000000000000..a9dc1243e859
--- /dev/null
+++ b/Documentation/ja_JP/SubmittingPatches
@@ -0,0 +1,556 @@
+NOTE:
+This is a version of Documentation/SubmittingPatches into Japanese.
+This document is maintained by Keiichi KII <k-keiichi@bx.jp.nec.com>
+and the JF Project team <http://www.linux.or.jp/JF/>.
+If you find any difference between this document and the original file
+or a problem with the translation,
+please contact the maintainer of this file or JF project.
+
+Please also note that the purpose of this file is to be easier to read
+for non English (read: Japanese) speakers and is not intended as a
+fork. So if you have any comments or updates of this file, please try
+to update the original English file first.
+
+Last Updated: 2007/10/24
+==================================
+ã“ã‚Œã¯ã€
+linux-2.6.23/Documentation/SubmittingPatches ã®å’Œè¨³
+ã§ã™ã€‚
+翻訳団体: JF プロジェクト < http://www.linux.or.jp/JF/ >
+翻訳日: 2007/10/17
+翻訳者: Keiichi Kii <k-keiichi at bx dot jp dot nec dot com>
+校正者: Masanari Kobayashi ã•ã‚“ <zap03216 at nifty dot ne dot jp>
+ Matsukura ã•ã‚“ <nbh--mats at nifty dot com>
+==================================
+
+ Linux カーãƒãƒ«ã«å¤‰æ›´ã‚’加ãˆã‚‹ãŸã‚ã® Howto
+ åˆã¯
+ ã‹ã® Linus Torvalds ã®å–り扱ã„説明書
+
+Linux カーãƒãƒ«ã«å¤‰æ›´ã‚’加ãˆãŸã„ã¨æ€ã£ã¦ã„る個人åˆã¯ä¼šç¤¾ã«ã¨ã£ã¦ã€ãƒ‘ッ
+ãƒã®æŠ•ç¨¿ã«é–¢é€£ã—ãŸä»•çµ„ã¿ã«æ…£ã‚Œã¦ã„ãªã‘ã‚Œã°ã€ãã®éŽç¨‹ã¯æ™‚々ã¿ãªã•ã‚“ã‚’
+ãŠã˜ã‘ã¥ã‹ã›ã‚‹ã“ã¨ã‚‚ã‚ã‚Šã¾ã™ã€‚ã“ã®æ–‡ç« ã¯ã‚ãªãŸã®å¤‰æ›´ã‚’大ã„ã«å—ã‘入れ
+ã¦ã‚‚らãˆã‚„ã™ãã™ã‚‹æ案を集ã‚ãŸã‚‚ã®ã§ã™ã€‚
+
+コードを投稿ã™ã‚‹å‰ã«ã€Documentation/SubmitChecklist ã®é …目リストã«ç›®
+を通ã—ã¦ãƒã‚§ãƒƒã‚¯ã—ã¦ãã ã•ã„。もã—ã‚ãªãŸãŒãƒ‰ãƒ©ã‚¤ãƒãƒ¼ã‚’投稿ã—よã†ã¨ã—
+ã¦ã„ã‚‹ãªã‚‰ã€Documentation/SubmittingDrivers ã«ã‚‚目を通ã—ã¦ãã ã•ã„。
+
+--------------------------------------------
+セクション1 パッãƒã®ä½œã‚Šæ–¹ã¨é€ã‚Šæ–¹
+--------------------------------------------
+
+1) 「 diff -up ã€
+------------
+
+パッãƒã®ä½œæˆã«ã¯ã€Œ diff -up ã€åˆã¯ã€Œ diff -uprN ã€ã‚’使ã£ã¦ãã ã•ã„。
+
+Linux カーãƒãƒ«ã«å¯¾ã™ã‚‹å…¨ã¦ã®å¤‰æ›´ã¯ diff(1) コマンドã«ã‚ˆã‚‹ãƒ‘ッãƒã®å½¢å¼ã§
+生æˆã—ã¦ãã ã•ã„。パッãƒã‚’作æˆã™ã‚‹ã¨ãã«ã¯ã€diff(1) コマンドã«ã€Œ -u ã€å¼•
+数を指定ã—ã¦ã€unified å½¢å¼ã®ãƒ‘ッãƒã‚’作æˆã™ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。ã¾ãŸã€
+変更ãŒã©ã® C 関数ã§è¡Œã‚ã‚ŒãŸã®ã‹ã‚’表示ã™ã‚‹ã€Œ -p ã€å¼•æ•°ã‚’使ã£ã¦ãã ã•ã„。
+ã“ã®å¼•æ•°ã¯ç”Ÿæˆã—ãŸå·®åˆ†ã‚’ãšã£ã¨èª­ã¿ã‚„ã™ãã—ã¦ãã‚Œã¾ã™ã€‚パッãƒã¯ Linux
+カーãƒãƒ«ã‚½ãƒ¼ã‚¹ã®ä¸­ã®ã‚µãƒ–ディレクトリã§ã¯ãªã Linux カーãƒãƒ«ã‚½ãƒ¼ã‚¹ã®ãƒ«ãƒ¼ãƒˆ
+ディレクトリを基準ã«ã—ãªã„ã¨ã„ã‘ã¾ã›ã‚“。
+
+1個ã®ãƒ•ã‚¡ã‚¤ãƒ«ã«ã¤ã„ã¦ã®ãƒ‘ッãƒã‚’作æˆã™ã‚‹ãŸã‚ã«ã¯ã€ã»ã¨ã‚“ã©ã®å ´åˆã€
+以下ã®ä½œæ¥­ã‚’è¡Œãˆã°å分ã§ã™ã€‚
+
+ SRCTREE= linux-2.6
+ MYFILE= drivers/net/mydriver.c
+
+ cd $SRCTREE
+ cp $MYFILE $MYFILE.orig
+ vi $MYFILE # make your change
+ cd ..
+ diff -up $SRCTREE/$MYFILE{.orig,} > /tmp/patch
+
+複数ã®ãƒ•ã‚¡ã‚¤ãƒ«ã«ã¤ã„ã¦ã®ãƒ‘ッãƒã‚’作æˆã™ã‚‹ãŸã‚ã«ã¯ã€ç´ ã®( vanilla )ã€ã™
+ãªã‚ã¡å¤‰æ›´ã‚’加ãˆã¦ãªã„ Linux カーãƒãƒ«ã‚’展開ã—ã€è‡ªåˆ†ã® Linux カーãƒãƒ«
+ソースã¨ã®å·®åˆ†ã‚’生æˆã—ãªã„ã¨ã„ã‘ã¾ã›ã‚“。例ãˆã°ã€
+
+ MYSRC= /devel/linux-2.6
+
+ tar xvfz linux-2.6.12.tar.gz
+ mv linux-2.6.12 linux-2.6.12-vanilla
+ diff -uprN -X linux-2.6.12-vanilla/Documentation/dontdiff \
+ linux-2.6.12-vanilla $MYSRC > /tmp/patch
+
+dontdiff ファイルã«ã¯ Linux カーãƒãƒ«ã®ãƒ“ルドプロセスã®éŽç¨‹ã§ç”Ÿæˆã•ã‚ŒãŸ
+ファイルã®ä¸€è¦§ãŒã®ã£ã¦ã„ã¾ã™ã€‚ãã—ã¦ã€ãれらã¯ãƒ‘ッãƒã‚’生æˆã™ã‚‹ diff(1)
+コマンドã§ç„¡è¦–ã•ã‚Œã‚‹ã¹ãã§ã™ã€‚dontdiff ファイル㯠2.6.12 以後ã®ãƒãƒ¼ã‚¸ãƒ§
+ン㮠Linux カーãƒãƒ«ã‚½ãƒ¼ã‚¹ãƒ„リーã«å«ã¾ã‚Œã¦ã„ã¾ã™ã€‚ãれよりå‰ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³
+ã® Linux カーãƒãƒ«ã‚½ãƒ¼ã‚¹ãƒ„リーã«å¯¾ã™ã‚‹ dontdiff ファイルã¯ã€
+<http://www.xenotime.net/linux/doc/dontdiff>ã‹ã‚‰å–å¾—ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+
+投稿ã™ã‚‹ãƒ‘ッãƒã®ä¸­ã«é–¢ä¿‚ã®ãªã„余分ãªãƒ•ã‚¡ã‚¤ãƒ«ãŒå«ã¾ã‚Œã¦ã„ãªã„ã“ã¨ã‚’確
+èªã—ã¦ãã ã•ã„。diff(1) コマンドã§ç”Ÿæˆã—ãŸãƒ‘ッãƒãŒã‚ãªãŸã®æ„図ã—ãŸã¨ãŠ
+ã‚Šã®ã‚‚ã®ã§ã‚ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。
+
+ã‚‚ã—ã‚ãªãŸã®ãƒ‘ッãƒãŒå¤šãã®å·®åˆ†ã‚’生ã¿å‡ºã™ã®ã§ã‚ã‚Œã°ã€ã‚ãªãŸã¯ãƒ‘ッãƒ
+ã‚’æ„味ã®ã‚ã‚‹ã²ã¨ã¾ã¨ã¾ã‚Šã”ã¨ã«åˆ†ã‘ãŸã„ã¨æ€ã†ã‹ã‚‚ã—ã‚Œã¾ã›ã‚“。
+ã“ã‚Œã¯ä»–ã®ã‚«ãƒ¼ãƒãƒ«é–‹ç™ºè€…ã«ã¨ã£ã¦ãƒ¬ãƒ“ューã—ã‚„ã™ããªã‚‹ã®ã§ã€ã‚ãªãŸã®
+パッãƒã‚’å—ã‘入れã¦ã‚‚らã†ãŸã‚ã«ã¯ã¨ã¦ã‚‚é‡è¦ãªã“ã¨ã§ã™ã€‚ã“れを補助ã§ã
+る多ãã®ã‚¹ã‚¯ãƒªãƒ—トãŒã‚ã‚Šã¾ã™ã€‚
+
+Quilt:
+http://savannah.nongnu.org/projects/quilt
+
+Andrew Morton's patch scripts:
+http://www.zip.com.au/~akpm/linux/patches/
+ã“ã®ãƒªãƒ³ã‚¯ã®å…ˆã®ã‚¹ã‚¯ãƒªãƒ—トã®ä»£ã‚ã‚Šã¨ã—ã¦ã€quilt ãŒãƒ‘ッãƒãƒžãƒã‚¸ãƒ¡ãƒ³ãƒˆ
+ツールã¨ã—ã¦æŽ¨å¥¨ã•ã‚Œã¦ã„ã¾ã™(上ã®ãƒªãƒ³ã‚¯ã‚’見ã¦ãã ã•ã„)。
+
+2) パッãƒã«å¯¾ã™ã‚‹èª¬æ˜Ž
+
+パッãƒã®ä¸­ã®å¤‰æ›´ç‚¹ã«å¯¾ã™ã‚‹æŠ€è¡“çš„ãªè©³ç´°ã«ã¤ã„ã¦èª¬æ˜Žã—ã¦ãã ã•ã„。
+
+説明ã¯ã§ãã‚‹é™ã‚Šå…·ä½“çš„ã«ã€‚ã‚‚ã£ã¨ã‚‚悪ã„説明ã¯ã€Œãƒ‰ãƒ©ã‚¤ãƒãƒ¼ X ã‚’æ›´æ–°ã€ã€
+「ドライãƒãƒ¼ X ã«å¯¾ã™ã‚‹ãƒã‚°ãƒ•ã‚£ãƒƒã‚¯ã‚¹ã€ã‚ã‚‹ã„ã¯ã€Œã“ã®ãƒ‘ッãƒã¯ã‚µãƒ–シス
+テム X ã«å¯¾ã™ã‚‹æ›´æ–°ã‚’å«ã‚“ã§ã„ã¾ã™ã€‚ã©ã†ã‹å–り入れã¦ãã ã•ã„。ã€ãªã©ã§ã™ã€‚
+
+説明ãŒé•·ããªã‚Šã ã—ãŸã®ã§ã‚ã‚Œã°ã€ãŠãらããã‚Œã¯ãƒ‘ッãƒã‚’分ã‘ã‚‹å¿…è¦ãŒã‚ã‚‹
+ã¨ã„ã†å…†å€™ã§ã™ã€‚次㮠#3 を見ã¦ãã ã•ã„。
+
+3) パッãƒã®åˆ†å‰²
+
+æ„味ã®ã‚ã‚‹ã²ã¨ã¾ã¨ã¾ã‚Šã”ã¨ã«å¤‰æ›´ã‚’個々ã®ãƒ‘ッãƒãƒ•ã‚¡ã‚¤ãƒ«ã«åˆ†ã‘ã¦ãã ã•ã„。
+
+例ãˆã°ã€ã‚‚ã—1ã¤ã®ãƒ‰ãƒ©ã‚¤ãƒãƒ¼ã«å¯¾ã™ã‚‹ãƒã‚°ãƒ•ã‚£ãƒƒã‚¯ã‚¹ã¨ãƒ‘フォーマンス強
+化ã®ä¸¡æ–¹ã®å¤‰æ›´ã‚’å«ã‚“ã§ã„ã‚‹ã®ã§ã‚ã‚Œã°ã€ãã®å¤‰æ›´ã‚’2ã¤ä»¥ä¸Šã®ãƒ‘ッãƒã«åˆ†
+ã‘ã¦ãã ã•ã„。もã—変更箇所㫠API ã®æ›´æ–°ã¨ã€ãã®æ–°ã—ã„ API を使ã†æ–°ãŸãª
+ドライãƒãƒ¼ãŒå«ã¾ã‚Œã¦ã„ã‚‹ãªã‚‰ã€2ã¤ã®ãƒ‘ッãƒã«åˆ†ã‘ã¦ãã ã•ã„。
+
+一方ã§ã€ã‚‚ã—ã‚ãªãŸãŒå¤šæ•°ã®ãƒ•ã‚¡ã‚¤ãƒ«ã«å¯¾ã—ã¦æ„味的ã«åŒã˜1ã¤ã®å¤‰æ›´ã‚’加ãˆ
+ã‚‹ã®ã§ã‚ã‚Œã°ã€ãã®å¤‰æ›´ã‚’1ã¤ã®ãƒ‘ッãƒã«ã¾ã¨ã‚ã¦ãã ã•ã„。言ã„ã‹ãˆã‚‹ã¨ã€
+æ„味的ã«åŒã˜1ã¤ã®å¤‰æ›´ã¯1ã¤ã®ãƒ‘ッãƒã®ä¸­ã«å«ã¾ã‚Œã¾ã™ã€‚
+
+ã‚るパッãƒãŒå¤‰æ›´ã‚’完çµã•ã›ã‚‹ãŸã‚ã«ä»–ã®ãƒ‘ッãƒã«ä¾å­˜ã—ã¦ã„ãŸã¨ã—ã¦ã‚‚ã€
+ãã‚Œã¯å•é¡Œã‚ã‚Šã¾ã›ã‚“。パッãƒã®èª¬æ˜Žã®ä¸­ã§ã€Œã“ã®ãƒ‘ッãƒã¯ãƒ‘ッムX ã«ä¾å­˜
+ã—ã¦ã„ã‚‹ã€ã¨ç°¡å˜ã«æ³¨æ„書ãã‚’ã¤ã‘ã¦ãã ã•ã„。
+
+ã‚‚ã—パッãƒã‚’よりå°ã•ãªãƒ‘ッãƒã®é›†åˆã«å‡ç¸®ã™ã‚‹ã“ã¨ãŒã§ããªã„ãªã‚‰ã€ã¾ãšã¯
+15ã‹ãã“らã®ãƒ‘ッãƒã‚’é€ã‚Šã€ãã®ãƒ¬ãƒ“ューã¨çµ±åˆã‚’å¾…ã£ã¦ä¸‹ã•ã„。
+
+4) パッãƒã®ã‚¹ã‚¿ã‚¤ãƒ«ãƒã‚§ãƒƒã‚¯
+
+ã‚ãªãŸã®ãƒ‘ッãƒãŒåŸºæœ¬çš„ãª( Linux カーãƒãƒ«ã®)コーディングスタイルã«é•åã—
+ã¦ã„ãªã„ã‹ã‚’ãƒã‚§ãƒƒã‚¯ã—ã¦ä¸‹ã•ã„。ãã®è©³ç´°ã‚’ Documentation/CodingStyle ã§
+見ã¤ã‘ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚コーディングスタイルã®é•åã¯ãƒ¬ãƒ“ューã™ã‚‹äººã®
+時間を無駄ã«ã™ã‚‹ã ã‘ãªã®ã§ã€æらãã‚ãªãŸã®ãƒ‘ッãƒã¯èª­ã¾ã‚Œã‚‹ã“ã¨ã™ã‚‰ãªã
+æ‹’å¦ã•ã‚Œã‚‹ã§ã—ょã†ã€‚
+
+ã‚ãªãŸã¯ãƒ‘ッãƒã‚’投稿ã™ã‚‹å‰ã«æœ€ä½Žé™ãƒ‘ッãƒã‚¹ã‚¿ã‚¤ãƒ«ãƒã‚§ãƒƒã‚«ãƒ¼
+( scripts/patchcheck.pl )を利用ã—ã¦ãƒ‘ッãƒã‚’ãƒã‚§ãƒƒã‚¯ã™ã¹ãã§ã™ã€‚
+ã‚‚ã—パッãƒã«é•åãŒã®ã“ã£ã¦ã„ã‚‹ãªã‚‰ã°ã€ãれらã®å…¨ã¦ã«ã¤ã„ã¦ã‚ãªãŸã¯æ­£å½“ãª
+ç†ç”±ã‚’示ã›ã‚‹ã‚ˆã†ã«ã—ã¦ãŠãå¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+
+5) é›»å­ãƒ¡ãƒ¼ãƒ«ã®å®›å…ˆã®é¸ã³æ–¹
+
+MAINTAINERS ファイルã¨ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã«ç›®ã‚’通ã—ã¦ãã ã•ã„。ãã—ã¦ã€ãã®å¤‰
+æ›´ãŒãƒ¡ãƒ³ãƒ†ãƒŠã®ã„る特定ã®ã‚µãƒ–システムã«åŠ ãˆã‚‰ã‚Œã‚‹ã‚‚ã®ã§ã‚ã‚‹ã“ã¨ãŒåˆ†ã‹
+ã‚Œã°ã€ãã®äººã«é›»å­ãƒ¡ãƒ¼ãƒ«ã‚’é€ã£ã¦ãã ã•ã„。
+
+ã‚‚ã—ã€ãƒ¡ãƒ³ãƒ†ãƒŠãŒè¼‰ã£ã¦ã„ãªã‹ã£ãŸã‚Šã€ãƒ¡ãƒ³ãƒ†ãƒŠã‹ã‚‰ã®å¿œç­”ãŒãªã„ãªã‚‰ã€
+LKML ( linux-kernel@vger.kernel.org )ã¸ãƒ‘ッãƒã‚’é€ã£ã¦ãã ã•ã„。ã»ã¨ã‚“ã©
+ã®ã‚«ãƒ¼ãƒãƒ«é–‹ç™ºè€…ã¯ã“ã®ãƒ¡ãƒ¼ãƒªãƒ³ã‚°ãƒªã‚¹ãƒˆã«ç›®ã‚’通ã—ã¦ãŠã‚Šã€å¤‰æ›´ã«å¯¾ã—ã¦
+コメントを得るã“ã¨ãŒã§ãã¾ã™ã€‚
+
+15個より多ãã®ãƒ‘ッãƒã‚’åŒæ™‚ã« vger.kernel.org ã®ãƒ¡ãƒ¼ãƒªãƒ³ã‚°ãƒªã‚¹ãƒˆã¸é€ã‚‰ãª
+ã„ã§ãã ã•ã„!!!
+
+Linus Torvalds 㯠Linux カーãƒãƒ«ã«å…¥ã‚‹å…¨ã¦ã®å¤‰æ›´ã«å¯¾ã™ã‚‹æœ€çµ‚çš„ãªæ„æ€æ±ºå®šè€…
+ã§ã™ã€‚é›»å­ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã¯ torvalds@linux-foundation.org ã«ãªã‚Šã¾ã™ã€‚å½¼ã¯
+多ãã®é›»å­ãƒ¡ãƒ¼ãƒ«ã‚’å—ã‘å–ã£ã¦ã„ã‚‹ãŸã‚ã€ã§ãã‚‹é™ã‚Šå½¼ã«é›»å­ãƒ¡ãƒ¼ãƒ«ã‚’é€ã‚‹ã®ã¯
+é¿ã‘ã‚‹ã¹ãã§ã™ã€‚
+
+ãƒã‚°ãƒ•ã‚£ãƒƒã‚¯ã‚¹ã§ã‚ã£ãŸã‚Šã€è‡ªæ˜Žãªå¤‰æ›´ã§ã‚ã£ãŸã‚Šã€è©±ã—åˆã„ã‚’ã»ã¨ã‚“ã©
+å¿…è¦ã¨ã—ãªã„パッãƒã¯ Linus ã¸é›»å­ãƒ¡ãƒ¼ãƒ«ã‚’é€ã‚‹ã‹ CC ã—ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。
+話ã—åˆã„ã‚’å¿…è¦ã¨ã—ãŸã‚Šã€æ˜Žç¢ºãªã‚¢ãƒ‰ãƒãƒ³ãƒ†ãƒ¼ã‚¸ãŒãªã„パッãƒã¯ã€é€šå¸¸ã¾ãš
+㯠LKML ã¸é€ã‚‰ã‚Œã‚‹ã¹ãã§ã™ã€‚パッãƒãŒè­°è«–ã•ã‚ŒãŸå¾Œã«ã ã‘ã€ãã®ãƒ‘ッãƒã‚’
+Linus ã¸é€ã‚‹ã¹ãã§ã™ã€‚
+
+6) CC (カーボンコピー)å…ˆã®é¸ã³æ–¹
+
+特ã«ç†ç”±ãŒãªã„ãªã‚‰ã€LKML ã«ã‚‚ CC ã—ã¦ãã ã•ã„。
+
+Linus 以外ã®ã‚«ãƒ¼ãƒãƒ«é–‹ç™ºè€…ã¯å¤‰æ›´ã«æ°—ã¥ãå¿…è¦ãŒã‚ã‚Šã€ãã®çµæžœã€å½¼ã‚‰ã¯ã
+ã®å¤‰æ›´ã«å¯¾ã—ã¦ã‚³ãƒ¡ãƒ³ãƒˆã‚’ãã‚ŒãŸã‚Šã€ã‚³ãƒ¼ãƒ‰ã«å¯¾ã—ã¦ãƒ¬ãƒ“ューやæ案をãã‚Œ
+ã‚‹ã‹ã‚‚ã—ã‚Œã¾ã›ã‚“。LKML ã¨ã¯ Linux カーãƒãƒ«é–‹ç™ºè€…ã«ã¨ã£ã¦ä¸€ç•ªä¸­å¿ƒçš„ãªãƒ¡ãƒ¼
+リングリストã§ã™ã€‚USB やフレームãƒãƒƒãƒ•ã‚¡ãƒ‡ãƒã‚¤ã‚¹ã‚„ VFS ã‚„ SCSI サブシステ
+ムãªã©ã®ç‰¹å®šã®ã‚µãƒ–システムã«é–¢ã™ã‚‹ãƒ¡ãƒ¼ãƒªãƒ³ã‚°ãƒªã‚¹ãƒˆã‚‚ã‚ã‚Šã¾ã™ã€‚ã‚ãªãŸ
+ã®å¤‰æ›´ã«ã€ã¯ã£ãã‚Šã¨é–¢é€£ã®ã‚るメーリングリストã«ã¤ã„ã¦çŸ¥ã‚ŠãŸã‘ã‚Œã°
+MAINTAINERS ファイルをå‚ç…§ã—ã¦ãã ã•ã„。
+
+VGER.KERNEL.ORG ã§ãƒ›ã‚¹ãƒ†ã‚£ãƒ³ã‚°ã•ã‚Œã¦ã„るメーリングリストã®ä¸€è¦§ãŒä¸‹è¨˜ã®
+サイトã«è¼‰ã£ã¦ã„ã¾ã™ã€‚
+<http://vger.kernel.org/vger-lists.html>
+
+ã‚‚ã—ã€å¤‰æ›´ãŒãƒ¦ãƒ¼ã‚¶ãƒ©ãƒ³ãƒ‰ã®ã‚«ãƒ¼ãƒãƒ«ã‚¤ãƒ³ã‚¿ãƒ•ã‚§ãƒ¼ã‚¹ã«å½±éŸ¿ã‚’与ãˆ
+ã‚‹ã®ã§ã‚ã‚Œã°ã€MAN-PAGES ã®ãƒ¡ãƒ³ãƒ†ãƒŠ( MAINTAINERS ファイルã«ä¸€è¦§
+ãŒã‚ã‚Šã¾ã™)ã« man ページã®ãƒ‘ッãƒã‚’é€ã£ã¦ãã ã•ã„。少ãªãã¨ã‚‚
+情報ãŒãƒžãƒ‹ãƒ¥ã‚¢ãƒ«ãƒšãƒ¼ã‚¸ã®ä¸­ã«å…¥ã£ã¦ãるよã†ã«ã€å¤‰æ›´ãŒèµ·ããŸã¨ã„ã†
+通知をé€ã£ã¦ãã ã•ã„。
+
+ãŸã¨ãˆã€ãƒ¡ãƒ³ãƒ†ãƒŠãŒ #4 ã§åå¿œãŒãªã‹ã£ãŸã¨ã—ã¦ã‚‚ã€ãƒ¡ãƒ³ãƒ†ãƒŠã®ã‚³ãƒ¼ãƒ‰ã«å¤‰æ›´ã‚’
+加ãˆãŸã¨ãã«ã¯ã€ã„ã¤ã‚‚メンテナ㫠CC ã™ã‚‹ã®ã‚’忘れãªã„よã†ã«ã—ã¦ãã ã•ã„。
+
+å°ã•ãªãƒ‘ッãƒã§ã‚ã‚Œã°ã€Adrian Bunk ãŒç®¡ç†ã—ã¦ã„ã‚‹ Trivial Patch Monkey
+(ã¡ã‚‡ã£ã¨ã—ãŸãƒ‘ッãƒã‚’集ã‚ã¦ã„ã‚‹)<trivial@kernel.org>ã« CC ã—ã¦ã‚‚ã„ã„
+ã§ã™ã€‚ã¡ã‚‡ã£ã¨ã—ãŸãƒ‘ッãƒã¨ã¯ä»¥ä¸‹ã®ãƒ«ãƒ¼ãƒ«ã®ã©ã‚Œã‹1ã¤ã‚’満ãŸã—ã¦ã„ãªã‘
+ã‚Œã°ãªã‚Šã¾ã›ã‚“。
+ ・ドキュメントã®ã‚¹ãƒšãƒ«ãƒŸã‚¹ã®ä¿®æ­£
+ ・grep(1) コマンドã«ã‚ˆã‚‹æ¤œç´¢ã‚’困難ã«ã—ã¦ã„るスペルã®ä¿®æ­£
+ ・コンパイル時ã®è­¦å‘Šã®ä¿®æ­£(無駄ãªè­¦å‘ŠãŒæ•£ä¹±ã™ã‚‹ã“ã¨ã¯å¥½ã¾ã—ããªã„ãŸ
+ ã‚ã§ã™)
+ ・コンパイルå•é¡Œã®ä¿®æ­£(ãれらã®ä¿®æ­£ãŒæœ¬å½“ã«æ­£ã—ã„å ´åˆã«é™ã‚‹)
+ ・実行時ã®å•é¡Œã®ä¿®æ­£(ãれらã®ä¿®æ­£ãŒæœ¬å½“ã«å•é¡Œã‚’修正ã—ã¦ã„ã‚‹å ´åˆã«é™ã‚‹)
+ ・廃止予定ã®é–¢æ•°ã‚„マクロを使用ã—ã¦ã„るコードã®é™¤åŽ»(例 check_region )
+ ・å•ã„åˆã‚ã›å…ˆã‚„ドキュメントã®ä¿®æ­£
+ ・移æ¤æ€§ã®ãªã„コードã‹ã‚‰ç§»æ¤æ€§ã®ã‚るコードã¸ã®ç½®ãæ›ãˆ(å°ã•ã„範囲ã§
+ ã‚ã‚Œã°ã‚¢ãƒ¼ã‚­ãƒ†ã‚¯ãƒãƒ£ç‰¹æœ‰ã®ã“ã¨ã§ã‚‚ä»–ã®äººãŒã‚³ãƒ”ーã§ãã¾ã™)
+ ・作者やメンテナã«ã‚ˆã‚‹ä¿®æ­£(ã™ãªã‚ã¡ patch monkey ã®å†è»¢é€ãƒ¢ãƒ¼ãƒ‰)
+URL: <http://www.kernel.org/pub/linux/kernel/people/bunk/trivial/>
+
+7) MIME やリンクや圧縮ファイルや添付ファイルã§ã¯ãªãプレインテキストã®ã¿
+
+Linus ã‚„ä»–ã®ã‚«ãƒ¼ãƒãƒ«é–‹ç™ºè€…ã¯ã‚ãªãŸãŒæŠ•ç¨¿ã—ãŸå¤‰æ›´ã‚’読んã§ã€ã‚³ãƒ¡ãƒ³ãƒˆã§ã
+ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚カーãƒãƒ«é–‹ç™ºè€…ã«ã¨ã£ã¦ã€ã‚ãªãŸãŒæ›¸ã„ãŸã‚³ãƒ¼ãƒ‰ã®ç‰¹å®šã®
+部分ã«ã‚³ãƒ¡ãƒ³ãƒˆã‚’ã™ã‚‹ãŸã‚ã«ã€æ¨™æº–çš„ãªé›»å­ãƒ¡ãƒ¼ãƒ«ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã§å¤‰æ›´ãŒå¼•ç”¨
+ã§ãã‚‹ã“ã¨ã¯é‡è¦ã§ã™ã€‚
+
+上記ã®ç†ç”±ã§ã€ã™ã¹ã¦ã®ãƒ‘ッãƒã¯æ–‡ä¸­ã«å«ã‚ã‚‹å½¢å¼ã®é›»å­ãƒ¡ãƒ¼ãƒ«ã§æŠ•ç¨¿ã•
+れるã¹ãã§ã™ã€‚警告:ã‚ãªãŸãŒãƒ‘ッãƒã‚’コピー&ペーストã™ã‚‹éš›ã«ã¯ã€ãƒ‘ッ
+ãƒã‚’改悪ã™ã‚‹ã‚¨ãƒ‡ã‚£ã‚¿ãƒ¼ã®æŠ˜ã‚Šè¿”ã—機能ã«æ³¨æ„ã—ã¦ãã ã•ã„。
+
+パッãƒã‚’圧縮ã®æœ‰ç„¡ã«é–¢ã‚ら㚠MIME å½¢å¼ã§æ·»ä»˜ã—ãªã„ã§ãã ã•ã„。多ãã®ãƒ
+ピュラーãªé›»å­ãƒ¡ãƒ¼ãƒ«ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã¯ MIME å½¢å¼ã®æ·»ä»˜ãƒ•ã‚¡ã‚¤ãƒ«ã‚’プレーンテ
+キストã¨ã—ã¦é€ä¿¡ã™ã‚‹ã¨ã¯é™ã‚‰ãªã„ã§ã—ょã†ã€‚ãã†ãªã‚‹ã¨ã€é›»å­ãƒ¡ãƒ¼ãƒ«ã‚¯ãƒ©
+イアントãŒã‚³ãƒ¼ãƒ‰ã«å¯¾ã™ã‚‹ã‚³ãƒ¡ãƒ³ãƒˆã‚’付ã‘ã‚‹ã“ã¨ã‚’ã§ããªãã—ã¾ã™ã€‚ã¾ãŸã€
+MIME å½¢å¼ã®æ·»ä»˜ãƒ•ã‚¡ã‚¤ãƒ«ã¯ Linus ã«æ‰‹é–“ã‚’å–らã›ã‚‹ã“ã¨ã«ãªã‚Šã€ãã®å¤‰æ›´ã‚’
+å—ã‘入れã¦ã‚‚らã†å¯èƒ½æ€§ãŒä½Žããªã£ã¦ã—ã¾ã„ã¾ã™ã€‚
+
+例外:ãŠä½¿ã„ã®é›»å­ãƒ¡ãƒ¼ãƒ«ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆãŒãƒ‘ッãƒã‚’ã‚ã¡ã‚ƒãã¡ã‚ƒã«ã™ã‚‹ã®ã§
+ã‚ã‚Œã°ã€èª°ã‹ãŒ MIME å½¢å¼ã®ãƒ‘ッãƒã‚’å†é€ã™ã‚‹ã‚ˆã†æ±‚ã‚ã‚‹ã‹ã‚‚ã—ã‚Œã¾ã›ã‚“。
+
+警告: Mozilla ã®ã‚ˆã†ãªç‰¹å®šã®é›»å­ãƒ¡ãƒ¼ãƒ«ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã¯é›»å­ãƒ¡ãƒ¼ãƒ«ã®
+ヘッダã«ä»¥ä¸‹ã®ã‚‚ã®ã‚’付加ã—ã¦é€ã‚Šã¾ã™ã€‚
+---- message header ----
+Content-Type: text/plain; charset=us-ascii; format=flowed
+---- message header ----
+å•é¡Œã¯ã€ã€Œ format=flowed ã€ãŒä»˜ã„ãŸé›»å­ãƒ¡ãƒ¼ãƒ«ã‚’特定ã®å—ä¿¡å´ã®é›»å­ãƒ¡ãƒ¼ãƒ«
+クライアントãŒã‚¿ãƒ–をスペースã«ç½®ãæ›ãˆã‚‹ã¨ã„ã†ã‚ˆã†ãªå¤‰æ›´ã‚’ã™ã‚‹ã“ã¨ã§ã™ã€‚
+ã—ãŸãŒã£ã¦é€ã‚‰ã‚Œã¦ããŸãƒ‘ッãƒã¯å£Šã‚Œã¦ã„るよã†ã«è¦‹ãˆã‚‹ã§ã—ょã†ã€‚
+
+ã“れを修正ã™ã‚‹ã«ã¯ã€mozilla ã® defaults/pref/mailnews.js ファイルを
+以下ã®ã‚ˆã†ã«ä¿®æ­£ã—ã¾ã™ã€‚
+pref("mailnews.send_plaintext_flowed", false); // RFC 2646=======
+pref("mailnews.display.disable_format_flowed_support", true);
+
+8) é›»å­ãƒ¡ãƒ¼ãƒ«ã®ã‚µã‚¤ã‚º
+
+パッãƒã‚’ Linus ã¸é€ã‚‹ã¨ãã¯å¸¸ã« #7 ã®æ‰‹é †ã«å¾“ã£ã¦ãã ã•ã„。
+
+大ããªãƒ‘ッãƒã¯ãƒ¡ãƒ¼ãƒªãƒ³ã‚°ãƒªã‚¹ãƒˆã‚„メンテナã«ã¨ã£ã¦ä¸è¦ªåˆ‡ã§ã™ã€‚パッãƒãŒ
+未圧縮㧠40KB を超ãˆã‚‹ã‚ˆã†ã§ã‚ã‚‹ãªã‚‰ã€ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆä¸Šã®ã‚¢ã‚¯ã‚»ã‚¹å¯èƒ½ãª
+サーãƒã«ä¿å­˜ã—ã€ä¿å­˜å ´æ‰€ã‚’示㙠URL ã‚’ä¼ãˆã‚‹ã»ã†ãŒé©åˆ‡ã§ã™ã€‚
+
+9) カーãƒãƒ«ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®æ˜Žè¨˜
+
+パッãƒãŒå¯¾è±¡ã¨ã™ã‚‹ã‚«ãƒ¼ãƒãƒ«ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’パッãƒã®æ¦‚è¦ã‹é›»å­ãƒ¡ãƒ¼ãƒ«ã®
+サブジェクトã«ä»˜ã‘ã‚‹ã“ã¨ãŒé‡è¦ã§ã™ã€‚
+
+パッãƒãŒæœ€æ–°ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®ã‚«ãƒ¼ãƒãƒ«ã«æ­£ã—ãé©ç”¨ã§ããªã‘ã‚Œã°ã€Linus ã¯
+ãã®ãƒ‘ッãƒã‚’採用ã—ãªã„ã§ã—ょã†ã€‚
+
+10) ãŒã£ã‹ã‚Šã›ãšå†æŠ•ç¨¿
+
+パッãƒã‚’投稿ã—ãŸå¾Œã¯ã€è¾›æŠ±å¼·ãå¾…ã£ã¦ã„ã¦ãã ã•ã„。Linus ãŒã‚ãªãŸã®ãƒ‘ッ
+ãƒã‚’æ°—ã«å…¥ã£ã¦æŽ¡ç”¨ã™ã‚Œã°ã€Linus ãŒãƒªãƒªãƒ¼ã‚¹ã™ã‚‹æ¬¡ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®ã‚«ãƒ¼ãƒãƒ«
+ã®ä¸­ã§å§¿ã‚’見ã›ã‚‹ã§ã—ょã†ã€‚
+
+ã—ã‹ã—ã€ãƒ‘ッãƒãŒæ¬¡ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®ã‚«ãƒ¼ãƒãƒ«ã«å…¥ã£ã¦ã„ãªã„ãªã‚‰ã€ã„ãã¤ã‚‚ã®
+ç†ç”±ãŒã‚ã‚‹ã®ã§ã—ょã†ã€‚ãã®åŽŸå› ã‚’絞り込ã¿ã€é–“é•ã£ã¦ã„ã‚‹ã‚‚ã®ã‚’æ­£ã—ã€æ›´æ–°
+ã—ãŸãƒ‘ッãƒã‚’投稿ã™ã‚‹ã®ã¯ã‚ãªãŸã®ä»•äº‹ã§ã™ã€‚
+
+Linus ãŒã‚ãªãŸã®ãƒ‘ッãƒã«å¯¾ã—ã¦ä½•ã®ã‚³ãƒ¡ãƒ³ãƒˆã‚‚ãªãä¸æŽ¡ç”¨ã«ã™ã‚‹ã“ã¨ã¯æ¥µã‚
+ã¦æ™®é€šã®ã“ã¨ã§ã™ã€‚ãã‚Œã¯è‡ªç„¶ãªå§¿ã§ã™ã€‚ã‚‚ã—ã€Linus ãŒã‚ãªãŸã®ãƒ‘ッãƒã‚’å—
+ã‘å–ã£ã¦ã„ãªã„ã®ã§ã‚ã‚Œã°ã€ä»¥ä¸‹ã®ç†ç”±ãŒè€ƒãˆã‚‰ã‚Œã¾ã™ã€‚
+* パッãƒãŒæœ€æ–°ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã® Linux カーãƒãƒ«ã«ãã¡ã‚“ã¨é©ç”¨ã§ããªã‹ã£ãŸ
+* パッãƒãŒ LKML ã§å分ã«è­°è«–ã•ã‚Œã¦ã„ãªã‹ã£ãŸ
+* スタイルã®å•é¡Œ(セクション2ã‚’å‚ç…§)
+* é›»å­ãƒ¡ãƒ¼ãƒ«ãƒ•ã‚©ãƒ¼ãƒžãƒƒãƒˆã®å•é¡Œ(ã“ã®ã‚»ã‚¯ã‚·ãƒ§ãƒ³ã‚’å‚ç…§)
+* パッãƒã«å¯¾ã™ã‚‹æŠ€è¡“çš„ãªå•é¡Œ
+* Linus ã¯ãŸãã•ã‚“ã®é›»å­ãƒ¡ãƒ¼ãƒ«ã‚’å—ã‘å–ã£ã¦ã„ã‚‹ã®ã§ã€ã©ã•ãã•ã«ç´›ã‚Œã¦è¦‹
+ 失ã£ãŸ
+* ä¸æ„‰å¿«ã«ã•ã›ã¦ã„ã‚‹
+
+判断ã§ããªã„å ´åˆã¯ã€LKML ã«ã‚³ãƒ¡ãƒ³ãƒˆã‚’頼んã§ãã ã•ã„。
+
+11) サブジェクトã«ã€Œ PATCH ã€
+
+Linus ã‚„ LKML ã¸ã®å¤§é‡ã®é›»å­ãƒ¡ãƒ¼ãƒ«ã®ãŸã‚ã«ã€ã‚µãƒ–ジェクトã®ãƒ—レフィックスã«
+「 [PATCH] ã€ã‚’付ã‘ã‚‹ã“ã¨ãŒæ…£ç¿’ã¨ãªã£ã¦ã„ã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã£ã¦ Linus ã‚„ä»–ã®
+カーãƒãƒ«é–‹ç™ºè€…ãŒãƒ‘ッãƒã§ã‚ã‚‹ã®ã‹ã€åˆã¯ã€ä»–ã®è­°è«–ã«é–¢ã™ã‚‹é›»å­ãƒ¡ãƒ¼ãƒ«ã§ã‚ã‚‹ã®
+ã‹ã‚’より簡å˜ã«è­˜åˆ¥ã§ãã¾ã™ã€‚
+
+12) パッãƒã¸ã®ç½²å
+
+誰ãŒä½•ã‚’ã—ãŸã®ã‹ã‚’追ã„ã‹ã‘ã‚„ã™ãã™ã‚‹ãŸã‚ã« (特ã«ã€ãƒ‘ッãƒãŒä½•äººã‹ã®
+メンテナを経ã¦æœ€çµ‚çš„ã« Linux カーãƒãƒ«ã«å–ã‚Šè¾¼ã¾ã‚Œã‚‹å ´åˆã®ãŸã‚ã«)ã€é›»å­
+メールã§ã‚„ã‚Šå–ã‚Šã•ã‚Œã‚‹ãƒ‘ッãƒã«å¯¾ã—ã¦ã€Œ sign-off ã€ã¨ã„ã†æ‰‹ç¶šãã‚’å°Žå…¥ã—
+ã¾ã—ãŸã€‚
+
+「 sign-off ã€ã¨ã¯ã€ãƒ‘ッãƒãŒã‚ãªãŸã®æ›¸ã„ãŸã‚‚ã®ã§ã‚ã‚‹ã‹ã€ã‚ã‚‹ã„ã¯ã€
+ã‚ãªãŸãŒãã®ãƒ‘ッãƒã‚’オープンソースã¨ã—ã¦æä¾›ã™ã‚‹æ¨©åˆ©ã‚’ä¿æŒã—ã¦ã„ã‚‹ã€
+ã¨ã„ã†è¨¼æ˜Žã‚’パッãƒã®èª¬æ˜Žã®æœ«å°¾ã«ä¸€è¡Œè¨˜è¼‰ã™ã‚‹ã¨ã„ã†ã‚‚ã®ã§ã™ã€‚
+ルールã¯ã¨ã¦ã‚‚å˜ç´”ã§ã™ã€‚以下ã®é …目を確èªã—ã¦ä¸‹ã•ã„。
+
+ 原作者ã®è¨¼æ˜Žæ›¸( DCO ) 1.1
+
+ ã“ã®ãƒ—ロジェクトã«å¯„与ã™ã‚‹ã‚‚ã®ã¨ã—ã¦ã€ä»¥ä¸‹ã®ã“ã¨ã‚’証明ã™ã‚‹ã€‚
+
+ (a) 本寄与ã¯ç§ãŒå…¨ä½“åˆã¯ä¸€éƒ¨ä½œæˆã—ãŸã‚‚ã®ã§ã‚ã‚Šã€ç§ãŒãã®ãƒ•ã‚¡ã‚¤
+ ル中ã«æ˜Žç¤ºã•ã‚ŒãŸã‚ªãƒ¼ãƒ—ンソースライセンスã®ä¸‹ã§å…¬é–‹ã™ã‚‹æ¨©åˆ©
+ ã‚’æŒã£ã¦ã„る。もã—ãã¯ã€
+
+ (b) 本寄与ã¯ã€ç§ãŒçŸ¥ã‚‹é™ã‚Šã€é©åˆ‡ãªã‚ªãƒ¼ãƒ—ンソースライセンスã§ã‚«ãƒ
+ ーã•ã‚Œã¦ã„る既存ã®ä½œå“ã‚’å…ƒã«ã—ã¦ã„る。åŒæ™‚ã«ã€ç§ã¯ãã®ãƒ©ã‚¤ã‚»
+ ンスã®ä¸‹ã§ã€ç§ãŒå…¨ä½“åˆã¯ä¸€éƒ¨ä½œæˆã—ãŸä¿®æ­£ç‰©ã‚’ã€ãƒ•ã‚¡ã‚¤ãƒ«ä¸­ã§ç¤º
+ ã•ã‚Œã‚‹åŒä¸€ã®ã‚ªãƒ¼ãƒ—ンソースライセンスã§(ç•°ãªã‚‹ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã®ä¸‹ã§
+ 投稿ã™ã‚‹ã“ã¨ãŒè¨±å¯ã•ã‚Œã¦ã„ã‚‹å ´åˆã‚’除ã„ã¦)投稿ã™ã‚‹æ¨©åˆ©ã‚’æŒã£ã¦
+ ã„る。もã—ãã¯ã€
+
+ (c) 本寄与ã¯(a)ã€(b)ã€(c)を証明ã™ã‚‹ç¬¬3者ã‹ã‚‰ç§ã¸ç›´æŽ¥æä¾›ã•ã‚ŒãŸ
+ ã‚‚ã®ã§ã‚ã‚Šã€ç§ã¯ãã‚Œã«å¤‰æ›´ã‚’加ãˆã¦ã„ãªã„。
+
+ (d) ç§ã¯ã“ã®ãƒ—ロジェクトã¨æœ¬å¯„与ãŒå…¬ã®ã‚‚ã®ã§ã‚ã‚‹ã“ã¨ã«ç†è§£åŠã³åŒæ„ã™
+ る。åŒæ™‚ã«ã€é–¢ä¸Žã—ãŸè¨˜éŒ²(投稿ã®éš›ã®å…¨ã¦ã®å€‹äººæƒ…報㨠sign-off ã‚’
+ å«ã‚€)ãŒç„¡æœŸé™ã«ä¿å…¨ã•ã‚Œã‚‹ã“ã¨ã¨ã€å½“該プロジェクトåˆã¯é–¢é€£ã™ã‚‹
+ オープンソースライセンスã«æ²¿ã£ãŸå½¢ã§å†é…布ã•ã‚Œã‚‹ã“ã¨ã«ç†è§£åŠã³
+ åŒæ„ã™ã‚‹ã€‚
+
+ã‚‚ã—ã“ã‚Œã«åŒæ„ã§ãã‚‹ãªã‚‰ã€ä»¥ä¸‹ã®ã‚ˆã†ãª1行を追加ã—ã¦ãã ã•ã„。
+
+ Signed-off-by: Random J Developer <random@developer.example.org>
+
+実åを使ã£ã¦ãã ã•ã„。(残念ã§ã™ãŒã€å½åや匿åã«ã‚ˆã‚‹å¯„与ã¯ã§ãã¾ã›ã‚“。)
+
+人ã«ã‚ˆã£ã¦ã¯ sign-off ã®è¿‘ãã«è¿½åŠ ã®ã‚¿ã‚°ã‚’付加ã—ã¦ã„ã¾ã™ã€‚ãれらã¯ä»Šã®ã¨ã“ã‚
+無視ã•ã‚Œã¾ã™ãŒã€ã‚ãªãŸã¯ãã®ã‚¿ã‚°ã‚’社内ã®æ‰‹ç¶šãã«åˆ©ç”¨ã—ãŸã‚Šã€sign-off ã«ç‰¹åˆ¥
+ãªæƒ…報を示ã—ãŸã‚Šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+
+13) ã„㤠Acked-by: を使ã†ã®ã‹
+
+「 Signed-off-by: ã€ã‚¿ã‚°ã¯ãã®ç½²å者ãŒãƒ‘ッãƒã®é–‹ç™ºã«é–¢ã‚ã£ã¦ã„ãŸã“ã¨ã‚„パッãƒ
+ã®ä¼æ’­ãƒ‘スã«ã„ãŸã“ã¨ã‚’示ã—ã¦ã„ã¾ã™ã€‚
+
+ã‚る人ãŒç›´æŽ¥ãƒ‘ッãƒã®æº–備や作æˆã«é–¢ã‚ã£ã¦ã„ãªã„ã‘ã‚Œã©ã€ãã®äººã®ãƒ‘ッãƒã«å¯¾ã™
+る承èªã‚’記録ã—ã€ç¤ºã—ãŸã„ã¨ã—ã¾ã™ã€‚ãã®å ´åˆã€ãã®äººã‚’示ã™ã®ã« Acked-by: ãŒä½¿
+ãˆã¾ã™ã€‚Acked-by: ã¯ãƒ‘ッãƒã®ãƒã‚§ãƒ³ã‚¸ãƒ­ã‚°ã«ã‚‚追加ã•ã‚Œã¾ã™ã€‚
+
+パッãƒã®å½±éŸ¿ã‚’å—ã‘るコードã®ãƒ¡ãƒ³ãƒ†ãƒŠãŒãƒ‘ッãƒã«é–¢ã‚ã£ã¦ã„ãªã‹ã£ãŸã‚Šã€ãƒ‘ッãƒ
+ã®ä¼æ’­ãƒ‘スã«ã„ãªã‹ã£ãŸæ™‚ã«ã‚‚ã€ãƒ¡ãƒ³ãƒ†ãƒŠã¯ Acked-by: ã‚’ã—ã°ã—ã°åˆ©ç”¨ã—ã¾ã™ã€‚
+
+Acked-by: 㯠Signed-off-by: ã®ã‚ˆã†ã«å…¬å¼ãªã‚¿ã‚°ã§ã¯ã‚ã‚Šã¾ã›ã‚“。ãã‚Œã¯ãƒ¡ãƒ³ãƒ†ãƒŠãŒ
+å°‘ãªãã¨ã‚‚パッãƒã‚’レビューã—ã€åŒæ„を示ã—ã¦ã„ã‚‹ã¨ã„ã†è¨˜éŒ²ã§ã™ã€‚ãã®ã‚ˆã†ãª
+ã“ã¨ã‹ã‚‰ãƒ‘ッãƒã®çµ±åˆè€…ãŒãƒ¡ãƒ³ãƒ†ãƒŠã®ã€Œã†ã‚“ã€è‰¯ã„ã¨æ€ã†ã‚ˆã€ã¨ã„ã†ç™ºè¨€ã‚’
+Acked-by: ã¸ç½®ãæ›ãˆã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚
+
+Acked-by: ãŒå¿…ãšã—もパッãƒå…¨ä½“ã®æ‰¿èªã‚’示ã—ã¦ã„ã‚‹ã‚ã‘ã§ã¯ã‚ã‚Šã¾ã›ã‚“。例ãˆã°ã€
+ã‚るパッãƒãŒè¤‡æ•°ã®ã‚µãƒ–システムã¸å½±éŸ¿ã‚’与ãˆã¦ãŠã‚Šã€ãã®ä¸­ã®1ã¤ã®ã‚µãƒ–システム
+ã®ãƒ¡ãƒ³ãƒ†ãƒŠã‹ã‚‰ã® Acked-by: ã‚’æŒã£ã¦ã„ã‚‹ã¨ã—ã¾ã™ã€‚ãã®å ´åˆã€Acked-by: ã¯é€šå¸¸
+ãã®ãƒ¡ãƒ³ãƒ†ãƒŠã®ã‚³ãƒ¼ãƒ‰ã«å½±éŸ¿ã‚’与ãˆã‚‹ä¸€éƒ¨åˆ†ã ã‘ã«å¯¾ã™ã‚‹æ‰¿èªã‚’示ã—ã¦ã„ã¾ã™ã€‚
+ã“ã®ç‚¹ã¯ã€ã”自分ã§åˆ¤æ–­ã—ã¦ãã ã•ã„。(ãã® Acked-by: ãŒ)ç–‘ã‚ã—ã„å ´åˆã¯ã€
+メーリングリストアーカイブã®ä¸­ã®å¤§å…ƒã®è­°è«–ã‚’å‚ç…§ã™ã¹ãã§ã™ã€‚
+
+14) 標準的ãªãƒ‘ッãƒã®ãƒ•ã‚©ãƒ¼ãƒžãƒƒãƒˆ
+
+標準的ãªãƒ‘ッãƒã®ã‚µãƒ–ジェクトã¯ä»¥ä¸‹ã®ã¨ãŠã‚Šã§ã™ã€‚
+
+ Subject: [PATCH 001/123] subsystem: summary phrase
+
+標準的ãªãƒ‘ッãƒã®ã€é›»å­ãƒ¡ãƒ¼ãƒ«ã®ãƒœãƒ‡ã‚£ã¯ä»¥ä¸‹ã®é …目をå«ã‚“ã§ã„ã¾ã™ã€‚
+
+ - パッãƒã®ä½œæˆè€…を明記ã™ã‚‹ã€Œ from ã€è¡Œ
+
+ - 空行
+
+ - 説明本体。ã“ã‚Œã¯ã“ã®ãƒ‘ッãƒã‚’説明ã™ã‚‹ãŸã‚ã«ç„¡æœŸé™ã®ãƒã‚§ãƒ³ã‚¸ãƒ­ã‚°
+ (変更履歴)ã«ã‚³ãƒ”ーã•ã‚Œã¾ã™ã€‚
+
+ - 上述ã—ãŸã€Œ Signed-off-by: ã€è¡Œã€‚ã“れも説明本体ã¨åŒã˜ããƒã‚§ãƒ³
+ ジログ内ã«ã‚³ãƒ”ーã•ã‚Œã¾ã™ã€‚
+
+ - マーカー行ã¯å˜ç´”ã«ã€Œ --- ã€ã§ã™ã€‚
+
+ - 余計ãªã‚³ãƒ¡ãƒ³ãƒˆã¯ã€ãƒã‚§ãƒ³ã‚¸ãƒ­ã‚°ã«ã¯ä¸é©åˆ‡ã§ã™ã€‚
+
+ - 実際ã®ãƒ‘ッãƒ(差分出力)
+
+サブジェクト行ã®ãƒ•ã‚©ãƒ¼ãƒžãƒƒãƒˆã¯ã€ã‚¢ãƒ«ãƒ•ã‚¡ãƒ™ãƒƒãƒˆé †ã§é›»å­ãƒ¡ãƒ¼ãƒ«ã‚’ã¨ã¦ã‚‚
+ソートã—ã‚„ã™ã„ã‚‚ã®ã«ãªã£ã¦ã„ã¾ã™ã€‚(ã»ã¨ã‚“ã©ã®é›»å­ãƒ¡ãƒ¼ãƒ«ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆ
+ã¯ã‚½ãƒ¼ãƒˆã‚’サãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã™)パッãƒã®ã‚µãƒ–ジェクトã®é€£ç•ªã¯0è©°ã‚ã§ã‚
+ã‚‹ãŸã‚ã€æ•°å­—ã§ã®ã‚½ãƒ¼ãƒˆã¨ã‚¢ãƒ«ãƒ•ã‚¡ãƒ™ãƒƒãƒˆã§ã®ã‚½ãƒ¼ãƒˆã¯åŒã˜çµæžœã«ãªã‚Šã¾ã™ã€‚
+
+é›»å­ãƒ¡ãƒ¼ãƒ«ã®ã‚µãƒ–ジェクト内ã®ã‚µãƒ–システム表記ã¯ã€ãƒ‘ッãƒãŒé©ç”¨ã•ã‚Œã‚‹
+分野ã¾ãŸã¯ã‚µãƒ–システムを識別ã§ãるよã†ã«ã™ã¹ãã§ã™ã€‚
+
+é›»å­ãƒ¡ãƒ¼ãƒ«ã®ã‚µãƒ–ジェクトã®ã€Œæ¦‚è¦ã®è¨€ã„回ã—ã€ã¯ãã®ãƒ‘ッãƒã®æ¦‚è¦ã‚’正確
+ã«è¡¨ç¾ã—ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。「概è¦ã®è¨€ã„回ã—ã€ã‚’ファイルåã«ã—ã¦ã¯ã„
+ã‘ã¾ã›ã‚“。一連ã®ãƒ‘ッãƒä¸­ã§ãã‚Œãžã‚Œã®ãƒ‘ッãƒã¯åŒã˜ã€Œæ¦‚è¦ã®è¨€ã„回ã—ã€ã‚’
+使ã£ã¦ã¯ã„ã‘ã¾ã›ã‚“(「一連ã®ãƒ‘ッãƒã€ã¨ã¯é †åºä»˜ã‘られãŸé–¢é€£ã®ã‚る複数ã®
+パッãƒç¾¤ã§ã™)。
+
+ã‚ãªãŸã®é›»å­ãƒ¡ãƒ¼ãƒ«ã®ã€Œæ¦‚è¦ã®è¨€ã„回ã—ã€ãŒãã®ãƒ‘ッãƒã«ã¨ã£ã¦ä¸–ç•Œã§å”¯
+一ã®è­˜åˆ¥å­ã«ãªã‚‹ã‚ˆã†ã«å¿ƒãŒã‘ã¦ãã ã•ã„。「概è¦ã®è¨€ã„回ã—ã€ã¯ git ã®
+ãƒã‚§ãƒ³ã‚¸ãƒ­ã‚°ã®ä¸­ã¸ãšã£ã¨ä¼æ’­ã—ã¦ã„ãã¾ã™ã€‚「概è¦ã®è¨€ã„回ã—ã€ã¯ã€é–‹
+発者ãŒå¾Œã§ãƒ‘ッãƒã‚’å‚ç…§ã™ã‚‹ãŸã‚ã«è­°è«–ã®ä¸­ã§åˆ©ç”¨ã™ã‚‹ã‹ã‚‚ã—ã‚Œã¾ã›ã‚“。
+人々ã¯ãã®ãƒ‘ッãƒã«é–¢é€£ã—ãŸè­°è«–を読むãŸã‚ã«ã€Œæ¦‚è¦ã®è¨€ã„回ã—ã€ã‚’使ã£ã¦
+google ã§æ¤œç´¢ã—ãŸãŒã‚‹ã§ã—ょã†ã€‚
+
+サブジェクトã®ä¾‹ã‚’二ã¤
+
+ Subject: [patch 2/5] ext2: improve scalability of bitmap searching
+ Subject: [PATCHv2 001/207] x86: fix eflags tracking
+
+「 from ã€è¡Œã¯é›»å­ãƒ¡ãƒ¼ãƒ«ã®ãƒœãƒ‡ã‚£ã®ä¸€ç•ªæœ€åˆã®è¡Œã§ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。
+ãã®å½¢å¼ã¯ä»¥ä¸‹ã®ã¨ãŠã‚Šã§ã™ã€‚
+
+ From: Original Author <author@example.com>
+
+「 from ã€è¡Œã¯ãƒã‚§ãƒ³ã‚¸ãƒ­ã‚°ã®ä¸­ã§ã€ãã®ãƒ‘ッãƒã®ä½œæˆè€…ã¨ã—ã¦ã‚¯ãƒ¬ã‚¸ãƒƒãƒˆã•ã‚Œ
+ã¦ã„る人を特定ã™ã‚‹ã‚‚ã®ã§ã™ã€‚「 from ã€è¡ŒãŒã‹ã‘ã¦ã„ã‚‹ã¨ã€é›»å­ãƒ¡ãƒ¼ãƒ«ã®ãƒ˜ãƒƒ
+ダーã®ã€Œ From: ã€ãŒã€ãƒã‚§ãƒ³ã‚¸ãƒ­ã‚°ã®ä¸­ã§ãƒ‘ッãƒã®ä½œæˆè€…を決定ã™ã‚‹ãŸã‚ã«ä½¿ã‚
+れるã§ã—ょã†ã€‚
+
+説明本体ã¯ç„¡æœŸé™ã®ã‚½ãƒ¼ã‚¹ã®ãƒã‚§ãƒ³ã‚¸ãƒ­ã‚°ã«ã‚³ãƒŸãƒƒãƒˆã•ã‚Œã¾ã™ã€‚ãªã®ã§ã€èª¬æ˜Ž
+本体ã¯ãã®ãƒ‘ッãƒã«è‡³ã£ãŸè­°è«–ã®è©³ç´°ã‚’忘れã¦ã„ã‚‹ã‚る程度ã®æŠ€é‡ã‚’æŒã£ã¦ã„る人
+ãŒãã®è©³ç´°ã‚’æ€ã„出ã™ã“ã¨ãŒã§ãã‚‹ã‚‚ã®ã§ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。
+
+「 --- ã€ãƒžãƒ¼ã‚«ãƒ¼è¡Œã¯ãƒ‘ッãƒå‡¦ç†ãƒ„ールã«å¯¾ã—ã¦ã€ãƒã‚§ãƒ³ã‚¸ãƒ­ã‚°ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã®çµ‚端
+部分をèªè­˜ã•ã›ã‚‹ã¨ã„ã†é‡è¦ãªå½¹ç›®ã‚’æžœãŸã—ã¾ã™ã€‚
+
+「 --- ã€ãƒžãƒ¼ã‚«ãƒ¼è¡Œã®å¾Œã®è¿½åŠ ã‚³ãƒ¡ãƒ³ãƒˆã®è‰¯ã„使用方法ã®1ã¤ã« diffstat コマンド
+ãŒã‚ã‚Šã¾ã™ã€‚diffstat コマンドã¨ã¯ä½•ã®ãƒ•ã‚¡ã‚¤ãƒ«ãŒå¤‰æ›´ã•ã‚Œã€1ファイル当ãŸã‚Šä½•è¡Œ
+追加ã•ã‚Œä½•è¡Œæ¶ˆã•ã‚ŒãŸã‹ã‚’示ã™ã‚‚ã®ã§ã™ã€‚diffstat コマンドã¯ç‰¹ã«å¤§ããªãƒ‘ッãƒã«
+ãŠã„ã¦å½¹ç«‹ã¡ã¾ã™ã€‚ãã®æ™‚点ã§ã ã‘åˆã¯ãƒ¡ãƒ³ãƒ†ãƒŠã«ã¨ã£ã¦ã®ã¿é–¢ä¿‚ã®ã‚るコメント
+ã¯ç„¡æœŸé™ã«ä¿å­˜ã•ã‚Œã‚‹ãƒã‚§ãƒ³ã‚¸ãƒ­ã‚°ã«ã¨ã£ã¦é©åˆ‡ã§ã¯ã‚ã‚Šã¾ã›ã‚“。ãã®ãŸã‚ã€ã“ã®
+よã†ãªã‚³ãƒ¡ãƒ³ãƒˆã‚‚マーカー行ã®å¾Œã«æ›¸ã‹ã‚Œã‚‹ã¹ãã§ã™ã€‚ファイルåã¯ã‚«ãƒ¼ãƒãƒ«ã‚½ãƒ¼
+スツリーã®ãƒˆãƒƒãƒ—ディレクトリã‹ã‚‰ã®è¡¨è¨˜ã§ãƒªã‚¹ãƒˆã•ã‚Œã‚‹ãŸã‚ã€æ¨ªæ–¹å‘ã®ã‚¹ãƒšãƒ¼ã‚¹
+ã‚’ã¨ã‚ŠéŽãŽãªã„よã†ã«ã€diffstat コマンドã«ã‚ªãƒ—ション「 -p 1 -w 70 ã€ã‚’指定ã—
+ã¦ãã ã•ã„(インデントをå«ã‚ã¦ã¡ã‚‡ã†ã©80列ã«åˆã†ã§ã—ょã†)。
+
+é©åˆ‡ãªãƒ‘ッãƒã®ãƒ•ã‚©ãƒ¼ãƒžãƒƒãƒˆã®è©³ç´°ã«ã¤ã„ã¦ã¯ã‚»ã‚¯ã‚·ãƒ§ãƒ³3ã®å‚考文献をå‚ç…§ã—ã¦
+ãã ã•ã„。
+
+------------------------------------
+セクション2 - ヒントã¨TIPSã¨å°æŠ€
+------------------------------------
+
+ã“ã®ã‚»ã‚¯ã‚·ãƒ§ãƒ³ã¯ Linux カーãƒãƒ«ã«å¤‰æ›´ã‚’é©ç”¨ã™ã‚‹ã“ã¨ã«é–¢ä¿‚ã®ã‚る一般的ãª
+「ãŠç´„æŸã€ã®å¤šãを載ã›ã¦ã„ã¾ã™ã€‚物事ã«ã¯ä¾‹å¤–ã¨ã„ã†ã‚‚ã®ãŒã‚ã‚Šã¾ã™ã€‚ã—ã‹
+ã—例外をé©ç”¨ã™ã‚‹ã«ã¯ã€æœ¬å½“ã«å¦¥å½“ãªç†ç”±ãŒä¸å¯æ¬ ã§ã™ã€‚ã‚ãªãŸã¯æらãã“ã®
+セクションを Linus ã®ã‚³ãƒ³ãƒ”ュータ・サイエンス101ã¨å‘¼ã¶ã§ã—ょã†ã€‚
+
+1) Documentation/CodingStyleã‚’å‚ç…§
+
+言ã†ã¾ã§ã‚‚ãªãã€ã‚ãªãŸã®ã‚³ãƒ¼ãƒ‰ãŒã“ã®ã‚³ãƒ¼ãƒ‡ã‚£ãƒ³ã‚°ã‚¹ã‚¿ã‚¤ãƒ«ã‹ã‚‰ã‚ã¾ã‚Šã«
+も逸脱ã—ã¦ã„ã‚‹ã¨ã€ãƒ¬ãƒ“ューやコメントãªã—ã«å—ã‘å–ã£ã¦ã‚‚らãˆãªã„ã‹ã‚‚ã—
+ã‚Œã¾ã›ã‚“。
+
+唯一ã®ç‰¹ç­†ã™ã¹ã例外ã¯ã€ã‚³ãƒ¼ãƒ‰ã‚’ã‚るファイルã‹ã‚‰åˆ¥ã®ãƒ•ã‚¡ã‚¤ãƒ«ã«ç§»å‹•
+ã™ã‚‹ã¨ãã§ã™ã€‚ã“ã®å ´åˆã€ã‚³ãƒ¼ãƒ‰ã‚’移動ã™ã‚‹ãƒ‘ッãƒã§ã¯ã€ç§»å‹•ã•ã‚Œã‚‹ã‚³ãƒ¼ãƒ‰
+ã«é–¢ã—ã¦ç§»å‹•ä»¥å¤–ã®å¤‰æ›´ã‚’一切加ãˆã‚‹ã¹ãã§ã¯ã‚ã‚Šã¾ã›ã‚“。ã“ã‚Œã«ã‚ˆã‚Šã€
+コードã®ç§»å‹•ã¨ã‚ãªãŸãŒè¡Œã£ãŸã‚³ãƒ¼ãƒ‰ã®ä¿®æ­£ã‚’明確ã«åŒºåˆ¥ã§ãるよã†ã«ãª
+ã‚Šã¾ã™ã€‚ã“ã‚Œã¯å®Ÿéš›ã«ä½•ãŒå¤‰æ›´ã•ã‚ŒãŸã‹ã‚’レビューã™ã‚‹éš›ã®å¤§ããªåŠ©ã‘ã«
+ãªã‚‹ã¨ã¨ã‚‚ã«ã€ãƒ„ールã«ã‚³ãƒ¼ãƒ‰ã®å±¥æ­´ã‚’追跡ã•ã›ã‚‹ã“ã¨ã‚‚容易ã«ãªã‚Šã¾ã™ã€‚
+
+投稿ã™ã‚‹ã‚ˆã‚Šå‰ã«ãƒ‘ッãƒã®ã‚¹ã‚¿ã‚¤ãƒ«ãƒã‚§ãƒƒã‚«ãƒ¼( scripts/checkpatch.pl )ã§
+ã‚ãªãŸã®ãƒ‘ッãƒã‚’ãƒã‚§ãƒƒã‚¯ã—ã¦ãã ã•ã„。ã“ã®ã‚¹ã‚¿ã‚¤ãƒ«ãƒã‚§ãƒƒã‚«ãƒ¼ã¯æœ€çµ‚çµ
+è«–ã¨ã—ã¦ã§ã¯ãªãã€æŒ‡æ¨™ã¨ã—ã¦ã¿ã‚‹ã¹ãã§ã™ã€‚ã‚‚ã—ã€ã‚ãªãŸã®ã‚³ãƒ¼ãƒ‰ãŒé•å
+ã¯ã—ã¦ã„ã‚‹ãŒä¿®æ­£ã™ã‚‹ã‚ˆã‚Šè‰¯ã見ãˆã‚‹ã®ã§ã‚ã‚Œã°ã€ãŠãらããã®ã¾ã¾ã«ã™ã‚‹
+ã®ãŒãƒ™ã‚¹ãƒˆã§ã™ã€‚
+
+スタイルãƒã‚§ãƒƒã‚«ãƒ¼ã«ã‚ˆã‚‹3段階ã®ãƒ¬ãƒãƒ¼ãƒˆ:
+ - エラー: é–“é•ã£ã¦ã„ã‚‹å¯èƒ½æ€§ãŒé«˜ã„
+ - 警告:注æ„ã—ã¦ãƒ¬ãƒ“ューã™ã‚‹å¿…è¦ãŒã‚ã‚‹
+ - ãƒã‚§ãƒƒã‚¯ï¼šè€ƒæ…®ã™ã‚‹å¿…è¦ãŒã‚ã‚‹
+
+ã‚ãªãŸã¯ãƒ‘ッãƒã«æ®‹ã£ã¦ã„ã‚‹å…¨ã¦ã®é•åã«ã¤ã„ã¦ã€ãã‚ŒãŒãªãœå¿…è¦ãªã®ã‹æ­£å½“ãª
+ç†ç”±ã‚’示ã›ã‚‹ã‚ˆã†ã«ã—ã¦ãŠãå¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+
+2) #ifdefã¯è¦‹è‹¦ã—ã„
+
+ifdef ãŒæ•£ä¹±ã—ãŸã‚³ãƒ¼ãƒ‰ã¯ã€èª­ã‚€ã®ã‚‚メンテナンスã™ã‚‹ã®ã‚‚é¢å€’ã§ã™ã€‚コードã®ä¸­
+㧠ifdef を使ã‚ãªã„ã§ãã ã•ã„。代ã‚ã‚Šã«ã€ãƒ˜ãƒƒãƒ€ãƒ•ã‚¡ã‚¤ãƒ«ã®ä¸­ã« ifdef を入れã¦ã€
+æ¡ä»¶ä»˜ãã§ã€ã‚³ãƒ¼ãƒ‰ã®ä¸­ã§ä½¿ã‚れる関数を「 static inline ã€é–¢æ•°ã‹ãƒžã‚¯ãƒ­ã§å®šç¾©ã—
+ã¦ãã ã•ã„。後ã¯ã‚³ãƒ³ãƒ‘イラãŒã€ä½•ã‚‚ã—ãªã„箇所を最é©åŒ–ã—ã¦å–り去ã£ã¦ãれるã§
+ã—ょã†ã€‚
+
+ã¾ãšã„コードã®ç°¡å˜ãªä¾‹
+
+ dev = alloc_etherdev (sizeof(struct funky_private));
+ if (!dev)
+ return -ENODEV;
+ #ifdef CONFIG_NET_FUNKINESS
+ init_funky_net(dev);
+ #endif
+
+クリーンアップã—ãŸã‚³ãƒ¼ãƒ‰ã®ä¾‹
+
+(in header)
+ #ifndef CONFIG_NET_FUNKINESS
+ static inline void init_funky_net (struct net_device *d) {}
+ #endif
+
+(in the code itself)
+ dev = alloc_etherdev (sizeof(struct funky_private));
+ if (!dev)
+ return -ENODEV;
+ init_funky_net(dev);
+
+3) マクロより「 static inline ã€ã‚’推奨
+
+「 static inline ã€é–¢æ•°ã¯ãƒžã‚¯ãƒ­ã‚ˆã‚Šã‚‚ãšã£ã¨æŽ¨å¥¨ã•ã‚Œã¦ã„ã¾ã™ã€‚ãれらã¯ã€
+型安全性ãŒã‚ã‚Šã€é•·ã•ã«ã‚‚制é™ãŒç„¡ãã€ãƒ•ã‚©ãƒ¼ãƒžãƒƒãƒˆã®åˆ¶é™ã‚‚ã‚ã‚Šã¾ã›ã‚“。
+gcc ã«ãŠã„ã¦ã¯ã€ãƒžã‚¯ãƒ­ã¨åŒã˜ãらã„軽ã„ã§ã™ã€‚
+
+マクロã¯ã€Œ static inline ã€ãŒæ˜Žã‚‰ã‹ã«ä¸é©åˆ‡ã§ã‚ã‚‹ã¨åˆ†ã‹ã‚‹å ´æ‰€(高速化パスã®
+ã„ãã¤ã‹ã®ç‰¹å®šã®ã‚±ãƒ¼ã‚¹)や「 static inline ã€é–¢æ•°ã‚’使ã†ã“ã¨ãŒã§ããªã„よã†ãª
+場所(マクロã®å¼•æ•°ã®æ–‡å­—列連çµã®ã‚ˆã†ãª)ã«ã ã‘使ã‚れるã¹ãã§ã™ã€‚
+
+「 static inline ã€ã¯ã€Œ static __inline__ ã€ã‚„「 extern inline ã€ã‚„
+「 extern __inline__ ã€ã‚ˆã‚Šã‚‚é©åˆ‡ã§ã™ã€‚
+
+4) 設計ã«å‡ã‚Šã™ãŽã‚‹ãª
+
+ãã‚ŒãŒæœ‰ç”¨ã«ãªã‚‹ã‹ã©ã†ã‹åˆ†ã‹ã‚‰ãªã„よã†ãªä¸æ˜Žçž­ãªå°†æ¥ã‚’見越ã—ãŸè¨­è¨ˆ
+ã‚’ã—ãªã„ã§ãã ã•ã„。「ã§ãã‚‹é™ã‚Šç°¡å˜ã«ã€ãã—ã¦ã€ãれ以上簡å˜ã«ãªã‚‰
+ãªã„よã†ãªè¨­è¨ˆã‚’ã—ã¦ãã ã•ã„。ã€
+
+----------------------
+セクション3 å‚考文献
+----------------------
+
+Andrew Morton, "The perfect patch" (tpp).
+ <http://www.zip.com.au/~akpm/linux/patches/stuff/tpp.txt>
+
+Jeff Garzik, "Linux kernel patch submission format".
+ <http://linux.yyz.us/patch-format.html>
+
+Greg Kroah-Hartman, "How to piss off a kernel subsystem maintainer".
+ <http://www.kroah.com/log/2005/03/31/>
+ <http://www.kroah.com/log/2005/07/08/>
+ <http://www.kroah.com/log/2005/10/19/>
+ <http://www.kroah.com/log/2006/01/11/>
+
+NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!
+ <http://marc.theaimsgroup.com/?l=linux-kernel&m=112112749912944&w=2>
+
+Kernel Documentation/CodingStyle:
+ <http://users.sosdg.org/~qiyong/lxr/source/Documentation/CodingStyle>
+
+Linus Torvalds's mail on the canonical patch format:
+ <http://lkml.org/lkml/2005/4/7/183>
+--
diff --git a/Documentation/java.txt b/Documentation/java.txt
index 3cce3fbb6644..e6a723281547 100644
--- a/Documentation/java.txt
+++ b/Documentation/java.txt
@@ -37,7 +37,7 @@ other program after you have done the following:
or the following, if you want to be more selective:
':Applet:M::<!--applet::/usr/bin/appletviewer:'
- Of cause you have to fix the path names. Given path/file names in this
+ Of course you have to fix the path names. The path/file names given in this
document match the Debian 2.1 system. (i.e. jdk installed in /usr,
custom wrappers from this document in /usr/local)
diff --git a/Documentation/kbuild/kconfig-language.txt b/Documentation/kbuild/kconfig-language.txt
index fe8b0c4892cf..616043a6da99 100644
--- a/Documentation/kbuild/kconfig-language.txt
+++ b/Documentation/kbuild/kconfig-language.txt
@@ -77,7 +77,12 @@ applicable everywhere (see syntax).
Optionally, dependencies only for this default value can be added with
"if".
-- dependencies: "depends on"/"requires" <expr>
+- type definition + default value:
+ "def_bool"/"def_tristate" <expr> ["if" <expr>]
+ This is a shorthand notation for a type definition plus a value.
+ Optionally dependencies for this default value can be added with "if".
+
+- dependencies: "depends on" <expr>
This defines a dependency for this menu entry. If multiple
dependencies are defined, they are connected with '&&'. Dependencies
are applied to all other options within this menu entry (which also
@@ -289,3 +294,10 @@ source:
"source" <prompt>
This reads the specified configuration file. This file is always parsed.
+
+mainmenu:
+
+ "mainmenu" <prompt>
+
+This sets the config program's title bar if the config program chooses
+to use it.
diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index e08ef8759a07..7a7753321a26 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -276,41 +276,39 @@ more details, with real examples.
--- 3.7 Compilation flags
- EXTRA_CFLAGS, EXTRA_AFLAGS, EXTRA_LDFLAGS, EXTRA_ARFLAGS
+ ccflags-y, asflags-y and ldflags-y
+ The three flags listed above applies only to the kbuild makefile
+ where they are assigned. They are used for all the normal
+ cc, as and ld invocation happenign during a recursive build.
+ Note: Flags with the same behaviour were previously named:
+ EXTRA_CFLAGS, EXTRA_AFLAGS and EXTRA_LDFLAGS.
+ They are yet supported but their use are deprecated.
- All the EXTRA_ variables apply only to the kbuild makefile
- where they are assigned. The EXTRA_ variables apply to all
- commands executed in the kbuild makefile.
-
- $(EXTRA_CFLAGS) specifies options for compiling C files with
- $(CC).
+ ccflags-y specifies options for compiling C files with $(CC).
Example:
# drivers/sound/emu10k1/Makefile
- EXTRA_CFLAGS += -I$(obj)
- ifdef DEBUG
- EXTRA_CFLAGS += -DEMU10K1_DEBUG
- endif
+ ccflags-y += -I$(obj)
+ ccflags-$(DEBUG) += -DEMU10K1_DEBUG
This variable is necessary because the top Makefile owns the
- variable $(CFLAGS) and uses it for compilation flags for the
+ variable $(KBUILD_CFLAGS) and uses it for compilation flags for the
entire tree.
- $(EXTRA_AFLAGS) is a similar string for per-directory options
+ asflags-y is a similar string for per-directory options
when compiling assembly language source.
Example:
#arch/x86_64/kernel/Makefile
- EXTRA_AFLAGS := -traditional
+ asflags-y := -traditional
- $(EXTRA_LDFLAGS) and $(EXTRA_ARFLAGS) are similar strings for
- per-directory options to $(LD) and $(AR).
+ ldflags-y is a string for per-directory options to $(LD).
Example:
#arch/m68k/fpsp040/Makefile
- EXTRA_LDFLAGS := -x
+ ldflags-y := -x
CFLAGS_$@, AFLAGS_$@
@@ -425,6 +423,7 @@ more details, with real examples.
as-instr checks if the assembler reports a specific instruction
and then outputs either option1 or option2
C escapes are supported in the test instruction
+ Note: as-instr-option uses KBUILD_AFLAGS for $(AS) options
cc-option
cc-option is used to check if $(CC) supports a given option, and not
@@ -438,6 +437,7 @@ more details, with real examples.
-march=pentium-mmx if supported by $(CC), otherwise -march=i586.
The second argument to cc-option is optional, and if omitted,
cflags-y will be assigned no value if first option is not supported.
+ Note: cc-option uses KBUILD_CFLAGS for $(CC) options
cc-option-yn
cc-option-yn is used to check if gcc supports a given option
@@ -453,6 +453,7 @@ more details, with real examples.
option. When $(biarch) equals 'y', the expanded variables $(aflags-y)
and $(cflags-y) will be assigned the values -a32 and -m32,
respectively.
+ Note: cc-option-yn uses KBUILD_CFLAGS for $(CC) options
cc-option-align
gcc versions >= 3.0 changed the type of options used to specify
@@ -464,10 +465,11 @@ more details, with real examples.
cc-option-align = -falign
Example:
- CFLAGS += $(cc-option-align)-functions=4
+ KBUILD_CFLAGS += $(cc-option-align)-functions=4
In the above example, the option -falign-functions=4 is used for
gcc >= 3.00. For gcc < 3.00, -malign-functions=4 is used.
+ Note: cc-option-align uses KBUILD_CFLAGS for $(CC) options
cc-version
cc-version returns a numerical version of the $(CC) compiler version.
@@ -492,9 +494,9 @@ more details, with real examples.
Example:
#fs/reiserfs/Makefile
- EXTRA_CFLAGS := $(call cc-ifversion, -lt, 0402, -O1)
+ ccflags-y := $(call cc-ifversion, -lt, 0402, -O1)
- In this example, EXTRA_CFLAGS will be assigned the value -O1 if the
+ In this example, ccflags-y will be assigned the value -O1 if the
$(CC) version is less than 4.2.
cc-ifversion takes all the shell operators:
-eq, -ne, -lt, -le, -gt, and -ge
@@ -516,6 +518,28 @@ more details, with real examples.
In this example for a specific GCC version the build will error out explaining
to the user why it stops.
+ cc-cross-prefix
+ cc-cross-prefix is used to check if there exists a $(CC) in path with
+ one of the listed prefixes. The first prefix where there exist a
+ prefix$(CC) in the PATH is returned - and if no prefix$(CC) is found
+ then nothing is returned.
+ Additional prefixes are separated by a single space in the
+ call of cc-cross-prefix.
+ This functionality is useful for architecture Makefiles that try
+ to set CROSS_COMPILE to well-known values but may have several
+ values to select between.
+ It is recommended only to try to set CROSS_COMPILE if it is a cross
+ build (host arch is different from target arch). And if CROSS_COMPILE
+ is already set then leave it with the old value.
+
+ Example:
+ #arch/m68k/Makefile
+ ifneq ($(SUBARCH),$(ARCH))
+ ifeq ($(CROSS_COMPILE),)
+ CROSS_COMPILE := $(call cc-cross-prefix, m68k-linux-gnu-)
+ endif
+ endif
+
=== 4 Host Program support
Kbuild supports building executables on the host for use during the
@@ -780,8 +804,8 @@ When kbuild executes, the following steps are followed (roughly):
Example:
#arch/s390/Makefile
LDFLAGS := -m elf_s390
- Note: EXTRA_LDFLAGS and LDFLAGS_$@ can be used to further customise
- the flags used. See chapter 7.
+ Note: ldflags-y can be used to further customise
+ the flags used. See chapter 3.7.
LDFLAGS_MODULE Options for $(LD) when linking modules
@@ -817,26 +841,26 @@ When kbuild executes, the following steps are followed (roughly):
In this example, the binary $(obj)/image is a binary version of
vmlinux. The usage of $(call if_changed,xxx) will be described later.
- AFLAGS $(AS) assembler flags
+ KBUILD_AFLAGS $(AS) assembler flags
Default value - see top level Makefile
Append or modify as required per architecture.
Example:
#arch/sparc64/Makefile
- AFLAGS += -m64 -mcpu=ultrasparc
+ KBUILD_AFLAGS += -m64 -mcpu=ultrasparc
- CFLAGS $(CC) compiler flags
+ KBUILD_CFLAGS $(CC) compiler flags
Default value - see top level Makefile
Append or modify as required per architecture.
- Often, the CFLAGS variable depends on the configuration.
+ Often, the KBUILD_CFLAGS variable depends on the configuration.
Example:
#arch/i386/Makefile
cflags-$(CONFIG_M386) += -march=i386
- CFLAGS += $(cflags-y)
+ KBUILD_CFLAGS += $(cflags-y)
Many arch Makefiles dynamically run the target C compiler to
probe supported options:
@@ -848,7 +872,7 @@ When kbuild executes, the following steps are followed (roughly):
-march=pentium2,-march=i686)
...
# Disable unit-at-a-time mode ...
- CFLAGS += $(call cc-option,-fno-unit-at-a-time)
+ KBUILD_CFLAGS += $(call cc-option,-fno-unit-at-a-time)
...
@@ -1096,8 +1120,8 @@ When kbuild executes, the following steps are followed (roughly):
specified options when building the target vmlinux.lds.
When building the *.lds target, kbuild uses the variables:
- CPPFLAGS : Set in top-level Makefile
- EXTRA_CPPFLAGS : May be set in the kbuild makefile
+ KBUILD_CPPFLAGS : Set in top-level Makefile
+ cppflags-y : May be set in the kbuild makefile
CPPFLAGS_$(@F) : Target specific flags.
Note that the full filename is used in this
assignment.
diff --git a/Documentation/kdump/kdump.txt b/Documentation/kdump/kdump.txt
index 2fedc081b4c8..d0ac72cc19ff 100644
--- a/Documentation/kdump/kdump.txt
+++ b/Documentation/kdump/kdump.txt
@@ -13,7 +13,7 @@ dump of the system kernel's memory needs to be taken (for example, when
the system panics). The system kernel's memory image is preserved across
the reboot and is accessible to the dump-capture kernel.
-You can use common Linux commands, such as cp and scp, to copy the
+You can use common commands, such as cp and scp, to copy the
memory image to a dump file on the local disk, or across the network to
a remote system.
@@ -69,7 +69,7 @@ http://www.kernel.org/pub/linux/kernel/people/horms/kexec-tools/kexec-tools-test
This is a symlink to the latest version, which at the time of writing is
20061214, the only release of kexec-tools-testing so far. As other versions
-are made released, the older onese will remain available at
+are released, the older ones will remain available at
http://www.kernel.org/pub/linux/kernel/people/horms/kexec-tools/
Note: Latest kexec-tools-testing git tree is available at
@@ -159,16 +159,17 @@ Dump-capture kernel config options (Arch Independent)
CONFIG_PROC_VMCORE=y
(CONFIG_PROC_VMCORE is set by default when CONFIG_CRASH_DUMP is selected.)
-Dump-capture kernel config options (Arch Dependent, i386)
---------------------------------------------------------
-1) On x86, enable high memory support under "Processor type and
+Dump-capture kernel config options (Arch Dependent, i386 and x86_64)
+--------------------------------------------------------------------
+
+1) On i386, enable high memory support under "Processor type and
features":
CONFIG_HIGHMEM64G=y
or
CONFIG_HIGHMEM4G
-2) On x86 and x86_64, disable symmetric multi-processing support
+2) On i386 and x86_64, disable symmetric multi-processing support
under "Processor type and features":
CONFIG_SMP=n
@@ -203,28 +204,6 @@ Dump-capture kernel config options (Arch Dependent, i386)
5) Make and install the kernel and its modules. DO NOT add this kernel
to the boot loader configuration files.
-Dump-capture kernel config options (Arch Dependent, x86_64)
-----------------------------------------------------------
-1) On x86 and x86_64, disable symmetric multi-processing support
- under "Processor type and features":
-
- CONFIG_SMP=n
-
- (If CONFIG_SMP=y, then specify maxcpus=1 on the kernel command line
- when loading the dump-capture kernel, see section "Load the Dump-capture
- Kernel".)
-
-2) Use a suitable value for "Physical address where the kernel is
- loaded" (under "Processor type and features"). This only appears when
- "kernel crash dumps" is enabled. By default this value is 0x1000000
- (16MB). It should be the same as X in the "crashkernel=Y@X" boot
- parameter.
-
- For x86_64, normally "CONFIG_PHYSICAL_START=0x1000000".
-
-3) Make and install the kernel and its modules. DO NOT add this kernel
- to the boot loader configuration files.
-
Dump-capture kernel config options (Arch Dependent, ppc64)
----------------------------------------------------------
@@ -252,6 +231,32 @@ Dump-capture kernel config options (Arch Dependent, ia64)
any space below the alignment point will be wasted.
+Extended crashkernel syntax
+===========================
+
+While the "crashkernel=size[@offset]" syntax is sufficient for most
+configurations, sometimes it's handy to have the reserved memory dependent
+on the value of System RAM -- that's mostly for distributors that pre-setup
+the kernel command line to avoid a unbootable system after some memory has
+been removed from the machine.
+
+The syntax is:
+
+ crashkernel=<range1>:<size1>[,<range2>:<size2>,...][@offset]
+ range=start-[end]
+
+For example:
+
+ crashkernel=512M-2G:64M,2G-:128M
+
+This would mean:
+
+ 1) if the RAM is smaller than 512M, then don't reserve anything
+ (this is the "rescue" case)
+ 2) if the RAM size is between 512M and 2G, then reserve 64M
+ 3) if the RAM size is larger than 2G, then reserve 128M
+
+
Boot into System Kernel
=======================
@@ -282,11 +287,9 @@ Based on the architecture and type of image (relocatable or not), one
can choose to load the uncompressed vmlinux or compressed bzImage/vmlinuz
of dump-capture kernel. Following is the summary.
-For i386:
+For i386 and x86_64:
- Use vmlinux if kernel is not relocatable.
- Use bzImage/vmlinuz if kernel is relocatable.
-For x86_64:
- - Use vmlinux
For ppc64:
- Use vmlinux
For ia64:
@@ -315,20 +318,22 @@ Following are the arch specific command line options to be used while
loading dump-capture kernel.
For i386, x86_64 and ia64:
- "1 irqpoll maxcpus=1"
+ "1 irqpoll maxcpus=1 reset_devices"
For ppc64:
- "1 maxcpus=1 noirqdistrib"
+ "1 maxcpus=1 noirqdistrib reset_devices"
Notes on loading the dump-capture kernel:
* By default, the ELF headers are stored in ELF64 format to support
- systems with more than 4GB memory. The --elf32-core-headers option can
- be used to force the generation of ELF32 headers. This is necessary
- because GDB currently cannot open vmcore files with ELF64 headers on
- 32-bit systems. ELF32 headers can be used on non-PAE systems (that is,
- less than 4GB of memory).
+ systems with more than 4GB memory. On i386, kexec automatically checks if
+ the physical RAM size exceeds the 4 GB limit and if not, uses ELF32.
+ So, on non-PAE systems, ELF32 is always used.
+
+ The --elf32-core-headers option can be used to force the generation of ELF32
+ headers. This is necessary because GDB currently cannot open vmcore files
+ with ELF64 headers on 32-bit systems.
* The "irqpoll" boot parameter reduces driver initialization failures
due to shared interrupts in the dump-capture kernel.
@@ -360,7 +365,7 @@ If die() is called, and it happens to be a thread with pid 0 or 1, or die()
is called inside interrupt context or die() is called and panic_on_oops is set,
the system will boot into the dump-capture kernel.
-On powererpc systems when a soft-reset is generated, die() is called by all cpus
+On powerpc systems when a soft-reset is generated, die() is called by all cpus
and the system will boot into the dump-capture kernel.
For testing purposes, you can trigger a crash by using "ALT-SysRq-c",
@@ -426,9 +431,3 @@ Contact
Vivek Goyal (vgoyal@in.ibm.com)
Maneesh Soni (maneesh@in.ibm.com)
-
-Trademark
-=========
-
-Linux is a trademark of Linus Torvalds in the United States, other
-countries, or both.
diff --git a/Documentation/kernel-docs.txt b/Documentation/kernel-docs.txt
index d9e3b199929b..5a4ef48224ae 100644
--- a/Documentation/kernel-docs.txt
+++ b/Documentation/kernel-docs.txt
@@ -76,9 +76,9 @@
* Title: "Conceptual Architecture of the Linux Kernel"
Author: Ivan T. Bowman.
URL: http://plg.uwaterloo.ca/~itbowman/papers/CS746G-a1.html
- Keywords: conceptual software arquitecture, extracted design,
+ Keywords: conceptual software architecture, extracted design,
reverse engineering, system structure.
- Description: Conceptual software arquitecture of the Linux kernel,
+ Description: Conceptual software architecture of the Linux kernel,
automatically extracted from the source code. Very detailed. Good
figures. Gives good overall kernel understanding.
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index fdd6dbcf864e..33121d6c827c 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -75,10 +75,12 @@ parameter is applicable:
PPT Parallel port support is enabled.
PS2 Appropriate PS/2 support is enabled.
RAM RAM disk support is enabled.
+ ROOTPLUG The example Root Plug LSM is enabled.
S390 S390 architecture is enabled.
SCSI Appropriate SCSI support is enabled.
A lot of drivers has their options described inside of
Documentation/scsi/.
+ SECURITY Different security models are enabled.
SELINUX SELinux support is enabled.
SERIAL Serial support is enabled.
SH SuperH architecture is enabled.
@@ -220,9 +222,6 @@ and is between 256 and 4096 characters. It is defined in the file
Warning: Many of these options can produce a lot of
output and make your system unusable. Be very careful.
-
- acpi_fake_ecdt [HW,ACPI] Workaround failure due to BIOS lacking ECDT
-
acpi_pm_good [X86-32,X86-64]
Override the pmtimer bug detection: force the kernel
to assume that this machine's pmtimer latches its value
@@ -295,9 +294,6 @@ and is between 256 and 4096 characters. It is defined in the file
apm= [APM] Advanced Power Management
See header of arch/i386/kernel/apm.c.
- applicom= [HW]
- Format: <mem>,<irq>
-
arcrimi= [HW,NET] ARCnet - "RIM I" (entirely mem-mapped) cards
Format: <io>,<irq>,<nodeID>
@@ -343,11 +339,10 @@ and is between 256 and 4096 characters. It is defined in the file
Format: <io>,<irq>,<mode>
See header of drivers/net/hamradio/baycom_ser_hdx.c.
- blkmtd_device= [HW,MTD]
- blkmtd_erasesz=
- blkmtd_ro=
- blkmtd_bs=
- blkmtd_count=
+ boot_delay= Milliseconds to delay each printk during boot.
+ Values larger than 10 seconds (10000) are changed to
+ no delay (0).
+ Format: integer
bttv.card= [HW,V4L] bttv (bt848 + bt878 based grabber cards)
bttv.radio= Most important insmod options are available as
@@ -368,6 +363,12 @@ and is between 256 and 4096 characters. It is defined in the file
possible to determine what the correct size should be.
This option provides an override for these situations.
+ capability.disable=
+ [SECURITY] Disable capabilities. This would normally
+ be used only if an alternative security model is to be
+ configured. Potentially dangerous and should only be
+ used if you are entirely sure of the consequences.
+
chandev= [HW,NET] Generic channel device initialisation
checkreqprot [SELINUX] Set initial checkreqprot flag value.
@@ -418,8 +419,11 @@ and is between 256 and 4096 characters. It is defined in the file
over the 8254 in addition to over the IO-APIC. The
kernel tries to set a sensible default.
- hpet= [X86-32,HPET] option to disable HPET and use PIT.
- Format: disable
+ hpet= [X86-32,HPET] option to control HPET usage
+ Format: { enable (default) | disable | force }
+ disable: disable HPET and use PIT instead
+ force: allow force enabled of undocumented chips (ICH4,
+ VIA, nVidia)
com20020= [HW,NET] ARCnet - COM20020 chipset
Format:
@@ -466,6 +470,16 @@ and is between 256 and 4096 characters. It is defined in the file
UART at the specified I/O port or MMIO address.
The options are the same as for ttyS, above.
+ no_console_suspend
+ [HW] Never suspend the console
+ Disable suspending of consoles during suspend and
+ hibernate operations. Once disabled, debugging
+ messages can reach various consoles while the rest
+ of the system is being put to sleep (ie, while
+ debugging driver suspend/resume hooks). This may
+ not work reliably with all consoles, but is known
+ to work with serial and VGA consoles.
+
cpcihp_generic= [HW,PCI] Generic port I/O CompactPCI driver
Format:
<first_slot>,<last_slot>,<port>,<enum_bit>[,<debug>]
@@ -474,6 +488,13 @@ and is between 256 and 4096 characters. It is defined in the file
[KNL] Reserve a chunk of physical memory to
hold a kernel to switch to with kexec on panic.
+ crashkernel=range1:size1[,range2:size2,...][@offset]
+ [KNL] Same as above, but depends on the memory
+ in the running system. The syntax of range is
+ start-[end] where start and end are both
+ a memory unit (amount[KMG]). See also
+ Documentation/kdump/kdump.txt for a example.
+
cs4232= [HW,OSS]
Format: <io>,<irq>,<dma>,<dma2>,<mpuio>,<mpuirq>
@@ -483,8 +504,6 @@ and is between 256 and 4096 characters. It is defined in the file
cs89x0_media= [HW,NET]
Format: { rj45 | aui | bnc }
- cyclades= [HW,SERIAL] Cyclades multi-serial port adapter.
-
dasd= [HW,NET]
See header of drivers/s390/block/dasd_devmap.c.
@@ -542,10 +561,6 @@ and is between 256 and 4096 characters. It is defined in the file
See drivers/char/README.epca and
Documentation/digiepca.txt.
- dmascc= [HW,AX25,SERIAL] AX.25 Z80SCC driver with DMA
- support available.
- Format: <io_dev0>[,<io_dev1>[,..<io_dev32>]]
-
dmasound= [HW,OSS] Sound subsystem buffers
dscc4.setup= [NET]
@@ -571,22 +586,10 @@ and is between 256 and 4096 characters. It is defined in the file
eata= [HW,SCSI]
- ec_intr= [HW,ACPI] ACPI Embedded Controller interrupt mode
- Format: <int>
- 0: polling mode
- non-0: interrupt mode (default)
-
- eda= [HW,PS2]
-
- edb= [HW,PS2]
-
edd= [EDD]
Format: {"of[f]" | "sk[ipmbr]"}
See comment in arch/i386/boot/edd.S
- eicon= [HW,ISDN]
- Format: <id>,<membase>,<irq>
-
eisa_irq_edge= [PARISC,HW]
See header of drivers/parisc/eisa.c.
@@ -765,6 +768,23 @@ and is between 256 and 4096 characters. It is defined in the file
inttest= [IA64]
+ intel_iommu= [DMAR] Intel IOMMU driver (DMAR) option
+ off
+ Disable intel iommu driver.
+ igfx_off [Default Off]
+ By default, gfx is mapped as normal device. If a gfx
+ device has a dedicated DMAR unit, the DMAR unit is
+ bypassed by not enabling DMAR with this option. In
+ this case, gfx device will use physical address for
+ DMA.
+ forcedac [x86_64]
+ With this option iommu will not optimize to look
+ for io virtual address below 32 bit forcing dual
+ address cycle on pci bus for cards supporting greater
+ than 32 bit addressing. The default is to look
+ for translation below 32 bit and if not available
+ then look in the higher range.
+
io7= [HW] IO7 for Marvel based alpha systems
See comment before marvel_specify_io7 in
arch/alpha/kernel/core_marvel.c.
@@ -862,9 +882,6 @@ and is between 256 and 4096 characters. It is defined in the file
lapic_timer_c2_ok [X86-32,x86-64,APIC] trust the local apic timer in
C2 power state.
- lasi= [HW,SCSI] PARISC LASI driver for the 53c700 chip
- Format: addr:<io>,irq:<irq>
-
libata.noacpi [LIBATA] Disables use of ACPI in libata suspend/resume
when set.
Format: <int>
@@ -906,6 +923,11 @@ and is between 256 and 4096 characters. It is defined in the file
n must be a power of two. The default size
is set in the kernel config file.
+ logo.nologo [FB] Disables display of the built-in Linux logo.
+ This may be used to provide more screen space for
+ kernel log messages and is useful when debugging
+ kernel boot problems.
+
lp=0 [LP] Specify parallel ports to use, e.g,
lp=port[,port...] lp=none,parport0 (lp0 not configured, lp1 uses
lp=reset first parallel port). 'lp=0' disables the
@@ -976,6 +998,8 @@ and is between 256 and 4096 characters. It is defined in the file
mce [X86-32] Machine Check Exception
+ mce=option [X86-64] See Documentation/x86_64/boot-options.txt
+
md= [HW] RAID subsystems devices and level
See Documentation/md.txt.
@@ -1105,9 +1129,6 @@ and is between 256 and 4096 characters. It is defined in the file
noapic [SMP,APIC] Tells the kernel to not make use of any
IOAPICs that may be present in the system.
- noasync [HW,M68K] Disables async and sync negotiation for
- all devices.
-
nobats [PPC] Do not use BATs for mapping kernel lowmem
on "Classic" PPC cores.
@@ -1418,7 +1439,9 @@ and is between 256 and 4096 characters. It is defined in the file
Param: "schedule" - profile schedule points.
Param: <number> - step/bucket size as a power of 2 for
statistical time based profiling.
- Param: "sleep" - profile D-state sleeping (millisecs)
+ Param: "sleep" - profile D-state sleeping (millisecs).
+ Requires CONFIG_SCHEDSTATS
+ Param: "kvm" - profile VM exits.
processor.max_cstate= [HW,ACPI]
Limit processor to maximum C-state
@@ -1463,14 +1486,10 @@ and is between 256 and 4096 characters. It is defined in the file
raid= [HW,RAID]
See Documentation/md.txt.
- ramdisk= [RAM] Sizes of RAM disks in kilobytes [deprecated]
- See Documentation/ramdisk.txt.
-
ramdisk_blocksize= [RAM]
See Documentation/ramdisk.txt.
ramdisk_size= [RAM] Sizes of RAM disks in kilobytes
- New name for the ramdisk parameter.
See Documentation/ramdisk.txt.
rcu.blimit= [KNL,BOOT] Set maximum number of finished
@@ -1533,6 +1552,15 @@ and is between 256 and 4096 characters. It is defined in the file
Useful for devices that are detected asynchronously
(e.g. USB and MMC devices).
+ root_plug.vendor_id=
+ [ROOTPLUG] Override the default vendor ID
+
+ root_plug.product_id=
+ [ROOTPLUG] Override the default product ID
+
+ root_plug.debug=
+ [ROOTPLUG] Enable debugging output
+
rw [KNL] Mount root device read-write on boot
S [KNL] Run init in single mode
@@ -1540,9 +1568,6 @@ and is between 256 and 4096 characters. It is defined in the file
sa1100ir [NET]
See drivers/net/irda/sa1100_ir.c.
- sb= [HW,OSS]
- Format: <io>,<irq>,<dma>,<dma2>
-
sbni= [NET] Granch SBNI12 leased line adapter
sc1200wdt= [HW,WDT] SC1200 WDT (watchdog) driver
@@ -1586,8 +1611,6 @@ and is between 256 and 4096 characters. It is defined in the file
serialnumber [BUGS=X86-32]
- sg_def_reserved_size= [SCSI]
-
shapers= [NET]
Maximal number of shapers.
@@ -1890,9 +1913,6 @@ and is between 256 and 4096 characters. It is defined in the file
Format:
<io>,<irq>,<dma>,<dma2>,<sb_io>,<sb_irq>,<sb_dma>,<mpu_io>,<mpu_irq>
- tsdev.xres= [TS] Horizontal screen resolution.
- tsdev.yres= [TS] Vertical screen resolution.
-
turbografx.map[2|3]= [HW,JOY]
TurboGraFX parallel port interface
Format:
@@ -1981,10 +2001,6 @@ and is between 256 and 4096 characters. It is defined in the file
norandmaps Don't use address space randomization
Equivalent to echo 0 > /proc/sys/kernel/randomize_va_space
- unwind_debug=N N > 0 will enable dwarf2 unwinder debugging
- This is useful to get more information why
- you got a "dwarf2 unwinder stuck"
-
______________________________________________________________________
TODO:
diff --git a/Documentation/keys-request-key.txt b/Documentation/keys-request-key.txt
index c1f64fdf84cb..266955d23ee6 100644
--- a/Documentation/keys-request-key.txt
+++ b/Documentation/keys-request-key.txt
@@ -20,6 +20,19 @@ or:
const char *callout_string,
void *aux);
+or:
+
+ struct key *request_key_async(const struct key_type *type,
+ const char *description,
+ const char *callout_string);
+
+or:
+
+ struct key *request_key_async_with_auxdata(const struct key_type *type,
+ const char *description,
+ const char *callout_string,
+ void *aux);
+
Or by userspace invoking the request_key system call:
key_serial_t request_key(const char *type,
@@ -32,10 +45,14 @@ does not need to link the key to a keyring to prevent it from being immediately
destroyed. The kernel interface returns a pointer directly to the key, and
it's up to the caller to destroy the key.
-The request_key_with_auxdata() call is like the in-kernel request_key() call,
-except that it permits auxiliary data to be passed to the upcaller (the default
-is NULL). This is only useful for those key types that define their own upcall
-mechanism rather than using /sbin/request-key.
+The request_key*_with_auxdata() calls are like the in-kernel request_key*()
+calls, except that they permit auxiliary data to be passed to the upcaller (the
+default is NULL). This is only useful for those key types that define their
+own upcall mechanism rather than using /sbin/request-key.
+
+The two async in-kernel calls may return keys that are still in the process of
+being constructed. The two non-async ones will wait for construction to
+complete first.
The userspace interface links the key to a keyring associated with the process
to prevent the key from going away, and returns the serial number of the key to
diff --git a/Documentation/keys.txt b/Documentation/keys.txt
index 947d57d53453..51652d39e61c 100644
--- a/Documentation/keys.txt
+++ b/Documentation/keys.txt
@@ -4,7 +4,7 @@
This service allows cryptographic keys, authentication tokens, cross-domain
user mappings, and similar to be cached in the kernel for the use of
-filesystems other kernel services.
+filesystems and other kernel services.
Keyrings are permitted; these are a special type of key that can hold links to
other keys. Processes each have three standard keyring subscriptions that a
@@ -726,6 +726,15 @@ call, and the key released upon close. How to deal with conflicting keys due to
two different users opening the same file is left to the filesystem author to
solve.
+To access the key manager, the following header must be #included:
+
+ <linux/key.h>
+
+Specific key types should have a header file under include/keys/ that should be
+used to access that type. For keys of type "user", for example, that would be:
+
+ <keys/user-type.h>
+
Note that there are two different types of pointers to keys that may be
encountered:
@@ -791,6 +800,36 @@ payload contents" for more information.
passed to the key_type->request_key() op if it exists.
+(*) A key can be requested asynchronously by calling one of:
+
+ struct key *request_key_async(const struct key_type *type,
+ const char *description,
+ const char *callout_string);
+
+ or:
+
+ struct key *request_key_async_with_auxdata(const struct key_type *type,
+ const char *description,
+ const char *callout_string,
+ void *aux);
+
+ which are asynchronous equivalents of request_key() and
+ request_key_with_auxdata() respectively.
+
+ These two functions return with the key potentially still under
+ construction. To wait for contruction completion, the following should be
+ called:
+
+ int wait_for_key_construction(struct key *key, bool intr);
+
+ The function will wait for the key to finish being constructed and then
+ invokes key_validate() to return an appropriate value to indicate the state
+ of the key (0 indicates the key is usable).
+
+ If intr is true, then the wait can be interrupted by a signal, in which
+ case error ERESTARTSYS will be returned.
+
+
(*) When it is no longer required, the key should be released using:
void key_put(struct key *key);
@@ -924,7 +963,11 @@ DEFINING A KEY TYPE
A kernel service may want to define its own key type. For instance, an AFS
filesystem might want to define a Kerberos 5 ticket key type. To do this, it
-author fills in a struct key_type and registers it with the system.
+author fills in a key_type struct and registers it with the system.
+
+Source files that implement key types should include the following header file:
+
+ <linux/key-type.h>
The structure has a number of fields, some of which are mandatory:
@@ -1053,22 +1096,44 @@ The structure has a number of fields, some of which are mandatory:
as might happen when the userspace buffer is accessed.
- (*) int (*request_key)(struct key *key, struct key *authkey, const char *op,
+ (*) int (*request_key)(struct key_construction *cons, const char *op,
void *aux);
- This method is optional. If provided, request_key() and
- request_key_with_auxdata() will invoke this function rather than
- upcalling to /sbin/request-key to operate upon a key of this type.
+ This method is optional. If provided, request_key() and friends will
+ invoke this function rather than upcalling to /sbin/request-key to operate
+ upon a key of this type.
+
+ The aux parameter is as passed to request_key_async_with_auxdata() and
+ similar or is NULL otherwise. Also passed are the construction record for
+ the key to be operated upon and the operation type (currently only
+ "create").
+
+ This method is permitted to return before the upcall is complete, but the
+ following function must be called under all circumstances to complete the
+ instantiation process, whether or not it succeeds, whether or not there's
+ an error:
+
+ void complete_request_key(struct key_construction *cons, int error);
+
+ The error parameter should be 0 on success, -ve on error. The
+ construction record is destroyed by this action and the authorisation key
+ will be revoked. If an error is indicated, the key under construction
+ will be negatively instantiated if it wasn't already instantiated.
+
+ If this method returns an error, that error will be returned to the
+ caller of request_key*(). complete_request_key() must be called prior to
+ returning.
+
+ The key under construction and the authorisation key can be found in the
+ key_construction struct pointed to by cons:
+
+ (*) struct key *key;
+
+ The key under construction.
- The aux parameter is as passed to request_key_with_auxdata() or is NULL
- otherwise. Also passed are the key to be operated upon, the
- authorisation key for this operation and the operation type (currently
- only "create").
+ (*) struct key *authkey;
- This function should return only when the upcall is complete. Upon return
- the authorisation key will be revoked, and the target key will be
- negatively instantiated if it is still uninstantiated. The error will be
- returned to the caller of request_key*().
+ The authorisation key.
============================
diff --git a/Documentation/lguest/Makefile b/Documentation/lguest/Makefile
index c0b7a4556390..bac037eb1cda 100644
--- a/Documentation/lguest/Makefile
+++ b/Documentation/lguest/Makefile
@@ -1,28 +1,8 @@
# This creates the demonstration utility "lguest" which runs a Linux guest.
-
-# For those people that have a separate object dir, look there for .config
-KBUILD_OUTPUT := ../..
-ifdef O
- ifeq ("$(origin O)", "command line")
- KBUILD_OUTPUT := $(O)
- endif
-endif
-# We rely on CONFIG_PAGE_OFFSET to know where to put lguest binary.
-include $(KBUILD_OUTPUT)/.config
-LGUEST_GUEST_TOP := ($(CONFIG_PAGE_OFFSET) - 0x08000000)
-
-CFLAGS:=-Wall -Wmissing-declarations -Wmissing-prototypes -O3 -Wl,-T,lguest.lds
+CFLAGS:=-Wall -Wmissing-declarations -Wmissing-prototypes -O3 -I../../include
LDLIBS:=-lz
-# Removing this works for some versions of ld.so (eg. Ubuntu Feisty) and
-# not others (eg. FC7).
-LDFLAGS+=-static
-all: lguest.lds lguest
-# The linker script on x86 is so complex the only way of creating one
-# which will link our binary in the right place is to mangle the
-# default one.
-lguest.lds:
- $(LD) --verbose | awk '/^==========/ { PRINT=1; next; } /SIZEOF_HEADERS/ { gsub(/0x[0-9A-F]*/, "$(LGUEST_GUEST_TOP)") } { if (PRINT) print $$0; }' > $@
+all: lguest
clean:
- rm -f lguest.lds lguest
+ rm -f lguest
diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c
index 103e346c8b6a..42008395534d 100644
--- a/Documentation/lguest/lguest.c
+++ b/Documentation/lguest/lguest.c
@@ -1,10 +1,7 @@
/*P:100 This is the Launcher code, a simple program which lays out the
* "physical" memory for the new Guest by mapping the kernel image and the
* virtual devices, then reads repeatedly from /dev/lguest to run the Guest.
- *
- * The only trick: the Makefile links it at a high address so it will be clear
- * of the guest memory region. It means that each Guest cannot have more than
- * about 2.5G of memory on a normally configured Host. :*/
+:*/
#define _LARGEFILE64_SOURCE
#define _GNU_SOURCE
#include <stdio.h>
@@ -15,6 +12,7 @@
#include <stdlib.h>
#include <elf.h>
#include <sys/mman.h>
+#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
@@ -34,19 +32,26 @@
#include <termios.h>
#include <getopt.h>
#include <zlib.h>
-/*L:110 We can ignore the 28 include files we need for this program, but I do
+#include <assert.h>
+#include <sched.h>
+#include "linux/lguest_launcher.h"
+#include "linux/virtio_config.h"
+#include "linux/virtio_net.h"
+#include "linux/virtio_blk.h"
+#include "linux/virtio_console.h"
+#include "linux/virtio_ring.h"
+#include "asm-x86/bootparam.h"
+/*L:110 We can ignore the 38 include files we need for this program, but I do
* want to draw attention to the use of kernel-style types.
*
* As Linus said, "C is a Spartan language, and so should your naming be." I
- * like these abbreviations and the header we need uses them, so we define them
- * here.
- */
+ * like these abbreviations, so we define them here. Note that u64 is always
+ * unsigned long long, which works on all Linux systems: this means that we can
+ * use %llu in printf for any u64. */
typedef unsigned long long u64;
typedef uint32_t u32;
typedef uint16_t u16;
typedef uint8_t u8;
-#include "../../include/linux/lguest_launcher.h"
-#include "../../include/asm-x86/e820_32.h"
/*:*/
#define PAGE_PRESENT 0x7 /* Present, RW, Execute */
@@ -55,6 +60,10 @@ typedef uint8_t u8;
#ifndef SIOCBRADDIF
#define SIOCBRADDIF 0x89a2 /* add interface to bridge */
#endif
+/* We can have up to 256 pages for devices. */
+#define DEVICE_PAGES 256
+/* This will occupy 2 pages: it must be a power of 2. */
+#define VIRTQUEUE_NUM 128
/*L:120 verbose is both a global flag and a macro. The C preprocessor allows
* this, and although I wouldn't recommend it, it works quite nicely here. */
@@ -65,8 +74,10 @@ static bool verbose;
/* The pipe to send commands to the waker process */
static int waker_fd;
-/* The top of guest physical memory. */
-static u32 top;
+/* The pointer to the start of guest memory. */
+static void *guest_base;
+/* The maximum guest physical address allowed, and maximum possible. */
+static unsigned long guest_limit, guest_max;
/* This is our list of devices. */
struct device_list
@@ -76,8 +87,17 @@ struct device_list
fd_set infds;
int max_infd;
+ /* Counter to assign interrupt numbers. */
+ unsigned int next_irq;
+
+ /* Counter to print out convenient device numbers. */
+ unsigned int device_num;
+
/* The descriptor page for the devices. */
- struct lguest_device_desc *descs;
+ u8 *descpage;
+
+ /* The tail of the last descriptor. */
+ unsigned int desc_used;
/* A single linked list of devices. */
struct device *dev;
@@ -85,31 +105,111 @@ struct device_list
struct device **lastdev;
};
+/* The list of Guest devices, based on command line arguments. */
+static struct device_list devices;
+
/* The device structure describes a single device. */
struct device
{
/* The linked-list pointer. */
struct device *next;
- /* The descriptor for this device, as mapped into the Guest. */
+
+ /* The this device's descriptor, as mapped into the Guest. */
struct lguest_device_desc *desc;
- /* The memory page(s) of this device, if any. Also mapped in Guest. */
- void *mem;
+
+ /* The name of this device, for --verbose. */
+ const char *name;
/* If handle_input is set, it wants to be called when this file
* descriptor is ready. */
int fd;
bool (*handle_input)(int fd, struct device *me);
- /* If handle_output is set, it wants to be called when the Guest sends
- * DMA to this key. */
- unsigned long watch_key;
- u32 (*handle_output)(int fd, const struct iovec *iov,
- unsigned int num, struct device *me);
+ /* Any queues attached to this device */
+ struct virtqueue *vq;
/* Device-specific data. */
void *priv;
};
+/* The virtqueue structure describes a queue attached to a device. */
+struct virtqueue
+{
+ struct virtqueue *next;
+
+ /* Which device owns me. */
+ struct device *dev;
+
+ /* The configuration for this queue. */
+ struct lguest_vqconfig config;
+
+ /* The actual ring of buffers. */
+ struct vring vring;
+
+ /* Last available index we saw. */
+ u16 last_avail_idx;
+
+ /* The routine to call when the Guest pings us. */
+ void (*handle_output)(int fd, struct virtqueue *me);
+};
+
+/* Since guest is UP and we don't run at the same time, we don't need barriers.
+ * But I include them in the code in case others copy it. */
+#define wmb()
+
+/* Convert an iovec element to the given type.
+ *
+ * This is a fairly ugly trick: we need to know the size of the type and
+ * alignment requirement to check the pointer is kosher. It's also nice to
+ * have the name of the type in case we report failure.
+ *
+ * Typing those three things all the time is cumbersome and error prone, so we
+ * have a macro which sets them all up and passes to the real function. */
+#define convert(iov, type) \
+ ((type *)_convert((iov), sizeof(type), __alignof__(type), #type))
+
+static void *_convert(struct iovec *iov, size_t size, size_t align,
+ const char *name)
+{
+ if (iov->iov_len != size)
+ errx(1, "Bad iovec size %zu for %s", iov->iov_len, name);
+ if ((unsigned long)iov->iov_base % align != 0)
+ errx(1, "Bad alignment %p for %s", iov->iov_base, name);
+ return iov->iov_base;
+}
+
+/* The virtio configuration space is defined to be little-endian. x86 is
+ * little-endian too, but it's nice to be explicit so we have these helpers. */
+#define cpu_to_le16(v16) (v16)
+#define cpu_to_le32(v32) (v32)
+#define cpu_to_le64(v64) (v64)
+#define le16_to_cpu(v16) (v16)
+#define le32_to_cpu(v32) (v32)
+#define le64_to_cpu(v32) (v64)
+
+/*L:100 The Launcher code itself takes us out into userspace, that scary place
+ * where pointers run wild and free! Unfortunately, like most userspace
+ * programs, it's quite boring (which is why everyone likes to hack on the
+ * kernel!). Perhaps if you make up an Lguest Drinking Game at this point, it
+ * will get you through this section. Or, maybe not.
+ *
+ * The Launcher sets up a big chunk of memory to be the Guest's "physical"
+ * memory and stores it in "guest_base". In other words, Guest physical ==
+ * Launcher virtual with an offset.
+ *
+ * This can be tough to get your head around, but usually it just means that we
+ * use these trivial conversion functions when the Guest gives us it's
+ * "physical" addresses: */
+static void *from_guest_phys(unsigned long addr)
+{
+ return guest_base + addr;
+}
+
+static unsigned long to_guest_phys(const void *addr)
+{
+ return (addr - guest_base);
+}
+
/*L:130
* Loading the Kernel.
*
@@ -123,43 +223,55 @@ static int open_or_die(const char *name, int flags)
return fd;
}
-/* map_zeroed_pages() takes a (page-aligned) address and a number of pages. */
-static void *map_zeroed_pages(unsigned long addr, unsigned int num)
+/* map_zeroed_pages() takes a number of pages. */
+static void *map_zeroed_pages(unsigned int num)
{
- /* We cache the /dev/zero file-descriptor so we only open it once. */
- static int fd = -1;
-
- if (fd == -1)
- fd = open_or_die("/dev/zero", O_RDONLY);
+ int fd = open_or_die("/dev/zero", O_RDONLY);
+ void *addr;
/* We use a private mapping (ie. if we write to the page, it will be
- * copied), and obviously we insist that it be mapped where we ask. */
- if (mmap((void *)addr, getpagesize() * num,
- PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_PRIVATE, fd, 0)
- != (void *)addr)
- err(1, "Mmaping %u pages of /dev/zero @%p", num, (void *)addr);
-
- /* Returning the address is just a courtesy: can simplify callers. */
- return (void *)addr;
+ * copied). */
+ addr = mmap(NULL, getpagesize() * num,
+ PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, fd, 0);
+ if (addr == MAP_FAILED)
+ err(1, "Mmaping %u pages of /dev/zero", num);
+
+ return addr;
}
-/* To find out where to start we look for the magic Guest string, which marks
- * the code we see in lguest_asm.S. This is a hack which we are currently
- * plotting to replace with the normal Linux entry point. */
-static unsigned long entry_point(void *start, void *end,
- unsigned long page_offset)
+/* Get some more pages for a device. */
+static void *get_pages(unsigned int num)
{
- void *p;
+ void *addr = from_guest_phys(guest_limit);
- /* The scan gives us the physical starting address. We want the
- * virtual address in this case, and fortunately, we already figured
- * out the physical-virtual difference and passed it here in
- * "page_offset". */
- for (p = start; p < end; p++)
- if (memcmp(p, "GenuineLguest", strlen("GenuineLguest")) == 0)
- return (long)p + strlen("GenuineLguest") + page_offset;
+ guest_limit += num * getpagesize();
+ if (guest_limit > guest_max)
+ errx(1, "Not enough memory for devices");
+ return addr;
+}
- err(1, "Is this image a genuine lguest?");
+/* This routine is used to load the kernel or initrd. It tries mmap, but if
+ * that fails (Plan 9's kernel file isn't nicely aligned on page boundaries),
+ * it falls back to reading the memory in. */
+static void map_at(int fd, void *addr, unsigned long offset, unsigned long len)
+{
+ ssize_t r;
+
+ /* We map writable even though for some segments are marked read-only.
+ * The kernel really wants to be writable: it patches its own
+ * instructions.
+ *
+ * MAP_PRIVATE means that the page won't be copied until a write is
+ * done to it. This allows us to share untouched memory between
+ * Guests. */
+ if (mmap(addr, len, PROT_READ|PROT_WRITE|PROT_EXEC,
+ MAP_FIXED|MAP_PRIVATE, fd, offset) != MAP_FAILED)
+ return;
+
+ /* pread does a seek and a read in one shot: saves a few lines. */
+ r = pread(fd, addr, len, offset);
+ if (r != len)
+ err(1, "Reading offset %lu len %lu gave %zi", offset, len, r);
}
/* This routine takes an open vmlinux image, which is in ELF, and maps it into
@@ -167,19 +279,14 @@ static unsigned long entry_point(void *start, void *end,
* by all modern binaries on Linux including the kernel.
*
* The ELF headers give *two* addresses: a physical address, and a virtual
- * address. The Guest kernel expects to be placed in memory at the physical
- * address, and the page tables set up so it will correspond to that virtual
- * address. We return the difference between the virtual and physical
- * addresses in the "page_offset" pointer.
+ * address. We use the physical address; the Guest will map itself to the
+ * virtual address.
*
* We return the starting address. */
-static unsigned long map_elf(int elf_fd, const Elf32_Ehdr *ehdr,
- unsigned long *page_offset)
+static unsigned long map_elf(int elf_fd, const Elf32_Ehdr *ehdr)
{
- void *addr;
Elf32_Phdr phdr[ehdr->e_phnum];
unsigned int i;
- unsigned long start = -1UL, end = 0;
/* Sanity checks on the main ELF header: an x86 executable with a
* reasonable number of correctly-sized program headers. */
@@ -199,9 +306,6 @@ static unsigned long map_elf(int elf_fd, const Elf32_Ehdr *ehdr,
if (read(elf_fd, phdr, sizeof(phdr)) != sizeof(phdr))
err(1, "Reading program headers");
- /* We don't know page_offset yet. */
- *page_offset = 0;
-
/* Try all the headers: there are usually only three. A read-only one,
* a read-write one, and a "note" section which isn't loadable. */
for (i = 0; i < ehdr->e_phnum; i++) {
@@ -212,158 +316,53 @@ static unsigned long map_elf(int elf_fd, const Elf32_Ehdr *ehdr,
verbose("Section %i: size %i addr %p\n",
i, phdr[i].p_memsz, (void *)phdr[i].p_paddr);
- /* We expect a simple linear address space: every segment must
- * have the same difference between virtual (p_vaddr) and
- * physical (p_paddr) address. */
- if (!*page_offset)
- *page_offset = phdr[i].p_vaddr - phdr[i].p_paddr;
- else if (*page_offset != phdr[i].p_vaddr - phdr[i].p_paddr)
- errx(1, "Page offset of section %i different", i);
-
- /* We track the first and last address we mapped, so we can
- * tell entry_point() where to scan. */
- if (phdr[i].p_paddr < start)
- start = phdr[i].p_paddr;
- if (phdr[i].p_paddr + phdr[i].p_filesz > end)
- end = phdr[i].p_paddr + phdr[i].p_filesz;
-
- /* We map this section of the file at its physical address. We
- * map it read & write even if the header says this segment is
- * read-only. The kernel really wants to be writable: it
- * patches its own instructions which would normally be
- * read-only.
- *
- * MAP_PRIVATE means that the page won't be copied until a
- * write is done to it. This allows us to share much of the
- * kernel memory between Guests. */
- addr = mmap((void *)phdr[i].p_paddr,
- phdr[i].p_filesz,
- PROT_READ|PROT_WRITE|PROT_EXEC,
- MAP_FIXED|MAP_PRIVATE,
- elf_fd, phdr[i].p_offset);
- if (addr != (void *)phdr[i].p_paddr)
- err(1, "Mmaping vmlinux seg %i gave %p not %p",
- i, addr, (void *)phdr[i].p_paddr);
+ /* We map this section of the file at its physical address. */
+ map_at(elf_fd, from_guest_phys(phdr[i].p_paddr),
+ phdr[i].p_offset, phdr[i].p_filesz);
}
- return entry_point((void *)start, (void *)end, *page_offset);
+ /* The entry point is given in the ELF header. */
+ return ehdr->e_entry;
}
-/*L:170 Prepare to be SHOCKED and AMAZED. And possibly a trifle nauseated.
- *
- * We know that CONFIG_PAGE_OFFSET sets what virtual address the kernel expects
- * to be. We don't know what that option was, but we can figure it out
- * approximately by looking at the addresses in the code. I chose the common
- * case of reading a memory location into the %eax register:
- *
- * movl <some-address>, %eax
- *
- * This gets encoded as five bytes: "0xA1 <4-byte-address>". For example,
- * "0xA1 0x18 0x60 0x47 0xC0" reads the address 0xC0476018 into %eax.
- *
- * In this example can guess that the kernel was compiled with
- * CONFIG_PAGE_OFFSET set to 0xC0000000 (it's always a round number). If the
- * kernel were larger than 16MB, we might see 0xC1 addresses show up, but our
- * kernel isn't that bloated yet.
- *
- * Unfortunately, x86 has variable-length instructions, so finding this
- * particular instruction properly involves writing a disassembler. Instead,
- * we rely on statistics. We look for "0xA1" and tally the different bytes
- * which occur 4 bytes later (the "0xC0" in our example above). When one of
- * those bytes appears three times, we can be reasonably confident that it
- * forms the start of CONFIG_PAGE_OFFSET.
+/*L:150 A bzImage, unlike an ELF file, is not meant to be loaded. You're
+ * supposed to jump into it and it will unpack itself. We used to have to
+ * perform some hairy magic because the unpacking code scared me.
*
- * This is amazingly reliable. */
-static unsigned long intuit_page_offset(unsigned char *img, unsigned long len)
+ * Fortunately, Jeremy Fitzhardinge convinced me it wasn't that hard and wrote
+ * a small patch to jump over the tricky bits in the Guest, so now we just read
+ * the funky header so we know where in the file to load, and away we go! */
+static unsigned long load_bzimage(int fd)
{
- unsigned int i, possibilities[256] = { 0 };
+ struct boot_params boot;
+ int r;
+ /* Modern bzImages get loaded at 1M. */
+ void *p = from_guest_phys(0x100000);
- for (i = 0; i + 4 < len; i++) {
- /* mov 0xXXXXXXXX,%eax */
- if (img[i] == 0xA1 && ++possibilities[img[i+4]] > 3)
- return (unsigned long)img[i+4] << 24;
- }
- errx(1, "could not determine page offset");
-}
+ /* Go back to the start of the file and read the header. It should be
+ * a Linux boot header (see Documentation/i386/boot.txt) */
+ lseek(fd, 0, SEEK_SET);
+ read(fd, &boot, sizeof(boot));
-/*L:160 Unfortunately the entire ELF image isn't compressed: the segments
- * which need loading are extracted and compressed raw. This denies us the
- * information we need to make a fully-general loader. */
-static unsigned long unpack_bzimage(int fd, unsigned long *page_offset)
-{
- gzFile f;
- int ret, len = 0;
- /* A bzImage always gets loaded at physical address 1M. This is
- * actually configurable as CONFIG_PHYSICAL_START, but as the comment
- * there says, "Don't change this unless you know what you are doing".
- * Indeed. */
- void *img = (void *)0x100000;
-
- /* gzdopen takes our file descriptor (carefully placed at the start of
- * the GZIP header we found) and returns a gzFile. */
- f = gzdopen(fd, "rb");
- /* We read it into memory in 64k chunks until we hit the end. */
- while ((ret = gzread(f, img + len, 65536)) > 0)
- len += ret;
- if (ret < 0)
- err(1, "reading image from bzImage");
-
- verbose("Unpacked size %i addr %p\n", len, img);
-
- /* Without the ELF header, we can't tell virtual-physical gap. This is
- * CONFIG_PAGE_OFFSET, and people do actually change it. Fortunately,
- * I have a clever way of figuring it out from the code itself. */
- *page_offset = intuit_page_offset(img, len);
-
- return entry_point(img, img + len, *page_offset);
-}
+ /* Inside the setup_hdr, we expect the magic "HdrS" */
+ if (memcmp(&boot.hdr.header, "HdrS", 4) != 0)
+ errx(1, "This doesn't look like a bzImage to me");
-/*L:150 A bzImage, unlike an ELF file, is not meant to be loaded. You're
- * supposed to jump into it and it will unpack itself. We can't do that
- * because the Guest can't run the unpacking code, and adding features to
- * lguest kills puppies, so we don't want to.
- *
- * The bzImage is formed by putting the decompressing code in front of the
- * compressed kernel code. So we can simple scan through it looking for the
- * first "gzip" header, and start decompressing from there. */
-static unsigned long load_bzimage(int fd, unsigned long *page_offset)
-{
- unsigned char c;
- int state = 0;
-
- /* GZIP header is 0x1F 0x8B <method> <flags>... <compressed-by>. */
- while (read(fd, &c, 1) == 1) {
- switch (state) {
- case 0:
- if (c == 0x1F)
- state++;
- break;
- case 1:
- if (c == 0x8B)
- state++;
- else
- state = 0;
- break;
- case 2 ... 8:
- state++;
- break;
- case 9:
- /* Seek back to the start of the gzip header. */
- lseek(fd, -10, SEEK_CUR);
- /* One final check: "compressed under UNIX". */
- if (c != 0x03)
- state = -1;
- else
- return unpack_bzimage(fd, page_offset);
- }
- }
- errx(1, "Could not find kernel in bzImage");
+ /* Skip over the extra sectors of the header. */
+ lseek(fd, (boot.hdr.setup_sects+1) * 512, SEEK_SET);
+
+ /* Now read everything into memory. in nice big chunks. */
+ while ((r = read(fd, p, 65536)) > 0)
+ p += r;
+
+ /* Finally, code32_start tells us where to enter the kernel. */
+ return boot.hdr.code32_start;
}
/*L:140 Loading the kernel is easy when it's a "vmlinux", but most kernels
- * come wrapped up in the self-decompressing "bzImage" format. With some funky
- * coding, we can load those, too. */
-static unsigned long load_kernel(int fd, unsigned long *page_offset)
+ * come wrapped up in the self-decompressing "bzImage" format. With a little
+ * work, we can load those, too. */
+static unsigned long load_kernel(int fd)
{
Elf32_Ehdr hdr;
@@ -373,10 +372,10 @@ static unsigned long load_kernel(int fd, unsigned long *page_offset)
/* If it's an ELF file, it starts with "\177ELF" */
if (memcmp(hdr.e_ident, ELFMAG, SELFMAG) == 0)
- return map_elf(fd, &hdr, page_offset);
+ return map_elf(fd, &hdr);
/* Otherwise we assume it's a bzImage, and try to unpack it */
- return load_bzimage(fd, page_offset);
+ return load_bzimage(fd);
}
/* This is a trivial little helper to align pages. Andi Kleen hated it because
@@ -402,59 +401,45 @@ static unsigned long load_initrd(const char *name, unsigned long mem)
int ifd;
struct stat st;
unsigned long len;
- void *iaddr;
ifd = open_or_die(name, O_RDONLY);
/* fstat() is needed to get the file size. */
if (fstat(ifd, &st) < 0)
err(1, "fstat() on initrd '%s'", name);
- /* The length needs to be rounded up to a page size: mmap needs the
- * address to be page aligned. */
+ /* We map the initrd at the top of memory, but mmap wants it to be
+ * page-aligned, so we round the size up for that. */
len = page_align(st.st_size);
- /* We map the initrd at the top of memory. */
- iaddr = mmap((void *)mem - len, st.st_size,
- PROT_READ|PROT_EXEC|PROT_WRITE,
- MAP_FIXED|MAP_PRIVATE, ifd, 0);
- if (iaddr != (void *)mem - len)
- err(1, "Mmaping initrd '%s' returned %p not %p",
- name, iaddr, (void *)mem - len);
+ map_at(ifd, from_guest_phys(mem - len), 0, st.st_size);
/* Once a file is mapped, you can close the file descriptor. It's a
* little odd, but quite useful. */
close(ifd);
- verbose("mapped initrd %s size=%lu @ %p\n", name, st.st_size, iaddr);
+ verbose("mapped initrd %s size=%lu @ %p\n", name, len, (void*)mem-len);
/* We return the initrd size. */
return len;
}
-/* Once we know how much memory we have, and the address the Guest kernel
- * expects, we can construct simple linear page tables which will get the Guest
- * far enough into the boot to create its own.
+/* Once we know how much memory we have, we can construct simple linear page
+ * tables which set virtual == physical which will get the Guest far enough
+ * into the boot to create its own.
*
* We lay them out of the way, just below the initrd (which is why we need to
* know its size). */
static unsigned long setup_pagetables(unsigned long mem,
- unsigned long initrd_size,
- unsigned long page_offset)
+ unsigned long initrd_size)
{
- u32 *pgdir, *linear;
+ unsigned long *pgdir, *linear;
unsigned int mapped_pages, i, linear_pages;
- unsigned int ptes_per_page = getpagesize()/sizeof(u32);
+ unsigned int ptes_per_page = getpagesize()/sizeof(void *);
- /* Ideally we map all physical memory starting at page_offset.
- * However, if page_offset is 0xC0000000 we can only map 1G of physical
- * (0xC0000000 + 1G overflows). */
- if (mem <= -page_offset)
- mapped_pages = mem/getpagesize();
- else
- mapped_pages = -page_offset/getpagesize();
+ mapped_pages = mem/getpagesize();
/* Each PTE page can map ptes_per_page pages: how many do we need? */
linear_pages = (mapped_pages + ptes_per_page-1)/ptes_per_page;
/* We put the toplevel page directory page at the top of memory. */
- pgdir = (void *)mem - initrd_size - getpagesize();
+ pgdir = from_guest_phys(mem) - initrd_size - getpagesize();
/* Now we use the next linear_pages pages as pte pages */
linear = (void *)pgdir - linear_pages*getpagesize();
@@ -465,21 +450,21 @@ static unsigned long setup_pagetables(unsigned long mem,
for (i = 0; i < mapped_pages; i++)
linear[i] = ((i * getpagesize()) | PAGE_PRESENT);
- /* The top level points to the linear page table pages above. The
- * entry representing page_offset points to the first one, and they
- * continue from there. */
+ /* The top level points to the linear page table pages above. */
for (i = 0; i < mapped_pages; i += ptes_per_page) {
- pgdir[(i + page_offset/getpagesize())/ptes_per_page]
- = (((u32)linear + i*sizeof(u32)) | PAGE_PRESENT);
+ pgdir[i/ptes_per_page]
+ = ((to_guest_phys(linear) + i*sizeof(void *))
+ | PAGE_PRESENT);
}
- verbose("Linear mapping of %u pages in %u pte pages at %p\n",
- mapped_pages, linear_pages, linear);
+ verbose("Linear mapping of %u pages in %u pte pages at %#lx\n",
+ mapped_pages, linear_pages, to_guest_phys(linear));
/* We return the top level (guest-physical) address: the kernel needs
* to know where it is. */
- return (unsigned long)pgdir;
+ return to_guest_phys(pgdir);
}
+/*:*/
/* Simple routine to roll all the commandline arguments together with spaces
* between them. */
@@ -496,16 +481,19 @@ static void concat(char *dst, char *args[])
dst[len] = '\0';
}
-/* This is where we actually tell the kernel to initialize the Guest. We saw
- * the arguments it expects when we looked at initialize() in lguest_user.c:
- * the top physical page to allow, the top level pagetable, the entry point and
- * the page_offset constant for the Guest. */
-static int tell_kernel(u32 pgdir, u32 start, u32 page_offset)
+/*L:185 This is where we actually tell the kernel to initialize the Guest. We
+ * saw the arguments it expects when we looked at initialize() in lguest_user.c:
+ * the base of Guest "physical" memory, the top physical page to allow, the
+ * top level pagetable and the entry point for the Guest. */
+static int tell_kernel(unsigned long pgdir, unsigned long start)
{
- u32 args[] = { LHREQ_INITIALIZE,
- top/getpagesize(), pgdir, start, page_offset };
+ unsigned long args[] = { LHREQ_INITIALIZE,
+ (unsigned long)guest_base,
+ guest_limit / getpagesize(), pgdir, start };
int fd;
+ verbose("Guest: %p - %p (%#lx)\n",
+ guest_base, guest_base + guest_limit, guest_limit);
fd = open_or_die("/dev/lguest", O_RDWR);
if (write(fd, args, sizeof(args)) < 0)
err(1, "Writing to /dev/lguest");
@@ -515,62 +503,67 @@ static int tell_kernel(u32 pgdir, u32 start, u32 page_offset)
}
/*:*/
-static void set_fd(int fd, struct device_list *devices)
+static void add_device_fd(int fd)
{
- FD_SET(fd, &devices->infds);
- if (fd > devices->max_infd)
- devices->max_infd = fd;
+ FD_SET(fd, &devices.infds);
+ if (fd > devices.max_infd)
+ devices.max_infd = fd;
}
/*L:200
* The Waker.
*
- * With a console and network devices, we can have lots of input which we need
- * to process. We could try to tell the kernel what file descriptors to watch,
- * but handing a file descriptor mask through to the kernel is fairly icky.
+ * With console, block and network devices, we can have lots of input which we
+ * need to process. We could try to tell the kernel what file descriptors to
+ * watch, but handing a file descriptor mask through to the kernel is fairly
+ * icky.
*
* Instead, we fork off a process which watches the file descriptors and writes
- * the LHREQ_BREAK command to the /dev/lguest filedescriptor to tell the Host
- * loop to stop running the Guest. This causes it to return from the
+ * the LHREQ_BREAK command to the /dev/lguest file descriptor to tell the Host
+ * stop running the Guest. This causes the Launcher to return from the
* /dev/lguest read with -EAGAIN, where it will write to /dev/lguest to reset
* the LHREQ_BREAK and wake us up again.
*
* This, of course, is merely a different *kind* of icky.
*/
-static void wake_parent(int pipefd, int lguest_fd, struct device_list *devices)
+static void wake_parent(int pipefd, int lguest_fd)
{
/* Add the pipe from the Launcher to the fdset in the device_list, so
* we watch it, too. */
- set_fd(pipefd, devices);
+ add_device_fd(pipefd);
for (;;) {
- fd_set rfds = devices->infds;
- u32 args[] = { LHREQ_BREAK, 1 };
+ fd_set rfds = devices.infds;
+ unsigned long args[] = { LHREQ_BREAK, 1 };
/* Wait until input is ready from one of the devices. */
- select(devices->max_infd+1, &rfds, NULL, NULL, NULL);
+ select(devices.max_infd+1, &rfds, NULL, NULL, NULL);
/* Is it a message from the Launcher? */
if (FD_ISSET(pipefd, &rfds)) {
- int ignorefd;
+ int fd;
/* If read() returns 0, it means the Launcher has
* exited. We silently follow. */
- if (read(pipefd, &ignorefd, sizeof(ignorefd)) == 0)
+ if (read(pipefd, &fd, sizeof(fd)) == 0)
exit(0);
- /* Otherwise it's telling us there's a problem with one
- * of the devices, and we should ignore that file
- * descriptor from now on. */
- FD_CLR(ignorefd, &devices->infds);
+ /* Otherwise it's telling us to change what file
+ * descriptors we're to listen to. Positive means
+ * listen to a new one, negative means stop
+ * listening. */
+ if (fd >= 0)
+ FD_SET(fd, &devices.infds);
+ else
+ FD_CLR(-fd - 1, &devices.infds);
} else /* Send LHREQ_BREAK command. */
write(lguest_fd, args, sizeof(args));
}
}
/* This routine just sets up a pipe to the Waker process. */
-static int setup_waker(int lguest_fd, struct device_list *device_list)
+static int setup_waker(int lguest_fd)
{
int pipefd[2], child;
- /* We create a pipe to talk to the waker, and also so it knows when the
+ /* We create a pipe to talk to the Waker, and also so it knows when the
* Launcher dies (and closes pipe). */
pipe(pipefd);
child = fork();
@@ -578,9 +571,10 @@ static int setup_waker(int lguest_fd, struct device_list *device_list)
err(1, "forking");
if (child == 0) {
- /* Close the "writing" end of our copy of the pipe */
+ /* We are the Waker: close the "writing" end of our copy of the
+ * pipe and start waiting for input. */
close(pipefd[1]);
- wake_parent(pipefd[0], lguest_fd, device_list);
+ wake_parent(pipefd[0], lguest_fd);
}
/* Close the reading end of our copy of the pipe. */
close(pipefd[0]);
@@ -589,12 +583,12 @@ static int setup_waker(int lguest_fd, struct device_list *device_list)
return pipefd[1];
}
-/*L:210
+/*
* Device Handling.
*
- * When the Guest sends DMA to us, it sends us an array of addresses and sizes.
+ * When the Guest gives us a buffer, it sends an array of addresses and sizes.
* We need to make sure it's not trying to reach into the Launcher itself, so
- * we have a convenient routine which check it and exits with an error message
+ * we have a convenient routine which checks it and exits with an error message
* if something funny is going on:
*/
static void *_check_pointer(unsigned long addr, unsigned int size,
@@ -602,87 +596,139 @@ static void *_check_pointer(unsigned long addr, unsigned int size,
{
/* We have to separately check addr and addr+size, because size could
* be huge and addr + size might wrap around. */
- if (addr >= top || addr + size >= top)
- errx(1, "%s:%i: Invalid address %li", __FILE__, line, addr);
+ if (addr >= guest_limit || addr + size >= guest_limit)
+ errx(1, "%s:%i: Invalid address %#lx", __FILE__, line, addr);
/* We return a pointer for the caller's convenience, now we know it's
* safe to use. */
- return (void *)addr;
+ return from_guest_phys(addr);
}
/* A macro which transparently hands the line number to the real function. */
#define check_pointer(addr,size) _check_pointer(addr, size, __LINE__)
-/* The Guest has given us the address of a "struct lguest_dma". We check it's
- * OK and convert it to an iovec (which is a simple array of ptr/size
- * pairs). */
-static u32 *dma2iov(unsigned long dma, struct iovec iov[], unsigned *num)
+/* Each buffer in the virtqueues is actually a chain of descriptors. This
+ * function returns the next descriptor in the chain, or vq->vring.num if we're
+ * at the end. */
+static unsigned next_desc(struct virtqueue *vq, unsigned int i)
{
- unsigned int i;
- struct lguest_dma *udma;
-
- /* First we make sure that the array memory itself is valid. */
- udma = check_pointer(dma, sizeof(*udma));
- /* Now we check each element */
- for (i = 0; i < LGUEST_MAX_DMA_SECTIONS; i++) {
- /* A zero length ends the array. */
- if (!udma->len[i])
- break;
+ unsigned int next;
- iov[i].iov_base = check_pointer(udma->addr[i], udma->len[i]);
- iov[i].iov_len = udma->len[i];
- }
- *num = i;
+ /* If this descriptor says it doesn't chain, we're done. */
+ if (!(vq->vring.desc[i].flags & VRING_DESC_F_NEXT))
+ return vq->vring.num;
- /* We return the pointer to where the caller should write the amount of
- * the buffer used. */
- return &udma->used_len;
+ /* Check they're not leading us off end of descriptors. */
+ next = vq->vring.desc[i].next;
+ /* Make sure compiler knows to grab that: we don't want it changing! */
+ wmb();
+
+ if (next >= vq->vring.num)
+ errx(1, "Desc next is %u", next);
+
+ return next;
}
-/* This routine gets a DMA buffer from the Guest for a given key, and converts
- * it to an iovec array. It returns the interrupt the Guest wants when we're
- * finished, and a pointer to the "used_len" field to fill in. */
-static u32 *get_dma_buffer(int fd, void *key,
- struct iovec iov[], unsigned int *num, u32 *irq)
+/* This looks in the virtqueue and for the first available buffer, and converts
+ * it to an iovec for convenient access. Since descriptors consist of some
+ * number of output then some number of input descriptors, it's actually two
+ * iovecs, but we pack them into one and note how many of each there were.
+ *
+ * This function returns the descriptor number found, or vq->vring.num (which
+ * is never a valid descriptor number) if none was found. */
+static unsigned get_vq_desc(struct virtqueue *vq,
+ struct iovec iov[],
+ unsigned int *out_num, unsigned int *in_num)
{
- u32 buf[] = { LHREQ_GETDMA, (u32)key };
- unsigned long udma;
- u32 *res;
-
- /* Ask the kernel for a DMA buffer corresponding to this key. */
- udma = write(fd, buf, sizeof(buf));
- /* They haven't registered any, or they're all used? */
- if (udma == (unsigned long)-1)
- return NULL;
-
- /* Convert it into our iovec array */
- res = dma2iov(udma, iov, num);
- /* The kernel stashes irq in ->used_len to get it out to us. */
- *irq = *res;
- /* Return a pointer to ((struct lguest_dma *)udma)->used_len. */
- return res;
+ unsigned int i, head;
+
+ /* Check it isn't doing very strange things with descriptor numbers. */
+ if ((u16)(vq->vring.avail->idx - vq->last_avail_idx) > vq->vring.num)
+ errx(1, "Guest moved used index from %u to %u",
+ vq->last_avail_idx, vq->vring.avail->idx);
+
+ /* If there's nothing new since last we looked, return invalid. */
+ if (vq->vring.avail->idx == vq->last_avail_idx)
+ return vq->vring.num;
+
+ /* Grab the next descriptor number they're advertising, and increment
+ * the index we've seen. */
+ head = vq->vring.avail->ring[vq->last_avail_idx++ % vq->vring.num];
+
+ /* If their number is silly, that's a fatal mistake. */
+ if (head >= vq->vring.num)
+ errx(1, "Guest says index %u is available", head);
+
+ /* When we start there are none of either input nor output. */
+ *out_num = *in_num = 0;
+
+ i = head;
+ do {
+ /* Grab the first descriptor, and check it's OK. */
+ iov[*out_num + *in_num].iov_len = vq->vring.desc[i].len;
+ iov[*out_num + *in_num].iov_base
+ = check_pointer(vq->vring.desc[i].addr,
+ vq->vring.desc[i].len);
+ /* If this is an input descriptor, increment that count. */
+ if (vq->vring.desc[i].flags & VRING_DESC_F_WRITE)
+ (*in_num)++;
+ else {
+ /* If it's an output descriptor, they're all supposed
+ * to come before any input descriptors. */
+ if (*in_num)
+ errx(1, "Descriptor has out after in");
+ (*out_num)++;
+ }
+
+ /* If we've got too many, that implies a descriptor loop. */
+ if (*out_num + *in_num > vq->vring.num)
+ errx(1, "Looped descriptor");
+ } while ((i = next_desc(vq, i)) != vq->vring.num);
+
+ return head;
}
-/* This is a convenient routine to send the Guest an interrupt. */
-static void trigger_irq(int fd, u32 irq)
+/* After we've used one of their buffers, we tell them about it. We'll then
+ * want to send them an interrupt, using trigger_irq(). */
+static void add_used(struct virtqueue *vq, unsigned int head, int len)
{
- u32 buf[] = { LHREQ_IRQ, irq };
+ struct vring_used_elem *used;
+
+ /* The virtqueue contains a ring of used buffers. Get a pointer to the
+ * next entry in that used ring. */
+ used = &vq->vring.used->ring[vq->vring.used->idx % vq->vring.num];
+ used->id = head;
+ used->len = len;
+ /* Make sure buffer is written before we update index. */
+ wmb();
+ vq->vring.used->idx++;
+}
+
+/* This actually sends the interrupt for this virtqueue */
+static void trigger_irq(int fd, struct virtqueue *vq)
+{
+ unsigned long buf[] = { LHREQ_IRQ, vq->config.irq };
+
+ /* If they don't want an interrupt, don't send one. */
+ if (vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT)
+ return;
+
+ /* Send the Guest an interrupt tell them we used something up. */
if (write(fd, buf, sizeof(buf)) != 0)
- err(1, "Triggering irq %i", irq);
+ err(1, "Triggering irq %i", vq->config.irq);
}
-/* This simply sets up an iovec array where we can put data to be discarded.
- * This happens when the Guest doesn't want or can't handle the input: we have
- * to get rid of it somewhere, and if we bury it in the ceiling space it will
- * start to smell after a week. */
-static void discard_iovec(struct iovec *iov, unsigned int *num)
+/* And here's the combo meal deal. Supersize me! */
+static void add_used_and_trigger(int fd, struct virtqueue *vq,
+ unsigned int head, int len)
{
- static char discard_buf[1024];
- *num = 1;
- iov->iov_base = discard_buf;
- iov->iov_len = sizeof(discard_buf);
+ add_used(vq, head, len);
+ trigger_irq(fd, vq);
}
-/* Here is the input terminal setting we save, and the routine to restore them
- * on exit so the user can see what they type next. */
+/*
+ * The Console
+ *
+ * Here is the input terminal setting we save, and the routine to restore them
+ * on exit so the user gets their terminal back. */
static struct termios orig_term;
static void restore_term(void)
{
@@ -701,38 +747,39 @@ struct console_abort
/* This is the routine which handles console input (ie. stdin). */
static bool handle_console_input(int fd, struct device *dev)
{
- u32 irq = 0, *lenp;
int len;
- unsigned int num;
- struct iovec iov[LGUEST_MAX_DMA_SECTIONS];
+ unsigned int head, in_num, out_num;
+ struct iovec iov[dev->vq->vring.num];
struct console_abort *abort = dev->priv;
- /* First we get the console buffer from the Guest. The key is dev->mem
- * which was set to 0 in setup_console(). */
- lenp = get_dma_buffer(fd, dev->mem, iov, &num, &irq);
- if (!lenp) {
- /* If it's not ready for input, warn and set up to discard. */
- warn("console: no dma buffer!");
- discard_iovec(iov, &num);
- }
+ /* First we need a console buffer from the Guests's input virtqueue. */
+ head = get_vq_desc(dev->vq, iov, &out_num, &in_num);
+
+ /* If they're not ready for input, stop listening to this file
+ * descriptor. We'll start again once they add an input buffer. */
+ if (head == dev->vq->vring.num)
+ return false;
+
+ if (out_num)
+ errx(1, "Output buffers in console in queue?");
/* This is why we convert to iovecs: the readv() call uses them, and so
* it reads straight into the Guest's buffer. */
- len = readv(dev->fd, iov, num);
+ len = readv(dev->fd, iov, in_num);
if (len <= 0) {
/* This implies that the console is closed, is /dev/null, or
- * something went terribly wrong. We still go through the rest
- * of the logic, though, especially the exit handling below. */
+ * something went terribly wrong. */
warnx("Failed to get console input, ignoring console.");
- len = 0;
+ /* Put the input terminal back. */
+ restore_term();
+ /* Remove callback from input vq, so it doesn't restart us. */
+ dev->vq->handle_output = NULL;
+ /* Stop listening to this fd: don't call us again. */
+ return false;
}
- /* If we read the data into the Guest, fill in the length and send the
- * interrupt. */
- if (lenp) {
- *lenp = len;
- trigger_irq(fd, irq);
- }
+ /* Tell the Guest about the new input. */
+ add_used_and_trigger(fd, dev->vq, head, len);
/* Three ^C within one second? Exit.
*
@@ -746,7 +793,7 @@ static bool handle_console_input(int fd, struct device *dev)
struct timeval now;
gettimeofday(&now, NULL);
if (now.tv_sec <= abort->start.tv_sec+1) {
- u32 args[] = { LHREQ_BREAK, 0 };
+ unsigned long args[] = { LHREQ_BREAK, 0 };
/* Close the fd so Waker will know it has to
* exit. */
close(waker_fd);
@@ -761,214 +808,168 @@ static bool handle_console_input(int fd, struct device *dev)
/* Any other key resets the abort counter. */
abort->count = 0;
- /* Now, if we didn't read anything, put the input terminal back and
- * return failure (meaning, don't call us again). */
- if (!len) {
- restore_term();
- return false;
- }
/* Everything went OK! */
return true;
}
-/* Handling console output is much simpler than input. */
-static u32 handle_console_output(int fd, const struct iovec *iov,
- unsigned num, struct device*dev)
+/* Handling output for console is simple: we just get all the output buffers
+ * and write them to stdout. */
+static void handle_console_output(int fd, struct virtqueue *vq)
{
- /* Whatever the Guest sends, write it to standard output. Return the
- * number of bytes written. */
- return writev(STDOUT_FILENO, iov, num);
-}
-
-/* Guest->Host network output is also pretty easy. */
-static u32 handle_tun_output(int fd, const struct iovec *iov,
- unsigned num, struct device *dev)
-{
- /* We put a flag in the "priv" pointer of the network device, and set
- * it as soon as we see output. We'll see why in handle_tun_input() */
- *(bool *)dev->priv = true;
- /* Whatever packet the Guest sent us, write it out to the tun
- * device. */
- return writev(dev->fd, iov, num);
+ unsigned int head, out, in;
+ int len;
+ struct iovec iov[vq->vring.num];
+
+ /* Keep getting output buffers from the Guest until we run out. */
+ while ((head = get_vq_desc(vq, iov, &out, &in)) != vq->vring.num) {
+ if (in)
+ errx(1, "Input buffers in output queue?");
+ len = writev(STDOUT_FILENO, iov, out);
+ add_used_and_trigger(fd, vq, head, len);
+ }
}
-/* This matches the peer_key() in lguest_net.c. The key for any given slot
- * is the address of the network device's page plus 4 * the slot number. */
-static unsigned long peer_offset(unsigned int peernum)
+/*
+ * The Network
+ *
+ * Handling output for network is also simple: we get all the output buffers
+ * and write them (ignoring the first element) to this device's file descriptor
+ * (stdout). */
+static void handle_net_output(int fd, struct virtqueue *vq)
{
- return 4 * peernum;
+ unsigned int head, out, in;
+ int len;
+ struct iovec iov[vq->vring.num];
+
+ /* Keep getting output buffers from the Guest until we run out. */
+ while ((head = get_vq_desc(vq, iov, &out, &in)) != vq->vring.num) {
+ if (in)
+ errx(1, "Input buffers in output queue?");
+ /* Check header, but otherwise ignore it (we told the Guest we
+ * supported no features, so it shouldn't have anything
+ * interesting). */
+ (void)convert(&iov[0], struct virtio_net_hdr);
+ len = writev(vq->dev->fd, iov+1, out-1);
+ add_used_and_trigger(fd, vq, head, len);
+ }
}
-/* This is where we handle a packet coming in from the tun device */
+/* This is where we handle a packet coming in from the tun device to our
+ * Guest. */
static bool handle_tun_input(int fd, struct device *dev)
{
- u32 irq = 0, *lenp;
+ unsigned int head, in_num, out_num;
int len;
- unsigned num;
- struct iovec iov[LGUEST_MAX_DMA_SECTIONS];
+ struct iovec iov[dev->vq->vring.num];
+ struct virtio_net_hdr *hdr;
- /* First we get a buffer the Guest has bound to its key. */
- lenp = get_dma_buffer(fd, dev->mem+peer_offset(NET_PEERNUM), iov, &num,
- &irq);
- if (!lenp) {
+ /* First we need a network buffer from the Guests's recv virtqueue. */
+ head = get_vq_desc(dev->vq, iov, &out_num, &in_num);
+ if (head == dev->vq->vring.num) {
/* Now, it's expected that if we try to send a packet too
- * early, the Guest won't be ready yet. This is why we set a
- * flag when the Guest sends its first packet. If it's sent a
- * packet we assume it should be ready to receive them.
- *
- * Actually, this is what the status bits in the descriptor are
- * for: we should *use* them. FIXME! */
- if (*(bool *)dev->priv)
+ * early, the Guest won't be ready yet. Wait until the device
+ * status says it's ready. */
+ /* FIXME: Actually want DRIVER_ACTIVE here. */
+ if (dev->desc->status & VIRTIO_CONFIG_S_DRIVER_OK)
warn("network: no dma buffer!");
- discard_iovec(iov, &num);
- }
+ /* We'll turn this back on if input buffers are registered. */
+ return false;
+ } else if (out_num)
+ errx(1, "Output buffers in network recv queue?");
+
+ /* First element is the header: we set it to 0 (no features). */
+ hdr = convert(&iov[0], struct virtio_net_hdr);
+ hdr->flags = 0;
+ hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE;
/* Read the packet from the device directly into the Guest's buffer. */
- len = readv(dev->fd, iov, num);
+ len = readv(dev->fd, iov+1, in_num-1);
if (len <= 0)
err(1, "reading network");
- /* Write the used_len, and trigger the interrupt for the Guest */
- if (lenp) {
- *lenp = len;
- trigger_irq(fd, irq);
- }
+ /* Tell the Guest about the new packet. */
+ add_used_and_trigger(fd, dev->vq, head, sizeof(*hdr) + len);
+
verbose("tun input packet len %i [%02x %02x] (%s)\n", len,
- ((u8 *)iov[0].iov_base)[0], ((u8 *)iov[0].iov_base)[1],
- lenp ? "sent" : "discarded");
+ ((u8 *)iov[1].iov_base)[0], ((u8 *)iov[1].iov_base)[1],
+ head != dev->vq->vring.num ? "sent" : "discarded");
+
/* All good. */
return true;
}
-/* The last device handling routine is block output: the Guest has sent a DMA
- * to the block device. It will have placed the command it wants in the
- * "struct lguest_block_page". */
-static u32 handle_block_output(int fd, const struct iovec *iov,
- unsigned num, struct device *dev)
+/*L:215 This is the callback attached to the network and console input
+ * virtqueues: it ensures we try again, in case we stopped console or net
+ * delivery because Guest didn't have any buffers. */
+static void enable_fd(int fd, struct virtqueue *vq)
{
- struct lguest_block_page *p = dev->mem;
- u32 irq, *lenp;
- unsigned int len, reply_num;
- struct iovec reply[LGUEST_MAX_DMA_SECTIONS];
- off64_t device_len, off = (off64_t)p->sector * 512;
-
- /* First we extract the device length from the dev->priv pointer. */
- device_len = *(off64_t *)dev->priv;
-
- /* We first check that the read or write is within the length of the
- * block file. */
- if (off >= device_len)
- err(1, "Bad offset %llu vs %llu", off, device_len);
- /* Move to the right location in the block file. This shouldn't fail,
- * but best to check. */
- if (lseek64(dev->fd, off, SEEK_SET) != off)
- err(1, "Bad seek to sector %i", p->sector);
-
- verbose("Block: %s at offset %llu\n", p->type ? "WRITE" : "READ", off);
-
- /* They were supposed to bind a reply buffer at key equal to the start
- * of the block device memory. We need this to tell them when the
- * request is finished. */
- lenp = get_dma_buffer(fd, dev->mem, reply, &reply_num, &irq);
- if (!lenp)
- err(1, "Block request didn't give us a dma buffer");
-
- if (p->type) {
- /* A write request. The DMA they sent contained the data, so
- * write it out. */
- len = writev(dev->fd, iov, num);
- /* Grr... Now we know how long the "struct lguest_dma" they
- * sent was, we make sure they didn't try to write over the end
- * of the block file (possibly extending it). */
- if (off + len > device_len) {
- /* Trim it back to the correct length */
- ftruncate64(dev->fd, device_len);
- /* Die, bad Guest, die. */
- errx(1, "Write past end %llu+%u", off, len);
- }
- /* The reply length is 0: we just send back an empty DMA to
- * interrupt them and tell them the write is finished. */
- *lenp = 0;
- } else {
- /* A read request. They sent an empty DMA to start the
- * request, and we put the read contents into the reply
- * buffer. */
- len = readv(dev->fd, reply, reply_num);
- *lenp = len;
- }
-
- /* The result is 1 (done), 2 if there was an error (short read or
- * write). */
- p->result = 1 + (p->bytes != len);
- /* Now tell them we've used their reply buffer. */
- trigger_irq(fd, irq);
-
- /* We're supposed to return the number of bytes of the output buffer we
- * used. But the block device uses the "result" field instead, so we
- * don't bother. */
- return 0;
+ add_device_fd(vq->dev->fd);
+ /* Tell waker to listen to it again */
+ write(waker_fd, &vq->dev->fd, sizeof(vq->dev->fd));
}
-/* This is the generic routine we call when the Guest sends some DMA out. */
-static void handle_output(int fd, unsigned long dma, unsigned long key,
- struct device_list *devices)
+/* This is the generic routine we call when the Guest uses LHCALL_NOTIFY. */
+static void handle_output(int fd, unsigned long addr)
{
struct device *i;
- u32 *lenp;
- struct iovec iov[LGUEST_MAX_DMA_SECTIONS];
- unsigned num = 0;
-
- /* Convert the "struct lguest_dma" they're sending to a "struct
- * iovec". */
- lenp = dma2iov(dma, iov, &num);
-
- /* Check each device: if they expect output to this key, tell them to
- * handle it. */
- for (i = devices->dev; i; i = i->next) {
- if (i->handle_output && key == i->watch_key) {
- /* We write the result straight into the used_len field
- * for them. */
- *lenp = i->handle_output(fd, iov, num, i);
- return;
+ struct virtqueue *vq;
+
+ /* Check each virtqueue. */
+ for (i = devices.dev; i; i = i->next) {
+ for (vq = i->vq; vq; vq = vq->next) {
+ if (vq->config.pfn == addr/getpagesize()
+ && vq->handle_output) {
+ verbose("Output to %s\n", vq->dev->name);
+ vq->handle_output(fd, vq);
+ return;
+ }
}
}
- /* This can happen: the kernel sends any SEND_DMA which doesn't match
- * another Guest to us. It could be that another Guest just left a
- * network, for example. But it's unusual. */
- warnx("Pending dma %p, key %p", (void *)dma, (void *)key);
+ /* Early console write is done using notify on a nul-terminated string
+ * in Guest memory. */
+ if (addr >= guest_limit)
+ errx(1, "Bad NOTIFY %#lx", addr);
+
+ write(STDOUT_FILENO, from_guest_phys(addr),
+ strnlen(from_guest_phys(addr), guest_limit - addr));
}
-/* This is called when the waker wakes us up: check for incoming file
+/* This is called when the Waker wakes us up: check for incoming file
* descriptors. */
-static void handle_input(int fd, struct device_list *devices)
+static void handle_input(int fd)
{
/* select() wants a zeroed timeval to mean "don't wait". */
struct timeval poll = { .tv_sec = 0, .tv_usec = 0 };
for (;;) {
struct device *i;
- fd_set fds = devices->infds;
+ fd_set fds = devices.infds;
/* If nothing is ready, we're done. */
- if (select(devices->max_infd+1, &fds, NULL, NULL, &poll) == 0)
+ if (select(devices.max_infd+1, &fds, NULL, NULL, &poll) == 0)
break;
/* Otherwise, call the device(s) which have readable
* file descriptors and a method of handling them. */
- for (i = devices->dev; i; i = i->next) {
+ for (i = devices.dev; i; i = i->next) {
if (i->handle_input && FD_ISSET(i->fd, &fds)) {
+ int dev_fd;
+ if (i->handle_input(fd, i))
+ continue;
+
/* If handle_input() returns false, it means we
- * should no longer service it.
- * handle_console_input() does this. */
- if (!i->handle_input(fd, i)) {
- /* Clear it from the set of input file
- * descriptors kept at the head of the
- * device list. */
- FD_CLR(i->fd, &devices->infds);
- /* Tell waker to ignore it too... */
- write(waker_fd, &i->fd, sizeof(i->fd));
- }
+ * should no longer service it. Networking and
+ * console do this when there's no input
+ * buffers to deliver into. Console also uses
+ * it when it discovers that stdin is
+ * closed. */
+ FD_CLR(i->fd, &devices.infds);
+ /* Tell waker to ignore it too, by sending a
+ * negative fd number (-1, since 0 is a valid
+ * FD number). */
+ dev_fd = -i->fd - 1;
+ write(waker_fd, &dev_fd, sizeof(dev_fd));
}
}
}
@@ -982,71 +983,122 @@ static void handle_input(int fd, struct device_list *devices)
* routines to allocate them.
*
* This routine allocates a new "struct lguest_device_desc" from descriptor
- * table in the devices array just above the Guest's normal memory. */
-static struct lguest_device_desc *
-new_dev_desc(struct lguest_device_desc *descs,
- u16 type, u16 features, u16 num_pages)
+ * table just above the Guest's normal memory. It returns a pointer to that
+ * descriptor. */
+static struct lguest_device_desc *new_dev_desc(u16 type)
{
- unsigned int i;
+ struct lguest_device_desc *d;
- for (i = 0; i < LGUEST_MAX_DEVICES; i++) {
- if (!descs[i].type) {
- descs[i].type = type;
- descs[i].features = features;
- descs[i].num_pages = num_pages;
- /* If they said the device needs memory, we allocate
- * that now, bumping up the top of Guest memory. */
- if (num_pages) {
- map_zeroed_pages(top, num_pages);
- descs[i].pfn = top/getpagesize();
- top += num_pages*getpagesize();
- }
- return &descs[i];
- }
- }
- errx(1, "too many devices");
+ /* We only have one page for all the descriptors. */
+ if (devices.desc_used + sizeof(*d) > getpagesize())
+ errx(1, "Too many devices");
+
+ /* We don't need to set config_len or status: page is 0 already. */
+ d = (void *)devices.descpage + devices.desc_used;
+ d->type = type;
+ devices.desc_used += sizeof(*d);
+
+ return d;
+}
+
+/* Each device descriptor is followed by some configuration information.
+ * Each configuration field looks like: u8 type, u8 len, [... len bytes...].
+ *
+ * This routine adds a new field to an existing device's descriptor. It only
+ * works for the last device, but that's OK because that's how we use it. */
+static void add_desc_field(struct device *dev, u8 type, u8 len, const void *c)
+{
+ /* This is the last descriptor, right? */
+ assert(devices.descpage + devices.desc_used
+ == (u8 *)(dev->desc + 1) + dev->desc->config_len);
+
+ /* We only have one page of device descriptions. */
+ if (devices.desc_used + 2 + len > getpagesize())
+ errx(1, "Too many devices");
+
+ /* Copy in the new config header: type then length. */
+ devices.descpage[devices.desc_used++] = type;
+ devices.descpage[devices.desc_used++] = len;
+ memcpy(devices.descpage + devices.desc_used, c, len);
+ devices.desc_used += len;
+
+ /* Update the device descriptor length: two byte head then data. */
+ dev->desc->config_len += 2 + len;
}
-/* This monster routine does all the creation and setup of a new device,
- * including caling new_dev_desc() to allocate the descriptor and device
- * memory. */
-static struct device *new_device(struct device_list *devices,
- u16 type, u16 num_pages, u16 features,
- int fd,
- bool (*handle_input)(int, struct device *),
- unsigned long watch_off,
- u32 (*handle_output)(int,
- const struct iovec *,
- unsigned,
- struct device *))
+/* This routine adds a virtqueue to a device. We specify how many descriptors
+ * the virtqueue is to have. */
+static void add_virtqueue(struct device *dev, unsigned int num_descs,
+ void (*handle_output)(int fd, struct virtqueue *me))
+{
+ unsigned int pages;
+ struct virtqueue **i, *vq = malloc(sizeof(*vq));
+ void *p;
+
+ /* First we need some pages for this virtqueue. */
+ pages = (vring_size(num_descs, getpagesize()) + getpagesize() - 1)
+ / getpagesize();
+ p = get_pages(pages);
+
+ /* Initialize the configuration. */
+ vq->config.num = num_descs;
+ vq->config.irq = devices.next_irq++;
+ vq->config.pfn = to_guest_phys(p) / getpagesize();
+
+ /* Initialize the vring. */
+ vring_init(&vq->vring, num_descs, p, getpagesize());
+
+ /* Add the configuration information to this device's descriptor. */
+ add_desc_field(dev, VIRTIO_CONFIG_F_VIRTQUEUE,
+ sizeof(vq->config), &vq->config);
+
+ /* Add to tail of list, so dev->vq is first vq, dev->vq->next is
+ * second. */
+ for (i = &dev->vq; *i; i = &(*i)->next);
+ *i = vq;
+
+ /* Link virtqueue back to device. */
+ vq->dev = dev;
+
+ /* Set the routine to call when the Guest does something to this
+ * virtqueue. */
+ vq->handle_output = handle_output;
+
+ /* Set the "Don't Notify Me" flag if we don't have a handler */
+ if (!handle_output)
+ vq->vring.used->flags = VRING_USED_F_NO_NOTIFY;
+}
+
+/* This routine does all the creation and setup of a new device, including
+ * calling new_dev_desc() to allocate the descriptor and device memory. */
+static struct device *new_device(const char *name, u16 type, int fd,
+ bool (*handle_input)(int, struct device *))
{
struct device *dev = malloc(sizeof(*dev));
/* Append to device list. Prepending to a single-linked list is
* easier, but the user expects the devices to be arranged on the bus
* in command-line order. The first network device on the command line
- * is eth0, the first block device /dev/lgba, etc. */
- *devices->lastdev = dev;
+ * is eth0, the first block device /dev/vda, etc. */
+ *devices.lastdev = dev;
dev->next = NULL;
- devices->lastdev = &dev->next;
+ devices.lastdev = &dev->next;
/* Now we populate the fields one at a time. */
dev->fd = fd;
/* If we have an input handler for this file descriptor, then we add it
* to the device_list's fdset and maxfd. */
if (handle_input)
- set_fd(dev->fd, devices);
- dev->desc = new_dev_desc(devices->descs, type, features, num_pages);
- dev->mem = (void *)(dev->desc->pfn * getpagesize());
+ add_device_fd(dev->fd);
+ dev->desc = new_dev_desc(type);
dev->handle_input = handle_input;
- dev->watch_key = (unsigned long)dev->mem + watch_off;
- dev->handle_output = handle_output;
+ dev->name = name;
return dev;
}
/* Our first setup routine is the console. It's a fairly simple device, but
* UNIX tty handling makes it uglier than it could be. */
-static void setup_console(struct device_list *devices)
+static void setup_console(void)
{
struct device *dev;
@@ -1062,127 +1114,38 @@ static void setup_console(struct device_list *devices)
atexit(restore_term);
}
- /* We don't currently require any memory for the console, so we ask for
- * 0 pages. */
- dev = new_device(devices, LGUEST_DEVICE_T_CONSOLE, 0, 0,
- STDIN_FILENO, handle_console_input,
- LGUEST_CONSOLE_DMA_KEY, handle_console_output);
+ dev = new_device("console", VIRTIO_ID_CONSOLE,
+ STDIN_FILENO, handle_console_input);
/* We store the console state in dev->priv, and initialize it. */
dev->priv = malloc(sizeof(struct console_abort));
((struct console_abort *)dev->priv)->count = 0;
- verbose("device %p: console\n",
- (void *)(dev->desc->pfn * getpagesize()));
-}
-/* Setting up a block file is also fairly straightforward. */
-static void setup_block_file(const char *filename, struct device_list *devices)
-{
- int fd;
- struct device *dev;
- off64_t *device_len;
- struct lguest_block_page *p;
-
- /* We open with O_LARGEFILE because otherwise we get stuck at 2G. We
- * open with O_DIRECT because otherwise our benchmarks go much too
- * fast. */
- fd = open_or_die(filename, O_RDWR|O_LARGEFILE|O_DIRECT);
-
- /* We want one page, and have no input handler (the block file never
- * has anything interesting to say to us). Our timing will be quite
- * random, so it should be a reasonable randomness source. */
- dev = new_device(devices, LGUEST_DEVICE_T_BLOCK, 1,
- LGUEST_DEVICE_F_RANDOMNESS,
- fd, NULL, 0, handle_block_output);
-
- /* We store the device size in the private area */
- device_len = dev->priv = malloc(sizeof(*device_len));
- /* This is the safe way of establishing the size of our device: it
- * might be a normal file or an actual block device like /dev/hdb. */
- *device_len = lseek64(fd, 0, SEEK_END);
-
- /* The device memory is a "struct lguest_block_page". It's zeroed
- * already, we just need to put in the device size. Block devices
- * think in sectors (ie. 512 byte chunks), so we translate here. */
- p = dev->mem;
- p->num_sectors = *device_len/512;
- verbose("device %p: block %i sectors\n",
- (void *)(dev->desc->pfn * getpagesize()), p->num_sectors);
+ /* The console needs two virtqueues: the input then the output. When
+ * they put something the input queue, we make sure we're listening to
+ * stdin. When they put something in the output queue, we write it to
+ * stdout. */
+ add_virtqueue(dev, VIRTQUEUE_NUM, enable_fd);
+ add_virtqueue(dev, VIRTQUEUE_NUM, handle_console_output);
+
+ verbose("device %u: console\n", devices.device_num++);
}
+/*:*/
-/*
- * Network Devices.
+/*M:010 Inter-guest networking is an interesting area. Simplest is to have a
+ * --sharenet=<name> option which opens or creates a named pipe. This can be
+ * used to send packets to another guest in a 1:1 manner.
*
- * Setting up network devices is quite a pain, because we have three types.
- * First, we have the inter-Guest network. This is a file which is mapped into
- * the address space of the Guests who are on the network. Because it is a
- * shared mapping, the same page underlies all the devices, and they can send
- * DMA to each other.
+ * More sopisticated is to use one of the tools developed for project like UML
+ * to do networking.
*
- * Remember from our network driver, the Guest is told what slot in the page it
- * is to use. We use exclusive fnctl locks to reserve a slot. If another
- * Guest is using a slot, the lock will fail and we try another. Because fnctl
- * locks are cleaned up automatically when we die, this cleverly means that our
- * reservation on the slot will vanish if we crash. */
-static unsigned int find_slot(int netfd, const char *filename)
-{
- struct flock fl;
-
- fl.l_type = F_WRLCK;
- fl.l_whence = SEEK_SET;
- fl.l_len = 1;
- /* Try a 1 byte lock in each possible position number */
- for (fl.l_start = 0;
- fl.l_start < getpagesize()/sizeof(struct lguest_net);
- fl.l_start++) {
- /* If we succeed, return the slot number. */
- if (fcntl(netfd, F_SETLK, &fl) == 0)
- return fl.l_start;
- }
- errx(1, "No free slots in network file %s", filename);
-}
-
-/* This function sets up the network file */
-static void setup_net_file(const char *filename,
- struct device_list *devices)
-{
- int netfd;
- struct device *dev;
-
- /* We don't use open_or_die() here: for friendliness we create the file
- * if it doesn't already exist. */
- netfd = open(filename, O_RDWR, 0);
- if (netfd < 0) {
- if (errno == ENOENT) {
- netfd = open(filename, O_RDWR|O_CREAT, 0600);
- if (netfd >= 0) {
- /* If we succeeded, initialize the file with a
- * blank page. */
- char page[getpagesize()];
- memset(page, 0, sizeof(page));
- write(netfd, page, sizeof(page));
- }
- }
- if (netfd < 0)
- err(1, "cannot open net file '%s'", filename);
- }
-
- /* We need 1 page, and the features indicate the slot to use and that
- * no checksum is needed. We never touch this device again; it's
- * between the Guests on the network, so we don't register input or
- * output handlers. */
- dev = new_device(devices, LGUEST_DEVICE_T_NET, 1,
- find_slot(netfd, filename)|LGUEST_NET_F_NOCSUM,
- -1, NULL, 0, NULL);
-
- /* Map the shared file. */
- if (mmap(dev->mem, getpagesize(), PROT_READ|PROT_WRITE,
- MAP_FIXED|MAP_SHARED, netfd, 0) != dev->mem)
- err(1, "could not mmap '%s'", filename);
- verbose("device %p: shared net %s, peer %i\n",
- (void *)(dev->desc->pfn * getpagesize()), filename,
- dev->desc->features & ~LGUEST_NET_F_NOCSUM);
-}
-/*:*/
+ * Faster is to do virtio bonding in kernel. Doing this 1:1 would be
+ * completely generic ("here's my vring, attach to your vring") and would work
+ * for any traffic. Of course, namespace and permissions issues need to be
+ * dealt with. A more sophisticated "multi-channel" virtio_net.c could hide
+ * multiple inter-guest channels behind one interface, although it would
+ * require some manner of hotplugging new virtio channels.
+ *
+ * Finally, we could implement a virtio network switch in the kernel. :*/
static u32 str2ip(const char *ipaddr)
{
@@ -1217,7 +1180,7 @@ static void add_to_bridge(int fd, const char *if_name, const char *br_name)
/* This sets up the Host end of the network device with an IP address, brings
* it up so packets will flow, the copies the MAC address into the hwaddr
- * pointer (in practice, the Host's slot in the network device's memory). */
+ * pointer. */
static void configure_device(int fd, const char *devname, u32 ipaddr,
unsigned char hwaddr[6])
{
@@ -1243,18 +1206,18 @@ static void configure_device(int fd, const char *devname, u32 ipaddr,
memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, 6);
}
-/*L:195 The other kind of network is a Host<->Guest network. This can either
- * use briding or routing, but the principle is the same: it uses the "tun"
- * device to inject packets into the Host as if they came in from a normal
- * network card. We just shunt packets between the Guest and the tun
- * device. */
-static void setup_tun_net(const char *arg, struct device_list *devices)
+/*L:195 Our network is a Host<->Guest network. This can either use bridging or
+ * routing, but the principle is the same: it uses the "tun" device to inject
+ * packets into the Host as if they came in from a normal network card. We
+ * just shunt packets between the Guest and the tun device. */
+static void setup_tun_net(const char *arg)
{
struct device *dev;
struct ifreq ifr;
int netfd, ipfd;
u32 ip;
const char *br_name = NULL;
+ u8 hwaddr[6];
/* We open the /dev/net/tun device and tell it we want a tap device. A
* tap device is like a tun device, only somehow different. To tell
@@ -1270,21 +1233,13 @@ static void setup_tun_net(const char *arg, struct device_list *devices)
* device: trust us! */
ioctl(netfd, TUNSETNOCSUM, 1);
- /* We create the net device with 1 page, using the features field of
- * the descriptor to tell the Guest it is in slot 1 (NET_PEERNUM), and
- * that the device has fairly random timing. We do *not* specify
- * LGUEST_NET_F_NOCSUM: these packets can reach the real world.
- *
- * We will put our MAC address is slot 0 for the Guest to see, so
- * it will send packets to us using the key "peer_offset(0)": */
- dev = new_device(devices, LGUEST_DEVICE_T_NET, 1,
- NET_PEERNUM|LGUEST_DEVICE_F_RANDOMNESS, netfd,
- handle_tun_input, peer_offset(0), handle_tun_output);
+ /* First we create a new network device. */
+ dev = new_device("net", VIRTIO_ID_NET, netfd, handle_tun_input);
- /* We keep a flag which says whether we've seen packets come out from
- * this network device. */
- dev->priv = malloc(sizeof(bool));
- *(bool *)dev->priv = false;
+ /* Network devices need a receive and a send queue, just like
+ * console. */
+ add_virtqueue(dev, VIRTQUEUE_NUM, enable_fd);
+ add_virtqueue(dev, VIRTQUEUE_NUM, handle_net_output);
/* We need a socket to perform the magic network ioctls to bring up the
* tap interface, connect to the bridge etc. Any socket will do! */
@@ -1300,72 +1255,293 @@ static void setup_tun_net(const char *arg, struct device_list *devices)
} else /* It is an IP address to set up the device with */
ip = str2ip(arg);
- /* We are peer 0, ie. first slot, so we hand dev->mem to this routine
- * to write the MAC address at the start of the device memory. */
- configure_device(ipfd, ifr.ifr_name, ip, dev->mem);
+ /* Set up the tun device, and get the mac address for the interface. */
+ configure_device(ipfd, ifr.ifr_name, ip, hwaddr);
- /* Set "promisc" bit: we want every single packet if we're going to
- * bridge to other machines (and otherwise it doesn't matter). */
- *((u8 *)dev->mem) |= 0x1;
+ /* Tell Guest what MAC address to use. */
+ add_desc_field(dev, VIRTIO_CONFIG_NET_MAC_F, sizeof(hwaddr), hwaddr);
+ /* We don't seed the socket any more; setup is done. */
close(ipfd);
- verbose("device %p: tun net %u.%u.%u.%u\n",
- (void *)(dev->desc->pfn * getpagesize()),
- (u8)(ip>>24), (u8)(ip>>16), (u8)(ip>>8), (u8)ip);
+ verbose("device %u: tun net %u.%u.%u.%u\n",
+ devices.device_num++,
+ (u8)(ip>>24),(u8)(ip>>16),(u8)(ip>>8),(u8)ip);
if (br_name)
verbose("attached to bridge: %s\n", br_name);
}
+
+/* Our block (disk) device should be really simple: the Guest asks for a block
+ * number and we read or write that position in the file. Unfortunately, that
+ * was amazingly slow: the Guest waits until the read is finished before
+ * running anything else, even if it could have been doing useful work.
+ *
+ * We could use async I/O, except it's reputed to suck so hard that characters
+ * actually go missing from your code when you try to use it.
+ *
+ * So we farm the I/O out to thread, and communicate with it via a pipe. */
+
+/* This hangs off device->priv. */
+struct vblk_info
+{
+ /* The size of the file. */
+ off64_t len;
+
+ /* The file descriptor for the file. */
+ int fd;
+
+ /* IO thread listens on this file descriptor [0]. */
+ int workpipe[2];
+
+ /* IO thread writes to this file descriptor to mark it done, then
+ * Launcher triggers interrupt to Guest. */
+ int done_fd;
+};
+/*:*/
+
+/*L:210
+ * The Disk
+ *
+ * Remember that the block device is handled by a separate I/O thread. We head
+ * straight into the core of that thread here:
+ */
+static bool service_io(struct device *dev)
+{
+ struct vblk_info *vblk = dev->priv;
+ unsigned int head, out_num, in_num, wlen;
+ int ret;
+ struct virtio_blk_inhdr *in;
+ struct virtio_blk_outhdr *out;
+ struct iovec iov[dev->vq->vring.num];
+ off64_t off;
+
+ /* See if there's a request waiting. If not, nothing to do. */
+ head = get_vq_desc(dev->vq, iov, &out_num, &in_num);
+ if (head == dev->vq->vring.num)
+ return false;
+
+ /* Every block request should contain at least one output buffer
+ * (detailing the location on disk and the type of request) and one
+ * input buffer (to hold the result). */
+ if (out_num == 0 || in_num == 0)
+ errx(1, "Bad virtblk cmd %u out=%u in=%u",
+ head, out_num, in_num);
+
+ out = convert(&iov[0], struct virtio_blk_outhdr);
+ in = convert(&iov[out_num+in_num-1], struct virtio_blk_inhdr);
+ off = out->sector * 512;
+
+ /* The block device implements "barriers", where the Guest indicates
+ * that it wants all previous writes to occur before this write. We
+ * don't have a way of asking our kernel to do a barrier, so we just
+ * synchronize all the data in the file. Pretty poor, no? */
+ if (out->type & VIRTIO_BLK_T_BARRIER)
+ fdatasync(vblk->fd);
+
+ /* In general the virtio block driver is allowed to try SCSI commands.
+ * It'd be nice if we supported eject, for example, but we don't. */
+ if (out->type & VIRTIO_BLK_T_SCSI_CMD) {
+ fprintf(stderr, "Scsi commands unsupported\n");
+ in->status = VIRTIO_BLK_S_UNSUPP;
+ wlen = sizeof(*in);
+ } else if (out->type & VIRTIO_BLK_T_OUT) {
+ /* Write */
+
+ /* Move to the right location in the block file. This can fail
+ * if they try to write past end. */
+ if (lseek64(vblk->fd, off, SEEK_SET) != off)
+ err(1, "Bad seek to sector %llu", out->sector);
+
+ ret = writev(vblk->fd, iov+1, out_num-1);
+ verbose("WRITE to sector %llu: %i\n", out->sector, ret);
+
+ /* Grr... Now we know how long the descriptor they sent was, we
+ * make sure they didn't try to write over the end of the block
+ * file (possibly extending it). */
+ if (ret > 0 && off + ret > vblk->len) {
+ /* Trim it back to the correct length */
+ ftruncate64(vblk->fd, vblk->len);
+ /* Die, bad Guest, die. */
+ errx(1, "Write past end %llu+%u", off, ret);
+ }
+ wlen = sizeof(*in);
+ in->status = (ret >= 0 ? VIRTIO_BLK_S_OK : VIRTIO_BLK_S_IOERR);
+ } else {
+ /* Read */
+
+ /* Move to the right location in the block file. This can fail
+ * if they try to read past end. */
+ if (lseek64(vblk->fd, off, SEEK_SET) != off)
+ err(1, "Bad seek to sector %llu", out->sector);
+
+ ret = readv(vblk->fd, iov+1, in_num-1);
+ verbose("READ from sector %llu: %i\n", out->sector, ret);
+ if (ret >= 0) {
+ wlen = sizeof(*in) + ret;
+ in->status = VIRTIO_BLK_S_OK;
+ } else {
+ wlen = sizeof(*in);
+ in->status = VIRTIO_BLK_S_IOERR;
+ }
+ }
+
+ /* We can't trigger an IRQ, because we're not the Launcher. It does
+ * that when we tell it we're done. */
+ add_used(dev->vq, head, wlen);
+ return true;
+}
+
+/* This is the thread which actually services the I/O. */
+static int io_thread(void *_dev)
+{
+ struct device *dev = _dev;
+ struct vblk_info *vblk = dev->priv;
+ char c;
+
+ /* Close other side of workpipe so we get 0 read when main dies. */
+ close(vblk->workpipe[1]);
+ /* Close the other side of the done_fd pipe. */
+ close(dev->fd);
+
+ /* When this read fails, it means Launcher died, so we follow. */
+ while (read(vblk->workpipe[0], &c, 1) == 1) {
+ /* We acknowledge each request immediately to reduce latency,
+ * rather than waiting until we've done them all. I haven't
+ * measured to see if it makes any difference. */
+ while (service_io(dev))
+ write(vblk->done_fd, &c, 1);
+ }
+ return 0;
+}
+
+/* Now we've seen the I/O thread, we return to the Launcher to see what happens
+ * when the thread tells us it's completed some I/O. */
+static bool handle_io_finish(int fd, struct device *dev)
+{
+ char c;
+
+ /* If the I/O thread died, presumably it printed the error, so we
+ * simply exit. */
+ if (read(dev->fd, &c, 1) != 1)
+ exit(1);
+
+ /* It did some work, so trigger the irq. */
+ trigger_irq(fd, dev->vq);
+ return true;
+}
+
+/* When the Guest submits some I/O, we just need to wake the I/O thread. */
+static void handle_virtblk_output(int fd, struct virtqueue *vq)
+{
+ struct vblk_info *vblk = vq->dev->priv;
+ char c = 0;
+
+ /* Wake up I/O thread and tell it to go to work! */
+ if (write(vblk->workpipe[1], &c, 1) != 1)
+ /* Presumably it indicated why it died. */
+ exit(1);
+}
+
+/*L:198 This actually sets up a virtual block device. */
+static void setup_block_file(const char *filename)
+{
+ int p[2];
+ struct device *dev;
+ struct vblk_info *vblk;
+ void *stack;
+ u64 cap;
+ unsigned int val;
+
+ /* This is the pipe the I/O thread will use to tell us I/O is done. */
+ pipe(p);
+
+ /* The device responds to return from I/O thread. */
+ dev = new_device("block", VIRTIO_ID_BLOCK, p[0], handle_io_finish);
+
+ /* The device has one virtqueue, where the Guest places requests. */
+ add_virtqueue(dev, VIRTQUEUE_NUM, handle_virtblk_output);
+
+ /* Allocate the room for our own bookkeeping */
+ vblk = dev->priv = malloc(sizeof(*vblk));
+
+ /* First we open the file and store the length. */
+ vblk->fd = open_or_die(filename, O_RDWR|O_LARGEFILE);
+ vblk->len = lseek64(vblk->fd, 0, SEEK_END);
+
+ /* Tell Guest how many sectors this device has. */
+ cap = cpu_to_le64(vblk->len / 512);
+ add_desc_field(dev, VIRTIO_CONFIG_BLK_F_CAPACITY, sizeof(cap), &cap);
+
+ /* Tell Guest not to put in too many descriptors at once: two are used
+ * for the in and out elements. */
+ val = cpu_to_le32(VIRTQUEUE_NUM - 2);
+ add_desc_field(dev, VIRTIO_CONFIG_BLK_F_SEG_MAX, sizeof(val), &val);
+
+ /* The I/O thread writes to this end of the pipe when done. */
+ vblk->done_fd = p[1];
+
+ /* This is the second pipe, which is how we tell the I/O thread about
+ * more work. */
+ pipe(vblk->workpipe);
+
+ /* Create stack for thread and run it */
+ stack = malloc(32768);
+ if (clone(io_thread, stack + 32768, CLONE_VM, dev) == -1)
+ err(1, "Creating clone");
+
+ /* We don't need to keep the I/O thread's end of the pipes open. */
+ close(vblk->done_fd);
+ close(vblk->workpipe[0]);
+
+ verbose("device %u: virtblock %llu sectors\n",
+ devices.device_num, cap);
+}
/* That's the end of device setup. */
/*L:220 Finally we reach the core of the Launcher, which runs the Guest, serves
* its input and output, and finally, lays it to rest. */
-static void __attribute__((noreturn))
-run_guest(int lguest_fd, struct device_list *device_list)
+static void __attribute__((noreturn)) run_guest(int lguest_fd)
{
for (;;) {
- u32 args[] = { LHREQ_BREAK, 0 };
- unsigned long arr[2];
+ unsigned long args[] = { LHREQ_BREAK, 0 };
+ unsigned long notify_addr;
int readval;
/* We read from the /dev/lguest device to run the Guest. */
- readval = read(lguest_fd, arr, sizeof(arr));
+ readval = read(lguest_fd, &notify_addr, sizeof(notify_addr));
- /* The read can only really return sizeof(arr) (the Guest did a
- * SEND_DMA to us), or an error. */
-
- /* For a successful read, arr[0] is the address of the "struct
- * lguest_dma", and arr[1] is the key the Guest sent to. */
- if (readval == sizeof(arr)) {
- handle_output(lguest_fd, arr[0], arr[1], device_list);
+ /* One unsigned long means the Guest did HCALL_NOTIFY */
+ if (readval == sizeof(notify_addr)) {
+ verbose("Notify on address %#lx\n", notify_addr);
+ handle_output(lguest_fd, notify_addr);
continue;
/* ENOENT means the Guest died. Reading tells us why. */
} else if (errno == ENOENT) {
char reason[1024] = { 0 };
read(lguest_fd, reason, sizeof(reason)-1);
errx(1, "%s", reason);
- /* EAGAIN means the waker wanted us to look at some input.
+ /* EAGAIN means the Waker wanted us to look at some input.
* Anything else means a bug or incompatible change. */
} else if (errno != EAGAIN)
err(1, "Running guest failed");
- /* Service input, then unset the BREAK which releases
- * the Waker. */
- handle_input(lguest_fd, device_list);
+ /* Service input, then unset the BREAK to release the Waker. */
+ handle_input(lguest_fd);
if (write(lguest_fd, args, sizeof(args)) < 0)
err(1, "Resetting break");
}
}
/*
- * This is the end of the Launcher.
+ * This is the end of the Launcher. The good news: we are over halfway
+ * through! The bad news: the most fiendish part of the code still lies ahead
+ * of us.
*
- * But wait! We've seen I/O from the Launcher, and we've seen I/O from the
- * Drivers. If we were to see the Host kernel I/O code, our understanding
- * would be complete... :*/
+ * Are you ready? Take a deep breath and join me in the core of the Host, in
+ * "make Host".
+ :*/
static struct option opts[] = {
{ "verbose", 0, NULL, 'v' },
- { "sharenet", 1, NULL, 's' },
{ "tunnet", 1, NULL, 't' },
{ "block", 1, NULL, 'b' },
{ "initrd", 1, NULL, 'i' },
@@ -1374,37 +1550,21 @@ static struct option opts[] = {
static void usage(void)
{
errx(1, "Usage: lguest [--verbose] "
- "[--sharenet=<filename>|--tunnet=(<ipaddr>|bridge:<bridgename>)\n"
+ "[--tunnet=(<ipaddr>|bridge:<bridgename>)\n"
"|--block=<filename>|--initrd=<filename>]...\n"
"<mem-in-mb> vmlinux [args...]");
}
-/*L:100 The Launcher code itself takes us out into userspace, that scary place
- * where pointers run wild and free! Unfortunately, like most userspace
- * programs, it's quite boring (which is why everyone like to hack on the
- * kernel!). Perhaps if you make up an Lguest Drinking Game at this point, it
- * will get you through this section. Or, maybe not.
- *
- * The Launcher binary sits up high, usually starting at address 0xB8000000.
- * Everything below this is the "physical" memory for the Guest. For example,
- * if the Guest were to write a "1" at physical address 0, we would see a "1"
- * in the Launcher at "(int *)0". Guest physical == Launcher virtual.
- *
- * This can be tough to get your head around, but usually it just means that we
- * don't need to do any conversion when the Guest gives us it's "physical"
- * addresses.
- */
+/*L:105 The main routine is where the real work begins: */
int main(int argc, char *argv[])
{
- /* Memory, top-level pagetable, code startpoint, PAGE_OFFSET and size
- * of the (optional) initrd. */
- unsigned long mem = 0, pgdir, start, page_offset, initrd_size = 0;
- /* A temporary and the /dev/lguest file descriptor. */
+ /* Memory, top-level pagetable, code startpoint and size of the
+ * (optional) initrd. */
+ unsigned long mem = 0, pgdir, start, initrd_size = 0;
+ /* Two temporaries and the /dev/lguest file descriptor. */
int i, c, lguest_fd;
- /* The list of Guest devices, based on command line arguments. */
- struct device_list device_list;
- /* The boot information for the Guest: at guest-physical address 0. */
- void *boot = (void *)0;
+ /* The boot information for the Guest. */
+ struct boot_params *boot;
/* If they specify an initrd file to load. */
const char *initrd_name = NULL;
@@ -1412,11 +1572,12 @@ int main(int argc, char *argv[])
* device receive input from a file descriptor, we keep an fdset
* (infds) and the maximum fd number (max_infd) with the head of the
* list. We also keep a pointer to the last device, for easy appending
- * to the list. */
- device_list.max_infd = -1;
- device_list.dev = NULL;
- device_list.lastdev = &device_list.dev;
- FD_ZERO(&device_list.infds);
+ * to the list. Finally, we keep the next interrupt number to hand out
+ * (1: remember that 0 is used by the timer). */
+ FD_ZERO(&devices.infds);
+ devices.max_infd = -1;
+ devices.lastdev = &devices.dev;
+ devices.next_irq = 1;
/* We need to know how much memory so we can set up the device
* descriptor and memory pages for the devices as we parse the command
@@ -1424,9 +1585,16 @@ int main(int argc, char *argv[])
* of memory now. */
for (i = 1; i < argc; i++) {
if (argv[i][0] != '-') {
- mem = top = atoi(argv[i]) * 1024 * 1024;
- device_list.descs = map_zeroed_pages(top, 1);
- top += getpagesize();
+ mem = atoi(argv[i]) * 1024 * 1024;
+ /* We start by mapping anonymous pages over all of
+ * guest-physical memory range. This fills it with 0,
+ * and ensures that the Guest won't be killed when it
+ * tries to access it. */
+ guest_base = map_zeroed_pages(mem / getpagesize()
+ + DEVICE_PAGES);
+ guest_limit = mem;
+ guest_max = mem + DEVICE_PAGES*getpagesize();
+ devices.descpage = get_pages(1);
break;
}
}
@@ -1437,14 +1605,11 @@ int main(int argc, char *argv[])
case 'v':
verbose = true;
break;
- case 's':
- setup_net_file(optarg, &device_list);
- break;
case 't':
- setup_tun_net(optarg, &device_list);
+ setup_tun_net(optarg);
break;
case 'b':
- setup_block_file(optarg, &device_list);
+ setup_block_file(optarg);
break;
case 'i':
initrd_name = optarg;
@@ -1459,56 +1624,61 @@ int main(int argc, char *argv[])
if (optind + 2 > argc)
usage();
- /* We always have a console device */
- setup_console(&device_list);
+ verbose("Guest base is at %p\n", guest_base);
- /* We start by mapping anonymous pages over all of guest-physical
- * memory range. This fills it with 0, and ensures that the Guest
- * won't be killed when it tries to access it. */
- map_zeroed_pages(0, mem / getpagesize());
+ /* We always have a console device */
+ setup_console();
/* Now we load the kernel */
- start = load_kernel(open_or_die(argv[optind+1], O_RDONLY),
- &page_offset);
+ start = load_kernel(open_or_die(argv[optind+1], O_RDONLY));
+
+ /* Boot information is stashed at physical address 0 */
+ boot = from_guest_phys(0);
/* Map the initrd image if requested (at top of physical memory) */
if (initrd_name) {
initrd_size = load_initrd(initrd_name, mem);
/* These are the location in the Linux boot header where the
* start and size of the initrd are expected to be found. */
- *(unsigned long *)(boot+0x218) = mem - initrd_size;
- *(unsigned long *)(boot+0x21c) = initrd_size;
+ boot->hdr.ramdisk_image = mem - initrd_size;
+ boot->hdr.ramdisk_size = initrd_size;
/* The bootloader type 0xFF means "unknown"; that's OK. */
- *(unsigned char *)(boot+0x210) = 0xFF;
+ boot->hdr.type_of_loader = 0xFF;
}
/* Set up the initial linear pagetables, starting below the initrd. */
- pgdir = setup_pagetables(mem, initrd_size, page_offset);
+ pgdir = setup_pagetables(mem, initrd_size);
/* The Linux boot header contains an "E820" memory map: ours is a
* simple, single region. */
- *(char*)(boot+E820NR) = 1;
- *((struct e820entry *)(boot+E820MAP))
- = ((struct e820entry) { 0, mem, E820_RAM });
+ boot->e820_entries = 1;
+ boot->e820_map[0] = ((struct e820entry) { 0, mem, E820_RAM });
/* The boot header contains a command line pointer: we put the command
- * line after the boot header (at address 4096) */
- *(void **)(boot + 0x228) = boot + 4096;
- concat(boot + 4096, argv+optind+2);
+ * line after the boot header. */
+ boot->hdr.cmd_line_ptr = to_guest_phys(boot + 1);
+ /* We use a simple helper to copy the arguments separated by spaces. */
+ concat((char *)(boot + 1), argv+optind+2);
+
+ /* Boot protocol version: 2.07 supports the fields for lguest. */
+ boot->hdr.version = 0x207;
+
+ /* The hardware_subarch value of "1" tells the Guest it's an lguest. */
+ boot->hdr.hardware_subarch = 1;
- /* The guest type value of "1" tells the Guest it's under lguest. */
- *(int *)(boot + 0x23c) = 1;
+ /* Tell the entry path not to try to reload segment registers. */
+ boot->hdr.loadflags |= KEEP_SEGMENTS;
/* We tell the kernel to initialize the Guest: this returns the open
* /dev/lguest file descriptor. */
- lguest_fd = tell_kernel(pgdir, start, page_offset);
+ lguest_fd = tell_kernel(pgdir, start);
/* We fork off a child process, which wakes the Launcher whenever one
* of the input file descriptors needs attention. Otherwise we would
* run the Guest until it tries to output something. */
- waker_fd = setup_waker(lguest_fd, &device_list);
+ waker_fd = setup_waker(lguest_fd);
/* Finally, run the Guest. This doesn't return. */
- run_guest(lguest_fd, &device_list);
+ run_guest(lguest_fd);
}
/*:*/
diff --git a/Documentation/lguest/lguest.txt b/Documentation/lguest/lguest.txt
index 821617bd6c04..7885ab2d5f53 100644
--- a/Documentation/lguest/lguest.txt
+++ b/Documentation/lguest/lguest.txt
@@ -6,7 +6,7 @@ Lguest is designed to be a minimal hypervisor for the Linux kernel, for
Linux developers and users to experiment with virtualization with the
minimum of complexity. Nonetheless, it should have sufficient
features to make it useful for specific tasks, and, of course, you are
-encouraged to fork and enhance it.
+encouraged to fork and enhance it (see drivers/lguest/README).
Features:
@@ -23,19 +23,30 @@ Developer features:
Running Lguest:
-- Lguest runs the same kernel as guest and host. You can configure
- them differently, but usually it's easiest not to.
+- The easiest way to run lguest is to use same kernel as guest and host.
+ You can configure them differently, but usually it's easiest not to.
You will need to configure your kernel with the following options:
- CONFIG_HIGHMEM64G=n ("High Memory Support" "64GB")[1]
- CONFIG_TUN=y/m ("Universal TUN/TAP device driver support")
- CONFIG_EXPERIMENTAL=y ("Prompt for development and/or incomplete code/drivers")
- CONFIG_PARAVIRT=y ("Paravirtualization support (EXPERIMENTAL)")
- CONFIG_LGUEST=y/m ("Linux hypervisor example code")
-
- and I recommend:
- CONFIG_HZ=100 ("Timer frequency")[2]
+ "General setup":
+ "Prompt for development and/or incomplete code/drivers" = Y
+ (CONFIG_EXPERIMENTAL=y)
+
+ "Processor type and features":
+ "Paravirtualized guest support" = Y
+ "Lguest guest support" = Y
+ "High Memory Support" = off/4GB
+ "Alignment value to which kernel should be aligned" = 0x100000
+ (CONFIG_PARAVIRT=y, CONFIG_LGUEST_GUEST=y, CONFIG_HIGHMEM64G=n and
+ CONFIG_PHYSICAL_ALIGN=0x100000)
+
+ "Device Drivers":
+ "Network device support"
+ "Universal TUN/TAP device driver support" = M/Y
+ (CONFIG_TUN=m)
+ "Virtualization"
+ "Linux hypervisor example code" = M/Y
+ (CONFIG_LGUEST=m)
- A tool called "lguest" is available in this directory: type "make"
to build it. If you didn't build your kernel in-tree, use "make
@@ -51,14 +62,17 @@ Running Lguest:
dd if=/dev/zero of=rootfile bs=1M count=2048
qemu -cdrom image.iso -hda rootfile -net user -net nic -boot d
+ Make sure that you install a getty on /dev/hvc0 if you want to log in on the
+ console!
+
- "modprobe lg" if you built it as a module.
- Run an lguest as root:
- Documentation/lguest/lguest 64m vmlinux --tunnet=192.168.19.1 --block=rootfile root=/dev/lgba
+ Documentation/lguest/lguest 64 vmlinux --tunnet=192.168.19.1 --block=rootfile root=/dev/vda
Explanation:
- 64m: the amount of memory to use.
+ 64: the amount of memory to use, in MB.
vmlinux: the kernel image found in the top of your build directory. You
can also use a standard bzImage.
@@ -66,10 +80,10 @@ Running Lguest:
--tunnet=192.168.19.1: configures a "tap" device for networking with this
IP address.
- --block=rootfile: a file or block device which becomes /dev/lgba
+ --block=rootfile: a file or block device which becomes /dev/vda
inside the guest.
- root=/dev/lgba: this (and anything else on the command line) are
+ root=/dev/vda: this (and anything else on the command line) are
kernel boot parameters.
- Configuring networking. I usually have the host masquerade, using
@@ -99,31 +113,7 @@ Running Lguest:
"--sharenet=<filename>": any two guests using the same file are on
the same network. This file is created if it does not exist.
-Lguest I/O model:
-
-Lguest uses a simplified DMA model plus shared memory for I/O. Guests
-can communicate with each other if they share underlying memory
-(usually by the lguest program mmaping the same file), but they can
-use any non-shared memory to communicate with the lguest process.
-
-Guests can register DMA buffers at any key (must be a valid physical
-address) using the LHCALL_BIND_DMA(key, dmabufs, num<<8|irq)
-hypercall. "dmabufs" is the physical address of an array of "num"
-"struct lguest_dma": each contains a used_len, and an array of
-physical addresses and lengths. When a transfer occurs, the
-"used_len" field of one of the buffers which has used_len 0 will be
-set to the length transferred and the irq will fire.
+There is a helpful mailing list at http://ozlabs.org/mailman/listinfo/lguest
-Using an irq value of 0 unbinds the dma buffers.
-
-To send DMA, the LHCALL_SEND_DMA(key, dma_physaddr) hypercall is used,
-and the bytes used is written to the used_len field. This can be 0 if
-noone else has bound a DMA buffer to that key or some other error.
-DMA buffers bound by the same guest are ignored.
-
-Cheers!
+Good luck!
Rusty Russell rusty@rustcorp.com.au.
-
-[1] These are on various places on the TODO list, waiting for you to
- get annoyed enough at the limitation to fix it.
-[2] Lguest is not yet tickless when idle. See [1].
diff --git a/Documentation/local_ops.txt b/Documentation/local_ops.txt
index b0aca0705d1e..1a45f11e645e 100644
--- a/Documentation/local_ops.txt
+++ b/Documentation/local_ops.txt
@@ -27,7 +27,7 @@ CPU which owns the data. Therefore, care must taken to make sure that only one
CPU writes to the local_t data. This is done by using per cpu data and making
sure that we modify it from within a preemption safe context. It is however
permitted to read local_t data from any CPU : it will then appear to be written
-out of order wrt other memory writes on the owner CPU.
+out of order wrt other memory writes by the owner CPU.
* Implementation for a given architecture
@@ -45,6 +45,52 @@ long fails. The definition looks like :
typedef struct { atomic_long_t a; } local_t;
+* Rules to follow when using local atomic operations
+
+- Variables touched by local ops must be per cpu variables.
+- _Only_ the CPU owner of these variables must write to them.
+- This CPU can use local ops from any context (process, irq, softirq, nmi, ...)
+ to update its local_t variables.
+- Preemption (or interrupts) must be disabled when using local ops in
+ process context to make sure the process won't be migrated to a
+ different CPU between getting the per-cpu variable and doing the
+ actual local op.
+- When using local ops in interrupt context, no special care must be
+ taken on a mainline kernel, since they will run on the local CPU with
+ preemption already disabled. I suggest, however, to explicitly
+ disable preemption anyway to make sure it will still work correctly on
+ -rt kernels.
+- Reading the local cpu variable will provide the current copy of the
+ variable.
+- Reads of these variables can be done from any CPU, because updates to
+ "long", aligned, variables are always atomic. Since no memory
+ synchronization is done by the writer CPU, an outdated copy of the
+ variable can be read when reading some _other_ cpu's variables.
+
+
+* Rules to follow when using local atomic operations
+
+- Variables touched by local ops must be per cpu variables.
+- _Only_ the CPU owner of these variables must write to them.
+- This CPU can use local ops from any context (process, irq, softirq, nmi, ...)
+ to update its local_t variables.
+- Preemption (or interrupts) must be disabled when using local ops in
+ process context to make sure the process won't be migrated to a
+ different CPU between getting the per-cpu variable and doing the
+ actual local op.
+- When using local ops in interrupt context, no special care must be
+ taken on a mainline kernel, since they will run on the local CPU with
+ preemption already disabled. I suggest, however, to explicitly
+ disable preemption anyway to make sure it will still work correctly on
+ -rt kernels.
+- Reading the local cpu variable will provide the current copy of the
+ variable.
+- Reads of these variables can be done from any CPU, because updates to
+ "long", aligned, variables are always atomic. Since no memory
+ synchronization is done by the writer CPU, an outdated copy of the
+ variable can be read when reading some _other_ cpu's variables.
+
+
* How to use local atomic operations
#include <linux/percpu.h>
diff --git a/Documentation/m68k/kernel-options.txt b/Documentation/m68k/kernel-options.txt
index 59108cebe163..248589e8bcf5 100644
--- a/Documentation/m68k/kernel-options.txt
+++ b/Documentation/m68k/kernel-options.txt
@@ -192,10 +192,10 @@ Devices possible for Atari:
seconds.
-2.6) ramdisk=
+2.6) ramdisk_size=
-------------
-Syntax: ramdisk=<size>
+Syntax: ramdisk_size=<size>
This option instructs the kernel to set up a ramdisk of the given
size in KBytes. Do not use this option if the ramdisk contents are
@@ -890,10 +890,7 @@ Syntax: nosync:0
5.5.2) noasync
--------------
-Syntax: noasync:0
-
- Disables async and sync negotiation for all devices. Any value
- after the colon is acceptable (and has the same effect).
+[OBSOLETE, REMOVED]
5.5.3) nodisconnect
-------------------
diff --git a/Documentation/make/headers_install.txt b/Documentation/make/headers_install.txt
new file mode 100644
index 000000000000..f2481cabffcb
--- /dev/null
+++ b/Documentation/make/headers_install.txt
@@ -0,0 +1,46 @@
+Exporting kernel headers for use by userspace
+=============================================
+
+The "make headers_install" command exports the kernel's header files in a
+form suitable for use by userspace programs.
+
+The linux kernel's exported header files describe the API for user space
+programs attempting to use kernel services. These kernel header files are
+used by the system's C library (such as glibc or uClibc) to define available
+system calls, as well as constants and structures to be used with these
+system calls. The C library's header files include the kernel header files
+from the "linux" subdirectory. The system's libc headers are usually
+installed at the default location /usr/include and the kernel headers in
+subdirectories under that (most notably /usr/include/linux and
+/usr/include/asm).
+
+Kernel headers are backwards compatible, but not forwards compatible. This
+means that a program built against a C library using older kernel headers
+should run on a newer kernel (although it may not have access to new
+features), but a program built against newer kernel headers may not work on an
+older kernel.
+
+The "make headers_install" command can be run in the top level directory of the
+kernel source code (or using a standard out-of-tree build). It takes two
+optional arguments:
+
+ make headers_install ARCH=i386 INSTALL_HDR_PATH=/usr/include
+
+ARCH indicates which architecture to produce headers for, and defaults to the
+current architecture. The linux/asm directory of the exported kernel headers
+is platform-specific, to see a complete list of supported architectures use
+the command:
+
+ ls -d include/asm-* | sed 's/.*-//'
+
+INSTALL_HDR_PATH indicates where to install the headers. It defaults to
+"./usr/include".
+
+The command "make headers_install_all" exports headers for all architectures
+simultaneously. (This is mostly of interest to distribution maintainers,
+who create an architecture-independent tarball from the resulting include
+directory.) Remember to provide the appropriate linux/asm directory via "mv"
+or "ln -s" before building a C library with headers exported this way.
+
+The kernel header export infrastructure is maintained by David Woodhouse
+<dwmw2@infradead.org>.
diff --git a/Documentation/markers.txt b/Documentation/markers.txt
new file mode 100644
index 000000000000..d9f50a19fa0c
--- /dev/null
+++ b/Documentation/markers.txt
@@ -0,0 +1,83 @@
+ Using the Linux Kernel Markers
+
+ Mathieu Desnoyers
+
+
+This document introduces Linux Kernel Markers and their use. It provides
+examples of how to insert markers in the kernel and connect probe functions to
+them and provides some examples of probe functions.
+
+
+* Purpose of markers
+
+A marker placed in code provides a hook to call a function (probe) that you can
+provide at runtime. A marker can be "on" (a probe is connected to it) or "off"
+(no probe is attached). When a marker is "off" it has no effect, except for
+adding a tiny time penalty (checking a condition for a branch) and space
+penalty (adding a few bytes for the function call at the end of the
+instrumented function and adds a data structure in a separate section). When a
+marker is "on", the function you provide is called each time the marker is
+executed, in the execution context of the caller. When the function provided
+ends its execution, it returns to the caller (continuing from the marker site).
+
+You can put markers at important locations in the code. Markers are
+lightweight hooks that can pass an arbitrary number of parameters,
+described in a printk-like format string, to the attached probe function.
+
+They can be used for tracing and performance accounting.
+
+
+* Usage
+
+In order to use the macro trace_mark, you should include linux/marker.h.
+
+#include <linux/marker.h>
+
+And,
+
+trace_mark(subsystem_event, "myint %d mystring %s", someint, somestring);
+Where :
+- subsystem_event is an identifier unique to your event
+ - subsystem is the name of your subsystem.
+ - event is the name of the event to mark.
+- "myint %d mystring %s" is the formatted string for the serializer. "myint" and
+ "mystring" are repectively the field names associated with the first and
+ second parameter.
+- someint is an integer.
+- somestring is a char pointer.
+
+Connecting a function (probe) to a marker is done by providing a probe (function
+to call) for the specific marker through marker_probe_register() and can be
+activated by calling marker_arm(). Marker deactivation can be done by calling
+marker_disarm() as many times as marker_arm() has been called. Removing a probe
+is done through marker_probe_unregister(); it will disarm the probe and make
+sure there is no caller left using the probe when it returns. Probe removal is
+preempt-safe because preemption is disabled around the probe call. See the
+"Probe example" section below for a sample probe module.
+
+The marker mechanism supports inserting multiple instances of the same marker.
+Markers can be put in inline functions, inlined static functions, and
+unrolled loops as well as regular functions.
+
+The naming scheme "subsystem_event" is suggested here as a convention intended
+to limit collisions. Marker names are global to the kernel: they are considered
+as being the same whether they are in the core kernel image or in modules.
+Conflicting format strings for markers with the same name will cause the markers
+to be detected to have a different format string not to be armed and will output
+a printk warning which identifies the inconsistency:
+
+"Format mismatch for probe probe_name (format), marker (format)"
+
+
+* Probe / marker example
+
+See the example provided in samples/markers/src
+
+Compile them with your kernel.
+
+Run, as root :
+modprobe marker-example (insmod order is not important)
+modprobe probe-example
+cat /proc/marker-example (returns an expected error)
+rmmod marker-example probe-example
+dmesg
diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt
index 650657c54733..4e17beba2379 100644
--- a/Documentation/memory-barriers.txt
+++ b/Documentation/memory-barriers.txt
@@ -1479,7 +1479,8 @@ kernel.
Any atomic operation that modifies some state in memory and returns information
about the state (old or new) implies an SMP-conditional general memory barrier
-(smp_mb()) on each side of the actual operation. These include:
+(smp_mb()) on each side of the actual operation (with the exception of
+explicit lock operations, described later). These include:
xchg();
cmpxchg();
@@ -1536,10 +1537,19 @@ If they're used for constructing a lock of some description, then they probably
do need memory barriers as a lock primitive generally has to do things in a
specific order.
-
Basically, each usage case has to be carefully considered as to whether memory
barriers are needed or not.
+The following operations are special locking primitives:
+
+ test_and_set_bit_lock();
+ clear_bit_unlock();
+ __clear_bit_unlock();
+
+These implement LOCK-class and UNLOCK-class operations. These should be used in
+preference to other operations when implementing locking primitives, because
+their implementations can be optimised on many architectures.
+
[!] Note that special memory barrier primitives are available for these
situations because on some CPUs the atomic instructions used imply full memory
barriers, and so barrier instructions are superfluous in conjunction with them,
diff --git a/Documentation/memory-hotplug.txt b/Documentation/memory-hotplug.txt
index 5fbcc22c98e9..168117bd6ee8 100644
--- a/Documentation/memory-hotplug.txt
+++ b/Documentation/memory-hotplug.txt
@@ -2,7 +2,8 @@
Memory Hotplug
==============
-Last Updated: Jul 28 2007
+Created: Jul 28 2007
+Add description of notifier of memory hotplug Oct 11 2007
This document is about memory hotplug including how-to-use and current status.
Because Memory Hotplug is still under development, contents of this text will
@@ -24,7 +25,8 @@ be changed often.
6.1 Memory offline and ZONE_MOVABLE
6.2. How to offline memory
7. Physical memory remove
-8. Future Work List
+8. Memory hotplug event notifier
+9. Future Work List
Note(1): x86_64's has special implementation for memory hotplug.
This text does not describe it.
@@ -307,8 +309,58 @@ Need more implementation yet....
- Notification completion of remove works by OS to firmware.
- Guard from remove if not yet.
+--------------------------------
+8. Memory hotplug event notifier
+--------------------------------
+Memory hotplug has event notifer. There are 6 types of notification.
+
+MEMORY_GOING_ONLINE
+ Generated before new memory becomes available in order to be able to
+ prepare subsystems to handle memory. The page allocator is still unable
+ to allocate from the new memory.
+
+MEMORY_CANCEL_ONLINE
+ Generated if MEMORY_GOING_ONLINE fails.
+
+MEMORY_ONLINE
+ Generated when memory has succesfully brought online. The callback may
+ allocate pages from the new memory.
+
+MEMORY_GOING_OFFLINE
+ Generated to begin the process of offlining memory. Allocations are no
+ longer possible from the memory but some of the memory to be offlined
+ is still in use. The callback can be used to free memory known to a
+ subsystem from the indicated memory section.
+
+MEMORY_CANCEL_OFFLINE
+ Generated if MEMORY_GOING_OFFLINE fails. Memory is available again from
+ the section that we attempted to offline.
+
+MEMORY_OFFLINE
+ Generated after offlining memory is complete.
+
+A callback routine can be registered by
+ hotplug_memory_notifier(callback_func, priority)
+
+The second argument of callback function (action) is event types of above.
+The third argument is passed by pointer of struct memory_notify.
+
+struct memory_notify {
+ unsigned long start_pfn;
+ unsigned long nr_pages;
+ int status_cahnge_nid;
+}
+
+start_pfn is start_pfn of online/offline memory.
+nr_pages is # of pages of online/offline memory.
+status_change_nid is set node id when N_HIGH_MEMORY of nodemask is (will be)
+set/clear. It means a new(memoryless) node gets new memory by online and a
+node loses all memory. If this is -1, then nodemask status is not changed.
+If status_changed_nid >= 0, callback should create/discard structures for the
+node if necessary.
+
--------------
-8. Future Work
+9. Future Work
--------------
- allowing memory hot-add to ZONE_MOVABLE. maybe we need some switch like
sysctl or new control file.
diff --git a/Documentation/mips/00-INDEX b/Documentation/mips/00-INDEX
new file mode 100644
index 000000000000..3f13bf8043d2
--- /dev/null
+++ b/Documentation/mips/00-INDEX
@@ -0,0 +1,6 @@
+00-INDEX
+ - this file.
+AU1xxx_IDE.README
+ - README for MIPS AU1XXX IDE driver.
+GT64120.README
+ - README for dir with info on MIPS boards using GT-64120 or GT-64120A.
diff --git a/Documentation/mips/AU1xxx_IDE.README b/Documentation/mips/AU1xxx_IDE.README
index afb31c141d9d..5c8334123f4f 100644
--- a/Documentation/mips/AU1xxx_IDE.README
+++ b/Documentation/mips/AU1xxx_IDE.README
@@ -59,7 +59,7 @@ Four configs variables are introduced:
CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA - enable the PIO+DBDMA mode
CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA - enable the MWDMA mode
CONFIG_BLK_DEV_IDE_AU1XXX_BURSTABLE_ON - set Burstable FIFO in DBDMA
- controler
+ controller
CONFIG_BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ - maximum transfer size
per descriptor
diff --git a/Documentation/mips/time.README b/Documentation/mips/time.README
deleted file mode 100644
index a4ce603ed3b3..000000000000
--- a/Documentation/mips/time.README
+++ /dev/null
@@ -1,173 +0,0 @@
-README for MIPS time services
-
-Jun Sun
-jsun@mvista.com or jsun@junsun.net
-
-
-ABOUT
------
-This file describes the new arch/mips/kernel/time.c, related files and the
-services they provide.
-
-If you are short in patience and just want to know how to use time.c for a
-new board or convert an existing board, go to the last section.
-
-
-FILES, COMPATABILITY AND CONFIGS
----------------------------------
-
-The old arch/mips/kernel/time.c is renamed to old-time.c.
-
-A new time.c is put there, together with include/asm-mips/time.h.
-
-Two configs variables are introduced, CONFIG_OLD_TIME_C and CONFIG_NEW_TIME_C.
-So we allow boards using
-
- 1) old time.c (CONFIG_OLD_TIME_C)
- 2) new time.c (CONFIG_NEW_TIME_C)
- 3) neither (their own private time.c)
-
-However, it is expected every board will move to the new time.c in the near
-future.
-
-
-WHAT THE NEW CODE PROVIDES?
----------------------------
-
-The new time code provide the following services:
-
- a) Implements functions required by Linux common code:
- time_init
-
- b) provides an abstraction of RTC and null RTC implementation as default.
- extern unsigned long (*rtc_get_time)(void);
- extern int (*rtc_set_time)(unsigned long);
-
- c) high-level and low-level timer interrupt routines where the timer
- interrupt source may or may not be the CPU timer. The high-level
- routine is dispatched through do_IRQ() while the low-level is
- dispatched in assemably code (usually int-handler.S)
-
-
-WHAT THE NEW CODE REQUIRES?
----------------------------
-
-For the new code to work properly, each board implementation needs to supply
-the following functions or values:
-
- a) board_time_init - a function pointer. Invoked at the beginnig of
- time_init(). It is optional.
- 1. (optional) set up RTC routines
- 2. (optional) calibrate and set the mips_hpt_frequency
-
- b) plat_timer_setup - a function pointer. Invoked at the end of time_init()
- 1. (optional) over-ride any decisions made in time_init()
- 2. set up the irqaction for timer interrupt.
- 3. enable the timer interrupt
-
- c) (optional) board-specific RTC routines.
-
- d) (optional) mips_hpt_frequency - It must be definied if the board
- is using CPU counter for timer interrupt.
-
-
-PORTING GUIDE
--------------
-
-Step 1: decide how you like to implement the time services.
-
- a) does this board have a RTC? If yes, implement the two RTC funcs.
-
- b) does the CPU have counter/compare registers?
-
- If the answer is no, you need a timer to provide the timer interrupt
- at 100 HZ speed.
-
- c) The following sub steps assume your CPU has counter register.
- Do you plan to use the CPU counter register as the timer interrupt
- or use an exnternal timer?
-
- In order to use CPU counter register as the timer interrupt source, you
- must know the counter speed (mips_hpt_frequency). It is usually the
- same as the CPU speed or an integral divisor of it.
-
- d) decide on whether you want to use high-level or low-level timer
- interrupt routines. The low-level one is presumably faster, but should
- not make too mcuh difference.
-
-
-Step 2: the machine setup() function
-
- If you supply board_time_init(), set the function poointer.
-
-
-Step 3: implement rtc routines, board_time_init() and plat_timer_setup()
- if needed.
-
- board_time_init() -
- a) (optional) set up RTC routines,
- b) (optional) calibrate and set the mips_hpt_frequency
- (only needed if you intended to use cpu counter as timer interrupt
- source)
-
- plat_timer_setup() -
- a) (optional) over-write any choices made above by time_init().
- b) machine specific code should setup the timer irqaction.
- c) enable the timer interrupt
-
-
- If the RTC chip is a common chip, I suggest the routines are put under
- arch/mips/libs. For example, for DS1386 chip, one would create
- rtc-ds1386.c under arch/mips/lib directory. Add the following line to
- the arch/mips/lib/Makefile:
-
- obj-$(CONFIG_DDB5476) += rtc-ds1386.o
-
-Step 4: if you are using low-level timer interrupt, change your interrupt
- dispathcing code to check for timer interrupt and jump to
- ll_timer_interrupt() directly if one is detected.
-
-Step 5: Modify arch/mips/config.in and add CONFIG_NEW_TIME_C to your machine.
- Modify the appropriate defconfig if applicable.
-
-Final notes:
-
-For some tricky cases, you may need to add your own wrapper functions
-for some of the functions in time.c.
-
-For example, you may define your own timer interrupt routine, which does
-some of its own processing and then calls timer_interrupt().
-
-You can also over-ride any of the built-in functions (RTC routines
-and/or timer interrupt routine).
-
-
-PORTING NOTES FOR SMP
-----------------------
-
-If you have a SMP box, things are slightly more complicated.
-
-The time service running every jiffy is logically divided into two parts:
-
- 1) the one for the whole system (defined in timer_interrupt())
- 2) the one that should run for each CPU (defined in local_timer_interrupt())
-
-You need to decide on your timer interrupt sources.
-
- case 1) - whole system has only one timer interrupt delivered to one CPU
-
- In this case, you set up timer interrupt as in UP systems. In addtion,
- you need to set emulate_local_timer_interrupt to 1 so that other
- CPUs get to call local_timer_interrupt().
-
- THIS IS CURRENTLY NOT IMPLEMNETED. However, it is rather easy to write
- one should such a need arise. You simply make a IPI call.
-
- case 2) - each CPU has a separate timer interrupt
-
- In this case, you need to set up IRQ such that each of them will
- call local_timer_interrupt(). In addition, you need to arrange
- one and only one of them to call timer_interrupt().
-
- You can also do the low-level version of those interrupt routines,
- following similar dispatching routes described above.
diff --git a/Documentation/mutex-design.txt b/Documentation/mutex-design.txt
index cbf79881a41c..aa60d1f627e5 100644
--- a/Documentation/mutex-design.txt
+++ b/Documentation/mutex-design.txt
@@ -90,7 +90,8 @@ of advantages of mutexes:
* - task may not exit with mutex held
* - memory areas where held locks reside must not be freed
* - held mutexes must not be reinitialized
- * - mutexes may not be used in irq contexts
+ * - mutexes may not be used in hardware or software interrupt
+ * contexts such as tasklets and timers
furthermore, there are also convenience features in the debugging
code:
@@ -132,4 +133,6 @@ the APIs of 'struct mutex' have been streamlined:
int mutex_trylock(struct mutex *lock);
void mutex_unlock(struct mutex *lock);
int mutex_is_locked(struct mutex *lock);
-
+ void mutex_lock_nested(struct mutex *lock, unsigned int subclass);
+ int mutex_lock_interruptible_nested(struct mutex *lock,
+ unsigned int subclass);
diff --git a/Documentation/networking/00-INDEX b/Documentation/networking/00-INDEX
index 153d84d281e6..563e442f2d42 100644
--- a/Documentation/networking/00-INDEX
+++ b/Documentation/networking/00-INDEX
@@ -4,8 +4,6 @@
- information on the 3Com EtherLink Plus (3c505) driver.
6pack.txt
- info on the 6pack protocol, an alternative to KISS for AX.25
-Configurable
- - info on some of the configurable network parameters
DLINK.txt
- info on the D-Link DE-600/DE-620 parallel port pocket adapters
PLIP.txt
@@ -26,8 +24,6 @@ baycom.txt
- info on the driver for Baycom style amateur radio modems
bridge.txt
- where to get user space programs for ethernet bridging with Linux.
-comx.txt
- - info on drivers for COMX line of synchronous serial adapters.
cops.txt
- info on the COPS LocalTalk Linux driver
cs89x0.txt
@@ -78,22 +74,14 @@ ltpc.txt
- the Apple or Farallon LocalTalk PC card driver
multicast.txt
- Behaviour of cards under Multicast
-ncsa-telnet
- - notes on how NCSA telnet (DOS) breaks with MTU discovery enabled.
-net-modules.txt
- - info and "insmod" parameters for all network driver modules.
netdevices.txt
- info on network device driver functions exported to the kernel.
olympic.txt
- IBM PCI Pit/Pit-Phy/Olympic Token Ring driver info.
policy-routing.txt
- IP policy-based routing
-pt.txt
- - the Gracilis Packetwin AX.25 device driver
ray_cs.txt
- Raylink Wireless LAN card driver info.
-routing.txt
- - the new routing mechanism
shaper.txt
- info on the module that can shape/limit transmitted traffic.
sk98lin.txt
diff --git a/Documentation/networking/3c505.txt b/Documentation/networking/3c505.txt
index b9d5b7230118..72f38b13101d 100644
--- a/Documentation/networking/3c505.txt
+++ b/Documentation/networking/3c505.txt
@@ -14,8 +14,7 @@ If no base address is given at boot time, the driver will autoprobe
ports 0x300, 0x280 and 0x310 (in that order). If no IRQ is given, the driver
will try to probe for it.
-The driver can be used as a loadable module. See net-modules.txt for details
-of the parameters it can take.
+The driver can be used as a loadable module.
Theoretically, one instance of the driver can now run multiple cards,
in the standard way (when loading a module, say "modprobe 3c505
diff --git a/Documentation/networking/Configurable b/Documentation/networking/Configurable
deleted file mode 100644
index 69c0dd466ead..000000000000
--- a/Documentation/networking/Configurable
+++ /dev/null
@@ -1,34 +0,0 @@
-
-There are a few network parameters that can be tuned to better match
-the kernel to your system hardware and intended usage. The defaults
-are usually a good choice for 99% of the people 99% of the time, but
-you should be aware they do exist and can be changed.
-
-The current list of parameters can be found in the files:
-
- linux/net/TUNABLE
- Documentation/networking/ip-sysctl.txt
-
-Some of these are accessible via the sysctl interface, and many more are
-scheduled to be added in this way. For example, some parameters related
-to Address Resolution Protocol (ARP) are very easily viewed and altered.
-
- # cat /proc/sys/net/ipv4/arp_timeout
- 6000
- # echo 7000 > /proc/sys/net/ipv4/arp_timeout
- # cat /proc/sys/net/ipv4/arp_timeout
- 7000
-
-Others are already accessible via the related user space programs.
-For example, MAX_WINDOW has a default of 32 k which is a good choice for
-modern hardware, but if you have a slow (8 bit) Ethernet card and/or a slow
-machine, then this will be far too big for the card to keep up with fast
-machines transmitting on the same net, resulting in overruns and receive errors.
-A value of about 4 k would be more appropriate, which can be set via:
-
- # route add -net 192.168.3.0 window 4096
-
-The remainder of these can only be presently changed by altering a #define
-in the related header file. This means an edit and recompile cycle.
-
- Paul Gortmaker 06/96
diff --git a/Documentation/networking/bcm43xx.txt b/Documentation/networking/bcm43xx.txt
index a136721499bf..d602c8d6ff3e 100644
--- a/Documentation/networking/bcm43xx.txt
+++ b/Documentation/networking/bcm43xx.txt
@@ -37,7 +37,7 @@ all, distributions. There is, however, additional software that is
required. The firmware used by the chip is the intellectual property
of Broadcom and they have not given the bcm43xx team redistribution
rights to this firmware. Since we cannot legally redistribute
-the firwmare we cannot include it with the driver. Furthermore, it
+the firmware we cannot include it with the driver. Furthermore, it
cannot be placed in the downloadable archives of any distributing
organization; therefore, the user is responsible for obtaining the
firmware and placing it in the appropriate location so that the driver
diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt
index 1da566630831..11340625e363 100644
--- a/Documentation/networking/bonding.txt
+++ b/Documentation/networking/bonding.txt
@@ -281,6 +281,39 @@ downdelay
will be rounded down to the nearest multiple. The default
value is 0.
+fail_over_mac
+
+ Specifies whether active-backup mode should set all slaves to
+ the same MAC address (the traditional behavior), or, when
+ enabled, change the bond's MAC address when changing the
+ active interface (i.e., fail over the MAC address itself).
+
+ Fail over MAC is useful for devices that cannot ever alter
+ their MAC address, or for devices that refuse incoming
+ broadcasts with their own source MAC (which interferes with
+ the ARP monitor).
+
+ The down side of fail over MAC is that every device on the
+ network must be updated via gratuitous ARP, vs. just updating
+ a switch or set of switches (which often takes place for any
+ traffic, not just ARP traffic, if the switch snoops incoming
+ traffic to update its tables) for the traditional method. If
+ the gratuitous ARP is lost, communication may be disrupted.
+
+ When fail over MAC is used in conjuction with the mii monitor,
+ devices which assert link up prior to being able to actually
+ transmit and receive are particularly susecptible to loss of
+ the gratuitous ARP, and an appropriate updelay setting may be
+ required.
+
+ A value of 0 disables fail over MAC, and is the default. A
+ value of 1 enables fail over MAC. This option is enabled
+ automatically if the first slave added cannot change its MAC
+ address. This option may be modified via sysfs only when no
+ slaves are present in the bond.
+
+ This option was added in bonding version 3.2.0.
+
lacp_rate
Option specifying the rate in which we'll ask our link partner
diff --git a/Documentation/networking/comx.txt b/Documentation/networking/comx.txt
deleted file mode 100644
index d1526eba2645..000000000000
--- a/Documentation/networking/comx.txt
+++ /dev/null
@@ -1,248 +0,0 @@
-
- COMX drivers for the 2.2 kernel
-
-Originally written by: Tivadar Szemethy, <tiv@itc.hu>
-Currently maintained by: Gergely Madarasz <gorgo@itc.hu>
-
-Last change: 21/06/1999.
-
-INTRODUCTION
-
-This document describes the software drivers and their use for the
-COMX line of synchronous serial adapters for Linux version 2.2.0 and
-above.
-The cards are produced and sold by ITC-Pro Ltd. Budapest, Hungary
-For further info contact <info@itc.hu>
-or http://www.itc.hu (mostly in Hungarian).
-The firmware files and software are available from ftp://ftp.itc.hu
-
-Currently, the drivers support the following cards and protocols:
-
-COMX (2x64 kbps intelligent board)
-CMX (1x256 + 1x128 kbps intelligent board)
-HiCOMX (2x2Mbps intelligent board)
-LoCOMX (1x512 kbps passive board)
-MixCOM (1x512 or 2x512kbps passive board with a hardware watchdog an
- optional BRI interface and optional flashROM (1-32M))
-SliceCOM (1x2Mbps channelized E1 board)
-PciCOM (X21)
-
-At the moment of writing this document, the (Cisco)-HDLC, LAPB, SyncPPP and
-Frame Relay (DTE, rfc1294 IP encapsulation with partially implemented Q933a
-LMI) protocols are available as link-level protocol.
-X.25 support is being worked on.
-
-USAGE
-
-Load the comx.o module and the hardware-specific and protocol-specific
-modules you'll need into the running kernel using the insmod utility.
-This creates the /proc/comx directory.
-See the example scripts in the 'etc' directory.
-
-/proc INTERFACE INTRO
-
-The COMX driver set has a new type of user interface based on the /proc
-filesystem which eliminates the need for external user-land software doing
-IOCTL calls.
-Each network interface or device (i.e. those ones you configure with 'ifconfig'
-and 'route' etc.) has a corresponding directory under /proc/comx. You can
-dynamically create a new interface by saying 'mkdir /proc/comx/comx0' (or you
-can name it whatever you want up to 8 characters long, comx[n] is just a
-convention).
-Generally the files contained in these directories are text files, which can
-be viewed by 'cat filename' and you can write a string to such a file by
-saying 'echo _string_ >filename'. This is very similar to the sysctl interface.
-Don't use a text editor to edit these files, always use 'echo' (or 'cat'
-where appropriate).
-When you've created the comx[n] directory, two files are created automagically
-in it: 'boardtype' and 'protocol'. You have to fill in these files correctly
-for your board and protocol you intend to use (see the board and protocol
-descriptions in this file below or the example scripts in the 'etc' directory).
-After filling in these files, other files will appear in the directory for
-setting the various hardware- and protocol-related informations (for example
-irq and io addresses, keepalive values etc.) These files are set to default
-values upon creation, so you don't necessarily have to change all of them.
-
-When you're ready with filling in the files in the comx[n] directory, you can
-configure the corresponding network interface with the standard network
-configuration utilities. If you're unable to bring the interfaces up, look up
-the various kernel log files on your system, and consult the messages for
-a probable reason.
-
-EXAMPLE
-
-To create the interface 'comx0' which is the first channel of a COMX card:
-
-insmod comx
-# insmod comx-hw-comx ; insmod comx-proto-ppp (these are usually
-autoloaded if you use the kernel module loader)
-
-mkdir /proc/comx/comx0
-echo comx >/proc/comx/comx0/boardtype
-echo 0x360 >/proc/comx/comx0/io <- jumper-selectable I/O port
-echo 0x0a >/proc/comx/comx0/irq <- jumper-selectable IRQ line
-echo 0xd000 >/proc/comx/comx0/memaddr <- software-configurable memory
- address. COMX uses 64 KB, and this
- can be: 0xa000, 0xb000, 0xc000,
- 0xd000, 0xe000. Avoid conflicts
- with other hardware.
-cat </etc/siol1.rom >/proc/comx/comx0/firmware <- the firmware for the card
-echo HDLC >/proc/comx/comx0/protocol <- the data-link protocol
-echo 10 >/proc/comx/comx0/keepalive <- the keepalive for the protocol
-ifconfig comx0 1.2.3.4 pointopoint 5.6.7.8 netmask 255.255.255.255 <-
- finally configure it with ifconfig
-Check its status:
-cat /proc/comx/comx0/status
-
-If you want to use the second channel of this board:
-
-mkdir /proc/comx/comx1
-echo comx >/proc/comx/comx1/boardtype
-echo 0x360 >/proc/comx/comx1/io
-echo 10 >/proc/comx/comx1/irq
-echo 0xd000 >/proc/comx/comx1/memaddr
-echo 1 >/proc/comx/comx1/channel <- channels are numbered
- as 0 (default) and 1
-
-Now, check if the driver recognized that you're going to use the other
-channel of the same adapter:
-
-cat /proc/comx/comx0/twin
-comx1
-cat /proc/comx/comx1/twin
-comx0
-
-You don't have to load the firmware twice, if you use both channels of
-an adapter, just write it into the channel 0's /proc firmware file.
-
-Default values: io 0x360 for COMX, 0x320 (HICOMX), irq 10, memaddr 0xd0000
-
-THE LOCOMX HARDWARE DRIVER
-
-The LoCOMX driver doesn't require firmware, and it doesn't use memory either,
-but it uses DMA channels 1 and 3. You can set the clock rate (if enabled by
-jumpers on the board) by writing the kbps value into the file named 'clock'.
-Set it to 'external' (it is the default) if you have external clock source.
-
-(Note: currently the LoCOMX driver does not support the internal clock)
-
-THE COMX, CMX AND HICOMX DRIVERS
-
-On the HICOMX, COMX and CMX, you have to load the firmware (it is different for
-the three cards!). All these adapters can share the same memory
-address (we usually use 0xd0000). On the CMX you can set the internal
-clock rate (if enabled by jumpers on the small adapter boards) by writing
-the kbps value into the 'clock' file. You have to do this before initializing
-the card. If you use both HICOMX and CMX/COMX cards, initialize the HICOMX
-first. The I/O address of the HICOMX board is not configurable by any
-method available to the user: it is hardwired to 0x320, and if you have to
-change it, consult ITC-Pro Ltd.
-
-THE MIXCOM DRIVER
-
-The MixCOM board doesn't require firmware, the driver communicates with
-it through I/O ports. You can have three of these cards in one machine.
-
-THE SLICECOM DRIVER
-
-The SliceCOM board doesn't require firmware. You can have 4 of these cards
-in one machine. The driver doesn't (yet) support shared interrupts, so
-you will need a separate IRQ line for every board.
-Read Documentation/networking/slicecom.txt for help on configuring
-this adapter.
-
-THE HDLC/PPP LINE PROTOCOL DRIVER
-
-The HDLC/SyncPPP line protocol driver uses the kernel's built-in syncppp
-driver (syncppp.o). You don't have to manually select syncppp.o when building
-the kernel, the dependencies compile it in automatically.
-
-
-
-
-EXAMPLE
-(setting up hw parameters, see above)
-
-# using HDLC:
-echo hdlc >/proc/comx/comx0/protocol
-echo 10 >/proc/comx/comx0/keepalive <- not necessary, 10 is the default
-ifconfig comx0 1.2.3.4 pointopoint 5.6.7.8 netmask 255.255.255.255
-
-(setting up hw parameters, see above)
-
-# using PPP:
-echo ppp >/proc/comx/comx0/protocol
-ifconfig comx0 up
-ifconfig comx0 1.2.3.4 pointopoint 5.6.7.8 netmask 255.255.255.255
-
-
-THE LAPB LINE PROTOCOL DRIVER
-
-For this, you'll need to configure LAPB support (See 'LAPB Data Link Driver' in
-'Network options' section) into your kernel (thanks to Jonathan Naylor for his
-excellent implementation).
-comx-proto-lapb.o provides the following files in the appropriate directory
-(the default values in parens): t1 (5), t2 (1), n2 (20), mode (DTE, STD) and
-window (7). Agree with the administrator of your peer router on these
-settings (most people use defaults, but you have to know if you are DTE or
-DCE).
-
-EXAMPLE
-
-(setting up hw parameters, see above)
-echo lapb >/proc/comx/comx0/protocol
-echo dce >/proc/comx/comx0/mode <- DCE interface in this example
-ifconfig comx0 1.2.3.4 pointopoint 5.6.7.8 netmask 255.255.255.255
-
-
-THE FRAME RELAY PROTOCOL DRIVER
-
-You DON'T need any other frame relay related modules from the kernel to use
-COMX-Frame Relay. This protocol is a bit more complicated than the others,
-because it allows to use 'subinterfaces' or DLCIs within one physical device.
-First you have to create the 'master' device (the actual physical interface)
-as you would do for other protocols. Specify 'frad' as protocol type.
-Now you can bring this interface up by saying 'ifconfig comx0 up' (or whatever
-you've named the interface). Do not assign any IP address to this interface
-and do not set any routes through it.
-Then, set up your DLCIs the following way: create a comx interface for each
-DLCI you intend to use (with mkdir), and write 'dlci' to the 'boardtype' file,
-and 'ietf-ip' to the 'protocol' file. Currently, the only supported
-encapsulation type is this (also called as RFC1294/1490 IP encapsulation).
-Write the DLCI number to the 'dlci' file, and write the name of the physical
-COMX device to the file called 'master'.
-Now you can assign an IP address to this interface and set routes using it.
-See the example file for further info and example config script.
-Notes: this driver implements a DTE interface with partially implemented
-Q933a LMI.
-You can find an extensively commented example in the 'etc' directory.
-
-FURTHER /proc FILES
-
-boardtype:
-Type of the hardware. Valid values are:
- 'comx', 'hicomx', 'locomx', 'cmx', 'slicecom'.
-
-protocol:
-Data-link protocol on this channel. Can be: HDLC, LAPB, PPP, FRAD
-
-status:
-You can read the channel's actual status from the 'status' file, for example
-'cat /proc/comx/comx3/status'.
-
-lineup_delay:
-Interpreted in seconds (default is 1). Used to avoid line jitter: the system
-will consider the line status 'UP' only if it is up for at least this number
-of seconds.
-
-debug:
-You can set various debug options through this file. Valid options are:
-'comx_events', 'comx_tx', 'comx_rx', 'hw_events', 'hw_tx', 'hw_rx'.
-You can enable a debug options by writing its name prepended by a '+' into
-the debug file, for example 'echo +comx_rx >comx0/debug'.
-Disabling an option happens similarly, use the '-' prefix
-(e.g. 'echo -hw_rx >debug').
-Debug results can be read from the debug file, for example:
-tail -f /proc/comx/comx2/debug
-
-
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index 6ae2feff3087..6f7872ba1def 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -184,14 +184,14 @@ tcp_frto - INTEGER
F-RTO is an enhanced recovery algorithm for TCP retransmission
timeouts. It is particularly beneficial in wireless environments
where packet loss is typically due to random radio interference
- rather than intermediate router congestion. FRTO is sender-side
+ rather than intermediate router congestion. F-RTO is sender-side
only modification. Therefore it does not require any support from
the peer, but in a typical case, however, where wireless link is
the local access link and most of the data flows downlink, the
- faraway servers should have FRTO enabled to take advantage of it.
+ faraway servers should have F-RTO enabled to take advantage of it.
If set to 1, basic version is enabled. 2 enables SACK enhanced
F-RTO if flow uses SACK. The basic version can be used also when
- SACK is in use though scenario(s) with it exists where FRTO
+ SACK is in use though scenario(s) with it exists where F-RTO
interacts badly with the packet counting of the SACK enabled TCP
flow.
@@ -293,7 +293,7 @@ tcp_no_metrics_save - BOOLEAN
when the connection closes, so that connections established in the
near future can use these to set initial conditions. Usually, this
increases overall performance, but may sometimes cause performance
- degredation. If set, TCP will not cache metrics on closing
+ degradation. If set, TCP will not cache metrics on closing
connections.
tcp_orphan_retries - INTEGER
diff --git a/Documentation/networking/ncsa-telnet b/Documentation/networking/ncsa-telnet
deleted file mode 100644
index d77d28b09093..000000000000
--- a/Documentation/networking/ncsa-telnet
+++ /dev/null
@@ -1,16 +0,0 @@
-NCSA telnet doesn't work with path MTU discovery enabled. This is due to a
-bug in NCSA that also stops it working with other modern networking code
-such as Solaris.
-
-The following information is courtesy of
-Marek <marekm@i17linuxb.ists.pwr.wroc.pl>
-
-There is a fixed version somewhere on ftp.upe.ac.za (sorry, I don't
-remember the exact pathname, and this site is very slow from here).
-It may or may not be faster for you to get it from
-ftp://ftp.ists.pwr.wroc.pl/pub/msdos/telnet/ncsa_upe/tel23074.zip
-(source is in v230704s.zip). I have tested it with 1.3.79 (with
-path mtu discovery enabled - ncsa 2.3.08 didn't work) and it seems
-to work. I don't know if anyone is working on this code - this
-version is over a year old. Too bad - it's faster and often more
-stable than these windoze telnets, and runs on almost anything...
diff --git a/Documentation/networking/net-modules.txt b/Documentation/networking/net-modules.txt
deleted file mode 100644
index 98c4392dd0fd..000000000000
--- a/Documentation/networking/net-modules.txt
+++ /dev/null
@@ -1,315 +0,0 @@
-Wed 2-Aug-95 <matti.aarnio@utu.fi>
-
- Linux network driver modules
-
- Do not mistake this for "README.modules" at the top-level
- directory! That document tells about modules in general, while
- this one tells only about network device driver modules.
-
- This is a potpourri of INSMOD-time(*) configuration options
- (if such exists) and their default values of various modules
- in the Linux network drivers collection.
-
- Some modules have also hidden (= non-documented) tunable values.
- The choice of not documenting them is based on general belief, that
- the less the user needs to know, the better. (There are things that
- driver developers can use, others should not confuse themselves.)
-
- In many cases it is highly preferred that insmod:ing is done
- ONLY with defining an explicit address for the card, AND BY
- NOT USING AUTO-PROBING!
-
- Now most cards have some explicitly defined base address that they
- are compiled with (to avoid auto-probing, among other things).
- If that compiled value does not match your actual configuration,
- do use the "io=0xXXX" -parameter for the insmod, and give there
- a value matching your environment.
-
- If you are adventurous, you can ask the driver to autoprobe
- by using the "io=0" parameter, however it is a potentially dangerous
- thing to do in a live system. (If you don't know where the
- card is located, you can try autoprobing, and after possible
- crash recovery, insmod with proper IO-address..)
-
- --------------------------
- (*) "INSMOD-time" means when you load module with
- /sbin/insmod you can feed it optional parameters.
- See "man insmod".
- --------------------------
-
-
- 8390 based Network Modules (Paul Gortmaker, Nov 12, 1995)
- --------------------------
-
-(Includes: smc-ultra, ne, wd, 3c503, hp, hp-plus, e2100 and ac3200)
-
-The 8390 series of network drivers now support multiple card systems without
-reloading the same module multiple times (memory efficient!) This is done by
-specifying multiple comma separated values, such as:
-
- insmod 3c503.o io=0x280,0x300,0x330,0x350 xcvr=0,1,0,1
-
-The above would have the one module controlling four 3c503 cards, with card 2
-and 4 using external transceivers. The "insmod" manual describes the usage
-of comma separated value lists.
-
-It is *STRONGLY RECOMMENDED* that you supply "io=" instead of autoprobing.
-If an "io=" argument is not supplied, then the ISA drivers will complain
-about autoprobing being not recommended, and begrudgingly autoprobe for
-a *SINGLE CARD ONLY* -- if you want to use multiple cards you *have* to
-supply an "io=0xNNN,0xQQQ,..." argument.
-
-The ne module is an exception to the above. A NE2000 is essentially an
-8390 chip, some bus glue and some RAM. Because of this, the ne probe is
-more invasive than the rest, and so at boot we make sure the ne probe is
-done last of all the 8390 cards (so that it won't trip over other 8390 based
-cards) With modules we can't ensure that all other non-ne 8390 cards have
-already been found. Because of this, the ne module REQUIRES an "io=0xNNN"
-argument passed in via insmod. It will refuse to autoprobe.
-
-It is also worth noting that auto-IRQ probably isn't as reliable during
-the flurry of interrupt activity on a running machine. Cards such as the
-ne2000 that can't get the IRQ setting from an EEPROM or configuration
-register are probably best supplied with an "irq=M" argument as well.
-
-
-----------------------------------------------------------------------
-Card/Module List - Configurable Parameters and Default Values
-----------------------------------------------------------------------
-
-3c501.c:
- io = 0x280 IO base address
- irq = 5 IRQ
- (Probes ports: 0x280, 0x300)
-
-3c503.c:
- io = 0 (It will complain if you don't supply an "io=0xNNN")
- irq = 0 (IRQ software selected by driver using autoIRQ)
- xcvr = 0 (Use xcvr=1 to select external transceiver.)
- (Probes ports: 0x300, 0x310, 0x330, 0x350, 0x250, 0x280, 0x2A0, 0x2E0)
-
-3c505.c:
- io = 0
- irq = 0
- dma = 6 (not autoprobed)
- (Probes ports: 0x300, 0x280, 0x310)
-
-3c507.c:
- io = 0x300
- irq = 0
- (Probes ports: 0x300, 0x320, 0x340, 0x280)
-
-3c509.c:
- io = 0
- irq = 0
- ( Module load-time probing Works reliably only on EISA, ISA ID-PROBE
- IS NOT RELIABLE! Compile this driver statically into kernel for
- now, if you need it auto-probing on an ISA-bus machine. )
-
-8390.c:
- (No public options, several other modules need this one)
-
-a2065.c:
- Since this is a Zorro board, it supports full autoprobing, even for
- multiple boards. (m68k/Amiga)
-
-ac3200.c:
- io = 0 (Checks 0x1000 to 0x8fff in 0x1000 intervals)
- irq = 0 (Read from config register)
- (EISA probing..)
-
-apricot.c:
- io = 0x300 (Can't be altered!)
- irq = 10
-
-arcnet.c:
- io = 0
- irqnum = 0
- shmem = 0
- num = 0
- DO SET THESE MANUALLY AT INSMOD!
- (When probing, looks at the following possible addresses:
- Suggested ones:
- 0x300, 0x2E0, 0x2F0, 0x2D0
- Other ones:
- 0x200, 0x210, 0x220, 0x230, 0x240, 0x250, 0x260, 0x270,
- 0x280, 0x290, 0x2A0, 0x2B0, 0x2C0,
- 0x310, 0x320, 0x330, 0x340, 0x350, 0x360, 0x370,
- 0x380, 0x390, 0x3A0, 0x3E0, 0x3F0 )
-
-ariadne.c:
- Since this is a Zorro board, it supports full autoprobing, even for
- multiple boards. (m68k/Amiga)
-
-at1700.c:
- io = 0x260
- irq = 0
- (Probes ports: 0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300)
-
-atarilance.c:
- Supports full autoprobing. (m68k/Atari)
-
-atp.c: *Not modularized*
- (Probes ports: 0x378, 0x278, 0x3BC;
- fixed IRQs: 5 and 7 )
-
-cops.c:
- io = 0x240
- irq = 5
- nodeid = 0 (AutoSelect = 0, NodeID 1-254 is hand selected.)
- (Probes ports: 0x240, 0x340, 0x200, 0x210, 0x220, 0x230, 0x260,
- 0x2A0, 0x300, 0x310, 0x320, 0x330, 0x350, 0x360)
-
-de4x5.c:
- io = 0x000b
- irq = 10
- is_not_dec = 0 -- For non-DEC card using DEC 21040/21041/21140 chip, set this to 1
- (EISA, and PCI probing)
-
-de600.c:
- de600_debug = 0
- (On port 0x378, irq 7 -- lpt1; compile time configurable)
-
-de620.c:
- bnc = 0, utp = 0 <-- Force media by setting either.
- io = 0x378 (also compile-time configurable)
- irq = 7
-
-depca.c:
- io = 0x200
- irq = 7
- (Probes ports: ISA: 0x300, 0x200;
- EISA: 0x0c00 )
-
-dummy.c:
- No options
-
-e2100.c:
- io = 0 (It will complain if you don't supply an "io=0xNNN")
- irq = 0 (IRQ software selected by driver)
- mem = 0 (Override default shared memory start of 0xd0000)
- xcvr = 0 (Use xcvr=1 to select external transceiver.)
- (Probes ports: 0x300, 0x280, 0x380, 0x220)
-
-eepro.c:
- io = 0x200
- irq = 0
- (Probes ports: 0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0x360)
-
-eexpress.c:
- io = 0x300
- irq = 0 (IRQ value read from EEPROM)
- (Probes ports: 0x300, 0x270, 0x320, 0x340)
-
-eql.c:
- (No parameters)
-
-ewrk3.c:
- io = 0x300
- irq = 5
- (With module no autoprobing!
- On EISA-bus does EISA probing.
- Static linkage probes ports on ISA bus:
- 0x100, 0x120, 0x140, 0x160, 0x180, 0x1A0, 0x1C0,
- 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0,
- 0x300, 0x340, 0x360, 0x380, 0x3A0, 0x3C0)
-
-hp-plus.c:
- io = 0 (It will complain if you don't supply an "io=0xNNN")
- irq = 0 (IRQ read from configuration register)
- (Probes ports: 0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340)
-
-hp.c:
- io = 0 (It will complain if you don't supply an "io=0xNNN")
- irq = 0 (IRQ software selected by driver using autoIRQ)
- (Probes ports: 0x300, 0x320, 0x340, 0x280, 0x2C0, 0x200, 0x240)
-
-hp100.c:
- hp100_port = 0 (IO-base address)
- (Does EISA-probing, if on EISA-slot;
- On ISA-bus probes all ports from 0x100 thru to 0x3E0
- in increments of 0x020)
-
-hydra.c:
- Since this is a Zorro board, it supports full autoprobing, even for
- multiple boards. (m68k/Amiga)
-
-ibmtr.c:
- io = 0xa20, 0xa24 (autoprobed by default)
- irq = 0 (driver cannot select irq - read from hardware)
- mem = 0 (shared memory base set at 0xd0000 and not yet
- able to override thru mem= parameter.)
-
-lance.c: *Not modularized*
- (PCI, and ISA probing; "CONFIG_PCI" needed for PCI support)
- (Probes ISA ports: 0x300, 0x320, 0x340, 0x360)
-
-loopback.c: *Static kernel component*
-
-ne.c:
- io = 0 (Explicitly *requires* an "io=0xNNN" value)
- irq = 0 (Tries to determine configured IRQ via autoIRQ)
- (Probes ports: 0x300, 0x280, 0x320, 0x340, 0x360)
-
-net_init.c: *Static kernel component*
-
-ni52.c: *Not modularized*
- (Probes ports: 0x300, 0x280, 0x360, 0x320, 0x340
- mems: 0xD0000, 0xD2000, 0xC8000, 0xCA000,
- 0xD4000, 0xD6000, 0xD8000 )
-
-ni65.c: *Not modularized* **16MB MEMORY BARRIER BUG**
- (Probes ports: 0x300, 0x320, 0x340, 0x360)
-
-pi2.c: *Not modularized* (well, NON-STANDARD modularization!)
- Only one card supported at this time.
- (Probes ports: 0x380, 0x300, 0x320, 0x340, 0x360, 0x3A0)
-
-plip.c:
- io = 0
- irq = 0 (by default, uses IRQ 5 for port at 0x3bc, IRQ 7
- for port at 0x378, and IRQ 2 for port at 0x278)
- (Probes ports: 0x278, 0x378, 0x3bc)
-
-ppp.c:
- No options (ppp-2.2+ has some, this is based on non-dynamic
- version from ppp-2.1.2d)
-
-seeq8005.c: *Not modularized*
- (Probes ports: 0x300, 0x320, 0x340, 0x360)
-
-skeleton.c: *Skeleton*
-
-slhc.c:
- No configuration parameters
-
-slip.c:
- slip_maxdev = 256 (default value from SL_NRUNIT on slip.h)
-
-
-smc-ultra.c:
- io = 0 (It will complain if you don't supply an "io=0xNNN")
- irq = 0 (IRQ val. read from EEPROM)
- (Probes ports: 0x200, 0x220, 0x240, 0x280, 0x300, 0x340, 0x380)
-
-tulip.c: *Partial modularization*
- (init-time memory allocation makes problems..)
-
-tunnel.c:
- No insmod parameters
-
-wavelan.c:
- io = 0x390 (Settable, but change not recommended)
- irq = 0 (Not honoured, if changed..)
-
-wd.c:
- io = 0 (It will complain if you don't supply an "io=0xNNN")
- irq = 0 (IRQ val. read from EEPROM, ancient cards use autoIRQ)
- mem = 0 (Force shared-memory on address 0xC8000, or whatever..)
- mem_end = 0 (Force non-std. mem. size via supplying mem_end val.)
- (eg. for 32k WD8003EBT, use mem=0xd0000 mem_end=0xd8000)
- (Probes ports: 0x300, 0x280, 0x380, 0x240)
-
-znet.c: *Not modularized*
- (Only one device on Zenith Z-Note (notebook?) systems,
- configuration information from (EE)PROM)
diff --git a/Documentation/networking/proc_net_tcp.txt b/Documentation/networking/proc_net_tcp.txt
index 5e21f7cb6383..4a79209e77a7 100644
--- a/Documentation/networking/proc_net_tcp.txt
+++ b/Documentation/networking/proc_net_tcp.txt
@@ -1,8 +1,9 @@
This document describes the interfaces /proc/net/tcp and /proc/net/tcp6.
+Note that these interfaces are deprecated in favor of tcp_diag.
These /proc interfaces provide information about currently active TCP
-connections, and are implemented by tcp_get_info() in net/ipv4/tcp_ipv4.c and
-tcp6_get_info() in net/ipv6/tcp_ipv6.c, respectively.
+connections, and are implemented by tcp4_seq_show() in net/ipv4/tcp_ipv4.c
+and tcp6_seq_show() in net/ipv6/tcp_ipv6.c, respectively.
It will first list all listening TCP sockets, and next list all established
TCP connections. A typical entry of /proc/net/tcp would look like this (split
diff --git a/Documentation/networking/pt.txt b/Documentation/networking/pt.txt
deleted file mode 100644
index 72e888c1d988..000000000000
--- a/Documentation/networking/pt.txt
+++ /dev/null
@@ -1,58 +0,0 @@
-This is the README for the Gracilis Packetwin device driver, version 0.5
-ALPHA for Linux 1.3.43.
-
-These files will allow you to talk to the PackeTwin (now know as PT) and
-connect through it just like a pair of TNCs. To do this you will also
-require the AX.25 code in the kernel enabled.
-
-There are four files in this archive; this readme, a patch file, a .c file
-and finally a .h file. The two program files need to be put into the
-drivers/net directory in the Linux source tree, for me this is the
-directory /usr/src/linux/drivers/net. The patch file needs to be patched in
-at the top of the Linux source tree (/usr/src/linux in my case).
-
-You will most probably have to edit the pt.c file to suit your own setup,
-this should just involve changing some of the defines at the top of the file.
-Please note that if you run an external modem you must specify a speed of 0.
-
-The program is currently setup to run a 4800 baud external modem on port A
-and a Kantronics DE-9600 daughter board on port B so if you have this (or
-something similar) then you're right.
-
-To compile in the driver, put the files in the correct place and patch in
-the diff. You will have to re-configure the kernel again before you
-recompile it.
-
-The driver is not real good at the moment for finding the card. You can
-'help' it by changing the order of the potential addresses in the structure
-found in the pt_init() function so the address of where the card is is put
-first.
-
-After compiling, you have to get them going, they are pretty well like any
-other net device and just need ifconfig to get them going.
-As an example, here is my /etc/rc.net
---------------------------
-
-#
-# Configure the PackeTwin, port A.
-/sbin/ifconfig pt0a 44.136.8.87 hw ax25 vk2xlz mtu 512
-/sbin/ifconfig pt0a 44.136.8.87 broadcast 44.136.8.255 netmask 255.255.255.0
-/sbin/route add -net 44.136.8.0 netmask 255.255.255.0 dev pt0a
-/sbin/route add -net 44.0.0.0 netmask 255.0.0.0 gw 44.136.8.68 dev pt0a
-/sbin/route add -net 138.25.16.0 netmask 255.255.240.0 dev pt0a
-/sbin/route add -host 44.136.8.255 dev pt0a
-#
-# Configure the PackeTwin, port B.
-/sbin/ifconfig pt0b 44.136.8.87 hw ax25 vk2xlz-1 mtu 512
-/sbin/ifconfig pt0b 44.136.8.87 broadcast 44.255.255.255 netmask 255.0.0.0
-/sbin/route add -host 44.136.8.216 dev pt0b
-/sbin/route add -host 44.136.8.95 dev pt0b
-/sbin/route add -host 44.255.255.255 dev pt0b
-
-This version of the driver comes under the GNU GPL. If you have one of my
-previous (non-GPL) versions of the driver, please update to this one.
-
-I hope that this all works well for you. I would be pleased to hear how
-many people use the driver and if it does its job.
-
- - Craig vk2xlz <csmall@small.dropbear.id.au>
diff --git a/Documentation/networking/routing.txt b/Documentation/networking/routing.txt
deleted file mode 100644
index a26838b930f2..000000000000
--- a/Documentation/networking/routing.txt
+++ /dev/null
@@ -1,46 +0,0 @@
-The directory ftp.inr.ac.ru:/ip-routing contains:
-
-- iproute.c - "professional" routing table maintenance utility.
-
-- rdisc.tar.gz - rdisc daemon, ported from Sun.
- STRONGLY RECOMMENDED FOR ALL HOSTS.
-
-- routing.tgz - original Mike McLagan's route by source patch.
- Currently it is obsolete.
-
-- gated.dif-ss<NEWEST>.gz - gated-R3_6Alpha_2 fixes.
- Look at README.gated
-
-- mrouted-3.8.dif.gz - mrouted-3.8 fixes.
-
-- rtmon.c - trivial debugging utility: reads and stores netlink.
-
-
-NEWS for user.
-
-- Policy based routing. Routing decisions are made on the basis
- not only of destination address, but also source address,
- TOS and incoming interface.
-- Complete set of IP level control messages.
- Now Linux is the only OS in the world complying to RFC requirements.
- Great win 8)
-- New interface addressing paradigm.
- Assignment of address ranges to interface,
- multiple prefixes etc. etc.
- Do not bother, it is compatible with the old one. Moreover:
-- You don't need to do "route add aaa.bbb.ccc... eth0" anymore,
- it is done automatically.
-- "Abstract" UNIX sockets and security enhancements.
- This is necessary to use TIRPC and TLI emulation library.
-
-NEWS for hacker.
-
-- New destination cache. Flexible, robust and just beautiful.
-- Network stack is reordered, simplified, optimized, a lot of bugs fixed.
- (well, and new bugs were introduced, but I haven't seen them yet 8))
- It is difficult to describe all the changes, look into source.
-
-If you see this file, then this patch works 8)
-
-Alexey Kuznetsov.
-kuznet@ms2.inr.ac.ru
diff --git a/Documentation/networking/rxrpc.txt b/Documentation/networking/rxrpc.txt
index cae231b1c134..c3669a3fb4af 100644
--- a/Documentation/networking/rxrpc.txt
+++ b/Documentation/networking/rxrpc.txt
@@ -689,7 +689,7 @@ such as the AFS filesystem. This permits such a utility to:
buffers manipulated directly.
To use the RxRPC facility, a kernel utility must still open an AF_RXRPC socket,
-bind an addess as appropriate and listen if it's to be a server socket, but
+bind an address as appropriate and listen if it's to be a server socket, but
then it passes this to the kernel interface functions.
The kernel interface functions are as follows:
@@ -857,3 +857,10 @@ The kernel interface functions are as follows:
This is used to extract the error number from a message indicating either
a local error occurred or a network error occurred.
+
+ (*) Allocate a null key for doing anonymous security.
+
+ struct key *rxrpc_get_null_key(const char *keyname);
+
+ This is used to allocate a null RxRPC key that can be used to indicate
+ anonymous security for a particular domain.
diff --git a/Documentation/networking/slicecom.hun b/Documentation/networking/slicecom.hun
deleted file mode 100644
index bed2f045e550..000000000000
--- a/Documentation/networking/slicecom.hun
+++ /dev/null
@@ -1,371 +0,0 @@
-
-SliceCOM adapter felhasznaloi dokumentacioja - 0.51 verziohoz
-
-Bartók István <bartoki@itc.hu>
-Utolso modositas: Wed Aug 29 17:26:58 CEST 2001
-
------------------------------------------------------------------
-
-Hasznalata:
-
-Forditas:
-
-Code maturity level options
- [*] Prompt for development and/or incomplete code/drivers
-
-Network device support
- Wan interfaces
- <M> MultiGate (COMX) synchronous
- <M> Support for MUNICH based boards: SliceCOM, PCICOM (NEW)
- <M> Support for HDLC and syncPPP...
-
-
-A modulok betoltese:
-
-modprobe comx
-
-modprobe comx-proto-ppp # a Cisco-HDLC es a SyncPPP protokollt is
- # ez a modul adja
-
-modprobe comx-hw-munich # a modul betoltodeskor azonnal jelent a
- # syslogba a detektalt kartyakrol
-
-
-Konfiguralas:
-
-# Ezen az interfeszen Cisco-HDLC vonali protokoll fog futni
-# Az interfeszhez rendelt idoszeletek: 1,2 (128 kbit/sec-es vonal)
-# (a G.703 keretben az elso adatot vivo idoszelet az 1-es)
-#
-mkdir /proc/comx/comx0.1/
-echo slicecom >/proc/comx/comx0.1/boardtype
-echo hdlc >/proc/comx/comx0.1/protocol
-echo 1 2 >/proc/comx/comx0.1/timeslots
-
-
-# Ezen az interfeszen SyncPPP vonali protokoll fog futni
-# Az interfeszhez rendelt idoszelet: 3 (64 kbit/sec-es vonal)
-#
-mkdir /proc/comx/comx0.2/
-echo slicecom >/proc/comx/comx0.2/boardtype
-echo ppp >/proc/comx/comx0.2/protocol
-echo 3 >/proc/comx/comx0.2/timeslots
-
-...
-
-ifconfig comx0.1 up
-ifconfig comx0.2 up
-
------------------------------------------------------------------
-
-A COMX driverek default 20 csomagnyi transmit queue-t rendelnek a halozati
-interfeszekhez. WAN halozatokban ennel hosszabbat is szokas hasznalni
-(20 es 100 kozott), hogy a vonal kihasznaltsaga nagy terheles eseten jobb
-legyen (bar ezzel megno a varhato kesleltetes a csomagok sorban allasa miatt):
-
-# ifconfig comx0 txqueuelen 50
-
-Ezt a beallitasi lehetoseget csak az ujabb disztribuciok ifconfig parancsa
-tamogatja (amik mar a 2.2 kernelekhez keszultek, mint a RedHat 6.1 vagy a
-Debian 2.2).
-
-A 2.1-es Debian disztribuciohoz a http://www.debian.org/~rcw/2.2/netbase/
-cimrol toltheto le ujabb netbase csomag, ami mar ilyet tamogato ifconfig
-parancsot tartalmaz. Bovebben a 2.2 kernel hasznalatarol Debian 2.1 alatt:
-http://www.debian.org/releases/stable/running-kernel-2.2
-
------------------------------------------------------------------
-
-A kartya LED-jeinek jelentese:
-
-piros - eg, ha Remote Alarm-ot kuld a tuloldal
-zold - eg, ha a vett jelben megtalalja a keretszinkront
-
-Reszletesebben:
-
-piros: zold: jelentes:
-
-- - nincs keretszinkron (nincs jel, vagy rossz a jel)
-- eg "minden rendben"
-eg eg a vetel OK, de a tuloldal Remote Alarm-ot kuld
-eg - ez nincs ertelmezve, egyelore funkcio nelkul
-
------------------------------------------------------------------
-
-Reszletesebb leiras a hardver beallitasi lehetosegeirol:
-
-Az altalanos,- es a protokoll-retegek beallitasi lehetosegeirol a 'comx.txt'
-fajlban leirtak SliceCOM kartyanal is ervenyesek, itt csak a hardver-specifikus
-beallitasi lehetosegek vannak osszefoglalva:
-
-Konfiguralasi interfesz a /proc/comx/ alatt:
-
-Minden timeslot-csoportnak kulon comx* interfeszt kell letrehozni mkdir-rel:
-comx0, comx1, .. stb. Itt beallithato, hogy az adott interfesz hanyadik kartya
-melyik timeslotja(i)bol alljon ossze. A Cisco-fele serial3:1 elnevezesek
-(serial3:1 = a 3. kartyaban az 1-es idoszelet-csoport) Linuxon aliasing-ot
-jelentenenek, ezert mi nem tudunk ilyen elnevezest hasznalni.
-
-Tobb kartya eseten a comx0.1, comx0.2, ... vagy slice0.1, slice0.2 nevek
-hasznalhatoak.
-
-Tobb SliceCOM kartya is lehet egy gepben, de sajat interrupt kell mindegyiknek,
-nem tud meg megosztott interruptot kezelni.
-
-Az egesz kartyat erinto beallitasok:
-
-Az ioport es irq beallitas nincs: amit a PCI BIOS kioszt a rendszernek,
-azt hasznalja a driver.
-
-
-comx0/boardnum - hanyadik SliceCOM kartya a gepben (a 'termeszetes' PCI
- sorrendben ertve: ahogyan a /proc/pci-ban vagy az 'lspci'
- kimeneteben megjelenik, altalaban az alaplapi PCI meghajto
- aramkorokhoz kozelebb eso kartyak a kisebb sorszamuak)
-
- Default: 0 (0-tol kezdodik a szamolas)
-
-
-Bar a kovetkezoket csak egy-egy interfeszen allitjuk at, megis az egesz kartya
-mukodeset egyszerre allitjak. A megkotes hogy csak UP-ban levo interfeszen
-hasznalhatoak, azert van, mert kulonben nem vart eredmenyekre vezetne egy ilyen
-paranccsorozat:
-
- echo 0 >boardnum
- echo internal >clock_source
- echo 1 >boardnum
-
-- Ez a 0-s board clock_source-at allitana at.
-
-Ezek a beallitasok megmaradnak az osszes interfesz torlesekor, de torlodnek
-a driver modul ki/betoltesekor.
-
-
-comx0/clock_source - A Tx orajelforrasa, a Cisco-val hasonlatosra keszult.
- Hasznalata:
-
- papaya:# echo line >/proc/comx/comx0/clock_source
- papaya:# echo internal >/proc/comx/comx0/clock_source
-
- line - A Tx orajelet a vett adatfolyambol dekodolja, igyekszik
- igazodni hozza. Ha nem lat orajelet az inputon, akkor
- atall a sajat orajelgeneratorara.
- internal - A Tx orajelet a sajat orajelgeneratora szolgaltatja.
-
- Default: line
-
- Normal osszeallitas eseten a tavkozlesi szolgaltato eszkoze
- (pl. HDSL modem) adja az orajelet, ezert ez a default.
-
-
-comx0/framing - A CRC4 ki/be kapcsolasa
-
- A CRC4: 16 PCM keretet (A PCM keret az, amibe a 32 darab 64
- kilobites csatorna van bemultiplexalva. Nem osszetevesztendo a HDLC
- kerettel.) 2x8 -as csoportokra osztanak, es azokhoz 4-4 bites CRC-t
- szamolnak. Elsosorban a vonal minosegenek a monitorozasara szolgal.
-
- papaya:~# echo crc4 >/proc/comx/comx0/framing
- papaya:~# echo no-crc4 >/proc/comx/comx0/framing
-
- Default a 'crc4', a MATAV vonalak altalaban igy futnak. De ha nem
- egyforma is a beallitas a vonal ket vegen, attol a forgalom altalaban
- at tud menni.
-
-
-comx0/linecode - A vonali kodolas beallitasa
-
- papaya:~# echo hdb3 >/proc/comx/comx0/linecode
- papaya:~# echo ami >/proc/comx/comx0/linecode
-
- Default a 'hdb3', a MATAV vonalak igy futnak.
-
- (az AMI kodolas igen ritka E1-es vonalaknal). Ha ez a beallitas nem
- egyezik a vonal ket vegen, akkor elofordulhat hogy a keretszinkron
- osszejon, de CRC4-hibak es a vonalakon atvitt adatokban is hibak
- keletkeznek (amit a HDLC/SyncPPP szinten CRC-hibaval jelez)
-
-
-comx0/reg - a kartya aramkoreinek, a MUNICH (reg) es a FALC (lbireg)
-comx0/lbireg regisztereinek kozvetlen elerese. Hasznalata:
-
- echo >reg 0x04 0x0 - a 4-es regiszterbe 0-t ir
- echo >reg 0x104 - printk()-val kiirja a 4-es regiszter
- tartalmat a syslogba.
-
- WARNING: ezek csak a fejleszteshez keszultek, sok galibat
- lehet veluk okozni!
-
-
-comx0/loopback - A kartya G.703 jelenek a visszahurkolasara is van lehetoseg:
-
- papaya:# echo none >/proc/comx/comx0/loopback
- papaya:# echo local >/proc/comx/comx0/loopback
- papaya:# echo remote >/proc/comx/comx0/loopback
-
- none - nincs visszahurkolas, normal mukodes
- local - a kartya a sajat maga altal adott jelet kapja vissza
- remote - a kartya a kivulrol vett jelet adja kifele
-
- Default: none
-
------------------------------------------------------------------
-
-Az interfeszhez (Cisco terminologiaban 'channel-group') kapcsolodo beallitasok:
-
-comx0/timeslots - mely timeslotok (idoszeletek) tartoznak az adott interfeszhez.
-
- papaya:~# cat /proc/comx/comx0/timeslots
- 1 3 4 5 6
- papaya:~#
-
- Egy timeslot megkeresese (hanyas interfeszbe tartozik nalunk):
-
- papaya:~# grep ' 4' /proc/comx/comx*/timeslots
- /proc/comx/comx0/timeslots:1 3 4 5 6
- papaya:~#
-
- Beallitasa:
- papaya:~# echo '1 5 2 6 7 8' >/proc/comx/comx0/timeslots
-
- A timeslotok sorrendje nem szamit, '1 3 2' ugyanaz mint az '1 2 3'.
-
- Beallitashoz az adott interfesznek DOWN-ban kell lennie
- (ifconfig comx0 down), de ugyanannak a kartyanak a tobbi interfesze
- uzemelhet kozben.
-
- Beallitaskor leellenorzi, hogy az uj timeslotok nem utkoznek-e egy
- masik interfesz timeslotjaival. Ha utkoznek, akkor nem allitja at.
-
- Mindig 10-es szamrendszerben tortenik a timeslotok ertelmezese, nehogy
- a 08, 09 alaku felirast rosszul ertelmezze.
-
------------------------------------------------------------------
-
-Az interfeszek es a kartya allapotanak lekerdezese:
-
-- A ' '-szel kezdodo sorok az eredeti kimenetet, a //-rel kezdodo sorok a
-magyarazatot jelzik.
-
- papaya:~$ cat /proc/comx/comx1/status
- Interface administrative status is UP, modem status is UP, protocol is UP
- Modem status changes: 0, Transmitter status is IDLE, tbusy: 0
- Interface load (input): 978376 / 947808 / 951024 bits/s (5s/5m/15m)
- (output): 978376 / 947848 / 951024 bits/s (5s/5m/15m)
- Debug flags: none
- RX errors: len: 22, overrun: 1, crc: 0, aborts: 0
- buffer overrun: 0, pbuffer overrun: 0
- TX errors: underrun: 0
- Line keepalive (value: 10) status UP [0]
-
-// Itt kezdodik a hardver-specifikus resz:
- Controller status:
- No alarms
-
-// Alarm: hibajelzes:
-//
-// No alarms - minden rendben
-//
-// LOS - Loss Of Signal - nem erzekel jelet a bemeneten.
-// AIS - Alarm Indication Signal - csak egymas utani 1-esek jonnek
-// a bemeneten, a tuloldal igy is jelezheti hogy meghibasodott vagy
-// nincs inicializalva.
-// AUXP - Auxiliary Pattern Indication - 01010101.. sorozat jon a bemeneten.
-// LFA - Loss of Frame Alignment - nincs keretszinkron
-// RRA - Receive Remote Alarm - a tuloldal el, de hibat jelez.
-// LMFA - Loss of CRC4 Multiframe Alignment - nincs CRC4-multikeret-szinkron
-// NMF - No Multiframe alignment Found after 400 msec - ilyen alarm a no-crc4
-// es crc4 keretezesek eseten nincs, lasd lentebb
-//
-// Egyeb lehetseges hibajelzesek:
-//
-// Transmit Line Short - a kartya ugy erzi hogy az adasi kimenete rovidre
-// van zarva, ezert kikapcsolta az adast. (nem feltetlenul veszi eszre
-// a kulso rovidzarat)
-
-// A veteli oldal csomagjainak lancolt listai, debug celokra:
-
- Rx ring:
- rafutott: 0
- lastcheck: 50845731, jiffies: 51314281
- base: 017b1858
- rx_desc_ptr: 0
- rx_desc_ptr: 017b1858
- hw_curr_ptr: 017b1858
- 06040000 017b1868 017b1898 c016ff00
- 06040000 017b1878 017b1e9c c016ff00
- 46040000 017b1888 017b24a0 c016ff00
- 06040000 017b1858 017b2aa4 c016ff00
-
-// A kartyat hasznalo tobbi interfesz: a 0-s channel-group a comx1 interfesz,
-// es az 1,2,...,16 timeslotok tartoznak hozza:
-
- Interfaces using this board: (channel-group, interface, timeslots)
- 0 comx1: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
- 1 comx2: 17
- 2 comx3: 18
- 3 comx4: 19
- 4 comx5: 20
- 5 comx6: 21
- 6 comx7: 22
- 7 comx8: 23
- 8 comx9: 24
- 9 comx10: 25
- 10 comx11: 26
- 11 comx12: 27
- 12 comx13: 28
- 13 comx14: 29
- 14 comx15: 30
- 15 comx16: 31
-
-// Hany esemenyt kezelt le a driver egy-egy hardver-interrupt kiszolgalasanal:
-
- Interrupt work histogram:
- hist[ 0]: 0 hist[ 1]: 2 hist[ 2]: 18574 hist[ 3]: 79
- hist[ 4]: 14 hist[ 5]: 1 hist[ 6]: 0 hist[ 7]: 1
- hist[ 8]: 0 hist[ 9]: 7
-
-// Hany kikuldendo csomag volt mar a Tx-ringben amikor ujabb lett irva bele:
-
- Tx ring histogram:
- hist[ 0]: 2329 hist[ 1]: 0 hist[ 2]: 0 hist[ 3]: 0
-
-// Az E1-interfesz hiba-szamlaloi, az rfc2495-nek megfeleloen:
-// (kb. a Cisco routerek "show controllers e1" formatumaban: http://www.cisco.com/univercd/cc/td/doc/product/software/ios11/rbook/rinterfc.htm#xtocid25669126)
-
-Data in current interval (91 seconds elapsed):
- 9516 Line Code Violations, 65 Path Code Violations, 2 E-Bit Errors
- 0 Slip Secs, 2 Fr Loss Secs, 2 Line Err Secs, 0 Degraded Mins
- 0 Errored Secs, 0 Bursty Err Secs, 0 Severely Err Secs, 11 Unavail Secs
-Data in Interval 1 (15 minutes):
- 0 Line Code Violations, 0 Path Code Violations, 0 E-Bit Errors
- 0 Slip Secs, 0 Fr Loss Secs, 0 Line Err Secs, 0 Degraded Mins
- 0 Errored Secs, 0 Bursty Err Secs, 0 Severely Err Secs, 0 Unavail Secs
-Data in last 4 intervals (1 hour):
- 0 Line Code Violations, 0 Path Code Violations, 0 E-Bit Errors
- 0 Slip Secs, 0 Fr Loss Secs, 0 Line Err Secs, 0 Degraded Mins
- 0 Errored Secs, 0 Bursty Err Secs, 0 Severely Err Secs, 0 Unavail Secs
-Data in last 96 intervals (24 hours):
- 0 Line Code Violations, 0 Path Code Violations, 0 E-Bit Errors
- 0 Slip Secs, 0 Fr Loss Secs, 0 Line Err Secs, 0 Degraded Mins
- 0 Errored Secs, 0 Bursty Err Secs, 0 Severely Err Secs, 0 Unavail Secs
-
------------------------------------------------------------------
-
-Nehany kulonlegesebb beallitasi lehetoseg (idovel beepulhetnek majd a driverbe):
-Ezekkel sok galibat lehet okozni, nagyon ovatosan kell oket hasznalni!
-
- modified CRC-4, for improved interworking of CRC-4 and non-CRC-4
- devices: (lasd page 107 es g706 Annex B)
- lbireg[ 0x1b ] |= 0x08
- lbireg[ 0x1c ] |= 0xc0
- - ilyenkor ertelmezett az NMF - 'No Multiframe alignment Found after
- 400 msec' alarm.
-
- FALC - a vonali meghajto IC
- local loop - a sajat adasomat halljam vissza
- remote loop - a kivulrol jovo adast adom vissza
-
- Egy hibakeresesre hasznalhato dolog:
- - 1-es timeslot local loop a FALC-ban: echo >lbireg 0x1d 0x21
- - local loop kikapcsolasa: echo >lbireg 0x1d 0x00
diff --git a/Documentation/networking/slicecom.txt b/Documentation/networking/slicecom.txt
deleted file mode 100644
index c82c0cf981b4..000000000000
--- a/Documentation/networking/slicecom.txt
+++ /dev/null
@@ -1,369 +0,0 @@
-
-SliceCOM adapter user's documentation - for the 0.51 driver version
-
-Written by Bartók István <bartoki@itc.hu>
-
-English translation: Lakatos György <gyuri@itc.hu>
-Mon Dec 11 15:28:42 CET 2000
-
-Last modified: Wed Aug 29 17:25:37 CEST 2001
-
------------------------------------------------------------------
-
-Usage:
-
-Compiling the kernel:
-
-Code maturity level options
- [*] Prompt for development and/or incomplete code/drivers
-
-Network device support
- Wan interfaces
- <M> MultiGate (COMX) synchronous
- <M> Support for MUNICH based boards: SliceCOM, PCICOM (NEW)
- <M> Support for HDLC and syncPPP...
-
-
-Loading the modules:
-
-modprobe comx
-
-modprobe comx-proto-ppp # module for Cisco-HDLC and SyncPPP protocols
-
-modprobe comx-hw-munich # the module logs information by the kernel
- # about the detected boards
-
-
-Configuring the board:
-
-# This interface will use the Cisco-HDLC line protocol,
-# the timeslices assigned are 1,2 (128 KiBit line speed)
-# (the first data timeslice in the G.703 frame is no. 1)
-#
-mkdir /proc/comx/comx0.1/
-echo slicecom >/proc/comx/comx0.1/boardtype
-echo hdlc >/proc/comx/comx0.1/protocol
-echo 1 2 >/proc/comx/comx0.1/timeslots
-
-
-# This interface uses SyncPPP line protocol, the assigned
-# is no. 3 (64 KiBit line speed)
-#
-mkdir /proc/comx/comx0.2/
-echo slicecom >/proc/comx/comx0.2/boardtype
-echo ppp >/proc/comx/comx0.2/protocol
-echo 3 >/proc/comx/comx0.2/timeslots
-
-...
-
-ifconfig comx0.1 up
-ifconfig comx0.2 up
-
------------------------------------------------------------------
-
-The COMX interfaces use a 10 packet transmit queue by default, however WAN
-networks sometimes use bigger values (20 to 100), to utilize the line better
-by large traffic (though the line delay increases because of more packets
-join the queue).
-
-# ifconfig comx0 txqueuelen 50
-
-This option is only supported by the ifconfig command of the later
-distributions, which came with 2.2 kernels, such as RedHat 6.1 or Debian 2.2.
-
-You can download a newer netbase packet from
-http://www.debian.org/~rcw/2.2/netbase/ for Debian 2.1, which has a new
-ifconfig. You can get further information about using 2.2 kernel with
-Debian 2.1 from http://www.debian.org/releases/stable/running-kernel-2.2
-
------------------------------------------------------------------
-
-The SliceCom LEDs:
-
-red - on, if the interface is unconfigured, or it gets Remote Alarm-s
-green - on, if the board finds frame-sync in the received signal
-
-A bit more detailed:
-
-red: green: meaning:
-
-- - no frame-sync, no signal received, or signal SNAFU.
-- on "Everything is OK"
-on on Reception is ok, but the remote end sends Remote Alarm
-on - The interface is unconfigured
-
------------------------------------------------------------------
-
-A more detailed description of the hardware setting options:
-
-The general and the protocol layer options described in the 'comx.txt' file
-apply to the SliceCom as well, I only summarize the SliceCom hardware specific
-settings below.
-
-The '/proc/comx' configuring interface:
-
-An interface directory should be created for every timeslot group with
-'mkdir', e,g: 'comx0', 'comx1' etc. The timeslots can be assigned here to the
-specific interface. The Cisco-like naming convention (serial3:1 - first
-timeslot group of the 3rd. board) can't be used here, because these mean IP
-aliasing in Linux.
-
-You can give any meaningful name to keep the configuration clear;
-e.g: 'comx0.1', 'comx0.2', 'comx1.1', comx1.2', if you have two boards
-with two interfaces each.
-
-Settings, which apply to the board:
-
-Neither 'io' nor 'irq' settings required, the driver uses the resources
-given by the PCI BIOS.
-
-comx0/boardnum - board number of the SliceCom in the PC (using the 'natural'
- PCI order) as listed in '/proc/pci' or the output of the
- 'lspci' command, generally the slots nearer to the motherboard
- PCI driver chips have the lower numbers.
-
- Default: 0 (the counting starts with 0)
-
-Though the options below are to be set on a single interface, they apply to the
-whole board. The restriction, to use them on 'UP' interfaces, is because the
-command sequence below could lead to unpredictable results.
-
- # echo 0 >boardnum
- # echo internal >clock_source
- # echo 1 >boardnum
-
-The sequence would set the clock source of board 0.
-
-These settings will persist after all the interfaces are cleared, but are
-cleared when the driver module is unloaded and loaded again.
-
-comx0/clock_source - source of the transmit clock
- Usage:
-
- # echo line >/proc/comx/comx0/clock_source
- # echo internal >/proc/comx/comx0/clock_source
-
- line - The Tx clock is being decoded if the input data stream,
- if no clock seen on the input, then the board will use it's
- own clock generator.
-
- internal - The Tx clock is supplied by the builtin clock generator.
-
- Default: line
-
- Normally, the telecommunication company's end device (the HDSL
- modem) provides the Tx clock, that's why 'line' is the default.
-
-comx0/framing - Switching CRC4 off/on
-
- CRC4: 16 PCM frames (The 32 64Kibit channels are multiplexed into a
- PCM frame, nothing to do with HDLC frames) are divided into 2x8
- groups, each group has a 4 bit CRC.
-
- # echo crc4 >/proc/comx/comx0/framing
- # echo no-crc4 >/proc/comx/comx0/framing
-
- Default is 'crc4', the Hungarian MATAV lines behave like this.
- The traffic generally passes if this setting on both ends don't match.
-
-comx0/linecode - Setting the line coding
-
- # echo hdb3 >/proc/comx/comx0/linecode
- # echo ami >/proc/comx/comx0/linecode
-
- Default a 'hdb3', MATAV lines use this.
-
- (AMI coding is rarely used with E1 lines). Frame sync may occur, if
- this setting doesn't match the other end's, but CRC4 and data errors
- will come, which will result in CRC errors on HDLC/SyncPPP level.
-
-comx0/reg - direct access to the board's MUNICH (reg) and FALC (lbireg)
-comx0/lbireg circuit's registers
-
- # echo >reg 0x04 0x0 - write 0 to register 4
- # echo >reg 0x104 - write the contents of register 4 with
- printk() to syslog
-
-WARNING! These are only for development purposes, messing with this will
- result much trouble!
-
-comx0/loopback - Places a loop to the board's G.703 signals
-
- # echo none >/proc/comx/comx0/loopback
- # echo local >/proc/comx/comx0/loopback
- # echo remote >/proc/comx/comx0/loopback
-
- none - normal operation, no loop
- local - the board receives it's own output
- remote - the board sends the received data to the remote side
-
- Default: none
-
------------------------------------------------------------------
-
-Interface (channel group in Cisco terms) settings:
-
-comx0/timeslots - which timeslots belong to the given interface
-
- Setting:
-
- # echo '1 5 2 6 7 8' >/proc/comx/comx0/timeslots
-
- # cat /proc/comx/comx0/timeslots
- 1 2 5 6 7 8
- #
-
- Finding a timeslot:
-
- # grep ' 4' /proc/comx/comx*/timeslots
- /proc/comx/comx0/timeslots:1 3 4 5 6
- #
-
- The timeslots can be in any order, '1 2 3' is the same as '1 3 2'.
-
- The interface has to be DOWN during the setting ('ifconfig comx0
- down'), but the other interfaces could operate normally.
-
- The driver checks if the assigned timeslots are vacant, if not, then
- the setting won't be applied.
-
- The timeslot values are treated as decimal numbers, not to misunderstand
- values of 08, 09 form.
-
------------------------------------------------------------------
-
-Checking the interface and board status:
-
-- Lines beginning with ' ' (space) belong to the original output, the lines
-which begin with '//' are the comments.
-
- papaya:~$ cat /proc/comx/comx1/status
- Interface administrative status is UP, modem status is UP, protocol is UP
- Modem status changes: 0, Transmitter status is IDLE, tbusy: 0
- Interface load (input): 978376 / 947808 / 951024 bits/s (5s/5m/15m)
- (output): 978376 / 947848 / 951024 bits/s (5s/5m/15m)
- Debug flags: none
- RX errors: len: 22, overrun: 1, crc: 0, aborts: 0
- buffer overrun: 0, pbuffer overrun: 0
- TX errors: underrun: 0
- Line keepalive (value: 10) status UP [0]
-
-// The hardware specific part starts here:
- Controller status:
- No alarms
-
-// Alarm:
-//
-// No alarms - Everything OK
-//
-// LOS - Loss Of Signal - No signal sensed on the input
-// AIS - Alarm Indication Signal - The remote side sends '11111111'-s,
-// it tells, that there's an error condition, or it's not
-// initialised.
-// AUXP - Auxiliary Pattern Indication - 01010101.. received.
-// LFA - Loss of Frame Alignment - no frame sync received.
-// RRA - Receive Remote Alarm - the remote end's OK, but signals error cond.
-// LMFA - Loss of CRC4 Multiframe Alignment - no CRC4 multiframe sync.
-// NMF - No Multiframe alignment Found after 400 msec - no such alarm using
-// no-crc4 or crc4 framing, see below.
-//
-// Other possible error messages:
-//
-// Transmit Line Short - the board felt, that it's output is short-circuited,
-// so it switched the transmission off. (The board can't definitely tell,
-// that it's output is short-circuited.)
-
-// Chained list of the received packets, for debug purposes:
-
- Rx ring:
- rafutott: 0
- lastcheck: 50845731, jiffies: 51314281
- base: 017b1858
- rx_desc_ptr: 0
- rx_desc_ptr: 017b1858
- hw_curr_ptr: 017b1858
- 06040000 017b1868 017b1898 c016ff00
- 06040000 017b1878 017b1e9c c016ff00
- 46040000 017b1888 017b24a0 c016ff00
- 06040000 017b1858 017b2aa4 c016ff00
-
-// All the interfaces using the board: comx1, using the 1,2,...16 timeslots,
-// comx2, using timeslot 17, etc.
-
- Interfaces using this board: (channel-group, interface, timeslots)
- 0 comx1: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
- 1 comx2: 17
- 2 comx3: 18
- 3 comx4: 19
- 4 comx5: 20
- 5 comx6: 21
- 6 comx7: 22
- 7 comx8: 23
- 8 comx9: 24
- 9 comx10: 25
- 10 comx11: 26
- 11 comx12: 27
- 12 comx13: 28
- 13 comx14: 29
- 14 comx15: 30
- 15 comx16: 31
-
-// The number of events handled by the driver during an interrupt cycle:
-
- Interrupt work histogram:
- hist[ 0]: 0 hist[ 1]: 2 hist[ 2]: 18574 hist[ 3]: 79
- hist[ 4]: 14 hist[ 5]: 1 hist[ 6]: 0 hist[ 7]: 1
- hist[ 8]: 0 hist[ 9]: 7
-
-// The number of packets to send in the Tx ring, when a new one arrived:
-
- Tx ring histogram:
- hist[ 0]: 2329 hist[ 1]: 0 hist[ 2]: 0 hist[ 3]: 0
-
-// The error counters of the E1 interface, according to the RFC2495,
-// (similar to the Cisco "show controllers e1" command's output:
-// http://www.cisco.com/univercd/cc/td/doc/product/software/ios11/rbook/rinterfc.htm#xtocid25669126)
-
-Data in current interval (91 seconds elapsed):
- 9516 Line Code Violations, 65 Path Code Violations, 2 E-Bit Errors
- 0 Slip Secs, 2 Fr Loss Secs, 2 Line Err Secs, 0 Degraded Mins
- 0 Errored Secs, 0 Bursty Err Secs, 0 Severely Err Secs, 11 Unavail Secs
-Data in Interval 1 (15 minutes):
- 0 Line Code Violations, 0 Path Code Violations, 0 E-Bit Errors
- 0 Slip Secs, 0 Fr Loss Secs, 0 Line Err Secs, 0 Degraded Mins
- 0 Errored Secs, 0 Bursty Err Secs, 0 Severely Err Secs, 0 Unavail Secs
-Data in last 4 intervals (1 hour):
- 0 Line Code Violations, 0 Path Code Violations, 0 E-Bit Errors
- 0 Slip Secs, 0 Fr Loss Secs, 0 Line Err Secs, 0 Degraded Mins
- 0 Errored Secs, 0 Bursty Err Secs, 0 Severely Err Secs, 0 Unavail Secs
-Data in last 96 intervals (24 hours):
- 0 Line Code Violations, 0 Path Code Violations, 0 E-Bit Errors
- 0 Slip Secs, 0 Fr Loss Secs, 0 Line Err Secs, 0 Degraded Mins
- 0 Errored Secs, 0 Bursty Err Secs, 0 Severely Err Secs, 0 Unavail Secs
-
------------------------------------------------------------------
-
-Some unique options, (may get into the driver later):
-Treat them very carefully, these can cause much trouble!
-
- modified CRC-4, for improved interworking of CRC-4 and non-CRC-4
- devices: (see page 107 and g706 Annex B)
- lbireg[ 0x1b ] |= 0x08
- lbireg[ 0x1c ] |= 0xc0
-
- - The NMF - 'No Multiframe alignment Found after 400 msec' alarm
- comes into account.
-
- FALC - the line driver chip.
- local loop - I hear my transmission back.
- remote loop - I echo the remote transmission back.
-
- Something useful for finding errors:
-
- - local loop for timeslot 1 in the FALC chip:
-
- # echo >lbireg 0x1d 0x21
-
- - Switching the loop off:
-
- # echo >lbireg 0x1d 0x00
diff --git a/Documentation/networking/tc-actions-env-rules.txt b/Documentation/networking/tc-actions-env-rules.txt
new file mode 100644
index 000000000000..01e716d185f4
--- /dev/null
+++ b/Documentation/networking/tc-actions-env-rules.txt
@@ -0,0 +1,29 @@
+
+The "enviromental" rules for authors of any new tc actions are:
+
+1) If you stealeth or borroweth any packet thou shalt be branching
+from the righteous path and thou shalt cloneth.
+
+For example if your action queues a packet to be processed later
+or intentionaly branches by redirecting a packet then you need to
+clone the packet.
+There are certain fields in the skb tc_verd that need to be reset so we
+avoid loops etc. A few are generic enough so much so that skb_act_clone()
+resets them for you. So invoke skb_act_clone() rather than skb_clone()
+
+2) If you munge any packet thou shalt call pskb_expand_head in the case
+someone else is referencing the skb. After that you "own" the skb.
+You must also tell us if it is ok to munge the packet (TC_OK2MUNGE),
+this way any action downstream can stomp on the packet.
+
+3) dropping packets you dont own is a nono. You simply return
+TC_ACT_SHOT to the caller and they will drop it.
+
+The "enviromental" rules for callers of actions (qdiscs etc) are:
+
+*) thou art responsible for freeing anything returned as being
+TC_ACT_SHOT/STOLEN/QUEUED. If none of TC_ACT_SHOT/STOLEN/QUEUED is
+returned then all is great and you dont need to do anything.
+
+Post on netdev if something is unclear.
+
diff --git a/Documentation/networking/udplite.txt b/Documentation/networking/udplite.txt
index 6be09ba24a36..b6409cab075c 100644
--- a/Documentation/networking/udplite.txt
+++ b/Documentation/networking/udplite.txt
@@ -12,7 +12,7 @@
For in-depth information, you can consult:
o The UDP-Lite Homepage: http://www.erg.abdn.ac.uk/users/gerrit/udp-lite/
- Fom here you can also download some example application source code.
+ From here you can also download some example application source code.
o The UDP-Lite HOWTO on
http://www.erg.abdn.ac.uk/users/gerrit/udp-lite/files/UDP-Lite-HOWTO.txt
@@ -223,7 +223,7 @@
While it is important that such cases are dealt with correctly, they
are (annoyingly) rare: UDP-Lite is designed for optimising multimedia
performance over wireless (or generally noisy) links and thus smaller
- coverage lenghts are likely to be expected.
+ coverage lengths are likely to be expected.
V) UDP-LITE RUNTIME STATISTICS AND THEIR MEANING
@@ -259,7 +259,7 @@
VI) IPTABLES
There is packet match support for UDP-Lite as well as support for the LOG target.
- If you copy and paste the following line into /etc/protcols,
+ If you copy and paste the following line into /etc/protocols,
udplite 136 UDP-Lite # UDP-Lite [RFC 3828]
diff --git a/Documentation/parport-lowlevel.txt b/Documentation/parport-lowlevel.txt
index 8f2302415eff..265fcdcb8e5f 100644
--- a/Documentation/parport-lowlevel.txt
+++ b/Documentation/parport-lowlevel.txt
@@ -25,7 +25,6 @@ Global functions:
parport_open
parport_close
parport_device_id
- parport_device_num
parport_device_coords
parport_find_class
parport_find_device
@@ -735,7 +734,7 @@ NULL is returned.
SEE ALSO
-parport_register_device, parport_device_num
+parport_register_device
parport_close - unregister device for particular device number
-------------
@@ -787,29 +786,7 @@ Many devices have ill-formed IEEE 1284 Device IDs.
SEE ALSO
-parport_find_class, parport_find_device, parport_device_num
-
-parport_device_num - convert device coordinates to device number
-------------------
-
-SYNOPSIS
-
-#include <linux/parport.h>
-
-int parport_device_num (int parport, int mux, int daisy);
-
-DESCRIPTION
-
-Convert between device coordinates (port, multiplexor, daisy chain
-address) and device number (zero-based).
-
-RETURN VALUE
-
-Device number, or -1 if no device at given coordinates.
-
-SEE ALSO
-
-parport_device_coords, parport_open, parport_device_id
+parport_find_class, parport_find_device
parport_device_coords - convert device number to device coordinates
------------------
@@ -833,7 +810,7 @@ Zero on success, in which case the coordinates are (*parport, *mux,
SEE ALSO
-parport_device_num, parport_open, parport_device_id
+parport_open, parport_device_id
parport_find_class - find a device by its class
------------------
diff --git a/Documentation/power/00-INDEX b/Documentation/power/00-INDEX
new file mode 100644
index 000000000000..8db4e41a052d
--- /dev/null
+++ b/Documentation/power/00-INDEX
@@ -0,0 +1,34 @@
+00-INDEX
+ - This file
+basic-pm-debugging.txt
+ - Debugging suspend and resume
+devices.txt
+ - How drivers interact with system-wide power management
+drivers-testing.txt
+ - Testing suspend and resume support in device drivers
+freezing-of-tasks.txt
+ - How processes and controlled during suspend
+interface.txt
+ - Power management user interface in /sys/power
+notifiers.txt
+ - Registering suspend notifiers in device drivers
+pci.txt
+ - How the PCI Subsystem Does Power Management
+s2ram.txt
+ - How to get suspend to ram working (and debug it when it isn't)
+states.txt
+ - System power management states
+swsusp-and-swap-files.txt
+ - Using swap files with software suspend (to disk)
+swsusp-dmcrypt.txt
+ - How to use dm-crypt and software suspend (to disk) together
+swsusp.txt
+ - Goals, implementation, and usage of software suspend (ACPI S3)
+tricks.txt
+ - How to trick software suspend (to disk) into working when it isn't
+userland-swsusp.txt
+ - Experimental implementation of software suspend in userspace
+video_extension.txt
+ - ACPI video extensions
+video.txt
+ - Video issues during resume from suspend
diff --git a/Documentation/power/basic-pm-debugging.txt b/Documentation/power/basic-pm-debugging.txt
index 1a85e2b964dc..57aef2f6e0de 100644
--- a/Documentation/power/basic-pm-debugging.txt
+++ b/Documentation/power/basic-pm-debugging.txt
@@ -78,8 +78,8 @@ c) Advanced debugging
In case the STD does not work on your system even in the minimal configuration
and compiling more drivers as modules is not practical or some modules cannot
be unloaded, you can use one of the more advanced debugging techniques to find
-the problem. First, if there is a serial port in your box, you can set the
-CONFIG_DISABLE_CONSOLE_SUSPEND kernel configuration option and try to log kernel
+the problem. First, if there is a serial port in your box, you can boot the
+kernel with the 'no_console_suspend' parameter and try to log kernel
messages using the serial console. This may provide you with some information
about the reasons of the suspend (resume) failure. Alternatively, it may be
possible to use a FireWire port for debugging with firescope
diff --git a/Documentation/power/drivers-testing.txt b/Documentation/power/drivers-testing.txt
index 33016c2f18dd..e4bdcaee24e4 100644
--- a/Documentation/power/drivers-testing.txt
+++ b/Documentation/power/drivers-testing.txt
@@ -14,8 +14,8 @@ the machine's BIOS.
Of course, for this purpose the test system has to be known to suspend and
resume without the driver being tested. Thus, if possible, you should first
resolve all suspend/resume-related problems in the test system before you start
-testing the new driver. Please see Documents/power/basic-pm-debugging.txt for
-more information about the debugging of suspend/resume functionality.
+testing the new driver. Please see Documentation/power/basic-pm-debugging.txt
+for more information about the debugging of suspend/resume functionality.
2. Testing the driver
diff --git a/Documentation/power/freezing-of-tasks.txt b/Documentation/power/freezing-of-tasks.txt
index 04dc1cf9d215..38b57248fd61 100644
--- a/Documentation/power/freezing-of-tasks.txt
+++ b/Documentation/power/freezing-of-tasks.txt
@@ -19,12 +19,13 @@ we only consider hibernation, but the description also applies to suspend).
Namely, as the first step of the hibernation procedure the function
freeze_processes() (defined in kernel/power/process.c) is called. It executes
try_to_freeze_tasks() that sets TIF_FREEZE for all of the freezable tasks and
-sends a fake signal to each of them. A task that receives such a signal and has
-TIF_FREEZE set, should react to it by calling the refrigerator() function
-(defined in kernel/power/process.c), which sets the task's PF_FROZEN flag,
-changes its state to TASK_UNINTERRUPTIBLE and makes it loop until PF_FROZEN is
-cleared for it. Then, we say that the task is 'frozen' and therefore the set of
-functions handling this mechanism is called 'the freezer' (these functions are
+either wakes them up, if they are kernel threads, or sends fake signals to them,
+if they are user space processes. A task that has TIF_FREEZE set, should react
+to it by calling the function called refrigerator() (defined in
+kernel/power/process.c), which sets the task's PF_FROZEN flag, changes its state
+to TASK_UNINTERRUPTIBLE and makes it loop until PF_FROZEN is cleared for it.
+Then, we say that the task is 'frozen' and therefore the set of functions
+handling this mechanism is referred to as 'the freezer' (these functions are
defined in kernel/power/process.c and include/linux/freezer.h). User space
processes are generally frozen before kernel threads.
@@ -35,21 +36,27 @@ task enter refrigerator() if the flag is set.
For user space processes try_to_freeze() is called automatically from the
signal-handling code, but the freezable kernel threads need to call it
-explicitly in suitable places. The code to do this may look like the following:
+explicitly in suitable places or use the wait_event_freezable() or
+wait_event_freezable_timeout() macros (defined in include/linux/freezer.h)
+that combine interruptible sleep with checking if TIF_FREEZE is set and calling
+try_to_freeze(). The main loop of a freezable kernel thread may look like the
+following one:
+ set_freezable();
do {
hub_events();
- wait_event_interruptible(khubd_wait,
- !list_empty(&hub_event_list));
- try_to_freeze();
- } while (!signal_pending(current));
+ wait_event_freezable(khubd_wait,
+ !list_empty(&hub_event_list) ||
+ kthread_should_stop());
+ } while (!kthread_should_stop() || !list_empty(&hub_event_list));
(from drivers/usb/core/hub.c::hub_thread()).
If a freezable kernel thread fails to call try_to_freeze() after the freezer has
set TIF_FREEZE for it, the freezing of tasks will fail and the entire
hibernation operation will be cancelled. For this reason, freezable kernel
-threads must call try_to_freeze() somewhere.
+threads must call try_to_freeze() somewhere or use one of the
+wait_event_freezable() and wait_event_freezable_timeout() macros.
After the system memory state has been restored from a hibernation image and
devices have been reinitialized, the function thaw_processes() is called in
@@ -81,7 +88,16 @@ hibernation image has been created and before the system is finally powered off.
The majority of these are user space processes, but if any of the kernel threads
may cause something like this to happen, they have to be freezable.
-2. The second reason is to prevent user space processes and some kernel threads
+2. Next, to create the hibernation image we need to free a sufficient amount of
+memory (approximately 50% of available RAM) and we need to do that before
+devices are deactivated, because we generally need them for swapping out. Then,
+after the memory for the image has been freed, we don't want tasks to allocate
+additional memory and we prevent them from doing that by freezing them earlier.
+[Of course, this also means that device drivers should not allocate substantial
+amounts of memory from their .suspend() callbacks before hibernation, but this
+is e separate issue.]
+
+3. The third reason is to prevent user space processes and some kernel threads
from interfering with the suspending and resuming of devices. A user space
process running on a second CPU while we are suspending devices may, for
example, be troublesome and without the freezing of tasks we would need some
@@ -111,7 +127,7 @@ frozen before the driver's .suspend() callback is executed and it will be
thawed after the driver's .resume() callback has run, so it won't be accessing
the device while it's suspended.
-3. Another reason for freezing tasks is to prevent user space processes from
+4. Another reason for freezing tasks is to prevent user space processes from
realizing that hibernation (or suspend) operation takes place. Ideally, user
space processes should not notice that such a system-wide operation has occurred
and should continue running without any problems after the restore (or resume
diff --git a/Documentation/power/interface.txt b/Documentation/power/interface.txt
index fd5192a8fa8a..e67211fe0ee2 100644
--- a/Documentation/power/interface.txt
+++ b/Documentation/power/interface.txt
@@ -20,7 +20,7 @@ states.
/sys/power/disk controls the operating mode of the suspend-to-disk
mechanism. Suspend-to-disk can be handled in several ways. We have a
few options for putting the system to sleep - using the platform driver
-(e.g. ACPI or other pm_ops), powering off the system or rebooting the
+(e.g. ACPI or other suspend_ops), powering off the system or rebooting the
system (for testing).
Additionally, /sys/power/disk can be used to turn on one of the two testing
diff --git a/Documentation/power/swsusp-and-swap-files.txt b/Documentation/power/swsusp-and-swap-files.txt
index 06f911a5f885..f281886de490 100644
--- a/Documentation/power/swsusp-and-swap-files.txt
+++ b/Documentation/power/swsusp-and-swap-files.txt
@@ -39,7 +39,7 @@ resume=<swap_file_partition> resume_offset=<swap_file_offset>
where <swap_file_partition> is the partition on which the swap file is located
and <swap_file_offset> is the offset of the swap header determined by the
application in 2) (of course, this step may be carried out automatically
-by the same application that determies the swap file's header offset using the
+by the same application that determines the swap file's header offset using the
FIBMAP ioctl)
OR
diff --git a/Documentation/powerpc/00-INDEX b/Documentation/powerpc/00-INDEX
index d6d65b9bcfe3..94a3c577b083 100644
--- a/Documentation/powerpc/00-INDEX
+++ b/Documentation/powerpc/00-INDEX
@@ -5,6 +5,8 @@ please mail me.
00-INDEX
- this file
+booting-without-of.txt
+ - Booting the Linux/ppc kernel without Open Firmware
cpu_features.txt
- info on how we support a variety of CPUs with minimal compile-time
options.
@@ -14,6 +16,8 @@ hvcs.txt
- IBM "Hypervisor Virtual Console Server" Installation Guide
mpc52xx.txt
- Linux 2.6.x on MPC52xx family
+mpc52xx-device-tree-bindings.txt
+ - MPC5200 Device Tree Bindings
ppc_htab.txt
- info about the Linux/PPC /proc/ppc_htab entry
SBC8260_memory_mapping.txt
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index a96e85397eb7..ac1be25c1e25 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -52,6 +52,7 @@ Table of Contents
i) Freescale QUICC Engine module (QE)
j) CFI or JEDEC memory-mapped NOR flash
k) Global Utilities Block
+ l) Xilinx IP cores
VII - Specifying interrupt information for devices
1) interrupts property
@@ -851,12 +852,18 @@ address which can extend beyond that limit.
/cpus/PowerPC,970FX@0
/cpus/PowerPC,970FX@1
(unit addresses do not require leading zeroes)
- - d-cache-line-size : one cell, L1 data cache line size in bytes
- - i-cache-line-size : one cell, L1 instruction cache line size in
+ - d-cache-block-size : one cell, L1 data cache block size in bytes (*)
+ - i-cache-block-size : one cell, L1 instruction cache block size in
bytes
- d-cache-size : one cell, size of L1 data cache in bytes
- i-cache-size : one cell, size of L1 instruction cache in bytes
+(*) The cache "block" size is the size on which the cache management
+instructions operate. Historically, this document used the cache
+"line" size here which is incorrect. The kernel will prefer the cache
+block size and will fallback to cache line size for backward
+compatibility.
+
Recommended properties:
- timebase-frequency : a cell indicating the frequency of the
@@ -870,6 +877,10 @@ address which can extend beyond that limit.
for the above, the common code doesn't use that property, but
you are welcome to re-use the pSeries or Maple one. A future
kernel version might provide a common function for this.
+ - d-cache-line-size : one cell, L1 data cache line size in bytes
+ if different from the block size
+ - i-cache-line-size : one cell, L1 instruction cache line size in
+ bytes if different from the block size
You are welcome to add any property you find relevant to your board,
like some information about the mechanism used to soft-reset the
@@ -2242,6 +2253,266 @@ platforms are moved over to use the flattened-device-tree model.
available.
For Axon: 0x0000012a
+ l) Xilinx IP cores
+
+ The Xilinx EDK toolchain ships with a set of IP cores (devices) for use
+ in Xilinx Spartan and Virtex FPGAs. The devices cover the whole range
+ of standard device types (network, serial, etc.) and miscellanious
+ devices (gpio, LCD, spi, etc). Also, since these devices are
+ implemented within the fpga fabric every instance of the device can be
+ synthesised with different options that change the behaviour.
+
+ Each IP-core has a set of parameters which the FPGA designer can use to
+ control how the core is synthesized. Historically, the EDK tool would
+ extract the device parameters relevant to device drivers and copy them
+ into an 'xparameters.h' in the form of #define symbols. This tells the
+ device drivers how the IP cores are configured, but it requres the kernel
+ to be recompiled every time the FPGA bitstream is resynthesized.
+
+ The new approach is to export the parameters into the device tree and
+ generate a new device tree each time the FPGA bitstream changes. The
+ parameters which used to be exported as #defines will now become
+ properties of the device node. In general, device nodes for IP-cores
+ will take the following form:
+
+ (name)@(base-address) {
+ compatible = "xlnx,(ip-core-name)-(HW_VER)"
+ [, (list of compatible devices), ...];
+ reg = <(baseaddr) (size)>;
+ interrupt-parent = <&interrupt-controller-phandle>;
+ interrupts = < ... >;
+ xlnx,(parameter1) = "(string-value)";
+ xlnx,(parameter2) = <(int-value)>;
+ };
+
+ (ip-core-name): the name of the ip block (given after the BEGIN
+ directive in system.mhs). Should be in lowercase
+ and all underscores '_' converted to dashes '-'.
+ (name): is derived from the "PARAMETER INSTANCE" value.
+ (parameter#): C_* parameters from system.mhs. The C_ prefix is
+ dropped from the parameter name, the name is converted
+ to lowercase and all underscore '_' characters are
+ converted to dashes '-'.
+ (baseaddr): the C_BASEADDR parameter.
+ (HW_VER): from the HW_VER parameter.
+ (size): equals C_HIGHADDR - C_BASEADDR + 1
+
+ Typically, the compatible list will include the exact IP core version
+ followed by an older IP core version which implements the same
+ interface or any other device with the same interface.
+
+ 'reg', 'interrupt-parent' and 'interrupts' are all optional properties.
+
+ For example, the following block from system.mhs:
+
+ BEGIN opb_uartlite
+ PARAMETER INSTANCE = opb_uartlite_0
+ PARAMETER HW_VER = 1.00.b
+ PARAMETER C_BAUDRATE = 115200
+ PARAMETER C_DATA_BITS = 8
+ PARAMETER C_ODD_PARITY = 0
+ PARAMETER C_USE_PARITY = 0
+ PARAMETER C_CLK_FREQ = 50000000
+ PARAMETER C_BASEADDR = 0xEC100000
+ PARAMETER C_HIGHADDR = 0xEC10FFFF
+ BUS_INTERFACE SOPB = opb_7
+ PORT OPB_Clk = CLK_50MHz
+ PORT Interrupt = opb_uartlite_0_Interrupt
+ PORT RX = opb_uartlite_0_RX
+ PORT TX = opb_uartlite_0_TX
+ PORT OPB_Rst = sys_bus_reset_0
+ END
+
+ becomes the following device tree node:
+
+ opb-uartlite-0@ec100000 {
+ device_type = "serial";
+ compatible = "xlnx,opb-uartlite-1.00.b";
+ reg = <ec100000 10000>;
+ interrupt-parent = <&opb-intc>;
+ interrupts = <1 0>; // got this from the opb_intc parameters
+ current-speed = <d#115200>; // standard serial device prop
+ clock-frequency = <d#50000000>; // standard serial device prop
+ xlnx,data-bits = <8>;
+ xlnx,odd-parity = <0>;
+ xlnx,use-parity = <0>;
+ };
+
+ Some IP cores actually implement 2 or more logical devices. In this case,
+ the device should still describe the whole IP core with a single node
+ and add a child node for each logical device. The ranges property can
+ be used to translate from parent IP-core to the registers of each device.
+ (Note: this makes the assumption that both logical devices have the same
+ bus binding. If this is not true, then separate nodes should be used for
+ each logical device). The 'cell-index' property can be used to enumerate
+ logical devices within an IP core. For example, the following is the
+ system.mhs entry for the dual ps2 controller found on the ml403 reference
+ design.
+
+ BEGIN opb_ps2_dual_ref
+ PARAMETER INSTANCE = opb_ps2_dual_ref_0
+ PARAMETER HW_VER = 1.00.a
+ PARAMETER C_BASEADDR = 0xA9000000
+ PARAMETER C_HIGHADDR = 0xA9001FFF
+ BUS_INTERFACE SOPB = opb_v20_0
+ PORT Sys_Intr1 = ps2_1_intr
+ PORT Sys_Intr2 = ps2_2_intr
+ PORT Clkin1 = ps2_clk_rx_1
+ PORT Clkin2 = ps2_clk_rx_2
+ PORT Clkpd1 = ps2_clk_tx_1
+ PORT Clkpd2 = ps2_clk_tx_2
+ PORT Rx1 = ps2_d_rx_1
+ PORT Rx2 = ps2_d_rx_2
+ PORT Txpd1 = ps2_d_tx_1
+ PORT Txpd2 = ps2_d_tx_2
+ END
+
+ It would result in the following device tree nodes:
+
+ opb_ps2_dual_ref_0@a9000000 {
+ ranges = <0 a9000000 2000>;
+ // If this device had extra parameters, then they would
+ // go here.
+ ps2@0 {
+ compatible = "xlnx,opb-ps2-dual-ref-1.00.a";
+ reg = <0 40>;
+ interrupt-parent = <&opb-intc>;
+ interrupts = <3 0>;
+ cell-index = <0>;
+ };
+ ps2@1000 {
+ compatible = "xlnx,opb-ps2-dual-ref-1.00.a";
+ reg = <1000 40>;
+ interrupt-parent = <&opb-intc>;
+ interrupts = <3 0>;
+ cell-index = <0>;
+ };
+ };
+
+ Also, the system.mhs file defines bus attachments from the processor
+ to the devices. The device tree structure should reflect the bus
+ attachments. Again an example; this system.mhs fragment:
+
+ BEGIN ppc405_virtex4
+ PARAMETER INSTANCE = ppc405_0
+ PARAMETER HW_VER = 1.01.a
+ BUS_INTERFACE DPLB = plb_v34_0
+ BUS_INTERFACE IPLB = plb_v34_0
+ END
+
+ BEGIN opb_intc
+ PARAMETER INSTANCE = opb_intc_0
+ PARAMETER HW_VER = 1.00.c
+ PARAMETER C_BASEADDR = 0xD1000FC0
+ PARAMETER C_HIGHADDR = 0xD1000FDF
+ BUS_INTERFACE SOPB = opb_v20_0
+ END
+
+ BEGIN opb_uart16550
+ PARAMETER INSTANCE = opb_uart16550_0
+ PARAMETER HW_VER = 1.00.d
+ PARAMETER C_BASEADDR = 0xa0000000
+ PARAMETER C_HIGHADDR = 0xa0001FFF
+ BUS_INTERFACE SOPB = opb_v20_0
+ END
+
+ BEGIN plb_v34
+ PARAMETER INSTANCE = plb_v34_0
+ PARAMETER HW_VER = 1.02.a
+ END
+
+ BEGIN plb_bram_if_cntlr
+ PARAMETER INSTANCE = plb_bram_if_cntlr_0
+ PARAMETER HW_VER = 1.00.b
+ PARAMETER C_BASEADDR = 0xFFFF0000
+ PARAMETER C_HIGHADDR = 0xFFFFFFFF
+ BUS_INTERFACE SPLB = plb_v34_0
+ END
+
+ BEGIN plb2opb_bridge
+ PARAMETER INSTANCE = plb2opb_bridge_0
+ PARAMETER HW_VER = 1.01.a
+ PARAMETER C_RNG0_BASEADDR = 0x20000000
+ PARAMETER C_RNG0_HIGHADDR = 0x3FFFFFFF
+ PARAMETER C_RNG1_BASEADDR = 0x60000000
+ PARAMETER C_RNG1_HIGHADDR = 0x7FFFFFFF
+ PARAMETER C_RNG2_BASEADDR = 0x80000000
+ PARAMETER C_RNG2_HIGHADDR = 0xBFFFFFFF
+ PARAMETER C_RNG3_BASEADDR = 0xC0000000
+ PARAMETER C_RNG3_HIGHADDR = 0xDFFFFFFF
+ BUS_INTERFACE SPLB = plb_v34_0
+ BUS_INTERFACE MOPB = opb_v20_0
+ END
+
+ Gives this device tree (some properties removed for clarity):
+
+ plb-v34-0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "ibm,plb";
+ ranges; // 1:1 translation
+
+ plb-bram-if-cntrl-0@ffff0000 {
+ reg = <ffff0000 10000>;
+ }
+
+ opb-v20-0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <20000000 20000000 20000000
+ 60000000 60000000 20000000
+ 80000000 80000000 40000000
+ c0000000 c0000000 20000000>;
+
+ opb-uart16550-0@a0000000 {
+ reg = <a00000000 2000>;
+ };
+
+ opb-intc-0@d1000fc0 {
+ reg = <d1000fc0 20>;
+ };
+ };
+ };
+
+ That covers the general approach to binding xilinx IP cores into the
+ device tree. The following are bindings for specific devices:
+
+ i) Xilinx ML300 Framebuffer
+
+ Simple framebuffer device from the ML300 reference design (also on the
+ ML403 reference design as well as others).
+
+ Optional properties:
+ - resolution = <xres yres> : pixel resolution of framebuffer. Some
+ implementations use a different resolution.
+ Default is <d#640 d#480>
+ - virt-resolution = <xvirt yvirt> : Size of framebuffer in memory.
+ Default is <d#1024 d#480>.
+ - rotate-display (empty) : rotate display 180 degrees.
+
+ ii) Xilinx SystemACE
+
+ The Xilinx SystemACE device is used to program FPGAs from an FPGA
+ bitstream stored on a CF card. It can also be used as a generic CF
+ interface device.
+
+ Optional properties:
+ - 8-bit (empty) : Set this property for SystemACE in 8 bit mode
+
+ iii) Xilinx EMAC and Xilinx TEMAC
+
+ Xilinx Ethernet devices. In addition to general xilinx properties
+ listed above, nodes for these devices should include a phy-handle
+ property, and may include other common network device properties
+ like local-mac-address.
+
+ iv) Xilinx Uartlite
+
+ Xilinx uartlite devices are simple fixed speed serial ports.
+
+ Requred properties:
+ - current-speed : Baud rate of uartlite
+
More devices will be defined as this spec matures.
VII - Specifying interrupt information for devices
diff --git a/Documentation/powerpc/eeh-pci-error-recovery.txt b/Documentation/powerpc/eeh-pci-error-recovery.txt
index 4530d1bf0286..df7afe43d462 100644
--- a/Documentation/powerpc/eeh-pci-error-recovery.txt
+++ b/Documentation/powerpc/eeh-pci-error-recovery.txt
@@ -36,8 +36,8 @@ Causes of EEH Errors
EEH was originally designed to guard against hardware failure, such
as PCI cards dying from heat, humidity, dust, vibration and bad
electrical connections. The vast majority of EEH errors seen in
-"real life" are due to eithr poorly seated PCI cards, or,
-unfortunately quite commonly, due device driver bugs, device firmware
+"real life" are due to either poorly seated PCI cards, or,
+unfortunately quite commonly, due to device driver bugs, device firmware
bugs, and sometimes PCI card hardware bugs.
The most common software bug, is one that causes the device to
diff --git a/Documentation/powerpc/mpc52xx-device-tree-bindings.txt b/Documentation/powerpc/mpc52xx-device-tree-bindings.txt
index e59fcbbe338c..5e03610e186f 100644
--- a/Documentation/powerpc/mpc52xx-device-tree-bindings.txt
+++ b/Documentation/powerpc/mpc52xx-device-tree-bindings.txt
@@ -17,12 +17,12 @@ passed by the boot loader to the kernel at boot time. The device tree
describes what devices are present on the board and how they are
connected. The device tree can either be passed as a binary blob (as
described in Documentation/powerpc/booting-without-of.txt), or passed
-by Open Firmare (IEEE 1275) compatible firmware using an OF compatible
+by Open Firmware (IEEE 1275) compatible firmware using an OF compatible
client interface API.
This document specifies the requirements on the device-tree for mpc5200
based boards. These requirements are above and beyond the details
-specified in either the OpenFirmware spec or booting-without-of.txt
+specified in either the Open Firmware spec or booting-without-of.txt
All new mpc5200-based boards are expected to match this document. In
cases where this document is not sufficient to support a new board port,
@@ -73,8 +73,8 @@ match on the compatible list; the 'most compatible' driver should be
selected.
The split between the MPC5200 and the MPC5200B leaves a bit of a
-connundrum. How should the compatible property be set up to provide
-maximum compatability information; but still acurately describe the
+conundrum. How should the compatible property be set up to provide
+maximum compatibility information; but still accurately describe the
chip? For the MPC5200; the answer is easy. Most of the SoC devices
originally appeared on the MPC5200. Since they didn't exist anywhere
else; the 5200 compatible properties will contain only one item;
@@ -84,7 +84,7 @@ The 5200B is almost the same as the 5200, but not quite. It fixes
silicon bugs and it adds a small number of enhancements. Most of the
devices either provide exactly the same interface as on the 5200. A few
devices have extra functions but still have a backwards compatible mode.
-To express this infomation as completely as possible, 5200B device trees
+To express this information as completely as possible, 5200B device trees
should have two items in the compatible list;
"mpc5200b-<device>\0mpc5200-<device>". It is *strongly* recommended
that 5200B device trees follow this convention (instead of only listing
@@ -185,7 +185,7 @@ bestcomm@<addr> dma-controller mpc5200-bestcomm 5200 pic also requires
Recommended soc5200 child nodes; populate as needed for your board
name device_type compatible Description
---- ----------- ---------- -----------
-gpt@<addr> gpt mpc5200-gpt General purpose timers
+gpt@<addr> gpt fsl,mpc5200-gpt General purpose timers
rtc@<addr> rtc mpc5200-rtc Real time clock
mscan@<addr> mscan mpc5200-mscan CAN bus controller
pci@<addr> pci mpc5200-pci PCI bridge
@@ -199,7 +199,7 @@ ethernet@<addr> network mpc5200-fec MPC5200 ethernet device
ata@<addr> ata mpc5200-ata IDE ATA interface
i2c@<addr> i2c mpc5200-i2c I2C controller
usb@<addr> usb-ohci-be mpc5200-ohci,ohci-be USB controller
-xlb@<addr> xlb mpc5200-xlb XLB arbritrator
+xlb@<addr> xlb mpc5200-xlb XLB arbitrator
Important child node properties
name type description
@@ -213,7 +213,7 @@ cell-index int When multiple devices are present, is the
5) General Purpose Timer nodes (child of soc5200 node)
On the mpc5200 and 5200b, GPT0 has a watchdog timer function. If the board
design supports the internal wdt, then the device node for GPT0 should
-include the empty property 'has-wdt'.
+include the empty property 'fsl,has-wdt'.
6) PSC nodes (child of soc5200 node)
PSC nodes can define the optional 'port-number' property to force assignment
diff --git a/Documentation/ramdisk.txt b/Documentation/ramdisk.txt
index 52f75b7d51c2..6c820baa19a6 100644
--- a/Documentation/ramdisk.txt
+++ b/Documentation/ramdisk.txt
@@ -22,16 +22,14 @@ The RAM disk dynamically grows as more space is required. It does this by using
RAM from the buffer cache. The driver marks the buffers it is using as dirty
so that the VM subsystem does not try to reclaim them later.
-Also, the RAM disk supports up to 16 RAM disks out of the box, and can
-be reconfigured to support up to 255 RAM disks - change "#define NUM_RAMDISKS"
-in drivers/block/rd.c. To use RAM disk support with your system, run
-'./MAKEDEV ram' from the /dev directory. RAM disks are all major number 1, and
-start with minor number 0 for /dev/ram0, etc. If used, modern kernels use
-/dev/ram0 for an initrd.
-
-The old "ramdisk=<ram_size>" has been changed to "ramdisk_size=<ram_size>" to
-make it clearer. The original "ramdisk=<ram_size>" has been kept around for
-compatibility reasons, but it may be removed in the future.
+The RAM disk supports up to 16 RAM disks by default, and can be reconfigured
+to support an unlimited number of RAM disks (at your own risk). Just change
+the configuration symbol BLK_DEV_RAM_COUNT in the Block drivers config menu
+and (re)build the kernel.
+
+To use RAM disk support with your system, run './MAKEDEV ram' from the /dev
+directory. RAM disks are all major number 1, and start with minor number 0
+for /dev/ram0, etc. If used, modern kernels use /dev/ram0 for an initrd.
The new RAM disk also has the ability to load compressed RAM disk images,
allowing one to squeeze more programs onto an average installation or
diff --git a/Documentation/rtc.txt b/Documentation/rtc.txt
index c931d613f641..e20b19c1b60d 100644
--- a/Documentation/rtc.txt
+++ b/Documentation/rtc.txt
@@ -180,9 +180,10 @@ driver returns ENOIOCTLCMD. Some common examples:
* RTC_IRQP_SET, RTC_IRQP_READ: the irq_set_freq function will be called
to set the frequency while the framework will handle the read for you
since the frequency is stored in the irq_freq member of the rtc_device
- structure. Also make sure you set the max_user_freq member in your
- initialization routines so the framework can sanity check the user
- input for you.
+ structure. Your driver needs to initialize the irq_freq member during
+ init. Make sure you check the requested frequency is in range of your
+ hardware in the irq_set_freq function. If you cannot actually change
+ the frequency, just return -ENOTTY.
If all else fails, check out the rtc-test.c driver!
diff --git a/Documentation/scsi/ChangeLog.ncr53c8xx b/Documentation/scsi/ChangeLog.ncr53c8xx
index 7d03e9d5b5f7..a9f721aeb11c 100644
--- a/Documentation/scsi/ChangeLog.ncr53c8xx
+++ b/Documentation/scsi/ChangeLog.ncr53c8xx
@@ -195,9 +195,9 @@ Sun Feb 14:00 1999 Gerard Roudier (groudier@club-internet.fr)
Pointed out by Leonard Zubkoff.
- Allow to tune request_irq() flags from the boot command line using
ncr53c8xx=irqm:??, as follows:
- a) If bit 0x10 is set in irqm, SA_SHIRQ flag is not used.
- b) If bit 0x20 is set in irqm, SA_INTERRUPT flag is not used.
- By default the driver uses both SA_SHIRQ and SA_INTERRUPT.
+ a) If bit 0x10 is set in irqm, IRQF_SHARED flag is not used.
+ b) If bit 0x20 is set in irqm, IRQF_DISABLED flag is not used.
+ By default the driver uses both IRQF_SHARED and IRQF_DISABLED.
Option 'ncr53c8xx=irqm:0x20' may be used when an IRQ is shared by
a 53C8XX adapter and a network board.
- Tiny mispelling fixed (ABORT instead of ABRT). Was fortunately
diff --git a/Documentation/scsi/aic79xx.txt b/Documentation/scsi/aic79xx.txt
index 6aa9a891f3d0..683ccae00ad4 100644
--- a/Documentation/scsi/aic79xx.txt
+++ b/Documentation/scsi/aic79xx.txt
@@ -120,7 +120,7 @@ The following information is available in this file:
list size to avoid SCSI malloc pool fragmentation.
- Cleanup channel display in our /proc output.
- Workaround duplicate device entries in the mid-layer
- devlice list during add-single-device.
+ device list during add-single-device.
1.3.6 (March 28th, 2003)
- Correct a double free in the Domain Validation code.
diff --git a/Documentation/scsi/aic7xxx.txt b/Documentation/scsi/aic7xxx.txt
index 5f34d2ba69b4..b7e238cbb5a7 100644
--- a/Documentation/scsi/aic7xxx.txt
+++ b/Documentation/scsi/aic7xxx.txt
@@ -159,7 +159,7 @@ The following information is available in this file:
- Add support for 2.5.X's scsi_report_device_reset().
6.2.34 (May 5th, 2003)
- - Fix locking regression instroduced in 6.2.29 that
+ - Fix locking regression introduced in 6.2.29 that
could cause a lock order reversal between the io_request_lock
and our per-softc lock. This was only possible on RH9,
SuSE, and kernel.org 2.4.X kernels.
@@ -264,7 +264,7 @@ The following information is available in this file:
Option: tag_info:{{value[,value...]}[,{value[,value...]}...]}
Definition: Set the per-target tagged queue depth on a
per controller basis. Both controllers and targets
- may be ommitted indicating that they should retain
+ may be omitted indicating that they should retain
the default tag depth.
Examples: tag_info:{{16,32,32,64,8,8,,32,32,32,32,32,32,32,32,32}
On Controller 0
@@ -290,7 +290,7 @@ The following information is available in this file:
-----------------------------------------------------------------
Option: dv: {value[,value...]}
Definition: Set Domain Validation Policy on a per-controller basis.
- Controllers may be ommitted indicating that
+ Controllers may be omitted indicating that
they should retain the default read streaming setting.
Example: dv:{-1,0,,1,1,0}
On Controller 0 leave DV at its default setting.
diff --git a/Documentation/scsi/arcmsr_spec.txt b/Documentation/scsi/arcmsr_spec.txt
index 5e0042340fd3..45d9482c1517 100644
--- a/Documentation/scsi/arcmsr_spec.txt
+++ b/Documentation/scsi/arcmsr_spec.txt
@@ -3,7 +3,7 @@
*******************************************************************************
** Usage of IOP331 adapter
** (All In/Out is in IOP331's view)
-** 1. Message 0 --> InitThread message and retrun code
+** 1. Message 0 --> InitThread message and return code
** 2. Doorbell is used for RS-232 emulation
** inDoorBell : bit0 -- data in ready
** (DRIVER DATA WRITE OK)
diff --git a/Documentation/scsi/ibmmca.txt b/Documentation/scsi/ibmmca.txt
index 9707941704e3..a810421f1fb3 100644
--- a/Documentation/scsi/ibmmca.txt
+++ b/Documentation/scsi/ibmmca.txt
@@ -21,7 +21,7 @@
versions older than 4.0 do not work with kernels 2.4.0 or later! If you
try to compile your kernel with the wrong driver source, the
compilation is aborted and you get a corresponding error message. This is
- no bug in the driver. It prevents you from using the wrong sourcecode
+ no bug in the driver; it prevents you from using the wrong source code
with the wrong kernel version.
Authors of this Driver
@@ -58,7 +58,7 @@
5 Users' Manual
5.1 Commandline Parameters
5.2 Troubleshooting
- 5.3 Bugreports
+ 5.3 Bug reports
5.4 Support WWW-page
6 References
7 Credits to
@@ -71,13 +71,13 @@
1 Abstract
----------
- This README-file describes the IBM SCSI-subsystem low level driver for
- Linux. The descriptions which were formerly kept in the source-code have
- been taken out to this file to easify the codes' readability. The driver
+ This README-file describes the IBM SCSI-subsystem low level driver for
+ Linux. The descriptions which were formerly kept in the source code have
+ been taken out of this file to simplify the codes readability. The driver
description has been updated, as most of the former description was already
- quite outdated. The history of the driver development is also kept inside
- here. Multiple historical developments have been summarized to shorten the
- textsize a bit. At the end of this file you can find a small manual for
+ quite outdated. The history of the driver development is also kept inside
+ here. Multiple historical developments have been summarized to shorten the
+ text size a bit. At the end of this file you can find a small manual for
this driver and hints to get it running on your machine.
2 Driver Description
@@ -186,7 +186,7 @@
between 0 and 7). The IBM SCSI-2 F/W adapter offers this on up to two
busses and provides support for 30 logical devices at the same time, where
in wide-addressing mode you can have 16 puns with 32 luns on each device.
- This section dexribes you the handling of devices on non-F/W adapters.
+ This section describes the handling of devices on non-F/W adapters.
Just imagine, that you can have 16 * 32 = 512 devices on a F/W adapter
which means a lot of possible devices for such a small machine.
@@ -209,10 +209,10 @@
--------------------------------------------------------
One consequence of information hiding is that the real (pun,lun)
numbers are also hidden. The two possibilities to get around this problem
- is to offer fake pun/lun combinations to the operating system or to
+ are to offer fake pun/lun combinations to the operating system or to
delete the whole mapping of the adapter and to reassign the ldns, using
the immediate assign command of the SCSI-subsystem for probing through
- all possible pun/lun combinations. a ldn is a "logical device number"
+ all possible pun/lun combinations. An ldn is a "logical device number"
which is used by IBM SCSI-subsystems to access some valid SCSI-device.
At the beginning of the development of this driver, the following approach
was used:
@@ -251,9 +251,9 @@
lun>0 or to non-existing devices, in order to satisfy the subsystem, if
there are less than 15 SCSI-devices connected. In the case of more than 15
devices, the dynamical mapping goes active. If the get_scsi[][] reports a
- device to be existant, but it has no ldn assigned, it gets a ldn out of 7
- to 14. The numbers are assigned in cyclic order. Therefore it takes 8
- dynamical reassignments on the SCSI-devices, until a certain device
+ device to be existent, but it has no ldn assigned, it gets an ldn out of 7
+ to 14. The numbers are assigned in cyclic order, therefore it takes 8
+ dynamical reassignments on the SCSI-devices until a certain device
loses its ldn again. This assures that dynamical remapping is avoided
during intense I/O between up to 15 SCSI-devices (means pun,lun
combinations). A further advantage of this method is that people who
@@ -551,7 +551,7 @@
than devices are available, they are assigned to non existing pun,lun
combinations to satisfy the adapter. With this, the dynamical mapping
was possible to implement. (For further info see the text in the
- source-code and in the description below. Read the description
+ source code and in the description below. Read the description
below BEFORE installing this driver on your system!)
2) Changed the name IBMMCA_DRIVER_VERSION to IBMMCA_SCSI_DRIVER_VERSION.
3) The LED-display shows on PS/2-95 no longer the ldn, but the SCSI-ID
@@ -762,9 +762,9 @@
- Michael Lang
Apr 23, 2000 (v3.2pre1)
- 1) During a very long time, I collected a huge amount of bugreports from
+ 1) During a very long time, I collected a huge amount of bug reports from
various people, trying really quite different things on their SCSI-
- PS/2s. Today, all these bugreports are taken into account and should be
+ PS/2s. Today, all these bug reports are taken into account and should be
mostly solved. The major topics were:
- Driver crashes during boottime by no obvious reason.
- Driver panics while the midlevel-SCSI-driver is trying to inquire
@@ -819,7 +819,7 @@
- Michael Lang
July 17, 2000 (v3.2pre8)
- A long period of collecting bugreports from all corners of the world
+ A long period of collecting bug reports from all corners of the world
now lead to the following corrections to the code:
1) SCSI-2 F/W support crashed with a COMMAND ERROR. The reason for this
was that it is possible to disable Fast-SCSI for the external bus.
@@ -873,7 +873,7 @@
July 26, 2000 (v3.2pre11)
1) I passed a horrible weekend getting mad with NMIs on kernel 2.2.14 and
a model 9595. Asking around in the community, nobody except of me has
- seen such errors. Weired, but I am trying to recompile everything on
+ seen such errors. Weird, but I am trying to recompile everything on
the model 9595. Maybe, as I use a specially modified gcc, that could
cause problems. But, it was not the reason. The true background was,
that the kernel was compiled for i386 and the 9595 has a 486DX-2.
@@ -886,7 +886,7 @@
alive rotator during boottime. This makes sense, when no monitor is
connected to the system. You can get rid of all display activity, if
you do not use any parameter or just ibmmcascsi=activity, for the
- harddrive activity LED, existant on all PS/2, except models 8595-XXX.
+ harddrive activity LED, existent on all PS/2, except models 8595-XXX.
If no monitor is available, please use ibmmcascsi=display, which works
fine together with the linuxinfo utility for the LED-panel.
- Michael Lang
@@ -1115,7 +1115,7 @@
If this really happens, do also send e-mail to the maintainer, as
forced detection should be never necessary. Forced detection is in
principal some flaw of the driver adapter detection and goes into
- bugreports.
+ bug reports.
Q: The driver screws up, if it starts to probe SCSI-devices, is there
some way out of it?
A: Yes, that was some recognition problem of the correct SCSI-adapter
@@ -1172,7 +1172,7 @@
recommended version is 3.2 or later. Here, the F/W support is in
a stable and reliable condition. Wide-addressing is in addition
supported.
- Q: I get a Ooops message and something like "killing interrupt".
+ Q: I get an Oops message and something like "killing interrupt".
A: The reason for this is that the IBM SCSI-subsystem only sends a
termination status back, if some error appeared. In former releases
of the driver, it was not checked, if the termination status block
@@ -1188,7 +1188,7 @@
and 15 get ignored by the driver & adapter!
Q: I have a 9595 and I get a NMI during heavy SCSI I/O e.g. during fsck.
A COMMAND ERROR is reported and characters on the screen are missing.
- Warm reboot is not possible. Things look like quite weired.
+ Warm reboot is not possible. Things look like quite weird.
A: Check the processor type of your 9595. If you have an 80486 or 486DX-2
processor complex on your mainboard and you compiled a kernel that
supports 80386 processors, it is possible, that the kernel cannot
@@ -1213,21 +1213,21 @@
problem. Not yet tried, but guessing that it could work. To get this,
set unchecked_isa_dma argument of ibmmca.h from 0 to 1.
- 5.3 Bugreports
+ 5.3 Bug reports
--------------
- If you really find bugs in the sourcecode or the driver will successfully
+ If you really find bugs in the source code or the driver will successfully
refuse to work on your machine, you should send a bug report to me. The
best for this is to follow the instructions on the WWW-page for this
driver. Fill out the bug-report form, placed on the WWW-page and ship it,
so the bugs can be taken into account with maximum efforts. But, please
do not send bug reports about this driver to Linus Torvalds or Leonard
- Zubkoff, as Linus is burried in E-Mail and Leonard is supervising all
+ Zubkoff, as Linus is buried in E-Mail and Leonard is supervising all
SCSI-drivers and won't have the time left to look inside every single
driver to fix a bug and especially DO NOT send modified code to Linus
Torvalds or Alan J. Cox which has not been checked here!!! They are both
- quite burried in E-mail (as me, sometimes, too) and one should first check
+ quite buried in E-mail (as me, sometimes, too) and one should first check
for problems on my local teststand. Recently, I got a lot of
- bugreports for errors in the ibmmca.c code, which I could not imagine, but
+ bug reports for errors in the ibmmca.c code, which I could not imagine, but
a look inside some Linux-distribution showed me quite often some modified
code, which did no longer work on most other machines than the one of the
modifier. Ok, so now that there is maintenance service available for this
@@ -1261,7 +1261,7 @@
some e-mail directly, but at least with the same information as required by
the formular.
- If you have extensive bugreports, including Ooops messages and
+ If you have extensive bug reports, including Oops messages and
screen-shots, please feel free to send it directly to the address
of the maintainer, too. The current address of the maintainer is:
@@ -1318,7 +1318,7 @@
detailed bug reports and ideas for this driver (and his
patience ;-)).
Alan J. Cox
- for his bugreports and his bold activities in cross-checking
+ for his bug reports and his bold activities in cross-checking
the driver-code with his teststand.
7.2 Sponsors & Supporters
diff --git a/Documentation/scsi/link_power_management_policy.txt b/Documentation/scsi/link_power_management_policy.txt
new file mode 100644
index 000000000000..d18993d01884
--- /dev/null
+++ b/Documentation/scsi/link_power_management_policy.txt
@@ -0,0 +1,19 @@
+This parameter allows the user to set the link (interface) power management.
+There are 3 possible options:
+
+Value Effect
+----------------------------------------------------------------------------
+min_power Tell the controller to try to make the link use the
+ least possible power when possible. This may
+ sacrifice some performance due to increased latency
+ when coming out of lower power states.
+
+max_performance Generally, this means no power management. Tell
+ the controller to have performance be a priority
+ over power management.
+
+medium_power Tell the controller to enter a lower power state
+ when possible, but do not enter the lowest power
+ state, thus improving latency over min_power setting.
+
+
diff --git a/Documentation/scsi/ncr53c8xx.txt b/Documentation/scsi/ncr53c8xx.txt
index 39d409a8efe5..230e30846ef2 100644
--- a/Documentation/scsi/ncr53c8xx.txt
+++ b/Documentation/scsi/ncr53c8xx.txt
@@ -785,8 +785,8 @@ port address 0x1400.
irqm:0 always open drain
irqm:1 same as initial settings (assumed BIOS settings)
irqm:2 always totem pole
- irqm:0x10 driver will not use SA_SHIRQ flag when requesting irq
- irqm:0x20 driver will not use SA_INTERRUPT flag when requesting irq
+ irqm:0x10 driver will not use IRQF_SHARED flag when requesting irq
+ irqm:0x20 driver will not use IRQF_DISABLED flag when requesting irq
(Bits 0x10 and 0x20 can be combined with hardware irq mode option)
@@ -1236,15 +1236,15 @@ when the SCSI DATA IN phase is reentered after a phase mismatch.
When an IRQ is shared by devices that are handled by different drivers, it
may happen that one driver complains about the request of the IRQ having
failed. Inder Linux-2.0, this may be due to one driver having requested the
-IRQ using the SA_INTERRUPT flag but some other having requested the same IRQ
+IRQ using the IRQF_DISABLED flag but some other having requested the same IRQ
without this flag. Under both Linux-2.0 and linux-2.2, this may be caused by
-one driver not having requested the IRQ with the SA_SHIRQ flag.
+one driver not having requested the IRQ with the IRQF_SHARED flag.
By default, the ncr53c8xx and sym53c8xx drivers request IRQs with both the
-SA_INTERRUPT and the SA_SHIRQ flag under Linux-2.0 and with only the SA_SHIRQ
+IRQF_DISABLED and the IRQF_SHARED flag under Linux-2.0 and with only the IRQF_SHARED
flag under Linux-2.2.
-Under Linux-2.0, you can disable use of SA_INTERRUPT flag from the boot
+Under Linux-2.0, you can disable use of IRQF_DISABLED flag from the boot
command line by using the following option:
ncr53c8xx=irqm:0x20 (for the generic ncr53c8xx driver)
@@ -1252,7 +1252,7 @@ command line by using the following option:
If this does not fix the problem, then you may want to check how all other
drivers are requesting the IRQ and report the problem. Note that if at least
-a single driver does not request the IRQ with the SA_SHIRQ flag (share IRQ),
+a single driver does not request the IRQ with the IRQF_SHARED flag (share IRQ),
then the request of the IRQ obviously will not succeed for all the drivers.
15. SCSI problem troubleshooting
diff --git a/Documentation/scsi/sym53c8xx_2.txt b/Documentation/scsi/sym53c8xx_2.txt
index 3d9f06bb3d00..49ea5c58c6bc 100644
--- a/Documentation/scsi/sym53c8xx_2.txt
+++ b/Documentation/scsi/sym53c8xx_2.txt
@@ -449,25 +449,14 @@ options as above.
cmd_per_lun=#tags (#tags > 1) tagged command queuing enabled
#tags will be truncated to the max queued commands configuration parameter.
-10.2.2 Detailed control of tagged commands
- This option allows you to specify a command queue depth for each device
- that supports tagged command queueing.
- Example:
- tag_ctrl=10/t2t3q16-t5q24/t1u2q32
- will set devices queue depth as follow:
- - controller #0 target #2 and target #3 -> 16 commands,
- - controller #0 target #5 -> 24 commands,
- - controller #1 target #1 logical unit #2 -> 32 commands,
- - all other logical units (all targets, all controllers) -> 10 commands.
-
-10.2.3 Burst max
+10.2.2 Burst max
burst=0 burst disabled
burst=255 get burst length from initial IO register settings.
burst=#x burst enabled (1<<#x burst transfers max)
#x is an integer value which is log base 2 of the burst transfers max.
By default the driver uses the maximum value supported by the chip.
-10.2.4 LED support
+10.2.3 LED support
led=1 enable LED support
led=0 disable LED support
Do not enable LED support if your scsi board does not use SDMS BIOS.
@@ -560,9 +549,9 @@ Previously, the sym2 driver accepted arguments of the form
sym53c8xx=tags:4,sync:10,debug:0x200
As a result of the new module parameters, this is no longer available.
-Most of the options have remained the same, but tags has split into
-cmd_per_lun and tag_ctrl for its two different purposes. The sample above
-would be specified as:
+Most of the options have remained the same, but tags has become
+cmd_per_lun to reflect its different purposes. The sample above would
+be specified as:
modprobe sym53c8xx cmd_per_lun=4 sync=10 debug=0x200
or on the kernel boot line as:
diff --git a/Documentation/sharedsubtree.txt b/Documentation/sharedsubtree.txt
index ccf1cebe744f..736540045dc7 100644
--- a/Documentation/sharedsubtree.txt
+++ b/Documentation/sharedsubtree.txt
@@ -153,6 +153,7 @@ replicas continue to be exactly same.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
+ #include <string.h>
#include <sys/mount.h>
#include <sys/fsuid.h>
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 241e26c4ff92..4b48c2e82c3c 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -365,13 +365,14 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Module snd-cmipci
-----------------
- Module for C-Media CMI8338 and 8738 PCI sound cards.
+ Module for C-Media CMI8338/8738/8768/8770 PCI sound cards.
- mpu_port - 0x300,0x310,0x320,0x330 = legacy port,
- 1 = integrated PCI port,
+ mpu_port - port address of MIDI interface (8338 only):
+ 0x300,0x310,0x320,0x330 = legacy port,
0 = disable (default)
- fm_port - 0x388 = legacy port,
- 1 = integrated PCI port (default),
+ fm_port - port address of OPL-3 FM synthesizer (8x38 only):
+ 0x388 = legacy port,
+ 1 = integrated PCI port (default on 8738),
0 = disable
soft_ac3 - Software-conversion of raw SPDIF packets (model 033 only)
(default = 1)
@@ -768,6 +769,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
single_cmd - Use single immediate commands to communicate with
codecs (for debugging only)
enable_msi - Enable Message Signaled Interrupt (MSI) (default = off)
+ power_save - Automatic power-saving timtout (in second, 0 =
+ disable)
+ power_save_controller - Reset HD-audio controller in power-saving mode
+ (default = on)
This module supports one card and autoprobe.
@@ -828,6 +833,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
ALC268
3stack 3-stack model
+ toshiba Toshiba A205
+ acer Acer laptops
auto auto-config reading BIOS (default)
ALC662
@@ -842,7 +849,11 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
3stack-dig 3-jack with SPDIF I/O
6stack-dig 6-jack digital with SPDIF I/O
arima Arima W820Di1
+ targa Targa T8, MSI-1049 T8
+ asus-a7j ASUS A7J
+ asus-a7m ASUS A7M
macpro MacPro support
+ mbp3 Macbook Pro rev3
imac24 iMac 24'' with jack detection
w2jc ASUS W2JC
auto auto-config reading BIOS (default)
@@ -854,6 +865,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
3stack-6ch-dig 3-jack 6-channel with SPDIF I/O
6stack-dig-demo 6-jack digital for Intel demo board
acer Acer laptops (Travelmate 3012WTMi, Aspire 5600, etc)
+ acer-aspire Acer Aspire 9810
medion Medion Laptops
medion-md2 Medion MD2
targa-dig Targa/MSI
@@ -862,6 +874,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
lenovo-101e Lenovo 101E
lenovo-nb0763 Lenovo NB0763
lenovo-ms7195-dig Lenovo MS7195
+ haier-w66 Haier W66
6stack-hp HP machines with 6stack (Nettle boards)
3stack-hp HP machines with 3stack (Lucknow, Samba boards)
auto auto-config reading BIOS (default)
@@ -885,6 +898,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
3stack-660-digout 3-jack with SPDIF OUT (for ALC660VD)
lenovo Lenovo 3000 C200
dallas Dallas laptops
+ hp HP TX1000
auto auto-config reading BIOS (default)
CMI9880
@@ -920,6 +934,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
3stack 3-stack, shared surrounds
laptop 2-channel only (FSC V2060, Samsung M50)
laptop-eapd 2-channel with EAPD (Samsung R65, ASUS A6J)
+ laptop-automute 2-channel with EAPD and HP-automute (Lenovo N100)
ultra 2-channel with EAPD (Samsung Ultra tablet PC)
AD1988
@@ -945,14 +960,30 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
can be adjusted. Appearing only when compiled with
$CONFIG_SND_DEBUG=y
- STAC9200/9205/9254
+ STAC9200
ref Reference board
+ dell-d21 Dell (unknown)
+ dell-d22 Dell (unknown)
+ dell-d23 Dell (unknown)
+ dell-m21 Dell Inspiron 630m, Dell Inspiron 640m
+ dell-m22 Dell Latitude D620, Dell Latitude D820
+ dell-m23 Dell XPS M1710, Dell Precision M90
+ dell-m24 Dell Latitude 120L
+ dell-m25 Dell Inspiron E1505n
+ dell-m26 Dell Inspiron 1501
+ dell-m27 Dell Inspiron E1705/9400
+ gateway Gateway laptops with EAPD control
+
+ STAC9205/9254
+ ref Reference board
+ dell-m42 Dell (unknown)
+ dell-m43 Dell Precision
+ dell-m44 Dell Inspiron
STAC9220/9221
ref Reference board
3stack D945 3stack
5stack D945 5stack + SPDIF
- dell Dell XPS M1210
intel-mac-v1 Intel Mac Type 1
intel-mac-v2 Intel Mac Type 2
intel-mac-v3 Intel Mac Type 3
@@ -964,6 +995,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
macbook-pro Intel Mac Book Pro 2nd generation (eq. type 3)
imac-intel Intel iMac (eq. type 2)
imac-intel-20 Intel iMac (newer version) (eq. type 3)
+ dell-d81 Dell (unknown)
+ dell-d82 Dell (unknown)
+ dell-m81 Dell (unknown)
+ dell-m82 Dell XPS M1210
STAC9202/9250/9251
ref Reference board, base config
@@ -975,6 +1010,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
ref Reference board
3stack D965 3stack
5stack D965 5stack + SPDIF
+ dell-3stack Dell Dimension E520
STAC9872
vaio Setup for VAIO FE550G/SZ110
@@ -989,6 +1025,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
subsystem ID (output of "lspci -nv") to ALSA BTS or alsa-devel
ML (see the section "Links and Addresses").
+ power_save and power_save_controller options are for power-saving
+ mode. See powersave.txt for details.
+
Note 2: If you get click noises on output, try the module option
position_fix=1 or 2. position_fix=1 will use the SD_LPIB
register value without FIFO size correction as the current
@@ -1349,7 +1388,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
port - port number or -1 (disable)
irq - IRQ number or -1 (disable)
pnp - PnP detection - 0 = disable, 1 = enable (default)
- uart_enter - Issue UART_ENTER command at open - bool, default = on
This module supports multiple devices and PnP.
@@ -1630,6 +1668,21 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
The power-management is supported.
+ Module snd-sc6000
+ -----------------
+
+ Module for Gallant SC-6000 soundcard.
+
+ port - Port # (0x220 or 0x240)
+ mss_port - MSS Port # (0x530 or 0xe80)
+ irq - IRQ # (5,7,9,10,11)
+ mpu_irq - MPU-401 IRQ # (5,7,9,10) ,0 - no MPU-401 irq
+ dma - DMA # (1,3,0)
+
+ This module supports multiple cards.
+
+ This card is also known as Audio Excel DSP 16 or Zoltrix AV302.
+
Module snd-sgalaxy
------------------
@@ -1650,9 +1703,11 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Module for ENSONIQ SoundScape PnP cards.
port - Port # (PnP setup)
+ wss_port - WSS Port # (PnP setup)
irq - IRQ # (PnP setup)
mpu_irq - MPU-401 IRQ # (PnP setup)
dma - DMA # (PnP setup)
+ dma2 - 2nd DMA # (PnP setup, -1 to disable)
This module supports multiple cards. ISA PnP must be enabled.
You need sscape_ctl tool in alsa-tools package for loading
@@ -1697,8 +1752,52 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
dma2 - DMA2 # for CS4232 PCM interface.
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
+ The below are options for wavefront_synth features:
+ wf_raw - Assume that we need to boot the OS (default:no)
+ If yes, then during driver loading, the state of the board is
+ ignored, and we reset the board and load the firmware anyway.
+ fx_raw - Assume that the FX process needs help (default:yes)
+ If false, we'll leave the FX processor in whatever state it is
+ when the driver is loaded. The default is to download the
+ microprogram and associated coefficients to set it up for
+ "default" operation, whatever that means.
+ debug_default - Debug parameters for card initialization
+ wait_usecs - How long to wait without sleeping, usecs
+ (default:150)
+ This magic number seems to give pretty optimal throughput
+ based on my limited experimentation.
+ If you want to play around with it and find a better value, be
+ my guest. Remember, the idea is to get a number that causes us
+ to just busy wait for as many WaveFront commands as possible,
+ without coming up with a number so large that we hog the whole
+ CPU.
+ Specifically, with this number, out of about 134,000 status
+ waits, only about 250 result in a sleep.
+ sleep_interval - How long to sleep when waiting for reply
+ (default: 100)
+ sleep_tries - How many times to try sleeping during a wait
+ (default: 50)
+ ospath - Pathname to processed ICS2115 OS firmware
+ (default:wavefront.os)
+ The path name of the ISC2115 OS firmware. In the recent
+ version, it's handled via firmware loader framework, so it
+ must be installed in the proper path, typically,
+ /lib/firmware.
+ reset_time - How long to wait for a reset to take effect
+ (default:2)
+ ramcheck_time - How many seconds to wait for the RAM test
+ (default:20)
+ osrun_time - How many seconds to wait for the ICS2115 OS
+ (default:10)
+
This module supports multiple cards and ISA PnP.
+ Note: the firmware file "wavefront.os" was located in the earlier
+ version in /etc. Now it's loaded via firmware loader, and
+ must be in the proper firmware path, such as /lib/firmware.
+ Copy (or symlink) the file appropriately if you get an error
+ regarding firmware downloading after upgrading the kernel.
+
Module snd-sonicvibes
---------------------
diff --git a/Documentation/sound/alsa/CMIPCI.txt b/Documentation/sound/alsa/CMIPCI.txt
index 4b2b15387056..16935c8561f7 100644
--- a/Documentation/sound/alsa/CMIPCI.txt
+++ b/Documentation/sound/alsa/CMIPCI.txt
@@ -1,5 +1,5 @@
- Brief Notes on C-Media 8738/8338 Driver
- =======================================
+ Brief Notes on C-Media 8338/8738/8768/8770 Driver
+ =================================================
Takashi Iwai <tiwai@suse.de>
@@ -209,10 +209,13 @@ In addition to the standard SB mixer, CM8x38 provides more functions.
MIDI CONTROLLER
---------------
-The MPU401-UART interface is disabled as default. You need to set
-module option "mpu_port" with a valid I/O port address to enable the
-MIDI support. The valid I/O ports are 0x300, 0x310, 0x320 and 0x330.
-Choose the value which doesn't conflict with other cards.
+With CMI8338 chips, the MPU401-UART interface is disabled as default.
+You need to set the module option "mpu_port" to a valid I/O port address
+to enable MIDI support. Valid I/O ports are 0x300, 0x310, 0x320 and
+0x330. Choose a value that doesn't conflict with other cards.
+
+With CMI8738 and newer chips, the MIDI interface is enabled by default
+and the driver automatically chooses a port address.
There is _no_ hardware wavetable function on this chip (except for
OPL3 synth below).
@@ -230,6 +233,8 @@ Set "fm_port" module option for more cards.
The output quality of FM OPL/3 is, however, very weird.
I don't know why..
+CMI8768 and newer chips do not have the FM synth.
+
Joystick and Modem
------------------
diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
index 74d3a35b59bc..2c3fc3cb3b6b 100644
--- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
+++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
@@ -18,8 +18,8 @@
</affiliation>
</author>
- <date>November 17, 2005</date>
- <edition>0.3.6</edition>
+ <date>September 10, 2007</date>
+ <edition>0.3.7</edition>
<abstract>
<para>
@@ -405,8 +405,9 @@
/* definition of the chip-specific record */
struct mychip {
struct snd_card *card;
- // rest of implementation will be in the section
- // "PCI Resource Managements"
+ /* rest of implementation will be in the section
+ * "PCI Resource Managements"
+ */
};
/* chip-specific destructor
@@ -414,7 +415,7 @@
*/
static int snd_mychip_free(struct mychip *chip)
{
- .... // will be implemented later...
+ .... /* will be implemented later... */
}
/* component-destructor
@@ -440,8 +441,9 @@
*rchip = NULL;
- // check PCI availability here
- // (see "PCI Resource Managements")
+ /* check PCI availability here
+ * (see "PCI Resource Managements")
+ */
....
/* allocate a chip-specific data with zero filled */
@@ -451,12 +453,13 @@
chip->card = card;
- // rest of initialization here; will be implemented
- // later, see "PCI Resource Managements"
+ /* rest of initialization here; will be implemented
+ * later, see "PCI Resource Managements"
+ */
....
- if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,
- chip, &ops)) < 0) {
+ err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
+ if (err < 0) {
snd_mychip_free(chip);
return err;
}
@@ -490,7 +493,8 @@
return -ENOMEM;
/* (3) */
- if ((err = snd_mychip_create(card, pci, &chip)) < 0) {
+ err = snd_mychip_create(card, pci, &chip);
+ if (err < 0) {
snd_card_free(card);
return err;
}
@@ -502,10 +506,11 @@
card->shortname, chip->ioport, chip->irq);
/* (5) */
- .... // implemented later
+ .... /* implemented later */
/* (6) */
- if ((err = snd_card_register(card)) < 0) {
+ err = snd_card_register(card);
+ if (err < 0) {
snd_card_free(card);
return err;
}
@@ -605,7 +610,8 @@
<![CDATA[
struct mychip *chip;
....
- if ((err = snd_mychip_create(card, pci, &chip)) < 0) {
+ err = snd_mychip_create(card, pci, &chip);
+ if (err < 0) {
snd_card_free(card);
return err;
}
@@ -666,7 +672,8 @@
<informalexample>
<programlisting>
<![CDATA[
- if ((err = snd_card_register(card)) < 0) {
+ err = snd_card_register(card);
+ if (err < 0) {
snd_card_free(card);
return err;
}
@@ -1091,7 +1098,7 @@
static int snd_mychip_free(struct mychip *chip)
{
/* disable hardware here if any */
- .... // (not implemented in this document)
+ .... /* (not implemented in this document) */
/* release the irq */
if (chip->irq >= 0)
@@ -1119,7 +1126,8 @@
*rchip = NULL;
/* initialize the PCI entry */
- if ((err = pci_enable_device(pci)) < 0)
+ err = pci_enable_device(pci);
+ if (err < 0)
return err;
/* check PCI availability (28bit DMA) */
if (pci_set_dma_mask(pci, DMA_28BIT_MASK) < 0 ||
@@ -1141,7 +1149,8 @@
chip->irq = -1;
/* (1) PCI resource allocation */
- if ((err = pci_request_regions(pci, "My Chip")) < 0) {
+ err = pci_request_regions(pci, "My Chip");
+ if (err < 0) {
kfree(chip);
pci_disable_device(pci);
return err;
@@ -1156,10 +1165,10 @@
chip->irq = pci->irq;
/* (2) initialization of the chip hardware */
- .... // (not implemented in this document)
+ .... /* (not implemented in this document) */
- if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,
- chip, &ops)) < 0) {
+ err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
+ if (err < 0) {
snd_mychip_free(chip);
return err;
}
@@ -1233,7 +1242,8 @@
<informalexample>
<programlisting>
<![CDATA[
- if ((err = pci_enable_device(pci)) < 0)
+ err = pci_enable_device(pci);
+ if (err < 0)
return err;
if (pci_set_dma_mask(pci, DMA_28BIT_MASK) < 0 ||
pci_set_consistent_dma_mask(pci, DMA_28BIT_MASK) < 0) {
@@ -1294,7 +1304,8 @@
<informalexample>
<programlisting>
<![CDATA[
- if ((err = pci_request_regions(pci, "My Chip")) < 0) {
+ err = pci_request_regions(pci, "My Chip");
+ if (err < 0) {
kfree(chip);
pci_disable_device(pci);
return err;
@@ -1322,7 +1333,7 @@
<programlisting>
<![CDATA[
if (request_irq(pci->irq, snd_mychip_interrupt,
- IRQF_DISABLED|IRQF_SHARED, "My Chip", chip)) {
+ IRQF_SHARED, "My Chip", chip)) {
printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
snd_mychip_free(chip);
return -EBUSY;
@@ -1773,7 +1784,8 @@
struct snd_pcm_runtime *runtime = substream->runtime;
runtime->hw = snd_mychip_playback_hw;
- // more hardware-initialization will be done here
+ /* more hardware-initialization will be done here */
+ ....
return 0;
}
@@ -1781,7 +1793,8 @@
static int snd_mychip_playback_close(struct snd_pcm_substream *substream)
{
struct mychip *chip = snd_pcm_substream_chip(substream);
- // the hardware-specific codes will be here
+ /* the hardware-specific codes will be here */
+ ....
return 0;
}
@@ -1793,7 +1806,8 @@
struct snd_pcm_runtime *runtime = substream->runtime;
runtime->hw = snd_mychip_capture_hw;
- // more hardware-initialization will be done here
+ /* more hardware-initialization will be done here */
+ ....
return 0;
}
@@ -1801,7 +1815,8 @@
static int snd_mychip_capture_close(struct snd_pcm_substream *substream)
{
struct mychip *chip = snd_pcm_substream_chip(substream);
- // the hardware-specific codes will be here
+ /* the hardware-specific codes will be here */
+ ....
return 0;
}
@@ -1844,10 +1859,12 @@
{
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
- // do something to start the PCM engine
+ /* do something to start the PCM engine */
+ ....
break;
case SNDRV_PCM_TRIGGER_STOP:
- // do something to stop the PCM engine
+ /* do something to stop the PCM engine */
+ ....
break;
default:
return -EINVAL;
@@ -1900,8 +1917,8 @@
struct snd_pcm *pcm;
int err;
- if ((err = snd_pcm_new(chip->card, "My Chip", 0, 1, 1,
- &pcm)) < 0)
+ err = snd_pcm_new(chip->card, "My Chip", 0, 1, 1, &pcm);
+ if (err < 0)
return err;
pcm->private_data = chip;
strcpy(pcm->name, "My Chip");
@@ -1939,8 +1956,8 @@
struct snd_pcm *pcm;
int err;
- if ((err = snd_pcm_new(chip->card, "My Chip", 0, 1, 1,
- &pcm)) < 0)
+ err = snd_pcm_new(chip->card, "My Chip", 0, 1, 1, &pcm);
+ if (err < 0)
return err;
pcm->private_data = chip;
strcpy(pcm->name, "My Chip");
@@ -2097,7 +2114,7 @@
struct mychip *chip = snd_pcm_chip(pcm);
/* free your own data */
kfree(chip->my_private_pcm_data);
- // do what you like else
+ /* do what you like else */
....
}
@@ -2884,10 +2901,10 @@ struct _snd_pcm_runtime {
<![CDATA[
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
- // do something to start the PCM engine
+ /* do something to start the PCM engine */
break;
case SNDRV_PCM_TRIGGER_STOP:
- // do something to stop the PCM engine
+ /* do something to stop the PCM engine */
break;
default:
return -EINVAL;
@@ -3071,7 +3088,7 @@ struct _snd_pcm_runtime {
spin_unlock(&chip->lock);
snd_pcm_period_elapsed(chip->substream);
spin_lock(&chip->lock);
- // acknowledge the interrupt if necessary
+ /* acknowledge the interrupt if necessary */
}
....
spin_unlock(&chip->lock);
@@ -3134,7 +3151,7 @@ struct _snd_pcm_runtime {
snd_pcm_period_elapsed(substream);
spin_lock(&chip->lock);
}
- // acknowledge the interrupt if necessary
+ /* acknowledge the interrupt if necessary */
}
....
spin_unlock(&chip->lock);
@@ -3456,6 +3473,13 @@ struct _snd_pcm_runtime {
</para>
<para>
+ The <structfield>tlv</structfield> field can be used to provide
+ metadata about the control; see the
+ <link linkend="control-interface-tlv">
+ <citetitle>Metadata</citetitle></link> subsection.
+ </para>
+
+ <para>
The other three are
<link linkend="control-interface-callbacks"><citetitle>
callback functions</citetitle></link>.
@@ -3604,7 +3628,7 @@ struct _snd_pcm_runtime {
<title>Example of info callback</title>
<programlisting>
<![CDATA[
- static int snd_myctl_info(struct snd_kcontrol *kcontrol,
+ static int snd_myctl_mono_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
@@ -3639,7 +3663,7 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- static int snd_myctl_info(struct snd_kcontrol *kcontrol,
+ static int snd_myctl_enum_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
static char *texts[4] = {
@@ -3658,6 +3682,16 @@ struct _snd_pcm_runtime {
</programlisting>
</informalexample>
</para>
+
+ <para>
+ Some common info callbacks are prepared for easy use:
+ <function>snd_ctl_boolean_mono_info()</function> and
+ <function>snd_ctl_boolean_stereo_info()</function>.
+ Obviously, the former is an info callback for a mono channel
+ boolean item, just like <function>snd_myctl_mono_info</function>
+ above, and the latter is for a stereo channel boolean item.
+ </para>
+
</section>
<section id="control-interface-callbacks-get">
@@ -3794,7 +3828,8 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- if ((err = snd_ctl_add(card, snd_ctl_new1(&my_control, chip))) < 0)
+ err = snd_ctl_add(card, snd_ctl_new1(&my_control, chip));
+ if (err < 0)
return err;
]]>
</programlisting>
@@ -3843,6 +3878,56 @@ struct _snd_pcm_runtime {
</para>
</section>
+ <section id="control-interface-tlv">
+ <title>Metadata</title>
+ <para>
+ To provide information about the dB values of a mixer control, use
+ on of the <constant>DECLARE_TLV_xxx</constant> macros from
+ <filename>&lt;sound/tlv.h&gt;</filename> to define a variable
+ containing this information, set the<structfield>tlv.p
+ </structfield> field to point to this variable, and include the
+ <constant>SNDRV_CTL_ELEM_ACCESS_TLV_READ</constant> flag in the
+ <structfield>access</structfield> field; like this:
+ <informalexample>
+ <programlisting>
+<![CDATA[
+ static DECLARE_TLV_DB_SCALE(db_scale_my_control, -4050, 150, 0);
+
+ static struct snd_kcontrol_new my_control __devinitdata = {
+ ...
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+ ...
+ .tlv.p = db_scale_my_control,
+ };
+]]>
+ </programlisting>
+ </informalexample>
+ </para>
+
+ <para>
+ The <function>DECLARE_TLV_DB_SCALE</function> macro defines
+ information about a mixer control where each step in the control's
+ value changes the dB value by a constant dB amount.
+ The first parameter is the name of the variable to be defined.
+ The second parameter is the minimum value, in units of 0.01 dB.
+ The third parameter is the step size, in units of 0.01 dB.
+ Set the fourth parameter to 1 if the minimum value actually mutes
+ the control.
+ </para>
+
+ <para>
+ The <function>DECLARE_TLV_DB_LINEAR</function> macro defines
+ information about a mixer control where the control's value affects
+ the output linearly.
+ The first parameter is the name of the variable to be defined.
+ The second parameter is the minimum value, in units of 0.01 dB.
+ The third parameter is the maximum value, in units of 0.01 dB.
+ If the minimum value mutes the control, set the second parameter to
+ <constant>TLV_DB_GAIN_MUTE</constant>.
+ </para>
+ </section>
+
</chapter>
@@ -3880,7 +3965,7 @@ struct _snd_pcm_runtime {
{
struct mychip *chip = ac97->private_data;
....
- // read a register value here from the codec
+ /* read a register value here from the codec */
return the_register_value;
}
@@ -3889,7 +3974,7 @@ struct _snd_pcm_runtime {
{
struct mychip *chip = ac97->private_data;
....
- // write the given register value to the codec
+ /* write the given register value to the codec */
}
static int snd_mychip_ac97(struct mychip *chip)
@@ -3902,7 +3987,8 @@ struct _snd_pcm_runtime {
.read = snd_mychip_ac97_read,
};
- if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &bus)) < 0)
+ err = snd_ac97_bus(chip->card, 0, &ops, NULL, &bus);
+ if (err < 0)
return err;
memset(&ac97, 0, sizeof(ac97));
ac97.private_data = chip;
@@ -4447,10 +4533,10 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- struct list_head *list;
struct snd_rawmidi_substream *substream;
- list_for_each(list, &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams) {
- substream = list_entry(list, struct snd_rawmidi_substream, list);
+ list_for_each_entry(substream,
+ &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams,
+ list {
sprintf(substream->name, "My MIDI Port %d", substream->number + 1);
}
/* same for SNDRV_RAWMIDI_STREAM_INPUT */
diff --git a/Documentation/sound/alsa/OSS-Emulation.txt b/Documentation/sound/alsa/OSS-Emulation.txt
index bfa0c9aacb4b..022aaeb0e9dd 100644
--- a/Documentation/sound/alsa/OSS-Emulation.txt
+++ b/Documentation/sound/alsa/OSS-Emulation.txt
@@ -303,10 +303,3 @@ ICE1712 supports only the unconventional format, interleaved
the buffer as the conventional (mono or 2-channels, 8 or 16bit) format
on OSS.
-USB devices
------------
-Some USB devices support only 24bit format packed in 3bytes. This
-format is not supported by OSS and no conversion is provided by kernel
-OSS emulation. You can use the user-space OSS emulation via libaoss
-instead.
-
diff --git a/Documentation/sound/alsa/hda_codec.txt b/Documentation/sound/alsa/hda_codec.txt
index 4eaae2a45534..8e1b02526698 100644
--- a/Documentation/sound/alsa/hda_codec.txt
+++ b/Documentation/sound/alsa/hda_codec.txt
@@ -49,6 +49,9 @@ struct hda_bus_ops {
unsigned int verb, unsigned int parm);
unsigned int (*get_response)(struct hda_codec *codec);
void (*private_free)(struct hda_bus *);
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ void (*pm_notify)(struct hda_codec *codec);
+#endif
};
The command callback is called when the codec module needs to send a
@@ -56,9 +59,16 @@ VERB to the controller. It's always a single command.
The get_response callback is called when the codec requires the answer
for the last command. These two callbacks are mandatory and have to
be given.
-The last, private_free callback, is optional. It's called in the
+The third, private_free callback, is optional. It's called in the
destructor to release any necessary data in the lowlevel driver.
+The pm_notify callback is available only with
+CONFIG_SND_HDA_POWER_SAVE kconfig. It's called when the codec needs
+to power up or may power down. The controller should check the all
+belonging codecs on the bus whether they are actually powered off
+(check codec->power_on), and optionally the driver may power down the
+contoller side, too.
+
The bus instance is created via snd_hda_bus_new(). You need to pass
the card instance, the template, and the pointer to store the
resultant bus instance.
@@ -86,10 +96,8 @@ resultant codec instance (can be NULL if not needed).
The codec is stored in a linked list of bus instance. You can follow
the codec list like:
- struct list_head *p;
struct hda_codec *codec;
- list_for_each(p, &bus->codec_list) {
- codec = list_entry(p, struct hda_codec, list);
+ list_for_each_entry(codec, &bus->codec_list, list) {
...
}
@@ -100,10 +108,15 @@ initialization sequence is called when the controls are built later.
Codec Access
============
-To access codec, use snd_codec_read() and snd_codec_write().
+To access codec, use snd_hda_codec_read() and snd_hda_codec_write().
snd_hda_param_read() is for reading parameters.
For writing a sequence of verbs, use snd_hda_sequence_write().
+There are variants of cached read/write, snd_hda_codec_write_cache(),
+snd_hda_sequence_write_cache(). These are used for recording the
+register states for the power-mangement resume. When no PM is needed,
+these are equivalent with non-cached version.
+
To retrieve the number of sub nodes connected to the given node, use
snd_hda_get_sub_nodes(). The connection list can be obtained via
snd_hda_get_connections() call.
@@ -239,6 +252,10 @@ set the codec->patch_ops field. This is defined as below:
int (*suspend)(struct hda_codec *codec, pm_message_t state);
int (*resume)(struct hda_codec *codec);
#endif
+ #ifdef CONFIG_SND_HDA_POWER_SAVE
+ int (*check_power_status)(struct hda_codec *codec,
+ hda_nid_t nid);
+ #endif
};
The build_controls callback is called from snd_hda_build_controls().
@@ -251,6 +268,18 @@ The unsol_event callback is called when an unsolicited event is
received.
The suspend and resume callbacks are for power management.
+They can be NULL if no special sequence is required. When the resume
+callback is NULL, the driver calls the init callback and resumes the
+registers from the cache. If other handling is needed, you'd need to
+write your own resume callback. There, the amp values can be resumed
+via
+ void snd_hda_codec_resume_amp(struct hda_codec *codec);
+and the other codec registers via
+ void snd_hda_codec_resume_cache(struct hda_codec *codec);
+
+The check_power_status callback is called when the amp value of the
+given widget NID is changed. The codec code can turn on/off the power
+appropriately from this information.
Each entry can be NULL if not necessary to be called.
@@ -267,8 +296,7 @@ Digital I/O
===========
Call snd_hda_create_spdif_out_ctls() from the patch to create controls
-related with SPDIF out. In the patch resume callback, call
-snd_hda_resume_spdif().
+related with SPDIF out.
Helper Functions
@@ -284,12 +312,7 @@ as a module parameter, and PCI subsystem IDs. If the matching entry
is found, it returns the config field value.
snd_hda_add_new_ctls() can be used to create and add control entries.
-Pass the zero-terminated array of struct snd_kcontrol_new. The same array
-can be passed to snd_hda_resume_ctls() for resume.
-Note that this will call control->put callback of these entries. So,
-put callback should check codec->in_resume and force to restore the
-given value if it's non-zero even if the value is identical with the
-cached value.
+Pass the zero-terminated array of struct snd_kcontrol_new
Macros HDA_CODEC_VOLUME(), HDA_CODEC_MUTE() and their variables can be
used for the entry of struct snd_kcontrol_new.
diff --git a/Documentation/sound/alsa/powersave.txt b/Documentation/sound/alsa/powersave.txt
new file mode 100644
index 000000000000..9657e8099228
--- /dev/null
+++ b/Documentation/sound/alsa/powersave.txt
@@ -0,0 +1,41 @@
+Notes on Power-Saving Mode
+==========================
+
+AC97 and HD-audio drivers have the automatic power-saving mode.
+This feature is enabled via Kconfig CONFIG_SND_AC97_POWER_SAVE
+and CONFIG_SND_HDA_POWER_SAVE options, respectively.
+
+With the automatic power-saving, the driver turns off the codec power
+appropriately when no operation is required. When no applications use
+the device and/or no analog loopback is set, the power disablement is
+done fully or partially. It'll save a certain power consumption, thus
+good for laptops (even for desktops).
+
+The time-out for automatic power-off can be specified via power_save
+module option of snd-ac97-codec and snd-hda-intel modules. Specify
+the time-out value in seconds. 0 means to disable the automatic
+power-saving. The default value of timeout is given via
+CONFIG_SND_AC97_POWER_SAVE_DEFAULT and
+CONFIG_SND_HDA_POWER_SAVE_DEFAULT Kconfig options. Setting this to 1
+(the minimum value) isn't recommended because many applications try to
+reopen the device frequently. 10 would be a good choice for normal
+operations.
+
+The power_save option is exported as writable. This means you can
+adjust the value via sysfs on the fly. For example, to turn on the
+automatic power-save mode with 10 seconds, write to
+/sys/modules/snd_ac97_codec/parameters/power_save (usually as root):
+
+ # echo 10 > /sys/modules/snd_ac97_codec/parameters/power_save
+
+
+Note that you might hear click noise/pop when changing the power
+state. Also, it often takes certain time to wake up from the
+power-down to the active state. These are often hardly to fix, so
+don't report extra bug reports unless you have a fix patch ;-)
+
+For HD-audio interface, there is another module option,
+power_save_controller. This enables/disables the power-save mode of
+the controller side. Setting this on may reduce a bit more power
+consumption, but might result in longer wake-up time and click noise.
+Try to turn it off when you experience such a thing too often.
diff --git a/Documentation/sound/alsa/soc/DAI.txt b/Documentation/sound/alsa/soc/DAI.txt
index 58cbfd01ea8f..3feeb9ecdec4 100644
--- a/Documentation/sound/alsa/soc/DAI.txt
+++ b/Documentation/sound/alsa/soc/DAI.txt
@@ -20,12 +20,12 @@ I2S
===
I2S is a common 4 wire DAI used in HiFi, STB and portable devices. The Tx and
-Rx lines are used for audio transmision, whilst the bit clock (BCLK) and
+Rx lines are used for audio transmission, whilst the bit clock (BCLK) and
left/right clock (LRC) synchronise the link. I2S is flexible in that either the
controller or CODEC can drive (master) the BCLK and LRC clock lines. Bit clock
usually varies depending on the sample rate and the master system clock
(SYSCLK). LRCLK is the same as the sample rate. A few devices support separate
-ADC and DAC LRCLK's, this allows for similtanious capture and playback at
+ADC and DAC LRCLK's, this allows for simultaneous capture and playback at
different sample rates.
I2S has several different operating modes:-
@@ -41,12 +41,12 @@ I2S has several different operating modes:-
PCM
===
-PCM is another 4 wire interface, very similar to I2S, that can support a more
+PCM is another 4 wire interface, very similar to I2S, which can support a more
flexible protocol. It has bit clock (BCLK) and sync (SYNC) lines that are used
to synchronise the link whilst the Tx and Rx lines are used to transmit and
receive the audio data. Bit clock usually varies depending on sample rate
whilst sync runs at the sample rate. PCM also supports Time Division
-Multiplexing (TDM) in that several devices can use the bus similtaniuosly (This
+Multiplexing (TDM) in that several devices can use the bus simultaneously (this
is sometimes referred to as network mode).
Common PCM operating modes:-
diff --git a/Documentation/sound/alsa/soc/clocking.txt b/Documentation/sound/alsa/soc/clocking.txt
index e93960d53a1e..14930887c25f 100644
--- a/Documentation/sound/alsa/soc/clocking.txt
+++ b/Documentation/sound/alsa/soc/clocking.txt
@@ -2,20 +2,20 @@ Audio Clocking
==============
This text describes the audio clocking terms in ASoC and digital audio in
-general. Note: Audio clocking can be complex !
+general. Note: Audio clocking can be complex!
Master Clock
------------
-Every audio subsystem is driven by a master clock (sometimes refered to as MCLK
+Every audio subsystem is driven by a master clock (sometimes referred to as MCLK
or SYSCLK). This audio master clock can be derived from a number of sources
(e.g. crystal, PLL, CPU clock) and is responsible for producing the correct
audio playback and capture sample rates.
-Some master clocks (e.g. PLL's and CPU based clocks) are configuarble in that
+Some master clocks (e.g. PLL's and CPU based clocks) are configurable in that
their speed can be altered by software (depending on the system use and to save
-power). Other master clocks are fixed at at set frequency (i.e. crystals).
+power). Other master clocks are fixed at a set frequency (i.e. crystals).
DAI Clocks
@@ -44,7 +44,7 @@ This relationship depends on the codec or SoC CPU in particular. In general
it's best to configure BCLK to the lowest possible speed (depending on your
rate, number of channels and wordsize) to save on power.
-It's also desireable to use the codec (if possible) to drive (or master) the
+It's also desirable to use the codec (if possible) to drive (or master) the
audio clocks as it's usually gives more accurate sample rates than the CPU.
diff --git a/Documentation/sound/alsa/soc/codec.txt b/Documentation/sound/alsa/soc/codec.txt
index 48983c75aad9..1e766ad0ebd1 100644
--- a/Documentation/sound/alsa/soc/codec.txt
+++ b/Documentation/sound/alsa/soc/codec.txt
@@ -19,7 +19,7 @@ Optionally, codec drivers can also provide:-
6) DAPM event handler.
7) DAC Digital mute control.
-It's probably best to use this guide in conjuction with the existing codec
+It's probably best to use this guide in conjunction with the existing codec
driver code in sound/soc/codecs/
ASoC Codec driver breakdown
@@ -28,7 +28,7 @@ ASoC Codec driver breakdown
1 - Codec DAI and PCM configuration
-----------------------------------
Each codec driver must have a struct snd_soc_codec_dai to define it's DAI and
-PCM's capablities and operations. This struct is exported so that it can be
+PCM's capabilities and operations. This struct is exported so that it can be
registered with the core by your machine driver.
e.g.
@@ -67,7 +67,7 @@ EXPORT_SYMBOL_GPL(wm8731_dai);
2 - Codec control IO
--------------------
-The codec can ususally be controlled via an I2C or SPI style interface (AC97
+The codec can usually be controlled via an I2C or SPI style interface (AC97
combines control with data in the DAI). The codec drivers will have to provide
functions to read and write the codec registers along with supplying a register
cache:-
diff --git a/Documentation/sound/alsa/soc/dapm.txt b/Documentation/sound/alsa/soc/dapm.txt
index c11877f5b4a1..ab0766fd7869 100644
--- a/Documentation/sound/alsa/soc/dapm.txt
+++ b/Documentation/sound/alsa/soc/dapm.txt
@@ -11,7 +11,7 @@ other PM systems.
DAPM is also completely transparent to all user space applications as all power
switching is done within the ASoC core. No code changes or recompiling are
-required for user space applications. DAPM makes power switching descisions based
+required for user space applications. DAPM makes power switching decisions based
upon any audio stream (capture/playback) activity and audio mixer settings
within the device.
@@ -38,7 +38,7 @@ There are 4 power domains within DAPM
Enabled and disabled when stream playback/capture is started and
stopped respectively. e.g. aplay, arecord.
-All DAPM power switching descisons are made automatically by consulting an audio
+All DAPM power switching decisions are made automatically by consulting an audio
routing map of the whole machine. This map is specific to each machine and
consists of the interconnections between every audio component (including
internal codec components). All audio components that effect power are called
diff --git a/Documentation/sound/alsa/soc/overview.txt b/Documentation/sound/alsa/soc/overview.txt
index 753c5cc5984a..c47ce9530677 100644
--- a/Documentation/sound/alsa/soc/overview.txt
+++ b/Documentation/sound/alsa/soc/overview.txt
@@ -2,18 +2,19 @@ ALSA SoC Layer
==============
The overall project goal of the ALSA System on Chip (ASoC) layer is to provide
-better ALSA support for embedded system on chip procesors (e.g. pxa2xx, au1x00,
+better ALSA support for embedded system-on-chip processors (e.g. pxa2xx, au1x00,
iMX, etc) and portable audio codecs. Currently there is some support in the
kernel for SoC audio, however it has some limitations:-
* Currently, codec drivers are often tightly coupled to the underlying SoC
- cpu. This is not ideal and leads to code duplication i.e. Linux now has 4
+ CPU. This is not ideal and leads to code duplication i.e. Linux now has 4
different wm8731 drivers for 4 different SoC platforms.
- * There is no standard method to signal user initiated audio events.
- e.g. Headphone/Mic insertion, Headphone/Mic detection after an insertion
- event. These are quite common events on portable devices and ofter require
- machine specific code to re route audio, enable amps etc after such an event.
+ * There is no standard method to signal user initiated audio events (e.g.
+ Headphone/Mic insertion, Headphone/Mic detection after an insertion
+ event). These are quite common events on portable devices and often require
+ machine specific code to re-route audio, enable amps, etc., after such an
+ event.
* Current drivers tend to power up the entire codec when playing
(or recording) audio. This is fine for a PC, but tends to waste a lot of
@@ -44,7 +45,7 @@ features :-
signals the codec when to change power states.
* Machine specific controls: Allow machines to add controls to the sound card
- e.g. volume control for speaker amp.
+ (e.g. volume control for speaker amp).
To achieve all this, ASoC basically splits an embedded audio system into 3
components :-
@@ -57,7 +58,7 @@ components :-
interface drivers (e.g. I2S, AC97, PCM) for that platform.
* Machine driver: The machine driver handles any machine specific controls and
- audio events. i.e. turing on an amp at start of playback.
+ audio events (e.g. turning on an amp at start of playback).
Documentation
diff --git a/Documentation/sound/alsa/soc/platform.txt b/Documentation/sound/alsa/soc/platform.txt
index e95b16d5a53b..d4678b4dc6c6 100644
--- a/Documentation/sound/alsa/soc/platform.txt
+++ b/Documentation/sound/alsa/soc/platform.txt
@@ -20,7 +20,7 @@ struct snd_soc_ops {
int (*trigger)(struct snd_pcm_substream *, int);
};
-The platform driver exports it's DMA functionailty via struct snd_soc_platform:-
+The platform driver exports its DMA functionality via struct snd_soc_platform:-
struct snd_soc_platform {
char *name;
diff --git a/Documentation/sound/alsa/soc/pops_clicks.txt b/Documentation/sound/alsa/soc/pops_clicks.txt
index 2cf7ee5b3d74..3371bd9d7cfa 100644
--- a/Documentation/sound/alsa/soc/pops_clicks.txt
+++ b/Documentation/sound/alsa/soc/pops_clicks.txt
@@ -2,7 +2,7 @@ Audio Pops and Clicks
=====================
Pops and clicks are unwanted audio artifacts caused by the powering up and down
-of components within the audio subsystem. This is noticable on PC's when an
+of components within the audio subsystem. This is noticeable on PCs when an
audio module is either loaded or unloaded (at module load time the sound card is
powered up and causes a popping noise on the speakers).
@@ -16,7 +16,7 @@ Minimising Playback Pops and Clicks
===================================
Playback pops in portable audio subsystems cannot be completely eliminated atm,
-however future audio codec hardware will have better pop and click supression.
+however future audio codec hardware will have better pop and click suppression.
Pops can be reduced within playback by powering the audio components in a
specific order. This order is different for startup and shutdown and follows
some basic rules:-
@@ -33,7 +33,7 @@ Minimising Capture Pops and Clicks
==================================
Capture artifacts are somewhat easier to get rid as we can delay activating the
-ADC until all the pops have occured. This follows similar power rules to
+ADC until all the pops have occurred. This follows similar power rules to
playback in that components are powered in a sequence depending upon stream
startup or shutdown.
diff --git a/Documentation/sound/oss/es1371 b/Documentation/sound/oss/es1371
deleted file mode 100644
index c3151266771c..000000000000
--- a/Documentation/sound/oss/es1371
+++ /dev/null
@@ -1,64 +0,0 @@
-/proc/sound, /dev/sndstat
--------------------------
-
-/proc/sound and /dev/sndstat is not supported by the
-driver. To find out whether the driver succeeded loading,
-check the kernel log (dmesg).
-
-
-ALaw/uLaw sample formats
-------------------------
-
-This driver does not support the ALaw/uLaw sample formats.
-ALaw is the default mode when opening a sound device
-using OSS/Free. The reason for the lack of support is
-that the hardware does not support these formats, and adding
-conversion routines to the kernel would lead to very ugly
-code in the presence of the mmap interface to the driver.
-And since xquake uses mmap, mmap is considered important :-)
-and no sane application uses ALaw/uLaw these days anyway.
-In short, playing a Sun .au file as follows:
-
-cat my_file.au > /dev/dsp
-
-does not work. Instead, you may use the play script from
-Chris Bagwell's sox-12.14 package (available from the URL
-below) to play many different audio file formats.
-The script automatically determines the audio format
-and does do audio conversions if necessary.
-http://home.sprynet.com/sprynet/cbagwell/projects.html
-
-
-Blocking vs. nonblocking IO
----------------------------
-
-Unlike OSS/Free this driver honours the O_NONBLOCK file flag
-not only during open, but also during read and write.
-This is an effort to make the sound driver interface more
-regular. Timidity has problems with this; a patch
-is available from http://www.ife.ee.ethz.ch/~sailer/linux/pciaudio.html.
-(Timidity patched will also run on OSS/Free).
-
-
-MIDI UART
----------
-
-The driver supports a simple MIDI UART interface, with
-no ioctl's supported.
-
-
-MIDI synthesizer
-----------------
-
-This soundcard does not have any hardware MIDI synthesizer;
-MIDI synthesis has to be done in software. To allow this
-the driver/soundcard supports two PCM (/dev/dsp) interfaces.
-
-There is a freely available software package that allows
-MIDI file playback on this soundcard called Timidity.
-See http://www.cgs.fi/~tt/timidity/.
-
-
-
-Thomas Sailer
-t.sailer@alumni.ethz.ch
diff --git a/Documentation/spi/pxa2xx b/Documentation/spi/pxa2xx
index 215e3b8e7266..f3853cc37bde 100644
--- a/Documentation/spi/pxa2xx
+++ b/Documentation/spi/pxa2xx
@@ -1,4 +1,4 @@
-PXA2xx SPI on SSP driver HOWTO
+PXA2xx SPI on SSP driver HOWTO
===================================================
This a mini howto on the pxa2xx_spi driver. The driver turns a PXA2xx
synchronous serial port into a SPI master controller
diff --git a/Documentation/spi/spi-summary b/Documentation/spi/spi-summary
index 76ea6c837be5..8861e47e5a2d 100644
--- a/Documentation/spi/spi-summary
+++ b/Documentation/spi/spi-summary
@@ -156,21 +156,29 @@ using the driver model to connect controller and protocol drivers using
device tables provided by board specific initialization code. SPI
shows up in sysfs in several locations:
+ /sys/devices/.../CTLR ... physical node for a given SPI controller
+
/sys/devices/.../CTLR/spiB.C ... spi_device on bus "B",
chipselect C, accessed through CTLR.
+ /sys/bus/spi/devices/spiB.C ... symlink to that physical
+ .../CTLR/spiB.C device
+
/sys/devices/.../CTLR/spiB.C/modalias ... identifies the driver
that should be used with this device (for hotplug/coldplug)
- /sys/bus/spi/devices/spiB.C ... symlink to the physical
- spiB.C device
-
/sys/bus/spi/drivers/D ... driver for one or more spi*.* devices
- /sys/class/spi_master/spiB ... class device for the controller
- managing bus "B". All the spiB.* devices share the same
+ /sys/class/spi_master/spiB ... symlink (or actual device node) to
+ a logical node which could hold class related state for the
+ controller managing bus "B". All spiB.* devices share one
physical SPI bus segment, with SCLK, MOSI, and MISO.
+Note that the actual location of the controller's class state depends
+on whether you enabled CONFIG_SYSFS_DEPRECATED or not. At this time,
+the only class-specific state is the bus number ("B" in "spiB"), so
+those /sys/class entries are only useful to quickly identify busses.
+
How does board-specific init code declare SPI devices?
------------------------------------------------------
@@ -337,7 +345,8 @@ SPI protocol drivers somewhat resemble platform device drivers:
The driver core will autmatically attempt to bind this driver to any SPI
device whose board_info gave a modalias of "CHIP". Your probe() code
-might look like this unless you're creating a class_device:
+might look like this unless you're creating a device which is managing
+a bus (appearing under /sys/class/spi_master).
static int __devinit CHIP_probe(struct spi_device *spi)
{
@@ -442,7 +451,7 @@ An SPI controller will probably be registered on the platform_bus; write
a driver to bind to the device, whichever bus is involved.
The main task of this type of driver is to provide an "spi_master".
-Use spi_alloc_master() to allocate the master, and class_get_devdata()
+Use spi_alloc_master() to allocate the master, and spi_master_get_devdata()
to get the driver-private data allocated for that device.
struct spi_master *master;
@@ -452,7 +461,7 @@ to get the driver-private data allocated for that device.
if (!master)
return -ENODEV;
- c = class_get_devdata(&master->cdev);
+ c = spi_master_get_devdata(master);
The driver will initialize the fields of that spi_master, including the
bus number (maybe the same as the platform device ID) and three methods
diff --git a/Documentation/spi/spidev_test.c b/Documentation/spi/spidev_test.c
index 218e86215297..cf0e3ce0d526 100644
--- a/Documentation/spi/spidev_test.c
+++ b/Documentation/spi/spidev_test.c
@@ -29,7 +29,7 @@ static void pabort(const char *s)
abort();
}
-static char *device = "/dev/spidev1.1";
+static const char *device = "/dev/spidev1.1";
static uint8_t mode;
static uint8_t bits = 8;
static uint32_t speed = 500000;
@@ -69,7 +69,7 @@ static void transfer(int fd)
puts("");
}
-void print_usage(char *prog)
+void print_usage(const char *prog)
{
printf("Usage: %s [-DsbdlHOLC3]\n", prog);
puts(" -D --device device to use (default /dev/spidev1.1)\n"
@@ -88,7 +88,7 @@ void print_usage(char *prog)
void parse_opts(int argc, char *argv[])
{
while (1) {
- static struct option lopts[] = {
+ static const struct option lopts[] = {
{ "device", 1, 0, 'D' },
{ "speed", 1, 0, 's' },
{ "delay", 1, 0, 'd' },
diff --git a/Documentation/sysctl/00-INDEX b/Documentation/sysctl/00-INDEX
new file mode 100644
index 000000000000..a20a9066dc4c
--- /dev/null
+++ b/Documentation/sysctl/00-INDEX
@@ -0,0 +1,16 @@
+00-INDEX
+ - this file.
+README
+ - general information about /proc/sys/ sysctl files.
+abi.txt
+ - documentation for /proc/sys/abi/*.
+ctl_unnumbered.txt
+ - explanation of why one should not add new binary sysctl numbers.
+fs.txt
+ - documentation for /proc/sys/fs/*.
+kernel.txt
+ - documentation for /proc/sys/kernel/*.
+sunrpc.txt
+ - documentation for /proc/sys/sunrpc/*.
+vm.txt
+ - documentation for /proc/sys/vm/*.
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index 111fd28727ec..8984a5396271 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -320,6 +320,14 @@ kernel. This value defaults to SHMMAX.
==============================================================
+softlockup_thresh:
+
+This value can be used to lower the softlockup tolerance
+threshold. The default threshold is 10s. If a cpu is locked up
+for 10s, the kernel complains. Valid values are 1-60s.
+
+==============================================================
+
tainted:
Non-zero if the kernel has been tainted. Numeric values, which
diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt
index a0ccc5b60260..b89570c30434 100644
--- a/Documentation/sysctl/vm.txt
+++ b/Documentation/sysctl/vm.txt
@@ -31,6 +31,7 @@ Currently, these files are in /proc/sys/vm:
- min_unmapped_ratio
- min_slab_ratio
- panic_on_oom
+- oom_kill_allocating_task
- mmap_min_address
- numa_zonelist_order
@@ -111,6 +112,12 @@ of kilobytes free. The VM uses this number to compute a pages_min
value for each lowmem zone in the system. Each lowmem zone gets
a number of reserved free pages based proportionally on its size.
+Some minimal ammount of memory is needed to satisfy PF_MEMALLOC
+allocations; if you set this to lower than 1024KB, your system will
+become subtly broken, and prone to deadlock under high loads.
+
+Setting this too high will OOM your machine instantly.
+
==============================================================
percpu_pagelist_fraction
@@ -220,6 +227,27 @@ The default value is 0.
1 and 2 are for failover of clustering. Please select either
according to your policy of failover.
+=============================================================
+
+oom_kill_allocating_task
+
+This enables or disables killing the OOM-triggering task in
+out-of-memory situations.
+
+If this is set to zero, the OOM killer will scan through the entire
+tasklist and select a task based on heuristics to kill. This normally
+selects a rogue memory-hogging task that frees up a large amount of
+memory when killed.
+
+If this is set to non-zero, the OOM killer simply kills the task that
+triggered the out-of-memory condition. This avoids the expensive
+tasklist scan.
+
+If panic_on_oom is selected, it takes precedence over whatever value
+is used in oom_kill_allocating_task.
+
+The default value is 0.
+
==============================================================
mmap_min_addr
diff --git a/Documentation/telephony/00-INDEX b/Documentation/telephony/00-INDEX
new file mode 100644
index 000000000000..4ffe0ed5b6fb
--- /dev/null
+++ b/Documentation/telephony/00-INDEX
@@ -0,0 +1,4 @@
+00-INDEX
+ - this file.
+ixj.txt
+ - document describing the Quicknet drivers.
diff --git a/Documentation/thinkpad-acpi.txt b/Documentation/thinkpad-acpi.txt
index 60953d6c919d..ec499265deca 100644
--- a/Documentation/thinkpad-acpi.txt
+++ b/Documentation/thinkpad-acpi.txt
@@ -105,10 +105,15 @@ The version of thinkpad-acpi's sysfs interface is exported by the driver
as a driver attribute (see below).
Sysfs driver attributes are on the driver's sysfs attribute space,
-for 2.6.20 this is /sys/bus/platform/drivers/thinkpad_acpi/.
+for 2.6.23 this is /sys/bus/platform/drivers/thinkpad_acpi/ and
+/sys/bus/platform/drivers/thinkpad_hwmon/
-Sysfs device attributes are on the driver's sysfs attribute space,
-for 2.6.20 this is /sys/devices/platform/thinkpad_acpi/.
+Sysfs device attributes are on the thinkpad_acpi device sysfs attribute
+space, for 2.6.23 this is /sys/devices/platform/thinkpad_acpi/.
+
+Sysfs device attributes for the sensors and fan are on the
+thinkpad_hwmon device's sysfs attribute space, but you should locate it
+looking for a hwmon device with the name attribute of "thinkpad".
Driver version
--------------
@@ -766,7 +771,7 @@ Temperature sensors
-------------------
procfs: /proc/acpi/ibm/thermal
-sysfs device attributes: (hwmon) temp*_input
+sysfs device attributes: (hwmon "thinkpad") temp*_input
Most ThinkPads include six or more separate temperature sensors but only
expose the CPU temperature through the standard ACPI methods. This
@@ -989,7 +994,9 @@ Fan control and monitoring: fan speed, fan enable/disable
---------------------------------------------------------
procfs: /proc/acpi/ibm/fan
-sysfs device attributes: (hwmon) fan_input, pwm1, pwm1_enable
+sysfs device attributes: (hwmon "thinkpad") fan1_input, pwm1,
+ pwm1_enable
+sysfs hwmon driver attributes: fan_watchdog
NOTE NOTE NOTE: fan control operations are disabled by default for
safety reasons. To enable them, the module parameter "fan_control=1"
@@ -1028,7 +1035,7 @@ enable it if necessary to avoid overheating.
An enabled fan in level "auto" may stop spinning if the EC decides the
ThinkPad is cool enough and doesn't need the extra airflow. This is
-normal, and the EC will spin the fan up if the varios thermal readings
+normal, and the EC will spin the fan up if the various thermal readings
rise too much.
On the X40, this seems to depend on the CPU and HDD temperatures.
@@ -1131,7 +1138,7 @@ hwmon device attribute fan1_input:
which can take up to two minutes. May return rubbish on older
ThinkPads.
-driver attribute fan_watchdog:
+hwmon driver attribute fan_watchdog:
Fan safety watchdog timer interval, in seconds. Minimum is
1 second, maximum is 120 seconds. 0 disables the watchdog.
@@ -1196,7 +1203,7 @@ for example:
Enabling debugging output
-------------------------
-The module takes a debug paramater which can be used to selectively
+The module takes a debug parameter which can be used to selectively
enable various classes of debugging output, for example:
modprobe ibm_acpi debug=0xffff
@@ -1233,3 +1240,9 @@ Sysfs interface changelog:
layer, the radio switch generates input event EV_RADIO,
and the driver enables hot key handling by default in
the firmware.
+
+0x020000: ABI fix: added a separate hwmon platform device and
+ driver, which must be located by name (thinkpad)
+ and the hwmon class for libsensors4 (lm-sensors 3)
+ compatibility. Moved all hwmon attributes to this
+ new platform device.
diff --git a/Documentation/usb/usb-serial.txt b/Documentation/usb/usb-serial.txt
index 4e0b62b8566f..8b077e43eee7 100644
--- a/Documentation/usb/usb-serial.txt
+++ b/Documentation/usb/usb-serial.txt
@@ -338,7 +338,7 @@ MCT USB Single Port Serial Adapter U232
This driver is for the MCT USB-RS232 Converter (25 pin, Model No.
U232-P25) from Magic Control Technology Corp. (there is also a 9 pin
Model No. U232-P9). More information about this device can be found at
- the manufacture's web-site: http://www.mct.com.tw.
+ the manufacturer's web-site: http://www.mct.com.tw.
The driver is generally working, though it still needs some more testing.
It is derived from the Belkin USB Serial Adapter F5U103 driver and its
diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx
index a3026689bbe6..37f0e3cedf43 100644
--- a/Documentation/video4linux/CARDLIST.em28xx
+++ b/Documentation/video4linux/CARDLIST.em28xx
@@ -8,4 +8,7 @@
7 -> Leadtek Winfast USB II (em2800)
8 -> Kworld USB2800 (em2800)
9 -> Pinnacle Dazzle DVC 90 (em2820/em2840) [2304:0207]
+ 10 -> Hauppauge WinTV HVR 900 (em2880)
+ 11 -> Terratec Hybrid XS (em2880)
12 -> Kworld PVR TV 2800 RF (em2820/em2840)
+ 13 -> Terratec Prodigy XS (em2880)
diff --git a/Documentation/vm/00-INDEX b/Documentation/vm/00-INDEX
new file mode 100644
index 000000000000..2131b00b63f6
--- /dev/null
+++ b/Documentation/vm/00-INDEX
@@ -0,0 +1,20 @@
+00-INDEX
+ - this file.
+balance
+ - various information on memory balancing.
+hugetlbpage.txt
+ - a brief summary of hugetlbpage support in the Linux kernel.
+locking
+ - info on how locking and synchronization is done in the Linux vm code.
+numa
+ - information about NUMA specific code in the Linux vm.
+numa_memory_policy.txt
+ - documentation of concepts and APIs of the 2.6 memory policy support.
+overcommit-accounting
+ - description of the Linux kernels overcommit handling modes.
+page_migration
+ - description of page migration in NUMA systems.
+slabinfo.c
+ - source code for a tool to get reports about slabs.
+slub.txt
+ - a short users guide for SLUB.
diff --git a/Documentation/vm/numa_memory_policy.txt b/Documentation/vm/numa_memory_policy.txt
index 8242f52d0f22..dd4986497996 100644
--- a/Documentation/vm/numa_memory_policy.txt
+++ b/Documentation/vm/numa_memory_policy.txt
@@ -302,31 +302,30 @@ MEMORY POLICIES AND CPUSETS
Memory policies work within cpusets as described above. For memory policies
that require a node or set of nodes, the nodes are restricted to the set of
-nodes whose memories are allowed by the cpuset constraints. If the
-intersection of the set of nodes specified for the policy and the set of nodes
-allowed by the cpuset is the empty set, the policy is considered invalid and
-cannot be installed.
+nodes whose memories are allowed by the cpuset constraints. If the nodemask
+specified for the policy contains nodes that are not allowed by the cpuset, or
+the intersection of the set of nodes specified for the policy and the set of
+nodes with memory is the empty set, the policy is considered invalid
+and cannot be installed.
The interaction of memory policies and cpusets can be problematic for a
couple of reasons:
-1) the memory policy APIs take physical node id's as arguments. However, the
- memory policy APIs do not provide a way to determine what nodes are valid
- in the context where the application is running. An application MAY consult
- the cpuset file system [directly or via an out of tree, and not generally
- available, libcpuset API] to obtain this information, but then the
- application must be aware that it is running in a cpuset and use what are
- intended primarily as administrative APIs.
-
- However, as long as the policy specifies at least one node that is valid
- in the controlling cpuset, the policy can be used.
+1) the memory policy APIs take physical node id's as arguments. As mentioned
+ above, it is illegal to specify nodes that are not allowed in the cpuset.
+ The application must query the allowed nodes using the get_mempolicy()
+ API with the MPOL_F_MEMS_ALLOWED flag to determine the allowed nodes and
+ restrict itself to those nodes. However, the resources available to a
+ cpuset can be changed by the system administrator, or a workload manager
+ application, at any time. So, a task may still get errors attempting to
+ specify policy nodes, and must query the allowed memories again.
2) when tasks in two cpusets share access to a memory region, such as shared
memory segments created by shmget() of mmap() with the MAP_ANONYMOUS and
MAP_SHARED flags, and any of the tasks install shared policy on the region,
only nodes whose memories are allowed in both cpusets may be used in the
- policies. Again, obtaining this information requires "stepping outside"
- the memory policy APIs, as well as knowing in what cpusets other task might
- be attaching to the shared region, to use the cpuset information.
+ policies. Obtaining this information requires "stepping outside" the
+ memory policy APIs to use the cpuset information and requires that one
+ know in what cpusets other task might be attaching to the shared region.
Furthermore, if the cpusets' allowed memory sets are disjoint, "local"
allocation is the only valid policy.
diff --git a/Documentation/vm/slabinfo.c b/Documentation/vm/slabinfo.c
index 1af7bd5a2183..7047696c47a1 100644
--- a/Documentation/vm/slabinfo.c
+++ b/Documentation/vm/slabinfo.c
@@ -11,6 +11,7 @@
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
+#include <strings.h>
#include <string.h>
#include <unistd.h>
#include <stdarg.h>
@@ -84,7 +85,7 @@ void fatal(const char *x, ...)
va_start(ap, x);
vfprintf(stderr, x, ap);
va_end(ap);
- exit(1);
+ exit(EXIT_FAILURE);
}
void usage(void)
@@ -119,14 +120,14 @@ void usage(void)
);
}
-unsigned long read_obj(char *name)
+unsigned long read_obj(const char *name)
{
FILE *f = fopen(name, "r");
if (!f)
buffer[0] = 0;
else {
- if (!fgets(buffer,sizeof(buffer), f))
+ if (!fgets(buffer, sizeof(buffer), f))
buffer[0] = 0;
fclose(f);
if (buffer[strlen(buffer)] == '\n')
@@ -139,7 +140,7 @@ unsigned long read_obj(char *name)
/*
* Get the contents of an attribute
*/
-unsigned long get_obj(char *name)
+unsigned long get_obj(const char *name)
{
if (!read_obj(name))
return 0;
@@ -147,7 +148,7 @@ unsigned long get_obj(char *name)
return atol(buffer);
}
-unsigned long get_obj_and_str(char *name, char **x)
+unsigned long get_obj_and_str(const char *name, char **x)
{
unsigned long result = 0;
char *p;
@@ -166,12 +167,12 @@ unsigned long get_obj_and_str(char *name, char **x)
return result;
}
-void set_obj(struct slabinfo *s, char *name, int n)
+void set_obj(struct slabinfo *s, const char *name, int n)
{
char x[100];
FILE *f;
- sprintf(x, "%s/%s", s->name, name);
+ snprintf(x, 100, "%s/%s", s->name, name);
f = fopen(x, "w");
if (!f)
fatal("Cannot write to %s\n", x);
@@ -180,13 +181,13 @@ void set_obj(struct slabinfo *s, char *name, int n)
fclose(f);
}
-unsigned long read_slab_obj(struct slabinfo *s, char *name)
+unsigned long read_slab_obj(struct slabinfo *s, const char *name)
{
char x[100];
FILE *f;
- int l;
+ size_t l;
- sprintf(x, "%s/%s", s->name, name);
+ snprintf(x, 100, "%s/%s", s->name, name);
f = fopen(x, "r");
if (!f) {
buffer[0] = 0;
@@ -453,7 +454,7 @@ void slabcache(struct slabinfo *s)
return;
store_size(size_str, slab_size(s));
- sprintf(dist_str,"%lu/%lu/%d", s->slabs, s->partial, s->cpu_slabs);
+ snprintf(dist_str, 40, "%lu/%lu/%d", s->slabs, s->partial, s->cpu_slabs);
if (!line++)
first_line();
@@ -1062,6 +1063,7 @@ void read_slab_dir(void)
slab->partial = get_obj("partial");
slab->partial = get_obj_and_str("partial", &t);
decode_numa_list(slab->numa_partial, t);
+ free(t);
slab->poison = get_obj("poison");
slab->reclaim_account = get_obj("reclaim_account");
slab->red_zone = get_obj("red_zone");
@@ -1069,6 +1071,7 @@ void read_slab_dir(void)
slab->slab_size = get_obj("slab_size");
slab->slabs = get_obj_and_str("slabs", &t);
decode_numa_list(slab->numa, t);
+ free(t);
slab->store_user = get_obj("store_user");
slab->trace = get_obj("trace");
chdir("..");
@@ -1148,7 +1151,7 @@ int main(int argc, char *argv[])
while ((c = getopt_long(argc, argv, "ad::efhil1noprstvzTS",
opts, NULL)) != -1)
- switch(c) {
+ switch (c) {
case '1':
show_single_ref = 1;
break;
diff --git a/Documentation/w1/00-INDEX b/Documentation/w1/00-INDEX
new file mode 100644
index 000000000000..5270cf4cb109
--- /dev/null
+++ b/Documentation/w1/00-INDEX
@@ -0,0 +1,8 @@
+00-INDEX
+ - This file
+masters/
+ - Individual chips providing 1-wire busses.
+w1.generic
+ - The 1-wire (w1) bus
+w1.netlink
+ - Userspace communication protocol over connector [1].
diff --git a/Documentation/w1/masters/00-INDEX b/Documentation/w1/masters/00-INDEX
new file mode 100644
index 000000000000..752613c4cea2
--- /dev/null
+++ b/Documentation/w1/masters/00-INDEX
@@ -0,0 +1,6 @@
+00-INDEX
+ - This file
+ds2482
+ - The Maxim/Dallas Semiconductor DS2482 provides 1-wire busses.
+ds2490
+ - The Maxim/Dallas Semiconductor DS2490 builds USB <-> W1 bridges.
diff --git a/Documentation/w1/masters/ds2482 b/Documentation/w1/masters/ds2482
index c5d5478d90b2..9210d6fa5024 100644
--- a/Documentation/w1/masters/ds2482
+++ b/Documentation/w1/masters/ds2482
@@ -15,7 +15,7 @@ Author: Ben Gardner <bgardner@wabtec.com>
Description
-----------
-The Maixm/Dallas Semiconductor DS2482 is a I2C device that provides
+The Maxim/Dallas Semiconductor DS2482 is a I2C device that provides
one (DS2482-100) or eight (DS2482-800) 1-wire busses.
diff --git a/Documentation/w1/masters/ds2490 b/Documentation/w1/masters/ds2490
index 44a4918bd7f2..239f9ae01843 100644
--- a/Documentation/w1/masters/ds2490
+++ b/Documentation/w1/masters/ds2490
@@ -10,7 +10,7 @@ Author: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
Description
-----------
-The Maixm/Dallas Semiconductor DS2490 is a chip
+The Maxim/Dallas Semiconductor DS2490 is a chip
which allows to build USB <-> W1 bridges.
DS9490(R) is a USB <-> W1 bus master device
diff --git a/Documentation/watchdog/src/watchdog-simple.c b/Documentation/watchdog/src/watchdog-simple.c
index 47801bc7e742..4cf72f3fa8e9 100644
--- a/Documentation/watchdog/src/watchdog-simple.c
+++ b/Documentation/watchdog/src/watchdog-simple.c
@@ -3,15 +3,25 @@
#include <unistd.h>
#include <fcntl.h>
-int main(int argc, const char *argv[]) {
+int main(void)
+{
int fd = open("/dev/watchdog", O_WRONLY);
+ int ret = 0;
if (fd == -1) {
perror("watchdog");
- exit(1);
+ exit(EXIT_FAILURE);
}
while (1) {
- write(fd, "\0", 1);
- fsync(fd);
+ ret = write(fd, "\0", 1);
+ if (ret != 1) {
+ ret = -1;
+ break;
+ }
+ ret = fsync(fd);
+ if (ret)
+ break;
sleep(10);
}
+ close(fd);
+ return ret;
}
diff --git a/Documentation/x86_64/mm.txt b/Documentation/x86_64/mm.txt
index f42798ed1c54..b89b6d2bebfa 100644
--- a/Documentation/x86_64/mm.txt
+++ b/Documentation/x86_64/mm.txt
@@ -9,6 +9,7 @@ ffff800000000000 - ffff80ffffffffff (=40 bits) guard hole
ffff810000000000 - ffffc0ffffffffff (=46 bits) direct mapping of all phys. memory
ffffc10000000000 - ffffc1ffffffffff (=40 bits) hole
ffffc20000000000 - ffffe1ffffffffff (=45 bits) vmalloc/ioremap space
+ffffe20000000000 - ffffe2ffffffffff (=40 bits) virtual memory map (1TB)
... unused hole ...
ffffffff80000000 - ffffffff82800000 (=40 MB) kernel text mapping, from phys 0
... unused hole ...
diff --git a/Documentation/xterm-linux.xpm b/Documentation/xterm-linux.xpm
deleted file mode 100644
index f469c1a18e6e..000000000000
--- a/Documentation/xterm-linux.xpm
+++ /dev/null
@@ -1,61 +0,0 @@
-/* XPM */
-/*****************************************************************************/
-/** This pixmap was made by Torsten Poulin - 1996 - torsten@diku.dk **/
-/** It was made by combining xterm-blank.xpm with **/
-/** the wonderfully cute Linux penguin mascot by Larry Ewing. **/
-/** I had to change Larry's penguin a little to make it fit. **/
-/** xterm-blank.xpm contained the following comment: **/
-/** This pixmap is kindly offered by Ion Cionca - 1992 - **/
-/** Swiss Federal Institute of Technology **/
-/** Central Computing Service **/
-/*****************************************************************************/
-static char * image_name [] = {
-/**/
-"64 38 8 1",
-/**/
-" s mask c none",
-". c gray70",
-"X c gray85",
-"o c gray50",
-"O c yellow",
-"+ c darkolivegreen",
-"@ c white",
-"# c black",
-" ###### ",
-" ######## ",
-" ########## ........................... ",
-" ########### .XXXXXXXXXXXXXXXXXXXXXXXXXXX. ",
-" ########### .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXoo ",
-" #@@@#@@@### .XX+++++++++++++++++++++++XXXXoo ",
-" #@#@#@#@### .XX++++++++++++++++++++++++XXXooo ",
-" #@#####@### .XX++@@+@++@+@@@@++@+++++++XXXooo ",
-" ###OOO######.XX++++++++++++++++++++++++XXXoooo ",
-" ##OOOOOO####.XX++@@@@+@@+@@@+++++++++++XXXoooo ",
-" #O#OOO#O####.XX++++++++++++++++++++++++XXXooooo ",
-" ##O###OO####.XX++@@@@@@@@@@+@@@@@++++++XXXooooo ",
-" ###OOOO@#####XX++++++++++++++++++++++++XXXooooo ",
-" ##@###@@@@####XX++@@@+@@@@+@@++@@@++++++XXXooooo ",
-" #@@@@@@@@@@####X++++++++++++++++++++++++XXXooooo ",
-" ##@@@@@@@@@@#####++@+++++++++++++++++++++XXXooooo ",
-" ###@@@@@@@@@@######+++++++++++++++++++++++XXXooooo ",
-" ####@@@@@@@@@@@#####+@@@@+@+@@@+@++++++++++XXXooooo ",
-" ###@@@@@@@@@@@@######++++++++++++++++++++++XXXooooo ",
-" ##@@@@@@@@@@@@@@#####@+@@@@++++++++++++++++XXXooooo ",
-" ###@@@@@@@@@@@@@@######++++++++++++++++++++XXXXoooo ",
-" ###@@@@@@@@@@@@@@######XXXXXXXXXXXXXXXXXXXXXXXXooo ",
-" ###@@@@@@@@@@@@@@@######XXXXXXXXXXXXXXXXXXXXXXXooo ",
-" ###@@@@@@@@@@@@@@@@#####ooooooooooooooooooooooo...oo ",
-" ###@@@@@@@@@@@@@@@######.........................ooo ",
-" #OO##@@@@@@@@@@@@@#######oooooooooooooooooooooooooooo ",
-" #OOO##@@@@@@@@@@@#OO####O#XXXXXXXXXXXXXXXXXXXXXXXoooo.. .. ",
-" ###OOOOO##@@@@@@@@@@#OOO#OOO#XXXXXXXXXXXXXX#######XXoooo . .",
-" #OOOOOOOO###@@@@@@@@@#OOOOOOO#ooooooooooooooooooooXXXooo . ",
-" #OOOOOOOOO###@@@@@@@@@#OOOOOOO##XXXXXXXXXXXXXXXXXooooo . ",
-" #OOOOOOOOO#@@@@@@@@###OOOOOOOOO#XXXXXXXXXXXXXXXoo oooooo ",
-" #OOOOOOOOO#@@@@@@@####OOOOOOOO#@@@@@@@@@@@XXXXXoo ooooo...o ",
-" #OOOOOOOOOOO###########OOOOOO##XXXXXXXXXXXXXXXXoo ooXXXoo..o ",
-" ##OOOOOOOOO###########OOOO##@@@@@@@@@@@@@XXXXoo oXXXXX..o ",
-" ###OOOO### oXX##OOO#XXXXXXXXXXXXXXXXXXoo o.....oo ",
-" #### oooo####oooooooooooooooooooo ooooooo ",
-" ",
-" "};
diff --git a/MAINTAINERS b/MAINTAINERS
index c7355e7f09ff..cad0882754a6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -136,17 +136,6 @@ M: ajk@iehk.rwth-aachen.de
L: linux-hams@vger.kernel.org
S: Maintained
-8139CP 10/100 FAST ETHERNET DRIVER
-P: Jeff Garzik
-M: jgarzik@pobox.com
-S: Maintained
-
-8139TOO 10/100 FAST ETHERNET DRIVER
-P: Jeff Garzik
-M: jgarzik@pobox.com
-W: http://sourceforge.net/projects/gkernel/
-S: Maintained
-
8169 10/100/1000 GIGABIT ETHERNET DRIVER
P: Francois Romieu
M: romieu@fr.zoreil.com
@@ -227,7 +216,7 @@ P: Len Brown
M: len.brown@intel.com
M: lenb@kernel.org
L: linux-acpi@vger.kernel.org
-W: http://acpi.sourceforge.net/
+W: http://www.lesswatts.org/projects/acpi/
T: git kernel.org:/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git
S: Supported
@@ -246,8 +235,8 @@ W: http://acpi.sourceforge.net/
S: Supported
ACPI FAN DRIVER
-P: Konstantin A. Karasyov
-M: konstantin.a.karasyov@intel.com
+P: Len Brown
+M: len.brown@intel.com
L: linux-acpi@vger.kernel.org
W: http://acpi.sourceforge.net/
S: Supported
@@ -259,15 +248,15 @@ L: pcihpd-discuss@lists.sourceforge.net
S: Supported
ACPI THERMAL DRIVER
-P: Konstantin A. Karasyov
-M: konstantin.a.karasyov@intel.com
+P: Len Brown
+M: len.brown@intel.com
L: linux-acpi@vger.kernel.org
W: http://acpi.sourceforge.net/
S: Supported
ACPI VIDEO DRIVER
-P: Luming Yu
-M: luming.yu@intel.com
+P: Rui Zhang
+M: rui.zhang@intel.com
L: linux-acpi@vger.kernel.org
W: http://acpi.sourceforge.net/
S: Supported
@@ -325,6 +314,12 @@ M: Juergen Fischer <fischer@norbit.de>
L: linux-scsi@vger.kernel.org
S: Maintained
+AIC7XXX / AIC79XX SCSI DRIVER
+P: Hannes Reinecke
+M: hare@suse.de
+L: linux-scsi@vger.kernel.org
+S: Maintained
+
ALCATEL SPEEDTOUCH USB DRIVER
P: Duncan Sands
M: duncan.sands@free.fr
@@ -403,6 +398,12 @@ P: Arnaldo Carvalho de Melo
M: acme@ghostprotocols.net
S: Maintained
+APPLETOUCH TOUCHPAD DRIVER
+P: Johannes Berg
+M: johannes@sipsolutions.net
+L: linux-input@vger.kernel.org
+S: Maintained
+
ARC FRAMEBUFFER DRIVER
P: Jaya Kumar
M: jayalk@intworks.biz
@@ -786,23 +787,25 @@ B43 WIRELESS DRIVER
P: Michael Buesch
M: mb@bu3sch.de
P: Stefano Brivio
-M: st3@riseup.net
+M: stefano.brivio@polimi.it
L: linux-wireless@vger.kernel.org
-W: http://bcm43xx.berlios.de/
+W: http://linuxwireless.org/en/users/Drivers/b43
S: Maintained
B43LEGACY WIRELESS DRIVER
P: Larry Finger
M: Larry.Finger@lwfinger.net
+P: Stefano Brivio
+M: stefano.brivio@polimi.it
L: linux-wireless@vger.kernel.org
-W: http://bcm43xx.berlios.de/
+W: http://linuxwireless.org/en/users/Drivers/b43
S: Maintained
BCM43XX WIRELESS DRIVER (SOFTMAC BASED VERSION)
P: Larry Finger
M: Larry.Finger@lwfinger.net
P: Stefano Brivio
-M: st3@riseup.net
+M: stefano.brivio@polimi.it
L: linux-wireless@vger.kernel.org
W: http://bcm43xx.berlios.de/
S: Maintained
@@ -1037,12 +1040,6 @@ M: kernel@wantstofly.org
L: netdev@vger.kernel.org
S: Maintained
-CIRRUS LOGIC GENERIC FBDEV DRIVER
-P: Jeff Garzik
-M: jgarzik@pobox.com
-L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only)
-S: Odd Fixes
-
CIRRUS LOGIC EP93XX OHCI USB HOST DRIVER
P: Lennert Buytenhek
M: kernel@wantstofly.org
@@ -1712,7 +1709,7 @@ S: Maintained
HID CORE LAYER
P: Jiri Kosina
M: jkosina@suse.cz
-L: linux-input@atrey.karlin.mff.cuni.cz
+L: linux-input@vger.kernel.org
T: git kernel.org:/pub/scm/linux/kernel/git/jikos/hid.git
S: Maintained
@@ -1769,7 +1766,7 @@ S: Maintained
HP100: Driver for HP 10/100 Mbit/s Voice Grade Network Adapter Series
P: Jaroslav Kysela
-M: perex@suse.cz
+M: perex@perex.cz
S: Maintained
HPET: High Precision Event Timers driver (hpet.c)
@@ -1877,10 +1874,8 @@ T: quilt kernel.org/pub/linux/kernel/people/bart/pata-2.6/
S: Maintained
IDE/ATAPI CDROM DRIVER
-P: Alan Cox
-M: alan@lxorguk.ukuu.org.uk
L: linux-ide@vger.kernel.org
-S: Maintained
+S: Unmaintained
IDE/ATAPI FLOPPY DRIVERS
P: Paul Bristow
@@ -1940,8 +1935,7 @@ INPUT (KEYBOARD, MOUSE, JOYSTICK, TOUCHSCREEN) DRIVERS
P: Dmitry Torokhov
M: dmitry.torokhov@gmail.com
M: dtor@mail.ru
-L: linux-input@atrey.karlin.mff.cuni.cz
-L: linux-joystick@atrey.karlin.mff.cuni.cz
+L: linux-input@vger.kernel.org
T: git kernel.org:/pub/scm/linux/kernel/git/dtor/input.git
S: Maintained
@@ -1965,17 +1959,6 @@ M: adaplas@gmail.com
L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only)
S: Maintained
-INTEL APIC/IOAPIC, LOWLEVEL X86 SMP SUPPORT
-P: Ingo Molnar
-M: mingo@redhat.com
-S: Maintained
-
-INTEL I8XX RANDOM NUMBER GENERATOR SUPPORT
-P: Jeff Garzik
-M: jgarzik@pobox.com
-W: http://sourceforge.net/projects/gkernel/
-S: Maintained
-
INTEL IA32 MICROCODE UPDATE SUPPORT
P: Tigran Aivazian
M: tigran@aivazian.fsnet.co.uk
@@ -2132,14 +2115,12 @@ S: Maintained
ISAPNP
P: Jaroslav Kysela
-M: perex@suse.cz
+M: perex@perex.cz
S: Maintained
ISDN SUBSYSTEM
P: Karsten Keil
M: kkeil@suse.de
-P: Kai Germaschewski
-M: kai.germaschewski@gmx.de
L: isdn4linux@listserv.isdn4linux.de
W: http://www.isdn4linux.de
T: git kernel.org:/pub/scm/linux/kernel/kkeil/isdn-2.6.git
@@ -2155,8 +2136,8 @@ S: Maintained
JOURNALLING FLASH FILE SYSTEM V2 (JFFS2)
P: David Woodhouse
M: dwmw2@infradead.org
-L: jffs-dev@axis.com
-W: http://sources.redhat.com/jffs2/
+L: linux-mtd@lists.infradead.org
+W: http://www.linux-mtd.infradead.org/doc/jffs2.html
S: Maintained
JFS FILESYSTEM
@@ -2182,7 +2163,7 @@ S: Maintained
KCONFIG
P: Roman Zippel
M: zippel@linux-m68k.org
-L: kbuild-devel@lists.sourceforge.net
+L: linux-kbuild@vger.kernel.org
S: Maintained
KDUMP
@@ -2208,11 +2189,10 @@ L: autofs@linux.kernel.org
S: Maintained
KERNEL BUILD (kbuild: Makefile, scripts/Makefile.*)
-P: Kai Germaschewski
-M: kai@germaschewski.name
P: Sam Ravnborg
M: sam@ravnborg.org
T: git kernel.org:/pub/scm/linux/kernel/git/sam/kbuild.git
+L: linux-kbuild@vger.kernel.org
S: Maintained
KERNEL JANITORS
@@ -2240,7 +2220,7 @@ S: Supported
KEXEC
P: Eric Biederman
M: ebiederm@xmission.com
-W: http://www.xmission.com/~ebiederm/files/kexec/
+W: http://ftp.kernel.org/pub/linux/kernel/people/horms/kexec-tools/
L: linux-kernel@vger.kernel.org
L: kexec@lists.infradead.org
S: Maintained
@@ -2286,6 +2266,13 @@ L: legousb-devel@lists.sourceforge.net
W: http://legousb.sourceforge.net/
S: Maintained
+LGUEST
+P: Rusty Russell
+M: rusty@rustcorp.com.au
+L: lguest@ozlabs.org
+W: http://lguest.ozlabs.org/
+S: Maintained
+
LINUX FOR IBM pSERIES (RS/6000)
P: Paul Mackerras
M: paulus@au.ibm.com
@@ -2348,6 +2335,8 @@ L: linuxppc-dev@ozlabs.org
S: Maintained
LINUX FOR POWERPC EMBEDDED PPC8XX
+P: Vitaly Bordug
+M: vitb@kernel.crashing.org
P: Marcelo Tosatti
M: marcelo@kvack.org
W: http://www.penguinppc.org/
@@ -2467,13 +2456,15 @@ W: http://www.tazenda.demon.co.uk/phil/linux-hp
S: Maintained
MAC80211
-P: Jiri Benc
-M: jbenc@suse.cz
P: Michael Wu
M: flamingice@sourmilk.net
+P: Johannes Berg
+M: johannes@sipsolutions.net
+P: Jiri Benc
+M: jbenc@suse.cz
L: linux-wireless@vger.kernel.org
W: http://linuxwireless.org/
-T: git kernel.org:/pub/scm/linux/kernel/git/jbenc/mac80211.git
+T: git kernel.org:/pub/scm/linux/kernel/git/linville/wireless-2.6.git
S: Maintained
MACVLAN DRIVER
@@ -2492,7 +2483,7 @@ S: Supported
MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7
P: Michael Kerrisk
-M: mtk-manpages@gmx.net
+M: mtk.manpages@gmail.com
W: ftp://ftp.kernel.org/pub/linux/docs/manpages
S: Maintained
@@ -2560,7 +2551,7 @@ S: Supported
MISCELLANEOUS MCA-SUPPORT
P: James Bottomley
-M: jejb@steeleye.com
+M: James.Bottomley@HansenPartnership.com
L: linux-kernel@vger.kernel.org
S: Maintained
@@ -2703,8 +2694,6 @@ M: Paul.Clements@steeleye.com
S: Maintained
NETWORK DEVICE DRIVERS
-P: Andrew Morton
-M: akpm@linux-foundation.org
P: Jeff Garzik
M: jgarzik@pobox.com
L: netdev@vger.kernel.org
@@ -2946,13 +2935,6 @@ L: linux-kernel@vger.kernel.org
L: linux-pci@atrey.karlin.mff.cuni.cz
S: Supported
-PCI SOUND DRIVERS (ES1370, ES1371 and SONICVIBES)
-P: Thomas Sailer
-M: sailer@ife.ee.ethz.ch
-L: linux-sound@vger.kernel.org
-W: http://www.ife.ee.ethz.ch/~sailer/linux/pciaudio.html
-S: Maintained
-
PCI SUBSYSTEM
P: Greg Kroah-Hartman
M: gregkh@suse.de
@@ -3263,6 +3245,8 @@ S: Supported
S390 NETWORK DRIVERS
P: Ursula Braun
M: ubraun@linux.vnet.ibm.com
+P: Frank Blaschka
+M: blaschka@linux.vnet.ibm.com
M: linux390@de.ibm.com
L: linux-s390@vger.kernel.org
W: http://www.ibm.com/developerworks/linux/linux390/
@@ -3319,9 +3303,11 @@ S: Maintained
SCSI SUBSYSTEM
P: James E.J. Bottomley
-M: James.Bottomley@SteelEye.com
+M: James.Bottomley@HansenPartnership.com
L: linux-scsi@vger.kernel.org
T: git kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git
+T: git kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6.git
+T: git kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-pending-2.6.git
S: Maintained
SCSI TAPE DRIVER
@@ -3468,15 +3454,10 @@ L: lm-sensors@lm-sensors.org
S: Maintained
SOFTMAC LAYER (IEEE 802.11)
-P: Johannes Berg
-M: johannes@sipsolutions.net
-P: Joe Jezak
-M: josejx@gentoo.org
P: Daniel Drake
M: dsd@gentoo.org
-W: http://softmac.sipsolutions.net/
L: linux-wireless@vger.kernel.org
-S: Maintained
+S: Obsolete
SOFTWARE RAID (Multiple Disks) SUPPORT
P: Ingo Molnar
@@ -3495,12 +3476,14 @@ L: linux-pm@lists.linux-foundation.org
S: Supported
SUSPEND TO RAM:
+P: Len Brown
+M: len.brown@intel.com
P: Pavel Machek
M: pavel@suse.cz
P: Rafael J. Wysocki
M: rjw@sisk.pl
L: linux-pm@lists.linux-foundation.org
-S: Maintained
+S: Supported
SONIC NETWORK DRIVER
P: Thomas Bogendoerfer
@@ -3523,7 +3506,7 @@ S: Maintained
SOUND
P: Jaroslav Kysela
-M: perex@suse.cz
+M: perex@perex.cz
L: alsa-devel@alsa-project.org (subscribers-only)
S: Maintained
@@ -3713,7 +3696,7 @@ S: Maintained
TI OMAP MMC INTERFACE DRIVER
P: Carlos Aguiar, Anderson Briglia and Syed Khasim
-M: linux-omap-open-source@linux.omap.com
+M: linux-omap-open-source@linux.omap.com (subscribers only)
W: http://linux.omap.com
W: http://www.muru.com/linux/omap/
S: Maintained
@@ -4118,10 +4101,6 @@ M: hirofumi@mail.parknet.co.jp
L: linux-kernel@vger.kernel.org
S: Maintained
-VIA 82Cxxx AUDIO DRIVER (old OSS driver)
-P: Jeff Garzik
-S: Odd fixes
-
VIA RHINE NETWORK DRIVER
P: Roger Luethi
M: rl@hellgate.ch
@@ -4177,6 +4156,12 @@ W: http://linuxtv.org
T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git
S: Maintained
+VLAN (802.1Q)
+P: Patrick McHardy
+M: kaber@trash.net
+L: netdev@vger.kernel.org
+S: Maintained
+
VT1211 HARDWARE MONITOR DRIVER
P: Juerg Haefliger
M: juergh@gmail.com
@@ -4281,9 +4266,15 @@ M: jacmet@sunsite.dk
L: linux-serial@vger.kernel.org
S: Maintained
-X86 3-LEVEL PAGING (PAE) SUPPORT
+X86 ARCHITECTURE (32-BIT AND 64-BIT)
+P: Thomas Gleixner
+M: tglx@linutronix.de
P: Ingo Molnar
M: mingo@redhat.com
+P: H. Peter Anvin
+M: hpa@zytor.com
+L: linux-kernel@vger.kernel.org
+T: git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git
S: Maintained
YAM DRIVER FOR AX.25
diff --git a/Makefile b/Makefile
index 1274084c9090..9c9c4bfb0e51 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
-SUBLEVEL = 23
-EXTRAVERSION =
+SUBLEVEL = 24
+EXTRAVERSION = -rc2
NAME = Arr Matey! A Hairy Bilge Rat!
# *DOCUMENTATION*
@@ -115,13 +115,20 @@ saved-output := $(KBUILD_OUTPUT)
KBUILD_OUTPUT := $(shell cd $(KBUILD_OUTPUT) && /bin/pwd)
$(if $(KBUILD_OUTPUT),, \
$(error output directory "$(saved-output)" does not exist))
+# Check that OUTPUT directory is not the same as where we have kernel src
+$(if $(filter-out $(KBUILD_OUTPUT),$(shell /bin/pwd)),, \
+ $(error Output directory (O=...) specifies kernel src dir))
-PHONY += $(MAKECMDGOALS)
+PHONY += $(MAKECMDGOALS) sub-make
-$(filter-out _all,$(MAKECMDGOALS)) _all:
+$(filter-out _all sub-make,$(MAKECMDGOALS)) _all: sub-make
+ $(Q)@:
+
+sub-make: FORCE
$(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \
KBUILD_SRC=$(CURDIR) \
- KBUILD_EXTMOD="$(KBUILD_EXTMOD)" -f $(CURDIR)/Makefile $@
+ KBUILD_EXTMOD="$(KBUILD_EXTMOD)" -f $(CURDIR)/Makefile \
+ $(filter-out _all sub-make,$(MAKECMDGOALS))
# Leave processing to above invocation of make
skip-makefile := 1
@@ -161,7 +168,8 @@ export srctree objtree VPATH TOPDIR
SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
-e s/arm.*/arm/ -e s/sa110/arm/ \
-e s/s390x/s390/ -e s/parisc64/parisc/ \
- -e s/ppc.*/powerpc/ -e s/mips.*/mips/ )
+ -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
+ -e s/sh[234].*/sh/ )
# Cross compiling and selecting different set of gcc/bin-utils
# ---------------------------------------------------------------------------
@@ -189,6 +197,16 @@ CROSS_COMPILE ?=
UTS_MACHINE := $(ARCH)
SRCARCH := $(ARCH)
+# Additional ARCH settings for x86
+ifeq ($(ARCH),i386)
+ SRCARCH := x86
+ K64BIT := n
+endif
+ifeq ($(ARCH),x86_64)
+ SRCARCH := x86
+ K64BIT := y
+endif
+
KCONFIG_CONFIG ?= .config
# SHELL used by kbuild
@@ -311,25 +329,25 @@ LINUXINCLUDE := -Iinclude \
$(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) \
-include include/linux/autoconf.h
-CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE)
+KBUILD_CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE)
-CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
+KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
-fno-strict-aliasing -fno-common \
-Werror-implicit-function-declaration
-AFLAGS := -D__ASSEMBLY__
+KBUILD_AFLAGS := -D__ASSEMBLY__
# Read KERNELRELEASE from include/config/kernel.release (if it exists)
KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
KERNELVERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
-export ARCH SRCARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC
+export ARCH SRCARCH K64BIT CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC
export CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE
export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
-export CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS
-export CFLAGS CFLAGS_KERNEL CFLAGS_MODULE
-export AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
+export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS
+export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE
+export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
# When compiling out-of-tree modules, put MODVERDIR in the module
# tree rather than in the kernel tree. The kernel tree might
@@ -411,7 +429,7 @@ ifeq ($(config-targets),1)
# Read arch specific Makefile to set KBUILD_DEFCONFIG as needed.
# KBUILD_DEFCONFIG may point out an alternative default configuration
# used for 'make defconfig'
-include $(srctree)/arch/$(ARCH)/Makefile
+include $(srctree)/arch/$(SRCARCH)/Makefile
export KBUILD_DEFCONFIG
config %config: scripts_basic outputmakefile FORCE
@@ -485,35 +503,54 @@ endif # $(dot-config)
all: vmlinux
ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
-CFLAGS += -Os
+KBUILD_CFLAGS += -Os
else
-CFLAGS += -O2
+KBUILD_CFLAGS += -O2
endif
-include $(srctree)/arch/$(ARCH)/Makefile
+include $(srctree)/arch/$(SRCARCH)/Makefile
ifdef CONFIG_FRAME_POINTER
-CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls
+KBUILD_CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls
else
-CFLAGS += -fomit-frame-pointer
+KBUILD_CFLAGS += -fomit-frame-pointer
endif
ifdef CONFIG_DEBUG_INFO
-CFLAGS += -g
+KBUILD_CFLAGS += -g
+KBUILD_AFLAGS += -gdwarf-2
endif
# Force gcc to behave correct even for buggy distributions
-CFLAGS += $(call cc-option, -fno-stack-protector)
+KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector)
# arch Makefile may override CC so keep this after arch Makefile is included
NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
CHECKFLAGS += $(NOSTDINC_FLAGS)
# warn about C99 declaration after statement
-CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
+KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
# disable pointer signed / unsigned warnings in gcc 4.0
-CFLAGS += $(call cc-option,-Wno-pointer-sign,)
+KBUILD_CFLAGS += $(call cc-option,-Wno-pointer-sign,)
+
+# Add user supplied CPPFLAGS, AFLAGS and CFLAGS as the last assignments
+# But warn user when we do so
+warn-assign = \
+$(warning "WARNING: Appending $$K$(1) ($(K$(1))) from $(origin K$(1)) to kernel $$$(1)")
+
+ifneq ($(KCPPFLAGS),)
+ $(call warn-assign,CPPFLAGS)
+ KBUILD_CPPFLAGS += $(KCPPFLAGS)
+endif
+ifneq ($(KAFLAGS),)
+ $(call warn-assign,AFLAGS)
+ KBUILD_AFLAGS += $(KAFLAGS)
+endif
+ifneq ($(KCFLAGS),)
+ $(call warn-assign,CFLAGS)
+ KBUILD_CFLAGS += $(KCFLAGS)
+endif
# Use --build-id when available.
LDFLAGS_BUILD_ID = $(patsubst -Wl$(comma)%,%,\
@@ -761,6 +798,9 @@ vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) vmlinux.o
ifdef CONFIG_HEADERS_CHECK
$(Q)$(MAKE) -f $(srctree)/Makefile headers_check
endif
+ifdef CONFIG_SAMPLES
+ $(Q)$(MAKE) $(build)=samples
+endif
$(call vmlinux-modpost)
$(call if_changed_rule,vmlinux__)
$(Q)rm -f .old_version
@@ -871,10 +911,7 @@ prepare2: prepare3 outputmakefile
prepare1: prepare2 include/linux/version.h include/linux/utsrelease.h \
include/asm include/config/auto.conf
-ifneq ($(KBUILD_MODULES),)
- $(Q)mkdir -p $(MODVERDIR)
- $(Q)rm -f $(MODVERDIR)/*
-endif
+ $(cmd_crmodverdir)
archprepare: prepare1 scripts_basic
@@ -890,14 +927,24 @@ prepare: prepare0
export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH)
-# FIXME: The asm symlink changes when $(ARCH) changes. That's
-# hard to detect, but I suppose "make mrproper" is a good idea
-# before switching between archs anyway.
-
-include/asm:
- @echo ' SYMLINK $@ -> include/asm-$(SRCARCH)'
- $(Q)if [ ! -d include ]; then mkdir -p include; fi;
- @ln -fsn asm-$(SRCARCH) $@
+# The asm symlink changes when $(ARCH) changes.
+# Detect this and ask user to run make mrproper
+
+include/asm: FORCE
+ $(Q)set -e; asmlink=`readlink include/asm | cut -d '-' -f 2`; \
+ if [ -L include/asm ]; then \
+ if [ "$$asmlink" != "$(SRCARCH)" ]; then \
+ echo "ERROR: the symlink $@ points to asm-$$asmlink but asm-$(SRCARCH) was expected"; \
+ echo " set ARCH or save .config and run 'make mrproper' to fix it"; \
+ exit 1; \
+ fi; \
+ else \
+ echo ' SYMLINK $@ -> include/asm-$(SRCARCH)'; \
+ if [ ! -d include ]; then \
+ mkdir -p include; \
+ fi; \
+ ln -fsn asm-$(SRCARCH) $@; \
+ fi
# Generate some files
# ---------------------------------------------------------------------------
@@ -1007,19 +1054,12 @@ _modinst_:
fi
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst
-# If System.map exists, run depmod. This deliberately does not have a
-# dependency on System.map since that would run the dependency tree on
-# vmlinux. This depmod is only for convenience to give the initial
+# This depmod is only for convenience to give the initial
# boot a modules.dep even before / is mounted read-write. However the
# boot script depmod is the master version.
-ifeq "$(strip $(INSTALL_MOD_PATH))" ""
-depmod_opts :=
-else
-depmod_opts := -b $(INSTALL_MOD_PATH) -r
-endif
PHONY += _modinst_post
_modinst_post: _modinst_
- if [ -r System.map -a -x $(DEPMOD) ]; then $(DEPMOD) -ae -F System.map $(depmod_opts) $(KERNELRELEASE); fi
+ $(call cmd,depmod)
else # CONFIG_MODULES
@@ -1149,6 +1189,7 @@ help:
@echo 'Static analysers'
@echo ' checkstack - Generate a list of stack hogs'
@echo ' namespacecheck - Name space analysis on compiled kernel'
+ @echo ' export_report - List the usages of all exported symbols'
@if [ -r $(srctree)/include/asm-$(SRCARCH)/Kbuild ]; then \
echo ' headers_check - Sanity check on exported headers'; \
fi
@@ -1206,8 +1247,7 @@ else # KBUILD_EXTMOD
KBUILD_MODULES := 1
PHONY += crmodverdir
crmodverdir:
- $(Q)mkdir -p $(MODVERDIR)
- $(Q)rm -f $(MODVERDIR)/*
+ $(cmd_crmodverdir)
PHONY += $(objtree)/Module.symvers
$(objtree)/Module.symvers:
@@ -1235,15 +1275,6 @@ _emodinst_:
$(Q)mkdir -p $(MODLIB)/$(install-dir)
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst
-# Run depmod only is we have System.map and depmod is executable
-quiet_cmd_depmod = DEPMOD $(KERNELRELEASE)
- cmd_depmod = if [ -r System.map -a -x $(DEPMOD) ]; then \
- $(DEPMOD) -ae -F System.map \
- $(if $(strip $(INSTALL_MOD_PATH)), \
- -b $(INSTALL_MOD_PATH) -r) \
- $(KERNELRELEASE); \
- fi
-
PHONY += _emodinst_post
_emodinst_post: _emodinst_
$(call cmd,depmod)
@@ -1255,8 +1286,10 @@ $(clean-dirs):
$(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@)
clean: rm-dirs := $(MODVERDIR)
+clean: rm-files := $(KBUILD_EXTMOD)/Module.symvers
clean: $(clean-dirs)
$(call cmd,rmdirs)
+ $(call cmd,rmfiles)
@find $(KBUILD_EXTMOD) $(RCS_FIND_IGNORE) \
\( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \) \
@@ -1309,8 +1342,8 @@ ALLSOURCE_ARCHS := $(ARCH) $(SRCARCH)
endif
define find-sources
- ( for ARCH in $(ALLSOURCE_ARCHS) ; do \
- find $(__srctree)arch/$${SRCARCH} $(RCS_FIND_IGNORE) \
+ ( for arch in $(ALLSOURCE_ARCHS) ; do \
+ find $(__srctree)arch/$${arch} $(RCS_FIND_IGNORE) \
-name $1 -print; \
done ; \
find $(__srctree)security/selinux/include $(RCS_FIND_IGNORE) \
@@ -1318,14 +1351,14 @@ define find-sources
find $(__srctree)include $(RCS_FIND_IGNORE) \
\( -name config -o -name 'asm-*' \) -prune \
-o -name $1 -print; \
- for ARCH in $(ALLINCLUDE_ARCHS) ; do \
- find $(__srctree)include/asm-$${SRCARCH} $(RCS_FIND_IGNORE) \
+ for arch in $(ALLINCLUDE_ARCHS) ; do \
+ find $(__srctree)include/asm-$${arch} $(RCS_FIND_IGNORE) \
-name $1 -print; \
done ; \
find $(__srctree)include/asm-generic $(RCS_FIND_IGNORE) \
-name $1 -print; \
find $(__srctree) $(RCS_FIND_IGNORE) \
- \( -name include -o -name arch \) -prune -o \
+ \( -name include -o -name arch -o -name '.tmp_*' \) -prune -o \
-name $1 -print; \
)
endef
@@ -1411,6 +1444,9 @@ versioncheck:
namespacecheck:
$(PERL) $(srctree)/scripts/namespace.pl
+export_report:
+ $(PERL) $(srctree)/scripts/export_report.pl
+
endif #ifeq ($(config-targets),1)
endif #ifeq ($(mixed-targets),1)
@@ -1471,9 +1507,11 @@ endif
# Modules
/ %/: prepare scripts FORCE
+ $(cmd_crmodverdir)
$(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
$(build)=$(build-dir)
%.ko: prepare scripts FORCE
+ $(cmd_crmodverdir)
$(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
$(build)=$(build-dir) $(@:.ko=.o)
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
@@ -1487,9 +1525,23 @@ quiet_cmd_rmdirs = $(if $(wildcard $(rm-dirs)),CLEAN $(wildcard $(rm-dirs)))
quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),CLEAN $(wildcard $(rm-files)))
cmd_rmfiles = rm -f $(rm-files)
+# Run depmod only is we have System.map and depmod is executable
+# and we build for the host arch
+quiet_cmd_depmod = DEPMOD $(KERNELRELEASE)
+ cmd_depmod = \
+ if [ -r System.map -a -x $(DEPMOD) ]; then \
+ $(DEPMOD) -ae -F System.map \
+ $(if $(strip $(INSTALL_MOD_PATH)), -b $(INSTALL_MOD_PATH) -r) \
+ $(KERNELRELEASE); \
+ fi
+
+# Create temporary dir for module support files
+# clean it up only when building all modules
+cmd_crmodverdir = $(Q)mkdir -p $(MODVERDIR) \
+ $(if $(KBUILD_MODULES),; rm -f $(MODVERDIR)/*)
-a_flags = -Wp,-MD,$(depfile) $(AFLAGS) $(AFLAGS_KERNEL) \
- $(NOSTDINC_FLAGS) $(CPPFLAGS) \
+a_flags = -Wp,-MD,$(depfile) $(KBUILD_AFLAGS) $(AFLAGS_KERNEL) \
+ $(NOSTDINC_FLAGS) $(KBUILD_CPPFLAGS) \
$(modkern_aflags) $(EXTRA_AFLAGS) $(AFLAGS_$(basetarget).o)
quiet_cmd_as_o_S = AS $@
diff --git a/README b/README
index 159912cf5155..592f8a238281 100644
--- a/README
+++ b/README
@@ -194,6 +194,8 @@ CONFIGURING the kernel:
"make *config" checks for a file named "all{yes/mod/no/random}.config"
for symbol values that are to be forced. If this file is not found,
it checks for a file named "all.config" to contain forced values.
+ Finally it checks the environment variable K64BIT and if found, sets
+ the config symbol "64BIT" to the value of the K64BIT variable.
NOTES on "make config":
- having unnecessary drivers will make the kernel bigger, and can
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 2a85dc33907c..4c002ba37e50 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -654,7 +654,7 @@ source "drivers/Kconfig"
source "fs/Kconfig"
-source "arch/alpha/oprofile/Kconfig"
+source "kernel/Kconfig.instrumentation"
source "arch/alpha/Kconfig.debug"
diff --git a/arch/alpha/Makefile b/arch/alpha/Makefile
index 1b704ee54bf3..63104ebd1806 100644
--- a/arch/alpha/Makefile
+++ b/arch/alpha/Makefile
@@ -12,79 +12,28 @@ NM := $(NM) -B
LDFLAGS_vmlinux := -static -N #-relax
CHECKFLAGS += -D__alpha__ -m64
-cflags-y := -pipe -mno-fp-regs -ffixed-8
+cflags-y := -pipe -mno-fp-regs -ffixed-8 -msmall-data
-# Determine if we can use the BWX instructions with GAS.
-old_gas := $(shell if $(AS) --version 2>&1 | grep 'version 2.7' > /dev/null; then echo y; else echo n; fi)
+cpuflags-$(CONFIG_ALPHA_EV67) := -mcpu=ev67
+cpuflags-$(CONFIG_ALPHA_EV6) := -mcpu=ev6
+cpuflags-$(CONFIG_ALPHA_POLARIS) := -mcpu=pca56
+cpuflags-$(CONFIG_ALPHA_SX164) := -mcpu=pca56
+cpuflags-$(CONFIG_ALPHA_EV56) := -mcpu=ev56
+cpuflags-$(CONFIG_ALPHA_EV5) := -mcpu=ev5
+cpuflags-$(CONFIG_ALPHA_EV4) := -mcpu=ev4
+# If GENERIC, make sure to turn off any instruction set extensions that
+# the host compiler might have on by default. Given that EV4 and EV5
+# have the same instruction set, prefer EV5 because an EV5 schedule is
+# more likely to keep an EV4 processor busy than vice-versa.
+cpuflags-$(CONFIG_ALPHA_GENERIC) := -mcpu=ev5
-ifeq ($(old_gas),y)
-$(error The assembler '$(AS)' does not support the BWX instruction)
-endif
-
-# Determine if GCC understands the -mcpu= option.
-have_mcpu := $(call cc-option-yn, -mcpu=ev5)
-have_mcpu_pca56 := $(call cc-option-yn, -mcpu=pca56)
-have_mcpu_ev6 := $(call cc-option-yn, -mcpu=ev6)
-have_mcpu_ev67 := $(call cc-option-yn, -mcpu=ev67)
-have_msmall_data := $(call cc-option-yn, -msmall-data)
-
-cflags-$(have_msmall_data) += -msmall-data
-
-# Turn on the proper cpu optimizations.
-ifeq ($(have_mcpu),y)
- mcpu_done := n
- # If GENERIC, make sure to turn off any instruction set extensions that
- # the host compiler might have on by default. Given that EV4 and EV5
- # have the same instruction set, prefer EV5 because an EV5 schedule is
- # more likely to keep an EV4 processor busy than vice-versa.
- ifeq ($(CONFIG_ALPHA_GENERIC),y)
- mcpu := ev5
- mcpu_done := y
- endif
- ifeq ($(mcpu_done)$(CONFIG_ALPHA_SX164)$(have_mcpu_pca56),nyy)
- mcpu := pca56
- mcpu_done := y
- endif
- ifeq ($(mcpu_done)$(CONFIG_ALPHA_POLARIS)$(have_mcpu_pca56),nyy)
- mcpu := pca56
- mcpu_done := y
- endif
- ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV4),ny)
- mcpu := ev4
- mcpu_done := y
- endif
- ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV56),ny)
- mcpu := ev56
- mcpu_done := y
- endif
- ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV5),ny)
- mcpu := ev5
- mcpu_done := y
- endif
- ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV67)$(have_mcpu_ev67),nyy)
- mcpu := ev67
- mcpu_done := y
- endif
- ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV6),ny)
- ifeq ($(have_mcpu_ev6),y)
- mcpu := ev6
- else
- ifeq ($(have_mcpu_pca56),y)
- mcpu := pca56
- else
- mcpu=ev56
- endif
- endif
- mcpu_done := y
- endif
- cflags-$(mcpu_done) += -mcpu=$(mcpu)
-endif
+cflags-y += $(cpuflags-y)
# For TSUNAMI, we must have the assembler not emulate our instructions.
# The same is true for IRONGATE, POLARIS, PYXIS.
# BWX is most important, but we don't really want any emulation ever.
-CFLAGS += $(cflags-y) -Wa,-mev6
+KBUILD_CFLAGS += $(cflags-y) -Wa,-mev6
head-y := arch/alpha/kernel/head.o
diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile
index ab6fa54b3860..dccf05245d4d 100644
--- a/arch/alpha/kernel/Makefile
+++ b/arch/alpha/kernel/Makefile
@@ -3,7 +3,7 @@
#
extra-y := head.o vmlinux.lds
-EXTRA_AFLAGS := $(CFLAGS)
+EXTRA_AFLAGS := $(KBUILD_CFLAGS)
EXTRA_CFLAGS := -Werror -Wno-sign-compare
obj-y := entry.o traps.o process.o init_task.o osf_sys.o irq.o \
diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S
index debc8f03886c..5fc61e281ac7 100644
--- a/arch/alpha/kernel/entry.S
+++ b/arch/alpha/kernel/entry.S
@@ -917,15 +917,6 @@ sys_pipe:
.end sys_pipe
.align 4
- .globl sys_ptrace
- .ent sys_ptrace
-sys_ptrace:
- .prologue 0
- mov $sp, $20
- jmp $31, do_sys_ptrace
-.end sys_ptrace
-
- .align 4
.globl sys_execve
.ent sys_execve
sys_execve:
diff --git a/arch/alpha/kernel/err_marvel.c b/arch/alpha/kernel/err_marvel.c
index f2956ac8dccc..497877bf2012 100644
--- a/arch/alpha/kernel/err_marvel.c
+++ b/arch/alpha/kernel/err_marvel.c
@@ -1082,7 +1082,7 @@ marvel_machine_check(u64 vector, u64 la_ptr)
}
/*
- * A system event or error has occured, handle it here.
+ * A system event or error has occurred, handle it here.
*
* Any errors in the logout frame have already been cleared by the
* PALcode, so just parse it.
diff --git a/arch/alpha/kernel/err_titan.c b/arch/alpha/kernel/err_titan.c
index 543d96d7fa2b..6f3867877d9e 100644
--- a/arch/alpha/kernel/err_titan.c
+++ b/arch/alpha/kernel/err_titan.c
@@ -591,7 +591,7 @@ privateer_process_680_frame(struct el_common *mchk_header, int print)
(struct el_PRIVATEER_envdata_mcheck *)
((unsigned long)mchk_header + mchk_header->sys_offset);
- /* TODO - catagorize errors, for now, no error */
+ /* TODO - categorize errors, for now, no error */
if (!print)
return status;
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index ce857158c1ea..6413c5f23226 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -715,7 +715,7 @@ osf_setsysinfo(unsigned long op, void __user *buffer, unsigned long nbytes,
/*
* Alpha Architecture Handbook 4.7.7.3:
* To be fully IEEE compiant, we must track the current IEEE
- * exception state in software, because spurrious bits can be
+ * exception state in software, because spurious bits can be
* set in the trap shadow of a software-complete insn.
*/
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index e1c470752ebc..2d00a08d3f08 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -7,6 +7,7 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/bootmem.h>
+#include <linux/scatterlist.h>
#include <linux/log2.h>
#include <asm/io.h>
@@ -465,7 +466,7 @@ EXPORT_SYMBOL(pci_free_consistent);
Write dma_length of each leader with the combined lengths of
the mergable followers. */
-#define SG_ENT_VIRT_ADDRESS(SG) (page_address((SG)->page) + (SG)->offset)
+#define SG_ENT_VIRT_ADDRESS(SG) (sg_virt((SG)))
#define SG_ENT_PHYS_ADDRESS(SG) __pa(SG_ENT_VIRT_ADDRESS(SG))
static void
diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c
index 83a781842266..1e9ad52c460e 100644
--- a/arch/alpha/kernel/ptrace.c
+++ b/arch/alpha/kernel/ptrace.c
@@ -260,38 +260,12 @@ void ptrace_disable(struct task_struct *child)
ptrace_cancel_bpt(child);
}
-asmlinkage long
-do_sys_ptrace(long request, long pid, long addr, long data,
- struct pt_regs *regs)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
- struct task_struct *child;
unsigned long tmp;
size_t copied;
long ret;
- lock_kernel();
- DBG(DBG_MEM, ("request=%ld pid=%ld addr=0x%lx data=0x%lx\n",
- request, pid, addr, data));
- if (request == PTRACE_TRACEME) {
- ret = ptrace_traceme();
- goto out_notsk;
- }
-
- child = ptrace_get_task_struct(pid);
- if (IS_ERR(child)) {
- ret = PTR_ERR(child);
- goto out_notsk;
- }
-
- if (request == PTRACE_ATTACH) {
- ret = ptrace_attach(child);
- goto out;
- }
-
- ret = ptrace_check_attach(child, request == PTRACE_KILL);
- if (ret < 0)
- goto out;
-
switch (request) {
/* When I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
@@ -301,13 +275,13 @@ do_sys_ptrace(long request, long pid, long addr, long data,
if (copied != sizeof(tmp))
break;
- regs->r0 = 0; /* special return: no errors */
+ force_successful_syscall_return();
ret = tmp;
break;
/* Read register number ADDR. */
case PTRACE_PEEKUSR:
- regs->r0 = 0; /* special return: no errors */
+ force_successful_syscall_return();
ret = get_reg(child, addr);
DBG(DBG_MEM, ("peek $%ld->%#lx\n", addr, ret));
break;
@@ -353,7 +327,7 @@ do_sys_ptrace(long request, long pid, long addr, long data,
/* make sure single-step breakpoint is gone. */
ptrace_cancel_bpt(child);
wake_up_process(child);
- goto out;
+ break;
case PTRACE_SINGLESTEP: /* execute single instruction. */
ret = -EIO;
@@ -366,20 +340,12 @@ do_sys_ptrace(long request, long pid, long addr, long data,
wake_up_process(child);
/* give it a chance to run. */
ret = 0;
- goto out;
-
- case PTRACE_DETACH: /* detach a process that was attached. */
- ret = ptrace_detach(child, data);
- goto out;
+ break;
default:
ret = ptrace_request(child, request, addr, data);
- goto out;
+ break;
}
- out:
- put_task_struct(child);
- out_notsk:
- unlock_kernel();
return ret;
}
diff --git a/arch/alpha/kernel/semaphore.c b/arch/alpha/kernel/semaphore.c
index 8c8aaa205eae..8d2982aa1b8d 100644
--- a/arch/alpha/kernel/semaphore.c
+++ b/arch/alpha/kernel/semaphore.c
@@ -69,7 +69,7 @@ __down_failed(struct semaphore *sem)
#ifdef CONFIG_DEBUG_SEMAPHORE
printk("%s(%d): down failed(%p)\n",
- tsk->comm, tsk->pid, sem);
+ tsk->comm, task_pid_nr(tsk), sem);
#endif
tsk->state = TASK_UNINTERRUPTIBLE;
@@ -98,7 +98,7 @@ __down_failed(struct semaphore *sem)
#ifdef CONFIG_DEBUG_SEMAPHORE
printk("%s(%d): down acquired(%p)\n",
- tsk->comm, tsk->pid, sem);
+ tsk->comm, task_pid_nr(tsk), sem);
#endif
}
@@ -111,7 +111,7 @@ __down_failed_interruptible(struct semaphore *sem)
#ifdef CONFIG_DEBUG_SEMAPHORE
printk("%s(%d): down failed(%p)\n",
- tsk->comm, tsk->pid, sem);
+ tsk->comm, task_pid_nr(tsk), sem);
#endif
tsk->state = TASK_INTERRUPTIBLE;
@@ -139,7 +139,7 @@ __down_failed_interruptible(struct semaphore *sem)
#ifdef CONFIG_DEBUG_SEMAPHORE
printk("%s(%d): down %s(%p)\n",
- current->comm, current->pid,
+ current->comm, task_pid_nr(current),
(ret < 0 ? "interrupted" : "acquired"), sem);
#endif
return ret;
@@ -168,7 +168,7 @@ down(struct semaphore *sem)
#endif
#ifdef CONFIG_DEBUG_SEMAPHORE
printk("%s(%d): down(%p) <count=%d> from %p\n",
- current->comm, current->pid, sem,
+ current->comm, task_pid_nr(current), sem,
atomic_read(&sem->count), __builtin_return_address(0));
#endif
__down(sem);
@@ -182,7 +182,7 @@ down_interruptible(struct semaphore *sem)
#endif
#ifdef CONFIG_DEBUG_SEMAPHORE
printk("%s(%d): down(%p) <count=%d> from %p\n",
- current->comm, current->pid, sem,
+ current->comm, task_pid_nr(current), sem,
atomic_read(&sem->count), __builtin_return_address(0));
#endif
return __down_interruptible(sem);
@@ -201,7 +201,7 @@ down_trylock(struct semaphore *sem)
#ifdef CONFIG_DEBUG_SEMAPHORE
printk("%s(%d): down_trylock %s from %p\n",
- current->comm, current->pid,
+ current->comm, task_pid_nr(current),
ret ? "failed" : "acquired",
__builtin_return_address(0));
#endif
@@ -217,7 +217,7 @@ up(struct semaphore *sem)
#endif
#ifdef CONFIG_DEBUG_SEMAPHORE
printk("%s(%d): up(%p) <count=%d> from %p\n",
- current->comm, current->pid, sem,
+ current->comm, task_pid_nr(current), sem,
atomic_read(&sem->count), __builtin_return_address(0));
#endif
__up(sem);
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
index ad176441be55..f4ab233201b2 100644
--- a/arch/alpha/kernel/smp.c
+++ b/arch/alpha/kernel/smp.c
@@ -439,7 +439,6 @@ setup_smp(void)
((char *)cpubase + i*hwrpb->processor_size);
if ((cpu->flags & 0x1cc) == 0x1cc) {
smp_num_probed++;
- /* Assume here that "whami" == index */
cpu_set(i, cpu_present_map);
cpu->pal_revision = boot_cpu_palrev;
}
diff --git a/arch/alpha/kernel/sys_alcor.c b/arch/alpha/kernel/sys_alcor.c
index 49bedfbbd31b..d187d01d2a17 100644
--- a/arch/alpha/kernel/sys_alcor.c
+++ b/arch/alpha/kernel/sys_alcor.c
@@ -138,7 +138,7 @@ alcor_init_irq(void)
for (i = 16; i < 48; ++i) {
/* On Alcor, at least, lines 20..30 are not connected
- and can generate spurrious interrupts if we turn them
+ and can generate spurious interrupts if we turn them
on while IRQ probing. */
if (i >= 16+20 && i <= 16+30)
continue;
diff --git a/arch/alpha/kernel/sys_sio.c b/arch/alpha/kernel/sys_sio.c
index 14b5a753aba5..ee7b9009ebb4 100644
--- a/arch/alpha/kernel/sys_sio.c
+++ b/arch/alpha/kernel/sys_sio.c
@@ -78,7 +78,7 @@ alphabook1_init_arch(void)
* example, sound boards seem to like using IRQ 9.
*
* This is NOT how we should do it. PIRQ0-X should have
- * their own IRQ's, the way intel uses the IO-APIC irq's.
+ * their own IRQs, the way intel uses the IO-APIC IRQs.
*/
static void __init
diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c
index ec0f05e0d8ff..2dc7f9fed213 100644
--- a/arch/alpha/kernel/traps.c
+++ b/arch/alpha/kernel/traps.c
@@ -182,7 +182,7 @@ die_if_kernel(char * str, struct pt_regs *regs, long err, unsigned long *r9_15)
#ifdef CONFIG_SMP
printk("CPU %d ", hard_smp_processor_id());
#endif
- printk("%s(%d): %s %ld\n", current->comm, current->pid, str, err);
+ printk("%s(%d): %s %ld\n", current->comm, task_pid_nr(current), str, err);
dik_show_regs(regs, r9_15);
add_taint(TAINT_DIE);
dik_show_trace((unsigned long *)(regs+1));
@@ -646,7 +646,7 @@ got_exception:
lock_kernel();
printk("%s(%d): unhandled unaligned exception\n",
- current->comm, current->pid);
+ current->comm, task_pid_nr(current));
printk("pc = [<%016lx>] ra = [<%016lx>] ps = %04lx\n",
pc, una_reg(26), regs->ps);
@@ -786,7 +786,7 @@ do_entUnaUser(void __user * va, unsigned long opcode,
}
if (++cnt < 5) {
printk("%s(%d): unaligned trap at %016lx: %p %lx %ld\n",
- current->comm, current->pid,
+ current->comm, task_pid_nr(current),
regs->pc - 4, va, opcode, reg);
}
last_time = jiffies;
diff --git a/arch/alpha/kernel/vmlinux.lds.S b/arch/alpha/kernel/vmlinux.lds.S
index 7af07d3ad5f0..55c05b511f4c 100644
--- a/arch/alpha/kernel/vmlinux.lds.S
+++ b/arch/alpha/kernel/vmlinux.lds.S
@@ -1,4 +1,5 @@
#include <asm-generic/vmlinux.lds.h>
+#include <asm/page.h>
OUTPUT_FORMAT("elf64-alpha")
OUTPUT_ARCH(alpha)
@@ -8,138 +9,145 @@ jiffies = jiffies_64;
SECTIONS
{
#ifdef CONFIG_ALPHA_LEGACY_START_ADDRESS
- . = 0xfffffc0000310000;
+ . = 0xfffffc0000310000;
#else
- . = 0xfffffc0001010000;
+ . = 0xfffffc0001010000;
#endif
- _text = .; /* Text and read-only data */
- .text : {
+ _text = .; /* Text and read-only data */
+ .text : {
*(.text.head)
- TEXT_TEXT
- SCHED_TEXT
- LOCK_TEXT
- *(.fixup)
- *(.gnu.warning)
- } :kernel
- _etext = .; /* End of text section */
-
- . = ALIGN(16);
- __start___ex_table = .; /* Exception table */
- __ex_table : { *(__ex_table) }
- __stop___ex_table = .;
-
- NOTES :kernel :note
- .dummy : { *(.dummy) } :kernel
-
- RODATA
-
- /* Will be freed after init */
- . = ALIGN(8192); /* Init code and data */
- __init_begin = .;
- .init.text : {
- _sinittext = .;
- *(.init.text)
- _einittext = .;
- }
- .init.data : { *(.init.data) }
-
- . = ALIGN(16);
- __setup_start = .;
- .init.setup : { *(.init.setup) }
- __setup_end = .;
-
- . = ALIGN(8);
- __initcall_start = .;
- .initcall.init : {
- INITCALLS
- }
- __initcall_end = .;
+ TEXT_TEXT
+ SCHED_TEXT
+ LOCK_TEXT
+ *(.fixup)
+ *(.gnu.warning)
+ } :kernel
+ _etext = .; /* End of text section */
+
+ /* Exception table */
+ . = ALIGN(16);
+ __ex_table : {
+ __start___ex_table = .;
+ *(__ex_table)
+ __stop___ex_table = .;
+ }
+
+ NOTES :kernel :note
+ .dummy : {
+ *(.dummy)
+ } :kernel
+
+ RODATA
+
+ /* Will be freed after init */
+ . = ALIGN(PAGE_SIZE);
+ /* Init code and data */
+ __init_begin = .;
+ .init.text : {
+ _sinittext = .;
+ *(.init.text)
+ _einittext = .;
+ }
+ .init.data : {
+ *(.init.data)
+ }
+
+ . = ALIGN(16);
+ .init.setup : {
+ __setup_start = .;
+ *(.init.setup)
+ __setup_end = .;
+ }
+
+ . = ALIGN(8);
+ .initcall.init : {
+ __initcall_start = .;
+ INITCALLS
+ __initcall_end = .;
+ }
#ifdef CONFIG_BLK_DEV_INITRD
- . = ALIGN(8192);
- __initramfs_start = .;
- .init.ramfs : { *(.init.ramfs) }
- __initramfs_end = .;
+ . = ALIGN(PAGE_SIZE);
+ .init.ramfs : {
+ __initramfs_start = .;
+ *(.init.ramfs)
+ __initramfs_end = .;
+ }
#endif
- . = ALIGN(8);
- .con_initcall.init : {
- __con_initcall_start = .;
- *(.con_initcall.init)
- __con_initcall_end = .;
- }
-
- . = ALIGN(8);
- SECURITY_INIT
-
- PERCPU(8192)
-
- . = ALIGN(2*8192);
- __init_end = .;
- /* Freed after init ends here */
-
- /* Note 2 page alignment above. */
- .data.init_thread : { *(.data.init_thread) }
-
- . = ALIGN(8192);
- .data.page_aligned : { *(.data.page_aligned) }
-
- . = ALIGN(64);
- .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-
- _data = .;
- .data : { /* Data */
- DATA_DATA
- CONSTRUCTORS
- }
-
- .got : { *(.got) }
- .sdata : { *(.sdata) }
-
- _edata = .; /* End of data section */
-
- __bss_start = .;
- .sbss : { *(.sbss) *(.scommon) }
- .bss : { *(.bss) *(COMMON) }
- __bss_stop = .;
-
- _end = .;
-
- /* Sections to be discarded */
- /DISCARD/ : { *(.exit.text) *(.exit.data) *(.exitcall.exit) }
-
- .mdebug 0 : { *(.mdebug) }
- .note 0 : { *(.note) }
- .comment 0 : { *(.comment) }
-
- /* Stabs debugging sections */
- .stab 0 : { *(.stab) }
- .stabstr 0 : { *(.stabstr) }
- .stab.excl 0 : { *(.stab.excl) }
- .stab.exclstr 0 : { *(.stab.exclstr) }
- .stab.index 0 : { *(.stab.index) }
- .stab.indexstr 0 : { *(.stab.indexstr) }
- /* DWARF 1 */
- .debug 0 : { *(.debug) }
- .line 0 : { *(.line) }
- /* GNU DWARF 1 extensions */
- .debug_srcinfo 0 : { *(.debug_srcinfo) }
- .debug_sfnames 0 : { *(.debug_sfnames) }
- /* DWARF 1.1 and DWARF 2 */
- .debug_aranges 0 : { *(.debug_aranges) }
- .debug_pubnames 0 : { *(.debug_pubnames) }
- /* DWARF 2 */
- .debug_info 0 : { *(.debug_info) }
- .debug_abbrev 0 : { *(.debug_abbrev) }
- .debug_line 0 : { *(.debug_line) }
- .debug_frame 0 : { *(.debug_frame) }
- .debug_str 0 : { *(.debug_str) }
- .debug_loc 0 : { *(.debug_loc) }
- .debug_macinfo 0 : { *(.debug_macinfo) }
- /* SGI/MIPS DWARF 2 extensions */
- .debug_weaknames 0 : { *(.debug_weaknames) }
- .debug_funcnames 0 : { *(.debug_funcnames) }
- .debug_typenames 0 : { *(.debug_typenames) }
- .debug_varnames 0 : { *(.debug_varnames) }
+ . = ALIGN(8);
+ .con_initcall.init : {
+ __con_initcall_start = .;
+ *(.con_initcall.init)
+ __con_initcall_end = .;
+ }
+
+ . = ALIGN(8);
+ SECURITY_INIT
+
+ PERCPU(PAGE_SIZE)
+
+ . = ALIGN(2 * PAGE_SIZE);
+ __init_end = .;
+ /* Freed after init ends here */
+
+ /* Note 2 page alignment above. */
+ .data.init_thread : {
+ *(.data.init_thread)
+ }
+
+ . = ALIGN(PAGE_SIZE);
+ .data.page_aligned : {
+ *(.data.page_aligned)
+ }
+
+ . = ALIGN(64);
+ .data.cacheline_aligned : {
+ *(.data.cacheline_aligned)
+ }
+
+ _data = .;
+ /* Data */
+ .data : {
+ DATA_DATA
+ CONSTRUCTORS
+ }
+
+ .got : {
+ *(.got)
+ }
+ .sdata : {
+ *(.sdata)
+ }
+ _edata = .; /* End of data section */
+
+ __bss_start = .;
+ .sbss : {
+ *(.sbss)
+ *(.scommon)
+ }
+ .bss : {
+ *(.bss)
+ *(COMMON)
+ }
+ __bss_stop = .;
+ _end = .;
+
+ /* Sections to be discarded */
+ /DISCARD/ : {
+ *(.exit.text)
+ *(.exit.data)
+ *(.exitcall.exit)
+ }
+
+ .mdebug 0 : {
+ *(.mdebug)
+ }
+ .note 0 : {
+ *(.note)
+ }
+
+ STABS_DEBUG
+ DWARF_DEBUG
}
diff --git a/arch/alpha/lib/Makefile b/arch/alpha/lib/Makefile
index 266f78e13076..9b72c59c95be 100644
--- a/arch/alpha/lib/Makefile
+++ b/arch/alpha/lib/Makefile
@@ -2,7 +2,7 @@
# Makefile for alpha-specific library files..
#
-EXTRA_AFLAGS := $(CFLAGS)
+EXTRA_AFLAGS := $(KBUILD_CFLAGS)
EXTRA_CFLAGS := -Werror
# Many of these routines have implementations tuned for ev6.
diff --git a/arch/alpha/lib/checksum.c b/arch/alpha/lib/checksum.c
index 8698e0746f9f..199f6efa83fa 100644
--- a/arch/alpha/lib/checksum.c
+++ b/arch/alpha/lib/checksum.c
@@ -5,7 +5,7 @@
* in an architecture-specific manner due to speed..
* Comments in other versions indicate that the algorithms are from RFC1071
*
- * accellerated versions (and 21264 assembly versions ) contributed by
+ * accelerated versions (and 21264 assembly versions ) contributed by
* Rick Gorton <rick.gorton@alpha-processor.com>
*/
diff --git a/arch/alpha/lib/csum_partial_copy.c b/arch/alpha/lib/csum_partial_copy.c
index 4ca75c74ce90..40736da9bea8 100644
--- a/arch/alpha/lib/csum_partial_copy.c
+++ b/arch/alpha/lib/csum_partial_copy.c
@@ -2,7 +2,7 @@
* csum_partial_copy - do IP checksumming and copy
*
* (C) Copyright 1996 Linus Torvalds
- * accellerated versions (and 21264 assembly versions ) contributed by
+ * accelerated versions (and 21264 assembly versions ) contributed by
* Rick Gorton <rick.gorton@alpha-processor.com>
*
* Don't look at this too closely - you'll go mad. The things
diff --git a/arch/alpha/lib/fls.c b/arch/alpha/lib/fls.c
index 7ad84ea0acf8..32afaa3fa686 100644
--- a/arch/alpha/lib/fls.c
+++ b/arch/alpha/lib/fls.c
@@ -3,7 +3,7 @@
*/
#include <linux/module.h>
-#include <asm/bitops.h>
+#include <linux/bitops.h>
/* This is fls(x)-1, except zero is held to zero. This allows most
efficent input into extbl, plus it allows easy handling of fls(0)=0. */
diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c
index a0e18da594d9..4829f96585b1 100644
--- a/arch/alpha/mm/fault.c
+++ b/arch/alpha/mm/fault.c
@@ -188,16 +188,16 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
/* We ran out of memory, or some other thing happened to us that
made us unable to handle the page fault gracefully. */
out_of_memory:
- if (is_init(current)) {
+ if (is_global_init(current)) {
yield();
down_read(&mm->mmap_sem);
goto survive;
}
printk(KERN_ALERT "VM: killing process %s(%d)\n",
- current->comm, current->pid);
+ current->comm, task_pid_nr(current));
if (!user_mode(regs))
goto no_context;
- do_exit(SIGKILL);
+ do_group_exit(SIGKILL);
do_sigbus:
/* Send a sigbus, regardless of whether we were in kernel
diff --git a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c
index 5e6da47779a4..40c15e7301de 100644
--- a/arch/alpha/mm/init.c
+++ b/arch/alpha/mm/init.c
@@ -235,7 +235,7 @@ callback_init(void * kernel_end)
unsigned long pfn = crb->map[i].pa >> PAGE_SHIFT;
crb->map[i].va = vaddr;
for (j = 0; j < crb->map[i].count; ++j) {
- /* Newer console's (especially on larger
+ /* Newer consoles (especially on larger
systems) may require more pages of
PTEs. Grab additional pages as needed. */
if (pmd != pmd_offset(pgd, vaddr)) {
diff --git a/arch/alpha/oprofile/Kconfig b/arch/alpha/oprofile/Kconfig
deleted file mode 100644
index 5ade19801b97..000000000000
--- a/arch/alpha/oprofile/Kconfig
+++ /dev/null
@@ -1,23 +0,0 @@
-
-menu "Profiling support"
- depends on EXPERIMENTAL
-
-config PROFILING
- bool "Profiling support (EXPERIMENTAL)"
- help
- Say Y here to enable the extended profiling support mechanisms used
- by profilers such as OProfile.
-
-
-config OPROFILE
- tristate "OProfile system profiling (EXPERIMENTAL)"
- depends on PROFILING
- help
- OProfile is a profiling system capable of profiling the
- whole system, include the kernel, kernel modules, libraries,
- and applications.
-
- If unsure, say N.
-
-endmenu
-
diff --git a/arch/alpha/oprofile/op_impl.h b/arch/alpha/oprofile/op_impl.h
index 6b97893c1a80..b2b87ae9a353 100644
--- a/arch/alpha/oprofile/op_impl.h
+++ b/arch/alpha/oprofile/op_impl.h
@@ -38,7 +38,7 @@ struct op_register_config {
unsigned long need_reset;
};
-/* Per-architecture configury and hooks. */
+/* Per-architecture configuration and hooks. */
struct op_axp_model {
void (*reg_setup) (struct op_register_config *,
struct op_counter_config *,
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 691aae309c8a..a7e9fea978a6 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -318,6 +318,9 @@ config ARCH_KS8695
config ARCH_NS9XXX
bool "NetSilicon NS9xxx"
+ select GENERIC_GPIO
+ select GENERIC_TIME
+ select GENERIC_CLOCKEVENTS
help
Say Y here if you intend to run this kernel on a NetSilicon NS9xxx
System.
@@ -336,14 +339,14 @@ config ARCH_PNX4008
This enables support for Philips PNX4008 mobile platform.
config ARCH_PXA
- bool "PXA2xx-based"
+ bool "PXA2xx/PXA3xx-based"
depends on MMU
select ARCH_MTD_XIP
select GENERIC_GPIO
select GENERIC_TIME
select GENERIC_CLOCKEVENTS
help
- Support for Intel's PXA2XX processor line.
+ Support for Intel/Marvell's PXA2xx/PXA3xx processor line.
config ARCH_RPC
bool "RiscPC"
@@ -486,7 +489,7 @@ source arch/arm/mm/Kconfig
config IWMMXT
bool "Enable iWMMXt support"
depends on CPU_XSCALE || CPU_XSC3
- default y if PXA27x
+ default y if PXA27x || PXA3xx
help
Enable support for iWMMXt context switching at run time if
running on a CPU that supports it.
@@ -848,7 +851,7 @@ config KEXEC
help
kexec is a system call that implements the ability to shutdown your
current kernel, and to start another kernel. It is like a reboot
- but it is indepedent of the system firmware. And like a reboot
+ but it is independent of the system firmware. And like a reboot
you can start any kernel with it, not just Linux.
It is an ongoing process to be certain the hardware in a machine
@@ -994,6 +997,10 @@ source "drivers/pnp/Kconfig"
source "drivers/block/Kconfig"
+# misc before ide - BLK_DEV_SGIIOC4 depends on SGI_IOC4
+
+source "drivers/misc/Kconfig"
+
if PCMCIA || ARCH_CLPS7500 || ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX \
|| ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC \
|| ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE \
@@ -1029,15 +1036,17 @@ source "drivers/spi/Kconfig"
source "drivers/w1/Kconfig"
+source "drivers/power/Kconfig"
+
source "drivers/hwmon/Kconfig"
-#source "drivers/l3/Kconfig"
+source "drivers/watchdog/Kconfig"
-source "drivers/misc/Kconfig"
+source "drivers/ssb/Kconfig"
-source "drivers/mfd/Kconfig"
+#source "drivers/l3/Kconfig"
-source "drivers/leds/Kconfig"
+source "drivers/mfd/Kconfig"
source "drivers/media/Kconfig"
@@ -1051,6 +1060,8 @@ source "drivers/usb/Kconfig"
source "drivers/mmc/Kconfig"
+source "drivers/leds/Kconfig"
+
source "drivers/rtc/Kconfig"
source "drivers/dma/Kconfig"
@@ -1059,7 +1070,7 @@ endmenu
source "fs/Kconfig"
-source "arch/arm/oprofile/Kconfig"
+source "kernel/Kconfig.instrumentation"
source "arch/arm/Kconfig.debug"
diff --git a/arch/arm/Kconfig-nommu b/arch/arm/Kconfig-nommu
index f087376748d1..901e6dff8437 100644
--- a/arch/arm/Kconfig-nommu
+++ b/arch/arm/Kconfig-nommu
@@ -26,7 +26,7 @@ config FLASH_SIZE
default 0x00400000
config PROCESSOR_ID
- hex
+ hex 'Hard wire the processor ID'
default 0x00007700
depends on !CPU_CP15
help
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index fa4ea9ff0797..35e56c99ad1d 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -12,11 +12,11 @@
LDFLAGS_vmlinux :=-p --no-undefined -X
CPPFLAGS_vmlinux.lds = -DTEXT_OFFSET=$(TEXT_OFFSET)
-OBJCOPYFLAGS :=-O binary -R .note -R .comment -S
+OBJCOPYFLAGS :=-O binary -R .note -R .note.gnu.build-id -R .comment -S
GZFLAGS :=-9
-#CFLAGS +=-pipe
+#KBUILD_CFLAGS +=-pipe
# Explicitly specifiy 32-bit ARM ISA since toolchain default can be -mthumb:
-CFLAGS +=$(call cc-option,-marm,)
+KBUILD_CFLAGS +=$(call cc-option,-marm,)
# Do not use arch/arm/defconfig - it's always outdated.
# Select a platform tht is kept up-to-date
@@ -28,15 +28,15 @@ MMUEXT := -nommu
endif
ifeq ($(CONFIG_FRAME_POINTER),y)
-CFLAGS +=-fno-omit-frame-pointer -mapcs -mno-sched-prolog
+KBUILD_CFLAGS +=-fno-omit-frame-pointer -mapcs -mno-sched-prolog
endif
ifeq ($(CONFIG_CPU_BIG_ENDIAN),y)
-CPPFLAGS += -mbig-endian
+KBUILD_CPPFLAGS += -mbig-endian
AS += -EB
LD += -EB
else
-CPPFLAGS += -mlittle-endian
+KBUILD_CPPFLAGS += -mlittle-endian
AS += -EL
LD += -EL
endif
@@ -85,8 +85,8 @@ CFLAGS_ABI :=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) $(call cc-option,-mno-th
endif
# Need -Uarm for gcc < 3.x
-CFLAGS +=$(CFLAGS_ABI) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm
-AFLAGS +=$(CFLAGS_ABI) $(arch-y) $(tune-y) -msoft-float
+KBUILD_CFLAGS +=$(CFLAGS_ABI) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm
+KBUILD_AFLAGS +=$(CFLAGS_ABI) $(arch-y) $(tune-y) -msoft-float
CHECKFLAGS += -D__arm__
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 6b8cbd69f249..5fde99f9d9f9 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -87,7 +87,7 @@ ifneq ($(PARAMS_PHYS),)
LDFLAGS_vmlinux += --defsym params_phys=$(PARAMS_PHYS)
endif
LDFLAGS_vmlinux += -p --no-undefined -X \
- $(shell $(CC) $(CFLAGS) --print-libgcc-file-name) -T
+ $(shell $(CC) $(KBUILD_CFLAGS) --print-libgcc-file-name) -T
# Don't allow any static data in misc.o, which
# would otherwise mess up our GOT table
diff --git a/arch/arm/boot/compressed/head-xscale.S b/arch/arm/boot/compressed/head-xscale.S
index 236bbe578312..67ea99ef6521 100644
--- a/arch/arm/boot/compressed/head-xscale.S
+++ b/arch/arm/boot/compressed/head-xscale.S
@@ -33,10 +33,6 @@ __XScale_start:
bic r0, r0, #0x1000 @ clear Icache
mcr p15, 0, r0, c1, c0, 0
-#ifdef CONFIG_ARCH_LUBBOCK
- mov r7, #MACH_TYPE_LUBBOCK
-#endif
-
#ifdef CONFIG_ARCH_COTULLA_IDP
mov r7, #MACH_TYPE_COTULLA_IDP
#endif
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index e1289a256ce5..3d0b9fa42f84 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -17,3 +17,4 @@ obj-$(CONFIG_SHARPSL_PM) += sharpsl_pm.o
obj-$(CONFIG_SHARP_SCOOP) += scoop.o
obj-$(CONFIG_ARCH_IXP2000) += uengine.o
obj-$(CONFIG_ARCH_IXP23XX) += uengine.o
+obj-$(CONFIG_PCI_HOST_ITE8152) += it8152.o
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index b36b1e8a105d..52fc6a883281 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -29,6 +29,7 @@
#include <linux/dma-mapping.h>
#include <linux/dmapool.h>
#include <linux/list.h>
+#include <linux/scatterlist.h>
#include <asm/cacheflush.h>
@@ -263,7 +264,7 @@ map_single(struct device *dev, void *ptr, size_t size,
* We don't need to sync the DMA buffer since
* it was allocated via the coherent allocators.
*/
- consistent_sync(ptr, size, dir);
+ dma_cache_maint(ptr, size, dir);
}
return dma_addr;
@@ -383,7 +384,7 @@ sync_single(struct device *dev, dma_addr_t dma_addr, size_t size,
* via the coherent allocators.
*/
} else {
- consistent_sync(dma_to_virt(dev, dma_addr), size, dir);
+ dma_cache_maint(dma_to_virt(dev, dma_addr), size, dir);
}
}
@@ -442,7 +443,7 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
BUG_ON(dir == DMA_NONE);
for (i = 0; i < nents; i++, sg++) {
- struct page *page = sg->page;
+ struct page *page = sg_page(sg);
unsigned int offset = sg->offset;
unsigned int length = sg->length;
void *ptr = page_address(page) + offset;
diff --git a/arch/arm/common/it8152.c b/arch/arm/common/it8152.c
new file mode 100644
index 000000000000..c03de9bfd76b
--- /dev/null
+++ b/arch/arm/common/it8152.c
@@ -0,0 +1,387 @@
+/*
+ * linux/arch/arm/common/it8152.c
+ *
+ * Copyright Compulab Ltd, 2002-2007
+ * Mike Rapoport <mike@compulab.co.il>
+ *
+ * The DMA bouncing part is taken from arch/arm/mach-ixp4xx/common-pci.c
+ * (see this file for respective copyrights)
+ *
+ * Thanks to Guennadi Liakhovetski <gl@dsa-ac.de> for IRQ enumberation
+ * and demux code.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/ptrace.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <asm/mach/pci.h>
+#include <asm/hardware/it8152.h>
+
+#define MAX_SLOTS 21
+
+static void it8152_mask_irq(unsigned int irq)
+{
+ if (irq >= IT8152_LD_IRQ(0)) {
+ __raw_writel((__raw_readl(IT8152_INTC_LDCNIMR) |
+ (1 << (irq - IT8152_LD_IRQ(0)))),
+ IT8152_INTC_LDCNIMR);
+ } else if (irq >= IT8152_LP_IRQ(0)) {
+ __raw_writel((__raw_readl(IT8152_INTC_LPCNIMR) |
+ (1 << (irq - IT8152_LP_IRQ(0)))),
+ IT8152_INTC_LPCNIMR);
+ } else if (irq >= IT8152_PD_IRQ(0)) {
+ __raw_writel((__raw_readl(IT8152_INTC_PDCNIMR) |
+ (1 << (irq - IT8152_PD_IRQ(0)))),
+ IT8152_INTC_PDCNIMR);
+ }
+}
+
+static void it8152_unmask_irq(unsigned int irq)
+{
+ if (irq >= IT8152_LD_IRQ(0)) {
+ __raw_writel((__raw_readl(IT8152_INTC_LDCNIMR) &
+ ~(1 << (irq - IT8152_LD_IRQ(0)))),
+ IT8152_INTC_LDCNIMR);
+ } else if (irq >= IT8152_LP_IRQ(0)) {
+ __raw_writel((__raw_readl(IT8152_INTC_LPCNIMR) &
+ ~(1 << (irq - IT8152_LP_IRQ(0)))),
+ IT8152_INTC_LPCNIMR);
+ } else if (irq >= IT8152_PD_IRQ(0)) {
+ __raw_writel((__raw_readl(IT8152_INTC_PDCNIMR) &
+ ~(1 << (irq - IT8152_PD_IRQ(0)))),
+ IT8152_INTC_PDCNIMR);
+ }
+}
+
+static inline void it8152_irq(int irq)
+{
+ struct irq_desc *desc;
+
+ printk(KERN_DEBUG "===> %s: irq=%d\n", __FUNCTION__, irq);
+
+ desc = irq_desc + irq;
+ desc_handle_irq(irq, desc);
+}
+
+static struct irq_chip it8152_irq_chip = {
+ .name = "it8152",
+ .ack = it8152_mask_irq,
+ .mask = it8152_mask_irq,
+ .unmask = it8152_unmask_irq,
+};
+
+void it8152_init_irq(void)
+{
+ int irq;
+
+ __raw_writel((0xffff), IT8152_INTC_PDCNIMR);
+ __raw_writel((0), IT8152_INTC_PDCNIRR);
+ __raw_writel((0xffff), IT8152_INTC_LPCNIMR);
+ __raw_writel((0), IT8152_INTC_LPCNIRR);
+ __raw_writel((0xffff), IT8152_INTC_LDCNIMR);
+ __raw_writel((0), IT8152_INTC_LDCNIRR);
+
+ for (irq = IT8152_IRQ(0); irq <= IT8152_LAST_IRQ; irq++) {
+ set_irq_chip(irq, &it8152_irq_chip);
+ set_irq_handler(irq, handle_level_irq);
+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+ }
+}
+
+void it8152_irq_demux(unsigned int irq, struct irq_desc *desc)
+{
+ int bits_pd, bits_lp, bits_ld;
+ int i;
+
+ printk(KERN_DEBUG "=> %s: irq = %d\n", __FUNCTION__, irq);
+
+ while (1) {
+ /* Read all */
+ bits_pd = __raw_readl(IT8152_INTC_PDCNIRR);
+ bits_lp = __raw_readl(IT8152_INTC_LPCNIRR);
+ bits_ld = __raw_readl(IT8152_INTC_LDCNIRR);
+
+ /* Ack */
+ __raw_writel((~bits_pd), IT8152_INTC_PDCNIRR);
+ __raw_writel((~bits_lp), IT8152_INTC_LPCNIRR);
+ __raw_writel((~bits_ld), IT8152_INTC_LDCNIRR);
+
+ if (!(bits_ld | bits_lp | bits_pd)) {
+ /* Re-read to guarantee, that there was a moment of
+ time, when they all three were 0. */
+ bits_pd = __raw_readl(IT8152_INTC_PDCNIRR);
+ bits_lp = __raw_readl(IT8152_INTC_LPCNIRR);
+ if (!(bits_ld | bits_lp | bits_pd))
+ return;
+ }
+
+ bits_pd &= ((1 << IT8152_PD_IRQ_COUNT) - 1);
+ while (bits_pd) {
+ i = __ffs(bits_pd);
+ it8152_irq(IT8152_PD_IRQ(i));
+ bits_pd &= ~(1 << i);
+ }
+
+ bits_lp &= ((1 << IT8152_LP_IRQ_COUNT) - 1);
+ while (bits_lp) {
+ i = __ffs(bits_pd);
+ it8152_irq(IT8152_LP_IRQ(i));
+ bits_lp &= ~(1 << i);
+ }
+
+ bits_ld &= ((1 << IT8152_LD_IRQ_COUNT) - 1);
+ while (bits_ld) {
+ i = __ffs(bits_pd);
+ it8152_irq(IT8152_LD_IRQ(i));
+ bits_ld &= ~(1 << i);
+ }
+ }
+}
+
+/* mapping for on-chip devices */
+int __init it8152_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ if ((dev->vendor == PCI_VENDOR_ID_ITE) &&
+ (dev->device == PCI_DEVICE_ID_ITE_8152)) {
+ if ((dev->class >> 8) == PCI_CLASS_MULTIMEDIA_AUDIO)
+ return IT8152_AUDIO_INT;
+ if ((dev->class >> 8) == PCI_CLASS_SERIAL_USB)
+ return IT8152_USB_INT;
+ if ((dev->class >> 8) == PCI_CLASS_SYSTEM_DMA)
+ return IT8152_CDMA_INT;
+ }
+
+ return 0;
+}
+
+static unsigned long it8152_pci_dev_base_address(struct pci_bus *bus,
+ unsigned int devfn)
+{
+ unsigned long addr = 0;
+
+ if (bus->number == 0) {
+ if (devfn < PCI_DEVFN(MAX_SLOTS, 0))
+ addr = (devfn << 8);
+ } else
+ addr = (bus->number << 16) | (devfn << 8);
+
+ return addr;
+}
+
+static int it8152_pci_read_config(struct pci_bus *bus,
+ unsigned int devfn, int where,
+ int size, u32 *value)
+{
+ unsigned long addr = it8152_pci_dev_base_address(bus, devfn);
+ u32 v;
+ int shift;
+
+ shift = (where & 3);
+
+ __raw_writel((addr + where), IT8152_PCI_CFG_ADDR);
+ v = (__raw_readl(IT8152_PCI_CFG_DATA) >> (8 * (shift)));
+
+ *value = v;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int it8152_pci_write_config(struct pci_bus *bus,
+ unsigned int devfn, int where,
+ int size, u32 value)
+{
+ unsigned long addr = it8152_pci_dev_base_address(bus, devfn);
+ u32 v, vtemp, mask = 0;
+ int shift;
+
+ if (size == 1)
+ mask = 0xff;
+ if (size == 2)
+ mask = 0xffff;
+
+ shift = (where & 3);
+
+ __raw_writel((addr + where), IT8152_PCI_CFG_ADDR);
+ vtemp = __raw_readl(IT8152_PCI_CFG_DATA);
+
+ if (mask)
+ vtemp &= ~(mask << (8 * shift));
+ else
+ vtemp = 0;
+
+ v = (value << (8 * shift));
+ __raw_writel((addr + where), IT8152_PCI_CFG_ADDR);
+ __raw_writel((v | vtemp), IT8152_PCI_CFG_DATA);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops it8152_ops = {
+ .read = it8152_pci_read_config,
+ .write = it8152_pci_write_config,
+};
+
+static struct resource it8152_io = {
+ .name = "IT8152 PCI I/O region",
+ .flags = IORESOURCE_IO,
+};
+
+static struct resource it8152_mem = {
+ .name = "IT8152 PCI memory region",
+ .start = 0x10000000,
+ .end = 0x13e00000,
+ .flags = IORESOURCE_MEM,
+};
+
+/*
+ * The following functions are needed for DMA bouncing.
+ * ITE8152 chip can addrees up to 64MByte, so all the devices
+ * connected to ITE8152 (PCI and USB) should have limited DMA window
+ */
+
+/*
+ * Setup DMA mask to 64MB on devices connected to ITE8152. Ignore all
+ * other devices.
+ */
+static int it8152_pci_platform_notify(struct device *dev)
+{
+ if (dev->bus == &pci_bus_type) {
+ if (dev->dma_mask)
+ *dev->dma_mask = (SZ_64M - 1) | PHYS_OFFSET;
+ dev->coherent_dma_mask = (SZ_64M - 1) | PHYS_OFFSET;
+ dmabounce_register_dev(dev, 2048, 4096);
+ }
+ return 0;
+}
+
+static int it8152_pci_platform_notify_remove(struct device *dev)
+{
+ if (dev->bus == &pci_bus_type)
+ dmabounce_unregister_dev(dev);
+
+ return 0;
+}
+
+int dma_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size)
+{
+ dev_dbg(dev, "%s: dma_addr %08x, size %08x\n",
+ __FUNCTION__, dma_addr, size);
+ return (dev->bus == &pci_bus_type) &&
+ ((dma_addr + size - PHYS_OFFSET) >= SZ_64M);
+}
+
+/*
+ * We override these so we properly do dmabounce otherwise drivers
+ * are able to set the dma_mask to 0xffffffff and we can no longer
+ * trap bounces. :(
+ *
+ * We just return true on everyhing except for < 64MB in which case
+ * we will fail miseralby and die since we can't handle that case.
+ */
+int pci_set_dma_mask(struct pci_dev *dev, u64 mask)
+{
+ printk(KERN_DEBUG "%s: %s %llx\n",
+ __FUNCTION__, dev->dev.bus_id, mask);
+ if (mask >= PHYS_OFFSET + SZ_64M - 1)
+ return 0;
+
+ return -EIO;
+}
+
+int
+pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
+{
+ printk(KERN_DEBUG "%s: %s %llx\n",
+ __FUNCTION__, dev->dev.bus_id, mask);
+ if (mask >= PHYS_OFFSET + SZ_64M - 1)
+ return 0;
+
+ return -EIO;
+}
+
+int __init it8152_pci_setup(int nr, struct pci_sys_data *sys)
+{
+ it8152_io.start = IT8152_IO_BASE + 0x12000;
+ it8152_io.end = IT8152_IO_BASE + 0x12000 + 0x100000;
+
+ sys->mem_offset = 0x10000000;
+ sys->io_offset = IT8152_IO_BASE;
+
+ if (request_resource(&ioport_resource, &it8152_io)) {
+ printk(KERN_ERR "PCI: unable to allocate IO region\n");
+ goto err0;
+ }
+ if (request_resource(&iomem_resource, &it8152_mem)) {
+ printk(KERN_ERR "PCI: unable to allocate memory region\n");
+ goto err1;
+ }
+
+ sys->resource[0] = &it8152_io;
+ sys->resource[1] = &it8152_mem;
+
+ if (platform_notify || platform_notify_remove) {
+ printk(KERN_ERR "PCI: Can't use platform_notify\n");
+ goto err2;
+ }
+
+ platform_notify = it8152_pci_platform_notify;
+ platform_notify_remove = it8152_pci_platform_notify_remove;
+
+ return 1;
+
+err2:
+ release_resource(&it8152_io);
+err1:
+ release_resource(&it8152_mem);
+err0:
+ return -EBUSY;
+}
+
+/*
+ * If we set up a device for bus mastering, we need to check the latency
+ * timer as we don't have even crappy BIOSes to set it properly.
+ * The implementation is from arch/i386/pci/i386.c
+ */
+unsigned int pcibios_max_latency = 255;
+
+void pcibios_set_master(struct pci_dev *dev)
+{
+ u8 lat;
+
+ /* no need to update on-chip OHCI controller */
+ if ((dev->vendor == PCI_VENDOR_ID_ITE) &&
+ (dev->device == PCI_DEVICE_ID_ITE_8152) &&
+ ((dev->class >> 8) == PCI_CLASS_SERIAL_USB))
+ return;
+
+ pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
+ if (lat < 16)
+ lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
+ else if (lat > pcibios_max_latency)
+ lat = pcibios_max_latency;
+ else
+ return;
+ printk(KERN_DEBUG "PCI: Setting latency timer of device %s to %d\n",
+ pci_name(dev), lat);
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
+}
+
+
+struct pci_bus * __init it8152_pci_scan_bus(int nr, struct pci_sys_data *sys)
+{
+ return pci_scan_bus(nr, &it8152_ops, sys);
+}
+
diff --git a/arch/arm/common/sharpsl_pm.c b/arch/arm/common/sharpsl_pm.c
index 111a7fa5debe..5bba5255b119 100644
--- a/arch/arm/common/sharpsl_pm.c
+++ b/arch/arm/common/sharpsl_pm.c
@@ -24,6 +24,7 @@
#include <linux/platform_device.h>
#include <linux/leds.h>
#include <linux/apm-emulation.h>
+#include <linux/suspend.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
@@ -765,9 +766,9 @@ static void sharpsl_apm_get_power_status(struct apm_power_info *info)
info->battery_life = sharpsl_pm.battstat.mainbat_percent;
}
-static struct pm_ops sharpsl_pm_ops = {
+static struct platform_suspend_ops sharpsl_pm_ops = {
.enter = corgi_pxa_pm_enter,
- .valid = pm_valid_only_mem,
+ .valid = suspend_valid_only_mem,
};
static int __init sharpsl_pm_probe(struct platform_device *pdev)
@@ -799,7 +800,7 @@ static int __init sharpsl_pm_probe(struct platform_device *pdev)
apm_get_power_status = sharpsl_apm_get_power_status;
- pm_set_ops(&sharpsl_pm_ops);
+ suspend_set_ops(&sharpsl_pm_ops);
mod_timer(&sharpsl_pm.ac_timer, jiffies + msecs_to_jiffies(250));
@@ -808,7 +809,7 @@ static int __init sharpsl_pm_probe(struct platform_device *pdev)
static int sharpsl_pm_remove(struct platform_device *pdev)
{
- pm_set_ops(NULL);
+ suspend_set_ops(NULL);
device_remove_file(&pdev->dev, &dev_attr_battery_percentage);
device_remove_file(&pdev->dev, &dev_attr_battery_voltage);
diff --git a/arch/arm/configs/cm_x270_defconfig b/arch/arm/configs/cm_x270_defconfig
new file mode 100644
index 000000000000..5cab08397ae7
--- /dev/null
+++ b/arch/arm/configs/cm_x270_defconfig
@@ -0,0 +1,1410 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.22
+# Wed Jul 18 14:11:48 2007
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+# CONFIG_GENERIC_CLOCKEVENTS is not set
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ZONE_DMA=y
+CONFIG_ARCH_MTD_XIP=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+# CONFIG_EPOLL is not set
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG 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"
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_PNX4008 is not set
+CONFIG_ARCH_PXA=y
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+CONFIG_DMABOUNCE=y
+
+#
+# Intel PXA2xx Implementations
+#
+# CONFIG_ARCH_LUBBOCK is not set
+# CONFIG_MACH_LOGICPD_PXA270 is not set
+# CONFIG_MACH_MAINSTONE is not set
+# CONFIG_ARCH_PXA_IDP is not set
+# CONFIG_PXA_SHARPSL is not set
+# CONFIG_MACH_TRIZEPS4 is not set
+CONFIG_MACH_ARMCORE=y
+CONFIG_PXA27x=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_OUTER_CACHE is not set
+CONFIG_IWMMXT=y
+CONFIG_XSCALE_PMU=y
+
+#
+# Bus support
+#
+CONFIG_PCI=y
+CONFIG_PCI_SYSCALL=y
+CONFIG_PCI_HOST_ITE8152=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE 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_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+# CONFIG_APM_EMULATION is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+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_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# 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_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_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL 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_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
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_EXT=y
+# CONFIG_MAC80211 is not set
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+# CONFIG_IEEE80211_CRYPT_TKIP is not set
+# CONFIG_IEEE80211_SOFTMAC is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# 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=m
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLKDEVS=m
+CONFIG_MTD_BLOCK=m
+# CONFIG_MTD_BLOCK_RO is not set
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_SHARP_SL is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_H1900 is not set
+CONFIG_MTD_NAND_IDS=m
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_SHARPSL is not set
+# CONFIG_MTD_NAND_CAFE is not set
+CONFIG_MTD_NAND_CM_X270=m
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+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=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# 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=12000
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_IDE=m
+CONFIG_IDE_MAX_HWIFS=4
+CONFIG_BLK_DEV_IDE=m
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=m
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI 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_IDEPCI is not set
+# CONFIG_IDEPCI_PCIBUS_ORDER is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# 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 is not set
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# 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 is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP 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_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_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_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# 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_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ARCNET is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
+CONFIG_DM9000=y
+# CONFIG_SMC911X is not set
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 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_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 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_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 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 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 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_MLX4_CORE is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# 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_MII is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# 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_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN 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 is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+CONFIG_TOUCHSCREEN_UCB1400=m
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=m
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+# CONFIG_W1 is not set
+# CONFIG_HWMON 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
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+CONFIG_LEDS_CM_X270=y
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+# CONFIG_LEDS_TRIGGER_TIMER is not set
+# CONFIG_LEDS_TRIGGER_IDE_DISK is not set
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+CONFIG_FB_PXA=y
+# CONFIG_FB_PXA_PARAMETERS is not set
+CONFIG_FB_MBX=m
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_AC97_CODEC=m
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# PCI devices
+#
+# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_DARLA20 is not set
+# CONFIG_SND_GINA20 is not set
+# CONFIG_SND_LAYLA20 is not set
+# CONFIG_SND_DARLA24 is not set
+# CONFIG_SND_GINA24 is not set
+# CONFIG_SND_LAYLA24 is not set
+# CONFIG_SND_MONA is not set
+# CONFIG_SND_MIA is not set
+# CONFIG_SND_ECHO3G is not set
+# CONFIG_SND_INDIGO is not set
+# CONFIG_SND_INDIGOIO is not set
+# CONFIG_SND_INDIGODJ is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_TRIDENT is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VX222 is not set
+# CONFIG_SND_YMFPCI is not set
+# CONFIG_SND_AC97_POWER_SAVE is not set
+
+#
+# ALSA ARM devices
+#
+CONFIG_SND_PXA2XX_PCM=m
+CONFIG_SND_PXA2XX_AC97=m
+
+#
+# USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_CAIAQ is not set
+
+#
+# System on Chip audio support
+#
+# CONFIG_SND_SOC is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=m
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV 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
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_PERSIST is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# 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 is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_DPCM 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_KARMA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# 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_AUERSWALD 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_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD Card Drivers
+#
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_BLOCK_BOUNCE=y
+
+#
+# MMC/SD Host Controller Drivers
+#
+CONFIG_MMC_PXA=m
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_TIFM_SD is not set
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+CONFIG_RTC_DRV_V3020=y
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_SA1100=y
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# 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_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=y
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS 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 is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+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 is not set
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_SLAB 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 is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=m
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_MANAGER=m
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+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
diff --git a/arch/arm/configs/omap_h2_1610_defconfig b/arch/arm/configs/omap_h2_1610_defconfig
index b0efd4ca9935..b8a78ab49cdd 100644
--- a/arch/arm/configs/omap_h2_1610_defconfig
+++ b/arch/arm/configs/omap_h2_1610_defconfig
@@ -1,41 +1,58 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.17
-# Thu Jun 29 15:25:18 2006
+# Linux kernel version: 2.6.23-rc6
+# Mon Sep 17 14:21:45 2007
#
CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ZONE_DMA=y
CONFIG_VECTORS_BASE=0xffff0000
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
-# Code maturity level options
+# General setup
#
CONFIG_EXPERIMENTAL=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_LOCK_KERNEL=y
CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_USER_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SYSFS_DEPRECATED is not set
# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
-CONFIG_UID16=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_HOTPLUG=y
@@ -44,27 +61,30 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=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_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
-
-#
-# Loadable module support
-#
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
# CONFIG_KMOD is not set
-
-#
-# Block layer
-#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
#
# IO Schedulers
@@ -86,7 +106,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_REALVIEW is not set
# CONFIG_ARCH_VERSATILE is not set
-# CONFIG_ARCH_AT91RM9200 is not set
+# CONFIG_ARCH_AT91 is not set
# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
@@ -96,11 +116,16 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# CONFIG_ARCH_NETX is not set
# CONFIG_ARCH_H720X is not set
# CONFIG_ARCH_IMX is not set
-# CONFIG_ARCH_IOP3XX is not set
-# CONFIG_ARCH_IXP4XX is not set
-# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_MXC is not set
# CONFIG_ARCH_PNX4008 is not set
# CONFIG_ARCH_PXA is not set
# CONFIG_ARCH_RPC is not set
@@ -108,6 +133,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# CONFIG_ARCH_S3C2410 is not set
# CONFIG_ARCH_SHARK is not set
# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
CONFIG_ARCH_OMAP=y
#
@@ -124,6 +150,7 @@ CONFIG_ARCH_OMAP1=y
CONFIG_OMAP_MUX=y
# CONFIG_OMAP_MUX_DEBUG is not set
CONFIG_OMAP_MUX_WARNINGS=y
+CONFIG_OMAP_MCBSP=y
# CONFIG_OMAP_MPU_TIMER is not set
CONFIG_OMAP_32K_TIMER=y
CONFIG_OMAP_32K_TIMER_HZ=128
@@ -162,6 +189,14 @@ CONFIG_OMAP_ARM_192MHZ=y
# CONFIG_OMAP_ARM_30MHZ is not set
#
+# Boot options
+#
+
+#
+# Power management
+#
+
+#
# Processor Type
#
CONFIG_CPU_32=y
@@ -171,6 +206,8 @@ CONFIG_CPU_ABRT_EV5TJ=y
CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_COPY_V4WB=y
CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
#
# Processor Features
@@ -180,10 +217,13 @@ CONFIG_ARM_THUMB=y
# CONFIG_CPU_DCACHE_DISABLE is not set
# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+# CONFIG_OUTER_CACHE is not set
#
# Bus support
#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
#
# PCCARD (PCMCIA/CardBus) support
@@ -193,10 +233,13 @@ CONFIG_ARM_THUMB=y
#
# Kernel Features
#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
CONFIG_PREEMPT=y
-CONFIG_NO_IDLE_HZ=y
CONFIG_HZ=128
-# CONFIG_AEABI is not set
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
@@ -206,6 +249,10 @@ CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
# CONFIG_LEDS is not set
CONFIG_ALIGNMENT_TRAP=y
@@ -216,6 +263,7 @@ CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_CMDLINE="mem=32M console=ttyS0,115200n8 root=0801 ro init=/bin/sh"
# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
#
# CPU Frequency scaling
@@ -251,7 +299,6 @@ CONFIG_FPE_NWFPE=y
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_AOUT=y
# CONFIG_BINFMT_MISC is not set
-# CONFIG_ARTHUR is not set
#
# Power management options
@@ -259,7 +306,10 @@ CONFIG_BINFMT_AOUT=y
CONFIG_PM=y
# CONFIG_PM_LEGACY is not set
# CONFIG_PM_DEBUG is not set
-# CONFIG_APM is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND_UP_POSSIBLE=y
+CONFIG_SUSPEND=y
+# CONFIG_APM_EMULATION is not set
#
# Networking
@@ -269,12 +319,13 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
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_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
@@ -295,29 +346,20 @@ CONFIG_IP_PNP_BOOTP=y
# 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_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -328,7 +370,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -344,7 +385,17 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
#
# Device Drivers
@@ -357,29 +408,10 @@ CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
# CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-
-#
-# Block devices
-#
+CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
@@ -387,7 +419,7 @@ CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_BLK_DEV_INITRD=y
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
# CONFIG_CDROM_PKTCDVD is not set
CONFIG_ATA_OVER_ETH=m
@@ -396,6 +428,9 @@ CONFIG_ATA_OVER_ETH=m
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
CONFIG_SCSI_PROC_FS=y
#
@@ -414,82 +449,42 @@ CONFIG_SCSI_PROC_FS=y
# 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 Transport Attributes
+# SCSI Transports
#
# CONFIG_SCSI_SPI_ATTRS is not set
# CONFIG_SCSI_FC_ATTRS is not set
# CONFIG_SCSI_ISCSI_ATTRS is not set
-# CONFIG_SCSI_SAS_ATTRS is not set
-
-#
-# SCSI low-level drivers
-#
+# CONFIG_SCSI_SAS_LIBSAS is not set
+CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
-# CONFIG_SCSI_SATA is not set
# CONFIG_SCSI_DEBUG is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
+# CONFIG_ATA is not set
# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
-# Network device support
-#
CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# PHY device support
-#
# CONFIG_PHYLIB is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
+# CONFIG_AX88796 is not set
CONFIG_SMC91X=y
# CONFIG_DM9000 is not set
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
# CONFIG_WAN is not set
CONFIG_PPP=y
# CONFIG_PPP_MULTILINK is not set
@@ -500,24 +495,24 @@ CONFIG_PPP=y
# CONFIG_PPP_BSDCOMP is not set
# CONFIG_PPP_MPPE is not set
# CONFIG_PPPOE is not set
+# CONFIG_PPPOL2TP is not set
CONFIG_SLIP=y
CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLHC=y
# CONFIG_SLIP_SMART is not set
# CONFIG_SLIP_MODE_SLIP6 is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
# CONFIG_ISDN is not set
#
# Input device support
#
CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -537,8 +532,14 @@ CONFIG_INPUT_EVBUG=y
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
CONFIG_INPUT_UINPUT=y
#
@@ -574,15 +575,7 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
# CONFIG_LEGACY_PTYS is not set
-
-#
-# IPMI
-#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
CONFIG_WATCHDOG=y
CONFIG_WATCHDOG_NOWAYOUT=y
@@ -590,25 +583,12 @@ CONFIG_WATCHDOG_NOWAYOUT=y
# Watchdog Device Drivers
#
# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_OMAP_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
-
-#
-# I2C support
-#
# CONFIG_I2C is not set
#
@@ -616,61 +596,70 @@ CONFIG_WATCHDOG_NOWAYOUT=y
#
# CONFIG_SPI is not set
# CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
-
-#
-# Hardware Monitoring support
-#
+# CONFIG_W1 is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ABITUGURU3 is not set
# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
#
-# Misc devices
-#
-
-#
-# LED devices
+# Multifunction device drivers
#
+# CONFIG_MFD_SM501 is not set
# CONFIG_NEW_LEDS is not set
#
-# LED drivers
-#
-
-#
-# LED Triggers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
# CONFIG_FB_CFB_FILLRECT is not set
# CONFIG_FB_CFB_COPYAREA is not set
# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
# CONFIG_FB_MACMODES is not set
# CONFIG_FB_BACKLIGHT is not set
CONFIG_FB_MODE_HELPERS=y
# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_OMAP is not set
# CONFIG_FB_VIRTUAL is not set
#
@@ -679,6 +668,7 @@ CONFIG_FB_MODE_HELPERS=y
# CONFIG_VGA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
CONFIG_FONTS=y
CONFIG_FONT_8x8=y
@@ -691,15 +681,10 @@ CONFIG_FONT_8x16=y
# CONFIG_FONT_SUN8x16 is not set
# CONFIG_FONT_SUN12x22 is not set
# CONFIG_FONT_10x18 is not set
-
-#
-# Logo configuration
-#
CONFIG_LOGO=y
# CONFIG_LOGO_LINUX_MONO is not set
# CONFIG_LOGO_LINUX_VGA16 is not set
CONFIG_LOGO_LINUX_CLUT224=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -717,10 +702,10 @@ CONFIG_SOUND=y
CONFIG_SOUND_PRIME=y
# CONFIG_SOUND_MSNDCLAS is not set
# CONFIG_SOUND_MSNDPIN is not set
-
-#
-# USB support
-#
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+CONFIG_HID_DEBUG=y
+CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_USB_ARCH_HAS_EHCI is not set
@@ -734,17 +719,22 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
#
-# MMC/SD Card support
+# DMA Engine support
#
-# CONFIG_MMC is not set
+# CONFIG_DMA_ENGINE is not set
#
-# Real Time Clock
+# DMA Clients
+#
+
+#
+# DMA Devices
#
-CONFIG_RTC_LIB=y
-# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -753,10 +743,12 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
CONFIG_ROMFS_FS=y
@@ -787,6 +779,7 @@ CONFIG_FAT_DEFAULT_CODEPAGE=437
# Pseudo filesystems
#
CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
@@ -825,6 +818,7 @@ CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -832,7 +826,6 @@ CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
#
# Partition Types
@@ -885,6 +878,11 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_UTF8 is not set
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Profiling support
#
# CONFIG_PROFILING is not set
@@ -893,13 +891,14 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
CONFIG_DEBUG_BUGVERBOSE=y
-# CONFIG_DEBUG_FS is not set
CONFIG_FRAME_POINTER=y
-# CONFIG_UNWIND_INFO is not set
# CONFIG_DEBUG_USER is not set
#
@@ -907,12 +906,12 @@ CONFIG_FRAME_POINTER=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_MANAGER=y
# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=y
@@ -921,7 +920,14 @@ CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_SHA512 is not set
# CONFIG_CRYPTO_WP512 is not set
# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
# CONFIG_CRYPTO_BLOWFISH is not set
# CONFIG_CRYPTO_TWOFISH is not set
# CONFIG_CRYPTO_SERPENT is not set
@@ -935,17 +941,22 @@ CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_MICHAEL_MIC is not set
# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
# CONFIG_CRYPTO_TEST is not set
-
-#
-# Hardware crypto devices
-#
+CONFIG_CRYPTO_HW=y
#
# Library routines
#
+CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/arm/configs/omap_osk_5912_defconfig b/arch/arm/configs/omap_osk_5912_defconfig
new file mode 100644
index 000000000000..8c1f15c7c45c
--- /dev/null
+++ b/arch/arm/configs/omap_osk_5912_defconfig
@@ -0,0 +1,1073 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.23-rc6
+# Mon Sep 17 14:15:05 2007
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ZONE_DMA=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=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 is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY 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_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=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_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+CONFIG_ARCH_OMAP1=y
+# CONFIG_ARCH_OMAP2 is not set
+
+#
+# OMAP Feature Selections
+#
+CONFIG_OMAP_RESET_CLOCKS=y
+CONFIG_OMAP_MUX=y
+# CONFIG_OMAP_MUX_DEBUG is not set
+CONFIG_OMAP_MUX_WARNINGS=y
+CONFIG_OMAP_MCBSP=y
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+CONFIG_OMAP_32K_TIMER_HZ=128
+# CONFIG_OMAP_DM_TIMER is not set
+CONFIG_OMAP_LL_DEBUG_UART1=y
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+# CONFIG_OMAP_LL_DEBUG_UART3 is not set
+CONFIG_OMAP_SERIAL_WAKE=y
+
+#
+# OMAP Core Type
+#
+# CONFIG_ARCH_OMAP730 is not set
+# CONFIG_ARCH_OMAP15XX is not set
+CONFIG_ARCH_OMAP16XX=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_OMAP_INNOVATOR is not set
+# CONFIG_MACH_OMAP_H2 is not set
+# CONFIG_MACH_OMAP_H3 is not set
+CONFIG_MACH_OMAP_OSK=y
+# CONFIG_OMAP_OSK_MISTRAL is not set
+# CONFIG_MACH_NOKIA770 is not set
+# CONFIG_MACH_OMAP_GENERIC is not set
+
+#
+# OMAP CPU Speed
+#
+# CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER is not set
+# CONFIG_OMAP_ARM_216MHZ is not set
+CONFIG_OMAP_ARM_192MHZ=y
+# CONFIG_OMAP_ARM_168MHZ is not set
+# CONFIG_OMAP_ARM_120MHZ is not set
+# CONFIG_OMAP_ARM_60MHZ is not set
+# CONFIG_OMAP_ARM_30MHZ is not set
+
+#
+# Boot options
+#
+
+#
+# Power management
+#
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+# CONFIG_OUTER_CACHE is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+
+#
+# PC-card bridges
+#
+CONFIG_OMAP_CF=y
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=128
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE 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_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="mem=32M console=ttyS0,115200 initrd=0x10400000,8M root=/dev/ram0 rw"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND_UP_POSSIBLE=y
+CONFIG_SUSPEND=y
+# CONFIG_APM_EMULATION is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=m
+# 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_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=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# 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_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_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL 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_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
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+CONFIG_MTD_OMAP_NOR=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_IDE=m
+CONFIG_BLK_DEV_IDE=m
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=m
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECS=m
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY 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_IDEPCI_PCIBUS_ORDER is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+CONFIG_SMC91X=y
+# CONFIG_DM9000 is not set
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_NET_PCMCIA is not set
+# CONFIG_WAN is not set
+CONFIG_PPP=y
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=y
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN 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 is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# 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_KEYBOARD_OMAP=y
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_UCB1400 is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_CS is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=m
+CONFIG_HW_RANDOM_OMAP=m
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_ISP1301_OMAP is not set
+CONFIG_TPS65010=y
+# 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
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+# CONFIG_W1 is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ABITUGURU3 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_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS 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_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 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_THMC50 is not set
+# CONFIG_SENSORS_VT1211 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_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_NEW_LEDS is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_OMAP is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+CONFIG_HID_DEBUG=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# 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_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS 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 is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_USER is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/arm/configs/zylonite_defconfig b/arch/arm/configs/zylonite_defconfig
new file mode 100644
index 000000000000..7949d04a3602
--- /dev/null
+++ b/arch/arm/configs/zylonite_defconfig
@@ -0,0 +1,736 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.23
+# Tue Oct 23 13:33:20 2007
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ZONE_DMA=y
+CONFIG_ARCH_MTD_XIP=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=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 is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=18
+# CONFIG_CGROUPS is not set
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_FAIR_USER_SCHED=y
+# CONFIG_FAIR_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_PNX4008 is not set
+CONFIG_ARCH_PXA=y
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+
+#
+# Intel PXA2xx/PXA3xx Implementations
+#
+
+#
+# Supported PXA3xx Processor Variants
+#
+CONFIG_CPU_PXA300=y
+CONFIG_CPU_PXA310=y
+CONFIG_CPU_PXA320=y
+# CONFIG_ARCH_LUBBOCK is not set
+# CONFIG_MACH_LOGICPD_PXA270 is not set
+# CONFIG_MACH_MAINSTONE is not set
+# CONFIG_ARCH_PXA_IDP is not set
+# CONFIG_PXA_SHARPSL is not set
+# CONFIG_MACH_TRIZEPS4 is not set
+# CONFIG_MACH_EM_X270 is not set
+CONFIG_MACH_ZYLONITE=y
+# CONFIG_MACH_ARMCORE is not set
+CONFIG_PXA3xx=y
+
+#
+# Boot options
+#
+
+#
+# Power management
+#
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSC3=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+CONFIG_IO_36=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+# CONFIG_OUTER_CACHE is not set
+CONFIG_IWMMXT=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE 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_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/nfs rootfstype=nfs nfsroot=192.168.1.100:/nfs/rootfs/ ip=192.168.1.101:192.168.1.100::255.255.255.0::eth0:on console=ttyS0,38400 mem=64M debug"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_SUSPEND_UP_POSSIBLE=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# 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 is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_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_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL 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_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
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 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_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+# CONFIG_BLK_DEV is not set
+# CONFIG_MISC_DEVICES is not set
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# 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_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+CONFIG_SMC91X=y
+# CONFIG_DM9000 is not set
+# CONFIG_SMC911X 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_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN 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 is not set
+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 is not set
+# CONFIG_INPUT_MOUSE 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 is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_PXA=y
+# CONFIG_FB_PXA_PARAMETERS is not set
+# CONFIG_FB_MBX is not set
+# CONFIG_FB_VIRTUAL 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 is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
+# CONFIG_FONT_8x16 is not set
+CONFIG_FONT_6x11=y
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_NEW_LEDS is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# 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_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS 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 is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+# CONFIG_INSTRUMENTATION is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_SAMPLES is not set
+CONFIG_DEBUG_USER=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_ECB is not set
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_HW is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+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
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index a2dd930d11ef..e5747547b44c 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -279,6 +279,25 @@ static void __devinit pci_fixup_cy82c693(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, pci_fixup_cy82c693);
+static void __init pci_fixup_it8152(struct pci_dev *dev)
+{
+ int i;
+ /* fixup for ITE 8152 devices */
+ /* FIXME: add defines for class 0x68000 and 0x80103 */
+ if ((dev->class >> 8) == PCI_CLASS_BRIDGE_HOST ||
+ dev->class == 0x68000 ||
+ dev->class == 0x80103) {
+ for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+ dev->resource[i].start = 0;
+ dev->resource[i].end = 0;
+ dev->resource[i].flags = 0;
+ }
+ }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8152, pci_fixup_it8152);
+
+
+
void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
{
if (debug_pci)
@@ -292,9 +311,12 @@ void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
*/
static inline int pdev_bad_for_parity(struct pci_dev *dev)
{
- return (dev->vendor == PCI_VENDOR_ID_INTERG &&
- (dev->device == PCI_DEVICE_ID_INTERG_2000 ||
- dev->device == PCI_DEVICE_ID_INTERG_2010));
+ return ((dev->vendor == PCI_VENDOR_ID_INTERG &&
+ (dev->device == PCI_DEVICE_ID_INTERG_2000 ||
+ dev->device == PCI_DEVICE_ID_INTERG_2010)) ||
+ (dev->vendor == PCI_VENDOR_ID_ITE &&
+ dev->device == PCI_DEVICE_ID_ITE_8152));
+
}
/*
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index a98d0c933db0..cecf658e3625 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -361,6 +361,7 @@
CALL(sys_signalfd)
/* 350 */ CALL(sys_timerfd)
CALL(sys_eventfd)
+ CALL(sys_fallocate)
#ifndef syscalls_counted
.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
#define syscalls_counted
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 93b7f8e22dcc..4f1a03124a74 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -265,7 +265,7 @@ void __show_regs(struct pt_regs *regs)
void show_regs(struct pt_regs * regs)
{
printk("\n");
- printk("Pid: %d, comm: %20s\n", current->pid, current->comm);
+ printk("Pid: %d, comm: %20s\n", task_pid_nr(current), current->comm);
__show_regs(regs);
__backtrace();
}
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 78c9f1a3d41f..4b05dc5c1023 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -382,16 +382,16 @@ static void clear_breakpoint(struct task_struct *task, struct debug_entry *bp)
if (ret != 2 || old_insn.thumb != BREAKINST_THUMB)
printk(KERN_ERR "%s:%d: corrupted Thumb breakpoint at "
- "0x%08lx (0x%04x)\n", task->comm, task->pid,
- addr, old_insn.thumb);
+ "0x%08lx (0x%04x)\n", task->comm,
+ task_pid_nr(task), addr, old_insn.thumb);
} else {
ret = swap_insn(task, addr & ~3, &old_insn.arm,
&bp->insn.arm, 4);
if (ret != 4 || old_insn.arm != BREAKINST_ARM)
printk(KERN_ERR "%s:%d: corrupted ARM breakpoint at "
- "0x%08lx (0x%08x)\n", task->comm, task->pid,
- addr, old_insn.arm);
+ "0x%08lx (0x%08x)\n", task->comm,
+ task_pid_nr(task), addr, old_insn.arm);
}
}
@@ -731,10 +731,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
ret = 0;
break;
- case PTRACE_DETACH:
- ret = ptrace_detach(child, data);
- break;
-
case PTRACE_GETREGS:
ret = ptrace_getregs(child, (void __user *)data);
break;
diff --git a/arch/arm/kernel/relocate_kernel.S b/arch/arm/kernel/relocate_kernel.S
index 7baadae7cb27..062c111c572f 100644
--- a/arch/arm/kernel/relocate_kernel.S
+++ b/arch/arm/kernel/relocate_kernel.S
@@ -7,6 +7,23 @@
.globl relocate_new_kernel
relocate_new_kernel:
+ /* Move boot params back to where the kernel expects them */
+
+ ldr r0,kexec_boot_params_address
+ teq r0,#0
+ beq 8f
+
+ ldr r1,kexec_boot_params_copy
+ mov r6,#KEXEC_BOOT_PARAMS_SIZE/4
+7:
+ ldr r5,[r1],#4
+ str r5,[r0],#4
+ subs r6,r6,#1
+ bne 7b
+
+8:
+ /* Boot params moved, now go on with the kernel */
+
ldr r0,kexec_indirection_page
ldr r1,kexec_start_address
@@ -50,7 +67,7 @@ relocate_new_kernel:
mov lr,r1
mov r0,#0
ldr r1,kexec_mach_type
- mov r2,#0
+ ldr r2,kexec_boot_params_address
mov pc,lr
.globl kexec_start_address
@@ -65,6 +82,16 @@ kexec_indirection_page:
kexec_mach_type:
.long 0x0
+ /* phy addr where new kernel will expect to find boot params */
+ .globl kexec_boot_params_address
+kexec_boot_params_address:
+ .long 0x0
+
+ /* phy addr where old kernel put a copy of orig boot params */
+ .globl kexec_boot_params_copy
+kexec_boot_params_copy:
+ .long 0x0
+
relocate_new_kernel_end:
.globl relocate_new_kernel_size
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 4de432ec903a..bf56eb337df1 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -24,6 +24,7 @@
#include <linux/interrupt.h>
#include <linux/smp.h>
#include <linux/fs.h>
+#include <linux/kexec.h>
#include <asm/cpu.h>
#include <asm/elf.h>
@@ -304,10 +305,23 @@ int cpu_architecture(void)
cpu_arch = (processor_id >> 16) & 7;
if (cpu_arch)
cpu_arch += CPU_ARCH_ARMv3;
- } else {
- /* the revised CPUID */
- cpu_arch = ((processor_id >> 12) & 0xf) - 0xb + CPU_ARCH_ARMv6;
- }
+ } else if ((processor_id & 0x000f0000) == 0x000f0000) {
+ unsigned int mmfr0;
+
+ /* Revised CPUID format. Read the Memory Model Feature
+ * Register 0 and check for VMSAv7 or PMSAv7 */
+ asm("mrc p15, 0, %0, c0, c1, 4"
+ : "=r" (mmfr0));
+ if ((mmfr0 & 0x0000000f) == 0x00000003 ||
+ (mmfr0 & 0x000000f0) == 0x00000030)
+ cpu_arch = CPU_ARCH_ARMv7;
+ else if ((mmfr0 & 0x0000000f) == 0x00000002 ||
+ (mmfr0 & 0x000000f0) == 0x00000020)
+ cpu_arch = CPU_ARCH_ARMv6;
+ else
+ cpu_arch = CPU_ARCH_UNKNOWN;
+ } else
+ cpu_arch = CPU_ARCH_UNKNOWN;
return cpu_arch;
}
@@ -770,6 +784,23 @@ static int __init customize_machine(void)
}
arch_initcall(customize_machine);
+#ifdef CONFIG_KEXEC
+
+/* Physical addr of where the boot params should be for this machine */
+extern unsigned long kexec_boot_params_address;
+
+/* Physical addr of the buffer into which the boot params are copied */
+extern unsigned long kexec_boot_params_copy;
+
+/* Pointer to the boot params buffer, for manipulation and display */
+unsigned long kexec_boot_params;
+EXPORT_SYMBOL(kexec_boot_params);
+
+/* The buffer itself - make sure it is sized correctly */
+static unsigned long kexec_boot_params_buf[(KEXEC_BOOT_PARAMS_SIZE + 3) / 4];
+
+#endif
+
void __init setup_arch(char **cmdline_p)
{
struct tag *tags = (struct tag *)&init_tags;
@@ -788,6 +819,18 @@ void __init setup_arch(char **cmdline_p)
else if (mdesc->boot_params)
tags = phys_to_virt(mdesc->boot_params);
+#ifdef CONFIG_KEXEC
+ kexec_boot_params_copy = virt_to_phys(kexec_boot_params_buf);
+ kexec_boot_params = (unsigned long)kexec_boot_params_buf;
+ if (__atags_pointer) {
+ kexec_boot_params_address = __atags_pointer;
+ memcpy((void *)kexec_boot_params, tags, KEXEC_BOOT_PARAMS_SIZE);
+ } else if (mdesc->boot_params) {
+ kexec_boot_params_address = mdesc->boot_params;
+ memcpy((void *)kexec_boot_params, tags, KEXEC_BOOT_PARAMS_SIZE);
+ }
+#endif
+
/*
* If we have the old style parameters, convert them to
* a tag list.
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c
index 4d25e49a14f7..9bd1870d980e 100644
--- a/arch/arm/kernel/sys_arm.c
+++ b/arch/arm/kernel/sys_arm.c
@@ -26,9 +26,9 @@
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/utsname.h>
+#include <linux/ipc.h>
#include <asm/uaccess.h>
-#include <asm/ipc.h>
extern unsigned long do_mremap(unsigned long addr, unsigned long old_len,
unsigned long new_len, unsigned long flags,
diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c
index 8e2f9bc3368b..e8b98046895b 100644
--- a/arch/arm/kernel/sys_oabi-compat.c
+++ b/arch/arm/kernel/sys_oabi-compat.c
@@ -80,7 +80,7 @@
#include <linux/sem.h>
#include <linux/socket.h>
#include <linux/net.h>
-#include <asm/ipc.h>
+#include <linux/ipc.h>
#include <asm/uaccess.h>
struct oldabi_stat64 {
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 8ad47619c079..4764bd9ccee8 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -223,7 +223,7 @@ static void __die(const char *str, int err, struct thread_info *thread, struct p
print_modules();
__show_regs(regs);
printk("Process %s (pid: %d, stack limit = 0x%p)\n",
- tsk->comm, tsk->pid, thread + 1);
+ tsk->comm, task_pid_nr(tsk), thread + 1);
if (!user_mode(regs) || in_interrupt()) {
dump_mem("Stack: ", regs->ARM_sp,
@@ -337,7 +337,7 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
#ifdef CONFIG_DEBUG_USER
if (user_debug & UDBG_UNDEFINED) {
printk(KERN_INFO "%s (%d): undefined instruction: pc=%p\n",
- current->comm, current->pid, pc);
+ current->comm, task_pid_nr(current), pc);
dump_instr(regs);
}
#endif
@@ -388,7 +388,7 @@ static int bad_syscall(int n, struct pt_regs *regs)
#ifdef CONFIG_DEBUG_USER
if (user_debug & UDBG_SYSCALL) {
printk(KERN_ERR "[%d] %s: obsolete system call %08x.\n",
- current->pid, current->comm, n);
+ task_pid_nr(current), current->comm, n);
dump_instr(regs);
}
#endif
@@ -565,7 +565,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
*/
if (user_debug & UDBG_SYSCALL) {
printk("[%d] %s: arm syscall %d\n",
- current->pid, current->comm, no);
+ task_pid_nr(current), current->comm, no);
dump_instr(regs);
if (user_mode(regs)) {
__show_regs(regs);
@@ -642,7 +642,7 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs)
#ifdef CONFIG_DEBUG_USER
if (user_debug & UDBG_BADABORT) {
printk(KERN_ERR "[%d] %s: bad data abort: code %d instr 0x%08lx\n",
- current->pid, current->comm, code, instr);
+ task_pid_nr(current), current->comm, code, instr);
dump_instr(regs);
show_pte(current->mm, addr);
}
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index a31157f1655a..05a9f8a1b45e 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -7,6 +7,8 @@ choice
config ARCH_AT91RM9200
bool "AT91RM9200"
+ select GENERIC_TIME
+ select GENERIC_CLOCKEVENTS
config ARCH_AT91SAM9260
bool "AT91SAM9260 or AT91SAM9XE"
@@ -20,8 +22,15 @@ config ARCH_AT91SAM9263
config ARCH_AT91SAM9RL
bool "AT91SAM9RL"
+config ARCH_AT91X40
+ bool "AT91x40"
+
endchoice
+config AT91_PMC_UNIT
+ bool
+ default !ARCH_AT91X40
+
# ----------------------------------------------------------
if ARCH_AT91RM9200
@@ -169,6 +178,22 @@ endif
# ----------------------------------------------------------
+if ARCH_AT91X40
+
+comment "AT91X40 Board Type"
+
+config MACH_AT91EB01
+ bool "Atmel AT91EB01 Evaluation Kit"
+ help
+ Select this if you are using Atmel's AT91EB01 Evaluation Kit.
+ It is also a popular target for simulators such as GDB's
+ ARM simulator (commonly known as the ARMulator) and the
+ Skyeye simulator.
+
+endif
+
+# ----------------------------------------------------------
+
comment "AT91 Board Options"
config MTD_AT91_DATAFLASH_CARD
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
index a4d80eb056ee..a21f08c64ea6 100644
--- a/arch/arm/mach-at91/Makefile
+++ b/arch/arm/mach-at91/Makefile
@@ -2,11 +2,12 @@
# Makefile for the linux kernel.
#
-obj-y := clock.o irq.o gpio.o
+obj-y := irq.o gpio.o
obj-m :=
obj-n :=
obj- :=
+obj-$(CONFIG_AT91_PMC_UNIT) += clock.o
obj-$(CONFIG_PM) += pm.o
# CPU-specific support
@@ -15,6 +16,7 @@ obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o at91sam9260_d
obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o
obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam926x_time.o at91sam9263_devices.o
obj-$(CONFIG_ARCH_AT91SAM9RL) += at91sam9rl.o at91sam926x_time.o at91sam9rl_devices.o
+obj-$(CONFIG_ARCH_AT91X40) += at91x40.o at91x40_time.o
# AT91RM9200 board-specific support
obj-$(CONFIG_MACH_ONEARM) += board-1arm.o
@@ -27,6 +29,7 @@ obj-$(CONFIG_MACH_KB9200) += board-kb9202.o
obj-$(CONFIG_MACH_ATEB9200) += board-eb9200.o
obj-$(CONFIG_MACH_KAFA) += board-kafa.o
obj-$(CONFIG_MACH_PICOTUX2XX) += board-picotux200.o
+obj-$(CONFIG_MACH_AT91EB01) += board-eb01.o
# AT91SAM9260 board-specific support
obj-$(CONFIG_MACH_AT91SAM9260EK) += board-sam9260ek.o
diff --git a/arch/arm/mach-at91/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c
index a6340357585d..50392ff71513 100644
--- a/arch/arm/mach-at91/at91rm9200_time.c
+++ b/arch/arm/mach-at91/at91rm9200_time.c
@@ -19,70 +19,64 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <linux/init.h>
+#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
+#include <linux/clockchips.h>
-#include <asm/hardware.h>
-#include <asm/io.h>
#include <asm/mach/time.h>
#include <asm/arch/at91_st.h>
static unsigned long last_crtr;
+static u32 irqmask;
+static struct clock_event_device clkevt;
/*
- * The ST_CRTR is updated asynchronously to the master clock. It is therefore
- * necessary to read it twice (with the same value) to ensure accuracy.
+ * The ST_CRTR is updated asynchronously to the master clock ... but
+ * the updates as seen by the CPU don't seem to be strictly monotonic.
+ * Waiting until we read the same value twice avoids glitching.
*/
-static inline unsigned long read_CRTR(void) {
+static inline unsigned long read_CRTR(void)
+{
unsigned long x1, x2;
+ x1 = at91_sys_read(AT91_ST_CRTR);
do {
- x1 = at91_sys_read(AT91_ST_CRTR);
x2 = at91_sys_read(AT91_ST_CRTR);
- } while (x1 != x2);
-
+ if (x1 == x2)
+ break;
+ x1 = x2;
+ } while (1);
return x1;
}
/*
- * Returns number of microseconds since last timer interrupt. Note that interrupts
- * will have been disabled by do_gettimeofday()
- * 'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy.
- * 'tick' is usecs per jiffy (linux/timex.h).
- */
-static unsigned long at91rm9200_gettimeoffset(void)
-{
- unsigned long elapsed;
-
- elapsed = (read_CRTR() - last_crtr) & AT91_ST_ALMV;
-
- return (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH;
-}
-
-/*
* IRQ handler for the timer.
*/
static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id)
{
- if (at91_sys_read(AT91_ST_SR) & AT91_ST_PITS) { /* This is a shared interrupt */
- write_seqlock(&xtime_lock);
+ u32 sr = at91_sys_read(AT91_ST_SR) & irqmask;
- while (((read_CRTR() - last_crtr) & AT91_ST_ALMV) >= LATCH) {
- timer_tick();
- last_crtr = (last_crtr + LATCH) & AT91_ST_ALMV;
- }
+ /* simulate "oneshot" timer with alarm */
+ if (sr & AT91_ST_ALMS) {
+ clkevt.event_handler(&clkevt);
+ return IRQ_HANDLED;
+ }
- write_sequnlock(&xtime_lock);
+ /* periodic mode should handle delayed ticks */
+ if (sr & AT91_ST_PITS) {
+ u32 crtr = read_CRTR();
+ while (((crtr - last_crtr) & AT91_ST_CRTV) >= LATCH) {
+ last_crtr += LATCH;
+ clkevt.event_handler(&clkevt);
+ }
return IRQ_HANDLED;
}
- else
- return IRQ_NONE; /* not handled */
+
+ /* this irq is shared ... */
+ return IRQ_NONE;
}
static struct irqaction at91rm9200_timer_irq = {
@@ -91,56 +85,127 @@ static struct irqaction at91rm9200_timer_irq = {
.handler = at91rm9200_timer_interrupt
};
-void at91rm9200_timer_reset(void)
+static cycle_t read_clk32k(void)
{
- last_crtr = 0;
+ return read_CRTR();
+}
- /* Real time counter incremented every 30.51758 microseconds */
- at91_sys_write(AT91_ST_RTMR, 1);
+static struct clocksource clk32k = {
+ .name = "32k_counter",
+ .rating = 150,
+ .read = read_clk32k,
+ .mask = CLOCKSOURCE_MASK(20),
+ .shift = 10,
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static void
+clkevt32k_mode(enum clock_event_mode mode, struct clock_event_device *dev)
+{
+ /* Disable and flush pending timer interrupts */
+ at91_sys_write(AT91_ST_IDR, AT91_ST_PITS | AT91_ST_ALMS);
+ (void) at91_sys_read(AT91_ST_SR);
- /* Set Period Interval timer */
- at91_sys_write(AT91_ST_PIMR, LATCH);
+ last_crtr = read_CRTR();
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ /* PIT for periodic irqs; fixed rate of 1/HZ */
+ irqmask = AT91_ST_PITS;
+ at91_sys_write(AT91_ST_PIMR, LATCH);
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ /* ALM for oneshot irqs, set by next_event()
+ * before 32 seconds have passed
+ */
+ irqmask = AT91_ST_ALMS;
+ at91_sys_write(AT91_ST_RTAR, last_crtr);
+ break;
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_RESUME:
+ irqmask = 0;
+ break;
+ }
+ at91_sys_write(AT91_ST_IER, irqmask);
+}
- /* Clear any pending interrupts */
+static int
+clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev)
+{
+ unsigned long flags;
+ u32 alm;
+ int status = 0;
+
+ BUG_ON(delta < 2);
+
+ /* Use "raw" primitives so we behave correctly on RT kernels. */
+ raw_local_irq_save(flags);
+
+ /* The alarm IRQ uses absolute time (now+delta), not the relative
+ * time (delta) in our calling convention. Like all clockevents
+ * using such "match" hardware, we have a race to defend against.
+ *
+ * Our defense here is to have set up the clockevent device so the
+ * delta is at least two. That way we never end up writing RTAR
+ * with the value then held in CRTR ... which would mean the match
+ * wouldn't trigger until 32 seconds later, after CRTR wraps.
+ */
+ alm = read_CRTR();
+
+ /* Cancel any pending alarm; flush any pending IRQ */
+ at91_sys_write(AT91_ST_RTAR, alm);
(void) at91_sys_read(AT91_ST_SR);
- /* Enable Period Interval Timer interrupt */
- at91_sys_write(AT91_ST_IER, AT91_ST_PITS);
+ /* Schedule alarm by writing RTAR. */
+ alm += delta;
+ at91_sys_write(AT91_ST_RTAR, alm);
+
+ raw_local_irq_restore(flags);
+ return status;
}
+static struct clock_event_device clkevt = {
+ .name = "at91_tick",
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+ .shift = 32,
+ .rating = 150,
+ .cpumask = CPU_MASK_CPU0,
+ .set_next_event = clkevt32k_next_event,
+ .set_mode = clkevt32k_mode,
+};
+
/*
- * Set up timer interrupt.
+ * ST (system timer) module supports both clockevents and clocksource.
*/
void __init at91rm9200_timer_init(void)
{
- /* Disable all timer interrupts */
- at91_sys_write(AT91_ST_IDR, AT91_ST_PITS | AT91_ST_WDOVF | AT91_ST_RTTINC | AT91_ST_ALMS);
- (void) at91_sys_read(AT91_ST_SR); /* Clear any pending interrupts */
+ /* Disable all timer interrupts, and clear any pending ones */
+ at91_sys_write(AT91_ST_IDR,
+ AT91_ST_PITS | AT91_ST_WDOVF | AT91_ST_RTTINC | AT91_ST_ALMS);
+ (void) at91_sys_read(AT91_ST_SR);
/* Make IRQs happen for the system timer */
setup_irq(AT91_ID_SYS, &at91rm9200_timer_irq);
- /* Change the kernel's 'tick' value to 10009 usec. (the default is 10000) */
- tick_usec = (LATCH * 1000000) / CLOCK_TICK_RATE;
+ /* The 32KiHz "Slow Clock" (tick every 30517.58 nanoseconds) is used
+ * directly for the clocksource and all clockevents, after adjusting
+ * its prescaler from the 1 Hz default.
+ */
+ at91_sys_write(AT91_ST_RTMR, 1);
- /* Initialize and enable the timer interrupt */
- at91rm9200_timer_reset();
-}
+ /* Setup timer clockevent, with minimum of two ticks (important!!) */
+ clkevt.mult = div_sc(AT91_SLOW_CLOCK, NSEC_PER_SEC, clkevt.shift);
+ clkevt.max_delta_ns = clockevent_delta2ns(AT91_ST_ALMV, &clkevt);
+ clkevt.min_delta_ns = clockevent_delta2ns(2, &clkevt) + 1;
+ clkevt.cpumask = cpumask_of_cpu(0);
+ clockevents_register_device(&clkevt);
-#ifdef CONFIG_PM
-static void at91rm9200_timer_suspend(void)
-{
- /* disable Period Interval Timer interrupt */
- at91_sys_write(AT91_ST_IDR, AT91_ST_PITS);
+ /* register clocksource */
+ clk32k.mult = clocksource_hz2mult(AT91_SLOW_CLOCK, clk32k.shift);
+ clocksource_register(&clk32k);
}
-#else
-#define at91rm9200_timer_suspend NULL
-#endif
struct sys_timer at91rm9200_timer = {
.init = at91rm9200_timer_init,
- .offset = at91rm9200_gettimeoffset,
- .suspend = at91rm9200_timer_suspend,
- .resume = at91rm9200_timer_reset,
};
diff --git a/arch/arm/mach-at91/at91x40.c b/arch/arm/mach-at91/at91x40.c
new file mode 100644
index 000000000000..1de121fc55f4
--- /dev/null
+++ b/arch/arm/mach-at91/at91x40.c
@@ -0,0 +1,67 @@
+/*
+ * arch/arm/mach-at91/at91x40.c
+ *
+ * (C) Copyright 2007, Greg Ungerer <gerg@snapgear.com>
+ * Copyright (C) 2005 SAN People
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/arch/at91x40.h>
+#include <asm/arch/at91_st.h>
+#include "generic.h"
+
+/*
+ * This is used in the gpio code, stub locally.
+ */
+int clk_enable(struct clk *clk)
+{
+ return 0;
+}
+
+void __init at91x40_initialize(unsigned long main_clock)
+{
+ at91_extern_irq = (1 << AT91X40_ID_IRQ0) | (1 << AT91X40_ID_IRQ1)
+ | (1 << AT91X40_ID_IRQ2);
+}
+
+/*
+ * The default interrupt priority levels (0 = lowest, 7 = highest).
+ */
+static unsigned int at91x40_default_irq_priority[NR_AIC_IRQS] __initdata = {
+ 7, /* Advanced Interrupt Controller (FIQ) */
+ 0, /* System Peripherals */
+ 0, /* USART 0 */
+ 0, /* USART 1 */
+ 2, /* Timer Counter 0 */
+ 2, /* Timer Counter 1 */
+ 2, /* Timer Counter 2 */
+ 0, /* Watchdog timer */
+ 0, /* Parallel IO Controller A */
+ 0, /* Reserved */
+ 0, /* Reserved */
+ 0, /* Reserved */
+ 0, /* Reserved */
+ 0, /* Reserved */
+ 0, /* Reserved */
+ 0, /* Reserved */
+ 0, /* External IRQ0 */
+ 0, /* External IRQ1 */
+ 0, /* External IRQ2 */
+};
+
+void __init at91x40_init_interrupts(unsigned int priority[NR_AIC_IRQS])
+{
+ if (!priority)
+ priority = at91x40_default_irq_priority;
+
+ at91_aic_init(priority);
+}
+
diff --git a/arch/arm/mach-at91/at91x40_time.c b/arch/arm/mach-at91/at91x40_time.c
new file mode 100644
index 000000000000..eddc882f1b4a
--- /dev/null
+++ b/arch/arm/mach-at91/at91x40_time.c
@@ -0,0 +1,80 @@
+/*
+ * arch/arm/mach-at91/at91x40_time.c
+ *
+ * (C) Copyright 2007, Greg Ungerer <gerg@snapgear.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/time.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach/time.h>
+#include <asm/arch/at91_tc.h>
+
+/*
+ * 3 counter/timer units present.
+ */
+#define AT91_TC_CLK0BASE 0
+#define AT91_TC_CLK1BASE 0x40
+#define AT91_TC_CLK2BASE 0x80
+
+static unsigned long at91x40_gettimeoffset(void)
+{
+ return (at91_sys_read(AT91_TC + AT91_TC_CLK1BASE + AT91_TC_CV) * 1000000 / (AT91X40_MASTER_CLOCK / 128));
+}
+
+static irqreturn_t at91x40_timer_interrupt(int irq, void *dev_id)
+{
+ at91_sys_read(AT91_TC + AT91_TC_CLK1BASE + AT91_TC_SR);
+ timer_tick();
+ return IRQ_HANDLED;
+}
+
+static struct irqaction at91x40_timer_irq = {
+ .name = "at91_tick",
+ .flags = IRQF_DISABLED | IRQF_TIMER,
+ .handler = at91x40_timer_interrupt
+};
+
+void __init at91x40_timer_init(void)
+{
+ unsigned int v;
+
+ at91_sys_write(AT91_TC + AT91_TC_BCR, 0);
+ v = at91_sys_read(AT91_TC + AT91_TC_BMR);
+ v = (v & ~AT91_TC_TC1XC1S) | AT91_TC_TC1XC1S_NONE;
+ at91_sys_write(AT91_TC + AT91_TC_BMR, v);
+
+ at91_sys_write(AT91_TC + AT91_TC_CLK1BASE + AT91_TC_CCR, AT91_TC_CLKDIS);
+ at91_sys_write(AT91_TC + AT91_TC_CLK1BASE + AT91_TC_CMR, (AT91_TC_TIMER_CLOCK4 | AT91_TC_CPCTRG));
+ at91_sys_write(AT91_TC + AT91_TC_CLK1BASE + AT91_TC_IDR, 0xffffffff);
+ at91_sys_write(AT91_TC + AT91_TC_CLK1BASE + AT91_TC_RC, (AT91X40_MASTER_CLOCK / 128) / HZ - 1);
+ at91_sys_write(AT91_TC + AT91_TC_CLK1BASE + AT91_TC_IER, (1<<4));
+
+ setup_irq(AT91X40_ID_TC1, &at91x40_timer_irq);
+
+ at91_sys_write(AT91_TC + AT91_TC_CLK1BASE + AT91_TC_CCR, (AT91_TC_SWTRG | AT91_TC_CLKEN));
+}
+
+struct sys_timer at91x40_timer = {
+ .init = at91x40_timer_init,
+ .offset = at91x40_gettimeoffset,
+};
+
diff --git a/arch/arm/mach-at91/board-eb01.c b/arch/arm/mach-at91/board-eb01.c
new file mode 100644
index 000000000000..0c1e3858e7df
--- /dev/null
+++ b/arch/arm/mach-at91/board-eb01.c
@@ -0,0 +1,44 @@
+/*
+ * arch/arm/mach-at91/board-eb01.c
+ *
+ * (C) Copyright 2007, Greg Ungerer <gerg@snapgear.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/arch/board.h>
+#include "generic.h"
+
+static void __init at91eb01_map_io(void)
+{
+ at91x40_initialize(40000000);
+}
+
+MACHINE_START(AT91EB01, "Atmel AT91 EB01")
+ /* Maintainer: Greg Ungerer <gerg@snapgear.com> */
+ .timer = &at91x40_timer,
+ .init_irq = at91x40_init_interrupts,
+ .map_io = at91eb01_map_io,
+MACHINE_END
+
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
index 68ed71a3e6c6..77d4c0a37842 100644
--- a/arch/arm/mach-at91/generic.h
+++ b/arch/arm/mach-at91/generic.h
@@ -14,6 +14,7 @@ extern void __init at91sam9260_initialize(unsigned long main_clock);
extern void __init at91sam9261_initialize(unsigned long main_clock);
extern void __init at91sam9263_initialize(unsigned long main_clock);
extern void __init at91sam9rl_initialize(unsigned long main_clock);
+extern void __init at91x40_initialize(unsigned long main_clock);
/* Interrupts */
extern void __init at91rm9200_init_interrupts(unsigned int priority[]);
@@ -21,12 +22,14 @@ extern void __init at91sam9260_init_interrupts(unsigned int priority[]);
extern void __init at91sam9261_init_interrupts(unsigned int priority[]);
extern void __init at91sam9263_init_interrupts(unsigned int priority[]);
extern void __init at91sam9rl_init_interrupts(unsigned int priority[]);
+extern void __init at91x40_init_interrupts(unsigned int priority[]);
extern void __init at91_aic_init(unsigned int priority[]);
/* Timer */
struct sys_timer;
extern struct sys_timer at91rm9200_timer;
extern struct sys_timer at91sam926x_timer;
+extern struct sys_timer at91x40_timer;
/* Clocks */
extern int __init at91_clock_init(unsigned long main_clock);
diff --git a/arch/arm/mach-at91/gpio.c b/arch/arm/mach-at91/gpio.c
index ba4a1bb3ee40..aa2d365c93fb 100644
--- a/arch/arm/mach-at91/gpio.c
+++ b/arch/arm/mach-at91/gpio.c
@@ -439,7 +439,7 @@ void __init at91_gpio_irq_setup(void)
for (i = 0; i < 32; i++, pin++) {
/*
* Can use the "simple" and not "edge" handler since it's
- * shorter, and the AIC handles interupts sanely.
+ * shorter, and the AIC handles interrupts sanely.
*/
set_irq_chip(pin, &gpio_irqchip);
set_irq_handler(pin, handle_simple_irq);
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index ddf9184d561d..98cb61482917 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -10,10 +10,9 @@
* (at your option) any later version.
*/
-#include <linux/pm.h>
+#include <linux/suspend.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
-#include <linux/pm.h>
#include <linux/interrupt.h>
#include <linux/sysfs.h>
#include <linux/module.h>
@@ -199,7 +198,7 @@ error:
}
-static struct pm_ops at91_pm_ops ={
+static struct platform_suspend_ops at91_pm_ops ={
.valid = at91_pm_valid_state,
.set_target = at91_pm_set_target,
.enter = at91_pm_enter,
@@ -220,7 +219,7 @@ static int __init at91_pm_init(void)
/* Disable SDRAM low-power mode. Cannot be used with self-refresh. */
at91_sys_write(AT91_SDRAMC_LPR, 0);
- pm_set_ops(&at91_pm_ops);
+ suspend_set_ops(&at91_pm_ops);
return 0;
}
diff --git a/arch/arm/mach-clps7500/core.c b/arch/arm/mach-clps7500/core.c
index 4dde34f25e63..986205ec9269 100644
--- a/arch/arm/mach-clps7500/core.c
+++ b/arch/arm/mach-clps7500/core.c
@@ -193,7 +193,11 @@ static struct irq_chip clps7500_no_chip = {
.unmask = cl7500_no_action,
};
-static struct irqaction irq_isa = { no_action, 0, CPU_MASK_NONE, "isa", NULL, NULL };
+static struct irqaction irq_isa = {
+ .handler = no_action,
+ .mask = CPU_MASK_NONE,
+ .name = "isa",
+};
static void __init clps7500_init_irq(void)
{
diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig
index 575a21dabd2f..ea8549bfbef2 100644
--- a/arch/arm/mach-ep93xx/Kconfig
+++ b/arch/arm/mach-ep93xx/Kconfig
@@ -27,6 +27,12 @@ config MACH_EDB9302A
Say 'Y' here if you want your kernel to support the Cirrus
Logic EDB9302A Evaluation Board.
+config MACH_EDB9307
+ bool "Support Cirrus Logic EDB9307"
+ help
+ Say 'Y' here if you want your kernel to support the Cirrus
+ Logic EDB9307 Evaluation Board.
+
config MACH_EDB9312
bool "Support Cirrus Logic EDB9312"
help
diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile
index 0d3bf932654e..0ecf99761feb 100644
--- a/arch/arm/mach-ep93xx/Makefile
+++ b/arch/arm/mach-ep93xx/Makefile
@@ -9,6 +9,7 @@ obj- :=
obj-$(CONFIG_MACH_ADSSPHERE) += adssphere.o
obj-$(CONFIG_MACH_EDB9302) += edb9302.o
obj-$(CONFIG_MACH_EDB9302A) += edb9302a.o
+obj-$(CONFIG_MACH_EDB9307) += edb9307.o
obj-$(CONFIG_MACH_EDB9312) += edb9312.o
obj-$(CONFIG_MACH_EDB9315) += edb9315.o
obj-$(CONFIG_MACH_EDB9315A) += edb9315a.o
diff --git a/arch/arm/mach-ep93xx/edb9307.c b/arch/arm/mach-ep93xx/edb9307.c
new file mode 100644
index 000000000000..d6a5698da91f
--- /dev/null
+++ b/arch/arm/mach-ep93xx/edb9307.c
@@ -0,0 +1,91 @@
+/*
+ * arch/arm/mach-ep93xx/edb9307.c
+ * Cirrus Logic EDB9307 support.
+ *
+ * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+static struct physmap_flash_data edb9307_flash_data = {
+ .width = 4,
+};
+
+static struct resource edb9307_flash_resource = {
+ .start = 0x60000000,
+ .end = 0x61ffffff,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device edb9307_flash = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &edb9307_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &edb9307_flash_resource,
+};
+
+static struct ep93xx_eth_data edb9307_eth_data = {
+ .phy_id = 1,
+};
+
+static struct resource edb9307_eth_resource[] = {
+ {
+ .start = EP93XX_ETHERNET_PHYS_BASE,
+ .end = EP93XX_ETHERNET_PHYS_BASE + 0xffff,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_EP93XX_ETHERNET,
+ .end = IRQ_EP93XX_ETHERNET,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device edb9307_eth_device = {
+ .name = "ep93xx-eth",
+ .id = -1,
+ .dev = {
+ .platform_data = &edb9307_eth_data,
+ },
+ .num_resources = 2,
+ .resource = edb9307_eth_resource,
+};
+
+static void __init edb9307_init_machine(void)
+{
+ ep93xx_init_devices();
+ platform_device_register(&edb9307_flash);
+
+ memcpy(edb9307_eth_data.dev_addr,
+ (void *)(EP93XX_ETHERNET_BASE + 0x50), 6);
+ platform_device_register(&edb9307_eth_device);
+}
+
+MACHINE_START(EDB9307, "Cirrus Logic EDB9307 Evaluation Board")
+ /* Maintainer: Herbert Valerio Riedel <hvr@gnu.org> */
+ .phys_io = EP93XX_APB_PHYS_BASE,
+ .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
+ .boot_params = 0x00000100,
+ .map_io = ep93xx_map_io,
+ .init_irq = ep93xx_init_irq,
+ .timer = &ep93xx_timer,
+ .init_machine = edb9307_init_machine,
+MACHINE_END
diff --git a/arch/arm/mach-footbridge/cats-hw.c b/arch/arm/mach-footbridge/cats-hw.c
index ef6ccc8993e9..c261472208cb 100644
--- a/arch/arm/mach-footbridge/cats-hw.c
+++ b/arch/arm/mach-footbridge/cats-hw.c
@@ -78,9 +78,9 @@ static void __init
fixup_cats(struct machine_desc *desc, struct tag *tags,
char **cmdline, struct meminfo *mi)
{
- ORIG_VIDEO_LINES = 25;
- ORIG_VIDEO_POINTS = 16;
- ORIG_Y = 24;
+ screen_info.orig_video_lines = 25;
+ screen_info.orig_video_points = 16;
+ screen_info.orig_y = 24;
}
MACHINE_START(CATS, "Chalice-CATS")
diff --git a/arch/arm/mach-footbridge/isa.c b/arch/arm/mach-footbridge/isa.c
index 28846c7edaaf..725a219d0ed5 100644
--- a/arch/arm/mach-footbridge/isa.c
+++ b/arch/arm/mach-footbridge/isa.c
@@ -12,6 +12,39 @@
#include <asm/irq.h>
+static struct resource rtc_resources[] = {
+ [0] = {
+ .start = 0x70,
+ .end = 0x73,
+ .flags = IORESOURCE_IO,
+ },
+ [1] = {
+ .start = IRQ_ISA_RTC_ALARM,
+ .end = IRQ_ISA_RTC_ALARM,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device rtc_device = {
+ .name = "rtc_cmos",
+ .id = -1,
+ .resource = rtc_resources,
+ .num_resources = ARRAY_SIZE(rtc_resources),
+};
+
+static struct resource serial_resources[] = {
+ [0] = {
+ .start = 0x3f8,
+ .end = 0x3ff,
+ .flags = IORESOURCE_IO,
+ },
+ [1] = {
+ .start = 0x2f8,
+ .end = 0x2ff,
+ .flags = IORESOURCE_IO,
+ },
+};
+
static struct plat_serial8250_port serial_platform_data[] = {
{
.iobase = 0x3f8,
@@ -38,11 +71,21 @@ static struct platform_device serial_device = {
.dev = {
.platform_data = serial_platform_data,
},
+ .resource = serial_resources,
+ .num_resources = ARRAY_SIZE(serial_resources),
};
static int __init footbridge_isa_init(void)
{
- return platform_device_register(&serial_device);
+ int err;
+
+ err = platform_device_register(&rtc_device);
+ if (err)
+ printk(KERN_ERR "Unable to register RTC device: %d\n", err);
+ err = platform_device_register(&serial_device);
+ if (err)
+ printk(KERN_ERR "Unable to register serial device: %d\n", err);
+ return 0;
}
arch_initcall(footbridge_isa_init);
diff --git a/arch/arm/mach-iop32x/n2100.c b/arch/arm/mach-iop32x/n2100.c
index 1873bd8cd1b2..bc91d6e66bc4 100644
--- a/arch/arm/mach-iop32x/n2100.c
+++ b/arch/arm/mach-iop32x/n2100.c
@@ -16,6 +16,7 @@
#include <linux/mm.h>
#include <linux/init.h>
+#include <linux/f75375s.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/pci.h>
@@ -200,11 +201,21 @@ static struct platform_device n2100_serial_device = {
.resource = &n2100_uart_resource,
};
+static struct f75375s_platform_data n2100_f75375s = {
+ .pwm = { 255, 255 },
+ .pwm_enable = { 0, 0 },
+};
+
static struct i2c_board_info __initdata n2100_i2c_devices[] = {
{
I2C_BOARD_INFO("rtc-rs5c372", 0x32),
.type = "rs5c372b",
},
+ {
+ I2C_BOARD_INFO("f75375", 0x2e),
+ .type = "f75375",
+ .platform_data = &n2100_f75375s,
+ },
};
/*
diff --git a/arch/arm/mach-ixp2000/Kconfig b/arch/arm/mach-ixp2000/Kconfig
index 86f53f8ccbf5..08d2707f6ca8 100644
--- a/arch/arm/mach-ixp2000/Kconfig
+++ b/arch/arm/mach-ixp2000/Kconfig
@@ -14,7 +14,7 @@ config ARCH_ENP2611
help
Say 'Y' here if you want your kernel to support the Radisys
ENP2611 PCI network processing card. For more information on
- this card, see <file:Documentation/arm/ENP2611>.
+ this card, see <file:Documentation/arm/IXP2000>.
config ARCH_IXDP2400
bool "Support Intel IXDP2400"
diff --git a/arch/arm/mach-netx/xc.c b/arch/arm/mach-netx/xc.c
index 172a058ddd66..ca9c5b61283a 100644
--- a/arch/arm/mach-netx/xc.c
+++ b/arch/arm/mach-netx/xc.c
@@ -190,15 +190,15 @@ struct xc *request_xc(int xcno, struct device *dev)
goto exit;
if (!request_mem_region
- (NETX_PA_XPEC(xcno), XPEC_MEM_SIZE, dev->kobj.name))
+ (NETX_PA_XPEC(xcno), XPEC_MEM_SIZE, kobject_name(&dev->kobj)))
goto exit_free;
if (!request_mem_region
- (NETX_PA_XMAC(xcno), XMAC_MEM_SIZE, dev->kobj.name))
+ (NETX_PA_XMAC(xcno), XMAC_MEM_SIZE, kobject_name(&dev->kobj)))
goto exit_release_1;
if (!request_mem_region
- (SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE, dev->kobj.name))
+ (SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE, kobject_name(&dev->kobj)))
goto exit_release_2;
x->xpec_base = (void * __iomem)io_p2v(NETX_PA_XPEC(xcno));
diff --git a/arch/arm/mach-ns9xxx/Makefile b/arch/arm/mach-ns9xxx/Makefile
index 4476411b8140..6fb82b855a55 100644
--- a/arch/arm/mach-ns9xxx/Makefile
+++ b/arch/arm/mach-ns9xxx/Makefile
@@ -1,4 +1,4 @@
-obj-y := irq.o time.o generic.o
+obj-y := irq.o time.o generic.o gpio.o
obj-$(CONFIG_MACH_CC9P9360DEV) += mach-cc9p9360dev.o
obj-$(CONFIG_MACH_CC9P9360JS) += mach-cc9p9360js.o
diff --git a/arch/arm/mach-ns9xxx/board-a9m9750dev.c b/arch/arm/mach-ns9xxx/board-a9m9750dev.c
index 925048e7adfe..0f65177f9e5f 100644
--- a/arch/arm/mach-ns9xxx/board-a9m9750dev.c
+++ b/arch/arm/mach-ns9xxx/board-a9m9750dev.c
@@ -13,6 +13,7 @@
#include <linux/irq.h>
#include <asm/mach/map.h>
+#include <asm/gpio.h>
#include <asm/arch-ns9xxx/board.h>
#include <asm/arch-ns9xxx/regs-sys.h>
@@ -44,7 +45,13 @@ static void a9m9750dev_fpga_ack_irq(unsigned int irq)
static void a9m9750dev_fpga_mask_irq(unsigned int irq)
{
- FPGA_IER &= ~(1 << (irq - FPGA_IRQ(0)));
+ u8 ier;
+
+ ier = __raw_readb(FPGA_IER);
+
+ ier &= ~(1 << (irq - FPGA_IRQ(0)));
+
+ __raw_writeb(ier, FPGA_IER);
}
static void a9m9750dev_fpga_maskack_irq(unsigned int irq)
@@ -55,7 +62,13 @@ static void a9m9750dev_fpga_maskack_irq(unsigned int irq)
static void a9m9750dev_fpga_unmask_irq(unsigned int irq)
{
- FPGA_IER |= 1 << (irq - FPGA_IRQ(0));
+ u8 ier;
+
+ ier = __raw_readb(FPGA_IER);
+
+ ier |= 1 << (irq - FPGA_IRQ(0));
+
+ __raw_writeb(ier, FPGA_IER);
}
static struct irq_chip a9m9750dev_fpga_chip = {
@@ -68,30 +81,34 @@ static struct irq_chip a9m9750dev_fpga_chip = {
static void a9m9750dev_fpga_demux_handler(unsigned int irq,
struct irq_desc *desc)
{
- int stat = FPGA_ISR;
+ u8 stat = __raw_readb(FPGA_ISR);
+
+ desc->chip->mask_ack(irq);
while (stat != 0) {
int irqno = fls(stat) - 1;
+ struct irq_desc *fpgadesc;
stat &= ~(1 << irqno);
- desc = irq_desc + FPGA_IRQ(irqno);
+ fpgadesc = irq_desc + FPGA_IRQ(irqno);
- desc_handle_irq(FPGA_IRQ(irqno), desc);
+ desc_handle_irq(FPGA_IRQ(irqno), fpgadesc);
}
+
+ desc->chip->unmask(irq);
}
void __init board_a9m9750dev_init_irq(void)
{
- u32 reg;
+ u32 eic;
int i;
- /*
- * configure gpio for IRQ_EXT2
- * use GPIO 11, because GPIO 32 is used for the LCD
- */
- /* XXX: proper GPIO handling */
- BBU_GCONFb1(1) &= ~0x2000;
+ if (gpio_request(11, "board a9m9750dev extirq2") == 0)
+ ns9xxx_gpio_configure(11, 0, 1);
+ else
+ printk(KERN_ERR "%s: cannot get gpio 11 for IRQ_EXT2\n",
+ __func__);
for (i = FPGA_IRQ(0); i <= FPGA_IRQ(7); ++i) {
set_irq_chip(i, &a9m9750dev_fpga_chip);
@@ -100,10 +117,10 @@ void __init board_a9m9750dev_init_irq(void)
}
/* IRQ_EXT2: level sensitive + active low */
- reg = SYS_EIC(2);
- REGSET(reg, SYS_EIC, PLTY, AL);
- REGSET(reg, SYS_EIC, LVEDG, LEVEL);
- SYS_EIC(2) = reg;
+ eic = __raw_readl(SYS_EIC(2));
+ REGSET(eic, SYS_EIC, PLTY, AL);
+ REGSET(eic, SYS_EIC, LVEDG, LEVEL);
+ __raw_writel(eic, SYS_EIC(2));
set_irq_chained_handler(IRQ_EXT2,
a9m9750dev_fpga_demux_handler);
@@ -167,17 +184,18 @@ void __init board_a9m9750dev_init_machine(void)
u32 reg;
/* setup static CS0: memory base ... */
- REGSETIM(SYS_SMCSSMB(0), SYS_SMCSSMB, CSxB,
- NS9XXX_CSxSTAT_PHYS(0) >> 12);
+ reg = __raw_readl(SYS_SMCSSMB(0));
+ REGSETIM(reg, SYS_SMCSSMB, CSxB, NS9XXX_CSxSTAT_PHYS(0) >> 12);
+ __raw_writel(reg, SYS_SMCSSMB(0));
/* ... and mask */
- reg = SYS_SMCSSMM(0);
+ reg = __raw_readl(SYS_SMCSSMM(0));
REGSETIM(reg, SYS_SMCSSMM, CSxM, 0xfffff);
REGSET(reg, SYS_SMCSSMM, CSEx, EN);
- SYS_SMCSSMM(0) = reg;
+ __raw_writel(reg, SYS_SMCSSMM(0));
/* setup static CS0: memory configuration */
- reg = MEM_SMC(0);
+ reg = __raw_readl(MEM_SMC(0));
REGSET(reg, MEM_SMC, PSMC, OFF);
REGSET(reg, MEM_SMC, BSMC, OFF);
REGSET(reg, MEM_SMC, EW, OFF);
@@ -185,13 +203,13 @@ void __init board_a9m9750dev_init_machine(void)
REGSET(reg, MEM_SMC, PC, AL);
REGSET(reg, MEM_SMC, PM, DIS);
REGSET(reg, MEM_SMC, MW, 8);
- MEM_SMC(0) = reg;
+ __raw_writel(reg, MEM_SMC(0));
/* setup static CS0: timing */
- MEM_SMWED(0) = 0x2;
- MEM_SMOED(0) = 0x2;
- MEM_SMRD(0) = 0x6;
- MEM_SMWD(0) = 0x6;
+ __raw_writel(0x2, MEM_SMWED(0));
+ __raw_writel(0x2, MEM_SMOED(0));
+ __raw_writel(0x6, MEM_SMRD(0));
+ __raw_writel(0x6, MEM_SMWD(0));
platform_add_devices(board_a9m9750dev_devices,
ARRAY_SIZE(board_a9m9750dev_devices));
diff --git a/arch/arm/mach-ns9xxx/gpio.c b/arch/arm/mach-ns9xxx/gpio.c
new file mode 100644
index 000000000000..b2230213b983
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/gpio.c
@@ -0,0 +1,190 @@
+/*
+ * arch/arm/mach-ns9xxx/gpio.c
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <linux/compiler.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+
+#include <asm/arch-ns9xxx/gpio.h>
+#include <asm/arch-ns9xxx/processor.h>
+#include <asm/arch-ns9xxx/regs-bbu.h>
+#include <asm/io.h>
+#include <asm/bug.h>
+#include <asm/types.h>
+#include <asm/bitops.h>
+
+#if defined(CONFIG_PROCESSOR_NS9360)
+#define GPIO_MAX 72
+#elif defined(CONFIG_PROCESSOR_NS9750)
+#define GPIO_MAX 49
+#endif
+
+/* protects BBU_GCONFx and BBU_GCTRLx */
+static spinlock_t gpio_lock = __SPIN_LOCK_UNLOCKED(gpio_lock);
+
+/* only access gpiores with atomic ops */
+static DECLARE_BITMAP(gpiores, GPIO_MAX);
+
+static inline int ns9xxx_valid_gpio(unsigned gpio)
+{
+#if defined(CONFIG_PROCESSOR_NS9360)
+ if (processor_is_ns9360())
+ return gpio <= 72;
+ else
+#endif
+#if defined(CONFIG_PROCESSOR_NS9750)
+ if (processor_is_ns9750())
+ return gpio <= 49;
+ else
+#endif
+ BUG();
+}
+
+static inline void __iomem *ns9xxx_gpio_get_gconfaddr(unsigned gpio)
+{
+ if (gpio < 56)
+ return BBU_GCONFb1(gpio / 8);
+ else
+ /*
+ * this could be optimised away on
+ * ns9750 only builds, but it isn't ...
+ */
+ return BBU_GCONFb2((gpio - 56) / 8);
+}
+
+static inline void __iomem *ns9xxx_gpio_get_gctrladdr(unsigned gpio)
+{
+ if (gpio < 32)
+ return BBU_GCTRL1;
+ else if (gpio < 64)
+ return BBU_GCTRL2;
+ else
+ /* this could be optimised away on ns9750 only builds */
+ return BBU_GCTRL3;
+}
+
+static inline void __iomem *ns9xxx_gpio_get_gstataddr(unsigned gpio)
+{
+ if (gpio < 32)
+ return BBU_GSTAT1;
+ else if (gpio < 64)
+ return BBU_GSTAT2;
+ else
+ /* this could be optimised away on ns9750 only builds */
+ return BBU_GSTAT3;
+}
+
+int gpio_request(unsigned gpio, const char *label)
+{
+ if (likely(ns9xxx_valid_gpio(gpio)))
+ return test_and_set_bit(gpio, gpiores) ? -EBUSY : 0;
+ else
+ return -EINVAL;
+}
+EXPORT_SYMBOL(gpio_request);
+
+void gpio_free(unsigned gpio)
+{
+ clear_bit(gpio, gpiores);
+ return;
+}
+EXPORT_SYMBOL(gpio_free);
+
+/*
+ * each gpio can serve for 4 different purposes [0..3]. These are called
+ * "functions" and passed in the parameter func. Functions 0-2 are always some
+ * special things, function 3 is GPIO. If func == 3 dir specifies input or
+ * output, and with inv you can enable an inverter (independent of func).
+ */
+static int __ns9xxx_gpio_configure(unsigned gpio, int dir, int inv, int func)
+{
+ void __iomem *conf = ns9xxx_gpio_get_gconfaddr(gpio);
+ u32 confval;
+ unsigned long flags;
+
+ spin_lock_irqsave(&gpio_lock, flags);
+
+ confval = __raw_readl(conf);
+ REGSETIM_IDX(confval, BBU_GCONFx, DIR, gpio & 7, dir);
+ REGSETIM_IDX(confval, BBU_GCONFx, INV, gpio & 7, inv);
+ REGSETIM_IDX(confval, BBU_GCONFx, FUNC, gpio & 7, func);
+ __raw_writel(confval, conf);
+
+ spin_unlock_irqrestore(&gpio_lock, flags);
+
+ return 0;
+}
+
+int ns9xxx_gpio_configure(unsigned gpio, int inv, int func)
+{
+ if (likely(ns9xxx_valid_gpio(gpio))) {
+ if (func == 3) {
+ printk(KERN_WARNING "use gpio_direction_input "
+ "or gpio_direction_output\n");
+ return -EINVAL;
+ } else
+ return __ns9xxx_gpio_configure(gpio, 0, inv, func);
+ } else
+ return -EINVAL;
+}
+EXPORT_SYMBOL(ns9xxx_gpio_configure);
+
+int gpio_direction_input(unsigned gpio)
+{
+ if (likely(ns9xxx_valid_gpio(gpio))) {
+ return __ns9xxx_gpio_configure(gpio, 0, 0, 3);
+ } else
+ return -EINVAL;
+}
+EXPORT_SYMBOL(gpio_direction_input);
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+ if (likely(ns9xxx_valid_gpio(gpio))) {
+ gpio_set_value(gpio, value);
+
+ return __ns9xxx_gpio_configure(gpio, 1, 0, 3);
+ } else
+ return -EINVAL;
+}
+EXPORT_SYMBOL(gpio_direction_output);
+
+int gpio_get_value(unsigned gpio)
+{
+ void __iomem *stat = ns9xxx_gpio_get_gstataddr(gpio);
+ int ret;
+
+ ret = 1 & (__raw_readl(stat) >> (gpio & 31));
+
+ return ret;
+}
+EXPORT_SYMBOL(gpio_get_value);
+
+void gpio_set_value(unsigned gpio, int value)
+{
+ void __iomem *ctrl = ns9xxx_gpio_get_gctrladdr(gpio);
+ u32 ctrlval;
+ unsigned long flags;
+
+ spin_lock_irqsave(&gpio_lock, flags);
+
+ ctrlval = __raw_readl(ctrl);
+
+ if (value)
+ ctrlval |= 1 << (gpio & 31);
+ else
+ ctrlval &= ~(1 << (gpio & 31));
+
+ __raw_writel(ctrlval, ctrl);
+
+ spin_unlock_irqrestore(&gpio_lock, flags);
+}
+EXPORT_SYMBOL(gpio_set_value);
diff --git a/arch/arm/mach-ns9xxx/irq.c b/arch/arm/mach-ns9xxx/irq.c
index b8c7b00522e6..00001b874e97 100644
--- a/arch/arm/mach-ns9xxx/irq.c
+++ b/arch/arm/mach-ns9xxx/irq.c
@@ -9,6 +9,7 @@
* the Free Software Foundation.
*/
#include <linux/interrupt.h>
+#include <asm/io.h>
#include <asm/mach/irq.h>
#include <asm/mach-types.h>
#include <asm/arch-ns9xxx/regs-sys.h>
@@ -17,48 +18,17 @@
#include "generic.h"
-static void ns9xxx_ack_irq_timer(unsigned int irq)
-{
- u32 tc = SYS_TC(irq - IRQ_TIMER0);
-
- /*
- * If the timer is programmed to halt on terminal count, the
- * timer must be disabled before clearing the interrupt.
- */
- if (REGGET(tc, SYS_TCx, REN) == 0) {
- REGSET(tc, SYS_TCx, TEN, DIS);
- SYS_TC(irq - IRQ_TIMER0) = tc;
- }
-
- REGSET(tc, SYS_TCx, INTC, SET);
- SYS_TC(irq - IRQ_TIMER0) = tc;
-
- REGSET(tc, SYS_TCx, INTC, UNSET);
- SYS_TC(irq - IRQ_TIMER0) = tc;
-}
-
-static void (*ns9xxx_ack_irq_functions[NR_IRQS])(unsigned int) = {
- [IRQ_TIMER0] = ns9xxx_ack_irq_timer,
- [IRQ_TIMER1] = ns9xxx_ack_irq_timer,
- [IRQ_TIMER2] = ns9xxx_ack_irq_timer,
- [IRQ_TIMER3] = ns9xxx_ack_irq_timer,
-};
-
static void ns9xxx_mask_irq(unsigned int irq)
{
/* XXX: better use cpp symbols */
- SYS_IC(irq / 4) &= ~(1 << (7 + 8 * (3 - (irq & 3))));
+ u32 ic = __raw_readl(SYS_IC(irq / 4));
+ ic &= ~(1 << (7 + 8 * (3 - (irq & 3))));
+ __raw_writel(ic, SYS_IC(irq / 4));
}
static void ns9xxx_ack_irq(unsigned int irq)
{
- if (!ns9xxx_ack_irq_functions[irq]) {
- printk(KERN_ERR "no ack function for irq %u\n", irq);
- BUG();
- }
-
- ns9xxx_ack_irq_functions[irq](irq);
- SYS_ISRADDR = 0;
+ __raw_writel(0, SYS_ISRADDR);
}
static void ns9xxx_maskack_irq(unsigned int irq)
@@ -70,7 +40,9 @@ static void ns9xxx_maskack_irq(unsigned int irq)
static void ns9xxx_unmask_irq(unsigned int irq)
{
/* XXX: better use cpp symbols */
- SYS_IC(irq / 4) |= 1 << (7 + 8 * (3 - (irq & 3)));
+ u32 ic = __raw_readl(SYS_IC(irq / 4));
+ ic |= 1 << (7 + 8 * (3 - (irq & 3)));
+ __raw_writel(ic, SYS_IC(irq / 4));
}
static struct irq_chip ns9xxx_chip = {
@@ -86,14 +58,14 @@ void __init ns9xxx_init_irq(void)
/* disable all IRQs */
for (i = 0; i < 8; ++i)
- SYS_IC(i) = (4 * i) << 24 | (4 * i + 1) << 16 |
- (4 * i + 2) << 8 | (4 * i + 3);
+ __raw_writel((4 * i) << 24 | (4 * i + 1) << 16 |
+ (4 * i + 2) << 8 | (4 * i + 3), SYS_IC(i));
/* simple interrupt prio table:
* prio(x) < prio(y) <=> x < y
*/
for (i = 0; i < 32; ++i)
- SYS_IVA(i) = i;
+ __raw_writel(i, SYS_IVA(i));
for (i = IRQ_WATCHDOG; i <= IRQ_EXT3; ++i) {
set_irq_chip(i, &ns9xxx_chip);
diff --git a/arch/arm/mach-ns9xxx/time.c b/arch/arm/mach-ns9xxx/time.c
index b97d0c54a388..c3dd1f4acb99 100644
--- a/arch/arm/mach-ns9xxx/time.c
+++ b/arch/arm/mach-ns9xxx/time.c
@@ -11,78 +11,174 @@
#include <linux/jiffies.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <linux/stringify.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+
#include <asm/arch-ns9xxx/regs-sys.h>
#include <asm/arch-ns9xxx/clock.h>
#include <asm/arch-ns9xxx/irqs.h>
#include <asm/arch/system.h>
#include "generic.h"
-#define TIMERCLOCKSELECT 64
+#define TIMER_CLOCKSOURCE 0
+#define TIMER_CLOCKEVENT 1
+static u32 latch;
+
+static cycle_t ns9xxx_clocksource_read(void)
+{
+ return __raw_readl(SYS_TR(TIMER_CLOCKSOURCE));
+}
-static u32 usecs_per_tick;
+static struct clocksource ns9xxx_clocksource = {
+ .name = "ns9xxx-timer" __stringify(TIMER_CLOCKSOURCE),
+ .rating = 300,
+ .read = ns9xxx_clocksource_read,
+ .mask = CLOCKSOURCE_MASK(32),
+ .shift = 20,
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
-static irqreturn_t
-ns9xxx_timer_interrupt(int irq, void *dev_id)
+static void ns9xxx_clockevent_setmode(enum clock_event_mode mode,
+ struct clock_event_device *clk)
{
- write_seqlock(&xtime_lock);
- timer_tick();
- write_sequnlock(&xtime_lock);
+ u32 tc = __raw_readl(SYS_TC(TIMER_CLOCKEVENT));
+
+ switch(mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ __raw_writel(latch, SYS_TRC(TIMER_CLOCKEVENT));
+ REGSET(tc, SYS_TCx, REN, EN);
+ REGSET(tc, SYS_TCx, INTS, EN);
+ REGSET(tc, SYS_TCx, TEN, EN);
+ break;
+
+ case CLOCK_EVT_MODE_ONESHOT:
+ REGSET(tc, SYS_TCx, REN, DIS);
+ REGSET(tc, SYS_TCx, INTS, EN);
+
+ /* fall through */
+
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ case CLOCK_EVT_MODE_RESUME:
+ default:
+ REGSET(tc, SYS_TCx, TEN, DIS);
+ break;
+ }
+
+ __raw_writel(tc, SYS_TC(TIMER_CLOCKEVENT));
+}
- return IRQ_HANDLED;
+static int ns9xxx_clockevent_setnextevent(unsigned long evt,
+ struct clock_event_device *clk)
+{
+ u32 tc = __raw_readl(SYS_TC(TIMER_CLOCKEVENT));
+
+ if (REGGET(tc, SYS_TCx, TEN)) {
+ REGSET(tc, SYS_TCx, TEN, DIS);
+ __raw_writel(tc, SYS_TC(TIMER_CLOCKEVENT));
+ }
+
+ REGSET(tc, SYS_TCx, TEN, EN);
+
+ __raw_writel(evt, SYS_TRC(TIMER_CLOCKEVENT));
+
+ __raw_writel(tc, SYS_TC(TIMER_CLOCKEVENT));
+
+ return 0;
}
-static unsigned long ns9xxx_timer_gettimeoffset(void)
+static struct clock_event_device ns9xxx_clockevent_device = {
+ .name = "ns9xxx-timer" __stringify(TIMER_CLOCKEVENT),
+ .shift = 20,
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+ .set_mode = ns9xxx_clockevent_setmode,
+ .set_next_event = ns9xxx_clockevent_setnextevent,
+};
+
+static irqreturn_t ns9xxx_clockevent_handler(int irq, void *dev_id)
{
- /* return the microseconds which have passed since the last interrupt
- * was _serviced_. That is, if an interrupt is pending or the counter
- * reloads, return one period more. */
+ int timerno = irq - IRQ_TIMER0;
+ u32 tc;
- u32 counter1 = SYS_TR(0);
- int pending = SYS_ISR & (1 << IRQ_TIMER0);
- u32 counter2 = SYS_TR(0);
- u32 elapsed;
+ struct clock_event_device *evt = &ns9xxx_clockevent_device;
- if (pending || counter2 > counter1)
- elapsed = 2 * SYS_TRC(0) - counter2;
- else
- elapsed = SYS_TRC(0) - counter1;
+ /* clear irq */
+ tc = __raw_readl(SYS_TC(timerno));
+ if (REGGET(tc, SYS_TCx, REN) == SYS_TCx_REN_DIS) {
+ REGSET(tc, SYS_TCx, TEN, DIS);
+ __raw_writel(tc, SYS_TC(timerno));
+ }
+ REGSET(tc, SYS_TCx, INTC, SET);
+ __raw_writel(tc, SYS_TC(timerno));
+ REGSET(tc, SYS_TCx, INTC, UNSET);
+ __raw_writel(tc, SYS_TC(timerno));
- return (elapsed * usecs_per_tick) >> 16;
+ evt->event_handler(evt);
+ return IRQ_HANDLED;
}
-static struct irqaction ns9xxx_timer_irq = {
- .name = "NS9xxx Timer Tick",
- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
- .handler = ns9xxx_timer_interrupt,
+static struct irqaction ns9xxx_clockevent_action = {
+ .name = "ns9xxx-timer" __stringify(TIMER_CLOCKEVENT),
+ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+ .handler = ns9xxx_clockevent_handler,
};
static void __init ns9xxx_timer_init(void)
{
int tc;
- usecs_per_tick =
- SH_DIV(1000000 * TIMERCLOCKSELECT, ns9xxx_cpuclock(), 16);
+ tc = __raw_readl(SYS_TC(TIMER_CLOCKSOURCE));
+ if (REGGET(tc, SYS_TCx, TEN)) {
+ REGSET(tc, SYS_TCx, TEN, DIS);
+ __raw_writel(tc, SYS_TC(TIMER_CLOCKSOURCE));
+ }
- /* disable timer */
- if ((tc = SYS_TC(0)) & SYS_TCx_TEN)
- SYS_TC(0) = tc & ~SYS_TCx_TEN;
-
- SYS_TRC(0) = SH_DIV(ns9xxx_cpuclock(), (TIMERCLOCKSELECT * HZ), 0);
+ __raw_writel(0, SYS_TRC(TIMER_CLOCKSOURCE));
REGSET(tc, SYS_TCx, TEN, EN);
- REGSET(tc, SYS_TCx, TLCS, DIV64); /* This must match TIMERCLOCKSELECT */
- REGSET(tc, SYS_TCx, INTS, EN);
- REGSET(tc, SYS_TCx, UDS, DOWN);
REGSET(tc, SYS_TCx, TDBG, STOP);
+ REGSET(tc, SYS_TCx, TLCS, CPU);
+ REGSET(tc, SYS_TCx, TM, IEE);
+ REGSET(tc, SYS_TCx, INTS, DIS);
+ REGSET(tc, SYS_TCx, UDS, UP);
REGSET(tc, SYS_TCx, TSZ, 32);
REGSET(tc, SYS_TCx, REN, EN);
- SYS_TC(0) = tc;
- setup_irq(IRQ_TIMER0, &ns9xxx_timer_irq);
+ __raw_writel(tc, SYS_TC(TIMER_CLOCKSOURCE));
+
+ ns9xxx_clocksource.mult = clocksource_hz2mult(ns9xxx_cpuclock(),
+ ns9xxx_clocksource.shift);
+
+ clocksource_register(&ns9xxx_clocksource);
+
+ latch = SH_DIV(ns9xxx_cpuclock(), HZ, 0);
+
+ tc = __raw_readl(SYS_TC(TIMER_CLOCKEVENT));
+ REGSET(tc, SYS_TCx, TEN, DIS);
+ REGSET(tc, SYS_TCx, TDBG, STOP);
+ REGSET(tc, SYS_TCx, TLCS, CPU);
+ REGSET(tc, SYS_TCx, TM, IEE);
+ REGSET(tc, SYS_TCx, INTS, DIS);
+ REGSET(tc, SYS_TCx, UDS, DOWN);
+ REGSET(tc, SYS_TCx, TSZ, 32);
+ REGSET(tc, SYS_TCx, REN, EN);
+ __raw_writel(tc, SYS_TC(TIMER_CLOCKEVENT));
+
+ ns9xxx_clockevent_device.mult = div_sc(ns9xxx_cpuclock(),
+ NSEC_PER_SEC, ns9xxx_clockevent_device.shift);
+ ns9xxx_clockevent_device.max_delta_ns =
+ clockevent_delta2ns(-1, &ns9xxx_clockevent_device);
+ ns9xxx_clockevent_device.min_delta_ns =
+ clockevent_delta2ns(1, &ns9xxx_clockevent_device);
+
+ ns9xxx_clockevent_device.cpumask = cpumask_of_cpu(0);
+ clockevents_register_device(&ns9xxx_clockevent_device);
+
+ setup_irq(IRQ_TIMER0 + TIMER_CLOCKEVENT, &ns9xxx_clockevent_action);
}
struct sys_timer ns9xxx_timer = {
.init = ns9xxx_timer_init,
- .offset = ns9xxx_timer_gettimeoffset,
};
diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig
index f6ecdd3a2478..79f0b1f8497b 100644
--- a/arch/arm/mach-omap1/Kconfig
+++ b/arch/arm/mach-omap1/Kconfig
@@ -84,11 +84,39 @@ config MACH_OMAP_PALMTE
bool "Palm Tungsten E"
depends on ARCH_OMAP1 && ARCH_OMAP15XX
help
- Support for the Palm Tungsten E PDA. Currently only the LCD panel
- is supported. To boot the kernel, you'll need a PalmOS compatible
- bootloader; check out http://palmtelinux.sourceforge.net for more
- information.
- Say Y here if you have such a PDA, say NO otherwise.
+ Support for the Palm Tungsten E PDA. To boot the kernel, you'll
+ need a PalmOS compatible bootloader; check out
+ http://palmtelinux.sourceforge.net/ for more information.
+ Say Y here if you have this PDA model, say N otherwise.
+
+config MACH_OMAP_PALMZ71
+ bool "Palm Zire71"
+ depends on ARCH_OMAP1 && ARCH_OMAP15XX
+ help
+ Support for the Palm Zire71 PDA. To boot the kernel,
+ you'll need a PalmOS compatible bootloader; check out
+ http://hackndev.com/palm/z71 for more informations.
+ Say Y here if you have such a PDA, say N otherwise.
+
+config MACH_OMAP_PALMTT
+ bool "Palm Tungsten|T"
+ depends on ARCH_OMAP1 && ARCH_OMAP15XX
+ help
+ Support for the Palm Tungsten|T PDA. To boot the kernel, you'll
+ need a PalmOS compatible bootloader (Garux); check out
+ http://www.hackndev.com/palm/tt/ for more information.
+ Say Y here if you have this PDA model, say N otherwise.
+
+config MACH_SX1
+ bool "Siemens SX1"
+ depends on ARCH_OMAP1 && ARCH_OMAP15XX
+ help
+ Support for the Siemens SX1 phone. To boot the kernel,
+ you'll need a SX1 compatible bootloader; check out
+ http://forum.oslik.ru and
+ http://www.handhelds.org/moin/moin.cgi/SiemensSX1
+ for more information.
+ Say Y here if you have such a phone, say NO otherwise.
config MACH_NOKIA770
bool "Nokia 770"
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
index a8b9a00cea22..391b6f4827f6 100644
--- a/arch/arm/mach-omap1/Makefile
+++ b/arch/arm/mach-omap1/Makefile
@@ -22,8 +22,11 @@ obj-$(CONFIG_MACH_OMAP_OSK) += board-osk.o
obj-$(CONFIG_MACH_OMAP_H3) += board-h3.o
obj-$(CONFIG_MACH_VOICEBLUE) += board-voiceblue.o
obj-$(CONFIG_MACH_OMAP_PALMTE) += board-palmte.o
+obj-$(CONFIG_MACH_OMAP_PALMZ71) += board-palmz71.o
+obj-$(CONFIG_MACH_OMAP_PALMTT) += board-palmtt.o
obj-$(CONFIG_MACH_NOKIA770) += board-nokia770.o
obj-$(CONFIG_MACH_AMS_DELTA) += board-ams-delta.o
+obj-$(CONFIG_MACH_SX1) += board-sx1.o
ifeq ($(CONFIG_ARCH_OMAP15XX),y)
# Innovator-1510 FPGA
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
index 8437d065ada5..c73ca61e585e 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -14,6 +14,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/input.h>
#include <linux/platform_device.h>
#include <asm/hardware.h>
@@ -23,6 +24,7 @@
#include <asm/arch/board-ams-delta.h>
#include <asm/arch/gpio.h>
+#include <asm/arch/keypad.h>
#include <asm/arch/mux.h>
#include <asm/arch/usb.h>
#include <asm/arch/board.h>
@@ -31,6 +33,86 @@
static u8 ams_delta_latch1_reg;
static u16 ams_delta_latch2_reg;
+static int ams_delta_keymap[] = {
+ KEY(0, 0, KEY_F1), /* Advert */
+
+ KEY(3, 0, KEY_COFFEE), /* Games */
+ KEY(2, 0, KEY_QUESTION), /* Directory */
+ KEY(3, 2, KEY_CONNECT), /* Internet */
+ KEY(2, 1, KEY_SHOP), /* Services */
+ KEY(1, 1, KEY_PHONE), /* VoiceMail */
+
+ KEY(1, 0, KEY_DELETE), /* Delete */
+ KEY(2, 2, KEY_PLAY), /* Play */
+ KEY(0, 1, KEY_PAGEUP), /* Up */
+ KEY(3, 1, KEY_PAGEDOWN), /* Down */
+ KEY(0, 2, KEY_EMAIL), /* ReadEmail */
+ KEY(1, 2, KEY_STOP), /* Stop */
+
+ /* Numeric keypad portion */
+ KEY(7, 0, KEY_KP1),
+ KEY(6, 0, KEY_KP2),
+ KEY(5, 0, KEY_KP3),
+ KEY(7, 1, KEY_KP4),
+ KEY(6, 1, KEY_KP5),
+ KEY(5, 1, KEY_KP6),
+ KEY(7, 2, KEY_KP7),
+ KEY(6, 2, KEY_KP8),
+ KEY(5, 2, KEY_KP9),
+ KEY(6, 3, KEY_KP0),
+ KEY(7, 3, KEY_KPASTERISK),
+ KEY(5, 3, KEY_KPDOT), /* # key */
+ KEY(2, 7, KEY_NUMLOCK), /* Mute */
+ KEY(1, 7, KEY_KPMINUS), /* Recall */
+ KEY(1, 6, KEY_KPPLUS), /* Redial */
+ KEY(6, 7, KEY_KPSLASH), /* Handsfree */
+ KEY(0, 6, KEY_ENTER), /* Video */
+
+ KEY(4, 7, KEY_CAMERA), /* Photo */
+
+ KEY(4, 0, KEY_F2), /* Home */
+ KEY(4, 1, KEY_F3), /* Office */
+ KEY(4, 2, KEY_F4), /* Mobile */
+ KEY(7, 7, KEY_F5), /* SMS */
+ KEY(5, 7, KEY_F6), /* Email */
+
+ /* QWERTY portion of keypad */
+ KEY(4, 3, KEY_Q),
+ KEY(3, 3, KEY_W),
+ KEY(2, 3, KEY_E),
+ KEY(1, 3, KEY_R),
+ KEY(0, 3, KEY_T),
+ KEY(7, 4, KEY_Y),
+ KEY(6, 4, KEY_U),
+ KEY(5, 4, KEY_I),
+ KEY(4, 4, KEY_O),
+ KEY(3, 4, KEY_P),
+
+ KEY(2, 4, KEY_A),
+ KEY(1, 4, KEY_S),
+ KEY(0, 4, KEY_D),
+ KEY(7, 5, KEY_F),
+ KEY(6, 5, KEY_G),
+ KEY(5, 5, KEY_H),
+ KEY(4, 5, KEY_J),
+ KEY(3, 5, KEY_K),
+ KEY(2, 5, KEY_L),
+
+ KEY(1, 5, KEY_Z),
+ KEY(0, 5, KEY_X),
+ KEY(7, 6, KEY_C),
+ KEY(6, 6, KEY_V),
+ KEY(5, 6, KEY_B),
+ KEY(4, 6, KEY_N),
+ KEY(3, 6, KEY_M),
+ KEY(2, 6, KEY_SPACE),
+
+ KEY(0, 7, KEY_LEFTSHIFT), /* Vol up */
+ KEY(3, 7, KEY_LEFTCTRL), /* Vol down */
+
+ 0
+};
+
void ams_delta_latch1_write(u8 mask, u8 value)
{
ams_delta_latch1_reg &= ~mask;
@@ -76,6 +158,10 @@ static struct map_desc ams_delta_io_desc[] __initdata = {
}
};
+static struct omap_lcd_config ams_delta_lcd_config __initdata = {
+ .ctrl_name = "internal",
+};
+
static struct omap_uart_config ams_delta_uart_config __initdata = {
.enabled_uarts = 1,
};
@@ -87,16 +173,50 @@ static struct omap_usb_config ams_delta_usb_config __initdata = {
};
static struct omap_board_config_kernel ams_delta_config[] = {
+ { OMAP_TAG_LCD, &ams_delta_lcd_config },
{ OMAP_TAG_UART, &ams_delta_uart_config },
{ OMAP_TAG_USB, &ams_delta_usb_config },
};
+static struct resource ams_delta_kp_resources[] = {
+ [0] = {
+ .start = INT_KEYBOARD,
+ .end = INT_KEYBOARD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct omap_kp_platform_data ams_delta_kp_data = {
+ .rows = 8,
+ .cols = 8,
+ .keymap = ams_delta_keymap,
+ .keymapsize = ARRAY_SIZE(ams_delta_keymap),
+ .delay = 9,
+};
+
+static struct platform_device ams_delta_kp_device = {
+ .name = "omap-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &ams_delta_kp_data,
+ },
+ .num_resources = ARRAY_SIZE(ams_delta_kp_resources),
+ .resource = ams_delta_kp_resources,
+};
+
+static struct platform_device ams_delta_lcd_device = {
+ .name = "lcd_ams_delta",
+ .id = -1,
+};
+
static struct platform_device ams_delta_led_device = {
.name = "ams-delta-led",
.id = -1
};
static struct platform_device *ams_delta_devices[] __initdata = {
+ &ams_delta_kp_device,
+ &ams_delta_lcd_device,
&ams_delta_led_device,
};
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c
index 2f8f6ecf111f..130681201c19 100644
--- a/arch/arm/mach-omap1/board-h2.c
+++ b/arch/arm/mach-omap1/board-h2.c
@@ -140,6 +140,66 @@ static struct platform_device h2_nor_device = {
.resource = &h2_nor_resource,
};
+#if 0 /* REVISIT: Enable when nand_platform_data is applied */
+
+static struct mtd_partition h2_nand_partitions[] = {
+#if 0
+ /* REVISIT: enable these partitions if you make NAND BOOT
+ * work on your H2 (rev C or newer); published versions of
+ * x-load only support P2 and H3.
+ */
+ {
+ .name = "xloader",
+ .offset = 0,
+ .size = 64 * 1024,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "bootloader",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 256 * 1024,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "params",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 192 * 1024,
+ },
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 2 * SZ_1M,
+ },
+#endif
+ {
+ .name = "filesystem",
+ .size = MTDPART_SIZ_FULL,
+ .offset = MTDPART_OFS_APPEND,
+ },
+};
+
+/* dip switches control NAND chip access: 8 bit, 16 bit, or neither */
+static struct nand_platform_data h2_nand_data = {
+ .options = NAND_SAMSUNG_LP_OPTIONS,
+ .parts = h2_nand_partitions,
+ .nr_parts = ARRAY_SIZE(h2_nand_partitions),
+};
+
+static struct resource h2_nand_resource = {
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device h2_nand_device = {
+ .name = "omapnand",
+ .id = 0,
+ .dev = {
+ .platform_data = &h2_nand_data,
+ },
+ .num_resources = 1,
+ .resource = &h2_nand_resource,
+};
+#endif
+
static struct resource h2_smc91x_resources[] = {
[0] = {
.start = OMAP1610_ETHR_START, /* Physical */
@@ -219,11 +279,15 @@ static struct resource h2_irda_resources[] = {
.flags = IORESOURCE_IRQ,
},
};
+
+static u64 irda_dmamask = 0xffffffff;
+
static struct platform_device h2_irda_device = {
.name = "omapirda",
.id = 0,
.dev = {
.platform_data = &h2_irda_data,
+ .dma_mask = &irda_dmamask,
},
.num_resources = ARRAY_SIZE(h2_irda_resources),
.resource = h2_irda_resources,
@@ -271,6 +335,7 @@ static struct platform_device h2_mcbsp1_device = {
static struct platform_device *h2_devices[] __initdata = {
&h2_nor_device,
+ //&h2_nand_device,
&h2_smc91x_device,
&h2_irda_device,
&h2_kp_device,
@@ -278,6 +343,7 @@ static struct platform_device *h2_devices[] __initdata = {
&h2_mcbsp1_device,
};
+#ifdef CONFIG_I2C_BOARDINFO
static struct i2c_board_info __initdata h2_i2c_board_info[] = {
{
I2C_BOARD_INFO("tps65010", 0x48),
@@ -291,6 +357,7 @@ static struct i2c_board_info __initdata h2_i2c_board_info[] = {
* - ... etc
*/
};
+#endif
static void __init h2_init_smc91x(void)
{
@@ -348,6 +415,13 @@ static struct omap_board_config_kernel h2_config[] __initdata = {
{ OMAP_TAG_LCD, &h2_lcd_config },
};
+#define H2_NAND_RB_GPIO_PIN 62
+
+static int h2_nand_dev_ready(struct nand_platform_data *data)
+{
+ return omap_get_gpio_datain(H2_NAND_RB_GPIO_PIN);
+}
+
static void __init h2_init(void)
{
/* Here we assume the NOR boot config: NOR on CS3 (possibly swapped
@@ -362,6 +436,13 @@ static void __init h2_init(void)
h2_nor_resource.end = h2_nor_resource.start = omap_cs3_phys();
h2_nor_resource.end += SZ_32M - 1;
+#if 0 /* REVISIT: Enable when nand_platform_data is applied */
+ h2_nand_resource.end = h2_nand_resource.start = OMAP_CS2B_PHYS;
+ h2_nand_resource.end += SZ_4K - 1;
+ if (!(omap_request_gpio(H2_NAND_RB_GPIO_PIN)))
+ h2_nand_data.dev_ready = h2_nand_dev_ready;
+#endif
+
omap_cfg_reg(L3_1610_FLASH_CS2B_OE);
omap_cfg_reg(M8_1610_FLASH_CS2B_WE);
@@ -388,8 +469,10 @@ static void __init h2_init(void)
if (gpio_request(58, "tps65010") == 0)
gpio_direction_input(58);
+#ifdef CONFIG_I2C_BOARDINFO
i2c_register_board_info(1, h2_i2c_board_info,
ARRAY_SIZE(h2_i2c_board_info));
+#endif
}
static void __init h2_map_io(void)
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
index add2f703204f..4f84ae273a1f 100644
--- a/arch/arm/mach-omap1/board-h3.c
+++ b/arch/arm/mach-omap1/board-h3.c
@@ -47,6 +47,8 @@
#include <asm/arch/keypad.h>
#include <asm/arch/dma.h>
#include <asm/arch/common.h>
+#include <asm/arch/mcbsp.h>
+#include <asm/arch/omap-alsa.h>
extern int omap_gpio_init(void);
@@ -354,11 +356,14 @@ static struct resource h3_irda_resources[] = {
},
};
+static u64 irda_dmamask = 0xffffffff;
+
static struct platform_device h3_irda_device = {
.name = "omapirda",
.id = 0,
.dev = {
.platform_data = &h3_irda_data,
+ .dma_mask = &irda_dmamask,
},
.num_resources = ARRAY_SIZE(h3_irda_resources),
.resource = h3_irda_resources,
@@ -369,6 +374,41 @@ static struct platform_device h3_lcd_device = {
.id = -1,
};
+static struct omap_mcbsp_reg_cfg mcbsp_regs = {
+ .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
+ .spcr1 = RINTM(3) | RRST,
+ .rcr2 = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
+ RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(1),
+ .rcr1 = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16),
+ .xcr2 = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
+ XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(1) | XFIG,
+ .xcr1 = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16),
+ .srgr1 = FWID(15),
+ .srgr2 = GSYNC | CLKSP | FSGM | FPER(31),
+
+ .pcr0 = CLKRM | SCLKME | FSXP | FSRP | CLKXP | CLKRP,
+ //.pcr0 = CLKXP | CLKRP, /* mcbsp: slave */
+};
+
+static struct omap_alsa_codec_config alsa_config = {
+ .name = "H3 TSC2101",
+ .mcbsp_regs_alsa = &mcbsp_regs,
+ .codec_configure_dev = NULL, // tsc2101_configure,
+ .codec_set_samplerate = NULL, // tsc2101_set_samplerate,
+ .codec_clock_setup = NULL, // tsc2101_clock_setup,
+ .codec_clock_on = NULL, // tsc2101_clock_on,
+ .codec_clock_off = NULL, // tsc2101_clock_off,
+ .get_default_samplerate = NULL, // tsc2101_get_default_samplerate,
+};
+
+static struct platform_device h3_mcbsp1_device = {
+ .name = "omap_alsa_mcbsp",
+ .id = 1,
+ .dev = {
+ .platform_data = &alsa_config,
+ },
+};
+
static struct platform_device *devices[] __initdata = {
&nor_device,
&nand_device,
@@ -377,6 +417,7 @@ static struct platform_device *devices[] __initdata = {
&h3_irda_device,
&h3_kp_device,
&h3_lcd_device,
+ &h3_mcbsp1_device,
};
static struct omap_usb_config h3_usb_config __initdata = {
diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c
index 70014f751bc4..22db19a53647 100644
--- a/arch/arm/mach-omap1/board-nokia770.c
+++ b/arch/arm/mach-omap1/board-nokia770.c
@@ -33,6 +33,12 @@
#include <asm/arch/dsp_common.h>
#include <asm/arch/aic23.h>
#include <asm/arch/gpio.h>
+#include <asm/arch/omapfb.h>
+#include <asm/arch/lcd_mipid.h>
+
+#include "../plat-omap/dsp/dsp_common.h"
+
+#define ADS7846_PENDOWN_GPIO 15
static void __init omap_nokia770_init_irq(void)
{
@@ -91,9 +97,44 @@ static struct platform_device nokia770_kp_device = {
};
static struct platform_device *nokia770_devices[] __initdata = {
- &nokia770_kp_device,
+ &nokia770_kp_device,
+};
+
+static void mipid_shutdown(struct mipid_platform_data *pdata)
+{
+ if (pdata->nreset_gpio != -1) {
+ printk(KERN_INFO "shutdown LCD\n");
+ omap_set_gpio_dataout(pdata->nreset_gpio, 0);
+ msleep(120);
+ }
+}
+
+static struct mipid_platform_data nokia770_mipid_platform_data = {
+ .shutdown = mipid_shutdown,
};
+static void mipid_dev_init(void)
+{
+ const struct omap_lcd_config *conf;
+
+ conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config);
+ if (conf != NULL) {
+ nokia770_mipid_platform_data.nreset_gpio = conf->nreset_gpio;
+ nokia770_mipid_platform_data.data_lines = conf->data_lines;
+ }
+}
+
+static void ads7846_dev_init(void)
+{
+ if (omap_request_gpio(ADS7846_PENDOWN_GPIO) < 0)
+ printk(KERN_ERR "can't get ads7846 pen down GPIO\n");
+}
+
+static int ads7846_get_pendown_state(void)
+{
+ return !omap_get_gpio_datain(ADS7846_PENDOWN_GPIO);
+}
+
static struct ads7846_platform_data nokia770_ads7846_platform_data __initdata = {
.x_max = 0x0fff,
.y_max = 0x0fff,
@@ -101,14 +142,17 @@ static struct ads7846_platform_data nokia770_ads7846_platform_data __initdata =
.pressure_max = 255,
.debounce_max = 10,
.debounce_tol = 3,
+ .debounce_rep = 1,
+ .get_pendown_state = ads7846_get_pendown_state,
};
static struct spi_board_info nokia770_spi_board_info[] __initdata = {
[0] = {
- .modalias = "lcd_mipid",
+ .modalias = "lcd_mipid",
.bus_num = 2,
.chip_select = 3,
.max_speed_hz = 12000000,
+ .platform_data = &nokia770_mipid_platform_data,
},
[1] = {
.modalias = "ads7846",
@@ -153,6 +197,7 @@ static struct omap_board_config_kernel nokia770_config[] = {
{ OMAP_TAG_MMC, &nokia770_mmc_config },
};
+#if defined(CONFIG_OMAP_DSP)
/*
* audio power control
*/
@@ -183,7 +228,7 @@ static void nokia770_audio_pwr_up(void)
clk_enable(dspxor_ck);
/* Turn on codec */
- tlv320aic23_power_up();
+ aic23_power_up();
if (omap_get_gpio_datain(HEADPHONE_GPIO))
/* HP not connected, turn on amplifier */
@@ -197,7 +242,7 @@ static void codec_delayed_power_down(struct work_struct *work)
{
down(&audio_pwr_sem);
if (audio_pwr_state == -1)
- tlv320aic23_power_down();
+ aic23_power_down();
clk_disable(dspxor_ck);
up(&audio_pwr_sem);
}
@@ -213,7 +258,8 @@ static void nokia770_audio_pwr_down(void)
schedule_delayed_work(&codec_power_down_work, HZ / 20); /* 50ms */
}
-void nokia770_audio_pwr_up_request(int stage)
+static int
+nokia770_audio_pwr_up_request(struct dsp_kfunc_device *kdev, int stage)
{
down(&audio_pwr_sem);
if (audio_pwr_state == -1)
@@ -221,9 +267,11 @@ void nokia770_audio_pwr_up_request(int stage)
/* force audio_pwr_state = 0, even if it was 1. */
audio_pwr_state = 0;
up(&audio_pwr_sem);
+ return 0;
}
-void nokia770_audio_pwr_down_request(int stage)
+static int
+nokia770_audio_pwr_down_request(struct dsp_kfunc_device *kdev, int stage)
{
down(&audio_pwr_sem);
switch (stage) {
@@ -239,8 +287,39 @@ void nokia770_audio_pwr_down_request(int stage)
break;
}
up(&audio_pwr_sem);
+ return 0;
}
+static struct dsp_kfunc_device nokia770_audio_device = {
+ .name = "audio",
+ .type = DSP_KFUNC_DEV_TYPE_AUDIO,
+ .enable = nokia770_audio_pwr_up_request,
+ .disable = nokia770_audio_pwr_down_request,
+};
+
+static __init int omap_dsp_init(void)
+{
+ int ret;
+
+ dspxor_ck = clk_get(0, "dspxor_ck");
+ if (IS_ERR(dspxor_ck)) {
+ printk(KERN_ERR "couldn't acquire dspxor_ck\n");
+ return PTR_ERR(dspxor_ck);
+ }
+
+ ret = dsp_kfunc_device_register(&nokia770_audio_device);
+ if (ret) {
+ printk(KERN_ERR
+ "KFUNC device registration faild: %s\n",
+ nokia770_audio_device.name);
+ goto out;
+ }
+ return 0;
+ out:
+ return ret;
+}
+#endif /* CONFIG_OMAP_DSP */
+
static void __init omap_nokia770_init(void)
{
nokia770_config[0].data = &nokia770_usb_config;
@@ -250,10 +329,11 @@ static void __init omap_nokia770_init(void)
ARRAY_SIZE(nokia770_spi_board_info));
omap_board_config = nokia770_config;
omap_board_config_size = ARRAY_SIZE(nokia770_config);
+ omap_gpio_init();
omap_serial_init();
- omap_dsp_audio_pwr_up_request = nokia770_audio_pwr_up_request;
- omap_dsp_audio_pwr_down_request = nokia770_audio_pwr_down_request;
- dspxor_ck = clk_get(0, "dspxor_ck");
+ omap_dsp_init();
+ ads7846_dev_init();
+ mipid_dev_init();
}
static void __init omap_nokia770_map_io(void)
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index a61bf455ee02..5db182da322b 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -29,6 +29,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
+#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
@@ -308,6 +309,18 @@ static struct platform_device osk5912_kp_device = {
.resource = osk5912_kp_resources,
};
+static struct omap_backlight_config mistral_bl_data = {
+ .default_intensity = 0xa0,
+};
+
+static struct platform_device mistral_bl_device = {
+ .name = "omap-bl",
+ .id = -1,
+ .dev = {
+ .platform_data = &mistral_bl_data,
+ },
+};
+
static struct platform_device osk5912_lcd_device = {
.name = "lcd_osk",
.id = -1,
@@ -315,6 +328,7 @@ static struct platform_device osk5912_lcd_device = {
static struct platform_device *mistral_devices[] __initdata = {
&osk5912_kp_device,
+ &mistral_bl_device,
&osk5912_lcd_device,
};
@@ -358,6 +372,38 @@ static void __init osk_mistral_init(void)
* can't talk to the ads or even the i2c eeprom.
*/
+ /* parallel camera interface */
+ omap_cfg_reg(J15_1610_CAM_LCLK);
+ omap_cfg_reg(J18_1610_CAM_D7);
+ omap_cfg_reg(J19_1610_CAM_D6);
+ omap_cfg_reg(J14_1610_CAM_D5);
+ omap_cfg_reg(K18_1610_CAM_D4);
+ omap_cfg_reg(K19_1610_CAM_D3);
+ omap_cfg_reg(K15_1610_CAM_D2);
+ omap_cfg_reg(K14_1610_CAM_D1);
+ omap_cfg_reg(L19_1610_CAM_D0);
+ omap_cfg_reg(L18_1610_CAM_VS);
+ omap_cfg_reg(L15_1610_CAM_HS);
+ omap_cfg_reg(M19_1610_CAM_RSTZ);
+ omap_cfg_reg(Y15_1610_CAM_OUTCLK);
+
+ /* serial camera interface */
+ omap_cfg_reg(H19_1610_CAM_EXCLK);
+ omap_cfg_reg(W13_1610_CCP_CLKM);
+ omap_cfg_reg(Y12_1610_CCP_CLKP);
+ /* CCP_DATAM CONFLICTS WITH UART1.TX (and serial console) */
+ // omap_cfg_reg(Y14_1610_CCP_DATAM);
+ omap_cfg_reg(W14_1610_CCP_DATAP);
+
+ /* CAM_PWDN */
+ if (omap_request_gpio(11) == 0) {
+ omap_cfg_reg(N20_1610_GPIO11);
+ omap_set_gpio_direction(11, 0 /* out */);
+ omap_set_gpio_dataout(11, 0 /* off */);
+ } else
+ pr_debug("OSK+Mistral: CAM_PWDN is awol\n");
+
+
// omap_cfg_reg(P19_1610_GPIO6); // BUSY
omap_cfg_reg(P20_1610_GPIO4); // PENIRQ
set_irq_type(OMAP_GPIO_IRQ(4), IRQT_FALLING);
@@ -388,6 +434,15 @@ static void __init osk_mistral_init(void)
} else
printk(KERN_ERR "OSK+Mistral: wakeup button is awol\n");
+ /* LCD: backlight, and power; power controls other devices on the
+ * board, like the touchscreen, EEPROM, and wakeup (!) switch.
+ */
+ omap_cfg_reg(PWL);
+ if (omap_request_gpio(2) == 0) {
+ omap_set_gpio_direction(2, 0 /* out */);
+ omap_set_gpio_dataout(2, 1 /* on */);
+ }
+
platform_add_devices(mistral_devices, ARRAY_SIZE(mistral_devices));
}
#else
diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c
index 015824185629..2f9d00a00135 100644
--- a/arch/arm/mach-omap1/board-palmte.c
+++ b/arch/arm/mach-omap1/board-palmte.c
@@ -17,49 +17,189 @@
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/input.h>
#include <linux/platform_device.h>
-#include <linux/notifier.h>
-#include <linux/clk.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/tsc2102.h>
+#include <linux/interrupt.h>
+#include <asm/apm.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
+#include <asm/mach/flash.h>
#include <asm/arch/gpio.h>
#include <asm/arch/mux.h>
#include <asm/arch/usb.h>
+#include <asm/arch/tc.h>
+#include <asm/arch/dma.h>
#include <asm/arch/board.h>
+#include <asm/arch/irda.h>
+#include <asm/arch/keypad.h>
#include <asm/arch/common.h>
+#include <asm/arch/mcbsp.h>
+#include <asm/arch/omap-alsa.h>
-static void __init omap_generic_init_irq(void)
+static void __init omap_palmte_init_irq(void)
{
omap1_init_common_hw();
omap_init_irq();
+ omap_gpio_init();
}
+static int palmte_keymap[] = {
+ KEY(0, 0, KEY_F1),
+ KEY(0, 1, KEY_F2),
+ KEY(0, 2, KEY_F3),
+ KEY(0, 3, KEY_F4),
+ KEY(0, 4, KEY_POWER),
+ KEY(1, 0, KEY_LEFT),
+ KEY(1, 1, KEY_DOWN),
+ KEY(1, 2, KEY_UP),
+ KEY(1, 3, KEY_RIGHT),
+ KEY(1, 4, KEY_CENTER),
+ 0,
+};
+
+static struct omap_kp_platform_data palmte_kp_data = {
+ .rows = 8,
+ .cols = 8,
+ .keymap = palmte_keymap,
+ .rep = 1,
+ .delay = 12,
+};
+
+static struct resource palmte_kp_resources[] = {
+ [0] = {
+ .start = INT_KEYBOARD,
+ .end = INT_KEYBOARD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device palmte_kp_device = {
+ .name = "omap-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &palmte_kp_data,
+ },
+ .num_resources = ARRAY_SIZE(palmte_kp_resources),
+ .resource = palmte_kp_resources,
+};
+
+static struct mtd_partition palmte_rom_partitions[] = {
+ /* PalmOS "Small ROM", contains the bootloader and the debugger */
+ {
+ .name = "smallrom",
+ .offset = 0,
+ .size = 0xa000,
+ .mask_flags = MTD_WRITEABLE,
+ },
+ /* PalmOS "Big ROM", a filesystem with all the OS code and data */
+ {
+ .name = "bigrom",
+ .offset = SZ_128K,
+ /*
+ * 0x5f0000 bytes big in the multi-language ("EFIGS") version,
+ * 0x7b0000 bytes in the English-only ("enUS") version.
+ */
+ .size = 0x7b0000,
+ .mask_flags = MTD_WRITEABLE,
+ },
+};
+
+static struct flash_platform_data palmte_rom_data = {
+ .map_name = "map_rom",
+ .width = 2,
+ .parts = palmte_rom_partitions,
+ .nr_parts = ARRAY_SIZE(palmte_rom_partitions),
+};
+
+static struct resource palmte_rom_resource = {
+ .start = OMAP_CS0_PHYS,
+ .end = OMAP_CS0_PHYS + SZ_8M - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device palmte_rom_device = {
+ .name = "omapflash",
+ .id = -1,
+ .dev = {
+ .platform_data = &palmte_rom_data,
+ },
+ .num_resources = 1,
+ .resource = &palmte_rom_resource,
+};
+
static struct platform_device palmte_lcd_device = {
.name = "lcd_palmte",
.id = -1,
};
+static struct omap_backlight_config palmte_backlight_config = {
+ .default_intensity = 0xa0,
+};
+
+static struct platform_device palmte_backlight_device = {
+ .name = "omap-bl",
+ .id = -1,
+ .dev = {
+ .platform_data = &palmte_backlight_config,
+ },
+};
+
+static struct omap_irda_config palmte_irda_config = {
+ .transceiver_cap = IR_SIRMODE,
+ .rx_channel = OMAP_DMA_UART3_RX,
+ .tx_channel = OMAP_DMA_UART3_TX,
+ .dest_start = UART3_THR,
+ .src_start = UART3_RHR,
+ .tx_trigger = 0,
+ .rx_trigger = 0,
+};
+
+static struct resource palmte_irda_resources[] = {
+ [0] = {
+ .start = INT_UART3,
+ .end = INT_UART3,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device palmte_irda_device = {
+ .name = "omapirda",
+ .id = -1,
+ .dev = {
+ .platform_data = &palmte_irda_config,
+ },
+ .num_resources = ARRAY_SIZE(palmte_irda_resources),
+ .resource = palmte_irda_resources,
+};
+
static struct platform_device *devices[] __initdata = {
+ &palmte_rom_device,
+ &palmte_kp_device,
&palmte_lcd_device,
+ &palmte_backlight_device,
+ &palmte_irda_device,
};
static struct omap_usb_config palmte_usb_config __initdata = {
- .register_dev = 1,
+ .register_dev = 1, /* Mini-B only receptacle */
.hmc_mode = 0,
- .pins[0] = 3,
+ .pins[0] = 2,
};
static struct omap_mmc_config palmte_mmc_config __initdata = {
- .mmc [0] = {
+ .mmc[0] = {
.enabled = 1,
- .wire4 = 1,
- .wp_pin = OMAP_MPUIO(3),
- .power_pin = -1,
- .switch_pin = -1,
+ .wp_pin = PALMTE_MMC_WP_GPIO,
+ .power_pin = PALMTE_MMC_POWER_GPIO,
+ .switch_pin = PALMTE_MMC_SWITCH_GPIO,
},
};
@@ -67,21 +207,222 @@ static struct omap_lcd_config palmte_lcd_config __initdata = {
.ctrl_name = "internal",
};
+static struct omap_uart_config palmte_uart_config __initdata = {
+ .enabled_uarts = (1 << 0) | (1 << 1) | (0 << 2),
+};
+
+static struct omap_mcbsp_reg_cfg palmte_mcbsp1_regs = {
+ .spcr2 = FRST | GRST | XRST | XINTM(3),
+ .xcr2 = XDATDLY(1) | XFIG,
+ .xcr1 = XWDLEN1(OMAP_MCBSP_WORD_32),
+ .pcr0 = SCLKME | FSXP | CLKXP,
+};
+
+static struct omap_alsa_codec_config palmte_alsa_config = {
+ .name = "TSC2102 audio",
+ .mcbsp_regs_alsa = &palmte_mcbsp1_regs,
+ .codec_configure_dev = NULL, /* tsc2102_configure, */
+ .codec_set_samplerate = NULL, /* tsc2102_set_samplerate, */
+ .codec_clock_setup = NULL, /* tsc2102_clock_setup, */
+ .codec_clock_on = NULL, /* tsc2102_clock_on, */
+ .codec_clock_off = NULL, /* tsc2102_clock_off, */
+ .get_default_samplerate = NULL, /* tsc2102_get_default_samplerate, */
+};
+
+#ifdef CONFIG_APM
+/*
+ * Values measured in 10 minute intervals averaged over 10 samples.
+ * May differ slightly from device to device but should be accurate
+ * enough to give basic idea of battery life left and trigger
+ * potential alerts.
+ */
+static const int palmte_battery_sample[] = {
+ 2194, 2157, 2138, 2120,
+ 2104, 2089, 2075, 2061,
+ 2048, 2038, 2026, 2016,
+ 2008, 1998, 1989, 1980,
+ 1970, 1958, 1945, 1928,
+ 1910, 1888, 1860, 1827,
+ 1791, 1751, 1709, 1656,
+};
+
+#define INTERVAL 10
+#define BATTERY_HIGH_TRESHOLD 66
+#define BATTERY_LOW_TRESHOLD 33
+
+static void palmte_get_power_status(struct apm_power_info *info, int *battery)
+{
+ int charging, batt, hi, lo, mid;
+
+ charging = !omap_get_gpio_datain(PALMTE_DC_GPIO);
+ batt = battery[0];
+ if (charging)
+ batt -= 60;
+
+ hi = ARRAY_SIZE(palmte_battery_sample);
+ lo = 0;
+
+ info->battery_flag = 0;
+ info->units = APM_UNITS_MINS;
+
+ if (batt > palmte_battery_sample[lo]) {
+ info->battery_life = 100;
+ info->time = INTERVAL * ARRAY_SIZE(palmte_battery_sample);
+ } else if (batt <= palmte_battery_sample[hi - 1]) {
+ info->battery_life = 0;
+ info->time = 0;
+ } else {
+ while (hi > lo + 1) {
+ mid = (hi + lo) >> 2;
+ if (batt <= palmte_battery_sample[mid])
+ lo = mid;
+ else
+ hi = mid;
+ }
+
+ mid = palmte_battery_sample[lo] - palmte_battery_sample[hi];
+ hi = palmte_battery_sample[lo] - batt;
+ info->battery_life = 100 - (100 * lo + 100 * hi / mid) /
+ ARRAY_SIZE(palmte_battery_sample);
+ info->time = INTERVAL * (ARRAY_SIZE(palmte_battery_sample) -
+ lo) - INTERVAL * hi / mid;
+ }
+
+ if (charging) {
+ info->ac_line_status = APM_AC_ONLINE;
+ info->battery_status = APM_BATTERY_STATUS_CHARGING;
+ info->battery_flag |= APM_BATTERY_FLAG_CHARGING;
+ } else {
+ info->ac_line_status = APM_AC_OFFLINE;
+ if (info->battery_life > BATTERY_HIGH_TRESHOLD)
+ info->battery_status = APM_BATTERY_STATUS_HIGH;
+ else if (info->battery_life > BATTERY_LOW_TRESHOLD)
+ info->battery_status = APM_BATTERY_STATUS_LOW;
+ else
+ info->battery_status = APM_BATTERY_STATUS_CRITICAL;
+ }
+
+ if (info->battery_life > BATTERY_HIGH_TRESHOLD)
+ info->battery_flag |= APM_BATTERY_FLAG_HIGH;
+ else if (info->battery_life > BATTERY_LOW_TRESHOLD)
+ info->battery_flag |= APM_BATTERY_FLAG_LOW;
+ else
+ info->battery_flag |= APM_BATTERY_FLAG_CRITICAL;
+}
+#else
+#define palmte_get_power_status NULL
+#endif
+
+static struct tsc2102_config palmte_tsc2102_config = {
+ .use_internal = 0,
+ .monitor = TSC_BAT1 | TSC_AUX | TSC_TEMP,
+ .temp_at25c = { 2200, 2615 },
+ .apm_report = palmte_get_power_status,
+ .alsa_config = &palmte_alsa_config,
+};
+
static struct omap_board_config_kernel palmte_config[] = {
- { OMAP_TAG_USB, &palmte_usb_config },
- { OMAP_TAG_MMC, &palmte_mmc_config },
- { OMAP_TAG_LCD, &palmte_lcd_config },
+ { OMAP_TAG_USB, &palmte_usb_config },
+ { OMAP_TAG_MMC, &palmte_mmc_config },
+ { OMAP_TAG_LCD, &palmte_lcd_config },
+ { OMAP_TAG_UART, &palmte_uart_config },
};
-static void __init omap_generic_init(void)
+static struct spi_board_info palmte_spi_info[] __initdata = {
+ {
+ .modalias = "tsc2102",
+ .bus_num = 2, /* uWire (officially) */
+ .chip_select = 0, /* As opposed to 3 */
+ .irq = OMAP_GPIO_IRQ(PALMTE_PINTDAV_GPIO),
+ .platform_data = &palmte_tsc2102_config,
+ .max_speed_hz = 8000000,
+ },
+};
+
+/* Periodically check for changes on important input pins */
+struct timer_list palmte_pin_timer;
+int prev_power, prev_headphones;
+
+static void palmte_pin_handler(unsigned long data) {
+ int power, headphones;
+
+ power = !omap_get_gpio_datain(PALMTE_DC_GPIO);
+ headphones = omap_get_gpio_datain(PALMTE_HEADPHONES_GPIO);
+
+ if (power && !prev_power)
+ printk(KERN_INFO "PM: cable connected\n");
+ else if (!power && prev_power)
+ printk(KERN_INFO "PM: cable disconnected\n");
+
+ if (headphones && !prev_headphones) {
+ /* Headphones connected, disable speaker */
+ omap_set_gpio_dataout(PALMTE_SPEAKER_GPIO, 0);
+ printk(KERN_INFO "PM: speaker off\n");
+ } else if (!headphones && prev_headphones) {
+ /* Headphones unplugged, re-enable speaker */
+ omap_set_gpio_dataout(PALMTE_SPEAKER_GPIO, 1);
+ printk(KERN_INFO "PM: speaker on\n");
+ }
+
+ prev_power = power;
+ prev_headphones = headphones;
+ mod_timer(&palmte_pin_timer, jiffies + msecs_to_jiffies(500));
+}
+
+static void __init palmte_gpio_setup(void)
+{
+ /* Set TSC2102 PINTDAV pin as input */
+ if (omap_request_gpio(PALMTE_PINTDAV_GPIO)) {
+ printk(KERN_ERR "Could not reserve PINTDAV GPIO!\n");
+ return;
+ }
+ omap_set_gpio_direction(PALMTE_PINTDAV_GPIO, 1);
+
+ /* Monitor cable-connected signals */
+ if (omap_request_gpio(PALMTE_DC_GPIO) ||
+ omap_request_gpio(PALMTE_USB_OR_DC_GPIO) ||
+ omap_request_gpio(PALMTE_USBDETECT_GPIO)) {
+ printk(KERN_ERR "Could not reserve cable signal GPIO!\n");
+ return;
+ }
+ omap_set_gpio_direction(PALMTE_DC_GPIO, 1);
+ omap_set_gpio_direction(PALMTE_USB_OR_DC_GPIO, 1);
+ omap_set_gpio_direction(PALMTE_USBDETECT_GPIO, 1);
+
+ /* Set speaker-enable pin as output */
+ if (omap_request_gpio(PALMTE_SPEAKER_GPIO)) {
+ printk(KERN_ERR "Could not reserve speaker GPIO!\n");
+ return;
+ }
+ omap_set_gpio_direction(PALMTE_SPEAKER_GPIO, 0);
+
+ /* Monitor the headphones-connected signal */
+ if (omap_request_gpio(PALMTE_HEADPHONES_GPIO)) {
+ printk(KERN_ERR "Could not reserve headphones signal GPIO!\n");
+ return;
+ }
+ omap_set_gpio_direction(PALMTE_HEADPHONES_GPIO, 1);
+
+ prev_power = omap_get_gpio_datain(PALMTE_DC_GPIO);
+ prev_headphones = !omap_get_gpio_datain(PALMTE_HEADPHONES_GPIO);
+ setup_timer(&palmte_pin_timer, palmte_pin_handler, 0);
+ palmte_pin_handler(0);
+}
+
+static void __init omap_palmte_init(void)
{
omap_board_config = palmte_config;
omap_board_config_size = ARRAY_SIZE(palmte_config);
platform_add_devices(devices, ARRAY_SIZE(devices));
+
+ spi_register_board_info(palmte_spi_info, ARRAY_SIZE(palmte_spi_info));
+
+ omap_serial_init();
+ palmte_gpio_setup();
}
-static void __init omap_generic_map_io(void)
+static void __init omap_palmte_map_io(void)
{
omap1_map_common_io();
}
@@ -90,8 +431,8 @@ MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E")
.phys_io = 0xfff00000,
.io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
.boot_params = 0x10000100,
- .map_io = omap_generic_map_io,
- .init_irq = omap_generic_init_irq,
- .init_machine = omap_generic_init,
+ .map_io = omap_palmte_map_io,
+ .init_irq = omap_palmte_init_irq,
+ .init_machine = omap_palmte_init,
.timer = &omap_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap1/board-palmtt.c b/arch/arm/mach-omap1/board-palmtt.c
new file mode 100644
index 000000000000..e47010fec275
--- /dev/null
+++ b/arch/arm/mach-omap1/board-palmtt.c
@@ -0,0 +1,357 @@
+/*
+ * linux/arch/arm/mach-omap1/board-palmtt.c
+ *
+ * Modified from board-palmtt2.c
+ *
+ * Modified and amended for Palm Tungsten|T
+ * by Marek Vasut <marek.vasut@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/notifier.h>
+#include <linux/clk.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/leds.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/flash.h>
+
+#include <asm/arch/led.h>
+#include <asm/arch/mcbsp.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/usb.h>
+#include <asm/arch/dma.h>
+#include <asm/arch/tc.h>
+#include <asm/arch/board.h>
+#include <asm/arch/irda.h>
+#include <asm/arch/keypad.h>
+#include <asm/arch/common.h>
+#include <asm/arch/omap-alsa.h>
+
+#include <linux/input.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
+
+static int palmtt_keymap[] = {
+ KEY(0, 0, KEY_ESC),
+ KEY(0, 1, KEY_SPACE),
+ KEY(0, 2, KEY_LEFTCTRL),
+ KEY(0, 3, KEY_TAB),
+ KEY(0, 4, KEY_ENTER),
+ KEY(1, 0, KEY_LEFT),
+ KEY(1, 1, KEY_DOWN),
+ KEY(1, 2, KEY_UP),
+ KEY(1, 3, KEY_RIGHT),
+ KEY(2, 0, KEY_SLEEP),
+ KEY(2, 4, KEY_Y),
+ 0
+};
+
+static struct mtd_partition palmtt_partitions[] = {
+ {
+ .name = "write8k",
+ .offset = 0,
+ .size = SZ_8K,
+ .mask_flags = 0,
+ },
+ {
+ .name = "PalmOS-BootLoader(ro)",
+ .offset = SZ_8K,
+ .size = 7 * SZ_8K,
+ .mask_flags = MTD_WRITEABLE,
+ },
+ {
+ .name = "u-boot",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 8 * SZ_8K,
+ .mask_flags = 0,
+ },
+ {
+ .name = "PalmOS-FS(ro)",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 7 * SZ_1M + 4 * SZ_64K - 16 * SZ_8K,
+ .mask_flags = MTD_WRITEABLE,
+ },
+ {
+ .name = "u-boot(rez)",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_128K,
+ .mask_flags = 0
+ },
+ {
+ .name = "empty",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0
+ }
+};
+
+static struct flash_platform_data palmtt_flash_data = {
+ .map_name = "cfi_probe",
+ .width = 2,
+ .parts = palmtt_partitions,
+ .nr_parts = ARRAY_SIZE(palmtt_partitions),
+};
+
+static struct resource palmtt_flash_resource = {
+ .start = OMAP_CS0_PHYS,
+ .end = OMAP_CS0_PHYS + SZ_8M - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device palmtt_flash_device = {
+ .name = "omapflash",
+ .id = 0,
+ .dev = {
+ .platform_data = &palmtt_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &palmtt_flash_resource,
+};
+
+#define DEFAULT_BITPERSAMPLE 16
+
+static struct omap_mcbsp_reg_cfg mcbsp_regs = {
+ .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
+ .spcr1 = RINTM(3) | RRST,
+ .rcr2 = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
+ RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(0),
+ .rcr1 = RFRLEN1(OMAP_MCBSP_WORD_8) |
+ RWDLEN1(OMAP_MCBSP_WORD_16),
+ .xcr2 = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
+ XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(0) | XFIG,
+ .xcr1 = XFRLEN1(OMAP_MCBSP_WORD_8) |
+ XWDLEN1(OMAP_MCBSP_WORD_16),
+ .srgr1 = FWID(DEFAULT_BITPERSAMPLE - 1),
+ .srgr2 = GSYNC | CLKSP | FSGM |
+ FPER(DEFAULT_BITPERSAMPLE * 2 - 1),
+ .pcr0 = CLKXP | CLKRP, /* mcbsp: slave */
+};
+
+static struct omap_alsa_codec_config alsa_config = {
+ .name = "PalmTT AIC23",
+ .mcbsp_regs_alsa = &mcbsp_regs,
+ .codec_configure_dev = NULL, // aic23_configure,
+ .codec_set_samplerate = NULL, // aic23_set_samplerate,
+ .codec_clock_setup = NULL, // aic23_clock_setup,
+ .codec_clock_on = NULL, // aic23_clock_on,
+ .codec_clock_off = NULL, // aic23_clock_off,
+ .get_default_samplerate = NULL, // aic23_get_default_samplerate,
+};
+
+static struct platform_device palmtt_mcbsp1_device = {
+ .name = "omap_alsa_mcbsp",
+ .id = 1,
+ .dev = {
+ .platform_data = &alsa_config,
+ },
+};
+
+static struct resource palmtt_kp_resources[] = {
+ [0] = {
+ .start = INT_KEYBOARD,
+ .end = INT_KEYBOARD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct omap_kp_platform_data palmtt_kp_data = {
+ .rows = 6,
+ .cols = 3,
+ .keymap = palmtt_keymap,
+};
+
+static struct platform_device palmtt_kp_device = {
+ .name = "omap-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &palmtt_kp_data,
+ },
+ .num_resources = ARRAY_SIZE(palmtt_kp_resources),
+ .resource = palmtt_kp_resources,
+};
+
+static struct platform_device palmtt_lcd_device = {
+ .name = "lcd_palmtt",
+ .id = -1,
+};
+static struct omap_irda_config palmtt_irda_config = {
+ .transceiver_cap = IR_SIRMODE,
+ .rx_channel = OMAP_DMA_UART3_RX,
+ .tx_channel = OMAP_DMA_UART3_TX,
+ .dest_start = UART3_THR,
+ .src_start = UART3_RHR,
+ .tx_trigger = 0,
+ .rx_trigger = 0,
+};
+
+static struct resource palmtt_irda_resources[] = {
+ [0] = {
+ .start = INT_UART3,
+ .end = INT_UART3,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device palmtt_irda_device = {
+ .name = "omapirda",
+ .id = -1,
+ .dev = {
+ .platform_data = &palmtt_irda_config,
+ },
+ .num_resources = ARRAY_SIZE(palmtt_irda_resources),
+ .resource = palmtt_irda_resources,
+};
+
+static struct platform_device palmtt_spi_device = {
+ .name = "spi_palmtt",
+ .id = -1,
+};
+
+static struct omap_backlight_config palmtt_backlight_config = {
+ .default_intensity = 0xa0,
+};
+
+static struct platform_device palmtt_backlight_device = {
+ .name = "omap-bl",
+ .id = -1,
+ .dev = {
+ .platform_data= &palmtt_backlight_config,
+ },
+};
+
+static struct omap_led_config palmtt_led_config[] = {
+ {
+ .cdev = {
+ .name = "palmtt:led0",
+ },
+ .gpio = PALMTT_LED_GPIO,
+ },
+};
+
+static struct omap_led_platform_data palmtt_led_data = {
+ .nr_leds = ARRAY_SIZE(palmtt_led_config),
+ .leds = palmtt_led_config,
+};
+
+static struct platform_device palmtt_led_device = {
+ .name = "omap-led",
+ .id = -1,
+ .dev = {
+ .platform_data = &palmtt_led_data,
+ },
+};
+
+static struct platform_device *palmtt_devices[] __initdata = {
+ &palmtt_flash_device,
+ &palmtt_mcbsp1_device,
+ &palmtt_kp_device,
+ &palmtt_lcd_device,
+ &palmtt_irda_device,
+ &palmtt_spi_device,
+ &palmtt_backlight_device,
+ &palmtt_led_device,
+};
+
+static int palmtt_get_pendown_state(void)
+{
+ return !omap_get_gpio_datain(6);
+}
+
+static const struct ads7846_platform_data palmtt_ts_info = {
+ .model = 7846,
+ .vref_delay_usecs = 100, /* internal, no capacitor */
+ .x_plate_ohms = 419,
+ .y_plate_ohms = 486,
+ .get_pendown_state = palmtt_get_pendown_state,
+};
+
+static struct spi_board_info __initdata palmtt_boardinfo[] = {
+ {
+ /* MicroWire (bus 2) CS0 has an ads7846e */
+ .modalias = "ads7846",
+ .platform_data = &palmtt_ts_info,
+ .irq = OMAP_GPIO_IRQ(6),
+ .max_speed_hz = 120000 /* max sample rate at 3V */
+ * 26 /* command + data + overhead */,
+ .bus_num = 2,
+ .chip_select = 0,
+ }
+};
+
+static void __init omap_palmtt_init_irq(void)
+{
+ omap1_init_common_hw();
+ omap_init_irq();
+}
+
+static struct omap_usb_config palmtt_usb_config __initdata = {
+ .register_dev = 1,
+ .hmc_mode = 0,
+ .pins[0] = 2,
+};
+
+static struct omap_lcd_config palmtt_lcd_config __initdata = {
+ .ctrl_name = "internal",
+};
+
+static struct omap_uart_config palmtt_uart_config __initdata = {
+ .enabled_uarts = (1 << 0) | (1 << 1) | (0 << 2),
+};
+
+static struct omap_board_config_kernel palmtt_config[] = {
+ { OMAP_TAG_USB, &palmtt_usb_config },
+ { OMAP_TAG_LCD, &palmtt_lcd_config },
+ { OMAP_TAG_UART, &palmtt_uart_config },
+};
+
+static void __init omap_mpu_wdt_mode(int mode) {
+ if (mode)
+ omap_writew(0x8000, OMAP_WDT_TIMER_MODE);
+ else {
+ omap_writew(0x00f5, OMAP_WDT_TIMER_MODE);
+ omap_writew(0x00a0, OMAP_WDT_TIMER_MODE);
+ }
+}
+
+static void __init omap_palmtt_init(void)
+{
+ omap_mpu_wdt_mode(0);
+
+ omap_board_config = palmtt_config;
+ omap_board_config_size = ARRAY_SIZE(palmtt_config);
+
+ platform_add_devices(palmtt_devices, ARRAY_SIZE(palmtt_devices));
+
+ spi_register_board_info(palmtt_boardinfo,ARRAY_SIZE(palmtt_boardinfo));
+ omap_serial_init();
+}
+
+static void __init omap_palmtt_map_io(void)
+{
+ omap1_map_common_io();
+}
+
+MACHINE_START(OMAP_PALMTT, "OMAP1510 based Palm Tungsten|T")
+ .phys_io = 0xfff00000,
+ .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
+ .boot_params = 0x10000100,
+ .map_io = omap_palmtt_map_io,
+ .init_irq = omap_palmtt_init_irq,
+ .init_machine = omap_palmtt_init,
+ .timer = &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap1/board-palmz71.c b/arch/arm/mach-omap1/board-palmz71.c
new file mode 100644
index 000000000000..c275d517764a
--- /dev/null
+++ b/arch/arm/mach-omap1/board-palmz71.c
@@ -0,0 +1,383 @@
+/*
+ * linux/arch/arm/mach-omap1/board-palmz71.c
+ *
+ * Modified from board-generic.c
+ *
+ * Support for the Palm Zire71 PDA.
+ *
+ * Original version : Laurent Gonzalez
+ *
+ * Modified for zire71 : Marek Vasut
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/notifier.h>
+#include <linux/clk.h>
+#include <linux/irq.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/flash.h>
+
+#include <asm/arch/mcbsp.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/usb.h>
+#include <asm/arch/dma.h>
+#include <asm/arch/tc.h>
+#include <asm/arch/board.h>
+#include <asm/arch/irda.h>
+#include <asm/arch/keypad.h>
+#include <asm/arch/common.h>
+#include <asm/arch/omap-alsa.h>
+
+#include <linux/input.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
+
+static void __init
+omap_palmz71_init_irq(void)
+{
+ omap1_init_common_hw();
+ omap_init_irq();
+ omap_gpio_init();
+}
+
+static int palmz71_keymap[] = {
+ KEY(0, 0, KEY_F1),
+ KEY(0, 1, KEY_F2),
+ KEY(0, 2, KEY_F3),
+ KEY(0, 3, KEY_F4),
+ KEY(0, 4, KEY_POWER),
+ KEY(1, 0, KEY_LEFT),
+ KEY(1, 1, KEY_DOWN),
+ KEY(1, 2, KEY_UP),
+ KEY(1, 3, KEY_RIGHT),
+ KEY(1, 4, KEY_CENTER),
+ KEY(2, 0, KEY_CAMERA),
+ 0,
+};
+
+static struct omap_kp_platform_data palmz71_kp_data = {
+ .rows = 8,
+ .cols = 8,
+ .keymap = palmz71_keymap,
+ .rep = 1,
+ .delay = 80,
+};
+
+static struct resource palmz71_kp_resources[] = {
+ [0] = {
+ .start = INT_KEYBOARD,
+ .end = INT_KEYBOARD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device palmz71_kp_device = {
+ .name = "omap-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &palmz71_kp_data,
+ },
+ .num_resources = ARRAY_SIZE(palmz71_kp_resources),
+ .resource = palmz71_kp_resources,
+};
+
+static struct mtd_partition palmz71_rom_partitions[] = {
+ /* PalmOS "Small ROM", contains the bootloader and the debugger */
+ {
+ .name = "smallrom",
+ .offset = 0,
+ .size = 0xa000,
+ .mask_flags = MTD_WRITEABLE,
+ },
+ /* PalmOS "Big ROM", a filesystem with all the OS code and data */
+ {
+ .name = "bigrom",
+ .offset = SZ_128K,
+ /*
+ * 0x5f0000 bytes big in the multi-language ("EFIGS") version,
+ * 0x7b0000 bytes in the English-only ("enUS") version.
+ */
+ .size = 0x7b0000,
+ .mask_flags = MTD_WRITEABLE,
+ },
+};
+
+static struct flash_platform_data palmz71_rom_data = {
+ .map_name = "map_rom",
+ .name = "onboardrom",
+ .width = 2,
+ .parts = palmz71_rom_partitions,
+ .nr_parts = ARRAY_SIZE(palmz71_rom_partitions),
+};
+
+static struct resource palmz71_rom_resource = {
+ .start = OMAP_CS0_PHYS,
+ .end = OMAP_CS0_PHYS + SZ_8M - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device palmz71_rom_device = {
+ .name = "omapflash",
+ .id = -1,
+ .dev = {
+ .platform_data = &palmz71_rom_data,
+ },
+ .num_resources = 1,
+ .resource = &palmz71_rom_resource,
+};
+
+static struct platform_device palmz71_lcd_device = {
+ .name = "lcd_palmz71",
+ .id = -1,
+};
+
+static struct omap_irda_config palmz71_irda_config = {
+ .transceiver_cap = IR_SIRMODE,
+ .rx_channel = OMAP_DMA_UART3_RX,
+ .tx_channel = OMAP_DMA_UART3_TX,
+ .dest_start = UART3_THR,
+ .src_start = UART3_RHR,
+ .tx_trigger = 0,
+ .rx_trigger = 0,
+};
+
+static struct resource palmz71_irda_resources[] = {
+ [0] = {
+ .start = INT_UART3,
+ .end = INT_UART3,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device palmz71_irda_device = {
+ .name = "omapirda",
+ .id = -1,
+ .dev = {
+ .platform_data = &palmz71_irda_config,
+ },
+ .num_resources = ARRAY_SIZE(palmz71_irda_resources),
+ .resource = palmz71_irda_resources,
+};
+
+static struct platform_device palmz71_spi_device = {
+ .name = "spi_palmz71",
+ .id = -1,
+};
+
+#define DEFAULT_BITPERSAMPLE 16
+
+static struct omap_mcbsp_reg_cfg mcbsp_regs = {
+ .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
+ .spcr1 = RINTM(3) | RRST,
+ .rcr2 = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
+ RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(0),
+ .rcr1 = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16),
+ .xcr2 = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
+ XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(0) | XFIG,
+ .xcr1 = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16),
+ .srgr1 = FWID(DEFAULT_BITPERSAMPLE - 1),
+ .srgr2 = GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1),
+ .pcr0 = CLKXP | CLKRP, /* mcbsp: slave */
+};
+
+static struct omap_alsa_codec_config alsa_config = {
+ .name = "PalmZ71 AIC23",
+ .mcbsp_regs_alsa = &mcbsp_regs,
+ .codec_configure_dev = NULL, /* aic23_configure */
+ .codec_set_samplerate = NULL, /* aic23_set_samplerate */
+ .codec_clock_setup = NULL, /* aic23_clock_setup */
+ .codec_clock_on = NULL, /* aic23_clock_on */
+ .codec_clock_off = NULL, /* aic23_clock_off */
+ .get_default_samplerate = NULL, /* aic23_get_default_samplerate */
+};
+
+static struct platform_device palmz71_mcbsp1_device = {
+ .name = "omap_alsa_mcbsp",
+ .id = 1,
+ .dev = {
+ .platform_data = &alsa_config,
+ },
+};
+
+static struct omap_backlight_config palmz71_backlight_config = {
+ .default_intensity = 0xa0,
+};
+
+static struct platform_device palmz71_backlight_device = {
+ .name = "omap-bl",
+ .id = -1,
+ .dev = {
+ .platform_data = &palmz71_backlight_config,
+ },
+};
+
+static struct platform_device *devices[] __initdata = {
+ &palmz71_rom_device,
+ &palmz71_kp_device,
+ &palmz71_mcbsp1_device,
+ &palmz71_lcd_device,
+ &palmz71_irda_device,
+ &palmz71_spi_device,
+ &palmz71_backlight_device,
+};
+
+static int
+palmz71_get_pendown_state(void)
+{
+ return !omap_get_gpio_datain(PALMZ71_PENIRQ_GPIO);
+}
+
+static const struct ads7846_platform_data palmz71_ts_info = {
+ .model = 7846,
+ .vref_delay_usecs = 100, /* internal, no capacitor */
+ .x_plate_ohms = 419,
+ .y_plate_ohms = 486,
+ .get_pendown_state = palmz71_get_pendown_state,
+};
+
+static struct spi_board_info __initdata palmz71_boardinfo[] = { {
+ /* MicroWire (bus 2) CS0 has an ads7846e */
+ .modalias = "ads7846",
+ .platform_data = &palmz71_ts_info,
+ .irq = OMAP_GPIO_IRQ(PALMZ71_PENIRQ_GPIO),
+ .max_speed_hz = 120000 /* max sample rate at 3V */
+ * 26 /* command + data + overhead */,
+ .bus_num = 2,
+ .chip_select = 0,
+} };
+
+static struct omap_usb_config palmz71_usb_config __initdata = {
+ .register_dev = 1, /* Mini-B only receptacle */
+ .hmc_mode = 0,
+ .pins[0] = 2,
+};
+
+static struct omap_mmc_config palmz71_mmc_config __initdata = {
+ .mmc[0] = {
+ .enabled = 1,
+ .wire4 = 0,
+ .wp_pin = PALMZ71_MMC_WP_GPIO,
+ .power_pin = -1,
+ .switch_pin = PALMZ71_MMC_IN_GPIO,
+ },
+};
+
+static struct omap_lcd_config palmz71_lcd_config __initdata = {
+ .ctrl_name = "internal",
+};
+
+static struct omap_uart_config palmz71_uart_config __initdata = {
+ .enabled_uarts = (1 << 0) | (1 << 1) | (0 << 2),
+};
+
+static struct omap_board_config_kernel palmz71_config[] = {
+ {OMAP_TAG_USB, &palmz71_usb_config},
+ {OMAP_TAG_MMC, &palmz71_mmc_config},
+ {OMAP_TAG_LCD, &palmz71_lcd_config},
+ {OMAP_TAG_UART, &palmz71_uart_config},
+};
+
+static irqreturn_t
+palmz71_powercable(int irq, void *dev_id)
+{
+ if (omap_get_gpio_datain(PALMZ71_USBDETECT_GPIO)) {
+ printk(KERN_INFO "PM: Power cable connected\n");
+ set_irq_type(OMAP_GPIO_IRQ(PALMZ71_USBDETECT_GPIO),
+ IRQT_FALLING);
+ } else {
+ printk(KERN_INFO "PM: Power cable disconnected\n");
+ set_irq_type(OMAP_GPIO_IRQ(PALMZ71_USBDETECT_GPIO),
+ IRQT_RISING);
+ }
+ return IRQ_HANDLED;
+}
+
+static void __init
+omap_mpu_wdt_mode(int mode)
+{
+ if (mode)
+ omap_writew(0x8000, OMAP_WDT_TIMER_MODE);
+ else {
+ omap_writew(0x00f5, OMAP_WDT_TIMER_MODE);
+ omap_writew(0x00a0, OMAP_WDT_TIMER_MODE);
+ }
+}
+
+static void __init
+palmz71_gpio_setup(int early)
+{
+ if (early) {
+ /* Only set GPIO1 so we have a working serial */
+ omap_set_gpio_dataout(1, 1);
+ omap_set_gpio_direction(1, 0);
+ } else {
+ /* Set MMC/SD host WP pin as input */
+ if (omap_request_gpio(PALMZ71_MMC_WP_GPIO)) {
+ printk(KERN_ERR "Could not reserve WP GPIO!\n");
+ return;
+ }
+ omap_set_gpio_direction(PALMZ71_MMC_WP_GPIO, 1);
+
+ /* Monitor the Power-cable-connected signal */
+ if (omap_request_gpio(PALMZ71_USBDETECT_GPIO)) {
+ printk(KERN_ERR
+ "Could not reserve cable signal GPIO!\n");
+ return;
+ }
+ omap_set_gpio_direction(PALMZ71_USBDETECT_GPIO, 1);
+ if (request_irq(OMAP_GPIO_IRQ(PALMZ71_USBDETECT_GPIO),
+ palmz71_powercable, IRQF_SAMPLE_RANDOM,
+ "palmz71-cable", 0))
+ printk(KERN_ERR
+ "IRQ request for power cable failed!\n");
+ palmz71_powercable(OMAP_GPIO_IRQ(PALMZ71_USBDETECT_GPIO), 0);
+ }
+}
+
+static void __init
+omap_palmz71_init(void)
+{
+ palmz71_gpio_setup(1);
+ omap_mpu_wdt_mode(0);
+
+ omap_board_config = palmz71_config;
+ omap_board_config_size = ARRAY_SIZE(palmz71_config);
+
+ platform_add_devices(devices, ARRAY_SIZE(devices));
+
+ spi_register_board_info(palmz71_boardinfo,
+ ARRAY_SIZE(palmz71_boardinfo));
+ omap_serial_init();
+ palmz71_gpio_setup(0);
+}
+
+static void __init
+omap_palmz71_map_io(void)
+{
+ omap1_map_common_io();
+}
+
+MACHINE_START(OMAP_PALMZ71, "OMAP310 based Palm Zire71")
+ .phys_io = 0xfff00000,
+ .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
+ .boot_params = 0x10000100,.map_io = omap_palmz71_map_io,
+ .init_irq = omap_palmz71_init_irq,
+ .init_machine = omap_palmz71_init,
+ .timer = &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap1/board-sx1.c b/arch/arm/mach-omap1/board-sx1.c
new file mode 100644
index 000000000000..2743d639aa05
--- /dev/null
+++ b/arch/arm/mach-omap1/board-sx1.c
@@ -0,0 +1,494 @@
+/*
+* linux/arch/arm/mach-omap1/board-sx1.c
+*
+* Modified from board-generic.c
+*
+* Support for the Siemens SX1 mobile phone.
+*
+* Original version : Vladimir Ananiev (Vovan888-at-gmail com)
+*
+* Maintainters : Vladimir Ananiev (aka Vovan888), Sergge
+* oslik.ru
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/notifier.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/types.h>
+#include <linux/i2c.h>
+#include <linux/errno.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/irda.h>
+#include <asm/arch/usb.h>
+#include <asm/arch/tc.h>
+#include <asm/arch/board.h>
+#include <asm/arch/common.h>
+#include <asm/arch/mcbsp.h>
+#include <asm/arch/omap-alsa.h>
+#include <asm/arch/keypad.h>
+
+/* Write to I2C device */
+int i2c_write_byte(u8 devaddr, u8 regoffset, u8 value)
+{
+ struct i2c_adapter *adap;
+ int err;
+ struct i2c_msg msg[1];
+ unsigned char data[2];
+
+ adap = i2c_get_adapter(0);
+ if (!adap)
+ return -ENODEV;
+ msg->addr = devaddr; /* I2C address of chip */
+ msg->flags = 0;
+ msg->len = 2;
+ msg->buf = data;
+ data[0] = regoffset; /* register num */
+ data[1] = value; /* register data */
+ err = i2c_transfer(adap, msg, 1);
+ if (err >= 0)
+ return 0;
+ return err;
+}
+
+/* Read from I2C device */
+int i2c_read_byte(u8 devaddr, u8 regoffset, u8 * value)
+{
+ struct i2c_adapter *adap;
+ int err;
+ struct i2c_msg msg[1];
+ unsigned char data[2];
+
+ adap = i2c_get_adapter(0);
+ if (!adap)
+ return -ENODEV;
+
+ msg->addr = devaddr; /* I2C address of chip */
+ msg->flags = 0;
+ msg->len = 1;
+ msg->buf = data;
+ data[0] = regoffset; /* register num */
+ err = i2c_transfer(adap, msg, 1);
+
+ msg->addr = devaddr; /* I2C address */
+ msg->flags = I2C_M_RD;
+ msg->len = 1;
+ msg->buf = data;
+ err = i2c_transfer(adap, msg, 1);
+ *value = data[0];
+
+ if (err >= 0)
+ return 0;
+ return err;
+}
+/* set keyboard backlight intensity */
+int sx1_setkeylight(u8 keylight)
+{
+ if (keylight > SOFIA_MAX_LIGHT_VAL)
+ keylight = SOFIA_MAX_LIGHT_VAL;
+ return i2c_write_byte(SOFIA_I2C_ADDR, SOFIA_KEYLIGHT_REG, keylight);
+}
+/* get current keylight intensity */
+int sx1_getkeylight(u8 * keylight)
+{
+ return i2c_read_byte(SOFIA_I2C_ADDR, SOFIA_KEYLIGHT_REG, keylight);
+}
+/* set LCD backlight intensity */
+int sx1_setbacklight(u8 backlight)
+{
+ if (backlight > SOFIA_MAX_LIGHT_VAL)
+ backlight = SOFIA_MAX_LIGHT_VAL;
+ return i2c_write_byte(SOFIA_I2C_ADDR, SOFIA_BACKLIGHT_REG, backlight);
+}
+/* get current LCD backlight intensity */
+int sx1_getbacklight (u8 * backlight)
+{
+ return i2c_read_byte(SOFIA_I2C_ADDR, SOFIA_BACKLIGHT_REG, backlight);
+}
+/* set LCD backlight power on/off */
+int sx1_setmmipower(u8 onoff)
+{
+ int err;
+ u8 dat = 0;
+ err = i2c_read_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, &dat);
+ if (err < 0)
+ return err;
+ if (onoff)
+ dat |= SOFIA_MMILIGHT_POWER;
+ else
+ dat &= ~SOFIA_MMILIGHT_POWER;
+ return i2c_write_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, dat);
+}
+/* set MMC power on/off */
+int sx1_setmmcpower(u8 onoff)
+{
+ int err;
+ u8 dat = 0;
+ err = i2c_read_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, &dat);
+ if (err < 0)
+ return err;
+ if (onoff)
+ dat |= SOFIA_MMC_POWER;
+ else
+ dat &= ~SOFIA_MMC_POWER;
+ return i2c_write_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, dat);
+}
+/* set USB power on/off */
+int sx1_setusbpower(u8 onoff)
+{
+ int err;
+ u8 dat = 0;
+ err = i2c_read_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, &dat);
+ if (err < 0)
+ return err;
+ if (onoff)
+ dat |= SOFIA_USB_POWER;
+ else
+ dat &= ~SOFIA_USB_POWER;
+ return i2c_write_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, dat);
+}
+
+EXPORT_SYMBOL(sx1_setkeylight);
+EXPORT_SYMBOL(sx1_getkeylight);
+EXPORT_SYMBOL(sx1_setbacklight);
+EXPORT_SYMBOL(sx1_getbacklight);
+EXPORT_SYMBOL(sx1_setmmipower);
+EXPORT_SYMBOL(sx1_setmmcpower);
+EXPORT_SYMBOL(sx1_setusbpower);
+
+/*----------- Keypad -------------------------*/
+
+static int sx1_keymap[] = {
+ KEY(5, 3, GROUP_0 | 117), /* camera Qt::Key_F17 */
+ KEY(0, 4, GROUP_0 | 114), /* voice memo Qt::Key_F14 */
+ KEY(1, 4, GROUP_2 | 114), /* voice memo */
+ KEY(2, 4, GROUP_3 | 114), /* voice memo */
+ KEY(0, 0, GROUP_1 | KEY_F12), /* red button Qt::Key_Hangup */
+ KEY(4, 3, GROUP_1 | KEY_LEFT),
+ KEY(2, 3, GROUP_1 | KEY_DOWN),
+ KEY(1, 3, GROUP_1 | KEY_RIGHT),
+ KEY(0, 3, GROUP_1 | KEY_UP),
+ KEY(3, 3, GROUP_1 | KEY_POWER), /* joystick press or Qt::Key_Select */
+ KEY(5, 0, GROUP_1 | KEY_1),
+ KEY(4, 0, GROUP_1 | KEY_2),
+ KEY(3, 0, GROUP_1 | KEY_3),
+ KEY(3, 4, GROUP_1 | KEY_4),
+ KEY(4, 4, GROUP_1 | KEY_5),
+ KEY(5, 4, GROUP_1 | KEY_KPASTERISK),/* "*" */
+ KEY(4, 1, GROUP_1 | KEY_6),
+ KEY(5, 1, GROUP_1 | KEY_7),
+ KEY(3, 1, GROUP_1 | KEY_8),
+ KEY(3, 2, GROUP_1 | KEY_9),
+ KEY(5, 2, GROUP_1 | KEY_0),
+ KEY(4, 2, GROUP_1 | 113), /* # F13 Toggle input method Qt::Key_F13 */
+ KEY(0, 1, GROUP_1 | KEY_F11), /* green button Qt::Key_Call */
+ KEY(1, 2, GROUP_1 | KEY_YEN), /* left soft Qt::Key_Context1 */
+ KEY(2, 2, GROUP_1 | KEY_F8), /* right soft Qt::Key_Back */
+ KEY(2, 1, GROUP_1 | KEY_LEFTSHIFT), /* shift */
+ KEY(1, 1, GROUP_1 | KEY_BACKSPACE), /* C (clear) */
+ KEY(0, 2, GROUP_1 | KEY_F7), /* menu Qt::Key_Menu */
+ 0
+};
+
+static struct resource sx1_kp_resources[] = {
+ [0] = {
+ .start = INT_KEYBOARD,
+ .end = INT_KEYBOARD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct omap_kp_platform_data sx1_kp_data = {
+ .rows = 6,
+ .cols = 6,
+ .keymap = sx1_keymap,
+ .keymapsize = ARRAY_SIZE(sx1_keymap),
+ .delay = 80,
+};
+
+static struct platform_device sx1_kp_device = {
+ .name = "omap-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &sx1_kp_data,
+ },
+ .num_resources = ARRAY_SIZE(sx1_kp_resources),
+ .resource = sx1_kp_resources,
+};
+
+/*----------- IRDA -------------------------*/
+
+static struct omap_irda_config sx1_irda_data = {
+ .transceiver_cap = IR_SIRMODE,
+ .rx_channel = OMAP_DMA_UART3_RX,
+ .tx_channel = OMAP_DMA_UART3_TX,
+ .dest_start = UART3_THR,
+ .src_start = UART3_RHR,
+ .tx_trigger = 0,
+ .rx_trigger = 0,
+};
+
+static struct resource sx1_irda_resources[] = {
+ [0] = {
+ .start = INT_UART3,
+ .end = INT_UART3,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 irda_dmamask = 0xffffffff;
+
+static struct platform_device sx1_irda_device = {
+ .name = "omapirda",
+ .id = 0,
+ .dev = {
+ .platform_data = &sx1_irda_data,
+ .dma_mask = &irda_dmamask,
+ },
+ .num_resources = ARRAY_SIZE(sx1_irda_resources),
+ .resource = sx1_irda_resources,
+};
+
+/*----------- McBSP & Sound -------------------------*/
+
+/* Playback interface - McBSP1 */
+static struct omap_mcbsp_reg_cfg mcbsp1_regs = {
+ .spcr2 = XINTM(3), /* SPCR2=30 */
+ .spcr1 = RINTM(3), /* SPCR1=30 */
+ .rcr2 = 0, /* RCR2 =00 */
+ .rcr1 = RFRLEN1(1) | RWDLEN1(OMAP_MCBSP_WORD_16), /* RCR1=140 */
+ .xcr2 = 0, /* XCR2 = 0 */
+ .xcr1 = XFRLEN1(1) | XWDLEN1(OMAP_MCBSP_WORD_16), /* XCR1 = 140 */
+ .srgr1 = FWID(15) | CLKGDV(12), /* SRGR1=0f0c */
+ .srgr2 = FSGM | FPER(31), /* SRGR2=101f */
+ .pcr0 = FSXM | FSRM | CLKXM | CLKRM | FSXP | FSRP | CLKXP | CLKRP,
+ /* PCR0 =0f0f */
+};
+
+/* TODO: PCM interface - McBSP2 */
+static struct omap_mcbsp_reg_cfg mcbsp2_regs = {
+ .spcr2 = FRST | GRST | XRST | XINTM(3), /* SPCR2=F1 */
+ .spcr1 = RINTM(3) | RRST, /* SPCR1=30 */
+ .rcr2 = 0, /* RCR2 =00 */
+ .rcr1 = RFRLEN1(1) | RWDLEN1(OMAP_MCBSP_WORD_16), /* RCR1 = 140 */
+ .xcr2 = 0, /* XCR2 = 0 */
+ .xcr1 = XFRLEN1(1) | XWDLEN1(OMAP_MCBSP_WORD_16), /* XCR1 = 140 */
+ .srgr1 = FWID(15) | CLKGDV(12), /* SRGR1=0f0c */
+ .srgr2 = FSGM | FPER(31), /* SRGR2=101f */
+ .pcr0 = FSXM | FSRM | CLKXM | CLKRM | FSXP | FSRP | CLKXP | CLKRP,
+ /* PCR0=0f0f */
+ /* mcbsp: slave */
+};
+
+static struct omap_alsa_codec_config sx1_alsa_config = {
+ .name = "SX1 EGold",
+ .mcbsp_regs_alsa = &mcbsp1_regs,
+};
+
+static struct platform_device sx1_mcbsp1_device = {
+ .name = "omap_alsa_mcbsp",
+ .id = 1,
+ .dev = {
+ .platform_data = &sx1_alsa_config,
+ },
+};
+
+/*----------- MTD -------------------------*/
+
+static struct mtd_partition sx1_partitions[] = {
+ /* bootloader (U-Boot, etc) in first sector */
+ {
+ .name = "bootloader",
+ .offset = 0x01800000,
+ .size = SZ_128K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ /* bootloader params in the next sector */
+ {
+ .name = "params",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_128K,
+ .mask_flags = 0,
+ },
+ /* kernel */
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_2M - 2 * SZ_128K,
+ .mask_flags = 0
+ },
+ /* file system */
+ {
+ .name = "filesystem",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0
+ }
+};
+
+static struct flash_platform_data sx1_flash_data = {
+ .map_name = "cfi_probe",
+ .width = 2,
+ .parts = sx1_partitions,
+ .nr_parts = ARRAY_SIZE(sx1_partitions),
+};
+
+#ifdef CONFIG_SX1_OLD_FLASH
+/* MTD Intel StrataFlash - old flashes */
+static struct resource sx1_old_flash_resource[] = {
+ [0] = {
+ .start = OMAP_CS0_PHYS, /* Physical */
+ .end = OMAP_CS0_PHYS + SZ_16M - 1,,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = OMAP_CS1_PHYS,
+ .end = OMAP_CS1_PHYS + SZ_8M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device sx1_flash_device = {
+ .name = "omapflash",
+ .id = 0,
+ .dev = {
+ .platform_data = &sx1_flash_data,
+ },
+ .num_resources = 2,
+ .resource = &sx1_old_flash_resource,
+};
+#else
+/* MTD Intel 4000 flash - new flashes */
+static struct resource sx1_new_flash_resource = {
+ .start = OMAP_CS0_PHYS,
+ .end = OMAP_CS0_PHYS + SZ_32M - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device sx1_flash_device = {
+ .name = "omapflash",
+ .id = 0,
+ .dev = {
+ .platform_data = &sx1_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &sx1_new_flash_resource,
+};
+#endif
+
+/*----------- USB -------------------------*/
+
+static struct omap_usb_config sx1_usb_config __initdata = {
+ .otg = 0,
+ .register_dev = 1,
+ .register_host = 0,
+ .hmc_mode = 0,
+ .pins[0] = 2,
+ .pins[1] = 0,
+ .pins[2] = 0,
+};
+
+/*----------- MMC -------------------------*/
+
+static struct omap_mmc_config sx1_mmc_config __initdata = {
+ .mmc [0] = {
+ .enabled = 1,
+ .wire4 = 0,
+ .wp_pin = -1,
+ .power_pin = -1, /* power is in Sofia */
+ .switch_pin = OMAP_MPUIO(3),
+ },
+};
+
+/*----------- LCD -------------------------*/
+
+static struct platform_device sx1_lcd_device = {
+ .name = "lcd_sx1",
+ .id = -1,
+};
+
+static struct omap_lcd_config sx1_lcd_config __initdata = {
+ .ctrl_name = "internal",
+};
+
+/*-----------------------------------------*/
+static struct platform_device *sx1_devices[] __initdata = {
+ &sx1_flash_device,
+ &sx1_kp_device,
+ &sx1_lcd_device,
+ &sx1_mcbsp1_device,
+ &sx1_irda_device,
+};
+/*-----------------------------------------*/
+
+static struct omap_uart_config sx1_uart_config __initdata = {
+ .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
+};
+
+static struct omap_board_config_kernel sx1_config[] = {
+ { OMAP_TAG_USB, &sx1_usb_config },
+ { OMAP_TAG_MMC, &sx1_mmc_config },
+ { OMAP_TAG_LCD, &sx1_lcd_config },
+ { OMAP_TAG_UART, &sx1_uart_config },
+};
+/*-----------------------------------------*/
+static void __init omap_sx1_init(void)
+{
+ platform_add_devices(sx1_devices, ARRAY_SIZE(sx1_devices));
+
+ omap_board_config = sx1_config;
+ omap_board_config_size = ARRAY_SIZE(sx1_config);
+ omap_serial_init();
+
+ /* turn on USB power */
+ /* sx1_setusbpower(1); cant do it here because i2c is not ready */
+ omap_request_gpio(1); /* A_IRDA_OFF */
+ omap_request_gpio(11); /* A_SWITCH */
+ omap_request_gpio(15); /* A_USB_ON */
+ omap_set_gpio_direction(1, 0);/* gpio1 -> output */
+ omap_set_gpio_direction(11, 0);/* gpio11 -> output */
+ omap_set_gpio_direction(15, 0);/* gpio15 -> output */
+ /* set GPIO data */
+ omap_set_gpio_dataout(1, 1);/*A_IRDA_OFF = 1 */
+ omap_set_gpio_dataout(11, 0);/*A_SWITCH = 0 */
+ omap_set_gpio_dataout(15, 0);/*A_USB_ON = 0 */
+
+}
+/*----------------------------------------*/
+static void __init omap_sx1_init_irq(void)
+{
+ omap1_init_common_hw();
+ omap_init_irq();
+ omap_gpio_init();
+}
+/*----------------------------------------*/
+
+static void __init omap_sx1_map_io(void)
+{
+ omap1_map_common_io();
+}
+
+MACHINE_START(SX1, "OMAP310 based Siemens SX1")
+ .phys_io = 0xfff00000,
+ .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
+ .boot_params = 0x10000100,
+ .map_io = omap_sx1_map_io,
+ .init_irq = omap_sx1_init_irq,
+ .init_machine = omap_sx1_init,
+ .timer = &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c
index 447a586eb334..214dd19889ac 100644
--- a/arch/arm/mach-omap1/board-voiceblue.c
+++ b/arch/arm/mach-omap1/board-voiceblue.c
@@ -235,7 +235,7 @@ static struct notifier_block panic_block = {
static int __init voiceblue_setup(void)
{
/* Setup panic notifier */
- notifier_chain_register(&panic_notifier_list, &panic_block);
+ atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
return 0;
}
diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c
index f625f6dd228a..5d9faa68d2ec 100644
--- a/arch/arm/mach-omap1/clock.c
+++ b/arch/arm/mach-omap1/clock.c
@@ -49,6 +49,15 @@ static void omap1_uart_recalc(struct clk * clk)
clk->rate = 12000000;
}
+static void omap1_sossi_recalc(struct clk *clk)
+{
+ u32 div = omap_readl(MOD_CONF_CTRL_1);
+
+ div = (div >> 17) & 0x7;
+ div++;
+ clk->rate = clk->parent->rate / div;
+}
+
static int omap1_clk_enable_dsp_domain(struct clk *clk)
{
int retval;
@@ -396,6 +405,31 @@ static int omap1_set_ext_clk_rate(struct clk * clk, unsigned long rate)
return 0;
}
+static int omap1_set_sossi_rate(struct clk *clk, unsigned long rate)
+{
+ u32 l;
+ int div;
+ unsigned long p_rate;
+
+ p_rate = clk->parent->rate;
+ /* Round towards slower frequency */
+ div = (p_rate + rate - 1) / rate;
+ div--;
+ if (div < 0 || div > 7)
+ return -EINVAL;
+
+ l = omap_readl(MOD_CONF_CTRL_1);
+ l &= ~(7 << 17);
+ l |= div << 17;
+ omap_writel(l, MOD_CONF_CTRL_1);
+
+ clk->rate = p_rate / (div + 1);
+ if (unlikely(clk->flags & RATE_PROPAGATES))
+ propagate_rate(clk);
+
+ return 0;
+}
+
static long omap1_round_ext_clk_rate(struct clk * clk, unsigned long rate)
{
return 96000000 / calc_ext_dsor(rate);
diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h
index f7df00205c4a..6eadf72828d8 100644
--- a/arch/arm/mach-omap1/clock.h
+++ b/arch/arm/mach-omap1/clock.h
@@ -17,6 +17,8 @@ static int omap1_clk_enable_generic(struct clk * clk);
static void omap1_clk_disable_generic(struct clk * clk);
static void omap1_ckctl_recalc(struct clk * clk);
static void omap1_watchdog_recalc(struct clk * clk);
+static int omap1_set_sossi_rate(struct clk *clk, unsigned long rate);
+static void omap1_sossi_recalc(struct clk *clk);
static void omap1_ckctl_recalc_dsp_domain(struct clk * clk);
static int omap1_clk_enable_dsp_domain(struct clk * clk);
static int omap1_clk_set_rate_dsp_domain(struct clk * clk, unsigned long rate);
@@ -168,9 +170,10 @@ static struct clk ck_dpll1 = {
static struct arm_idlect1_clk ck_dpll1out = {
.clk = {
- .name = "ck_dpll1out",
+ .name = "ck_dpll1out",
.parent = &ck_dpll1,
- .flags = CLOCK_IN_OMAP16XX | CLOCK_IDLE_CONTROL,
+ .flags = CLOCK_IN_OMAP16XX | CLOCK_IDLE_CONTROL |
+ ENABLE_REG_32BIT | RATE_PROPAGATES,
.enable_reg = (void __iomem *)ARM_IDLECT2,
.enable_bit = EN_CKOUT_ARM,
.recalc = &followparent_recalc,
@@ -180,6 +183,19 @@ static struct arm_idlect1_clk ck_dpll1out = {
.idlect_shift = 12,
};
+static struct clk sossi_ck = {
+ .name = "ck_sossi",
+ .parent = &ck_dpll1out.clk,
+ .flags = CLOCK_IN_OMAP16XX | CLOCK_NO_IDLE_PARENT |
+ ENABLE_REG_32BIT,
+ .enable_reg = (void __iomem *)MOD_CONF_CTRL_1,
+ .enable_bit = 16,
+ .recalc = &omap1_sossi_recalc,
+ .set_rate = &omap1_set_sossi_rate,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
+};
+
static struct clk arm_ck = {
.name = "arm_ck",
.parent = &ck_dpll1,
@@ -282,7 +298,7 @@ static struct clk arminth_ck16xx = {
static struct clk dsp_ck = {
.name = "dsp_ck",
.parent = &ck_dpll1,
- .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+ .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
RATE_CKCTL,
.enable_reg = (void __iomem *)ARM_CKCTL,
.enable_bit = EN_DSPCK,
@@ -295,7 +311,7 @@ static struct clk dsp_ck = {
static struct clk dspmmu_ck = {
.name = "dspmmu_ck",
.parent = &ck_dpll1,
- .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+ .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
RATE_CKCTL | ALWAYS_ENABLED,
.rate_offset = CKCTL_DSPMMUDIV_OFFSET,
.recalc = &omap1_ckctl_recalc,
@@ -306,7 +322,7 @@ static struct clk dspmmu_ck = {
static struct clk dspper_ck = {
.name = "dspper_ck",
.parent = &ck_dpll1,
- .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+ .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
RATE_CKCTL | VIRTUAL_IO_ADDRESS,
.enable_reg = (void __iomem *)DSP_IDLECT2,
.enable_bit = EN_PERCK,
@@ -320,7 +336,7 @@ static struct clk dspper_ck = {
static struct clk dspxor_ck = {
.name = "dspxor_ck",
.parent = &ck_ref,
- .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+ .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
VIRTUAL_IO_ADDRESS,
.enable_reg = (void __iomem *)DSP_IDLECT2,
.enable_bit = EN_XORPCK,
@@ -332,7 +348,7 @@ static struct clk dspxor_ck = {
static struct clk dsptim_ck = {
.name = "dsptim_ck",
.parent = &ck_ref,
- .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+ .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
VIRTUAL_IO_ADDRESS,
.enable_reg = (void __iomem *)DSP_IDLECT2,
.enable_bit = EN_DSPTIMCK,
@@ -374,7 +390,7 @@ static struct clk arminth_ck1510 = {
static struct clk tipb_ck = {
/* No-idle controlled by "tc_ck" */
- .name = "tibp_ck",
+ .name = "tipb_ck",
.parent = &tc_ck.clk,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
ALWAYS_ENABLED,
@@ -733,7 +749,7 @@ remains active during MPU idle whenever this is enabled */
static struct clk i2c_fck = {
.name = "i2c_fck",
.id = 1,
- .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+ .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
VIRTUAL_CLOCK | CLOCK_NO_IDLE_PARENT |
ALWAYS_ENABLED,
.parent = &armxor_ck.clk,
@@ -760,6 +776,7 @@ static struct clk * onchip_clks[] = {
&ck_dpll1,
/* CK_GEN1 clocks */
&ck_dpll1out.clk,
+ &sossi_ck,
&arm_ck,
&armper_ck.clk,
&arm_gpio_ck,
diff --git a/arch/arm/mach-omap1/irq.c b/arch/arm/mach-omap1/irq.c
index 0733078940fa..1da9d59a0347 100644
--- a/arch/arm/mach-omap1/irq.c
+++ b/arch/arm/mach-omap1/irq.c
@@ -5,7 +5,7 @@
*
* Copyright (C) 2004 Nokia Corporation
* Written by Tony Lindgren <tony@atomide.com>
- * Major cleanups by Juha Yrjölä <juha.yrjola@nokia.com>
+ * Major cleanups by Juha Yrjölä <juha.yrjola@nokia.com>
*
* Completely re-written to support various OMAP chips with bank specific
* interrupt handlers.
diff --git a/arch/arm/mach-omap1/leds-innovator.c b/arch/arm/mach-omap1/leds-innovator.c
index a0cd001ac39a..e7835d6f53a0 100644
--- a/arch/arm/mach-omap1/leds-innovator.c
+++ b/arch/arm/mach-omap1/leds-innovator.c
@@ -95,8 +95,5 @@ void innovator_leds_event(led_event_t evt)
break;
}
- if (led_state & LED_STATE_ENABLED)
- ;
-
local_irq_restore(flags);
}
diff --git a/arch/arm/mach-omap1/mux.c b/arch/arm/mach-omap1/mux.c
index 5432335bc493..52c70e5fcf65 100644
--- a/arch/arm/mach-omap1/mux.c
+++ b/arch/arm/mach-omap1/mux.c
@@ -283,6 +283,30 @@ MUX_CFG("R11_1610_CF_IOIS16", B, 0, 3, 2, 16, 1, 2, 1, 1)
MUX_CFG("V10_1610_CF_IREQ", A, 24, 3, 2, 14, 0, 2, 0, 1)
MUX_CFG("W10_1610_CF_RESET", A, 18, 3, 2, 12, 1, 2, 1, 1)
MUX_CFG("W11_1610_CF_CD1", 10, 15, 3, 3, 8, 1, 3, 1, 1)
+
+/* parallel camera */
+MUX_CFG("J15_1610_CAM_LCLK", 4, 24, 0, 0, 18, 1, 0, 0, 0)
+MUX_CFG("J18_1610_CAM_D7", 4, 27, 0, 0, 19, 1, 0, 0, 0)
+MUX_CFG("J19_1610_CAM_D6", 5, 0, 0, 0, 20, 1, 0, 0, 0)
+MUX_CFG("J14_1610_CAM_D5", 5, 3, 0, 0, 21, 1, 0, 0, 0)
+MUX_CFG("K18_1610_CAM_D4", 5, 6, 0, 0, 22, 1, 0, 0, 0)
+MUX_CFG("K19_1610_CAM_D3", 5, 9, 0, 0, 23, 1, 0, 0, 0)
+MUX_CFG("K15_1610_CAM_D2", 5, 12, 0, 0, 24, 1, 0, 0, 0)
+MUX_CFG("K14_1610_CAM_D1", 5, 15, 0, 0, 25, 1, 0, 0, 0)
+MUX_CFG("L19_1610_CAM_D0", 5, 18, 0, 0, 26, 1, 0, 0, 0)
+MUX_CFG("L18_1610_CAM_VS", 5, 21, 0, 0, 27, 1, 0, 0, 0)
+MUX_CFG("L15_1610_CAM_HS", 5, 24, 0, 0, 28, 1, 0, 0, 0)
+MUX_CFG("M19_1610_CAM_RSTZ", 5, 27, 0, 0, 29, 0, 0, 0, 0)
+MUX_CFG("Y15_1610_CAM_OUTCLK", A, 0, 6, 2, 6, 0, 2, 0, 0)
+
+/* serial camera */
+MUX_CFG("H19_1610_CAM_EXCLK", 4, 21, 0, 0, 17, 0, 0, 0, 0)
+ /* REVISIT 5912 spec sez CCP_* can't pullup or pulldown ... ? */
+MUX_CFG("Y12_1610_CCP_CLKP", 8, 18, 6, 1, 24, 1, 1, 0, 0)
+MUX_CFG("W13_1610_CCP_CLKM", 9, 0, 6, 1, 28, 1, 1, 0, 0)
+MUX_CFG("W14_1610_CCP_DATAP", 9, 24, 6, 2, 4, 1, 2, 0, 0)
+MUX_CFG("Y14_1610_CCP_DATAM", 9, 21, 6, 2, 3, 1, 2, 0, 0)
+
};
#endif /* CONFIG_ARCH_OMAP15XX || CONFIG_ARCH_OMAP16XX */
diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c
index 2e68be607295..3bf01e28df33 100644
--- a/arch/arm/mach-omap1/pm.c
+++ b/arch/arm/mach-omap1/pm.c
@@ -35,10 +35,9 @@
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/pm.h>
+#include <linux/suspend.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
-#include <linux/pm.h>
#include <linux/interrupt.h>
#include <linux/sysfs.h>
#include <linux/module.h>
@@ -153,11 +152,8 @@ void omap_pm_idle(void)
use_idlect1 = omap_dm_timer_modify_idlect_mask(use_idlect1);
#endif
- if (omap_dma_running()) {
+ if (omap_dma_running())
use_idlect1 &= ~(1 << 6);
- if (omap_lcd_dma_ext_running())
- use_idlect1 &= ~(1 << 12);
- }
/* We should be able to remove the do_sleep variable and multiple
* tests above as soon as drivers, timer and DMA code have been fixed.
@@ -603,27 +599,15 @@ static void (*saved_idle)(void) = NULL;
/*
* omap_pm_prepare - Do preliminary suspend work.
- * @state: suspend state we're entering.
*
*/
-static int omap_pm_prepare(suspend_state_t state)
+static int omap_pm_prepare(void)
{
- int error = 0;
-
/* We cannot sleep in idle until we have resumed */
saved_idle = pm_idle;
pm_idle = NULL;
- switch (state)
- {
- case PM_SUSPEND_STANDBY:
- case PM_SUSPEND_MEM:
- break;
- default:
- return -EINVAL;
- }
-
- return error;
+ return 0;
}
@@ -651,16 +635,14 @@ static int omap_pm_enter(suspend_state_t state)
/**
* omap_pm_finish - Finish up suspend sequence.
- * @state: State we're coming out of.
*
* This is called after we wake back up (or if entering the sleep state
* failed).
*/
-static int omap_pm_finish(suspend_state_t state)
+static void omap_pm_finish(void)
{
pm_idle = saved_idle;
- return 0;
}
@@ -677,11 +659,11 @@ static struct irqaction omap_wakeup_irq = {
-static struct pm_ops omap_pm_ops ={
+static struct platform_suspend_ops omap_pm_ops ={
.prepare = omap_pm_prepare,
.enter = omap_pm_enter,
.finish = omap_pm_finish,
- .valid = pm_valid_only_mem,
+ .valid = suspend_valid_only_mem,
};
static int __init omap_pm_init(void)
@@ -738,7 +720,7 @@ static int __init omap_pm_init(void)
else if (cpu_is_omap16xx())
omap_writel(OMAP1610_IDLECT3_VAL, OMAP1610_IDLECT3);
- pm_set_ops(&omap_pm_ops);
+ suspend_set_ops(&omap_pm_ops);
#if defined(DEBUG) && defined(CONFIG_PROC_FS)
omap_pm_init_proc();
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 7393109f5c30..7069c9d536f1 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -11,6 +11,10 @@ config ARCH_OMAP2420
select OMAP_DM_TIMER
select ARCH_OMAP_OTG
+config ARCH_OMAP2430
+ bool "OMAP2430 support"
+ depends on ARCH_OMAP24XX
+
comment "OMAP Board Type"
depends on ARCH_OMAP2
@@ -21,8 +25,13 @@ config MACH_OMAP_GENERIC
config MACH_OMAP_H4
bool "OMAP 2420 H4 board"
depends on ARCH_OMAP2 && ARCH_OMAP24XX
- select OMAP_DEBUG_LEDS if LEDS || LEDS_OMAP_DEBUG
+ select OMAP_DEBUG_DEVICES
config MACH_OMAP_APOLLON
bool "OMAP 2420 Apollon board"
depends on ARCH_OMAP2 && ARCH_OMAP24XX
+
+config MACH_OMAP_2430SDP
+ bool "OMAP 2430 SDP board"
+ depends on ARCH_OMAP2 && ARCH_OMAP24XX
+
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 266d88e77bdc..b05b738d31e6 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -14,5 +14,6 @@ obj-$(CONFIG_PM) += pm.o pm-domain.o sleep.o
# Specific board support
obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o
obj-$(CONFIG_MACH_OMAP_H4) += board-h4.o
+obj-$(CONFIG_MACH_OMAP_2430SDP) += board-2430sdp.o
obj-$(CONFIG_MACH_OMAP_APOLLON) += board-apollon.o
diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
new file mode 100644
index 000000000000..7e76fbf19b5d
--- /dev/null
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -0,0 +1,218 @@
+/*
+ * linux/arch/arm/mach-omap2/board-2430sdp.c
+ *
+ * Copyright (C) 2006 Texas Instruments
+ *
+ * Modified from mach-omap2/board-generic.c
+ *
+ * Initial Code : Based on a patch from Komal Shah and Richard Woodruff
+ * Updated the Code for 2430 SDP : Syed Mohammed Khasim
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/flash.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/board.h>
+#include <asm/arch/common.h>
+#include <asm/arch/gpmc.h>
+#include "prcm-regs.h"
+
+#include <asm/io.h>
+
+
+#define SDP2430_FLASH_CS 0
+#define SDP2430_SMC91X_CS 5
+
+static struct mtd_partition sdp2430_partitions[] = {
+ /* bootloader (U-Boot, etc) in first sector */
+ {
+ .name = "bootloader",
+ .offset = 0,
+ .size = SZ_256K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ /* bootloader params in the next sector */
+ {
+ .name = "params",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_128K,
+ .mask_flags = 0,
+ },
+ /* kernel */
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_2M,
+ .mask_flags = 0
+ },
+ /* file system */
+ {
+ .name = "filesystem",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0
+ }
+};
+
+static struct flash_platform_data sdp2430_flash_data = {
+ .map_name = "cfi_probe",
+ .width = 2,
+ .parts = sdp2430_partitions,
+ .nr_parts = ARRAY_SIZE(sdp2430_partitions),
+};
+
+static struct resource sdp2430_flash_resource = {
+ .start = SDP2430_CS0_BASE,
+ .end = SDP2430_CS0_BASE + SZ_64M - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device sdp2430_flash_device = {
+ .name = "omapflash",
+ .id = 0,
+ .dev = {
+ .platform_data = &sdp2430_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &sdp2430_flash_resource,
+};
+
+static struct resource sdp2430_smc91x_resources[] = {
+ [0] = {
+ .start = SDP2430_CS0_BASE,
+ .end = SDP2430_CS0_BASE + SZ_64M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = OMAP_GPIO_IRQ(OMAP24XX_ETHR_GPIO_IRQ),
+ .end = OMAP_GPIO_IRQ(OMAP24XX_ETHR_GPIO_IRQ),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device sdp2430_smc91x_device = {
+ .name = "smc91x",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(sdp2430_smc91x_resources),
+ .resource = sdp2430_smc91x_resources,
+};
+
+static struct platform_device *sdp2430_devices[] __initdata = {
+ &sdp2430_smc91x_device,
+ &sdp2430_flash_device,
+};
+
+static inline void __init sdp2430_init_smc91x(void)
+{
+ int eth_cs;
+ unsigned long cs_mem_base;
+ unsigned int rate;
+ struct clk *l3ck;
+
+ eth_cs = SDP2430_SMC91X_CS;
+
+ l3ck = clk_get(NULL, "core_l3_ck");
+ if (IS_ERR(l3ck))
+ rate = 100000000;
+ else
+ rate = clk_get_rate(l3ck);
+
+ /* Make sure CS1 timings are correct, for 2430 always muxed */
+ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG1, 0x00011200);
+
+ if (rate >= 160000000) {
+ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f01);
+ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080803);
+ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1c0b1c0a);
+ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
+ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
+ } else if (rate >= 130000000) {
+ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
+ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
+ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
+ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
+ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
+ } else { /* rate = 100000000 */
+ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
+ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
+ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
+ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x031A1F1F);
+ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000003C2);
+ }
+
+ if (gpmc_cs_request(eth_cs, SZ_16M, &cs_mem_base) < 0) {
+ printk(KERN_ERR "Failed to request GPMC mem for smc91x\n");
+ return;
+ }
+
+ sdp2430_smc91x_resources[0].start = cs_mem_base + 0x300;
+ sdp2430_smc91x_resources[0].end = cs_mem_base + 0x30f;
+ udelay(100);
+
+ if (omap_request_gpio(OMAP24XX_ETHR_GPIO_IRQ) < 0) {
+ printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n",
+ OMAP24XX_ETHR_GPIO_IRQ);
+ gpmc_cs_free(eth_cs);
+ return;
+ }
+ omap_set_gpio_direction(OMAP24XX_ETHR_GPIO_IRQ, 1);
+
+}
+
+static void __init omap_2430sdp_init_irq(void)
+{
+ omap2_init_common_hw();
+ omap_init_irq();
+ omap_gpio_init();
+ sdp2430_init_smc91x();
+}
+
+static struct omap_uart_config sdp2430_uart_config __initdata = {
+ .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
+};
+
+static struct omap_board_config_kernel sdp2430_config[] = {
+ {OMAP_TAG_UART, &sdp2430_uart_config},
+};
+
+static void __init omap_2430sdp_init(void)
+{
+ platform_add_devices(sdp2430_devices, ARRAY_SIZE(sdp2430_devices));
+ omap_board_config = sdp2430_config;
+ omap_board_config_size = ARRAY_SIZE(sdp2430_config);
+ omap_serial_init();
+}
+
+static void __init omap_2430sdp_map_io(void)
+{
+ omap2_map_common_io();
+}
+
+MACHINE_START(OMAP_2430SDP, "OMAP2430 sdp2430 board")
+ /* Maintainer: Syed Khasim - Texas Instruments Inc */
+ .phys_io = 0x48000000,
+ .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc,
+ .boot_params = 0x80000100,
+ .map_io = omap_2430sdp_map_io,
+ .init_irq = omap_2430sdp_init_irq,
+ .init_machine = omap_2430sdp_init,
+ .timer = &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
index 878ff9181d0e..3bb49c17c858 100644
--- a/arch/arm/mach-omap2/board-apollon.c
+++ b/arch/arm/mach-omap2/board-apollon.c
@@ -25,6 +25,8 @@
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
+#include <linux/leds.h>
+#include <linux/irq.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
@@ -32,10 +34,12 @@
#include <asm/mach/flash.h>
#include <asm/arch/gpio.h>
+#include <asm/arch/led.h>
#include <asm/arch/mux.h>
#include <asm/arch/usb.h>
#include <asm/arch/board.h>
#include <asm/arch/common.h>
+#include <asm/arch/gpmc.h>
#include "prcm-regs.h"
/* LED & Switch macros */
@@ -46,6 +50,9 @@
#define SW_UP_GPIO17 17
#define SW_DOWN_GPIO58 58
+#define APOLLON_FLASH_CS 0
+#define APOLLON_ETH_CS 1
+
static struct mtd_partition apollon_partitions[] = {
{
.name = "X-Loader + U-Boot",
@@ -85,10 +92,10 @@ static struct flash_platform_data apollon_flash_data = {
.nr_parts = ARRAY_SIZE(apollon_partitions),
};
-static struct resource apollon_flash_resource = {
- .start = APOLLON_CS0_BASE,
- .end = APOLLON_CS0_BASE + SZ_128K,
- .flags = IORESOURCE_MEM,
+static struct resource apollon_flash_resource[] = {
+ [0] = {
+ .flags = IORESOURCE_MEM,
+ },
};
static struct platform_device apollon_onenand_device = {
@@ -97,14 +104,24 @@ static struct platform_device apollon_onenand_device = {
.dev = {
.platform_data = &apollon_flash_data,
},
- .num_resources = ARRAY_SIZE(&apollon_flash_resource),
- .resource = &apollon_flash_resource,
+ .num_resources = ARRAY_SIZE(apollon_flash_resource),
+ .resource = apollon_flash_resource,
};
+static void __init apollon_flash_init(void)
+{
+ unsigned long base;
+
+ if (gpmc_cs_request(APOLLON_FLASH_CS, SZ_128K, &base) < 0) {
+ printk(KERN_ERR "Cannot request OneNAND GPMC CS\n");
+ return;
+ }
+ apollon_flash_resource[0].start = base;
+ apollon_flash_resource[0].end = base + SZ_128K - 1;
+}
+
static struct resource apollon_smc91x_resources[] = {
[0] = {
- .start = APOLLON_ETHR_START, /* Physical */
- .end = APOLLON_ETHR_START + 0xf,
.flags = IORESOURCE_MEM,
},
[1] = {
@@ -126,14 +143,51 @@ static struct platform_device apollon_lcd_device = {
.id = -1,
};
+static struct omap_led_config apollon_led_config[] = {
+ {
+ .cdev = {
+ .name = "apollon:led0",
+ },
+ .gpio = LED0_GPIO13,
+ },
+ {
+ .cdev = {
+ .name = "apollon:led1",
+ },
+ .gpio = LED1_GPIO14,
+ },
+ {
+ .cdev = {
+ .name = "apollon:led2",
+ },
+ .gpio = LED2_GPIO15,
+ },
+};
+
+static struct omap_led_platform_data apollon_led_data = {
+ .nr_leds = ARRAY_SIZE(apollon_led_config),
+ .leds = apollon_led_config,
+};
+
+static struct platform_device apollon_led_device = {
+ .name = "omap-led",
+ .id = -1,
+ .dev = {
+ .platform_data = &apollon_led_data,
+ },
+};
+
static struct platform_device *apollon_devices[] __initdata = {
&apollon_onenand_device,
&apollon_smc91x_device,
&apollon_lcd_device,
+ &apollon_led_device,
};
static inline void __init apollon_init_smc91x(void)
{
+ unsigned long base;
+
/* Make sure CS1 timings are correct */
GPMC_CONFIG1_1 = 0x00011203;
GPMC_CONFIG2_1 = 0x001f1f01;
@@ -141,13 +195,20 @@ static inline void __init apollon_init_smc91x(void)
GPMC_CONFIG4_1 = 0x1c091c09;
GPMC_CONFIG5_1 = 0x041f1f1f;
GPMC_CONFIG6_1 = 0x000004c4;
- GPMC_CONFIG7_1 = 0x00000f40 | (APOLLON_CS1_BASE >> 24);
+
+ if (gpmc_cs_request(APOLLON_ETH_CS, SZ_16M, &base) < 0) {
+ printk(KERN_ERR "Failed to request GPMC CS for smc91x\n");
+ return;
+ }
+ apollon_smc91x_resources[0].start = base + 0x300;
+ apollon_smc91x_resources[0].end = base + 0x30f;
udelay(100);
omap_cfg_reg(W4__24XX_GPIO74);
if (omap_request_gpio(APOLLON_ETHR_GPIO_IRQ) < 0) {
printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n",
APOLLON_ETHR_GPIO_IRQ);
+ gpmc_cs_free(APOLLON_ETH_CS);
return;
}
omap_set_gpio_direction(APOLLON_ETHR_GPIO_IRQ, 1);
@@ -175,6 +236,13 @@ static struct omap_mmc_config apollon_mmc_config __initdata = {
},
};
+static struct omap_usb_config apollon_usb_config __initdata = {
+ .register_dev = 1,
+ .hmc_mode = 0x14, /* 0:dev 1:host1 2:disable */
+
+ .pins[0] = 6,
+};
+
static struct omap_lcd_config apollon_lcd_config __initdata = {
.ctrl_name = "internal",
};
@@ -182,6 +250,7 @@ static struct omap_lcd_config apollon_lcd_config __initdata = {
static struct omap_board_config_kernel apollon_config[] = {
{ OMAP_TAG_UART, &apollon_uart_config },
{ OMAP_TAG_MMC, &apollon_mmc_config },
+ { OMAP_TAG_USB, &apollon_usb_config },
{ OMAP_TAG_LCD, &apollon_lcd_config },
};
@@ -250,10 +319,22 @@ static void __init apollon_sw_init(void)
return;
}
+static void __init apollon_usb_init(void)
+{
+ /* USB device */
+ /* DEVICE_SUSPEND */
+ omap_cfg_reg(P21_242X_GPIO12);
+ omap_request_gpio(12);
+ omap_set_gpio_direction(12, 0); /* OUT */
+ omap_set_gpio_dataout(12, 0);
+}
+
static void __init omap_apollon_init(void)
{
apollon_led_init();
apollon_sw_init();
+ apollon_flash_init();
+ apollon_usb_init();
/* REVISIT: where's the correct place */
omap_cfg_reg(W19_24XX_SYS_NIRQ);
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index 452193f01531..f125f432cc3e 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -131,26 +131,6 @@ static struct platform_device h4_flash_device = {
.resource = &h4_flash_resource,
};
-static struct resource h4_smc91x_resources[] = {
- [0] = {
- .start = OMAP24XX_ETHR_START, /* Physical */
- .end = OMAP24XX_ETHR_START + 0xf,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = OMAP_GPIO_IRQ(OMAP24XX_ETHR_GPIO_IRQ),
- .end = OMAP_GPIO_IRQ(OMAP24XX_ETHR_GPIO_IRQ),
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct platform_device h4_smc91x_device = {
- .name = "smc91x",
- .id = -1,
- .num_resources = ARRAY_SIZE(h4_smc91x_resources),
- .resource = h4_smc91x_resources,
-};
-
/* Select between the IrDA and aGPS module
*/
static int h4_select_irda(struct device *dev, int state)
@@ -266,29 +246,14 @@ static struct platform_device h4_lcd_device = {
.id = -1,
};
-static struct resource h4_led_resources[] = {
- [0] = {
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct platform_device h4_led_device = {
- .name = "omap_dbg_led",
- .id = -1,
- .num_resources = ARRAY_SIZE(h4_led_resources),
- .resource = h4_led_resources,
-};
-
static struct platform_device *h4_devices[] __initdata = {
- &h4_smc91x_device,
&h4_flash_device,
&h4_irda_device,
&h4_kp_device,
&h4_lcd_device,
- &h4_led_device,
};
-static inline void __init h4_init_smc91x(void)
+static inline void __init h4_init_debug(void)
{
/* Make sure CS1 timings are correct */
GPMC_CONFIG1_1 = 0x00011200;
@@ -301,12 +266,8 @@ static inline void __init h4_init_smc91x(void)
udelay(100);
omap_cfg_reg(M15_24XX_GPIO92);
- if (omap_request_gpio(OMAP24XX_ETHR_GPIO_IRQ) < 0) {
- printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n",
- OMAP24XX_ETHR_GPIO_IRQ);
- return;
- }
- omap_set_gpio_direction(OMAP24XX_ETHR_GPIO_IRQ, 1);
+ if (debug_card_init(cs_mem_base, OMAP24XX_ETHR_GPIO_IRQ) < 0)
+ gpmc_cs_free(eth_cs);
}
static void __init omap_h4_init_irq(void)
@@ -314,7 +275,6 @@ static void __init omap_h4_init_irq(void)
omap2_init_common_hw();
omap_init_irq();
omap_gpio_init();
- h4_init_smc91x();
}
static struct omap_uart_config h4_uart_config __initdata = {
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index d9af4367f8bb..e6e85b7b097b 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -651,7 +651,7 @@ static u32 omap2_get_clksel(u32 *div_sel, u32 *field_mask,
break;
case CM_SYSCLKOUT_SEL1:
div_addr = (u32)&PRCM_CLKOUT_CTRL;
- if ((div_off == 3) || (div_off = 11))
+ if ((div_off == 3) || (div_off == 11))
mask= 0x3;
break;
case CM_CORE_SEL1:
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index 52ec2f2d6360..b603bc5f8e5b 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -55,8 +55,10 @@ static void omap_init_i2c(void)
if (machine_is_omap_h4())
return;
- omap_cfg_reg(J15_24XX_I2C2_SCL);
- omap_cfg_reg(H19_24XX_I2C2_SDA);
+ if (!cpu_is_omap2430()) {
+ omap_cfg_reg(J15_24XX_I2C2_SCL);
+ omap_cfg_reg(H19_24XX_I2C2_SDA);
+ }
(void) platform_device_register(&omap_i2c_device2);
}
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index e290b989aa94..5a4cc2076a7d 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -22,7 +22,14 @@
#undef DEBUG
+#ifdef CONFIG_ARCH_OMAP2420
#define GPMC_BASE 0x6800a000
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2430
+#define GPMC_BASE 0x6E000000
+#endif
+
#define GPMC_REVISION 0x00
#define GPMC_SYSCONFIG 0x10
#define GPMC_SYSSTATUS 0x14
@@ -88,7 +95,7 @@ u32 gpmc_cs_read_reg(int cs, int idx)
}
/* TODO: Add support for gpmc_fck to clock framework and use it */
-static unsigned long gpmc_get_fclk_period(void)
+unsigned long gpmc_get_fclk_period(void)
{
/* In picoseconds */
return 1000000000 / ((clk_get_rate(gpmc_l3_clk)) / 1000);
@@ -104,6 +111,13 @@ unsigned int gpmc_ns_to_ticks(unsigned int time_ns)
return (time_ns * 1000 + tick_ps - 1) / tick_ps;
}
+unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns)
+{
+ unsigned long ticks = gpmc_ns_to_ticks(time_ns);
+
+ return ticks * gpmc_get_fclk_period() / 1000;
+}
+
#ifdef DEBUG
static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
int time, const char *name)
@@ -120,15 +134,21 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
else
ticks = gpmc_ns_to_ticks(time);
nr_bits = end_bit - st_bit + 1;
- if (ticks >= 1 << nr_bits)
+ if (ticks >= 1 << nr_bits) {
+#ifdef DEBUG
+ printk(KERN_INFO "GPMC CS%d: %-10s* %3d ns, %3d ticks >= %d\n",
+ cs, name, time, ticks, 1 << nr_bits);
+#endif
return -1;
+ }
mask = (1 << nr_bits) - 1;
l = gpmc_cs_read_reg(cs, reg);
#ifdef DEBUG
- printk(KERN_INFO "GPMC CS%d: %-10s: %d ticks, %3lu ns (was %i ticks)\n",
+ printk(KERN_INFO
+ "GPMC CS%d: %-10s: %3d ticks, %3lu ns (was %3i ticks) %3d ns\n",
cs, name, ticks, gpmc_get_fclk_period() * ticks / 1000,
- (l >> st_bit) & mask);
+ (l >> st_bit) & mask, time);
#endif
l &= ~(mask << st_bit);
l |= ticks << st_bit;
@@ -157,7 +177,7 @@ int gpmc_cs_calc_divider(int cs, unsigned int sync_clk)
div = l / gpmc_get_fclk_period();
if (div > 4)
return -1;
- if (div < 0)
+ if (div <= 0)
div = 1;
return div;
@@ -191,14 +211,19 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
GPMC_SET_ONE(GPMC_CS_CONFIG5, 24, 27, page_burst_access);
+ /* caller is expected to have initialized CONFIG1 to cover
+ * at least sync vs async
+ */
+ l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+ if (l & (GPMC_CONFIG1_READTYPE_SYNC | GPMC_CONFIG1_WRITETYPE_SYNC)) {
#ifdef DEBUG
- printk(KERN_INFO "GPMC CS%d CLK period is %lu (div %d)\n",
- cs, gpmc_get_fclk_period(), div);
+ printk(KERN_INFO "GPMC CS%d CLK period is %lu ns (div %d)\n",
+ cs, (div * gpmc_get_fclk_period()) / 1000, div);
#endif
-
- l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
- l &= ~0x03;
- l |= (div - 1);
+ l &= ~0x03;
+ l |= (div - 1);
+ gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
+ }
return 0;
}
diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c
index 871ace4fccb8..4dfd878d7968 100644
--- a/arch/arm/mach-omap2/id.c
+++ b/arch/arm/mach-omap2/id.c
@@ -17,7 +17,13 @@
#include <asm/io.h>
+#if defined(CONFIG_ARCH_OMAP2420)
#define OMAP24XX_TAP_BASE io_p2v(0x48014000)
+#endif
+
+#if defined(CONFIG_ARCH_OMAP2430)
+#define OMAP24XX_TAP_BASE io_p2v(0x4900A000)
+#endif
#define OMAP_TAP_IDCODE 0x0204
#define OMAP_TAP_PROD_ID 0x0208
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 82dc70f6b779..5a4091f582ed 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -5,6 +5,7 @@
*
* Copyright (C) 2005 Nokia Corporation
* Author: Juha Yrjölä <juha.yrjola@nokia.com>
+ * Updated map desc to add 2430 support : <x0khasim@ti.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -26,6 +27,7 @@
extern void omap_sram_init(void);
extern int omap2_clk_init(void);
extern void omap2_check_revision(void);
+extern void omap2_init_memory(void);
extern void gpmc_init(void);
extern void omapfb_reserve_sdram(void);
@@ -40,6 +42,20 @@ static struct map_desc omap2_io_desc[] __initdata = {
.length = L3_24XX_SIZE,
.type = MT_DEVICE
},
+#ifdef CONFIG_ARCH_OMAP2430
+ {
+ .virtual = L4_WK_243X_VIRT,
+ .pfn = __phys_to_pfn(L4_WK_243X_PHYS),
+ .length = L4_WK_243X_SIZE,
+ .type = MT_DEVICE
+ },
+ {
+ .virtual = OMAP243X_GPMC_VIRT,
+ .pfn = __phys_to_pfn(OMAP243X_GPMC_PHYS),
+ .length = OMAP243X_GPMC_SIZE,
+ .type = MT_DEVICE
+ },
+#endif
{
.virtual = DSP_MEM_24XX_VIRT,
.pfn = __phys_to_pfn(DSP_MEM_24XX_PHYS),
@@ -80,5 +96,11 @@ void __init omap2_init_common_hw(void)
{
omap2_mux_init();
omap2_clk_init();
+/*
+ * Need to Fix this for 2430
+ */
+#ifndef CONFIG_ARCH_OMAP2430
+ omap2_init_memory();
+#endif
gpmc_init();
}
diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c
index a39d30680300..f064f725e724 100644
--- a/arch/arm/mach-omap2/irq.c
+++ b/arch/arm/mach-omap2/irq.c
@@ -37,7 +37,7 @@ static struct omap_irq_bank {
} __attribute__ ((aligned(4))) irq_banks[] = {
{
/* MPU INTC */
- .base_reg = OMAP24XX_IC_BASE,
+ .base_reg = IO_ADDRESS(OMAP24XX_IC_BASE),
.nr_irqs = 96,
}, {
/* XXX: DSP INTC */
@@ -47,7 +47,7 @@ static struct omap_irq_bank {
/* XXX: FIQ and additional INTC support (only MPU at the moment) */
static void omap_ack_irq(unsigned int irq)
{
- omap_writel(0x1, irq_banks[0].base_reg + INTC_CONTROL);
+ __raw_writel(0x1, irq_banks[0].base_reg + INTC_CONTROL);
}
static void omap_mask_irq(unsigned int irq)
@@ -60,7 +60,7 @@ static void omap_mask_irq(unsigned int irq)
irq %= 32;
}
- omap_writel(1 << irq, irq_banks[0].base_reg + INTC_MIR_SET0 + offset);
+ __raw_writel(1 << irq, irq_banks[0].base_reg + INTC_MIR_SET0 + offset);
}
static void omap_unmask_irq(unsigned int irq)
@@ -73,7 +73,7 @@ static void omap_unmask_irq(unsigned int irq)
irq %= 32;
}
- omap_writel(1 << irq, irq_banks[0].base_reg + INTC_MIR_CLEAR0 + offset);
+ __raw_writel(1 << irq, irq_banks[0].base_reg + INTC_MIR_CLEAR0 + offset);
}
static void omap_mask_ack_irq(unsigned int irq)
@@ -93,17 +93,20 @@ static void __init omap_irq_bank_init_one(struct omap_irq_bank *bank)
{
unsigned long tmp;
- tmp = omap_readl(bank->base_reg + INTC_REVISION) & 0xff;
+ tmp = __raw_readl(bank->base_reg + INTC_REVISION) & 0xff;
printk(KERN_INFO "IRQ: Found an INTC at 0x%08lx "
"(revision %ld.%ld) with %d interrupts\n",
bank->base_reg, tmp >> 4, tmp & 0xf, bank->nr_irqs);
- tmp = omap_readl(bank->base_reg + INTC_SYSCONFIG);
+ tmp = __raw_readl(bank->base_reg + INTC_SYSCONFIG);
tmp |= 1 << 1; /* soft reset */
- omap_writel(tmp, bank->base_reg + INTC_SYSCONFIG);
+ __raw_writel(tmp, bank->base_reg + INTC_SYSCONFIG);
- while (!(omap_readl(bank->base_reg + INTC_SYSSTATUS) & 0x1))
+ while (!(__raw_readl(bank->base_reg + INTC_SYSSTATUS) & 0x1))
/* Wait for reset to complete */;
+
+ /* Enable autoidle */
+ __raw_writel(1 << 0, bank->base_reg + INTC_SYSCONFIG);
}
void __init omap_init_irq(void)
diff --git a/arch/arm/mach-omap2/memory.c b/arch/arm/mach-omap2/memory.c
index 85cbc2a2e663..3e5d8cd4ea4f 100644
--- a/arch/arm/mach-omap2/memory.c
+++ b/arch/arm/mach-omap2/memory.c
@@ -30,6 +30,7 @@
#include "prcm-regs.h"
#include "memory.h"
+
static struct memory_timings mem_timings;
u32 omap2_memory_get_slow_dll_ctrl(void)
@@ -99,3 +100,20 @@ void omap2_init_memory_params(u32 force_lock_to_unlock_mode)
/* 90 degree phase for anything below 133Mhz + disable DLL filter */
mem_timings.slow_dll_ctrl |= ((1 << 1) | (3 << 8));
}
+
+/* turn on smart idle modes for SDRAM scheduler and controller */
+void __init omap2_init_memory(void)
+{
+ u32 l;
+
+ l = SMS_SYSCONFIG;
+ l &= ~(0x3 << 3);
+ l |= (0x2 << 3);
+ SMS_SYSCONFIG = l;
+
+ l = SDRC_SYSCONFIG;
+ l &= ~(0x3 << 3);
+ l |= (0x2 << 3);
+ SDRC_SYSCONFIG = l;
+
+}
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index 0439906d5da7..05750975d746 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -53,8 +53,8 @@ MUX_CFG_24XX("W19_24XX_SYS_NIRQ", 0x12c, 0, 1, 1, 1)
MUX_CFG_24XX("W14_24XX_SYS_CLKOUT", 0x137, 0, 1, 1, 1)
/* 24xx GPMC chipselects, wait pin monitoring */
-MUX_CFG_24XX("E2_GPMC_NCS2", 0x08e, 0, 1, 1, 1)
-MUX_CFG_24XX("L2_GPMC_NCS7", 0x093, 0, 1, 1, 1)
+MUX_CFG_24XX("E2_GPMC_NCS2", 0x08e, 0, 1, 1, 1)
+MUX_CFG_24XX("L2_GPMC_NCS7", 0x093, 0, 1, 1, 1)
MUX_CFG_24XX("L3_GPMC_WAIT0", 0x09a, 0, 1, 1, 1)
MUX_CFG_24XX("N7_GPMC_WAIT1", 0x09b, 0, 1, 1, 1)
MUX_CFG_24XX("M1_GPMC_WAIT2", 0x09c, 0, 1, 1, 1)
@@ -67,18 +67,18 @@ MUX_CFG_24XX("W15_24XX_MCBSP2_DR", 0x126, 1, 1, 0, 1)
MUX_CFG_24XX("V15_24XX_MCBSP2_DX", 0x127, 1, 1, 0, 1)
/* 24xx GPIO */
-MUX_CFG_24XX("M21_242X_GPIO11", 0x0c9, 3, 1, 1, 1)
-MUX_CFG_24XX("P21_242X_GPIO12", 0x0ca, 3, 0, 0, 1)
-MUX_CFG_24XX("AA10_242X_GPIO13", 0x0e5, 3, 0, 0, 1)
-MUX_CFG_24XX("AA6_242X_GPIO14", 0x0e6, 3, 0, 0, 1)
-MUX_CFG_24XX("AA4_242X_GPIO15", 0x0e7, 3, 0, 0, 1)
-MUX_CFG_24XX("Y11_242X_GPIO16", 0x0e8, 3, 0, 0, 1)
-MUX_CFG_24XX("AA12_242X_GPIO17", 0x0e9, 3, 0, 0, 1)
-MUX_CFG_24XX("AA8_242X_GPIO58", 0x0ea, 3, 0, 0, 1)
+MUX_CFG_24XX("M21_242X_GPIO11", 0x0c9, 3, 1, 1, 1)
+MUX_CFG_24XX("P21_242X_GPIO12", 0x0ca, 3, 0, 0, 1)
+MUX_CFG_24XX("AA10_242X_GPIO13", 0x0e5, 3, 0, 0, 1)
+MUX_CFG_24XX("AA6_242X_GPIO14", 0x0e6, 3, 0, 0, 1)
+MUX_CFG_24XX("AA4_242X_GPIO15", 0x0e7, 3, 0, 0, 1)
+MUX_CFG_24XX("Y11_242X_GPIO16", 0x0e8, 3, 0, 0, 1)
+MUX_CFG_24XX("AA12_242X_GPIO17", 0x0e9, 3, 0, 0, 1)
+MUX_CFG_24XX("AA8_242X_GPIO58", 0x0ea, 3, 0, 0, 1)
MUX_CFG_24XX("Y20_24XX_GPIO60", 0x12c, 3, 0, 0, 1)
-MUX_CFG_24XX("W4__24XX_GPIO74", 0x0f2, 3, 0, 0, 1)
+MUX_CFG_24XX("W4__24XX_GPIO74", 0x0f2, 3, 0, 0, 1)
MUX_CFG_24XX("M15_24XX_GPIO92", 0x10a, 3, 0, 0, 1)
-MUX_CFG_24XX("J15_24XX_GPIO99", 0x113, 3, 1, 1, 1)
+MUX_CFG_24XX("J15_24XX_GPIO99", 0x113, 3, 1, 1, 1)
MUX_CFG_24XX("V14_24XX_GPIO117", 0x128, 3, 1, 0, 1)
MUX_CFG_24XX("P14_24XX_GPIO125", 0x140, 3, 1, 1, 1)
@@ -95,17 +95,17 @@ MUX_CFG_24XX("T3_242X_GPIO55", 0xd9, 3, 0, 0, 1)
MUX_CFG_24XX("U2_242X_GPIO56", 0xda, 3, 0, 0, 1)
/* 24xx external DMA requests */
-MUX_CFG_24XX("AA10_242X_DMAREQ0", 0x0e5, 2, 0, 0, 1)
-MUX_CFG_24XX("AA6_242X_DMAREQ1", 0x0e6, 2, 0, 0, 1)
-MUX_CFG_24XX("E4_242X_DMAREQ2", 0x074, 2, 0, 0, 1)
-MUX_CFG_24XX("G4_242X_DMAREQ3", 0x073, 2, 0, 0, 1)
-MUX_CFG_24XX("D3_242X_DMAREQ4", 0x072, 2, 0, 0, 1)
-MUX_CFG_24XX("E3_242X_DMAREQ5", 0x071, 2, 0, 0, 1)
+MUX_CFG_24XX("AA10_242X_DMAREQ0", 0x0e5, 2, 0, 0, 1)
+MUX_CFG_24XX("AA6_242X_DMAREQ1", 0x0e6, 2, 0, 0, 1)
+MUX_CFG_24XX("E4_242X_DMAREQ2", 0x074, 2, 0, 0, 1)
+MUX_CFG_24XX("G4_242X_DMAREQ3", 0x073, 2, 0, 0, 1)
+MUX_CFG_24XX("D3_242X_DMAREQ4", 0x072, 2, 0, 0, 1)
+MUX_CFG_24XX("E3_242X_DMAREQ5", 0x071, 2, 0, 0, 1)
/* TSC IRQ */
MUX_CFG_24XX("P20_24XX_TSC_IRQ", 0x108, 0, 0, 0, 1)
-/* UART3 */
+/* UART3 */
MUX_CFG_24XX("K15_24XX_UART3_TX", 0x118, 0, 0, 0, 1)
MUX_CFG_24XX("K14_24XX_UART3_RX", 0x119, 0, 0, 0, 1)
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index 6f4a5436d0ce..baf7d82b458b 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -16,10 +16,9 @@
* published by the Free Software Foundation.
*/
-#include <linux/pm.h>
+#include <linux/suspend.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
-#include <linux/pm.h>
#include <linux/interrupt.h>
#include <linux/sysfs.h>
#include <linux/module.h>
@@ -71,28 +70,12 @@ void omap2_pm_idle(void)
local_irq_enable();
}
-static int omap2_pm_prepare(suspend_state_t state)
+static int omap2_pm_prepare(void)
{
- int error = 0;
-
/* We cannot sleep in idle until we have resumed */
saved_idle = pm_idle;
pm_idle = NULL;
-
- switch (state)
- {
- case PM_SUSPEND_STANDBY:
- case PM_SUSPEND_MEM:
- break;
-
- case PM_SUSPEND_DISK:
- return -ENOTSUPP;
-
- default:
- return -EINVAL;
- }
-
- return error;
+ return 0;
}
#define INT0_WAKE_MASK (OMAP_IRQ_BIT(INT_24XX_GPIO_BANK1) | \
@@ -353,9 +336,6 @@ static int omap2_pm_enter(suspend_state_t state)
case PM_SUSPEND_MEM:
ret = omap2_pm_suspend();
break;
- case PM_SUSPEND_DISK:
- ret = -ENOTSUPP;
- break;
default:
ret = -EINVAL;
}
@@ -363,17 +343,16 @@ static int omap2_pm_enter(suspend_state_t state)
return ret;
}
-static int omap2_pm_finish(suspend_state_t state)
+static void omap2_pm_finish(void)
{
pm_idle = saved_idle;
- return 0;
}
-static struct pm_ops omap_pm_ops = {
+static struct platform_suspend_ops omap_pm_ops = {
.prepare = omap2_pm_prepare,
.enter = omap2_pm_enter,
.finish = omap2_pm_finish,
- .valid = pm_valid_only_mem,
+ .valid = suspend_valid_only_mem,
};
int __init omap2_pm_init(void)
@@ -397,7 +376,7 @@ int __init omap2_pm_init(void)
omap2_sram_suspend = omap_sram_push(omap24xx_cpu_suspend,
omap24xx_cpu_suspend_sz);
- pm_set_ops(&omap_pm_ops);
+ suspend_set_ops(&omap_pm_ops);
pm_idle = omap2_pm_idle;
pmdomain_init();
diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c
index 62e801ef9ad9..8d322c20ccae 100644
--- a/arch/arm/mach-omap2/timer-gp.c
+++ b/arch/arm/mach-omap2/timer-gp.c
@@ -5,7 +5,7 @@
*
* Copyright (C) 2005 Nokia Corporation
* Author: Paul Mundt <paul.mundt@nokia.com>
- * Juha Yrjölä <juha.yrjola@nokia.com>
+ * Juha Yrjölä <juha.yrjola@nokia.com>
* OMAP Dual-mode timer framework support by Timo Teras
*
* Some parts based off of TI's 24xx code:
diff --git a/arch/arm/mach-omap2/usb-tusb6010.c b/arch/arm/mach-omap2/usb-tusb6010.c
new file mode 100644
index 000000000000..80bb42eb5082
--- /dev/null
+++ b/arch/arm/mach-omap2/usb-tusb6010.c
@@ -0,0 +1,349 @@
+/*
+ * linux/arch/arm/mach-omap2/usb-tusb6010.c
+ *
+ * Copyright (C) 2006 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+
+#include <linux/usb/musb.h>
+
+#include <asm/arch/gpmc.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+
+
+static u8 async_cs, sync_cs;
+static unsigned refclk_psec;
+
+
+/* t2_ps, when quantized to fclk units, must happen no earlier than
+ * the clock after after t1_NS.
+ *
+ * Return a possibly updated value of t2_ps, converted to nsec.
+ */
+static unsigned
+next_clk(unsigned t1_NS, unsigned t2_ps, unsigned fclk_ps)
+{
+ unsigned t1_ps = t1_NS * 1000;
+ unsigned t1_f, t2_f;
+
+ if ((t1_ps + fclk_ps) < t2_ps)
+ return t2_ps / 1000;
+
+ t1_f = (t1_ps + fclk_ps - 1) / fclk_ps;
+ t2_f = (t2_ps + fclk_ps - 1) / fclk_ps;
+
+ if (t1_f >= t2_f)
+ t2_f = t1_f + 1;
+
+ return (t2_f * fclk_ps) / 1000;
+}
+
+/* NOTE: timings are from tusb 6010 datasheet Rev 1.8, 12-Sept 2006 */
+
+static int tusb_set_async_mode(unsigned sysclk_ps, unsigned fclk_ps)
+{
+ struct gpmc_timings t;
+ unsigned t_acsnh_advnh = sysclk_ps + 3000;
+ unsigned tmp;
+
+ memset(&t, 0, sizeof(t));
+
+ /* CS_ON = t_acsnh_acsnl */
+ t.cs_on = 8;
+ /* ADV_ON = t_acsnh_advnh - t_advn */
+ t.adv_on = next_clk(t.cs_on, t_acsnh_advnh - 7000, fclk_ps);
+
+ /*
+ * READ ... from omap2420 TRM fig 12-13
+ */
+
+ /* ADV_RD_OFF = t_acsnh_advnh */
+ t.adv_rd_off = next_clk(t.adv_on, t_acsnh_advnh, fclk_ps);
+
+ /* OE_ON = t_acsnh_advnh + t_advn_oen (then wait for nRDY) */
+ t.oe_on = next_clk(t.adv_on, t_acsnh_advnh + 1000, fclk_ps);
+
+ /* ACCESS = counters continue only after nRDY */
+ tmp = t.oe_on * 1000 + 300;
+ t.access = next_clk(t.oe_on, tmp, fclk_ps);
+
+ /* OE_OFF = after data gets sampled */
+ tmp = t.access * 1000;
+ t.oe_off = next_clk(t.access, tmp, fclk_ps);
+
+ t.cs_rd_off = t.oe_off;
+
+ tmp = t.cs_rd_off * 1000 + 7000 /* t_acsn_rdy_z */;
+ t.rd_cycle = next_clk(t.cs_rd_off, tmp, fclk_ps);
+
+ /*
+ * WRITE ... from omap2420 TRM fig 12-15
+ */
+
+ /* ADV_WR_OFF = t_acsnh_advnh */
+ t.adv_wr_off = t.adv_rd_off;
+
+ /* WE_ON = t_acsnh_advnh + t_advn_wen (then wait for nRDY) */
+ t.we_on = next_clk(t.adv_wr_off, t_acsnh_advnh + 1000, fclk_ps);
+
+ /* WE_OFF = after data gets sampled */
+ tmp = t.we_on * 1000 + 300;
+ t.we_off = next_clk(t.we_on, tmp, fclk_ps);
+
+ t.cs_wr_off = t.we_off;
+
+ tmp = t.cs_wr_off * 1000 + 7000 /* t_acsn_rdy_z */;
+ t.wr_cycle = next_clk(t.cs_wr_off, tmp, fclk_ps);
+
+ return gpmc_cs_set_timings(async_cs, &t);
+}
+
+static int tusb_set_sync_mode(unsigned sysclk_ps, unsigned fclk_ps)
+{
+ struct gpmc_timings t;
+ unsigned t_scsnh_advnh = sysclk_ps + 3000;
+ unsigned tmp;
+
+ memset(&t, 0, sizeof(t));
+ t.cs_on = 8;
+
+ /* ADV_ON = t_acsnh_advnh - t_advn */
+ t.adv_on = next_clk(t.cs_on, t_scsnh_advnh - 7000, fclk_ps);
+
+ /* GPMC_CLK rate = fclk rate / div */
+ t.sync_clk = 12 /* 11.1 nsec */;
+ tmp = (t.sync_clk * 1000 + fclk_ps - 1) / fclk_ps;
+ if (tmp > 4)
+ return -ERANGE;
+ if (tmp <= 0)
+ tmp = 1;
+ t.page_burst_access = (fclk_ps * tmp) / 1000;
+
+ /*
+ * READ ... based on omap2420 TRM fig 12-19, 12-20
+ */
+
+ /* ADV_RD_OFF = t_scsnh_advnh */
+ t.adv_rd_off = next_clk(t.adv_on, t_scsnh_advnh, fclk_ps);
+
+ /* OE_ON = t_scsnh_advnh + t_advn_oen * fclk_ps (then wait for nRDY) */
+ tmp = (t.adv_rd_off * 1000) + (3 * fclk_ps);
+ t.oe_on = next_clk(t.adv_on, tmp, fclk_ps);
+
+ /* ACCESS = number of clock cycles after t_adv_eon */
+ tmp = (t.oe_on * 1000) + (5 * fclk_ps);
+ t.access = next_clk(t.oe_on, tmp, fclk_ps);
+
+ /* OE_OFF = after data gets sampled */
+ tmp = (t.access * 1000) + (1 * fclk_ps);
+ t.oe_off = next_clk(t.access, tmp, fclk_ps);
+
+ t.cs_rd_off = t.oe_off;
+
+ tmp = t.cs_rd_off * 1000 + 7000 /* t_scsn_rdy_z */;
+ t.rd_cycle = next_clk(t.cs_rd_off, tmp, fclk_ps);
+
+ /*
+ * WRITE ... based on omap2420 TRM fig 12-21
+ */
+
+ /* ADV_WR_OFF = t_scsnh_advnh */
+ t.adv_wr_off = t.adv_rd_off;
+
+ /* WE_ON = t_scsnh_advnh + t_advn_wen * fclk_ps (then wait for nRDY) */
+ tmp = (t.adv_wr_off * 1000) + (3 * fclk_ps);
+ t.we_on = next_clk(t.adv_wr_off, tmp, fclk_ps);
+
+ /* WE_OFF = number of clock cycles after t_adv_wen */
+ tmp = (t.we_on * 1000) + (6 * fclk_ps);
+ t.we_off = next_clk(t.we_on, tmp, fclk_ps);
+
+ t.cs_wr_off = t.we_off;
+
+ tmp = t.cs_wr_off * 1000 + 7000 /* t_scsn_rdy_z */;
+ t.wr_cycle = next_clk(t.cs_wr_off, tmp, fclk_ps);
+
+ return gpmc_cs_set_timings(sync_cs, &t);
+}
+
+extern unsigned long gpmc_get_fclk_period(void);
+
+/* tusb driver calls this when it changes the chip's clocking */
+int tusb6010_platform_retime(unsigned is_refclk)
+{
+ static const char error[] =
+ KERN_ERR "tusb6010 %s retime error %d\n";
+
+ unsigned fclk_ps = gpmc_get_fclk_period();
+ unsigned sysclk_ps;
+ int status;
+
+ if (!refclk_psec)
+ return -ENODEV;
+
+ sysclk_ps = is_refclk ? refclk_psec : TUSB6010_OSCCLK_60;
+
+ status = tusb_set_async_mode(sysclk_ps, fclk_ps);
+ if (status < 0) {
+ printk(error, "async", status);
+ goto done;
+ }
+ status = tusb_set_sync_mode(sysclk_ps, fclk_ps);
+ if (status < 0)
+ printk(error, "sync", status);
+done:
+ return status;
+}
+EXPORT_SYMBOL_GPL(tusb6010_platform_retime);
+
+static struct resource tusb_resources[] = {
+ /* Order is significant! The start/end fields
+ * are updated during setup..
+ */
+ { /* Asynchronous access */
+ .flags = IORESOURCE_MEM,
+ },
+ { /* Synchronous access */
+ .flags = IORESOURCE_MEM,
+ },
+ { /* IRQ */
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 tusb_dmamask = ~(u32)0;
+
+static struct platform_device tusb_device = {
+ .name = "musb_hdrc",
+ .id = -1,
+ .dev = {
+ .dma_mask = &tusb_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .num_resources = ARRAY_SIZE(tusb_resources),
+ .resource = tusb_resources,
+};
+
+
+/* this may be called only from board-*.c setup code */
+int __init
+tusb6010_setup_interface(struct musb_hdrc_platform_data *data,
+ unsigned ps_refclk, unsigned waitpin,
+ unsigned async, unsigned sync,
+ unsigned irq, unsigned dmachan)
+{
+ int status;
+ static char error[] __initdata =
+ KERN_ERR "tusb6010 init error %d, %d\n";
+
+ /* ASYNC region, primarily for PIO */
+ status = gpmc_cs_request(async, SZ_16M, (unsigned long *)
+ &tusb_resources[0].start);
+ if (status < 0) {
+ printk(error, 1, status);
+ return status;
+ }
+ tusb_resources[0].end = tusb_resources[0].start + 0x9ff;
+ async_cs = async;
+ gpmc_cs_write_reg(async, GPMC_CS_CONFIG1,
+ GPMC_CONFIG1_PAGE_LEN(2)
+ | GPMC_CONFIG1_WAIT_READ_MON
+ | GPMC_CONFIG1_WAIT_WRITE_MON
+ | GPMC_CONFIG1_WAIT_PIN_SEL(waitpin)
+ | GPMC_CONFIG1_READTYPE_ASYNC
+ | GPMC_CONFIG1_WRITETYPE_ASYNC
+ | GPMC_CONFIG1_DEVICESIZE_16
+ | GPMC_CONFIG1_DEVICETYPE_NOR
+ | GPMC_CONFIG1_MUXADDDATA);
+
+
+ /* SYNC region, primarily for DMA */
+ status = gpmc_cs_request(sync, SZ_16M, (unsigned long *)
+ &tusb_resources[1].start);
+ if (status < 0) {
+ printk(error, 2, status);
+ return status;
+ }
+ tusb_resources[1].end = tusb_resources[1].start + 0x9ff;
+ sync_cs = sync;
+ gpmc_cs_write_reg(sync, GPMC_CS_CONFIG1,
+ GPMC_CONFIG1_READMULTIPLE_SUPP
+ | GPMC_CONFIG1_READTYPE_SYNC
+ | GPMC_CONFIG1_WRITEMULTIPLE_SUPP
+ | GPMC_CONFIG1_WRITETYPE_SYNC
+ | GPMC_CONFIG1_CLKACTIVATIONTIME(1)
+ | GPMC_CONFIG1_PAGE_LEN(2)
+ | GPMC_CONFIG1_WAIT_READ_MON
+ | GPMC_CONFIG1_WAIT_WRITE_MON
+ | GPMC_CONFIG1_WAIT_PIN_SEL(waitpin)
+ | GPMC_CONFIG1_DEVICESIZE_16
+ | GPMC_CONFIG1_DEVICETYPE_NOR
+ | GPMC_CONFIG1_MUXADDDATA
+ /* fclk divider gets set later */
+ );
+
+ /* IRQ */
+ status = omap_request_gpio(irq);
+ if (status < 0) {
+ printk(error, 3, status);
+ return status;
+ }
+ omap_set_gpio_direction(irq, 1);
+ tusb_resources[2].start = irq + IH_GPIO_BASE;
+
+ /* set up memory timings ... can speed them up later */
+ if (!ps_refclk) {
+ printk(error, 4, status);
+ return -ENODEV;
+ }
+ refclk_psec = ps_refclk;
+ status = tusb6010_platform_retime(1);
+ if (status < 0) {
+ printk(error, 5, status);
+ return status;
+ }
+
+ /* finish device setup ... */
+ if (!data) {
+ printk(error, 6, status);
+ return -ENODEV;
+ }
+ data->multipoint = 1;
+ tusb_device.dev.platform_data = data;
+
+ /* REVISIT let the driver know what DMA channels work */
+ if (!dmachan)
+ tusb_device.dev.dma_mask = NULL;
+ else {
+ /* assume OMAP 2420 ES2.0 and later */
+ if (dmachan & (1 << 0))
+ omap_cfg_reg(AA10_242X_DMAREQ0);
+ if (dmachan & (1 << 1))
+ omap_cfg_reg(AA6_242X_DMAREQ1);
+ if (dmachan & (1 << 2))
+ omap_cfg_reg(E4_242X_DMAREQ2);
+ if (dmachan & (1 << 3))
+ omap_cfg_reg(G4_242X_DMAREQ3);
+ if (dmachan & (1 << 4))
+ omap_cfg_reg(D3_242X_DMAREQ4);
+ if (dmachan & (1 << 5))
+ omap_cfg_reg(E3_242X_DMAREQ5);
+ }
+
+ /* so far so good ... register the device */
+ status = platform_device_register(&tusb_device);
+ if (status < 0) {
+ printk(error, 7, status);
+ return status;
+ }
+ return 0;
+}
diff --git a/arch/arm/mach-pnx4008/pm.c b/arch/arm/mach-pnx4008/pm.c
index 2a137f33f752..40116d254349 100644
--- a/arch/arm/mach-pnx4008/pm.c
+++ b/arch/arm/mach-pnx4008/pm.c
@@ -15,7 +15,7 @@
#include <linux/rtc.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
-#include <linux/pm.h>
+#include <linux/suspend.h>
#include <linux/delay.h>
#include <linux/clk.h>
@@ -117,7 +117,7 @@ static int pnx4008_pm_valid(suspend_state_t state)
(state == PM_SUSPEND_MEM);
}
-static struct pm_ops pnx4008_pm_ops = {
+static struct platform_suspend_ops pnx4008_pm_ops = {
.enter = pnx4008_pm_enter,
.valid = pnx4008_pm_valid,
};
@@ -146,7 +146,7 @@ static int __init pnx4008_pm_init(void)
return -ENOMEM;
}
- pm_set_ops(&pnx4008_pm_ops);
+ suspend_set_ops(&pnx4008_pm_ops);
return 0;
}
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 5ebec6d88b51..656d49661a29 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -1,6 +1,24 @@
if ARCH_PXA
-menu "Intel PXA2xx Implementations"
+menu "Intel PXA2xx/PXA3xx Implementations"
+
+if PXA3xx
+
+menu "Supported PXA3xx Processor Variants"
+
+config CPU_PXA300
+ bool "PXA300 (codename Monahans-L)"
+
+config CPU_PXA310
+ bool "PXA310 (codename Monahans-LV)"
+ select CPU_PXA300
+
+config CPU_PXA320
+ bool "PXA320 (codename Monahans-P)"
+
+endmenu
+
+endif
choice
prompt "Select target board"
@@ -41,6 +59,15 @@ config MACH_EM_X270
bool "CompuLab EM-x270 platform"
select PXA27x
+config MACH_ZYLONITE
+ bool "PXA3xx Development Platform"
+ select PXA3xx
+
+config MACH_ARMCORE
+ bool "CompuLab CM-X270 modules"
+ select PXA27x
+ select IWMMXT
+
endchoice
if PXA_SHARPSL
@@ -130,6 +157,11 @@ config PXA27x
help
Select code specific to PXA27x variants
+config PXA3xx
+ bool
+ help
+ Select code specific to PXA3xx variants
+
config PXA_SHARP_C7xx
bool
select PXA_SSP
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 7d6ab5c59ab9..4263527e5123 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -3,36 +3,51 @@
#
# Common support (must be linked before board specific support)
-obj-y += clock.o generic.o irq.o dma.o time.o
-obj-$(CONFIG_PXA25x) += pxa25x.o
-obj-$(CONFIG_PXA27x) += pxa27x.o
+obj-y += clock.o generic.o irq.o dma.o time.o
+obj-$(CONFIG_PXA25x) += pxa25x.o
+obj-$(CONFIG_PXA27x) += pxa27x.o
+obj-$(CONFIG_PXA3xx) += pxa3xx.o mfp.o
+obj-$(CONFIG_CPU_PXA300) += pxa300.o
+obj-$(CONFIG_CPU_PXA320) += pxa320.o
# Specific board support
-obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o
+obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o
obj-$(CONFIG_MACH_LOGICPD_PXA270) += lpd270.o
-obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o
-obj-$(CONFIG_ARCH_PXA_IDP) += idp.o
+obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o
+obj-$(CONFIG_ARCH_PXA_IDP) += idp.o
obj-$(CONFIG_MACH_TRIZEPS4) += trizeps4.o
obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o corgi_pm.o
obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o spitz_pm.o
obj-$(CONFIG_MACH_AKITA) += akita-ioexp.o
obj-$(CONFIG_MACH_POODLE) += poodle.o corgi_ssp.o
-obj-$(CONFIG_MACH_TOSA) += tosa.o
-obj-$(CONFIG_MACH_EM_X270) += em-x270.o
+obj-$(CONFIG_MACH_TOSA) += tosa.o
+obj-$(CONFIG_MACH_EM_X270) += em-x270.o
+
+ifeq ($(CONFIG_MACH_ZYLONITE),y)
+ obj-y += zylonite.o
+ obj-$(CONFIG_CPU_PXA300) += zylonite_pxa300.o
+ obj-$(CONFIG_CPU_PXA320) += zylonite_pxa320.o
+endif
+
+obj-$(CONFIG_MACH_ARMCORE) += cm-x270.o
# Support for blinky lights
led-y := leds.o
-led-$(CONFIG_ARCH_LUBBOCK) += leds-lubbock.o
-led-$(CONFIG_MACH_MAINSTONE) += leds-mainstone.o
-led-$(CONFIG_ARCH_PXA_IDP) += leds-idp.o
-led-$(CONFIG_MACH_TRIZEPS4) += leds-trizeps4.o
+led-$(CONFIG_ARCH_LUBBOCK) += leds-lubbock.o
+led-$(CONFIG_MACH_MAINSTONE) += leds-mainstone.o
+led-$(CONFIG_ARCH_PXA_IDP) += leds-idp.o
+led-$(CONFIG_MACH_TRIZEPS4) += leds-trizeps4.o
-obj-$(CONFIG_LEDS) += $(led-y)
+obj-$(CONFIG_LEDS) += $(led-y)
# Misc features
-obj-$(CONFIG_PM) += pm.o sleep.o
-obj-$(CONFIG_PXA_SSP) += ssp.o
+obj-$(CONFIG_PM) += pm.o sleep.o
+obj-$(CONFIG_PXA_SSP) += ssp.o
ifeq ($(CONFIG_PXA27x),y)
-obj-$(CONFIG_PM) += standby.o
+obj-$(CONFIG_PM) += standby.o
+endif
+
+ifeq ($(CONFIG_PCI),y)
+obj-$(CONFIG_MACH_ARMCORE) += cm-x270-pci.o
endif
diff --git a/arch/arm/mach-pxa/clock.c b/arch/arm/mach-pxa/clock.c
index 34a31caa6f9d..83ef5ecaf432 100644
--- a/arch/arm/mach-pxa/clock.c
+++ b/arch/arm/mach-pxa/clock.c
@@ -9,19 +9,15 @@
#include <linux/string.h>
#include <linux/clk.h>
#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
#include <asm/arch/pxa-regs.h>
#include <asm/hardware.h>
-struct clk {
- struct list_head node;
- unsigned long rate;
- struct module *owner;
- const char *name;
- unsigned int enabled;
- void (*enable)(void);
- void (*disable)(void);
-};
+#include "devices.h"
+#include "generic.h"
+#include "clock.h"
static LIST_HEAD(clocks);
static DEFINE_MUTEX(clocks_mutex);
@@ -33,7 +29,8 @@ struct clk *clk_get(struct device *dev, const char *id)
mutex_lock(&clocks_mutex);
list_for_each_entry(p, &clocks, node) {
- if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
+ if (strcmp(id, p->name) == 0 &&
+ (p->dev == NULL || p->dev == dev)) {
clk = p;
break;
}
@@ -46,7 +43,6 @@ EXPORT_SYMBOL(clk_get);
void clk_put(struct clk *clk)
{
- module_put(clk->owner);
}
EXPORT_SYMBOL(clk_put);
@@ -56,8 +52,12 @@ int clk_enable(struct clk *clk)
spin_lock_irqsave(&clocks_lock, flags);
if (clk->enabled++ == 0)
- clk->enable();
+ clk->ops->enable(clk);
spin_unlock_irqrestore(&clocks_lock, flags);
+
+ if (clk->delay)
+ udelay(clk->delay);
+
return 0;
}
EXPORT_SYMBOL(clk_enable);
@@ -70,54 +70,75 @@ void clk_disable(struct clk *clk)
spin_lock_irqsave(&clocks_lock, flags);
if (--clk->enabled == 0)
- clk->disable();
+ clk->ops->disable(clk);
spin_unlock_irqrestore(&clocks_lock, flags);
}
EXPORT_SYMBOL(clk_disable);
unsigned long clk_get_rate(struct clk *clk)
{
- return clk->rate;
+ unsigned long rate;
+
+ rate = clk->rate;
+ if (clk->ops->getrate)
+ rate = clk->ops->getrate(clk);
+
+ return rate;
}
EXPORT_SYMBOL(clk_get_rate);
-static void clk_gpio27_enable(void)
+static void clk_gpio27_enable(struct clk *clk)
{
pxa_gpio_mode(GPIO11_3_6MHz_MD);
}
-static void clk_gpio27_disable(void)
+static void clk_gpio27_disable(struct clk *clk)
{
}
-static struct clk clk_gpio27 = {
- .name = "GPIO27_CLK",
- .rate = 3686400,
+static const struct clkops clk_gpio27_ops = {
.enable = clk_gpio27_enable,
.disable = clk_gpio27_disable,
};
-int clk_register(struct clk *clk)
+
+void clk_cken_enable(struct clk *clk)
{
- mutex_lock(&clocks_mutex);
- list_add(&clk->node, &clocks);
- mutex_unlock(&clocks_mutex);
- return 0;
+ CKEN |= 1 << clk->cken;
}
-EXPORT_SYMBOL(clk_register);
-void clk_unregister(struct clk *clk)
+void clk_cken_disable(struct clk *clk)
{
+ CKEN &= ~(1 << clk->cken);
+}
+
+const struct clkops clk_cken_ops = {
+ .enable = clk_cken_enable,
+ .disable = clk_cken_disable,
+};
+
+static struct clk common_clks[] = {
+ {
+ .name = "GPIO27_CLK",
+ .ops = &clk_gpio27_ops,
+ .rate = 3686400,
+ },
+};
+
+void clks_register(struct clk *clks, size_t num)
+{
+ int i;
+
mutex_lock(&clocks_mutex);
- list_del(&clk->node);
+ for (i = 0; i < num; i++)
+ list_add(&clks[i].node, &clocks);
mutex_unlock(&clocks_mutex);
}
-EXPORT_SYMBOL(clk_unregister);
static int __init clk_init(void)
{
- clk_register(&clk_gpio27);
+ clks_register(common_clks, ARRAY_SIZE(common_clks));
return 0;
}
arch_initcall(clk_init);
diff --git a/arch/arm/mach-pxa/clock.h b/arch/arm/mach-pxa/clock.h
new file mode 100644
index 000000000000..bc6b77e1592e
--- /dev/null
+++ b/arch/arm/mach-pxa/clock.h
@@ -0,0 +1,43 @@
+struct clk;
+
+struct clkops {
+ void (*enable)(struct clk *);
+ void (*disable)(struct clk *);
+ unsigned long (*getrate)(struct clk *);
+};
+
+struct clk {
+ struct list_head node;
+ const char *name;
+ struct device *dev;
+ const struct clkops *ops;
+ unsigned long rate;
+ unsigned int cken;
+ unsigned int delay;
+ unsigned int enabled;
+};
+
+#define INIT_CKEN(_name, _cken, _rate, _delay, _dev) \
+ { \
+ .name = _name, \
+ .dev = _dev, \
+ .ops = &clk_cken_ops, \
+ .rate = _rate, \
+ .cken = CKEN_##_cken, \
+ .delay = _delay, \
+ }
+
+#define INIT_CK(_name, _cken, _ops, _dev) \
+ { \
+ .name = _name, \
+ .dev = _dev, \
+ .ops = _ops, \
+ .cken = CKEN_##_cken, \
+ }
+
+extern const struct clkops clk_cken_ops;
+
+void clk_cken_enable(struct clk *clk);
+void clk_cken_disable(struct clk *clk);
+
+void clks_register(struct clk *clks, size_t num);
diff --git a/arch/arm/mach-pxa/cm-x270-pci.c b/arch/arm/mach-pxa/cm-x270-pci.c
new file mode 100644
index 000000000000..878d3b9b8633
--- /dev/null
+++ b/arch/arm/mach-pxa/cm-x270-pci.c
@@ -0,0 +1,218 @@
+/*
+ * linux/arch/arm/mach-pxa/cm-x270-pci.c
+ *
+ * PCI bios-type initialisation for PCI machines
+ *
+ * Bits taken from various places.
+ *
+ * Copyright (C) 2007 Compulab, Ltd.
+ * Mike Rapoport <mike@compulab.co.il>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+
+#include <asm/mach/pci.h>
+#include <asm/arch/cm-x270.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/mach-types.h>
+
+#include <asm/hardware/it8152.h>
+
+unsigned long it8152_base_address = CMX270_IT8152_VIRT;
+
+/*
+ * Only first 64MB of memory can be accessed via PCI.
+ * We use GFP_DMA to allocate safe buffers to do map/unmap.
+ * This is really ugly and we need a better way of specifying
+ * DMA-capable regions of memory.
+ */
+void __init cmx270_pci_adjust_zones(int node, unsigned long *zone_size,
+ unsigned long *zhole_size)
+{
+ unsigned int sz = SZ_64M >> PAGE_SHIFT;
+
+ printk(KERN_INFO "Adjusting zones for CM-x270\n");
+
+ /*
+ * Only adjust if > 64M on current system
+ */
+ if (node || (zone_size[0] <= sz))
+ return;
+
+ zone_size[1] = zone_size[0] - sz;
+ zone_size[0] = sz;
+ zhole_size[1] = zhole_size[0];
+ zhole_size[0] = 0;
+}
+
+static void cmx270_it8152_irq_demux(unsigned int irq, struct irq_desc *desc)
+{
+ /* clear our parent irq */
+ GEDR(GPIO_IT8152_IRQ) = GPIO_bit(GPIO_IT8152_IRQ);
+
+ it8152_irq_demux(irq, desc);
+}
+
+void __cmx270_pci_init_irq(void)
+{
+ it8152_init_irq();
+ pxa_gpio_mode(IRQ_TO_GPIO(GPIO_IT8152_IRQ));
+ set_irq_type(IRQ_GPIO(GPIO_IT8152_IRQ), IRQT_RISING);
+
+ set_irq_chained_handler(IRQ_GPIO(GPIO_IT8152_IRQ),
+ cmx270_it8152_irq_demux);
+}
+
+#ifdef CONFIG_PM
+static unsigned long sleep_save_ite[10];
+
+void __cmx270_pci_suspend(void)
+{
+ /* save ITE state */
+ sleep_save_ite[0] = __raw_readl(IT8152_INTC_PDCNIMR);
+ sleep_save_ite[1] = __raw_readl(IT8152_INTC_LPCNIMR);
+ sleep_save_ite[2] = __raw_readl(IT8152_INTC_LPNIAR);
+
+ /* Clear ITE IRQ's */
+ __raw_writel((0), IT8152_INTC_PDCNIRR);
+ __raw_writel((0), IT8152_INTC_LPCNIRR);
+}
+
+void __cmx270_pci_resume(void)
+{
+ /* restore IT8152 state */
+ __raw_writel((sleep_save_ite[0]), IT8152_INTC_PDCNIMR);
+ __raw_writel((sleep_save_ite[1]), IT8152_INTC_LPCNIMR);
+ __raw_writel((sleep_save_ite[2]), IT8152_INTC_LPNIAR);
+}
+#else
+void cmx270_pci_suspend(void) {}
+void cmx270_pci_resume(void) {}
+#endif
+
+/* PCI IRQ mapping*/
+static int __init cmx270_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ int irq;
+
+ printk(KERN_DEBUG "===> %s: %s slot=%x, pin=%x\n", __FUNCTION__,
+ pci_name(dev), slot, pin);
+
+ irq = it8152_pci_map_irq(dev, slot, pin);
+ if (irq)
+ return irq;
+
+ /*
+ Here comes the ugly part. The routing is baseboard specific,
+ but defining a platform for each possible base of CM-x270 is
+ unrealistic. Here we keep mapping for ATXBase and SB-x270.
+ */
+ /* ATXBASE PCI slot */
+ if (slot == 7)
+ return IT8152_PCI_INTA;
+
+ /* ATXBase/SB-x270 CardBus */
+ if (slot == 8 || slot == 0)
+ return IT8152_PCI_INTB;
+
+ /* ATXBase Ethernet */
+ if (slot == 9)
+ return IT8152_PCI_INTA;
+
+ /* SB-x270 Ethernet */
+ if (slot == 16)
+ return IT8152_PCI_INTA;
+
+ /* PC104+ interrupt routing */
+ if ((slot == 17) || (slot == 19))
+ return IT8152_PCI_INTA;
+ if ((slot == 18) || (slot == 20))
+ return IT8152_PCI_INTB;
+
+ return(0);
+}
+
+static struct pci_bus * __init
+cmx270_pci_scan_bus(int nr, struct pci_sys_data *sys)
+{
+ printk(KERN_INFO "Initializing CM-X270 PCI subsystem\n");
+
+ __raw_writel(0x800, IT8152_PCI_CFG_ADDR);
+ if (__raw_readl(IT8152_PCI_CFG_DATA) == 0x81521283) {
+ printk(KERN_INFO "PCI Bridge found.\n");
+
+ /* set PCI I/O base at 0 */
+ writel(0x848, IT8152_PCI_CFG_ADDR);
+ writel(0, IT8152_PCI_CFG_DATA);
+
+ /* set PCI memory base at 0 */
+ writel(0x840, IT8152_PCI_CFG_ADDR);
+ writel(0, IT8152_PCI_CFG_DATA);
+
+ writel(0x20, IT8152_GPIO_GPDR);
+
+ /* CardBus Controller on ATXbase baseboard */
+ writel(0x4000, IT8152_PCI_CFG_ADDR);
+ if (readl(IT8152_PCI_CFG_DATA) == 0xAC51104C) {
+ printk(KERN_INFO "CardBus Bridge found.\n");
+
+ /* Configure socket 0 */
+ writel(0x408C, IT8152_PCI_CFG_ADDR);
+ writel(0x1022, IT8152_PCI_CFG_DATA);
+
+ writel(0x4080, IT8152_PCI_CFG_ADDR);
+ writel(0x3844d060, IT8152_PCI_CFG_DATA);
+
+ writel(0x4090, IT8152_PCI_CFG_ADDR);
+ writel(((readl(IT8152_PCI_CFG_DATA) & 0xffff) |
+ 0x60440000),
+ IT8152_PCI_CFG_DATA);
+
+ writel(0x4018, IT8152_PCI_CFG_ADDR);
+ writel(0xb0000000, IT8152_PCI_CFG_DATA);
+
+ /* Configure socket 1 */
+ writel(0x418C, IT8152_PCI_CFG_ADDR);
+ writel(0x1022, IT8152_PCI_CFG_DATA);
+
+ writel(0x4180, IT8152_PCI_CFG_ADDR);
+ writel(0x3844d060, IT8152_PCI_CFG_DATA);
+
+ writel(0x4190, IT8152_PCI_CFG_ADDR);
+ writel(((readl(IT8152_PCI_CFG_DATA) & 0xffff) |
+ 0x60440000),
+ IT8152_PCI_CFG_DATA);
+
+ writel(0x4118, IT8152_PCI_CFG_ADDR);
+ writel(0xb0000000, IT8152_PCI_CFG_DATA);
+ }
+ }
+ return it8152_pci_scan_bus(nr, sys);
+}
+
+static struct hw_pci cmx270_pci __initdata = {
+ .swizzle = pci_std_swizzle,
+ .map_irq = cmx270_pci_map_irq,
+ .nr_controllers = 1,
+ .setup = it8152_pci_setup,
+ .scan = cmx270_pci_scan_bus,
+};
+
+static int __init cmx270_init_pci(void)
+{
+ if (machine_is_armcore())
+ pci_common_init(&cmx270_pci);
+
+ return 0;
+}
+
+subsys_initcall(cmx270_init_pci);
diff --git a/arch/arm/mach-pxa/cm-x270-pci.h b/arch/arm/mach-pxa/cm-x270-pci.h
new file mode 100644
index 000000000000..ffe37b66f9a0
--- /dev/null
+++ b/arch/arm/mach-pxa/cm-x270-pci.h
@@ -0,0 +1,13 @@
+extern void __cmx270_pci_init_irq(void);
+extern void __cmx270_pci_suspend(void);
+extern void __cmx270_pci_resume(void);
+
+#ifdef CONFIG_PCI
+#define cmx270_pci_init_irq __cmx270_pci_init_irq
+#define cmx270_pci_suspend __cmx270_pci_suspend
+#define cmx270_pci_resume __cmx270_pci_resume
+#else
+#define cmx270_pci_init_irq() do {} while (0)
+#define cmx270_pci_suspend() do {} while (0)
+#define cmx270_pci_resume() do {} while (0)
+#endif
diff --git a/arch/arm/mach-pxa/cm-x270.c b/arch/arm/mach-pxa/cm-x270.c
new file mode 100644
index 000000000000..177664ccb2e2
--- /dev/null
+++ b/arch/arm/mach-pxa/cm-x270.c
@@ -0,0 +1,645 @@
+/*
+ * linux/arch/arm/mach-pxa/cm-x270.c
+ *
+ * Copyright (C) 2007 CompuLab, Ltd.
+ * Mike Rapoport <mike@compulab.co.il>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/types.h>
+#include <linux/pm.h>
+#include <linux/fb.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/sysdev.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+
+#include <linux/dm9000.h>
+#include <linux/rtc-v3020.h>
+#include <linux/serial_8250.h>
+
+#include <video/mbxfb.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxafb.h>
+#include <asm/arch/ohci.h>
+#include <asm/arch/mmc.h>
+#include <asm/arch/bitfield.h>
+#include <asm/arch/cm-x270.h>
+
+#include <asm/hardware/it8152.h>
+
+#include "generic.h"
+#include "cm-x270-pci.h"
+
+#define RTC_PHYS_BASE (PXA_CS1_PHYS + (5 << 22))
+#define DM9000_PHYS_BASE (PXA_CS1_PHYS + (6 << 22))
+
+static struct resource cmx270_dm9k_resource[] = {
+ [0] = {
+ .start = DM9000_PHYS_BASE,
+ .end = DM9000_PHYS_BASE + 4,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = DM9000_PHYS_BASE + 8,
+ .end = DM9000_PHYS_BASE + 8 + 500,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .start = CMX270_ETHIRQ,
+ .end = CMX270_ETHIRQ,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+/* for the moment we limit ourselves to 32bit IO until some
+ * better IO routines can be written and tested
+ */
+static struct dm9000_plat_data cmx270_dm9k_platdata = {
+ .flags = DM9000_PLATF_32BITONLY,
+};
+
+/* Ethernet device */
+static struct platform_device cmx270_device_dm9k = {
+ .name = "dm9000",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(cmx270_dm9k_resource),
+ .resource = cmx270_dm9k_resource,
+ .dev = {
+ .platform_data = &cmx270_dm9k_platdata,
+ }
+};
+
+/* audio device */
+static struct platform_device cmx270_audio_device = {
+ .name = "pxa2xx-ac97",
+ .id = -1,
+};
+
+/* touchscreen controller */
+static struct platform_device cmx270_ts_device = {
+ .name = "ucb1400_ts",
+ .id = -1,
+};
+
+/* RTC */
+static struct resource cmx270_v3020_resource[] = {
+ [0] = {
+ .start = RTC_PHYS_BASE,
+ .end = RTC_PHYS_BASE + 4,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+struct v3020_platform_data cmx270_v3020_pdata = {
+ .leftshift = 16,
+};
+
+static struct platform_device cmx270_rtc_device = {
+ .name = "v3020",
+ .num_resources = ARRAY_SIZE(cmx270_v3020_resource),
+ .resource = cmx270_v3020_resource,
+ .id = -1,
+ .dev = {
+ .platform_data = &cmx270_v3020_pdata,
+ }
+};
+
+/*
+ * CM-X270 LEDs
+ */
+static struct platform_device cmx270_led_device = {
+ .name = "cm-x270-led",
+ .id = -1,
+};
+
+/* 2700G graphics */
+static u64 fb_dma_mask = ~(u64)0;
+
+static struct resource cmx270_2700G_resource[] = {
+ /* frame buffer memory including ODFB and External SDRAM */
+ [0] = {
+ .start = MARATHON_PHYS,
+ .end = MARATHON_PHYS + 0x02000000,
+ .flags = IORESOURCE_MEM,
+ },
+ /* Marathon registers */
+ [1] = {
+ .start = MARATHON_PHYS + 0x03fe0000,
+ .end = MARATHON_PHYS + 0x03ffffff,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static unsigned long save_lcd_regs[10];
+
+static int cmx270_marathon_probe(struct fb_info *fb)
+{
+ /* save PXA-270 pin settings before enabling 2700G */
+ save_lcd_regs[0] = GPDR1;
+ save_lcd_regs[1] = GPDR2;
+ save_lcd_regs[2] = GAFR1_U;
+ save_lcd_regs[3] = GAFR2_L;
+ save_lcd_regs[4] = GAFR2_U;
+
+ /* Disable PXA-270 on-chip controller driving pins */
+ GPDR1 &= ~(0xfc000000);
+ GPDR2 &= ~(0x00c03fff);
+ GAFR1_U &= ~(0xfff00000);
+ GAFR2_L &= ~(0x0fffffff);
+ GAFR2_U &= ~(0x0000f000);
+ return 0;
+}
+
+static int cmx270_marathon_remove(struct fb_info *fb)
+{
+ GPDR1 = save_lcd_regs[0];
+ GPDR2 = save_lcd_regs[1];
+ GAFR1_U = save_lcd_regs[2];
+ GAFR2_L = save_lcd_regs[3];
+ GAFR2_U = save_lcd_regs[4];
+ return 0;
+}
+
+static struct mbxfb_platform_data cmx270_2700G_data = {
+ .xres = {
+ .min = 240,
+ .max = 1200,
+ .defval = 640,
+ },
+ .yres = {
+ .min = 240,
+ .max = 1200,
+ .defval = 480,
+ },
+ .bpp = {
+ .min = 16,
+ .max = 32,
+ .defval = 16,
+ },
+ .memsize = 8*1024*1024,
+ .probe = cmx270_marathon_probe,
+ .remove = cmx270_marathon_remove,
+};
+
+static struct platform_device cmx270_2700G = {
+ .name = "mbx-fb",
+ .dev = {
+ .platform_data = &cmx270_2700G_data,
+ .dma_mask = &fb_dma_mask,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .num_resources = ARRAY_SIZE(cmx270_2700G_resource),
+ .resource = cmx270_2700G_resource,
+ .id = -1,
+};
+
+static u64 ata_dma_mask = ~(u64)0;
+
+static struct platform_device cmx270_ata = {
+ .name = "pata_cm_x270",
+ .id = -1,
+ .dev = {
+ .dma_mask = &ata_dma_mask,
+ .coherent_dma_mask = 0xffffffff,
+ },
+};
+
+/* platform devices */
+static struct platform_device *platform_devices[] __initdata = {
+ &cmx270_device_dm9k,
+ &cmx270_audio_device,
+ &cmx270_rtc_device,
+ &cmx270_2700G,
+ &cmx270_led_device,
+ &cmx270_ts_device,
+ &cmx270_ata,
+};
+
+/* Map PCI companion and IDE/General Purpose CS statically */
+static struct map_desc cmx270_io_desc[] __initdata = {
+ [0] = { /* IDE/general purpose space */
+ .virtual = CMX270_IDE104_VIRT,
+ .pfn = __phys_to_pfn(CMX270_IDE104_PHYS),
+ .length = SZ_64M - SZ_8M,
+ .type = MT_DEVICE
+ },
+ [1] = { /* PCI bridge */
+ .virtual = CMX270_IT8152_VIRT,
+ .pfn = __phys_to_pfn(CMX270_IT8152_PHYS),
+ .length = SZ_64M,
+ .type = MT_DEVICE
+ },
+};
+
+/*
+ Display definitions
+ keep these for backwards compatibility, although symbolic names (as
+ e.g. in lpd270.c) looks better
+*/
+#define MTYPE_STN320x240 0
+#define MTYPE_TFT640x480 1
+#define MTYPE_CRT640x480 2
+#define MTYPE_CRT800x600 3
+#define MTYPE_TFT320x240 6
+#define MTYPE_STN640x480 7
+
+static struct pxafb_mode_info generic_stn_320x240_mode = {
+ .pixclock = 76923,
+ .bpp = 8,
+ .xres = 320,
+ .yres = 240,
+ .hsync_len = 3,
+ .vsync_len = 2,
+ .left_margin = 3,
+ .upper_margin = 0,
+ .right_margin = 3,
+ .lower_margin = 0,
+ .sync = (FB_SYNC_HOR_HIGH_ACT |
+ FB_SYNC_VERT_HIGH_ACT),
+ .cmap_greyscale = 0,
+};
+
+static struct pxafb_mach_info generic_stn_320x240 = {
+ .modes = &generic_stn_320x240_mode,
+ .num_modes = 1,
+ .lccr0 = 0,
+ .lccr3 = (LCCR3_PixClkDiv(0x03) |
+ LCCR3_Acb(0xff) |
+ LCCR3_PCP),
+ .cmap_inverse = 0,
+ .cmap_static = 0,
+};
+
+static struct pxafb_mode_info generic_tft_640x480_mode = {
+ .pixclock = 38461,
+ .bpp = 8,
+ .xres = 640,
+ .yres = 480,
+ .hsync_len = 60,
+ .vsync_len = 2,
+ .left_margin = 70,
+ .upper_margin = 10,
+ .right_margin = 70,
+ .lower_margin = 5,
+ .sync = 0,
+ .cmap_greyscale = 0,
+};
+
+static struct pxafb_mach_info generic_tft_640x480 = {
+ .modes = &generic_tft_640x480_mode,
+ .num_modes = 1,
+ .lccr0 = (LCCR0_PAS),
+ .lccr3 = (LCCR3_PixClkDiv(0x01) |
+ LCCR3_Acb(0xff) |
+ LCCR3_PCP),
+ .cmap_inverse = 0,
+ .cmap_static = 0,
+};
+
+static struct pxafb_mode_info generic_crt_640x480_mode = {
+ .pixclock = 38461,
+ .bpp = 8,
+ .xres = 640,
+ .yres = 480,
+ .hsync_len = 63,
+ .vsync_len = 2,
+ .left_margin = 81,
+ .upper_margin = 33,
+ .right_margin = 16,
+ .lower_margin = 10,
+ .sync = (FB_SYNC_HOR_HIGH_ACT |
+ FB_SYNC_VERT_HIGH_ACT),
+ .cmap_greyscale = 0,
+};
+
+static struct pxafb_mach_info generic_crt_640x480 = {
+ .modes = &generic_crt_640x480_mode,
+ .num_modes = 1,
+ .lccr0 = (LCCR0_PAS),
+ .lccr3 = (LCCR3_PixClkDiv(0x01) |
+ LCCR3_Acb(0xff)),
+ .cmap_inverse = 0,
+ .cmap_static = 0,
+};
+
+static struct pxafb_mode_info generic_crt_800x600_mode = {
+ .pixclock = 28846,
+ .bpp = 8,
+ .xres = 800,
+ .yres = 600,
+ .hsync_len = 63,
+ .vsync_len = 2,
+ .left_margin = 26,
+ .upper_margin = 21,
+ .right_margin = 26,
+ .lower_margin = 11,
+ .sync = (FB_SYNC_HOR_HIGH_ACT |
+ FB_SYNC_VERT_HIGH_ACT),
+ .cmap_greyscale = 0,
+};
+
+static struct pxafb_mach_info generic_crt_800x600 = {
+ .modes = &generic_crt_800x600_mode,
+ .num_modes = 1,
+ .lccr0 = (LCCR0_PAS),
+ .lccr3 = (LCCR3_PixClkDiv(0x02) |
+ LCCR3_Acb(0xff)),
+ .cmap_inverse = 0,
+ .cmap_static = 0,
+};
+
+static struct pxafb_mode_info generic_tft_320x240_mode = {
+ .pixclock = 134615,
+ .bpp = 16,
+ .xres = 320,
+ .yres = 240,
+ .hsync_len = 63,
+ .vsync_len = 7,
+ .left_margin = 75,
+ .upper_margin = 0,
+ .right_margin = 15,
+ .lower_margin = 15,
+ .sync = 0,
+ .cmap_greyscale = 0,
+};
+
+static struct pxafb_mach_info generic_tft_320x240 = {
+ .modes = &generic_tft_320x240_mode,
+ .num_modes = 1,
+ .lccr0 = (LCCR0_PAS),
+ .lccr3 = (LCCR3_PixClkDiv(0x06) |
+ LCCR3_Acb(0xff) |
+ LCCR3_PCP),
+ .cmap_inverse = 0,
+ .cmap_static = 0,
+};
+
+static struct pxafb_mode_info generic_stn_640x480_mode = {
+ .pixclock = 57692,
+ .bpp = 8,
+ .xres = 640,
+ .yres = 480,
+ .hsync_len = 4,
+ .vsync_len = 2,
+ .left_margin = 10,
+ .upper_margin = 5,
+ .right_margin = 10,
+ .lower_margin = 5,
+ .sync = (FB_SYNC_HOR_HIGH_ACT |
+ FB_SYNC_VERT_HIGH_ACT),
+ .cmap_greyscale = 0,
+};
+
+static struct pxafb_mach_info generic_stn_640x480 = {
+ .modes = &generic_stn_640x480_mode,
+ .num_modes = 1,
+ .lccr0 = 0,
+ .lccr3 = (LCCR3_PixClkDiv(0x02) |
+ LCCR3_Acb(0xff)),
+ .cmap_inverse = 0,
+ .cmap_static = 0,
+};
+
+static struct pxafb_mach_info *cmx270_display = &generic_crt_640x480;
+
+static int __init cmx270_set_display(char *str)
+{
+ int disp_type = simple_strtol(str, NULL, 0);
+ switch (disp_type) {
+ case MTYPE_STN320x240:
+ cmx270_display = &generic_stn_320x240;
+ break;
+ case MTYPE_TFT640x480:
+ cmx270_display = &generic_tft_640x480;
+ break;
+ case MTYPE_CRT640x480:
+ cmx270_display = &generic_crt_640x480;
+ break;
+ case MTYPE_CRT800x600:
+ cmx270_display = &generic_crt_800x600;
+ break;
+ case MTYPE_TFT320x240:
+ cmx270_display = &generic_tft_320x240;
+ break;
+ case MTYPE_STN640x480:
+ cmx270_display = &generic_stn_640x480;
+ break;
+ default: /* fallback to CRT 640x480 */
+ cmx270_display = &generic_crt_640x480;
+ break;
+ }
+ return 1;
+}
+
+/*
+ This should be done really early to get proper configuration for
+ frame buffer.
+ Indeed, pxafb parameters can be used istead, but CM-X270 bootloader
+ has limitied line length for kernel command line, and also it will
+ break compatibitlty with proprietary releases already in field.
+*/
+__setup("monitor=", cmx270_set_display);
+
+/* PXA27x OHCI controller setup */
+static int cmx270_ohci_init(struct device *dev)
+{
+ /* Set the Power Control Polarity Low */
+ UHCHR = (UHCHR | UHCHR_PCPL) &
+ ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSE);
+
+ return 0;
+}
+
+static struct pxaohci_platform_data cmx270_ohci_platform_data = {
+ .port_mode = PMM_PERPORT_MODE,
+ .init = cmx270_ohci_init,
+};
+
+
+static int cmx270_mci_init(struct device *dev,
+ irq_handler_t cmx270_detect_int,
+ void *data)
+{
+ int err;
+
+ /*
+ * setup GPIO for PXA27x MMC controller
+ */
+ pxa_gpio_mode(GPIO32_MMCCLK_MD);
+ pxa_gpio_mode(GPIO112_MMCCMD_MD);
+ pxa_gpio_mode(GPIO92_MMCDAT0_MD);
+ pxa_gpio_mode(GPIO109_MMCDAT1_MD);
+ pxa_gpio_mode(GPIO110_MMCDAT2_MD);
+ pxa_gpio_mode(GPIO111_MMCDAT3_MD);
+
+ /* SB-X270 uses GPIO105 as SD power enable */
+ pxa_gpio_mode(105 | GPIO_OUT);
+
+ /* card detect IRQ on GPIO 83 */
+ pxa_gpio_mode(IRQ_TO_GPIO(CMX270_MMC_IRQ));
+ set_irq_type(CMX270_MMC_IRQ, IRQT_FALLING);
+
+ err = request_irq(CMX270_MMC_IRQ, cmx270_detect_int,
+ IRQF_DISABLED | IRQF_TRIGGER_FALLING,
+ "MMC card detect", data);
+ if (err) {
+ printk(KERN_ERR "cmx270_mci_init: MMC/SD: can't"
+ " request MMC card detect IRQ\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static void cmx270_mci_setpower(struct device *dev, unsigned int vdd)
+{
+ struct pxamci_platform_data *p_d = dev->platform_data;
+
+ if ((1 << vdd) & p_d->ocr_mask) {
+ printk(KERN_DEBUG "%s: on\n", __FUNCTION__);
+ GPCR(105) = GPIO_bit(105);
+ } else {
+ GPSR(105) = GPIO_bit(105);
+ printk(KERN_DEBUG "%s: off\n", __FUNCTION__);
+ }
+}
+
+static void cmx270_mci_exit(struct device *dev, void *data)
+{
+ free_irq(CMX270_MMC_IRQ, data);
+}
+
+static struct pxamci_platform_data cmx270_mci_platform_data = {
+ .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
+ .init = cmx270_mci_init,
+ .setpower = cmx270_mci_setpower,
+ .exit = cmx270_mci_exit,
+};
+
+#ifdef CONFIG_PM
+static unsigned long sleep_save_msc[10];
+
+static int cmx270_suspend(struct sys_device *dev, pm_message_t state)
+{
+ cmx270_pci_suspend();
+
+ /* save MSC registers */
+ sleep_save_msc[0] = MSC0;
+ sleep_save_msc[1] = MSC1;
+ sleep_save_msc[2] = MSC2;
+
+ /* setup power saving mode registers */
+ PCFR = 0x0;
+ PSLR = 0xff400000;
+ PMCR = 0x00000005;
+ PWER = 0x80000000;
+ PFER = 0x00000000;
+ PRER = 0x00000000;
+ PGSR0 = 0xC0018800;
+ PGSR1 = 0x004F0002;
+ PGSR2 = 0x6021C000;
+ PGSR3 = 0x00020000;
+
+ return 0;
+}
+
+static int cmx270_resume(struct sys_device *dev)
+{
+ cmx270_pci_resume();
+
+ /* restore MSC registers */
+ MSC0 = sleep_save_msc[0];
+ MSC1 = sleep_save_msc[1];
+ MSC2 = sleep_save_msc[2];
+
+ return 0;
+}
+
+static struct sysdev_class cmx270_pm_sysclass = {
+ set_kset_name("pm"),
+ .resume = cmx270_resume,
+ .suspend = cmx270_suspend,
+};
+
+static struct sys_device cmx270_pm_device = {
+ .cls = &cmx270_pm_sysclass,
+};
+
+static int __init cmx270_pm_init(void)
+{
+ int error;
+ error = sysdev_class_register(&cmx270_pm_sysclass);
+ if (error == 0)
+ error = sysdev_register(&cmx270_pm_device);
+ return error;
+}
+#else
+static int __init cmx270_pm_init(void) { return 0; }
+#endif
+
+static void __init cmx270_init(void)
+{
+ cmx270_pm_init();
+
+ set_pxa_fb_info(cmx270_display);
+
+ /* register CM-X270 platform devices */
+ platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+
+ /* set MCI and OHCI platform parameters */
+ pxa_set_mci_info(&cmx270_mci_platform_data);
+ pxa_set_ohci_info(&cmx270_ohci_platform_data);
+
+ /* This enables the STUART */
+ pxa_gpio_mode(GPIO46_STRXD_MD);
+ pxa_gpio_mode(GPIO47_STTXD_MD);
+
+ /* This enables the BTUART */
+ pxa_gpio_mode(GPIO42_BTRXD_MD);
+ pxa_gpio_mode(GPIO43_BTTXD_MD);
+ pxa_gpio_mode(GPIO44_BTCTS_MD);
+ pxa_gpio_mode(GPIO45_BTRTS_MD);
+}
+
+static void __init cmx270_init_irq(void)
+{
+ pxa27x_init_irq();
+
+
+ cmx270_pci_init_irq();
+
+ /* Setup interrupt for dm9000 */
+ pxa_gpio_mode(IRQ_TO_GPIO(CMX270_ETHIRQ));
+ set_irq_type(CMX270_ETHIRQ, IRQT_RISING);
+
+ /* Setup interrupt for 2700G */
+ pxa_gpio_mode(IRQ_TO_GPIO(CMX270_GFXIRQ));
+ set_irq_type(CMX270_GFXIRQ, IRQT_FALLING);
+}
+
+static void __init cmx270_map_io(void)
+{
+ pxa_map_io();
+ iotable_init(cmx270_io_desc, ARRAY_SIZE(cmx270_io_desc));
+}
+
+
+MACHINE_START(ARMCORE, "Compulab CM-x270")
+ .boot_params = 0xa0000100,
+ .phys_io = 0x40000000,
+ .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
+ .map_io = cmx270_map_io,
+ .init_irq = cmx270_init_irq,
+ .timer = &pxa_timer,
+ .init_machine = cmx270_init,
+MACHINE_END
diff --git a/arch/arm/mach-pxa/devices.h b/arch/arm/mach-pxa/devices.h
index 636fdb1c049c..94c8d5cdd60a 100644
--- a/arch/arm/mach-pxa/devices.h
+++ b/arch/arm/mach-pxa/devices.h
@@ -9,3 +9,6 @@ extern struct platform_device pxa_device_i2c;
extern struct platform_device pxa_device_i2s;
extern struct platform_device pxa_device_ficp;
extern struct platform_device pxa_device_rtc;
+
+extern struct platform_device pxa27x_device_i2c_power;
+extern struct platform_device pxa27x_device_ohci;
diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
index 5510f6fdce55..1c34946ee16e 100644
--- a/arch/arm/mach-pxa/generic.c
+++ b/arch/arm/mach-pxa/generic.c
@@ -25,10 +25,6 @@
#include <linux/pm.h>
#include <linux/string.h>
-#include <linux/sched.h>
-#include <asm/cnt32_to_63.h>
-#include <asm/div64.h>
-
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/system.h>
@@ -47,66 +43,39 @@
#include "generic.h"
/*
- * This is the PXA2xx sched_clock implementation. This has a resolution
- * of at least 308ns and a maximum value that depends on the value of
- * CLOCK_TICK_RATE.
- *
- * The return value is guaranteed to be monotonic in that range as
- * long as there is always less than 582 seconds between successive
- * calls to this function.
+ * Get the clock frequency as reflected by CCCR and the turbo flag.
+ * We assume these values have been applied via a fcs.
+ * If info is not 0 we also display the current settings.
*/
-unsigned long long sched_clock(void)
+unsigned int get_clk_frequency_khz(int info)
{
- unsigned long long v = cnt32_to_63(OSCR);
- /* Note: top bit ov v needs cleared unless multiplier is even. */
-
-#if CLOCK_TICK_RATE == 3686400
- /* 1E9 / 3686400 => 78125 / 288, max value = 32025597s (370 days). */
- /* The <<1 is used to get rid of tick.hi top bit */
- v *= 78125<<1;
- do_div(v, 288<<1);
-#elif CLOCK_TICK_RATE == 3250000
- /* 1E9 / 3250000 => 4000 / 13, max value = 709490156s (8211 days) */
- v *= 4000;
- do_div(v, 13);
-#elif CLOCK_TICK_RATE == 3249600
- /* 1E9 / 3249600 => 625000 / 2031, max value = 4541295s (52 days) */
- v *= 625000;
- do_div(v, 2031);
-#else
-#warning "consider fixing sched_clock for your value of CLOCK_TICK_RATE"
- /*
- * 96-bit math to perform tick * NSEC_PER_SEC / CLOCK_TICK_RATE for
- * any value of CLOCK_TICK_RATE. Max value is in the 80 thousand
- * years range and truncation to unsigned long long limits it to
- * sched_clock's max range of ~584 years. This is nice but with
- * higher computation cost.
- */
- {
- union {
- unsigned long long val;
- struct { unsigned long lo, hi; };
- } x;
- unsigned long long y;
-
- x.val = v;
- x.hi &= 0x7fffffff;
- y = (unsigned long long)x.lo * NSEC_PER_SEC;
- x.lo = y;
- y = (y >> 32) + (unsigned long long)x.hi * NSEC_PER_SEC;
- x.hi = do_div(y, CLOCK_TICK_RATE);
- do_div(x.val, CLOCK_TICK_RATE);
- x.hi += y;
- v = x.val;
- }
-#endif
+ if (cpu_is_pxa21x() || cpu_is_pxa25x())
+ return pxa25x_get_clk_frequency_khz(info);
+ else if (cpu_is_pxa27x())
+ return pxa27x_get_clk_frequency_khz(info);
+ else
+ return pxa3xx_get_clk_frequency_khz(info);
+}
+EXPORT_SYMBOL(get_clk_frequency_khz);
- return v;
+/*
+ * Return the current memory clock frequency in units of 10kHz
+ */
+unsigned int get_memclk_frequency_10khz(void)
+{
+ if (cpu_is_pxa21x() || cpu_is_pxa25x())
+ return pxa25x_get_memclk_frequency_10khz();
+ else if (cpu_is_pxa27x())
+ return pxa27x_get_memclk_frequency_10khz();
+ else
+ return pxa3xx_get_memclk_frequency_10khz();
}
+EXPORT_SYMBOL(get_memclk_frequency_10khz);
/*
* Handy function to set GPIO alternate functions
*/
+int pxa_last_gpio;
int pxa_gpio_mode(int gpio_mode)
{
@@ -115,7 +84,7 @@ int pxa_gpio_mode(int gpio_mode)
int fn = (gpio_mode & GPIO_MD_MASK_FN) >> 8;
int gafr;
- if (gpio > PXA_LAST_GPIO)
+ if (gpio > pxa_last_gpio)
return -EINVAL;
local_irq_save(flags);
@@ -136,6 +105,44 @@ int pxa_gpio_mode(int gpio_mode)
EXPORT_SYMBOL(pxa_gpio_mode);
+int gpio_direction_input(unsigned gpio)
+{
+ unsigned long flags;
+ u32 mask;
+
+ if (gpio > pxa_last_gpio)
+ return -EINVAL;
+
+ mask = GPIO_bit(gpio);
+ local_irq_save(flags);
+ GPDR(gpio) &= ~mask;
+ local_irq_restore(flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(gpio_direction_input);
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+ unsigned long flags;
+ u32 mask;
+
+ if (gpio > pxa_last_gpio)
+ return -EINVAL;
+
+ mask = GPIO_bit(gpio);
+ local_irq_save(flags);
+ if (value)
+ GPSR(gpio) = mask;
+ else
+ GPCR(gpio) = mask;
+ GPDR(gpio) |= mask;
+ local_irq_restore(flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(gpio_direction_output);
+
/*
* Return GPIO level
*/
@@ -159,7 +166,7 @@ EXPORT_SYMBOL(pxa_gpio_set_value);
/*
* Routine to safely enable or disable a clock in the CKEN
*/
-void pxa_set_cken(int clock, int enable)
+void __pxa_set_cken(int clock, int enable)
{
unsigned long flags;
local_irq_save(flags);
@@ -172,7 +179,7 @@ void pxa_set_cken(int clock, int enable)
local_irq_restore(flags);
}
-EXPORT_SYMBOL(pxa_set_cken);
+EXPORT_SYMBOL(__pxa_set_cken);
/*
* Intel PXA2xx internal register mapping.
@@ -329,21 +336,80 @@ void __init set_pxa_fb_parent(struct device *parent_dev)
pxa_device_fb.dev.parent = parent_dev;
}
+static struct resource pxa_resource_ffuart[] = {
+ {
+ .start = __PREG(FFUART),
+ .end = __PREG(FFUART) + 35,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_FFUART,
+ .end = IRQ_FFUART,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
struct platform_device pxa_device_ffuart= {
.name = "pxa2xx-uart",
.id = 0,
+ .resource = pxa_resource_ffuart,
+ .num_resources = ARRAY_SIZE(pxa_resource_ffuart),
};
+
+static struct resource pxa_resource_btuart[] = {
+ {
+ .start = __PREG(BTUART),
+ .end = __PREG(BTUART) + 35,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_BTUART,
+ .end = IRQ_BTUART,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
struct platform_device pxa_device_btuart = {
.name = "pxa2xx-uart",
.id = 1,
+ .resource = pxa_resource_btuart,
+ .num_resources = ARRAY_SIZE(pxa_resource_btuart),
};
+
+static struct resource pxa_resource_stuart[] = {
+ {
+ .start = __PREG(STUART),
+ .end = __PREG(STUART) + 35,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_STUART,
+ .end = IRQ_STUART,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
struct platform_device pxa_device_stuart = {
.name = "pxa2xx-uart",
.id = 2,
+ .resource = pxa_resource_stuart,
+ .num_resources = ARRAY_SIZE(pxa_resource_stuart),
};
+
+static struct resource pxa_resource_hwuart[] = {
+ {
+ .start = __PREG(HWUART),
+ .end = __PREG(HWUART) + 47,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_HWUART,
+ .end = IRQ_HWUART,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
struct platform_device pxa_device_hwuart = {
.name = "pxa2xx-uart",
.id = 3,
+ .resource = pxa_resource_hwuart,
+ .num_resources = ARRAY_SIZE(pxa_resource_hwuart),
};
static struct resource pxai2c_resources[] = {
diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h
index 91ab2ad8b34b..b30f240a16c7 100644
--- a/arch/arm/mach-pxa/generic.h
+++ b/arch/arm/mach-pxa/generic.h
@@ -15,14 +15,40 @@ extern struct sys_timer pxa_timer;
extern void __init pxa_init_irq_low(void);
extern void __init pxa_init_irq_high(void);
extern void __init pxa_init_irq_gpio(int gpio_nr);
+extern void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int));
extern void __init pxa25x_init_irq(void);
extern void __init pxa27x_init_irq(void);
+extern void __init pxa3xx_init_irq(void);
extern void __init pxa_map_io(void);
extern unsigned int get_clk_frequency_khz(int info);
+extern int pxa_last_gpio;
#define SET_BANK(__nr,__start,__size) \
mi->bank[__nr].start = (__start), \
mi->bank[__nr].size = (__size), \
mi->bank[__nr].node = (((unsigned)(__start) - PHYS_OFFSET) >> 27)
+#ifdef CONFIG_PXA25x
+extern unsigned pxa25x_get_clk_frequency_khz(int);
+extern unsigned pxa25x_get_memclk_frequency_10khz(void);
+#else
+#define pxa25x_get_clk_frequency_khz(x) (0)
+#define pxa25x_get_memclk_frequency_10khz() (0)
+#endif
+
+#ifdef CONFIG_PXA27x
+extern unsigned pxa27x_get_clk_frequency_khz(int);
+extern unsigned pxa27x_get_memclk_frequency_10khz(void);
+#else
+#define pxa27x_get_clk_frequency_khz(x) (0)
+#define pxa27x_get_memclk_frequency_10khz() (0)
+#endif
+
+#ifdef CONFIG_PXA3xx
+extern unsigned pxa3xx_get_clk_frequency_khz(int);
+extern unsigned pxa3xx_get_memclk_frequency_10khz(void);
+#else
+#define pxa3xx_get_clk_frequency_khz(x) (0)
+#define pxa3xx_get_memclk_frequency_10khz() (0)
+#endif
diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
index ae2ae08032d7..07acb45b16ea 100644
--- a/arch/arm/mach-pxa/irq.c
+++ b/arch/arm/mach-pxa/irq.c
@@ -38,33 +38,11 @@ static void pxa_unmask_low_irq(unsigned int irq)
ICMR |= (1 << irq);
}
-static int pxa_set_wake(unsigned int irq, unsigned int on)
-{
- u32 mask;
-
- switch (irq) {
- case IRQ_RTCAlrm:
- mask = PWER_RTC;
- break;
-#ifdef CONFIG_PXA27x
- /* REVISIT can handle USBH1, USBH2, USB, MSL, USIM, ... */
-#endif
- default:
- return -EINVAL;
- }
- if (on)
- PWER |= mask;
- else
- PWER &= ~mask;
- return 0;
-}
-
static struct irq_chip pxa_internal_chip_low = {
.name = "SC",
.ack = pxa_mask_low_irq,
.mask = pxa_mask_low_irq,
.unmask = pxa_unmask_low_irq,
- .set_wake = pxa_set_wake,
};
void __init pxa_init_irq_low(void)
@@ -87,7 +65,7 @@ void __init pxa_init_irq_low(void)
}
}
-#ifdef CONFIG_PXA27x
+#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
/*
* This is for the second set of internal IRQs as found on the PXA27x.
@@ -125,26 +103,6 @@ void __init pxa_init_irq_high(void)
}
#endif
-/* Note that if an input/irq line ever gets changed to an output during
- * suspend, the relevant PWER, PRER, and PFER bits should be cleared.
- */
-#ifdef CONFIG_PXA27x
-
-/* PXA27x: Various gpios can issue wakeup events. This logic only
- * handles the simple cases, not the WEMUX2 and WEMUX3 options
- */
-#define PXA27x_GPIO_NOWAKE_MASK \
- ((1 << 8) | (1 << 7) | (1 << 6) | (1 << 5) | (1 << 2))
-#define WAKEMASK(gpio) \
- (((gpio) <= 15) \
- ? ((1 << (gpio)) & ~PXA27x_GPIO_NOWAKE_MASK) \
- : ((gpio == 35) ? (1 << 24) : 0))
-#else
-
-/* pxa 210, 250, 255, 26x: gpios 0..15 can issue wakeups */
-#define WAKEMASK(gpio) (((gpio) <= 15) ? (1 << (gpio)) : 0)
-#endif
-
/*
* PXA GPIO edge detection for IRQs:
* IRQs are generated on Falling-Edge, Rising-Edge, or both.
@@ -158,11 +116,9 @@ static long GPIO_IRQ_mask[4];
static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
{
int gpio, idx;
- u32 mask;
gpio = IRQ_TO_GPIO(irq);
idx = gpio >> 5;
- mask = WAKEMASK(gpio);
if (type == IRQT_PROBE) {
/* Don't mess with enabled GPIOs using preconfigured edges or
@@ -182,19 +138,15 @@ static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
if (type & __IRQT_RISEDGE) {
/* printk("rising "); */
__set_bit (gpio, GPIO_IRQ_rising_edge);
- PRER |= mask;
} else {
__clear_bit (gpio, GPIO_IRQ_rising_edge);
- PRER &= ~mask;
}
if (type & __IRQT_FALEDGE) {
/* printk("falling "); */
__set_bit (gpio, GPIO_IRQ_falling_edge);
- PFER |= mask;
} else {
__clear_bit (gpio, GPIO_IRQ_falling_edge);
- PFER &= ~mask;
}
/* printk("edges\n"); */
@@ -213,29 +165,12 @@ static void pxa_ack_low_gpio(unsigned int irq)
GEDR0 = (1 << (irq - IRQ_GPIO0));
}
-static int pxa_set_gpio_wake(unsigned int irq, unsigned int on)
-{
- int gpio = IRQ_TO_GPIO(irq);
- u32 mask = WAKEMASK(gpio);
-
- if (!mask)
- return -EINVAL;
-
- if (on)
- PWER |= mask;
- else
- PWER &= ~mask;
- return 0;
-}
-
-
static struct irq_chip pxa_low_gpio_chip = {
.name = "GPIO-l",
.ack = pxa_ack_low_gpio,
.mask = pxa_mask_low_irq,
.unmask = pxa_unmask_low_irq,
.set_type = pxa_gpio_irq_type,
- .set_wake = pxa_set_gpio_wake,
};
/*
@@ -342,13 +277,14 @@ static struct irq_chip pxa_muxed_gpio_chip = {
.mask = pxa_mask_muxed_gpio,
.unmask = pxa_unmask_muxed_gpio,
.set_type = pxa_gpio_irq_type,
- .set_wake = pxa_set_gpio_wake,
};
void __init pxa_init_irq_gpio(int gpio_nr)
{
int irq, i;
+ pxa_last_gpio = gpio_nr - 1;
+
/* clear all GPIO edge detects */
for (i = 0; i < gpio_nr; i += 32) {
GFER(i) = 0;
@@ -375,3 +311,13 @@ void __init pxa_init_irq_gpio(int gpio_nr)
set_irq_chip(IRQ_GPIO_2_x, &pxa_internal_chip_low);
set_irq_chained_handler(IRQ_GPIO_2_x, pxa_gpio_demux_handler);
}
+
+void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int))
+{
+ pxa_internal_chip_low.set_wake = set_wake;
+#ifdef CONFIG_PXA27x
+ pxa_internal_chip_high.set_wake = set_wake;
+#endif
+ pxa_low_gpio_chip.set_wake = set_wake;
+ pxa_muxed_gpio_chip.set_wake = set_wake;
+}
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index e70048fd00a5..011a1a72b61c 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -512,6 +512,25 @@ static void __init lubbock_map_io(void)
pxa_gpio_mode(GPIO44_BTCTS_MD);
pxa_gpio_mode(GPIO45_BTRTS_MD);
+ GPSR(GPIO48_nPOE) =
+ GPIO_bit(GPIO48_nPOE) |
+ GPIO_bit(GPIO49_nPWE) |
+ GPIO_bit(GPIO50_nPIOR) |
+ GPIO_bit(GPIO51_nPIOW) |
+ GPIO_bit(GPIO52_nPCE_1) |
+ GPIO_bit(GPIO53_nPCE_2);
+
+ pxa_gpio_mode(GPIO48_nPOE_MD);
+ pxa_gpio_mode(GPIO49_nPWE_MD);
+ pxa_gpio_mode(GPIO50_nPIOR_MD);
+ pxa_gpio_mode(GPIO51_nPIOW_MD);
+ pxa_gpio_mode(GPIO52_nPCE_1_MD);
+ pxa_gpio_mode(GPIO53_nPCE_2_MD);
+ pxa_gpio_mode(GPIO54_pSKTSEL_MD);
+ pxa_gpio_mode(GPIO55_nPREG_MD);
+ pxa_gpio_mode(GPIO56_nPWAIT_MD);
+ pxa_gpio_mode(GPIO57_nIOIS16_MD);
+
/* This is for the SMC chip select */
pxa_gpio_mode(GPIO79_nCS_3_MD);
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index b02c79c7e6a3..a4bc3483cbb3 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -444,6 +444,25 @@ static void __init mainstone_init(void)
*/
pxa_gpio_mode(GPIO45_SYSCLK_AC97_MD);
+ GPSR(GPIO48_nPOE) =
+ GPIO_bit(GPIO48_nPOE) |
+ GPIO_bit(GPIO49_nPWE) |
+ GPIO_bit(GPIO50_nPIOR) |
+ GPIO_bit(GPIO51_nPIOW) |
+ GPIO_bit(GPIO85_nPCE_1) |
+ GPIO_bit(GPIO54_nPCE_2);
+
+ pxa_gpio_mode(GPIO48_nPOE_MD);
+ pxa_gpio_mode(GPIO49_nPWE_MD);
+ pxa_gpio_mode(GPIO50_nPIOR_MD);
+ pxa_gpio_mode(GPIO51_nPIOW_MD);
+ pxa_gpio_mode(GPIO85_nPCE_1_MD);
+ pxa_gpio_mode(GPIO54_nPCE_2_MD);
+ pxa_gpio_mode(GPIO79_pSKTSEL_MD);
+ pxa_gpio_mode(GPIO55_nPREG_MD);
+ pxa_gpio_mode(GPIO56_nPWAIT_MD);
+ pxa_gpio_mode(GPIO57_nIOIS16_MD);
+
platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
/* reading Mainstone's "Virtual Configuration Register"
diff --git a/arch/arm/mach-pxa/mfp.c b/arch/arm/mach-pxa/mfp.c
new file mode 100644
index 000000000000..436f96574964
--- /dev/null
+++ b/arch/arm/mach-pxa/mfp.c
@@ -0,0 +1,235 @@
+/*
+ * linux/arch/arm/mach-pxa/mfp.c
+ *
+ * PXA3xx Multi-Function Pin Support
+ *
+ * Copyright (C) 2007 Marvell Internation Ltd.
+ *
+ * 2007-08-21: eric miao <eric.miao@marvell.com>
+ * initial version
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/mfp.h>
+
+/* mfp_spin_lock is used to ensure that MFP register configuration
+ * (most likely a read-modify-write operation) is atomic, and that
+ * mfp_table[] is consistent
+ */
+static DEFINE_SPINLOCK(mfp_spin_lock);
+
+static void __iomem *mfpr_mmio_base = (void __iomem *)&__REG(MFPR_BASE);
+static struct pxa3xx_mfp_pin mfp_table[MFP_PIN_MAX];
+
+#define mfpr_readl(off) \
+ __raw_readl(mfpr_mmio_base + (off))
+
+#define mfpr_writel(off, val) \
+ __raw_writel(val, mfpr_mmio_base + (off))
+
+/*
+ * perform a read-back of any MFPR register to make sure the
+ * previous writings are finished
+ */
+#define mfpr_sync() (void)__raw_readl(mfpr_mmio_base + 0)
+
+static inline void __mfp_config(int pin, unsigned long val)
+{
+ unsigned long off = mfp_table[pin].mfpr_off;
+
+ mfp_table[pin].mfpr_val = val;
+ mfpr_writel(off, val);
+}
+
+void pxa3xx_mfp_config(mfp_cfg_t *mfp_cfgs, int num)
+{
+ int i, pin;
+ unsigned long val, flags;
+ mfp_cfg_t *mfp_cfg = mfp_cfgs;
+
+ spin_lock_irqsave(&mfp_spin_lock, flags);
+
+ for (i = 0; i < num; i++, mfp_cfg++) {
+ pin = MFP_CFG_PIN(*mfp_cfg);
+ val = MFP_CFG_VAL(*mfp_cfg);
+
+ BUG_ON(pin >= MFP_PIN_MAX);
+
+ __mfp_config(pin, val);
+ }
+
+ mfpr_sync();
+ spin_unlock_irqrestore(&mfp_spin_lock, flags);
+}
+
+unsigned long pxa3xx_mfp_read(int mfp)
+{
+ unsigned long val, flags;
+
+ BUG_ON(mfp >= MFP_PIN_MAX);
+
+ spin_lock_irqsave(&mfp_spin_lock, flags);
+ val = mfpr_readl(mfp_table[mfp].mfpr_off);
+ spin_unlock_irqrestore(&mfp_spin_lock, flags);
+
+ return val;
+}
+
+void pxa3xx_mfp_write(int mfp, unsigned long val)
+{
+ unsigned long flags;
+
+ BUG_ON(mfp >= MFP_PIN_MAX);
+
+ spin_lock_irqsave(&mfp_spin_lock, flags);
+ mfpr_writel(mfp_table[mfp].mfpr_off, val);
+ mfpr_sync();
+ spin_unlock_irqrestore(&mfp_spin_lock, flags);
+}
+
+void pxa3xx_mfp_set_afds(int mfp, int af, int ds)
+{
+ uint32_t mfpr_off, mfpr_val;
+ unsigned long flags;
+
+ BUG_ON(mfp >= MFP_PIN_MAX);
+
+ spin_lock_irqsave(&mfp_spin_lock, flags);
+ mfpr_off = mfp_table[mfp].mfpr_off;
+
+ mfpr_val = mfpr_readl(mfpr_off);
+ mfpr_val &= ~(MFPR_AF_MASK | MFPR_DRV_MASK);
+ mfpr_val |= (((af & 0x7) << MFPR_ALT_OFFSET) |
+ ((ds & 0x7) << MFPR_DRV_OFFSET));
+
+ mfpr_writel(mfpr_off, mfpr_val);
+ mfpr_sync();
+
+ spin_unlock_irqrestore(&mfp_spin_lock, flags);
+}
+
+void pxa3xx_mfp_set_rdh(int mfp, int rdh)
+{
+ uint32_t mfpr_off, mfpr_val;
+ unsigned long flags;
+
+ BUG_ON(mfp >= MFP_PIN_MAX);
+
+ spin_lock_irqsave(&mfp_spin_lock, flags);
+
+ mfpr_off = mfp_table[mfp].mfpr_off;
+
+ mfpr_val = mfpr_readl(mfpr_off);
+ mfpr_val &= ~MFPR_RDH_MASK;
+
+ if (likely(rdh))
+ mfpr_val |= (1u << MFPR_SS_OFFSET);
+
+ mfpr_writel(mfpr_off, mfpr_val);
+ mfpr_sync();
+
+ spin_unlock_irqrestore(&mfp_spin_lock, flags);
+}
+
+void pxa3xx_mfp_set_lpm(int mfp, int lpm)
+{
+ uint32_t mfpr_off, mfpr_val;
+ unsigned long flags;
+
+ BUG_ON(mfp >= MFP_PIN_MAX);
+
+ spin_lock_irqsave(&mfp_spin_lock, flags);
+
+ mfpr_off = mfp_table[mfp].mfpr_off;
+ mfpr_val = mfpr_readl(mfpr_off);
+ mfpr_val &= ~MFPR_LPM_MASK;
+
+ if (lpm & 0x1) mfpr_val |= 1u << MFPR_SON_OFFSET;
+ if (lpm & 0x2) mfpr_val |= 1u << MFPR_SD_OFFSET;
+ if (lpm & 0x4) mfpr_val |= 1u << MFPR_PU_OFFSET;
+ if (lpm & 0x8) mfpr_val |= 1u << MFPR_PD_OFFSET;
+ if (lpm &0x10) mfpr_val |= 1u << MFPR_PS_OFFSET;
+
+ mfpr_writel(mfpr_off, mfpr_val);
+ mfpr_sync();
+
+ spin_unlock_irqrestore(&mfp_spin_lock, flags);
+}
+
+void pxa3xx_mfp_set_pull(int mfp, int pull)
+{
+ uint32_t mfpr_off, mfpr_val;
+ unsigned long flags;
+
+ BUG_ON(mfp >= MFP_PIN_MAX);
+
+ spin_lock_irqsave(&mfp_spin_lock, flags);
+
+ mfpr_off = mfp_table[mfp].mfpr_off;
+ mfpr_val = mfpr_readl(mfpr_off);
+ mfpr_val &= ~MFPR_PULL_MASK;
+ mfpr_val |= ((pull & 0x7u) << MFPR_PD_OFFSET);
+
+ mfpr_writel(mfpr_off, mfpr_val);
+ mfpr_sync();
+
+ spin_unlock_irqrestore(&mfp_spin_lock, flags);
+}
+
+void pxa3xx_mfp_set_edge(int mfp, int edge)
+{
+ uint32_t mfpr_off, mfpr_val;
+ unsigned long flags;
+
+ BUG_ON(mfp >= MFP_PIN_MAX);
+
+ spin_lock_irqsave(&mfp_spin_lock, flags);
+
+ mfpr_off = mfp_table[mfp].mfpr_off;
+ mfpr_val = mfpr_readl(mfpr_off);
+
+ mfpr_val &= ~MFPR_EDGE_MASK;
+ mfpr_val |= (edge & 0x3u) << MFPR_ERE_OFFSET;
+ mfpr_val |= (!edge & 0x1) << MFPR_EC_OFFSET;
+
+ mfpr_writel(mfpr_off, mfpr_val);
+ mfpr_sync();
+
+ spin_unlock_irqrestore(&mfp_spin_lock, flags);
+}
+
+void __init pxa3xx_mfp_init_addr(struct pxa3xx_mfp_addr_map *map)
+{
+ struct pxa3xx_mfp_addr_map *p;
+ unsigned long offset, flags;
+ int i;
+
+ spin_lock_irqsave(&mfp_spin_lock, flags);
+
+ for (p = map; p->start != MFP_PIN_INVALID; p++) {
+ offset = p->offset;
+ i = p->start;
+
+ do {
+ mfp_table[i].mfpr_off = offset;
+ mfp_table[i].mfpr_val = 0;
+ offset += 4; i++;
+ } while ((i <= p->end) && (p->end != -1));
+ }
+
+ spin_unlock_irqrestore(&mfp_spin_lock, flags);
+}
+
+void __init pxa3xx_init_mfp(void)
+{
+ memset(mfp_table, 0, sizeof(mfp_table));
+}
diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c
index b59a81a8e7d3..a941c71c7d06 100644
--- a/arch/arm/mach-pxa/pm.c
+++ b/arch/arm/mach-pxa/pm.c
@@ -86,7 +86,7 @@ static int pxa_pm_valid(suspend_state_t state)
return -EINVAL;
}
-static struct pm_ops pxa_pm_ops = {
+static struct platform_suspend_ops pxa_pm_ops = {
.valid = pxa_pm_valid,
.enter = pxa_pm_enter,
};
@@ -104,7 +104,7 @@ static int __init pxa_pm_init(void)
return -ENOMEM;
}
- pm_set_ops(&pxa_pm_ops);
+ suspend_set_ops(&pxa_pm_ops);
return 0;
}
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index 6dfcca72e90f..dcd81f8d0833 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -20,7 +20,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
-#include <linux/pm.h>
+#include <linux/suspend.h>
#include <asm/hardware.h>
#include <asm/arch/irqs.h>
@@ -30,6 +30,7 @@
#include "generic.h"
#include "devices.h"
+#include "clock.h"
/*
* Various clock factors driven by the CCCR register.
@@ -53,7 +54,7 @@ static unsigned char N2_clk_mult[8] = { 0, 0, 2, 3, 4, 0, 6, 0 };
* We assume these values have been applied via a fcs.
* If info is not 0 we also display the current settings.
*/
-unsigned int get_clk_frequency_khz(int info)
+unsigned int pxa25x_get_clk_frequency_khz(int info)
{
unsigned long cccr, turbo;
unsigned int l, L, m, M, n2, N;
@@ -86,27 +87,48 @@ unsigned int get_clk_frequency_khz(int info)
return (turbo & 1) ? (N/1000) : (M/1000);
}
-EXPORT_SYMBOL(get_clk_frequency_khz);
-
/*
* Return the current memory clock frequency in units of 10kHz
*/
-unsigned int get_memclk_frequency_10khz(void)
+unsigned int pxa25x_get_memclk_frequency_10khz(void)
{
return L_clk_mult[(CCCR >> 0) & 0x1f] * BASE_CLK / 10000;
}
-EXPORT_SYMBOL(get_memclk_frequency_10khz);
-
-/*
- * Return the current LCD clock frequency in units of 10kHz
- */
-unsigned int get_lcdclk_frequency_10khz(void)
+static unsigned long clk_pxa25x_lcd_getrate(struct clk *clk)
{
- return get_memclk_frequency_10khz();
+ return pxa25x_get_memclk_frequency_10khz() * 10000;
}
-EXPORT_SYMBOL(get_lcdclk_frequency_10khz);
+static const struct clkops clk_pxa25x_lcd_ops = {
+ .enable = clk_cken_enable,
+ .disable = clk_cken_disable,
+ .getrate = clk_pxa25x_lcd_getrate,
+};
+
+/*
+ * 3.6864MHz -> OST, GPIO, SSP, PWM, PLLs (95.842MHz, 147.456MHz)
+ * 95.842MHz -> MMC 19.169MHz, I2C 31.949MHz, FICP 47.923MHz, USB 47.923MHz
+ * 147.456MHz -> UART 14.7456MHz, AC97 12.288MHz, I2S 5.672MHz (allegedly)
+ */
+static struct clk pxa25x_clks[] = {
+ INIT_CK("LCDCLK", LCD, &clk_pxa25x_lcd_ops, &pxa_device_fb.dev),
+ INIT_CKEN("UARTCLK", FFUART, 14745600, 1, &pxa_device_ffuart.dev),
+ INIT_CKEN("UARTCLK", BTUART, 14745600, 1, &pxa_device_btuart.dev),
+ INIT_CKEN("UARTCLK", BTUART, 14745600, 1, &pxa_device_btuart.dev),
+ INIT_CKEN("UARTCLK", STUART, 14745600, 1, NULL),
+ INIT_CKEN("UDCCLK", USB, 47923000, 5, &pxa_device_udc.dev),
+ INIT_CKEN("MMCCLK", MMC, 19169000, 0, &pxa_device_mci.dev),
+ INIT_CKEN("I2CCLK", I2C, 31949000, 0, &pxa_device_i2c.dev),
+ /*
+ INIT_CKEN("PWMCLK", PWM0, 3686400, 0, NULL),
+ INIT_CKEN("PWMCLK", PWM0, 3686400, 0, NULL),
+ INIT_CKEN("SSPCLK", SSP, 3686400, 0, NULL),
+ INIT_CKEN("I2SCLK", I2S, 14745600, 0, NULL),
+ INIT_CKEN("NSSPCLK", NSSP, 3686400, 0, NULL),
+ */
+ INIT_CKEN("FICPCLK", FICP, 47923000, 0, NULL),
+};
#ifdef CONFIG_PM
@@ -193,7 +215,7 @@ static void pxa25x_cpu_pm_enter(suspend_state_t state)
static struct pxa_cpu_pm_fns pxa25x_cpu_pm_fns = {
.save_size = SLEEP_SAVE_SIZE,
- .valid = pm_valid_only_mem,
+ .valid = suspend_valid_only_mem,
.save = pxa25x_cpu_pm_save,
.restore = pxa25x_cpu_pm_restore,
.enter = pxa25x_cpu_pm_enter,
@@ -205,10 +227,52 @@ static void __init pxa25x_init_pm(void)
}
#endif
+/* PXA25x: supports wakeup from GPIO0..GPIO15 and RTC alarm
+ */
+
+static int pxa25x_set_wake(unsigned int irq, unsigned int on)
+{
+ int gpio = IRQ_TO_GPIO(irq);
+ uint32_t gpio_bit, mask = 0;
+
+ if (gpio >= 0 && gpio <= 15) {
+ gpio_bit = GPIO_bit(gpio);
+ mask = gpio_bit;
+ if (on) {
+ if (GRER(gpio) | gpio_bit)
+ PRER |= gpio_bit;
+ else
+ PRER &= ~gpio_bit;
+
+ if (GFER(gpio) | gpio_bit)
+ PFER |= gpio_bit;
+ else
+ PFER &= ~gpio_bit;
+ }
+ goto set_pwer;
+ }
+
+ if (irq == IRQ_RTCAlrm) {
+ mask = PWER_RTC;
+ goto set_pwer;
+ }
+
+ return -EINVAL;
+
+set_pwer:
+ if (on)
+ PWER |= mask;
+ else
+ PWER &=~mask;
+
+ return 0;
+}
+
void __init pxa25x_init_irq(void)
{
pxa_init_irq_low();
pxa_init_irq_gpio(85);
+ pxa_init_irq_set_wake(pxa25x_set_wake);
}
static struct platform_device *pxa25x_devices[] __initdata = {
@@ -229,6 +293,8 @@ static int __init pxa25x_init(void)
int ret = 0;
if (cpu_is_pxa21x() || cpu_is_pxa25x()) {
+ clks_register(pxa25x_clks, ARRAY_SIZE(pxa25x_clks));
+
if ((ret = pxa_init_dma(16)))
return ret;
#ifdef CONFIG_PM
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 203371ab19db..d0f2b597db12 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -14,7 +14,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/pm.h>
+#include <linux/suspend.h>
#include <linux/platform_device.h>
#include <asm/hardware.h>
@@ -27,6 +27,7 @@
#include "generic.h"
#include "devices.h"
+#include "clock.h"
/* Crystal clock: 13MHz */
#define BASE_CLK 13000000
@@ -36,7 +37,7 @@
* We assume these values have been applied via a fcs.
* If info is not 0 we also display the current settings.
*/
-unsigned int get_clk_frequency_khz( int info)
+unsigned int pxa27x_get_clk_frequency_khz(int info)
{
unsigned long ccsr, clkcfg;
unsigned int l, L, m, M, n2, N, S;
@@ -79,7 +80,7 @@ unsigned int get_clk_frequency_khz( int info)
* Return the current mem clock frequency in units of 10kHz as
* reflected by CCCR[A], B, and L
*/
-unsigned int get_memclk_frequency_10khz(void)
+unsigned int pxa27x_get_memclk_frequency_10khz(void)
{
unsigned long ccsr, clkcfg;
unsigned int l, L, m, M;
@@ -104,7 +105,7 @@ unsigned int get_memclk_frequency_10khz(void)
/*
* Return the current LCD clock frequency in units of 10kHz as
*/
-unsigned int get_lcdclk_frequency_10khz(void)
+static unsigned int pxa27x_get_lcdclk_frequency_10khz(void)
{
unsigned long ccsr;
unsigned int l, L, k, K;
@@ -120,9 +121,47 @@ unsigned int get_lcdclk_frequency_10khz(void)
return (K / 10000);
}
-EXPORT_SYMBOL(get_clk_frequency_khz);
-EXPORT_SYMBOL(get_memclk_frequency_10khz);
-EXPORT_SYMBOL(get_lcdclk_frequency_10khz);
+static unsigned long clk_pxa27x_lcd_getrate(struct clk *clk)
+{
+ return pxa27x_get_lcdclk_frequency_10khz() * 10000;
+}
+
+static const struct clkops clk_pxa27x_lcd_ops = {
+ .enable = clk_cken_enable,
+ .disable = clk_cken_disable,
+ .getrate = clk_pxa27x_lcd_getrate,
+};
+
+static struct clk pxa27x_clks[] = {
+ INIT_CK("LCDCLK", LCD, &clk_pxa27x_lcd_ops, &pxa_device_fb.dev),
+ INIT_CK("CAMCLK", CAMERA, &clk_pxa27x_lcd_ops, NULL),
+
+ INIT_CKEN("UARTCLK", FFUART, 14857000, 1, &pxa_device_ffuart.dev),
+ INIT_CKEN("UARTCLK", BTUART, 14857000, 1, &pxa_device_btuart.dev),
+ INIT_CKEN("UARTCLK", STUART, 14857000, 1, NULL),
+
+ INIT_CKEN("I2SCLK", I2S, 14682000, 0, &pxa_device_i2s.dev),
+ INIT_CKEN("I2CCLK", I2C, 32842000, 0, &pxa_device_i2c.dev),
+ INIT_CKEN("UDCCLK", USB, 48000000, 5, &pxa_device_udc.dev),
+ INIT_CKEN("MMCCLK", MMC, 19500000, 0, &pxa_device_mci.dev),
+ INIT_CKEN("FICPCLK", FICP, 48000000, 0, &pxa_device_ficp.dev),
+
+ INIT_CKEN("USBCLK", USB, 48000000, 0, &pxa27x_device_ohci.dev),
+ INIT_CKEN("I2CCLK", PWRI2C, 13000000, 0, &pxa27x_device_i2c_power.dev),
+ INIT_CKEN("KBDCLK", KEYPAD, 32768, 0, NULL),
+
+ /*
+ INIT_CKEN("PWMCLK", PWM0, 13000000, 0, NULL),
+ INIT_CKEN("SSPCLK", SSP1, 13000000, 0, NULL),
+ INIT_CKEN("SSPCLK", SSP2, 13000000, 0, NULL),
+ INIT_CKEN("SSPCLK", SSP3, 13000000, 0, NULL),
+ INIT_CKEN("MSLCLK", MSL, 48000000, 0, NULL),
+ INIT_CKEN("USIMCLK", USIM, 48000000, 0, NULL),
+ INIT_CKEN("MSTKCLK", MEMSTK, 19500000, 0, NULL),
+ INIT_CKEN("IMCLK", IM, 0, 0, NULL),
+ INIT_CKEN("MEMCLK", MEMC, 0, 0, NULL),
+ */
+};
#ifdef CONFIG_PM
@@ -267,6 +306,69 @@ static void __init pxa27x_init_pm(void)
}
#endif
+/* PXA27x: Various gpios can issue wakeup events. This logic only
+ * handles the simple cases, not the WEMUX2 and WEMUX3 options
+ */
+#define PXA27x_GPIO_NOWAKE_MASK \
+ ((1 << 8) | (1 << 7) | (1 << 6) | (1 << 5) | (1 << 2))
+#define WAKEMASK(gpio) \
+ (((gpio) <= 15) \
+ ? ((1 << (gpio)) & ~PXA27x_GPIO_NOWAKE_MASK) \
+ : ((gpio == 35) ? (1 << 24) : 0))
+
+static int pxa27x_set_wake(unsigned int irq, unsigned int on)
+{
+ int gpio = IRQ_TO_GPIO(irq);
+ uint32_t mask;
+
+ if ((gpio >= 0 && gpio <= 15) || (gpio == 35)) {
+ if (WAKEMASK(gpio) == 0)
+ return -EINVAL;
+
+ mask = WAKEMASK(gpio);
+
+ if (on) {
+ if (GRER(gpio) | GPIO_bit(gpio))
+ PRER |= mask;
+ else
+ PRER &= ~mask;
+
+ if (GFER(gpio) | GPIO_bit(gpio))
+ PFER |= mask;
+ else
+ PFER &= ~mask;
+ }
+ goto set_pwer;
+ }
+
+ switch (irq) {
+ case IRQ_RTCAlrm:
+ mask = PWER_RTC;
+ break;
+ case IRQ_USB:
+ mask = 1u << 26;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+set_pwer:
+ if (on)
+ PWER |= mask;
+ else
+ PWER &=~mask;
+
+ return 0;
+}
+
+void __init pxa27x_init_irq(void)
+{
+ pxa_init_irq_low();
+ pxa_init_irq_high();
+ pxa_init_irq_gpio(128);
+ pxa_init_irq_set_wake(pxa27x_set_wake);
+}
+
/*
* device registration specific to PXA27x.
*/
@@ -286,7 +388,7 @@ static struct resource pxa27x_ohci_resources[] = {
},
};
-static struct platform_device pxa27x_device_ohci = {
+struct platform_device pxa27x_device_ohci = {
.name = "pxa27x-ohci",
.id = -1,
.dev = {
@@ -314,7 +416,7 @@ static struct resource i2c_power_resources[] = {
},
};
-static struct platform_device pxa27x_device_i2c_power = {
+struct platform_device pxa27x_device_i2c_power = {
.name = "pxa2xx-i2c",
.id = 1,
.resource = i2c_power_resources,
@@ -336,17 +438,12 @@ static struct platform_device *devices[] __initdata = {
&pxa27x_device_ohci,
};
-void __init pxa27x_init_irq(void)
-{
- pxa_init_irq_low();
- pxa_init_irq_high();
- pxa_init_irq_gpio(128);
-}
-
static int __init pxa27x_init(void)
{
int ret = 0;
if (cpu_is_pxa27x()) {
+ clks_register(pxa27x_clks, ARRAY_SIZE(pxa27x_clks));
+
if ((ret = pxa_init_dma(32)))
return ret;
#ifdef CONFIG_PM
diff --git a/arch/arm/mach-pxa/pxa300.c b/arch/arm/mach-pxa/pxa300.c
new file mode 100644
index 000000000000..0a0d3877f212
--- /dev/null
+++ b/arch/arm/mach-pxa/pxa300.c
@@ -0,0 +1,95 @@
+/*
+ * linux/arch/arm/mach-pxa/pxa300.c
+ *
+ * Code specific to PXA300/PXA310
+ *
+ * Copyright (C) 2007 Marvell Internation Ltd.
+ *
+ * 2007-08-21: eric miao <eric.miao@marvell.com>
+ * initial version
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/mfp-pxa300.h>
+
+static struct pxa3xx_mfp_addr_map pxa300_mfp_addr_map[] __initdata = {
+
+ MFP_ADDR_X(GPIO0, GPIO2, 0x00b4),
+ MFP_ADDR_X(GPIO3, GPIO26, 0x027c),
+ MFP_ADDR_X(GPIO27, GPIO98, 0x0400),
+ MFP_ADDR_X(GPIO99, GPIO127, 0x0600),
+ MFP_ADDR_X(GPIO0_2, GPIO1_2, 0x0674),
+ MFP_ADDR_X(GPIO2_2, GPIO6_2, 0x02dc),
+
+ MFP_ADDR(nBE0, 0x0204),
+ MFP_ADDR(nBE1, 0x0208),
+
+ MFP_ADDR(nLUA, 0x0244),
+ MFP_ADDR(nLLA, 0x0254),
+
+ MFP_ADDR(DF_CLE_nOE, 0x0240),
+ MFP_ADDR(DF_nRE_nOE, 0x0200),
+ MFP_ADDR(DF_ALE_nWE, 0x020C),
+ MFP_ADDR(DF_INT_RnB, 0x00C8),
+ MFP_ADDR(DF_nCS0, 0x0248),
+ MFP_ADDR(DF_nCS1, 0x0278),
+ MFP_ADDR(DF_nWE, 0x00CC),
+
+ MFP_ADDR(DF_ADDR0, 0x0210),
+ MFP_ADDR(DF_ADDR1, 0x0214),
+ MFP_ADDR(DF_ADDR2, 0x0218),
+ MFP_ADDR(DF_ADDR3, 0x021C),
+
+ MFP_ADDR(DF_IO0, 0x0220),
+ MFP_ADDR(DF_IO1, 0x0228),
+ MFP_ADDR(DF_IO2, 0x0230),
+ MFP_ADDR(DF_IO3, 0x0238),
+ MFP_ADDR(DF_IO4, 0x0258),
+ MFP_ADDR(DF_IO5, 0x0260),
+ MFP_ADDR(DF_IO6, 0x0268),
+ MFP_ADDR(DF_IO7, 0x0270),
+ MFP_ADDR(DF_IO8, 0x0224),
+ MFP_ADDR(DF_IO9, 0x022C),
+ MFP_ADDR(DF_IO10, 0x0234),
+ MFP_ADDR(DF_IO11, 0x023C),
+ MFP_ADDR(DF_IO12, 0x025C),
+ MFP_ADDR(DF_IO13, 0x0264),
+ MFP_ADDR(DF_IO14, 0x026C),
+ MFP_ADDR(DF_IO15, 0x0274),
+
+ MFP_ADDR_END,
+};
+
+/* override pxa300 MFP register addresses */
+static struct pxa3xx_mfp_addr_map pxa310_mfp_addr_map[] __initdata = {
+ MFP_ADDR_X(GPIO30, GPIO98, 0x0418),
+ MFP_ADDR_X(GPIO7_2, GPIO12_2, 0x052C),
+
+ MFP_ADDR(ULPI_STP, 0x040C),
+ MFP_ADDR(ULPI_NXT, 0x0410),
+ MFP_ADDR(ULPI_DIR, 0x0414),
+
+ MFP_ADDR_END,
+};
+
+static int __init pxa300_init(void)
+{
+ if (cpu_is_pxa300() || cpu_is_pxa310()) {
+ pxa3xx_init_mfp();
+ pxa3xx_mfp_init_addr(pxa300_mfp_addr_map);
+ }
+
+ if (cpu_is_pxa310())
+ pxa3xx_mfp_init_addr(pxa310_mfp_addr_map);
+
+ return 0;
+}
+
+core_initcall(pxa300_init);
diff --git a/arch/arm/mach-pxa/pxa320.c b/arch/arm/mach-pxa/pxa320.c
new file mode 100644
index 000000000000..1010f77d977a
--- /dev/null
+++ b/arch/arm/mach-pxa/pxa320.c
@@ -0,0 +1,88 @@
+/*
+ * linux/arch/arm/mach-pxa/pxa320.c
+ *
+ * Code specific to PXA320
+ *
+ * Copyright (C) 2007 Marvell Internation Ltd.
+ *
+ * 2007-08-21: eric miao <eric.miao@marvell.com>
+ * initial version
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/mfp.h>
+#include <asm/arch/mfp-pxa320.h>
+
+static struct pxa3xx_mfp_addr_map pxa320_mfp_addr_map[] __initdata = {
+
+ MFP_ADDR_X(GPIO0, GPIO4, 0x0124),
+ MFP_ADDR_X(GPIO5, GPIO26, 0x028C),
+ MFP_ADDR_X(GPIO27, GPIO62, 0x0400),
+ MFP_ADDR_X(GPIO63, GPIO73, 0x04B4),
+ MFP_ADDR_X(GPIO74, GPIO98, 0x04F0),
+ MFP_ADDR_X(GPIO99, GPIO127, 0x0600),
+ MFP_ADDR_X(GPIO0_2, GPIO5_2, 0x0674),
+ MFP_ADDR_X(GPIO6_2, GPIO13_2, 0x0494),
+ MFP_ADDR_X(GPIO14_2, GPIO17_2, 0x04E0),
+
+ MFP_ADDR(nXCVREN, 0x0138),
+ MFP_ADDR(DF_CLE_nOE, 0x0204),
+ MFP_ADDR(DF_nADV1_ALE, 0x0208),
+ MFP_ADDR(DF_SCLK_S, 0x020C),
+ MFP_ADDR(DF_SCLK_E, 0x0210),
+ MFP_ADDR(nBE0, 0x0214),
+ MFP_ADDR(nBE1, 0x0218),
+ MFP_ADDR(DF_nADV2_ALE, 0x021C),
+ MFP_ADDR(DF_INT_RnB, 0x0220),
+ MFP_ADDR(DF_nCS0, 0x0224),
+ MFP_ADDR(DF_nCS1, 0x0228),
+ MFP_ADDR(DF_nWE, 0x022C),
+ MFP_ADDR(DF_nRE_nOE, 0x0230),
+ MFP_ADDR(nLUA, 0x0234),
+ MFP_ADDR(nLLA, 0x0238),
+ MFP_ADDR(DF_ADDR0, 0x023C),
+ MFP_ADDR(DF_ADDR1, 0x0240),
+ MFP_ADDR(DF_ADDR2, 0x0244),
+ MFP_ADDR(DF_ADDR3, 0x0248),
+ MFP_ADDR(DF_IO0, 0x024C),
+ MFP_ADDR(DF_IO8, 0x0250),
+ MFP_ADDR(DF_IO1, 0x0254),
+ MFP_ADDR(DF_IO9, 0x0258),
+ MFP_ADDR(DF_IO2, 0x025C),
+ MFP_ADDR(DF_IO10, 0x0260),
+ MFP_ADDR(DF_IO3, 0x0264),
+ MFP_ADDR(DF_IO11, 0x0268),
+ MFP_ADDR(DF_IO4, 0x026C),
+ MFP_ADDR(DF_IO12, 0x0270),
+ MFP_ADDR(DF_IO5, 0x0274),
+ MFP_ADDR(DF_IO13, 0x0278),
+ MFP_ADDR(DF_IO6, 0x027C),
+ MFP_ADDR(DF_IO14, 0x0280),
+ MFP_ADDR(DF_IO7, 0x0284),
+ MFP_ADDR(DF_IO15, 0x0288),
+
+ MFP_ADDR_END,
+};
+
+static void __init pxa320_init_mfp(void)
+{
+ pxa3xx_init_mfp();
+ pxa3xx_mfp_init_addr(pxa320_mfp_addr_map);
+}
+
+static int __init pxa320_init(void)
+{
+ if (cpu_is_pxa320())
+ pxa320_init_mfp();
+
+ return 0;
+}
+
+core_initcall(pxa320_init);
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
new file mode 100644
index 000000000000..5da798282a54
--- /dev/null
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -0,0 +1,216 @@
+/*
+ * linux/arch/arm/mach-pxa/pxa3xx.c
+ *
+ * code specific to pxa3xx aka Monahans
+ *
+ * Copyright (C) 2006 Marvell International Ltd.
+ *
+ * 2007-09-02: eric miao <eric.miao@marvell.com>
+ * initial version
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/pxa3xx-regs.h>
+#include <asm/arch/ohci.h>
+#include <asm/arch/pm.h>
+#include <asm/arch/dma.h>
+#include <asm/arch/ssp.h>
+
+#include "generic.h"
+#include "devices.h"
+#include "clock.h"
+
+/* Crystal clock: 13MHz */
+#define BASE_CLK 13000000
+
+/* Ring Oscillator Clock: 60MHz */
+#define RO_CLK 60000000
+
+#define ACCR_D0CS (1 << 26)
+
+/* crystal frequency to static memory controller multiplier (SMCFS) */
+static unsigned char smcfs_mult[8] = { 6, 0, 8, 0, 0, 16, };
+
+/* crystal frequency to HSIO bus frequency multiplier (HSS) */
+static unsigned char hss_mult[4] = { 8, 12, 16, 0 };
+
+/*
+ * Get the clock frequency as reflected by CCSR and the turbo flag.
+ * We assume these values have been applied via a fcs.
+ * If info is not 0 we also display the current settings.
+ */
+unsigned int pxa3xx_get_clk_frequency_khz(int info)
+{
+ unsigned long acsr, xclkcfg;
+ unsigned int t, xl, xn, hss, ro, XL, XN, CLK, HSS;
+
+ /* Read XCLKCFG register turbo bit */
+ __asm__ __volatile__("mrc\tp14, 0, %0, c6, c0, 0" : "=r"(xclkcfg));
+ t = xclkcfg & 0x1;
+
+ acsr = ACSR;
+
+ xl = acsr & 0x1f;
+ xn = (acsr >> 8) & 0x7;
+ hss = (acsr >> 14) & 0x3;
+
+ XL = xl * BASE_CLK;
+ XN = xn * XL;
+
+ ro = acsr & ACCR_D0CS;
+
+ CLK = (ro) ? RO_CLK : ((t) ? XN : XL);
+ HSS = (ro) ? RO_CLK : hss_mult[hss] * BASE_CLK;
+
+ if (info) {
+ pr_info("RO Mode clock: %d.%02dMHz (%sactive)\n",
+ RO_CLK / 1000000, (RO_CLK % 1000000) / 10000,
+ (ro) ? "" : "in");
+ pr_info("Run Mode clock: %d.%02dMHz (*%d)\n",
+ XL / 1000000, (XL % 1000000) / 10000, xl);
+ pr_info("Turbo Mode clock: %d.%02dMHz (*%d, %sactive)\n",
+ XN / 1000000, (XN % 1000000) / 10000, xn,
+ (t) ? "" : "in");
+ pr_info("HSIO bus clock: %d.%02dMHz\n",
+ HSS / 1000000, (HSS % 1000000) / 10000);
+ }
+
+ return CLK;
+}
+
+/*
+ * Return the current static memory controller clock frequency
+ * in units of 10kHz
+ */
+unsigned int pxa3xx_get_memclk_frequency_10khz(void)
+{
+ unsigned long acsr;
+ unsigned int smcfs, clk = 0;
+
+ acsr = ACSR;
+
+ smcfs = (acsr >> 23) & 0x7;
+ clk = (acsr & ACCR_D0CS) ? RO_CLK : smcfs_mult[smcfs] * BASE_CLK;
+
+ return (clk / 10000);
+}
+
+/*
+ * Return the current HSIO bus clock frequency
+ */
+static unsigned long clk_pxa3xx_hsio_getrate(struct clk *clk)
+{
+ unsigned long acsr;
+ unsigned int hss, hsio_clk;
+
+ acsr = ACSR;
+
+ hss = (acsr >> 14) & 0x3;
+ hsio_clk = (acsr & ACCR_D0CS) ? RO_CLK : hss_mult[hss] * BASE_CLK;
+
+ return hsio_clk;
+}
+
+static void clk_pxa3xx_cken_enable(struct clk *clk)
+{
+ unsigned long mask = 1ul << (clk->cken & 0x1f);
+
+ local_irq_disable();
+
+ if (clk->cken < 32)
+ CKENA |= mask;
+ else
+ CKENB |= mask;
+
+ local_irq_enable();
+}
+
+static void clk_pxa3xx_cken_disable(struct clk *clk)
+{
+ unsigned long mask = 1ul << (clk->cken & 0x1f);
+
+ local_irq_disable();
+
+ if (clk->cken < 32)
+ CKENA &= ~mask;
+ else
+ CKENB &= ~mask;
+
+ local_irq_enable();
+}
+
+static const struct clkops clk_pxa3xx_hsio_ops = {
+ .enable = clk_pxa3xx_cken_enable,
+ .disable = clk_pxa3xx_cken_disable,
+ .getrate = clk_pxa3xx_hsio_getrate,
+};
+
+static struct clk pxa3xx_clks[] = {
+ INIT_CK("LCDCLK", LCD, &clk_pxa3xx_hsio_ops, &pxa_device_fb.dev),
+ INIT_CK("CAMCLK", CAMERA, &clk_pxa3xx_hsio_ops, NULL),
+
+ INIT_CKEN("UARTCLK", FFUART, 14857000, 1, &pxa_device_ffuart.dev),
+ INIT_CKEN("UARTCLK", BTUART, 14857000, 1, &pxa_device_btuart.dev),
+ INIT_CKEN("UARTCLK", STUART, 14857000, 1, NULL),
+
+ INIT_CKEN("I2CCLK", I2C, 32842000, 0, &pxa_device_i2c.dev),
+ INIT_CKEN("UDCCLK", UDC, 48000000, 5, &pxa_device_udc.dev),
+};
+
+void __init pxa3xx_init_irq(void)
+{
+ /* enable CP6 access */
+ u32 value;
+ __asm__ __volatile__("mrc p15, 0, %0, c15, c1, 0\n": "=r"(value));
+ value |= (1 << 6);
+ __asm__ __volatile__("mcr p15, 0, %0, c15, c1, 0\n": :"r"(value));
+
+ pxa_init_irq_low();
+ pxa_init_irq_high();
+ pxa_init_irq_gpio(128);
+}
+
+/*
+ * device registration specific to PXA3xx.
+ */
+
+static struct platform_device *devices[] __initdata = {
+ &pxa_device_mci,
+ &pxa_device_udc,
+ &pxa_device_fb,
+ &pxa_device_ffuart,
+ &pxa_device_btuart,
+ &pxa_device_stuart,
+ &pxa_device_i2c,
+ &pxa_device_i2s,
+ &pxa_device_ficp,
+ &pxa_device_rtc,
+};
+
+static int __init pxa3xx_init(void)
+{
+ int ret = 0;
+
+ if (cpu_is_pxa3xx()) {
+ clks_register(pxa3xx_clks, ARRAY_SIZE(pxa3xx_clks));
+
+ if ((ret = pxa_init_dma(32)))
+ return ret;
+
+ return platform_add_devices(devices, ARRAY_SIZE(devices));
+ }
+ return 0;
+}
+
+subsys_initcall(pxa3xx_init);
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c
index 98d27e646b09..fbfa1920353d 100644
--- a/arch/arm/mach-pxa/time.c
+++ b/arch/arm/mach-pxa/time.c
@@ -16,10 +16,48 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/clockchips.h>
+#include <linux/sched.h>
+#include <asm/div64.h>
+#include <asm/cnt32_to_63.h>
#include <asm/mach/irq.h>
#include <asm/mach/time.h>
#include <asm/arch/pxa-regs.h>
+#include <asm/mach-types.h>
+
+/*
+ * This is PXA's sched_clock implementation. This has a resolution
+ * of at least 308 ns and a maximum value of 208 days.
+ *
+ * The return value is guaranteed to be monotonic in that range as
+ * long as there is always less than 582 seconds between successive
+ * calls to sched_clock() which should always be the case in practice.
+ */
+
+#define OSCR2NS_SCALE_FACTOR 10
+
+static unsigned long oscr2ns_scale;
+
+static void __init set_oscr2ns_scale(unsigned long oscr_rate)
+{
+ unsigned long long v = 1000000000ULL << OSCR2NS_SCALE_FACTOR;
+ do_div(v, oscr_rate);
+ oscr2ns_scale = v;
+ /*
+ * We want an even value to automatically clear the top bit
+ * returned by cnt32_to_63() without an additional run time
+ * instruction. So if the LSB is 1 then round it up.
+ */
+ if (oscr2ns_scale & 1)
+ oscr2ns_scale++;
+}
+
+unsigned long long sched_clock(void)
+{
+ unsigned long long v = cnt32_to_63(OSCR);
+ return (v * oscr2ns_scale) >> OSCR2NS_SCALE_FACTOR;
+}
+
static irqreturn_t
pxa_ost0_interrupt(int irq, void *dev_id)
@@ -30,6 +68,7 @@ pxa_ost0_interrupt(int irq, void *dev_id)
if (c->mode == CLOCK_EVT_MODE_ONESHOT) {
/* Disarm the compare/match, signal the event. */
OIER &= ~OIER_E0;
+ OSSR = OSSR_M0;
c->event_handler(c);
} else if (c->mode == CLOCK_EVT_MODE_PERIODIC) {
/* Call the event handler as many times as necessary
@@ -62,9 +101,9 @@ pxa_ost0_interrupt(int irq, void *dev_id)
* anything that might put us "very close".
*/
#define MIN_OSCR_DELTA 16
- do {
+ do {
OSSR = OSSR_M0;
- next_match = (OSMR0 += LATCH);
+ next_match = (OSMR0 += LATCH);
c->event_handler(c);
} while (((signed long)(next_match - OSCR) <= MIN_OSCR_DELTA)
&& (c->mode == CLOCK_EVT_MODE_PERIODIC));
@@ -76,14 +115,16 @@ pxa_ost0_interrupt(int irq, void *dev_id)
static int
pxa_osmr0_set_next_event(unsigned long delta, struct clock_event_device *dev)
{
- unsigned long irqflags;
+ unsigned long flags, next, oscr;
- raw_local_irq_save(irqflags);
- OSMR0 = OSCR + delta;
- OSSR = OSSR_M0;
+ raw_local_irq_save(flags);
OIER |= OIER_E0;
- raw_local_irq_restore(irqflags);
- return 0;
+ next = OSCR + delta;
+ OSMR0 = next;
+ oscr = OSCR;
+ raw_local_irq_restore(flags);
+
+ return (signed)(next - oscr) <= MIN_OSCR_DELTA ? -ETIME : 0;
}
static void
@@ -94,15 +135,16 @@ pxa_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *dev)
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
raw_local_irq_save(irqflags);
- OSMR0 = OSCR + LATCH;
OSSR = OSSR_M0;
OIER |= OIER_E0;
+ OSMR0 = OSCR + LATCH;
raw_local_irq_restore(irqflags);
break;
case CLOCK_EVT_MODE_ONESHOT:
raw_local_irq_save(irqflags);
OIER &= ~OIER_E0;
+ OSSR = OSSR_M0;
raw_local_irq_restore(irqflags);
break;
@@ -111,8 +153,12 @@ pxa_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *dev)
/* initializing, released, or preparing for suspend */
raw_local_irq_save(irqflags);
OIER &= ~OIER_E0;
+ OSSR = OSSR_M0;
raw_local_irq_restore(irqflags);
break;
+
+ case CLOCK_EVT_MODE_RESUME:
+ break;
}
}
@@ -149,18 +195,29 @@ static struct irqaction pxa_ost0_irq = {
static void __init pxa_timer_init(void)
{
+ unsigned long clock_tick_rate;
+
OIER = 0;
OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3;
+ if (cpu_is_pxa21x() || cpu_is_pxa25x())
+ clock_tick_rate = 3686400;
+ else if (machine_is_mainstone())
+ clock_tick_rate = 3249600;
+ else
+ clock_tick_rate = 3250000;
+
+ set_oscr2ns_scale(clock_tick_rate);
+
ckevt_pxa_osmr0.mult =
- div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, ckevt_pxa_osmr0.shift);
+ div_sc(clock_tick_rate, NSEC_PER_SEC, ckevt_pxa_osmr0.shift);
ckevt_pxa_osmr0.max_delta_ns =
clockevent_delta2ns(0x7fffffff, &ckevt_pxa_osmr0);
ckevt_pxa_osmr0.min_delta_ns =
clockevent_delta2ns(MIN_OSCR_DELTA, &ckevt_pxa_osmr0) + 1;
cksrc_pxa_oscr0.mult =
- clocksource_hz2mult(CLOCK_TICK_RATE, cksrc_pxa_oscr0.shift);
+ clocksource_hz2mult(clock_tick_rate, cksrc_pxa_oscr0.shift);
setup_irq(IRQ_OST0, &pxa_ost0_irq);
diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c
new file mode 100644
index 000000000000..743a87b2faa1
--- /dev/null
+++ b/arch/arm/mach-pxa/zylonite.c
@@ -0,0 +1,184 @@
+/*
+ * linux/arch/arm/mach-pxa/zylonite.c
+ *
+ * Support for the PXA3xx Development Platform (aka Zylonite)
+ *
+ * Copyright (C) 2006 Marvell International Ltd.
+ *
+ * 2007-09-04: eric miao <eric.miao@marvell.com>
+ * rewrite to align with latest kernel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/hardware.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/pxafb.h>
+#include <asm/arch/zylonite.h>
+
+#include "generic.h"
+
+int gpio_backlight;
+int gpio_eth_irq;
+
+int lcd_id;
+int lcd_orientation;
+
+static struct resource smc91x_resources[] = {
+ [0] = {
+ .start = ZYLONITE_ETH_PHYS + 0x300,
+ .end = ZYLONITE_ETH_PHYS + 0xfffff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = -1, /* for run-time assignment */
+ .end = -1,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device smc91x_device = {
+ .name = "smc91x",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(smc91x_resources),
+ .resource = smc91x_resources,
+};
+
+#if defined(CONFIG_FB_PXA) || (CONFIG_FB_PXA_MODULES)
+static void zylonite_backlight_power(int on)
+{
+ gpio_set_value(gpio_backlight, on);
+}
+
+static struct pxafb_mode_info toshiba_ltm035a776c_mode = {
+ .pixclock = 110000,
+ .xres = 240,
+ .yres = 320,
+ .bpp = 16,
+ .hsync_len = 4,
+ .left_margin = 6,
+ .right_margin = 4,
+ .vsync_len = 2,
+ .upper_margin = 2,
+ .lower_margin = 3,
+ .sync = FB_SYNC_VERT_HIGH_ACT,
+};
+
+static struct pxafb_mode_info toshiba_ltm04c380k_mode = {
+ .pixclock = 50000,
+ .xres = 640,
+ .yres = 480,
+ .bpp = 16,
+ .hsync_len = 1,
+ .left_margin = 0x9f,
+ .right_margin = 1,
+ .vsync_len = 44,
+ .upper_margin = 0,
+ .lower_margin = 0,
+ .sync = FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
+};
+
+static struct pxafb_mach_info zylonite_toshiba_lcd_info = {
+ .num_modes = 1,
+ .lccr0 = LCCR0_Act,
+ .lccr3 = LCCR3_PCP,
+ .pxafb_backlight_power = zylonite_backlight_power,
+};
+
+static struct pxafb_mode_info sharp_ls037_modes[] = {
+ [0] = {
+ .pixclock = 158000,
+ .xres = 240,
+ .yres = 320,
+ .bpp = 16,
+ .hsync_len = 4,
+ .left_margin = 39,
+ .right_margin = 39,
+ .vsync_len = 1,
+ .upper_margin = 2,
+ .lower_margin = 3,
+ .sync = 0,
+ },
+ [1] = {
+ .pixclock = 39700,
+ .xres = 480,
+ .yres = 640,
+ .bpp = 16,
+ .hsync_len = 8,
+ .left_margin = 81,
+ .right_margin = 81,
+ .vsync_len = 1,
+ .upper_margin = 2,
+ .lower_margin = 7,
+ .sync = 0,
+ },
+};
+
+static struct pxafb_mach_info zylonite_sharp_lcd_info = {
+ .modes = sharp_ls037_modes,
+ .num_modes = 2,
+ .lccr0 = LCCR0_Act,
+ .lccr3 = LCCR3_PCP | LCCR3_HSP | LCCR3_VSP,
+ .pxafb_backlight_power = zylonite_backlight_power,
+};
+
+static void __init zylonite_init_lcd(void)
+{
+ /* backlight GPIO: output, default on */
+ gpio_direction_output(gpio_backlight, 1);
+
+ if (lcd_id & 0x20) {
+ set_pxa_fb_info(&zylonite_sharp_lcd_info);
+ return;
+ }
+
+ /* legacy LCD panels, it would be handy here if LCD panel type can
+ * be decided at run-time
+ */
+ if (1)
+ zylonite_toshiba_lcd_info.modes = &toshiba_ltm035a776c_mode;
+ else
+ zylonite_toshiba_lcd_info.modes = &toshiba_ltm04c380k_mode;
+
+ set_pxa_fb_info(&zylonite_toshiba_lcd_info);
+}
+#else
+static inline void zylonite_init_lcd(void) {}
+#endif
+
+static void __init zylonite_init(void)
+{
+ /* board-processor specific initialization */
+ zylonite_pxa300_init();
+ zylonite_pxa320_init();
+
+ /*
+ * Note: We depend that the bootloader set
+ * the correct value to MSC register for SMC91x.
+ */
+ smc91x_resources[1].start = gpio_to_irq(gpio_eth_irq);
+ smc91x_resources[1].end = gpio_to_irq(gpio_eth_irq);
+ platform_device_register(&smc91x_device);
+
+ zylonite_init_lcd();
+}
+
+MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)")
+ .phys_io = 0x40000000,
+ .boot_params = 0xa0000100,
+ .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
+ .map_io = pxa_map_io,
+ .init_irq = pxa3xx_init_irq,
+ .timer = &pxa_timer,
+ .init_machine = zylonite_init,
+MACHINE_END
diff --git a/arch/arm/mach-pxa/zylonite_pxa300.c b/arch/arm/mach-pxa/zylonite_pxa300.c
new file mode 100644
index 000000000000..1832bc316501
--- /dev/null
+++ b/arch/arm/mach-pxa/zylonite_pxa300.c
@@ -0,0 +1,188 @@
+/*
+ * linux/arch/arm/mach-pxa/zylonite_pxa300.c
+ *
+ * PXA300/PXA310 specific support code for the
+ * PXA3xx Development Platform (aka Zylonite)
+ *
+ * Copyright (C) 2007 Marvell Internation Ltd.
+ * 2007-08-21: eric miao <eric.miao@marvell.com>
+ * initial version
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/gpio.h>
+#include <asm/arch/mfp-pxa300.h>
+#include <asm/arch/zylonite.h>
+
+#define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x)
+
+/* PXA300/PXA310 common configurations */
+static mfp_cfg_t common_mfp_cfg[] __initdata = {
+ /* LCD */
+ GPIO54_LCD_LDD_0,
+ GPIO55_LCD_LDD_1,
+ GPIO56_LCD_LDD_2,
+ GPIO57_LCD_LDD_3,
+ GPIO58_LCD_LDD_4,
+ GPIO59_LCD_LDD_5,
+ GPIO60_LCD_LDD_6,
+ GPIO61_LCD_LDD_7,
+ GPIO62_LCD_LDD_8,
+ GPIO63_LCD_LDD_9,
+ GPIO64_LCD_LDD_10,
+ GPIO65_LCD_LDD_11,
+ GPIO66_LCD_LDD_12,
+ GPIO67_LCD_LDD_13,
+ GPIO68_LCD_LDD_14,
+ GPIO69_LCD_LDD_15,
+ GPIO70_LCD_LDD_16,
+ GPIO71_LCD_LDD_17,
+ GPIO72_LCD_FCLK,
+ GPIO73_LCD_LCLK,
+ GPIO74_LCD_PCLK,
+ GPIO75_LCD_BIAS,
+ GPIO76_LCD_VSYNC,
+ GPIO127_LCD_CS_N,
+
+ /* BTUART */
+ GPIO111_UART2_RTS,
+ GPIO112_UART2_RXD,
+ GPIO113_UART2_TXD,
+ GPIO114_UART2_CTS,
+
+ /* STUART */
+ GPIO109_UART3_TXD,
+ GPIO110_UART3_RXD,
+
+ /* AC97 */
+ GPIO23_AC97_nACRESET,
+ GPIO24_AC97_SYSCLK,
+ GPIO29_AC97_BITCLK,
+ GPIO25_AC97_SDATA_IN_0,
+ GPIO27_AC97_SDATA_OUT,
+ GPIO28_AC97_SYNC,
+
+ /* Keypad */
+ GPIO107_KP_DKIN_0,
+ GPIO108_KP_DKIN_1,
+ GPIO115_KP_MKIN_0,
+ GPIO116_KP_MKIN_1,
+ GPIO117_KP_MKIN_2,
+ GPIO118_KP_MKIN_3,
+ GPIO119_KP_MKIN_4,
+ GPIO120_KP_MKIN_5,
+ GPIO2_2_KP_MKIN_6,
+ GPIO3_2_KP_MKIN_7,
+ GPIO121_KP_MKOUT_0,
+ GPIO122_KP_MKOUT_1,
+ GPIO123_KP_MKOUT_2,
+ GPIO124_KP_MKOUT_3,
+ GPIO125_KP_MKOUT_4,
+ GPIO4_2_KP_MKOUT_5,
+ GPIO5_2_KP_MKOUT_6,
+ GPIO6_2_KP_MKOUT_7,
+};
+
+static mfp_cfg_t pxa300_mfp_cfg[] __initdata = {
+ /* FFUART */
+ GPIO30_UART1_RXD,
+ GPIO31_UART1_TXD,
+ GPIO32_UART1_CTS,
+ GPIO37_UART1_RTS,
+ GPIO33_UART1_DCD,
+ GPIO34_UART1_DSR,
+ GPIO35_UART1_RI,
+ GPIO36_UART1_DTR,
+
+ /* Ethernet */
+ GPIO2_nCS3,
+ GPIO99_GPIO,
+};
+
+static mfp_cfg_t pxa310_mfp_cfg[] __initdata = {
+ /* FFUART */
+ GPIO99_UART1_RXD,
+ GPIO100_UART1_TXD,
+ GPIO101_UART1_CTS,
+ GPIO106_UART1_RTS,
+
+ /* Ethernet */
+ GPIO2_nCS3,
+ GPIO102_GPIO,
+};
+
+#define NUM_LCD_DETECT_PINS 7
+
+static int lcd_detect_pins[] __initdata = {
+ MFP_PIN_GPIO71, /* LCD_LDD_17 - ORIENT */
+ MFP_PIN_GPIO70, /* LCD_LDD_16 - LCDID[5] */
+ MFP_PIN_GPIO75, /* LCD_BIAS - LCDID[4] */
+ MFP_PIN_GPIO73, /* LCD_LCLK - LCDID[3] */
+ MFP_PIN_GPIO72, /* LCD_FCLK - LCDID[2] */
+ MFP_PIN_GPIO127,/* LCD_CS_N - LCDID[1] */
+ MFP_PIN_GPIO76, /* LCD_VSYNC - LCDID[0] */
+};
+
+static void __init zylonite_detect_lcd_panel(void)
+{
+ unsigned long mfpr_save[NUM_LCD_DETECT_PINS];
+ int i, gpio, id = 0;
+
+ /* save the original MFP settings of these pins and configure
+ * them as GPIO Input, DS01X, Pull Neither, Edge Clear
+ */
+ for (i = 0; i < NUM_LCD_DETECT_PINS; i++) {
+ mfpr_save[i] = pxa3xx_mfp_read(lcd_detect_pins[i]);
+ pxa3xx_mfp_write(lcd_detect_pins[i], 0x8440);
+ }
+
+ for (i = 0; i < NUM_LCD_DETECT_PINS; i++) {
+ id = id << 1;
+ gpio = mfp_to_gpio(lcd_detect_pins[i]);
+ gpio_direction_input(gpio);
+
+ if (gpio_get_value(gpio))
+ id = id | 0x1;
+ }
+
+ /* lcd id, flush out bit 1 */
+ lcd_id = id & 0x3d;
+
+ /* lcd orientation, portrait or landscape */
+ lcd_orientation = (id >> 6) & 0x1;
+
+ /* restore the original MFP settings */
+ for (i = 0; i < NUM_LCD_DETECT_PINS; i++)
+ pxa3xx_mfp_write(lcd_detect_pins[i], mfpr_save[i]);
+}
+
+void __init zylonite_pxa300_init(void)
+{
+ if (cpu_is_pxa300() || cpu_is_pxa310()) {
+ /* initialize MFP */
+ pxa3xx_mfp_config(ARRAY_AND_SIZE(common_mfp_cfg));
+
+ /* detect LCD panel */
+ zylonite_detect_lcd_panel();
+
+ /* GPIO pin assignment */
+ gpio_backlight = mfp_to_gpio(MFP_PIN_GPIO20);
+ }
+
+ if (cpu_is_pxa300()) {
+ pxa3xx_mfp_config(ARRAY_AND_SIZE(pxa300_mfp_cfg));
+ gpio_eth_irq = mfp_to_gpio(MFP_PIN_GPIO99);
+ }
+
+ if (cpu_is_pxa310()) {
+ pxa3xx_mfp_config(ARRAY_AND_SIZE(pxa310_mfp_cfg));
+ gpio_eth_irq = mfp_to_gpio(MFP_PIN_GPIO102);
+ }
+}
diff --git a/arch/arm/mach-pxa/zylonite_pxa320.c b/arch/arm/mach-pxa/zylonite_pxa320.c
new file mode 100644
index 000000000000..94c715808b59
--- /dev/null
+++ b/arch/arm/mach-pxa/zylonite_pxa320.c
@@ -0,0 +1,173 @@
+/*
+ * linux/arch/arm/mach-pxa/zylonite_pxa320.c
+ *
+ * PXA320 specific support code for the
+ * PXA3xx Development Platform (aka Zylonite)
+ *
+ * Copyright (C) 2007 Marvell Internation Ltd.
+ * 2007-08-21: eric miao <eric.miao@marvell.com>
+ * initial version
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/mfp-pxa320.h>
+#include <asm/arch/zylonite.h>
+
+#define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x)
+
+static mfp_cfg_t mfp_cfg[] __initdata = {
+ /* LCD */
+ GPIO6_2_LCD_LDD_0,
+ GPIO7_2_LCD_LDD_1,
+ GPIO8_2_LCD_LDD_2,
+ GPIO9_2_LCD_LDD_3,
+ GPIO10_2_LCD_LDD_4,
+ GPIO11_2_LCD_LDD_5,
+ GPIO12_2_LCD_LDD_6,
+ GPIO13_2_LCD_LDD_7,
+ GPIO63_LCD_LDD_8,
+ GPIO64_LCD_LDD_9,
+ GPIO65_LCD_LDD_10,
+ GPIO66_LCD_LDD_11,
+ GPIO67_LCD_LDD_12,
+ GPIO68_LCD_LDD_13,
+ GPIO69_LCD_LDD_14,
+ GPIO70_LCD_LDD_15,
+ GPIO71_LCD_LDD_16,
+ GPIO72_LCD_LDD_17,
+ GPIO73_LCD_CS_N,
+ GPIO74_LCD_VSYNC,
+ GPIO14_2_LCD_FCLK,
+ GPIO15_2_LCD_LCLK,
+ GPIO16_2_LCD_PCLK,
+ GPIO17_2_LCD_BIAS,
+
+ /* FFUART */
+ GPIO41_UART1_RXD,
+ GPIO42_UART1_TXD,
+ GPIO43_UART1_CTS,
+ GPIO44_UART1_DCD,
+ GPIO45_UART1_DSR,
+ GPIO46_UART1_RI,
+ GPIO47_UART1_DTR,
+ GPIO48_UART1_RTS,
+
+ /* AC97 */
+ GPIO34_AC97_SYSCLK,
+ GPIO35_AC97_SDATA_IN_0,
+ GPIO37_AC97_SDATA_OUT,
+ GPIO38_AC97_SYNC,
+ GPIO39_AC97_BITCLK,
+ GPIO40_AC97_nACRESET,
+
+ /* I2C */
+ GPIO32_I2C_SCL,
+ GPIO33_I2C_SDA,
+
+ /* Keypad */
+ GPIO105_KP_DKIN_0,
+ GPIO106_KP_DKIN_1,
+ GPIO113_KP_MKIN_0,
+ GPIO114_KP_MKIN_1,
+ GPIO115_KP_MKIN_2,
+ GPIO116_KP_MKIN_3,
+ GPIO117_KP_MKIN_4,
+ GPIO118_KP_MKIN_5,
+ GPIO119_KP_MKIN_6,
+ GPIO120_KP_MKIN_7,
+ GPIO121_KP_MKOUT_0,
+ GPIO122_KP_MKOUT_1,
+ GPIO123_KP_MKOUT_2,
+ GPIO124_KP_MKOUT_3,
+ GPIO125_KP_MKOUT_4,
+ GPIO126_KP_MKOUT_5,
+ GPIO127_KP_MKOUT_6,
+ GPIO5_2_KP_MKOUT_7,
+
+ /* Ethernet */
+ GPIO4_nCS3,
+ GPIO90_GPIO,
+};
+
+#define NUM_LCD_DETECT_PINS 7
+
+static int lcd_detect_pins[] __initdata = {
+ MFP_PIN_GPIO72, /* LCD_LDD_17 - ORIENT */
+ MFP_PIN_GPIO71, /* LCD_LDD_16 - LCDID[5] */
+ MFP_PIN_GPIO17_2, /* LCD_BIAS - LCDID[4] */
+ MFP_PIN_GPIO15_2, /* LCD_LCLK - LCDID[3] */
+ MFP_PIN_GPIO14_2, /* LCD_FCLK - LCDID[2] */
+ MFP_PIN_GPIO73, /* LCD_CS_N - LCDID[1] */
+ MFP_PIN_GPIO74, /* LCD_VSYNC - LCDID[0] */
+ /*
+ * set the MFP_PIN_GPIO 14/15/17 to alternate function other than
+ * GPIO to avoid input level confliction with 14_2, 15_2, 17_2
+ */
+ MFP_PIN_GPIO14,
+ MFP_PIN_GPIO15,
+ MFP_PIN_GPIO17,
+};
+
+static int lcd_detect_mfpr[] __initdata = {
+ /* AF0, DS 1X, Pull Neither, Edge Clear */
+ 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440,
+ 0xc442, /* Backlight, Pull-Up, AF2 */
+ 0x8445, /* AF5 */
+ 0x8445, /* AF5 */
+};
+
+static void __init zylonite_detect_lcd_panel(void)
+{
+ unsigned long mfpr_save[ARRAY_SIZE(lcd_detect_pins)];
+ int i, gpio, id = 0;
+
+ /* save the original MFP settings of these pins and configure them
+ * as GPIO Input, DS01X, Pull Neither, Edge Clear
+ */
+ for (i = 0; i < ARRAY_SIZE(lcd_detect_pins); i++) {
+ mfpr_save[i] = pxa3xx_mfp_read(lcd_detect_pins[i]);
+ pxa3xx_mfp_write(lcd_detect_pins[i], lcd_detect_mfpr[i]);
+ }
+
+ for (i = 0; i < NUM_LCD_DETECT_PINS; i++) {
+ id = id << 1;
+ gpio = mfp_to_gpio(lcd_detect_pins[i]);
+ gpio_direction_input(gpio);
+
+ if (gpio_get_value(gpio))
+ id = id | 0x1;
+ }
+
+ /* lcd id, flush out bit 1 */
+ lcd_id = id & 0x3d;
+
+ /* lcd orientation, portrait or landscape */
+ lcd_orientation = (id >> 6) & 0x1;
+
+ /* restore the original MFP settings */
+ for (i = 0; i < ARRAY_SIZE(lcd_detect_pins); i++)
+ pxa3xx_mfp_write(lcd_detect_pins[i], mfpr_save[i]);
+}
+
+void __init zylonite_pxa320_init(void)
+{
+ if (cpu_is_pxa320()) {
+ /* initialize MFP */
+ pxa3xx_mfp_config(ARRAY_AND_SIZE(mfp_cfg));
+
+ /* detect LCD panel */
+ zylonite_detect_lcd_panel();
+
+ /* GPIO pin assignment */
+ gpio_backlight = mfp_to_gpio(MFP_PIN_GPIO14);
+ gpio_eth_irq = mfp_to_gpio(MFP_PIN_GPIO9);
+ }
+}
diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c
index cab9d6265e9e..2bfaa6102025 100644
--- a/arch/arm/mach-s3c2410/clock.c
+++ b/arch/arm/mach-s3c2410/clock.c
@@ -238,7 +238,7 @@ int __init s3c2410_baseclk_add(void)
}
/* We must be careful disabling the clocks we are not intending to
- * be using at boot time, as subsytems such as the LCD which do
+ * be using at boot time, as subsystems such as the LCD which do
* their own DMA requests to the bus can cause the system to lockup
* if they where in the middle of requesting bus access.
*
diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c
index 80d83739ab9f..8f12e855ef5f 100644
--- a/arch/arm/mach-s3c2410/dma.c
+++ b/arch/arm/mach-s3c2410/dma.c
@@ -145,7 +145,7 @@ static struct s3c24xx_dma_order __initdata s3c2410_dma_order = {
},
};
-static int s3c2410_dma_add(struct sys_device *sysdev)
+static int __init s3c2410_dma_add(struct sys_device *sysdev)
{
s3c2410_dma_init();
s3c24xx_dma_order_set(&s3c2410_dma_order);
diff --git a/arch/arm/mach-s3c2410/mach-amlm5900.c b/arch/arm/mach-s3c2410/mach-amlm5900.c
index 43bb5e106302..a67a0685664d 100644
--- a/arch/arm/mach-s3c2410/mach-amlm5900.c
+++ b/arch/arm/mach-s3c2410/mach-amlm5900.c
@@ -168,13 +168,31 @@ static void __init amlm5900_map_io(void)
}
#ifdef CONFIG_FB_S3C2410
-static struct s3c2410fb_mach_info __initdata amlm5900_lcd_info = {
+static struct s3c2410fb_display __initdata amlm5900_lcd_info = {
.width = 160,
.height = 160,
-/* commented out until stn patch is submitted
-* .type = S3C2410_LCDCON1_STN4,
-*/
+ .type = S3C2410_LCDCON1_STN4,
+
+ .pixclock = 680000, /* HCLK = 100MHz */
+ .xres = 160,
+ .yres = 160,
+ .bpp = 4,
+ .left_margin = 1 << (4 + 3),
+ .right_margin = 8 << 3,
+ .hsync_len = 48,
+ .upper_margin = 0,
+ .lower_margin = 0,
+
+ .lcdcon5 = 0x00000001,
+};
+
+static struct s3c2410fb_mach_info __initdata amlm5900_fb_info = {
+
+ .displays = &amlm5900_lcd_info,
+ .num_displays = 1,
+ .default_display = 0,
+
.gpccon = 0xaaaaaaaa,
.gpccon_mask = 0xffffffff,
.gpcup = 0x0000ffff,
@@ -184,32 +202,6 @@ static struct s3c2410fb_mach_info __initdata amlm5900_lcd_info = {
.gpdcon_mask = 0xffffffff,
.gpdup = 0x0000ffff,
.gpdup_mask = 0xffffffff,
-
- .xres = {
- .min = 160,
- .max = 160,
- .defval = 160,
- },
-
- .yres = {
- .min = 160,
- .max = 160,
- .defval = 160,
- },
-
- .bpp = {
- .min = 4,
- .max = 4,
- .defval = 4,
- },
-
- .regs = {
- .lcdcon1 = 0x00008225,
- .lcdcon2 = 0x0027c000,
- .lcdcon3 = 0x00182708,
- .lcdcon4 = 0x00000002,
- .lcdcon5 = 0x00000001,
- }
};
#endif
@@ -239,7 +231,7 @@ static void __init amlm5900_init(void)
{
amlm5900_init_pm();
#ifdef CONFIG_FB_S3C2410
- s3c24xx_fb_set_platdata(&amlm5900_lcd_info);
+ s3c24xx_fb_set_platdata(&amlm5900_fb_info);
#endif
platform_add_devices(amlm5900_devices, ARRAY_SIZE(amlm5900_devices));
}
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index bc926992b4e4..587864fe25fb 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -467,35 +467,70 @@ static struct platform_device bast_device_axpp = {
/* LCD/VGA controller */
-static struct s3c2410fb_mach_info __initdata bast_lcd_info = {
- .width = 640,
- .height = 480,
-
- .xres = {
- .min = 320,
- .max = 1024,
- .defval = 640,
- },
+static struct s3c2410fb_display __initdata bast_lcd_info[] = {
+ {
+ .type = S3C2410_LCDCON1_TFT,
+ .width = 640,
+ .height = 480,
+
+ .pixclock = 33333,
+ .xres = 640,
+ .yres = 480,
+ .bpp = 4,
+ .left_margin = 40,
+ .right_margin = 20,
+ .hsync_len = 88,
+ .upper_margin = 30,
+ .lower_margin = 32,
+ .vsync_len = 3,
- .yres = {
- .min = 240,
- .max = 600,
- .defval = 480,
+ .lcdcon5 = 0x00014b02,
},
+ {
+ .type = S3C2410_LCDCON1_TFT,
+ .width = 640,
+ .height = 480,
+
+ .pixclock = 33333,
+ .xres = 640,
+ .yres = 480,
+ .bpp = 8,
+ .left_margin = 40,
+ .right_margin = 20,
+ .hsync_len = 88,
+ .upper_margin = 30,
+ .lower_margin = 32,
+ .vsync_len = 3,
- .bpp = {
- .min = 4,
- .max = 16,
- .defval = 8,
+ .lcdcon5 = 0x00014b02,
},
+ {
+ .type = S3C2410_LCDCON1_TFT,
+ .width = 640,
+ .height = 480,
+
+ .pixclock = 33333,
+ .xres = 640,
+ .yres = 480,
+ .bpp = 16,
+ .left_margin = 40,
+ .right_margin = 20,
+ .hsync_len = 88,
+ .upper_margin = 30,
+ .lower_margin = 32,
+ .vsync_len = 3,
- .regs = {
- .lcdcon1 = 0x00000176,
- .lcdcon2 = 0x1d77c7c2,
- .lcdcon3 = 0x013a7f13,
- .lcdcon4 = 0x00000057,
.lcdcon5 = 0x00014b02,
- }
+ },
+};
+
+/* LCD/VGA controller */
+
+static struct s3c2410fb_mach_info __initdata bast_fb_info = {
+
+ .displays = bast_lcd_info,
+ .num_displays = ARRAY_SIZE(bast_lcd_info),
+ .default_display = 4,
};
/* Standard BAST devices */
@@ -552,7 +587,7 @@ static void __init bast_map_io(void)
static void __init bast_init(void)
{
- s3c24xx_fb_set_platdata(&bast_lcd_info);
+ s3c24xx_fb_set_platdata(&bast_fb_info);
platform_add_devices(bast_devices, ARRAY_SIZE(bast_devices));
}
diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
index 9a172b4ad720..7c1145e87c12 100644
--- a/arch/arm/mach-s3c2410/mach-h1940.c
+++ b/arch/arm/mach-s3c2410/mach-h1940.c
@@ -133,29 +133,31 @@ static struct s3c2410_udc_mach_info h1940_udc_cfg __initdata = {
/**
* Set lcd on or off
**/
-static struct s3c2410fb_mach_info h1940_lcdcfg __initdata = {
- .fixed_syncs= 1,
- .regs={
- .lcdcon1= S3C2410_LCDCON1_TFT16BPP | \
- S3C2410_LCDCON1_TFT | \
- S3C2410_LCDCON1_CLKVAL(0x0C),
-
- .lcdcon2= S3C2410_LCDCON2_VBPD(7) | \
- S3C2410_LCDCON2_LINEVAL(319) | \
- S3C2410_LCDCON2_VFPD(6) | \
- S3C2410_LCDCON2_VSPW(0),
-
- .lcdcon3= S3C2410_LCDCON3_HBPD(19) | \
- S3C2410_LCDCON3_HOZVAL(239) | \
- S3C2410_LCDCON3_HFPD(7),
-
- .lcdcon4= S3C2410_LCDCON4_MVAL(0) | \
- S3C2410_LCDCON4_HSPW(3),
-
- .lcdcon5= S3C2410_LCDCON5_FRM565 | \
- S3C2410_LCDCON5_INVVLINE | \
- S3C2410_LCDCON5_HWSWP,
- },
+static struct s3c2410fb_display h1940_lcd __initdata = {
+ .lcdcon5= S3C2410_LCDCON5_FRM565 | \
+ S3C2410_LCDCON5_INVVLINE | \
+ S3C2410_LCDCON5_HWSWP,
+
+ .type = S3C2410_LCDCON1_TFT,
+ .width = 240,
+ .height = 320,
+ .pixclock = 260000,
+ .xres = 240,
+ .yres = 320,
+ .bpp = 16,
+ .left_margin = 20,
+ .right_margin = 8,
+ .hsync_len = 4,
+ .upper_margin = 8,
+ .lower_margin = 7,
+ .vsync_len = 1,
+};
+
+static struct s3c2410fb_mach_info h1940_fb_info __initdata = {
+ .displays = &h1940_lcd,
+ .num_displays = 1,
+ .default_display = 0,
+
.lpcsel= 0x02,
.gpccon= 0xaa940659,
.gpccon_mask= 0xffffffff,
@@ -165,12 +167,6 @@ static struct s3c2410fb_mach_info h1940_lcdcfg __initdata = {
.gpdcon_mask= 0xffffffff,
.gpdup= 0x0000faff,
.gpdup_mask= 0xffffffff,
-
- .width= 240,
- .height= 320,
- .xres= {240,240,240},
- .yres= {320,320,320},
- .bpp= {16,16,16},
};
static struct platform_device s3c_device_leds = {
@@ -217,7 +213,7 @@ static void __init h1940_init(void)
{
u32 tmp;
- s3c24xx_fb_set_platdata(&h1940_lcdcfg);
+ s3c24xx_fb_set_platdata(&h1940_fb_info);
s3c24xx_udc_set_platdata(&h1940_udc_cfg);
/* Turn off suspend on both USB ports, and switch the
diff --git a/arch/arm/mach-s3c2410/mach-qt2410.c b/arch/arm/mach-s3c2410/mach-qt2410.c
index e670b1e1631b..a1caf4b0adac 100644
--- a/arch/arm/mach-s3c2410/mach-qt2410.c
+++ b/arch/arm/mach-s3c2410/mach-qt2410.c
@@ -95,157 +95,83 @@ static struct s3c2410_uartcfg smdk2410_uartcfgs[] = {
/* LCD driver info */
-/* Configuration for 640x480 SHARP LQ080V3DG01 */
-static struct s3c2410fb_mach_info qt2410_biglcd_cfg __initdata = {
- .regs = {
-
- .lcdcon1 = S3C2410_LCDCON1_TFT16BPP |
- S3C2410_LCDCON1_TFT |
- S3C2410_LCDCON1_CLKVAL(0x01), /* HCLK/4 */
-
- .lcdcon2 = S3C2410_LCDCON2_VBPD(18) | /* 19 */
- S3C2410_LCDCON2_LINEVAL(479) |
- S3C2410_LCDCON2_VFPD(10) | /* 11 */
- S3C2410_LCDCON2_VSPW(14), /* 15 */
-
- .lcdcon3 = S3C2410_LCDCON3_HBPD(43) | /* 44 */
- S3C2410_LCDCON3_HOZVAL(639) | /* 640 */
- S3C2410_LCDCON3_HFPD(115), /* 116 */
-
- .lcdcon4 = S3C2410_LCDCON4_MVAL(0) |
- S3C2410_LCDCON4_HSPW(95), /* 96 */
-
- .lcdcon5 = S3C2410_LCDCON5_FRM565 |
- S3C2410_LCDCON5_INVVLINE |
- S3C2410_LCDCON5_INVVFRAME |
- S3C2410_LCDCON5_PWREN |
- S3C2410_LCDCON5_HWSWP,
+static struct s3c2410fb_display qt2410_lcd_cfg[] __initdata = {
+ {
+ /* Configuration for 640x480 SHARP LQ080V3DG01 */
+ .lcdcon5 = S3C2410_LCDCON5_FRM565 |
+ S3C2410_LCDCON5_INVVLINE |
+ S3C2410_LCDCON5_INVVFRAME |
+ S3C2410_LCDCON5_PWREN |
+ S3C2410_LCDCON5_HWSWP,
+
+ .type = S3C2410_LCDCON1_TFT,
+ .width = 640,
+ .height = 480,
+
+ .pixclock = 40000, /* HCLK/4 */
+ .xres = 640,
+ .yres = 480,
+ .bpp = 16,
+ .left_margin = 44,
+ .right_margin = 116,
+ .hsync_len = 96,
+ .upper_margin = 19,
+ .lower_margin = 11,
+ .vsync_len = 15,
},
-
- .lpcsel = ((0xCE6) & ~7) | 1<<4,
-
- .width = 640,
- .height = 480,
-
- .xres = {
- .min = 640,
- .max = 640,
- .defval = 640,
- },
-
- .yres = {
- .min = 480,
- .max = 480,
- .defval = 480,
- },
-
- .bpp = {
- .min = 16,
- .max = 16,
- .defval = 16,
- },
-};
-
-/* Configuration for 480x640 toppoly TD028TTEC1 */
-static struct s3c2410fb_mach_info qt2410_prodlcd_cfg __initdata = {
- .regs = {
-
- .lcdcon1 = S3C2410_LCDCON1_TFT16BPP |
- S3C2410_LCDCON1_TFT |
- S3C2410_LCDCON1_CLKVAL(0x01), /* HCLK/4 */
-
- .lcdcon2 = S3C2410_LCDCON2_VBPD(1) | /* 2 */
- S3C2410_LCDCON2_LINEVAL(639) |/* 640 */
- S3C2410_LCDCON2_VFPD(3) | /* 4 */
- S3C2410_LCDCON2_VSPW(1), /* 2 */
-
- .lcdcon3 = S3C2410_LCDCON3_HBPD(7) | /* 8 */
- S3C2410_LCDCON3_HOZVAL(479) | /* 479 */
- S3C2410_LCDCON3_HFPD(23), /* 24 */
-
- .lcdcon4 = S3C2410_LCDCON4_MVAL(0) |
- S3C2410_LCDCON4_HSPW(7), /* 8 */
-
- .lcdcon5 = S3C2410_LCDCON5_FRM565 |
- S3C2410_LCDCON5_INVVLINE |
- S3C2410_LCDCON5_INVVFRAME |
- S3C2410_LCDCON5_PWREN |
- S3C2410_LCDCON5_HWSWP,
- },
-
- .lpcsel = ((0xCE6) & ~7) | 1<<4,
-
- .width = 480,
- .height = 640,
-
- .xres = {
- .min = 480,
- .max = 480,
- .defval = 480,
+ {
+ /* Configuration for 480x640 toppoly TD028TTEC1 */
+ .lcdcon5 = S3C2410_LCDCON5_FRM565 |
+ S3C2410_LCDCON5_INVVLINE |
+ S3C2410_LCDCON5_INVVFRAME |
+ S3C2410_LCDCON5_PWREN |
+ S3C2410_LCDCON5_HWSWP,
+
+ .type = S3C2410_LCDCON1_TFT,
+ .width = 480,
+ .height = 640,
+ .pixclock = 40000, /* HCLK/4 */
+ .xres = 480,
+ .yres = 640,
+ .bpp = 16,
+ .left_margin = 8,
+ .right_margin = 24,
+ .hsync_len = 8,
+ .upper_margin = 2,
+ .lower_margin = 4,
+ .vsync_len = 2,
},
-
- .yres = {
- .min = 640,
- .max = 640,
- .defval = 640,
- },
-
- .bpp = {
- .min = 16,
- .max = 16,
- .defval = 16,
+ {
+ /* Config for 240x320 LCD */
+ .lcdcon5 = S3C2410_LCDCON5_FRM565 |
+ S3C2410_LCDCON5_INVVLINE |
+ S3C2410_LCDCON5_INVVFRAME |
+ S3C2410_LCDCON5_PWREN |
+ S3C2410_LCDCON5_HWSWP,
+
+ .type = S3C2410_LCDCON1_TFT,
+ .width = 240,
+ .height = 320,
+ .pixclock = 100000, /* HCLK/10 */
+ .xres = 240,
+ .yres = 320,
+ .bpp = 16,
+ .left_margin = 13,
+ .right_margin = 8,
+ .hsync_len = 4,
+ .upper_margin = 2,
+ .lower_margin = 7,
+ .vsync_len = 4,
},
};
-/* Config for 240x320 LCD */
-static struct s3c2410fb_mach_info qt2410_lcd_cfg __initdata = {
- .regs = {
-
- .lcdcon1 = S3C2410_LCDCON1_TFT16BPP |
- S3C2410_LCDCON1_TFT |
- S3C2410_LCDCON1_CLKVAL(0x04),
-
- .lcdcon2 = S3C2410_LCDCON2_VBPD(1) |
- S3C2410_LCDCON2_LINEVAL(319) |
- S3C2410_LCDCON2_VFPD(6) |
- S3C2410_LCDCON2_VSPW(3),
-
- .lcdcon3 = S3C2410_LCDCON3_HBPD(12) |
- S3C2410_LCDCON3_HOZVAL(239) |
- S3C2410_LCDCON3_HFPD(7),
- .lcdcon4 = S3C2410_LCDCON4_MVAL(0) |
- S3C2410_LCDCON4_HSPW(3),
-
- .lcdcon5 = S3C2410_LCDCON5_FRM565 |
- S3C2410_LCDCON5_INVVLINE |
- S3C2410_LCDCON5_INVVFRAME |
- S3C2410_LCDCON5_PWREN |
- S3C2410_LCDCON5_HWSWP,
- },
+static struct s3c2410fb_mach_info qt2410_fb_info __initdata = {
+ .displays = qt2410_lcd_cfg,
+ .num_displays = ARRAY_SIZE(qt2410_lcd_cfg),
+ .default_display = 0,
.lpcsel = ((0xCE6) & ~7) | 1<<4,
-
- .width = 240,
- .height = 320,
-
- .xres = {
- .min = 240,
- .max = 240,
- .defval = 240,
- },
-
- .yres = {
- .min = 320,
- .max = 320,
- .defval = 320,
- },
-
- .bpp = {
- .min = 16,
- .max = 16,
- .defval = 16,
- },
};
/* CS8900 */
@@ -408,16 +334,17 @@ static void __init qt2410_machine_init(void)
switch (tft_type) {
case 'p': /* production */
- s3c24xx_fb_set_platdata(&qt2410_prodlcd_cfg);
+ qt2410_fb_info.default_display = 1;
break;
case 'b': /* big */
- s3c24xx_fb_set_platdata(&qt2410_biglcd_cfg);
+ qt2410_fb_info.default_display = 0;
break;
case 's': /* small */
default:
- s3c24xx_fb_set_platdata(&qt2410_lcd_cfg);
+ qt2410_fb_info.default_display = 2;
break;
}
+ s3c24xx_fb_set_platdata(&qt2410_fb_info);
s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPIO_OUTPUT);
s3c2410_gpio_setpin(S3C2410_GPB0, 1);
diff --git a/arch/arm/mach-s3c2412/clock.c b/arch/arm/mach-s3c2412/clock.c
index 8543dd6df391..458993601897 100644
--- a/arch/arm/mach-s3c2412/clock.c
+++ b/arch/arm/mach-s3c2412/clock.c
@@ -689,7 +689,7 @@ int __init s3c2412_baseclk_add(void)
}
/* We must be careful disabling the clocks we are not intending to
- * be using at boot time, as subsytems such as the LCD which do
+ * be using at boot time, as subsystems such as the LCD which do
* their own DMA requests to the bus can cause the system to lockup
* if they where in the middle of requesting bus access.
*
diff --git a/arch/arm/mach-s3c2412/dma.c b/arch/arm/mach-s3c2412/dma.c
index 4b9425c1bf72..53c1d5bbce19 100644
--- a/arch/arm/mach-s3c2412/dma.c
+++ b/arch/arm/mach-s3c2412/dma.c
@@ -144,7 +144,7 @@ static struct s3c24xx_dma_selection __initdata s3c2412_dma_sel = {
.map_size = ARRAY_SIZE(s3c2412_dma_mappings),
};
-static int s3c2412_dma_add(struct sys_device *sysdev)
+static int __init s3c2412_dma_add(struct sys_device *sysdev)
{
s3c2410_dma_init();
return s3c24xx_dma_init_map(&s3c2412_dma_sel);
diff --git a/arch/arm/mach-s3c2412/irq.c b/arch/arm/mach-s3c2412/irq.c
index f0d66828f965..e9d0c769f5da 100644
--- a/arch/arm/mach-s3c2412/irq.c
+++ b/arch/arm/mach-s3c2412/irq.c
@@ -38,6 +38,9 @@
#include <asm/plat-s3c24xx/irq.h>
#include <asm/plat-s3c24xx/pm.h>
+#define INTMSK(start, end) ((1 << ((end) + 1 - (start))) - 1)
+#define INTMSK_SUB(start, end) (INTMSK(start, end) << ((start - S3C2410_IRQSUB(0))))
+
/* the s3c2412 changes the behaviour of IRQ_EINT0 through IRQ_EINT3 by
* having them turn up in both the INT* and the EINT* registers. Whilst
* both show the status, they both now need to be acked when the IRQs
@@ -105,6 +108,51 @@ static struct irq_chip s3c2412_irq_eint0t4 = {
.set_type = s3c_irqext_type,
};
+#define INTBIT(x) (1 << ((x) - S3C2410_IRQSUB(0)))
+
+/* CF and SDI sub interrupts */
+
+static void s3c2412_irq_demux_cfsdi(unsigned int irq, struct irq_desc *desc)
+{
+ unsigned int subsrc, submsk;
+
+ subsrc = __raw_readl(S3C2410_SUBSRCPND);
+ submsk = __raw_readl(S3C2410_INTSUBMSK);
+
+ subsrc &= ~submsk;
+
+ if (subsrc & INTBIT(IRQ_S3C2412_SDI))
+ desc_handle_irq(IRQ_S3C2412_SDI, irq_desc + IRQ_S3C2412_SDI);
+
+ if (subsrc & INTBIT(IRQ_S3C2412_CF))
+ desc_handle_irq(IRQ_S3C2412_CF, irq_desc + IRQ_S3C2412_CF);
+}
+
+#define INTMSK_CFSDI (1UL << (IRQ_S3C2412_CFSDI - IRQ_EINT0))
+#define SUBMSK_CFSDI INTMSK_SUB(IRQ_S3C2412_SDI, IRQ_S3C2412_CF)
+
+static void s3c2412_irq_cfsdi_mask(unsigned int irqno)
+{
+ s3c_irqsub_mask(irqno, INTMSK_CFSDI, SUBMSK_CFSDI);
+}
+
+static void s3c2412_irq_cfsdi_unmask(unsigned int irqno)
+{
+ s3c_irqsub_unmask(irqno, INTMSK_CFSDI);
+}
+
+static void s3c2412_irq_cfsdi_ack(unsigned int irqno)
+{
+ s3c_irqsub_maskack(irqno, INTMSK_CFSDI, SUBMSK_CFSDI);
+}
+
+static struct irq_chip s3c2412_irq_cfsdi = {
+ .name = "s3c2412-cfsdi",
+ .ack = s3c2412_irq_cfsdi_ack,
+ .mask = s3c2412_irq_cfsdi_mask,
+ .unmask = s3c2412_irq_cfsdi_unmask,
+};
+
static int s3c2412_irq_add(struct sys_device *sysdev)
{
unsigned int irqno;
@@ -115,6 +163,16 @@ static int s3c2412_irq_add(struct sys_device *sysdev)
set_irq_flags(irqno, IRQF_VALID);
}
+ /* add demux support for CF/SDI */
+
+ set_irq_chained_handler(IRQ_S3C2412_CFSDI, s3c2412_irq_demux_cfsdi);
+
+ for (irqno = IRQ_S3C2412_SDI; irqno <= IRQ_S3C2412_CF; irqno++) {
+ set_irq_chip(irqno, &s3c2412_irq_cfsdi);
+ set_irq_handler(irqno, handle_level_irq);
+ set_irq_flags(irqno, IRQF_VALID);
+ }
+
return 0;
}
diff --git a/arch/arm/mach-s3c2412/s3c2412.c b/arch/arm/mach-s3c2412/s3c2412.c
index e0ccb404623f..4f92a1562d77 100644
--- a/arch/arm/mach-s3c2412/s3c2412.c
+++ b/arch/arm/mach-s3c2412/s3c2412.c
@@ -78,6 +78,11 @@ void __init s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no)
s3c_device_lcd.name = "s3c2412-lcd";
s3c_device_nand.name = "s3c2412-nand";
+ /* alter IRQ of SDI controller */
+
+ s3c_device_sdi.resource[1].start = IRQ_S3C2412_SDI;
+ s3c_device_sdi.resource[1].end = IRQ_S3C2412_SDI;
+
/* spi channel related changes, s3c2412/13 specific */
s3c_device_spi0.name = "s3c2412-spi";
s3c_device_spi0.resource[0].end = S3C24XX_PA_SPI + 0x24;
diff --git a/arch/arm/mach-s3c2440/dma.c b/arch/arm/mach-s3c2440/dma.c
index f509f062e749..0b1260827ac6 100644
--- a/arch/arm/mach-s3c2440/dma.c
+++ b/arch/arm/mach-s3c2440/dma.c
@@ -190,7 +190,7 @@ static struct s3c24xx_dma_order __initdata s3c2440_dma_order = {
},
};
-static int s3c2440_dma_add(struct sys_device *sysdev)
+static int __init s3c2440_dma_add(struct sys_device *sysdev)
{
s3c2410_dma_init();
s3c24xx_dma_order_set(&s3c2440_dma_order);
diff --git a/arch/arm/mach-s3c2440/mach-rx3715.c b/arch/arm/mach-s3c2440/mach-rx3715.c
index b59e6d39f2f2..bac40c4878a5 100644
--- a/arch/arm/mach-s3c2440/mach-rx3715.c
+++ b/arch/arm/mach-s3c2440/mach-rx3715.c
@@ -110,28 +110,32 @@ static struct s3c2410_uartcfg rx3715_uartcfgs[] = {
/* framebuffer lcd controller information */
-static struct s3c2410fb_mach_info rx3715_lcdcfg __initdata = {
- .regs = {
- .lcdcon1 = S3C2410_LCDCON1_TFT16BPP | \
- S3C2410_LCDCON1_TFT | \
- S3C2410_LCDCON1_CLKVAL(0x0C),
-
- .lcdcon2 = S3C2410_LCDCON2_VBPD(5) | \
- S3C2410_LCDCON2_LINEVAL(319) | \
- S3C2410_LCDCON2_VFPD(6) | \
- S3C2410_LCDCON2_VSPW(2),
-
- .lcdcon3 = S3C2410_LCDCON3_HBPD(35) | \
- S3C2410_LCDCON3_HOZVAL(239) | \
- S3C2410_LCDCON3_HFPD(35),
-
- .lcdcon4 = S3C2410_LCDCON4_MVAL(0) | \
- S3C2410_LCDCON4_HSPW(7),
-
- .lcdcon5 = S3C2410_LCDCON5_INVVLINE |
- S3C2410_LCDCON5_FRM565 |
- S3C2410_LCDCON5_HWSWP,
- },
+static struct s3c2410fb_display rx3715_lcdcfg __initdata = {
+ .lcdcon5 = S3C2410_LCDCON5_INVVLINE |
+ S3C2410_LCDCON5_FRM565 |
+ S3C2410_LCDCON5_HWSWP,
+
+ .type = S3C2410_LCDCON1_TFT,
+ .width = 240,
+ .height = 320,
+
+ .pixclock = 260000,
+ .xres = 240,
+ .yres = 320,
+ .bpp = 16,
+ .left_margin = 36,
+ .right_margin = 36,
+ .hsync_len = 8,
+ .upper_margin = 6,
+ .lower_margin = 7,
+ .vsync_len = 3,
+};
+
+static struct s3c2410fb_mach_info rx3715_fb_info __initdata = {
+
+ .displays = &rx3715_lcdcfg,
+ .num_displays = 1,
+ .default_display = 0,
.lpcsel = 0xf82,
@@ -144,28 +148,6 @@ static struct s3c2410fb_mach_info rx3715_lcdcfg __initdata = {
.gpdcon_mask = 0xffc0fff0,
.gpdup = 0x0000faff,
.gpdup_mask = 0xffffffff,
-
- .fixed_syncs = 1,
- .width = 240,
- .height = 320,
-
- .xres = {
- .min = 240,
- .max = 240,
- .defval = 240,
- },
-
- .yres = {
- .max = 320,
- .min = 320,
- .defval = 320,
- },
-
- .bpp = {
- .min = 16,
- .max = 16,
- .defval = 16,
- },
};
static struct mtd_partition rx3715_nand_part[] = {
@@ -224,7 +206,7 @@ static void __init rx3715_init_machine(void)
#endif
s3c2410_pm_init();
- s3c24xx_fb_set_platdata(&rx3715_lcdcfg);
+ s3c24xx_fb_set_platdata(&rx3715_fb_info);
platform_add_devices(rx3715_devices, ARRAY_SIZE(rx3715_devices));
}
diff --git a/arch/arm/mach-s3c2440/mach-smdk2440.c b/arch/arm/mach-s3c2440/mach-smdk2440.c
index 670115b8a12e..4552828bf800 100644
--- a/arch/arm/mach-s3c2440/mach-smdk2440.c
+++ b/arch/arm/mach-s3c2440/mach-smdk2440.c
@@ -103,31 +103,35 @@ static struct s3c2410_uartcfg smdk2440_uartcfgs[] __initdata = {
/* LCD driver info */
-static struct s3c2410fb_mach_info smdk2440_lcd_cfg __initdata = {
- .regs = {
-
- .lcdcon1 = S3C2410_LCDCON1_TFT16BPP |
- S3C2410_LCDCON1_TFT |
- S3C2410_LCDCON1_CLKVAL(0x04),
-
- .lcdcon2 = S3C2410_LCDCON2_VBPD(7) |
- S3C2410_LCDCON2_LINEVAL(319) |
- S3C2410_LCDCON2_VFPD(6) |
- S3C2410_LCDCON2_VSPW(3),
-
- .lcdcon3 = S3C2410_LCDCON3_HBPD(19) |
- S3C2410_LCDCON3_HOZVAL(239) |
- S3C2410_LCDCON3_HFPD(7),
-
- .lcdcon4 = S3C2410_LCDCON4_MVAL(0) |
- S3C2410_LCDCON4_HSPW(3),
-
- .lcdcon5 = S3C2410_LCDCON5_FRM565 |
- S3C2410_LCDCON5_INVVLINE |
- S3C2410_LCDCON5_INVVFRAME |
- S3C2410_LCDCON5_PWREN |
- S3C2410_LCDCON5_HWSWP,
- },
+static struct s3c2410fb_display smdk2440_lcd_cfg __initdata = {
+
+ .lcdcon5 = S3C2410_LCDCON5_FRM565 |
+ S3C2410_LCDCON5_INVVLINE |
+ S3C2410_LCDCON5_INVVFRAME |
+ S3C2410_LCDCON5_PWREN |
+ S3C2410_LCDCON5_HWSWP,
+
+ .type = S3C2410_LCDCON1_TFT,
+
+ .width = 240,
+ .height = 320,
+
+ .pixclock = 166667, /* HCLK 60 MHz, divisor 10 */
+ .xres = 240,
+ .yres = 320,
+ .bpp = 16,
+ .left_margin = 20,
+ .right_margin = 8,
+ .hsync_len = 4,
+ .upper_margin = 8,
+ .lower_margin = 7,
+ .vsync_len = 4,
+};
+
+static struct s3c2410fb_mach_info smdk2440_fb_info __initdata = {
+ .displays = &smdk2440_lcd_cfg,
+ .num_displays = 1,
+ .default_display = 0,
#if 0
/* currently setup by downloader */
@@ -142,28 +146,6 @@ static struct s3c2410fb_mach_info smdk2440_lcd_cfg __initdata = {
#endif
.lpcsel = ((0xCE6) & ~7) | 1<<4,
- .type = S3C2410_LCDCON1_TFT16BPP,
-
- .width = 240,
- .height = 320,
-
- .xres = {
- .min = 240,
- .max = 240,
- .defval = 240,
- },
-
- .yres = {
- .min = 320,
- .max = 320,
- .defval = 320,
- },
-
- .bpp = {
- .min = 16,
- .max = 16,
- .defval = 16,
- },
};
static struct platform_device *smdk2440_devices[] __initdata = {
@@ -183,7 +165,7 @@ static void __init smdk2440_map_io(void)
static void __init smdk2440_machine_init(void)
{
- s3c24xx_fb_set_platdata(&smdk2440_lcd_cfg);
+ s3c24xx_fb_set_platdata(&smdk2440_fb_info);
platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices));
smdk_machine_init();
diff --git a/arch/arm/mach-s3c2443/clock.c b/arch/arm/mach-s3c2443/clock.c
index 58402948c47c..b42f956738d0 100644
--- a/arch/arm/mach-s3c2443/clock.c
+++ b/arch/arm/mach-s3c2443/clock.c
@@ -1005,7 +1005,7 @@ void __init s3c2443_init_clocks(int xtal)
}
/* We must be careful disabling the clocks we are not intending to
- * be using at boot time, as subsytems such as the LCD which do
+ * be using at boot time, as subsystems such as the LCD which do
* their own DMA requests to the bus can cause the system to lockup
* if they where in the middle of requesting bus access.
*
diff --git a/arch/arm/mach-s3c2443/dma.c b/arch/arm/mach-s3c2443/dma.c
index fc3ede82af8f..f6c006d4297b 100644
--- a/arch/arm/mach-s3c2443/dma.c
+++ b/arch/arm/mach-s3c2443/dma.c
@@ -162,7 +162,7 @@ static struct s3c24xx_dma_selection __initdata s3c2443_dma_sel = {
.map_size = ARRAY_SIZE(s3c2443_dma_mappings),
};
-static int s3c2443_dma_add(struct sys_device *sysdev)
+static int __init s3c2443_dma_add(struct sys_device *sysdev)
{
s3c24xx_dma_init(6, IRQ_S3C2443_DMA0, 0x100);
return s3c24xx_dma_init_map(&s3c2443_dma_sel);
diff --git a/arch/arm/mach-s3c2443/irq.c b/arch/arm/mach-s3c2443/irq.c
index 6cd4818f3f0d..f9ad498a6fc0 100644
--- a/arch/arm/mach-s3c2443/irq.c
+++ b/arch/arm/mach-s3c2443/irq.c
@@ -252,7 +252,7 @@ static int __init s3c2443_add_sub(unsigned int base,
return 0;
}
-static int s3c2443_irq_add(struct sys_device *sysdev)
+static int __init s3c2443_irq_add(struct sys_device *sysdev)
{
printk("S3C2443: IRQ Support\n");
@@ -280,7 +280,7 @@ static struct sysdev_driver s3c2443_irq_driver = {
.add = s3c2443_irq_add,
};
-static int s3c2443_irq_init(void)
+static int __init s3c2443_irq_init(void)
{
return sysdev_driver_register(&s3c2443_sysclass, &s3c2443_irq_driver);
}
diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c
index 01a37d3c0727..246c573e7252 100644
--- a/arch/arm/mach-sa1100/pm.c
+++ b/arch/arm/mach-sa1100/pm.c
@@ -122,14 +122,14 @@ unsigned long sleep_phys_sp(void *sp)
return virt_to_phys(sp);
}
-static struct pm_ops sa11x0_pm_ops = {
+static struct platform_suspend_ops sa11x0_pm_ops = {
.enter = sa11x0_pm_enter,
- .valid = pm_valid_only_mem,
+ .valid = suspend_valid_only_mem,
};
static int __init sa11x0_pm_init(void)
{
- pm_set_ops(&sa11x0_pm_ops);
+ suspend_set_ops(&sa11x0_pm_ops);
return 0;
}
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 12161ae445da..7868f4dc1d00 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -322,7 +322,7 @@ config CPU_SA1100
# XScale
config CPU_XSCALE
bool
- depends on ARCH_IOP32X || ARCH_IOP33X || ARCH_PXA || ARCH_IXP4XX || ARCH_IXP2000
+ depends on ARCH_IOP32X || ARCH_IOP33X || PXA25x || PXA27x || ARCH_IXP4XX || ARCH_IXP2000
default y
select CPU_32v5
select CPU_ABRT_EV5T
@@ -333,7 +333,7 @@ config CPU_XSCALE
# XScale Core Version 3
config CPU_XSC3
bool
- depends on ARCH_IXP23XX || ARCH_IOP13XX
+ depends on ARCH_IXP23XX || ARCH_IOP13XX || PXA3xx
default y
select CPU_32v5
select CPU_ABRT_EV5T
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index 074b7cb07743..e162cca5917f 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -757,7 +757,7 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
if (ai_usermode & 1)
printk("Alignment trap: %s (%d) PC=0x%08lx Instr=0x%0*lx "
"Address=0x%08lx FSR 0x%03x\n", current->comm,
- current->pid, instrptr,
+ task_pid_nr(current), instrptr,
thumb_mode(regs) ? 4 : 8,
thumb_mode(regs) ? tinstr : instr,
addr, fsr);
diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c
index 1f9f94f9af4b..cefdf2f9f26e 100644
--- a/arch/arm/mm/consistent.c
+++ b/arch/arm/mm/consistent.c
@@ -481,7 +481,7 @@ core_initcall(consistent_init);
* platforms with CONFIG_DMABOUNCE.
* Use the driver DMA support - see dma-mapping.h (dma_sync_*)
*/
-void consistent_sync(const void *start, size_t size, int direction)
+void dma_cache_maint(const void *start, size_t size, int direction)
{
const void *end = start + size;
@@ -504,4 +504,4 @@ void consistent_sync(const void *start, size_t size, int direction)
BUG();
}
}
-EXPORT_SYMBOL(consistent_sync);
+EXPORT_SYMBOL(dma_cache_maint);
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index 846cce48e2b7..a8a7dab757eb 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -197,7 +197,7 @@ survive:
return fault;
out_of_memory:
- if (!is_init(tsk))
+ if (!is_global_init(tsk))
goto out;
/*
@@ -266,7 +266,7 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
* the page fault gracefully.
*/
printk("VM: killing process %s\n", tsk->comm);
- do_exit(SIGKILL);
+ do_group_exit(SIGKILL);
return 0;
}
if (fault & VM_FAULT_SIGBUS) {
diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S
index 5b80b6bdd0cb..194ef48968e6 100644
--- a/arch/arm/mm/proc-arm926.S
+++ b/arch/arm/mm/proc-arm926.S
@@ -105,9 +105,13 @@ ENTRY(cpu_arm926_do_idle)
mrc p15, 0, r1, c1, c0, 0 @ Read control register
mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer
bic r2, r1, #1 << 12
+ mrs r3, cpsr @ Disable FIQs while Icache
+ orr ip, r3, #PSR_F_BIT @ is disabled
+ msr cpsr_c, ip
mcr p15, 0, r2, c1, c0, 0 @ Disable I cache
mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt
mcr p15, 0, r1, c1, c0, 0 @ Restore ICache enable
+ msr cpsr_c, r3 @ Restore FIQ state
mov pc, lr
/*
diff --git a/arch/arm/nwfpe/ARM-gcc.h b/arch/arm/nwfpe/ARM-gcc.h
index e6598470b076..436e54aa02ec 100644
--- a/arch/arm/nwfpe/ARM-gcc.h
+++ b/arch/arm/nwfpe/ARM-gcc.h
@@ -68,7 +68,7 @@ a compiler does not support explicit inlining, this macro should be defined
to be `static'.
-------------------------------------------------------------------------------
*/
-#define INLINE extern __inline__
+#define INLINE static inline
/* For use as a GCC soft-float library we need some special function names. */
diff --git a/arch/arm/nwfpe/entry.S b/arch/arm/nwfpe/entry.S
index 1dc13bc6d810..48bca0db4607 100644
--- a/arch/arm/nwfpe/entry.S
+++ b/arch/arm/nwfpe/entry.S
@@ -70,13 +70,24 @@ floating point instructions. GCC attempts to group floating point
instructions to allow the emulator to spread the cost of the trap over
several floating point instructions. */
+#include <asm/asm-offsets.h>
+
.globl nwfpe_enter
nwfpe_enter:
mov r4, lr @ save the failure-return addresses
mov sl, sp @ we access the registers via 'sl'
- ldr r5, [sp, #60] @ get contents of PC;
+ ldr r5, [sp, #S_PC] @ get contents of PC;
+ mov r6, r0 @ save the opcode
emulate:
+ ldr r1, [sp, #S_PSR] @ fetch the PSR
+ bl checkCondition @ check the condition
+ cmp r0, #0 @ r0 = 0 ==> condition failed
+
+ @ if condition code failed to match, next insn
+ beq next @ get the next instruction;
+
+ mov r0, r6 @ prepare for EmulateAll()
bl EmulateAll @ emulate the instruction
cmp r0, #0 @ was emulation successful
moveq pc, r4 @ no, return failure
@@ -91,18 +102,10 @@ next:
teqne r2, #0x0E000000
movne pc, r9 @ return ok if not a fp insn
- str r5, [sp, #60] @ update PC copy in regs
+ str r5, [sp, #S_PC] @ update PC copy in regs
mov r0, r6 @ save a copy
- ldr r1, [sp, #64] @ fetch the condition codes
- bl checkCondition @ check the condition
- cmp r0, #0 @ r0 = 0 ==> condition failed
-
- @ if condition code failed to match, next insn
- beq next @ get the next instruction;
-
- mov r0, r6 @ prepare for EmulateAll()
- b emulate @ if r0 != 0, goto EmulateAll
+ b emulate @ check condition and emulate
@ We need to be prepared for the instructions at .Lx1 and .Lx2
@ to fault. Emit the appropriate exception gunk to fix things up.
diff --git a/arch/arm/nwfpe/fpa11.inl b/arch/arm/nwfpe/fpa11.inl
index 10c3caf2868f..ab8d6826245f 100644
--- a/arch/arm/nwfpe/fpa11.inl
+++ b/arch/arm/nwfpe/fpa11.inl
@@ -22,13 +22,13 @@
#include "fpa11.h"
/* Read and write floating point status register */
-extern __inline__ unsigned int readFPSR(void)
+static inline unsigned int readFPSR(void)
{
FPA11 *fpa11 = GET_FPA11();
return (fpa11->fpsr);
}
-extern __inline__ void writeFPSR(FPSR reg)
+static inline void writeFPSR(FPSR reg)
{
FPA11 *fpa11 = GET_FPA11();
/* the sysid byte in the status register is readonly */
@@ -36,14 +36,14 @@ extern __inline__ void writeFPSR(FPSR reg)
}
/* Read and write floating point control register */
-extern __inline__ FPCR readFPCR(void)
+static inline FPCR readFPCR(void)
{
FPA11 *fpa11 = GET_FPA11();
/* clear SB, AB and DA bits before returning FPCR */
return (fpa11->fpcr & ~MASK_RFC);
}
-extern __inline__ void writeFPCR(FPCR reg)
+static inline void writeFPCR(FPCR reg)
{
FPA11 *fpa11 = GET_FPA11();
fpa11->fpcr &= ~MASK_WFC; /* clear SB, AB and DA bits */
diff --git a/arch/arm/nwfpe/fpopcode.h b/arch/arm/nwfpe/fpopcode.h
index ec78e3517fc9..786e4c96156d 100644
--- a/arch/arm/nwfpe/fpopcode.h
+++ b/arch/arm/nwfpe/fpopcode.h
@@ -78,11 +78,11 @@ TABLE 1
+-------------------------+---+---+---------+---------+
| Precision | u | v | FPSR.EP | length |
+-------------------------+---+---+---------+---------+
-| Single | 0 ü 0 | x | 1 words |
-| Double | 1 ü 1 | x | 2 words |
-| Extended | 1 ü 1 | x | 3 words |
-| Packed decimal | 1 ü 1 | 0 | 3 words |
-| Expanded packed decimal | 1 ü 1 | 1 | 4 words |
+| Single | 0 | 0 | x | 1 words |
+| Double | 1 | 1 | x | 2 words |
+| Extended | 1 | 1 | x | 3 words |
+| Packed decimal | 1 | 1 | 0 | 3 words |
+| Expanded packed decimal | 1 | 1 | 1 | 4 words |
+-------------------------+---+---+---------+---------+
Note: x = don't care
*/
@@ -92,10 +92,10 @@ TABLE 2
+---+---+---------------------------------+
| w | x | Number of registers to transfer |
+---+---+---------------------------------+
-| 0 ü 1 | 1 |
-| 1 ü 0 | 2 |
-| 1 ü 1 | 3 |
-| 0 ü 0 | 4 |
+| 0 | 1 | 1 |
+| 1 | 0 | 2 |
+| 1 | 1 | 3 |
+| 0 | 0 | 4 |
+---+---+---------------------------------+
*/
@@ -156,10 +156,10 @@ TABLE 5
+-------------------------+---+---+
| Rounding Precision | e | f |
+-------------------------+---+---+
-| IEEE Single precision | 0 ü 0 |
-| IEEE Double precision | 0 ü 1 |
-| IEEE Extended precision | 1 ü 0 |
-| undefined (trap) | 1 ü 1 |
+| IEEE Single precision | 0 | 0 |
+| IEEE Double precision | 0 | 1 |
+| IEEE Extended precision | 1 | 0 |
+| undefined (trap) | 1 | 1 |
+-------------------------+---+---+
*/
@@ -168,10 +168,10 @@ TABLE 5
+---------------------------------+---+---+
| Rounding Mode | g | h |
+---------------------------------+---+---+
-| Round to nearest (default) | 0 ü 0 |
-| Round toward plus infinity | 0 ü 1 |
-| Round toward negative infinity | 1 ü 0 |
-| Round toward zero | 1 ü 1 |
+| Round to nearest (default) | 0 | 0 |
+| Round toward plus infinity | 0 | 1 |
+| Round toward negative infinity | 1 | 0 |
+| Round toward zero | 1 | 1 |
+---------------------------------+---+---+
*/
@@ -369,20 +369,20 @@ TABLE 5
#define getRoundingMode(opcode) ((opcode & MASK_ROUNDING_MODE) >> 5)
#ifdef CONFIG_FPE_NWFPE_XP
-static inline __attribute_pure__ floatx80 getExtendedConstant(const unsigned int nIndex)
+static inline floatx80 __pure getExtendedConstant(const unsigned int nIndex)
{
extern const floatx80 floatx80Constant[];
return floatx80Constant[nIndex];
}
#endif
-static inline __attribute_pure__ float64 getDoubleConstant(const unsigned int nIndex)
+static inline float64 __pure getDoubleConstant(const unsigned int nIndex)
{
extern const float64 float64Constant[];
return float64Constant[nIndex];
}
-static inline __attribute_pure__ float32 getSingleConstant(const unsigned int nIndex)
+static inline float32 __pure getSingleConstant(const unsigned int nIndex)
{
extern const float32 float32Constant[];
return float32Constant[nIndex];
diff --git a/arch/arm/oprofile/Kconfig b/arch/arm/oprofile/Kconfig
deleted file mode 100644
index afd93ad02feb..000000000000
--- a/arch/arm/oprofile/Kconfig
+++ /dev/null
@@ -1,42 +0,0 @@
-
-menu "Profiling support"
- depends on EXPERIMENTAL
-
-config PROFILING
- bool "Profiling support (EXPERIMENTAL)"
- help
- Say Y here to enable the extended profiling support mechanisms used
- by profilers such as OProfile.
-
-
-config OPROFILE
- tristate "OProfile system profiling (EXPERIMENTAL)"
- depends on PROFILING
- help
- OProfile is a profiling system capable of profiling the
- whole system, include the kernel, kernel modules, libraries,
- and applications.
-
- If unsure, say N.
-
-if OPROFILE
-
-config OPROFILE_ARMV6
- bool
- depends on CPU_V6 && !SMP
- default y
- select OPROFILE_ARM11_CORE
-
-config OPROFILE_MPCORE
- bool
- depends on CPU_V6 && SMP
- default y
- select OPROFILE_ARM11_CORE
-
-config OPROFILE_ARM11_CORE
- bool
-
-endif
-
-endmenu
-
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index cfc69f3842fd..c1f7e5a819a3 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -20,10 +20,15 @@ endchoice
comment "OMAP Feature Selections"
-config OMAP_DEBUG_LEDS
+config OMAP_DEBUG_DEVICES
bool
help
- For debug card leds on TI reference boards.
+ For debug cards on TI reference boards.
+
+config OMAP_DEBUG_LEDS
+ bool
+ depends on OMAP_DEBUG_DEVICES
+ default y if LEDS || LEDS_OMAP_DEBUG
config OMAP_RESET_CLOCKS
bool "Reset unused clocks during boot"
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
index 41a3c1cf3bd4..2549129aabc6 100644
--- a/arch/arm/plat-omap/Makefile
+++ b/arch/arm/plat-omap/Makefile
@@ -17,4 +17,5 @@ obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o
obj-$(CONFIG_CPU_FREQ) += cpu-omap.o
obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
+obj-$(CONFIG_OMAP_DEBUG_DEVICES) += debug-devices.o
obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o
diff --git a/arch/arm/plat-omap/debug-devices.c b/arch/arm/plat-omap/debug-devices.c
new file mode 100644
index 000000000000..83a5f8b91857
--- /dev/null
+++ b/arch/arm/plat-omap/debug-devices.c
@@ -0,0 +1,86 @@
+/*
+ * linux/arch/arm/plat-omap/debug-devices.c
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Modified from mach-omap2/board-h4.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+
+/* Many OMAP development platforms reuse the same "debug board"; these
+ * platforms include H2, H3, H4, and Perseus2.
+ */
+
+static struct resource smc91x_resources[] = {
+ [0] = {
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device smc91x_device = {
+ .name = "smc91x",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(smc91x_resources),
+ .resource = smc91x_resources,
+};
+
+static struct resource led_resources[] = {
+ [0] = {
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device led_device = {
+ .name = "omap_dbg_led",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(led_resources),
+ .resource = led_resources,
+};
+
+static struct platform_device *debug_devices[] __initdata = {
+ &smc91x_device,
+ &led_device,
+ /* ps2 kbd + mouse ports */
+ /* 4 extra uarts */
+ /* 6 input dip switches */
+ /* 8 output pins */
+};
+
+int __init debug_card_init(u32 addr, unsigned gpio)
+{
+ int status;
+
+ smc91x_resources[0].start = addr + 0x300;
+ smc91x_resources[0].end = addr + 0x30f;
+
+ smc91x_resources[1].start = OMAP_GPIO_IRQ(gpio);
+ smc91x_resources[1].end = OMAP_GPIO_IRQ(gpio);
+
+ status = omap_request_gpio(gpio);
+ if (status < 0) {
+ printk(KERN_ERR "GPIO%d unavailable for smc91x IRQ\n", gpio);
+ return status;
+ }
+ omap_set_gpio_direction(gpio, 1);
+
+ led_resources[0].start = addr;
+ led_resources[0].end = addr + SZ_4K - 1;
+
+ return platform_add_devices(debug_devices, ARRAY_SIZE(debug_devices));
+}
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index 88d5b6d9f950..dcbba07cf98a 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -2,7 +2,7 @@
* linux/arch/arm/plat-omap/dma.c
*
* Copyright (C) 2003 Nokia Corporation
- * Author: Juha Yrjölä <juha.yrjola@nokia.com>
+ * Author: Juha Yrjölä <juha.yrjola@nokia.com>
* DMA channel linking for 1610 by Samuel Ortiz <samuel.ortiz@nokia.com>
* Graphics DMA and LCD DMA graphics tranformations
* by Imre Deak <imre.deak@nokia.com>
@@ -1347,11 +1347,6 @@ void omap_stop_lcd_dma(void)
omap_writew(w, OMAP1610_DMA_LCD_CTRL);
}
-int omap_lcd_dma_ext_running(void)
-{
- return lcd_dma.ext_ctrl && lcd_dma.active;
-}
-
/*----------------------------------------------------------------------------*/
static int __init omap_init_dma(void)
@@ -1493,7 +1488,6 @@ EXPORT_SYMBOL(omap_free_lcd_dma);
EXPORT_SYMBOL(omap_enable_lcd_dma);
EXPORT_SYMBOL(omap_setup_lcd_dma);
EXPORT_SYMBOL(omap_stop_lcd_dma);
-EXPORT_SYMBOL(omap_lcd_dma_ext_running);
EXPORT_SYMBOL(omap_set_lcd_dma_b1);
EXPORT_SYMBOL(omap_set_lcd_dma_single_transfer);
EXPORT_SYMBOL(omap_set_lcd_dma_ext_controller);
diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c
index 4493bcff5172..ee40c1a0b83d 100644
--- a/arch/arm/plat-omap/fb.c
+++ b/arch/arm/plat-omap/fb.c
@@ -171,7 +171,7 @@ static int check_fbmem_region(int region_idx, struct omapfb_mem_region *rg,
* Called from map_io. We need to call to this early enough so that we
* can reserve the fixed SDRAM regions before VM could get hold of them.
*/
-void omapfb_reserve_sdram(void)
+void __init omapfb_reserve_sdram(void)
{
struct bootmem_data *bdata;
unsigned long sdram_start, sdram_size;
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index 337455dfe64d..6097753394ad 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -4,7 +4,7 @@
* Support functions for OMAP GPIO
*
* Copyright (C) 2003-2005 Nokia Corporation
- * Written by Juha Yrjölä <juha.yrjola@nokia.com>
+ * Written by Juha Yrjölä <juha.yrjola@nokia.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c
index 6d048490c559..29696e46ed65 100644
--- a/arch/arm/plat-s3c24xx/dma.c
+++ b/arch/arm/plat-s3c24xx/dma.c
@@ -1272,7 +1272,7 @@ struct sysdev_class dma_sysclass = {
/* kmem cache implementation */
-static void s3c2410_dma_cache_ctor(void *p, struct kmem_cache *c, unsigned long f)
+static void s3c2410_dma_cache_ctor(struct kmem_cache *c, void *p)
{
memset(p, 0, sizeof(struct s3c2410_dma_buf));
}
@@ -1372,7 +1372,7 @@ int __init s3c24xx_dma_init(unsigned int channels, unsigned int irq,
return ret;
}
-int s3c2410_dma_init(void)
+int __init s3c2410_dma_init(void)
{
return s3c24xx_dma_init(4, IRQ_DMA0, 0x40);
}
diff --git a/arch/arm/plat-s3c24xx/pm.c b/arch/arm/plat-s3c24xx/pm.c
index eab1850616d8..4fdb3117744f 100644
--- a/arch/arm/plat-s3c24xx/pm.c
+++ b/arch/arm/plat-s3c24xx/pm.c
@@ -612,9 +612,9 @@ static int s3c2410_pm_enter(suspend_state_t state)
return 0;
}
-static struct pm_ops s3c2410_pm_ops = {
+static struct platform_suspend_ops s3c2410_pm_ops = {
.enter = s3c2410_pm_enter,
- .valid = pm_valid_only_mem,
+ .valid = suspend_valid_only_mem,
};
/* s3c2410_pm_init
@@ -628,6 +628,6 @@ int __init s3c2410_pm_init(void)
{
printk("S3C2410 Power Management, (c) 2004 Simtec Electronics\n");
- pm_set_ops(&s3c2410_pm_ops);
+ suspend_set_ops(&s3c2410_pm_ops);
return 0;
}
diff --git a/arch/arm/plat-s3c24xx/sleep.S b/arch/arm/plat-s3c24xx/sleep.S
index d47113bbc34c..a646cbe8244c 100644
--- a/arch/arm/plat-s3c24xx/sleep.S
+++ b/arch/arm/plat-s3c24xx/sleep.S
@@ -96,6 +96,14 @@ resume_with_mmu:
s3c2410_sleep_save_phys:
.word 0
+
+ /* sleep magic, to allow the bootloader to check for an valid
+ * image to resume to. Must be the first word before the
+ * s3c2410_cpu_resume entry.
+ */
+
+ .word 0x2bedf00d
+
/* s3c2410_cpu_resume
*
* resume code entry for bootloader to call
diff --git a/arch/arm/vfp/Makefile b/arch/arm/vfp/Makefile
index 7e136e77971a..39f6d8e1af73 100644
--- a/arch/arm/vfp/Makefile
+++ b/arch/arm/vfp/Makefile
@@ -7,7 +7,7 @@
# EXTRA_CFLAGS := -DDEBUG
# EXTRA_AFLAGS := -DDEBUG
-AFLAGS :=$(AFLAGS:-msoft-float=-Wa,-mfpu=softvfp+vfp)
+KBUILD_AFLAGS :=$(KBUILD_AFLAGS:-msoft-float=-Wa,-mfpu=softvfp+vfp)
LDFLAGS +=--no-warn-mismatch
obj-y += vfp.o
diff --git a/arch/arm/vfp/vfpdouble.c b/arch/arm/vfp/vfpdouble.c
index 74e89f8fb3ab..190a09ad18eb 100644
--- a/arch/arm/vfp/vfpdouble.c
+++ b/arch/arm/vfp/vfpdouble.c
@@ -1132,7 +1132,7 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr)
unsigned int vecitr, veclen, vecstride;
struct op *fop;
- vecstride = (1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK)) * 2;
+ vecstride = (1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK));
fop = (op == FOP_EXT) ? &fops_ext[FEXT_TO_IDX(inst)] : &fops[FOP_TO_IDX(op)];
@@ -1184,10 +1184,10 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr)
* CHECK: It appears to be undefined whether we stop when
* we encounter an exception. We continue.
*/
- dest = FREG_BANK(dest) + ((FREG_IDX(dest) + vecstride) & 6);
- dn = FREG_BANK(dn) + ((FREG_IDX(dn) + vecstride) & 6);
+ dest = FREG_BANK(dest) + ((FREG_IDX(dest) + vecstride) & 3);
+ dn = FREG_BANK(dn) + ((FREG_IDX(dn) + vecstride) & 3);
if (FREG_BANK(dm) != 0)
- dm = FREG_BANK(dm) + ((FREG_IDX(dm) + vecstride) & 6);
+ dm = FREG_BANK(dm) + ((FREG_IDX(dm) + vecstride) & 3);
}
return exceptions;
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index eea3f50743d5..b4e210df92f2 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -229,7 +229,7 @@ void VFP9_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
/*
* Enable access to the VFP so we can handle the bounce.
*/
- fmxr(FPEXC, fpexc & ~(FPEXC_EX|FPEXC_INV|FPEXC_UFC|FPEXC_IOC));
+ fmxr(FPEXC, fpexc & ~(FPEXC_EX|FPEXC_FPV2|FPEXC_INV|FPEXC_UFC|FPEXC_OFC|FPEXC_IOC));
orig_fpscr = fpscr = fmrx(FPSCR);
diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig
index d12346aaa88b..4f402c924504 100644
--- a/arch/avr32/Kconfig
+++ b/arch/avr32/Kconfig
@@ -19,9 +19,6 @@ config AVR32
There is an AVR32 Linux project with a web page at
http://avr32linux.org/.
-config UID16
- bool
-
config GENERIC_GPIO
bool
default y
@@ -189,7 +186,7 @@ config CMDLINE
endmenu
-menu "Power managment options"
+menu "Power management options"
menu "CPU Frequency scaling"
diff --git a/arch/avr32/Makefile b/arch/avr32/Makefile
index dc6bc01f232c..87918647be6d 100644
--- a/arch/avr32/Makefile
+++ b/arch/avr32/Makefile
@@ -11,15 +11,15 @@ all: uImage vmlinux.elf
KBUILD_DEFCONFIG := atstk1002_defconfig
-CFLAGS += -pipe -fno-builtin -mno-pic
-AFLAGS += -mrelax -mno-pic
+KBUILD_CFLAGS += -pipe -fno-builtin -mno-pic
+KBUILD_AFLAGS += -mrelax -mno-pic
CFLAGS_MODULE += -mno-relax
LDFLAGS_vmlinux += --relax
cpuflags-$(CONFIG_CPU_AT32AP7000) += -mcpu=ap7000
-CFLAGS += $(cpuflags-y)
-AFLAGS += $(cpuflags-y)
+KBUILD_CFLAGS += $(cpuflags-y)
+KBUILD_AFLAGS += $(cpuflags-y)
CHECKFLAGS += -D__avr32__ -D__BIG_ENDIAN
diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c
index 6b9e466104ad..5be0d13f4b03 100644
--- a/arch/avr32/boards/atstk1000/atstk1002.c
+++ b/arch/avr32/boards/atstk1000/atstk1002.c
@@ -16,6 +16,7 @@
#include <linux/string.h>
#include <linux/types.h>
#include <linux/spi/spi.h>
+#include <linux/spi/at73c213.h>
#include <video/atmel_lcdc.h>
@@ -49,7 +50,26 @@ static struct eth_platform_data __initdata eth_data[2] = {
};
#ifndef CONFIG_BOARD_ATSTK1002_SW1_CUSTOM
+#ifndef CONFIG_BOARD_ATSTK1002_SW3_CUSTOM
+static struct at73c213_board_info at73c213_data = {
+ .ssc_id = 0,
+ .shortname = "AVR32 STK1000 external DAC",
+};
+#endif
+#endif
+
+#ifndef CONFIG_BOARD_ATSTK1002_SW1_CUSTOM
static struct spi_board_info spi0_board_info[] __initdata = {
+#ifndef CONFIG_BOARD_ATSTK1002_SW3_CUSTOM
+ {
+ /* AT73C213 */
+ .modalias = "at73c213",
+ .max_speed_hz = 200000,
+ .chip_select = 0,
+ .mode = SPI_MODE_1,
+ .platform_data = &at73c213_data,
+ },
+#endif
{
/* QVGA display */
.modalias = "ltv350qv",
@@ -180,6 +200,38 @@ static void setup_j2_leds(void)
}
#endif
+#ifndef CONFIG_BOARD_ATSTK1002_SW1_CUSTOM
+#ifndef CONFIG_BOARD_ATSTK1002_SW3_CUSTOM
+static void __init at73c213_set_clk(struct at73c213_board_info *info)
+{
+ struct clk *gclk;
+ struct clk *pll;
+
+ gclk = clk_get(NULL, "gclk0");
+ if (IS_ERR(gclk))
+ goto err_gclk;
+ pll = clk_get(NULL, "pll0");
+ if (IS_ERR(pll))
+ goto err_pll;
+
+ if (clk_set_parent(gclk, pll)) {
+ pr_debug("STK1000: failed to set pll0 as parent for DAC clock\n");
+ goto err_set_clk;
+ }
+
+ at32_select_periph(GPIO_PIN_PA(30), GPIO_PERIPH_A, 0);
+ info->dac_clk = gclk;
+
+err_set_clk:
+ clk_put(pll);
+err_pll:
+ clk_put(gclk);
+err_gclk:
+ return;
+}
+#endif
+#endif
+
void __init setup_board(void)
{
#ifdef CONFIG_BOARD_ATSTK1002_SW2_CUSTOM
@@ -248,6 +300,12 @@ static int __init atstk1002_init(void)
setup_j2_leds();
+#ifndef CONFIG_BOARD_ATSTK1002_SW3_CUSTOM
+#ifndef CONFIG_BOARD_ATSTK1002_SW1_CUSTOM
+ at73c213_set_clk(&at73c213_data);
+#endif
+#endif
+
return 0;
}
postcore_initcall(atstk1002_init);
diff --git a/arch/avr32/kernel/kprobes.c b/arch/avr32/kernel/kprobes.c
index 4942ee662e0b..20b1c9d8f945 100644
--- a/arch/avr32/kernel/kprobes.c
+++ b/arch/avr32/kernel/kprobes.c
@@ -22,6 +22,8 @@ DEFINE_PER_CPU(struct kprobe *, current_kprobe);
static unsigned long kprobe_status;
static struct pt_regs jprobe_saved_regs;
+struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}};
+
int __kprobes arch_prepare_kprobe(struct kprobe *p)
{
int ret = 0;
diff --git a/arch/avr32/kernel/ptrace.c b/arch/avr32/kernel/ptrace.c
index 39060cbeb2a3..9e16b8a447f2 100644
--- a/arch/avr32/kernel/ptrace.c
+++ b/arch/avr32/kernel/ptrace.c
@@ -227,11 +227,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
ret = 0;
break;
- /* Detach a process that was attached */
- case PTRACE_DETACH:
- ret = ptrace_detach(child, data);
- break;
-
case PTRACE_GETREGS:
ret = ptrace_getregs(child, (void __user *)data);
break;
diff --git a/arch/avr32/kernel/traps.c b/arch/avr32/kernel/traps.c
index 9a73ce7eb50f..8a7caf8e7b45 100644
--- a/arch/avr32/kernel/traps.c
+++ b/arch/avr32/kernel/traps.c
@@ -89,7 +89,7 @@ void _exception(long signr, struct pt_regs *regs, int code,
* generate the same exception over and over again and we get
* nowhere. Better to kill it and let the kernel panic.
*/
- if (is_init(current)) {
+ if (is_global_init(current)) {
__sighandler_t handler;
spin_lock_irq(&current->sighand->siglock);
diff --git a/arch/avr32/mach-at32ap/at32ap7000.c b/arch/avr32/mach-at32ap/at32ap7000.c
index f6d154ca4d24..7c4388f4f17f 100644
--- a/arch/avr32/mach-at32ap/at32ap7000.c
+++ b/arch/avr32/mach-at32ap/at32ap7000.c
@@ -474,7 +474,7 @@ static struct resource at32ap700x_rtc0_resource[] = {
static struct resource at32_wdt0_resource[] = {
{
.start = 0xfff000b0,
- .end = 0xfff000bf,
+ .end = 0xfff000cf,
.flags = IORESOURCE_MEM,
},
};
@@ -556,6 +556,17 @@ static struct clk pico_clk = {
.users = 1,
};
+static struct resource dmaca0_resource[] = {
+ {
+ .start = 0xff200000,
+ .end = 0xff20ffff,
+ .flags = IORESOURCE_MEM,
+ },
+ IRQ(2),
+};
+DEFINE_DEV(dmaca, 0);
+DEV_CLK(hclk, dmaca0, hsb, 10);
+
/* --------------------------------------------------------------------
* HMATRIX
* -------------------------------------------------------------------- */
@@ -655,6 +666,7 @@ void __init at32_add_system_devices(void)
platform_device_register(&at32_eic0_device);
platform_device_register(&smc0_device);
platform_device_register(&pdc_device);
+ platform_device_register(&dmaca0_device);
platform_device_register(&at32_systc0_device);
@@ -678,7 +690,7 @@ static struct resource atmel_usart0_resource[] = {
IRQ(6),
};
DEFINE_DEV_DATA(atmel_usart, 0);
-DEV_CLK(usart, atmel_usart0, pba, 4);
+DEV_CLK(usart, atmel_usart0, pba, 3);
static struct atmel_uart_data atmel_usart1_data = {
.use_dma_tx = 1,
@@ -960,6 +972,96 @@ at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n)
}
/* --------------------------------------------------------------------
+ * TWI
+ * -------------------------------------------------------------------- */
+static struct resource atmel_twi0_resource[] __initdata = {
+ PBMEM(0xffe00800),
+ IRQ(5),
+};
+static struct clk atmel_twi0_pclk = {
+ .name = "twi_pclk",
+ .parent = &pba_clk,
+ .mode = pba_clk_mode,
+ .get_rate = pba_clk_get_rate,
+ .index = 2,
+};
+
+struct platform_device *__init at32_add_device_twi(unsigned int id)
+{
+ struct platform_device *pdev;
+
+ if (id != 0)
+ return NULL;
+
+ pdev = platform_device_alloc("atmel_twi", id);
+ if (!pdev)
+ return NULL;
+
+ if (platform_device_add_resources(pdev, atmel_twi0_resource,
+ ARRAY_SIZE(atmel_twi0_resource)))
+ goto err_add_resources;
+
+ select_peripheral(PA(6), PERIPH_A, 0); /* SDA */
+ select_peripheral(PA(7), PERIPH_A, 0); /* SDL */
+
+ atmel_twi0_pclk.dev = &pdev->dev;
+
+ platform_device_add(pdev);
+ return pdev;
+
+err_add_resources:
+ platform_device_put(pdev);
+ return NULL;
+}
+
+/* --------------------------------------------------------------------
+ * MMC
+ * -------------------------------------------------------------------- */
+static struct resource atmel_mci0_resource[] __initdata = {
+ PBMEM(0xfff02400),
+ IRQ(28),
+};
+static struct clk atmel_mci0_pclk = {
+ .name = "mci_clk",
+ .parent = &pbb_clk,
+ .mode = pbb_clk_mode,
+ .get_rate = pbb_clk_get_rate,
+ .index = 9,
+};
+
+struct platform_device *__init at32_add_device_mci(unsigned int id)
+{
+ struct platform_device *pdev;
+
+ if (id != 0)
+ return NULL;
+
+ pdev = platform_device_alloc("atmel_mci", id);
+ if (!pdev)
+ return NULL;
+
+ if (platform_device_add_resources(pdev, atmel_mci0_resource,
+ ARRAY_SIZE(atmel_mci0_resource)))
+ goto err_add_resources;
+
+ select_peripheral(PA(10), PERIPH_A, 0); /* CLK */
+ select_peripheral(PA(11), PERIPH_A, 0); /* CMD */
+ select_peripheral(PA(12), PERIPH_A, 0); /* DATA0 */
+ select_peripheral(PA(13), PERIPH_A, 0); /* DATA1 */
+ select_peripheral(PA(14), PERIPH_A, 0); /* DATA2 */
+ select_peripheral(PA(15), PERIPH_A, 0); /* DATA3 */
+
+ atmel_mci0_pclk.dev = &pdev->dev;
+
+ platform_device_add(pdev);
+ return pdev;
+
+err_add_resources:
+ platform_device_put(pdev);
+ return NULL;
+}
+
+/* --------------------------------------------------------------------
* LCDC
* -------------------------------------------------------------------- */
static struct atmel_lcdfb_info atmel_lcdfb0_data;
@@ -1228,6 +1330,241 @@ out_free_pdev:
}
/* --------------------------------------------------------------------
+ * IDE / CompactFlash
+ * -------------------------------------------------------------------- */
+static struct resource at32_smc_cs4_resource[] __initdata = {
+ {
+ .start = 0x04000000,
+ .end = 0x07ffffff,
+ .flags = IORESOURCE_MEM,
+ },
+ IRQ(~0UL), /* Magic IRQ will be overridden */
+};
+static struct resource at32_smc_cs5_resource[] __initdata = {
+ {
+ .start = 0x20000000,
+ .end = 0x23ffffff,
+ .flags = IORESOURCE_MEM,
+ },
+ IRQ(~0UL), /* Magic IRQ will be overridden */
+};
+
+static int __init at32_init_ide_or_cf(struct platform_device *pdev,
+ unsigned int cs, unsigned int extint)
+{
+ static unsigned int extint_pin_map[4] __initdata = {
+ GPIO_PIN_PB(25),
+ GPIO_PIN_PB(26),
+ GPIO_PIN_PB(27),
+ GPIO_PIN_PB(28),
+ };
+ static bool common_pins_initialized __initdata = false;
+ unsigned int extint_pin;
+ int ret;
+
+ if (extint >= ARRAY_SIZE(extint_pin_map))
+ return -EINVAL;
+ extint_pin = extint_pin_map[extint];
+
+ switch (cs) {
+ case 4:
+ ret = platform_device_add_resources(pdev,
+ at32_smc_cs4_resource,
+ ARRAY_SIZE(at32_smc_cs4_resource));
+ if (ret)
+ return ret;
+
+ select_peripheral(PE(21), PERIPH_A, 0); /* NCS4 -> OE_N */
+ set_ebi_sfr_bits(HMATRIX_BIT(CS4A));
+ break;
+ case 5:
+ ret = platform_device_add_resources(pdev,
+ at32_smc_cs5_resource,
+ ARRAY_SIZE(at32_smc_cs5_resource));
+ if (ret)
+ return ret;
+
+ select_peripheral(PE(22), PERIPH_A, 0); /* NCS5 -> OE_N */
+ set_ebi_sfr_bits(HMATRIX_BIT(CS5A));
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (!common_pins_initialized) {
+ select_peripheral(PE(19), PERIPH_A, 0); /* CFCE1 -> CS0_N */
+ select_peripheral(PE(20), PERIPH_A, 0); /* CFCE2 -> CS1_N */
+ select_peripheral(PE(23), PERIPH_A, 0); /* CFRNW -> DIR */
+ select_peripheral(PE(24), PERIPH_A, 0); /* NWAIT <- IORDY */
+ common_pins_initialized = true;
+ }
+
+ at32_select_periph(extint_pin, GPIO_PERIPH_A, AT32_GPIOF_DEGLITCH);
+
+ pdev->resource[1].start = EIM_IRQ_BASE + extint;
+ pdev->resource[1].end = pdev->resource[1].start;
+
+ return 0;
+}
+
+struct platform_device *__init
+at32_add_device_ide(unsigned int id, unsigned int extint,
+ struct ide_platform_data *data)
+{
+ struct platform_device *pdev;
+
+ pdev = platform_device_alloc("at32_ide", id);
+ if (!pdev)
+ goto fail;
+
+ if (platform_device_add_data(pdev, data,
+ sizeof(struct ide_platform_data)))
+ goto fail;
+
+ if (at32_init_ide_or_cf(pdev, data->cs, extint))
+ goto fail;
+
+ platform_device_add(pdev);
+ return pdev;
+
+fail:
+ platform_device_put(pdev);
+ return NULL;
+}
+
+struct platform_device *__init
+at32_add_device_cf(unsigned int id, unsigned int extint,
+ struct cf_platform_data *data)
+{
+ struct platform_device *pdev;
+
+ pdev = platform_device_alloc("at32_cf", id);
+ if (!pdev)
+ goto fail;
+
+ if (platform_device_add_data(pdev, data,
+ sizeof(struct cf_platform_data)))
+ goto fail;
+
+ if (at32_init_ide_or_cf(pdev, data->cs, extint))
+ goto fail;
+
+ if (data->detect_pin != GPIO_PIN_NONE)
+ at32_select_gpio(data->detect_pin, AT32_GPIOF_DEGLITCH);
+ if (data->reset_pin != GPIO_PIN_NONE)
+ at32_select_gpio(data->reset_pin, 0);
+ if (data->vcc_pin != GPIO_PIN_NONE)
+ at32_select_gpio(data->vcc_pin, 0);
+ /* READY is used as extint, so we can't select it as gpio */
+
+ platform_device_add(pdev);
+ return pdev;
+
+fail:
+ platform_device_put(pdev);
+ return NULL;
+}
+
+/* --------------------------------------------------------------------
+ * AC97C
+ * -------------------------------------------------------------------- */
+static struct resource atmel_ac97c0_resource[] __initdata = {
+ PBMEM(0xfff02800),
+ IRQ(29),
+};
+static struct clk atmel_ac97c0_pclk = {
+ .name = "pclk",
+ .parent = &pbb_clk,
+ .mode = pbb_clk_mode,
+ .get_rate = pbb_clk_get_rate,
+ .index = 10,
+};
+
+struct platform_device *__init at32_add_device_ac97c(unsigned int id)
+{
+ struct platform_device *pdev;
+
+ if (id != 0)
+ return NULL;
+
+ pdev = platform_device_alloc("atmel_ac97c", id);
+ if (!pdev)
+ return NULL;
+
+ if (platform_device_add_resources(pdev, atmel_ac97c0_resource,
+ ARRAY_SIZE(atmel_ac97c0_resource)))
+ goto err_add_resources;
+
+ select_peripheral(PB(20), PERIPH_B, 0); /* SYNC */
+ select_peripheral(PB(21), PERIPH_B, 0); /* SDO */
+ select_peripheral(PB(22), PERIPH_B, 0); /* SDI */
+ select_peripheral(PB(23), PERIPH_B, 0); /* SCLK */
+
+ atmel_ac97c0_pclk.dev = &pdev->dev;
+
+ platform_device_add(pdev);
+ return pdev;
+
+err_add_resources:
+ platform_device_put(pdev);
+ return NULL;
+}
+
+/* --------------------------------------------------------------------
+ * ABDAC
+ * -------------------------------------------------------------------- */
+static struct resource abdac0_resource[] __initdata = {
+ PBMEM(0xfff02000),
+ IRQ(27),
+};
+static struct clk abdac0_pclk = {
+ .name = "pclk",
+ .parent = &pbb_clk,
+ .mode = pbb_clk_mode,
+ .get_rate = pbb_clk_get_rate,
+ .index = 8,
+};
+static struct clk abdac0_sample_clk = {
+ .name = "sample_clk",
+ .mode = genclk_mode,
+ .get_rate = genclk_get_rate,
+ .set_rate = genclk_set_rate,
+ .set_parent = genclk_set_parent,
+ .index = 6,
+};
+
+struct platform_device *__init at32_add_device_abdac(unsigned int id)
+{
+ struct platform_device *pdev;
+
+ if (id != 0)
+ return NULL;
+
+ pdev = platform_device_alloc("abdac", id);
+ if (!pdev)
+ return NULL;
+
+ if (platform_device_add_resources(pdev, abdac0_resource,
+ ARRAY_SIZE(abdac0_resource)))
+ goto err_add_resources;
+
+ select_peripheral(PB(20), PERIPH_A, 0); /* DATA1 */
+ select_peripheral(PB(21), PERIPH_A, 0); /* DATA0 */
+ select_peripheral(PB(22), PERIPH_A, 0); /* DATAN1 */
+ select_peripheral(PB(23), PERIPH_A, 0); /* DATAN0 */
+
+ abdac0_pclk.dev = &pdev->dev;
+ abdac0_sample_clk.dev = &pdev->dev;
+
+ platform_device_add(pdev);
+ return pdev;
+
+err_add_resources:
+ platform_device_put(pdev);
+ return NULL;
+}
+
+/* --------------------------------------------------------------------
* GCLK
* -------------------------------------------------------------------- */
static struct clk gclk0 = {
@@ -1290,6 +1627,7 @@ struct clk *at32_clock_list[] = {
&smc0_mck,
&pdc_hclk,
&pdc_pclk,
+ &dmaca0_hclk,
&pico_clk,
&pio0_mck,
&pio1_mck,
@@ -1307,6 +1645,8 @@ struct clk *at32_clock_list[] = {
&macb1_pclk,
&atmel_spi0_spi_clk,
&atmel_spi1_spi_clk,
+ &atmel_twi0_pclk,
+ &atmel_mci0_pclk,
&atmel_lcdfb0_hck1,
&atmel_lcdfb0_pixclk,
&ssc0_pclk,
@@ -1314,6 +1654,9 @@ struct clk *at32_clock_list[] = {
&ssc2_pclk,
&usba0_hclk,
&usba0_pclk,
+ &atmel_ac97c0_pclk,
+ &abdac0_pclk,
+ &abdac0_sample_clk,
&gclk0,
&gclk1,
&gclk2,
@@ -1355,6 +1698,7 @@ void __init at32_clock_init(void)
genclk_init_parent(&gclk3);
genclk_init_parent(&gclk4);
genclk_init_parent(&atmel_lcdfb0_pixclk);
+ genclk_init_parent(&abdac0_sample_clk);
/*
* Turn on all clocks that have at least one user already, and
diff --git a/arch/avr32/mach-at32ap/extint.c b/arch/avr32/mach-at32ap/extint.c
index 8acd01090031..f5bfd4c81fe7 100644
--- a/arch/avr32/mach-at32ap/extint.c
+++ b/arch/avr32/mach-at32ap/extint.c
@@ -142,7 +142,7 @@ static int eic_set_irq_type(unsigned int irq, unsigned int flow_type)
return ret;
}
-struct irq_chip eic_chip = {
+static struct irq_chip eic_chip = {
.name = "eic",
.ack = eic_ack_irq,
.mask = eic_mask_irq,
diff --git a/arch/avr32/mach-at32ap/hsmc.c b/arch/avr32/mach-at32ap/hsmc.c
index 704607fbcc69..fa427ed42787 100644
--- a/arch/avr32/mach-at32ap/hsmc.c
+++ b/arch/avr32/mach-at32ap/hsmc.c
@@ -7,7 +7,6 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-#define DEBUG
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/init.h>
diff --git a/arch/avr32/mach-at32ap/intc.c b/arch/avr32/mach-at32ap/intc.c
index dd5c009cf224..0b286cd53028 100644
--- a/arch/avr32/mach-at32ap/intc.c
+++ b/arch/avr32/mach-at32ap/intc.c
@@ -13,6 +13,7 @@
#include <linux/irq.h>
#include <linux/platform_device.h>
+#include <asm/intc.h>
#include <asm/io.h>
#include "intc.h"
@@ -136,7 +137,8 @@ fail:
panic("Interrupt controller initialization failed!\n");
}
-unsigned long intc_get_pending(int group)
+unsigned long intc_get_pending(unsigned int group)
{
return intc_readl(&intc0, INTREQ0 + 4 * group);
}
+EXPORT_SYMBOL_GPL(intc_get_pending);
diff --git a/arch/avr32/mach-at32ap/pm.h b/arch/avr32/mach-at32ap/pm.h
index 47efd0d1951f..694d521edc2f 100644
--- a/arch/avr32/mach-at32ap/pm.h
+++ b/arch/avr32/mach-at32ap/pm.h
@@ -113,8 +113,8 @@
/* Register access macros */
#define pm_readl(reg) \
- __raw_readl((void __iomem *)AT32_PM_BASE + PM_##reg)
+ __raw_readl((void __iomem __force *)AT32_PM_BASE + PM_##reg)
#define pm_writel(reg,value) \
- __raw_writel((value), (void __iomem *)AT32_PM_BASE + PM_##reg)
+ __raw_writel((value), (void __iomem __force *)AT32_PM_BASE + PM_##reg)
#endif /* __ARCH_AVR32_MACH_AT32AP_PM_H__ */
diff --git a/arch/avr32/mach-at32ap/time-tc.c b/arch/avr32/mach-at32ap/time-tc.c
index e3070bdd4bb9..10265863c982 100644
--- a/arch/avr32/mach-at32ap/time-tc.c
+++ b/arch/avr32/mach-at32ap/time-tc.c
@@ -79,7 +79,7 @@ static int avr32_timer_calc_div_and_set_jiffies(struct clk *pclk)
{
unsigned int cycles_max = (clocksource_avr32.mask + 1) / 2;
unsigned int divs[] = { 4, 8, 16, 32 };
- int divs_size = sizeof(divs) / sizeof(*divs);
+ int divs_size = ARRAY_SIZE(divs);
int i = 0;
unsigned long count_hz;
unsigned long shift;
diff --git a/arch/avr32/mm/dma-coherent.c b/arch/avr32/mm/dma-coherent.c
index 099212d4567c..177fea8f7b71 100644
--- a/arch/avr32/mm/dma-coherent.c
+++ b/arch/avr32/mm/dma-coherent.c
@@ -21,13 +21,13 @@ void dma_cache_sync(struct device *dev, void *vaddr, size_t size, int direction)
switch (direction) {
case DMA_FROM_DEVICE: /* invalidate only */
- dma_cache_inv(vaddr, size);
+ invalidate_dcache_region(vaddr, size);
break;
case DMA_TO_DEVICE: /* writeback only */
- dma_cache_wback(vaddr, size);
+ clean_dcache_region(vaddr, size);
break;
case DMA_BIDIRECTIONAL: /* writeback and invalidate */
- dma_cache_wback_inv(vaddr, size);
+ flush_dcache_region(vaddr, size);
break;
default:
BUG();
diff --git a/arch/avr32/mm/fault.c b/arch/avr32/mm/fault.c
index ae2d2c593b2b..6560cb18b4e3 100644
--- a/arch/avr32/mm/fault.c
+++ b/arch/avr32/mm/fault.c
@@ -160,7 +160,7 @@ bad_area:
if (exception_trace && printk_ratelimit())
printk("%s%s[%d]: segfault at %08lx pc %08lx "
"sp %08lx ecr %lu\n",
- is_init(tsk) ? KERN_EMERG : KERN_INFO,
+ is_global_init(tsk) ? KERN_EMERG : KERN_INFO,
tsk->comm, tsk->pid, address, regs->pc,
regs->sp, ecr);
_exception(SIGSEGV, regs, code, address);
@@ -209,14 +209,14 @@ no_context:
*/
out_of_memory:
up_read(&mm->mmap_sem);
- if (is_init(current)) {
+ if (is_global_init(current)) {
yield();
down_read(&mm->mmap_sem);
goto survive;
}
printk("VM: Killing process %s\n", tsk->comm);
if (user_mode(regs))
- do_exit(SIGKILL);
+ do_group_exit(SIGKILL);
goto no_context;
do_sigbus:
@@ -231,7 +231,7 @@ do_sigbus:
if (exception_trace)
printk("%s%s[%d]: bus error at %08lx pc %08lx "
"sp %08lx ecr %lu\n",
- is_init(tsk) ? KERN_EMERG : KERN_INFO,
+ is_global_init(tsk) ? KERN_EMERG : KERN_INFO,
tsk->comm, tsk->pid, address, regs->pc,
regs->sp, ecr);
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
index b24f4535ffe0..9f9de3e95826 100644
--- a/arch/blackfin/Kconfig
+++ b/arch/blackfin/Kconfig
@@ -71,7 +71,7 @@ config GENERIC_CALIBRATE_DELAY
config IRQCHIP_DEMUX_GPIO
bool
- depends on (BF53x || BF561 || BF54x)
+ depends on (BF52x || BF53x || BF561 || BF54x)
default y
source "init/Kconfig"
@@ -85,6 +85,21 @@ choice
prompt "CPU"
default BF533
+config BF522
+ bool "BF522"
+ help
+ BF522 Processor Support.
+
+config BF525
+ bool "BF525"
+ help
+ BF525 Processor Support.
+
+config BF527
+ bool "BF527"
+ help
+ BF527 Processor Support.
+
config BF531
bool "BF531"
help
@@ -144,13 +159,18 @@ endchoice
choice
prompt "Silicon Rev"
+ default BF_REV_0_1 if BF527
default BF_REV_0_2 if BF537
default BF_REV_0_3 if BF533
default BF_REV_0_0 if BF549
config BF_REV_0_0
bool "0.0"
- depends on (BF549)
+ depends on (BF549 || BF527)
+
+config BF_REV_0_1
+ bool "0.2"
+ depends on (BF549 || BF527)
config BF_REV_0_2
bool "0.2"
@@ -176,6 +196,11 @@ config BF_REV_NONE
endchoice
+config BF52x
+ bool
+ depends on (BF522 || BF525 || BF527)
+ default y
+
config BF53x
bool
depends on (BF531 || BF532 || BF533 || BF534 || BF536 || BF537)
@@ -204,6 +229,12 @@ choice
configuration to ensure that all the other settings are
correct.
+config BFIN527_EZKIT
+ bool "BF527-EZKIT"
+ depends on (BF522 || BF525 || BF527)
+ help
+ BF533-EZKIT-LITE board Support.
+
config BFIN533_EZKIT
bool "BF533-EZKIT"
depends on (BF533 || BF532 || BF531)
@@ -264,6 +295,12 @@ config PNAV10
help
PNAV 1.0 board Support.
+config H8606_HVSISTEMAS
+ bool "HV Sistemas H8606"
+ depends on (BF532)
+ help
+ HV Sistemas H8606 board support.
+
config GENERIC_BOARD
bool "Custom"
depends on (BF537 || BF536 \
@@ -286,7 +323,8 @@ config MEM_MT48LC64M4A2FB_7E
config MEM_MT48LC16M16A2TG_75
bool
depends on (BFIN533_EZKIT || BFIN561_EZKIT \
- || BFIN533_BLUETECHNIX_CM || BFIN537_BLUETECHNIX_CM)
+ || BFIN533_BLUETECHNIX_CM || BFIN537_BLUETECHNIX_CM \
+ || H8606_HVSISTEMAS)
default y
config MEM_MT48LC32M8A2_75
@@ -299,11 +337,17 @@ config MEM_MT48LC8M32B2B5_7
depends on (BFIN561_BLUETECHNIX_CM)
default y
+config MEM_MT48LC32M16A2TG_75
+ bool
+ depends on (BFIN527_EZKIT)
+ default y
+
config BFIN_SHARED_FLASH_ENET
bool
depends on (BFIN533_STAMP)
default y
+source "arch/blackfin/mach-bf527/Kconfig"
source "arch/blackfin/mach-bf533/Kconfig"
source "arch/blackfin/mach-bf561/Kconfig"
source "arch/blackfin/mach-bf537/Kconfig"
@@ -329,7 +373,7 @@ config CLKIN_HZ
int "Crystal Frequency in Hz"
default "11059200" if BFIN533_STAMP
default "27000000" if BFIN533_EZKIT
- default "25000000" if BFIN537_STAMP
+ default "25000000" if (BFIN537_STAMP || BFIN527_EZKIT || H8606_HVSISTEMAS)
default "30000000" if BFIN561_EZKIT
default "24576000" if PNAV10
help
@@ -362,11 +406,12 @@ config VCO_MULT
range 1 64
default "22" if BFIN533_EZKIT
default "45" if BFIN533_STAMP
- default "20" if BFIN537_STAMP
+ default "20" if (BFIN537_STAMP || BFIN527_EZKIT)
default "22" if BFIN533_BLUETECHNIX_CM
default "20" if BFIN537_BLUETECHNIX_CM
default "20" if BFIN561_BLUETECHNIX_CM
default "20" if BFIN561_EZKIT
+ default "16" if H8606_HVSISTEMAS
help
This controls the frequency of the on-chip PLL. This can be between 1 and 64.
PLL Frequency = (Crystal Frequency) * (this setting)
@@ -398,11 +443,12 @@ config SCLK_DIV
range 1 15
default 5 if BFIN533_EZKIT
default 5 if BFIN533_STAMP
- default 4 if BFIN537_STAMP
+ default 4 if (BFIN537_STAMP || BFIN527_EZKIT)
default 5 if BFIN533_BLUETECHNIX_CM
default 4 if BFIN537_BLUETECHNIX_CM
default 4 if BFIN561_BLUETECHNIX_CM
default 5 if BFIN561_EZKIT
+ default 3 if H8606_HVSISTEMAS
help
This sets the frequency of the system clock (including SDRAM or DDR).
This can be between 1 and 15
@@ -450,15 +496,19 @@ comment "Memory Setup"
config MEM_SIZE
int "SDRAM Memory Size in MBytes"
default 32 if BFIN533_EZKIT
+ default 64 if BFIN527_EZKIT
default 64 if BFIN537_STAMP
default 64 if BFIN561_EZKIT
default 128 if BFIN533_STAMP
default 64 if PNAV10
+ default 32 if H8606_HVSISTEMAS
config MEM_ADD_WIDTH
int "SDRAM Memory Address Width"
default 9 if BFIN533_EZKIT
default 9 if BFIN561_EZKIT
+ default 9 if H8606_HVSISTEMAS
+ default 10 if BFIN527_EZKIT
default 10 if BFIN537_STAMP
default 11 if BFIN533_STAMP
default 10 if PNAV10
@@ -613,85 +663,86 @@ config I_ENTRY_L1
bool "Locate interrupt entry code in L1 Memory"
default y
help
- If enabled interrupt entry code (STORE/RESTORE CONTEXT) is linked
- into L1 instruction memory.(less latency)
+ If enabled, interrupt entry code (STORE/RESTORE CONTEXT) is linked
+ into L1 instruction memory. (less latency)
config EXCPT_IRQ_SYSC_L1
- bool "Locate entire ASM lowlevel excepetion / interrupt - Syscall and CPLB handler code in L1 Memory"
+ bool "Locate entire ASM lowlevel exception / interrupt - Syscall and CPLB handler code in L1 Memory"
default y
help
- If enabled entire ASM lowlevel exception and interrupt entry code (STORE/RESTORE CONTEXT) is linked
- into L1 instruction memory.(less latency)
+ If enabled, the entire ASM lowlevel exception and interrupt entry code
+ (STORE/RESTORE CONTEXT) is linked into L1 instruction memory.
+ (less latency)
config DO_IRQ_L1
bool "Locate frequently called do_irq dispatcher function in L1 Memory"
default y
help
- If enabled frequently called do_irq dispatcher function is linked
- into L1 instruction memory.(less latency)
+ If enabled, the frequently called do_irq dispatcher function is linked
+ into L1 instruction memory. (less latency)
config CORE_TIMER_IRQ_L1
bool "Locate frequently called timer_interrupt() function in L1 Memory"
default y
help
- If enabled frequently called timer_interrupt() function is linked
- into L1 instruction memory.(less latency)
+ If enabled, the frequently called timer_interrupt() function is linked
+ into L1 instruction memory. (less latency)
config IDLE_L1
bool "Locate frequently idle function in L1 Memory"
default y
help
- If enabled frequently called idle function is linked
- into L1 instruction memory.(less latency)
+ If enabled, the frequently called idle function is linked
+ into L1 instruction memory. (less latency)
config SCHEDULE_L1
bool "Locate kernel schedule function in L1 Memory"
default y
help
- If enabled frequently called kernel schedule is linked
- into L1 instruction memory.(less latency)
+ If enabled, the frequently called kernel schedule is linked
+ into L1 instruction memory. (less latency)
config ARITHMETIC_OPS_L1
bool "Locate kernel owned arithmetic functions in L1 Memory"
default y
help
- If enabled arithmetic functions are linked
- into L1 instruction memory.(less latency)
+ If enabled, arithmetic functions are linked
+ into L1 instruction memory. (less latency)
config ACCESS_OK_L1
bool "Locate access_ok function in L1 Memory"
default y
help
- If enabled access_ok function is linked
- into L1 instruction memory.(less latency)
+ If enabled, the access_ok function is linked
+ into L1 instruction memory. (less latency)
config MEMSET_L1
bool "Locate memset function in L1 Memory"
default y
help
- If enabled memset function is linked
- into L1 instruction memory.(less latency)
+ If enabled, the memset function is linked
+ into L1 instruction memory. (less latency)
config MEMCPY_L1
bool "Locate memcpy function in L1 Memory"
default y
help
- If enabled memcpy function is linked
- into L1 instruction memory.(less latency)
+ If enabled, the memcpy function is linked
+ into L1 instruction memory. (less latency)
config SYS_BFIN_SPINLOCK_L1
bool "Locate sys_bfin_spinlock function in L1 Memory"
default y
help
- If enabled sys_bfin_spinlock function is linked
- into L1 instruction memory.(less latency)
+ If enabled, sys_bfin_spinlock function is linked
+ into L1 instruction memory. (less latency)
config IP_CHECKSUM_L1
bool "Locate IP Checksum function in L1 Memory"
default n
help
- If enabled IP Checksum function is linked
- into L1 instruction memory.(less latency)
+ If enabled, the IP Checksum function is linked
+ into L1 instruction memory. (less latency)
config CACHELINE_ALIGNED_L1
bool "Locate cacheline_aligned data to L1 Data Memory"
@@ -699,24 +750,24 @@ config CACHELINE_ALIGNED_L1
default n if BF54x
depends on !BF531
help
- If enabled cacheline_anligned data is linked
- into L1 data memory.(less latency)
+ If enabled, cacheline_anligned data is linked
+ into L1 data memory. (less latency)
config SYSCALL_TAB_L1
bool "Locate Syscall Table L1 Data Memory"
default n
depends on !BF531
help
- If enabled the Syscall LUT is linked
- into L1 data memory.(less latency)
+ If enabled, the Syscall LUT is linked
+ into L1 data memory. (less latency)
config CPLB_SWITCH_TAB_L1
bool "Locate CPLB Switch Tables L1 Data Memory"
default n
depends on !BF531
help
- If enabled the CPLB Switch Tables are linked
- into L1 data memory.(less latency)
+ If enabled, the CPLB Switch Tables are linked
+ into L1 data memory. (less latency)
endmenu
@@ -748,9 +799,19 @@ config LARGE_ALLOCS
a lot of RAM, and you need to able to allocate very large
contiguous chunks. If unsure, say N.
+config BFIN_GPTIMERS
+ tristate "Enable Blackfin General Purpose Timers API"
+ default n
+ help
+ Enable support for the General Purpose Timers API. If you
+ are unsure, say N.
+
+ To compile this driver as a module, choose M here: the module
+ will be called gptimers.ko.
+
config BFIN_DMA_5XX
bool "Enable DMA Support"
- depends on (BF533 || BF532 || BF531 || BF537 || BF536 || BF534 || BF561 || BF54x)
+ depends on (BF52x || BF53x || BF561 || BF54x)
default y
help
DMA driver for BF5xx.
@@ -758,7 +819,7 @@ config BFIN_DMA_5XX
choice
prompt "Uncached SDRAM region"
default DMA_UNCACHED_1M
- depends BFIN_DMA_5XX
+ depends on BFIN_DMA_5XX
config DMA_UNCACHED_2M
bool "Enable 2M DMA region"
config DMA_UNCACHED_1M
@@ -1012,7 +1073,7 @@ source "drivers/Kconfig"
source "fs/Kconfig"
-source "arch/blackfin/oprofile/Kconfig"
+source "kernel/Kconfig.instrumentation"
menu "Kernel hacking"
@@ -1029,13 +1090,13 @@ config DEBUG_HWERR
from.
config DEBUG_ICACHE_CHECK
- bool "Check Instruction cache coherancy"
+ bool "Check Instruction cache coherency"
depends on DEBUG_KERNEL
depends on DEBUG_HWERR
help
- Say Y here if you are getting wierd unexplained errors. This will
- ensure that icache is what SDRAM says it should be, by doing a
- byte wise comparision between SDRAM and instruction cache. This
+ Say Y here if you are getting weird unexplained errors. This will
+ ensure that icache is what SDRAM says it should be by doing a
+ byte wise comparison between SDRAM and instruction cache. This
also relocates the irq_panic() function to L1 memory, (which is
un-cached).
diff --git a/arch/blackfin/Makefile b/arch/blackfin/Makefile
index 20841663270f..f7cac7c51e7e 100644
--- a/arch/blackfin/Makefile
+++ b/arch/blackfin/Makefile
@@ -12,12 +12,17 @@ LDFLAGS_vmlinux := -X
OBJCOPYFLAGS := -O binary -R .note -R .comment -S
GZFLAGS := -9
+KBUILD_CFLAGS += $(call cc-option,-mno-fdpic)
+KBUILD_AFLAGS += $(call cc-option,-mno-fdpic)
CFLAGS_MODULE += -mlong-calls
KALLSYMS += --symbol-prefix=_
KBUILD_DEFCONFIG := BF537-STAMP_defconfig
# setup the machine name and the machine dependent settings
+machine-$(CONFIG_BF522) := bf527
+machine-$(CONFIG_BF525) := bf527
+machine-$(CONFIG_BF527) := bf527
machine-$(CONFIG_BF531) := bf533
machine-$(CONFIG_BF532) := bf533
machine-$(CONFIG_BF533) := bf533
@@ -32,6 +37,9 @@ machine-$(CONFIG_BF561) := bf561
MACHINE := $(machine-y)
export MACHINE
+cpu-$(CONFIG_BF522) := bf522
+cpu-$(CONFIG_BF525) := bf525
+cpu-$(CONFIG_BF527) := bf527
cpu-$(CONFIG_BF531) := bf531
cpu-$(CONFIG_BF532) := bf532
cpu-$(CONFIG_BF533) := bf533
@@ -53,8 +61,8 @@ rev-$(CONFIG_BF_REV_0_5) := 0.5
rev-$(CONFIG_BF_REV_NONE) := none
rev-$(CONFIG_BF_REV_ANY) := any
-CFLAGS += -mcpu=$(cpu-y)-$(rev-y)
-AFLAGS += -mcpu=$(cpu-y)-$(rev-y)
+KBUILD_CFLAGS += -mcpu=$(cpu-y)-$(rev-y)
+KBUILD_AFLAGS += -mcpu=$(cpu-y)-$(rev-y)
head-y := arch/$(ARCH)/mach-$(MACHINE)/head.o arch/$(ARCH)/kernel/init_task.o
@@ -97,12 +105,23 @@ archclean:
$(Q)$(MAKE) $(clean)=$(boot)
-all: vmImage
boot := arch/$(ARCH)/boot
BOOT_TARGETS = vmImage
-.PHONY: $(BOOT_TARGETS)
+PHONY += $(BOOT_TARGETS) install
+KBUILD_IMAGE := $(boot)/vmImage
+
+all: vmImage
+
$(BOOT_TARGETS): vmlinux
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+
+install:
+ $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) install
+
define archhelp
echo '* vmImage - Kernel-only image for U-Boot (arch/$(ARCH)/boot/vmImage)'
+ echo ' install - Install kernel using'
+ echo ' (your) ~/bin/$(CROSS_COMPILE)installkernel or'
+ echo ' (distribution) PATH: $(CROSS_COMPILE)installkernel or'
+ echo ' install to $$(INSTALL_PATH)'
endef
diff --git a/arch/blackfin/boot/Makefile b/arch/blackfin/boot/Makefile
index 8cd33560e817..522f3c124060 100644
--- a/arch/blackfin/boot/Makefile
+++ b/arch/blackfin/boot/Makefile
@@ -26,3 +26,6 @@ $(obj)/vmlinux.gz: $(obj)/vmlinux.bin FORCE
$(obj)/vmImage: $(obj)/vmlinux.gz
$(call if_changed,uimage)
@echo 'Kernel: $@ is ready'
+
+install:
+ sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map "$(INSTALL_PATH)"
diff --git a/arch/blackfin/boot/install.sh b/arch/blackfin/boot/install.sh
new file mode 100644
index 000000000000..9560a6b29100
--- /dev/null
+++ b/arch/blackfin/boot/install.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+#
+# arch/blackfin/boot/install.sh
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License. See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 1995 by Linus Torvalds
+#
+# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin
+# Adapted from code in arch/i386/boot/install.sh by Mike Frysinger
+#
+# "make install" script for Blackfin architecture
+#
+# Arguments:
+# $1 - kernel version
+# $2 - kernel image file
+# $3 - kernel map file
+# $4 - default install path (blank if root directory)
+#
+
+verify () {
+ if [ ! -f "$1" ]; then
+ echo "" 1>&2
+ echo " *** Missing file: $1" 1>&2
+ echo ' *** You need to run "make" before "make install".' 1>&2
+ echo "" 1>&2
+ exit 1
+ fi
+}
+
+# Make sure the files actually exist
+verify "$2"
+verify "$3"
+
+# User may have a custom install script
+
+if [ -x ~/bin/${CROSS_COMPILE}installkernel ]; then exec ~/bin/${CROSS_COMPILE}installkernel "$@"; fi
+if which ${CROSS_COMPILE}installkernel >/dev/null 2>&1; then
+ exec ${CROSS_COMPILE}installkernel "$@"
+fi
+
+# Default install - same as make zlilo
+
+back_it_up() {
+ local file=$1
+ [ -f ${file} ] || return 0
+ local stamp=$(stat -c %Y ${file} 2>/dev/null)
+ mv ${file} ${file}.${stamp:-old}
+}
+
+back_it_up $4/uImage
+back_it_up $4/System.map
+
+cat $2 > $4/uImage
+cp $3 $4/System.map
diff --git a/arch/blackfin/configs/BF527-EZKIT_defconfig b/arch/blackfin/configs/BF527-EZKIT_defconfig
new file mode 100644
index 000000000000..1f6a93df6b32
--- /dev/null
+++ b/arch/blackfin/configs/BF527-EZKIT_defconfig
@@ -0,0 +1,1241 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.22.9
+#
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_BLACKFIN=y
+CONFIG_ZONE_DMA=y
+CONFIG_BFIN=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_GENERIC_GPIO=y
+CONFIG_FORCE_MAX_ZONEORDER=14
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_IRQCHIP_DEMUX_GPIO=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_EVENTFD=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
+# CONFIG_NP2 is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+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_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+
+#
+# Blackfin Processor Options
+#
+
+#
+# Processor and Board Settings
+#
+# CONFIG_BF522 is not set
+# CONFIG_BF525 is not set
+CONFIG_BF527=y
+# CONFIG_BF531 is not set
+# CONFIG_BF532 is not set
+# CONFIG_BF533 is not set
+# CONFIG_BF534 is not set
+# CONFIG_BF536 is not set
+# CONFIG_BF537 is not set
+# CONFIG_BF542 is not set
+# CONFIG_BF544 is not set
+# CONFIG_BF548 is not set
+# CONFIG_BF549 is not set
+# CONFIG_BF561 is not set
+CONFIG_BF_REV_0_0=y
+# CONFIG_BF_REV_0_1 is not set
+# CONFIG_BF_REV_0_2 is not set
+# CONFIG_BF_REV_0_3 is not set
+# CONFIG_BF_REV_0_4 is not set
+# CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_ANY is not set
+# CONFIG_BF_REV_NONE is not set
+CONFIG_BF52x=y
+CONFIG_BFIN_SINGLE_CORE=y
+CONFIG_BFIN527_EZKIT=y
+# CONFIG_BFIN533_EZKIT is not set
+# CONFIG_BFIN533_STAMP is not set
+# CONFIG_BFIN537_STAMP is not set
+# CONFIG_BFIN533_BLUETECHNIX_CM is not set
+# CONFIG_BFIN537_BLUETECHNIX_CM is not set
+# CONFIG_BFIN548_EZKIT is not set
+# CONFIG_BFIN561_BLUETECHNIX_CM is not set
+# CONFIG_BFIN561_EZKIT is not set
+# CONFIG_BFIN561_TEPLA is not set
+# CONFIG_PNAV10 is not set
+# CONFIG_GENERIC_BOARD is not set
+CONFIG_MEM_MT48LC32M16A2TG_75=y
+
+#
+# BF527 Specific Configuration
+#
+
+#
+# Alternative Multiplexing Scheme
+#
+# CONFIG_BF527_SPORT0_PORTF is not set
+CONFIG_BF527_SPORT0_PORTG=y
+CONFIG_BF527_SPORT0_TSCLK_PG10=y
+# CONFIG_BF527_SPORT0_TSCLK_PG14 is not set
+# CONFIG_BF527_UART1_PORTF is not set
+CONFIG_BF527_UART1_PORTG=y
+# CONFIG_BF527_NAND_D_PORTF is not set
+CONFIG_BF527_NAND_D_PORTH=y
+
+#
+# Interrupt Priority Assignment
+#
+
+#
+# Priority
+#
+CONFIG_IRQ_PLL_WAKEUP=7
+CONFIG_IRQ_DMA0_ERROR=7
+CONFIG_IRQ_DMAR0_BLK=7
+CONFIG_IRQ_DMAR1_BLK=7
+CONFIG_IRQ_DMAR0_OVR=7
+CONFIG_IRQ_DMAR1_OVR=7
+CONFIG_IRQ_PPI_ERROR=7
+CONFIG_IRQ_MAC_ERROR=7
+CONFIG_IRQ_SPORT0_ERROR=7
+CONFIG_IRQ_SPORT1_ERROR=7
+CONFIG_IRQ_UART0_ERROR=7
+CONFIG_IRQ_UART1_ERROR=7
+CONFIG_IRQ_RTC=8
+CONFIG_IRQ_PPI=8
+CONFIG_IRQ_SPORT0_RX=9
+CONFIG_IRQ_SPORT0_TX=9
+CONFIG_IRQ_SPORT1_RX=9
+CONFIG_IRQ_SPORT1_TX=9
+CONFIG_IRQ_TWI=10
+CONFIG_IRQ_SPI=10
+CONFIG_IRQ_UART0_RX=10
+CONFIG_IRQ_UART0_TX=10
+CONFIG_IRQ_UART1_RX=10
+CONFIG_IRQ_UART1_TX=10
+CONFIG_IRQ_OPTSEC=11
+CONFIG_IRQ_CNT=11
+CONFIG_IRQ_MAC_RX=11
+CONFIG_IRQ_PORTH_INTA=11
+CONFIG_IRQ_MAC_TX=11
+CONFIG_IRQ_PORTH_INTB=11
+CONFIG_IRQ_TMR0=12
+CONFIG_IRQ_TMR1=12
+CONFIG_IRQ_TMR2=12
+CONFIG_IRQ_TMR3=12
+CONFIG_IRQ_TMR4=12
+CONFIG_IRQ_TMR5=12
+CONFIG_IRQ_TMR6=12
+CONFIG_IRQ_TMR7=12
+CONFIG_IRQ_PORTG_INTA=12
+CONFIG_IRQ_PORTG_INTB=12
+CONFIG_IRQ_MEM_DMA0=13
+CONFIG_IRQ_MEM_DMA1=13
+CONFIG_IRQ_WATCH=13
+CONFIG_IRQ_PORTF_INTA=13
+CONFIG_IRQ_PORTF_INTB=13
+CONFIG_IRQ_SPI_ERROR=7
+CONFIG_IRQ_NFC_ERROR=7
+CONFIG_IRQ_HDMA_ERROR=7
+CONFIG_IRQ_HDMA=7
+CONFIG_IRQ_USB_EINT=10
+CONFIG_IRQ_USB_INT0=11
+CONFIG_IRQ_USB_INT1=11
+CONFIG_IRQ_USB_INT2=11
+CONFIG_IRQ_USB_DMA=11
+
+#
+# Board customizations
+#
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Clock/PLL Setup
+#
+CONFIG_CLKIN_HZ=25000000
+# CONFIG_BFIN_KERNEL_CLOCK is not set
+CONFIG_MAX_VCO_HZ=600000000
+CONFIG_MIN_VCO_HZ=50000000
+CONFIG_MAX_SCLK_HZ=133333333
+CONFIG_MIN_SCLK_HZ=27000000
+
+#
+# Kernel Timer/Scheduler
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+
+#
+# Memory Setup
+#
+CONFIG_MEM_SIZE=64
+CONFIG_MEM_ADD_WIDTH=10
+CONFIG_BOOT_LOAD=0x1000
+CONFIG_BFIN_SCRATCH_REG_RETN=y
+# CONFIG_BFIN_SCRATCH_REG_RETE is not set
+# CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
+
+#
+# Blackfin Kernel Optimizations
+#
+
+#
+# Memory Optimizations
+#
+CONFIG_I_ENTRY_L1=y
+CONFIG_EXCPT_IRQ_SYSC_L1=y
+CONFIG_DO_IRQ_L1=y
+CONFIG_CORE_TIMER_IRQ_L1=y
+CONFIG_IDLE_L1=y
+# CONFIG_SCHEDULE_L1 is not set
+CONFIG_ARITHMETIC_OPS_L1=y
+CONFIG_ACCESS_OK_L1=y
+# CONFIG_MEMSET_L1 is not set
+# CONFIG_MEMCPY_L1 is not set
+# CONFIG_SYS_BFIN_SPINLOCK_L1 is not set
+# CONFIG_IP_CHECKSUM_L1 is not set
+CONFIG_CACHELINE_ALIGNED_L1=y
+# CONFIG_SYSCALL_TAB_L1 is not set
+# CONFIG_CPLB_SWITCH_TAB_L1 is not set
+CONFIG_RAMKERNEL=y
+# CONFIG_ROMKERNEL 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_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_LARGE_ALLOCS=y
+CONFIG_BFIN_DMA_5XX=y
+# CONFIG_DMA_UNCACHED_2M is not set
+CONFIG_DMA_UNCACHED_1M=y
+# CONFIG_DMA_UNCACHED_NONE is not set
+
+#
+# Cache Support
+#
+CONFIG_BFIN_ICACHE=y
+CONFIG_BFIN_DCACHE=y
+# CONFIG_BFIN_DCACHE_BANKA is not set
+# CONFIG_BFIN_ICACHE_LOCK is not set
+# CONFIG_BFIN_WB is not set
+CONFIG_BFIN_WT=y
+CONFIG_L1_MAX_PIECE=16
+
+#
+# Asynchonous Memory Configuration
+#
+
+#
+# EBIU_AMBCTL Global Control
+#
+CONFIG_C_AMCKEN=y
+CONFIG_C_CDPRIO=y
+# CONFIG_C_AMBEN is not set
+# CONFIG_C_AMBEN_B0 is not set
+# CONFIG_C_AMBEN_B0_B1 is not set
+# CONFIG_C_AMBEN_B0_B1_B2 is not set
+CONFIG_C_AMBEN_ALL=y
+
+#
+# EBIU_AMBCTL Control
+#
+CONFIG_BANK_0=0x7BB0
+CONFIG_BANK_1=0x5554
+CONFIG_BANK_2=0x7BB0
+CONFIG_BANK_3=0xFFC0
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF_FDPIC=y
+CONFIG_BINFMT_FLAT=y
+CONFIG_BINFMT_ZFLAT=y
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+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_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+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_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_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETLABEL 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_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
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_MW320D=m
+CONFIG_MTD_RAM=y
+CONFIG_MTD_ROM=m
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_BF5xx=m
+CONFIG_BFIN_FLASH_SIZE=0x400000
+CONFIG_EBIU_FLASH_BASE=0x20000000
+# CONFIG_MTD_UCLINUX is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+CONFIG_MTD_NAND_BFIN=m
+CONFIG_BFIN_NAND_BASE=0x20212000
+CONFIG_BFIN_NAND_CLE=2
+CONFIG_BFIN_NAND_ALE=1
+CONFIG_BFIN_NAND_READY=3
+CONFIG_MTD_NAND_IDS=m
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNPACPI is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN 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_FIXED_PHY is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_SMC91X is not set
+CONFIG_BFIN_MAC=y
+CONFIG_BFIN_MAC_USE_L1=y
+CONFIG_BFIN_TX_DESC_NUM=10
+CONFIG_BFIN_RX_DESC_NUM=20
+CONFIG_BFIN_MAC_RMII=y
+# CONFIG_SMSC911X is not set
+# CONFIG_DM9000 is not set
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# 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 is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_UINPUT is not set
+# CONFIG_BF53X_PFBUTTONS is not set
+# CONFIG_TWI_KEYPAD is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_AD9960 is not set
+# CONFIG_SPI_ADC_BF533 is not set
+# CONFIG_BF5xx_PFLAGS is not set
+# CONFIG_BF5xx_PPIFCD is not set
+# CONFIG_BF5xx_TIMERS is not set
+# CONFIG_BF5xx_PPI is not set
+# CONFIG_BFIN_SPORT is not set
+# CONFIG_BFIN_TIMER_LATENCY is not set
+# CONFIG_TWI_LCD is not set
+# CONFIG_AD5304 is not set
+# CONFIG_BF5xx_TEA5764 is not set
+# CONFIG_BF5xx_FBDMA is not set
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_BFIN=y
+CONFIG_SERIAL_BFIN_CONSOLE=y
+# CONFIG_SERIAL_BFIN_DMA is not set
+CONFIG_SERIAL_BFIN_PIO=y
+# CONFIG_SERIAL_BFIN_UART0 is not set
+CONFIG_SERIAL_BFIN_UART1=y
+# CONFIG_BFIN_UART1_CTSRTS is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_BFIN_SPORT is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# CAN, the car bus and industrial fieldbus
+#
+# CONFIG_CAN4LINUX is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_BFIN_WDT=y
+CONFIG_HW_RANDOM=y
+# CONFIG_GEN_RTC is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_BLACKFIN_GPIO is not set
+CONFIG_I2C_BLACKFIN_TWI=m
+CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=50
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_AD5252 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8575 is not set
+# CONFIG_SENSORS_PCA9543 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 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
+
+#
+# SPI support
+#
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BFIN=y
+# CONFIG_SPI_BITBANG is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_AT25 is not set
+# CONFIG_SPI_SPIDEV is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU 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_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS 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_LM70 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_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VT1211 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_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+
+#
+# Enable Host or Gadget support to see Inventra options
+#
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_BFIN=y
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# PBX support
+#
+# CONFIG_PBX is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# 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_YAFFS_FS=m
+CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_DOES_ECC is not set
+CONFIG_YAFFS_YAFFS2=y
+CONFIG_YAFFS_AUTO_YAFFS2=y
+# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
+CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
+# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
+# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
+CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_MMRS=y
+CONFIG_DEBUG_HUNT_FOR_ZERO=y
+CONFIG_DEBUG_BFIN_HWTRACE_ON=y
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
+# CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
+# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
+CONFIG_EARLY_PRINTK=y
+CONFIG_CPLB_INFO=y
+CONFIG_ACCESS_CHECK=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITY_NETWORK is not set
+CONFIG_SECURITY_CAPABILITIES=y
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/blackfin/configs/BF533-EZKIT_defconfig b/arch/blackfin/configs/BF533-EZKIT_defconfig
index 57f58d5cd47a..9e9b420342d1 100644
--- a/arch/blackfin/configs/BF533-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF533-EZKIT_defconfig
@@ -198,7 +198,7 @@ CONFIG_CLKIN_HZ=27000000
# CONFIG_BFIN_KERNEL_CLOCK is not set
CONFIG_MAX_VCO_HZ=750000000
CONFIG_MIN_VCO_HZ=50000000
-CONFIG_MAX_SCLK_HZ=133000000
+CONFIG_MAX_SCLK_HZ=133333333
CONFIG_MIN_SCLK_HZ=27000000
#
diff --git a/arch/blackfin/configs/BF533-STAMP_defconfig b/arch/blackfin/configs/BF533-STAMP_defconfig
index 306302baff06..f59ade980109 100644
--- a/arch/blackfin/configs/BF533-STAMP_defconfig
+++ b/arch/blackfin/configs/BF533-STAMP_defconfig
@@ -199,7 +199,7 @@ CONFIG_CLKIN_HZ=11059200
# CONFIG_BFIN_KERNEL_CLOCK is not set
CONFIG_MAX_VCO_HZ=750000000
CONFIG_MIN_VCO_HZ=50000000
-CONFIG_MAX_SCLK_HZ=133000000
+CONFIG_MAX_SCLK_HZ=133333333
CONFIG_MIN_SCLK_HZ=27000000
#
diff --git a/arch/blackfin/configs/BF537-STAMP_defconfig b/arch/blackfin/configs/BF537-STAMP_defconfig
index 828b604438eb..07eb63dc25e0 100644
--- a/arch/blackfin/configs/BF537-STAMP_defconfig
+++ b/arch/blackfin/configs/BF537-STAMP_defconfig
@@ -206,7 +206,7 @@ CONFIG_CLKIN_HZ=25000000
# CONFIG_BFIN_KERNEL_CLOCK is not set
CONFIG_MAX_VCO_HZ=600000000
CONFIG_MIN_VCO_HZ=50000000
-CONFIG_MAX_SCLK_HZ=133000000
+CONFIG_MAX_SCLK_HZ=133333333
CONFIG_MIN_SCLK_HZ=27000000
#
diff --git a/arch/blackfin/configs/BF548-EZKIT_defconfig b/arch/blackfin/configs/BF548-EZKIT_defconfig
index e80f3d59c283..0dd3d2253dc2 100644
--- a/arch/blackfin/configs/BF548-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF548-EZKIT_defconfig
@@ -1,6 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.22.6
+# Linux kernel version: 2.6.22.10
+# Sat Oct 27 02:34:07 2007
#
# CONFIG_MMU is not set
# CONFIG_FPU is not set
@@ -64,7 +65,6 @@ CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
@@ -117,6 +117,9 @@ CONFIG_PREEMPT_VOLUNTARY=y
#
# Processor and Board Settings
#
+# CONFIG_BF522 is not set
+# CONFIG_BF525 is not set
+# CONFIG_BF527 is not set
# CONFIG_BF531 is not set
# CONFIG_BF532 is not set
# CONFIG_BF533 is not set
@@ -129,6 +132,7 @@ CONFIG_PREEMPT_VOLUNTARY=y
CONFIG_BF549=y
# CONFIG_BF561 is not set
CONFIG_BF_REV_0_0=y
+# CONFIG_BF_REV_0_1 is not set
# CONFIG_BF_REV_0_2 is not set
# CONFIG_BF_REV_0_3 is not set
# CONFIG_BF_REV_0_4 is not set
@@ -137,6 +141,7 @@ CONFIG_BF_REV_0_0=y
# CONFIG_BF_REV_NONE is not set
CONFIG_BF54x=y
CONFIG_BFIN_SINGLE_CORE=y
+# CONFIG_BFIN527_EZKIT is not set
# CONFIG_BFIN533_EZKIT is not set
# CONFIG_BFIN533_STAMP is not set
# CONFIG_BFIN537_STAMP is not set
@@ -147,8 +152,23 @@ CONFIG_BFIN548_EZKIT=y
# CONFIG_BFIN561_EZKIT is not set
# CONFIG_BFIN561_TEPLA is not set
# CONFIG_PNAV10 is not set
+# CONFIG_H8606_HVSISTEMAS is not set
# CONFIG_GENERIC_BOARD is not set
CONFIG_IRQ_PLL_WAKEUP=7
+CONFIG_IRQ_RTC=8
+CONFIG_IRQ_SPORT0_RX=9
+CONFIG_IRQ_SPORT0_TX=9
+CONFIG_IRQ_SPORT1_RX=9
+CONFIG_IRQ_SPORT1_TX=9
+CONFIG_IRQ_UART0_RX=10
+CONFIG_IRQ_UART0_TX=10
+CONFIG_IRQ_UART1_RX=10
+CONFIG_IRQ_UART1_TX=10
+CONFIG_IRQ_CNT=8
+CONFIG_IRQ_USB_INT0=11
+CONFIG_IRQ_USB_INT1=11
+CONFIG_IRQ_USB_INT2=11
+CONFIG_IRQ_USB_DMA=11
CONFIG_IRQ_TIMER0=11
CONFIG_IRQ_TIMER1=11
CONFIG_IRQ_TIMER2=11
@@ -160,15 +180,6 @@ CONFIG_IRQ_TIMER7=11
CONFIG_IRQ_TIMER8=11
CONFIG_IRQ_TIMER9=11
CONFIG_IRQ_TIMER10=11
-CONFIG_IRQ_RTC=8
-CONFIG_IRQ_SPORT0_RX=9
-CONFIG_IRQ_SPORT0_TX=9
-CONFIG_IRQ_SPORT1_RX=9
-CONFIG_IRQ_SPORT1_TX=9
-CONFIG_IRQ_UART0_RX=10
-CONFIG_IRQ_UART0_TX=10
-CONFIG_IRQ_UART1_RX=10
-CONFIG_IRQ_UART1_TX=10
#
# BF548 Specific Configuration
@@ -236,16 +247,11 @@ CONFIG_IRQ_PIXC_IN0=8
CONFIG_IRQ_PIXC_IN1=8
CONFIG_IRQ_PIXC_OUT=8
CONFIG_IRQ_SDH=8
-CONFIG_IRQ_CNT=8
CONFIG_IRQ_KEY=8
CONFIG_IRQ_CAN1_RX=11
CONFIG_IRQ_CAN1_TX=11
CONFIG_IRQ_SDH_MASK0=11
CONFIG_IRQ_SDH_MASK1=11
-CONFIG_IRQ_USB_INT0=11
-CONFIG_IRQ_USB_INT1=11
-CONFIG_IRQ_USB_INT2=11
-CONFIG_IRQ_USB_DMA=11
CONFIG_IRQ_OTPSEC=11
CONFIG_IRQ_PINT2=11
CONFIG_IRQ_PINT3=11
@@ -273,9 +279,9 @@ CONFIG_PINT3_ASSIGN=0x02020303
#
CONFIG_CLKIN_HZ=25000000
# CONFIG_BFIN_KERNEL_CLOCK is not set
-CONFIG_MAX_VCO_HZ=533000000
+CONFIG_MAX_VCO_HZ=533333333
CONFIG_MIN_VCO_HZ=50000000
-CONFIG_MAX_SCLK_HZ=133000000
+CONFIG_MAX_SCLK_HZ=133333333
CONFIG_MIN_SCLK_HZ=27000000
#
@@ -332,9 +338,10 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_LARGE_ALLOCS=y
+# CONFIG_BFIN_GPTIMERS is not set
CONFIG_BFIN_DMA_5XX=y
-# CONFIG_DMA_UNCACHED_2M is not set
-CONFIG_DMA_UNCACHED_1M=y
+CONFIG_DMA_UNCACHED_2M=y
+# CONFIG_DMA_UNCACHED_1M is not set
# CONFIG_DMA_UNCACHED_NONE is not set
#
@@ -353,7 +360,7 @@ CONFIG_L1_MAX_PIECE=16
#
#
-# EBIU_AMBCTL Global Control
+# EBIU_AMGCTL Global Control
#
CONFIG_C_AMCKEN=y
# CONFIG_C_AMBEN is not set
@@ -722,7 +729,7 @@ CONFIG_NETDEV_10000=y
#
# Input device support
#
-CONFIG_INPUT=y
+CONFIG_INPUT=m
# CONFIG_INPUT_FF_MEMLESS is not set
# CONFIG_INPUT_POLLDEV is not set
@@ -731,18 +738,39 @@ CONFIG_INPUT=y
#
# CONFIG_INPUT_MOUSEDEV is not set
# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
+CONFIG_INPUT_TSDEV=m
+CONFIG_INPUT_TSDEV_SCREEN_X=240
+CONFIG_INPUT_TSDEV_SCREEN_Y=320
+CONFIG_INPUT_EVDEV=m
+CONFIG_INPUT_EVBUG=m
#
# Input Device Drivers
#
-# CONFIG_INPUT_KEYBOARD is not set
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# 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_KEYBOARD_GPIO is not set
+CONFIG_KEYBOARD_BFIN=m
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TABLET is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
+CONFIG_TOUCHSCREEN_AD7877=m
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_UCB1400 is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
CONFIG_INPUT_MISC=y
# CONFIG_INPUT_ATI_REMOTE is not set
# CONFIG_INPUT_ATI_REMOTE2 is not set
@@ -764,9 +792,9 @@ CONFIG_INPUT_MISC=y
#
# CONFIG_AD9960 is not set
# CONFIG_SPI_ADC_BF533 is not set
-# CONFIG_BFIN_PFLAGS is not set
+# CONFIG_BF5xx_PFLAGS is not set
# CONFIG_BF5xx_PPIFCD is not set
-# CONFIG_BF5xx_TIMERS is not set
+# CONFIG_BFIN_SIMPLE_TIMER is not set
# CONFIG_BF5xx_PPI is not set
# CONFIG_BFIN_SPORT is not set
# CONFIG_BFIN_TIMER_LATENCY is not set
@@ -809,7 +837,14 @@ CONFIG_UNIX98_PTYS=y
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-# CONFIG_WATCHDOG is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_BFIN_WDT=y
CONFIG_HW_RANDOM=y
# CONFIG_GEN_RTC is not set
# CONFIG_R3964 is not set
@@ -951,17 +986,92 @@ CONFIG_DAB=y
#
# CONFIG_DISPLAY_SUPPORT is not set
# CONFIG_VGASTATE is not set
-# CONFIG_FB is not set
+CONFIG_FB=m
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
+CONFIG_FB_CFB_FILLRECT=m
+CONFIG_FB_CFB_COPYAREA=m
+CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_BFIN_7171 is not set
+# CONFIG_FB_BFIN_7393 is not set
+CONFIG_FB_BF54X_LQ043=m
+# CONFIG_FB_BFIN_T350MCQB is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_LOGO is not set
#
# Sound
#
-# CONFIG_SOUND is not set
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ALSA Blackfin devices
+#
+# CONFIG_SND_BLACKFIN_AD1836 is not set
+# CONFIG_SND_BFIN_AD73311 is not set
+
+#
+# System on Chip audio support
+#
+CONFIG_SND_SOC_AC97_BUS=y
+CONFIG_SND_SOC=y
+CONFIG_SND_BF5XX_SOC=y
+CONFIG_SND_BF5XX_SOC_AC97=y
+CONFIG_SND_BF5XX_SOC_BF548_EZKIT=y
+CONFIG_SND_BF5XX_SPORT_NUM=0
+# CONFIG_SND_BF5XX_HAVE_COLD_RESET is not set
+CONFIG_SND_SOC_AD1980=y
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=y
#
# HID Devices
#
-CONFIG_HID=y
+CONFIG_HID=m
# CONFIG_HID_DEBUG is not set
#
@@ -1094,8 +1204,13 @@ CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
# CONFIG_EXT2_FS_POSIX_ACL is not set
# CONFIG_EXT2_FS_SECURITY is not set
-# CONFIG_EXT3_FS is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
@@ -1116,15 +1231,22 @@ CONFIG_DNOTIFY=y
#
# CD-ROM/DVD Filesystems
#
-# CONFIG_ISO9660_FS is not set
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
# CONFIG_UDF_FS is not set
#
# DOS/FAT/NT Filesystems
#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_NTFS_FS is not set
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
#
# Pseudo filesystems
@@ -1176,10 +1298,33 @@ CONFIG_JFFS2_RTIME=y
#
# Network File Systems
#
-# CONFIG_NFS_FS is not set
-# CONFIG_NFSD is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp437"
+CONFIG_CIFS=y
+# 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
@@ -1188,13 +1333,68 @@ CONFIG_JFFS2_RTIME=y
#
# Partition Types
#
-# CONFIG_PARTITION_ADVANCED is not set
+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 is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
#
# Native Language Support
#
-# CONFIG_NLS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+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=m
+CONFIG_NLS_ISO8859_1=m
+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
#
# Distributed Lock Manager
diff --git a/arch/blackfin/configs/BF561-EZKIT_defconfig b/arch/blackfin/configs/BF561-EZKIT_defconfig
index 85e647f87759..277d72dac0f9 100644
--- a/arch/blackfin/configs/BF561-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF561-EZKIT_defconfig
@@ -243,7 +243,7 @@ CONFIG_CLKIN_HZ=30000000
# CONFIG_BFIN_KERNEL_CLOCK is not set
CONFIG_MAX_VCO_HZ=600000000
CONFIG_MIN_VCO_HZ=50000000
-CONFIG_MAX_SCLK_HZ=133000000
+CONFIG_MAX_SCLK_HZ=133333333
CONFIG_MIN_SCLK_HZ=27000000
#
diff --git a/arch/blackfin/configs/PNAV-10_defconfig b/arch/blackfin/configs/PNAV-10_defconfig
index 15e36aaf2186..3d403e0b82c2 100644
--- a/arch/blackfin/configs/PNAV-10_defconfig
+++ b/arch/blackfin/configs/PNAV-10_defconfig
@@ -204,7 +204,7 @@ CONFIG_CLKIN_HZ=24576000
# CONFIG_BFIN_KERNEL_CLOCK is not set
CONFIG_MAX_VCO_HZ=600000000
CONFIG_MIN_VCO_HZ=50000000
-CONFIG_MAX_SCLK_HZ=133000000
+CONFIG_MAX_SCLK_HZ=133333333
CONFIG_MIN_SCLK_HZ=27000000
#
diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile
index 8aeb6066b19b..8a4cfb293b27 100644
--- a/arch/blackfin/kernel/Makefile
+++ b/arch/blackfin/kernel/Makefile
@@ -9,6 +9,7 @@ obj-y := \
sys_bfin.o time.o traps.o irqchip.o dma-mapping.o flat.o \
fixed_code.o cplbinit.o cacheinit.o reboot.o bfin_gpio.o
+obj-$(CONFIG_BFIN_GPTIMERS) += gptimers.o
obj-$(CONFIG_MODULES) += module.o
obj-$(CONFIG_BFIN_DMA_5XX) += bfin_dma_5xx.o
obj-$(CONFIG_DUAL_CORE_TEST_MODULE) += dualcore_test.o
diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c
index e19164fb4cd1..503eef4c7fec 100644
--- a/arch/blackfin/kernel/bfin_dma_5xx.c
+++ b/arch/blackfin/kernel/bfin_dma_5xx.c
@@ -420,6 +420,32 @@ unsigned short get_dma_curr_ycount(unsigned int channel)
}
EXPORT_SYMBOL(get_dma_curr_ycount);
+unsigned long get_dma_next_desc_ptr(unsigned int channel)
+{
+ BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+ && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+ return dma_ch[channel].regs->next_desc_ptr;
+}
+EXPORT_SYMBOL(get_dma_next_desc_ptr);
+
+unsigned long get_dma_curr_desc_ptr(unsigned int channel)
+{
+ BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+ && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+ return dma_ch[channel].regs->curr_desc_ptr;
+}
+
+unsigned long get_dma_curr_addr(unsigned int channel)
+{
+ BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+ && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+ return dma_ch[channel].regs->curr_addr_ptr;
+}
+EXPORT_SYMBOL(get_dma_curr_addr);
+
static void *__dma_memcpy(void *dest, const void *src, size_t size)
{
int direction; /* 1 - address decrease, 0 - address increase */
diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c
index 3fe0cd49e8db..ce85d4bf34ca 100644
--- a/arch/blackfin/kernel/bfin_gpio.c
+++ b/arch/blackfin/kernel/bfin_gpio.c
@@ -124,7 +124,7 @@ static struct gpio_port_t *gpio_bankb[gpio_bank(MAX_BLACKFIN_GPIOS)] = {
};
#endif
-#ifdef BF537_FAMILY
+#if defined(BF527_FAMILY) || defined(BF537_FAMILY)
static struct gpio_port_t *gpio_bankb[gpio_bank(MAX_BLACKFIN_GPIOS)] = {
(struct gpio_port_t *) PORTFIO,
(struct gpio_port_t *) PORTGIO,
@@ -139,6 +139,21 @@ static unsigned short *port_fer[gpio_bank(MAX_BLACKFIN_GPIOS)] = {
#endif
+#ifdef BF527_FAMILY
+static unsigned short *port_mux[gpio_bank(MAX_BLACKFIN_GPIOS)] = {
+ (unsigned short *) PORTF_MUX,
+ (unsigned short *) PORTG_MUX,
+ (unsigned short *) PORTH_MUX,
+};
+
+static const
+u8 pmux_offset[][16] =
+ {{ 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 4, 6, 8, 8, 10, 10 }, /* PORTF */
+ { 0, 0, 0, 0, 0, 2, 2, 4, 4, 6, 8, 10, 10, 10, 12, 12 }, /* PORTG */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 4, 4, 4, 4, 4 }, /* PORTH */
+ };
+#endif
+
#ifdef BF561_FAMILY
static struct gpio_port_t *gpio_bankb[gpio_bank(MAX_BLACKFIN_GPIOS)] = {
(struct gpio_port_t *) FIO0_FLAG_D,
@@ -186,6 +201,10 @@ static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PROG_INTB
static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PROG_INTB, IRQ_PORTG_INTB, IRQ_MAC_TX};
#endif
+#ifdef BF527_FAMILY
+static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PORTF_INTB, IRQ_PORTG_INTB, IRQ_PORTH_INTB};
+#endif
+
#ifdef BF561_FAMILY
static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PROG0_INTB, IRQ_PROG1_INTB, IRQ_PROG2_INTB};
#endif
@@ -238,7 +257,7 @@ static int cmp_label(unsigned short ident, const char *label)
return -EINVAL;
}
-#ifdef BF537_FAMILY
+#if defined(BF527_FAMILY) || defined(BF537_FAMILY)
static void port_setup(unsigned short gpio, unsigned short usage)
{
if (!check_gpio(gpio)) {
@@ -354,6 +373,18 @@ inline u16 get_portmux(unsigned short portno)
return (pmux >> (2 * gpio_sub_n(portno)) & 0x3);
}
+#elif defined(BF527_FAMILY)
+inline void portmux_setup(unsigned short portno, unsigned short function)
+{
+ u16 pmux, ident = P_IDENT(portno);
+ u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)];
+
+ pmux = *port_mux[gpio_bank(ident)];
+ pmux &= ~(3 << offset);
+ pmux |= (function & 3) << offset;
+ *port_mux[gpio_bank(ident)] = pmux;
+ SSYNC();
+}
#else
# define portmux_setup(...) do { } while (0)
#endif
diff --git a/arch/blackfin/kernel/dma-mapping.c b/arch/blackfin/kernel/dma-mapping.c
index 94d7b119b71e..d6b61d56b656 100644
--- a/arch/blackfin/kernel/dma-mapping.c
+++ b/arch/blackfin/kernel/dma-mapping.c
@@ -35,6 +35,7 @@
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/io.h>
+#include <linux/scatterlist.h>
#include <asm/cacheflush.h>
#include <asm/bfin-global.h>
@@ -160,8 +161,7 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
BUG_ON(direction == DMA_NONE);
for (i = 0; i < nents; i++, sg++) {
- sg->dma_address = (dma_addr_t)(page_address(sg->page) +
- sg->offset);
+ sg->dma_address = (dma_addr_t) sg_virt(sg);
invalidate_dcache_range(sg_dma_address(sg),
sg_dma_address(sg) +
diff --git a/arch/blackfin/kernel/entry.S b/arch/blackfin/kernel/entry.S
index 65c5ba4260b0..65f4e67a65c4 100644
--- a/arch/blackfin/kernel/entry.S
+++ b/arch/blackfin/kernel/entry.S
@@ -54,9 +54,11 @@ ENTRY(_ret_from_fork)
[sp + PT_IPEND] = r0;
/* do a 'fake' RTI by jumping to [RETI]
* to avoid clearing supervisor mode in child
- */
+ */
+ r0 = [sp + PT_PC];
+ [sp + PT_P0] = r0;
+
RESTORE_ALL_SYS
- p0 = reti;
jump (p0);
ENDPROC(_ret_from_fork)
diff --git a/arch/blackfin/kernel/fixed_code.S b/arch/blackfin/kernel/fixed_code.S
index d8b1ebc70996..90262691b11a 100644
--- a/arch/blackfin/kernel/fixed_code.S
+++ b/arch/blackfin/kernel/fixed_code.S
@@ -129,4 +129,18 @@ ENTRY(_atomic_xor32)
rts;
ENDPROC (_atomic_ior32)
+.align 16
+ /*
+ * safe_user_instruction
+ * Four NOPS are enough to allow the pipeline to speculativily load
+ * execute anything it wants. After that, things have gone bad, and
+ * we are stuck - so panic. Since we might be in user space, we can't
+ * call panic, so just cause a unhandled exception, this should cause
+ * a dump of the trace buffer so we can tell were we are, and a reboot
+ */
+ENTRY(_safe_user_instruction)
+ NOP; NOP; NOP; NOP;
+ EXCPT 0x4;
+ENDPROC(_safe_user_instruction)
+
ENTRY(_fixed_code_end)
diff --git a/arch/blackfin/kernel/gptimers.c b/arch/blackfin/kernel/gptimers.c
new file mode 100644
index 000000000000..5cf4bdb1df3b
--- /dev/null
+++ b/arch/blackfin/kernel/gptimers.c
@@ -0,0 +1,283 @@
+/*
+ * bfin_gptimers.c - derived from bf53x_timers.c
+ * Driver for General Purpose Timer functions on the Blackfin processor
+ *
+ * Copyright (C) 2005 John DeHority
+ * Copyright (C) 2006 Hella Aglaia GmbH (awe@aglaia-gmbh.de)
+ *
+ * Licensed under the GPLv2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include <asm/io.h>
+#include <asm/blackfin.h>
+#include <asm/gptimers.h>
+
+#ifdef DEBUG
+# define tassert(expr)
+#else
+# define tassert(expr) \
+ if (!(expr)) \
+ printk(KERN_DEBUG "%s:%s:%i: Assertion failed: " #expr "\n", __FILE__, __func__, __LINE__);
+#endif
+
+#define BFIN_TIMER_NUM_GROUP (BFIN_TIMER_OCTET(MAX_BLACKFIN_GPTIMERS - 1) + 1)
+
+typedef struct {
+ uint16_t config;
+ uint16_t __pad;
+ uint32_t counter;
+ uint32_t period;
+ uint32_t width;
+} GPTIMER_timer_regs;
+
+typedef struct {
+ uint16_t enable;
+ uint16_t __pad0;
+ uint16_t disable;
+ uint16_t __pad1;
+ uint32_t status;
+} GPTIMER_group_regs;
+
+static volatile GPTIMER_timer_regs *const timer_regs[MAX_BLACKFIN_GPTIMERS] =
+{
+ (GPTIMER_timer_regs *)TIMER0_CONFIG,
+ (GPTIMER_timer_regs *)TIMER1_CONFIG,
+ (GPTIMER_timer_regs *)TIMER2_CONFIG,
+#if (MAX_BLACKFIN_GPTIMERS > 3)
+ (GPTIMER_timer_regs *)TIMER3_CONFIG,
+ (GPTIMER_timer_regs *)TIMER4_CONFIG,
+ (GPTIMER_timer_regs *)TIMER5_CONFIG,
+ (GPTIMER_timer_regs *)TIMER6_CONFIG,
+ (GPTIMER_timer_regs *)TIMER7_CONFIG,
+#endif
+#if (MAX_BLACKFIN_GPTIMERS > 8)
+ (GPTIMER_timer_regs *)TIMER8_CONFIG,
+ (GPTIMER_timer_regs *)TIMER9_CONFIG,
+ (GPTIMER_timer_regs *)TIMER10_CONFIG,
+ (GPTIMER_timer_regs *)TIMER11_CONFIG,
+#endif
+};
+
+static volatile GPTIMER_group_regs *const group_regs[BFIN_TIMER_NUM_GROUP] =
+{
+ (GPTIMER_group_regs *)TIMER0_GROUP_REG,
+#if (MAX_BLACKFIN_GPTIMERS > 8)
+ (GPTIMER_group_regs *)TIMER8_GROUP_REG,
+#endif
+};
+
+static uint32_t const trun_mask[MAX_BLACKFIN_GPTIMERS] =
+{
+ TIMER_STATUS_TRUN0,
+ TIMER_STATUS_TRUN1,
+ TIMER_STATUS_TRUN2,
+#if (MAX_BLACKFIN_GPTIMERS > 3)
+ TIMER_STATUS_TRUN3,
+ TIMER_STATUS_TRUN4,
+ TIMER_STATUS_TRUN5,
+ TIMER_STATUS_TRUN6,
+ TIMER_STATUS_TRUN7,
+#endif
+#if (MAX_BLACKFIN_GPTIMERS > 8)
+ TIMER_STATUS_TRUN8,
+ TIMER_STATUS_TRUN9,
+ TIMER_STATUS_TRUN10,
+ TIMER_STATUS_TRUN11,
+#endif
+};
+
+static uint32_t const tovf_mask[MAX_BLACKFIN_GPTIMERS] =
+{
+ TIMER_STATUS_TOVF0,
+ TIMER_STATUS_TOVF1,
+ TIMER_STATUS_TOVF2,
+#if (MAX_BLACKFIN_GPTIMERS > 3)
+ TIMER_STATUS_TOVF3,
+ TIMER_STATUS_TOVF4,
+ TIMER_STATUS_TOVF5,
+ TIMER_STATUS_TOVF6,
+ TIMER_STATUS_TOVF7,
+#endif
+#if (MAX_BLACKFIN_GPTIMERS > 8)
+ TIMER_STATUS_TOVF8,
+ TIMER_STATUS_TOVF9,
+ TIMER_STATUS_TOVF10,
+ TIMER_STATUS_TOVF11,
+#endif
+};
+
+static uint32_t const timil_mask[MAX_BLACKFIN_GPTIMERS] =
+{
+ TIMER_STATUS_TIMIL0,
+ TIMER_STATUS_TIMIL1,
+ TIMER_STATUS_TIMIL2,
+#if (MAX_BLACKFIN_GPTIMERS > 3)
+ TIMER_STATUS_TIMIL3,
+ TIMER_STATUS_TIMIL4,
+ TIMER_STATUS_TIMIL5,
+ TIMER_STATUS_TIMIL6,
+ TIMER_STATUS_TIMIL7,
+#endif
+#if (MAX_BLACKFIN_GPTIMERS > 8)
+ TIMER_STATUS_TIMIL8,
+ TIMER_STATUS_TIMIL9,
+ TIMER_STATUS_TIMIL10,
+ TIMER_STATUS_TIMIL11,
+#endif
+};
+
+void set_gptimer_pwidth(int timer_id, uint32_t value)
+{
+ tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
+ timer_regs[timer_id]->width = value;
+ SSYNC();
+}
+EXPORT_SYMBOL(set_gptimer_pwidth);
+
+uint32_t get_gptimer_pwidth(int timer_id)
+{
+ tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
+ return timer_regs[timer_id]->width;
+}
+EXPORT_SYMBOL(get_gptimer_pwidth);
+
+void set_gptimer_period(int timer_id, uint32_t period)
+{
+ tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
+ timer_regs[timer_id]->period = period;
+ SSYNC();
+}
+EXPORT_SYMBOL(set_gptimer_period);
+
+uint32_t get_gptimer_period(int timer_id)
+{
+ tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
+ return timer_regs[timer_id]->period;
+}
+EXPORT_SYMBOL(get_gptimer_period);
+
+uint32_t get_gptimer_count(int timer_id)
+{
+ tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
+ return timer_regs[timer_id]->counter;
+}
+EXPORT_SYMBOL(get_gptimer_count);
+
+uint32_t get_gptimer_status(int group)
+{
+ tassert(group < BFIN_TIMER_NUM_GROUP);
+ return group_regs[group]->status;
+}
+EXPORT_SYMBOL(get_gptimer_status);
+
+void set_gptimer_status(int group, uint32_t value)
+{
+ tassert(group < BFIN_TIMER_NUM_GROUP);
+ group_regs[group]->status = value;
+ SSYNC();
+}
+EXPORT_SYMBOL(set_gptimer_status);
+
+uint16_t get_gptimer_intr(int timer_id)
+{
+ tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
+ return (group_regs[BFIN_TIMER_OCTET(timer_id)]->status & timil_mask[timer_id]) ? 1 : 0;
+}
+EXPORT_SYMBOL(get_gptimer_intr);
+
+void clear_gptimer_intr(int timer_id)
+{
+ tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
+ group_regs[BFIN_TIMER_OCTET(timer_id)]->status = timil_mask[timer_id];
+}
+EXPORT_SYMBOL(clear_gptimer_intr);
+
+uint16_t get_gptimer_over(int timer_id)
+{
+ tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
+ return (group_regs[BFIN_TIMER_OCTET(timer_id)]->status & tovf_mask[timer_id]) ? 1 : 0;
+}
+EXPORT_SYMBOL(get_gptimer_over);
+
+void clear_gptimer_over(int timer_id)
+{
+ tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
+ group_regs[BFIN_TIMER_OCTET(timer_id)]->status = tovf_mask[timer_id];
+}
+EXPORT_SYMBOL(clear_gptimer_over);
+
+void set_gptimer_config(int timer_id, uint16_t config)
+{
+ tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
+ timer_regs[timer_id]->config = config;
+ SSYNC();
+}
+EXPORT_SYMBOL(set_gptimer_config);
+
+uint16_t get_gptimer_config(int timer_id)
+{
+ tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
+ return timer_regs[timer_id]->config;
+}
+EXPORT_SYMBOL(get_gptimer_config);
+
+void enable_gptimers(uint16_t mask)
+{
+ int i;
+ tassert((mask & ~BLACKFIN_GPTIMER_IDMASK) == 0);
+ for (i = 0; i < BFIN_TIMER_NUM_GROUP; ++i) {
+ group_regs[i]->enable = mask & 0xFF;
+ mask >>= 8;
+ }
+ SSYNC();
+}
+EXPORT_SYMBOL(enable_gptimers);
+
+void disable_gptimers(uint16_t mask)
+{
+ int i;
+ uint16_t m = mask;
+ tassert((mask & ~BLACKFIN_GPTIMER_IDMASK) == 0);
+ for (i = 0; i < BFIN_TIMER_NUM_GROUP; ++i) {
+ group_regs[i]->disable = m & 0xFF;
+ m >>= 8;
+ }
+ for (i = 0; i < MAX_BLACKFIN_GPTIMERS; ++i)
+ if (mask & (1 << i))
+ group_regs[BFIN_TIMER_OCTET(i)]->status |= trun_mask[i];
+ SSYNC();
+}
+EXPORT_SYMBOL(disable_gptimers);
+
+void set_gptimer_pulse_hi(int timer_id)
+{
+ tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
+ timer_regs[timer_id]->config |= TIMER_PULSE_HI;
+ SSYNC();
+}
+EXPORT_SYMBOL(set_gptimer_pulse_hi);
+
+void clear_gptimer_pulse_hi(int timer_id)
+{
+ tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
+ timer_regs[timer_id]->config &= ~TIMER_PULSE_HI;
+ SSYNC();
+}
+EXPORT_SYMBOL(clear_gptimer_pulse_hi);
+
+uint16_t get_enabled_gptimers(void)
+{
+ int i;
+ uint16_t result = 0;
+ for (i = 0; i < BFIN_TIMER_NUM_GROUP; ++i)
+ result |= (group_regs[i]->enable << (i << 3));
+ return result;
+}
+EXPORT_SYMBOL(get_enabled_gptimers);
+
+MODULE_AUTHOR("Axel Weiss (awe@aglaia-gmbh.de)");
+MODULE_DESCRIPTION("Blackfin General Purpose Timers API");
+MODULE_LICENSE("GPL");
diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c
index 64ce5fea8609..85caf9b711a1 100644
--- a/arch/blackfin/kernel/ptrace.c
+++ b/arch/blackfin/kernel/ptrace.c
@@ -385,12 +385,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
}
- case PTRACE_DETACH:
- { /* detach a process that was attached. */
- ret = ptrace_detach(child, data);
- break;
- }
-
case PTRACE_GETREGS:
{
diff --git a/arch/blackfin/kernel/reboot.c b/arch/blackfin/kernel/reboot.c
index 356078ec462b..ae28aac6fec1 100644
--- a/arch/blackfin/kernel/reboot.c
+++ b/arch/blackfin/kernel/reboot.c
@@ -11,7 +11,7 @@
#include <asm/reboot.h>
#include <asm/system.h>
-#if defined(BF537_FAMILY) || defined(BF533_FAMILY)
+#if defined(BF537_FAMILY) || defined(BF533_FAMILY) || defined(BF527_FAMILY)
#define SYSCR_VAL 0x0
#elif defined(BF561_FAMILY)
#define SYSCR_VAL 0x20
diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c
index 8dcd76e87ed5..934234f43839 100644
--- a/arch/blackfin/kernel/setup.c
+++ b/arch/blackfin/kernel/setup.c
@@ -316,6 +316,15 @@ void __init setup_arch(char **cmdline_p)
init_leds();
+ _bfin_swrst = bfin_read_SWRST();
+
+ if (_bfin_swrst & RESET_DOUBLE)
+ printk(KERN_INFO "Recovering from Double Fault event\n");
+ else if (_bfin_swrst & RESET_WDOG)
+ printk(KERN_INFO "Recovering from Watchdog event\n");
+ else if (_bfin_swrst & RESET_SOFTWARE)
+ printk(KERN_NOTICE "Reset caused by Software reset\n");
+
printk(KERN_INFO "Blackfin support (C) 2004-2007 Analog Devices, Inc.\n");
if (bfin_compiled_revid() == 0xffff)
printk(KERN_INFO "Compiled for ADSP-%s Rev any\n", CPU);
@@ -402,8 +411,6 @@ void __init setup_arch(char **cmdline_p)
if (l1_length > L1_DATA_A_LENGTH)
panic("L1 data memory overflow\n");
- _bfin_swrst = bfin_read_SWRST();
-
/* Copy atomic sequences to their fixed location, and sanity check that
these locations are the ones that we advertise to userspace. */
memcpy((void *)FIXED_CODE_START, &fixed_code_start,
@@ -424,6 +431,8 @@ void __init setup_arch(char **cmdline_p)
!= ATOMIC_AND32 - FIXED_CODE_START);
BUG_ON((char *)&atomic_xor32 - (char *)&fixed_code_start
!= ATOMIC_XOR32 - FIXED_CODE_START);
+ BUG_ON((char *)&safe_user_instruction - (char *)&fixed_code_start
+ != SAFE_USER_INSTRUCTION - FIXED_CODE_START);
init_exception_vectors();
bf53x_cache_init();
@@ -459,7 +468,7 @@ static u_long get_vco(void)
return vco;
}
-/*Get the Core clock*/
+/* Get the Core clock */
u_long get_cclk(void)
{
u_long csel, ssel;
@@ -493,12 +502,24 @@ u_long get_sclk(void)
}
EXPORT_SYMBOL(get_sclk);
+unsigned long sclk_to_usecs(unsigned long sclk)
+{
+ return (USEC_PER_SEC * (u64)sclk) / get_sclk();
+}
+EXPORT_SYMBOL(sclk_to_usecs);
+
+unsigned long usecs_to_sclk(unsigned long usecs)
+{
+ return (get_sclk() * (u64)usecs) / USEC_PER_SEC;
+}
+EXPORT_SYMBOL(usecs_to_sclk);
+
/*
* Get CPU information for use by the procfs.
*/
static int show_cpuinfo(struct seq_file *m, void *v)
{
- char *cpu, *mmu, *fpu, *name;
+ char *cpu, *mmu, *fpu, *vendor, *cache;
uint32_t revid;
u_long cclk = 0, sclk = 0;
@@ -508,70 +529,83 @@ static int show_cpuinfo(struct seq_file *m, void *v)
mmu = "none";
fpu = "none";
revid = bfin_revid();
- name = bfin_board_name;
cclk = get_cclk();
sclk = get_sclk();
- seq_printf(m, "CPU:\t\tADSP-%s Rev. 0.%d\n"
- "MMU:\t\t%s\n"
- "FPU:\t\t%s\n"
- "Core Clock:\t%9lu Hz\n"
- "System Clock:\t%9lu Hz\n"
- "BogoMips:\t%lu.%02lu\n"
- "Calibration:\t%lu loops\n",
- cpu, revid, mmu, fpu,
- cclk,
- sclk,
- (loops_per_jiffy * HZ) / 500000,
- ((loops_per_jiffy * HZ) / 5000) % 100,
- (loops_per_jiffy * HZ));
- seq_printf(m, "Board Name:\t%s\n", name);
- seq_printf(m, "Board Memory:\t%ld MB\n", physical_mem_end >> 20);
- seq_printf(m, "Kernel Memory:\t%ld MB\n", (unsigned long)_ramend >> 20);
- if (bfin_read_IMEM_CONTROL() & (ENICPLB | IMC))
- seq_printf(m, "I-CACHE:\tON\n");
- else
- seq_printf(m, "I-CACHE:\tOFF\n");
- if ((bfin_read_DMEM_CONTROL()) & (ENDCPLB | DMC_ENABLE))
- seq_printf(m, "D-CACHE:\tON"
-#if defined CONFIG_BFIN_WB
- " (write-back)"
-#elif defined CONFIG_BFIN_WT
- " (write-through)"
-#endif
- "\n");
- else
- seq_printf(m, "D-CACHE:\tOFF\n");
-
+ switch (bfin_read_CHIPID() & CHIPID_MANUFACTURE) {
+ case 0xca:
+ vendor = "Analog Devices";
+ break;
+ default:
+ vendor = "unknown";
+ break;
+ }
+ seq_printf(m, "processor\t: %d\n"
+ "vendor_id\t: %s\n"
+ "cpu family\t: 0x%x\n"
+ "model name\t: ADSP-%s %lu(MHz CCLK) %lu(MHz SCLK)\n"
+ "stepping\t: %d\n",
+ 0,
+ vendor,
+ (bfin_read_CHIPID() & CHIPID_FAMILY),
+ cpu, cclk/1000000, sclk/1000000,
+ revid);
+
+ seq_printf(m, "cpu MHz\t\t: %lu.%03lu/%lu.%03lu\n",
+ cclk/1000000, cclk%1000000,
+ sclk/1000000, sclk%1000000);
+ seq_printf(m, "bogomips\t: %lu.%02lu\n"
+ "Calibration\t: %lu loops\n",
+ (loops_per_jiffy * HZ) / 500000,
+ ((loops_per_jiffy * HZ) / 5000) % 100,
+ (loops_per_jiffy * HZ));
+
+ /* Check Cache configutation */
switch (bfin_read_DMEM_CONTROL() & (1 << DMC0_P | 1 << DMC1_P)) {
case ACACHE_BSRAM:
- seq_printf(m, "DBANK-A:\tCACHE\n" "DBANK-B:\tSRAM\n");
+ cache = "dbank-A/B\t: cache/sram";
dcache_size = 16;
dsup_banks = 1;
break;
case ACACHE_BCACHE:
- seq_printf(m, "DBANK-A:\tCACHE\n" "DBANK-B:\tCACHE\n");
+ cache = "dbank-A/B\t: cache/cache";
dcache_size = 32;
dsup_banks = 2;
break;
case ASRAM_BSRAM:
- seq_printf(m, "DBANK-A:\tSRAM\n" "DBANK-B:\tSRAM\n");
+ cache = "dbank-A/B\t: sram/sram";
dcache_size = 0;
dsup_banks = 0;
break;
default:
+ cache = "unknown";
+ dcache_size = 0;
+ dsup_banks = 0;
break;
}
+ /* Is it turned on? */
+ if (!((bfin_read_DMEM_CONTROL()) & (ENDCPLB | DMC_ENABLE)))
+ dcache_size = 0;
- seq_printf(m, "I-CACHE Size:\t%dKB\n", BFIN_ICACHESIZE / 1024);
- seq_printf(m, "D-CACHE Size:\t%dKB\n", dcache_size);
- seq_printf(m, "I-CACHE Setup:\t%d Sub-banks/%d Ways, %d Lines/Way\n",
+ seq_printf(m, "cache size\t: %d KB(L1 icache) "
+ "%d KB(L1 dcache-%s) %d KB(L2 cache)\n",
+ BFIN_ICACHESIZE / 1024, dcache_size,
+#if defined CONFIG_BFIN_WB
+ "wb"
+#elif defined CONFIG_BFIN_WT
+ "wt"
+#endif
+ "", 0);
+
+ seq_printf(m, "%s\n", cache);
+
+ seq_printf(m, "icache setup\t: %d Sub-banks/%d Ways, %d Lines/Way\n",
BFIN_ISUBBANKS, BFIN_IWAYS, BFIN_ILINES);
seq_printf(m,
- "D-CACHE Setup:\t%d Super-banks/%d Sub-banks/%d Ways, %d Lines/Way\n",
+ "dcache setup\t: %d Super-banks/%d Sub-banks/%d Ways, %d Lines/Way\n",
dsup_banks, BFIN_DSUBBANKS, BFIN_DWAYS,
BFIN_DLINES);
#ifdef CONFIG_BFIN_ICACHE_LOCK
@@ -625,6 +659,15 @@ static int show_cpuinfo(struct seq_file *m, void *v)
seq_printf(m, "No Ways are locked\n");
}
#endif
+
+ seq_printf(m, "board name\t: %s\n", bfin_board_name);
+ seq_printf(m, "board memory\t: %ld kB (0x%p -> 0x%p)\n",
+ physical_mem_end >> 10, (void *)0, (void *)physical_mem_end);
+ seq_printf(m, "kernel memory\t: %d kB (0x%p -> 0x%p)\n",
+ ((int)memory_end - (int)_stext) >> 10,
+ _stext,
+ (void *)memory_end);
+
return 0;
}
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c
index 8823e9ade584..cfa05436c972 100644
--- a/arch/blackfin/kernel/traps.c
+++ b/arch/blackfin/kernel/traps.c
@@ -37,10 +37,24 @@
#include <asm/blackfin.h>
#include <asm/irq_handler.h>
#include <asm/trace.h>
+#include <asm/fixed_code.h>
#ifdef CONFIG_KGDB
# include <linux/debugger.h>
# include <linux/kgdb.h>
+
+# define CHK_DEBUGGER_TRAP() \
+ do { \
+ CHK_DEBUGGER(trapnr, sig, info.si_code, fp, ); \
+ } while (0)
+# define CHK_DEBUGGER_TRAP_MAYBE() \
+ do { \
+ if (kgdb_connected) \
+ CHK_DEBUGGER_TRAP(); \
+ } while (0)
+#else
+# define CHK_DEBUGGER_TRAP() do { } while (0)
+# define CHK_DEBUGGER_TRAP_MAYBE() do { } while (0)
#endif
/* Initiate the event table handler */
@@ -53,13 +67,13 @@ void __init trap_init(void)
int kstack_depth_to_print = 48;
-#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
-static int printk_address(unsigned long address)
+static void decode_address(char *buf, unsigned long address)
{
struct vm_list_struct *vml;
struct task_struct *p;
struct mm_struct *mm;
- unsigned long offset;
+ unsigned long flags, offset;
+ unsigned int in_exception = bfin_read_IPEND() & 0x10;
#ifdef CONFIG_KALLSYMS
unsigned long symsize;
@@ -75,20 +89,33 @@ static int printk_address(unsigned long address)
/* yeah! kernel space! */
if (!modname)
modname = delim = "";
- return printk("<0x%p> { %s%s%s%s + 0x%lx }",
+ sprintf(buf, "<0x%p> { %s%s%s%s + 0x%lx }",
(void *)address, delim, modname, delim, symname,
(unsigned long)offset);
+ return;
}
#endif
+ /* Problem in fixed code section? */
+ if (address >= FIXED_CODE_START && address < FIXED_CODE_END) {
+ sprintf(buf, "<0x%p> /* Maybe fixed code section */", (void *)address);
+ return;
+ }
+
+ /* Problem somewhere before the kernel start address */
+ if (address < CONFIG_BOOT_LOAD) {
+ sprintf(buf, "<0x%p> /* Maybe null pointer? */", (void *)address);
+ return;
+ }
+
/* looks like we're off in user-land, so let's walk all the
* mappings of all our processes and see if we can't be a whee
* bit more specific
*/
- write_lock_irq(&tasklist_lock);
+ write_lock_irqsave(&tasklist_lock, flags);
for_each_process(p) {
- mm = get_task_mm(p);
+ mm = (in_exception ? p->mm : get_task_mm(p));
if (!mm)
continue;
@@ -117,23 +144,30 @@ static int printk_address(unsigned long address)
else
offset = (address - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT);
- write_unlock_irq(&tasklist_lock);
- return printk("<0x%p> [ %s + 0x%lx ]",
- (void *)address, name, offset);
+ sprintf(buf, "<0x%p> [ %s + 0x%lx ]",
+ (void *)address, name, offset);
+ if (!in_exception)
+ mmput(mm);
+ goto done;
}
vml = vml->next;
}
+ if (!in_exception)
+ mmput(mm);
}
- write_unlock_irq(&tasklist_lock);
/* we were unable to find this address anywhere */
- return printk("[<0x%p>]", (void *)address);
+ sprintf(buf, "[<0x%p>]", (void *)address);
+
+done:
+ write_unlock_irqrestore(&tasklist_lock, flags);
}
-#endif
asmlinkage void double_fault_c(struct pt_regs *fp)
{
+ console_verbose();
+ oops_in_progress = 1;
printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n");
dump_bfin_regs(fp, (void *)fp->retx);
panic("Double Fault - unrecoverable event\n");
@@ -149,22 +183,29 @@ asmlinkage void trap_c(struct pt_regs *fp)
siginfo_t info;
unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE;
+ trace_buffer_save(j);
+
+ /* Important - be very careful dereferncing pointers - will lead to
+ * double faults if the stack has become corrupt
+ */
+
+ /* If the fault was caused by a kernel thread, or interrupt handler
+ * we will kernel panic, so the system reboots.
+ * If KGDB is enabled, don't set this for kernel breakpoints
+ */
+ if ((bfin_read_IPEND() & 0xFFC0)
#ifdef CONFIG_KGDB
-# define CHK_DEBUGGER_TRAP() \
- do { \
- CHK_DEBUGGER(trapnr, sig, info.si_code, fp, ); \
- } while (0)
-# define CHK_DEBUGGER_TRAP_MAYBE() \
- do { \
- if (kgdb_connected) \
- CHK_DEBUGGER_TRAP(); \
- } while (0)
-#else
-# define CHK_DEBUGGER_TRAP() do { } while (0)
-# define CHK_DEBUGGER_TRAP_MAYBE() do { } while (0)
+ && trapnr != VEC_EXCPT02
#endif
-
- trace_buffer_save(j);
+ ){
+ console_verbose();
+ oops_in_progress = 1;
+ } else if (current) {
+ if (current->mm == NULL) {
+ console_verbose();
+ oops_in_progress = 1;
+ }
+ }
/* trap_c() will be called for exceptions. During exceptions
* processing, the pc value should be set with retx value.
@@ -209,7 +250,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
case VEC_EXCPT03:
info.si_code = SEGV_STACKFLOW;
sig = SIGSEGV;
- printk(KERN_EMERG EXC_0x03);
+ printk(KERN_NOTICE EXC_0x03);
CHK_DEBUGGER_TRAP();
break;
/* 0x04 - User Defined, Caught by default */
@@ -238,7 +279,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
case VEC_OVFLOW:
info.si_code = TRAP_TRACEFLOW;
sig = SIGTRAP;
- printk(KERN_EMERG EXC_0x11);
+ printk(KERN_NOTICE EXC_0x11);
CHK_DEBUGGER_TRAP();
break;
/* 0x12 - Reserved, Caught by default */
@@ -260,14 +301,14 @@ asmlinkage void trap_c(struct pt_regs *fp)
case VEC_UNDEF_I:
info.si_code = ILL_ILLOPC;
sig = SIGILL;
- printk(KERN_EMERG EXC_0x21);
+ printk(KERN_NOTICE EXC_0x21);
CHK_DEBUGGER_TRAP();
break;
/* 0x22 - Illegal Instruction Combination, handled here */
case VEC_ILGAL_I:
info.si_code = ILL_ILLPARAOP;
sig = SIGILL;
- printk(KERN_EMERG EXC_0x22);
+ printk(KERN_NOTICE EXC_0x22);
CHK_DEBUGGER_TRAP();
break;
/* 0x23 - Data CPLB Protection Violation,
@@ -275,21 +316,21 @@ asmlinkage void trap_c(struct pt_regs *fp)
case VEC_CPLB_VL:
info.si_code = ILL_CPLB_VI;
sig = SIGILL;
- printk(KERN_EMERG EXC_0x23);
+ printk(KERN_NOTICE EXC_0x23);
CHK_DEBUGGER_TRAP();
break;
/* 0x24 - Data access misaligned, handled here */
case VEC_MISALI_D:
info.si_code = BUS_ADRALN;
sig = SIGBUS;
- printk(KERN_EMERG EXC_0x24);
+ printk(KERN_NOTICE EXC_0x24);
CHK_DEBUGGER_TRAP();
break;
/* 0x25 - Unrecoverable Event, handled here */
case VEC_UNCOV:
info.si_code = ILL_ILLEXCPT;
sig = SIGILL;
- printk(KERN_EMERG EXC_0x25);
+ printk(KERN_NOTICE EXC_0x25);
CHK_DEBUGGER_TRAP();
break;
/* 0x26 - Data CPLB Miss, normal case is handled in _cplb_hdr,
@@ -297,7 +338,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
case VEC_CPLB_M:
info.si_code = BUS_ADRALN;
sig = SIGBUS;
- printk(KERN_EMERG EXC_0x26);
+ printk(KERN_NOTICE EXC_0x26);
CHK_DEBUGGER_TRAP();
break;
/* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */
@@ -305,11 +346,10 @@ asmlinkage void trap_c(struct pt_regs *fp)
info.si_code = ILL_CPLB_MULHIT;
#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
sig = SIGSEGV;
- printk(KERN_EMERG "\n"
- KERN_EMERG "NULL pointer access (probably)\n");
+ printk(KERN_NOTICE "NULL pointer access (probably)\n");
#else
sig = SIGILL;
- printk(KERN_EMERG EXC_0x27);
+ printk(KERN_NOTICE EXC_0x27);
#endif
CHK_DEBUGGER_TRAP();
break;
@@ -329,7 +369,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
case VEC_ISTRU_VL: /* ADSP-BF535 only (MH) */
info.si_code = BUS_OPFETCH;
sig = SIGBUS;
- printk(KERN_EMERG "BF535: VEC_ISTRU_VL\n");
+ printk(KERN_NOTICE "BF535: VEC_ISTRU_VL\n");
CHK_DEBUGGER_TRAP();
break;
#else
@@ -339,7 +379,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
case VEC_MISALI_I:
info.si_code = BUS_ADRALN;
sig = SIGBUS;
- printk(KERN_EMERG EXC_0x2A);
+ printk(KERN_NOTICE EXC_0x2A);
CHK_DEBUGGER_TRAP();
break;
/* 0x2B - Instruction CPLB protection Violation,
@@ -347,14 +387,14 @@ asmlinkage void trap_c(struct pt_regs *fp)
case VEC_CPLB_I_VL:
info.si_code = ILL_CPLB_VI;
sig = SIGILL;
- printk(KERN_EMERG EXC_0x2B);
+ printk(KERN_NOTICE EXC_0x2B);
CHK_DEBUGGER_TRAP();
break;
/* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */
case VEC_CPLB_I_M:
info.si_code = ILL_CPLB_MISS;
sig = SIGBUS;
- printk(KERN_EMERG EXC_0x2C);
+ printk(KERN_NOTICE EXC_0x2C);
CHK_DEBUGGER_TRAP();
break;
/* 0x2D - Instruction CPLB Multiple Hits, handled here */
@@ -362,10 +402,10 @@ asmlinkage void trap_c(struct pt_regs *fp)
info.si_code = ILL_CPLB_MULHIT;
#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
sig = SIGSEGV;
- printk(KERN_EMERG "\n\nJump to address 0 - 0x0fff\n");
+ printk(KERN_NOTICE "Jump to address 0 - 0x0fff\n");
#else
sig = SIGILL;
- printk(KERN_EMERG EXC_0x2D);
+ printk(KERN_NOTICE EXC_0x2D);
#endif
CHK_DEBUGGER_TRAP();
break;
@@ -373,7 +413,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
case VEC_ILL_RES:
info.si_code = ILL_PRVOPC;
sig = SIGILL;
- printk(KERN_EMERG EXC_0x2E);
+ printk(KERN_NOTICE EXC_0x2E);
CHK_DEBUGGER_TRAP();
break;
/* 0x2F - Reserved, Caught by default */
@@ -402,38 +442,40 @@ asmlinkage void trap_c(struct pt_regs *fp)
break;
}
- if (sig != 0 && sig != SIGTRAP) {
+ BUG_ON(sig == 0);
+
+ if (sig != SIGTRAP) {
unsigned long stack;
dump_bfin_regs(fp, (void *)fp->retx);
- dump_bfin_trace_buffer();
+
+ /* Print out the trace buffer if it makes sense */
+#ifndef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE
+ if (trapnr == VEC_CPLB_I_M || trapnr == VEC_CPLB_M)
+ printk(KERN_NOTICE "No trace since you do not have "
+ "CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE enabled\n"
+ KERN_NOTICE "\n");
+ else
+#endif
+ dump_bfin_trace_buffer();
show_stack(current, &stack);
- if (current->mm == NULL)
+ if (oops_in_progress) {
+#ifndef CONFIG_ACCESS_CHECK
+ printk(KERN_EMERG "Hey - dork - please turn on "
+ "CONFIG_ACCESS_CHECK\n");
+#endif
panic("Kernel exception");
+ }
+
+ /* Ensure that bad return addresses don't end up in an infinite
+ * loop, due to speculative loads/reads
+ */
+ fp->pc = SAFE_USER_INSTRUCTION;
}
info.si_signo = sig;
info.si_errno = 0;
info.si_addr = (void *)fp->pc;
force_sig_info(sig, &info, current);
- /* if the address that we are about to return to is not valid, set it
- * to a valid address, if we have a current application or panic
- */
- if (!(fp->pc <= physical_mem_end
-#if L1_CODE_LENGTH != 0
- || (fp->pc >= L1_CODE_START &&
- fp->pc <= (L1_CODE_START + L1_CODE_LENGTH))
-#endif
- )) {
- if (current->mm) {
- fp->pc = current->mm->start_code;
- } else {
- printk(KERN_EMERG
- "I can't return to memory that doesn't exist"
- " - bad things happen\n");
- panic("Help - I've fallen and can't get up\n");
- }
- }
-
trace_buffer_restore(j);
return;
}
@@ -446,21 +488,21 @@ void dump_bfin_trace_buffer(void)
{
#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
int tflags, i = 0;
+ char buf[150];
#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND
int j, index;
#endif
trace_buffer_save(tflags);
- printk(KERN_EMERG "Hardware Trace:\n");
+ printk(KERN_NOTICE "Hardware Trace:\n");
if (likely(bfin_read_TBUFSTAT() & TBUFCNT)) {
for (; bfin_read_TBUFSTAT() & TBUFCNT; i++) {
- printk(KERN_EMERG "%4i Target : ", i);
- printk_address((unsigned long)bfin_read_TBUF());
- printk("\n" KERN_EMERG " Source : ");
- printk_address((unsigned long)bfin_read_TBUF());
- printk("\n");
+ decode_address(buf, (unsigned long)bfin_read_TBUF());
+ printk(KERN_NOTICE "%4i Target : %s\n", i, buf);
+ decode_address(buf, (unsigned long)bfin_read_TBUF());
+ printk(KERN_NOTICE " Source : %s\n", buf);
}
}
@@ -472,17 +514,16 @@ void dump_bfin_trace_buffer(void)
j = (1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN) * 128;
while (j) {
- printk(KERN_EMERG "%4i Target : ", i);
- printk_address(software_trace_buff[index]);
+ decode_address(buf, software_trace_buff[index]);
+ printk(KERN_NOTICE "%4i Target : %s\n", i, buf);
index -= 1;
if (index < 0 )
index = EXPAND_LEN;
- printk("\n" KERN_EMERG " Source : ");
- printk_address(software_trace_buff[index]);
+ decode_address(buf, software_trace_buff[index]);
+ printk(KERN_NOTICE " Source : %s\n", buf);
index -= 1;
if (index < 0)
index = EXPAND_LEN;
- printk("\n");
j--;
i++;
}
@@ -497,10 +538,7 @@ static void show_trace(struct task_struct *tsk, unsigned long *sp)
{
unsigned long addr;
- printk("\nCall Trace:");
-#ifdef CONFIG_KALLSYMS
- printk("\n");
-#endif
+ printk(KERN_NOTICE "\n" KERN_NOTICE "Call Trace:\n");
while (!kstack_end(sp)) {
addr = *sp++;
@@ -516,7 +554,7 @@ static void show_trace(struct task_struct *tsk, unsigned long *sp)
print_ip_sym(addr);
}
- printk("\n");
+ printk(KERN_NOTICE "\n");
}
void show_stack(struct task_struct *task, unsigned long *stack)
@@ -538,14 +576,15 @@ void show_stack(struct task_struct *task, unsigned long *stack)
addr = (unsigned long)stack;
endstack = (unsigned long *)PAGE_ALIGN(addr);
- printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack);
+ printk(KERN_NOTICE "Stack from %08lx:", (unsigned long)stack);
for (i = 0; i < kstack_depth_to_print; i++) {
if (stack + 1 > endstack)
break;
if (i % 8 == 0)
- printk("\n" KERN_EMERG " ");
+ printk("\n" KERN_NOTICE " ");
printk(" %08lx", *stack++);
}
+ printk("\n");
show_trace(task, stack);
}
@@ -566,33 +605,34 @@ EXPORT_SYMBOL(dump_stack);
void dump_bfin_regs(struct pt_regs *fp, void *retaddr)
{
- if (current->pid) {
- printk(KERN_EMERG "\n" KERN_EMERG "CURRENT PROCESS:\n"
- KERN_EMERG "\n");
- printk(KERN_EMERG "COMM=%s PID=%d\n",
- current->comm, current->pid);
+ char buf [150];
+
+ if (!oops_in_progress) {
+ if (current->pid && current->mm) {
+ printk(KERN_NOTICE "\n" KERN_NOTICE "CURRENT PROCESS:\n");
+ printk(KERN_NOTICE "COMM=%s PID=%d\n",
+ current->comm, current->pid);
+
+ printk(KERN_NOTICE "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n"
+ KERN_NOTICE "BSS = 0x%p-0x%p USER-STACK = 0x%p\n"
+ KERN_NOTICE "\n",
+ (void *)current->mm->start_code,
+ (void *)current->mm->end_code,
+ (void *)current->mm->start_data,
+ (void *)current->mm->end_data,
+ (void *)current->mm->end_data,
+ (void *)current->mm->brk,
+ (void *)current->mm->start_stack);
+ } else {
+ printk (KERN_NOTICE "\n" KERN_NOTICE
+ "No Valid pid - Either things are really messed up,"
+ " or you are in the kernel\n");
+ }
} else {
- printk
- (KERN_EMERG "\n" KERN_EMERG
- "No Valid pid - Either things are really messed up,"
- " or you are in the kernel\n");
- }
-
- if (current->mm) {
- printk(KERN_EMERG "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n"
- KERN_EMERG "BSS = 0x%p-0x%p USER-STACK = 0x%p\n"
- KERN_EMERG "\n",
- (void *)current->mm->start_code,
- (void *)current->mm->end_code,
- (void *)current->mm->start_data,
- (void *)current->mm->end_data,
- (void *)current->mm->end_data,
- (void *)current->mm->brk,
- (void *)current->mm->start_stack);
+ printk(KERN_NOTICE "Kernel or interrupt exception\n");
}
- printk(KERN_EMERG "return address: [0x%p]; contents of:", retaddr);
- if (retaddr != 0 && retaddr <= (void *)physical_mem_end
+ if (retaddr >= (void *)FIXED_CODE_START && retaddr < (void *)physical_mem_end
#if L1_CODE_LENGTH != 0
/* FIXME: Copy the code out of L1 Instruction SRAM through dma
memcpy. */
@@ -602,18 +642,20 @@ void dump_bfin_regs(struct pt_regs *fp, void *retaddr)
) {
int i = ((unsigned int)retaddr & 0xFFFFFFF0) - 32;
unsigned short x = 0;
+ printk(KERN_NOTICE "return address: [0x%p]; contents of:", retaddr);
for (; i < ((unsigned int)retaddr & 0xFFFFFFF0) + 32; i += 2) {
if (!(i & 0xF))
- printk("\n" KERN_EMERG "0x%08x: ", i);
+ printk("\n" KERN_NOTICE "0x%08x: ", i);
if (get_user(x, (unsigned short *)i))
break;
#ifndef CONFIG_DEBUG_HWERR
/* If one of the last few instructions was a STI
* it is likely that the error occured awhile ago
- * and we just noticed
+ * and we just noticed. This only happens in kernel
+ * context, which should mean an oops is happening
*/
- if (x >= 0x0040 && x <= 0x0047 && i <= 0)
+ if (oops_in_progress && x >= 0x0040 && x <= 0x0047 && i <= 0)
panic("\n\nWARNING : You should reconfigure"
" the kernel to turn on\n"
" 'Hardware error interrupt"
@@ -626,56 +668,60 @@ void dump_bfin_regs(struct pt_regs *fp, void *retaddr)
else
printk(" %04x ", x);
}
- printk("\n" KERN_EMERG "\n");
+ printk("\n");
} else
- printk(KERN_EMERG
+ printk("\n" KERN_NOTICE
"Cannot look at the [PC] for it is"
- "in unreadable L1 SRAM - sorry\n");
+ " in unreadable memory - sorry\n");
+
+ printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\n");
+ printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n",
+ (long)fp->seqstat, fp->ipend, fp->syscfg);
+ decode_address(buf, fp->rete);
+ printk(KERN_NOTICE " RETE: %s\n", buf);
+ decode_address(buf, fp->retn);
+ printk(KERN_NOTICE " RETN: %s\n", buf);
+ decode_address(buf, fp->retx);
+ printk(KERN_NOTICE " RETX: %s\n", buf);
+ decode_address(buf, fp->rets);
+ printk(KERN_NOTICE " RETS: %s\n", buf);
- printk(KERN_EMERG
- "RETE: %08lx RETN: %08lx RETX: %08lx RETS: %08lx\n",
- fp->rete, fp->retn, fp->retx, fp->rets);
- printk(KERN_EMERG "IPEND: %04lx SYSCFG: %04lx\n",
- fp->ipend, fp->syscfg);
- printk(KERN_EMERG "SEQSTAT: %08lx SP: %08lx\n",
- (long)fp->seqstat, (long)fp);
- printk(KERN_EMERG "R0: %08lx R1: %08lx R2: %08lx R3: %08lx\n",
+ if ((long)fp->seqstat & SEQSTAT_EXCAUSE) {
+ decode_address(buf, bfin_read_DCPLB_FAULT_ADDR());
+ printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf);
+ decode_address(buf, bfin_read_ICPLB_FAULT_ADDR());
+ printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf);
+ }
+
+ printk(KERN_NOTICE "\n" KERN_NOTICE "PROCESSOR STATE:\n");
+ printk(KERN_NOTICE " R0 : %08lx R1 : %08lx R2 : %08lx R3 : %08lx\n",
fp->r0, fp->r1, fp->r2, fp->r3);
- printk(KERN_EMERG "R4: %08lx R5: %08lx R6: %08lx R7: %08lx\n",
+ printk(KERN_NOTICE " R4 : %08lx R5 : %08lx R6 : %08lx R7 : %08lx\n",
fp->r4, fp->r5, fp->r6, fp->r7);
- printk(KERN_EMERG "P0: %08lx P1: %08lx P2: %08lx P3: %08lx\n",
+ printk(KERN_NOTICE " P0 : %08lx P1 : %08lx P2 : %08lx P3 : %08lx\n",
fp->p0, fp->p1, fp->p2, fp->p3);
- printk(KERN_EMERG
- "P4: %08lx P5: %08lx FP: %08lx\n",
- fp->p4, fp->p5, fp->fp);
- printk(KERN_EMERG
- "A0.w: %08lx A0.x: %08lx A1.w: %08lx A1.x: %08lx\n",
- fp->a0w, fp->a0x, fp->a1w, fp->a1x);
-
- printk(KERN_EMERG "LB0: %08lx LT0: %08lx LC0: %08lx\n",
+ printk(KERN_NOTICE " P4 : %08lx P5 : %08lx FP : %08lx SP : %08lx\n",
+ fp->p4, fp->p5, fp->fp, (long)fp);
+ printk(KERN_NOTICE " LB0: %08lx LT0: %08lx LC0: %08lx\n",
fp->lb0, fp->lt0, fp->lc0);
- printk(KERN_EMERG "LB1: %08lx LT1: %08lx LC1: %08lx\n",
+ printk(KERN_NOTICE " LB1: %08lx LT1: %08lx LC1: %08lx\n",
fp->lb1, fp->lt1, fp->lc1);
- printk(KERN_EMERG "B0: %08lx L0: %08lx M0: %08lx I0: %08lx\n",
+ printk(KERN_NOTICE " B0 : %08lx L0 : %08lx M0 : %08lx I0 : %08lx\n",
fp->b0, fp->l0, fp->m0, fp->i0);
- printk(KERN_EMERG "B1: %08lx L1: %08lx M1: %08lx I1: %08lx\n",
+ printk(KERN_NOTICE " B1 : %08lx L1 : %08lx M1 : %08lx I1 : %08lx\n",
fp->b1, fp->l1, fp->m1, fp->i1);
- printk(KERN_EMERG "B2: %08lx L2: %08lx M2: %08lx I2: %08lx\n",
+ printk(KERN_NOTICE " B2 : %08lx L2 : %08lx M2 : %08lx I2 : %08lx\n",
fp->b2, fp->l2, fp->m2, fp->i2);
- printk(KERN_EMERG "B3: %08lx L3: %08lx M3: %08lx I3: %08lx\n",
+ printk(KERN_NOTICE " B3 : %08lx L3 : %08lx M3 : %08lx I3 : %08lx\n",
fp->b3, fp->l3, fp->m3, fp->i3);
+ printk(KERN_NOTICE "A0.w: %08lx A0.x: %08lx A1.w: %08lx A1.x: %08lx\n",
+ fp->a0w, fp->a0x, fp->a1w, fp->a1x);
- printk(KERN_EMERG "\n" KERN_EMERG "USP: %08lx ASTAT: %08lx\n",
+ printk(KERN_NOTICE "USP : %08lx ASTAT: %08lx\n",
rdusp(), fp->astat);
- if ((long)fp->seqstat & SEQSTAT_EXCAUSE) {
- printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n",
- (void *)bfin_read_DCPLB_FAULT_ADDR());
- printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n",
- (void *)bfin_read_ICPLB_FAULT_ADDR());
- }
- printk("\n\n");
+ printk(KERN_NOTICE "\n");
}
#ifdef CONFIG_SYS_BFIN_SPINLOCK_L1
@@ -750,6 +796,8 @@ void panic_cplb_error(int cplb_panic, struct pt_regs *fp)
break;
}
+ oops_in_progress = 1;
+
printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", (void *)bfin_read_DCPLB_FAULT_ADDR());
printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", (void *)bfin_read_ICPLB_FAULT_ADDR());
dump_bfin_regs(fp, (void *)fp->retx);
diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S
index eec43674a465..9b75bc83c71f 100644
--- a/arch/blackfin/kernel/vmlinux.lds.S
+++ b/arch/blackfin/kernel/vmlinux.lds.S
@@ -172,9 +172,14 @@ SECTIONS
__ebss_b_l1 = .;
}
- ___init_end = LOADADDR(.data_b_l1) + SIZEOF(.data_b_l1);
-
- .bss LOADADDR(.data_b_l1) + SIZEOF(.data_b_l1) :
+ /* Force trailing alignment of our init section so that when we
+ * free our init memory, we don't leave behind a partial page.
+ */
+ . = LOADADDR(.data_b_l1) + SIZEOF(.data_b_l1);
+ . = ALIGN(PAGE_SIZE);
+ ___init_end = .;
+
+ .bss :
{
. = ALIGN(4);
___bss_start = .;
diff --git a/arch/blackfin/lib/Makefile b/arch/blackfin/lib/Makefile
index 635288fc5f54..bfdad52c570b 100644
--- a/arch/blackfin/lib/Makefile
+++ b/arch/blackfin/lib/Makefile
@@ -4,7 +4,7 @@
lib-y := \
ashldi3.o ashrdi3.o lshrdi3.o \
- muldi3.o divsi3.o udivsi3.o modsi3.o umodsi3.o \
+ muldi3.o divsi3.o udivsi3.o udivdi3.o modsi3.o umodsi3.o \
checksum.o memcpy.o memset.o memcmp.o memchr.o memmove.o \
strcmp.o strcpy.o strncmp.o strncpy.o \
umulsi3_highpart.o smulsi3_highpart.o \
diff --git a/arch/blackfin/lib/udivdi3.S b/arch/blackfin/lib/udivdi3.S
new file mode 100644
index 000000000000..ad1ebee675e1
--- /dev/null
+++ b/arch/blackfin/lib/udivdi3.S
@@ -0,0 +1,375 @@
+/*
+ * udivdi3.S - unsigned long long division
+ *
+ * Copyright 2003-2007 Analog Devices Inc.
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPLv2 or later.
+ */
+
+#include <linux/linkage.h>
+
+#define CARRY AC0
+
+#ifdef CONFIG_ARITHMETIC_OPS_L1
+.section .l1.text
+#else
+.text
+#endif
+
+
+ENTRY(___udivdi3)
+ R3 = [SP + 12];
+ [--SP] = (R7:4, P5:3);
+
+ /* Attempt to use divide primitive first; these will handle
+ ** most cases, and they're quick - avoids stalls incurred by
+ ** testing for identities.
+ */
+
+ R4 = R2 | R3;
+ CC = R4 == 0;
+ IF CC JUMP .LDIV_BY_ZERO;
+
+ R4.H = 0x8000;
+ R4 >>>= 16; // R4 now 0xFFFF8000
+ R5 = R0 | R2; // If either dividend or
+ R4 = R5 & R4; // divisor have bits in
+ CC = R4; // top half or low half's sign
+ IF CC JUMP .LIDENTS; // bit, skip builtins.
+ R4 = R1 | R3; // Also check top halves
+ CC = R4;
+ IF CC JUMP .LIDENTS;
+
+ /* Can use the builtins. */
+
+ AQ = CC; // Clear AQ (CC==0)
+ DIVQ(R0, R2);
+ DIVQ(R0, R2);
+ DIVQ(R0, R2);
+ DIVQ(R0, R2);
+ DIVQ(R0, R2);
+ DIVQ(R0, R2);
+ DIVQ(R0, R2);
+ DIVQ(R0, R2);
+ DIVQ(R0, R2);
+ DIVQ(R0, R2);
+ DIVQ(R0, R2);
+ DIVQ(R0, R2);
+ DIVQ(R0, R2);
+ DIVQ(R0, R2);
+ DIVQ(R0, R2);
+ DIVQ(R0, R2);
+ DIVQ(R0, R2);
+ R0 = R0.L (Z);
+ R1 = 0;
+ (R7:4, P5:3) = [SP++];
+ RTS;
+
+.LIDENTS:
+ /* Test for common identities. Value to be returned is
+ ** placed in R6,R7.
+ */
+ // Check for 0/y, return 0
+ R4 = R0 | R1;
+ CC = R4 == 0;
+ IF CC JUMP .LRETURN_R0;
+
+ // Check for x/x, return 1
+ R6 = R0 - R2; // If x == y, then both R6 and R7 will be zero
+ R7 = R1 - R3;
+ R4 = R6 | R7; // making R4 zero.
+ R6 += 1; // which would now make R6:R7==1.
+ CC = R4 == 0;
+ IF CC JUMP .LRETURN_IDENT;
+
+ // Check for x/1, return x
+ R6 = R0;
+ R7 = R1;
+ CC = R3 == 0;
+ IF !CC JUMP .Lnexttest;
+ CC = R2 == 1;
+ IF CC JUMP .LRETURN_IDENT;
+
+.Lnexttest:
+ R4.L = ONES R2; // check for div by power of two which
+ R5.L = ONES R3; // can be done using a shift
+ R6 = PACK (R5.L, R4.L);
+ CC = R6 == 1;
+ IF CC JUMP .Lpower_of_two_upper_zero;
+ R6 = PACK (R4.L, R5.L);
+ CC = R6 == 1;
+ IF CC JUMP .Lpower_of_two_lower_zero;
+
+ // Check for x < y, return 0
+ R6 = 0;
+ R7 = R6;
+ CC = R1 < R3 (IU);
+ IF CC JUMP .LRETURN_IDENT;
+ CC = R1 == R3;
+ IF !CC JUMP .Lno_idents;
+ CC = R0 < R2 (IU);
+ IF CC JUMP .LRETURN_IDENT;
+
+.Lno_idents: // Idents don't match. Go for the full operation
+
+
+ // If X, or X and Y have high bit set, it'll affect the
+ // results, so shift right one to stop this. Note: we've already
+ // checked that X >= Y, so Y's msb won't be set unless X's
+ // is.
+
+ R4 = 0;
+ CC = R1 < 0;
+ IF !CC JUMP .Lx_msb_clear;
+ CC = !CC; // 1 -> 0;
+ R1 = ROT R1 BY -1; // Shift X >> 1
+ R0 = ROT R0 BY -1; // lsb -> CC
+ BITSET(R4,31); // to record only x msb was set
+ CC = R3 < 0;
+ IF !CC JUMP .Ly_msb_clear;
+ CC = !CC;
+ R3 = ROT R3 BY -1; // Shift Y >> 1
+ R2 = ROT R2 BY -1;
+ BITCLR(R4,31); // clear bit to record only x msb was set
+
+.Ly_msb_clear:
+.Lx_msb_clear:
+ // Bit 31 in R4 indicates X msb set, but Y msb wasn't, and no bits
+ // were lost, so we should shift result left by one.
+
+ [--SP] = R4; // save for later
+
+ // In the loop that follows, each iteration we add
+ // either Y' or -Y' to the Remainder. We compute the
+ // negated Y', and store, for convenience. Y' goes
+ // into P0:P1, while -Y' goes into P2:P3.
+
+ P0 = R2;
+ P1 = R3;
+ R2 = -R2;
+ CC = CARRY;
+ CC = !CC;
+ R4 = CC;
+ R3 = -R3;
+ R3 = R3 - R4;
+
+ R6 = 0; // remainder = 0
+ R7 = R6;
+
+ [--SP] = R2; P2 = SP;
+ [--SP] = R3; P3 = SP;
+ [--SP] = R6; P5 = SP; // AQ = 0
+ [--SP] = P1;
+
+ /* In the loop that follows, we use the following
+ ** register assignments:
+ ** R0,R1 X, workspace
+ ** R2,R3 Y, workspace
+ ** R4,R5 partial Div
+ ** R6,R7 partial remainder
+ ** P5 AQ
+ ** The remainder and div form a 128-bit number, with
+ ** the remainder in the high 64-bits.
+ */
+ R4 = R0; // Div = X'
+ R5 = R1;
+ R3 = 0;
+
+ P4 = 64; // Iterate once per bit
+ LSETUP(.LULST,.LULEND) LC0 = P4;
+.LULST:
+ /* Shift Div and remainder up by one. The bit shifted
+ ** out of the top of the quotient is shifted into the bottom
+ ** of the remainder.
+ */
+ CC = R3;
+ R4 = ROT R4 BY 1;
+ R5 = ROT R5 BY 1 || // low q to high q
+ R2 = [P5]; // load saved AQ
+ R6 = ROT R6 BY 1 || // high q to low r
+ R0 = [P2]; // load -Y'
+ R7 = ROT R7 BY 1 || // low r to high r
+ R1 = [P3];
+
+ // Assume add -Y'
+ CC = R2 < 0; // But if AQ is set...
+ IF CC R0 = P0; // then add Y' instead
+ IF CC R1 = P1;
+
+ R6 = R6 + R0; // Rem += (Y' or -Y')
+ CC = CARRY;
+ R0 = CC;
+ R7 = R7 + R1;
+ R7 = R7 + R0 (NS) ||
+ R1 = [SP];
+ // Set the next AQ bit
+ R1 = R7 ^ R1; // from Remainder and Y'
+ R1 = R1 >> 31 || // Negate AQ's value, and
+ [P5] = R1; // save next AQ
+ BITTGL(R1, 0); // add neg AQ to the Div
+.LULEND: R4 = R4 + R1;
+
+ R6 = [SP + 16];
+
+ R0 = R4;
+ R1 = R5;
+ CC = BITTST(R6,30); // Just set CC=0
+ R4 = ROT R0 BY 1; // but if we had to shift X,
+ R5 = ROT R1 BY 1; // and didn't shift any bits out,
+ CC = BITTST(R6,31); // then the result will be half as
+ IF CC R0 = R4; // much as required, so shift left
+ IF CC R1 = R5; // one space.
+
+ SP += 20;
+ (R7:4, P5:3) = [SP++];
+ RTS;
+
+.Lpower_of_two:
+ /* Y has a single bit set, which means it's a power of two.
+ ** That means we can perform the division just by shifting
+ ** X to the right the appropriate number of bits
+ */
+
+ /* signbits returns the number of sign bits, minus one.
+ ** 1=>30, 2=>29, ..., 0x40000000=>0. Which means we need
+ ** to shift right n-signbits spaces. It also means 0x80000000
+ ** is a special case, because that *also* gives a signbits of 0
+ */
+.Lpower_of_two_lower_zero:
+ R7 = 0;
+ R6 = R1 >> 31;
+ CC = R3 < 0;
+ IF CC JUMP .LRETURN_IDENT;
+
+ R2.L = SIGNBITS R3;
+ R2 = R2.L (Z);
+ R2 += -62;
+ (R7:4, P5:3) = [SP++];
+ JUMP ___lshftli;
+
+.Lpower_of_two_upper_zero:
+ CC = R2 < 0;
+ IF CC JUMP .Lmaxint_shift;
+
+ R2.L = SIGNBITS R2;
+ R2 = R2.L (Z);
+ R2 += -30;
+ (R7:4, P5:3) = [SP++];
+ JUMP ___lshftli;
+
+.Lmaxint_shift:
+ R2 = -31;
+ (R7:4, P5:3) = [SP++];
+ JUMP ___lshftli;
+
+.LRETURN_IDENT:
+ R0 = R6;
+ R1 = R7;
+.LRETURN_R0:
+ (R7:4, P5:3) = [SP++];
+ RTS;
+.LDIV_BY_ZERO:
+ R0 = ~R2;
+ R1 = R0;
+ (R7:4, P5:3) = [SP++];
+ RTS;
+
+ENDPROC(___udivdi3)
+
+
+ENTRY(___lshftli)
+ CC = R2 == 0;
+ IF CC JUMP .Lfinished; // nothing to do
+ CC = R2 < 0;
+ IF CC JUMP .Lrshift;
+ R3 = 64;
+ CC = R2 < R3;
+ IF !CC JUMP .Lretzero;
+
+ // We're shifting left, and it's less than 64 bits, so
+ // a valid result will be returned.
+
+ R3 >>= 1; // R3 now 32
+ CC = R2 < R3;
+
+ IF !CC JUMP .Lzerohalf;
+
+ // We're shifting left, between 1 and 31 bits, which means
+ // some of the low half will be shifted into the high half.
+ // Work out how much.
+
+ R3 = R3 - R2;
+
+ // Save that much data from the bottom half.
+
+ P1 = R7;
+ R7 = R0;
+ R7 >>= R3;
+
+ // Adjust both parts of the parameter.
+
+ R0 <<= R2;
+ R1 <<= R2;
+
+ // And include the bits moved across.
+
+ R1 = R1 | R7;
+ R7 = P1;
+ RTS;
+
+.Lzerohalf:
+ // We're shifting left, between 32 and 63 bits, so the
+ // bottom half will become zero, and the top half will
+ // lose some bits. How many?
+
+ R2 = R2 - R3; // N - 32
+ R1 = LSHIFT R0 BY R2.L;
+ R0 = R0 - R0;
+ RTS;
+
+.Lretzero:
+ R0 = R0 - R0;
+ R1 = R0;
+.Lfinished:
+ RTS;
+
+.Lrshift:
+ // We're shifting right, but by how much?
+ R2 = -R2;
+ R3 = 64;
+ CC = R2 < R3;
+ IF !CC JUMP .Lretzero;
+
+ // Shifting right less than 64 bits, so some result bits will
+ // be retained.
+
+ R3 >>= 1; // R3 now 32
+ CC = R2 < R3;
+ IF !CC JUMP .Lsignhalf;
+
+ // Shifting right between 1 and 31 bits, so need to copy
+ // data across words.
+
+ P1 = R7;
+ R3 = R3 - R2;
+ R7 = R1;
+ R7 <<= R3;
+ R1 >>= R2;
+ R0 >>= R2;
+ R0 = R7 | R0;
+ R7 = P1;
+ RTS;
+
+.Lsignhalf:
+ // Shifting right between 32 and 63 bits, so the top half
+ // will become all zero-bits, and the bottom half is some
+ // of the top half. But how much?
+
+ R2 = R2 - R3;
+ R0 = R1;
+ R0 >>= R2;
+ R1 = 0;
+ RTS;
+
+ENDPROC(___lshftli)
diff --git a/arch/blackfin/mach-bf527/Kconfig b/arch/blackfin/mach-bf527/Kconfig
new file mode 100644
index 000000000000..50321f723dee
--- /dev/null
+++ b/arch/blackfin/mach-bf527/Kconfig
@@ -0,0 +1,251 @@
+if (BF52x)
+
+menu "BF527 Specific Configuration"
+
+comment "Alternative Multiplexing Scheme"
+
+choice
+ prompt "SPORT0"
+ default BF527_SPORT0_PORTG
+ help
+ Select PORT used for SPORT0. See Hardware Reference Manual
+
+config BF527_SPORT0_PORTF
+ bool "PORT F"
+ help
+ PORT F
+
+config BF527_SPORT0_PORTG
+ bool "PORT G"
+ help
+ PORT G
+endchoice
+
+choice
+ prompt "SPORT0 TSCLK Location"
+ depends on BF527_SPORT0_PORTG
+ default BF527_SPORT0_TSCLK_PG10
+ help
+ Select PIN used for SPORT0_TSCLK. See Hardware Reference Manual
+
+config BF527_SPORT0_TSCLK_PG10
+ bool "PORT PG10"
+ help
+ PORT PG10
+
+config BF527_SPORT0_TSCLK_PG14
+ bool "PORT PG14"
+ help
+ PORT PG14
+endchoice
+
+choice
+ prompt "UART1"
+ default BF527_UART1_PORTG
+ help
+ Select PORT used for UART1. See Hardware Reference Manual
+
+config BF527_UART1_PORTF
+ bool "PORT F"
+ help
+ PORT F
+
+config BF527_UART1_PORTG
+ bool "PORT G"
+ help
+ PORT G
+endchoice
+
+choice
+ prompt "NAND (NFC) Data"
+ default BF527_NAND_D_PORTH
+ help
+ Select PORT used for NAND Data Bus. See Hardware Reference Manual
+
+config BF527_NAND_D_PORTF
+ bool "PORT F"
+ help
+ PORT F
+
+config BF527_NAND_D_PORTH
+ bool "PORT H"
+ help
+ PORT H
+endchoice
+
+comment "Interrupt Priority Assignment"
+menu "Priority"
+
+config IRQ_PLL_WAKEUP
+ int "IRQ_PLL_WAKEUP"
+ default 7
+config IRQ_DMA0_ERROR
+ int "IRQ_DMA0_ERROR"
+ default 7
+config IRQ_DMAR0_BLK
+ int "IRQ_DMAR0_BLK"
+ default 7
+config IRQ_DMAR1_BLK
+ int "IRQ_DMAR1_BLK"
+ default 7
+config IRQ_DMAR0_OVR
+ int "IRQ_DMAR0_OVR"
+ default 7
+config IRQ_DMAR1_OVR
+ int "IRQ_DMAR1_OVR"
+ default 7
+config IRQ_PPI_ERROR
+ int "IRQ_PPI_ERROR"
+ default 7
+config IRQ_MAC_ERROR
+ int "IRQ_MAC_ERROR"
+ default 7
+config IRQ_SPORT0_ERROR
+ int "IRQ_SPORT0_ERROR"
+ default 7
+config IRQ_SPORT1_ERROR
+ int "IRQ_SPORT1_ERROR"
+ default 7
+config IRQ_UART0_ERROR
+ int "IRQ_UART0_ERROR"
+ default 7
+config IRQ_UART1_ERROR
+ int "IRQ_UART1_ERROR"
+ default 7
+config IRQ_RTC
+ int "IRQ_RTC"
+ default 8
+config IRQ_PPI
+ int "IRQ_PPI"
+ default 8
+config IRQ_SPORT0_RX
+ int "IRQ_SPORT0_RX"
+ default 9
+config IRQ_SPORT0_TX
+ int "IRQ_SPORT0_TX"
+ default 9
+config IRQ_SPORT1_RX
+ int "IRQ_SPORT1_RX"
+ default 9
+config IRQ_SPORT1_TX
+ int "IRQ_SPORT1_TX"
+ default 9
+config IRQ_TWI
+ int "IRQ_TWI"
+ default 10
+config IRQ_SPI
+ int "IRQ_SPI"
+ default 10
+config IRQ_UART0_RX
+ int "IRQ_UART0_RX"
+ default 10
+config IRQ_UART0_TX
+ int "IRQ_UART0_TX"
+ default 10
+config IRQ_UART1_RX
+ int "IRQ_UART1_RX"
+ default 10
+config IRQ_UART1_TX
+ int "IRQ_UART1_TX"
+ default 10
+config IRQ_OPTSEC
+ int "IRQ_OPTSEC"
+ default 11
+config IRQ_CNT
+ int "IRQ_CNT"
+ default 11
+config IRQ_MAC_RX
+ int "IRQ_MAC_RX"
+ default 11
+config IRQ_PORTH_INTA
+ int "IRQ_PORTH_INTA"
+ default 11
+config IRQ_MAC_TX
+ int "IRQ_MAC_TX/NFC"
+ default 11
+config IRQ_PORTH_INTB
+ int "IRQ_PORTH_INTB"
+ default 11
+config IRQ_TMR0
+ int "IRQ_TMR0"
+ default 12
+config IRQ_TMR1
+ int "IRQ_TMR1"
+ default 12
+config IRQ_TMR2
+ int "IRQ_TMR2"
+ default 12
+config IRQ_TMR3
+ int "IRQ_TMR3"
+ default 12
+config IRQ_TMR4
+ int "IRQ_TMR4"
+ default 12
+config IRQ_TMR5
+ int "IRQ_TMR5"
+ default 12
+config IRQ_TMR6
+ int "IRQ_TMR6"
+ default 12
+config IRQ_TMR7
+ int "IRQ_TMR7"
+ default 12
+config IRQ_PORTG_INTA
+ int "IRQ_PORTG_INTA"
+ default 12
+config IRQ_PORTG_INTB
+ int "IRQ_PORTG_INTB"
+ default 12
+config IRQ_MEM_DMA0
+ int "IRQ_MEM_DMA0"
+ default 13
+config IRQ_MEM_DMA1
+ int "IRQ_MEM_DMA1"
+ default 13
+config IRQ_WATCH
+ int "IRQ_WATCH"
+ default 13
+config IRQ_PORTF_INTA
+ int "IRQ_PORTF_INTA"
+ default 13
+config IRQ_PORTF_INTB
+ int "IRQ_PORTF_INTB"
+ default 13
+config IRQ_SPI_ERROR
+ int "IRQ_SPI_ERROR"
+ default 7
+config IRQ_NFC_ERROR
+ int "IRQ_NFC_ERROR"
+ default 7
+config IRQ_HDMA_ERROR
+ int "IRQ_HDMA_ERROR"
+ default 7
+config IRQ_HDMA
+ int "IRQ_HDMA"
+ default 7
+config IRQ_USB_EINT
+ int "IRQ_USB_EINT"
+ default 10
+config IRQ_USB_INT0
+ int "IRQ_USB_INT0"
+ default 10
+config IRQ_USB_INT1
+ int "IRQ_USB_INT1"
+ default 10
+config IRQ_USB_INT2
+ int "IRQ_USB_INT2"
+ default 10
+config IRQ_USB_DMA
+ int "IRQ_USB_DMA"
+ default 10
+
+ help
+ Enter the priority numbers between 7-13 ONLY. Others are Reserved.
+ This applies to all the above. It is not recommended to assign the
+ highest priority number 7 to UART or any other device.
+
+endmenu
+
+endmenu
+
+endif
diff --git a/arch/blackfin/mach-bf527/Makefile b/arch/blackfin/mach-bf527/Makefile
new file mode 100644
index 000000000000..9f99f5d0bcd1
--- /dev/null
+++ b/arch/blackfin/mach-bf527/Makefile
@@ -0,0 +1,9 @@
+#
+# arch/blackfin/mach-bf527/Makefile
+#
+
+extra-y := head.o
+
+obj-y := ints-priority.o dma.o
+
+obj-$(CONFIG_CPU_FREQ) += cpu.o
diff --git a/arch/blackfin/mach-bf527/boards/Makefile b/arch/blackfin/mach-bf527/boards/Makefile
new file mode 100644
index 000000000000..912ac8ebc889
--- /dev/null
+++ b/arch/blackfin/mach-bf527/boards/Makefile
@@ -0,0 +1,7 @@
+#
+# arch/blackfin/mach-bf532/boards/Makefile
+#
+
+obj-y += eth_mac.o
+obj-$(CONFIG_BFIN527_EZKIT) += ezkit.o
+
diff --git a/arch/blackfin/mach-bf527/boards/eth_mac.c b/arch/blackfin/mach-bf527/boards/eth_mac.c
new file mode 100644
index 000000000000..a725cc8a9290
--- /dev/null
+++ b/arch/blackfin/mach-bf527/boards/eth_mac.c
@@ -0,0 +1,50 @@
+/*
+ * arch/blackfin/mach-bf537/board/eth_mac.c
+ *
+ * Copyright (C) 2007 Analog Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/module.h>
+#include <asm/blackfin.h>
+
+#if defined(CONFIG_GENERIC_BOARD) || defined(CONFIG_BFIN537_STAMP)
+
+/*
+ * Currently the MAC address is saved in Flash by U-Boot
+ */
+#define FLASH_MAC 0x203f0000
+
+void get_bf537_ether_addr(char *addr)
+{
+ unsigned int flash_mac = (unsigned int) FLASH_MAC;
+ *(u32 *)(&(addr[0])) = bfin_read32(flash_mac);
+ flash_mac += 4;
+ *(u16 *)(&(addr[4])) = bfin_read16(flash_mac);
+}
+
+#else
+
+/*
+ * Provide MAC address function for other specific board setting
+ */
+void get_bf537_ether_addr(char *addr)
+{
+ printk(KERN_WARNING "%s: No valid Ethernet MAC address found\n", __FILE__);
+}
+
+#endif
+
+EXPORT_SYMBOL(get_bf537_ether_addr);
diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c
new file mode 100644
index 000000000000..bf1bedcc8868
--- /dev/null
+++ b/arch/blackfin/mach-bf527/boards/ezkit.c
@@ -0,0 +1,790 @@
+/*
+ * File: arch/blackfin/mach-bf527/boards/ezkit.c
+ * Based on: arch/blackfin/mach-bf537/boards/stamp.c
+ * Author: Aidan Williams <aidan@nicta.com.au>
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ * Copyright 2005 National ICT Australia (NICTA)
+ * Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
+#include <linux/usb_isp1362.h>
+#endif
+#include <linux/pata_platform.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/usb_sl811.h>
+#include <asm/cplb.h>
+#include <asm/dma.h>
+#include <asm/bfin5xx_spi.h>
+#include <asm/reboot.h>
+#include <asm/nand.h>
+#include <linux/spi/ad7877.h>
+
+/*
+ * Name the Board for the /proc/cpuinfo
+ */
+const char bfin_board_name[] = "ADDS-BF527-EZKIT";
+
+/*
+ * Driver needs to know address, irq and flag pin.
+ */
+
+#define ISP1761_BASE 0x203C0000
+#define ISP1761_IRQ IRQ_PF7
+
+#if defined(CONFIG_USB_ISP1760_HCD) || defined(CONFIG_USB_ISP1760_HCD_MODULE)
+static struct resource bfin_isp1761_resources[] = {
+ [0] = {
+ .name = "isp1761-regs",
+ .start = ISP1761_BASE + 0x00000000,
+ .end = ISP1761_BASE + 0x000fffff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = ISP1761_IRQ,
+ .end = ISP1761_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device bfin_isp1761_device = {
+ .name = "isp1761",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_isp1761_resources),
+ .resource = bfin_isp1761_resources,
+};
+
+static struct platform_device *bfin_isp1761_devices[] = {
+ &bfin_isp1761_device,
+};
+
+int __init bfin_isp1761_init(void)
+{
+ unsigned int num_devices = ARRAY_SIZE(bfin_isp1761_devices);
+
+ printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+ set_irq_type(ISP1761_IRQ, IRQF_TRIGGER_FALLING);
+
+ return platform_add_devices(bfin_isp1761_devices, num_devices);
+}
+
+void __exit bfin_isp1761_exit(void)
+{
+ platform_device_unregister(&bfin_isp1761_device);
+}
+
+arch_initcall(bfin_isp1761_init);
+#endif
+
+#if defined(CONFIG_MTD_NAND_BF5XX) || defined(CONFIG_MTD_NAND_BF5XX_MODULE)
+static struct mtd_partition partition_info[] = {
+ {
+ .name = "Linux Kernel",
+ .offset = 0,
+ .size = 4 * SIZE_1M,
+ },
+ {
+ .name = "File System",
+ .offset = 4 * SIZE_1M,
+ .size = (256 - 4) * SIZE_1M,
+ },
+};
+
+static struct bf5xx_nand_platform bf5xx_nand_platform = {
+ .page_size = NFC_PG_SIZE_256,
+ .data_width = NFC_NWIDTH_8,
+ .partitions = partition_info,
+ .nr_partitions = ARRAY_SIZE(partition_info),
+ .rd_dly = 3,
+ .wr_dly = 3,
+};
+
+static struct resource bf5xx_nand_resources[] = {
+ {
+ .start = NFC_CTL,
+ .end = NFC_DATA_RD + 2,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = CH_NFC,
+ .end = CH_NFC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device bf5xx_nand_device = {
+ .name = "bf5xx-nand",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bf5xx_nand_resources),
+ .resource = bf5xx_nand_resources,
+ .dev = {
+ .platform_data = &bf5xx_nand_platform,
+ },
+};
+#endif
+
+#if defined(CONFIG_BFIN_CFPCMCIA) || defined(CONFIG_BFIN_CFPCMCIA_MODULE)
+static struct resource bfin_pcmcia_cf_resources[] = {
+ {
+ .start = 0x20310000, /* IO PORT */
+ .end = 0x20312000,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = 0x20311000, /* Attribute Memory */
+ .end = 0x20311FFF,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_PF4,
+ .end = IRQ_PF4,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
+ }, {
+ .start = 6, /* Card Detect PF6 */
+ .end = 6,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device bfin_pcmcia_cf_device = {
+ .name = "bfin_cf_pcmcia",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(bfin_pcmcia_cf_resources),
+ .resource = bfin_pcmcia_cf_resources,
+};
+#endif
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+static struct platform_device rtc_device = {
+ .name = "rtc-bfin",
+ .id = -1,
+};
+#endif
+
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+static struct resource smc91x_resources[] = {
+ {
+ .name = "smc91x-regs",
+ .start = 0x20300300,
+ .end = 0x20300300 + 16,
+ .flags = IORESOURCE_MEM,
+ }, {
+
+ .start = IRQ_PF7,
+ .end = IRQ_PF7,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+ },
+};
+static struct platform_device smc91x_device = {
+ .name = "smc91x",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(smc91x_resources),
+ .resource = smc91x_resources,
+};
+#endif
+
+#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
+static struct resource dm9000_resources[] = {
+ [0] = {
+ .start = 0x203FB800,
+ .end = 0x203FB800 + 8,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_PF9,
+ .end = IRQ_PF9,
+ .flags = (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE),
+ },
+};
+
+static struct platform_device dm9000_device = {
+ .name = "dm9000",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(dm9000_resources),
+ .resource = dm9000_resources,
+};
+#endif
+
+#if defined(CONFIG_USB_SL811_HCD) || defined(CONFIG_USB_SL811_HCD_MODULE)
+static struct resource sl811_hcd_resources[] = {
+ {
+ .start = 0x20340000,
+ .end = 0x20340000,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = 0x20340004,
+ .end = 0x20340004,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = CONFIG_USB_SL811_BFIN_IRQ,
+ .end = CONFIG_USB_SL811_BFIN_IRQ,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+ },
+};
+
+#if defined(CONFIG_USB_SL811_BFIN_USE_VBUS)
+void sl811_port_power(struct device *dev, int is_on)
+{
+ gpio_request(CONFIG_USB_SL811_BFIN_GPIO_VBUS, "usb:SL811_VBUS");
+ gpio_direction_output(CONFIG_USB_SL811_BFIN_GPIO_VBUS);
+
+ if (is_on)
+ gpio_set_value(CONFIG_USB_SL811_BFIN_GPIO_VBUS, 1);
+ else
+ gpio_set_value(CONFIG_USB_SL811_BFIN_GPIO_VBUS, 0);
+}
+#endif
+
+static struct sl811_platform_data sl811_priv = {
+ .potpg = 10,
+ .power = 250, /* == 500mA */
+#if defined(CONFIG_USB_SL811_BFIN_USE_VBUS)
+ .port_power = &sl811_port_power,
+#endif
+};
+
+static struct platform_device sl811_hcd_device = {
+ .name = "sl811-hcd",
+ .id = 0,
+ .dev = {
+ .platform_data = &sl811_priv,
+ },
+ .num_resources = ARRAY_SIZE(sl811_hcd_resources),
+ .resource = sl811_hcd_resources,
+};
+#endif
+
+#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
+static struct resource isp1362_hcd_resources[] = {
+ {
+ .start = 0x20360000,
+ .end = 0x20360000,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = 0x20360004,
+ .end = 0x20360004,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = CONFIG_USB_ISP1362_BFIN_GPIO_IRQ,
+ .end = CONFIG_USB_ISP1362_BFIN_GPIO_IRQ,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+ },
+};
+
+static struct isp1362_platform_data isp1362_priv = {
+ .sel15Kres = 1,
+ .clknotstop = 0,
+ .oc_enable = 0,
+ .int_act_high = 0,
+ .int_edge_triggered = 0,
+ .remote_wakeup_connected = 0,
+ .no_power_switching = 1,
+ .power_switching_mode = 0,
+};
+
+static struct platform_device isp1362_hcd_device = {
+ .name = "isp1362-hcd",
+ .id = 0,
+ .dev = {
+ .platform_data = &isp1362_priv,
+ },
+ .num_resources = ARRAY_SIZE(isp1362_hcd_resources),
+ .resource = isp1362_hcd_resources,
+};
+#endif
+
+#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+static struct platform_device bfin_mac_device = {
+ .name = "bfin_mac",
+};
+#endif
+
+#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
+static struct resource net2272_bfin_resources[] = {
+ {
+ .start = 0x20300000,
+ .end = 0x20300000 + 0x100,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_PF7,
+ .end = IRQ_PF7,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+ },
+};
+
+static struct platform_device net2272_bfin_device = {
+ .name = "net2272",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(net2272_bfin_resources),
+ .resource = net2272_bfin_resources,
+};
+#endif
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+/* all SPI peripherals info goes here */
+
+#if defined(CONFIG_MTD_M25P80) \
+ || defined(CONFIG_MTD_M25P80_MODULE)
+static struct mtd_partition bfin_spi_flash_partitions[] = {
+ {
+ .name = "bootloader",
+ .size = 0x00020000,
+ .offset = 0,
+ .mask_flags = MTD_CAP_ROM
+ }, {
+ .name = "kernel",
+ .size = 0xe0000,
+ .offset = 0x20000
+ }, {
+ .name = "file system",
+ .size = 0x700000,
+ .offset = 0x00100000,
+ }
+};
+
+static struct flash_platform_data bfin_spi_flash_data = {
+ .name = "m25p80",
+ .parts = bfin_spi_flash_partitions,
+ .nr_parts = ARRAY_SIZE(bfin_spi_flash_partitions),
+ .type = "m25p64",
+};
+
+/* SPI flash chip (m25p64) */
+static struct bfin5xx_spi_chip spi_flash_chip_info = {
+ .enable_dma = 0, /* use dma transfer with this chip*/
+ .bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_SPI_ADC_BF533) \
+ || defined(CONFIG_SPI_ADC_BF533_MODULE)
+/* SPI ADC chip */
+static struct bfin5xx_spi_chip spi_adc_chip_info = {
+ .enable_dma = 1, /* use dma transfer with this chip*/
+ .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_SND_BLACKFIN_AD1836) \
+ || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
+static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
+ .enable_dma = 0,
+ .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_AD9960) || defined(CONFIG_AD9960_MODULE)
+static struct bfin5xx_spi_chip ad9960_spi_chip_info = {
+ .enable_dma = 0,
+ .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
+static struct bfin5xx_spi_chip spi_mmc_chip_info = {
+ .enable_dma = 1,
+ .bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_PBX)
+static struct bfin5xx_spi_chip spi_si3xxx_chip_info = {
+ .ctl_reg = 0x4, /* send zero */
+ .enable_dma = 0,
+ .bits_per_word = 8,
+ .cs_change_per_word = 1,
+};
+#endif
+
+#if defined(CONFIG_AD5304) || defined(CONFIG_AD5304_MODULE)
+static struct bfin5xx_spi_chip ad5304_chip_info = {
+ .enable_dma = 0,
+ .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
+static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
+ .enable_dma = 0,
+ .bits_per_word = 16,
+};
+
+static const struct ad7877_platform_data bfin_ad7877_ts_info = {
+ .model = 7877,
+ .vref_delay_usecs = 50, /* internal, no capacitor */
+ .x_plate_ohms = 419,
+ .y_plate_ohms = 486,
+ .pressure_max = 1000,
+ .pressure_min = 0,
+ .stopacq_polarity = 1,
+ .first_conversion_delay = 3,
+ .acquisition_time = 1,
+ .averaging = 1,
+ .pen_down_acc_interval = 1,
+};
+#endif
+
+static struct spi_board_info bfin_spi_board_info[] __initdata = {
+#if defined(CONFIG_MTD_M25P80) \
+ || defined(CONFIG_MTD_M25P80_MODULE)
+ {
+ /* the modalias must be the same as spi device driver name */
+ .modalias = "m25p80", /* Name of spi_driver for this device */
+ .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0, /* Framework bus number */
+ .chip_select = 1, /* Framework chip select. On STAMP537 it is SPISSEL1*/
+ .platform_data = &bfin_spi_flash_data,
+ .controller_data = &spi_flash_chip_info,
+ .mode = SPI_MODE_3,
+ },
+#endif
+
+#if defined(CONFIG_SPI_ADC_BF533) \
+ || defined(CONFIG_SPI_ADC_BF533_MODULE)
+ {
+ .modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
+ .max_speed_hz = 6250000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0, /* Framework bus number */
+ .chip_select = 1, /* Framework chip select. */
+ .platform_data = NULL, /* No spi_driver specific config */
+ .controller_data = &spi_adc_chip_info,
+ },
+#endif
+
+#if defined(CONFIG_SND_BLACKFIN_AD1836) \
+ || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
+ {
+ .modalias = "ad1836-spi",
+ .max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+ .controller_data = &ad1836_spi_chip_info,
+ },
+#endif
+#if defined(CONFIG_AD9960) || defined(CONFIG_AD9960_MODULE)
+ {
+ .modalias = "ad9960-spi",
+ .max_speed_hz = 10000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 1,
+ .controller_data = &ad9960_spi_chip_info,
+ },
+#endif
+#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
+ {
+ .modalias = "spi_mmc_dummy",
+ .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 0,
+ .platform_data = NULL,
+ .controller_data = &spi_mmc_chip_info,
+ .mode = SPI_MODE_3,
+ },
+ {
+ .modalias = "spi_mmc",
+ .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = CONFIG_SPI_MMC_CS_CHAN,
+ .platform_data = NULL,
+ .controller_data = &spi_mmc_chip_info,
+ .mode = SPI_MODE_3,
+ },
+#endif
+#if defined(CONFIG_PBX)
+ {
+ .modalias = "fxs-spi",
+ .max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 8 - CONFIG_J11_JUMPER,
+ .controller_data = &spi_si3xxx_chip_info,
+ .mode = SPI_MODE_3,
+ },
+ {
+ .modalias = "fxo-spi",
+ .max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 8 - CONFIG_J19_JUMPER,
+ .controller_data = &spi_si3xxx_chip_info,
+ .mode = SPI_MODE_3,
+ },
+#endif
+#if defined(CONFIG_AD5304) || defined(CONFIG_AD5304_MODULE)
+ {
+ .modalias = "ad5304_spi",
+ .max_speed_hz = 1250000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 2,
+ .platform_data = NULL,
+ .controller_data = &ad5304_chip_info,
+ .mode = SPI_MODE_2,
+ },
+#endif
+#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
+ {
+ .modalias = "ad7877",
+ .platform_data = &bfin_ad7877_ts_info,
+ .irq = IRQ_PF6,
+ .max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 1,
+ .chip_select = 1,
+ .controller_data = &spi_ad7877_chip_info,
+ },
+#endif
+};
+
+/* SPI controller data */
+static struct bfin5xx_spi_master bfin_spi0_info = {
+ .num_chipselect = 8,
+ .enable_dma = 1, /* master has the ability to do dma transfer */
+};
+
+/* SPI (0) */
+static struct resource bfin_spi0_resource[] = {
+ [0] = {
+ .start = SPI0_REGBASE,
+ .end = SPI0_REGBASE + 0xFF,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = CH_SPI,
+ .end = CH_SPI,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device bfin_spi0_device = {
+ .name = "bfin-spi",
+ .id = 0, /* Bus number */
+ .num_resources = ARRAY_SIZE(bfin_spi0_resource),
+ .resource = bfin_spi0_resource,
+ .dev = {
+ .platform_data = &bfin_spi0_info, /* Passed to driver */
+ },
+};
+#endif /* spi master and devices */
+
+#if defined(CONFIG_FB_BF537_LQ035) || defined(CONFIG_FB_BF537_LQ035_MODULE)
+static struct platform_device bfin_fb_device = {
+ .name = "bf537-lq035",
+};
+#endif
+
+#if defined(CONFIG_FB_BFIN_7393) || defined(CONFIG_FB_BFIN_7393_MODULE)
+static struct platform_device bfin_fb_adv7393_device = {
+ .name = "bfin-adv7393",
+};
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+static struct resource bfin_uart_resources[] = {
+#ifdef CONFIG_SERIAL_BFIN_UART0
+ {
+ .start = 0xFFC00400,
+ .end = 0xFFC004FF,
+ .flags = IORESOURCE_MEM,
+ },
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART1
+ {
+ .start = 0xFFC02000,
+ .end = 0xFFC020FF,
+ .flags = IORESOURCE_MEM,
+ },
+#endif
+};
+
+static struct platform_device bfin_uart_device = {
+ .name = "bfin-uart",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(bfin_uart_resources),
+ .resource = bfin_uart_resources,
+};
+#endif
+
+#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+static struct resource bfin_twi0_resource[] = {
+ [0] = {
+ .start = TWI0_REGBASE,
+ .end = TWI0_REGBASE,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_TWI,
+ .end = IRQ_TWI,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device i2c_bfin_twi_device = {
+ .name = "i2c-bfin-twi",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_twi0_resource),
+ .resource = bfin_twi0_resource,
+};
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+static struct platform_device bfin_sport0_uart_device = {
+ .name = "bfin-sport-uart",
+ .id = 0,
+};
+
+static struct platform_device bfin_sport1_uart_device = {
+ .name = "bfin-sport-uart",
+ .id = 1,
+};
+#endif
+
+#if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
+#define PATA_INT 55
+
+static struct pata_platform_info bfin_pata_platform_data = {
+ .ioport_shift = 1,
+ .irq_type = IRQF_TRIGGER_HIGH | IRQF_DISABLED,
+};
+
+static struct resource bfin_pata_resources[] = {
+ {
+ .start = 0x20314020,
+ .end = 0x2031403F,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = 0x2031401C,
+ .end = 0x2031401F,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = PATA_INT,
+ .end = PATA_INT,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device bfin_pata_device = {
+ .name = "pata_platform",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(bfin_pata_resources),
+ .resource = bfin_pata_resources,
+ .dev = {
+ .platform_data = &bfin_pata_platform_data,
+ }
+};
+#endif
+
+static struct platform_device *stamp_devices[] __initdata = {
+#if defined(CONFIG_MTD_NAND_BF5XX) || defined(CONFIG_MTD_NAND_BF5XX_MODULE)
+ &bf5xx_nand_device,
+#endif
+
+#if defined(CONFIG_BFIN_CFPCMCIA) || defined(CONFIG_BFIN_CFPCMCIA_MODULE)
+ &bfin_pcmcia_cf_device,
+#endif
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+ &rtc_device,
+#endif
+
+#if defined(CONFIG_USB_SL811_HCD) || defined(CONFIG_USB_SL811_HCD_MODULE)
+ &sl811_hcd_device,
+#endif
+
+#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
+ &isp1362_hcd_device,
+#endif
+
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+ &smc91x_device,
+#endif
+
+#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
+ &dm9000_device,
+#endif
+
+#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+ &bfin_mac_device,
+#endif
+
+#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
+ &net2272_bfin_device,
+#endif
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ &bfin_spi0_device,
+#endif
+
+#if defined(CONFIG_FB_BF537_LQ035) || defined(CONFIG_FB_BF537_LQ035_MODULE)
+ &bfin_fb_device,
+#endif
+
+#if defined(CONFIG_FB_BFIN_7393) || defined(CONFIG_FB_BFIN_7393_MODULE)
+ &bfin_fb_adv7393_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+ &bfin_uart_device,
+#endif
+
+#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+ &i2c_bfin_twi_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+ &bfin_sport0_uart_device,
+ &bfin_sport1_uart_device,
+#endif
+
+#if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
+ &bfin_pata_device,
+#endif
+};
+
+static int __init stamp_init(void)
+{
+ printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+ platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ spi_register_board_info(bfin_spi_board_info,
+ ARRAY_SIZE(bfin_spi_board_info));
+#endif
+
+#if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
+ irq_desc[PATA_INT].status |= IRQ_NOAUTOEN;
+#endif
+ return 0;
+}
+
+arch_initcall(stamp_init);
+
+void native_machine_restart(char *cmd)
+{
+ /* workaround reboot hang when booting from SPI */
+ if ((bfin_read_SYSCR() & 0x7) == 0x3)
+ bfin_gpio_reset_spi0_ssel1();
+}
diff --git a/arch/blackfin/mach-bf527/cpu.c b/arch/blackfin/mach-bf527/cpu.c
new file mode 100644
index 000000000000..1975402b1dbc
--- /dev/null
+++ b/arch/blackfin/mach-bf527/cpu.c
@@ -0,0 +1,161 @@
+/*
+ * File: arch/blackfin/mach-bf527/cpu.c
+ * Based on: arch/blackfin/mach-bf537/cpu.c
+ * Author: michael.kang@analog.com
+ *
+ * Created:
+ * Description: clock scaling for the bf527
+ *
+ * Modified:
+ * Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/cpufreq.h>
+#include <asm/dpmc.h>
+#include <linux/fs.h>
+#include <asm/bfin-global.h>
+
+/* CONFIG_CLKIN_HZ=11059200 */
+#define VCO5 (CONFIG_CLKIN_HZ*45) /*497664000 */
+#define VCO4 (CONFIG_CLKIN_HZ*36) /*398131200 */
+#define VCO3 (CONFIG_CLKIN_HZ*27) /*298598400 */
+#define VCO2 (CONFIG_CLKIN_HZ*18) /*199065600 */
+#define VCO1 (CONFIG_CLKIN_HZ*9) /*99532800 */
+#define VCO(x) VCO##x
+
+#define MFREQ(x) {VCO(x), VCO(x)/4}, {VCO(x), VCO(x)/2}, {VCO(x), VCO(x)}
+/* frequency */
+static struct cpufreq_frequency_table bf527_freq_table[] = {
+ MFREQ(1),
+ MFREQ(3),
+ {VCO4, VCO4 / 2}, {VCO4, VCO4},
+ MFREQ(5),
+ {0, CPUFREQ_TABLE_END},
+};
+
+/*
+ * dpmc_fops->ioctl()
+ * static int dpmc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+ */
+static int bf527_getfreq(unsigned int cpu)
+{
+ unsigned long cclk_mhz;
+
+ /* The driver only support single cpu */
+ if (cpu == 0)
+ dpmc_fops.ioctl(NULL, NULL, IOCTL_GET_CORECLOCK, &cclk_mhz);
+ else
+ cclk_mhz = -1;
+
+ return cclk_mhz;
+}
+
+static int bf527_target(struct cpufreq_policy *policy,
+ unsigned int target_freq, unsigned int relation)
+{
+ unsigned long cclk_mhz;
+ unsigned long vco_mhz;
+ unsigned long flags;
+ unsigned int index;
+ struct cpufreq_freqs freqs;
+
+ if (cpufreq_frequency_table_target
+ (policy, bf527_freq_table, target_freq, relation, &index))
+ return -EINVAL;
+
+ cclk_mhz = bf527_freq_table[index].frequency;
+ vco_mhz = bf527_freq_table[index].index;
+
+ dpmc_fops.ioctl(NULL, NULL, IOCTL_CHANGE_FREQUENCY, &vco_mhz);
+ freqs.old = bf527_getfreq(0);
+ freqs.new = cclk_mhz;
+ freqs.cpu = 0;
+
+ pr_debug
+ ("cclk begin change to cclk %d,vco=%d,index=%d,target=%d,oldfreq=%d\n",
+ cclk_mhz, vco_mhz, index, target_freq, freqs.old);
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+ local_irq_save(flags);
+ dpmc_fops.ioctl(NULL, NULL, IOCTL_SET_CCLK, &cclk_mhz);
+ local_irq_restore(flags);
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+ vco_mhz = get_vco();
+ cclk_mhz = get_cclk();
+ return 0;
+}
+
+/* make sure that only the "userspace" governor is run -- anything else wouldn't make sense on
+ * this platform, anyway.
+ */
+static int bf527_verify_speed(struct cpufreq_policy *policy)
+{
+ return cpufreq_frequency_table_verify(policy, &bf527_freq_table);
+}
+
+static int __init __bf527_cpu_init(struct cpufreq_policy *policy)
+{
+ if (policy->cpu != 0)
+ return -EINVAL;
+
+ policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+
+ policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+ /*Now ,only support one cpu */
+ policy->cur = bf527_getfreq(0);
+ cpufreq_frequency_table_get_attr(bf527_freq_table, policy->cpu);
+ return cpufreq_frequency_table_cpuinfo(policy, bf527_freq_table);
+}
+
+static struct freq_attr *bf527_freq_attr[] = {
+ &cpufreq_freq_attr_scaling_available_freqs,
+ NULL,
+};
+
+static struct cpufreq_driver bf527_driver = {
+ .verify = bf527_verify_speed,
+ .target = bf527_target,
+ .get = bf527_getfreq,
+ .init = __bf527_cpu_init,
+ .name = "bf527",
+ .owner = THIS_MODULE,
+ .attr = bf527_freq_attr,
+};
+
+static int __init bf527_cpu_init(void)
+{
+ return cpufreq_register_driver(&bf527_driver);
+}
+
+static void __exit bf527_cpu_exit(void)
+{
+ cpufreq_unregister_driver(&bf527_driver);
+}
+
+MODULE_AUTHOR("Mickael Kang");
+MODULE_DESCRIPTION("cpufreq driver for bf527 CPU");
+MODULE_LICENSE("GPL");
+
+module_init(bf527_cpu_init);
+module_exit(bf527_cpu_exit);
diff --git a/arch/blackfin/mach-bf527/dma.c b/arch/blackfin/mach-bf527/dma.c
new file mode 100644
index 000000000000..522de24cc394
--- /dev/null
+++ b/arch/blackfin/mach-bf527/dma.c
@@ -0,0 +1,115 @@
+/*
+ * File: arch/blackfin/mach-bf527/dma.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description: This file contains the simple DMA Implementation for Blackfin
+ *
+ * Modified:
+ * Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <asm/blackfin.h>
+#include <asm/dma.h>
+
+struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+ (struct dma_register *) DMA0_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_NEXT_DESC_PTR,
+ (struct dma_register *) DMA3_NEXT_DESC_PTR,
+ (struct dma_register *) DMA4_NEXT_DESC_PTR,
+ (struct dma_register *) DMA5_NEXT_DESC_PTR,
+ (struct dma_register *) DMA6_NEXT_DESC_PTR,
+ (struct dma_register *) DMA7_NEXT_DESC_PTR,
+ (struct dma_register *) DMA8_NEXT_DESC_PTR,
+ (struct dma_register *) DMA9_NEXT_DESC_PTR,
+ (struct dma_register *) DMA10_NEXT_DESC_PTR,
+ (struct dma_register *) DMA11_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA_D0_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA_S0_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA_D1_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA_S1_NEXT_DESC_PTR,
+};
+
+int channel2irq(unsigned int channel)
+{
+ int ret_irq = -1;
+
+ switch (channel) {
+ case CH_PPI:
+ ret_irq = IRQ_PPI;
+ break;
+
+ case CH_EMAC_RX:
+ ret_irq = IRQ_MAC_RX;
+ break;
+
+ case CH_EMAC_TX:
+ ret_irq = IRQ_MAC_TX;
+ break;
+
+ case CH_UART1_RX:
+ ret_irq = IRQ_UART1_RX;
+ break;
+
+ case CH_UART1_TX:
+ ret_irq = IRQ_UART1_TX;
+ break;
+
+ case CH_SPORT0_RX:
+ ret_irq = IRQ_SPORT0_RX;
+ break;
+
+ case CH_SPORT0_TX:
+ ret_irq = IRQ_SPORT0_TX;
+ break;
+
+ case CH_SPORT1_RX:
+ ret_irq = IRQ_SPORT1_RX;
+ break;
+
+ case CH_SPORT1_TX:
+ ret_irq = IRQ_SPORT1_TX;
+ break;
+
+ case CH_SPI:
+ ret_irq = IRQ_SPI;
+ break;
+
+ case CH_UART0_RX:
+ ret_irq = IRQ_UART0_RX;
+ break;
+
+ case CH_UART0_TX:
+ ret_irq = IRQ_UART0_TX;
+ break;
+
+ case CH_MEM_STREAM0_SRC:
+ case CH_MEM_STREAM0_DEST:
+ ret_irq = IRQ_MEM_DMA0;
+ break;
+
+ case CH_MEM_STREAM1_SRC:
+ case CH_MEM_STREAM1_DEST:
+ ret_irq = IRQ_MEM_DMA1;
+ break;
+ }
+ return ret_irq;
+}
diff --git a/arch/blackfin/mach-bf527/head.S b/arch/blackfin/mach-bf527/head.S
new file mode 100644
index 000000000000..cdb00a084965
--- /dev/null
+++ b/arch/blackfin/mach-bf527/head.S
@@ -0,0 +1,456 @@
+/*
+ * File: arch/blackfin/mach-bf527/head.S
+ * Based on: arch/blackfin/mach-bf533/head.S
+ * Author: Jeff Dionne <jeff@uclinux.org> COPYRIGHT 1998 D. Jeff Dionne
+ *
+ * Created: 1998
+ * Description: Startup code for Blackfin BF537
+ *
+ * Modified:
+ * Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/blackfin.h>
+#include <asm/trace.h>
+
+#if CONFIG_BFIN_KERNEL_CLOCK
+#include <asm/mach-common/clocks.h>
+#include <asm/mach/mem_init.h>
+#endif
+
+.global __rambase
+.global __ramstart
+.global __ramend
+.extern ___bss_stop
+.extern ___bss_start
+.extern _bf53x_relocate_l1_mem
+
+#define INITIAL_STACK 0xFFB01000
+
+__INIT
+
+ENTRY(__start)
+ /* R0: argument of command line string, passed from uboot, save it */
+ R7 = R0;
+ /* Enable Cycle Counter and Nesting Of Interrupts */
+#ifdef CONFIG_BFIN_SCRATCH_REG_CYCLES
+ R0 = SYSCFG_SNEN;
+#else
+ R0 = SYSCFG_SNEN | SYSCFG_CCEN;
+#endif
+ SYSCFG = R0;
+ R0 = 0;
+
+ /* Clear Out All the data and pointer Registers */
+ R1 = R0;
+ R2 = R0;
+ R3 = R0;
+ R4 = R0;
+ R5 = R0;
+ R6 = R0;
+
+ P0 = R0;
+ P1 = R0;
+ P2 = R0;
+ P3 = R0;
+ P4 = R0;
+ P5 = R0;
+
+ LC0 = r0;
+ LC1 = r0;
+ L0 = r0;
+ L1 = r0;
+ L2 = r0;
+ L3 = r0;
+
+ /* Clear Out All the DAG Registers */
+ B0 = r0;
+ B1 = r0;
+ B2 = r0;
+ B3 = r0;
+
+ I0 = r0;
+ I1 = r0;
+ I2 = r0;
+ I3 = r0;
+
+ M0 = r0;
+ M1 = r0;
+ M2 = r0;
+ M3 = r0;
+
+ trace_buffer_init(p0,r0);
+ P0 = R1;
+ R0 = R1;
+
+ /* Turn off the icache */
+ p0.l = LO(IMEM_CONTROL);
+ p0.h = HI(IMEM_CONTROL);
+ R1 = [p0];
+ R0 = ~ENICPLB;
+ R0 = R0 & R1;
+
+ /* Anomaly 05000125 */
+#if ANOMALY_05000125
+ CLI R2;
+ SSYNC;
+#endif
+ [p0] = R0;
+ SSYNC;
+#if ANOMALY_05000125
+ STI R2;
+#endif
+
+ /* Turn off the dcache */
+ p0.l = LO(DMEM_CONTROL);
+ p0.h = HI(DMEM_CONTROL);
+ R1 = [p0];
+ R0 = ~ENDCPLB;
+ R0 = R0 & R1;
+
+ /* Anomaly 05000125 */
+#if ANOMALY_05000125
+ CLI R2;
+ SSYNC;
+#endif
+ [p0] = R0;
+ SSYNC;
+#if ANOMALY_05000125
+ STI R2;
+#endif
+
+
+#if defined(CONFIG_BF527)
+ p0.h = hi(EMAC_SYSTAT);
+ p0.l = lo(EMAC_SYSTAT);
+ R0.h = 0xFFFF; /* Clear EMAC Interrupt Status bits */
+ R0.l = 0xFFFF;
+ [P0] = R0;
+ SSYNC;
+#endif
+
+ /* Initialise UART - when booting from u-boot, the UART is not disabled
+ * so if we dont initalize here, our serial console gets hosed */
+ p0.h = hi(UART1_LCR);
+ p0.l = lo(UART1_LCR);
+ r0 = 0x0(Z);
+ w[p0] = r0.L; /* To enable DLL writes */
+ ssync;
+
+ p0.h = hi(UART1_DLL);
+ p0.l = lo(UART1_DLL);
+ r0 = 0x0(Z);
+ w[p0] = r0.L;
+ ssync;
+
+ p0.h = hi(UART1_DLH);
+ p0.l = lo(UART1_DLH);
+ r0 = 0x00(Z);
+ w[p0] = r0.L;
+ ssync;
+
+ p0.h = hi(UART1_GCTL);
+ p0.l = lo(UART1_GCTL);
+ r0 = 0x0(Z);
+ w[p0] = r0.L; /* To enable UART clock */
+ ssync;
+
+ /* Initialize stack pointer */
+ sp.l = lo(INITIAL_STACK);
+ sp.h = hi(INITIAL_STACK);
+ fp = sp;
+ usp = sp;
+
+#ifdef CONFIG_EARLY_PRINTK
+ SP += -12;
+ call _init_early_exception_vectors;
+ SP += 12;
+#endif
+
+ /* Put The Code for PLL Programming and SDRAM Programming in L1 ISRAM */
+ call _bf53x_relocate_l1_mem;
+#if CONFIG_BFIN_KERNEL_CLOCK
+ call _start_dma_code;
+#endif
+
+ /* Code for initializing Async memory banks */
+
+ p2.h = hi(EBIU_AMBCTL1);
+ p2.l = lo(EBIU_AMBCTL1);
+ r0.h = hi(AMBCTL1VAL);
+ r0.l = lo(AMBCTL1VAL);
+ [p2] = r0;
+ ssync;
+
+ p2.h = hi(EBIU_AMBCTL0);
+ p2.l = lo(EBIU_AMBCTL0);
+ r0.h = hi(AMBCTL0VAL);
+ r0.l = lo(AMBCTL0VAL);
+ [p2] = r0;
+ ssync;
+
+ p2.h = hi(EBIU_AMGCTL);
+ p2.l = lo(EBIU_AMGCTL);
+ r0 = AMGCTLVAL;
+ w[p2] = r0;
+ ssync;
+
+ /* This section keeps the processor in supervisor mode
+ * during kernel boot. Switches to user mode at end of boot.
+ * See page 3-9 of Hardware Reference manual for documentation.
+ */
+
+ /* EVT15 = _real_start */
+
+ p0.l = lo(EVT15);
+ p0.h = hi(EVT15);
+ p1.l = _real_start;
+ p1.h = _real_start;
+ [p0] = p1;
+ csync;
+
+ p0.l = lo(IMASK);
+ p0.h = hi(IMASK);
+ p1.l = IMASK_IVG15;
+ p1.h = 0x0;
+ [p0] = p1;
+ csync;
+
+ raise 15;
+ p0.l = .LWAIT_HERE;
+ p0.h = .LWAIT_HERE;
+ reti = p0;
+#if ANOMALY_05000281
+ nop; nop; nop;
+#endif
+ rti;
+
+.LWAIT_HERE:
+ jump .LWAIT_HERE;
+ENDPROC(__start)
+
+ENTRY(_real_start)
+ [ -- sp ] = reti;
+ p0.l = lo(WDOG_CTL);
+ p0.h = hi(WDOG_CTL);
+ r0 = 0xAD6(z);
+ w[p0] = r0; /* watchdog off for now */
+ ssync;
+
+ /* Code update for BSS size == 0
+ * Zero out the bss region.
+ */
+
+ p1.l = ___bss_start;
+ p1.h = ___bss_start;
+ p2.l = ___bss_stop;
+ p2.h = ___bss_stop;
+ r0 = 0;
+ p2 -= p1;
+ lsetup (.L_clear_bss, .L_clear_bss) lc0 = p2;
+.L_clear_bss:
+ B[p1++] = r0;
+
+ /* In case there is a NULL pointer reference
+ * Zero out region before stext
+ */
+
+ p1.l = 0x0;
+ p1.h = 0x0;
+ r0.l = __stext;
+ r0.h = __stext;
+ r0 = r0 >> 1;
+ p2 = r0;
+ r0 = 0;
+ lsetup (.L_clear_zero, .L_clear_zero) lc0 = p2;
+.L_clear_zero:
+ W[p1++] = r0;
+
+ /* pass the uboot arguments to the global value command line */
+ R0 = R7;
+ call _cmdline_init;
+
+ p1.l = __rambase;
+ p1.h = __rambase;
+ r0.l = __sdata;
+ r0.h = __sdata;
+ [p1] = r0;
+
+ p1.l = __ramstart;
+ p1.h = __ramstart;
+ p3.l = ___bss_stop;
+ p3.h = ___bss_stop;
+
+ r1 = p3;
+ [p1] = r1;
+
+ /*
+ * load the current thread pointer and stack
+ */
+ r1.l = _init_thread_union;
+ r1.h = _init_thread_union;
+
+ r2.l = 0x2000;
+ r2.h = 0x0000;
+ r1 = r1 + r2;
+ sp = r1;
+ usp = sp;
+ fp = sp;
+ jump.l _start_kernel;
+ENDPROC(_real_start)
+
+__FINIT
+
+.section .l1.text
+#if CONFIG_BFIN_KERNEL_CLOCK
+ENTRY(_start_dma_code)
+
+ /* Enable PHY CLK buffer output */
+ p0.h = hi(VR_CTL);
+ p0.l = lo(VR_CTL);
+ r0.l = w[p0];
+ bitset(r0, 14);
+ w[p0] = r0.l;
+ ssync;
+
+ p0.h = hi(SIC_IWR0);
+ p0.l = lo(SIC_IWR0);
+ r0.l = 0x1;
+ r0.h = 0x0;
+ [p0] = r0;
+ SSYNC;
+
+ /*
+ * Set PLL_CTL
+ * - [14:09] = MSEL[5:0] : CLKIN / VCO multiplication factors
+ * - [8] = BYPASS : BYPASS the PLL, run CLKIN into CCLK/SCLK
+ * - [7] = output delay (add 200ps of delay to mem signals)
+ * - [6] = input delay (add 200ps of input delay to mem signals)
+ * - [5] = PDWN : 1=All Clocks off
+ * - [3] = STOPCK : 1=Core Clock off
+ * - [1] = PLL_OFF : 1=Disable Power to PLL
+ * - [0] = DF : 1=Pass CLKIN/2 to PLL / 0=Pass CLKIN to PLL
+ * all other bits set to zero
+ */
+
+ p0.h = hi(PLL_LOCKCNT);
+ p0.l = lo(PLL_LOCKCNT);
+ r0 = 0x300(Z);
+ w[p0] = r0.l;
+ ssync;
+
+ P2.H = hi(EBIU_SDGCTL);
+ P2.L = lo(EBIU_SDGCTL);
+ R0 = [P2];
+ BITSET (R0, 24);
+ [P2] = R0;
+ SSYNC;
+
+ r0 = CONFIG_VCO_MULT & 63; /* Load the VCO multiplier */
+ r0 = r0 << 9; /* Shift it over, */
+ r1 = CLKIN_HALF; /* Do we need to divide CLKIN by 2?*/
+ r0 = r1 | r0;
+ r1 = PLL_BYPASS; /* Bypass the PLL? */
+ r1 = r1 << 8; /* Shift it over */
+ r0 = r1 | r0; /* add them all together */
+
+ p0.h = hi(PLL_CTL);
+ p0.l = lo(PLL_CTL); /* Load the address */
+ cli r2; /* Disable interrupts */
+ ssync;
+ w[p0] = r0.l; /* Set the value */
+ idle; /* Wait for the PLL to stablize */
+ sti r2; /* Enable interrupts */
+
+.Lcheck_again:
+ p0.h = hi(PLL_STAT);
+ p0.l = lo(PLL_STAT);
+ R0 = W[P0](Z);
+ CC = BITTST(R0,5);
+ if ! CC jump .Lcheck_again;
+
+ /* Configure SCLK & CCLK Dividers */
+ r0 = (CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV);
+ p0.h = hi(PLL_DIV);
+ p0.l = lo(PLL_DIV);
+ w[p0] = r0.l;
+ ssync;
+
+ p0.l = lo(EBIU_SDRRC);
+ p0.h = hi(EBIU_SDRRC);
+ r0 = mem_SDRRC;
+ w[p0] = r0.l;
+ ssync;
+
+ p0.l = LO(EBIU_SDBCTL);
+ p0.h = HI(EBIU_SDBCTL); /* SDRAM Memory Bank Control Register */
+ r0 = mem_SDBCTL;
+ w[p0] = r0.l;
+ ssync;
+
+ P2.H = hi(EBIU_SDGCTL);
+ P2.L = lo(EBIU_SDGCTL);
+ R0 = [P2];
+ BITCLR (R0, 24);
+ p0.h = hi(EBIU_SDSTAT);
+ p0.l = lo(EBIU_SDSTAT);
+ r2.l = w[p0];
+ cc = bittst(r2,3);
+ if !cc jump .Lskip;
+ NOP;
+ BITSET (R0, 23);
+.Lskip:
+ [P2] = R0;
+ SSYNC;
+
+ R0.L = lo(mem_SDGCTL);
+ R0.H = hi(mem_SDGCTL);
+ R1 = [p2];
+ R1 = R1 | R0;
+ [P2] = R1;
+ SSYNC;
+
+ p0.h = hi(SIC_IWR0);
+ p0.l = lo(SIC_IWR0);
+ r0.l = lo(IWR_ENABLE_ALL);
+ r0.h = hi(IWR_ENABLE_ALL);
+ [p0] = r0;
+ SSYNC;
+
+ RTS;
+ENDPROC(_start_dma_code)
+#endif /* CONFIG_BFIN_KERNEL_CLOCK */
+
+.data
+
+/*
+ * Set up the usable of RAM stuff. Size of RAM is determined then
+ * an initial stack set up at the end.
+ */
+
+.align 4
+__rambase:
+.long 0
+__ramstart:
+.long 0
+__ramend:
+.long 0
diff --git a/arch/blackfin/mach-bf527/ints-priority.c b/arch/blackfin/mach-bf527/ints-priority.c
new file mode 100644
index 000000000000..1fa389793968
--- /dev/null
+++ b/arch/blackfin/mach-bf527/ints-priority.c
@@ -0,0 +1,100 @@
+/*
+ * File: arch/blackfin/mach-bf537/ints-priority.c
+ * Based on: arch/blackfin/mach-bf533/ints-priority.c
+ * Author: Michael Hennerich (michael.hennerich@analog.com)
+ *
+ * Created:
+ * Description: Set up the interrupt priorities
+ *
+ * Modified:
+ * Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/module.h>
+#include <linux/irq.h>
+#include <asm/blackfin.h>
+
+void program_IAR(void)
+{
+ /* Program the IAR0 Register with the configured priority */
+ bfin_write_SIC_IAR0(((CONFIG_IRQ_PLL_WAKEUP - 7) << IRQ_PLL_WAKEUP_POS) |
+ ((CONFIG_IRQ_DMA0_ERROR - 7) << IRQ_DMA0_ERROR_POS) |
+ ((CONFIG_IRQ_DMAR0_BLK - 7) << IRQ_DMAR0_BLK_POS) |
+ ((CONFIG_IRQ_DMAR1_BLK - 7) << IRQ_DMAR1_BLK_POS) |
+ ((CONFIG_IRQ_DMAR0_OVR - 7) << IRQ_DMAR0_OVR_POS) |
+ ((CONFIG_IRQ_DMAR1_OVR - 7) << IRQ_DMAR1_OVR_POS) |
+ ((CONFIG_IRQ_PPI_ERROR - 7) << IRQ_PPI_ERROR_POS) |
+ ((CONFIG_IRQ_MAC_ERROR - 7) << IRQ_MAC_ERROR_POS));
+
+
+ bfin_write_SIC_IAR1(((CONFIG_IRQ_SPORT0_ERROR - 7) << IRQ_SPORT0_ERROR_POS) |
+ ((CONFIG_IRQ_SPORT1_ERROR - 7) << IRQ_SPORT1_ERROR_POS) |
+ ((CONFIG_IRQ_UART0_ERROR - 7) << IRQ_UART0_ERROR_POS) |
+ ((CONFIG_IRQ_UART1_ERROR - 7) << IRQ_UART1_ERROR_POS) |
+ ((CONFIG_IRQ_RTC - 7) << IRQ_RTC_POS) |
+ ((CONFIG_IRQ_PPI - 7) << IRQ_PPI_POS));
+
+ bfin_write_SIC_IAR2(((CONFIG_IRQ_SPORT0_RX - 7) << IRQ_SPORT0_RX_POS) |
+ ((CONFIG_IRQ_SPORT0_TX - 7) << IRQ_SPORT0_TX_POS) |
+ ((CONFIG_IRQ_SPORT1_RX - 7) << IRQ_SPORT1_RX_POS) |
+ ((CONFIG_IRQ_SPORT1_TX - 7) << IRQ_SPORT1_TX_POS) |
+ ((CONFIG_IRQ_TWI - 7) << IRQ_TWI_POS) |
+ ((CONFIG_IRQ_SPI - 7) << IRQ_SPI_POS) |
+ ((CONFIG_IRQ_UART0_RX - 7) << IRQ_UART0_RX_POS) |
+ ((CONFIG_IRQ_UART0_TX - 7) << IRQ_UART0_TX_POS));
+
+ bfin_write_SIC_IAR3(((CONFIG_IRQ_UART1_RX - 7) << IRQ_UART1_RX_POS) |
+ ((CONFIG_IRQ_UART1_TX - 7) << IRQ_UART1_TX_POS) |
+ ((CONFIG_IRQ_OPTSEC - 7) << IRQ_OPTSEC_POS) |
+ ((CONFIG_IRQ_CNT - 7) << IRQ_CNT_POS) |
+ ((CONFIG_IRQ_MAC_RX - 7) << IRQ_MAC_RX_POS) |
+ ((CONFIG_IRQ_PORTH_INTA - 7) << IRQ_PORTH_INTA_POS) |
+ ((CONFIG_IRQ_MAC_TX - 7) << IRQ_MAC_TX_POS) |
+ ((CONFIG_IRQ_PORTH_INTB - 7) << IRQ_PORTH_INTB_POS));
+
+ bfin_write_SIC_IAR4(((CONFIG_IRQ_TMR0 - 7) << IRQ_TMR0_POS) |
+ ((CONFIG_IRQ_TMR1 - 7) << IRQ_TMR1_POS) |
+ ((CONFIG_IRQ_TMR2 - 7) << IRQ_TMR2_POS) |
+ ((CONFIG_IRQ_TMR3 - 7) << IRQ_TMR3_POS) |
+ ((CONFIG_IRQ_TMR4 - 7) << IRQ_TMR4_POS) |
+ ((CONFIG_IRQ_TMR5 - 7) << IRQ_TMR5_POS) |
+ ((CONFIG_IRQ_TMR6 - 7) << IRQ_TMR6_POS) |
+ ((CONFIG_IRQ_TMR7 - 7) << IRQ_TMR7_POS));
+
+ bfin_write_SIC_IAR5(((CONFIG_IRQ_PORTG_INTA - 7) << IRQ_PORTG_INTA_POS) |
+ ((CONFIG_IRQ_PORTG_INTB - 7) << IRQ_PORTG_INTB_POS) |
+ ((CONFIG_IRQ_MEM_DMA0 - 7) << IRQ_MEM_DMA0_POS) |
+ ((CONFIG_IRQ_MEM_DMA1 - 7) << IRQ_MEM_DMA1_POS) |
+ ((CONFIG_IRQ_WATCH - 7) << IRQ_WATCH_POS) |
+ ((CONFIG_IRQ_PORTF_INTA - 7) << IRQ_PORTF_INTA_POS) |
+ ((CONFIG_IRQ_PORTF_INTB - 7) << IRQ_PORTF_INTB_POS) |
+ ((CONFIG_IRQ_SPI_ERROR - 7) << IRQ_SPI_ERROR_POS));
+
+ bfin_write_SIC_IAR6(((CONFIG_IRQ_NFC_ERROR - 7) << IRQ_NFC_ERROR_POS) |
+ ((CONFIG_IRQ_HDMA_ERROR - 7) << IRQ_HDMA_ERROR_POS) |
+ ((CONFIG_IRQ_HDMA - 7) << IRQ_HDMA_POS) |
+ ((CONFIG_IRQ_USB_EINT - 7) << IRQ_USB_EINT_POS) |
+ ((CONFIG_IRQ_USB_INT0 - 7) << IRQ_USB_INT0_POS) |
+ ((CONFIG_IRQ_USB_INT1 - 7) << IRQ_USB_INT1_POS) |
+ ((CONFIG_IRQ_USB_INT2 - 7) << IRQ_USB_INT2_POS) |
+ ((CONFIG_IRQ_USB_DMA - 7) << IRQ_USB_DMA_POS));
+
+ SSYNC();
+}
diff --git a/arch/blackfin/mach-bf533/boards/H8606.c b/arch/blackfin/mach-bf533/boards/H8606.c
new file mode 100644
index 000000000000..b941550f9568
--- /dev/null
+++ b/arch/blackfin/mach-bf533/boards/H8606.c
@@ -0,0 +1,345 @@
+/*
+ * File: arch/blackfin/mach-bf533/H8606.c
+ * Based on: arch/blackfin/mach-bf533/stamp.c
+ * Author: Javier Herrero <jherrero@hvsistemas.es>
+ *
+ * Created: 2007
+ * Description: Board Info File for the HV Sistemas H8606 board
+ *
+ * Modified:
+ * Copyright 2005 National ICT Australia (NICTA)
+ * Copyright 2004-2006 Analog Devices Inc
+ * Copyright 2007 HV Sistemas S.L.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
+#include <linux/usb_isp1362.h>
+#endif
+#include <linux/pata_platform.h>
+#include <linux/irq.h>
+#include <asm/dma.h>
+#include <asm/bfin5xx_spi.h>
+#include <asm/reboot.h>
+
+/*
+ * Name the Board for the /proc/cpuinfo
+ */
+const char bfin_board_name[] = "HV Sistemas H8606";
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_BFIN_MODULE)
+static struct platform_device rtc_device = {
+ .name = "rtc-bfin",
+ .id = -1,
+};
+#endif
+
+/*
+* Driver needs to know address, irq and flag pin.
+ */
+ #if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
+static struct resource dm9000_resources[] = {
+ [0] = {
+ .start = 0x20300000,
+ .end = 0x20300000 + 8,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_PF10,
+ .end = IRQ_PF10,
+ .flags = (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE),
+ },
+};
+
+static struct platform_device dm9000_device = {
+ .id = 0,
+ .name = "dm9000",
+ .resource = dm9000_resources,
+ .num_resources = ARRAY_SIZE(dm9000_resources),
+};
+#endif
+
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+static struct resource smc91x_resources[] = {
+ {
+ .name = "smc91x-regs",
+ .start = 0x20300300,
+ .end = 0x20300300 + 16,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_PROG_INTB,
+ .end = IRQ_PROG_INTB,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+ }, {
+ /*
+ * denotes the flag pin and is used directly if
+ * CONFIG_IRQCHIP_DEMUX_GPIO is defined.
+ */
+ .start = IRQ_PF7,
+ .end = IRQ_PF7,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+ },
+};
+
+static struct platform_device smc91x_device = {
+ .name = "smc91x",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(smc91x_resources),
+ .resource = smc91x_resources,
+};
+#endif
+
+#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
+static struct resource net2272_bfin_resources[] = {
+ {
+ .start = 0x20300000,
+ .end = 0x20300000 + 0x100,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_PF10,
+ .end = IRQ_PF10,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+ },
+};
+
+static struct platform_device net2272_bfin_device = {
+ .name = "net2272",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(net2272_bfin_resources),
+ .resource = net2272_bfin_resources,
+};
+#endif
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+/* all SPI peripherals info goes here */
+
+#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
+static struct mtd_partition bfin_spi_flash_partitions[] = {
+ {
+ .name = "bootloader",
+ .size = 0x00060000,
+ .offset = 0,
+ .mask_flags = MTD_CAP_ROM
+ }, {
+ .name = "kernel",
+ .size = 0x100000,
+ .offset = 0x60000
+ }, {
+ .name = "file system",
+ .size = 0x6a0000,
+ .offset = 0x00160000,
+ }
+};
+
+static struct flash_platform_data bfin_spi_flash_data = {
+ .name = "m25p80",
+ .parts = bfin_spi_flash_partitions,
+ .nr_parts = ARRAY_SIZE(bfin_spi_flash_partitions),
+ .type = "m25p64",
+};
+
+/* SPI flash chip (m25p64) */
+static struct bfin5xx_spi_chip spi_flash_chip_info = {
+ .enable_dma = 0, /* use dma transfer with this chip*/
+ .bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_SPI_ADC_BF533) || defined(CONFIG_SPI_ADC_BF533_MODULE)
+/* SPI ADC chip */
+static struct bfin5xx_spi_chip spi_adc_chip_info = {
+ .ctl_reg = 0x1000,
+ .enable_dma = 1, /* use dma transfer with this chip*/
+ .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_SND_BLACKFIN_AD1836) || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
+static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
+ .ctl_reg = 0x1000,
+ .enable_dma = 0,
+ .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_PBX)
+static struct bfin5xx_spi_chip spi_si3xxx_chip_info = {
+ .ctl_reg = 0x1c04,
+ .enable_dma = 0,
+ .bits_per_word = 8,
+ .cs_change_per_word = 1,
+};
+#endif
+
+/* Notice: for blackfin, the speed_hz is the value of register
+ * SPI_BAUD, not the real baudrate */
+static struct spi_board_info bfin_spi_board_info[] __initdata = {
+#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
+ {
+ /* the modalias must be the same as spi device driver name */
+ .modalias = "m25p80", /* Name of spi_driver for this device */
+ /* this value is the baudrate divisor */
+ .max_speed_hz = 50000000, /* actual baudrate is SCLK/(2xspeed_hz) */
+ .bus_num = 0, /* Framework bus number */
+ .chip_select = 2, /* Framework chip select. On STAMP537 it is SPISSEL2*/
+ .platform_data = &bfin_spi_flash_data,
+ .controller_data = &spi_flash_chip_info,
+ .mode = SPI_MODE_3,
+ },
+#endif
+
+#if defined(CONFIG_SPI_ADC_BF533) || defined(CONFIG_SPI_ADC_BF533_MODULE)
+ {
+ .modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
+ .max_speed_hz = 4, /* actual baudrate is SCLK/(2xspeed_hz) */
+ .bus_num = 1, /* Framework bus number */
+ .chip_select = 1, /* Framework chip select. */
+ .platform_data = NULL, /* No spi_driver specific config */
+ .controller_data = &spi_adc_chip_info,
+ },
+#endif
+
+#if defined(CONFIG_SND_BLACKFIN_AD1836) || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
+ {
+ .modalias = "ad1836-spi",
+ .max_speed_hz = 16,
+ .bus_num = 1,
+ .chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+ .controller_data = &ad1836_spi_chip_info,
+ },
+#endif
+
+#if defined(CONFIG_PBX)
+ {
+ .modalias = "fxs-spi",
+ .max_speed_hz = 4,
+ .bus_num = 1,
+ .chip_select = 3,
+ .controller_data = &spi_si3xxx_chip_info,
+ },
+
+ {
+ .modalias = "fxo-spi",
+ .max_speed_hz = 4,
+ .bus_num = 1,
+ .chip_select = 2,
+ .controller_data = &spi_si3xxx_chip_info,
+ },
+#endif
+};
+
+/* SPI (0) */
+static struct resource bfin_spi0_resource[] = {
+ [0] = {
+ .start = SPI0_REGBASE,
+ .end = SPI0_REGBASE + 0xFF,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = CH_SPI,
+ .end = CH_SPI,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+
+/* SPI controller data */
+static struct bfin5xx_spi_master bfin_spi0_info = {
+ .num_chipselect = 8,
+ .enable_dma = 1, /* master has the ability to do dma transfer */
+};
+
+static struct platform_device bfin_spi0_device = {
+ .name = "bfin-spi",
+ .id = 0, /* Bus number */
+ .num_resources = ARRAY_SIZE(bfin_spi0_resource),
+ .resource = bfin_spi0_resource,
+ .dev = {
+ .platform_data = &bfin_spi0_info, /* Passed to driver */
+ },
+};
+#endif /* spi master and devices */
+
+#if defined(CONFIG_FB_BF537_LQ035) || defined(CONFIG_FB_BF537_LQ035_MODULE)
+static struct platform_device bfin_fb_device = {
+ .name = "bf537-fb",
+};
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+static struct resource bfin_uart_resources[] = {
+ {
+ .start = 0xFFC00400,
+ .end = 0xFFC004FF,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device bfin_uart_device = {
+ .name = "bfin-uart",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(bfin_uart_resources),
+ .resource = bfin_uart_resources,
+};
+#endif
+
+static struct platform_device *stamp_devices[] __initdata = {
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+ &rtc_device,
+#endif
+
+#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
+ &dm9000_device,
+#endif
+
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+ &smc91x_device,
+#endif
+
+#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
+ &net2272_bfin_device,
+#endif
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ &bfin_spi0_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+ &bfin_uart_device,
+#endif
+};
+
+static int __init H8606_init(void)
+{
+ printk(KERN_INFO "HV Sistemas H8606 board support by http://www.hvsistemas.com\n");
+ printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+ platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
+#endif
+ return 0;
+}
+
+arch_initcall(H8606_init); \ No newline at end of file
diff --git a/arch/blackfin/mach-bf533/boards/Makefile b/arch/blackfin/mach-bf533/boards/Makefile
index 12a631ab389d..2452b456ccbd 100644
--- a/arch/blackfin/mach-bf533/boards/Makefile
+++ b/arch/blackfin/mach-bf533/boards/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_GENERIC_BOARD) += generic_board.o
obj-$(CONFIG_BFIN533_STAMP) += stamp.o
obj-$(CONFIG_BFIN533_EZKIT) += ezkit.o
obj-$(CONFIG_BFIN533_BLUETECHNIX_CM) += cm_bf533.o
+obj-$(CONFIG_H8606_HVSISTEMAS) += H8606.o
diff --git a/arch/blackfin/mach-bf533/boards/cm_bf533.c b/arch/blackfin/mach-bf533/boards/cm_bf533.c
index a57b52d207cd..a863522a4467 100644
--- a/arch/blackfin/mach-bf533/boards/cm_bf533.c
+++ b/arch/blackfin/mach-bf533/boards/cm_bf533.c
@@ -42,11 +42,11 @@
/*
* Name the Board for the /proc/cpuinfo
*/
-char *bfin_board_name = "Bluetechnix CM BF533";
+const char bfin_board_name[] = "Bluetechnix CM BF533";
#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
/* all SPI peripherals info goes here */
-
+#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
static struct mtd_partition bfin_spi_flash_partitions[] = {
{
.name = "bootloader",
@@ -76,12 +76,15 @@ static struct bfin5xx_spi_chip spi_flash_chip_info = {
.enable_dma = 0, /* use dma transfer with this chip*/
.bits_per_word = 8,
};
+#endif
/* SPI ADC chip */
+#if defined(CONFIG_SPI_ADC_BF533) || defined(CONFIG_SPI_ADC_BF533_MODULE)
static struct bfin5xx_spi_chip spi_adc_chip_info = {
.enable_dma = 1, /* use dma transfer with this chip*/
.bits_per_word = 16,
};
+#endif
#if defined(CONFIG_SND_BLACKFIN_AD1836) || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
@@ -90,7 +93,15 @@ static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
};
#endif
+#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
+static struct bfin5xx_spi_chip spi_mmc_chip_info = {
+ .enable_dma = 1,
+ .bits_per_word = 8,
+};
+#endif
+
static struct spi_board_info bfin_spi_board_info[] __initdata = {
+#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
{
/* the modalias must be the same as spi device driver name */
.modalias = "m25p80", /* Name of spi_driver for this device */
@@ -100,7 +111,11 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.platform_data = &bfin_spi_flash_data,
.controller_data = &spi_flash_chip_info,
.mode = SPI_MODE_3,
- }, {
+ },
+#endif
+
+#if defined(CONFIG_SPI_ADC_BF533) || defined(CONFIG_SPI_ADC_BF533_MODULE)
+ {
.modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
.max_speed_hz = 6250000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0, /* Framework bus number */
@@ -108,6 +123,8 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.platform_data = NULL, /* No spi_driver specific config */
.controller_data = &spi_adc_chip_info,
},
+#endif
+
#if defined(CONFIG_SND_BLACKFIN_AD1836) || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
{
.modalias = "ad1836-spi",
@@ -117,6 +134,27 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.controller_data = &ad1836_spi_chip_info,
},
#endif
+
+#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
+ {
+ .modalias = "spi_mmc_dummy",
+ .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 0,
+ .platform_data = NULL,
+ .controller_data = &spi_mmc_chip_info,
+ .mode = SPI_MODE_3,
+ },
+ {
+ .modalias = "spi_mmc",
+ .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = CONFIG_SPI_MMC_CS_CHAN,
+ .platform_data = NULL,
+ .controller_data = &spi_mmc_chip_info,
+ .mode = SPI_MODE_3,
+ },
+#endif
};
/* SPI (0) */
diff --git a/arch/blackfin/mach-bf533/boards/ezkit.c b/arch/blackfin/mach-bf533/boards/ezkit.c
index 5c1e35d3c012..34b63920e272 100644
--- a/arch/blackfin/mach-bf533/boards/ezkit.c
+++ b/arch/blackfin/mach-bf533/boards/ezkit.c
@@ -43,7 +43,7 @@
/*
* Name the Board for the /proc/cpuinfo
*/
-char *bfin_board_name = "ADDS-BF533-EZKIT";
+const char bfin_board_name[] = "ADDS-BF533-EZKIT";
#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
static struct platform_device rtc_device = {
diff --git a/arch/blackfin/mach-bf533/boards/generic_board.c b/arch/blackfin/mach-bf533/boards/generic_board.c
index 9bc1f0d0ab50..310b7772c458 100644
--- a/arch/blackfin/mach-bf533/boards/generic_board.c
+++ b/arch/blackfin/mach-bf533/boards/generic_board.c
@@ -35,7 +35,7 @@
/*
* Name the Board for the /proc/cpuinfo
*/
-char *bfin_board_name = "UNKNOWN BOARD";
+const char bfin_board_name[] = "UNKNOWN BOARD";
#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
static struct platform_device rtc_device = {
diff --git a/arch/blackfin/mach-bf533/boards/stamp.c b/arch/blackfin/mach-bf533/boards/stamp.c
index 8975e06ea158..62ffa500420f 100644
--- a/arch/blackfin/mach-bf533/boards/stamp.c
+++ b/arch/blackfin/mach-bf533/boards/stamp.c
@@ -46,7 +46,7 @@
/*
* Name the Board for the /proc/cpuinfo
*/
-char *bfin_board_name = "ADDS-BF533-STAMP";
+const char bfin_board_name[] = "ADDS-BF533-STAMP";
#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
static struct platform_device rtc_device = {
@@ -218,7 +218,7 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
{
.modalias = "spi_mmc_dummy",
- .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */
+ .max_speed_hz = 20000000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 0,
.platform_data = NULL,
@@ -227,7 +227,7 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
},
{
.modalias = "spi_mmc",
- .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */
+ .max_speed_hz = 20000000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = CONFIG_SPI_MMC_CS_CHAN,
.platform_data = NULL,
diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537.c b/arch/blackfin/mach-bf537/boards/cm_bf537.c
index 44dea05e1d03..2915931045e3 100644
--- a/arch/blackfin/mach-bf537/boards/cm_bf537.c
+++ b/arch/blackfin/mach-bf537/boards/cm_bf537.c
@@ -43,7 +43,7 @@
/*
* Name the Board for the /proc/cpuinfo
*/
-char *bfin_board_name = "Bluetechnix CM BF537";
+const char bfin_board_name[] = "Bluetechnix CM BF537";
#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
/* all SPI peripherals info goes here */
@@ -281,8 +281,8 @@ static struct resource net2272_bfin_resources[] = {
.end = 0x20200000 + 0x100,
.flags = IORESOURCE_MEM,
}, {
- .start = IRQ_PF7,
- .end = IRQ_PF7,
+ .start = IRQ_PH14,
+ .end = IRQ_PH14,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
},
};
diff --git a/arch/blackfin/mach-bf537/boards/generic_board.c b/arch/blackfin/mach-bf537/boards/generic_board.c
index 6668c8e4a3fc..255da7a98481 100644
--- a/arch/blackfin/mach-bf537/boards/generic_board.c
+++ b/arch/blackfin/mach-bf537/boards/generic_board.c
@@ -49,7 +49,7 @@
/*
* Name the Board for the /proc/cpuinfo
*/
-char *bfin_board_name = "GENERIC Board";
+const char bfin_board_name[] = "GENERIC Board";
/*
* Driver needs to know address, irq and flag pin.
diff --git a/arch/blackfin/mach-bf537/boards/pnav10.c b/arch/blackfin/mach-bf537/boards/pnav10.c
index f83a2544004d..87b808926789 100644
--- a/arch/blackfin/mach-bf537/boards/pnav10.c
+++ b/arch/blackfin/mach-bf537/boards/pnav10.c
@@ -47,7 +47,7 @@
/*
* Name the Board for the /proc/cpuinfo
*/
-char *bfin_board_name = "PNAV-1.0";
+const char bfin_board_name[] = "PNAV-1.0";
/*
* Driver needs to know address, irq and flag pin.
diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c
index f42ba3aa86d7..5f7b91fbafe8 100644
--- a/arch/blackfin/mach-bf537/boards/stamp.c
+++ b/arch/blackfin/mach-bf537/boards/stamp.c
@@ -49,7 +49,7 @@
/*
* Name the Board for the /proc/cpuinfo
*/
-char *bfin_board_name = "ADDS-BF537-STAMP";
+const char bfin_board_name[] = "ADDS-BF537-STAMP";
/*
* Driver needs to know address, irq and flag pin.
@@ -450,7 +450,7 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
{
.modalias = "spi_mmc_dummy",
- .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */
+ .max_speed_hz = 20000000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 0,
.platform_data = NULL,
@@ -459,7 +459,7 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
},
{
.modalias = "spi_mmc",
- .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */
+ .max_speed_hz = 20000000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = CONFIG_SPI_MMC_CS_CHAN,
.platform_data = NULL,
@@ -612,7 +612,7 @@ static struct platform_device bfin_sport1_uart_device = {
static struct pata_platform_info bfin_pata_platform_data = {
.ioport_shift = 1,
- .irq_type = IRQF_TRIGGER_HIGH | IRQF_DISABLED,
+ .irq_flags = IRQF_TRIGGER_HIGH | IRQF_DISABLED,
};
static struct resource bfin_pata_resources[] = {
diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c
index 2c47db494f7d..6b6490e66b30 100644
--- a/arch/blackfin/mach-bf548/boards/ezkit.c
+++ b/arch/blackfin/mach-bf548/boards/ezkit.c
@@ -49,7 +49,7 @@
/*
* Name the Board for the /proc/cpuinfo
*/
-char *bfin_board_name = "ADSP-BF548-EZKIT";
+const char bfin_board_name[] = "ADSP-BF548-EZKIT";
/*
* Driver needs to know address, irq and flag pin.
@@ -88,7 +88,7 @@ static struct platform_device bf54x_lq043_device = {
#endif
#if defined(CONFIG_KEYBOARD_BFIN) || defined(CONFIG_KEYBOARD_BFIN_MODULE)
-static int bf548_keymap[] = {
+static const unsigned int bf548_keymap[] = {
KEYVAL(0, 0, KEY_ENTER),
KEYVAL(0, 1, KEY_HELP),
KEYVAL(0, 2, KEY_0),
@@ -110,8 +110,8 @@ static int bf548_keymap[] = {
static struct bfin_kpad_platform_data bf54x_kpad_data = {
.rows = 4,
.cols = 4,
- .keymap = bf548_keymap,
- .keymapsize = ARRAY_SIZE(bf548_keymap),
+ .keymap = bf548_keymap,
+ .keymapsize = ARRAY_SIZE(bf548_keymap),
.repeat = 0,
.debounce_time = 5000, /* ns (5ms) */
.coldrive_time = 1000, /* ns (1ms) */
@@ -560,7 +560,7 @@ static struct platform_device *ezkit_devices[] __initdata = {
#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
&bf54x_spi_master0,
-/* &bf54x_spi_master1,*/
+ &bf54x_spi_master1,
#endif
#if defined(CONFIG_KEYBOARD_BFIN) || defined(CONFIG_KEYBOARD_BFIN_MODULE)
diff --git a/arch/blackfin/mach-bf548/dma.c b/arch/blackfin/mach-bf548/dma.c
index a8184113be48..957bf1366eff 100644
--- a/arch/blackfin/mach-bf548/dma.c
+++ b/arch/blackfin/mach-bf548/dma.c
@@ -64,6 +64,7 @@
(struct dma_register *) MDMA_D3_NEXT_DESC_PTR,
(struct dma_register *) MDMA_S3_NEXT_DESC_PTR,
};
+EXPORT_SYMBOL(base_addr);
int channel2irq(unsigned int channel)
{
diff --git a/arch/blackfin/mach-bf561/boards/cm_bf561.c b/arch/blackfin/mach-bf561/boards/cm_bf561.c
index cd827a1b6ba1..97aeb43fd8b4 100644
--- a/arch/blackfin/mach-bf561/boards/cm_bf561.c
+++ b/arch/blackfin/mach-bf561/boards/cm_bf561.c
@@ -42,7 +42,7 @@
/*
* Name the Board for the /proc/cpuinfo
*/
-char *bfin_board_name = "Bluetechnix CM BF561";
+const char bfin_board_name[] = "Bluetechnix CM BF561";
#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
/* all SPI peripherals info goes here */
diff --git a/arch/blackfin/mach-bf561/boards/ezkit.c b/arch/blackfin/mach-bf561/boards/ezkit.c
index 57e14edca8b1..059d516cec23 100644
--- a/arch/blackfin/mach-bf561/boards/ezkit.c
+++ b/arch/blackfin/mach-bf561/boards/ezkit.c
@@ -39,7 +39,7 @@
/*
* Name the Board for the /proc/cpuinfo
*/
-char *bfin_board_name = "ADDS-BF561-EZKIT";
+const char bfin_board_name[] = "ADDS-BF561-EZKIT";
#define ISP1761_BASE 0x2C0F0000
#define ISP1761_IRQ IRQ_PF10
diff --git a/arch/blackfin/mach-bf561/boards/generic_board.c b/arch/blackfin/mach-bf561/boards/generic_board.c
index 4dfea5da674c..46816be4b2ba 100644
--- a/arch/blackfin/mach-bf561/boards/generic_board.c
+++ b/arch/blackfin/mach-bf561/boards/generic_board.c
@@ -32,7 +32,7 @@
#include <linux/platform_device.h>
#include <linux/irq.h>
-char *bfin_board_name = "UNKNOWN BOARD";
+const char bfin_board_name[] = "UNKNOWN BOARD";
/*
* Driver needs to know address, irq and flag pin.
diff --git a/arch/blackfin/mach-bf561/boards/tepla.c b/arch/blackfin/mach-bf561/boards/tepla.c
index c442eb23db5e..4a17c6da2a59 100644
--- a/arch/blackfin/mach-bf561/boards/tepla.c
+++ b/arch/blackfin/mach-bf561/boards/tepla.c
@@ -16,7 +16,7 @@
#include <linux/platform_device.h>
#include <linux/irq.h>
-char *bfin_board_name = "Tepla-BF561";
+const char bfin_board_name[] = "Tepla-BF561";
/*
* Driver needs to know address, irq and flag pin.
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
index e3ad5802868a..1b13fa470977 100644
--- a/arch/blackfin/mach-common/entry.S
+++ b/arch/blackfin/mach-common/entry.S
@@ -917,7 +917,7 @@ ENTRY(_ex_table)
.long _ex_soft_bp /* 0x01 - User Defined - Software breakpoint */
.long _ex_replaceable /* 0x02 - User Defined */
.long _ex_trap_c /* 0x03 - User Defined - userspace stack overflow */
- .long _ex_replaceable /* 0x04 - User Defined */
+ .long _ex_trap_c /* 0x04 - User Defined - dump trace buffer */
.long _ex_replaceable /* 0x05 - User Defined */
.long _ex_replaceable /* 0x06 - User Defined */
.long _ex_replaceable /* 0x07 - User Defined */
diff --git a/arch/blackfin/mach-common/ints-priority-dc.c b/arch/blackfin/mach-common/ints-priority-dc.c
index 2db3546fc874..c2f05fabedc1 100644
--- a/arch/blackfin/mach-common/ints-priority-dc.c
+++ b/arch/blackfin/mach-common/ints-priority-dc.c
@@ -52,7 +52,13 @@
* -
*/
-unsigned long irq_flags = 0;
+/* Initialize this to an actual value to force it into the .data
+ * section so that we know it is properly initialized at entry into
+ * the kernel but before bss is initialized to zero (which is where
+ * it would live otherwise). The 0x1f magic represents the IRQs we
+ * cannot actually mask out in hardware.
+ */
+unsigned long irq_flags = 0x1f;
/* The number of spurious interrupts */
atomic_t num_spurious;
diff --git a/arch/blackfin/mach-common/ints-priority-sc.c b/arch/blackfin/mach-common/ints-priority-sc.c
index d3b7672b2b94..2d2b63567b30 100644
--- a/arch/blackfin/mach-common/ints-priority-sc.c
+++ b/arch/blackfin/mach-common/ints-priority-sc.c
@@ -58,7 +58,13 @@
* -
*/
-unsigned long irq_flags = 0;
+/* Initialize this to an actual value to force it into the .data
+ * section so that we know it is properly initialized at entry into
+ * the kernel but before bss is initialized to zero (which is where
+ * it would live otherwise). The 0x1f magic represents the IRQs we
+ * cannot actually mask out in hardware.
+ */
+unsigned long irq_flags = 0x1f;
/* The number of spurious interrupts */
atomic_t num_spurious;
@@ -92,10 +98,15 @@ static void __init search_IAR(void)
for (irqn = 0; irqn < NR_PERI_INTS; irqn++) {
int iar_shift = (irqn & 7) * 4;
- if (ivg ==
+ if (ivg ==
(0xf &
+#ifndef CONFIG_BF52x
bfin_read32((unsigned long *)SIC_IAR0 +
(irqn >> 3)) >> iar_shift)) {
+#else
+ bfin_read32((unsigned long *)SIC_IAR0 +
+ ((irqn%32) >> 3) + ((irqn / 32) * 16)) >> iar_shift)) {
+#endif
ivg_table[irq_pos].irqno = IVG7 + irqn;
ivg_table[irq_pos].isrflag = 1 << (irqn % 32);
ivg7_13[ivg].istop++;
@@ -140,7 +151,7 @@ static void bfin_core_unmask_irq(unsigned int irq)
static void bfin_internal_mask_irq(unsigned int irq)
{
-#ifndef CONFIG_BF54x
+#ifdef CONFIG_BF53x
bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() &
~(1 << (irq - (IRQ_CORETMR + 1))));
#else
@@ -155,7 +166,7 @@ static void bfin_internal_mask_irq(unsigned int irq)
static void bfin_internal_unmask_irq(unsigned int irq)
{
-#ifndef CONFIG_BF54x
+#ifdef CONFIG_BF53x
bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() |
(1 << (irq - (IRQ_CORETMR + 1))));
#else
@@ -750,13 +761,15 @@ int __init init_arch_irq(void)
int irq;
unsigned long ilat = 0;
/* Disable all the peripheral intrs - page 4-29 HW Ref manual */
-#ifdef CONFIG_BF54x
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x)
bfin_write_SIC_IMASK0(SIC_UNMASK_ALL);
bfin_write_SIC_IMASK1(SIC_UNMASK_ALL);
- bfin_write_SIC_IMASK2(SIC_UNMASK_ALL);
bfin_write_SIC_IWR0(IWR_ENABLE_ALL);
bfin_write_SIC_IWR1(IWR_ENABLE_ALL);
+#ifdef CONFIG_BF54x
+ bfin_write_SIC_IMASK2(SIC_UNMASK_ALL);
bfin_write_SIC_IWR2(IWR_ENABLE_ALL);
+#endif
#else
bfin_write_SIC_IMASK(SIC_UNMASK_ALL);
bfin_write_SIC_IWR(IWR_ENABLE_ALL);
@@ -787,7 +800,7 @@ int __init init_arch_irq(void)
switch (irq) {
#ifdef CONFIG_IRQCHIP_DEMUX_GPIO
-#ifndef CONFIG_BF54x
+#if defined(CONFIG_BF53x)
case IRQ_PROG_INTA:
set_irq_chained_handler(irq,
bfin_demux_gpio_irq);
@@ -798,7 +811,7 @@ int __init init_arch_irq(void)
bfin_demux_gpio_irq);
break;
#endif
-#else
+#elif defined(CONFIG_BF54x)
case IRQ_PINT0:
set_irq_chained_handler(irq,
bfin_demux_gpio_irq);
@@ -815,7 +828,20 @@ int __init init_arch_irq(void)
set_irq_chained_handler(irq,
bfin_demux_gpio_irq);
break;
-#endif /*CONFIG_BF54x */
+#elif defined(CONFIG_BF52x)
+ case IRQ_PORTF_INTA:
+ set_irq_chained_handler(irq,
+ bfin_demux_gpio_irq);
+ break;
+ case IRQ_PORTG_INTA:
+ set_irq_chained_handler(irq,
+ bfin_demux_gpio_irq);
+ break;
+ case IRQ_PORTH_INTA:
+ set_irq_chained_handler(irq,
+ bfin_demux_gpio_irq);
+ break;
+#endif
#endif
default:
set_irq_handler(irq, handle_simple_irq);
@@ -880,14 +906,15 @@ void do_irq(int vec, struct pt_regs *fp)
} else {
struct ivgx *ivg = ivg7_13[vec - IVG7].ifirst;
struct ivgx *ivg_stop = ivg7_13[vec - IVG7].istop;
-#ifdef CONFIG_BF54x
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x)
unsigned long sic_status[3];
SSYNC();
- sic_status[0] = bfin_read_SIC_ISR(0) & bfin_read_SIC_IMASK(0);
- sic_status[1] = bfin_read_SIC_ISR(1) & bfin_read_SIC_IMASK(1);
- sic_status[2] = bfin_read_SIC_ISR(2) & bfin_read_SIC_IMASK(2);
-
+ sic_status[0] = bfin_read_SIC_ISR0() & bfin_read_SIC_IMASK0();
+ sic_status[1] = bfin_read_SIC_ISR1() & bfin_read_SIC_IMASK1();
+#ifdef CONFIG_BF54x
+ sic_status[2] = bfin_read_SIC_ISR2() & bfin_read_SIC_IMASK2();
+#endif
for (;; ivg++) {
if (ivg >= ivg_stop) {
atomic_inc(&num_spurious);
diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c
index b10302722202..dac51fb06f22 100644
--- a/arch/blackfin/mach-common/pm.c
+++ b/arch/blackfin/mach-common/pm.c
@@ -32,7 +32,7 @@
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include <linux/pm.h>
+#include <linux/suspend.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
#include <linux/io.h>
@@ -89,28 +89,15 @@ void bfin_pm_suspend_standby_enter(void)
#endif /* CONFIG_PM_WAKEUP_GPIO_BY_SIC_IWR */
}
-
/*
- * bfin_pm_prepare - Do preliminary suspend work.
- * @state: suspend state we're entering.
+ * bfin_pm_valid - Tell the PM core that we only support the standby sleep
+ * state
+ * @state: suspend state we're checking.
*
*/
-static int bfin_pm_prepare(suspend_state_t state)
+static int bfin_pm_valid(suspend_state_t state)
{
- int error = 0;
-
- switch (state) {
- case PM_SUSPEND_STANDBY:
- break;
-
- case PM_SUSPEND_MEM:
- return -ENOTSUPP;
-
- default:
- return -EINVAL;
- }
-
- return error;
+ return (state == PM_SUSPEND_STANDBY);
}
/*
@@ -135,44 +122,14 @@ static int bfin_pm_enter(suspend_state_t state)
return 0;
}
-/*
- * bfin_pm_finish - Finish up suspend sequence.
- * @state: State we're coming out of.
- *
- * This is called after we wake back up (or if entering the sleep state
- * failed).
- */
-static int bfin_pm_finish(suspend_state_t state)
-{
- switch (state) {
- case PM_SUSPEND_STANDBY:
- break;
-
- case PM_SUSPEND_MEM:
- return -ENOTSUPP;
-
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int bfin_pm_valid(suspend_state_t state)
-{
- return (state == PM_SUSPEND_STANDBY);
-}
-
-struct pm_ops bfin_pm_ops = {
- .prepare = bfin_pm_prepare,
+struct platform_suspend_ops bfin_pm_ops = {
.enter = bfin_pm_enter,
- .finish = bfin_pm_finish,
.valid = bfin_pm_valid,
};
static int __init bfin_pm_init(void)
{
- pm_set_ops(&bfin_pm_ops);
+ suspend_set_ops(&bfin_pm_ops);
return 0;
}
diff --git a/arch/blackfin/oprofile/Kconfig b/arch/blackfin/oprofile/Kconfig
deleted file mode 100644
index 0a2fd999c941..000000000000
--- a/arch/blackfin/oprofile/Kconfig
+++ /dev/null
@@ -1,29 +0,0 @@
-menu "Profiling support"
-depends on EXPERIMENTAL
-
-config PROFILING
- bool "Profiling support (EXPERIMENTAL)"
- help
- Say Y here to enable the extended profiling support mechanisms used
- by profilers such as OProfile.
-
-config OPROFILE
- tristate "OProfile system profiling (EXPERIMENTAL)"
- depends on PROFILING
- help
- OProfile is a profiling system capable of profiling the
- whole system, include the kernel, kernel modules, libraries,
- and applications.
-
- If unsure, say N.
-
-config HARDWARE_PM
- tristate "Hardware Performance Monitor Profiling"
- depends on PROFILING
- help
- take use of hardware performance monitor to profiling the kernel
- and application.
-
- If unsure, say N.
-
-endmenu
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index 6b4d026a00a1..222da1501f47 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -13,6 +13,10 @@ config ZONE_DMA
bool
default y
+config NO_DMA
+ bool
+ default y
+
config RWSEM_GENERIC_SPINLOCK
bool
default y
@@ -57,6 +61,10 @@ menu "General setup"
source "fs/Kconfig.binfmt"
+config GENERIC_HARDIRQS
+ bool
+ default y
+
config ETRAX_CMDLINE
string "Kernel command line"
default "root=/dev/mtdblock3"
@@ -149,7 +157,8 @@ source "net/Kconfig"
# bring in ETRAX built-in drivers
menu "Drivers for built-in interfaces"
-source arch/cris/arch-v10/drivers/Kconfig
+# arch/cris/arch is a symlink to correct arch (arch-v10 or arch-v32)
+source arch/cris/arch/drivers/Kconfig
endmenu
@@ -180,6 +189,10 @@ source "drivers/isdn/Kconfig"
source "drivers/telephony/Kconfig"
+source "drivers/i2c/Kconfig"
+
+source "drivers/rtc/Kconfig"
+
#
# input before char - char/joystick depends on it. As does USB.
#
@@ -194,8 +207,14 @@ source "fs/Kconfig"
source "sound/Kconfig"
+source "drivers/pcmcia/Kconfig"
+
+source "drivers/pci/Kconfig"
+
source "drivers/usb/Kconfig"
+source "kernel/Kconfig.instrumentation"
+
source "arch/cris/Kconfig.debug"
source "security/Kconfig"
diff --git a/arch/cris/Makefile b/arch/cris/Makefile
index ee114699ef8e..e6bf00c262e0 100644
--- a/arch/cris/Makefile
+++ b/arch/cris/Makefile
@@ -29,18 +29,18 @@ LD = $(CROSS_COMPILE)ld -mcrislinux
OBJCOPYFLAGS := -O binary -R .note -R .comment -S
CPPFLAGS_vmlinux.lds = -DDRAM_VIRTUAL_BASE=0x$(CONFIG_ETRAX_DRAM_VIRTUAL_BASE)
-AFLAGS += -mlinux
+KBUILD_AFLAGS += -mlinux
-CFLAGS := $(CFLAGS) -mlinux -march=$(arch-y) -pipe
+KBUILD_CFLAGS += -mlinux -march=$(arch-y) -pipe
ifdef CONFIG_FRAME_POINTER
-CFLAGS := $(subst -fomit-frame-pointer,,$(CFLAGS)) -g
-CFLAGS += -fno-omit-frame-pointer
+KBUILD_CFLAGS := $(subst -fomit-frame-pointer,,$(KBUILD_CFLAGS)) -g
+KBUILD_CFLAGS += -fno-omit-frame-pointer
endif
head-y := arch/$(ARCH)/$(SARCH)/kernel/head.o
-LIBGCC = $(shell $(CC) $(CFLAGS) -print-file-name=libgcc.a)
+LIBGCC = $(shell $(CC) $(KBUILD_CFLAGS) -print-file-name=libgcc.a)
core-y += arch/$(ARCH)/kernel/ arch/$(ARCH)/mm/
core-y += arch/$(ARCH)/$(SARCH)/kernel/ arch/$(ARCH)/$(SARCH)/mm/
diff --git a/arch/cris/arch-v10/Kconfig b/arch/cris/arch-v10/Kconfig
index c7ea9efd0104..f1ce6f64401d 100644
--- a/arch/cris/arch-v10/Kconfig
+++ b/arch/cris/arch-v10/Kconfig
@@ -182,7 +182,7 @@ config ETRAX_LED7G
set this to same as CONFIG_ETRAX_LED1G (normally 2).
config ETRAX_LED8Y
- int "Eigth yellow LED bit"
+ int "Eighth yellow LED bit"
depends on ETRAX_CSP0_LEDS
default "2"
help
diff --git a/arch/cris/arch-v10/boot/compressed/misc.c b/arch/cris/arch-v10/boot/compressed/misc.c
index ffb8d21b2f83..e205d2e7e089 100644
--- a/arch/cris/arch-v10/boot/compressed/misc.c
+++ b/arch/cris/arch-v10/boot/compressed/misc.c
@@ -8,7 +8,7 @@
*
* malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
* puts by Nick Holloway 1993, better puts by Martin Mares 1995
- * adoptation for Linux/CRIS Axis Communications AB, 1999
+ * adaptation for Linux/CRIS Axis Communications AB, 1999
*
*/
diff --git a/arch/cris/arch-v10/defconfig b/arch/cris/arch-v10/defconfig
index 710c20ba2be7..572f11926399 100644
--- a/arch/cris/arch-v10/defconfig
+++ b/arch/cris/arch-v10/defconfig
@@ -99,7 +99,6 @@ CONFIG_MTD=y
CONFIG_MTD_CFI=y
# CONFIG_MTD_CFI_INTELEXT is not set
CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_AMDSTD=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_ETRAX_I2C=y
@@ -145,7 +144,6 @@ CONFIG_MTD_CFI=y
# CONFIG_MTD_CFI_GEOMETRY is not set
# CONFIG_MTD_CFI_INTELEXT is not set
CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_AMDSTD=y
# CONFIG_MTD_SHARP is not set
# CONFIG_MTD_PHYSMAP is not set
# CONFIG_MTD_NORA is not set
diff --git a/arch/cris/arch-v10/drivers/Kconfig b/arch/cris/arch-v10/drivers/Kconfig
index 03e2e68f947d..faf8b4d3ca01 100644
--- a/arch/cris/arch-v10/drivers/Kconfig
+++ b/arch/cris/arch-v10/drivers/Kconfig
@@ -2,6 +2,7 @@ config ETRAX_ETHERNET
bool "Ethernet support"
depends on ETRAX_ARCH_V10
select NET_ETHERNET
+ select MII
help
This option enables the ETRAX 100LX built-in 10/100Mbit Ethernet
controller.
@@ -605,8 +606,6 @@ config ETRAX_AXISFLASHMAP
select MTD
select MTD_CFI
select MTD_CFI_AMDSTD
- select MTD_OBSOLETE_CHIPS
- select MTD_AMDSTD
select MTD_CHAR
select MTD_BLOCK
select MTD_PARTITIONS
diff --git a/arch/cris/arch-v10/drivers/axisflashmap.c b/arch/cris/arch-v10/drivers/axisflashmap.c
index efd7b0f3a910..ea3cf2e39a14 100644
--- a/arch/cris/arch-v10/drivers/axisflashmap.c
+++ b/arch/cris/arch-v10/drivers/axisflashmap.c
@@ -312,12 +312,12 @@ static struct mtd_info *probe_cs(struct map_info *map_cs)
"%s: Probing a 0x%08lx bytes large window at 0x%08lx.\n",
map_cs->name, map_cs->size, map_cs->map_priv_1);
-#ifdef CONFIG_MTD_AMDSTD
- mtd_cs = do_map_probe("amd_flash", map_cs);
-#endif
#ifdef CONFIG_MTD_CFI
+ mtd_cs = do_map_probe("cfi_probe", map_cs);
+#endif
+#ifdef CONFIG_MTD_JEDECPROBE
if (!mtd_cs) {
- mtd_cs = do_map_probe("cfi_probe", map_cs);
+ mtd_cs = do_map_probe("jedec_probe", map_cs);
}
#endif
diff --git a/arch/cris/arch-v10/drivers/gpio.c b/arch/cris/arch-v10/drivers/gpio.c
index f389ed6998fe..0d347a705835 100644
--- a/arch/cris/arch-v10/drivers/gpio.c
+++ b/arch/cris/arch-v10/drivers/gpio.c
@@ -297,8 +297,10 @@ gpio_poll(struct file *file,
data = *R_PORT_PB_DATA;
else if (priv->minor == GPIO_MINOR_G)
data = *R_PORT_G_DATA;
- else
+ else {
+ spin_unlock(&gpio_lock);
return 0;
+ }
if ((data & priv->highalarm) ||
(~data & priv->lowalarm)) {
@@ -381,18 +383,21 @@ static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
ssize_t retval = count;
if (priv->minor !=GPIO_MINOR_A && priv->minor != GPIO_MINOR_B) {
- return -EFAULT;
+ retval = -EFAULT;
+ goto out;
}
if (!access_ok(VERIFY_READ, buf, count)) {
- return -EFAULT;
+ retval = -EFAULT;
+ goto out;
}
clk_mask = priv->clk_mask;
data_mask = priv->data_mask;
/* It must have been configured using the IO_CFG_WRITE_MODE */
/* Perhaps a better error code? */
if (clk_mask == 0 || data_mask == 0) {
- return -EPERM;
+ retval = -EPERM;
+ goto out;
}
write_msb = priv->write_msb;
D(printk("gpio_write: %lu to data 0x%02X clk 0x%02X msb: %i\n",count, data_mask, clk_mask, write_msb));
@@ -425,6 +430,7 @@ static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
}
}
}
+out:
spin_unlock(&gpio_lock);
return retval;
}
@@ -506,6 +512,7 @@ gpio_release(struct inode *inode, struct file *filp)
while (p) {
if (p->highalarm | p->lowalarm) {
gpio_some_alarms = 1;
+ spin_unlock(&gpio_lock);
return 0;
}
p = p->next;
diff --git a/arch/cris/arch-v10/drivers/pcf8563.c b/arch/cris/arch-v10/drivers/pcf8563.c
index 1de0026bb94e..c263b8232dbc 100644
--- a/arch/cris/arch-v10/drivers/pcf8563.c
+++ b/arch/cris/arch-v10/drivers/pcf8563.c
@@ -4,7 +4,7 @@
* From Phillips' datasheet:
*
* The PCF8563 is a CMOS real-time clock/calendar optimized for low power
- * consumption. A programmable clock output, interupt output and voltage
+ * consumption. A programmable clock output, interrupt output and voltage
* low detector are also provided. All address and data are transferred
* serially via two-line bidirectional I2C-bus. Maximum bus speed is
* 400 kbits/s. The built-in word address register is incremented
diff --git a/arch/cris/arch-v10/kernel/debugport.c b/arch/cris/arch-v10/kernel/debugport.c
index 2b536ca6f444..93679a48c791 100644
--- a/arch/cris/arch-v10/kernel/debugport.c
+++ b/arch/cris/arch-v10/kernel/debugport.c
@@ -83,7 +83,7 @@
*
* Revision 1.4 2002/11/19 14:35:24 starvik
* Changes from linux 2.4
- * Changed struct initializer syntax to the currently prefered notation
+ * Changed struct initializer syntax to the currently preferred notation
*
* Revision 1.3 2002/11/06 09:47:03 starvik
* Modified for new interrupt macros
diff --git a/arch/cris/arch-v10/kernel/entry.S b/arch/cris/arch-v10/kernel/entry.S
index ae45d4522e65..ec62c951fa3c 100644
--- a/arch/cris/arch-v10/kernel/entry.S
+++ b/arch/cris/arch-v10/kernel/entry.S
@@ -97,7 +97,7 @@
*
* Revision 1.36 2001/11/22 13:36:36 bjornw
* * In ret_from_intr, check regs->dccr for usermode reentrance instead of
- * DCCR explicitely (because the latter might not reflect current reality)
+ * DCCR explicitly (because the latter might not reflect current reality)
* * In mmu_bus_fault, set $r9 _after_ calling the C-code instead of before
* since $r9 is call-clobbered and is potentially needed afterwards
*
@@ -500,9 +500,8 @@ _work_notifysig:
;; deal with pending signals and notify-resume requests
move.d $r9, $r10 ; do_notify_resume syscall/irq param
- moveq 0, $r11 ; oldset param - 0 in this case
- move.d $sp, $r12 ; the regs param
- move.d $r1, $r13 ; the thread_info_flags parameter
+ move.d $sp, $r11 ; the regs param
+ move.d $r1, $r12 ; the thread_info_flags parameter
jsr do_notify_resume
ba _Rexit
@@ -678,13 +677,19 @@ IRQ1_interrupt:
push $r10 ; push orig_r10
clear.d [$sp=$sp-4] ; frametype == 0, normal frame
+ ;; If there is a glitch on the NMI pin shorter than ~100ns
+ ;; (i.e. non-active by the time we get here) then the nmi_pin bit
+ ;; in R_IRQ_MASK0_RD will already be cleared. The watchdog_nmi bit
+ ;; is cleared by us however (when feeding the watchdog), which is why
+ ;; we use that bit to determine what brought us here.
+
move.d [R_IRQ_MASK0_RD], $r1 ; External NMI or watchdog?
- and.d 0x80000000, $r1
- beq wdog
+ and.d (1<<30), $r1
+ bne wdog
move.d $sp, $r10
jsr handle_nmi
setf m ; Enable NMI again
- retb ; Return from NMI
+ ba _Rexit ; Return the standard way
nop
wdog:
#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
@@ -775,22 +780,9 @@ multiple_interrupt:
push $r10 ; push orig_r10
clear.d [$sp=$sp-4] ; frametype == 0, normal frame
- moveq 2, $r2 ; first bit we care about is the timer0 irq
- move.d [R_VECT_MASK_RD], $r0; read the irq bits that triggered the multiple irq
- move.d $r0, [R_VECT_MASK_CLR] ; Block all active IRQs
-1:
- btst $r2, $r0 ; check for the irq given by bit r2
- bpl 2f
- move.d $r2, $r10 ; First argument to do_IRQ
- move.d $sp, $r11 ; second argument to do_IRQ
- jsr do_IRQ
-2:
- addq 1, $r2 ; next vector bit
- cmp.b 32, $r2
- bne 1b ; process all irq's up to and including number 31
- moveq 0, $r9 ; make ret_from_intr realise we came from an ir
+ move.d $sp, $r10
+ jsr do_multiple_IRQ
- move.d $r0, [R_VECT_MASK_SET] ; Unblock all the IRQs
jump ret_from_intr
do_sigtrap:
@@ -837,6 +829,13 @@ _ugdb_handle_breakpoint:
ba do_sigtrap ; SIGTRAP the offending process.
pop $dccr ; Restore dccr in delay slot.
+ .global kernel_execve
+kernel_execve:
+ move.d __NR_execve, $r9
+ break 13
+ ret
+ nop
+
.data
hw_bp_trigs:
@@ -1135,6 +1134,42 @@ sys_call_table:
.long sys_add_key
.long sys_request_key
.long sys_keyctl
+ .long sys_ioprio_set
+ .long sys_ioprio_get /* 290 */
+ .long sys_inotify_init
+ .long sys_inotify_add_watch
+ .long sys_inotify_rm_watch
+ .long sys_migrate_pages
+ .long sys_openat /* 295 */
+ .long sys_mkdirat
+ .long sys_mknodat
+ .long sys_fchownat
+ .long sys_futimesat
+ .long sys_fstatat64 /* 300 */
+ .long sys_unlinkat
+ .long sys_renameat
+ .long sys_linkat
+ .long sys_symlinkat
+ .long sys_readlinkat /* 305 */
+ .long sys_fchmodat
+ .long sys_faccessat
+ .long sys_pselect6
+ .long sys_ppoll
+ .long sys_unshare /* 310 */
+ .long sys_set_robust_list
+ .long sys_get_robust_list
+ .long sys_splice
+ .long sys_sync_file_range
+ .long sys_tee /* 315 */
+ .long sys_vmsplice
+ .long sys_move_pages
+ .long sys_getcpu
+ .long sys_epoll_pwait
+ .long sys_utimensat /* 320 */
+ .long sys_signalfd
+ .long sys_timerfd
+ .long sys_eventfd
+ .long sys_fallocate
/*
* NOTE!! This doesn't have to be exact - we just have
diff --git a/arch/cris/arch-v10/kernel/fasttimer.c b/arch/cris/arch-v10/kernel/fasttimer.c
index 8cbdf594b369..c1a3a2100ee7 100644
--- a/arch/cris/arch-v10/kernel/fasttimer.c
+++ b/arch/cris/arch-v10/kernel/fasttimer.c
@@ -1,97 +1,9 @@
-/* $Id: fasttimer.c,v 1.9 2005/03/04 08:16:16 starvik Exp $
+/*
* linux/arch/cris/kernel/fasttimer.c
*
* Fast timers for ETRAX100/ETRAX100LX
- * This may be useful in other OS than Linux so use 2 space indentation...
*
- * $Log: fasttimer.c,v $
- * Revision 1.9 2005/03/04 08:16:16 starvik
- * Merge of Linux 2.6.11.
- *
- * Revision 1.8 2005/01/05 06:09:29 starvik
- * cli()/sti() will be obsolete in 2.6.11.
- *
- * Revision 1.7 2005/01/03 13:35:46 starvik
- * Removed obsolete stuff.
- * Mark fast timer IRQ as not shared.
- *
- * Revision 1.6 2004/05/14 10:18:39 starvik
- * Export fast_timer_list
- *
- * Revision 1.5 2004/05/14 07:58:01 starvik
- * Merge of changes from 2.4
- *
- * Revision 1.4 2003/07/04 08:27:41 starvik
- * Merge of Linux 2.5.74
- *
- * Revision 1.3 2002/12/12 08:26:32 starvik
- * Don't use C-comments inside CVS comments
- *
- * Revision 1.2 2002/12/11 15:42:02 starvik
- * Extracted v10 (ETRAX 100LX) specific stuff from arch/cris/kernel/
- *
- * Revision 1.1 2002/11/18 07:58:06 starvik
- * Fast timers (from Linux 2.4)
- *
- * Revision 1.5 2002/10/15 06:21:39 starvik
- * Added call to init_waitqueue_head
- *
- * Revision 1.4 2002/05/28 17:47:59 johana
- * Added del_fast_timer()
- *
- * Revision 1.3 2002/05/28 16:16:07 johana
- * Handle empty fast_timer_list
- *
- * Revision 1.2 2002/05/27 15:38:42 johana
- * Made it compile without warnings on Linux 2.4.
- * (includes, wait_queue, PROC_FS and snprintf)
- *
- * Revision 1.1 2002/05/27 15:32:25 johana
- * arch/etrax100/kernel/fasttimer.c v1.8 from the elinux tree.
- *
- * Revision 1.8 2001/11/27 13:50:40 pkj
- * Disable interrupts while stopping the timer and while modifying the
- * list of active timers in timer1_handler() as it may be interrupted
- * by other interrupts (e.g., the serial interrupt) which may add fast
- * timers.
- *
- * Revision 1.7 2001/11/22 11:50:32 pkj
- * * Only store information about the last 16 timers.
- * * proc_fasttimer_read() now uses an allocated buffer, since it
- * requires more space than just a page even for only writing the
- * last 16 timers. The buffer is only allocated on request, so
- * unless /proc/fasttimer is read, it is never allocated.
- * * Renamed fast_timer_started to fast_timers_started to match
- * fast_timers_added and fast_timers_expired.
- * * Some clean-up.
- *
- * Revision 1.6 2000/12/13 14:02:08 johana
- * Removed volatile for fast_timer_list
- *
- * Revision 1.5 2000/12/13 13:55:35 johana
- * Added DEBUG_LOG, added som cli() and cleanup
- *
- * Revision 1.4 2000/12/05 13:48:50 johana
- * Added range check when writing proc file, modified timer int handling
- *
- * Revision 1.3 2000/11/23 10:10:20 johana
- * More debug/logging possibilities.
- * Moved GET_JIFFIES_USEC() to timex.h and time.c
- *
- * Revision 1.2 2000/11/01 13:41:04 johana
- * Clean up and bugfixes.
- * Created new do_gettimeofday_fast() that gets a timeval struct
- * with time based on jiffies and *R_TIMER0_DATA, uses a table
- * for fast conversion of timer value to microseconds.
- * (Much faster the standard do_gettimeofday() and we don't really
- * wan't to use the true time - we wan't the "uptime" so timers don't screw up
- * when we change the time.
- * TODO: Add efficient support for continuous timers as well.
- *
- * Revision 1.1 2000/10/26 15:49:16 johana
- * Added fasttimer, highresolution timers.
- *
- * Copyright (C) 2000,2001 2002 Axis Communications AB, Lund, Sweden
+ * Copyright (C) 2000-2007 Axis Communications AB, Lund, Sweden
*/
#include <linux/errno.h>
@@ -125,7 +37,7 @@
#ifdef FAST_TIMER_SANITY_CHECKS
#define SANITYCHECK(x) x
-static int sanity_failed = 0;
+static int sanity_failed;
#else
#define SANITYCHECK(x)
#endif
@@ -134,15 +46,13 @@ static int sanity_failed = 0;
#define D2(x)
#define DP(x)
-#define __INLINE__ inline
-
-static int fast_timer_running = 0;
-static int fast_timers_added = 0;
-static int fast_timers_started = 0;
-static int fast_timers_expired = 0;
-static int fast_timers_deleted = 0;
-static int fast_timer_is_init = 0;
-static int fast_timer_ints = 0;
+static unsigned int fast_timer_running;
+static unsigned int fast_timers_added;
+static unsigned int fast_timers_started;
+static unsigned int fast_timers_expired;
+static unsigned int fast_timers_deleted;
+static unsigned int fast_timer_is_init;
+static unsigned int fast_timer_ints;
struct fast_timer *fast_timer_list = NULL;
@@ -150,8 +60,8 @@ struct fast_timer *fast_timer_list = NULL;
#define DEBUG_LOG_MAX 128
static const char * debug_log_string[DEBUG_LOG_MAX];
static unsigned long debug_log_value[DEBUG_LOG_MAX];
-static int debug_log_cnt = 0;
-static int debug_log_cnt_wrapped = 0;
+static unsigned int debug_log_cnt;
+static unsigned int debug_log_cnt_wrapped;
#define DEBUG_LOG(string, value) \
{ \
@@ -206,45 +116,29 @@ int timer_freq_settings[NUM_TIMER_STATS];
int timer_delay_settings[NUM_TIMER_STATS];
/* Not true gettimeofday, only checks the jiffies (uptime) + useconds */
-void __INLINE__ do_gettimeofday_fast(struct timeval *tv)
+inline void do_gettimeofday_fast(struct fasttime_t *tv)
{
- unsigned long sec = jiffies;
- unsigned long usec = GET_JIFFIES_USEC();
-
- usec += (sec % HZ) * (1000000 / HZ);
- sec = sec / HZ;
-
- if (usec > 1000000)
- {
- usec -= 1000000;
- sec++;
- }
- tv->tv_sec = sec;
- tv->tv_usec = usec;
+ tv->tv_jiff = jiffies;
+ tv->tv_usec = GET_JIFFIES_USEC();
}
-int __INLINE__ timeval_cmp(struct timeval *t0, struct timeval *t1)
+inline int fasttime_cmp(struct fasttime_t *t0, struct fasttime_t *t1)
{
- if (t0->tv_sec < t1->tv_sec)
- {
- return -1;
- }
- else if (t0->tv_sec > t1->tv_sec)
- {
- return 1;
- }
- if (t0->tv_usec < t1->tv_usec)
- {
- return -1;
- }
- else if (t0->tv_usec > t1->tv_usec)
- {
- return 1;
- }
- return 0;
+ /* Compare jiffies. Takes care of wrapping */
+ if (time_before(t0->tv_jiff, t1->tv_jiff))
+ return -1;
+ else if (time_after(t0->tv_jiff, t1->tv_jiff))
+ return 1;
+
+ /* Compare us */
+ if (t0->tv_usec < t1->tv_usec)
+ return -1;
+ else if (t0->tv_usec > t1->tv_usec)
+ return 1;
+ return 0;
}
-void __INLINE__ start_timer1(unsigned long delay_us)
+inline void start_timer1(unsigned long delay_us)
{
int freq_index = 0; /* This is the lowest resolution */
unsigned long upper_limit = MAX_DELAY_US;
@@ -285,7 +179,7 @@ void __INLINE__ start_timer1(unsigned long delay_us)
timer_freq_settings[fast_timers_started % NUM_TIMER_STATS] = freq_index;
timer_delay_settings[fast_timers_started % NUM_TIMER_STATS] = delay_us;
- D1(printk("start_timer1 : %d us freq: %i div: %i\n",
+ D1(printk(KERN_DEBUG "start_timer1 : %d us freq: %i div: %i\n",
delay_us, freq_index, div));
/* Clear timer1 irq */
*R_IRQ_MASK0_CLR = IO_STATE(R_IRQ_MASK0_CLR, timer1, clr);
@@ -340,7 +234,7 @@ void start_one_shot_timer(struct fast_timer *t,
printk(KERN_WARNING
"timer name: %s data: 0x%08lX already in list!\n", name, data);
sanity_failed++;
- return;
+ goto done;
}
else
{
@@ -356,11 +250,11 @@ void start_one_shot_timer(struct fast_timer *t,
t->name = name;
t->tv_expires.tv_usec = t->tv_set.tv_usec + delay_us % 1000000;
- t->tv_expires.tv_sec = t->tv_set.tv_sec + delay_us / 1000000;
+ t->tv_expires.tv_jiff = t->tv_set.tv_jiff + delay_us / 1000000 / HZ;
if (t->tv_expires.tv_usec > 1000000)
{
t->tv_expires.tv_usec -= 1000000;
- t->tv_expires.tv_sec++;
+ t->tv_expires.tv_jiff += HZ;
}
#ifdef FAST_TIMER_LOG
timer_added_log[fast_timers_added % NUM_TIMER_STATS] = *t;
@@ -368,7 +262,7 @@ void start_one_shot_timer(struct fast_timer *t,
fast_timers_added++;
/* Check if this should timeout before anything else */
- if (tmp == NULL || timeval_cmp(&t->tv_expires, &tmp->tv_expires) < 0)
+ if (tmp == NULL || fasttime_cmp(&t->tv_expires, &tmp->tv_expires) < 0)
{
/* Put first in list and modify the timer value */
t->prev = NULL;
@@ -384,8 +278,8 @@ void start_one_shot_timer(struct fast_timer *t,
start_timer1(delay_us);
} else {
/* Put in correct place in list */
- while (tmp->next &&
- timeval_cmp(&t->tv_expires, &tmp->next->tv_expires) > 0)
+ while (tmp->next && fasttime_cmp(&t->tv_expires,
+ &tmp->next->tv_expires) > 0)
{
tmp = tmp->next;
}
@@ -401,6 +295,7 @@ void start_one_shot_timer(struct fast_timer *t,
D2(printk("start_one_shot_timer: %d us done\n", delay_us));
+done:
local_irq_restore(flags);
} /* start_one_shot_timer */
@@ -444,11 +339,18 @@ int del_fast_timer(struct fast_timer * t)
/* Timer 1 interrupt handler */
static irqreturn_t
-timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
+timer1_handler(int irq, void *dev_id)
{
struct fast_timer *t;
unsigned long flags;
+ /* We keep interrupts disabled not only when we modify the
+ * fast timer list, but any time we hold a reference to a
+ * timer in the list, since del_fast_timer may be called
+ * from (another) interrupt context. Thus, the only time
+ * when interrupts are enabled is when calling the timer
+ * callback function.
+ */
local_irq_save(flags);
/* Clear timer1 irq */
@@ -466,18 +368,19 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
fast_timer_running = 0;
fast_timer_ints++;
- local_irq_restore(flags);
-
t = fast_timer_list;
while (t)
{
- struct timeval tv;
+ struct fasttime_t tv;
+ fast_timer_function_type *f;
+ unsigned long d;
/* Has it really expired? */
do_gettimeofday_fast(&tv);
- D1(printk("t: %is %06ius\n", tv.tv_sec, tv.tv_usec));
+ D1(printk(KERN_DEBUG "t: %is %06ius\n",
+ tv.tv_jiff, tv.tv_usec));
- if (timeval_cmp(&t->tv_expires, &tv) <= 0)
+ if (fasttime_cmp(&t->tv_expires, &tv) <= 0)
{
/* Yes it has expired */
#ifdef FAST_TIMER_LOG
@@ -486,7 +389,6 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
fast_timers_expired++;
/* Remove this timer before call, since it may reuse the timer */
- local_irq_save(flags);
if (t->prev)
{
t->prev->next = t->next;
@@ -501,16 +403,23 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
}
t->prev = NULL;
t->next = NULL;
- local_irq_restore(flags);
- if (t->function != NULL)
- {
- t->function(t->data);
- }
- else
- {
+ /* Save function callback data before enabling
+ * interrupts, since the timer may be removed and
+ * we don't know how it was allocated
+ * (e.g. ->function and ->data may become overwritten
+ * after deletion if the timer was stack-allocated).
+ */
+ f = t->function;
+ d = t->data;
+
+ if (f != NULL) {
+ /* Run callback with interrupts enabled. */
+ local_irq_restore(flags);
+ f(d);
+ local_irq_save(flags);
+ } else
DEBUG_LOG("!timer1 %i function==NULL!\n", fast_timer_ints);
- }
}
else
{
@@ -518,16 +427,20 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
D1(printk(".\n"));
}
- local_irq_save(flags);
if ((t = fast_timer_list) != NULL)
{
/* Start next timer.. */
- long us;
- struct timeval tv;
+ long us = 0;
+ struct fasttime_t tv;
do_gettimeofday_fast(&tv);
- us = ((t->tv_expires.tv_sec - tv.tv_sec) * 1000000 +
- t->tv_expires.tv_usec - tv.tv_usec);
+
+ /* time_after_eq takes care of wrapping */
+ if (time_after_eq(t->tv_expires.tv_jiff, tv.tv_jiff))
+ us = ((t->tv_expires.tv_jiff - tv.tv_jiff) *
+ 1000000 / HZ + t->tv_expires.tv_usec -
+ tv.tv_usec);
+
if (us > 0)
{
if (!fast_timer_running)
@@ -537,7 +450,6 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
#endif
start_timer1(us);
}
- local_irq_restore(flags);
break;
}
else
@@ -548,9 +460,10 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
D1(printk("e! %d\n", us));
}
}
- local_irq_restore(flags);
}
+ local_irq_restore(flags);
+
if (!t)
{
D1(printk("t1 stop!\n"));
@@ -575,28 +488,17 @@ static void wake_up_func(unsigned long data)
void schedule_usleep(unsigned long us)
{
struct fast_timer t;
-#ifdef DECLARE_WAITQUEUE
wait_queue_head_t sleep_wait;
init_waitqueue_head(&sleep_wait);
- {
- DECLARE_WAITQUEUE(wait, current);
-#else
- struct wait_queue *sleep_wait = NULL;
- struct wait_queue wait = { current, NULL };
-#endif
D1(printk("schedule_usleep(%d)\n", us));
- add_wait_queue(&sleep_wait, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
start_one_shot_timer(&t, wake_up_func, (unsigned long)&sleep_wait, us,
"usleep");
- schedule();
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&sleep_wait, &wait);
+ /* Uninterruptible sleep on the fast timer. (The condition is somewhat
+ * redundant since the timer is what wakes us up.) */
+ wait_event(sleep_wait, !fast_timer_pending(&t));
+
D1(printk("done schedule_usleep(%d)\n", us));
-#ifdef DECLARE_WAITQUEUE
- }
-#endif
}
#ifdef CONFIG_PROC_FS
@@ -616,7 +518,7 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
unsigned long flags;
int i = 0;
int num_to_show;
- struct timeval tv;
+ struct fasttime_t tv;
struct fast_timer *t, *nextt;
static char *bigbuf = NULL;
static unsigned long used;
@@ -624,7 +526,8 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
if (!bigbuf && !(bigbuf = vmalloc(BIG_BUF_SIZE)))
{
used = 0;
- bigbuf[0] = '\0';
+ if (buf)
+ buf[0] = '\0';
return 0;
}
@@ -646,7 +549,7 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
used += sprintf(bigbuf + used, "Fast timer running: %s\n",
fast_timer_running ? "yes" : "no");
used += sprintf(bigbuf + used, "Current time: %lu.%06lu\n",
- (unsigned long)tv.tv_sec,
+ (unsigned long)tv.tv_jiff,
(unsigned long)tv.tv_usec);
#ifdef FAST_TIMER_SANITY_CHECKS
used += sprintf(bigbuf + used, "Sanity failed: %i\n",
@@ -696,9 +599,9 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
"d: %6li us data: 0x%08lX"
"\n",
t->name,
- (unsigned long)t->tv_set.tv_sec,
+ (unsigned long)t->tv_set.tv_jiff,
(unsigned long)t->tv_set.tv_usec,
- (unsigned long)t->tv_expires.tv_sec,
+ (unsigned long)t->tv_expires.tv_jiff,
(unsigned long)t->tv_expires.tv_usec,
t->delay_us,
t->data
@@ -718,9 +621,9 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
"d: %6li us data: 0x%08lX"
"\n",
t->name,
- (unsigned long)t->tv_set.tv_sec,
+ (unsigned long)t->tv_set.tv_jiff,
(unsigned long)t->tv_set.tv_usec,
- (unsigned long)t->tv_expires.tv_sec,
+ (unsigned long)t->tv_expires.tv_jiff,
(unsigned long)t->tv_expires.tv_usec,
t->delay_us,
t->data
@@ -738,9 +641,9 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
"d: %6li us data: 0x%08lX"
"\n",
t->name,
- (unsigned long)t->tv_set.tv_sec,
+ (unsigned long)t->tv_set.tv_jiff,
(unsigned long)t->tv_set.tv_usec,
- (unsigned long)t->tv_expires.tv_sec,
+ (unsigned long)t->tv_expires.tv_jiff,
(unsigned long)t->tv_expires.tv_usec,
t->delay_us,
t->data
@@ -761,15 +664,15 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
/* " func: 0x%08lX" */
"\n",
t->name,
- (unsigned long)t->tv_set.tv_sec,
+ (unsigned long)t->tv_set.tv_jiff,
(unsigned long)t->tv_set.tv_usec,
- (unsigned long)t->tv_expires.tv_sec,
+ (unsigned long)t->tv_expires.tv_jiff,
(unsigned long)t->tv_expires.tv_usec,
t->delay_us,
t->data
/* , t->function */
);
- local_irq_disable();
+ local_irq_save(flags);
if (t->next != nextt)
{
printk(KERN_WARNING "timer removed!\n");
@@ -798,7 +701,7 @@ static volatile int num_test_timeout = 0;
static struct fast_timer tr[10];
static int exp_num[10];
-static struct timeval tv_exp[100];
+static struct fasttime_t tv_exp[100];
static void test_timeout(unsigned long data)
{
@@ -836,7 +739,7 @@ static void fast_timer_test(void)
int prev_num;
int j;
- struct timeval tv, tv0, tv1, tv2;
+ struct fasttime_t tv, tv0, tv1, tv2;
printk("fast_timer_test() start\n");
do_gettimeofday_fast(&tv);
@@ -849,7 +752,8 @@ static void fast_timer_test(void)
{
do_gettimeofday_fast(&tv_exp[j]);
}
- printk("fast_timer_test() %is %06i\n", tv.tv_sec, tv.tv_usec);
+ printk(KERN_DEBUG "fast_timer_test() %is %06i\n",
+ tv.tv_jiff, tv.tv_usec);
for (j = 0; j < 1000; j++)
{
@@ -858,12 +762,12 @@ static void fast_timer_test(void)
}
for (j = 0; j < 100; j++)
{
- printk("%i.%i %i.%i %i.%i %i.%i %i.%i\n",
- tv_exp[j].tv_sec,tv_exp[j].tv_usec,
- tv_exp[j+1].tv_sec,tv_exp[j+1].tv_usec,
- tv_exp[j+2].tv_sec,tv_exp[j+2].tv_usec,
- tv_exp[j+3].tv_sec,tv_exp[j+3].tv_usec,
- tv_exp[j+4].tv_sec,tv_exp[j+4].tv_usec);
+ printk(KERN_DEBUG "%i.%i %i.%i %i.%i %i.%i %i.%i\n",
+ tv_exp[j].tv_jiff, tv_exp[j].tv_usec,
+ tv_exp[j+1].tv_jiff, tv_exp[j+1].tv_usec,
+ tv_exp[j+2].tv_jiff, tv_exp[j+2].tv_usec,
+ tv_exp[j+3].tv_jiff, tv_exp[j+3].tv_usec,
+ tv_exp[j+4].tv_jiff, tv_exp[j+4].tv_usec);
j += 4;
}
do_gettimeofday_fast(&tv0);
@@ -895,9 +799,12 @@ static void fast_timer_test(void)
}
}
do_gettimeofday_fast(&tv2);
- printk("Timers started %is %06i\n", tv0.tv_sec, tv0.tv_usec);
- printk("Timers started at %is %06i\n", tv1.tv_sec, tv1.tv_usec);
- printk("Timers done %is %06i\n", tv2.tv_sec, tv2.tv_usec);
+ printk(KERN_DEBUG "Timers started %is %06i\n",
+ tv0.tv_jiff, tv0.tv_usec);
+ printk(KERN_DEBUG "Timers started at %is %06i\n",
+ tv1.tv_jiff, tv1.tv_usec);
+ printk(KERN_DEBUG "Timers done %is %06i\n",
+ tv2.tv_jiff, tv2.tv_usec);
DP(printk("buf0:\n");
printk(buf0);
printk("buf1:\n");
@@ -919,9 +826,9 @@ static void fast_timer_test(void)
printk("%-10s set: %6is %06ius exp: %6is %06ius "
"data: 0x%08X func: 0x%08X\n",
t->name,
- t->tv_set.tv_sec,
+ t->tv_set.tv_jiff,
t->tv_set.tv_usec,
- t->tv_expires.tv_sec,
+ t->tv_expires.tv_jiff,
t->tv_expires.tv_usec,
t->data,
t->function
@@ -929,10 +836,12 @@ static void fast_timer_test(void)
printk(" del: %6ius did exp: %6is %06ius as #%i error: %6li\n",
t->delay_us,
- tv_exp[j].tv_sec,
+ tv_exp[j].tv_jiff,
tv_exp[j].tv_usec,
exp_num[j],
- (tv_exp[j].tv_sec - t->tv_expires.tv_sec)*1000000 + tv_exp[j].tv_usec - t->tv_expires.tv_usec);
+ (tv_exp[j].tv_jiff - t->tv_expires.tv_jiff) *
+ 1000000 + tv_exp[j].tv_usec -
+ t->tv_expires.tv_usec);
}
proc_fasttimer_read(buf5, NULL, 0, 0, 0);
printk("buf5 after all done:\n");
@@ -942,7 +851,7 @@ static void fast_timer_test(void)
#endif
-void fast_timer_init(void)
+int fast_timer_init(void)
{
/* For some reason, request_irq() hangs when called froom time_init() */
if (!fast_timer_is_init)
@@ -975,4 +884,6 @@ void fast_timer_init(void)
fast_timer_test();
#endif
}
+ return 0;
}
+__initcall(fast_timer_init);
diff --git a/arch/cris/arch-v10/kernel/io_interface_mux.c b/arch/cris/arch-v10/kernel/io_interface_mux.c
index 29d48ad00df9..3a9114e89edf 100644
--- a/arch/cris/arch-v10/kernel/io_interface_mux.c
+++ b/arch/cris/arch-v10/kernel/io_interface_mux.c
@@ -304,7 +304,7 @@ static unsigned char clear_group_from_set(const unsigned char groups, struct if_
static struct if_group *get_group(const unsigned char groups)
{
int i;
- for (i = 0; i < sizeof(if_groups)/sizeof(struct if_group); i++) {
+ for (i = 0; i < ARRAY_SIZE(if_groups); i++) {
if (groups & if_groups[i].group) {
return &if_groups[i];
}
diff --git a/arch/cris/arch-v10/kernel/irq.c b/arch/cris/arch-v10/kernel/irq.c
index 96094cbf1255..e06ab0050d37 100644
--- a/arch/cris/arch-v10/kernel/irq.c
+++ b/arch/cris/arch-v10/kernel/irq.c
@@ -12,10 +12,16 @@
*/
#include <asm/irq.h>
+#include <asm/current.h>
#include <linux/irq.h>
+#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/init.h>
+/* From kgdb.c. */
+extern void kgdb_init(void);
+extern void breakpoint(void);
+
#define mask_irq(irq_nr) (*R_VECT_MASK_CLR = 1 << (irq_nr));
#define unmask_irq(irq_nr) (*R_VECT_MASK_SET = 1 << (irq_nr));
@@ -75,8 +81,8 @@ BUILD_IRQ(12, 0x1000)
BUILD_IRQ(13, 0x2000)
void mmu_bus_fault(void); /* IRQ 14 is the bus fault interrupt */
void multiple_interrupt(void); /* IRQ 15 is the multiple IRQ interrupt */
-BUILD_IRQ(16, 0x10000)
-BUILD_IRQ(17, 0x20000)
+BUILD_IRQ(16, 0x10000 | 0x20000) /* ethernet tx interrupt needs to block rx */
+BUILD_IRQ(17, 0x20000 | 0x10000) /* ...and vice versa */
BUILD_IRQ(18, 0x40000)
BUILD_IRQ(19, 0x80000)
BUILD_IRQ(20, 0x100000)
@@ -147,6 +153,55 @@ void system_call(void); /* from entry.S */
void do_sigtrap(void); /* from entry.S */
void gdb_handle_breakpoint(void); /* from entry.S */
+extern void do_IRQ(int irq, struct pt_regs * regs);
+
+/* Handle multiple IRQs */
+void do_multiple_IRQ(struct pt_regs* regs)
+{
+ int bit;
+ unsigned masked;
+ unsigned mask;
+ unsigned ethmask = 0;
+
+ /* Get interrupts to mask and handle */
+ mask = masked = *R_VECT_MASK_RD;
+
+ /* Never mask timer IRQ */
+ mask &= ~(IO_MASK(R_VECT_MASK_RD, timer0));
+
+ /*
+ * If either ethernet interrupt (rx or tx) is active then block
+ * the other one too. Unblock afterwards also.
+ */
+ if (mask &
+ (IO_STATE(R_VECT_MASK_RD, dma0, active) |
+ IO_STATE(R_VECT_MASK_RD, dma1, active))) {
+ ethmask = (IO_MASK(R_VECT_MASK_RD, dma0) |
+ IO_MASK(R_VECT_MASK_RD, dma1));
+ }
+
+ /* Block them */
+ *R_VECT_MASK_CLR = (mask | ethmask);
+
+ /* An extra irq_enter here to prevent softIRQs to run after
+ * each do_IRQ. This will decrease the interrupt latency.
+ */
+ irq_enter();
+
+ /* Handle all IRQs */
+ for (bit = 2; bit < 32; bit++) {
+ if (masked & (1 << bit)) {
+ do_IRQ(bit, regs);
+ }
+ }
+
+ /* This irq_exit() will trigger the soft IRQs. */
+ irq_exit();
+
+ /* Unblock the IRQs again */
+ *R_VECT_MASK_SET = (masked | ethmask);
+}
+
/* init_IRQ() is called by start_kernel and is responsible for fixing IRQ masks and
setting the irq vector table.
*/
@@ -169,7 +224,7 @@ init_IRQ(void)
for (i = 0; i < 256; i++)
etrax_irv->v[i] = weird_irq;
- /* Initialize IRQ handler descriptiors. */
+ /* Initialize IRQ handler descriptors. */
for(i = 2; i < NR_IRQS; i++) {
irq_desc[i].chip = &crisv10_irq_type;
set_int_vector(i, interrupt[i]);
diff --git a/arch/cris/arch-v10/kernel/kgdb.c b/arch/cris/arch-v10/kernel/kgdb.c
index 07628a13c6c4..77f4b1423725 100644
--- a/arch/cris/arch-v10/kernel/kgdb.c
+++ b/arch/cris/arch-v10/kernel/kgdb.c
@@ -959,7 +959,7 @@ stub_is_stopped(int sigval)
/* Send register contents. We probably only need to send the
* PC, frame pointer and stack pointer here. Other registers will be
- * explicitely asked for. But for now, send all.
+ * explicitly asked for. But for now, send all.
*/
for (regno = R0; regno <= USP; regno++) {
diff --git a/arch/cris/arch-v10/kernel/process.c b/arch/cris/arch-v10/kernel/process.c
index b6831ceb6a62..1a3760c94f85 100644
--- a/arch/cris/arch-v10/kernel/process.c
+++ b/arch/cris/arch-v10/kernel/process.c
@@ -64,7 +64,7 @@ void hard_reset_now (void)
#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
cause_of_death = 0xbedead;
#else
- /* Since we dont plan to keep on reseting the watchdog,
+ /* Since we dont plan to keep on resetting the watchdog,
the key can be arbitrary hence three */
*R_WATCHDOG = IO_FIELD(R_WATCHDOG, key, 3) |
IO_STATE(R_WATCHDOG, enable, start);
diff --git a/arch/cris/arch-v10/kernel/ptrace.c b/arch/cris/arch-v10/kernel/ptrace.c
index f4f9db698b44..b570ae9b6cad 100644
--- a/arch/cris/arch-v10/kernel/ptrace.c
+++ b/arch/cris/arch-v10/kernel/ptrace.c
@@ -177,10 +177,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
ret = 0;
break;
- case PTRACE_DETACH:
- ret = ptrace_detach(child, data);
- break;
-
/* Get all GP registers from the child. */
case PTRACE_GETREGS: {
int i;
diff --git a/arch/cris/arch-v10/kernel/setup.c b/arch/cris/arch-v10/kernel/setup.c
index 682ef955aec4..de27b50b72a2 100644
--- a/arch/cris/arch-v10/kernel/setup.c
+++ b/arch/cris/arch-v10/kernel/setup.c
@@ -13,6 +13,7 @@
#include <linux/seq_file.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
+#include <linux/param.h>
#ifdef CONFIG_PROC_FS
#define HAS_FPU 0x0001
@@ -56,8 +57,8 @@ int show_cpuinfo(struct seq_file *m, void *v)
revision = rdvr();
- if (revision >= sizeof cpu_info/sizeof *cpu_info)
- info = &cpu_info[sizeof cpu_info/sizeof *cpu_info - 1];
+ if (revision >= ARRAY_SIZE(cpu_info))
+ info = &cpu_info[ARRAY_SIZE(cpu_info) - 1];
else
info = &cpu_info[revision];
diff --git a/arch/cris/arch-v10/kernel/shadows.c b/arch/cris/arch-v10/kernel/shadows.c
index 38fd44dfbc5b..326178aef6ee 100644
--- a/arch/cris/arch-v10/kernel/shadows.c
+++ b/arch/cris/arch-v10/kernel/shadows.c
@@ -20,7 +20,7 @@ unsigned long r_timer_ctrl_shadow;
* These are only usable if there actually IS a latch connected
* to the corresponding external chip-select pin.
*
- * A common usage is that CSP0 controls LED's and CSP4 video chips.
+ * A common usage is that CSP0 controls LEDs and CSP4 video chips.
*/
unsigned long port_cse1_shadow;
diff --git a/arch/cris/arch-v10/kernel/time.c b/arch/cris/arch-v10/kernel/time.c
index 077e973c33f0..5976f6199c47 100644
--- a/arch/cris/arch-v10/kernel/time.c
+++ b/arch/cris/arch-v10/kernel/time.c
@@ -1,5 +1,4 @@
-/* $Id: time.c,v 1.5 2004/09/29 06:12:46 starvik Exp $
- *
+/*
* linux/arch/cris/arch-v10/kernel/time.c
*
* Copyright (C) 1991, 1992, 1995 Linus Torvalds
@@ -20,6 +19,7 @@
#include <asm/io.h>
#include <asm/delay.h>
#include <asm/rtc.h>
+#include <asm/irq_regs.h>
/* define this if you need to use print_timestamp */
/* it will make jiffies at 96 hz instead of 100 hz though */
@@ -201,8 +201,9 @@ static long last_rtc_update = 0;
extern void cris_do_profile(struct pt_regs *regs);
static inline irqreturn_t
-timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+timer_interrupt(int irq, void *dev_id)
{
+ struct pt_regs *regs = get_irq_regs();
/* acknowledge the timer irq */
#ifdef USE_CASCADE_TIMERS
@@ -221,9 +222,11 @@ timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
#endif
/* reset watchdog otherwise it resets us! */
-
reset_watchdog();
+ /* Update statistics. */
+ update_process_times(user_mode(regs));
+
/* call the real timer interrupt handler */
do_timer(1);
@@ -254,8 +257,12 @@ timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
* it needs to be IRQF_DISABLED to make the jiffies update work properly
*/
-static struct irqaction irq2 = { timer_interrupt, IRQF_SHARED | IRQF_DISABLED,
- CPU_MASK_NONE, "timer", NULL, NULL};
+static struct irqaction irq2 = {
+ .handler = timer_interrupt,
+ .flags = IRQF_SHARED | IRQF_DISABLED,
+ .mask = CPU_MASK_NONE,
+ .name = "timer",
+};
void __init
time_init(void)
diff --git a/arch/cris/arch-v10/lib/dram_init.S b/arch/cris/arch-v10/lib/dram_init.S
index 9cf83932cd5d..6a6bdfd6984d 100644
--- a/arch/cris/arch-v10/lib/dram_init.S
+++ b/arch/cris/arch-v10/lib/dram_init.S
@@ -40,7 +40,7 @@
* Copy warning from head.S about r8 and r9
*
* Revision 1.7 2001/04/18 12:05:39 bjornw
- * Fixed comments, and explicitely include config.h to be sure its there
+ * Fixed comments, and explicitly include config.h to be sure its there
*
* Revision 1.6 2001/04/10 06:20:16 starvik
* Delay should be 200us, not 200ns
@@ -66,7 +66,7 @@
*/
/* Just to be certain the config file is included, we include it here
- * explicitely instead of depending on it being included in the file that
+ * explicitly instead of depending on it being included in the file that
* uses this code.
*/
diff --git a/arch/cris/arch-v10/lib/memset.c b/arch/cris/arch-v10/lib/memset.c
index 82bb66839171..42c1101043a3 100644
--- a/arch/cris/arch-v10/lib/memset.c
+++ b/arch/cris/arch-v10/lib/memset.c
@@ -66,7 +66,7 @@ void *memset(void *pdst,
{
register char *dst __asm__ ("r13") = pdst;
-
+
/* This is NONPORTABLE, but since this whole routine is */
/* grossly nonportable that doesn't matter. */
@@ -110,52 +110,52 @@ void *memset(void *pdst,
If you want to check that the allocation was right; then
check the equalities in the first comment. It should say
"r13=r13, r12=r12, r11=r11" */
- __asm__ volatile ("
- ;; Check that the following is true (same register names on
- ;; both sides of equal sign, as in r8=r8):
- ;; %0=r13, %1=r12, %4=r11
- ;;
- ;; Save the registers we'll clobber in the movem process
- ;; on the stack. Don't mention them to gcc, it will only be
- ;; upset.
- subq 11*4,$sp
- movem $r10,[$sp]
-
- move.d $r11,$r0
- move.d $r11,$r1
- move.d $r11,$r2
- move.d $r11,$r3
- move.d $r11,$r4
- move.d $r11,$r5
- move.d $r11,$r6
- move.d $r11,$r7
- move.d $r11,$r8
- move.d $r11,$r9
- move.d $r11,$r10
-
- ;; Now we've got this:
- ;; r13 - dst
- ;; r12 - n
-
- ;; Update n for the first loop
- subq 12*4,$r12
-0:
- subq 12*4,$r12
- bge 0b
- movem $r11,[$r13+]
-
- addq 12*4,$r12 ;; compensate for last loop underflowing n
-
- ;; Restore registers from stack
- movem [$sp+],$r10"
+ __asm__ volatile ("\n\
+ ;; Check that the following is true (same register names on \n\
+ ;; both sides of equal sign, as in r8=r8): \n\
+ ;; %0=r13, %1=r12, %4=r11 \n\
+ ;; \n\
+ ;; Save the registers we'll clobber in the movem process \n\
+ ;; on the stack. Don't mention them to gcc, it will only be \n\
+ ;; upset. \n\
+ subq 11*4,$sp \n\
+ movem $r10,[$sp] \n\
+ \n\
+ move.d $r11,$r0 \n\
+ move.d $r11,$r1 \n\
+ move.d $r11,$r2 \n\
+ move.d $r11,$r3 \n\
+ move.d $r11,$r4 \n\
+ move.d $r11,$r5 \n\
+ move.d $r11,$r6 \n\
+ move.d $r11,$r7 \n\
+ move.d $r11,$r8 \n\
+ move.d $r11,$r9 \n\
+ move.d $r11,$r10 \n\
+ \n\
+ ;; Now we've got this: \n\
+ ;; r13 - dst \n\
+ ;; r12 - n \n\
+ \n\
+ ;; Update n for the first loop \n\
+ subq 12*4,$r12 \n\
+0: \n\
+ subq 12*4,$r12 \n\
+ bge 0b \n\
+ movem $r11,[$r13+] \n\
+ \n\
+ addq 12*4,$r12 ;; compensate for last loop underflowing n \n\
+ \n\
+ ;; Restore registers from stack \n\
+ movem [$sp+],$r10"
/* Outputs */ : "=r" (dst), "=r" (n)
/* Inputs */ : "0" (dst), "1" (n), "r" (lc));
-
+
}
/* Either we directly starts copying, using dword copying
- in a loop, or we copy as much as possible with 'movem'
+ in a loop, or we copy as much as possible with 'movem'
and then the last block (<44 bytes) is copied here.
This will work since 'movem' will have updated src,dst,n. */
diff --git a/arch/cris/arch-v10/lib/string.c b/arch/cris/arch-v10/lib/string.c
index 8ffde4901b57..7161a2bef4fe 100644
--- a/arch/cris/arch-v10/lib/string.c
+++ b/arch/cris/arch-v10/lib/string.c
@@ -41,7 +41,7 @@ void *memcpy(void *pdst,
Make sure the compiler is able to make something useful of this.
As it is now: r10 -> r13; r11 -> r11 (nop); r12 -> r12 (nop).
- If gcc was allright, it really would need no temporaries, and no
+ If gcc was alright, it really would need no temporaries, and no
stack space to save stuff on. */
register void *return_dst __asm__ ("r10") = pdst;
@@ -95,33 +95,33 @@ void *memcpy(void *pdst,
If you want to check that the allocation was right; then
check the equalities in the first comment. It should say
"r13=r13, r11=r11, r12=r12" */
- __asm__ volatile ("
- ;; Check that the following is true (same register names on
- ;; both sides of equal sign, as in r8=r8):
- ;; %0=r13, %1=r11, %2=r12
- ;;
- ;; Save the registers we'll use in the movem process
- ;; on the stack.
- subq 11*4,$sp
- movem $r10,[$sp]
-
- ;; Now we've got this:
- ;; r11 - src
- ;; r13 - dst
- ;; r12 - n
-
- ;; Update n for the first loop
- subq 44,$r12
-0:
- movem [$r11+],$r10
- subq 44,$r12
- bge 0b
- movem $r10,[$r13+]
-
- addq 44,$r12 ;; compensate for last loop underflowing n
-
- ;; Restore registers from stack
- movem [$sp+],$r10"
+ __asm__ volatile ("\n\
+ ;; Check that the following is true (same register names on \n\
+ ;; both sides of equal sign, as in r8=r8): \n\
+ ;; %0=r13, %1=r11, %2=r12 \n\
+ ;; \n\
+ ;; Save the registers we'll use in the movem process \n\
+ ;; on the stack. \n\
+ subq 11*4,$sp \n\
+ movem $r10,[$sp] \n\
+ \n\
+ ;; Now we've got this: \n\
+ ;; r11 - src \n\
+ ;; r13 - dst \n\
+ ;; r12 - n \n\
+ \n\
+ ;; Update n for the first loop \n\
+ subq 44,$r12 \n\
+0: \n\
+ movem [$r11+],$r10 \n\
+ subq 44,$r12 \n\
+ bge 0b \n\
+ movem $r10,[$r13+] \n\
+ \n\
+ addq 44,$r12 ;; compensate for last loop underflowing n \n\
+ \n\
+ ;; Restore registers from stack \n\
+ movem [$sp+],$r10"
/* Outputs */ : "=r" (dst), "=r" (src), "=r" (n)
/* Inputs */ : "0" (dst), "1" (src), "2" (n));
diff --git a/arch/cris/arch-v10/lib/usercopy.c b/arch/cris/arch-v10/lib/usercopy.c
index 43778d53c254..b8e6c0430e5b 100644
--- a/arch/cris/arch-v10/lib/usercopy.c
+++ b/arch/cris/arch-v10/lib/usercopy.c
@@ -38,7 +38,7 @@ __copy_user (void __user *pdst, const void *psrc, unsigned long pn)
As it is now: r10 -> r13; r11 -> r11 (nop); r12 -> r12 (nop).
FIXME: Comment for old gcc version. Check.
- If gcc was allright, it really would need no temporaries, and no
+ If gcc was alright, it really would need no temporaries, and no
stack space to save stuff on. */
register char *dst __asm__ ("r13") = pdst;
@@ -92,58 +92,58 @@ __copy_user (void __user *pdst, const void *psrc, unsigned long pn)
.ifnc %0%1%2%3,$r13$r11$r12$r10 \n\
.err \n\
.endif \n\
-
- ;; Save the registers we'll use in the movem process
- ;; on the stack.
- subq 11*4,$sp
- movem $r10,[$sp]
-
- ;; Now we've got this:
- ;; r11 - src
- ;; r13 - dst
- ;; r12 - n
-
- ;; Update n for the first loop
- subq 44,$r12
-
-; Since the noted PC of a faulting instruction in a delay-slot of a taken
-; branch, is that of the branch target, we actually point at the from-movem
-; for this case. There is no ambiguity here; if there was a fault in that
-; instruction (meaning a kernel oops), the faulted PC would be the address
-; after *that* movem.
-
-0:
- movem [$r11+],$r10
- subq 44,$r12
- bge 0b
- movem $r10,[$r13+]
-1:
- addq 44,$r12 ;; compensate for last loop underflowing n
-
- ;; Restore registers from stack
- movem [$sp+],$r10
-2:
- .section .fixup,\"ax\"
-
-; To provide a correct count in r10 of bytes that failed to be copied,
-; we jump back into the loop if the loop-branch was taken. There is no
-; performance penalty for sany use; the program will segfault soon enough.
-
-3:
- move.d [$sp],$r10
- addq 44,$r10
- move.d $r10,[$sp]
- jump 0b
-4:
- movem [$sp+],$r10
- addq 44,$r10
- addq 44,$r12
- jump 2b
-
- .previous
- .section __ex_table,\"a\"
- .dword 0b,3b
- .dword 1b,4b
+ \n\
+ ;; Save the registers we'll use in the movem process \n\
+ ;; on the stack. \n\
+ subq 11*4,$sp \n\
+ movem $r10,[$sp] \n\
+ \n\
+ ;; Now we've got this: \n\
+ ;; r11 - src \n\
+ ;; r13 - dst \n\
+ ;; r12 - n \n\
+ \n\
+ ;; Update n for the first loop \n\
+ subq 44,$r12 \n\
+ \n\
+; Since the noted PC of a faulting instruction in a delay-slot of a taken \n\
+; branch, is that of the branch target, we actually point at the from-movem \n\
+; for this case. There is no ambiguity here; if there was a fault in that \n\
+; instruction (meaning a kernel oops), the faulted PC would be the address \n\
+; after *that* movem. \n\
+ \n\
+0: \n\
+ movem [$r11+],$r10 \n\
+ subq 44,$r12 \n\
+ bge 0b \n\
+ movem $r10,[$r13+] \n\
+1: \n\
+ addq 44,$r12 ;; compensate for last loop underflowing n \n\
+ \n\
+ ;; Restore registers from stack \n\
+ movem [$sp+],$r10 \n\
+2: \n\
+ .section .fixup,\"ax\" \n\
+ \n\
+; To provide a correct count in r10 of bytes that failed to be copied, \n\
+; we jump back into the loop if the loop-branch was taken. There is no \n\
+; performance penalty for sany use; the program will segfault soon enough.\n\
+ \n\
+3: \n\
+ move.d [$sp],$r10 \n\
+ addq 44,$r10 \n\
+ move.d $r10,[$sp] \n\
+ jump 0b \n\
+4: \n\
+ movem [$sp+],$r10 \n\
+ addq 44,$r10 \n\
+ addq 44,$r12 \n\
+ jump 2b \n\
+ \n\
+ .previous \n\
+ .section __ex_table,\"a\" \n\
+ .dword 0b,3b \n\
+ .dword 1b,4b \n\
.previous"
/* Outputs */ : "=r" (dst), "=r" (src), "=r" (n), "=r" (retn)
@@ -200,7 +200,7 @@ __copy_user_zeroing (void __user *pdst, const void *psrc, unsigned long pn)
As it is now: r10 -> r13; r11 -> r11 (nop); r12 -> r12 (nop).
FIXME: Comment for old gcc version. Check.
- If gcc was allright, it really would need no temporaries, and no
+ If gcc was alright, it really would need no temporaries, and no
stack space to save stuff on. */
register char *dst __asm__ ("r13") = pdst;
@@ -253,59 +253,59 @@ __copy_user_zeroing (void __user *pdst, const void *psrc, unsigned long pn)
If you want to check that the allocation was right; then
check the equalities in the first comment. It should say
"r13=r13, r11=r11, r12=r12" */
- __asm__ volatile ("
+ __asm__ volatile ("\n\
.ifnc %0%1%2%3,$r13$r11$r12$r10 \n\
.err \n\
.endif \n\
-
- ;; Save the registers we'll use in the movem process
- ;; on the stack.
- subq 11*4,$sp
- movem $r10,[$sp]
-
- ;; Now we've got this:
- ;; r11 - src
- ;; r13 - dst
- ;; r12 - n
-
- ;; Update n for the first loop
- subq 44,$r12
-0:
- movem [$r11+],$r10
-1:
- subq 44,$r12
- bge 0b
- movem $r10,[$r13+]
-
- addq 44,$r12 ;; compensate for last loop underflowing n
-
- ;; Restore registers from stack
- movem [$sp+],$r10
-4:
- .section .fixup,\"ax\"
-
-;; Do not jump back into the loop if we fail. For some uses, we get a
-;; page fault somewhere on the line. Without checking for page limits,
-;; we don't know where, but we need to copy accurately and keep an
-;; accurate count; not just clear the whole line. To do that, we fall
-;; down in the code below, proceeding with smaller amounts. It should
-;; be kept in mind that we have to cater to code like what at one time
-;; was in fs/super.c:
-;; i = size - copy_from_user((void *)page, data, size);
-;; which would cause repeated faults while clearing the remainder of
-;; the SIZE bytes at PAGE after the first fault.
-;; A caveat here is that we must not fall through from a failing page
-;; to a valid page.
-
-3:
- movem [$sp+],$r10
- addq 44,$r12 ;; Get back count before faulting point.
- subq 44,$r11 ;; Get back pointer to faulting movem-line.
- jump 4b ;; Fall through, pretending the fault didn't happen.
-
- .previous
- .section __ex_table,\"a\"
- .dword 1b,3b
+ \n\
+ ;; Save the registers we'll use in the movem process \n\
+ ;; on the stack. \n\
+ subq 11*4,$sp \n\
+ movem $r10,[$sp] \n\
+ \n\
+ ;; Now we've got this: \n\
+ ;; r11 - src \n\
+ ;; r13 - dst \n\
+ ;; r12 - n \n\
+ \n\
+ ;; Update n for the first loop \n\
+ subq 44,$r12 \n\
+0: \n\
+ movem [$r11+],$r10 \n\
+1: \n\
+ subq 44,$r12 \n\
+ bge 0b \n\
+ movem $r10,[$r13+] \n\
+ \n\
+ addq 44,$r12 ;; compensate for last loop underflowing n \n\
+ \n\
+ ;; Restore registers from stack \n\
+ movem [$sp+],$r10 \n\
+4: \n\
+ .section .fixup,\"ax\" \n\
+ \n\
+;; Do not jump back into the loop if we fail. For some uses, we get a \n\
+;; page fault somewhere on the line. Without checking for page limits, \n\
+;; we don't know where, but we need to copy accurately and keep an \n\
+;; accurate count; not just clear the whole line. To do that, we fall \n\
+;; down in the code below, proceeding with smaller amounts. It should \n\
+;; be kept in mind that we have to cater to code like what at one time \n\
+;; was in fs/super.c: \n\
+;; i = size - copy_from_user((void *)page, data, size); \n\
+;; which would cause repeated faults while clearing the remainder of \n\
+;; the SIZE bytes at PAGE after the first fault. \n\
+;; A caveat here is that we must not fall through from a failing page \n\
+;; to a valid page. \n\
+ \n\
+3: \n\
+ movem [$sp+],$r10 \n\
+ addq 44,$r12 ;; Get back count before faulting point. \n\
+ subq 44,$r11 ;; Get back pointer to faulting movem-line. \n\
+ jump 4b ;; Fall through, pretending the fault didn't happen.\n\
+ \n\
+ .previous \n\
+ .section __ex_table,\"a\" \n\
+ .dword 1b,3b \n\
.previous"
/* Outputs */ : "=r" (dst), "=r" (src), "=r" (n), "=r" (retn)
@@ -380,7 +380,7 @@ __do_clear_user (void __user *pto, unsigned long pn)
As it is now: r10 -> r13; r11 -> r11 (nop); r12 -> r12 (nop).
FIXME: Comment for old gcc version. Check.
- If gcc was allright, it really would need no temporaries, and no
+ If gcc was alright, it really would need no temporaries, and no
stack space to save stuff on. */
register char *dst __asm__ ("r13") = pto;
@@ -425,64 +425,64 @@ __do_clear_user (void __user *pto, unsigned long pn)
If you want to check that the allocation was right; then
check the equalities in the first comment. It should say
something like "r13=r13, r11=r11, r12=r12". */
- __asm__ volatile ("
+ __asm__ volatile ("\n\
.ifnc %0%1%2,$r13$r12$r10 \n\
.err \n\
.endif \n\
-
- ;; Save the registers we'll clobber in the movem process
- ;; on the stack. Don't mention them to gcc, it will only be
- ;; upset.
- subq 11*4,$sp
- movem $r10,[$sp]
-
- clear.d $r0
- clear.d $r1
- clear.d $r2
- clear.d $r3
- clear.d $r4
- clear.d $r5
- clear.d $r6
- clear.d $r7
- clear.d $r8
- clear.d $r9
- clear.d $r10
- clear.d $r11
-
- ;; Now we've got this:
- ;; r13 - dst
- ;; r12 - n
-
- ;; Update n for the first loop
- subq 12*4,$r12
-0:
- subq 12*4,$r12
- bge 0b
- movem $r11,[$r13+]
-1:
- addq 12*4,$r12 ;; compensate for last loop underflowing n
-
- ;; Restore registers from stack
- movem [$sp+],$r10
-2:
- .section .fixup,\"ax\"
-3:
- move.d [$sp],$r10
- addq 12*4,$r10
- move.d $r10,[$sp]
- clear.d $r10
- jump 0b
-
-4:
- movem [$sp+],$r10
- addq 12*4,$r10
- addq 12*4,$r12
- jump 2b
-
- .previous
- .section __ex_table,\"a\"
- .dword 0b,3b
- .dword 1b,4b
+ \n\
+ ;; Save the registers we'll clobber in the movem process \n\
+ ;; on the stack. Don't mention them to gcc, it will only be \n\
+ ;; upset. \n\
+ subq 11*4,$sp \n\
+ movem $r10,[$sp] \n\
+ \n\
+ clear.d $r0 \n\
+ clear.d $r1 \n\
+ clear.d $r2 \n\
+ clear.d $r3 \n\
+ clear.d $r4 \n\
+ clear.d $r5 \n\
+ clear.d $r6 \n\
+ clear.d $r7 \n\
+ clear.d $r8 \n\
+ clear.d $r9 \n\
+ clear.d $r10 \n\
+ clear.d $r11 \n\
+ \n\
+ ;; Now we've got this: \n\
+ ;; r13 - dst \n\
+ ;; r12 - n \n\
+ \n\
+ ;; Update n for the first loop \n\
+ subq 12*4,$r12 \n\
+0: \n\
+ subq 12*4,$r12 \n\
+ bge 0b \n\
+ movem $r11,[$r13+] \n\
+1: \n\
+ addq 12*4,$r12 ;; compensate for last loop underflowing n\n\
+ \n\
+ ;; Restore registers from stack \n\
+ movem [$sp+],$r10 \n\
+2: \n\
+ .section .fixup,\"ax\" \n\
+3: \n\
+ move.d [$sp],$r10 \n\
+ addq 12*4,$r10 \n\
+ move.d $r10,[$sp] \n\
+ clear.d $r10 \n\
+ jump 0b \n\
+ \n\
+4: \n\
+ movem [$sp+],$r10 \n\
+ addq 12*4,$r10 \n\
+ addq 12*4,$r12 \n\
+ jump 2b \n\
+ \n\
+ .previous \n\
+ .section __ex_table,\"a\" \n\
+ .dword 0b,3b \n\
+ .dword 1b,4b \n\
.previous"
/* Outputs */ : "=r" (dst), "=r" (n), "=r" (retn)
diff --git a/arch/cris/arch-v32/boot/compressed/misc.c b/arch/cris/arch-v32/boot/compressed/misc.c
index 11902697196d..0169ba1ca9c9 100644
--- a/arch/cris/arch-v32/boot/compressed/misc.c
+++ b/arch/cris/arch-v32/boot/compressed/misc.c
@@ -8,7 +8,7 @@
*
* malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
* puts by Nick Holloway 1993, better puts by Martin Mares 1995
- * adoptation for Linux/CRIS Axis Communications AB, 1999
+ * adaptation for Linux/CRIS Axis Communications AB, 1999
*
*/
@@ -151,7 +151,7 @@ serout(const char *s, reg_scope_instances regi_ser)
do {
rs = REG_RD(ser, regi_ser, rs_stat_din);
}
- while (!rs.tr_rdy);/* Wait for tranceiver. */
+ while (!rs.tr_rdy);/* Wait for transceiver. */
REG_WR(ser, regi_ser, rw_dout, dout);
}
@@ -264,7 +264,7 @@ serial_setup(reg_scope_instances regi_ser)
tr_ctrl.stop_bits = 1; /* 2 stop bits. */
/*
- * The baudrate setup is a bit fishy, but in the end the tranceiver is
+ * The baudrate setup is a bit fishy, but in the end the transceiver is
* set to 4800 and the receiver to 115200. The magic value is
* 29.493 MHz.
*/
diff --git a/arch/cris/arch-v32/drivers/Kconfig b/arch/cris/arch-v32/drivers/Kconfig
index cc6ba5423754..7f72d7c9e1ce 100644
--- a/arch/cris/arch-v32/drivers/Kconfig
+++ b/arch/cris/arch-v32/drivers/Kconfig
@@ -362,8 +362,6 @@ config ETRAX_AXISFLASHMAP
select MTD
select MTD_CFI
select MTD_CFI_AMDSTD
- select MTD_OBSOLETE_CHIPS
- select MTD_AMDSTD
select MTD_CHAR
select MTD_BLOCK
select MTD_PARTITIONS
diff --git a/arch/cris/arch-v32/drivers/axisflashmap.c b/arch/cris/arch-v32/drivers/axisflashmap.c
index 5180d45412fc..c5ff95e18269 100644
--- a/arch/cris/arch-v32/drivers/axisflashmap.c
+++ b/arch/cris/arch-v32/drivers/axisflashmap.c
@@ -190,13 +190,12 @@ static struct mtd_info *probe_cs(struct map_info *map_cs)
"%s: Probing a 0x%08lx bytes large window at 0x%08lx.\n",
map_cs->name, map_cs->size, map_cs->map_priv_1);
-#ifdef CONFIG_MTD_AMDSTD
- mtd_cs = do_map_probe("amd_flash", map_cs);
-#endif
#ifdef CONFIG_MTD_CFI
- if (!mtd_cs) {
mtd_cs = do_map_probe("cfi_probe", map_cs);
- }
+#endif
+#ifdef CONFIG_MTD_JEDECPROBE
+ if (!mtd_cs)
+ mtd_cs = do_map_probe("jedec_probe", map_cs);
#endif
return mtd_cs;
@@ -205,7 +204,7 @@ static struct mtd_info *probe_cs(struct map_info *map_cs)
/*
* Probe each chip select individually for flash chips. If there are chips on
* both cse0 and cse1, the mtd_info structs will be concatenated to one struct
- * so that MTD partitions can cross chip boundries.
+ * so that MTD partitions can cross chip boundaries.
*
* The only known restriction to how you can mount your chips is that each
* chip select must hold similar flash chips. But you need external hardware
diff --git a/arch/cris/arch-v32/drivers/i2c.c b/arch/cris/arch-v32/drivers/i2c.c
index e12f6cc6f4a2..f1edd2e359b2 100644
--- a/arch/cris/arch-v32/drivers/i2c.c
+++ b/arch/cris/arch-v32/drivers/i2c.c
@@ -275,7 +275,7 @@ i2c_getack(void)
ack = 0;
i2c_delay(CLOCK_HIGH_TIME/2);
if(!ack){
- if(!i2c_getbit()) /* receiver pulld SDA low */
+ if(!i2c_getbit()) /* receiver pulled SDA low */
ack = 1;
i2c_delay(CLOCK_HIGH_TIME/2);
}
diff --git a/arch/cris/arch-v32/drivers/nandflash.c b/arch/cris/arch-v32/drivers/nandflash.c
index 93ddea4d9564..5ce015c6bb0d 100644
--- a/arch/cris/arch-v32/drivers/nandflash.c
+++ b/arch/cris/arch-v32/drivers/nandflash.c
@@ -138,7 +138,7 @@ struct mtd_info* __init crisv32_nand_flash_probe (void)
/* Enable the following for a flash based bad block table */
this->options = NAND_USE_FLASH_BBT;
- /* Scan to find existance of the device */
+ /* Scan to find existence of the device */
if (nand_scan (crisv32_mtd, 1)) {
err = -ENXIO;
goto out_ior;
diff --git a/arch/cris/arch-v32/drivers/pcf8563.c b/arch/cris/arch-v32/drivers/pcf8563.c
index da479a14f836..6dbd700d3d66 100644
--- a/arch/cris/arch-v32/drivers/pcf8563.c
+++ b/arch/cris/arch-v32/drivers/pcf8563.c
@@ -4,7 +4,7 @@
* From Phillips' datasheet:
*
* The PCF8563 is a CMOS real-time clock/calendar optimized for low power
- * consumption. A programmable clock output, interupt output and voltage
+ * consumption. A programmable clock output, interrupt output and voltage
* low detector are also provided. All address and data are transferred
* serially via two-line bidirectional I2C-bus. Maximum bus speed is
* 400 kbits/s. The built-in word address register is incremented
diff --git a/arch/cris/arch-v32/drivers/sync_serial.c b/arch/cris/arch-v32/drivers/sync_serial.c
index df89298aafc4..d581b0a92a3f 100644
--- a/arch/cris/arch-v32/drivers/sync_serial.c
+++ b/arch/cris/arch-v32/drivers/sync_serial.c
@@ -185,7 +185,7 @@ static struct sync_port ports[]=
}
};
-#define NUMBER_OF_PORTS (sizeof(ports)/sizeof(sync_port))
+#define NUMBER_OF_PORTS ARRAY_SIZE(ports)
static const struct file_operations sync_serial_fops = {
.owner = THIS_MODULE,
diff --git a/arch/cris/arch-v32/kernel/cache.c b/arch/cris/arch-v32/kernel/cache.c
new file mode 100644
index 000000000000..80da7b88a72b
--- /dev/null
+++ b/arch/cris/arch-v32/kernel/cache.c
@@ -0,0 +1,33 @@
+#include <linux/module.h>
+#include <asm/io.h>
+#include <asm/arch/cache.h>
+#include <asm/arch/hwregs/dma.h>
+
+/* This file is used to workaround a cache bug, Guinness TR 106. */
+
+inline void flush_dma_descr(struct dma_descr_data *descr, int flush_buf)
+{
+ /* Flush descriptor to make sure we get correct in_eop and after. */
+ asm volatile ("ftagd [%0]" :: "r" (descr));
+ /* Flush buffer pointed out by descriptor. */
+ if (flush_buf)
+ cris_flush_cache_range(phys_to_virt((unsigned)descr->buf),
+ (unsigned)(descr->after - descr->buf));
+}
+EXPORT_SYMBOL(flush_dma_descr);
+
+void flush_dma_list(struct dma_descr_data *descr)
+{
+ while (1) {
+ flush_dma_descr(descr, 1);
+ if (descr->eol)
+ break;
+ descr = phys_to_virt((unsigned)descr->next);
+ }
+}
+EXPORT_SYMBOL(flush_dma_list);
+
+/* From cacheflush.S */
+EXPORT_SYMBOL(cris_flush_cache);
+/* From cacheflush.S */
+EXPORT_SYMBOL(cris_flush_cache_range);
diff --git a/arch/cris/arch-v32/kernel/cacheflush.S b/arch/cris/arch-v32/kernel/cacheflush.S
new file mode 100644
index 000000000000..956e8fb82f01
--- /dev/null
+++ b/arch/cris/arch-v32/kernel/cacheflush.S
@@ -0,0 +1,94 @@
+ .global cris_flush_cache_range
+cris_flush_cache_range:
+ move.d 1024, $r12
+ cmp.d $r11, $r12
+ bhi cris_flush_1KB
+ nop
+ add.d $r10, $r11
+ ftagd [$r10]
+cris_flush_last:
+ addq 32, $r10
+ cmp.d $r11, $r10
+ blt cris_flush_last
+ ftagd [$r10]
+ ret
+ nop
+cris_flush_1KB:
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ba cris_flush_cache_range
+ sub.d $r12, $r11
+
+ .global cris_flush_cache
+cris_flush_cache:
+ moveq 0, $r10
+cris_flush_line:
+ move.d 16*1024, $r11
+ addq 16, $r10
+ cmp.d $r10, $r11
+ blt cris_flush_line
+ fidxd [$r10]
+ ret
+ nop
diff --git a/arch/cris/arch-v32/kernel/fasttimer.c b/arch/cris/arch-v32/kernel/fasttimer.c
index 79e1e4c2ca1d..b40551f9f40d 100644
--- a/arch/cris/arch-v32/kernel/fasttimer.c
+++ b/arch/cris/arch-v32/kernel/fasttimer.c
@@ -97,7 +97,7 @@
* with time based on jiffies and *R_TIMER0_DATA, uses a table
* for fast conversion of timer value to microseconds.
* (Much faster the standard do_gettimeofday() and we don't really
- * wan't to use the true time - we wan't the "uptime" so timers don't screw up
+ * want to use the true time - we want the "uptime" so timers don't screw up
* when we change the time.
* TODO: Add efficient support for continuous timers as well.
*
diff --git a/arch/cris/arch-v32/kernel/io.c b/arch/cris/arch-v32/kernel/io.c
index dfbfcb8d2585..a22a9e02e093 100644
--- a/arch/cris/arch-v32/kernel/io.c
+++ b/arch/cris/arch-v32/kernel/io.c
@@ -49,7 +49,7 @@ struct crisv32_ioport crisv32_ioports[] =
}
};
-#define NBR_OF_PORTS sizeof(crisv32_ioports)/sizeof(struct crisv32_ioport)
+#define NBR_OF_PORTS ARRAY_SIZE(crisv32_ioports)
struct crisv32_iopin crisv32_led1_green;
struct crisv32_iopin crisv32_led1_red;
diff --git a/arch/cris/arch-v32/kernel/irq.c b/arch/cris/arch-v32/kernel/irq.c
index cc361bf578ae..a9acaa270243 100644
--- a/arch/cris/arch-v32/kernel/irq.c
+++ b/arch/cris/arch-v32/kernel/irq.c
@@ -140,7 +140,7 @@ block_irq(int irq, int cpu)
spin_lock_irqsave(&irq_lock, flags);
intr_mask = REG_RD_INT(intr_vect, irq_regs[cpu], rw_mask);
- /* Remember; 1 let thru, 0 block. */
+ /* Remember; 1 let through, 0 block. */
intr_mask &= ~(1 << (irq - FIRST_IRQ));
REG_WR_INT(intr_vect, irq_regs[cpu], rw_mask, intr_mask);
@@ -156,7 +156,7 @@ unblock_irq(int irq, int cpu)
spin_lock_irqsave(&irq_lock, flags);
intr_mask = REG_RD_INT(intr_vect, irq_regs[cpu], rw_mask);
- /* Remember; 1 let thru, 0 block. */
+ /* Remember; 1 let through, 0 block. */
intr_mask |= (1 << (irq - FIRST_IRQ));
REG_WR_INT(intr_vect, irq_regs[cpu], rw_mask, intr_mask);
@@ -308,7 +308,7 @@ crisv32_do_multiple(struct pt_regs* regs)
*/
irq_enter();
- /* Get which IRQs that happend. */
+ /* Get which IRQs that happened. */
masked = REG_RD_INT(intr_vect, irq_regs[cpu], r_masked_vect);
/* Calculate new IRQ mask with these IRQs disabled. */
@@ -366,7 +366,7 @@ init_IRQ(void)
for (i = 0; i < 256; i++)
etrax_irv->v[i] = weird_irq;
- /* Point all IRQ's to bad handlers. */
+ /* Point all IRQs to bad handlers. */
for (i = FIRST_IRQ, j = 0; j < NR_IRQS; i++, j++) {
irq_desc[j].chip = &crisv32_irq_type;
set_exception_vector(i, interrupt[j]);
diff --git a/arch/cris/arch-v32/kernel/process.c b/arch/cris/arch-v32/kernel/process.c
index 6326351af252..b72a15580dc7 100644
--- a/arch/cris/arch-v32/kernel/process.c
+++ b/arch/cris/arch-v32/kernel/process.c
@@ -162,7 +162,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
/* Put the switch stack right below the pt_regs. */
swstack = ((struct switch_stack *) childregs) - 1;
- /* Paramater to ret_from_sys_call. 0 is don't restart the syscall. */
+ /* Parameter to ret_from_sys_call. 0 is don't restart the syscall. */
swstack->r9 = 0;
/*
diff --git a/arch/cris/arch-v32/kernel/ptrace.c b/arch/cris/arch-v32/kernel/ptrace.c
index 38ece0cd47cb..2df60529a8af 100644
--- a/arch/cris/arch-v32/kernel/ptrace.c
+++ b/arch/cris/arch-v32/kernel/ptrace.c
@@ -245,10 +245,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
}
- case PTRACE_DETACH:
- ret = ptrace_detach(child, data);
- break;
-
/* Get all GP registers from the child. */
case PTRACE_GETREGS: {
int i;
diff --git a/arch/cris/arch-v32/kernel/setup.c b/arch/cris/arch-v32/kernel/setup.c
index 4662f363df63..72e9e8331f63 100644
--- a/arch/cris/arch-v32/kernel/setup.c
+++ b/arch/cris/arch-v32/kernel/setup.c
@@ -54,12 +54,10 @@ show_cpuinfo(struct seq_file *m, void *v)
{
int i;
int cpu = (int)v - 1;
- int entries;
unsigned long revision;
struct cpu_info *info;
- entries = sizeof cpinfo / sizeof(struct cpu_info);
- info = &cpinfo[entries - 1];
+ info = &cpinfo[ARRAY_SIZE(cpinfo) - 1];
#ifdef CONFIG_SMP
if (!cpu_online(cpu))
@@ -68,7 +66,7 @@ show_cpuinfo(struct seq_file *m, void *v)
revision = rdvr();
- for (i = 0; i < entries; i++) {
+ for (i = 0; i < ARRAY_SIZE(cpinfo); i++) {
if (cpinfo[i].rev == revision) {
info = &cpinfo[i];
break;
diff --git a/arch/cris/arch-v32/kernel/signal.c b/arch/cris/arch-v32/kernel/signal.c
index 7cd6ac803409..024cc6901974 100644
--- a/arch/cris/arch-v32/kernel/signal.c
+++ b/arch/cris/arch-v32/kernel/signal.c
@@ -347,7 +347,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
/* Grab and setup a signal frame.
*
* Basically a lot of state-info is stacked, and arranged for the
- * user-mode program to return to the kernel using either a trampiline
+ * user-mode program to return to the kernel using either a trampoline
* which performs the syscall sigreturn(), or a provided user-mode
* trampoline.
*/
@@ -641,7 +641,7 @@ ugdb_trap_user(struct thread_info *ti, int sig)
user_regs(ti)->spc = 0;
}
/* FIXME: Filter out false h/w breakpoint hits (i.e. EDA
- not withing any configured h/w breakpoint range). Synchronize with
+ not within any configured h/w breakpoint range). Synchronize with
what already exists for kernel debugging. */
if (((user_regs(ti)->exs & 0xff00) >> 8) == BREAK_8_INTR_VECT) {
/* Break 8: subtract 2 from ERP unless in a delay slot. */
diff --git a/arch/cris/arch-v32/kernel/smp.c b/arch/cris/arch-v32/kernel/smp.c
index 77e655f26560..171c96e0a5d3 100644
--- a/arch/cris/arch-v32/kernel/smp.c
+++ b/arch/cris/arch-v32/kernel/smp.c
@@ -63,8 +63,12 @@ static unsigned long irq_regs[NR_CPUS] =
static irqreturn_t crisv32_ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int send_ipi(int vector, int wait, cpumask_t cpu_mask);
-static struct irqaction irq_ipi = { crisv32_ipi_interrupt, IRQF_DISABLED,
- CPU_MASK_NONE, "ipi", NULL, NULL};
+static struct irqaction irq_ipi = {
+ .handler = crisv32_ipi_interrupt,
+ .flags = IRQF_DISABLED,
+ .mask = CPU_MASK_NONE,
+ .name = "ipi",
+};
extern void cris_mmu_init(void);
extern void cris_timer_init(void);
@@ -138,7 +142,7 @@ smp_boot_one_cpu(int cpuid)
return -1;
}
-/* Secondary CPUs starts uing C here. Here we need to setup CPU
+/* Secondary CPUs starts using C here. Here we need to setup CPU
* specific stuff such as the local timer and the MMU. */
void __init smp_callin(void)
{
diff --git a/arch/cris/arch-v32/kernel/time.c b/arch/cris/arch-v32/kernel/time.c
index be0a01657d4f..2f7e8e200f2c 100644
--- a/arch/cris/arch-v32/kernel/time.c
+++ b/arch/cris/arch-v32/kernel/time.c
@@ -99,7 +99,7 @@ unsigned long do_slow_gettimeoffset(void)
/* From timer MDS describing the hardware watchdog:
* 4.3.1 Watchdog Operation
* The watchdog timer is an 8-bit timer with a configurable start value.
- * Once started the whatchdog counts downwards with a frequency of 763 Hz
+ * Once started the watchdog counts downwards with a frequency of 763 Hz
* (100/131072 MHz). When the watchdog counts down to 1, it generates an
* NMI (Non Maskable Interrupt), and when it counts down to 0, it resets the
* chip.
diff --git a/arch/cris/arch-v32/kernel/traps.c b/arch/cris/arch-v32/kernel/traps.c
index 2462b1ef1fbb..17fd3dbd1c80 100644
--- a/arch/cris/arch-v32/kernel/traps.c
+++ b/arch/cris/arch-v32/kernel/traps.c
@@ -105,7 +105,7 @@ bad_value:
/*
* This gets called from entry.S when the watchdog has bitten. Show something
- * similiar to an Oops dump, and if the kernel if configured to be a nice doggy;
+ * similar to an Oops dump, and if the kernel is configured to be a nice doggy;
* halt instead of reboot.
*/
void
diff --git a/arch/cris/arch-v32/lib/dram_init.S b/arch/cris/arch-v32/lib/dram_init.S
index 158b3dbb4d9d..218fbe259ee5 100644
--- a/arch/cris/arch-v32/lib/dram_init.S
+++ b/arch/cris/arch-v32/lib/dram_init.S
@@ -12,7 +12,7 @@
*/
/* Just to be certain the config file is included, we include it here
- * explicitely instead of depending on it being included in the file that
+ * explicitly instead of depending on it being included in the file that
* uses this code.
*/
diff --git a/arch/cris/arch-v32/lib/string.c b/arch/cris/arch-v32/lib/string.c
index 98e282ac824a..6740b2cebae5 100644
--- a/arch/cris/arch-v32/lib/string.c
+++ b/arch/cris/arch-v32/lib/string.c
@@ -41,7 +41,7 @@ void *memcpy(void *pdst,
Make sure the compiler is able to make something useful of this.
As it is now: r10 -> r13; r11 -> r11 (nop); r12 -> r12 (nop).
- If gcc was allright, it really would need no temporaries, and no
+ If gcc was alright, it really would need no temporaries, and no
stack space to save stuff on. */
register void *return_dst __asm__ ("r10") = pdst;
diff --git a/arch/cris/arch-v32/lib/usercopy.c b/arch/cris/arch-v32/lib/usercopy.c
index f0b08460c1be..04d0cf35a276 100644
--- a/arch/cris/arch-v32/lib/usercopy.c
+++ b/arch/cris/arch-v32/lib/usercopy.c
@@ -34,7 +34,7 @@ __copy_user (void __user *pdst, const void *psrc, unsigned long pn)
As it is now: r10 -> r13; r11 -> r11 (nop); r12 -> r12 (nop).
FIXME: Comment for old gcc version. Check.
- If gcc was allright, it really would need no temporaries, and no
+ If gcc was alright, it really would need no temporaries, and no
stack space to save stuff on. */
register char *dst __asm__ ("r13") = pdst;
@@ -168,7 +168,7 @@ __copy_user_zeroing (void __user *pdst, const void *psrc, unsigned long pn)
As it is now: r10 -> r13; r11 -> r11 (nop); r12 -> r12 (nop).
FIXME: Comment for old gcc version. Check.
- If gcc was allright, it really would need no temporaries, and no
+ If gcc was alright, it really would need no temporaries, and no
stack space to save stuff on. */
register char *dst __asm__ ("r13") = pdst;
@@ -332,7 +332,7 @@ __do_clear_user (void __user *pto, unsigned long pn)
As it is now: r10 -> r13; r11 -> r11 (nop); r12 -> r12 (nop).
FIXME: Comment for old gcc version. Check.
- If gcc was allright, it really would need no temporaries, and no
+ If gcc was alright, it really would need no temporaries, and no
stack space to save stuff on. */
register char *dst __asm__ ("r13") = pto;
diff --git a/arch/cris/arch-v32/mm/tlb.c b/arch/cris/arch-v32/mm/tlb.c
index c2d12e9c40d7..a076ef6e9389 100644
--- a/arch/cris/arch-v32/mm/tlb.c
+++ b/arch/cris/arch-v32/mm/tlb.c
@@ -30,8 +30,8 @@ do { \
* The TLB can host up to 256 different mm contexts at the same time. The running
* context is found in the PID register. Each TLB entry contains a page_id that
* has to match the PID register to give a hit. page_id_map keeps track of which
- * mm's is assigned to which page_id's, making sure it's known when to
- * invalidate TLB entries.
+ * mm is assigned to which page_id, making sure it's known when to invalidate TLB
+ * entries.
*
* The last page_id is never running, it is used as an invalid page_id so that
* it's possible to make TLB entries that will nerver match.
@@ -188,7 +188,7 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
spin_unlock(&mmu_context_lock);
/*
- * Remember the pgd for the fault handlers. Keep a seperate copy of it
+ * Remember the pgd for the fault handlers. Keep a separate copy of it
* because current and active_mm might be invalid at points where
* there's still a need to derefer the pgd.
*/
diff --git a/arch/cris/defconfig b/arch/cris/defconfig
index 142a10818af3..9c33ae659934 100644
--- a/arch/cris/defconfig
+++ b/arch/cris/defconfig
@@ -226,8 +226,6 @@ CONFIG_MTD_CFI_UTIL=y
CONFIG_MTD_RAM=y
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-CONFIG_MTD_OBSOLETE_CHIPS=y
-CONFIG_MTD_AMDSTD=y
# CONFIG_MTD_SHARP is not set
# CONFIG_MTD_JEDEC is not set
@@ -276,6 +274,7 @@ CONFIG_MTDRAM_ABS_POS=0x0
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_UB is not set
CONFIG_BLK_DEV_RAM=y
@@ -302,16 +301,14 @@ CONFIG_IOSCHED_CFQ=y
#
# ATA/ATAPI/MFM/RLL support
#
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDE=y
+# CONFIG_IDE is not set
+# CONFIG_PARIDE is not set
#
# Please see Documentation/ide.txt for help/info on IDE drives
#
# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
# CONFIG_IDEDISK_MULTI_MODE is not set
-CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
# CONFIG_IDE_TASK_IOCTL is not set
@@ -321,7 +318,6 @@ CONFIG_BLK_DEV_IDECD=y
#
# CONFIG_IDE_GENERIC is not set
# CONFIG_IDE_ARM is not set
-CONFIG_BLK_DEV_IDEDMA=y
# CONFIG_IDEDMA_AUTO is not set
# CONFIG_BLK_DEV_HD is not set
@@ -329,6 +325,7 @@ CONFIG_BLK_DEV_IDEDMA=y
# SCSI device support
#
# CONFIG_SCSI is not set
+# CONFIG_ISCSI_TCP is not set
#
# IEEE 1394 (FireWire) support
@@ -414,26 +411,11 @@ CONFIG_NETFILTER=y
# CONFIG_NET_POLL_CONTROLLER is not set
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
-CONFIG_BT=y
-CONFIG_BT_L2CAP=y
-# CONFIG_BT_SCO is not set
-CONFIG_BT_RFCOMM=y
-# CONFIG_BT_RFCOMM_TTY is not set
-CONFIG_BT_BNEP=y
-# CONFIG_BT_BNEP_MC_FILTER is not set
-# CONFIG_BT_BNEP_PROTO_FILTER is not set
-# CONFIG_BT_HIDP is not set
-
-#
-# Bluetooth device drivers
-#
-CONFIG_BT_HCIUSB=y
-# CONFIG_BT_HCIUSB_SCO is not set
-# CONFIG_BT_HCIUART is not set
-# CONFIG_BT_HCIBCM203X is not set
-# CONFIG_BT_HCIBPA10X is not set
-# CONFIG_BT_HCIBFUSB is not set
-# CONFIG_BT_HCIVHCI is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_AF_RXRPC_DEBUG is not set
+# CONFIG_BT is not set
+# CONFIG_I2C is not set
+
CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
@@ -485,31 +467,17 @@ CONFIG_NET_ETHERNET=y
#
# Input device support
#
-CONFIG_INPUT=y
-
-#
-# 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_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
+# CONFIG_INPUT is not set
#
# Input I/O drivers
#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
CONFIG_SERIO=y
# CONFIG_SERIO_I8042 is not set
# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_CT82C710 is not set
-CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_LIBPS2 is not set
# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
#
# Input Device Drivers
@@ -525,6 +493,7 @@ CONFIG_MOUSE_PS2=y
# CONFIG_MOUSE_SERIAL 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
@@ -542,6 +511,8 @@ CONFIG_MOUSE_PS2=y
#
# Non-8250 serial port support
#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -559,6 +530,8 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_GEN_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
+# CONFIG_RTC_LIB is not set
+# CONFIG_RTC_CLASS is not set
#
# Ftape, the floppy tape device driver
@@ -660,7 +633,9 @@ CONFIG_NFS_V3=y
# CONFIG_NFSD is not set
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -686,9 +661,21 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SOUND is not set
#
+# Generic devices
+#
+# CONFIG_SND_MPU401_UART is not set
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
+# CONFIG_PARPORT_PC_PCMCIA is not set
+# CONFIG_NET_PCMCIA is not set
#
# PC-card bridges
@@ -734,6 +721,7 @@ CONFIG_USB_DEVICEFS=y
# USB Input Devices
#
# CONFIG_USB_HID is not set
+# HID_SUPPORT is not set
#
# USB HID Boot Protocol drivers
@@ -829,7 +817,7 @@ CONFIG_USB_RTL8150=y
#
# Hardware crypto devices
-#
+# CONFIG_CRYPTO_HW is not set
#
# Library routines
diff --git a/arch/cris/kernel/crisksyms.c b/arch/cris/kernel/crisksyms.c
index 105bb5ed48f7..62f0e752915a 100644
--- a/arch/cris/kernel/crisksyms.c
+++ b/arch/cris/kernel/crisksyms.c
@@ -27,6 +27,7 @@ extern void __Mod(void);
extern void __ashldi3(void);
extern void __ashrdi3(void);
extern void __lshrdi3(void);
+extern void __negdi2(void);
extern void iounmap(volatile void * __iomem);
/* Platform dependent support */
@@ -34,19 +35,6 @@ EXPORT_SYMBOL(kernel_thread);
EXPORT_SYMBOL(get_cmos_time);
EXPORT_SYMBOL(loops_per_usec);
-/* String functions */
-EXPORT_SYMBOL(memcmp);
-EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(strcpy);
-EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strcmp);
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strncat);
-EXPORT_SYMBOL(strncmp);
-EXPORT_SYMBOL(strncpy);
-
/* Math functions */
EXPORT_SYMBOL(__Udiv);
EXPORT_SYMBOL(__Umod);
@@ -55,6 +43,7 @@ EXPORT_SYMBOL(__Mod);
EXPORT_SYMBOL(__ashldi3);
EXPORT_SYMBOL(__ashrdi3);
EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(__negdi2);
/* Memory functions */
EXPORT_SYMBOL(__ioremap);
@@ -84,4 +73,4 @@ EXPORT_SYMBOL(start_one_shot_timer);
EXPORT_SYMBOL(del_fast_timer);
EXPORT_SYMBOL(schedule_usleep);
#endif
-
+EXPORT_SYMBOL(csum_partial);
diff --git a/arch/cris/kernel/irq.c b/arch/cris/kernel/irq.c
index 903ea62c6e21..2dfac8c79090 100644
--- a/arch/cris/kernel/irq.c
+++ b/arch/cris/kernel/irq.c
@@ -2,12 +2,12 @@
*
* linux/arch/cris/kernel/irq.c
*
- * Copyright (c) 2000,2001 Axis Communications AB
+ * Copyright (c) 2000,2007 Axis Communications AB
*
* Authors: Bjorn Wesen (bjornw@axis.com)
*
* This file contains the code used by various IRQ handling routines:
- * asking for different IRQ's should be done through these routines
+ * asking for different IRQs should be done through these routines
* instead of just grabbing them. Thus setups with different IRQ numbers
* shouldn't result in any weird surprises, and installing new handlers
* should be easier.
@@ -15,7 +15,7 @@
*/
/*
- * IRQ's are in fact implemented a bit like signal handlers for the kernel.
+ * IRQs are in fact implemented a bit like signal handlers for the kernel.
* Naturally it's not a 1:1 relation, but there are similarities.
*/
@@ -83,23 +83,25 @@ skip:
/* called by the assembler IRQ entry functions defined in irq.h
- * to dispatch the interrupts to registred handlers
+ * to dispatch the interrupts to registered handlers
* interrupts are disabled upon entry - depending on if the
- * interrupt was registred with IRQF_DISABLED or not, interrupts
+ * interrupt was registered with IRQF_DISABLED or not, interrupts
* are re-enabled or not.
*/
asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
{
unsigned long sp;
+ struct pt_regs *old_regs = set_irq_regs(regs);
irq_enter();
sp = rdsp();
if (unlikely((sp & (PAGE_SIZE - 1)) < (PAGE_SIZE/8))) {
printk("do_IRQ: stack overflow: %lX\n", sp);
show_stack(NULL, (unsigned long *)sp);
}
- __do_IRQ(irq, regs);
+ __do_IRQ(irq);
irq_exit();
+ set_irq_regs(old_regs);
}
void weird_irq(void)
diff --git a/arch/cris/kernel/process.c b/arch/cris/kernel/process.c
index 123451c44154..9ca558fc5bc8 100644
--- a/arch/cris/kernel/process.c
+++ b/arch/cris/kernel/process.c
@@ -195,6 +195,11 @@ EXPORT_SYMBOL(enable_hlt);
*/
void (*pm_idle)(void);
+extern void default_idle(void);
+
+void (*pm_power_off)(void);
+EXPORT_SYMBOL(pm_power_off);
+
/*
* The idle thread. There's no useful work to be
* done, so just try to conserve power and have a
diff --git a/arch/cris/kernel/ptrace.c b/arch/cris/kernel/ptrace.c
index 1085d037027b..3ccd20e85dce 100644
--- a/arch/cris/kernel/ptrace.c
+++ b/arch/cris/kernel/ptrace.c
@@ -81,13 +81,13 @@
/* notification of userspace execution resumption
* - triggered by current->work.notify_resume
*/
-extern int do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs);
+extern int do_signal(int canrestart, struct pt_regs *regs);
-void do_notify_resume(int canrestart, sigset_t *oldset, struct pt_regs *regs,
+void do_notify_resume(int canrestart, struct pt_regs *regs,
__u32 thread_info_flags )
{
/* deal with pending signal delivery */
if (thread_info_flags & _TIF_SIGPENDING)
- do_signal(canrestart,oldset,regs);
+ do_signal(canrestart,regs);
}
diff --git a/arch/cris/kernel/sys_cris.c b/arch/cris/kernel/sys_cris.c
index 0aa0e0ebb3a9..8b9984197edc 100644
--- a/arch/cris/kernel/sys_cris.c
+++ b/arch/cris/kernel/sys_cris.c
@@ -13,6 +13,7 @@
#include <linux/sched.h>
#include <linux/syscalls.h>
#include <linux/mm.h>
+#include <linux/fs.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/sem.h>
@@ -21,9 +22,9 @@
#include <linux/stat.h>
#include <linux/mman.h>
#include <linux/file.h>
+#include <linux/ipc.h>
#include <asm/uaccess.h>
-#include <asm/ipc.h>
#include <asm/segment.h>
/*
diff --git a/arch/cris/kernel/time.c b/arch/cris/kernel/time.c
index acfd04559405..7a2cc7efbcf8 100644
--- a/arch/cris/kernel/time.c
+++ b/arch/cris/kernel/time.c
@@ -171,10 +171,6 @@ get_cmos_time(void)
mon = CMOS_READ(RTC_MONTH);
year = CMOS_READ(RTC_YEAR);
- printk(KERN_DEBUG
- "rtc: sec 0x%x min 0x%x hour 0x%x day 0x%x mon 0x%x year 0x%x\n",
- sec, min, hour, day, mon, year);
-
BCD_TO_BIN(sec);
BCD_TO_BIN(min);
BCD_TO_BIN(hour);
@@ -207,12 +203,12 @@ void
cris_do_profile(struct pt_regs* regs)
{
-#if CONFIG_SYSTEM_PROFILER
+#ifdef CONFIG_SYSTEM_PROFILER
cris_profile_sample(regs);
#endif
-#if CONFIG_PROFILING
- profile_tick(CPU_PROFILING, regs);
+#ifdef CONFIG_PROFILING
+ profile_tick(CPU_PROFILING);
#endif
}
diff --git a/arch/cris/mm/fault.c b/arch/cris/mm/fault.c
index 8672ab7d7978..3034f3ff950c 100644
--- a/arch/cris/mm/fault.c
+++ b/arch/cris/mm/fault.c
@@ -13,7 +13,7 @@
* Fixed warning.
*
* Revision 1.18 2005/01/12 08:10:14 starvik
- * Readded the change of frametype when handling kernel page fault fixup
+ * Re-added the change of frametype when handling kernel page fault fixup
* for v10. This is necessary to avoid that the CPU remakes the faulting
* access.
*
@@ -49,7 +49,7 @@
*
* Revision 1.8 2003/07/04 13:02:48 tobiasa
* Moved code snippet from arch/cris/mm/fault.c that searches for fixup code
- * to seperate function in arch-specific files.
+ * to separate function in arch-specific files.
*
* Revision 1.7 2003/01/22 06:48:38 starvik
* Fixed warnings issued by GCC 3.2.1
@@ -360,7 +360,7 @@ do_page_fault(unsigned long address, struct pt_regs *regs,
up_read(&mm->mmap_sem);
printk("VM: killing process %s\n", tsk->comm);
if (user_mode(regs))
- do_exit(SIGKILL);
+ do_group_exit(SIGKILL);
goto no_context;
do_sigbus:
diff --git a/arch/cris/mm/init.c b/arch/cris/mm/init.c
index b7842ff213a6..0c833d176226 100644
--- a/arch/cris/mm/init.c
+++ b/arch/cris/mm/init.c
@@ -8,7 +8,7 @@
*
* $Log: init.c,v $
* Revision 1.11 2004/05/28 09:28:56 starvik
- * Calculation of loops_per_usec moved because initalization order has changed
+ * Calculation of loops_per_usec moved because initialization order has changed
* in Linux 2.6.
*
* Revision 1.10 2004/05/14 07:58:05 starvik
diff --git a/arch/cris/mm/tlb.c b/arch/cris/mm/tlb.c
index c4a98e2e529e..b7f8de576777 100644
--- a/arch/cris/mm/tlb.c
+++ b/arch/cris/mm/tlb.c
@@ -16,7 +16,7 @@
/* The TLB can host up to 64 different mm contexts at the same time.
* The running context is R_MMU_CONTEXT, and each TLB entry contains a
* page_id that has to match to give a hit. In page_id_map, we keep track
- * of which mm's we have assigned which page_id's, so that we know when
+ * of which mm we have assigned to which page_id, so that we know when
* to invalidate TLB entries.
*
* The last page_id is never running - it is used as an invalid page_id
diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig
index 74eef7111f2b..43153e767bb1 100644
--- a/arch/frv/Kconfig
+++ b/arch/frv/Kconfig
@@ -375,6 +375,8 @@ source "drivers/Kconfig"
source "fs/Kconfig"
+source "kernel/Kconfig.instrumentation"
+
source "arch/frv/Kconfig.debug"
source "security/Kconfig"
diff --git a/arch/frv/Makefile b/arch/frv/Makefile
index 9bf7345c5cc9..310c47a663f8 100644
--- a/arch/frv/Makefile
+++ b/arch/frv/Makefile
@@ -39,13 +39,13 @@ endif
ARCHMODFLAGS += -G0 -mlong-calls
ifdef CONFIG_GPREL_DATA_8
-CFLAGS += -G8
+KBUILD_CFLAGS += -G8
else
ifdef CONFIG_GPREL_DATA_4
-CFLAGS += -G4
+KBUILD_CFLAGS += -G4
else
ifdef CONFIG_GPREL_DATA_NONE
-CFLAGS += -G0
+KBUILD_CFLAGS += -G0
endif
endif
endif
@@ -53,26 +53,26 @@ endif
#LDFLAGS_vmlinux := -Map linkmap.txt
ifdef CONFIG_GC_SECTIONS
-CFLAGS += -ffunction-sections -fdata-sections
+KBUILD_CFLAGS += -ffunction-sections -fdata-sections
LINKFLAGS += --gc-sections
endif
ifndef CONFIG_FRAME_POINTER
-CFLAGS += -mno-linked-fp
+KBUILD_CFLAGS += -mno-linked-fp
endif
ifdef CONFIG_CPU_FR451_COMPILE
-CFLAGS += -mcpu=fr450
-AFLAGS += -mcpu=fr450
+KBUILD_CFLAGS += -mcpu=fr450
+KBUILD_AFLAGS += -mcpu=fr450
ASFLAGS += -mcpu=fr450
else
ifdef CONFIG_CPU_FR551_COMPILE
-CFLAGS += -mcpu=fr550
-AFLAGS += -mcpu=fr550
+KBUILD_CFLAGS += -mcpu=fr550
+KBUILD_AFLAGS += -mcpu=fr550
ASFLAGS += -mcpu=fr550
else
-CFLAGS += -mcpu=fr400
-AFLAGS += -mcpu=fr400
+KBUILD_CFLAGS += -mcpu=fr400
+KBUILD_AFLAGS += -mcpu=fr400
ASFLAGS += -mcpu=fr400
endif
endif
@@ -80,16 +80,16 @@ endif
# pretend the kernel is going to run on an FR400 with no media-fp unit
# - reserve CC3 for use with atomic ops
# - all the extra registers are dealt with only at context switch time
-CFLAGS += -mno-fdpic -mgpr-32 -msoft-float -mno-media
-CFLAGS += -ffixed-fcc3 -ffixed-cc3 -ffixed-gr15 -ffixed-icc2
-AFLAGS += -mno-fdpic
+KBUILD_CFLAGS += -mno-fdpic -mgpr-32 -msoft-float -mno-media
+KBUILD_CFLAGS += -ffixed-fcc3 -ffixed-cc3 -ffixed-gr15 -ffixed-icc2
+KBUILD_AFLAGS += -mno-fdpic
ASFLAGS += -mno-fdpic
# make sure the .S files get compiled with debug info
# and disable optimisations that are unhelpful whilst debugging
ifdef CONFIG_DEBUG_INFO
-#CFLAGS += -O1
-AFLAGS += -Wa,--gdwarf2
+#KBUILD_CFLAGS += -O1
+KBUILD_AFLAGS += -Wa,--gdwarf2
ASFLAGS += -Wa,--gdwarf2
endif
diff --git a/arch/frv/kernel/irq-mb93091.c b/arch/frv/kernel/irq-mb93091.c
index ad753c1e9b8f..9e38f99bbab8 100644
--- a/arch/frv/kernel/irq-mb93091.c
+++ b/arch/frv/kernel/irq-mb93091.c
@@ -17,10 +17,10 @@
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/irq.h>
+#include <linux/bitops.h>
#include <asm/io.h>
#include <asm/system.h>
-#include <asm/bitops.h>
#include <asm/delay.h>
#include <asm/irq.h>
#include <asm/irc-regs.h>
diff --git a/arch/frv/kernel/irq-mb93093.c b/arch/frv/kernel/irq-mb93093.c
index e0983f6926ed..3c2752ca9775 100644
--- a/arch/frv/kernel/irq-mb93093.c
+++ b/arch/frv/kernel/irq-mb93093.c
@@ -17,10 +17,10 @@
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/irq.h>
+#include <linux/bitops.h>
#include <asm/io.h>
#include <asm/system.h>
-#include <asm/bitops.h>
#include <asm/delay.h>
#include <asm/irq.h>
#include <asm/irc-regs.h>
diff --git a/arch/frv/kernel/irq-mb93493.c b/arch/frv/kernel/irq-mb93493.c
index c157eeff871d..7754c7338e4b 100644
--- a/arch/frv/kernel/irq-mb93493.c
+++ b/arch/frv/kernel/irq-mb93493.c
@@ -17,10 +17,10 @@
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/irq.h>
+#include <linux/bitops.h>
#include <asm/io.h>
#include <asm/system.h>
-#include <asm/bitops.h>
#include <asm/delay.h>
#include <asm/irq.h>
#include <asm/irc-regs.h>
diff --git a/arch/frv/kernel/irq.c b/arch/frv/kernel/irq.c
index c7e59dcadee4..73abae767fdc 100644
--- a/arch/frv/kernel/irq.c
+++ b/arch/frv/kernel/irq.c
@@ -24,12 +24,12 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/module.h>
+#include <linux/bitops.h>
#include <asm/atomic.h>
#include <asm/io.h>
#include <asm/smp.h>
#include <asm/system.h>
-#include <asm/bitops.h>
#include <asm/uaccess.h>
#include <asm/pgalloc.h>
#include <asm/delay.h>
@@ -134,7 +134,7 @@ static struct irq_chip frv_cpu_pic = {
};
/*
- * handles all normal device IRQ's
+ * handles all normal device IRQs
* - registers are referred to by the __frame variable (GR28)
* - IRQ distribution is complicated in this arch because of the many PICs, the
* way they work and the way they cascade
diff --git a/arch/frv/kernel/semaphore.c b/arch/frv/kernel/semaphore.c
index 8e182ced1a0f..7ee3a147b471 100644
--- a/arch/frv/kernel/semaphore.c
+++ b/arch/frv/kernel/semaphore.c
@@ -139,7 +139,7 @@ void __up(struct semaphore *sem)
waiter = list_entry(sem->wait_list.next, struct sem_waiter, list);
/* We must be careful not to touch 'waiter' after we set ->task = NULL.
- * It is an allocated on the waiter's stack and may become invalid at
+ * It is allocated on the waiter's stack and may become invalid at
* any time after that point (due to a wakeup from another source).
*/
list_del_init(&waiter->list);
diff --git a/arch/frv/kernel/sys_frv.c b/arch/frv/kernel/sys_frv.c
index 6fbe2665c577..04c6b1677ccf 100644
--- a/arch/frv/kernel/sys_frv.c
+++ b/arch/frv/kernel/sys_frv.c
@@ -23,10 +23,10 @@
#include <linux/file.h>
#include <linux/utsname.h>
#include <linux/syscalls.h>
+#include <linux/ipc.h>
#include <asm/setup.h>
#include <asm/uaccess.h>
-#include <asm/ipc.h>
/*
* sys_pipe() is the normal C calling standard for creating
diff --git a/arch/frv/kernel/time.c b/arch/frv/kernel/time.c
index ed588d73d7d8..925fb0199a0f 100644
--- a/arch/frv/kernel/time.c
+++ b/arch/frv/kernel/time.c
@@ -43,7 +43,10 @@ unsigned long __delay_loops_MHz;
static irqreturn_t timer_interrupt(int irq, void *dummy);
static struct irqaction timer_irq = {
- timer_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "timer", NULL, NULL
+ .handler = timer_interrupt,
+ .flags = IRQF_DISABLED,
+ .mask = CPU_MASK_NONE,
+ .name = "timer",
};
static inline int set_rtc_mmss(unsigned long nowtime)
@@ -63,7 +66,7 @@ static irqreturn_t timer_interrupt(int irq, void *dummy)
/*
* Here we are in the timer irq handler. We just have irqs locally
* disabled but we don't know if the timer_bh is running on the other
- * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
+ * CPU. We need to avoid to SMP race with it. NOTE: we don't need
* the irq version of write_lock because as just said we have irq
* locally disabled. -arca
*/
@@ -123,7 +126,7 @@ void time_init(void)
/* FIX by dqg : Set to zero for platforms that don't have tod */
/* without this time is undefined and can overflow time_t, causing */
- /* very stange errors */
+ /* very strange errors */
year = 1980;
mon = day = 1;
hour = min = sec = 0;
diff --git a/arch/frv/mb93090-mb00/pci-dma.c b/arch/frv/mb93090-mb00/pci-dma.c
index 671ce1e8434f..662f7b12d005 100644
--- a/arch/frv/mb93090-mb00/pci-dma.c
+++ b/arch/frv/mb93090-mb00/pci-dma.c
@@ -15,6 +15,7 @@
#include <linux/list.h>
#include <linux/pci.h>
#include <linux/highmem.h>
+#include <linux/scatterlist.h>
#include <asm/io.h>
void *dma_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_handle, gfp_t gfp)
@@ -86,7 +87,7 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
dampr2 = __get_DAMPR(2);
for (i = 0; i < nents; i++) {
- vaddr = kmap_atomic(sg[i].page, __KM_CACHE);
+ vaddr = kmap_atomic(sg_page(&sg[i]), __KM_CACHE);
frv_dcache_writeback((unsigned long) vaddr,
(unsigned long) vaddr + PAGE_SIZE);
diff --git a/arch/frv/mm/fault.c b/arch/frv/mm/fault.c
index 6798fa0257b1..05093d41d98e 100644
--- a/arch/frv/mm/fault.c
+++ b/arch/frv/mm/fault.c
@@ -259,7 +259,7 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear
up_read(&mm->mmap_sem);
printk("VM: killing process %s\n", current->comm);
if (user_mode(__frame))
- do_exit(SIGKILL);
+ do_group_exit(SIGKILL);
goto no_context;
do_sigbus:
diff --git a/arch/frv/mm/init.c b/arch/frv/mm/init.c
index 4103c2c487f3..b841ecfd5d5a 100644
--- a/arch/frv/mm/init.c
+++ b/arch/frv/mm/init.c
@@ -197,7 +197,7 @@ void __init mem_init(void)
/*
* free the memory that was only required for initialisation
*/
-void __init free_initmem(void)
+void free_initmem(void)
{
#if defined(CONFIG_RAMKERNEL) && !defined(CONFIG_PROTECT_KERNEL)
unsigned long start, end, addr;
diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig
index e35f74e6e505..ff6a8712bd6d 100644
--- a/arch/h8300/Kconfig
+++ b/arch/h8300/Kconfig
@@ -1,6 +1,6 @@
#
# For a description of the syntax of this configuration file,
-# see Documentation/kbuild/config-language.txt.
+# see Documentation/kbuild/kconfig-language.txt.
#
mainmenu "uClinux/h8300 (w/o MMU) Kernel Configuration"
@@ -223,6 +223,8 @@ endmenu
source "fs/Kconfig"
+source "kernel/Kconfig.instrumentation"
+
source "arch/h8300/Kconfig.debug"
source "security/Kconfig"
diff --git a/arch/h8300/Kconfig.debug b/arch/h8300/Kconfig.debug
index 996d97e953b0..ee671c3f2c74 100644
--- a/arch/h8300/Kconfig.debug
+++ b/arch/h8300/Kconfig.debug
@@ -42,16 +42,16 @@ config SH_STANDARD_BIOS
Require eCos/RedBoot
config DEFAULT_CMDLINE
- bool "Use buildin commandline"
+ bool "Use builtin commandline"
default n
help
- buildin kernel commandline enabled.
+ builtin kernel commandline enabled.
config KERNEL_COMMAND
string "Buildin commmand string"
depends on DEFAULT_CMDLINE
help
- buildin kernel commandline strings.
+ builtin kernel commandline strings.
config BLKDEV_RESERVE
bool "BLKDEV Reserved Memory"
diff --git a/arch/h8300/Makefile b/arch/h8300/Makefile
index 53b5c1edf596..a556447877b4 100644
--- a/arch/h8300/Makefile
+++ b/arch/h8300/Makefile
@@ -30,16 +30,16 @@ ldflags-$(CONFIG_CPU_H8300H) := -mh8300helf
cflags-$(CONFIG_CPU_H8S) := -ms
ldflags-$(CONFIG_CPU_H8S) := -mh8300self
-CFLAGS += $(cflags-y)
-CFLAGS += -mint32 -fno-builtin
-CFLAGS += -g
-CFLAGS += -D__linux__
-CFLAGS += -DUTS_SYSNAME=\"uClinux\"
-AFLAGS += -DPLATFORM=$(PLATFORM) -DMODEL=$(MODEL) $(cflags-y)
+KBUILD_CFLAGS += $(cflags-y)
+KBUILD_CFLAGS += -mint32 -fno-builtin
+KBUILD_CFLAGS += -g
+KBUILD_CFLAGS += -D__linux__
+KBUILD_CFLAGS += -DUTS_SYSNAME=\"uClinux\"
+KBUILD_AFLAGS += -DPLATFORM=$(PLATFORM) -DMODEL=$(MODEL) $(cflags-y)
LDFLAGS += $(ldflags-y)
CROSS_COMPILE = h8300-elf-
-LIBGCC := $(shell $(CROSS-COMPILE)$(CC) $(CFLAGS) -print-libgcc-file-name)
+LIBGCC := $(shell $(CROSS-COMPILE)$(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
head-y := arch/$(ARCH)/platform/$(PLATFORM)/$(BOARD)/crt0_$(MODEL).o
diff --git a/arch/h8300/kernel/irq.c b/arch/h8300/kernel/irq.c
index 43d21e93f41f..8dec4dd57b4e 100644
--- a/arch/h8300/kernel/irq.c
+++ b/arch/h8300/kernel/irq.c
@@ -68,7 +68,7 @@ static void h8300_shutdown_irq(unsigned int irq)
}
/*
- * h8300 interrupt controler implementation
+ * h8300 interrupt controller implementation
*/
struct irq_chip h8300irq_chip = {
.name = "H8300-INTC",
diff --git a/arch/h8300/kernel/sys_h8300.c b/arch/h8300/kernel/sys_h8300.c
index ddc62727dc9f..00608be6d567 100644
--- a/arch/h8300/kernel/sys_h8300.c
+++ b/arch/h8300/kernel/sys_h8300.c
@@ -19,12 +19,12 @@
#include <linux/file.h>
#include <linux/utsname.h>
#include <linux/fs.h>
+#include <linux/ipc.h>
#include <asm/setup.h>
#include <asm/uaccess.h>
#include <asm/cachectl.h>
#include <asm/traps.h>
-#include <asm/ipc.h>
#include <asm/unistd.h>
/*
diff --git a/arch/h8300/kernel/time.c b/arch/h8300/kernel/time.c
index 330638220a2e..e37c835e67cf 100644
--- a/arch/h8300/kernel/time.c
+++ b/arch/h8300/kernel/time.c
@@ -53,7 +53,7 @@ void time_init(void)
/* FIX by dqg : Set to zero for platforms that don't have tod */
/* without this time is undefined and can overflow time_t, causing */
- /* very stange errors */
+ /* very strange errors */
year = 1980;
mon = day = 1;
hour = min = sec = 0;
diff --git a/arch/h8300/kernel/traps.c b/arch/h8300/kernel/traps.c
index f97183011c2c..f8f7d7ea97f1 100644
--- a/arch/h8300/kernel/traps.c
+++ b/arch/h8300/kernel/traps.c
@@ -5,7 +5,7 @@
* Cloned from Linux/m68k.
*
* No original Copyright holder listed,
- * Probabily original (C) Roman Zippel (assigned DJD, 1999)
+ * Probable original (C) Roman Zippel (assigned DJD, 1999)
*
* Copyright 1999-2000 D. Jeff Dionne, <jeff@rt-control.com>
*
diff --git a/arch/h8300/lib/Makefile b/arch/h8300/lib/Makefile
index 98272b66f4e5..1577f5075b10 100644
--- a/arch/h8300/lib/Makefile
+++ b/arch/h8300/lib/Makefile
@@ -2,7 +2,4 @@
# Makefile for H8/300-specific library files..
#
-.S.o:
- $(CC) $(AFLAGS) -D__ASSEMBLY__ -c $< -o $@
-
lib-y = ashrdi3.o checksum.o memcpy.o memset.o abs.o romfs.o
diff --git a/arch/h8300/platform/h8s/ints.c b/arch/h8300/platform/h8s/ints.c
index a71d6e2a3919..551fd5f30d82 100644
--- a/arch/h8300/platform/h8s/ints.c
+++ b/arch/h8300/platform/h8s/ints.c
@@ -179,7 +179,7 @@ int request_irq(unsigned int irq,
if (use_kmalloc)
irq_handle = kmalloc(sizeof(irq_handler_t), GFP_ATOMIC);
else {
- /* use bootmem allocater */
+ /* use bootmem allocator */
irq_handle = (irq_handler_t *)alloc_bootmem(sizeof(irq_handler_t));
irq_handle = (irq_handler_t *)((unsigned long)irq_handle | 0x80000000);
}
diff --git a/arch/h8300/platform/h8s/ints_h8s.c b/arch/h8300/platform/h8s/ints_h8s.c
index 93395d2a8a07..faa8a459d952 100644
--- a/arch/h8300/platform/h8s/ints_h8s.c
+++ b/arch/h8300/platform/h8s/ints_h8s.c
@@ -63,7 +63,7 @@ static const struct irq_pins irq_assign_table1[16]={
{H8300_GPIO_P2,H8300_GPIO_B6},{H8300_GPIO_P2,H8300_GPIO_B7},
};
-/* IRQ to GPIO pinno transrate */
+/* IRQ to GPIO pin translation */
#define IRQ_GPIO_MAP(irqbit,irq,port,bit) \
do { \
if (*(volatile unsigned short *)ITSR & irqbit) { \
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 2e6310b8eab7..bef47725d4ad 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -54,6 +54,11 @@ config ARCH_HAS_ILOG2_U64
bool
default n
+config HUGETLB_PAGE_SIZE_VARIABLE
+ bool
+ depends on HUGETLB_PAGE
+ default y
+
config GENERIC_FIND_NEXT_BIT
bool
default y
@@ -300,6 +305,9 @@ config HOTPLUG_CPU
config ARCH_ENABLE_MEMORY_HOTPLUG
def_bool y
+config ARCH_ENABLE_MEMORY_HOTREMOVE
+ def_bool y
+
config SCHED_SMT
bool "SMT scheduler support"
depends on SMP
@@ -348,6 +356,7 @@ config ARCH_FLATMEM_ENABLE
config ARCH_SPARSEMEM_ENABLE
def_bool y
depends on ARCH_DISCONTIGMEM_ENABLE
+ select SPARSEMEM_VMEMMAP_ENABLE
config ARCH_DISCONTIGMEM_DEFAULT
def_bool y if (IA64_SGI_SN2 || IA64_GENERIC || IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB)
@@ -443,9 +452,9 @@ config IA64_PALINFO
config IA64_MC_ERR_INJECT
tristate "MC error injection support"
help
- Selets whether support for MC error injection. By enabling the
- support, kernel provide sysfs interface for user application to
- call MC error injection PAL procedure to inject various errors.
+ Adds support for MC error injection. If enabled, the kernel
+ will provide a sysfs interface for user applications to
+ call MC error injection PAL procedures to inject various errors.
This is a useful tool for MCA testing.
If you're unsure, do not select this option.
@@ -482,7 +491,7 @@ config KEXEC
but it is independent of the system firmware. And like a reboot
you can start any kernel with it, not just Linux.
- The name comes from the similiarity to the exec system call.
+ The name comes from the similarity to the exec system call.
It is an ongoing process to be certain the hardware in a machine
is properly shutdown, so do not be surprised if this code does not
@@ -583,21 +592,7 @@ config IRQ_PER_CPU
source "arch/ia64/hp/sim/Kconfig"
-menu "Instrumentation Support"
- depends on EXPERIMENTAL
-
-source "arch/ia64/oprofile/Kconfig"
-
-config KPROBES
- bool "Kprobes"
- depends on KALLSYMS && MODULES
- help
- Kprobes allows you to trap at almost any kernel address and
- execute a callback function. register_kprobe() establishes
- a probepoint and specifies the callback. Kprobes is useful
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-endmenu
+source "kernel/Kconfig.instrumentation"
source "arch/ia64/Kconfig.debug"
diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile
index 21033ed83307..34951aa2370b 100644
--- a/arch/ia64/Makefile
+++ b/arch/ia64/Makefile
@@ -29,7 +29,7 @@ cflags-y := -pipe $(EXTRA) -ffixed-r13 -mfixed-range=f12-f15,f32-f127 \
CFLAGS_KERNEL := -mconstant-gp
GAS_STATUS = $(shell $(srctree)/arch/ia64/scripts/check-gas "$(CC)" "$(OBJDUMP)")
-CPPFLAGS += $(shell $(srctree)/arch/ia64/scripts/toolchain-flags "$(CC)" "$(OBJDUMP)" "$(READELF)")
+KBUILD_CPPFLAGS += $(shell $(srctree)/arch/ia64/scripts/toolchain-flags "$(CC)" "$(OBJDUMP)" "$(READELF)")
ifeq ($(GAS_STATUS),buggy)
$(error Sorry, you need a newer version of the assember, one that is built from \
@@ -44,7 +44,7 @@ ifeq ($(call cc-version),0304)
cflags-$(CONFIG_MCKINLEY) += -mtune=mckinley
endif
-CFLAGS += $(cflags-y)
+KBUILD_CFLAGS += $(cflags-y)
head-y := arch/ia64/kernel/head.o arch/ia64/kernel/init_task.o
libs-y += arch/ia64/lib/
diff --git a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig
index 449d3e75bfc2..7f6b2377d13f 100644
--- a/arch/ia64/configs/sn2_defconfig
+++ b/arch/ia64/configs/sn2_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.23-rc6
-# Tue Sep 18 11:24:01 2007
+# Linux kernel version: 2.6.23
+# Thu Oct 18 16:03:40 2007
#
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -26,7 +26,10 @@ CONFIG_TASK_IO_ACCOUNTING=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=20
+CONFIG_CGROUPS=y
CONFIG_CPUSETS=y
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_FAIR_USER_SCHED=y
CONFIG_SYSFS_DEPRECATED=y
CONFIG_RELAY=y
CONFIG_BLK_DEV_INITRD=y
@@ -47,7 +50,6 @@ CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
@@ -68,6 +70,7 @@ CONFIG_STOP_MACHINE=y
CONFIG_BLOCK=y
# CONFIG_BLK_DEV_IO_TRACE is not set
CONFIG_BLK_DEV_BSG=y
+CONFIG_BLOCK_COMPAT=y
#
# IO Schedulers
@@ -92,6 +95,7 @@ CONFIG_MMU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_HUGETLB_PAGE_SIZE_VARIABLE=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_TIME=y
@@ -112,10 +116,10 @@ CONFIG_IA64_SGI_SN2=y
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 is not set
-CONFIG_PGTABLE_4=y
+# CONFIG_IA64_PAGE_SIZE_16KB is not set
+CONFIG_IA64_PAGE_SIZE_64KB=y
+CONFIG_PGTABLE_3=y
+# CONFIG_PGTABLE_4 is not set
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
# CONFIG_HZ_300 is not set
@@ -130,6 +134,7 @@ CONFIG_SMP=y
CONFIG_NR_CPUS=1024
# CONFIG_HOTPLUG_CPU is not set
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
CONFIG_SCHED_SMT=y
CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
@@ -143,6 +148,7 @@ CONFIG_DISCONTIGMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_NEED_MULTIPLE_NODES=y
# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
CONFIG_RESOURCES_64BIT=y
@@ -170,6 +176,7 @@ CONFIG_IA64_PALINFO=y
CONFIG_IA64_MC_ERR_INJECT=y
CONFIG_SGI_SN=y
# CONFIG_IA64_ESI is not set
+# CONFIG_IA64_HP_AML_NFW is not set
#
# SN Devices
@@ -219,7 +226,6 @@ CONFIG_PCI_DOMAINS=y
CONFIG_PCI_SYSCALL=y
CONFIG_PCIEPORTBUS=y
CONFIG_HOTPLUG_PCI_PCIE=y
-# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set
CONFIG_PCIEAER=y
CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
@@ -230,10 +236,6 @@ CONFIG_HOTPLUG_PCI=y
# CONFIG_HOTPLUG_PCI_CPCI is not set
# CONFIG_HOTPLUG_PCI_SHPC is not set
CONFIG_HOTPLUG_PCI_SGI=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
# CONFIG_PCCARD is not set
#
@@ -270,6 +272,7 @@ CONFIG_INET_TUNNEL=m
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_LRO=y
CONFIG_INET_DIAG=m
CONFIG_INET_TCP_DIAG=m
# CONFIG_TCP_CONG_ADVANCED is not set
@@ -341,6 +344,7 @@ CONFIG_IPV6_SIT=m
#
# Generic Driver Options
#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=y
@@ -401,7 +405,12 @@ CONFIG_IDE_PROC_FS=y
# IDE chipset support/bugfixes
#
CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_PLATFORM is not set
# CONFIG_BLK_DEV_IDEPNP is not set
+
+#
+# PCI IDE chipsets support
+#
CONFIG_BLK_DEV_IDEPCI=y
CONFIG_IDEPCI_SHARE_IRQ=y
CONFIG_IDEPCI_PCIBUS_ORDER=y
@@ -409,8 +418,6 @@ CONFIG_IDEPCI_PCIBUS_ORDER=y
# CONFIG_BLK_DEV_GENERIC is not set
# CONFIG_BLK_DEV_OPTI621 is not set
CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-# CONFIG_IDEDMA_ONLYDISK is not set
# CONFIG_BLK_DEV_AEC62XX is not set
# CONFIG_BLK_DEV_ALI15X3 is not set
# CONFIG_BLK_DEV_AMD74XX is not set
@@ -438,7 +445,6 @@ CONFIG_BLK_DEV_SGIIOC4=y
# CONFIG_BLK_DEV_TC86C001 is not set
# CONFIG_IDE_ARM is not set
CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_IDEDMA_IVB is not set
# CONFIG_BLK_DEV_HD is not set
#
@@ -481,6 +487,7 @@ CONFIG_SCSI_SAS_ATTRS=y
CONFIG_SCSI_SAS_LIBSAS=y
# CONFIG_SCSI_SAS_ATA is not set
# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
+CONFIG_SCSI_SRP_ATTRS=y
CONFIG_SCSI_LOWLEVEL=y
CONFIG_ISCSI_TCP=m
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
@@ -491,6 +498,7 @@ CONFIG_ISCSI_TCP=m
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_AIC79XX is not set
# CONFIG_SCSI_AIC94XX 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
@@ -531,6 +539,7 @@ CONFIG_ATA_ACPI=y
# CONFIG_SATA_VIA is not set
CONFIG_SATA_VITESSE=y
# CONFIG_SATA_INIC162X is not set
+# CONFIG_PATA_ACPI is not set
# CONFIG_PATA_ALI is not set
# CONFIG_PATA_AMD is not set
# CONFIG_PATA_ARTOP is not set
@@ -555,6 +564,7 @@ CONFIG_SATA_VITESSE=y
# CONFIG_PATA_OLDPIIX is not set
# CONFIG_PATA_NETCELL is not set
# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_NS87415 is not set
# CONFIG_PATA_OPTI is not set
# CONFIG_PATA_OPTIDMA is not set
# CONFIG_PATA_PDC_OLD is not set
@@ -587,10 +597,6 @@ CONFIG_DM_MULTIPATH=m
CONFIG_DM_MULTIPATH_EMC=m
# CONFIG_DM_MULTIPATH_RDAC is not set
# CONFIG_DM_DELAY is not set
-
-#
-# Fusion MPT device support
-#
CONFIG_FUSION=y
CONFIG_FUSION_SPI=y
CONFIG_FUSION_FC=y
@@ -612,13 +618,16 @@ CONFIG_NETDEVICES=y
# 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_IP1000 is not set
# CONFIG_ARCNET is not set
# CONFIG_NET_ETHERNET is not set
CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
@@ -637,12 +646,15 @@ CONFIG_CHELSIO_T1=m
CONFIG_CHELSIO_T1_1G=y
# CONFIG_CHELSIO_T1_NAPI is not set
CONFIG_CHELSIO_T3=m
+CONFIG_IXGBE=m
# CONFIG_IXGB is not set
CONFIG_S2IO=m
# CONFIG_S2IO_NAPI is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
+# CONFIG_NIU is not set
# CONFIG_MLX4_CORE is not set
+# CONFIG_TEHUTI is not set
# CONFIG_TR is not set
#
@@ -668,6 +680,7 @@ CONFIG_S2IO=m
# CONFIG_NET_FC is not set
# CONFIG_SHAPER 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
@@ -689,7 +702,6 @@ CONFIG_INPUT_MOUSEDEV=y
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
# CONFIG_INPUT_EVDEV is not set
# CONFIG_INPUT_EVBUG is not set
@@ -713,6 +725,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# Character devices
#
CONFIG_VT=y
+# CONFIG_VT_UNICODE is not set
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
# CONFIG_VT_HW_CONSOLE_BINDING is not set
@@ -759,9 +772,6 @@ CONFIG_LEGACY_PTY_COUNT=256
CONFIG_EFI_RTC=y
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
-CONFIG_AGP=y
-CONFIG_AGP_SGI_TIOCA=y
-# CONFIG_DRM is not set
CONFIG_RAW_DRIVER=m
CONFIG_MAX_RAW_DEVS=256
# CONFIG_HPET is not set
@@ -781,6 +791,12 @@ CONFIG_DEVPORT=y
# CONFIG_HWMON is not set
#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
# Multifunction device drivers
#
# CONFIG_MFD_SM501 is not set
@@ -795,15 +811,18 @@ CONFIG_DEVPORT=y
#
# Graphics support
#
+CONFIG_AGP=y
+CONFIG_AGP_SGI_TIOCA=y
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+# CONFIG_FB is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
-# CONFIG_VGASTATE is not set
-CONFIG_VIDEO_OUTPUT_CONTROL=m
-# CONFIG_FB is not set
#
# Console display driver support
@@ -819,6 +838,7 @@ CONFIG_DUMMY_CONSOLE=y
CONFIG_HID_SUPPORT=y
CONFIG_HID=y
CONFIG_HID_DEBUG=y
+# CONFIG_HIDRAW is not set
#
# USB Input Devices
@@ -950,19 +970,6 @@ CONFIG_INFINIBAND_SRP=m
# CONFIG_RTC_CLASS is not set
#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
# Userspace I/O
#
# CONFIG_UIO is not set
@@ -1004,6 +1011,8 @@ CONFIG_XFS_RT=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_PRINT_QUOTA_WARNING=y
# CONFIG_QFMT_V1 is not set
# CONFIG_QFMT_V2 is not set
CONFIG_QUOTACTL=y
@@ -1042,7 +1051,6 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
-CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -1061,10 +1069,7 @@ CONFIG_RAMFS=y
# CONFIG_QNX4FS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
+CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=m
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
@@ -1081,6 +1086,7 @@ CONFIG_EXPORTFS=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=m
CONFIG_SUNRPC_GSS=m
+CONFIG_SUNRPC_XPRT_RDMA=m
# CONFIG_SUNRPC_BIND34 is not set
CONFIG_RPCSEC_GSS_KRB5=m
# CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -1117,10 +1123,6 @@ CONFIG_SGI_PARTITION=y
# CONFIG_KARMA_PARTITION is not set
CONFIG_EFI_PARTITION=y
# CONFIG_SYSV68_PARTITION is not set
-
-#
-# Native Language Support
-#
CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
CONFIG_NLS_CODEPAGE_437=y
@@ -1161,10 +1163,6 @@ CONFIG_NLS_ISO8859_1=y
# CONFIG_NLS_KOI8_R is not set
# CONFIG_NLS_KOI8_U is not set
CONFIG_NLS_UTF8=y
-
-#
-# Distributed Lock Manager
-#
# CONFIG_DLM is not set
#
@@ -1222,6 +1220,7 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_FAULT_INJECTION is not set
CONFIG_IA64_GRANULE_16MB=y
@@ -1237,6 +1236,7 @@ CONFIG_SYSVIPC_COMPAT=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_XOR_BLOCKS=y
CONFIG_ASYNC_CORE=y
CONFIG_ASYNC_MEMCPY=y
@@ -1261,6 +1261,7 @@ CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_CBC=m
CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_XTS is not set
# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=m
# CONFIG_CRYPTO_FCRYPT is not set
@@ -1274,9 +1275,11 @@ CONFIG_CRYPTO_DES=m
# CONFIG_CRYPTO_ARC4 is not set
# CONFIG_CRYPTO_KHAZAD is not set
# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_SEED is not set
CONFIG_CRYPTO_DEFLATE=m
# CONFIG_CRYPTO_MICHAEL_MIC is not set
CONFIG_CRYPTO_CRC32C=m
# CONFIG_CRYPTO_CAMELLIA is not set
# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO_AUTHENC is not set
# CONFIG_CRYPTO_HW is not set
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index e980e7aa2306..bc859a311eaf 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -246,7 +246,7 @@ static int reserve_sba_gart = 1;
static SBA_INLINE void sba_mark_invalid(struct ioc *, dma_addr_t, size_t);
static SBA_INLINE void sba_free_range(struct ioc *, dma_addr_t, size_t);
-#define sba_sg_address(sg) (page_address((sg)->page) + (sg)->offset)
+#define sba_sg_address(sg) sg_virt((sg))
#ifdef FULL_VALID_PDIR
static u64 prefetch_spill_page;
@@ -396,7 +396,7 @@ sba_dump_sg( struct ioc *ioc, struct scatterlist *startsg, int nents)
printk(KERN_DEBUG " %d : DMA %08lx/%05x CPU %p\n", nents,
startsg->dma_address, startsg->dma_length,
sba_sg_address(startsg));
- startsg++;
+ startsg = sg_next(startsg);
}
}
@@ -409,7 +409,7 @@ sba_check_sg( struct ioc *ioc, struct scatterlist *startsg, int nents)
while (the_nents-- > 0) {
if (sba_sg_address(the_sg) == 0x0UL)
sba_dump_sg(NULL, startsg, nents);
- the_sg++;
+ the_sg = sg_next(the_sg);
}
}
@@ -1179,7 +1179,6 @@ sba_fill_pdir(
u64 *pdirp = NULL;
unsigned long dma_offset = 0;
- dma_sg--;
while (nents-- > 0) {
int cnt = startsg->dma_length;
startsg->dma_length = 0;
@@ -1201,7 +1200,8 @@ sba_fill_pdir(
u32 pide = startsg->dma_address & ~PIDE_FLAG;
dma_offset = (unsigned long) pide & ~iovp_mask;
startsg->dma_address = 0;
- dma_sg++;
+ if (n_mappings)
+ dma_sg = sg_next(dma_sg);
dma_sg->dma_address = pide | ioc->ibase;
pdirp = &(ioc->pdir_base[pide >> iovp_shift]);
n_mappings++;
@@ -1228,7 +1228,7 @@ sba_fill_pdir(
pdirp++;
} while (cnt > 0);
}
- startsg++;
+ startsg = sg_next(startsg);
}
/* force pdir update */
wmb();
@@ -1297,7 +1297,7 @@ sba_coalesce_chunks( struct ioc *ioc,
while (--nents > 0) {
unsigned long vaddr; /* tmp */
- startsg++;
+ startsg = sg_next(startsg);
/* PARANOID */
startsg->dma_address = startsg->dma_length = 0;
@@ -1407,7 +1407,7 @@ int sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, int di
#ifdef ALLOW_IOV_BYPASS_SG
ASSERT(to_pci_dev(dev)->dma_mask);
if (likely((ioc->dma_mask & ~to_pci_dev(dev)->dma_mask) == 0)) {
- for (sg = sglist ; filled < nents ; filled++, sg++){
+ for_each_sg(sglist, sg, nents, filled) {
sg->dma_length = sg->length;
sg->dma_address = virt_to_phys(sba_sg_address(sg));
}
@@ -1501,7 +1501,7 @@ void sba_unmap_sg (struct device *dev, struct scatterlist *sglist, int nents, in
while (nents && sglist->dma_length) {
sba_unmap_single(dev, sglist->dma_address, sglist->dma_length, dir);
- sglist++;
+ sglist = sg_next(sglist);
nents--;
}
diff --git a/arch/ia64/hp/sim/boot/fw-emu.c b/arch/ia64/hp/sim/boot/fw-emu.c
index 1189d035d316..bf6d9d8c802f 100644
--- a/arch/ia64/hp/sim/boot/fw-emu.c
+++ b/arch/ia64/hp/sim/boot/fw-emu.c
@@ -285,7 +285,7 @@ sys_fw_init (const char *args, int arglen)
}
cmd_line[arglen] = '\0';
- memset(efi_systab, 0, sizeof(efi_systab));
+ memset(efi_systab, 0, sizeof(*efi_systab));
efi_systab->hdr.signature = EFI_SYSTEM_TABLE_SIGNATURE;
efi_systab->hdr.revision = ((1 << 16) | 00);
efi_systab->hdr.headersize = sizeof(efi_systab->hdr);
diff --git a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c
index d62fa76e5a7d..6ef9b5219930 100644
--- a/arch/ia64/hp/sim/simscsi.c
+++ b/arch/ia64/hp/sim/simscsi.c
@@ -131,7 +131,7 @@ simscsi_sg_readwrite (struct scsi_cmnd *sc, int mode, unsigned long offset)
stat.fd = desc[sc->device->id];
scsi_for_each_sg(sc, sl, scsi_sg_count(sc), i) {
- req.addr = __pa(page_address(sl->page) + sl->offset);
+ req.addr = __pa(sg_virt(sl));
req.len = sl->length;
if (DBG)
printk("simscsi_sg_%s @ %lx (off %lx) use_sg=%d len=%d\n",
@@ -212,7 +212,7 @@ static void simscsi_fillresult(struct scsi_cmnd *sc, char *buf, unsigned len)
if (!len)
break;
thislen = min(len, slp->length);
- memcpy(page_address(slp->page) + slp->offset, buf, thislen);
+ memcpy(sg_virt(slp), buf, thislen);
len -= thislen;
}
}
@@ -360,6 +360,7 @@ static struct scsi_host_template driver_template = {
.max_sectors = 1024,
.cmd_per_lun = SIMSCSI_REQ_QUEUE_LEN,
.use_clustering = DISABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
};
static int __init
diff --git a/arch/ia64/ia32/binfmt_elf32.c b/arch/ia64/ia32/binfmt_elf32.c
index 1cfab326fb7e..f6ae3ec93810 100644
--- a/arch/ia64/ia32/binfmt_elf32.c
+++ b/arch/ia64/ia32/binfmt_elf32.c
@@ -240,7 +240,7 @@ static int __init check_elf32_binfmt(void)
{
if (cpu_uses_ia32el()) {
printk("Please use IA-32 EL for executing IA-32 binaries\n");
- return unregister_binfmt(&elf_format);
+ unregister_binfmt(&elf_format);
}
return 0;
}
diff --git a/arch/ia64/ia32/elfcore32.h b/arch/ia64/ia32/elfcore32.h
index a47f63b204fb..446c9aac924d 100644
--- a/arch/ia64/ia32/elfcore32.h
+++ b/arch/ia64/ia32/elfcore32.h
@@ -117,6 +117,7 @@ elf_core_copy_task_fpregs(struct task_struct *tsk, struct pt_regs *regs, elf_fpr
}
#define ELF_CORE_COPY_XFPREGS 1
+#define ELF_CORE_XFPREG_TYPE NT_PRXFPREG
static inline int
elf_core_copy_task_xfpregs(struct task_struct *tsk, elf_fpxregset_t *xfpu)
{
diff --git a/arch/ia64/ia32/ia32priv.h b/arch/ia64/ia32/ia32priv.h
index 466bbcb138b2..c5c872b250da 100644
--- a/arch/ia64/ia32/ia32priv.h
+++ b/arch/ia64/ia32/ia32priv.h
@@ -290,7 +290,6 @@ struct old_linux32_dirent {
#define _ASM_IA64_ELF_H /* Don't include elf.h */
#include <linux/sched.h>
-#include <asm/processor.h>
/*
* This is used to ensure we don't load something for the wrong architecture.
diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
index a3405b3c1eef..d025a22eb225 100644
--- a/arch/ia64/ia32/sys_ia32.c
+++ b/arch/ia64/ia32/sys_ia32.c
@@ -773,7 +773,7 @@ emulate_mmap (struct file *file, unsigned long start, unsigned long len, int pro
if (flags & MAP_SHARED)
printk(KERN_INFO
"%s(%d): emulate_mmap() can't share head (addr=0x%lx)\n",
- current->comm, current->pid, start);
+ current->comm, task_pid_nr(current), start);
ret = mmap_subpage(file, start, min(PAGE_ALIGN(start), end), prot, flags,
off);
if (IS_ERR((void *) ret))
@@ -786,7 +786,7 @@ emulate_mmap (struct file *file, unsigned long start, unsigned long len, int pro
if (flags & MAP_SHARED)
printk(KERN_INFO
"%s(%d): emulate_mmap() can't share tail (end=0x%lx)\n",
- current->comm, current->pid, end);
+ current->comm, task_pid_nr(current), end);
ret = mmap_subpage(file, max(start, PAGE_START(end)), end, prot, flags,
(off + len) - offset_in_page(end));
if (IS_ERR((void *) ret))
@@ -816,7 +816,7 @@ emulate_mmap (struct file *file, unsigned long start, unsigned long len, int pro
if ((flags & MAP_SHARED) && !is_congruent)
printk(KERN_INFO "%s(%d): emulate_mmap() can't share contents of incongruent mmap "
- "(addr=0x%lx,off=0x%llx)\n", current->comm, current->pid, start, off);
+ "(addr=0x%lx,off=0x%llx)\n", current->comm, task_pid_nr(current), start, off);
DBG("mmap_body: mapping [0x%lx-0x%lx) %s with poff 0x%llx\n", pstart, pend,
is_congruent ? "congruent" : "not congruent", poff);
diff --git a/arch/ia64/kernel/.gitignore b/arch/ia64/kernel/.gitignore
new file mode 100644
index 000000000000..98307759a3b8
--- /dev/null
+++ b/arch/ia64/kernel/.gitignore
@@ -0,0 +1 @@
+gate.lds
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index 3d45d24a9d61..897e2083a3b1 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -678,9 +678,11 @@ int __init acpi_boot_init(void)
/* I/O APIC */
if (acpi_table_parse_madt
- (ACPI_MADT_TYPE_IO_SAPIC, acpi_parse_iosapic, NR_IOSAPICS) < 1)
- printk(KERN_ERR PREFIX
- "Error parsing MADT - no IOSAPIC entries\n");
+ (ACPI_MADT_TYPE_IO_SAPIC, acpi_parse_iosapic, NR_IOSAPICS) < 1) {
+ if (!ia64_platform_is("sn2"))
+ printk(KERN_ERR PREFIX
+ "Error parsing MADT - no IOSAPIC entries\n");
+ }
/* System-Level Interrupt Routing */
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index 73ca86d03810..8e8f8b6193ee 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -218,9 +218,10 @@ efi_gettimeofday (struct timespec *ts)
{
efi_time_t tm;
- memset(ts, 0, sizeof(ts));
- if ((*efi.get_time)(&tm, NULL) != EFI_SUCCESS)
+ if ((*efi.get_time)(&tm, NULL) != EFI_SUCCESS) {
+ memset(ts, 0, sizeof(*ts));
return;
+ }
ts->tv_sec = mktime(tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second);
ts->tv_nsec = tm.nanosecond;
@@ -967,7 +968,7 @@ find_memmap_space (void)
* to use. We can allocate partial granules only if the unavailable
* parts exist, and are WB.
*/
-void
+unsigned long
efi_memmap_init(unsigned long *s, unsigned long *e)
{
struct kern_memdesc *k, *prev = NULL;
@@ -1084,11 +1085,14 @@ efi_memmap_init(unsigned long *s, unsigned long *e)
/* reserve the memory we are using for kern_memmap */
*s = (u64)kern_memmap;
*e = (u64)++k;
+
+ return total_mem;
}
void
efi_initialize_iomem_resources(struct resource *code_resource,
- struct resource *data_resource)
+ struct resource *data_resource,
+ struct resource *bss_resource)
{
struct resource *res;
void *efi_map_start, *efi_map_end, *p;
@@ -1109,7 +1113,7 @@ efi_initialize_iomem_resources(struct resource *code_resource,
if (md->num_pages == 0) /* should not happen */
continue;
- flags = IORESOURCE_MEM;
+ flags = IORESOURCE_MEM | IORESOURCE_BUSY;
switch (md->type) {
case EFI_MEMORY_MAPPED_IO:
@@ -1131,12 +1135,11 @@ efi_initialize_iomem_resources(struct resource *code_resource,
case EFI_ACPI_MEMORY_NVS:
name = "ACPI Non-volatile Storage";
- flags |= IORESOURCE_BUSY;
break;
case EFI_UNUSABLE_MEMORY:
name = "reserved";
- flags |= IORESOURCE_BUSY | IORESOURCE_DISABLED;
+ flags |= IORESOURCE_DISABLED;
break;
case EFI_RESERVED_TYPE:
@@ -1145,7 +1148,6 @@ efi_initialize_iomem_resources(struct resource *code_resource,
case EFI_ACPI_RECLAIM_MEMORY:
default:
name = "reserved";
- flags |= IORESOURCE_BUSY;
break;
}
@@ -1169,6 +1171,7 @@ efi_initialize_iomem_resources(struct resource *code_resource,
*/
insert_resource(res, code_resource);
insert_resource(res, data_resource);
+ insert_resource(res, bss_resource);
#ifdef CONFIG_KEXEC
insert_resource(res, &efi_memmap_res);
insert_resource(res, &boot_param_res);
@@ -1227,7 +1230,7 @@ kdump_find_rsvd_region (unsigned long size,
#ifdef CONFIG_PROC_VMCORE
/* locate the size find a the descriptor at a certain address */
-unsigned long
+unsigned long __init
vmcore_find_descriptor_size (unsigned long address)
{
void *efi_map_start, *efi_map_end, *p;
diff --git a/arch/ia64/kernel/gate.lds.S b/arch/ia64/kernel/gate.lds.S
index 6d198339bf85..454d7a7dfa9d 100644
--- a/arch/ia64/kernel/gate.lds.S
+++ b/arch/ia64/kernel/gate.lds.S
@@ -1,7 +1,8 @@
/*
- * Linker script for gate DSO. The gate pages are an ELF shared object prelinked to its
- * virtual address, with only one read-only segment and one execute-only segment (both fit
- * in one page). This script controls its layout.
+ * Linker script for gate DSO. The gate pages are an ELF shared object
+ * prelinked to its virtual address, with only one read-only segment and
+ * one execute-only segment (both fit in one page). This script controls
+ * its layout.
*/
@@ -9,72 +10,83 @@
SECTIONS
{
- . = GATE_ADDR + SIZEOF_HEADERS;
-
- .hash : { *(.hash) } :readable
- .gnu.hash : { *(.gnu.hash) }
- .dynsym : { *(.dynsym) }
- .dynstr : { *(.dynstr) }
- .gnu.version : { *(.gnu.version) }
- .gnu.version_d : { *(.gnu.version_d) }
- .gnu.version_r : { *(.gnu.version_r) }
- .dynamic : { *(.dynamic) } :readable :dynamic
-
- /*
- * This linker script is used both with -r and with -shared. For the layouts to match,
- * we need to skip more than enough space for the dynamic symbol table et al. If this
- * amount is insufficient, ld -shared will barf. Just increase it here.
- */
- . = GATE_ADDR + 0x500;
-
- .data.patch : {
- __start_gate_mckinley_e9_patchlist = .;
- *(.data.patch.mckinley_e9)
- __end_gate_mckinley_e9_patchlist = .;
-
- __start_gate_vtop_patchlist = .;
- *(.data.patch.vtop)
- __end_gate_vtop_patchlist = .;
-
- __start_gate_fsyscall_patchlist = .;
- *(.data.patch.fsyscall_table)
- __end_gate_fsyscall_patchlist = .;
-
- __start_gate_brl_fsys_bubble_down_patchlist = .;
- *(.data.patch.brl_fsys_bubble_down)
- __end_gate_brl_fsys_bubble_down_patchlist = .;
- } :readable
- .IA_64.unwind_info : { *(.IA_64.unwind_info*) }
- .IA_64.unwind : { *(.IA_64.unwind*) } :readable :unwind
+ . = GATE_ADDR + SIZEOF_HEADERS;
+
+ .hash : { *(.hash) } :readable
+ .gnu.hash : { *(.gnu.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+
+ .note : { *(.note*) } :readable :note
+
+ .dynamic : { *(.dynamic) } :readable :dynamic
+
+ /*
+ * This linker script is used both with -r and with -shared. For
+ * the layouts to match, we need to skip more than enough space for
+ * the dynamic symbol table et al. If this amount is insufficient,
+ * ld -shared will barf. Just increase it here.
+ */
+ . = GATE_ADDR + 0x500;
+
+ .data.patch : {
+ __start_gate_mckinley_e9_patchlist = .;
+ *(.data.patch.mckinley_e9)
+ __end_gate_mckinley_e9_patchlist = .;
+
+ __start_gate_vtop_patchlist = .;
+ *(.data.patch.vtop)
+ __end_gate_vtop_patchlist = .;
+
+ __start_gate_fsyscall_patchlist = .;
+ *(.data.patch.fsyscall_table)
+ __end_gate_fsyscall_patchlist = .;
+
+ __start_gate_brl_fsys_bubble_down_patchlist = .;
+ *(.data.patch.brl_fsys_bubble_down)
+ __end_gate_brl_fsys_bubble_down_patchlist = .;
+ } :readable
+
+ .IA_64.unwind_info : { *(.IA_64.unwind_info*) }
+ .IA_64.unwind : { *(.IA_64.unwind*) } :readable :unwind
#ifdef HAVE_BUGGY_SEGREL
- .text (GATE_ADDR + PAGE_SIZE) : { *(.text) *(.text.*) } :readable
+ .text (GATE_ADDR + PAGE_SIZE) : { *(.text) *(.text.*) } :readable
#else
- . = ALIGN (PERCPU_PAGE_SIZE) + (. & (PERCPU_PAGE_SIZE - 1));
- .text : { *(.text) *(.text.*) } :epc
+ . = ALIGN(PERCPU_PAGE_SIZE) + (. & (PERCPU_PAGE_SIZE - 1));
+ .text : { *(.text) *(.text.*) } :epc
#endif
- /DISCARD/ : {
- *(.got.plt) *(.got)
- *(.data .data.* .gnu.linkonce.d.*)
- *(.dynbss)
- *(.bss .bss.* .gnu.linkonce.b.*)
- *(__ex_table)
- *(__mca_table)
- }
+ /DISCARD/ : {
+ *(.got.plt) *(.got)
+ *(.data .data.* .gnu.linkonce.d.*)
+ *(.dynbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ *(__ex_table)
+ *(__mca_table)
+ }
}
/*
+ * ld does not recognize this name token; use the constant.
+ */
+#define PT_IA_64_UNWIND 0x70000001
+
+/*
* We must supply the ELF program headers explicitly to get just one
* PT_LOAD segment, and set the flags explicitly to make segments read-only.
*/
PHDRS
{
- readable PT_LOAD FILEHDR PHDRS FLAGS(4); /* PF_R */
+ readable PT_LOAD FILEHDR PHDRS FLAGS(4); /* PF_R */
#ifndef HAVE_BUGGY_SEGREL
- epc PT_LOAD FILEHDR PHDRS FLAGS(1); /* PF_X */
+ epc PT_LOAD FILEHDR PHDRS FLAGS(1); /* PF_X */
#endif
- dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
- unwind 0x70000001; /* PT_IA_64_UNWIND, but ld doesn't match the name */
+ dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
+ note PT_NOTE FLAGS(4); /* PF_R */
+ unwind PT_IA_64_UNWIND;
}
/*
@@ -82,14 +94,14 @@ PHDRS
*/
VERSION
{
- LINUX_2.5 {
- global:
- __kernel_syscall_via_break;
- __kernel_syscall_via_epc;
- __kernel_sigtramp;
-
- local: *;
- };
+ LINUX_2.5 {
+ global:
+ __kernel_syscall_via_break;
+ __kernel_syscall_via_epc;
+ __kernel_sigtramp;
+
+ local: *;
+ };
}
/* The ELF entry point can be used to set the AT_SYSINFO value. */
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
index cfe4654838f4..274a59383043 100644
--- a/arch/ia64/kernel/iosapic.c
+++ b/arch/ia64/kernel/iosapic.c
@@ -748,6 +748,15 @@ skip_numa_setup:
#endif
}
+static inline unsigned char choose_dmode(void)
+{
+#ifdef CONFIG_SMP
+ if (smp_int_redirect & SMP_IRQ_REDIRECTION)
+ return IOSAPIC_LOWEST_PRIORITY;
+#endif
+ return IOSAPIC_FIXED;
+}
+
/*
* ACPI can describe IOSAPIC interrupts via static tables and namespace
* methods. This provides an interface to register those interrupts and
@@ -762,6 +771,7 @@ iosapic_register_intr (unsigned int gsi,
unsigned long flags;
struct iosapic_rte_info *rte;
u32 low32;
+ unsigned char dmode;
/*
* If this GSI has already been registered (i.e., it's a
@@ -791,8 +801,8 @@ iosapic_register_intr (unsigned int gsi,
spin_lock(&irq_desc[irq].lock);
dest = get_target_cpu(gsi, irq);
- err = register_intr(gsi, irq, IOSAPIC_LOWEST_PRIORITY,
- polarity, trigger);
+ dmode = choose_dmode();
+ err = register_intr(gsi, irq, dmode, polarity, trigger);
if (err < 0) {
spin_unlock(&irq_desc[irq].lock);
irq = err;
@@ -961,10 +971,12 @@ iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,
{
int vector, irq;
unsigned int dest = cpu_physical_id(smp_processor_id());
+ unsigned char dmode;
irq = vector = isa_irq_to_vector(isa_irq);
BUG_ON(bind_irq_vector(irq, vector, CPU_MASK_ALL));
- register_intr(gsi, irq, IOSAPIC_LOWEST_PRIORITY, polarity, trigger);
+ dmode = choose_dmode();
+ register_intr(gsi, irq, dmode, polarity, trigger);
DBG("ISA: IRQ %u -> GSI %u (%s,%s) -> CPU %d (0x%04x) vector %d\n",
isa_irq, gsi, trigger == IOSAPIC_EDGE ? "edge" : "level",
diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c
index 44be1c952b7c..6dee579f205f 100644
--- a/arch/ia64/kernel/irq.c
+++ b/arch/ia64/kernel/irq.c
@@ -61,9 +61,11 @@ int show_interrupts(struct seq_file *p, void *v)
unsigned long flags;
if (i == 0) {
- seq_printf(p, " ");
+ char cpuname[16];
+ seq_printf(p, " ");
for_each_online_cpu(j) {
- seq_printf(p, "CPU%d ",j);
+ snprintf(cpuname, 10, "CPU%d", j);
+ seq_printf(p, "%10s ", cpuname);
}
seq_putc(p, '\n');
}
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index 5dc98b5abcfb..5fd65d8302c8 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -40,6 +40,8 @@ extern void jprobe_inst_return(void);
DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
+struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}};
+
enum instruction_type {A, I, M, F, B, L, X, u};
static enum instruction_type bundle_encoding[32][3] = {
{ M, I, I }, /* 00 */
diff --git a/arch/ia64/kernel/machine_kexec.c b/arch/ia64/kernel/machine_kexec.c
index 58e943a5d95c..d6cd45f4c6c7 100644
--- a/arch/ia64/kernel/machine_kexec.c
+++ b/arch/ia64/kernel/machine_kexec.c
@@ -15,10 +15,15 @@
#include <linux/cpu.h>
#include <linux/irq.h>
#include <linux/efi.h>
+#include <linux/numa.h>
+#include <linux/mmzone.h>
+
+#include <asm/numa.h>
#include <asm/mmu_context.h>
#include <asm/setup.h>
#include <asm/delay.h>
#include <asm/meminit.h>
+#include <asm/processor.h>
typedef NORET_TYPE void (*relocate_new_kernel_t)(
unsigned long indirection_page,
@@ -121,3 +126,28 @@ void machine_kexec(struct kimage *image)
unw_init_running(ia64_machine_kexec, image);
for(;;);
}
+
+void arch_crash_save_vmcoreinfo(void)
+{
+#if defined(CONFIG_ARCH_DISCONTIGMEM_ENABLE) && defined(CONFIG_NUMA)
+ VMCOREINFO_SYMBOL(pgdat_list);
+ VMCOREINFO_LENGTH(pgdat_list, MAX_NUMNODES);
+
+ VMCOREINFO_SYMBOL(node_memblk);
+ VMCOREINFO_LENGTH(node_memblk, NR_NODE_MEMBLKS);
+ VMCOREINFO_SIZE(node_memblk_s);
+ VMCOREINFO_OFFSET(node_memblk_s, start_paddr);
+ VMCOREINFO_OFFSET(node_memblk_s, size);
+#endif
+#ifdef CONFIG_PGTABLE_3
+ VMCOREINFO_CONFIG(PGTABLE_3);
+#elif CONFIG_PGTABLE_4
+ VMCOREINFO_CONFIG(PGTABLE_4);
+#endif
+}
+
+unsigned long paddr_vmcoreinfo_note(void)
+{
+ return ia64_tpa((unsigned long)(char *)&vmcoreinfo_note);
+}
+
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index cc87025e8f54..10b48cd15a87 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -571,7 +571,7 @@ out:
* Outputs
* None
*/
-static void __init
+void
ia64_mca_register_cpev (int cpev)
{
/* Register the CPE interrupt vector with SAL */
diff --git a/arch/ia64/kernel/msi_ia64.c b/arch/ia64/kernel/msi_ia64.c
index 2fdbd5c3f213..e86d02959794 100644
--- a/arch/ia64/kernel/msi_ia64.c
+++ b/arch/ia64/kernel/msi_ia64.c
@@ -109,7 +109,7 @@ int ia64_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
write_msi_msg(irq, &msg);
set_irq_chip_and_handler(irq, &ia64_msi_chip, handle_edge_irq);
- return irq;
+ return 0;
}
void ia64_teardown_msi_irq(unsigned int irq)
diff --git a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c
index 6ef6ffb943a0..396004e8cd14 100644
--- a/arch/ia64/kernel/palinfo.c
+++ b/arch/ia64/kernel/palinfo.c
@@ -470,7 +470,7 @@ register_info(char *page)
return p - page;
}
-static const char *proc_features[]={
+static char *proc_features_0[]={ /* Feature set 0 */
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
@@ -502,25 +502,92 @@ static const char *proc_features[]={
"Enable BERR promotion"
};
+static char *proc_features_16[]={ /* Feature set 16 */
+ "Disable ETM",
+ "Enable ETM",
+ "Enable MCA on half-way timer",
+ "Enable snoop WC",
+ NULL,
+ "Enable Fast Deferral",
+ "Disable MCA on memory aliasing",
+ "Enable RSB",
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ "DP system processor",
+ "Low Voltage",
+ "HT supported",
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL
+};
+
+static char **proc_features[]={
+ proc_features_0,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ proc_features_16,
+ NULL, NULL, NULL, NULL,
+};
+
+static char *
+feature_set_info(char *page, u64 avail, u64 status, u64 control, u64 set)
+{
+ char *p = page;
+ char **vf, **v;
+ int i;
+
+ vf = v = proc_features[set];
+ for(i=0; i < 64; i++, avail >>=1, status >>=1, control >>=1) {
+
+ if (!(control)) /* No remaining bits set */
+ break;
+ if (!(avail & 0x1)) /* Print only bits that are available */
+ continue;
+ if (vf)
+ v = vf + i;
+ if ( v && *v ) {
+ p += sprintf(p, "%-40s : %s %s\n", *v,
+ avail & 0x1 ? (status & 0x1 ?
+ "On " : "Off"): "",
+ avail & 0x1 ? (control & 0x1 ?
+ "Ctrl" : "NoCtrl"): "");
+ } else {
+ p += sprintf(p, "Feature set %2ld bit %2d\t\t\t"
+ " : %s %s\n",
+ set, i,
+ avail & 0x1 ? (status & 0x1 ?
+ "On " : "Off"): "",
+ avail & 0x1 ? (control & 0x1 ?
+ "Ctrl" : "NoCtrl"): "");
+ }
+ }
+ return p;
+}
static int
processor_info(char *page)
{
char *p = page;
- const char **v = proc_features;
- u64 avail=1, status=1, control=1;
- int i;
+ u64 avail=1, status=1, control=1, feature_set=0;
s64 ret;
- if ((ret=ia64_pal_proc_get_features(&avail, &status, &control)) != 0) return 0;
+ do {
+ ret = ia64_pal_proc_get_features(&avail, &status, &control,
+ feature_set);
+ if (ret < 0) {
+ return p - page;
+ }
+ if (ret == 1) {
+ feature_set++;
+ continue;
+ }
+
+ p = feature_set_info(p, avail, status, control, feature_set);
+
+ feature_set++;
+ } while(1);
- for(i=0; i < 64; i++, v++,avail >>=1, status >>=1, control >>=1) {
- if ( ! *v ) continue;
- p += sprintf(p, "%-40s : %s%s %s\n", *v,
- avail & 0x1 ? "" : "NotImpl",
- avail & 0x1 ? (status & 0x1 ? "On" : "Off"): "",
- avail & 0x1 ? (control & 0x1 ? "Ctrl" : "NoCtrl"): "");
- }
return p - page;
}
diff --git a/arch/ia64/kernel/patch.c b/arch/ia64/kernel/patch.c
index e796e29f8e15..2cb9425e0421 100644
--- a/arch/ia64/kernel/patch.c
+++ b/arch/ia64/kernel/patch.c
@@ -129,9 +129,6 @@ ia64_patch_mckinley_e9 (unsigned long start, unsigned long end)
first_time = 0;
if (need_workaround)
printk(KERN_INFO "Leaving McKinley Errata 9 workaround enabled\n");
- else
- printk(KERN_INFO "McKinley Errata 9 workaround not needed; "
- "disabling it\n");
}
if (need_workaround)
return;
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index f55fa07849c4..73e7c2e40b54 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -158,14 +158,14 @@
*/
#define PROTECT_CTX(c, f) \
do { \
- DPRINT(("spinlock_irq_save ctx %p by [%d]\n", c, current->pid)); \
+ DPRINT(("spinlock_irq_save ctx %p by [%d]\n", c, task_pid_nr(current))); \
spin_lock_irqsave(&(c)->ctx_lock, f); \
- DPRINT(("spinlocked ctx %p by [%d]\n", c, current->pid)); \
+ DPRINT(("spinlocked ctx %p by [%d]\n", c, task_pid_nr(current))); \
} while(0)
#define UNPROTECT_CTX(c, f) \
do { \
- DPRINT(("spinlock_irq_restore ctx %p by [%d]\n", c, current->pid)); \
+ DPRINT(("spinlock_irq_restore ctx %p by [%d]\n", c, task_pid_nr(current))); \
spin_unlock_irqrestore(&(c)->ctx_lock, f); \
} while(0)
@@ -227,12 +227,12 @@
#ifdef PFM_DEBUGGING
#define DPRINT(a) \
do { \
- if (unlikely(pfm_sysctl.debug >0)) { printk("%s.%d: CPU%d [%d] ", __FUNCTION__, __LINE__, smp_processor_id(), current->pid); printk a; } \
+ if (unlikely(pfm_sysctl.debug >0)) { printk("%s.%d: CPU%d [%d] ", __FUNCTION__, __LINE__, smp_processor_id(), task_pid_nr(current)); printk a; } \
} while (0)
#define DPRINT_ovfl(a) \
do { \
- if (unlikely(pfm_sysctl.debug > 0 && pfm_sysctl.debug_ovfl >0)) { printk("%s.%d: CPU%d [%d] ", __FUNCTION__, __LINE__, smp_processor_id(), current->pid); printk a; } \
+ if (unlikely(pfm_sysctl.debug > 0 && pfm_sysctl.debug_ovfl >0)) { printk("%s.%d: CPU%d [%d] ", __FUNCTION__, __LINE__, smp_processor_id(), task_pid_nr(current)); printk a; } \
} while (0)
#endif
@@ -558,7 +558,7 @@ static ctl_table pfm_sysctl_dir[] = {
{
.ctl_name = CTL_UNNUMBERED,
.procname = "perfmon",
- .mode = 0755,
+ .mode = 0555,
.child = pfm_ctl_table,
},
{}
@@ -567,7 +567,7 @@ static ctl_table pfm_sysctl_root[] = {
{
.ctl_name = CTL_KERN,
.procname = "kernel",
- .mode = 0755,
+ .mode = 0555,
.child = pfm_sysctl_dir,
},
{}
@@ -913,7 +913,7 @@ pfm_mask_monitoring(struct task_struct *task)
unsigned long mask, val, ovfl_mask;
int i;
- DPRINT_ovfl(("masking monitoring for [%d]\n", task->pid));
+ DPRINT_ovfl(("masking monitoring for [%d]\n", task_pid_nr(task)));
ovfl_mask = pmu_conf->ovfl_val;
/*
@@ -992,12 +992,12 @@ pfm_restore_monitoring(struct task_struct *task)
ovfl_mask = pmu_conf->ovfl_val;
if (task != current) {
- printk(KERN_ERR "perfmon.%d: invalid task[%d] current[%d]\n", __LINE__, task->pid, current->pid);
+ printk(KERN_ERR "perfmon.%d: invalid task[%d] current[%d]\n", __LINE__, task_pid_nr(task), task_pid_nr(current));
return;
}
if (ctx->ctx_state != PFM_CTX_MASKED) {
printk(KERN_ERR "perfmon.%d: task[%d] current[%d] invalid state=%d\n", __LINE__,
- task->pid, current->pid, ctx->ctx_state);
+ task_pid_nr(task), task_pid_nr(current), ctx->ctx_state);
return;
}
psr = pfm_get_psr();
@@ -1051,7 +1051,8 @@ pfm_restore_monitoring(struct task_struct *task)
if ((mask & 0x1) == 0UL) continue;
ctx->th_pmcs[i] = ctx->ctx_pmcs[i];
ia64_set_pmc(i, ctx->th_pmcs[i]);
- DPRINT(("[%d] pmc[%d]=0x%lx\n", task->pid, i, ctx->th_pmcs[i]));
+ DPRINT(("[%d] pmc[%d]=0x%lx\n",
+ task_pid_nr(task), i, ctx->th_pmcs[i]));
}
ia64_srlz_d();
@@ -1370,7 +1371,7 @@ pfm_reserve_session(struct task_struct *task, int is_syswide, unsigned int cpu)
error_conflict:
DPRINT(("system wide not possible, conflicting session [%d] on CPU%d\n",
- pfm_sessions.pfs_sys_session[cpu]->pid,
+ task_pid_nr(pfm_sessions.pfs_sys_session[cpu]),
cpu));
abort:
UNLOCK_PFS(flags);
@@ -1442,7 +1443,7 @@ pfm_remove_smpl_mapping(struct task_struct *task, void *vaddr, unsigned long siz
/* sanity checks */
if (task->mm == NULL || size == 0UL || vaddr == NULL) {
- printk(KERN_ERR "perfmon: pfm_remove_smpl_mapping [%d] invalid context mm=%p\n", task->pid, task->mm);
+ printk(KERN_ERR "perfmon: pfm_remove_smpl_mapping [%d] invalid context mm=%p\n", task_pid_nr(task), task->mm);
return -EINVAL;
}
@@ -1459,7 +1460,7 @@ pfm_remove_smpl_mapping(struct task_struct *task, void *vaddr, unsigned long siz
up_write(&task->mm->mmap_sem);
if (r !=0) {
- printk(KERN_ERR "perfmon: [%d] unable to unmap sampling buffer @%p size=%lu\n", task->pid, vaddr, size);
+ printk(KERN_ERR "perfmon: [%d] unable to unmap sampling buffer @%p size=%lu\n", task_pid_nr(task), vaddr, size);
}
DPRINT(("do_unmap(%p, %lu)=%d\n", vaddr, size, r));
@@ -1501,7 +1502,7 @@ pfm_free_smpl_buffer(pfm_context_t *ctx)
return 0;
invalid_free:
- printk(KERN_ERR "perfmon: pfm_free_smpl_buffer [%d] no buffer\n", current->pid);
+ printk(KERN_ERR "perfmon: pfm_free_smpl_buffer [%d] no buffer\n", task_pid_nr(current));
return -EINVAL;
}
#endif
@@ -1547,13 +1548,13 @@ pfm_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
unsigned long flags;
DECLARE_WAITQUEUE(wait, current);
if (PFM_IS_FILE(filp) == 0) {
- printk(KERN_ERR "perfmon: pfm_poll: bad magic [%d]\n", current->pid);
+ printk(KERN_ERR "perfmon: pfm_poll: bad magic [%d]\n", task_pid_nr(current));
return -EINVAL;
}
ctx = (pfm_context_t *)filp->private_data;
if (ctx == NULL) {
- printk(KERN_ERR "perfmon: pfm_read: NULL ctx [%d]\n", current->pid);
+ printk(KERN_ERR "perfmon: pfm_read: NULL ctx [%d]\n", task_pid_nr(current));
return -EINVAL;
}
@@ -1607,7 +1608,7 @@ pfm_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
PROTECT_CTX(ctx, flags);
}
- DPRINT(("[%d] back to running ret=%ld\n", current->pid, ret));
+ DPRINT(("[%d] back to running ret=%ld\n", task_pid_nr(current), ret));
set_current_state(TASK_RUNNING);
remove_wait_queue(&ctx->ctx_msgq_wait, &wait);
@@ -1616,7 +1617,7 @@ pfm_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
ret = -EINVAL;
msg = pfm_get_next_msg(ctx);
if (msg == NULL) {
- printk(KERN_ERR "perfmon: pfm_read no msg for ctx=%p [%d]\n", ctx, current->pid);
+ printk(KERN_ERR "perfmon: pfm_read no msg for ctx=%p [%d]\n", ctx, task_pid_nr(current));
goto abort_locked;
}
@@ -1647,13 +1648,13 @@ pfm_poll(struct file *filp, poll_table * wait)
unsigned int mask = 0;
if (PFM_IS_FILE(filp) == 0) {
- printk(KERN_ERR "perfmon: pfm_poll: bad magic [%d]\n", current->pid);
+ printk(KERN_ERR "perfmon: pfm_poll: bad magic [%d]\n", task_pid_nr(current));
return 0;
}
ctx = (pfm_context_t *)filp->private_data;
if (ctx == NULL) {
- printk(KERN_ERR "perfmon: pfm_poll: NULL ctx [%d]\n", current->pid);
+ printk(KERN_ERR "perfmon: pfm_poll: NULL ctx [%d]\n", task_pid_nr(current));
return 0;
}
@@ -1692,7 +1693,7 @@ pfm_do_fasync(int fd, struct file *filp, pfm_context_t *ctx, int on)
ret = fasync_helper (fd, filp, on, &ctx->ctx_async_queue);
DPRINT(("pfm_fasync called by [%d] on ctx_fd=%d on=%d async_queue=%p ret=%d\n",
- current->pid,
+ task_pid_nr(current),
fd,
on,
ctx->ctx_async_queue, ret));
@@ -1707,13 +1708,13 @@ pfm_fasync(int fd, struct file *filp, int on)
int ret;
if (PFM_IS_FILE(filp) == 0) {
- printk(KERN_ERR "perfmon: pfm_fasync bad magic [%d]\n", current->pid);
+ printk(KERN_ERR "perfmon: pfm_fasync bad magic [%d]\n", task_pid_nr(current));
return -EBADF;
}
ctx = (pfm_context_t *)filp->private_data;
if (ctx == NULL) {
- printk(KERN_ERR "perfmon: pfm_fasync NULL ctx [%d]\n", current->pid);
+ printk(KERN_ERR "perfmon: pfm_fasync NULL ctx [%d]\n", task_pid_nr(current));
return -EBADF;
}
/*
@@ -1759,7 +1760,7 @@ pfm_syswide_force_stop(void *info)
if (owner != ctx->ctx_task) {
printk(KERN_ERR "perfmon: pfm_syswide_force_stop CPU%d unexpected owner [%d] instead of [%d]\n",
smp_processor_id(),
- owner->pid, ctx->ctx_task->pid);
+ task_pid_nr(owner), task_pid_nr(ctx->ctx_task));
return;
}
if (GET_PMU_CTX() != ctx) {
@@ -1769,7 +1770,7 @@ pfm_syswide_force_stop(void *info)
return;
}
- DPRINT(("on CPU%d forcing system wide stop for [%d]\n", smp_processor_id(), ctx->ctx_task->pid));
+ DPRINT(("on CPU%d forcing system wide stop for [%d]\n", smp_processor_id(), task_pid_nr(ctx->ctx_task)));
/*
* the context is already protected in pfm_close(), we simply
* need to mask interrupts to avoid a PMU interrupt race on
@@ -1821,7 +1822,7 @@ pfm_flush(struct file *filp, fl_owner_t id)
ctx = (pfm_context_t *)filp->private_data;
if (ctx == NULL) {
- printk(KERN_ERR "perfmon: pfm_flush: NULL ctx [%d]\n", current->pid);
+ printk(KERN_ERR "perfmon: pfm_flush: NULL ctx [%d]\n", task_pid_nr(current));
return -EBADF;
}
@@ -1969,7 +1970,7 @@ pfm_close(struct inode *inode, struct file *filp)
ctx = (pfm_context_t *)filp->private_data;
if (ctx == NULL) {
- printk(KERN_ERR "perfmon: pfm_close: NULL ctx [%d]\n", current->pid);
+ printk(KERN_ERR "perfmon: pfm_close: NULL ctx [%d]\n", task_pid_nr(current));
return -EBADF;
}
@@ -2066,7 +2067,7 @@ pfm_close(struct inode *inode, struct file *filp)
*/
ctx->ctx_state = PFM_CTX_ZOMBIE;
- DPRINT(("zombie ctx for [%d]\n", task->pid));
+ DPRINT(("zombie ctx for [%d]\n", task_pid_nr(task)));
/*
* cannot free the context on the spot. deferred until
* the task notices the ZOMBIE state
@@ -2472,7 +2473,7 @@ pfm_setup_buffer_fmt(struct task_struct *task, struct file *filp, pfm_context_t
/* invoke and lock buffer format, if found */
fmt = pfm_find_buffer_fmt(arg->ctx_smpl_buf_id);
if (fmt == NULL) {
- DPRINT(("[%d] cannot find buffer format\n", task->pid));
+ DPRINT(("[%d] cannot find buffer format\n", task_pid_nr(task)));
return -EINVAL;
}
@@ -2483,7 +2484,7 @@ pfm_setup_buffer_fmt(struct task_struct *task, struct file *filp, pfm_context_t
ret = pfm_buf_fmt_validate(fmt, task, ctx_flags, cpu, fmt_arg);
- DPRINT(("[%d] after validate(0x%x,%d,%p)=%d\n", task->pid, ctx_flags, cpu, fmt_arg, ret));
+ DPRINT(("[%d] after validate(0x%x,%d,%p)=%d\n", task_pid_nr(task), ctx_flags, cpu, fmt_arg, ret));
if (ret) goto error;
@@ -2605,23 +2606,23 @@ pfm_task_incompatible(pfm_context_t *ctx, struct task_struct *task)
* no kernel task or task not owner by caller
*/
if (task->mm == NULL) {
- DPRINT(("task [%d] has not memory context (kernel thread)\n", task->pid));
+ DPRINT(("task [%d] has not memory context (kernel thread)\n", task_pid_nr(task)));
return -EPERM;
}
if (pfm_bad_permissions(task)) {
- DPRINT(("no permission to attach to [%d]\n", task->pid));
+ DPRINT(("no permission to attach to [%d]\n", task_pid_nr(task)));
return -EPERM;
}
/*
* cannot block in self-monitoring mode
*/
if (CTX_OVFL_NOBLOCK(ctx) == 0 && task == current) {
- DPRINT(("cannot load a blocking context on self for [%d]\n", task->pid));
+ DPRINT(("cannot load a blocking context on self for [%d]\n", task_pid_nr(task)));
return -EINVAL;
}
if (task->exit_state == EXIT_ZOMBIE) {
- DPRINT(("cannot attach to zombie task [%d]\n", task->pid));
+ DPRINT(("cannot attach to zombie task [%d]\n", task_pid_nr(task)));
return -EBUSY;
}
@@ -2631,7 +2632,7 @@ pfm_task_incompatible(pfm_context_t *ctx, struct task_struct *task)
if (task == current) return 0;
if ((task->state != TASK_STOPPED) && (task->state != TASK_TRACED)) {
- DPRINT(("cannot attach to non-stopped task [%d] state=%ld\n", task->pid, task->state));
+ DPRINT(("cannot attach to non-stopped task [%d] state=%ld\n", task_pid_nr(task), task->state));
return -EBUSY;
}
/*
@@ -3512,7 +3513,7 @@ pfm_use_debug_registers(struct task_struct *task)
if (pmu_conf->use_rr_dbregs == 0) return 0;
- DPRINT(("called for [%d]\n", task->pid));
+ DPRINT(("called for [%d]\n", task_pid_nr(task)));
/*
* do it only once
@@ -3543,7 +3544,7 @@ pfm_use_debug_registers(struct task_struct *task)
DPRINT(("ptrace_use_dbregs=%u sys_use_dbregs=%u by [%d] ret = %d\n",
pfm_sessions.pfs_ptrace_use_dbregs,
pfm_sessions.pfs_sys_use_dbregs,
- task->pid, ret));
+ task_pid_nr(task), ret));
UNLOCK_PFS(flags);
@@ -3568,7 +3569,7 @@ pfm_release_debug_registers(struct task_struct *task)
LOCK_PFS(flags);
if (pfm_sessions.pfs_ptrace_use_dbregs == 0) {
- printk(KERN_ERR "perfmon: invalid release for [%d] ptrace_use_dbregs=0\n", task->pid);
+ printk(KERN_ERR "perfmon: invalid release for [%d] ptrace_use_dbregs=0\n", task_pid_nr(task));
ret = -1;
} else {
pfm_sessions.pfs_ptrace_use_dbregs--;
@@ -3620,7 +3621,7 @@ pfm_restart(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
/* sanity check */
if (unlikely(task == NULL)) {
- printk(KERN_ERR "perfmon: [%d] pfm_restart no task\n", current->pid);
+ printk(KERN_ERR "perfmon: [%d] pfm_restart no task\n", task_pid_nr(current));
return -EINVAL;
}
@@ -3629,7 +3630,7 @@ pfm_restart(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
fmt = ctx->ctx_buf_fmt;
DPRINT(("restarting self %d ovfl=0x%lx\n",
- task->pid,
+ task_pid_nr(task),
ctx->ctx_ovfl_regs[0]));
if (CTX_HAS_SMPL(ctx)) {
@@ -3653,11 +3654,11 @@ pfm_restart(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
pfm_reset_regs(ctx, ctx->ctx_ovfl_regs, PFM_PMD_LONG_RESET);
if (rst_ctrl.bits.mask_monitoring == 0) {
- DPRINT(("resuming monitoring for [%d]\n", task->pid));
+ DPRINT(("resuming monitoring for [%d]\n", task_pid_nr(task)));
if (state == PFM_CTX_MASKED) pfm_restore_monitoring(task);
} else {
- DPRINT(("keeping monitoring stopped for [%d]\n", task->pid));
+ DPRINT(("keeping monitoring stopped for [%d]\n", task_pid_nr(task)));
// cannot use pfm_stop_monitoring(task, regs);
}
@@ -3714,10 +3715,10 @@ pfm_restart(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
* "self-monitoring".
*/
if (CTX_OVFL_NOBLOCK(ctx) == 0 && state == PFM_CTX_MASKED) {
- DPRINT(("unblocking [%d] \n", task->pid));
+ DPRINT(("unblocking [%d] \n", task_pid_nr(task)));
complete(&ctx->ctx_restart_done);
} else {
- DPRINT(("[%d] armed exit trap\n", task->pid));
+ DPRINT(("[%d] armed exit trap\n", task_pid_nr(task)));
ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_RESET;
@@ -3805,7 +3806,7 @@ pfm_write_ibr_dbr(int mode, pfm_context_t *ctx, void *arg, int count, struct pt_
* don't bother if we are loaded and task is being debugged
*/
if (is_loaded && (thread->flags & IA64_THREAD_DBG_VALID) != 0) {
- DPRINT(("debug registers already in use for [%d]\n", task->pid));
+ DPRINT(("debug registers already in use for [%d]\n", task_pid_nr(task)));
return -EBUSY;
}
@@ -3846,7 +3847,7 @@ pfm_write_ibr_dbr(int mode, pfm_context_t *ctx, void *arg, int count, struct pt_
* is shared by all processes running on it
*/
if (first_time && can_access_pmu) {
- DPRINT(("[%d] clearing ibrs, dbrs\n", task->pid));
+ DPRINT(("[%d] clearing ibrs, dbrs\n", task_pid_nr(task)));
for (i=0; i < pmu_conf->num_ibrs; i++) {
ia64_set_ibr(i, 0UL);
ia64_dv_serialize_instruction();
@@ -4035,7 +4036,7 @@ pfm_stop(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
return -EBUSY;
}
DPRINT(("task [%d] ctx_state=%d is_system=%d\n",
- PFM_CTX_TASK(ctx)->pid,
+ task_pid_nr(PFM_CTX_TASK(ctx)),
state,
is_system));
/*
@@ -4093,7 +4094,7 @@ pfm_stop(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
* monitoring disabled in kernel at next reschedule
*/
ctx->ctx_saved_psr_up = 0;
- DPRINT(("task=[%d]\n", task->pid));
+ DPRINT(("task=[%d]\n", task_pid_nr(task)));
}
return 0;
}
@@ -4298,11 +4299,12 @@ pfm_context_load(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
if (is_system) {
if (pfm_sessions.pfs_ptrace_use_dbregs) {
- DPRINT(("cannot load [%d] dbregs in use\n", task->pid));
+ DPRINT(("cannot load [%d] dbregs in use\n",
+ task_pid_nr(task)));
ret = -EBUSY;
} else {
pfm_sessions.pfs_sys_use_dbregs++;
- DPRINT(("load [%d] increased sys_use_dbreg=%u\n", task->pid, pfm_sessions.pfs_sys_use_dbregs));
+ DPRINT(("load [%d] increased sys_use_dbreg=%u\n", task_pid_nr(task), pfm_sessions.pfs_sys_use_dbregs));
set_dbregs = 1;
}
}
@@ -4394,7 +4396,7 @@ pfm_context_load(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
/* allow user level control */
ia64_psr(regs)->sp = 0;
- DPRINT(("clearing psr.sp for [%d]\n", task->pid));
+ DPRINT(("clearing psr.sp for [%d]\n", task_pid_nr(task)));
SET_LAST_CPU(ctx, smp_processor_id());
INC_ACTIVATION();
@@ -4429,7 +4431,7 @@ pfm_context_load(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
*/
SET_PMU_OWNER(task, ctx);
- DPRINT(("context loaded on PMU for [%d]\n", task->pid));
+ DPRINT(("context loaded on PMU for [%d]\n", task_pid_nr(task)));
} else {
/*
* when not current, task MUST be stopped, so this is safe
@@ -4493,7 +4495,7 @@ pfm_context_unload(pfm_context_t *ctx, void *arg, int count, struct pt_regs *reg
int prev_state, is_system;
int ret;
- DPRINT(("ctx_state=%d task [%d]\n", ctx->ctx_state, task ? task->pid : -1));
+ DPRINT(("ctx_state=%d task [%d]\n", ctx->ctx_state, task ? task_pid_nr(task) : -1));
prev_state = ctx->ctx_state;
is_system = ctx->ctx_fl_system;
@@ -4568,7 +4570,7 @@ pfm_context_unload(pfm_context_t *ctx, void *arg, int count, struct pt_regs *reg
*/
ia64_psr(regs)->sp = 1;
- DPRINT(("setting psr.sp for [%d]\n", task->pid));
+ DPRINT(("setting psr.sp for [%d]\n", task_pid_nr(task)));
}
/*
* save PMDs to context
@@ -4608,7 +4610,7 @@ pfm_context_unload(pfm_context_t *ctx, void *arg, int count, struct pt_regs *reg
ctx->ctx_fl_can_restart = 0;
ctx->ctx_fl_going_zombie = 0;
- DPRINT(("disconnected [%d] from context\n", task->pid));
+ DPRINT(("disconnected [%d] from context\n", task_pid_nr(task)));
return 0;
}
@@ -4631,7 +4633,7 @@ pfm_exit_thread(struct task_struct *task)
PROTECT_CTX(ctx, flags);
- DPRINT(("state=%d task [%d]\n", ctx->ctx_state, task->pid));
+ DPRINT(("state=%d task [%d]\n", ctx->ctx_state, task_pid_nr(task)));
state = ctx->ctx_state;
switch(state) {
@@ -4640,13 +4642,13 @@ pfm_exit_thread(struct task_struct *task)
* only comes to this function if pfm_context is not NULL, i.e., cannot
* be in unloaded state
*/
- printk(KERN_ERR "perfmon: pfm_exit_thread [%d] ctx unloaded\n", task->pid);
+ printk(KERN_ERR "perfmon: pfm_exit_thread [%d] ctx unloaded\n", task_pid_nr(task));
break;
case PFM_CTX_LOADED:
case PFM_CTX_MASKED:
ret = pfm_context_unload(ctx, NULL, 0, regs);
if (ret) {
- printk(KERN_ERR "perfmon: pfm_exit_thread [%d] state=%d unload failed %d\n", task->pid, state, ret);
+ printk(KERN_ERR "perfmon: pfm_exit_thread [%d] state=%d unload failed %d\n", task_pid_nr(task), state, ret);
}
DPRINT(("ctx unloaded for current state was %d\n", state));
@@ -4655,12 +4657,12 @@ pfm_exit_thread(struct task_struct *task)
case PFM_CTX_ZOMBIE:
ret = pfm_context_unload(ctx, NULL, 0, regs);
if (ret) {
- printk(KERN_ERR "perfmon: pfm_exit_thread [%d] state=%d unload failed %d\n", task->pid, state, ret);
+ printk(KERN_ERR "perfmon: pfm_exit_thread [%d] state=%d unload failed %d\n", task_pid_nr(task), state, ret);
}
free_ok = 1;
break;
default:
- printk(KERN_ERR "perfmon: pfm_exit_thread [%d] unexpected state=%d\n", task->pid, state);
+ printk(KERN_ERR "perfmon: pfm_exit_thread [%d] unexpected state=%d\n", task_pid_nr(task), state);
break;
}
UNPROTECT_CTX(ctx, flags);
@@ -4744,7 +4746,7 @@ recheck:
DPRINT(("context %d state=%d [%d] task_state=%ld must_stop=%d\n",
ctx->ctx_fd,
state,
- task->pid,
+ task_pid_nr(task),
task->state, PFM_CMD_STOPPED(cmd)));
/*
@@ -4791,7 +4793,7 @@ recheck:
*/
if (PFM_CMD_STOPPED(cmd)) {
if ((task->state != TASK_STOPPED) && (task->state != TASK_TRACED)) {
- DPRINT(("[%d] task not in stopped state\n", task->pid));
+ DPRINT(("[%d] task not in stopped state\n", task_pid_nr(task)));
return -EBUSY;
}
/*
@@ -4884,7 +4886,7 @@ restart_args:
* limit abuse to min page size
*/
if (unlikely(sz > PFM_MAX_ARGSIZE)) {
- printk(KERN_ERR "perfmon: [%d] argument too big %lu\n", current->pid, sz);
+ printk(KERN_ERR "perfmon: [%d] argument too big %lu\n", task_pid_nr(current), sz);
return -E2BIG;
}
@@ -5031,11 +5033,11 @@ pfm_context_force_terminate(pfm_context_t *ctx, struct pt_regs *regs)
{
int ret;
- DPRINT(("entering for [%d]\n", current->pid));
+ DPRINT(("entering for [%d]\n", task_pid_nr(current)));
ret = pfm_context_unload(ctx, NULL, 0, regs);
if (ret) {
- printk(KERN_ERR "pfm_context_force_terminate: [%d] unloaded failed with %d\n", current->pid, ret);
+ printk(KERN_ERR "pfm_context_force_terminate: [%d] unloaded failed with %d\n", task_pid_nr(current), ret);
}
/*
@@ -5072,7 +5074,7 @@ pfm_handle_work(void)
ctx = PFM_GET_CTX(current);
if (ctx == NULL) {
- printk(KERN_ERR "perfmon: [%d] has no PFM context\n", current->pid);
+ printk(KERN_ERR "perfmon: [%d] has no PFM context\n", task_pid_nr(current));
return;
}
@@ -5269,7 +5271,7 @@ pfm_overflow_handler(struct task_struct *task, pfm_context_t *ctx, u64 pmc0, str
DPRINT_ovfl(("pmc0=0x%lx pid=%d iip=0x%lx, %s "
"used_pmds=0x%lx\n",
pmc0,
- task ? task->pid: -1,
+ task ? task_pid_nr(task): -1,
(regs ? regs->cr_iip : 0),
CTX_OVFL_NOBLOCK(ctx) ? "nonblocking" : "blocking",
ctx->ctx_used_pmds[0]));
@@ -5458,7 +5460,7 @@ pfm_overflow_handler(struct task_struct *task, pfm_context_t *ctx, u64 pmc0, str
}
DPRINT_ovfl(("owner [%d] pending=%ld reason=%u ovfl_pmds=0x%lx ovfl_notify=0x%lx masked=%d\n",
- GET_PMU_OWNER() ? GET_PMU_OWNER()->pid : -1,
+ GET_PMU_OWNER() ? task_pid_nr(GET_PMU_OWNER()) : -1,
PFM_GET_WORK_PENDING(task),
ctx->ctx_fl_trap_reason,
ovfl_pmds,
@@ -5483,7 +5485,7 @@ pfm_overflow_handler(struct task_struct *task, pfm_context_t *ctx, u64 pmc0, str
sanity_check:
printk(KERN_ERR "perfmon: CPU%d overflow handler [%d] pmc0=0x%lx\n",
smp_processor_id(),
- task ? task->pid : -1,
+ task ? task_pid_nr(task) : -1,
pmc0);
return;
@@ -5516,7 +5518,7 @@ stop_monitoring:
*
* Overall pretty hairy stuff....
*/
- DPRINT(("ctx is zombie for [%d], converted to spurious\n", task ? task->pid: -1));
+ DPRINT(("ctx is zombie for [%d], converted to spurious\n", task ? task_pid_nr(task): -1));
pfm_clear_psr_up();
ia64_psr(regs)->up = 0;
ia64_psr(regs)->sp = 1;
@@ -5577,13 +5579,13 @@ pfm_do_interrupt_handler(int irq, void *arg, struct pt_regs *regs)
report_spurious1:
printk(KERN_INFO "perfmon: spurious overflow interrupt on CPU%d: process %d has no PFM context\n",
- this_cpu, task->pid);
+ this_cpu, task_pid_nr(task));
pfm_unfreeze_pmu();
return -1;
report_spurious2:
printk(KERN_INFO "perfmon: spurious overflow interrupt on CPU%d: process %d, invalid flag\n",
this_cpu,
- task->pid);
+ task_pid_nr(task));
pfm_unfreeze_pmu();
return -1;
}
@@ -5870,7 +5872,8 @@ pfm_force_cleanup(pfm_context_t *ctx, struct pt_regs *regs)
ia64_psr(regs)->sp = 1;
if (GET_PMU_OWNER() == task) {
- DPRINT(("cleared ownership for [%d]\n", ctx->ctx_task->pid));
+ DPRINT(("cleared ownership for [%d]\n",
+ task_pid_nr(ctx->ctx_task)));
SET_PMU_OWNER(NULL, NULL);
}
@@ -5882,7 +5885,7 @@ pfm_force_cleanup(pfm_context_t *ctx, struct pt_regs *regs)
task->thread.pfm_context = NULL;
task->thread.flags &= ~IA64_THREAD_PM_VALID;
- DPRINT(("force cleanup for [%d]\n", task->pid));
+ DPRINT(("force cleanup for [%d]\n", task_pid_nr(task)));
}
@@ -6426,7 +6429,7 @@ pfm_flush_pmds(struct task_struct *task, pfm_context_t *ctx)
if (PMD_IS_COUNTING(i)) {
DPRINT(("[%d] pmd[%d] ctx_pmd=0x%lx hw_pmd=0x%lx\n",
- task->pid,
+ task_pid_nr(task),
i,
ctx->ctx_pmds[i].val,
val & ovfl_val));
@@ -6448,11 +6451,11 @@ pfm_flush_pmds(struct task_struct *task, pfm_context_t *ctx)
*/
if (pmc0 & (1UL << i)) {
val += 1 + ovfl_val;
- DPRINT(("[%d] pmd[%d] overflowed\n", task->pid, i));
+ DPRINT(("[%d] pmd[%d] overflowed\n", task_pid_nr(task), i));
}
}
- DPRINT(("[%d] ctx_pmd[%d]=0x%lx pmd_val=0x%lx\n", task->pid, i, val, pmd_val));
+ DPRINT(("[%d] ctx_pmd[%d]=0x%lx pmd_val=0x%lx\n", task_pid_nr(task), i, val, pmd_val));
if (is_self) ctx->th_pmds[i] = pmd_val;
@@ -6793,14 +6796,14 @@ dump_pmu_state(const char *from)
printk("CPU%d from %s() current [%d] iip=0x%lx %s\n",
this_cpu,
from,
- current->pid,
+ task_pid_nr(current),
regs->cr_iip,
current->comm);
task = GET_PMU_OWNER();
ctx = GET_PMU_CTX();
- printk("->CPU%d owner [%d] ctx=%p\n", this_cpu, task ? task->pid : -1, ctx);
+ printk("->CPU%d owner [%d] ctx=%p\n", this_cpu, task ? task_pid_nr(task) : -1, ctx);
psr = pfm_get_psr();
@@ -6848,7 +6851,7 @@ pfm_inherit(struct task_struct *task, struct pt_regs *regs)
{
struct thread_struct *thread;
- DPRINT(("perfmon: pfm_inherit clearing state for [%d]\n", task->pid));
+ DPRINT(("perfmon: pfm_inherit clearing state for [%d]\n", task_pid_nr(task)));
thread = &task->thread;
diff --git a/arch/ia64/kernel/perfmon_default_smpl.c b/arch/ia64/kernel/perfmon_default_smpl.c
index ff80eab83b38..a7af1cb419f9 100644
--- a/arch/ia64/kernel/perfmon_default_smpl.c
+++ b/arch/ia64/kernel/perfmon_default_smpl.c
@@ -44,11 +44,11 @@ default_validate(struct task_struct *task, unsigned int flags, int cpu, void *da
int ret = 0;
if (data == NULL) {
- DPRINT(("[%d] no argument passed\n", task->pid));
+ DPRINT(("[%d] no argument passed\n", task_pid_nr(task)));
return -EINVAL;
}
- DPRINT(("[%d] validate flags=0x%x CPU%d\n", task->pid, flags, cpu));
+ DPRINT(("[%d] validate flags=0x%x CPU%d\n", task_pid_nr(task), flags, cpu));
/*
* must hold at least the buffer header + one minimally sized entry
@@ -88,7 +88,7 @@ default_init(struct task_struct *task, void *buf, unsigned int flags, int cpu, v
hdr->hdr_count = 0UL;
DPRINT(("[%d] buffer=%p buf_size=%lu hdr_size=%lu hdr_version=%u cur_offs=%lu\n",
- task->pid,
+ task_pid_nr(task),
buf,
hdr->hdr_buf_size,
sizeof(*hdr),
@@ -245,7 +245,7 @@ default_restart(struct task_struct *task, pfm_ovfl_ctrl_t *ctrl, void *buf, stru
static int
default_exit(struct task_struct *task, void *buf, struct pt_regs *regs)
{
- DPRINT(("[%d] exit(%p)\n", task->pid, buf));
+ DPRINT(("[%d] exit(%p)\n", task_pid_nr(task), buf));
return 0;
}
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index c613fc0e91cc..2418289ee5ca 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -105,7 +105,8 @@ show_regs (struct pt_regs *regs)
unsigned long ip = regs->cr_iip + ia64_psr(regs)->ri;
print_modules();
- printk("\nPid: %d, CPU %d, comm: %20s\n", current->pid, smp_processor_id(), current->comm);
+ printk("\nPid: %d, CPU %d, comm: %20s\n", task_pid_nr(current),
+ smp_processor_id(), current->comm);
printk("psr : %016lx ifs : %016lx ip : [<%016lx>] %s\n",
regs->cr_ipsr, regs->cr_ifs, ip, print_tainted());
print_symbol("ip is at %s\n", ip);
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index 9e392a30d197..2b3751eef5ce 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -90,7 +90,12 @@ static struct resource code_resource = {
.name = "Kernel code",
.flags = IORESOURCE_BUSY | IORESOURCE_MEM
};
-extern char _text[], _end[], _etext[];
+
+static struct resource bss_resource = {
+ .name = "Kernel bss",
+ .flags = IORESOURCE_BUSY | IORESOURCE_MEM
+};
+extern char _text[], _end[], _etext[], _edata[], _bss[];
unsigned long ia64_max_cacheline_size;
@@ -200,14 +205,59 @@ static int __init register_memory(void)
code_resource.start = ia64_tpa(_text);
code_resource.end = ia64_tpa(_etext) - 1;
data_resource.start = ia64_tpa(_etext);
- data_resource.end = ia64_tpa(_end) - 1;
- efi_initialize_iomem_resources(&code_resource, &data_resource);
+ data_resource.end = ia64_tpa(_edata) - 1;
+ bss_resource.start = ia64_tpa(_bss);
+ bss_resource.end = ia64_tpa(_end) - 1;
+ efi_initialize_iomem_resources(&code_resource, &data_resource,
+ &bss_resource);
return 0;
}
__initcall(register_memory);
+
+#ifdef CONFIG_KEXEC
+static void __init setup_crashkernel(unsigned long total, int *n)
+{
+ unsigned long long base = 0, size = 0;
+ int ret;
+
+ ret = parse_crashkernel(boot_command_line, total,
+ &size, &base);
+ if (ret == 0 && size > 0) {
+ if (!base) {
+ sort_regions(rsvd_region, *n);
+ base = kdump_find_rsvd_region(size,
+ rsvd_region, *n);
+ }
+ if (base != ~0UL) {
+ printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
+ "for crashkernel (System RAM: %ldMB)\n",
+ (unsigned long)(size >> 20),
+ (unsigned long)(base >> 20),
+ (unsigned long)(total >> 20));
+ rsvd_region[*n].start =
+ (unsigned long)__va(base);
+ rsvd_region[*n].end =
+ (unsigned long)__va(base + size);
+ (*n)++;
+ crashk_res.start = base;
+ crashk_res.end = base + size - 1;
+ }
+ }
+ efi_memmap_res.start = ia64_boot_param->efi_memmap;
+ efi_memmap_res.end = efi_memmap_res.start +
+ ia64_boot_param->efi_memmap_size;
+ boot_param_res.start = __pa(ia64_boot_param);
+ boot_param_res.end = boot_param_res.start +
+ sizeof(*ia64_boot_param);
+}
+#else
+static inline void __init setup_crashkernel(unsigned long total, int *n)
+{}
+#endif
+
/**
* reserve_memory - setup reserved memory areas
*
@@ -219,6 +269,7 @@ void __init
reserve_memory (void)
{
int n = 0;
+ unsigned long total_memory;
/*
* none of the entries in this table overlap
@@ -254,50 +305,11 @@ reserve_memory (void)
n++;
#endif
- efi_memmap_init(&rsvd_region[n].start, &rsvd_region[n].end);
+ total_memory = efi_memmap_init(&rsvd_region[n].start, &rsvd_region[n].end);
n++;
-#ifdef CONFIG_KEXEC
- /* crashkernel=size@offset specifies the size to reserve for a crash
- * kernel. If offset is 0, then it is determined automatically.
- * By reserving this memory we guarantee that linux never set's it
- * up as a DMA target.Useful for holding code to do something
- * appropriate after a kernel panic.
- */
- {
- char *from = strstr(boot_command_line, "crashkernel=");
- unsigned long base, size;
- if (from) {
- size = memparse(from + 12, &from);
- if (*from == '@')
- base = memparse(from+1, &from);
- else
- base = 0;
- if (size) {
- if (!base) {
- sort_regions(rsvd_region, n);
- base = kdump_find_rsvd_region(size,
- rsvd_region, n);
- }
- if (base != ~0UL) {
- rsvd_region[n].start =
- (unsigned long)__va(base);
- rsvd_region[n].end =
- (unsigned long)__va(base + size);
- n++;
- crashk_res.start = base;
- crashk_res.end = base + size - 1;
- }
- }
- }
- efi_memmap_res.start = ia64_boot_param->efi_memmap;
- efi_memmap_res.end = efi_memmap_res.start +
- ia64_boot_param->efi_memmap_size;
- boot_param_res.start = __pa(ia64_boot_param);
- boot_param_res.end = boot_param_res.start +
- sizeof(*ia64_boot_param);
- }
-#endif
+ setup_crashkernel(total_memory, &n);
+
/* end of memory marker */
rsvd_region[n].start = ~0UL;
rsvd_region[n].end = ~0UL;
@@ -405,34 +417,6 @@ mark_bsp_online (void)
#endif
}
-#ifdef CONFIG_SMP
-static void __init
-check_for_logical_procs (void)
-{
- pal_logical_to_physical_t info;
- s64 status;
-
- status = ia64_pal_logical_to_phys(0, &info);
- if (status == -1) {
- printk(KERN_INFO "No logical to physical processor mapping "
- "available\n");
- return;
- }
- if (status) {
- printk(KERN_ERR "ia64_pal_logical_to_phys failed with %ld\n",
- status);
- return;
- }
- /*
- * Total number of siblings that BSP has. Though not all of them
- * may have booted successfully. The correct number of siblings
- * booted is in info.overview_num_log.
- */
- smp_num_siblings = info.overview_tpc;
- smp_num_cpucores = info.overview_cpp;
-}
-#endif
-
static __initdata int nomca;
static __init int setup_nomca(char *s)
{
@@ -528,19 +512,6 @@ setup_arch (char **cmdline_p)
#ifdef CONFIG_SMP
cpu_physical_id(0) = hard_smp_processor_id();
-
- cpu_set(0, cpu_sibling_map[0]);
- cpu_set(0, cpu_core_map[0]);
-
- check_for_logical_procs();
- if (smp_num_cpucores > 1)
- printk(KERN_INFO
- "cpu package is Multi-Core capable: number of cores=%d\n",
- smp_num_cpucores);
- if (smp_num_siblings > 1)
- printk(KERN_INFO
- "cpu package is Multi-Threading capable: number of siblings=%d\n",
- smp_num_siblings);
#endif
cpu_init(); /* initialize the bootstrap CPU */
@@ -653,12 +624,13 @@ show_cpuinfo (struct seq_file *m, void *v)
lpj*HZ/500000, (lpj*HZ/5000) % 100);
#ifdef CONFIG_SMP
seq_printf(m, "siblings : %u\n", cpus_weight(cpu_core_map[cpunum]));
+ if (c->socket_id != -1)
+ seq_printf(m, "physical id: %u\n", c->socket_id);
if (c->threads_per_core > 1 || c->cores_per_socket > 1)
seq_printf(m,
- "physical id: %u\n"
- "core id : %u\n"
- "thread id : %u\n",
- c->socket_id, c->core_id, c->thread_id);
+ "core id : %u\n"
+ "thread id : %u\n",
+ c->core_id, c->thread_id);
#endif
seq_printf(m,"\n");
@@ -770,6 +742,9 @@ identify_cpu (struct cpuinfo_ia64 *c)
c->socket_id = -1;
identify_siblings(c);
+
+ if (c->threads_per_core > smp_num_siblings)
+ smp_num_siblings = c->threads_per_core;
#endif
c->ppn = cpuid.field.ppn;
c->number = cpuid.field.number;
@@ -873,6 +848,16 @@ cpu_init (void)
void *cpu_data;
cpu_data = per_cpu_init();
+#ifdef CONFIG_SMP
+ /*
+ * insert boot cpu into sibling and core mapes
+ * (must be done after per_cpu area is setup)
+ */
+ if (smp_processor_id() == 0) {
+ cpu_set(0, per_cpu(cpu_sibling_map, 0));
+ cpu_set(0, cpu_core_map[0]);
+ }
+#endif
/*
* We set ar.k3 so that assembly code in MCA handler can compute
diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c
index aeec8184e862..cdb64cc4d9c8 100644
--- a/arch/ia64/kernel/signal.c
+++ b/arch/ia64/kernel/signal.c
@@ -227,7 +227,7 @@ ia64_rt_sigreturn (struct sigscratch *scr)
si.si_signo = SIGSEGV;
si.si_errno = 0;
si.si_code = SI_KERNEL;
- si.si_pid = current->pid;
+ si.si_pid = task_pid_vnr(current);
si.si_uid = current->uid;
si.si_addr = sc;
force_sig_info(SIGSEGV, &si, current);
@@ -332,7 +332,7 @@ force_sigsegv_info (int sig, void __user *addr)
si.si_signo = SIGSEGV;
si.si_errno = 0;
si.si_code = SI_KERNEL;
- si.si_pid = current->pid;
+ si.si_pid = task_pid_vnr(current);
si.si_uid = current->uid;
si.si_addr = addr;
force_sig_info(SIGSEGV, &si, current);
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
index 308772f7cddc..f0fc4d8465ad 100644
--- a/arch/ia64/kernel/smpboot.c
+++ b/arch/ia64/kernel/smpboot.c
@@ -138,9 +138,10 @@ cpumask_t cpu_possible_map = CPU_MASK_NONE;
EXPORT_SYMBOL(cpu_possible_map);
cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
-cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
+DEFINE_PER_CPU_SHARED_ALIGNED(cpumask_t, cpu_sibling_map);
+EXPORT_PER_CPU_SYMBOL(cpu_sibling_map);
+
int smp_num_siblings = 1;
-int smp_num_cpucores = 1;
/* which logical CPU number maps to which CPU (physical APIC ID) */
volatile int ia64_cpu_to_sapicid[NR_CPUS];
@@ -650,12 +651,12 @@ clear_cpu_sibling_map(int cpu)
{
int i;
- for_each_cpu_mask(i, cpu_sibling_map[cpu])
- cpu_clear(cpu, cpu_sibling_map[i]);
+ for_each_cpu_mask(i, per_cpu(cpu_sibling_map, cpu))
+ cpu_clear(cpu, per_cpu(cpu_sibling_map, i));
for_each_cpu_mask(i, cpu_core_map[cpu])
cpu_clear(cpu, cpu_core_map[i]);
- cpu_sibling_map[cpu] = cpu_core_map[cpu] = CPU_MASK_NONE;
+ per_cpu(cpu_sibling_map, cpu) = cpu_core_map[cpu] = CPU_MASK_NONE;
}
static void
@@ -666,7 +667,7 @@ remove_siblinginfo(int cpu)
if (cpu_data(cpu)->threads_per_core == 1 &&
cpu_data(cpu)->cores_per_socket == 1) {
cpu_clear(cpu, cpu_core_map[cpu]);
- cpu_clear(cpu, cpu_sibling_map[cpu]);
+ cpu_clear(cpu, per_cpu(cpu_sibling_map, cpu));
return;
}
@@ -807,8 +808,8 @@ set_cpu_sibling_map(int cpu)
cpu_set(i, cpu_core_map[cpu]);
cpu_set(cpu, cpu_core_map[i]);
if (cpu_data(cpu)->core_id == cpu_data(i)->core_id) {
- cpu_set(i, cpu_sibling_map[cpu]);
- cpu_set(cpu, cpu_sibling_map[i]);
+ cpu_set(i, per_cpu(cpu_sibling_map, cpu));
+ cpu_set(cpu, per_cpu(cpu_sibling_map, i));
}
}
}
@@ -839,7 +840,7 @@ __cpu_up (unsigned int cpu)
if (cpu_data(cpu)->threads_per_core == 1 &&
cpu_data(cpu)->cores_per_socket == 1) {
- cpu_set(cpu, cpu_sibling_map[cpu]);
+ cpu_set(cpu, per_cpu(cpu_sibling_map, cpu));
cpu_set(cpu, cpu_core_map[cpu]);
return 0;
}
@@ -884,13 +885,17 @@ identify_siblings(struct cpuinfo_ia64 *c)
u16 pltid;
pal_logical_to_physical_t info;
- if (smp_num_cpucores == 1 && smp_num_siblings == 1)
- return;
-
if ((status = ia64_pal_logical_to_phys(-1, &info)) != PAL_STATUS_SUCCESS) {
- printk(KERN_ERR "ia64_pal_logical_to_phys failed with %ld\n",
- status);
- return;
+ if (status != PAL_STATUS_UNIMPLEMENTED) {
+ printk(KERN_ERR
+ "ia64_pal_logical_to_phys failed with %ld\n",
+ status);
+ return;
+ }
+
+ info.overview_ppid = 0;
+ info.overview_cpp = 1;
+ info.overview_tpc = 1;
}
if ((status = ia64_sal_physical_id_info(&pltid)) != PAL_STATUS_SUCCESS) {
printk(KERN_ERR "ia64_sal_pltid failed with %ld\n", status);
@@ -898,6 +903,10 @@ identify_siblings(struct cpuinfo_ia64 *c)
}
c->socket_id = (pltid << 8) | info.overview_ppid;
+
+ if (info.overview_cpp == 1 && info.overview_tpc == 1)
+ return;
+
c->cores_per_socket = info.overview_cpp;
c->threads_per_core = info.overview_tpc;
c->num_log = info.overview_num_log;
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
index 98cfc90cab1d..2bb84214e5f1 100644
--- a/arch/ia64/kernel/time.c
+++ b/arch/ia64/kernel/time.c
@@ -371,6 +371,11 @@ ia64_setup_printk_clock(void)
ia64_printk_clock = ia64_itc_printk_clock;
}
+/* IA64 doesn't cache the timezone */
+void update_vsyscall_tz(void)
+{
+}
+
void update_vsyscall(struct timespec *wall, struct clocksource *c)
{
unsigned long flags;
diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c
index 3aeaf15e468b..78d65cb947d2 100644
--- a/arch/ia64/kernel/traps.c
+++ b/arch/ia64/kernel/traps.c
@@ -61,7 +61,7 @@ die (const char *str, struct pt_regs *regs, long err)
if (++die.lock_owner_depth < 3) {
printk("%s[%d]: %s %ld [%d]\n",
- current->comm, current->pid, str, err, ++die_counter);
+ current->comm, task_pid_nr(current), str, err, ++die_counter);
(void) notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV);
show_regs(regs);
} else
@@ -315,7 +315,7 @@ handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr)
last.time = current_jiffies + 5 * HZ;
printk(KERN_WARNING
"%s(%d): floating-point assist fault at ip %016lx, isr %016lx\n",
- current->comm, current->pid, regs->cr_iip + ia64_psr(regs)->ri, isr);
+ current->comm, task_pid_nr(current), regs->cr_iip + ia64_psr(regs)->ri, isr);
}
}
}
@@ -453,7 +453,7 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
if (code == 8) {
# ifdef CONFIG_IA64_PRINT_HAZARDS
printk("%s[%d]: possible hazard @ ip=%016lx (pr = %016lx)\n",
- current->comm, current->pid,
+ current->comm, task_pid_nr(current),
regs.cr_iip + ia64_psr(&regs)->ri, regs.pr);
# endif
return;
diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c
index fe6aa5a9f8fa..2173de9fe917 100644
--- a/arch/ia64/kernel/unaligned.c
+++ b/arch/ia64/kernel/unaligned.c
@@ -1340,7 +1340,8 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
size_t len;
len = sprintf(buf, "%s(%d): unaligned access to 0x%016lx, "
- "ip=0x%016lx\n\r", current->comm, current->pid,
+ "ip=0x%016lx\n\r", current->comm,
+ task_pid_nr(current),
ifa, regs->cr_iip + ipsr->ri);
/*
* Don't call tty_write_message() if we're in the kernel; we might
@@ -1363,7 +1364,7 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
"administrator\n"
"echo 0 > /proc/sys/kernel/ignore-"
"unaligned-usertrap to re-enable\n",
- current->comm, current->pid);
+ current->comm, task_pid_nr(current));
}
}
} else {
diff --git a/arch/ia64/kernel/uncached.c b/arch/ia64/kernel/uncached.c
index c58e933694d5..a7be4f203420 100644
--- a/arch/ia64/kernel/uncached.c
+++ b/arch/ia64/kernel/uncached.c
@@ -196,7 +196,7 @@ unsigned long uncached_alloc_page(int starting_nid)
nid = starting_nid;
do {
- if (!node_online(nid))
+ if (!node_state(nid, N_HIGH_MEMORY))
continue;
uc_pool = &uncached_pools[nid];
if (uc_pool->pool == NULL)
@@ -268,7 +268,7 @@ static int __init uncached_init(void)
{
int nid;
- for_each_online_node(nid) {
+ for_each_node_state(nid, N_ONLINE) {
uncached_pools[nid].pool = gen_pool_create(PAGE_SHIFT, nid);
mutex_init(&uncached_pools[nid].add_chunk_mutex);
}
diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c
index d3c538be466c..7e9c275ea148 100644
--- a/arch/ia64/mm/contig.c
+++ b/arch/ia64/mm/contig.c
@@ -146,6 +146,46 @@ find_bootmap_location (unsigned long start, unsigned long end, void *arg)
return 0;
}
+#ifdef CONFIG_SMP
+static void *cpu_data;
+/**
+ * per_cpu_init - setup per-cpu variables
+ *
+ * Allocate and setup per-cpu data areas.
+ */
+void * __cpuinit
+per_cpu_init (void)
+{
+ int cpu;
+ static int first_time=1;
+
+ /*
+ * get_free_pages() cannot be used before cpu_init() done. BSP
+ * allocates "NR_CPUS" pages for all CPUs to avoid that AP calls
+ * get_zeroed_page().
+ */
+ if (first_time) {
+ first_time=0;
+ for (cpu = 0; cpu < NR_CPUS; cpu++) {
+ memcpy(cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start);
+ __per_cpu_offset[cpu] = (char *) cpu_data - __per_cpu_start;
+ cpu_data += PERCPU_PAGE_SIZE;
+ per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu];
+ }
+ }
+ return __per_cpu_start + __per_cpu_offset[smp_processor_id()];
+}
+
+static inline void
+alloc_per_cpu_data(void)
+{
+ cpu_data = __alloc_bootmem(PERCPU_PAGE_SIZE * NR_CPUS,
+ PERCPU_PAGE_SIZE, __pa(MAX_DMA_ADDRESS));
+}
+#else
+#define alloc_per_cpu_data() do { } while (0)
+#endif /* CONFIG_SMP */
+
/**
* find_memory - setup memory map
*
@@ -182,41 +222,9 @@ find_memory (void)
find_initrd();
+ alloc_per_cpu_data();
}
-#ifdef CONFIG_SMP
-/**
- * per_cpu_init - setup per-cpu variables
- *
- * Allocate and setup per-cpu data areas.
- */
-void * __cpuinit
-per_cpu_init (void)
-{
- void *cpu_data;
- int cpu;
- static int first_time=1;
-
- /*
- * get_free_pages() cannot be used before cpu_init() done. BSP
- * allocates "NR_CPUS" pages for all CPUs to avoid that AP calls
- * get_zeroed_page().
- */
- if (first_time) {
- first_time=0;
- cpu_data = __alloc_bootmem(PERCPU_PAGE_SIZE * NR_CPUS,
- PERCPU_PAGE_SIZE, __pa(MAX_DMA_ADDRESS));
- for (cpu = 0; cpu < NR_CPUS; cpu++) {
- memcpy(cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start);
- __per_cpu_offset[cpu] = (char *) cpu_data - __per_cpu_start;
- cpu_data += PERCPU_PAGE_SIZE;
- per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu];
- }
- }
- return __per_cpu_start + __per_cpu_offset[smp_processor_id()];
-}
-#endif /* CONFIG_SMP */
-
static int
count_pages (u64 start, u64 end, void *arg)
{
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
index 0d34585058c8..0b567398f38e 100644
--- a/arch/ia64/mm/discontig.c
+++ b/arch/ia64/mm/discontig.c
@@ -48,7 +48,7 @@ struct early_node_data {
static struct early_node_data mem_data[MAX_NUMNODES] __initdata;
static nodemask_t memory_less_mask __initdata;
-static pg_data_t *pgdat_list[MAX_NUMNODES];
+pg_data_t *pgdat_list[MAX_NUMNODES];
/*
* To prevent cache aliasing effects, align per-node structures so that they
@@ -715,3 +715,11 @@ void arch_refresh_nodedata(int update_node, pg_data_t *update_pgdat)
scatter_node_data();
}
#endif
+
+#ifdef CONFIG_SPARSEMEM_VMEMMAP
+int __meminit vmemmap_populate(struct page *start_page,
+ unsigned long size, int node)
+{
+ return vmemmap_populate_basepages(start_page, size, node);
+}
+#endif
diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c
index 9150ffaff9e8..7571076a16a1 100644
--- a/arch/ia64/mm/fault.c
+++ b/arch/ia64/mm/fault.c
@@ -274,13 +274,13 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
out_of_memory:
up_read(&mm->mmap_sem);
- if (is_init(current)) {
+ if (is_global_init(current)) {
yield();
down_read(&mm->mmap_sem);
goto survive;
}
printk(KERN_CRIT "VM: killing process %s\n", current->comm);
if (user_mode(regs))
- do_exit(SIGKILL);
+ do_group_exit(SIGKILL);
goto no_context;
}
diff --git a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c
index a9ff685aea25..d3ce8f3bcaa6 100644
--- a/arch/ia64/mm/hugetlbpage.c
+++ b/arch/ia64/mm/hugetlbpage.c
@@ -194,6 +194,6 @@ static int __init hugetlb_setup_sz(char *str)
* override here with new page shift.
*/
ia64_set_rr(HPAGE_REGION_BASE, hpage_shift << 2);
- return 1;
+ return 0;
}
-__setup("hugepagesz=", hugetlb_setup_sz);
+early_param("hugepagesz", hugetlb_setup_sz);
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index c14abefabafa..25aef6211a54 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -54,15 +54,12 @@ struct page *zero_page_memmap_ptr; /* map entry for zero page */
EXPORT_SYMBOL(zero_page_memmap_ptr);
void
-lazy_mmu_prot_update (pte_t pte)
+__ia64_sync_icache_dcache (pte_t pte)
{
unsigned long addr;
struct page *page;
unsigned long order;
- if (!pte_exec(pte))
- return; /* not an executable page... */
-
page = pte_page(pte);
addr = (unsigned long) page_address(page);
@@ -130,8 +127,8 @@ ia64_init_addr_space (void)
vma->vm_mm = current->mm;
vma->vm_start = current->thread.rbs_bot & PAGE_MASK;
vma->vm_end = vma->vm_start + PAGE_SIZE;
- vma->vm_page_prot = protection_map[VM_DATA_DEFAULT_FLAGS & 0x7];
vma->vm_flags = VM_DATA_DEFAULT_FLAGS|VM_GROWSUP|VM_ACCOUNT;
+ vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
down_write(&current->mm->mmap_sem);
if (insert_vm_struct(current->mm, vma)) {
up_write(&current->mm->mmap_sem);
@@ -475,7 +472,7 @@ struct memmap_init_callback_data {
unsigned long zone;
};
-static int
+static int __meminit
virtual_memmap_init (u64 start, u64 end, void *arg)
{
struct memmap_init_callback_data *args;
@@ -506,7 +503,7 @@ virtual_memmap_init (u64 start, u64 end, void *arg)
return 0;
}
-void
+void __meminit
memmap_init (unsigned long size, int nid, unsigned long zone,
unsigned long start_pfn)
{
@@ -721,10 +718,21 @@ int arch_add_memory(int nid, u64 start, u64 size)
return ret;
}
-
+#ifdef CONFIG_MEMORY_HOTREMOVE
int remove_memory(u64 start, u64 size)
{
- return -EINVAL;
+ unsigned long start_pfn, end_pfn;
+ unsigned long timeout = 120 * HZ;
+ int ret;
+ start_pfn = start >> PAGE_SHIFT;
+ end_pfn = start_pfn + (size >> PAGE_SHIFT);
+ ret = offline_pages(start_pfn, end_pfn, timeout);
+ if (ret)
+ goto out;
+ /* we can free mem_map at this point */
+out:
+ return ret;
}
EXPORT_SYMBOL_GPL(remove_memory);
+#endif /* CONFIG_MEMORY_HOTREMOVE */
#endif
diff --git a/arch/ia64/oprofile/Kconfig b/arch/ia64/oprofile/Kconfig
deleted file mode 100644
index 97271ab484dc..000000000000
--- a/arch/ia64/oprofile/Kconfig
+++ /dev/null
@@ -1,20 +0,0 @@
-config PROFILING
- bool "Profiling support (EXPERIMENTAL)"
- help
- Say Y here to enable the extended profiling support mechanisms used
- by profilers such as OProfile.
-
-config OPROFILE
- tristate "OProfile system profiling (EXPERIMENTAL)"
- depends on PROFILING
- help
- OProfile is a profiling system capable of profiling the
- whole system, include the kernel, kernel modules, libraries,
- and applications.
-
- Due to firmware bugs, you may need to use the "nohalt" boot
- option if you're using OProfile with the hardware performance
- counters.
-
- If unsure, say N.
-
diff --git a/arch/ia64/scripts/check-segrel.lds b/arch/ia64/scripts/check-segrel.lds
index 1c2f13e181d0..85a0d54fb5ab 100644
--- a/arch/ia64/scripts/check-segrel.lds
+++ b/arch/ia64/scripts/check-segrel.lds
@@ -1,6 +1,7 @@
SECTIONS {
. = SIZEOF_HEADERS;
.rodata : { *(.rodata) } :ro
+ .note : { *(.note*) }
. = 0xa0000;
.data : { *(.data) } :dat
/DISCARD/ : { *(*) }
diff --git a/arch/ia64/sn/kernel/Makefile b/arch/ia64/sn/kernel/Makefile
index 0a59371d3475..688a3c27e0f6 100644
--- a/arch/ia64/sn/kernel/Makefile
+++ b/arch/ia64/sn/kernel/Makefile
@@ -7,7 +7,7 @@
# Copyright (C) 1999,2001-2006 Silicon Graphics, Inc. All Rights Reserved.
#
-CPPFLAGS += -I$(srctree)/arch/ia64/sn/include
+EXTRA_CFLAGS += -Iarch/ia64/sn/include
obj-y += setup.o bte.o bte_error.o irq.o mca.o idle.o \
huberror.o io_acpi_init.o io_common.o \
diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c
index 0f9b12683bf3..53351c3cd7b1 100644
--- a/arch/ia64/sn/kernel/irq.c
+++ b/arch/ia64/sn/kernel/irq.c
@@ -5,7 +5,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (c) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2007 Silicon Graphics, Inc. All Rights Reserved.
*/
#include <linux/irq.h>
@@ -85,12 +85,18 @@ static void sn_shutdown_irq(unsigned int irq)
{
}
+extern void ia64_mca_register_cpev(int);
+
static void sn_disable_irq(unsigned int irq)
{
+ if (irq == local_vector_to_irq(IA64_CPE_VECTOR))
+ ia64_mca_register_cpev(0);
}
static void sn_enable_irq(unsigned int irq)
{
+ if (irq == local_vector_to_irq(IA64_CPE_VECTOR))
+ ia64_mca_register_cpev(irq);
}
static void sn_ack_irq(unsigned int irq)
diff --git a/arch/ia64/sn/kernel/mca.c b/arch/ia64/sn/kernel/mca.c
index 3db62f24596c..868c9aa64fe2 100644
--- a/arch/ia64/sn/kernel/mca.c
+++ b/arch/ia64/sn/kernel/mca.c
@@ -98,6 +98,7 @@ sn_platform_plat_specific_err_print(const u8 * sect_header, u8 ** oemdata,
while (*sn_oemdata_size > sn_oemdata_bufsize) {
u8 *newbuf = vmalloc(*sn_oemdata_size);
if (!newbuf) {
+ mutex_unlock(&sn_oemdata_mutex);
printk(KERN_ERR "%s: unable to extend sn_oemdata\n",
__FUNCTION__);
return 1;
diff --git a/arch/ia64/sn/kernel/sn2/Makefile b/arch/ia64/sn/kernel/sn2/Makefile
index 99e177693234..08e6565dc908 100644
--- a/arch/ia64/sn/kernel/sn2/Makefile
+++ b/arch/ia64/sn/kernel/sn2/Makefile
@@ -9,7 +9,7 @@
# sn2 specific kernel files
#
-CPPFLAGS += -I$(srctree)/arch/ia64/sn/include
+EXTRA_CFLAGS += -Iarch/ia64/sn/include
obj-y += cache.o io.o ptc_deadlock.o sn2_smp.o sn_proc_fs.o \
prominfo_proc.o timer.o timer_interrupt.o sn_hwperf.o
diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c
index e336e1692a73..81785b78bc1e 100644
--- a/arch/ia64/sn/kernel/xpc_main.c
+++ b/arch/ia64/sn/kernel/xpc_main.c
@@ -3,7 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (c) 2004-2006 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2004-2007 Silicon Graphics, Inc. All Rights Reserved.
*/
@@ -257,7 +257,9 @@ xpc_hb_checker(void *ignore)
set_cpus_allowed(current, cpumask_of_cpu(XPC_HB_CHECK_CPU));
+ /* set our heartbeating to other partitions into motion */
xpc_hb_check_timeout = jiffies + (xpc_hb_check_interval * HZ);
+ xpc_hb_beater(0);
while (!(volatile int) xpc_exiting) {
@@ -1338,16 +1340,8 @@ xpc_init(void)
dev_warn(xpc_part, "can't register die notifier\n");
}
-
- /*
- * Set the beating to other partitions into motion. This is
- * the last requirement for other partitions' discovery to
- * initiate communications with us.
- */
init_timer(&xpc_hb_timer);
xpc_hb_timer.function = xpc_hb_beater;
- xpc_hb_beater(0);
-
/*
* The real work-horse behind xpc. This processes incoming
diff --git a/arch/ia64/sn/kernel/xpnet.c b/arch/ia64/sn/kernel/xpnet.c
index e58fcadff2e9..a5df672d8392 100644
--- a/arch/ia64/sn/kernel/xpnet.c
+++ b/arch/ia64/sn/kernel/xpnet.c
@@ -269,8 +269,9 @@ xpnet_receive(partid_t partid, int channel, struct xpnet_message *msg)
skb->protocol = eth_type_trans(skb, xpnet_device);
skb->ip_summed = CHECKSUM_UNNECESSARY;
- dev_dbg(xpnet, "passing skb to network layer; \n\tskb->head=0x%p "
- "skb->data=0x%p skb->tail=0x%p skb->end=0x%p skb->len=%d\n",
+ dev_dbg(xpnet, "passing skb to network layer\n"
+ KERN_DEBUG "\tskb->head=0x%p skb->data=0x%p skb->tail=0x%p "
+ "skb->end=0x%p skb->len=%d\n",
(void *)skb->head, (void *)skb->data, skb_tail_pointer(skb),
skb_end_pointer(skb), skb->len);
@@ -576,10 +577,10 @@ xpnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
msg->tailout_ignore = end_addr - (u64)skb_tail_pointer(skb);
msg->buf_pa = __pa(start_addr);
- dev_dbg(xpnet, "sending XPC message to %d:%d\nmsg->buf_pa="
- "0x%lx, msg->size=%u, msg->leadin_ignore=%u, "
- "msg->tailout_ignore=%u\n", dest_partid,
- XPC_NET_CHANNEL, msg->buf_pa, msg->size,
+ dev_dbg(xpnet, "sending XPC message to %d:%d\n"
+ KERN_DEBUG "msg->buf_pa=0x%lx, msg->size=%u, "
+ "msg->leadin_ignore=%u, msg->tailout_ignore=%u\n",
+ dest_partid, XPC_NET_CHANNEL, msg->buf_pa, msg->size,
msg->leadin_ignore, msg->tailout_ignore);
diff --git a/arch/ia64/sn/pci/Makefile b/arch/ia64/sn/pci/Makefile
index c6946784a6a8..ad4ef34dfe26 100644
--- a/arch/ia64/sn/pci/Makefile
+++ b/arch/ia64/sn/pci/Makefile
@@ -7,6 +7,6 @@
#
# Makefile for the sn pci general routines.
-CPPFLAGS += -I$(srctree)/arch/ia64/sn/include
+EXTRA_CFLAGS += -Iarch/ia64/sn/include
obj-y := pci_dma.o tioca_provider.o tioce_provider.o pcibr/
diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c
index d79ddacfba2d..511db2fd7bff 100644
--- a/arch/ia64/sn/pci/pci_dma.c
+++ b/arch/ia64/sn/pci/pci_dma.c
@@ -16,7 +16,7 @@
#include <asm/sn/pcidev.h>
#include <asm/sn/sn_sal.h>
-#define SG_ENT_VIRT_ADDRESS(sg) (page_address((sg)->page) + (sg)->offset)
+#define SG_ENT_VIRT_ADDRESS(sg) (sg_virt((sg)))
#define SG_ENT_PHYS_ADDRESS(SG) virt_to_phys(SG_ENT_VIRT_ADDRESS(SG))
/**
@@ -218,16 +218,17 @@ EXPORT_SYMBOL(sn_dma_unmap_single);
*
* Unmap a set of streaming mode DMA translations.
*/
-void sn_dma_unmap_sg(struct device *dev, struct scatterlist *sg,
+void sn_dma_unmap_sg(struct device *dev, struct scatterlist *sgl,
int nhwentries, int direction)
{
int i;
struct pci_dev *pdev = to_pci_dev(dev);
struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
+ struct scatterlist *sg;
BUG_ON(dev->bus != &pci_bus_type);
- for (i = 0; i < nhwentries; i++, sg++) {
+ for_each_sg(sgl, sg, nhwentries, i) {
provider->dma_unmap(pdev, sg->dma_address, direction);
sg->dma_address = (dma_addr_t) NULL;
sg->dma_length = 0;
@@ -244,11 +245,11 @@ EXPORT_SYMBOL(sn_dma_unmap_sg);
*
* Maps each entry of @sg for DMA.
*/
-int sn_dma_map_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
+int sn_dma_map_sg(struct device *dev, struct scatterlist *sgl, int nhwentries,
int direction)
{
unsigned long phys_addr;
- struct scatterlist *saved_sg = sg;
+ struct scatterlist *saved_sg = sgl, *sg;
struct pci_dev *pdev = to_pci_dev(dev);
struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
int i;
@@ -258,7 +259,7 @@ int sn_dma_map_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
/*
* Setup a DMA address for each entry in the scatterlist.
*/
- for (i = 0; i < nhwentries; i++, sg++) {
+ for_each_sg(sgl, sg, nhwentries, i) {
phys_addr = SG_ENT_PHYS_ADDRESS(sg);
sg->dma_address = provider->dma_map(pdev,
phys_addr, sg->length,
diff --git a/arch/ia64/sn/pci/pcibr/Makefile b/arch/ia64/sn/pci/pcibr/Makefile
index 3b403ea456f9..01192d3247dd 100644
--- a/arch/ia64/sn/pci/pcibr/Makefile
+++ b/arch/ia64/sn/pci/pcibr/Makefile
@@ -7,7 +7,7 @@
#
# Makefile for the sn2 io routines.
-CPPFLAGS += -I$(srctree)/arch/ia64/sn/include
+EXTRA_CFLAGS += -Iarch/ia64/sn/include
obj-y += pcibr_dma.o pcibr_reg.o \
pcibr_ate.o pcibr_provider.o
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index bd5fe76401f1..ab9a264cb194 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -426,7 +426,7 @@ source "drivers/Kconfig"
source "fs/Kconfig"
-source "arch/m32r/oprofile/Kconfig"
+source "kernel/Kconfig.instrumentation"
source "arch/m32r/Kconfig.debug"
diff --git a/arch/m32r/Makefile b/arch/m32r/Makefile
index 60e12f312654..4072a07ebf8e 100644
--- a/arch/m32r/Makefile
+++ b/arch/m32r/Makefile
@@ -9,7 +9,7 @@ LDFLAGS :=
OBJCOPYFLAGS := -O binary -R .note -R .comment -S
LDFLAGS_vmlinux :=
-CFLAGS += -pipe -fno-schedule-insns
+KBUILD_CFLAGS += -pipe -fno-schedule-insns
CFLAGS_KERNEL += -mmodel=medium
CFLAGS_MODULE += -mmodel=large
@@ -24,14 +24,14 @@ endif
cflags-$(CONFIG_ISA_M32R) += -DNO_FPU
aflags-$(CONFIG_ISA_M32R) += -DNO_FPU -O2 -Wa,-no-bitinst
-CFLAGS += $(cflags-y)
-AFLAGS += $(aflags-y)
+KBUILD_CFLAGS += $(cflags-y)
+KBUILD_AFLAGS += $(aflags-y)
CHECKFLAGS += -D__m32r__ -D__BIG_ENDIAN__=1
head-y := arch/m32r/kernel/head.o arch/m32r/kernel/init_task.o
-LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
+LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
libs-y += arch/m32r/lib/ $(LIBGCC)
core-y += arch/m32r/kernel/ \
diff --git a/arch/m32r/kernel/irq.c b/arch/m32r/kernel/irq.c
index f8d8650383e0..d0c5b0b7da2f 100644
--- a/arch/m32r/kernel/irq.c
+++ b/arch/m32r/kernel/irq.c
@@ -71,7 +71,7 @@ skip:
}
/*
- * do_IRQ handles all normal device IRQ's (the special
+ * do_IRQ handles all normal device IRQs (the special
* SMP cross-CPU interrupts have their own specific
* handlers).
*/
diff --git a/arch/m32r/kernel/ptrace.c b/arch/m32r/kernel/ptrace.c
index 62a51429306e..ed4d0756c5db 100644
--- a/arch/m32r/kernel/ptrace.c
+++ b/arch/m32r/kernel/ptrace.c
@@ -570,7 +570,7 @@ withdraw_debug_trap(struct pt_regs *regs)
}
}
-static void
+void
init_debug_traps(struct task_struct *child)
{
struct debug_trap *p = &child->thread.debug_trap;
@@ -593,8 +593,8 @@ void ptrace_disable(struct task_struct *child)
/* nothing to do.. */
}
-static int
-do_ptrace(long request, struct task_struct *child, long addr, long data)
+long
+arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
int ret;
@@ -704,14 +704,6 @@ do_ptrace(long request, struct task_struct *child, long addr, long data)
break;
}
- /*
- * detach a process that was attached.
- */
- case PTRACE_DETACH:
- ret = 0;
- ret = ptrace_detach(child, data);
- break;
-
case PTRACE_GETREGS:
ret = ptrace_getregs(child, (void __user *)data);
break;
@@ -728,42 +720,6 @@ do_ptrace(long request, struct task_struct *child, long addr, long data)
return ret;
}
-asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
-{
- struct task_struct *child;
- int ret;
-
- lock_kernel();
- if (request == PTRACE_TRACEME) {
- ret = ptrace_traceme();
- goto out;
- }
-
- child = ptrace_get_task_struct(pid);
- if (IS_ERR(child)) {
- ret = PTR_ERR(child);
- goto out;
- }
-
- if (request == PTRACE_ATTACH) {
- ret = ptrace_attach(child);
- if (ret == 0)
- init_debug_traps(child);
- goto out_tsk;
- }
-
- ret = ptrace_check_attach(child, request == PTRACE_KILL);
- if (ret == 0)
- ret = do_ptrace(request, child, addr, data);
-
-out_tsk:
- put_task_struct(child);
-out:
- unlock_kernel();
-
- return ret;
-}
-
/* notification of system call entry/exit
* - triggered by current->work.syscall_trace
*/
diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c
index 916faf6070af..a753d79c4e89 100644
--- a/arch/m32r/kernel/signal.c
+++ b/arch/m32r/kernel/signal.c
@@ -358,7 +358,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) {
- /* Reenable any watchpoints before delivering the
+ /* Re-enable any watchpoints before delivering the
* signal to user space. The processor register will
* have been cleared if the watchpoint triggered
* inside the kernel.
diff --git a/arch/m32r/kernel/smp.c b/arch/m32r/kernel/smp.c
index 360129174b2b..c837bc13b015 100644
--- a/arch/m32r/kernel/smp.c
+++ b/arch/m32r/kernel/smp.c
@@ -202,7 +202,7 @@ void smp_flush_cache_all_interrupt(void)
}
/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
-/* TLB flush request Routins */
+/* TLB flush request Routines */
/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
/*==========================================================================*
@@ -378,7 +378,7 @@ void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long va)
* Name: flush_tlb_others
*
* Description: This routine requests other CPU to execute flush TLB.
- * 1.Setup parmeters.
+ * 1.Setup parameters.
* 2.Send 'INVALIDATE_TLB_IPI' to other CPU.
* Request other CPU to execute 'smp_invalidate_interrupt()'.
* 3.Wait for other CPUs operation finished.
@@ -502,7 +502,7 @@ void smp_invalidate_interrupt(void)
}
/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
-/* Stop CPU request Routins */
+/* Stop CPU request Routines */
/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
/*==========================================================================*
@@ -566,7 +566,7 @@ static void stop_this_cpu(void *dummy)
}
/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
-/* Call function Routins */
+/* Call function Routines */
/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
/*==========================================================================*
@@ -690,7 +690,7 @@ void smp_call_function_interrupt(void)
}
/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
-/* Timer Routins */
+/* Timer Routines */
/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
/*==========================================================================*
@@ -802,7 +802,7 @@ void smp_local_timer_interrupt(void)
}
/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
-/* Send IPI Routins */
+/* Send IPI Routines */
/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
/*==========================================================================*
@@ -814,7 +814,7 @@ void smp_local_timer_interrupt(void)
*
* Arguments: ipi_num - Number of IPI
* try - 0 : Send IPI certainly.
- * !0 : The following IPI is not sended when Target CPU
+ * !0 : The following IPI is not sent when Target CPU
* has not received the before IPI.
*
* Returns: void (cannot fail)
@@ -844,7 +844,7 @@ void send_IPI_allbutself(int ipi_num, int try)
* Arguments: cpu_mask - Bitmap of target CPUs logical ID
* ipi_num - Number of IPI
* try - 0 : Send IPI certainly.
- * !0 : The following IPI is not sended when Target CPU
+ * !0 : The following IPI is not sent when Target CPU
* has not received the before IPI.
*
* Returns: void (cannot fail)
@@ -885,7 +885,7 @@ static void send_IPI_mask(cpumask_t cpumask, int ipi_num, int try)
* Arguments: cpu_mask - Bitmap of target CPUs physical ID
* ipi_num - Number of IPI
* try - 0 : Send IPI certainly.
- * !0 : The following IPI is not sended when Target CPU
+ * !0 : The following IPI is not sent when Target CPU
* has not received the before IPI.
*
* Returns: IPICRi regster value.
diff --git a/arch/m32r/kernel/smpboot.c b/arch/m32r/kernel/smpboot.c
index 9dae410014d8..0e383da158e9 100644
--- a/arch/m32r/kernel/smpboot.c
+++ b/arch/m32r/kernel/smpboot.c
@@ -133,7 +133,7 @@ static void map_cpu_to_physid(int, int);
static void unmap_cpu_to_physid(int, int);
/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
-/* Boot up APs Routins : BSP */
+/* Boot up APs Routines : BSP */
/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
void __devinit smp_prepare_boot_cpu(void)
{
@@ -404,7 +404,7 @@ void __init smp_cpus_done(unsigned int max_cpus)
}
/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
-/* Activate a secondary processor Routins */
+/* Activate a secondary processor Routines */
/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
/*==========================================================================*
@@ -509,7 +509,7 @@ static void __init smp_online(void)
}
/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
-/* Boot up CPUs common Routins */
+/* Boot up CPUs common Routines */
/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
static void __init show_mp_info(int nr_cpu)
{
diff --git a/arch/m32r/kernel/sys_m32r.c b/arch/m32r/kernel/sys_m32r.c
index b13dbbeaeafa..6d7a80fdad48 100644
--- a/arch/m32r/kernel/sys_m32r.c
+++ b/arch/m32r/kernel/sys_m32r.c
@@ -20,11 +20,11 @@
#include <linux/mman.h>
#include <linux/file.h>
#include <linux/utsname.h>
+#include <linux/ipc.h>
#include <asm/uaccess.h>
#include <asm/cachectl.h>
#include <asm/cacheflush.h>
-#include <asm/ipc.h>
#include <asm/syscall.h>
#include <asm/unistd.h>
@@ -214,7 +214,7 @@ asmlinkage int sys_uname(struct old_utsname __user * name)
asmlinkage int sys_cacheflush(void *addr, int bytes, int cache)
{
- /* This should flush more selectivly ... */
+ /* This should flush more selectively ... */
_flush_cache_all();
return 0;
}
diff --git a/arch/m32r/kernel/time.c b/arch/m32r/kernel/time.c
index 3858c9f39ba5..994cc1556355 100644
--- a/arch/m32r/kernel/time.c
+++ b/arch/m32r/kernel/time.c
@@ -228,8 +228,12 @@ irqreturn_t timer_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-struct irqaction irq0 = { timer_interrupt, IRQF_DISABLED, CPU_MASK_NONE,
- "MFT2", NULL, NULL };
+struct irqaction irq0 = {
+ .handler = timer_interrupt,
+ .flags = IRQF_DISABLED,
+ .mask = CPU_MASK_NONE,
+ .name = "MFT2",
+};
void __init time_init(void)
{
diff --git a/arch/m32r/kernel/traps.c b/arch/m32r/kernel/traps.c
index 97e0b1c0830e..89ba4a0b5d51 100644
--- a/arch/m32r/kernel/traps.c
+++ b/arch/m32r/kernel/traps.c
@@ -196,7 +196,7 @@ static void show_registers(struct pt_regs *regs)
printk("SPI: %08lx\n", sp);
}
printk("Process %s (pid: %d, process nr: %d, stackpage=%08lx)",
- current->comm, current->pid, 0xffff & i, 4096+(unsigned long)current);
+ current->comm, task_pid_nr(current), 0xffff & i, 4096+(unsigned long)current);
/*
* When in-kernel, we also print out the stack and code at the
diff --git a/arch/m32r/mm/fault.c b/arch/m32r/mm/fault.c
index 676a1c443d28..4a71df4c1b30 100644
--- a/arch/m32r/mm/fault.c
+++ b/arch/m32r/mm/fault.c
@@ -271,14 +271,14 @@ no_context:
*/
out_of_memory:
up_read(&mm->mmap_sem);
- if (is_init(tsk)) {
+ if (is_global_init(tsk)) {
yield();
down_read(&mm->mmap_sem);
goto survive;
}
printk("VM: killing process %s\n", tsk->comm);
if (error_code & ACE_USERMODE)
- do_exit(SIGKILL);
+ do_group_exit(SIGKILL);
goto no_context;
do_sigbus:
diff --git a/arch/m32r/oprofile/Kconfig b/arch/m32r/oprofile/Kconfig
deleted file mode 100644
index 19d37730b664..000000000000
--- a/arch/m32r/oprofile/Kconfig
+++ /dev/null
@@ -1,23 +0,0 @@
-
-menu "Profiling support"
- depends on EXPERIMENTAL
-
-config PROFILING
- bool "Profiling support (EXPERIMENTAL)"
- help
- Say Y here to enable the extended profiling support mechanisms used
- by profilers such as OProfile.
-
-
-config OPROFILE
- tristate "OProfile system profiling (EXPERIMENTAL)"
- depends on PROFILING
- help
- OProfile is a profiling system capable of profiling the
- whole system, include the kernel, kernel modules, libraries,
- and applications.
-
- If unsure, say N.
-
-endmenu
-
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 20a9c08e59c3..01dee84f840a 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -683,6 +683,8 @@ endmenu
source "fs/Kconfig"
+source "kernel/Kconfig.instrumentation"
+
source "arch/m68k/Kconfig.debug"
source "security/Kconfig"
diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile
index aa383a5ea7ac..4a1bd44ff162 100644
--- a/arch/m68k/Makefile
+++ b/arch/m68k/Makefile
@@ -32,18 +32,18 @@ endif
CHECKFLAGS += -D__mc68000__
# without -fno-strength-reduce the 53c7xx.c driver fails ;-(
-CFLAGS += -pipe -fno-strength-reduce -ffixed-a2
+KBUILD_CFLAGS += -pipe -fno-strength-reduce -ffixed-a2
# enable processor switch if compiled only for a single cpu
ifndef CONFIG_M68020
ifndef CONFIG_M68030
ifndef CONFIG_M68060
-CFLAGS := $(CFLAGS) -m68040
+KBUILD_CFLAGS += -m68040
endif
ifndef CONFIG_M68040
-CFLAGS := $(CFLAGS) -m68060
+KBUILD_CFLAGS += -m68060
endif
endif
@@ -52,7 +52,7 @@ endif
ifdef CONFIG_KGDB
# If configured for kgdb support, include debugging infos and keep the
# frame pointer
-CFLAGS := $(subst -fomit-frame-pointer,,$(CFLAGS)) -g
+KBUILD_CFLAGS := $(subst -fomit-frame-pointer,,$(KBUILD_CFLAGS)) -g
endif
ifndef CONFIG_SUN3
diff --git a/arch/m68k/amiga/pcmcia.c b/arch/m68k/amiga/pcmcia.c
index fc57c6e72acf..186662ca1a89 100644
--- a/arch/m68k/amiga/pcmcia.c
+++ b/arch/m68k/amiga/pcmcia.c
@@ -33,7 +33,7 @@ void pcmcia_reset(void)
/* copy a tuple, including tuple header. return nb bytes copied */
-/* be carefull as this may trigger a GAYLE_IRQ_WR interrupt ! */
+/* be careful as this may trigger a GAYLE_IRQ_WR interrupt ! */
int pcmcia_copy_tuple(unsigned char tuple_id, void *tuple, int max_len)
{
diff --git a/arch/m68k/ifpsp060/CHANGES b/arch/m68k/ifpsp060/CHANGES
index c1e712dfc2e7..ba96596910fd 100644
--- a/arch/m68k/ifpsp060/CHANGES
+++ b/arch/m68k/ifpsp060/CHANGES
@@ -4,7 +4,7 @@ M68000 Hi-Performance Microprocessor Division
M68060 Software Package
Production Release P1.00 -- October 10, 1994
-M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
+M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
THE SOFTWARE is provided on an "AS IS" basis and without warranty.
To the maximum extent permitted by applicable law,
diff --git a/arch/m68k/ifpsp060/MISC b/arch/m68k/ifpsp060/MISC
index b7e644b94ae2..1a63913daa16 100644
--- a/arch/m68k/ifpsp060/MISC
+++ b/arch/m68k/ifpsp060/MISC
@@ -4,7 +4,7 @@ M68000 Hi-Performance Microprocessor Division
M68060 Software Package
Production Release P1.00 -- October 10, 1994
-M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
+M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
THE SOFTWARE is provided on an "AS IS" basis and without warranty.
To the maximum extent permitted by applicable law,
diff --git a/arch/m68k/ifpsp060/README b/arch/m68k/ifpsp060/README
index e3bced429bd3..f6f8f5c59419 100644
--- a/arch/m68k/ifpsp060/README
+++ b/arch/m68k/ifpsp060/README
@@ -4,7 +4,7 @@ M68000 Hi-Performance Microprocessor Division
M68060 Software Package
Production Release P1.00 -- October 10, 1994
-M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
+M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
THE SOFTWARE is provided on an "AS IS" basis and without warranty.
To the maximum extent permitted by applicable law,
diff --git a/arch/m68k/ifpsp060/TEST.DOC b/arch/m68k/ifpsp060/TEST.DOC
index 5e5900cb2dc4..1ba3aef1500f 100644
--- a/arch/m68k/ifpsp060/TEST.DOC
+++ b/arch/m68k/ifpsp060/TEST.DOC
@@ -4,7 +4,7 @@ M68000 Hi-Performance Microprocessor Division
M68060 Software Package
Production Release P1.00 -- October 10, 1994
-M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
+M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
THE SOFTWARE is provided on an "AS IS" basis and without warranty.
To the maximum extent permitted by applicable law,
diff --git a/arch/m68k/ifpsp060/fplsp.doc b/arch/m68k/ifpsp060/fplsp.doc
index fb637c436762..89730a934c5e 100644
--- a/arch/m68k/ifpsp060/fplsp.doc
+++ b/arch/m68k/ifpsp060/fplsp.doc
@@ -4,7 +4,7 @@ M68000 Hi-Performance Microprocessor Division
M68060 Software Package
Production Release P1.00 -- October 10, 1994
-M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
+M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
THE SOFTWARE is provided on an "AS IS" basis and without warranty.
To the maximum extent permitted by applicable law,
diff --git a/arch/m68k/ifpsp060/fpsp.doc b/arch/m68k/ifpsp060/fpsp.doc
index 408315209e62..23d513f72ed9 100644
--- a/arch/m68k/ifpsp060/fpsp.doc
+++ b/arch/m68k/ifpsp060/fpsp.doc
@@ -4,7 +4,7 @@ M68000 Hi-Performance Microprocessor Division
M68060 Software Package
Production Release P1.00 -- October 10, 1994
-M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
+M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
THE SOFTWARE is provided on an "AS IS" basis and without warranty.
To the maximum extent permitted by applicable law,
diff --git a/arch/m68k/ifpsp060/fskeleton.S b/arch/m68k/ifpsp060/fskeleton.S
index a45a4ff9d2af..0a1ae4f44130 100644
--- a/arch/m68k/ifpsp060/fskeleton.S
+++ b/arch/m68k/ifpsp060/fskeleton.S
@@ -4,7 +4,7 @@
|M68060 Software Package
|Production Release P1.00 -- October 10, 1994
|
-|M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
+|M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
|
|THE SOFTWARE is provided on an "AS IS" basis and without warranty.
|To the maximum extent permitted by applicable law,
diff --git a/arch/m68k/ifpsp060/ilsp.doc b/arch/m68k/ifpsp060/ilsp.doc
index f6fae6d900ae..4e6292f095aa 100644
--- a/arch/m68k/ifpsp060/ilsp.doc
+++ b/arch/m68k/ifpsp060/ilsp.doc
@@ -4,7 +4,7 @@ M68000 Hi-Performance Microprocessor Division
M68060 Software Package
Production Release P1.00 -- October 10, 1994
-M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
+M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
THE SOFTWARE is provided on an "AS IS" basis and without warranty.
To the maximum extent permitted by applicable law,
diff --git a/arch/m68k/ifpsp060/iskeleton.S b/arch/m68k/ifpsp060/iskeleton.S
index b2dbdf5ee309..91a9c65fee8a 100644
--- a/arch/m68k/ifpsp060/iskeleton.S
+++ b/arch/m68k/ifpsp060/iskeleton.S
@@ -4,7 +4,7 @@
|M68060 Software Package
|Production Release P1.00 -- October 10, 1994
|
-|M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
+|M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
|
|THE SOFTWARE is provided on an "AS IS" basis and without warranty.
|To the maximum extent permitted by applicable law,
diff --git a/arch/m68k/ifpsp060/isp.doc b/arch/m68k/ifpsp060/isp.doc
index 5a90fded3f0b..9dadd727fc50 100644
--- a/arch/m68k/ifpsp060/isp.doc
+++ b/arch/m68k/ifpsp060/isp.doc
@@ -4,7 +4,7 @@ M68000 Hi-Performance Microprocessor Division
M68060 Software Package
Production Release P1.00 -- October 10, 1994
-M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
+M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
THE SOFTWARE is provided on an "AS IS" basis and without warranty.
To the maximum extent permitted by applicable law,
diff --git a/arch/m68k/ifpsp060/os.S b/arch/m68k/ifpsp060/os.S
index aa4df87a6c42..7a0d6e428066 100644
--- a/arch/m68k/ifpsp060/os.S
+++ b/arch/m68k/ifpsp060/os.S
@@ -4,7 +4,7 @@
|M68060 Software Package
|Production Release P1.00 -- October 10, 1994
|
-|M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
+|M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
|
|THE SOFTWARE is provided on an "AS IS" basis and without warranty.
|To the maximum extent permitted by applicable law,
diff --git a/arch/m68k/ifpsp060/src/fplsp.S b/arch/m68k/ifpsp060/src/fplsp.S
index fdb79b927ef1..3b7ea2dc9f1b 100644
--- a/arch/m68k/ifpsp060/src/fplsp.S
+++ b/arch/m68k/ifpsp060/src/fplsp.S
@@ -4,7 +4,7 @@ M68000 Hi-Performance Microprocessor Division
M68060 Software Package
Production Release P1.00 -- October 10, 1994
-M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
+M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
THE SOFTWARE is provided on an "AS IS" basis and without warranty.
To the maximum extent permitted by applicable law,
diff --git a/arch/m68k/ifpsp060/src/fpsp.S b/arch/m68k/ifpsp060/src/fpsp.S
index 3b597a9bbf43..6c1a9a217887 100644
--- a/arch/m68k/ifpsp060/src/fpsp.S
+++ b/arch/m68k/ifpsp060/src/fpsp.S
@@ -4,7 +4,7 @@ M68000 Hi-Performance Microprocessor Division
M68060 Software Package
Production Release P1.00 -- October 10, 1994
-M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
+M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
THE SOFTWARE is provided on an "AS IS" basis and without warranty.
To the maximum extent permitted by applicable law,
diff --git a/arch/m68k/ifpsp060/src/ftest.S b/arch/m68k/ifpsp060/src/ftest.S
index 2edcbae0fd53..1f947915d81e 100644
--- a/arch/m68k/ifpsp060/src/ftest.S
+++ b/arch/m68k/ifpsp060/src/ftest.S
@@ -4,7 +4,7 @@ M68000 Hi-Performance Microprocessor Division
M68060 Software Package
Production Release P1.00 -- October 10, 1994
-M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
+M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
THE SOFTWARE is provided on an "AS IS" basis and without warranty.
To the maximum extent permitted by applicable law,
diff --git a/arch/m68k/ifpsp060/src/ilsp.S b/arch/m68k/ifpsp060/src/ilsp.S
index afa7422cddb5..970abaf3303e 100644
--- a/arch/m68k/ifpsp060/src/ilsp.S
+++ b/arch/m68k/ifpsp060/src/ilsp.S
@@ -4,7 +4,7 @@ M68000 Hi-Performance Microprocessor Division
M68060 Software Package
Production Release P1.00 -- October 10, 1994
-M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
+M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
THE SOFTWARE is provided on an "AS IS" basis and without warranty.
To the maximum extent permitted by applicable law,
diff --git a/arch/m68k/ifpsp060/src/isp.S b/arch/m68k/ifpsp060/src/isp.S
index b269091d9df6..6dccda766e22 100644
--- a/arch/m68k/ifpsp060/src/isp.S
+++ b/arch/m68k/ifpsp060/src/isp.S
@@ -4,7 +4,7 @@ M68000 Hi-Performance Microprocessor Division
M68060 Software Package
Production Release P1.00 -- October 10, 1994
-M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
+M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
THE SOFTWARE is provided on an "AS IS" basis and without warranty.
To the maximum extent permitted by applicable law,
diff --git a/arch/m68k/ifpsp060/src/itest.S b/arch/m68k/ifpsp060/src/itest.S
index ba4a30cbcbea..beca47e7d514 100644
--- a/arch/m68k/ifpsp060/src/itest.S
+++ b/arch/m68k/ifpsp060/src/itest.S
@@ -4,7 +4,7 @@ M68000 Hi-Performance Microprocessor Division
M68060 Software Package
Production Release P1.00 -- October 10, 1994
-M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
+M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
THE SOFTWARE is provided on an "AS IS" basis and without warranty.
To the maximum extent permitted by applicable law,
diff --git a/arch/m68k/ifpsp060/src/pfpsp.S b/arch/m68k/ifpsp060/src/pfpsp.S
index 0c997c436beb..51b9f7d879dd 100644
--- a/arch/m68k/ifpsp060/src/pfpsp.S
+++ b/arch/m68k/ifpsp060/src/pfpsp.S
@@ -4,7 +4,7 @@ M68000 Hi-Performance Microprocessor Division
M68060 Software Package
Production Release P1.00 -- October 10, 1994
-M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
+M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
THE SOFTWARE is provided on an "AS IS" basis and without warranty.
To the maximum extent permitted by applicable law,
diff --git a/arch/m68k/kernel/dma.c b/arch/m68k/kernel/dma.c
index 9d4e4b5b6bd8..6f8c080dd9f9 100644
--- a/arch/m68k/kernel/dma.c
+++ b/arch/m68k/kernel/dma.c
@@ -9,10 +9,10 @@
#include <linux/dma-mapping.h>
#include <linux/device.h>
#include <linux/kernel.h>
+#include <linux/scatterlist.h>
#include <linux/vmalloc.h>
#include <asm/pgalloc.h>
-#include <asm/scatterlist.h>
void *dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *handle, gfp_t flag)
@@ -121,7 +121,7 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
int i;
for (i = 0; i < nents; sg++, i++) {
- sg->dma_address = page_to_phys(sg->page) + sg->offset;
+ sg->dma_address = sg_phys(sg);
dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir);
}
return nents;
diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c
index e792d3cba4c7..2075543c2d92 100644
--- a/arch/m68k/kernel/ptrace.c
+++ b/arch/m68k/kernel/ptrace.c
@@ -226,10 +226,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
wake_up_process(child);
break;
- case PTRACE_DETACH: /* detach a process that was attached. */
- ret = ptrace_detach(child, data);
- break;
-
case PTRACE_GETREGS: /* Get all gp regs from the child. */
for (i = 0; i < 19; i++) {
tmp = get_reg(child, i);
diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
index 36d78cf1a7bc..e892f17ba3fa 100644
--- a/arch/m68k/kernel/sys_m68k.c
+++ b/arch/m68k/kernel/sys_m68k.c
@@ -21,12 +21,12 @@
#include <linux/mman.h>
#include <linux/file.h>
#include <linux/utsname.h>
+#include <linux/ipc.h>
#include <asm/setup.h>
#include <asm/uaccess.h>
#include <asm/cachectl.h>
#include <asm/traps.h>
-#include <asm/ipc.h>
#include <asm/page.h>
#include <asm/unistd.h>
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index 4e2752a0e89b..97f556fa4932 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -900,7 +900,7 @@ void show_registers(struct pt_regs *regs)
regs->d4, regs->d5, regs->a0, regs->a1);
printk("Process %s (pid: %d, task=%p)\n",
- current->comm, current->pid, current);
+ current->comm, task_pid_nr(current), current);
addr = (unsigned long)&fp->un;
printk("Frame format=%X ", regs->format);
switch (regs->format) {
@@ -1038,7 +1038,7 @@ void bad_super_trap (struct frame *fp)
fp->un.fmtb.daddr, space_names[ssw & DFC],
fp->ptregs.pc);
}
- printk ("Current process id is %d\n", current->pid);
+ printk ("Current process id is %d\n", task_pid_nr(current));
die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
}
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index 8547dbc5e8d7..01b468b9392e 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -284,7 +284,7 @@ static struct mac_model mac_data_table[] = {
},
/*
- * Weirdified MacII hardware - all subtley different. Gee thanks
+ * Weirdified MacII hardware - all subtly different. Gee thanks
* Apple. All these boxes seem to have VIA2 in a different place to
* the MacII (+1A000 rather than +4000)
* CSA: see http://developer.apple.com/technotes/hw/hw_09.html
@@ -707,7 +707,7 @@ static struct mac_model mac_data_table[] = {
* All of these probably have onboard SONIC in the Dock which
* means we'll have to probe for it eventually.
*
- * Are these reallly MAC_VIA_IIci? The developer notes for the
+ * Are these really MAC_VIA_IIci? The developer notes for the
* Duos show pretty much the same custom parts as in most of
* the other PowerBooks which would imply MAC_VIA_QUADRA.
*/
diff --git a/arch/m68k/mac/iop.c b/arch/m68k/mac/iop.c
index 0cea21f58192..5b2799eb96a6 100644
--- a/arch/m68k/mac/iop.c
+++ b/arch/m68k/mac/iop.c
@@ -100,7 +100,7 @@
* finished; this function moves the message state to MSG_COMPLETE and signals
* the IOP. This two-step process is provided to allow the handler to defer
* message processing to a bottom-half handler if the processing will take
- * a signifigant amount of time (handlers are called at interrupt time so they
+ * a significant amount of time (handlers are called at interrupt time so they
* should execute quickly.)
*/
@@ -120,7 +120,7 @@
/*#define DEBUG_IOP*/
-/* Set to nonezero if the IOPs are present. Set by iop_init() */
+/* Set to non-zero if the IOPs are present. Set by iop_init() */
int iop_scc_present,iop_ism_present;
diff --git a/arch/m68k/mac/oss.c b/arch/m68k/mac/oss.c
index d7be16917efd..50603d3dce84 100644
--- a/arch/m68k/mac/oss.c
+++ b/arch/m68k/mac/oss.c
@@ -8,7 +8,7 @@
*
* 990502 (jmt) - Major rewrite for new interrupt architecture as well as some
* recent insights into OSS operational details.
- * 990610 (jmt) - Now taking fulll advantage of the OSS. Interrupts are mapped
+ * 990610 (jmt) - Now taking full advantage of the OSS. Interrupts are mapped
* to mostly match the A/UX interrupt scheme supported on the
* VIA side. Also added support for enabling the ISM irq again
* since we now have a functional IOP manager.
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
index d5cac72eb3db..8df270e950fa 100644
--- a/arch/m68k/mac/via.c
+++ b/arch/m68k/mac/via.c
@@ -1,7 +1,7 @@
/*
* 6522 Versatile Interface Adapter (VIA)
*
- * There are two of these on the Mac II. Some IRQ's are vectored
+ * There are two of these on the Mac II. Some IRQs are vectored
* via them as are assorted bits and bobs - eg RTC, ADB.
*
* CSA: Motorola seems to have removed documentation on the 6522 from
diff --git a/arch/m68k/math-emu/fp_log.c b/arch/m68k/math-emu/fp_log.c
index 87b4f0158560..b1033ae0d6f0 100644
--- a/arch/m68k/math-emu/fp_log.c
+++ b/arch/m68k/math-emu/fp_log.c
@@ -65,7 +65,7 @@ fp_fsqrt(struct fp_ext *dest, struct fp_ext *src)
fp_copy_ext(&src2, dest);
/*
- * The taylor row arround a for sqrt(x) is:
+ * The taylor row around a for sqrt(x) is:
* sqrt(x) = sqrt(a) + 1/(2*sqrt(a))*(x-a) + R
* With a=1 this gives:
* sqrt(x) = 1 + 1/2*(x-1)
diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c
index 578b48f47b9e..f493f03231d5 100644
--- a/arch/m68k/mm/fault.c
+++ b/arch/m68k/mm/fault.c
@@ -180,7 +180,7 @@ good_area:
*/
out_of_memory:
up_read(&mm->mmap_sem);
- if (is_init(current)) {
+ if (is_global_init(current)) {
yield();
down_read(&mm->mmap_sem);
goto survive;
@@ -188,7 +188,7 @@ out_of_memory:
printk("VM: killing process %s\n", current->comm);
if (user_mode(regs))
- do_exit(SIGKILL);
+ do_group_exit(SIGKILL);
no_context:
current->thread.signo = SIGBUS;
diff --git a/arch/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c
index ad3ed1fb8879..46161cef08b9 100644
--- a/arch/m68k/q40/q40ints.c
+++ b/arch/m68k/q40/q40ints.c
@@ -184,7 +184,7 @@ static struct IRQ_TABLE eirqs[] = {
};
/* complain only this many times about spurious ints : */
-static int ccleirq=60; /* ISA dev IRQ's*/
+static int ccleirq=60; /* ISA dev IRQs*/
/*static int cclirq=60;*/ /* internal */
/* FIXME: add shared ints,mask,unmask,probing.... */
@@ -234,7 +234,7 @@ static void q40_irq_handler(unsigned int irq, struct pt_regs *fp)
* There is a little mess wrt which IRQ really caused this irq request. The
* main problem is that IIRQ_REG and EIRQ_REG reflect the state when they
* are read - which is long after the request came in. In theory IRQs should
- * not just go away but they occassionally do
+ * not just go away but they occasionally do
*/
if (irq > 4 && irq <= 15 && mext_disabled) {
/*aliased_irq++;*/
diff --git a/arch/m68k/sun3/mmu_emu.c b/arch/m68k/sun3/mmu_emu.c
index 7a0e3a220687..fb0f6a20cc3c 100644
--- a/arch/m68k/sun3/mmu_emu.c
+++ b/arch/m68k/sun3/mmu_emu.c
@@ -239,7 +239,7 @@ void clear_context(unsigned long context)
/* gets an empty context. if full, kills the next context listed to
die first */
/* This context invalidation scheme is, well, totally arbitrary, I'm
- sure it could be much more intellegent... but it gets the job done
+ sure it could be much more intelligent... but it gets the job done
for now without much overhead in making it's decision. */
/* todo: come up with optimized scheme for flushing contexts */
unsigned long get_free_context(struct mm_struct *mm)
diff --git a/arch/m68k/tools/amiga/dmesg.c b/arch/m68k/tools/amiga/dmesg.c
index e892748e7386..7340f5b6cf6d 100644
--- a/arch/m68k/tools/amiga/dmesg.c
+++ b/arch/m68k/tools/amiga/dmesg.c
@@ -3,7 +3,7 @@
* in Chip RAM with the kernel command
* line option `debug=mem'.
*
- * © Copyright 1996 by Geert Uytterhoeven <geert@linux-m68k.org>
+ * © Copyright 1996 by Geert Uytterhoeven <geert@linux-m68k.org>
*
*
* Usage:
diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig
index 185906b54cb0..f4b582cbb567 100644
--- a/arch/m68knommu/Kconfig
+++ b/arch/m68knommu/Kconfig
@@ -451,6 +451,12 @@ config MOD5272
help
Support for the Netburner MOD-5272 board.
+config SAVANTrosie1
+ bool "Savant Rosie1 board support"
+ depends on M523x
+ help
+ Support for the Savant Rosie1 board.
+
config ROMFS_FROM_ROM
bool "ROMFS image not RAM resident"
depends on (NETtel || SNAPGEAR)
@@ -492,7 +498,12 @@ config SNEHA
bool
default y
depends on CPU16B
-
+
+config SAVANT
+ bool
+ default y
+ depends on SAVANTrosie1
+
config AVNET
bool
default y
@@ -696,6 +707,8 @@ source "drivers/Kconfig"
source "fs/Kconfig"
+source "kernel/Kconfig.instrumentation"
+
source "arch/m68knommu/Kconfig.debug"
source "security/Kconfig"
diff --git a/arch/m68knommu/Makefile b/arch/m68knommu/Makefile
index 1305cc980023..30aa2553693d 100644
--- a/arch/m68knommu/Makefile
+++ b/arch/m68knommu/Makefile
@@ -48,6 +48,7 @@ board-$(CONFIG_SNEHA) := SNEHA
board-$(CONFIG_M5208EVB) := M5208EVB
board-$(CONFIG_MOD5272) := MOD5272
board-$(CONFIG_AVNET) := AVNET
+board-$(CONFIG_SAVANT) := SAVANT
BOARD := $(board-y)
model-$(CONFIG_RAMKERNEL) := ram
@@ -102,11 +103,11 @@ cflags-$(CONFIG_M68EZ328) := -m68000
cflags-$(CONFIG_M68VZ328) := -m68000
cflags-$(CONFIG_M68360) := -m68332
-AFLAGS += $(cflags-y)
+KBUILD_AFLAGS += $(cflags-y)
-CFLAGS += $(cflags-y)
-CFLAGS += -D__linux__
-CFLAGS += -DUTS_SYSNAME=\"uClinux\"
+KBUILD_CFLAGS += $(cflags-y)
+KBUILD_CFLAGS += -D__linux__
+KBUILD_CFLAGS += -DUTS_SYSNAME=\"uClinux\"
head-y := arch/m68knommu/platform/$(cpuclass-y)/head.o
@@ -117,4 +118,4 @@ core-y += arch/m68knommu/kernel/ \
libs-y += arch/m68knommu/lib/
archclean:
- $(Q)$(MAKE) $(clean)=arch/m68knommu/boot
+
diff --git a/arch/m68knommu/defconfig b/arch/m68knommu/defconfig
index 3891de09ac23..5a0ecaaee3b0 100644
--- a/arch/m68knommu/defconfig
+++ b/arch/m68knommu/defconfig
@@ -1,41 +1,48 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.17
-# Tue Jun 27 12:57:06 2006
+# Linux kernel version: 2.6.23
+# Thu Oct 18 13:17:38 2007
#
CONFIG_M68K=y
# CONFIG_MMU is not set
# CONFIG_FPU is not set
+CONFIG_ZONE_DMA=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_TIME_LOW_RES=y
+CONFIG_NO_IOPORT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
-# Code maturity level options
+# General setup
#
CONFIG_EXPERIMENTAL=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
# CONFIG_SYSVIPC is not set
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_SYSCTL is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_USER_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SYSFS_DEPRECATED is not set
# CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
-CONFIG_UID16=y
+# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
# CONFIG_KALLSYMS is not set
# CONFIG_HOTPLUG is not set
CONFIG_PRINTK=y
@@ -44,20 +51,25 @@ CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
# CONFIG_FUTEX is not set
# CONFIG_EPOLL is not set
+# CONFIG_SIGNALFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_TINY_SHMEM=y
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
-
-#
-# Loadable module support
-#
-# CONFIG_MODULES is not set
-
-#
-# Block layer
-#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
#
# IO Schedulers
@@ -99,6 +111,7 @@ CONFIG_CLOCK_DIV=1
#
# Platform
#
+# CONFIG_UC5272 is not set
CONFIG_M5272C3=y
# CONFIG_COBRA5272 is not set
# CONFIG_CANCam is not set
@@ -107,7 +120,6 @@ CONFIG_M5272C3=y
# CONFIG_CPU16B is not set
# CONFIG_MOD5272 is not set
CONFIG_FREESCALE=y
-# CONFIG_LARGE_ALLOCS is not set
CONFIG_4KSTACKS=y
#
@@ -121,6 +133,11 @@ CONFIG_RAMAUTOBIT=y
# CONFIG_RAM8BIT is not set
# CONFIG_RAM16BIT is not set
# CONFIG_RAM32BIT is not set
+
+#
+# ROM configuration
+#
+# CONFIG_ROM is not set
CONFIG_RAMKERNEL=y
# CONFIG_ROMKERNEL is not set
CONFIG_SELECT_MEMORY_MODEL=y
@@ -131,20 +148,19 @@ CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_VIRT_TO_BUS=y
#
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
#
# CONFIG_PCI is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
#
# PCCARD (PCMCIA/CardBus) support
#
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
#
# Executable file formats
@@ -168,7 +184,6 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -187,27 +202,21 @@ CONFIG_IP_FIB_HASH=y
# CONFIG_INET_IPCOMP is not set
# CONFIG_INET_XFRM_TUNNEL is not set
# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
# CONFIG_INET_DIAG is not set
# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -218,7 +227,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -234,7 +242,17 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
#
# Device Drivers
@@ -245,16 +263,8 @@ CONFIG_TCP_CONG_BIC=y
#
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
+# CONFIG_SYS_HYPERVISOR is not set
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
@@ -266,11 +276,13 @@ CONFIG_MTD_PARTITIONS=y
# User Modules And Translation Layers
#
CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
CONFIG_MTD_BLOCK=y
# CONFIG_FTL is not set
# CONFIG_NFTL is not set
# CONFIG_INFTL is not set
# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
#
# RAM/ROM/Flash chip drivers
@@ -290,7 +302,6 @@ CONFIG_MTD_CFI_I2=y
CONFIG_MTD_RAM=y
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
#
# Mapping drivers for chip access
@@ -313,42 +324,25 @@ CONFIG_MTD_UCLINUX=y
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
# CONFIG_MTD_NAND is not set
-
-#
-# OneNAND Flash Device Drivers
-#
# CONFIG_MTD_ONENAND is not set
#
-# Parallel port support
+# UBI - Unsorted block images
#
+# CONFIG_MTD_UBI is not set
# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-
-#
-# Block devices
-#
+CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
-# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_MISC_DEVICES is not set
# CONFIG_IDE is not set
#
@@ -356,67 +350,29 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
#
# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
-# Network device support
-#
CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# PHY device support
-#
# CONFIG_PHYLIB is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
CONFIG_NET_ETHERNET=y
# CONFIG_MII is not set
CONFIG_FEC=y
# CONFIG_FEC2 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
# CONFIG_WAN is not set
CONFIG_PPP=y
# CONFIG_PPP_MULTILINK is not set
@@ -427,20 +383,14 @@ CONFIG_PPP=y
# CONFIG_PPP_BSDCOMP is not set
# CONFIG_PPP_MPPE is not set
# CONFIG_PPPOE is not set
+# CONFIG_PPPOL2TP is not set
# CONFIG_SLIP is not set
+CONFIG_SLHC=y
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
# CONFIG_PHONE is not set
#
@@ -472,34 +422,13 @@ CONFIG_SERIAL_COLDFIRE=y
# CONFIG_UNIX98_PTYS is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
-
-#
-# I2C support
-#
# CONFIG_I2C is not set
#
@@ -507,101 +436,74 @@ CONFIG_LEGACY_PTY_COUNT=256
#
# CONFIG_SPI is not set
# CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
+# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
#
-# Misc devices
+# Multifunction device drivers
#
+# CONFIG_MFD_SM501 is not set
#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=y
# CONFIG_FB is not set
#
# Sound
#
# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB_ARCH_HAS_HCD is not set
-# CONFIG_USB_ARCH_HAS_OHCI is not set
-# CONFIG_USB_ARCH_HAS_EHCI is not set
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
+# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
-
-#
-# LED devices
-#
# CONFIG_NEW_LEDS is not set
+# CONFIG_RTC_CLASS is not set
#
-# LED drivers
+# DMA Engine support
#
+# CONFIG_DMA_ENGINE is not set
#
-# LED Triggers
+# DMA Clients
#
#
-# InfiniBand support
+# DMA Devices
#
#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+# Userspace I/O
#
-
-#
-# Real Time Clock
-#
-# CONFIG_RTC_CLASS is not set
+# CONFIG_UIO is not set
#
# File systems
#
CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
CONFIG_ROMFS_FS=y
@@ -629,6 +531,7 @@ CONFIG_ROMFS_FS=y
# Pseudo filesystems
#
CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
@@ -645,7 +548,6 @@ CONFIG_RAMFS=y
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
@@ -664,7 +566,6 @@ CONFIG_RAMFS=y
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
#
# Partition Types
@@ -678,15 +579,21 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_NLS is not set
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_DEBUG_FS is not set
-# CONFIG_UNWIND_INFO is not set
# CONFIG_FULLDEBUG is not set
# CONFIG_HIGHPROFILE is not set
# CONFIG_BOOTPARAM is not set
@@ -699,20 +606,16 @@ CONFIG_LOG_BUF_SHIFT=14
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
# CONFIG_CRYPTO is not set
#
-# Hardware crypto devices
-#
-
-#
# Library routines
#
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
# CONFIG_CRC32 is not set
+# CONFIG_CRC7 is not set
# CONFIG_LIBCRC32C is not set
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_DMA=y
diff --git a/arch/m68knommu/kernel/setup.c b/arch/m68knommu/kernel/setup.c
index 3f86ade3a22a..332345d7675d 100644
--- a/arch/m68knommu/kernel/setup.c
+++ b/arch/m68knommu/kernel/setup.c
@@ -43,11 +43,8 @@ EXPORT_SYMBOL(memory_end);
char __initdata command_line[COMMAND_LINE_SIZE];
/* machine dependent timer functions */
-void (*mach_sched_init)(irq_handler_t handler);
-void (*mach_tick)(void);
void (*mach_gettod)(int*, int*, int*, int*, int*, int*);
int (*mach_set_clock_mmss)(unsigned long);
-unsigned long (*mach_gettimeoffset)(void);
/* machine dependent reboot functions */
void (*mach_reset)(void);
@@ -116,7 +113,7 @@ void (*mach_power_off)(void);
extern int _stext, _etext, _sdata, _edata, _sbss, _ebss, _end;
extern int _ramstart, _ramend;
-void setup_arch(char **cmdline_p)
+void __init setup_arch(char **cmdline_p)
{
int bootmap_size;
@@ -151,27 +148,15 @@ void setup_arch(char **cmdline_p)
#ifdef CONFIG_ELITE
printk(KERN_INFO "Modified for M5206eLITE by Rob Scott, rscott@mtrob.fdns.net\n");
#endif
-#ifdef CONFIG_TELOS
- printk(KERN_INFO "Modified for Omnia ToolVox by James D. Schettine, james@telos-systems.com\n");
-#endif
#endif
printk(KERN_INFO "Flat model support (C) 1998,1999 Kenneth Albanowski, D. Jeff Dionne\n");
#if defined( CONFIG_PILOT ) && defined( CONFIG_M68328 )
printk(KERN_INFO "TRG SuperPilot FLASH card support <info@trgnet.com>\n");
#endif
-
#if defined( CONFIG_PILOT ) && defined( CONFIG_M68EZ328 )
printk(KERN_INFO "PalmV support by Lineo Inc. <jeff@uclinux.com>\n");
#endif
-
-#ifdef CONFIG_M68EZ328ADS
- printk(KERN_INFO "M68EZ328ADS board support (C) 1999 Vladimir Gurevich <vgurevic@cisco.com>\n");
-#endif
-
-#ifdef CONFIG_ALMA_ANS
- printk(KERN_INFO "Alma Electronics board support (C) 1999 Vladimir Gurevich <vgurevic@cisco.com>\n");
-#endif
#if defined (CONFIG_M68360)
printk(KERN_INFO "QUICC port done by SED Systems <hamilton@sedsystems.ca>,\n");
printk(KERN_INFO "based on 2.0.38 port by Lineo Inc. <mleslie@lineo.com>.\n");
@@ -188,11 +173,9 @@ void setup_arch(char **cmdline_p)
"BSS=0x%06x-0x%06x\n", (int) &_stext, (int) &_etext,
(int) &_sdata, (int) &_edata,
(int) &_sbss, (int) &_ebss);
- printk(KERN_DEBUG "KERNEL -> ROMFS=0x%06x-0x%06x MEM=0x%06x-0x%06x "
- "STACK=0x%06x-0x%06x\n",
+ printk(KERN_DEBUG "MEMORY -> ROMFS=0x%06x-0x%06x MEM=0x%06x-0x%06x\n ",
(int) &_ebss, (int) memory_start,
- (int) memory_start, (int) memory_end,
- (int) memory_end, (int) _ramend);
+ (int) memory_start, (int) memory_end);
#endif
/* Keep a copy of command line */
@@ -287,12 +270,3 @@ struct seq_operations cpuinfo_op = {
.show = show_cpuinfo,
};
-void arch_gettod(int *year, int *mon, int *day, int *hour,
- int *min, int *sec)
-{
- if (mach_gettod)
- mach_gettod(year, mon, day, hour, min, sec);
- else
- *year = *mon = *day = *hour = *min = *sec = 0;
-}
-
diff --git a/arch/m68knommu/kernel/signal.c b/arch/m68knommu/kernel/signal.c
index 437f8c6c14a0..70371378db86 100644
--- a/arch/m68knommu/kernel/signal.c
+++ b/arch/m68knommu/kernel/signal.c
@@ -781,15 +781,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
/* Did we come from a system call? */
if (regs->orig_d0 >= 0) {
/* Restart the system call - no handlers present */
- if (regs->d0 == -ERESTARTNOHAND
- || regs->d0 == -ERESTARTSYS
- || regs->d0 == -ERESTARTNOINTR) {
- regs->d0 = regs->orig_d0;
- regs->pc -= 2;
- } else if (regs->d0 == -ERESTART_RESTARTBLOCK) {
- regs->d0 = __NR_restart_syscall;
- regs->pc -= 2;
- }
+ handle_restart(regs, NULL, 0);
}
return 0;
}
diff --git a/arch/m68knommu/kernel/sys_m68k.c b/arch/m68knommu/kernel/sys_m68k.c
index 15d62c5279a9..65f7a95f056e 100644
--- a/arch/m68knommu/kernel/sys_m68k.c
+++ b/arch/m68knommu/kernel/sys_m68k.c
@@ -18,13 +18,13 @@
#include <linux/mman.h>
#include <linux/file.h>
#include <linux/utsname.h>
+#include <linux/ipc.h>
#include <linux/fs.h>
#include <asm/setup.h>
#include <asm/uaccess.h>
#include <asm/cachectl.h>
#include <asm/traps.h>
-#include <asm/ipc.h>
#include <asm/cacheflush.h>
#include <asm/unistd.h>
diff --git a/arch/m68knommu/kernel/time.c b/arch/m68knommu/kernel/time.c
index 467053da2d08..77e5375a2dd5 100644
--- a/arch/m68knommu/kernel/time.c
+++ b/arch/m68knommu/kernel/time.c
@@ -27,7 +27,6 @@
#define TICK_SIZE (tick_nsec / 1000)
-
static inline int set_rtc_mmss(unsigned long nowtime)
{
if (mach_set_clock_mmss)
@@ -39,15 +38,11 @@ static inline int set_rtc_mmss(unsigned long nowtime)
* timer_interrupt() needs to keep up the real-time clock,
* as well as call the "do_timer()" routine every clocktick
*/
-static irqreturn_t timer_interrupt(int irq, void *dummy)
+irqreturn_t arch_timer_interrupt(int irq, void *dummy)
{
/* last time the cmos clock got updated */
static long last_rtc_update=0;
- /* may need to kick the hardware timer */
- if (mach_tick)
- mach_tick();
-
write_seqlock(&xtime_lock);
do_timer(1);
@@ -103,10 +98,10 @@ void time_init(void)
{
unsigned int year, mon, day, hour, min, sec;
- extern void arch_gettod(int *year, int *mon, int *day, int *hour,
- int *min, int *sec);
-
- arch_gettod(&year, &mon, &day, &hour, &min, &sec);
+ if (mach_gettod)
+ mach_gettod(&year, &mon, &day, &hour, &min, &sec);
+ else
+ year = mon = day = hour = min = sec = 0;
if ((year += 1900) < 1970)
year += 100;
@@ -114,7 +109,7 @@ void time_init(void)
xtime.tv_nsec = 0;
wall_to_monotonic.tv_sec = -xtime.tv_sec;
- mach_sched_init(timer_interrupt);
+ hw_timer_init();
}
/*
@@ -128,7 +123,7 @@ void do_gettimeofday(struct timeval *tv)
do {
seq = read_seqbegin_irqsave(&xtime_lock, flags);
- usec = mach_gettimeoffset ? mach_gettimeoffset() : 0;
+ usec = hw_timer_offset();
sec = xtime.tv_sec;
usec += (xtime.tv_nsec / 1000);
} while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
@@ -160,8 +155,7 @@ int do_settimeofday(struct timespec *tv)
* Discover what correction gettimeofday
* would have done, and then undo it!
*/
- if (mach_gettimeoffset)
- nsec -= (mach_gettimeoffset() * 1000);
+ nsec -= (hw_timer_offset() * 1000);
wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
diff --git a/arch/m68knommu/mm/init.c b/arch/m68knommu/mm/init.c
index 06e538d1be3a..22e2a0d02b81 100644
--- a/arch/m68knommu/mm/init.c
+++ b/arch/m68knommu/mm/init.c
@@ -98,7 +98,7 @@ extern unsigned long memory_end;
* The parameters are pointers to where to stick the starting and ending
* addresses of available kernel virtual memory.
*/
-void paging_init(void)
+void __init paging_init(void)
{
/*
* Make sure start_mem is page aligned, otherwise bootmem and
@@ -147,7 +147,7 @@ void paging_init(void)
}
}
-void mem_init(void)
+void __init mem_init(void)
{
int codek = 0, datak = 0, initk = 0;
unsigned long tmp;
diff --git a/arch/m68knommu/platform/5206/Makefile b/arch/m68knommu/platform/5206/Makefile
index 701b7abe019d..c7bb0cef31a0 100644
--- a/arch/m68knommu/platform/5206/Makefile
+++ b/arch/m68knommu/platform/5206/Makefile
@@ -13,7 +13,7 @@
#
ifdef CONFIG_FULLDEBUG
-AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
+EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
endif
obj-y := config.o
diff --git a/arch/m68knommu/platform/5206/config.c b/arch/m68knommu/platform/5206/config.c
index d0f2dc5cb5a1..b3c4dd4cc135 100644
--- a/arch/m68knommu/platform/5206/config.c
+++ b/arch/m68knommu/platform/5206/config.c
@@ -10,13 +10,10 @@
/***************************************************************************/
#include <linux/kernel.h>
-#include <linux/sched.h>
#include <linux/param.h>
#include <linux/init.h>
#include <linux/interrupt.h>
-#include <asm/irq.h>
#include <asm/dma.h>
-#include <asm/traps.h>
#include <asm/machdep.h>
#include <asm/coldfire.h>
#include <asm/mcftimer.h>
@@ -25,9 +22,6 @@
/***************************************************************************/
-void coldfire_tick(void);
-void coldfire_timer_init(irq_handler_t handler);
-unsigned long coldfire_timer_offset(void);
void coldfire_reset(void);
/***************************************************************************/
@@ -97,9 +91,6 @@ int mcf_timerirqpending(int timer)
void config_BSP(char *commandp, int size)
{
mcf_setimr(MCFSIM_IMR_MASKALL);
- mach_sched_init = coldfire_timer_init;
- mach_tick = coldfire_tick;
- mach_gettimeoffset = coldfire_timer_offset;
mach_reset = coldfire_reset;
}
diff --git a/arch/m68knommu/platform/5206e/Makefile b/arch/m68knommu/platform/5206e/Makefile
index 701b7abe019d..c7bb0cef31a0 100644
--- a/arch/m68knommu/platform/5206e/Makefile
+++ b/arch/m68knommu/platform/5206e/Makefile
@@ -13,7 +13,7 @@
#
ifdef CONFIG_FULLDEBUG
-AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
+EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
endif
obj-y := config.o
diff --git a/arch/m68knommu/platform/5206e/config.c b/arch/m68knommu/platform/5206e/config.c
index 425703fb6cee..f84a4aea8cb6 100644
--- a/arch/m68knommu/platform/5206e/config.c
+++ b/arch/m68knommu/platform/5206e/config.c
@@ -9,23 +9,16 @@
/***************************************************************************/
#include <linux/kernel.h>
-#include <linux/sched.h>
#include <linux/param.h>
#include <linux/interrupt.h>
-#include <asm/irq.h>
#include <asm/dma.h>
-#include <asm/traps.h>
#include <asm/machdep.h>
#include <asm/coldfire.h>
-#include <asm/mcftimer.h>
#include <asm/mcfsim.h>
#include <asm/mcfdma.h>
/***************************************************************************/
-void coldfire_tick(void);
-void coldfire_timer_init(irq_handler_t handler);
-unsigned long coldfire_timer_offset(void);
void coldfire_reset(void);
/***************************************************************************/
@@ -102,9 +95,6 @@ void config_BSP(char *commandp, int size)
commandp[size-1] = 0;
#endif /* CONFIG_NETtel */
- mach_sched_init = coldfire_timer_init;
- mach_tick = coldfire_tick;
- mach_gettimeoffset = coldfire_timer_offset;
mach_reset = coldfire_reset;
}
diff --git a/arch/m68knommu/platform/520x/Makefile b/arch/m68knommu/platform/520x/Makefile
index e861b05106bc..31b4eb51739d 100644
--- a/arch/m68knommu/platform/520x/Makefile
+++ b/arch/m68knommu/platform/520x/Makefile
@@ -13,7 +13,7 @@
#
ifdef CONFIG_FULLDEBUG
-AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
+EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
endif
obj-y := config.o
diff --git a/arch/m68knommu/platform/520x/config.c b/arch/m68knommu/platform/520x/config.c
index a2c95bebd004..6edbd41261cc 100644
--- a/arch/m68knommu/platform/520x/config.c
+++ b/arch/m68knommu/platform/520x/config.c
@@ -27,9 +27,6 @@ unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS];
/***************************************************************************/
-void coldfire_pit_tick(void);
-void coldfire_pit_init(irq_handler_t handler);
-unsigned long coldfire_pit_offset(void);
void coldfire_reset(void);
/***************************************************************************/
@@ -47,10 +44,7 @@ void mcf_autovector(unsigned int vec)
void config_BSP(char *commandp, int size)
{
- mach_sched_init = coldfire_pit_init;
- mach_tick = coldfire_pit_tick;
- mach_gettimeoffset = coldfire_pit_offset;
- mach_reset = coldfire_reset;
+ mach_reset = coldfire_reset;
}
/***************************************************************************/
diff --git a/arch/m68knommu/platform/523x/Makefile b/arch/m68knommu/platform/523x/Makefile
index c1578b016160..ac9fbece8a4f 100644
--- a/arch/m68knommu/platform/523x/Makefile
+++ b/arch/m68knommu/platform/523x/Makefile
@@ -13,7 +13,7 @@
#
ifdef CONFIG_FULLDEBUG
-AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
+EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
endif
obj-y := config.o
diff --git a/arch/m68knommu/platform/523x/config.c b/arch/m68knommu/platform/523x/config.c
index 0a3af05a434b..e7f80c8e8636 100644
--- a/arch/m68knommu/platform/523x/config.c
+++ b/arch/m68knommu/platform/523x/config.c
@@ -13,12 +13,10 @@
/***************************************************************************/
#include <linux/kernel.h>
-#include <linux/sched.h>
#include <linux/param.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <asm/dma.h>
-#include <asm/traps.h>
#include <asm/machdep.h>
#include <asm/coldfire.h>
#include <asm/mcfsim.h>
@@ -26,9 +24,6 @@
/***************************************************************************/
-void coldfire_pit_tick(void);
-void coldfire_pit_init(irq_handler_t handler);
-unsigned long coldfire_pit_offset(void);
void coldfire_reset(void);
/***************************************************************************/
@@ -62,9 +57,6 @@ void mcf_autovector(unsigned int vec)
void config_BSP(char *commandp, int size)
{
mcf_disableall();
- mach_sched_init = coldfire_pit_init;
- mach_tick = coldfire_pit_tick;
- mach_gettimeoffset = coldfire_pit_offset;
mach_reset = coldfire_reset;
}
diff --git a/arch/m68knommu/platform/5249/Makefile b/arch/m68knommu/platform/5249/Makefile
index 701b7abe019d..c7bb0cef31a0 100644
--- a/arch/m68knommu/platform/5249/Makefile
+++ b/arch/m68knommu/platform/5249/Makefile
@@ -13,7 +13,7 @@
#
ifdef CONFIG_FULLDEBUG
-AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
+EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
endif
obj-y := config.o
diff --git a/arch/m68knommu/platform/5249/config.c b/arch/m68knommu/platform/5249/config.c
index dc2c362590c2..d4d39435cb15 100644
--- a/arch/m68knommu/platform/5249/config.c
+++ b/arch/m68knommu/platform/5249/config.c
@@ -9,24 +9,17 @@
/***************************************************************************/
#include <linux/kernel.h>
-#include <linux/sched.h>
#include <linux/param.h>
#include <linux/init.h>
#include <linux/interrupt.h>
-#include <asm/irq.h>
#include <asm/dma.h>
-#include <asm/traps.h>
#include <asm/machdep.h>
#include <asm/coldfire.h>
-#include <asm/mcftimer.h>
#include <asm/mcfsim.h>
#include <asm/mcfdma.h>
/***************************************************************************/
-void coldfire_tick(void);
-void coldfire_timer_init(irq_handler_t handler);
-unsigned long coldfire_timer_offset(void);
void coldfire_reset(void);
/***************************************************************************/
@@ -95,9 +88,6 @@ int mcf_timerirqpending(int timer)
void config_BSP(char *commandp, int size)
{
mcf_setimr(MCFSIM_IMR_MASKALL);
- mach_sched_init = coldfire_timer_init;
- mach_tick = coldfire_tick;
- mach_gettimeoffset = coldfire_timer_offset;
mach_reset = coldfire_reset;
}
diff --git a/arch/m68knommu/platform/5272/Makefile b/arch/m68knommu/platform/5272/Makefile
index 0871a29dd589..7475c38c3b4e 100644
--- a/arch/m68knommu/platform/5272/Makefile
+++ b/arch/m68knommu/platform/5272/Makefile
@@ -13,7 +13,7 @@
#
ifdef CONFIG_FULLDEBUG
-AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
+EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
endif
obj-y := config.o
diff --git a/arch/m68knommu/platform/5272/config.c b/arch/m68knommu/platform/5272/config.c
index 1365a8300d5d..634a6375e4a5 100644
--- a/arch/m68knommu/platform/5272/config.c
+++ b/arch/m68knommu/platform/5272/config.c
@@ -10,24 +10,17 @@
/***************************************************************************/
#include <linux/kernel.h>
-#include <linux/sched.h>
#include <linux/param.h>
#include <linux/init.h>
#include <linux/interrupt.h>
-#include <asm/irq.h>
#include <asm/dma.h>
-#include <asm/traps.h>
#include <asm/machdep.h>
#include <asm/coldfire.h>
-#include <asm/mcftimer.h>
#include <asm/mcfsim.h>
#include <asm/mcfdma.h>
/***************************************************************************/
-void coldfire_tick(void);
-void coldfire_timer_init(irq_handler_t handler);
-unsigned long coldfire_timer_offset(void);
void coldfire_reset(void);
extern unsigned int mcf_timervector;
@@ -128,9 +121,6 @@ void config_BSP(char *commandp, int size)
mcf_timervector = 69;
mcf_profilevector = 70;
- mach_sched_init = coldfire_timer_init;
- mach_tick = coldfire_tick;
- mach_gettimeoffset = coldfire_timer_offset;
mach_reset = coldfire_reset;
}
diff --git a/arch/m68knommu/platform/527x/Makefile b/arch/m68knommu/platform/527x/Makefile
index 0871a29dd589..7475c38c3b4e 100644
--- a/arch/m68knommu/platform/527x/Makefile
+++ b/arch/m68knommu/platform/527x/Makefile
@@ -13,7 +13,7 @@
#
ifdef CONFIG_FULLDEBUG
-AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
+EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
endif
obj-y := config.o
diff --git a/arch/m68knommu/platform/527x/config.c b/arch/m68knommu/platform/527x/config.c
index 1b820441419a..9cbfbc68ae4f 100644
--- a/arch/m68knommu/platform/527x/config.c
+++ b/arch/m68knommu/platform/527x/config.c
@@ -13,12 +13,10 @@
/***************************************************************************/
#include <linux/kernel.h>
-#include <linux/sched.h>
#include <linux/param.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <asm/dma.h>
-#include <asm/traps.h>
#include <asm/machdep.h>
#include <asm/coldfire.h>
#include <asm/mcfsim.h>
@@ -26,9 +24,6 @@
/***************************************************************************/
-void coldfire_pit_tick(void);
-void coldfire_pit_init(irq_handler_t handler);
-unsigned long coldfire_pit_offset(void);
void coldfire_reset(void);
/***************************************************************************/
@@ -62,9 +57,6 @@ void mcf_autovector(unsigned int vec)
void config_BSP(char *commandp, int size)
{
mcf_disableall();
- mach_sched_init = coldfire_pit_init;
- mach_tick = coldfire_pit_tick;
- mach_gettimeoffset = coldfire_pit_offset;
mach_reset = coldfire_reset;
}
diff --git a/arch/m68knommu/platform/528x/Makefile b/arch/m68knommu/platform/528x/Makefile
index 0871a29dd589..7475c38c3b4e 100644
--- a/arch/m68knommu/platform/528x/Makefile
+++ b/arch/m68knommu/platform/528x/Makefile
@@ -13,7 +13,7 @@
#
ifdef CONFIG_FULLDEBUG
-AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
+EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
endif
obj-y := config.o
diff --git a/arch/m68knommu/platform/528x/config.c b/arch/m68knommu/platform/528x/config.c
index a089e9513699..acbd43486d97 100644
--- a/arch/m68knommu/platform/528x/config.c
+++ b/arch/m68knommu/platform/528x/config.c
@@ -13,12 +13,10 @@
/***************************************************************************/
#include <linux/kernel.h>
-#include <linux/sched.h>
#include <linux/param.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <asm/dma.h>
-#include <asm/traps.h>
#include <asm/machdep.h>
#include <asm/coldfire.h>
#include <asm/mcfsim.h>
@@ -26,9 +24,6 @@
/***************************************************************************/
-void coldfire_pit_tick(void);
-void coldfire_pit_init(irq_handler_t handler);
-unsigned long coldfire_pit_offset(void);
void coldfire_reset(void);
/***************************************************************************/
@@ -62,9 +57,6 @@ void mcf_autovector(unsigned int vec)
void config_BSP(char *commandp, int size)
{
mcf_disableall();
- mach_sched_init = coldfire_pit_init;
- mach_tick = coldfire_pit_tick;
- mach_gettimeoffset = coldfire_pit_offset;
mach_reset = coldfire_reset;
}
diff --git a/arch/m68knommu/platform/5307/Makefile b/arch/m68knommu/platform/5307/Makefile
index 719a313494bc..5b600530c8d2 100644
--- a/arch/m68knommu/platform/5307/Makefile
+++ b/arch/m68knommu/platform/5307/Makefile
@@ -13,7 +13,7 @@
#
ifdef CONFIG_FULLDEBUG
-AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
+EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
endif
obj-$(CONFIG_COLDFIRE) += entry.o vectors.o
diff --git a/arch/m68knommu/platform/5307/config.c b/arch/m68knommu/platform/5307/config.c
index e3461619fd65..6040821e637d 100644
--- a/arch/m68knommu/platform/5307/config.c
+++ b/arch/m68knommu/platform/5307/config.c
@@ -10,25 +10,18 @@
/***************************************************************************/
#include <linux/kernel.h>
-#include <linux/sched.h>
#include <linux/param.h>
#include <linux/init.h>
#include <linux/interrupt.h>
-#include <asm/irq.h>
#include <asm/dma.h>
-#include <asm/traps.h>
#include <asm/machdep.h>
#include <asm/coldfire.h>
-#include <asm/mcftimer.h>
#include <asm/mcfsim.h>
#include <asm/mcfdma.h>
#include <asm/mcfwdebug.h>
/***************************************************************************/
-void coldfire_tick(void);
-void coldfire_timer_init(irq_handler_t handler);
-unsigned long coldfire_timer_offset(void);
void coldfire_reset(void);
extern unsigned int mcf_timervector;
@@ -122,9 +115,6 @@ void config_BSP(char *commandp, int size)
mcf_timerlevel = 6;
#endif
- mach_sched_init = coldfire_timer_init;
- mach_tick = coldfire_tick;
- mach_gettimeoffset = coldfire_timer_offset;
mach_reset = coldfire_reset;
#ifdef MCF_BDM_DISABLE
diff --git a/arch/m68knommu/platform/5307/entry.S b/arch/m68knommu/platform/5307/entry.S
index a8cd867805ca..b333731b875a 100644
--- a/arch/m68knommu/platform/5307/entry.S
+++ b/arch/m68knommu/platform/5307/entry.S
@@ -74,7 +74,8 @@ ENTRY(system_call)
movel %sp,%d2 /* get thread_info pointer */
andl #-THREAD_SIZE,%d2 /* at start of kernel stack */
movel %d2,%a0
- movel %sp,%a0@(THREAD_ESP0) /* save top of frame */
+ movel %a0@,%a1 /* save top of frame */
+ movel %sp,%a1@(TASK_THREAD+THREAD_ESP0)
btst #(TIF_SYSCALL_TRACE%8),%a0@(TI_FLAGS+(31-TIF_SYSCALL_TRACE)/8)
bnes 1f
@@ -83,6 +84,8 @@ ENTRY(system_call)
movel %d0,%sp@(PT_D0) /* save the return value */
jra ret_from_exception
1:
+ movel #-ENOSYS,%d2 /* strace needs -ENOSYS in PT_D0 */
+ movel %d2,PT_D0(%sp) /* on syscall entry */
subql #4,%sp
SAVE_SWITCH_STACK
jbsr syscall_trace
diff --git a/arch/m68knommu/platform/5307/pit.c b/arch/m68knommu/platform/5307/pit.c
index e53c446d10e4..173b754d1cda 100644
--- a/arch/m68knommu/platform/5307/pit.c
+++ b/arch/m68knommu/platform/5307/pit.c
@@ -17,6 +17,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <asm/machdep.h>
#include <asm/io.h>
#include <asm/coldfire.h>
#include <asm/mcfpit.h>
@@ -31,28 +32,30 @@
/***************************************************************************/
-void coldfire_pit_tick(void)
+static irqreturn_t hw_tick(int irq, void *dummy)
{
unsigned short pcsr;
/* Reset the ColdFire timer */
pcsr = __raw_readw(TA(MCFPIT_PCSR));
__raw_writew(pcsr | MCFPIT_PCSR_PIF, TA(MCFPIT_PCSR));
+
+ return arch_timer_interrupt(irq, dummy);
}
/***************************************************************************/
static struct irqaction coldfire_pit_irq = {
- .name = "timer",
- .flags = IRQF_DISABLED | IRQF_TIMER,
+ .name = "timer",
+ .flags = IRQF_DISABLED | IRQF_TIMER,
+ .handler = hw_tick,
};
-void coldfire_pit_init(irq_handler_t handler)
+void hw_timer_init(void)
{
volatile unsigned char *icrp;
volatile unsigned long *imrp;
- coldfire_pit_irq.handler = handler;
setup_irq(MCFINT_VECBASE + MCFINT_PIT1, &coldfire_pit_irq);
icrp = (volatile unsigned char *) (MCF_IPSBAR + MCFICM_INTC0 +
@@ -71,7 +74,7 @@ void coldfire_pit_init(irq_handler_t handler)
/***************************************************************************/
-unsigned long coldfire_pit_offset(void)
+unsigned long hw_timer_offset(void)
{
volatile unsigned long *ipr;
unsigned long pmr, pcntr, offset;
@@ -83,7 +86,7 @@ unsigned long coldfire_pit_offset(void)
/*
* If we are still in the first half of the upcount and a
- * timer interupt is pending, then add on a ticks worth of time.
+ * timer interrupt is pending, then add on a ticks worth of time.
*/
offset = ((pmr - pcntr) * (1000000 / HZ)) / pmr;
if ((offset < (1000000 / HZ / 2)) && (*ipr & MCFPIT_IMR_IBIT))
diff --git a/arch/m68knommu/platform/5307/timers.c b/arch/m68knommu/platform/5307/timers.c
index 64bd0ff9029e..489dec85c859 100644
--- a/arch/m68knommu/platform/5307/timers.c
+++ b/arch/m68knommu/platform/5307/timers.c
@@ -9,10 +9,9 @@
/***************************************************************************/
#include <linux/kernel.h>
+#include <linux/init.h>
#include <linux/sched.h>
-#include <linux/param.h>
#include <linux/interrupt.h>
-#include <linux/init.h>
#include <linux/irq.h>
#include <asm/io.h>
#include <asm/traps.h>
@@ -54,24 +53,28 @@ extern int mcf_timerirqpending(int timer);
/***************************************************************************/
-void coldfire_tick(void)
+static irqreturn_t hw_tick(int irq, void *dummy)
{
/* Reset the ColdFire timer */
__raw_writeb(MCFTIMER_TER_CAP | MCFTIMER_TER_REF, TA(MCFTIMER_TER));
+
+ return arch_timer_interrupt(irq, dummy);
}
/***************************************************************************/
static struct irqaction coldfire_timer_irq = {
- .name = "timer",
- .flags = IRQF_DISABLED | IRQF_TIMER,
+ .name = "timer",
+ .flags = IRQF_DISABLED | IRQF_TIMER,
+ .handler = hw_tick,
};
+/***************************************************************************/
+
static int ticks_per_intr;
-void coldfire_timer_init(irq_handler_t handler)
+void hw_timer_init(void)
{
- coldfire_timer_irq.handler = handler;
setup_irq(mcf_timervector, &coldfire_timer_irq);
__raw_writew(MCFTIMER_TMR_DISABLE, TA(MCFTIMER_TMR));
@@ -89,7 +92,7 @@ void coldfire_timer_init(irq_handler_t handler)
/***************************************************************************/
-unsigned long coldfire_timer_offset(void)
+unsigned long hw_timer_offset(void)
{
unsigned long tcn, offset;
diff --git a/arch/m68knommu/platform/532x/Makefile b/arch/m68knommu/platform/532x/Makefile
index 12301803b9eb..475b92866a9b 100644
--- a/arch/m68knommu/platform/532x/Makefile
+++ b/arch/m68knommu/platform/532x/Makefile
@@ -13,7 +13,7 @@
#
ifdef CONFIG_FULLDEBUG
-AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
+EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
endif
#obj-y := config.o usb-mcf532x.o spi-mcf532x.o
diff --git a/arch/m68knommu/platform/532x/config.c b/arch/m68knommu/platform/532x/config.c
index b32c6425f821..f77328b7b6db 100644
--- a/arch/m68knommu/platform/532x/config.c
+++ b/arch/m68knommu/platform/532x/config.c
@@ -18,25 +18,18 @@
/***************************************************************************/
#include <linux/kernel.h>
-#include <linux/sched.h>
#include <linux/param.h>
#include <linux/init.h>
#include <linux/interrupt.h>
-#include <asm/irq.h>
#include <asm/dma.h>
-#include <asm/traps.h>
#include <asm/machdep.h>
#include <asm/coldfire.h>
-#include <asm/mcftimer.h>
#include <asm/mcfsim.h>
#include <asm/mcfdma.h>
#include <asm/mcfwdebug.h>
/***************************************************************************/
-void coldfire_tick(void);
-void coldfire_timer_init(irq_handler_t handler);
-unsigned long coldfire_timer_offset(void);
void coldfire_reset(void);
extern unsigned int mcf_timervector;
@@ -104,9 +97,6 @@ void config_BSP(char *commandp, int size)
mcf_timervector = 64+32;
mcf_profilevector = 64+33;
- mach_sched_init = coldfire_timer_init;
- mach_tick = coldfire_tick;
- mach_gettimeoffset = coldfire_timer_offset;
mach_reset = coldfire_reset;
#ifdef MCF_BDM_DISABLE
diff --git a/arch/m68knommu/platform/5407/Makefile b/arch/m68knommu/platform/5407/Makefile
index 91b2f495dd39..68633b27df51 100644
--- a/arch/m68knommu/platform/5407/Makefile
+++ b/arch/m68knommu/platform/5407/Makefile
@@ -13,7 +13,7 @@
#
ifdef CONFIG_FULLDEBUG
-AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
+EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
endif
obj-y := config.o
diff --git a/arch/m68knommu/platform/5407/config.c b/arch/m68knommu/platform/5407/config.c
index e692536817d8..2d3b62eba7ca 100644
--- a/arch/m68knommu/platform/5407/config.c
+++ b/arch/m68knommu/platform/5407/config.c
@@ -10,24 +10,17 @@
/***************************************************************************/
#include <linux/kernel.h>
-#include <linux/sched.h>
#include <linux/param.h>
#include <linux/init.h>
#include <linux/interrupt.h>
-#include <asm/irq.h>
#include <asm/dma.h>
-#include <asm/traps.h>
#include <asm/machdep.h>
#include <asm/coldfire.h>
-#include <asm/mcftimer.h>
#include <asm/mcfsim.h>
#include <asm/mcfdma.h>
/***************************************************************************/
-void coldfire_tick(void);
-void coldfire_timer_init(irq_handler_t handler);
-unsigned long coldfire_timer_offset(void);
void coldfire_reset(void);
extern unsigned int mcf_timervector;
@@ -108,9 +101,6 @@ void config_BSP(char *commandp, int size)
mcf_timerlevel = 6;
#endif
- mach_sched_init = coldfire_timer_init;
- mach_tick = coldfire_tick;
- mach_gettimeoffset = coldfire_timer_offset;
mach_reset = coldfire_reset;
}
diff --git a/arch/m68knommu/platform/68328/config.c b/arch/m68knommu/platform/68328/config.c
index e5c537d14dfb..a7bd21deb00f 100644
--- a/arch/m68knommu/platform/68328/config.c
+++ b/arch/m68knommu/platform/68328/config.c
@@ -15,28 +15,14 @@
/***************************************************************************/
-#include <asm/dbg.h>
-#include <stdarg.h>
#include <linux/types.h>
#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/console.h>
-#include <linux/interrupt.h>
-#include <asm/current.h>
-
-#include <asm/setup.h>
#include <asm/system.h>
-#include <asm/pgtable.h>
-#include <asm/irq.h>
#include <asm/machdep.h>
#include <asm/MC68328.h>
/***************************************************************************/
-void m68328_timer_init(irq_handler_t timer_routine);
-void m68328_timer_tick(void);
-unsigned long m68328_timer_gettimeoffset(void);
void m68328_timer_gettod(int *year, int *mon, int *day, int *hour, int *min, int *sec);
/***************************************************************************/
@@ -59,14 +45,8 @@ void config_BSP(char *command, int len)
printk(KERN_INFO "68328 support Kenneth Albanowski <kjahds@kjshds.com>\n");
printk(KERN_INFO "68328/Pilot support Bernhard Kuhn <kuhn@lpr.e-technik.tu-muenchen.de>\n");
- mach_sched_init = m68328_timer_init;
- mach_tick = m68328_timer_tick;
- mach_gettimeoffset = m68328_timer_gettimeoffset;
- mach_gettod = m68328_timer_gettod;
- mach_hwclk = NULL;
- mach_set_clock_mmss = NULL;
- mach_reset = m68328_reset;
- *command = '\0';
+ mach_gettod = m68328_timer_gettod;
+ mach_reset = m68328_reset;
}
/***************************************************************************/
diff --git a/arch/m68knommu/platform/68328/timers.c b/arch/m68knommu/platform/68328/timers.c
index 0396476f955d..04cbc661d4bd 100644
--- a/arch/m68knommu/platform/68328/timers.c
+++ b/arch/m68knommu/platform/68328/timers.c
@@ -53,18 +53,28 @@
/***************************************************************************/
+static irqreturn_t hw_tick(int irq, void *dummy)
+{
+ /* Reset Timer1 */
+ TSTAT &= 0;
+
+ return arch_timer_interrupt(irq, dummy);
+}
+
+/***************************************************************************/
+
static struct irqaction m68328_timer_irq = {
- .name = "timer",
- .flags = IRQF_DISABLED | IRQF_TIMER,
+ .name = "timer",
+ .flags = IRQF_DISABLED | IRQF_TIMER,
+ .handler = hw_tick,
};
-void m68328_timer_init(irq_handler_t timer_routine)
+void hw_timer_init(void)
{
/* disable timer 1 */
TCTL = 0;
/* set ISR */
- m68328_timer_irq.handler = timer_routine;
setup_irq(TMR_IRQ_NUM, &m68328_timer_irq);
/* Restart mode, Enable int, Set clock source */
@@ -78,14 +88,7 @@ void m68328_timer_init(irq_handler_t timer_routine)
/***************************************************************************/
-void m68328_timer_tick(void)
-{
- /* Reset Timer1 */
- TSTAT &= 0;
-}
-/***************************************************************************/
-
-unsigned long m68328_timer_gettimeoffset(void)
+unsigned long hw_timer_offset(void)
{
unsigned long ticks = TCN, offset = 0;
diff --git a/arch/m68knommu/platform/68360/config.c b/arch/m68knommu/platform/68360/config.c
index 155b72fe2607..2b3196af811f 100644
--- a/arch/m68knommu/platform/68360/config.c
+++ b/arch/m68knommu/platform/68360/config.c
@@ -14,8 +14,6 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/console.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
@@ -40,8 +38,6 @@ extern void m360_cpm_reset(void);
unsigned long int system_clock;
-void M68360_init_IRQ(void);
-
extern QUICC *pquicc;
/* TODO DON"T Hard Code this */
@@ -49,14 +45,24 @@ extern QUICC *pquicc;
// unsigned int system_clock = 33000000l;
extern unsigned long int system_clock; //In kernel setup.c
-extern void config_M68360_irq(void);
+
+static irqreturn_t hw_tick(int irq, void *dummy)
+{
+ /* Reset Timer1 */
+ /* TSTAT &= 0; */
+
+ pquicc->timer_ter1 = 0x0002; /* clear timer event */
+
+ return arch_timer_interrupt(irq, dummy);
+}
static struct irqaction m68360_timer_irq = {
- .name = "timer",
- .flags = IRQF_DISABLED | IRQF_TIMER,
+ .name = "timer",
+ .flags = IRQF_DISABLED | IRQF_TIMER,
+ .handler = hw_tick,
};
-void BSP_sched_init(irq_handler_t timer_routine)
+void hw_timer_init(void)
{
unsigned char prescaler;
unsigned short tgcr_save;
@@ -90,7 +96,6 @@ void BSP_sched_init(irq_handler_t timer_routine)
pquicc->timer_ter1 = 0x0003; /* clear timer events */
/* enable timer 1 interrupt in CIMR */
- m68360_timer_irq.handler = timer_routine;
setup_irq(CPMVEC_TIMER1, &m68360_timer_irq);
/* Start timer 1: */
@@ -98,16 +103,7 @@ void BSP_sched_init(irq_handler_t timer_routine)
pquicc->timer_tgcr = tgcr_save;
}
-
-void BSP_tick(void)
-{
- /* Reset Timer1 */
- /* TSTAT &= 0; */
-
- pquicc->timer_ter1 = 0x0002; /* clear timer event */
-}
-
-unsigned long BSP_gettimeoffset (void)
+unsigned long hw_timer_offset(void)
{
return 0;
}
@@ -117,17 +113,7 @@ void BSP_gettod (int *yearp, int *monp, int *dayp,
{
}
-int BSP_hwclk(int op, struct rtc_time *t)
-{
- if (!op) {
- /* read */
- } else {
- /* write */
- }
- return 0;
-}
-
-int BSP_set_clock_mmss (unsigned long nowtime)
+int BSP_set_clock_mmss(unsigned long nowtime)
{
#if 0
short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
@@ -200,11 +186,6 @@ void config_BSP(char *command, int len)
scc1_hwaddr = "\00\01\02\03\04\05";
#endif
- mach_sched_init = BSP_sched_init;
- mach_tick = BSP_tick;
- mach_gettimeoffset = BSP_gettimeoffset;
mach_gettod = BSP_gettod;
- mach_hwclk = NULL;
- mach_set_clock_mmss = NULL;
mach_reset = BSP_reset;
}
diff --git a/arch/m68knommu/platform/68EZ328/config.c b/arch/m68knommu/platform/68EZ328/config.c
index ab36551fc969..1be1a16f6896 100644
--- a/arch/m68knommu/platform/68EZ328/config.c
+++ b/arch/m68knommu/platform/68EZ328/config.c
@@ -13,15 +13,8 @@
/***************************************************************************/
-#include <stdarg.h>
#include <linux/types.h>
#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/console.h>
-#include <linux/interrupt.h>
-
-#include <asm/setup.h>
#include <asm/system.h>
#include <asm/pgtable.h>
#include <asm/machdep.h>
@@ -32,9 +25,6 @@
/***************************************************************************/
-void m68328_timer_init(irq_handler_t timer_routine);
-void m68328_timer_tick(void);
-unsigned long m68328_timer_gettimeoffset(void);
void m68328_timer_gettod(int *year, int *mon, int *day, int *hour, int *min, int *sec);
/***************************************************************************/
@@ -79,13 +69,8 @@ void config_BSP(char *command, int len)
else command[0] = 0;
#endif
- mach_sched_init = m68328_timer_init;
- mach_tick = m68328_timer_tick;
- mach_gettimeoffset = m68328_timer_gettimeoffset;
- mach_gettod = m68328_timer_gettod;
- mach_hwclk = NULL;
- mach_set_clock_mmss = NULL;
- mach_reset = m68ez328_reset;
+ mach_gettod = m68328_timer_gettod;
+ mach_reset = m68ez328_reset;
}
/***************************************************************************/
diff --git a/arch/m68knommu/platform/68VZ328/config.c b/arch/m68knommu/platform/68VZ328/config.c
index 79dced929c97..fc5c63054e98 100644
--- a/arch/m68knommu/platform/68VZ328/config.c
+++ b/arch/m68knommu/platform/68VZ328/config.c
@@ -16,17 +16,13 @@
#include <linux/types.h>
#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/console.h>
#include <linux/kd.h>
#include <linux/netdevice.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
-#include <asm/setup.h>
#include <asm/system.h>
#include <asm/pgtable.h>
-#include <asm/irq.h>
#include <asm/machdep.h>
#include <asm/MC68VZ328.h>
#include <asm/bootstd.h>
@@ -37,9 +33,6 @@
/***************************************************************************/
-void m68328_timer_init(irq_handler_t timer_routine);
-void m68328_timer_tick(void);
-unsigned long m68328_timer_gettimeoffset(void);
void m68328_timer_gettod(int *year, int *mon, int *day, int *hour, int *min, int *sec);
/***************************************************************************/
@@ -193,9 +186,6 @@ void config_BSP(char *command, int size)
init_hardware(command, size);
- mach_sched_init = (void *) m68328_timer_init;
- mach_tick = m68328_timer_tick;
- mach_gettimeoffset = m68328_timer_gettimeoffset;
mach_gettod = m68328_timer_gettod;
mach_reset = m68vz328_reset;
}
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index f943736541cb..2f2ce0c28bc0 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -21,6 +21,7 @@ config MACH_ALCHEMY
config BASLER_EXCITE
bool "Basler eXcite smart camera"
+ select CEVT_R4K
select DMA_COHERENT
select HW_HAS_PCI
select IRQ_CPU
@@ -47,6 +48,7 @@ config BASLER_EXCITE_PROTOTYPE
config BCM47XX
bool "BCM47XX based boards"
+ select CEVT_R4K
select DMA_NONCOHERENT
select HW_HAS_PCI
select IRQ_CPU
@@ -63,6 +65,8 @@ config BCM47XX
config MIPS_COBALT
bool "Cobalt Server"
+ select CEVT_R4K
+ select CEVT_GT641XX
select DMA_NONCOHERENT
select HW_HAS_PCI
select I8253
@@ -80,6 +84,7 @@ config MIPS_COBALT
config MACH_DECSTATION
bool "DECstations"
select BOOT_ELF32
+ select CEVT_R4K
select DMA_NONCOHERENT
select NO_IOPORT
select IRQ_CPU
@@ -111,6 +116,7 @@ config MACH_JAZZ
select ARC
select ARC32
select ARCH_MAY_HAVE_PC_FDC
+ select CEVT_R4K
select GENERIC_ISA_DMA
select IRQ_CPU
select I8253
@@ -130,9 +136,11 @@ config MACH_JAZZ
config LASAT
bool "LASAT Networks platforms"
+ select CEVT_R4K
select DMA_NONCOHERENT
select SYS_HAS_EARLY_PRINTK
select HW_HAS_PCI
+ select IRQ_CPU
select PCI_GT64XXX_PCI0
select MIPS_NILE4
select R5000_CPU_SCACHE
@@ -145,6 +153,7 @@ config LASAT
config LEMOTE_FULONG
bool "Lemote Fulong mini-PC"
select ARCH_SPARSEMEM_ENABLE
+ select CEVT_R4K
select SYS_HAS_CPU_LOONGSON2
select DMA_NONCOHERENT
select BOOT_ELF32
@@ -169,6 +178,7 @@ config LEMOTE_FULONG
config MIPS_ATLAS
bool "MIPS Atlas board"
select BOOT_ELF32
+ select CEVT_R4K
select DMA_NONCOHERENT
select SYS_HAS_EARLY_PRINTK
select IRQ_CPU
@@ -199,6 +209,7 @@ config MIPS_MALTA
bool "MIPS Malta board"
select ARCH_MAY_HAVE_PC_FDC
select BOOT_ELF32
+ select CEVT_R4K
select DMA_NONCOHERENT
select GENERIC_ISA_DMA
select IRQ_CPU
@@ -229,6 +240,7 @@ config MIPS_MALTA
config MIPS_SEAD
bool "MIPS SEAD board"
+ select CEVT_R4K
select IRQ_CPU
select DMA_NONCOHERENT
select SYS_HAS_EARLY_PRINTK
@@ -247,6 +259,7 @@ config MIPS_SEAD
config MIPS_SIM
bool 'MIPS simulator (MIPSsim)'
+ select CEVT_R4K
select DMA_NONCOHERENT
select SYS_HAS_EARLY_PRINTK
select IRQ_CPU
@@ -264,6 +277,7 @@ config MIPS_SIM
config MARKEINS
bool "NEC EMMA2RH Mark-eins"
+ select CEVT_R4K
select DMA_NONCOHERENT
select HW_HAS_PCI
select IRQ_CPU
@@ -278,6 +292,7 @@ config MARKEINS
config MACH_VR41XX
bool "NEC VR4100 series based machines"
+ select CEVT_R4K
select SYS_HAS_CPU_VR41XX
select GENERIC_HARDIRQS_NO__DO_IRQ
@@ -314,6 +329,7 @@ config PMC_MSP
config PMC_YOSEMITE
bool "PMC-Sierra Yosemite eval board"
+ select CEVT_R4K
select DMA_COHERENT
select HW_HAS_PCI
select IRQ_CPU
@@ -334,6 +350,7 @@ config PMC_YOSEMITE
config QEMU
bool "Qemu"
+ select CEVT_R4K
select DMA_COHERENT
select GENERIC_ISA_DMA
select HAVE_STD_PC_SERIAL_PORT
@@ -344,10 +361,10 @@ config QEMU
select PCSPEAKER
select SWAP_IO_SPACE
select SYS_HAS_CPU_MIPS32_R1
+ select SYS_HAS_EARLY_PRINTK
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_BIG_ENDIAN
select SYS_SUPPORTS_LITTLE_ENDIAN
- select ARCH_SPARSEMEM_ENABLE
select GENERIC_HARDIRQS_NO__DO_IRQ
select NR_CPUS_DEFAULT_1
select SYS_SUPPORTS_SMP
@@ -364,6 +381,7 @@ config SGI_IP22
select ARC
select ARC32
select BOOT_ELF32
+ select CEVT_R4K
select DMA_NONCOHERENT
select HW_HAS_EISA
select I8253
@@ -408,8 +426,10 @@ config SGI_IP32
select ARC
select ARC32
select BOOT_ELF32
+ select CEVT_R4K
select DMA_NONCOHERENT
select HW_HAS_PCI
+ select IRQ_CPU
select R5000_CPU_SCACHE
select RM7000_CPU_SCACHE
select SYS_HAS_CPU_R5000
@@ -526,6 +546,7 @@ config SIBYTE_BIGSUR
select SWAP_IO_SPACE
select SYS_HAS_CPU_SB1
select SYS_SUPPORTS_BIG_ENDIAN
+ select SYS_SUPPORTS_HIGHMEM
select SYS_SUPPORTS_LITTLE_ENDIAN
config SNI_RM
@@ -534,6 +555,7 @@ config SNI_RM
select ARC32 if CPU_LITTLE_ENDIAN
select ARCH_MAY_HAVE_PC_FDC
select BOOT_ELF32
+ select CEVT_R4K
select DMA_NONCOHERENT
select GENERIC_ISA_DMA
select HW_HAS_EISA
@@ -562,6 +584,7 @@ config SNI_RM
config TOSHIBA_JMR3927
bool "Toshiba JMR-TX3927 board"
+ select CEVT_TXX9
select DMA_NONCOHERENT
select HW_HAS_PCI
select MIPS_TX3927
@@ -575,6 +598,8 @@ config TOSHIBA_JMR3927
config TOSHIBA_RBTX4927
bool "Toshiba RBTX49[23]7 board"
+ select CEVT_R4K
+ select CEVT_TXX9
select DMA_NONCOHERENT
select HAS_TXX9_SERIAL
select HW_HAS_PCI
@@ -595,6 +620,8 @@ config TOSHIBA_RBTX4927
config TOSHIBA_RBTX4938
bool "Toshiba RBTX4938 board"
+ select CEVT_R4K
+ select CEVT_TXX9
select DMA_NONCOHERENT
select HAS_TXX9_SERIAL
select HW_HAS_PCI
@@ -614,6 +641,7 @@ config TOSHIBA_RBTX4938
config WR_PPMC
bool "Wind River PPMC board"
+ select CEVT_R4K
select IRQ_CPU
select BOOT_ELF32
select DMA_NONCOHERENT
@@ -706,6 +734,27 @@ config ARCH_MAY_HAVE_PC_FDC
config BOOT_RAW
bool
+config CEVT_BCM1480
+ bool
+
+config CEVT_GT641XX
+ bool
+
+config CEVT_R4K
+ bool
+
+config CEVT_SB1250
+ bool
+
+config CEVT_TXX9
+ bool
+
+config CSRC_BCM1480
+ bool
+
+config CSRC_SB1250
+ bool
+
config CFE
bool
@@ -1360,7 +1409,6 @@ config MIPS_MT_SMP
depends on SYS_SUPPORTS_MULTITHREADING
select CPU_MIPSR2_IRQ_VI
select CPU_MIPSR2_IRQ_EI
- select CPU_MIPSR2_SRS
select MIPS_MT
select NR_CPUS_DEFAULT_2
select SMP
@@ -1377,7 +1425,6 @@ config MIPS_MT_SMTC
select GENERIC_CLOCKEVENTS_BROADCAST
select CPU_MIPSR2_IRQ_VI
select CPU_MIPSR2_IRQ_EI
- select CPU_MIPSR2_SRS
select MIPS_MT
select NR_CPUS_DEFAULT_8
select SMP
@@ -1404,7 +1451,6 @@ config MIPS_VPE_LOADER
depends on SYS_SUPPORTS_MULTITHREADING
select CPU_MIPSR2_IRQ_VI
select CPU_MIPSR2_IRQ_EI
- select CPU_MIPSR2_SRS
select MIPS_MT
help
Includes a loader for loading an elf relocatable object
@@ -1533,12 +1579,6 @@ config CPU_MIPSR2_IRQ_VI
config CPU_MIPSR2_IRQ_EI
bool
-#
-# Shadow registers are an R2 feature
-#
-config CPU_MIPSR2_SRS
- bool
-
config CPU_HAS_SYNC
bool
depends on !CPU_R3000
@@ -1786,7 +1826,7 @@ config KEXEC
but it is independent of the system firmware. And like a reboot
you can start any kernel with it, not just Linux.
- The name comes from the similiarity to the exec system call.
+ The name comes from the similarity to the exec system call.
It is an ongoing process to be certain the hardware in a machine
is properly shutdown, so do not be surprised if this code does not
@@ -1979,7 +2019,7 @@ source "drivers/Kconfig"
source "fs/Kconfig"
-source "arch/mips/oprofile/Kconfig"
+source "kernel/Kconfig.instrumentation"
source "arch/mips/Kconfig.debug"
diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug
index 3efe117721aa..fd7124c1b75a 100644
--- a/arch/mips/Kconfig.debug
+++ b/arch/mips/Kconfig.debug
@@ -6,18 +6,6 @@ config TRACE_IRQFLAGS_SUPPORT
source "lib/Kconfig.debug"
-config CROSSCOMPILE
- bool "Are you using a crosscompiler"
- help
- Say Y here if you are compiling the kernel on a different
- architecture than the one it is intended to run on. This is just a
- convenience option which will select the appropriate value for
- the CROSS_COMPILE make variable which otherwise has to be passed on
- the command line from mips-linux-, mipsel-linux-, mips64-linux- and
- mips64el-linux- as appropriate for a particular kernel configuration.
- You will have to pass the value for CROSS_COMPILE manually if the
- name prefix for your tools is different.
-
config CMDLINE
string "Default kernel command string"
default ""
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index ebd5d02a7d78..a1f8d8b96b03 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -18,15 +18,15 @@ cflags-y :=
# Select the object file format to substitute into the linker script.
#
ifdef CONFIG_CPU_LITTLE_ENDIAN
-32bit-tool-prefix = mipsel-linux-
-64bit-tool-prefix = mips64el-linux-
+32bit-tool-archpref = mipsel
+64bit-tool-archpref = mips64el
32bit-bfd = elf32-tradlittlemips
64bit-bfd = elf64-tradlittlemips
32bit-emul = elf32ltsmip
64bit-emul = elf64ltsmip
else
-32bit-tool-prefix = mips-linux-
-64bit-tool-prefix = mips64-linux-
+32bit-tool-archpref = mips
+64bit-tool-archpref = mips64
32bit-bfd = elf32-tradbigmips
64bit-bfd = elf64-tradbigmips
32bit-emul = elf32btsmip
@@ -34,16 +34,18 @@ else
endif
ifdef CONFIG_32BIT
-tool-prefix = $(32bit-tool-prefix)
+tool-archpref = $(32bit-tool-archpref)
UTS_MACHINE := mips
endif
ifdef CONFIG_64BIT
-tool-prefix = $(64bit-tool-prefix)
+tool-archpref = $(64bit-tool-archpref)
UTS_MACHINE := mips64
endif
-ifdef CONFIG_CROSSCOMPILE
-CROSS_COMPILE := $(tool-prefix)
+ifneq ($(SUBARCH),$(ARCH))
+ ifeq ($(CROSS_COMPILE),)
+ CROSS_COMPILE := $(call cc-cross-prefix, $(tool-archpref)-linux- $(tool-archpref)-linux-gnu- $(tool-archpref)-unknown-linux-gnu-)
+ endif
endif
ifdef CONFIG_32BIT
@@ -279,7 +281,6 @@ core-$(CONFIG_MACH_DECSTATION) += arch/mips/dec/
cflags-$(CONFIG_MACH_DECSTATION)+= -Iinclude/asm-mips/mach-dec
libs-$(CONFIG_MACH_DECSTATION) += arch/mips/dec/prom/
load-$(CONFIG_MACH_DECSTATION) += 0xffffffff80040000
-CLEAN_FILES += drivers/tc/lk201-map.c
#
# Wind River PPMC Board (4KC + GT64120)
@@ -608,14 +609,14 @@ ifdef CONFIG_64BIT
endif
endif
-AFLAGS += $(cflags-y)
-CFLAGS += $(cflags-y) \
+KBUILD_AFLAGS += $(cflags-y)
+KBUILD_CFLAGS += $(cflags-y) \
-D"VMLINUX_LOAD_ADDRESS=$(load-y)"
LDFLAGS += -m $(ld-emul)
ifdef CONFIG_MIPS
-CHECKFLAGS += $(shell $(CC) $(CFLAGS) -dM -E -xc /dev/null | \
+CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -xc /dev/null | \
egrep -vw '__GNUC_(|MINOR_|PATCHLEVEL_)_' | \
sed -e 's/^\#define /-D/' -e "s/ /='/" -e "s/$$/'/")
ifdef CONFIG_64BIT
@@ -632,7 +633,7 @@ OBJCOPYFLAGS += --remove-section=.reginfo
#
CPPFLAGS_vmlinux.lds := \
- $(CFLAGS) \
+ $(KBUILD_CFLAGS) \
-D"LOADADDR=$(load-y)" \
-D"JIFFIES=$(JIFFIES)" \
-D"DATAOFFSET=$(if $(dataoffset-y),$(dataoffset-y),0)"
diff --git a/arch/mips/au1000/Kconfig b/arch/mips/au1000/Kconfig
index 29c95d97217d..b36cec58a9a8 100644
--- a/arch/mips/au1000/Kconfig
+++ b/arch/mips/au1000/Kconfig
@@ -137,6 +137,8 @@ config SOC_AU1200
config SOC_AU1X00
bool
select 64BIT_PHYS_ADDR
+ select CEVT_R4K
+ select IRQ_CPU
select SYS_HAS_CPU_MIPS32_R1
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_APM_EMULATION
diff --git a/arch/mips/au1000/common/au1xxx_irqmap.c b/arch/mips/au1000/common/au1xxx_irqmap.c
index 7acfe9bf5fc3..98a4e34b0248 100644
--- a/arch/mips/au1000/common/au1xxx_irqmap.c
+++ b/arch/mips/au1000/common/au1xxx_irqmap.c
@@ -54,7 +54,7 @@
* Careful if you change match 2 request!
* The interrupt handler is called directly from the low level dispatch code.
*/
-au1xxx_irq_map_t __initdata au1xxx_ic0_map[] = {
+struct au1xxx_irqmap __initdata au1xxx_ic0_map[] = {
#if defined(CONFIG_SOC_AU1000)
{ AU1000_UART0_INT, INTC_INT_HIGH_LEVEL, 0},
diff --git a/arch/mips/au1000/common/dbdma.c b/arch/mips/au1000/common/dbdma.c
index 461cf0139737..9d6ad43fded6 100644
--- a/arch/mips/au1000/common/dbdma.c
+++ b/arch/mips/au1000/common/dbdma.c
@@ -859,7 +859,7 @@ dbdma_interrupt(int irq, void *dev_id)
intstat = dbdma_gptr->ddma_intstat;
au_sync();
- chan_index = au_ffs(intstat) - 1;
+ chan_index = ffs(intstat);
ctp = chan_tab_ptr[chan_index];
cp = ctp->chan_ptr;
diff --git a/arch/mips/au1000/common/irq.c b/arch/mips/au1000/common/irq.c
index a6640b998c6e..ddfb7f0a17a6 100644
--- a/arch/mips/au1000/common/irq.c
+++ b/arch/mips/au1000/common/irq.c
@@ -1,11 +1,10 @@
/*
- * BRIEF MODULE DESCRIPTION
- * Au1000 interrupt routines.
- *
* Copyright 2001 MontaVista Software Inc.
* Author: MontaVista Software, Inc.
* ppopov@mvista.com or source@mvista.com
*
+ * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org)
+ *
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
@@ -26,59 +25,123 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/errno.h>
+#include <linux/bitops.h>
#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/kernel_stat.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/types.h>
+#include <linux/io.h>
#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/timex.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/delay.h>
-#include <linux/bitops.h>
+#include <linux/irq.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
+#include <asm/irq_cpu.h>
#include <asm/mipsregs.h>
-#include <asm/system.h>
#include <asm/mach-au1x00/au1000.h>
#ifdef CONFIG_MIPS_PB1000
#include <asm/mach-pb1x00/pb1000.h>
#endif
-#undef DEBUG_IRQ
-#ifdef DEBUG_IRQ
-/* note: prints function name for you */
-#define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)
-#else
-#define DPRINTK(fmt, args...)
-#endif
-
#define EXT_INTC0_REQ0 2 /* IP 2 */
#define EXT_INTC0_REQ1 3 /* IP 3 */
#define EXT_INTC1_REQ0 4 /* IP 4 */
#define EXT_INTC1_REQ1 5 /* IP 5 */
#define MIPS_TIMER_IP 7 /* IP 7 */
-void (*board_init_irq)(void);
+void (*board_init_irq)(void) __initdata = NULL;
static DEFINE_SPINLOCK(irq_lock);
+#ifdef CONFIG_PM
+
+/*
+ * Save/restore the interrupt controller state.
+ * Called from the save/restore core registers as part of the
+ * au_sleep function in power.c.....maybe I should just pm_register()
+ * them instead?
+ */
+static unsigned int sleep_intctl_config0[2];
+static unsigned int sleep_intctl_config1[2];
+static unsigned int sleep_intctl_config2[2];
+static unsigned int sleep_intctl_src[2];
+static unsigned int sleep_intctl_assign[2];
+static unsigned int sleep_intctl_wake[2];
+static unsigned int sleep_intctl_mask[2];
+
+void save_au1xxx_intctl(void)
+{
+ sleep_intctl_config0[0] = au_readl(IC0_CFG0RD);
+ sleep_intctl_config1[0] = au_readl(IC0_CFG1RD);
+ sleep_intctl_config2[0] = au_readl(IC0_CFG2RD);
+ sleep_intctl_src[0] = au_readl(IC0_SRCRD);
+ sleep_intctl_assign[0] = au_readl(IC0_ASSIGNRD);
+ sleep_intctl_wake[0] = au_readl(IC0_WAKERD);
+ sleep_intctl_mask[0] = au_readl(IC0_MASKRD);
+
+ sleep_intctl_config0[1] = au_readl(IC1_CFG0RD);
+ sleep_intctl_config1[1] = au_readl(IC1_CFG1RD);
+ sleep_intctl_config2[1] = au_readl(IC1_CFG2RD);
+ sleep_intctl_src[1] = au_readl(IC1_SRCRD);
+ sleep_intctl_assign[1] = au_readl(IC1_ASSIGNRD);
+ sleep_intctl_wake[1] = au_readl(IC1_WAKERD);
+ sleep_intctl_mask[1] = au_readl(IC1_MASKRD);
+}
+
+/*
+ * For most restore operations, we clear the entire register and
+ * then set the bits we found during the save.
+ */
+void restore_au1xxx_intctl(void)
+{
+ au_writel(0xffffffff, IC0_MASKCLR); au_sync();
+
+ au_writel(0xffffffff, IC0_CFG0CLR); au_sync();
+ au_writel(sleep_intctl_config0[0], IC0_CFG0SET); au_sync();
+ au_writel(0xffffffff, IC0_CFG1CLR); au_sync();
+ au_writel(sleep_intctl_config1[0], IC0_CFG1SET); au_sync();
+ au_writel(0xffffffff, IC0_CFG2CLR); au_sync();
+ au_writel(sleep_intctl_config2[0], IC0_CFG2SET); au_sync();
+ au_writel(0xffffffff, IC0_SRCCLR); au_sync();
+ au_writel(sleep_intctl_src[0], IC0_SRCSET); au_sync();
+ au_writel(0xffffffff, IC0_ASSIGNCLR); au_sync();
+ au_writel(sleep_intctl_assign[0], IC0_ASSIGNSET); au_sync();
+ au_writel(0xffffffff, IC0_WAKECLR); au_sync();
+ au_writel(sleep_intctl_wake[0], IC0_WAKESET); au_sync();
+ au_writel(0xffffffff, IC0_RISINGCLR); au_sync();
+ au_writel(0xffffffff, IC0_FALLINGCLR); au_sync();
+ au_writel(0x00000000, IC0_TESTBIT); au_sync();
+
+ au_writel(0xffffffff, IC1_MASKCLR); au_sync();
+
+ au_writel(0xffffffff, IC1_CFG0CLR); au_sync();
+ au_writel(sleep_intctl_config0[1], IC1_CFG0SET); au_sync();
+ au_writel(0xffffffff, IC1_CFG1CLR); au_sync();
+ au_writel(sleep_intctl_config1[1], IC1_CFG1SET); au_sync();
+ au_writel(0xffffffff, IC1_CFG2CLR); au_sync();
+ au_writel(sleep_intctl_config2[1], IC1_CFG2SET); au_sync();
+ au_writel(0xffffffff, IC1_SRCCLR); au_sync();
+ au_writel(sleep_intctl_src[1], IC1_SRCSET); au_sync();
+ au_writel(0xffffffff, IC1_ASSIGNCLR); au_sync();
+ au_writel(sleep_intctl_assign[1], IC1_ASSIGNSET); au_sync();
+ au_writel(0xffffffff, IC1_WAKECLR); au_sync();
+ au_writel(sleep_intctl_wake[1], IC1_WAKESET); au_sync();
+ au_writel(0xffffffff, IC1_RISINGCLR); au_sync();
+ au_writel(0xffffffff, IC1_FALLINGCLR); au_sync();
+ au_writel(0x00000000, IC1_TESTBIT); au_sync();
+
+ au_writel(sleep_intctl_mask[1], IC1_MASKSET); au_sync();
+
+ au_writel(sleep_intctl_mask[0], IC0_MASKSET); au_sync();
+}
+#endif /* CONFIG_PM */
+
inline void local_enable_irq(unsigned int irq_nr)
{
- if (irq_nr > AU1000_LAST_INTC0_INT) {
- au_writel(1<<(irq_nr-32), IC1_MASKSET);
- au_writel(1<<(irq_nr-32), IC1_WAKESET);
- }
- else {
- au_writel(1<<irq_nr, IC0_MASKSET);
- au_writel(1<<irq_nr, IC0_WAKESET);
+ unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
+
+ if (bit >= 32) {
+ au_writel(1 << (bit - 32), IC1_MASKSET);
+ au_writel(1 << (bit - 32), IC1_WAKESET);
+ } else {
+ au_writel(1 << bit, IC0_MASKSET);
+ au_writel(1 << bit, IC0_WAKESET);
}
au_sync();
}
@@ -86,13 +149,14 @@ inline void local_enable_irq(unsigned int irq_nr)
inline void local_disable_irq(unsigned int irq_nr)
{
- if (irq_nr > AU1000_LAST_INTC0_INT) {
- au_writel(1<<(irq_nr-32), IC1_MASKCLR);
- au_writel(1<<(irq_nr-32), IC1_WAKECLR);
- }
- else {
- au_writel(1<<irq_nr, IC0_MASKCLR);
- au_writel(1<<irq_nr, IC0_WAKECLR);
+ unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
+
+ if (bit >= 32) {
+ au_writel(1 << (bit - 32), IC1_MASKCLR);
+ au_writel(1 << (bit - 32), IC1_WAKECLR);
+ } else {
+ au_writel(1 << bit, IC0_MASKCLR);
+ au_writel(1 << bit, IC0_WAKECLR);
}
au_sync();
}
@@ -100,13 +164,14 @@ inline void local_disable_irq(unsigned int irq_nr)
static inline void mask_and_ack_rise_edge_irq(unsigned int irq_nr)
{
- if (irq_nr > AU1000_LAST_INTC0_INT) {
- au_writel(1<<(irq_nr-32), IC1_RISINGCLR);
- au_writel(1<<(irq_nr-32), IC1_MASKCLR);
- }
- else {
- au_writel(1<<irq_nr, IC0_RISINGCLR);
- au_writel(1<<irq_nr, IC0_MASKCLR);
+ unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
+
+ if (bit >= 32) {
+ au_writel(1 << (bit - 32), IC1_RISINGCLR);
+ au_writel(1 << (bit - 32), IC1_MASKCLR);
+ } else {
+ au_writel(1 << bit, IC0_RISINGCLR);
+ au_writel(1 << bit, IC0_MASKCLR);
}
au_sync();
}
@@ -114,13 +179,14 @@ static inline void mask_and_ack_rise_edge_irq(unsigned int irq_nr)
static inline void mask_and_ack_fall_edge_irq(unsigned int irq_nr)
{
- if (irq_nr > AU1000_LAST_INTC0_INT) {
- au_writel(1<<(irq_nr-32), IC1_FALLINGCLR);
- au_writel(1<<(irq_nr-32), IC1_MASKCLR);
- }
- else {
- au_writel(1<<irq_nr, IC0_FALLINGCLR);
- au_writel(1<<irq_nr, IC0_MASKCLR);
+ unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
+
+ if (bit >= 32) {
+ au_writel(1 << (bit - 32), IC1_FALLINGCLR);
+ au_writel(1 << (bit - 32), IC1_MASKCLR);
+ } else {
+ au_writel(1 << bit, IC0_FALLINGCLR);
+ au_writel(1 << bit, IC0_MASKCLR);
}
au_sync();
}
@@ -128,18 +194,20 @@ static inline void mask_and_ack_fall_edge_irq(unsigned int irq_nr)
static inline void mask_and_ack_either_edge_irq(unsigned int irq_nr)
{
- /* This may assume that we don't get interrupts from
+ unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
+
+ /*
+ * This may assume that we don't get interrupts from
* both edges at once, or if we do, that we don't care.
*/
- if (irq_nr > AU1000_LAST_INTC0_INT) {
- au_writel(1<<(irq_nr-32), IC1_FALLINGCLR);
- au_writel(1<<(irq_nr-32), IC1_RISINGCLR);
- au_writel(1<<(irq_nr-32), IC1_MASKCLR);
- }
- else {
- au_writel(1<<irq_nr, IC0_FALLINGCLR);
- au_writel(1<<irq_nr, IC0_RISINGCLR);
- au_writel(1<<irq_nr, IC0_MASKCLR);
+ if (bit >= 32) {
+ au_writel(1 << (bit - 32), IC1_FALLINGCLR);
+ au_writel(1 << (bit - 32), IC1_RISINGCLR);
+ au_writel(1 << (bit - 32), IC1_MASKCLR);
+ } else {
+ au_writel(1 << bit, IC0_FALLINGCLR);
+ au_writel(1 << bit, IC0_RISINGCLR);
+ au_writel(1 << bit, IC0_MASKCLR);
}
au_sync();
}
@@ -156,15 +224,13 @@ static inline void mask_and_ack_level_irq(unsigned int irq_nr)
au_sync();
}
#endif
- return;
}
-
static void end_irq(unsigned int irq_nr)
{
- if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
+ if (!(irq_desc[irq_nr].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
local_enable_irq(irq_nr);
- }
+
#if defined(CONFIG_MIPS_PB1000)
if (irq_nr == AU1000_GPIO_15) {
au_writel(0x4000, PB1000_MDR); /* enable int */
@@ -181,15 +247,12 @@ unsigned long save_local_and_disable(int controller)
spin_lock_irqsave(&irq_lock, flags);
if (controller) {
mask = au_readl(IC1_MASKSET);
- for (i=32; i<64; i++) {
+ for (i = 32; i < 64; i++)
local_disable_irq(i);
- }
- }
- else {
+ } else {
mask = au_readl(IC0_MASKSET);
- for (i=0; i<32; i++) {
+ for (i = 0; i < 32; i++)
local_disable_irq(i);
- }
}
spin_unlock_irqrestore(&irq_lock, flags);
@@ -202,10 +265,10 @@ void restore_local_and_enable(int controller, unsigned long mask)
unsigned long flags, new_mask;
spin_lock_irqsave(&irq_lock, flags);
- for (i=0; i<32; i++) {
- if (mask & (1<<i)) {
+ for (i = 0; i < 32; i++) {
+ if (mask & (1 << i)) {
if (controller)
- local_enable_irq(i+32);
+ local_enable_irq(i + 32);
else
local_enable_irq(i);
}
@@ -220,245 +283,157 @@ void restore_local_and_enable(int controller, unsigned long mask)
static struct irq_chip rise_edge_irq_type = {
- .name = "Au1000 Rise Edge",
- .ack = mask_and_ack_rise_edge_irq,
- .mask = local_disable_irq,
- .mask_ack = mask_and_ack_rise_edge_irq,
- .unmask = local_enable_irq,
- .end = end_irq,
+ .name = "Au1000 Rise Edge",
+ .ack = mask_and_ack_rise_edge_irq,
+ .mask = local_disable_irq,
+ .mask_ack = mask_and_ack_rise_edge_irq,
+ .unmask = local_enable_irq,
+ .end = end_irq,
};
static struct irq_chip fall_edge_irq_type = {
- .name = "Au1000 Fall Edge",
- .ack = mask_and_ack_fall_edge_irq,
- .mask = local_disable_irq,
- .mask_ack = mask_and_ack_fall_edge_irq,
- .unmask = local_enable_irq,
- .end = end_irq,
+ .name = "Au1000 Fall Edge",
+ .ack = mask_and_ack_fall_edge_irq,
+ .mask = local_disable_irq,
+ .mask_ack = mask_and_ack_fall_edge_irq,
+ .unmask = local_enable_irq,
+ .end = end_irq,
};
static struct irq_chip either_edge_irq_type = {
- .name = "Au1000 Rise or Fall Edge",
- .ack = mask_and_ack_either_edge_irq,
- .mask = local_disable_irq,
- .mask_ack = mask_and_ack_either_edge_irq,
- .unmask = local_enable_irq,
- .end = end_irq,
+ .name = "Au1000 Rise or Fall Edge",
+ .ack = mask_and_ack_either_edge_irq,
+ .mask = local_disable_irq,
+ .mask_ack = mask_and_ack_either_edge_irq,
+ .unmask = local_enable_irq,
+ .end = end_irq,
};
static struct irq_chip level_irq_type = {
- .name = "Au1000 Level",
- .ack = mask_and_ack_level_irq,
- .mask = local_disable_irq,
- .mask_ack = mask_and_ack_level_irq,
- .unmask = local_enable_irq,
- .end = end_irq,
+ .name = "Au1000 Level",
+ .ack = mask_and_ack_level_irq,
+ .mask = local_disable_irq,
+ .mask_ack = mask_and_ack_level_irq,
+ .unmask = local_enable_irq,
+ .end = end_irq,
};
-#ifdef CONFIG_PM
-void startup_match20_interrupt(irq_handler_t handler)
+static void __init setup_local_irq(unsigned int irq_nr, int type, int int_req)
{
- struct irq_desc *desc = &irq_desc[AU1000_TOY_MATCH2_INT];
-
- static struct irqaction action;
- memset(&action, 0, sizeof(struct irqaction));
-
- /* This is a big problem.... since we didn't use request_irq
- * when kernel/irq.c calls probe_irq_xxx this interrupt will
- * be probed for usage. This will end up disabling the device :(
- * Give it a bogus "action" pointer -- this will keep it from
- * getting auto-probed!
- *
- * By setting the status to match that of request_irq() we
- * can avoid it. --cgray
- */
- action.dev_id = handler;
- action.flags = IRQF_DISABLED;
- cpus_clear(action.mask);
- action.name = "Au1xxx TOY";
- action.handler = handler;
- action.next = NULL;
-
- desc->action = &action;
- desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS);
+ unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
- local_enable_irq(AU1000_TOY_MATCH2_INT);
-}
-#endif
+ if (irq_nr > AU1000_MAX_INTR)
+ return;
-static void setup_local_irq(unsigned int irq_nr, int type, int int_req)
-{
- if (irq_nr > AU1000_MAX_INTR) return;
/* Config2[n], Config1[n], Config0[n] */
- if (irq_nr > AU1000_LAST_INTC0_INT) {
+ if (bit >= 32) {
switch (type) {
- case INTC_INT_RISE_EDGE: /* 0:0:1 */
- au_writel(1<<(irq_nr-32), IC1_CFG2CLR);
- au_writel(1<<(irq_nr-32), IC1_CFG1CLR);
- au_writel(1<<(irq_nr-32), IC1_CFG0SET);
- set_irq_chip(irq_nr, &rise_edge_irq_type);
- break;
- case INTC_INT_FALL_EDGE: /* 0:1:0 */
- au_writel(1<<(irq_nr-32), IC1_CFG2CLR);
- au_writel(1<<(irq_nr-32), IC1_CFG1SET);
- au_writel(1<<(irq_nr-32), IC1_CFG0CLR);
- set_irq_chip(irq_nr, &fall_edge_irq_type);
- break;
- case INTC_INT_RISE_AND_FALL_EDGE: /* 0:1:1 */
- au_writel(1<<(irq_nr-32), IC1_CFG2CLR);
- au_writel(1<<(irq_nr-32), IC1_CFG1SET);
- au_writel(1<<(irq_nr-32), IC1_CFG0SET);
- set_irq_chip(irq_nr, &either_edge_irq_type);
- break;
- case INTC_INT_HIGH_LEVEL: /* 1:0:1 */
- au_writel(1<<(irq_nr-32), IC1_CFG2SET);
- au_writel(1<<(irq_nr-32), IC1_CFG1CLR);
- au_writel(1<<(irq_nr-32), IC1_CFG0SET);
- set_irq_chip(irq_nr, &level_irq_type);
- break;
- case INTC_INT_LOW_LEVEL: /* 1:1:0 */
- au_writel(1<<(irq_nr-32), IC1_CFG2SET);
- au_writel(1<<(irq_nr-32), IC1_CFG1SET);
- au_writel(1<<(irq_nr-32), IC1_CFG0CLR);
- set_irq_chip(irq_nr, &level_irq_type);
- break;
- case INTC_INT_DISABLED: /* 0:0:0 */
- au_writel(1<<(irq_nr-32), IC1_CFG0CLR);
- au_writel(1<<(irq_nr-32), IC1_CFG1CLR);
- au_writel(1<<(irq_nr-32), IC1_CFG2CLR);
- break;
- default: /* disable the interrupt */
- printk("unexpected int type %d (irq %d)\n", type, irq_nr);
- au_writel(1<<(irq_nr-32), IC1_CFG0CLR);
- au_writel(1<<(irq_nr-32), IC1_CFG1CLR);
- au_writel(1<<(irq_nr-32), IC1_CFG2CLR);
- return;
+ case INTC_INT_RISE_EDGE: /* 0:0:1 */
+ au_writel(1 << (bit - 32), IC1_CFG2CLR);
+ au_writel(1 << (bit - 32), IC1_CFG1CLR);
+ au_writel(1 << (bit - 32), IC1_CFG0SET);
+ set_irq_chip(irq_nr, &rise_edge_irq_type);
+ break;
+ case INTC_INT_FALL_EDGE: /* 0:1:0 */
+ au_writel(1 << (bit - 32), IC1_CFG2CLR);
+ au_writel(1 << (bit - 32), IC1_CFG1SET);
+ au_writel(1 << (bit - 32), IC1_CFG0CLR);
+ set_irq_chip(irq_nr, &fall_edge_irq_type);
+ break;
+ case INTC_INT_RISE_AND_FALL_EDGE: /* 0:1:1 */
+ au_writel(1 << (bit - 32), IC1_CFG2CLR);
+ au_writel(1 << (bit - 32), IC1_CFG1SET);
+ au_writel(1 << (bit - 32), IC1_CFG0SET);
+ set_irq_chip(irq_nr, &either_edge_irq_type);
+ break;
+ case INTC_INT_HIGH_LEVEL: /* 1:0:1 */
+ au_writel(1 << (bit - 32), IC1_CFG2SET);
+ au_writel(1 << (bit - 32), IC1_CFG1CLR);
+ au_writel(1 << (bit - 32), IC1_CFG0SET);
+ set_irq_chip(irq_nr, &level_irq_type);
+ break;
+ case INTC_INT_LOW_LEVEL: /* 1:1:0 */
+ au_writel(1 << (bit - 32), IC1_CFG2SET);
+ au_writel(1 << (bit - 32), IC1_CFG1SET);
+ au_writel(1 << (bit - 32), IC1_CFG0CLR);
+ set_irq_chip(irq_nr, &level_irq_type);
+ break;
+ case INTC_INT_DISABLED: /* 0:0:0 */
+ au_writel(1 << (bit - 32), IC1_CFG0CLR);
+ au_writel(1 << (bit - 32), IC1_CFG1CLR);
+ au_writel(1 << (bit - 32), IC1_CFG2CLR);
+ break;
+ default: /* disable the interrupt */
+ printk(KERN_WARNING "unexpected int type %d (irq %d)\n",
+ type, irq_nr);
+ au_writel(1 << (bit - 32), IC1_CFG0CLR);
+ au_writel(1 << (bit - 32), IC1_CFG1CLR);
+ au_writel(1 << (bit - 32), IC1_CFG2CLR);
+ return;
}
if (int_req) /* assign to interrupt request 1 */
- au_writel(1<<(irq_nr-32), IC1_ASSIGNCLR);
+ au_writel(1 << (bit - 32), IC1_ASSIGNCLR);
else /* assign to interrupt request 0 */
- au_writel(1<<(irq_nr-32), IC1_ASSIGNSET);
- au_writel(1<<(irq_nr-32), IC1_SRCSET);
- au_writel(1<<(irq_nr-32), IC1_MASKCLR);
- au_writel(1<<(irq_nr-32), IC1_WAKECLR);
- }
- else {
+ au_writel(1 << (bit - 32), IC1_ASSIGNSET);
+ au_writel(1 << (bit - 32), IC1_SRCSET);
+ au_writel(1 << (bit - 32), IC1_MASKCLR);
+ au_writel(1 << (bit - 32), IC1_WAKECLR);
+ } else {
switch (type) {
- case INTC_INT_RISE_EDGE: /* 0:0:1 */
- au_writel(1<<irq_nr, IC0_CFG2CLR);
- au_writel(1<<irq_nr, IC0_CFG1CLR);
- au_writel(1<<irq_nr, IC0_CFG0SET);
- set_irq_chip(irq_nr, &rise_edge_irq_type);
- break;
- case INTC_INT_FALL_EDGE: /* 0:1:0 */
- au_writel(1<<irq_nr, IC0_CFG2CLR);
- au_writel(1<<irq_nr, IC0_CFG1SET);
- au_writel(1<<irq_nr, IC0_CFG0CLR);
- set_irq_chip(irq_nr, &fall_edge_irq_type);
- break;
- case INTC_INT_RISE_AND_FALL_EDGE: /* 0:1:1 */
- au_writel(1<<irq_nr, IC0_CFG2CLR);
- au_writel(1<<irq_nr, IC0_CFG1SET);
- au_writel(1<<irq_nr, IC0_CFG0SET);
- set_irq_chip(irq_nr, &either_edge_irq_type);
- break;
- case INTC_INT_HIGH_LEVEL: /* 1:0:1 */
- au_writel(1<<irq_nr, IC0_CFG2SET);
- au_writel(1<<irq_nr, IC0_CFG1CLR);
- au_writel(1<<irq_nr, IC0_CFG0SET);
- set_irq_chip(irq_nr, &level_irq_type);
- break;
- case INTC_INT_LOW_LEVEL: /* 1:1:0 */
- au_writel(1<<irq_nr, IC0_CFG2SET);
- au_writel(1<<irq_nr, IC0_CFG1SET);
- au_writel(1<<irq_nr, IC0_CFG0CLR);
- set_irq_chip(irq_nr, &level_irq_type);
- break;
- case INTC_INT_DISABLED: /* 0:0:0 */
- au_writel(1<<irq_nr, IC0_CFG0CLR);
- au_writel(1<<irq_nr, IC0_CFG1CLR);
- au_writel(1<<irq_nr, IC0_CFG2CLR);
- break;
- default: /* disable the interrupt */
- printk("unexpected int type %d (irq %d)\n", type, irq_nr);
- au_writel(1<<irq_nr, IC0_CFG0CLR);
- au_writel(1<<irq_nr, IC0_CFG1CLR);
- au_writel(1<<irq_nr, IC0_CFG2CLR);
- return;
+ case INTC_INT_RISE_EDGE: /* 0:0:1 */
+ au_writel(1 << bit, IC0_CFG2CLR);
+ au_writel(1 << bit, IC0_CFG1CLR);
+ au_writel(1 << bit, IC0_CFG0SET);
+ set_irq_chip(irq_nr, &rise_edge_irq_type);
+ break;
+ case INTC_INT_FALL_EDGE: /* 0:1:0 */
+ au_writel(1 << bit, IC0_CFG2CLR);
+ au_writel(1 << bit, IC0_CFG1SET);
+ au_writel(1 << bit, IC0_CFG0CLR);
+ set_irq_chip(irq_nr, &fall_edge_irq_type);
+ break;
+ case INTC_INT_RISE_AND_FALL_EDGE: /* 0:1:1 */
+ au_writel(1 << bit, IC0_CFG2CLR);
+ au_writel(1 << bit, IC0_CFG1SET);
+ au_writel(1 << bit, IC0_CFG0SET);
+ set_irq_chip(irq_nr, &either_edge_irq_type);
+ break;
+ case INTC_INT_HIGH_LEVEL: /* 1:0:1 */
+ au_writel(1 << bit, IC0_CFG2SET);
+ au_writel(1 << bit, IC0_CFG1CLR);
+ au_writel(1 << bit, IC0_CFG0SET);
+ set_irq_chip(irq_nr, &level_irq_type);
+ break;
+ case INTC_INT_LOW_LEVEL: /* 1:1:0 */
+ au_writel(1 << bit, IC0_CFG2SET);
+ au_writel(1 << bit, IC0_CFG1SET);
+ au_writel(1 << bit, IC0_CFG0CLR);
+ set_irq_chip(irq_nr, &level_irq_type);
+ break;
+ case INTC_INT_DISABLED: /* 0:0:0 */
+ au_writel(1 << bit, IC0_CFG0CLR);
+ au_writel(1 << bit, IC0_CFG1CLR);
+ au_writel(1 << bit, IC0_CFG2CLR);
+ break;
+ default: /* disable the interrupt */
+ printk(KERN_WARNING "unexpected int type %d (irq %d)\n",
+ type, irq_nr);
+ au_writel(1 << bit, IC0_CFG0CLR);
+ au_writel(1 << bit, IC0_CFG1CLR);
+ au_writel(1 << bit, IC0_CFG2CLR);
+ return;
}
if (int_req) /* assign to interrupt request 1 */
- au_writel(1<<irq_nr, IC0_ASSIGNCLR);
+ au_writel(1 << bit, IC0_ASSIGNCLR);
else /* assign to interrupt request 0 */
- au_writel(1<<irq_nr, IC0_ASSIGNSET);
- au_writel(1<<irq_nr, IC0_SRCSET);
- au_writel(1<<irq_nr, IC0_MASKCLR);
- au_writel(1<<irq_nr, IC0_WAKECLR);
+ au_writel(1 << bit, IC0_ASSIGNSET);
+ au_writel(1 << bit, IC0_SRCSET);
+ au_writel(1 << bit, IC0_MASKCLR);
+ au_writel(1 << bit, IC0_WAKECLR);
}
au_sync();
}
-
-void __init arch_init_irq(void)
-{
- int i;
- unsigned long cp0_status;
- au1xxx_irq_map_t *imp;
- extern au1xxx_irq_map_t au1xxx_irq_map[];
- extern au1xxx_irq_map_t au1xxx_ic0_map[];
- extern int au1xxx_nr_irqs;
- extern int au1xxx_ic0_nr_irqs;
-
- cp0_status = read_c0_status();
-
- /* Initialize interrupt controllers to a safe state.
- */
- au_writel(0xffffffff, IC0_CFG0CLR);
- au_writel(0xffffffff, IC0_CFG1CLR);
- au_writel(0xffffffff, IC0_CFG2CLR);
- au_writel(0xffffffff, IC0_MASKCLR);
- au_writel(0xffffffff, IC0_ASSIGNSET);
- au_writel(0xffffffff, IC0_WAKECLR);
- au_writel(0xffffffff, IC0_SRCSET);
- au_writel(0xffffffff, IC0_FALLINGCLR);
- au_writel(0xffffffff, IC0_RISINGCLR);
- au_writel(0x00000000, IC0_TESTBIT);
-
- au_writel(0xffffffff, IC1_CFG0CLR);
- au_writel(0xffffffff, IC1_CFG1CLR);
- au_writel(0xffffffff, IC1_CFG2CLR);
- au_writel(0xffffffff, IC1_MASKCLR);
- au_writel(0xffffffff, IC1_ASSIGNSET);
- au_writel(0xffffffff, IC1_WAKECLR);
- au_writel(0xffffffff, IC1_SRCSET);
- au_writel(0xffffffff, IC1_FALLINGCLR);
- au_writel(0xffffffff, IC1_RISINGCLR);
- au_writel(0x00000000, IC1_TESTBIT);
-
- /* Initialize IC0, which is fixed per processor.
- */
- imp = au1xxx_ic0_map;
- for (i=0; i<au1xxx_ic0_nr_irqs; i++) {
- setup_local_irq(imp->im_irq, imp->im_type, imp->im_request);
- imp++;
- }
-
- /* Now set up the irq mapping for the board.
- */
- imp = au1xxx_irq_map;
- for (i=0; i<au1xxx_nr_irqs; i++) {
- setup_local_irq(imp->im_irq, imp->im_type, imp->im_request);
- imp++;
- }
-
- set_c0_status(ALLINTS);
-
- /* Board specific IRQ initialization.
- */
- if (board_init_irq)
- (*board_init_irq)();
-}
-
-
/*
* Interrupts are nested. Even if an interrupt handler is registered
* as "fast", we might get another interrupt before we return from
@@ -467,44 +442,45 @@ void __init arch_init_irq(void)
static void intc0_req0_irqdispatch(void)
{
- int irq = 0;
- static unsigned long intc0_req0 = 0;
+ static unsigned long intc0_req0;
+ unsigned int bit;
intc0_req0 |= au_readl(IC0_REQ0INT);
if (!intc0_req0)
return;
+
#ifdef AU1000_USB_DEV_REQ_INT
/*
* Because of the tight timing of SETUP token to reply
* transactions, the USB devices-side packet complete
* interrupt needs the highest priority.
*/
- if ((intc0_req0 & (1<<AU1000_USB_DEV_REQ_INT))) {
- intc0_req0 &= ~(1<<AU1000_USB_DEV_REQ_INT);
+ if ((intc0_req0 & (1 << AU1000_USB_DEV_REQ_INT))) {
+ intc0_req0 &= ~(1 << AU1000_USB_DEV_REQ_INT);
do_IRQ(AU1000_USB_DEV_REQ_INT);
return;
}
#endif
- irq = au_ffs(intc0_req0) - 1;
- intc0_req0 &= ~(1<<irq);
- do_IRQ(irq);
+ bit = ffs(intc0_req0);
+ intc0_req0 &= ~(1 << bit);
+ do_IRQ(MIPS_CPU_IRQ_BASE + bit);
}
static void intc0_req1_irqdispatch(void)
{
- int irq = 0;
- static unsigned long intc0_req1 = 0;
+ static unsigned long intc0_req1;
+ unsigned int bit;
intc0_req1 |= au_readl(IC0_REQ1INT);
if (!intc0_req1)
return;
- irq = au_ffs(intc0_req1) - 1;
- intc0_req1 &= ~(1<<irq);
- do_IRQ(irq);
+ bit = ffs(intc0_req1);
+ intc0_req1 &= ~(1 << bit);
+ do_IRQ(bit);
}
@@ -514,126 +490,41 @@ static void intc0_req1_irqdispatch(void)
*/
static void intc1_req0_irqdispatch(void)
{
- int irq = 0;
- static unsigned long intc1_req0 = 0;
+ static unsigned long intc1_req0;
+ unsigned int bit;
intc1_req0 |= au_readl(IC1_REQ0INT);
if (!intc1_req0)
return;
- irq = au_ffs(intc1_req0) - 1;
- intc1_req0 &= ~(1<<irq);
- irq += 32;
- do_IRQ(irq);
+ bit = ffs(intc1_req0);
+ intc1_req0 &= ~(1 << bit);
+ do_IRQ(MIPS_CPU_IRQ_BASE + 32 + bit);
}
static void intc1_req1_irqdispatch(void)
{
- int irq = 0;
- static unsigned long intc1_req1 = 0;
+ static unsigned long intc1_req1;
+ unsigned int bit;
intc1_req1 |= au_readl(IC1_REQ1INT);
if (!intc1_req1)
return;
- irq = au_ffs(intc1_req1) - 1;
- intc1_req1 &= ~(1<<irq);
- irq += 32;
- do_IRQ(irq);
-}
-
-#ifdef CONFIG_PM
-
-/* Save/restore the interrupt controller state.
- * Called from the save/restore core registers as part of the
- * au_sleep function in power.c.....maybe I should just pm_register()
- * them instead?
- */
-static unsigned int sleep_intctl_config0[2];
-static unsigned int sleep_intctl_config1[2];
-static unsigned int sleep_intctl_config2[2];
-static unsigned int sleep_intctl_src[2];
-static unsigned int sleep_intctl_assign[2];
-static unsigned int sleep_intctl_wake[2];
-static unsigned int sleep_intctl_mask[2];
-
-void
-save_au1xxx_intctl(void)
-{
- sleep_intctl_config0[0] = au_readl(IC0_CFG0RD);
- sleep_intctl_config1[0] = au_readl(IC0_CFG1RD);
- sleep_intctl_config2[0] = au_readl(IC0_CFG2RD);
- sleep_intctl_src[0] = au_readl(IC0_SRCRD);
- sleep_intctl_assign[0] = au_readl(IC0_ASSIGNRD);
- sleep_intctl_wake[0] = au_readl(IC0_WAKERD);
- sleep_intctl_mask[0] = au_readl(IC0_MASKRD);
-
- sleep_intctl_config0[1] = au_readl(IC1_CFG0RD);
- sleep_intctl_config1[1] = au_readl(IC1_CFG1RD);
- sleep_intctl_config2[1] = au_readl(IC1_CFG2RD);
- sleep_intctl_src[1] = au_readl(IC1_SRCRD);
- sleep_intctl_assign[1] = au_readl(IC1_ASSIGNRD);
- sleep_intctl_wake[1] = au_readl(IC1_WAKERD);
- sleep_intctl_mask[1] = au_readl(IC1_MASKRD);
-}
-
-/* For most restore operations, we clear the entire register and
- * then set the bits we found during the save.
- */
-void
-restore_au1xxx_intctl(void)
-{
- au_writel(0xffffffff, IC0_MASKCLR); au_sync();
-
- au_writel(0xffffffff, IC0_CFG0CLR); au_sync();
- au_writel(sleep_intctl_config0[0], IC0_CFG0SET); au_sync();
- au_writel(0xffffffff, IC0_CFG1CLR); au_sync();
- au_writel(sleep_intctl_config1[0], IC0_CFG1SET); au_sync();
- au_writel(0xffffffff, IC0_CFG2CLR); au_sync();
- au_writel(sleep_intctl_config2[0], IC0_CFG2SET); au_sync();
- au_writel(0xffffffff, IC0_SRCCLR); au_sync();
- au_writel(sleep_intctl_src[0], IC0_SRCSET); au_sync();
- au_writel(0xffffffff, IC0_ASSIGNCLR); au_sync();
- au_writel(sleep_intctl_assign[0], IC0_ASSIGNSET); au_sync();
- au_writel(0xffffffff, IC0_WAKECLR); au_sync();
- au_writel(sleep_intctl_wake[0], IC0_WAKESET); au_sync();
- au_writel(0xffffffff, IC0_RISINGCLR); au_sync();
- au_writel(0xffffffff, IC0_FALLINGCLR); au_sync();
- au_writel(0x00000000, IC0_TESTBIT); au_sync();
-
- au_writel(0xffffffff, IC1_MASKCLR); au_sync();
-
- au_writel(0xffffffff, IC1_CFG0CLR); au_sync();
- au_writel(sleep_intctl_config0[1], IC1_CFG0SET); au_sync();
- au_writel(0xffffffff, IC1_CFG1CLR); au_sync();
- au_writel(sleep_intctl_config1[1], IC1_CFG1SET); au_sync();
- au_writel(0xffffffff, IC1_CFG2CLR); au_sync();
- au_writel(sleep_intctl_config2[1], IC1_CFG2SET); au_sync();
- au_writel(0xffffffff, IC1_SRCCLR); au_sync();
- au_writel(sleep_intctl_src[1], IC1_SRCSET); au_sync();
- au_writel(0xffffffff, IC1_ASSIGNCLR); au_sync();
- au_writel(sleep_intctl_assign[1], IC1_ASSIGNSET); au_sync();
- au_writel(0xffffffff, IC1_WAKECLR); au_sync();
- au_writel(sleep_intctl_wake[1], IC1_WAKESET); au_sync();
- au_writel(0xffffffff, IC1_RISINGCLR); au_sync();
- au_writel(0xffffffff, IC1_FALLINGCLR); au_sync();
- au_writel(0x00000000, IC1_TESTBIT); au_sync();
-
- au_writel(sleep_intctl_mask[1], IC1_MASKSET); au_sync();
-
- au_writel(sleep_intctl_mask[0], IC0_MASKSET); au_sync();
+ bit = ffs(intc1_req1);
+ intc1_req1 &= ~(1 << bit);
+ do_IRQ(MIPS_CPU_IRQ_BASE + 32 + bit);
}
-#endif /* CONFIG_PM */
asmlinkage void plat_irq_dispatch(void)
{
- unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
+ unsigned int pending = read_c0_status() & read_c0_cause();
if (pending & CAUSEF_IP7)
- do_IRQ(63);
+ do_IRQ(MIPS_CPU_IRQ_BASE + 7);
else if (pending & CAUSEF_IP2)
intc0_req0_irqdispatch();
else if (pending & CAUSEF_IP3)
@@ -645,3 +536,65 @@ asmlinkage void plat_irq_dispatch(void)
else
spurious_interrupt();
}
+
+void __init arch_init_irq(void)
+{
+ int i;
+ struct au1xxx_irqmap *imp;
+ extern struct au1xxx_irqmap au1xxx_irq_map[];
+ extern struct au1xxx_irqmap au1xxx_ic0_map[];
+ extern int au1xxx_nr_irqs;
+ extern int au1xxx_ic0_nr_irqs;
+
+ /*
+ * Initialize interrupt controllers to a safe state.
+ */
+ au_writel(0xffffffff, IC0_CFG0CLR);
+ au_writel(0xffffffff, IC0_CFG1CLR);
+ au_writel(0xffffffff, IC0_CFG2CLR);
+ au_writel(0xffffffff, IC0_MASKCLR);
+ au_writel(0xffffffff, IC0_ASSIGNSET);
+ au_writel(0xffffffff, IC0_WAKECLR);
+ au_writel(0xffffffff, IC0_SRCSET);
+ au_writel(0xffffffff, IC0_FALLINGCLR);
+ au_writel(0xffffffff, IC0_RISINGCLR);
+ au_writel(0x00000000, IC0_TESTBIT);
+
+ au_writel(0xffffffff, IC1_CFG0CLR);
+ au_writel(0xffffffff, IC1_CFG1CLR);
+ au_writel(0xffffffff, IC1_CFG2CLR);
+ au_writel(0xffffffff, IC1_MASKCLR);
+ au_writel(0xffffffff, IC1_ASSIGNSET);
+ au_writel(0xffffffff, IC1_WAKECLR);
+ au_writel(0xffffffff, IC1_SRCSET);
+ au_writel(0xffffffff, IC1_FALLINGCLR);
+ au_writel(0xffffffff, IC1_RISINGCLR);
+ au_writel(0x00000000, IC1_TESTBIT);
+
+ mips_cpu_irq_init();
+
+ /*
+ * Initialize IC0, which is fixed per processor.
+ */
+ imp = au1xxx_ic0_map;
+ for (i = 0; i < au1xxx_ic0_nr_irqs; i++) {
+ setup_local_irq(imp->im_irq, imp->im_type, imp->im_request);
+ imp++;
+ }
+
+ /*
+ * Now set up the irq mapping for the board.
+ */
+ imp = au1xxx_irq_map;
+ for (i = 0; i < au1xxx_nr_irqs; i++) {
+ setup_local_irq(imp->im_irq, imp->im_type, imp->im_request);
+ imp++;
+ }
+
+ set_c0_status(ALLINTS);
+
+ /* Board specific IRQ initialization.
+ */
+ if (board_init_irq)
+ board_init_irq();
+}
diff --git a/arch/mips/au1000/common/power.c b/arch/mips/au1000/common/power.c
index 6f57f72a7d57..54047d69b820 100644
--- a/arch/mips/au1000/common/power.c
+++ b/arch/mips/au1000/common/power.c
@@ -403,9 +403,9 @@ static int pm_do_freq(ctl_table * ctl, int write, struct file *file,
}
- /* We don't want _any_ interrupts other than
- * match20. Otherwise our au1000_calibrate_delay()
- * calculation will be off, potentially a lot.
+ /*
+ * We don't want _any_ interrupts other than match20. Otherwise our
+ * au1000_calibrate_delay() calculation will be off, potentially a lot.
*/
intc0_mask = save_local_and_disable(0);
intc1_mask = save_local_and_disable(1);
@@ -414,6 +414,7 @@ static int pm_do_freq(ctl_table * ctl, int write, struct file *file,
au1000_calibrate_delay();
restore_local_and_enable(0, intc0_mask);
restore_local_and_enable(1, intc1_mask);
+
return retval;
}
diff --git a/arch/mips/au1000/common/prom.c b/arch/mips/au1000/common/prom.c
index a8637cdb5b4b..90d70695aa60 100644
--- a/arch/mips/au1000/common/prom.c
+++ b/arch/mips/au1000/common/prom.c
@@ -33,7 +33,6 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -41,18 +40,16 @@
#include <asm/bootinfo.h>
-/* #define DEBUG_CMDLINE */
-
-extern int prom_argc;
-extern char **prom_argv, **prom_envp;
-
+int prom_argc;
+char **prom_argv;
+char **prom_envp;
char * __init_or_module prom_getcmdline(void)
{
return &(arcs_cmdline[0]);
}
-void prom_init_cmdline(void)
+void prom_init_cmdline(void)
{
char *cp;
int actr;
@@ -61,7 +58,7 @@ void prom_init_cmdline(void)
cp = &(arcs_cmdline[0]);
while(actr < prom_argc) {
- strcpy(cp, prom_argv[actr]);
+ strcpy(cp, prom_argv[actr]);
cp += strlen(prom_argv[actr]);
*cp++ = ' ';
actr++;
@@ -70,10 +67,8 @@ void prom_init_cmdline(void)
--cp;
if (prom_argc > 1)
*cp = '\0';
-
}
-
char *prom_getenv(char *envname)
{
/*
@@ -95,21 +90,23 @@ char *prom_getenv(char *envname)
}
env++;
}
+
return NULL;
}
-inline unsigned char str2hexnum(unsigned char c)
+static inline unsigned char str2hexnum(unsigned char c)
{
- if(c >= '0' && c <= '9')
+ if (c >= '0' && c <= '9')
return c - '0';
- if(c >= 'a' && c <= 'f')
+ if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
- if(c >= 'A' && c <= 'F')
+ if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
+
return 0; /* foo */
}
-inline void str2eaddr(unsigned char *ea, unsigned char *str)
+static inline void str2eaddr(unsigned char *ea, unsigned char *str)
{
int i;
@@ -124,35 +121,29 @@ inline void str2eaddr(unsigned char *ea, unsigned char *str)
}
}
-int get_ethernet_addr(char *ethernet_addr)
+int prom_get_ethernet_addr(char *ethernet_addr)
{
- char *ethaddr_str;
+ char *ethaddr_str;
+ char *argptr;
- ethaddr_str = prom_getenv("ethaddr");
+ /* Check the environment variables first */
+ ethaddr_str = prom_getenv("ethaddr");
if (!ethaddr_str) {
- printk("ethaddr not set in boot prom\n");
- return -1;
- }
- str2eaddr(ethernet_addr, ethaddr_str);
-
-#if 0
- {
- int i;
+ /* Check command line */
+ argptr = prom_getcmdline();
+ ethaddr_str = strstr(argptr, "ethaddr=");
+ if (!ethaddr_str)
+ return -1;
- printk("get_ethernet_addr: ");
- for (i=0; i<5; i++)
- printk("%02x:", (unsigned char)*(ethernet_addr+i));
- printk("%02x\n", *(ethernet_addr+i));
+ ethaddr_str += strlen("ethaddr=");
}
-#endif
+
+ str2eaddr(ethernet_addr, ethaddr_str);
return 0;
}
+EXPORT_SYMBOL(prom_get_ethernet_addr);
void __init prom_free_prom_memory(void)
{
}
-
-EXPORT_SYMBOL(prom_getcmdline);
-EXPORT_SYMBOL(get_ethernet_addr);
-EXPORT_SYMBOL(str2eaddr);
diff --git a/arch/mips/au1000/common/setup.c b/arch/mips/au1000/common/setup.c
index b212c0726125..a90d425d4651 100644
--- a/arch/mips/au1000/common/setup.c
+++ b/arch/mips/au1000/common/setup.c
@@ -40,10 +40,11 @@
#include <asm/mipsregs.h>
#include <asm/reboot.h>
#include <asm/pgtable.h>
-#include <asm/mach-au1x00/au1000.h>
#include <asm/time.h>
-extern char * prom_getcmdline(void);
+#include <au1000.h>
+#include <prom.h>
+
extern void __init board_setup(void);
extern void au1000_restart(char *);
extern void au1000_halt(void);
diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c
index 2556399708ba..f113b512d7b1 100644
--- a/arch/mips/au1000/common/time.c
+++ b/arch/mips/au1000/common/time.c
@@ -67,7 +67,7 @@ static DEFINE_SPINLOCK(time_lock);
unsigned long wtimer;
#ifdef CONFIG_PM
-irqreturn_t counter0_irq(int irq, void *dev_id)
+static irqreturn_t counter0_irq(int irq, void *dev_id)
{
unsigned long pc0;
int time_elapsed;
@@ -117,6 +117,13 @@ irqreturn_t counter0_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
+struct irqaction counter0_action = {
+ .handler = counter0_irq,
+ .flags = IRQF_DISABLED,
+ .name = "alchemy-toy",
+ .dev_id = NULL,
+};
+
/* When we wakeup from sleep, we have to "catch up" on all of the
* timer ticks we have missed.
*/
@@ -221,7 +228,7 @@ unsigned long cal_r4koff(void)
return (cpu_speed / HZ);
}
-void __init plat_timer_setup(struct irqaction *irq)
+void __init plat_time_init(void)
{
unsigned int est_freq;
@@ -255,15 +262,10 @@ void __init plat_timer_setup(struct irqaction *irq)
* we do this.
*/
if (no_au1xxx_32khz) {
- unsigned int c0_status;
-
printk("WARNING: no 32KHz clock found.\n");
- /* Ensure we get CPO_COUNTER interrupts.
- */
- c0_status = read_c0_status();
- c0_status |= IE_IRQ5;
- write_c0_status(c0_status);
+ /* Ensure we get CPO_COUNTER interrupts. */
+ set_c0_status(IE_IRQ5);
}
else {
while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S);
@@ -280,7 +282,7 @@ void __init plat_timer_setup(struct irqaction *irq)
au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2);
au_sync();
while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20);
- startup_match20_interrupt(counter0_irq);
+ setup_irq(AU1000_TOY_MATCH2_INT, &counter0_action);
/* We can use the real 'wait' instruction.
*/
diff --git a/arch/mips/au1000/db1x00/init.c b/arch/mips/au1000/db1x00/init.c
index 4d7bcfc8cf73..43298fd9459c 100644
--- a/arch/mips/au1000/db1x00/init.c
+++ b/arch/mips/au1000/db1x00/init.c
@@ -31,15 +31,13 @@
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/bootmem.h>
-#include <asm/addrspace.h>
-#include <asm/bootinfo.h>
#include <linux/string.h>
#include <linux/kernel.h>
-int prom_argc;
-char **prom_argv, **prom_envp;
-extern void __init prom_init_cmdline(void);
-extern char *prom_getenv(char *envname);
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+
+#include <prom.h>
const char *get_system_type(void)
{
diff --git a/arch/mips/au1000/db1x00/irqmap.c b/arch/mips/au1000/db1x00/irqmap.c
index 3e5729145c2b..09cea03411b0 100644
--- a/arch/mips/au1000/db1x00/irqmap.c
+++ b/arch/mips/au1000/db1x00/irqmap.c
@@ -79,7 +79,7 @@ char irq_tab_alchemy[][5] __initdata = {
#endif
-au1xxx_irq_map_t __initdata au1xxx_irq_map[] = {
+struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
#ifndef CONFIG_MIPS_MIRAGE
#ifdef CONFIG_MIPS_DB1550
diff --git a/arch/mips/au1000/mtx-1/Makefile b/arch/mips/au1000/mtx-1/Makefile
index 764bf9f7e281..85a90941de4f 100644
--- a/arch/mips/au1000/mtx-1/Makefile
+++ b/arch/mips/au1000/mtx-1/Makefile
@@ -8,3 +8,6 @@
#
lib-y := init.o board_setup.o irqmap.o
+obj-y := platform.o
+
+EXTRA_CFLAGS += -Werror
diff --git a/arch/mips/au1000/mtx-1/init.c b/arch/mips/au1000/mtx-1/init.c
index 2aa7b2ed6a8c..cdeae3212a2d 100644
--- a/arch/mips/au1000/mtx-1/init.c
+++ b/arch/mips/au1000/mtx-1/init.c
@@ -34,13 +34,11 @@
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/bootmem.h>
+
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
-int prom_argc;
-char **prom_argv, **prom_envp;
-extern void __init prom_init_cmdline(void);
-extern char *prom_getenv(char *envname);
+#include <prom.h>
const char *get_system_type(void)
{
diff --git a/arch/mips/au1000/mtx-1/irqmap.c b/arch/mips/au1000/mtx-1/irqmap.c
index a4fa0f227e42..49c612aeddcf 100644
--- a/arch/mips/au1000/mtx-1/irqmap.c
+++ b/arch/mips/au1000/mtx-1/irqmap.c
@@ -58,7 +58,7 @@ char irq_tab_alchemy[][5] __initdata = {
[7] = { -1, INTD, INTC, INTX, INTX}, /* IDSEL 07 - AdapterD-Slot1 (bottom) */
};
-au1xxx_irq_map_t __initdata au1xxx_irq_map[] = {
+struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
{ AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0},
{ AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
{ AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 },
diff --git a/arch/mips/au1000/mtx-1/platform.c b/arch/mips/au1000/mtx-1/platform.c
new file mode 100644
index 000000000000..49c0fb409fea
--- /dev/null
+++ b/arch/mips/au1000/mtx-1/platform.c
@@ -0,0 +1,77 @@
+/*
+ * MTX-1 platform devices registration
+ *
+ * Copyright (C) 2007, Florian Fainelli <florian@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+
+#include <asm/gpio.h>
+
+static struct resource mtx1_wdt_res[] = {
+ [0] = {
+ .start = 15,
+ .end = 15,
+ .name = "mtx1-wdt-gpio",
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device mtx1_wdt = {
+ .name = "mtx1-wdt",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(mtx1_wdt_res),
+ .resource = mtx1_wdt_res,
+};
+
+static struct gpio_led default_leds[] = {
+ {
+ .name = "mtx1:green",
+ .gpio = 211,
+ }, {
+ .name = "mtx1:red",
+ .gpio = 212,
+ },
+};
+
+static struct gpio_led_platform_data mtx1_led_data = {
+ .num_leds = ARRAY_SIZE(default_leds),
+ .leds = default_leds,
+};
+
+static struct platform_device mtx1_gpio_leds = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &mtx1_led_data,
+ }
+};
+
+static struct __initdata platform_device * mtx1_devs[] = {
+ &mtx1_gpio_leds,
+ &mtx1_wdt
+};
+
+static int __init mtx1_register_devices(void)
+{
+ return platform_add_devices(mtx1_devs, ARRAY_SIZE(mtx1_devs));
+}
+
+arch_initcall(mtx1_register_devices);
diff --git a/arch/mips/au1000/pb1000/init.c b/arch/mips/au1000/pb1000/init.c
index 4535f7208e18..ddccaf6997d0 100644
--- a/arch/mips/au1000/pb1000/init.c
+++ b/arch/mips/au1000/pb1000/init.c
@@ -30,15 +30,13 @@
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/bootmem.h>
-#include <asm/addrspace.h>
-#include <asm/bootinfo.h>
#include <linux/string.h>
#include <linux/kernel.h>
-int prom_argc;
-char **prom_argv, **prom_envp;
-extern void __init prom_init_cmdline(void);
-extern char *prom_getenv(char *envname);
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+
+#include <prom.h>
const char *get_system_type(void)
{
diff --git a/arch/mips/au1000/pb1000/irqmap.c b/arch/mips/au1000/pb1000/irqmap.c
index 156500ba467f..88e354508204 100644
--- a/arch/mips/au1000/pb1000/irqmap.c
+++ b/arch/mips/au1000/pb1000/irqmap.c
@@ -47,7 +47,7 @@
#include <asm/system.h>
#include <asm/mach-au1x00/au1000.h>
-au1xxx_irq_map_t __initdata au1xxx_irq_map[] = {
+struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
{ AU1000_GPIO_15, INTC_INT_LOW_LEVEL, 0 },
};
diff --git a/arch/mips/au1000/pb1100/init.c b/arch/mips/au1000/pb1100/init.c
index 7ba6852de7cd..c93fd39b4aba 100644
--- a/arch/mips/au1000/pb1100/init.c
+++ b/arch/mips/au1000/pb1100/init.c
@@ -31,15 +31,13 @@
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/bootmem.h>
-#include <asm/addrspace.h>
-#include <asm/bootinfo.h>
#include <linux/string.h>
#include <linux/kernel.h>
-int prom_argc;
-char **prom_argv, **prom_envp;
-extern void __init prom_init_cmdline(void);
-extern char *prom_getenv(char *envname);
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+
+#include <prom.h>
const char *get_system_type(void)
{
diff --git a/arch/mips/au1000/pb1100/irqmap.c b/arch/mips/au1000/pb1100/irqmap.c
index d986916221b7..880456bf8c11 100644
--- a/arch/mips/au1000/pb1100/irqmap.c
+++ b/arch/mips/au1000/pb1100/irqmap.c
@@ -47,7 +47,7 @@
#include <asm/system.h>
#include <asm/mach-au1x00/au1000.h>
-au1xxx_irq_map_t __initdata au1xxx_irq_map[] = {
+struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
{ AU1000_GPIO_9, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card Fully_Interted#
{ AU1000_GPIO_10, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card STSCHG#
{ AU1000_GPIO_11, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card IRQ#
diff --git a/arch/mips/au1000/pb1200/Makefile b/arch/mips/au1000/pb1200/Makefile
index 22b673cf55af..970b1b1d5cda 100644
--- a/arch/mips/au1000/pb1200/Makefile
+++ b/arch/mips/au1000/pb1200/Makefile
@@ -3,3 +3,5 @@
#
lib-y := init.o board_setup.o irqmap.o
+
+EXTRA_CFLAGS += -Werror
diff --git a/arch/mips/au1000/pb1200/board_setup.c b/arch/mips/au1000/pb1200/board_setup.c
index 2122515f79d7..b98bebfa87c6 100644
--- a/arch/mips/au1000/pb1200/board_setup.c
+++ b/arch/mips/au1000/pb1200/board_setup.c
@@ -41,8 +41,10 @@
#include <asm/mipsregs.h>
#include <asm/reboot.h>
#include <asm/pgtable.h>
-#include <asm/mach-au1x00/au1000.h>
-#include <asm/mach-au1x00/au1xxx_dbdma.h>
+
+#include <au1000.h>
+#include <au1xxx_dbdma.h>
+#include <prom.h>
#ifdef CONFIG_MIPS_PB1200
#include <asm/mach-pb1x00/pb1200.h>
@@ -66,9 +68,11 @@ void board_reset(void)
void __init board_setup(void)
{
char *argptr = NULL;
- u32 pin_func;
#if 0
+ {
+ u32 pin_func;
+
/* Enable PSC1 SYNC for AC97. Normaly done in audio driver,
* but it is board specific code, so put it here.
*/
@@ -79,11 +83,13 @@ void __init board_setup(void)
au_writel(0, (u32)bcsr|0x10); /* turn off pcmcia power */
au_sync();
+ }
#endif
#if defined(CONFIG_I2C_AU1550)
{
u32 freq0, clksrc;
+ u32 pin_func;
/* Select SMBUS in CPLD */
bcsr->resets &= ~(BCSR_RESETS_PCS0MUX);
diff --git a/arch/mips/au1000/pb1200/init.c b/arch/mips/au1000/pb1200/init.c
index 5a70029d5388..c251570749ee 100644
--- a/arch/mips/au1000/pb1200/init.c
+++ b/arch/mips/au1000/pb1200/init.c
@@ -31,15 +31,13 @@
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/bootmem.h>
-#include <asm/addrspace.h>
-#include <asm/bootinfo.h>
#include <linux/string.h>
#include <linux/kernel.h>
-int prom_argc;
-char **prom_argv, **prom_envp;
-extern void __init prom_init_cmdline(void);
-extern char *prom_getenv(char *envname);
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+
+#include <prom.h>
const char *get_system_type(void)
{
diff --git a/arch/mips/au1000/pb1200/irqmap.c b/arch/mips/au1000/pb1200/irqmap.c
index 7c708db04a88..c096be4ed4e7 100644
--- a/arch/mips/au1000/pb1200/irqmap.c
+++ b/arch/mips/au1000/pb1200/irqmap.c
@@ -36,8 +36,8 @@
#include <linux/slab.h>
#include <linux/random.h>
#include <linux/delay.h>
+#include <linux/bitops.h>
-#include <asm/bitops.h>
#include <asm/bootinfo.h>
#include <asm/io.h>
#include <asm/mipsregs.h>
@@ -54,7 +54,7 @@
#define PB1200_INT_END DB1200_INT_END
#endif
-au1xxx_irq_map_t __initdata au1xxx_irq_map[] = {
+struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
{ AU1000_GPIO_7, INTC_INT_LOW_LEVEL, 0 }, // This is exteranl interrupt cascade
};
@@ -74,7 +74,7 @@ irqreturn_t pb1200_cascade_handler( int irq, void *dev_id)
bcsr->int_status = bisr;
for( ; bisr; bisr &= (bisr-1) )
{
- extirq_nr = (PB1200_INT_BEGIN-1) + au_ffs(bisr);
+ extirq_nr = PB1200_INT_BEGIN + ffs(bisr);
/* Ack and dispatch IRQ */
do_IRQ(extirq_nr);
}
@@ -94,51 +94,41 @@ inline void pb1200_disable_irq(unsigned int irq_nr)
bcsr->intclr = 1<<(irq_nr - PB1200_INT_BEGIN);
}
-static unsigned int pb1200_startup_irq( unsigned int irq_nr )
+static unsigned int pb1200_setup_cascade(void)
{
- if (++pb1200_cascade_en == 1)
- {
- request_irq(AU1000_GPIO_7, &pb1200_cascade_handler,
- 0, "Pb1200 Cascade", (void *)&pb1200_cascade_handler );
-#ifdef CONFIG_MIPS_PB1200
- /* We have a problem with CPLD rev3. Enable a workaround */
- if( ((bcsr->whoami & BCSR_WHOAMI_CPLD)>>4) <= 3)
- {
- printk("\nWARNING!!!\n");
- printk("\nWARNING!!!\n");
- printk("\nWARNING!!!\n");
- printk("\nWARNING!!!\n");
- printk("\nWARNING!!!\n");
- printk("\nWARNING!!!\n");
- printk("Pb1200 must be at CPLD rev4. Please have Pb1200\n");
- printk("updated to latest revision. This software will not\n");
- printk("work on anything less than CPLD rev4\n");
- printk("\nWARNING!!!\n");
- printk("\nWARNING!!!\n");
- printk("\nWARNING!!!\n");
- printk("\nWARNING!!!\n");
- printk("\nWARNING!!!\n");
- printk("\nWARNING!!!\n");
- while(1);
- }
-#endif
- }
- pb1200_enable_irq(irq_nr);
+ int err;
+
+ err = request_irq(AU1000_GPIO_7, &pb1200_cascade_handler,
+ 0, "Pb1200 Cascade", &pb1200_cascade_handler);
+ if (err)
+ return err;
+
return 0;
}
-static void pb1200_shutdown_irq( unsigned int irq_nr )
+static unsigned int pb1200_startup_irq(unsigned int irq)
{
- pb1200_disable_irq(irq_nr);
- if (--pb1200_cascade_en == 0)
- {
- free_irq(AU1000_GPIO_7, &pb1200_cascade_handler );
+ if (++pb1200_cascade_en == 1) {
+ int res;
+
+ res = pb1200_setup_cascade();
+ if (res)
+ return res;
}
- return;
+
+ pb1200_enable_irq(irq);
+
+ return 0;
}
-static struct irq_chip external_irq_type =
+static void pb1200_shutdown_irq(unsigned int irq)
{
+ pb1200_disable_irq(irq);
+ if (--pb1200_cascade_en == 0)
+ free_irq(AU1000_GPIO_7, &pb1200_cascade_handler);
+}
+
+static struct irq_chip external_irq_type = {
#ifdef CONFIG_MIPS_PB1200
.name = "Pb1200 Ext",
#endif
@@ -155,16 +145,38 @@ static struct irq_chip external_irq_type =
void _board_init_irq(void)
{
- int irq_nr;
+ unsigned int irq;
- for (irq_nr = PB1200_INT_BEGIN; irq_nr <= PB1200_INT_END; irq_nr++)
- {
- set_irq_chip_and_handler(irq_nr, &external_irq_type,
+#ifdef CONFIG_MIPS_PB1200
+ /* We have a problem with CPLD rev3. Enable a workaround */
+ if (((bcsr->whoami & BCSR_WHOAMI_CPLD) >> 4) <= 3) {
+ printk("\nWARNING!!!\n");
+ printk("\nWARNING!!!\n");
+ printk("\nWARNING!!!\n");
+ printk("\nWARNING!!!\n");
+ printk("\nWARNING!!!\n");
+ printk("\nWARNING!!!\n");
+ printk("Pb1200 must be at CPLD rev4. Please have Pb1200\n");
+ printk("updated to latest revision. This software will not\n");
+ printk("work on anything less than CPLD rev4\n");
+ printk("\nWARNING!!!\n");
+ printk("\nWARNING!!!\n");
+ printk("\nWARNING!!!\n");
+ printk("\nWARNING!!!\n");
+ printk("\nWARNING!!!\n");
+ printk("\nWARNING!!!\n");
+ panic("Game over. Your score is 0.");
+ }
+#endif
+
+ for (irq = PB1200_INT_BEGIN; irq <= PB1200_INT_END; irq++) {
+ set_irq_chip_and_handler(irq, &external_irq_type,
handle_level_irq);
- pb1200_disable_irq(irq_nr);
+ pb1200_disable_irq(irq);
}
- /* GPIO_7 can not be hooked here, so it is hooked upon first
- request of any source attached to the cascade */
+ /*
+ * GPIO_7 can not be hooked here, so it is hooked upon first
+ * request of any source attached to the cascade
+ */
}
-
diff --git a/arch/mips/au1000/pb1500/init.c b/arch/mips/au1000/pb1500/init.c
index e58a9d6c5021..507d4b204161 100644
--- a/arch/mips/au1000/pb1500/init.c
+++ b/arch/mips/au1000/pb1500/init.c
@@ -31,15 +31,13 @@
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/bootmem.h>
-#include <asm/addrspace.h>
-#include <asm/bootinfo.h>
#include <linux/string.h>
#include <linux/kernel.h>
-int prom_argc;
-char **prom_argv, **prom_envp;
-extern void __init prom_init_cmdline(void);
-extern char *prom_getenv(char *envname);
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+
+#include <prom.h>
const char *get_system_type(void)
{
diff --git a/arch/mips/au1000/pb1500/irqmap.c b/arch/mips/au1000/pb1500/irqmap.c
index 409d1612bb63..810f695e24bb 100644
--- a/arch/mips/au1000/pb1500/irqmap.c
+++ b/arch/mips/au1000/pb1500/irqmap.c
@@ -52,7 +52,7 @@ char irq_tab_alchemy[][5] __initdata = {
[13] = { -1, INTA, INTB, INTC, INTD}, /* IDSEL 13 - PCI slot */
};
-au1xxx_irq_map_t __initdata au1xxx_irq_map[] = {
+struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
{ AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0},
{ AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
{ AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 },
diff --git a/arch/mips/au1000/pb1550/init.c b/arch/mips/au1000/pb1550/init.c
index fad53bf5aad1..b03eee601e36 100644
--- a/arch/mips/au1000/pb1550/init.c
+++ b/arch/mips/au1000/pb1550/init.c
@@ -31,15 +31,13 @@
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/bootmem.h>
-#include <asm/addrspace.h>
-#include <asm/bootinfo.h>
#include <linux/string.h>
#include <linux/kernel.h>
-int prom_argc;
-char **prom_argv, **prom_envp;
-extern void __init prom_init_cmdline(void);
-extern char *prom_getenv(char *envname);
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+
+#include <prom.h>
const char *get_system_type(void)
{
diff --git a/arch/mips/au1000/pb1550/irqmap.c b/arch/mips/au1000/pb1550/irqmap.c
index 24a9d186cf5a..56becab28e5d 100644
--- a/arch/mips/au1000/pb1550/irqmap.c
+++ b/arch/mips/au1000/pb1550/irqmap.c
@@ -52,7 +52,7 @@ char irq_tab_alchemy[][5] __initdata = {
[13] = { -1, INTA, INTB, INTC, INTD}, /* IDSEL 13 - PCI slot 1 (right) */
};
-au1xxx_irq_map_t __initdata au1xxx_irq_map[] = {
+struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
{ AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 },
{ AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 },
};
diff --git a/arch/mips/au1000/xxs1500/init.c b/arch/mips/au1000/xxs1500/init.c
index 9f839c36f69e..6532939f377a 100644
--- a/arch/mips/au1000/xxs1500/init.c
+++ b/arch/mips/au1000/xxs1500/init.c
@@ -30,15 +30,13 @@
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/bootmem.h>
-#include <asm/addrspace.h>
-#include <asm/bootinfo.h>
#include <linux/string.h>
#include <linux/kernel.h>
-int prom_argc;
-char **prom_argv, **prom_envp;
-extern void __init prom_init_cmdline(void);
-extern char *prom_getenv(char *envname);
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+
+#include <prom.h>
const char *get_system_type(void)
{
diff --git a/arch/mips/au1000/xxs1500/irqmap.c b/arch/mips/au1000/xxs1500/irqmap.c
index 3844c6429e27..389349295d70 100644
--- a/arch/mips/au1000/xxs1500/irqmap.c
+++ b/arch/mips/au1000/xxs1500/irqmap.c
@@ -47,7 +47,7 @@
#include <asm/system.h>
#include <asm/au1000.h>
-au1xxx_irq_map_t __initdata au1xxx_irq_map[] = {
+struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
{ AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0},
{ AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
{ AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 },
diff --git a/arch/mips/basler/excite/excite_irq.c b/arch/mips/basler/excite/excite_irq.c
index 1ecab6350421..4903e067916b 100644
--- a/arch/mips/basler/excite/excite_irq.c
+++ b/arch/mips/basler/excite/excite_irq.c
@@ -29,7 +29,7 @@
#include <linux/timex.h>
#include <linux/slab.h>
#include <linux/random.h>
-#include <asm/bitops.h>
+#include <linux/bitops.h>
#include <asm/bootinfo.h>
#include <asm/io.h>
#include <asm/irq.h>
diff --git a/arch/mips/basler/excite/excite_setup.c b/arch/mips/basler/excite/excite_setup.c
index 404ca9284b30..6dd8f0d46d09 100644
--- a/arch/mips/basler/excite/excite_setup.c
+++ b/arch/mips/basler/excite/excite_setup.c
@@ -68,24 +68,23 @@ DEFINE_SPINLOCK(titan_lock);
int titan_irqflags;
+/*
+ * The eXcite platform uses the alternate timer interrupt
+ *
+ * Fixme: At the time of this writing cevt-r4k.c doesn't yet know about how
+ * to handle the alternate timer interrupt of the RM9000.
+ */
void __init plat_time_init(void)
{
const u32 modebit5 = ocd_readl(0x00e4);
- unsigned int
- mult = ((modebit5 >> 11) & 0x1f) + 2,
- div = ((modebit5 >> 16) & 0x1f) + 2;
+ unsigned int mult = ((modebit5 >> 11) & 0x1f) + 2;
+ unsigned int div = ((modebit5 >> 16) & 0x1f) + 2;
- if (div == 33) div = 1;
+ if (div == 33)
+ div = 1;
mips_hpt_frequency = EXCITE_CPU_EXT_CLOCK * mult / div / 2;
}
-void __init plat_timer_setup(struct irqaction *irq)
-{
- /* The eXcite platform uses the alternate timer interrupt */
- set_c0_intcontrol(0x80);
- setup_irq(TIMER_IRQ, irq);
-}
-
static int __init excite_init_console(void)
{
#if defined(CONFIG_SERIAL_8250)
diff --git a/arch/mips/bcm47xx/time.c b/arch/mips/bcm47xx/time.c
index 0ab4676c8bd3..0c6f47b3fd94 100644
--- a/arch/mips/bcm47xx/time.c
+++ b/arch/mips/bcm47xx/time.c
@@ -46,10 +46,3 @@ void __init plat_time_init(void)
/* Set MIPS counter frequency for fixed_rate_gettimeoffset() */
mips_hpt_frequency = hz;
}
-
-void __init
-plat_timer_setup(struct irqaction *irq)
-{
- /* Enable the timer interrupt */
- setup_irq(7, irq);
-}
diff --git a/arch/mips/cobalt/Makefile b/arch/mips/cobalt/Makefile
index 6b83f4ddc8fc..d73833b7c781 100644
--- a/arch/mips/cobalt/Makefile
+++ b/arch/mips/cobalt/Makefile
@@ -2,7 +2,7 @@
# Makefile for the Cobalt micro systems family specific parts of the kernel
#
-obj-y := buttons.o irq.o led.o reset.o rtc.o serial.o setup.o
+obj-y := buttons.o irq.o led.o reset.o rtc.o serial.o setup.o time.o
obj-$(CONFIG_PCI) += pci.o
obj-$(CONFIG_EARLY_PRINTK) += console.o
diff --git a/arch/mips/cobalt/setup.c b/arch/mips/cobalt/setup.c
index d11bb1bc7b6b..dd23beb8604f 100644
--- a/arch/mips/cobalt/setup.c
+++ b/arch/mips/cobalt/setup.c
@@ -9,19 +9,17 @@
* Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv)
*
*/
-#include <linux/interrupt.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
#include <linux/pm.h>
#include <asm/bootinfo.h>
-#include <asm/time.h>
-#include <asm/i8253.h>
-#include <asm/io.h>
#include <asm/reboot.h>
#include <asm/gt64120.h>
#include <cobalt.h>
-#include <irq.h>
extern void cobalt_machine_restart(char *command);
extern void cobalt_machine_halt(void);
@@ -41,17 +39,6 @@ const char *get_system_type(void)
return "MIPS Cobalt";
}
-void __init plat_timer_setup(struct irqaction *irq)
-{
- /* Load timer value for HZ (TCLK is 50MHz) */
- GT_WRITE(GT_TC0_OFS, 50*1000*1000 / HZ);
-
- /* Enable timer0 */
- GT_WRITE(GT_TC_CONTROL_OFS, GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK);
-
- setup_irq(GT641XX_TIMER0_IRQ, irq);
-}
-
/*
* Cobalt doesn't have PS/2 keyboard/mouse interfaces,
* keyboard conntroller is never used.
@@ -84,11 +71,6 @@ static struct resource cobalt_reserved_resources[] = {
},
};
-void __init plat_time_init(void)
-{
- setup_pit_timer();
-}
-
void __init plat_mem_setup(void)
{
int i;
diff --git a/arch/mips/cobalt/time.c b/arch/mips/cobalt/time.c
new file mode 100644
index 000000000000..fa819fccd5db
--- /dev/null
+++ b/arch/mips/cobalt/time.c
@@ -0,0 +1,35 @@
+/*
+ * Cobalt time initialization.
+ *
+ * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <linux/init.h>
+
+#include <asm/gt64120.h>
+#include <asm/i8253.h>
+#include <asm/time.h>
+
+#define GT641XX_BASE_CLOCK 50000000 /* 50MHz */
+
+void __init plat_time_init(void)
+{
+ setup_pit_timer();
+
+ gt641xx_set_base_clock(GT641XX_BASE_CLOCK);
+
+ mips_timer_state = gt641xx_timer0_state;
+}
diff --git a/arch/mips/configs/db1000_defconfig b/arch/mips/configs/db1000_defconfig
index 885b633647e9..5a8b7acb7dd7 100644
--- a/arch/mips/configs/db1000_defconfig
+++ b/arch/mips/configs/db1000_defconfig
@@ -738,7 +738,6 @@ CONFIG_HW_CONSOLE=y
CONFIG_VT_HW_CONSOLE_BINDING=y
# CONFIG_SERIAL_NONSTANDARD is not set
# CONFIG_AU1X00_GPIO is not set
-# CONFIG_TS_AU1X00_ADS7846 is not set
#
# Serial drivers
diff --git a/arch/mips/configs/db1100_defconfig b/arch/mips/configs/db1100_defconfig
index e3c3a07e8a7c..d4ed90bca269 100644
--- a/arch/mips/configs/db1100_defconfig
+++ b/arch/mips/configs/db1100_defconfig
@@ -714,7 +714,6 @@ CONFIG_HW_CONSOLE=y
CONFIG_VT_HW_CONSOLE_BINDING=y
# CONFIG_SERIAL_NONSTANDARD is not set
# CONFIG_AU1X00_GPIO is not set
-# CONFIG_TS_AU1X00_ADS7846 is not set
#
# Serial drivers
diff --git a/arch/mips/configs/db1200_defconfig b/arch/mips/configs/db1200_defconfig
index 9aa7c3ebfa3f..a055657e6983 100644
--- a/arch/mips/configs/db1200_defconfig
+++ b/arch/mips/configs/db1200_defconfig
@@ -775,7 +775,6 @@ CONFIG_HW_CONSOLE=y
CONFIG_VT_HW_CONSOLE_BINDING=y
# CONFIG_SERIAL_NONSTANDARD is not set
# CONFIG_AU1X00_GPIO is not set
-# CONFIG_TS_AU1X00_ADS7846 is not set
#
# Serial drivers
diff --git a/arch/mips/configs/db1500_defconfig b/arch/mips/configs/db1500_defconfig
index 99240668bca1..0ad08cf446ec 100644
--- a/arch/mips/configs/db1500_defconfig
+++ b/arch/mips/configs/db1500_defconfig
@@ -811,7 +811,6 @@ CONFIG_SERIO_RAW=m
# CONFIG_VT is not set
# CONFIG_SERIAL_NONSTANDARD is not set
# CONFIG_AU1X00_GPIO is not set
-# CONFIG_TS_AU1X00_ADS7846 is not set
#
# Serial drivers
diff --git a/arch/mips/configs/db1550_defconfig b/arch/mips/configs/db1550_defconfig
index 19992f76c60d..057c7d429c80 100644
--- a/arch/mips/configs/db1550_defconfig
+++ b/arch/mips/configs/db1550_defconfig
@@ -856,7 +856,6 @@ CONFIG_SERIO_RAW=m
# CONFIG_VT is not set
# CONFIG_SERIAL_NONSTANDARD is not set
# CONFIG_AU1X00_GPIO is not set
-# CONFIG_TS_AU1X00_ADS7846 is not set
#
# Serial drivers
diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig
index 49bcc58929ba..892d4c38fd0d 100644
--- a/arch/mips/configs/ip27_defconfig
+++ b/arch/mips/configs/ip27_defconfig
@@ -175,6 +175,7 @@ CONFIG_POSIX_MQUEUE=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=15
+CONFIG_CGROUPS=y
CONFIG_CPUSETS=y
CONFIG_SYSFS_DEPRECATED=y
CONFIG_RELAY=y
diff --git a/arch/mips/configs/mipssim_defconfig b/arch/mips/configs/mipssim_defconfig
index 86dcb7464353..61b72f5a953e 100644
--- a/arch/mips/configs/mipssim_defconfig
+++ b/arch/mips/configs/mipssim_defconfig
@@ -1,71 +1,68 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Tue Feb 20 21:47:35 2007
+# Linux kernel version: 2.6.23
+# Thu Oct 18 22:45:52 2007
#
CONFIG_MIPS=y
#
# Machine selection
#
-CONFIG_ZONE_DMA=y
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_PB1200 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_DB1200 is not set
-# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MACH_ALCHEMY is not set
# CONFIG_BASLER_EXCITE is not set
+# CONFIG_BCM47XX is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_LEMOTE_FULONG is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
-# CONFIG_WR_PPMC is not set
CONFIG_MIPS_SIM=y
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_MARKEINS is not set
+# CONFIG_MACH_VR41XX is not set
# CONFIG_PNX8550_JBS is not set
# CONFIG_PNX8550_STB810 is not set
-# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_MSP is not set
# CONFIG_PMC_YOSEMITE is not set
# CONFIG_QEMU is not set
-# CONFIG_MARKEINS is not set
# CONFIG_SGI_IP22 is not set
# CONFIG_SGI_IP27 is not set
# CONFIG_SGI_IP32 is not set
-# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SIBYTE_RHONE is not set
# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_SENTOSA is not set
-# CONFIG_SIBYTE_RHONE is not set
-# CONFIG_SIBYTE_CARMEL is not set
# CONFIG_SIBYTE_PTSWARM is not set
-# CONFIG_SIBYTE_LITTLESUR is not set
-# CONFIG_SIBYTE_CRHINE is not set
-# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SIBYTE_BIGSUR is not set
# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
+# CONFIG_WR_PPMC is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
+CONFIG_BOOT_RAW=y
+CONFIG_CEVT_R4K=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_SYS_HAS_EARLY_PRINTK=y
+# CONFIG_HOTPLUG_CPU is not set
+# CONFIG_NO_IOPORT is not set
# CONFIG_CPU_BIG_ENDIAN is not set
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
@@ -76,6 +73,11 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
#
# CPU selection
#
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_CPU_LOONGSON2 is not set
CONFIG_CPU_MIPS32_R1=y
# CONFIG_CPU_MIPS32_R2 is not set
# CONFIG_CPU_MIPS64_R1 is not set
@@ -115,8 +117,8 @@ CONFIG_CPU_HAS_PREFETCH=y
CONFIG_MIPS_MT_DISABLED=y
# CONFIG_MIPS_MT_SMP is not set
# CONFIG_MIPS_MT_SMTC is not set
+CONFIG_SYS_SUPPORTS_MULTITHREADING=y
# CONFIG_MIPS_VPE_LOADER is not set
-# CONFIG_64BIT_PHYS_ADDR is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
@@ -130,50 +132,52 @@ CONFIG_FLATMEM_MANUAL=y
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
# CONFIG_HZ_48 is not set
-# CONFIG_HZ_100 is not set
+CONFIG_HZ_100=y
# CONFIG_HZ_128 is not set
# CONFIG_HZ_250 is not set
# CONFIG_HZ_256 is not set
-CONFIG_HZ_1000=y
+# CONFIG_HZ_1000 is not set
# CONFIG_HZ_1024 is not set
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_HZ=1000
+CONFIG_HZ=100
CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
# CONFIG_KEXEC is not set
+# CONFIG_SECCOMP is not set
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
-# Code maturity level options
+# General setup
#
CONFIG_EXPERIMENTAL=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
+# CONFIG_SWAP is not set
CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
+# CONFIG_USER_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_FAIR_USER_SCHED=y
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
@@ -187,31 +191,29 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
-
-#
-# Loadable module support
-#
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
-
-#
-# Block layer
-#
CONFIG_BLOCK=y
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
#
# IO Schedulers
@@ -229,18 +231,11 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
# Bus options (PCI, PCMCIA, EISA, ISA, TC)
#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_MMU=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
# CONFIG_PCCARD is not set
#
-# PCI Hotplug Support
-#
-
-#
# Executable file formats
#
CONFIG_BINFMT_ELF=y
@@ -250,9 +245,8 @@ CONFIG_TRAD_SIGNALS=y
#
# Power management options
#
-CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
-# CONFIG_PM_DEBUG is not set
+# CONFIG_PM is not set
+CONFIG_SUSPEND_UP_POSSIBLE=y
#
# Networking
@@ -262,75 +256,50 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
-CONFIG_XFRM=y
-# CONFIG_XFRM_USER is not set
-# CONFIG_XFRM_SUB_POLICY is not set
-CONFIG_XFRM_MIGRATE=y
-CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
+# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_ASK_IP_FIB_HASH=y
# CONFIG_IP_FIB_TRIE is not set
CONFIG_IP_FIB_HASH=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_MULTIPATH=y
-# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
-CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_MULTIPLE_TABLES is not set
+# CONFIG_IP_ROUTE_MULTIPATH is not set
+# CONFIG_IP_ROUTE_VERBOSE is not set
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
# CONFIG_IP_PNP_RARP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
-CONFIG_IP_MROUTE=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
+# CONFIG_IP_MROUTE is not set
# CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
+# CONFIG_SYN_COOKIES is not set
# 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=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
CONFIG_INET_DIAG=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=y
+# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
-CONFIG_NETWORK_SECMARK=y
+# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IP_SCTP=m
-# CONFIG_SCTP_DBG_MSG is not set
-# CONFIG_SCTP_DBG_OBJCNT is not set
-# CONFIG_SCTP_HMAC_NONE is not set
-# CONFIG_SCTP_HMAC_SHA1 is not set
-CONFIG_SCTP_HMAC_MD5=y
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
+# CONFIG_IP_SCTP is not set
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -347,44 +316,7 @@ CONFIG_SCTP_HMAC_MD5=y
#
# QoS and/or fair queueing
#
-CONFIG_NET_SCHED=y
-CONFIG_NET_SCH_FIFO=y
-CONFIG_NET_SCH_CLK_JIFFIES=y
-# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
-# CONFIG_NET_SCH_CLK_CPU is not set
-
-#
-# Queueing/Scheduling
-#
-CONFIG_NET_SCH_CBQ=m
-CONFIG_NET_SCH_HTB=m
-CONFIG_NET_SCH_HFSC=m
-CONFIG_NET_SCH_PRIO=m
-CONFIG_NET_SCH_RED=m
-CONFIG_NET_SCH_SFQ=m
-CONFIG_NET_SCH_TEQL=m
-CONFIG_NET_SCH_TBF=m
-CONFIG_NET_SCH_GRED=m
-CONFIG_NET_SCH_DSMARK=m
-CONFIG_NET_SCH_NETEM=m
-CONFIG_NET_SCH_INGRESS=m
-
-#
-# Classification
-#
-CONFIG_NET_CLS=y
-CONFIG_NET_CLS_BASIC=m
-CONFIG_NET_CLS_TCINDEX=m
-CONFIG_NET_CLS_ROUTE4=m
-CONFIG_NET_CLS_ROUTE=y
-# CONFIG_NET_CLS_FW is not set
-# CONFIG_NET_CLS_U32 is not set
-# CONFIG_NET_CLS_RSVP is not set
-# CONFIG_NET_CLS_RSVP6 is not set
-# CONFIG_NET_EMATCH is not set
-# CONFIG_NET_CLS_ACT is not set
-# CONFIG_NET_CLS_POLICE is not set
-CONFIG_NET_ESTIMATOR=y
+# CONFIG_NET_SCHED is not set
#
# Network testing
@@ -393,8 +325,17 @@ CONFIG_NET_ESTIMATOR=y
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
-CONFIG_FIB_RULES=y
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
#
# Device Drivers
@@ -403,52 +344,25 @@ CONFIG_FIB_RULES=y
#
# Generic Driver Options
#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
# CONFIG_STANDALONE is not set
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
# CONFIG_FW_LOADER is not set
# CONFIG_DEBUG_DRIVER is not set
# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNPACPI is not set
-
-#
-# Block devices
-#
+CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
CONFIG_BLK_DEV_NBD=y
# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
-
-#
-# Misc devices
-#
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_MISC_DEVICES is not set
# CONFIG_IDE is not set
#
@@ -456,48 +370,29 @@ CONFIG_BLK_DEV_NBD=y
#
# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
# CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
-# Network device support
-#
CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
# CONFIG_DUMMY is not set
# 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_PHYLIB is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
CONFIG_NET_ETHERNET=y
# CONFIG_MII is not set
+# CONFIG_AX88796 is not set
CONFIG_MIPS_SIM_NET=y
# CONFIG_DM9000 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_B44 is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
@@ -513,49 +408,18 @@ CONFIG_MIPS_SIM_NET=y
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
# CONFIG_PHONE is not set
#
# Input device support
#
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
+# CONFIG_INPUT is not set
#
# Hardware I/O ports
#
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO is not set
# CONFIG_GAMEPORT is not set
#
@@ -581,31 +445,13 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
# CONFIG_I2C is not set
#
@@ -613,118 +459,60 @@ CONFIG_LEGACY_PTY_COUNT=256
#
# CONFIG_SPI is not set
# CONFIG_SPI_MASTER is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
#
-# Dallas's 1-wire bus
+# Sonics Silicon Backplane
#
-# CONFIG_W1 is not set
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
#
-# Hardware Monitoring support
+# Multifunction device drivers
#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+# CONFIG_MFD_SM501 is not set
#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
#
# Graphics support
#
-# CONFIG_FIRMWARE_EDID 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
#
-# Sound
+# Display device support
#
-# CONFIG_SOUND is not set
+# CONFIG_DISPLAY_SUPPORT is not set
#
-# HID Devices
-#
-# CONFIG_HID is not set
-
-#
-# USB support
-#
-# CONFIG_USB_ARCH_HAS_HCD is not set
-# CONFIG_USB_ARCH_HAS_OHCI is not set
-# CONFIG_USB_ARCH_HAS_EHCI is not set
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
+# Sound
#
+# CONFIG_SOUND is not set
+# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
-
-#
-# LED devices
-#
# CONFIG_NEW_LEDS is not set
-
-#
-# LED drivers
-#
-
-#
-# LED Triggers
-#
-
-#
-# InfiniBand support
-#
-
-#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
-#
-
-#
-# Real Time Clock
-#
+CONFIG_RTC_LIB=y
# CONFIG_RTC_CLASS is not set
#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
+# Userspace I/O
#
+# CONFIG_UIO is not set
#
# File systems
#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT2_FS is not set
# CONFIG_EXT3_FS is not set
# CONFIG_EXT4DEV_FS is not set
# CONFIG_REISERFS_FS is not set
@@ -732,6 +520,7 @@ CONFIG_EXT2_FS=y
# CONFIG_FS_POSIX_ACL is not set
# CONFIG_XFS_FS is not set
# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
CONFIG_ROMFS_FS=y
# CONFIG_INOTIFY is not set
@@ -760,10 +549,11 @@ CONFIG_ROMFS_FS=y
CONFIG_PROC_FS=y
# CONFIG_PROC_KCORE is not set
CONFIG_PROC_SYSCTL=y
-# CONFIG_SYSFS is not set
-# CONFIG_TMPFS is not set
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
#
# Miscellaneous filesystems
@@ -781,10 +571,7 @@ CONFIG_RAMFS=y
# CONFIG_QNX4FS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
+CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
@@ -796,6 +583,7 @@ CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -803,22 +591,14 @@ CONFIG_SUNRPC=y
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
#
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
# CONFIG_NLS is not set
-
-#
-# Distributed Lock Manager
-#
+# CONFIG_DLM is not set
#
# Profiling support
@@ -833,20 +613,22 @@ CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_MAGIC_SYSRQ is not set
# 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_LOG_BUF_SHIFT=14
# CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_SCHED_DEBUG is not set
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
# CONFIG_DEBUG_SLAB 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_MUTEXES is not set
# CONFIG_DEBUG_LOCK_ALLOC is not set
# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
@@ -854,7 +636,9 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE="nfsroot=192.168.192.169:/u1/mipsel,timeo=20 ip=dhcp"
# CONFIG_DEBUG_STACK_USAGE is not set
@@ -865,60 +649,20 @@ CONFIG_CMDLINE="nfsroot=192.168.192.169:/u1/mipsel,timeo=20 ip=dhcp"
# Security options
#
# CONFIG_KEYS is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=m
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_XCBC=m
-# CONFIG_CRYPTO_NULL is not set
-# CONFIG_CRYPTO_MD4 is not set
-CONFIG_CRYPTO_MD5=y
-# CONFIG_CRYPTO_SHA1 is not set
-# CONFIG_CRYPTO_SHA256 is not set
-# CONFIG_CRYPTO_SHA512 is not set
-# CONFIG_CRYPTO_WP512 is not set
-# CONFIG_CRYPTO_TGR192 is not set
-CONFIG_CRYPTO_GF128MUL=m
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_LRW=m
-# CONFIG_CRYPTO_DES is not set
-CONFIG_CRYPTO_FCRYPT=m
-# CONFIG_CRYPTO_BLOWFISH is not set
-# CONFIG_CRYPTO_TWOFISH is not set
-# CONFIG_CRYPTO_SERPENT is not set
-# CONFIG_CRYPTO_AES is not set
-# CONFIG_CRYPTO_CAST5 is not set
-# CONFIG_CRYPTO_CAST6 is not set
-# CONFIG_CRYPTO_TEA is not set
-# CONFIG_CRYPTO_ARC4 is not set
-# CONFIG_CRYPTO_KHAZAD is not set
-# CONFIG_CRYPTO_ANUBIS is not set
-# CONFIG_CRYPTO_DEFLATE is not set
-# CONFIG_CRYPTO_MICHAEL_MIC is not set
-# CONFIG_CRYPTO_CRC32C is not set
-CONFIG_CRYPTO_CAMELLIA=m
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Hardware crypto devices
-#
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_CRYPTO is not set
#
# Library routines
#
-CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
-CONFIG_CRC16=y
-CONFIG_CRC32=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+# CONFIG_CRC32 is not set
+# 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
diff --git a/arch/mips/configs/mtx1_defconfig b/arch/mips/configs/mtx1_defconfig
index 0280ef389d8d..b536d7c63790 100644
--- a/arch/mips/configs/mtx1_defconfig
+++ b/arch/mips/configs/mtx1_defconfig
@@ -3021,7 +3021,7 @@ CONFIG_MAGIC_SYSRQ=y
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
-# CONFIG_CROSSCOMPILE is not set
+CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
CONFIG_SYS_SUPPORTS_KGDB=y
diff --git a/arch/mips/configs/pb1100_defconfig b/arch/mips/configs/pb1100_defconfig
index d53fa8f8e099..703d28db05b9 100644
--- a/arch/mips/configs/pb1100_defconfig
+++ b/arch/mips/configs/pb1100_defconfig
@@ -731,7 +731,6 @@ CONFIG_HW_CONSOLE=y
CONFIG_VT_HW_CONSOLE_BINDING=y
# CONFIG_SERIAL_NONSTANDARD is not set
# CONFIG_AU1X00_GPIO is not set
-# CONFIG_TS_AU1X00_ADS7846 is not set
#
# Serial drivers
diff --git a/arch/mips/configs/pb1500_defconfig b/arch/mips/configs/pb1500_defconfig
index dc4aa0c66847..82f0c5cee0dc 100644
--- a/arch/mips/configs/pb1500_defconfig
+++ b/arch/mips/configs/pb1500_defconfig
@@ -849,7 +849,6 @@ CONFIG_SERIO_RAW=m
# CONFIG_VT is not set
# CONFIG_SERIAL_NONSTANDARD is not set
# CONFIG_AU1X00_GPIO is not set
-# CONFIG_TS_AU1X00_ADS7846 is not set
#
# Serial drivers
diff --git a/arch/mips/configs/pb1550_defconfig b/arch/mips/configs/pb1550_defconfig
index 24428e13002b..147a4fc7fdd8 100644
--- a/arch/mips/configs/pb1550_defconfig
+++ b/arch/mips/configs/pb1550_defconfig
@@ -842,7 +842,6 @@ CONFIG_SERIO_RAW=m
# CONFIG_VT is not set
# CONFIG_SERIAL_NONSTANDARD is not set
# CONFIG_AU1X00_GPIO is not set
-# CONFIG_TS_AU1X00_ADS7846 is not set
#
# Serial drivers
diff --git a/arch/mips/configs/sb1250-swarm_defconfig b/arch/mips/configs/sb1250-swarm_defconfig
index 3ed991ae0ebe..c2798229cbfb 100644
--- a/arch/mips/configs/sb1250-swarm_defconfig
+++ b/arch/mips/configs/sb1250-swarm_defconfig
@@ -196,6 +196,7 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_CGROUPS=y
CONFIG_CPUSETS=y
CONFIG_SYSFS_DEPRECATED=y
CONFIG_RELAY=y
@@ -467,7 +468,7 @@ CONFIG_BLK_DEV_IDEFLOPPY=y
#
CONFIG_IDE_GENERIC=y
# CONFIG_BLK_DEV_IDEPCI is not set
-# CONFIG_BLK_DEV_IDE_SWARM is not set
+CONFIG_BLK_DEV_IDE_SWARM=y
# CONFIG_IDE_ARM is not set
# CONFIG_BLK_DEV_IDEDMA is not set
# CONFIG_IDEDMA_AUTO is not set
diff --git a/arch/mips/emma2rh/markeins/setup.c b/arch/mips/emma2rh/markeins/setup.c
index 5e1da53b04a7..82f9e9013e70 100644
--- a/arch/mips/emma2rh/markeins/setup.c
+++ b/arch/mips/emma2rh/markeins/setup.c
@@ -104,12 +104,6 @@ void __init plat_time_init(void)
mips_hpt_frequency = (bus_frequency * (4 + reg)) / 4 / 2;
}
-void __init plat_timer_setup(struct irqaction *irq)
-{
- /* we are using the cpu counter for timer interrupts */
- setup_irq(CPU_IRQ_BASE + 7, irq);
-}
-
static void markeins_board_init(void);
extern void markeins_irq_setup(void);
diff --git a/arch/mips/gt64120/wrppmc/time.c b/arch/mips/gt64120/wrppmc/time.c
index b207e7f1417a..668dbd5f12c5 100644
--- a/arch/mips/gt64120/wrppmc/time.c
+++ b/arch/mips/gt64120/wrppmc/time.c
@@ -19,12 +19,6 @@
#define WRPPMC_CPU_CLK_FREQ 40000000 /* 40MHZ */
-void __init plat_timer_setup(struct irqaction *irq)
-{
- /* Install ISR for timer interrupt */
- setup_irq(WRPPMC_MIPS_TIMER_IRQ, irq);
-}
-
/*
* Estimate CPU frequency. Sets mips_hpt_frequency as a side-effect
*
diff --git a/arch/mips/jazz/irq.c b/arch/mips/jazz/irq.c
index 835b056cea36..d7f8a782aae4 100644
--- a/arch/mips/jazz/irq.c
+++ b/arch/mips/jazz/irq.c
@@ -4,7 +4,7 @@
* for more details.
*
* Copyright (C) 1992 Linus Torvalds
- * Copyright (C) 1994 - 2001, 2003 Ralf Baechle
+ * Copyright (C) 1994 - 2001, 2003, 07 Ralf Baechle
*/
#include <linux/clockchips.h>
#include <linux/init.h>
@@ -13,6 +13,7 @@
#include <linux/spinlock.h>
#include <asm/irq_cpu.h>
+#include <asm/i8253.h>
#include <asm/i8259.h>
#include <asm/io.h>
#include <asm/jazz.h>
@@ -96,9 +97,10 @@ asmlinkage void plat_irq_dispatch(void)
if (pending & IE_IRQ4) {
r4030_read_reg32(JAZZ_TIMER_REGISTER);
do_IRQ(JAZZ_TIMER_IRQ);
- } else if (pending & IE_IRQ2)
- do_IRQ(r4030_read_reg32(JAZZ_EISA_IRQ_ACK));
- else if (pending & IE_IRQ1) {
+ } else if (pending & IE_IRQ2) {
+ irq = *(volatile u8 *)JAZZ_EISA_IRQ_ACK;
+ do_IRQ(irq);
+ } else if (pending & IE_IRQ1) {
irq = *(volatile u8 *)JAZZ_IO_IRQ_SOURCE >> 2;
if (likely(irq > 0))
do_IRQ(irq + JAZZ_IRQ_START - 1);
@@ -116,16 +118,16 @@ static void r4030_set_mode(enum clock_event_mode mode,
struct clock_event_device r4030_clockevent = {
.name = "r4030",
.features = CLOCK_EVT_FEAT_PERIODIC,
- .rating = 100,
+ .rating = 300,
.irq = JAZZ_TIMER_IRQ,
- .cpumask = CPU_MASK_CPU0,
.set_mode = r4030_set_mode,
};
static irqreturn_t r4030_timer_interrupt(int irq, void *dev_id)
{
- r4030_clockevent.event_handler(&r4030_clockevent);
+ struct clock_event_device *cd = dev_id;
+ cd->event_handler(cd);
return IRQ_HANDLED;
}
@@ -133,15 +135,22 @@ static struct irqaction r4030_timer_irqaction = {
.handler = r4030_timer_interrupt,
.flags = IRQF_DISABLED,
.mask = CPU_MASK_CPU0,
- .name = "timer",
+ .name = "R4030 timer",
};
-void __init plat_timer_setup(struct irqaction *ignored)
+void __init plat_time_init(void)
{
- struct irqaction *irq = &r4030_timer_irqaction;
+ struct clock_event_device *cd = &r4030_clockevent;
+ struct irqaction *action = &r4030_timer_irqaction;
+ unsigned int cpu = smp_processor_id();
BUG_ON(HZ != 100);
+ cd->cpumask = cpumask_of_cpu(cpu);
+ clockevents_register_device(cd);
+ action->dev_id = cd;
+ setup_irq(JAZZ_TIMER_IRQ, action);
+
/*
* Set clock to 100Hz.
*
@@ -149,7 +158,5 @@ void __init plat_timer_setup(struct irqaction *ignored)
* a programmable 4-bit divider. This makes it fairly inflexible.
*/
r4030_write_reg32(JAZZ_TIMER_INTERVAL, 9);
- setup_irq(JAZZ_TIMER_IRQ, irq);
-
- clockevents_register_device(&r4030_clockevent);
+ setup_pit_timer();
}
diff --git a/arch/mips/jazz/setup.c b/arch/mips/jazz/setup.c
index cfc7dce78dab..a7857973ca03 100644
--- a/arch/mips/jazz/setup.c
+++ b/arch/mips/jazz/setup.c
@@ -5,7 +5,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1996, 1997, 1998, 2001 by Ralf Baechle
+ * Copyright (C) 1996, 1997, 1998, 2001, 07 by Ralf Baechle
* Copyright (C) 2001 MIPS Technologies, Inc.
* Copyright (C) 2007 by Thomas Bogendoerfer
*/
@@ -25,7 +25,6 @@
#include <linux/serial_8250.h>
#include <asm/bootinfo.h>
-#include <asm/i8253.h>
#include <asm/irq.h>
#include <asm/jazz.h>
#include <asm/jazzdma.h>
@@ -64,11 +63,6 @@ static struct resource jazz_io_resources[] = {
}
};
-void __init plat_time_init(void)
-{
- setup_pit_timer();
-}
-
void __init plat_mem_setup(void)
{
int i;
diff --git a/arch/mips/jmr3927/rbhma3100/setup.c b/arch/mips/jmr3927/rbhma3100/setup.c
index 7f14f70a1b88..06e01c8f4e3a 100644
--- a/arch/mips/jmr3927/rbhma3100/setup.c
+++ b/arch/mips/jmr3927/rbhma3100/setup.c
@@ -1,15 +1,4 @@
-/***********************************************************************
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- * ahennessy@mvista.com
- *
- * Based on arch/mips/ddb5xxx/ddb5477/setup.c
- *
- * Setup file for JMR3927.
- *
- * Copyright (C) 2000-2001 Toshiba Corporation
- *
+/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
@@ -30,19 +19,21 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
- ***********************************************************************
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ahennessy@mvista.com
+ *
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org)
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/kdev_t.h>
#include <linux/types.h>
-#include <linux/sched.h>
#include <linux/pci.h>
#include <linux/ide.h>
-#include <linux/irq.h>
#include <linux/ioport.h>
-#include <linux/param.h> /* for HZ */
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/platform_device.h>
@@ -53,17 +44,13 @@
#endif
#include <asm/addrspace.h>
-#include <asm/time.h>
+#include <asm/txx9tmr.h>
#include <asm/reboot.h>
#include <asm/jmr3927/jmr3927.h>
#include <asm/mipsregs.h>
extern void puts(const char *cp);
-/* Tick Timer divider */
-#define JMR3927_TIMER_CCD 0 /* 1/2 */
-#define JMR3927_TIMER_CLK (JMR3927_IMCLK / (2 << JMR3927_TIMER_CCD))
-
/* don't enable - see errata */
static int jmr3927_ccfg_toeon;
@@ -98,33 +85,12 @@ static void jmr3927_machine_power_off(void)
while (1);
}
-static cycle_t jmr3927_hpt_read(void)
-{
- /* We assume this function is called xtime_lock held. */
- return jiffies * (JMR3927_TIMER_CLK / HZ) + jmr3927_tmrptr->trr;
-}
-
-static void jmr3927_timer_ack(void)
-{
- jmr3927_tmrptr->tisr = 0; /* ack interrupt */
-}
-
void __init plat_time_init(void)
{
- clocksource_mips.read = jmr3927_hpt_read;
- mips_timer_ack = jmr3927_timer_ack;
- mips_hpt_frequency = JMR3927_TIMER_CLK;
-}
-
-void __init plat_timer_setup(struct irqaction *irq)
-{
- jmr3927_tmrptr->cpra = JMR3927_TIMER_CLK / HZ;
- jmr3927_tmrptr->itmr = TXx927_TMTITMR_TIIE | TXx927_TMTITMR_TZCE;
- jmr3927_tmrptr->ccdr = JMR3927_TIMER_CCD;
- jmr3927_tmrptr->tcr =
- TXx927_TMTCR_TCE | TXx927_TMTCR_CCDE | TXx927_TMTCR_TMODE_ITVL;
-
- setup_irq(JMR3927_IRQ_TICK, irq);
+ txx9_clockevent_init(TX3927_TMR_REG(0),
+ TXX9_IRQ_BASE + JMR3927_IRQ_IRC_TMR(0),
+ JMR3927_IMCLK);
+ txx9_clocksource_init(TX3927_TMR_REG(1), JMR3927_IMCLK);
}
#define DO_WRITE_THROUGH
@@ -289,15 +255,8 @@ static void __init tx3927_setup(void)
tx3927_ccfgptr->ccfg, tx3927_ccfgptr->pcfg);
/* TMR */
- /* disable all timers */
- for (i = 0; i < TX3927_NR_TMR; i++) {
- tx3927_tmrptr(i)->tcr = TXx927_TMTCR_CRE;
- tx3927_tmrptr(i)->tisr = 0;
- tx3927_tmrptr(i)->cpra = 0xffffffff;
- tx3927_tmrptr(i)->itmr = 0;
- tx3927_tmrptr(i)->ccdr = 0;
- tx3927_tmrptr(i)->pgmr = 0;
- }
+ for (i = 0; i < TX3927_NR_TMR; i++)
+ txx9_tmr_init(TX3927_TMR_REG(i));
/* DMA */
tx3927_dmaptr->mcr = 0;
@@ -425,7 +384,7 @@ static int __init jmr3927_rtc_init(void)
.flags = IORESOURCE_MEM,
};
struct platform_device *dev;
- dev = platform_device_register_simple("ds1742", -1, &res, 1);
+ dev = platform_device_register_simple("rtc-ds1742", -1, &res, 1);
return IS_ERR(dev) ? PTR_ERR(dev) : 0;
}
device_initcall(jmr3927_rtc_init);
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index a2689f93c160..b551535b7e48 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -8,6 +8,14 @@ obj-y += cpu-probe.o branch.o entry.o genex.o irq.o process.o \
ptrace.o reset.o semaphore.o setup.o signal.o syscall.o \
time.o topology.o traps.o unaligned.o
+obj-$(CONFIG_CEVT_BCM1480) += cevt-bcm1480.o
+obj-$(CONFIG_CEVT_R4K) += cevt-r4k.o
+obj-$(CONFIG_CEVT_GT641XX) += cevt-gt641xx.o
+obj-$(CONFIG_CEVT_SB1250) += cevt-sb1250.o
+obj-$(CONFIG_CEVT_TXX9) += cevt-txx9.o
+obj-$(CONFIG_CSRC_BCM1480) += csrc-bcm1480.o
+obj-$(CONFIG_CSRC_SB1250) += csrc-sb1250.o
+
binfmt_irix-objs := irixelf.o irixinv.o irixioctl.o irixsig.o \
irix5sys.o sysirix.o
@@ -71,7 +79,7 @@ obj-$(CONFIG_PCSPEAKER) += pcspeaker.o
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
-CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
+CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
obj-$(CONFIG_HAVE_STD_PC_SERIAL_PORT) += 8250-platform.o
diff --git a/arch/mips/kernel/cevt-bcm1480.c b/arch/mips/kernel/cevt-bcm1480.c
new file mode 100644
index 000000000000..0a57f86945f1
--- /dev/null
+++ b/arch/mips/kernel/cevt-bcm1480.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2000,2001,2004 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <linux/clockchips.h>
+#include <linux/interrupt.h>
+#include <linux/percpu.h>
+
+#include <asm/addrspace.h>
+#include <asm/io.h>
+#include <asm/time.h>
+
+#include <asm/sibyte/bcm1480_regs.h>
+#include <asm/sibyte/sb1250_regs.h>
+#include <asm/sibyte/bcm1480_int.h>
+#include <asm/sibyte/bcm1480_scd.h>
+
+#include <asm/sibyte/sb1250.h>
+
+#define IMR_IP2_VAL K_BCM1480_INT_MAP_I0
+#define IMR_IP3_VAL K_BCM1480_INT_MAP_I1
+#define IMR_IP4_VAL K_BCM1480_INT_MAP_I2
+
+/*
+ * The general purpose timer ticks at 1MHz independent if
+ * the rest of the system
+ */
+static void sibyte_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ unsigned int cpu = smp_processor_id();
+ void __iomem *cfg, *init;
+
+ cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
+ init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT));
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ __raw_writeq(0, cfg);
+ __raw_writeq((V_SCD_TIMER_FREQ / HZ) - 1, init);
+ __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
+ cfg);
+ break;
+
+ case CLOCK_EVT_MODE_ONESHOT:
+ /* Stop the timer until we actually program a shot */
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ __raw_writeq(0, cfg);
+ break;
+
+ case CLOCK_EVT_MODE_UNUSED: /* shuddup gcc */
+ case CLOCK_EVT_MODE_RESUME:
+ ;
+ }
+}
+
+static int sibyte_next_event(unsigned long delta, struct clock_event_device *cd)
+{
+ unsigned int cpu = smp_processor_id();
+ void __iomem *cfg, *init;
+
+ cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
+ init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT));
+
+ __raw_writeq(0, cfg);
+ __raw_writeq(delta - 1, init);
+ __raw_writeq(M_SCD_TIMER_ENABLE, cfg);
+
+ return 0;
+}
+
+static irqreturn_t sibyte_counter_handler(int irq, void *dev_id)
+{
+ unsigned int cpu = smp_processor_id();
+ struct clock_event_device *cd = dev_id;
+ void __iomem *cfg;
+ unsigned long tmode;
+
+ if (cd->mode == CLOCK_EVT_MODE_PERIODIC)
+ tmode = M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS;
+ else
+ tmode = 0;
+
+ /* ACK interrupt */
+ cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
+ ____raw_writeq(tmode, cfg);
+
+ cd->event_handler(cd);
+
+ return IRQ_HANDLED;
+}
+
+static DEFINE_PER_CPU(struct clock_event_device, sibyte_hpt_clockevent);
+static DEFINE_PER_CPU(struct irqaction, sibyte_hpt_irqaction);
+static DEFINE_PER_CPU(char [18], sibyte_hpt_name);
+
+void __cpuinit sb1480_clockevent_init(void)
+{
+ unsigned int cpu = smp_processor_id();
+ unsigned int irq = K_BCM1480_INT_TIMER_0 + cpu;
+ struct irqaction *action = &per_cpu(sibyte_hpt_irqaction, cpu);
+ struct clock_event_device *cd = &per_cpu(sibyte_hpt_clockevent, cpu);
+ unsigned char *name = per_cpu(sibyte_hpt_name, cpu);
+
+ BUG_ON(cpu > 3); /* Only have 4 general purpose timers */
+
+ sprintf(name, "bcm1480-counter-%d", cpu);
+ cd->name = name;
+ cd->features = CLOCK_EVT_FEAT_PERIODIC |
+ CLOCK_EVT_FEAT_ONESHOT;
+ clockevent_set_clock(cd, V_SCD_TIMER_FREQ);
+ cd->max_delta_ns = clockevent_delta2ns(0x7fffff, cd);
+ cd->min_delta_ns = clockevent_delta2ns(2, cd);
+ cd->rating = 200;
+ cd->irq = irq;
+ cd->cpumask = cpumask_of_cpu(cpu);
+ cd->set_next_event = sibyte_next_event;
+ cd->set_mode = sibyte_set_mode;
+ clockevents_register_device(cd);
+
+ bcm1480_mask_irq(cpu, irq);
+
+ /*
+ * Map the timer interrupt to IP[4] of this cpu
+ */
+ __raw_writeq(IMR_IP4_VAL,
+ IOADDR(A_BCM1480_IMR_REGISTER(cpu,
+ R_BCM1480_IMR_INTERRUPT_MAP_BASE_H) + (irq << 3)));
+
+ bcm1480_unmask_irq(cpu, irq);
+
+ action->handler = sibyte_counter_handler;
+ action->flags = IRQF_DISABLED | IRQF_PERCPU;
+ action->mask = cpumask_of_cpu(cpu);
+ action->name = name;
+ action->dev_id = cd;
+
+ irq_set_affinity(irq, cpumask_of_cpu(cpu));
+ setup_irq(irq, action);
+}
diff --git a/arch/mips/kernel/cevt-gt641xx.c b/arch/mips/kernel/cevt-gt641xx.c
new file mode 100644
index 000000000000..c36772631fe0
--- /dev/null
+++ b/arch/mips/kernel/cevt-gt641xx.c
@@ -0,0 +1,142 @@
+/*
+ * GT641xx clockevent routines.
+ *
+ * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <linux/clockchips.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+
+#include <asm/gt64120.h>
+#include <asm/time.h>
+
+#include <irq.h>
+
+static DEFINE_SPINLOCK(gt641xx_timer_lock);
+static unsigned int gt641xx_base_clock;
+
+void gt641xx_set_base_clock(unsigned int clock)
+{
+ gt641xx_base_clock = clock;
+}
+
+int gt641xx_timer0_state(void)
+{
+ if (GT_READ(GT_TC0_OFS))
+ return 0;
+
+ GT_WRITE(GT_TC0_OFS, gt641xx_base_clock / HZ);
+ GT_WRITE(GT_TC_CONTROL_OFS, GT_TC_CONTROL_ENTC0_MSK);
+
+ return 1;
+}
+
+static int gt641xx_timer0_set_next_event(unsigned long delta,
+ struct clock_event_device *evt)
+{
+ u32 ctrl;
+
+ spin_lock(&gt641xx_timer_lock);
+
+ ctrl = GT_READ(GT_TC_CONTROL_OFS);
+ ctrl &= ~(GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK);
+ ctrl |= GT_TC_CONTROL_ENTC0_MSK;
+
+ GT_WRITE(GT_TC0_OFS, delta);
+ GT_WRITE(GT_TC_CONTROL_OFS, ctrl);
+
+ spin_unlock(&gt641xx_timer_lock);
+
+ return 0;
+}
+
+static void gt641xx_timer0_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ u32 ctrl;
+
+ spin_lock(&gt641xx_timer_lock);
+
+ ctrl = GT_READ(GT_TC_CONTROL_OFS);
+ ctrl &= ~(GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK);
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ ctrl |= GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK;
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ ctrl |= GT_TC_CONTROL_ENTC0_MSK;
+ break;
+ default:
+ break;
+ }
+
+ GT_WRITE(GT_TC_CONTROL_OFS, ctrl);
+
+ spin_unlock(&gt641xx_timer_lock);
+}
+
+static void gt641xx_timer0_event_handler(struct clock_event_device *dev)
+{
+}
+
+static struct clock_event_device gt641xx_timer0_clockevent = {
+ .name = "gt641xx-timer0",
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+ .cpumask = CPU_MASK_CPU0,
+ .irq = GT641XX_TIMER0_IRQ,
+ .set_next_event = gt641xx_timer0_set_next_event,
+ .set_mode = gt641xx_timer0_set_mode,
+ .event_handler = gt641xx_timer0_event_handler,
+};
+
+static irqreturn_t gt641xx_timer0_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *cd = &gt641xx_timer0_clockevent;
+
+ cd->event_handler(cd);
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction gt641xx_timer0_irqaction = {
+ .handler = gt641xx_timer0_interrupt,
+ .flags = IRQF_DISABLED | IRQF_PERCPU,
+ .name = "gt641xx_timer0",
+};
+
+static int __init gt641xx_timer0_clockevent_init(void)
+{
+ struct clock_event_device *cd;
+
+ if (!gt641xx_base_clock)
+ return 0;
+
+ GT_WRITE(GT_TC0_OFS, gt641xx_base_clock / HZ);
+
+ cd = &gt641xx_timer0_clockevent;
+ cd->rating = 200 + gt641xx_base_clock / 10000000;
+ clockevent_set_clock(cd, gt641xx_base_clock);
+ cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd);
+ cd->min_delta_ns = clockevent_delta2ns(0x300, cd);
+
+ clockevents_register_device(&gt641xx_timer0_clockevent);
+
+ return setup_irq(GT641XX_TIMER0_IRQ, &gt641xx_timer0_irqaction);
+}
+arch_initcall(gt641xx_timer0_clockevent_init);
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c
new file mode 100644
index 000000000000..bab935a3d74b
--- /dev/null
+++ b/arch/mips/kernel/cevt-r4k.c
@@ -0,0 +1,290 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007 MIPS Technologies, Inc.
+ * Copyright (C) 2007 Ralf Baechle <ralf@linux-mips.org>
+ */
+#include <linux/clockchips.h>
+#include <linux/interrupt.h>
+#include <linux/percpu.h>
+
+#include <asm/smtc_ipi.h>
+#include <asm/time.h>
+
+static int mips_next_event(unsigned long delta,
+ struct clock_event_device *evt)
+{
+ unsigned int cnt;
+ int res;
+
+#ifdef CONFIG_MIPS_MT_SMTC
+ {
+ unsigned long flags, vpflags;
+ local_irq_save(flags);
+ vpflags = dvpe();
+#endif
+ cnt = read_c0_count();
+ cnt += delta;
+ write_c0_compare(cnt);
+ res = ((int)(read_c0_count() - cnt) > 0) ? -ETIME : 0;
+#ifdef CONFIG_MIPS_MT_SMTC
+ evpe(vpflags);
+ local_irq_restore(flags);
+ }
+#endif
+ return res;
+}
+
+static void mips_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ /* Nothing to do ... */
+}
+
+static DEFINE_PER_CPU(struct clock_event_device, mips_clockevent_device);
+static int cp0_timer_irq_installed;
+
+/*
+ * Timer ack for an R4k-compatible timer of a known frequency.
+ */
+static void c0_timer_ack(void)
+{
+ write_c0_compare(read_c0_compare());
+}
+
+/*
+ * Possibly handle a performance counter interrupt.
+ * Return true if the timer interrupt should not be checked
+ */
+static inline int handle_perf_irq(int r2)
+{
+ /*
+ * The performance counter overflow interrupt may be shared with the
+ * timer interrupt (cp0_perfcount_irq < 0). If it is and a
+ * performance counter has overflowed (perf_irq() == IRQ_HANDLED)
+ * and we can't reliably determine if a counter interrupt has also
+ * happened (!r2) then don't check for a timer interrupt.
+ */
+ return (cp0_perfcount_irq < 0) &&
+ perf_irq() == IRQ_HANDLED &&
+ !r2;
+}
+
+static irqreturn_t c0_compare_interrupt(int irq, void *dev_id)
+{
+ const int r2 = cpu_has_mips_r2;
+ struct clock_event_device *cd;
+ int cpu = smp_processor_id();
+
+ /*
+ * Suckage alert:
+ * Before R2 of the architecture there was no way to see if a
+ * performance counter interrupt was pending, so we have to run
+ * the performance counter interrupt handler anyway.
+ */
+ if (handle_perf_irq(r2))
+ goto out;
+
+ /*
+ * The same applies to performance counter interrupts. But with the
+ * above we now know that the reason we got here must be a timer
+ * interrupt. Being the paranoiacs we are we check anyway.
+ */
+ if (!r2 || (read_c0_cause() & (1 << 30))) {
+ c0_timer_ack();
+#ifdef CONFIG_MIPS_MT_SMTC
+ if (cpu_data[cpu].vpe_id)
+ goto out;
+ cpu = 0;
+#endif
+ cd = &per_cpu(mips_clockevent_device, cpu);
+ cd->event_handler(cd);
+ }
+
+out:
+ return IRQ_HANDLED;
+}
+
+static struct irqaction c0_compare_irqaction = {
+ .handler = c0_compare_interrupt,
+#ifdef CONFIG_MIPS_MT_SMTC
+ .flags = IRQF_DISABLED,
+#else
+ .flags = IRQF_DISABLED | IRQF_PERCPU,
+#endif
+ .name = "timer",
+};
+
+#ifdef CONFIG_MIPS_MT_SMTC
+DEFINE_PER_CPU(struct clock_event_device, smtc_dummy_clockevent_device);
+
+static void smtc_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+}
+
+static void mips_broadcast(cpumask_t mask)
+{
+ unsigned int cpu;
+
+ for_each_cpu_mask(cpu, mask)
+ smtc_send_ipi(cpu, SMTC_CLOCK_TICK, 0);
+}
+
+static void setup_smtc_dummy_clockevent_device(void)
+{
+ //uint64_t mips_freq = mips_hpt_^frequency;
+ unsigned int cpu = smp_processor_id();
+ struct clock_event_device *cd;
+
+ cd = &per_cpu(smtc_dummy_clockevent_device, cpu);
+
+ cd->name = "SMTC";
+ cd->features = CLOCK_EVT_FEAT_DUMMY;
+
+ /* Calculate the min / max delta */
+ cd->mult = 0; //div_sc((unsigned long) mips_freq, NSEC_PER_SEC, 32);
+ cd->shift = 0; //32;
+ cd->max_delta_ns = 0; //clockevent_delta2ns(0x7fffffff, cd);
+ cd->min_delta_ns = 0; //clockevent_delta2ns(0x30, cd);
+
+ cd->rating = 200;
+ cd->irq = 17; //-1;
+// if (cpu)
+// cd->cpumask = CPU_MASK_ALL; // cpumask_of_cpu(cpu);
+// else
+ cd->cpumask = cpumask_of_cpu(cpu);
+
+ cd->set_mode = smtc_set_mode;
+
+ cd->broadcast = mips_broadcast;
+
+ clockevents_register_device(cd);
+}
+#endif
+
+static void mips_event_handler(struct clock_event_device *dev)
+{
+}
+
+/*
+ * FIXME: This doesn't hold for the relocated E9000 compare interrupt.
+ */
+static int c0_compare_int_pending(void)
+{
+ return (read_c0_cause() >> cp0_compare_irq) & 0x100;
+}
+
+static int c0_compare_int_usable(void)
+{
+ unsigned int delta;
+ unsigned int cnt;
+
+ /*
+ * IP7 already pending? Try to clear it by acking the timer.
+ */
+ if (c0_compare_int_pending()) {
+ write_c0_compare(read_c0_count());
+ irq_disable_hazard();
+ if (c0_compare_int_pending())
+ return 0;
+ }
+
+ for (delta = 0x10; delta <= 0x400000; delta <<= 1) {
+ cnt = read_c0_count();
+ cnt += delta;
+ write_c0_compare(cnt);
+ irq_disable_hazard();
+ if ((int)(read_c0_count() - cnt) < 0)
+ break;
+ /* increase delta if the timer was already expired */
+ }
+
+ while ((int)(read_c0_count() - cnt) <= 0)
+ ; /* Wait for expiry */
+
+ if (!c0_compare_int_pending())
+ return 0;
+
+ write_c0_compare(read_c0_count());
+ irq_disable_hazard();
+ if (c0_compare_int_pending())
+ return 0;
+
+ /*
+ * Feels like a real count / compare timer.
+ */
+ return 1;
+}
+
+void __cpuinit mips_clockevent_init(void)
+{
+ uint64_t mips_freq = mips_hpt_frequency;
+ unsigned int cpu = smp_processor_id();
+ struct clock_event_device *cd;
+ unsigned int irq;
+
+ if (!cpu_has_counter || !mips_hpt_frequency)
+ return;
+
+#ifdef CONFIG_MIPS_MT_SMTC
+ setup_smtc_dummy_clockevent_device();
+
+ /*
+ * On SMTC we only register VPE0's compare interrupt as clockevent
+ * device.
+ */
+ if (cpu)
+ return;
+#endif
+
+ if (!c0_compare_int_usable())
+ return;
+
+ /*
+ * With vectored interrupts things are getting platform specific.
+ * get_c0_compare_int is a hook to allow a platform to return the
+ * interrupt number of it's liking.
+ */
+ irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
+ if (get_c0_compare_int)
+ irq = get_c0_compare_int();
+
+ cd = &per_cpu(mips_clockevent_device, cpu);
+
+ cd->name = "MIPS";
+ cd->features = CLOCK_EVT_FEAT_ONESHOT;
+
+ /* Calculate the min / max delta */
+ cd->mult = div_sc((unsigned long) mips_freq, NSEC_PER_SEC, 32);
+ cd->shift = 32;
+ cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd);
+ cd->min_delta_ns = clockevent_delta2ns(0x300, cd);
+
+ cd->rating = 300;
+ cd->irq = irq;
+#ifdef CONFIG_MIPS_MT_SMTC
+ cd->cpumask = CPU_MASK_ALL;
+#else
+ cd->cpumask = cpumask_of_cpu(cpu);
+#endif
+ cd->set_next_event = mips_next_event;
+ cd->set_mode = mips_set_mode;
+ cd->event_handler = mips_event_handler;
+
+ clockevents_register_device(cd);
+
+ if (!cp0_timer_irq_installed)
+ return;
+
+ cp0_timer_irq_installed = 1;
+
+#ifdef CONFIG_MIPS_MT_SMTC
+#define CPUCTR_IMASKBIT (0x100 << cp0_compare_irq)
+ setup_irq_smtc(irq, &c0_compare_irqaction, CPUCTR_IMASKBIT);
+#else
+ setup_irq(irq, &c0_compare_irqaction);
+#endif
+}
diff --git a/arch/mips/kernel/cevt-sb1250.c b/arch/mips/kernel/cevt-sb1250.c
new file mode 100644
index 000000000000..63ac3ad462bc
--- /dev/null
+++ b/arch/mips/kernel/cevt-sb1250.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2000, 2001 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <linux/clockchips.h>
+#include <linux/interrupt.h>
+#include <linux/percpu.h>
+
+#include <asm/addrspace.h>
+#include <asm/io.h>
+#include <asm/time.h>
+
+#include <asm/sibyte/sb1250.h>
+#include <asm/sibyte/sb1250_regs.h>
+#include <asm/sibyte/sb1250_int.h>
+#include <asm/sibyte/sb1250_scd.h>
+
+#define IMR_IP2_VAL K_INT_MAP_I0
+#define IMR_IP3_VAL K_INT_MAP_I1
+#define IMR_IP4_VAL K_INT_MAP_I2
+
+/*
+ * The general purpose timer ticks at 1MHz independent if
+ * the rest of the system
+ */
+static void sibyte_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ unsigned int cpu = smp_processor_id();
+ void __iomem *cfg, *init;
+
+ cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
+ init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT));
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ __raw_writeq(0, cfg);
+ __raw_writeq((V_SCD_TIMER_FREQ / HZ) - 1, init);
+ __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
+ cfg);
+ break;
+
+ case CLOCK_EVT_MODE_ONESHOT:
+ /* Stop the timer until we actually program a shot */
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ __raw_writeq(0, cfg);
+ break;
+
+ case CLOCK_EVT_MODE_UNUSED: /* shuddup gcc */
+ case CLOCK_EVT_MODE_RESUME:
+ ;
+ }
+}
+
+static int sibyte_next_event(unsigned long delta, struct clock_event_device *cd)
+{
+ unsigned int cpu = smp_processor_id();
+ void __iomem *cfg, *init;
+
+ cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
+ init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT));
+
+ __raw_writeq(0, cfg);
+ __raw_writeq(delta - 1, init);
+ __raw_writeq(M_SCD_TIMER_ENABLE, cfg);
+
+ return 0;
+}
+
+static irqreturn_t sibyte_counter_handler(int irq, void *dev_id)
+{
+ unsigned int cpu = smp_processor_id();
+ struct clock_event_device *cd = dev_id;
+ void __iomem *cfg;
+ unsigned long tmode;
+
+ if (cd->mode == CLOCK_EVT_MODE_PERIODIC)
+ tmode = M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS;
+ else
+ tmode = 0;
+
+ /* ACK interrupt */
+ cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
+ ____raw_writeq(tmode, cfg);
+
+ cd->event_handler(cd);
+
+ return IRQ_HANDLED;
+}
+
+static DEFINE_PER_CPU(struct clock_event_device, sibyte_hpt_clockevent);
+static DEFINE_PER_CPU(struct irqaction, sibyte_hpt_irqaction);
+static DEFINE_PER_CPU(char [18], sibyte_hpt_name);
+
+void __cpuinit sb1250_clockevent_init(void)
+{
+ unsigned int cpu = smp_processor_id();
+ unsigned int irq = K_INT_TIMER_0 + cpu;
+ struct irqaction *action = &per_cpu(sibyte_hpt_irqaction, cpu);
+ struct clock_event_device *cd = &per_cpu(sibyte_hpt_clockevent, cpu);
+ unsigned char *name = per_cpu(sibyte_hpt_name, cpu);
+
+ /* Only have 4 general purpose timers, and we use last one as hpt */
+ BUG_ON(cpu > 2);
+
+ sprintf(name, "sb1250-counter-%d", cpu);
+ cd->name = name;
+ cd->features = CLOCK_EVT_FEAT_PERIODIC |
+ CLOCK_EVT_FEAT_ONESHOT;
+ clockevent_set_clock(cd, V_SCD_TIMER_FREQ);
+ cd->max_delta_ns = clockevent_delta2ns(0x7fffff, cd);
+ cd->min_delta_ns = clockevent_delta2ns(2, cd);
+ cd->rating = 200;
+ cd->irq = irq;
+ cd->cpumask = cpumask_of_cpu(cpu);
+ cd->set_next_event = sibyte_next_event;
+ cd->set_mode = sibyte_set_mode;
+ clockevents_register_device(cd);
+
+ sb1250_mask_irq(cpu, irq);
+
+ /*
+ * Map the timer interrupt to IP[4] of this cpu
+ */
+ __raw_writeq(IMR_IP4_VAL,
+ IOADDR(A_IMR_REGISTER(cpu, R_IMR_INTERRUPT_MAP_BASE) +
+ (irq << 3)));
+
+ sb1250_unmask_irq(cpu, irq);
+
+ action->handler = sibyte_counter_handler;
+ action->flags = IRQF_DISABLED | IRQF_PERCPU;
+ action->mask = cpumask_of_cpu(cpu);
+ action->name = name;
+ action->dev_id = cd;
+
+ irq_set_affinity(irq, cpumask_of_cpu(cpu));
+ setup_irq(irq, action);
+}
diff --git a/arch/mips/kernel/cevt-txx9.c b/arch/mips/kernel/cevt-txx9.c
new file mode 100644
index 000000000000..795cb8fb0d74
--- /dev/null
+++ b/arch/mips/kernel/cevt-txx9.c
@@ -0,0 +1,171 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Based on linux/arch/mips/kernel/cevt-r4k.c,
+ * linux/arch/mips/jmr3927/rbhma3100/setup.c
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ * Copyright (C) 2007 MIPS Technologies, Inc.
+ * Copyright (C) 2007 Ralf Baechle <ralf@linux-mips.org>
+ */
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <asm/time.h>
+#include <asm/txx9tmr.h>
+
+#define TCR_BASE (TXx9_TMTCR_CCDE | TXx9_TMTCR_CRE | TXx9_TMTCR_TMODE_ITVL)
+#define TIMER_CCD 0 /* 1/2 */
+#define TIMER_CLK(imclk) ((imclk) / (2 << TIMER_CCD))
+
+static struct txx9_tmr_reg __iomem *txx9_cs_tmrptr;
+
+static cycle_t txx9_cs_read(void)
+{
+ return __raw_readl(&txx9_cs_tmrptr->trr);
+}
+
+/* Use 1 bit smaller width to use full bits in that width */
+#define TXX9_CLOCKSOURCE_BITS (TXX9_TIMER_BITS - 1)
+
+static struct clocksource txx9_clocksource = {
+ .name = "TXx9",
+ .rating = 200,
+ .read = txx9_cs_read,
+ .mask = CLOCKSOURCE_MASK(TXX9_CLOCKSOURCE_BITS),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+void __init txx9_clocksource_init(unsigned long baseaddr,
+ unsigned int imbusclk)
+{
+ struct txx9_tmr_reg __iomem *tmrptr;
+
+ clocksource_set_clock(&txx9_clocksource, TIMER_CLK(imbusclk));
+ clocksource_register(&txx9_clocksource);
+
+ tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg));
+ __raw_writel(TCR_BASE, &tmrptr->tcr);
+ __raw_writel(0, &tmrptr->tisr);
+ __raw_writel(TIMER_CCD, &tmrptr->ccdr);
+ __raw_writel(TXx9_TMITMR_TZCE, &tmrptr->itmr);
+ __raw_writel(1 << TXX9_CLOCKSOURCE_BITS, &tmrptr->cpra);
+ __raw_writel(TCR_BASE | TXx9_TMTCR_TCE, &tmrptr->tcr);
+ txx9_cs_tmrptr = tmrptr;
+}
+
+static struct txx9_tmr_reg __iomem *txx9_tmrptr;
+
+static void txx9tmr_stop_and_clear(struct txx9_tmr_reg __iomem *tmrptr)
+{
+ /* stop and reset counter */
+ __raw_writel(TCR_BASE, &tmrptr->tcr);
+ /* clear pending interrupt */
+ __raw_writel(0, &tmrptr->tisr);
+}
+
+static void txx9tmr_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ struct txx9_tmr_reg __iomem *tmrptr = txx9_tmrptr;
+
+ txx9tmr_stop_and_clear(tmrptr);
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ __raw_writel(TXx9_TMITMR_TIIE | TXx9_TMITMR_TZCE,
+ &tmrptr->itmr);
+ /* start timer */
+ __raw_writel(((u64)(NSEC_PER_SEC / HZ) * evt->mult) >>
+ evt->shift,
+ &tmrptr->cpra);
+ __raw_writel(TCR_BASE | TXx9_TMTCR_TCE, &tmrptr->tcr);
+ break;
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ case CLOCK_EVT_MODE_UNUSED:
+ __raw_writel(0, &tmrptr->itmr);
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ __raw_writel(TXx9_TMITMR_TIIE, &tmrptr->itmr);
+ break;
+ case CLOCK_EVT_MODE_RESUME:
+ __raw_writel(TIMER_CCD, &tmrptr->ccdr);
+ __raw_writel(0, &tmrptr->itmr);
+ break;
+ }
+}
+
+static int txx9tmr_set_next_event(unsigned long delta,
+ struct clock_event_device *evt)
+{
+ struct txx9_tmr_reg __iomem *tmrptr = txx9_tmrptr;
+
+ txx9tmr_stop_and_clear(tmrptr);
+ /* start timer */
+ __raw_writel(delta, &tmrptr->cpra);
+ __raw_writel(TCR_BASE | TXx9_TMTCR_TCE, &tmrptr->tcr);
+ return 0;
+}
+
+static struct clock_event_device txx9tmr_clock_event_device = {
+ .name = "TXx9",
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+ .rating = 200,
+ .cpumask = CPU_MASK_CPU0,
+ .set_mode = txx9tmr_set_mode,
+ .set_next_event = txx9tmr_set_next_event,
+};
+
+static irqreturn_t txx9tmr_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *cd = &txx9tmr_clock_event_device;
+ struct txx9_tmr_reg __iomem *tmrptr = txx9_tmrptr;
+
+ __raw_writel(0, &tmrptr->tisr); /* ack interrupt */
+ cd->event_handler(cd);
+ return IRQ_HANDLED;
+}
+
+static struct irqaction txx9tmr_irq = {
+ .handler = txx9tmr_interrupt,
+ .flags = IRQF_DISABLED | IRQF_PERCPU,
+ .name = "txx9tmr",
+};
+
+void __init txx9_clockevent_init(unsigned long baseaddr, int irq,
+ unsigned int imbusclk)
+{
+ struct clock_event_device *cd = &txx9tmr_clock_event_device;
+ struct txx9_tmr_reg __iomem *tmrptr;
+
+ tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg));
+ txx9tmr_stop_and_clear(tmrptr);
+ __raw_writel(TIMER_CCD, &tmrptr->ccdr);
+ __raw_writel(0, &tmrptr->itmr);
+ txx9_tmrptr = tmrptr;
+
+ clockevent_set_clock(cd, TIMER_CLK(imbusclk));
+ cd->max_delta_ns =
+ clockevent_delta2ns(0xffffffff >> (32 - TXX9_TIMER_BITS), cd);
+ cd->min_delta_ns = clockevent_delta2ns(0xf, cd);
+ cd->irq = irq;
+ clockevents_register_device(cd);
+ setup_irq(irq, &txx9tmr_irq);
+ printk(KERN_INFO "TXx9: clockevent device at 0x%lx, irq %d\n",
+ baseaddr, irq);
+}
+
+void __init txx9_tmr_init(unsigned long baseaddr)
+{
+ struct txx9_tmr_reg __iomem *tmrptr;
+
+ tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg));
+ __raw_writel(TXx9_TMTCR_CRE, &tmrptr->tcr);
+ __raw_writel(0, &tmrptr->tisr);
+ __raw_writel(0xffffffff, &tmrptr->cpra);
+ __raw_writel(0, &tmrptr->itmr);
+ __raw_writel(0, &tmrptr->ccdr);
+ __raw_writel(0, &tmrptr->pgmr);
+ iounmap(tmrptr);
+}
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index c8c47a2d1972..5c2794391bf5 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -943,6 +943,11 @@ __init void cpu_probe(void)
}
__cpu_name[cpu] = cpu_to_name(c);
+
+ if (cpu_has_mips_r2)
+ c->srsets = ((read_c0_srsctl() >> 26) & 0x0f) + 1;
+ else
+ c->srsets = 1;
}
__init void cpu_report(void)
diff --git a/arch/mips/kernel/csrc-bcm1480.c b/arch/mips/kernel/csrc-bcm1480.c
new file mode 100644
index 000000000000..868745e7184b
--- /dev/null
+++ b/arch/mips/kernel/csrc-bcm1480.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2000,2001,2004 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <linux/clocksource.h>
+
+#include <asm/addrspace.h>
+#include <asm/io.h>
+#include <asm/time.h>
+
+#include <asm/sibyte/bcm1480_regs.h>
+#include <asm/sibyte/sb1250_regs.h>
+#include <asm/sibyte/bcm1480_int.h>
+#include <asm/sibyte/bcm1480_scd.h>
+
+#include <asm/sibyte/sb1250.h>
+
+static cycle_t bcm1480_hpt_read(void)
+{
+ return (cycle_t) __raw_readq(IOADDR(A_SCD_ZBBUS_CYCLE_COUNT));
+}
+
+struct clocksource bcm1480_clocksource = {
+ .name = "zbbus-cycles",
+ .rating = 200,
+ .read = bcm1480_hpt_read,
+ .mask = CLOCKSOURCE_MASK(64),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+void __init sb1480_clocksource_init(void)
+{
+ struct clocksource *cs = &bcm1480_clocksource;
+ unsigned int plldiv;
+ unsigned long zbbus;
+
+ plldiv = G_BCM1480_SYS_PLL_DIV(__raw_readq(IOADDR(A_SCD_SYSTEM_CFG)));
+ zbbus = ((plldiv >> 1) * 50000000) + ((plldiv & 1) * 25000000);
+ clocksource_set_clock(cs, zbbus);
+ clocksource_register(cs);
+}
diff --git a/arch/mips/kernel/csrc-sb1250.c b/arch/mips/kernel/csrc-sb1250.c
new file mode 100644
index 000000000000..92212bbb8e45
--- /dev/null
+++ b/arch/mips/kernel/csrc-sb1250.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2000, 2001 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <linux/clocksource.h>
+
+#include <asm/addrspace.h>
+#include <asm/io.h>
+#include <asm/time.h>
+
+#include <asm/sibyte/sb1250.h>
+#include <asm/sibyte/sb1250_regs.h>
+#include <asm/sibyte/sb1250_int.h>
+#include <asm/sibyte/sb1250_scd.h>
+
+#define SB1250_HPT_NUM 3
+#define SB1250_HPT_VALUE M_SCD_TIMER_CNT /* max value */
+
+/*
+ * The HPT is free running from SB1250_HPT_VALUE down to 0 then starts over
+ * again.
+ */
+static cycle_t sb1250_hpt_read(void)
+{
+ unsigned int count;
+
+ count = G_SCD_TIMER_CNT(__raw_readq(IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CNT))));
+
+ return SB1250_HPT_VALUE - count;
+}
+
+struct clocksource bcm1250_clocksource = {
+ .name = "bcm1250-counter-3",
+ .rating = 200,
+ .read = sb1250_hpt_read,
+ .mask = CLOCKSOURCE_MASK(23),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+void __init sb1250_clocksource_init(void)
+{
+ struct clocksource *cs = &bcm1250_clocksource;
+
+ /* Setup hpt using timer #3 but do not enable irq for it */
+ __raw_writeq(0,
+ IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM,
+ R_SCD_TIMER_CFG)));
+ __raw_writeq(SB1250_HPT_VALUE,
+ IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM,
+ R_SCD_TIMER_INIT)));
+ __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
+ IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM,
+ R_SCD_TIMER_CFG)));
+
+ clocksource_set_clock(cs, V_SCD_TIMER_FREQ);
+ clocksource_register(cs);
+}
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index c0f19d638b98..e76a76bf0b3d 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -146,7 +146,7 @@ NESTED(handle_int, PT_SIZE, sp)
and k0, ST0_IEP
bnez k0, 1f
- mfc0 k0, EP0_EPC
+ mfc0 k0, CP0_EPC
.set noreorder
j k0
rfe
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index e46782b0ebc8..236768731063 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -27,16 +27,6 @@
#include <kernel-entry-init.h>
- .macro ARC64_TWIDDLE_PC
-#if defined(CONFIG_ARC64) || defined(CONFIG_MAPPED_KERNEL)
- /* We get launched at a XKPHYS address but the kernel is linked to
- run at a KSEG0 address, so jump there. */
- PTR_LA t0, \@f
- jr t0
-\@:
-#endif
- .endm
-
/*
* inputs are the text nasid in t1, data nasid in t2.
*/
@@ -140,7 +130,7 @@
EXPORT(_stext)
-#ifndef CONFIG_BOOT_RAW
+#ifdef CONFIG_BOOT_RAW
/*
* Give us a fighting chance of running if execution beings at the
* kernel load address. This is needed because this platform does
@@ -149,13 +139,19 @@ EXPORT(_stext)
__INIT
#endif
+ __INIT_REFOK
+
NESTED(kernel_entry, 16, sp) # kernel entry point
kernel_entry_setup # cpu specific setup
setup_c0_status_pri
- ARC64_TWIDDLE_PC
+ /* We might not get launched at the address the kernel is linked to,
+ so we jump there. */
+ PTR_LA t0, 0f
+ jr t0
+0:
#ifdef CONFIG_MIPS_MT_SMTC
/*
diff --git a/arch/mips/kernel/i8253.c b/arch/mips/kernel/i8253.c
index 5d9830df3595..c2d497ceffdd 100644
--- a/arch/mips/kernel/i8253.c
+++ b/arch/mips/kernel/i8253.c
@@ -12,8 +12,9 @@
#include <asm/delay.h>
#include <asm/i8253.h>
#include <asm/io.h>
+#include <asm/time.h>
-static DEFINE_SPINLOCK(i8253_lock);
+DEFINE_SPINLOCK(i8253_lock);
/*
* Initialize the PIT timer.
@@ -87,11 +88,10 @@ struct clock_event_device pit_clockevent = {
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
.set_mode = init_pit_timer,
.set_next_event = pit_next_event,
- .shift = 32,
.irq = 0,
};
-irqreturn_t timer_interrupt(int irq, void *dev_id)
+static irqreturn_t timer_interrupt(int irq, void *dev_id)
{
pit_clockevent.event_handler(&pit_clockevent);
@@ -111,19 +111,20 @@ static struct irqaction irq0 = {
*/
void __init setup_pit_timer(void)
{
+ struct clock_event_device *cd = &pit_clockevent;
+ unsigned int cpu = smp_processor_id();
+
/*
* Start pit with the boot cpu mask and make it global after the
* IO_APIC has been initialized.
*/
- pit_clockevent.cpumask = cpumask_of_cpu(0);
- pit_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, 32);
- pit_clockevent.max_delta_ns =
- clockevent_delta2ns(0x7FFF, &pit_clockevent);
- pit_clockevent.min_delta_ns =
- clockevent_delta2ns(0xF, &pit_clockevent);
- clockevents_register_device(&pit_clockevent);
-
- irq0.mask = cpumask_of_cpu(0);
+ cd->cpumask = cpumask_of_cpu(cpu);
+ clockevent_set_clock(cd, CLOCK_TICK_RATE);
+ cd->max_delta_ns = clockevent_delta2ns(0x7FFF, cd);
+ cd->min_delta_ns = clockevent_delta2ns(0xF, cd);
+ clockevents_register_device(cd);
+
+ irq0.mask = cpumask_of_cpu(cpu);
setup_irq(0, &irq0);
}
diff --git a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c
index 8ef5cf4cc423..7852c7cdf29e 100644
--- a/arch/mips/kernel/irixelf.c
+++ b/arch/mips/kernel/irixelf.c
@@ -44,11 +44,14 @@
static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs);
static int load_irix_library(struct file *);
static int irix_core_dump(long signr, struct pt_regs * regs,
- struct file *file);
+ struct file *file, unsigned long limit);
static struct linux_binfmt irix_format = {
- NULL, THIS_MODULE, load_irix_binary, load_irix_library,
- irix_core_dump, PAGE_SIZE
+ .module = THIS_MODULE,
+ .load_binary = load_irix_binary,
+ .load_shlib = load_irix_library,
+ .core_dump = irix_core_dump,
+ .min_coredump = PAGE_SIZE,
};
/* Debugging routines. */
@@ -1088,7 +1091,7 @@ end_coredump:
* and then they are actually written out. If we run out of core limit
* we just truncate.
*/
-static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file)
+static int irix_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit)
{
int has_dumped = 0;
mm_segment_t fs;
@@ -1098,7 +1101,6 @@ static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file)
struct vm_area_struct *vma;
struct elfhdr elf;
off_t offset = 0, dataoff;
- int limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
int numnote = 3;
struct memelfnote notes[3];
struct elf_prstatus prstatus; /* NT_PRSTATUS */
@@ -1170,8 +1172,8 @@ static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file)
prstatus.pr_sighold = current->blocked.sig[0];
psinfo.pr_pid = prstatus.pr_pid = current->pid;
psinfo.pr_ppid = prstatus.pr_ppid = current->parent->pid;
- psinfo.pr_pgrp = prstatus.pr_pgrp = process_group(current);
- psinfo.pr_sid = prstatus.pr_sid = process_session(current);
+ psinfo.pr_pgrp = prstatus.pr_pgrp = task_pgrp_nr(current);
+ psinfo.pr_sid = prstatus.pr_sid = task_session_nr(current);
if (current->pid == current->tgid) {
/*
* This is the record for the group leader. Add in the
diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c
index 85c2e389edd6..5b10ac133ec8 100644
--- a/arch/mips/kernel/irixsig.c
+++ b/arch/mips/kernel/irixsig.c
@@ -24,8 +24,12 @@
#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
+#define _IRIX_NSIG 128
+#define _IRIX_NSIG_BPW BITS_PER_LONG
+#define _IRIX_NSIG_WORDS (_IRIX_NSIG / _IRIX_NSIG_BPW)
+
typedef struct {
- unsigned long sig[4];
+ unsigned long sig[_IRIX_NSIG_WORDS];
} irix_sigset_t;
struct sigctx_irix5 {
@@ -426,6 +430,7 @@ asmlinkage int irix_sigprocmask(int how, irix_sigset_t __user *new,
break;
default:
+ spin_unlock_irq(&current->sighand->siglock);
return -EINVAL;
}
recalc_sigpending();
@@ -527,7 +532,7 @@ asmlinkage int irix_sigpoll_sys(unsigned long __user *set,
expire = schedule_timeout_interruptible(expire);
- for (i=0; i<=4; i++)
+ for (i=0; i < _IRIX_NSIG_WORDS; i++)
tmp |= (current->pending.signal.sig[i] & kset.sig[i]);
if (tmp)
@@ -609,7 +614,7 @@ repeat:
p = list_entry(_p, struct task_struct, sibling);
if ((type == IRIX_P_PID) && p->pid != pid)
continue;
- if ((type == IRIX_P_PGID) && process_group(p) != pid)
+ if ((type == IRIX_P_PGID) && task_pgrp_nr(p) != pid)
continue;
if ((p->exit_signal != SIGCHLD))
continue;
diff --git a/arch/mips/kernel/irq-rm7000.c b/arch/mips/kernel/irq-rm7000.c
index 250732883488..971adf6ef4f4 100644
--- a/arch/mips/kernel/irq-rm7000.c
+++ b/arch/mips/kernel/irq-rm7000.c
@@ -44,5 +44,5 @@ void __init rm7k_cpu_irq_init(void)
for (i = base; i < base + 4; i++)
set_irq_chip_and_handler(i, &rm7k_irq_controller,
- handle_level_irq);
+ handle_percpu_irq);
}
diff --git a/arch/mips/kernel/irq-rm9000.c b/arch/mips/kernel/irq-rm9000.c
index ae83d2df6f31..7b04583bd800 100644
--- a/arch/mips/kernel/irq-rm9000.c
+++ b/arch/mips/kernel/irq-rm9000.c
@@ -104,5 +104,5 @@ void __init rm9k_cpu_irq_init(void)
rm9000_perfcount_irq = base + 1;
set_irq_chip_and_handler(rm9000_perfcount_irq, &rm9k_perfcounter_irq,
- handle_level_irq);
+ handle_percpu_irq);
}
diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c
index 7b66e03b5899..0ee2567b780d 100644
--- a/arch/mips/kernel/irq_cpu.c
+++ b/arch/mips/kernel/irq_cpu.c
@@ -116,5 +116,5 @@ void __init mips_cpu_irq_init(void)
for (i = irq_base + 2; i < irq_base + 8; i++)
set_irq_chip_and_handler(i, &mips_cpu_irq_controller,
- handle_level_irq);
+ handle_percpu_irq);
}
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index d6e01215fb2b..2b8ec1102e86 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -35,12 +35,12 @@
#include <linux/security.h>
#include <linux/compat.h>
#include <linux/vfs.h>
+#include <linux/ipc.h>
#include <net/sock.h>
#include <net/scm.h>
#include <asm/compat-signal.h>
-#include <asm/ipc.h>
#include <asm/sim.h>
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c
index cb0801437b66..e7ed0ac48537 100644
--- a/arch/mips/kernel/module.c
+++ b/arch/mips/kernel/module.c
@@ -381,7 +381,7 @@ const struct exception_table_entry *search_module_dbetables(unsigned long addr)
return e;
}
-/* Put in dbe list if neccessary. */
+/* Put in dbe list if necessary. */
int module_finalize(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs,
struct module *me)
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
index efd2d1314123..6e6e947cce1e 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -60,6 +60,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
cpu_has_dsp ? " dsp" : "",
cpu_has_mipsmt ? " mt" : ""
);
+ seq_printf(m, "shadow register sets\t: %d\n",
+ cpu_data[n].srsets);
sprintf(fmt, "VCE%%c exceptions\t\t: %s\n",
cpu_has_vce ? "%u" : "not available");
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 58aa6fec1146..35234b92b9a5 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -65,13 +65,13 @@ int ptrace_getregs(struct task_struct *child, __s64 __user *data)
regs = task_pt_regs(child);
for (i = 0; i < 32; i++)
- __put_user(regs->regs[i], data + i);
- __put_user(regs->lo, data + EF_LO - EF_R0);
- __put_user(regs->hi, data + EF_HI - EF_R0);
- __put_user(regs->cp0_epc, data + EF_CP0_EPC - EF_R0);
- __put_user(regs->cp0_badvaddr, data + EF_CP0_BADVADDR - EF_R0);
- __put_user(regs->cp0_status, data + EF_CP0_STATUS - EF_R0);
- __put_user(regs->cp0_cause, data + EF_CP0_CAUSE - EF_R0);
+ __put_user((long)regs->regs[i], data + i);
+ __put_user((long)regs->lo, data + EF_LO - EF_R0);
+ __put_user((long)regs->hi, data + EF_HI - EF_R0);
+ __put_user((long)regs->cp0_epc, data + EF_CP0_EPC - EF_R0);
+ __put_user((long)regs->cp0_badvaddr, data + EF_CP0_BADVADDR - EF_R0);
+ __put_user((long)regs->cp0_status, data + EF_CP0_STATUS - EF_R0);
+ __put_user((long)regs->cp0_cause, data + EF_CP0_CAUSE - EF_R0);
return 0;
}
@@ -390,11 +390,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
}
case PTRACE_GETREGS:
- ret = ptrace_getregs(child, (__u64 __user *) data);
+ ret = ptrace_getregs(child, (__s64 __user *) data);
break;
case PTRACE_SETREGS:
- ret = ptrace_setregs(child, (__u64 __user *) data);
+ ret = ptrace_setregs(child, (__s64 __user *) data);
break;
case PTRACE_GETFPREGS:
@@ -435,10 +435,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
wake_up_process(child);
break;
- case PTRACE_DETACH: /* detach a process that was attached. */
- ret = ptrace_detach(child, data);
- break;
-
case PTRACE_GET_THREAD_AREA:
ret = put_user(task_thread_info(child)->tp_value,
(unsigned long __user *) data);
diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c
index f2bffed94fa3..76818be6ba7c 100644
--- a/arch/mips/kernel/ptrace32.c
+++ b/arch/mips/kernel/ptrace32.c
@@ -346,11 +346,11 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
}
case PTRACE_GETREGS:
- ret = ptrace_getregs(child, (__u64 __user *) (__u64) data);
+ ret = ptrace_getregs(child, (__s64 __user *) (__u64) data);
break;
case PTRACE_SETREGS:
- ret = ptrace_setregs(child, (__u64 __user *) (__u64) data);
+ ret = ptrace_setregs(child, (__s64 __user *) (__u64) data);
break;
case PTRACE_GETFPREGS:
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 118be24224f2..01993ec3368b 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -293,7 +293,7 @@ EXPORT(sysn32_call_table)
PTR sys_ni_syscall /* 6170, was get_kernel_syms */
PTR sys_ni_syscall /* was query_module */
PTR sys_quotactl
- PTR sys_nfsservctl
+ PTR compat_sys_nfsservctl
PTR sys_ni_syscall /* res. for getpmsg */
PTR sys_ni_syscall /* 6175 for putpmsg */
PTR sys_ni_syscall /* res. for afs_syscall */
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index a8c1a698d588..9c92d42996cb 100644
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -88,11 +88,19 @@ unsigned int smtc_status = 0;
/* Boot command line configuration overrides */
+static int vpe0limit;
static int ipibuffers = 0;
static int nostlb = 0;
static int asidmask = 0;
unsigned long smtc_asid_mask = 0xff;
+static int __init vpe0tcs(char *str)
+{
+ get_option(&str, &vpe0limit);
+
+ return 1;
+}
+
static int __init ipibufs(char *str)
{
get_option(&str, &ipibuffers);
@@ -125,6 +133,7 @@ static int __init asidmask_set(char *str)
return 1;
}
+__setup("vpe0tcs=", vpe0tcs);
__setup("ipibufs=", ipibufs);
__setup("nostlb", stlb_disable);
__setup("asidmask=", asidmask_set);
@@ -340,7 +349,7 @@ static void smtc_tc_setup(int vpe, int tc, int cpu)
void mipsmt_prepare_cpus(void)
{
- int i, vpe, tc, ntc, nvpe, tcpervpe, slop, cpu;
+ int i, vpe, tc, ntc, nvpe, tcpervpe[NR_CPUS], slop, cpu;
unsigned long flags;
unsigned long val;
int nipi;
@@ -401,8 +410,39 @@ void mipsmt_prepare_cpus(void)
ntc = NR_CPUS;
if (tclimit > 0 && ntc > tclimit)
ntc = tclimit;
- tcpervpe = ntc / nvpe;
- slop = ntc % nvpe; /* Residual TCs, < NVPE */
+ slop = ntc % nvpe;
+ for (i = 0; i < nvpe; i++) {
+ tcpervpe[i] = ntc / nvpe;
+ if (slop) {
+ if((slop - i) > 0) tcpervpe[i]++;
+ }
+ }
+ /* Handle command line override for VPE0 */
+ if (vpe0limit > ntc) vpe0limit = ntc;
+ if (vpe0limit > 0) {
+ int slopslop;
+ if (vpe0limit < tcpervpe[0]) {
+ /* Reducing TC count - distribute to others */
+ slop = tcpervpe[0] - vpe0limit;
+ slopslop = slop % (nvpe - 1);
+ tcpervpe[0] = vpe0limit;
+ for (i = 1; i < nvpe; i++) {
+ tcpervpe[i] += slop / (nvpe - 1);
+ if(slopslop && ((slopslop - (i - 1) > 0)))
+ tcpervpe[i]++;
+ }
+ } else if (vpe0limit > tcpervpe[0]) {
+ /* Increasing TC count - steal from others */
+ slop = vpe0limit - tcpervpe[0];
+ slopslop = slop % (nvpe - 1);
+ tcpervpe[0] = vpe0limit;
+ for (i = 1; i < nvpe; i++) {
+ tcpervpe[i] -= slop / (nvpe - 1);
+ if(slopslop && ((slopslop - (i - 1) > 0)))
+ tcpervpe[i]--;
+ }
+ }
+ }
/* Set up shared TLB */
smtc_configure_tlb();
@@ -416,7 +456,7 @@ void mipsmt_prepare_cpus(void)
if (vpe != 0)
printk(", ");
printk("VPE %d: TC", vpe);
- for (i = 0; i < tcpervpe; i++) {
+ for (i = 0; i < tcpervpe[vpe]; i++) {
/*
* TC 0 is bound to VPE 0 at reset,
* and is presumably executing this
@@ -429,15 +469,6 @@ void mipsmt_prepare_cpus(void)
printk(" %d", tc);
tc++;
}
- if (slop) {
- if (tc != 0) {
- smtc_tc_setup(vpe, tc, cpu);
- cpu++;
- }
- printk(" %d", tc);
- tc++;
- slop--;
- }
if (vpe != 0) {
/*
* Clear any stale software interrupts from VPE's Cause
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index 17c4374d2209..af1bdc897488 100644
--- a/arch/mips/kernel/syscall.c
+++ b/arch/mips/kernel/syscall.c
@@ -28,11 +28,11 @@
#include <linux/shm.h>
#include <linux/compiler.h>
#include <linux/module.h>
+#include <linux/ipc.h>
#include <asm/branch.h>
#include <asm/cachectl.h>
#include <asm/cacheflush.h>
-#include <asm/ipc.h>
#include <asm/asm-offsets.h>
#include <asm/signal.h>
#include <asm/sim.h>
@@ -73,7 +73,14 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
task_size = STACK_TOP;
+ if (len > task_size)
+ return -ENOMEM;
+
if (flags & MAP_FIXED) {
+ /* Even MAP_FIXED mappings must reside within task_size. */
+ if (task_size - len < addr)
+ return -EINVAL;
+
/*
* We do not accept a shared mapping if it would violate
* cache aliasing constraints.
@@ -83,8 +90,6 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
return addr;
}
- if (len > task_size)
- return -ENOMEM;
do_color_align = 0;
if (filp || (flags & MAP_SHARED))
do_color_align = 1;
diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c
index ee7790d9debe..4c477c7ff74a 100644
--- a/arch/mips/kernel/sysirix.c
+++ b/arch/mips/kernel/sysirix.c
@@ -763,11 +763,11 @@ asmlinkage int irix_setpgrp(int flags)
printk("[%s:%d] setpgrp(%d) ", current->comm, current->pid, flags);
#endif
if(!flags)
- error = process_group(current);
+ error = task_pgrp_nr(current);
else
error = sys_setsid();
#ifdef DEBUG_PROCGRPS
- printk("returning %d\n", process_group(current));
+ printk("returning %d\n", task_pgrp_nr(current));
#endif
return error;
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index 5892491b40eb..3284b9b4ecac 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -3,53 +3,31 @@
* Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
* Copyright (c) 2003, 2004 Maciej W. Rozycki
*
- * Common time service routines for MIPS machines. See
- * Documentation/mips/time.README.
+ * Common time service routines for MIPS machines.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
+#include <linux/bug.h>
#include <linux/clockchips.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/param.h>
-#include <linux/profile.h>
#include <linux/time.h>
#include <linux/timex.h>
#include <linux/smp.h>
-#include <linux/kernel_stat.h>
#include <linux/spinlock.h>
-#include <linux/interrupt.h>
#include <linux/module.h>
-#include <linux/kallsyms.h>
-#include <asm/bootinfo.h>
-#include <asm/cache.h>
-#include <asm/compiler.h>
-#include <asm/cpu.h>
#include <asm/cpu-features.h>
#include <asm/div64.h>
-#include <asm/sections.h>
#include <asm/smtc_ipi.h>
#include <asm/time.h>
-#include <irq.h>
-
-/*
- * The integer part of the number of usecs per jiffy is taken from tick,
- * but the fractional part is not recorded, so we calculate it using the
- * initial value of HZ. This aids systems where tick isn't really an
- * integer (e.g. for HZ = 128).
- */
-#define USECS_PER_JIFFY TICK_SIZE
-#define USECS_PER_JIFFY_FRAC ((unsigned long)(u32)((1000000ULL << 32) / HZ))
-
-#define TICK_SIZE (tick_nsec / 1000)
-
/*
* forward reference
*/
@@ -72,30 +50,6 @@ int update_persistent_clock(struct timespec now)
return rtc_mips_set_mmss(now.tv_sec);
}
-/* how many counter cycles in a jiffy */
-static unsigned long cycles_per_jiffy __read_mostly;
-
-/*
- * Null timer ack for systems not needing one (e.g. i8254).
- */
-static void null_timer_ack(void) { /* nothing */ }
-
-/*
- * Null high precision timer functions for systems lacking one.
- */
-static cycle_t null_hpt_read(void)
-{
- return 0;
-}
-
-/*
- * Timer ack for an R4k-compatible timer of a known frequency.
- */
-static void c0_timer_ack(void)
-{
- write_c0_compare(read_c0_compare());
-}
-
/*
* High precision timer functions for a R4k-compatible timer.
*/
@@ -105,23 +59,6 @@ static cycle_t c0_hpt_read(void)
}
int (*mips_timer_state)(void);
-void (*mips_timer_ack)(void);
-
-/*
- * local_timer_interrupt() does profiling and process accounting
- * on a per-CPU basis.
- *
- * In UP mode, it is invoked from the (global) timer_interrupt.
- *
- * In SMP mode, it might invoked by per-CPU timer interrupt, or
- * a broadcasted inter-processor interrupt which itself is triggered
- * by the global timer interrupt.
- */
-void local_timer_interrupt(int irq, void *dev_id)
-{
- profile_tick(CPU_PROFILING);
- update_process_times(user_mode(get_irq_regs()));
-}
int null_perf_irq(void)
{
@@ -135,35 +72,6 @@ int (*perf_irq)(void) = null_perf_irq;
EXPORT_SYMBOL(perf_irq);
/*
- * Timer interrupt
- */
-int cp0_compare_irq;
-
-/*
- * Performance counter IRQ or -1 if shared with timer
- */
-int cp0_perfcount_irq;
-EXPORT_SYMBOL_GPL(cp0_perfcount_irq);
-
-/*
- * Possibly handle a performance counter interrupt.
- * Return true if the timer interrupt should not be checked
- */
-static inline int handle_perf_irq(int r2)
-{
- /*
- * The performance counter overflow interrupt may be shared with the
- * timer interrupt (cp0_perfcount_irq < 0). If it is and a
- * performance counter has overflowed (perf_irq() == IRQ_HANDLED)
- * and we can't reliably determine if a counter interrupt has also
- * happened (!r2) then don't check for a timer interrupt.
- */
- return (cp0_perfcount_irq < 0) &&
- perf_irq() == IRQ_HANDLED &&
- !r2;
-}
-
-/*
* time_init() - it does the following things.
*
* 1) plat_time_init() -
@@ -172,14 +80,17 @@ static inline int handle_perf_irq(int r2)
* (only needed if you intended to use cpu counter as timer interrupt
* source)
* 2) calculate a couple of cached variables for later usage
- * 3) plat_timer_setup() -
- * a) (optional) over-write any choices made above by time_init().
- * b) machine specific code should setup the timer irqaction.
- * c) enable the timer interrupt
*/
unsigned int mips_hpt_frequency;
+static struct clocksource clocksource_mips = {
+ .name = "MIPS",
+ .read = c0_hpt_read,
+ .mask = CLOCKSOURCE_MASK(32),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
static unsigned int __init calibrate_hpt(void)
{
cycle_t frequency, hpt_start, hpt_end, hpt_count, hz;
@@ -222,258 +133,73 @@ static unsigned int __init calibrate_hpt(void)
return frequency >> log_2_loops;
}
-struct clocksource clocksource_mips = {
- .name = "MIPS",
- .mask = CLOCKSOURCE_MASK(32),
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-static int mips_next_event(unsigned long delta,
- struct clock_event_device *evt)
-{
- unsigned int cnt;
- int res;
-
-#ifdef CONFIG_MIPS_MT_SMTC
- {
- unsigned long flags, vpflags;
- local_irq_save(flags);
- vpflags = dvpe();
-#endif
- cnt = read_c0_count();
- cnt += delta;
- write_c0_compare(cnt);
- res = ((long)(read_c0_count() - cnt ) > 0) ? -ETIME : 0;
-#ifdef CONFIG_MIPS_MT_SMTC
- evpe(vpflags);
- local_irq_restore(flags);
- }
-#endif
- return res;
-}
-
-static void mips_set_mode(enum clock_event_mode mode,
- struct clock_event_device *evt)
-{
- /* Nothing to do ... */
-}
-
-static DEFINE_PER_CPU(struct clock_event_device, mips_clockevent_device);
-static int cp0_timer_irq_installed;
-
-static irqreturn_t timer_interrupt(int irq, void *dev_id)
-{
- const int r2 = cpu_has_mips_r2;
- struct clock_event_device *cd;
- int cpu = smp_processor_id();
-
- /*
- * Suckage alert:
- * Before R2 of the architecture there was no way to see if a
- * performance counter interrupt was pending, so we have to run
- * the performance counter interrupt handler anyway.
- */
- if (handle_perf_irq(r2))
- goto out;
-
- /*
- * The same applies to performance counter interrupts. But with the
- * above we now know that the reason we got here must be a timer
- * interrupt. Being the paranoiacs we are we check anyway.
- */
- if (!r2 || (read_c0_cause() & (1 << 30))) {
- c0_timer_ack();
-#ifdef CONFIG_MIPS_MT_SMTC
- if (cpu_data[cpu].vpe_id)
- goto out;
- cpu = 0;
-#endif
- cd = &per_cpu(mips_clockevent_device, cpu);
- cd->event_handler(cd);
- }
-
-out:
- return IRQ_HANDLED;
-}
-
-static struct irqaction timer_irqaction = {
- .handler = timer_interrupt,
-#ifdef CONFIG_MIPS_MT_SMTC
- .flags = IRQF_DISABLED,
-#else
- .flags = IRQF_DISABLED | IRQF_PERCPU,
-#endif
- .name = "timer",
-};
-
-static void __init init_mips_clocksource(void)
+void __init clocksource_set_clock(struct clocksource *cs, unsigned int clock)
{
u64 temp;
u32 shift;
- if (!mips_hpt_frequency || clocksource_mips.read == null_hpt_read)
- return;
-
- /* Calclate a somewhat reasonable rating value */
- clocksource_mips.rating = 200 + mips_hpt_frequency / 10000000;
/* Find a shift value */
for (shift = 32; shift > 0; shift--) {
temp = (u64) NSEC_PER_SEC << shift;
- do_div(temp, mips_hpt_frequency);
+ do_div(temp, clock);
if ((temp >> 32) == 0)
break;
}
- clocksource_mips.shift = shift;
- clocksource_mips.mult = (u32)temp;
-
- clocksource_register(&clocksource_mips);
-}
-
-void __init __weak plat_time_init(void)
-{
+ cs->shift = shift;
+ cs->mult = (u32) temp;
}
-void __init __weak plat_timer_setup(struct irqaction *irq)
+void __cpuinit clockevent_set_clock(struct clock_event_device *cd,
+ unsigned int clock)
{
-}
-
-#ifdef CONFIG_MIPS_MT_SMTC
-DEFINE_PER_CPU(struct clock_event_device, smtc_dummy_clockevent_device);
-
-static void smtc_set_mode(enum clock_event_mode mode,
- struct clock_event_device *evt)
-{
-}
-
-int dummycnt[NR_CPUS];
-
-static void mips_broadcast(cpumask_t mask)
-{
- unsigned int cpu;
+ u64 temp;
+ u32 shift;
- for_each_cpu_mask(cpu, mask)
- smtc_send_ipi(cpu, SMTC_CLOCK_TICK, 0);
+ /* Find a shift value */
+ for (shift = 32; shift > 0; shift--) {
+ temp = (u64) clock << shift;
+ do_div(temp, NSEC_PER_SEC);
+ if ((temp >> 32) == 0)
+ break;
+ }
+ cd->shift = shift;
+ cd->mult = (u32) temp;
}
-static void setup_smtc_dummy_clockevent_device(void)
+static void __init init_mips_clocksource(void)
{
- //uint64_t mips_freq = mips_hpt_^frequency;
- unsigned int cpu = smp_processor_id();
- struct clock_event_device *cd;
-
- cd = &per_cpu(smtc_dummy_clockevent_device, cpu);
-
- cd->name = "SMTC";
- cd->features = CLOCK_EVT_FEAT_DUMMY;
-
- /* Calculate the min / max delta */
- cd->mult = 0; //div_sc((unsigned long) mips_freq, NSEC_PER_SEC, 32);
- cd->shift = 0; //32;
- cd->max_delta_ns = 0; //clockevent_delta2ns(0x7fffffff, cd);
- cd->min_delta_ns = 0; //clockevent_delta2ns(0x30, cd);
-
- cd->rating = 200;
- cd->irq = 17; //-1;
-// if (cpu)
-// cd->cpumask = CPU_MASK_ALL; // cpumask_of_cpu(cpu);
-// else
- cd->cpumask = cpumask_of_cpu(cpu);
-
- cd->set_mode = smtc_set_mode;
+ /* Calclate a somewhat reasonable rating value */
+ clocksource_mips.rating = 200 + mips_hpt_frequency / 10000000;
- cd->broadcast = mips_broadcast;
+ clocksource_set_clock(&clocksource_mips, mips_hpt_frequency);
- clockevents_register_device(cd);
+ clocksource_register(&clocksource_mips);
}
-#endif
-static void mips_event_handler(struct clock_event_device *dev)
+void __init __weak plat_time_init(void)
{
}
-void __cpuinit mips_clockevent_init(void)
+/*
+ * This function exists in order to cause an error due to a duplicate
+ * definition if platform code should have its own implementation. The hook
+ * to use instead is plat_time_init. plat_time_init does not receive the
+ * irqaction pointer argument anymore. This is because any function which
+ * initializes an interrupt timer now takes care of its own request_irq rsp.
+ * setup_irq calls and each clock_event_device should use its own
+ * struct irqrequest.
+ */
+void __init plat_timer_setup(void)
{
- uint64_t mips_freq = mips_hpt_frequency;
- unsigned int cpu = smp_processor_id();
- struct clock_event_device *cd;
- unsigned int irq = MIPS_CPU_IRQ_BASE + 7;
-
- if (!cpu_has_counter)
- return;
-
-#ifdef CONFIG_MIPS_MT_SMTC
- setup_smtc_dummy_clockevent_device();
-
- /*
- * On SMTC we only register VPE0's compare interrupt as clockevent
- * device.
- */
- if (cpu)
- return;
-#endif
-
- cd = &per_cpu(mips_clockevent_device, cpu);
-
- cd->name = "MIPS";
- cd->features = CLOCK_EVT_FEAT_ONESHOT;
-
- /* Calculate the min / max delta */
- cd->mult = div_sc((unsigned long) mips_freq, NSEC_PER_SEC, 32);
- cd->shift = 32;
- cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd);
- cd->min_delta_ns = clockevent_delta2ns(0x30, cd);
-
- cd->rating = 300;
- cd->irq = irq;
-#ifdef CONFIG_MIPS_MT_SMTC
- cd->cpumask = CPU_MASK_ALL;
-#else
- cd->cpumask = cpumask_of_cpu(cpu);
-#endif
- cd->set_next_event = mips_next_event;
- cd->set_mode = mips_set_mode;
- cd->event_handler = mips_event_handler;
-
- clockevents_register_device(cd);
-
- if (!cp0_timer_irq_installed) {
-#ifdef CONFIG_MIPS_MT_SMTC
-#define CPUCTR_IMASKBIT (0x100 << cp0_compare_irq)
- setup_irq_smtc(irq, &timer_irqaction, CPUCTR_IMASKBIT);
-#else
- setup_irq(irq, &timer_irqaction);
-#endif /* CONFIG_MIPS_MT_SMTC */
- cp0_timer_irq_installed = 1;
- }
+ BUG();
}
void __init time_init(void)
{
plat_time_init();
- /* Choose appropriate high precision timer routines. */
- if (!cpu_has_counter && !clocksource_mips.read)
- /* No high precision timer -- sorry. */
- clocksource_mips.read = null_hpt_read;
- else if (!mips_hpt_frequency && !mips_timer_state) {
- /* A high precision timer of unknown frequency. */
- if (!clocksource_mips.read)
- /* No external high precision timer -- use R4k. */
- clocksource_mips.read = c0_hpt_read;
- } else {
+ if (cpu_has_counter && (mips_hpt_frequency || mips_timer_state)) {
/* We know counter frequency. Or we can get it. */
- if (!clocksource_mips.read) {
- /* No external high precision timer -- use R4k. */
- clocksource_mips.read = c0_hpt_read;
-
- if (!mips_timer_state) {
- /* No external timer interrupt -- use R4k. */
- mips_timer_ack = c0_timer_ack;
- /* Calculate cache parameters. */
- cycles_per_jiffy =
- (mips_hpt_frequency + HZ / 2) / HZ;
- }
- }
if (!mips_hpt_frequency)
mips_hpt_frequency = calibrate_hpt();
@@ -481,29 +207,8 @@ void __init time_init(void)
printk("Using %u.%03u MHz high precision timer.\n",
((mips_hpt_frequency + 500) / 1000) / 1000,
((mips_hpt_frequency + 500) / 1000) % 1000);
-
-#ifdef CONFIG_IRQ_CPU
- setup_irq(MIPS_CPU_IRQ_BASE + 7, &timer_irqaction);
-#endif
+ init_mips_clocksource();
}
- if (!mips_timer_ack)
- /* No timer interrupt ack (e.g. i8254). */
- mips_timer_ack = null_timer_ack;
-
- /*
- * Call board specific timer interrupt setup.
- *
- * this pointer must be setup in machine setup routine.
- *
- * Even if a machine chooses to use a low-level timer interrupt,
- * it still needs to setup the timer_irqaction.
- * In that case, it might be better to set timer_irqaction.handler
- * to be NULL function so that we are sure the high-level code
- * is not invoked accidentally.
- */
- plat_timer_setup(&timer_irqaction);
-
- init_mips_clocksource();
mips_clockevent_init();
}
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 632bce1bf420..23e73d0650a3 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -9,9 +9,10 @@
* Copyright (C) 1999 Silicon Graphics, Inc.
* Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
* Copyright (C) 2000, 01 MIPS Technologies, Inc.
- * Copyright (C) 2002, 2003, 2004, 2005 Maciej W. Rozycki
+ * Copyright (C) 2002, 2003, 2004, 2005, 2007 Maciej W. Rozycki
*/
#include <linux/bug.h>
+#include <linux/compiler.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
@@ -104,7 +105,7 @@ static int __init set_raw_show_trace(char *str)
__setup("raw_show_trace", set_raw_show_trace);
#endif
-static void show_backtrace(struct task_struct *task, struct pt_regs *regs)
+static void show_backtrace(struct task_struct *task, const struct pt_regs *regs)
{
unsigned long sp = regs->regs[29];
unsigned long ra = regs->regs[31];
@@ -126,7 +127,8 @@ static void show_backtrace(struct task_struct *task, struct pt_regs *regs)
* This routine abuses get_user()/put_user() to reference pointers
* with at least a bit of error checking ...
*/
-static void show_stacktrace(struct task_struct *task, struct pt_regs *regs)
+static void show_stacktrace(struct task_struct *task,
+ const struct pt_regs *regs)
{
const int field = 2 * sizeof(unsigned long);
long stackdata;
@@ -203,7 +205,7 @@ static void show_code(unsigned int __user *pc)
}
}
-void show_regs(struct pt_regs *regs)
+static void __show_regs(const struct pt_regs *regs)
{
const int field = 2 * sizeof(unsigned long);
unsigned int cause = regs->cp0_cause;
@@ -299,12 +301,20 @@ void show_regs(struct pt_regs *regs)
cpu_name_string());
}
-void show_registers(struct pt_regs *regs)
+/*
+ * FIXME: really the generic show_regs should take a const pointer argument.
+ */
+void show_regs(struct pt_regs *regs)
{
- show_regs(regs);
+ __show_regs((struct pt_regs *)regs);
+}
+
+void show_registers(const struct pt_regs *regs)
+{
+ __show_regs(regs);
print_modules();
printk("Process %s (pid: %d, threadinfo=%p, task=%p)\n",
- current->comm, current->pid, current_thread_info(), current);
+ current->comm, task_pid_nr(current), current_thread_info(), current);
show_stacktrace(current, regs);
show_code((unsigned int __user *) regs->cp0_epc);
printk("\n");
@@ -312,7 +322,7 @@ void show_registers(struct pt_regs *regs)
static DEFINE_SPINLOCK(die_lock);
-void __noreturn die(const char * str, struct pt_regs * regs)
+void __noreturn die(const char * str, const struct pt_regs * regs)
{
static int die_counter;
#ifdef CONFIG_MIPS_MT_SMTC
@@ -401,7 +411,7 @@ asmlinkage void do_be(struct pt_regs *regs)
}
/*
- * ll/sc emulation
+ * ll/sc, rdhwr, sync emulation
*/
#define OPCODE 0xfc000000
@@ -410,9 +420,11 @@ asmlinkage void do_be(struct pt_regs *regs)
#define OFFSET 0x0000ffff
#define LL 0xc0000000
#define SC 0xe0000000
+#define SPEC0 0x00000000
#define SPEC3 0x7c000000
#define RD 0x0000f800
#define FUNC 0x0000003f
+#define SYNC 0x0000000f
#define RDHWR 0x0000003b
/*
@@ -423,11 +435,10 @@ unsigned long ll_bit;
static struct task_struct *ll_task = NULL;
-static inline void simulate_ll(struct pt_regs *regs, unsigned int opcode)
+static inline int simulate_ll(struct pt_regs *regs, unsigned int opcode)
{
unsigned long value, __user *vaddr;
long offset;
- int signal = 0;
/*
* analyse the ll instruction that just caused a ri exception
@@ -442,14 +453,10 @@ static inline void simulate_ll(struct pt_regs *regs, unsigned int opcode)
vaddr = (unsigned long __user *)
((unsigned long)(regs->regs[(opcode & BASE) >> 21]) + offset);
- if ((unsigned long)vaddr & 3) {
- signal = SIGBUS;
- goto sig;
- }
- if (get_user(value, vaddr)) {
- signal = SIGSEGV;
- goto sig;
- }
+ if ((unsigned long)vaddr & 3)
+ return SIGBUS;
+ if (get_user(value, vaddr))
+ return SIGSEGV;
preempt_disable();
@@ -462,22 +469,16 @@ static inline void simulate_ll(struct pt_regs *regs, unsigned int opcode)
preempt_enable();
- compute_return_epc(regs);
-
regs->regs[(opcode & RT) >> 16] = value;
- return;
-
-sig:
- force_sig(signal, current);
+ return 0;
}
-static inline void simulate_sc(struct pt_regs *regs, unsigned int opcode)
+static inline int simulate_sc(struct pt_regs *regs, unsigned int opcode)
{
unsigned long __user *vaddr;
unsigned long reg;
long offset;
- int signal = 0;
/*
* analyse the sc instruction that just caused a ri exception
@@ -493,34 +494,25 @@ static inline void simulate_sc(struct pt_regs *regs, unsigned int opcode)
((unsigned long)(regs->regs[(opcode & BASE) >> 21]) + offset);
reg = (opcode & RT) >> 16;
- if ((unsigned long)vaddr & 3) {
- signal = SIGBUS;
- goto sig;
- }
+ if ((unsigned long)vaddr & 3)
+ return SIGBUS;
preempt_disable();
if (ll_bit == 0 || ll_task != current) {
- compute_return_epc(regs);
regs->regs[reg] = 0;
preempt_enable();
- return;
+ return 0;
}
preempt_enable();
- if (put_user(regs->regs[reg], vaddr)) {
- signal = SIGSEGV;
- goto sig;
- }
+ if (put_user(regs->regs[reg], vaddr))
+ return SIGSEGV;
- compute_return_epc(regs);
regs->regs[reg] = 1;
- return;
-
-sig:
- force_sig(signal, current);
+ return 0;
}
/*
@@ -530,27 +522,14 @@ sig:
* few processors such as NEC's VR4100 throw reserved instruction exceptions
* instead, so we're doing the emulation thing in both exception handlers.
*/
-static inline int simulate_llsc(struct pt_regs *regs)
+static int simulate_llsc(struct pt_regs *regs, unsigned int opcode)
{
- unsigned int opcode;
-
- if (get_user(opcode, (unsigned int __user *) exception_epc(regs)))
- goto out_sigsegv;
+ if ((opcode & OPCODE) == LL)
+ return simulate_ll(regs, opcode);
+ if ((opcode & OPCODE) == SC)
+ return simulate_sc(regs, opcode);
- if ((opcode & OPCODE) == LL) {
- simulate_ll(regs, opcode);
- return 0;
- }
- if ((opcode & OPCODE) == SC) {
- simulate_sc(regs, opcode);
- return 0;
- }
-
- return -EFAULT; /* Strange things going on ... */
-
-out_sigsegv:
- force_sig(SIGSEGV, current);
- return -EFAULT;
+ return -1; /* Must be something else ... */
}
/*
@@ -558,16 +537,9 @@ out_sigsegv:
* registers not implemented in hardware. The only current use of this
* is the thread area pointer.
*/
-static inline int simulate_rdhwr(struct pt_regs *regs)
+static int simulate_rdhwr(struct pt_regs *regs, unsigned int opcode)
{
struct thread_info *ti = task_thread_info(current);
- unsigned int opcode;
-
- if (get_user(opcode, (unsigned int __user *) exception_epc(regs)))
- goto out_sigsegv;
-
- if (unlikely(compute_return_epc(regs)))
- return -EFAULT;
if ((opcode & OPCODE) == SPEC3 && (opcode & FUNC) == RDHWR) {
int rd = (opcode & RD) >> 11;
@@ -577,16 +549,20 @@ static inline int simulate_rdhwr(struct pt_regs *regs)
regs->regs[rt] = ti->tp_value;
return 0;
default:
- return -EFAULT;
+ return -1;
}
}
/* Not ours. */
- return -EFAULT;
+ return -1;
+}
-out_sigsegv:
- force_sig(SIGSEGV, current);
- return -EFAULT;
+static int simulate_sync(struct pt_regs *regs, unsigned int opcode)
+{
+ if ((opcode & OPCODE) == SPEC0 && (opcode & FUNC) == SYNC)
+ return 0;
+
+ return -1; /* Must be something else ... */
}
asmlinkage void do_ov(struct pt_regs *regs)
@@ -758,16 +734,35 @@ out_sigsegv:
asmlinkage void do_ri(struct pt_regs *regs)
{
- die_if_kernel("Reserved instruction in kernel code", regs);
+ unsigned int __user *epc = (unsigned int __user *)exception_epc(regs);
+ unsigned long old_epc = regs->cp0_epc;
+ unsigned int opcode = 0;
+ int status = -1;
- if (!cpu_has_llsc)
- if (!simulate_llsc(regs))
- return;
+ die_if_kernel("Reserved instruction in kernel code", regs);
- if (!simulate_rdhwr(regs))
+ if (unlikely(compute_return_epc(regs) < 0))
return;
- force_sig(SIGILL, current);
+ if (unlikely(get_user(opcode, epc) < 0))
+ status = SIGSEGV;
+
+ if (!cpu_has_llsc && status < 0)
+ status = simulate_llsc(regs, opcode);
+
+ if (status < 0)
+ status = simulate_rdhwr(regs, opcode);
+
+ if (status < 0)
+ status = simulate_sync(regs, opcode);
+
+ if (status < 0)
+ status = SIGILL;
+
+ if (unlikely(status > 0)) {
+ regs->cp0_epc = old_epc; /* Undo skip-over. */
+ force_sig(status, current);
+ }
}
/*
@@ -799,7 +794,11 @@ static void mt_ase_fp_affinity(void)
asmlinkage void do_cpu(struct pt_regs *regs)
{
+ unsigned int __user *epc;
+ unsigned long old_epc;
+ unsigned int opcode;
unsigned int cpid;
+ int status;
die_if_kernel("do_cpu invoked from kernel context!", regs);
@@ -807,14 +806,32 @@ asmlinkage void do_cpu(struct pt_regs *regs)
switch (cpid) {
case 0:
- if (!cpu_has_llsc)
- if (!simulate_llsc(regs))
- return;
+ epc = (unsigned int __user *)exception_epc(regs);
+ old_epc = regs->cp0_epc;
+ opcode = 0;
+ status = -1;
- if (!simulate_rdhwr(regs))
+ if (unlikely(compute_return_epc(regs) < 0))
return;
- break;
+ if (unlikely(get_user(opcode, epc) < 0))
+ status = SIGSEGV;
+
+ if (!cpu_has_llsc && status < 0)
+ status = simulate_llsc(regs, opcode);
+
+ if (status < 0)
+ status = simulate_rdhwr(regs, opcode);
+
+ if (status < 0)
+ status = SIGILL;
+
+ if (unlikely(status > 0)) {
+ regs->cp0_epc = old_epc; /* Undo skip-over. */
+ force_sig(status, current);
+ }
+
+ return;
case 1:
if (used_math()) /* Using the FPU again. */
@@ -1083,59 +1100,6 @@ void *set_except_vector(int n, void *addr)
return (void *)old_handler;
}
-#ifdef CONFIG_CPU_MIPSR2_SRS
-/*
- * MIPSR2 shadow register set allocation
- * FIXME: SMP...
- */
-
-static struct shadow_registers {
- /*
- * Number of shadow register sets supported
- */
- unsigned long sr_supported;
- /*
- * Bitmap of allocated shadow registers
- */
- unsigned long sr_allocated;
-} shadow_registers;
-
-static void mips_srs_init(void)
-{
- shadow_registers.sr_supported = ((read_c0_srsctl() >> 26) & 0x0f) + 1;
- printk(KERN_INFO "%ld MIPSR2 register sets available\n",
- shadow_registers.sr_supported);
- shadow_registers.sr_allocated = 1; /* Set 0 used by kernel */
-}
-
-int mips_srs_max(void)
-{
- return shadow_registers.sr_supported;
-}
-
-int mips_srs_alloc(void)
-{
- struct shadow_registers *sr = &shadow_registers;
- int set;
-
-again:
- set = find_first_zero_bit(&sr->sr_allocated, sr->sr_supported);
- if (set >= sr->sr_supported)
- return -1;
-
- if (test_and_set_bit(set, &sr->sr_allocated))
- goto again;
-
- return set;
-}
-
-void mips_srs_free(int set)
-{
- struct shadow_registers *sr = &shadow_registers;
-
- clear_bit(set, &sr->sr_allocated);
-}
-
static asmlinkage void do_default_vi(void)
{
show_regs(get_irq_regs());
@@ -1146,6 +1110,7 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
{
unsigned long handler;
unsigned long old_handler = vi_handlers[n];
+ int srssets = current_cpu_data.srsets;
u32 *w;
unsigned char *b;
@@ -1161,7 +1126,7 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
b = (unsigned char *)(ebase + 0x200 + n*VECTORSPACING);
- if (srs >= mips_srs_max())
+ if (srs >= srssets)
panic("Shadow register set %d not supported", srs);
if (cpu_has_veic) {
@@ -1169,7 +1134,7 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
board_bind_eic_interrupt(n, srs);
} else if (cpu_has_vint) {
/* SRSMap is only defined if shadow sets are implemented */
- if (mips_srs_max() > 1)
+ if (srssets > 1)
change_c0_srsmap(0xf << n*4, srs << n*4);
}
@@ -1236,14 +1201,6 @@ void *set_vi_handler(int n, vi_handler_t addr)
return set_vi_srs_handler(n, addr, 0);
}
-#else
-
-static inline void mips_srs_init(void)
-{
-}
-
-#endif /* CONFIG_CPU_MIPSR2_SRS */
-
/*
* This is used by native signal handling
*/
@@ -1319,6 +1276,17 @@ extern void cpu_cache_init(void);
extern void tlb_init(void);
extern void flush_tlb_handlers(void);
+/*
+ * Timer interrupt
+ */
+int cp0_compare_irq;
+
+/*
+ * Performance counter IRQ or -1 if shared with timer
+ */
+int cp0_perfcount_irq;
+EXPORT_SYMBOL_GPL(cp0_perfcount_irq);
+
void __init per_cpu_trap_init(void)
{
unsigned int cpu = smp_processor_id();
@@ -1475,8 +1443,6 @@ void __init trap_init(void)
else
ebase = CAC_BASE;
- mips_srs_init();
-
per_cpu_trap_init();
/*
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index 84f9a4cc6f2f..5fc2398bdb76 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -5,6 +5,10 @@
#define mips mips
OUTPUT_ARCH(mips)
ENTRY(kernel_entry)
+PHDRS {
+ text PT_LOAD FLAGS(7); /* RWX */
+ note PT_NOTE FLAGS(4); /* R__ */
+}
jiffies = JIFFIES;
SECTIONS
@@ -22,7 +26,6 @@ SECTIONS
*/
/* . = 0xa800000000300000; */
- /* . = 0xa800000000300000; */
. = 0xffffffff80300000;
#endif
. = LOADADDR;
@@ -32,9 +35,10 @@ SECTIONS
TEXT_TEXT
SCHED_TEXT
LOCK_TEXT
+ KPROBES_TEXT
*(.fixup)
*(.gnu.warning)
- } =0
+ } :text = 0
_etext = .; /* End of text section */
/* Exception table */
@@ -51,25 +55,31 @@ SECTIONS
*(__dbe_table)
__stop___dbe_table = .;
}
+
+ NOTES :text :note
+ .dummy : { *(.dummy) } :text
+
RODATA
/* writeable */
.data : { /* Data */
- . = . + DATAOFFSET; /* for CONFIG_MAPPED_KERNEL */
- /*
- * This ALIGN is needed as a workaround for a bug a gcc bug upto 4.1 which
- * limits the maximum alignment to at most 32kB and results in the following
- * warning:
- *
- * CC arch/mips/kernel/init_task.o
- * arch/mips/kernel/init_task.c:30: warning: alignment of ‘init_thread_union’
- * is greater than maximum object file alignment. Using 32768
- */
- . = ALIGN(_PAGE_SIZE);
- *(.data.init_task)
-
- DATA_DATA
- CONSTRUCTORS
+ . = . + DATAOFFSET; /* for CONFIG_MAPPED_KERNEL */
+ /*
+ * This ALIGN is needed as a workaround for a bug a
+ * gcc bug upto 4.1 which limits the maximum alignment
+ * to at most 32kB and results in the following
+ * warning:
+ *
+ * CC arch/mips/kernel/init_task.o
+ * arch/mips/kernel/init_task.c:30: warning: alignment
+ * of ‘init_thread_union’ is greater than maximum
+ * object file alignment. Using 32768
+ */
+ . = ALIGN(_PAGE_SIZE);
+ *(.data.init_task)
+
+ DATA_DATA
+ CONSTRUCTORS
}
_gp = . + 0x8000;
.lit8 : {
@@ -201,7 +211,4 @@ SECTIONS
*(.gptab.bss)
*(.gptab.sbss)
}
- .note : {
- *(.note)
- }
}
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index 61b729fa0548..38bd33fa2a23 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -942,8 +942,8 @@ static int vpe_elfload(struct vpe * v)
if (phdr->p_type != PT_LOAD)
continue;
- memcpy((void *)phdr->p_vaddr, (char *)hdr + phdr->p_offset, phdr->p_filesz);
- memset((void *)phdr->p_vaddr + phdr->p_filesz, 0, phdr->p_memsz - phdr->p_filesz);
+ memcpy((void *)phdr->p_paddr, (char *)hdr + phdr->p_offset, phdr->p_filesz);
+ memset((void *)phdr->p_paddr + phdr->p_filesz, 0, phdr->p_memsz - phdr->p_filesz);
phdr++;
}
@@ -1003,6 +1003,7 @@ static void cleanup_tc(struct tc *tc)
write_tc_c0_tcstatus(tmp);
write_tc_c0_tchalt(TCHALT_H);
+ mips_ihb();
/* bind it to anything other than VPE1 */
// write_tc_c0_tcbind(read_tc_c0_tcbind() & ~TCBIND_CURVPE); // | TCBIND_CURVPE
@@ -1235,9 +1236,12 @@ int vpe_free(vpe_handle vpe)
settc(t->index);
write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() & ~VPECONF0_VPA);
- /* mark the TC unallocated and halt'ed */
- write_tc_c0_tcstatus(read_tc_c0_tcstatus() & ~TCSTATUS_A);
+ /* halt the TC */
write_tc_c0_tchalt(TCHALT_H);
+ mips_ihb();
+
+ /* mark the TC unallocated */
+ write_tc_c0_tcstatus(read_tc_c0_tcstatus() & ~TCSTATUS_A);
v->state = VPE_STATE_UNUSED;
@@ -1317,7 +1321,8 @@ static void kspd_sp_exit( int sp_id)
}
#endif
-static ssize_t store_kill(struct class_device *dev, const char *buf, size_t len)
+static ssize_t store_kill(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t len)
{
struct vpe *vpe = get_vpe(tclimit);
struct vpe_notifications *not;
@@ -1334,14 +1339,16 @@ static ssize_t store_kill(struct class_device *dev, const char *buf, size_t len)
return len;
}
-static ssize_t show_ntcs(struct class_device *cd, char *buf)
+static ssize_t show_ntcs(struct device *cd, struct device_attribute *attr,
+ char *buf)
{
struct vpe *vpe = get_vpe(tclimit);
return sprintf(buf, "%d\n", vpe->ntcs);
}
-static ssize_t store_ntcs(struct class_device *dev, const char *buf, size_t len)
+static ssize_t store_ntcs(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t len)
{
struct vpe *vpe = get_vpe(tclimit);
unsigned long new;
@@ -1362,13 +1369,13 @@ out_einval:
return -EINVAL;;
}
-static struct class_device_attribute vpe_class_attributes[] = {
+static struct device_attribute vpe_class_attributes[] = {
__ATTR(kill, S_IWUSR, NULL, store_kill),
__ATTR(ntcs, S_IRUGO | S_IWUSR, show_ntcs, store_ntcs),
{}
};
-static void vpe_class_device_release(struct class_device *cd)
+static void vpe_device_release(struct device *cd)
{
kfree(cd);
}
@@ -1376,11 +1383,11 @@ static void vpe_class_device_release(struct class_device *cd)
struct class vpe_class = {
.name = "vpe",
.owner = THIS_MODULE,
- .release = vpe_class_device_release,
- .class_dev_attrs = vpe_class_attributes,
+ .dev_release = vpe_device_release,
+ .dev_attrs = vpe_class_attributes,
};
-struct class_device vpe_device;
+struct device vpe_device;
static int __init vpe_module_init(void)
{
@@ -1423,12 +1430,12 @@ static int __init vpe_module_init(void)
goto out_chrdev;
}
- class_device_initialize(&vpe_device);
+ device_initialize(&vpe_device);
vpe_device.class = &vpe_class,
vpe_device.parent = NULL,
- strlcpy(vpe_device.class_id, "vpe1", BUS_ID_SIZE);
+ strlcpy(vpe_device.bus_id, "vpe1", BUS_ID_SIZE);
vpe_device.devt = MKDEV(major, minor);
- err = class_device_add(&vpe_device);
+ err = device_add(&vpe_device);
if (err) {
printk(KERN_ERR "Adding vpe_device failed\n");
goto out_class;
@@ -1530,14 +1537,16 @@ static int __init vpe_module_init(void)
t->pvpe = get_vpe(0); /* set the parent vpe */
}
+ /* halt the TC */
+ write_tc_c0_tchalt(TCHALT_H);
+ mips_ihb();
+
tmp = read_tc_c0_tcstatus();
/* mark not activated and not dynamically allocatable */
tmp &= ~(TCSTATUS_A | TCSTATUS_DA);
tmp |= TCSTATUS_IXMT; /* interrupt exempt */
write_tc_c0_tcstatus(tmp);
-
- write_tc_c0_tchalt(TCHALT_H);
}
}
@@ -1573,7 +1582,7 @@ static void __exit vpe_module_exit(void)
}
}
- class_device_del(&vpe_device);
+ device_del(&vpe_device);
unregister_chrdev(major, module_name);
}
diff --git a/arch/mips/lasat/interrupt.c b/arch/mips/lasat/interrupt.c
index 5f35289bfff5..cfeab669782f 100644
--- a/arch/mips/lasat/interrupt.c
+++ b/arch/mips/lasat/interrupt.c
@@ -19,16 +19,14 @@
* Lasat boards.
*/
#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
#include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
+#include <linux/irq.h>
#include <asm/bootinfo.h>
+#include <asm/irq_cpu.h>
#include <asm/lasat/lasatint.h>
-#include <asm/time.h>
-#include <asm/gdb-stub.h>
+
+#include <irq.h>
static volatile int *lasat_int_status;
static volatile int *lasat_int_mask;
@@ -88,7 +86,7 @@ asmlinkage void plat_irq_dispatch(void)
int irq;
if (cause & CAUSEF_IP7) { /* R4000 count / compare IRQ */
- ll_timer_interrupt(7);
+ do_IRQ(7);
return;
}
@@ -96,12 +94,18 @@ asmlinkage void plat_irq_dispatch(void)
/* if int_status == 0, then the interrupt has already been cleared */
if (int_status) {
- irq = ls1bit32(int_status);
+ irq = LASAT_IRQ_BASE + ls1bit32(int_status);
do_IRQ(irq);
}
}
+static struct irqaction cascade = {
+ .handler = no_action,
+ .mask = CPU_MASK_NONE,
+ .name = "cascade",
+};
+
void __init arch_init_irq(void)
{
int i;
@@ -125,6 +129,10 @@ void __init arch_init_irq(void)
panic("arch_init_irq: mips_machtype incorrect");
}
- for (i = 0; i <= LASATINT_END; i++)
+ mips_cpu_irq_init();
+
+ for (i = LASAT_IRQ_BASE; i <= LASAT_IRQ_END; i++)
set_irq_chip_and_handler(i, &lasat_irq_type, handle_level_irq);
+
+ setup_irq(LASAT_CASCADE_IRQ, &cascade);
}
diff --git a/arch/mips/lasat/setup.c b/arch/mips/lasat/setup.c
index 54827d0174bf..e072da4ff3b3 100644
--- a/arch/mips/lasat/setup.c
+++ b/arch/mips/lasat/setup.c
@@ -117,14 +117,11 @@ static struct notifier_block lasat_panic_block[] =
}
};
-void plat_time_init(void)
+void __init plat_time_init(void)
{
mips_hpt_frequency = lasat_board_info.li_cpu_hz / 2;
-}
-void __init plat_timer_setup(struct irqaction *irq)
-{
- change_c0_status(ST0_IM, IE_IRQ0 | IE_IRQ5);
+ change_c0_status(ST0_IM, IE_IRQ0);
}
void __init plat_mem_setup(void)
diff --git a/arch/mips/lemote/lm2e/setup.c b/arch/mips/lemote/lm2e/setup.c
index 09314a20f9fb..2cc6745991ab 100644
--- a/arch/mips/lemote/lm2e/setup.c
+++ b/arch/mips/lemote/lm2e/setup.c
@@ -53,11 +53,6 @@ unsigned long bus_clock;
unsigned int memsize;
unsigned int highmemsize = 0;
-void __init plat_timer_setup(struct irqaction *irq)
-{
- setup_irq(MIPS_CPU_IRQ_BASE + 7, irq);
-}
-
void __init plat_time_init(void)
{
/* setup mips r4k timer */
diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c
index 1d00b778ff1e..f02ce6308e51 100644
--- a/arch/mips/mips-boards/generic/time.c
+++ b/arch/mips/mips-boards/generic/time.c
@@ -127,41 +127,8 @@ unsigned long read_persistent_clock(void)
return mc146818_get_cmos_time();
}
-void __init plat_time_init(void)
-{
- unsigned int est_freq;
-
- /* Set Data mode - binary. */
- CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL);
-
- est_freq = estimate_cpu_frequency();
-
- printk("CPU frequency %d.%02d MHz\n", est_freq/1000000,
- (est_freq%1000000)*100/1000000);
-
- cpu_khz = est_freq / 1000;
-
- mips_scroll_message();
-#ifdef CONFIG_I8253 /* Only Malta has a PIT */
- setup_pit_timer();
-#endif
-}
-
-//static irqreturn_t mips_perf_interrupt(int irq, void *dev_id)
-//{
-// return perf_irq();
-//}
-
-//static struct irqaction perf_irqaction = {
-// .handler = mips_perf_interrupt,
-// .flags = IRQF_DISABLED | IRQF_PERCPU,
-// .name = "performance",
-//};
-
void __init plat_perf_setup(void)
{
-// struct irqaction *irq = &perf_irqaction;
-
cp0_perfcount_irq = -1;
#ifdef MSC01E_INT_BASE
@@ -179,14 +146,13 @@ void __init plat_perf_setup(void)
}
}
-void __init plat_timer_setup(struct irqaction *irq)
+unsigned int __init get_c0_compare_int(void)
{
#ifdef MSC01E_INT_BASE
if (cpu_has_veic) {
set_vi_handler(MSC01E_INT_CPUCTR, mips_timer_dispatch);
mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR;
- }
- else
+ } else
#endif
{
if (cpu_has_vint)
@@ -194,13 +160,26 @@ void __init plat_timer_setup(struct irqaction *irq)
mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
}
-#ifdef CONFIG_MIPS_MT_SMTC
- setup_irq_smtc(mips_cpu_timer_irq, irq, 0x100 << cp0_compare_irq);
-#else
- setup_irq(mips_cpu_timer_irq, irq);
-#endif /* CONFIG_MIPS_MT_SMTC */
-#ifdef CONFIG_SMP
- set_irq_handler(mips_cpu_timer_irq, handle_percpu_irq);
+ return mips_cpu_timer_irq;
+}
+
+void __init plat_time_init(void)
+{
+ unsigned int est_freq;
+
+ /* Set Data mode - binary. */
+ CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL);
+
+ est_freq = estimate_cpu_frequency();
+
+ printk("CPU frequency %d.%02d MHz\n", est_freq/1000000,
+ (est_freq%1000000)*100/1000000);
+
+ cpu_khz = est_freq / 1000;
+
+ mips_scroll_message();
+#ifdef CONFIG_I8253 /* Only Malta has a PIT */
+ setup_pit_timer();
#endif
plat_perf_setup();
diff --git a/arch/mips/mipssim/sim_cmdline.c b/arch/mips/mipssim/sim_cmdline.c
index c63021a5dc6c..74240e1ce5a5 100644
--- a/arch/mips/mipssim/sim_cmdline.c
+++ b/arch/mips/mipssim/sim_cmdline.c
@@ -28,8 +28,5 @@ char * __init prom_getcmdline(void)
void __init prom_init_cmdline(void)
{
- char *cp;
- cp = arcs_cmdline;
- /* Get boot line from environment? */
- *cp = '\0';
+ /* XXX: Get boot line from environment? */
}
diff --git a/arch/mips/mipssim/sim_time.c b/arch/mips/mipssim/sim_time.c
index e7fa0d1078a3..bfaafa38846f 100644
--- a/arch/mips/mipssim/sim_time.c
+++ b/arch/mips/mipssim/sim_time.c
@@ -75,25 +75,6 @@ static unsigned int __init estimate_cpu_frequency(void)
return count;
}
-void __init plat_time_init(void)
-{
- unsigned int est_freq, flags;
-
- local_irq_save(flags);
-
- /* Set Data mode - binary. */
- CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL);
-
- est_freq = estimate_cpu_frequency();
-
- printk(KERN_INFO "CPU frequency %d.%02d MHz\n", est_freq / 1000000,
- (est_freq % 1000000) * 100 / 1000000);
-
- cpu_khz = est_freq / 1000;
-
- local_irq_restore(flags);
-}
-
static int mips_cpu_timer_irq;
static void mips_timer_dispatch(void)
@@ -102,26 +83,37 @@ static void mips_timer_dispatch(void)
}
-void __init plat_timer_setup(struct irqaction *irq)
+unsigned __init get_c0_compare_int(void)
{
+#ifdef MSC01E_INT_BASE
if (cpu_has_veic) {
set_vi_handler(MSC01E_INT_CPUCTR, mips_timer_dispatch);
mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR;
} else {
+#endif
if (cpu_has_vint)
set_vi_handler(cp0_compare_irq, mips_timer_dispatch);
mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
}
- /* we are using the cpu counter for timer interrupts */
- setup_irq(mips_cpu_timer_irq, irq);
+ return mips_cpu_timer_irq;
+}
-#ifdef CONFIG_SMP
- /* irq_desc(riptor) is a global resource, when the interrupt overlaps
- on seperate cpu's the first one tries to handle the second interrupt.
- The effect is that the int remains disabled on the second cpu.
- Mark the interrupt with IRQ_PER_CPU to avoid any confusion */
- irq_desc[mips_cpu_timer_irq].flags |= IRQ_PER_CPU;
- set_irq_handler(mips_cpu_timer_irq, handle_percpu_irq);
-#endif
+void __init plat_time_init(void)
+{
+ unsigned int est_freq, flags;
+
+ local_irq_save(flags);
+
+ /* Set Data mode - binary. */
+ CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL);
+
+ est_freq = estimate_cpu_frequency();
+
+ printk(KERN_INFO "CPU frequency %d.%02d MHz\n", est_freq / 1000000,
+ (est_freq % 1000000) * 100 / 1000000);
+
+ cpu_khz = est_freq / 1000;
+
+ local_irq_restore(flags);
}
diff --git a/arch/mips/mm/c-r3k.c b/arch/mips/mm/c-r3k.c
index c55312f6fd3a..562abb77d1d5 100644
--- a/arch/mips/mm/c-r3k.c
+++ b/arch/mips/mm/c-r3k.c
@@ -7,7 +7,7 @@
* Tx39XX R4k style caches added. HK
* Copyright (C) 1998, 1999, 2000 Harald Koerfgen
* Copyright (C) 1998 Gleb Raiko & Vladimir Roganov
- * Copyright (C) 2001, 2004 Maciej W. Rozycki
+ * Copyright (C) 2001, 2004, 2007 Maciej W. Rozycki
*/
#include <linux/init.h>
#include <linux/kernel.h>
@@ -26,8 +26,6 @@
static unsigned long icache_size, dcache_size; /* Size in bytes */
static unsigned long icache_lsize, dcache_lsize; /* Size in bytes */
-#undef DEBUG_CACHE
-
unsigned long __init r3k_cache_size(unsigned long ca_flags)
{
unsigned long flags, status, dummy, size;
@@ -217,26 +215,6 @@ static void r3k_flush_dcache_range(unsigned long start, unsigned long end)
write_c0_status(flags);
}
-static inline unsigned long get_phys_page(unsigned long addr,
- struct mm_struct *mm)
-{
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte;
- unsigned long physpage;
-
- pgd = pgd_offset(mm, addr);
- pud = pud_offset(pgd, addr);
- pmd = pmd_offset(pud, addr);
- pte = pte_offset(pmd, addr);
-
- if ((physpage = pte_val(*pte)) & _PAGE_VALID)
- return KSEG0ADDR(physpage & PAGE_MASK);
-
- return 0;
-}
-
static inline void r3k_flush_cache_all(void)
{
}
@@ -252,12 +230,40 @@ static void r3k_flush_cache_mm(struct mm_struct *mm)
}
static void r3k_flush_cache_range(struct vm_area_struct *vma,
- unsigned long start, unsigned long end)
+ unsigned long start, unsigned long end)
{
}
-static void r3k_flush_cache_page(struct vm_area_struct *vma, unsigned long page, unsigned long pfn)
+static void r3k_flush_cache_page(struct vm_area_struct *vma,
+ unsigned long addr, unsigned long pfn)
{
+ unsigned long kaddr = KSEG0ADDR(pfn << PAGE_SHIFT);
+ int exec = vma->vm_flags & VM_EXEC;
+ struct mm_struct *mm = vma->vm_mm;
+ pgd_t *pgdp;
+ pud_t *pudp;
+ pmd_t *pmdp;
+ pte_t *ptep;
+
+ pr_debug("cpage[%08lx,%08lx]\n",
+ cpu_context(smp_processor_id(), mm), addr);
+
+ /* No ASID => no such page in the cache. */
+ if (cpu_context(smp_processor_id(), mm) == 0)
+ return;
+
+ pgdp = pgd_offset(mm, addr);
+ pudp = pud_offset(pgdp, addr);
+ pmdp = pmd_offset(pudp, addr);
+ ptep = pte_offset(pmdp, addr);
+
+ /* Invalid => no such page in the cache. */
+ if (!(pte_val(*ptep) & _PAGE_PRESENT))
+ return;
+
+ r3k_flush_dcache_range(kaddr, kaddr + PAGE_SIZE);
+ if (exec)
+ r3k_flush_icache_range(kaddr, kaddr + PAGE_SIZE);
}
static void local_r3k_flush_data_cache_page(void *addr)
@@ -272,9 +278,7 @@ static void r3k_flush_cache_sigtramp(unsigned long addr)
{
unsigned long flags;
-#ifdef DEBUG_CACHE
- printk("csigtramp[%08lx]", addr);
-#endif
+ pr_debug("csigtramp[%08lx]\n", addr);
flags = read_c0_status();
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 971f6c047b8a..9355f1c9325f 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -7,6 +7,7 @@
* Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Ralf Baechle (ralf@gnu.org)
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
*/
+#include <linux/hardirq.h>
#include <linux/init.h>
#include <linux/highmem.h>
#include <linux/kernel.h>
@@ -345,11 +346,26 @@ static void r4k___flush_cache_all(void)
r4k_on_each_cpu(local_r4k___flush_cache_all, NULL, 1, 1);
}
+static inline int has_valid_asid(const struct mm_struct *mm)
+{
+#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC)
+ int i;
+
+ for_each_online_cpu(i)
+ if (cpu_context(i, mm))
+ return 1;
+
+ return 0;
+#else
+ return cpu_context(smp_processor_id(), mm);
+#endif
+}
+
static inline void local_r4k_flush_cache_range(void * args)
{
struct vm_area_struct *vma = args;
- if (!(cpu_context(smp_processor_id(), vma->vm_mm)))
+ if (!(has_valid_asid(vma->vm_mm)))
return;
r4k_blast_dcache();
@@ -368,7 +384,7 @@ static inline void local_r4k_flush_cache_mm(void * args)
{
struct mm_struct *mm = args;
- if (!cpu_context(smp_processor_id(), mm))
+ if (!has_valid_asid(mm))
return;
/*
@@ -420,7 +436,7 @@ static inline void local_r4k_flush_cache_page(void *args)
* If ownes no valid ASID yet, cannot possibly have gotten
* this page into the cache.
*/
- if (cpu_context(smp_processor_id(), mm) == 0)
+ if (!has_valid_asid(mm))
return;
addr &= PAGE_MASK;
@@ -492,7 +508,11 @@ static inline void local_r4k_flush_data_cache_page(void * addr)
static void r4k_flush_data_cache_page(unsigned long addr)
{
- r4k_on_each_cpu(local_r4k_flush_data_cache_page, (void *) addr, 1, 1);
+ if (in_atomic())
+ local_r4k_flush_data_cache_page((void *)addr);
+ else
+ r4k_on_each_cpu(local_r4k_flush_data_cache_page, (void *) addr,
+ 1, 1);
}
struct flush_icache_range_args {
@@ -983,11 +1003,15 @@ static void __init probe_pcache(void)
printk("Primary instruction cache %ldkB, %s, %s, linesize %d bytes.\n",
icache_size >> 10,
- cpu_has_vtag_icache ? "virtually tagged" : "physically tagged",
+ cpu_has_vtag_icache ? "VIVT" : "VIPT",
way_string[c->icache.ways], c->icache.linesz);
- printk("Primary data cache %ldkB, %s, linesize %d bytes.\n",
- dcache_size >> 10, way_string[c->dcache.ways], c->dcache.linesz);
+ printk("Primary data cache %ldkB, %s, %s, %s, linesize %d bytes\n",
+ dcache_size >> 10, way_string[c->dcache.ways],
+ (c->dcache.flags & MIPS_CACHE_PINDEX) ? "PIPT" : "VIPT",
+ (c->dcache.flags & MIPS_CACHE_ALIASES) ?
+ "cache aliases" : "no aliases",
+ c->dcache.linesz);
}
/*
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index 43dde874f414..81f30ac2bff9 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -47,8 +47,6 @@ void (*_dma_cache_wback)(unsigned long start, unsigned long size);
void (*_dma_cache_inv)(unsigned long start, unsigned long size);
EXPORT_SYMBOL(_dma_cache_wback_inv);
-EXPORT_SYMBOL(_dma_cache_wback);
-EXPORT_SYMBOL(_dma_cache_inv);
#endif /* CONFIG_DMA_NONCOHERENT */
diff --git a/arch/mips/mm/cerr-sb1.c b/arch/mips/mm/cerr-sb1.c
index e7f539e3284b..1bd1f18ac23c 100644
--- a/arch/mips/mm/cerr-sb1.c
+++ b/arch/mips/mm/cerr-sb1.c
@@ -154,7 +154,7 @@ static void check_bus_watcher(void)
if (status & ~(1UL << 31)) {
l2_err = csr_in32(IOADDR(A_BUS_L2_ERRORS));
#ifdef DUMP_L2_ECC_TAG_ON_ERROR
- l2_tag = in64(IO_SPACE_BASE | A_L2_ECC_TAG);
+ l2_tag = in64(IOADDR(A_L2_ECC_TAG));
#endif
memio_err = csr_in32(IOADDR(A_BUS_MEM_IO_ERRORS));
printk("Bus watcher error counters: %08x %08x\n", l2_err, memio_err);
@@ -183,9 +183,9 @@ asmlinkage void sb1_cache_error(void)
#ifdef CONFIG_SIBYTE_BW_TRACE
/* Freeze the trace buffer now */
#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
- csr_out32(M_BCM1480_SCD_TRACE_CFG_FREEZE, IO_SPACE_BASE | A_SCD_TRACE_CFG);
+ csr_out32(M_BCM1480_SCD_TRACE_CFG_FREEZE, IOADDR(A_SCD_TRACE_CFG));
#else
- csr_out32(M_SCD_TRACE_CFG_FREEZE, IO_SPACE_BASE | A_SCD_TRACE_CFG);
+ csr_out32(M_SCD_TRACE_CFG_FREEZE, IOADDR(A_SCD_TRACE_CFG));
#endif
printk("Trace buffer frozen\n");
#endif
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
index 98b5e5bac02e..33519ce49540 100644
--- a/arch/mips/mm/dma-default.c
+++ b/arch/mips/mm/dma-default.c
@@ -12,6 +12,7 @@
#include <linux/dma-mapping.h>
#include <linux/mm.h>
#include <linux/module.h>
+#include <linux/scatterlist.h>
#include <linux/string.h>
#include <asm/cache.h>
@@ -165,12 +166,11 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
for (i = 0; i < nents; i++, sg++) {
unsigned long addr;
- addr = (unsigned long) page_address(sg->page);
+ addr = (unsigned long) sg_virt(sg);
if (!plat_device_is_coherent(dev) && addr)
- __dma_sync(addr + sg->offset, sg->length, direction);
+ __dma_sync(addr, sg->length, direction);
sg->dma_address = plat_map_dma_mem(dev,
- (void *)(addr + sg->offset),
- sg->length);
+ (void *)addr, sg->length);
}
return nents;
@@ -223,10 +223,9 @@ void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
for (i = 0; i < nhwentries; i++, sg++) {
if (!plat_device_is_coherent(dev) &&
direction != DMA_TO_DEVICE) {
- addr = (unsigned long) page_address(sg->page);
+ addr = (unsigned long) sg_virt(sg);
if (addr)
- __dma_sync(addr + sg->offset, sg->length,
- direction);
+ __dma_sync(addr, sg->length, direction);
}
plat_unmap_dma_mem(sg->dma_address);
}
@@ -304,7 +303,7 @@ void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
/* Make sure that gcc doesn't leave the empty loop body. */
for (i = 0; i < nelems; i++, sg++) {
if (cpu_is_noncoherent_r10000(dev))
- __dma_sync((unsigned long)page_address(sg->page),
+ __dma_sync((unsigned long)page_address(sg_page(sg)),
sg->length, direction);
plat_unmap_dma_mem(sg->dma_address);
}
@@ -322,7 +321,7 @@ void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nele
/* Make sure that gcc doesn't leave the empty loop body. */
for (i = 0; i < nelems; i++, sg++) {
if (!plat_device_is_coherent(dev))
- __dma_sync((unsigned long)page_address(sg->page),
+ __dma_sync((unsigned long)page_address(sg_page(sg)),
sg->length, direction);
plat_unmap_dma_mem(sg->dma_address);
}
diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c
index 521771b373de..fa636fc6b7b9 100644
--- a/arch/mips/mm/fault.c
+++ b/arch/mips/mm/fault.c
@@ -173,14 +173,14 @@ no_context:
*/
out_of_memory:
up_read(&mm->mmap_sem);
- if (is_init(tsk)) {
+ if (is_global_init(tsk)) {
yield();
down_read(&mm->mmap_sem);
goto survive;
}
printk("VM: killing process %s\n", tsk->comm);
if (user_mode(regs))
- do_exit(SIGKILL);
+ do_group_exit(SIGKILL);
goto no_context;
do_sigbus:
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index 5240432e6d1d..ec3b9e9f30f4 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -211,7 +211,7 @@ void copy_user_highpage(struct page *to, struct page *from,
void *vfrom, *vto;
vto = kmap_atomic(to, KM_USER1);
- if (cpu_has_dc_aliases && !Page_dcache_dirty(from)) {
+ if (cpu_has_dc_aliases && page_mapped(from)) {
vfrom = kmap_coherent(from, vaddr);
copy_page(vto, vfrom);
kunmap_coherent();
@@ -234,12 +234,15 @@ void copy_to_user_page(struct vm_area_struct *vma,
struct page *page, unsigned long vaddr, void *dst, const void *src,
unsigned long len)
{
- if (cpu_has_dc_aliases) {
+ if (cpu_has_dc_aliases && page_mapped(page)) {
void *vto = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK);
memcpy(vto, src, len);
kunmap_coherent();
- } else
+ } else {
memcpy(dst, src, len);
+ if (cpu_has_dc_aliases)
+ SetPageDcacheDirty(page);
+ }
if ((vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc)
flush_cache_page(vma, vaddr, page_to_pfn(page));
}
@@ -250,13 +253,15 @@ void copy_from_user_page(struct vm_area_struct *vma,
struct page *page, unsigned long vaddr, void *dst, const void *src,
unsigned long len)
{
- if (cpu_has_dc_aliases) {
- void *vfrom =
- kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK);
+ if (cpu_has_dc_aliases && page_mapped(page)) {
+ void *vfrom = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK);
memcpy(dst, vfrom, len);
kunmap_coherent();
- } else
+ } else {
memcpy(dst, src, len);
+ if (cpu_has_dc_aliases)
+ SetPageDcacheDirty(page);
+ }
}
EXPORT_SYMBOL(copy_from_user_page);
@@ -421,7 +426,7 @@ void __init mem_init(void)
#ifdef CONFIG_HIGHMEM
for (tmp = highstart_pfn; tmp < highend_pfn; tmp++) {
- struct page *page = mem_map + tmp;
+ struct page *page = pfn_to_page(tmp);
if (!page_is_ram(tmp)) {
SetPageReserved(page);
diff --git a/arch/mips/oprofile/Kconfig b/arch/mips/oprofile/Kconfig
deleted file mode 100644
index fb6f235348b0..000000000000
--- a/arch/mips/oprofile/Kconfig
+++ /dev/null
@@ -1,23 +0,0 @@
-
-menu "Profiling support"
- depends on EXPERIMENTAL
-
-config PROFILING
- bool "Profiling support (EXPERIMENTAL)"
- help
- Say Y here to enable the extended profiling support mechanisms used
- by profilers such as OProfile.
-
-
-config OPROFILE
- tristate "OProfile system profiling (EXPERIMENTAL)"
- depends on PROFILING && !MIPS_MT_SMTC && EXPERIMENTAL
- help
- OProfile is a profiling system capable of profiling the
- whole system, include the kernel, kernel modules, libraries,
- and applications.
-
- If unsure, say N.
-
-endmenu
-
diff --git a/arch/mips/pci/fixup-pmcmsp.c b/arch/mips/pci/fixup-pmcmsp.c
index 00261211dbfa..65735b1b7665 100644
--- a/arch/mips/pci/fixup-pmcmsp.c
+++ b/arch/mips/pci/fixup-pmcmsp.c
@@ -202,7 +202,7 @@ int pcibios_plat_dev_init(struct pci_dev *dev)
* RETURNS: IRQ number
*
****************************************************************************/
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
#if !defined(CONFIG_PMC_MSP7120_GW) && !defined(CONFIG_PMC_MSP7120_EVAL)
printk(KERN_WARNING "PCI: unknown board, no PCI IRQs assigned.\n");
diff --git a/arch/mips/pci/fixup-sni.c b/arch/mips/pci/fixup-sni.c
index a45bedd17233..5c8a79bb2661 100644
--- a/arch/mips/pci/fixup-sni.c
+++ b/arch/mips/pci/fixup-sni.c
@@ -113,6 +113,16 @@ static char irq_tab_pcit[13][5] __initdata = {
{ 0, INTA, INTB, INTC, INTD }, /* Slot 5 */
};
+static char irq_tab_pcit_cplus[13][5] __initdata = {
+ /* INTA INTB INTC INTD */
+ { 0, 0, 0, 0, 0 }, /* HOST bridge */
+ { 0, INTB, INTC, INTD, INTA }, /* PCI Slot 9 */
+ { 0, 0, 0, 0, 0 }, /* PCI-EISA */
+ { 0, 0, 0, 0, 0 }, /* Unused */
+ { 0, INTA, INTB, INTC, INTD }, /* PCI-PCI bridge */
+ { 0, INTB, INTC, INTD, INTA }, /* fixup */
+};
+
static inline int is_rm300_revd(void)
{
unsigned char csmsr = *(volatile unsigned char *)PCIMT_CSMSR;
@@ -123,8 +133,19 @@ static inline int is_rm300_revd(void)
int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
switch (sni_brd_type) {
- case SNI_BRD_PCI_TOWER:
case SNI_BRD_PCI_TOWER_CPLUS:
+ if (slot == 4) {
+ /*
+ * SNI messed up interrupt wiring for onboard
+ * PCI bus 1; we need to fix this up here
+ */
+ while (dev && dev->bus->number != 1)
+ dev = dev->bus->self;
+ if (dev && dev->devfn >= PCI_DEVFN(4, 0))
+ slot = 5;
+ }
+ return irq_tab_pcit_cplus[slot][pin];
+ case SNI_BRD_PCI_TOWER:
return irq_tab_pcit[slot][pin];
case SNI_BRD_PCI_MTOWER:
diff --git a/arch/mips/pci/fixup-tb0219.c b/arch/mips/pci/fixup-tb0219.c
index 720a2b720c5c..ed87733f6796 100644
--- a/arch/mips/pci/fixup-tb0219.c
+++ b/arch/mips/pci/fixup-tb0219.c
@@ -2,7 +2,7 @@
* fixup-tb0219.c, The TANBAC TB0219 specific PCI fixups.
*
* Copyright (C) 2003 Megasolution Inc. <matsu@megasolution.jp>
- * Copyright (C) 2004 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ * Copyright (C) 2004-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* 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
diff --git a/arch/mips/pci/ops-pmcmsp.c b/arch/mips/pci/ops-pmcmsp.c
index 09fa007c1d1b..109c95ca698b 100644
--- a/arch/mips/pci/ops-pmcmsp.c
+++ b/arch/mips/pci/ops-pmcmsp.c
@@ -206,7 +206,7 @@ static void pci_proc_init(void)
}
#endif /* CONFIG_PROC_FS && PCI_COUNTERS */
-spinlock_t bpci_lock = SPIN_LOCK_UNLOCKED;
+DEFINE_SPINLOCK(bpci_lock);
/*****************************************************************************
*
@@ -404,7 +404,7 @@ int msp_pcibios_config_access(unsigned char access_type,
if (pciirqflag == 0) {
request_irq(MSP_INT_PCI,/* Hardcoded internal MSP7120 wiring */
bpci_interrupt,
- SA_SHIRQ | SA_INTERRUPT,
+ IRQF_SHARED | IRQF_DISABLED,
"PMC MSP PCI Host",
preg);
pciirqflag = ~0;
diff --git a/arch/mips/pci/pci-excite.c b/arch/mips/pci/pci-excite.c
index 3c86c77cb74f..8a56876afcc6 100644
--- a/arch/mips/pci/pci-excite.c
+++ b/arch/mips/pci/pci-excite.c
@@ -131,7 +131,7 @@ static int __init basler_excite_pci_setup(void)
ocd_writel(0x00000000, bar + 0x100);
}
- /* Finally, enable the PCI interupt */
+ /* Finally, enable the PCI interrupt */
#if USB_IRQ > 7
set_c0_intcontrol(1 << USB_IRQ);
#else
diff --git a/arch/mips/pci/pci-lasat.c b/arch/mips/pci/pci-lasat.c
index 5abd5c7119be..e70ae3236e0b 100644
--- a/arch/mips/pci/pci-lasat.c
+++ b/arch/mips/pci/pci-lasat.c
@@ -5,12 +5,15 @@
*
* Copyright (C) 2000, 2001, 04 Keith M Wesolowski
*/
-#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/types.h>
+
#include <asm/bootinfo.h>
+#include <irq.h>
+
extern struct pci_ops nile4_pci_ops;
extern struct pci_ops gt64xxx_pci0_ops;
static struct resource lasat_pci_mem_resource = {
@@ -54,15 +57,15 @@ static int __init lasat_pci_setup(void)
arch_initcall(lasat_pci_setup);
-#define LASATINT_ETH1 0
-#define LASATINT_ETH0 1
-#define LASATINT_HDC 2
-#define LASATINT_COMP 3
-#define LASATINT_HDLC 4
-#define LASATINT_PCIA 5
-#define LASATINT_PCIB 6
-#define LASATINT_PCIC 7
-#define LASATINT_PCID 8
+#define LASAT_IRQ_ETH1 (LASAT_IRQ_BASE + 0)
+#define LASAT_IRQ_ETH0 (LASAT_IRQ_BASE + 1)
+#define LASAT_IRQ_HDC (LASAT_IRQ_BASE + 2)
+#define LASAT_IRQ_COMP (LASAT_IRQ_BASE + 3)
+#define LASAT_IRQ_HDLC (LASAT_IRQ_BASE + 4)
+#define LASAT_IRQ_PCIA (LASAT_IRQ_BASE + 5)
+#define LASAT_IRQ_PCIB (LASAT_IRQ_BASE + 6)
+#define LASAT_IRQ_PCIC (LASAT_IRQ_BASE + 7)
+#define LASAT_IRQ_PCID (LASAT_IRQ_BASE + 8)
int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
@@ -70,13 +73,13 @@ int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
case 1:
case 2:
case 3:
- return LASATINT_PCIA + (((slot-1) + (pin-1)) % 4);
+ return LASAT_IRQ_PCIA + (((slot-1) + (pin-1)) % 4);
case 4:
- return LASATINT_ETH1; /* Ethernet 1 (LAN 2) */
+ return LASAT_IRQ_ETH1; /* Ethernet 1 (LAN 2) */
case 5:
- return LASATINT_ETH0; /* Ethernet 0 (LAN 1) */
+ return LASAT_IRQ_ETH0; /* Ethernet 0 (LAN 1) */
case 6:
- return LASATINT_HDC; /* IDE controller */
+ return LASAT_IRQ_HDC; /* IDE controller */
default:
return 0xff; /* Illegal */
}
diff --git a/arch/mips/pci/pci-vr41xx.c b/arch/mips/pci/pci-vr41xx.c
index 240df9e33813..33c4f683d067 100644
--- a/arch/mips/pci/pci-vr41xx.c
+++ b/arch/mips/pci/pci-vr41xx.c
@@ -154,6 +154,7 @@ static int __init vr41xx_pciu_init(void)
pciu_write(PCICLKSELREG, QUARTER_VTCLOCK);
else {
printk(KERN_ERR "PCI Clock is over 33MHz.\n");
+ iounmap(pciu_base);
return -EINVAL;
}
diff --git a/arch/mips/pmc-sierra/Kconfig b/arch/mips/pmc-sierra/Kconfig
index abbd0bbfabd7..6b293ce0935f 100644
--- a/arch/mips/pmc-sierra/Kconfig
+++ b/arch/mips/pmc-sierra/Kconfig
@@ -4,11 +4,13 @@ choice
config PMC_MSP4200_EVAL
bool "PMC-Sierra MSP4200 Eval Board"
+ select CEVT_R4K
select IRQ_MSP_SLP
select HW_HAS_PCI
config PMC_MSP4200_GW
bool "PMC-Sierra MSP4200 VoIP Gateway"
+ select CEVT_R4K
select IRQ_MSP_SLP
select HW_HAS_PCI
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_serial.c b/arch/mips/pmc-sierra/msp71xx/msp_serial.c
index 15e7b8000b4c..9de34302e5f4 100644
--- a/arch/mips/pmc-sierra/msp71xx/msp_serial.c
+++ b/arch/mips/pmc-sierra/msp71xx/msp_serial.c
@@ -122,7 +122,7 @@ void __init msp_serial_setup(void)
up.uartclk = uartclk;
up.regshift = 2;
up.iotype = UPIO_DWAPB; /* UPIO_MEM like */
- up.flags = STD_COM_FLAGS;
+ up.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
up.type = PORT_16550A;
up.line = 0;
up.private_data = (void*)UART0_STATUS_REG;
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_time.c b/arch/mips/pmc-sierra/msp71xx/msp_time.c
index f221d4763625..7cfeda5a651b 100644
--- a/arch/mips/pmc-sierra/msp71xx/msp_time.c
+++ b/arch/mips/pmc-sierra/msp71xx/msp_time.c
@@ -86,8 +86,5 @@ void __init plat_timer_setup(struct irqaction *irq)
#ifdef CONFIG_IRQ_MSP_CIC
/* we are using the vpe0 counter for timer interrupts */
setup_irq(MSP_INT_VPE0_TIMER, irq);
-#else
- /* we are using the mips counter for timer interrupts */
- setup_irq(MSP_INT_TIMER, irq);
#endif
}
diff --git a/arch/mips/pmc-sierra/yosemite/setup.c b/arch/mips/pmc-sierra/yosemite/setup.c
index 015fcc363dc0..855977ca51cd 100644
--- a/arch/mips/pmc-sierra/yosemite/setup.c
+++ b/arch/mips/pmc-sierra/yosemite/setup.c
@@ -137,11 +137,6 @@ int rtc_mips_set_time(unsigned long tim)
return 0;
}
-void __init plat_timer_setup(struct irqaction *irq)
-{
- setup_irq(7, irq);
-}
-
void __init plat_time_init(void)
{
mips_hpt_frequency = cpu_clock_freq / 2;
diff --git a/arch/mips/qemu/Makefile b/arch/mips/qemu/Makefile
index cec24c117f6e..2ba4ef34b4a7 100644
--- a/arch/mips/qemu/Makefile
+++ b/arch/mips/qemu/Makefile
@@ -4,6 +4,7 @@
obj-y = q-firmware.o q-irq.o q-mem.o q-setup.o q-reset.o
-obj-$(CONFIG_SMP) += q-smp.o
+obj-$(CONFIG_EARLY_PRINTK) += q-console.o
+obj-$(CONFIG_SMP) += q-smp.o
EXTRA_CFLAGS += -Werror
diff --git a/arch/mips/qemu/q-console.c b/arch/mips/qemu/q-console.c
new file mode 100644
index 000000000000..81101ae5017a
--- /dev/null
+++ b/arch/mips/qemu/q-console.c
@@ -0,0 +1,26 @@
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/serial_reg.h>
+#include <asm/io.h>
+
+#define PORT(offset) (0x3f8 + (offset))
+
+static inline unsigned int serial_in(int offset)
+{
+ return inb(PORT(offset));
+}
+
+static inline void serial_out(int offset, int value)
+{
+ outb(value, PORT(offset));
+}
+
+int prom_putchar(char c)
+{
+ while ((serial_in(UART_LSR) & UART_LSR_THRE) == 0)
+ ;
+
+ serial_out(UART_TX, c);
+
+ return 1;
+}
diff --git a/arch/mips/qemu/q-firmware.c b/arch/mips/qemu/q-firmware.c
index c2239b417587..3ed43f416cd1 100644
--- a/arch/mips/qemu/q-firmware.c
+++ b/arch/mips/qemu/q-firmware.c
@@ -2,6 +2,9 @@
#include <linux/string.h>
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
+#include <asm/io.h>
+
+#define QEMU_PORT_BASE 0xb4000000
void __init prom_init(void)
{
@@ -15,4 +18,7 @@ void __init prom_init(void)
} else {
add_memory_region(0x0<<20, 0x10<<20, BOOT_MEM_RAM);
}
+
+
+ set_io_port_base(QEMU_PORT_BASE);
}
diff --git a/arch/mips/qemu/q-irq.c b/arch/mips/qemu/q-irq.c
index 4681757460a1..11f984767880 100644
--- a/arch/mips/qemu/q-irq.c
+++ b/arch/mips/qemu/q-irq.c
@@ -1,4 +1,5 @@
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/linkage.h>
#include <asm/i8259.h>
diff --git a/arch/mips/qemu/q-setup.c b/arch/mips/qemu/q-setup.c
index 23d34c1917c0..969cedc8d8b9 100644
--- a/arch/mips/qemu/q-setup.c
+++ b/arch/mips/qemu/q-setup.c
@@ -6,8 +6,6 @@
extern void qemu_reboot_setup(void);
-#define QEMU_PORT_BASE 0xb4000000
-
const char *get_system_type(void)
{
return "Qemu";
@@ -20,6 +18,5 @@ void __init plat_time_init(void)
void __init plat_mem_setup(void)
{
- set_io_port_base(QEMU_PORT_BASE);
qemu_reboot_setup();
}
diff --git a/arch/mips/sgi-ip22/Makefile b/arch/mips/sgi-ip22/Makefile
index 1fb3e353e212..e3acb51b70b5 100644
--- a/arch/mips/sgi-ip22/Makefile
+++ b/arch/mips/sgi-ip22/Makefile
@@ -7,3 +7,5 @@ obj-y += ip22-mc.o ip22-hpc.o ip22-int.o ip22-berr.o \
ip22-time.o ip22-nvram.o ip22-platform.o ip22-reset.o ip22-setup.o
obj-$(CONFIG_EISA) += ip22-eisa.o
+
+EXTRA_CFLAGS += -Werror
diff --git a/arch/mips/sgi-ip22/ip22-reset.c b/arch/mips/sgi-ip22/ip22-reset.c
index 63afd7e44428..a435b31cf031 100644
--- a/arch/mips/sgi-ip22/ip22-reset.c
+++ b/arch/mips/sgi-ip22/ip22-reset.c
@@ -232,11 +232,18 @@ static struct notifier_block panic_block = {
static int __init reboot_setup(void)
{
+ int res;
+
_machine_restart = sgi_machine_restart;
_machine_halt = sgi_machine_halt;
pm_power_off = sgi_machine_power_off;
- request_irq(SGI_PANEL_IRQ, panel_int, 0, "Front Panel", NULL);
+ res = request_irq(SGI_PANEL_IRQ, panel_int, 0, "Front Panel", NULL);
+ if (res) {
+ printk(KERN_ERR "Allocation of front panel IRQ failed\n");
+ return res;
+ }
+
init_timer(&blink_timer);
blink_timer.function = blink_timeout;
atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
diff --git a/arch/mips/sgi-ip22/ip22-time.c b/arch/mips/sgi-ip22/ip22-time.c
index 9b9bffd2e8fb..10e505491655 100644
--- a/arch/mips/sgi-ip22/ip22-time.c
+++ b/arch/mips/sgi-ip22/ip22-time.c
@@ -192,12 +192,3 @@ void indy_8254timer_irq(void)
ArcEnterInteractiveMode();
irq_exit();
}
-
-void __init plat_timer_setup(struct irqaction *irq)
-{
- /* over-write the handler, we use our own way */
- irq->handler = no_action;
-
- /* setup irqaction */
- setup_irq(SGI_TIMER_IRQ, irq);
-}
diff --git a/arch/mips/sgi-ip27/ip27-init.c b/arch/mips/sgi-ip27/ip27-init.c
index 681b593071cb..3305fa9ae66d 100644
--- a/arch/mips/sgi-ip27/ip27-init.c
+++ b/arch/mips/sgi-ip27/ip27-init.c
@@ -110,7 +110,7 @@ static void __init per_hub_init(cnodeid_t cnode)
}
}
-void __init per_cpu_init(void)
+void __cpuinit per_cpu_init(void)
{
int cpu = smp_processor_id();
int slice = LOCAL_HUB_L(PI_CPU_NUM);
diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c
index 856649cf9f1e..1bb692a3b319 100644
--- a/arch/mips/sgi-ip27/ip27-irq.c
+++ b/arch/mips/sgi-ip27/ip27-irq.c
@@ -374,14 +374,13 @@ int __devinit request_bridge_irq(struct bridge_controller *bc)
return irq;
}
-extern void ip27_rt_timer_interrupt(void);
-
asmlinkage void plat_irq_dispatch(void)
{
unsigned long pending = read_c0_cause() & read_c0_status();
+ extern unsigned int rt_timer_irq;
if (pending & CAUSEF_IP4)
- ip27_rt_timer_interrupt();
+ do_IRQ(rt_timer_irq);
else if (pending & CAUSEF_IP2) /* PI_INT_PEND_0 or CC_PEND_{A|B} */
ip27_do_irq_mask0();
else if (pending & CAUSEF_IP3) /* PI_INT_PEND_1 */
diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c
index b7b3479b6bce..08d45369be45 100644
--- a/arch/mips/sgi-ip27/ip27-timer.c
+++ b/arch/mips/sgi-ip27/ip27-timer.c
@@ -3,6 +3,7 @@
* Copytight (C) 1999, 2000 Silicon Graphics, Inc.
*/
#include <linux/bcd.h>
+#include <linux/clockchips.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -25,22 +26,8 @@
#include <asm/sn/sn0/ip27.h>
#include <asm/sn/sn0/hub.h>
-/*
- * This is a hack; we really need to figure these values out dynamically
- *
- * Since 800 ns works very well with various HUB frequencies, such as
- * 360, 380, 390 and 400 MHZ, we use 800 ns rtc cycle time.
- *
- * Ralf: which clock rate is used to feed the counter?
- */
-#define NSEC_PER_CYCLE 800
-#define CYCLES_PER_SEC (NSEC_PER_SEC/NSEC_PER_CYCLE)
-#define CYCLES_PER_JIFFY (CYCLES_PER_SEC/HZ)
-
#define TICK_SIZE (tick_nsec / 1000)
-static unsigned long ct_cur[NR_CPUS]; /* What counter should be at next timer irq */
-
#if 0
static int set_rtc_mmss(unsigned long nowtime)
{
@@ -86,36 +73,6 @@ static int set_rtc_mmss(unsigned long nowtime)
}
#endif
-static unsigned int rt_timer_irq;
-
-void ip27_rt_timer_interrupt(void)
-{
- int cpu = smp_processor_id();
- int cpuA = cputoslice(cpu) == 0;
- unsigned int irq = rt_timer_irq;
-
- irq_enter();
- write_seqlock(&xtime_lock);
-
-again:
- LOCAL_HUB_S(cpuA ? PI_RT_PEND_A : PI_RT_PEND_B, 0); /* Ack */
- ct_cur[cpu] += CYCLES_PER_JIFFY;
- LOCAL_HUB_S(cpuA ? PI_RT_COMPARE_A : PI_RT_COMPARE_B, ct_cur[cpu]);
-
- if (LOCAL_HUB_L(PI_RT_COUNT) >= ct_cur[cpu])
- goto again;
-
- kstat_this_cpu.irqs[irq]++; /* kstat only for bootcpu? */
-
- if (cpu == 0)
- do_timer(1);
-
- update_process_times(user_mode(get_irq_regs()));
-
- write_sequnlock(&xtime_lock);
- irq_exit();
-}
-
/* Includes for ioc3_init(). */
#include <asm/sn/types.h>
#include <asm/sn/sn0/addrs.h>
@@ -171,33 +128,112 @@ static struct irq_chip rt_irq_type = {
.eoi = enable_rt_irq,
};
-static struct irqaction rt_irqaction = {
- .handler = (irq_handler_t) ip27_rt_timer_interrupt,
- .flags = IRQF_DISABLED,
- .mask = CPU_MASK_NONE,
- .name = "timer"
-};
-
-void __init plat_timer_setup(struct irqaction *irq)
+static int rt_next_event(unsigned long delta, struct clock_event_device *evt)
{
- int irqno = allocate_irqno();
+ unsigned int cpu = smp_processor_id();
+ int slice = cputoslice(cpu);
+ unsigned long cnt;
- if (irqno < 0)
- panic("Can't allocate interrupt number for timer interrupt");
+ cnt = LOCAL_HUB_L(PI_RT_COUNT);
+ cnt += delta;
+ LOCAL_HUB_S(PI_RT_COMPARE_A + PI_COUNT_OFFSET * slice, cnt);
+
+ return LOCAL_HUB_L(PI_RT_COUNT) >= cnt ? -ETIME : 0;
+}
- set_irq_chip_and_handler(irqno, &rt_irq_type, handle_percpu_irq);
+static void rt_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ switch (mode) {
+ case CLOCK_EVT_MODE_ONESHOT:
+ /* The only mode supported */
+ break;
+
+ case CLOCK_EVT_MODE_PERIODIC:
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ case CLOCK_EVT_MODE_RESUME:
+ /* Nothing to do */
+ break;
+ }
+}
- /* over-write the handler, we use our own way */
- irq->handler = no_action;
+unsigned int rt_timer_irq;
- /* setup irqaction */
- irq_desc[irqno].status |= IRQ_PER_CPU;
+static irqreturn_t hub_rt_counter_handler(int irq, void *dev_id)
+{
+ struct clock_event_device *cd = dev_id;
+ unsigned int cpu = smp_processor_id();
+ int slice = cputoslice(cpu);
- rt_timer_irq = irqno;
/*
- * Only needed to get /proc/interrupt to display timer irq stats
+ * Ack
*/
- setup_irq(irqno, &rt_irqaction);
+ LOCAL_HUB_S(PI_RT_PEND_A + PI_COUNT_OFFSET * slice, 0);
+ cd->event_handler(cd);
+
+ return IRQ_HANDLED;
+}
+
+struct irqaction hub_rt_irqaction = {
+ .handler = hub_rt_counter_handler,
+ .flags = IRQF_DISABLED | IRQF_PERCPU,
+ .name = "hub-rt",
+};
+
+/*
+ * This is a hack; we really need to figure these values out dynamically
+ *
+ * Since 800 ns works very well with various HUB frequencies, such as
+ * 360, 380, 390 and 400 MHZ, we use 800 ns rtc cycle time.
+ *
+ * Ralf: which clock rate is used to feed the counter?
+ */
+#define NSEC_PER_CYCLE 800
+#define CYCLES_PER_SEC (NSEC_PER_SEC / NSEC_PER_CYCLE)
+
+static DEFINE_PER_CPU(struct clock_event_device, hub_rt_clockevent);
+static DEFINE_PER_CPU(char [11], hub_rt_name);
+
+static void __cpuinit hub_rt_clock_event_init(void)
+{
+ unsigned int cpu = smp_processor_id();
+ struct clock_event_device *cd = &per_cpu(hub_rt_clockevent, cpu);
+ unsigned char *name = per_cpu(hub_rt_name, cpu);
+ int irq = rt_timer_irq;
+
+ sprintf(name, "hub-rt %d", cpu);
+ cd->name = "HUB-RT",
+ cd->features = CLOCK_EVT_FEAT_ONESHOT,
+ clockevent_set_clock(cd, CYCLES_PER_SEC);
+ cd->max_delta_ns = clockevent_delta2ns(0xfffffffffffff, cd);
+ cd->min_delta_ns = clockevent_delta2ns(0x300, cd);
+ cd->rating = 200,
+ cd->irq = irq,
+ cd->cpumask = cpumask_of_cpu(cpu),
+ cd->rating = 300,
+ cd->set_next_event = rt_next_event,
+ cd->set_mode = rt_set_mode,
+ clockevents_register_device(cd);
+}
+
+static void __init hub_rt_clock_event_global_init(void)
+{
+ unsigned int irq;
+
+ do {
+ smp_wmb();
+ irq = rt_timer_irq;
+ if (irq)
+ break;
+
+ irq = allocate_irqno();
+ if (irq < 0)
+ panic("Allocation of irq number for timer failed");
+ } while (xchg(&rt_timer_irq, irq));
+
+ set_irq_chip_and_handler(irq, &rt_irq_type, handle_percpu_irq);
+ setup_irq(irq, &hub_rt_irqaction);
}
static cycle_t hub_rt_read(void)
@@ -205,21 +241,29 @@ static cycle_t hub_rt_read(void)
return REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT);
}
-struct clocksource ht_rt_clocksource = {
- .name = "HUB",
+struct clocksource hub_rt_clocksource = {
+ .name = "HUB-RT",
.rating = 200,
.read = hub_rt_read,
.mask = CLOCKSOURCE_MASK(52),
- .shift = 32,
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
+static void __init hub_rt_clocksource_init(void)
+{
+ struct clocksource *cs = &hub_rt_clocksource;
+
+ clocksource_set_clock(cs, CYCLES_PER_SEC);
+ clocksource_register(cs);
+}
+
void __init plat_time_init(void)
{
- clocksource_register(&ht_rt_clocksource);
+ hub_rt_clocksource_init();
+ hub_rt_clock_event_global_init();
}
-void __init cpu_time_init(void)
+void __cpuinit cpu_time_init(void)
{
lboard_t *board;
klcpu_t *cpu;
@@ -237,6 +281,7 @@ void __init cpu_time_init(void)
printk("CPU %d clock is %dMHz.\n", smp_processor_id(), cpu->cpu_speed);
+ hub_rt_clock_event_init();
set_c0_status(SRB_TIMOCLK);
}
@@ -248,17 +293,12 @@ void __init hub_rtc_init(cnodeid_t cnode)
* node and timeouts will not happen there.
*/
if (get_compact_nodeid() == cnode) {
- int cpu = smp_processor_id();
LOCAL_HUB_S(PI_RT_EN_A, 1);
LOCAL_HUB_S(PI_RT_EN_B, 1);
LOCAL_HUB_S(PI_PROF_EN_A, 0);
LOCAL_HUB_S(PI_PROF_EN_B, 0);
- ct_cur[cpu] = CYCLES_PER_JIFFY;
- LOCAL_HUB_S(PI_RT_COMPARE_A, ct_cur[cpu]);
LOCAL_HUB_S(PI_RT_COUNT, 0);
LOCAL_HUB_S(PI_RT_PEND_A, 0);
- LOCAL_HUB_S(PI_RT_COMPARE_B, ct_cur[cpu]);
- LOCAL_HUB_S(PI_RT_COUNT, 0);
LOCAL_HUB_S(PI_RT_PEND_B, 0);
}
}
diff --git a/arch/mips/sgi-ip32/ip32-irq.c b/arch/mips/sgi-ip32/ip32-irq.c
index 7f4b793c3df3..aab17ddd2f30 100644
--- a/arch/mips/sgi-ip32/ip32-irq.c
+++ b/arch/mips/sgi-ip32/ip32-irq.c
@@ -20,6 +20,7 @@
#include <linux/random.h>
#include <linux/sched.h>
+#include <asm/irq_cpu.h>
#include <asm/mipsregs.h>
#include <asm/signal.h>
#include <asm/system.h>
@@ -39,14 +40,8 @@ static void inline flush_mace_bus(void)
mace->perif.ctrl.misc;
}
-#undef DEBUG_IRQ
-#ifdef DEBUG_IRQ
-#define DBG(x...) printk(x)
-#else
-#define DBG(x...)
-#endif
-
-/* O2 irq map
+/*
+ * O2 irq map
*
* IP0 -> software (ignored)
* IP1 -> software (ignored)
@@ -55,60 +50,60 @@ static void inline flush_mace_bus(void)
* IP4 -> (irq2) X unknown
* IP5 -> (irq3) X unknown
* IP6 -> (irq4) X unknown
- * IP7 -> (irq5) 0 CPU count/compare timer (system timer)
+ * IP7 -> (irq5) 7 CPU count/compare timer (system timer)
*
* crime: (C)
*
* CRIME_INT_STAT 31:0:
*
- * 0 -> 1 Video in 1
- * 1 -> 2 Video in 2
- * 2 -> 3 Video out
- * 3 -> 4 Mace ethernet
+ * 0 -> 8 Video in 1
+ * 1 -> 9 Video in 2
+ * 2 -> 10 Video out
+ * 3 -> 11 Mace ethernet
* 4 -> S SuperIO sub-interrupt
* 5 -> M Miscellaneous sub-interrupt
* 6 -> A Audio sub-interrupt
- * 7 -> 8 PCI bridge errors
- * 8 -> 9 PCI SCSI aic7xxx 0
- * 9 -> 10 PCI SCSI aic7xxx 1
- * 10 -> 11 PCI slot 0
- * 11 -> 12 unused (PCI slot 1)
- * 12 -> 13 unused (PCI slot 2)
- * 13 -> 14 unused (PCI shared 0)
- * 14 -> 15 unused (PCI shared 1)
- * 15 -> 16 unused (PCI shared 2)
- * 16 -> 17 GBE0 (E)
- * 17 -> 18 GBE1 (E)
- * 18 -> 19 GBE2 (E)
- * 19 -> 20 GBE3 (E)
- * 20 -> 21 CPU errors
- * 21 -> 22 Memory errors
- * 22 -> 23 RE empty edge (E)
- * 23 -> 24 RE full edge (E)
- * 24 -> 25 RE idle edge (E)
- * 25 -> 26 RE empty level
- * 26 -> 27 RE full level
- * 27 -> 28 RE idle level
- * 28 -> 29 unused (software 0) (E)
- * 29 -> 30 unused (software 1) (E)
- * 30 -> 31 unused (software 2) - crime 1.5 CPU SysCorError (E)
- * 31 -> 32 VICE
+ * 7 -> 15 PCI bridge errors
+ * 8 -> 16 PCI SCSI aic7xxx 0
+ * 9 -> 17 PCI SCSI aic7xxx 1
+ * 10 -> 18 PCI slot 0
+ * 11 -> 19 unused (PCI slot 1)
+ * 12 -> 20 unused (PCI slot 2)
+ * 13 -> 21 unused (PCI shared 0)
+ * 14 -> 22 unused (PCI shared 1)
+ * 15 -> 23 unused (PCI shared 2)
+ * 16 -> 24 GBE0 (E)
+ * 17 -> 25 GBE1 (E)
+ * 18 -> 26 GBE2 (E)
+ * 19 -> 27 GBE3 (E)
+ * 20 -> 28 CPU errors
+ * 21 -> 29 Memory errors
+ * 22 -> 30 RE empty edge (E)
+ * 23 -> 31 RE full edge (E)
+ * 24 -> 32 RE idle edge (E)
+ * 25 -> 33 RE empty level
+ * 26 -> 34 RE full level
+ * 27 -> 35 RE idle level
+ * 28 -> 36 unused (software 0) (E)
+ * 29 -> 37 unused (software 1) (E)
+ * 30 -> 38 unused (software 2) - crime 1.5 CPU SysCorError (E)
+ * 31 -> 39 VICE
*
* S, M, A: Use the MACE ISA interrupt register
* MACE_ISA_INT_STAT 31:0
*
- * 0-7 -> 33-40 Audio
- * 8 -> 41 RTC
- * 9 -> 42 Keyboard
+ * 0-7 -> 40-47 Audio
+ * 8 -> 48 RTC
+ * 9 -> 49 Keyboard
* 10 -> X Keyboard polled
- * 11 -> 44 Mouse
+ * 11 -> 51 Mouse
* 12 -> X Mouse polled
- * 13-15 -> 46-48 Count/compare timers
- * 16-19 -> 49-52 Parallel (16 E)
- * 20-25 -> 53-58 Serial 1 (22 E)
- * 26-31 -> 59-64 Serial 2 (28 E)
+ * 13-15 -> 53-55 Count/compare timers
+ * 16-19 -> 56-59 Parallel (16 E)
+ * 20-25 -> 60-62 Serial 1 (22 E)
+ * 26-31 -> 66-71 Serial 2 (28 E)
*
- * Note that this means IRQs 5-7, 43, and 45 do not exist. This is a
+ * Note that this means IRQs 12-14, 50, and 52 do not exist. This is a
* different IRQ map than IRIX uses, but that's OK as Linux irq handling
* is quite different anyway.
*/
@@ -123,6 +118,7 @@ struct irqaction memerr_irq = {
.mask = CPU_MASK_NONE,
.name = "CRIME memory error",
};
+
struct irqaction cpuerr_irq = {
.handler = crime_cpuerr_intr,
.flags = IRQF_DISABLED,
@@ -131,82 +127,76 @@ struct irqaction cpuerr_irq = {
};
/*
- * For interrupts wired from a single device to the CPU. Only the clock
- * uses this it seems, which is IRQ 0 and IP7.
- */
-
-static void enable_cpu_irq(unsigned int irq)
-{
- set_c0_status(STATUSF_IP7);
-}
-
-static void disable_cpu_irq(unsigned int irq)
-{
- clear_c0_status(STATUSF_IP7);
-}
-
-static void end_cpu_irq(unsigned int irq)
-{
- if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
- enable_cpu_irq(irq);
-}
-
-static struct irq_chip ip32_cpu_interrupt = {
- .name = "IP32 CPU",
- .ack = disable_cpu_irq,
- .mask = disable_cpu_irq,
- .mask_ack = disable_cpu_irq,
- .unmask = enable_cpu_irq,
- .end = end_cpu_irq,
-};
-
-/*
* This is for pure CRIME interrupts - ie not MACE. The advantage?
* We get to split the register in half and do faster lookups.
*/
static uint64_t crime_mask;
-static void enable_crime_irq(unsigned int irq)
+static inline void crime_enable_irq(unsigned int irq)
{
- crime_mask |= 1 << (irq - 1);
+ unsigned int bit = irq - CRIME_IRQ_BASE;
+
+ crime_mask |= 1 << bit;
crime->imask = crime_mask;
}
-static void disable_crime_irq(unsigned int irq)
+static inline void crime_disable_irq(unsigned int irq)
{
- crime_mask &= ~(1 << (irq - 1));
+ unsigned int bit = irq - CRIME_IRQ_BASE;
+
+ crime_mask &= ~(1 << bit);
crime->imask = crime_mask;
flush_crime_bus();
}
-static void mask_and_ack_crime_irq(unsigned int irq)
+static void crime_level_mask_and_ack_irq(unsigned int irq)
+{
+ crime_disable_irq(irq);
+}
+
+static void crime_level_end_irq(unsigned int irq)
{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+ crime_enable_irq(irq);
+}
+
+static struct irq_chip crime_level_interrupt = {
+ .name = "IP32 CRIME",
+ .ack = crime_level_mask_and_ack_irq,
+ .mask = crime_disable_irq,
+ .mask_ack = crime_level_mask_and_ack_irq,
+ .unmask = crime_enable_irq,
+ .end = crime_level_end_irq,
+};
+
+static void crime_edge_mask_and_ack_irq(unsigned int irq)
+{
+ unsigned int bit = irq - CRIME_IRQ_BASE;
+ uint64_t crime_int;
+
/* Edge triggered interrupts must be cleared. */
- if ((irq >= CRIME_GBE0_IRQ && irq <= CRIME_GBE3_IRQ)
- || (irq >= CRIME_RE_EMPTY_E_IRQ && irq <= CRIME_RE_IDLE_E_IRQ)
- || (irq >= CRIME_SOFT0_IRQ && irq <= CRIME_SOFT2_IRQ)) {
- uint64_t crime_int;
- crime_int = crime->hard_int;
- crime_int &= ~(1 << (irq - 1));
- crime->hard_int = crime_int;
- }
- disable_crime_irq(irq);
+
+ crime_int = crime->hard_int;
+ crime_int &= ~(1 << bit);
+ crime->hard_int = crime_int;
+
+ crime_disable_irq(irq);
}
-static void end_crime_irq(unsigned int irq)
+static void crime_edge_end_irq(unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
- enable_crime_irq(irq);
+ crime_enable_irq(irq);
}
-static struct irq_chip ip32_crime_interrupt = {
- .name = "IP32 CRIME",
- .ack = mask_and_ack_crime_irq,
- .mask = disable_crime_irq,
- .mask_ack = mask_and_ack_crime_irq,
- .unmask = enable_crime_irq,
- .end = end_crime_irq,
+static struct irq_chip crime_edge_interrupt = {
+ .name = "IP32 CRIME",
+ .ack = crime_edge_mask_and_ack_irq,
+ .mask = crime_disable_irq,
+ .mask_ack = crime_edge_mask_and_ack_irq,
+ .unmask = crime_enable_irq,
+ .end = crime_edge_end_irq,
};
/*
@@ -293,7 +283,7 @@ static void enable_maceisa_irq(unsigned int irq)
{
unsigned int crime_int = 0;
- DBG("maceisa enable: %u\n", irq);
+ pr_debug("maceisa enable: %u\n", irq);
switch (irq) {
case MACEISA_AUDIO_SW_IRQ ... MACEISA_AUDIO3_MERR_IRQ:
@@ -306,7 +296,7 @@ static void enable_maceisa_irq(unsigned int irq)
crime_int = MACE_SUPERIO_INT;
break;
}
- DBG("crime_int %08x enabled\n", crime_int);
+ pr_debug("crime_int %08x enabled\n", crime_int);
crime_mask |= crime_int;
crime->imask = crime_mask;
maceisa_mask |= 1 << (irq - 33);
@@ -318,11 +308,11 @@ static void disable_maceisa_irq(unsigned int irq)
unsigned int crime_int = 0;
maceisa_mask &= ~(1 << (irq - 33));
- if(!(maceisa_mask & MACEISA_AUDIO_INT))
+ if (!(maceisa_mask & MACEISA_AUDIO_INT))
crime_int |= MACE_AUDIO_INT;
- if(!(maceisa_mask & MACEISA_MISC_INT))
+ if (!(maceisa_mask & MACEISA_MISC_INT))
crime_int |= MACE_MISC_INT;
- if(!(maceisa_mask & MACEISA_SUPERIO_INT))
+ if (!(maceisa_mask & MACEISA_SUPERIO_INT))
crime_int |= MACE_SUPERIO_INT;
crime_mask &= ~crime_int;
crime->imask = crime_mask;
@@ -355,12 +345,12 @@ static void end_maceisa_irq(unsigned irq)
}
static struct irq_chip ip32_maceisa_interrupt = {
- .name = "IP32 MACE ISA",
- .ack = mask_and_ack_maceisa_irq,
- .mask = disable_maceisa_irq,
- .mask_ack = mask_and_ack_maceisa_irq,
- .unmask = enable_maceisa_irq,
- .end = end_maceisa_irq,
+ .name = "IP32 MACE ISA",
+ .ack = mask_and_ack_maceisa_irq,
+ .mask = disable_maceisa_irq,
+ .mask_ack = mask_and_ack_maceisa_irq,
+ .unmask = enable_maceisa_irq,
+ .end = end_maceisa_irq,
};
/* This is used for regular non-ISA, non-PCI MACE interrupts. That means
@@ -422,16 +412,24 @@ static void ip32_irq0(void)
uint64_t crime_int;
int irq = 0;
+ /*
+ * Sanity check interrupt numbering enum.
+ * MACE got 32 interrupts and there are 32 MACE ISA interrupts daisy
+ * chained.
+ */
+ BUILD_BUG_ON(CRIME_VICE_IRQ - MACE_VID_IN1_IRQ != 31);
+ BUILD_BUG_ON(MACEISA_SERIAL2_RDMAOR_IRQ - MACEISA_AUDIO_SW_IRQ != 31);
+
crime_int = crime->istat & crime_mask;
- irq = __ffs(crime_int);
+ irq = MACE_VID_IN1_IRQ + __ffs(crime_int);
crime_int = 1 << irq;
if (crime_int & CRIME_MACEISA_INT_MASK) {
unsigned long mace_int = mace->perif.ctrl.istat;
- irq = __ffs(mace_int & maceisa_mask) + 32;
+ irq = __ffs(mace_int & maceisa_mask) + MACEISA_AUDIO_SW_IRQ;
}
- irq++;
- DBG("*irq %u*\n", irq);
+
+ pr_debug("*irq %u*\n", irq);
do_IRQ(irq);
}
@@ -457,7 +455,7 @@ static void ip32_irq4(void)
static void ip32_irq5(void)
{
- do_IRQ(IP32_R4K_TIMER_IRQ);
+ do_IRQ(MIPS_CPU_IRQ_BASE + 7);
}
asmlinkage void plat_irq_dispatch(void)
@@ -490,21 +488,33 @@ void __init arch_init_irq(void)
mace->perif.ctrl.istat = 0;
mace->perif.ctrl.imask = 0;
- for (irq = 0; irq <= IP32_IRQ_MAX; irq++) {
- struct irq_chip *controller;
-
- if (irq == IP32_R4K_TIMER_IRQ)
- controller = &ip32_cpu_interrupt;
- else if (irq <= MACE_PCI_BRIDGE_IRQ && irq >= MACE_VID_IN1_IRQ)
- controller = &ip32_mace_interrupt;
- else if (irq <= MACEPCI_SHARED2_IRQ && irq >= MACEPCI_SCSI0_IRQ)
- controller = &ip32_macepci_interrupt;
- else if (irq <= CRIME_VICE_IRQ && irq >= CRIME_GBE0_IRQ)
- controller = &ip32_crime_interrupt;
- else
- controller = &ip32_maceisa_interrupt;
-
- set_irq_chip(irq, controller);
+ mips_cpu_irq_init();
+ for (irq = MIPS_CPU_IRQ_BASE + 8; irq <= IP32_IRQ_MAX; irq++) {
+ switch (irq) {
+ case MACE_VID_IN1_IRQ ... MACE_PCI_BRIDGE_IRQ:
+ set_irq_chip(irq, &ip32_mace_interrupt);
+ break;
+ case MACEPCI_SCSI0_IRQ ... MACEPCI_SHARED2_IRQ:
+ set_irq_chip(irq, &ip32_macepci_interrupt);
+ break;
+ case CRIME_GBE0_IRQ ... CRIME_GBE3_IRQ:
+ set_irq_chip(irq, &crime_edge_interrupt);
+ break;
+ case CRIME_CPUERR_IRQ:
+ case CRIME_MEMERR_IRQ:
+ set_irq_chip(irq, &crime_level_interrupt);
+ break;
+ case CRIME_RE_EMPTY_E_IRQ ... CRIME_RE_IDLE_E_IRQ:
+ case CRIME_SOFT0_IRQ ... CRIME_SOFT2_IRQ:
+ set_irq_chip(irq, &crime_edge_interrupt);
+ break;
+ case CRIME_VICE_IRQ:
+ set_irq_chip(irq, &crime_edge_interrupt);
+ break;
+ default:
+ set_irq_chip(irq, &ip32_maceisa_interrupt);
+ break;
+ }
}
setup_irq(CRIME_MEMERR_IRQ, &memerr_irq);
setup_irq(CRIME_CPUERR_IRQ, &cpuerr_irq);
diff --git a/arch/mips/sgi-ip32/ip32-platform.c b/arch/mips/sgi-ip32/ip32-platform.c
index 7309e48d163d..77febd68fcd4 100644
--- a/arch/mips/sgi-ip32/ip32-platform.c
+++ b/arch/mips/sgi-ip32/ip32-platform.c
@@ -42,7 +42,7 @@ static struct platform_device uart8250_device = {
static int __init uart8250_init(void)
{
uart8250_data[0].membase = (void __iomem *) &mace->isa.serial1;
- uart8250_data[1].membase = (void __iomem *) &mace->isa.serial1;
+ uart8250_data[1].membase = (void __iomem *) &mace->isa.serial2;
return platform_device_register(&uart8250_device);
}
diff --git a/arch/mips/sgi-ip32/ip32-setup.c b/arch/mips/sgi-ip32/ip32-setup.c
index 4125a5ba119e..1024bf40bd9e 100644
--- a/arch/mips/sgi-ip32/ip32-setup.c
+++ b/arch/mips/sgi-ip32/ip32-setup.c
@@ -80,12 +80,6 @@ void __init plat_time_init(void)
printk("%d MHz CPU detected\n", mips_hpt_frequency * 2 / 1000000);
}
-void __init plat_timer_setup(struct irqaction *irq)
-{
- irq->handler = no_action;
- setup_irq(IP32_R4K_TIMER_IRQ, irq);
-}
-
void __init plat_mem_setup(void)
{
board_be_init = ip32_be_init;
diff --git a/arch/mips/sibyte/Kconfig b/arch/mips/sibyte/Kconfig
index e8fb880272bd..366b19d33f77 100644
--- a/arch/mips/sibyte/Kconfig
+++ b/arch/mips/sibyte/Kconfig
@@ -1,5 +1,7 @@
config SIBYTE_SB1250
bool
+ select CEVT_SB1250
+ select CSRC_SB1250
select HW_HAS_PCI
select IRQ_CPU
select SIBYTE_ENABLE_LDT_IF_PCI
@@ -9,6 +11,8 @@ config SIBYTE_SB1250
config SIBYTE_BCM1120
bool
+ select CEVT_SB1250
+ select CSRC_SB1250
select IRQ_CPU
select SIBYTE_BCM112X
select SIBYTE_HAS_ZBUS_PROFILING
@@ -16,6 +20,8 @@ config SIBYTE_BCM1120
config SIBYTE_BCM1125
bool
+ select CEVT_SB1250
+ select CSRC_SB1250
select HW_HAS_PCI
select IRQ_CPU
select SIBYTE_BCM112X
@@ -24,6 +30,8 @@ config SIBYTE_BCM1125
config SIBYTE_BCM1125H
bool
+ select CEVT_SB1250
+ select CSRC_SB1250
select HW_HAS_PCI
select IRQ_CPU
select SIBYTE_BCM112X
@@ -33,12 +41,16 @@ config SIBYTE_BCM1125H
config SIBYTE_BCM112X
bool
+ select CEVT_SB1250
+ select CSRC_SB1250
select IRQ_CPU
select SIBYTE_SB1xxx_SOC
select SIBYTE_HAS_ZBUS_PROFILING
config SIBYTE_BCM1x80
bool
+ select CEVT_BCM1480
+ select CSRC_BCM1480
select HW_HAS_PCI
select IRQ_CPU
select SIBYTE_HAS_ZBUS_PROFILING
@@ -47,6 +59,8 @@ config SIBYTE_BCM1x80
config SIBYTE_BCM1x55
bool
+ select CEVT_BCM1480
+ select CSRC_BCM1480
select HW_HAS_PCI
select IRQ_CPU
select SIBYTE_SB1xxx_SOC
diff --git a/arch/mips/sibyte/bcm1480/irq.c b/arch/mips/sibyte/bcm1480/irq.c
index 7aa79bf63c4a..db372a0f106d 100644
--- a/arch/mips/sibyte/bcm1480/irq.c
+++ b/arch/mips/sibyte/bcm1480/irq.c
@@ -265,42 +265,6 @@ void __init init_bcm1480_irqs(void)
}
}
-
-static irqreturn_t bcm1480_dummy_handler(int irq, void *dev_id)
-{
- return IRQ_NONE;
-}
-
-static struct irqaction bcm1480_dummy_action = {
- .handler = bcm1480_dummy_handler,
- .flags = 0,
- .mask = CPU_MASK_NONE,
- .name = "bcm1480-private",
- .next = NULL,
- .dev_id = 0
-};
-
-int bcm1480_steal_irq(int irq)
-{
- struct irq_desc *desc = irq_desc + irq;
- unsigned long flags;
- int retval = 0;
-
- if (irq >= BCM1480_NR_IRQS)
- return -EINVAL;
-
- spin_lock_irqsave(&desc->lock, flags);
- /* Don't allow sharing at all for these */
- if (desc->action != NULL)
- retval = -EBUSY;
- else {
- desc->action = &bcm1480_dummy_action;
- desc->depth = 0;
- }
- spin_unlock_irqrestore(&desc->lock, flags);
- return 0;
-}
-
/*
* init_IRQ is called early in the boot sequence from init/main.c. It
* is responsible for setting up the interrupt mapper and installing the
@@ -329,7 +293,6 @@ int bcm1480_steal_irq(int irq)
void __init arch_init_irq(void)
{
-
unsigned int i, cpu;
u64 tmp;
unsigned int imask = STATUSF_IP4 | STATUSF_IP3 | STATUSF_IP2 |
@@ -386,8 +349,6 @@ void __init arch_init_irq(void)
__raw_writeq(tmp, IOADDR(A_BCM1480_IMR_REGISTER(cpu, R_BCM1480_IMR_INTERRUPT_MASK_L)));
}
- bcm1480_steal_irq(K_BCM1480_INT_MBOX_0_0);
-
/*
* Note that the timer interrupts are also mapped, but this is
* done in bcm1480_time_init(). Also, the profiling driver
@@ -409,12 +370,11 @@ void __init arch_init_irq(void)
#endif
/* Setup uart 1 settings, mapper */
/* QQQ FIXME */
- __raw_writeq(M_DUART_IMR_BRK, IO_SPACE_BASE + A_DUART_IMRREG(kgdb_port));
+ __raw_writeq(M_DUART_IMR_BRK, IOADDR(A_DUART_IMRREG(kgdb_port)));
- bcm1480_steal_irq(kgdb_irq);
__raw_writeq(IMR_IP6_VAL,
- IO_SPACE_BASE + A_BCM1480_IMR_REGISTER(0, R_BCM1480_IMR_INTERRUPT_MAP_BASE_H) +
- (kgdb_irq<<3));
+ IOADDR(A_BCM1480_IMR_REGISTER(0, R_BCM1480_IMR_INTERRUPT_MAP_BASE_H) +
+ (kgdb_irq << 3)));
bcm1480_unmask_irq(0, kgdb_irq);
#ifdef CONFIG_GDB_CONSOLE
@@ -452,8 +412,34 @@ static void bcm1480_kgdb_interrupt(void)
extern void bcm1480_mailbox_interrupt(void);
+static inline void dispatch_ip2(void)
+{
+ unsigned long long mask_h, mask_l;
+ unsigned int cpu = smp_processor_id();
+ unsigned long base;
+
+ /*
+ * Default...we've hit an IP[2] interrupt, which means we've got to
+ * check the 1480 interrupt registers to figure out what to do. Need
+ * to detect which CPU we're on, now that smp_affinity is supported.
+ */
+ base = A_BCM1480_IMR_MAPPER(cpu);
+ mask_h = __raw_readq(
+ IOADDR(base + R_BCM1480_IMR_INTERRUPT_STATUS_BASE_H));
+ mask_l = __raw_readq(
+ IOADDR(base + R_BCM1480_IMR_INTERRUPT_STATUS_BASE_L));
+
+ if (mask_h) {
+ if (mask_h ^ 1)
+ do_IRQ(fls64(mask_h) - 1);
+ else if (mask_l)
+ do_IRQ(63 + fls64(mask_l));
+ }
+}
+
asmlinkage void plat_irq_dispatch(void)
{
+ unsigned int cpu = smp_processor_id();
unsigned int pending;
#ifdef CONFIG_SIBYTE_BCM1480_PROF
@@ -469,17 +455,8 @@ asmlinkage void plat_irq_dispatch(void)
else
#endif
- if (pending & CAUSEF_IP4) {
- int cpu = smp_processor_id();
- int irq = K_BCM1480_INT_TIMER_0 + cpu;
-
- /* Reset the timer */
- __raw_writeq(M_SCD_TIMER_ENABLE|M_SCD_TIMER_MODE_CONTINUOUS,
- IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
-
- do_IRQ(irq);
- }
-
+ if (pending & CAUSEF_IP4)
+ do_IRQ(K_BCM1480_INT_TIMER_0 + cpu);
#ifdef CONFIG_SMP
else if (pending & CAUSEF_IP3)
bcm1480_mailbox_interrupt();
@@ -490,27 +467,6 @@ asmlinkage void plat_irq_dispatch(void)
bcm1480_kgdb_interrupt(); /* KGDB (uart 1) */
#endif
- else if (pending & CAUSEF_IP2) {
- unsigned long long mask_h, mask_l;
- unsigned long base;
-
- /*
- * Default...we've hit an IP[2] interrupt, which means we've
- * got to check the 1480 interrupt registers to figure out what
- * to do. Need to detect which CPU we're on, now that
- * smp_affinity is supported.
- */
- base = A_BCM1480_IMR_MAPPER(smp_processor_id());
- mask_h = __raw_readq(
- IOADDR(base + R_BCM1480_IMR_INTERRUPT_STATUS_BASE_H));
- mask_l = __raw_readq(
- IOADDR(base + R_BCM1480_IMR_INTERRUPT_STATUS_BASE_L));
-
- if (mask_h) {
- if (mask_h ^ 1)
- do_IRQ(fls64(mask_h) - 1);
- else
- do_IRQ(63 + fls64(mask_l));
- }
- }
+ else if (pending & CAUSEF_IP2)
+ dispatch_ip2();
}
diff --git a/arch/mips/sibyte/bcm1480/smp.c b/arch/mips/sibyte/bcm1480/smp.c
index 6eac36d1b8c8..436ba78359ab 100644
--- a/arch/mips/sibyte/bcm1480/smp.c
+++ b/arch/mips/sibyte/bcm1480/smp.c
@@ -58,7 +58,7 @@ static void *mailbox_0_regs[] = {
/*
* SMP init and finish on secondary CPUs
*/
-void bcm1480_smp_init(void)
+void __cpuinit bcm1480_smp_init(void)
{
unsigned int imask = STATUSF_IP4 | STATUSF_IP3 | STATUSF_IP2 |
STATUSF_IP1 | STATUSF_IP0;
@@ -67,10 +67,11 @@ void bcm1480_smp_init(void)
change_c0_status(ST0_IM, imask);
}
-void bcm1480_smp_finish(void)
+void __cpuinit bcm1480_smp_finish(void)
{
- extern void bcm1480_time_init(void);
- bcm1480_time_init();
+ extern void sb1480_clockevent_init(void);
+
+ sb1480_clockevent_init();
local_irq_enable();
}
diff --git a/arch/mips/sibyte/bcm1480/time.c b/arch/mips/sibyte/bcm1480/time.c
index 40d7126cd5bf..1680a68952ae 100644
--- a/arch/mips/sibyte/bcm1480/time.c
+++ b/arch/mips/sibyte/bcm1480/time.c
@@ -15,162 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
+#include <linux/init.h>
-/*
- * These are routines to set up and handle interrupts from the
- * bcm1480 general purpose timer 0. We're using the timer as a
- * system clock, so we set it up to run at 100 Hz. On every
- * interrupt, we update our idea of what the time of day is,
- * then call do_timer() in the architecture-independent kernel
- * code to do general bookkeeping (e.g. update jiffies, run
- * bottom halves, etc.)
- */
-#include <linux/clockchips.h>
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/kernel_stat.h>
-
-#include <asm/irq.h>
-#include <asm/addrspace.h>
-#include <asm/time.h>
-#include <asm/io.h>
-
-#include <asm/sibyte/bcm1480_regs.h>
-#include <asm/sibyte/sb1250_regs.h>
-#include <asm/sibyte/bcm1480_int.h>
-#include <asm/sibyte/bcm1480_scd.h>
-
-#include <asm/sibyte/sb1250.h>
-
-
-#define IMR_IP2_VAL K_BCM1480_INT_MAP_I0
-#define IMR_IP3_VAL K_BCM1480_INT_MAP_I1
-#define IMR_IP4_VAL K_BCM1480_INT_MAP_I2
-
-#ifdef CONFIG_SIMULATION
-#define BCM1480_HPT_VALUE 50000
-#else
-#define BCM1480_HPT_VALUE 1000000
-#endif
-
-extern int bcm1480_steal_irq(int irq);
+extern void sb1480_clockevent_init(void);
+extern void sb1480_clocksource_init(void);
void __init plat_time_init(void)
{
- unsigned int cpu = smp_processor_id();
- unsigned int irq = K_BCM1480_INT_TIMER_0 + cpu;
-
- BUG_ON(cpu > 3); /* Only have 4 general purpose timers */
-
- bcm1480_mask_irq(cpu, irq);
-
- /* Map the timer interrupt to ip[4] of this cpu */
- __raw_writeq(IMR_IP4_VAL, IOADDR(A_BCM1480_IMR_REGISTER(cpu, R_BCM1480_IMR_INTERRUPT_MAP_BASE_H)
- + (irq<<3)));
-
- bcm1480_unmask_irq(cpu, irq);
- bcm1480_steal_irq(irq);
-}
-
-/*
- * The general purpose timer ticks at 1 Mhz independent if
- * the rest of the system
- */
-static void sibyte_set_mode(enum clock_event_mode mode,
- struct clock_event_device *evt)
-{
- unsigned int cpu = smp_processor_id();
- void __iomem *timer_cfg, *timer_init;
-
- timer_cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
- timer_init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
-
- switch (mode) {
- case CLOCK_EVT_MODE_PERIODIC:
- __raw_writeq(0, timer_cfg);
- __raw_writeq(BCM1480_HPT_VALUE / HZ - 1, timer_init);
- __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
- timer_cfg);
- break;
-
- case CLOCK_EVT_MODE_ONESHOT:
- /* Stop the timer until we actually program a shot */
- case CLOCK_EVT_MODE_SHUTDOWN:
- __raw_writeq(0, timer_cfg);
- break;
-
- case CLOCK_EVT_MODE_UNUSED: /* shuddup gcc */
- ;
- }
-}
-
-struct clock_event_device sibyte_hpt_clockevent = {
- .name = "bcm1480-counter",
- .features = CLOCK_EVT_FEAT_PERIODIC,
- .set_mode = sibyte_set_mode,
- .shift = 32,
- .irq = 0,
-};
-
-static irqreturn_t sibyte_counter_handler(int irq, void *dev_id)
-{
- struct clock_event_device *cd = &sibyte_hpt_clockevent;
- unsigned int cpu = smp_processor_id();
-
- /* Reset the timer */
- __raw_writeq(M_SCD_TIMER_ENABLE|M_SCD_TIMER_MODE_CONTINUOUS,
- IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
- cd->event_handler(cd);
-
- return IRQ_HANDLED;
-}
-
-static struct irqaction sibyte_counter_irqaction = {
- .handler = sibyte_counter_handler,
- .flags = IRQF_DISABLED | IRQF_PERCPU,
- .name = "timer",
-};
-
-/*
- * This interrupt is "special" in that it doesn't use the request_irq
- * way to hook the irq line. The timer interrupt is initialized early
- * enough to make this a major pain, and it's also firing enough to
- * warrant a bit of special case code. bcm1480_timer_interrupt is
- * called directly from irq_handler.S when IP[4] is set during an
- * interrupt
- */
-static void __init sb1480_clockevent_init(void)
-{
- unsigned int cpu = smp_processor_id();
- unsigned int irq = K_BCM1480_INT_TIMER_0 + cpu;
-
- setup_irq(irq, &sibyte_counter_irqaction);
-}
-
-void bcm1480_timer_interrupt(void)
-{
- int cpu = smp_processor_id();
- int irq = K_BCM1480_INT_TIMER_0 + cpu;
-
- /* Reset the timer */
- __raw_writeq(M_SCD_TIMER_ENABLE|M_SCD_TIMER_MODE_CONTINUOUS,
- IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
-
- ll_timer_interrupt(irq);
-}
-
-static cycle_t bcm1480_hpt_read(void)
-{
- /* We assume this function is called xtime_lock held. */
- unsigned long count =
- __raw_readq(IOADDR(A_SCD_TIMER_REGISTER(0, R_SCD_TIMER_CNT)));
- return (jiffies + 1) * (BCM1480_HPT_VALUE / HZ) - count;
-}
-
-void __init bcm1480_hpt_setup(void)
-{
- clocksource_mips.read = bcm1480_hpt_read;
- mips_hpt_frequency = BCM1480_HPT_VALUE;
+ sb1480_clocksource_init();
sb1480_clockevent_init();
}
diff --git a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c
index 7659174819c6..eac9065ffe0c 100644
--- a/arch/mips/sibyte/sb1250/irq.c
+++ b/arch/mips/sibyte/sb1250/irq.c
@@ -236,41 +236,6 @@ void __init init_sb1250_irqs(void)
}
-static irqreturn_t sb1250_dummy_handler(int irq, void *dev_id)
-{
- return IRQ_NONE;
-}
-
-static struct irqaction sb1250_dummy_action = {
- .handler = sb1250_dummy_handler,
- .flags = 0,
- .mask = CPU_MASK_NONE,
- .name = "sb1250-private",
- .next = NULL,
- .dev_id = 0
-};
-
-int sb1250_steal_irq(int irq)
-{
- struct irq_desc *desc = irq_desc + irq;
- unsigned long flags;
- int retval = 0;
-
- if (irq >= SB1250_NR_IRQS)
- return -EINVAL;
-
- spin_lock_irqsave(&desc->lock, flags);
- /* Don't allow sharing at all for these */
- if (desc->action != NULL)
- retval = -EBUSY;
- else {
- desc->action = &sb1250_dummy_action;
- desc->depth = 0;
- }
- spin_unlock_irqrestore(&desc->lock, flags);
- return 0;
-}
-
/*
* arch_init_irq is called early in the boot sequence from init/main.c via
* init_IRQ. It is responsible for setting up the interrupt mapper and
@@ -342,8 +307,6 @@ void __init arch_init_irq(void)
__raw_writeq(tmp, IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MASK)));
__raw_writeq(tmp, IOADDR(A_IMR_REGISTER(1, R_IMR_INTERRUPT_MASK)));
- sb1250_steal_irq(K_INT_MBOX_0);
-
/*
* Note that the timer interrupts are also mapped, but this is
* done in sb1250_time_init(). Also, the profiling driver
@@ -367,7 +330,6 @@ void __init arch_init_irq(void)
__raw_writeq(M_DUART_IMR_BRK,
IOADDR(A_DUART_IMRREG(kgdb_port)));
- sb1250_steal_irq(kgdb_irq);
__raw_writeq(IMR_IP6_VAL,
IOADDR(A_IMR_REGISTER(0,
R_IMR_INTERRUPT_MAP_BASE) +
@@ -400,43 +362,27 @@ static void sb1250_kgdb_interrupt(void)
#endif /* CONFIG_KGDB */
-static inline void sb1250_timer_interrupt(void)
-{
- int cpu = smp_processor_id();
- int irq = K_INT_TIMER_0 + cpu;
-
- irq_enter();
- kstat_this_cpu.irqs[irq]++;
-
- write_seqlock(&xtime_lock);
-
- /* ACK interrupt */
- ____raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
- IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
-
- /*
- * call the generic timer interrupt handling
- */
- do_timer(1);
+extern void sb1250_mailbox_interrupt(void);
- write_sequnlock(&xtime_lock);
+static inline void dispatch_ip2(void)
+{
+ unsigned int cpu = smp_processor_id();
+ unsigned long long mask;
/*
- * In UP mode, we call local_timer_interrupt() to do profiling
- * and process accouting.
- *
- * In SMP mode, local_timer_interrupt() is invoked by appropriate
- * low-level local timer interrupt handler.
+ * Default...we've hit an IP[2] interrupt, which means we've got to
+ * check the 1250 interrupt registers to figure out what to do. Need
+ * to detect which CPU we're on, now that smp_affinity is supported.
*/
- local_timer_interrupt(irq);
-
- irq_exit();
+ mask = __raw_readq(IOADDR(A_IMR_REGISTER(cpu,
+ R_IMR_INTERRUPT_STATUS_BASE)));
+ if (mask)
+ do_IRQ(fls64(mask) - 1);
}
-extern void sb1250_mailbox_interrupt(void);
-
asmlinkage void plat_irq_dispatch(void)
{
+ unsigned int cpu = smp_processor_id();
unsigned int pending;
/*
@@ -454,7 +400,7 @@ asmlinkage void plat_irq_dispatch(void)
if (pending & CAUSEF_IP7) /* CPU performance counter interrupt */
do_IRQ(MIPS_CPU_IRQ_BASE + 7);
else if (pending & CAUSEF_IP4)
- sb1250_timer_interrupt();
+ do_IRQ(K_INT_TIMER_0 + cpu); /* sb1250_timer_interrupt() */
#ifdef CONFIG_SMP
else if (pending & CAUSEF_IP3)
@@ -466,21 +412,8 @@ asmlinkage void plat_irq_dispatch(void)
sb1250_kgdb_interrupt();
#endif
- else if (pending & CAUSEF_IP2) {
- unsigned long long mask;
-
- /*
- * Default...we've hit an IP[2] interrupt, which means we've
- * got to check the 1250 interrupt registers to figure out what
- * to do. Need to detect which CPU we're on, now that
- * smp_affinity is supported.
- */
- mask = __raw_readq(IOADDR(A_IMR_REGISTER(smp_processor_id(),
- R_IMR_INTERRUPT_STATUS_BASE)));
- if (mask)
- do_IRQ(fls64(mask) - 1);
- else
- spurious_interrupt();
- } else
+ else if (pending & CAUSEF_IP2)
+ dispatch_ip2();
+ else
spurious_interrupt();
}
diff --git a/arch/mips/sibyte/sb1250/smp.c b/arch/mips/sibyte/sb1250/smp.c
index c38e1f34460d..3f52c95a4eb8 100644
--- a/arch/mips/sibyte/sb1250/smp.c
+++ b/arch/mips/sibyte/sb1250/smp.c
@@ -46,7 +46,7 @@ static void *mailbox_regs[] = {
/*
* SMP init and finish on secondary CPUs
*/
-void sb1250_smp_init(void)
+void __cpuinit sb1250_smp_init(void)
{
unsigned int imask = STATUSF_IP4 | STATUSF_IP3 | STATUSF_IP2 |
STATUSF_IP1 | STATUSF_IP0;
@@ -55,10 +55,11 @@ void sb1250_smp_init(void)
change_c0_status(ST0_IM, imask);
}
-void sb1250_smp_finish(void)
+void __cpuinit sb1250_smp_finish(void)
{
- extern void sb1250_time_init(void);
- sb1250_time_init();
+ extern void sb1250_clockevent_init(void);
+
+ sb1250_clockevent_init();
local_irq_enable();
}
diff --git a/arch/mips/sibyte/sb1250/time.c b/arch/mips/sibyte/sb1250/time.c
index 38199ad8fc54..68337bf7a5aa 100644
--- a/arch/mips/sibyte/sb1250/time.c
+++ b/arch/mips/sibyte/sb1250/time.c
@@ -15,255 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
+#include <linux/init.h>
-/*
- * These are routines to set up and handle interrupts from the
- * sb1250 general purpose timer 0. We're using the timer as a
- * system clock, so we set it up to run at 100 Hz. On every
- * interrupt, we update our idea of what the time of day is,
- * then call do_timer() in the architecture-independent kernel
- * code to do general bookkeeping (e.g. update jiffies, run
- * bottom halves, etc.)
- */
-#include <linux/clockchips.h>
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/kernel_stat.h>
-
-#include <asm/irq.h>
-#include <asm/addrspace.h>
-#include <asm/time.h>
-#include <asm/io.h>
-
-#include <asm/sibyte/sb1250.h>
-#include <asm/sibyte/sb1250_regs.h>
-#include <asm/sibyte/sb1250_int.h>
-#include <asm/sibyte/sb1250_scd.h>
-
-
-#define IMR_IP2_VAL K_INT_MAP_I0
-#define IMR_IP3_VAL K_INT_MAP_I1
-#define IMR_IP4_VAL K_INT_MAP_I2
-
-#define SB1250_HPT_NUM 3
-#define SB1250_HPT_VALUE M_SCD_TIMER_CNT /* max value */
-
-
-extern int sb1250_steal_irq(int irq);
-
-static cycle_t sb1250_hpt_read(void);
-
-void __init sb1250_hpt_setup(void)
-{
- int cpu = smp_processor_id();
-
- if (!cpu) {
- /* Setup hpt using timer #3 but do not enable irq for it */
- __raw_writeq(0, IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CFG)));
- __raw_writeq(SB1250_HPT_VALUE,
- IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_INIT)));
- __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
- IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CFG)));
-
- mips_hpt_frequency = V_SCD_TIMER_FREQ;
- clocksource_mips.read = sb1250_hpt_read;
- clocksource_mips.mask = M_SCD_TIMER_INIT;
- }
-}
-
-/*
- * The general purpose timer ticks at 1 Mhz independent if
- * the rest of the system
- */
-static void sibyte_set_mode(enum clock_event_mode mode,
- struct clock_event_device *evt)
-{
- unsigned int cpu = smp_processor_id();
- void __iomem *timer_cfg, *timer_init;
-
- timer_cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
- timer_init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
-
- switch(mode) {
- case CLOCK_EVT_MODE_PERIODIC:
- __raw_writeq(0, timer_cfg);
- __raw_writeq((V_SCD_TIMER_FREQ / HZ) - 1, timer_init);
- __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
- timer_cfg);
- break;
-
- case CLOCK_EVT_MODE_ONESHOT:
- /* Stop the timer until we actually program a shot */
- case CLOCK_EVT_MODE_SHUTDOWN:
- __raw_writeq(0, timer_cfg);
- break;
-
- case CLOCK_EVT_MODE_UNUSED: /* shuddup gcc */
- ;
- }
-}
-
-static int
-sibyte_next_event(unsigned long delta, struct clock_event_device *evt)
-{
- unsigned int cpu = smp_processor_id();
- void __iomem *timer_cfg, *timer_init;
-
- timer_cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
- timer_init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
-
- __raw_writeq(0, timer_cfg);
- __raw_writeq(delta, timer_init);
- __raw_writeq(M_SCD_TIMER_ENABLE, timer_cfg);
-
- return 0;
-}
-
-struct clock_event_device sibyte_hpt_clockevent = {
- .name = "sb1250-counter",
- .features = CLOCK_EVT_FEAT_PERIODIC,
- .set_mode = sibyte_set_mode,
- .set_next_event = sibyte_next_event,
- .shift = 32,
- .irq = 0,
-};
-
-static irqreturn_t sibyte_counter_handler(int irq, void *dev_id)
-{
- struct clock_event_device *cd = &sibyte_hpt_clockevent;
-
- cd->event_handler(cd);
-
- return IRQ_HANDLED;
-}
-
-static struct irqaction sibyte_irqaction = {
- .handler = sibyte_counter_handler,
- .flags = IRQF_DISABLED | IRQF_PERCPU,
- .name = "timer",
-};
-
-/*
- * The general purpose timer ticks at 1 Mhz independent if
- * the rest of the system
- */
-static void sibyte_set_mode(enum clock_event_mode mode,
- struct clock_event_device *evt)
-{
- unsigned int cpu = smp_processor_id();
- void __iomem *timer_cfg, *timer_init;
-
- timer_cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
- timer_init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
-
- switch (mode) {
- case CLOCK_EVT_MODE_PERIODIC:
- __raw_writeq(0, timer_cfg);
- __raw_writeq((V_SCD_TIMER_FREQ / HZ) - 1, timer_init);
- __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
- timer_cfg);
- break;
-
- case CLOCK_EVT_MODE_ONESHOT:
- /* Stop the timer until we actually program a shot */
- case CLOCK_EVT_MODE_SHUTDOWN:
- __raw_writeq(0, timer_cfg);
- break;
-
- case CLOCK_EVT_MODE_UNUSED: /* shuddup gcc */
- ;
- }
-}
-
-static int
-sibyte_next_event(unsigned long delta, struct clock_event_device *evt)
-{
- unsigned int cpu = smp_processor_id();
- void __iomem *timer_cfg, *timer_init;
-
- timer_cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
- timer_init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
-
- __raw_writeq(0, timer_cfg);
- __raw_writeq(delta, timer_init);
- __raw_writeq(M_SCD_TIMER_ENABLE, timer_cfg);
-
- return 0;
-}
-
-struct clock_event_device sibyte_hpt_clockevent = {
- .name = "sb1250-counter",
- .features = CLOCK_EVT_FEAT_PERIODIC,
- .set_mode = sibyte_set_mode,
- .set_next_event = sibyte_next_event,
- .shift = 32,
- .irq = 0,
-};
-
-static irqreturn_t sibyte_counter_handler(int irq, void *dev_id)
-{
- struct clock_event_device *cd = &sibyte_hpt_clockevent;
-
- cd->event_handler(cd);
-
- return IRQ_HANDLED;
-}
-
-static struct irqaction sibyte_irqaction = {
- .handler = sibyte_counter_handler,
- .flags = IRQF_DISABLED | IRQF_PERCPU,
- .name = "timer",
-};
-
-static void __init sb1250_clockevent_init(void)
-{
- struct clock_event_device *cd = &sibyte_hpt_clockevent;
- unsigned int cpu = smp_processor_id();
- int irq = K_INT_TIMER_0 + cpu;
-
- /* Only have 4 general purpose timers, and we use last one as hpt */
- BUG_ON(cpu > 2);
-
- sb1250_mask_irq(cpu, irq);
-
- /* Map the timer interrupt to ip[4] of this cpu */
- __raw_writeq(IMR_IP4_VAL,
- IOADDR(A_IMR_REGISTER(cpu, R_IMR_INTERRUPT_MAP_BASE) +
- (irq << 3)));
- cd->cpumask = cpumask_of_cpu(0);
-
- sb1250_unmask_irq(cpu, irq);
- sb1250_steal_irq(irq);
-
- /*
- * This interrupt is "special" in that it doesn't use the request_irq
- * way to hook the irq line. The timer interrupt is initialized early
- * enough to make this a major pain, and it's also firing enough to
- * warrant a bit of special case code. sb1250_timer_interrupt is
- * called directly from irq_handler.S when IP[4] is set during an
- * interrupt
- */
- setup_irq(irq, &sibyte_irqaction);
-
- clockevents_register_device(cd);
-}
+extern void sb1250_clocksource_init(void);
+extern void sb1250_clockevent_init(void);
void __init plat_time_init(void)
{
sb1250_clocksource_init();
sb1250_clockevent_init();
}
-
-/*
- * The HPT is free running from SB1250_HPT_VALUE down to 0 then starts over
- * again.
- */
-static cycle_t sb1250_hpt_read(void)
-{
- unsigned int count;
-
- count = G_SCD_TIMER_CNT(__raw_readq(IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CNT))));
-
- return SB1250_HPT_VALUE - count;
-}
diff --git a/arch/mips/sibyte/swarm/setup.c b/arch/mips/sibyte/swarm/setup.c
index 8b3ef0e4cd55..080c966263b7 100644
--- a/arch/mips/sibyte/swarm/setup.c
+++ b/arch/mips/sibyte/swarm/setup.c
@@ -69,31 +69,6 @@ const char *get_system_type(void)
return "SiByte " SIBYTE_BOARD_NAME;
}
-void __init plat_time_init(void)
-{
-#if defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
- /* Setup HPT */
- sb1250_hpt_setup();
-#endif
-}
-
-void __init plat_timer_setup(struct irqaction *irq)
-{
- /*
- * we don't set up irqaction, because we will deliver timer
- * interrupts through low-level (direct) meachanism.
- */
-
- /* We only need to setup the generic timer */
-#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
- bcm1480_time_init();
-#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
- sb1250_time_init();
-#else
-#error invalid SiByte board configuration
-#endif
-}
-
int swarm_be_handler(struct pt_regs *regs, int is_fixup)
{
if (!is_fixup && (regs->cp0_cause & 4)) {
diff --git a/arch/mips/sni/pcimt.c b/arch/mips/sni/pcimt.c
index 39bb15f1f2a6..834650f371e0 100644
--- a/arch/mips/sni/pcimt.c
+++ b/arch/mips/sni/pcimt.c
@@ -244,9 +244,9 @@ static void pcimt_hwint1(void)
if (pend & IT_EISA) {
int irq;
/*
- * Note: ASIC PCI's builtin interrupt achknowledge feature is
+ * Note: ASIC PCI's builtin interrupt acknowledge feature is
* broken. Using it may result in loss of some or all i8259
- * interupts, so don't use PCIMT_INT_ACKNOWLEDGE ...
+ * interrupts, so don't use PCIMT_INT_ACKNOWLEDGE ...
*/
irq = i8259_irq();
if (unlikely(irq < 0))
diff --git a/arch/mips/sni/time.c b/arch/mips/sni/time.c
index b80877349d38..6f339af08d22 100644
--- a/arch/mips/sni/time.c
+++ b/arch/mips/sni/time.c
@@ -1,6 +1,7 @@
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/time.h>
+#include <linux/clockchips.h>
#include <asm/i8253.h>
#include <asm/sni.h>
@@ -11,27 +12,78 @@
#define SNI_COUNTER2_DIV 64
#define SNI_COUNTER0_DIV ((SNI_CLOCK_TICK_RATE / SNI_COUNTER2_DIV) / HZ)
-static void sni_a20r_timer_ack(void)
+static void a20r_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
{
- *(volatile u8 *)A20R_PT_TIM0_ACK = 0x0; wmb();
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0x34;
+ wmb();
+ *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = SNI_COUNTER0_DIV;
+ wmb();
+ *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = SNI_COUNTER0_DIV >> 8;
+ wmb();
+
+ *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0xb4;
+ wmb();
+ *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = SNI_COUNTER2_DIV;
+ wmb();
+ *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = SNI_COUNTER2_DIV >> 8;
+ wmb();
+
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ break;
+ case CLOCK_EVT_MODE_RESUME:
+ break;
+ }
}
+static struct clock_event_device a20r_clockevent_device = {
+ .name = "a20r-timer",
+ .features = CLOCK_EVT_FEAT_PERIODIC,
+
+ /* .mult, .shift, .max_delta_ns and .min_delta_ns left uninitialized */
+
+ .rating = 300,
+ .irq = SNI_A20R_IRQ_TIMER,
+ .set_mode = a20r_set_mode,
+};
+
+static irqreturn_t a20r_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *cd = dev_id;
+
+ *(volatile u8 *)A20R_PT_TIM0_ACK = 0;
+ wmb();
+
+ cd->event_handler(cd);
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction a20r_irqaction = {
+ .handler = a20r_interrupt,
+ .flags = IRQF_DISABLED | IRQF_PERCPU,
+ .name = "a20r-timer",
+};
+
/*
* a20r platform uses 2 counters to divide the input frequency.
* Counter 2 output is connected to Counter 0 & 1 input.
*/
-static void __init sni_a20r_timer_setup(struct irqaction *irq)
+static void __init sni_a20r_timer_setup(void)
{
- *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0x34; wmb();
- *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = (SNI_COUNTER0_DIV) & 0xff; wmb();
- *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = (SNI_COUNTER0_DIV >> 8) & 0xff; wmb();
-
- *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0xb4; wmb();
- *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = (SNI_COUNTER2_DIV) & 0xff; wmb();
- *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = (SNI_COUNTER2_DIV >> 8) & 0xff; wmb();
-
- setup_irq(SNI_A20R_IRQ_TIMER, irq);
- mips_timer_ack = sni_a20r_timer_ack;
+ struct clock_event_device *cd = &a20r_clockevent_device;
+ struct irqaction *action = &a20r_irqaction;
+ unsigned int cpu = smp_processor_id();
+
+ cd->cpumask = cpumask_of_cpu(cpu);
+ clockevents_register_device(cd);
+ action->dev_id = cd;
+ setup_irq(SNI_A20R_IRQ_TIMER, &a20r_irqaction);
}
#define SNI_8254_TICK_RATE 1193182UL
@@ -118,36 +170,13 @@ void __init plat_time_init(void)
mips_hpt_frequency = r4k_tick * HZ;
- setup_pit_timer();
-}
-
-/*
- * R4k counter based timer interrupt. Works on RM200-225 and possibly
- * others but not on RM400
- */
-static void __init sni_cpu_timer_setup(struct irqaction *irq)
-{
- setup_irq(SNI_MIPS_IRQ_CPU_TIMER, irq);
-}
-
-void __init plat_timer_setup(struct irqaction *irq)
-{
switch (sni_brd_type) {
case SNI_BRD_10:
case SNI_BRD_10NEW:
case SNI_BRD_TOWER_OASIC:
case SNI_BRD_MINITOWER:
- sni_a20r_timer_setup(irq);
- break;
-
- case SNI_BRD_PCI_TOWER:
- case SNI_BRD_RM200:
- case SNI_BRD_PCI_MTOWER:
- case SNI_BRD_PCI_DESKTOP:
- case SNI_BRD_PCI_TOWER_CPLUS:
- case SNI_BRD_PCI_MTOWER_CPLUS:
- sni_cpu_timer_setup(irq);
- break;
+ sni_a20r_timer_setup();
+ break;
}
}
diff --git a/arch/mips/tx4927/common/tx4927_setup.c b/arch/mips/tx4927/common/tx4927_setup.c
index 8ce0989671d8..36c5f200eb3d 100644
--- a/arch/mips/tx4927/common/tx4927_setup.c
+++ b/arch/mips/tx4927/common/tx4927_setup.c
@@ -72,22 +72,6 @@ void __init plat_time_init(void)
#endif
}
-void __init plat_timer_setup(struct irqaction *irq)
-{
- setup_irq(TX4927_IRQ_CPU_TIMER, irq);
-
-#ifdef CONFIG_TOSHIBA_RBTX4927
- {
- extern void toshiba_rbtx4927_timer_setup(struct irqaction
- *irq);
- toshiba_rbtx4927_timer_setup(irq);
- }
-#endif
-
- return;
-}
-
-
#ifdef DEBUG
void print_cp0(char *key, int num, char *name, u32 val)
{
diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
index acaf613358c7..0299595ce1c4 100644
--- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
+++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
@@ -63,6 +63,7 @@
#include <asm/processor.h>
#include <asm/reboot.h>
#include <asm/time.h>
+#include <asm/txx9tmr.h>
#include <linux/bootmem.h>
#include <linux/blkdev.h>
#ifdef CONFIG_TOSHIBA_FPCIB0
@@ -93,8 +94,6 @@
#define TOSHIBA_RBTX4927_SETUP_EFWFU ( 1 << 3 )
#define TOSHIBA_RBTX4927_SETUP_SETUP ( 1 << 4 )
-#define TOSHIBA_RBTX4927_SETUP_TIME_INIT ( 1 << 5 )
-#define TOSHIBA_RBTX4927_SETUP_TIMER_SETUP ( 1 << 6 )
#define TOSHIBA_RBTX4927_SETUP_PCIBIOS ( 1 << 7 )
#define TOSHIBA_RBTX4927_SETUP_PCI1 ( 1 << 8 )
#define TOSHIBA_RBTX4927_SETUP_PCI2 ( 1 << 9 )
@@ -108,7 +107,6 @@ static const u32 toshiba_rbtx4927_setup_debug_flag =
(TOSHIBA_RBTX4927_SETUP_NONE | TOSHIBA_RBTX4927_SETUP_INFO |
TOSHIBA_RBTX4927_SETUP_WARN | TOSHIBA_RBTX4927_SETUP_EROR |
TOSHIBA_RBTX4927_SETUP_EFWFU | TOSHIBA_RBTX4927_SETUP_SETUP |
- TOSHIBA_RBTX4927_SETUP_TIME_INIT | TOSHIBA_RBTX4927_SETUP_TIMER_SETUP
| TOSHIBA_RBTX4927_SETUP_PCIBIOS | TOSHIBA_RBTX4927_SETUP_PCI1 |
TOSHIBA_RBTX4927_SETUP_PCI2 | TOSHIBA_RBTX4927_SETUP_PCI66);
#endif
@@ -132,7 +130,6 @@ extern void toshiba_rbtx4927_power_off(void);
int tx4927_using_backplane = 0;
-extern void gt64120_time_init(void);
extern void toshiba_rbtx4927_irq_setup(void);
char *prom_getcmdline(void);
@@ -723,6 +720,7 @@ void toshiba_rbtx4927_power_off(void)
void __init toshiba_rbtx4927_setup(void)
{
+ int i;
u32 cp0_config;
char *argptr;
@@ -766,6 +764,9 @@ void __init toshiba_rbtx4927_setup(void)
_machine_halt = toshiba_rbtx4927_halt;
pm_power_off = toshiba_rbtx4927_power_off;
+ for (i = 0; i < TX4927_NR_TMR; i++)
+ txx9_tmr_init(TX4927_TMR_REG(0) & 0xfffffffffULL);
+
#ifdef CONFIG_PCI
/* PCIC */
@@ -894,7 +895,6 @@ void __init toshiba_rbtx4927_setup(void)
#ifdef CONFIG_SERIAL_TXX9
{
extern int early_serial_txx9_setup(struct uart_port *port);
- int i;
struct uart_port req;
for(i = 0; i < 2; i++) {
memset(&req, 0, sizeof(req));
@@ -939,20 +939,11 @@ void __init toshiba_rbtx4927_setup(void)
void __init
toshiba_rbtx4927_time_init(void)
{
- TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT, "-\n");
-
mips_hpt_frequency = tx4927_cpu_clock / 2;
-
- TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT, "+\n");
-
-}
-
-void __init toshiba_rbtx4927_timer_setup(struct irqaction *irq)
-{
- TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIMER_SETUP,
- "-\n");
- TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIMER_SETUP,
- "+\n");
+ if (tx4927_ccfgptr->ccfg & TX4927_CCFG_TINTDIS)
+ txx9_clockevent_init(TX4927_TMR_REG(0) & 0xfffffffffULL,
+ TXX9_IRQ_BASE + 17,
+ 50000000);
}
static int __init toshiba_rbtx4927_rtc_init(void)
@@ -963,7 +954,7 @@ static int __init toshiba_rbtx4927_rtc_init(void)
.flags = IORESOURCE_MEM,
};
struct platform_device *dev =
- platform_device_register_simple("ds1742", -1, &res, 1);
+ platform_device_register_simple("rtc-ds1742", -1, &res, 1);
return IS_ERR(dev) ? PTR_ERR(dev) : 0;
}
device_initcall(toshiba_rbtx4927_rtc_init);
diff --git a/arch/mips/tx4938/common/setup.c b/arch/mips/tx4938/common/setup.c
index ab4082267553..3ba4101d141e 100644
--- a/arch/mips/tx4938/common/setup.c
+++ b/arch/mips/tx4938/common/setup.c
@@ -24,7 +24,7 @@
#include <linux/slab.h>
#include <linux/random.h>
#include <linux/irq.h>
-#include <asm/bitops.h>
+#include <linux/bitops.h>
#include <asm/bootinfo.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -43,8 +43,3 @@ plat_mem_setup(void)
{
toshiba_rbtx4938_setup();
}
-
-void __init plat_timer_setup(struct irqaction *irq)
-{
- setup_irq(TX4938_IRQ_CPU_TIMER, irq);
-}
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/setup.c b/arch/mips/tx4938/toshiba_rbtx4938/setup.c
index ceecaf498957..4a8152375efe 100644
--- a/arch/mips/tx4938/toshiba_rbtx4938/setup.c
+++ b/arch/mips/tx4938/toshiba_rbtx4938/setup.c
@@ -26,6 +26,7 @@
#include <asm/reboot.h>
#include <asm/irq.h>
#include <asm/time.h>
+#include <asm/txx9tmr.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/bootinfo.h>
@@ -773,15 +774,8 @@ void __init tx4938_board_setup(void)
}
/* TMR */
- /* disable all timers */
- for (i = 0; i < TX4938_NR_TMR; i++) {
- tx4938_tmrptr(i)->tcr = 0x00000020;
- tx4938_tmrptr(i)->tisr = 0;
- tx4938_tmrptr(i)->cpra = 0xffffffff;
- tx4938_tmrptr(i)->itmr = 0;
- tx4938_tmrptr(i)->ccdr = 0;
- tx4938_tmrptr(i)->pgmr = 0;
- }
+ for (i = 0; i < TX4938_NR_TMR; i++)
+ txx9_tmr_init(TX4938_TMR_REG(i) & 0xfffffffffULL);
/* enable DMA */
TX4938_WR64(0xff1fb150, TX4938_DMA_MCR_MSTEN);
@@ -852,12 +846,13 @@ void tx4938_report_pcic_status(void)
#endif /* CONFIG_PCI */
-/* We use onchip r4k counter or TMR timer as our system wide timer
- * interrupt running at 100HZ. */
-
void __init plat_time_init(void)
{
mips_hpt_frequency = txx9_cpu_clock / 2;
+ if (tx4938_ccfgptr->ccfg & TX4938_CCFG_TINTDIS)
+ txx9_clockevent_init(TX4938_TMR_REG(0) & 0xfffffffffULL,
+ TXX9_IRQ_BASE + TX4938_IR_TMR(0),
+ txx9_gbus_clock / 2);
}
void __init toshiba_rbtx4938_setup(void)
diff --git a/arch/mips/vr41xx/Kconfig b/arch/mips/vr41xx/Kconfig
index 8f4d3e74c230..eeb089f20c0d 100644
--- a/arch/mips/vr41xx/Kconfig
+++ b/arch/mips/vr41xx/Kconfig
@@ -5,6 +5,7 @@ choice
config CASIO_E55
bool "CASIO CASSIOPEIA E-10/15/55/65"
+ select CEVT_R4K
select DMA_NONCOHERENT
select IRQ_CPU
select ISA
@@ -13,6 +14,7 @@ config CASIO_E55
config IBM_WORKPAD
bool "IBM WorkPad z50"
+ select CEVT_R4K
select DMA_NONCOHERENT
select IRQ_CPU
select ISA
@@ -21,6 +23,7 @@ config IBM_WORKPAD
config NEC_CMBVR4133
bool "NEC CMB-VR4133"
+ select CEVT_R4K
select DMA_NONCOHERENT
select IRQ_CPU
select HW_HAS_PCI
@@ -29,6 +32,7 @@ config NEC_CMBVR4133
config TANBAC_TB022X
bool "TANBAC VR4131 multichip module and TANBAC VR4131DIMM"
+ select CEVT_R4K
select DMA_NONCOHERENT
select IRQ_CPU
select HW_HAS_PCI
@@ -43,6 +47,7 @@ config TANBAC_TB022X
config VICTOR_MPC30X
bool "Victor MP-C303/304"
+ select CEVT_R4K
select DMA_NONCOHERENT
select IRQ_CPU
select HW_HAS_PCI
@@ -52,6 +57,7 @@ config VICTOR_MPC30X
config ZAO_CAPCELLA
bool "ZAO Networks Capcella"
+ select CEVT_R4K
select DMA_NONCOHERENT
select IRQ_CPU
select HW_HAS_PCI
diff --git a/arch/mips/vr41xx/common/icu.c b/arch/mips/vr41xx/common/icu.c
index 1899601e5862..3f23d9fda662 100644
--- a/arch/mips/vr41xx/common/icu.c
+++ b/arch/mips/vr41xx/common/icu.c
@@ -525,6 +525,7 @@ static inline int set_sysint1_assign(unsigned int irq, unsigned char assign)
intassign1 |= (uint16_t)assign << 9;
break;
default:
+ spin_unlock_irq(&desc->lock);
return -EINVAL;
}
@@ -592,6 +593,7 @@ static inline int set_sysint2_assign(unsigned int irq, unsigned char assign)
intassign3 |= (uint16_t)assign << 12;
break;
default:
+ spin_unlock_irq(&desc->lock);
return -EINVAL;
}
diff --git a/arch/mips/vr41xx/common/init.c b/arch/mips/vr41xx/common/init.c
index 407cec203b29..8d760df686c4 100644
--- a/arch/mips/vr41xx/common/init.c
+++ b/arch/mips/vr41xx/common/init.c
@@ -48,11 +48,6 @@ void __init plat_time_init(void)
mips_hpt_frequency = tclock / 4;
}
-void __init plat_timer_setup(struct irqaction *irq)
-{
- setup_irq(TIMER_IRQ, irq);
-}
-
void __init plat_mem_setup(void)
{
vr41xx_calculate_clock_frequency();
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 3d73545e8c48..b8ef1787a191 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -267,7 +267,7 @@ source "drivers/Kconfig"
source "fs/Kconfig"
-source "arch/parisc/oprofile/Kconfig"
+source "kernel/Kconfig.instrumentation"
source "arch/parisc/Kconfig.debug"
diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile
index 760567a9ba16..ae4a9b3d4fd6 100644
--- a/arch/parisc/Makefile
+++ b/arch/parisc/Makefile
@@ -19,26 +19,27 @@
NM = sh $(srctree)/arch/parisc/nm
CHECKFLAGS += -D__hppa__=1
+MACHINE := $(shell uname -m)
+ifeq ($(MACHINE),parisc*)
+NATIVE := 1
+endif
+
ifdef CONFIG_64BIT
-CROSS_COMPILE := $(shell if [ -x /usr/bin/hppa64-linux-gnu-gcc ]; then \
- echo hppa64-linux-gnu-; else echo hppa64-linux-; fi)
UTS_MACHINE := parisc64
CHECKFLAGS += -D__LP64__=1 -m64
-else
-MACHINE := $(subst 64,,$(shell uname -m))
-ifneq ($(MACHINE),parisc)
-CROSS_COMPILE := hppa-linux-
-endif
+WIDTH := 64
+CROSS_COMPILE := hppa64-linux-gnu-
+else # 32-bit
+WIDTH :=
endif
-FINAL_LD=$(CROSS_COMPILE)ld --warn-common --warn-section-align
+# attempt to help out folks who are cross-compiling
+ifeq ($(NATIVE),1)
+CROSS_COMPILE := hppa$(WIDTH)-linux-
+endif
OBJCOPY_FLAGS =-O binary -R .note -R .comment -S
-ifneq ($(call cc-ifversion, -lt, 0303, "bad"),)
-$(error Sorry, GCC v3.3 or above is required.)
-endif
-
cflags-y := -pipe
# These flags should be implied by an hppa-linux configuration, but they
@@ -63,13 +64,13 @@ cflags-$(CONFIG_PA8X00) += -march=2.0 -mschedule=8000
head-y := arch/parisc/kernel/head.o
-CFLAGS += $(cflags-y)
+KBUILD_CFLAGS += $(cflags-y)
kernel-y := mm/ kernel/ math-emu/ kernel/init_task.o
kernel-$(CONFIG_HPUX) += hpux/
core-y += $(addprefix arch/parisc/, $(kernel-y))
-libs-y += arch/parisc/lib/ `$(CC) -print-libgcc-file-name`
+libs-y += arch/parisc/lib/
drivers-$(CONFIG_OPROFILE) += arch/parisc/oprofile/
@@ -77,27 +78,27 @@ PALO := $(shell if which palo; then : ; \
elif [ -x /sbin/palo ]; then echo /sbin/palo; \
fi)
+PALOCONF := $(shell if [ -f $(src)/palo.conf ]; then echo $(src)/palo.conf; \
+ else echo $(obj)/palo.conf; \
+ fi)
+
palo: vmlinux
- @if [ -x $PALO ]; then \
+ @if test ! -x "$(PALO)"; then \
echo 'ERROR: Please install palo first (apt-get install palo)';\
echo 'or build it from source and install it somewhere in your $$PATH';\
false; \
fi
- @if [ ! -f ./palo.conf ]; then \
- cp arch/parisc/defpalo.conf palo.conf; \
- echo 'A generic palo config file (./palo.conf) has been created for you.'; \
+ @if test ! -f "$(PALOCONF)"; then \
+ cp $(src)/arch/parisc/defpalo.conf $(obj)/palo.conf; \
+ echo 'A generic palo config file ($(obj)/palo.conf) has been created for you.'; \
echo 'You should check it and re-run "make palo".'; \
echo 'WARNING: the "lifimage" file is now placed in this directory by default!'; \
false; \
fi
- $(PALO) -f ./palo.conf
-
-oldpalo: vmlinux
- export TOPDIR=`pwd`; \
- unset STRIP LDFLAGS CPP CPPFLAGS AFLAGS CFLAGS CC LD; cd ../palo && make lifimage
+ $(PALO) -f $(PALOCONF)
-# Shorthands for known targets not supported by parisc, use palo as default
-Image zImage bzImage: palo
+# Shorthands for known targets not supported by parisc, use vmlinux as default
+Image zImage bzImage: vmlinux
kernel_install: vmlinux
sh $(src)/arch/parisc/install.sh \
@@ -116,3 +117,12 @@ define archhelp
@echo ' (distribution) /sbin/installkernel or'
@echo ' copy to $$(INSTALL_PATH)'
endef
+
+# we require gcc 3.3 or above to compile the kernel
+archprepare: checkbin
+checkbin:
+ @if test "$(call cc-version)" -lt "0303"; then \
+ echo -n "Sorry, GCC v3.3 or above is required to build " ; \
+ echo "the kernel." ; \
+ false ; \
+ fi
diff --git a/arch/parisc/configs/712_defconfig b/arch/parisc/configs/712_defconfig
index 41fd0696bbe7..9fc96e727165 100644
--- a/arch/parisc/configs/712_defconfig
+++ b/arch/parisc/configs/712_defconfig
@@ -1,39 +1,51 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-pa6
-# Sun Mar 26 19:59:51 2006
+# Linux kernel version: 2.6.23
+# Fri Oct 12 21:00:07 2007
#
CONFIG_PARISC=y
CONFIG_MMU=y
CONFIG_STACK_GROWSUP=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
-# Code maturity level options
+# General setup
#
CONFIG_EXPERIMENTAL=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
CONFIG_LOCALVERSION=""
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_USER_NS is not set
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY 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_EXTRA_PASS is not set
@@ -43,31 +55,29 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
-
-#
-# Loadable module support
-#
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
-
-#
-# Block layer
-#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
#
# IO Schedulers
@@ -91,6 +101,9 @@ CONFIG_PA7100LC=y
# CONFIG_PA7300LC is not set
# CONFIG_PA8X00 is not set
CONFIG_PA11=y
+CONFIG_PARISC_PAGE_SIZE_4KB=y
+# CONFIG_PARISC_PAGE_SIZE_16KB is not set
+# CONFIG_PARISC_PAGE_SIZE_64KB is not set
# CONFIG_SMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
# CONFIG_PREEMPT_NONE is not set
@@ -98,6 +111,7 @@ CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_PREEMPT is not set
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
CONFIG_SELECT_MEMORY_MODEL=y
@@ -108,6 +122,9 @@ CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
# CONFIG_HPUX is not set
#
@@ -120,6 +137,7 @@ CONFIG_GSC_LASI=y
# CONFIG_GSC_WAX is not set
# CONFIG_EISA is not set
# CONFIG_PCI is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
#
# PCCARD (PCMCIA/CardBus) support
@@ -127,14 +145,11 @@ CONFIG_GSC_LASI=y
# CONFIG_PCCARD is not set
#
-# PCI Hotplug Support
-#
-
-#
# PA-RISC specific drivers
#
CONFIG_CHASSIS_LCD_LED=y
# CONFIG_PDC_CHASSIS is not set
+CONFIG_PDC_CHASSIS_WARN=y
CONFIG_PDC_STABLE=y
#
@@ -151,13 +166,15 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
CONFIG_XFRM=y
CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
CONFIG_NET_KEY=m
+# CONFIG_NET_KEY_MIGRATE is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
# CONFIG_IP_ADVANCED_ROUTER is not set
@@ -174,17 +191,23 @@ CONFIG_IP_PNP_BOOTP=y
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# 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=m
CONFIG_INET_TCP_DIAG=m
# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-
-#
-# IP: Virtual Server Configuration
-#
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
# CONFIG_IP_VS is not set
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
@@ -192,37 +215,18 @@ CONFIG_NETFILTER=y
# Core Netfilter Configuration
#
# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NF_CONNTRACK_ENABLED is not set
+# CONFIG_NF_CONNTRACK is not set
# CONFIG_NETFILTER_XTABLES is not set
#
# IP: Netfilter Configuration
#
-CONFIG_IP_NF_CONNTRACK=m
-# CONFIG_IP_NF_CT_ACCT is not set
-CONFIG_IP_NF_CONNTRACK_MARK=y
-# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
-CONFIG_IP_NF_CT_PROTO_SCTP=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-# CONFIG_IP_NF_NETBIOS_NS is not set
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-# CONFIG_IP_NF_PPTP is not set
CONFIG_IP_NF_QUEUE=m
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -234,7 +238,6 @@ CONFIG_LLC2=m
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -250,7 +253,17 @@ CONFIG_NET_PKTGEN=m
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
#
# Device Drivers
@@ -259,39 +272,24 @@ CONFIG_NET_PKTGEN=m
#
# Generic Driver Options
#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
# CONFIG_STANDALONE is not set
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
CONFIG_FW_LOADER=y
# CONFIG_DEBUG_DRIVER is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
CONFIG_PARPORT=y
CONFIG_PARPORT_PC=m
# CONFIG_PARPORT_PC_FIFO is not set
# CONFIG_PARPORT_PC_SUPERIO is not set
-CONFIG_PARPORT_NOT_PC=y
CONFIG_PARPORT_GSC=y
+# CONFIG_PARPORT_AX88796 is not set
# CONFIG_PARPORT_1284 is not set
-
-#
-# Plug and Play support
-#
-
-#
-# Block devices
-#
+CONFIG_PARPORT_NOT_PC=y
+CONFIG_BLK_DEV=y
# CONFIG_PARIDE is not set
# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
@@ -300,13 +298,11 @@ CONFIG_BLK_DEV_CRYPTOLOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=6144
-CONFIG_BLK_DEV_INITRD=y
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
# CONFIG_CDROM_PKTCDVD is not set
CONFIG_ATA_OVER_ETH=m
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
# CONFIG_IDE is not set
#
@@ -314,6 +310,9 @@ CONFIG_ATA_OVER_ETH=m
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
CONFIG_SCSI_PROC_FS=y
#
@@ -333,104 +332,61 @@ CONFIG_CHR_DEV_SG=y
# 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 Transport Attributes
+# SCSI Transports
#
CONFIG_SCSI_SPI_ATTRS=y
# CONFIG_SCSI_FC_ATTRS is not set
CONFIG_SCSI_ISCSI_ATTRS=m
-# CONFIG_SCSI_SAS_ATTRS is not set
-
-#
-# SCSI low-level drivers
-#
+# CONFIG_SCSI_SAS_LIBSAS is not set
+CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
-# CONFIG_SCSI_SATA is not set
# CONFIG_SCSI_PPA is not set
# CONFIG_SCSI_IMM is not set
CONFIG_SCSI_LASI700=y
CONFIG_53C700_LE_ON_BE=y
# CONFIG_SCSI_ZALON is not set
CONFIG_SCSI_DEBUG=m
-
-#
-# Multi-device support (RAID and LVM)
-#
+# 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_RAID5 is not set
-# CONFIG_MD_RAID6 is not set
+# CONFIG_MD_RAID456 is not set
# CONFIG_MD_MULTIPATH is not set
# CONFIG_MD_FAULTY is not set
# CONFIG_BLK_DEV_DM is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
-# Network device support
-#
CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
CONFIG_DUMMY=m
CONFIG_BONDING=m
+# CONFIG_MACVLAN is not set
# CONFIG_EQUALIZER is not set
CONFIG_TUN=m
-
-#
-# PHY device support
-#
+# CONFIG_VETH is not set
# CONFIG_PHYLIB is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
CONFIG_NET_ETHERNET=y
CONFIG_MII=m
CONFIG_LASI_82596=y
+# 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_B44 is not set
# CONFIG_NET_POCKET is not set
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-CONFIG_NET_RADIO=y
-
-#
-# Obsolete Wireless cards support (pre-802.11)
-#
-# CONFIG_STRIP is not set
-# CONFIG_ATMEL is not set
-# CONFIG_HOSTAP is not set
-
-#
-# Wan interfaces
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
# CONFIG_WAN is not set
# CONFIG_PLIP is not set
CONFIG_PPP=m
@@ -442,26 +398,22 @@ CONFIG_PPP_DEFLATE=m
CONFIG_PPP_BSDCOMP=m
CONFIG_PPP_MPPE=m
CONFIG_PPPOE=m
+# CONFIG_PPPOL2TP is not set
# CONFIG_SLIP is not set
+CONFIG_SLHC=m
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
# 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
@@ -486,14 +438,22 @@ CONFIG_KEYBOARD_ATKBD_HP_KEYCODES=y
# 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_KEYBOARD_HIL_OLD is not set
CONFIG_KEYBOARD_HIL=y
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_TOUCHKIT is not set
CONFIG_MOUSE_SERIAL=m
# CONFIG_MOUSE_VSXXXAA is not set
CONFIG_MOUSE_HIL=m
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
@@ -516,6 +476,7 @@ CONFIG_SERIO_LIBPS2=y
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
# CONFIG_SERIAL_NONSTANDARD is not set
#
@@ -523,6 +484,7 @@ CONFIG_HW_CONSOLE=y
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_GSC=y
CONFIG_SERIAL_8250_NR_UARTS=17
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_8250_EXTENDED=y
@@ -545,36 +507,15 @@ CONFIG_PRINTER=m
# CONFIG_LP_CONSOLE is not set
CONFIG_PPDEV=m
# CONFIG_TIPAR is not set
-
-#
-# IPMI
-#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
CONFIG_GEN_RTC=y
CONFIG_GEN_RTC_X=y
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
CONFIG_RAW_DRIVER=y
CONFIG_MAX_RAW_DEVS=256
-
-#
-# TPM devices
-#
# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
-
-#
-# I2C support
-#
# CONFIG_I2C is not set
#
@@ -582,46 +523,59 @@ CONFIG_MAX_RAW_DEVS=256
#
# CONFIG_SPI is not set
# CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
+# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
#
-# Misc devices
+# Sonics Silicon Backplane
#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
#
-# Multimedia Capabilities Port drivers
+# Multifunction device drivers
#
+# CONFIG_MFD_SM501 is not set
#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
CONFIG_FB_MODE_HELPERS=y
CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
CONFIG_FB_STI=y
# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_VIRTUAL is not set
@@ -633,6 +587,7 @@ CONFIG_DUMMY_CONSOLE=y
CONFIG_DUMMY_CONSOLE_COLUMNS=128
CONFIG_DUMMY_CONSOLE_ROWS=48
CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
CONFIG_STI_CONSOLE=y
CONFIG_FONTS=y
@@ -646,16 +601,11 @@ CONFIG_FONT_8x16=y
# CONFIG_FONT_SUN8x16 is not set
# CONFIG_FONT_SUN12x22 is not set
# CONFIG_FONT_10x18 is not set
-
-#
-# Logo configuration
-#
CONFIG_LOGO=y
# CONFIG_LOGO_LINUX_MONO is not set
# CONFIG_LOGO_LINUX_VGA16 is not set
# CONFIG_LOGO_LINUX_CLUT224 is not set
CONFIG_LOGO_PARISC_CLUT224=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -673,9 +623,11 @@ CONFIG_SND_SEQUENCER=y
CONFIG_SND_OSSEMUL=y
CONFIG_SND_MIXER_OSS=y
CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
CONFIG_SND_SEQUENCER_OSS=y
# CONFIG_SND_DYNAMIC_MINORS is not set
CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
# CONFIG_SND_VERBOSE_PRINTK is not set
# CONFIG_SND_DEBUG is not set
@@ -685,8 +637,10 @@ CONFIG_SND_SUPPORT_OLD_API=y
# CONFIG_SND_DUMMY is not set
# CONFIG_SND_VIRMIDI is not set
# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_MTS64 is not set
# CONFIG_SND_SERIAL_U16550 is not set
# CONFIG_SND_MPU401 is not set
+# CONFIG_SND_PORTMAN2X4 is not set
#
# GSC devices
@@ -694,15 +648,25 @@ CONFIG_SND_SUPPORT_OLD_API=y
CONFIG_SND_HARMONY=y
#
-# Open Sound System
+# System on Chip audio support
#
-# CONFIG_SOUND_PRIME is not set
+# CONFIG_SND_SOC is not set
#
-# USB support
+# SoC Audio support for SuperH
#
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+CONFIG_HID_DEBUG=y
+CONFIG_USB_SUPPORT=y
# CONFIG_USB_ARCH_HAS_HCD is not set
# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -712,19 +676,28 @@ CONFIG_SND_HARMONY=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_RTC_CLASS is not set
#
-# MMC/SD Card support
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
#
-# CONFIG_MMC is not set
#
-# InfiniBand support
+# DMA Devices
#
+# CONFIG_AUXDISPLAY is not set
#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+# Userspace I/O
#
+# CONFIG_UIO is not set
#
# File systems
@@ -734,6 +707,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4DEV_FS is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
# CONFIG_REISERFS_FS is not set
@@ -744,15 +718,16 @@ CONFIG_JFS_FS=m
# CONFIG_JFS_STATISTICS is not set
CONFIG_FS_POSIX_ACL=y
CONFIG_XFS_FS=m
-CONFIG_XFS_EXPORT=y
# CONFIG_XFS_QUOTA is not set
# CONFIG_XFS_SECURITY is not set
# CONFIG_XFS_POSIX_ACL is not set
# CONFIG_XFS_RT is not set
+# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
@@ -783,11 +758,12 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
# CONFIG_CONFIGFS_FS is not set
#
@@ -795,6 +771,7 @@ CONFIG_RAMFS=y
#
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
# CONFIG_HFS_FS is not set
# CONFIG_HFSPLUS_FS is not set
# CONFIG_BEFS_FS is not set
@@ -806,6 +783,8 @@ CONFIG_RAMFS=y
# CONFIG_QNX4FS_FS is not set
# CONFIG_SYSV_FS is not set
CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
#
# Network File Systems
@@ -827,6 +806,7 @@ CONFIG_EXPORTFS=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
CONFIG_RPCSEC_GSS_KRB5=y
CONFIG_RPCSEC_GSS_SPKM3=m
CONFIG_SMB_FS=m
@@ -834,12 +814,13 @@ 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
-# CONFIG_9P_FS is not set
#
# Partition Types
@@ -892,6 +873,11 @@ CONFIG_NLS_KOI8_U=m
CONFIG_NLS_UTF8=m
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Profiling support
#
CONFIG_PROFILING=y
@@ -901,21 +887,32 @@ CONFIG_OPROFILE=m
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
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_LOG_BUF_SHIFT=16
+# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
# CONFIG_DEBUG_SLAB is not set
-CONFIG_DEBUG_MUTEXES=y
+# 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_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
CONFIG_DEBUG_RODATA=y
#
@@ -924,12 +921,13 @@ CONFIG_DEBUG_RODATA=y
CONFIG_KEYS=y
CONFIG_KEYS_DEBUG_PROC_KEYS=y
# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_MD4=m
CONFIG_CRYPTO_MD5=y
@@ -938,9 +936,18 @@ CONFIG_CRYPTO_SHA256=m
CONFIG_CRYPTO_SHA512=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_TGR192=m
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_AES=m
CONFIG_CRYPTO_CAST5=m
@@ -949,21 +956,28 @@ CONFIG_CRYPTO_TEA=m
CONFIG_CRYPTO_ARC4=m
CONFIG_CRYPTO_KHAZAD=m
CONFIG_CRYPTO_ANUBIS=m
+# CONFIG_CRYPTO_SEED is not set
CONFIG_CRYPTO_DEFLATE=m
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_CAMELLIA is not set
CONFIG_CRYPTO_TEST=m
-
-#
-# Hardware crypto devices
-#
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_HW is not set
#
# Library routines
#
+CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
CONFIG_LIBCRC32C=m
CONFIG_ZLIB_INFLATE=m
CONFIG_ZLIB_DEFLATE=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/parisc/configs/a500_defconfig b/arch/parisc/configs/a500_defconfig
index f3b812f04592..ea071218a3ed 100644
--- a/arch/parisc/configs/a500_defconfig
+++ b/arch/parisc/configs/a500_defconfig
@@ -1,73 +1,98 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.14-rc5-pa1
-# Fri Oct 21 23:04:54 2005
+# Linux kernel version: 2.6.23
+# Fri Oct 12 21:12:44 2007
#
CONFIG_PARISC=y
CONFIG_MMU=y
CONFIG_STACK_GROWSUP=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_TIME_LOW_RES=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
-# Code maturity level options
+# General setup
#
CONFIG_EXPERIMENTAL=y
-# CONFIG_CLEAN_COMPILE is not set
-CONFIG_BROKEN=y
-CONFIG_BROKEN_ON_SMP=y
CONFIG_LOCK_KERNEL=y
CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
CONFIG_LOCALVERSION=""
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_USER_NS is not set
# CONFIG_AUDIT is not set
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
# CONFIG_CPUSETS is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
+CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SIGNALFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-
-#
-# Loadable module support
-#
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
CONFIG_STOP_MACHINE=y
+CONFIG_BLOCK=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_BLOCK_COMPAT=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
#
# Processor type and features
@@ -80,11 +105,23 @@ CONFIG_PA8X00=y
CONFIG_PA20=y
CONFIG_PREFETCH=y
CONFIG_64BIT=y
+CONFIG_PARISC_PAGE_SIZE_4KB=y
+# CONFIG_PARISC_PAGE_SIZE_16KB is not set
+# CONFIG_PARISC_PAGE_SIZE_64KB is not set
CONFIG_SMP=y
CONFIG_HOTPLUG_CPU=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y
+CONFIG_NODES_SHIFT=3
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_BKL=y
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
CONFIG_SELECT_MEMORY_MODEL=y
@@ -95,7 +132,10 @@ CONFIG_DISCONTIGMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_NEED_MULTIPLE_NODES=y
# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_PREEMPT is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
CONFIG_COMPAT=y
CONFIG_NR_CPUS=8
@@ -104,7 +144,7 @@ CONFIG_NR_CPUS=8
#
# CONFIG_GSC is not set
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
# CONFIG_PCI_DEBUG is not set
CONFIG_PCI_LBA=y
CONFIG_IOSAPIC=y
@@ -124,13 +164,14 @@ CONFIG_CARDBUS=y
# PC-card bridges
#
CONFIG_YENTA=m
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
CONFIG_PD6729=m
CONFIG_I82092=m
CONFIG_PCCARD_NONSTATIC=m
-
-#
-# PCI Hotplug Support
-#
# CONFIG_HOTPLUG_PCI is not set
#
@@ -139,6 +180,7 @@ CONFIG_PCCARD_NONSTATIC=m
# CONFIG_SUPERIO is not set
# CONFIG_CHASSIS_LCD_LED is not set
CONFIG_PDC_CHASSIS=y
+CONFIG_PDC_CHASSIS_WARN=y
CONFIG_PDC_STABLE=y
#
@@ -160,7 +202,10 @@ CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
CONFIG_XFRM=y
CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
CONFIG_NET_KEY=m
+# CONFIG_NET_KEY_MIGRATE is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
# CONFIG_IP_ADVANCED_ROUTER is not set
@@ -177,97 +222,97 @@ CONFIG_IP_PNP_BOOTP=y
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
CONFIG_INET_TUNNEL=m
+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_BIC=y
-
-#
-# IP: Virtual Server Configuration
-#
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
# CONFIG_IP_VS is not set
CONFIG_IPV6=m
# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
+# CONFIG_IPV6_MIP6 is not set
+CONFIG_INET6_XFRM_TUNNEL=m
CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
CONFIG_IPV6_TUNNEL=m
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_NETWORK_SECMARK is not set
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NF_CONNTRACK_ENABLED is not set
+# CONFIG_NF_CONNTRACK is not set
+CONFIG_NETFILTER_XTABLES=m
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_TIME is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
#
# IP: Netfilter Configuration
#
-CONFIG_IP_NF_CONNTRACK=m
-# CONFIG_IP_NF_CT_ACCT is not set
-CONFIG_IP_NF_CONNTRACK_MARK=y
-# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
-CONFIG_IP_NF_CT_PROTO_SCTP=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-# CONFIG_IP_NF_NETBIOS_NS is not set
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-# CONFIG_IP_NF_PPTP is not set
CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MAC=m
-CONFIG_IP_NF_MATCH_PKTTYPE=m
-CONFIG_IP_NF_MATCH_MARK=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
CONFIG_IP_NF_MATCH_TOS=m
CONFIG_IP_NF_MATCH_RECENT=m
CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_LENGTH=m
+# CONFIG_IP_NF_MATCH_AH is not set
CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
-CONFIG_IP_NF_MATCH_HELPER=m
-CONFIG_IP_NF_MATCH_STATE=m
-CONFIG_IP_NF_MATCH_CONNTRACK=m
CONFIG_IP_NF_MATCH_OWNER=m
# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
-# CONFIG_IP_NF_MATCH_REALM is not set
-CONFIG_IP_NF_MATCH_SCTP=m
-# CONFIG_IP_NF_MATCH_DCCP is not set
-CONFIG_IP_NF_MATCH_COMMENT=m
-CONFIG_IP_NF_MATCH_CONNMARK=m
-CONFIG_IP_NF_MATCH_HASHLIMIT=m
-# CONFIG_IP_NF_MATCH_STRING is not set
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
-# CONFIG_IP_NF_TARGET_NFQUEUE is not set
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_IP_NF_TARGET_NETMAP=m
-CONFIG_IP_NF_TARGET_SAME=m
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_NAT_TFTP=m
-CONFIG_IP_NF_NAT_AMANDA=m
CONFIG_IP_NF_MANGLE=m
CONFIG_IP_NF_TARGET_TOS=m
CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_DSCP=m
-CONFIG_IP_NF_TARGET_MARK=m
-CONFIG_IP_NF_TARGET_CLASSIFY=m
# CONFIG_IP_NF_TARGET_TTL is not set
-CONFIG_IP_NF_TARGET_CONNMARK=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_RAW=m
-CONFIG_IP_NF_TARGET_NOTRACK=m
CONFIG_IP_NF_ARPTABLES=m
CONFIG_IP_NF_ARPFILTER=m
CONFIG_IP_NF_ARP_MANGLE=m
@@ -277,48 +322,38 @@ CONFIG_IP_NF_ARP_MANGLE=m
#
# CONFIG_IP6_NF_QUEUE is not set
CONFIG_IP6_NF_IPTABLES=m
-# CONFIG_IP6_NF_MATCH_LIMIT is not set
-CONFIG_IP6_NF_MATCH_MAC=m
CONFIG_IP6_NF_MATCH_RT=m
CONFIG_IP6_NF_MATCH_OPTS=m
CONFIG_IP6_NF_MATCH_FRAG=m
CONFIG_IP6_NF_MATCH_HL=m
-# CONFIG_IP6_NF_MATCH_MULTIPORT is not set
# CONFIG_IP6_NF_MATCH_OWNER is not set
-# CONFIG_IP6_NF_MATCH_MARK is not set
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-# CONFIG_IP6_NF_MATCH_AHESP is not set
-# CONFIG_IP6_NF_MATCH_LENGTH is not set
+# CONFIG_IP6_NF_MATCH_AH is not set
+# CONFIG_IP6_NF_MATCH_MH is not set
# CONFIG_IP6_NF_MATCH_EUI64 is not set
CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_LOG=m
CONFIG_IP6_NF_TARGET_REJECT=m
-# CONFIG_IP6_NF_TARGET_NFQUEUE is not set
CONFIG_IP6_NF_MANGLE=m
-# CONFIG_IP6_NF_TARGET_MARK is not set
# CONFIG_IP6_NF_TARGET_HL is not set
CONFIG_IP6_NF_RAW=m
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
CONFIG_IP_DCCP=m
CONFIG_INET_DCCP_DIAG=m
+CONFIG_IP_DCCP_ACKVEC=y
#
# DCCP CCIDs Configuration (EXPERIMENTAL)
#
+CONFIG_IP_DCCP_CCID2=m
+# CONFIG_IP_DCCP_CCID2_DEBUG is not set
# CONFIG_IP_DCCP_CCID3 is not set
#
# DCCP Kernel Hacking
#
# CONFIG_IP_DCCP_DEBUG is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
# CONFIG_VLAN_8021Q is not set
@@ -329,11 +364,13 @@ CONFIG_LLC2=m
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
#
# Network testing
@@ -342,7 +379,17 @@ CONFIG_NET_PKTGEN=m
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
#
# Device Drivers
@@ -351,34 +398,17 @@ CONFIG_NET_PKTGEN=m
#
# Generic Driver Options
#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
# CONFIG_STANDALONE is not set
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
CONFIG_FW_LOADER=y
# CONFIG_DEBUG_DRIVER is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
+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
@@ -391,21 +421,14 @@ CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=6144
-CONFIG_BLK_DEV_INITRD=y
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
# CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
# CONFIG_ATA_OVER_ETH is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+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_IDE is not set
#
@@ -413,6 +436,9 @@ CONFIG_IOSCHED_CFQ=y
#
CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+CONFIG_SCSI_NETLINK=y
CONFIG_SCSI_PROC_FS=y
#
@@ -432,18 +458,18 @@ CONFIG_CHR_DEV_SG=y
CONFIG_SCSI_MULTI_LUN=y
# 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 Transport Attributes
+# SCSI Transports
#
CONFIG_SCSI_SPI_ATTRS=y
CONFIG_SCSI_FC_ATTRS=m
CONFIG_SCSI_ISCSI_ATTRS=m
-CONFIG_SCSI_SAS_ATTRS=m
-
-#
-# SCSI low-level drivers
-#
+# CONFIG_SCSI_SAS_LIBSAS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP 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
@@ -451,59 +477,40 @@ CONFIG_SCSI_SAS_ATTRS=m
# CONFIG_SCSI_AIC7XXX is not set
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_AIC94XX 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_SATA is not set
-# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA_PIO 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_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_IOMAPPED is not set
-# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
-CONFIG_SCSI_QLOGIC_FC=m
-# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set
+CONFIG_SCSI_SYM53C8XX_MMIO=y
CONFIG_SCSI_QLOGIC_1280=m
-# CONFIG_SCSI_QLOGIC_1280_1040 is not set
-CONFIG_SCSI_QLA2XXX=y
-# CONFIG_SCSI_QLA21XX is not set
-# CONFIG_SCSI_QLA22XX is not set
-CONFIG_SCSI_QLA2300=m
-CONFIG_SCSI_QLA2322=m
-# CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA24XX is not set
+# 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=m
-
-#
-# PCMCIA SCSI adapter support
-#
-CONFIG_PCMCIA_FDOMAIN=m
-CONFIG_PCMCIA_QLOGIC=m
-CONFIG_PCMCIA_SYM53C500=m
-
-#
-# Multi-device support (RAID and LVM)
-#
+# CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set
+# CONFIG_ATA is not set
CONFIG_MD=y
CONFIG_BLK_DEV_MD=y
CONFIG_MD_LINEAR=y
CONFIG_MD_RAID0=y
CONFIG_MD_RAID1=y
# CONFIG_MD_RAID10 is not set
-# CONFIG_MD_RAID5 is not set
-# CONFIG_MD_RAID6 is not set
+# CONFIG_MD_RAID456 is not set
# CONFIG_MD_MULTIPATH is not set
# CONFIG_MD_FAULTY is not set
# CONFIG_BLK_DEV_DM is not set
@@ -517,39 +524,25 @@ CONFIG_FUSION_FC=m
# CONFIG_FUSION_SAS is not set
CONFIG_FUSION_MAX_SGE=128
CONFIG_FUSION_CTL=m
+# CONFIG_FUSION_LOGGING is not set
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
# CONFIG_I2O is not set
-
-#
-# Network device support
-#
CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
CONFIG_DUMMY=m
CONFIG_BONDING=m
+# CONFIG_MACVLAN is not set
# CONFIG_EQUALIZER is not set
CONFIG_TUN=m
-
-#
-# ARCnet devices
-#
+# CONFIG_VETH is not set
+# CONFIG_IP1000 is not set
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
# CONFIG_PHYLIB is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
CONFIG_NET_ETHERNET=y
CONFIG_MII=m
# CONFIG_HAPPYMEAL is not set
@@ -558,10 +551,6 @@ CONFIG_MII=m
CONFIG_NET_VENDOR_3COM=y
CONFIG_VORTEX=m
CONFIG_TYPHOON=m
-
-#
-# Tulip family network device support
-#
CONFIG_NET_TULIP=y
CONFIG_DE2104X=m
CONFIG_TULIP=y
@@ -573,15 +562,18 @@ CONFIG_TULIP_MMIO=y
# CONFIG_DM9102 is not set
# CONFIG_ULI526X is not set
CONFIG_PCMCIA_XIRCOM=m
-# CONFIG_PCMCIA_XIRTULIP is not set
CONFIG_HP100=m
+# 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_NET_PCI=y
CONFIG_PCNET32=m
+# CONFIG_PCNET32_NAPI 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_DGRS is not set
# CONFIG_EEPRO100 is not set
CONFIG_E100=m
# CONFIG_FEALNX is not set
@@ -593,84 +585,46 @@ CONFIG_E100=m
# CONFIG_EPIC100 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_VIA_RHINE is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+# CONFIG_SC92031 is not set
+CONFIG_NETDEV_1000=y
CONFIG_ACENIC=m
CONFIG_ACENIC_OMIT_TIGON_I=y
# CONFIG_DL2K is not set
CONFIG_E1000=m
CONFIG_E1000_NAPI=y
# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+# CONFIG_E1000E 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_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
CONFIG_TIGON3=m
# CONFIG_BNX2 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_IXGBE is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+# CONFIG_NIU is not set
+# CONFIG_MLX4_CORE is not set
+# CONFIG_TEHUTI is not set
# CONFIG_TR is not set
#
-# Wireless LAN (non-hamradio)
-#
-CONFIG_NET_RADIO=y
-
-#
-# Obsolete Wireless cards support (pre-802.11)
-#
-# CONFIG_STRIP is not set
-# CONFIG_PCMCIA_WAVELAN is not set
-CONFIG_PCMCIA_NETWAVE=m
-
-#
-# Wireless 802.11 Frequency Hopping cards support
-#
-CONFIG_PCMCIA_RAYCS=m
-
-#
-# Wireless 802.11b ISA/PCI cards support
-#
-CONFIG_HERMES=m
-CONFIG_PLX_HERMES=m
-CONFIG_TMD_HERMES=m
-# CONFIG_NORTEL_HERMES is not set
-CONFIG_PCI_HERMES=m
-# CONFIG_ATMEL is not set
-
-#
-# Wireless 802.11b Pcmcia/Cardbus cards support
-#
-CONFIG_PCMCIA_HERMES=m
-# CONFIG_PCMCIA_SPECTRUM is not set
-CONFIG_AIRO_CS=m
-CONFIG_PCMCIA_WL3501=m
-
-#
-# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
-#
-# CONFIG_PRISM54 is not set
-# CONFIG_HOSTAP is not set
-CONFIG_NET_WIRELESS=y
-
-#
-# PCMCIA network device support
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
CONFIG_NET_PCMCIA=y
CONFIG_PCMCIA_3C589=m
CONFIG_PCMCIA_3C574=m
@@ -680,10 +634,6 @@ CONFIG_PCMCIA_3C574=m
CONFIG_PCMCIA_SMC91C92=m
CONFIG_PCMCIA_XIRC2PS=m
# CONFIG_PCMCIA_AXNET is not set
-
-#
-# Wan interfaces
-#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -694,28 +644,25 @@ CONFIG_PPP_ASYNC=m
CONFIG_PPP_SYNC_TTY=m
CONFIG_PPP_DEFLATE=m
CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPP_MPPE is not set
# CONFIG_PPPOE is not set
+# CONFIG_PPPOL2TP is not set
# CONFIG_SLIP is not set
+CONFIG_SLHC=m
# CONFIG_NET_FC is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
# 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
@@ -732,6 +679,7 @@ CONFIG_INPUT=y
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE 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
@@ -747,6 +695,7 @@ CONFIG_INPUT=y
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
# CONFIG_SERIAL_NONSTANDARD is not set
#
@@ -754,8 +703,10 @@ CONFIG_HW_CONSOLE=y
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_CS=m
CONFIG_SERIAL_8250_NR_UARTS=17
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_MANY_PORTS=y
CONFIG_SERIAL_8250_SHARE_IRQ=y
@@ -765,83 +716,73 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y
#
# Non-8250 serial port support
#
-# CONFIG_SERIAL_MUX is not set
CONFIG_PDC_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
# CONFIG_LEGACY_PTYS is not set
-
-#
-# IPMI
-#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
CONFIG_GEN_RTC=y
CONFIG_GEN_RTC_X=y
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
+CONFIG_AGP=y
+CONFIG_AGP_PARISC=y
# CONFIG_DRM is not set
#
# PCMCIA character devices
#
# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
CONFIG_RAW_DRIVER=y
CONFIG_MAX_RAW_DEVS=256
-
-#
-# TPM devices
-#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
# CONFIG_I2C is not set
#
-# Dallas's 1-wire bus
+# SPI support
#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
+# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
#
-# Misc devices
+# Sonics Silicon Backplane
#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
#
-# Multimedia Capabilities Port drivers
+# Multifunction device drivers
#
+# CONFIG_MFD_SM501 is not set
#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
# CONFIG_FB is not set
#
@@ -856,34 +797,47 @@ CONFIG_DUMMY_CONSOLE_ROWS=64
# Sound
#
# CONFIG_SOUND is not set
-
-#
-# USB support
-#
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG 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 is not set
#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_INFINIBAND is not set
+# CONFIG_RTC_CLASS is not set
#
-# MMC/SD Card support
+# DMA Engine support
#
-# CONFIG_MMC is not set
+# CONFIG_DMA_ENGINE is not set
#
-# InfiniBand support
+# DMA Clients
#
-# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# DMA Devices
#
#
+# Userspace I/O
+#
+# CONFIG_UIO is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -891,6 +845,7 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4DEV_FS is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
# CONFIG_REISERFS_FS is not set
@@ -901,14 +856,16 @@ CONFIG_JFS_FS=m
# CONFIG_JFS_STATISTICS is not set
CONFIG_FS_POSIX_ACL=y
CONFIG_XFS_FS=m
-CONFIG_XFS_EXPORT=y
# CONFIG_XFS_QUOTA is not set
# CONFIG_XFS_SECURITY is not set
# CONFIG_XFS_POSIX_ACL is not set
# CONFIG_XFS_RT is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
@@ -939,18 +896,20 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
-# CONFIG_HUGETLBFS is not set
+# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
#
# Miscellaneous filesystems
#
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
# CONFIG_HFS_FS is not set
# CONFIG_HFSPLUS_FS is not set
# CONFIG_BEFS_FS is not set
@@ -963,6 +922,7 @@ CONFIG_RAMFS=y
# CONFIG_SYSV_FS is not set
CONFIG_UFS_FS=m
# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
#
# Network File Systems
@@ -983,6 +943,7 @@ CONFIG_EXPORTFS=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=m
CONFIG_SUNRPC_GSS=m
+# CONFIG_SUNRPC_BIND34 is not set
CONFIG_RPCSEC_GSS_KRB5=m
CONFIG_RPCSEC_GSS_SPKM3=m
CONFIG_SMB_FS=m
@@ -990,12 +951,13 @@ 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
-# CONFIG_9P_FS is not set
#
# Partition Types
@@ -1048,6 +1010,11 @@ CONFIG_NLS_ISO8859_15=m
CONFIG_NLS_UTF8=m
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Profiling support
#
CONFIG_PROFILING=y
@@ -1057,19 +1024,34 @@ CONFIG_OPROFILE=m
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
+CONFIG_ENABLE_MUST_CHECK=y
CONFIG_MAGIC_SYSRQ=y
-CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+CONFIG_HEADERS_CHECK=y
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
# CONFIG_DEBUG_SLAB 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 is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_IOREMAP is not set
-# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
# CONFIG_DEBUG_RWLOCK is not set
+# CONFIG_DEBUG_RODATA is not set
#
# Security options
@@ -1077,12 +1059,13 @@ CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_KEYS=y
CONFIG_KEYS_DEBUG_PROC_KEYS=y
# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
CONFIG_CRYPTO_NULL=m
# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=y
@@ -1091,32 +1074,47 @@ CONFIG_CRYPTO_SHA1=m
# CONFIG_CRYPTO_SHA512 is not set
# CONFIG_CRYPTO_WP512 is not set
# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_ECB is not set
+CONFIG_CRYPTO_CBC=m
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_FCRYPT is not set
CONFIG_CRYPTO_BLOWFISH=m
# CONFIG_CRYPTO_TWOFISH is not set
# CONFIG_CRYPTO_SERPENT is not set
# CONFIG_CRYPTO_AES is not set
-# CONFIG_CRYPTO_CAST5 is not set
+CONFIG_CRYPTO_CAST5=m
# CONFIG_CRYPTO_CAST6 is not set
# CONFIG_CRYPTO_TEA is not set
# CONFIG_CRYPTO_ARC4 is not set
# CONFIG_CRYPTO_KHAZAD is not set
# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_SEED is not set
CONFIG_CRYPTO_DEFLATE=m
# CONFIG_CRYPTO_MICHAEL_MIC is not set
CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_CAMELLIA is not set
CONFIG_CRYPTO_TEST=m
-
-#
-# Hardware crypto devices
-#
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_HW is not set
#
# Library routines
#
+CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
CONFIG_LIBCRC32C=m
CONFIG_ZLIB_INFLATE=m
CONFIG_ZLIB_DEFLATE=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/parisc/configs/b180_defconfig b/arch/parisc/configs/b180_defconfig
index 35093612ad2c..1bf22c9a4614 100644
--- a/arch/parisc/configs/b180_defconfig
+++ b/arch/parisc/configs/b180_defconfig
@@ -1,38 +1,47 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1-pa0
-# Tue Jan 17 08:21:01 2006
+# Linux kernel version: 2.6.23
+# Fri Oct 12 21:16:46 2007
#
CONFIG_PARISC=y
CONFIG_MMU=y
CONFIG_STACK_GROWSUP=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
-# Code maturity level options
+# General setup
#
# CONFIG_EXPERIMENTAL is not set
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
CONFIG_LOCALVERSION=""
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
-CONFIG_INITRAMFS_SOURCE=""
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_SYSCTL=y
# CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -42,30 +51,27 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
-
-#
-# Loadable module support
-#
CONFIG_MODULES=y
# CONFIG_MODULE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
# CONFIG_KMOD is not set
-
-#
-# Block layer
-#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -89,16 +95,26 @@ CONFIG_PA7100LC=y
# CONFIG_PA7300LC is not set
# CONFIG_PA8X00 is not set
CONFIG_PA11=y
+CONFIG_PARISC_PAGE_SIZE_4KB=y
+# CONFIG_PARISC_PAGE_SIZE_16KB is not set
+# CONFIG_PARISC_PAGE_SIZE_64KB is not set
# CONFIG_SMP is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4096
-# CONFIG_PREEMPT is not set
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
# CONFIG_HPUX is not set
#
@@ -113,7 +129,7 @@ CONFIG_EISA=y
CONFIG_EISA_NAMES=y
CONFIG_ISA=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
# CONFIG_PCI_DEBUG is not set
CONFIG_GSC_DINO=y
# CONFIG_PCI_LBA is not set
@@ -124,14 +140,11 @@ CONFIG_GSC_DINO=y
# CONFIG_PCCARD is not set
#
-# PCI Hotplug Support
-#
-
-#
# PA-RISC specific drivers
#
CONFIG_CHASSIS_LCD_LED=y
# CONFIG_PDC_CHASSIS is not set
+CONFIG_PDC_CHASSIS_WARN=y
CONFIG_PDC_STABLE=y
#
@@ -151,6 +164,8 @@ CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -167,18 +182,32 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
+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_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
CONFIG_IPV6=y
# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
# CONFIG_INET6_AH is not set
# CONFIG_INET6_ESP is not set
# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+CONFIG_IPV6_SIT=y
# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_NETLABEL is not set
+# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
# CONFIG_BRIDGE is not set
# CONFIG_VLAN_8021Q is not set
@@ -199,7 +228,14 @@ CONFIG_IPV6=y
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -208,39 +244,24 @@ CONFIG_IPV6=y
#
# Generic Driver Options
#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
# CONFIG_FW_LOADER is not set
# CONFIG_DEBUG_DRIVER is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
CONFIG_PARPORT=y
CONFIG_PARPORT_PC=y
# CONFIG_PARPORT_SERIAL is not set
-CONFIG_PARPORT_NOT_PC=y
CONFIG_PARPORT_GSC=y
+# CONFIG_PARPORT_AX88796 is not set
# CONFIG_PARPORT_1284 is not set
-
-#
-# Plug and Play support
-#
+CONFIG_PARPORT_NOT_PC=y
# CONFIG_PNP is not set
-
-#
-# Block devices
-#
+CONFIG_BLK_DEV=y
# CONFIG_PARIDE is not set
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_CPQ_CISS_DA is not set
@@ -251,15 +272,13 @@ CONFIG_BLK_DEV_CRYPTOLOOP=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
CONFIG_ATA_OVER_ETH=y
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+CONFIG_MISC_DEVICES=y
+# CONFIG_PHANTOM is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_SGI_IOC4 is not set
# CONFIG_IDE is not set
#
@@ -267,6 +286,8 @@ CONFIG_ATA_OVER_ETH=y
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_NETLINK is not set
CONFIG_SCSI_PROC_FS=y
#
@@ -286,18 +307,17 @@ CONFIG_CHR_DEV_SG=y
# 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 Transport Attributes
+# SCSI Transports
#
CONFIG_SCSI_SPI_ATTRS=y
# CONFIG_SCSI_FC_ATTRS is not set
# CONFIG_SCSI_ISCSI_ATTRS is not set
-# CONFIG_SCSI_SAS_ATTRS is not set
-
-#
-# SCSI low-level drivers
-#
+# CONFIG_SCSI_SAS_LIBSAS is not set
+CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
@@ -308,12 +328,14 @@ CONFIG_SCSI_SPI_ATTRS=y
# 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_IN2000 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_SATA is not set
+# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_DTC3280 is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -327,23 +349,22 @@ CONFIG_SCSI_SPI_ATTRS=y
# CONFIG_SCSI_NCR53C406A is not set
CONFIG_SCSI_LASI700=y
CONFIG_53C700_LE_ON_BE=y
+# CONFIG_SCSI_STEX is not set
CONFIG_SCSI_SYM53C8XX_2=y
CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
CONFIG_SCSI_SYM53C8XX_MMIO=y
-# CONFIG_SCSI_IPR is not set
CONFIG_SCSI_ZALON=y
CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
CONFIG_SCSI_NCR53C8XX_SYNC=40
-# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
# CONFIG_SCSI_PAS16 is not set
# CONFIG_SCSI_PSI240I is not set
# CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
# CONFIG_SCSI_LPFC is not set
# CONFIG_SCSI_SIM710 is not set
# CONFIG_SCSI_SYM53C416 is not set
@@ -351,22 +372,14 @@ CONFIG_SCSI_NCR53C8XX_SYNC=40
# CONFIG_SCSI_T128 is not set
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
-
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
+# CONFIG_SCSI_SRP is not set
+# CONFIG_ATA is not set
CONFIG_MD=y
CONFIG_BLK_DEV_MD=y
CONFIG_MD_LINEAR=y
CONFIG_MD_RAID0=y
CONFIG_MD_RAID1=y
-CONFIG_MD_RAID5=y
-CONFIG_MD_RAID6=y
+# CONFIG_MD_RAID456 is not set
# CONFIG_MD_MULTIPATH is not set
# CONFIG_MD_FAULTY is not set
# CONFIG_BLK_DEV_DM is not set
@@ -382,35 +395,21 @@ CONFIG_MD_RAID6=y
#
# IEEE 1394 (FireWire) support
#
-# CONFIG_IEEE1394 is not set
#
-# I2O device support
+# An alternative FireWire stack is available with EXPERIMENTAL=y
#
+# CONFIG_IEEE1394 is not set
# CONFIG_I2O is not set
-
-#
-# Network device support
-#
CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
+# CONFIG_VETH is not set
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
# CONFIG_PHYLIB is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
CONFIG_NET_ETHERNET=y
# CONFIG_MII is not set
CONFIG_LASI_82596=y
@@ -420,10 +419,6 @@ CONFIG_LASI_82596=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_NET_VENDOR_SMC is not set
# CONFIG_NET_VENDOR_RACAL is not set
-
-#
-# Tulip family network device support
-#
CONFIG_NET_TULIP=y
CONFIG_TULIP=y
# CONFIG_TULIP_MMIO is not set
@@ -435,62 +430,47 @@ CONFIG_TULIP=y
# CONFIG_DEPCA is not set
# CONFIG_HP100 is not set
# CONFIG_NET_ISA 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_NET_PCI is not set
+# CONFIG_B44 is not set
# CONFIG_NET_POCKET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_R8169 is not set
# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_QLA3XXX is not set
+CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_IXGBE is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+# CONFIG_NIU is not set
+# CONFIG_MLX4_CORE is not set
+# CONFIG_TEHUTI is not set
# CONFIG_TR is not set
#
-# Wireless LAN (non-hamradio)
-#
-CONFIG_NET_RADIO=y
-
-#
-# Obsolete Wireless cards support (pre-802.11)
-#
-# CONFIG_STRIP is not set
-# CONFIG_ARLAN is not set
-# CONFIG_WAVELAN is not set
-
-#
-# Wireless 802.11b ISA/PCI cards support
-#
-# CONFIG_HERMES is not set
-# CONFIG_ATMEL is not set
-
-#
-# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
-#
-# CONFIG_HOSTAP is not set
-CONFIG_NET_WIRELESS=y
-
-#
-# Wan interfaces
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_PLIP is not set
@@ -501,24 +481,19 @@ CONFIG_PPP=y
# CONFIG_PPP_DEFLATE is not set
# CONFIG_PPP_BSDCOMP is not set
# CONFIG_SLIP is not set
+CONFIG_SLHC=y
# CONFIG_NET_FC is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
# 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
@@ -543,19 +518,31 @@ CONFIG_KEYBOARD_ATKBD_HP_KEYCODES=y
# 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_KEYBOARD_HIL_OLD is not set
CONFIG_KEYBOARD_HIL=y
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_TOUCHKIT is not set
# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
# CONFIG_MOUSE_INPORT is not set
# CONFIG_MOUSE_LOGIBM is not set
# CONFIG_MOUSE_PC110PAD is not set
# CONFIG_MOUSE_VSXXXAA is not set
CONFIG_MOUSE_HIL=y
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_POWERMATE is not set
# CONFIG_INPUT_UINPUT is not set
# CONFIG_HP_SDC_RTC is not set
@@ -579,6 +566,7 @@ CONFIG_SERIO_LIBPS2=y
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
# CONFIG_SERIAL_NONSTANDARD is not set
#
@@ -586,17 +574,20 @@ CONFIG_HW_CONSOLE=y
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_GSC=y
+CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=13
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_MANY_PORTS=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_RSA is not set
# CONFIG_SERIAL_8250_FOURPORT is not set
# CONFIG_SERIAL_8250_ACCENT is not set
# CONFIG_SERIAL_8250_BOCA is not set
+# CONFIG_SERIAL_8250_EXAR_ST16C554 is not set
# CONFIG_SERIAL_8250_HUB6 is not set
+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
@@ -605,6 +596,7 @@ CONFIG_SERIAL_MUX=y
CONFIG_SERIAL_MUX_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -612,35 +604,18 @@ CONFIG_PRINTER=y
# CONFIG_LP_CONSOLE is not set
# CONFIG_PPDEV is not set
# CONFIG_TIPAR is not set
-
-#
-# IPMI
-#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
+# CONFIG_AGP is not set
# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
# CONFIG_I2C is not set
#
@@ -648,46 +623,59 @@ CONFIG_GEN_RTC=y
#
# CONFIG_SPI is not set
# CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
+# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
#
-# Misc devices
+# Sonics Silicon Backplane
#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
#
-# Multimedia Capabilities Port drivers
+# Multifunction device drivers
#
+# CONFIG_MFD_SM501 is not set
#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
# CONFIG_FB_MODE_HELPERS is not set
# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
# CONFIG_FB_CIRRUS is not set
# CONFIG_FB_PM2 is not set
# CONFIG_FB_CYBER2000 is not set
@@ -698,16 +686,18 @@ CONFIG_FB_STI=y
# CONFIG_FB_NVIDIA is not set
# CONFIG_FB_RIVA is not set
# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
# CONFIG_FB_RADEON is not set
# CONFIG_FB_ATY128 is not set
# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
# CONFIG_FB_SIS is not set
# CONFIG_FB_NEOMAGIC is not set
# CONFIG_FB_KYRO is not set
# CONFIG_FB_3DFX is not set
# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
# CONFIG_FB_VIRTUAL is not set
#
@@ -717,21 +707,17 @@ CONFIG_DUMMY_CONSOLE=y
CONFIG_DUMMY_CONSOLE_COLUMNS=160
CONFIG_DUMMY_CONSOLE_ROWS=64
CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
CONFIG_STI_CONSOLE=y
# CONFIG_FONTS is not set
CONFIG_FONT_8x8=y
CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
CONFIG_LOGO=y
CONFIG_LOGO_LINUX_MONO=y
CONFIG_LOGO_LINUX_VGA16=y
CONFIG_LOGO_LINUX_CLUT224=y
CONFIG_LOGO_PARISC_CLUT224=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -749,8 +735,11 @@ CONFIG_SND_SEQUENCER=y
CONFIG_SND_OSSEMUL=y
CONFIG_SND_MIXER_OSS=y
CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
# CONFIG_SND_VERBOSE_PRINTK is not set
# CONFIG_SND_DEBUG is not set
@@ -760,13 +749,16 @@ CONFIG_SND_SUPPORT_OLD_API=y
# CONFIG_SND_DUMMY is not set
# CONFIG_SND_VIRMIDI is not set
# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_MTS64 is not set
# CONFIG_SND_SERIAL_U16550 is not set
# CONFIG_SND_MPU401 is not set
+# CONFIG_SND_PORTMAN2X4 is not set
#
# PCI devices
#
# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
# CONFIG_SND_ALI5451 is not set
# CONFIG_SND_ATIIXP is not set
# CONFIG_SND_ATIIXP_MODEM is not set
@@ -778,6 +770,18 @@ CONFIG_SND_SUPPORT_OLD_API=y
# CONFIG_SND_CMIPCI is not set
# CONFIG_SND_CS4281 is not set
# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_DARLA20 is not set
+# CONFIG_SND_GINA20 is not set
+# CONFIG_SND_LAYLA20 is not set
+# CONFIG_SND_DARLA24 is not set
+# CONFIG_SND_GINA24 is not set
+# CONFIG_SND_LAYLA24 is not set
+# CONFIG_SND_MONA is not set
+# CONFIG_SND_MIA is not set
+# CONFIG_SND_ECHO3G is not set
+# CONFIG_SND_INDIGO is not set
+# CONFIG_SND_INDIGOIO is not set
+# CONFIG_SND_INDIGODJ is not set
# CONFIG_SND_EMU10K1 is not set
# CONFIG_SND_EMU10K1X is not set
# CONFIG_SND_ENS1370 is not set
@@ -791,11 +795,13 @@ CONFIG_SND_SUPPORT_OLD_API=y
# CONFIG_SND_ICE1712 is not set
# CONFIG_SND_ICE1724 is not set
# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
# CONFIG_SND_KORG1212 is not set
# CONFIG_SND_MAESTRO3 is not set
# CONFIG_SND_MIXART is not set
# CONFIG_SND_NM256 is not set
# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
# CONFIG_SND_RME32 is not set
# CONFIG_SND_RME96 is not set
# CONFIG_SND_RME9652 is not set
@@ -812,15 +818,25 @@ CONFIG_SND_SUPPORT_OLD_API=y
CONFIG_SND_HARMONY=y
#
-# Open Sound System
+# System on Chip audio support
#
-# CONFIG_SOUND_PRIME is not set
+# CONFIG_SND_SOC is not set
#
-# USB support
+# SoC Audio support for SuperH
+#
+
+#
+# Open Sound System
#
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+CONFIG_HID_DEBUG=y
+CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -831,20 +847,29 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_INFINIBAND is not set
+# CONFIG_RTC_CLASS is not set
#
-# MMC/SD Card support
+# DMA Engine support
#
-# CONFIG_MMC is not set
+# CONFIG_DMA_ENGINE is not set
#
-# InfiniBand support
+# DMA Clients
#
-# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# DMA Devices
#
+# CONFIG_AUXDISPLAY is not set
+
+#
+# Userspace I/O
+#
+# CONFIG_UIO is not set
#
# File systems
@@ -860,9 +885,11 @@ CONFIG_JBD=y
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
@@ -889,11 +916,12 @@ CONFIG_JOLIET=y
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
#
# Miscellaneous filesystems
@@ -912,6 +940,7 @@ CONFIG_RAMFS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_DIRECTIO is not set
CONFIG_NFSD=y
CONFIG_NFSD_V3=y
# CONFIG_NFSD_V3_ACL is not set
@@ -982,22 +1011,32 @@ CONFIG_NLS_UTF8=m
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+CONFIG_HEADERS_CHECK=y
CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_MUTEXES 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 is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_IOREMAP is not set
-# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
# CONFIG_DEBUG_RODATA is not set
#
@@ -1007,13 +1046,10 @@ CONFIG_FORCED_INLINING=y
CONFIG_SECURITY=y
# CONFIG_SECURITY_NETWORK is not set
CONFIG_SECURITY_CAPABILITIES=y
-# CONFIG_SECURITY_SECLVL is not set
-# CONFIG_SECURITY_SELINUX is not set
-
-#
-# Cryptographic options
-#
CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_MANAGER=y
# CONFIG_CRYPTO_HMAC is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_MD4 is not set
@@ -1023,7 +1059,12 @@ CONFIG_CRYPTO=y
# CONFIG_CRYPTO_SHA512 is not set
# CONFIG_CRYPTO_WP512 is not set
# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_ECB is not set
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_CRYPTD is not set
# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
# CONFIG_CRYPTO_BLOWFISH is not set
# CONFIG_CRYPTO_TWOFISH is not set
# CONFIG_CRYPTO_SERPENT is not set
@@ -1034,19 +1075,26 @@ CONFIG_CRYPTO=y
# CONFIG_CRYPTO_ARC4 is not set
# CONFIG_CRYPTO_KHAZAD is not set
# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_SEED is not set
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_MICHAEL_MIC is not set
# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
# CONFIG_CRYPTO_TEST is not set
-
-#
-# Hardware crypto devices
-#
+# CONFIG_CRYPTO_AUTHENC is not set
+CONFIG_CRYPTO_HW=y
#
# Library routines
#
+CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
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
diff --git a/arch/parisc/configs/c3000_defconfig b/arch/parisc/configs/c3000_defconfig
index eb2f9a3d515c..c6def3c1d209 100644
--- a/arch/parisc/configs/c3000_defconfig
+++ b/arch/parisc/configs/c3000_defconfig
@@ -1,39 +1,50 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-pa6
-# Sun Mar 26 20:03:29 2006
+# Linux kernel version: 2.6.23
+# Fri Oct 12 21:24:00 2007
#
CONFIG_PARISC=y
CONFIG_MMU=y
CONFIG_STACK_GROWSUP=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
-# Code maturity level options
+# General setup
#
CONFIG_EXPERIMENTAL=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
CONFIG_LOCALVERSION=""
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_USER_NS is not set
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
-CONFIG_INITRAMFS_SOURCE=""
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -43,31 +54,29 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
-
-#
-# Loadable module support
-#
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
-
-#
-# Block layer
-#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
#
# IO Schedulers
@@ -93,6 +102,9 @@ CONFIG_PA8X00=y
CONFIG_PA20=y
CONFIG_PREFETCH=y
# CONFIG_64BIT is not set
+CONFIG_PARISC_PAGE_SIZE_4KB=y
+# CONFIG_PARISC_PAGE_SIZE_16KB is not set
+# CONFIG_PARISC_PAGE_SIZE_64KB is not set
# CONFIG_SMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
# CONFIG_PREEMPT_NONE is not set
@@ -100,6 +112,7 @@ CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_PREEMPT is not set
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
CONFIG_SELECT_MEMORY_MODEL=y
@@ -110,6 +123,9 @@ CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
# CONFIG_HPUX is not set
#
@@ -117,7 +133,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
#
# CONFIG_GSC is not set
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
# CONFIG_PCI_DEBUG is not set
CONFIG_PCI_LBA=y
CONFIG_IOSAPIC=y
@@ -127,10 +143,6 @@ CONFIG_IOMMU_SBA=y
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
# CONFIG_HOTPLUG_PCI is not set
#
@@ -139,6 +151,7 @@ CONFIG_IOMMU_SBA=y
CONFIG_SUPERIO=y
CONFIG_CHASSIS_LCD_LED=y
# CONFIG_PDC_CHASSIS is not set
+CONFIG_PDC_CHASSIS_WARN=y
CONFIG_PDC_STABLE=y
#
@@ -155,13 +168,15 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
CONFIG_XFRM=y
CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
CONFIG_NET_KEY=m
+# CONFIG_NET_KEY_MIGRATE is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
# CONFIG_IP_ADVANCED_ROUTER is not set
@@ -178,22 +193,36 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+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 is not set
# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-
-#
-# IP: Virtual Server Configuration
-#
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
# CONFIG_IP_VS is not set
CONFIG_IPV6=m
# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
# CONFIG_INET6_AH is not set
# CONFIG_INET6_ESP is not set
CONFIG_INET6_IPCOMP=m
+# CONFIG_IPV6_MIP6 is not set
+CONFIG_INET6_XFRM_TUNNEL=m
CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
CONFIG_IPV6_TUNNEL=m
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_NETWORK_SECMARK is not set
CONFIG_NETFILTER=y
CONFIG_NETFILTER_DEBUG=y
@@ -201,42 +230,24 @@ CONFIG_NETFILTER_DEBUG=y
# Core Netfilter Configuration
#
# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NF_CONNTRACK_ENABLED is not set
+# CONFIG_NF_CONNTRACK is not set
# CONFIG_NETFILTER_XTABLES is not set
#
# IP: Netfilter Configuration
#
-CONFIG_IP_NF_CONNTRACK=m
-# CONFIG_IP_NF_CT_ACCT is not set
-# CONFIG_IP_NF_CONNTRACK_MARK is not set
-# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
-# CONFIG_IP_NF_CT_PROTO_SCTP is not set
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-# CONFIG_IP_NF_NETBIOS_NS is not set
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-# CONFIG_IP_NF_PPTP is not set
CONFIG_IP_NF_QUEUE=m
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
#
# IPv6: Netfilter Configuration (EXPERIMENTAL)
#
# CONFIG_IP6_NF_QUEUE is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
+# CONFIG_IP6_NF_IPTABLES is not set
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -247,7 +258,6 @@ CONFIG_IP_NF_QUEUE=m
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -263,7 +273,17 @@ CONFIG_NET_PKTGEN=m
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
#
# Device Drivers
@@ -272,33 +292,17 @@ CONFIG_NET_PKTGEN=m
#
# Generic Driver Options
#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
# CONFIG_STANDALONE is not set
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
CONFIG_FW_LOADER=y
# CONFIG_DEBUG_DRIVER is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-
-#
-# Block devices
-#
+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
@@ -310,14 +314,15 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_UB is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+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_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
CONFIG_BLK_DEV_IDE=y
#
@@ -331,19 +336,26 @@ CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDEFLOPPY is not set
CONFIG_BLK_DEV_IDESCSI=y
# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
#
# IDE chipset support/bugfixes
#
CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_PLATFORM is not set
+
+#
+# PCI IDE chipsets support
+#
CONFIG_BLK_DEV_IDEPCI=y
CONFIG_IDEPCI_SHARE_IRQ=y
+CONFIG_IDEPCI_PCIBUS_ORDER=y
# CONFIG_BLK_DEV_OFFBOARD is not set
# CONFIG_BLK_DEV_GENERIC is not set
# CONFIG_BLK_DEV_OPTI621 is not set
CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-# CONFIG_IDEDMA_PCI_AUTO is not set
+CONFIG_IDEDMA_ONLYDISK=y
# CONFIG_BLK_DEV_AEC62XX is not set
# CONFIG_BLK_DEV_ALI15X3 is not set
# CONFIG_BLK_DEV_AMD74XX is not set
@@ -354,8 +366,10 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_CS5530 is not set
# CONFIG_BLK_DEV_HPT34X 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 is not set
+# CONFIG_BLK_DEV_IT8213 is not set
# CONFIG_BLK_DEV_IT821X is not set
CONFIG_BLK_DEV_NS87415=y
# CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -365,10 +379,10 @@ CONFIG_BLK_DEV_SIIMAGE=m
# 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_IDE_ARM is not set
CONFIG_BLK_DEV_IDEDMA=y
# CONFIG_IDEDMA_IVB is not set
-# CONFIG_IDEDMA_AUTO is not set
# CONFIG_BLK_DEV_HD is not set
#
@@ -376,6 +390,9 @@ CONFIG_BLK_DEV_IDEDMA=y
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
CONFIG_SCSI_PROC_FS=y
#
@@ -395,18 +412,17 @@ CONFIG_CHR_DEV_SG=y
CONFIG_SCSI_MULTI_LUN=y
# 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 Transport Attributes
+# SCSI Transports
#
CONFIG_SCSI_SPI_ATTRS=y
# CONFIG_SCSI_FC_ATTRS is not set
CONFIG_SCSI_ISCSI_ATTRS=m
-# CONFIG_SCSI_SAS_ATTRS is not set
-
-#
-# SCSI low-level drivers
-#
+# CONFIG_SCSI_SAS_LIBSAS is not set
+CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
@@ -415,66 +431,53 @@ CONFIG_SCSI_ISCSI_ATTRS=m
# 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_ARCMSR is not set
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
-CONFIG_SCSI_SATA=y
-# CONFIG_SCSI_SATA_AHCI is not set
-# CONFIG_SCSI_SATA_SVW is not set
-CONFIG_SCSI_ATA_PIIX=m
-# CONFIG_SCSI_SATA_MV is not set
-# CONFIG_SCSI_SATA_NV is not set
-# CONFIG_SCSI_PDC_ADMA is not set
-# CONFIG_SCSI_SATA_QSTOR is not set
-CONFIG_SCSI_SATA_PROMISE=m
-# CONFIG_SCSI_SATA_SX4 is not set
-CONFIG_SCSI_SATA_SIL=m
-# CONFIG_SCSI_SATA_SIL24 is not set
-# CONFIG_SCSI_SATA_SIS is not set
-# CONFIG_SCSI_SATA_ULI is not set
-CONFIG_SCSI_SATA_VIA=m
-# CONFIG_SCSI_SATA_VITESSE is not set
+# CONFIG_SCSI_HPTIOP 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_STEX is not set
CONFIG_SCSI_SYM53C8XX_2=y
CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
CONFIG_SCSI_SYM53C8XX_MMIO=y
-# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# 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_NSP32 is not set
CONFIG_SCSI_DEBUG=m
-
-#
-# Multi-device support (RAID and LVM)
-#
+# CONFIG_SCSI_SRP is not set
+# CONFIG_ATA is not set
CONFIG_MD=y
CONFIG_BLK_DEV_MD=y
CONFIG_MD_LINEAR=y
CONFIG_MD_RAID0=y
CONFIG_MD_RAID1=y
# CONFIG_MD_RAID10 is not set
-# CONFIG_MD_RAID5 is not set
-# CONFIG_MD_RAID6 is not set
+# CONFIG_MD_RAID456 is not set
# CONFIG_MD_MULTIPATH is not set
# 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=m
# CONFIG_DM_MULTIPATH_EMC is not set
+# CONFIG_DM_MULTIPATH_RDAC is not set
+# CONFIG_DM_DELAY is not set
#
# Fusion MPT device support
@@ -485,49 +488,31 @@ CONFIG_FUSION_SPI=m
# CONFIG_FUSION_SAS is not set
CONFIG_FUSION_MAX_SGE=128
CONFIG_FUSION_CTL=m
+# CONFIG_FUSION_LOGGING is not set
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
# CONFIG_I2O is not set
-
-#
-# Network device support
-#
CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
CONFIG_DUMMY=m
CONFIG_BONDING=m
+# CONFIG_MACVLAN is not set
# CONFIG_EQUALIZER is not set
CONFIG_TUN=m
-
-#
-# ARCnet devices
-#
+# CONFIG_VETH is not set
+# CONFIG_IP1000 is not set
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
# CONFIG_PHYLIB is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
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
-
-#
-# Tulip family network device support
-#
CONFIG_NET_TULIP=y
CONFIG_DE2104X=m
CONFIG_TULIP=y
@@ -539,13 +524,16 @@ CONFIG_TULIP_MMIO=y
# 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_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_DGRS is not set
# CONFIG_EEPRO100 is not set
CONFIG_E100=m
# CONFIG_FEALNX is not set
@@ -558,16 +546,15 @@ CONFIG_E100=m
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+# CONFIG_SC92031 is not set
+CONFIG_NETDEV_1000=y
CONFIG_ACENIC=m
# CONFIG_ACENIC_OMIT_TIGON_I is not set
# CONFIG_DL2K is not set
CONFIG_E1000=m
# CONFIG_E1000_NAPI is not set
# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+# CONFIG_E1000E is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
@@ -579,27 +566,36 @@ CONFIG_E1000=m
# CONFIG_VIA_VELOCITY is not set
CONFIG_TIGON3=m
# CONFIG_BNX2 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_IXGBE is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+# CONFIG_NIU is not set
+# CONFIG_MLX4_CORE is not set
+# CONFIG_TEHUTI is not set
# CONFIG_TR is not set
#
-# Wireless LAN (non-hamradio)
+# Wireless LAN
#
-# CONFIG_NET_RADIO is not set
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
#
-# Wan interfaces
+# 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_MII is not set
+# CONFIG_USB_USBNET is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -612,27 +608,23 @@ CONFIG_PPP_DEFLATE=m
CONFIG_PPP_BSDCOMP=m
# CONFIG_PPP_MPPE is not set
CONFIG_PPPOE=m
+# CONFIG_PPPOL2TP is not set
# CONFIG_SLIP is not set
+CONFIG_SLHC=m
# CONFIG_NET_FC is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
# 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
@@ -655,11 +647,14 @@ CONFIG_INPUT_KEYBOARD=y
# 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 is not set
# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH 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
@@ -679,6 +674,7 @@ CONFIG_SERIO_LIBPS2=m
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
# CONFIG_SERIAL_NONSTANDARD is not set
#
@@ -686,6 +682,7 @@ CONFIG_HW_CONSOLE=y
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=13
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_8250_EXTENDED=y
@@ -704,38 +701,19 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
CONFIG_GEN_RTC=y
CONFIG_GEN_RTC_X=y
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
+# CONFIG_AGP is not set
# CONFIG_DRM is not set
CONFIG_RAW_DRIVER=y
CONFIG_MAX_RAW_DEVS=256
-
-#
-# TPM devices
-#
# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
# CONFIG_I2C is not set
#
@@ -743,46 +721,59 @@ CONFIG_MAX_RAW_DEVS=256
#
# CONFIG_SPI is not set
# CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
+# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
#
-# Misc devices
+# Sonics Silicon Backplane
#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
#
-# Multimedia Capabilities Port drivers
+# Multifunction device drivers
#
+# CONFIG_MFD_SM501 is not set
#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
# CONFIG_FB_MODE_HELPERS is not set
# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
# CONFIG_FB_CIRRUS is not set
# CONFIG_FB_PM2 is not set
# CONFIG_FB_CYBER2000 is not set
@@ -793,17 +784,20 @@ CONFIG_FB_STI=y
# CONFIG_FB_NVIDIA is not set
# CONFIG_FB_RIVA is not set
# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
# CONFIG_FB_RADEON is not set
# CONFIG_FB_ATY128 is not set
# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
# CONFIG_FB_SAVAGE is not set
# CONFIG_FB_SIS is not set
# CONFIG_FB_NEOMAGIC is not set
# CONFIG_FB_KYRO is not set
# CONFIG_FB_3DFX is not set
# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
# CONFIG_FB_VIRTUAL is not set
#
@@ -813,21 +807,17 @@ CONFIG_DUMMY_CONSOLE=y
CONFIG_DUMMY_CONSOLE_COLUMNS=160
CONFIG_DUMMY_CONSOLE_ROWS=64
CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
CONFIG_STI_CONSOLE=y
# CONFIG_FONTS is not set
CONFIG_FONT_8x8=y
CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
CONFIG_LOGO=y
# CONFIG_LOGO_LINUX_MONO is not set
# CONFIG_LOGO_LINUX_VGA16 is not set
# CONFIG_LOGO_LINUX_CLUT224 is not set
CONFIG_LOGO_PARISC_CLUT224=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -845,9 +835,11 @@ CONFIG_SND_SEQUENCER=y
CONFIG_SND_OSSEMUL=y
CONFIG_SND_MIXER_OSS=y
CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
CONFIG_SND_SEQUENCER_OSS=y
# CONFIG_SND_DYNAMIC_MINORS is not set
CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
# CONFIG_SND_VERBOSE_PRINTK is not set
# CONFIG_SND_DEBUG is not set
@@ -855,7 +847,6 @@ CONFIG_SND_SUPPORT_OLD_API=y
# Generic devices
#
CONFIG_SND_AC97_CODEC=y
-CONFIG_SND_AC97_BUS=y
# CONFIG_SND_DUMMY is not set
# CONFIG_SND_VIRMIDI is not set
# CONFIG_SND_MTPAV is not set
@@ -866,7 +857,7 @@ CONFIG_SND_AC97_BUS=y
# PCI devices
#
CONFIG_SND_AD1889=y
-# CONFIG_SND_AD1889_OPL3 is not set
+# CONFIG_SND_ALS300 is not set
# CONFIG_SND_ALI5451 is not set
# CONFIG_SND_ATIIXP is not set
# CONFIG_SND_ATIIXP_MODEM is not set
@@ -879,6 +870,18 @@ CONFIG_SND_AD1889=y
# CONFIG_SND_CMIPCI is not set
# CONFIG_SND_CS4281 is not set
# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_DARLA20 is not set
+# CONFIG_SND_GINA20 is not set
+# CONFIG_SND_LAYLA20 is not set
+# CONFIG_SND_DARLA24 is not set
+# CONFIG_SND_GINA24 is not set
+# CONFIG_SND_LAYLA24 is not set
+# CONFIG_SND_MONA is not set
+# CONFIG_SND_MIA is not set
+# CONFIG_SND_ECHO3G is not set
+# CONFIG_SND_INDIGO is not set
+# CONFIG_SND_INDIGOIO is not set
+# CONFIG_SND_INDIGODJ is not set
# CONFIG_SND_EMU10K1 is not set
# CONFIG_SND_EMU10K1X is not set
# CONFIG_SND_ENS1370 is not set
@@ -898,6 +901,7 @@ CONFIG_SND_AD1889=y
# CONFIG_SND_MIXART is not set
# CONFIG_SND_NM256 is not set
# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
# CONFIG_SND_RME32 is not set
# CONFIG_SND_RME96 is not set
# CONFIG_SND_RME9652 is not set
@@ -907,22 +911,43 @@ CONFIG_SND_AD1889=y
# CONFIG_SND_VIA82XX_MODEM is not set
# CONFIG_SND_VX222 is not set
# CONFIG_SND_YMFPCI is not set
+# CONFIG_SND_AC97_POWER_SAVE is not set
#
# USB devices
#
# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_CAIAQ is not set
+
+#
+# System on Chip audio support
+#
+# CONFIG_SND_SOC is not set
+
+#
+# SoC Audio support for SuperH
+#
#
# Open Sound System
#
# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=y
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
#
-# USB support
+# USB Input Devices
#
+CONFIG_USB_HID=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+CONFIG_USB_HIDDEV=y
+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=y
@@ -930,7 +955,7 @@ CONFIG_USB_DEBUG=y
# Miscellaneous USB options
#
CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
+CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
# CONFIG_USB_OTG is not set
@@ -940,15 +965,16 @@ CONFIG_USB_DEVICEFS=y
# CONFIG_USB_EHCI_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+# 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 is not set
# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
#
# USB Device Class drivers
#
-# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
# CONFIG_USB_ACM is not set
CONFIG_USB_PRINTER=m
@@ -970,54 +996,14 @@ CONFIG_USB_STORAGE_SDDR09=y
CONFIG_USB_STORAGE_SDDR55=y
CONFIG_USB_STORAGE_JUMPSHOT=y
# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
# CONFIG_USB_LIBUSUAL is not set
#
-# USB Input Devices
-#
-CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
-CONFIG_USB_HIDDEV=y
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
-# CONFIG_USB_YEALINK is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_ATI_REMOTE2 is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-# CONFIG_USB_APPLETOUCH is not set
-
-#
# USB Imaging devices
#
CONFIG_USB_MDC800=m
CONFIG_USB_MICROTEK=m
-
-#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
-# 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_USB_MON is not set
#
@@ -1034,16 +1020,22 @@ CONFIG_USB_MICROTEK=m
#
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
# CONFIG_USB_AUERSWALD is not set
# CONFIG_USB_RIO500 is not set
CONFIG_USB_LEGOTOWER=m
# 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_PHIDGETKIT is not set
-# CONFIG_USB_PHIDGETSERVO 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_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
#
@@ -1054,22 +1046,30 @@ CONFIG_USB_LEGOTOWER=m
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_INFINIBAND is not set
+# CONFIG_RTC_CLASS is not set
#
-# MMC/SD Card support
+# DMA Engine support
#
-# CONFIG_MMC is not set
+# CONFIG_DMA_ENGINE is not set
#
-# InfiniBand support
+# DMA Clients
#
-# CONFIG_INFINIBAND is not set
#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+# DMA Devices
#
#
+# Userspace I/O
+#
+# CONFIG_UIO is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -1077,21 +1077,23 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4DEV_FS is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
CONFIG_XFS_FS=m
-CONFIG_XFS_EXPORT=y
# CONFIG_XFS_QUOTA is not set
# CONFIG_XFS_SECURITY is not set
# CONFIG_XFS_POSIX_ACL is not set
# CONFIG_XFS_RT is not set
+# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
@@ -1121,11 +1123,12 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
# CONFIG_CONFIGFS_FS is not set
#
@@ -1164,6 +1167,7 @@ CONFIG_LOCKD_V4=y
CONFIG_EXPORTFS=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -1171,7 +1175,6 @@ CONFIG_SUNRPC=y
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
#
# Partition Types
@@ -1224,6 +1227,11 @@ CONFIG_NLS_ISO8859_15=m
CONFIG_NLS_UTF8=m
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Profiling support
#
CONFIG_PROFILING=y
@@ -1233,21 +1241,32 @@ CONFIG_OPROFILE=m
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+CONFIG_HEADERS_CHECK=y
CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
# CONFIG_DEBUG_SLAB is not set
-CONFIG_DEBUG_MUTEXES=y
+# 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_BUGVERBOSE is not set
# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
CONFIG_DEBUG_RODATA=y
#
@@ -1255,12 +1274,12 @@ CONFIG_DEBUG_RODATA=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=m
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_MANAGER=m
# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
CONFIG_CRYPTO_NULL=m
# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=m
@@ -1269,7 +1288,15 @@ CONFIG_CRYPTO_MD5=m
# CONFIG_CRYPTO_SHA512 is not set
# CONFIG_CRYPTO_WP512 is not set
# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_ECB is not set
+CONFIG_CRYPTO_CBC=m
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_FCRYPT is not set
CONFIG_CRYPTO_BLOWFISH=m
# CONFIG_CRYPTO_TWOFISH is not set
# CONFIG_CRYPTO_SERPENT is not set
@@ -1280,21 +1307,28 @@ CONFIG_CRYPTO_BLOWFISH=m
# CONFIG_CRYPTO_ARC4 is not set
# CONFIG_CRYPTO_KHAZAD is not set
# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_SEED is not set
CONFIG_CRYPTO_DEFLATE=m
# CONFIG_CRYPTO_MICHAEL_MIC is not set
CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_CAMELLIA is not set
CONFIG_CRYPTO_TEST=m
-
-#
-# Hardware crypto devices
-#
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_HW is not set
#
# Library routines
#
+CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
CONFIG_LIBCRC32C=m
CONFIG_ZLIB_INFLATE=m
CONFIG_ZLIB_DEFLATE=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/parisc/defconfig b/arch/parisc/defconfig
index b38b58eb9dc2..448a757b06c6 100644
--- a/arch/parisc/defconfig
+++ b/arch/parisc/defconfig
@@ -1,39 +1,51 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-pa10
-# Sun Apr 2 15:26:38 2006
+# Linux kernel version: 2.6.23
+# Fri Oct 12 20:54:57 2007
#
CONFIG_PARISC=y
CONFIG_MMU=y
CONFIG_STACK_GROWSUP=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
-# Code maturity level options
+# General setup
#
CONFIG_EXPERIMENTAL=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
CONFIG_LOCALVERSION=""
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_USER_NS is not set
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY 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_EXTRA_PASS is not set
@@ -43,31 +55,29 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
-
-#
-# Loadable module support
-#
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
-
-#
-# Block layer
-#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
#
# IO Schedulers
@@ -101,6 +111,7 @@ CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_PREEMPT is not set
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
CONFIG_SELECT_MEMORY_MODEL=y
@@ -111,6 +122,9 @@ CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
# CONFIG_HPUX is not set
#
@@ -125,7 +139,7 @@ CONFIG_EISA=y
CONFIG_EISA_NAMES=y
# CONFIG_ISA is not set
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
# CONFIG_PCI_DEBUG is not set
CONFIG_GSC_DINO=y
CONFIG_PCI_LBA=y
@@ -154,10 +168,6 @@ CONFIG_YENTA_TOSHIBA=y
CONFIG_PD6729=y
CONFIG_I82092=y
CONFIG_PCCARD_NONSTATIC=y
-
-#
-# PCI Hotplug Support
-#
# CONFIG_HOTPLUG_PCI is not set
#
@@ -166,6 +176,7 @@ CONFIG_PCCARD_NONSTATIC=y
CONFIG_SUPERIO=y
CONFIG_CHASSIS_LCD_LED=y
CONFIG_PDC_CHASSIS=y
+CONFIG_PDC_CHASSIS_WARN=y
CONFIG_PDC_STABLE=y
#
@@ -182,13 +193,15 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
CONFIG_XFRM=y
CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
CONFIG_NET_KEY=m
+# CONFIG_NET_KEY_MIGRATE is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
# CONFIG_IP_ADVANCED_ROUTER is not set
@@ -205,33 +218,39 @@ CONFIG_IP_PNP_BOOTP=y
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
+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=m
CONFIG_INET_TCP_DIAG=m
# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
CONFIG_IPV6=y
# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
CONFIG_INET6_AH=y
CONFIG_INET6_ESP=y
CONFIG_INET6_IPCOMP=y
+# CONFIG_IPV6_MIP6 is not set
+CONFIG_INET6_XFRM_TUNNEL=y
CONFIG_INET6_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=y
# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -243,7 +262,6 @@ CONFIG_LLC2=m
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -259,7 +277,17 @@ CONFIG_LLC2=m
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
#
# Device Drivers
@@ -268,41 +296,26 @@ CONFIG_LLC2=m
#
# Generic Driver Options
#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
# CONFIG_STANDALONE is not set
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
CONFIG_FW_LOADER=y
# CONFIG_DEBUG_DRIVER is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
CONFIG_PARPORT=y
CONFIG_PARPORT_PC=m
# CONFIG_PARPORT_SERIAL is not set
# CONFIG_PARPORT_PC_FIFO is not set
# CONFIG_PARPORT_PC_SUPERIO is not set
CONFIG_PARPORT_PC_PCMCIA=m
-CONFIG_PARPORT_NOT_PC=y
CONFIG_PARPORT_GSC=y
+# CONFIG_PARPORT_AX88796 is not set
CONFIG_PARPORT_1284=y
-
-#
-# Plug and Play support
-#
-
-#
-# Block devices
-#
+CONFIG_PARPORT_NOT_PC=y
+CONFIG_BLK_DEV=y
# CONFIG_PARIDE is not set
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_CPQ_CISS_DA is not set
@@ -317,13 +330,14 @@ CONFIG_BLK_DEV_CRYPTOLOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=6144
-CONFIG_BLK_DEV_INITRD=y
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+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_IDE=y
CONFIG_BLK_DEV_IDE=y
@@ -334,24 +348,32 @@ CONFIG_BLK_DEV_IDE=y
CONFIG_BLK_DEV_IDEDISK=y
CONFIG_IDEDISK_MULTI_MODE=y
CONFIG_BLK_DEV_IDECS=y
+# CONFIG_BLK_DEV_DELKIN is not set
CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
CONFIG_BLK_DEV_IDESCSI=y
# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
#
# IDE chipset support/bugfixes
#
CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_PLATFORM is not set
+
+#
+# PCI IDE chipsets support
+#
CONFIG_BLK_DEV_IDEPCI=y
CONFIG_IDEPCI_SHARE_IRQ=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_IDEDMA_FORCED is not set
-# CONFIG_IDEDMA_PCI_AUTO is not set
+CONFIG_IDEDMA_ONLYDISK=y
# CONFIG_BLK_DEV_AEC62XX is not set
# CONFIG_BLK_DEV_ALI15X3 is not set
# CONFIG_BLK_DEV_AMD74XX is not set
@@ -362,8 +384,10 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_CS5530 is not set
# CONFIG_BLK_DEV_HPT34X 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 is not set
+# CONFIG_BLK_DEV_IT8213 is not set
# CONFIG_BLK_DEV_IT821X is not set
CONFIG_BLK_DEV_NS87415=y
# CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -373,10 +397,10 @@ CONFIG_BLK_DEV_NS87415=y
# 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_IDE_ARM is not set
CONFIG_BLK_DEV_IDEDMA=y
# CONFIG_IDEDMA_IVB is not set
-# CONFIG_IDEDMA_AUTO is not set
# CONFIG_BLK_DEV_HD is not set
#
@@ -384,6 +408,9 @@ CONFIG_BLK_DEV_IDEDMA=y
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
CONFIG_SCSI_PROC_FS=y
#
@@ -403,18 +430,17 @@ CONFIG_CHR_DEV_SG=y
# 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 Transport Attributes
+# SCSI Transports
#
CONFIG_SCSI_SPI_ATTRS=y
# CONFIG_SCSI_FC_ATTRS is not set
# CONFIG_SCSI_ISCSI_ATTRS is not set
-# CONFIG_SCSI_SAS_ATTRS is not set
-
-#
-# SCSI low-level drivers
-#
+# CONFIG_SCSI_SAS_LIBSAS is not set
+CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
@@ -424,11 +450,13 @@ CONFIG_SCSI_SPI_ATTRS=y
# 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_ARCMSR is not set
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
-# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_IPS is not set
@@ -438,55 +466,45 @@ CONFIG_SCSI_SPI_ATTRS=y
# CONFIG_SCSI_IMM is not set
CONFIG_SCSI_LASI700=y
CONFIG_53C700_LE_ON_BE=y
+# 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_IPR is not set
CONFIG_SCSI_ZALON=y
CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
CONFIG_SCSI_NCR53C8XX_SYNC=20
-# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
# CONFIG_SCSI_LPFC is not set
# CONFIG_SCSI_SIM710 is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
-
-#
-# PCMCIA SCSI adapter support
-#
-# CONFIG_PCMCIA_AHA152X is not set
-# CONFIG_PCMCIA_FDOMAIN is not set
-# CONFIG_PCMCIA_NINJA_SCSI is not set
-# CONFIG_PCMCIA_QLOGIC is not set
-# CONFIG_PCMCIA_SYM53C500 is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
+# CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set
+# CONFIG_ATA is not set
CONFIG_MD=y
CONFIG_BLK_DEV_MD=y
CONFIG_MD_LINEAR=y
CONFIG_MD_RAID0=y
CONFIG_MD_RAID1=y
CONFIG_MD_RAID10=y
-CONFIG_MD_RAID5=y
-CONFIG_MD_RAID6=y
+# CONFIG_MD_RAID456 is not set
# CONFIG_MD_MULTIPATH is not set
# CONFIG_MD_FAULTY is not set
CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_DEBUG is not set
# CONFIG_DM_CRYPT is not set
# CONFIG_DM_SNAPSHOT is not set
# CONFIG_DM_MIRROR is not set
# CONFIG_DM_ZERO is not set
# CONFIG_DM_MULTIPATH is not set
+# CONFIG_DM_DELAY is not set
#
# Fusion MPT device support
@@ -499,35 +517,20 @@ CONFIG_BLK_DEV_DM=y
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
# CONFIG_I2O is not set
-
-#
-# Network device support
-#
CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
CONFIG_DUMMY=m
CONFIG_BONDING=m
+# CONFIG_MACVLAN is not set
# CONFIG_EQUALIZER is not set
CONFIG_TUN=m
-
-#
-# ARCnet devices
-#
+# CONFIG_VETH is not set
+# CONFIG_IP1000 is not set
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
# CONFIG_PHYLIB is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
CONFIG_NET_ETHERNET=y
CONFIG_MII=m
CONFIG_LASI_82596=y
@@ -536,10 +539,6 @@ CONFIG_LASI_82596=y
# CONFIG_CASSINI is not set
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_NET_VENDOR_SMC is not set
-
-#
-# Tulip family network device support
-#
CONFIG_NET_TULIP=y
# CONFIG_DE2104X is not set
CONFIG_TULIP=y
@@ -554,6 +553,10 @@ CONFIG_TULIP=y
# CONFIG_PCMCIA_XIRTULIP is not set
# CONFIG_DEPCA 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_NET_PCI=y
# CONFIG_PCNET32 is not set
# CONFIG_AMD8111_ETH is not set
@@ -561,7 +564,6 @@ CONFIG_NET_PCI=y
# CONFIG_AC3200 is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
-# CONFIG_DGRS is not set
# CONFIG_EEPRO100 is not set
# CONFIG_E100 is not set
# CONFIG_LNE390 is not set
@@ -577,15 +579,14 @@ CONFIG_NET_PCI=y
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
+# CONFIG_SC92031 is not set
# CONFIG_NET_POCKET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
CONFIG_ACENIC=y
# CONFIG_ACENIC_OMIT_TIGON_I is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
@@ -597,64 +598,36 @@ CONFIG_ACENIC=y
# CONFIG_VIA_VELOCITY is not set
CONFIG_TIGON3=y
# CONFIG_BNX2 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_IXGBE is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+# CONFIG_NIU is not set
+# CONFIG_MLX4_CORE is not set
+# CONFIG_TEHUTI is not set
# CONFIG_TR is not set
#
-# Wireless LAN (non-hamradio)
-#
-CONFIG_NET_RADIO=y
-
-#
-# Obsolete Wireless cards support (pre-802.11)
-#
-# CONFIG_STRIP is not set
-# CONFIG_PCMCIA_WAVELAN is not set
-# CONFIG_PCMCIA_NETWAVE is not set
-
-#
-# Wireless 802.11 Frequency Hopping cards support
-#
-# CONFIG_PCMCIA_RAYCS is not set
-
-#
-# Wireless 802.11b ISA/PCI cards support
-#
-CONFIG_HERMES=y
-# CONFIG_PLX_HERMES is not set
-# CONFIG_TMD_HERMES is not set
-# CONFIG_NORTEL_HERMES is not set
-# CONFIG_PCI_HERMES is not set
-# CONFIG_ATMEL is not set
-
-#
-# Wireless 802.11b Pcmcia/Cardbus cards support
+# Wireless LAN
#
-CONFIG_PCMCIA_HERMES=y
-CONFIG_PCMCIA_SPECTRUM=y
-# CONFIG_AIRO_CS is not set
-# CONFIG_PCMCIA_WL3501 is not set
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
#
-# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
-#
-# CONFIG_PRISM54 is not set
-# CONFIG_HOSTAP is not set
-CONFIG_NET_WIRELESS=y
-
-#
-# PCMCIA network device support
+# 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_MII is not set
+# CONFIG_USB_USBNET is not set
CONFIG_NET_PCMCIA=y
# CONFIG_PCMCIA_3C589 is not set
# CONFIG_PCMCIA_3C574 is not set
@@ -664,10 +637,6 @@ CONFIG_NET_PCMCIA=y
# CONFIG_PCMCIA_SMC91C92 is not set
# CONFIG_PCMCIA_XIRC2PS is not set
# CONFIG_PCMCIA_AXNET is not set
-
-#
-# Wan interfaces
-#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -681,27 +650,23 @@ CONFIG_PPP_DEFLATE=m
CONFIG_PPP_BSDCOMP=m
# CONFIG_PPP_MPPE is not set
CONFIG_PPPOE=m
+# CONFIG_PPPOL2TP is not set
# CONFIG_SLIP is not set
+CONFIG_SLHC=m
# CONFIG_NET_FC is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
# 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
@@ -726,14 +691,23 @@ CONFIG_KEYBOARD_ATKBD_HP_KEYCODES=y
# 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_KEYBOARD_HIL_OLD is not set
CONFIG_KEYBOARD_HIL=y
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_TOUCHKIT is not set
CONFIG_MOUSE_SERIAL=y
+# CONFIG_MOUSE_APPLETOUCH is not set
# CONFIG_MOUSE_VSXXXAA is not set
CONFIG_MOUSE_HIL=y
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
@@ -757,6 +731,7 @@ CONFIG_SERIO_LIBPS2=y
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
# CONFIG_SERIAL_NONSTANDARD is not set
#
@@ -764,6 +739,8 @@ CONFIG_HW_CONSOLE=y
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_GSC=y
+CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_CS=y
CONFIG_SERIAL_8250_NR_UARTS=17
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
@@ -788,25 +765,14 @@ CONFIG_PRINTER=m
# CONFIG_LP_CONSOLE is not set
CONFIG_PPDEV=m
# CONFIG_TIPAR is not set
-
-#
-# IPMI
-#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
CONFIG_GEN_RTC=y
CONFIG_GEN_RTC_X=y
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
+# CONFIG_AGP is not set
# CONFIG_DRM is not set
#
@@ -816,16 +782,8 @@ CONFIG_GEN_RTC_X=y
# CONFIG_CARDMAN_4000 is not set
# CONFIG_CARDMAN_4040 is not set
# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
# CONFIG_I2C is not set
#
@@ -833,46 +791,59 @@ CONFIG_GEN_RTC_X=y
#
# CONFIG_SPI is not set
# CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
+# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
#
-# Misc devices
+# Sonics Silicon Backplane
#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
#
-# Multimedia Capabilities Port drivers
+# Multifunction device drivers
#
+# CONFIG_MFD_SM501 is not set
#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
CONFIG_FB_MODE_HELPERS=y
CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
# CONFIG_FB_CIRRUS is not set
# CONFIG_FB_PM2 is not set
# CONFIG_FB_CYBER2000 is not set
@@ -883,17 +854,20 @@ CONFIG_FB_STI=y
# CONFIG_FB_NVIDIA is not set
# CONFIG_FB_RIVA is not set
# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
# CONFIG_FB_RADEON is not set
# CONFIG_FB_ATY128 is not set
# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
# CONFIG_FB_SAVAGE is not set
# CONFIG_FB_SIS is not set
# CONFIG_FB_NEOMAGIC is not set
# CONFIG_FB_KYRO is not set
# CONFIG_FB_3DFX is not set
# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
# CONFIG_FB_VIRTUAL is not set
#
@@ -903,6 +877,7 @@ CONFIG_DUMMY_CONSOLE=y
CONFIG_DUMMY_CONSOLE_COLUMNS=128
CONFIG_DUMMY_CONSOLE_ROWS=48
CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
CONFIG_STI_CONSOLE=y
CONFIG_FONTS=y
@@ -916,16 +891,11 @@ CONFIG_FONT_8x16=y
# CONFIG_FONT_SUN8x16 is not set
# CONFIG_FONT_SUN12x22 is not set
# CONFIG_FONT_10x18 is not set
-
-#
-# Logo configuration
-#
CONFIG_LOGO=y
# CONFIG_LOGO_LINUX_MONO is not set
# CONFIG_LOGO_LINUX_VGA16 is not set
# CONFIG_LOGO_LINUX_CLUT224 is not set
CONFIG_LOGO_PARISC_CLUT224=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -938,35 +908,36 @@ CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_TIMER=y
CONFIG_SND_PCM=y
-CONFIG_SND_HWDEP=y
CONFIG_SND_SEQUENCER=y
# CONFIG_SND_SEQ_DUMMY is not set
CONFIG_SND_OSSEMUL=y
CONFIG_SND_MIXER_OSS=y
CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
CONFIG_SND_SEQUENCER_OSS=y
CONFIG_SND_DYNAMIC_MINORS=y
CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
# CONFIG_SND_VERBOSE_PRINTK is not set
# CONFIG_SND_DEBUG is not set
#
# Generic devices
#
-CONFIG_SND_OPL3_LIB=y
CONFIG_SND_AC97_CODEC=y
-CONFIG_SND_AC97_BUS=y
# CONFIG_SND_DUMMY is not set
# CONFIG_SND_VIRMIDI is not set
# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_MTS64 is not set
# CONFIG_SND_SERIAL_U16550 is not set
# CONFIG_SND_MPU401 is not set
+# CONFIG_SND_PORTMAN2X4 is not set
#
# PCI devices
#
CONFIG_SND_AD1889=y
-CONFIG_SND_AD1889_OPL3=y
+# CONFIG_SND_ALS300 is not set
# CONFIG_SND_ALI5451 is not set
# CONFIG_SND_ATIIXP is not set
# CONFIG_SND_ATIIXP_MODEM is not set
@@ -979,6 +950,18 @@ CONFIG_SND_AD1889_OPL3=y
# CONFIG_SND_CMIPCI is not set
# CONFIG_SND_CS4281 is not set
# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_DARLA20 is not set
+# CONFIG_SND_GINA20 is not set
+# CONFIG_SND_LAYLA20 is not set
+# CONFIG_SND_DARLA24 is not set
+# CONFIG_SND_GINA24 is not set
+# CONFIG_SND_LAYLA24 is not set
+# CONFIG_SND_MONA is not set
+# CONFIG_SND_MIA is not set
+# CONFIG_SND_ECHO3G is not set
+# CONFIG_SND_INDIGO is not set
+# CONFIG_SND_INDIGOIO is not set
+# CONFIG_SND_INDIGODJ is not set
# CONFIG_SND_EMU10K1 is not set
# CONFIG_SND_EMU10K1X is not set
# CONFIG_SND_ENS1370 is not set
@@ -998,6 +981,7 @@ CONFIG_SND_AD1889_OPL3=y
# CONFIG_SND_MIXART is not set
# CONFIG_SND_NM256 is not set
# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
# CONFIG_SND_RME32 is not set
# CONFIG_SND_RME96 is not set
# CONFIG_SND_RME9652 is not set
@@ -1007,15 +991,19 @@ CONFIG_SND_AD1889_OPL3=y
# CONFIG_SND_VIA82XX_MODEM is not set
# CONFIG_SND_VX222 is not set
# CONFIG_SND_YMFPCI is not set
+# CONFIG_SND_AC97_POWER_SAVE is not set
#
# USB devices
#
# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_CAIAQ is not set
#
# PCMCIA devices
#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
#
# GSC devices
@@ -1023,15 +1011,34 @@ CONFIG_SND_AD1889_OPL3=y
CONFIG_SND_HARMONY=y
#
+# System on Chip audio support
+#
+# CONFIG_SND_SOC is not set
+
+#
+# SoC Audio support for SuperH
+#
+
+#
# Open Sound System
#
# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=y
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+CONFIG_HID_DEBUG=y
#
-# USB support
+# USB Input Devices
#
+CONFIG_USB_HID=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV 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
@@ -1039,7 +1046,7 @@ CONFIG_USB=y
# Miscellaneous USB options
#
CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
+CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
# CONFIG_USB_OTG is not set
@@ -1049,15 +1056,16 @@ CONFIG_USB_DEVICEFS=y
# CONFIG_USB_EHCI_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+# 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
#
# USB Device Class drivers
#
-# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
# CONFIG_USB_ACM is not set
# CONFIG_USB_PRINTER is not set
@@ -1072,52 +1080,10 @@ CONFIG_USB_UHCI_HCD=y
# CONFIG_USB_LIBUSUAL is not set
#
-# USB Input Devices
-#
-CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
-# CONFIG_USB_HIDDEV is not set
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
-# CONFIG_USB_YEALINK is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_ATI_REMOTE2 is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-# CONFIG_USB_APPLETOUCH is not set
-
-#
# USB Imaging devices
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-
-#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
-# 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_USB_ZD1201 is not set
CONFIG_USB_MON=y
#
@@ -1135,16 +1101,22 @@ CONFIG_USB_MON=y
#
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
# CONFIG_USB_AUERSWALD 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_PHIDGETKIT is not set
-# CONFIG_USB_PHIDGETSERVO 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_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
#
@@ -1155,20 +1127,29 @@ CONFIG_USB_MON=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_INFINIBAND is not set
+# CONFIG_RTC_CLASS is not set
#
-# MMC/SD Card support
+# DMA Engine support
#
-# CONFIG_MMC is not set
+# CONFIG_DMA_ENGINE is not set
#
-# InfiniBand support
+# DMA Clients
#
-# CONFIG_INFINIBAND is not set
#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+# DMA Devices
+#
+# CONFIG_AUXDISPLAY is not set
+
+#
+# Userspace I/O
#
+# CONFIG_UIO is not set
#
# File systems
@@ -1178,16 +1159,19 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4DEV_FS is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
CONFIG_AUTOFS_FS=y
@@ -1217,11 +1201,12 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
# CONFIG_CONFIGFS_FS is not set
#
@@ -1229,6 +1214,7 @@ CONFIG_RAMFS=y
#
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
# CONFIG_HFS_FS is not set
# CONFIG_HFSPLUS_FS is not set
# CONFIG_BEFS_FS is not set
@@ -1261,6 +1247,7 @@ CONFIG_EXPORTFS=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
CONFIG_RPCSEC_GSS_KRB5=y
CONFIG_RPCSEC_GSS_SPKM3=m
CONFIG_SMB_FS=m
@@ -1268,12 +1255,13 @@ 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
-# CONFIG_9P_FS is not set
#
# Partition Types
@@ -1326,6 +1314,11 @@ CONFIG_NLS_KOI8_U=m
CONFIG_NLS_UTF8=y
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Profiling support
#
CONFIG_PROFILING=y
@@ -1335,21 +1328,32 @@ CONFIG_OPROFILE=m
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+CONFIG_HEADERS_CHECK=y
CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
# CONFIG_DEBUG_SLAB is not set
-CONFIG_DEBUG_MUTEXES=y
+# 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_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
# CONFIG_DEBUG_RODATA is not set
#
@@ -1358,12 +1362,13 @@ CONFIG_FORCED_INLINING=y
CONFIG_KEYS=y
CONFIG_KEYS_DEBUG_PROC_KEYS=y
# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_MD4=m
CONFIG_CRYPTO_MD5=y
@@ -1372,9 +1377,18 @@ CONFIG_CRYPTO_SHA256=m
CONFIG_CRYPTO_SHA512=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_TGR192=m
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_ECB is not set
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_AES=m
CONFIG_CRYPTO_CAST5=m
@@ -1383,21 +1397,28 @@ CONFIG_CRYPTO_TEA=m
CONFIG_CRYPTO_ARC4=m
CONFIG_CRYPTO_KHAZAD=m
CONFIG_CRYPTO_ANUBIS=m
+# CONFIG_CRYPTO_SEED is not set
CONFIG_CRYPTO_DEFLATE=y
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_CAMELLIA is not set
CONFIG_CRYPTO_TEST=m
-
-#
-# Hardware crypto devices
-#
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_HW is not set
#
# Library routines
#
+CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
CONFIG_LIBCRC32C=m
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/parisc/hpux/gate.S b/arch/parisc/hpux/gate.S
index 0b9d5b1e4b37..38a1c1b8d4e8 100644
--- a/arch/parisc/hpux/gate.S
+++ b/arch/parisc/hpux/gate.S
@@ -20,7 +20,7 @@
.import hpux_call_table
.import hpux_syscall_exit,code
- .align 4096
+ .align PAGE_SIZE
ENTRY(hpux_gateway_page)
nop
#ifdef CONFIG_64BIT
@@ -103,5 +103,5 @@ syscall_nosys:
ldo -ENOSYS(%r0),%r28
ENDPROC(hpux_gateway_page)
- .align 4096
+ .align PAGE_SIZE
ENTRY(end_hpux_gateway_page)
diff --git a/arch/parisc/kernel/asm-offsets.c b/arch/parisc/kernel/asm-offsets.c
index d3b7917a87cb..eaa79bc14d94 100644
--- a/arch/parisc/kernel/asm-offsets.c
+++ b/arch/parisc/kernel/asm-offsets.c
@@ -290,9 +290,6 @@ int main(void)
DEFINE(ASM_PTE_ENTRY_SIZE, PTE_ENTRY_SIZE);
DEFINE(ASM_PFN_PTE_SHIFT, PFN_PTE_SHIFT);
DEFINE(ASM_PT_INITIAL, PT_INITIAL);
- DEFINE(ASM_PAGE_SIZE, PAGE_SIZE);
- DEFINE(ASM_PAGE_SIZE_DIV64, PAGE_SIZE/64);
- DEFINE(ASM_PAGE_SIZE_DIV128, PAGE_SIZE/128);
BLANK();
DEFINE(EXCDATA_IP, offsetof(struct exception_data, fault_ip));
DEFINE(EXCDATA_SPACE, offsetof(struct exception_data, fault_space));
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index 42598abf4576..111d47284eac 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -98,7 +98,6 @@
* The "get_stack" macros are responsible for determining the
* kernel stack value.
*
- * For Faults:
* If sr7 == 0
* Already using a kernel stack, so call the
* get_stack_use_r30 macro to push a pt_regs structure
@@ -110,26 +109,6 @@
* task pointer pointed to by cr30. Set the stack
* pointer to point to the end of the task structure.
*
- * For Interrupts:
- * If sr7 == 0
- * Already using a kernel stack, check to see if r30
- * is already pointing to the per processor interrupt
- * stack. If it is, call the get_stack_use_r30 macro
- * to push a pt_regs structure on the stack, and store
- * registers there. Otherwise, call get_stack_use_cr31
- * to get a pointer to the base of the interrupt stack
- * and push a pt_regs structure on that stack.
- * else
- * Need to set up a kernel stack, so call the
- * get_stack_use_cr30 macro to set up a pointer
- * to the pt_regs structure contained within the
- * task pointer pointed to by cr30. Set the stack
- * pointer to point to the end of the task structure.
- * N.B: We don't use the interrupt stack for the
- * first interrupt from userland, because signals/
- * resched's are processed when returning to userland,
- * and we can sleep in those cases.
- *
* Note that we use shadowed registers for temps until
* we can save %r26 and %r29. %r26 is used to preserve
* %r8 (a shadowed register) which temporarily contained
@@ -652,7 +631,7 @@
.text
- .align 4096
+ .align PAGE_SIZE
ENTRY(fault_vector_20)
/* First vector is invalid (0) */
@@ -904,7 +883,7 @@ ENDPROC(_switch_to)
*
*/
- .align 4096
+ .align PAGE_SIZE
ENTRY(syscall_exit_rfi)
mfctl %cr30,%r16
@@ -1086,23 +1065,13 @@ intr_do_preempt:
intr_extint:
CMPIB=,n 0,%r16,1f
+
get_stack_use_cr30
- b,n 3f
+ b,n 2f
1:
-#if 0 /* Interrupt Stack support not working yet! */
- mfctl %cr31,%r1
- copy %r30,%r17
- /* FIXME! depi below has hardcoded idea of interrupt stack size (32k)*/
- DEPI 0,31,15,%r17
- CMPB=,n %r1,%r17,2f
- get_stack_use_cr31
- b,n 3f
-#endif
-2:
get_stack_use_r30
-
-3:
+2:
save_specials %r29
virt_map
save_general %r29
diff --git a/arch/parisc/kernel/head.S b/arch/parisc/kernel/head.S
index 9676c486bb63..a7b8859488bb 100644
--- a/arch/parisc/kernel/head.S
+++ b/arch/parisc/kernel/head.S
@@ -95,7 +95,7 @@ $bss_loop:
1:
stw %r3,0(%r4)
- ldo (ASM_PAGE_SIZE >> PxD_VALUE_SHIFT)(%r3),%r3
+ ldo (PAGE_SIZE >> PxD_VALUE_SHIFT)(%r3),%r3
addib,> -1,%r1,1b
#if PT_NLEVELS == 3
ldo ASM_PMD_ENTRY_SIZE(%r4),%r4
@@ -128,10 +128,6 @@ $pgt_fill_loop:
/* And the stack pointer too */
ldo THREAD_SZ_ALGN(%r6),%sp
- /* And the interrupt stack */
- load32 interrupt_stack,%r6
- mtctl %r6,%cr31
-
#ifdef CONFIG_SMP
/* Set the smp rendevous address into page zero.
** It would be safer to do this in init_smp_config() but
diff --git a/arch/parisc/kernel/hpmc.S b/arch/parisc/kernel/hpmc.S
index 43b41df0b541..2cbf13b3ef11 100644
--- a/arch/parisc/kernel/hpmc.S
+++ b/arch/parisc/kernel/hpmc.S
@@ -55,13 +55,13 @@
* IODC requires 7K byte stack. That leaves 1K byte for os_hpmc.
*/
- .align 4096
+ .align PAGE_SIZE
hpmc_stack:
.block 16384
#define HPMC_IODC_BUF_SIZE 0x8000
- .align 4096
+ .align PAGE_SIZE
hpmc_iodc_buf:
.block HPMC_IODC_BUF_SIZE
diff --git a/arch/parisc/kernel/init_task.c b/arch/parisc/kernel/init_task.c
index 446f98d3fd7b..26198a074d67 100644
--- a/arch/parisc/kernel/init_task.c
+++ b/arch/parisc/kernel/init_task.c
@@ -49,7 +49,6 @@ EXPORT_SYMBOL(init_mm);
* way process stacks are handled. This is done by having a special
* "init_task" linker map entry..
*/
-unsigned char interrupt_stack[ISTACK_SIZE] __attribute__ ((section("init_istack"), aligned(4096)));
union thread_union init_thread_union
__attribute__((aligned(128))) __attribute__((__section__(".data.init_task"))) =
{ INIT_THREAD_INFO(init_task) };
diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S
index 90b240878520..5901092e0196 100644
--- a/arch/parisc/kernel/pacache.S
+++ b/arch/parisc/kernel/pacache.S
@@ -289,7 +289,7 @@ ENTRY(copy_user_page_asm)
*/
ldd 0(%r25), %r19
- ldi ASM_PAGE_SIZE_DIV128, %r1
+ ldi (PAGE_SIZE / 128), %r1
ldw 64(%r25), %r0 /* prefetch 1 cacheline ahead */
ldw 128(%r25), %r0 /* prefetch 2 */
@@ -355,7 +355,7 @@ ENTRY(copy_user_page_asm)
* use ldd/std on a 32 bit kernel.
*/
ldw 0(%r25), %r19
- ldi ASM_PAGE_SIZE_DIV64, %r1
+ ldi (PAGE_SIZE / 64), %r1
1:
ldw 4(%r25), %r20
@@ -553,7 +553,7 @@ ENTRY(__clear_user_page_asm)
pdtlb 0(%r28)
#ifdef CONFIG_64BIT
- ldi ASM_PAGE_SIZE_DIV128, %r1
+ ldi (PAGE_SIZE / 128), %r1
/* PREFETCH (Write) has not (yet) been proven to help here */
/* #define PREFETCHW_OP ldd 256(%0), %r0 */
@@ -578,7 +578,7 @@ ENTRY(__clear_user_page_asm)
ldo 128(%r28), %r28
#else /* ! CONFIG_64BIT */
- ldi ASM_PAGE_SIZE_DIV64, %r1
+ ldi (PAGE_SIZE / 64), %r1
1:
stw %r0, 0(%r28)
diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c
index 7aca704e96f0..671ee5b9950c 100644
--- a/arch/parisc/kernel/parisc_ksyms.c
+++ b/arch/parisc/kernel/parisc_ksyms.c
@@ -122,31 +122,9 @@ EXPORT_SYMBOL($$divI_12);
EXPORT_SYMBOL($$divI_14);
EXPORT_SYMBOL($$divI_15);
-extern void __ashrdi3(void);
-extern void __ashldi3(void);
-extern void __lshrdi3(void);
-extern void __muldi3(void);
-
-EXPORT_SYMBOL(__ashrdi3);
-EXPORT_SYMBOL(__ashldi3);
-EXPORT_SYMBOL(__lshrdi3);
-EXPORT_SYMBOL(__muldi3);
-
asmlinkage void * __canonicalize_funcptr_for_compare(void *);
EXPORT_SYMBOL(__canonicalize_funcptr_for_compare);
-#ifdef CONFIG_64BIT
-extern void __divdi3(void);
-extern void __udivdi3(void);
-extern void __umoddi3(void);
-extern void __moddi3(void);
-
-EXPORT_SYMBOL(__divdi3);
-EXPORT_SYMBOL(__udivdi3);
-EXPORT_SYMBOL(__umoddi3);
-EXPORT_SYMBOL(__moddi3);
-#endif
-
#ifndef CONFIG_64BIT
extern void $$dyncall(void);
EXPORT_SYMBOL($$dyncall);
diff --git a/arch/parisc/kernel/pci-dma.c b/arch/parisc/kernel/pci-dma.c
index 23c1388df1f5..9448d4e91142 100644
--- a/arch/parisc/kernel/pci-dma.c
+++ b/arch/parisc/kernel/pci-dma.c
@@ -25,6 +25,7 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/types.h>
+#include <linux/scatterlist.h>
#include <asm/cacheflush.h>
#include <asm/dma.h> /* for DMA_CHUNK_SIZE */
@@ -569,11 +570,10 @@ static void *fail_alloc_consistent(struct device *dev, size_t size,
static void *pa11_dma_alloc_noncoherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag)
{
- void *addr = NULL;
+ void *addr;
- /* rely on kmalloc to be cacheline aligned */
- addr = kmalloc(size, flag);
- if(addr)
+ addr = (void *)__get_free_pages(flag, get_order(size));
+ if (addr)
*dma_handle = (dma_addr_t)virt_to_phys(addr);
return addr;
@@ -582,7 +582,7 @@ static void *pa11_dma_alloc_noncoherent(struct device *dev, size_t size,
static void pa11_dma_free_noncoherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t iova)
{
- kfree(vaddr);
+ free_pages((unsigned long)vaddr, get_order(size));
return;
}
diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c
index 563df0072dee..507d0ac99f66 100644
--- a/arch/parisc/kernel/pci.c
+++ b/arch/parisc/kernel/pci.c
@@ -194,37 +194,13 @@ void __init pcibios_init_bus(struct pci_bus *bus)
pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bridge_ctl);
}
-
-/* KLUGE: Link the child and parent resources - generic PCI didn't */
-static void
-pcibios_link_hba_resources( struct resource *hba_res, struct resource *r)
-{
- if (!r->parent) {
- printk(KERN_EMERG "PCI: resource not parented! [%p-%p]\n",
- (void*) r->start, (void*) r->end);
- r->parent = hba_res;
-
- /* reverse link is harder *sigh* */
- if (r->parent->child) {
- if (r->parent->sibling) {
- struct resource *next = r->parent->sibling;
- while (next->sibling)
- next = next->sibling;
- next->sibling = r;
- } else {
- r->parent->sibling = r;
- }
- } else
- r->parent->child = r;
- }
-}
-
/* called by drivers/pci/setup-bus.c:pci_setup_bridge(). */
void __devinit pcibios_resource_to_bus(struct pci_dev *dev,
struct pci_bus_region *region, struct resource *res)
{
- struct pci_bus *bus = dev->bus;
- struct pci_hba_data *hba = HBA_DATA(bus->bridge->platform_data);
+#ifdef CONFIG_64BIT
+ struct pci_hba_data *hba = HBA_DATA(dev->bus->bridge->platform_data);
+#endif
if (res->flags & IORESOURCE_IO) {
/*
@@ -243,23 +219,15 @@ void __devinit pcibios_resource_to_bus(struct pci_dev *dev,
}
DBG_RES("pcibios_resource_to_bus(%02x %s [%lx,%lx])\n",
- bus->number, res->flags & IORESOURCE_IO ? "IO" : "MEM",
+ dev->bus->number, res->flags & IORESOURCE_IO ? "IO" : "MEM",
region->start, region->end);
-
- /* KLUGE ALERT
- ** if this resource isn't linked to a "parent", then it seems
- ** to be a child of the HBA - lets link it in.
- */
- pcibios_link_hba_resources(&hba->io_space, bus->resource[0]);
- pcibios_link_hba_resources(&hba->lmmio_space, bus->resource[1]);
}
void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
struct pci_bus_region *region)
{
#ifdef CONFIG_64BIT
- struct pci_bus *bus = dev->bus;
- struct pci_hba_data *hba = HBA_DATA(bus->bridge->platform_data);
+ struct pci_hba_data *hba = HBA_DATA(dev->bus->bridge->platform_data);
#endif
if (res->flags & IORESOURCE_MEM) {
diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c
index 549f5484342c..370086fb8333 100644
--- a/arch/parisc/kernel/processor.c
+++ b/arch/parisc/kernel/processor.c
@@ -82,7 +82,12 @@ static int __cpuinit processor_probe(struct parisc_device *dev)
unsigned long cpuid;
struct cpuinfo_parisc *p;
-#ifndef CONFIG_SMP
+#ifdef CONFIG_SMP
+ if (num_online_cpus() >= NR_CPUS) {
+ printk(KERN_INFO "num_online_cpus() >= NR_CPUS\n");
+ return 1;
+ }
+#else
if (boot_cpu_data.cpu_count > 0) {
printk(KERN_INFO "CONFIG_SMP=n ignoring additional CPUs\n");
return 1;
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
index 26ec774c5027..49c637970789 100644
--- a/arch/parisc/kernel/ptrace.c
+++ b/arch/parisc/kernel/ptrace.c
@@ -329,10 +329,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
/* give it a chance to run. */
goto out_wake;
- case PTRACE_DETACH:
- ret = ptrace_detach(child, data);
- goto out_tsk;
-
case PTRACE_GETEVENTMSG:
ret = put_user(child->ptrace_message, (unsigned int __user *) data);
goto out_tsk;
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c
index fb35ebc0c4da..2ce3806f02e1 100644
--- a/arch/parisc/kernel/signal.c
+++ b/arch/parisc/kernel/signal.c
@@ -181,7 +181,7 @@ give_sigsegv:
si.si_signo = SIGSEGV;
si.si_errno = 0;
si.si_code = SI_KERNEL;
- si.si_pid = current->pid;
+ si.si_pid = task_pid_vnr(current);
si.si_uid = current->uid;
si.si_addr = &frame->uc;
force_sig_info(SIGSEGV, &si, current);
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c
index d7bc7bb42c94..85fc7754ec25 100644
--- a/arch/parisc/kernel/smp.c
+++ b/arch/parisc/kernel/smp.c
@@ -432,22 +432,10 @@ smp_cpu_init(int cpunum)
void __init smp_callin(void)
{
int slave_id = cpu_now_booting;
-#if 0
- void *istack;
-#endif
smp_cpu_init(slave_id);
preempt_disable();
-#if 0 /* NOT WORKING YET - see entry.S */
- istack = (void *)__get_free_pages(GFP_KERNEL,ISTACK_ORDER);
- if (istack == NULL) {
- printk(KERN_CRIT "Failed to allocate interrupt stack for cpu %d\n",slave_id);
- BUG();
- }
- mtctl(istack,31);
-#endif
-
flush_cache_all_local(); /* start with known state */
flush_tlb_all_local(NULL);
diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c
index 2989c6682bf6..50bbf33ee00c 100644
--- a/arch/parisc/kernel/sys_parisc32.c
+++ b/arch/parisc/kernel/sys_parisc32.c
@@ -473,3 +473,10 @@ long sys32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char __user *buf,
return sys_lookup_dcookie((u64)cookie_high << 32 | cookie_low,
buf, len);
}
+
+asmlinkage long compat_sys_fallocate(int fd, int mode, u32 offhi, u32 offlo,
+ u32 lenhi, u32 lenlo)
+{
+ return sys_fallocate(fd, mode, ((loff_t)offhi << 32) | offlo,
+ ((loff_t)lenhi << 32) | lenlo);
+}
diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S
index 56f6231cb863..69b6eebc466e 100644
--- a/arch/parisc/kernel/syscall.S
+++ b/arch/parisc/kernel/syscall.S
@@ -10,6 +10,7 @@
#include <asm/asm-offsets.h>
#include <asm/unistd.h>
#include <asm/errno.h>
+#include <asm/page.h>
#include <asm/psw.h>
#include <asm/thread_info.h>
#include <asm/assembly.h>
@@ -38,7 +39,7 @@
* pointers.
*/
- .align ASM_PAGE_SIZE
+ .align PAGE_SIZE
ENTRY(linux_gateway_page)
/* ADDRESS 0x00 to 0xb0 = 176 bytes / 4 bytes per insn = 44 insns */
@@ -597,7 +598,7 @@ cas_action:
/* Make sure nothing else is placed on this page */
- .align ASM_PAGE_SIZE
+ .align PAGE_SIZE
END(linux_gateway_page)
ENTRY(end_linux_gateway_page)
@@ -608,7 +609,7 @@ ENTRY(end_linux_gateway_page)
.section .rodata,"a"
- .align ASM_PAGE_SIZE
+ .align PAGE_SIZE
/* Light-weight-syscall table */
/* Start of lws table. */
ENTRY(lws_table)
@@ -617,13 +618,13 @@ ENTRY(lws_table)
END(lws_table)
/* End of lws table */
- .align ASM_PAGE_SIZE
+ .align PAGE_SIZE
ENTRY(sys_call_table)
#include "syscall_table.S"
END(sys_call_table)
#ifdef CONFIG_64BIT
- .align ASM_PAGE_SIZE
+ .align PAGE_SIZE
ENTRY(sys_call_table64)
#define SYSCALL_TABLE_64BIT
#include "syscall_table.S"
@@ -636,7 +637,7 @@ END(sys_call_table64)
will use this set of locks
*/
.section .data
- .align 4096
+ .align PAGE_SIZE
ENTRY(lws_lock_start)
/* lws locks */
.align 16
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
index 2540786a970f..117438e9eb2a 100644
--- a/arch/parisc/kernel/syscall_table.S
+++ b/arch/parisc/kernel/syscall_table.S
@@ -403,6 +403,7 @@
ENTRY_COMP(signalfd)
ENTRY_COMP(timerfd)
ENTRY_SAME(eventfd)
+ ENTRY_COMP(fallocate) /* 305 */
/* Nothing yet */
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
index 8b3062a5c812..24be86bba94d 100644
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
@@ -189,16 +189,14 @@ static struct clocksource clocksource_cr16 = {
#ifdef CONFIG_SMP
int update_cr16_clocksource(void)
{
- int change = 0;
-
/* since the cr16 cycle counters are not synchronized across CPUs,
we'll check if we should switch to a safe clocksource: */
if (clocksource_cr16.rating != 0 && num_online_cpus() > 1) {
clocksource_change_rating(&clocksource_cr16, 0);
- change = 1;
+ return 1;
}
- return change;
+ return 0;
}
#else
int update_cr16_clocksource(void)
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
index bbf029a184ac..99fd56939afa 100644
--- a/arch/parisc/kernel/traps.c
+++ b/arch/parisc/kernel/traps.c
@@ -219,7 +219,7 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err)
return; /* STFU */
printk(KERN_CRIT "%s (pid %d): %s (code %ld) at " RFMT "\n",
- current->comm, current->pid, str, err, regs->iaoq[0]);
+ current->comm, task_pid_nr(current), str, err, regs->iaoq[0]);
#ifdef PRINT_USER_FAULTS
/* XXX for debugging only */
show_regs(regs);
@@ -252,7 +252,7 @@ KERN_CRIT " || ||\n");
if (err)
printk(KERN_CRIT "%s (pid %d): %s (code %ld)\n",
- current->comm, current->pid, str, err);
+ current->comm, task_pid_nr(current), str, err);
/* Wot's wrong wif bein' racy? */
if (current->thread.flags & PARISC_KERNEL_DEATH) {
@@ -317,7 +317,7 @@ static void handle_break(struct pt_regs *regs)
if (unlikely(iir != GDB_BREAK_INSN)) {
printk(KERN_DEBUG "break %d,%d: pid=%d command='%s'\n",
iir & 31, (iir>>13) & ((1<<13)-1),
- current->pid, current->comm);
+ task_pid_nr(current), current->comm);
show_regs(regs);
}
#endif
@@ -747,7 +747,7 @@ void handle_interruption(int code, struct pt_regs *regs)
if (user_mode(regs)) {
#ifdef PRINT_USER_FAULTS
printk(KERN_DEBUG "\nhandle_interruption() pid=%d command='%s'\n",
- current->pid, current->comm);
+ task_pid_nr(current), current->comm);
show_regs(regs);
#endif
/* SIGBUS, for lack of a better one. */
@@ -772,7 +772,7 @@ void handle_interruption(int code, struct pt_regs *regs)
else
printk(KERN_DEBUG "User Fault (long pointer) (fault %d) ",
code);
- printk("pid=%d command='%s'\n", current->pid, current->comm);
+ printk("pid=%d command='%s'\n", task_pid_nr(current), current->comm);
show_regs(regs);
#endif
si.si_signo = SIGSEGV;
diff --git a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c
index 347bb922e6d0..aebf3c168871 100644
--- a/arch/parisc/kernel/unaligned.c
+++ b/arch/parisc/kernel/unaligned.c
@@ -469,7 +469,7 @@ void handle_unaligned(struct pt_regs *regs)
&& ++unaligned_count < 5) {
char buf[256];
sprintf(buf, "%s(%d): unaligned access to 0x" RFMT " at ip=0x" RFMT "\n",
- current->comm, current->pid, regs->ior, regs->iaoq[0]);
+ current->comm, task_pid_nr(current), regs->ior, regs->iaoq[0]);
printk(KERN_WARNING "%s", buf);
#ifdef DEBUG_UNALIGNED
show_regs(regs);
diff --git a/arch/parisc/kernel/unwind.c b/arch/parisc/kernel/unwind.c
index cf780cb3b916..701b2d2d8882 100644
--- a/arch/parisc/kernel/unwind.c
+++ b/arch/parisc/kernel/unwind.c
@@ -209,8 +209,8 @@ static int unwind_init(void)
static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int frame_size)
{
- void handle_interruption(int, struct pt_regs *);
- static unsigned long *hi = (unsigned long)&handle_interruption;
+ extern void handle_interruption(int, struct pt_regs *);
+ static unsigned long *hi = (unsigned long *)&handle_interruption;
if (pc == get_func_addr(hi)) {
struct pt_regs *regs = (struct pt_regs *)(info->sp - frame_size - PT_SZ_ALGN);
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index ee7a16eb6fdd..40d0ff9b81ab 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -46,168 +46,211 @@ jiffies = jiffies_64;
#endif
SECTIONS
{
+ . = KERNEL_BINARY_TEXT_START;
- . = KERNEL_BINARY_TEXT_START;
-
- _text = .; /* Text and read-only data */
- .text ALIGN(16) : {
- TEXT_TEXT
- SCHED_TEXT
- LOCK_TEXT
- *(.text.do_softirq)
- *(.text.sys_exit)
- *(.text.do_sigaltstack)
- *(.text.do_fork)
- *(.text.*)
- *(.fixup)
- *(.lock.text) /* out-of-line lock text */
- *(.gnu.warning)
+ _text = .; /* Text and read-only data */
+ .text ALIGN(16) : {
+ TEXT_TEXT
+ SCHED_TEXT
+ LOCK_TEXT
+ *(.text.do_softirq)
+ *(.text.sys_exit)
+ *(.text.do_sigaltstack)
+ *(.text.do_fork)
+ *(.text.*)
+ *(.fixup)
+ *(.lock.text) /* out-of-line lock text */
+ *(.gnu.warning)
} = 0
+ /* End of text section */
+ _etext = .;
- _etext = .; /* End of text section */
+ RODATA
+ BUG_TABLE
- RODATA
-
- BUG_TABLE
-
- /* writeable */
- . = ALIGN(ASM_PAGE_SIZE); /* Make sure this is page aligned so
- that we can properly leave these
- as writable */
- data_start = .;
-
- . = ALIGN(16); /* Exception table */
- __start___ex_table = .;
- __ex_table : { *(__ex_table) }
- __stop___ex_table = .;
+ /* writeable */
+ /* Make sure this is page aligned so
+ * that we can properly leave these
+ * as writable
+ */
+ . = ALIGN(PAGE_SIZE);
+ data_start = .;
+ . = ALIGN(16);
+ /* Exception table */
+ __ex_table : {
+ __start___ex_table = .;
+ *(__ex_table)
+ __stop___ex_table = .;
+ }
- NOTES
+ NOTES
- __start___unwind = .; /* unwind info */
- .PARISC.unwind : { *(.PARISC.unwind) }
- __stop___unwind = .;
+ /* unwind info */
+ .PARISC.unwind : {
+ __start___unwind = .;
+ *(.PARISC.unwind)
+ __stop___unwind = .;
+ }
- /* rarely changed data like cpu maps */
- . = ALIGN(16);
- .data.read_mostly : { *(.data.read_mostly) }
+ /* rarely changed data like cpu maps */
+ . = ALIGN(16);
+ .data.read_mostly : {
+ *(.data.read_mostly)
+ }
- . = ALIGN(L1_CACHE_BYTES);
- .data : { /* Data */
- DATA_DATA
- CONSTRUCTORS
+ . = ALIGN(L1_CACHE_BYTES);
+ /* Data */
+ .data : {
+ DATA_DATA
+ CONSTRUCTORS
}
- . = ALIGN(L1_CACHE_BYTES);
- .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+ . = ALIGN(L1_CACHE_BYTES);
+ .data.cacheline_aligned : {
+ *(.data.cacheline_aligned)
+ }
- /* PA-RISC locks requires 16-byte alignment */
- . = ALIGN(16);
- .data.lock_aligned : { *(.data.lock_aligned) }
+ /* PA-RISC locks requires 16-byte alignment */
+ . = ALIGN(16);
+ .data.lock_aligned : {
+ *(.data.lock_aligned)
+ }
- . = ALIGN(ASM_PAGE_SIZE);
- /* nosave data is really only used for software suspend...it's here
- * just in case we ever implement it */
- __nosave_begin = .;
- .data_nosave : { *(.data.nosave) }
- . = ALIGN(ASM_PAGE_SIZE);
- __nosave_end = .;
+ /* nosave data is really only used for software suspend...it's here
+ * just in case we ever implement it
+ */
+ . = ALIGN(PAGE_SIZE);
+ __nosave_begin = .;
+ .data_nosave : {
+ *(.data.nosave)
+ }
+ . = ALIGN(PAGE_SIZE);
+ __nosave_end = .;
- _edata = .; /* End of data section */
+ /* End of data section */
+ _edata = .;
- __bss_start = .; /* BSS */
- /* page table entries need to be PAGE_SIZE aligned */
- . = ALIGN(ASM_PAGE_SIZE);
- .data.vmpages : {
- *(.data.vm0.pmd)
- *(.data.vm0.pgd)
- *(.data.vm0.pte)
+ /* BSS */
+ __bss_start = .;
+ /* page table entries need to be PAGE_SIZE aligned */
+ . = ALIGN(PAGE_SIZE);
+ .data.vmpages : {
+ *(.data.vm0.pmd)
+ *(.data.vm0.pgd)
+ *(.data.vm0.pte)
}
- .bss : { *(.bss) *(COMMON) }
- __bss_stop = .;
-
+ .bss : {
+ *(.bss)
+ *(COMMON)
+ }
+ __bss_stop = .;
- /* assembler code expects init_task to be 16k aligned */
- . = ALIGN(16384); /* init_task */
- .data.init_task : { *(.data.init_task) }
- /* The interrupt stack is currently partially coded, but not yet
- * implemented */
- . = ALIGN(16384);
- init_istack : { *(init_istack) }
+ /* assembler code expects init_task to be 16k aligned */
+ . = ALIGN(16384);
+ /* init_task */
+ .data.init_task : {
+ *(.data.init_task)
+ }
#ifdef CONFIG_64BIT
- . = ALIGN(16); /* Linkage tables */
- .opd : { *(.opd) } PROVIDE (__gp = .);
- .plt : { *(.plt) }
- .dlt : { *(.dlt) }
+ . = ALIGN(16);
+ /* Linkage tables */
+ .opd : {
+ *(.opd)
+ } PROVIDE (__gp = .);
+ .plt : {
+ *(.plt)
+ }
+ .dlt : {
+ *(.dlt)
+ }
#endif
- /* reserve space for interrupt stack by aligning __init* to 16k */
- . = ALIGN(16384);
- __init_begin = .;
- .init.text : {
- _sinittext = .;
- *(.init.text)
- _einittext = .;
- }
- .init.data : { *(.init.data) }
- . = ALIGN(16);
- __setup_start = .;
- .init.setup : { *(.init.setup) }
- __setup_end = .;
- __initcall_start = .;
- .initcall.init : {
- INITCALLS
- }
- __initcall_end = .;
- __con_initcall_start = .;
- .con_initcall.init : { *(.con_initcall.init) }
- __con_initcall_end = .;
- SECURITY_INIT
- /* alternate instruction replacement. This is a mechanism x86 uses
- * to detect the CPU type and replace generic instruction sequences
- * with CPU specific ones. We don't currently do this in PA, but
- * it seems like a good idea... */
- . = ALIGN(4);
- __alt_instructions = .;
- .altinstructions : { *(.altinstructions) }
- __alt_instructions_end = .;
- .altinstr_replacement : { *(.altinstr_replacement) }
- /* .exit.text is discard at runtime, not link time, to deal with references
- from .altinstructions and .eh_frame */
- .exit.text : { *(.exit.text) }
- .exit.data : { *(.exit.data) }
+ /* reserve space for interrupt stack by aligning __init* to 16k */
+ . = ALIGN(16384);
+ __init_begin = .;
+ .init.text : {
+ _sinittext = .;
+ *(.init.text)
+ _einittext = .;
+ }
+ .init.data : {
+ *(.init.data)
+ }
+ . = ALIGN(16);
+ .init.setup : {
+ __setup_start = .;
+ *(.init.setup)
+ __setup_end = .;
+ }
+ .initcall.init : {
+ __initcall_start = .;
+ INITCALLS
+ __initcall_end = .;
+ }
+ .con_initcall.init : {
+ __con_initcall_start = .;
+ *(.con_initcall.init)
+ __con_initcall_end = .;
+ }
+ SECURITY_INIT
+
+ /* alternate instruction replacement. This is a mechanism x86 uses
+ * to detect the CPU type and replace generic instruction sequences
+ * with CPU specific ones. We don't currently do this in PA, but
+ * it seems like a good idea...
+ */
+ . = ALIGN(4);
+ .altinstructions : {
+ __alt_instructions = .;
+ *(.altinstructions)
+ __alt_instructions_end = .;
+ }
+ .altinstr_replacement : {
+ *(.altinstr_replacement)
+ }
+
+ /* .exit.text is discard at runtime, not link time, to deal with references
+ * from .altinstructions and .eh_frame
+ */
+ .exit.text : {
+ *(.exit.text)
+ }
+ .exit.data : {
+ *(.exit.data)
+ }
#ifdef CONFIG_BLK_DEV_INITRD
- . = ALIGN(ASM_PAGE_SIZE);
- __initramfs_start = .;
- .init.ramfs : { *(.init.ramfs) }
- __initramfs_end = .;
+ . = ALIGN(PAGE_SIZE);
+ .init.ramfs : {
+ __initramfs_start = .;
+ *(.init.ramfs)
+ __initramfs_end = .;
+ }
#endif
- PERCPU(ASM_PAGE_SIZE)
+ PERCPU(PAGE_SIZE)
+ . = ALIGN(PAGE_SIZE);
+ __init_end = .;
+ /* freed after init ends here */
+ _end = . ;
- . = ALIGN(ASM_PAGE_SIZE);
- __init_end = .;
- /* freed after init ends here */
-
- _end = . ;
-
- /* Sections to be discarded */
- /DISCARD/ : {
- *(.exitcall.exit)
+ /* Sections to be discarded */
+ /DISCARD/ : {
+ *(.exitcall.exit)
#ifdef CONFIG_64BIT
- /* temporary hack until binutils is fixed to not emit these
- for static binaries */
- *(.interp)
- *(.dynsym)
- *(.dynstr)
- *(.dynamic)
- *(.hash)
- *(.gnu.hash)
+ /* temporary hack until binutils is fixed to not emit these
+ * for static binaries
+ */
+ *(.interp)
+ *(.dynsym)
+ *(.dynstr)
+ *(.dynamic)
+ *(.hash)
+ *(.gnu.hash)
#endif
}
- STABS_DEBUG
- .note 0 : { *(.note) }
-
+ STABS_DEBUG
+ .note 0 : { *(.note) }
}
diff --git a/arch/parisc/lib/Makefile b/arch/parisc/lib/Makefile
index 5f2e6904d14a..7ce406c7daf5 100644
--- a/arch/parisc/lib/Makefile
+++ b/arch/parisc/lib/Makefile
@@ -4,4 +4,4 @@
lib-y := lusercopy.o bitops.o checksum.o io.o memset.o fixup.o memcpy.o
-obj-y := iomap.o
+obj-y := libgcc/ milli/ iomap.o
diff --git a/arch/parisc/lib/libgcc/Makefile b/arch/parisc/lib/libgcc/Makefile
new file mode 100644
index 000000000000..b67a85ad9c87
--- /dev/null
+++ b/arch/parisc/lib/libgcc/Makefile
@@ -0,0 +1,4 @@
+obj-y := __ashldi3.o __ashrdi3.o __clzsi2.o __divdi3.o __divsi3.o \
+ __lshrdi3.o __moddi3.o __modsi3.o __udivdi3.o \
+ __udivmoddi4.o __udivmodsi4.o __udivsi3.o \
+ __umoddi3.o __umodsi3.o __muldi3.o __umulsidi3.o
diff --git a/arch/parisc/lib/libgcc/__ashldi3.c b/arch/parisc/lib/libgcc/__ashldi3.c
new file mode 100644
index 000000000000..a14a257abb2b
--- /dev/null
+++ b/arch/parisc/lib/libgcc/__ashldi3.c
@@ -0,0 +1,19 @@
+#include "libgcc.h"
+
+u64 __ashldi3(u64 v, int cnt)
+{
+ int c = cnt & 31;
+ u32 vl = (u32) v;
+ u32 vh = (u32) (v >> 32);
+
+ if (cnt & 32) {
+ vh = (vl << c);
+ vl = 0;
+ } else {
+ vh = (vh << c) + (vl >> (32 - c));
+ vl = (vl << c);
+ }
+
+ return ((u64) vh << 32) + vl;
+}
+EXPORT_SYMBOL(__ashldi3);
diff --git a/arch/parisc/lib/libgcc/__ashrdi3.c b/arch/parisc/lib/libgcc/__ashrdi3.c
new file mode 100644
index 000000000000..8636a5aa4f77
--- /dev/null
+++ b/arch/parisc/lib/libgcc/__ashrdi3.c
@@ -0,0 +1,19 @@
+#include "libgcc.h"
+
+u64 __ashrdi3(u64 v, int cnt)
+{
+ int c = cnt & 31;
+ u32 vl = (u32) v;
+ u32 vh = (u32) (v >> 32);
+
+ if (cnt & 32) {
+ vl = ((s32) vh >> c);
+ vh = (s32) vh >> 31;
+ } else {
+ vl = (vl >> c) + (vh << (32 - c));
+ vh = ((s32) vh >> c);
+ }
+
+ return ((u64) vh << 32) + vl;
+}
+EXPORT_SYMBOL(__ashrdi3);
diff --git a/arch/parisc/lib/libgcc/__clzsi2.c b/arch/parisc/lib/libgcc/__clzsi2.c
new file mode 100644
index 000000000000..a7aa2f55a9c6
--- /dev/null
+++ b/arch/parisc/lib/libgcc/__clzsi2.c
@@ -0,0 +1,30 @@
+#include "libgcc.h"
+
+u32 __clzsi2(u32 v)
+{
+ int p = 31;
+
+ if (v & 0xffff0000) {
+ p -= 16;
+ v >>= 16;
+ }
+ if (v & 0xff00) {
+ p -= 8;
+ v >>= 8;
+ }
+ if (v & 0xf0) {
+ p -= 4;
+ v >>= 4;
+ }
+ if (v & 0xc) {
+ p -= 2;
+ v >>= 2;
+ }
+ if (v & 0x2) {
+ p -= 1;
+ v >>= 1;
+ }
+
+ return p;
+}
+EXPORT_SYMBOL(__clzsi2);
diff --git a/arch/parisc/lib/libgcc/__divdi3.c b/arch/parisc/lib/libgcc/__divdi3.c
new file mode 100644
index 000000000000..f23c6fe2838b
--- /dev/null
+++ b/arch/parisc/lib/libgcc/__divdi3.c
@@ -0,0 +1,23 @@
+#include "libgcc.h"
+
+s64 __divdi3(s64 num, s64 den)
+{
+ int minus = 0;
+ s64 v;
+
+ if (num < 0) {
+ num = -num;
+ minus = 1;
+ }
+ if (den < 0) {
+ den = -den;
+ minus ^= 1;
+ }
+
+ v = __udivmoddi4(num, den, NULL);
+ if (minus)
+ v = -v;
+
+ return v;
+}
+EXPORT_SYMBOL(__divdi3);
diff --git a/arch/parisc/lib/libgcc/__divsi3.c b/arch/parisc/lib/libgcc/__divsi3.c
new file mode 100644
index 000000000000..730fb530680d
--- /dev/null
+++ b/arch/parisc/lib/libgcc/__divsi3.c
@@ -0,0 +1,23 @@
+#include "libgcc.h"
+
+s32 __divsi3(s32 num, s32 den)
+{
+ int minus = 0;
+ s32 v;
+
+ if (num < 0) {
+ num = -num;
+ minus = 1;
+ }
+ if (den < 0) {
+ den = -den;
+ minus ^= 1;
+ }
+
+ v = __udivmodsi4(num, den, NULL);
+ if (minus)
+ v = -v;
+
+ return v;
+}
+EXPORT_SYMBOL(__divsi3);
diff --git a/arch/parisc/lib/libgcc/__lshrdi3.c b/arch/parisc/lib/libgcc/__lshrdi3.c
new file mode 100644
index 000000000000..4a820708ec57
--- /dev/null
+++ b/arch/parisc/lib/libgcc/__lshrdi3.c
@@ -0,0 +1,19 @@
+#include "libgcc.h"
+
+u64 __lshrdi3(u64 v, int cnt)
+{
+ int c = cnt & 31;
+ u32 vl = (u32) v;
+ u32 vh = (u32) (v >> 32);
+
+ if (cnt & 32) {
+ vl = (vh >> c);
+ vh = 0;
+ } else {
+ vl = (vl >> c) + (vh << (32 - c));
+ vh = (vh >> c);
+ }
+
+ return ((u64) vh << 32) + vl;
+}
+EXPORT_SYMBOL(__lshrdi3);
diff --git a/arch/parisc/lib/libgcc/__moddi3.c b/arch/parisc/lib/libgcc/__moddi3.c
new file mode 100644
index 000000000000..ed64bbafc989
--- /dev/null
+++ b/arch/parisc/lib/libgcc/__moddi3.c
@@ -0,0 +1,23 @@
+#include "libgcc.h"
+
+s64 __moddi3(s64 num, s64 den)
+{
+ int minus = 0;
+ s64 v;
+
+ if (num < 0) {
+ num = -num;
+ minus = 1;
+ }
+ if (den < 0) {
+ den = -den;
+ minus ^= 1;
+ }
+
+ (void)__udivmoddi4(num, den, (u64 *) & v);
+ if (minus)
+ v = -v;
+
+ return v;
+}
+EXPORT_SYMBOL(__moddi3);
diff --git a/arch/parisc/lib/libgcc/__modsi3.c b/arch/parisc/lib/libgcc/__modsi3.c
new file mode 100644
index 000000000000..62f773efaeea
--- /dev/null
+++ b/arch/parisc/lib/libgcc/__modsi3.c
@@ -0,0 +1,23 @@
+#include "libgcc.h"
+
+s32 __modsi3(s32 num, s32 den)
+{
+ int minus = 0;
+ s32 v;
+
+ if (num < 0) {
+ num = -num;
+ minus = 1;
+ }
+ if (den < 0) {
+ den = -den;
+ minus ^= 1;
+ }
+
+ (void)__udivmodsi4(num, den, (u32 *) & v);
+ if (minus)
+ v = -v;
+
+ return v;
+}
+EXPORT_SYMBOL(__modsi3);
diff --git a/arch/parisc/lib/libgcc/__muldi3.c b/arch/parisc/lib/libgcc/__muldi3.c
new file mode 100644
index 000000000000..3308abdd5580
--- /dev/null
+++ b/arch/parisc/lib/libgcc/__muldi3.c
@@ -0,0 +1,22 @@
+#include "libgcc.h"
+
+union DWunion {
+ struct {
+ s32 high;
+ s32 low;
+ } s;
+ s64 ll;
+};
+
+s64 __muldi3(s64 u, s64 v)
+{
+ const union DWunion uu = { .ll = u };
+ const union DWunion vv = { .ll = v };
+ union DWunion w = { .ll = __umulsidi3(uu.s.low, vv.s.low) };
+
+ w.s.high += ((u32)uu.s.low * (u32)vv.s.high
+ + (u32)uu.s.high * (u32)vv.s.low);
+
+ return w.ll;
+}
+EXPORT_SYMBOL(__muldi3);
diff --git a/arch/parisc/lib/libgcc/__udivdi3.c b/arch/parisc/lib/libgcc/__udivdi3.c
new file mode 100644
index 000000000000..740023d690f5
--- /dev/null
+++ b/arch/parisc/lib/libgcc/__udivdi3.c
@@ -0,0 +1,7 @@
+#include "libgcc.h"
+
+u64 __udivdi3(u64 num, u64 den)
+{
+ return __udivmoddi4(num, den, NULL);
+}
+EXPORT_SYMBOL(__udivdi3);
diff --git a/arch/parisc/lib/libgcc/__udivmoddi4.c b/arch/parisc/lib/libgcc/__udivmoddi4.c
new file mode 100644
index 000000000000..2df0caa5a7d8
--- /dev/null
+++ b/arch/parisc/lib/libgcc/__udivmoddi4.c
@@ -0,0 +1,31 @@
+#include "libgcc.h"
+
+u64 __udivmoddi4(u64 num, u64 den, u64 * rem_p)
+{
+ u64 quot = 0, qbit = 1;
+
+ if (den == 0) {
+ BUG();
+ }
+
+ /* Left-justify denominator and count shift */
+ while ((s64) den >= 0) {
+ den <<= 1;
+ qbit <<= 1;
+ }
+
+ while (qbit) {
+ if (den <= num) {
+ num -= den;
+ quot += qbit;
+ }
+ den >>= 1;
+ qbit >>= 1;
+ }
+
+ if (rem_p)
+ *rem_p = num;
+
+ return quot;
+}
+EXPORT_SYMBOL(__udivmoddi4);
diff --git a/arch/parisc/lib/libgcc/__udivmodsi4.c b/arch/parisc/lib/libgcc/__udivmodsi4.c
new file mode 100644
index 000000000000..2a2fc28b2026
--- /dev/null
+++ b/arch/parisc/lib/libgcc/__udivmodsi4.c
@@ -0,0 +1,31 @@
+#include "libgcc.h"
+
+u32 __udivmodsi4(u32 num, u32 den, u32 * rem_p)
+{
+ u32 quot = 0, qbit = 1;
+
+ if (den == 0) {
+ BUG();
+ }
+
+ /* Left-justify denominator and count shift */
+ while ((s32) den >= 0) {
+ den <<= 1;
+ qbit <<= 1;
+ }
+
+ while (qbit) {
+ if (den <= num) {
+ num -= den;
+ quot += qbit;
+ }
+ den >>= 1;
+ qbit >>= 1;
+ }
+
+ if (rem_p)
+ *rem_p = num;
+
+ return quot;
+}
+EXPORT_SYMBOL(__udivmodsi4);
diff --git a/arch/parisc/lib/libgcc/__udivsi3.c b/arch/parisc/lib/libgcc/__udivsi3.c
new file mode 100644
index 000000000000..756a44164e90
--- /dev/null
+++ b/arch/parisc/lib/libgcc/__udivsi3.c
@@ -0,0 +1,7 @@
+#include "libgcc.h"
+
+u32 __udivsi3(u32 num, u32 den)
+{
+ return __udivmodsi4(num, den, NULL);
+}
+EXPORT_SYMBOL(__udivsi3);
diff --git a/arch/parisc/lib/libgcc/__umoddi3.c b/arch/parisc/lib/libgcc/__umoddi3.c
new file mode 100644
index 000000000000..ac744e948bc1
--- /dev/null
+++ b/arch/parisc/lib/libgcc/__umoddi3.c
@@ -0,0 +1,10 @@
+#include "libgcc.h"
+
+u64 __umoddi3(u64 num, u64 den)
+{
+ u64 v;
+
+ (void)__udivmoddi4(num, den, &v);
+ return v;
+}
+EXPORT_SYMBOL(__umoddi3);
diff --git a/arch/parisc/lib/libgcc/__umodsi3.c b/arch/parisc/lib/libgcc/__umodsi3.c
new file mode 100644
index 000000000000..51f55aa89f9a
--- /dev/null
+++ b/arch/parisc/lib/libgcc/__umodsi3.c
@@ -0,0 +1,10 @@
+#include "libgcc.h"
+
+u32 __umodsi3(u32 num, u32 den)
+{
+ u32 v;
+
+ (void)__udivmodsi4(num, den, &v);
+ return v;
+}
+EXPORT_SYMBOL(__umodsi3);
diff --git a/arch/parisc/lib/libgcc/__umulsidi3.c b/arch/parisc/lib/libgcc/__umulsidi3.c
new file mode 100644
index 000000000000..396f669164d4
--- /dev/null
+++ b/arch/parisc/lib/libgcc/__umulsidi3.c
@@ -0,0 +1,46 @@
+#include "libgcc.h"
+
+#define __ll_B ((u32) 1 << (32 / 2))
+#define __ll_lowpart(t) ((u32) (t) & (__ll_B - 1))
+#define __ll_highpart(t) ((u32) (t) >> 16)
+
+#define umul_ppmm(w1, w0, u, v) \
+ do { \
+ u32 __x0, __x1, __x2, __x3; \
+ u16 __ul, __vl, __uh, __vh; \
+ \
+ __ul = __ll_lowpart (u); \
+ __uh = __ll_highpart (u); \
+ __vl = __ll_lowpart (v); \
+ __vh = __ll_highpart (v); \
+ \
+ __x0 = (u32) __ul * __vl; \
+ __x1 = (u32) __ul * __vh; \
+ __x2 = (u32) __uh * __vl; \
+ __x3 = (u32) __uh * __vh; \
+ \
+ __x1 += __ll_highpart (__x0);/* this can't give carry */ \
+ __x1 += __x2; /* but this indeed can */ \
+ if (__x1 < __x2) /* did we get it? */ \
+ __x3 += __ll_B; /* yes, add it in the proper pos. */ \
+ \
+ (w1) = __x3 + __ll_highpart (__x1); \
+ (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \
+ } while (0)
+
+union DWunion {
+ struct {
+ s32 high;
+ s32 low;
+ } s;
+ s64 ll;
+};
+
+u64 __umulsidi3(u32 u, u32 v)
+{
+ union DWunion __w;
+
+ umul_ppmm(__w.s.high, __w.s.low, u, v);
+
+ return __w.ll;
+}
diff --git a/arch/parisc/lib/libgcc/libgcc.h b/arch/parisc/lib/libgcc/libgcc.h
new file mode 100644
index 000000000000..5a6f7a510fbd
--- /dev/null
+++ b/arch/parisc/lib/libgcc/libgcc.h
@@ -0,0 +1,32 @@
+#ifndef _PA_LIBGCC_H_
+#define _PA_LIBGCC_H_
+
+#include <linux/types.h>
+#include <linux/module.h>
+
+/* Cribbed from klibc/libgcc/ */
+u64 __ashldi3(u64 v, int cnt);
+u64 __ashrdi3(u64 v, int cnt);
+
+u32 __clzsi2(u32 v);
+
+s64 __divdi3(s64 num, s64 den);
+s32 __divsi3(s32 num, s32 den);
+
+u64 __lshrdi3(u64 v, int cnt);
+
+s64 __moddi3(s64 num, s64 den);
+s32 __modsi3(s32 num, s32 den);
+
+u64 __udivdi3(u64 num, u64 den);
+u32 __udivsi3(u32 num, u32 den);
+
+u64 __udivmoddi4(u64 num, u64 den, u64 * rem_p);
+u32 __udivmodsi4(u32 num, u32 den, u32 * rem_p);
+
+u64 __umulsidi3(u32 u, u32 v);
+
+u64 __umoddi3(u64 num, u64 den);
+u32 __umodsi3(u32 num, u32 den);
+
+#endif /*_PA_LIBGCC_H_*/
diff --git a/arch/parisc/lib/memcpy.c b/arch/parisc/lib/memcpy.c
index 2c43ebe99a9c..d22042d33100 100644
--- a/arch/parisc/lib/memcpy.c
+++ b/arch/parisc/lib/memcpy.c
@@ -139,12 +139,12 @@ DECLARE_PER_CPU(struct exception_data, exception_data);
#define stw(_s,_t,_o,_a,_e) def_store_insn(stw,"r",_s,_t,_o,_a,_e)
#ifdef CONFIG_PREFETCH
-extern inline void prefetch_src(const void *addr)
+static inline void prefetch_src(const void *addr)
{
__asm__("ldw 0(" s_space ",%0), %%r0" : : "r" (addr));
}
-extern inline void prefetch_dst(const void *addr)
+static inline void prefetch_dst(const void *addr)
{
__asm__("ldd 0(" d_space ",%0), %%r0" : : "r" (addr));
}
diff --git a/arch/parisc/lib/milli/Makefile b/arch/parisc/lib/milli/Makefile
new file mode 100644
index 000000000000..9b24e9b1f3cb
--- /dev/null
+++ b/arch/parisc/lib/milli/Makefile
@@ -0,0 +1 @@
+obj-y := dyncall.o divI.o divU.o remI.o remU.o div_const.o mulI.o
diff --git a/arch/parisc/lib/milli/divI.S b/arch/parisc/lib/milli/divI.S
new file mode 100644
index 000000000000..ac106b7b6f24
--- /dev/null
+++ b/arch/parisc/lib/milli/divI.S
@@ -0,0 +1,254 @@
+/* 32 and 64-bit millicode, original author Hewlett-Packard
+ adapted for gcc by Paul Bame <bame@debian.org>
+ and Alan Modra <alan@linuxcare.com.au>.
+
+ Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
+
+ This file is part of GCC and is released under the terms of
+ of the GNU General Public License as published by the Free Software
+ Foundation; either version 2, or (at your option) any later version.
+ See the file COPYING in the top-level GCC source directory for a copy
+ of the license. */
+
+#include "milli.h"
+
+#ifdef L_divI
+/* ROUTINES: $$divI, $$divoI
+
+ Single precision divide for signed binary integers.
+
+ The quotient is truncated towards zero.
+ The sign of the quotient is the XOR of the signs of the dividend and
+ divisor.
+ Divide by zero is trapped.
+ Divide of -2**31 by -1 is trapped for $$divoI but not for $$divI.
+
+ INPUT REGISTERS:
+ . arg0 == dividend
+ . arg1 == divisor
+ . mrp == return pc
+ . sr0 == return space when called externally
+
+ OUTPUT REGISTERS:
+ . arg0 = undefined
+ . arg1 = undefined
+ . ret1 = quotient
+
+ OTHER REGISTERS AFFECTED:
+ . r1 = undefined
+
+ SIDE EFFECTS:
+ . Causes a trap under the following conditions:
+ . divisor is zero (traps with ADDIT,= 0,25,0)
+ . dividend==-2**31 and divisor==-1 and routine is $$divoI
+ . (traps with ADDO 26,25,0)
+ . Changes memory at the following places:
+ . NONE
+
+ PERMISSIBLE CONTEXT:
+ . Unwindable.
+ . Suitable for internal or external millicode.
+ . Assumes the special millicode register conventions.
+
+ DISCUSSION:
+ . Branchs to other millicode routines using BE
+ . $$div_# for # being 2,3,4,5,6,7,8,9,10,12,14,15
+ .
+ . For selected divisors, calls a divide by constant routine written by
+ . Karl Pettis. Eligible divisors are 1..15 excluding 11 and 13.
+ .
+ . The only overflow case is -2**31 divided by -1.
+ . Both routines return -2**31 but only $$divoI traps. */
+
+RDEFINE(temp,r1)
+RDEFINE(retreg,ret1) /* r29 */
+RDEFINE(temp1,arg0)
+ SUBSPA_MILLI_DIV
+ ATTR_MILLI
+ .import $$divI_2,millicode
+ .import $$divI_3,millicode
+ .import $$divI_4,millicode
+ .import $$divI_5,millicode
+ .import $$divI_6,millicode
+ .import $$divI_7,millicode
+ .import $$divI_8,millicode
+ .import $$divI_9,millicode
+ .import $$divI_10,millicode
+ .import $$divI_12,millicode
+ .import $$divI_14,millicode
+ .import $$divI_15,millicode
+ .export $$divI,millicode
+ .export $$divoI,millicode
+ .proc
+ .callinfo millicode
+ .entry
+GSYM($$divoI)
+ comib,=,n -1,arg1,LREF(negative1) /* when divisor == -1 */
+GSYM($$divI)
+ ldo -1(arg1),temp /* is there at most one bit set ? */
+ and,<> arg1,temp,r0 /* if not, don't use power of 2 divide */
+ addi,> 0,arg1,r0 /* if divisor > 0, use power of 2 divide */
+ b,n LREF(neg_denom)
+LSYM(pow2)
+ addi,>= 0,arg0,retreg /* if numerator is negative, add the */
+ add arg0,temp,retreg /* (denominaotr -1) to correct for shifts */
+ extru,= arg1,15,16,temp /* test denominator with 0xffff0000 */
+ extrs retreg,15,16,retreg /* retreg = retreg >> 16 */
+ or arg1,temp,arg1 /* arg1 = arg1 | (arg1 >> 16) */
+ ldi 0xcc,temp1 /* setup 0xcc in temp1 */
+ extru,= arg1,23,8,temp /* test denominator with 0xff00 */
+ extrs retreg,23,24,retreg /* retreg = retreg >> 8 */
+ or arg1,temp,arg1 /* arg1 = arg1 | (arg1 >> 8) */
+ ldi 0xaa,temp /* setup 0xaa in temp */
+ extru,= arg1,27,4,r0 /* test denominator with 0xf0 */
+ extrs retreg,27,28,retreg /* retreg = retreg >> 4 */
+ and,= arg1,temp1,r0 /* test denominator with 0xcc */
+ extrs retreg,29,30,retreg /* retreg = retreg >> 2 */
+ and,= arg1,temp,r0 /* test denominator with 0xaa */
+ extrs retreg,30,31,retreg /* retreg = retreg >> 1 */
+ MILLIRETN
+LSYM(neg_denom)
+ addi,< 0,arg1,r0 /* if arg1 >= 0, it's not power of 2 */
+ b,n LREF(regular_seq)
+ sub r0,arg1,temp /* make denominator positive */
+ comb,=,n arg1,temp,LREF(regular_seq) /* test against 0x80000000 and 0 */
+ ldo -1(temp),retreg /* is there at most one bit set ? */
+ and,= temp,retreg,r0 /* if so, the denominator is power of 2 */
+ b,n LREF(regular_seq)
+ sub r0,arg0,retreg /* negate numerator */
+ comb,=,n arg0,retreg,LREF(regular_seq) /* test against 0x80000000 */
+ copy retreg,arg0 /* set up arg0, arg1 and temp */
+ copy temp,arg1 /* before branching to pow2 */
+ b LREF(pow2)
+ ldo -1(arg1),temp
+LSYM(regular_seq)
+ comib,>>=,n 15,arg1,LREF(small_divisor)
+ add,>= 0,arg0,retreg /* move dividend, if retreg < 0, */
+LSYM(normal)
+ subi 0,retreg,retreg /* make it positive */
+ sub 0,arg1,temp /* clear carry, */
+ /* negate the divisor */
+ ds 0,temp,0 /* set V-bit to the comple- */
+ /* ment of the divisor sign */
+ add retreg,retreg,retreg /* shift msb bit into carry */
+ ds r0,arg1,temp /* 1st divide step, if no carry */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 2nd divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 3rd divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 4th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 5th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 6th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 7th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 8th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 9th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 10th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 11th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 12th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 13th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 14th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 15th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 16th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 17th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 18th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 19th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 20th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 21st divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 22nd divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 23rd divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 24th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 25th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 26th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 27th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 28th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 29th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 30th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 31st divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 32nd divide step, */
+ addc retreg,retreg,retreg /* shift last retreg bit into retreg */
+ xor,>= arg0,arg1,0 /* get correct sign of quotient */
+ sub 0,retreg,retreg /* based on operand signs */
+ MILLIRETN
+ nop
+
+LSYM(small_divisor)
+
+#if defined(CONFIG_64BIT)
+/* Clear the upper 32 bits of the arg1 register. We are working with */
+/* small divisors (and 32-bit integers) We must not be mislead */
+/* by "1" bits left in the upper 32 bits. */
+ depd %r0,31,32,%r25
+#endif
+ blr,n arg1,r0
+ nop
+/* table for divisor == 0,1, ... ,15 */
+ addit,= 0,arg1,r0 /* trap if divisor == 0 */
+ nop
+ MILLIRET /* divisor == 1 */
+ copy arg0,retreg
+ MILLI_BEN($$divI_2) /* divisor == 2 */
+ nop
+ MILLI_BEN($$divI_3) /* divisor == 3 */
+ nop
+ MILLI_BEN($$divI_4) /* divisor == 4 */
+ nop
+ MILLI_BEN($$divI_5) /* divisor == 5 */
+ nop
+ MILLI_BEN($$divI_6) /* divisor == 6 */
+ nop
+ MILLI_BEN($$divI_7) /* divisor == 7 */
+ nop
+ MILLI_BEN($$divI_8) /* divisor == 8 */
+ nop
+ MILLI_BEN($$divI_9) /* divisor == 9 */
+ nop
+ MILLI_BEN($$divI_10) /* divisor == 10 */
+ nop
+ b LREF(normal) /* divisor == 11 */
+ add,>= 0,arg0,retreg
+ MILLI_BEN($$divI_12) /* divisor == 12 */
+ nop
+ b LREF(normal) /* divisor == 13 */
+ add,>= 0,arg0,retreg
+ MILLI_BEN($$divI_14) /* divisor == 14 */
+ nop
+ MILLI_BEN($$divI_15) /* divisor == 15 */
+ nop
+
+LSYM(negative1)
+ sub 0,arg0,retreg /* result is negation of dividend */
+ MILLIRET
+ addo arg0,arg1,r0 /* trap iff dividend==0x80000000 && divisor==-1 */
+ .exit
+ .procend
+ .end
+#endif
diff --git a/arch/parisc/lib/milli/divU.S b/arch/parisc/lib/milli/divU.S
new file mode 100644
index 000000000000..9287fe2546fa
--- /dev/null
+++ b/arch/parisc/lib/milli/divU.S
@@ -0,0 +1,235 @@
+/* 32 and 64-bit millicode, original author Hewlett-Packard
+ adapted for gcc by Paul Bame <bame@debian.org>
+ and Alan Modra <alan@linuxcare.com.au>.
+
+ Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
+
+ This file is part of GCC and is released under the terms of
+ of the GNU General Public License as published by the Free Software
+ Foundation; either version 2, or (at your option) any later version.
+ See the file COPYING in the top-level GCC source directory for a copy
+ of the license. */
+
+#include "milli.h"
+
+#ifdef L_divU
+/* ROUTINE: $$divU
+ .
+ . Single precision divide for unsigned integers.
+ .
+ . Quotient is truncated towards zero.
+ . Traps on divide by zero.
+
+ INPUT REGISTERS:
+ . arg0 == dividend
+ . arg1 == divisor
+ . mrp == return pc
+ . sr0 == return space when called externally
+
+ OUTPUT REGISTERS:
+ . arg0 = undefined
+ . arg1 = undefined
+ . ret1 = quotient
+
+ OTHER REGISTERS AFFECTED:
+ . r1 = undefined
+
+ SIDE EFFECTS:
+ . Causes a trap under the following conditions:
+ . divisor is zero
+ . Changes memory at the following places:
+ . NONE
+
+ PERMISSIBLE CONTEXT:
+ . Unwindable.
+ . Does not create a stack frame.
+ . Suitable for internal or external millicode.
+ . Assumes the special millicode register conventions.
+
+ DISCUSSION:
+ . Branchs to other millicode routines using BE:
+ . $$divU_# for 3,5,6,7,9,10,12,14,15
+ .
+ . For selected small divisors calls the special divide by constant
+ . routines written by Karl Pettis. These are: 3,5,6,7,9,10,12,14,15. */
+
+RDEFINE(temp,r1)
+RDEFINE(retreg,ret1) /* r29 */
+RDEFINE(temp1,arg0)
+ SUBSPA_MILLI_DIV
+ ATTR_MILLI
+ .export $$divU,millicode
+ .import $$divU_3,millicode
+ .import $$divU_5,millicode
+ .import $$divU_6,millicode
+ .import $$divU_7,millicode
+ .import $$divU_9,millicode
+ .import $$divU_10,millicode
+ .import $$divU_12,millicode
+ .import $$divU_14,millicode
+ .import $$divU_15,millicode
+ .proc
+ .callinfo millicode
+ .entry
+GSYM($$divU)
+/* The subtract is not nullified since it does no harm and can be used
+ by the two cases that branch back to "normal". */
+ ldo -1(arg1),temp /* is there at most one bit set ? */
+ and,= arg1,temp,r0 /* if so, denominator is power of 2 */
+ b LREF(regular_seq)
+ addit,= 0,arg1,0 /* trap for zero dvr */
+ copy arg0,retreg
+ extru,= arg1,15,16,temp /* test denominator with 0xffff0000 */
+ extru retreg,15,16,retreg /* retreg = retreg >> 16 */
+ or arg1,temp,arg1 /* arg1 = arg1 | (arg1 >> 16) */
+ ldi 0xcc,temp1 /* setup 0xcc in temp1 */
+ extru,= arg1,23,8,temp /* test denominator with 0xff00 */
+ extru retreg,23,24,retreg /* retreg = retreg >> 8 */
+ or arg1,temp,arg1 /* arg1 = arg1 | (arg1 >> 8) */
+ ldi 0xaa,temp /* setup 0xaa in temp */
+ extru,= arg1,27,4,r0 /* test denominator with 0xf0 */
+ extru retreg,27,28,retreg /* retreg = retreg >> 4 */
+ and,= arg1,temp1,r0 /* test denominator with 0xcc */
+ extru retreg,29,30,retreg /* retreg = retreg >> 2 */
+ and,= arg1,temp,r0 /* test denominator with 0xaa */
+ extru retreg,30,31,retreg /* retreg = retreg >> 1 */
+ MILLIRETN
+ nop
+LSYM(regular_seq)
+ comib,>= 15,arg1,LREF(special_divisor)
+ subi 0,arg1,temp /* clear carry, negate the divisor */
+ ds r0,temp,r0 /* set V-bit to 1 */
+LSYM(normal)
+ add arg0,arg0,retreg /* shift msb bit into carry */
+ ds r0,arg1,temp /* 1st divide step, if no carry */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 2nd divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 3rd divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 4th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 5th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 6th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 7th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 8th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 9th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 10th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 11th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 12th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 13th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 14th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 15th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 16th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 17th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 18th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 19th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 20th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 21st divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 22nd divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 23rd divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 24th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 25th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 26th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 27th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 28th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 29th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 30th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 31st divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 32nd divide step, */
+ MILLIRET
+ addc retreg,retreg,retreg /* shift last retreg bit into retreg */
+
+/* Handle the cases where divisor is a small constant or has high bit on. */
+LSYM(special_divisor)
+/* blr arg1,r0 */
+/* comib,>,n 0,arg1,LREF(big_divisor) ; nullify previous instruction */
+
+/* Pratap 8/13/90. The 815 Stirling chip set has a bug that prevents us from
+ generating such a blr, comib sequence. A problem in nullification. So I
+ rewrote this code. */
+
+#if defined(CONFIG_64BIT)
+/* Clear the upper 32 bits of the arg1 register. We are working with
+ small divisors (and 32-bit unsigned integers) We must not be mislead
+ by "1" bits left in the upper 32 bits. */
+ depd %r0,31,32,%r25
+#endif
+ comib,> 0,arg1,LREF(big_divisor)
+ nop
+ blr arg1,r0
+ nop
+
+LSYM(zero_divisor) /* this label is here to provide external visibility */
+ addit,= 0,arg1,0 /* trap for zero dvr */
+ nop
+ MILLIRET /* divisor == 1 */
+ copy arg0,retreg
+ MILLIRET /* divisor == 2 */
+ extru arg0,30,31,retreg
+ MILLI_BEN($$divU_3) /* divisor == 3 */
+ nop
+ MILLIRET /* divisor == 4 */
+ extru arg0,29,30,retreg
+ MILLI_BEN($$divU_5) /* divisor == 5 */
+ nop
+ MILLI_BEN($$divU_6) /* divisor == 6 */
+ nop
+ MILLI_BEN($$divU_7) /* divisor == 7 */
+ nop
+ MILLIRET /* divisor == 8 */
+ extru arg0,28,29,retreg
+ MILLI_BEN($$divU_9) /* divisor == 9 */
+ nop
+ MILLI_BEN($$divU_10) /* divisor == 10 */
+ nop
+ b LREF(normal) /* divisor == 11 */
+ ds r0,temp,r0 /* set V-bit to 1 */
+ MILLI_BEN($$divU_12) /* divisor == 12 */
+ nop
+ b LREF(normal) /* divisor == 13 */
+ ds r0,temp,r0 /* set V-bit to 1 */
+ MILLI_BEN($$divU_14) /* divisor == 14 */
+ nop
+ MILLI_BEN($$divU_15) /* divisor == 15 */
+ nop
+
+/* Handle the case where the high bit is on in the divisor.
+ Compute: if( dividend>=divisor) quotient=1; else quotient=0;
+ Note: dividend>==divisor iff dividend-divisor does not borrow
+ and not borrow iff carry. */
+LSYM(big_divisor)
+ sub arg0,arg1,r0
+ MILLIRET
+ addc r0,r0,retreg
+ .exit
+ .procend
+ .end
+#endif
diff --git a/arch/parisc/lib/milli/div_const.S b/arch/parisc/lib/milli/div_const.S
new file mode 100644
index 000000000000..dd660076e944
--- /dev/null
+++ b/arch/parisc/lib/milli/div_const.S
@@ -0,0 +1,682 @@
+/* 32 and 64-bit millicode, original author Hewlett-Packard
+ adapted for gcc by Paul Bame <bame@debian.org>
+ and Alan Modra <alan@linuxcare.com.au>.
+
+ Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
+
+ This file is part of GCC and is released under the terms of
+ of the GNU General Public License as published by the Free Software
+ Foundation; either version 2, or (at your option) any later version.
+ See the file COPYING in the top-level GCC source directory for a copy
+ of the license. */
+
+#include "milli.h"
+
+#ifdef L_div_const
+/* ROUTINE: $$divI_2
+ . $$divI_3 $$divU_3
+ . $$divI_4
+ . $$divI_5 $$divU_5
+ . $$divI_6 $$divU_6
+ . $$divI_7 $$divU_7
+ . $$divI_8
+ . $$divI_9 $$divU_9
+ . $$divI_10 $$divU_10
+ .
+ . $$divI_12 $$divU_12
+ .
+ . $$divI_14 $$divU_14
+ . $$divI_15 $$divU_15
+ . $$divI_16
+ . $$divI_17 $$divU_17
+ .
+ . Divide by selected constants for single precision binary integers.
+
+ INPUT REGISTERS:
+ . arg0 == dividend
+ . mrp == return pc
+ . sr0 == return space when called externally
+
+ OUTPUT REGISTERS:
+ . arg0 = undefined
+ . arg1 = undefined
+ . ret1 = quotient
+
+ OTHER REGISTERS AFFECTED:
+ . r1 = undefined
+
+ SIDE EFFECTS:
+ . Causes a trap under the following conditions: NONE
+ . Changes memory at the following places: NONE
+
+ PERMISSIBLE CONTEXT:
+ . Unwindable.
+ . Does not create a stack frame.
+ . Suitable for internal or external millicode.
+ . Assumes the special millicode register conventions.
+
+ DISCUSSION:
+ . Calls other millicode routines using mrp: NONE
+ . Calls other millicode routines: NONE */
+
+
+/* TRUNCATED DIVISION BY SMALL INTEGERS
+
+ We are interested in q(x) = floor(x/y), where x >= 0 and y > 0
+ (with y fixed).
+
+ Let a = floor(z/y), for some choice of z. Note that z will be
+ chosen so that division by z is cheap.
+
+ Let r be the remainder(z/y). In other words, r = z - ay.
+
+ Now, our method is to choose a value for b such that
+
+ q'(x) = floor((ax+b)/z)
+
+ is equal to q(x) over as large a range of x as possible. If the
+ two are equal over a sufficiently large range, and if it is easy to
+ form the product (ax), and it is easy to divide by z, then we can
+ perform the division much faster than the general division algorithm.
+
+ So, we want the following to be true:
+
+ . For x in the following range:
+ .
+ . ky <= x < (k+1)y
+ .
+ . implies that
+ .
+ . k <= (ax+b)/z < (k+1)
+
+ We want to determine b such that this is true for all k in the
+ range {0..K} for some maximum K.
+
+ Since (ax+b) is an increasing function of x, we can take each
+ bound separately to determine the "best" value for b.
+
+ (ax+b)/z < (k+1) implies
+
+ (a((k+1)y-1)+b < (k+1)z implies
+
+ b < a + (k+1)(z-ay) implies
+
+ b < a + (k+1)r
+
+ This needs to be true for all k in the range {0..K}. In
+ particular, it is true for k = 0 and this leads to a maximum
+ acceptable value for b.
+
+ b < a+r or b <= a+r-1
+
+ Taking the other bound, we have
+
+ k <= (ax+b)/z implies
+
+ k <= (aky+b)/z implies
+
+ k(z-ay) <= b implies
+
+ kr <= b
+
+ Clearly, the largest range for k will be achieved by maximizing b,
+ when r is not zero. When r is zero, then the simplest choice for b
+ is 0. When r is not 0, set
+
+ . b = a+r-1
+
+ Now, by construction, q'(x) = floor((ax+b)/z) = q(x) = floor(x/y)
+ for all x in the range:
+
+ . 0 <= x < (K+1)y
+
+ We need to determine what K is. Of our two bounds,
+
+ . b < a+(k+1)r is satisfied for all k >= 0, by construction.
+
+ The other bound is
+
+ . kr <= b
+
+ This is always true if r = 0. If r is not 0 (the usual case), then
+ K = floor((a+r-1)/r), is the maximum value for k.
+
+ Therefore, the formula q'(x) = floor((ax+b)/z) yields the correct
+ answer for q(x) = floor(x/y) when x is in the range
+
+ (0,(K+1)y-1) K = floor((a+r-1)/r)
+
+ To be most useful, we want (K+1)y-1 = (max x) >= 2**32-1 so that
+ the formula for q'(x) yields the correct value of q(x) for all x
+ representable by a single word in HPPA.
+
+ We are also constrained in that computing the product (ax), adding
+ b, and dividing by z must all be done quickly, otherwise we will be
+ better off going through the general algorithm using the DS
+ instruction, which uses approximately 70 cycles.
+
+ For each y, there is a choice of z which satisfies the constraints
+ for (K+1)y >= 2**32. We may not, however, be able to satisfy the
+ timing constraints for arbitrary y. It seems that z being equal to
+ a power of 2 or a power of 2 minus 1 is as good as we can do, since
+ it minimizes the time to do division by z. We want the choice of z
+ to also result in a value for (a) that minimizes the computation of
+ the product (ax). This is best achieved if (a) has a regular bit
+ pattern (so the multiplication can be done with shifts and adds).
+ The value of (a) also needs to be less than 2**32 so the product is
+ always guaranteed to fit in 2 words.
+
+ In actual practice, the following should be done:
+
+ 1) For negative x, you should take the absolute value and remember
+ . the fact so that the result can be negated. This obviously does
+ . not apply in the unsigned case.
+ 2) For even y, you should factor out the power of 2 that divides y
+ . and divide x by it. You can then proceed by dividing by the
+ . odd factor of y.
+
+ Here is a table of some odd values of y, and corresponding choices
+ for z which are "good".
+
+ y z r a (hex) max x (hex)
+
+ 3 2**32 1 55555555 100000001
+ 5 2**32 1 33333333 100000003
+ 7 2**24-1 0 249249 (infinite)
+ 9 2**24-1 0 1c71c7 (infinite)
+ 11 2**20-1 0 1745d (infinite)
+ 13 2**24-1 0 13b13b (infinite)
+ 15 2**32 1 11111111 10000000d
+ 17 2**32 1 f0f0f0f 10000000f
+
+ If r is 1, then b = a+r-1 = a. This simplifies the computation
+ of (ax+b), since you can compute (x+1)(a) instead. If r is 0,
+ then b = 0 is ok to use which simplifies (ax+b).
+
+ The bit patterns for 55555555, 33333333, and 11111111 are obviously
+ very regular. The bit patterns for the other values of a above are:
+
+ y (hex) (binary)
+
+ 7 249249 001001001001001001001001 << regular >>
+ 9 1c71c7 000111000111000111000111 << regular >>
+ 11 1745d 000000010111010001011101 << irregular >>
+ 13 13b13b 000100111011000100111011 << irregular >>
+
+ The bit patterns for (a) corresponding to (y) of 11 and 13 may be
+ too irregular to warrant using this method.
+
+ When z is a power of 2 minus 1, then the division by z is slightly
+ more complicated, involving an iterative solution.
+
+ The code presented here solves division by 1 through 17, except for
+ 11 and 13. There are algorithms for both signed and unsigned
+ quantities given.
+
+ TIMINGS (cycles)
+
+ divisor positive negative unsigned
+
+ . 1 2 2 2
+ . 2 4 4 2
+ . 3 19 21 19
+ . 4 4 4 2
+ . 5 18 22 19
+ . 6 19 22 19
+ . 8 4 4 2
+ . 10 18 19 17
+ . 12 18 20 18
+ . 15 16 18 16
+ . 16 4 4 2
+ . 17 16 18 16
+
+ Now, the algorithm for 7, 9, and 14 is an iterative one. That is,
+ a loop body is executed until the tentative quotient is 0. The
+ number of times the loop body is executed varies depending on the
+ dividend, but is never more than two times. If the dividend is
+ less than the divisor, then the loop body is not executed at all.
+ Each iteration adds 4 cycles to the timings.
+
+ divisor positive negative unsigned
+
+ . 7 19+4n 20+4n 20+4n n = number of iterations
+ . 9 21+4n 22+4n 21+4n
+ . 14 21+4n 22+4n 20+4n
+
+ To give an idea of how the number of iterations varies, here is a
+ table of dividend versus number of iterations when dividing by 7.
+
+ smallest largest required
+ dividend dividend iterations
+
+ . 0 6 0
+ . 7 0x6ffffff 1
+ 0x1000006 0xffffffff 2
+
+ There is some overlap in the range of numbers requiring 1 and 2
+ iterations. */
+
+RDEFINE(t2,r1)
+RDEFINE(x2,arg0) /* r26 */
+RDEFINE(t1,arg1) /* r25 */
+RDEFINE(x1,ret1) /* r29 */
+
+ SUBSPA_MILLI_DIV
+ ATTR_MILLI
+
+ .proc
+ .callinfo millicode
+ .entry
+/* NONE of these routines require a stack frame
+ ALL of these routines are unwindable from millicode */
+
+GSYM($$divide_by_constant)
+ .export $$divide_by_constant,millicode
+/* Provides a "nice" label for the code covered by the unwind descriptor
+ for things like gprof. */
+
+/* DIVISION BY 2 (shift by 1) */
+GSYM($$divI_2)
+ .export $$divI_2,millicode
+ comclr,>= arg0,0,0
+ addi 1,arg0,arg0
+ MILLIRET
+ extrs arg0,30,31,ret1
+
+
+/* DIVISION BY 4 (shift by 2) */
+GSYM($$divI_4)
+ .export $$divI_4,millicode
+ comclr,>= arg0,0,0
+ addi 3,arg0,arg0
+ MILLIRET
+ extrs arg0,29,30,ret1
+
+
+/* DIVISION BY 8 (shift by 3) */
+GSYM($$divI_8)
+ .export $$divI_8,millicode
+ comclr,>= arg0,0,0
+ addi 7,arg0,arg0
+ MILLIRET
+ extrs arg0,28,29,ret1
+
+/* DIVISION BY 16 (shift by 4) */
+GSYM($$divI_16)
+ .export $$divI_16,millicode
+ comclr,>= arg0,0,0
+ addi 15,arg0,arg0
+ MILLIRET
+ extrs arg0,27,28,ret1
+
+/****************************************************************************
+*
+* DIVISION BY DIVISORS OF FFFFFFFF, and powers of 2 times these
+*
+* includes 3,5,15,17 and also 6,10,12
+*
+****************************************************************************/
+
+/* DIVISION BY 3 (use z = 2**32; a = 55555555) */
+
+GSYM($$divI_3)
+ .export $$divI_3,millicode
+ comb,<,N x2,0,LREF(neg3)
+
+ addi 1,x2,x2 /* this cannot overflow */
+ extru x2,1,2,x1 /* multiply by 5 to get started */
+ sh2add x2,x2,x2
+ b LREF(pos)
+ addc x1,0,x1
+
+LSYM(neg3)
+ subi 1,x2,x2 /* this cannot overflow */
+ extru x2,1,2,x1 /* multiply by 5 to get started */
+ sh2add x2,x2,x2
+ b LREF(neg)
+ addc x1,0,x1
+
+GSYM($$divU_3)
+ .export $$divU_3,millicode
+ addi 1,x2,x2 /* this CAN overflow */
+ addc 0,0,x1
+ shd x1,x2,30,t1 /* multiply by 5 to get started */
+ sh2add x2,x2,x2
+ b LREF(pos)
+ addc x1,t1,x1
+
+/* DIVISION BY 5 (use z = 2**32; a = 33333333) */
+
+GSYM($$divI_5)
+ .export $$divI_5,millicode
+ comb,<,N x2,0,LREF(neg5)
+
+ addi 3,x2,t1 /* this cannot overflow */
+ sh1add x2,t1,x2 /* multiply by 3 to get started */
+ b LREF(pos)
+ addc 0,0,x1
+
+LSYM(neg5)
+ sub 0,x2,x2 /* negate x2 */
+ addi 1,x2,x2 /* this cannot overflow */
+ shd 0,x2,31,x1 /* get top bit (can be 1) */
+ sh1add x2,x2,x2 /* multiply by 3 to get started */
+ b LREF(neg)
+ addc x1,0,x1
+
+GSYM($$divU_5)
+ .export $$divU_5,millicode
+ addi 1,x2,x2 /* this CAN overflow */
+ addc 0,0,x1
+ shd x1,x2,31,t1 /* multiply by 3 to get started */
+ sh1add x2,x2,x2
+ b LREF(pos)
+ addc t1,x1,x1
+
+/* DIVISION BY 6 (shift to divide by 2 then divide by 3) */
+GSYM($$divI_6)
+ .export $$divI_6,millicode
+ comb,<,N x2,0,LREF(neg6)
+ extru x2,30,31,x2 /* divide by 2 */
+ addi 5,x2,t1 /* compute 5*(x2+1) = 5*x2+5 */
+ sh2add x2,t1,x2 /* multiply by 5 to get started */
+ b LREF(pos)
+ addc 0,0,x1
+
+LSYM(neg6)
+ subi 2,x2,x2 /* negate, divide by 2, and add 1 */
+ /* negation and adding 1 are done */
+ /* at the same time by the SUBI */
+ extru x2,30,31,x2
+ shd 0,x2,30,x1
+ sh2add x2,x2,x2 /* multiply by 5 to get started */
+ b LREF(neg)
+ addc x1,0,x1
+
+GSYM($$divU_6)
+ .export $$divU_6,millicode
+ extru x2,30,31,x2 /* divide by 2 */
+ addi 1,x2,x2 /* cannot carry */
+ shd 0,x2,30,x1 /* multiply by 5 to get started */
+ sh2add x2,x2,x2
+ b LREF(pos)
+ addc x1,0,x1
+
+/* DIVISION BY 10 (shift to divide by 2 then divide by 5) */
+GSYM($$divU_10)
+ .export $$divU_10,millicode
+ extru x2,30,31,x2 /* divide by 2 */
+ addi 3,x2,t1 /* compute 3*(x2+1) = (3*x2)+3 */
+ sh1add x2,t1,x2 /* multiply by 3 to get started */
+ addc 0,0,x1
+LSYM(pos)
+ shd x1,x2,28,t1 /* multiply by 0x11 */
+ shd x2,0,28,t2
+ add x2,t2,x2
+ addc x1,t1,x1
+LSYM(pos_for_17)
+ shd x1,x2,24,t1 /* multiply by 0x101 */
+ shd x2,0,24,t2
+ add x2,t2,x2
+ addc x1,t1,x1
+
+ shd x1,x2,16,t1 /* multiply by 0x10001 */
+ shd x2,0,16,t2
+ add x2,t2,x2
+ MILLIRET
+ addc x1,t1,x1
+
+GSYM($$divI_10)
+ .export $$divI_10,millicode
+ comb,< x2,0,LREF(neg10)
+ copy 0,x1
+ extru x2,30,31,x2 /* divide by 2 */
+ addib,TR 1,x2,LREF(pos) /* add 1 (cannot overflow) */
+ sh1add x2,x2,x2 /* multiply by 3 to get started */
+
+LSYM(neg10)
+ subi 2,x2,x2 /* negate, divide by 2, and add 1 */
+ /* negation and adding 1 are done */
+ /* at the same time by the SUBI */
+ extru x2,30,31,x2
+ sh1add x2,x2,x2 /* multiply by 3 to get started */
+LSYM(neg)
+ shd x1,x2,28,t1 /* multiply by 0x11 */
+ shd x2,0,28,t2
+ add x2,t2,x2
+ addc x1,t1,x1
+LSYM(neg_for_17)
+ shd x1,x2,24,t1 /* multiply by 0x101 */
+ shd x2,0,24,t2
+ add x2,t2,x2
+ addc x1,t1,x1
+
+ shd x1,x2,16,t1 /* multiply by 0x10001 */
+ shd x2,0,16,t2
+ add x2,t2,x2
+ addc x1,t1,x1
+ MILLIRET
+ sub 0,x1,x1
+
+/* DIVISION BY 12 (shift to divide by 4 then divide by 3) */
+GSYM($$divI_12)
+ .export $$divI_12,millicode
+ comb,< x2,0,LREF(neg12)
+ copy 0,x1
+ extru x2,29,30,x2 /* divide by 4 */
+ addib,tr 1,x2,LREF(pos) /* compute 5*(x2+1) = 5*x2+5 */
+ sh2add x2,x2,x2 /* multiply by 5 to get started */
+
+LSYM(neg12)
+ subi 4,x2,x2 /* negate, divide by 4, and add 1 */
+ /* negation and adding 1 are done */
+ /* at the same time by the SUBI */
+ extru x2,29,30,x2
+ b LREF(neg)
+ sh2add x2,x2,x2 /* multiply by 5 to get started */
+
+GSYM($$divU_12)
+ .export $$divU_12,millicode
+ extru x2,29,30,x2 /* divide by 4 */
+ addi 5,x2,t1 /* cannot carry */
+ sh2add x2,t1,x2 /* multiply by 5 to get started */
+ b LREF(pos)
+ addc 0,0,x1
+
+/* DIVISION BY 15 (use z = 2**32; a = 11111111) */
+GSYM($$divI_15)
+ .export $$divI_15,millicode
+ comb,< x2,0,LREF(neg15)
+ copy 0,x1
+ addib,tr 1,x2,LREF(pos)+4
+ shd x1,x2,28,t1
+
+LSYM(neg15)
+ b LREF(neg)
+ subi 1,x2,x2
+
+GSYM($$divU_15)
+ .export $$divU_15,millicode
+ addi 1,x2,x2 /* this CAN overflow */
+ b LREF(pos)
+ addc 0,0,x1
+
+/* DIVISION BY 17 (use z = 2**32; a = f0f0f0f) */
+GSYM($$divI_17)
+ .export $$divI_17,millicode
+ comb,<,n x2,0,LREF(neg17)
+ addi 1,x2,x2 /* this cannot overflow */
+ shd 0,x2,28,t1 /* multiply by 0xf to get started */
+ shd x2,0,28,t2
+ sub t2,x2,x2
+ b LREF(pos_for_17)
+ subb t1,0,x1
+
+LSYM(neg17)
+ subi 1,x2,x2 /* this cannot overflow */
+ shd 0,x2,28,t1 /* multiply by 0xf to get started */
+ shd x2,0,28,t2
+ sub t2,x2,x2
+ b LREF(neg_for_17)
+ subb t1,0,x1
+
+GSYM($$divU_17)
+ .export $$divU_17,millicode
+ addi 1,x2,x2 /* this CAN overflow */
+ addc 0,0,x1
+ shd x1,x2,28,t1 /* multiply by 0xf to get started */
+LSYM(u17)
+ shd x2,0,28,t2
+ sub t2,x2,x2
+ b LREF(pos_for_17)
+ subb t1,x1,x1
+
+
+/* DIVISION BY DIVISORS OF FFFFFF, and powers of 2 times these
+ includes 7,9 and also 14
+
+
+ z = 2**24-1
+ r = z mod x = 0
+
+ so choose b = 0
+
+ Also, in order to divide by z = 2**24-1, we approximate by dividing
+ by (z+1) = 2**24 (which is easy), and then correcting.
+
+ (ax) = (z+1)q' + r
+ . = zq' + (q'+r)
+
+ So to compute (ax)/z, compute q' = (ax)/(z+1) and r = (ax) mod (z+1)
+ Then the true remainder of (ax)/z is (q'+r). Repeat the process
+ with this new remainder, adding the tentative quotients together,
+ until a tentative quotient is 0 (and then we are done). There is
+ one last correction to be done. It is possible that (q'+r) = z.
+ If so, then (q'+r)/(z+1) = 0 and it looks like we are done. But,
+ in fact, we need to add 1 more to the quotient. Now, it turns
+ out that this happens if and only if the original value x is
+ an exact multiple of y. So, to avoid a three instruction test at
+ the end, instead use 1 instruction to add 1 to x at the beginning. */
+
+/* DIVISION BY 7 (use z = 2**24-1; a = 249249) */
+GSYM($$divI_7)
+ .export $$divI_7,millicode
+ comb,<,n x2,0,LREF(neg7)
+LSYM(7)
+ addi 1,x2,x2 /* cannot overflow */
+ shd 0,x2,29,x1
+ sh3add x2,x2,x2
+ addc x1,0,x1
+LSYM(pos7)
+ shd x1,x2,26,t1
+ shd x2,0,26,t2
+ add x2,t2,x2
+ addc x1,t1,x1
+
+ shd x1,x2,20,t1
+ shd x2,0,20,t2
+ add x2,t2,x2
+ addc x1,t1,t1
+
+ /* computed <t1,x2>. Now divide it by (2**24 - 1) */
+
+ copy 0,x1
+ shd,= t1,x2,24,t1 /* tentative quotient */
+LSYM(1)
+ addb,tr t1,x1,LREF(2) /* add to previous quotient */
+ extru x2,31,24,x2 /* new remainder (unadjusted) */
+
+ MILLIRETN
+
+LSYM(2)
+ addb,tr t1,x2,LREF(1) /* adjust remainder */
+ extru,= x2,7,8,t1 /* new quotient */
+
+LSYM(neg7)
+ subi 1,x2,x2 /* negate x2 and add 1 */
+LSYM(8)
+ shd 0,x2,29,x1
+ sh3add x2,x2,x2
+ addc x1,0,x1
+
+LSYM(neg7_shift)
+ shd x1,x2,26,t1
+ shd x2,0,26,t2
+ add x2,t2,x2
+ addc x1,t1,x1
+
+ shd x1,x2,20,t1
+ shd x2,0,20,t2
+ add x2,t2,x2
+ addc x1,t1,t1
+
+ /* computed <t1,x2>. Now divide it by (2**24 - 1) */
+
+ copy 0,x1
+ shd,= t1,x2,24,t1 /* tentative quotient */
+LSYM(3)
+ addb,tr t1,x1,LREF(4) /* add to previous quotient */
+ extru x2,31,24,x2 /* new remainder (unadjusted) */
+
+ MILLIRET
+ sub 0,x1,x1 /* negate result */
+
+LSYM(4)
+ addb,tr t1,x2,LREF(3) /* adjust remainder */
+ extru,= x2,7,8,t1 /* new quotient */
+
+GSYM($$divU_7)
+ .export $$divU_7,millicode
+ addi 1,x2,x2 /* can carry */
+ addc 0,0,x1
+ shd x1,x2,29,t1
+ sh3add x2,x2,x2
+ b LREF(pos7)
+ addc t1,x1,x1
+
+/* DIVISION BY 9 (use z = 2**24-1; a = 1c71c7) */
+GSYM($$divI_9)
+ .export $$divI_9,millicode
+ comb,<,n x2,0,LREF(neg9)
+ addi 1,x2,x2 /* cannot overflow */
+ shd 0,x2,29,t1
+ shd x2,0,29,t2
+ sub t2,x2,x2
+ b LREF(pos7)
+ subb t1,0,x1
+
+LSYM(neg9)
+ subi 1,x2,x2 /* negate and add 1 */
+ shd 0,x2,29,t1
+ shd x2,0,29,t2
+ sub t2,x2,x2
+ b LREF(neg7_shift)
+ subb t1,0,x1
+
+GSYM($$divU_9)
+ .export $$divU_9,millicode
+ addi 1,x2,x2 /* can carry */
+ addc 0,0,x1
+ shd x1,x2,29,t1
+ shd x2,0,29,t2
+ sub t2,x2,x2
+ b LREF(pos7)
+ subb t1,x1,x1
+
+/* DIVISION BY 14 (shift to divide by 2 then divide by 7) */
+GSYM($$divI_14)
+ .export $$divI_14,millicode
+ comb,<,n x2,0,LREF(neg14)
+GSYM($$divU_14)
+ .export $$divU_14,millicode
+ b LREF(7) /* go to 7 case */
+ extru x2,30,31,x2 /* divide by 2 */
+
+LSYM(neg14)
+ subi 2,x2,x2 /* negate (and add 2) */
+ b LREF(8)
+ extru x2,30,31,x2 /* divide by 2 */
+ .exit
+ .procend
+ .end
+#endif
diff --git a/arch/parisc/lib/milli/dyncall.S b/arch/parisc/lib/milli/dyncall.S
new file mode 100644
index 000000000000..27f9ca558d0a
--- /dev/null
+++ b/arch/parisc/lib/milli/dyncall.S
@@ -0,0 +1,32 @@
+/* 32 and 64-bit millicode, original author Hewlett-Packard
+ adapted for gcc by Paul Bame <bame@debian.org>
+ and Alan Modra <alan@linuxcare.com.au>.
+
+ Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
+
+ This file is part of GCC and is released under the terms of
+ of the GNU General Public License as published by the Free Software
+ Foundation; either version 2, or (at your option) any later version.
+ See the file COPYING in the top-level GCC source directory for a copy
+ of the license. */
+
+#include "milli.h"
+
+#ifdef L_dyncall
+ SUBSPA_MILLI
+ ATTR_DATA
+GSYM($$dyncall)
+ .export $$dyncall,millicode
+ .proc
+ .callinfo millicode
+ .entry
+ bb,>=,n %r22,30,LREF(1) ; branch if not plabel address
+ depi 0,31,2,%r22 ; clear the two least significant bits
+ ldw 4(%r22),%r19 ; load new LTP value
+ ldw 0(%r22),%r22 ; load address of target
+LSYM(1)
+ bv %r0(%r22) ; branch to the real target
+ stw %r2,-24(%r30) ; save return address into frame marker
+ .exit
+ .procend
+#endif
diff --git a/arch/parisc/lib/milli/milli.S b/arch/parisc/lib/milli/milli.S
new file mode 100644
index 000000000000..47c6cde712e3
--- /dev/null
+++ b/arch/parisc/lib/milli/milli.S
@@ -0,0 +1,2071 @@
+/* 32 and 64-bit millicode, original author Hewlett-Packard
+ adapted for gcc by Paul Bame <bame@debian.org>
+ and Alan Modra <alan@linuxcare.com.au>.
+
+ Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
+
+ This file is part of GCC and is released under the terms of
+ of the GNU General Public License as published by the Free Software
+ Foundation; either version 2, or (at your option) any later version.
+ See the file COPYING in the top-level GCC source directory for a copy
+ of the license. */
+
+#ifdef CONFIG_64BIT
+ .level 2.0w
+#endif
+
+/* Hardware General Registers. */
+r0: .reg %r0
+r1: .reg %r1
+r2: .reg %r2
+r3: .reg %r3
+r4: .reg %r4
+r5: .reg %r5
+r6: .reg %r6
+r7: .reg %r7
+r8: .reg %r8
+r9: .reg %r9
+r10: .reg %r10
+r11: .reg %r11
+r12: .reg %r12
+r13: .reg %r13
+r14: .reg %r14
+r15: .reg %r15
+r16: .reg %r16
+r17: .reg %r17
+r18: .reg %r18
+r19: .reg %r19
+r20: .reg %r20
+r21: .reg %r21
+r22: .reg %r22
+r23: .reg %r23
+r24: .reg %r24
+r25: .reg %r25
+r26: .reg %r26
+r27: .reg %r27
+r28: .reg %r28
+r29: .reg %r29
+r30: .reg %r30
+r31: .reg %r31
+
+/* Hardware Space Registers. */
+sr0: .reg %sr0
+sr1: .reg %sr1
+sr2: .reg %sr2
+sr3: .reg %sr3
+sr4: .reg %sr4
+sr5: .reg %sr5
+sr6: .reg %sr6
+sr7: .reg %sr7
+
+/* Hardware Floating Point Registers. */
+fr0: .reg %fr0
+fr1: .reg %fr1
+fr2: .reg %fr2
+fr3: .reg %fr3
+fr4: .reg %fr4
+fr5: .reg %fr5
+fr6: .reg %fr6
+fr7: .reg %fr7
+fr8: .reg %fr8
+fr9: .reg %fr9
+fr10: .reg %fr10
+fr11: .reg %fr11
+fr12: .reg %fr12
+fr13: .reg %fr13
+fr14: .reg %fr14
+fr15: .reg %fr15
+
+/* Hardware Control Registers. */
+cr11: .reg %cr11
+sar: .reg %cr11 /* Shift Amount Register */
+
+/* Software Architecture General Registers. */
+rp: .reg r2 /* return pointer */
+#ifdef CONFIG_64BIT
+mrp: .reg r2 /* millicode return pointer */
+#else
+mrp: .reg r31 /* millicode return pointer */
+#endif
+ret0: .reg r28 /* return value */
+ret1: .reg r29 /* return value (high part of double) */
+sp: .reg r30 /* stack pointer */
+dp: .reg r27 /* data pointer */
+arg0: .reg r26 /* argument */
+arg1: .reg r25 /* argument or high part of double argument */
+arg2: .reg r24 /* argument */
+arg3: .reg r23 /* argument or high part of double argument */
+
+/* Software Architecture Space Registers. */
+/* sr0 ; return link from BLE */
+sret: .reg sr1 /* return value */
+sarg: .reg sr1 /* argument */
+/* sr4 ; PC SPACE tracker */
+/* sr5 ; process private data */
+
+/* Frame Offsets (millicode convention!) Used when calling other
+ millicode routines. Stack unwinding is dependent upon these
+ definitions. */
+r31_slot: .equ -20 /* "current RP" slot */
+sr0_slot: .equ -16 /* "static link" slot */
+#if defined(CONFIG_64BIT)
+mrp_slot: .equ -16 /* "current RP" slot */
+psp_slot: .equ -8 /* "previous SP" slot */
+#else
+mrp_slot: .equ -20 /* "current RP" slot (replacing "r31_slot") */
+#endif
+
+
+#define DEFINE(name,value)name: .EQU value
+#define RDEFINE(name,value)name: .REG value
+#ifdef milliext
+#define MILLI_BE(lbl) BE lbl(sr7,r0)
+#define MILLI_BEN(lbl) BE,n lbl(sr7,r0)
+#define MILLI_BLE(lbl) BLE lbl(sr7,r0)
+#define MILLI_BLEN(lbl) BLE,n lbl(sr7,r0)
+#define MILLIRETN BE,n 0(sr0,mrp)
+#define MILLIRET BE 0(sr0,mrp)
+#define MILLI_RETN BE,n 0(sr0,mrp)
+#define MILLI_RET BE 0(sr0,mrp)
+#else
+#define MILLI_BE(lbl) B lbl
+#define MILLI_BEN(lbl) B,n lbl
+#define MILLI_BLE(lbl) BL lbl,mrp
+#define MILLI_BLEN(lbl) BL,n lbl,mrp
+#define MILLIRETN BV,n 0(mrp)
+#define MILLIRET BV 0(mrp)
+#define MILLI_RETN BV,n 0(mrp)
+#define MILLI_RET BV 0(mrp)
+#endif
+
+#define CAT(a,b) a##b
+
+#define SUBSPA_MILLI .section .text
+#define SUBSPA_MILLI_DIV .section .text.div,"ax",@progbits! .align 16
+#define SUBSPA_MILLI_MUL .section .text.mul,"ax",@progbits! .align 16
+#define ATTR_MILLI
+#define SUBSPA_DATA .section .data
+#define ATTR_DATA
+#define GLOBAL $global$
+#define GSYM(sym) !sym:
+#define LSYM(sym) !CAT(.L,sym:)
+#define LREF(sym) CAT(.L,sym)
+
+#ifdef L_dyncall
+ SUBSPA_MILLI
+ ATTR_DATA
+GSYM($$dyncall)
+ .export $$dyncall,millicode
+ .proc
+ .callinfo millicode
+ .entry
+ bb,>=,n %r22,30,LREF(1) ; branch if not plabel address
+ depi 0,31,2,%r22 ; clear the two least significant bits
+ ldw 4(%r22),%r19 ; load new LTP value
+ ldw 0(%r22),%r22 ; load address of target
+LSYM(1)
+ bv %r0(%r22) ; branch to the real target
+ stw %r2,-24(%r30) ; save return address into frame marker
+ .exit
+ .procend
+#endif
+
+#ifdef L_divI
+/* ROUTINES: $$divI, $$divoI
+
+ Single precision divide for signed binary integers.
+
+ The quotient is truncated towards zero.
+ The sign of the quotient is the XOR of the signs of the dividend and
+ divisor.
+ Divide by zero is trapped.
+ Divide of -2**31 by -1 is trapped for $$divoI but not for $$divI.
+
+ INPUT REGISTERS:
+ . arg0 == dividend
+ . arg1 == divisor
+ . mrp == return pc
+ . sr0 == return space when called externally
+
+ OUTPUT REGISTERS:
+ . arg0 = undefined
+ . arg1 = undefined
+ . ret1 = quotient
+
+ OTHER REGISTERS AFFECTED:
+ . r1 = undefined
+
+ SIDE EFFECTS:
+ . Causes a trap under the following conditions:
+ . divisor is zero (traps with ADDIT,= 0,25,0)
+ . dividend==-2**31 and divisor==-1 and routine is $$divoI
+ . (traps with ADDO 26,25,0)
+ . Changes memory at the following places:
+ . NONE
+
+ PERMISSIBLE CONTEXT:
+ . Unwindable.
+ . Suitable for internal or external millicode.
+ . Assumes the special millicode register conventions.
+
+ DISCUSSION:
+ . Branchs to other millicode routines using BE
+ . $$div_# for # being 2,3,4,5,6,7,8,9,10,12,14,15
+ .
+ . For selected divisors, calls a divide by constant routine written by
+ . Karl Pettis. Eligible divisors are 1..15 excluding 11 and 13.
+ .
+ . The only overflow case is -2**31 divided by -1.
+ . Both routines return -2**31 but only $$divoI traps. */
+
+RDEFINE(temp,r1)
+RDEFINE(retreg,ret1) /* r29 */
+RDEFINE(temp1,arg0)
+ SUBSPA_MILLI_DIV
+ ATTR_MILLI
+ .import $$divI_2,millicode
+ .import $$divI_3,millicode
+ .import $$divI_4,millicode
+ .import $$divI_5,millicode
+ .import $$divI_6,millicode
+ .import $$divI_7,millicode
+ .import $$divI_8,millicode
+ .import $$divI_9,millicode
+ .import $$divI_10,millicode
+ .import $$divI_12,millicode
+ .import $$divI_14,millicode
+ .import $$divI_15,millicode
+ .export $$divI,millicode
+ .export $$divoI,millicode
+ .proc
+ .callinfo millicode
+ .entry
+GSYM($$divoI)
+ comib,=,n -1,arg1,LREF(negative1) /* when divisor == -1 */
+GSYM($$divI)
+ ldo -1(arg1),temp /* is there at most one bit set ? */
+ and,<> arg1,temp,r0 /* if not, don't use power of 2 divide */
+ addi,> 0,arg1,r0 /* if divisor > 0, use power of 2 divide */
+ b,n LREF(neg_denom)
+LSYM(pow2)
+ addi,>= 0,arg0,retreg /* if numerator is negative, add the */
+ add arg0,temp,retreg /* (denominaotr -1) to correct for shifts */
+ extru,= arg1,15,16,temp /* test denominator with 0xffff0000 */
+ extrs retreg,15,16,retreg /* retreg = retreg >> 16 */
+ or arg1,temp,arg1 /* arg1 = arg1 | (arg1 >> 16) */
+ ldi 0xcc,temp1 /* setup 0xcc in temp1 */
+ extru,= arg1,23,8,temp /* test denominator with 0xff00 */
+ extrs retreg,23,24,retreg /* retreg = retreg >> 8 */
+ or arg1,temp,arg1 /* arg1 = arg1 | (arg1 >> 8) */
+ ldi 0xaa,temp /* setup 0xaa in temp */
+ extru,= arg1,27,4,r0 /* test denominator with 0xf0 */
+ extrs retreg,27,28,retreg /* retreg = retreg >> 4 */
+ and,= arg1,temp1,r0 /* test denominator with 0xcc */
+ extrs retreg,29,30,retreg /* retreg = retreg >> 2 */
+ and,= arg1,temp,r0 /* test denominator with 0xaa */
+ extrs retreg,30,31,retreg /* retreg = retreg >> 1 */
+ MILLIRETN
+LSYM(neg_denom)
+ addi,< 0,arg1,r0 /* if arg1 >= 0, it's not power of 2 */
+ b,n LREF(regular_seq)
+ sub r0,arg1,temp /* make denominator positive */
+ comb,=,n arg1,temp,LREF(regular_seq) /* test against 0x80000000 and 0 */
+ ldo -1(temp),retreg /* is there at most one bit set ? */
+ and,= temp,retreg,r0 /* if so, the denominator is power of 2 */
+ b,n LREF(regular_seq)
+ sub r0,arg0,retreg /* negate numerator */
+ comb,=,n arg0,retreg,LREF(regular_seq) /* test against 0x80000000 */
+ copy retreg,arg0 /* set up arg0, arg1 and temp */
+ copy temp,arg1 /* before branching to pow2 */
+ b LREF(pow2)
+ ldo -1(arg1),temp
+LSYM(regular_seq)
+ comib,>>=,n 15,arg1,LREF(small_divisor)
+ add,>= 0,arg0,retreg /* move dividend, if retreg < 0, */
+LSYM(normal)
+ subi 0,retreg,retreg /* make it positive */
+ sub 0,arg1,temp /* clear carry, */
+ /* negate the divisor */
+ ds 0,temp,0 /* set V-bit to the comple- */
+ /* ment of the divisor sign */
+ add retreg,retreg,retreg /* shift msb bit into carry */
+ ds r0,arg1,temp /* 1st divide step, if no carry */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 2nd divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 3rd divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 4th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 5th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 6th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 7th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 8th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 9th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 10th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 11th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 12th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 13th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 14th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 15th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 16th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 17th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 18th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 19th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 20th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 21st divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 22nd divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 23rd divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 24th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 25th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 26th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 27th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 28th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 29th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 30th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 31st divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 32nd divide step, */
+ addc retreg,retreg,retreg /* shift last retreg bit into retreg */
+ xor,>= arg0,arg1,0 /* get correct sign of quotient */
+ sub 0,retreg,retreg /* based on operand signs */
+ MILLIRETN
+ nop
+
+LSYM(small_divisor)
+
+#if defined(CONFIG_64BIT)
+/* Clear the upper 32 bits of the arg1 register. We are working with */
+/* small divisors (and 32-bit integers) We must not be mislead */
+/* by "1" bits left in the upper 32 bits. */
+ depd %r0,31,32,%r25
+#endif
+ blr,n arg1,r0
+ nop
+/* table for divisor == 0,1, ... ,15 */
+ addit,= 0,arg1,r0 /* trap if divisor == 0 */
+ nop
+ MILLIRET /* divisor == 1 */
+ copy arg0,retreg
+ MILLI_BEN($$divI_2) /* divisor == 2 */
+ nop
+ MILLI_BEN($$divI_3) /* divisor == 3 */
+ nop
+ MILLI_BEN($$divI_4) /* divisor == 4 */
+ nop
+ MILLI_BEN($$divI_5) /* divisor == 5 */
+ nop
+ MILLI_BEN($$divI_6) /* divisor == 6 */
+ nop
+ MILLI_BEN($$divI_7) /* divisor == 7 */
+ nop
+ MILLI_BEN($$divI_8) /* divisor == 8 */
+ nop
+ MILLI_BEN($$divI_9) /* divisor == 9 */
+ nop
+ MILLI_BEN($$divI_10) /* divisor == 10 */
+ nop
+ b LREF(normal) /* divisor == 11 */
+ add,>= 0,arg0,retreg
+ MILLI_BEN($$divI_12) /* divisor == 12 */
+ nop
+ b LREF(normal) /* divisor == 13 */
+ add,>= 0,arg0,retreg
+ MILLI_BEN($$divI_14) /* divisor == 14 */
+ nop
+ MILLI_BEN($$divI_15) /* divisor == 15 */
+ nop
+
+LSYM(negative1)
+ sub 0,arg0,retreg /* result is negation of dividend */
+ MILLIRET
+ addo arg0,arg1,r0 /* trap iff dividend==0x80000000 && divisor==-1 */
+ .exit
+ .procend
+ .end
+#endif
+
+#ifdef L_divU
+/* ROUTINE: $$divU
+ .
+ . Single precision divide for unsigned integers.
+ .
+ . Quotient is truncated towards zero.
+ . Traps on divide by zero.
+
+ INPUT REGISTERS:
+ . arg0 == dividend
+ . arg1 == divisor
+ . mrp == return pc
+ . sr0 == return space when called externally
+
+ OUTPUT REGISTERS:
+ . arg0 = undefined
+ . arg1 = undefined
+ . ret1 = quotient
+
+ OTHER REGISTERS AFFECTED:
+ . r1 = undefined
+
+ SIDE EFFECTS:
+ . Causes a trap under the following conditions:
+ . divisor is zero
+ . Changes memory at the following places:
+ . NONE
+
+ PERMISSIBLE CONTEXT:
+ . Unwindable.
+ . Does not create a stack frame.
+ . Suitable for internal or external millicode.
+ . Assumes the special millicode register conventions.
+
+ DISCUSSION:
+ . Branchs to other millicode routines using BE:
+ . $$divU_# for 3,5,6,7,9,10,12,14,15
+ .
+ . For selected small divisors calls the special divide by constant
+ . routines written by Karl Pettis. These are: 3,5,6,7,9,10,12,14,15. */
+
+RDEFINE(temp,r1)
+RDEFINE(retreg,ret1) /* r29 */
+RDEFINE(temp1,arg0)
+ SUBSPA_MILLI_DIV
+ ATTR_MILLI
+ .export $$divU,millicode
+ .import $$divU_3,millicode
+ .import $$divU_5,millicode
+ .import $$divU_6,millicode
+ .import $$divU_7,millicode
+ .import $$divU_9,millicode
+ .import $$divU_10,millicode
+ .import $$divU_12,millicode
+ .import $$divU_14,millicode
+ .import $$divU_15,millicode
+ .proc
+ .callinfo millicode
+ .entry
+GSYM($$divU)
+/* The subtract is not nullified since it does no harm and can be used
+ by the two cases that branch back to "normal". */
+ ldo -1(arg1),temp /* is there at most one bit set ? */
+ and,= arg1,temp,r0 /* if so, denominator is power of 2 */
+ b LREF(regular_seq)
+ addit,= 0,arg1,0 /* trap for zero dvr */
+ copy arg0,retreg
+ extru,= arg1,15,16,temp /* test denominator with 0xffff0000 */
+ extru retreg,15,16,retreg /* retreg = retreg >> 16 */
+ or arg1,temp,arg1 /* arg1 = arg1 | (arg1 >> 16) */
+ ldi 0xcc,temp1 /* setup 0xcc in temp1 */
+ extru,= arg1,23,8,temp /* test denominator with 0xff00 */
+ extru retreg,23,24,retreg /* retreg = retreg >> 8 */
+ or arg1,temp,arg1 /* arg1 = arg1 | (arg1 >> 8) */
+ ldi 0xaa,temp /* setup 0xaa in temp */
+ extru,= arg1,27,4,r0 /* test denominator with 0xf0 */
+ extru retreg,27,28,retreg /* retreg = retreg >> 4 */
+ and,= arg1,temp1,r0 /* test denominator with 0xcc */
+ extru retreg,29,30,retreg /* retreg = retreg >> 2 */
+ and,= arg1,temp,r0 /* test denominator with 0xaa */
+ extru retreg,30,31,retreg /* retreg = retreg >> 1 */
+ MILLIRETN
+ nop
+LSYM(regular_seq)
+ comib,>= 15,arg1,LREF(special_divisor)
+ subi 0,arg1,temp /* clear carry, negate the divisor */
+ ds r0,temp,r0 /* set V-bit to 1 */
+LSYM(normal)
+ add arg0,arg0,retreg /* shift msb bit into carry */
+ ds r0,arg1,temp /* 1st divide step, if no carry */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 2nd divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 3rd divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 4th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 5th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 6th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 7th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 8th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 9th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 10th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 11th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 12th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 13th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 14th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 15th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 16th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 17th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 18th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 19th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 20th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 21st divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 22nd divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 23rd divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 24th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 25th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 26th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 27th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 28th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 29th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 30th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 31st divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds temp,arg1,temp /* 32nd divide step, */
+ MILLIRET
+ addc retreg,retreg,retreg /* shift last retreg bit into retreg */
+
+/* Handle the cases where divisor is a small constant or has high bit on. */
+LSYM(special_divisor)
+/* blr arg1,r0 */
+/* comib,>,n 0,arg1,LREF(big_divisor) ; nullify previous instruction */
+
+/* Pratap 8/13/90. The 815 Stirling chip set has a bug that prevents us from
+ generating such a blr, comib sequence. A problem in nullification. So I
+ rewrote this code. */
+
+#if defined(CONFIG_64BIT)
+/* Clear the upper 32 bits of the arg1 register. We are working with
+ small divisors (and 32-bit unsigned integers) We must not be mislead
+ by "1" bits left in the upper 32 bits. */
+ depd %r0,31,32,%r25
+#endif
+ comib,> 0,arg1,LREF(big_divisor)
+ nop
+ blr arg1,r0
+ nop
+
+LSYM(zero_divisor) /* this label is here to provide external visibility */
+ addit,= 0,arg1,0 /* trap for zero dvr */
+ nop
+ MILLIRET /* divisor == 1 */
+ copy arg0,retreg
+ MILLIRET /* divisor == 2 */
+ extru arg0,30,31,retreg
+ MILLI_BEN($$divU_3) /* divisor == 3 */
+ nop
+ MILLIRET /* divisor == 4 */
+ extru arg0,29,30,retreg
+ MILLI_BEN($$divU_5) /* divisor == 5 */
+ nop
+ MILLI_BEN($$divU_6) /* divisor == 6 */
+ nop
+ MILLI_BEN($$divU_7) /* divisor == 7 */
+ nop
+ MILLIRET /* divisor == 8 */
+ extru arg0,28,29,retreg
+ MILLI_BEN($$divU_9) /* divisor == 9 */
+ nop
+ MILLI_BEN($$divU_10) /* divisor == 10 */
+ nop
+ b LREF(normal) /* divisor == 11 */
+ ds r0,temp,r0 /* set V-bit to 1 */
+ MILLI_BEN($$divU_12) /* divisor == 12 */
+ nop
+ b LREF(normal) /* divisor == 13 */
+ ds r0,temp,r0 /* set V-bit to 1 */
+ MILLI_BEN($$divU_14) /* divisor == 14 */
+ nop
+ MILLI_BEN($$divU_15) /* divisor == 15 */
+ nop
+
+/* Handle the case where the high bit is on in the divisor.
+ Compute: if( dividend>=divisor) quotient=1; else quotient=0;
+ Note: dividend>==divisor iff dividend-divisor does not borrow
+ and not borrow iff carry. */
+LSYM(big_divisor)
+ sub arg0,arg1,r0
+ MILLIRET
+ addc r0,r0,retreg
+ .exit
+ .procend
+ .end
+#endif
+
+#ifdef L_remI
+/* ROUTINE: $$remI
+
+ DESCRIPTION:
+ . $$remI returns the remainder of the division of two signed 32-bit
+ . integers. The sign of the remainder is the same as the sign of
+ . the dividend.
+
+
+ INPUT REGISTERS:
+ . arg0 == dividend
+ . arg1 == divisor
+ . mrp == return pc
+ . sr0 == return space when called externally
+
+ OUTPUT REGISTERS:
+ . arg0 = destroyed
+ . arg1 = destroyed
+ . ret1 = remainder
+
+ OTHER REGISTERS AFFECTED:
+ . r1 = undefined
+
+ SIDE EFFECTS:
+ . Causes a trap under the following conditions: DIVIDE BY ZERO
+ . Changes memory at the following places: NONE
+
+ PERMISSIBLE CONTEXT:
+ . Unwindable
+ . Does not create a stack frame
+ . Is usable for internal or external microcode
+
+ DISCUSSION:
+ . Calls other millicode routines via mrp: NONE
+ . Calls other millicode routines: NONE */
+
+RDEFINE(tmp,r1)
+RDEFINE(retreg,ret1)
+
+ SUBSPA_MILLI
+ ATTR_MILLI
+ .proc
+ .callinfo millicode
+ .entry
+GSYM($$remI)
+GSYM($$remoI)
+ .export $$remI,MILLICODE
+ .export $$remoI,MILLICODE
+ ldo -1(arg1),tmp /* is there at most one bit set ? */
+ and,<> arg1,tmp,r0 /* if not, don't use power of 2 */
+ addi,> 0,arg1,r0 /* if denominator > 0, use power */
+ /* of 2 */
+ b,n LREF(neg_denom)
+LSYM(pow2)
+ comb,>,n 0,arg0,LREF(neg_num) /* is numerator < 0 ? */
+ and arg0,tmp,retreg /* get the result */
+ MILLIRETN
+LSYM(neg_num)
+ subi 0,arg0,arg0 /* negate numerator */
+ and arg0,tmp,retreg /* get the result */
+ subi 0,retreg,retreg /* negate result */
+ MILLIRETN
+LSYM(neg_denom)
+ addi,< 0,arg1,r0 /* if arg1 >= 0, it's not power */
+ /* of 2 */
+ b,n LREF(regular_seq)
+ sub r0,arg1,tmp /* make denominator positive */
+ comb,=,n arg1,tmp,LREF(regular_seq) /* test against 0x80000000 and 0 */
+ ldo -1(tmp),retreg /* is there at most one bit set ? */
+ and,= tmp,retreg,r0 /* if not, go to regular_seq */
+ b,n LREF(regular_seq)
+ comb,>,n 0,arg0,LREF(neg_num_2) /* if arg0 < 0, negate it */
+ and arg0,retreg,retreg
+ MILLIRETN
+LSYM(neg_num_2)
+ subi 0,arg0,tmp /* test against 0x80000000 */
+ and tmp,retreg,retreg
+ subi 0,retreg,retreg
+ MILLIRETN
+LSYM(regular_seq)
+ addit,= 0,arg1,0 /* trap if div by zero */
+ add,>= 0,arg0,retreg /* move dividend, if retreg < 0, */
+ sub 0,retreg,retreg /* make it positive */
+ sub 0,arg1, tmp /* clear carry, */
+ /* negate the divisor */
+ ds 0, tmp,0 /* set V-bit to the comple- */
+ /* ment of the divisor sign */
+ or 0,0, tmp /* clear tmp */
+ add retreg,retreg,retreg /* shift msb bit into carry */
+ ds tmp,arg1, tmp /* 1st divide step, if no carry */
+ /* out, msb of quotient = 0 */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+LSYM(t1)
+ ds tmp,arg1, tmp /* 2nd divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 3rd divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 4th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 5th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 6th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 7th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 8th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 9th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 10th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 11th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 12th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 13th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 14th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 15th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 16th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 17th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 18th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 19th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 20th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 21st divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 22nd divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 23rd divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 24th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 25th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 26th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 27th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 28th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 29th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 30th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 31st divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 32nd divide step, */
+ addc retreg,retreg,retreg /* shift last bit into retreg */
+ movb,>=,n tmp,retreg,LREF(finish) /* branch if pos. tmp */
+ add,< arg1,0,0 /* if arg1 > 0, add arg1 */
+ add,tr tmp,arg1,retreg /* for correcting remainder tmp */
+ sub tmp,arg1,retreg /* else add absolute value arg1 */
+LSYM(finish)
+ add,>= arg0,0,0 /* set sign of remainder */
+ sub 0,retreg,retreg /* to sign of dividend */
+ MILLIRET
+ nop
+ .exit
+ .procend
+#ifdef milliext
+ .origin 0x00000200
+#endif
+ .end
+#endif
+
+#ifdef L_remU
+/* ROUTINE: $$remU
+ . Single precision divide for remainder with unsigned binary integers.
+ .
+ . The remainder must be dividend-(dividend/divisor)*divisor.
+ . Divide by zero is trapped.
+
+ INPUT REGISTERS:
+ . arg0 == dividend
+ . arg1 == divisor
+ . mrp == return pc
+ . sr0 == return space when called externally
+
+ OUTPUT REGISTERS:
+ . arg0 = undefined
+ . arg1 = undefined
+ . ret1 = remainder
+
+ OTHER REGISTERS AFFECTED:
+ . r1 = undefined
+
+ SIDE EFFECTS:
+ . Causes a trap under the following conditions: DIVIDE BY ZERO
+ . Changes memory at the following places: NONE
+
+ PERMISSIBLE CONTEXT:
+ . Unwindable.
+ . Does not create a stack frame.
+ . Suitable for internal or external millicode.
+ . Assumes the special millicode register conventions.
+
+ DISCUSSION:
+ . Calls other millicode routines using mrp: NONE
+ . Calls other millicode routines: NONE */
+
+
+RDEFINE(temp,r1)
+RDEFINE(rmndr,ret1) /* r29 */
+ SUBSPA_MILLI
+ ATTR_MILLI
+ .export $$remU,millicode
+ .proc
+ .callinfo millicode
+ .entry
+GSYM($$remU)
+ ldo -1(arg1),temp /* is there at most one bit set ? */
+ and,= arg1,temp,r0 /* if not, don't use power of 2 */
+ b LREF(regular_seq)
+ addit,= 0,arg1,r0 /* trap on div by zero */
+ and arg0,temp,rmndr /* get the result for power of 2 */
+ MILLIRETN
+LSYM(regular_seq)
+ comib,>=,n 0,arg1,LREF(special_case)
+ subi 0,arg1,rmndr /* clear carry, negate the divisor */
+ ds r0,rmndr,r0 /* set V-bit to 1 */
+ add arg0,arg0,temp /* shift msb bit into carry */
+ ds r0,arg1,rmndr /* 1st divide step, if no carry */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 2nd divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 3rd divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 4th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 5th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 6th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 7th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 8th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 9th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 10th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 11th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 12th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 13th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 14th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 15th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 16th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 17th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 18th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 19th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 20th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 21st divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 22nd divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 23rd divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 24th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 25th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 26th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 27th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 28th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 29th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 30th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 31st divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 32nd divide step, */
+ comiclr,<= 0,rmndr,r0
+ add rmndr,arg1,rmndr /* correction */
+ MILLIRETN
+ nop
+
+/* Putting >= on the last DS and deleting COMICLR does not work! */
+LSYM(special_case)
+ sub,>>= arg0,arg1,rmndr
+ copy arg0,rmndr
+ MILLIRETN
+ nop
+ .exit
+ .procend
+ .end
+#endif
+
+#ifdef L_div_const
+/* ROUTINE: $$divI_2
+ . $$divI_3 $$divU_3
+ . $$divI_4
+ . $$divI_5 $$divU_5
+ . $$divI_6 $$divU_6
+ . $$divI_7 $$divU_7
+ . $$divI_8
+ . $$divI_9 $$divU_9
+ . $$divI_10 $$divU_10
+ .
+ . $$divI_12 $$divU_12
+ .
+ . $$divI_14 $$divU_14
+ . $$divI_15 $$divU_15
+ . $$divI_16
+ . $$divI_17 $$divU_17
+ .
+ . Divide by selected constants for single precision binary integers.
+
+ INPUT REGISTERS:
+ . arg0 == dividend
+ . mrp == return pc
+ . sr0 == return space when called externally
+
+ OUTPUT REGISTERS:
+ . arg0 = undefined
+ . arg1 = undefined
+ . ret1 = quotient
+
+ OTHER REGISTERS AFFECTED:
+ . r1 = undefined
+
+ SIDE EFFECTS:
+ . Causes a trap under the following conditions: NONE
+ . Changes memory at the following places: NONE
+
+ PERMISSIBLE CONTEXT:
+ . Unwindable.
+ . Does not create a stack frame.
+ . Suitable for internal or external millicode.
+ . Assumes the special millicode register conventions.
+
+ DISCUSSION:
+ . Calls other millicode routines using mrp: NONE
+ . Calls other millicode routines: NONE */
+
+
+/* TRUNCATED DIVISION BY SMALL INTEGERS
+
+ We are interested in q(x) = floor(x/y), where x >= 0 and y > 0
+ (with y fixed).
+
+ Let a = floor(z/y), for some choice of z. Note that z will be
+ chosen so that division by z is cheap.
+
+ Let r be the remainder(z/y). In other words, r = z - ay.
+
+ Now, our method is to choose a value for b such that
+
+ q'(x) = floor((ax+b)/z)
+
+ is equal to q(x) over as large a range of x as possible. If the
+ two are equal over a sufficiently large range, and if it is easy to
+ form the product (ax), and it is easy to divide by z, then we can
+ perform the division much faster than the general division algorithm.
+
+ So, we want the following to be true:
+
+ . For x in the following range:
+ .
+ . ky <= x < (k+1)y
+ .
+ . implies that
+ .
+ . k <= (ax+b)/z < (k+1)
+
+ We want to determine b such that this is true for all k in the
+ range {0..K} for some maximum K.
+
+ Since (ax+b) is an increasing function of x, we can take each
+ bound separately to determine the "best" value for b.
+
+ (ax+b)/z < (k+1) implies
+
+ (a((k+1)y-1)+b < (k+1)z implies
+
+ b < a + (k+1)(z-ay) implies
+
+ b < a + (k+1)r
+
+ This needs to be true for all k in the range {0..K}. In
+ particular, it is true for k = 0 and this leads to a maximum
+ acceptable value for b.
+
+ b < a+r or b <= a+r-1
+
+ Taking the other bound, we have
+
+ k <= (ax+b)/z implies
+
+ k <= (aky+b)/z implies
+
+ k(z-ay) <= b implies
+
+ kr <= b
+
+ Clearly, the largest range for k will be achieved by maximizing b,
+ when r is not zero. When r is zero, then the simplest choice for b
+ is 0. When r is not 0, set
+
+ . b = a+r-1
+
+ Now, by construction, q'(x) = floor((ax+b)/z) = q(x) = floor(x/y)
+ for all x in the range:
+
+ . 0 <= x < (K+1)y
+
+ We need to determine what K is. Of our two bounds,
+
+ . b < a+(k+1)r is satisfied for all k >= 0, by construction.
+
+ The other bound is
+
+ . kr <= b
+
+ This is always true if r = 0. If r is not 0 (the usual case), then
+ K = floor((a+r-1)/r), is the maximum value for k.
+
+ Therefore, the formula q'(x) = floor((ax+b)/z) yields the correct
+ answer for q(x) = floor(x/y) when x is in the range
+
+ (0,(K+1)y-1) K = floor((a+r-1)/r)
+
+ To be most useful, we want (K+1)y-1 = (max x) >= 2**32-1 so that
+ the formula for q'(x) yields the correct value of q(x) for all x
+ representable by a single word in HPPA.
+
+ We are also constrained in that computing the product (ax), adding
+ b, and dividing by z must all be done quickly, otherwise we will be
+ better off going through the general algorithm using the DS
+ instruction, which uses approximately 70 cycles.
+
+ For each y, there is a choice of z which satisfies the constraints
+ for (K+1)y >= 2**32. We may not, however, be able to satisfy the
+ timing constraints for arbitrary y. It seems that z being equal to
+ a power of 2 or a power of 2 minus 1 is as good as we can do, since
+ it minimizes the time to do division by z. We want the choice of z
+ to also result in a value for (a) that minimizes the computation of
+ the product (ax). This is best achieved if (a) has a regular bit
+ pattern (so the multiplication can be done with shifts and adds).
+ The value of (a) also needs to be less than 2**32 so the product is
+ always guaranteed to fit in 2 words.
+
+ In actual practice, the following should be done:
+
+ 1) For negative x, you should take the absolute value and remember
+ . the fact so that the result can be negated. This obviously does
+ . not apply in the unsigned case.
+ 2) For even y, you should factor out the power of 2 that divides y
+ . and divide x by it. You can then proceed by dividing by the
+ . odd factor of y.
+
+ Here is a table of some odd values of y, and corresponding choices
+ for z which are "good".
+
+ y z r a (hex) max x (hex)
+
+ 3 2**32 1 55555555 100000001
+ 5 2**32 1 33333333 100000003
+ 7 2**24-1 0 249249 (infinite)
+ 9 2**24-1 0 1c71c7 (infinite)
+ 11 2**20-1 0 1745d (infinite)
+ 13 2**24-1 0 13b13b (infinite)
+ 15 2**32 1 11111111 10000000d
+ 17 2**32 1 f0f0f0f 10000000f
+
+ If r is 1, then b = a+r-1 = a. This simplifies the computation
+ of (ax+b), since you can compute (x+1)(a) instead. If r is 0,
+ then b = 0 is ok to use which simplifies (ax+b).
+
+ The bit patterns for 55555555, 33333333, and 11111111 are obviously
+ very regular. The bit patterns for the other values of a above are:
+
+ y (hex) (binary)
+
+ 7 249249 001001001001001001001001 << regular >>
+ 9 1c71c7 000111000111000111000111 << regular >>
+ 11 1745d 000000010111010001011101 << irregular >>
+ 13 13b13b 000100111011000100111011 << irregular >>
+
+ The bit patterns for (a) corresponding to (y) of 11 and 13 may be
+ too irregular to warrant using this method.
+
+ When z is a power of 2 minus 1, then the division by z is slightly
+ more complicated, involving an iterative solution.
+
+ The code presented here solves division by 1 through 17, except for
+ 11 and 13. There are algorithms for both signed and unsigned
+ quantities given.
+
+ TIMINGS (cycles)
+
+ divisor positive negative unsigned
+
+ . 1 2 2 2
+ . 2 4 4 2
+ . 3 19 21 19
+ . 4 4 4 2
+ . 5 18 22 19
+ . 6 19 22 19
+ . 8 4 4 2
+ . 10 18 19 17
+ . 12 18 20 18
+ . 15 16 18 16
+ . 16 4 4 2
+ . 17 16 18 16
+
+ Now, the algorithm for 7, 9, and 14 is an iterative one. That is,
+ a loop body is executed until the tentative quotient is 0. The
+ number of times the loop body is executed varies depending on the
+ dividend, but is never more than two times. If the dividend is
+ less than the divisor, then the loop body is not executed at all.
+ Each iteration adds 4 cycles to the timings.
+
+ divisor positive negative unsigned
+
+ . 7 19+4n 20+4n 20+4n n = number of iterations
+ . 9 21+4n 22+4n 21+4n
+ . 14 21+4n 22+4n 20+4n
+
+ To give an idea of how the number of iterations varies, here is a
+ table of dividend versus number of iterations when dividing by 7.
+
+ smallest largest required
+ dividend dividend iterations
+
+ . 0 6 0
+ . 7 0x6ffffff 1
+ 0x1000006 0xffffffff 2
+
+ There is some overlap in the range of numbers requiring 1 and 2
+ iterations. */
+
+RDEFINE(t2,r1)
+RDEFINE(x2,arg0) /* r26 */
+RDEFINE(t1,arg1) /* r25 */
+RDEFINE(x1,ret1) /* r29 */
+
+ SUBSPA_MILLI_DIV
+ ATTR_MILLI
+
+ .proc
+ .callinfo millicode
+ .entry
+/* NONE of these routines require a stack frame
+ ALL of these routines are unwindable from millicode */
+
+GSYM($$divide_by_constant)
+ .export $$divide_by_constant,millicode
+/* Provides a "nice" label for the code covered by the unwind descriptor
+ for things like gprof. */
+
+/* DIVISION BY 2 (shift by 1) */
+GSYM($$divI_2)
+ .export $$divI_2,millicode
+ comclr,>= arg0,0,0
+ addi 1,arg0,arg0
+ MILLIRET
+ extrs arg0,30,31,ret1
+
+
+/* DIVISION BY 4 (shift by 2) */
+GSYM($$divI_4)
+ .export $$divI_4,millicode
+ comclr,>= arg0,0,0
+ addi 3,arg0,arg0
+ MILLIRET
+ extrs arg0,29,30,ret1
+
+
+/* DIVISION BY 8 (shift by 3) */
+GSYM($$divI_8)
+ .export $$divI_8,millicode
+ comclr,>= arg0,0,0
+ addi 7,arg0,arg0
+ MILLIRET
+ extrs arg0,28,29,ret1
+
+/* DIVISION BY 16 (shift by 4) */
+GSYM($$divI_16)
+ .export $$divI_16,millicode
+ comclr,>= arg0,0,0
+ addi 15,arg0,arg0
+ MILLIRET
+ extrs arg0,27,28,ret1
+
+/****************************************************************************
+*
+* DIVISION BY DIVISORS OF FFFFFFFF, and powers of 2 times these
+*
+* includes 3,5,15,17 and also 6,10,12
+*
+****************************************************************************/
+
+/* DIVISION BY 3 (use z = 2**32; a = 55555555) */
+
+GSYM($$divI_3)
+ .export $$divI_3,millicode
+ comb,<,N x2,0,LREF(neg3)
+
+ addi 1,x2,x2 /* this cannot overflow */
+ extru x2,1,2,x1 /* multiply by 5 to get started */
+ sh2add x2,x2,x2
+ b LREF(pos)
+ addc x1,0,x1
+
+LSYM(neg3)
+ subi 1,x2,x2 /* this cannot overflow */
+ extru x2,1,2,x1 /* multiply by 5 to get started */
+ sh2add x2,x2,x2
+ b LREF(neg)
+ addc x1,0,x1
+
+GSYM($$divU_3)
+ .export $$divU_3,millicode
+ addi 1,x2,x2 /* this CAN overflow */
+ addc 0,0,x1
+ shd x1,x2,30,t1 /* multiply by 5 to get started */
+ sh2add x2,x2,x2
+ b LREF(pos)
+ addc x1,t1,x1
+
+/* DIVISION BY 5 (use z = 2**32; a = 33333333) */
+
+GSYM($$divI_5)
+ .export $$divI_5,millicode
+ comb,<,N x2,0,LREF(neg5)
+
+ addi 3,x2,t1 /* this cannot overflow */
+ sh1add x2,t1,x2 /* multiply by 3 to get started */
+ b LREF(pos)
+ addc 0,0,x1
+
+LSYM(neg5)
+ sub 0,x2,x2 /* negate x2 */
+ addi 1,x2,x2 /* this cannot overflow */
+ shd 0,x2,31,x1 /* get top bit (can be 1) */
+ sh1add x2,x2,x2 /* multiply by 3 to get started */
+ b LREF(neg)
+ addc x1,0,x1
+
+GSYM($$divU_5)
+ .export $$divU_5,millicode
+ addi 1,x2,x2 /* this CAN overflow */
+ addc 0,0,x1
+ shd x1,x2,31,t1 /* multiply by 3 to get started */
+ sh1add x2,x2,x2
+ b LREF(pos)
+ addc t1,x1,x1
+
+/* DIVISION BY 6 (shift to divide by 2 then divide by 3) */
+GSYM($$divI_6)
+ .export $$divI_6,millicode
+ comb,<,N x2,0,LREF(neg6)
+ extru x2,30,31,x2 /* divide by 2 */
+ addi 5,x2,t1 /* compute 5*(x2+1) = 5*x2+5 */
+ sh2add x2,t1,x2 /* multiply by 5 to get started */
+ b LREF(pos)
+ addc 0,0,x1
+
+LSYM(neg6)
+ subi 2,x2,x2 /* negate, divide by 2, and add 1 */
+ /* negation and adding 1 are done */
+ /* at the same time by the SUBI */
+ extru x2,30,31,x2
+ shd 0,x2,30,x1
+ sh2add x2,x2,x2 /* multiply by 5 to get started */
+ b LREF(neg)
+ addc x1,0,x1
+
+GSYM($$divU_6)
+ .export $$divU_6,millicode
+ extru x2,30,31,x2 /* divide by 2 */
+ addi 1,x2,x2 /* cannot carry */
+ shd 0,x2,30,x1 /* multiply by 5 to get started */
+ sh2add x2,x2,x2
+ b LREF(pos)
+ addc x1,0,x1
+
+/* DIVISION BY 10 (shift to divide by 2 then divide by 5) */
+GSYM($$divU_10)
+ .export $$divU_10,millicode
+ extru x2,30,31,x2 /* divide by 2 */
+ addi 3,x2,t1 /* compute 3*(x2+1) = (3*x2)+3 */
+ sh1add x2,t1,x2 /* multiply by 3 to get started */
+ addc 0,0,x1
+LSYM(pos)
+ shd x1,x2,28,t1 /* multiply by 0x11 */
+ shd x2,0,28,t2
+ add x2,t2,x2
+ addc x1,t1,x1
+LSYM(pos_for_17)
+ shd x1,x2,24,t1 /* multiply by 0x101 */
+ shd x2,0,24,t2
+ add x2,t2,x2
+ addc x1,t1,x1
+
+ shd x1,x2,16,t1 /* multiply by 0x10001 */
+ shd x2,0,16,t2
+ add x2,t2,x2
+ MILLIRET
+ addc x1,t1,x1
+
+GSYM($$divI_10)
+ .export $$divI_10,millicode
+ comb,< x2,0,LREF(neg10)
+ copy 0,x1
+ extru x2,30,31,x2 /* divide by 2 */
+ addib,TR 1,x2,LREF(pos) /* add 1 (cannot overflow) */
+ sh1add x2,x2,x2 /* multiply by 3 to get started */
+
+LSYM(neg10)
+ subi 2,x2,x2 /* negate, divide by 2, and add 1 */
+ /* negation and adding 1 are done */
+ /* at the same time by the SUBI */
+ extru x2,30,31,x2
+ sh1add x2,x2,x2 /* multiply by 3 to get started */
+LSYM(neg)
+ shd x1,x2,28,t1 /* multiply by 0x11 */
+ shd x2,0,28,t2
+ add x2,t2,x2
+ addc x1,t1,x1
+LSYM(neg_for_17)
+ shd x1,x2,24,t1 /* multiply by 0x101 */
+ shd x2,0,24,t2
+ add x2,t2,x2
+ addc x1,t1,x1
+
+ shd x1,x2,16,t1 /* multiply by 0x10001 */
+ shd x2,0,16,t2
+ add x2,t2,x2
+ addc x1,t1,x1
+ MILLIRET
+ sub 0,x1,x1
+
+/* DIVISION BY 12 (shift to divide by 4 then divide by 3) */
+GSYM($$divI_12)
+ .export $$divI_12,millicode
+ comb,< x2,0,LREF(neg12)
+ copy 0,x1
+ extru x2,29,30,x2 /* divide by 4 */
+ addib,tr 1,x2,LREF(pos) /* compute 5*(x2+1) = 5*x2+5 */
+ sh2add x2,x2,x2 /* multiply by 5 to get started */
+
+LSYM(neg12)
+ subi 4,x2,x2 /* negate, divide by 4, and add 1 */
+ /* negation and adding 1 are done */
+ /* at the same time by the SUBI */
+ extru x2,29,30,x2
+ b LREF(neg)
+ sh2add x2,x2,x2 /* multiply by 5 to get started */
+
+GSYM($$divU_12)
+ .export $$divU_12,millicode
+ extru x2,29,30,x2 /* divide by 4 */
+ addi 5,x2,t1 /* cannot carry */
+ sh2add x2,t1,x2 /* multiply by 5 to get started */
+ b LREF(pos)
+ addc 0,0,x1
+
+/* DIVISION BY 15 (use z = 2**32; a = 11111111) */
+GSYM($$divI_15)
+ .export $$divI_15,millicode
+ comb,< x2,0,LREF(neg15)
+ copy 0,x1
+ addib,tr 1,x2,LREF(pos)+4
+ shd x1,x2,28,t1
+
+LSYM(neg15)
+ b LREF(neg)
+ subi 1,x2,x2
+
+GSYM($$divU_15)
+ .export $$divU_15,millicode
+ addi 1,x2,x2 /* this CAN overflow */
+ b LREF(pos)
+ addc 0,0,x1
+
+/* DIVISION BY 17 (use z = 2**32; a = f0f0f0f) */
+GSYM($$divI_17)
+ .export $$divI_17,millicode
+ comb,<,n x2,0,LREF(neg17)
+ addi 1,x2,x2 /* this cannot overflow */
+ shd 0,x2,28,t1 /* multiply by 0xf to get started */
+ shd x2,0,28,t2
+ sub t2,x2,x2
+ b LREF(pos_for_17)
+ subb t1,0,x1
+
+LSYM(neg17)
+ subi 1,x2,x2 /* this cannot overflow */
+ shd 0,x2,28,t1 /* multiply by 0xf to get started */
+ shd x2,0,28,t2
+ sub t2,x2,x2
+ b LREF(neg_for_17)
+ subb t1,0,x1
+
+GSYM($$divU_17)
+ .export $$divU_17,millicode
+ addi 1,x2,x2 /* this CAN overflow */
+ addc 0,0,x1
+ shd x1,x2,28,t1 /* multiply by 0xf to get started */
+LSYM(u17)
+ shd x2,0,28,t2
+ sub t2,x2,x2
+ b LREF(pos_for_17)
+ subb t1,x1,x1
+
+
+/* DIVISION BY DIVISORS OF FFFFFF, and powers of 2 times these
+ includes 7,9 and also 14
+
+
+ z = 2**24-1
+ r = z mod x = 0
+
+ so choose b = 0
+
+ Also, in order to divide by z = 2**24-1, we approximate by dividing
+ by (z+1) = 2**24 (which is easy), and then correcting.
+
+ (ax) = (z+1)q' + r
+ . = zq' + (q'+r)
+
+ So to compute (ax)/z, compute q' = (ax)/(z+1) and r = (ax) mod (z+1)
+ Then the true remainder of (ax)/z is (q'+r). Repeat the process
+ with this new remainder, adding the tentative quotients together,
+ until a tentative quotient is 0 (and then we are done). There is
+ one last correction to be done. It is possible that (q'+r) = z.
+ If so, then (q'+r)/(z+1) = 0 and it looks like we are done. But,
+ in fact, we need to add 1 more to the quotient. Now, it turns
+ out that this happens if and only if the original value x is
+ an exact multiple of y. So, to avoid a three instruction test at
+ the end, instead use 1 instruction to add 1 to x at the beginning. */
+
+/* DIVISION BY 7 (use z = 2**24-1; a = 249249) */
+GSYM($$divI_7)
+ .export $$divI_7,millicode
+ comb,<,n x2,0,LREF(neg7)
+LSYM(7)
+ addi 1,x2,x2 /* cannot overflow */
+ shd 0,x2,29,x1
+ sh3add x2,x2,x2
+ addc x1,0,x1
+LSYM(pos7)
+ shd x1,x2,26,t1
+ shd x2,0,26,t2
+ add x2,t2,x2
+ addc x1,t1,x1
+
+ shd x1,x2,20,t1
+ shd x2,0,20,t2
+ add x2,t2,x2
+ addc x1,t1,t1
+
+ /* computed <t1,x2>. Now divide it by (2**24 - 1) */
+
+ copy 0,x1
+ shd,= t1,x2,24,t1 /* tentative quotient */
+LSYM(1)
+ addb,tr t1,x1,LREF(2) /* add to previous quotient */
+ extru x2,31,24,x2 /* new remainder (unadjusted) */
+
+ MILLIRETN
+
+LSYM(2)
+ addb,tr t1,x2,LREF(1) /* adjust remainder */
+ extru,= x2,7,8,t1 /* new quotient */
+
+LSYM(neg7)
+ subi 1,x2,x2 /* negate x2 and add 1 */
+LSYM(8)
+ shd 0,x2,29,x1
+ sh3add x2,x2,x2
+ addc x1,0,x1
+
+LSYM(neg7_shift)
+ shd x1,x2,26,t1
+ shd x2,0,26,t2
+ add x2,t2,x2
+ addc x1,t1,x1
+
+ shd x1,x2,20,t1
+ shd x2,0,20,t2
+ add x2,t2,x2
+ addc x1,t1,t1
+
+ /* computed <t1,x2>. Now divide it by (2**24 - 1) */
+
+ copy 0,x1
+ shd,= t1,x2,24,t1 /* tentative quotient */
+LSYM(3)
+ addb,tr t1,x1,LREF(4) /* add to previous quotient */
+ extru x2,31,24,x2 /* new remainder (unadjusted) */
+
+ MILLIRET
+ sub 0,x1,x1 /* negate result */
+
+LSYM(4)
+ addb,tr t1,x2,LREF(3) /* adjust remainder */
+ extru,= x2,7,8,t1 /* new quotient */
+
+GSYM($$divU_7)
+ .export $$divU_7,millicode
+ addi 1,x2,x2 /* can carry */
+ addc 0,0,x1
+ shd x1,x2,29,t1
+ sh3add x2,x2,x2
+ b LREF(pos7)
+ addc t1,x1,x1
+
+/* DIVISION BY 9 (use z = 2**24-1; a = 1c71c7) */
+GSYM($$divI_9)
+ .export $$divI_9,millicode
+ comb,<,n x2,0,LREF(neg9)
+ addi 1,x2,x2 /* cannot overflow */
+ shd 0,x2,29,t1
+ shd x2,0,29,t2
+ sub t2,x2,x2
+ b LREF(pos7)
+ subb t1,0,x1
+
+LSYM(neg9)
+ subi 1,x2,x2 /* negate and add 1 */
+ shd 0,x2,29,t1
+ shd x2,0,29,t2
+ sub t2,x2,x2
+ b LREF(neg7_shift)
+ subb t1,0,x1
+
+GSYM($$divU_9)
+ .export $$divU_9,millicode
+ addi 1,x2,x2 /* can carry */
+ addc 0,0,x1
+ shd x1,x2,29,t1
+ shd x2,0,29,t2
+ sub t2,x2,x2
+ b LREF(pos7)
+ subb t1,x1,x1
+
+/* DIVISION BY 14 (shift to divide by 2 then divide by 7) */
+GSYM($$divI_14)
+ .export $$divI_14,millicode
+ comb,<,n x2,0,LREF(neg14)
+GSYM($$divU_14)
+ .export $$divU_14,millicode
+ b LREF(7) /* go to 7 case */
+ extru x2,30,31,x2 /* divide by 2 */
+
+LSYM(neg14)
+ subi 2,x2,x2 /* negate (and add 2) */
+ b LREF(8)
+ extru x2,30,31,x2 /* divide by 2 */
+ .exit
+ .procend
+ .end
+#endif
+
+#ifdef L_mulI
+/* VERSION "@(#)$$mulI $ Revision: 12.4 $ $ Date: 94/03/17 17:18:51 $" */
+/******************************************************************************
+This routine is used on PA2.0 processors when gcc -mno-fpregs is used
+
+ROUTINE: $$mulI
+
+
+DESCRIPTION:
+
+ $$mulI multiplies two single word integers, giving a single
+ word result.
+
+
+INPUT REGISTERS:
+
+ arg0 = Operand 1
+ arg1 = Operand 2
+ r31 == return pc
+ sr0 == return space when called externally
+
+
+OUTPUT REGISTERS:
+
+ arg0 = undefined
+ arg1 = undefined
+ ret1 = result
+
+OTHER REGISTERS AFFECTED:
+
+ r1 = undefined
+
+SIDE EFFECTS:
+
+ Causes a trap under the following conditions: NONE
+ Changes memory at the following places: NONE
+
+PERMISSIBLE CONTEXT:
+
+ Unwindable
+ Does not create a stack frame
+ Is usable for internal or external microcode
+
+DISCUSSION:
+
+ Calls other millicode routines via mrp: NONE
+ Calls other millicode routines: NONE
+
+***************************************************************************/
+
+
+#define a0 %arg0
+#define a1 %arg1
+#define t0 %r1
+#define r %ret1
+
+#define a0__128a0 zdep a0,24,25,a0
+#define a0__256a0 zdep a0,23,24,a0
+#define a1_ne_0_b_l0 comb,<> a1,0,LREF(l0)
+#define a1_ne_0_b_l1 comb,<> a1,0,LREF(l1)
+#define a1_ne_0_b_l2 comb,<> a1,0,LREF(l2)
+#define b_n_ret_t0 b,n LREF(ret_t0)
+#define b_e_shift b LREF(e_shift)
+#define b_e_t0ma0 b LREF(e_t0ma0)
+#define b_e_t0 b LREF(e_t0)
+#define b_e_t0a0 b LREF(e_t0a0)
+#define b_e_t02a0 b LREF(e_t02a0)
+#define b_e_t04a0 b LREF(e_t04a0)
+#define b_e_2t0 b LREF(e_2t0)
+#define b_e_2t0a0 b LREF(e_2t0a0)
+#define b_e_2t04a0 b LREF(e2t04a0)
+#define b_e_3t0 b LREF(e_3t0)
+#define b_e_4t0 b LREF(e_4t0)
+#define b_e_4t0a0 b LREF(e_4t0a0)
+#define b_e_4t08a0 b LREF(e4t08a0)
+#define b_e_5t0 b LREF(e_5t0)
+#define b_e_8t0 b LREF(e_8t0)
+#define b_e_8t0a0 b LREF(e_8t0a0)
+#define r__r_a0 add r,a0,r
+#define r__r_2a0 sh1add a0,r,r
+#define r__r_4a0 sh2add a0,r,r
+#define r__r_8a0 sh3add a0,r,r
+#define r__r_t0 add r,t0,r
+#define r__r_2t0 sh1add t0,r,r
+#define r__r_4t0 sh2add t0,r,r
+#define r__r_8t0 sh3add t0,r,r
+#define t0__3a0 sh1add a0,a0,t0
+#define t0__4a0 sh2add a0,0,t0
+#define t0__5a0 sh2add a0,a0,t0
+#define t0__8a0 sh3add a0,0,t0
+#define t0__9a0 sh3add a0,a0,t0
+#define t0__16a0 zdep a0,27,28,t0
+#define t0__32a0 zdep a0,26,27,t0
+#define t0__64a0 zdep a0,25,26,t0
+#define t0__128a0 zdep a0,24,25,t0
+#define t0__t0ma0 sub t0,a0,t0
+#define t0__t0_a0 add t0,a0,t0
+#define t0__t0_2a0 sh1add a0,t0,t0
+#define t0__t0_4a0 sh2add a0,t0,t0
+#define t0__t0_8a0 sh3add a0,t0,t0
+#define t0__2t0_a0 sh1add t0,a0,t0
+#define t0__3t0 sh1add t0,t0,t0
+#define t0__4t0 sh2add t0,0,t0
+#define t0__4t0_a0 sh2add t0,a0,t0
+#define t0__5t0 sh2add t0,t0,t0
+#define t0__8t0 sh3add t0,0,t0
+#define t0__8t0_a0 sh3add t0,a0,t0
+#define t0__9t0 sh3add t0,t0,t0
+#define t0__16t0 zdep t0,27,28,t0
+#define t0__32t0 zdep t0,26,27,t0
+#define t0__256a0 zdep a0,23,24,t0
+
+
+ SUBSPA_MILLI
+ ATTR_MILLI
+ .align 16
+ .proc
+ .callinfo millicode
+ .export $$mulI,millicode
+GSYM($$mulI)
+ combt,<<= a1,a0,LREF(l4) /* swap args if unsigned a1>a0 */
+ copy 0,r /* zero out the result */
+ xor a0,a1,a0 /* swap a0 & a1 using the */
+ xor a0,a1,a1 /* old xor trick */
+ xor a0,a1,a0
+LSYM(l4)
+ combt,<= 0,a0,LREF(l3) /* if a0>=0 then proceed like unsigned */
+ zdep a1,30,8,t0 /* t0 = (a1&0xff)<<1 ********* */
+ sub,> 0,a1,t0 /* otherwise negate both and */
+ combt,<=,n a0,t0,LREF(l2) /* swap back if |a0|<|a1| */
+ sub 0,a0,a1
+ movb,tr,n t0,a0,LREF(l2) /* 10th inst. */
+
+LSYM(l0) r__r_t0 /* add in this partial product */
+LSYM(l1) a0__256a0 /* a0 <<= 8 ****************** */
+LSYM(l2) zdep a1,30,8,t0 /* t0 = (a1&0xff)<<1 ********* */
+LSYM(l3) blr t0,0 /* case on these 8 bits ****** */
+ extru a1,23,24,a1 /* a1 >>= 8 ****************** */
+
+/*16 insts before this. */
+/* a0 <<= 8 ************************** */
+LSYM(x0) a1_ne_0_b_l2 ! a0__256a0 ! MILLIRETN ! nop
+LSYM(x1) a1_ne_0_b_l1 ! r__r_a0 ! MILLIRETN ! nop
+LSYM(x2) a1_ne_0_b_l1 ! r__r_2a0 ! MILLIRETN ! nop
+LSYM(x3) a1_ne_0_b_l0 ! t0__3a0 ! MILLIRET ! r__r_t0
+LSYM(x4) a1_ne_0_b_l1 ! r__r_4a0 ! MILLIRETN ! nop
+LSYM(x5) a1_ne_0_b_l0 ! t0__5a0 ! MILLIRET ! r__r_t0
+LSYM(x6) t0__3a0 ! a1_ne_0_b_l1 ! r__r_2t0 ! MILLIRETN
+LSYM(x7) t0__3a0 ! a1_ne_0_b_l0 ! r__r_4a0 ! b_n_ret_t0
+LSYM(x8) a1_ne_0_b_l1 ! r__r_8a0 ! MILLIRETN ! nop
+LSYM(x9) a1_ne_0_b_l0 ! t0__9a0 ! MILLIRET ! r__r_t0
+LSYM(x10) t0__5a0 ! a1_ne_0_b_l1 ! r__r_2t0 ! MILLIRETN
+LSYM(x11) t0__3a0 ! a1_ne_0_b_l0 ! r__r_8a0 ! b_n_ret_t0
+LSYM(x12) t0__3a0 ! a1_ne_0_b_l1 ! r__r_4t0 ! MILLIRETN
+LSYM(x13) t0__5a0 ! a1_ne_0_b_l0 ! r__r_8a0 ! b_n_ret_t0
+LSYM(x14) t0__3a0 ! t0__2t0_a0 ! b_e_shift ! r__r_2t0
+LSYM(x15) t0__5a0 ! a1_ne_0_b_l0 ! t0__3t0 ! b_n_ret_t0
+LSYM(x16) t0__16a0 ! a1_ne_0_b_l1 ! r__r_t0 ! MILLIRETN
+LSYM(x17) t0__9a0 ! a1_ne_0_b_l0 ! t0__t0_8a0 ! b_n_ret_t0
+LSYM(x18) t0__9a0 ! a1_ne_0_b_l1 ! r__r_2t0 ! MILLIRETN
+LSYM(x19) t0__9a0 ! a1_ne_0_b_l0 ! t0__2t0_a0 ! b_n_ret_t0
+LSYM(x20) t0__5a0 ! a1_ne_0_b_l1 ! r__r_4t0 ! MILLIRETN
+LSYM(x21) t0__5a0 ! a1_ne_0_b_l0 ! t0__4t0_a0 ! b_n_ret_t0
+LSYM(x22) t0__5a0 ! t0__2t0_a0 ! b_e_shift ! r__r_2t0
+LSYM(x23) t0__5a0 ! t0__2t0_a0 ! b_e_t0 ! t0__2t0_a0
+LSYM(x24) t0__3a0 ! a1_ne_0_b_l1 ! r__r_8t0 ! MILLIRETN
+LSYM(x25) t0__5a0 ! a1_ne_0_b_l0 ! t0__5t0 ! b_n_ret_t0
+LSYM(x26) t0__3a0 ! t0__4t0_a0 ! b_e_shift ! r__r_2t0
+LSYM(x27) t0__3a0 ! a1_ne_0_b_l0 ! t0__9t0 ! b_n_ret_t0
+LSYM(x28) t0__3a0 ! t0__2t0_a0 ! b_e_shift ! r__r_4t0
+LSYM(x29) t0__3a0 ! t0__2t0_a0 ! b_e_t0 ! t0__4t0_a0
+LSYM(x30) t0__5a0 ! t0__3t0 ! b_e_shift ! r__r_2t0
+LSYM(x31) t0__32a0 ! a1_ne_0_b_l0 ! t0__t0ma0 ! b_n_ret_t0
+LSYM(x32) t0__32a0 ! a1_ne_0_b_l1 ! r__r_t0 ! MILLIRETN
+LSYM(x33) t0__8a0 ! a1_ne_0_b_l0 ! t0__4t0_a0 ! b_n_ret_t0
+LSYM(x34) t0__16a0 ! t0__t0_a0 ! b_e_shift ! r__r_2t0
+LSYM(x35) t0__9a0 ! t0__3t0 ! b_e_t0 ! t0__t0_8a0
+LSYM(x36) t0__9a0 ! a1_ne_0_b_l1 ! r__r_4t0 ! MILLIRETN
+LSYM(x37) t0__9a0 ! a1_ne_0_b_l0 ! t0__4t0_a0 ! b_n_ret_t0
+LSYM(x38) t0__9a0 ! t0__2t0_a0 ! b_e_shift ! r__r_2t0
+LSYM(x39) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__2t0_a0
+LSYM(x40) t0__5a0 ! a1_ne_0_b_l1 ! r__r_8t0 ! MILLIRETN
+LSYM(x41) t0__5a0 ! a1_ne_0_b_l0 ! t0__8t0_a0 ! b_n_ret_t0
+LSYM(x42) t0__5a0 ! t0__4t0_a0 ! b_e_shift ! r__r_2t0
+LSYM(x43) t0__5a0 ! t0__4t0_a0 ! b_e_t0 ! t0__2t0_a0
+LSYM(x44) t0__5a0 ! t0__2t0_a0 ! b_e_shift ! r__r_4t0
+LSYM(x45) t0__9a0 ! a1_ne_0_b_l0 ! t0__5t0 ! b_n_ret_t0
+LSYM(x46) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__t0_a0
+LSYM(x47) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__t0_2a0
+LSYM(x48) t0__3a0 ! a1_ne_0_b_l0 ! t0__16t0 ! b_n_ret_t0
+LSYM(x49) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__t0_4a0
+LSYM(x50) t0__5a0 ! t0__5t0 ! b_e_shift ! r__r_2t0
+LSYM(x51) t0__9a0 ! t0__t0_8a0 ! b_e_t0 ! t0__3t0
+LSYM(x52) t0__3a0 ! t0__4t0_a0 ! b_e_shift ! r__r_4t0
+LSYM(x53) t0__3a0 ! t0__4t0_a0 ! b_e_t0 ! t0__4t0_a0
+LSYM(x54) t0__9a0 ! t0__3t0 ! b_e_shift ! r__r_2t0
+LSYM(x55) t0__9a0 ! t0__3t0 ! b_e_t0 ! t0__2t0_a0
+LSYM(x56) t0__3a0 ! t0__2t0_a0 ! b_e_shift ! r__r_8t0
+LSYM(x57) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__3t0
+LSYM(x58) t0__3a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__4t0_a0
+LSYM(x59) t0__9a0 ! t0__2t0_a0 ! b_e_t02a0 ! t0__3t0
+LSYM(x60) t0__5a0 ! t0__3t0 ! b_e_shift ! r__r_4t0
+LSYM(x61) t0__5a0 ! t0__3t0 ! b_e_t0 ! t0__4t0_a0
+LSYM(x62) t0__32a0 ! t0__t0ma0 ! b_e_shift ! r__r_2t0
+LSYM(x63) t0__64a0 ! a1_ne_0_b_l0 ! t0__t0ma0 ! b_n_ret_t0
+LSYM(x64) t0__64a0 ! a1_ne_0_b_l1 ! r__r_t0 ! MILLIRETN
+LSYM(x65) t0__8a0 ! a1_ne_0_b_l0 ! t0__8t0_a0 ! b_n_ret_t0
+LSYM(x66) t0__32a0 ! t0__t0_a0 ! b_e_shift ! r__r_2t0
+LSYM(x67) t0__8a0 ! t0__4t0_a0 ! b_e_t0 ! t0__2t0_a0
+LSYM(x68) t0__8a0 ! t0__2t0_a0 ! b_e_shift ! r__r_4t0
+LSYM(x69) t0__8a0 ! t0__2t0_a0 ! b_e_t0 ! t0__4t0_a0
+LSYM(x70) t0__64a0 ! t0__t0_4a0 ! b_e_t0 ! t0__t0_2a0
+LSYM(x71) t0__9a0 ! t0__8t0 ! b_e_t0 ! t0__t0ma0
+LSYM(x72) t0__9a0 ! a1_ne_0_b_l1 ! r__r_8t0 ! MILLIRETN
+LSYM(x73) t0__9a0 ! t0__8t0_a0 ! b_e_shift ! r__r_t0
+LSYM(x74) t0__9a0 ! t0__4t0_a0 ! b_e_shift ! r__r_2t0
+LSYM(x75) t0__9a0 ! t0__4t0_a0 ! b_e_t0 ! t0__2t0_a0
+LSYM(x76) t0__9a0 ! t0__2t0_a0 ! b_e_shift ! r__r_4t0
+LSYM(x77) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__4t0_a0
+LSYM(x78) t0__9a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__2t0_a0
+LSYM(x79) t0__16a0 ! t0__5t0 ! b_e_t0 ! t0__t0ma0
+LSYM(x80) t0__16a0 ! t0__5t0 ! b_e_shift ! r__r_t0
+LSYM(x81) t0__9a0 ! t0__9t0 ! b_e_shift ! r__r_t0
+LSYM(x82) t0__5a0 ! t0__8t0_a0 ! b_e_shift ! r__r_2t0
+LSYM(x83) t0__5a0 ! t0__8t0_a0 ! b_e_t0 ! t0__2t0_a0
+LSYM(x84) t0__5a0 ! t0__4t0_a0 ! b_e_shift ! r__r_4t0
+LSYM(x85) t0__8a0 ! t0__2t0_a0 ! b_e_t0 ! t0__5t0
+LSYM(x86) t0__5a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__2t0_a0
+LSYM(x87) t0__9a0 ! t0__9t0 ! b_e_t02a0 ! t0__t0_4a0
+LSYM(x88) t0__5a0 ! t0__2t0_a0 ! b_e_shift ! r__r_8t0
+LSYM(x89) t0__5a0 ! t0__2t0_a0 ! b_e_t0 ! t0__8t0_a0
+LSYM(x90) t0__9a0 ! t0__5t0 ! b_e_shift ! r__r_2t0
+LSYM(x91) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__2t0_a0
+LSYM(x92) t0__5a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__2t0_a0
+LSYM(x93) t0__32a0 ! t0__t0ma0 ! b_e_t0 ! t0__3t0
+LSYM(x94) t0__9a0 ! t0__5t0 ! b_e_2t0 ! t0__t0_2a0
+LSYM(x95) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__5t0
+LSYM(x96) t0__8a0 ! t0__3t0 ! b_e_shift ! r__r_4t0
+LSYM(x97) t0__8a0 ! t0__3t0 ! b_e_t0 ! t0__4t0_a0
+LSYM(x98) t0__32a0 ! t0__3t0 ! b_e_t0 ! t0__t0_2a0
+LSYM(x99) t0__8a0 ! t0__4t0_a0 ! b_e_t0 ! t0__3t0
+LSYM(x100) t0__5a0 ! t0__5t0 ! b_e_shift ! r__r_4t0
+LSYM(x101) t0__5a0 ! t0__5t0 ! b_e_t0 ! t0__4t0_a0
+LSYM(x102) t0__32a0 ! t0__t0_2a0 ! b_e_t0 ! t0__3t0
+LSYM(x103) t0__5a0 ! t0__5t0 ! b_e_t02a0 ! t0__4t0_a0
+LSYM(x104) t0__3a0 ! t0__4t0_a0 ! b_e_shift ! r__r_8t0
+LSYM(x105) t0__5a0 ! t0__4t0_a0 ! b_e_t0 ! t0__5t0
+LSYM(x106) t0__3a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__4t0_a0
+LSYM(x107) t0__9a0 ! t0__t0_4a0 ! b_e_t02a0 ! t0__8t0_a0
+LSYM(x108) t0__9a0 ! t0__3t0 ! b_e_shift ! r__r_4t0
+LSYM(x109) t0__9a0 ! t0__3t0 ! b_e_t0 ! t0__4t0_a0
+LSYM(x110) t0__9a0 ! t0__3t0 ! b_e_2t0 ! t0__2t0_a0
+LSYM(x111) t0__9a0 ! t0__4t0_a0 ! b_e_t0 ! t0__3t0
+LSYM(x112) t0__3a0 ! t0__2t0_a0 ! b_e_t0 ! t0__16t0
+LSYM(x113) t0__9a0 ! t0__4t0_a0 ! b_e_t02a0 ! t0__3t0
+LSYM(x114) t0__9a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__3t0
+LSYM(x115) t0__9a0 ! t0__2t0_a0 ! b_e_2t0a0 ! t0__3t0
+LSYM(x116) t0__3a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__4t0_a0
+LSYM(x117) t0__3a0 ! t0__4t0_a0 ! b_e_t0 ! t0__9t0
+LSYM(x118) t0__3a0 ! t0__4t0_a0 ! b_e_t0a0 ! t0__9t0
+LSYM(x119) t0__3a0 ! t0__4t0_a0 ! b_e_t02a0 ! t0__9t0
+LSYM(x120) t0__5a0 ! t0__3t0 ! b_e_shift ! r__r_8t0
+LSYM(x121) t0__5a0 ! t0__3t0 ! b_e_t0 ! t0__8t0_a0
+LSYM(x122) t0__5a0 ! t0__3t0 ! b_e_2t0 ! t0__4t0_a0
+LSYM(x123) t0__5a0 ! t0__8t0_a0 ! b_e_t0 ! t0__3t0
+LSYM(x124) t0__32a0 ! t0__t0ma0 ! b_e_shift ! r__r_4t0
+LSYM(x125) t0__5a0 ! t0__5t0 ! b_e_t0 ! t0__5t0
+LSYM(x126) t0__64a0 ! t0__t0ma0 ! b_e_shift ! r__r_2t0
+LSYM(x127) t0__128a0 ! a1_ne_0_b_l0 ! t0__t0ma0 ! b_n_ret_t0
+LSYM(x128) t0__128a0 ! a1_ne_0_b_l1 ! r__r_t0 ! MILLIRETN
+LSYM(x129) t0__128a0 ! a1_ne_0_b_l0 ! t0__t0_a0 ! b_n_ret_t0
+LSYM(x130) t0__64a0 ! t0__t0_a0 ! b_e_shift ! r__r_2t0
+LSYM(x131) t0__8a0 ! t0__8t0_a0 ! b_e_t0 ! t0__2t0_a0
+LSYM(x132) t0__8a0 ! t0__4t0_a0 ! b_e_shift ! r__r_4t0
+LSYM(x133) t0__8a0 ! t0__4t0_a0 ! b_e_t0 ! t0__4t0_a0
+LSYM(x134) t0__8a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__2t0_a0
+LSYM(x135) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__3t0
+LSYM(x136) t0__8a0 ! t0__2t0_a0 ! b_e_shift ! r__r_8t0
+LSYM(x137) t0__8a0 ! t0__2t0_a0 ! b_e_t0 ! t0__8t0_a0
+LSYM(x138) t0__8a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__4t0_a0
+LSYM(x139) t0__8a0 ! t0__2t0_a0 ! b_e_2t0a0 ! t0__4t0_a0
+LSYM(x140) t0__3a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__5t0
+LSYM(x141) t0__8a0 ! t0__2t0_a0 ! b_e_4t0a0 ! t0__2t0_a0
+LSYM(x142) t0__9a0 ! t0__8t0 ! b_e_2t0 ! t0__t0ma0
+LSYM(x143) t0__16a0 ! t0__9t0 ! b_e_t0 ! t0__t0ma0
+LSYM(x144) t0__9a0 ! t0__8t0 ! b_e_shift ! r__r_2t0
+LSYM(x145) t0__9a0 ! t0__8t0 ! b_e_t0 ! t0__2t0_a0
+LSYM(x146) t0__9a0 ! t0__8t0_a0 ! b_e_shift ! r__r_2t0
+LSYM(x147) t0__9a0 ! t0__8t0_a0 ! b_e_t0 ! t0__2t0_a0
+LSYM(x148) t0__9a0 ! t0__4t0_a0 ! b_e_shift ! r__r_4t0
+LSYM(x149) t0__9a0 ! t0__4t0_a0 ! b_e_t0 ! t0__4t0_a0
+LSYM(x150) t0__9a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__2t0_a0
+LSYM(x151) t0__9a0 ! t0__4t0_a0 ! b_e_2t0a0 ! t0__2t0_a0
+LSYM(x152) t0__9a0 ! t0__2t0_a0 ! b_e_shift ! r__r_8t0
+LSYM(x153) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__8t0_a0
+LSYM(x154) t0__9a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__4t0_a0
+LSYM(x155) t0__32a0 ! t0__t0ma0 ! b_e_t0 ! t0__5t0
+LSYM(x156) t0__9a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__2t0_a0
+LSYM(x157) t0__32a0 ! t0__t0ma0 ! b_e_t02a0 ! t0__5t0
+LSYM(x158) t0__16a0 ! t0__5t0 ! b_e_2t0 ! t0__t0ma0
+LSYM(x159) t0__32a0 ! t0__5t0 ! b_e_t0 ! t0__t0ma0
+LSYM(x160) t0__5a0 ! t0__4t0 ! b_e_shift ! r__r_8t0
+LSYM(x161) t0__8a0 ! t0__5t0 ! b_e_t0 ! t0__4t0_a0
+LSYM(x162) t0__9a0 ! t0__9t0 ! b_e_shift ! r__r_2t0
+LSYM(x163) t0__9a0 ! t0__9t0 ! b_e_t0 ! t0__2t0_a0
+LSYM(x164) t0__5a0 ! t0__8t0_a0 ! b_e_shift ! r__r_4t0
+LSYM(x165) t0__8a0 ! t0__4t0_a0 ! b_e_t0 ! t0__5t0
+LSYM(x166) t0__5a0 ! t0__8t0_a0 ! b_e_2t0 ! t0__2t0_a0
+LSYM(x167) t0__5a0 ! t0__8t0_a0 ! b_e_2t0a0 ! t0__2t0_a0
+LSYM(x168) t0__5a0 ! t0__4t0_a0 ! b_e_shift ! r__r_8t0
+LSYM(x169) t0__5a0 ! t0__4t0_a0 ! b_e_t0 ! t0__8t0_a0
+LSYM(x170) t0__32a0 ! t0__t0_2a0 ! b_e_t0 ! t0__5t0
+LSYM(x171) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__9t0
+LSYM(x172) t0__5a0 ! t0__4t0_a0 ! b_e_4t0 ! t0__2t0_a0
+LSYM(x173) t0__9a0 ! t0__2t0_a0 ! b_e_t02a0 ! t0__9t0
+LSYM(x174) t0__32a0 ! t0__t0_2a0 ! b_e_t04a0 ! t0__5t0
+LSYM(x175) t0__8a0 ! t0__2t0_a0 ! b_e_5t0 ! t0__2t0_a0
+LSYM(x176) t0__5a0 ! t0__4t0_a0 ! b_e_8t0 ! t0__t0_a0
+LSYM(x177) t0__5a0 ! t0__4t0_a0 ! b_e_8t0a0 ! t0__t0_a0
+LSYM(x178) t0__5a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__8t0_a0
+LSYM(x179) t0__5a0 ! t0__2t0_a0 ! b_e_2t0a0 ! t0__8t0_a0
+LSYM(x180) t0__9a0 ! t0__5t0 ! b_e_shift ! r__r_4t0
+LSYM(x181) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__4t0_a0
+LSYM(x182) t0__9a0 ! t0__5t0 ! b_e_2t0 ! t0__2t0_a0
+LSYM(x183) t0__9a0 ! t0__5t0 ! b_e_2t0a0 ! t0__2t0_a0
+LSYM(x184) t0__5a0 ! t0__9t0 ! b_e_4t0 ! t0__t0_a0
+LSYM(x185) t0__9a0 ! t0__4t0_a0 ! b_e_t0 ! t0__5t0
+LSYM(x186) t0__32a0 ! t0__t0ma0 ! b_e_2t0 ! t0__3t0
+LSYM(x187) t0__9a0 ! t0__4t0_a0 ! b_e_t02a0 ! t0__5t0
+LSYM(x188) t0__9a0 ! t0__5t0 ! b_e_4t0 ! t0__t0_2a0
+LSYM(x189) t0__5a0 ! t0__4t0_a0 ! b_e_t0 ! t0__9t0
+LSYM(x190) t0__9a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__5t0
+LSYM(x191) t0__64a0 ! t0__3t0 ! b_e_t0 ! t0__t0ma0
+LSYM(x192) t0__8a0 ! t0__3t0 ! b_e_shift ! r__r_8t0
+LSYM(x193) t0__8a0 ! t0__3t0 ! b_e_t0 ! t0__8t0_a0
+LSYM(x194) t0__8a0 ! t0__3t0 ! b_e_2t0 ! t0__4t0_a0
+LSYM(x195) t0__8a0 ! t0__8t0_a0 ! b_e_t0 ! t0__3t0
+LSYM(x196) t0__8a0 ! t0__3t0 ! b_e_4t0 ! t0__2t0_a0
+LSYM(x197) t0__8a0 ! t0__3t0 ! b_e_4t0a0 ! t0__2t0_a0
+LSYM(x198) t0__64a0 ! t0__t0_2a0 ! b_e_t0 ! t0__3t0
+LSYM(x199) t0__8a0 ! t0__4t0_a0 ! b_e_2t0a0 ! t0__3t0
+LSYM(x200) t0__5a0 ! t0__5t0 ! b_e_shift ! r__r_8t0
+LSYM(x201) t0__5a0 ! t0__5t0 ! b_e_t0 ! t0__8t0_a0
+LSYM(x202) t0__5a0 ! t0__5t0 ! b_e_2t0 ! t0__4t0_a0
+LSYM(x203) t0__5a0 ! t0__5t0 ! b_e_2t0a0 ! t0__4t0_a0
+LSYM(x204) t0__8a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__3t0
+LSYM(x205) t0__5a0 ! t0__8t0_a0 ! b_e_t0 ! t0__5t0
+LSYM(x206) t0__64a0 ! t0__t0_4a0 ! b_e_t02a0 ! t0__3t0
+LSYM(x207) t0__8a0 ! t0__2t0_a0 ! b_e_3t0 ! t0__4t0_a0
+LSYM(x208) t0__5a0 ! t0__5t0 ! b_e_8t0 ! t0__t0_a0
+LSYM(x209) t0__5a0 ! t0__5t0 ! b_e_8t0a0 ! t0__t0_a0
+LSYM(x210) t0__5a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__5t0
+LSYM(x211) t0__5a0 ! t0__4t0_a0 ! b_e_2t0a0 ! t0__5t0
+LSYM(x212) t0__3a0 ! t0__4t0_a0 ! b_e_4t0 ! t0__4t0_a0
+LSYM(x213) t0__3a0 ! t0__4t0_a0 ! b_e_4t0a0 ! t0__4t0_a0
+LSYM(x214) t0__9a0 ! t0__t0_4a0 ! b_e_2t04a0 ! t0__8t0_a0
+LSYM(x215) t0__5a0 ! t0__4t0_a0 ! b_e_5t0 ! t0__2t0_a0
+LSYM(x216) t0__9a0 ! t0__3t0 ! b_e_shift ! r__r_8t0
+LSYM(x217) t0__9a0 ! t0__3t0 ! b_e_t0 ! t0__8t0_a0
+LSYM(x218) t0__9a0 ! t0__3t0 ! b_e_2t0 ! t0__4t0_a0
+LSYM(x219) t0__9a0 ! t0__8t0_a0 ! b_e_t0 ! t0__3t0
+LSYM(x220) t0__3a0 ! t0__9t0 ! b_e_4t0 ! t0__2t0_a0
+LSYM(x221) t0__3a0 ! t0__9t0 ! b_e_4t0a0 ! t0__2t0_a0
+LSYM(x222) t0__9a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__3t0
+LSYM(x223) t0__9a0 ! t0__4t0_a0 ! b_e_2t0a0 ! t0__3t0
+LSYM(x224) t0__9a0 ! t0__3t0 ! b_e_8t0 ! t0__t0_a0
+LSYM(x225) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__5t0
+LSYM(x226) t0__3a0 ! t0__2t0_a0 ! b_e_t02a0 ! t0__32t0
+LSYM(x227) t0__9a0 ! t0__5t0 ! b_e_t02a0 ! t0__5t0
+LSYM(x228) t0__9a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__3t0
+LSYM(x229) t0__9a0 ! t0__2t0_a0 ! b_e_4t0a0 ! t0__3t0
+LSYM(x230) t0__9a0 ! t0__5t0 ! b_e_5t0 ! t0__t0_a0
+LSYM(x231) t0__9a0 ! t0__2t0_a0 ! b_e_3t0 ! t0__4t0_a0
+LSYM(x232) t0__3a0 ! t0__2t0_a0 ! b_e_8t0 ! t0__4t0_a0
+LSYM(x233) t0__3a0 ! t0__2t0_a0 ! b_e_8t0a0 ! t0__4t0_a0
+LSYM(x234) t0__3a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__9t0
+LSYM(x235) t0__3a0 ! t0__4t0_a0 ! b_e_2t0a0 ! t0__9t0
+LSYM(x236) t0__9a0 ! t0__2t0_a0 ! b_e_4t08a0 ! t0__3t0
+LSYM(x237) t0__16a0 ! t0__5t0 ! b_e_3t0 ! t0__t0ma0
+LSYM(x238) t0__3a0 ! t0__4t0_a0 ! b_e_2t04a0 ! t0__9t0
+LSYM(x239) t0__16a0 ! t0__5t0 ! b_e_t0ma0 ! t0__3t0
+LSYM(x240) t0__9a0 ! t0__t0_a0 ! b_e_8t0 ! t0__3t0
+LSYM(x241) t0__9a0 ! t0__t0_a0 ! b_e_8t0a0 ! t0__3t0
+LSYM(x242) t0__5a0 ! t0__3t0 ! b_e_2t0 ! t0__8t0_a0
+LSYM(x243) t0__9a0 ! t0__9t0 ! b_e_t0 ! t0__3t0
+LSYM(x244) t0__5a0 ! t0__3t0 ! b_e_4t0 ! t0__4t0_a0
+LSYM(x245) t0__8a0 ! t0__3t0 ! b_e_5t0 ! t0__2t0_a0
+LSYM(x246) t0__5a0 ! t0__8t0_a0 ! b_e_2t0 ! t0__3t0
+LSYM(x247) t0__5a0 ! t0__8t0_a0 ! b_e_2t0a0 ! t0__3t0
+LSYM(x248) t0__32a0 ! t0__t0ma0 ! b_e_shift ! r__r_8t0
+LSYM(x249) t0__32a0 ! t0__t0ma0 ! b_e_t0 ! t0__8t0_a0
+LSYM(x250) t0__5a0 ! t0__5t0 ! b_e_2t0 ! t0__5t0
+LSYM(x251) t0__5a0 ! t0__5t0 ! b_e_2t0a0 ! t0__5t0
+LSYM(x252) t0__64a0 ! t0__t0ma0 ! b_e_shift ! r__r_4t0
+LSYM(x253) t0__64a0 ! t0__t0ma0 ! b_e_t0 ! t0__4t0_a0
+LSYM(x254) t0__128a0 ! t0__t0ma0 ! b_e_shift ! r__r_2t0
+LSYM(x255) t0__256a0 ! a1_ne_0_b_l0 ! t0__t0ma0 ! b_n_ret_t0
+/*1040 insts before this. */
+LSYM(ret_t0) MILLIRET
+LSYM(e_t0) r__r_t0
+LSYM(e_shift) a1_ne_0_b_l2
+ a0__256a0 /* a0 <<= 8 *********** */
+ MILLIRETN
+LSYM(e_t0ma0) a1_ne_0_b_l0
+ t0__t0ma0
+ MILLIRET
+ r__r_t0
+LSYM(e_t0a0) a1_ne_0_b_l0
+ t0__t0_a0
+ MILLIRET
+ r__r_t0
+LSYM(e_t02a0) a1_ne_0_b_l0
+ t0__t0_2a0
+ MILLIRET
+ r__r_t0
+LSYM(e_t04a0) a1_ne_0_b_l0
+ t0__t0_4a0
+ MILLIRET
+ r__r_t0
+LSYM(e_2t0) a1_ne_0_b_l1
+ r__r_2t0
+ MILLIRETN
+LSYM(e_2t0a0) a1_ne_0_b_l0
+ t0__2t0_a0
+ MILLIRET
+ r__r_t0
+LSYM(e2t04a0) t0__t0_2a0
+ a1_ne_0_b_l1
+ r__r_2t0
+ MILLIRETN
+LSYM(e_3t0) a1_ne_0_b_l0
+ t0__3t0
+ MILLIRET
+ r__r_t0
+LSYM(e_4t0) a1_ne_0_b_l1
+ r__r_4t0
+ MILLIRETN
+LSYM(e_4t0a0) a1_ne_0_b_l0
+ t0__4t0_a0
+ MILLIRET
+ r__r_t0
+LSYM(e4t08a0) t0__t0_2a0
+ a1_ne_0_b_l1
+ r__r_4t0
+ MILLIRETN
+LSYM(e_5t0) a1_ne_0_b_l0
+ t0__5t0
+ MILLIRET
+ r__r_t0
+LSYM(e_8t0) a1_ne_0_b_l1
+ r__r_8t0
+ MILLIRETN
+LSYM(e_8t0a0) a1_ne_0_b_l0
+ t0__8t0_a0
+ MILLIRET
+ r__r_t0
+
+ .procend
+ .end
+#endif
diff --git a/arch/parisc/lib/milli/milli.h b/arch/parisc/lib/milli/milli.h
new file mode 100644
index 000000000000..19ac79f336de
--- /dev/null
+++ b/arch/parisc/lib/milli/milli.h
@@ -0,0 +1,165 @@
+/* 32 and 64-bit millicode, original author Hewlett-Packard
+ adapted for gcc by Paul Bame <bame@debian.org>
+ and Alan Modra <alan@linuxcare.com.au>.
+
+ Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
+
+ This file is part of GCC and is released under the terms of
+ of the GNU General Public License as published by the Free Software
+ Foundation; either version 2, or (at your option) any later version.
+ See the file COPYING in the top-level GCC source directory for a copy
+ of the license. */
+
+#ifndef _PA_MILLI_H_
+#define _PA_MILLI_H_
+
+#define L_dyncall
+#define L_divI
+#define L_divU
+#define L_remI
+#define L_remU
+#define L_div_const
+#define L_mulI
+
+#ifdef CONFIG_64BIT
+ .level 2.0w
+#endif
+
+/* Hardware General Registers. */
+r0: .reg %r0
+r1: .reg %r1
+r2: .reg %r2
+r3: .reg %r3
+r4: .reg %r4
+r5: .reg %r5
+r6: .reg %r6
+r7: .reg %r7
+r8: .reg %r8
+r9: .reg %r9
+r10: .reg %r10
+r11: .reg %r11
+r12: .reg %r12
+r13: .reg %r13
+r14: .reg %r14
+r15: .reg %r15
+r16: .reg %r16
+r17: .reg %r17
+r18: .reg %r18
+r19: .reg %r19
+r20: .reg %r20
+r21: .reg %r21
+r22: .reg %r22
+r23: .reg %r23
+r24: .reg %r24
+r25: .reg %r25
+r26: .reg %r26
+r27: .reg %r27
+r28: .reg %r28
+r29: .reg %r29
+r30: .reg %r30
+r31: .reg %r31
+
+/* Hardware Space Registers. */
+sr0: .reg %sr0
+sr1: .reg %sr1
+sr2: .reg %sr2
+sr3: .reg %sr3
+sr4: .reg %sr4
+sr5: .reg %sr5
+sr6: .reg %sr6
+sr7: .reg %sr7
+
+/* Hardware Floating Point Registers. */
+fr0: .reg %fr0
+fr1: .reg %fr1
+fr2: .reg %fr2
+fr3: .reg %fr3
+fr4: .reg %fr4
+fr5: .reg %fr5
+fr6: .reg %fr6
+fr7: .reg %fr7
+fr8: .reg %fr8
+fr9: .reg %fr9
+fr10: .reg %fr10
+fr11: .reg %fr11
+fr12: .reg %fr12
+fr13: .reg %fr13
+fr14: .reg %fr14
+fr15: .reg %fr15
+
+/* Hardware Control Registers. */
+cr11: .reg %cr11
+sar: .reg %cr11 /* Shift Amount Register */
+
+/* Software Architecture General Registers. */
+rp: .reg r2 /* return pointer */
+#ifdef CONFIG_64BIT
+mrp: .reg r2 /* millicode return pointer */
+#else
+mrp: .reg r31 /* millicode return pointer */
+#endif
+ret0: .reg r28 /* return value */
+ret1: .reg r29 /* return value (high part of double) */
+sp: .reg r30 /* stack pointer */
+dp: .reg r27 /* data pointer */
+arg0: .reg r26 /* argument */
+arg1: .reg r25 /* argument or high part of double argument */
+arg2: .reg r24 /* argument */
+arg3: .reg r23 /* argument or high part of double argument */
+
+/* Software Architecture Space Registers. */
+/* sr0 ; return link from BLE */
+sret: .reg sr1 /* return value */
+sarg: .reg sr1 /* argument */
+/* sr4 ; PC SPACE tracker */
+/* sr5 ; process private data */
+
+/* Frame Offsets (millicode convention!) Used when calling other
+ millicode routines. Stack unwinding is dependent upon these
+ definitions. */
+r31_slot: .equ -20 /* "current RP" slot */
+sr0_slot: .equ -16 /* "static link" slot */
+#if defined(CONFIG_64BIT)
+mrp_slot: .equ -16 /* "current RP" slot */
+psp_slot: .equ -8 /* "previous SP" slot */
+#else
+mrp_slot: .equ -20 /* "current RP" slot (replacing "r31_slot") */
+#endif
+
+
+#define DEFINE(name,value)name: .EQU value
+#define RDEFINE(name,value)name: .REG value
+#ifdef milliext
+#define MILLI_BE(lbl) BE lbl(sr7,r0)
+#define MILLI_BEN(lbl) BE,n lbl(sr7,r0)
+#define MILLI_BLE(lbl) BLE lbl(sr7,r0)
+#define MILLI_BLEN(lbl) BLE,n lbl(sr7,r0)
+#define MILLIRETN BE,n 0(sr0,mrp)
+#define MILLIRET BE 0(sr0,mrp)
+#define MILLI_RETN BE,n 0(sr0,mrp)
+#define MILLI_RET BE 0(sr0,mrp)
+#else
+#define MILLI_BE(lbl) B lbl
+#define MILLI_BEN(lbl) B,n lbl
+#define MILLI_BLE(lbl) BL lbl,mrp
+#define MILLI_BLEN(lbl) BL,n lbl,mrp
+#define MILLIRETN BV,n 0(mrp)
+#define MILLIRET BV 0(mrp)
+#define MILLI_RETN BV,n 0(mrp)
+#define MILLI_RET BV 0(mrp)
+#endif
+
+#define CAT(a,b) a##b
+
+#define SUBSPA_MILLI .section .text
+#define SUBSPA_MILLI_DIV .section .text.div,"ax",@progbits! .align 16
+#define SUBSPA_MILLI_MUL .section .text.mul,"ax",@progbits! .align 16
+#define ATTR_MILLI
+#define SUBSPA_DATA .section .data
+#define ATTR_DATA
+#define GLOBAL $global$
+#define GSYM(sym) !sym:
+#define LSYM(sym) !CAT(.L,sym:)
+#define LREF(sym) CAT(.L,sym)
+
+#endif /*_PA_MILLI_H_*/
diff --git a/arch/parisc/lib/milli/mulI.S b/arch/parisc/lib/milli/mulI.S
new file mode 100644
index 000000000000..4c7e0c36d15e
--- /dev/null
+++ b/arch/parisc/lib/milli/mulI.S
@@ -0,0 +1,474 @@
+/* 32 and 64-bit millicode, original author Hewlett-Packard
+ adapted for gcc by Paul Bame <bame@debian.org>
+ and Alan Modra <alan@linuxcare.com.au>.
+
+ Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
+
+ This file is part of GCC and is released under the terms of
+ of the GNU General Public License as published by the Free Software
+ Foundation; either version 2, or (at your option) any later version.
+ See the file COPYING in the top-level GCC source directory for a copy
+ of the license. */
+
+#include "milli.h"
+
+#ifdef L_mulI
+/* VERSION "@(#)$$mulI $ Revision: 12.4 $ $ Date: 94/03/17 17:18:51 $" */
+/******************************************************************************
+This routine is used on PA2.0 processors when gcc -mno-fpregs is used
+
+ROUTINE: $$mulI
+
+
+DESCRIPTION:
+
+ $$mulI multiplies two single word integers, giving a single
+ word result.
+
+
+INPUT REGISTERS:
+
+ arg0 = Operand 1
+ arg1 = Operand 2
+ r31 == return pc
+ sr0 == return space when called externally
+
+
+OUTPUT REGISTERS:
+
+ arg0 = undefined
+ arg1 = undefined
+ ret1 = result
+
+OTHER REGISTERS AFFECTED:
+
+ r1 = undefined
+
+SIDE EFFECTS:
+
+ Causes a trap under the following conditions: NONE
+ Changes memory at the following places: NONE
+
+PERMISSIBLE CONTEXT:
+
+ Unwindable
+ Does not create a stack frame
+ Is usable for internal or external microcode
+
+DISCUSSION:
+
+ Calls other millicode routines via mrp: NONE
+ Calls other millicode routines: NONE
+
+***************************************************************************/
+
+
+#define a0 %arg0
+#define a1 %arg1
+#define t0 %r1
+#define r %ret1
+
+#define a0__128a0 zdep a0,24,25,a0
+#define a0__256a0 zdep a0,23,24,a0
+#define a1_ne_0_b_l0 comb,<> a1,0,LREF(l0)
+#define a1_ne_0_b_l1 comb,<> a1,0,LREF(l1)
+#define a1_ne_0_b_l2 comb,<> a1,0,LREF(l2)
+#define b_n_ret_t0 b,n LREF(ret_t0)
+#define b_e_shift b LREF(e_shift)
+#define b_e_t0ma0 b LREF(e_t0ma0)
+#define b_e_t0 b LREF(e_t0)
+#define b_e_t0a0 b LREF(e_t0a0)
+#define b_e_t02a0 b LREF(e_t02a0)
+#define b_e_t04a0 b LREF(e_t04a0)
+#define b_e_2t0 b LREF(e_2t0)
+#define b_e_2t0a0 b LREF(e_2t0a0)
+#define b_e_2t04a0 b LREF(e2t04a0)
+#define b_e_3t0 b LREF(e_3t0)
+#define b_e_4t0 b LREF(e_4t0)
+#define b_e_4t0a0 b LREF(e_4t0a0)
+#define b_e_4t08a0 b LREF(e4t08a0)
+#define b_e_5t0 b LREF(e_5t0)
+#define b_e_8t0 b LREF(e_8t0)
+#define b_e_8t0a0 b LREF(e_8t0a0)
+#define r__r_a0 add r,a0,r
+#define r__r_2a0 sh1add a0,r,r
+#define r__r_4a0 sh2add a0,r,r
+#define r__r_8a0 sh3add a0,r,r
+#define r__r_t0 add r,t0,r
+#define r__r_2t0 sh1add t0,r,r
+#define r__r_4t0 sh2add t0,r,r
+#define r__r_8t0 sh3add t0,r,r
+#define t0__3a0 sh1add a0,a0,t0
+#define t0__4a0 sh2add a0,0,t0
+#define t0__5a0 sh2add a0,a0,t0
+#define t0__8a0 sh3add a0,0,t0
+#define t0__9a0 sh3add a0,a0,t0
+#define t0__16a0 zdep a0,27,28,t0
+#define t0__32a0 zdep a0,26,27,t0
+#define t0__64a0 zdep a0,25,26,t0
+#define t0__128a0 zdep a0,24,25,t0
+#define t0__t0ma0 sub t0,a0,t0
+#define t0__t0_a0 add t0,a0,t0
+#define t0__t0_2a0 sh1add a0,t0,t0
+#define t0__t0_4a0 sh2add a0,t0,t0
+#define t0__t0_8a0 sh3add a0,t0,t0
+#define t0__2t0_a0 sh1add t0,a0,t0
+#define t0__3t0 sh1add t0,t0,t0
+#define t0__4t0 sh2add t0,0,t0
+#define t0__4t0_a0 sh2add t0,a0,t0
+#define t0__5t0 sh2add t0,t0,t0
+#define t0__8t0 sh3add t0,0,t0
+#define t0__8t0_a0 sh3add t0,a0,t0
+#define t0__9t0 sh3add t0,t0,t0
+#define t0__16t0 zdep t0,27,28,t0
+#define t0__32t0 zdep t0,26,27,t0
+#define t0__256a0 zdep a0,23,24,t0
+
+
+ SUBSPA_MILLI
+ ATTR_MILLI
+ .align 16
+ .proc
+ .callinfo millicode
+ .export $$mulI,millicode
+GSYM($$mulI)
+ combt,<<= a1,a0,LREF(l4) /* swap args if unsigned a1>a0 */
+ copy 0,r /* zero out the result */
+ xor a0,a1,a0 /* swap a0 & a1 using the */
+ xor a0,a1,a1 /* old xor trick */
+ xor a0,a1,a0
+LSYM(l4)
+ combt,<= 0,a0,LREF(l3) /* if a0>=0 then proceed like unsigned */
+ zdep a1,30,8,t0 /* t0 = (a1&0xff)<<1 ********* */
+ sub,> 0,a1,t0 /* otherwise negate both and */
+ combt,<=,n a0,t0,LREF(l2) /* swap back if |a0|<|a1| */
+ sub 0,a0,a1
+ movb,tr,n t0,a0,LREF(l2) /* 10th inst. */
+
+LSYM(l0) r__r_t0 /* add in this partial product */
+LSYM(l1) a0__256a0 /* a0 <<= 8 ****************** */
+LSYM(l2) zdep a1,30,8,t0 /* t0 = (a1&0xff)<<1 ********* */
+LSYM(l3) blr t0,0 /* case on these 8 bits ****** */
+ extru a1,23,24,a1 /* a1 >>= 8 ****************** */
+
+/*16 insts before this. */
+/* a0 <<= 8 ************************** */
+LSYM(x0) a1_ne_0_b_l2 ! a0__256a0 ! MILLIRETN ! nop
+LSYM(x1) a1_ne_0_b_l1 ! r__r_a0 ! MILLIRETN ! nop
+LSYM(x2) a1_ne_0_b_l1 ! r__r_2a0 ! MILLIRETN ! nop
+LSYM(x3) a1_ne_0_b_l0 ! t0__3a0 ! MILLIRET ! r__r_t0
+LSYM(x4) a1_ne_0_b_l1 ! r__r_4a0 ! MILLIRETN ! nop
+LSYM(x5) a1_ne_0_b_l0 ! t0__5a0 ! MILLIRET ! r__r_t0
+LSYM(x6) t0__3a0 ! a1_ne_0_b_l1 ! r__r_2t0 ! MILLIRETN
+LSYM(x7) t0__3a0 ! a1_ne_0_b_l0 ! r__r_4a0 ! b_n_ret_t0
+LSYM(x8) a1_ne_0_b_l1 ! r__r_8a0 ! MILLIRETN ! nop
+LSYM(x9) a1_ne_0_b_l0 ! t0__9a0 ! MILLIRET ! r__r_t0
+LSYM(x10) t0__5a0 ! a1_ne_0_b_l1 ! r__r_2t0 ! MILLIRETN
+LSYM(x11) t0__3a0 ! a1_ne_0_b_l0 ! r__r_8a0 ! b_n_ret_t0
+LSYM(x12) t0__3a0 ! a1_ne_0_b_l1 ! r__r_4t0 ! MILLIRETN
+LSYM(x13) t0__5a0 ! a1_ne_0_b_l0 ! r__r_8a0 ! b_n_ret_t0
+LSYM(x14) t0__3a0 ! t0__2t0_a0 ! b_e_shift ! r__r_2t0
+LSYM(x15) t0__5a0 ! a1_ne_0_b_l0 ! t0__3t0 ! b_n_ret_t0
+LSYM(x16) t0__16a0 ! a1_ne_0_b_l1 ! r__r_t0 ! MILLIRETN
+LSYM(x17) t0__9a0 ! a1_ne_0_b_l0 ! t0__t0_8a0 ! b_n_ret_t0
+LSYM(x18) t0__9a0 ! a1_ne_0_b_l1 ! r__r_2t0 ! MILLIRETN
+LSYM(x19) t0__9a0 ! a1_ne_0_b_l0 ! t0__2t0_a0 ! b_n_ret_t0
+LSYM(x20) t0__5a0 ! a1_ne_0_b_l1 ! r__r_4t0 ! MILLIRETN
+LSYM(x21) t0__5a0 ! a1_ne_0_b_l0 ! t0__4t0_a0 ! b_n_ret_t0
+LSYM(x22) t0__5a0 ! t0__2t0_a0 ! b_e_shift ! r__r_2t0
+LSYM(x23) t0__5a0 ! t0__2t0_a0 ! b_e_t0 ! t0__2t0_a0
+LSYM(x24) t0__3a0 ! a1_ne_0_b_l1 ! r__r_8t0 ! MILLIRETN
+LSYM(x25) t0__5a0 ! a1_ne_0_b_l0 ! t0__5t0 ! b_n_ret_t0
+LSYM(x26) t0__3a0 ! t0__4t0_a0 ! b_e_shift ! r__r_2t0
+LSYM(x27) t0__3a0 ! a1_ne_0_b_l0 ! t0__9t0 ! b_n_ret_t0
+LSYM(x28) t0__3a0 ! t0__2t0_a0 ! b_e_shift ! r__r_4t0
+LSYM(x29) t0__3a0 ! t0__2t0_a0 ! b_e_t0 ! t0__4t0_a0
+LSYM(x30) t0__5a0 ! t0__3t0 ! b_e_shift ! r__r_2t0
+LSYM(x31) t0__32a0 ! a1_ne_0_b_l0 ! t0__t0ma0 ! b_n_ret_t0
+LSYM(x32) t0__32a0 ! a1_ne_0_b_l1 ! r__r_t0 ! MILLIRETN
+LSYM(x33) t0__8a0 ! a1_ne_0_b_l0 ! t0__4t0_a0 ! b_n_ret_t0
+LSYM(x34) t0__16a0 ! t0__t0_a0 ! b_e_shift ! r__r_2t0
+LSYM(x35) t0__9a0 ! t0__3t0 ! b_e_t0 ! t0__t0_8a0
+LSYM(x36) t0__9a0 ! a1_ne_0_b_l1 ! r__r_4t0 ! MILLIRETN
+LSYM(x37) t0__9a0 ! a1_ne_0_b_l0 ! t0__4t0_a0 ! b_n_ret_t0
+LSYM(x38) t0__9a0 ! t0__2t0_a0 ! b_e_shift ! r__r_2t0
+LSYM(x39) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__2t0_a0
+LSYM(x40) t0__5a0 ! a1_ne_0_b_l1 ! r__r_8t0 ! MILLIRETN
+LSYM(x41) t0__5a0 ! a1_ne_0_b_l0 ! t0__8t0_a0 ! b_n_ret_t0
+LSYM(x42) t0__5a0 ! t0__4t0_a0 ! b_e_shift ! r__r_2t0
+LSYM(x43) t0__5a0 ! t0__4t0_a0 ! b_e_t0 ! t0__2t0_a0
+LSYM(x44) t0__5a0 ! t0__2t0_a0 ! b_e_shift ! r__r_4t0
+LSYM(x45) t0__9a0 ! a1_ne_0_b_l0 ! t0__5t0 ! b_n_ret_t0
+LSYM(x46) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__t0_a0
+LSYM(x47) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__t0_2a0
+LSYM(x48) t0__3a0 ! a1_ne_0_b_l0 ! t0__16t0 ! b_n_ret_t0
+LSYM(x49) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__t0_4a0
+LSYM(x50) t0__5a0 ! t0__5t0 ! b_e_shift ! r__r_2t0
+LSYM(x51) t0__9a0 ! t0__t0_8a0 ! b_e_t0 ! t0__3t0
+LSYM(x52) t0__3a0 ! t0__4t0_a0 ! b_e_shift ! r__r_4t0
+LSYM(x53) t0__3a0 ! t0__4t0_a0 ! b_e_t0 ! t0__4t0_a0
+LSYM(x54) t0__9a0 ! t0__3t0 ! b_e_shift ! r__r_2t0
+LSYM(x55) t0__9a0 ! t0__3t0 ! b_e_t0 ! t0__2t0_a0
+LSYM(x56) t0__3a0 ! t0__2t0_a0 ! b_e_shift ! r__r_8t0
+LSYM(x57) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__3t0
+LSYM(x58) t0__3a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__4t0_a0
+LSYM(x59) t0__9a0 ! t0__2t0_a0 ! b_e_t02a0 ! t0__3t0
+LSYM(x60) t0__5a0 ! t0__3t0 ! b_e_shift ! r__r_4t0
+LSYM(x61) t0__5a0 ! t0__3t0 ! b_e_t0 ! t0__4t0_a0
+LSYM(x62) t0__32a0 ! t0__t0ma0 ! b_e_shift ! r__r_2t0
+LSYM(x63) t0__64a0 ! a1_ne_0_b_l0 ! t0__t0ma0 ! b_n_ret_t0
+LSYM(x64) t0__64a0 ! a1_ne_0_b_l1 ! r__r_t0 ! MILLIRETN
+LSYM(x65) t0__8a0 ! a1_ne_0_b_l0 ! t0__8t0_a0 ! b_n_ret_t0
+LSYM(x66) t0__32a0 ! t0__t0_a0 ! b_e_shift ! r__r_2t0
+LSYM(x67) t0__8a0 ! t0__4t0_a0 ! b_e_t0 ! t0__2t0_a0
+LSYM(x68) t0__8a0 ! t0__2t0_a0 ! b_e_shift ! r__r_4t0
+LSYM(x69) t0__8a0 ! t0__2t0_a0 ! b_e_t0 ! t0__4t0_a0
+LSYM(x70) t0__64a0 ! t0__t0_4a0 ! b_e_t0 ! t0__t0_2a0
+LSYM(x71) t0__9a0 ! t0__8t0 ! b_e_t0 ! t0__t0ma0
+LSYM(x72) t0__9a0 ! a1_ne_0_b_l1 ! r__r_8t0 ! MILLIRETN
+LSYM(x73) t0__9a0 ! t0__8t0_a0 ! b_e_shift ! r__r_t0
+LSYM(x74) t0__9a0 ! t0__4t0_a0 ! b_e_shift ! r__r_2t0
+LSYM(x75) t0__9a0 ! t0__4t0_a0 ! b_e_t0 ! t0__2t0_a0
+LSYM(x76) t0__9a0 ! t0__2t0_a0 ! b_e_shift ! r__r_4t0
+LSYM(x77) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__4t0_a0
+LSYM(x78) t0__9a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__2t0_a0
+LSYM(x79) t0__16a0 ! t0__5t0 ! b_e_t0 ! t0__t0ma0
+LSYM(x80) t0__16a0 ! t0__5t0 ! b_e_shift ! r__r_t0
+LSYM(x81) t0__9a0 ! t0__9t0 ! b_e_shift ! r__r_t0
+LSYM(x82) t0__5a0 ! t0__8t0_a0 ! b_e_shift ! r__r_2t0
+LSYM(x83) t0__5a0 ! t0__8t0_a0 ! b_e_t0 ! t0__2t0_a0
+LSYM(x84) t0__5a0 ! t0__4t0_a0 ! b_e_shift ! r__r_4t0
+LSYM(x85) t0__8a0 ! t0__2t0_a0 ! b_e_t0 ! t0__5t0
+LSYM(x86) t0__5a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__2t0_a0
+LSYM(x87) t0__9a0 ! t0__9t0 ! b_e_t02a0 ! t0__t0_4a0
+LSYM(x88) t0__5a0 ! t0__2t0_a0 ! b_e_shift ! r__r_8t0
+LSYM(x89) t0__5a0 ! t0__2t0_a0 ! b_e_t0 ! t0__8t0_a0
+LSYM(x90) t0__9a0 ! t0__5t0 ! b_e_shift ! r__r_2t0
+LSYM(x91) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__2t0_a0
+LSYM(x92) t0__5a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__2t0_a0
+LSYM(x93) t0__32a0 ! t0__t0ma0 ! b_e_t0 ! t0__3t0
+LSYM(x94) t0__9a0 ! t0__5t0 ! b_e_2t0 ! t0__t0_2a0
+LSYM(x95) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__5t0
+LSYM(x96) t0__8a0 ! t0__3t0 ! b_e_shift ! r__r_4t0
+LSYM(x97) t0__8a0 ! t0__3t0 ! b_e_t0 ! t0__4t0_a0
+LSYM(x98) t0__32a0 ! t0__3t0 ! b_e_t0 ! t0__t0_2a0
+LSYM(x99) t0__8a0 ! t0__4t0_a0 ! b_e_t0 ! t0__3t0
+LSYM(x100) t0__5a0 ! t0__5t0 ! b_e_shift ! r__r_4t0
+LSYM(x101) t0__5a0 ! t0__5t0 ! b_e_t0 ! t0__4t0_a0
+LSYM(x102) t0__32a0 ! t0__t0_2a0 ! b_e_t0 ! t0__3t0
+LSYM(x103) t0__5a0 ! t0__5t0 ! b_e_t02a0 ! t0__4t0_a0
+LSYM(x104) t0__3a0 ! t0__4t0_a0 ! b_e_shift ! r__r_8t0
+LSYM(x105) t0__5a0 ! t0__4t0_a0 ! b_e_t0 ! t0__5t0
+LSYM(x106) t0__3a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__4t0_a0
+LSYM(x107) t0__9a0 ! t0__t0_4a0 ! b_e_t02a0 ! t0__8t0_a0
+LSYM(x108) t0__9a0 ! t0__3t0 ! b_e_shift ! r__r_4t0
+LSYM(x109) t0__9a0 ! t0__3t0 ! b_e_t0 ! t0__4t0_a0
+LSYM(x110) t0__9a0 ! t0__3t0 ! b_e_2t0 ! t0__2t0_a0
+LSYM(x111) t0__9a0 ! t0__4t0_a0 ! b_e_t0 ! t0__3t0
+LSYM(x112) t0__3a0 ! t0__2t0_a0 ! b_e_t0 ! t0__16t0
+LSYM(x113) t0__9a0 ! t0__4t0_a0 ! b_e_t02a0 ! t0__3t0
+LSYM(x114) t0__9a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__3t0
+LSYM(x115) t0__9a0 ! t0__2t0_a0 ! b_e_2t0a0 ! t0__3t0
+LSYM(x116) t0__3a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__4t0_a0
+LSYM(x117) t0__3a0 ! t0__4t0_a0 ! b_e_t0 ! t0__9t0
+LSYM(x118) t0__3a0 ! t0__4t0_a0 ! b_e_t0a0 ! t0__9t0
+LSYM(x119) t0__3a0 ! t0__4t0_a0 ! b_e_t02a0 ! t0__9t0
+LSYM(x120) t0__5a0 ! t0__3t0 ! b_e_shift ! r__r_8t0
+LSYM(x121) t0__5a0 ! t0__3t0 ! b_e_t0 ! t0__8t0_a0
+LSYM(x122) t0__5a0 ! t0__3t0 ! b_e_2t0 ! t0__4t0_a0
+LSYM(x123) t0__5a0 ! t0__8t0_a0 ! b_e_t0 ! t0__3t0
+LSYM(x124) t0__32a0 ! t0__t0ma0 ! b_e_shift ! r__r_4t0
+LSYM(x125) t0__5a0 ! t0__5t0 ! b_e_t0 ! t0__5t0
+LSYM(x126) t0__64a0 ! t0__t0ma0 ! b_e_shift ! r__r_2t0
+LSYM(x127) t0__128a0 ! a1_ne_0_b_l0 ! t0__t0ma0 ! b_n_ret_t0
+LSYM(x128) t0__128a0 ! a1_ne_0_b_l1 ! r__r_t0 ! MILLIRETN
+LSYM(x129) t0__128a0 ! a1_ne_0_b_l0 ! t0__t0_a0 ! b_n_ret_t0
+LSYM(x130) t0__64a0 ! t0__t0_a0 ! b_e_shift ! r__r_2t0
+LSYM(x131) t0__8a0 ! t0__8t0_a0 ! b_e_t0 ! t0__2t0_a0
+LSYM(x132) t0__8a0 ! t0__4t0_a0 ! b_e_shift ! r__r_4t0
+LSYM(x133) t0__8a0 ! t0__4t0_a0 ! b_e_t0 ! t0__4t0_a0
+LSYM(x134) t0__8a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__2t0_a0
+LSYM(x135) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__3t0
+LSYM(x136) t0__8a0 ! t0__2t0_a0 ! b_e_shift ! r__r_8t0
+LSYM(x137) t0__8a0 ! t0__2t0_a0 ! b_e_t0 ! t0__8t0_a0
+LSYM(x138) t0__8a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__4t0_a0
+LSYM(x139) t0__8a0 ! t0__2t0_a0 ! b_e_2t0a0 ! t0__4t0_a0
+LSYM(x140) t0__3a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__5t0
+LSYM(x141) t0__8a0 ! t0__2t0_a0 ! b_e_4t0a0 ! t0__2t0_a0
+LSYM(x142) t0__9a0 ! t0__8t0 ! b_e_2t0 ! t0__t0ma0
+LSYM(x143) t0__16a0 ! t0__9t0 ! b_e_t0 ! t0__t0ma0
+LSYM(x144) t0__9a0 ! t0__8t0 ! b_e_shift ! r__r_2t0
+LSYM(x145) t0__9a0 ! t0__8t0 ! b_e_t0 ! t0__2t0_a0
+LSYM(x146) t0__9a0 ! t0__8t0_a0 ! b_e_shift ! r__r_2t0
+LSYM(x147) t0__9a0 ! t0__8t0_a0 ! b_e_t0 ! t0__2t0_a0
+LSYM(x148) t0__9a0 ! t0__4t0_a0 ! b_e_shift ! r__r_4t0
+LSYM(x149) t0__9a0 ! t0__4t0_a0 ! b_e_t0 ! t0__4t0_a0
+LSYM(x150) t0__9a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__2t0_a0
+LSYM(x151) t0__9a0 ! t0__4t0_a0 ! b_e_2t0a0 ! t0__2t0_a0
+LSYM(x152) t0__9a0 ! t0__2t0_a0 ! b_e_shift ! r__r_8t0
+LSYM(x153) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__8t0_a0
+LSYM(x154) t0__9a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__4t0_a0
+LSYM(x155) t0__32a0 ! t0__t0ma0 ! b_e_t0 ! t0__5t0
+LSYM(x156) t0__9a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__2t0_a0
+LSYM(x157) t0__32a0 ! t0__t0ma0 ! b_e_t02a0 ! t0__5t0
+LSYM(x158) t0__16a0 ! t0__5t0 ! b_e_2t0 ! t0__t0ma0
+LSYM(x159) t0__32a0 ! t0__5t0 ! b_e_t0 ! t0__t0ma0
+LSYM(x160) t0__5a0 ! t0__4t0 ! b_e_shift ! r__r_8t0
+LSYM(x161) t0__8a0 ! t0__5t0 ! b_e_t0 ! t0__4t0_a0
+LSYM(x162) t0__9a0 ! t0__9t0 ! b_e_shift ! r__r_2t0
+LSYM(x163) t0__9a0 ! t0__9t0 ! b_e_t0 ! t0__2t0_a0
+LSYM(x164) t0__5a0 ! t0__8t0_a0 ! b_e_shift ! r__r_4t0
+LSYM(x165) t0__8a0 ! t0__4t0_a0 ! b_e_t0 ! t0__5t0
+LSYM(x166) t0__5a0 ! t0__8t0_a0 ! b_e_2t0 ! t0__2t0_a0
+LSYM(x167) t0__5a0 ! t0__8t0_a0 ! b_e_2t0a0 ! t0__2t0_a0
+LSYM(x168) t0__5a0 ! t0__4t0_a0 ! b_e_shift ! r__r_8t0
+LSYM(x169) t0__5a0 ! t0__4t0_a0 ! b_e_t0 ! t0__8t0_a0
+LSYM(x170) t0__32a0 ! t0__t0_2a0 ! b_e_t0 ! t0__5t0
+LSYM(x171) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__9t0
+LSYM(x172) t0__5a0 ! t0__4t0_a0 ! b_e_4t0 ! t0__2t0_a0
+LSYM(x173) t0__9a0 ! t0__2t0_a0 ! b_e_t02a0 ! t0__9t0
+LSYM(x174) t0__32a0 ! t0__t0_2a0 ! b_e_t04a0 ! t0__5t0
+LSYM(x175) t0__8a0 ! t0__2t0_a0 ! b_e_5t0 ! t0__2t0_a0
+LSYM(x176) t0__5a0 ! t0__4t0_a0 ! b_e_8t0 ! t0__t0_a0
+LSYM(x177) t0__5a0 ! t0__4t0_a0 ! b_e_8t0a0 ! t0__t0_a0
+LSYM(x178) t0__5a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__8t0_a0
+LSYM(x179) t0__5a0 ! t0__2t0_a0 ! b_e_2t0a0 ! t0__8t0_a0
+LSYM(x180) t0__9a0 ! t0__5t0 ! b_e_shift ! r__r_4t0
+LSYM(x181) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__4t0_a0
+LSYM(x182) t0__9a0 ! t0__5t0 ! b_e_2t0 ! t0__2t0_a0
+LSYM(x183) t0__9a0 ! t0__5t0 ! b_e_2t0a0 ! t0__2t0_a0
+LSYM(x184) t0__5a0 ! t0__9t0 ! b_e_4t0 ! t0__t0_a0
+LSYM(x185) t0__9a0 ! t0__4t0_a0 ! b_e_t0 ! t0__5t0
+LSYM(x186) t0__32a0 ! t0__t0ma0 ! b_e_2t0 ! t0__3t0
+LSYM(x187) t0__9a0 ! t0__4t0_a0 ! b_e_t02a0 ! t0__5t0
+LSYM(x188) t0__9a0 ! t0__5t0 ! b_e_4t0 ! t0__t0_2a0
+LSYM(x189) t0__5a0 ! t0__4t0_a0 ! b_e_t0 ! t0__9t0
+LSYM(x190) t0__9a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__5t0
+LSYM(x191) t0__64a0 ! t0__3t0 ! b_e_t0 ! t0__t0ma0
+LSYM(x192) t0__8a0 ! t0__3t0 ! b_e_shift ! r__r_8t0
+LSYM(x193) t0__8a0 ! t0__3t0 ! b_e_t0 ! t0__8t0_a0
+LSYM(x194) t0__8a0 ! t0__3t0 ! b_e_2t0 ! t0__4t0_a0
+LSYM(x195) t0__8a0 ! t0__8t0_a0 ! b_e_t0 ! t0__3t0
+LSYM(x196) t0__8a0 ! t0__3t0 ! b_e_4t0 ! t0__2t0_a0
+LSYM(x197) t0__8a0 ! t0__3t0 ! b_e_4t0a0 ! t0__2t0_a0
+LSYM(x198) t0__64a0 ! t0__t0_2a0 ! b_e_t0 ! t0__3t0
+LSYM(x199) t0__8a0 ! t0__4t0_a0 ! b_e_2t0a0 ! t0__3t0
+LSYM(x200) t0__5a0 ! t0__5t0 ! b_e_shift ! r__r_8t0
+LSYM(x201) t0__5a0 ! t0__5t0 ! b_e_t0 ! t0__8t0_a0
+LSYM(x202) t0__5a0 ! t0__5t0 ! b_e_2t0 ! t0__4t0_a0
+LSYM(x203) t0__5a0 ! t0__5t0 ! b_e_2t0a0 ! t0__4t0_a0
+LSYM(x204) t0__8a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__3t0
+LSYM(x205) t0__5a0 ! t0__8t0_a0 ! b_e_t0 ! t0__5t0
+LSYM(x206) t0__64a0 ! t0__t0_4a0 ! b_e_t02a0 ! t0__3t0
+LSYM(x207) t0__8a0 ! t0__2t0_a0 ! b_e_3t0 ! t0__4t0_a0
+LSYM(x208) t0__5a0 ! t0__5t0 ! b_e_8t0 ! t0__t0_a0
+LSYM(x209) t0__5a0 ! t0__5t0 ! b_e_8t0a0 ! t0__t0_a0
+LSYM(x210) t0__5a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__5t0
+LSYM(x211) t0__5a0 ! t0__4t0_a0 ! b_e_2t0a0 ! t0__5t0
+LSYM(x212) t0__3a0 ! t0__4t0_a0 ! b_e_4t0 ! t0__4t0_a0
+LSYM(x213) t0__3a0 ! t0__4t0_a0 ! b_e_4t0a0 ! t0__4t0_a0
+LSYM(x214) t0__9a0 ! t0__t0_4a0 ! b_e_2t04a0 ! t0__8t0_a0
+LSYM(x215) t0__5a0 ! t0__4t0_a0 ! b_e_5t0 ! t0__2t0_a0
+LSYM(x216) t0__9a0 ! t0__3t0 ! b_e_shift ! r__r_8t0
+LSYM(x217) t0__9a0 ! t0__3t0 ! b_e_t0 ! t0__8t0_a0
+LSYM(x218) t0__9a0 ! t0__3t0 ! b_e_2t0 ! t0__4t0_a0
+LSYM(x219) t0__9a0 ! t0__8t0_a0 ! b_e_t0 ! t0__3t0
+LSYM(x220) t0__3a0 ! t0__9t0 ! b_e_4t0 ! t0__2t0_a0
+LSYM(x221) t0__3a0 ! t0__9t0 ! b_e_4t0a0 ! t0__2t0_a0
+LSYM(x222) t0__9a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__3t0
+LSYM(x223) t0__9a0 ! t0__4t0_a0 ! b_e_2t0a0 ! t0__3t0
+LSYM(x224) t0__9a0 ! t0__3t0 ! b_e_8t0 ! t0__t0_a0
+LSYM(x225) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__5t0
+LSYM(x226) t0__3a0 ! t0__2t0_a0 ! b_e_t02a0 ! t0__32t0
+LSYM(x227) t0__9a0 ! t0__5t0 ! b_e_t02a0 ! t0__5t0
+LSYM(x228) t0__9a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__3t0
+LSYM(x229) t0__9a0 ! t0__2t0_a0 ! b_e_4t0a0 ! t0__3t0
+LSYM(x230) t0__9a0 ! t0__5t0 ! b_e_5t0 ! t0__t0_a0
+LSYM(x231) t0__9a0 ! t0__2t0_a0 ! b_e_3t0 ! t0__4t0_a0
+LSYM(x232) t0__3a0 ! t0__2t0_a0 ! b_e_8t0 ! t0__4t0_a0
+LSYM(x233) t0__3a0 ! t0__2t0_a0 ! b_e_8t0a0 ! t0__4t0_a0
+LSYM(x234) t0__3a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__9t0
+LSYM(x235) t0__3a0 ! t0__4t0_a0 ! b_e_2t0a0 ! t0__9t0
+LSYM(x236) t0__9a0 ! t0__2t0_a0 ! b_e_4t08a0 ! t0__3t0
+LSYM(x237) t0__16a0 ! t0__5t0 ! b_e_3t0 ! t0__t0ma0
+LSYM(x238) t0__3a0 ! t0__4t0_a0 ! b_e_2t04a0 ! t0__9t0
+LSYM(x239) t0__16a0 ! t0__5t0 ! b_e_t0ma0 ! t0__3t0
+LSYM(x240) t0__9a0 ! t0__t0_a0 ! b_e_8t0 ! t0__3t0
+LSYM(x241) t0__9a0 ! t0__t0_a0 ! b_e_8t0a0 ! t0__3t0
+LSYM(x242) t0__5a0 ! t0__3t0 ! b_e_2t0 ! t0__8t0_a0
+LSYM(x243) t0__9a0 ! t0__9t0 ! b_e_t0 ! t0__3t0
+LSYM(x244) t0__5a0 ! t0__3t0 ! b_e_4t0 ! t0__4t0_a0
+LSYM(x245) t0__8a0 ! t0__3t0 ! b_e_5t0 ! t0__2t0_a0
+LSYM(x246) t0__5a0 ! t0__8t0_a0 ! b_e_2t0 ! t0__3t0
+LSYM(x247) t0__5a0 ! t0__8t0_a0 ! b_e_2t0a0 ! t0__3t0
+LSYM(x248) t0__32a0 ! t0__t0ma0 ! b_e_shift ! r__r_8t0
+LSYM(x249) t0__32a0 ! t0__t0ma0 ! b_e_t0 ! t0__8t0_a0
+LSYM(x250) t0__5a0 ! t0__5t0 ! b_e_2t0 ! t0__5t0
+LSYM(x251) t0__5a0 ! t0__5t0 ! b_e_2t0a0 ! t0__5t0
+LSYM(x252) t0__64a0 ! t0__t0ma0 ! b_e_shift ! r__r_4t0
+LSYM(x253) t0__64a0 ! t0__t0ma0 ! b_e_t0 ! t0__4t0_a0
+LSYM(x254) t0__128a0 ! t0__t0ma0 ! b_e_shift ! r__r_2t0
+LSYM(x255) t0__256a0 ! a1_ne_0_b_l0 ! t0__t0ma0 ! b_n_ret_t0
+/*1040 insts before this. */
+LSYM(ret_t0) MILLIRET
+LSYM(e_t0) r__r_t0
+LSYM(e_shift) a1_ne_0_b_l2
+ a0__256a0 /* a0 <<= 8 *********** */
+ MILLIRETN
+LSYM(e_t0ma0) a1_ne_0_b_l0
+ t0__t0ma0
+ MILLIRET
+ r__r_t0
+LSYM(e_t0a0) a1_ne_0_b_l0
+ t0__t0_a0
+ MILLIRET
+ r__r_t0
+LSYM(e_t02a0) a1_ne_0_b_l0
+ t0__t0_2a0
+ MILLIRET
+ r__r_t0
+LSYM(e_t04a0) a1_ne_0_b_l0
+ t0__t0_4a0
+ MILLIRET
+ r__r_t0
+LSYM(e_2t0) a1_ne_0_b_l1
+ r__r_2t0
+ MILLIRETN
+LSYM(e_2t0a0) a1_ne_0_b_l0
+ t0__2t0_a0
+ MILLIRET
+ r__r_t0
+LSYM(e2t04a0) t0__t0_2a0
+ a1_ne_0_b_l1
+ r__r_2t0
+ MILLIRETN
+LSYM(e_3t0) a1_ne_0_b_l0
+ t0__3t0
+ MILLIRET
+ r__r_t0
+LSYM(e_4t0) a1_ne_0_b_l1
+ r__r_4t0
+ MILLIRETN
+LSYM(e_4t0a0) a1_ne_0_b_l0
+ t0__4t0_a0
+ MILLIRET
+ r__r_t0
+LSYM(e4t08a0) t0__t0_2a0
+ a1_ne_0_b_l1
+ r__r_4t0
+ MILLIRETN
+LSYM(e_5t0) a1_ne_0_b_l0
+ t0__5t0
+ MILLIRET
+ r__r_t0
+LSYM(e_8t0) a1_ne_0_b_l1
+ r__r_8t0
+ MILLIRETN
+LSYM(e_8t0a0) a1_ne_0_b_l0
+ t0__8t0_a0
+ MILLIRET
+ r__r_t0
+
+ .procend
+ .end
+#endif
diff --git a/arch/parisc/lib/milli/remI.S b/arch/parisc/lib/milli/remI.S
new file mode 100644
index 000000000000..63bc094471e2
--- /dev/null
+++ b/arch/parisc/lib/milli/remI.S
@@ -0,0 +1,185 @@
+/* 32 and 64-bit millicode, original author Hewlett-Packard
+ adapted for gcc by Paul Bame <bame@debian.org>
+ and Alan Modra <alan@linuxcare.com.au>.
+
+ Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
+
+ This file is part of GCC and is released under the terms of
+ of the GNU General Public License as published by the Free Software
+ Foundation; either version 2, or (at your option) any later version.
+ See the file COPYING in the top-level GCC source directory for a copy
+ of the license. */
+
+#include "milli.h"
+
+#ifdef L_remI
+/* ROUTINE: $$remI
+
+ DESCRIPTION:
+ . $$remI returns the remainder of the division of two signed 32-bit
+ . integers. The sign of the remainder is the same as the sign of
+ . the dividend.
+
+
+ INPUT REGISTERS:
+ . arg0 == dividend
+ . arg1 == divisor
+ . mrp == return pc
+ . sr0 == return space when called externally
+
+ OUTPUT REGISTERS:
+ . arg0 = destroyed
+ . arg1 = destroyed
+ . ret1 = remainder
+
+ OTHER REGISTERS AFFECTED:
+ . r1 = undefined
+
+ SIDE EFFECTS:
+ . Causes a trap under the following conditions: DIVIDE BY ZERO
+ . Changes memory at the following places: NONE
+
+ PERMISSIBLE CONTEXT:
+ . Unwindable
+ . Does not create a stack frame
+ . Is usable for internal or external microcode
+
+ DISCUSSION:
+ . Calls other millicode routines via mrp: NONE
+ . Calls other millicode routines: NONE */
+
+RDEFINE(tmp,r1)
+RDEFINE(retreg,ret1)
+
+ SUBSPA_MILLI
+ ATTR_MILLI
+ .proc
+ .callinfo millicode
+ .entry
+GSYM($$remI)
+GSYM($$remoI)
+ .export $$remI,MILLICODE
+ .export $$remoI,MILLICODE
+ ldo -1(arg1),tmp /* is there at most one bit set ? */
+ and,<> arg1,tmp,r0 /* if not, don't use power of 2 */
+ addi,> 0,arg1,r0 /* if denominator > 0, use power */
+ /* of 2 */
+ b,n LREF(neg_denom)
+LSYM(pow2)
+ comb,>,n 0,arg0,LREF(neg_num) /* is numerator < 0 ? */
+ and arg0,tmp,retreg /* get the result */
+ MILLIRETN
+LSYM(neg_num)
+ subi 0,arg0,arg0 /* negate numerator */
+ and arg0,tmp,retreg /* get the result */
+ subi 0,retreg,retreg /* negate result */
+ MILLIRETN
+LSYM(neg_denom)
+ addi,< 0,arg1,r0 /* if arg1 >= 0, it's not power */
+ /* of 2 */
+ b,n LREF(regular_seq)
+ sub r0,arg1,tmp /* make denominator positive */
+ comb,=,n arg1,tmp,LREF(regular_seq) /* test against 0x80000000 and 0 */
+ ldo -1(tmp),retreg /* is there at most one bit set ? */
+ and,= tmp,retreg,r0 /* if not, go to regular_seq */
+ b,n LREF(regular_seq)
+ comb,>,n 0,arg0,LREF(neg_num_2) /* if arg0 < 0, negate it */
+ and arg0,retreg,retreg
+ MILLIRETN
+LSYM(neg_num_2)
+ subi 0,arg0,tmp /* test against 0x80000000 */
+ and tmp,retreg,retreg
+ subi 0,retreg,retreg
+ MILLIRETN
+LSYM(regular_seq)
+ addit,= 0,arg1,0 /* trap if div by zero */
+ add,>= 0,arg0,retreg /* move dividend, if retreg < 0, */
+ sub 0,retreg,retreg /* make it positive */
+ sub 0,arg1, tmp /* clear carry, */
+ /* negate the divisor */
+ ds 0, tmp,0 /* set V-bit to the comple- */
+ /* ment of the divisor sign */
+ or 0,0, tmp /* clear tmp */
+ add retreg,retreg,retreg /* shift msb bit into carry */
+ ds tmp,arg1, tmp /* 1st divide step, if no carry */
+ /* out, msb of quotient = 0 */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+LSYM(t1)
+ ds tmp,arg1, tmp /* 2nd divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 3rd divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 4th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 5th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 6th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 7th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 8th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 9th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 10th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 11th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 12th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 13th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 14th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 15th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 16th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 17th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 18th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 19th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 20th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 21st divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 22nd divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 23rd divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 24th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 25th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 26th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 27th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 28th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 29th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 30th divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 31st divide step */
+ addc retreg,retreg,retreg /* shift retreg with/into carry */
+ ds tmp,arg1, tmp /* 32nd divide step, */
+ addc retreg,retreg,retreg /* shift last bit into retreg */
+ movb,>=,n tmp,retreg,LREF(finish) /* branch if pos. tmp */
+ add,< arg1,0,0 /* if arg1 > 0, add arg1 */
+ add,tr tmp,arg1,retreg /* for correcting remainder tmp */
+ sub tmp,arg1,retreg /* else add absolute value arg1 */
+LSYM(finish)
+ add,>= arg0,0,0 /* set sign of remainder */
+ sub 0,retreg,retreg /* to sign of dividend */
+ MILLIRET
+ nop
+ .exit
+ .procend
+#ifdef milliext
+ .origin 0x00000200
+#endif
+ .end
+#endif
diff --git a/arch/parisc/lib/milli/remU.S b/arch/parisc/lib/milli/remU.S
new file mode 100644
index 000000000000..c0a2d6e247c3
--- /dev/null
+++ b/arch/parisc/lib/milli/remU.S
@@ -0,0 +1,148 @@
+/* 32 and 64-bit millicode, original author Hewlett-Packard
+ adapted for gcc by Paul Bame <bame@debian.org>
+ and Alan Modra <alan@linuxcare.com.au>.
+
+ Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
+
+ This file is part of GCC and is released under the terms of
+ of the GNU General Public License as published by the Free Software
+ Foundation; either version 2, or (at your option) any later version.
+ See the file COPYING in the top-level GCC source directory for a copy
+ of the license. */
+
+#include "milli.h"
+
+#ifdef L_remU
+/* ROUTINE: $$remU
+ . Single precision divide for remainder with unsigned binary integers.
+ .
+ . The remainder must be dividend-(dividend/divisor)*divisor.
+ . Divide by zero is trapped.
+
+ INPUT REGISTERS:
+ . arg0 == dividend
+ . arg1 == divisor
+ . mrp == return pc
+ . sr0 == return space when called externally
+
+ OUTPUT REGISTERS:
+ . arg0 = undefined
+ . arg1 = undefined
+ . ret1 = remainder
+
+ OTHER REGISTERS AFFECTED:
+ . r1 = undefined
+
+ SIDE EFFECTS:
+ . Causes a trap under the following conditions: DIVIDE BY ZERO
+ . Changes memory at the following places: NONE
+
+ PERMISSIBLE CONTEXT:
+ . Unwindable.
+ . Does not create a stack frame.
+ . Suitable for internal or external millicode.
+ . Assumes the special millicode register conventions.
+
+ DISCUSSION:
+ . Calls other millicode routines using mrp: NONE
+ . Calls other millicode routines: NONE */
+
+
+RDEFINE(temp,r1)
+RDEFINE(rmndr,ret1) /* r29 */
+ SUBSPA_MILLI
+ ATTR_MILLI
+ .export $$remU,millicode
+ .proc
+ .callinfo millicode
+ .entry
+GSYM($$remU)
+ ldo -1(arg1),temp /* is there at most one bit set ? */
+ and,= arg1,temp,r0 /* if not, don't use power of 2 */
+ b LREF(regular_seq)
+ addit,= 0,arg1,r0 /* trap on div by zero */
+ and arg0,temp,rmndr /* get the result for power of 2 */
+ MILLIRETN
+LSYM(regular_seq)
+ comib,>=,n 0,arg1,LREF(special_case)
+ subi 0,arg1,rmndr /* clear carry, negate the divisor */
+ ds r0,rmndr,r0 /* set V-bit to 1 */
+ add arg0,arg0,temp /* shift msb bit into carry */
+ ds r0,arg1,rmndr /* 1st divide step, if no carry */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 2nd divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 3rd divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 4th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 5th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 6th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 7th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 8th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 9th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 10th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 11th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 12th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 13th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 14th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 15th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 16th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 17th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 18th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 19th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 20th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 21st divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 22nd divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 23rd divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 24th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 25th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 26th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 27th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 28th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 29th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 30th divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 31st divide step */
+ addc temp,temp,temp /* shift temp with/into carry */
+ ds rmndr,arg1,rmndr /* 32nd divide step, */
+ comiclr,<= 0,rmndr,r0
+ add rmndr,arg1,rmndr /* correction */
+ MILLIRETN
+ nop
+
+/* Putting >= on the last DS and deleting COMICLR does not work! */
+LSYM(special_case)
+ sub,>>= arg0,arg1,rmndr
+ copy arg0,rmndr
+ MILLIRETN
+ nop
+ .exit
+ .procend
+ .end
+#endif
diff --git a/arch/parisc/math-emu/Makefile b/arch/parisc/math-emu/Makefile
index affd4c80e3b7..1f3f225897f5 100644
--- a/arch/parisc/math-emu/Makefile
+++ b/arch/parisc/math-emu/Makefile
@@ -3,7 +3,7 @@
#
# See arch/parisc/math-emu/README
-CFLAGS += -Wno-parentheses -Wno-implicit-function-declaration \
+EXTRA_CFLAGS += -Wno-parentheses -Wno-implicit-function-declaration \
-Wno-uninitialized -Wno-strict-prototypes -Wno-return-type \
-Wno-implicit-int
diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c
index 7899ab87785a..b2e3e9a8cece 100644
--- a/arch/parisc/mm/fault.c
+++ b/arch/parisc/mm/fault.c
@@ -211,7 +211,7 @@ bad_area:
#ifdef PRINT_USER_FAULTS
printk(KERN_DEBUG "\n");
printk(KERN_DEBUG "do_page_fault() pid=%d command='%s' type=%lu address=0x%08lx\n",
- tsk->pid, tsk->comm, code, address);
+ task_pid_nr(tsk), tsk->comm, code, address);
if (vma) {
printk(KERN_DEBUG "vm_start = 0x%08lx, vm_end = 0x%08lx\n",
vma->vm_start, vma->vm_end);
@@ -263,6 +263,6 @@ no_context:
up_read(&mm->mmap_sem);
printk(KERN_CRIT "VM: killing process %s\n", current->comm);
if (user_mode(regs))
- do_exit(SIGKILL);
+ do_group_exit(SIGKILL);
goto no_context;
}
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index e724b362c49a..aa875fa43488 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -607,7 +607,7 @@ void show_mem(void)
printk("Zone list for zone %d on node %d: ", j, i);
for (k = 0; zl->zones[k] != NULL; k++)
- printk("[%ld/%s] ", zone_to_nid(zl->zones[k]), zl->zones[k]->name);
+ printk("[%d/%s] ", zone_to_nid(zl->zones[k]), zl->zones[k]->name);
printk("\n");
}
}
diff --git a/arch/parisc/oprofile/Kconfig b/arch/parisc/oprofile/Kconfig
deleted file mode 100644
index 5ade19801b97..000000000000
--- a/arch/parisc/oprofile/Kconfig
+++ /dev/null
@@ -1,23 +0,0 @@
-
-menu "Profiling support"
- depends on EXPERIMENTAL
-
-config PROFILING
- bool "Profiling support (EXPERIMENTAL)"
- help
- Say Y here to enable the extended profiling support mechanisms used
- by profilers such as OProfile.
-
-
-config OPROFILE
- tristate "OProfile system profiling (EXPERIMENTAL)"
- depends on PROFILING
- help
- OProfile is a profiling system capable of profiling the
- whole system, include the kernel, kernel modules, libraries,
- and applications.
-
- If unsure, say N.
-
-endmenu
-
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 037664d496d7..18f397ca05ef 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -295,6 +295,7 @@ config ARCH_FLATMEM_ENABLE
config ARCH_SPARSEMEM_ENABLE
def_bool y
depends on PPC64
+ select SPARSEMEM_VMEMMAP_ENABLE
config ARCH_SPARSEMEM_DEFAULT
def_bool y
@@ -668,21 +669,7 @@ source "arch/powerpc/sysdev/qe_lib/Kconfig"
source "lib/Kconfig"
-menu "Instrumentation Support"
- depends on EXPERIMENTAL
-
-source "arch/powerpc/oprofile/Kconfig"
-
-config KPROBES
- bool "Kprobes"
- depends on !BOOKE && !4xx && KALLSYMS && MODULES
- help
- Kprobes allows you to trap at almost any kernel address and
- execute a callback function. register_kprobe() establishes
- a probepoint and specifies the callback. Kprobes is useful
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-endmenu
+source "kernel/Kconfig.instrumentation"
source "arch/powerpc/Kconfig.debug"
@@ -698,3 +685,7 @@ source "crypto/Kconfig"
config PPC_CLOCK
bool
default n
+
+config PPC_LIB_RHEAP
+ bool
+
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index 464f9b4b3169..6a79fe43e229 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -144,7 +144,7 @@ config BDI_SWITCH
config BOOTX_TEXT
bool "Support for early boot text console (BootX or OpenFirmware only)"
- depends PPC_OF && PPC_MULTIPLATFORM
+ depends on PPC_OF && PPC_MULTIPLATFORM
help
Say Y here to see progress messages from the boot firmware in text
mode. Requires either BootX or Open Firmware.
@@ -216,7 +216,6 @@ config PPC_EARLY_DEBUG_BEAT
config PPC_EARLY_DEBUG_44x
bool "Early serial debugging for IBM/AMCC 44x CPUs"
depends on 44x
- select PPC_UDBG_16550
help
Select this to enable early debugging for IBM 44x chips via the
inbuilt serial port.
@@ -234,12 +233,12 @@ endchoice
config PPC_EARLY_DEBUG_44x_PHYSLOW
hex "Low 32 bits of early debug UART physical address"
- depends PPC_EARLY_DEBUG_44x
+ depends on PPC_EARLY_DEBUG_44x
default "0x40000200"
config PPC_EARLY_DEBUG_44x_PHYSHIGH
hex "EPRN of early debug UART physical address"
- depends PPC_EARLY_DEBUG_44x
+ depends on PPC_EARLY_DEBUG_44x
default "0x1"
config PPC_EARLY_DEBUG_CPM_ADDR
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index 643839a3f5d8..bd87626c1f60 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -75,10 +75,10 @@ CPPFLAGS-$(CONFIG_PPC32) := -Iarch/$(ARCH)
AFLAGS-$(CONFIG_PPC32) := -Iarch/$(ARCH)
CFLAGS-$(CONFIG_PPC64) := -mminimal-toc -mtraceback=none -mcall-aixdesc
CFLAGS-$(CONFIG_PPC32) := -Iarch/$(ARCH) -ffixed-r2 -mmultiple
-CPPFLAGS += $(CPPFLAGS-y)
-AFLAGS += $(AFLAGS-y)
-CFLAGS += -msoft-float -pipe $(CFLAGS-y)
-CPP = $(CC) -E $(CFLAGS)
+KBUILD_CPPFLAGS += $(CPPFLAGS-y)
+KBUILD_AFLAGS += $(AFLAGS-y)
+KBUILD_CFLAGS += -msoft-float -pipe $(CFLAGS-y)
+CPP = $(CC) -E $(KBUILD_CFLAGS)
CHECKFLAGS += -m$(CONFIG_WORD_SIZE) -D__powerpc__ -D__powerpc$(CONFIG_WORD_SIZE)__
@@ -88,35 +88,38 @@ GCC_BROKEN_VEC := $(shell if [ $(call cc-version) -lt 0400 ] ; then echo "y"; fi
ifeq ($(CONFIG_POWER4_ONLY),y)
ifeq ($(CONFIG_ALTIVEC),y)
ifeq ($(GCC_BROKEN_VEC),y)
- CFLAGS += $(call cc-option,-mcpu=970)
+ KBUILD_CFLAGS += $(call cc-option,-mcpu=970)
else
- CFLAGS += $(call cc-option,-mcpu=power4)
+ KBUILD_CFLAGS += $(call cc-option,-mcpu=power4)
endif
else
- CFLAGS += $(call cc-option,-mcpu=power4)
+ KBUILD_CFLAGS += $(call cc-option,-mcpu=power4)
endif
else
- CFLAGS += $(call cc-option,-mtune=power4)
+ KBUILD_CFLAGS += $(call cc-option,-mtune=power4)
endif
endif
ifeq ($(CONFIG_TUNE_CELL),y)
- CFLAGS += $(call cc-option,-mtune=cell)
+ KBUILD_CFLAGS += $(call cc-option,-mtune=cell)
endif
# No AltiVec instruction when building kernel
-CFLAGS += $(call cc-option,-mno-altivec)
+KBUILD_CFLAGS += $(call cc-option,-mno-altivec)
+
+# No SPE instruction when building kernel
+KBUILD_CFLAGS += $(call cc-option,-mno-spe)
# Enable unit-at-a-time mode when possible. It shrinks the
# kernel considerably.
-CFLAGS += $(call cc-option,-funit-at-a-time)
+KBUILD_CFLAGS += $(call cc-option,-funit-at-a-time)
# Never use string load/store instructions as they are
# often slow when they are implemented at all
-CFLAGS += -mno-string
+KBUILD_CFLAGS += -mno-string
ifeq ($(CONFIG_6xx),y)
-CFLAGS += -mcpu=powerpc
+KBUILD_CFLAGS += -mcpu=powerpc
endif
cpu-as-$(CONFIG_4xx) += -Wa,-m405
@@ -125,8 +128,8 @@ cpu-as-$(CONFIG_POWER4) += -Wa,-maltivec
cpu-as-$(CONFIG_E500) += -Wa,-me500
cpu-as-$(CONFIG_E200) += -Wa,-me200
-AFLAGS += $(cpu-as-y)
-CFLAGS += $(cpu-as-y)
+KBUILD_AFLAGS += $(cpu-as-y)
+KBUILD_CFLAGS += $(cpu-as-y)
head-y := arch/powerpc/kernel/head_$(CONFIG_WORD_SIZE).o
head-$(CONFIG_8xx) := arch/powerpc/kernel/head_8xx.o
diff --git a/arch/powerpc/boot/dts/bamboo.dts b/arch/powerpc/boot/dts/bamboo.dts
index a88ae3d218a5..cb2fb50a281c 100644
--- a/arch/powerpc/boot/dts/bamboo.dts
+++ b/arch/powerpc/boot/dts/bamboo.dts
@@ -98,11 +98,13 @@
interrupt-parent = <&MAL0>;
interrupts = <0 1 2 3 4>;
#interrupt-cells = <1>;
+ #address-cells = <0>;
+ #size-cells = <0>;
interrupt-map = </*TXEOB*/ 0 &UIC0 a 4
/*RXEOB*/ 1 &UIC0 b 4
/*SERR*/ 2 &UIC1 0 4
/*TXDE*/ 3 &UIC1 1 4
- /*RXDE*/ 4 &UIC1 3 4>;
+ /*RXDE*/ 4 &UIC1 2 4>;
};
POB0: opb {
@@ -196,6 +198,7 @@
};
EMAC0: ethernet@ef600e00 {
+ linux,network-index = <0>;
device_type = "network";
compatible = "ibm,emac-440ep", "ibm,emac-440gp", "ibm,emac";
interrupt-parent = <&UIC1>;
@@ -210,12 +213,13 @@
rx-fifo-size = <1000>;
tx-fifo-size = <800>;
phy-mode = "rmii";
- phy-map = <00000001>;
+ phy-map = <00000000>;
zmii-device = <&ZMII0>;
zmii-channel = <0>;
};
EMAC1: ethernet@ef600f00 {
+ linux,network-index = <1>;
device_type = "network";
compatible = "ibm,emac-440ep", "ibm,emac-440gp", "ibm,emac";
interrupt-parent = <&UIC1>;
@@ -230,7 +234,7 @@
rx-fifo-size = <1000>;
tx-fifo-size = <800>;
phy-mode = "rmii";
- phy-map = <00000001>;
+ phy-map = <00000000>;
zmii-device = <&ZMII0>;
zmii-channel = <1>;
};
diff --git a/arch/powerpc/boot/dts/lite5200.dts b/arch/powerpc/boot/dts/lite5200.dts
index bc45f5fbb060..6731763f0282 100644
--- a/arch/powerpc/boot/dts/lite5200.dts
+++ b/arch/powerpc/boot/dts/lite5200.dts
@@ -70,18 +70,16 @@
};
gpt@600 { // General Purpose Timer
- compatible = "mpc5200-gpt";
- device_type = "gpt";
+ compatible = "fsl,mpc5200-gpt";
cell-index = <0>;
reg = <600 10>;
interrupts = <1 9 0>;
interrupt-parent = <&mpc5200_pic>;
- has-wdt;
+ fsl,has-wdt;
};
gpt@610 { // General Purpose Timer
- compatible = "mpc5200-gpt";
- device_type = "gpt";
+ compatible = "fsl,mpc5200-gpt";
cell-index = <1>;
reg = <610 10>;
interrupts = <1 a 0>;
@@ -89,8 +87,7 @@
};
gpt@620 { // General Purpose Timer
- compatible = "mpc5200-gpt";
- device_type = "gpt";
+ compatible = "fsl,mpc5200-gpt";
cell-index = <2>;
reg = <620 10>;
interrupts = <1 b 0>;
@@ -98,8 +95,7 @@
};
gpt@630 { // General Purpose Timer
- compatible = "mpc5200-gpt";
- device_type = "gpt";
+ compatible = "fsl,mpc5200-gpt";
cell-index = <3>;
reg = <630 10>;
interrupts = <1 c 0>;
@@ -107,8 +103,7 @@
};
gpt@640 { // General Purpose Timer
- compatible = "mpc5200-gpt";
- device_type = "gpt";
+ compatible = "fsl,mpc5200-gpt";
cell-index = <4>;
reg = <640 10>;
interrupts = <1 d 0>;
@@ -116,8 +111,7 @@
};
gpt@650 { // General Purpose Timer
- compatible = "mpc5200-gpt";
- device_type = "gpt";
+ compatible = "fsl,mpc5200-gpt";
cell-index = <5>;
reg = <650 10>;
interrupts = <1 e 0>;
@@ -125,8 +119,7 @@
};
gpt@660 { // General Purpose Timer
- compatible = "mpc5200-gpt";
- device_type = "gpt";
+ compatible = "fsl,mpc5200-gpt";
cell-index = <6>;
reg = <660 10>;
interrupts = <1 f 0>;
@@ -134,8 +127,7 @@
};
gpt@670 { // General Purpose Timer
- compatible = "mpc5200-gpt";
- device_type = "gpt";
+ compatible = "fsl,mpc5200-gpt";
cell-index = <7>;
reg = <670 10>;
interrupts = <1 10 0>;
diff --git a/arch/powerpc/boot/dts/lite5200b.dts b/arch/powerpc/boot/dts/lite5200b.dts
index a6bb1d0558ef..b540388c608c 100644
--- a/arch/powerpc/boot/dts/lite5200b.dts
+++ b/arch/powerpc/boot/dts/lite5200b.dts
@@ -70,18 +70,16 @@
};
gpt@600 { // General Purpose Timer
- compatible = "mpc5200b-gpt","mpc5200-gpt";
- device_type = "gpt";
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
cell-index = <0>;
reg = <600 10>;
interrupts = <1 9 0>;
interrupt-parent = <&mpc5200_pic>;
- has-wdt;
+ fsl,has-wdt;
};
gpt@610 { // General Purpose Timer
- compatible = "mpc5200b-gpt","mpc5200-gpt";
- device_type = "gpt";
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
cell-index = <1>;
reg = <610 10>;
interrupts = <1 a 0>;
@@ -89,8 +87,7 @@
};
gpt@620 { // General Purpose Timer
- compatible = "mpc5200b-gpt","mpc5200-gpt";
- device_type = "gpt";
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
cell-index = <2>;
reg = <620 10>;
interrupts = <1 b 0>;
@@ -98,8 +95,7 @@
};
gpt@630 { // General Purpose Timer
- compatible = "mpc5200b-gpt","mpc5200-gpt";
- device_type = "gpt";
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
cell-index = <3>;
reg = <630 10>;
interrupts = <1 c 0>;
@@ -107,8 +103,7 @@
};
gpt@640 { // General Purpose Timer
- compatible = "mpc5200b-gpt","mpc5200-gpt";
- device_type = "gpt";
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
cell-index = <4>;
reg = <640 10>;
interrupts = <1 d 0>;
@@ -116,8 +111,7 @@
};
gpt@650 { // General Purpose Timer
- compatible = "mpc5200b-gpt","mpc5200-gpt";
- device_type = "gpt";
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
cell-index = <5>;
reg = <650 10>;
interrupts = <1 e 0>;
@@ -125,8 +119,7 @@
};
gpt@660 { // General Purpose Timer
- compatible = "mpc5200b-gpt","mpc5200-gpt";
- device_type = "gpt";
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
cell-index = <6>;
reg = <660 10>;
interrupts = <1 f 0>;
@@ -134,8 +127,7 @@
};
gpt@670 { // General Purpose Timer
- compatible = "mpc5200b-gpt","mpc5200-gpt";
- device_type = "gpt";
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
cell-index = <7>;
reg = <670 10>;
interrupts = <1 10 0>;
@@ -277,10 +269,26 @@
ethernet@3000 {
device_type = "network";
compatible = "mpc5200b-fec","mpc5200-fec";
- reg = <3000 800>;
+ reg = <3000 400>;
mac-address = [ 02 03 04 05 06 07 ]; // Bad!
interrupts = <2 5 0>;
interrupt-parent = <&mpc5200_pic>;
+ phy-handle = <&phy0>;
+ };
+
+ mdio@3000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ device_type = "mdio";
+ compatible = "mpc5200b-fec-phy";
+ reg = <3000 400>; // fec range, since we need to setup fec interrupts
+ interrupts = <2 5 0>; // these are for "mii command finished", not link changes & co.
+ interrupt-parent = <&mpc5200_pic>;
+
+ phy0:ethernet-phy@0 {
+ device_type = "ethernet-phy";
+ reg = <0>;
+ };
};
ata@3a00 {
diff --git a/arch/powerpc/boot/dts/sequoia.dts b/arch/powerpc/boot/dts/sequoia.dts
index 36be75b04de1..8833dfe2e8b4 100644
--- a/arch/powerpc/boot/dts/sequoia.dts
+++ b/arch/powerpc/boot/dts/sequoia.dts
@@ -241,6 +241,12 @@
reg = <ef600d00 c>;
};
+ RGMII0: emac-rgmii@ef601000 {
+ device_type = "rgmii-interface";
+ compatible = "ibm,rgmii-440epx", "ibm,rgmii";
+ reg = <ef601000 8>;
+ };
+
EMAC0: ethernet@ef600e00 {
linux,network-index = <0>;
device_type = "network";
@@ -261,10 +267,12 @@
max-frame-size = <5dc>;
rx-fifo-size = <1000>;
tx-fifo-size = <800>;
- phy-mode = "rmii";
+ phy-mode = "rgmii";
phy-map = <00000000>;
zmii-device = <&ZMII0>;
zmii-channel = <0>;
+ rgmii-device = <&RGMII0>;
+ rgmii-channel = <0>;
};
EMAC1: ethernet@ef600f00 {
@@ -287,10 +295,12 @@
max-frame-size = <5dc>;
rx-fifo-size = <1000>;
tx-fifo-size = <800>;
- phy-mode = "rmii";
+ phy-mode = "rgmii";
phy-map = <00000000>;
zmii-device = <&ZMII0>;
zmii-channel = <1>;
+ rgmii-device = <&RGMII0>;
+ rgmii-channel = <1>;
};
};
};
diff --git a/arch/powerpc/boot/dts/walnut.dts b/arch/powerpc/boot/dts/walnut.dts
index ec54f4e04ad6..754fa3960f83 100644
--- a/arch/powerpc/boot/dts/walnut.dts
+++ b/arch/powerpc/boot/dts/walnut.dts
@@ -64,10 +64,15 @@
MAL: mcmal {
compatible = "ibm,mcmal-405gp", "ibm,mcmal";
dcr-reg = <180 62>;
- num-tx-chans = <2>;
+ num-tx-chans = <1>;
num-rx-chans = <1>;
interrupt-parent = <&UIC0>;
- interrupts = <a 4 b 4 c 4 d 4 e 4>;
+ interrupts = <
+ b 4 /* TXEOB */
+ c 4 /* RXEOB */
+ a 4 /* SERR */
+ d 4 /* TXDE */
+ e 4 /* RXDE */>;
};
POB0: opb {
@@ -117,10 +122,13 @@
device_type = "network";
compatible = "ibm,emac-405gp", "ibm,emac";
interrupt-parent = <&UIC0>;
- interrupts = <9 4 f 4>;
+ interrupts = <
+ f 4 /* Ethernet */
+ 9 4 /* Ethernet Wake Up */>;
+ local-mac-address = [000000000000]; /* Filled in by zImage */
reg = <ef600800 70>;
mal-device = <&MAL>;
- mal-tx-channel = <0 1>;
+ mal-tx-channel = <0>;
mal-rx-channel = <0>;
cell-index = <0>;
max-frame-size = <5dc>;
diff --git a/arch/powerpc/boot/treeboot-walnut.c b/arch/powerpc/boot/treeboot-walnut.c
index 3adf2d08a230..bb2c309d70fc 100644
--- a/arch/powerpc/boot/treeboot-walnut.c
+++ b/arch/powerpc/boot/treeboot-walnut.c
@@ -57,8 +57,8 @@ void ibm405gp_fixup_clocks(unsigned int sysclk, unsigned int ser_clk)
}
/* setup the timebase clock to tick at the cpu frequency */
- cpc0_cr1 = cpc0_cr1 & ~ 0x00800000;
- mtdcr(DCRN_CPC0_CR1, cpc0_cr1);
+ cpc0_cr1 = cpc0_cr1 & ~0x00800000;
+ mtdcr(DCRN_405_CPC0_CR1, cpc0_cr1);
tb = cpu;
dt_fixup_cpu_clocks(cpu, tb, 0);
@@ -109,6 +109,7 @@ static void walnut_flashsel_fixup(void)
setprop(sram, "reg", reg_sram, sizeof(reg_sram));
}
+#define WALNUT_OPENBIOS_MAC_OFF 0xfffffe0b
static void walnut_fixups(void)
{
ibm4xx_fixup_memsize();
@@ -116,6 +117,7 @@ static void walnut_fixups(void)
ibm4xx_quiesce_eth((u32 *)0xef600800, NULL);
ibm4xx_fixup_ebc_ranges("/plb/ebc");
walnut_flashsel_fixup();
+ dt_fixup_mac_addresses((u8 *) WALNUT_OPENBIOS_MAC_OFF);
}
void platform_init(void)
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper
index 39b27e5ef6c1..31147a037728 100755
--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -21,6 +21,14 @@
# (default ./arch/powerpc/boot)
# -W dir specify working directory for temporary files (default .)
+# Stop execution if any command fails
+set -e
+
+# Allow for verbose output
+if [ "$V" = 1 ]; then
+ set -x
+fi
+
# defaults
kernel=
ofile=zImage
@@ -111,7 +119,7 @@ if [ -n "$dts" ]; then
if [ -z "$dtb" ]; then
dtb="$platform.dtb"
fi
- dtc -O dtb -o "$dtb" -b 0 -V 16 "$dts" || exit 1
+ dtc -O dtb -o "$dtb" -b 0 -V 16 "$dts"
fi
if [ -z "$kernel" ]; then
@@ -149,7 +157,6 @@ cuboot*)
ps3)
platformo="$object/ps3-head.o $object/ps3-hvcall.o $object/ps3.o"
lds=$object/zImage.ps3.lds
- binary=y
gzip=
ext=bin
objflags="-O binary --set-section-flags=.bss=contents,alloc,load,data"
@@ -233,7 +240,7 @@ entry=`${CROSS}objdump -f "$ofile" | grep '^start address ' | cut -d' ' -f3`
if [ -n "$binary" ]; then
mv "$ofile" "$ofile".elf
- ${CROSS}objcopy -O binary "$ofile".elf "$ofile".bin
+ ${CROSS}objcopy -O binary "$ofile".elf "$ofile"
fi
# post-processing needed for some platforms
@@ -246,9 +253,9 @@ coff)
$object/hack-coff "$ofile"
;;
cuboot*)
- gzip -f -9 "$ofile".bin
+ gzip -f -9 "$ofile"
mkimage -A ppc -O linux -T kernel -C gzip -a "$base" -e "$entry" \
- $uboot_version -d "$ofile".bin.gz "$ofile"
+ $uboot_version -d "$ofile".gz "$ofile"
;;
treeboot*)
mv "$ofile" "$ofile.elf"
@@ -269,11 +276,11 @@ ps3)
# then copied to offset 0x100. At runtime the bootwrapper program
# copies the 0x100 bytes at __system_reset_kernel to addr 0x100.
- system_reset_overlay=0x`${CROSS}nm "$ofile".elf \
+ system_reset_overlay=0x`${CROSS}nm "$ofile" \
| grep ' __system_reset_overlay$' \
| cut -d' ' -f1`
system_reset_overlay=`printf "%d" $system_reset_overlay`
- system_reset_kernel=0x`${CROSS}nm "$ofile".elf \
+ system_reset_kernel=0x`${CROSS}nm "$ofile" \
| grep ' __system_reset_kernel$' \
| cut -d' ' -f1`
system_reset_kernel=`printf "%d" $system_reset_kernel`
@@ -282,23 +289,15 @@ ps3)
rm -f "$object/otheros.bld"
- msg=$(dd if="$ofile.bin" of="$ofile.bin" conv=notrunc \
- skip=$overlay_dest seek=$system_reset_kernel \
- count=$overlay_size bs=1 2>&1)
+ ${CROSS}objcopy -O binary "$ofile" "$ofile.bin"
- if [ $? -ne "0" ]; then
- echo $msg
- exit 1
- fi
-
- msg=$(dd if="$ofile.bin" of="$ofile.bin" conv=notrunc \
- skip=$system_reset_overlay seek=$overlay_dest \
- count=$overlay_size bs=1 2>&1)
+ dd if="$ofile.bin" of="$ofile.bin" conv=notrunc \
+ skip=$overlay_dest seek=$system_reset_kernel \
+ count=$overlay_size bs=1
- if [ $? -ne "0" ]; then
- echo $msg
- exit 2
- fi
+ dd if="$ofile.bin" of="$ofile.bin" conv=notrunc \
+ skip=$system_reset_overlay seek=$overlay_dest \
+ count=$overlay_size bs=1
gzip --force -9 --stdout "$ofile.bin" > "$object/otheros.bld"
;;
diff --git a/arch/powerpc/configs/bamboo_defconfig b/arch/powerpc/configs/bamboo_defconfig
index b592dec4640f..844808ebf245 100644
--- a/arch/powerpc/configs/bamboo_defconfig
+++ b/arch/powerpc/configs/bamboo_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.23-rc1
-# Fri Aug 3 10:46:53 2007
+# Linux kernel version: 2.6.23
+# Fri Oct 19 09:01:11 2007
#
# CONFIG_PPC64 is not set
@@ -22,8 +22,13 @@ CONFIG_PHYS_64BIT=y
# CONFIG_PPC_MM_SLICES is not set
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_PPC32=y
+CONFIG_WORD_SIZE=32
CONFIG_PPC_MERGE=y
CONFIG_MMU=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_IRQ_PER_CPU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
@@ -67,6 +72,8 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_FAIR_USER_SCHED=y
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_BLK_DEV_INITRD=y
@@ -87,12 +94,12 @@ CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
@@ -132,6 +139,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# CONFIG_PQ2ADS is not set
CONFIG_BAMBOO=y
# CONFIG_EBONY is not set
+# CONFIG_SEQUOIA is not set
CONFIG_440EP=y
CONFIG_IBM440EP_ERR42=y
# CONFIG_MPIC is not set
@@ -145,11 +153,16 @@ CONFIG_IBM440EP_ERR42=y
# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_CPM2 is not set
+# CONFIG_FSL_ULI1575 is not set
#
# Kernel options
#
# CONFIG_HIGHMEM is not set
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
# CONFIG_HZ_300 is not set
@@ -171,6 +184,7 @@ CONFIG_FLATMEM_MANUAL=y
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_RESOURCES_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
@@ -196,10 +210,6 @@ CONFIG_PCI_SYSCALL=y
CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_DEBUG is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
@@ -214,7 +224,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
CONFIG_HIGHMEM_START=0xfe000000
CONFIG_LOWMEM_SIZE=0x30000000
CONFIG_KERNEL_START=0xc0000000
-CONFIG_TASK_SIZE=0x80000000
+CONFIG_TASK_SIZE=0xc0000000
CONFIG_CONSISTENT_START=0xff100000
CONFIG_CONSISTENT_SIZE=0x00200000
CONFIG_BOOT_LOAD=0x01000000
@@ -251,6 +261,7 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
# CONFIG_INET_XFRM_MODE_TUNNEL is not set
# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
@@ -308,6 +319,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
#
# Generic Driver Options
#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=y
@@ -352,10 +364,6 @@ CONFIG_MISC_DEVICES=y
# CONFIG_SCSI_NETLINK is not set
# CONFIG_ATA is not set
# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
# CONFIG_FUSION is not set
#
@@ -374,12 +382,36 @@ CONFIG_NETDEVICES=y
# CONFIG_MACVLAN is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_IP1000 is not set
# CONFIG_ARCNET is not set
-# CONFIG_NET_ETHERNET is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# 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 is not set
+# CONFIG_HP100 is not set
+CONFIG_IBM_NEW_EMAC=y
+CONFIG_IBM_NEW_EMAC_RXB=128
+CONFIG_IBM_NEW_EMAC_TXB=64
+CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
+CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
+CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
+# CONFIG_IBM_NEW_EMAC_DEBUG is not set
+CONFIG_IBM_NEW_EMAC_ZMII=y
+# 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_NET_PCI is not set
+# CONFIG_B44 is not set
CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
@@ -387,6 +419,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_SIS190 is not set
# CONFIG_SKGE is not set
# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
@@ -395,11 +428,14 @@ CONFIG_NETDEV_1000=y
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
# CONFIG_CHELSIO_T3 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_CORE is not set
+# CONFIG_TEHUTI is not set
# CONFIG_TR is not set
#
@@ -462,14 +498,11 @@ CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
-# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
# CONFIG_GEN_RTC is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
# CONFIG_TCG_TPM is not set
CONFIG_DEVPORT=y
@@ -483,6 +516,13 @@ CONFIG_DEVPORT=y
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
#
# Multifunction device drivers
@@ -499,16 +539,17 @@ CONFIG_DAB=y
#
# Graphics support
#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+# CONFIG_FB is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
-# CONFIG_VGASTATE is not set
-CONFIG_VIDEO_OUTPUT_CONTROL=m
-# CONFIG_FB is not set
-# CONFIG_FB_IBM_GXT4500 is not set
#
# Sound
@@ -535,19 +576,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_RTC_CLASS is not set
#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
# Userspace I/O
#
# CONFIG_UIO is not set
@@ -599,7 +627,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -618,10 +645,7 @@ CONFIG_CRAMFS=y
# CONFIG_QNX4FS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
+CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
@@ -647,15 +671,7 @@ CONFIG_SUNRPC=y
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
# CONFIG_NLS is not set
-
-#
-# Distributed Lock Manager
-#
# CONFIG_DLM is not set
# CONFIG_UCC_SLOW is not set
@@ -695,7 +711,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
@@ -708,6 +724,7 @@ CONFIG_SCHED_DEBUG=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_FAULT_INJECTION is not set
# CONFIG_DEBUG_STACKOVERFLOW is not set
@@ -727,6 +744,7 @@ CONFIG_PPC_EARLY_DEBUG=y
# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
# CONFIG_PPC_EARLY_DEBUG_BEAT is not set
CONFIG_PPC_EARLY_DEBUG_44x=y
+# CONFIG_PPC_EARLY_DEBUG_CPM is not set
CONFIG_PPC_EARLY_DEBUG_44x_PHYSLOW=0xef600300
CONFIG_PPC_EARLY_DEBUG_44x_PHYSHIGH=0x0
@@ -735,6 +753,7 @@ CONFIG_PPC_EARLY_DEBUG_44x_PHYSHIGH=0x0
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_CRYPTO=y
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_BLKCIPHER=y
@@ -754,6 +773,7 @@ CONFIG_CRYPTO_ECB=y
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_PCBC=y
# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_XTS is not set
# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_FCRYPT is not set
@@ -767,9 +787,12 @@ CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_ARC4 is not set
# CONFIG_CRYPTO_KHAZAD is not set
# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_SEED is not set
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_MICHAEL_MIC is not set
# CONFIG_CRYPTO_CRC32C is not set
# CONFIG_CRYPTO_CAMELLIA is not set
# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO_AUTHENC is not set
CONFIG_CRYPTO_HW=y
+# CONFIG_PPC_CLOCK is not set
diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig
index 8b47c846421c..dcd7c02727c2 100644
--- a/arch/powerpc/configs/cell_defconfig
+++ b/arch/powerpc/configs/cell_defconfig
@@ -68,6 +68,7 @@ CONFIG_SYSVIPC_SYSCTL=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=15
+CONFIG_CGROUPS=y
CONFIG_CPUSETS=y
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
diff --git a/arch/powerpc/configs/celleb_defconfig b/arch/powerpc/configs/celleb_defconfig
index b4ac498c3cce..2c5969801bd6 100644
--- a/arch/powerpc/configs/celleb_defconfig
+++ b/arch/powerpc/configs/celleb_defconfig
@@ -92,8 +92,9 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
@@ -1218,7 +1219,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/powerpc/configs/chrp32_defconfig b/arch/powerpc/configs/chrp32_defconfig
index c3977e334b3b..6f27e57331d5 100644
--- a/arch/powerpc/configs/chrp32_defconfig
+++ b/arch/powerpc/configs/chrp32_defconfig
@@ -92,8 +92,9 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
@@ -1373,7 +1374,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/powerpc/configs/ebony_defconfig b/arch/powerpc/configs/ebony_defconfig
index 3a50467b1f75..d3ef642811ef 100644
--- a/arch/powerpc/configs/ebony_defconfig
+++ b/arch/powerpc/configs/ebony_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.23-rc4
-# Thu Aug 30 16:34:11 2007
+# Linux kernel version: 2.6.23
+# Thu Oct 18 08:01:57 2007
#
# CONFIG_PPC64 is not set
@@ -21,8 +21,13 @@ CONFIG_PHYS_64BIT=y
# CONFIG_PPC_MM_SLICES is not set
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_PPC32=y
+CONFIG_WORD_SIZE=32
CONFIG_PPC_MERGE=y
CONFIG_MMU=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_IRQ_PER_CPU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
@@ -66,6 +71,8 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_FAIR_USER_SCHED=y
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_BLK_DEV_INITRD=y
@@ -86,12 +93,12 @@ CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
@@ -129,7 +136,9 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
# CONFIG_PQ2ADS is not set
+# CONFIG_BAMBOO is not set
CONFIG_EBONY=y
+# CONFIG_SEQUOIA is not set
CONFIG_440GP=y
# CONFIG_MPIC is not set
# CONFIG_MPIC_WEIRD is not set
@@ -148,6 +157,10 @@ CONFIG_440GP=y
# Kernel options
#
# CONFIG_HIGHMEM is not set
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
# CONFIG_HZ_300 is not set
@@ -169,6 +182,7 @@ CONFIG_FLATMEM_MANUAL=y
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_RESOURCES_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
@@ -193,10 +207,6 @@ CONFIG_PCI_SYSCALL=y
CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_DEBUG is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
@@ -211,7 +221,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
CONFIG_HIGHMEM_START=0xfe000000
CONFIG_LOWMEM_SIZE=0x30000000
CONFIG_KERNEL_START=0xc0000000
-CONFIG_TASK_SIZE=0x80000000
+CONFIG_TASK_SIZE=0xc0000000
CONFIG_CONSISTENT_START=0xff100000
CONFIG_CONSISTENT_SIZE=0x00200000
CONFIG_BOOT_LOAD=0x01000000
@@ -248,6 +258,7 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
# CONFIG_INET_XFRM_MODE_TUNNEL is not set
# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
@@ -305,6 +316,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
#
# Generic Driver Options
#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=y
@@ -331,6 +343,7 @@ CONFIG_MTD_BLOCK=y
# CONFIG_INFTL is not set
# CONFIG_RFD_FTL is not set
# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
#
# RAM/ROM/Flash chip drivers
@@ -363,6 +376,7 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
# CONFIG_MTD_PHYSMAP is not set
CONFIG_MTD_PHYSMAP_OF=y
+# CONFIG_MTD_INTEL_VR_NOR is not set
# CONFIG_MTD_PLATRAM is not set
#
@@ -422,10 +436,6 @@ CONFIG_MISC_DEVICES=y
# CONFIG_SCSI_NETLINK is not set
# CONFIG_ATA is not set
# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
# CONFIG_FUSION is not set
#
@@ -442,12 +452,36 @@ CONFIG_NETDEVICES=y
# CONFIG_MACVLAN is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_IP1000 is not set
# CONFIG_ARCNET is not set
-# CONFIG_NET_ETHERNET is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# 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 is not set
+# CONFIG_HP100 is not set
+CONFIG_IBM_NEW_EMAC=y
+CONFIG_IBM_NEW_EMAC_RXB=128
+CONFIG_IBM_NEW_EMAC_TXB=64
+CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
+CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
+CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
+# CONFIG_IBM_NEW_EMAC_DEBUG is not set
+CONFIG_IBM_NEW_EMAC_ZMII=y
+# 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_NET_PCI is not set
+# CONFIG_B44 is not set
CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
@@ -455,6 +489,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_SIS190 is not set
# CONFIG_SKGE is not set
# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
@@ -463,11 +498,14 @@ CONFIG_NETDEV_1000=y
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
# CONFIG_CHELSIO_T3 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_CORE is not set
+# CONFIG_TEHUTI is not set
# CONFIG_TR is not set
#
@@ -536,8 +574,6 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_GEN_RTC is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
# CONFIG_TCG_TPM is not set
CONFIG_DEVPORT=y
@@ -553,6 +589,12 @@ CONFIG_DEVPORT=y
# CONFIG_HWMON is not set
#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
# Multifunction device drivers
#
# CONFIG_MFD_SM501 is not set
@@ -567,16 +609,17 @@ CONFIG_DEVPORT=y
#
# Graphics support
#
+# CONFIG_AGP is not set
+# CONFIG_DRM 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
-# CONFIG_VGASTATE is not set
-# CONFIG_VIDEO_OUTPUT_CONTROL is not set
-# CONFIG_FB is not set
-# CONFIG_FB_IBM_GXT4500 is not set
#
# Sound
@@ -603,19 +646,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_RTC_CLASS is not set
#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
# Userspace I/O
#
# CONFIG_UIO is not set
@@ -667,7 +697,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -683,10 +712,12 @@ CONFIG_RAMFS=y
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
# CONFIG_JFFS2_SUMMARY is not set
# CONFIG_JFFS2_FS_XATTR is not set
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
CONFIG_CRAMFS=y
@@ -695,10 +726,7 @@ CONFIG_CRAMFS=y
# CONFIG_QNX4FS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
+CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
@@ -724,15 +752,7 @@ CONFIG_SUNRPC=y
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
# CONFIG_NLS is not set
-
-#
-# Distributed Lock Manager
-#
# CONFIG_DLM is not set
# CONFIG_UCC_SLOW is not set
@@ -773,7 +793,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
@@ -786,6 +806,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_FAULT_INJECTION is not set
# CONFIG_DEBUG_STACKOVERFLOW is not set
@@ -800,6 +821,7 @@ CONFIG_FORCED_INLINING=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_CRYPTO=y
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_BLKCIPHER=y
@@ -819,6 +841,7 @@ CONFIG_CRYPTO_ECB=y
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_PCBC=y
# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_XTS is not set
# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_FCRYPT is not set
@@ -832,9 +855,12 @@ CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_ARC4 is not set
# CONFIG_CRYPTO_KHAZAD is not set
# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_SEED is not set
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_MICHAEL_MIC is not set
# CONFIG_CRYPTO_CRC32C is not set
# CONFIG_CRYPTO_CAMELLIA is not set
# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO_AUTHENC is not set
# CONFIG_CRYPTO_HW is not set
+# CONFIG_PPC_CLOCK is not set
diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig
index a655d87b3f8b..0a6fa1fc9766 100644
--- a/arch/powerpc/configs/g5_defconfig
+++ b/arch/powerpc/configs/g5_defconfig
@@ -92,8 +92,9 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
@@ -1580,7 +1581,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/powerpc/configs/holly_defconfig b/arch/powerpc/configs/holly_defconfig
index 97d0202a9fe0..11009185d230 100644
--- a/arch/powerpc/configs/holly_defconfig
+++ b/arch/powerpc/configs/holly_defconfig
@@ -88,8 +88,9 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
@@ -909,7 +910,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHED_DEBUG is not set
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/powerpc/configs/iseries_defconfig b/arch/powerpc/configs/iseries_defconfig
index 3fe1929460e7..d78e3a6fc68c 100644
--- a/arch/powerpc/configs/iseries_defconfig
+++ b/arch/powerpc/configs/iseries_defconfig
@@ -93,8 +93,9 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
@@ -1056,7 +1057,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/powerpc/configs/kilauea_defconfig b/arch/powerpc/configs/kilauea_defconfig
index 31790d329269..fd1c530aa3ec 100644
--- a/arch/powerpc/configs/kilauea_defconfig
+++ b/arch/powerpc/configs/kilauea_defconfig
@@ -91,8 +91,9 @@ CONFIG_SIGNALFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
@@ -700,7 +701,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/powerpc/configs/linkstation_defconfig b/arch/powerpc/configs/linkstation_defconfig
index a4e3ee045a6a..401033aefd40 100644
--- a/arch/powerpc/configs/linkstation_defconfig
+++ b/arch/powerpc/configs/linkstation_defconfig
@@ -89,8 +89,9 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
@@ -1459,7 +1460,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/powerpc/configs/lite5200_defconfig b/arch/powerpc/configs/lite5200_defconfig
index d42e226d3a28..dd78ed955eb0 100644
--- a/arch/powerpc/configs/lite5200_defconfig
+++ b/arch/powerpc/configs/lite5200_defconfig
@@ -87,8 +87,9 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
@@ -816,7 +817,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/powerpc/configs/maple_defconfig b/arch/powerpc/configs/maple_defconfig
index 96b538bc676b..84b9ab4a5a92 100644
--- a/arch/powerpc/configs/maple_defconfig
+++ b/arch/powerpc/configs/maple_defconfig
@@ -90,8 +90,9 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
@@ -1095,8 +1096,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
-CONFIG_DEBUG_SLAB=y
-# CONFIG_DEBUG_SLAB_LEAK is not set
+# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/powerpc/configs/mpc7448_hpc2_defconfig b/arch/powerpc/configs/mpc7448_hpc2_defconfig
index 05814a3b0e33..87ae894551b7 100644
--- a/arch/powerpc/configs/mpc7448_hpc2_defconfig
+++ b/arch/powerpc/configs/mpc7448_hpc2_defconfig
@@ -87,8 +87,9 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
diff --git a/arch/powerpc/configs/mpc8272_ads_defconfig b/arch/powerpc/configs/mpc8272_ads_defconfig
index 6b7951ec941a..865a942ecc69 100644
--- a/arch/powerpc/configs/mpc8272_ads_defconfig
+++ b/arch/powerpc/configs/mpc8272_ads_defconfig
@@ -85,8 +85,9 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
@@ -867,7 +868,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/powerpc/configs/mpc8313_rdb_defconfig b/arch/powerpc/configs/mpc8313_rdb_defconfig
index f387dac69d09..259d40d1eb5a 100644
--- a/arch/powerpc/configs/mpc8313_rdb_defconfig
+++ b/arch/powerpc/configs/mpc8313_rdb_defconfig
@@ -87,8 +87,9 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
@@ -1272,7 +1273,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/powerpc/configs/mpc832x_mds_defconfig b/arch/powerpc/configs/mpc832x_mds_defconfig
index fc6695302cc8..dd68d1818d6b 100644
--- a/arch/powerpc/configs/mpc832x_mds_defconfig
+++ b/arch/powerpc/configs/mpc832x_mds_defconfig
@@ -87,8 +87,9 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
diff --git a/arch/powerpc/configs/mpc832x_rdb_defconfig b/arch/powerpc/configs/mpc832x_rdb_defconfig
index 6d1c3e842051..4f391028c79c 100644
--- a/arch/powerpc/configs/mpc832x_rdb_defconfig
+++ b/arch/powerpc/configs/mpc832x_rdb_defconfig
@@ -87,8 +87,9 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
diff --git a/arch/powerpc/configs/mpc834x_itx_defconfig b/arch/powerpc/configs/mpc834x_itx_defconfig
index ddafa6b9af05..eb28dd85cb2b 100644
--- a/arch/powerpc/configs/mpc834x_itx_defconfig
+++ b/arch/powerpc/configs/mpc834x_itx_defconfig
@@ -87,8 +87,9 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
diff --git a/arch/powerpc/configs/mpc834x_itxgp_defconfig b/arch/powerpc/configs/mpc834x_itxgp_defconfig
index 8241c6985861..22b95462c913 100644
--- a/arch/powerpc/configs/mpc834x_itxgp_defconfig
+++ b/arch/powerpc/configs/mpc834x_itxgp_defconfig
@@ -87,8 +87,9 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
diff --git a/arch/powerpc/configs/mpc834x_mds_defconfig b/arch/powerpc/configs/mpc834x_mds_defconfig
index 06233b1a9418..e59a88e95486 100644
--- a/arch/powerpc/configs/mpc834x_mds_defconfig
+++ b/arch/powerpc/configs/mpc834x_mds_defconfig
@@ -87,8 +87,9 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
diff --git a/arch/powerpc/configs/mpc836x_mds_defconfig b/arch/powerpc/configs/mpc836x_mds_defconfig
index 3045749d62fe..75657528518e 100644
--- a/arch/powerpc/configs/mpc836x_mds_defconfig
+++ b/arch/powerpc/configs/mpc836x_mds_defconfig
@@ -87,8 +87,9 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
diff --git a/arch/powerpc/configs/mpc8540_ads_defconfig b/arch/powerpc/configs/mpc8540_ads_defconfig
index b282c3521dd5..b953b2c51453 100644
--- a/arch/powerpc/configs/mpc8540_ads_defconfig
+++ b/arch/powerpc/configs/mpc8540_ads_defconfig
@@ -90,8 +90,9 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
@@ -704,7 +705,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/powerpc/configs/mpc8544_ds_defconfig b/arch/powerpc/configs/mpc8544_ds_defconfig
index 150221f6f723..9a3e08bcd188 100644
--- a/arch/powerpc/configs/mpc8544_ds_defconfig
+++ b/arch/powerpc/configs/mpc8544_ds_defconfig
@@ -93,8 +93,9 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
@@ -1427,7 +1428,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/powerpc/configs/mpc8560_ads_defconfig b/arch/powerpc/configs/mpc8560_ads_defconfig
index 3d68c65212cf..0211e6b68e1a 100644
--- a/arch/powerpc/configs/mpc8560_ads_defconfig
+++ b/arch/powerpc/configs/mpc8560_ads_defconfig
@@ -94,8 +94,9 @@ CONFIG_SIGNALFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
@@ -791,7 +792,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/powerpc/configs/mpc8568mds_defconfig b/arch/powerpc/configs/mpc8568mds_defconfig
index 0307fe7b0487..883d8af9debd 100644
--- a/arch/powerpc/configs/mpc8568mds_defconfig
+++ b/arch/powerpc/configs/mpc8568mds_defconfig
@@ -88,8 +88,9 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
@@ -949,7 +950,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/powerpc/configs/mpc8572_ds_defconfig b/arch/powerpc/configs/mpc8572_ds_defconfig
index 7f1a3e987138..4e85b2e88525 100644
--- a/arch/powerpc/configs/mpc8572_ds_defconfig
+++ b/arch/powerpc/configs/mpc8572_ds_defconfig
@@ -93,8 +93,9 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
@@ -1427,7 +1428,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/powerpc/configs/mpc85xx_cds_defconfig b/arch/powerpc/configs/mpc85xx_cds_defconfig
index e6850c619f88..a4f33d110542 100644
--- a/arch/powerpc/configs/mpc85xx_cds_defconfig
+++ b/arch/powerpc/configs/mpc85xx_cds_defconfig
@@ -90,8 +90,9 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
@@ -832,7 +833,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/powerpc/configs/mpc8610_hpcd_defconfig b/arch/powerpc/configs/mpc8610_hpcd_defconfig
index de19b781937f..0483211f52be 100644
--- a/arch/powerpc/configs/mpc8610_hpcd_defconfig
+++ b/arch/powerpc/configs/mpc8610_hpcd_defconfig
@@ -88,8 +88,9 @@ CONFIG_SIGNALFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
@@ -993,7 +994,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/powerpc/configs/mpc8641_hpcn_defconfig b/arch/powerpc/configs/mpc8641_hpcn_defconfig
index b2f389dcaded..ed214fcd8abe 100644
--- a/arch/powerpc/configs/mpc8641_hpcn_defconfig
+++ b/arch/powerpc/configs/mpc8641_hpcn_defconfig
@@ -94,8 +94,9 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
@@ -1432,7 +1433,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/powerpc/configs/mpc866_ads_defconfig b/arch/powerpc/configs/mpc866_ads_defconfig
index 143a0cd83327..070b0a5b9c0d 100644
--- a/arch/powerpc/configs/mpc866_ads_defconfig
+++ b/arch/powerpc/configs/mpc866_ads_defconfig
@@ -83,8 +83,9 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
# CONFIG_VM_EVENT_COUNTERS is not set
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
diff --git a/arch/powerpc/configs/pasemi_defconfig b/arch/powerpc/configs/pasemi_defconfig
index 295207030c60..78c968aade4e 100644
--- a/arch/powerpc/configs/pasemi_defconfig
+++ b/arch/powerpc/configs/pasemi_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.23-rc4
-# Thu Aug 30 16:40:47 2007
+# Linux kernel version: 2.6.24-rc2
+# Tue Nov 6 23:23:50 2007
#
CONFIG_PPC64=y
@@ -10,6 +10,7 @@ CONFIG_PPC64=y
#
CONFIG_POWER4_ONLY=y
CONFIG_POWER4=y
+# CONFIG_TUNE_CELL is not set
CONFIG_PPC_FPU=y
CONFIG_ALTIVEC=y
CONFIG_PPC_STD_MMU=y
@@ -18,8 +19,13 @@ CONFIG_PPC_MM_SLICES=y
CONFIG_SMP=y
CONFIG_NR_CPUS=2
CONFIG_64BIT=y
+CONFIG_WORD_SIZE=64
CONFIG_PPC_MERGE=y
CONFIG_MMU=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_IRQ_PER_CPU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
@@ -65,7 +71,10 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=17
-# CONFIG_CPUSETS is not set
+# CONFIG_CGROUPS is not set
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_FAIR_USER_SCHED=y
+# CONFIG_FAIR_CGROUP_SCHED is not set
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_BLK_DEV_INITRD=y
@@ -86,12 +95,12 @@ CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
@@ -106,14 +115,15 @@ CONFIG_STOP_MACHINE=y
CONFIG_BLOCK=y
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
+CONFIG_BLOCK_COMPAT=y
#
# IO Schedulers
#
CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_AS=y
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_DEADLINE is not set
# CONFIG_DEFAULT_CFQ is not set
@@ -124,7 +134,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# Platform support
#
CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_EMBEDDED6xx is not set
# CONFIG_PPC_82xx is not set
# CONFIG_PPC_83xx is not set
# CONFIG_PPC_86xx is not set
@@ -140,6 +149,7 @@ CONFIG_PPC_PASEMI=y
# PA Semi PWRficient options
#
CONFIG_PPC_PASEMI_IOMMU=y
+# CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE is not set
CONFIG_PPC_PASEMI_MDIO=y
CONFIG_ELECTRA_IDE=y
# CONFIG_PPC_CELLEB is not set
@@ -155,29 +165,52 @@ CONFIG_MPIC=y
# CONFIG_U3_DART is not set
# CONFIG_PPC_RTAS is not set
# CONFIG_MMIO_NVRAM is not set
+CONFIG_MPIC_BROKEN_REGREAD=y
# CONFIG_PPC_MPC106 is not set
# CONFIG_PPC_970_NAP is not set
# CONFIG_PPC_INDIRECT_IO is not set
# CONFIG_GENERIC_IOMAP is not set
-# CONFIG_CPU_FREQ is not set
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+
+#
+# CPU Frequency drivers
+#
+CONFIG_PPC_PASEMI_CPUFREQ=y
# CONFIG_CPM2 is not set
# CONFIG_FSL_ULI1575 is not set
#
# Kernel options
#
-CONFIG_HZ_100=y
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_100 is not set
# CONFIG_HZ_250 is not set
# CONFIG_HZ_300 is not set
-# CONFIG_HZ_1000 is not set
-CONFIG_HZ=100
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
-CONFIG_PREEMPT_BKL=y
+# CONFIG_PREEMPT_BKL is not set
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
-CONFIG_FORCE_MAX_ZONEORDER=13
+CONFIG_FORCE_MAX_ZONEORDER=9
CONFIG_IOMMU_VMERGE=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
# CONFIG_KEXEC is not set
@@ -195,12 +228,13 @@ CONFIG_FLATMEM_MANUAL=y
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_RESOURCES_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
-# CONFIG_PPC_HAS_HASH_64K is not set
-# CONFIG_PPC_64K_PAGES is not set
+CONFIG_PPC_HAS_HASH_64K=y
+CONFIG_PPC_64K_PAGES=y
# CONFIG_SCHED_SMT is not set
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -221,11 +255,8 @@ 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
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
CONFIG_PCCARD=y
CONFIG_PCMCIA_DEBUG=y
CONFIG_PCMCIA=y
@@ -239,6 +270,7 @@ CONFIG_CARDBUS=y
# CONFIG_YENTA is not set
# CONFIG_PD6729 is not set
# CONFIG_I82092 is not set
+# CONFIG_ELECTRA_CF is not set
# CONFIG_HOTPLUG_PCI is not set
CONFIG_KERNEL_START=0xc000000000000000
@@ -254,7 +286,7 @@ CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
-# CONFIG_XFRM_USER is not set
+CONFIG_XFRM_USER=y
# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_XFRM_MIGRATE is not set
CONFIG_NET_KEY=y
@@ -280,6 +312,7 @@ CONFIG_INET_TUNNEL=y
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_LRO=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
@@ -305,10 +338,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
# CONFIG_NET_SCHED is not set
#
@@ -337,6 +366,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
#
# Generic Driver Options
#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=y
@@ -360,6 +390,7 @@ CONFIG_MTD_BLOCK=y
# CONFIG_INFTL is not set
# CONFIG_RFD_FTL is not set
# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
#
# RAM/ROM/Flash chip drivers
@@ -384,6 +415,7 @@ CONFIG_MTD_CFI_I2=y
# Mapping drivers for chip access
#
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_INTEL_VR_NOR is not set
# CONFIG_MTD_PLATRAM is not set
#
@@ -401,7 +433,15 @@ CONFIG_MTD_PHRAM=y
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
# CONFIG_MTD_DOC2001PLUS is not set
-# CONFIG_MTD_NAND is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_CAFE is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
# CONFIG_MTD_ONENAND is not set
#
@@ -454,10 +494,42 @@ CONFIG_IDE_PROC_FS=y
# IDE chipset support/bugfixes
#
# CONFIG_IDE_GENERIC is not set
-# CONFIG_BLK_DEV_IDEPCI is not set
+# CONFIG_BLK_DEV_PLATFORM is not set
+
+#
+# PCI IDE chipsets support
+#
# CONFIG_IDEPCI_PCIBUS_ORDER is not set
+# CONFIG_BLK_DEV_GENERIC is not set
+# CONFIG_BLK_DEV_OPTI621 is not set
+# 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 is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X 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 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_SL82C105 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_IDE_ARM is not set
# CONFIG_BLK_DEV_IDEDMA is not set
+CONFIG_IDE_ARCH_OBSOLETE_INIT=y
# CONFIG_BLK_DEV_HD is not set
#
@@ -497,10 +569,11 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_FC_ATTRS is not set
# 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_BLK_DEV_3W_XXXX_RAID=y
-CONFIG_SCSI_3W_9XXX=y
+# 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
@@ -573,9 +646,10 @@ CONFIG_ATA_GENERIC=y
# CONFIG_PATA_OLDPIIX is not set
# CONFIG_PATA_NETCELL is not set
# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_NS87415 is not set
# CONFIG_PATA_OPTI is not set
# CONFIG_PATA_OPTIDMA is not set
-# CONFIG_PATA_PCMCIA is not set
+CONFIG_PATA_PCMCIA=y
# CONFIG_PATA_PDC_OLD is not set
# CONFIG_PATA_RADISYS is not set
# CONFIG_PATA_RZ1000 is not set
@@ -588,41 +662,13 @@ CONFIG_ATA_GENERIC=y
# CONFIG_PATA_WINBOND is not set
CONFIG_PATA_PLATFORM=y
# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
# CONFIG_FUSION is not set
-# CONFIG_FUSION_SPI is not set
-# CONFIG_FUSION_FC is not set
-# CONFIG_FUSION_SAS is not set
#
# IEEE 1394 (FireWire) support
#
# CONFIG_FIREWIRE is not set
-CONFIG_IEEE1394=y
-
-#
-# Subsystem Options
-#
-# CONFIG_IEEE1394_VERBOSEDEBUG is not set
-
-#
-# Controllers
-#
-CONFIG_IEEE1394_PCILYNX=y
-CONFIG_IEEE1394_OHCI1394=y
-
-#
-# Protocols
-#
-# CONFIG_IEEE1394_VIDEO1394 is not set
-CONFIG_IEEE1394_SBP2=y
-# CONFIG_IEEE1394_ETH1394_ROM_ENTRY is not set
-# CONFIG_IEEE1394_ETH1394 is not set
-# CONFIG_IEEE1394_DV1394 is not set
-CONFIG_IEEE1394_RAWIO=y
+# CONFIG_IEEE1394 is not set
# CONFIG_I2O is not set
# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_NETDEVICES=y
@@ -632,6 +678,8 @@ CONFIG_DUMMY=y
# CONFIG_MACVLAN is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_IP1000 is not set
# CONFIG_ARCNET is not set
CONFIG_PHYLIB=y
@@ -648,6 +696,7 @@ CONFIG_MARVELL_PHY=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
# CONFIG_HAPPYMEAL is not set
@@ -656,13 +705,16 @@ CONFIG_MII=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_NET_TULIP 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_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_DGRS is not set
# CONFIG_EEPRO100 is not set
# CONFIG_E100 is not set
# CONFIG_FEALNX is not set
@@ -681,6 +733,7 @@ CONFIG_NETDEV_1000=y
CONFIG_E1000=y
CONFIG_E1000_NAPI=y
# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+# CONFIG_E1000E is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
@@ -688,6 +741,7 @@ CONFIG_E1000_NAPI=y
# CONFIG_SIS190 is not set
# CONFIG_SKGE is not set
# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
CONFIG_TIGON3=y
# CONFIG_BNX2 is not set
@@ -696,12 +750,15 @@ CONFIG_TIGON3=y
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
# CONFIG_CHELSIO_T3 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_PASEMI_MAC=y
# CONFIG_MLX4_CORE is not set
+# CONFIG_TEHUTI is not set
# CONFIG_TR is not set
#
@@ -748,7 +805,6 @@ CONFIG_INPUT_MOUSEDEV_PSAUX=y
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
CONFIG_INPUT_JOYDEV=y
-# CONFIG_INPUT_TSDEV is not set
CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_EVBUG is not set
@@ -809,15 +865,12 @@ CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=4
# CONFIG_IPMI_HANDLER is not set
-# CONFIG_WATCHDOG is not set
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_PASEMI=y
CONFIG_GEN_RTC=y
CONFIG_GEN_RTC_X=y
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
#
# PCMCIA character devices
@@ -895,8 +948,6 @@ CONFIG_SENSORS_EEPROM=y
# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
CONFIG_HWMON_VID=y
-# CONFIG_SENSORS_ABITUGURU is not set
-# CONFIG_SENSORS_ABITUGURU3 is not set
# CONFIG_SENSORS_AD7418 is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
@@ -904,12 +955,12 @@ CONFIG_HWMON_VID=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
-# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_FSCPOS 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
@@ -945,6 +996,13 @@ CONFIG_SENSORS_LM90=y
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
#
# Multifunction device drivers
@@ -962,14 +1020,14 @@ CONFIG_DAB=y
#
# Graphics support
#
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_LCD_CLASS_DEVICE=m
-CONFIG_BACKLIGHT_CLASS_DEVICE=y
-
-#
-# Display device support
-#
-# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_AGP is not set
+CONFIG_DRM=y
+# CONFIG_DRM_TDFX is not set
+# CONFIG_DRM_R128 is not set
+CONFIG_DRM_RADEON=y
+# CONFIG_DRM_MGA is not set
+# CONFIG_DRM_VIA is not set
+# CONFIG_DRM_SAVAGE is not set
CONFIG_VGASTATE=y
# CONFIG_VIDEO_OUTPUT_CONTROL is not set
CONFIG_FB=y
@@ -978,6 +1036,7 @@ CONFIG_FB_DDC=y
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
# CONFIG_FB_SYS_FILLRECT is not set
# CONFIG_FB_SYS_COPYAREA is not set
# CONFIG_FB_SYS_IMAGEBLIT is not set
@@ -1025,6 +1084,15 @@ CONFIG_FB_RADEON_BACKLIGHT=y
# CONFIG_FB_PM3 is not set
# CONFIG_FB_IBM_GXT4500 is not set
# CONFIG_FB_VIRTUAL is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_CORGI is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
#
# Console display driver support
@@ -1177,6 +1245,7 @@ CONFIG_SND_USB_USX2Y=y
CONFIG_HID_SUPPORT=y
CONFIG_HID=y
# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
#
# USB Input Devices
@@ -1327,6 +1396,7 @@ CONFIG_RTC_INTF_DEV=y
# I2C RTC drivers
#
CONFIG_RTC_DRV_DS1307=y
+# CONFIG_RTC_DRV_DS1374 is not set
# CONFIG_RTC_DRV_DS1672 is not set
# CONFIG_RTC_DRV_MAX6900 is not set
# CONFIG_RTC_DRV_RS5C372 is not set
@@ -1356,19 +1426,6 @@ CONFIG_RTC_DRV_DS1307=y
#
#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
# Userspace I/O
#
# CONFIG_UIO is not set
@@ -1387,7 +1444,6 @@ CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_SECURITY is not set
# CONFIG_EXT4DEV_FS is not set
CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
@@ -1435,7 +1491,6 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
-CONFIG_RAMFS=y
CONFIG_CONFIGFS_FS=y
#
@@ -1448,30 +1503,43 @@ CONFIG_CONFIGFS_FS=y
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
-# CONFIG_JFFS2_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
+CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFS_V4 is not set
# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
# CONFIG_SUNRPC_BIND34 is not set
-# CONFIG_RPCSEC_GSS_KRB5 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
@@ -1500,10 +1568,6 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
# CONFIG_SYSV68_PARTITION is not set
-
-#
-# Native Language Support
-#
CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
CONFIG_NLS_CODEPAGE_437=y
@@ -1544,10 +1608,6 @@ CONFIG_NLS_ISO8859_1=y
# CONFIG_NLS_KOI8_R is not set
# CONFIG_NLS_KOI8_U is not set
# CONFIG_NLS_UTF8 is not set
-
-#
-# Distributed Lock Manager
-#
# CONFIG_DLM is not set
# CONFIG_UCC_SLOW is not set
@@ -1560,23 +1620,24 @@ CONFIG_CRC_CCITT=y
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_CRC7 is not set
-# CONFIG_LIBCRC32C is not set
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAS_DMA=y
-
-#
-# Instrumentation Support
-#
+CONFIG_INSTRUMENTATION=y
CONFIG_PROFILING=y
CONFIG_OPROFILE=y
# CONFIG_KPROBES is not set
+# CONFIG_MARKERS is not set
#
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
@@ -1585,10 +1646,10 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
-CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHED_DEBUG is not set
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
@@ -1600,9 +1661,12 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
# CONFIG_FORCED_INLINING is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_FAULT_INJECTION is not set
+# CONFIG_SAMPLES is not set
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -1619,6 +1683,7 @@ CONFIG_XMON_DISASSEMBLY=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_CRYPTO=y
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_BLKCIPHER=y
@@ -1627,34 +1692,38 @@ CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_HMAC=y
# CONFIG_CRYPTO_XCBC is not set
# CONFIG_CRYPTO_NULL is not set
-# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_SHA1=y
-# CONFIG_CRYPTO_SHA256 is not set
-# CONFIG_CRYPTO_SHA512 is not set
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
# CONFIG_CRYPTO_WP512 is not set
# CONFIG_CRYPTO_TGR192 is not set
# CONFIG_CRYPTO_GF128MUL is not set
-CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_ECB is not set
CONFIG_CRYPTO_CBC=y
-CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_PCBC is not set
# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_XTS is not set
# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_FCRYPT is not set
-# CONFIG_CRYPTO_BLOWFISH is not set
+CONFIG_CRYPTO_BLOWFISH=y
# CONFIG_CRYPTO_TWOFISH is not set
# CONFIG_CRYPTO_SERPENT is not set
-# CONFIG_CRYPTO_AES is not set
+CONFIG_CRYPTO_AES=y
# CONFIG_CRYPTO_CAST5 is not set
# CONFIG_CRYPTO_CAST6 is not set
# CONFIG_CRYPTO_TEA is not set
# CONFIG_CRYPTO_ARC4 is not set
# CONFIG_CRYPTO_KHAZAD is not set
# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_SEED is not set
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_MICHAEL_MIC is not set
# CONFIG_CRYPTO_CRC32C is not set
# CONFIG_CRYPTO_CAMELLIA is not set
# CONFIG_CRYPTO_TEST is not set
-# CONFIG_CRYPTO_HW is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_PPC_CLOCK is not set
diff --git a/arch/powerpc/configs/pmac32_defconfig b/arch/powerpc/configs/pmac32_defconfig
index cfc9c6573a3c..8e5988c4a164 100644
--- a/arch/powerpc/configs/pmac32_defconfig
+++ b/arch/powerpc/configs/pmac32_defconfig
@@ -91,8 +91,9 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
@@ -208,7 +209,6 @@ CONFIG_PM=y
# CONFIG_PM_LEGACY is not set
CONFIG_PM_DEBUG=y
# CONFIG_PM_VERBOSE is not set
-# CONFIG_DISABLE_CONSOLE_SUSPEND is not set
CONFIG_PM_SLEEP=y
CONFIG_SUSPEND=y
CONFIG_HIBERNATION=y
@@ -1829,7 +1829,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig
index 5f6224a1feb8..3e90c835fe12 100644
--- a/arch/powerpc/configs/ppc64_defconfig
+++ b/arch/powerpc/configs/ppc64_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.23-rc4
-# Thu Aug 30 16:47:09 2007
+# Linux kernel version: 2.6.24-rc2
+# Tue Nov 6 23:43:56 2007
#
CONFIG_PPC64=y
@@ -11,6 +11,7 @@ CONFIG_PPC64=y
# CONFIG_POWER4_ONLY is not set
CONFIG_POWER3=y
CONFIG_POWER4=y
+# CONFIG_TUNE_CELL is not set
CONFIG_PPC_FPU=y
CONFIG_ALTIVEC=y
CONFIG_PPC_STD_MMU=y
@@ -19,8 +20,13 @@ CONFIG_VIRT_CPU_ACCOUNTING=y
CONFIG_SMP=y
CONFIG_NR_CPUS=32
CONFIG_64BIT=y
+CONFIG_WORD_SIZE=64
CONFIG_PPC_MERGE=y
CONFIG_MMU=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_IRQ_PER_CPU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
@@ -71,8 +77,16 @@ CONFIG_TASK_DELAY_ACCT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=17
+CONFIG_CGROUPS=y
+# CONFIG_CGROUP_DEBUG is not set
+# CONFIG_CGROUP_NS is not set
+# CONFIG_CGROUP_CPUACCT is not set
CONFIG_CPUSETS=y
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_FAIR_USER_SCHED=y
+# CONFIG_FAIR_CGROUP_SCHED is not set
CONFIG_SYSFS_DEPRECATED=y
+CONFIG_PROC_PID_CPUSET=y
CONFIG_RELAY=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
@@ -92,12 +106,12 @@ CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
@@ -112,6 +126,7 @@ CONFIG_STOP_MACHINE=y
CONFIG_BLOCK=y
CONFIG_BLK_DEV_IO_TRACE=y
CONFIG_BLK_DEV_BSG=y
+CONFIG_BLOCK_COMPAT=y
#
# IO Schedulers
@@ -130,7 +145,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# Platform support
#
CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_EMBEDDED6xx is not set
# CONFIG_PPC_82xx is not set
# CONFIG_PPC_83xx is not set
# CONFIG_PPC_86xx is not set
@@ -153,7 +167,15 @@ CONFIG_VIOPATH=y
CONFIG_PPC_PMAC=y
CONFIG_PPC_PMAC64=y
CONFIG_PPC_MAPLE=y
-# CONFIG_PPC_PASEMI is not set
+CONFIG_PPC_PASEMI=y
+
+#
+# PA Semi PWRficient options
+#
+CONFIG_PPC_PASEMI_IOMMU=y
+# CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE is not set
+CONFIG_PPC_PASEMI_MDIO=y
+CONFIG_ELECTRA_IDE=y
CONFIG_PPC_CELLEB=y
# CONFIG_PPC_PS3 is not set
CONFIG_PPC_CELL=y
@@ -186,6 +208,7 @@ CONFIG_RTAS_FLASH=m
CONFIG_PPC_PMI=m
CONFIG_MMIO_NVRAM=y
CONFIG_MPIC_U3_HT_IRQS=y
+CONFIG_MPIC_BROKEN_REGREAD=y
CONFIG_IBMVIO=y
# CONFIG_IBMEBUS is not set
# CONFIG_PPC_MPC106 is not set
@@ -199,6 +222,8 @@ CONFIG_CPU_FREQ_STAT=y
# CONFIG_CPU_FREQ_STAT_DETAILS is not set
CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
@@ -209,6 +234,7 @@ CONFIG_CPU_FREQ_GOV_USERSPACE=y
# CPU Frequency drivers
#
CONFIG_CPU_FREQ_PMAC64=y
+CONFIG_PPC_PASEMI_CPUFREQ=y
# CONFIG_CPM2 is not set
CONFIG_AXON_RAM=m
# CONFIG_FSL_ULI1575 is not set
@@ -216,6 +242,10 @@ CONFIG_AXON_RAM=m
#
# Kernel options
#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
# CONFIG_HZ_300 is not set
@@ -248,6 +278,8 @@ CONFIG_SPARSEMEM=y
CONFIG_HAVE_MEMORY_PRESENT=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPARSEMEM_EXTREME=y
+CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
+CONFIG_SPARSEMEM_VMEMMAP=y
CONFIG_MEMORY_HOTPLUG=y
CONFIG_MEMORY_HOTPLUG_SPARSE=y
CONFIG_SPLIT_PTLOCK_CPUS=4
@@ -262,6 +294,7 @@ CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
# CONFIG_PM is not set
CONFIG_SUSPEND_SMP_POSSIBLE=y
+CONFIG_HIBERNATION_SMP_POSSIBLE=y
CONFIG_SECCOMP=y
# CONFIG_WANT_DEVICE_TREE is not set
CONFIG_ISA_DMA_API=y
@@ -278,12 +311,22 @@ CONFIG_PCI_SYSCALL=y
# CONFIG_PCIEPORTBUS is not set
CONFIG_ARCH_SUPPORTS_MSI=y
CONFIG_PCI_MSI=y
+CONFIG_PCI_LEGACY=y
# CONFIG_PCI_DEBUG is not set
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_CARDBUS=y
#
-# PCCARD (PCMCIA/CardBus) support
+# PC-card bridges
#
-# CONFIG_PCCARD is not set
+# CONFIG_YENTA is not set
+# CONFIG_PD6729 is not set
+# CONFIG_I82092 is not set
+CONFIG_ELECTRA_CF=y
CONFIG_HOTPLUG_PCI=m
# CONFIG_HOTPLUG_PCI_FAKE is not set
# CONFIG_HOTPLUG_PCI_CPCI is not set
@@ -313,7 +356,10 @@ 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_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
CONFIG_NET_IPIP=y
# CONFIG_NET_IPGRE is not set
# CONFIG_IP_MROUTE is not set
@@ -327,6 +373,7 @@ CONFIG_INET_TUNNEL=y
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
@@ -398,6 +445,7 @@ CONFIG_NETFILTER_XT_MATCH_STATE=m
CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
CONFIG_NETFILTER_XT_MATCH_STRING=m
CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+# CONFIG_NETFILTER_XT_MATCH_TIME is not set
CONFIG_NETFILTER_XT_MATCH_U32=m
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
@@ -459,10 +507,6 @@ CONFIG_LLC=y
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
# CONFIG_NET_SCHED is not set
CONFIG_NET_CLS_ROUTE=y
@@ -492,6 +536,7 @@ CONFIG_NET_CLS_ROUTE=y
#
# Generic Driver Options
#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=y
@@ -533,6 +578,8 @@ CONFIG_BLK_DEV_IDE=y
# CONFIG_BLK_DEV_IDE_SATA is not set
CONFIG_BLK_DEV_IDEDISK=y
# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECS is not set
+# CONFIG_BLK_DEV_DELKIN is not set
CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
@@ -544,6 +591,11 @@ CONFIG_IDE_PROC_FS=y
# IDE chipset support/bugfixes
#
CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_PLATFORM is not set
+
+#
+# PCI IDE chipsets support
+#
CONFIG_BLK_DEV_IDEPCI=y
CONFIG_IDEPCI_SHARE_IRQ=y
CONFIG_IDEPCI_PCIBUS_ORDER=y
@@ -551,8 +603,6 @@ CONFIG_IDEPCI_PCIBUS_ORDER=y
CONFIG_BLK_DEV_GENERIC=y
# CONFIG_BLK_DEV_OPTI621 is not set
CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-# CONFIG_IDEDMA_ONLYDISK is not set
# CONFIG_BLK_DEV_AEC62XX is not set
# CONFIG_BLK_DEV_ALI15X3 is not set
CONFIG_BLK_DEV_AMD74XX=y
@@ -584,7 +634,7 @@ CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
CONFIG_BLK_DEV_IDEDMA_PMAC=y
# CONFIG_IDE_ARM is not set
CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDE_ARCH_OBSOLETE_INIT=y
# CONFIG_BLK_DEV_HD is not set
#
@@ -625,6 +675,7 @@ CONFIG_SCSI_FC_ATTRS=y
CONFIG_SCSI_ISCSI_ATTRS=m
# CONFIG_SCSI_SAS_ATTRS is not set
# CONFIG_SCSI_SAS_LIBSAS is not set
+CONFIG_SCSI_SRP_ATTRS=y
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
@@ -665,19 +716,20 @@ CONFIG_SCSI_LPFC=m
# CONFIG_SCSI_DC390T is not set
CONFIG_SCSI_DEBUG=m
# CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set
CONFIG_ATA=y
CONFIG_ATA_NONSTANDARD=y
# CONFIG_SATA_AHCI is not set
CONFIG_SATA_SVW=y
# CONFIG_ATA_PIIX is not set
-# CONFIG_SATA_MV is not set
+CONFIG_SATA_MV=y
# CONFIG_SATA_NV is not set
# CONFIG_PDC_ADMA is not set
# CONFIG_SATA_QSTOR is not set
# CONFIG_SATA_PROMISE is not set
# CONFIG_SATA_SX4 is not set
# CONFIG_SATA_SIL is not set
-# CONFIG_SATA_SIL24 is not set
+CONFIG_SATA_SIL24=y
# CONFIG_SATA_SIS is not set
# CONFIG_SATA_ULI is not set
# CONFIG_SATA_VIA is not set
@@ -707,8 +759,10 @@ CONFIG_SATA_SVW=y
# CONFIG_PATA_OLDPIIX is not set
# CONFIG_PATA_NETCELL is not set
# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_NS87415 is not set
# CONFIG_PATA_OPTI is not set
# CONFIG_PATA_OPTIDMA is not set
+CONFIG_PATA_PCMCIA=y
# CONFIG_PATA_PDC_OLD is not set
# CONFIG_PATA_RADISYS is not set
# CONFIG_PATA_RZ1000 is not set
@@ -719,6 +773,7 @@ CONFIG_SATA_SVW=y
# CONFIG_PATA_SIS is not set
# CONFIG_PATA_VIA is not set
CONFIG_PATA_WINBOND=y
+CONFIG_PATA_PLATFORM=y
CONFIG_PATA_SCC=y
CONFIG_MD=y
CONFIG_BLK_DEV_MD=y
@@ -739,15 +794,10 @@ CONFIG_DM_ZERO=m
CONFIG_DM_MULTIPATH=m
CONFIG_DM_MULTIPATH_EMC=m
# CONFIG_DM_MULTIPATH_RDAC is not set
+# CONFIG_DM_MULTIPATH_HP is not set
# CONFIG_DM_DELAY is not set
-
-#
-# Fusion MPT device support
-#
+# CONFIG_DM_UEVENT is not set
# CONFIG_FUSION is not set
-# CONFIG_FUSION_SPI is not set
-# CONFIG_FUSION_FC is not set
-# CONFIG_FUSION_SAS is not set
#
# IEEE 1394 (FireWire) support
@@ -794,13 +844,15 @@ CONFIG_BONDING=m
# CONFIG_MACVLAN is not set
# CONFIG_EQUALIZER is not set
CONFIG_TUN=m
+# CONFIG_VETH is not set
+# CONFIG_IP1000 is not set
# CONFIG_ARCNET is not set
-CONFIG_PHYLIB=m
+CONFIG_PHYLIB=y
#
# MII PHY device drivers
#
-CONFIG_MARVELL_PHY=m
+CONFIG_MARVELL_PHY=y
# CONFIG_DAVICOM_PHY is not set
# CONFIG_QSEMI_PHY is not set
# CONFIG_LXT_PHY is not set
@@ -812,6 +864,9 @@ CONFIG_BROADCOM_PHY=m
CONFIG_FIXED_PHY=m
CONFIG_FIXED_MII_10_FDX=y
CONFIG_FIXED_MII_100_FDX=y
+# CONFIG_FIXED_MII_1000_FDX is not set
+CONFIG_FIXED_MII_AMNT=1
+# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
# CONFIG_HAPPYMEAL is not set
@@ -823,6 +878,11 @@ CONFIG_VORTEX=y
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
CONFIG_IBMVETH=m
+# CONFIG_IBM_NEW_EMAC is not set
+CONFIG_IBM_NEW_EMAC_ZMII=y
+CONFIG_IBM_NEW_EMAC_RGMII=y
+CONFIG_IBM_NEW_EMAC_TAH=y
+CONFIG_IBM_NEW_EMAC_EMAC4=y
CONFIG_NET_PCI=y
CONFIG_PCNET32=y
# CONFIG_PCNET32_NAPI is not set
@@ -830,7 +890,6 @@ CONFIG_PCNET32=y
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
-# CONFIG_DGRS is not set
# CONFIG_EEPRO100 is not set
CONFIG_E100=y
# CONFIG_FEALNX is not set
@@ -850,6 +909,7 @@ CONFIG_ACENIC_OMIT_TIGON_I=y
CONFIG_E1000=y
# CONFIG_E1000_NAPI is not set
# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+# CONFIG_E1000E is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
@@ -857,6 +917,7 @@ CONFIG_E1000=y
# CONFIG_SIS190 is not set
# CONFIG_SKGE is not set
# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
CONFIG_TIGON3=y
# CONFIG_BNX2 is not set
@@ -866,13 +927,16 @@ CONFIG_SPIDER_NET=m
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
# CONFIG_CHELSIO_T3 is not set
+# CONFIG_IXGBE is not set
CONFIG_IXGB=m
# CONFIG_IXGB_NAPI is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
-CONFIG_PASEMI_MAC=m
+# CONFIG_NIU is not set
+CONFIG_PASEMI_MAC=y
# CONFIG_MLX4_CORE is not set
+# CONFIG_TEHUTI is not set
CONFIG_TR=y
CONFIG_IBMOL=y
# CONFIG_3C359 is not set
@@ -893,6 +957,7 @@ CONFIG_IBMOL=y
# CONFIG_USB_RTL8150 is not set
# CONFIG_USB_USBNET_MII is not set
# CONFIG_USB_USBNET is not set
+# CONFIG_NET_PCMCIA is not set
# CONFIG_WAN is not set
CONFIG_ISERIES_VETH=m
# CONFIG_FDDI is not set
@@ -912,6 +977,7 @@ CONFIG_SLHC=m
# CONFIG_NET_FC is not set
# CONFIG_SHAPER is not set
CONFIG_NETCONSOLE=y
+# CONFIG_NETCONSOLE_DYNAMIC is not set
CONFIG_NETPOLL=y
CONFIG_NETPOLL_TRAP=y
CONFIG_NET_POLL_CONTROLLER=y
@@ -933,7 +999,6 @@ CONFIG_INPUT_MOUSEDEV=y
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
CONFIG_INPUT_EVDEV=m
# CONFIG_INPUT_EVBUG is not set
@@ -996,6 +1061,7 @@ CONFIG_HW_CONSOLE=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_PCI=y
+# CONFIG_SERIAL_8250_CS is not set
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
@@ -1023,14 +1089,18 @@ CONFIG_HVC_RTAS=y
CONFIG_HVC_BEAT=y
CONFIG_HVCS=m
# CONFIG_IPMI_HANDLER is not set
-# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
CONFIG_RAW_DRIVER=y
CONFIG_MAX_RAW_DEVS=256
# CONFIG_HANGCHECK_TIMER is not set
@@ -1062,6 +1132,7 @@ CONFIG_I2C_POWERMAC=y
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_OCORES is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
+CONFIG_I2C_PASEMI=y
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
# CONFIG_I2C_SIMTEC is not set
@@ -1100,6 +1171,13 @@ CONFIG_I2C_POWERMAC=y
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
#
# Multifunction device drivers
@@ -1116,18 +1194,8 @@ CONFIG_I2C_POWERMAC=y
#
# Graphics support
#
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_LCD_CLASS_DEVICE=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=y
-
-#
-# Display device support
-#
-CONFIG_DISPLAY_SUPPORT=y
-
-#
-# Display hardware drivers
-#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
# CONFIG_VGASTATE is not set
CONFIG_VIDEO_OUTPUT_CONTROL=m
CONFIG_FB=y
@@ -1136,6 +1204,7 @@ CONFIG_FB_DDC=y
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
# CONFIG_FB_SYS_FILLRECT is not set
# CONFIG_FB_SYS_COPYAREA is not set
# CONFIG_FB_SYS_IMAGEBLIT is not set
@@ -1186,6 +1255,19 @@ CONFIG_FB_RADEON_BACKLIGHT=y
# CONFIG_FB_PM3 is not set
CONFIG_FB_IBM_GXT4500=y
# CONFIG_FB_VIRTUAL is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_CORGI is not set
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=y
+
+#
+# Display hardware drivers
+#
#
# Console display driver support
@@ -1327,6 +1409,12 @@ CONFIG_SND_AOA_SOUNDBUS_I2S=m
# CONFIG_SND_USB_CAIAQ is not set
#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
+
+#
# System on Chip audio support
#
# CONFIG_SND_SOC is not set
@@ -1342,6 +1430,7 @@ CONFIG_SND_AOA_SOUNDBUS_I2S=m
CONFIG_HID_SUPPORT=y
CONFIG_HID=y
# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
#
# USB Input Devices
@@ -1483,19 +1572,53 @@ CONFIG_EDAC=y
#
# CONFIG_EDAC_DEBUG is not set
CONFIG_EDAC_MM_EDAC=y
-# CONFIG_RTC_CLASS is not set
+CONFIG_EDAC_PASEMI=y
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+CONFIG_RTC_DRV_DS1307=y
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
#
-# DMA Engine support
+# SPI RTC drivers
#
-# CONFIG_DMA_ENGINE is not set
#
-# DMA Clients
+# Platform RTC drivers
#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
#
-# DMA Devices
+# on-CPU RTC drivers
#
#
@@ -1579,7 +1702,6 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
-CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -1598,10 +1720,7 @@ CONFIG_CRAMFS=y
# CONFIG_QNX4FS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
+CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
CONFIG_NFS_V3_ACL=y
@@ -1613,6 +1732,7 @@ CONFIG_NFSD_V3=y
CONFIG_NFSD_V3_ACL=y
CONFIG_NFSD_V4=y
CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_EXPORTFS=m
@@ -1620,6 +1740,7 @@ CONFIG_NFS_ACL_SUPPORT=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
+CONFIG_SUNRPC_XPRT_RDMA=m
# CONFIG_SUNRPC_BIND34 is not set
CONFIG_RPCSEC_GSS_KRB5=y
CONFIG_RPCSEC_GSS_SPKM3=m
@@ -1656,10 +1777,6 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
# CONFIG_SYSV68_PARTITION is not set
-
-#
-# Native Language Support
-#
CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
CONFIG_NLS_CODEPAGE_437=y
@@ -1700,10 +1817,6 @@ CONFIG_NLS_ISO8859_15=m
CONFIG_NLS_KOI8_R=m
CONFIG_NLS_KOI8_U=m
CONFIG_NLS_UTF8=m
-
-#
-# Distributed Lock Manager
-#
# CONFIG_DLM is not set
# CONFIG_UCC_SLOW is not set
@@ -1727,18 +1840,17 @@ CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAS_DMA=y
-
-#
-# Instrumentation Support
-#
+CONFIG_INSTRUMENTATION=y
CONFIG_PROFILING=y
CONFIG_OPROFILE=y
# CONFIG_KPROBES is not set
+# CONFIG_MARKERS is not set
#
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
@@ -1750,7 +1862,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
@@ -1762,9 +1874,12 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
CONFIG_FORCED_INLINING=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_FAULT_INJECTION is not set
+# CONFIG_SAMPLES is not set
CONFIG_DEBUG_STACKOVERFLOW=y
CONFIG_DEBUG_STACK_USAGE=y
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -1774,6 +1889,7 @@ CONFIG_XMON=y
# CONFIG_XMON_DEFAULT is not set
CONFIG_XMON_DISASSEMBLY=y
CONFIG_IRQSTACKS=y
+# CONFIG_VIRQ_DEBUG is not set
CONFIG_BOOTX_TEXT=y
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -1782,6 +1898,7 @@ CONFIG_BOOTX_TEXT=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_XOR_BLOCKS=y
CONFIG_ASYNC_CORE=y
CONFIG_ASYNC_MEMCPY=y
@@ -1806,6 +1923,7 @@ CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_XTS is not set
# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_FCRYPT is not set
@@ -1820,9 +1938,12 @@ CONFIG_CRYPTO_TEA=m
CONFIG_CRYPTO_ARC4=m
CONFIG_CRYPTO_KHAZAD=m
CONFIG_CRYPTO_ANUBIS=m
+# CONFIG_CRYPTO_SEED is not set
CONFIG_CRYPTO_DEFLATE=m
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_CRC32C=m
# CONFIG_CRYPTO_CAMELLIA is not set
CONFIG_CRYPTO_TEST=m
+# CONFIG_CRYPTO_AUTHENC is not set
# CONFIG_CRYPTO_HW is not set
+# CONFIG_PPC_CLOCK is not set
diff --git a/arch/powerpc/configs/pq2fads_defconfig b/arch/powerpc/configs/pq2fads_defconfig
index a51fc39dea4e..9191f557b044 100644
--- a/arch/powerpc/configs/pq2fads_defconfig
+++ b/arch/powerpc/configs/pq2fads_defconfig
@@ -86,8 +86,9 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
@@ -930,7 +931,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHED_DEBUG is not set
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/powerpc/configs/prpmc2800_defconfig b/arch/powerpc/configs/prpmc2800_defconfig
index cce3d3da086b..3e87faf9b5c2 100644
--- a/arch/powerpc/configs/prpmc2800_defconfig
+++ b/arch/powerpc/configs/prpmc2800_defconfig
@@ -89,8 +89,9 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig
index ca7a197998ee..3566c448bdc0 100644
--- a/arch/powerpc/configs/ps3_defconfig
+++ b/arch/powerpc/configs/ps3_defconfig
@@ -91,8 +91,9 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
@@ -1059,7 +1060,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
CONFIG_DEBUG_SPINLOCK=y
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
index 0f274e5f6926..62a38406b62f 100644
--- a/arch/powerpc/configs/pseries_defconfig
+++ b/arch/powerpc/configs/pseries_defconfig
@@ -71,6 +71,7 @@ CONFIG_AUDITSYSCALL=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=17
+CONFIG_CGROUPS=y
CONFIG_CPUSETS=y
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
@@ -96,8 +97,9 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
@@ -176,6 +178,10 @@ CONFIG_IBMEBUS=y
#
# Kernel options
#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
# CONFIG_HZ_300 is not set
@@ -1504,7 +1510,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/powerpc/configs/sequoia_defconfig b/arch/powerpc/configs/sequoia_defconfig
index bc7f5089a894..45a4ca0e0d7d 100644
--- a/arch/powerpc/configs/sequoia_defconfig
+++ b/arch/powerpc/configs/sequoia_defconfig
@@ -91,8 +91,9 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
@@ -781,7 +782,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/powerpc/configs/walnut_defconfig b/arch/powerpc/configs/walnut_defconfig
index 766bf840c18d..02896ecba490 100644
--- a/arch/powerpc/configs/walnut_defconfig
+++ b/arch/powerpc/configs/walnut_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.23-rc4
-# Wed Sep 5 12:06:37 2007
+# Linux kernel version: 2.6.23
+# Thu Oct 18 12:54:18 2007
#
# CONFIG_PPC64 is not set
@@ -18,8 +18,13 @@ CONFIG_4xx=y
# CONFIG_PPC_MM_SLICES is not set
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_PPC32=y
+CONFIG_WORD_SIZE=32
CONFIG_PPC_MERGE=y
CONFIG_MMU=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_IRQ_PER_CPU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
@@ -63,6 +68,8 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_FAIR_USER_SCHED=y
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_BLK_DEV_INITRD=y
@@ -83,12 +90,12 @@ CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
@@ -126,7 +133,9 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
# CONFIG_PQ2ADS is not set
+# CONFIG_KILAUEA is not set
CONFIG_WALNUT=y
+# CONFIG_XILINX_VIRTEX_GENERIC_BOARD is not set
CONFIG_405GP=y
CONFIG_IBM405_ERR77=y
CONFIG_IBM405_ERR51=y
@@ -147,6 +156,10 @@ CONFIG_IBM405_ERR51=y
# Kernel options
#
# CONFIG_HIGHMEM is not set
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
# CONFIG_HZ_300 is not set
@@ -168,6 +181,7 @@ CONFIG_FLATMEM_MANUAL=y
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_RESOURCES_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
@@ -176,6 +190,8 @@ CONFIG_VIRT_TO_BUS=y
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
# CONFIG_PM is not set
+CONFIG_SUSPEND_UP_POSSIBLE=y
+CONFIG_HIBERNATION_UP_POSSIBLE=y
CONFIG_SECCOMP=y
CONFIG_WANT_DEVICE_TREE=y
CONFIG_DEVICE_TREE="walnut.dts"
@@ -189,10 +205,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_PCI_DOMAINS is not set
# CONFIG_PCI_SYSCALL is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
# CONFIG_PCCARD is not set
#
@@ -206,7 +218,7 @@ CONFIG_ZONE_DMA=y
CONFIG_HIGHMEM_START=0xfe000000
CONFIG_LOWMEM_SIZE=0x30000000
CONFIG_KERNEL_START=0xc0000000
-CONFIG_TASK_SIZE=0x80000000
+CONFIG_TASK_SIZE=0xc0000000
CONFIG_CONSISTENT_START=0xff100000
CONFIG_CONSISTENT_SIZE=0x00200000
CONFIG_BOOT_LOAD=0x00400000
@@ -243,6 +255,7 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
# CONFIG_INET_XFRM_MODE_TUNNEL is not set
# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
@@ -300,6 +313,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
#
# Generic Driver Options
#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=y
@@ -327,6 +341,7 @@ CONFIG_MTD_BLOCK=m
# CONFIG_INFTL is not set
# CONFIG_RFD_FTL is not set
# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
#
# RAM/ROM/Flash chip drivers
@@ -359,7 +374,6 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
# CONFIG_MTD_PHYSMAP is not set
CONFIG_MTD_PHYSMAP_OF=y
-# CONFIG_MTD_WALNUT is not set
# CONFIG_MTD_PLATRAM is not set
#
@@ -418,7 +432,22 @@ CONFIG_NETDEVICES=y
# CONFIG_MACVLAN is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-# CONFIG_NET_ETHERNET is not set
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+CONFIG_IBM_NEW_EMAC=y
+CONFIG_IBM_NEW_EMAC_RXB=128
+CONFIG_IBM_NEW_EMAC_TXB=64
+CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
+CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
+CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
+# CONFIG_IBM_NEW_EMAC_DEBUG is not set
+CONFIG_IBM_NEW_EMAC_ZMII=y
+# 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_B44 is not set
CONFIG_NETDEV_1000=y
CONFIG_NETDEV_10000=y
@@ -497,6 +526,12 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_HWMON is not set
#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
# Multifunction device drivers
#
# CONFIG_MFD_SM501 is not set
@@ -511,16 +546,15 @@ CONFIG_LEGACY_PTY_COUNT=256
#
# Graphics support
#
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+# CONFIG_FB is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
-# CONFIG_VGASTATE is not set
-CONFIG_VIDEO_OUTPUT_CONTROL=m
-# CONFIG_FB is not set
-# CONFIG_FB_IBM_GXT4500 is not set
#
# Sound
@@ -545,19 +579,6 @@ CONFIG_USB_SUPPORT=y
# CONFIG_RTC_CLASS is not set
#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
# Userspace I/O
#
# CONFIG_UIO is not set
@@ -609,7 +630,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -629,10 +649,7 @@ CONFIG_CRAMFS=y
# CONFIG_QNX4FS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
+CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
@@ -658,15 +675,7 @@ CONFIG_SUNRPC=y
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
# CONFIG_NLS is not set
-
-#
-# Distributed Lock Manager
-#
# CONFIG_DLM is not set
# CONFIG_UCC_SLOW is not set
@@ -706,7 +715,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
@@ -719,6 +728,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_FAULT_INJECTION is not set
# CONFIG_DEBUG_STACKOVERFLOW is not set
@@ -733,6 +743,7 @@ CONFIG_FORCED_INLINING=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_CRYPTO=y
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_BLKCIPHER=y
@@ -752,6 +763,7 @@ CONFIG_CRYPTO_ECB=y
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_PCBC=y
# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_XTS is not set
# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_FCRYPT is not set
@@ -765,9 +777,12 @@ CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_ARC4 is not set
# CONFIG_CRYPTO_KHAZAD is not set
# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_SEED is not set
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_MICHAEL_MIC is not set
# CONFIG_CRYPTO_CRC32C is not set
# CONFIG_CRYPTO_CAMELLIA is not set
# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO_AUTHENC is not set
CONFIG_CRYPTO_HW=y
+# CONFIG_PPC_CLOCK is not set
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 0ae5d57b9368..2c8e756d19a3 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -141,6 +141,7 @@ int main(void)
DEFINE(PACALPPACAPTR, offsetof(struct paca_struct, lppaca_ptr));
DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id));
DEFINE(PACA_STARTPURR, offsetof(struct paca_struct, startpurr));
+ DEFINE(PACA_STARTSPURR, offsetof(struct paca_struct, startspurr));
DEFINE(PACA_USER_TIME, offsetof(struct paca_struct, user_time));
DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time));
DEFINE(PACA_SLBSHADOWPTR, offsetof(struct paca_struct, slb_shadow_ptr));
diff --git a/arch/powerpc/kernel/binfmt_elf32.c b/arch/powerpc/kernel/binfmt_elf32.c
index 5cb58757e1b1..1d45d7782d4e 100644
--- a/arch/powerpc/kernel/binfmt_elf32.c
+++ b/arch/powerpc/kernel/binfmt_elf32.c
@@ -13,49 +13,44 @@
* 2 of the License, or (at your option) any later version.
*/
-#define ELF_ARCH EM_PPC
-#define ELF_CLASS ELFCLASS32
-#define ELF_DATA ELFDATA2MSB;
-
#include <asm/processor.h>
#include <linux/module.h>
-#include <linux/elfcore.h>
#include <linux/compat.h>
+#include <linux/elfcore-compat.h>
+
+#undef ELF_ARCH
+#undef ELF_CLASS
+#define ELF_CLASS ELFCLASS32
+#define ELF_ARCH EM_PPC
+
+#undef elfhdr
+#undef elf_phdr
+#undef elf_note
+#undef elf_addr_t
+#define elfhdr elf32_hdr
+#define elf_phdr elf32_phdr
+#define elf_note elf32_note
+#define elf_addr_t Elf32_Off
-#define elf_prstatus elf_prstatus32
-struct elf_prstatus32
+#define elf_prstatus compat_elf_prstatus
+#define elf_prpsinfo compat_elf_prpsinfo
+
+#define elf_core_copy_regs compat_elf_core_copy_regs
+static inline void compat_elf_core_copy_regs(compat_elf_gregset_t *elf_regs,
+ struct pt_regs *regs)
{
- struct elf_siginfo pr_info; /* Info associated with signal */
- short pr_cursig; /* Current signal */
- unsigned int pr_sigpend; /* Set of pending signals */
- unsigned int pr_sighold; /* Set of held signals */
- pid_t pr_pid;
- pid_t pr_ppid;
- pid_t pr_pgrp;
- pid_t pr_sid;
- struct compat_timeval pr_utime; /* User time */
- struct compat_timeval pr_stime; /* System time */
- struct compat_timeval pr_cutime; /* Cumulative user time */
- struct compat_timeval pr_cstime; /* Cumulative system time */
- elf_gregset_t pr_reg; /* General purpose registers. */
- int pr_fpvalid; /* True if math co-processor being used. */
-};
+ PPC_ELF_CORE_COPY_REGS((*elf_regs), regs);
+}
-#define elf_prpsinfo elf_prpsinfo32
-struct elf_prpsinfo32
+#define elf_core_copy_task_regs compat_elf_core_copy_task_regs
+static int compat_elf_core_copy_task_regs(struct task_struct *tsk,
+ compat_elf_gregset_t *elf_regs)
{
- char pr_state; /* numeric process state */
- char pr_sname; /* char for pr_state */
- char pr_zomb; /* zombie */
- char pr_nice; /* nice val */
- unsigned int pr_flag; /* flags */
- u32 pr_uid;
- u32 pr_gid;
- pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid;
- /* Lots missing */
- char pr_fname[16]; /* filename of executable */
- char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
-};
+ struct pt_regs *regs = tsk->thread.regs;
+ if (regs)
+ compat_elf_core_copy_regs(elf_regs, regs);
+ return 1;
+}
#include <linux/time.h>
diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c
index 3ef51fb6f107..9c74fdf29eec 100644
--- a/arch/powerpc/kernel/btext.c
+++ b/arch/powerpc/kernel/btext.c
@@ -186,7 +186,9 @@ int btext_initialize(struct device_node *np)
pitch = *prop;
if (pitch == 1)
pitch = 0x1000;
- prop = of_get_property(np, "address", NULL);
+ prop = of_get_property(np, "linux,bootx-addr", NULL);
+ if (prop == NULL)
+ prop = of_get_property(np, "address", NULL);
if (prop)
address = *prop;
diff --git a/arch/powerpc/kernel/cpu_setup_6xx.S b/arch/powerpc/kernel/cpu_setup_6xx.S
index 8b4a4ee85eca..f1ee0b3f78f2 100644
--- a/arch/powerpc/kernel/cpu_setup_6xx.S
+++ b/arch/powerpc/kernel/cpu_setup_6xx.S
@@ -113,7 +113,7 @@ setup_604_hid0:
* around #3 and with the same fix we use. We may want to
* check if the CPU is using 60x bus mode in which case
* the workaround for errata #4 is useless. Also, we may
- * want to explicitely clear HID0_NOPDST as this is not
+ * want to explicitly clear HID0_NOPDST as this is not
* needed once we have applied workaround #5 (though it's
* not set by Apple's firmware at least).
*/
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index d3fb7d0c6c1c..9ed351f3c966 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -1104,6 +1104,16 @@ static struct cpu_spec __initdata cpu_specs[] = {
{
.pvr_mask = 0xf0000fff,
.pvr_value = 0x40000850,
+ .cpu_name = "440GR Rev. A",
+ .cpu_features = CPU_FTRS_44X,
+ .cpu_user_features = COMMON_USER_BOOKE,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .platform = "ppc440",
+ },
+ { /* Use logical PVR for 440EP (logical pvr = pvr | 0x8) */
+ .pvr_mask = 0xf0000fff,
+ .pvr_value = 0x40000858,
.cpu_name = "440EP Rev. A",
.cpu_features = CPU_FTRS_44X,
.cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
@@ -1115,28 +1125,27 @@ static struct cpu_spec __initdata cpu_specs[] = {
{
.pvr_mask = 0xf0000fff,
.pvr_value = 0x400008d3,
- .cpu_name = "440EP Rev. B",
+ .cpu_name = "440GR Rev. B",
.cpu_features = CPU_FTRS_44X,
.cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
.icache_bsize = 32,
.dcache_bsize = 32,
- .cpu_setup = __setup_cpu_440ep,
.platform = "ppc440",
},
- { /* 440EPX */
- .pvr_mask = 0xf0000ffb,
- .pvr_value = 0x200008D0,
- .cpu_name = "440EPX",
+ { /* Use logical PVR for 440EP (logical pvr = pvr | 0x8) */
+ .pvr_mask = 0xf0000fff,
+ .pvr_value = 0x400008db,
+ .cpu_name = "440EP Rev. B",
.cpu_features = CPU_FTRS_44X,
.cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
.icache_bsize = 32,
.dcache_bsize = 32,
- .cpu_setup = __setup_cpu_440epx,
+ .cpu_setup = __setup_cpu_440ep,
.platform = "ppc440",
},
{ /* 440GRX */
.pvr_mask = 0xf0000ffb,
- .pvr_value = 0x200008D8,
+ .pvr_value = 0x200008D0,
.cpu_name = "440GRX",
.cpu_features = CPU_FTRS_44X,
.cpu_user_features = COMMON_USER_BOOKE,
@@ -1145,6 +1154,17 @@ static struct cpu_spec __initdata cpu_specs[] = {
.cpu_setup = __setup_cpu_440grx,
.platform = "ppc440",
},
+ { /* Use logical PVR for 440EPx (logical pvr = pvr | 0x8) */
+ .pvr_mask = 0xf0000ffb,
+ .pvr_value = 0x200008D8,
+ .cpu_name = "440EPX",
+ .cpu_features = CPU_FTRS_44X,
+ .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .cpu_setup = __setup_cpu_440epx,
+ .platform = "ppc440",
+ },
{ /* 440GP Rev. B */
.pvr_mask = 0xf0000fff,
.pvr_value = 0x40000440,
diff --git a/arch/powerpc/kernel/dma_64.c b/arch/powerpc/kernel/dma_64.c
index 7b0e754383cf..14206e3f0819 100644
--- a/arch/powerpc/kernel/dma_64.c
+++ b/arch/powerpc/kernel/dma_64.c
@@ -154,14 +154,14 @@ static void dma_direct_unmap_single(struct device *dev, dma_addr_t dma_addr,
{
}
-static int dma_direct_map_sg(struct device *dev, struct scatterlist *sg,
+static int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl,
int nents, enum dma_data_direction direction)
{
+ struct scatterlist *sg;
int i;
- for (i = 0; i < nents; i++, sg++) {
- sg->dma_address = (page_to_phys(sg->page) + sg->offset) |
- dma_direct_offset;
+ for_each_sg(sgl, sg, nents, i) {
+ sg->dma_address = sg_phys(sg) | dma_direct_offset;
sg->dma_length = sg->length;
}
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index 21d889e63e87..69a91bd46115 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -244,6 +244,16 @@ syscall_exit_cont:
andis. r10,r0,DBCR0_IC@h
bnel- load_dbcr0
#endif
+#ifdef CONFIG_44x
+ lis r4,icache_44x_need_flush@ha
+ lwz r5,icache_44x_need_flush@l(r4)
+ cmplwi cr0,r5,0
+ bne- 2f
+1:
+#endif /* CONFIG_44x */
+BEGIN_FTR_SECTION
+ lwarx r7,0,r1
+END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX)
stwcx. r0,0,r1 /* to clear the reservation */
lwz r4,_LINK(r1)
lwz r5,_CCR(r1)
@@ -258,6 +268,12 @@ syscall_exit_cont:
mtspr SPRN_SRR1,r8
SYNC
RFI
+#ifdef CONFIG_44x
+2: li r7,0
+ iccci r0,r0
+ stw r7,icache_44x_need_flush@l(r4)
+ b 1b
+#endif /* CONFIG_44x */
66: li r3,-ENOSYS
b ret_from_syscall
@@ -683,6 +699,16 @@ resume_kernel:
/* interrupts are hard-disabled at this point */
restore:
+#ifdef CONFIG_44x
+ lis r4,icache_44x_need_flush@ha
+ lwz r5,icache_44x_need_flush@l(r4)
+ cmplwi cr0,r5,0
+ beq+ 1f
+ li r6,0
+ iccci r0,r0
+ stw r6,icache_44x_need_flush@l(r4)
+1:
+#endif /* CONFIG_44x */
lwz r0,GPR0(r1)
lwz r2,GPR2(r1)
REST_4GPRS(3, r1)
@@ -694,6 +720,9 @@ restore:
mtctr r11
PPC405_ERR77(0,r1)
+BEGIN_FTR_SECTION
+ lwarx r11,0,r1
+END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX)
stwcx. r0,0,r1 /* to clear the reservation */
#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 0ec134034899..148a3547c9aa 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -408,6 +408,12 @@ END_FTR_SECTION_IFSET(CPU_FTR_1T_SEGMENT)
std r7,SLBSHADOW_STACKVSID(r9) /* Save VSID */
std r0,SLBSHADOW_STACKESID(r9) /* Save ESID */
+ /* No need to check for CPU_FTR_NO_SLBIE_B here, since when
+ * we have 1TB segments, the only CPUs known to have the errata
+ * only support less than 1TB of system memory and we'll never
+ * actually hit this code path.
+ */
+
slbie r6
slbie r6 /* Workaround POWER5 < DD2.1 issue */
slbmte r7,r0
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 97c5857faf00..c34986835a4e 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -904,7 +904,7 @@ handle_page_fault:
*/
12: bl .save_nvgprs
addi r3,r1,STACK_FRAME_OVERHEAD
- lwz r4,_DAR(r1)
+ ld r4,_DAR(r1)
bl .low_hash_fault
b .ret_from_except
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index 53bf64623bd8..72fd87156b24 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -41,6 +41,7 @@
#include <linux/kobject.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
+#include <linux/of_platform.h>
#include <asm/ibmebus.h>
#include <asm/abs_addr.h>
@@ -50,6 +51,13 @@ static struct device ibmebus_bus_device = { /* fake "parent" device */
struct bus_type ibmebus_bus_type;
+/* These devices will automatically be added to the bus during init */
+static struct of_device_id builtin_matches[] = {
+ { .compatible = "IBM,lhca" },
+ { .compatible = "IBM,lhea" },
+ {},
+};
+
static void *ibmebus_alloc_coherent(struct device *dev,
size_t size,
dma_addr_t *dma_handle,
@@ -87,15 +95,15 @@ static void ibmebus_unmap_single(struct device *dev,
}
static int ibmebus_map_sg(struct device *dev,
- struct scatterlist *sg,
+ struct scatterlist *sgl,
int nents, enum dma_data_direction direction)
{
+ struct scatterlist *sg;
int i;
- for (i = 0; i < nents; i++) {
- sg[i].dma_address = (dma_addr_t)page_address(sg[i].page)
- + sg[i].offset;
- sg[i].dma_length = sg[i].length;
+ for_each_sg(sgl, sg, nents, i) {
+ sg->dma_address = (dma_addr_t) sg_virt(sg);
+ sg->dma_length = sg->length;
}
return nents;
@@ -123,190 +131,87 @@ static struct dma_mapping_ops ibmebus_dma_ops = {
.dma_supported = ibmebus_dma_supported,
};
-static int ibmebus_bus_probe(struct device *dev)
+static int ibmebus_match_path(struct device *dev, void *data)
{
- struct ibmebus_dev *ibmebusdev = to_ibmebus_dev(dev);
- struct ibmebus_driver *ibmebusdrv = to_ibmebus_driver(dev->driver);
- const struct of_device_id *id;
- int error = -ENODEV;
-
- if (!ibmebusdrv->probe)
- return error;
-
- id = of_match_device(ibmebusdrv->id_table, &ibmebusdev->ofdev);
- if (id) {
- error = ibmebusdrv->probe(ibmebusdev, id);
- }
-
- return error;
+ struct device_node *dn = to_of_device(dev)->node;
+ return (dn->full_name &&
+ (strcasecmp((char *)data, dn->full_name) == 0));
}
-static int ibmebus_bus_remove(struct device *dev)
+static int ibmebus_match_node(struct device *dev, void *data)
{
- struct ibmebus_dev *ibmebusdev = to_ibmebus_dev(dev);
- struct ibmebus_driver *ibmebusdrv = to_ibmebus_driver(dev->driver);
-
- if (ibmebusdrv->remove) {
- return ibmebusdrv->remove(ibmebusdev);
- }
-
- return 0;
+ return to_of_device(dev)->node == data;
}
-static void __devinit ibmebus_dev_release(struct device *dev)
+static int ibmebus_create_device(struct device_node *dn)
{
- of_node_put(to_ibmebus_dev(dev)->ofdev.node);
- kfree(to_ibmebus_dev(dev));
-}
-
-static int __devinit ibmebus_register_device_common(
- struct ibmebus_dev *dev, const char *name)
-{
- int err = 0;
-
- dev->ofdev.dev.parent = &ibmebus_bus_device;
- dev->ofdev.dev.bus = &ibmebus_bus_type;
- dev->ofdev.dev.release = ibmebus_dev_release;
+ struct of_device *dev;
+ int ret;
- dev->ofdev.dev.archdata.of_node = dev->ofdev.node;
- dev->ofdev.dev.archdata.dma_ops = &ibmebus_dma_ops;
- dev->ofdev.dev.archdata.numa_node = of_node_to_nid(dev->ofdev.node);
-
- /* An ibmebusdev is based on a of_device. We have to change the
- * bus type to use our own DMA mapping operations.
- */
- if ((err = of_device_register(&dev->ofdev)) != 0) {
- printk(KERN_ERR "%s: failed to register device (%d).\n",
- __FUNCTION__, err);
- return -ENODEV;
- }
-
- return 0;
-}
-
-static struct ibmebus_dev* __devinit ibmebus_register_device_node(
- struct device_node *dn)
-{
- struct ibmebus_dev *dev;
- int i, len, bus_len;
-
- dev = kzalloc(sizeof(struct ibmebus_dev), GFP_KERNEL);
+ dev = of_device_alloc(dn, NULL, &ibmebus_bus_device);
if (!dev)
- return ERR_PTR(-ENOMEM);
-
- dev->ofdev.node = of_node_get(dn);
-
- len = strlen(dn->full_name + 1);
- bus_len = min(len, BUS_ID_SIZE - 1);
- memcpy(dev->ofdev.dev.bus_id, dn->full_name + 1
- + (len - bus_len), bus_len);
- for (i = 0; i < bus_len; i++)
- if (dev->ofdev.dev.bus_id[i] == '/')
- dev->ofdev.dev.bus_id[i] = '_';
-
- /* Register with generic device framework. */
- if (ibmebus_register_device_common(dev, dn->name) != 0) {
- kfree(dev);
- return ERR_PTR(-ENODEV);
- }
-
- return dev;
-}
-
-static void ibmebus_probe_of_nodes(char* name)
-{
- struct device_node *dn = NULL;
-
- while ((dn = of_find_node_by_name(dn, name))) {
- if (IS_ERR(ibmebus_register_device_node(dn))) {
- of_node_put(dn);
- return;
- }
- }
-
- of_node_put(dn);
+ return -ENOMEM;
- return;
-}
+ dev->dev.bus = &ibmebus_bus_type;
+ dev->dev.archdata.dma_ops = &ibmebus_dma_ops;
-static void ibmebus_add_devices_by_id(struct of_device_id *idt)
-{
- while (strlen(idt->name) > 0) {
- ibmebus_probe_of_nodes(idt->name);
- idt++;
+ ret = of_device_register(dev);
+ if (ret) {
+ of_device_free(dev);
+ return ret;
}
- return;
-}
-
-static int ibmebus_match_name(struct device *dev, void *data)
-{
- const struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev);
- const char *name;
-
- name = of_get_property(ebus_dev->ofdev.node, "name", NULL);
-
- if (name && (strcmp(data, name) == 0))
- return 1;
-
return 0;
}
-static int ibmebus_unregister_device(struct device *dev)
+static int ibmebus_create_devices(const struct of_device_id *matches)
{
- of_device_unregister(to_of_device(dev));
+ struct device_node *root, *child;
+ int ret = 0;
- return 0;
-}
+ root = of_find_node_by_path("/");
-static void ibmebus_remove_devices_by_id(struct of_device_id *idt)
-{
- struct device *dev;
+ for (child = NULL; (child = of_get_next_child(root, child)); ) {
+ if (!of_match_node(matches, child))
+ continue;
- while (strlen(idt->name) > 0) {
- while ((dev = bus_find_device(&ibmebus_bus_type, NULL,
- (void*)idt->name,
- ibmebus_match_name))) {
- ibmebus_unregister_device(dev);
+ if (bus_find_device(&ibmebus_bus_type, NULL, child,
+ ibmebus_match_node))
+ continue;
+
+ ret = ibmebus_create_device(child);
+ if (ret) {
+ printk(KERN_ERR "%s: failed to create device (%i)",
+ __FUNCTION__, ret);
+ of_node_put(child);
+ break;
}
- idt++;
}
- return;
+ of_node_put(root);
+ return ret;
}
-int ibmebus_register_driver(struct ibmebus_driver *drv)
+int ibmebus_register_driver(struct of_platform_driver *drv)
{
- int err = 0;
+ /* If the driver uses devices that ibmebus doesn't know, add them */
+ ibmebus_create_devices(drv->match_table);
drv->driver.name = drv->name;
drv->driver.bus = &ibmebus_bus_type;
- drv->driver.probe = ibmebus_bus_probe;
- drv->driver.remove = ibmebus_bus_remove;
- if ((err = driver_register(&drv->driver) != 0))
- return err;
-
- /* remove all supported devices first, in case someone
- * probed them manually before registering the driver */
- ibmebus_remove_devices_by_id(drv->id_table);
- ibmebus_add_devices_by_id(drv->id_table);
-
- return 0;
+ return driver_register(&drv->driver);
}
EXPORT_SYMBOL(ibmebus_register_driver);
-void ibmebus_unregister_driver(struct ibmebus_driver *drv)
+void ibmebus_unregister_driver(struct of_platform_driver *drv)
{
driver_unregister(&drv->driver);
- ibmebus_remove_devices_by_id(drv->id_table);
}
EXPORT_SYMBOL(ibmebus_unregister_driver);
-int ibmebus_request_irq(struct ibmebus_dev *dev,
- u32 ist,
- irq_handler_t handler,
- unsigned long irq_flags, const char * devname,
+int ibmebus_request_irq(u32 ist, irq_handler_t handler,
+ unsigned long irq_flags, const char *devname,
void *dev_id)
{
unsigned int irq = irq_create_mapping(NULL, ist);
@@ -314,12 +219,11 @@ int ibmebus_request_irq(struct ibmebus_dev *dev,
if (irq == NO_IRQ)
return -EINVAL;
- return request_irq(irq, handler,
- irq_flags, devname, dev_id);
+ return request_irq(irq, handler, irq_flags, devname, dev_id);
}
EXPORT_SYMBOL(ibmebus_request_irq);
-void ibmebus_free_irq(struct ibmebus_dev *dev, u32 ist, void *dev_id)
+void ibmebus_free_irq(u32 ist, void *dev_id)
{
unsigned int irq = irq_find_mapping(NULL, ist);
@@ -327,29 +231,10 @@ void ibmebus_free_irq(struct ibmebus_dev *dev, u32 ist, void *dev_id)
}
EXPORT_SYMBOL(ibmebus_free_irq);
-static int ibmebus_bus_match(struct device *dev, struct device_driver *drv)
-{
- const struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev);
- struct ibmebus_driver *ebus_drv = to_ibmebus_driver(drv);
- const struct of_device_id *ids = ebus_drv->id_table;
- const struct of_device_id *found_id;
-
- if (!ids)
- return 0;
-
- found_id = of_match_device(ids, &ebus_dev->ofdev);
- if (found_id)
- return 1;
-
- return 0;
-}
-
static ssize_t name_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev);
- const char *name = of_get_property(ebus_dev->ofdev.node, "name", NULL);
- return sprintf(buf, "%s\n", name);
+ return sprintf(buf, "%s\n", to_of_device(dev)->node->name);
}
static struct device_attribute ibmebus_dev_attrs[] = {
@@ -357,18 +242,6 @@ static struct device_attribute ibmebus_dev_attrs[] = {
__ATTR_NULL
};
-static int ibmebus_match_path(struct device *dev, void *data)
-{
- int rc;
- struct device_node *dn =
- of_node_get(to_ibmebus_dev(dev)->ofdev.node);
-
- rc = (dn->full_name && (strcasecmp((char*)data, dn->full_name) == 0));
-
- of_node_put(dn);
- return rc;
-}
-
static char *ibmebus_chomp(const char *in, size_t count)
{
char *out = kmalloc(count + 1, GFP_KERNEL);
@@ -388,9 +261,8 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus,
const char *buf, size_t count)
{
struct device_node *dn = NULL;
- struct ibmebus_dev *dev;
char *path;
- ssize_t rc;
+ ssize_t rc = 0;
path = ibmebus_chomp(buf, count);
if (!path)
@@ -405,9 +277,8 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus,
}
if ((dn = of_find_node_by_path(path))) {
- dev = ibmebus_register_device_node(dn);
+ rc = ibmebus_create_device(dn);
of_node_put(dn);
- rc = IS_ERR(dev) ? PTR_ERR(dev) : count;
} else {
printk(KERN_WARNING "%s: no such device node: %s\n",
__FUNCTION__, path);
@@ -416,7 +287,9 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus,
out:
kfree(path);
- return rc;
+ if (rc)
+ return rc;
+ return count;
}
static ssize_t ibmebus_store_remove(struct bus_type *bus,
@@ -431,7 +304,7 @@ static ssize_t ibmebus_store_remove(struct bus_type *bus,
if ((dev = bus_find_device(&ibmebus_bus_type, NULL, path,
ibmebus_match_path))) {
- ibmebus_unregister_device(dev);
+ of_device_unregister(to_of_device(dev));
kfree(path);
return count;
@@ -451,8 +324,7 @@ static struct bus_attribute ibmebus_bus_attrs[] = {
};
struct bus_type ibmebus_bus_type = {
- .name = "ibmebus",
- .match = ibmebus_bus_match,
+ .uevent = of_device_uevent,
.dev_attrs = ibmebus_dev_attrs,
.bus_attrs = ibmebus_bus_attrs
};
@@ -464,9 +336,9 @@ static int __init ibmebus_bus_init(void)
printk(KERN_INFO "IBM eBus Device Driver\n");
- err = bus_register(&ibmebus_bus_type);
+ err = of_bus_type_init(&ibmebus_bus_type, "ibmebus");
if (err) {
- printk(KERN_ERR ":%s: failed to register IBM eBus.\n",
+ printk(KERN_ERR "%s: failed to register IBM eBus.\n",
__FUNCTION__);
return err;
}
@@ -480,6 +352,13 @@ static int __init ibmebus_bus_init(void)
return err;
}
+ err = ibmebus_create_devices(builtin_matches);
+ if (err) {
+ device_unregister(&ibmebus_bus_device);
+ bus_unregister(&ibmebus_bus_type);
+ return err;
+ }
+
return 0;
}
-__initcall(ibmebus_bus_init);
+postcore_initcall(ibmebus_bus_init);
diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c
index abd2957fe537..c3cf0e8f3ac1 100644
--- a/arch/powerpc/kernel/idle.c
+++ b/arch/powerpc/kernel/idle.c
@@ -122,7 +122,7 @@ static ctl_table powersave_nap_sysctl_root[] = {
{
.ctl_name = CTL_KERN,
.procname = "kernel",
- .mode = 0755,
+ .mode = 0555,
.child = powersave_nap_ctl_table,
},
{}
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index e4ec6eee81a8..2d0c9ef555e9 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -277,7 +277,7 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
dma_addr_t dma_next = 0, dma_addr;
unsigned long flags;
struct scatterlist *s, *outs, *segstart;
- int outcount, incount;
+ int outcount, incount, i;
unsigned long handle;
BUG_ON(direction == DMA_NONE);
@@ -297,7 +297,7 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
spin_lock_irqsave(&(tbl->it_lock), flags);
- for (s = outs; nelems; nelems--, s++) {
+ for_each_sg(sglist, s, nelems, i) {
unsigned long vaddr, npages, entry, slen;
slen = s->length;
@@ -307,7 +307,7 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
continue;
}
/* Allocate iommu entries for that segment */
- vaddr = (unsigned long)page_address(s->page) + s->offset;
+ vaddr = (unsigned long) sg_virt(s);
npages = iommu_num_pages(vaddr, slen);
entry = iommu_range_alloc(tbl, npages, &handle, mask >> IOMMU_PAGE_SHIFT, 0);
@@ -341,7 +341,8 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
if (novmerge || (dma_addr != dma_next)) {
/* Can't merge: create a new segment */
segstart = s;
- outcount++; outs++;
+ outcount++;
+ outs = sg_next(outs);
DBG(" can't merge, new segment.\n");
} else {
outs->dma_length += s->length;
@@ -374,7 +375,7 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
* next entry of the sglist if we didn't fill the list completely
*/
if (outcount < incount) {
- outs++;
+ outs = sg_next(outs);
outs->dma_address = DMA_ERROR_CODE;
outs->dma_length = 0;
}
@@ -385,7 +386,7 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
return outcount;
failure:
- for (s = &sglist[0]; s <= outs; s++) {
+ for_each_sg(sglist, s, nelems, i) {
if (s->dma_length != 0) {
unsigned long vaddr, npages;
@@ -395,6 +396,8 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
s->dma_address = DMA_ERROR_CODE;
s->dma_length = 0;
}
+ if (s == outs)
+ break;
}
spin_unlock_irqrestore(&(tbl->it_lock), flags);
return 0;
@@ -404,6 +407,7 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction)
{
+ struct scatterlist *sg;
unsigned long flags;
BUG_ON(direction == DMA_NONE);
@@ -413,15 +417,16 @@ void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
spin_lock_irqsave(&(tbl->it_lock), flags);
+ sg = sglist;
while (nelems--) {
unsigned int npages;
- dma_addr_t dma_handle = sglist->dma_address;
+ dma_addr_t dma_handle = sg->dma_address;
- if (sglist->dma_length == 0)
+ if (sg->dma_length == 0)
break;
- npages = iommu_num_pages(dma_handle,sglist->dma_length);
+ npages = iommu_num_pages(dma_handle, sg->dma_length);
__iommu_free(tbl, dma_handle, npages);
- sglist++;
+ sg = sg_next(sg);
}
/* Flush/invalidate TLBs if necessary. As for iommu_free(), we
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 2250f9e6c5ca..b0e5deb4274f 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -491,7 +491,7 @@ struct irq_host *irq_alloc_host(struct device_node *of_node,
/* Legacy flags are left to default at this point,
* one can then use irq_create_mapping() to
- * explicitely change them
+ * explicitly change them
*/
ops->map(host, i, i);
}
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index 440f5a87271f..5338e4855712 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -38,6 +38,8 @@
DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
+struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}};
+
int __kprobes arch_prepare_kprobe(struct kprobe *p)
{
int ret = 0;
diff --git a/arch/powerpc/kernel/l2cr_6xx.S b/arch/powerpc/kernel/l2cr_6xx.S
index 858f28ac8a06..2a2f3c3f6d80 100644
--- a/arch/powerpc/kernel/l2cr_6xx.S
+++ b/arch/powerpc/kernel/l2cr_6xx.S
@@ -1,6 +1,6 @@
/*
L2CR functions
- Copyright © 1997-1998 by PowerLogix R & D, Inc.
+ Copyright © 1997-1998 by PowerLogix R & D, Inc.
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
diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c
index e60a0c544d63..c0c8e8c3ced9 100644
--- a/arch/powerpc/kernel/machine_kexec.c
+++ b/arch/powerpc/kernel/machine_kexec.c
@@ -61,45 +61,39 @@ NORET_TYPE void machine_kexec(struct kimage *image)
for(;;);
}
-static int __init early_parse_crashk(char *p)
-{
- unsigned long size;
-
- if (!p)
- return 1;
-
- size = memparse(p, &p);
-
- if (*p == '@')
- crashk_res.start = memparse(p + 1, &p);
- else
- crashk_res.start = KDUMP_KERNELBASE;
-
- crashk_res.end = crashk_res.start + size - 1;
-
- return 0;
-}
-early_param("crashkernel", early_parse_crashk);
-
void __init reserve_crashkernel(void)
{
- unsigned long size;
+ unsigned long long crash_size, crash_base;
+ int ret;
+
+ /* this is necessary because of lmb_phys_mem_size() */
+ lmb_analyze();
+
+ /* use common parsing */
+ ret = parse_crashkernel(boot_command_line, lmb_phys_mem_size(),
+ &crash_size, &crash_base);
+ if (ret == 0 && crash_size > 0) {
+ if (crash_base == 0)
+ crash_base = KDUMP_KERNELBASE;
+ crashk_res.start = crash_base;
+ } else {
+ /* handle the device tree */
+ crash_size = crashk_res.end - crashk_res.start + 1;
+ }
- if (crashk_res.start == 0)
+ if (crash_size == 0)
return;
/* We might have got these values via the command line or the
* device tree, either way sanitise them now. */
- size = crashk_res.end - crashk_res.start + 1;
-
if (crashk_res.start != KDUMP_KERNELBASE)
printk("Crash kernel location must be 0x%x\n",
KDUMP_KERNELBASE);
crashk_res.start = KDUMP_KERNELBASE;
- size = PAGE_ALIGN(size);
- crashk_res.end = crashk_res.start + size - 1;
+ crash_size = PAGE_ALIGN(crash_size);
+ crashk_res.end = crashk_res.start + crash_size - 1;
/* Crash kernel trumps memory limit */
if (memory_limit && memory_limit <= crashk_res.end) {
@@ -108,7 +102,13 @@ void __init reserve_crashkernel(void)
memory_limit);
}
- lmb_reserve(crashk_res.start, size);
+ printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
+ "for crashkernel (System RAM: %ldMB)\n",
+ (unsigned long)(crash_size >> 20),
+ (unsigned long)(crashk_res.start >> 20),
+ (unsigned long)(lmb_phys_mem_size() >> 20));
+
+ lmb_reserve(crashk_res.start, crash_size);
}
int overlaps_crashkernel(unsigned long start, unsigned long size)
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index 8533de50347d..8b642ab26d37 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -288,7 +288,16 @@ _GLOBAL(_tlbia)
*/
_GLOBAL(_tlbie)
#if defined(CONFIG_40x)
+ /* We run the search with interrupts disabled because we have to change
+ * the PID and I don't want to preempt when that happens.
+ */
+ mfmsr r5
+ mfspr r6,SPRN_PID
+ wrteei 0
+ mtspr SPRN_PID,r4
tlbsx. r3, 0, r3
+ mtspr SPRN_PID,r6
+ wrtee r5
bne 10f
sync
/* There are only 64 TLB entries, so r3 < 64, which means bit 25 is clear.
@@ -297,23 +306,23 @@ _GLOBAL(_tlbie)
tlbwe r3, r3, TLB_TAG
isync
10:
+
#elif defined(CONFIG_44x)
- mfspr r4,SPRN_MMUCR
- mfspr r5,SPRN_PID /* Get PID */
- rlwimi r4,r5,0,24,31 /* Set TID */
+ mfspr r5,SPRN_MMUCR
+ rlwimi r5,r4,0,24,31 /* Set TID */
/* We have to run the search with interrupts disabled, even critical
* and debug interrupts (in fact the only critical exceptions we have
* are debug and machine check). Otherwise an interrupt which causes
* a TLB miss can clobber the MMUCR between the mtspr and the tlbsx. */
- mfmsr r5
+ mfmsr r4
lis r6,(MSR_EE|MSR_CE|MSR_ME|MSR_DE)@ha
addi r6,r6,(MSR_EE|MSR_CE|MSR_ME|MSR_DE)@l
- andc r6,r5,r6
+ andc r6,r4,r6
mtmsr r6
- mtspr SPRN_MMUCR,r4
+ mtspr SPRN_MMUCR,r5
tlbsx. r3, 0, r3
- mtmsr r5
+ mtmsr r4
bne 10f
sync
/* There are only 64 TLB entries, so r3 < 64,
@@ -534,12 +543,21 @@ END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
addi r3,r3,L1_CACHE_BYTES
bdnz 0b
sync
+#ifndef CONFIG_44x
+ /* We don't flush the icache on 44x. Those have a virtual icache
+ * and we don't have access to the virtual address here (it's
+ * not the page vaddr but where it's mapped in user space). The
+ * flushing of the icache on these is handled elsewhere, when
+ * a change in the address space occurs, before returning to
+ * user space
+ */
mtctr r4
1: icbi 0,r6
addi r6,r6,L1_CACHE_BYTES
bdnz 1b
sync
isync
+#endif /* CONFIG_44x */
blr
/*
diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c
index 8f3db32fac8b..3388ad619996 100644
--- a/arch/powerpc/kernel/of_device.c
+++ b/arch/powerpc/kernel/of_device.c
@@ -7,8 +7,88 @@
#include <linux/slab.h>
#include <asm/errno.h>
+#include <asm/dcr.h>
#include <asm/of_device.h>
+static void of_device_make_bus_id(struct of_device *dev)
+{
+ static atomic_t bus_no_reg_magic;
+ struct device_node *node = dev->node;
+ char *name = dev->dev.bus_id;
+ const u32 *reg;
+ u64 addr;
+ int magic;
+
+ /*
+ * If it's a DCR based device, use 'd' for native DCRs
+ * and 'D' for MMIO DCRs.
+ */
+#ifdef CONFIG_PPC_DCR
+ reg = of_get_property(node, "dcr-reg", NULL);
+ if (reg) {
+#ifdef CONFIG_PPC_DCR_NATIVE
+ snprintf(name, BUS_ID_SIZE, "d%x.%s",
+ *reg, node->name);
+#else /* CONFIG_PPC_DCR_NATIVE */
+ addr = of_translate_dcr_address(node, *reg, NULL);
+ if (addr != OF_BAD_ADDR) {
+ snprintf(name, BUS_ID_SIZE,
+ "D%llx.%s", (unsigned long long)addr,
+ node->name);
+ return;
+ }
+#endif /* !CONFIG_PPC_DCR_NATIVE */
+ }
+#endif /* CONFIG_PPC_DCR */
+
+ /*
+ * For MMIO, get the physical address
+ */
+ reg = of_get_property(node, "reg", NULL);
+ if (reg) {
+ addr = of_translate_address(node, reg);
+ if (addr != OF_BAD_ADDR) {
+ snprintf(name, BUS_ID_SIZE,
+ "%llx.%s", (unsigned long long)addr,
+ node->name);
+ return;
+ }
+ }
+
+ /*
+ * No BusID, use the node name and add a globally incremented
+ * counter (and pray...)
+ */
+ magic = atomic_add_return(1, &bus_no_reg_magic);
+ snprintf(name, BUS_ID_SIZE, "%s.%d", node->name, magic - 1);
+}
+
+struct of_device *of_device_alloc(struct device_node *np,
+ const char *bus_id,
+ struct device *parent)
+{
+ struct of_device *dev;
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return NULL;
+
+ dev->node = of_node_get(np);
+ dev->dev.dma_mask = &dev->dma_mask;
+ dev->dev.parent = parent;
+ dev->dev.release = of_release_dev;
+ dev->dev.archdata.of_node = np;
+ dev->dev.archdata.numa_node = of_node_to_nid(np);
+
+ if (bus_id)
+ strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
+ else
+ of_device_make_bus_id(dev);
+
+ return dev;
+}
+EXPORT_SYMBOL(of_device_alloc);
+
ssize_t of_device_get_modalias(struct of_device *ofdev,
char *str, ssize_t len)
{
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
index eca8ccc3fa12..aeaa20268ce2 100644
--- a/arch/powerpc/kernel/of_platform.c
+++ b/arch/powerpc/kernel/of_platform.c
@@ -23,7 +23,6 @@
#include <linux/of_platform.h>
#include <asm/errno.h>
-#include <asm/dcr.h>
#include <asm/topology.h>
#include <asm/pci-bridge.h>
#include <asm/ppc-pci.h>
@@ -53,8 +52,6 @@ static struct of_device_id of_default_bus_ids[] = {
{},
};
-static atomic_t bus_no_reg_magic;
-
struct bus_type of_platform_bus_type = {
.uevent = of_device_uevent,
};
@@ -87,89 +84,26 @@ void of_unregister_platform_driver(struct of_platform_driver *drv)
}
EXPORT_SYMBOL(of_unregister_platform_driver);
-static void of_platform_make_bus_id(struct of_device *dev)
-{
- struct device_node *node = dev->node;
- char *name = dev->dev.bus_id;
- const u32 *reg;
- u64 addr;
- int magic;
-
- /*
- * If it's a DCR based device, use 'd' for native DCRs
- * and 'D' for MMIO DCRs.
- */
-#ifdef CONFIG_PPC_DCR
- reg = of_get_property(node, "dcr-reg", NULL);
- if (reg) {
-#ifdef CONFIG_PPC_DCR_NATIVE
- snprintf(name, BUS_ID_SIZE, "d%x.%s",
- *reg, node->name);
-#else /* CONFIG_PPC_DCR_NATIVE */
- addr = of_translate_dcr_address(node, *reg, NULL);
- if (addr != OF_BAD_ADDR) {
- snprintf(name, BUS_ID_SIZE,
- "D%llx.%s", (unsigned long long)addr,
- node->name);
- return;
- }
-#endif /* !CONFIG_PPC_DCR_NATIVE */
- }
-#endif /* CONFIG_PPC_DCR */
-
- /*
- * For MMIO, get the physical address
- */
- reg = of_get_property(node, "reg", NULL);
- if (reg) {
- addr = of_translate_address(node, reg);
- if (addr != OF_BAD_ADDR) {
- snprintf(name, BUS_ID_SIZE,
- "%llx.%s", (unsigned long long)addr,
- node->name);
- return;
- }
- }
-
- /*
- * No BusID, use the node name and add a globally incremented
- * counter (and pray...)
- */
- magic = atomic_add_return(1, &bus_no_reg_magic);
- snprintf(name, BUS_ID_SIZE, "%s.%d", node->name, magic - 1);
-}
-
struct of_device* of_platform_device_create(struct device_node *np,
const char *bus_id,
struct device *parent)
{
struct of_device *dev;
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ dev = of_device_alloc(np, bus_id, parent);
if (!dev)
return NULL;
- dev->node = of_node_get(np);
dev->dma_mask = 0xffffffffUL;
- dev->dev.dma_mask = &dev->dma_mask;
- dev->dev.parent = parent;
dev->dev.bus = &of_platform_bus_type;
- dev->dev.release = of_release_dev;
- dev->dev.archdata.of_node = np;
- dev->dev.archdata.numa_node = of_node_to_nid(np);
/* We do not fill the DMA ops for platform devices by default.
* This is currently the responsibility of the platform code
* to do such, possibly using a device notifier
*/
- if (bus_id)
- strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
- else
- of_platform_make_bus_id(dev);
-
if (of_device_register(dev) != 0) {
- kfree(dev);
+ of_device_free(dev);
return NULL;
}
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 7949c203cb89..41e13f4cc6e3 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -149,10 +149,32 @@ void flush_altivec_to_thread(struct task_struct *tsk)
}
}
-int dump_task_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs)
+int dump_task_altivec(struct task_struct *tsk, elf_vrregset_t *vrregs)
{
- flush_altivec_to_thread(current);
- memcpy(vrregs, &current->thread.vr[0], sizeof(*vrregs));
+ /* ELF_NVRREG includes the VSCR and VRSAVE which we need to save
+ * separately, see below */
+ const int nregs = ELF_NVRREG - 2;
+ elf_vrreg_t *reg;
+ u32 *dest;
+
+ if (tsk == current)
+ flush_altivec_to_thread(tsk);
+
+ reg = (elf_vrreg_t *)vrregs;
+
+ /* copy the 32 vr registers */
+ memcpy(reg, &tsk->thread.vr[0], nregs * sizeof(*reg));
+ reg += nregs;
+
+ /* copy the vscr */
+ memcpy(reg, &tsk->thread.vscr, sizeof(*reg));
+ reg++;
+
+ /* vrsave is stored in the high 32bit slot of the final 128bits */
+ memset(reg, 0, sizeof(*reg));
+ dest = (u32 *)reg;
+ *dest = tsk->thread.vrsave;
+
return 1;
}
#endif /* CONFIG_ALTIVEC */
@@ -328,7 +350,7 @@ struct task_struct *__switch_to(struct task_struct *prev,
local_irq_save(flags);
account_system_vtime(current);
- account_process_vtime(current);
+ account_process_tick(current, 0);
calculate_steal_time();
last = _switch(old_thread, new_thread);
@@ -437,7 +459,7 @@ void show_regs(struct pt_regs * regs)
printk("DAR: "REG", DSISR: "REG"\n", regs->dar, regs->dsisr);
#endif
printk("TASK = %p[%d] '%s' THREAD: %p",
- current, current->pid, current->comm, task_thread_info(current));
+ current, task_pid_nr(current), current->comm, task_thread_info(current));
#ifdef CONFIG_SMP
printk(" CPU: %d", smp_processor_id());
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 9f329a8928ea..acc0d247d3c3 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -697,6 +697,18 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
prop = of_get_flat_dt_prop(node, "cpu-version", NULL);
if (prop && (*prop & 0xff000000) == 0x0f000000)
identify_cpu(0, *prop);
+#if defined(CONFIG_44x) && defined(CONFIG_PPC_FPU)
+ /*
+ * Since 440GR(x)/440EP(x) processors have the same pvr,
+ * we check the node path and set bit 28 in the cur_cpu_spec
+ * pvr for EP(x) processor version. This bit is always 0 in
+ * the "real" pvr. Then we call identify_cpu again with
+ * the new logical pvr to enable FPU support.
+ */
+ if (strstr(uname, "440EP")) {
+ identify_cpu(0, cur_cpu_spec->pvr_value | 0x8);
+ }
+#endif
}
check_cpu_feature_properties(node);
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 1db10f70ae69..1add6efdb315 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -1244,7 +1244,7 @@ static void __init prom_initialize_tce_table(void)
local_alloc_bottom = base;
/* It seems OF doesn't null-terminate the path :-( */
- memset(path, 0, sizeof(path));
+ memset(path, 0, PROM_SCRATCH_SIZE);
/* Call OF to setup the TCE hardware */
if (call_prom("package-to-path", 3, 1, node,
path, PROM_SCRATCH_SIZE-1) == PROM_ERROR) {
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index cf7732cdd6c7..3e17d154d0d4 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -505,10 +505,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
ret = ptrace_set_debugreg(child, addr, data);
break;
- case PTRACE_DETACH:
- ret = ptrace_detach(child, data);
- break;
-
#ifdef CONFIG_PPC64
case PTRACE_GETREGS64:
#endif
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c
index 62b7bf2f3eab..f2276593f416 100644
--- a/arch/powerpc/kernel/rtas_flash.c
+++ b/arch/powerpc/kernel/rtas_flash.c
@@ -286,7 +286,7 @@ static ssize_t rtas_flash_read(struct file *file, char __user *buf,
}
/* constructor for flash_block_cache */
-void rtas_block_ctor(void *ptr, struct kmem_cache *cache, unsigned long flags)
+void rtas_block_ctor(struct kmem_cache *cache, void *ptr)
{
memset(ptr, 0, RTAS_BLK_SIZE);
}
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 36c90ba2d312..2de00f870edc 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -413,16 +413,28 @@ void __init smp_setup_cpu_maps(void)
of_node_put(dn);
}
+ vdso_data->processorCount = num_present_cpus();
+#endif /* CONFIG_PPC64 */
+}
+
+/*
+ * Being that cpu_sibling_map is now a per_cpu array, then it cannot
+ * be initialized until the per_cpu areas have been created. This
+ * function is now called from setup_per_cpu_areas().
+ */
+void __init smp_setup_cpu_sibling_map(void)
+{
+#if defined(CONFIG_PPC64)
+ int cpu;
+
/*
* Do the sibling map; assume only two threads per processor.
*/
for_each_possible_cpu(cpu) {
- cpu_set(cpu, cpu_sibling_map[cpu]);
+ cpu_set(cpu, per_cpu(cpu_sibling_map, cpu));
if (cpu_has_feature(CPU_FTR_SMT))
- cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]);
+ cpu_set(cpu ^ 0x1, per_cpu(cpu_sibling_map, cpu));
}
-
- vdso_data->processorCount = num_present_cpus();
#endif /* CONFIG_PPC64 */
}
#endif /* CONFIG_SMP */
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 008ab6823b02..3b1529c103ef 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -291,23 +291,16 @@ static void __init initialize_cache_info(void)
if ( num_cpus == 1 ) {
const u32 *sizep, *lsizep;
u32 size, lsize;
- const char *dc, *ic;
-
- /* Then read cache informations */
- if (machine_is(powermac)) {
- dc = "d-cache-block-size";
- ic = "i-cache-block-size";
- } else {
- dc = "d-cache-line-size";
- ic = "i-cache-line-size";
- }
size = 0;
lsize = cur_cpu_spec->dcache_bsize;
sizep = of_get_property(np, "d-cache-size", NULL);
if (sizep != NULL)
size = *sizep;
- lsizep = of_get_property(np, dc, NULL);
+ lsizep = of_get_property(np, "d-cache-block-size", NULL);
+ /* fallback if block size missing */
+ if (lsizep == NULL)
+ lsizep = of_get_property(np, "d-cache-line-size", NULL);
if (lsizep != NULL)
lsize = *lsizep;
if (sizep == 0 || lsizep == 0)
@@ -324,7 +317,9 @@ static void __init initialize_cache_info(void)
sizep = of_get_property(np, "i-cache-size", NULL);
if (sizep != NULL)
size = *sizep;
- lsizep = of_get_property(np, ic, NULL);
+ lsizep = of_get_property(np, "i-cache-block-size", NULL);
+ if (lsizep == NULL)
+ lsizep = of_get_property(np, "i-cache-line-size", NULL);
if (lsizep != NULL)
lsize = *lsizep;
if (sizep == 0 || lsizep == 0)
@@ -426,11 +421,14 @@ void __init setup_system(void)
printk("-----------------------------------------------------\n");
printk("ppc64_pft_size = 0x%lx\n", ppc64_pft_size);
printk("physicalMemorySize = 0x%lx\n", lmb_phys_mem_size());
- printk("ppc64_caches.dcache_line_size = 0x%x\n",
- ppc64_caches.dline_size);
- printk("ppc64_caches.icache_line_size = 0x%x\n",
- ppc64_caches.iline_size);
- printk("htab_address = 0x%p\n", htab_address);
+ if (ppc64_caches.dline_size != 0x80)
+ printk("ppc64_caches.dcache_line_size = 0x%x\n",
+ ppc64_caches.dline_size);
+ if (ppc64_caches.iline_size != 0x80)
+ printk("ppc64_caches.icache_line_size = 0x%x\n",
+ ppc64_caches.iline_size);
+ if (htab_address)
+ printk("htab_address = 0x%p\n", htab_address);
printk("htab_hash_mask = 0x%lx\n", htab_hash_mask);
#if PHYSICAL_START > 0
printk("physical_start = 0x%x\n", PHYSICAL_START);
@@ -597,6 +595,9 @@ void __init setup_per_cpu_areas(void)
paca[i].data_offset = ptr - __per_cpu_start;
memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
}
+
+ /* Now that per_cpu is setup, initialize cpu_sibling_map */
+ smp_setup_cpu_sibling_map();
}
#endif
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index d30f08fa0297..338950aeb6f6 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -61,11 +61,11 @@ struct thread_info *secondary_ti;
cpumask_t cpu_possible_map = CPU_MASK_NONE;
cpumask_t cpu_online_map = CPU_MASK_NONE;
-cpumask_t cpu_sibling_map[NR_CPUS] = { [0 ... NR_CPUS-1] = CPU_MASK_NONE };
+DEFINE_PER_CPU(cpumask_t, cpu_sibling_map) = CPU_MASK_NONE;
EXPORT_SYMBOL(cpu_online_map);
EXPORT_SYMBOL(cpu_possible_map);
-EXPORT_SYMBOL(cpu_sibling_map);
+EXPORT_PER_CPU_SYMBOL(cpu_sibling_map);
/* SMP operations for this machine */
struct smp_ops_t *smp_ops;
diff --git a/arch/powerpc/kernel/swsusp_32.S b/arch/powerpc/kernel/swsusp_32.S
index 69e8f86aa4f8..77fc76607ab2 100644
--- a/arch/powerpc/kernel/swsusp_32.S
+++ b/arch/powerpc/kernel/swsusp_32.S
@@ -133,10 +133,12 @@ _GLOBAL(swsusp_arch_suspend)
/* Resume code */
_GLOBAL(swsusp_arch_resume)
+#ifdef CONFIG_ALTIVEC
/* Stop pending alitvec streams and memory accesses */
BEGIN_FTR_SECTION
DSSALL
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+#endif
sync
/* Disable MSR:DR to make sure we don't take a TLB or
diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c
index bd85b5fd08c8..4a4f5c6b560b 100644
--- a/arch/powerpc/kernel/sys_ppc32.c
+++ b/arch/powerpc/kernel/sys_ppc32.c
@@ -41,10 +41,10 @@
#include <linux/compat.h>
#include <linux/ptrace.h>
#include <linux/elf.h>
+#include <linux/ipc.h>
#include <asm/ptrace.h>
#include <asm/types.h>
-#include <asm/ipc.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
#include <asm/semaphore.h>
diff --git a/arch/powerpc/kernel/syscalls.c b/arch/powerpc/kernel/syscalls.c
index f85f402ceaef..3b1d5dd65643 100644
--- a/arch/powerpc/kernel/syscalls.c
+++ b/arch/powerpc/kernel/syscalls.c
@@ -38,7 +38,6 @@
#include <linux/personality.h>
#include <asm/uaccess.h>
-#include <asm/ipc.h>
#include <asm/semaphore.h>
#include <asm/syscalls.h>
#include <asm/time.h>
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 9368da371f36..c0d77723ba11 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -212,23 +212,44 @@ static u64 read_purr(void)
}
/*
+ * Read the SPURR on systems that have it, otherwise the purr
+ */
+static u64 read_spurr(u64 purr)
+{
+ if (cpu_has_feature(CPU_FTR_SPURR))
+ return mfspr(SPRN_SPURR);
+ return purr;
+}
+
+/*
* Account time for a transition between system, hard irq
* or soft irq state.
*/
void account_system_vtime(struct task_struct *tsk)
{
- u64 now, delta;
+ u64 now, nowscaled, delta, deltascaled;
unsigned long flags;
local_irq_save(flags);
now = read_purr();
delta = now - get_paca()->startpurr;
get_paca()->startpurr = now;
+ nowscaled = read_spurr(now);
+ deltascaled = nowscaled - get_paca()->startspurr;
+ get_paca()->startspurr = nowscaled;
if (!in_interrupt()) {
+ /* deltascaled includes both user and system time.
+ * Hence scale it based on the purr ratio to estimate
+ * the system time */
+ deltascaled = deltascaled * get_paca()->system_time /
+ (get_paca()->system_time + get_paca()->user_time);
delta += get_paca()->system_time;
get_paca()->system_time = 0;
}
account_system_time(tsk, 0, delta);
+ get_paca()->purrdelta = delta;
+ account_system_time_scaled(tsk, deltascaled);
+ get_paca()->spurrdelta = deltascaled;
local_irq_restore(flags);
}
@@ -238,25 +259,19 @@ void account_system_vtime(struct task_struct *tsk)
* user and system time records.
* Must be called with interrupts disabled.
*/
-void account_process_vtime(struct task_struct *tsk)
+void account_process_tick(struct task_struct *tsk, int user_tick)
{
- cputime_t utime;
+ cputime_t utime, utimescaled;
utime = get_paca()->user_time;
get_paca()->user_time = 0;
account_user_time(tsk, utime);
-}
-static void account_process_time(struct pt_regs *regs)
-{
- int cpu = smp_processor_id();
-
- account_process_vtime(current);
- run_local_timers();
- if (rcu_pending(cpu))
- rcu_check_callbacks(cpu, user_mode(regs));
- scheduler_tick();
- run_posix_cpu_timers(current);
+ /* Estimate the scaled utime by scaling the real utime based
+ * on the last spurr to purr ratio */
+ utimescaled = utime * get_paca()->spurrdelta / get_paca()->purrdelta;
+ get_paca()->spurrdelta = get_paca()->purrdelta = 0;
+ account_user_time_scaled(tsk, utimescaled);
}
/*
@@ -266,6 +281,7 @@ struct cpu_purr_data {
int initialized; /* thread is running */
u64 tb; /* last TB value read */
u64 purr; /* last PURR value read */
+ u64 spurr; /* last SPURR value read */
};
/*
@@ -347,7 +363,6 @@ static void snapshot_purr(void)
#else /* ! CONFIG_VIRT_CPU_ACCOUNTING */
#define calc_cputime_factors()
-#define account_process_time(regs) update_process_times(user_mode(regs))
#define calculate_steal_time() do { } while (0)
#endif
@@ -558,7 +573,7 @@ void timer_interrupt(struct pt_regs * regs)
/* not time for this event yet */
now = per_cpu(decrementer_next_tb, cpu) - now;
if (now <= DECREMENTER_MAX)
- set_dec((unsigned int)now - 1);
+ set_dec((int)now);
return;
}
old_regs = set_irq_regs(regs);
@@ -571,20 +586,8 @@ void timer_interrupt(struct pt_regs * regs)
get_lppaca()->int_dword.fields.decr_int = 0;
#endif
- /*
- * We cannot disable the decrementer, so in the period
- * between this cpu's being marked offline in cpu_online_map
- * and calling stop-self, it is taking timer interrupts.
- * Avoid calling into the scheduler rebalancing code if this
- * is the case.
- */
- if (!cpu_is_offline(cpu))
- account_process_time(regs);
-
if (evt->event_handler)
evt->event_handler(evt);
- else
- evt->set_next_event(DECREMENTER_MAX, evt);
#ifdef CONFIG_PPC_ISERIES
if (firmware_has_feature(FW_FEATURE_ISERIES) && hvlpevent_is_pending())
@@ -808,9 +811,6 @@ static int decrementer_set_next_event(unsigned long evt,
struct clock_event_device *dev)
{
__get_cpu_var(decrementer_next_tb) = get_tb_or_rtc() + evt;
- /* The decrementer interrupts on the 0 -> -1 transition */
- if (evt)
- --evt;
set_dec(evt);
return 0;
}
@@ -829,7 +829,7 @@ static void register_decrementer_clockevent(int cpu)
*dec = decrementer_clockevent;
dec->cpumask = cpumask_of_cpu(cpu);
- printk(KERN_ERR "clockevent: %s mult[%lx] shift[%d] cpu[%d]\n",
+ printk(KERN_DEBUG "clockevent: %s mult[%lx] shift[%d] cpu[%d]\n",
dec->name, dec->mult, dec->shift, cpu);
clockevents_register_device(dec);
@@ -843,7 +843,8 @@ void init_decrementer_clockevent(void)
decrementer_clockevent.shift);
decrementer_clockevent.max_delta_ns =
clockevent_delta2ns(DECREMENTER_MAX, &decrementer_clockevent);
- decrementer_clockevent.min_delta_ns = 1000;
+ decrementer_clockevent.min_delta_ns =
+ clockevent_delta2ns(2, &decrementer_clockevent);
register_decrementer_clockevent(cpu);
}
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index bf9e39c6e296..59c464e26f38 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -201,7 +201,7 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr)
* generate the same exception over and over again and we get
* nowhere. Better to kill it and let the kernel panic.
*/
- if (is_init(current)) {
+ if (is_global_init(current)) {
__sighandler_t handler;
spin_lock_irq(&current->sighand->siglock);
@@ -881,7 +881,7 @@ void nonrecoverable_exception(struct pt_regs *regs)
void trace_syscall(struct pt_regs *regs)
{
printk("Task: %p(%d), PC: %08lX/%08lX, Syscall: %3ld, Result: %s%ld %s\n",
- current, current->pid, regs->nip, regs->link, regs->gpr[0],
+ current, task_pid_nr(current), regs->nip, regs->link, regs->gpr[0],
regs->ccr&0x10000000?"Error=":"", regs->gpr[3], print_tainted());
}
diff --git a/arch/powerpc/kernel/vdso32/vdso32.lds.S b/arch/powerpc/kernel/vdso32/vdso32.lds.S
index 26e138c4ce17..9352ab5200e5 100644
--- a/arch/powerpc/kernel/vdso32/vdso32.lds.S
+++ b/arch/powerpc/kernel/vdso32/vdso32.lds.S
@@ -1,130 +1,147 @@
-
/*
* This is the infamous ld script for the 32 bits vdso
* library
*/
#include <asm/vdso.h>
-/* Default link addresses for the vDSOs */
OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc")
OUTPUT_ARCH(powerpc:common)
ENTRY(_start)
SECTIONS
{
- . = VDSO32_LBASE + SIZEOF_HEADERS;
- .hash : { *(.hash) } :text
- .gnu.hash : { *(.gnu.hash) }
- .dynsym : { *(.dynsym) }
- .dynstr : { *(.dynstr) }
- .gnu.version : { *(.gnu.version) }
- .gnu.version_d : { *(.gnu.version_d) }
- .gnu.version_r : { *(.gnu.version_r) }
-
- .note : { *(.note.*) } :text :note
-
- . = ALIGN (16);
- .text :
- {
- *(.text .stub .text.* .gnu.linkonce.t.*)
- }
- PROVIDE (__etext = .);
- PROVIDE (_etext = .);
- PROVIDE (etext = .);
-
- . = ALIGN(8);
- __ftr_fixup : {
- *(__ftr_fixup)
- }
+ . = VDSO32_LBASE + SIZEOF_HEADERS;
+
+ .hash : { *(.hash) } :text
+ .gnu.hash : { *(.gnu.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+
+ .note : { *(.note.*) } :text :note
+
+ . = ALIGN(16);
+ .text : {
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ }
+ PROVIDE(__etext = .);
+ PROVIDE(_etext = .);
+ PROVIDE(etext = .);
+
+ . = ALIGN(8);
+ __ftr_fixup : { *(__ftr_fixup) }
#ifdef CONFIG_PPC64
- . = ALIGN(8);
- __fw_ftr_fixup : {
- *(__fw_ftr_fixup)
- }
+ . = ALIGN(8);
+ __fw_ftr_fixup : { *(__fw_ftr_fixup) }
#endif
- /* Other stuff is appended to the text segment: */
- .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
- .rodata1 : { *(.rodata1) }
-
- .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr
- .eh_frame : { KEEP (*(.eh_frame)) } :text
- .gcc_except_table : { *(.gcc_except_table) }
- .fixup : { *(.fixup) }
-
- .dynamic : { *(.dynamic) } :text :dynamic
- .got : { *(.got) }
- .plt : { *(.plt) }
-
- _end = .;
- __end = .;
- PROVIDE (end = .);
-
-
- /* Stabs debugging sections are here too
- */
- .stab 0 : { *(.stab) }
- .stabstr 0 : { *(.stabstr) }
- .stab.excl 0 : { *(.stab.excl) }
- .stab.exclstr 0 : { *(.stab.exclstr) }
- .stab.index 0 : { *(.stab.index) }
- .stab.indexstr 0 : { *(.stab.indexstr) }
- .comment 0 : { *(.comment) }
- .debug 0 : { *(.debug) }
- .line 0 : { *(.line) }
-
- .debug_srcinfo 0 : { *(.debug_srcinfo) }
- .debug_sfnames 0 : { *(.debug_sfnames) }
-
- .debug_aranges 0 : { *(.debug_aranges) }
- .debug_pubnames 0 : { *(.debug_pubnames) }
-
- .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
- .debug_abbrev 0 : { *(.debug_abbrev) }
- .debug_line 0 : { *(.debug_line) }
- .debug_frame 0 : { *(.debug_frame) }
- .debug_str 0 : { *(.debug_str) }
- .debug_loc 0 : { *(.debug_loc) }
- .debug_macinfo 0 : { *(.debug_macinfo) }
-
- .debug_weaknames 0 : { *(.debug_weaknames) }
- .debug_funcnames 0 : { *(.debug_funcnames) }
- .debug_typenames 0 : { *(.debug_typenames) }
- .debug_varnames 0 : { *(.debug_varnames) }
-
- /DISCARD/ : { *(.note.GNU-stack) }
- /DISCARD/ : { *(.data .data.* .gnu.linkonce.d.* .sdata*) }
- /DISCARD/ : { *(.bss .sbss .dynbss .dynsbss) }
+ /*
+ * Other stuff is appended to the text segment:
+ */
+ .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+ .rodata1 : { *(.rodata1) }
+
+ .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr
+ .eh_frame : { KEEP (*(.eh_frame)) } :text
+ .gcc_except_table : { *(.gcc_except_table) }
+ .fixup : { *(.fixup) }
+
+ .dynamic : { *(.dynamic) } :text :dynamic
+ .got : { *(.got) }
+ .plt : { *(.plt) }
+
+ _end = .;
+ __end = .;
+ PROVIDE(end = .);
+
+ /*
+ * Stabs debugging sections are here too.
+ */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+
+ /*
+ * DWARF debug sections.
+ * Symbols in the DWARF debugging sections are relative to the beginning
+ * of the section so we begin them at 0.
+ */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+
+ /DISCARD/ : {
+ *(.note.GNU-stack)
+ *(.data .data.* .gnu.linkonce.d.* .sdata*)
+ *(.bss .sbss .dynbss .dynsbss)
+ }
}
+/*
+ * Very old versions of ld do not recognize this name token; use the constant.
+ */
+#define PT_GNU_EH_FRAME 0x6474e550
+/*
+ * We must supply the ELF program headers explicitly to get just one
+ * PT_LOAD segment, and set the flags explicitly to make segments read-only.
+ */
PHDRS
{
- text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */
- note PT_NOTE FLAGS(4); /* PF_R */
- dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
- eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */
+ text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */
+ dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
+ note PT_NOTE FLAGS(4); /* PF_R */
+ eh_frame_hdr PT_GNU_EH_FRAME;
}
-
/*
* This controls what symbols we export from the DSO.
*/
VERSION
{
- VDSO_VERSION_STRING {
- global:
- __kernel_datapage_offset; /* Has to be there for the kernel to find */
- __kernel_get_syscall_map;
- __kernel_gettimeofday;
- __kernel_clock_gettime;
- __kernel_clock_getres;
- __kernel_get_tbfreq;
- __kernel_sync_dicache;
- __kernel_sync_dicache_p5;
- __kernel_sigtramp32;
- __kernel_sigtramp_rt32;
- local: *;
- };
+ VDSO_VERSION_STRING {
+ global:
+ /*
+ * Has to be there for the kernel to find
+ */
+ __kernel_datapage_offset;
+
+ __kernel_get_syscall_map;
+ __kernel_gettimeofday;
+ __kernel_clock_gettime;
+ __kernel_clock_getres;
+ __kernel_get_tbfreq;
+ __kernel_sync_dicache;
+ __kernel_sync_dicache_p5;
+ __kernel_sigtramp32;
+ __kernel_sigtramp_rt32;
+
+ local: *;
+ };
}
diff --git a/arch/powerpc/kernel/vdso64/sigtramp.S b/arch/powerpc/kernel/vdso64/sigtramp.S
index 17a83fa6dc52..59eb59bb4082 100644
--- a/arch/powerpc/kernel/vdso64/sigtramp.S
+++ b/arch/powerpc/kernel/vdso64/sigtramp.S
@@ -134,13 +134,16 @@ V_FUNCTION_END(__kernel_sigtramp_rt64)
9:
/* This is where the pt_regs pointer can be found on the stack. */
-#define PTREGS 128+168+56
+#define PTREGS 128+168+56
/* Size of regs. */
-#define RSIZE 8
+#define RSIZE 8
+
+/* Size of CR reg in DWARF unwind info. */
+#define CRSIZE 4
/* This is the offset of the VMX reg pointer. */
-#define VREGS 48*RSIZE+33*8
+#define VREGS 48*RSIZE+33*8
/* Describe where general purpose regs are saved. */
#define EH_FRAME_GEN \
@@ -178,7 +181,7 @@ V_FUNCTION_END(__kernel_sigtramp_rt64)
rsave (31, 31*RSIZE); \
rsave (67, 32*RSIZE); /* ap, used as temp for nip */ \
rsave (65, 36*RSIZE); /* lr */ \
- rsave (70, 38*RSIZE) /* cr */
+ rsave (70, 38*RSIZE + (RSIZE - CRSIZE)) /* cr */
/* Describe where the FP regs are saved. */
#define EH_FRAME_FP \
diff --git a/arch/powerpc/kernel/vdso64/vdso64.lds.S b/arch/powerpc/kernel/vdso64/vdso64.lds.S
index 2d70f35d50b5..932b3fdb34b9 100644
--- a/arch/powerpc/kernel/vdso64/vdso64.lds.S
+++ b/arch/powerpc/kernel/vdso64/vdso64.lds.S
@@ -10,100 +10,114 @@ ENTRY(_start)
SECTIONS
{
- . = VDSO64_LBASE + SIZEOF_HEADERS;
- .hash : { *(.hash) } :text
- .gnu.hash : { *(.gnu.hash) }
- .dynsym : { *(.dynsym) }
- .dynstr : { *(.dynstr) }
- .gnu.version : { *(.gnu.version) }
- .gnu.version_d : { *(.gnu.version_d) }
- .gnu.version_r : { *(.gnu.version_r) }
-
- .note : { *(.note.*) } :text :note
-
- . = ALIGN (16);
- .text :
- {
- *(.text .stub .text.* .gnu.linkonce.t.*)
- *(.sfpr .glink)
- } :text
- PROVIDE (__etext = .);
- PROVIDE (_etext = .);
- PROVIDE (etext = .);
-
- . = ALIGN(8);
- __ftr_fixup : {
- *(__ftr_fixup)
- }
-
- . = ALIGN(8);
- __fw_ftr_fixup : {
- *(__fw_ftr_fixup)
- }
-
- /* Other stuff is appended to the text segment: */
- .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
- .rodata1 : { *(.rodata1) }
- .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr
- .eh_frame : { KEEP (*(.eh_frame)) } :text
- .gcc_except_table : { *(.gcc_except_table) }
-
- .opd ALIGN(8) : { KEEP (*(.opd)) }
- .got ALIGN(8) : { *(.got .toc) }
- .rela.dyn ALIGN(8) : { *(.rela.dyn) }
-
- .dynamic : { *(.dynamic) } :text :dynamic
-
- _end = .;
- PROVIDE (end = .);
-
- /* Stabs debugging sections are here too
- */
- .stab 0 : { *(.stab) }
- .stabstr 0 : { *(.stabstr) }
- .stab.excl 0 : { *(.stab.excl) }
- .stab.exclstr 0 : { *(.stab.exclstr) }
- .stab.index 0 : { *(.stab.index) }
- .stab.indexstr 0 : { *(.stab.indexstr) }
- .comment 0 : { *(.comment) }
- /* DWARF debug sectio/ns.
- Symbols in the DWARF debugging sections are relative to the beginning
- of the section so we begin them at 0. */
- /* DWARF 1 */
- .debug 0 : { *(.debug) }
- .line 0 : { *(.line) }
- /* GNU DWARF 1 extensions */
- .debug_srcinfo 0 : { *(.debug_srcinfo) }
- .debug_sfnames 0 : { *(.debug_sfnames) }
- /* DWARF 1.1 and DWARF 2 */
- .debug_aranges 0 : { *(.debug_aranges) }
- .debug_pubnames 0 : { *(.debug_pubnames) }
- /* DWARF 2 */
- .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
- .debug_abbrev 0 : { *(.debug_abbrev) }
- .debug_line 0 : { *(.debug_line) }
- .debug_frame 0 : { *(.debug_frame) }
- .debug_str 0 : { *(.debug_str) }
- .debug_loc 0 : { *(.debug_loc) }
- .debug_macinfo 0 : { *(.debug_macinfo) }
- /* SGI/MIPS DWARF 2 extensions */
- .debug_weaknames 0 : { *(.debug_weaknames) }
- .debug_funcnames 0 : { *(.debug_funcnames) }
- .debug_typenames 0 : { *(.debug_typenames) }
- .debug_varnames 0 : { *(.debug_varnames) }
-
- /DISCARD/ : { *(.note.GNU-stack) }
- /DISCARD/ : { *(.branch_lt) }
- /DISCARD/ : { *(.data .data.* .gnu.linkonce.d.*) }
- /DISCARD/ : { *(.bss .sbss .dynbss .dynsbss) }
+ . = VDSO64_LBASE + SIZEOF_HEADERS;
+
+ .hash : { *(.hash) } :text
+ .gnu.hash : { *(.gnu.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+
+ .note : { *(.note.*) } :text :note
+
+ . = ALIGN(16);
+ .text : {
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ *(.sfpr .glink)
+ } :text
+ PROVIDE(__etext = .);
+ PROVIDE(_etext = .);
+ PROVIDE(etext = .);
+
+ . = ALIGN(8);
+ __ftr_fixup : { *(__ftr_fixup) }
+
+ . = ALIGN(8);
+ __fw_ftr_fixup : { *(__fw_ftr_fixup) }
+
+ /*
+ * Other stuff is appended to the text segment:
+ */
+ .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+ .rodata1 : { *(.rodata1) }
+
+ .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr
+ .eh_frame : { KEEP (*(.eh_frame)) } :text
+ .gcc_except_table : { *(.gcc_except_table) }
+
+ .opd ALIGN(8) : { KEEP (*(.opd)) }
+ .got ALIGN(8) : { *(.got .toc) }
+ .rela.dyn ALIGN(8) : { *(.rela.dyn) }
+
+ .dynamic : { *(.dynamic) } :text :dynamic
+
+ _end = .;
+ PROVIDE(end = .);
+
+ /*
+ * Stabs debugging sections are here too.
+ */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+
+ /*
+ * DWARF debug sections.
+ * Symbols in the DWARF debugging sections are relative to the beginning
+ * of the section so we begin them at 0.
+ */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+
+ /DISCARD/ : {
+ *(.note.GNU-stack)
+ *(.branch_lt)
+ *(.data .data.* .gnu.linkonce.d.* .sdata*)
+ *(.bss .sbss .dynbss .dynsbss)
+ }
}
+/*
+ * Very old versions of ld do not recognize this name token; use the constant.
+ */
+#define PT_GNU_EH_FRAME 0x6474e550
+
+/*
+ * We must supply the ELF program headers explicitly to get just one
+ * PT_LOAD segment, and set the flags explicitly to make segments read-only.
+ */
PHDRS
{
- text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */
- note PT_NOTE FLAGS(4); /* PF_R */
- dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
- eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */
+ text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */
+ dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
+ note PT_NOTE FLAGS(4); /* PF_R */
+ eh_frame_hdr PT_GNU_EH_FRAME;
}
/*
@@ -111,17 +125,22 @@ PHDRS
*/
VERSION
{
- VDSO_VERSION_STRING {
- global:
- __kernel_datapage_offset; /* Has to be there for the kernel to find */
- __kernel_get_syscall_map;
- __kernel_gettimeofday;
- __kernel_clock_gettime;
- __kernel_clock_getres;
- __kernel_get_tbfreq;
- __kernel_sync_dicache;
- __kernel_sync_dicache_p5;
- __kernel_sigtramp_rt64;
- local: *;
- };
+ VDSO_VERSION_STRING {
+ global:
+ /*
+ * Has to be there for the kernel to find
+ */
+ __kernel_datapage_offset;
+
+ __kernel_get_syscall_map;
+ __kernel_gettimeofday;
+ __kernel_clock_gettime;
+ __kernel_clock_getres;
+ __kernel_get_tbfreq;
+ __kernel_sync_dicache;
+ __kernel_sync_dicache_p5;
+ __kernel_sigtramp_rt64;
+
+ local: *;
+ };
}
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 823a8cbd60b5..f66fa5d966b0 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -37,11 +37,10 @@ SECTIONS
ALIGN_FUNCTION();
*(.text.head)
_text = .;
- TEXT_TEXT
+ *(.text .fixup .text.init.refok .exit.text.refok)
SCHED_TEXT
LOCK_TEXT
KPROBES_TEXT
- *(.fixup)
#ifdef CONFIG_PPC32
*(.got1)
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index 65d492e316a6..4bb023f4c869 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -14,7 +14,6 @@ endif
obj-$(CONFIG_PPC64) += copypage_64.o copyuser_64.o \
memcpy_64.o usercopy_64.o mem_64.o string.o
-obj-$(CONFIG_QUICC_ENGINE) += rheap.o
obj-$(CONFIG_XMON) += sstep.o
obj-$(CONFIG_KPROBES) += sstep.o
obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-noncoherent.o
@@ -23,6 +22,4 @@ ifeq ($(CONFIG_PPC64),y)
obj-$(CONFIG_SMP) += locks.o
endif
-# Temporary hack until we have migrated to asm-powerpc
-obj-$(CONFIG_8xx) += rheap.o
-obj-$(CONFIG_CPM2) += rheap.o
+obj-$(CONFIG_PPC_LIB_RHEAP) += rheap.o
diff --git a/arch/powerpc/lib/rheap.c b/arch/powerpc/lib/rheap.c
index ada5b42dd231..22c3b4f53de7 100644
--- a/arch/powerpc/lib/rheap.c
+++ b/arch/powerpc/lib/rheap.c
@@ -15,6 +15,7 @@
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/mm.h>
#include <linux/err.h>
#include <linux/slab.h>
@@ -275,6 +276,7 @@ rh_info_t *rh_create(unsigned int alignment)
return info;
}
+EXPORT_SYMBOL_GPL(rh_create);
/*
* Destroy a dynamically created remote heap. Deallocate only if the areas
@@ -288,6 +290,7 @@ void rh_destroy(rh_info_t * info)
if ((info->flags & RHIF_STATIC_INFO) == 0)
kfree(info);
}
+EXPORT_SYMBOL_GPL(rh_destroy);
/*
* Initialize in place a remote heap info block. This is needed to support
@@ -320,6 +323,7 @@ void rh_init(rh_info_t * info, unsigned int alignment, int max_blocks,
for (i = 0, blk = block; i < max_blocks; i++, blk++)
list_add(&blk->list, &info->empty_list);
}
+EXPORT_SYMBOL_GPL(rh_init);
/* Attach a free memory region, coalesces regions if adjuscent */
int rh_attach_region(rh_info_t * info, unsigned long start, int size)
@@ -360,6 +364,7 @@ int rh_attach_region(rh_info_t * info, unsigned long start, int size)
return 0;
}
+EXPORT_SYMBOL_GPL(rh_attach_region);
/* Detatch given address range, splits free block if needed. */
unsigned long rh_detach_region(rh_info_t * info, unsigned long start, int size)
@@ -428,6 +433,7 @@ unsigned long rh_detach_region(rh_info_t * info, unsigned long start, int size)
return s;
}
+EXPORT_SYMBOL_GPL(rh_detach_region);
/* Allocate a block of memory at the specified alignment. The value returned
* is an offset into the buffer initialized by rh_init(), or a negative number
@@ -502,6 +508,7 @@ unsigned long rh_alloc_align(rh_info_t * info, int size, int alignment, const ch
return start;
}
+EXPORT_SYMBOL_GPL(rh_alloc_align);
/* Allocate a block of memory at the default alignment. The value returned is
* an offset into the buffer initialized by rh_init(), or a negative number if
@@ -511,6 +518,7 @@ unsigned long rh_alloc(rh_info_t * info, int size, const char *owner)
{
return rh_alloc_align(info, size, info->alignment, owner);
}
+EXPORT_SYMBOL_GPL(rh_alloc);
/* Allocate a block of memory at the given offset, rounded up to the default
* alignment. The value returned is an offset into the buffer initialized by
@@ -594,6 +602,7 @@ unsigned long rh_alloc_fixed(rh_info_t * info, unsigned long start, int size, co
return start;
}
+EXPORT_SYMBOL_GPL(rh_alloc_fixed);
/* Deallocate the memory previously allocated by one of the rh_alloc functions.
* The return value is the size of the deallocated block, or a negative number
@@ -626,6 +635,7 @@ int rh_free(rh_info_t * info, unsigned long start)
return size;
}
+EXPORT_SYMBOL_GPL(rh_free);
int rh_get_stats(rh_info_t * info, int what, int max_stats, rh_stats_t * stats)
{
@@ -663,6 +673,7 @@ int rh_get_stats(rh_info_t * info, int what, int max_stats, rh_stats_t * stats)
return nr;
}
+EXPORT_SYMBOL_GPL(rh_get_stats);
int rh_set_owner(rh_info_t * info, unsigned long start, const char *owner)
{
@@ -687,6 +698,7 @@ int rh_set_owner(rh_info_t * info, unsigned long start, const char *owner)
return size;
}
+EXPORT_SYMBOL_GPL(rh_set_owner);
void rh_dump(rh_info_t * info)
{
@@ -722,6 +734,7 @@ void rh_dump(rh_info_t * info)
st[i].size, st[i].owner != NULL ? st[i].owner : "");
printk(KERN_INFO "\n");
}
+EXPORT_SYMBOL_GPL(rh_dump);
void rh_dump_blk(rh_info_t * info, rh_block_t * blk)
{
@@ -729,3 +742,5 @@ void rh_dump_blk(rh_info_t * info, rh_block_t * blk)
"blk @0x%p: 0x%lx-0x%lx (%u)\n",
blk, blk->start, blk->start + blk->size, blk->size);
}
+EXPORT_SYMBOL_GPL(rh_dump_blk);
+
diff --git a/arch/powerpc/math-emu/math.c b/arch/powerpc/math-emu/math.c
index 69058b2873de..381306bb1590 100644
--- a/arch/powerpc/math-emu/math.c
+++ b/arch/powerpc/math-emu/math.c
@@ -407,11 +407,16 @@ do_mathemu(struct pt_regs *regs)
case XE:
idx = (insn >> 16) & 0x1f;
- if (!idx)
- goto illegal;
-
op0 = (void *)&current->thread.fpr[(insn >> 21) & 0x1f];
- op1 = (void *)(regs->gpr[idx] + regs->gpr[(insn >> 11) & 0x1f]);
+ if (!idx) {
+ if (((insn >> 1) & 0x3ff) == STFIWX)
+ op1 = (void *)(regs->gpr[(insn >> 11) & 0x1f]);
+ else
+ goto illegal;
+ } else {
+ op1 = (void *)(regs->gpr[idx] + regs->gpr[(insn >> 11) & 0x1f]);
+ }
+
break;
case XEU:
diff --git a/arch/powerpc/mm/40x_mmu.c b/arch/powerpc/mm/40x_mmu.c
index e067df836be2..3899ea97fbdf 100644
--- a/arch/powerpc/mm/40x_mmu.c
+++ b/arch/powerpc/mm/40x_mmu.c
@@ -98,13 +98,12 @@ unsigned long __init mmu_mapin_ram(void)
v = KERNELBASE;
p = PPC_MEMSTART;
- s = 0;
+ s = total_lowmem;
- if (__map_without_ltlbs) {
- return s;
- }
+ if (__map_without_ltlbs)
+ return 0;
- while (s <= (total_lowmem - LARGE_PAGE_SIZE_16M)) {
+ while (s >= LARGE_PAGE_SIZE_16M) {
pmd_t *pmdp;
unsigned long val = p | _PMD_SIZE_16M | _PAGE_HWEXEC | _PAGE_HWWRITE;
@@ -116,10 +115,10 @@ unsigned long __init mmu_mapin_ram(void)
v += LARGE_PAGE_SIZE_16M;
p += LARGE_PAGE_SIZE_16M;
- s += LARGE_PAGE_SIZE_16M;
+ s -= LARGE_PAGE_SIZE_16M;
}
- while (s <= (total_lowmem - LARGE_PAGE_SIZE_4M)) {
+ while (s >= LARGE_PAGE_SIZE_4M) {
pmd_t *pmdp;
unsigned long val = p | _PMD_SIZE_4M | _PAGE_HWEXEC | _PAGE_HWWRITE;
@@ -128,8 +127,8 @@ unsigned long __init mmu_mapin_ram(void)
v += LARGE_PAGE_SIZE_4M;
p += LARGE_PAGE_SIZE_4M;
- s += LARGE_PAGE_SIZE_4M;
+ s -= LARGE_PAGE_SIZE_4M;
}
- return s;
+ return total_lowmem - s;
}
diff --git a/arch/powerpc/mm/44x_mmu.c b/arch/powerpc/mm/44x_mmu.c
index c3df50476539..04dc08798d3d 100644
--- a/arch/powerpc/mm/44x_mmu.c
+++ b/arch/powerpc/mm/44x_mmu.c
@@ -35,6 +35,7 @@
*/
unsigned int tlb_44x_index; /* = 0 */
unsigned int tlb_44x_hwater = PPC44x_TLB_SIZE - 1 - PPC44x_EARLY_TLBS;
+int icache_44x_need_flush;
/*
* "Pins" a 256MB TLB entry in AS0 for kernel lowmem
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index ab3546c5ac3a..8135da06e0a4 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -309,7 +309,7 @@ good_area:
set_bit(PG_arch_1, &page->flags);
}
pte_update(ptep, 0, _PAGE_HWEXEC);
- _tlbie(address);
+ _tlbie(address, mm->context.id);
pte_unmap_unlock(ptep, ptl);
up_read(&mm->mmap_sem);
return 0;
@@ -375,7 +375,7 @@ bad_area_nosemaphore:
*/
out_of_memory:
up_read(&mm->mmap_sem);
- if (is_init(current)) {
+ if (is_global_init(current)) {
yield();
down_read(&mm->mmap_sem);
goto survive;
diff --git a/arch/powerpc/mm/hash_low_64.S b/arch/powerpc/mm/hash_low_64.S
index ad253b959030..e935edd6b72b 100644
--- a/arch/powerpc/mm/hash_low_64.S
+++ b/arch/powerpc/mm/hash_low_64.S
@@ -331,7 +331,7 @@ htab_pte_insert_failure:
*****************************************************************************/
/* _hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,
- * pte_t *ptep, unsigned long trap, int local)
+ * pte_t *ptep, unsigned long trap, int local, int ssize)
*/
/*
@@ -557,7 +557,8 @@ htab_inval_old_hpte:
mr r4,r31 /* PTE.pte */
li r5,0 /* PTE.hidx */
li r6,MMU_PAGE_64K /* psize */
- ld r7,STK_PARM(r8)(r1) /* local */
+ ld r7,STK_PARM(r9)(r1) /* ssize */
+ ld r8,STK_PARM(r8)(r1) /* local */
bl .flush_hash_page
b htab_insert_pte
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 611ad084b7e7..f09730bf3a33 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -51,6 +51,7 @@
#include <asm/cputable.h>
#include <asm/sections.h>
#include <asm/spu.h>
+#include <asm/udbg.h>
#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
@@ -209,9 +210,10 @@ static int __init htab_dt_scan_seg_sizes(unsigned long node,
if (prop[0] == 40) {
DBG("1T segment support detected\n");
cur_cpu_spec->cpu_features |= CPU_FTR_1T_SEGMENT;
+ return 1;
}
- return 1;
}
+ cur_cpu_spec->cpu_features &= ~CPU_FTR_NO_SLBIE_B;
return 0;
}
@@ -790,8 +792,7 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
}
if (user_region) {
if (psize != get_paca()->context.user_psize) {
- get_paca()->context.user_psize =
- mm->context.user_psize;
+ get_paca()->context = mm->context;
slb_flush_and_rebolt();
}
} else if (get_paca()->vmalloc_sllp !=
@@ -884,6 +885,9 @@ void hash_preload(struct mm_struct *mm, unsigned long ea,
local_irq_restore(flags);
}
+/* WARNING: This is called from hash_low_64.S, if you change this prototype,
+ * do not forget to update the assembly call site !
+ */
void flush_hash_page(unsigned long va, real_pte_t pte, int psize, int ssize,
int local)
{
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index 08f0d9ff7712..71efb38d599b 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -526,7 +526,7 @@ repeat:
return err;
}
-static void zero_ctor(void *addr, struct kmem_cache *cache, unsigned long flags)
+static void zero_ctor(struct kmem_cache *cache, void *addr)
{
memset(addr, 0, kmem_cache_size(cache));
}
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index fa90f6561b9f..c0f5cff77035 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -19,8 +19,6 @@
*
*/
-#undef DEBUG
-
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/kernel.h>
@@ -66,12 +64,6 @@
#include "mmu_decl.h"
-#ifdef DEBUG
-#define DBG(fmt...) printk(fmt)
-#else
-#define DBG(fmt...)
-#endif
-
#if PGTABLE_RANGE > USER_VSID_RANGE
#warning Limited user VSID range means pagetable space is wasted
#endif
@@ -142,7 +134,7 @@ static int __init setup_kcore(void)
module_init(setup_kcore);
#endif
-static void zero_ctor(void *addr, struct kmem_cache *cache, unsigned long flags)
+static void zero_ctor(struct kmem_cache *cache, void *addr)
{
memset(addr, 0, kmem_cache_size(cache));
}
@@ -175,11 +167,79 @@ void pgtable_cache_init(void)
int size = pgtable_cache_size[i];
const char *name = pgtable_cache_name[i];
- DBG("Allocating page table cache %s (#%d) "
- "for size: %08x...\n", name, i, size);
+ pr_debug("Allocating page table cache %s (#%d) "
+ "for size: %08x...\n", name, i, size);
pgtable_cache[i] = kmem_cache_create(name,
size, size,
SLAB_PANIC,
zero_ctor);
}
}
+
+#ifdef CONFIG_SPARSEMEM_VMEMMAP
+/*
+ * Given an address within the vmemmap, determine the pfn of the page that
+ * represents the start of the section it is within. Note that we have to
+ * do this by hand as the proffered address may not be correctly aligned.
+ * Subtraction of non-aligned pointers produces undefined results.
+ */
+unsigned long __meminit vmemmap_section_start(unsigned long page)
+{
+ unsigned long offset = page - ((unsigned long)(vmemmap));
+
+ /* Return the pfn of the start of the section. */
+ return (offset / sizeof(struct page)) & PAGE_SECTION_MASK;
+}
+
+/*
+ * Check if this vmemmap page is already initialised. If any section
+ * which overlaps this vmemmap page is initialised then this page is
+ * initialised already.
+ */
+int __meminit vmemmap_populated(unsigned long start, int page_size)
+{
+ unsigned long end = start + page_size;
+
+ for (; start < end; start += (PAGES_PER_SECTION * sizeof(struct page)))
+ if (pfn_valid(vmemmap_section_start(start)))
+ return 1;
+
+ return 0;
+}
+
+int __meminit vmemmap_populate(struct page *start_page,
+ unsigned long nr_pages, int node)
+{
+ unsigned long mode_rw;
+ unsigned long start = (unsigned long)start_page;
+ unsigned long end = (unsigned long)(start_page + nr_pages);
+ unsigned long page_size = 1 << mmu_psize_defs[mmu_linear_psize].shift;
+
+ mode_rw = _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX;
+
+ /* Align to the page size of the linear mapping. */
+ start = _ALIGN_DOWN(start, page_size);
+
+ for (; start < end; start += page_size) {
+ int mapped;
+ void *p;
+
+ if (vmemmap_populated(start, page_size))
+ continue;
+
+ p = vmemmap_alloc_block(page_size, node);
+ if (!p)
+ return -ENOMEM;
+
+ pr_debug("vmemmap %08lx allocated at %p, physical %08lx.\n",
+ start, p, __pa(p));
+
+ mapped = htab_bolt_mapping(start, start + page_size,
+ __pa(p), mode_rw, mmu_linear_psize,
+ mmu_kernel_ssize);
+ BUG_ON(mapped < 0);
+ }
+
+ return 0;
+}
+#endif
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index 32dcfc9b0082..81eb96ec13b2 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -129,51 +129,6 @@ int __devinit arch_add_memory(int nid, u64 start, u64 size)
return __add_pages(zone, start_pfn, nr_pages);
}
-/*
- * First pass at this code will check to determine if the remove
- * request is within the RMO. Do not allow removal within the RMO.
- */
-int __devinit remove_memory(u64 start, u64 size)
-{
- struct zone *zone;
- unsigned long start_pfn, end_pfn, nr_pages;
-
- start_pfn = start >> PAGE_SHIFT;
- nr_pages = size >> PAGE_SHIFT;
- end_pfn = start_pfn + nr_pages;
-
- printk("%s(): Attempting to remove memoy in range "
- "%lx to %lx\n", __func__, start, start+size);
- /*
- * check for range within RMO
- */
- zone = page_zone(pfn_to_page(start_pfn));
-
- printk("%s(): memory will be removed from "
- "the %s zone\n", __func__, zone->name);
-
- /*
- * not handling removing memory ranges that
- * overlap multiple zones yet
- */
- if (end_pfn > (zone->zone_start_pfn + zone->spanned_pages))
- goto overlap;
-
- /* make sure it is NOT in RMO */
- if ((start < lmb.rmo_size) || ((start+size) < lmb.rmo_size)) {
- printk("%s(): range to be removed must NOT be in RMO!\n",
- __func__);
- goto in_rmo;
- }
-
- return __remove_pages(zone, start_pfn, nr_pages);
-
-overlap:
- printk("%s(): memory range to be removed overlaps "
- "multiple zones!!!\n", __func__);
-in_rmo:
- return -1;
-}
#endif /* CONFIG_MEMORY_HOTPLUG */
void show_mem(void)
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h
index c94a64fd3c01..eb3a732e91db 100644
--- a/arch/powerpc/mm/mmu_decl.h
+++ b/arch/powerpc/mm/mmu_decl.h
@@ -61,12 +61,12 @@ extern unsigned long total_lowmem;
#define mmu_mapin_ram() (0UL)
#elif defined(CONFIG_4xx)
-#define flush_HPTE(X, va, pg) _tlbie(va)
+#define flush_HPTE(pid, va, pg) _tlbie(va, pid)
extern void MMU_init_hw(void);
extern unsigned long mmu_mapin_ram(void);
#elif defined(CONFIG_FSL_BOOKE)
-#define flush_HPTE(X, va, pg) _tlbie(va)
+#define flush_HPTE(pid, va, pg) _tlbie(va, pid)
extern void MMU_init_hw(void);
extern unsigned long mmu_mapin_ram(void);
extern void adjust_total_lowmem(void);
diff --git a/arch/powerpc/mm/slb.c b/arch/powerpc/mm/slb.c
index 6c164cec9d2c..27922dff8b94 100644
--- a/arch/powerpc/mm/slb.c
+++ b/arch/powerpc/mm/slb.c
@@ -25,6 +25,7 @@
#include <asm/smp.h>
#include <asm/firmware.h>
#include <linux/compiler.h>
+#include <asm/udbg.h>
#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
@@ -148,6 +149,35 @@ void slb_vmalloc_update(void)
slb_flush_and_rebolt();
}
+/* Helper function to compare esids. There are four cases to handle.
+ * 1. The system is not 1T segment size capable. Use the GET_ESID compare.
+ * 2. The system is 1T capable, both addresses are < 1T, use the GET_ESID compare.
+ * 3. The system is 1T capable, only one of the two addresses is > 1T. This is not a match.
+ * 4. The system is 1T capable, both addresses are > 1T, use the GET_ESID_1T macro to compare.
+ */
+static inline int esids_match(unsigned long addr1, unsigned long addr2)
+{
+ int esid_1t_count;
+
+ /* System is not 1T segment size capable. */
+ if (!cpu_has_feature(CPU_FTR_1T_SEGMENT))
+ return (GET_ESID(addr1) == GET_ESID(addr2));
+
+ esid_1t_count = (((addr1 >> SID_SHIFT_1T) != 0) +
+ ((addr2 >> SID_SHIFT_1T) != 0));
+
+ /* both addresses are < 1T */
+ if (esid_1t_count == 0)
+ return (GET_ESID(addr1) == GET_ESID(addr2));
+
+ /* One address < 1T, the other > 1T. Not a match */
+ if (esid_1t_count == 1)
+ return 0;
+
+ /* Both addresses are > 1T. */
+ return (GET_ESID_1T(addr1) == GET_ESID_1T(addr2));
+}
+
/* Flush all user entries from the segment table of the current processor. */
void switch_slb(struct task_struct *tsk, struct mm_struct *mm)
{
@@ -157,7 +187,8 @@ void switch_slb(struct task_struct *tsk, struct mm_struct *mm)
unsigned long stack = KSTK_ESP(tsk);
unsigned long unmapped_base;
- if (offset <= SLB_CACHE_ENTRIES) {
+ if (!cpu_has_feature(CPU_FTR_NO_SLBIE_B) &&
+ offset <= SLB_CACHE_ENTRIES) {
int i;
asm volatile("isync" : : : "memory");
for (i = 0; i < offset; i++) {
@@ -192,15 +223,14 @@ void switch_slb(struct task_struct *tsk, struct mm_struct *mm)
return;
slb_allocate(pc);
- if (GET_ESID(pc) == GET_ESID(stack))
+ if (esids_match(pc,stack))
return;
if (is_kernel_addr(stack))
return;
slb_allocate(stack);
- if ((GET_ESID(pc) == GET_ESID(unmapped_base))
- || (GET_ESID(stack) == GET_ESID(unmapped_base)))
+ if (esids_match(pc,unmapped_base) || esids_match(stack,unmapped_base))
return;
if (is_kernel_addr(unmapped_base))
diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c
index 319826ef1645..ad928edafb0a 100644
--- a/arch/powerpc/mm/slice.c
+++ b/arch/powerpc/mm/slice.c
@@ -34,7 +34,7 @@
#include <asm/mmu.h>
#include <asm/spu.h>
-static spinlock_t slice_convert_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(slice_convert_lock);
#ifdef DEBUG
diff --git a/arch/powerpc/mm/tlb_64.c b/arch/powerpc/mm/tlb_64.c
index eafbca52bff9..e2d867ce1c7e 100644
--- a/arch/powerpc/mm/tlb_64.c
+++ b/arch/powerpc/mm/tlb_64.c
@@ -54,12 +54,10 @@ unsigned long pte_freelist_forced_free;
((PAGE_SIZE - sizeof(struct pte_freelist_batch)) \
/ sizeof(pgtable_free_t))
-#ifdef CONFIG_SMP
static void pte_free_smp_sync(void *arg)
{
/* Do nothing, just ensure we sync with all CPUs */
}
-#endif
/* This is only called when we are critically out of memory
* (and fail to get a page in pte_free_tlb).
diff --git a/arch/powerpc/oprofile/Kconfig b/arch/powerpc/oprofile/Kconfig
deleted file mode 100644
index 7089e79689b9..000000000000
--- a/arch/powerpc/oprofile/Kconfig
+++ /dev/null
@@ -1,24 +0,0 @@
-config PROFILING
- bool "Profiling support (EXPERIMENTAL)"
- help
- Say Y here to enable the extended profiling support mechanisms used
- by profilers such as OProfile.
-
-
-config OPROFILE
- tristate "OProfile system profiling (EXPERIMENTAL)"
- depends on PROFILING
- help
- OProfile is a profiling system capable of profiling the
- whole system, include the kernel, kernel modules, libraries,
- and applications.
-
- If unsure, say N.
-
-config OPROFILE_CELL
- bool "OProfile for Cell Broadband Engine"
- depends on (SPU_FS = y && OPROFILE = m) || (SPU_FS = y && OPROFILE = y) || (SPU_FS = m && OPROFILE = m)
- default y
- help
- Profiling of Cell BE SPUs requires special support enabled
- by this option.
diff --git a/arch/powerpc/platforms/40x/Kconfig b/arch/powerpc/platforms/40x/Kconfig
index 47b3b0a3864a..8f6699fcc145 100644
--- a/arch/powerpc/platforms/40x/Kconfig
+++ b/arch/powerpc/platforms/40x/Kconfig
@@ -100,6 +100,7 @@ config 405GP
bool
select IBM405_ERR77
select IBM405_ERR51
+ select IBM_NEW_EMAC_ZMII
config 405EP
bool
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig
index 51f3ea40a285..8390cc164135 100644
--- a/arch/powerpc/platforms/44x/Kconfig
+++ b/arch/powerpc/platforms/44x/Kconfig
@@ -43,14 +43,14 @@ config 440EP
bool
select PPC_FPU
select IBM440EP_ERR42
-# select IBM_NEW_EMAC_ZMII
+ select IBM_NEW_EMAC_ZMII
config 440EPX
bool
select PPC_FPU
-# Disabled until the new EMAC Driver is merged.
-# select IBM_NEW_EMAC_EMAC4
-# select IBM_NEW_EMAC_ZMII
+ select IBM_NEW_EMAC_EMAC4
+ select IBM_NEW_EMAC_RGMII
+ select IBM_NEW_EMAC_ZMII
config 440GP
bool
diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c
index 65b7ae426238..25d2bfa3d9dc 100644
--- a/arch/powerpc/platforms/52xx/lite5200.c
+++ b/arch/powerpc/platforms/52xx/lite5200.c
@@ -145,6 +145,9 @@ static void __init lite5200_setup_arch(void)
/* Some mpc5200 & mpc5200b related configuration */
mpc5200_setup_xlb_arbiter();
+ /* Map wdt for mpc52xx_restart() */
+ mpc52xx_map_wdt();
+
#ifdef CONFIG_PM
mpc52xx_suspend.board_suspend_prepare = lite5200_suspend_prepare;
mpc52xx_suspend.board_resume_finish = lite5200_resume_finish;
@@ -183,5 +186,6 @@ define_machine(lite5200) {
.init = mpc52xx_declare_of_platform_devices,
.init_IRQ = mpc52xx_init_irq,
.get_irq = mpc52xx_get_irq,
+ .restart = mpc52xx_restart,
.calibrate_decr = generic_calibrate_decr,
};
diff --git a/arch/powerpc/platforms/52xx/lite5200_pm.c b/arch/powerpc/platforms/52xx/lite5200_pm.c
index f26afcd41757..ffa14aff5248 100644
--- a/arch/powerpc/platforms/52xx/lite5200_pm.c
+++ b/arch/powerpc/platforms/52xx/lite5200_pm.c
@@ -1,5 +1,5 @@
#include <linux/init.h>
-#include <linux/pm.h>
+#include <linux/suspend.h>
#include <asm/io.h>
#include <asm/time.h>
#include <asm/mpc52xx.h>
@@ -18,6 +18,8 @@ static void __iomem *sram;
static const int sram_size = 0x4000; /* 16 kBytes */
static void __iomem *mbar;
+static suspend_state_t lite5200_pm_target_state;
+
static int lite5200_pm_valid(suspend_state_t state)
{
switch (state) {
@@ -29,13 +31,22 @@ static int lite5200_pm_valid(suspend_state_t state)
}
}
-static int lite5200_pm_prepare(suspend_state_t state)
+static int lite5200_pm_set_target(suspend_state_t state)
+{
+ if (lite5200_pm_valid(state)) {
+ lite5200_pm_target_state = state;
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static int lite5200_pm_prepare(void)
{
/* deep sleep? let mpc52xx code handle that */
- if (state == PM_SUSPEND_STANDBY)
- return mpc52xx_pm_prepare(state);
+ if (lite5200_pm_target_state == PM_SUSPEND_STANDBY)
+ return mpc52xx_pm_prepare();
- if (state != PM_SUSPEND_MEM)
+ if (lite5200_pm_target_state != PM_SUSPEND_MEM)
return -EINVAL;
/* map registers */
@@ -190,17 +201,16 @@ static int lite5200_pm_enter(suspend_state_t state)
return 0;
}
-static int lite5200_pm_finish(suspend_state_t state)
+static void lite5200_pm_finish(void)
{
/* deep sleep? let mpc52xx code handle that */
- if (state == PM_SUSPEND_STANDBY) {
- return mpc52xx_pm_finish(state);
- }
- return 0;
+ if (lite5200_pm_target_state == PM_SUSPEND_STANDBY)
+ mpc52xx_pm_finish();
}
-static struct pm_ops lite5200_pm_ops = {
+static struct platform_suspend_ops lite5200_pm_ops = {
.valid = lite5200_pm_valid,
+ .set_target = lite5200_pm_set_target,
.prepare = lite5200_pm_prepare,
.enter = lite5200_pm_enter,
.finish = lite5200_pm_finish,
@@ -208,6 +218,6 @@ static struct pm_ops lite5200_pm_ops = {
int __init lite5200_pm_init(void)
{
- pm_set_ops(&lite5200_pm_ops);
+ suspend_set_ops(&lite5200_pm_ops);
return 0;
}
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c
index 3bc201e07e6b..9850685c5429 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_common.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c
@@ -18,15 +18,20 @@
#include <asm/prom.h>
#include <asm/mpc52xx.h>
+/*
+ * This variable is mapped in mpc52xx_map_wdt() and used in mpc52xx_restart().
+ * Permanent mapping is required because mpc52xx_restart() can be called
+ * from interrupt context while node mapping (which calls ioremap())
+ * cannot be used at such point.
+ */
+static volatile struct mpc52xx_gpt *mpc52xx_wdt = NULL;
-void __iomem *
-mpc52xx_find_and_map(const char *compatible)
+static void __iomem *
+mpc52xx_map_node(struct device_node *ofn)
{
- struct device_node *ofn;
const u32 *regaddr_p;
u64 regaddr64, size64;
- ofn = of_find_compatible_node(NULL, NULL, compatible);
if (!ofn)
return NULL;
@@ -42,8 +47,23 @@ mpc52xx_find_and_map(const char *compatible)
return ioremap((u32)regaddr64, (u32)size64);
}
+
+void __iomem *
+mpc52xx_find_and_map(const char *compatible)
+{
+ return mpc52xx_map_node(
+ of_find_compatible_node(NULL, NULL, compatible));
+}
+
EXPORT_SYMBOL(mpc52xx_find_and_map);
+void __iomem *
+mpc52xx_find_and_map_path(const char *path)
+{
+ return mpc52xx_map_node(of_find_node_by_path(path));
+}
+
+EXPORT_SYMBOL(mpc52xx_find_and_map_path);
/**
* mpc52xx_find_ipb_freq - Find the IPB bus frequency for a device
@@ -113,3 +133,46 @@ mpc52xx_declare_of_platform_devices(void)
"Error while probing of_platform bus\n");
}
+void __init
+mpc52xx_map_wdt(void)
+{
+ const void *has_wdt;
+ struct device_node *np;
+
+ /* mpc52xx_wdt is mapped here and used in mpc52xx_restart,
+ * possibly from a interrupt context. wdt is only implement
+ * on a gpt0, so check has-wdt property before mapping.
+ */
+ for_each_compatible_node(np, NULL, "fsl,mpc5200-gpt") {
+ has_wdt = of_get_property(np, "fsl,has-wdt", NULL);
+ if (has_wdt) {
+ mpc52xx_wdt = mpc52xx_map_node(np);
+ return;
+ }
+ }
+ for_each_compatible_node(np, NULL, "mpc5200-gpt") {
+ has_wdt = of_get_property(np, "has-wdt", NULL);
+ if (has_wdt) {
+ mpc52xx_wdt = mpc52xx_map_node(np);
+ return;
+ }
+ }
+}
+
+void
+mpc52xx_restart(char *cmd)
+{
+ local_irq_disable();
+
+ /* Turn on the watchdog and wait for it to expire.
+ * It effectively does a reset. */
+ if (mpc52xx_wdt) {
+ out_be32(&mpc52xx_wdt->mode, 0x00000000);
+ out_be32(&mpc52xx_wdt->count, 0x000000ff);
+ out_be32(&mpc52xx_wdt->mode, 0x00009004);
+ } else
+ printk("mpc52xx_restart: Can't access wdt. "
+ "Restart impossible, system halted.\n");
+
+ while (1);
+}
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pm.c b/arch/powerpc/platforms/52xx/mpc52xx_pm.c
index ee2e7639c63e..7ffa7babf254 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pm.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pm.c
@@ -1,5 +1,5 @@
#include <linux/init.h>
-#include <linux/pm.h>
+#include <linux/suspend.h>
#include <linux/io.h>
#include <asm/time.h>
#include <asm/cacheflush.h>
@@ -57,11 +57,8 @@ int mpc52xx_set_wakeup_gpio(u8 pin, u8 level)
return 0;
}
-int mpc52xx_pm_prepare(suspend_state_t state)
+int mpc52xx_pm_prepare(void)
{
- if (state != PM_SUSPEND_STANDBY)
- return -EINVAL;
-
/* map the whole register space */
mbar = mpc52xx_find_and_map("mpc5200");
if (!mbar) {
@@ -166,18 +163,16 @@ int mpc52xx_pm_enter(suspend_state_t state)
return 0;
}
-int mpc52xx_pm_finish(suspend_state_t state)
+void mpc52xx_pm_finish(void)
{
/* call board resume code */
if (mpc52xx_suspend.board_resume_finish)
mpc52xx_suspend.board_resume_finish(mbar);
iounmap(mbar);
-
- return 0;
}
-static struct pm_ops mpc52xx_pm_ops = {
+static struct platform_suspend_ops mpc52xx_pm_ops = {
.valid = mpc52xx_pm_valid,
.prepare = mpc52xx_pm_prepare,
.enter = mpc52xx_pm_enter,
@@ -186,6 +181,6 @@ static struct pm_ops mpc52xx_pm_ops = {
int __init mpc52xx_pm_init(void)
{
- pm_set_ops(&mpc52xx_pm_ops);
+ suspend_set_ops(&mpc52xx_pm_ops);
return 0;
}
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index cc6013ffc29a..ea22cad2cd0a 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -117,10 +117,10 @@ config RTAS_FLASH
config PPC_PMI
tristate "Support for PMI"
- depends PPC_IBM_CELL_BLADE
+ depends on PPC_IBM_CELL_BLADE
help
PMI (Platform Management Interrupt) is a way to
- communicate with the BMC (Baseboard Mangement Controller).
+ communicate with the BMC (Baseboard Management Controller).
It is used in some IBM Cell blades.
default m
@@ -264,6 +264,7 @@ config TAU_AVERAGE
config QUICC_ENGINE
bool
+ select PPC_LIB_RHEAP
help
The QUICC Engine (QE) is a new generation of communications
coprocessors on Freescale embedded CPUs (akin to CPM in older chips).
@@ -274,6 +275,7 @@ config CPM2
bool
default n
select CPM
+ select PPC_LIB_RHEAP
help
The CPM2 (Communications Processor Module) is a coprocessor on
embedded CPUs made by Freescale. Selecting this option means that
@@ -313,4 +315,6 @@ config FSL_ULI1575
config CPM
bool
+source "arch/powerpc/sysdev/bestcomm/Kconfig"
+
endmenu
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index 4c315be25015..99684ea606af 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -37,6 +37,7 @@ config PPC_8xx
select FSL_SOC
select 8xx
select WANT_DEVICE_TREE
+ select PPC_LIB_RHEAP
config 40x
bool "AMCC 40x"
@@ -47,6 +48,7 @@ config 44x
bool "AMCC 44x"
select PPC_DCR_NATIVE
select WANT_DEVICE_TREE
+ select PPC_UDBG_16550
config E200
bool "Freescale e200"
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index 1245b2f517bb..095988f13bf4 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -77,12 +77,7 @@ static void msic_dcr_write(struct axon_msic *msic, unsigned int dcr_n, u32 val)
{
pr_debug("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n);
- dcr_write(msic->dcr_host, msic->dcr_host.base + dcr_n, val);
-}
-
-static u32 msic_dcr_read(struct axon_msic *msic, unsigned int dcr_n)
-{
- return dcr_read(msic->dcr_host, msic->dcr_host.base + dcr_n);
+ dcr_write(msic->dcr_host, dcr_n, val);
}
static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
@@ -91,7 +86,7 @@ static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
u32 write_offset, msi;
int idx;
- write_offset = msic_dcr_read(msic, MSIC_WRITE_OFFSET_REG);
+ write_offset = dcr_read(msic->dcr_host, MSIC_WRITE_OFFSET_REG);
pr_debug("axon_msi: original write_offset 0x%x\n", write_offset);
/* write_offset doesn't wrap properly, so we have to mask it */
@@ -306,7 +301,7 @@ static int axon_msi_notify_reboot(struct notifier_block *nb,
list_for_each_entry(msic, &axon_msic_list, list) {
pr_debug("axon_msi: disabling %s\n",
msic->irq_host->of_node->full_name);
- tmp = msic_dcr_read(msic, MSIC_CTRL_REG);
+ tmp = dcr_read(msic->dcr_host, MSIC_CTRL_REG);
tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE;
msic_dcr_write(msic, MSIC_CTRL_REG, tmp);
}
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq.c b/arch/powerpc/platforms/cell/cbe_cpufreq.c
index 5123e9d4164b..13d5a87f13b1 100644
--- a/arch/powerpc/platforms/cell/cbe_cpufreq.c
+++ b/arch/powerpc/platforms/cell/cbe_cpufreq.c
@@ -117,7 +117,7 @@ static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy)
policy->cur = cbe_freqs[cur_pmode].frequency;
#ifdef CONFIG_SMP
- policy->cpus = cpu_sibling_map[policy->cpu];
+ policy->cpus = per_cpu(cpu_sibling_map, policy->cpu);
#endif
cpufreq_frequency_table_get_attr(cbe_freqs, policy->cpu);
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c
index 151fd8b82d63..04f74f9f9ab6 100644
--- a/arch/powerpc/platforms/cell/interrupt.c
+++ b/arch/powerpc/platforms/cell/interrupt.c
@@ -158,6 +158,18 @@ static unsigned int iic_get_irq(void)
return virq;
}
+void iic_setup_cpu(void)
+{
+ out_be64(&__get_cpu_var(iic).regs->prio, 0xff);
+}
+
+u8 iic_get_target_id(int cpu)
+{
+ return per_cpu(iic, cpu).target_id;
+}
+
+EXPORT_SYMBOL_GPL(iic_get_target_id);
+
#ifdef CONFIG_SMP
/* Use the highest interrupt priorities for IPI */
@@ -166,29 +178,17 @@ static inline int iic_ipi_to_irq(int ipi)
return IIC_IRQ_TYPE_IPI + 0xf - ipi;
}
-void iic_setup_cpu(void)
-{
- out_be64(&__get_cpu_var(iic).regs->prio, 0xff);
-}
-
void iic_cause_IPI(int cpu, int mesg)
{
out_be64(&per_cpu(iic, cpu).regs->generate, (0xf - mesg) << 4);
}
-u8 iic_get_target_id(int cpu)
-{
- return per_cpu(iic, cpu).target_id;
-}
-EXPORT_SYMBOL_GPL(iic_get_target_id);
-
struct irq_host *iic_get_irq_host(int node)
{
return iic_host;
}
EXPORT_SYMBOL_GPL(iic_get_irq_host);
-
static irqreturn_t iic_ipi_action(int irq, void *dev_id)
{
int ipi = (int)(long)dev_id;
diff --git a/arch/powerpc/platforms/cell/smp.c b/arch/powerpc/platforms/cell/smp.c
index 1c0acbad7425..e4438456c867 100644
--- a/arch/powerpc/platforms/cell/smp.c
+++ b/arch/powerpc/platforms/cell/smp.c
@@ -44,6 +44,7 @@
#include <asm/rtas.h>
#include "interrupt.h"
+#include <asm/udbg.h>
#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index d72b16d6816e..d9e56a503795 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -748,7 +748,7 @@ static ssize_t spufs_wbox_write(struct file *file, const char __user *buf,
if (count)
goto out;
- /* write aѕ much as possible */
+ /* write as much as possible */
for (count = 4, udata++; (count + 4) <= len; count += 4, udata++) {
int ret;
ret = __get_user(wbox_data, udata);
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index 11098747d09b..0966d093db43 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -68,7 +68,7 @@ spufs_destroy_inode(struct inode *inode)
}
static void
-spufs_init_once(void *p, struct kmem_cache * cachep, unsigned long flags)
+spufs_init_once(struct kmem_cache *cachep, void *p)
{
struct spufs_inode_info *ei = p;
diff --git a/arch/powerpc/platforms/celleb/scc_uhc.c b/arch/powerpc/platforms/celleb/scc_uhc.c
index a7c548bde2e3..b59c38a06e3e 100644
--- a/arch/powerpc/platforms/celleb/scc_uhc.c
+++ b/arch/powerpc/platforms/celleb/scc_uhc.c
@@ -36,7 +36,7 @@ static inline int uhc_clkctrl_ready(u32 val)
}
/*
- * UHC(usb host controler) enable function.
+ * UHC(usb host controller) enable function.
* affect to both of OHCI and EHCI core module.
*/
static void enable_scc_uhc(struct pci_dev *dev)
diff --git a/arch/powerpc/platforms/celleb/setup.c b/arch/powerpc/platforms/celleb/setup.c
index 1769d755eff3..ddfb35ae741f 100644
--- a/arch/powerpc/platforms/celleb/setup.c
+++ b/arch/powerpc/platforms/celleb/setup.c
@@ -49,6 +49,7 @@
#include <asm/machdep.h>
#include <asm/cputable.h>
#include <asm/irq.h>
+#include <asm/time.h>
#include <asm/spu_priv1.h>
#include <asm/firmware.h>
#include <asm/of_platform.h>
diff --git a/arch/powerpc/platforms/iseries/htab.c b/arch/powerpc/platforms/iseries/htab.c
index 15a7097e5dd7..f99c6c4b6985 100644
--- a/arch/powerpc/platforms/iseries/htab.c
+++ b/arch/powerpc/platforms/iseries/htab.c
@@ -39,9 +39,9 @@ static inline void iSeries_hunlock(unsigned long slot)
spin_unlock(&iSeries_hlocks[(slot >> 4) & 0x3f]);
}
-long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
+static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
unsigned long pa, unsigned long rflags,
- unsigned long vflags, int psize)
+ unsigned long vflags, int psize, int ssize)
{
long slot;
struct hash_pte lhpte;
diff --git a/arch/powerpc/platforms/iseries/irq.h b/arch/powerpc/platforms/iseries/irq.h
index 69f1b437fc7b..a1c236074034 100644
--- a/arch/powerpc/platforms/iseries/irq.h
+++ b/arch/powerpc/platforms/iseries/irq.h
@@ -1,9 +1,13 @@
#ifndef _ISERIES_IRQ_H
#define _ISERIES_IRQ_H
+#ifdef CONFIG_PCI
extern void iSeries_init_IRQ(void);
extern int iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, u32);
extern void iSeries_activate_IRQs(void);
+#else
+#define iSeries_init_IRQ NULL
+#endif
extern unsigned int iSeries_get_irq(void);
#endif /* _ISERIES_IRQ_H */
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index 37ae07ee54a9..0877a8834110 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -617,10 +617,6 @@ static void iseries_dedicated_idle(void)
}
}
-#ifndef CONFIG_PCI
-void __init iSeries_init_IRQ(void) { }
-#endif
-
static void __iomem *iseries_ioremap(phys_addr_t address, unsigned long size,
unsigned long flags)
{
diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c
index 910b00b4703e..be06cfd9fa3d 100644
--- a/arch/powerpc/platforms/iseries/vio.c
+++ b/arch/powerpc/platforms/iseries/vio.c
@@ -2,7 +2,7 @@
* Legacy iSeries specific vio initialisation
* that needs to be built in (not a module).
*
- * © Copyright 2007 IBM Corporation
+ * © Copyright 2007 IBM Corporation
* Author: Stephen Rothwell
* Some parts collected from various other files
*
@@ -523,15 +523,16 @@ static void __init get_viotape_info(struct device_node *vio_root)
static int __init iseries_vio_init(void)
{
struct device_node *vio_root;
+ int ret = -ENODEV;
if (!firmware_has_feature(FW_FEATURE_ISERIES))
- return -ENODEV;
+ goto out;
iommu_vio_init();
vio_root = of_find_node_by_path("/vdevice");
if (!vio_root)
- return -ENODEV;
+ goto out;
if (viopath_hostLp == HvLpIndexInvalid) {
vio_set_hostlp();
@@ -544,10 +545,11 @@ static int __init iseries_vio_init(void)
get_viocd_info(vio_root);
get_viotape_info(vio_root);
- return 0;
+ ret = 0;
put_node:
of_node_put(vio_root);
- return -ENODEV;
+ out:
+ return ret;
}
arch_initcall(iseries_vio_init);
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index 354c05861629..144177d77cf1 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -41,13 +41,13 @@
#include <linux/root_dev.h>
#include <linux/serial.h>
#include <linux/smp.h>
+#include <linux/bitops.h>
#include <asm/processor.h>
#include <asm/sections.h>
#include <asm/prom.h>
#include <asm/system.h>
#include <asm/pgtable.h>
-#include <asm/bitops.h>
#include <asm/io.h>
#include <asm/kexec.h>
#include <asm/pci-bridge.h>
diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c
index 5ddf40a66ae8..3a5d112af5e0 100644
--- a/arch/powerpc/platforms/pasemi/setup.c
+++ b/arch/powerpc/platforms/pasemi/setup.c
@@ -37,6 +37,10 @@
#include <asm/time.h>
#include <asm/of_platform.h>
+#include <pcmcia/ss.h>
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ds.h>
+
#include "pasemi.h"
/* SDC reset register, must be pre-mapped at reset time */
@@ -308,7 +312,57 @@ static void __init pas_init_early(void)
iommu_init_early_pasemi();
}
+#ifdef CONFIG_PCMCIA
+static int pcmcia_notify(struct notifier_block *nb, unsigned long action,
+ void *data)
+{
+ struct device *dev = data;
+ struct device *parent;
+ struct pcmcia_device *pdev = to_pcmcia_dev(dev);
+
+ /* We are only intereted in device addition */
+ if (action != BUS_NOTIFY_ADD_DEVICE)
+ return 0;
+
+ parent = pdev->socket->dev.parent;
+
+ /* We know electra_cf devices will always have of_node set, since
+ * electra_cf is an of_platform driver.
+ */
+ if (!parent->archdata.of_node)
+ return 0;
+
+ if (!of_device_is_compatible(parent->archdata.of_node, "electra-cf"))
+ return 0;
+
+ /* We use the direct ops for localbus */
+ dev->archdata.dma_ops = &dma_direct_ops;
+
+ return 0;
+}
+
+static struct notifier_block pcmcia_notifier = {
+ .notifier_call = pcmcia_notify,
+};
+
+static inline void pasemi_pcmcia_init(void)
+{
+ extern struct bus_type pcmcia_bus_type;
+
+ bus_register_notifier(&pcmcia_bus_type, &pcmcia_notifier);
+}
+
+#else
+
+static inline void pasemi_pcmcia_init(void)
+{
+}
+
+#endif
+
+
static struct of_device_id pasemi_bus_ids[] = {
+ { .type = "localbus", },
{ .type = "sdc", },
{},
};
@@ -318,6 +372,8 @@ static int __init pasemi_publish_devices(void)
if (!machine_is(pasemi))
return 0;
+ pasemi_pcmcia_init();
+
/* Publish OF platform devices for SDC and other non-PCI devices */
of_platform_bus_probe(NULL, pasemi_bus_ids, NULL);
diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c
index 190ff4b59a55..6405f4a36763 100644
--- a/arch/powerpc/platforms/ps3/system-bus.c
+++ b/arch/powerpc/platforms/ps3/system-bus.c
@@ -616,20 +616,20 @@ static void ps3_unmap_single(struct device *_dev, dma_addr_t dma_addr,
}
}
-static int ps3_sb_map_sg(struct device *_dev, struct scatterlist *sg, int nents,
- enum dma_data_direction direction)
+static int ps3_sb_map_sg(struct device *_dev, struct scatterlist *sgl,
+ int nents, enum dma_data_direction direction)
{
#if defined(CONFIG_PS3_DYNAMIC_DMA)
BUG_ON("do");
return -EPERM;
#else
struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
+ struct scatterlist *sg;
int i;
- for (i = 0; i < nents; i++, sg++) {
- int result = ps3_dma_map(dev->d_region,
- page_to_phys(sg->page) + sg->offset, sg->length,
- &sg->dma_address, 0);
+ for_each_sg(sgl, sg, nents, i) {
+ int result = ps3_dma_map(dev->d_region, sg_phys(sg),
+ sg->length, &sg->dma_address, 0);
if (result) {
pr_debug("%s:%d: ps3_dma_map failed (%d)\n",
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 22322b35a0ff..fb3d636e088b 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -186,6 +186,11 @@ static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len)
n += scnprintf(buf+n, len-n, "cmd/stat:%x\n", cfg);
printk(KERN_WARNING "EEH: PCI cmd/status register: %08x\n", cfg);
+ if (!dev) {
+ printk(KERN_WARNING "EEH: no PCI device for this of node\n");
+ return n;
+ }
+
/* Gather bridge-specific registers */
if (dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) {
rtas_read_config(pdn, PCI_SEC_STATUS, 2, &cfg);
@@ -198,7 +203,7 @@ static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len)
}
/* Dump out the PCI-X command and status regs */
- cap = pci_find_capability(pdn->pcidev, PCI_CAP_ID_PCIX);
+ cap = pci_find_capability(dev, PCI_CAP_ID_PCIX);
if (cap) {
rtas_read_config(pdn, cap, 4, &cfg);
n += scnprintf(buf+n, len-n, "pcix-cmd:%x\n", cfg);
@@ -210,7 +215,7 @@ static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len)
}
/* If PCI-E capable, dump PCI-E cap 10, and the AER */
- cap = pci_find_capability(pdn->pcidev, PCI_CAP_ID_EXP);
+ cap = pci_find_capability(dev, PCI_CAP_ID_EXP);
if (cap) {
n += scnprintf(buf+n, len-n, "pci-e cap10:\n");
printk(KERN_WARNING
@@ -222,7 +227,7 @@ static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len)
printk(KERN_WARNING "EEH: PCI-E %02x: %08x\n", i, cfg);
}
- cap = pci_find_ext_capability(pdn->pcidev, PCI_EXT_CAP_ID_ERR);
+ cap = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
if (cap) {
n += scnprintf(buf+n, len-n, "pci-e AER:\n");
printk(KERN_WARNING
@@ -318,7 +323,7 @@ eeh_wait_for_slot_status(struct pci_dn *pdn, int max_wait_msecs)
if (rets[2] == 0) return -1; /* permanently unavailable */
- if (max_wait_msecs <= 0) return -1;
+ if (max_wait_msecs <= 0) break;
mwait = rets[2];
if (mwait <= 0) {
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c
index 15e015ef6865..57e025e84ab4 100644
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -105,17 +105,18 @@ static void eeh_report_error(struct pci_dev *dev, void *userdata)
return;
rc = driver->err_handler->error_detected (dev, pci_channel_io_frozen);
+
+ /* A driver that needs a reset trumps all others */
+ if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
if (*res == PCI_ERS_RESULT_NONE) *res = rc;
- if (*res == PCI_ERS_RESULT_DISCONNECT &&
- rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
}
/**
* eeh_report_mmio_enabled - tell drivers that MMIO has been enabled
*
- * Report an EEH error to each device driver, collect up and
- * merge the device driver responses. Cumulative response
- * passed back in "userdata".
+ * Tells each device driver that IO ports, MMIO and config space I/O
+ * are now enabled. Collects up and merges the device driver responses.
+ * Cumulative response passed back in "userdata".
*/
static void eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata)
@@ -123,17 +124,16 @@ static void eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata)
enum pci_ers_result rc, *res = userdata;
struct pci_driver *driver = dev->driver;
- // dev->error_state = pci_channel_mmio_enabled;
-
if (!driver ||
!driver->err_handler ||
!driver->err_handler->mmio_enabled)
return;
rc = driver->err_handler->mmio_enabled (dev);
+
+ /* A driver that needs a reset trumps all others */
+ if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
if (*res == PCI_ERS_RESULT_NONE) *res = rc;
- if (*res == PCI_ERS_RESULT_DISCONNECT &&
- rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
}
/**
diff --git a/arch/powerpc/platforms/pseries/firmware.c b/arch/powerpc/platforms/pseries/firmware.c
index 8b18a1c40092..b765b7c77b65 100644
--- a/arch/powerpc/platforms/pseries/firmware.c
+++ b/arch/powerpc/platforms/pseries/firmware.c
@@ -25,6 +25,7 @@
#include <asm/firmware.h>
#include <asm/prom.h>
+#include <asm/udbg.h>
#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c
index 2793a1b100e6..f15222bbe136 100644
--- a/arch/powerpc/platforms/pseries/msi.c
+++ b/arch/powerpc/platforms/pseries/msi.c
@@ -171,6 +171,7 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
struct pci_dn *pdn;
int hwirq, virq, i, rc;
struct msi_desc *entry;
+ struct msi_msg msg;
pdn = get_pdn(pdev);
if (!pdn)
@@ -213,6 +214,11 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
dev_dbg(&pdev->dev, "rtas_msi: allocated virq %d\n", virq);
set_irq_msi(virq, entry);
+
+ /* Read config space back so we can restore after reset */
+ read_msi_msg(virq, &msg);
+ entry->msg = msg;
+
unmask_msi_irq(virq);
}
diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c
index 3a393c7f390e..a1ab25c7082f 100644
--- a/arch/powerpc/platforms/pseries/ras.c
+++ b/arch/powerpc/platforms/pseries/ras.c
@@ -332,7 +332,7 @@ static int recover_mce(struct pt_regs *regs, struct rtas_error_log * err)
err->disposition == RTAS_DISP_NOT_RECOVERED &&
err->target == RTAS_TARGET_MEMORY &&
err->type == RTAS_TYPE_ECC_UNCORR &&
- !(current->pid == 0 || is_init(current))) {
+ !(current->pid == 0 || is_global_init(current))) {
/* Kill off a user process with an ECC error */
printk(KERN_ERR "MCE: uncorrectable ecc error for pid %d\n",
current->pid);
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 1a6f5641ebc8..99a77d743d48 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_FSL_SOC) += fsl_soc.o
obj-$(CONFIG_FSL_PCI) += fsl_pci.o
obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
obj-$(CONFIG_QUICC_ENGINE) += qe_lib/
+obj-$(CONFIG_PPC_BESTCOMM) += bestcomm/
mv64x60-$(CONFIG_PCI) += mv64x60_pci.o
obj-$(CONFIG_MV64X60) += $(mv64x60-y) mv64x60_pic.o mv64x60_dev.o \
mv64x60_udbg.o
diff --git a/arch/powerpc/sysdev/bestcomm/Kconfig b/arch/powerpc/sysdev/bestcomm/Kconfig
new file mode 100644
index 000000000000..57cc56562567
--- /dev/null
+++ b/arch/powerpc/sysdev/bestcomm/Kconfig
@@ -0,0 +1,39 @@
+#
+# Kconfig options for Bestcomm
+#
+
+config PPC_BESTCOMM
+ tristate "Bestcomm DMA engine support"
+ depends on PPC_MPC52xx
+ default n
+ select PPC_LIB_RHEAP
+ help
+ BestComm is the name of the communication coprocessor found
+ on the Freescale MPC5200 family of processor. It's usage is
+ optionnal for some drivers (like ATA), but required for
+ others (like FEC).
+
+ If you want to use drivers that require DMA operations,
+ answer Y or M. Otherwise say N.
+
+config PPC_BESTCOMM_ATA
+ tristate "Bestcomm ATA task support"
+ depends on PPC_BESTCOMM
+ default n
+ help
+ This option enables the support for the ATA task.
+
+config PPC_BESTCOMM_FEC
+ tristate "Bestcomm FEC tasks support"
+ depends on PPC_BESTCOMM
+ default n
+ help
+ This option enables the support for the FEC tasks.
+
+config PPC_BESTCOMM_GEN_BD
+ tristate "Bestcomm GenBD tasks support"
+ depends on PPC_BESTCOMM
+ default n
+ help
+ This option enables the support for the GenBD tasks.
+
diff --git a/arch/powerpc/sysdev/bestcomm/Makefile b/arch/powerpc/sysdev/bestcomm/Makefile
new file mode 100644
index 000000000000..aed2df2a6580
--- /dev/null
+++ b/arch/powerpc/sysdev/bestcomm/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for BestComm & co
+#
+
+bestcomm-core-objs := bestcomm.o sram.o
+bestcomm-ata-objs := ata.o bcom_ata_task.o
+bestcomm-fec-objs := fec.o bcom_fec_rx_task.o bcom_fec_tx_task.o
+bestcomm-gen-bd-objs := gen_bd.o bcom_gen_bd_rx_task.o bcom_gen_bd_tx_task.o
+
+obj-$(CONFIG_PPC_BESTCOMM) += bestcomm-core.o
+obj-$(CONFIG_PPC_BESTCOMM_ATA) += bestcomm-ata.o
+obj-$(CONFIG_PPC_BESTCOMM_FEC) += bestcomm-fec.o
+obj-$(CONFIG_PPC_BESTCOMM_GEN_BD) += bestcomm-gen-bd.o
+
diff --git a/arch/powerpc/sysdev/bestcomm/ata.c b/arch/powerpc/sysdev/bestcomm/ata.c
new file mode 100644
index 000000000000..1f5258fb38c3
--- /dev/null
+++ b/arch/powerpc/sysdev/bestcomm/ata.c
@@ -0,0 +1,154 @@
+/*
+ * Bestcomm ATA task driver
+ *
+ *
+ * Patterned after bestcomm/fec.c by Dale Farnsworth <dfarnsworth@mvista.com>
+ * 2003-2004 (c) MontaVista, Software, Inc.
+ *
+ * Copyright (C) 2006-2007 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2006 Freescale - John Rigby
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <asm/io.h>
+
+#include "bestcomm.h"
+#include "bestcomm_priv.h"
+#include "ata.h"
+
+
+/* ======================================================================== */
+/* Task image/var/inc */
+/* ======================================================================== */
+
+/* ata task image */
+extern u32 bcom_ata_task[];
+
+/* ata task vars that need to be set before enabling the task */
+struct bcom_ata_var {
+ u32 enable; /* (u16*) address of task's control register */
+ u32 bd_base; /* (struct bcom_bd*) beginning of ring buffer */
+ u32 bd_last; /* (struct bcom_bd*) end of ring buffer */
+ u32 bd_start; /* (struct bcom_bd*) current bd */
+ u32 buffer_size; /* size of receive buffer */
+};
+
+/* ata task incs that need to be set before enabling the task */
+struct bcom_ata_inc {
+ u16 pad0;
+ s16 incr_bytes;
+ u16 pad1;
+ s16 incr_dst;
+ u16 pad2;
+ s16 incr_src;
+};
+
+
+/* ======================================================================== */
+/* Task support code */
+/* ======================================================================== */
+
+struct bcom_task *
+bcom_ata_init(int queue_len, int maxbufsize)
+{
+ struct bcom_task *tsk;
+ struct bcom_ata_var *var;
+ struct bcom_ata_inc *inc;
+
+ tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_ata_bd), 0);
+ if (!tsk)
+ return NULL;
+
+ tsk->flags = BCOM_FLAGS_NONE;
+
+ bcom_ata_reset_bd(tsk);
+
+ var = (struct bcom_ata_var *) bcom_task_var(tsk->tasknum);
+ inc = (struct bcom_ata_inc *) bcom_task_inc(tsk->tasknum);
+
+ if (bcom_load_image(tsk->tasknum, bcom_ata_task)) {
+ bcom_task_free(tsk);
+ return NULL;
+ }
+
+ var->enable = bcom_eng->regs_base +
+ offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);
+ var->bd_base = tsk->bd_pa;
+ var->bd_last = tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);
+ var->bd_start = tsk->bd_pa;
+ var->buffer_size = maxbufsize;
+
+ /* Configure some stuff */
+ bcom_set_task_pragma(tsk->tasknum, BCOM_ATA_PRAGMA);
+ bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);
+
+ out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_ATA_RX], BCOM_IPR_ATA_RX);
+ out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_ATA_TX], BCOM_IPR_ATA_TX);
+
+ out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum); /* Clear ints */
+
+ return tsk;
+}
+EXPORT_SYMBOL_GPL(bcom_ata_init);
+
+void bcom_ata_rx_prepare(struct bcom_task *tsk)
+{
+ struct bcom_ata_inc *inc;
+
+ inc = (struct bcom_ata_inc *) bcom_task_inc(tsk->tasknum);
+
+ inc->incr_bytes = -(s16)sizeof(u32);
+ inc->incr_src = 0;
+ inc->incr_dst = sizeof(u32);
+
+ bcom_set_initiator(tsk->tasknum, BCOM_INITIATOR_ATA_RX);
+}
+EXPORT_SYMBOL_GPL(bcom_ata_rx_prepare);
+
+void bcom_ata_tx_prepare(struct bcom_task *tsk)
+{
+ struct bcom_ata_inc *inc;
+
+ inc = (struct bcom_ata_inc *) bcom_task_inc(tsk->tasknum);
+
+ inc->incr_bytes = -(s16)sizeof(u32);
+ inc->incr_src = sizeof(u32);
+ inc->incr_dst = 0;
+
+ bcom_set_initiator(tsk->tasknum, BCOM_INITIATOR_ATA_TX);
+}
+EXPORT_SYMBOL_GPL(bcom_ata_tx_prepare);
+
+void bcom_ata_reset_bd(struct bcom_task *tsk)
+{
+ struct bcom_ata_var *var;
+
+ /* Reset all BD */
+ memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
+
+ tsk->index = 0;
+ tsk->outdex = 0;
+
+ var = (struct bcom_ata_var *) bcom_task_var(tsk->tasknum);
+ var->bd_start = var->bd_base;
+}
+EXPORT_SYMBOL_GPL(bcom_ata_reset_bd);
+
+void bcom_ata_release(struct bcom_task *tsk)
+{
+ /* Nothing special for the ATA tasks */
+ bcom_task_free(tsk);
+}
+EXPORT_SYMBOL_GPL(bcom_ata_release);
+
+
+MODULE_DESCRIPTION("BestComm ATA task driver");
+MODULE_AUTHOR("John Rigby");
+MODULE_LICENSE("GPL v2");
+
diff --git a/arch/powerpc/sysdev/bestcomm/ata.h b/arch/powerpc/sysdev/bestcomm/ata.h
new file mode 100644
index 000000000000..10982769c465
--- /dev/null
+++ b/arch/powerpc/sysdev/bestcomm/ata.h
@@ -0,0 +1,37 @@
+/*
+ * Header for Bestcomm ATA task driver
+ *
+ *
+ * Copyright (C) 2006 Freescale - John Rigby
+ * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef __BESTCOMM_ATA_H__
+#define __BESTCOMM_ATA_H__
+
+
+struct bcom_ata_bd {
+ u32 status;
+ u32 dst_pa;
+ u32 src_pa;
+};
+
+extern struct bcom_task *
+bcom_ata_init(int queue_len, int maxbufsize);
+
+extern void
+bcom_ata_rx_prepare(struct bcom_task *tsk);
+
+extern void
+bcom_ata_tx_prepare(struct bcom_task *tsk);
+
+extern void
+bcom_ata_reset_bd(struct bcom_task *tsk);
+
+
+#endif /* __BESTCOMM_ATA_H__ */
+
diff --git a/arch/powerpc/sysdev/bestcomm/bcom_ata_task.c b/arch/powerpc/sysdev/bestcomm/bcom_ata_task.c
new file mode 100644
index 000000000000..cc6049a4e469
--- /dev/null
+++ b/arch/powerpc/sysdev/bestcomm/bcom_ata_task.c
@@ -0,0 +1,67 @@
+/*
+ * Bestcomm ATA task microcode
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Created based on bestcom/code_dma/image_rtos1/dma_image.hex
+ */
+
+#include <asm/types.h>
+
+/*
+ * The header consists of the following fields:
+ * u32 magic;
+ * u8 desc_size;
+ * u8 var_size;
+ * u8 inc_size;
+ * u8 first_var;
+ * u8 reserved[8];
+ *
+ * The size fields contain the number of 32-bit words.
+ */
+
+u32 bcom_ata_task[] = {
+ /* header */
+ 0x4243544b,
+ 0x0e060709,
+ 0x00000000,
+ 0x00000000,
+
+ /* Task descriptors */
+ 0x8198009b, /* LCD: idx0 = var3; idx0 <= var2; idx0 += inc3 */
+ 0x13e00c08, /* DRD1A: var3 = var1; FN=0 MORE init=31 WS=0 RS=0 */
+ 0xb8000264, /* LCD: idx1 = *idx0, idx2 = var0; idx1 < var9; idx1 += inc4, idx2 += inc4 */
+ 0x10000f00, /* DRD1A: var3 = idx0; FN=0 MORE init=0 WS=0 RS=0 */
+ 0x60140002, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=2 RS=2 */
+ 0x0c8cfc8a, /* DRD2B1: *idx2 = EU3(); EU3(*idx2,var10) */
+ 0xd8988240, /* LCDEXT: idx1 = idx1; idx1 > var9; idx1 += inc0 */
+ 0xf845e011, /* LCDEXT: idx2 = *(idx0 + var00000015); ; idx2 += inc2 */
+ 0xb845e00a, /* LCD: idx3 = *(idx0 + var00000019); ; idx3 += inc1 */
+ 0x0bfecf90, /* DRD1A: *idx3 = *idx2; FN=0 TFD init=31 WS=3 RS=3 */
+ 0x9898802d, /* LCD: idx1 = idx1; idx1 once var0; idx1 += inc5 */
+ 0x64000005, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=5 INT EXT init=0 WS=0 RS=0 */
+ 0x0c0cf849, /* DRD2B1: *idx0 = EU3(); EU3(idx1,var9) */
+ 0x000001f8, /* NOP */
+
+ /* VAR[9]-VAR[14] */
+ 0x40000000,
+ 0x7fff7fff,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+
+ /* INC[0]-INC[6] */
+ 0x40000000,
+ 0xe0000000,
+ 0xe0000000,
+ 0xa000000c,
+ 0x20000000,
+ 0x00000000,
+ 0x00000000,
+};
+
diff --git a/arch/powerpc/sysdev/bestcomm/bcom_fec_rx_task.c b/arch/powerpc/sysdev/bestcomm/bcom_fec_rx_task.c
new file mode 100644
index 000000000000..a1ad6a02fcef
--- /dev/null
+++ b/arch/powerpc/sysdev/bestcomm/bcom_fec_rx_task.c
@@ -0,0 +1,78 @@
+/*
+ * Bestcomm FEC RX task microcode
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Automatically created based on BestCommAPI-2.2/code_dma/image_rtos1/dma_image.hex
+ * on Tue Mar 22 11:19:38 2005 GMT
+ */
+
+#include <asm/types.h>
+
+/*
+ * The header consists of the following fields:
+ * u32 magic;
+ * u8 desc_size;
+ * u8 var_size;
+ * u8 inc_size;
+ * u8 first_var;
+ * u8 reserved[8];
+ *
+ * The size fields contain the number of 32-bit words.
+ */
+
+u32 bcom_fec_rx_task[] = {
+ /* header */
+ 0x4243544b,
+ 0x18060709,
+ 0x00000000,
+ 0x00000000,
+
+ /* Task descriptors */
+ 0x808220e3, /* LCD: idx0 = var1, idx1 = var4; idx1 <= var3; idx0 += inc4, idx1 += inc3 */
+ 0x10601010, /* DRD1A: var4 = var2; FN=0 MORE init=3 WS=0 RS=0 */
+ 0xb8800264, /* LCD: idx2 = *idx1, idx3 = var0; idx2 < var9; idx2 += inc4, idx3 += inc4 */
+ 0x10001308, /* DRD1A: var4 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
+ 0x60140002, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=2 RS=2 */
+ 0x0cccfcca, /* DRD2B1: *idx3 = EU3(); EU3(*idx3,var10) */
+ 0x80004000, /* LCDEXT: idx2 = 0x00000000; ; */
+ 0xb8c58029, /* LCD: idx3 = *(idx1 + var00000015); idx3 once var0; idx3 += inc5 */
+ 0x60000002, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=0 RS=0 */
+ 0x088cf8cc, /* DRD2B1: idx2 = EU3(); EU3(idx3,var12) */
+ 0x991982f2, /* LCD: idx2 = idx2, idx3 = idx3; idx2 > var11; idx2 += inc6, idx3 += inc2 */
+ 0x006acf80, /* DRD1A: *idx3 = *idx0; FN=0 init=3 WS=1 RS=1 */
+ 0x80004000, /* LCDEXT: idx2 = 0x00000000; ; */
+ 0x9999802d, /* LCD: idx3 = idx3; idx3 once var0; idx3 += inc5 */
+ 0x70000002, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */
+ 0x034cfc4e, /* DRD2B1: var13 = EU3(); EU3(*idx1,var14) */
+ 0x00008868, /* DRD1A: idx2 = var13; FN=0 init=0 WS=0 RS=0 */
+ 0x99198341, /* LCD: idx2 = idx2, idx3 = idx3; idx2 > var13; idx2 += inc0, idx3 += inc1 */
+ 0x007ecf80, /* DRD1A: *idx3 = *idx0; FN=0 init=3 WS=3 RS=3 */
+ 0x99198272, /* LCD: idx2 = idx2, idx3 = idx3; idx2 > var9; idx2 += inc6, idx3 += inc2 */
+ 0x046acf80, /* DRD1A: *idx3 = *idx0; FN=0 INT init=3 WS=1 RS=1 */
+ 0x9819002d, /* LCD: idx2 = idx0; idx2 once var0; idx2 += inc5 */
+ 0x0060c790, /* DRD1A: *idx1 = *idx2; FN=0 init=3 WS=0 RS=0 */
+ 0x000001f8, /* NOP */
+
+ /* VAR[9]-VAR[14] */
+ 0x40000000,
+ 0x7fff7fff,
+ 0x00000000,
+ 0x00000003,
+ 0x40000008,
+ 0x43ffffff,
+
+ /* INC[0]-INC[6] */
+ 0x40000000,
+ 0xe0000000,
+ 0xe0000000,
+ 0xa0000008,
+ 0x20000000,
+ 0x00000000,
+ 0x4000ffff,
+};
+
diff --git a/arch/powerpc/sysdev/bestcomm/bcom_fec_tx_task.c b/arch/powerpc/sysdev/bestcomm/bcom_fec_tx_task.c
new file mode 100644
index 000000000000..b1c495c3a65a
--- /dev/null
+++ b/arch/powerpc/sysdev/bestcomm/bcom_fec_tx_task.c
@@ -0,0 +1,91 @@
+/*
+ * Bestcomm FEC TX task microcode
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Automatically created based on BestCommAPI-2.2/code_dma/image_rtos1/dma_image.hex
+ * on Tue Mar 22 11:19:29 2005 GMT
+ */
+
+#include <asm/types.h>
+
+/*
+ * The header consists of the following fields:
+ * u32 magic;
+ * u8 desc_size;
+ * u8 var_size;
+ * u8 inc_size;
+ * u8 first_var;
+ * u8 reserved[8];
+ *
+ * The size fields contain the number of 32-bit words.
+ */
+
+u32 bcom_fec_tx_task[] = {
+ /* header */
+ 0x4243544b,
+ 0x2407070d,
+ 0x00000000,
+ 0x00000000,
+
+ /* Task descriptors */
+ 0x8018001b, /* LCD: idx0 = var0; idx0 <= var0; idx0 += inc3 */
+ 0x60000005, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=5 EXT init=0 WS=0 RS=0 */
+ 0x01ccfc0d, /* DRD2B1: var7 = EU3(); EU3(*idx0,var13) */
+ 0x8082a123, /* LCD: idx0 = var1, idx1 = var5; idx1 <= var4; idx0 += inc4, idx1 += inc3 */
+ 0x10801418, /* DRD1A: var5 = var3; FN=0 MORE init=4 WS=0 RS=0 */
+ 0xf88103a4, /* LCDEXT: idx2 = *idx1, idx3 = var2; idx2 < var14; idx2 += inc4, idx3 += inc4 */
+ 0x801a6024, /* LCD: idx4 = var0; ; idx4 += inc4 */
+ 0x10001708, /* DRD1A: var5 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
+ 0x60140002, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=2 RS=2 */
+ 0x0cccfccf, /* DRD2B1: *idx3 = EU3(); EU3(*idx3,var15) */
+ 0x991a002c, /* LCD: idx2 = idx2, idx3 = idx4; idx2 once var0; idx2 += inc5, idx3 += inc4 */
+ 0x70000002, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */
+ 0x024cfc4d, /* DRD2B1: var9 = EU3(); EU3(*idx1,var13) */
+ 0x60000003, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=3 EXT init=0 WS=0 RS=0 */
+ 0x0cccf247, /* DRD2B1: *idx3 = EU3(); EU3(var9,var7) */
+ 0x80004000, /* LCDEXT: idx2 = 0x00000000; ; */
+ 0xb8c80029, /* LCD: idx3 = *(idx1 + var0000001a); idx3 once var0; idx3 += inc5 */
+ 0x70000002, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */
+ 0x088cf8d1, /* DRD2B1: idx2 = EU3(); EU3(idx3,var17) */
+ 0x00002f10, /* DRD1A: var11 = idx2; FN=0 init=0 WS=0 RS=0 */
+ 0x99198432, /* LCD: idx2 = idx2, idx3 = idx3; idx2 > var16; idx2 += inc6, idx3 += inc2 */
+ 0x008ac398, /* DRD1A: *idx0 = *idx3; FN=0 init=4 WS=1 RS=1 */
+ 0x80004000, /* LCDEXT: idx2 = 0x00000000; ; */
+ 0x9999802d, /* LCD: idx3 = idx3; idx3 once var0; idx3 += inc5 */
+ 0x70000002, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */
+ 0x048cfc53, /* DRD2B1: var18 = EU3(); EU3(*idx1,var19) */
+ 0x60000008, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=8 EXT init=0 WS=0 RS=0 */
+ 0x088cf48b, /* DRD2B1: idx2 = EU3(); EU3(var18,var11) */
+ 0x99198481, /* LCD: idx2 = idx2, idx3 = idx3; idx2 > var18; idx2 += inc0, idx3 += inc1 */
+ 0x009ec398, /* DRD1A: *idx0 = *idx3; FN=0 init=4 WS=3 RS=3 */
+ 0x991983b2, /* LCD: idx2 = idx2, idx3 = idx3; idx2 > var14; idx2 += inc6, idx3 += inc2 */
+ 0x088ac398, /* DRD1A: *idx0 = *idx3; FN=0 TFD init=4 WS=1 RS=1 */
+ 0x9919002d, /* LCD: idx2 = idx2; idx2 once var0; idx2 += inc5 */
+ 0x60000005, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=5 EXT init=0 WS=0 RS=0 */
+ 0x0c4cf88e, /* DRD2B1: *idx1 = EU3(); EU3(idx2,var14) */
+ 0x000001f8, /* NOP */
+
+ /* VAR[13]-VAR[19] */
+ 0x0c000000,
+ 0x40000000,
+ 0x7fff7fff,
+ 0x00000000,
+ 0x00000003,
+ 0x40000004,
+ 0x43ffffff,
+
+ /* INC[0]-INC[6] */
+ 0x40000000,
+ 0xe0000000,
+ 0xe0000000,
+ 0xa0000008,
+ 0x20000000,
+ 0x00000000,
+ 0x4000ffff,
+};
+
diff --git a/arch/powerpc/sysdev/bestcomm/bcom_gen_bd_rx_task.c b/arch/powerpc/sysdev/bestcomm/bcom_gen_bd_rx_task.c
new file mode 100644
index 000000000000..efee022b0256
--- /dev/null
+++ b/arch/powerpc/sysdev/bestcomm/bcom_gen_bd_rx_task.c
@@ -0,0 +1,63 @@
+/*
+ * Bestcomm GenBD RX task microcode
+ *
+ * Copyright (C) 2006 AppSpec Computer Technologies Corp.
+ * Jeff Gibbons <jeff.gibbons@appspec.com>
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Based on BestCommAPI-2.2/code_dma/image_rtos1/dma_image.hex
+ * on Tue Mar 4 10:14:12 2006 GMT
+ *
+ */
+
+#include <asm/types.h>
+
+/*
+ * The header consists of the following fields:
+ * u32 magic;
+ * u8 desc_size;
+ * u8 var_size;
+ * u8 inc_size;
+ * u8 first_var;
+ * u8 reserved[8];
+ *
+ * The size fields contain the number of 32-bit words.
+ */
+
+u32 bcom_gen_bd_rx_task[] = {
+ /* header */
+ 0x4243544b,
+ 0x0d020409,
+ 0x00000000,
+ 0x00000000,
+
+ /* Task descriptors */
+ 0x808220da, /* LCD: idx0 = var1, idx1 = var4; idx1 <= var3; idx0 += inc3, idx1 += inc2 */
+ 0x13e01010, /* DRD1A: var4 = var2; FN=0 MORE init=31 WS=0 RS=0 */
+ 0xb880025b, /* LCD: idx2 = *idx1, idx3 = var0; idx2 < var9; idx2 += inc3, idx3 += inc3 */
+ 0x10001308, /* DRD1A: var4 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
+ 0x60140002, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=2 RS=2 */
+ 0x0cccfcca, /* DRD2B1: *idx3 = EU3(); EU3(*idx3,var10) */
+ 0xd9190240, /* LCDEXT: idx2 = idx2; idx2 > var9; idx2 += inc0 */
+ 0xb8c5e009, /* LCD: idx3 = *(idx1 + var00000015); ; idx3 += inc1 */
+ 0x07fecf80, /* DRD1A: *idx3 = *idx0; FN=0 INT init=31 WS=3 RS=3 */
+ 0x99190024, /* LCD: idx2 = idx2; idx2 once var0; idx2 += inc4 */
+ 0x60000005, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=5 EXT init=0 WS=0 RS=0 */
+ 0x0c4cf889, /* DRD2B1: *idx1 = EU3(); EU3(idx2,var9) */
+ 0x000001f8, /* NOP */
+
+ /* VAR[9]-VAR[10] */
+ 0x40000000,
+ 0x7fff7fff,
+
+ /* INC[0]-INC[3] */
+ 0x40000000,
+ 0xe0000000,
+ 0xa0000008,
+ 0x20000000,
+};
+
diff --git a/arch/powerpc/sysdev/bestcomm/bcom_gen_bd_tx_task.c b/arch/powerpc/sysdev/bestcomm/bcom_gen_bd_tx_task.c
new file mode 100644
index 000000000000..c605aa42ecbb
--- /dev/null
+++ b/arch/powerpc/sysdev/bestcomm/bcom_gen_bd_tx_task.c
@@ -0,0 +1,69 @@
+/*
+ * Bestcomm GenBD TX task microcode
+ *
+ * Copyright (C) 2006 AppSpec Computer Technologies Corp.
+ * Jeff Gibbons <jeff.gibbons@appspec.com>
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Based on BestCommAPI-2.2/code_dma/image_rtos1/dma_image.hex
+ * on Tue Mar 4 10:14:12 2006 GMT
+ *
+ */
+
+#include <asm/types.h>
+
+/*
+ * The header consists of the following fields:
+ * u32 magic;
+ * u8 desc_size;
+ * u8 var_size;
+ * u8 inc_size;
+ * u8 first_var;
+ * u8 reserved[8];
+ *
+ * The size fields contain the number of 32-bit words.
+ */
+
+u32 bcom_gen_bd_tx_task[] = {
+ /* header */
+ 0x4243544b,
+ 0x0f040609,
+ 0x00000000,
+ 0x00000000,
+
+ /* Task descriptors */
+ 0x800220e3, /* LCD: idx0 = var0, idx1 = var4; idx1 <= var3; idx0 += inc4, idx1 += inc3 */
+ 0x13e01010, /* DRD1A: var4 = var2; FN=0 MORE init=31 WS=0 RS=0 */
+ 0xb8808264, /* LCD: idx2 = *idx1, idx3 = var1; idx2 < var9; idx2 += inc4, idx3 += inc4 */
+ 0x10001308, /* DRD1A: var4 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
+ 0x60140002, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=2 RS=2 */
+ 0x0cccfcca, /* DRD2B1: *idx3 = EU3(); EU3(*idx3,var10) */
+ 0xd9190300, /* LCDEXT: idx2 = idx2; idx2 > var12; idx2 += inc0 */
+ 0xb8c5e009, /* LCD: idx3 = *(idx1 + var00000015); ; idx3 += inc1 */
+ 0x03fec398, /* DRD1A: *idx0 = *idx3; FN=0 init=31 WS=3 RS=3 */
+ 0x9919826a, /* LCD: idx2 = idx2, idx3 = idx3; idx2 > var9; idx2 += inc5, idx3 += inc2 */
+ 0x0feac398, /* DRD1A: *idx0 = *idx3; FN=0 TFD INT init=31 WS=1 RS=1 */
+ 0x99190036, /* LCD: idx2 = idx2; idx2 once var0; idx2 += inc6 */
+ 0x60000005, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=5 EXT init=0 WS=0 RS=0 */
+ 0x0c4cf889, /* DRD2B1: *idx1 = EU3(); EU3(idx2,var9) */
+ 0x000001f8, /* NOP */
+
+ /* VAR[9]-VAR[12] */
+ 0x40000000,
+ 0x7fff7fff,
+ 0x00000000,
+ 0x40000004,
+
+ /* INC[0]-INC[5] */
+ 0x40000000,
+ 0xe0000000,
+ 0xe0000000,
+ 0xa0000008,
+ 0x20000000,
+ 0x4000ffff,
+};
+
diff --git a/arch/powerpc/sysdev/bestcomm/bestcomm.c b/arch/powerpc/sysdev/bestcomm/bestcomm.c
new file mode 100644
index 000000000000..740ad73ce5cc
--- /dev/null
+++ b/arch/powerpc/sysdev/bestcomm/bestcomm.c
@@ -0,0 +1,531 @@
+/*
+ * Driver for MPC52xx processor BestComm peripheral controller
+ *
+ *
+ * Copyright (C) 2006-2007 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2005 Varma Electronics Oy,
+ * ( by Andrey Volkov <avolkov@varma-el.com> )
+ * Copyright (C) 2003-2004 MontaVista, Software, Inc.
+ * ( by Dale Farnsworth <dfarnsworth@mvista.com> )
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mpc52xx.h>
+
+#include "sram.h"
+#include "bestcomm_priv.h"
+#include "bestcomm.h"
+
+#define DRIVER_NAME "bestcomm-core"
+
+
+struct bcom_engine *bcom_eng = NULL;
+EXPORT_SYMBOL_GPL(bcom_eng); /* needed for inline functions */
+
+
+/* ======================================================================== */
+/* Public and private API */
+/* ======================================================================== */
+
+/* Private API */
+
+struct bcom_task *
+bcom_task_alloc(int bd_count, int bd_size, int priv_size)
+{
+ int i, tasknum = -1;
+ struct bcom_task *tsk;
+
+ /* Get and reserve a task num */
+ spin_lock(&bcom_eng->lock);
+
+ for (i=0; i<BCOM_MAX_TASKS; i++)
+ if (!bcom_eng->tdt[i].stop) { /* we use stop as a marker */
+ bcom_eng->tdt[i].stop = 0xfffffffful; /* dummy addr */
+ tasknum = i;
+ break;
+ }
+
+ spin_unlock(&bcom_eng->lock);
+
+ if (tasknum < 0)
+ return NULL;
+
+ /* Allocate our structure */
+ tsk = kzalloc(sizeof(struct bcom_task) + priv_size, GFP_KERNEL);
+ if (!tsk)
+ goto error;
+
+ tsk->tasknum = tasknum;
+ if (priv_size)
+ tsk->priv = (void*)tsk + sizeof(struct bcom_task);
+
+ /* Get IRQ of that task */
+ tsk->irq = irq_of_parse_and_map(bcom_eng->ofnode, tsk->tasknum);
+ if (tsk->irq == NO_IRQ)
+ goto error;
+
+ /* Init the BDs, if needed */
+ if (bd_count) {
+ tsk->cookie = kmalloc(sizeof(void*) * bd_count, GFP_KERNEL);
+ if (!tsk->cookie)
+ goto error;
+
+ tsk->bd = bcom_sram_alloc(bd_count * bd_size, 4, &tsk->bd_pa);
+ if (!tsk->bd)
+ goto error;
+ memset(tsk->bd, 0x00, bd_count * bd_size);
+
+ tsk->num_bd = bd_count;
+ tsk->bd_size = bd_size;
+ }
+
+ return tsk;
+
+error:
+ if (tsk) {
+ if (tsk->irq != NO_IRQ)
+ irq_dispose_mapping(tsk->irq);
+ bcom_sram_free(tsk->bd);
+ kfree(tsk->cookie);
+ kfree(tsk);
+ }
+
+ bcom_eng->tdt[tasknum].stop = 0;
+
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(bcom_task_alloc);
+
+void
+bcom_task_free(struct bcom_task *tsk)
+{
+ /* Stop the task */
+ bcom_disable_task(tsk->tasknum);
+
+ /* Clear TDT */
+ bcom_eng->tdt[tsk->tasknum].start = 0;
+ bcom_eng->tdt[tsk->tasknum].stop = 0;
+
+ /* Free everything */
+ irq_dispose_mapping(tsk->irq);
+ bcom_sram_free(tsk->bd);
+ kfree(tsk->cookie);
+ kfree(tsk);
+}
+EXPORT_SYMBOL_GPL(bcom_task_free);
+
+int
+bcom_load_image(int task, u32 *task_image)
+{
+ struct bcom_task_header *hdr = (struct bcom_task_header *)task_image;
+ struct bcom_tdt *tdt;
+ u32 *desc, *var, *inc;
+ u32 *desc_src, *var_src, *inc_src;
+
+ /* Safety checks */
+ if (hdr->magic != BCOM_TASK_MAGIC) {
+ printk(KERN_ERR DRIVER_NAME
+ ": Trying to load invalid microcode\n");
+ return -EINVAL;
+ }
+
+ if ((task < 0) || (task >= BCOM_MAX_TASKS)) {
+ printk(KERN_ERR DRIVER_NAME
+ ": Trying to load invalid task %d\n", task);
+ return -EINVAL;
+ }
+
+ /* Initial load or reload */
+ tdt = &bcom_eng->tdt[task];
+
+ if (tdt->start) {
+ desc = bcom_task_desc(task);
+ if (hdr->desc_size != bcom_task_num_descs(task)) {
+ printk(KERN_ERR DRIVER_NAME
+ ": Trying to reload wrong task image "
+ "(%d size %d/%d)!\n",
+ task,
+ hdr->desc_size,
+ bcom_task_num_descs(task));
+ return -EINVAL;
+ }
+ } else {
+ phys_addr_t start_pa;
+
+ desc = bcom_sram_alloc(hdr->desc_size * sizeof(u32), 4, &start_pa);
+ if (!desc)
+ return -ENOMEM;
+
+ tdt->start = start_pa;
+ tdt->stop = start_pa + ((hdr->desc_size-1) * sizeof(u32));
+ }
+
+ var = bcom_task_var(task);
+ inc = bcom_task_inc(task);
+
+ /* Clear & copy */
+ memset(var, 0x00, BCOM_VAR_SIZE);
+ memset(inc, 0x00, BCOM_INC_SIZE);
+
+ desc_src = (u32 *)(hdr + 1);
+ var_src = desc_src + hdr->desc_size;
+ inc_src = var_src + hdr->var_size;
+
+ memcpy(desc, desc_src, hdr->desc_size * sizeof(u32));
+ memcpy(var + hdr->first_var, var_src, hdr->var_size * sizeof(u32));
+ memcpy(inc, inc_src, hdr->inc_size * sizeof(u32));
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(bcom_load_image);
+
+void
+bcom_set_initiator(int task, int initiator)
+{
+ int i;
+ int num_descs;
+ u32 *desc;
+ int next_drd_has_initiator;
+
+ bcom_set_tcr_initiator(task, initiator);
+
+ /* Just setting tcr is apparently not enough due to some problem */
+ /* with it. So we just go thru all the microcode and replace in */
+ /* the DRD directly */
+
+ desc = bcom_task_desc(task);
+ next_drd_has_initiator = 1;
+ num_descs = bcom_task_num_descs(task);
+
+ for (i=0; i<num_descs; i++, desc++) {
+ if (!bcom_desc_is_drd(*desc))
+ continue;
+ if (next_drd_has_initiator)
+ if (bcom_desc_initiator(*desc) != BCOM_INITIATOR_ALWAYS)
+ bcom_set_desc_initiator(desc, initiator);
+ next_drd_has_initiator = !bcom_drd_is_extended(*desc);
+ }
+}
+EXPORT_SYMBOL_GPL(bcom_set_initiator);
+
+
+/* Public API */
+
+void
+bcom_enable(struct bcom_task *tsk)
+{
+ bcom_enable_task(tsk->tasknum);
+}
+EXPORT_SYMBOL_GPL(bcom_enable);
+
+void
+bcom_disable(struct bcom_task *tsk)
+{
+ bcom_disable_task(tsk->tasknum);
+}
+EXPORT_SYMBOL_GPL(bcom_disable);
+
+
+/* ======================================================================== */
+/* Engine init/cleanup */
+/* ======================================================================== */
+
+/* Function Descriptor table */
+/* this will need to be updated if Freescale changes their task code FDT */
+static u32 fdt_ops[] = {
+ 0xa0045670, /* FDT[48] - load_acc() */
+ 0x80045670, /* FDT[49] - unload_acc() */
+ 0x21800000, /* FDT[50] - and() */
+ 0x21e00000, /* FDT[51] - or() */
+ 0x21500000, /* FDT[52] - xor() */
+ 0x21400000, /* FDT[53] - andn() */
+ 0x21500000, /* FDT[54] - not() */
+ 0x20400000, /* FDT[55] - add() */
+ 0x20500000, /* FDT[56] - sub() */
+ 0x20800000, /* FDT[57] - lsh() */
+ 0x20a00000, /* FDT[58] - rsh() */
+ 0xc0170000, /* FDT[59] - crc8() */
+ 0xc0145670, /* FDT[60] - crc16() */
+ 0xc0345670, /* FDT[61] - crc32() */
+ 0xa0076540, /* FDT[62] - endian32() */
+ 0xa0000760, /* FDT[63] - endian16() */
+};
+
+
+static int __devinit
+bcom_engine_init(void)
+{
+ int task;
+ phys_addr_t tdt_pa, ctx_pa, var_pa, fdt_pa;
+ unsigned int tdt_size, ctx_size, var_size, fdt_size;
+ u16 regval;
+
+ /* Allocate & clear SRAM zones for FDT, TDTs, contexts and vars/incs */
+ tdt_size = BCOM_MAX_TASKS * sizeof(struct bcom_tdt);
+ ctx_size = BCOM_MAX_TASKS * BCOM_CTX_SIZE;
+ var_size = BCOM_MAX_TASKS * (BCOM_VAR_SIZE + BCOM_INC_SIZE);
+ fdt_size = BCOM_FDT_SIZE;
+
+ bcom_eng->tdt = bcom_sram_alloc(tdt_size, sizeof(u32), &tdt_pa);
+ bcom_eng->ctx = bcom_sram_alloc(ctx_size, BCOM_CTX_ALIGN, &ctx_pa);
+ bcom_eng->var = bcom_sram_alloc(var_size, BCOM_VAR_ALIGN, &var_pa);
+ bcom_eng->fdt = bcom_sram_alloc(fdt_size, BCOM_FDT_ALIGN, &fdt_pa);
+
+ if (!bcom_eng->tdt || !bcom_eng->ctx || !bcom_eng->var || !bcom_eng->fdt) {
+ printk(KERN_ERR "DMA: SRAM alloc failed in engine init !\n");
+
+ bcom_sram_free(bcom_eng->tdt);
+ bcom_sram_free(bcom_eng->ctx);
+ bcom_sram_free(bcom_eng->var);
+ bcom_sram_free(bcom_eng->fdt);
+
+ return -ENOMEM;
+ }
+
+ memset(bcom_eng->tdt, 0x00, tdt_size);
+ memset(bcom_eng->ctx, 0x00, ctx_size);
+ memset(bcom_eng->var, 0x00, var_size);
+ memset(bcom_eng->fdt, 0x00, fdt_size);
+
+ /* Copy the FDT for the EU#3 */
+ memcpy(&bcom_eng->fdt[48], fdt_ops, sizeof(fdt_ops));
+
+ /* Initialize Task base structure */
+ for (task=0; task<BCOM_MAX_TASKS; task++)
+ {
+ out_be16(&bcom_eng->regs->tcr[task], 0);
+ out_8(&bcom_eng->regs->ipr[task], 0);
+
+ bcom_eng->tdt[task].context = ctx_pa;
+ bcom_eng->tdt[task].var = var_pa;
+ bcom_eng->tdt[task].fdt = fdt_pa;
+
+ var_pa += BCOM_VAR_SIZE + BCOM_INC_SIZE;
+ ctx_pa += BCOM_CTX_SIZE;
+ }
+
+ out_be32(&bcom_eng->regs->taskBar, tdt_pa);
+
+ /* Init 'always' initiator */
+ out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_ALWAYS], BCOM_IPR_ALWAYS);
+
+ /* Disable COMM Bus Prefetch on the original 5200; it's broken */
+ if ((mfspr(SPRN_SVR) & MPC5200_SVR_MASK) == MPC5200_SVR) {
+ regval = in_be16(&bcom_eng->regs->PtdCntrl);
+ out_be16(&bcom_eng->regs->PtdCntrl, regval | 1);
+ }
+
+ /* Init lock */
+ spin_lock_init(&bcom_eng->lock);
+
+ return 0;
+}
+
+static void
+bcom_engine_cleanup(void)
+{
+ int task;
+
+ /* Stop all tasks */
+ for (task=0; task<BCOM_MAX_TASKS; task++)
+ {
+ out_be16(&bcom_eng->regs->tcr[task], 0);
+ out_8(&bcom_eng->regs->ipr[task], 0);
+ }
+
+ out_be32(&bcom_eng->regs->taskBar, 0ul);
+
+ /* Release the SRAM zones */
+ bcom_sram_free(bcom_eng->tdt);
+ bcom_sram_free(bcom_eng->ctx);
+ bcom_sram_free(bcom_eng->var);
+ bcom_sram_free(bcom_eng->fdt);
+}
+
+
+/* ======================================================================== */
+/* OF platform driver */
+/* ======================================================================== */
+
+static int __devinit
+mpc52xx_bcom_probe(struct of_device *op, const struct of_device_id *match)
+{
+ struct device_node *ofn_sram;
+ struct resource res_bcom;
+
+ int rv;
+
+ /* Inform user we're ok so far */
+ printk(KERN_INFO "DMA: MPC52xx BestComm driver\n");
+
+ /* Get the bestcomm node */
+ of_node_get(op->node);
+
+ /* Prepare SRAM */
+ ofn_sram = of_find_compatible_node(NULL, "sram", "mpc5200-sram");
+ if (!ofn_sram) {
+ printk(KERN_ERR DRIVER_NAME ": "
+ "No SRAM found in device tree\n");
+ rv = -ENODEV;
+ goto error_ofput;
+ }
+ rv = bcom_sram_init(ofn_sram, DRIVER_NAME);
+ of_node_put(ofn_sram);
+
+ if (rv) {
+ printk(KERN_ERR DRIVER_NAME ": "
+ "Error in SRAM init\n");
+ goto error_ofput;
+ }
+
+ /* Get a clean struct */
+ bcom_eng = kzalloc(sizeof(struct bcom_engine), GFP_KERNEL);
+ if (!bcom_eng) {
+ printk(KERN_ERR DRIVER_NAME ": "
+ "Can't allocate state structure\n");
+ rv = -ENOMEM;
+ goto error_sramclean;
+ }
+
+ /* Save the node */
+ bcom_eng->ofnode = op->node;
+
+ /* Get, reserve & map io */
+ if (of_address_to_resource(op->node, 0, &res_bcom)) {
+ printk(KERN_ERR DRIVER_NAME ": "
+ "Can't get resource\n");
+ rv = -EINVAL;
+ goto error_sramclean;
+ }
+
+ if (!request_mem_region(res_bcom.start, sizeof(struct mpc52xx_sdma),
+ DRIVER_NAME)) {
+ printk(KERN_ERR DRIVER_NAME ": "
+ "Can't request registers region\n");
+ rv = -EBUSY;
+ goto error_sramclean;
+ }
+
+ bcom_eng->regs_base = res_bcom.start;
+ bcom_eng->regs = ioremap(res_bcom.start, sizeof(struct mpc52xx_sdma));
+ if (!bcom_eng->regs) {
+ printk(KERN_ERR DRIVER_NAME ": "
+ "Can't map registers\n");
+ rv = -ENOMEM;
+ goto error_release;
+ }
+
+ /* Now, do the real init */
+ rv = bcom_engine_init();
+ if (rv)
+ goto error_unmap;
+
+ /* Done ! */
+ printk(KERN_INFO "DMA: MPC52xx BestComm engine @%08lx ok !\n",
+ bcom_eng->regs_base);
+
+ return 0;
+
+ /* Error path */
+error_unmap:
+ iounmap(bcom_eng->regs);
+error_release:
+ release_mem_region(res_bcom.start, sizeof(struct mpc52xx_sdma));
+error_sramclean:
+ kfree(bcom_eng);
+ bcom_sram_cleanup();
+error_ofput:
+ of_node_put(op->node);
+
+ printk(KERN_ERR "DMA: MPC52xx BestComm init failed !\n");
+
+ return rv;
+}
+
+
+static int
+mpc52xx_bcom_remove(struct of_device *op)
+{
+ /* Clean up the engine */
+ bcom_engine_cleanup();
+
+ /* Cleanup SRAM */
+ bcom_sram_cleanup();
+
+ /* Release regs */
+ iounmap(bcom_eng->regs);
+ release_mem_region(bcom_eng->regs_base, sizeof(struct mpc52xx_sdma));
+
+ /* Release the node */
+ of_node_put(bcom_eng->ofnode);
+
+ /* Release memory */
+ kfree(bcom_eng);
+ bcom_eng = NULL;
+
+ return 0;
+}
+
+static struct of_device_id mpc52xx_bcom_of_match[] = {
+ {
+ .type = "dma-controller",
+ .compatible = "mpc5200-bestcomm",
+ },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, mpc52xx_bcom_of_match);
+
+
+static struct of_platform_driver mpc52xx_bcom_of_platform_driver = {
+ .owner = THIS_MODULE,
+ .name = DRIVER_NAME,
+ .match_table = mpc52xx_bcom_of_match,
+ .probe = mpc52xx_bcom_probe,
+ .remove = mpc52xx_bcom_remove,
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+
+/* ======================================================================== */
+/* Module */
+/* ======================================================================== */
+
+static int __init
+mpc52xx_bcom_init(void)
+{
+ return of_register_platform_driver(&mpc52xx_bcom_of_platform_driver);
+}
+
+static void __exit
+mpc52xx_bcom_exit(void)
+{
+ of_unregister_platform_driver(&mpc52xx_bcom_of_platform_driver);
+}
+
+/* If we're not a module, we must make sure everything is setup before */
+/* anyone tries to use us ... that's why we use subsys_initcall instead */
+/* of module_init. */
+subsys_initcall(mpc52xx_bcom_init);
+module_exit(mpc52xx_bcom_exit);
+
+MODULE_DESCRIPTION("Freescale MPC52xx BestComm DMA");
+MODULE_AUTHOR("Sylvain Munaut <tnt@246tNt.com>");
+MODULE_AUTHOR("Andrey Volkov <avolkov@varma-el.com>");
+MODULE_AUTHOR("Dale Farnsworth <dfarnsworth@mvista.com>");
+MODULE_LICENSE("GPL v2");
+
diff --git a/arch/powerpc/sysdev/bestcomm/bestcomm.h b/arch/powerpc/sysdev/bestcomm/bestcomm.h
new file mode 100644
index 000000000000..e802cb4eb69a
--- /dev/null
+++ b/arch/powerpc/sysdev/bestcomm/bestcomm.h
@@ -0,0 +1,190 @@
+/*
+ * Public header for the MPC52xx processor BestComm driver
+ *
+ *
+ * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2005 Varma Electronics Oy,
+ * ( by Andrey Volkov <avolkov@varma-el.com> )
+ * Copyright (C) 2003-2004 MontaVista, Software, Inc.
+ * ( by Dale Farnsworth <dfarnsworth@mvista.com> )
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef __BESTCOMM_H__
+#define __BESTCOMM_H__
+
+struct bcom_bd; /* defined later on ... */
+
+
+/* ======================================================================== */
+/* Generic task managment */
+/* ======================================================================== */
+
+/**
+ * struct bcom_task - Structure describing a loaded BestComm task
+ *
+ * This structure is never built by the driver it self. It's built and
+ * filled the intermediate layer of the BestComm API, the task dependent
+ * support code.
+ *
+ * Most likely you don't need to poke around inside this structure. The
+ * fields are exposed in the header just for the sake of inline functions
+ */
+struct bcom_task {
+ unsigned int tasknum;
+ unsigned int flags;
+ int irq;
+
+ struct bcom_bd *bd;
+ phys_addr_t bd_pa;
+ void **cookie;
+ unsigned short index;
+ unsigned short outdex;
+ unsigned int num_bd;
+ unsigned int bd_size;
+
+ void* priv;
+};
+
+#define BCOM_FLAGS_NONE 0x00000000ul
+#define BCOM_FLAGS_ENABLE_TASK (1ul << 0)
+
+/**
+ * bcom_enable - Enable a BestComm task
+ * @tsk: The BestComm task structure
+ *
+ * This function makes sure the given task is enabled and can be run
+ * by the BestComm engine as needed
+ */
+extern void bcom_enable(struct bcom_task *tsk);
+
+/**
+ * bcom_disable - Disable a BestComm task
+ * @tsk: The BestComm task structure
+ *
+ * This function disable a given task, making sure it's not executed
+ * by the BestComm engine.
+ */
+extern void bcom_disable(struct bcom_task *tsk);
+
+
+/**
+ * bcom_get_task_irq - Returns the irq number of a BestComm task
+ * @tsk: The BestComm task structure
+ */
+static inline int
+bcom_get_task_irq(struct bcom_task *tsk) {
+ return tsk->irq;
+}
+
+/* ======================================================================== */
+/* BD based tasks helpers */
+/* ======================================================================== */
+
+/**
+ * struct bcom_bd - Structure describing a generic BestComm buffer descriptor
+ * @status: The current status of this buffer. Exact meaning depends on the
+ * task type
+ * @data: An array of u32 whose meaning depends on the task type.
+ */
+struct bcom_bd {
+ u32 status;
+ u32 data[1]; /* variable, but at least 1 */
+};
+
+#define BCOM_BD_READY 0x40000000ul
+
+/** _bcom_next_index - Get next input index.
+ * @tsk: pointer to task structure
+ *
+ * Support function; Device drivers should not call this
+ */
+static inline int
+_bcom_next_index(struct bcom_task *tsk)
+{
+ return ((tsk->index + 1) == tsk->num_bd) ? 0 : tsk->index + 1;
+}
+
+/** _bcom_next_outdex - Get next output index.
+ * @tsk: pointer to task structure
+ *
+ * Support function; Device drivers should not call this
+ */
+static inline int
+_bcom_next_outdex(struct bcom_task *tsk)
+{
+ return ((tsk->outdex + 1) == tsk->num_bd) ? 0 : tsk->outdex + 1;
+}
+
+/**
+ * bcom_queue_empty - Checks if a BestComm task BD queue is empty
+ * @tsk: The BestComm task structure
+ */
+static inline int
+bcom_queue_empty(struct bcom_task *tsk)
+{
+ return tsk->index == tsk->outdex;
+}
+
+/**
+ * bcom_queue_full - Checks if a BestComm task BD queue is full
+ * @tsk: The BestComm task structure
+ */
+static inline int
+bcom_queue_full(struct bcom_task *tsk)
+{
+ return tsk->outdex == _bcom_next_index(tsk);
+}
+
+/**
+ * bcom_buffer_done - Checks if a BestComm
+ * @tsk: The BestComm task structure
+ */
+static inline int
+bcom_buffer_done(struct bcom_task *tsk)
+{
+ if (bcom_queue_empty(tsk))
+ return 0;
+ return !(tsk->bd[tsk->outdex].status & BCOM_BD_READY);
+}
+
+/**
+ * bcom_prepare_next_buffer - clear status of next available buffer.
+ * @tsk: The BestComm task structure
+ *
+ * Returns pointer to next buffer descriptor
+ */
+static inline struct bcom_bd *
+bcom_prepare_next_buffer(struct bcom_task *tsk)
+{
+ tsk->bd[tsk->index].status = 0; /* cleanup last status */
+ return &tsk->bd[tsk->index];
+}
+
+static inline void
+bcom_submit_next_buffer(struct bcom_task *tsk, void *cookie)
+{
+ tsk->cookie[tsk->index] = cookie;
+ mb(); /* ensure the bd is really up-to-date */
+ tsk->bd[tsk->index].status |= BCOM_BD_READY;
+ tsk->index = _bcom_next_index(tsk);
+ if (tsk->flags & BCOM_FLAGS_ENABLE_TASK)
+ bcom_enable(tsk);
+}
+
+static inline void *
+bcom_retrieve_buffer(struct bcom_task *tsk, u32 *p_status, struct bcom_bd **p_bd)
+{
+ void *cookie = tsk->cookie[tsk->outdex];
+ if (p_status)
+ *p_status = tsk->bd[tsk->outdex].status;
+ if (p_bd)
+ *p_bd = &tsk->bd[tsk->outdex];
+ tsk->outdex = _bcom_next_outdex(tsk);
+ return cookie;
+}
+
+#endif /* __BESTCOMM_H__ */
diff --git a/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h b/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h
new file mode 100644
index 000000000000..866a2915ef2f
--- /dev/null
+++ b/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h
@@ -0,0 +1,334 @@
+/*
+ * Private header for the MPC52xx processor BestComm driver
+ *
+ * By private, we mean that driver should not use it directly. It's meant
+ * to be used by the BestComm engine driver itself and by the intermediate
+ * layer between the core and the drivers.
+ *
+ * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2005 Varma Electronics Oy,
+ * ( by Andrey Volkov <avolkov@varma-el.com> )
+ * Copyright (C) 2003-2004 MontaVista, Software, Inc.
+ * ( by Dale Farnsworth <dfarnsworth@mvista.com> )
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef __BESTCOMM_PRIV_H__
+#define __BESTCOMM_PRIV_H__
+
+#include <linux/spinlock.h>
+#include <linux/of.h>
+#include <asm/io.h>
+#include <asm/mpc52xx.h>
+
+#include "sram.h"
+
+
+/* ======================================================================== */
+/* Engine related stuff */
+/* ======================================================================== */
+
+/* Zones sizes and needed alignments */
+#define BCOM_MAX_TASKS 16
+#define BCOM_MAX_VAR 24
+#define BCOM_MAX_INC 8
+#define BCOM_MAX_FDT 64
+#define BCOM_MAX_CTX 20
+#define BCOM_CTX_SIZE (BCOM_MAX_CTX * sizeof(u32))
+#define BCOM_CTX_ALIGN 0x100
+#define BCOM_VAR_SIZE (BCOM_MAX_VAR * sizeof(u32))
+#define BCOM_INC_SIZE (BCOM_MAX_INC * sizeof(u32))
+#define BCOM_VAR_ALIGN 0x80
+#define BCOM_FDT_SIZE (BCOM_MAX_FDT * sizeof(u32))
+#define BCOM_FDT_ALIGN 0x100
+
+/**
+ * struct bcom_tdt - Task Descriptor Table Entry
+ *
+ */
+struct bcom_tdt {
+ u32 start;
+ u32 stop;
+ u32 var;
+ u32 fdt;
+ u32 exec_status; /* used internally by BestComm engine */
+ u32 mvtp; /* used internally by BestComm engine */
+ u32 context;
+ u32 litbase;
+};
+
+/**
+ * struct bcom_engine
+ *
+ * This holds all info needed globaly to handle the engine
+ */
+struct bcom_engine {
+ struct device_node *ofnode;
+ struct mpc52xx_sdma __iomem *regs;
+ phys_addr_t regs_base;
+
+ struct bcom_tdt *tdt;
+ u32 *ctx;
+ u32 *var;
+ u32 *fdt;
+
+ spinlock_t lock;
+};
+
+extern struct bcom_engine *bcom_eng;
+
+
+/* ======================================================================== */
+/* Tasks related stuff */
+/* ======================================================================== */
+
+/* Tasks image header */
+#define BCOM_TASK_MAGIC 0x4243544B /* 'BCTK' */
+
+struct bcom_task_header {
+ u32 magic;
+ u8 desc_size; /* the size fields */
+ u8 var_size; /* are given in number */
+ u8 inc_size; /* of 32-bits words */
+ u8 first_var;
+ u8 reserved[8];
+};
+
+/* Descriptors stucture & co */
+#define BCOM_DESC_NOP 0x000001f8
+#define BCOM_LCD_MASK 0x80000000
+#define BCOM_DRD_EXTENDED 0x40000000
+#define BCOM_DRD_INITIATOR_SHIFT 21
+
+/* Tasks pragma */
+#define BCOM_PRAGMA_BIT_RSV 7 /* reserved pragma bit */
+#define BCOM_PRAGMA_BIT_PRECISE_INC 6 /* increment 0=when possible, */
+ /* 1=iter end */
+#define BCOM_PRAGMA_BIT_RST_ERROR_NO 5 /* don't reset errors on */
+ /* task enable */
+#define BCOM_PRAGMA_BIT_PACK 4 /* pack data enable */
+#define BCOM_PRAGMA_BIT_INTEGER 3 /* data alignment */
+ /* 0=frac(msb), 1=int(lsb) */
+#define BCOM_PRAGMA_BIT_SPECREAD 2 /* XLB speculative read */
+#define BCOM_PRAGMA_BIT_CW 1 /* write line buffer enable */
+#define BCOM_PRAGMA_BIT_RL 0 /* read line buffer enable */
+
+ /* Looks like XLB speculative read generates XLB errors when a buffer
+ * is at the end of the physical memory. i.e. when accessing the
+ * lasts words, the engine tries to prefetch the next but there is no
+ * next ...
+ */
+#define BCOM_STD_PRAGMA ((0 << BCOM_PRAGMA_BIT_RSV) | \
+ (0 << BCOM_PRAGMA_BIT_PRECISE_INC) | \
+ (0 << BCOM_PRAGMA_BIT_RST_ERROR_NO) | \
+ (0 << BCOM_PRAGMA_BIT_PACK) | \
+ (0 << BCOM_PRAGMA_BIT_INTEGER) | \
+ (0 << BCOM_PRAGMA_BIT_SPECREAD) | \
+ (1 << BCOM_PRAGMA_BIT_CW) | \
+ (1 << BCOM_PRAGMA_BIT_RL))
+
+#define BCOM_PCI_PRAGMA ((0 << BCOM_PRAGMA_BIT_RSV) | \
+ (0 << BCOM_PRAGMA_BIT_PRECISE_INC) | \
+ (0 << BCOM_PRAGMA_BIT_RST_ERROR_NO) | \
+ (0 << BCOM_PRAGMA_BIT_PACK) | \
+ (1 << BCOM_PRAGMA_BIT_INTEGER) | \
+ (0 << BCOM_PRAGMA_BIT_SPECREAD) | \
+ (1 << BCOM_PRAGMA_BIT_CW) | \
+ (1 << BCOM_PRAGMA_BIT_RL))
+
+#define BCOM_ATA_PRAGMA BCOM_STD_PRAGMA
+#define BCOM_CRC16_DP_0_PRAGMA BCOM_STD_PRAGMA
+#define BCOM_CRC16_DP_1_PRAGMA BCOM_STD_PRAGMA
+#define BCOM_FEC_RX_BD_PRAGMA BCOM_STD_PRAGMA
+#define BCOM_FEC_TX_BD_PRAGMA BCOM_STD_PRAGMA
+#define BCOM_GEN_DP_0_PRAGMA BCOM_STD_PRAGMA
+#define BCOM_GEN_DP_1_PRAGMA BCOM_STD_PRAGMA
+#define BCOM_GEN_DP_2_PRAGMA BCOM_STD_PRAGMA
+#define BCOM_GEN_DP_3_PRAGMA BCOM_STD_PRAGMA
+#define BCOM_GEN_DP_BD_0_PRAGMA BCOM_STD_PRAGMA
+#define BCOM_GEN_DP_BD_1_PRAGMA BCOM_STD_PRAGMA
+#define BCOM_GEN_RX_BD_PRAGMA BCOM_STD_PRAGMA
+#define BCOM_GEN_TX_BD_PRAGMA BCOM_STD_PRAGMA
+#define BCOM_GEN_LPC_PRAGMA BCOM_STD_PRAGMA
+#define BCOM_PCI_RX_PRAGMA BCOM_PCI_PRAGMA
+#define BCOM_PCI_TX_PRAGMA BCOM_PCI_PRAGMA
+
+/* Initiators number */
+#define BCOM_INITIATOR_ALWAYS 0
+#define BCOM_INITIATOR_SCTMR_0 1
+#define BCOM_INITIATOR_SCTMR_1 2
+#define BCOM_INITIATOR_FEC_RX 3
+#define BCOM_INITIATOR_FEC_TX 4
+#define BCOM_INITIATOR_ATA_RX 5
+#define BCOM_INITIATOR_ATA_TX 6
+#define BCOM_INITIATOR_SCPCI_RX 7
+#define BCOM_INITIATOR_SCPCI_TX 8
+#define BCOM_INITIATOR_PSC3_RX 9
+#define BCOM_INITIATOR_PSC3_TX 10
+#define BCOM_INITIATOR_PSC2_RX 11
+#define BCOM_INITIATOR_PSC2_TX 12
+#define BCOM_INITIATOR_PSC1_RX 13
+#define BCOM_INITIATOR_PSC1_TX 14
+#define BCOM_INITIATOR_SCTMR_2 15
+#define BCOM_INITIATOR_SCLPC 16
+#define BCOM_INITIATOR_PSC5_RX 17
+#define BCOM_INITIATOR_PSC5_TX 18
+#define BCOM_INITIATOR_PSC4_RX 19
+#define BCOM_INITIATOR_PSC4_TX 20
+#define BCOM_INITIATOR_I2C2_RX 21
+#define BCOM_INITIATOR_I2C2_TX 22
+#define BCOM_INITIATOR_I2C1_RX 23
+#define BCOM_INITIATOR_I2C1_TX 24
+#define BCOM_INITIATOR_PSC6_RX 25
+#define BCOM_INITIATOR_PSC6_TX 26
+#define BCOM_INITIATOR_IRDA_RX 25
+#define BCOM_INITIATOR_IRDA_TX 26
+#define BCOM_INITIATOR_SCTMR_3 27
+#define BCOM_INITIATOR_SCTMR_4 28
+#define BCOM_INITIATOR_SCTMR_5 29
+#define BCOM_INITIATOR_SCTMR_6 30
+#define BCOM_INITIATOR_SCTMR_7 31
+
+/* Initiators priorities */
+#define BCOM_IPR_ALWAYS 7
+#define BCOM_IPR_SCTMR_0 2
+#define BCOM_IPR_SCTMR_1 2
+#define BCOM_IPR_FEC_RX 6
+#define BCOM_IPR_FEC_TX 5
+#define BCOM_IPR_ATA_RX 4
+#define BCOM_IPR_ATA_TX 3
+#define BCOM_IPR_SCPCI_RX 2
+#define BCOM_IPR_SCPCI_TX 2
+#define BCOM_IPR_PSC3_RX 2
+#define BCOM_IPR_PSC3_TX 2
+#define BCOM_IPR_PSC2_RX 2
+#define BCOM_IPR_PSC2_TX 2
+#define BCOM_IPR_PSC1_RX 2
+#define BCOM_IPR_PSC1_TX 2
+#define BCOM_IPR_SCTMR_2 2
+#define BCOM_IPR_SCLPC 2
+#define BCOM_IPR_PSC5_RX 2
+#define BCOM_IPR_PSC5_TX 2
+#define BCOM_IPR_PSC4_RX 2
+#define BCOM_IPR_PSC4_TX 2
+#define BCOM_IPR_I2C2_RX 2
+#define BCOM_IPR_I2C2_TX 2
+#define BCOM_IPR_I2C1_RX 2
+#define BCOM_IPR_I2C1_TX 2
+#define BCOM_IPR_PSC6_RX 2
+#define BCOM_IPR_PSC6_TX 2
+#define BCOM_IPR_IRDA_RX 2
+#define BCOM_IPR_IRDA_TX 2
+#define BCOM_IPR_SCTMR_3 2
+#define BCOM_IPR_SCTMR_4 2
+#define BCOM_IPR_SCTMR_5 2
+#define BCOM_IPR_SCTMR_6 2
+#define BCOM_IPR_SCTMR_7 2
+
+
+/* ======================================================================== */
+/* API */
+/* ======================================================================== */
+
+extern struct bcom_task *bcom_task_alloc(int bd_count, int bd_size, int priv_size);
+extern void bcom_task_free(struct bcom_task *tsk);
+extern int bcom_load_image(int task, u32 *task_image);
+extern void bcom_set_initiator(int task, int initiator);
+
+
+#define TASK_ENABLE 0x8000
+
+static inline void
+bcom_enable_task(int task)
+{
+ u16 reg;
+ reg = in_be16(&bcom_eng->regs->tcr[task]);
+ out_be16(&bcom_eng->regs->tcr[task], reg | TASK_ENABLE);
+}
+
+static inline void
+bcom_disable_task(int task)
+{
+ u16 reg = in_be16(&bcom_eng->regs->tcr[task]);
+ out_be16(&bcom_eng->regs->tcr[task], reg & ~TASK_ENABLE);
+}
+
+
+static inline u32 *
+bcom_task_desc(int task)
+{
+ return bcom_sram_pa2va(bcom_eng->tdt[task].start);
+}
+
+static inline int
+bcom_task_num_descs(int task)
+{
+ return (bcom_eng->tdt[task].stop - bcom_eng->tdt[task].start)/sizeof(u32) + 1;
+}
+
+static inline u32 *
+bcom_task_var(int task)
+{
+ return bcom_sram_pa2va(bcom_eng->tdt[task].var);
+}
+
+static inline u32 *
+bcom_task_inc(int task)
+{
+ return &bcom_task_var(task)[BCOM_MAX_VAR];
+}
+
+
+static inline int
+bcom_drd_is_extended(u32 desc)
+{
+ return (desc) & BCOM_DRD_EXTENDED;
+}
+
+static inline int
+bcom_desc_is_drd(u32 desc)
+{
+ return !(desc & BCOM_LCD_MASK) && desc != BCOM_DESC_NOP;
+}
+
+static inline int
+bcom_desc_initiator(u32 desc)
+{
+ return (desc >> BCOM_DRD_INITIATOR_SHIFT) & 0x1f;
+}
+
+static inline void
+bcom_set_desc_initiator(u32 *desc, int initiator)
+{
+ *desc = (*desc & ~(0x1f << BCOM_DRD_INITIATOR_SHIFT)) |
+ ((initiator & 0x1f) << BCOM_DRD_INITIATOR_SHIFT);
+}
+
+
+static inline void
+bcom_set_task_pragma(int task, int pragma)
+{
+ u32 *fdt = &bcom_eng->tdt[task].fdt;
+ *fdt = (*fdt & ~0xff) | pragma;
+}
+
+static inline void
+bcom_set_task_auto_start(int task, int next_task)
+{
+ u16 __iomem *tcr = &bcom_eng->regs->tcr[task];
+ out_be16(tcr, (in_be16(tcr) & ~0xff) | 0x00c0 | next_task);
+}
+
+static inline void
+bcom_set_tcr_initiator(int task, int initiator)
+{
+ u16 __iomem *tcr = &bcom_eng->regs->tcr[task];
+ out_be16(tcr, (in_be16(tcr) & ~0x1f00) | ((initiator & 0x1f) << 8));
+}
+
+
+#endif /* __BESTCOMM_PRIV_H__ */
+
diff --git a/arch/powerpc/sysdev/bestcomm/fec.c b/arch/powerpc/sysdev/bestcomm/fec.c
new file mode 100644
index 000000000000..957a988d23ea
--- /dev/null
+++ b/arch/powerpc/sysdev/bestcomm/fec.c
@@ -0,0 +1,270 @@
+/*
+ * Bestcomm FEC tasks driver
+ *
+ *
+ * Copyright (C) 2006-2007 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003-2004 MontaVista, Software, Inc.
+ * ( by Dale Farnsworth <dfarnsworth@mvista.com> )
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <asm/io.h>
+
+#include "bestcomm.h"
+#include "bestcomm_priv.h"
+#include "fec.h"
+
+
+/* ======================================================================== */
+/* Task image/var/inc */
+/* ======================================================================== */
+
+/* fec tasks images */
+extern u32 bcom_fec_rx_task[];
+extern u32 bcom_fec_tx_task[];
+
+/* rx task vars that need to be set before enabling the task */
+struct bcom_fec_rx_var {
+ u32 enable; /* (u16*) address of task's control register */
+ u32 fifo; /* (u32*) address of fec's fifo */
+ u32 bd_base; /* (struct bcom_bd*) beginning of ring buffer */
+ u32 bd_last; /* (struct bcom_bd*) end of ring buffer */
+ u32 bd_start; /* (struct bcom_bd*) current bd */
+ u32 buffer_size; /* size of receive buffer */
+};
+
+/* rx task incs that need to be set before enabling the task */
+struct bcom_fec_rx_inc {
+ u16 pad0;
+ s16 incr_bytes;
+ u16 pad1;
+ s16 incr_dst;
+ u16 pad2;
+ s16 incr_dst_ma;
+};
+
+/* tx task vars that need to be set before enabling the task */
+struct bcom_fec_tx_var {
+ u32 DRD; /* (u32*) address of self-modified DRD */
+ u32 fifo; /* (u32*) address of fec's fifo */
+ u32 enable; /* (u16*) address of task's control register */
+ u32 bd_base; /* (struct bcom_bd*) beginning of ring buffer */
+ u32 bd_last; /* (struct bcom_bd*) end of ring buffer */
+ u32 bd_start; /* (struct bcom_bd*) current bd */
+ u32 buffer_size; /* set by uCode for each packet */
+};
+
+/* tx task incs that need to be set before enabling the task */
+struct bcom_fec_tx_inc {
+ u16 pad0;
+ s16 incr_bytes;
+ u16 pad1;
+ s16 incr_src;
+ u16 pad2;
+ s16 incr_src_ma;
+};
+
+/* private structure in the task */
+struct bcom_fec_priv {
+ phys_addr_t fifo;
+ int maxbufsize;
+};
+
+
+/* ======================================================================== */
+/* Task support code */
+/* ======================================================================== */
+
+struct bcom_task *
+bcom_fec_rx_init(int queue_len, phys_addr_t fifo, int maxbufsize)
+{
+ struct bcom_task *tsk;
+ struct bcom_fec_priv *priv;
+
+ tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_fec_bd),
+ sizeof(struct bcom_fec_priv));
+ if (!tsk)
+ return NULL;
+
+ tsk->flags = BCOM_FLAGS_NONE;
+
+ priv = tsk->priv;
+ priv->fifo = fifo;
+ priv->maxbufsize = maxbufsize;
+
+ if (bcom_fec_rx_reset(tsk)) {
+ bcom_task_free(tsk);
+ return NULL;
+ }
+
+ return tsk;
+}
+EXPORT_SYMBOL_GPL(bcom_fec_rx_init);
+
+int
+bcom_fec_rx_reset(struct bcom_task *tsk)
+{
+ struct bcom_fec_priv *priv = tsk->priv;
+ struct bcom_fec_rx_var *var;
+ struct bcom_fec_rx_inc *inc;
+
+ /* Shutdown the task */
+ bcom_disable_task(tsk->tasknum);
+
+ /* Reset the microcode */
+ var = (struct bcom_fec_rx_var *) bcom_task_var(tsk->tasknum);
+ inc = (struct bcom_fec_rx_inc *) bcom_task_inc(tsk->tasknum);
+
+ if (bcom_load_image(tsk->tasknum, bcom_fec_rx_task))
+ return -1;
+
+ var->enable = bcom_eng->regs_base +
+ offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);
+ var->fifo = (u32) priv->fifo;
+ var->bd_base = tsk->bd_pa;
+ var->bd_last = tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);
+ var->bd_start = tsk->bd_pa;
+ var->buffer_size = priv->maxbufsize;
+
+ inc->incr_bytes = -(s16)sizeof(u32); /* These should be in the */
+ inc->incr_dst = sizeof(u32); /* task image, but we stick */
+ inc->incr_dst_ma= sizeof(u8); /* to the official ones */
+
+ /* Reset the BDs */
+ tsk->index = 0;
+ tsk->outdex = 0;
+
+ memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
+
+ /* Configure some stuff */
+ bcom_set_task_pragma(tsk->tasknum, BCOM_FEC_RX_BD_PRAGMA);
+ bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);
+
+ out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_FEC_RX], BCOM_IPR_FEC_RX);
+
+ out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum); /* Clear ints */
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(bcom_fec_rx_reset);
+
+void
+bcom_fec_rx_release(struct bcom_task *tsk)
+{
+ /* Nothing special for the FEC tasks */
+ bcom_task_free(tsk);
+}
+EXPORT_SYMBOL_GPL(bcom_fec_rx_release);
+
+
+
+ /* Return 2nd to last DRD */
+ /* This is an ugly hack, but at least it's only done
+ once at initialization */
+static u32 *self_modified_drd(int tasknum)
+{
+ u32 *desc;
+ int num_descs;
+ int drd_count;
+ int i;
+
+ num_descs = bcom_task_num_descs(tasknum);
+ desc = bcom_task_desc(tasknum) + num_descs - 1;
+ drd_count = 0;
+ for (i=0; i<num_descs; i++, desc--)
+ if (bcom_desc_is_drd(*desc) && ++drd_count == 3)
+ break;
+ return desc;
+}
+
+struct bcom_task *
+bcom_fec_tx_init(int queue_len, phys_addr_t fifo)
+{
+ struct bcom_task *tsk;
+ struct bcom_fec_priv *priv;
+
+ tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_fec_bd),
+ sizeof(struct bcom_fec_priv));
+ if (!tsk)
+ return NULL;
+
+ tsk->flags = BCOM_FLAGS_ENABLE_TASK;
+
+ priv = tsk->priv;
+ priv->fifo = fifo;
+
+ if (bcom_fec_tx_reset(tsk)) {
+ bcom_task_free(tsk);
+ return NULL;
+ }
+
+ return tsk;
+}
+EXPORT_SYMBOL_GPL(bcom_fec_tx_init);
+
+int
+bcom_fec_tx_reset(struct bcom_task *tsk)
+{
+ struct bcom_fec_priv *priv = tsk->priv;
+ struct bcom_fec_tx_var *var;
+ struct bcom_fec_tx_inc *inc;
+
+ /* Shutdown the task */
+ bcom_disable_task(tsk->tasknum);
+
+ /* Reset the microcode */
+ var = (struct bcom_fec_tx_var *) bcom_task_var(tsk->tasknum);
+ inc = (struct bcom_fec_tx_inc *) bcom_task_inc(tsk->tasknum);
+
+ if (bcom_load_image(tsk->tasknum, bcom_fec_tx_task))
+ return -1;
+
+ var->enable = bcom_eng->regs_base +
+ offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);
+ var->fifo = (u32) priv->fifo;
+ var->DRD = bcom_sram_va2pa(self_modified_drd(tsk->tasknum));
+ var->bd_base = tsk->bd_pa;
+ var->bd_last = tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);
+ var->bd_start = tsk->bd_pa;
+
+ inc->incr_bytes = -(s16)sizeof(u32); /* These should be in the */
+ inc->incr_src = sizeof(u32); /* task image, but we stick */
+ inc->incr_src_ma= sizeof(u8); /* to the official ones */
+
+ /* Reset the BDs */
+ tsk->index = 0;
+ tsk->outdex = 0;
+
+ memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
+
+ /* Configure some stuff */
+ bcom_set_task_pragma(tsk->tasknum, BCOM_FEC_TX_BD_PRAGMA);
+ bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);
+
+ out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_FEC_TX], BCOM_IPR_FEC_TX);
+
+ out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum); /* Clear ints */
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(bcom_fec_tx_reset);
+
+void
+bcom_fec_tx_release(struct bcom_task *tsk)
+{
+ /* Nothing special for the FEC tasks */
+ bcom_task_free(tsk);
+}
+EXPORT_SYMBOL_GPL(bcom_fec_tx_release);
+
+
+MODULE_DESCRIPTION("BestComm FEC tasks driver");
+MODULE_AUTHOR("Dale Farnsworth <dfarnsworth@mvista.com>");
+MODULE_LICENSE("GPL v2");
+
diff --git a/arch/powerpc/sysdev/bestcomm/fec.h b/arch/powerpc/sysdev/bestcomm/fec.h
new file mode 100644
index 000000000000..ee565d94d503
--- /dev/null
+++ b/arch/powerpc/sysdev/bestcomm/fec.h
@@ -0,0 +1,61 @@
+/*
+ * Header for Bestcomm FEC tasks driver
+ *
+ *
+ * Copyright (C) 2006-2007 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003-2004 MontaVista, Software, Inc.
+ * ( by Dale Farnsworth <dfarnsworth@mvista.com> )
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef __BESTCOMM_FEC_H__
+#define __BESTCOMM_FEC_H__
+
+
+struct bcom_fec_bd {
+ u32 status;
+ u32 skb_pa;
+};
+
+#define BCOM_FEC_TX_BD_TFD 0x08000000ul /* transmit frame done */
+#define BCOM_FEC_TX_BD_TC 0x04000000ul /* transmit CRC */
+#define BCOM_FEC_TX_BD_ABC 0x02000000ul /* append bad CRC */
+
+#define BCOM_FEC_RX_BD_L 0x08000000ul /* buffer is last in frame */
+#define BCOM_FEC_RX_BD_BC 0x00800000ul /* DA is broadcast */
+#define BCOM_FEC_RX_BD_MC 0x00400000ul /* DA is multicast and not broadcast */
+#define BCOM_FEC_RX_BD_LG 0x00200000ul /* Rx frame length violation */
+#define BCOM_FEC_RX_BD_NO 0x00100000ul /* Rx non-octet aligned frame */
+#define BCOM_FEC_RX_BD_CR 0x00040000ul /* Rx CRC error */
+#define BCOM_FEC_RX_BD_OV 0x00020000ul /* overrun */
+#define BCOM_FEC_RX_BD_TR 0x00010000ul /* Rx frame truncated */
+#define BCOM_FEC_RX_BD_LEN_MASK 0x000007fful /* mask for length of received frame */
+#define BCOM_FEC_RX_BD_ERRORS (BCOM_FEC_RX_BD_LG | BCOM_FEC_RX_BD_NO | \
+ BCOM_FEC_RX_BD_CR | BCOM_FEC_RX_BD_OV | BCOM_FEC_RX_BD_TR)
+
+
+extern struct bcom_task *
+bcom_fec_rx_init(int queue_len, phys_addr_t fifo, int maxbufsize);
+
+extern int
+bcom_fec_rx_reset(struct bcom_task *tsk);
+
+extern void
+bcom_fec_rx_release(struct bcom_task *tsk);
+
+
+extern struct bcom_task *
+bcom_fec_tx_init(int queue_len, phys_addr_t fifo);
+
+extern int
+bcom_fec_tx_reset(struct bcom_task *tsk);
+
+extern void
+bcom_fec_tx_release(struct bcom_task *tsk);
+
+
+#endif /* __BESTCOMM_FEC_H__ */
+
diff --git a/arch/powerpc/sysdev/bestcomm/gen_bd.c b/arch/powerpc/sysdev/bestcomm/gen_bd.c
new file mode 100644
index 000000000000..8d33eafbb3f4
--- /dev/null
+++ b/arch/powerpc/sysdev/bestcomm/gen_bd.c
@@ -0,0 +1,260 @@
+/*
+ * Driver for MPC52xx processor BestComm General Buffer Descriptor
+ *
+ * Copyright (C) 2007 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2006 AppSpec Computer Technologies Corp.
+ * Jeff Gibbons <jeff.gibbons@appspec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+
+#include <asm/mpc52xx.h>
+
+#include "bestcomm.h"
+#include "bestcomm_priv.h"
+#include "gen_bd.h"
+
+
+/* ======================================================================== */
+/* Task image/var/inc */
+/* ======================================================================== */
+
+/* gen_bd tasks images */
+extern u32 bcom_gen_bd_rx_task[];
+extern u32 bcom_gen_bd_tx_task[];
+
+/* rx task vars that need to be set before enabling the task */
+struct bcom_gen_bd_rx_var {
+ u32 enable; /* (u16*) address of task's control register */
+ u32 fifo; /* (u32*) address of gen_bd's fifo */
+ u32 bd_base; /* (struct bcom_bd*) beginning of ring buffer */
+ u32 bd_last; /* (struct bcom_bd*) end of ring buffer */
+ u32 bd_start; /* (struct bcom_bd*) current bd */
+ u32 buffer_size; /* size of receive buffer */
+};
+
+/* rx task incs that need to be set before enabling the task */
+struct bcom_gen_bd_rx_inc {
+ u16 pad0;
+ s16 incr_bytes;
+ u16 pad1;
+ s16 incr_dst;
+};
+
+/* tx task vars that need to be set before enabling the task */
+struct bcom_gen_bd_tx_var {
+ u32 fifo; /* (u32*) address of gen_bd's fifo */
+ u32 enable; /* (u16*) address of task's control register */
+ u32 bd_base; /* (struct bcom_bd*) beginning of ring buffer */
+ u32 bd_last; /* (struct bcom_bd*) end of ring buffer */
+ u32 bd_start; /* (struct bcom_bd*) current bd */
+ u32 buffer_size; /* set by uCode for each packet */
+};
+
+/* tx task incs that need to be set before enabling the task */
+struct bcom_gen_bd_tx_inc {
+ u16 pad0;
+ s16 incr_bytes;
+ u16 pad1;
+ s16 incr_src;
+ u16 pad2;
+ s16 incr_src_ma;
+};
+
+/* private structure */
+struct bcom_gen_bd_priv {
+ phys_addr_t fifo;
+ int initiator;
+ int ipr;
+ int maxbufsize;
+};
+
+
+/* ======================================================================== */
+/* Task support code */
+/* ======================================================================== */
+
+struct bcom_task *
+bcom_gen_bd_rx_init(int queue_len, phys_addr_t fifo,
+ int initiator, int ipr, int maxbufsize)
+{
+ struct bcom_task *tsk;
+ struct bcom_gen_bd_priv *priv;
+
+ tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_gen_bd),
+ sizeof(struct bcom_gen_bd_priv));
+ if (!tsk)
+ return NULL;
+
+ tsk->flags = BCOM_FLAGS_NONE;
+
+ priv = tsk->priv;
+ priv->fifo = fifo;
+ priv->initiator = initiator;
+ priv->ipr = ipr;
+ priv->maxbufsize = maxbufsize;
+
+ if (bcom_gen_bd_rx_reset(tsk)) {
+ bcom_task_free(tsk);
+ return NULL;
+ }
+
+ return tsk;
+}
+EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_init);
+
+int
+bcom_gen_bd_rx_reset(struct bcom_task *tsk)
+{
+ struct bcom_gen_bd_priv *priv = tsk->priv;
+ struct bcom_gen_bd_rx_var *var;
+ struct bcom_gen_bd_rx_inc *inc;
+
+ /* Shutdown the task */
+ bcom_disable_task(tsk->tasknum);
+
+ /* Reset the microcode */
+ var = (struct bcom_gen_bd_rx_var *) bcom_task_var(tsk->tasknum);
+ inc = (struct bcom_gen_bd_rx_inc *) bcom_task_inc(tsk->tasknum);
+
+ if (bcom_load_image(tsk->tasknum, bcom_gen_bd_rx_task))
+ return -1;
+
+ var->enable = bcom_eng->regs_base +
+ offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);
+ var->fifo = (u32) priv->fifo;
+ var->bd_base = tsk->bd_pa;
+ var->bd_last = tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);
+ var->bd_start = tsk->bd_pa;
+ var->buffer_size = priv->maxbufsize;
+
+ inc->incr_bytes = -(s16)sizeof(u32);
+ inc->incr_dst = sizeof(u32);
+
+ /* Reset the BDs */
+ tsk->index = 0;
+ tsk->outdex = 0;
+
+ memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
+
+ /* Configure some stuff */
+ bcom_set_task_pragma(tsk->tasknum, BCOM_GEN_RX_BD_PRAGMA);
+ bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);
+
+ out_8(&bcom_eng->regs->ipr[priv->initiator], priv->ipr);
+ bcom_set_initiator(tsk->tasknum, priv->initiator);
+
+ out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum); /* Clear ints */
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_reset);
+
+void
+bcom_gen_bd_rx_release(struct bcom_task *tsk)
+{
+ /* Nothing special for the GenBD tasks */
+ bcom_task_free(tsk);
+}
+EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_release);
+
+
+extern struct bcom_task *
+bcom_gen_bd_tx_init(int queue_len, phys_addr_t fifo,
+ int initiator, int ipr)
+{
+ struct bcom_task *tsk;
+ struct bcom_gen_bd_priv *priv;
+
+ tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_gen_bd),
+ sizeof(struct bcom_gen_bd_priv));
+ if (!tsk)
+ return NULL;
+
+ tsk->flags = BCOM_FLAGS_NONE;
+
+ priv = tsk->priv;
+ priv->fifo = fifo;
+ priv->initiator = initiator;
+ priv->ipr = ipr;
+
+ if (bcom_gen_bd_tx_reset(tsk)) {
+ bcom_task_free(tsk);
+ return NULL;
+ }
+
+ return tsk;
+}
+EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_init);
+
+int
+bcom_gen_bd_tx_reset(struct bcom_task *tsk)
+{
+ struct bcom_gen_bd_priv *priv = tsk->priv;
+ struct bcom_gen_bd_tx_var *var;
+ struct bcom_gen_bd_tx_inc *inc;
+
+ /* Shutdown the task */
+ bcom_disable_task(tsk->tasknum);
+
+ /* Reset the microcode */
+ var = (struct bcom_gen_bd_tx_var *) bcom_task_var(tsk->tasknum);
+ inc = (struct bcom_gen_bd_tx_inc *) bcom_task_inc(tsk->tasknum);
+
+ if (bcom_load_image(tsk->tasknum, bcom_gen_bd_tx_task))
+ return -1;
+
+ var->enable = bcom_eng->regs_base +
+ offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);
+ var->fifo = (u32) priv->fifo;
+ var->bd_base = tsk->bd_pa;
+ var->bd_last = tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);
+ var->bd_start = tsk->bd_pa;
+
+ inc->incr_bytes = -(s16)sizeof(u32);
+ inc->incr_src = sizeof(u32);
+ inc->incr_src_ma = sizeof(u8);
+
+ /* Reset the BDs */
+ tsk->index = 0;
+ tsk->outdex = 0;
+
+ memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
+
+ /* Configure some stuff */
+ bcom_set_task_pragma(tsk->tasknum, BCOM_GEN_TX_BD_PRAGMA);
+ bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);
+
+ out_8(&bcom_eng->regs->ipr[priv->initiator], priv->ipr);
+ bcom_set_initiator(tsk->tasknum, priv->initiator);
+
+ out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum); /* Clear ints */
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_reset);
+
+void
+bcom_gen_bd_tx_release(struct bcom_task *tsk)
+{
+ /* Nothing special for the GenBD tasks */
+ bcom_task_free(tsk);
+}
+EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_release);
+
+
+MODULE_DESCRIPTION("BestComm General Buffer Descriptor tasks driver");
+MODULE_AUTHOR("Jeff Gibbons <jeff.gibbons@appspec.com>");
+MODULE_LICENSE("GPL v2");
+
diff --git a/arch/powerpc/sysdev/bestcomm/gen_bd.h b/arch/powerpc/sysdev/bestcomm/gen_bd.h
new file mode 100644
index 000000000000..5b6fa803c6aa
--- /dev/null
+++ b/arch/powerpc/sysdev/bestcomm/gen_bd.h
@@ -0,0 +1,48 @@
+/*
+ * Header for Bestcomm General Buffer Descriptor tasks driver
+ *
+ *
+ * Copyright (C) 2007 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2006 AppSpec Computer Technologies Corp.
+ * Jeff Gibbons <jeff.gibbons@appspec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ *
+ */
+
+#ifndef __BESTCOMM_GEN_BD_H__
+#define __BESTCOMM_GEN_BD_H__
+
+struct bcom_gen_bd {
+ u32 status;
+ u32 buf_pa;
+};
+
+
+extern struct bcom_task *
+bcom_gen_bd_rx_init(int queue_len, phys_addr_t fifo,
+ int initiator, int ipr, int maxbufsize);
+
+extern int
+bcom_gen_bd_rx_reset(struct bcom_task *tsk);
+
+extern void
+bcom_gen_bd_rx_release(struct bcom_task *tsk);
+
+
+extern struct bcom_task *
+bcom_gen_bd_tx_init(int queue_len, phys_addr_t fifo,
+ int initiator, int ipr);
+
+extern int
+bcom_gen_bd_tx_reset(struct bcom_task *tsk);
+
+extern void
+bcom_gen_bd_tx_release(struct bcom_task *tsk);
+
+
+#endif /* __BESTCOMM_GEN_BD_H__ */
+
diff --git a/arch/powerpc/sysdev/bestcomm/sram.c b/arch/powerpc/sysdev/bestcomm/sram.c
new file mode 100644
index 000000000000..99784383a843
--- /dev/null
+++ b/arch/powerpc/sysdev/bestcomm/sram.c
@@ -0,0 +1,177 @@
+/*
+ * Simple memory allocator for on-board SRAM
+ *
+ *
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * Copyright (C) 2005 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/of.h>
+
+#include <asm/io.h>
+#include <asm/mmu.h>
+
+#include "sram.h"
+
+
+/* Struct keeping our 'state' */
+struct bcom_sram *bcom_sram = NULL;
+EXPORT_SYMBOL_GPL(bcom_sram); /* needed for inline functions */
+
+
+/* ======================================================================== */
+/* Public API */
+/* ======================================================================== */
+/* DO NOT USE in interrupts, if needed in irq handler, we should use the
+ _irqsave version of the spin_locks */
+
+int bcom_sram_init(struct device_node *sram_node, char *owner)
+{
+ int rv;
+ const u32 *regaddr_p;
+ u64 regaddr64, size64;
+ unsigned int psize;
+
+ /* Create our state struct */
+ if (bcom_sram) {
+ printk(KERN_ERR "%s: bcom_sram_init: "
+ "Already initialized !\n", owner);
+ return -EBUSY;
+ }
+
+ bcom_sram = kmalloc(sizeof(struct bcom_sram), GFP_KERNEL);
+ if (!bcom_sram) {
+ printk(KERN_ERR "%s: bcom_sram_init: "
+ "Couldn't allocate internal state !\n", owner);
+ return -ENOMEM;
+ }
+
+ /* Get address and size of the sram */
+ regaddr_p = of_get_address(sram_node, 0, &size64, NULL);
+ if (!regaddr_p) {
+ printk(KERN_ERR "%s: bcom_sram_init: "
+ "Invalid device node !\n", owner);
+ rv = -EINVAL;
+ goto error_free;
+ }
+
+ regaddr64 = of_translate_address(sram_node, regaddr_p);
+
+ bcom_sram->base_phys = (phys_addr_t) regaddr64;
+ bcom_sram->size = (unsigned int) size64;
+
+ /* Request region */
+ if (!request_mem_region(bcom_sram->base_phys, bcom_sram->size, owner)) {
+ printk(KERN_ERR "%s: bcom_sram_init: "
+ "Couldn't request region !\n", owner);
+ rv = -EBUSY;
+ goto error_free;
+ }
+
+ /* Map SRAM */
+ /* sram is not really __iomem */
+ bcom_sram->base_virt = (void*) ioremap(bcom_sram->base_phys, bcom_sram->size);
+
+ if (!bcom_sram->base_virt) {
+ printk(KERN_ERR "%s: bcom_sram_init: "
+ "Map error SRAM zone 0x%08lx (0x%0x)!\n",
+ owner, bcom_sram->base_phys, bcom_sram->size );
+ rv = -ENOMEM;
+ goto error_release;
+ }
+
+ /* Create an rheap (defaults to 32 bits word alignment) */
+ bcom_sram->rh = rh_create(4);
+
+ /* Attach the free zones */
+#if 0
+ /* Currently disabled ... for future use only */
+ reg_addr_p = of_get_property(sram_node, "available", &psize);
+#else
+ regaddr_p = NULL;
+ psize = 0;
+#endif
+
+ if (!regaddr_p || !psize) {
+ /* Attach the whole zone */
+ rh_attach_region(bcom_sram->rh, 0, bcom_sram->size);
+ } else {
+ /* Attach each zone independently */
+ while (psize >= 2 * sizeof(u32)) {
+ phys_addr_t zbase = of_translate_address(sram_node, regaddr_p);
+ rh_attach_region(bcom_sram->rh, zbase - bcom_sram->base_phys, regaddr_p[1]);
+ regaddr_p += 2;
+ psize -= 2 * sizeof(u32);
+ }
+ }
+
+ /* Init our spinlock */
+ spin_lock_init(&bcom_sram->lock);
+
+ return 0;
+
+error_release:
+ release_mem_region(bcom_sram->base_phys, bcom_sram->size);
+error_free:
+ kfree(bcom_sram);
+ bcom_sram = NULL;
+
+ return rv;
+}
+EXPORT_SYMBOL_GPL(bcom_sram_init);
+
+void bcom_sram_cleanup(void)
+{
+ /* Free resources */
+ if (bcom_sram) {
+ rh_destroy(bcom_sram->rh);
+ iounmap((void __iomem *)bcom_sram->base_virt);
+ release_mem_region(bcom_sram->base_phys, bcom_sram->size);
+ kfree(bcom_sram);
+ bcom_sram = NULL;
+ }
+}
+EXPORT_SYMBOL_GPL(bcom_sram_cleanup);
+
+void* bcom_sram_alloc(int size, int align, phys_addr_t *phys)
+{
+ unsigned long offset;
+
+ spin_lock(&bcom_sram->lock);
+ offset = rh_alloc_align(bcom_sram->rh, size, align, NULL);
+ spin_unlock(&bcom_sram->lock);
+
+ if (IS_ERR_VALUE(offset))
+ return NULL;
+
+ *phys = bcom_sram->base_phys + offset;
+ return bcom_sram->base_virt + offset;
+}
+EXPORT_SYMBOL_GPL(bcom_sram_alloc);
+
+void bcom_sram_free(void *ptr)
+{
+ unsigned long offset;
+
+ if (!ptr)
+ return;
+
+ offset = ptr - bcom_sram->base_virt;
+
+ spin_lock(&bcom_sram->lock);
+ rh_free(bcom_sram->rh, offset);
+ spin_unlock(&bcom_sram->lock);
+}
+EXPORT_SYMBOL_GPL(bcom_sram_free);
+
diff --git a/arch/powerpc/sysdev/bestcomm/sram.h b/arch/powerpc/sysdev/bestcomm/sram.h
new file mode 100644
index 000000000000..b6d668963cce
--- /dev/null
+++ b/arch/powerpc/sysdev/bestcomm/sram.h
@@ -0,0 +1,54 @@
+/*
+ * Handling of a sram zone for bestcomm
+ *
+ *
+ * Copyright (C) 2007 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef __BESTCOMM_SRAM_H__
+#define __BESTCOMM_SRAM_H__
+
+#include <asm/rheap.h>
+#include <asm/mmu.h>
+#include <linux/spinlock.h>
+
+
+/* Structure used internally */
+ /* The internals are here for the inline functions
+ * sake, certainly not for the user to mess with !
+ */
+struct bcom_sram {
+ phys_addr_t base_phys;
+ void *base_virt;
+ unsigned int size;
+ rh_info_t *rh;
+ spinlock_t lock;
+};
+
+extern struct bcom_sram *bcom_sram;
+
+
+/* Public API */
+extern int bcom_sram_init(struct device_node *sram_node, char *owner);
+extern void bcom_sram_cleanup(void);
+
+extern void* bcom_sram_alloc(int size, int align, phys_addr_t *phys);
+extern void bcom_sram_free(void *ptr);
+
+static inline phys_addr_t bcom_sram_va2pa(void *va) {
+ return bcom_sram->base_phys +
+ (unsigned long)(va - bcom_sram->base_virt);
+}
+
+static inline void *bcom_sram_pa2va(phys_addr_t pa) {
+ return bcom_sram->base_virt +
+ (unsigned long)(pa - bcom_sram->base_phys);
+}
+
+
+#endif /* __BESTCOMM_SRAM_H__ */
+
diff --git a/arch/powerpc/sysdev/cpm_common.c b/arch/powerpc/sysdev/cpm_common.c
index 66c8ad4cfce6..165981c87786 100644
--- a/arch/powerpc/sysdev/cpm_common.c
+++ b/arch/powerpc/sysdev/cpm_common.c
@@ -77,8 +77,6 @@ int __init cpm_muram_init(void)
int i = 0;
int ret = 0;
- printk("cpm_muram_init\n");
-
spin_lock_init(&cpm_muram_lock);
/* initialize the info header */
rh_init(&cpm_muram_info, 1,
@@ -193,7 +191,7 @@ void __iomem *cpm_muram_addr(unsigned long offset)
EXPORT_SYMBOL(cpm_muram_addr);
/**
- * cpm_muram_phys - turn a muram virtual address into a DMA address
+ * cpm_muram_dma - turn a muram virtual address into a DMA address
* @offset: virtual address from cpm_muram_addr() to convert
*/
dma_addr_t cpm_muram_dma(void __iomem *addr)
diff --git a/arch/powerpc/sysdev/dcr.c b/arch/powerpc/sysdev/dcr.c
index ab11c0b29024..427027c7ea0f 100644
--- a/arch/powerpc/sysdev/dcr.c
+++ b/arch/powerpc/sysdev/dcr.c
@@ -126,13 +126,13 @@ dcr_host_t dcr_map(struct device_node *dev, unsigned int dcr_n,
}
EXPORT_SYMBOL_GPL(dcr_map);
-void dcr_unmap(dcr_host_t host, unsigned int dcr_n, unsigned int dcr_c)
+void dcr_unmap(dcr_host_t host, unsigned int dcr_c)
{
dcr_host_t h = host;
if (h.token == NULL)
return;
- h.token += dcr_n * h.stride;
+ h.token += host.base * h.stride;
iounmap(h.token);
h.token = NULL;
}
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index af090c93be10..33df4c347ca7 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -255,7 +255,7 @@ DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8533E, quirk_fsl_pcie_transpare
DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8533, quirk_fsl_pcie_transparent);
DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8544E, quirk_fsl_pcie_transparent);
DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8544, quirk_fsl_pcie_transparent);
-DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8572E, quirk_fsl_pcie_transparent)
+DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8572E, quirk_fsl_pcie_transparent);
DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8572, quirk_fsl_pcie_transparent);
DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8641, quirk_fsl_pcie_transparent);
DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8641D, quirk_fsl_pcie_transparent);
diff --git a/arch/powerpc/sysdev/i8259.c b/arch/powerpc/sysdev/i8259.c
index 7c1b27ac7d3c..216c0f5680d2 100644
--- a/arch/powerpc/sysdev/i8259.c
+++ b/arch/powerpc/sysdev/i8259.c
@@ -137,6 +137,7 @@ static void i8259_unmask_irq(unsigned int irq_nr)
static struct irq_chip i8259_pic = {
.typename = " i8259 ",
.mask = i8259_mask_irq,
+ .disable = i8259_mask_irq,
.unmask = i8259_unmask_irq,
.mask_ack = i8259_mask_and_ack_irq,
};
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 893e65439e85..e47938899a92 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -156,7 +156,7 @@ static inline u32 _mpic_read(enum mpic_reg_type type,
switch(type) {
#ifdef CONFIG_PPC_DCR
case mpic_access_dcr:
- return dcr_read(rb->dhost, rb->dhost.base + reg);
+ return dcr_read(rb->dhost, reg);
#endif
case mpic_access_mmio_be:
return in_be32(rb->base + (reg >> 2));
@@ -173,7 +173,7 @@ static inline void _mpic_write(enum mpic_reg_type type,
switch(type) {
#ifdef CONFIG_PPC_DCR
case mpic_access_dcr:
- return dcr_write(rb->dhost, rb->dhost.base + reg, value);
+ return dcr_write(rb->dhost, reg, value);
#endif
case mpic_access_mmio_be:
return out_be32(rb->base + (reg >> 2), value);
diff --git a/arch/powerpc/sysdev/mv64x60_pci.c b/arch/powerpc/sysdev/mv64x60_pci.c
index 9b3baa7317d7..6933f9c73b43 100644
--- a/arch/powerpc/sysdev/mv64x60_pci.c
+++ b/arch/powerpc/sysdev/mv64x60_pci.c
@@ -24,8 +24,9 @@
#define MV64X60_VAL_LEN_MAX 11
#define MV64X60_PCICFG_CPCI_HOTSWAP 0x68
-static ssize_t mv64x60_hs_reg_read(struct kobject *kobj, char *buf, loff_t off,
- size_t count)
+static ssize_t mv64x60_hs_reg_read(struct kobject *kobj,
+ struct bin_attribute *attr, char *buf,
+ loff_t off, size_t count)
{
struct pci_dev *phb;
u32 v;
@@ -44,8 +45,9 @@ static ssize_t mv64x60_hs_reg_read(struct kobject *kobj, char *buf, loff_t off,
return sprintf(buf, "0x%08x\n", v);
}
-static ssize_t mv64x60_hs_reg_write(struct kobject *kobj, char *buf, loff_t off,
- size_t count)
+static ssize_t mv64x60_hs_reg_write(struct kobject *kobj,
+ struct bin_attribute *attr, char *buf,
+ loff_t off, size_t count)
{
struct pci_dev *phb;
u32 v;
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index 20dce4681259..6473fa7cb4b9 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -102,6 +102,7 @@ config 44x
config 8xx
bool "8xx"
+ select PPC_LIB_RHEAP
config E200
bool "e200"
@@ -798,6 +799,7 @@ config CPM1
config CPM2
bool
depends on 8260 || MPC8560 || MPC8555
+ select PPC_LIB_RHEAP
default y
help
The CPM2 (Communications Processor Module) is a coprocessor on
@@ -1277,6 +1279,10 @@ config BOOT_LOAD
config PIN_TLB
bool "Pinned Kernel TLBs (860 ONLY)"
depends on ADVANCED_OPTIONS && 8xx
+
+config PPC_LIB_RHEAP
+ bool
+
endmenu
source "net/Kconfig"
@@ -1311,7 +1317,7 @@ endmenu
source "lib/Kconfig"
-source "arch/powerpc/oprofile/Kconfig"
+source "kernel/Kconfig.instrumentation"
source "arch/ppc/Kconfig.debug"
diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile
index eee6264e8a04..95894ef7beaa 100644
--- a/arch/ppc/Makefile
+++ b/arch/ppc/Makefile
@@ -22,22 +22,22 @@ endif
LDFLAGS_vmlinux := -Ttext $(KERNELLOAD) -Bstatic
# The -Iarch/$(ARCH)/include is temporary while we are merging
-CPPFLAGS += -Iarch/$(ARCH) -Iarch/$(ARCH)/include
-AFLAGS += -Iarch/$(ARCH)
-CFLAGS += -Iarch/$(ARCH) -msoft-float -pipe \
+KBUILD_CPPFLAGS += -Iarch/$(ARCH) -Iarch/$(ARCH)/include
+KBUILD_AFLAGS += -Iarch/$(ARCH)
+KBUILD_CFLAGS += -Iarch/$(ARCH) -msoft-float -pipe \
-ffixed-r2 -mmultiple
# No AltiVec instruction when building kernel
-CFLAGS += $(call cc-option, -mno-altivec)
+KBUILD_CFLAGS += $(call cc-option, -mno-altivec)
-CPP = $(CC) -E $(CFLAGS)
+CPP = $(CC) -E $(KBUILD_CFLAGS)
# Temporary hack until we have migrated to asm-powerpc
LINUXINCLUDE += -Iarch/$(ARCH)/include
CHECKFLAGS += -D__powerpc__
ifndef CONFIG_FSL_BOOKE
-CFLAGS += -mstring
+KBUILD_CFLAGS += -mstring
endif
cpu-as-$(CONFIG_4xx) += -Wa,-m405
@@ -45,8 +45,8 @@ cpu-as-$(CONFIG_6xx) += -Wa,-maltivec
cpu-as-$(CONFIG_E500) += -Wa,-me500
cpu-as-$(CONFIG_E200) += -Wa,-me200
-AFLAGS += $(cpu-as-y)
-CFLAGS += $(cpu-as-y)
+KBUILD_AFLAGS += $(cpu-as-y)
+KBUILD_CFLAGS += $(cpu-as-y)
# Default to the common case.
KBUILD_DEFCONFIG := common_defconfig
diff --git a/arch/ppc/boot/Makefile b/arch/ppc/boot/Makefile
index b739e25d4728..500497e3c72d 100644
--- a/arch/ppc/boot/Makefile
+++ b/arch/ppc/boot/Makefile
@@ -13,7 +13,8 @@
# modified by Cort (cort@cs.nmt.edu)
#
-CFLAGS += -fno-builtin -D__BOOTER__ -Iarch/$(ARCH)/boot/include
+# KBUILD_CFLAGS used when building rest of boot (takes effect recursively)
+KBUILD_CFLAGS += -fno-builtin -D__BOOTER__ -Iarch/$(ARCH)/boot/include
HOSTCFLAGS += -Iarch/$(ARCH)/boot/include
BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
index fba7ca17a67e..59e77eb63338 100644
--- a/arch/ppc/kernel/entry.S
+++ b/arch/ppc/kernel/entry.S
@@ -244,6 +244,16 @@ syscall_exit_cont:
andis. r10,r0,DBCR0_IC@h
bnel- load_dbcr0
#endif
+#ifdef CONFIG_44x
+ lis r4,icache_44x_need_flush@ha
+ lwz r5,icache_44x_need_flush@l(r4)
+ cmplwi cr0,r5,0
+ bne- 2f
+1:
+#endif /* CONFIG_44x */
+BEGIN_FTR_SECTION
+ lwarx r7,0,r1
+END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX)
stwcx. r0,0,r1 /* to clear the reservation */
lwz r4,_LINK(r1)
lwz r5,_CCR(r1)
@@ -258,6 +268,12 @@ syscall_exit_cont:
mtspr SPRN_SRR1,r8
SYNC
RFI
+#ifdef CONFIG_44x
+2: li r7,0
+ iccci r0,r0
+ stw r7,icache_44x_need_flush@l(r4)
+ b 1b
+#endif /* CONFIG_44x */
66: li r3,-ENOSYS
b ret_from_syscall
@@ -679,6 +695,16 @@ resume_kernel:
/* interrupts are hard-disabled at this point */
restore:
+#ifdef CONFIG_44x
+ lis r4,icache_44x_need_flush@ha
+ lwz r5,icache_44x_need_flush@l(r4)
+ cmplwi cr0,r5,0
+ beq+ 1f
+ li r6,0
+ iccci r0,r0
+ stw r6,icache_44x_need_flush@l(r4)
+1:
+#endif /* CONFIG_44x */
lwz r0,GPR0(r1)
lwz r2,GPR2(r1)
REST_4GPRS(3, r1)
@@ -690,6 +716,9 @@ restore:
mtctr r11
PPC405_ERR77(0,r1)
+BEGIN_FTR_SECTION
+ lwarx r11,0,r1
+END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX)
stwcx. r0,0,r1 /* to clear the reservation */
#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
index a22e1f4d94c8..e0c850d85c53 100644
--- a/arch/ppc/kernel/misc.S
+++ b/arch/ppc/kernel/misc.S
@@ -224,7 +224,16 @@ _GLOBAL(_tlbia)
*/
_GLOBAL(_tlbie)
#if defined(CONFIG_40x)
+ /* We run the search with interrupts disabled because we have to change
+ * the PID and I don't want to preempt when that happens.
+ */
+ mfmsr r5
+ mfspr r6,SPRN_PID
+ wrteei 0
+ mtspr SPRN_PID,r4
tlbsx. r3, 0, r3
+ mtspr SPRN_PID,r6
+ wrtee r5
bne 10f
sync
/* There are only 64 TLB entries, so r3 < 64, which means bit 25 is clear.
@@ -234,22 +243,21 @@ _GLOBAL(_tlbie)
isync
10:
#elif defined(CONFIG_44x)
- mfspr r4,SPRN_MMUCR
- mfspr r5,SPRN_PID /* Get PID */
- rlwimi r4,r5,0,24,31 /* Set TID */
+ mfspr r5,SPRN_MMUCR
+ rlwimi r5,r4,0,24,31 /* Set TID */
/* We have to run the search with interrupts disabled, even critical
* and debug interrupts (in fact the only critical exceptions we have
* are debug and machine check). Otherwise an interrupt which causes
* a TLB miss can clobber the MMUCR between the mtspr and the tlbsx. */
- mfmsr r5
+ mfmsr r4
lis r6,(MSR_EE|MSR_CE|MSR_ME|MSR_DE)@ha
addi r6,r6,(MSR_EE|MSR_CE|MSR_ME|MSR_DE)@l
- andc r6,r5,r6
+ andc r6,r4,r6
mtmsr r6
- mtspr SPRN_MMUCR,r4
+ mtspr SPRN_MMUCR,r5
tlbsx. r3, 0, r3
- mtmsr r5
+ mtmsr r4
bne 10f
sync
/* There are only 64 TLB entries, so r3 < 64,
@@ -491,12 +499,21 @@ END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
addi r3,r3,L1_CACHE_BYTES
bdnz 0b
sync
+#ifndef CONFIG_44x
+ /* We don't flush the icache on 44x. Those have a virtual icache
+ * and we don't have access to the virtual address here (it's
+ * not the page vaddr but where it's mapped in user space). The
+ * flushing of the icache on these is handled elsewhere, when
+ * a change in the address space occurs, before returning to
+ * user space
+ */
mtctr r4
1: icbi 0,r6
addi r6,r6,L1_CACHE_BYTES
bdnz 1b
sync
isync
+#endif /* CONFIG_44x */
blr
/*
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c
index 3f3b292eb773..c78568905c3b 100644
--- a/arch/ppc/kernel/traps.c
+++ b/arch/ppc/kernel/traps.c
@@ -121,7 +121,7 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr)
* generate the same exception over and over again and we get
* nowhere. Better to kill it and let the kernel panic.
*/
- if (is_init(current)) {
+ if (is_global_init(current)) {
__sighandler_t handler;
spin_lock_irq(&current->sighand->siglock);
diff --git a/arch/ppc/mm/44x_mmu.c b/arch/ppc/mm/44x_mmu.c
index 0a0a0487b334..6536a25cfcb8 100644
--- a/arch/ppc/mm/44x_mmu.c
+++ b/arch/ppc/mm/44x_mmu.c
@@ -61,6 +61,7 @@ extern char etext[], _stext[];
*/
unsigned int tlb_44x_index = 0;
unsigned int tlb_44x_hwater = 62;
+int icache_44x_need_flush;
/*
* "Pins" a 256MB TLB entry in AS0 for kernel lowmem
diff --git a/arch/ppc/mm/4xx_mmu.c b/arch/ppc/mm/4xx_mmu.c
index 838e09db71d9..ea785dbaac7c 100644
--- a/arch/ppc/mm/4xx_mmu.c
+++ b/arch/ppc/mm/4xx_mmu.c
@@ -99,13 +99,12 @@ unsigned long __init mmu_mapin_ram(void)
v = KERNELBASE;
p = PPC_MEMSTART;
- s = 0;
+ s = total_lowmem;
- if (__map_without_ltlbs) {
- return s;
- }
+ if (__map_without_ltlbs)
+ return 0;
- while (s <= (total_lowmem - LARGE_PAGE_SIZE_16M)) {
+ while (s >= LARGE_PAGE_SIZE_16M) {
pmd_t *pmdp;
unsigned long val = p | _PMD_SIZE_16M | _PAGE_HWEXEC | _PAGE_HWWRITE;
@@ -117,10 +116,10 @@ unsigned long __init mmu_mapin_ram(void)
v += LARGE_PAGE_SIZE_16M;
p += LARGE_PAGE_SIZE_16M;
- s += LARGE_PAGE_SIZE_16M;
+ s -= LARGE_PAGE_SIZE_16M;
}
- while (s <= (total_lowmem - LARGE_PAGE_SIZE_4M)) {
+ while (s >= LARGE_PAGE_SIZE_4M) {
pmd_t *pmdp;
unsigned long val = p | _PMD_SIZE_4M | _PAGE_HWEXEC | _PAGE_HWWRITE;
@@ -129,8 +128,8 @@ unsigned long __init mmu_mapin_ram(void)
v += LARGE_PAGE_SIZE_4M;
p += LARGE_PAGE_SIZE_4M;
- s += LARGE_PAGE_SIZE_4M;
+ s -= LARGE_PAGE_SIZE_4M;
}
- return s;
+ return total_lowmem - s;
}
diff --git a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c
index b98244e277fb..36c0e7529edb 100644
--- a/arch/ppc/mm/fault.c
+++ b/arch/ppc/mm/fault.c
@@ -227,7 +227,7 @@ good_area:
set_bit(PG_arch_1, &page->flags);
}
pte_update(ptep, 0, _PAGE_HWEXEC);
- _tlbie(address);
+ _tlbie(address, mm->context.id);
pte_unmap_unlock(ptep, ptl);
up_read(&mm->mmap_sem);
return 0;
@@ -290,14 +290,14 @@ bad_area:
*/
out_of_memory:
up_read(&mm->mmap_sem);
- if (is_init(current)) {
+ if (is_global_init(current)) {
yield();
down_read(&mm->mmap_sem);
goto survive;
}
printk("VM: killing process %s\n", current->comm);
if (user_mode(regs))
- do_exit(SIGKILL);
+ do_group_exit(SIGKILL);
return SIGKILL;
do_sigbus:
diff --git a/arch/ppc/mm/mmu_decl.h b/arch/ppc/mm/mmu_decl.h
index 540f3292b229..f1d4f2109a99 100644
--- a/arch/ppc/mm/mmu_decl.h
+++ b/arch/ppc/mm/mmu_decl.h
@@ -54,12 +54,12 @@ extern unsigned int num_tlbcam_entries;
#define mmu_mapin_ram() (0UL)
#elif defined(CONFIG_4xx)
-#define flush_HPTE(X, va, pg) _tlbie(va)
+#define flush_HPTE(pid, va, pg) _tlbie(va, pid)
extern void MMU_init_hw(void);
extern unsigned long mmu_mapin_ram(void);
#elif defined(CONFIG_FSL_BOOKE)
-#define flush_HPTE(X, va, pg) _tlbie(va)
+#define flush_HPTE(pid, va, pg) _tlbie(va, pid)
extern void MMU_init_hw(void);
extern unsigned long mmu_mapin_ram(void);
extern void adjust_total_lowmem(void);
diff --git a/arch/ppc/platforms/4xx/ebony.c b/arch/ppc/platforms/4xx/ebony.c
index 05d7184d7e14..453643a0eeea 100644
--- a/arch/ppc/platforms/4xx/ebony.c
+++ b/arch/ppc/platforms/4xx/ebony.c
@@ -236,7 +236,7 @@ ebony_early_serial_map(void)
gen550_init(0, &port);
/* Purge TLB entry added in head_44x.S for early serial access */
- _tlbie(UART0_IO_BASE);
+ _tlbie(UART0_IO_BASE, 0);
#endif
port.membase = ioremap64(PPC440GP_UART1_ADDR, 8);
diff --git a/arch/ppc/platforms/4xx/luan.c b/arch/ppc/platforms/4xx/luan.c
index 4b169610f154..b79ebb8a3e6c 100644
--- a/arch/ppc/platforms/4xx/luan.c
+++ b/arch/ppc/platforms/4xx/luan.c
@@ -230,9 +230,14 @@ luan_setup_hoses(void)
/* Allocate hoses for PCIX1 and PCIX2 */
hose1 = pcibios_alloc_controller();
+ if (!hose1)
+ return;
+
hose2 = pcibios_alloc_controller();
- if (!hose1 || !hose2)
+ if (!hose2) {
+ pcibios_free_controller(hose1);
return;
+ }
/* Setup PCIX1 */
hose1->first_busno = 0;
diff --git a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c
index fd0f971881d6..28a712cd4800 100644
--- a/arch/ppc/platforms/4xx/ocotea.c
+++ b/arch/ppc/platforms/4xx/ocotea.c
@@ -259,7 +259,7 @@ ocotea_early_serial_map(void)
gen550_init(0, &port);
/* Purge TLB entry added in head_44x.S for early serial access */
- _tlbie(UART0_IO_BASE);
+ _tlbie(UART0_IO_BASE, 0);
#endif
port.membase = ioremap64(PPC440GX_UART1_ADDR, 8);
diff --git a/arch/ppc/platforms/4xx/taishan.c b/arch/ppc/platforms/4xx/taishan.c
index 888c492b4a45..f6a0c6650f33 100644
--- a/arch/ppc/platforms/4xx/taishan.c
+++ b/arch/ppc/platforms/4xx/taishan.c
@@ -316,7 +316,7 @@ taishan_early_serial_map(void)
gen550_init(0, &port);
/* Purge TLB entry added in head_44x.S for early serial access */
- _tlbie(UART0_IO_BASE);
+ _tlbie(UART0_IO_BASE, 0);
#endif
port.membase = ioremap64(PPC440GX_UART1_ADDR, 8);
diff --git a/arch/ppc/platforms/chestnut.c b/arch/ppc/platforms/chestnut.c
index 248684f50dd9..dcd6070b85eb 100644
--- a/arch/ppc/platforms/chestnut.c
+++ b/arch/ppc/platforms/chestnut.c
@@ -49,7 +49,6 @@ extern void gen550_progress(char *, unsigned short);
extern void gen550_init(int, struct uart_port *);
extern void mv64360_pcibios_fixup(mv64x60_handle_t *bh);
-#define BIT(x) (1<<x)
#define CHESTNUT_PRESERVE_MASK (BIT(MV64x60_CPU2DEV_0_WIN) | \
BIT(MV64x60_CPU2DEV_1_WIN) | \
BIT(MV64x60_CPU2DEV_2_WIN) | \
diff --git a/arch/ppc/syslib/i8259.c b/arch/ppc/syslib/i8259.c
index 1e5a00a4b5f5..559f27c6aefe 100644
--- a/arch/ppc/syslib/i8259.c
+++ b/arch/ppc/syslib/i8259.c
@@ -127,6 +127,7 @@ static void i8259_unmask_irq(unsigned int irq_nr)
static struct irq_chip i8259_pic = {
.typename = " i8259 ",
.mask = i8259_mask_irq,
+ .disable = i8259_mask_irq,
.unmask = i8259_unmask_irq,
.mask_ack = i8259_mask_and_ack_irq,
};
diff --git a/arch/ppc/syslib/m8260_setup.c b/arch/ppc/syslib/m8260_setup.c
index 15f0d7323535..46588fa94381 100644
--- a/arch/ppc/syslib/m8260_setup.c
+++ b/arch/ppc/syslib/m8260_setup.c
@@ -25,6 +25,7 @@
#include <asm/machdep.h>
#include <asm/bootinfo.h>
#include <asm/time.h>
+#include <asm/ppc_sys.h>
#include "cpm2_pic.h"
@@ -61,7 +62,7 @@ m8260_setup_arch(void)
#endif
identify_ppc_sys_by_name_and_id(BOARD_CHIP_NAME,
- in_be32(CPM_MAP_ADDR + CPM_IMMR_OFFSET));
+ in_be32((void *)CPM_MAP_ADDR + CPM_IMMR_OFFSET));
m82xx_board_setup();
}
@@ -147,12 +148,12 @@ m8260_show_cpuinfo(struct seq_file *m)
seq_printf(m, "vendor\t\t: %s\n"
"machine\t\t: %s\n"
"\n"
- "mem size\t\t: 0x%08x\n"
- "console baud\t\t: %d\n"
+ "mem size\t\t: 0x%08lx\n"
+ "console baud\t\t: %ld\n"
"\n"
- "core clock\t: %u MHz\n"
- "CPM clock\t: %u MHz\n"
- "bus clock\t: %u MHz\n",
+ "core clock\t: %lu MHz\n"
+ "CPM clock\t: %lu MHz\n"
+ "bus clock\t: %lu MHz\n",
CPUINFO_VENDOR, CPUINFO_MACHINE, bp->bi_memsize,
bp->bi_baudrate, bp->bi_intfreq / 1000000,
bp->bi_cpmfreq / 1000000, bp->bi_busfreq / 1000000);
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index b71132166f60..1330061020ab 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -513,7 +513,7 @@ config ZFCPDUMP
default n
help
Select this option if you want to build an zfcpdump enabled kernel.
- Refer to "Documentation/s390/zfcpdump.txt" for more details on this.
+ Refer to <file:Documentation/s390/zfcpdump.txt> for more details on this.
endmenu
@@ -529,21 +529,7 @@ source "drivers/Kconfig"
source "fs/Kconfig"
-menu "Instrumentation Support"
-
-source "arch/s390/oprofile/Kconfig"
-
-config KPROBES
- bool "Kprobes (EXPERIMENTAL)"
- depends on EXPERIMENTAL && MODULES
- help
- Kprobes allows you to trap at almost any kernel address and
- execute a callback function. register_kprobe() establishes
- a probepoint and specifies the callback. Kprobes is useful
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-
-endmenu
+source "kernel/Kconfig.instrumentation"
source "arch/s390/Kconfig.debug"
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index 143ed8e154af..f708be367b03 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -15,16 +15,16 @@
ifndef CONFIG_64BIT
LDFLAGS := -m elf_s390
-CFLAGS += -m31
-AFLAGS += -m31
+KBUILD_CFLAGS += -m31
+KBUILD_AFLAGS += -m31
UTS_MACHINE := s390
STACK_SIZE := 8192
CHECKFLAGS += -D__s390__ -msize-long
else
LDFLAGS := -m elf64_s390
MODFLAGS += -fpic -D__PIC__
-CFLAGS += -m64
-AFLAGS += -m64
+KBUILD_CFLAGS += -m64
+KBUILD_AFLAGS += -m64
UTS_MACHINE := s390x
STACK_SIZE := 16384
CHECKFLAGS += -D__s390__ -D__s390x__
@@ -77,9 +77,9 @@ cflags-$(CONFIG_WARN_STACK) += -mwarn-dynamicstack
cflags-$(CONFIG_WARN_STACK) += -mwarn-framesize=$(CONFIG_WARN_STACK_SIZE)
endif
-CFLAGS += -mbackchain -msoft-float $(cflags-y)
-CFLAGS += -pipe -fno-strength-reduce -Wno-sign-compare
-AFLAGS += $(aflags-y)
+KBUILD_CFLAGS += -mbackchain -msoft-float $(cflags-y)
+KBUILD_CFLAGS += -pipe -fno-strength-reduce -Wno-sign-compare
+KBUILD_AFLAGS += $(aflags-y)
OBJCOPYFLAGS := -O binary
LDFLAGS_vmlinux := -e start
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index 2aae23dba4bb..ece7b99da895 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.22
-# Tue Jul 17 12:50:23 2007
+# Linux kernel version: 2.6.23
+# Mon Oct 22 12:10:44 2007
#
CONFIG_MMU=y
CONFIG_ZONE_DMA=y
@@ -19,15 +19,11 @@ CONFIG_S390=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
-# Code maturity level options
+# General setup
#
CONFIG_EXPERIMENTAL=y
CONFIG_LOCK_KERNEL=y
CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
@@ -42,7 +38,14 @@ CONFIG_AUDIT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=17
+CONFIG_CGROUPS=y
+# CONFIG_CGROUP_DEBUG is not set
+CONFIG_CGROUP_NS=y
+CONFIG_CGROUP_CPUACCT=y
# CONFIG_CPUSETS is not set
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_FAIR_USER_SCHED=y
+# CONFIG_FAIR_CGROUP_SCHED is not set
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_BLK_DEV_INITRD=y
@@ -63,7 +66,6 @@ CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
@@ -83,6 +85,7 @@ CONFIG_STOP_MACHINE=y
CONFIG_BLOCK=y
# CONFIG_BLK_DEV_IO_TRACE is not set
CONFIG_BLK_DEV_BSG=y
+CONFIG_BLOCK_COMPAT=y
#
# IO Schedulers
@@ -108,7 +111,6 @@ CONFIG_64BIT=y
CONFIG_SMP=y
CONFIG_NR_CPUS=32
CONFIG_HOTPLUG_CPU=y
-CONFIG_DEFAULT_MIGRATION_COST=1000000
CONFIG_COMPAT=y
CONFIG_SYSVIPC_COMPAT=y
CONFIG_AUDIT_ARCH=y
@@ -143,9 +145,11 @@ CONFIG_FLATMEM_MANUAL=y
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_RESOURCES_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_HOLES_IN_ZONE=y
@@ -219,12 +223,14 @@ CONFIG_INET_TUNNEL=y
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_LRO=y
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_IP_VS is not set
CONFIG_IPV6=y
# CONFIG_IPV6_PRIVACY is not set
# CONFIG_IPV6_ROUTER_PREF is not set
@@ -243,7 +249,48 @@ CONFIG_IPV6_SIT=y
# CONFIG_IPV6_TUNNEL is not set
# CONFIG_IPV6_MULTIPLE_TABLES is not set
# CONFIG_NETWORK_SECMARK is not set
-# CONFIG_NETFILTER is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK=m
+# CONFIG_NF_CT_ACCT is not set
+# CONFIG_NF_CONNTRACK_MARK is not set
+# CONFIG_NF_CONNTRACK_EVENTS is not set
+# CONFIG_NF_CT_PROTO_SCTP is not set
+# CONFIG_NF_CT_PROTO_UDPLITE is not set
+# CONFIG_NF_CONNTRACK_AMANDA is not set
+# CONFIG_NF_CONNTRACK_FTP is not set
+# CONFIG_NF_CONNTRACK_H323 is not set
+# CONFIG_NF_CONNTRACK_IRC is not set
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+# CONFIG_NF_CONNTRACK_PPTP is not set
+# CONFIG_NF_CONNTRACK_SANE is not set
+# CONFIG_NF_CONNTRACK_SIP is not set
+# CONFIG_NF_CONNTRACK_TFTP is not set
+# CONFIG_NF_CT_NETLINK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_NF_CONNTRACK_IPV4 is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+# CONFIG_NF_CONNTRACK_IPV6 is not set
+# CONFIG_IP6_NF_QUEUE is not set
+# CONFIG_IP6_NF_IPTABLES is not set
# CONFIG_IP_DCCP is not set
CONFIG_IP_SCTP=m
# CONFIG_SCTP_DBG_MSG is not set
@@ -263,12 +310,7 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
CONFIG_NET_SCHED=y
-CONFIG_NET_SCH_FIFO=y
#
# Queueing/Scheduling
@@ -306,10 +348,12 @@ CONFIG_NET_CLS_ACT=y
CONFIG_NET_ACT_POLICE=y
# CONFIG_NET_ACT_GACT is not set
# CONFIG_NET_ACT_MIRRED is not set
+CONFIG_NET_ACT_NAT=m
# CONFIG_NET_ACT_PEDIT is not set
# CONFIG_NET_ACT_SIMP is not set
CONFIG_NET_CLS_POLICE=y
# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_SCH_FIFO=y
#
# Network testing
@@ -329,6 +373,7 @@ CONFIG_CCW=y
#
# Generic Driver Options
#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
@@ -400,17 +445,11 @@ CONFIG_SCSI_FC_ATTRS=y
# CONFIG_SCSI_ISCSI_ATTRS is not set
# CONFIG_SCSI_SAS_ATTRS is not set
# CONFIG_SCSI_SAS_LIBSAS is not set
-
-#
-# SCSI low-level drivers
-#
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
# CONFIG_SCSI_DEBUG is not set
CONFIG_ZFCP=y
-
-#
-# Multi-device support (RAID and LVM)
-#
CONFIG_MD=y
CONFIG_BLK_DEV_MD=y
CONFIG_MD_LINEAR=m
@@ -429,7 +468,9 @@ CONFIG_DM_ZERO=y
CONFIG_DM_MULTIPATH=y
# CONFIG_DM_MULTIPATH_EMC is not set
# CONFIG_DM_MULTIPATH_RDAC is not set
+# CONFIG_DM_MULTIPATH_HP is not set
# CONFIG_DM_DELAY is not set
+# CONFIG_DM_UEVENT is not set
CONFIG_NETDEVICES=y
# CONFIG_NETDEVICES_MULTIQUEUE is not set
# CONFIG_IFB is not set
@@ -438,8 +479,13 @@ CONFIG_BONDING=m
# CONFIG_MACVLAN is not set
CONFIG_EQUALIZER=m
CONFIG_TUN=m
+CONFIG_VETH=m
CONFIG_NET_ETHERNET=y
# CONFIG_MII 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_NETDEV_1000=y
CONFIG_NETDEV_10000=y
# CONFIG_TR is not set
@@ -473,7 +519,6 @@ CONFIG_CCWGROUP=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_WATCHDOG is not set
CONFIG_HW_RANDOM=m
# CONFIG_R3964 is not set
CONFIG_RAW_DRIVER=m
@@ -490,7 +535,6 @@ CONFIG_TN3270_CONSOLE=y
CONFIG_TN3215=y
CONFIG_TN3215_CONSOLE=y
CONFIG_CCW_CONSOLE=y
-CONFIG_SCLP=y
CONFIG_SCLP_TTY=y
CONFIG_SCLP_CONSOLE=y
CONFIG_SCLP_VT220_TTY=y
@@ -514,6 +558,11 @@ CONFIG_S390_TAPE_34XX=m
CONFIG_MONWRITER=m
CONFIG_S390_VMUR=m
# CONFIG_POWER_SUPPLY is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
#
# File systems
@@ -569,7 +618,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
CONFIG_CONFIGFS_FS=m
#
@@ -588,10 +636,7 @@ CONFIG_CONFIGFS_FS=m
# CONFIG_QNX4FS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
+CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
@@ -638,27 +683,13 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
# CONFIG_SYSV68_PARTITION is not set
-
-#
-# Native Language Support
-#
# CONFIG_NLS is not set
-
-#
-# Distributed Lock Manager
-#
CONFIG_DLM=m
# CONFIG_DLM_DEBUG is not set
-
-#
-# Instrumentation Support
-#
-
-#
-# Profiling support
-#
+CONFIG_INSTRUMENTATION=y
# CONFIG_PROFILING is not set
CONFIG_KPROBES=y
+# CONFIG_MARKERS is not set
#
# Kernel hacking
@@ -682,6 +713,7 @@ CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_LOCK_ALLOC is not set
# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
CONFIG_DEBUG_SPINLOCK_SLEEP=y
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
@@ -694,14 +726,17 @@ CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_LKDTM is not set
# CONFIG_FAULT_INJECTION is not set
+CONFIG_SAMPLES=y
#
# Security options
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_CRYPTO=y
CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_AEAD=m
CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_HASH=m
CONFIG_CRYPTO_MANAGER=y
@@ -720,6 +755,7 @@ CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_XTS is not set
# CONFIG_CRYPTO_CRYPTD is not set
# CONFIG_CRYPTO_DES is not set
CONFIG_CRYPTO_FCRYPT=m
@@ -733,11 +769,13 @@ CONFIG_CRYPTO_FCRYPT=m
# CONFIG_CRYPTO_ARC4 is not set
# CONFIG_CRYPTO_KHAZAD is not set
# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_SEED=m
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_MICHAEL_MIC is not set
# CONFIG_CRYPTO_CRC32C is not set
CONFIG_CRYPTO_CAMELLIA=m
# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_AUTHENC=m
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_SHA1_S390 is not set
# CONFIG_CRYPTO_SHA256_S390 is not set
@@ -755,5 +793,6 @@ CONFIG_BITREVERSE=m
# CONFIG_CRC16 is not set
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=m
+CONFIG_CRC7=m
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index 5236fdb17fcb..50b85d07ddd2 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -58,9 +58,9 @@
#include <linux/vfs.h>
#include <linux/ptrace.h>
#include <linux/fadvise.h>
+#include <linux/ipc.h>
#include <asm/types.h>
-#include <asm/ipc.h>
#include <asm/uaccess.h>
#include <asm/semaphore.h>
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index e6289ee74ecd..8bf4ae1150be 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -200,11 +200,13 @@ static noinline __init void find_memory_chunks(unsigned long memsize)
cc = __tprot(addr);
while (cc == old_cc) {
addr += CHUNK_INCR;
- cc = __tprot(addr);
+ if (addr >= memsize)
+ break;
#ifndef CONFIG_64BIT
if (addr == ADDR2G)
break;
#endif
+ cc = __tprot(addr);
}
if (old_addr != addr &&
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 66b51901c87d..ce0856d32500 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -648,6 +648,8 @@ static int dump_set_type(enum dump_type type)
case DUMP_TYPE_CCW:
if (MACHINE_IS_VM)
dump_method = DUMP_METHOD_CCW_VM;
+ else if (diag308_set_works)
+ dump_method = DUMP_METHOD_CCW_DIAG;
else
dump_method = DUMP_METHOD_CCW_CIO;
break;
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index e40373d9fbce..c5549a206284 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -33,6 +33,8 @@
DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
+struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}};
+
int __kprobes arch_prepare_kprobe(struct kprobe *p)
{
/* Make sure the probe isn't going on a difficult instruction */
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index abb447a3e472..29f7884b4ffa 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -44,6 +44,7 @@
#include <asm/processor.h>
#include <asm/irq.h>
#include <asm/timer.h>
+#include <asm/cpu.h>
asmlinkage void ret_from_fork(void) asm ("ret_from_fork");
@@ -91,6 +92,15 @@ EXPORT_SYMBOL(unregister_idle_notifier);
void do_monitor_call(struct pt_regs *regs, long interruption_code)
{
+#ifdef CONFIG_SMP
+ struct s390_idle_data *idle;
+
+ idle = &__get_cpu_var(s390_idle);
+ spin_lock(&idle->lock);
+ idle->idle_time += get_clock() - idle->idle_enter;
+ idle->in_idle = 0;
+ spin_unlock(&idle->lock);
+#endif
/* disable monitor call class 0 */
__ctl_clear_bit(8, 15);
@@ -105,6 +115,9 @@ extern void s390_handle_mcck(void);
static void default_idle(void)
{
int cpu, rc;
+#ifdef CONFIG_SMP
+ struct s390_idle_data *idle;
+#endif
/* CPU is going idle. */
cpu = smp_processor_id();
@@ -141,7 +154,14 @@ static void default_idle(void)
s390_handle_mcck();
return;
}
-
+#ifdef CONFIG_SMP
+ idle = &__get_cpu_var(s390_idle);
+ spin_lock(&idle->lock);
+ idle->idle_count++;
+ idle->in_idle = 1;
+ idle->idle_enter = get_clock();
+ spin_unlock(&idle->lock);
+#endif
trace_hardirqs_on();
/* Wait for external, I/O or machine check interrupt. */
__load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT |
@@ -166,7 +186,7 @@ void show_regs(struct pt_regs *regs)
printk("CPU: %d %s\n", task_thread_info(tsk)->cpu, print_tainted());
printk("Process %s (pid: %d, task: %p, ksp: %p)\n",
- current->comm, current->pid, (void *) tsk,
+ current->comm, task_pid_nr(current), (void *) tsk,
(void *) tsk->thread.ksp);
show_registers(regs);
@@ -254,14 +274,12 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp,
save_fp_regs(&current->thread.fp_regs);
memcpy(&p->thread.fp_regs, &current->thread.fp_regs,
sizeof(s390_fp_regs));
- p->thread.user_seg = __pa((unsigned long) p->mm->pgd) | _SEGMENT_TABLE;
/* Set a new TLS ? */
if (clone_flags & CLONE_SETTLS)
p->thread.acrs[0] = regs->gprs[6];
#else /* CONFIG_64BIT */
/* Save the fpu registers to new thread structure. */
save_fp_regs(&p->thread.fp_regs);
- p->thread.user_seg = __pa((unsigned long) p->mm->pgd) | _REGION_TABLE;
/* Set a new TLS ? */
if (clone_flags & CLONE_SETTLS) {
if (test_thread_flag(TIF_31BIT)) {
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index f4503ca27630..1d81bf9488ae 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -683,11 +683,6 @@ do_ptrace(struct task_struct *child, long request, long addr, long data)
wake_up_process(child);
return 0;
- case PTRACE_DETACH:
- /* detach a process that was attached. */
- return ptrace_detach(child, data);
-
-
/* Do requests that differ for 31/64 bit */
default:
#ifdef CONFIG_COMPAT
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 35edbef1d222..b05ae8584258 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -42,6 +42,7 @@
#include <asm/tlbflush.h>
#include <asm/timer.h>
#include <asm/lowcore.h>
+#include <asm/cpu.h>
/*
* An array with a pointer the lowcore of every CPU.
@@ -325,7 +326,7 @@ static void smp_ext_bitcall(int cpu, ec_bit_sig sig)
*/
void smp_ptlb_callback(void *info)
{
- local_flush_tlb();
+ __tlb_flush_local();
}
void smp_ptlb_all(void)
@@ -494,6 +495,8 @@ int __cpuinit start_secondary(void *cpuvoid)
return 0;
}
+DEFINE_PER_CPU(struct s390_idle_data, s390_idle);
+
static void __init smp_create_idle(unsigned int cpu)
{
struct task_struct *p;
@@ -506,6 +509,7 @@ static void __init smp_create_idle(unsigned int cpu)
if (IS_ERR(p))
panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p));
current_set[cpu] = p;
+ spin_lock_init(&(&per_cpu(s390_idle, cpu))->lock);
}
static int cpu_stopped(int cpu)
@@ -724,6 +728,7 @@ void __init smp_prepare_boot_cpu(void)
cpu_set(0, cpu_online_map);
S390_lowcore.percpu_offset = __per_cpu_offset[0];
current_set[0] = current;
+ spin_lock_init(&(&__get_cpu_var(s390_idle))->lock);
}
void __init smp_cpus_done(unsigned int max_cpus)
@@ -756,22 +761,71 @@ static ssize_t show_capability(struct sys_device *dev, char *buf)
}
static SYSDEV_ATTR(capability, 0444, show_capability, NULL);
+static ssize_t show_idle_count(struct sys_device *dev, char *buf)
+{
+ struct s390_idle_data *idle;
+ unsigned long long idle_count;
+
+ idle = &per_cpu(s390_idle, dev->id);
+ spin_lock_irq(&idle->lock);
+ idle_count = idle->idle_count;
+ spin_unlock_irq(&idle->lock);
+ return sprintf(buf, "%llu\n", idle_count);
+}
+static SYSDEV_ATTR(idle_count, 0444, show_idle_count, NULL);
+
+static ssize_t show_idle_time(struct sys_device *dev, char *buf)
+{
+ struct s390_idle_data *idle;
+ unsigned long long new_time;
+
+ idle = &per_cpu(s390_idle, dev->id);
+ spin_lock_irq(&idle->lock);
+ if (idle->in_idle) {
+ new_time = get_clock();
+ idle->idle_time += new_time - idle->idle_enter;
+ idle->idle_enter = new_time;
+ }
+ new_time = idle->idle_time;
+ spin_unlock_irq(&idle->lock);
+ return sprintf(buf, "%llu\n", new_time >> 12);
+}
+static SYSDEV_ATTR(idle_time_us, 0444, show_idle_time, NULL);
+
+static struct attribute *cpu_attrs[] = {
+ &attr_capability.attr,
+ &attr_idle_count.attr,
+ &attr_idle_time_us.attr,
+ NULL,
+};
+
+static struct attribute_group cpu_attr_group = {
+ .attrs = cpu_attrs,
+};
+
static int __cpuinit smp_cpu_notify(struct notifier_block *self,
unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned int)(long)hcpu;
struct cpu *c = &per_cpu(cpu_devices, cpu);
struct sys_device *s = &c->sysdev;
+ struct s390_idle_data *idle;
switch (action) {
case CPU_ONLINE:
case CPU_ONLINE_FROZEN:
- if (sysdev_create_file(s, &attr_capability))
+ idle = &per_cpu(s390_idle, cpu);
+ spin_lock_irq(&idle->lock);
+ idle->idle_enter = 0;
+ idle->idle_time = 0;
+ idle->idle_count = 0;
+ spin_unlock_irq(&idle->lock);
+ if (sysfs_create_group(&s->kobj, &cpu_attr_group))
return NOTIFY_BAD;
break;
case CPU_DEAD:
case CPU_DEAD_FROZEN:
- sysdev_remove_file(s, &attr_capability);
+ sysfs_remove_group(&s->kobj, &cpu_attr_group);
break;
}
return NOTIFY_OK;
@@ -784,6 +838,7 @@ static struct notifier_block __cpuinitdata smp_cpu_nb = {
static int __init topology_init(void)
{
int cpu;
+ int rc;
register_cpu_notifier(&smp_cpu_nb);
@@ -796,7 +851,9 @@ static int __init topology_init(void)
if (!cpu_online(cpu))
continue;
s = &c->sysdev;
- sysdev_create_file(s, &attr_capability);
+ rc = sysfs_create_group(&s->kobj, &cpu_attr_group);
+ if (rc)
+ return rc;
}
return 0;
}
diff --git a/arch/s390/kernel/sys_s390.c b/arch/s390/kernel/sys_s390.c
index 1eaff84a1eb6..fefee99f28aa 100644
--- a/arch/s390/kernel/sys_s390.c
+++ b/arch/s390/kernel/sys_s390.c
@@ -28,9 +28,9 @@
#include <linux/utsname.h>
#include <linux/personality.h>
#include <linux/unistd.h>
+#include <linux/ipc.h>
#include <asm/uaccess.h>
-#include <asm/ipc.h>
/*
* sys_pipe() is the normal C calling standard for creating
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 48dae49bc1ec..22b800ce2126 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -145,12 +145,8 @@ void account_ticks(u64 time)
do_timer(ticks);
#endif
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
- account_tick_vtime(current);
-#else
while (ticks--)
update_process_times(user_mode(get_irq_regs()));
-#endif
s390_do_profile();
}
@@ -307,7 +303,7 @@ static cycle_t read_tod_clock(void)
static struct clocksource clocksource_tod = {
.name = "tod",
- .rating = 100,
+ .rating = 400,
.read = read_tod_clock,
.mask = -1ULL,
.mult = 1000,
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index 84ff78de6bac..c5f05b3fb2c3 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -32,7 +32,7 @@ static DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer);
* Update process times based on virtual cpu times stored by entry.S
* to the lowcore fields user_timer, system_timer & steal_clock.
*/
-void account_tick_vtime(struct task_struct *tsk)
+void account_process_tick(struct task_struct *tsk, int user_tick)
{
cputime_t cputime;
__u64 timer, clock;
@@ -64,12 +64,6 @@ void account_tick_vtime(struct task_struct *tsk)
S390_lowcore.steal_clock -= cputime << 12;
account_steal_time(tsk, cputime);
}
-
- run_local_timers();
- if (rcu_pending(smp_processor_id()))
- rcu_check_callbacks(smp_processor_id(), rcu_user_flag);
- scheduler_tick();
- run_posix_cpu_timers(tsk);
}
/*
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c
index 60604b2819b2..7e8efaade2ea 100644
--- a/arch/s390/lib/uaccess_pt.c
+++ b/arch/s390/lib/uaccess_pt.c
@@ -15,6 +15,27 @@
#include <asm/futex.h>
#include "uaccess.h"
+static inline pte_t *follow_table(struct mm_struct *mm, unsigned long addr)
+{
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+
+ pgd = pgd_offset(mm, addr);
+ if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
+ return NULL;
+
+ pud = pud_offset(pgd, addr);
+ if (pud_none(*pud) || unlikely(pud_bad(*pud)))
+ return NULL;
+
+ pmd = pmd_offset(pud, addr);
+ if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
+ return NULL;
+
+ return pte_offset_map(pmd, addr);
+}
+
static int __handle_fault(struct mm_struct *mm, unsigned long address,
int write_access)
{
@@ -64,7 +85,7 @@ out:
out_of_memory:
up_read(&mm->mmap_sem);
- if (is_init(current)) {
+ if (is_global_init(current)) {
yield();
down_read(&mm->mmap_sem);
goto survive;
@@ -85,8 +106,6 @@ static size_t __user_copy_pt(unsigned long uaddr, void *kptr,
{
struct mm_struct *mm = current->mm;
unsigned long offset, pfn, done, size;
- pgd_t *pgd;
- pmd_t *pmd;
pte_t *pte;
void *from, *to;
@@ -94,15 +113,7 @@ static size_t __user_copy_pt(unsigned long uaddr, void *kptr,
retry:
spin_lock(&mm->page_table_lock);
do {
- pgd = pgd_offset(mm, uaddr);
- if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
- goto fault;
-
- pmd = pmd_offset(pgd, uaddr);
- if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
- goto fault;
-
- pte = pte_offset_map(pmd, uaddr);
+ pte = follow_table(mm, uaddr);
if (!pte || !pte_present(*pte) ||
(write_user && !pte_write(*pte)))
goto fault;
@@ -142,22 +153,12 @@ static unsigned long __dat_user_addr(unsigned long uaddr)
{
struct mm_struct *mm = current->mm;
unsigned long pfn, ret;
- pgd_t *pgd;
- pmd_t *pmd;
pte_t *pte;
int rc;
ret = 0;
retry:
- pgd = pgd_offset(mm, uaddr);
- if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
- goto fault;
-
- pmd = pmd_offset(pgd, uaddr);
- if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
- goto fault;
-
- pte = pte_offset_map(pmd, uaddr);
+ pte = follow_table(mm, uaddr);
if (!pte || !pte_present(*pte))
goto fault;
@@ -229,8 +230,6 @@ static size_t strnlen_user_pt(size_t count, const char __user *src)
unsigned long uaddr = (unsigned long) src;
struct mm_struct *mm = current->mm;
unsigned long offset, pfn, done, len;
- pgd_t *pgd;
- pmd_t *pmd;
pte_t *pte;
size_t len_str;
@@ -240,15 +239,7 @@ static size_t strnlen_user_pt(size_t count, const char __user *src)
retry:
spin_lock(&mm->page_table_lock);
do {
- pgd = pgd_offset(mm, uaddr);
- if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
- goto fault;
-
- pmd = pmd_offset(pgd, uaddr);
- if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
- goto fault;
-
- pte = pte_offset_map(pmd, uaddr);
+ pte = follow_table(mm, uaddr);
if (!pte || !pte_present(*pte))
goto fault;
@@ -308,8 +299,6 @@ static size_t copy_in_user_pt(size_t n, void __user *to,
uaddr, done, size;
unsigned long uaddr_from = (unsigned long) from;
unsigned long uaddr_to = (unsigned long) to;
- pgd_t *pgd_from, *pgd_to;
- pmd_t *pmd_from, *pmd_to;
pte_t *pte_from, *pte_to;
int write_user;
@@ -317,39 +306,14 @@ static size_t copy_in_user_pt(size_t n, void __user *to,
retry:
spin_lock(&mm->page_table_lock);
do {
- pgd_from = pgd_offset(mm, uaddr_from);
- if (pgd_none(*pgd_from) || unlikely(pgd_bad(*pgd_from))) {
- uaddr = uaddr_from;
- write_user = 0;
- goto fault;
- }
- pgd_to = pgd_offset(mm, uaddr_to);
- if (pgd_none(*pgd_to) || unlikely(pgd_bad(*pgd_to))) {
- uaddr = uaddr_to;
- write_user = 1;
- goto fault;
- }
-
- pmd_from = pmd_offset(pgd_from, uaddr_from);
- if (pmd_none(*pmd_from) || unlikely(pmd_bad(*pmd_from))) {
- uaddr = uaddr_from;
- write_user = 0;
- goto fault;
- }
- pmd_to = pmd_offset(pgd_to, uaddr_to);
- if (pmd_none(*pmd_to) || unlikely(pmd_bad(*pmd_to))) {
- uaddr = uaddr_to;
- write_user = 1;
- goto fault;
- }
-
- pte_from = pte_offset_map(pmd_from, uaddr_from);
+ pte_from = follow_table(mm, uaddr_from);
if (!pte_from || !pte_present(*pte_from)) {
uaddr = uaddr_from;
write_user = 0;
goto fault;
}
- pte_to = pte_offset_map(pmd_to, uaddr_to);
+
+ pte_to = follow_table(mm, uaddr_to);
if (!pte_to || !pte_present(*pte_to) || !pte_write(*pte_to)) {
uaddr = uaddr_to;
write_user = 1;
diff --git a/arch/s390/mm/Makefile b/arch/s390/mm/Makefile
index f95449b29fa5..66401930f83e 100644
--- a/arch/s390/mm/Makefile
+++ b/arch/s390/mm/Makefile
@@ -2,6 +2,6 @@
# Makefile for the linux s390-specific parts of the memory manager.
#
-obj-y := init.o fault.o extmem.o mmap.o vmem.o
+obj-y := init.o fault.o extmem.o mmap.o vmem.o pgtable.o
obj-$(CONFIG_CMM) += cmm.o
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c
index fabc50adc46a..d4ed93dfb9c7 100644
--- a/arch/s390/mm/cmm.c
+++ b/arch/s390/mm/cmm.c
@@ -17,6 +17,7 @@
#include <linux/ctype.h>
#include <linux/swap.h>
#include <linux/kthread.h>
+#include <linux/oom.h>
#include <asm/pgalloc.h>
#include <asm/uaccess.h>
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 4c1ac341ec80..2456b52ed068 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -211,14 +211,14 @@ static int do_out_of_memory(struct pt_regs *regs, unsigned long error_code,
struct mm_struct *mm = tsk->mm;
up_read(&mm->mmap_sem);
- if (is_init(tsk)) {
+ if (is_global_init(tsk)) {
yield();
down_read(&mm->mmap_sem);
return 1;
}
printk("VM: killing process %s\n", tsk->comm);
if (regs->psw.mask & PSW_MASK_PSTATE)
- do_exit(SIGKILL);
+ do_group_exit(SIGKILL);
do_no_context(regs, error_code, address);
return 0;
}
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index 3a25bbf2eb0a..b234bb4a6da7 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -81,6 +81,7 @@ void show_mem(void)
static void __init setup_ro_region(void)
{
pgd_t *pgd;
+ pud_t *pud;
pmd_t *pmd;
pte_t *pte;
pte_t new_pte;
@@ -91,7 +92,8 @@ static void __init setup_ro_region(void)
for (; address < end; address += PAGE_SIZE) {
pgd = pgd_offset_k(address);
- pmd = pmd_offset(pgd, address);
+ pud = pud_offset(pgd, address);
+ pmd = pmd_offset(pud, address);
pte = pte_offset_kernel(pmd, address);
new_pte = mk_pte_phys(address, __pgprot(_PAGE_RO));
*pte = new_pte;
@@ -103,32 +105,28 @@ static void __init setup_ro_region(void)
*/
void __init paging_init(void)
{
- pgd_t *pg_dir;
- int i;
- unsigned long pgdir_k;
static const int ssm_mask = 0x04000000L;
unsigned long max_zone_pfns[MAX_NR_ZONES];
+ unsigned long pgd_type;
- pg_dir = swapper_pg_dir;
-
+ init_mm.pgd = swapper_pg_dir;
+ S390_lowcore.kernel_asce = __pa(init_mm.pgd) & PAGE_MASK;
#ifdef CONFIG_64BIT
- pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | _KERN_REGION_TABLE;
- for (i = 0; i < PTRS_PER_PGD; i++)
- pgd_clear_kernel(pg_dir + i);
+ S390_lowcore.kernel_asce |= _ASCE_TYPE_REGION3 | _ASCE_TABLE_LENGTH;
+ pgd_type = _REGION3_ENTRY_EMPTY;
#else
- pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | _KERNSEG_TABLE;
- for (i = 0; i < PTRS_PER_PGD; i++)
- pmd_clear_kernel((pmd_t *)(pg_dir + i));
+ S390_lowcore.kernel_asce |= _ASCE_TABLE_LENGTH;
+ pgd_type = _SEGMENT_ENTRY_EMPTY;
#endif
+ clear_table((unsigned long *) init_mm.pgd, pgd_type,
+ sizeof(unsigned long)*2048);
vmem_map_init();
setup_ro_region();
- S390_lowcore.kernel_asce = pgdir_k;
-
/* enable virtual mapping in kernel mode */
- __ctl_load(pgdir_k, 1, 1);
- __ctl_load(pgdir_k, 7, 7);
- __ctl_load(pgdir_k, 13, 13);
+ __ctl_load(S390_lowcore.kernel_asce, 1, 1);
+ __ctl_load(S390_lowcore.kernel_asce, 7, 7);
+ __ctl_load(S390_lowcore.kernel_asce, 13, 13);
__raw_local_irq_ssm(ssm_mask);
memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
new file mode 100644
index 000000000000..e60e0ae13402
--- /dev/null
+++ b/arch/s390/mm/pgtable.c
@@ -0,0 +1,94 @@
+/*
+ * arch/s390/mm/pgtable.c
+ *
+ * Copyright IBM Corp. 2007
+ * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/smp.h>
+#include <linux/highmem.h>
+#include <linux/slab.h>
+#include <linux/pagemap.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/quicklist.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/tlb.h>
+#include <asm/tlbflush.h>
+
+#ifndef CONFIG_64BIT
+#define ALLOC_ORDER 1
+#else
+#define ALLOC_ORDER 2
+#endif
+
+unsigned long *crst_table_alloc(struct mm_struct *mm, int noexec)
+{
+ struct page *page = alloc_pages(GFP_KERNEL, ALLOC_ORDER);
+
+ if (!page)
+ return NULL;
+ page->index = 0;
+ if (noexec) {
+ struct page *shadow = alloc_pages(GFP_KERNEL, ALLOC_ORDER);
+ if (!shadow) {
+ __free_pages(page, ALLOC_ORDER);
+ return NULL;
+ }
+ page->index = page_to_phys(shadow);
+ }
+ return (unsigned long *) page_to_phys(page);
+}
+
+void crst_table_free(unsigned long *table)
+{
+ unsigned long *shadow = get_shadow_table(table);
+
+ if (shadow)
+ free_pages((unsigned long) shadow, ALLOC_ORDER);
+ free_pages((unsigned long) table, ALLOC_ORDER);
+}
+
+/*
+ * page table entry allocation/free routines.
+ */
+unsigned long *page_table_alloc(int noexec)
+{
+ struct page *page = alloc_page(GFP_KERNEL);
+ unsigned long *table;
+
+ if (!page)
+ return NULL;
+ page->index = 0;
+ if (noexec) {
+ struct page *shadow = alloc_page(GFP_KERNEL);
+ if (!shadow) {
+ __free_page(page);
+ return NULL;
+ }
+ table = (unsigned long *) page_to_phys(shadow);
+ clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE);
+ page->index = (addr_t) table;
+ }
+ table = (unsigned long *) page_to_phys(page);
+ clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE);
+ return table;
+}
+
+void page_table_free(unsigned long *table)
+{
+ unsigned long *shadow = get_shadow_pte(table);
+
+ if (shadow)
+ free_page((unsigned long) shadow);
+ free_page((unsigned long) table);
+
+}
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index fd594d5fe142..fb9c5a85aa56 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -73,31 +73,28 @@ static void __init_refok *vmem_alloc_pages(unsigned int order)
return alloc_bootmem_pages((1 << order) * PAGE_SIZE);
}
+#define vmem_pud_alloc() ({ BUG(); ((pud_t *) NULL); })
+
static inline pmd_t *vmem_pmd_alloc(void)
{
- pmd_t *pmd;
- int i;
+ pmd_t *pmd = NULL;
- pmd = vmem_alloc_pages(PMD_ALLOC_ORDER);
+#ifdef CONFIG_64BIT
+ pmd = vmem_alloc_pages(2);
if (!pmd)
return NULL;
- for (i = 0; i < PTRS_PER_PMD; i++)
- pmd_clear_kernel(pmd + i);
+ clear_table((unsigned long *) pmd, _SEGMENT_ENTRY_EMPTY, PAGE_SIZE*4);
+#endif
return pmd;
}
static inline pte_t *vmem_pte_alloc(void)
{
- pte_t *pte;
- pte_t empty_pte;
- int i;
+ pte_t *pte = vmem_alloc_pages(0);
- pte = vmem_alloc_pages(PTE_ALLOC_ORDER);
if (!pte)
return NULL;
- pte_val(empty_pte) = _PAGE_TYPE_EMPTY;
- for (i = 0; i < PTRS_PER_PTE; i++)
- pte[i] = empty_pte;
+ clear_table((unsigned long *) pte, _PAGE_TYPE_EMPTY, PAGE_SIZE);
return pte;
}
@@ -108,6 +105,7 @@ static int vmem_add_range(unsigned long start, unsigned long size)
{
unsigned long address;
pgd_t *pg_dir;
+ pud_t *pu_dir;
pmd_t *pm_dir;
pte_t *pt_dir;
pte_t pte;
@@ -116,13 +114,21 @@ static int vmem_add_range(unsigned long start, unsigned long size)
for (address = start; address < start + size; address += PAGE_SIZE) {
pg_dir = pgd_offset_k(address);
if (pgd_none(*pg_dir)) {
+ pu_dir = vmem_pud_alloc();
+ if (!pu_dir)
+ goto out;
+ pgd_populate_kernel(&init_mm, pg_dir, pu_dir);
+ }
+
+ pu_dir = pud_offset(pg_dir, address);
+ if (pud_none(*pu_dir)) {
pm_dir = vmem_pmd_alloc();
if (!pm_dir)
goto out;
- pgd_populate_kernel(&init_mm, pg_dir, pm_dir);
+ pud_populate_kernel(&init_mm, pu_dir, pm_dir);
}
- pm_dir = pmd_offset(pg_dir, address);
+ pm_dir = pmd_offset(pu_dir, address);
if (pmd_none(*pm_dir)) {
pt_dir = vmem_pte_alloc();
if (!pt_dir)
@@ -148,6 +154,7 @@ static void vmem_remove_range(unsigned long start, unsigned long size)
{
unsigned long address;
pgd_t *pg_dir;
+ pud_t *pu_dir;
pmd_t *pm_dir;
pte_t *pt_dir;
pte_t pte;
@@ -155,9 +162,10 @@ static void vmem_remove_range(unsigned long start, unsigned long size)
pte_val(pte) = _PAGE_TYPE_EMPTY;
for (address = start; address < start + size; address += PAGE_SIZE) {
pg_dir = pgd_offset_k(address);
- if (pgd_none(*pg_dir))
+ pu_dir = pud_offset(pg_dir, address);
+ if (pud_none(*pu_dir))
continue;
- pm_dir = pmd_offset(pg_dir, address);
+ pm_dir = pmd_offset(pu_dir, address);
if (pmd_none(*pm_dir))
continue;
pt_dir = pte_offset_kernel(pm_dir, address);
@@ -174,6 +182,7 @@ static int vmem_add_mem_map(unsigned long start, unsigned long size)
unsigned long address, start_addr, end_addr;
struct page *map_start, *map_end;
pgd_t *pg_dir;
+ pud_t *pu_dir;
pmd_t *pm_dir;
pte_t *pt_dir;
pte_t pte;
@@ -188,13 +197,21 @@ static int vmem_add_mem_map(unsigned long start, unsigned long size)
for (address = start_addr; address < end_addr; address += PAGE_SIZE) {
pg_dir = pgd_offset_k(address);
if (pgd_none(*pg_dir)) {
+ pu_dir = vmem_pud_alloc();
+ if (!pu_dir)
+ goto out;
+ pgd_populate_kernel(&init_mm, pg_dir, pu_dir);
+ }
+
+ pu_dir = pud_offset(pg_dir, address);
+ if (pud_none(*pu_dir)) {
pm_dir = vmem_pmd_alloc();
if (!pm_dir)
goto out;
- pgd_populate_kernel(&init_mm, pg_dir, pm_dir);
+ pud_populate_kernel(&init_mm, pu_dir, pm_dir);
}
- pm_dir = pmd_offset(pg_dir, address);
+ pm_dir = pmd_offset(pu_dir, address);
if (pmd_none(*pm_dir)) {
pt_dir = vmem_pte_alloc();
if (!pt_dir)
diff --git a/arch/s390/oprofile/Kconfig b/arch/s390/oprofile/Kconfig
deleted file mode 100644
index 208220a5f23f..000000000000
--- a/arch/s390/oprofile/Kconfig
+++ /dev/null
@@ -1,22 +0,0 @@
-
-menu "Profiling support"
-
-config PROFILING
- bool "Profiling support"
- help
- Say Y here to enable profiling support mechanisms used by
- profilers such as readprofile or OProfile.
-
-
-config OPROFILE
- tristate "OProfile system profiling"
- depends on PROFILING
- help
- OProfile is a profiling system capable of profiling the
- whole system, include the kernel, kernel modules, libraries,
- and applications.
-
- If unsure, say N.
-
-endmenu
-
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 44982c1dfa23..496d635f89b2 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -182,9 +182,7 @@ config CPU_HAS_IPR_IRQ
bool
config CPU_HAS_SR_RB
- bool "CPU has SR.RB"
- depends on CPU_SH3 || CPU_SH4
- default y
+ bool
help
This will enable the use of SR.RB register bank usage. Processors
that are lacking this bit must have another method in place for
@@ -213,10 +211,12 @@ config SH_SOLUTION_ENGINE
bool "SolutionEngine"
select SOLUTION_ENGINE
select CPU_HAS_IPR_IRQ
- depends on CPU_SUBTYPE_SH7709 || CPU_SUBTYPE_SH7750
+ depends on CPU_SUBTYPE_SH7705 || CPU_SUBTYPE_SH7709 || CPU_SUBTYPE_SH7710 || \
+ CPU_SUBTYPE_SH7712 || CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7750S || \
+ CPU_SUBTYPE_SH7750R
help
- Select SolutionEngine if configuring for a Hitachi SH7709
- or SH7750 evaluation board.
+ Select SolutionEngine if configuring for a Hitachi SH7705, SH7709,
+ SH7710, SH7712, SH7750, SH7750S or SH7750R evaluation board.
config SH_7206_SOLUTION_ENGINE
bool "SolutionEngine7206"
@@ -291,9 +291,7 @@ config SH_DREAMCAST
depends on CPU_SUBTYPE_SH7091
help
Select Dreamcast if configuring for a SEGA Dreamcast.
- More information at
- <http://www.m17n.org/linux-sh/dreamcast/>. There is a
- Dreamcast project is at <http://linuxdc.sourceforge.net/>.
+ More information at <http://www.linux-sh.org>
config SH_MPC1211
bool "Interface MPC1211"
@@ -607,7 +605,7 @@ config BOOT_LINK_OFFSET
config UBC_WAKEUP
bool "Wakeup UBC on startup"
- depends on CPU_SH4
+ depends on CPU_SH4 && !CPU_SH4A
help
Selecting this option will wakeup the User Break Controller (UBC) on
startup. Although the UBC is left in an awake state when the processor
@@ -758,7 +756,7 @@ source "drivers/Kconfig"
source "fs/Kconfig"
-source "arch/sh/oprofile/Kconfig"
+source "kernel/Kconfig.instrumentation"
source "arch/sh/Kconfig.debug"
diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug
index b507b501f0cf..722da6851f56 100644
--- a/arch/sh/Kconfig.debug
+++ b/arch/sh/Kconfig.debug
@@ -86,6 +86,14 @@ config 4KSTACKS
on the VM subsystem for higher order allocations. This option
will also use IRQ stacks to compensate for the reduced stackspace.
+config IRQSTACKS
+ bool "Use separate kernel stacks when processing interrupts"
+ depends on DEBUG_KERNEL
+ help
+ If you say Y here the kernel will use separate kernel stacks
+ for handling hard and soft interrupts. This can help avoid
+ overflowing the process kernel stacks.
+
config SH_KGDB
bool "Include KGDB kernel debugger"
select FRAME_POINTER
@@ -116,12 +124,13 @@ config KGDB_NMI
config SH_KGDB_CONSOLE
bool "Console messages through GDB"
- depends on !SERIAL_SH_SCI_CONSOLE
+ depends on !SERIAL_SH_SCI_CONSOLE && SERIAL_SH_SCI=y
select SERIAL_CORE_CONSOLE
default n
config KGDB_SYSRQ
bool "Allow SysRq 'G' to enter KGDB"
+ depends on MAGIC_SYSRQ
default y
comment "Serial port setup"
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index a0a2083aad3e..e189fae8b60c 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -66,7 +66,7 @@ cflags-y += $(isaflags-y) -ffreestanding
cflags-$(CONFIG_MORE_COMPILE_OPTIONS) += \
$(shell echo $(CONFIG_COMPILE_OPTIONS) | sed -e 's/"//g')
-OBJCOPYFLAGS := -O binary -R .note -R .comment -R .stab -R .stabstr -S
+OBJCOPYFLAGS := -O binary -R .note -R .note.gnu.build-id -R .comment -R .stab -R .stabstr -S
#
# arch/sh/defconfig doesn't reflect any real hardware, and as such should
@@ -91,12 +91,12 @@ LDFLAGS_vmlinux += --defsym 'jiffies=jiffies_64+4'
LDFLAGS += -EB
endif
-CFLAGS += -pipe $(cflags-y)
-AFLAGS += $(cflags-y)
+KBUILD_CFLAGS += -pipe $(cflags-y)
+KBUILD_AFLAGS += $(cflags-y)
head-y := arch/sh/kernel/head.o arch/sh/kernel/init_task.o
-LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
+LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
core-y += arch/sh/kernel/ arch/sh/mm/
core-$(CONFIG_SH_FPU_EMU) += arch/sh/math-emu/
diff --git a/arch/sh/boards/hp6xx/pm.c b/arch/sh/boards/hp6xx/pm.c
index 8143d1b948e7..d22f6eac9cca 100644
--- a/arch/sh/boards/hp6xx/pm.c
+++ b/arch/sh/boards/hp6xx/pm.c
@@ -67,14 +67,14 @@ static int hp6x0_pm_enter(suspend_state_t state)
return 0;
}
-static struct pm_ops hp6x0_pm_ops = {
+static struct platform_suspend_ops hp6x0_pm_ops = {
.enter = hp6x0_pm_enter,
- .valid = pm_valid_only_mem,
+ .valid = suspend_valid_only_mem,
};
static int __init hp6x0_pm_init(void)
{
- pm_set_ops(&hp6x0_pm_ops);
+ suspend_set_ops(&hp6x0_pm_ops);
return 0;
}
diff --git a/arch/sh/boards/renesas/hs7751rvoip/irq.c b/arch/sh/boards/renesas/hs7751rvoip/irq.c
index 943f93aa6052..e55c6686b21f 100644
--- a/arch/sh/boards/renesas/hs7751rvoip/irq.c
+++ b/arch/sh/boards/renesas/hs7751rvoip/irq.c
@@ -12,6 +12,7 @@
#include <linux/init.h>
#include <linux/irq.h>
+#include <linux/interrupt.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/hs7751rvoip.h>
diff --git a/arch/sh/boards/renesas/hs7751rvoip/setup.c b/arch/sh/boards/renesas/hs7751rvoip/setup.c
index fa5fa3920222..c05625975f2c 100644
--- a/arch/sh/boards/renesas/hs7751rvoip/setup.c
+++ b/arch/sh/boards/renesas/hs7751rvoip/setup.c
@@ -15,20 +15,6 @@
#include <asm/io.h>
#include <asm/machvec.h>
-static struct ipr_data hs77501rvoip_ipr_map[] = {
-#if defined(CONFIG_HS7751RVOIP_CODEC)
- { DMTE0_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY },
- { DMTE1_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY },
-#endif
-};
-
-static void __init hs7751rvoip_init_irq(void)
-{
- make_ipr_irq(hs77501rvoip_ipr_map, ARRAY_SIZE(hs77501rvoip_ipr_map));
-
- init_hs7751rvoip_IRQ();
-}
-
static void hs7751rvoip_power_off(void)
{
ctrl_outw(ctrl_inw(PA_OUTPORTR) & 0xffdf, PA_OUTPORTR);
@@ -75,14 +61,13 @@ static int __init hs7751rvoip_cf_init(void)
return 0;
}
+device_initcall(hs7751rvoip_cf_init);
/*
* Initialize the board
*/
static void __init hs7751rvoip_setup(char **cmdline_p)
{
- device_initcall(hs7751rvoip_cf_init);
-
ctrl_outb(0xf0, PA_OUTPORTR);
pm_power_off = hs7751rvoip_power_off;
@@ -115,6 +100,6 @@ static struct sh_machine_vector mv_hs7751rvoip __initmv = {
.mv_outsw = hs7751rvoip_outsw,
.mv_outsl = hs7751rvoip_outsl,
- .mv_init_irq = hs7751rvoip_init_irq,
+ .mv_init_irq = init_hs7751rvoip_IRQ,
.mv_ioport_map = hs7751rvoip_ioport_map,
};
diff --git a/arch/sh/boards/renesas/r7780rp/setup.c b/arch/sh/boards/renesas/r7780rp/setup.c
index afe9de73666a..0fdc0bc19145 100644
--- a/arch/sh/boards/renesas/r7780rp/setup.c
+++ b/arch/sh/boards/renesas/r7780rp/setup.c
@@ -16,6 +16,8 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/pata_platform.h>
+#include <linux/types.h>
+#include <net/ax88796.h>
#include <asm/machvec.h>
#include <asm/r7780rp.h>
#include <asm/clock.h>
@@ -136,11 +138,50 @@ static struct platform_device heartbeat_device = {
.resource = heartbeat_resources,
};
+static struct ax_plat_data ax88796_platdata = {
+ .flags = AXFLG_HAS_93CX6,
+ .wordlength = 2,
+ .dcr_val = 0x1,
+ .rcr_val = 0x40,
+};
+
+static struct resource ax88796_resources[] = {
+ {
+#ifdef CONFIG_SH_R7780RP
+ .start = 0xa5800400,
+ .end = 0xa5800400 + (0x20 * 0x2) - 1,
+#else
+ .start = 0xa4100400,
+ .end = 0xa4100400 + (0x20 * 0x2) - 1,
+#endif
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_AX88796,
+ .end = IRQ_AX88796,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device ax88796_device = {
+ .name = "ax88796",
+ .id = 0,
+
+ .dev = {
+ .platform_data = &ax88796_platdata,
+ },
+
+ .num_resources = ARRAY_SIZE(ax88796_resources),
+ .resource = ax88796_resources,
+};
+
+
static struct platform_device *r7780rp_devices[] __initdata = {
&r8a66597_usb_host_device,
&m66592_usb_peripheral_device,
&cf_ide_device,
&heartbeat_device,
+ &ax88796_device,
};
static int __init r7780rp_devices_setup(void)
@@ -183,6 +224,34 @@ static void r7780rp_power_off(void)
ctrl_outw(0x0001, PA_POFF);
}
+static inline unsigned char is_ide_ioaddr(unsigned long addr)
+{
+ return ((cf_ide_resources[0].start <= addr &&
+ addr <= cf_ide_resources[0].end) ||
+ (cf_ide_resources[1].start <= addr &&
+ addr <= cf_ide_resources[1].end));
+}
+
+void highlander_writeb(u8 b, void __iomem *addr)
+{
+ unsigned long tmp = (unsigned long __force)addr;
+
+ if (is_ide_ioaddr(tmp))
+ ctrl_outw((u16)b, tmp);
+ else
+ ctrl_outb(b, tmp);
+}
+
+u8 highlander_readb(void __iomem *addr)
+{
+ unsigned long tmp = (unsigned long __force)addr;
+
+ if (is_ide_ioaddr(tmp))
+ return ctrl_inw(tmp) & 0xff;
+ else
+ return ctrl_inb(tmp);
+}
+
/*
* Initialize the board
*/
@@ -267,4 +336,6 @@ static struct sh_machine_vector mv_highlander __initmv = {
.mv_setup = highlander_setup,
.mv_init_irq = highlander_init_irq,
.mv_irq_demux = highlander_irq_demux,
+ .mv_readb = highlander_readb,
+ .mv_writeb = highlander_writeb,
};
diff --git a/arch/sh/boards/renesas/sh7710voipgw/setup.c b/arch/sh/boards/renesas/sh7710voipgw/setup.c
index 2dce8bd97f90..0d56fd83bcba 100644
--- a/arch/sh/boards/renesas/sh7710voipgw/setup.c
+++ b/arch/sh/boards/renesas/sh7710voipgw/setup.c
@@ -11,7 +11,6 @@
#include <asm/machvec.h>
#include <asm/irq.h>
#include <asm/io.h>
-#include <asm/irq.h>
static struct ipr_data sh7710voipgw_ipr_map[] = {
{ TIMER2_IRQ, TIMER2_IPR_ADDR, TIMER2_IPR_POS, TIMER2_PRIORITY },
diff --git a/arch/sh/boards/se/7206/irq.c b/arch/sh/boards/se/7206/irq.c
index 27da88486f73..9d5bfc77d0de 100644
--- a/arch/sh/boards/se/7206/irq.c
+++ b/arch/sh/boards/se/7206/irq.c
@@ -9,7 +9,6 @@
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/io.h>
-#include <linux/irq.h>
#include <linux/interrupt.h>
#include <asm/se7206.h>
diff --git a/arch/sh/boards/se/770x/setup.c b/arch/sh/boards/se/770x/setup.c
index d07a3368f546..318bc8a3969c 100644
--- a/arch/sh/boards/se/770x/setup.c
+++ b/arch/sh/boards/se/770x/setup.c
@@ -94,6 +94,7 @@ static unsigned char heartbeat_bit_pos[] = { 8, 9, 10, 11, 12, 13, 14, 15 };
static struct heartbeat_data heartbeat_data = {
.bit_pos = heartbeat_bit_pos,
.nr_bits = ARRAY_SIZE(heartbeat_bit_pos),
+ .regsize = 16,
};
static struct resource heartbeat_resources[] = {
diff --git a/arch/sh/boards/se/7722/setup.c b/arch/sh/boards/se/7722/setup.c
index 03b63457e178..eb97dca5b736 100644
--- a/arch/sh/boards/se/7722/setup.c
+++ b/arch/sh/boards/se/7722/setup.c
@@ -16,8 +16,13 @@
#include <asm/machvec.h>
#include <asm/se7722.h>
#include <asm/io.h>
+#include <asm/heartbeat.h>
/* Heartbeat */
+static struct heartbeat_data heartbeat_data = {
+ .regsize = 16,
+};
+
static struct resource heartbeat_resources[] = {
[0] = {
.start = PA_LED,
@@ -29,6 +34,9 @@ static struct resource heartbeat_resources[] = {
static struct platform_device heartbeat_device = {
.name = "heartbeat",
.id = -1,
+ .dev = {
+ .platform_data = &heartbeat_data,
+ },
.num_resources = ARRAY_SIZE(heartbeat_resources),
.resource = heartbeat_resources,
};
@@ -103,8 +111,8 @@ static void __init se7722_setup(char **cmdline_p)
ctrl_outl(0x00051001, MSTPCR0);
ctrl_outl(0x00000000, MSTPCR1);
- /* KEYSC, VOU, BEU, CEU, VEU, VPU, LCDC */
- ctrl_outl(0xffffbfC0, MSTPCR2);
+ /* KEYSC, VOU, BEU, CEU, VEU, VPU, LCDC, USB */
+ ctrl_outl(0xffffb7c0, MSTPCR2);
ctrl_outw(0x0000, PORT_PECR); /* PORT E 1 = IRQ5 ,E 0 = BS */
ctrl_outw(0x1000, PORT_PJCR); /* PORT J 1 = IRQ1,J 0 =IRQ0 */
diff --git a/arch/sh/boards/se/7780/setup.c b/arch/sh/boards/se/7780/setup.c
index 76e53b26a808..0f08ab3b2bec 100644
--- a/arch/sh/boards/se/7780/setup.c
+++ b/arch/sh/boards/se/7780/setup.c
@@ -14,8 +14,13 @@
#include <asm/machvec.h>
#include <asm/se7780.h>
#include <asm/io.h>
+#include <asm/heartbeat.h>
/* Heartbeat */
+static struct heartbeat_data heartbeat_data = {
+ .regsize = 16,
+};
+
static struct resource heartbeat_resources[] = {
[0] = {
.start = PA_LED,
@@ -27,6 +32,9 @@ static struct resource heartbeat_resources[] = {
static struct platform_device heartbeat_device = {
.name = "heartbeat",
.id = -1,
+ .dev = {
+ .platform_data = &heartbeat_data,
+ },
.num_resources = ARRAY_SIZE(heartbeat_resources),
.resource = heartbeat_resources,
};
diff --git a/arch/sh/boards/snapgear/Makefile b/arch/sh/boards/snapgear/Makefile
index 59fc976bfc2f..d2d2f4b6a502 100644
--- a/arch/sh/boards/snapgear/Makefile
+++ b/arch/sh/boards/snapgear/Makefile
@@ -2,5 +2,4 @@
# Makefile for the SnapGear specific parts of the kernel
#
-obj-y := setup.o io.o rtc.o
-
+obj-y := setup.o io.o
diff --git a/arch/sh/boards/snapgear/rtc.c b/arch/sh/boards/snapgear/rtc.c
deleted file mode 100644
index edb3dd936cbb..000000000000
--- a/arch/sh/boards/snapgear/rtc.c
+++ /dev/null
@@ -1,309 +0,0 @@
-/****************************************************************************/
-/*
- * linux/arch/sh/boards/snapgear/rtc.c -- Secureedge5410 RTC code
- *
- * Copyright (C) 2002 David McCullough <davidm@snapgear.com>
- * Copyright (C) 2003 Paul Mundt <lethal@linux-sh.org>
- *
- * The SecureEdge5410 can have one of 2 real time clocks, the SH
- * built in version or the preferred external DS1302. Here we work out
- * each to see what we have and then run with it.
- */
-/****************************************************************************/
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/rtc.h>
-#include <linux/mc146818rtc.h>
-#include <asm/io.h>
-
-static int use_ds1302;
-
-/****************************************************************************/
-/*
- * we need to implement a DS1302 driver here that can operate in
- * conjunction with the builtin rtc driver which is already quite friendly
- */
-/*****************************************************************************/
-
-#define RTC_CMD_READ 0x81 /* Read command */
-#define RTC_CMD_WRITE 0x80 /* Write command */
-
-#define RTC_ADDR_YEAR 0x06 /* Address of year register */
-#define RTC_ADDR_DAY 0x05 /* Address of day of week register */
-#define RTC_ADDR_MON 0x04 /* Address of month register */
-#define RTC_ADDR_DATE 0x03 /* Address of day of month register */
-#define RTC_ADDR_HOUR 0x02 /* Address of hour register */
-#define RTC_ADDR_MIN 0x01 /* Address of minute register */
-#define RTC_ADDR_SEC 0x00 /* Address of second register */
-
-#define RTC_RESET 0x1000
-#define RTC_IODATA 0x0800
-#define RTC_SCLK 0x0400
-
-#define set_dirp(x)
-#define get_dirp(x) 0
-#define set_dp(x) SECUREEDGE_WRITE_IOPORT(x, 0x1c00)
-#define get_dp(x) SECUREEDGE_READ_IOPORT()
-
-static void ds1302_sendbits(unsigned int val)
-{
- int i;
-
- for (i = 8; (i); i--, val >>= 1) {
- set_dp((get_dp() & ~RTC_IODATA) | ((val & 0x1) ? RTC_IODATA : 0));
- set_dp(get_dp() | RTC_SCLK); // clock high
- set_dp(get_dp() & ~RTC_SCLK); // clock low
- }
-}
-
-static unsigned int ds1302_recvbits(void)
-{
- unsigned int val;
- int i;
-
- for (i = 0, val = 0; (i < 8); i++) {
- val |= (((get_dp() & RTC_IODATA) ? 1 : 0) << i);
- set_dp(get_dp() | RTC_SCLK); // clock high
- set_dp(get_dp() & ~RTC_SCLK); // clock low
- }
- return(val);
-}
-
-static unsigned int ds1302_readbyte(unsigned int addr)
-{
- unsigned int val;
- unsigned long flags;
-
- local_irq_save(flags);
- set_dirp(get_dirp() | RTC_RESET | RTC_IODATA | RTC_SCLK);
- set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK));
-
- set_dp(get_dp() | RTC_RESET);
- ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_READ);
- set_dirp(get_dirp() & ~RTC_IODATA);
- val = ds1302_recvbits();
- set_dp(get_dp() & ~RTC_RESET);
- local_irq_restore(flags);
-
- return(val);
-}
-
-static void ds1302_writebyte(unsigned int addr, unsigned int val)
-{
- unsigned long flags;
-
- local_irq_save(flags);
- set_dirp(get_dirp() | RTC_RESET | RTC_IODATA | RTC_SCLK);
- set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK));
- set_dp(get_dp() | RTC_RESET);
- ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_WRITE);
- ds1302_sendbits(val);
- set_dp(get_dp() & ~RTC_RESET);
- local_irq_restore(flags);
-}
-
-static void ds1302_reset(void)
-{
- unsigned long flags;
- /* Hardware dependent reset/init */
- local_irq_save(flags);
- set_dirp(get_dirp() | RTC_RESET | RTC_IODATA | RTC_SCLK);
- set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK));
- local_irq_restore(flags);
-}
-
-/*****************************************************************************/
-
-static inline int bcd2int(int val)
-{
- return((((val & 0xf0) >> 4) * 10) + (val & 0xf));
-}
-
-static inline int int2bcd(int val)
-{
- return(((val / 10) << 4) + (val % 10));
-}
-
-/*****************************************************************************/
-/*
- * Write and Read some RAM in the DS1302, if it works assume it's there
- * Otherwise use the SH4 internal RTC
- */
-
-void snapgear_rtc_gettimeofday(struct timespec *);
-int snapgear_rtc_settimeofday(const time_t);
-
-void __init secureedge5410_rtc_init(void)
-{
- unsigned char *test = "snapgear";
- int i;
-
- ds1302_reset();
-
- use_ds1302 = 1;
-
- for (i = 0; test[i]; i++)
- ds1302_writebyte(32 + i, test[i]);
-
- for (i = 0; test[i]; i++)
- if (ds1302_readbyte(32 + i) != test[i]) {
- use_ds1302 = 0;
- break;
- }
-
- if (use_ds1302) {
- rtc_sh_get_time = snapgear_rtc_gettimeofday;
- rtc_sh_set_time = snapgear_rtc_settimeofday;
- }
-
- printk("SnapGear RTC: using %s rtc.\n", use_ds1302 ? "ds1302" : "internal");
-}
-
-/****************************************************************************/
-/*
- * our generic interface that chooses the correct code to use
- */
-
-void snapgear_rtc_gettimeofday(struct timespec *ts)
-{
- unsigned int sec, min, hr, day, mon, yr;
-
- if (!use_ds1302)
- return;
-
- sec = bcd2int(ds1302_readbyte(RTC_ADDR_SEC));
- min = bcd2int(ds1302_readbyte(RTC_ADDR_MIN));
- hr = bcd2int(ds1302_readbyte(RTC_ADDR_HOUR));
- day = bcd2int(ds1302_readbyte(RTC_ADDR_DATE));
- mon = bcd2int(ds1302_readbyte(RTC_ADDR_MON));
- yr = bcd2int(ds1302_readbyte(RTC_ADDR_YEAR));
-
-bad_time:
- if (yr > 99 || mon < 1 || mon > 12 || day > 31 || day < 1 ||
- hr > 23 || min > 59 || sec > 59) {
- printk(KERN_ERR
- "SnapGear RTC: invalid value, resetting to 1 Jan 2000\n");
- ds1302_writebyte(RTC_ADDR_MIN, min = 0);
- ds1302_writebyte(RTC_ADDR_HOUR, hr = 0);
- ds1302_writebyte(RTC_ADDR_DAY, 7);
- ds1302_writebyte(RTC_ADDR_DATE, day = 1);
- ds1302_writebyte(RTC_ADDR_MON, mon = 1);
- ds1302_writebyte(RTC_ADDR_YEAR, yr = 0);
- ds1302_writebyte(RTC_ADDR_SEC, sec = 0);
- }
-
- ts->tv_sec = mktime(2000 + yr, mon, day, hr, min, sec);
- if (ts->tv_sec < 0) {
-#if 0
- printk("BAD TIME %d %d %d %d %d %d\n", yr, mon, day, hr, min, sec);
-#endif
- yr = 100;
- goto bad_time;
- }
- ts->tv_nsec = 0;
-}
-
-int snapgear_rtc_settimeofday(const time_t secs)
-{
- int retval = 0;
- int real_seconds, real_minutes, cmos_minutes;
- unsigned long nowtime;
-
- if (!use_ds1302)
- return 0;
-
-/*
- * This is called direct from the kernel timer handling code.
- * It is supposed to synchronize the kernel clock to the RTC.
- */
-
- nowtime = secs;
-
- /* STOP RTC */
- ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) | 0x80);
-
- cmos_minutes = bcd2int(ds1302_readbyte(RTC_ADDR_MIN));
-
- /*
- * since we're only adjusting minutes and seconds,
- * don't interfere with hour overflow. This avoids
- * messing with unknown time zones but requires your
- * RTC not to be off by more than 15 minutes
- */
- real_seconds = nowtime % 60;
- real_minutes = nowtime / 60;
- if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
- real_minutes += 30; /* correct for half hour time zone */
- real_minutes %= 60;
-
- if (abs(real_minutes - cmos_minutes) < 30) {
- ds1302_writebyte(RTC_ADDR_MIN, int2bcd(real_minutes));
- ds1302_writebyte(RTC_ADDR_SEC, int2bcd(real_seconds));
- } else {
- printk(KERN_WARNING
- "SnapGear RTC: can't update from %d to %d\n",
- cmos_minutes, real_minutes);
- retval = -1;
- }
-
- /* START RTC */
- ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) & ~0x80);
- return(0);
-}
-
-unsigned char secureedge5410_cmos_read(int addr)
-{
- unsigned char val = 0;
-
- if (!use_ds1302)
- return(__CMOS_READ(addr, w));
-
- switch(addr) {
- case RTC_SECONDS: val = ds1302_readbyte(RTC_ADDR_SEC); break;
- case RTC_SECONDS_ALARM: break;
- case RTC_MINUTES: val = ds1302_readbyte(RTC_ADDR_MIN); break;
- case RTC_MINUTES_ALARM: break;
- case RTC_HOURS: val = ds1302_readbyte(RTC_ADDR_HOUR); break;
- case RTC_HOURS_ALARM: break;
- case RTC_DAY_OF_WEEK: val = ds1302_readbyte(RTC_ADDR_DAY); break;
- case RTC_DAY_OF_MONTH: val = ds1302_readbyte(RTC_ADDR_DATE); break;
- case RTC_MONTH: val = ds1302_readbyte(RTC_ADDR_MON); break;
- case RTC_YEAR: val = ds1302_readbyte(RTC_ADDR_YEAR); break;
- case RTC_REG_A: /* RTC_FREQ_SELECT */ break;
- case RTC_REG_B: /* RTC_CONTROL */ break;
- case RTC_REG_C: /* RTC_INTR_FLAGS */ break;
- case RTC_REG_D: val = RTC_VRT /* RTC_VALID */; break;
- default: break;
- }
-
- return(val);
-}
-
-void secureedge5410_cmos_write(unsigned char val, int addr)
-{
- if (!use_ds1302) {
- __CMOS_WRITE(val, addr, w);
- return;
- }
-
- switch(addr) {
- case RTC_SECONDS: ds1302_writebyte(RTC_ADDR_SEC, val); break;
- case RTC_SECONDS_ALARM: break;
- case RTC_MINUTES: ds1302_writebyte(RTC_ADDR_MIN, val); break;
- case RTC_MINUTES_ALARM: break;
- case RTC_HOURS: ds1302_writebyte(RTC_ADDR_HOUR, val); break;
- case RTC_HOURS_ALARM: break;
- case RTC_DAY_OF_WEEK: ds1302_writebyte(RTC_ADDR_DAY, val); break;
- case RTC_DAY_OF_MONTH: ds1302_writebyte(RTC_ADDR_DATE, val); break;
- case RTC_MONTH: ds1302_writebyte(RTC_ADDR_MON, val); break;
- case RTC_YEAR: ds1302_writebyte(RTC_ADDR_YEAR, val); break;
- case RTC_REG_A: /* RTC_FREQ_SELECT */ break;
- case RTC_REG_B: /* RTC_CONTROL */ break;
- case RTC_REG_C: /* RTC_INTR_FLAGS */ break;
- case RTC_REG_D: /* RTC_VALID */ break;
- default: break;
- }
-}
diff --git a/arch/sh/boards/snapgear/setup.c b/arch/sh/boards/snapgear/setup.c
index 2b594f600002..7022483f98e8 100644
--- a/arch/sh/boards/snapgear/setup.c
+++ b/arch/sh/boards/snapgear/setup.c
@@ -22,20 +22,15 @@
#include <asm/snapgear.h>
#include <asm/irq.h>
#include <asm/io.h>
-#include <asm/rtc.h>
#include <asm/cpu/timer.h>
-extern void secureedge5410_rtc_init(void);
-extern void pcibios_init(void);
-
-/****************************************************************************/
/*
* EraseConfig handling functions
*/
static irqreturn_t eraseconfig_interrupt(int irq, void *dev_id)
{
- volatile char dummy __attribute__((unused)) = * (volatile char *) 0xb8000000;
+ (void)ctrl_inb(0xb8000000); /* dummy read */
printk("SnapGear: erase switch interrupt!\n");
@@ -76,19 +71,10 @@ static void __init init_snapgear_IRQ(void)
}
/*
- * Initialize the board
- */
-static void __init snapgear_setup(char **cmdline_p)
-{
- board_time_init = secureedge5410_rtc_init;
-}
-
-/*
* The Machine Vector
*/
static struct sh_machine_vector mv_snapgear __initmv = {
.mv_name = "SnapGear SecureEdge5410",
- .mv_setup = snapgear_setup,
.mv_nr_irqs = 72,
.mv_inb = snapgear_inb,
diff --git a/arch/sh/boot/Makefile b/arch/sh/boot/Makefile
index 4c5ffdcd55b6..1b0f5be01d10 100644
--- a/arch/sh/boot/Makefile
+++ b/arch/sh/boot/Makefile
@@ -39,7 +39,7 @@ KERNEL_LOAD := $(shell /bin/bash -c 'printf "0x%8x" \
quiet_cmd_uimage = UIMAGE $@
cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A sh -O linux -T kernel \
- -C gzip -a $(KERNEL_LOAD) -e $(KERNEL_LOAD) \
+ -C none -a $(KERNEL_LOAD) -e $(KERNEL_LOAD) \
-n 'Linux-$(KERNELRELEASE)' -d $< $@
$(obj)/uImage: $(obj)/zImage FORCE
diff --git a/arch/sh/boot/compressed/Makefile b/arch/sh/boot/compressed/Makefile
index 013504ae1122..906a13f82fe0 100644
--- a/arch/sh/boot/compressed/Makefile
+++ b/arch/sh/boot/compressed/Makefile
@@ -21,7 +21,7 @@ IMAGE_OFFSET := $(shell /bin/bash -c 'printf "0x%08x" \
$(CONFIG_MEMORY_START) + \
$(CONFIG_BOOT_LINK_OFFSET)]')
-LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
+LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup -T $(obj)/../../kernel/vmlinux.lds
diff --git a/arch/sh/cchips/hd6446x/Makefile b/arch/sh/cchips/hd6446x/Makefile
index a106dd9db986..f7de4076e242 100644
--- a/arch/sh/cchips/hd6446x/Makefile
+++ b/arch/sh/cchips/hd6446x/Makefile
@@ -1,2 +1,4 @@
obj-$(CONFIG_HD64461) += hd64461.o
obj-$(CONFIG_HD64465) += hd64465/
+
+EXTRA_CFLAGS += -Werror
diff --git a/arch/sh/cchips/voyagergx/Makefile b/arch/sh/cchips/voyagergx/Makefile
index 085de72fd327..f73963cb3744 100644
--- a/arch/sh/cchips/voyagergx/Makefile
+++ b/arch/sh/cchips/voyagergx/Makefile
@@ -6,3 +6,4 @@ obj-y := irq.o setup.o
obj-$(CONFIG_USB_OHCI_HCD) += consistent.o
+EXTRA_CFLAGS += -Werror
diff --git a/arch/sh/configs/r7785rp_defconfig b/arch/sh/configs/r7785rp_defconfig
index 5c29338532da..158e03f0b1ef 100644
--- a/arch/sh/configs/r7785rp_defconfig
+++ b/arch/sh/configs/r7785rp_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.22-rc4
-# Thu Jul 12 12:33:15 2007
+# Linux kernel version: 2.6.24-rc1
+# Fri Nov 2 14:30:49 2007
#
CONFIG_SUPERH=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
@@ -13,39 +13,40 @@ CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_SYS_SUPPORTS_NUMA=y
CONFIG_SYS_SUPPORTS_PCI=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_NO_VIRT_TO_BUS=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
-# Code maturity level options
+# General setup
#
CONFIG_EXPERIMENTAL=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_LOCK_KERNEL=y
CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
# CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
+# CONFIG_USER_NS is not set
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_FAIR_USER_SCHED=y
+# CONFIG_FAIR_CGROUP_SCHED is not set
# CONFIG_SYSFS_DEPRECATED is not set
# CONFIG_RELAY is not set
# CONFIG_BLK_DEV_INITRD is not set
@@ -66,7 +67,6 @@ CONFIG_BASE_FULL=y
CONFIG_ANON_INODES=y
# CONFIG_EPOLL is not set
CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
@@ -75,24 +75,17 @@ CONFIG_SLAB=y
# CONFIG_SLOB is not set
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-
-#
-# Loadable module support
-#
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
-
-#
-# Block layer
-#
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
#
# IO Schedulers
@@ -115,7 +108,6 @@ CONFIG_CPU_SH4A=y
CONFIG_CPU_SHX2=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
-# CONFIG_CPU_SUBTYPE_SH7300 is not set
# CONFIG_CPU_SUBTYPE_SH7705 is not set
# CONFIG_CPU_SUBTYPE_SH7706 is not set
# CONFIG_CPU_SUBTYPE_SH7707 is not set
@@ -123,6 +115,7 @@ CONFIG_CPU_SHX2=y
# CONFIG_CPU_SUBTYPE_SH7709 is not set
# CONFIG_CPU_SUBTYPE_SH7710 is not set
# CONFIG_CPU_SUBTYPE_SH7712 is not set
+# CONFIG_CPU_SUBTYPE_SH7720 is not set
# CONFIG_CPU_SUBTYPE_SH7750 is not set
# CONFIG_CPU_SUBTYPE_SH7091 is not set
# CONFIG_CPU_SUBTYPE_SH7750R is not set
@@ -137,7 +130,6 @@ CONFIG_CPU_SHX2=y
# CONFIG_CPU_SUBTYPE_SH7780 is not set
CONFIG_CPU_SUBTYPE_SH7785=y
# CONFIG_CPU_SUBTYPE_SHX3 is not set
-# CONFIG_CPU_SUBTYPE_SH73180 is not set
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
@@ -149,15 +141,17 @@ CONFIG_MMU=y
CONFIG_PAGE_OFFSET=0x80000000
CONFIG_MEMORY_START=0x08000000
CONFIG_MEMORY_SIZE=0x08000000
-CONFIG_32BIT=y
+# CONFIG_32BIT is not set
# CONFIG_X2TLB is not set
CONFIG_VSYSCALL=y
+# CONFIG_NUMA is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_SPARSEMEM_ENABLE=y
CONFIG_ARCH_SPARSEMEM_DEFAULT=y
-CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_MAX_ACTIVE_REGIONS=2
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_8KB is not set
# CONFIG_PAGE_SIZE_64KB is not set
@@ -167,12 +161,14 @@ CONFIG_HUGETLB_PAGE_SIZE_1MB=y
# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set
# CONFIG_HUGETLB_PAGE_SIZE_64MB is not set
CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
+# CONFIG_FLATMEM_MANUAL is not set
# CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
CONFIG_SPARSEMEM_STATIC=y
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+# CONFIG_MEMORY_HOTPLUG is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
@@ -182,7 +178,9 @@ CONFIG_NR_QUICK=2
# Cache configuration
#
# CONFIG_SH_DIRECT_MAPPED is not set
-# CONFIG_SH_WRITETHROUGH is not set
+CONFIG_CACHE_WRITEBACK=y
+# CONFIG_CACHE_WRITETHROUGH is not set
+# CONFIG_CACHE_OFF is not set
#
# Processor features
@@ -190,12 +188,11 @@ CONFIG_NR_QUICK=2
CONFIG_CPU_LITTLE_ENDIAN=y
# CONFIG_CPU_BIG_ENDIAN is not set
CONFIG_SH_FPU=y
-# CONFIG_SH_DSP is not set
CONFIG_SH_STORE_QUEUES=y
CONFIG_CPU_HAS_INTEVT=y
-CONFIG_CPU_HAS_INTC2_IRQ=y
CONFIG_CPU_HAS_SR_RB=y
CONFIG_CPU_HAS_PTEA=y
+CONFIG_CPU_HAS_FPU=y
#
# Board support
@@ -214,6 +211,7 @@ CONFIG_SH_PCLK_FREQ=50000000
# CONFIG_TICK_ONESHOT is not set
# CONFIG_NO_HZ is not set
# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
#
# CPU Frequency scaling
@@ -249,6 +247,7 @@ CONFIG_KEXEC=y
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
CONFIG_PREEMPT_BKL=y
+CONFIG_GUSA=y
#
# Boot options
@@ -268,10 +267,6 @@ CONFIG_PCI_AUTO=y
CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
# CONFIG_ARCH_SUPPORTS_MSI is not set
# CONFIG_PCI_DEBUG is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
@@ -322,6 +317,7 @@ CONFIG_IP_PNP_DHCP=y
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
@@ -348,10 +344,6 @@ CONFIG_LLC=m
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
# CONFIG_NET_SCHED is not set
#
@@ -371,6 +363,7 @@ CONFIG_WIRELESS_EXT=y
# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
#
# Device Drivers
@@ -379,33 +372,17 @@ CONFIG_WIRELESS_EXT=y
#
# Generic Driver Options
#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=m
# CONFIG_DEBUG_DRIVER is not set
# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
# CONFIG_CONNECTOR is not set
# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNPACPI is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_CPQ_DA is not set
+CONFIG_BLK_DEV=y
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
@@ -419,14 +396,11 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
-
-#
-# Misc devices
-#
+CONFIG_MISC_DEVICES=y
# CONFIG_PHANTOM is not set
+CONFIG_EEPROM_93CX6=y
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
-# CONFIG_BLINK is not set
# CONFIG_IDE is not set
#
@@ -434,6 +408,7 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
# CONFIG_SCSI_TGT is not set
# CONFIG_SCSI_NETLINK is not set
CONFIG_SCSI_PROC_FS=y
@@ -463,12 +438,9 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SPI_ATTRS is not set
# CONFIG_SCSI_FC_ATTRS is not set
# CONFIG_SCSI_ISCSI_ATTRS is not set
-# CONFIG_SCSI_SAS_ATTRS is not set
# CONFIG_SCSI_SAS_LIBSAS is not set
-
-#
-# SCSI low-level drivers
-#
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
@@ -478,7 +450,6 @@ CONFIG_SCSI_WAIT_SCAN=m
# 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_ARCMSR is not set
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
@@ -543,6 +514,7 @@ CONFIG_SATA_SIL=y
# CONFIG_PATA_OLDPIIX is not set
# CONFIG_PATA_NETCELL is not set
# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_NS87415 is not set
# CONFIG_PATA_OPTI is not set
# CONFIG_PATA_OPTIDMA is not set
# CONFIG_PATA_PDC_OLD is not set
@@ -556,45 +528,26 @@ CONFIG_SATA_SIL=y
# CONFIG_PATA_VIA is not set
# CONFIG_PATA_WINBOND is not set
CONFIG_PATA_PLATFORM=y
-
-#
-# Multi-device support (RAID and LVM)
-#
# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
# CONFIG_FUSION is not set
-# CONFIG_FUSION_SPI is not set
-# CONFIG_FUSION_FC is not set
-# CONFIG_FUSION_SAS is not set
#
# IEEE 1394 (FireWire) support
#
# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
# CONFIG_I2O is not set
-
-#
-# Network device support
-#
CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
# CONFIG_DUMMY is not set
# 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_IP1000 is not set
# CONFIG_ARCNET is not set
# CONFIG_PHYLIB is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
# CONFIG_STNIC is not set
@@ -603,17 +556,20 @@ CONFIG_MII=y
# CONFIG_CASSINI is not set
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_SMC91X is not set
-
-#
-# Tulip family network device support
-#
+# CONFIG_SMC911X is not set
# CONFIG_NET_TULIP 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_NET_PCI is not set
+# CONFIG_B44 is not set
CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
@@ -631,11 +587,14 @@ CONFIG_R8169=y
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
# CONFIG_CHELSIO_T3 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_CORE is not set
+# CONFIG_TEHUTI is not set
# CONFIG_TR is not set
#
@@ -653,15 +612,7 @@ CONFIG_NETDEV_10000=y
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
# CONFIG_PHONE is not set
#
@@ -669,6 +620,7 @@ CONFIG_NETDEV_10000=y
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -678,7 +630,6 @@ CONFIG_INPUT_MOUSEDEV=y
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
# CONFIG_INPUT_EVDEV is not set
# CONFIG_INPUT_EVBUG is not set
@@ -732,21 +683,11 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
# CONFIG_IPMI_HANDLER is not set
-# CONFIG_WATCHDOG is not set
CONFIG_HW_RANDOM=y
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
-# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
# CONFIG_TCG_TPM is not set
CONFIG_DEVPORT=y
# CONFIG_I2C is not set
@@ -756,21 +697,31 @@ CONFIG_DEVPORT=y
#
# CONFIG_SPI is not set
# CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
#
# Multifunction device drivers
@@ -787,19 +738,16 @@ CONFIG_HWMON=y
#
# Graphics support
#
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Display device support
-#
-# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_DRM is not set
# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
CONFIG_FB=y
# CONFIG_FIRMWARE_EDID is not set
# CONFIG_FB_DDC is not set
# CONFIG_FB_CFB_FILLRECT is not set
# CONFIG_FB_CFB_COPYAREA is not set
# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
# CONFIG_FB_SYS_FILLRECT is not set
# CONFIG_FB_SYS_COPYAREA is not set
# CONFIG_FB_SYS_IMAGEBLIT is not set
@@ -819,7 +767,6 @@ CONFIG_FB_DEFERRED_IO=y
# CONFIG_FB_CYBER2000 is not set
# CONFIG_FB_ASILIANT is not set
# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_EPSON1355 is not set
# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_NVIDIA is not set
# CONFIG_FB_RIVA is not set
@@ -839,6 +786,12 @@ CONFIG_FB_DEFERRED_IO=y
# CONFIG_FB_ARK is not set
# CONFIG_FB_PM3 is not set
# CONFIG_FB_VIRTUAL is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
# CONFIG_LOGO is not set
#
@@ -855,20 +808,14 @@ CONFIG_SOUND=m
# Open Sound System
#
CONFIG_SOUND_PRIME=m
-# CONFIG_OSS_OBSOLETE is not set
# CONFIG_SOUND_TRIDENT is not set
# CONFIG_SOUND_MSNDCLAS is not set
# CONFIG_SOUND_MSNDPIN is not set
-
-#
-# HID Devices
-#
+CONFIG_HID_SUPPORT=y
CONFIG_HID=y
# CONFIG_HID_DEBUG is not set
-
-#
-# USB support
-#
+# CONFIG_HIDRAW 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
@@ -883,32 +830,8 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
# CONFIG_USB_GADGET is not set
# CONFIG_MMC is not set
-
-#
-# LED devices
-#
# CONFIG_NEW_LEDS is not set
-
-#
-# LED drivers
-#
-
-#
-# LED Triggers
-#
-
-#
-# InfiniBand support
-#
# CONFIG_INFINIBAND is not set
-
-#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
-#
-
-#
-# Real Time Clock
-#
CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_HCTOSYS=y
@@ -925,10 +848,6 @@ CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_DRV_TEST is not set
#
-# I2C RTC drivers
-#
-
-#
# SPI RTC drivers
#
@@ -936,8 +855,10 @@ CONFIG_RTC_INTF_DEV=y
# Platform RTC drivers
#
# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_DS1742 is not set
# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
# CONFIG_RTC_DRV_V3020 is not set
#
@@ -946,17 +867,9 @@ CONFIG_RTC_INTF_DEV=y
CONFIG_RTC_DRV_SH=y
#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
+# Userspace I/O
#
+# CONFIG_UIO is not set
#
# File systems
@@ -1017,7 +930,6 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
-CONFIG_RAMFS=y
CONFIG_CONFIGFS_FS=m
#
@@ -1036,10 +948,7 @@ CONFIG_CONFIGFS_FS=m
# CONFIG_QNX4FS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
+CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
@@ -1065,17 +974,12 @@ CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
#
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
CONFIG_NLS_CODEPAGE_437=y
@@ -1116,23 +1020,18 @@ CONFIG_NLS_ISO8859_1=y
# CONFIG_NLS_KOI8_R is not set
# CONFIG_NLS_KOI8_U is not set
# CONFIG_NLS_UTF8 is not set
-
-#
-# Distributed Lock Manager
-#
# CONFIG_DLM is not set
-
-#
-# Profiling support
-#
+CONFIG_INSTRUMENTATION=y
CONFIG_PROFILING=y
CONFIG_OPROFILE=m
+# CONFIG_MARKERS is not set
#
# Kernel hacking
#
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
@@ -1141,6 +1040,7 @@ CONFIG_DEBUG_FS=y
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
# CONFIG_DETECT_SOFTLOCKUP is not set
+CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
# CONFIG_DEBUG_SLAB is not set
@@ -1150,6 +1050,7 @@ CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_LOCK_ALLOC=y
# CONFIG_PROVE_LOCKING is not set
CONFIG_LOCKDEP=y
+# CONFIG_LOCK_STAT is not set
# CONFIG_DEBUG_LOCKDEP is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
CONFIG_DEBUG_LOCKING_API_SELFTESTS=y
@@ -1159,17 +1060,21 @@ CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
CONFIG_FRAME_POINTER=y
CONFIG_FORCED_INLINING=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_FAULT_INJECTION is not set
+# CONFIG_SAMPLES is not set
CONFIG_SH_STANDARD_BIOS=y
# CONFIG_EARLY_SCIF_CONSOLE is not set
CONFIG_EARLY_PRINTK=y
# CONFIG_DEBUG_BOOTMEM is not set
CONFIG_DEBUG_STACKOVERFLOW=y
CONFIG_DEBUG_STACK_USAGE=y
-# CONFIG_4KSTACKS is not set
+CONFIG_4KSTACKS=y
+# CONFIG_IRQSTACKS is not set
# CONFIG_SH_KGDB is not set
#
@@ -1177,10 +1082,7 @@ CONFIG_DEBUG_STACK_USAGE=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_CRYPTO=y
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_BLKCIPHER=y
@@ -1201,6 +1103,7 @@ CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_XTS is not set
# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_FCRYPT is not set
@@ -1214,15 +1117,14 @@ CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_ARC4 is not set
# CONFIG_CRYPTO_KHAZAD is not set
# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_SEED is not set
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_MICHAEL_MIC is not set
# CONFIG_CRYPTO_CRC32C is not set
# CONFIG_CRYPTO_CAMELLIA is not set
# CONFIG_CRYPTO_TEST is not set
-
-#
-# Hardware crypto devices
-#
+# CONFIG_CRYPTO_AUTHENC is not set
+CONFIG_CRYPTO_HW=y
#
# Library routines
@@ -1232,6 +1134,7 @@ CONFIG_BITREVERSE=y
# CONFIG_CRC16 is not set
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
# CONFIG_LIBCRC32C is not set
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
diff --git a/arch/sh/drivers/pci/Makefile b/arch/sh/drivers/pci/Makefile
index 2f65ac72f48a..fba6b5ba0b3a 100644
--- a/arch/sh/drivers/pci/Makefile
+++ b/arch/sh/drivers/pci/Makefile
@@ -5,7 +5,6 @@
obj-y += pci.o
obj-$(CONFIG_PCI_AUTO) += pci-auto.o
-obj-$(CONFIG_CPU_SUBTYPE_ST40STB1) += pci-st40.o
obj-$(CONFIG_CPU_SUBTYPE_SH7751) += pci-sh7751.o ops-sh4.o
obj-$(CONFIG_CPU_SUBTYPE_SH7751R) += pci-sh7751.o ops-sh4.o
obj-$(CONFIG_CPU_SUBTYPE_SH7780) += pci-sh7780.o ops-sh4.o
diff --git a/arch/sh/drivers/pci/dma-dreamcast.c b/arch/sh/drivers/pci/dma-dreamcast.c
index 230d6ec0d239..888a34050599 100644
--- a/arch/sh/drivers/pci/dma-dreamcast.c
+++ b/arch/sh/drivers/pci/dma-dreamcast.c
@@ -51,7 +51,7 @@ void *dreamcast_consistent_alloc(struct device *dev, size_t size,
buf = P2SEGADDR(buf);
/* Flush the dcache before we hand off the buffer */
- dma_cache_wback_inv((void *)buf, size);
+ __flush_purge_region((void *)buf, size);
return (void *)buf;
}
diff --git a/arch/sh/drivers/pci/pci-st40.c b/arch/sh/drivers/pci/pci-st40.c
deleted file mode 100644
index 1502a14386b6..000000000000
--- a/arch/sh/drivers/pci/pci-st40.c
+++ /dev/null
@@ -1,488 +0,0 @@
-/*
- * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * Support functions for the ST40 PCI hardware.
- */
-
-#include <linux/kernel.h>
-#include <linux/smp.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/types.h>
-#include <asm/pci.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h> /* irqreturn_t */
-
-#include "pci-st40.h"
-
-/* This is in P2 of course */
-#define ST40PCI_BASE_ADDRESS (0xb0000000)
-#define ST40PCI_MEM_ADDRESS (ST40PCI_BASE_ADDRESS+0x0)
-#define ST40PCI_IO_ADDRESS (ST40PCI_BASE_ADDRESS+0x06000000)
-#define ST40PCI_REG_ADDRESS (ST40PCI_BASE_ADDRESS+0x07000000)
-
-#define ST40PCI_REG(x) (ST40PCI_REG_ADDRESS+(ST40PCI_##x))
-#define ST40PCI_REG_INDEXED(reg, index) \
- (ST40PCI_REG(reg##0) + \
- ((ST40PCI_REG(reg##1) - ST40PCI_REG(reg##0))*index))
-
-#define ST40PCI_WRITE(reg,val) writel((val),ST40PCI_REG(reg))
-#define ST40PCI_WRITE_SHORT(reg,val) writew((val),ST40PCI_REG(reg))
-#define ST40PCI_WRITE_BYTE(reg,val) writeb((val),ST40PCI_REG(reg))
-#define ST40PCI_WRITE_INDEXED(reg, index, val) \
- writel((val), ST40PCI_REG_INDEXED(reg, index));
-
-#define ST40PCI_READ(reg) readl(ST40PCI_REG(reg))
-#define ST40PCI_READ_SHORT(reg) readw(ST40PCI_REG(reg))
-#define ST40PCI_READ_BYTE(reg) readb(ST40PCI_REG(reg))
-
-#define ST40PCI_SERR_IRQ 64
-#define ST40PCI_ERR_IRQ 65
-
-
-/* Macros to extract PLL params */
-#define PLL_MDIV(reg) ( ((unsigned)reg) & 0xff )
-#define PLL_NDIV(reg) ( (((unsigned)reg)>>8) & 0xff )
-#define PLL_PDIV(reg) ( (((unsigned)reg)>>16) & 0x3 )
-#define PLL_SETUP(reg) ( (((unsigned)reg)>>19) & 0x1ff )
-
-/* Build up the appropriate settings */
-#define PLL_SET(mdiv,ndiv,pdiv,setup) \
-( ((mdiv)&0xff) | (((ndiv)&0xff)<<8) | (((pdiv)&3)<<16)| (((setup)&0x1ff)<<19))
-
-#define PLLPCICR (0xbb040000+0x10)
-
-#define PLLPCICR_POWERON (1<<28)
-#define PLLPCICR_OUT_EN (1<<29)
-#define PLLPCICR_LOCKSELECT (1<<30)
-#define PLLPCICR_LOCK (1<<31)
-
-
-#define PLL_25MHZ 0x793c8512
-#define PLL_33MHZ PLL_SET(18,88,3,295)
-
-static void pci_set_rbar_region(unsigned int region, unsigned long localAddr,
- unsigned long pciOffset, unsigned long regionSize);
-
-static __init void SetPCIPLL(void)
-{
- {
- /* Lets play with the PLL values */
- unsigned long pll1cr1;
- unsigned long mdiv, ndiv, pdiv;
- unsigned long muxcr;
- unsigned int muxcr_ratios[4] = { 8, 16, 21, 1 };
- unsigned int freq;
-
-#define CLKGENA 0xbb040000
-#define CLKGENA_PLL2_MUXCR CLKGENA + 0x48
- pll1cr1 = ctrl_inl(PLLPCICR);
- printk("PLL1CR1 %08lx\n", pll1cr1);
- mdiv = PLL_MDIV(pll1cr1);
- ndiv = PLL_NDIV(pll1cr1);
- pdiv = PLL_PDIV(pll1cr1);
- printk("mdiv %02lx ndiv %02lx pdiv %02lx\n", mdiv, ndiv, pdiv);
- freq = ((2*27*ndiv)/mdiv) / (1 << pdiv);
- printk("PLL freq %dMHz\n", freq);
- muxcr = ctrl_inl(CLKGENA_PLL2_MUXCR);
- printk("PCI freq %dMhz\n", freq / muxcr_ratios[muxcr & 3]);
- }
-}
-
-
-struct pci_err {
- unsigned mask;
- const char *error_string;
-};
-
-static struct pci_err int_error[]={
- { INT_MNLTDIM,"MNLTDIM: Master non-lock transfer"},
- { INT_TTADI, "TTADI: Illegal byte enable in I/O transfer"},
- { INT_TMTO, "TMTO: Target memory read/write timeout"},
- { INT_MDEI, "MDEI: Master function disable error"},
- { INT_APEDI, "APEDI: Address parity error"},
- { INT_SDI, "SDI: SERR detected"},
- { INT_DPEITW, "DPEITW: Data parity error target write"},
- { INT_PEDITR, "PEDITR: PERR detected"},
- { INT_TADIM, "TADIM: Target abort detected"},
- { INT_MADIM, "MADIM: Master abort detected"},
- { INT_MWPDI, "MWPDI: PERR from target at data write"},
- { INT_MRDPEI, "MRDPEI: Master read data parity error"}
-};
-#define NUM_PCI_INT_ERRS (sizeof(int_error)/sizeof(struct pci_err))
-
-static struct pci_err aint_error[]={
- { AINT_MBI, "MBI: Master broken"},
- { AINT_TBTOI, "TBTOI: Target bus timeout"},
- { AINT_MBTOI, "MBTOI: Master bus timeout"},
- { AINT_TAI, "TAI: Target abort"},
- { AINT_MAI, "MAI: Master abort"},
- { AINT_RDPEI, "RDPEI: Read data parity"},
- { AINT_WDPE, "WDPE: Write data parity"}
-};
-
-#define NUM_PCI_AINT_ERRS (sizeof(aint_error)/sizeof(struct pci_err))
-
-static void print_pci_errors(unsigned reg,struct pci_err *error,int num_errors)
-{
- int i;
-
- for(i=0;i<num_errors;i++) {
- if(reg & error[i].mask) {
- printk("%s\n",error[i].error_string);
- }
- }
-
-}
-
-
-static char * pci_commands[16]={
- "Int Ack",
- "Special Cycle",
- "I/O Read",
- "I/O Write",
- "Reserved",
- "Reserved",
- "Memory Read",
- "Memory Write",
- "Reserved",
- "Reserved",
- "Configuration Read",
- "Configuration Write",
- "Memory Read Multiple",
- "Dual Address Cycle",
- "Memory Read Line",
- "Memory Write-and-Invalidate"
-};
-
-static irqreturn_t st40_pci_irq(int irq, void *dev_instance)
-{
- unsigned pci_int, pci_air, pci_cir, pci_aint;
- static int count=0;
-
-
- pci_int = ST40PCI_READ(INT);pci_aint = ST40PCI_READ(AINT);
- pci_cir = ST40PCI_READ(CIR);pci_air = ST40PCI_READ(AIR);
-
- /* Reset state to stop multiple interrupts */
- ST40PCI_WRITE(INT, ~0); ST40PCI_WRITE(AINT, ~0);
-
-
- if(++count>1) return IRQ_HANDLED;
-
- printk("** PCI ERROR **\n");
-
- if(pci_int) {
- printk("** INT register status\n");
- print_pci_errors(pci_int,int_error,NUM_PCI_INT_ERRS);
- }
-
- if(pci_aint) {
- printk("** AINT register status\n");
- print_pci_errors(pci_aint,aint_error,NUM_PCI_AINT_ERRS);
- }
-
- printk("** Address and command info\n");
-
- printk("** Command %s : Address 0x%x\n",
- pci_commands[pci_cir&0xf],pci_air);
-
- if(pci_cir&CIR_PIOTEM) {
- printk("CIR_PIOTEM:PIO transfer error for master\n");
- }
- if(pci_cir&CIR_RWTET) {
- printk("CIR_RWTET:Read/Write transfer error for target\n");
- }
-
- return IRQ_HANDLED;
-}
-
-
-/* Rounds a number UP to the nearest power of two. Used for
- * sizing the PCI window.
- */
-static u32 r2p2(u32 num)
-{
- int i = 31;
- u32 tmp = num;
-
- if (num == 0)
- return 0;
-
- do {
- if (tmp & (1 << 31))
- break;
- i--;
- tmp <<= 1;
- } while (i >= 0);
-
- tmp = 1 << i;
- /* If the original number isn't a power of 2, round it up */
- if (tmp != num)
- tmp <<= 1;
-
- return tmp;
-}
-
-static void __init pci_fixup_ide_bases(struct pci_dev *d)
-{
- int i;
-
- /*
- * PCI IDE controllers use non-standard I/O port decoding, respect it.
- */
- if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
- return;
- printk("PCI: IDE base address fixup for %s\n", pci_name(d));
- for(i=0; i<4; i++) {
- struct resource *r = &d->resource[i];
- if ((r->start & ~0x80) == 0x374) {
- r->start |= 2;
- r->end = r->start;
- }
- }
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
-
-int __init st40pci_init(unsigned memStart, unsigned memSize)
-{
- u32 lsr0;
-
- SetPCIPLL();
-
- /* Initialises the ST40 pci subsystem, performing a reset, then programming
- * up the address space decoders appropriately
- */
-
- /* Should reset core here as well methink */
-
- ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_SOFT_RESET);
-
- /* Loop while core resets */
- while (ST40PCI_READ(CR) & CR_SOFT_RESET);
-
- /* Switch off interrupts */
- ST40PCI_WRITE(INTM, 0);
- ST40PCI_WRITE(AINT, 0);
-
- /* Now, lets reset all the cards on the bus with extreme prejudice */
- ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_RSTCTL);
- udelay(250);
-
- /* Set bus active, take it out of reset */
- ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_BMAM | CR_CFINT | CR_PFCS | CR_PFE);
-
- /* The PCI spec says that no access must be made to the bus until 1 second
- * after reset. This seem ludicrously long, but some delay is needed here
- */
- mdelay(1000);
-
- /* Switch off interrupts */
- ST40PCI_WRITE(INTM, 0);
- ST40PCI_WRITE(AINT, 0);
-
- /* Allow it to be a master */
-
- ST40PCI_WRITE_SHORT(CSR_CMD,
- PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
- PCI_COMMAND_IO);
-
- /* Access to the 0xb0000000 -> 0xb6000000 area will go through to 0x10000000 -> 0x16000000
- * on the PCI bus. This allows a nice 1-1 bus to phys mapping.
- */
-
-
- ST40PCI_WRITE(MBR, 0x10000000);
- /* Always set the max size 128M (actually, it is only 96MB wide) */
- ST40PCI_WRITE(MBMR, 0x07ff0000);
-
- /* I/O addresses are mapped at 0xb6000000 -> 0xb7000000. These are changed to 0, to
- * allow cards that have legacy io such as vga to function correctly. This gives a
- * maximum of 64K of io/space as only the bottom 16 bits of the address are copied
- * over to the bus when the transaction is made. 64K of io space is more than enough
- */
- ST40PCI_WRITE(IOBR, 0x0);
- /* Set up the 64K window */
- ST40PCI_WRITE(IOBMR, 0x0);
-
- /* Now we set up the mbars so the PCI bus can see the local memory */
- /* Expose a 256M window starting at PCI address 0... */
- ST40PCI_WRITE(CSR_MBAR0, 0);
- ST40PCI_WRITE(LSR0, 0x0fff0001);
-
- /* ... and set up the initial incoming window to expose all of RAM */
- pci_set_rbar_region(7, memStart, memStart, memSize);
-
- /* Maximise timeout values */
- ST40PCI_WRITE_BYTE(CSR_TRDY, 0xff);
- ST40PCI_WRITE_BYTE(CSR_RETRY, 0xff);
- ST40PCI_WRITE_BYTE(CSR_MIT, 0xff);
-
- ST40PCI_WRITE_BYTE(PERF,PERF_MASTER_WRITE_POSTING);
-
- return 1;
-}
-
-char * __devinit pcibios_setup(char *str)
-{
- return str;
-}
-
-
-#define SET_CONFIG_BITS(bus,devfn,where)\
- (((bus) << 16) | ((devfn) << 8) | ((where) & ~3) | (bus!=0))
-
-#define CONFIG_CMD(bus, devfn, where) SET_CONFIG_BITS(bus->number,devfn,where)
-
-
-static int CheckForMasterAbort(void)
-{
- if (ST40PCI_READ(INT) & INT_MADIM) {
- /* Should we clear config space version as well ??? */
- ST40PCI_WRITE(INT, INT_MADIM);
- ST40PCI_WRITE_SHORT(CSR_STATUS, 0);
- return 1;
- }
-
- return 0;
-}
-
-/* Write to config register */
-static int st40pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * val)
-{
- ST40PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where));
- switch (size) {
- case 1:
- *val = (u8)ST40PCI_READ_BYTE(PDR + (where & 3));
- break;
- case 2:
- *val = (u16)ST40PCI_READ_SHORT(PDR + (where & 2));
- break;
- case 4:
- *val = ST40PCI_READ(PDR);
- break;
- }
-
- if (CheckForMasterAbort()){
- switch (size) {
- case 1:
- *val = (u8)0xff;
- break;
- case 2:
- *val = (u16)0xffff;
- break;
- case 4:
- *val = 0xffffffff;
- break;
- }
- }
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int st40pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val)
-{
- ST40PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where));
-
- switch (size) {
- case 1:
- ST40PCI_WRITE_BYTE(PDR + (where & 3), (u8)val);
- break;
- case 2:
- ST40PCI_WRITE_SHORT(PDR + (where & 2), (u16)val);
- break;
- case 4:
- ST40PCI_WRITE(PDR, val);
- break;
- }
-
- CheckForMasterAbort();
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-struct pci_ops st40pci_config_ops = {
- .read = st40pci_read,
- .write = st40pci_write,
-};
-
-
-/* Everything hangs off this */
-static struct pci_bus *pci_root_bus;
-
-static int __init pcibios_init(void)
-{
- extern unsigned long memory_start, memory_end;
-
- printk(KERN_ALERT "pci-st40.c: pcibios_init\n");
-
- if (sh_mv.mv_init_pci != NULL) {
- sh_mv.mv_init_pci();
- }
-
- /* The pci subsytem needs to know where memory is and how much
- * of it there is. I've simply made these globals. A better mechanism
- * is probably needed.
- */
- st40pci_init(PHYSADDR(memory_start),
- PHYSADDR(memory_end) - PHYSADDR(memory_start));
-
- if (request_irq(ST40PCI_ERR_IRQ, st40_pci_irq,
- IRQF_DISABLED, "st40pci", NULL)) {
- printk(KERN_ERR "st40pci: Cannot hook interrupt\n");
- return -EIO;
- }
-
- /* Enable the PCI interrupts on the device */
- ST40PCI_WRITE(INTM, ~0);
- ST40PCI_WRITE(AINT, ~0);
-
- /* Map the io address apprioately */
-#ifdef CONFIG_HD64465
- hd64465_port_map(PCIBIOS_MIN_IO, (64 * 1024) - PCIBIOS_MIN_IO + 1,
- ST40_IO_ADDR + PCIBIOS_MIN_IO, 0);
-#endif
-
- /* ok, do the scan man */
- pci_root_bus = pci_scan_bus(0, &st40pci_config_ops, NULL);
- pci_assign_unassigned_resources();
-
- return 0;
-}
-subsys_initcall(pcibios_init);
-
-/*
- * Publish a region of local address space over the PCI bus
- * to other devices.
- */
-static void pci_set_rbar_region(unsigned int region, unsigned long localAddr,
- unsigned long pciOffset, unsigned long regionSize)
-{
- unsigned long mask;
-
- if (region > 7)
- return;
-
- if (regionSize > (512 * 1024 * 1024))
- return;
-
- mask = r2p2(regionSize) - 0x10000;
-
- /* Disable the region (in case currently in use, should never happen) */
- ST40PCI_WRITE_INDEXED(RSR, region, 0);
-
- /* Start of local address space to publish */
- ST40PCI_WRITE_INDEXED(RLAR, region, PHYSADDR(localAddr) );
-
- /* Start of region in PCI address space as an offset from MBAR0 */
- ST40PCI_WRITE_INDEXED(RBAR, region, pciOffset);
-
- /* Size of region */
- ST40PCI_WRITE_INDEXED(RSR, region, mask | 1);
-}
-
diff --git a/arch/sh/drivers/pci/pci-st40.h b/arch/sh/drivers/pci/pci-st40.h
deleted file mode 100644
index cf0d35bd135c..000000000000
--- a/arch/sh/drivers/pci/pci-st40.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * Definitions for the ST40 PCI hardware.
- */
-
-#ifndef __PCI_ST40_H__
-#define __PCI_ST40_H__
-
-#define ST40PCI_VCR_STATUS 0x00
-
-#define ST40PCI_VCR_VERSION 0x08
-
-#define ST40PCI_CR 0x10
-
-#define CR_SOFT_RESET (1<<12)
-#define CR_PFCS (1<<11)
-#define CR_PFE (1<<9)
-#define CR_BMAM (1<<6)
-#define CR_HOST (1<<5)
-#define CR_CLKEN (1<<4)
-#define CR_SOCS (1<<3)
-#define CR_IOCS (1<<2)
-#define CR_RSTCTL (1<<1)
-#define CR_CFINT (1<<0)
-#define CR_LOCK_MASK 0x5a000000
-
-
-#define ST40PCI_LSR0 0X14
-#define ST40PCI_LAR0 0x1c
-
-#define ST40PCI_INT 0x24
-#define INT_MNLTDIM (1<<15)
-#define INT_TTADI (1<<14)
-#define INT_TMTO (1<<9)
-#define INT_MDEI (1<<8)
-#define INT_APEDI (1<<7)
-#define INT_SDI (1<<6)
-#define INT_DPEITW (1<<5)
-#define INT_PEDITR (1<<4)
-#define INT_TADIM (1<<3)
-#define INT_MADIM (1<<2)
-#define INT_MWPDI (1<<1)
-#define INT_MRDPEI (1<<0)
-
-
-#define ST40PCI_INTM 0x28
-#define ST40PCI_AIR 0x2c
-
-#define ST40PCI_CIR 0x30
-#define CIR_PIOTEM (1<<31)
-#define CIR_RWTET (1<<26)
-
-#define ST40PCI_AINT 0x40
-#define AINT_MBI (1<<13)
-#define AINT_TBTOI (1<<12)
-#define AINT_MBTOI (1<<11)
-#define AINT_TAI (1<<3)
-#define AINT_MAI (1<<2)
-#define AINT_RDPEI (1<<1)
-#define AINT_WDPE (1<<0)
-
-#define ST40PCI_AINTM 0x44
-#define ST40PCI_BMIR 0x48
-#define ST40PCI_PAR 0x4c
-#define ST40PCI_MBR 0x50
-#define ST40PCI_IOBR 0x54
-#define ST40PCI_PINT 0x58
-#define ST40PCI_PINTM 0x5c
-#define ST40PCI_MBMR 0x70
-#define ST40PCI_IOBMR 0x74
-#define ST40PCI_PDR 0x78
-
-/* H8 specific registers start here */
-#define ST40PCI_WCBAR 0x7c
-#define ST40PCI_LOCCFG_UNLOCK 0x34
-
-#define ST40PCI_RBAR0 0x100
-#define ST40PCI_RSR0 0x104
-#define ST40PCI_RLAR0 0x108
-
-#define ST40PCI_RBAR1 0x110
-#define ST40PCI_RSR1 0x114
-#define ST40PCI_RLAR1 0x118
-
-
-#define ST40PCI_RBAR2 0x120
-#define ST40PCI_RSR2 0x124
-#define ST40PCI_RLAR2 0x128
-
-#define ST40PCI_RBAR3 0x130
-#define ST40PCI_RSR3 0x134
-#define ST40PCI_RLAR3 0x138
-
-#define ST40PCI_RBAR4 0x140
-#define ST40PCI_RSR4 0x144
-#define ST40PCI_RLAR4 0x148
-
-#define ST40PCI_RBAR5 0x150
-#define ST40PCI_RSR5 0x154
-#define ST40PCI_RLAR5 0x158
-
-#define ST40PCI_RBAR6 0x160
-#define ST40PCI_RSR6 0x164
-#define ST40PCI_RLAR6 0x168
-
-#define ST40PCI_RBAR7 0x170
-#define ST40PCI_RSR7 0x174
-#define ST40PCI_RLAR7 0x178
-
-
-#define ST40PCI_RBAR(n) (0x100+(0x10*(n)))
-#define ST40PCI_RSR(n) (0x104+(0x10*(n)))
-#define ST40PCI_RLAR(n) (0x108+(0x10*(n)))
-
-#define ST40PCI_PERF 0x80
-#define PERF_MASTER_WRITE_POSTING (1<<4)
-/* H8 specific registers end here */
-
-
-/* These are configs space registers */
-#define ST40PCI_CSR_VID 0x10000
-#define ST40PCI_CSR_DID 0x10002
-#define ST40PCI_CSR_CMD 0x10004
-#define ST40PCI_CSR_STATUS 0x10006
-#define ST40PCI_CSR_MBAR0 0x10010
-#define ST40PCI_CSR_TRDY 0x10040
-#define ST40PCI_CSR_RETRY 0x10041
-#define ST40PCI_CSR_MIT 0x1000d
-
-#define ST40_IO_ADDR 0xb6000000
-
-#endif /* __PCI_ST40_H__ */
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile
index 1f141a8ba17c..4b81d9c47b00 100644
--- a/arch/sh/kernel/Makefile
+++ b/arch/sh/kernel/Makefile
@@ -10,7 +10,6 @@ obj-y := debugtraps.o io.o io_generic.o irq.o machvec.o process.o ptrace.o \
obj-y += cpu/ timers/
obj-$(CONFIG_VSYSCALL) += vsyscall/
-
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_CF_ENABLER) += cf-enabler.o
obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o
@@ -22,3 +21,5 @@ obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
obj-$(CONFIG_PM) += pm.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
+
+EXTRA_CFLAGS += -Werror
diff --git a/arch/sh/kernel/cpu/irq/ipr.c b/arch/sh/kernel/cpu/irq/ipr.c
index 5da325414880..56ea7b269b59 100644
--- a/arch/sh/kernel/cpu/irq/ipr.c
+++ b/arch/sh/kernel/cpu/irq/ipr.c
@@ -49,7 +49,6 @@ static void enable_ipr_irq(unsigned int irq)
* bits/4. This is to make it easier to read the value directly from the
* datasheets. The IPR address is calculated using the ipr_offset table.
*/
-
void register_ipr_controller(struct ipr_desc *desc)
{
int i;
@@ -71,12 +70,4 @@ void register_ipr_controller(struct ipr_desc *desc)
disable_ipr_irq(p->irq);
}
}
-
EXPORT_SYMBOL(register_ipr_controller);
-
-#if !defined(CONFIG_CPU_HAS_PINT_IRQ)
-int ipr_irq_demux(int irq)
-{
- return irq;
-}
-#endif
diff --git a/arch/sh/kernel/cpu/sh3/ex.S b/arch/sh/kernel/cpu/sh3/ex.S
index 2b2a9e02fb75..b6abf38d3a8d 100644
--- a/arch/sh/kernel/cpu/sh3/ex.S
+++ b/arch/sh/kernel/cpu/sh3/ex.S
@@ -46,7 +46,7 @@ ENTRY(exception_handling_table)
.long exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/
ENTRY(nmi_slot)
#if defined (CONFIG_KGDB_NMI)
- .long debug_enter /* 1C0 */ ! Allow trap to debugger
+ .long kgdb_handle_exception /* 1C0 */ ! Allow trap to debugger
#else
.long exception_none /* 1C0 */ ! Not implemented yet
#endif
diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c
index 21375d777e99..bc9c28a69bf1 100644
--- a/arch/sh/kernel/cpu/sh4/probe.c
+++ b/arch/sh/kernel/cpu/sh4/probe.c
@@ -139,14 +139,6 @@ int __init detect_cpu_and_cache_system(void)
boot_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER |
CPU_HAS_LLSC;
break;
- case 0x8000:
- boot_cpu_data.type = CPU_ST40RA;
- boot_cpu_data.flags |= CPU_HAS_FPU;
- break;
- case 0x8100:
- boot_cpu_data.type = CPU_ST40GX1;
- boot_cpu_data.flags |= CPU_HAS_FPU;
- break;
case 0x700:
boot_cpu_data.type = CPU_SH4_501;
boot_cpu_data.icache.ways = 2;
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
index 55f66104431d..b9c6547c4a90 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
@@ -14,6 +14,32 @@
#include <asm/mmzone.h>
#include <asm/sci.h>
+static struct resource usbf_resources[] = {
+ [0] = {
+ .name = "m66592_udc",
+ .start = 0xA4480000,
+ .end = 0xA44800FF,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = "m66592_udc",
+ .start = 65,
+ .end = 65,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device usbf_device = {
+ .name = "m66592_udc",
+ .id = -1,
+ .dev = {
+ .dma_mask = NULL,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .num_resources = ARRAY_SIZE(usbf_resources),
+ .resource = usbf_resources,
+};
+
static struct plat_sci_port sci_platform_data[] = {
{
.mapbase = 0xffe00000,
@@ -47,6 +73,7 @@ static struct platform_device sci_device = {
};
static struct platform_device *sh7722_devices[] __initdata = {
+ &usbf_device,
&sci_device,
};
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index 4b49d03ffbd2..0586bc62ad96 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -11,7 +11,6 @@
#include <linux/module.h>
#include <linux/kernel_stat.h>
#include <linux/seq_file.h>
-#include <linux/irq.h>
#include <asm/processor.h>
#include <asm/machvec.h>
#include <asm/uaccess.h>
@@ -69,7 +68,7 @@ unlock:
}
#endif
-#ifdef CONFIG_4KSTACKS
+#ifdef CONFIG_IRQSTACKS
/*
* per-CPU IRQ handling contexts (thread information and stack)
*/
@@ -85,7 +84,7 @@ static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly;
asmlinkage int do_IRQ(unsigned int irq, struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);
-#ifdef CONFIG_4KSTACKS
+#ifdef CONFIG_IRQSTACKS
union irq_ctx *curctx, *irqctx;
#endif
@@ -109,7 +108,7 @@ asmlinkage int do_IRQ(unsigned int irq, struct pt_regs *regs)
irq = irq_demux(evt2irq(irq));
-#ifdef CONFIG_4KSTACKS
+#ifdef CONFIG_IRQSTACKS
curctx = (union irq_ctx *)current_thread_info();
irqctx = hardirq_ctx[smp_processor_id()];
@@ -157,7 +156,7 @@ asmlinkage int do_IRQ(unsigned int irq, struct pt_regs *regs)
return 1;
}
-#ifdef CONFIG_4KSTACKS
+#ifdef CONFIG_IRQSTACKS
static char softirq_stack[NR_CPUS * THREAD_SIZE]
__attribute__((__section__(".bss.page_aligned")));
diff --git a/arch/sh/kernel/kgdb_stub.c b/arch/sh/kernel/kgdb_stub.c
index 2fdc700dfd6e..d453c3a1c79f 100644
--- a/arch/sh/kernel/kgdb_stub.c
+++ b/arch/sh/kernel/kgdb_stub.c
@@ -102,6 +102,7 @@
#include <linux/init.h>
#include <linux/console.h>
#include <linux/sysrq.h>
+#include <linux/module.h>
#include <asm/system.h>
#include <asm/cacheflush.h>
#include <asm/current.h>
@@ -116,7 +117,9 @@ kgdb_debug_hook_t *kgdb_debug_hook;
kgdb_bus_error_hook_t *kgdb_bus_err_hook;
int (*kgdb_getchar)(void);
+EXPORT_SYMBOL_GPL(kgdb_getchar);
void (*kgdb_putchar)(int);
+EXPORT_SYMBOL_GPL(kgdb_putchar);
static void put_debug_char(int c)
{
@@ -136,7 +139,7 @@ static int get_debug_char(void)
#define NUMREGBYTES (MAXREG*4)
#define OUTBUFMAX (NUMREGBYTES*2+512)
-enum regs {
+enum {
R0 = 0, R1, R2, R3, R4, R5, R6, R7,
R8, R9, R10, R11, R12, R13, R14, R15,
PC, PR, GBR, VBR, MACH, MACL, SR,
@@ -176,9 +179,13 @@ int kgdb_nofault; /* Boolean to ignore bus errs (i.e. in GDB) */
/* SCI/UART settings, used in kgdb_console_setup() */
int kgdb_portnum = CONFIG_KGDB_DEFPORT;
+EXPORT_SYMBOL_GPL(kgdb_portnum);
int kgdb_baud = CONFIG_KGDB_DEFBAUD;
+EXPORT_SYMBOL_GPL(kgdb_baud);
char kgdb_parity = CONFIG_KGDB_DEFPARITY;
+EXPORT_SYMBOL_GPL(kgdb_parity);
char kgdb_bits = CONFIG_KGDB_DEFBITS;
+EXPORT_SYMBOL_GPL(kgdb_bits);
/* Jump buffer for setjmp/longjmp */
static jmp_buf rem_com_env;
diff --git a/arch/sh/kernel/machine_kexec.c b/arch/sh/kernel/machine_kexec.c
index 790ed69b8666..5c17de51987e 100644
--- a/arch/sh/kernel/machine_kexec.c
+++ b/arch/sh/kernel/machine_kexec.c
@@ -104,24 +104,3 @@ NORET_TYPE void machine_kexec(struct kimage *image)
(*rnk)(page_list, reboot_code_buffer, image->start, vbr_reg);
}
-/* crashkernel=size@addr specifies the location to reserve for
- * a crash kernel. By reserving this memory we guarantee
- * that linux never sets it up as a DMA target.
- * Useful for holding code to do something appropriate
- * after a kernel panic.
- */
-static int __init parse_crashkernel(char *arg)
-{
- unsigned long size, base;
- size = memparse(arg, &arg);
- if (*arg == '@') {
- base = memparse(arg+1, &arg);
- /* FIXME: Do I want a sanity check
- * to validate the memory range?
- */
- crashk_res.start = base;
- crashk_res.end = base + size - 1;
- }
- return 0;
-}
-early_param("crashkernel", parse_crashkernel);
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
index b4469992d6b2..6d7f2b07e491 100644
--- a/arch/sh/kernel/process.c
+++ b/arch/sh/kernel/process.c
@@ -121,7 +121,7 @@ void machine_power_off(void)
void show_regs(struct pt_regs * regs)
{
printk("\n");
- printk("Pid : %d, Comm: %20s\n", current->pid, current->comm);
+ printk("Pid : %d, Comm: %20s\n", task_pid_nr(current), current->comm);
print_symbol("PC is at %s\n", instruction_pointer(regs));
printk("PC : %08lx SP : %08lx SR : %08lx ",
regs->pc, regs->regs[15], regs->sr);
diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c
index f64a2d2416d4..ac725f0aeb72 100644
--- a/arch/sh/kernel/ptrace.c
+++ b/arch/sh/kernel/ptrace.c
@@ -211,10 +211,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
}
- case PTRACE_DETACH: /* detach a process that was attached. */
- ret = ptrace_detach(child, data);
- break;
-
#ifdef CONFIG_SH_DSP
case PTRACE_GETDSPREGS: {
unsigned long dp;
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index b3027a6775b9..4156aac8c27d 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -32,12 +32,6 @@
#include <asm/clock.h>
#include <asm/mmu_context.h>
-extern void * __rd_start, * __rd_end;
-
-/*
- * Machine setup..
- */
-
/*
* Initialize loops_per_jiffy as 10000000 (1000MIPS).
* This value will be used at the very early stage of serial setup.
@@ -63,33 +57,25 @@ struct screen_info screen_info;
extern int root_mountflags;
-/*
- * This is set up by the setup-routine at boot-time
- */
-#define PARAM ((unsigned char *)empty_zero_page)
-
-#define MOUNT_ROOT_RDONLY (*(unsigned long *) (PARAM+0x000))
-#define RAMDISK_FLAGS (*(unsigned long *) (PARAM+0x004))
-#define ORIG_ROOT_DEV (*(unsigned long *) (PARAM+0x008))
-#define LOADER_TYPE (*(unsigned long *) (PARAM+0x00c))
-#define INITRD_START (*(unsigned long *) (PARAM+0x010))
-#define INITRD_SIZE (*(unsigned long *) (PARAM+0x014))
-/* ... */
-#define COMMAND_LINE ((char *) (PARAM+0x100))
-
#define RAMDISK_IMAGE_START_MASK 0x07FF
#define RAMDISK_PROMPT_FLAG 0x8000
#define RAMDISK_LOAD_FLAG 0x4000
static char __initdata command_line[COMMAND_LINE_SIZE] = { 0, };
-static struct resource code_resource = { .name = "Kernel code", };
-static struct resource data_resource = { .name = "Kernel data", };
+static struct resource code_resource = {
+ .name = "Kernel code",
+ .flags = IORESOURCE_BUSY | IORESOURCE_MEM,
+};
+
+static struct resource data_resource = {
+ .name = "Kernel data",
+ .flags = IORESOURCE_BUSY | IORESOURCE_MEM,
+};
unsigned long memory_start;
EXPORT_SYMBOL(memory_start);
-
-unsigned long memory_end;
+unsigned long memory_end = 0;
EXPORT_SYMBOL(memory_end);
static int __init early_parse_mem(char *p)
@@ -128,6 +114,37 @@ static void __init register_bootmem_low_pages(void)
free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(pages));
}
+#ifdef CONFIG_KEXEC
+static void __init reserve_crashkernel(void)
+{
+ unsigned long long free_mem;
+ unsigned long long crash_size, crash_base;
+ int ret;
+
+ free_mem = ((unsigned long long)max_low_pfn - min_low_pfn) << PAGE_SHIFT;
+
+ ret = parse_crashkernel(boot_command_line, free_mem,
+ &crash_size, &crash_base);
+ if (ret == 0 && crash_size) {
+ if (crash_base > 0) {
+ printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
+ "for crashkernel (System RAM: %ldMB)\n",
+ (unsigned long)(crash_size >> 20),
+ (unsigned long)(crash_base >> 20),
+ (unsigned long)(free_mem >> 20));
+ crashk_res.start = crash_base;
+ crashk_res.end = crash_base + crash_size - 1;
+ reserve_bootmem(crash_base, crash_size);
+ } else
+ printk(KERN_INFO "crashkernel reservation failed - "
+ "you have to specify a base address\n");
+ }
+}
+#else
+static inline void __init reserve_crashkernel(void)
+{}
+#endif
+
void __init setup_bootmem_allocator(unsigned long free_pfn)
{
unsigned long bootmap_size;
@@ -164,14 +181,7 @@ void __init setup_bootmem_allocator(unsigned long free_pfn)
sparse_memory_present_with_active_regions(0);
#ifdef CONFIG_BLK_DEV_INITRD
- ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
- if (&__rd_start != &__rd_end) {
- LOADER_TYPE = 1;
- INITRD_START = PHYSADDR((unsigned long)&__rd_start) -
- __MEMORY_START;
- INITRD_SIZE = (unsigned long)&__rd_end -
- (unsigned long)&__rd_start;
- }
+ ROOT_DEV = Root_RAM0;
if (LOADER_TYPE && INITRD_START) {
if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
@@ -189,11 +199,8 @@ void __init setup_bootmem_allocator(unsigned long free_pfn)
}
}
#endif
-#ifdef CONFIG_KEXEC
- if (crashk_res.start != crashk_res.end)
- reserve_bootmem(crashk_res.start,
- crashk_res.end - crashk_res.start + 1);
-#endif
+
+ reserve_crashkernel();
}
#ifndef CONFIG_NEED_MULTIPLE_NODES
@@ -237,7 +244,8 @@ void __init setup_arch(char **cmdline_p)
data_resource.end = virt_to_phys(_edata)-1;
memory_start = (unsigned long)PAGE_OFFSET+__MEMORY_START;
- memory_end = memory_start + __MEMORY_SIZE;
+ if (!memory_end)
+ memory_end = memory_start + __MEMORY_SIZE;
#ifdef CONFIG_CMDLINE_BOOL
strlcpy(command_line, CONFIG_CMDLINE, sizeof(command_line));
@@ -295,7 +303,6 @@ static const char *cpu_name[] = {
[CPU_SH7750S] = "SH7750S", [CPU_SH7750R] = "SH7750R",
[CPU_SH7751] = "SH7751", [CPU_SH7751R] = "SH7751R",
[CPU_SH7760] = "SH7760",
- [CPU_ST40RA] = "ST40RA", [CPU_ST40GX1] = "ST40GX1",
[CPU_SH4_202] = "SH4-202", [CPU_SH4_501] = "SH4-501",
[CPU_SH7770] = "SH7770", [CPU_SH7780] = "SH7780",
[CPU_SH7781] = "SH7781", [CPU_SH7343] = "SH7343",
diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c
index 548e4285b375..e1a6de9088b5 100644
--- a/arch/sh/kernel/sh_ksyms.c
+++ b/arch/sh/kernel/sh_ksyms.c
@@ -106,7 +106,6 @@ DECLARE_EXPORT(__movmem);
DECLARE_EXPORT(__movstr);
#endif
-#ifdef CONFIG_CPU_SH4
#if __GNUC__ == 4
DECLARE_EXPORT(__movmem_i4_even);
DECLARE_EXPORT(__movmem_i4_odd);
@@ -126,7 +125,6 @@ DECLARE_EXPORT(__movstr_i4_even);
DECLARE_EXPORT(__movstr_i4_odd);
DECLARE_EXPORT(__movstrSI12_i4);
#endif /* __GNUC__ == 4 */
-#endif
#if !defined(CONFIG_CACHE_OFF) && (defined(CONFIG_CPU_SH4) || \
defined(CONFIG_SH7705_CACHE_32KB))
diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c
index 2f42442cf164..ca754fd42437 100644
--- a/arch/sh/kernel/signal.c
+++ b/arch/sh/kernel/signal.c
@@ -382,7 +382,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
set_fs(USER_DS);
pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
- current->comm, current->pid, frame, regs->pc, regs->pr);
+ current->comm, task_pid_nr(current), frame, regs->pc, regs->pr);
flush_cache_sigtramp(regs->pr);
@@ -462,7 +462,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
set_fs(USER_DS);
pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
- current->comm, current->pid, frame, regs->pc, regs->pr);
+ current->comm, task_pid_nr(current), frame, regs->pc, regs->pr);
flush_cache_sigtramp(regs->pr);
diff --git a/arch/sh/kernel/sys_sh.c b/arch/sh/kernel/sys_sh.c
index 024ce5dedd8c..d545a686a201 100644
--- a/arch/sh/kernel/sys_sh.c
+++ b/arch/sh/kernel/sys_sh.c
@@ -22,9 +22,9 @@
#include <linux/utsname.h>
#include <linux/module.h>
#include <linux/fs.h>
+#include <linux/ipc.h>
#include <asm/cacheflush.h>
#include <asm/uaccess.h>
-#include <asm/ipc.h>
#include <asm/unistd.h>
/*
diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c
index dcb46e71da1c..cf99111cb33f 100644
--- a/arch/sh/kernel/traps.c
+++ b/arch/sh/kernel/traps.c
@@ -95,8 +95,8 @@ void die(const char * str, struct pt_regs * regs, long err)
print_modules();
show_regs(regs);
- printk("Process: %s (pid: %d, stack limit = %p)\n",
- current->comm, current->pid, task_stack_page(current) + 1);
+ printk("Process: %s (pid: %d, stack limit = %p)\n", current->comm,
+ task_pid_nr(current), task_stack_page(current) + 1);
if (!user_mode(regs) || in_interrupt())
dump_mem("Stack: ", regs->regs[15], THREAD_SIZE +
@@ -386,7 +386,8 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
printk(KERN_NOTICE "Fixing up unaligned userspace access "
"in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
- current->comm,current->pid,(u16*)regs->pc,instruction);
+ current->comm, task_pid_nr(current),
+ (u16 *)regs->pc, instruction);
}
ret = -EFAULT;
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
index 6d5abba2ee27..0956fb3681a3 100644
--- a/arch/sh/kernel/vmlinux.lds.S
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -1,4 +1,4 @@
-/* $Id: vmlinux.lds.S,v 1.8 2003/05/16 17:18:14 lethal Exp $
+/*
* ld script to make SuperH Linux kernel
* Written by Niibe Yutaka
*/
@@ -15,121 +15,124 @@ OUTPUT_ARCH(sh)
ENTRY(_start)
SECTIONS
{
- . = CONFIG_PAGE_OFFSET + CONFIG_MEMORY_START + CONFIG_ZERO_PAGE_OFFSET;
- _text = .; /* Text and read-only data */
- text = .; /* Text and read-only data */
- .empty_zero_page : {
- *(.empty_zero_page)
+ . = CONFIG_PAGE_OFFSET + CONFIG_MEMORY_START + CONFIG_ZERO_PAGE_OFFSET;
+ _text = .; /* Text and read-only data */
+
+ .empty_zero_page : {
+ *(.empty_zero_page)
} = 0
- .text : {
- *(.text.head)
- TEXT_TEXT
- SCHED_TEXT
- LOCK_TEXT
- *(.fixup)
- *(.gnu.warning)
+
+ .text : {
+ *(.text.head)
+ TEXT_TEXT
+ SCHED_TEXT
+ LOCK_TEXT
+ KPROBES_TEXT
+ *(.fixup)
+ *(.gnu.warning)
} = 0x0009
- . = ALIGN(16); /* Exception table */
- __start___ex_table = .;
- __ex_table : { *(__ex_table) }
- __stop___ex_table = .;
+ . = ALIGN(16); /* Exception table */
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ _etext = .; /* End of text section */
- _etext = .; /* End of text section */
+ BUG_TABLE
+ NOTES
+ RO_DATA(PAGE_SIZE)
- RODATA
+ . = ALIGN(THREAD_SIZE);
+ .data : { /* Data */
+ *(.data.init_task)
- BUG_TABLE
+ . = ALIGN(L1_CACHE_BYTES);
+ *(.data.cacheline_aligned)
- .data : { /* Data */
- DATA_DATA
+ . = ALIGN(L1_CACHE_BYTES);
+ *(.data.read_mostly)
- /* Align the initial ramdisk image (INITRD) on page boundaries. */
- . = ALIGN(PAGE_SIZE);
- __rd_start = .;
- *(.initrd)
- . = ALIGN(PAGE_SIZE);
- __rd_end = .;
+ . = ALIGN(PAGE_SIZE);
+ *(.data.page_aligned)
- CONSTRUCTORS
+ __nosave_begin = .;
+ *(.data.nosave)
+ . = ALIGN(PAGE_SIZE);
+ __nosave_end = .;
+
+ DATA_DATA
+ CONSTRUCTORS
}
- . = ALIGN(PAGE_SIZE);
- .data.page_aligned : { *(.data.page_aligned) }
- __nosave_begin = .;
- .data_nosave : { *(.data.nosave) }
- . = ALIGN(PAGE_SIZE);
- __nosave_end = .;
-
- PERCPU(PAGE_SIZE)
-
- . = ALIGN(L1_CACHE_BYTES);
- .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-
- _edata = .; /* End of data section */
-
- . = ALIGN(THREAD_SIZE); /* init_task */
- .data.init_task : { *(.data.init_task) }
-
- . = ALIGN(PAGE_SIZE); /* Init code and data */
- __init_begin = .;
- _sinittext = .;
- .init.text : { *(.init.text) }
- _einittext = .;
- .init.data : { *(.init.data) }
- . = ALIGN(16);
- __setup_start = .;
- .init.setup : { *(.init.setup) }
- __setup_end = .;
- __initcall_start = .;
- .initcall.init : {
- INITCALLS
- }
- __initcall_end = .;
- __con_initcall_start = .;
- .con_initcall.init : { *(.con_initcall.init) }
- __con_initcall_end = .;
- SECURITY_INIT
-
- /* .exit.text is discarded at runtime, not link time, to deal with
- references from .rodata */
- .exit.text : { *(.exit.text) }
- .exit.data : { *(.exit.data) }
+ _edata = .; /* End of data section */
-#ifdef CONFIG_BLK_DEV_INITRD
- . = ALIGN(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE); /* Init code and data */
+ __init_begin = .;
+ _sinittext = .;
+ .init.text : { *(.init.text) }
+ _einittext = .;
+ .init.data : { *(.init.data) }
+
+ . = ALIGN(16);
+ __setup_start = .;
+ .init.setup : { *(.init.setup) }
+ __setup_end = .;
- __initramfs_start = .;
- .init.ramfs : { *(.init.ramfs) }
- __initramfs_end = .;
+ __initcall_start = .;
+ .initcall.init : {
+ INITCALLS
+ }
+ __initcall_end = .;
+ __con_initcall_start = .;
+ .con_initcall.init : { *(.con_initcall.init) }
+ __con_initcall_end = .;
+
+ SECURITY_INIT
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ . = ALIGN(PAGE_SIZE);
+ __initramfs_start = .;
+ .init.ramfs : { *(.init.ramfs) }
+ __initramfs_end = .;
#endif
- . = ALIGN(4);
- __machvec_start = .;
- .machvec.init : { *(.machvec.init) }
- __machvec_end = .;
-
- . = ALIGN(PAGE_SIZE);
- .bss : {
- __init_end = .;
- __bss_start = .; /* BSS */
- *(.bss.page_aligned)
- *(.bss)
. = ALIGN(4);
- _ebss = .; /* uClinux MTD sucks */
- _end = . ;
- }
-
- /* When something in the kernel is NOT compiled as a module, the
- * module cleanup code and data are put into these segments. Both
- * can then be thrown away, as cleanup code is never called unless
- * it's a module.
- */
- /DISCARD/ : {
- *(.exitcall.exit)
+ __machvec_start = .;
+ .machvec.init : { *(.machvec.init) }
+ __machvec_end = .;
+
+ PERCPU(PAGE_SIZE)
+
+ /*
+ * .exit.text is discarded at runtime, not link time, to deal with
+ * references from __bug_table
+ */
+ .exit.text : { *(.exit.text) }
+ .exit.data : { *(.exit.data) }
+
+ . = ALIGN(PAGE_SIZE);
+ .bss : {
+ __init_end = .;
+ __bss_start = .; /* BSS */
+ *(.bss.page_aligned)
+ *(.bss)
+ *(COMMON)
+ . = ALIGN(4);
+ _ebss = .; /* uClinux MTD sucks */
+ _end = . ;
}
- STABS_DEBUG
+ /*
+ * When something in the kernel is NOT compiled as a module, the
+ * module cleanup code and data are put into these segments. Both
+ * can then be thrown away, as cleanup code is never called unless
+ * it's a module.
+ */
+ /DISCARD/ : {
+ *(.exitcall.exit)
+ }
- DWARF_DEBUG
+ STABS_DEBUG
+ DWARF_DEBUG
}
diff --git a/arch/sh/kernel/vsyscall/vsyscall.lds.S b/arch/sh/kernel/vsyscall/vsyscall.lds.S
index b13c3d439fee..6d59ee7c23dd 100644
--- a/arch/sh/kernel/vsyscall/vsyscall.lds.S
+++ b/arch/sh/kernel/vsyscall/vsyscall.lds.S
@@ -17,45 +17,55 @@ ENTRY(__kernel_vsyscall);
SECTIONS
{
- . = SIZEOF_HEADERS;
+ . = SIZEOF_HEADERS;
- .hash : { *(.hash) } :text
- .gnu.hash : { *(.gnu.hash) }
- .dynsym : { *(.dynsym) }
- .dynstr : { *(.dynstr) }
- .gnu.version : { *(.gnu.version) }
- .gnu.version_d : { *(.gnu.version_d) }
- .gnu.version_r : { *(.gnu.version_r) }
+ .hash : { *(.hash) } :text
+ .gnu.hash : { *(.gnu.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
- /* This linker script is used both with -r and with -shared.
- For the layouts to match, we need to skip more than enough
- space for the dynamic symbol table et al. If this amount
- is insufficient, ld -shared will barf. Just increase it here. */
- . = 0x400;
+ /*
+ * This linker script is used both with -r and with -shared.
+ * For the layouts to match, we need to skip more than enough
+ * space for the dynamic symbol table et al. If this amount
+ * is insufficient, ld -shared will barf. Just increase it here.
+ */
+ . = 0x400;
- .text : { *(.text) } :text =0x90909090
- .note : { *(.note.*) } :text :note
- .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr
- .eh_frame : { KEEP (*(.eh_frame)) } :text
- .dynamic : { *(.dynamic) } :text :dynamic
- .useless : {
- *(.got.plt) *(.got)
- *(.data .data.* .gnu.linkonce.d.*)
- *(.dynbss)
- *(.bss .bss.* .gnu.linkonce.b.*)
- } :text
+ .text : { *(.text) } :text =0x90909090
+ .note : { *(.note.*) } :text :note
+ .eh_frame_hdr : { *(.eh_frame_hdr ) } :text :eh_frame_hdr
+ .eh_frame : {
+ KEEP (*(.eh_frame))
+ LONG (0)
+ } :text
+ .dynamic : { *(.dynamic) } :text :dynamic
+ .useless : {
+ *(.got.plt) *(.got)
+ *(.data .data.* .gnu.linkonce.d.*)
+ *(.dynbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ } :text
}
/*
+ * Very old versions of ld do not recognize this name token; use the constant.
+ */
+#define PT_GNU_EH_FRAME 0x6474e550
+
+/*
* We must supply the ELF program headers explicitly to get just one
* PT_LOAD segment, and set the flags explicitly to make segments read-only.
*/
PHDRS
{
- text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */
- dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
- note PT_NOTE FLAGS(4); /* PF_R */
- eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */
+ text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */
+ dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
+ note PT_NOTE FLAGS(4); /* PF_R */
+ eh_frame_hdr PT_GNU_EH_FRAME;
}
/*
@@ -63,12 +73,12 @@ PHDRS
*/
VERSION
{
- LINUX_2.6 {
- global:
- __kernel_vsyscall;
- __kernel_sigreturn;
- __kernel_rt_sigreturn;
+ LINUX_2.6 {
+ global:
+ __kernel_vsyscall;
+ __kernel_sigreturn;
+ __kernel_rt_sigreturn;
- local: *;
- };
+ local: *;
+ };
}
diff --git a/arch/sh/lib/Makefile b/arch/sh/lib/Makefile
index e23dd1a3fccd..9dc7b6985052 100644
--- a/arch/sh/lib/Makefile
+++ b/arch/sh/lib/Makefile
@@ -9,3 +9,5 @@ memcpy-y := memcpy.o
memcpy-$(CONFIG_CPU_SH4) := memcpy-sh4.o
lib-y += $(memcpy-y)
+
+EXTRA_CFLAGS += -Werror
diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig
index cf446bbab5b0..1265f204f7d1 100644
--- a/arch/sh/mm/Kconfig
+++ b/arch/sh/mm/Kconfig
@@ -17,7 +17,7 @@ config CPU_SH4
bool
select CPU_HAS_INTEVT
select CPU_HAS_SR_RB
- select CPU_HAS_PTEA if (!CPU_SUBTYPE_ST40 && !CPU_SH4A) || CPU_SHX2
+ select CPU_HAS_PTEA if !CPU_SH4A || CPU_SHX2
select CPU_HAS_FPU if !CPU_SH4AL_DSP
config CPU_SH4A
@@ -29,10 +29,6 @@ config CPU_SH4AL_DSP
select CPU_SH4A
select CPU_HAS_DSP
-config CPU_SUBTYPE_ST40
- bool
- select CPU_SH4
-
config CPU_SHX2
bool
@@ -152,21 +148,6 @@ config CPU_SUBTYPE_SH4_202
bool "Support SH4-202 processor"
select CPU_SH4
-# ST40 Processor Support
-
-config CPU_SUBTYPE_ST40STB1
- bool "Support ST40STB1/ST40RA processors"
- select CPU_SUBTYPE_ST40
- help
- Select ST40STB1 if you have a ST40RA CPU.
- This was previously called the ST40STB1, hence the option name.
-
-config CPU_SUBTYPE_ST40GX1
- bool "Support ST40GX1 processor"
- select CPU_SUBTYPE_ST40
- help
- Select ST40GX1 if you have a ST40GX1 CPU.
-
# SH-4A Processor Support
config CPU_SUBTYPE_SH7770
diff --git a/arch/sh/mm/Makefile b/arch/sh/mm/Makefile
index ee30fb44dfe1..aa44607f072d 100644
--- a/arch/sh/mm/Makefile
+++ b/arch/sh/mm/Makefile
@@ -33,3 +33,5 @@ endif
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
obj-$(CONFIG_32BIT) += pmb.o
obj-$(CONFIG_NUMA) += numa.o
+
+EXTRA_CFLAGS += -Werror
diff --git a/arch/sh/mm/clear_page.S b/arch/sh/mm/clear_page.S
index 8a706131e521..7a7c81ee3f01 100644
--- a/arch/sh/mm/clear_page.S
+++ b/arch/sh/mm/clear_page.S
@@ -150,48 +150,3 @@ ENTRY(__clear_user)
.long 8b, .Lbad_clear_user
.long 9b, .Lbad_clear_user
.previous
-
-#if defined(CONFIG_CPU_SH4)
-/*
- * __clear_user_page
- * @to: P3 address (with same color)
- * @orig_to: P1 address
- *
- * void __clear_user_page(void *to, void *orig_to)
- */
-
-/*
- * r0 --- scratch
- * r4 --- to
- * r5 --- orig_to
- * r6 --- to + PAGE_SIZE
- */
-ENTRY(__clear_user_page)
- mov.l .Lpsz,r0
- mov r4,r6
- add r0,r6
- mov #0,r0
- !
-1: ocbi @r5
- add #32,r5
- movca.l r0,@r4
- mov r4,r1
- add #32,r4
- mov.l r0,@-r4
- mov.l r0,@-r4
- mov.l r0,@-r4
- mov.l r0,@-r4
- mov.l r0,@-r4
- mov.l r0,@-r4
- mov.l r0,@-r4
- add #28,r4
- cmp/eq r6,r4
- bf/s 1b
- ocbwb @r1
- !
- rts
- nop
-.Lpsz: .long PAGE_SIZE
-
-#endif
-
diff --git a/arch/sh/mm/consistent.c b/arch/sh/mm/consistent.c
index 38c82d890ffd..e220c29a3c00 100644
--- a/arch/sh/mm/consistent.c
+++ b/arch/sh/mm/consistent.c
@@ -34,7 +34,7 @@ void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *handle)
/*
* We must flush the cache before we pass it on to the device
*/
- dma_cache_wback_inv(ret, size);
+ __flush_purge_region(ret, size);
page = virt_to_page(ret);
free = page + (size >> PAGE_SHIFT);
@@ -68,13 +68,13 @@ void consistent_sync(void *vaddr, size_t size, int direction)
switch (direction) {
case DMA_FROM_DEVICE: /* invalidate only */
- dma_cache_inv(p1addr, size);
+ __flush_invalidate_region(p1addr, size);
break;
case DMA_TO_DEVICE: /* writeback only */
- dma_cache_wback(p1addr, size);
+ __flush_wback_region(p1addr, size);
break;
case DMA_BIDIRECTIONAL: /* writeback and invalidate */
- dma_cache_wback_inv(p1addr, size);
+ __flush_purge_region(p1addr, size);
break;
default:
BUG();
diff --git a/arch/sh/mm/copy_page.S b/arch/sh/mm/copy_page.S
index a81dbdb05596..40685018b952 100644
--- a/arch/sh/mm/copy_page.S
+++ b/arch/sh/mm/copy_page.S
@@ -68,67 +68,6 @@ ENTRY(copy_page_slow)
rts
nop
-#if defined(CONFIG_CPU_SH4)
-/*
- * __copy_user_page
- * @to: P1 address (with same color)
- * @from: P1 address
- * @orig_to: P1 address
- *
- * void __copy_user_page(void *to, void *from, void *orig_to)
- */
-
-/*
- * r0, r1, r2, r3, r4, r5, r6, r7 --- scratch
- * r8 --- from + PAGE_SIZE
- * r9 --- orig_to
- * r10 --- to
- * r11 --- from
- */
-ENTRY(__copy_user_page)
- mov.l r8,@-r15
- mov.l r9,@-r15
- mov.l r10,@-r15
- mov.l r11,@-r15
- mov r4,r10
- mov r5,r11
- mov r6,r9
- mov r5,r8
- mov.l .Lpsz,r0
- add r0,r8
- !
-1: ocbi @r9
- add #32,r9
- mov.l @r11+,r0
- mov.l @r11+,r1
- mov.l @r11+,r2
- mov.l @r11+,r3
- mov.l @r11+,r4
- mov.l @r11+,r5
- mov.l @r11+,r6
- mov.l @r11+,r7
- movca.l r0,@r10
- mov r10,r0
- add #32,r10
- mov.l r7,@-r10
- mov.l r6,@-r10
- mov.l r5,@-r10
- mov.l r4,@-r10
- mov.l r3,@-r10
- mov.l r2,@-r10
- mov.l r1,@-r10
- ocbwb @r0
- cmp/eq r11,r8
- bf/s 1b
- add #28,r10
- !
- mov.l @r15+,r11
- mov.l @r15+,r10
- mov.l @r15+,r9
- mov.l @r15+,r8
- rts
- nop
-#endif
.align 2
.Lpsz: .long PAGE_SIZE
/*
@@ -255,7 +194,11 @@ EX( mov.l @r5+,r8 )
EX( mov.l @r5+,r9 )
EX( mov.l @r5+,r10 )
EX( mov.l @r5+,r11 )
+#ifdef CONFIG_CPU_SH4
EX( movca.l r0,@r4 )
+#else
+EX( mov.l r0,@r4 )
+#endif
add #-32, r6
EX( mov.l r1,@(4,r4) )
mov #32, r0
diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c
index 04a39aa7f1f9..f33cedb353fc 100644
--- a/arch/sh/mm/fault.c
+++ b/arch/sh/mm/fault.c
@@ -207,14 +207,14 @@ no_context:
*/
out_of_memory:
up_read(&mm->mmap_sem);
- if (is_init(current)) {
+ if (is_global_init(current)) {
yield();
down_read(&mm->mmap_sem);
goto survive;
}
printk("VM: killing process %s\n", tsk->comm);
if (user_mode(regs))
- do_exit(SIGKILL);
+ do_group_exit(SIGKILL);
goto no_context;
do_sigbus:
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index 82b68c789a5f..d5e160da64b2 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -294,12 +294,6 @@ int arch_add_memory(int nid, u64 start, u64 size)
}
EXPORT_SYMBOL_GPL(arch_add_memory);
-int remove_memory(u64 start, u64 size)
-{
- return -EINVAL;
-}
-EXPORT_SYMBOL_GPL(remove_memory);
-
#ifdef CONFIG_NUMA
int memory_add_physaddr_to_nid(u64 addr)
{
diff --git a/arch/sh/mm/pg-sh4.c b/arch/sh/mm/pg-sh4.c
index 25f5c6f6821d..8c7a9ca79879 100644
--- a/arch/sh/mm/pg-sh4.c
+++ b/arch/sh/mm/pg-sh4.c
@@ -9,6 +9,8 @@
#include <linux/mm.h>
#include <linux/mutex.h>
#include <linux/fs.h>
+#include <linux/highmem.h>
+#include <linux/module.h>
#include <asm/mmu_context.h>
#include <asm/cacheflush.h>
@@ -50,34 +52,61 @@ static inline void kunmap_coherent(struct page *page)
void clear_user_page(void *to, unsigned long address, struct page *page)
{
__set_bit(PG_mapped, &page->flags);
- if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0)
- clear_page(to);
- else {
- void *vto = kmap_coherent(page, address);
- __clear_user_page(vto, to);
- kunmap_coherent(vto);
- }
+
+ clear_page(to);
+ if ((((address & PAGE_MASK) ^ (unsigned long)to) & CACHE_ALIAS))
+ __flush_wback_region(to, PAGE_SIZE);
}
-/*
- * copy_user_page
- * @to: P1 address
- * @from: P1 address
- * @address: U0 address to be mapped
- * @page: page (virt_to_page(to))
- */
-void copy_user_page(void *to, void *from, unsigned long address,
- struct page *page)
+void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
+ unsigned long vaddr, void *dst, const void *src,
+ unsigned long len)
{
+ void *vto;
+
__set_bit(PG_mapped, &page->flags);
- if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0)
- copy_page(to, from);
- else {
- void *vfrom = kmap_coherent(page, address);
- __copy_user_page(vfrom, from, to);
- kunmap_coherent(vfrom);
- }
+
+ vto = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK);
+ memcpy(vto, src, len);
+ kunmap_coherent(vto);
+
+ if (vma->vm_flags & VM_EXEC)
+ flush_cache_page(vma, vaddr, page_to_pfn(page));
+}
+
+void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
+ unsigned long vaddr, void *dst, const void *src,
+ unsigned long len)
+{
+ void *vfrom;
+
+ __set_bit(PG_mapped, &page->flags);
+
+ vfrom = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK);
+ memcpy(dst, vfrom, len);
+ kunmap_coherent(vfrom);
+}
+
+void copy_user_highpage(struct page *to, struct page *from,
+ unsigned long vaddr, struct vm_area_struct *vma)
+{
+ void *vfrom, *vto;
+
+ __set_bit(PG_mapped, &to->flags);
+
+ vto = kmap_atomic(to, KM_USER1);
+ vfrom = kmap_coherent(from, vaddr);
+ copy_page(vto, vfrom);
+ kunmap_coherent(vfrom);
+
+ if (((vaddr ^ (unsigned long)vto) & CACHE_ALIAS))
+ __flush_wback_region(vto, PAGE_SIZE);
+
+ kunmap_atomic(vto, KM_USER1);
+ /* Make sure this page is cleared on other CPU's too before using it */
+ smp_wmb();
}
+EXPORT_SYMBOL(copy_user_highpage);
/*
* For SH-4, we have our own implementation for ptep_get_and_clear
diff --git a/arch/sh/mm/pmb.c b/arch/sh/mm/pmb.c
index 7d43758dc244..1d45b82f0a63 100644
--- a/arch/sh/mm/pmb.c
+++ b/arch/sh/mm/pmb.c
@@ -292,8 +292,7 @@ void pmb_unmap(unsigned long addr)
} while (pmbe);
}
-static void pmb_cache_ctor(void *pmb, struct kmem_cache *cachep,
- unsigned long flags)
+static void pmb_cache_ctor(struct kmem_cache *cachep, void *pmb)
{
struct pmb_entry *pmbe = pmb;
diff --git a/arch/sh/oprofile/Kconfig b/arch/sh/oprofile/Kconfig
deleted file mode 100644
index 5ade19801b97..000000000000
--- a/arch/sh/oprofile/Kconfig
+++ /dev/null
@@ -1,23 +0,0 @@
-
-menu "Profiling support"
- depends on EXPERIMENTAL
-
-config PROFILING
- bool "Profiling support (EXPERIMENTAL)"
- help
- Say Y here to enable the extended profiling support mechanisms used
- by profilers such as OProfile.
-
-
-config OPROFILE
- tristate "OProfile system profiling (EXPERIMENTAL)"
- depends on PROFILING
- help
- OProfile is a profiling system capable of profiling the
- whole system, include the kernel, kernel modules, libraries,
- and applications.
-
- If unsure, say N.
-
-endmenu
-
diff --git a/arch/sh/oprofile/Makefile b/arch/sh/oprofile/Makefile
index 1f25d9bb7538..2efc2e79fd29 100644
--- a/arch/sh/oprofile/Makefile
+++ b/arch/sh/oprofile/Makefile
@@ -15,3 +15,4 @@ profdrvr-$(CONFIG_CPU_SUBTYPE_SH7091) := op_model_sh7750.o
oprofile-y := $(DRIVER_OBJS) $(profdrvr-y)
+EXTRA_CFLAGS += -Werror
diff --git a/arch/sh/oprofile/op_model_sh7750.c b/arch/sh/oprofile/op_model_sh7750.c
index ebee7e24ede9..6b9a98e07004 100644
--- a/arch/sh/oprofile/op_model_sh7750.c
+++ b/arch/sh/oprofile/op_model_sh7750.c
@@ -16,7 +16,6 @@
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/fs.h>
-#include <linux/notifier.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -44,8 +43,6 @@
*/
#define NR_CNTRS 2
-extern const char *get_cpu_subtype(void);
-
struct op_counter_config {
unsigned long enabled;
unsigned long event;
@@ -111,17 +108,12 @@ static struct op_counter_config ctr[NR_CNTRS];
* behavior.
*/
-static int sh7750_timer_notify(struct notifier_block *self,
- unsigned long val, void *regs)
+static int sh7750_timer_notify(struct pt_regs *regs)
{
- oprofile_add_sample((struct pt_regs *)regs, 0);
+ oprofile_add_sample(regs, 0);
return 0;
}
-static struct notifier_block sh7750_timer_notifier = {
- .notifier_call = sh7750_timer_notify,
-};
-
static u64 sh7750_read_counter(int counter)
{
u32 hi, lo;
@@ -240,7 +232,7 @@ static int sh7750_perf_counter_start(void)
ctrl_outw(pmcr | PMCR_ENABLE, PMCR2);
}
- return register_profile_notifier(&sh7750_timer_notifier);
+ return register_timer_hook(sh7750_timer_notify);
}
static void sh7750_perf_counter_stop(void)
@@ -248,7 +240,7 @@ static void sh7750_perf_counter_stop(void)
ctrl_outw(ctrl_inw(PMCR1) & ~PMCR_PMEN, PMCR1);
ctrl_outw(ctrl_inw(PMCR2) & ~PMCR_PMEN, PMCR2);
- unregister_profile_notifier(&sh7750_timer_notifier);
+ unregister_timer_hook(sh7750_timer_notify);
}
static struct oprofile_operations sh7750_perf_counter_ops = {
@@ -257,13 +249,13 @@ static struct oprofile_operations sh7750_perf_counter_ops = {
.stop = sh7750_perf_counter_stop,
};
-int __init oprofile_arch_init(struct oprofile_operations **ops)
+int __init oprofile_arch_init(struct oprofile_operations *ops)
{
if (!(current_cpu_data.flags & CPU_HAS_PERF_COUNTER))
return -ENODEV;
- sh7750_perf_counter_ops.cpu_type = (char *)get_cpu_subtype();
- *ops = &sh7750_perf_counter_ops;
+ ops = &sh7750_perf_counter_ops;
+ ops->cpu_type = (char *)get_cpu_subtype(&current_cpu_data);
printk(KERN_INFO "oprofile: using SH-4 (%s) performance monitoring.\n",
sh7750_perf_counter_ops.cpu_type);
diff --git a/arch/sh/tools/mach-types b/arch/sh/tools/mach-types
index 439bfe3d29af..ff071693325c 100644
--- a/arch/sh/tools/mach-types
+++ b/arch/sh/tools/mach-types
@@ -1,26 +1,35 @@
#
-# List of boards.
+# MACH_<xxx> CONFIG_<xxx>
#
#
-# MACH_<xxx> CONFIG_<xxx>
+# List of board groups.
#
SE SH_SOLUTION_ENGINE
-7751SE SH_7751_SOLUTION_ENGINE
-7722SE SH_7722_SOLUTION_ENGINE
-7343SE SH_7343_SOLUTION_ENGINE
+HIGHLANDER SH_HIGHLANDER
+RTS7751R2D SH_RTS7751R2D
+
+#
+# List of companion chips / MFDs.
+#
+HD64461 HD64461
+HD64465 HD64465
+
+#
+# List of boards.
+#
7206SE SH_7206_SOLUTION_ENGINE
+7343SE SH_7343_SOLUTION_ENGINE
7619SE SH_7619_SOLUTION_ENGINE
+7722SE SH_7722_SOLUTION_ENGINE
+7751SE SH_7751_SOLUTION_ENGINE
7780SE SH_7780_SOLUTION_ENGINE
7751SYSTEMH SH_7751_SYSTEMH
HP6XX SH_HP6XX
-HD64461 HD64461
-HD64465 HD64465
DREAMCAST SH_DREAMCAST
MPC1211 SH_MPC1211
SNAPGEAR SH_SECUREEDGE5410
HS7751RVOIP SH_HS7751RVOIP
-RTS7751R2D SH_RTS7751R2D
EDOSK7705 SH_EDOSK7705
SH4202_MICRODEV SH_SH4202_MICRODEV
SH03 SH_SH03
@@ -32,3 +41,7 @@ TITAN SH_TITAN
SHMIN SH_SHMIN
7710VOIPGW SH_7710VOIPGW
LBOXRE2 SH_LBOX_RE2
+X3PROTO SH_X3PROTO
+MAGICPANELR2 SH_MAGIC_PANEL_R2
+R2D_PLUS RTS7751R2D_PLUS
+R2D_1 RTS7751R2D_1
diff --git a/arch/sh64/Kconfig b/arch/sh64/Kconfig
index b3327ce8e82f..6884d5a518ad 100644
--- a/arch/sh64/Kconfig
+++ b/arch/sh64/Kconfig
@@ -1,6 +1,6 @@
#
# For a description of the syntax of this configuration file,
-# see Documentation/kbuild/config-language.txt.
+# see Documentation/kbuild/kconfig-language.txt.
#
mainmenu "Linux/SH64 Kernel Configuration"
@@ -284,7 +284,7 @@ source "drivers/Kconfig"
source "fs/Kconfig"
-source "arch/sh64/oprofile/Kconfig"
+source "kernel/Kconfig.instrumentation"
source "arch/sh64/Kconfig.debug"
diff --git a/arch/sh64/Makefile b/arch/sh64/Makefile
index 8290c6380d7d..8dac7e1a2be6 100644
--- a/arch/sh64/Makefile
+++ b/arch/sh64/Makefile
@@ -26,7 +26,7 @@ LDFLAGS += -EB -mshelf32_linux
endif
# No requirements for endianess support from AFLAGS, 'as' always run through gcc
-CFLAGS += $(cpu-y)
+KBUILD_CFLAGS += $(cpu-y)
LDFLAGS_vmlinux += --defsym phys_stext=_stext-$(CONFIG_CACHED_MEMORY_OFFSET) \
--defsym phys_stext_shmedia=phys_stext+1 \
@@ -58,7 +58,7 @@ ifneq ($(machine-y),)
core-y += arch/sh64/mach-$(machine-y)/
endif
-LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
+LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
libs-y += arch/$(ARCH)/lib/ $(LIBGCC)
drivers-$(CONFIG_OPROFILE) += arch/sh64/oprofile/
diff --git a/arch/sh64/configs/cayman_defconfig b/arch/sh64/configs/cayman_defconfig
index 91b59118c1b1..75552bb01405 100644
--- a/arch/sh64/configs/cayman_defconfig
+++ b/arch/sh64/configs/cayman_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.23-rc8
-# Tue Oct 9 15:37:16 2007
+# Linux kernel version: 2.6.24-rc1
+# Fri Nov 2 14:35:27 2007
#
CONFIG_SUPERH=y
CONFIG_SUPERH64=y
@@ -36,6 +36,10 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_FAIR_USER_SCHED=y
+# CONFIG_FAIR_CGROUP_SCHED is not set
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
# CONFIG_BLK_DEV_INITRD is not set
@@ -148,6 +152,7 @@ CONFIG_FLATMEM_MANUAL=y
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
@@ -160,10 +165,6 @@ CONFIG_PCI=y
CONFIG_SH_PCIDMA_NONCOHERENT=y
# CONFIG_ARCH_SUPPORTS_MSI is not set
# CONFIG_PCI_DEBUG is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
@@ -209,6 +210,7 @@ CONFIG_IP_PNP=y
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
@@ -234,10 +236,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
# CONFIG_NET_SCHED is not set
#
@@ -266,6 +264,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
#
# Generic Driver Options
#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
@@ -333,6 +332,7 @@ CONFIG_SCSI_SPI_ATTRS=y
# CONFIG_SCSI_FC_ATTRS is not set
# 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_BLK_DEV_3W_XXXX_RAID is not set
@@ -370,14 +370,7 @@ CONFIG_SCSI_SYM53C8XX_MMIO=y
# CONFIG_SCSI_SRP is not set
# CONFIG_ATA is not set
# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
# CONFIG_FUSION is not set
-# CONFIG_FUSION_SPI is not set
-# CONFIG_FUSION_FC is not set
-# CONFIG_FUSION_SAS is not set
#
# IEEE 1394 (FireWire) support
@@ -392,6 +385,8 @@ CONFIG_NETDEVICES=y
# CONFIG_MACVLAN is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_IP1000 is not set
# CONFIG_ARCNET is not set
# CONFIG_PHYLIB is not set
CONFIG_NET_ETHERNET=y
@@ -402,6 +397,7 @@ CONFIG_NET_ETHERNET=y
# CONFIG_CASSINI is not set
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_SMC91X is not set
+# CONFIG_SMC911X is not set
CONFIG_NET_TULIP=y
# CONFIG_DE2104X is not set
CONFIG_TULIP=y
@@ -413,13 +409,16 @@ CONFIG_TULIP=y
# 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_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_DGRS is not set
# CONFIG_EEPRO100 is not set
# CONFIG_E100 is not set
# CONFIG_FEALNX is not set
@@ -437,6 +436,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
@@ -453,11 +453,14 @@ CONFIG_NETDEV_1000=y
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
# CONFIG_CHELSIO_T3 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_CORE is not set
+# CONFIG_TEHUTI is not set
# CONFIG_TR is not set
#
@@ -493,7 +496,6 @@ 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_TSDEV is not set
# CONFIG_INPUT_EVDEV is not set
# CONFIG_INPUT_EVBUG is not set
@@ -561,23 +563,9 @@ CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-
-#
-# Watchdog Device Drivers
-#
-# CONFIG_SOFT_WATCHDOG is not set
-
-#
-# PCI-based Watchdog Cards
-#
-# CONFIG_PCIPCWATCHDOG is not set
-# CONFIG_WDTPCI is not set
CONFIG_HW_RANDOM=y
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
-# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
# CONFIG_TCG_TPM is not set
CONFIG_DEVPORT=y
@@ -644,8 +632,6 @@ CONFIG_I2C_BOARDINFO=y
# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
-# CONFIG_SENSORS_ABITUGURU3 is not set
# CONFIG_SENSORS_AD7418 is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
@@ -653,12 +639,12 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
-# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_FSCPOS 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
@@ -694,6 +680,25 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
#
# Multifunction device drivers
@@ -713,11 +718,11 @@ CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
# CONFIG_VIDEO_VIVI is not set
# CONFIG_VIDEO_SAA5246A is not set
# CONFIG_VIDEO_SAA5249 is not set
-# CONFIG_TUNER_TEA5761 is not set
# CONFIG_VIDEO_SAA7134 is not set
# CONFIG_VIDEO_HEXIUM_ORION is not set
# CONFIG_VIDEO_HEXIUM_GEMINI is not set
# CONFIG_VIDEO_CX88 is not set
+# CONFIG_VIDEO_CX23885 is not set
# CONFIG_VIDEO_CAFE_CCIC is not set
# CONFIG_RADIO_ADAPTERS is not set
CONFIG_DVB_CORE=y
@@ -796,6 +801,7 @@ CONFIG_DVB_CAPTURE_DRIVERS=y
# CONFIG_DVB_OR51132 is not set
# CONFIG_DVB_BCM3510 is not set
# CONFIG_DVB_LGDT330X is not set
+# CONFIG_DVB_S5H1409 is not set
#
# Tuners/PLL support
@@ -805,6 +811,9 @@ CONFIG_DVB_CAPTURE_DRIVERS=y
# CONFIG_DVB_TDA827X is not set
# CONFIG_DVB_TUNER_QT1010 is not set
# CONFIG_DVB_TUNER_MT2060 is not set
+# CONFIG_DVB_TUNER_MT2266 is not set
+# CONFIG_DVB_TUNER_MT2131 is not set
+# CONFIG_DVB_TUNER_DIB0070 is not set
#
# Miscellaneous devices
@@ -817,12 +826,7 @@ CONFIG_DAB=y
#
# Graphics support
#
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Display device support
-#
-# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_DRM is not set
# CONFIG_VGASTATE is not set
CONFIG_VIDEO_OUTPUT_CONTROL=y
CONFIG_FB=y
@@ -831,6 +835,7 @@ CONFIG_FIRMWARE_EDID=y
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
# CONFIG_FB_SYS_FILLRECT is not set
# CONFIG_FB_SYS_COPYAREA is not set
# CONFIG_FB_SYS_IMAGEBLIT is not set
@@ -869,6 +874,12 @@ CONFIG_FB_KYRO=y
# CONFIG_FB_ARK is not set
# CONFIG_FB_PM3 is not set
# CONFIG_FB_VIRTUAL is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
#
# Console display driver support
@@ -903,6 +914,7 @@ CONFIG_LOGO_SUPERH_CLUT224=y
CONFIG_HID_SUPPORT=y
CONFIG_HID=y
# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
@@ -923,19 +935,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_RTC_CLASS is not set
#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
# Userspace I/O
#
# CONFIG_UIO is not set
@@ -994,7 +993,6 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
-CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -1013,10 +1011,7 @@ CONFIG_RAMFS=y
# CONFIG_QNX4FS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
+CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
@@ -1058,26 +1053,17 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
# CONFIG_SYSV68_PARTITION is not set
-
-#
-# Native Language Support
-#
# CONFIG_NLS is not set
-
-#
-# Distributed Lock Manager
-#
# CONFIG_DLM is not set
-
-#
-# Profiling support
-#
+CONFIG_INSTRUMENTATION=y
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
#
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
@@ -1101,10 +1087,13 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
CONFIG_FRAME_POINTER=y
CONFIG_FORCED_INLINING=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_FAULT_INJECTION is not set
+# CONFIG_SAMPLES is not set
# CONFIG_EARLY_PRINTK is not set
CONFIG_SH64_PROC_TLB=y
CONFIG_SH64_PROC_ASIDS=y
@@ -1118,6 +1107,7 @@ CONFIG_SH64_SR_WATCH=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
# CONFIG_CRYPTO is not set
#
diff --git a/arch/sh64/configs/harp_defconfig b/arch/sh64/configs/harp_defconfig
index e4b84b51baf8..ba302cd0c285 100644
--- a/arch/sh64/configs/harp_defconfig
+++ b/arch/sh64/configs/harp_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.23-rc8
-# Mon Oct 1 18:01:38 2007
+# Linux kernel version: 2.6.24-rc1
+# Fri Nov 2 14:35:57 2007
#
CONFIG_SUPERH=y
CONFIG_SUPERH64=y
@@ -36,6 +36,10 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_FAIR_USER_SCHED=y
+# CONFIG_FAIR_CGROUP_SCHED is not set
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
# CONFIG_BLK_DEV_INITRD is not set
@@ -141,6 +145,7 @@ CONFIG_FLATMEM_MANUAL=y
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
@@ -150,10 +155,6 @@ CONFIG_NR_QUICK=1
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
#
# CONFIG_ARCH_SUPPORTS_MSI is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
# CONFIG_PCCARD is not set
#
@@ -198,6 +199,7 @@ CONFIG_IP_PNP=y
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
@@ -223,10 +225,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
# CONFIG_NET_SCHED is not set
#
@@ -255,6 +253,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
#
# Generic Driver Options
#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
@@ -314,6 +313,7 @@ CONFIG_SCSI_SPI_ATTRS=y
# CONFIG_SCSI_FC_ATTRS is not set
# 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_DEBUG is not set
@@ -326,11 +326,18 @@ CONFIG_NETDEVICES=y
# CONFIG_MACVLAN is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
+# CONFIG_VETH is not set
# CONFIG_PHYLIB is not set
CONFIG_NET_ETHERNET=y
# CONFIG_MII is not set
# CONFIG_STNIC is not set
# CONFIG_SMC91X is not set
+# CONFIG_SMC911X 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_B44 is not set
CONFIG_NETDEV_1000=y
CONFIG_NETDEV_10000=y
@@ -364,7 +371,6 @@ CONFIG_INPUT_MOUSEDEV=y
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
# CONFIG_INPUT_EVDEV is not set
# CONFIG_INPUT_EVBUG is not set
@@ -410,13 +416,6 @@ CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-
-#
-# Watchdog Device Drivers
-#
-# CONFIG_SOFT_WATCHDOG is not set
CONFIG_HW_RANDOM=y
# CONFIG_R3964 is not set
# CONFIG_RAW_DRIVER is not set
@@ -432,9 +431,8 @@ CONFIG_HW_RANDOM=y
# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
-# CONFIG_SENSORS_ABITUGURU3 is not set
# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
# CONFIG_SENSORS_IT87 is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_PC87427 is not set
@@ -444,6 +442,19 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
#
# Multifunction device drivers
@@ -460,12 +471,6 @@ CONFIG_DAB=y
#
# Graphics support
#
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Display device support
-#
-# CONFIG_DISPLAY_SUPPORT is not set
# CONFIG_VGASTATE is not set
CONFIG_VIDEO_OUTPUT_CONTROL=y
CONFIG_FB=y
@@ -474,6 +479,7 @@ CONFIG_FIRMWARE_EDID=y
# CONFIG_FB_CFB_FILLRECT is not set
# CONFIG_FB_CFB_COPYAREA is not set
# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
# CONFIG_FB_SYS_FILLRECT is not set
# CONFIG_FB_SYS_COPYAREA is not set
# CONFIG_FB_SYS_IMAGEBLIT is not set
@@ -490,6 +496,12 @@ CONFIG_FB_MODE_HELPERS=y
#
# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_VIRTUAL is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
#
# Console display driver support
@@ -524,6 +536,7 @@ CONFIG_LOGO_SUPERH_CLUT224=y
CONFIG_HID_SUPPORT=y
CONFIG_HID=y
# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
# CONFIG_USB_ARCH_HAS_OHCI is not set
@@ -543,19 +556,6 @@ CONFIG_USB_ARCH_HAS_HCD=y
# CONFIG_RTC_CLASS is not set
#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
# Userspace I/O
#
# CONFIG_UIO is not set
@@ -614,7 +614,6 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
-CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -633,10 +632,7 @@ CONFIG_RAMFS=y
# CONFIG_QNX4FS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
+CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
@@ -678,26 +674,17 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
# CONFIG_SYSV68_PARTITION is not set
-
-#
-# Native Language Support
-#
# CONFIG_NLS is not set
-
-#
-# Distributed Lock Manager
-#
# CONFIG_DLM is not set
-
-#
-# Profiling support
-#
+CONFIG_INSTRUMENTATION=y
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
#
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
@@ -721,16 +708,17 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
CONFIG_FRAME_POINTER=y
CONFIG_FORCED_INLINING=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_FAULT_INJECTION is not set
+# CONFIG_SAMPLES is not set
# CONFIG_EARLY_PRINTK is not set
-# CONFIG_DEBUG_KERNEL_WITH_GDB_STUB is not set
CONFIG_SH64_PROC_TLB=y
CONFIG_SH64_PROC_ASIDS=y
CONFIG_SH64_SR_WATCH=y
# CONFIG_POOR_MANS_STRACE is not set
-# CONFIG_SH_ALPHANUMERIC is not set
# CONFIG_SH_NO_BSS_INIT is not set
#
@@ -738,6 +726,7 @@ CONFIG_SH64_SR_WATCH=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
# CONFIG_CRYPTO is not set
#
diff --git a/arch/sh64/configs/sim_defconfig b/arch/sh64/configs/sim_defconfig
index f83bae659dc3..18476cc522c3 100644
--- a/arch/sh64/configs/sim_defconfig
+++ b/arch/sh64/configs/sim_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.23-rc8
-# Mon Oct 1 17:50:35 2007
+# Linux kernel version: 2.6.24-rc1
+# Fri Nov 2 14:36:08 2007
#
CONFIG_SUPERH=y
CONFIG_SUPERH64=y
@@ -33,6 +33,10 @@ CONFIG_SWAP=y
# CONFIG_USER_NS is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_FAIR_USER_SCHED=y
+# CONFIG_FAIR_CGROUP_SCHED is not set
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
# CONFIG_BLK_DEV_INITRD is not set
@@ -138,6 +142,7 @@ CONFIG_FLATMEM_MANUAL=y
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
@@ -147,10 +152,6 @@ CONFIG_NR_QUICK=1
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
#
# CONFIG_ARCH_SUPPORTS_MSI is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
# CONFIG_PCCARD is not set
#
@@ -171,6 +172,7 @@ CONFIG_BINFMT_ELF=y
#
# Generic Driver Options
#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
@@ -217,6 +219,7 @@ CONFIG_SCSI_MULTI_LUN=y
CONFIG_SCSI_SPI_ATTRS=y
# CONFIG_SCSI_FC_ATTRS is not set
# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_SCSI_DEBUG is not set
# CONFIG_ATA is not set
@@ -238,7 +241,6 @@ CONFIG_INPUT_MOUSEDEV=y
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
# CONFIG_INPUT_EVDEV is not set
# CONFIG_INPUT_EVBUG is not set
@@ -283,7 +285,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
# CONFIG_LEGACY_PTYS is not set
# CONFIG_IPMI_HANDLER is not set
-# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_R3964 is not set
# CONFIG_RAW_DRIVER is not set
@@ -298,6 +299,13 @@ CONFIG_UNIX98_PTYS=y
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
#
# Multifunction device drivers
@@ -313,12 +321,6 @@ CONFIG_DAB=y
#
# Graphics support
#
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Display device support
-#
-# CONFIG_DISPLAY_SUPPORT is not set
# CONFIG_VGASTATE is not set
CONFIG_VIDEO_OUTPUT_CONTROL=y
CONFIG_FB=y
@@ -327,6 +329,7 @@ CONFIG_FIRMWARE_EDID=y
# CONFIG_FB_CFB_FILLRECT is not set
# CONFIG_FB_CFB_COPYAREA is not set
# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
# CONFIG_FB_SYS_FILLRECT is not set
# CONFIG_FB_SYS_COPYAREA is not set
# CONFIG_FB_SYS_IMAGEBLIT is not set
@@ -343,6 +346,12 @@ CONFIG_FB_MODE_HELPERS=y
#
# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_VIRTUAL is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
#
# Console display driver support
@@ -381,19 +390,6 @@ CONFIG_LOGO_SUPERH_CLUT224=y
# CONFIG_RTC_CLASS is not set
#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
# Userspace I/O
#
# CONFIG_UIO is not set
@@ -451,7 +447,6 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
-CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -492,22 +487,17 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
# CONFIG_SYSV68_PARTITION is not set
-
-#
-# Native Language Support
-#
# CONFIG_NLS is not set
-
-#
-# Profiling support
-#
+CONFIG_INSTRUMENTATION=y
CONFIG_PROFILING=y
# CONFIG_OPROFILE is not set
+# CONFIG_MARKERS is not set
#
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
@@ -531,16 +521,17 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
CONFIG_FRAME_POINTER=y
CONFIG_FORCED_INLINING=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_FAULT_INJECTION is not set
+# CONFIG_SAMPLES is not set
# CONFIG_EARLY_PRINTK is not set
-# CONFIG_DEBUG_KERNEL_WITH_GDB_STUB is not set
CONFIG_SH64_PROC_TLB=y
CONFIG_SH64_PROC_ASIDS=y
CONFIG_SH64_SR_WATCH=y
# CONFIG_POOR_MANS_STRACE is not set
-# CONFIG_SH_ALPHANUMERIC is not set
CONFIG_SH_NO_BSS_INIT=y
#
@@ -548,6 +539,7 @@ CONFIG_SH_NO_BSS_INIT=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
# CONFIG_CRYPTO is not set
#
diff --git a/arch/sh64/kernel/pci_sh5.c b/arch/sh64/kernel/pci_sh5.c
index 388bb711f1b0..b4d9534d2b0e 100644
--- a/arch/sh64/kernel/pci_sh5.c
+++ b/arch/sh64/kernel/pci_sh5.c
@@ -480,7 +480,7 @@ static int __init pcibios_init(void)
return -EINVAL;
}
- /* The pci subsytem needs to know where memory is and how much
+ /* The pci subsystem needs to know where memory is and how much
* of it there is. I've simply made these globals. A better mechanism
* is probably needed.
*/
diff --git a/arch/sh64/kernel/process.c b/arch/sh64/kernel/process.c
index ceb9458abda4..0761af4d2a42 100644
--- a/arch/sh64/kernel/process.c
+++ b/arch/sh64/kernel/process.c
@@ -26,6 +26,7 @@
#include <linux/reboot.h>
#include <linux/init.h>
#include <linux/module.h>
+#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
@@ -656,9 +657,6 @@ unsigned long get_wchan(struct task_struct *p)
*/
#if defined(CONFIG_SH64_PROC_ASIDS)
-#include <linux/init.h>
-#include <linux/proc_fs.h>
-
static int
asids_proc_info(char *buf, char **start, off_t fpos, int length, int *eof, void *data)
{
@@ -686,10 +684,8 @@ asids_proc_info(char *buf, char **start, off_t fpos, int length, int *eof, void
static int __init register_proc_asids(void)
{
- create_proc_read_entry("asids", 0, NULL, asids_proc_info, NULL);
- return 0;
+ create_proc_read_entry("asids", 0, NULL, asids_proc_info, NULL);
+ return 0;
}
-
__initcall(register_proc_asids);
#endif
-
diff --git a/arch/sh64/kernel/ptrace.c b/arch/sh64/kernel/ptrace.c
index df06c6477468..8a2d339cf760 100644
--- a/arch/sh64/kernel/ptrace.c
+++ b/arch/sh64/kernel/ptrace.c
@@ -244,10 +244,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
}
- case PTRACE_DETACH: /* detach a process that was attached. */
- ret = ptrace_detach(child, data);
- break;
-
default:
ret = ptrace_request(child, request, addr, data);
break;
diff --git a/arch/sh64/kernel/sys_sh64.c b/arch/sh64/kernel/sys_sh64.c
index b7f18e298a20..de0a303ba26f 100644
--- a/arch/sh64/kernel/sys_sh64.c
+++ b/arch/sh64/kernel/sys_sh64.c
@@ -29,8 +29,8 @@
#include <linux/file.h>
#include <linux/utsname.h>
#include <linux/syscalls.h>
+#include <linux/ipc.h>
#include <asm/uaccess.h>
-#include <asm/ipc.h>
#include <asm/ptrace.h>
#include <asm/unistd.h>
diff --git a/arch/sh64/kernel/traps.c b/arch/sh64/kernel/traps.c
index 9d0d58fb29fa..f32df3831f45 100644
--- a/arch/sh64/kernel/traps.c
+++ b/arch/sh64/kernel/traps.c
@@ -30,7 +30,6 @@
#include <linux/interrupt.h>
#include <linux/sysctl.h>
#include <linux/module.h>
-
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -242,9 +241,6 @@ DO_ERROR(12, SIGILL, "reserved instruction", reserved_inst, current)
#endif /* CONFIG_SH64_ID2815_WORKAROUND */
-
-#include <asm/system.h>
-
/* Called with interrupts disabled */
asmlinkage void do_exception_error(unsigned long ex, struct pt_regs *regs)
{
@@ -764,7 +760,7 @@ static int misaligned_fixup(struct pt_regs *regs)
--user_mode_unaligned_fixup_count;
/* Only do 'count' worth of these reports, to remove a potential DoS against syslog */
printk("Fixing up unaligned userspace access in \"%s\" pid=%d pc=0x%08x ins=0x%08lx\n",
- current->comm, current->pid, (__u32)regs->pc, opcode);
+ current->comm, task_pid_nr(current), (__u32)regs->pc, opcode);
} else
#endif
if (!user_mode(regs) && (kernel_mode_unaligned_fixup_count > 0)) {
@@ -774,7 +770,7 @@ static int misaligned_fixup(struct pt_regs *regs)
(__u32)regs->pc, opcode);
} else {
printk("Fixing up unaligned kernelspace access in \"%s\" pid=%d pc=0x%08x ins=0x%08lx\n",
- current->comm, current->pid, (__u32)regs->pc, opcode);
+ current->comm, task_pid_nr(current), (__u32)regs->pc, opcode);
}
}
@@ -984,4 +980,3 @@ asmlinkage void do_debug_interrupt(unsigned long code, struct pt_regs *regs)
/* Clear all DEBUGINT causes */
poke_real_address_q(DM_EXP_CAUSE_PHY, 0x0);
}
-
diff --git a/arch/sh64/mm/consistent.c b/arch/sh64/mm/consistent.c
index 8875a2a40da7..c439620402cb 100644
--- a/arch/sh64/mm/consistent.c
+++ b/arch/sh64/mm/consistent.c
@@ -11,6 +11,7 @@
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/pci.h>
+#include <linux/dma-mapping.h>
#include <linux/module.h>
#include <asm/io.h>
@@ -32,7 +33,7 @@ void *consistent_alloc(struct pci_dev *hwdev, size_t size,
if (vp != NULL) {
memset(vp, 0, size);
*dma_handle = virt_to_phys(ret);
- dma_cache_wback_inv((unsigned long)ret, size);
+ dma_cache_sync(NULL, ret, size, DMA_BIDIRECTIONAL);
}
return vp;
diff --git a/arch/sh64/mm/fault.c b/arch/sh64/mm/fault.c
index 0d069d82141f..7c79a1ba8059 100644
--- a/arch/sh64/mm/fault.c
+++ b/arch/sh64/mm/fault.c
@@ -81,7 +81,7 @@ static inline void print_vma(struct vm_area_struct *vma)
static inline void print_task(struct task_struct *tsk)
{
- printk("Task pid %d\n", tsk->pid);
+ printk("Task pid %d\n", task_pid_nr(tsk));
}
static pte_t *lookup_pte(struct mm_struct *mm, unsigned long address)
@@ -272,13 +272,13 @@ bad_area:
* usermode, so only need a few */
count++;
printk("user mode bad_area address=%08lx pid=%d (%s) pc=%08lx\n",
- address, current->pid, current->comm,
+ address, task_pid_nr(current), current->comm,
(unsigned long) regs->pc);
#if 0
show_regs(regs);
#endif
}
- if (is_init(tsk)) {
+ if (is_global_init(tsk)) {
panic("INIT had user mode bad_area\n");
}
tsk->thread.address = address;
@@ -320,21 +320,21 @@ no_context:
* us unable to handle the page fault gracefully.
*/
out_of_memory:
- if (is_init(current)) {
+ if (is_global_init(current)) {
panic("INIT out of memory\n");
yield();
goto survive;
}
printk("fault:Out of memory\n");
up_read(&mm->mmap_sem);
- if (is_init(current)) {
+ if (is_global_init(current)) {
yield();
down_read(&mm->mmap_sem);
goto survive;
}
printk("VM: killing process %s\n", tsk->comm);
if (user_mode(regs))
- do_exit(SIGKILL);
+ do_group_exit(SIGKILL);
goto no_context;
do_sigbus:
diff --git a/arch/sh64/oprofile/Kconfig b/arch/sh64/oprofile/Kconfig
deleted file mode 100644
index 19d37730b664..000000000000
--- a/arch/sh64/oprofile/Kconfig
+++ /dev/null
@@ -1,23 +0,0 @@
-
-menu "Profiling support"
- depends on EXPERIMENTAL
-
-config PROFILING
- bool "Profiling support (EXPERIMENTAL)"
- help
- Say Y here to enable the extended profiling support mechanisms used
- by profilers such as OProfile.
-
-
-config OPROFILE
- tristate "OProfile system profiling (EXPERIMENTAL)"
- depends on PROFILING
- help
- OProfile is a profiling system capable of profiling the
- whole system, include the kernel, kernel modules, libraries,
- and applications.
-
- If unsure, say N.
-
-endmenu
-
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 9d327ec59759..527adc808ad6 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -320,12 +320,7 @@ endmenu
source "fs/Kconfig"
-menu "Instrumentation Support"
- depends on EXPERIMENTAL
-
-source "arch/sparc/oprofile/Kconfig"
-
-endmenu
+source "kernel/Kconfig.instrumentation"
source "arch/sparc/Kconfig.debug"
diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile
index f33c3817f014..fef28e267a52 100644
--- a/arch/sparc/Makefile
+++ b/arch/sparc/Makefile
@@ -8,16 +8,16 @@
#
#
-# Uncomment the first CFLAGS if you are doing kgdb source level
+# Uncomment the first KBUILD_CFLAGS if you are doing kgdb source level
# debugging of the kernel to get the proper debugging information.
AS := $(AS) -32
LDFLAGS := -m elf32_sparc
CHECKFLAGS += -D__sparc__
-#CFLAGS := $(CFLAGS) -g -pipe -fcall-used-g5 -fcall-used-g7
-CFLAGS := $(CFLAGS) -m32 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7
-AFLAGS := $(AFLAGS) -m32
+#KBUILD_CFLAGS += -g -pipe -fcall-used-g5 -fcall-used-g7
+KBUILD_CFLAGS += -m32 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7
+KBUILD_AFLAGS += -m32
#LDFLAGS_vmlinux = -N -Ttext 0xf0004000
# Since 2.5.40, the first stage is left not btfix-ed.
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index 62182d2d7b0d..97aa50d1e4ae 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -35,6 +35,7 @@
#include <linux/slab.h>
#include <linux/pci.h> /* struct pci_dev */
#include <linux/proc_fs.h>
+#include <linux/scatterlist.h>
#include <asm/io.h>
#include <asm/vaddrs.h>
@@ -717,19 +718,18 @@ void pci_unmap_page(struct pci_dev *hwdev,
* Device ownership issues as mentioned above for pci_map_single are
* the same here.
*/
-int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents,
+int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sgl, int nents,
int direction)
{
+ struct scatterlist *sg;
int n;
BUG_ON(direction == PCI_DMA_NONE);
/* IIep is write-through, not flushing. */
- for (n = 0; n < nents; n++) {
- BUG_ON(page_address(sg->page) == NULL);
- sg->dvma_address =
- virt_to_phys(page_address(sg->page)) + sg->offset;
+ for_each_sg(sgl, sg, nents, n) {
+ BUG_ON(page_address(sg_page(sg)) == NULL);
+ sg->dvma_address = virt_to_phys(sg_virt(sg));
sg->dvma_length = sg->length;
- sg++;
}
return nents;
}
@@ -738,19 +738,19 @@ int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents,
* Again, cpu read rules concerning calls here are the same as for
* pci_unmap_single() above.
*/
-void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents,
+void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sgl, int nents,
int direction)
{
+ struct scatterlist *sg;
int n;
BUG_ON(direction == PCI_DMA_NONE);
if (direction != PCI_DMA_TODEVICE) {
- for (n = 0; n < nents; n++) {
- BUG_ON(page_address(sg->page) == NULL);
+ for_each_sg(sgl, sg, nents, n) {
+ BUG_ON(page_address(sg_page(sg)) == NULL);
mmu_inval_dma_area(
- (unsigned long) page_address(sg->page),
+ (unsigned long) page_address(sg_page(sg)),
(sg->length + PAGE_SIZE-1) & PAGE_MASK);
- sg++;
}
}
}
@@ -789,34 +789,34 @@ void pci_dma_sync_single_for_device(struct pci_dev *hwdev, dma_addr_t ba, size_t
* The same as pci_dma_sync_single_* but for a scatter-gather list,
* same rules and usage.
*/
-void pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev, struct scatterlist *sg, int nents, int direction)
+void pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev, struct scatterlist *sgl, int nents, int direction)
{
+ struct scatterlist *sg;
int n;
BUG_ON(direction == PCI_DMA_NONE);
if (direction != PCI_DMA_TODEVICE) {
- for (n = 0; n < nents; n++) {
- BUG_ON(page_address(sg->page) == NULL);
+ for_each_sg(sgl, sg, nents, n) {
+ BUG_ON(page_address(sg_page(sg)) == NULL);
mmu_inval_dma_area(
- (unsigned long) page_address(sg->page),
+ (unsigned long) page_address(sg_page(sg)),
(sg->length + PAGE_SIZE-1) & PAGE_MASK);
- sg++;
}
}
}
-void pci_dma_sync_sg_for_device(struct pci_dev *hwdev, struct scatterlist *sg, int nents, int direction)
+void pci_dma_sync_sg_for_device(struct pci_dev *hwdev, struct scatterlist *sgl, int nents, int direction)
{
+ struct scatterlist *sg;
int n;
BUG_ON(direction == PCI_DMA_NONE);
if (direction != PCI_DMA_TODEVICE) {
- for (n = 0; n < nents; n++) {
- BUG_ON(page_address(sg->page) == NULL);
+ for_each_sg(sgl, sg, nents, n) {
+ BUG_ON(page_address(sg_page(sg)) == NULL);
mmu_inval_dma_area(
- (unsigned long) page_address(sg->page),
+ (unsigned long) page_address(sg_page(sg)),
(sg->length + PAGE_SIZE-1) & PAGE_MASK);
- sg++;
}
}
}
diff --git a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c
index 722d67d32961..01a6756ba371 100644
--- a/arch/sparc/kernel/irq.c
+++ b/arch/sparc/kernel/irq.c
@@ -18,7 +18,6 @@
#include <linux/linkage.h>
#include <linux/kernel_stat.h>
#include <linux/signal.h>
-#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/random.h>
@@ -479,7 +478,7 @@ EXPORT_SYMBOL(pdma_areasize);
extern void floppy_hardint(void);
-static irqreturn_t (*floppy_irq_handler)(int irq, void *dev_id);
+static irq_handler_t floppy_irq_handler;
void sparc_floppy_irq(int irq, void *dev_id, struct pt_regs *regs)
{
@@ -500,7 +499,7 @@ void sparc_floppy_irq(int irq, void *dev_id, struct pt_regs *regs)
}
int sparc_floppy_request_irq(int irq, unsigned long flags,
- irqreturn_t (*irq_handler)(int irq, void *))
+ irq_handler_t irq_handler)
{
floppy_irq_handler = irq_handler;
return request_fast_irq(irq, floppy_hardint, flags, "floppy");
diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c
index fb2caef79cec..3ea000d15e3a 100644
--- a/arch/sparc/kernel/of_device.c
+++ b/arch/sparc/kernel/of_device.c
@@ -585,24 +585,6 @@ static int __init of_debug(char *str)
__setup("of_debug=", of_debug);
-int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus)
-{
- /* initialize common driver fields */
- if (!drv->driver.name)
- drv->driver.name = drv->name;
- if (!drv->driver.owner)
- drv->driver.owner = drv->owner;
- drv->driver.bus = bus;
-
- /* register with core */
- return driver_register(&drv->driver);
-}
-
-void of_unregister_driver(struct of_platform_driver *drv)
-{
- driver_unregister(&drv->driver);
-}
-
struct of_device* of_platform_device_create(struct device_node *np,
const char *bus_id,
struct device *parent,
@@ -628,6 +610,4 @@ struct of_device* of_platform_device_create(struct device_node *np,
return dev;
}
-EXPORT_SYMBOL(of_register_driver);
-EXPORT_SYMBOL(of_unregister_driver);
EXPORT_SYMBOL(of_platform_device_create);
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index f2eae457fc9a..f2d432edc92d 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -753,7 +753,7 @@ void __init pci_time_init(void)
local_irq_enable();
}
-static __inline__ unsigned long do_gettimeoffset(void)
+static inline unsigned long do_gettimeoffset(void)
{
/*
* We divide all by 100
diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c
index 33f7a3ddb104..77460e316a03 100644
--- a/arch/sparc/kernel/process.c
+++ b/arch/sparc/kernel/process.c
@@ -1,7 +1,6 @@
-/* $Id: process.c,v 1.161 2002/01/23 11:27:32 davem Exp $
- * linux/arch/sparc/kernel/process.c
+/* linux/arch/sparc/kernel/process.c
*
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1995 David S. Miller (davem@davemloft.net)
* Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
*/
@@ -397,7 +396,7 @@ void flush_thread(void)
}
}
-static __inline__ struct sparc_stackf __user *
+static inline struct sparc_stackf __user *
clone_stackframe(struct sparc_stackf __user *dst,
struct sparc_stackf __user *src)
{
diff --git a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace.c
index 003f8eed32f4..fe562db475e9 100644
--- a/arch/sparc/kernel/ptrace.c
+++ b/arch/sparc/kernel/ptrace.c
@@ -155,7 +155,7 @@ static inline void read_sunos_user(struct pt_regs *regs, unsigned long offset,
/* Rest of them are completely unsupported. */
default:
printk("%s [%d]: Wants to read user offset %ld\n",
- current->comm, current->pid, offset);
+ current->comm, task_pid_nr(current), offset);
pt_error_return(regs, EIO);
return;
}
@@ -222,7 +222,7 @@ static inline void write_sunos_user(struct pt_regs *regs, unsigned long offset,
/* Rest of them are completely unsupported or "no-touch". */
default:
printk("%s [%d]: Wants to write user offset %ld\n",
- current->comm, current->pid, offset);
+ current->comm, task_pid_nr(current), offset);
goto failure;
}
success:
diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c
index a954a0c00000..42bf09db9a81 100644
--- a/arch/sparc/kernel/sys_sparc.c
+++ b/arch/sparc/kernel/sys_sparc.c
@@ -21,9 +21,9 @@
#include <linux/utsname.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
+#include <linux/ipc.h>
#include <asm/uaccess.h>
-#include <asm/ipc.h>
#include <asm/unistd.h>
/* #define DEBUG_UNIMP_SYSCALL */
@@ -357,7 +357,7 @@ c_sys_nis_syscall (struct pt_regs *regs)
if (count++ > 5)
return -ENOSYS;
printk ("%s[%d]: Unimplemented SPARC system call %d\n",
- current->comm, current->pid, (int)regs->u_regs[1]);
+ current->comm, task_pid_nr(current), (int)regs->u_regs[1]);
#ifdef DEBUG_UNIMP_SYSCALL
show_regs (regs);
#endif
diff --git a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c
index f807172cab0e..28c187c5d9fd 100644
--- a/arch/sparc/kernel/sys_sunos.c
+++ b/arch/sparc/kernel/sys_sunos.c
@@ -866,7 +866,7 @@ asmlinkage int sunos_killpg(int pgrp, int sig)
rcu_read_lock();
ret = -EINVAL;
if (pgrp > 0)
- ret = kill_pgrp(find_pid(pgrp), sig, 0);
+ ret = kill_pgrp(find_vpid(pgrp), sig, 0);
rcu_read_unlock();
return ret;
diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c
index 4bf78a5e8e0f..45cb7c5286d7 100644
--- a/arch/sparc/kernel/time.c
+++ b/arch/sparc/kernel/time.c
@@ -1,7 +1,6 @@
-/* $Id: time.c,v 1.60 2002/01/23 14:33:55 davem Exp $
- * linux/arch/sparc/kernel/time.c
+/* linux/arch/sparc/kernel/time.c
*
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1995 David S. Miller (davem@davemloft.net)
* Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu)
*
* Chris Davis (cdavis@cois.on.ca) 03/27/1998
@@ -210,7 +209,7 @@ static void __devinit kick_start_clock(void)
}
/* Return nonzero if the clock chip battery is low. */
-static __inline__ int has_low_battery(void)
+static inline int has_low_battery(void)
{
struct mostek48t02 *regs = (struct mostek48t02 *)mstk48t02_regs;
unsigned char data1, data2;
@@ -252,7 +251,7 @@ static void __devinit mostek_set_system_time(void)
}
/* Probe for the real time clock chip on Sun4 */
-static __inline__ void sun4_clock_probe(void)
+static inline void sun4_clock_probe(void)
{
#ifdef CONFIG_SUN4
int temp;
diff --git a/arch/sparc/kernel/traps.c b/arch/sparc/kernel/traps.c
index 3bc3bff51e08..d404e7994527 100644
--- a/arch/sparc/kernel/traps.c
+++ b/arch/sparc/kernel/traps.c
@@ -38,7 +38,7 @@ struct trap_trace_entry trapbuf[1024];
void syscall_trace_entry(struct pt_regs *regs)
{
- printk("%s[%d]: ", current->comm, current->pid);
+ printk("%s[%d]: ", current->comm, task_pid_nr(current));
printk("scall<%d> (could be %d)\n", (int) regs->u_regs[UREG_G1],
(int) regs->u_regs[UREG_I0]);
}
@@ -99,7 +99,7 @@ void die_if_kernel(char *str, struct pt_regs *regs)
" /_| \\__/ |_\\\n"
" \\__U_/\n");
- printk("%s(%d): %s [#%d]\n", current->comm, current->pid, str, ++die_counter);
+ printk("%s(%d): %s [#%d]\n", current->comm, task_pid_nr(current), str, ++die_counter);
show_regs(regs);
add_taint(TAINT_DIE);
diff --git a/arch/sparc/mm/btfixup.c b/arch/sparc/mm/btfixup.c
index ec4231c2855a..a312d127d47a 100644
--- a/arch/sparc/mm/btfixup.c
+++ b/arch/sparc/mm/btfixup.c
@@ -1,5 +1,4 @@
-/* $Id: btfixup.c,v 1.10 2000/05/09 17:40:13 davem Exp $
- * btfixup.c: Boot time code fixup and relocator, so that
+/* btfixup.c: Boot time code fixup and relocator, so that
* we can get rid of most indirect calls to achieve single
* image sun4c and srmmu kernel.
*
@@ -69,7 +68,7 @@ static void __init set_addr(unsigned int *addr, unsigned int q1, int fmangled, u
}
}
#else
-static __inline__ void set_addr(unsigned int *addr, unsigned int q1, int fmangled, unsigned int value)
+static inline void set_addr(unsigned int *addr, unsigned int q1, int fmangled, unsigned int value)
{
*addr = value;
}
diff --git a/arch/sparc/mm/fault.c b/arch/sparc/mm/fault.c
index 50747fe44356..e4d9c8e19df5 100644
--- a/arch/sparc/mm/fault.c
+++ b/arch/sparc/mm/fault.c
@@ -369,7 +369,7 @@ out_of_memory:
up_read(&mm->mmap_sem);
printk("VM: killing process %s\n", tsk->comm);
if (from_user)
- do_exit(SIGKILL);
+ do_group_exit(SIGKILL);
goto no_context;
do_sigbus:
diff --git a/arch/sparc/mm/io-unit.c b/arch/sparc/mm/io-unit.c
index 7c89893b1fe8..b86dfce8eee4 100644
--- a/arch/sparc/mm/io-unit.c
+++ b/arch/sparc/mm/io-unit.c
@@ -11,8 +11,8 @@
#include <linux/mm.h>
#include <linux/highmem.h> /* pte_offset_map => kmap_atomic */
#include <linux/bitops.h>
+#include <linux/scatterlist.h>
-#include <asm/scatterlist.h>
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
#include <asm/sbus.h>
@@ -144,8 +144,9 @@ static void iounit_get_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus
spin_lock_irqsave(&iounit->lock, flags);
while (sz != 0) {
--sz;
- sg[sz].dvma_address = iounit_get_area(iounit, (unsigned long)page_address(sg[sz].page) + sg[sz].offset, sg[sz].length);
- sg[sz].dvma_length = sg[sz].length;
+ sg->dvma_address = iounit_get_area(iounit, (unsigned long) sg_virt(sg), sg->length);
+ sg->dvma_length = sg->length;
+ sg = sg_next(sg);
}
spin_unlock_irqrestore(&iounit->lock, flags);
}
@@ -173,11 +174,12 @@ static void iounit_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_
spin_lock_irqsave(&iounit->lock, flags);
while (sz != 0) {
--sz;
- len = ((sg[sz].dvma_address & ~PAGE_MASK) + sg[sz].length + (PAGE_SIZE-1)) >> PAGE_SHIFT;
- vaddr = (sg[sz].dvma_address - IOUNIT_DMA_BASE) >> PAGE_SHIFT;
+ len = ((sg->dvma_address & ~PAGE_MASK) + sg->length + (PAGE_SIZE-1)) >> PAGE_SHIFT;
+ vaddr = (sg->dvma_address - IOUNIT_DMA_BASE) >> PAGE_SHIFT;
IOD(("iounit_release %08lx-%08lx\n", (long)vaddr, (long)len+vaddr));
for (len += vaddr; vaddr < len; vaddr++)
clear_bit(vaddr, iounit->bmap);
+ sg = sg_next(sg);
}
spin_unlock_irqrestore(&iounit->lock, flags);
}
diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c
index 52e907af9d29..4b934270f05e 100644
--- a/arch/sparc/mm/iommu.c
+++ b/arch/sparc/mm/iommu.c
@@ -12,8 +12,8 @@
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/highmem.h> /* pte_offset_map => kmap_atomic */
+#include <linux/scatterlist.h>
-#include <asm/scatterlist.h>
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
#include <asm/sbus.h>
@@ -238,9 +238,9 @@ static void iommu_get_scsi_sgl_noflush(struct scatterlist *sg, int sz, struct sb
while (sz != 0) {
--sz;
n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT;
- sg->dvma_address = iommu_get_one(sg->page, n, sbus) + sg->offset;
+ sg->dvma_address = iommu_get_one(sg_page(sg), n, sbus) + sg->offset;
sg->dvma_length = (__u32) sg->length;
- sg++;
+ sg = sg_next(sg);
}
}
@@ -252,9 +252,9 @@ static void iommu_get_scsi_sgl_gflush(struct scatterlist *sg, int sz, struct sbu
while (sz != 0) {
--sz;
n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT;
- sg->dvma_address = iommu_get_one(sg->page, n, sbus) + sg->offset;
+ sg->dvma_address = iommu_get_one(sg_page(sg), n, sbus) + sg->offset;
sg->dvma_length = (__u32) sg->length;
- sg++;
+ sg = sg_next(sg);
}
}
@@ -273,7 +273,7 @@ static void iommu_get_scsi_sgl_pflush(struct scatterlist *sg, int sz, struct sbu
* XXX Is this a good assumption?
* XXX What if someone else unmaps it here and races us?
*/
- if ((page = (unsigned long) page_address(sg->page)) != 0) {
+ if ((page = (unsigned long) page_address(sg_page(sg))) != 0) {
for (i = 0; i < n; i++) {
if (page != oldpage) { /* Already flushed? */
flush_page_for_dma(page);
@@ -283,9 +283,9 @@ static void iommu_get_scsi_sgl_pflush(struct scatterlist *sg, int sz, struct sbu
}
}
- sg->dvma_address = iommu_get_one(sg->page, n, sbus) + sg->offset;
+ sg->dvma_address = iommu_get_one(sg_page(sg), n, sbus) + sg->offset;
sg->dvma_length = (__u32) sg->length;
- sg++;
+ sg = sg_next(sg);
}
}
@@ -325,7 +325,7 @@ static void iommu_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_b
n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT;
iommu_release_one(sg->dvma_address & PAGE_MASK, n, sbus);
sg->dvma_address = 0x21212121;
- sg++;
+ sg = sg_next(sg);
}
}
diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c
index 005a3e72d4f2..0729305f2f59 100644
--- a/arch/sparc/mm/sun4c.c
+++ b/arch/sparc/mm/sun4c.c
@@ -1,7 +1,6 @@
-/* $Id: sun4c.c,v 1.212 2001/12/21 04:56:15 davem Exp $
- * sun4c.c: Doing in software what should be done in hardware.
+/* sun4c.c: Doing in software what should be done in hardware.
*
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
* Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
* Copyright (C) 1996 Andrew Tridgell (Andrew.Tridgell@anu.edu.au)
* Copyright (C) 1997-2000 Anton Blanchard (anton@samba.org)
@@ -17,8 +16,8 @@
#include <linux/highmem.h>
#include <linux/fs.h>
#include <linux/seq_file.h>
+#include <linux/scatterlist.h>
-#include <asm/scatterlist.h>
#include <asm/page.h>
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
@@ -719,7 +718,7 @@ static void add_ring(struct sun4c_mmu_ring *ring,
ring->num_entries++;
}
-static __inline__ void add_lru(struct sun4c_mmu_entry *entry)
+static inline void add_lru(struct sun4c_mmu_entry *entry)
{
struct sun4c_mmu_ring *ring = &sun4c_ulru_ring;
struct sun4c_mmu_entry *head = &ring->ringhd;
@@ -746,7 +745,7 @@ static void add_ring_ordered(struct sun4c_mmu_ring *ring,
add_lru(entry);
}
-static __inline__ void remove_ring(struct sun4c_mmu_ring *ring,
+static inline void remove_ring(struct sun4c_mmu_ring *ring,
struct sun4c_mmu_entry *entry)
{
struct sun4c_mmu_entry *next = entry->next;
@@ -1228,8 +1227,9 @@ static void sun4c_get_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *
{
while (sz != 0) {
--sz;
- sg[sz].dvma_address = (__u32)sun4c_lockarea(page_address(sg[sz].page) + sg[sz].offset, sg[sz].length);
- sg[sz].dvma_length = sg[sz].length;
+ sg->dvma_address = (__u32)sun4c_lockarea(sg_virt(sg), sg->length);
+ sg->dvma_length = sg->length;
+ sg = sg_next(sg);
}
}
@@ -1244,7 +1244,8 @@ static void sun4c_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_b
{
while (sz != 0) {
--sz;
- sun4c_unlockarea((char *)sg[sz].dvma_address, sg[sz].length);
+ sun4c_unlockarea((char *)sg->dvma_address, sg->length);
+ sg = sg_next(sg);
}
}
@@ -1834,7 +1835,7 @@ static unsigned long sun4c_pte_to_pgoff(pte_t pte)
}
-static __inline__ unsigned long sun4c_pmd_page_v(pmd_t pmd)
+static inline unsigned long sun4c_pmd_page_v(pmd_t pmd)
{
return (pmd_val(pmd) & PAGE_MASK);
}
@@ -1920,7 +1921,7 @@ static void sun4c_free_pgd_fast(pgd_t *pgd)
}
-static __inline__ pte_t *
+static inline pte_t *
sun4c_pte_alloc_one_fast(struct mm_struct *mm, unsigned long address)
{
unsigned long *ret;
@@ -1954,7 +1955,7 @@ static struct page *sun4c_pte_alloc_one(struct mm_struct *mm, unsigned long addr
return virt_to_page(pte);
}
-static __inline__ void sun4c_free_pte_fast(pte_t *pte)
+static inline void sun4c_free_pte_fast(pte_t *pte)
{
*(unsigned long *)pte = (unsigned long) pte_quicklist;
pte_quicklist = (unsigned long *) pte;
diff --git a/arch/sparc/oprofile/Kconfig b/arch/sparc/oprofile/Kconfig
deleted file mode 100644
index d8a84088471a..000000000000
--- a/arch/sparc/oprofile/Kconfig
+++ /dev/null
@@ -1,17 +0,0 @@
-config PROFILING
- bool "Profiling support (EXPERIMENTAL)"
- help
- Say Y here to enable the extended profiling support mechanisms used
- by profilers such as OProfile.
-
-
-config OPROFILE
- tristate "OProfile system profiling (EXPERIMENTAL)"
- depends on PROFILING
- help
- OProfile is a profiling system capable of profiling the
- whole system, include the kernel, kernel modules, libraries,
- and applications.
-
- If unsure, say N.
-
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index 33dabf588bdd..10b212a1f9f5 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -72,6 +72,10 @@ config ARCH_NO_VIRT_TO_BUS
config OF
def_bool y
+config GENERIC_HARDIRQS_NO__DO_IRQ
+ bool
+ def_bool y
+
choice
prompt "Kernel page size"
default SPARC64_PAGE_SIZE_8KB
@@ -240,10 +244,10 @@ config ARCH_SELECT_MEMORY_MODEL
config ARCH_SPARSEMEM_ENABLE
def_bool y
+ select SPARSEMEM_VMEMMAP_ENABLE
config ARCH_SPARSEMEM_DEFAULT
def_bool y
- select SPARSEMEM_STATIC
source "mm/Kconfig"
@@ -404,7 +408,7 @@ config SUNOS_EMUL
config SOLARIS_EMUL
tristate "Solaris binary emulation (EXPERIMENTAL)"
- depends on SPARC32_COMPAT && EXPERIMENTAL
+ depends on SPARC32_COMPAT && NET && EXPERIMENTAL
help
This is experimental code which will enable you to run (many)
Solaris binaries on your SPARC Linux machine.
@@ -456,25 +460,9 @@ source "drivers/Kconfig"
source "drivers/sbus/char/Kconfig"
-source "drivers/fc4/Kconfig"
-
source "fs/Kconfig"
-menu "Instrumentation Support"
- depends on EXPERIMENTAL
-
-source "arch/sparc64/oprofile/Kconfig"
-
-config KPROBES
- bool "Kprobes (EXPERIMENTAL)"
- depends on KALLSYMS && EXPERIMENTAL && MODULES
- help
- Kprobes allows you to trap at almost any kernel address and
- execute a callback function. register_kprobe() establishes
- a probepoint and specifies the callback. Kprobes is useful
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-endmenu
+source "kernel/Kconfig.instrumentation"
source "arch/sparc64/Kconfig.debug"
diff --git a/arch/sparc64/Makefile b/arch/sparc64/Makefile
index cad10c5b83d3..01159cb5f16d 100644
--- a/arch/sparc64/Makefile
+++ b/arch/sparc64/Makefile
@@ -18,8 +18,6 @@ NEW_GCC := $(call cc-option-yn, -m64 -mcmodel=medlow)
NEW_GAS := $(shell if $(LD) -V 2>&1 | grep 'elf64_sparc' > /dev/null; then echo y; else echo n; fi)
UNDECLARED_REGS := $(shell if $(CC) -c -x assembler /dev/null -Wa,--help | grep undeclared-regs > /dev/null; then echo y; else echo n; fi; )
-export NEW_GCC
-
ifneq ($(NEW_GAS),y)
AS = sparc64-linux-as
LD = sparc64-linux-ld
@@ -39,17 +37,17 @@ AS := $(AS) --undeclared-regs
endif
ifneq ($(NEW_GCC),y)
- CFLAGS := $(CFLAGS) -pipe -mno-fpu -mtune=ultrasparc -mmedlow \
+ KBUILD_CFLAGS += -pipe -mno-fpu -mtune=ultrasparc -mmedlow \
-ffixed-g4 -ffixed-g5 -fcall-used-g7 -Wno-sign-compare
else
- CFLAGS := $(CFLAGS) -m64 -pipe -mno-fpu -mcpu=ultrasparc -mcmodel=medlow \
+ KBUILD_CFLAGS += -m64 -pipe -mno-fpu -mcpu=ultrasparc -mcmodel=medlow \
-ffixed-g4 -ffixed-g5 -fcall-used-g7 -Wno-sign-compare \
$(CC_UNDECL)
- AFLAGS += -m64 -mcpu=ultrasparc $(CC_UNDECL)
+ KBUILD_AFLAGS += -m64 -mcpu=ultrasparc $(CC_UNDECL)
endif
ifeq ($(CONFIG_MCOUNT),y)
- CFLAGS := $(CFLAGS) -pg
+ KBUILD_CFLAGS += -pg
endif
head-y := arch/sparc64/kernel/head.o arch/sparc64/kernel/init_task.o
@@ -58,8 +56,6 @@ core-y += arch/sparc64/kernel/ arch/sparc64/mm/
core-$(CONFIG_SOLARIS_EMUL) += arch/sparc64/solaris/
core-y += arch/sparc64/math-emu/
libs-y += arch/sparc64/prom/ arch/sparc64/lib/
-
-# FIXME: is drivers- right?
drivers-$(CONFIG_OPROFILE) += arch/sparc64/oprofile/
boot := arch/sparc64/boot
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index 1aa2c4048e4b..22734ac08c8a 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.23
-# Sat Oct 13 21:53:54 2007
+# Linux kernel version: 2.6.24-rc1
+# Wed Oct 31 15:36:47 2007
#
CONFIG_SPARC=y
CONFIG_SPARC64=y
@@ -19,6 +19,7 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_AUDIT_ARCH=y
CONFIG_ARCH_NO_VIRT_TO_BUS=y
CONFIG_OF=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
CONFIG_SPARC64_PAGE_SIZE_8KB=y
# CONFIG_SPARC64_PAGE_SIZE_64KB is not set
# CONFIG_SPARC64_PAGE_SIZE_512KB is not set
@@ -49,9 +50,14 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=18
+# CONFIG_CGROUPS is not set
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_FAIR_USER_SCHED=y
+# CONFIG_FAIR_CGROUP_SCHED is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_RELAY=y
-# CONFIG_BLK_DEV_INITRD 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
@@ -113,22 +119,7 @@ CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
# CONFIG_SMP is not set
-CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_TABLE=m
-# CONFIG_CPU_FREQ_DEBUG is not set
-CONFIG_CPU_FREQ_STAT=m
-CONFIG_CPU_FREQ_STAT_DETAILS=y
-CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
-# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
-# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
-# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
-CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
-CONFIG_CPU_FREQ_GOV_POWERSAVE=m
-CONFIG_CPU_FREQ_GOV_USERSPACE=m
-CONFIG_CPU_FREQ_GOV_ONDEMAND=m
-CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
-CONFIG_US3_FREQ=m
-CONFIG_US2E_FREQ=m
+# CONFIG_CPU_FREQ is not set
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_HWEIGHT=y
@@ -145,7 +136,10 @@ CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_SPARSEMEM_MANUAL=y
CONFIG_SPARSEMEM=y
CONFIG_HAVE_MEMORY_PRESENT=y
-CONFIG_SPARSEMEM_STATIC=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPARSEMEM_EXTREME=y
+CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
+CONFIG_SPARSEMEM_VMEMMAP=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_RESOURCES_64BIT=y
CONFIG_ZONE_DMA_FLAG=0
@@ -154,7 +148,7 @@ CONFIG_SBUS=y
CONFIG_SBUSCHAR=y
CONFIG_SUN_AUXIO=y
CONFIG_SUN_IO=y
-# CONFIG_SUN_LDOMS is not set
+CONFIG_SUN_LDOMS=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCI_SYSCALL=y
@@ -275,10 +269,6 @@ CONFIG_VLAN_8021Q=m
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
# CONFIG_NET_SCHED is not set
#
@@ -335,6 +325,7 @@ CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
CONFIG_CDROM_PKTCDVD_WCACHE=y
CONFIG_ATA_OVER_ETH=m
+CONFIG_SUNVDC=m
CONFIG_MISC_DEVICES=y
# CONFIG_PHANTOM is not set
# CONFIG_EEPROM_93CX6 is not set
@@ -372,8 +363,6 @@ CONFIG_IDEPCI_PCIBUS_ORDER=y
# CONFIG_BLK_DEV_GENERIC is not set
# CONFIG_BLK_DEV_OPTI621 is not set
CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_ONLYDISK=y
# CONFIG_BLK_DEV_AEC62XX is not set
CONFIG_BLK_DEV_ALI15X3=y
# CONFIG_WDC_ALI15X3 is not set
@@ -401,6 +390,7 @@ CONFIG_BLK_DEV_ALI15X3=y
# CONFIG_BLK_DEV_TC86C001 is not set
# CONFIG_IDE_ARM is not set
CONFIG_BLK_DEV_IDEDMA=y
+CONFIG_IDE_ARCH_OBSOLETE_INIT=y
# CONFIG_BLK_DEV_HD is not set
#
@@ -438,11 +428,12 @@ CONFIG_SCSI_WAIT_SCAN=m
#
CONFIG_SCSI_SPI_ATTRS=y
CONFIG_SCSI_FC_ATTRS=y
-CONFIG_SCSI_ISCSI_ATTRS=m
+# CONFIG_SCSI_ISCSI_ATTRS is not set
# CONFIG_SCSI_SAS_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=m
+# CONFIG_ISCSI_TCP 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
@@ -492,14 +483,8 @@ CONFIG_DM_MIRROR=m
CONFIG_DM_ZERO=m
# CONFIG_DM_MULTIPATH is not set
# CONFIG_DM_DELAY is not set
-
-#
-# Fusion MPT device support
-#
+# CONFIG_DM_UEVENT is not set
# CONFIG_FUSION is not set
-# CONFIG_FUSION_SPI is not set
-# CONFIG_FUSION_FC is not set
-# CONFIG_FUSION_SAS is not set
#
# IEEE 1394 (FireWire) support
@@ -509,7 +494,7 @@ CONFIG_DM_ZERO=m
# CONFIG_I2O is not set
CONFIG_NETDEVICES=y
# CONFIG_NETDEVICES_MULTIQUEUE is not set
-CONFIG_DUMMY=m
+# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
# CONFIG_EQUALIZER is not set
@@ -526,6 +511,7 @@ CONFIG_MII=m
# CONFIG_SUNQE is not set
# CONFIG_SUNGEM is not set
CONFIG_CASSINI=m
+CONFIG_SUNVNET=m
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
@@ -580,7 +566,7 @@ CONFIG_NETDEV_10000=y
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
-# CONFIG_NIU is not set
+CONFIG_NIU=m
# CONFIG_MLX4_CORE is not set
# CONFIG_TEHUTI is not set
# CONFIG_TR is not set
@@ -638,7 +624,6 @@ 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_TSDEV is not set
CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_EVBUG is not set
@@ -706,7 +691,8 @@ CONFIG_SERIAL_SUNCORE=y
# CONFIG_SERIAL_SUNZILOG is not set
CONFIG_SERIAL_SUNSU=y
CONFIG_SERIAL_SUNSU_CONSOLE=y
-CONFIG_SERIAL_SUNSAB=m
+CONFIG_SERIAL_SUNSAB=y
+CONFIG_SERIAL_SUNSAB_CONSOLE=y
CONFIG_SERIAL_SUNHV=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
@@ -714,11 +700,9 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
# CONFIG_LEGACY_PTYS is not set
# CONFIG_IPMI_HANDLER is not set
-# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
-# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
# CONFIG_TCG_TPM is not set
CONFIG_DEVPORT=y
@@ -786,8 +770,6 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
-# CONFIG_SENSORS_ABITUGURU3 is not set
# CONFIG_SENSORS_AD7418 is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
@@ -795,12 +777,12 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
-# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_FSCPOS 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
@@ -836,6 +818,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_WATCHDOG is not set
#
# Sonics Silicon Backplane
@@ -858,12 +841,7 @@ CONFIG_SSB_POSSIBLE=y
#
# Graphics support
#
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Display device support
-#
-# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_DRM is not set
# CONFIG_VGASTATE is not set
# CONFIG_VIDEO_OUTPUT_CONTROL is not set
CONFIG_FB=y
@@ -872,6 +850,7 @@ CONFIG_FB_DDC=y
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
# CONFIG_FB_SYS_FILLRECT is not set
# CONFIG_FB_SYS_COPYAREA is not set
# CONFIG_FB_SYS_IMAGEBLIT is not set
@@ -890,9 +869,18 @@ CONFIG_FB_TILEBLITTING=y
# CONFIG_FB_PM2 is not set
# CONFIG_FB_ASILIANT is not set
# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_SBUS is not set
-# CONFIG_FB_XVR500 is not set
-# CONFIG_FB_XVR2500 is not set
+# CONFIG_FB_UVESA is not set
+CONFIG_FB_SBUS=y
+# CONFIG_FB_BW2 is not set
+# CONFIG_FB_CG3 is not set
+CONFIG_FB_CG6=y
+CONFIG_FB_FFB=y
+# CONFIG_FB_TCX is not set
+# CONFIG_FB_CG14 is not set
+# CONFIG_FB_P9100 is not set
+# CONFIG_FB_LEO is not set
+CONFIG_FB_XVR500=y
+CONFIG_FB_XVR2500=y
# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_NVIDIA is not set
# CONFIG_FB_RIVA is not set
@@ -902,7 +890,11 @@ CONFIG_FB_RADEON_I2C=y
# CONFIG_FB_RADEON_BACKLIGHT is not set
# CONFIG_FB_RADEON_DEBUG is not set
# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_ATY is not set
+CONFIG_FB_ATY=y
+CONFIG_FB_ATY_CT=y
+# CONFIG_FB_ATY_GENERIC_LCD is not set
+CONFIG_FB_ATY_GX=y
+# CONFIG_FB_ATY_BACKLIGHT is not set
# CONFIG_FB_S3 is not set
# CONFIG_FB_SAVAGE is not set
# CONFIG_FB_SIS is not set
@@ -915,6 +907,12 @@ CONFIG_FB_RADEON_I2C=y
# CONFIG_FB_ARK is not set
# CONFIG_FB_PM3 is not set
# CONFIG_FB_VIRTUAL is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
#
# Console display driver support
@@ -1066,6 +1064,7 @@ CONFIG_AC97_BUS=m
CONFIG_HID_SUPPORT=y
CONFIG_HID=y
# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
#
# USB Input Devices
@@ -1187,19 +1186,6 @@ CONFIG_USB_STORAGE=m
# CONFIG_RTC_CLASS is not set
#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
# Userspace I/O
#
# CONFIG_UIO is not set
@@ -1207,7 +1193,7 @@ CONFIG_USB_STORAGE=m
#
# Misc Linux/SPARC drivers
#
-CONFIG_SUN_OPENPROMIO=m
+CONFIG_SUN_OPENPROMIO=y
# CONFIG_OBP_FLASH is not set
# CONFIG_SUN_BPP is not set
# CONFIG_BBC_I2C is not set
@@ -1215,11 +1201,6 @@ CONFIG_SUN_OPENPROMIO=m
# CONFIG_DISPLAY7SEG is not set
#
-# Fibre Channel support
-#
-# CONFIG_FC4 is not set
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -1275,7 +1256,6 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
-CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -1295,10 +1275,7 @@ CONFIG_RAMFS=y
# CONFIG_QNX4FS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
+CONFIG_NETWORK_FILESYSTEMS=y
# CONFIG_NFS_FS is not set
# CONFIG_NFSD is not set
# CONFIG_SMB_FS is not set
@@ -1313,10 +1290,6 @@ CONFIG_RAMFS=y
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
CONFIG_SUN_PARTITION=y
-
-#
-# Native Language Support
-#
CONFIG_NLS=m
CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_CODEPAGE_437 is not set
@@ -1357,24 +1330,19 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_KOI8_R is not set
# CONFIG_NLS_KOI8_U is not set
# CONFIG_NLS_UTF8 is not set
-
-#
-# Distributed Lock Manager
-#
# CONFIG_DLM is not set
-
-#
-# Instrumentation Support
-#
+CONFIG_INSTRUMENTATION=y
CONFIG_PROFILING=y
CONFIG_OPROFILE=m
CONFIG_KPROBES=y
+# CONFIG_MARKERS is not set
#
# Kernel hacking
#
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_PRINTK_TIME=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
CONFIG_ENABLE_MUST_CHECK=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
@@ -1401,10 +1369,13 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
CONFIG_FORCED_INLINING=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_LKDTM is not set
# CONFIG_FAULT_INJECTION is not set
+# CONFIG_SAMPLES is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_DCFLUSH is not set
# CONFIG_STACK_DEBUG is not set
@@ -1417,6 +1388,7 @@ CONFIG_FORCED_INLINING=y
CONFIG_KEYS=y
# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_XOR_BLOCKS=m
CONFIG_ASYNC_CORE=m
CONFIG_ASYNC_MEMCPY=m
diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile
index 112c46e66578..ef50d217432f 100644
--- a/arch/sparc64/kernel/Makefile
+++ b/arch/sparc64/kernel/Makefile
@@ -39,12 +39,3 @@ else
obj-y += sys_sunos32.o sunos_ioctl32.o
endif
endif
-
-ifneq ($(NEW_GCC),y)
- CMODEL_CFLAG := -mmedlow
-else
- CMODEL_CFLAG := -m64 -mcmodel=medlow
-endif
-
-head.o: head.S ttable.S itlb_miss.S dtlb_miss.S ktlb.S tsb.S \
- etrap.S rtrap.S winfixup.S entry.S
diff --git a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c
index d208cc7804f2..92c1b36a2e16 100644
--- a/arch/sparc64/kernel/binfmt_aout32.c
+++ b/arch/sparc64/kernel/binfmt_aout32.c
@@ -35,11 +35,14 @@
static int load_aout32_binary(struct linux_binprm *, struct pt_regs * regs);
static int load_aout32_library(struct file*);
-static int aout32_core_dump(long signr, struct pt_regs * regs, struct file *file);
+static int aout32_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit);
static struct linux_binfmt aout32_format = {
- NULL, THIS_MODULE, load_aout32_binary, load_aout32_library, aout32_core_dump,
- PAGE_SIZE
+ .module = THIS_MODULE,
+ .load_binary = load_aout32_binary,
+ .load_shlib = load_aout32_library,
+ .core_dump = aout32_core_dump,
+ .min_coredump = PAGE_SIZE,
};
static void set_brk(unsigned long start, unsigned long end)
@@ -83,7 +86,7 @@ if (file->f_op->llseek) { \
* dumping of the process results in another error..
*/
-static int aout32_core_dump(long signr, struct pt_regs *regs, struct file *file)
+static int aout32_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit)
{
mm_segment_t fs;
int has_dumped = 0;
@@ -102,13 +105,11 @@ static int aout32_core_dump(long signr, struct pt_regs *regs, struct file *file)
/* If the size of the dump file exceeds the rlimit, then see what would happen
if we wrote the stack, but not the data area. */
- if ((dump.u_dsize+dump.u_ssize) >
- current->signal->rlim[RLIMIT_CORE].rlim_cur)
+ if (dump.u_dsize + dump.u_ssize > limit)
dump.u_dsize = 0;
/* Make sure we have enough room to write the stack and data areas. */
- if ((dump.u_ssize) >
- current->signal->rlim[RLIMIT_CORE].rlim_cur)
+ if (dump.u_ssize > limit)
dump.u_ssize = 0;
/* make sure we actually have a data and stack area to dump */
diff --git a/arch/sparc64/kernel/binfmt_elf32.c b/arch/sparc64/kernel/binfmt_elf32.c
index 9ad84ff10a17..1587a29a4b0e 100644
--- a/arch/sparc64/kernel/binfmt_elf32.c
+++ b/arch/sparc64/kernel/binfmt_elf32.c
@@ -1,7 +1,7 @@
/*
* binfmt_elf32.c: Support 32-bit Sparc ELF binaries on Ultra.
*
- * Copyright (C) 1995, 1996, 1997, 1998 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1995, 1996, 1997, 1998 David S. Miller (davem@davemloft.net)
* Copyright (C) 1995, 1996, 1997, 1998 Jakub Jelinek (jj@ultra.linux.cz)
*/
@@ -133,7 +133,7 @@ struct elf_prpsinfo32
#undef cputime_to_timeval
#define cputime_to_timeval cputime_to_compat_timeval
-static __inline__ void
+static inline void
cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value)
{
unsigned long jiffies = cputime_to_jiffies(cputime);
diff --git a/arch/sparc64/kernel/central.c b/arch/sparc64/kernel/central.c
index 8230099f0d8a..b61b8dfb09cf 100644
--- a/arch/sparc64/kernel/central.c
+++ b/arch/sparc64/kernel/central.c
@@ -1,7 +1,6 @@
-/* $Id: central.c,v 1.15 2001/12/19 00:29:51 davem Exp $
- * central.c: Central FHC driver for Sunfire/Starfire/Wildfire.
+/* central.c: Central FHC driver for Sunfire/Starfire/Wildfire.
*
- * Copyright (C) 1997, 1999 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1997, 1999 David S. Miller (davem@davemloft.net)
*/
#include <linux/kernel.h>
@@ -385,7 +384,7 @@ void __init central_probe(void)
init_all_fhc_hw();
}
-static __inline__ void fhc_ledblink(struct linux_fhc *fhc, int on)
+static inline void fhc_ledblink(struct linux_fhc *fhc, int on)
{
u32 tmp;
@@ -402,7 +401,7 @@ static __inline__ void fhc_ledblink(struct linux_fhc *fhc, int on)
upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
}
-static __inline__ void central_ledblink(struct linux_central *central, int on)
+static inline void central_ledblink(struct linux_central *central, int on)
{
u8 tmp;
diff --git a/arch/sparc64/kernel/ds.c b/arch/sparc64/kernel/ds.c
index 9f472a79d37e..eeb5a2fc788d 100644
--- a/arch/sparc64/kernel/ds.c
+++ b/arch/sparc64/kernel/ds.c
@@ -6,7 +6,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
-#include <linux/module.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/sched.h>
diff --git a/arch/sparc64/kernel/iommu.c b/arch/sparc64/kernel/iommu.c
index b35a62167e9c..070a4846c0cb 100644
--- a/arch/sparc64/kernel/iommu.c
+++ b/arch/sparc64/kernel/iommu.c
@@ -472,15 +472,13 @@ static void dma_4u_unmap_single(struct device *dev, dma_addr_t bus_addr,
spin_unlock_irqrestore(&iommu->lock, flags);
}
-#define SG_ENT_PHYS_ADDRESS(SG) \
- (__pa(page_address((SG)->page)) + (SG)->offset)
+#define SG_ENT_PHYS_ADDRESS(SG) (__pa(sg_virt((SG))))
-static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg,
- int nused, int nelems,
- unsigned long iopte_protection)
+static void fill_sg(iopte_t *iopte, struct scatterlist *sg,
+ int nused, int nelems,
+ unsigned long iopte_protection)
{
struct scatterlist *dma_sg = sg;
- struct scatterlist *sg_end = sg + nelems;
int i;
for (i = 0; i < nused; i++) {
@@ -515,7 +513,8 @@ static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg,
len -= (IO_PAGE_SIZE - (tmp & (IO_PAGE_SIZE - 1UL)));
break;
}
- sg++;
+ sg = sg_next(sg);
+ nelems--;
}
pteval = iopte_protection | (pteval & IOPTE_PAGE);
@@ -528,24 +527,26 @@ static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg,
}
pteval = (pteval & IOPTE_PAGE) + len;
- sg++;
+ sg = sg_next(sg);
+ nelems--;
/* Skip over any tail mappings we've fully mapped,
* adjusting pteval along the way. Stop when we
* detect a page crossing event.
*/
- while (sg < sg_end &&
+ while (nelems &&
(pteval << (64 - IO_PAGE_SHIFT)) != 0UL &&
(pteval == SG_ENT_PHYS_ADDRESS(sg)) &&
((pteval ^
(SG_ENT_PHYS_ADDRESS(sg) + sg->length - 1UL)) >> IO_PAGE_SHIFT) == 0UL) {
pteval += sg->length;
- sg++;
+ sg = sg_next(sg);
+ nelems--;
}
if ((pteval << (64 - IO_PAGE_SHIFT)) == 0UL)
pteval = ~0UL;
} while (dma_npages != 0);
- dma_sg++;
+ dma_sg = sg_next(dma_sg);
}
}
@@ -563,9 +564,7 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
/* Fast path single entry scatterlists. */
if (nelems == 1) {
sglist->dma_address =
- dma_4u_map_single(dev,
- (page_address(sglist->page) +
- sglist->offset),
+ dma_4u_map_single(dev, sg_virt(sglist),
sglist->length, direction);
if (unlikely(sglist->dma_address == DMA_ERROR_CODE))
return 0;
@@ -606,7 +605,7 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
sgtmp = sglist;
while (used && sgtmp->dma_length) {
sgtmp->dma_address += dma_base;
- sgtmp++;
+ sgtmp = sg_next(sgtmp);
used--;
}
used = nelems - used;
@@ -642,6 +641,7 @@ static void dma_4u_unmap_sg(struct device *dev, struct scatterlist *sglist,
struct strbuf *strbuf;
iopte_t *base;
unsigned long flags, ctx, i, npages;
+ struct scatterlist *sg, *sgprv;
u32 bus_addr;
if (unlikely(direction == DMA_NONE)) {
@@ -654,11 +654,14 @@ static void dma_4u_unmap_sg(struct device *dev, struct scatterlist *sglist,
bus_addr = sglist->dma_address & IO_PAGE_MASK;
- for (i = 1; i < nelems; i++)
- if (sglist[i].dma_length == 0)
+ sgprv = NULL;
+ for_each_sg(sglist, sg, nelems, i) {
+ if (sg->dma_length == 0)
break;
- i--;
- npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length) -
+ sgprv = sg;
+ }
+
+ npages = (IO_PAGE_ALIGN(sgprv->dma_address + sgprv->dma_length) -
bus_addr) >> IO_PAGE_SHIFT;
base = iommu->page_table +
@@ -730,6 +733,7 @@ static void dma_4u_sync_sg_for_cpu(struct device *dev,
struct iommu *iommu;
struct strbuf *strbuf;
unsigned long flags, ctx, npages, i;
+ struct scatterlist *sg, *sgprv;
u32 bus_addr;
iommu = dev->archdata.iommu;
@@ -753,11 +757,14 @@ static void dma_4u_sync_sg_for_cpu(struct device *dev,
/* Step 2: Kick data out of streaming buffers. */
bus_addr = sglist[0].dma_address & IO_PAGE_MASK;
- for(i = 1; i < nelems; i++)
- if (!sglist[i].dma_length)
+ sgprv = NULL;
+ for_each_sg(sglist, sg, nelems, i) {
+ if (sg->dma_length == 0)
break;
- i--;
- npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length)
+ sgprv = sg;
+ }
+
+ npages = (IO_PAGE_ALIGN(sgprv->dma_address + sgprv->dma_length)
- bus_addr) >> IO_PAGE_SHIFT;
strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
diff --git a/arch/sparc64/kernel/iommu_common.c b/arch/sparc64/kernel/iommu_common.c
index 12c93a3eee26..efd5dff85f60 100644
--- a/arch/sparc64/kernel/iommu_common.c
+++ b/arch/sparc64/kernel/iommu_common.c
@@ -12,18 +12,22 @@
*/
#ifdef VERIFY_SG
-static int verify_lengths(struct scatterlist *sg, int nents, int npages)
+static int verify_lengths(struct scatterlist *sglist, int nents, int npages)
{
int sg_len, dma_len;
int i, pgcount;
+ struct scatterlist *sg;
sg_len = 0;
- for (i = 0; i < nents; i++)
- sg_len += sg[i].length;
+ for_each_sg(sglist, sg, nents, i)
+ sg_len += sg->length;
dma_len = 0;
- for (i = 0; i < nents && sg[i].dma_length; i++)
- dma_len += sg[i].dma_length;
+ for_each_sg(sglist, sg, nents, i) {
+ if (!sg->dma_length)
+ break;
+ dma_len += sg->dma_length;
+ }
if (sg_len != dma_len) {
printk("verify_lengths: Error, different, sg[%d] dma[%d]\n",
@@ -32,13 +36,16 @@ static int verify_lengths(struct scatterlist *sg, int nents, int npages)
}
pgcount = 0;
- for (i = 0; i < nents && sg[i].dma_length; i++) {
+ for_each_sg(sglist, sg, nents, i) {
unsigned long start, end;
- start = sg[i].dma_address;
+ if (!sg->dma_length)
+ break;
+
+ start = sg->dma_address;
start = start & IO_PAGE_MASK;
- end = sg[i].dma_address + sg[i].dma_length;
+ end = sg->dma_address + sg->dma_length;
end = (end + (IO_PAGE_SIZE - 1)) & IO_PAGE_MASK;
pgcount += ((end - start) >> IO_PAGE_SHIFT);
@@ -66,7 +73,7 @@ static int verify_one_map(struct scatterlist *dma_sg, struct scatterlist **__sg,
daddr = dma_sg->dma_address;
sglen = sg->length;
- sgaddr = (unsigned long) (page_address(sg->page) + sg->offset);
+ sgaddr = (unsigned long) sg_virt(sg);
while (dlen > 0) {
unsigned long paddr;
@@ -113,10 +120,10 @@ static int verify_one_map(struct scatterlist *dma_sg, struct scatterlist **__sg,
if (dlen > 0 && ((daddr & ~IO_PAGE_MASK) == 0))
iopte++;
- sg++;
+ sg = sg_next(sg);
if (--nents <= 0)
break;
- sgaddr = (unsigned long) (page_address(sg->page) + sg->offset);
+ sgaddr = (unsigned long) sg_virt(sg);
sglen = sg->length;
}
if (dlen < 0) {
@@ -147,7 +154,7 @@ static int verify_maps(struct scatterlist *sg, int nents, iopte_t *iopte)
nents = verify_one_map(dma_sg, &sg, nents, &iopte);
if (nents <= 0)
break;
- dma_sg++;
+ dma_sg = sg_next(dma_sg);
if (dma_sg->dma_length == 0)
break;
}
@@ -169,22 +176,24 @@ static int verify_maps(struct scatterlist *sg, int nents, iopte_t *iopte)
return 0;
}
-void verify_sglist(struct scatterlist *sg, int nents, iopte_t *iopte, int npages)
+void verify_sglist(struct scatterlist *sglist, int nents, iopte_t *iopte, int npages)
{
- if (verify_lengths(sg, nents, npages) < 0 ||
- verify_maps(sg, nents, iopte) < 0) {
+ struct scatterlist *sg;
+
+ if (verify_lengths(sglist, nents, npages) < 0 ||
+ verify_maps(sglist, nents, iopte) < 0) {
int i;
printk("verify_sglist: Crap, messed up mappings, dumping, iodma at ");
- printk("%016lx.\n", sg->dma_address & IO_PAGE_MASK);
+ printk("%016lx.\n", sglist->dma_address & IO_PAGE_MASK);
- for (i = 0; i < nents; i++) {
+ for_each_sg(sglist, sg, nents, i) {
printk("sg(%d): page_addr(%p) off(%x) length(%x) "
- "dma_address[%016lx] dma_length[%016lx]\n",
+ "dma_address[%016x] dma_length[%016x]\n",
i,
- page_address(sg[i].page), sg[i].offset,
- sg[i].length,
- sg[i].dma_address, sg[i].dma_length);
+ page_address(sg_page(sg)), sg->offset,
+ sg->length,
+ sg->dma_address, sg->dma_length);
}
}
@@ -198,19 +207,18 @@ unsigned long prepare_sg(struct scatterlist *sg, int nents)
unsigned long prev;
u32 dent_addr, dent_len;
- prev = (unsigned long) (page_address(sg->page) + sg->offset);
+ prev = (unsigned long) sg_virt(sg);
prev += (unsigned long) (dent_len = sg->length);
- dent_addr = (u32) ((unsigned long)(page_address(sg->page) + sg->offset)
- & (IO_PAGE_SIZE - 1UL));
+ dent_addr = (u32) ((unsigned long)(sg_virt(sg)) & (IO_PAGE_SIZE - 1UL));
while (--nents) {
unsigned long addr;
- sg++;
- addr = (unsigned long) (page_address(sg->page) + sg->offset);
+ sg = sg_next(sg);
+ addr = (unsigned long) sg_virt(sg);
if (! VCONTIG(prev, addr)) {
dma_sg->dma_address = dent_addr;
dma_sg->dma_length = dent_len;
- dma_sg++;
+ dma_sg = sg_next(dma_sg);
dent_addr = ((dent_addr +
dent_len +
@@ -225,6 +233,11 @@ unsigned long prepare_sg(struct scatterlist *sg, int nents)
dma_sg->dma_address = dent_addr;
dma_sg->dma_length = dent_len;
+ if (dma_sg != sg) {
+ dma_sg = sg_next(dma_sg);
+ dma_sg->dma_length = 0;
+ }
+
return ((unsigned long) dent_addr +
(unsigned long) dent_len +
(IO_PAGE_SIZE - 1UL)) >> IO_PAGE_SHIFT;
diff --git a/arch/sparc64/kernel/iommu_common.h b/arch/sparc64/kernel/iommu_common.h
index ad791014419c..75b5a5814522 100644
--- a/arch/sparc64/kernel/iommu_common.h
+++ b/arch/sparc64/kernel/iommu_common.h
@@ -8,6 +8,7 @@
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/mm.h>
+#include <linux/scatterlist.h>
#include <asm/iommu.h>
#include <asm/scatterlist.h>
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index f3922e5a89f6..30431bd24e1e 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -257,8 +257,8 @@ struct irq_handler_data {
unsigned long imap;
void (*pre_handler)(unsigned int, void *, void *);
- void *pre_handler_arg1;
- void *pre_handler_arg2;
+ void *arg1;
+ void *arg2;
};
#ifdef CONFIG_SMP
@@ -346,7 +346,7 @@ static void sun4u_irq_disable(unsigned int virt_irq)
}
}
-static void sun4u_irq_end(unsigned int virt_irq)
+static void sun4u_irq_eoi(unsigned int virt_irq)
{
struct irq_handler_data *data = get_irq_chip_data(virt_irq);
struct irq_desc *desc = irq_desc + virt_irq;
@@ -401,7 +401,7 @@ static void sun4v_irq_disable(unsigned int virt_irq)
"err(%d)\n", ino, err);
}
-static void sun4v_irq_end(unsigned int virt_irq)
+static void sun4v_irq_eoi(unsigned int virt_irq)
{
unsigned int ino = virt_irq_table[virt_irq].dev_ino;
struct irq_desc *desc = irq_desc + virt_irq;
@@ -478,7 +478,7 @@ static void sun4v_virq_disable(unsigned int virt_irq)
dev_handle, dev_ino, err);
}
-static void sun4v_virq_end(unsigned int virt_irq)
+static void sun4v_virq_eoi(unsigned int virt_irq)
{
struct irq_desc *desc = irq_desc + virt_irq;
unsigned long dev_handle, dev_ino;
@@ -498,33 +498,11 @@ static void sun4v_virq_end(unsigned int virt_irq)
dev_handle, dev_ino, err);
}
-static void run_pre_handler(unsigned int virt_irq)
-{
- struct irq_handler_data *data = get_irq_chip_data(virt_irq);
- unsigned int ino;
-
- ino = virt_irq_table[virt_irq].dev_ino;
- if (likely(data->pre_handler)) {
- data->pre_handler(ino,
- data->pre_handler_arg1,
- data->pre_handler_arg2);
- }
-}
-
static struct irq_chip sun4u_irq = {
.typename = "sun4u",
.enable = sun4u_irq_enable,
.disable = sun4u_irq_disable,
- .end = sun4u_irq_end,
- .set_affinity = sun4u_set_affinity,
-};
-
-static struct irq_chip sun4u_irq_ack = {
- .typename = "sun4u+ack",
- .enable = sun4u_irq_enable,
- .disable = sun4u_irq_disable,
- .ack = run_pre_handler,
- .end = sun4u_irq_end,
+ .eoi = sun4u_irq_eoi,
.set_affinity = sun4u_set_affinity,
};
@@ -532,7 +510,7 @@ static struct irq_chip sun4v_irq = {
.typename = "sun4v",
.enable = sun4v_irq_enable,
.disable = sun4v_irq_disable,
- .end = sun4v_irq_end,
+ .eoi = sun4v_irq_eoi,
.set_affinity = sun4v_set_affinity,
};
@@ -540,31 +518,33 @@ static struct irq_chip sun4v_virq = {
.typename = "vsun4v",
.enable = sun4v_virq_enable,
.disable = sun4v_virq_disable,
- .end = sun4v_virq_end,
+ .eoi = sun4v_virq_eoi,
.set_affinity = sun4v_virt_set_affinity,
};
+static void fastcall pre_flow_handler(unsigned int virt_irq,
+ struct irq_desc *desc)
+{
+ struct irq_handler_data *data = get_irq_chip_data(virt_irq);
+ unsigned int ino = virt_irq_table[virt_irq].dev_ino;
+
+ data->pre_handler(ino, data->arg1, data->arg2);
+
+ handle_fasteoi_irq(virt_irq, desc);
+}
+
void irq_install_pre_handler(int virt_irq,
void (*func)(unsigned int, void *, void *),
void *arg1, void *arg2)
{
struct irq_handler_data *data = get_irq_chip_data(virt_irq);
- struct irq_chip *chip = get_irq_chip(virt_irq);
-
- if (WARN_ON(chip == &sun4v_irq || chip == &sun4v_virq)) {
- printk(KERN_ERR "IRQ: Trying to install pre-handler on "
- "sun4v irq %u\n", virt_irq);
- return;
- }
+ struct irq_desc *desc = irq_desc + virt_irq;
data->pre_handler = func;
- data->pre_handler_arg1 = arg1;
- data->pre_handler_arg2 = arg2;
-
- if (chip == &sun4u_irq_ack)
- return;
+ data->arg1 = arg1;
+ data->arg2 = arg2;
- set_irq_chip(virt_irq, &sun4u_irq_ack);
+ desc->handle_irq = pre_flow_handler;
}
unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap)
@@ -582,7 +562,10 @@ unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap)
if (!virt_irq) {
virt_irq = virt_irq_alloc(0, ino);
bucket_set_virt_irq(__pa(bucket), virt_irq);
- set_irq_chip(virt_irq, &sun4u_irq);
+ set_irq_chip_and_handler_name(virt_irq,
+ &sun4u_irq,
+ handle_fasteoi_irq,
+ "IVEC");
}
data = get_irq_chip_data(virt_irq);
@@ -617,7 +600,9 @@ static unsigned int sun4v_build_common(unsigned long sysino,
if (!virt_irq) {
virt_irq = virt_irq_alloc(0, sysino);
bucket_set_virt_irq(__pa(bucket), virt_irq);
- set_irq_chip(virt_irq, chip);
+ set_irq_chip_and_handler_name(virt_irq, chip,
+ handle_fasteoi_irq,
+ "IVEC");
}
data = get_irq_chip_data(virt_irq);
@@ -665,7 +650,10 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
virt_irq = virt_irq_alloc(devhandle, devino);
bucket_set_virt_irq(__pa(bucket), virt_irq);
- set_irq_chip(virt_irq, &sun4v_virq);
+
+ set_irq_chip_and_handler_name(virt_irq, &sun4v_virq,
+ handle_fasteoi_irq,
+ "IVEC");
data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC);
if (unlikely(!data))
@@ -724,6 +712,7 @@ void handler_irq(int irq, struct pt_regs *regs)
: "memory");
while (bucket_pa) {
+ struct irq_desc *desc;
unsigned long next_pa;
unsigned int virt_irq;
@@ -731,7 +720,9 @@ void handler_irq(int irq, struct pt_regs *regs)
virt_irq = bucket_get_virt_irq(bucket_pa);
bucket_clear_chain_pa(bucket_pa);
- __do_IRQ(virt_irq);
+ desc = irq_desc + virt_irq;
+
+ desc->handle_irq(virt_irq, desc);
bucket_pa = next_pa;
}
@@ -877,7 +868,7 @@ void __cpuinit sun4v_register_mondo_queues(int this_cpu)
static void __init alloc_one_mondo(unsigned long *pa_ptr, unsigned long qmask)
{
unsigned long size = PAGE_ALIGN(qmask + 1);
- void *p = __alloc_bootmem_low(size, size, 0);
+ void *p = __alloc_bootmem(size, size, 0);
if (!p) {
prom_printf("SUN4V: Error, cannot allocate mondo queue.\n");
prom_halt();
@@ -889,7 +880,7 @@ static void __init alloc_one_mondo(unsigned long *pa_ptr, unsigned long qmask)
static void __init alloc_one_kbuf(unsigned long *pa_ptr, unsigned long qmask)
{
unsigned long size = PAGE_ALIGN(qmask + 1);
- void *p = __alloc_bootmem_low(size, size, 0);
+ void *p = __alloc_bootmem(size, size, 0);
if (!p) {
prom_printf("SUN4V: Error, cannot allocate kbuf page.\n");
@@ -906,7 +897,7 @@ static void __init init_cpu_send_mondo_info(struct trap_per_cpu *tb)
BUILD_BUG_ON((NR_CPUS * sizeof(u16)) > (PAGE_SIZE - 64));
- page = alloc_bootmem_low_pages(PAGE_SIZE);
+ page = alloc_bootmem_pages(PAGE_SIZE);
if (!page) {
prom_printf("SUN4V: Error, cannot allocate cpu mondo page.\n");
prom_halt();
@@ -953,7 +944,7 @@ void __init init_IRQ(void)
kill_prom_timer();
size = sizeof(struct ino_bucket) * NUM_IVECS;
- ivector_table = alloc_bootmem_low(size);
+ ivector_table = alloc_bootmem(size);
if (!ivector_table) {
prom_printf("Fatal error, cannot allocate ivector_table\n");
prom_halt();
diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c
index c93a15b785fa..d94f901d321e 100644
--- a/arch/sparc64/kernel/kprobes.c
+++ b/arch/sparc64/kernel/kprobes.c
@@ -42,6 +42,8 @@
DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
+struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}};
+
int __kprobes arch_prepare_kprobe(struct kprobe *p)
{
p->ainsn.insn[0] = *p->addr;
diff --git a/arch/sparc64/kernel/ktlb.S b/arch/sparc64/kernel/ktlb.S
index d4024ac0d619..964527d2ffa0 100644
--- a/arch/sparc64/kernel/ktlb.S
+++ b/arch/sparc64/kernel/ktlb.S
@@ -226,6 +226,15 @@ kvmap_dtlb_load:
ba,pt %xcc, sun4v_dtlb_load
mov %g5, %g3
+kvmap_vmemmap:
+ sub %g4, %g5, %g5
+ srlx %g5, 22, %g5
+ sethi %hi(vmemmap_table), %g1
+ sllx %g5, 3, %g5
+ or %g1, %lo(vmemmap_table), %g1
+ ba,pt %xcc, kvmap_dtlb_load
+ ldx [%g1 + %g5], %g5
+
kvmap_dtlb_nonlinear:
/* Catch kernel NULL pointer derefs. */
sethi %hi(PAGE_SIZE), %g5
@@ -233,6 +242,13 @@ kvmap_dtlb_nonlinear:
bleu,pn %xcc, kvmap_dtlb_longpath
nop
+ /* Do not use the TSB for vmemmap. */
+ mov (VMEMMAP_BASE >> 24), %g5
+ sllx %g5, 24, %g5
+ cmp %g4,%g5
+ bgeu,pn %xcc, kvmap_vmemmap
+ nop
+
KERN_TSB_LOOKUP_TL1(%g4, %g6, %g5, %g1, %g2, %g3, kvmap_dtlb_load)
kvmap_dtlb_tsbmiss:
diff --git a/arch/sparc64/kernel/ldc.c b/arch/sparc64/kernel/ldc.c
index 85a2be0b0962..217478a94128 100644
--- a/arch/sparc64/kernel/ldc.c
+++ b/arch/sparc64/kernel/ldc.c
@@ -2057,7 +2057,7 @@ static void fill_cookies(struct cookie_state *sp, unsigned long pa,
static int sg_count_one(struct scatterlist *sg)
{
- unsigned long base = page_to_pfn(sg->page) << PAGE_SHIFT;
+ unsigned long base = page_to_pfn(sg_page(sg)) << PAGE_SHIFT;
long len = sg->length;
if ((sg->offset | len) & (8UL - 1))
@@ -2121,7 +2121,7 @@ int ldc_map_sg(struct ldc_channel *lp,
state.nc = 0;
for (i = 0; i < num_sg; i++)
- fill_cookies(&state, page_to_pfn(sg[i].page) << PAGE_SHIFT,
+ fill_cookies(&state, page_to_pfn(sg_page(&sg[i])) << PAGE_SHIFT,
sg[i].offset, sg[i].length);
return state.nc;
diff --git a/arch/sparc64/kernel/module.c b/arch/sparc64/kernel/module.c
index 579871527699..158484bf5999 100644
--- a/arch/sparc64/kernel/module.c
+++ b/arch/sparc64/kernel/module.c
@@ -11,7 +11,6 @@
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/slab.h>
-#include <linux/vmalloc.h>
#include <linux/mm.h>
#include <asm/processor.h>
diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c
index 42d779866fba..fc5c0cc793b8 100644
--- a/arch/sparc64/kernel/of_device.c
+++ b/arch/sparc64/kernel/of_device.c
@@ -869,26 +869,6 @@ static int __init of_debug(char *str)
__setup("of_debug=", of_debug);
-int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus)
-{
- /* initialize common driver fields */
- if (!drv->driver.name)
- drv->driver.name = drv->name;
- if (!drv->driver.owner)
- drv->driver.owner = drv->owner;
- drv->driver.bus = bus;
-
- /* register with core */
- return driver_register(&drv->driver);
-}
-EXPORT_SYMBOL(of_register_driver);
-
-void of_unregister_driver(struct of_platform_driver *drv)
-{
- driver_unregister(&drv->driver);
-}
-EXPORT_SYMBOL(of_unregister_driver);
-
struct of_device* of_platform_device_create(struct device_node *np,
const char *bus_id,
struct device *parent,
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
index 9b808640a193..63b3ebc0c3c2 100644
--- a/arch/sparc64/kernel/pci.c
+++ b/arch/sparc64/kernel/pci.c
@@ -207,8 +207,7 @@ static struct {
{ "SUNW,sun4v-pci", sun4v_pci_init },
{ "pciex108e,80f0", fire_pci_init },
};
-#define PCI_NUM_CONTROLLER_TYPES (sizeof(pci_controller_table) / \
- sizeof(pci_controller_table[0]))
+#define PCI_NUM_CONTROLLER_TYPES ARRAY_SIZE(pci_controller_table)
static int __init pci_controller_init(const char *model_name, int namelen, struct device_node *dp)
{
diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c
index c76bfbb7da08..923e0bcc3bfd 100644
--- a/arch/sparc64/kernel/pci_common.c
+++ b/arch/sparc64/kernel/pci_common.c
@@ -396,6 +396,13 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm)
saw_mem = saw_io = 0;
pbm_ranges = of_get_property(pbm->prom_node, "ranges", &i);
+ if (!pbm_ranges) {
+ prom_printf("PCI: Fatal error, missing PBM ranges property "
+ " for %s\n",
+ pbm->name);
+ prom_halt();
+ }
+
num_pbm_ranges = i / sizeof(*pbm_ranges);
for (i = 0; i < num_pbm_ranges; i++) {
diff --git a/arch/sparc64/kernel/pci_msi.c b/arch/sparc64/kernel/pci_msi.c
index 31a165fd3e48..d6d64b44af63 100644
--- a/arch/sparc64/kernel/pci_msi.c
+++ b/arch/sparc64/kernel/pci_msi.c
@@ -28,8 +28,15 @@ static irqreturn_t sparc64_msiq_interrupt(int irq, void *cookie)
unsigned long msi;
err = ops->dequeue_msi(pbm, msiqid, &head, &msi);
- if (likely(err > 0))
- __do_IRQ(pbm->msi_irq_table[msi - pbm->msi_first]);
+ if (likely(err > 0)) {
+ struct irq_desc *desc;
+ unsigned int virt_irq;
+
+ virt_irq = pbm->msi_irq_table[msi - pbm->msi_first];
+ desc = irq_desc + virt_irq;
+
+ desc->handle_irq(virt_irq, desc);
+ }
if (unlikely(err < 0))
goto err_dequeue;
@@ -128,7 +135,8 @@ int sparc64_setup_msi_irq(unsigned int *virt_irq_p,
if (!*virt_irq_p)
goto out_err;
- set_irq_chip(*virt_irq_p, &msi_irq);
+ set_irq_chip_and_handler_name(*virt_irq_p, &msi_irq,
+ handle_simple_irq, "MSI");
err = alloc_msi(pbm);
if (unlikely(err < 0))
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
index 95de1444ee67..8c4875bdb4a8 100644
--- a/arch/sparc64/kernel/pci_sun4v.c
+++ b/arch/sparc64/kernel/pci_sun4v.c
@@ -365,15 +365,13 @@ static void dma_4v_unmap_single(struct device *dev, dma_addr_t bus_addr,
spin_unlock_irqrestore(&iommu->lock, flags);
}
-#define SG_ENT_PHYS_ADDRESS(SG) \
- (__pa(page_address((SG)->page)) + (SG)->offset)
+#define SG_ENT_PHYS_ADDRESS(SG) (__pa(sg_virt((SG))))
-static inline long fill_sg(long entry, struct device *dev,
- struct scatterlist *sg,
- int nused, int nelems, unsigned long prot)
+static long fill_sg(long entry, struct device *dev,
+ struct scatterlist *sg,
+ int nused, int nelems, unsigned long prot)
{
struct scatterlist *dma_sg = sg;
- struct scatterlist *sg_end = sg + nelems;
unsigned long flags;
int i;
@@ -413,7 +411,8 @@ static inline long fill_sg(long entry, struct device *dev,
len -= (IO_PAGE_SIZE - (tmp & (IO_PAGE_SIZE - 1UL)));
break;
}
- sg++;
+ sg = sg_next(sg);
+ nelems--;
}
pteval = (pteval & IOPTE_PAGE);
@@ -431,24 +430,26 @@ static inline long fill_sg(long entry, struct device *dev,
}
pteval = (pteval & IOPTE_PAGE) + len;
- sg++;
+ sg = sg_next(sg);
+ nelems--;
/* Skip over any tail mappings we've fully mapped,
* adjusting pteval along the way. Stop when we
* detect a page crossing event.
*/
- while (sg < sg_end &&
+ while (nelems &&
(pteval << (64 - IO_PAGE_SHIFT)) != 0UL &&
(pteval == SG_ENT_PHYS_ADDRESS(sg)) &&
((pteval ^
(SG_ENT_PHYS_ADDRESS(sg) + sg->length - 1UL)) >> IO_PAGE_SHIFT) == 0UL) {
pteval += sg->length;
- sg++;
+ sg = sg_next(sg);
+ nelems--;
}
if ((pteval << (64 - IO_PAGE_SHIFT)) == 0UL)
pteval = ~0UL;
} while (dma_npages != 0);
- dma_sg++;
+ dma_sg = sg_next(dma_sg);
}
if (unlikely(iommu_batch_end() < 0L))
@@ -475,9 +476,7 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
/* Fast path single entry scatterlists. */
if (nelems == 1) {
sglist->dma_address =
- dma_4v_map_single(dev,
- (page_address(sglist->page) +
- sglist->offset),
+ dma_4v_map_single(dev, sg_virt(sglist),
sglist->length, direction);
if (unlikely(sglist->dma_address == DMA_ERROR_CODE))
return 0;
@@ -510,7 +509,7 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
sgtmp = sglist;
while (used && sgtmp->dma_length) {
sgtmp->dma_address += dma_base;
- sgtmp++;
+ sgtmp = sg_next(sgtmp);
used--;
}
used = nelems - used;
@@ -545,6 +544,7 @@ static void dma_4v_unmap_sg(struct device *dev, struct scatterlist *sglist,
struct pci_pbm_info *pbm;
struct iommu *iommu;
unsigned long flags, i, npages;
+ struct scatterlist *sg, *sgprv;
long entry;
u32 devhandle, bus_addr;
@@ -558,12 +558,15 @@ static void dma_4v_unmap_sg(struct device *dev, struct scatterlist *sglist,
devhandle = pbm->devhandle;
bus_addr = sglist->dma_address & IO_PAGE_MASK;
-
- for (i = 1; i < nelems; i++)
- if (sglist[i].dma_length == 0)
+ sgprv = NULL;
+ for_each_sg(sglist, sg, nelems, i) {
+ if (sg->dma_length == 0)
break;
- i--;
- npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length) -
+
+ sgprv = sg;
+ }
+
+ npages = (IO_PAGE_ALIGN(sgprv->dma_address + sgprv->dma_length) -
bus_addr) >> IO_PAGE_SHIFT;
entry = ((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
diff --git a/arch/sparc64/kernel/semaphore.c b/arch/sparc64/kernel/semaphore.c
index a809e63f03ef..9974a6899551 100644
--- a/arch/sparc64/kernel/semaphore.c
+++ b/arch/sparc64/kernel/semaphore.c
@@ -1,5 +1,4 @@
-/* $Id: semaphore.c,v 1.9 2001/11/18 00:12:56 davem Exp $
- * semaphore.c: Sparc64 semaphore implementation.
+/* semaphore.c: Sparc64 semaphore implementation.
*
* This is basically the PPC semaphore scheme ported to use
* the sparc64 atomic instructions, so see the PPC code for
@@ -19,7 +18,7 @@
* sem->count = tmp;
* return old_count;
*/
-static __inline__ int __sem_update_count(struct semaphore *sem, int incr)
+static inline int __sem_update_count(struct semaphore *sem, int incr)
{
int old_count, tmp;
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index c73b7a48b036..7cd8d94df0dc 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -52,14 +52,13 @@ int sparc64_multi_core __read_mostly;
cpumask_t cpu_possible_map __read_mostly = CPU_MASK_NONE;
cpumask_t cpu_online_map __read_mostly = CPU_MASK_NONE;
-cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly =
- { [0 ... NR_CPUS-1] = CPU_MASK_NONE };
+DEFINE_PER_CPU(cpumask_t, cpu_sibling_map) = CPU_MASK_NONE;
cpumask_t cpu_core_map[NR_CPUS] __read_mostly =
{ [0 ... NR_CPUS-1] = CPU_MASK_NONE };
EXPORT_SYMBOL(cpu_possible_map);
EXPORT_SYMBOL(cpu_online_map);
-EXPORT_SYMBOL(cpu_sibling_map);
+EXPORT_PER_CPU_SYMBOL(cpu_sibling_map);
EXPORT_SYMBOL(cpu_core_map);
static cpumask_t smp_commenced_mask;
@@ -460,7 +459,7 @@ again:
}
}
-static __inline__ void spitfire_xcall_deliver(u64 data0, u64 data1, u64 data2, cpumask_t mask)
+static inline void spitfire_xcall_deliver(u64 data0, u64 data1, u64 data2, cpumask_t mask)
{
u64 pstate;
int i;
@@ -907,7 +906,7 @@ extern atomic_t dcpage_flushes;
extern atomic_t dcpage_flushes_xcall;
#endif
-static __inline__ void __local_flush_dcache_page(struct page *page)
+static inline void __local_flush_dcache_page(struct page *page)
{
#ifdef DCACHE_ALIASING_POSSIBLE
__flush_dcache_page(page_address(page),
@@ -1261,16 +1260,16 @@ void __devinit smp_fill_in_sib_core_maps(void)
for_each_present_cpu(i) {
unsigned int j;
- cpus_clear(cpu_sibling_map[i]);
+ cpus_clear(per_cpu(cpu_sibling_map, i));
if (cpu_data(i).proc_id == -1) {
- cpu_set(i, cpu_sibling_map[i]);
+ cpu_set(i, per_cpu(cpu_sibling_map, i));
continue;
}
for_each_present_cpu(j) {
if (cpu_data(i).proc_id ==
cpu_data(j).proc_id)
- cpu_set(j, cpu_sibling_map[i]);
+ cpu_set(j, per_cpu(cpu_sibling_map, i));
}
}
}
@@ -1342,9 +1341,9 @@ int __cpu_disable(void)
cpu_clear(cpu, cpu_core_map[i]);
cpus_clear(cpu_core_map[cpu]);
- for_each_cpu_mask(i, cpu_sibling_map[cpu])
- cpu_clear(cpu, cpu_sibling_map[i]);
- cpus_clear(cpu_sibling_map[cpu]);
+ for_each_cpu_mask(i, per_cpu(cpu_sibling_map, cpu))
+ cpu_clear(cpu, per_cpu(cpu_sibling_map, i));
+ cpus_clear(per_cpu(cpu_sibling_map, cpu));
c = &cpu_data(cpu);
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index 23fad7ebdd0d..60765e314bd8 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -221,7 +221,7 @@ EXPORT_SYMBOL(pci_dma_supported);
/* I/O device mmaping on Sparc64. */
EXPORT_SYMBOL(io_remap_pfn_range);
-#ifdef CONFIG_COMPAT
+#if defined(CONFIG_COMPAT) && defined(CONFIG_NET)
/* Solaris/SunOS binary compatibility */
EXPORT_SYMBOL(verify_compat_iovec);
#endif
diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c
index 0d5c50264945..c56573a10eee 100644
--- a/arch/sparc64/kernel/sys_sparc.c
+++ b/arch/sparc64/kernel/sys_sparc.c
@@ -26,7 +26,6 @@
#include <linux/random.h>
#include <asm/uaccess.h>
-#include <asm/ipc.h>
#include <asm/utrap.h>
#include <asm/perfctr.h>
#include <asm/a.out.h>
@@ -319,7 +318,7 @@ unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr, u
if (flags & MAP_FIXED) {
/* Ok, don't mess with it. */
- return get_unmapped_area(NULL, addr, len, pgoff, flags);
+ return get_unmapped_area(NULL, orig_addr, len, pgoff, flags);
}
flags &= ~MAP_SHARED;
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index e8dce90d05d4..98c468803ce3 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -51,10 +51,8 @@
#include <linux/vfs.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/ptrace.h>
-#include <linux/highuid.h>
#include <asm/types.h>
-#include <asm/ipc.h>
#include <asm/uaccess.h>
#include <asm/fpumacro.h>
#include <asm/semaphore.h>
diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c
index 8f7a06e2c7e7..cfc22d3fe54c 100644
--- a/arch/sparc64/kernel/sys_sunos32.c
+++ b/arch/sparc64/kernel/sys_sunos32.c
@@ -57,7 +57,6 @@
#include <linux/personality.h>
/* For SOCKET_I */
-#include <linux/socket.h>
#include <net/sock.h>
#include <net/compat.h>
@@ -831,7 +830,7 @@ asmlinkage int sunos_killpg(int pgrp, int sig)
rcu_read_lock();
ret = -EINVAL;
if (pgrp > 0)
- ret = kill_pgrp(find_pid(pgrp), sig, 0);
+ ret = kill_pgrp(find_vpid(pgrp), sig, 0);
rcu_read_unlock();
return ret;
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index cd8c740cba1d..4352ee4d8dac 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -28,7 +28,6 @@
#include <linux/jiffies.h>
#include <linux/cpufreq.h>
#include <linux/percpu.h>
-#include <linux/profile.h>
#include <linux/miscdevice.h>
#include <linux/rtc.h>
#include <linux/kernel_stat.h>
@@ -47,7 +46,6 @@
#include <asm/sections.h>
#include <asm/cpudata.h>
#include <asm/uaccess.h>
-#include <asm/prom.h>
#include <asm/irq_regs.h>
DEFINE_SPINLOCK(mostek_lock);
@@ -1070,7 +1068,7 @@ static int set_rtc_mmss(unsigned long nowtime)
* Not having a register set can lead to trouble.
* Also starfire doesn't have a tod clock.
*/
- if (!mregs && !dregs & !bregs)
+ if (!mregs && !dregs && !bregs)
return -1;
if (mregs) {
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index 34573a55b6e5..04998388259f 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -1,7 +1,6 @@
-/* $Id: traps.c,v 1.85 2002/02/09 19:49:31 davem Exp $
- * arch/sparc64/kernel/traps.c
+/* arch/sparc64/kernel/traps.c
*
- * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1995,1997 David S. Miller (davem@davemloft.net)
* Copyright (C) 1997,1999,2000 Jakub Jelinek (jakub@redhat.com)
*/
@@ -765,7 +764,7 @@ static unsigned long cheetah_afsr_errors;
*/
struct cheetah_err_info *cheetah_error_log;
-static __inline__ struct cheetah_err_info *cheetah_get_error_log(unsigned long afsr)
+static inline struct cheetah_err_info *cheetah_get_error_log(unsigned long afsr)
{
struct cheetah_err_info *p;
int cpu = smp_processor_id();
@@ -1085,7 +1084,7 @@ static unsigned char cheetah_mtag_syntab[] = {
};
/* Return the highest priority error conditon mentioned. */
-static __inline__ unsigned long cheetah_get_hipri(unsigned long afsr)
+static inline unsigned long cheetah_get_hipri(unsigned long afsr)
{
unsigned long tmp = 0;
int i;
@@ -2225,7 +2224,7 @@ void die_if_kernel(char *str, struct pt_regs *regs)
" /_| \\__/ |_\\\n"
" \\__U_/\n");
- printk("%s(%d): %s [#%d]\n", current->comm, current->pid, str, ++die_counter);
+ printk("%s(%d): %s [#%d]\n", current->comm, task_pid_nr(current), str, ++die_counter);
notify_die(DIE_OOPS, str, regs, 0, 255, SIGSEGV);
__asm__ __volatile__("flushw");
__show_regs(regs);
diff --git a/arch/sparc64/lib/atomic.S b/arch/sparc64/lib/atomic.S
index 9633750167d0..70ac4186f62b 100644
--- a/arch/sparc64/lib/atomic.S
+++ b/arch/sparc64/lib/atomic.S
@@ -1,10 +1,10 @@
-/* $Id: atomic.S,v 1.4 2001/11/18 00:12:56 davem Exp $
- * atomic.S: These things are too big to do inline.
+/* atomic.S: These things are too big to do inline.
*
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net)
*/
#include <asm/asi.h>
+#include <asm/backoff.h>
.text
@@ -16,27 +16,31 @@
.globl atomic_add
.type atomic_add,#function
atomic_add: /* %o0 = increment, %o1 = atomic_ptr */
+ BACKOFF_SETUP(%o2)
1: lduw [%o1], %g1
add %g1, %o0, %g7
cas [%o1], %g1, %g7
cmp %g1, %g7
- bne,pn %icc, 1b
+ bne,pn %icc, 2f
nop
retl
nop
+2: BACKOFF_SPIN(%o2, %o3, 1b)
.size atomic_add, .-atomic_add
.globl atomic_sub
.type atomic_sub,#function
atomic_sub: /* %o0 = decrement, %o1 = atomic_ptr */
+ BACKOFF_SETUP(%o2)
1: lduw [%o1], %g1
sub %g1, %o0, %g7
cas [%o1], %g1, %g7
cmp %g1, %g7
- bne,pn %icc, 1b
+ bne,pn %icc, 2f
nop
retl
nop
+2: BACKOFF_SPIN(%o2, %o3, 1b)
.size atomic_sub, .-atomic_sub
/* On SMP we need to use memory barriers to ensure
@@ -60,89 +64,101 @@ atomic_sub: /* %o0 = decrement, %o1 = atomic_ptr */
.globl atomic_add_ret
.type atomic_add_ret,#function
atomic_add_ret: /* %o0 = increment, %o1 = atomic_ptr */
+ BACKOFF_SETUP(%o2)
ATOMIC_PRE_BARRIER
1: lduw [%o1], %g1
add %g1, %o0, %g7
cas [%o1], %g1, %g7
cmp %g1, %g7
- bne,pn %icc, 1b
+ bne,pn %icc, 2f
add %g7, %o0, %g7
sra %g7, 0, %o0
ATOMIC_POST_BARRIER
retl
nop
+2: BACKOFF_SPIN(%o2, %o3, 1b)
.size atomic_add_ret, .-atomic_add_ret
.globl atomic_sub_ret
.type atomic_sub_ret,#function
atomic_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */
+ BACKOFF_SETUP(%o2)
ATOMIC_PRE_BARRIER
1: lduw [%o1], %g1
sub %g1, %o0, %g7
cas [%o1], %g1, %g7
cmp %g1, %g7
- bne,pn %icc, 1b
+ bne,pn %icc, 2f
sub %g7, %o0, %g7
sra %g7, 0, %o0
ATOMIC_POST_BARRIER
retl
nop
+2: BACKOFF_SPIN(%o2, %o3, 1b)
.size atomic_sub_ret, .-atomic_sub_ret
.globl atomic64_add
.type atomic64_add,#function
atomic64_add: /* %o0 = increment, %o1 = atomic_ptr */
+ BACKOFF_SETUP(%o2)
1: ldx [%o1], %g1
add %g1, %o0, %g7
casx [%o1], %g1, %g7
cmp %g1, %g7
- bne,pn %xcc, 1b
+ bne,pn %xcc, 2f
nop
retl
nop
+2: BACKOFF_SPIN(%o2, %o3, 1b)
.size atomic64_add, .-atomic64_add
.globl atomic64_sub
.type atomic64_sub,#function
atomic64_sub: /* %o0 = decrement, %o1 = atomic_ptr */
+ BACKOFF_SETUP(%o2)
1: ldx [%o1], %g1
sub %g1, %o0, %g7
casx [%o1], %g1, %g7
cmp %g1, %g7
- bne,pn %xcc, 1b
+ bne,pn %xcc, 2f
nop
retl
nop
+2: BACKOFF_SPIN(%o2, %o3, 1b)
.size atomic64_sub, .-atomic64_sub
.globl atomic64_add_ret
.type atomic64_add_ret,#function
atomic64_add_ret: /* %o0 = increment, %o1 = atomic_ptr */
+ BACKOFF_SETUP(%o2)
ATOMIC_PRE_BARRIER
1: ldx [%o1], %g1
add %g1, %o0, %g7
casx [%o1], %g1, %g7
cmp %g1, %g7
- bne,pn %xcc, 1b
+ bne,pn %xcc, 2f
add %g7, %o0, %g7
mov %g7, %o0
ATOMIC_POST_BARRIER
retl
nop
+2: BACKOFF_SPIN(%o2, %o3, 1b)
.size atomic64_add_ret, .-atomic64_add_ret
.globl atomic64_sub_ret
.type atomic64_sub_ret,#function
atomic64_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */
+ BACKOFF_SETUP(%o2)
ATOMIC_PRE_BARRIER
1: ldx [%o1], %g1
sub %g1, %o0, %g7
casx [%o1], %g1, %g7
cmp %g1, %g7
- bne,pn %xcc, 1b
+ bne,pn %xcc, 2f
sub %g7, %o0, %g7
mov %g7, %o0
ATOMIC_POST_BARRIER
retl
nop
+2: BACKOFF_SPIN(%o2, %o3, 1b)
.size atomic64_sub_ret, .-atomic64_sub_ret
diff --git a/arch/sparc64/lib/bitops.S b/arch/sparc64/lib/bitops.S
index 892431a82131..6b015a6eefb5 100644
--- a/arch/sparc64/lib/bitops.S
+++ b/arch/sparc64/lib/bitops.S
@@ -1,10 +1,10 @@
-/* $Id: bitops.S,v 1.3 2001/11/18 00:12:56 davem Exp $
- * bitops.S: Sparc64 atomic bit operations.
+/* bitops.S: Sparc64 atomic bit operations.
*
- * Copyright (C) 2000 David S. Miller (davem@redhat.com)
+ * Copyright (C) 2000, 2007 David S. Miller (davem@davemloft.net)
*/
#include <asm/asi.h>
+#include <asm/backoff.h>
.text
@@ -29,6 +29,7 @@
.globl test_and_set_bit
.type test_and_set_bit,#function
test_and_set_bit: /* %o0=nr, %o1=addr */
+ BACKOFF_SETUP(%o3)
BITOP_PRE_BARRIER
srlx %o0, 6, %g1
mov 1, %o2
@@ -40,18 +41,20 @@ test_and_set_bit: /* %o0=nr, %o1=addr */
or %g7, %o2, %g1
casx [%o1], %g7, %g1
cmp %g7, %g1
- bne,pn %xcc, 1b
+ bne,pn %xcc, 2f
and %g7, %o2, %g2
clr %o0
movrne %g2, 1, %o0
BITOP_POST_BARRIER
retl
nop
+2: BACKOFF_SPIN(%o3, %o4, 1b)
.size test_and_set_bit, .-test_and_set_bit
.globl test_and_clear_bit
.type test_and_clear_bit,#function
test_and_clear_bit: /* %o0=nr, %o1=addr */
+ BACKOFF_SETUP(%o3)
BITOP_PRE_BARRIER
srlx %o0, 6, %g1
mov 1, %o2
@@ -63,18 +66,20 @@ test_and_clear_bit: /* %o0=nr, %o1=addr */
andn %g7, %o2, %g1
casx [%o1], %g7, %g1
cmp %g7, %g1
- bne,pn %xcc, 1b
+ bne,pn %xcc, 2f
and %g7, %o2, %g2
clr %o0
movrne %g2, 1, %o0
BITOP_POST_BARRIER
retl
nop
+2: BACKOFF_SPIN(%o3, %o4, 1b)
.size test_and_clear_bit, .-test_and_clear_bit
.globl test_and_change_bit
.type test_and_change_bit,#function
test_and_change_bit: /* %o0=nr, %o1=addr */
+ BACKOFF_SETUP(%o3)
BITOP_PRE_BARRIER
srlx %o0, 6, %g1
mov 1, %o2
@@ -86,18 +91,20 @@ test_and_change_bit: /* %o0=nr, %o1=addr */
xor %g7, %o2, %g1
casx [%o1], %g7, %g1
cmp %g7, %g1
- bne,pn %xcc, 1b
+ bne,pn %xcc, 2f
and %g7, %o2, %g2
clr %o0
movrne %g2, 1, %o0
BITOP_POST_BARRIER
retl
nop
+2: BACKOFF_SPIN(%o3, %o4, 1b)
.size test_and_change_bit, .-test_and_change_bit
.globl set_bit
.type set_bit,#function
set_bit: /* %o0=nr, %o1=addr */
+ BACKOFF_SETUP(%o3)
srlx %o0, 6, %g1
mov 1, %o2
sllx %g1, 3, %g3
@@ -108,15 +115,17 @@ set_bit: /* %o0=nr, %o1=addr */
or %g7, %o2, %g1
casx [%o1], %g7, %g1
cmp %g7, %g1
- bne,pn %xcc, 1b
+ bne,pn %xcc, 2f
nop
retl
nop
+2: BACKOFF_SPIN(%o3, %o4, 1b)
.size set_bit, .-set_bit
.globl clear_bit
.type clear_bit,#function
clear_bit: /* %o0=nr, %o1=addr */
+ BACKOFF_SETUP(%o3)
srlx %o0, 6, %g1
mov 1, %o2
sllx %g1, 3, %g3
@@ -127,15 +136,17 @@ clear_bit: /* %o0=nr, %o1=addr */
andn %g7, %o2, %g1
casx [%o1], %g7, %g1
cmp %g7, %g1
- bne,pn %xcc, 1b
+ bne,pn %xcc, 2f
nop
retl
nop
+2: BACKOFF_SPIN(%o3, %o4, 1b)
.size clear_bit, .-clear_bit
.globl change_bit
.type change_bit,#function
change_bit: /* %o0=nr, %o1=addr */
+ BACKOFF_SETUP(%o3)
srlx %o0, 6, %g1
mov 1, %o2
sllx %g1, 3, %g3
@@ -146,8 +157,9 @@ change_bit: /* %o0=nr, %o1=addr */
xor %g7, %o2, %g1
casx [%o1], %g7, %g1
cmp %g7, %g1
- bne,pn %xcc, 1b
+ bne,pn %xcc, 2f
nop
retl
nop
+2: BACKOFF_SPIN(%o3, %o4, 1b)
.size change_bit, .-change_bit
diff --git a/arch/sparc64/math-emu/Makefile b/arch/sparc64/math-emu/Makefile
index a0b06fd29467..cc5cb9baf6aa 100644
--- a/arch/sparc64/math-emu/Makefile
+++ b/arch/sparc64/math-emu/Makefile
@@ -4,4 +4,4 @@
obj-y := math.o
-EXTRA_CFLAGS = -I. -Iinclude/math-emu -w
+EXTRA_CFLAGS = -Iinclude/math-emu -w
diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c
index 9f7740eee8d2..e2027f27c0fe 100644
--- a/arch/sparc64/mm/fault.c
+++ b/arch/sparc64/mm/fault.c
@@ -463,7 +463,7 @@ out_of_memory:
up_read(&mm->mmap_sem);
printk("VM: killing process %s\n", current->comm);
if (!(regs->tstate & TSTATE_PRIV))
- do_exit(SIGKILL);
+ do_group_exit(SIGKILL);
goto handle_kernel_fault;
intr_or_no_mm:
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index f0ab9aab308f..e18ccf85224f 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -201,7 +201,7 @@ inline void flush_dcache_page_impl(struct page *page)
#define dcache_dirty_cpu(page) \
(((page)->flags >> PG_dcache_cpu_shift) & PG_dcache_cpu_mask)
-static __inline__ void set_dcache_dirty(struct page *page, int this_cpu)
+static inline void set_dcache_dirty(struct page *page, int this_cpu)
{
unsigned long mask = this_cpu;
unsigned long non_cpu_bits;
@@ -223,7 +223,7 @@ static __inline__ void set_dcache_dirty(struct page *page, int this_cpu)
: "g1", "g7");
}
-static __inline__ void clear_dcache_dirty_cpu(struct page *page, unsigned long cpu)
+static inline void clear_dcache_dirty_cpu(struct page *page, unsigned long cpu)
{
unsigned long mask = (1UL << PG_dcache_dirty);
@@ -1645,6 +1645,58 @@ EXPORT_SYMBOL(_PAGE_E);
unsigned long _PAGE_CACHE __read_mostly;
EXPORT_SYMBOL(_PAGE_CACHE);
+#ifdef CONFIG_SPARSEMEM_VMEMMAP
+
+#define VMEMMAP_CHUNK_SHIFT 22
+#define VMEMMAP_CHUNK (1UL << VMEMMAP_CHUNK_SHIFT)
+#define VMEMMAP_CHUNK_MASK ~(VMEMMAP_CHUNK - 1UL)
+#define VMEMMAP_ALIGN(x) (((x)+VMEMMAP_CHUNK-1UL)&VMEMMAP_CHUNK_MASK)
+
+#define VMEMMAP_SIZE ((((1UL << MAX_PHYSADDR_BITS) >> PAGE_SHIFT) * \
+ sizeof(struct page *)) >> VMEMMAP_CHUNK_SHIFT)
+unsigned long vmemmap_table[VMEMMAP_SIZE];
+
+int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node)
+{
+ unsigned long vstart = (unsigned long) start;
+ unsigned long vend = (unsigned long) (start + nr);
+ unsigned long phys_start = (vstart - VMEMMAP_BASE);
+ unsigned long phys_end = (vend - VMEMMAP_BASE);
+ unsigned long addr = phys_start & VMEMMAP_CHUNK_MASK;
+ unsigned long end = VMEMMAP_ALIGN(phys_end);
+ unsigned long pte_base;
+
+ pte_base = (_PAGE_VALID | _PAGE_SZ4MB_4U |
+ _PAGE_CP_4U | _PAGE_CV_4U |
+ _PAGE_P_4U | _PAGE_W_4U);
+ if (tlb_type == hypervisor)
+ pte_base = (_PAGE_VALID | _PAGE_SZ4MB_4V |
+ _PAGE_CP_4V | _PAGE_CV_4V |
+ _PAGE_P_4V | _PAGE_W_4V);
+
+ for (; addr < end; addr += VMEMMAP_CHUNK) {
+ unsigned long *vmem_pp =
+ vmemmap_table + (addr >> VMEMMAP_CHUNK_SHIFT);
+ void *block;
+
+ if (!(*vmem_pp & _PAGE_VALID)) {
+ block = vmemmap_alloc_block(1UL << 22, node);
+ if (!block)
+ return -ENOMEM;
+
+ *vmem_pp = pte_base | __pa(block);
+
+ printk(KERN_INFO "[%p-%p] page_structs=%lu "
+ "node=%d entry=%lu/%lu\n", start, block, nr,
+ node,
+ addr >> VMEMMAP_CHUNK_SHIFT,
+ VMEMMAP_SIZE >> VMEMMAP_CHUNK_SHIFT);
+ }
+ }
+ return 0;
+}
+#endif /* CONFIG_SPARSEMEM_VMEMMAP */
+
static void prot_init_common(unsigned long page_none,
unsigned long page_shared,
unsigned long page_copy,
@@ -1909,9 +1961,4 @@ void online_page(struct page *page)
num_physpages++;
}
-int remove_memory(u64 start, u64 size)
-{
- return -EINVAL;
-}
-
#endif /* CONFIG_MEMORY_HOTPLUG */
diff --git a/arch/sparc64/mm/tsb.c b/arch/sparc64/mm/tsb.c
index 7ff0a02f5813..a3e6e4b635b3 100644
--- a/arch/sparc64/mm/tsb.c
+++ b/arch/sparc64/mm/tsb.c
@@ -182,7 +182,9 @@ static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_idx, unsign
break;
default:
- BUG();
+ printk(KERN_ERR "TSB[%s:%d]: Impossible TSB size %lu, killing process.\n",
+ current->comm, current->pid, tsb_bytes);
+ do_exit(SIGSEGV);
};
tte |= pte_sz_bits(page_sz);
diff --git a/arch/sparc64/mm/ultra.S b/arch/sparc64/mm/ultra.S
index 737c26923c09..2865c105b6a4 100644
--- a/arch/sparc64/mm/ultra.S
+++ b/arch/sparc64/mm/ultra.S
@@ -120,13 +120,6 @@ __spitfire_flush_tlb_mm_slow:
/*
* The following code flushes one page_size worth.
*/
-#if (PAGE_SHIFT == 13)
-#define ITAG_MASK 0xfe
-#elif (PAGE_SHIFT == 16)
-#define ITAG_MASK 0x7fe
-#else
-#error unsupported PAGE_SIZE
-#endif
.section .kprobes.text, "ax"
.align 32
.globl __flush_icache_page
diff --git a/arch/sparc64/oprofile/Kconfig b/arch/sparc64/oprofile/Kconfig
deleted file mode 100644
index d8a84088471a..000000000000
--- a/arch/sparc64/oprofile/Kconfig
+++ /dev/null
@@ -1,17 +0,0 @@
-config PROFILING
- bool "Profiling support (EXPERIMENTAL)"
- help
- Say Y here to enable the extended profiling support mechanisms used
- by profilers such as OProfile.
-
-
-config OPROFILE
- tristate "OProfile system profiling (EXPERIMENTAL)"
- depends on PROFILING
- help
- OProfile is a profiling system capable of profiling the
- whole system, include the kernel, kernel modules, libraries,
- and applications.
-
- If unsure, say N.
-
diff --git a/arch/sparc64/prom/console.c b/arch/sparc64/prom/console.c
index 3fafa9a8b50b..e1c3fc87484d 100644
--- a/arch/sparc64/prom/console.c
+++ b/arch/sparc64/prom/console.c
@@ -1,8 +1,7 @@
-/* $Id: console.c,v 1.9 1997/10/29 07:41:43 ecd Exp $
- * console.c: Routines that deal with sending and receiving IO
+/* console.c: Routines that deal with sending and receiving IO
* to/from the current console device using the PROM.
*
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1995 David S. Miller (davem@davemloft.net)
* Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
*/
@@ -19,7 +18,7 @@ extern int prom_stdin, prom_stdout;
/* Non blocking get character from console input device, returns -1
* if no input was taken. This can be used for polling.
*/
-__inline__ int
+inline int
prom_nbgetchar(void)
{
char inc;
@@ -35,7 +34,7 @@ prom_nbgetchar(void)
/* Non blocking put character to console device, returns -1 if
* unsuccessful.
*/
-__inline__ int
+inline int
prom_nbputchar(char c)
{
char outc;
diff --git a/arch/sparc64/prom/tree.c b/arch/sparc64/prom/tree.c
index b2c5b12c9818..a99ccd7fb1b0 100644
--- a/arch/sparc64/prom/tree.c
+++ b/arch/sparc64/prom/tree.c
@@ -18,14 +18,12 @@
/* Return the child of node 'node' or zero if no this node has no
* direct descendent.
*/
-__inline__ int
-__prom_getchild(int node)
+inline int __prom_getchild(int node)
{
return p1275_cmd ("child", P1275_INOUT(1, 1), node);
}
-__inline__ int
-prom_getchild(int node)
+inline int prom_getchild(int node)
{
int cnode;
@@ -35,8 +33,7 @@ prom_getchild(int node)
return (int)cnode;
}
-__inline__ int
-prom_getparent(int node)
+inline int prom_getparent(int node)
{
int cnode;
@@ -49,14 +46,12 @@ prom_getparent(int node)
/* Return the next sibling of node 'node' or zero if no more siblings
* at this level of depth in the tree.
*/
-__inline__ int
-__prom_getsibling(int node)
+inline int __prom_getsibling(int node)
{
return p1275_cmd(prom_peer_name, P1275_INOUT(1, 1), node);
}
-__inline__ int
-prom_getsibling(int node)
+inline int prom_getsibling(int node)
{
int sibnode;
@@ -72,8 +67,7 @@ prom_getsibling(int node)
/* Return the length in bytes of property 'prop' at node 'node'.
* Return -1 on error.
*/
-__inline__ int
-prom_getproplen(int node, const char *prop)
+inline int prom_getproplen(int node, const char *prop)
{
if((!node) || (!prop)) return -1;
return p1275_cmd ("getproplen",
@@ -86,8 +80,8 @@ prom_getproplen(int node, const char *prop)
* 'buffer' which has a size of 'bufsize'. If the acquisition
* was successful the length will be returned, else -1 is returned.
*/
-__inline__ int
-prom_getproperty(int node, const char *prop, char *buffer, int bufsize)
+inline int prom_getproperty(int node, const char *prop,
+ char *buffer, int bufsize)
{
int plen;
@@ -107,8 +101,7 @@ prom_getproperty(int node, const char *prop, char *buffer, int bufsize)
/* Acquire an integer property and return its value. Returns -1
* on failure.
*/
-__inline__ int
-prom_getint(int node, const char *prop)
+inline int prom_getint(int node, const char *prop)
{
int intprop;
@@ -122,8 +115,7 @@ prom_getint(int node, const char *prop)
* integer.
*/
-int
-prom_getintdefault(int node, const char *property, int deflt)
+int prom_getintdefault(int node, const char *property, int deflt)
{
int retval;
@@ -134,8 +126,7 @@ prom_getintdefault(int node, const char *property, int deflt)
}
/* Acquire a boolean property, 1=TRUE 0=FALSE. */
-int
-prom_getbool(int node, const char *prop)
+int prom_getbool(int node, const char *prop)
{
int retval;
@@ -148,8 +139,7 @@ prom_getbool(int node, const char *prop)
* string on error. The char pointer is the user supplied string
* buffer.
*/
-void
-prom_getstring(int node, const char *prop, char *user_buf, int ubuf_size)
+void prom_getstring(int node, const char *prop, char *user_buf, int ubuf_size)
{
int len;
@@ -163,8 +153,7 @@ prom_getstring(int node, const char *prop, char *user_buf, int ubuf_size)
/* Does the device at node 'node' have name 'name'?
* YES = 1 NO = 0
*/
-int
-prom_nodematch(int node, const char *name)
+int prom_nodematch(int node, const char *name)
{
char namebuf[128];
prom_getproperty(node, "name", namebuf, sizeof(namebuf));
@@ -175,8 +164,7 @@ prom_nodematch(int node, const char *name)
/* Search siblings at 'node_start' for a node with name
* 'nodename'. Return node if successful, zero if not.
*/
-int
-prom_searchsiblings(int node_start, const char *nodename)
+int prom_searchsiblings(int node_start, const char *nodename)
{
int thisnode, error;
@@ -197,8 +185,7 @@ prom_searchsiblings(int node_start, const char *nodename)
/* Return the first property type for node 'node'.
* buffer should be at least 32B in length
*/
-__inline__ char *
-prom_firstprop(int node, char *buffer)
+inline char *prom_firstprop(int node, char *buffer)
{
*buffer = 0;
if(node == -1) return buffer;
@@ -212,8 +199,7 @@ prom_firstprop(int node, char *buffer)
* at node 'node' . Returns NULL string if no more
* property types for this node.
*/
-__inline__ char *
-prom_nextprop(int node, const char *oprop, char *buffer)
+inline char *prom_nextprop(int node, const char *oprop, char *buffer)
{
char buf[32];
@@ -279,8 +265,7 @@ prom_setprop(int node, const char *pname, char *value, int size)
node, pname, value, P1275_SIZE(size));
}
-__inline__ int
-prom_inst2pkg(int inst)
+inline int prom_inst2pkg(int inst)
{
int node;
diff --git a/arch/sparc64/solaris/ipc.c b/arch/sparc64/solaris/ipc.c
index a531a2cdb381..499135fa7060 100644
--- a/arch/sparc64/solaris/ipc.c
+++ b/arch/sparc64/solaris/ipc.c
@@ -11,10 +11,10 @@
#include <linux/shm.h>
#include <linux/sem.h>
#include <linux/msg.h>
+#include <linux/ipc.h>
#include <asm/uaccess.h>
#include <asm/string.h>
-#include <asm/ipc.h>
#include "conv.h"
diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c
index 3b67de7455f1..c86cb3091a8e 100644
--- a/arch/sparc64/solaris/misc.c
+++ b/arch/sparc64/solaris/misc.c
@@ -415,7 +415,7 @@ asmlinkage int solaris_procids(int cmd, s32 pid, s32 pgid)
switch (cmd) {
case 0: /* getpgrp */
- return process_group(current);
+ return task_pgrp_nr(current);
case 1: /* setpgrp */
{
int (*sys_setpgid)(pid_t,pid_t) =
@@ -426,7 +426,7 @@ asmlinkage int solaris_procids(int cmd, s32 pid, s32 pgid)
ret = sys_setpgid(0, 0);
if (ret) return ret;
proc_clear_tty(current);
- return process_group(current);
+ return task_pgrp_nr(current);
}
case 2: /* getsid */
{
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index e6ff30266542..dd1689b814cb 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -3,7 +3,7 @@ config DEFCONFIG_LIST
option defconfig_list
default "arch/$ARCH/defconfig"
-# UML uses the generic IRQ sugsystem
+# UML uses the generic IRQ subsystem
config GENERIC_HARDIRQS
bool
default y
@@ -55,6 +55,14 @@ config GENERIC_BUG
default y
depends on BUG
+config GENERIC_TIME
+ bool
+ default y
+
+config GENERIC_CLOCKEVENTS
+ bool
+ default y
+
# Used in kernel/irq/manage.c and include/linux/irq.h
config IRQ_RELEASE_METHOD
bool
@@ -62,63 +70,25 @@ config IRQ_RELEASE_METHOD
menu "UML-specific options"
-config MODE_TT
- bool "Tracing thread support (DEPRECATED)"
- default n
- depends on BROKEN
- help
- This option controls whether tracing thread support is compiled
- into UML. This option is largely obsolete, given that skas0 provides
- skas security and performance without needing to patch the host.
- It is safe to say 'N' here; saying 'Y' may cause additional problems
- with the resulting binary even if you run UML in SKAS mode, and running
- in TT mode is strongly *NOT RECOMMENDED*.
-
config STATIC_LINK
bool "Force a static link"
default n
- depends on !MODE_TT
help
- If CONFIG_MODE_TT is disabled, then this option gives you the ability
- to force a static link of UML. Normally, if only skas mode is built
- in to UML, it will be linked as a shared binary. This is inconvenient
- for use in a chroot jail. So, if you intend to run UML inside a
- chroot, and you disable CONFIG_MODE_TT, you probably want to say Y
- here.
- Additionally, this option enables using higher memory spaces (up to
- 2.75G) for UML - disabling CONFIG_MODE_TT and enabling this option leads
- to best results for this.
-
-config KERNEL_HALF_GIGS
- int "Kernel address space size (in .5G units)"
- default "1"
- depends on MODE_TT
- help
- This determines the amount of address space that UML will allocate for
- its own, measured in half Gigabyte units. The default is 1.
- Change this only if you need to boot UML with an unusually large amount
- of physical memory.
-
-config MODE_SKAS
- bool "Separate Kernel Address Space support" if MODE_TT
- default y
- help
- This option controls whether skas (separate kernel address space)
- support is compiled in.
- Unless you have specific needs to use TT mode (which applies almost only
- to developers), you should say Y here.
- SKAS mode will make use of the SKAS3 patch if it is applied on the host
- (and your UML will run in SKAS3 mode), but if no SKAS patch is applied
- on the host it will run in SKAS0 mode, which is anyway faster than TT
- mode.
+ This option gives you the ability to force a static link of UML.
+ Normally, UML is linked as a shared binary. This is inconvenient for
+ use in a chroot jail. So, if you intend to run UML inside a chroot,
+ you probably want to say Y here.
+ Additionally, this option enables using higher memory spaces (up to
+ 2.75G) for UML.
source "arch/um/Kconfig.arch"
source "mm/Kconfig"
+source "kernel/time/Kconfig"
config LD_SCRIPT_STATIC
bool
default y
- depends on MODE_TT || STATIC_LINK
+ depends on STATIC_LINK
config LD_SCRIPT_DYN
bool
@@ -128,18 +98,18 @@ config LD_SCRIPT_DYN
config NET
bool "Networking support"
help
- Unless you really know what you are doing, you should say Y here.
- The reason is that some programs need kernel networking support even
- when running on a stand-alone machine that isn't connected to any
- other computer. If you are upgrading from an older kernel, you
- should consider updating your networking tools too because changes
- in the kernel and the tools often go hand in hand. The tools are
- contained in the package net-tools, the location and version number
- of which are given in <file:Documentation/Changes>.
+ Unless you really know what you are doing, you should say Y here.
+ The reason is that some programs need kernel networking support even
+ when running on a stand-alone machine that isn't connected to any
+ other computer. If you are upgrading from an older kernel, you
+ should consider updating your networking tools too because changes
+ in the kernel and the tools often go hand in hand. The tools are
+ contained in the package net-tools, the location and version number
+ of which are given in <file:Documentation/Changes>.
- For a general introduction to Linux networking, it is highly
- recommended to read the NET-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
+ For a general introduction to Linux networking, it is highly
+ recommended to read the NET-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
source "fs/Kconfig.binfmt"
@@ -147,99 +117,99 @@ source "fs/Kconfig.binfmt"
config HOSTFS
tristate "Host filesystem"
help
- While the User-Mode Linux port uses its own root file system for
- booting and normal file access, this module lets the UML user
- access files stored on the host. It does not require any
- network connection between the Host and UML. An example use of
- this might be:
+ While the User-Mode Linux port uses its own root file system for
+ booting and normal file access, this module lets the UML user
+ access files stored on the host. It does not require any
+ network connection between the Host and UML. An example use of
+ this might be:
- mount none /tmp/fromhost -t hostfs -o /tmp/umlshare
+ mount none /tmp/fromhost -t hostfs -o /tmp/umlshare
- where /tmp/fromhost is an empty directory inside UML and
- /tmp/umlshare is a directory on the host with files the UML user
- wishes to access.
+ where /tmp/fromhost is an empty directory inside UML and
+ /tmp/umlshare is a directory on the host with files the UML user
+ wishes to access.
- For more information, see
- <http://user-mode-linux.sourceforge.net/hostfs.html>.
+ For more information, see
+ <http://user-mode-linux.sourceforge.net/hostfs.html>.
- If you'd like to be able to work with files stored on the host,
- say Y or M here; otherwise say N.
+ If you'd like to be able to work with files stored on the host,
+ say Y or M here; otherwise say N.
config HPPFS
tristate "HoneyPot ProcFS (EXPERIMENTAL)"
depends on EXPERIMENTAL
help
- hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc
- entries to be overridden, removed, or fabricated from the host.
- Its purpose is to allow a UML to appear to be a physical machine
- by removing or changing anything in /proc which gives away the
- identity of a UML.
+ hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc
+ entries to be overridden, removed, or fabricated from the host.
+ Its purpose is to allow a UML to appear to be a physical machine
+ by removing or changing anything in /proc which gives away the
+ identity of a UML.
- See <http://user-mode-linux.sf.net/hppfs.html> for more information.
+ See <http://user-mode-linux.sf.net/hppfs.html> for more information.
- You only need this if you are setting up a UML honeypot. Otherwise,
- it is safe to say 'N' here.
+ You only need this if you are setting up a UML honeypot. Otherwise,
+ it is safe to say 'N' here.
config MCONSOLE
bool "Management console"
default y
help
- The user mode linux management console is a low-level interface to
- the kernel, somewhat like the i386 SysRq interface. Since there is
- a full-blown operating system running under every user mode linux
- instance, there is much greater flexibility possible than with the
- SysRq mechanism.
+ The user mode linux management console is a low-level interface to
+ the kernel, somewhat like the i386 SysRq interface. Since there is
+ a full-blown operating system running under every user mode linux
+ instance, there is much greater flexibility possible than with the
+ SysRq mechanism.
- If you answer 'Y' to this option, to use this feature, you need the
- mconsole client (called uml_mconsole) which is present in CVS in
- 2.4.5-9um and later (path /tools/mconsole), and is also in the
- distribution RPM package in 2.4.6 and later.
+ If you answer 'Y' to this option, to use this feature, you need the
+ mconsole client (called uml_mconsole) which is present in CVS in
+ 2.4.5-9um and later (path /tools/mconsole), and is also in the
+ distribution RPM package in 2.4.6 and later.
- It is safe to say 'Y' here.
+ It is safe to say 'Y' here.
config MAGIC_SYSRQ
bool "Magic SysRq key"
depends on MCONSOLE
- ---help---
- If you say Y here, you will have some control over the system even
- if the system crashes for example during kernel debugging (e.g., you
- will be able to flush the buffer cache to disk, reboot the system
- immediately or dump some status information). A key for each of the
- possible requests is provided.
+ help
+ If you say Y here, you will have some control over the system even
+ if the system crashes for example during kernel debugging (e.g., you
+ will be able to flush the buffer cache to disk, reboot the system
+ immediately or dump some status information). A key for each of the
+ possible requests is provided.
- This is the feature normally accomplished by pressing a key
- while holding SysRq (Alt+PrintScreen).
+ This is the feature normally accomplished by pressing a key
+ while holding SysRq (Alt+PrintScreen).
- On UML, this is accomplished by sending a "sysrq" command with
- mconsole, followed by the letter for the requested command.
+ On UML, this is accomplished by sending a "sysrq" command with
+ mconsole, followed by the letter for the requested command.
- The keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
- unless you really know what this hack does.
+ The keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
+ unless you really know what this hack does.
config SMP
bool "Symmetric multi-processing support (EXPERIMENTAL)"
default n
#SMP_BROKEN is for x86_64.
- depends on MODE_TT && EXPERIMENTAL && (!SMP_BROKEN || (BROKEN && SMP_BROKEN))
+ depends on EXPERIMENTAL && (!SMP_BROKEN || (BROKEN && SMP_BROKEN))
help
- This option enables UML SMP support.
- It is NOT related to having a real SMP box. Not directly, at least.
+ This option enables UML SMP support.
+ It is NOT related to having a real SMP box. Not directly, at least.
- UML implements virtual SMP by allowing as many processes to run
- simultaneously on the host as there are virtual processors configured.
+ UML implements virtual SMP by allowing as many processes to run
+ simultaneously on the host as there are virtual processors configured.
- Obviously, if the host is a uniprocessor, those processes will
- timeshare, but, inside UML, will appear to be running simultaneously.
- If the host is a multiprocessor, then UML processes may run
- simultaneously, depending on the host scheduler.
+ Obviously, if the host is a uniprocessor, those processes will
+ timeshare, but, inside UML, will appear to be running simultaneously.
+ If the host is a multiprocessor, then UML processes may run
+ simultaneously, depending on the host scheduler.
- This, however, is supported only in TT mode. So, if you use the SKAS
- patch on your host, switching to TT mode and enabling SMP usually gives
- you worse performances.
- Also, since the support for SMP has been under-developed, there could
- be some bugs being exposed by enabling SMP.
+ This, however, is supported only in TT mode. So, if you use the SKAS
+ patch on your host, switching to TT mode and enabling SMP usually
+ gives you worse performances.
+ Also, since the support for SMP has been under-developed, there could
+ be some bugs being exposed by enabling SMP.
- If you don't know what to do, say N.
+ If you don't know what to do, say N.
config NR_CPUS
int "Maximum number of CPUs (2-32)"
@@ -251,29 +221,24 @@ config NEST_LEVEL
int "Nesting level"
default "0"
help
- This is set to the number of layers of UMLs that this UML will be run
- in. Normally, this is zero, meaning that it will run directly on the
- host. Setting it to one will build a UML that can run inside a UML
- that is running on the host. Generally, if you intend this UML to run
- inside another UML, set CONFIG_NEST_LEVEL to one more than the host
- UML.
-
- Note that if the hosting UML has its CONFIG_KERNEL_HALF_GIGS set to
- greater than one, then the guest UML should have its CONFIG_NEST_LEVEL
- set to the host's CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS.
- Only change this if you are running nested UMLs.
+ This is set to the number of layers of UMLs that this UML will be run
+ in. Normally, this is zero, meaning that it will run directly on the
+ host. Setting it to one will build a UML that can run inside a UML
+ that is running on the host. Generally, if you intend this UML to run
+ inside another UML, set CONFIG_NEST_LEVEL to one more than the host
+ UML.
config HIGHMEM
bool "Highmem support (EXPERIMENTAL)"
depends on !64BIT && EXPERIMENTAL
default n
help
- This was used to allow UML to run with big amounts of memory.
- Currently it is unstable, so if unsure say N.
+ This was used to allow UML to run with big amounts of memory.
+ Currently it is unstable, so if unsure say N.
- To use big amounts of memory, it is recommended to disable TT mode (i.e.
- CONFIG_MODE_TT) and enable static linking (i.e. CONFIG_STATIC_LINK) -
- this should allow the guest to use up to 2.75G of memory.
+ To use big amounts of memory, it is recommended enable static
+ linking (i.e. CONFIG_STATIC_LINK) - this should allow the
+ guest to use up to 2.75G of memory.
config KERNEL_STACK_ORDER
int "Kernel stack size order"
@@ -281,20 +246,9 @@ config KERNEL_STACK_ORDER
range 1 10 if 64BIT
default 0 if !64BIT
help
- This option determines the size of UML kernel stacks. They will
- be 1 << order pages. The default is OK unless you're running Valgrind
- on UML, in which case, set this to 3.
-
-config UML_REAL_TIME_CLOCK
- bool "Real-time Clock"
- default y
- help
- This option makes UML time deltas match wall clock deltas. This should
- normally be enabled. The exception would be if you are debugging with
- UML and spend long times with UML stopped at a breakpoint. In this
- case, when UML is restarted, it will call the timer enough times to make
- up for the time spent at the breakpoint. This could result in a
- noticeable lag. If this is a problem, then disable this option.
+ This option determines the size of UML kernel stacks. They will
+ be 1 << order pages. The default is OK unless you're running Valgrind
+ on UML, in which case, set this to 3.
endmenu
@@ -335,4 +289,6 @@ config INPUT
bool
default n
+source "kernel/Kconfig.instrumentation"
+
source "arch/um/Kconfig.debug"
diff --git a/arch/um/Kconfig.char b/arch/um/Kconfig.char
index a5b079d5e865..9a78d354f0b4 100644
--- a/arch/um/Kconfig.char
+++ b/arch/um/Kconfig.char
@@ -5,7 +5,7 @@ config STDERR_CONSOLE
bool "stderr console"
default y
help
- console driver which dumps all printk messages to stderr.
+ console driver which dumps all printk messages to stderr.
config STDIO_CONSOLE
bool
@@ -14,60 +14,58 @@ config STDIO_CONSOLE
config SSL
bool "Virtual serial line"
help
- The User-Mode Linux environment allows you to create virtual serial
- lines on the UML that are usually made to show up on the host as
- ttys or ptys.
+ The User-Mode Linux environment allows you to create virtual serial
+ lines on the UML that are usually made to show up on the host as
+ ttys or ptys.
- See <http://user-mode-linux.sourceforge.net/input.html> for more
- information and command line examples of how to use this facility.
+ See <http://user-mode-linux.sourceforge.net/input.html> for more
+ information and command line examples of how to use this facility.
- Unless you have a specific reason for disabling this, say Y.
+ Unless you have a specific reason for disabling this, say Y.
config NULL_CHAN
bool "null channel support"
help
- This option enables support for attaching UML consoles and serial
- lines to a device similar to /dev/null. Data written to it disappears
- and there is never any data to be read.
+ This option enables support for attaching UML consoles and serial
+ lines to a device similar to /dev/null. Data written to it disappears
+ and there is never any data to be read.
config PORT_CHAN
bool "port channel support"
help
- This option enables support for attaching UML consoles and serial
- lines to host portals. They may be accessed with 'telnet <host>
- <port number>'. Any number of consoles and serial lines may be
- attached to a single portal, although what UML device you get when
- you telnet to that portal will be unpredictable.
- It is safe to say 'Y' here.
+ This option enables support for attaching UML consoles and serial
+ lines to host portals. They may be accessed with 'telnet <host>
+ <port number>'. Any number of consoles and serial lines may be
+ attached to a single portal, although what UML device you get when
+ you telnet to that portal will be unpredictable.
+ It is safe to say 'Y' here.
config PTY_CHAN
bool "pty channel support"
help
- This option enables support for attaching UML consoles and serial
- lines to host pseudo-terminals. Access to both traditional
- pseudo-terminals (/dev/pty*) and pts pseudo-terminals are controlled
- with this option. The assignment of UML devices to host devices
- will be announced in the kernel message log.
- It is safe to say 'Y' here.
+ This option enables support for attaching UML consoles and serial
+ lines to host pseudo-terminals. Access to both traditional
+ pseudo-terminals (/dev/pty*) and pts pseudo-terminals are controlled
+ with this option. The assignment of UML devices to host devices
+ will be announced in the kernel message log.
+ It is safe to say 'Y' here.
config TTY_CHAN
bool "tty channel support"
help
- This option enables support for attaching UML consoles and serial
- lines to host terminals. Access to both virtual consoles
- (/dev/tty*) and the slave side of pseudo-terminals (/dev/ttyp* and
- /dev/pts/*) are controlled by this option.
- It is safe to say 'Y' here.
+ This option enables support for attaching UML consoles and serial
+ lines to host terminals. Access to both virtual consoles
+ (/dev/tty*) and the slave side of pseudo-terminals (/dev/ttyp* and
+ /dev/pts/*) are controlled by this option.
+ It is safe to say 'Y' here.
config XTERM_CHAN
bool "xterm channel support"
help
- This option enables support for attaching UML consoles and serial
- lines to xterms. Each UML device so assigned will be brought up in
- its own xterm.
- If you disable this option, then CONFIG_PT_PROXY will be disabled as
- well, since UML's gdb currently requires an xterm.
- It is safe to say 'Y' here.
+ This option enables support for attaching UML consoles and serial
+ lines to xterms. Each UML device so assigned will be brought up in
+ its own xterm.
+ It is safe to say 'Y' here.
config NOCONFIG_CHAN
bool
@@ -77,39 +75,39 @@ config CON_ZERO_CHAN
string "Default main console channel initialization"
default "fd:0,fd:1"
help
- This is the string describing the channel to which the main console
- will be attached by default. This value can be overridden from the
- command line. The default value is "fd:0,fd:1", which attaches the
- main console to stdin and stdout.
- It is safe to leave this unchanged.
+ This is the string describing the channel to which the main console
+ will be attached by default. This value can be overridden from the
+ command line. The default value is "fd:0,fd:1", which attaches the
+ main console to stdin and stdout.
+ It is safe to leave this unchanged.
config CON_CHAN
string "Default console channel initialization"
default "xterm"
help
- This is the string describing the channel to which all consoles
- except the main console will be attached by default. This value can
- be overridden from the command line. The default value is "xterm",
- which brings them up in xterms.
- It is safe to leave this unchanged, although you may wish to change
- this if you expect the UML that you build to be run in environments
- which don't have X or xterm available.
+ This is the string describing the channel to which all consoles
+ except the main console will be attached by default. This value can
+ be overridden from the command line. The default value is "xterm",
+ which brings them up in xterms.
+ It is safe to leave this unchanged, although you may wish to change
+ this if you expect the UML that you build to be run in environments
+ which don't have X or xterm available.
config SSL_CHAN
string "Default serial line channel initialization"
default "pty"
help
- This is the string describing the channel to which the serial lines
- will be attached by default. This value can be overridden from the
- command line. The default value is "pty", which attaches them to
- traditional pseudo-terminals.
- It is safe to leave this unchanged, although you may wish to change
- this if you expect the UML that you build to be run in environments
- which don't have a set of /dev/pty* devices.
+ This is the string describing the channel to which the serial lines
+ will be attached by default. This value can be overridden from the
+ command line. The default value is "pty", which attaches them to
+ traditional pseudo-terminals.
+ It is safe to leave this unchanged, although you may wish to change
+ this if you expect the UML that you build to be run in environments
+ which don't have a set of /dev/pty* devices.
config UNIX98_PTYS
bool "Unix98 PTY support"
- ---help---
+ help
A pseudo terminal (PTY) is a software device consisting of two
halves: a master and a slave. The slave device behaves identical to
a physical terminal; the master device is used by a process to
@@ -132,7 +130,7 @@ config UNIX98_PTYS
config LEGACY_PTYS
bool "Legacy (BSD) PTY support"
default y
- ---help---
+ help
A pseudo terminal (PTY) is a software device consisting of two
halves: a master and a slave. The slave device behaves identical to
a physical terminal; the master device is used by a process to
@@ -170,7 +168,7 @@ config LEGACY_PTY_COUNT
int "Maximum number of legacy PTY in use"
depends on LEGACY_PTYS
default "256"
- ---help---
+ help
The maximum number of legacy PTYs that can be used at any one time.
The default is 256, and should be more than enough. Embedded
systems may want to reduce this to save memory.
@@ -196,10 +194,10 @@ config UML_WATCHDOG
config UML_SOUND
tristate "Sound support"
help
- This option enables UML sound support. If enabled, it will pull in
- soundcore and the UML hostaudio relay, which acts as a intermediary
- between the host's dsp and mixer devices and the UML sound system.
- It is safe to say 'Y' here.
+ This option enables UML sound support. If enabled, it will pull in
+ soundcore and the UML hostaudio relay, which acts as a intermediary
+ between the host's dsp and mixer devices and the UML sound system.
+ It is safe to say 'Y' here.
config SOUND
tristate
@@ -217,22 +215,21 @@ config HW_RANDOM
config UML_RANDOM
tristate "Hardware random number generator"
help
- This option enables UML's "hardware" random number generator. It
- attaches itself to the host's /dev/random, supplying as much entropy
- as the host has, rather than the small amount the UML gets from its
- own drivers. It registers itself as a standard hardware random number
- generator, major 10, minor 183, and the canonical device name is
- /dev/hwrng.
- The way to make use of this is to install the rng-tools package
- (check your distro, or download from
- http://sourceforge.net/projects/gkernel/). rngd periodically reads
- /dev/hwrng and injects the entropy into /dev/random.
+ This option enables UML's "hardware" random number generator. It
+ attaches itself to the host's /dev/random, supplying as much entropy
+ as the host has, rather than the small amount the UML gets from its
+ own drivers. It registers itself as a standard hardware random number
+ generator, major 10, minor 183, and the canonical device name is
+ /dev/hwrng.
+ The way to make use of this is to install the rng-tools package
+ (check your distro, or download from
+ http://sourceforge.net/projects/gkernel/). rngd periodically reads
+ /dev/hwrng and injects the entropy into /dev/random.
config MMAPPER
tristate "iomem emulation driver"
help
- This driver allows a host file to be used as emulated IO memory inside
- UML.
+ This driver allows a host file to be used as emulated IO memory inside
+ UML.
endmenu
-
diff --git a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug
index c86f5eb29fd5..1f6462ffd3e8 100644
--- a/arch/um/Kconfig.debug
+++ b/arch/um/Kconfig.debug
@@ -2,50 +2,31 @@ menu "Kernel hacking"
source "lib/Kconfig.debug"
-config CMDLINE_ON_HOST
- bool "Show command line arguments on the host in TT mode"
- depends on MODE_TT
- default !DEBUG_INFO
- help
- This controls whether arguments in guest processes should be shown on
- the host's ps output.
- Enabling this option hinders debugging on some recent GDB versions
- (because GDB gets "confused" when we do an execvp()). So probably you
- should disable it.
-
-config PT_PROXY
- bool "Enable ptrace proxy"
- depends on XTERM_CHAN && DEBUG_INFO && MODE_TT
- help
- This option enables a debugging interface which allows gdb to debug
- the kernel without needing to actually attach to kernel threads.
- If you want to do kernel debugging, say Y here; otherwise say N.
-
config GPROF
bool "Enable gprof support"
- depends on DEBUG_INFO && MODE_SKAS && !MODE_TT
+ depends on DEBUG_INFO
help
- This allows profiling of a User-Mode Linux kernel with the gprof
- utility.
+ This allows profiling of a User-Mode Linux kernel with the gprof
+ utility.
- See <http://user-mode-linux.sourceforge.net/gprof.html> for more
- details.
+ See <http://user-mode-linux.sourceforge.net/gprof.html> for more
+ details.
- If you're involved in UML kernel development and want to use gprof,
- say Y. If you're unsure, say N.
+ If you're involved in UML kernel development and want to use gprof,
+ say Y. If you're unsure, say N.
config GCOV
bool "Enable gcov support"
- depends on DEBUG_INFO && MODE_SKAS
+ depends on DEBUG_INFO
help
- This option allows developers to retrieve coverage data from a UML
- session.
+ This option allows developers to retrieve coverage data from a UML
+ session.
- See <http://user-mode-linux.sourceforge.net/gprof.html> for more
- details.
+ See <http://user-mode-linux.sourceforge.net/gprof.html> for more
+ details.
- If you're involved in UML kernel development and want to use gcov,
- say Y. If you're unsure, say N.
+ If you're involved in UML kernel development and want to use gcov,
+ say Y. If you're unsure, say N.
config DEBUG_STACK_USAGE
bool "Stack utilization instrumentation"
diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386
index d6cffb27fff8..e0ac74e5d4c4 100644
--- a/arch/um/Kconfig.i386
+++ b/arch/um/Kconfig.i386
@@ -1,6 +1,6 @@
menu "Host processor type and features"
-source "arch/i386/Kconfig.cpu"
+source "arch/x86/Kconfig.cpu"
endmenu
@@ -65,20 +65,6 @@ config 3_LEVEL_PGTABLES
However, this it experimental on 32-bit architectures, so if unsure say
N (on x86-64 it's automatically enabled, instead, as it's safe there).
-config STUB_CODE
- hex
- default 0xbfffe000 if !HOST_VMSPLIT_2G
- default 0x7fffe000 if HOST_VMSPLIT_2G
-
-config STUB_DATA
- hex
- default 0xbffff000 if !HOST_VMSPLIT_2G
- default 0x7ffff000 if HOST_VMSPLIT_2G
-
-config STUB_START
- hex
- default STUB_CODE
-
config ARCH_HAS_SC_SIGNALS
bool
default y
diff --git a/arch/um/Kconfig.net b/arch/um/Kconfig.net
index 14a04ebdeae9..66e50026ade9 100644
--- a/arch/um/Kconfig.net
+++ b/arch/um/Kconfig.net
@@ -108,6 +108,28 @@ config UML_NET_DAEMON
more than one without conflict. If you don't need UML networking,
say N.
+config UML_NET_VDE
+ bool "VDE transport"
+ depends on UML_NET
+ help
+ This User-Mode Linux network transport allows one or more running
+ UMLs on a single host to communicate with each other and also
+ with the rest of the world using Virtual Distributed Ethernet,
+ an improved fork of uml_switch.
+
+ You must have libvdeplug installed in order to build the vde
+ transport into UML.
+
+ To use this form of networking, you will need to run vde_switch
+ on the host.
+
+ For more information, see <http://wiki.virtualsquare.org/>
+ That site has a good overview of what VDE is and also examples
+ of the UML command line to use to enable VDE networking.
+
+ If you need UML networking with VDE,
+ say Y.
+
config UML_NET_MCAST
bool "Multicast transport"
depends on UML_NET
diff --git a/arch/um/Kconfig.x86_64 b/arch/um/Kconfig.x86_64
index f60e9e506424..d632e9a89cc3 100644
--- a/arch/um/Kconfig.x86_64
+++ b/arch/um/Kconfig.x86_64
@@ -17,24 +17,12 @@ config SEMAPHORE_SLEEPERS
config TOP_ADDR
hex
- default 0x80000000
+ default 0x7fc0000000
config 3_LEVEL_PGTABLES
bool
default y
-config STUB_CODE
- hex
- default 0x7fbfffe000
-
-config STUB_DATA
- hex
- default 0x7fbffff000
-
-config STUB_START
- hex
- default STUB_CODE
-
config ARCH_HAS_SC_SIGNALS
bool
default n
diff --git a/arch/um/Makefile b/arch/um/Makefile
index 0666729eb976..31999bc1c8a4 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -2,7 +2,7 @@
# This file is included by the global makefile so that you can add your own
# architecture-specific flags and dependencies.
#
-# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
# Licensed under the GPL
#
@@ -31,18 +31,9 @@ SYMLINK_HEADERS := $(foreach header,$(SYMLINK_HEADERS),include/asm-um/$(header))
ARCH_SYMLINKS = include/asm-um/arch $(ARCH_DIR)/include/sysdep $(ARCH_DIR)/os \
$(SYMLINK_HEADERS) $(ARCH_DIR)/include/uml-config.h
-um-modes-$(CONFIG_MODE_TT) += tt
-um-modes-$(CONFIG_MODE_SKAS) += skas
+MODE_INCLUDE += -I$(srctree)/$(ARCH_DIR)/include/skas
-MODE_INCLUDE += $(foreach mode,$(um-modes-y),\
- -I$(srctree)/$(ARCH_DIR)/include/$(mode))
-
-MAKEFILES-INCL += $(foreach mode,$(um-modes-y),\
- $(srctree)/$(ARCH_DIR)/Makefile-$(mode))
-
-ifneq ($(MAKEFILES-INCL),)
- include $(MAKEFILES-INCL)
-endif
+include $(srctree)/$(ARCH_DIR)/Makefile-skas
ARCH_INCLUDE := -I$(ARCH_DIR)/include
ifneq ($(KBUILD_SRC),)
@@ -58,14 +49,15 @@ SYS_DIR := $(ARCH_DIR)/include/sysdep-$(SUBARCH)
#
# These apply to USER_CFLAGS to.
-CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \
+KBUILD_CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \
$(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap \
- -Din6addr_loopback=kernel_in6addr_loopback
+ -Din6addr_loopback=kernel_in6addr_loopback \
+ -Din6addr_any=kernel_in6addr_any
-AFLAGS += $(ARCH_INCLUDE)
+KBUILD_AFLAGS += $(ARCH_INCLUDE)
USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -D__KERNEL__,,\
- $(patsubst -I%,,$(CFLAGS)))) $(ARCH_INCLUDE) $(MODE_INCLUDE) \
+ $(patsubst -I%,,$(KBUILD_CFLAGS)))) $(ARCH_INCLUDE) $(MODE_INCLUDE) \
-D_FILE_OFFSET_BITS=64
include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH)
@@ -75,22 +67,24 @@ include $(srctree)/$(ARCH_DIR)/Makefile-os-$(OS)
# -Derrno=kernel_errno - This turns all kernel references to errno into
# kernel_errno to separate them from the libc errno. This allows -fno-common
-# in CFLAGS. Otherwise, it would cause ld to complain about the two different
+# in KBUILD_CFLAGS. Otherwise, it would cause ld to complain about the two different
# errnos.
# These apply to kernelspace only.
+#
+# strip leading and trailing whitespace to make the USER_CFLAGS removal of these
+# defines more robust
-KERNEL_DEFINES = -Derrno=kernel_errno -Dsigprocmask=kernel_sigprocmask \
- -Dmktime=kernel_mktime $(ARCH_KERNEL_DEFINES)
-CFLAGS += $(KERNEL_DEFINES)
-CFLAGS += $(call cc-option,-fno-unit-at-a-time,)
+KERNEL_DEFINES = $(strip -Derrno=kernel_errno -Dsigprocmask=kernel_sigprocmask \
+ -Dmktime=kernel_mktime $(ARCH_KERNEL_DEFINES))
+KBUILD_CFLAGS += $(KERNEL_DEFINES)
+KBUILD_CFLAGS += $(call cc-option,-fno-unit-at-a-time,)
# These are needed for clean and mrproper, since in that case .config is not
# included; the values here are meaningless
CONFIG_NEST_LEVEL ?= 0
-CONFIG_KERNEL_HALF_GIGS ?= 0
-SIZE = (($(CONFIG_NEST_LEVEL) + $(CONFIG_KERNEL_HALF_GIGS)) * 0x20000000)
+SIZE = ($(CONFIG_NEST_LEVEL) * 0x20000000)
PHONY += linux
@@ -123,7 +117,6 @@ CFLAGS_NO_HARDENING := $(call cc-option, -fno-PIC,) $(call cc-option, -fno-pic,)
$(call cc-option, -fno-stack-protector,) \
$(call cc-option, -fno-stack-protector-all,)
-CPP_MODE-$(CONFIG_MODE_TT) := -DMODE_TT
CONFIG_KERNEL_STACK_ORDER ?= 2
STACK_SIZE := $(shell echo $$[ 4096 * (1 << $(CONFIG_KERNEL_STACK_ORDER)) ] )
@@ -131,13 +124,10 @@ ifndef START
START = $(shell echo $$[ $(TOP_ADDR) - $(SIZE) ] )
endif
-CPPFLAGS_vmlinux.lds = -U$(SUBARCH) \
- -DSTART=$(START) -DELF_ARCH=$(ELF_ARCH) \
- -DELF_FORMAT="$(ELF_FORMAT)" $(CPP_MODE-y) \
- -DKERNEL_STACK_SIZE=$(STACK_SIZE) \
- -DUNMAP_PATH=arch/um/sys-$(SUBARCH)/unmap.o
+CPPFLAGS_vmlinux.lds = -U$(SUBARCH) -DSTART=$(START) -DELF_ARCH=$(ELF_ARCH) \
+ -DELF_FORMAT="$(ELF_FORMAT)" -DKERNEL_STACK_SIZE=$(STACK_SIZE)
-#The wrappers will select whether using "malloc" or the kernel allocator.
+# The wrappers will select whether using "malloc" or the kernel allocator.
LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc
CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS)
@@ -150,8 +140,8 @@ define cmd_vmlinux__
FORCE ,$^) ; rm -f linux
endef
-#When cleaning we don't include .config, so we don't include
-#TT or skas makefiles and don't clean skas_ptregs.h.
+# When cleaning we don't include .config, so we don't include
+# TT or skas makefiles and don't clean skas_ptregs.h.
CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/include/uml-config.h \
$(ARCH_DIR)/include/user_constants.h \
$(ARCH_DIR)/include/kern_constants.h $(ARCH_DIR)/Kconfig.arch
@@ -178,7 +168,7 @@ ifneq ($(KBUILD_SRC),)
$(Q)mkdir -p $(objtree)/include/asm-um
$(Q)ln -fsn $(srctree)/include/asm-$(HEADER_ARCH) include/asm-um/arch
else
- $(Q)cd $(TOPDIR)/include/asm-um && ln -sf ../asm-$(HEADER_ARCH) arch
+ $(Q)cd $(TOPDIR)/include/asm-um && ln -fsn ../asm-$(SUBARCH) arch
endif
$(objtree)/$(ARCH_DIR)/include:
@@ -190,7 +180,7 @@ $(ARCH_DIR)/include/sysdep: $(objtree)/$(ARCH_DIR)/include
ifneq ($(KBUILD_SRC),)
$(Q)ln -fsn $(srctree)/$(ARCH_DIR)/include/sysdep-$(SUBARCH) $(ARCH_DIR)/include/sysdep
else
- $(Q)cd $(ARCH_DIR)/include && ln -sf sysdep-$(SUBARCH) sysdep
+ $(Q)cd $(ARCH_DIR)/include && ln -fsn sysdep-$(SUBARCH) sysdep
endif
$(ARCH_DIR)/os:
@@ -198,7 +188,7 @@ $(ARCH_DIR)/os:
ifneq ($(KBUILD_SRC),)
$(Q)ln -fsn $(srctree)/$(ARCH_DIR)/os-$(OS) $(ARCH_DIR)/os
else
- $(Q)cd $(ARCH_DIR) && ln -sf os-$(OS) os
+ $(Q)cd $(ARCH_DIR) && ln -fsn os-$(OS) os
endif
# Generated files
diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386
index 60107ed4905b..67290117d909 100644
--- a/arch/um/Makefile-i386
+++ b/arch/um/Makefile-i386
@@ -2,22 +2,19 @@ core-y += arch/um/sys-i386/ arch/x86/crypto/
TOP_ADDR := $(CONFIG_TOP_ADDR)
-ifeq ($(CONFIG_MODE_SKAS),y)
- ifneq ($(CONFIG_MODE_TT),y)
- START := 0x8048000
- endif
-endif
+START := 0x8048000
LDFLAGS += -m elf_i386
ELF_ARCH := $(SUBARCH)
ELF_FORMAT := elf32-$(SUBARCH)
OBJCOPYFLAGS := -O binary -R .note -R .comment -S
HEADER_ARCH := x86
+CHECKFLAGS += -D__i386__
ifeq ("$(origin SUBARCH)", "command line")
ifneq ("$(shell uname -m | sed -e s/i.86/i386/)", "$(SUBARCH)")
-CFLAGS += $(call cc-option,-m32)
-AFLAGS += $(call cc-option,-m32)
+KBUILD_CFLAGS += $(call cc-option,-m32)
+KBUILD_AFLAGS += $(call cc-option,-m32)
LINK-y += $(call cc-option,-m32)
UML_OBJCOPYFLAGS += -F $(ELF_FORMAT)
@@ -25,15 +22,13 @@ export LDFLAGS HOSTCFLAGS HOSTLDFLAGS UML_OBJCOPYFLAGS
endif
endif
-CFLAGS += -DCONFIG_X86_32
-AFLAGS += -DCONFIG_X86_32
+KBUILD_CFLAGS += -DCONFIG_X86_32
+KBUILD_AFLAGS += -DCONFIG_X86_32
CONFIG_X86_32 := y
export CONFIG_X86_32
-ARCH_KERNEL_DEFINES += -U__$(SUBARCH)__ -U$(SUBARCH)
-
# First of all, tune CFLAGS for the specific CPU. This actually sets cflags-y.
-include $(srctree)/arch/i386/Makefile.cpu
+include $(srctree)/arch/x86/Makefile_32.cpu
# prevent gcc from keeping the stack 16 byte aligned. Taken from i386.
cflags-y += $(call cc-option,-mpreferred-stack-boundary=2)
@@ -42,4 +37,4 @@ cflags-y += $(call cc-option,-mpreferred-stack-boundary=2)
# an unresolved reference.
cflags-y += -ffreestanding
-CFLAGS += $(cflags-y)
+KBUILD_CFLAGS += $(cflags-y)
diff --git a/arch/um/Makefile-os-Linux b/arch/um/Makefile-os-Linux
index 0c0f9a1cbbad..52859487c95d 100644
--- a/arch/um/Makefile-os-Linux
+++ b/arch/um/Makefile-os-Linux
@@ -5,4 +5,4 @@
# To get a definition of F_SETSIG
USER_CFLAGS += -D_GNU_SOURCE -D_LARGEFILE64_SOURCE
-CFLAGS += -D_LARGEFILE64_SOURCE
+KBUILD_CFLAGS += -D_LARGEFILE64_SOURCE
diff --git a/arch/um/Makefile-x86_64 b/arch/um/Makefile-x86_64
index 8a00e5f6934c..8ed362f93582 100644
--- a/arch/um/Makefile-x86_64
+++ b/arch/um/Makefile-x86_64
@@ -6,15 +6,12 @@ START := 0x60000000
_extra_flags_ = -fno-builtin -m64
-#We #undef __x86_64__ for kernelspace, not for userspace where
-#it's needed for headers to work!
-ARCH_KERNEL_DEFINES = -U__$(SUBARCH)__
-CFLAGS += $(_extra_flags_)
+KBUILD_CFLAGS += $(_extra_flags_)
-CHECKFLAGS += -m64
-AFLAGS += -m64
+CHECKFLAGS += -m64 -D__x86_64__
+KBUILD_AFLAGS += -m64
LDFLAGS += -m elf_x86_64
-CPPFLAGS += -m64
+KBUILD_CPPFLAGS += -m64
ELF_ARCH := i386:x86-64
ELF_FORMAT := elf64-x86-64
diff --git a/arch/um/defconfig b/arch/um/defconfig
index 1e0f677c2f46..f609edede065 100644
--- a/arch/um/defconfig
+++ b/arch/um/defconfig
@@ -12,9 +12,7 @@ CONFIG_IRQ_RELEASE_METHOD=y
#
# UML-specific options
#
-# CONFIG_MODE_TT is not set
# CONFIG_STATIC_LINK is not set
-CONFIG_MODE_SKAS=y
#
# Host processor type and features
@@ -61,9 +59,6 @@ CONFIG_SEMAPHORE_SLEEPERS=y
# CONFIG_HOST_2G_2G is not set
CONFIG_TOP_ADDR=0xc0000000
# CONFIG_3_LEVEL_PGTABLES is not set
-CONFIG_STUB_CODE=0xbfffe000
-CONFIG_STUB_DATA=0xbffff000
-CONFIG_STUB_START=0xbfffe000
CONFIG_ARCH_HAS_SC_SIGNALS=y
CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA=y
CONFIG_GENERIC_HWEIGHT=y
@@ -75,6 +70,9 @@ CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
CONFIG_LD_SCRIPT_DYN=y
CONFIG_NET=y
CONFIG_BINFMT_ELF=y
@@ -82,11 +80,10 @@ CONFIG_BINFMT_MISC=m
# CONFIG_HOSTFS is not set
# CONFIG_HPPFS is not set
CONFIG_MCONSOLE=y
-# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_MAGIC_SYSRQ=y
CONFIG_NEST_LEVEL=0
# CONFIG_HIGHMEM is not set
CONFIG_KERNEL_STACK_ORDER=0
-CONFIG_UML_REAL_TIME_CLOCK=y
#
# Code maturity level options
diff --git a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile
index de17d4c6e02d..d283e7b022a0 100644
--- a/arch/um/drivers/Makefile
+++ b/arch/um/drivers/Makefile
@@ -17,12 +17,18 @@ ubd-objs := ubd_kern.o ubd_user.o
port-objs := port_kern.o port_user.o
harddog-objs := harddog_kern.o harddog_user.o
-LDFLAGS_pcap.o := -r $(shell $(CC) $(CFLAGS) -print-file-name=libpcap.a)
+LDFLAGS_pcap.o := -r $(shell $(CC) $(KBUILD_CFLAGS) -print-file-name=libpcap.a)
-targets := pcap_kern.o pcap_user.o
+LDFLAGS_vde.o := -r $(shell $(CC) $(CFLAGS) -print-file-name=libvdeplug.a)
+
+targets := pcap_kern.o pcap_user.o vde_kern.o vde_user.o
$(obj)/pcap.o: $(obj)/pcap_kern.o $(obj)/pcap_user.o
$(LD) -r -dp -o $@ $^ $(LDFLAGS) $(LDFLAGS_pcap.o)
+
+$(obj)/vde.o: $(obj)/vde_kern.o $(obj)/vde_user.o
+ $(LD) -r -dp -o $@ $^ $(LDFLAGS) $(LDFLAGS_vde.o)
+
#XXX: The call below does not work because the flags are added before the
# object name, so nothing from the library gets linked.
#$(call if_changed,ld)
@@ -37,6 +43,7 @@ obj-$(CONFIG_STDERR_CONSOLE) += stderr_console.o
obj-$(CONFIG_UML_NET_SLIP) += slip.o slip_common.o
obj-$(CONFIG_UML_NET_SLIRP) += slirp.o slip_common.o
obj-$(CONFIG_UML_NET_DAEMON) += daemon.o
+obj-$(CONFIG_UML_NET_VDE) += vde.o
obj-$(CONFIG_UML_NET_MCAST) += mcast.o
obj-$(CONFIG_UML_NET_PCAP) += pcap.o
obj-$(CONFIG_UML_NET) += net.o
@@ -54,6 +61,6 @@ obj-$(CONFIG_BLK_DEV_COW_COMMON) += cow_user.o
obj-$(CONFIG_UML_RANDOM) += random.o
# pcap_user.o must be added explicitly.
-USER_OBJS := fd.o null.o pty.o tty.o xterm.o slip_common.o pcap_user.o
+USER_OBJS := fd.o null.o pty.o tty.o xterm.o slip_common.o pcap_user.o vde_user.o
include arch/um/scripts/Makefile.rules
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 629b00e3b0b0..db3082b4da46 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -1,28 +1,19 @@
/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
* Licensed under the GPL
*/
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
#include <linux/slab.h>
#include <linux/tty.h>
-#include <linux/string.h>
#include <linux/tty_flip.h>
-#include <asm/irq.h>
#include "chan_kern.h"
-#include "kern.h"
-#include "irq_user.h"
-#include "sigio.h"
-#include "line.h"
#include "os.h"
#ifdef CONFIG_NOCONFIG_CHAN
static void *not_configged_init(char *str, int device,
const struct chan_opts *opts)
{
- printk("Using a channel type which is configured out of "
+ printk(KERN_ERR "Using a channel type which is configured out of "
"UML\n");
return NULL;
}
@@ -30,34 +21,34 @@ static void *not_configged_init(char *str, int device,
static int not_configged_open(int input, int output, int primary, void *data,
char **dev_out)
{
- printk("Using a channel type which is configured out of "
+ printk(KERN_ERR "Using a channel type which is configured out of "
"UML\n");
return -ENODEV;
}
static void not_configged_close(int fd, void *data)
{
- printk("Using a channel type which is configured out of "
+ printk(KERN_ERR "Using a channel type which is configured out of "
"UML\n");
}
static int not_configged_read(int fd, char *c_out, void *data)
{
- printk("Using a channel type which is configured out of "
+ printk(KERN_ERR "Using a channel type which is configured out of "
"UML\n");
return -EIO;
}
static int not_configged_write(int fd, const char *buf, int len, void *data)
{
- printk("Using a channel type which is configured out of "
+ printk(KERN_ERR "Using a channel type which is configured out of "
"UML\n");
return -EIO;
}
static int not_configged_console_write(int fd, const char *buf, int len)
{
- printk("Using a channel type which is configured out of "
+ printk(KERN_ERR "Using a channel type which is configured out of "
"UML\n");
return -EIO;
}
@@ -65,14 +56,14 @@ static int not_configged_console_write(int fd, const char *buf, int len)
static int not_configged_window_size(int fd, void *data, unsigned short *rows,
unsigned short *cols)
{
- printk("Using a channel type which is configured out of "
+ printk(KERN_ERR "Using a channel type which is configured out of "
"UML\n");
return -ENODEV;
}
static void not_configged_free(void *data)
{
- printk("Using a channel type which is configured out of "
+ printk(KERN_ERR "Using a channel type which is configured out of "
"UML\n");
}
@@ -89,64 +80,17 @@ static const struct chan_ops not_configged_ops = {
};
#endif /* CONFIG_NOCONFIG_CHAN */
-void generic_close(int fd, void *unused)
-{
- os_close_file(fd);
-}
-
-int generic_read(int fd, char *c_out, void *unused)
-{
- int n;
-
- n = os_read_file(fd, c_out, sizeof(*c_out));
-
- if(n == -EAGAIN)
- return 0;
- else if(n == 0)
- return -EIO;
- return n;
-}
-
-/* XXX Trivial wrapper around os_write_file */
-
-int generic_write(int fd, const char *buf, int n, void *unused)
-{
- return os_write_file(fd, buf, n);
-}
-
-int generic_window_size(int fd, void *unused, unsigned short *rows_out,
- unsigned short *cols_out)
-{
- int rows, cols;
- int ret;
-
- ret = os_window_size(fd, &rows, &cols);
- if(ret < 0)
- return ret;
-
- ret = ((*rows_out != rows) || (*cols_out != cols));
-
- *rows_out = rows;
- *cols_out = cols;
-
- return ret;
-}
-
-void generic_free(void *data)
-{
- kfree(data);
-}
-
static void tty_receive_char(struct tty_struct *tty, char ch)
{
- if(tty == NULL) return;
+ if (tty == NULL)
+ return;
- if(I_IXON(tty) && !I_IXOFF(tty) && !tty->raw) {
- if(ch == STOP_CHAR(tty)){
+ if (I_IXON(tty) && !I_IXOFF(tty) && !tty->raw) {
+ if (ch == STOP_CHAR(tty)) {
stop_tty(tty);
return;
}
- else if(ch == START_CHAR(tty)){
+ else if (ch == START_CHAR(tty)) {
start_tty(tty);
return;
}
@@ -159,14 +103,14 @@ static int open_one_chan(struct chan *chan)
{
int fd, err;
- if(chan->opened)
+ if (chan->opened)
return 0;
- if(chan->ops->open == NULL)
+ if (chan->ops->open == NULL)
fd = 0;
else fd = (*chan->ops->open)(chan->input, chan->output, chan->primary,
chan->data, &chan->dev);
- if(fd < 0)
+ if (fd < 0)
return fd;
err = os_set_fd_block(fd, 0);
@@ -187,10 +131,10 @@ int open_chan(struct list_head *chans)
struct chan *chan;
int ret, err = 0;
- list_for_each(ele, chans){
+ list_for_each(ele, chans) {
chan = list_entry(ele, struct chan, list);
ret = open_one_chan(chan);
- if(chan->primary)
+ if (chan->primary)
err = ret;
}
return err;
@@ -201,9 +145,9 @@ void chan_enable_winch(struct list_head *chans, struct tty_struct *tty)
struct list_head *ele;
struct chan *chan;
- list_for_each(ele, chans){
+ list_for_each(ele, chans) {
chan = list_entry(ele, struct chan, list);
- if(chan->primary && chan->output && chan->ops->winch){
+ if (chan->primary && chan->output && chan->ops->winch) {
register_winch(chan->fd, tty);
return;
}
@@ -216,7 +160,7 @@ int enable_chan(struct line *line)
struct chan *chan;
int err;
- list_for_each(ele, &line->chan_list){
+ list_for_each(ele, &line->chan_list) {
chan = list_entry(ele, struct chan, list);
err = open_one_chan(chan);
if (err) {
@@ -226,7 +170,7 @@ int enable_chan(struct line *line)
continue;
}
- if(chan->enabled)
+ if (chan->enabled)
continue;
err = line_setup_irq(chan->fd, chan->input, chan->output, line,
chan);
@@ -263,12 +207,12 @@ void free_irqs(void)
list_splice_init(&irqs_to_free, &list);
spin_unlock_irqrestore(&irqs_to_free_lock, flags);
- list_for_each(ele, &list){
+ list_for_each(ele, &list) {
chan = list_entry(ele, struct chan, free_list);
- if(chan->input)
+ if (chan->input)
free_irq(chan->line->driver->read_irq, chan);
- if(chan->output)
+ if (chan->output)
free_irq(chan->line->driver->write_irq, chan);
chan->enabled = 0;
}
@@ -278,22 +222,22 @@ static void close_one_chan(struct chan *chan, int delay_free_irq)
{
unsigned long flags;
- if(!chan->opened)
+ if (!chan->opened)
return;
- if(delay_free_irq){
+ if (delay_free_irq) {
spin_lock_irqsave(&irqs_to_free_lock, flags);
list_add(&chan->free_list, &irqs_to_free);
spin_unlock_irqrestore(&irqs_to_free_lock, flags);
}
else {
- if(chan->input)
+ if (chan->input)
free_irq(chan->line->driver->read_irq, chan);
- if(chan->output)
+ if (chan->output)
free_irq(chan->line->driver->write_irq, chan);
chan->enabled = 0;
}
- if(chan->ops->close != NULL)
+ if (chan->ops->close != NULL)
(*chan->ops->close)(chan->fd, chan->data);
chan->opened = 0;
@@ -322,7 +266,7 @@ void deactivate_chan(struct list_head *chans, int irq)
list_for_each(ele, chans) {
chan = list_entry(ele, struct chan, list);
- if(chan->enabled && chan->input)
+ if (chan->enabled && chan->input)
deactivate_fd(chan->fd, irq);
}
}
@@ -335,7 +279,7 @@ void reactivate_chan(struct list_head *chans, int irq)
list_for_each(ele, chans) {
chan = list_entry(ele, struct chan, list);
- if(chan->enabled && chan->input)
+ if (chan->enabled && chan->input)
reactivate_fd(chan->fd, irq);
}
}
@@ -347,10 +291,14 @@ int write_chan(struct list_head *chans, const char *buf, int len,
struct chan *chan = NULL;
int n, ret = 0;
+ if (len == 0)
+ return 0;
+
list_for_each(ele, chans) {
chan = list_entry(ele, struct chan, list);
if (!chan->output || (chan->ops->write == NULL))
continue;
+
n = chan->ops->write(chan->fd, buf, len, chan->data);
if (chan->primary) {
ret = n;
@@ -367,12 +315,14 @@ int console_write_chan(struct list_head *chans, const char *buf, int len)
struct chan *chan;
int n, ret = 0;
- list_for_each(ele, chans){
+ list_for_each(ele, chans) {
chan = list_entry(ele, struct chan, list);
- if(!chan->output || (chan->ops->console_write == NULL))
+ if (!chan->output || (chan->ops->console_write == NULL))
continue;
+
n = chan->ops->console_write(chan->fd, buf, len);
- if(chan->primary) ret = n;
+ if (chan->primary)
+ ret = n;
}
return ret;
}
@@ -382,10 +332,11 @@ int console_open_chan(struct line *line, struct console *co)
int err;
err = open_chan(&line->chan_list);
- if(err)
+ if (err)
return err;
- printk("Console initialized on /dev/%s%d\n", co->name, co->index);
+ printk(KERN_INFO "Console initialized on /dev/%s%d\n", co->name,
+ co->index);
return 0;
}
@@ -395,10 +346,10 @@ int chan_window_size(struct list_head *chans, unsigned short *rows_out,
struct list_head *ele;
struct chan *chan;
- list_for_each(ele, chans){
+ list_for_each(ele, chans) {
chan = list_entry(ele, struct chan, list);
- if(chan->primary){
- if(chan->ops->window_size == NULL)
+ if (chan->primary) {
+ if (chan->ops->window_size == NULL)
return 0;
return chan->ops->window_size(chan->fd, chan->data,
rows_out, cols_out);
@@ -413,10 +364,11 @@ static void free_one_chan(struct chan *chan, int delay_free_irq)
close_one_chan(chan, delay_free_irq);
- if(chan->ops->free != NULL)
+ if (chan->ops->free != NULL)
(*chan->ops->free)(chan->data);
- if(chan->primary && chan->output) ignore_sigio_fd(chan->fd);
+ if (chan->primary && chan->output)
+ ignore_sigio_fd(chan->fd);
kfree(chan);
}
@@ -425,7 +377,7 @@ static void free_chan(struct list_head *chans, int delay_free_irq)
struct list_head *ele, *next;
struct chan *chan;
- list_for_each_safe(ele, next, chans){
+ list_for_each_safe(ele, next, chans) {
chan = list_entry(ele, struct chan, list);
free_one_chan(chan, delay_free_irq);
}
@@ -436,14 +388,14 @@ static int one_chan_config_string(struct chan *chan, char *str, int size,
{
int n = 0;
- if(chan == NULL){
+ if (chan == NULL) {
CONFIG_CHUNK(str, size, n, "none", 1);
return n;
}
CONFIG_CHUNK(str, size, n, chan->ops->type, 0);
- if(chan->dev == NULL){
+ if (chan->dev == NULL) {
CONFIG_CHUNK(str, size, n, "", 1);
return n;
}
@@ -463,7 +415,7 @@ static int chan_pair_config_string(struct chan *in, struct chan *out,
str += n;
size -= n;
- if(in == out){
+ if (in == out) {
CONFIG_CHUNK(str, size, n, "", 1);
return n;
}
@@ -483,13 +435,13 @@ int chan_config_string(struct list_head *chans, char *str, int size,
struct list_head *ele;
struct chan *chan, *in = NULL, *out = NULL;
- list_for_each(ele, chans){
+ list_for_each(ele, chans) {
chan = list_entry(ele, struct chan, list);
- if(!chan->primary)
+ if (!chan->primary)
continue;
- if(chan->input)
+ if (chan->input)
in = chan;
- if(chan->output)
+ if (chan->output)
out = chan;
}
@@ -548,27 +500,27 @@ static struct chan *parse_chan(struct line *line, char *str, int device,
ops = NULL;
data = NULL;
- for(i = 0; i < ARRAY_SIZE(chan_table); i++){
+ for(i = 0; i < ARRAY_SIZE(chan_table); i++) {
entry = &chan_table[i];
- if(!strncmp(str, entry->key, strlen(entry->key))){
+ if (!strncmp(str, entry->key, strlen(entry->key))) {
ops = entry->ops;
str += strlen(entry->key);
break;
}
}
- if(ops == NULL){
+ if (ops == NULL) {
*error_out = "No match for configured backends";
return NULL;
}
data = (*ops->init)(str, device, opts);
- if(data == NULL){
+ if (data == NULL) {
*error_out = "Configuration failed";
return NULL;
}
chan = kmalloc(sizeof(*chan), GFP_ATOMIC);
- if(chan == NULL){
+ if (chan == NULL) {
*error_out = "Memory allocation failed";
return NULL;
}
@@ -594,26 +546,26 @@ int parse_chan_pair(char *str, struct line *line, int device,
struct chan *new, *chan;
char *in, *out;
- if(!list_empty(chans)){
+ if (!list_empty(chans)) {
chan = list_entry(chans->next, struct chan, list);
free_chan(chans, 0);
INIT_LIST_HEAD(chans);
}
out = strchr(str, ',');
- if(out != NULL){
+ if (out != NULL) {
in = str;
*out = '\0';
out++;
new = parse_chan(line, in, device, opts, error_out);
- if(new == NULL)
+ if (new == NULL)
return -1;
new->input = 1;
list_add(&new->list, chans);
new = parse_chan(line, out, device, opts, error_out);
- if(new == NULL)
+ if (new == NULL)
return -1;
list_add(&new->list, chans);
@@ -621,7 +573,7 @@ int parse_chan_pair(char *str, struct line *line, int device,
}
else {
new = parse_chan(line, str, device, opts, error_out);
- if(new == NULL)
+ if (new == NULL)
return -1;
list_add(&new->list, chans);
@@ -636,9 +588,9 @@ int chan_out_fd(struct list_head *chans)
struct list_head *ele;
struct chan *chan;
- list_for_each(ele, chans){
+ list_for_each(ele, chans) {
chan = list_entry(ele, struct chan, list);
- if(chan->primary && chan->output)
+ if (chan->primary && chan->output)
return chan->fd;
}
return -1;
@@ -652,23 +604,25 @@ void chan_interrupt(struct list_head *chans, struct delayed_work *task,
int err;
char c;
- list_for_each_safe(ele, next, chans){
+ list_for_each_safe(ele, next, chans) {
chan = list_entry(ele, struct chan, list);
- if(!chan->input || (chan->ops->read == NULL)) continue;
+ if (!chan->input || (chan->ops->read == NULL))
+ continue;
do {
if (tty && !tty_buffer_request_room(tty, 1)) {
schedule_delayed_work(task, 1);
goto out;
}
err = chan->ops->read(chan->fd, &c, chan->data);
- if(err > 0)
+ if (err > 0)
tty_receive_char(tty, c);
- } while(err > 0);
+ } while (err > 0);
- if(err == 0) reactivate_fd(chan->fd, irq);
- if(err == -EIO){
- if(chan->primary){
- if(tty != NULL)
+ if (err == 0)
+ reactivate_fd(chan->fd, irq);
+ if (err == -EIO) {
+ if (chan->primary) {
+ if (tty != NULL)
tty_hangup(tty);
close_chan(chans, 1);
return;
@@ -677,5 +631,6 @@ void chan_interrupt(struct list_head *chans, struct delayed_work *task,
}
}
out:
- if(tty) tty_flip_buffer_push(tty);
+ if (tty)
+ tty_flip_buffer_push(tty);
}
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c
index 4d438f36ea2e..b88e93b3a39f 100644
--- a/arch/um/drivers/chan_user.c
+++ b/arch/um/drivers/chan_user.c
@@ -1,51 +1,107 @@
-/*
- * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
+/*
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
* Licensed under the GPL
*/
-#include <unistd.h>
#include <stdlib.h>
+#include <unistd.h>
#include <errno.h>
-#include <termios.h>
-#include <string.h>
-#include <signal.h>
#include <sched.h>
-#include <sys/stat.h>
+#include <signal.h>
+#include <termios.h>
#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include "kern_util.h"
#include "chan_user.h"
-#include "user.h"
#include "os.h"
-#include "choose-mode.h"
-#include "mode.h"
+#include "um_malloc.h"
+#include "user.h"
+
+void generic_close(int fd, void *unused)
+{
+ close(fd);
+}
+
+int generic_read(int fd, char *c_out, void *unused)
+{
+ int n;
+
+ n = read(fd, c_out, sizeof(*c_out));
+ if (n > 0)
+ return n;
+ else if (errno == EAGAIN)
+ return 0;
+ else if (n == 0)
+ return -EIO;
+ return -errno;
+}
+
+/* XXX Trivial wrapper around write */
+
+int generic_write(int fd, const char *buf, int n, void *unused)
+{
+ int err;
+
+ err = write(fd, buf, n);
+ if (err > 0)
+ return err;
+ else if (errno == EAGAIN)
+ return 0;
+ else if (err == 0)
+ return -EIO;
+ return -errno;
+}
+
+int generic_window_size(int fd, void *unused, unsigned short *rows_out,
+ unsigned short *cols_out)
+{
+ struct winsize size;
+ int ret;
+
+ if (ioctl(fd, TIOCGWINSZ, &size) < 0)
+ return -errno;
+
+ ret = ((*rows_out != size.ws_row) || (*cols_out != size.ws_col));
+
+ *rows_out = size.ws_row;
+ *cols_out = size.ws_col;
+
+ return ret;
+}
+
+void generic_free(void *data)
+{
+ kfree(data);
+}
int generic_console_write(int fd, const char *buf, int n)
{
struct termios save, new;
int err;
- if(isatty(fd)){
+ if (isatty(fd)) {
CATCH_EINTR(err = tcgetattr(fd, &save));
if (err)
goto error;
new = save;
- /* The terminal becomes a bit less raw, to handle \n also as
+ /*
+ * The terminal becomes a bit less raw, to handle \n also as
* "Carriage Return", not only as "New Line". Otherwise, the new
- * line won't start at the first column.*/
+ * line won't start at the first column.
+ */
new.c_oflag |= OPOST;
CATCH_EINTR(err = tcsetattr(fd, TCSAFLUSH, &new));
if (err)
goto error;
}
err = generic_write(fd, buf, n, NULL);
- /* Restore raw mode, in any case; we *must* ignore any error apart
- * EINTR, except for debug.*/
- if(isatty(fd))
+ /*
+ * Restore raw mode, in any case; we *must* ignore any error apart
+ * EINTR, except for debug.
+ */
+ if (isatty(fd))
CATCH_EINTR(tcsetattr(fd, TCSAFLUSH, &save));
- return(err);
+ return err;
error:
- return(-errno);
+ return -errno;
}
/*
@@ -82,62 +138,73 @@ static int winch_thread(void *arg)
struct winch_data *data = arg;
sigset_t sigs;
int pty_fd, pipe_fd;
- int count, err;
+ int count;
char c = 1;
pty_fd = data->pty_fd;
pipe_fd = data->pipe_fd;
- count = os_write_file(pipe_fd, &c, sizeof(c));
- if(count != sizeof(c))
- printk("winch_thread : failed to write synchronization "
- "byte, err = %d\n", -count);
+ count = write(pipe_fd, &c, sizeof(c));
+ if (count != sizeof(c))
+ printk(UM_KERN_ERR "winch_thread : failed to write "
+ "synchronization byte, err = %d\n", -count);
- /* We are not using SIG_IGN on purpose, so don't fix it as I thought to
+ /*
+ * We are not using SIG_IGN on purpose, so don't fix it as I thought to
* do! If using SIG_IGN, the sigsuspend() call below would not stop on
- * SIGWINCH. */
+ * SIGWINCH.
+ */
signal(SIGWINCH, winch_handler);
sigfillset(&sigs);
/* Block all signals possible. */
- if(sigprocmask(SIG_SETMASK, &sigs, NULL) < 0){
- printk("winch_thread : sigprocmask failed, errno = %d\n",
- errno);
+ if (sigprocmask(SIG_SETMASK, &sigs, NULL) < 0) {
+ printk(UM_KERN_ERR "winch_thread : sigprocmask failed, "
+ "errno = %d\n", errno);
exit(1);
}
/* In sigsuspend(), block anything else than SIGWINCH. */
sigdelset(&sigs, SIGWINCH);
- if(setsid() < 0){
- printk("winch_thread : setsid failed, errno = %d\n", errno);
+ if (setsid() < 0) {
+ printk(UM_KERN_ERR "winch_thread : setsid failed, errno = %d\n",
+ errno);
+ exit(1);
+ }
+
+ if (ioctl(pty_fd, TIOCSCTTY, 0) < 0) {
+ printk(UM_KERN_ERR "winch_thread : TIOCSCTTY failed on "
+ "fd %d err = %d\n", pty_fd, errno);
exit(1);
}
- err = os_new_tty_pgrp(pty_fd, os_getpid());
- if(err < 0){
- printk("winch_thread : new_tty_pgrp failed on fd %d, "
- "err = %d\n", pty_fd, -err);
+ if (tcsetpgrp(pty_fd, os_getpid()) < 0) {
+ printk(UM_KERN_ERR "winch_thread : tcsetpgrp failed on "
+ "fd %d err = %d\n", pty_fd, errno);
exit(1);
}
- /* These are synchronization calls between various UML threads on the
+ /*
+ * These are synchronization calls between various UML threads on the
* host - since they are not different kernel threads, we cannot use
* kernel semaphores. We don't use SysV semaphores because they are
- * persistent. */
- count = os_read_file(pipe_fd, &c, sizeof(c));
- if(count != sizeof(c))
- printk("winch_thread : failed to read synchronization byte, "
- "err = %d\n", -count);
-
- while(1){
- /* This will be interrupted by SIGWINCH only, since
+ * persistent.
+ */
+ count = read(pipe_fd, &c, sizeof(c));
+ if (count != sizeof(c))
+ printk(UM_KERN_ERR "winch_thread : failed to read "
+ "synchronization byte, err = %d\n", errno);
+
+ while(1) {
+ /*
+ * This will be interrupted by SIGWINCH only, since
* other signals are blocked.
*/
sigsuspend(&sigs);
- count = os_write_file(pipe_fd, &c, sizeof(c));
- if(count != sizeof(c))
- printk("winch_thread : write failed, err = %d\n",
- -count);
+ count = write(pipe_fd, &c, sizeof(c));
+ if (count != sizeof(c))
+ printk(UM_KERN_ERR "winch_thread : write failed, "
+ "err = %d\n", errno);
}
}
@@ -149,44 +216,49 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out,
char c;
err = os_pipe(fds, 1, 1);
- if(err < 0){
- printk("winch_tramp : os_pipe failed, err = %d\n", -err);
+ if (err < 0) {
+ printk(UM_KERN_ERR "winch_tramp : os_pipe failed, err = %d\n",
+ -err);
goto out;
}
data = ((struct winch_data) { .pty_fd = fd,
.pipe_fd = fds[1] } );
- /* CLONE_FILES so this thread doesn't hold open files which are open
+ /*
+ * CLONE_FILES so this thread doesn't hold open files which are open
* now, but later closed in a different thread. This is a
* problem with /dev/net/tun, which if held open by this
* thread, prevents the TUN/TAP device from being reused.
*/
err = run_helper_thread(winch_thread, &data, CLONE_FILES, stack_out);
- if(err < 0){
- printk("fork of winch_thread failed - errno = %d\n", -err);
+ if (err < 0) {
+ printk(UM_KERN_ERR "fork of winch_thread failed - errno = %d\n",
+ -err);
goto out_close;
}
*fd_out = fds[0];
- n = os_read_file(fds[0], &c, sizeof(c));
- if(n != sizeof(c)){
- printk("winch_tramp : failed to read synchronization byte\n");
- printk("read failed, err = %d\n", -n);
- printk("fd %d will not support SIGWINCH\n", fd);
- err = -EINVAL;
+ n = read(fds[0], &c, sizeof(c));
+ if (n != sizeof(c)) {
+ printk(UM_KERN_ERR "winch_tramp : failed to read "
+ "synchronization byte\n");
+ printk(UM_KERN_ERR "read failed, err = %d\n", errno);
+ printk(UM_KERN_ERR "fd %d will not support SIGWINCH\n", fd);
+ err = -EINVAL;
goto out_close;
}
if (os_set_fd_block(*fd_out, 0)) {
- printk("winch_tramp: failed to set thread_fd non-blocking.\n");
+ printk(UM_KERN_ERR "winch_tramp: failed to set thread_fd "
+ "non-blocking.\n");
goto out_close;
}
return err;
out_close:
- os_close_file(fds[1]);
- os_close_file(fds[0]);
+ close(fds[1]);
+ close(fds[0]);
out:
return err;
}
@@ -197,21 +269,20 @@ void register_winch(int fd, struct tty_struct *tty)
int pid, thread, count, thread_fd = -1;
char c = 1;
- if(!isatty(fd))
+ if (!isatty(fd))
return;
pid = tcgetpgrp(fd);
- if (!CHOOSE_MODE_PROC(is_tracer_winch, is_skas_winch, pid, fd, tty) &&
- (pid == -1)) {
+ if (!is_skas_winch(pid, fd, tty) && (pid == -1)) {
thread = winch_tramp(fd, tty, &thread_fd, &stack);
if (thread < 0)
return;
register_winch_irq(thread_fd, fd, thread, tty, stack);
- count = os_write_file(thread_fd, &c, sizeof(c));
- if(count != sizeof(c))
- printk("register_winch : failed to write "
- "synchronization byte, err = %d\n", -count);
+ count = write(thread_fd, &c, sizeof(c));
+ if (count != sizeof(c))
+ printk(UM_KERN_ERR "register_winch : failed to write "
+ "synchronization byte, err = %d\n", errno);
}
}
diff --git a/arch/um/drivers/cow_user.c b/arch/um/drivers/cow_user.c
index 0ec4052db9c5..93f227a25ba4 100644
--- a/arch/um/drivers/cow_user.c
+++ b/arch/um/drivers/cow_user.c
@@ -1,17 +1,18 @@
-#include <stddef.h>
-#include <string.h>
-#include <errno.h>
-/* _XOPEN_SOURCE is needed for pread, but we define _GNU_SOURCE, which defines
+/*
+ * Copyright (C) 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
+ * Licensed under the GPL
+ */
+
+/*
+ * _XOPEN_SOURCE is needed for pread, but we define _GNU_SOURCE, which defines
* that.
*/
#include <unistd.h>
#include <byteswap.h>
-#include <sys/time.h>
-#include <sys/param.h>
-#include <sys/user.h>
-
-#include "os.h"
-
+#include <errno.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <asm/types.h>
#include "cow.h"
#include "cow_sys.h"
@@ -28,7 +29,8 @@ struct cow_header_v1 {
__s32 sectorsize;
} __attribute__((packed));
-/* Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in
+/*
+ * Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in
* case other systems have different values for MAXPATHLEN.
*
* The same must hold for V2 - we want file format compatibility, not anything
@@ -46,7 +48,8 @@ struct cow_header_v2 {
__s32 sectorsize;
} __attribute__((packed));
-/* Changes from V2 -
+/*
+ * Changes from V2 -
* PATH_LEN_V3 as described above
* Explicitly specify field bit lengths for systems with different
* lengths for the usual C types. Not sure whether char or
@@ -70,7 +73,8 @@ struct cow_header_v2 {
* Fixed (finally!) the rounding bug
*/
-/* Until Dec2005, __attribute__((packed)) was left out from the below
+/*
+ * Until Dec2005, __attribute__((packed)) was left out from the below
* definition, leading on 64-bit systems to 4 bytes of padding after mtime, to
* align size to 8-byte alignment. This shifted all fields above (no padding
* was present on 32-bit, no other padding was added).
@@ -122,7 +126,7 @@ void cow_sizes(int version, __u64 size, int sectorsize, int align,
int bitmap_offset, unsigned long *bitmap_len_out,
int *data_offset_out)
{
- if(version < 3){
+ if (version < 3) {
*bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize);
*data_offset_out = bitmap_offset + *bitmap_len_out;
@@ -144,46 +148,46 @@ static int absolutize(char *to, int size, char *from)
char save_cwd[256], *slash;
int remaining;
- if(getcwd(save_cwd, sizeof(save_cwd)) == NULL) {
+ if (getcwd(save_cwd, sizeof(save_cwd)) == NULL) {
cow_printf("absolutize : unable to get cwd - errno = %d\n",
errno);
- return(-1);
+ return -1;
}
slash = strrchr(from, '/');
- if(slash != NULL){
+ if (slash != NULL) {
*slash = '\0';
- if(chdir(from)){
+ if (chdir(from)) {
*slash = '/';
cow_printf("absolutize : Can't cd to '%s' - "
"errno = %d\n", from, errno);
- return(-1);
+ return -1;
}
*slash = '/';
- if(getcwd(to, size) == NULL){
+ if (getcwd(to, size) == NULL) {
cow_printf("absolutize : unable to get cwd of '%s' - "
"errno = %d\n", from, errno);
- return(-1);
+ return -1;
}
remaining = size - strlen(to);
- if(strlen(slash) + 1 > remaining){
+ if (strlen(slash) + 1 > remaining) {
cow_printf("absolutize : unable to fit '%s' into %d "
"chars\n", from, size);
- return(-1);
+ return -1;
}
strcat(to, slash);
}
else {
- if(strlen(save_cwd) + 1 + strlen(from) + 1 > size){
+ if (strlen(save_cwd) + 1 + strlen(from) + 1 > size) {
cow_printf("absolutize : unable to fit '%s' into %d "
"chars\n", from, size);
- return(-1);
+ return -1;
}
strcpy(to, save_cwd);
strcat(to, "/");
strcat(to, from);
}
chdir(save_cwd);
- return(0);
+ return 0;
}
int write_cow_header(char *cow_file, int fd, char *backing_file,
@@ -194,22 +198,23 @@ int write_cow_header(char *cow_file, int fd, char *backing_file,
int err;
err = cow_seek_file(fd, 0);
- if(err < 0){
+ if (err < 0) {
cow_printf("write_cow_header - lseek failed, err = %d\n", -err);
goto out;
}
err = -ENOMEM;
header = cow_malloc(sizeof(*header));
- if(header == NULL){
- cow_printf("write_cow_header - failed to allocate COW V3 header\n");
+ if (header == NULL) {
+ cow_printf("write_cow_header - failed to allocate COW V3 "
+ "header\n");
goto out;
}
header->magic = htonl(COW_MAGIC);
header->version = htonl(COW_VERSION);
err = -EINVAL;
- if(strlen(backing_file) > sizeof(header->backing_file) - 1){
+ if (strlen(backing_file) > sizeof(header->backing_file) - 1) {
/* Below, %zd is for a size_t value */
cow_printf("Backing file name \"%s\" is too long - names are "
"limited to %zd characters\n", backing_file,
@@ -217,12 +222,12 @@ int write_cow_header(char *cow_file, int fd, char *backing_file,
goto out_free;
}
- if(absolutize(header->backing_file, sizeof(header->backing_file),
+ if (absolutize(header->backing_file, sizeof(header->backing_file),
backing_file))
goto out_free;
err = os_file_modtime(header->backing_file, &modtime);
- if(err < 0){
+ if (err < 0) {
cow_printf("write_cow_header - backing file '%s' mtime "
"request failed, err = %d\n", header->backing_file,
-err);
@@ -230,7 +235,7 @@ int write_cow_header(char *cow_file, int fd, char *backing_file,
}
err = cow_file_size(header->backing_file, size);
- if(err < 0){
+ if (err < 0) {
cow_printf("write_cow_header - couldn't get size of "
"backing file '%s', err = %d\n",
header->backing_file, -err);
@@ -244,7 +249,7 @@ int write_cow_header(char *cow_file, int fd, char *backing_file,
header->cow_format = COW_BITMAP;
err = cow_write_file(fd, header, sizeof(*header));
- if(err != sizeof(*header)){
+ if (err != sizeof(*header)) {
cow_printf("write_cow_header - write of header to "
"new COW file '%s' failed, err = %d\n", cow_file,
-err);
@@ -254,14 +259,14 @@ int write_cow_header(char *cow_file, int fd, char *backing_file,
out_free:
cow_free(header);
out:
- return(err);
+ return err;
}
int file_reader(__u64 offset, char *buf, int len, void *arg)
{
int fd = *((int *) arg);
- return(pread(fd, buf, len, offset));
+ return pread(fd, buf, len, offset);
}
/* XXX Need to sanity-check the values read from the header */
@@ -278,31 +283,29 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
unsigned long version, magic;
header = cow_malloc(sizeof(*header));
- if(header == NULL){
+ if (header == NULL) {
cow_printf("read_cow_header - Failed to allocate header\n");
- return(-ENOMEM);
+ return -ENOMEM;
}
err = -EINVAL;
n = (*reader)(0, (char *) header, sizeof(*header), arg);
- if(n < offsetof(typeof(header->v1), backing_file)){
+ if (n < offsetof(typeof(header->v1), backing_file)) {
cow_printf("read_cow_header - short header\n");
goto out;
}
magic = header->v1.magic;
- if(magic == COW_MAGIC) {
+ if (magic == COW_MAGIC)
version = header->v1.version;
- }
- else if(magic == ntohl(COW_MAGIC)){
+ else if (magic == ntohl(COW_MAGIC))
version = ntohl(header->v1.version);
- }
/* No error printed because the non-COW case comes through here */
else goto out;
*version_out = version;
- if(version == 1){
- if(n < sizeof(header->v1)){
+ if (version == 1) {
+ if (n < sizeof(header->v1)) {
cow_printf("read_cow_header - failed to read V1 "
"header\n");
goto out;
@@ -314,8 +317,8 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
*align_out = *sectorsize_out;
file = header->v1.backing_file;
}
- else if(version == 2){
- if(n < sizeof(header->v2)){
+ else if (version == 2) {
+ if (n < sizeof(header->v2)) {
cow_printf("read_cow_header - failed to read V2 "
"header\n");
goto out;
@@ -328,8 +331,8 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
file = header->v2.backing_file;
}
/* This is very subtle - see above at union cow_header definition */
- else if(version == 3 && (*((int*)header->v3.backing_file) != 0)){
- if(n < sizeof(header->v3)){
+ else if (version == 3 && (*((int*)header->v3.backing_file) != 0)) {
+ if (n < sizeof(header->v3)) {
cow_printf("read_cow_header - failed to read V3 "
"header\n");
goto out;
@@ -345,17 +348,18 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
*bitmap_offset_out = ROUND_UP(sizeof(header->v3), *align_out);
file = header->v3.backing_file;
}
- else if(version == 3){
+ else if (version == 3) {
cow_printf("read_cow_header - broken V3 file with"
" 64-bit layout - recovering content.\n");
- if(n < sizeof(header->v3_b)){
+ if (n < sizeof(header->v3_b)) {
cow_printf("read_cow_header - failed to read V3 "
"header\n");
goto out;
}
- /* this was used until Dec2005 - 64bits are needed to represent
+ /*
+ * this was used until Dec2005 - 64bits are needed to represent
* 2038+. I.e. we can safely do this truncating cast.
*
* Additionally, we must use ntohl() instead of ntohll(), since
@@ -381,7 +385,7 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
}
err = -ENOMEM;
*backing_file_out = cow_strdup(file);
- if(*backing_file_out == NULL){
+ if (*backing_file_out == NULL) {
cow_printf("read_cow_header - failed to allocate backing "
"file\n");
goto out;
@@ -389,7 +393,7 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
err = 0;
out:
cow_free(header);
- return(err);
+ return err;
}
int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize,
@@ -402,7 +406,7 @@ int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize,
err = write_cow_header(cow_file, fd, backing_file, sectorsize,
alignment, &size);
- if(err)
+ if (err)
goto out;
*bitmap_offset_out = ROUND_UP(sizeof(struct cow_header_v3), alignment);
@@ -411,17 +415,18 @@ int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize,
offset = *data_offset_out + size - sizeof(zero);
err = cow_seek_file(fd, offset);
- if(err < 0){
+ if (err < 0) {
cow_printf("cow bitmap lseek failed : err = %d\n", -err);
goto out;
}
- /* does not really matter how much we write it is just to set EOF
+ /*
+ * does not really matter how much we write it is just to set EOF
* this also sets the entire COW bitmap
* to zero without having to allocate it
*/
err = cow_write_file(fd, &zero, sizeof(zero));
- if(err != sizeof(zero)){
+ if (err != sizeof(zero)) {
cow_printf("Write of bitmap to new COW file '%s' failed, "
"err = %d\n", cow_file, -err);
if (err >= 0)
@@ -429,15 +434,7 @@ int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize,
goto out;
}
- return(0);
-
+ return 0;
out:
- return(err);
+ return err;
}
-
-/*
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/daemon.h b/arch/um/drivers/daemon.h
index 3bc3cf6b94aa..6e0e891f8a00 100644
--- a/arch/um/drivers/daemon.h
+++ b/arch/um/drivers/daemon.h
@@ -1,8 +1,11 @@
-/*
- * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
+/*
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
+#ifndef __DAEMON_H__
+#define __DAEMON_H__
+
#include "net_user.h"
#define SWITCH_VERSION 3
@@ -20,16 +23,7 @@ struct daemon_data {
extern const struct net_user_info daemon_user_info;
-extern int daemon_user_write(int fd, void *buf, int len,
+extern int daemon_user_write(int fd, void *buf, int len,
struct daemon_data *pri);
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
+#endif
diff --git a/arch/um/drivers/daemon_kern.c b/arch/um/drivers/daemon_kern.c
index adeece11e596..d53ff52bb404 100644
--- a/arch/um/drivers/daemon_kern.c
+++ b/arch/um/drivers/daemon_kern.c
@@ -1,16 +1,14 @@
/*
- * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
* James Leu (jleu@mindspring.net).
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Copyright (C) 2001 by various other people who didn't put their name here.
* Licensed under the GPL.
*/
-#include "linux/kernel.h"
#include "linux/init.h"
-#include "linux/netdevice.h"
-#include "linux/etherdevice.h"
+#include <linux/netdevice.h>
#include "net_kern.h"
-#include "net_user.h"
#include "daemon.h"
struct daemon_init {
@@ -36,25 +34,21 @@ static void daemon_init(struct net_device *dev, void *data)
dpri->data_addr = NULL;
dpri->local_addr = NULL;
- printk("daemon backend (uml_switch version %d) - %s:%s",
+ printk("daemon backend (uml_switch version %d) - %s:%s",
SWITCH_VERSION, dpri->sock_type, dpri->ctl_sock);
printk("\n");
}
-static int daemon_read(int fd, struct sk_buff **skb,
- struct uml_net_private *lp)
+static int daemon_read(int fd, struct sk_buff *skb, struct uml_net_private *lp)
{
- *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER);
- if(*skb == NULL) return(-ENOMEM);
- return(net_recvfrom(fd, skb_mac_header(*skb),
- (*skb)->dev->mtu + ETH_HEADER_OTHER));
+ return net_recvfrom(fd, skb_mac_header(skb),
+ skb->dev->mtu + ETH_HEADER_OTHER);
}
-static int daemon_write(int fd, struct sk_buff **skb,
- struct uml_net_private *lp)
+static int daemon_write(int fd, struct sk_buff *skb, struct uml_net_private *lp)
{
- return(daemon_user_write(fd, (*skb)->data, (*skb)->len,
- (struct daemon_data *) &lp->user));
+ return daemon_user_write(fd, skb->data, skb->len,
+ (struct daemon_data *) &lp->user);
}
static const struct net_kern_info daemon_kern_info = {
@@ -72,14 +66,14 @@ static int daemon_setup(char *str, char **mac_out, void *data)
*init = ((struct daemon_init)
{ .sock_type = "unix",
.ctl_sock = "/tmp/uml.ctl" });
-
+
remain = split_if_spec(str, mac_out, &init->sock_type, &init->ctl_sock,
NULL);
- if(remain != NULL)
+ if (remain != NULL)
printk(KERN_WARNING "daemon_setup : Ignoring data socket "
"specification\n");
-
- return(1);
+
+ return 1;
}
static struct transport daemon_transport = {
diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c
index 8d2008f06682..f23c109a055c 100644
--- a/arch/um/drivers/daemon_user.c
+++ b/arch/um/drivers/daemon_user.c
@@ -1,24 +1,23 @@
/*
- * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
* James Leu (jleu@mindspring.net).
* Copyright (C) 2001 by various other people who didn't put their name here.
* Licensed under the GPL.
*/
-#include <errno.h>
-#include <unistd.h>
#include <stdint.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
#include <sys/socket.h>
-#include <sys/un.h>
#include <sys/time.h>
-#include "net_user.h"
+#include <sys/un.h>
#include "daemon.h"
-#include "kern_util.h"
-#include "user.h"
+#include "net_user.h"
#include "os.h"
#include "um_malloc.h"
-
-#define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER)
+#include "user.h"
enum request_type { REQ_NEW_CONTROL };
@@ -36,8 +35,9 @@ static struct sockaddr_un *new_addr(void *name, int len)
struct sockaddr_un *sun;
sun = kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL);
- if(sun == NULL){
- printk("new_addr: allocation of sockaddr_un failed\n");
+ if (sun == NULL) {
+ printk(UM_KERN_ERR "new_addr: allocation of sockaddr_un "
+ "failed\n");
return NULL;
}
sun->sun_family = AF_UNIX;
@@ -54,38 +54,39 @@ static int connect_to_switch(struct daemon_data *pri)
int fd, n, err;
pri->control = socket(AF_UNIX, SOCK_STREAM, 0);
- if(pri->control < 0){
+ if (pri->control < 0) {
err = -errno;
- printk("daemon_open : control socket failed, errno = %d\n",
- -err);
+ printk(UM_KERN_ERR "daemon_open : control socket failed, "
+ "errno = %d\n", -err);
return err;
}
- if(connect(pri->control, (struct sockaddr *) ctl_addr,
- sizeof(*ctl_addr)) < 0){
+ if (connect(pri->control, (struct sockaddr *) ctl_addr,
+ sizeof(*ctl_addr)) < 0) {
err = -errno;
- printk("daemon_open : control connect failed, errno = %d\n",
- -err);
+ printk(UM_KERN_ERR "daemon_open : control connect failed, "
+ "errno = %d\n", -err);
goto out;
}
fd = socket(AF_UNIX, SOCK_DGRAM, 0);
- if(fd < 0){
+ if (fd < 0) {
err = -errno;
- printk("daemon_open : data socket failed, errno = %d\n",
- -err);
+ printk(UM_KERN_ERR "daemon_open : data socket failed, "
+ "errno = %d\n", -err);
goto out;
}
- if(bind(fd, (struct sockaddr *) local_addr, sizeof(*local_addr)) < 0){
+ if (bind(fd, (struct sockaddr *) local_addr, sizeof(*local_addr)) < 0) {
err = -errno;
- printk("daemon_open : data bind failed, errno = %d\n",
- -err);
+ printk(UM_KERN_ERR "daemon_open : data bind failed, "
+ "errno = %d\n", -err);
goto out_close;
}
sun = kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL);
- if(sun == NULL){
- printk("new_addr: allocation of sockaddr_un failed\n");
+ if (sun == NULL) {
+ printk(UM_KERN_ERR "new_addr: allocation of sockaddr_un "
+ "failed\n");
err = -ENOMEM;
goto out_close;
}
@@ -94,18 +95,18 @@ static int connect_to_switch(struct daemon_data *pri)
req.version = SWITCH_VERSION;
req.type = REQ_NEW_CONTROL;
req.sock = *local_addr;
- n = os_write_file(pri->control, &req, sizeof(req));
- if(n != sizeof(req)){
- printk("daemon_open : control setup request failed, err = %d\n",
- -n);
+ n = write(pri->control, &req, sizeof(req));
+ if (n != sizeof(req)) {
+ printk(UM_KERN_ERR "daemon_open : control setup request "
+ "failed, err = %d\n", -errno);
err = -ENOTCONN;
goto out_free;
}
- n = os_read_file(pri->control, sun, sizeof(*sun));
- if(n != sizeof(*sun)){
- printk("daemon_open : read of data socket failed, err = %d\n",
- -n);
+ n = read(pri->control, sun, sizeof(*sun));
+ if (n != sizeof(*sun)) {
+ printk(UM_KERN_ERR "daemon_open : read of data socket failed, "
+ "err = %d\n", -errno);
err = -ENOTCONN;
goto out_free;
}
@@ -116,9 +117,9 @@ static int connect_to_switch(struct daemon_data *pri)
out_free:
kfree(sun);
out_close:
- os_close_file(fd);
+ close(fd);
out:
- os_close_file(pri->control);
+ close(pri->control);
return err;
}
@@ -132,8 +133,8 @@ static int daemon_user_init(void *data, void *dev)
int usecs;
} name;
- if(!strcmp(pri->sock_type, "unix"))
- pri->ctl_addr = new_addr(pri->ctl_sock,
+ if (!strcmp(pri->sock_type, "unix"))
+ pri->ctl_addr = new_addr(pri->ctl_sock,
strlen(pri->ctl_sock) + 1);
name.zero = 0;
name.pid = os_getpid();
@@ -142,7 +143,7 @@ static int daemon_user_init(void *data, void *dev)
pri->local_addr = new_addr(&name, sizeof(name));
pri->dev = dev;
pri->fd = connect_to_switch(pri);
- if(pri->fd < 0){
+ if (pri->fd < 0) {
kfree(pri->local_addr);
pri->local_addr = NULL;
return pri->fd;
@@ -161,9 +162,9 @@ static void daemon_remove(void *data)
{
struct daemon_data *pri = data;
- os_close_file(pri->fd);
+ close(pri->fd);
pri->fd = -1;
- os_close_file(pri->control);
+ close(pri->control);
pri->control = -1;
kfree(pri->data_addr);
@@ -181,18 +182,13 @@ int daemon_user_write(int fd, void *buf, int len, struct daemon_data *pri)
return net_sendto(fd, buf, len, data_addr, sizeof(*data_addr));
}
-static int daemon_set_mtu(int mtu, void *data)
-{
- return mtu;
-}
-
const struct net_user_info daemon_user_info = {
.init = daemon_user_init,
.open = daemon_open,
.close = NULL,
.remove = daemon_remove,
- .set_mtu = daemon_set_mtu,
.add_address = NULL,
.delete_address = NULL,
- .max_packet = MAX_PACKET - ETH_HEADER_OTHER
+ .mtu = ETH_MAX_PACKET,
+ .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER,
};
diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c
index 39c01ffd45c9..0a2bb5b64b82 100644
--- a/arch/um/drivers/fd.c
+++ b/arch/um/drivers/fd.c
@@ -1,17 +1,18 @@
-/*
- * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
+/*
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
* Licensed under the GPL
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
-#include <termios.h>
#include <errno.h>
-#include "user.h"
+#include <termios.h>
#include "chan_user.h"
+#include "kern_constants.h"
#include "os.h"
#include "um_malloc.h"
+#include "user.h"
struct fd_chan {
int fd;
@@ -26,22 +27,26 @@ static void *fd_init(char *str, int device, const struct chan_opts *opts)
char *end;
int n;
- if(*str != ':'){
- printk("fd_init : channel type 'fd' must specify a file "
- "descriptor\n");
- return(NULL);
+ if (*str != ':') {
+ printk(UM_KERN_ERR "fd_init : channel type 'fd' must specify a "
+ "file descriptor\n");
+ return NULL;
}
str++;
n = strtoul(str, &end, 0);
- if((*end != '\0') || (end == str)){
- printk("fd_init : couldn't parse file descriptor '%s'\n", str);
- return(NULL);
+ if ((*end != '\0') || (end == str)) {
+ printk(UM_KERN_ERR "fd_init : couldn't parse file descriptor "
+ "'%s'\n", str);
+ return NULL;
}
+
data = kmalloc(sizeof(*data), UM_GFP_KERNEL);
- if(data == NULL) return(NULL);
+ if (data == NULL)
+ return NULL;
+
*data = ((struct fd_chan) { .fd = n,
.raw = opts->raw });
- return(data);
+ return data;
}
static int fd_open(int input, int output, int primary, void *d, char **dev_out)
@@ -49,18 +54,18 @@ static int fd_open(int input, int output, int primary, void *d, char **dev_out)
struct fd_chan *data = d;
int err;
- if(data->raw && isatty(data->fd)){
+ if (data->raw && isatty(data->fd)) {
CATCH_EINTR(err = tcgetattr(data->fd, &data->tt));
- if(err)
- return(err);
+ if (err)
+ return err;
err = raw(data->fd);
- if(err)
- return(err);
+ if (err)
+ return err;
}
sprintf(data->str, "%d", data->fd);
*dev_out = data->str;
- return(data->fd);
+ return data->fd;
}
static void fd_close(int fd, void *d)
@@ -68,13 +73,14 @@ static void fd_close(int fd, void *d)
struct fd_chan *data = d;
int err;
- if(data->raw && isatty(fd)){
- CATCH_EINTR(err = tcsetattr(fd, TCSAFLUSH, &data->tt));
- if(err)
- printk("Failed to restore terminal state - "
- "errno = %d\n", -err);
- data->raw = 0;
- }
+ if (!data->raw || !isatty(fd))
+ return;
+
+ CATCH_EINTR(err = tcsetattr(fd, TCSAFLUSH, &data->tt));
+ if (err)
+ printk(UM_KERN_ERR "Failed to restore terminal state - "
+ "errno = %d\n", -err);
+ data->raw = 0;
}
const struct chan_ops fd_ops = {
@@ -89,14 +95,3 @@ const struct chan_ops fd_ops = {
.free = generic_free,
.winch = 1,
};
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/harddog_kern.c b/arch/um/drivers/harddog_kern.c
index 55601687b3bc..a9ad4bd6d953 100644
--- a/arch/um/drivers/harddog_kern.c
+++ b/arch/um/drivers/harddog_kern.c
@@ -69,7 +69,7 @@ static int harddog_open(struct inode *inode, struct file *file)
spin_lock(&lock);
if(timer_alive)
goto err;
-#ifdef CONFIG_HARDDOG_NOWAYOUT
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
__module_get(THIS_MODULE);
#endif
diff --git a/arch/um/drivers/harddog_user.c b/arch/um/drivers/harddog_user.c
index 1171790f742c..b56f8e0196a9 100644
--- a/arch/um/drivers/harddog_user.c
+++ b/arch/um/drivers/harddog_user.c
@@ -1,16 +1,13 @@
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
-#include "user.h"
-#include "mconsole.h"
#include "os.h"
-#include "choose-mode.h"
-#include "mode.h"
+#include "user.h"
struct dog_data {
int stdin;
@@ -25,10 +22,10 @@ static void pre_exec(void *d)
dup2(data->stdin, 0);
dup2(data->stdout, 1);
dup2(data->stdout, 2);
- os_close_file(data->stdin);
- os_close_file(data->stdout);
- os_close_file(data->close_me[0]);
- os_close_file(data->close_me[1]);
+ close(data->stdin);
+ close(data->stdout);
+ close(data->close_me[0]);
+ close(data->close_me[1]);
}
int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock)
@@ -42,13 +39,13 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock)
char **args = NULL;
err = os_pipe(in_fds, 1, 0);
- if(err < 0){
+ if (err < 0) {
printk("harddog_open - os_pipe failed, err = %d\n", -err);
goto out;
}
err = os_pipe(out_fds, 1, 0);
- if(err < 0){
+ if (err < 0) {
printk("harddog_open - os_pipe failed, err = %d\n", -err);
goto out_close_in;
}
@@ -58,37 +55,37 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock)
data.close_me[0] = out_fds[1];
data.close_me[1] = in_fds[0];
- if(sock != NULL){
+ if (sock != NULL) {
mconsole_args[2] = sock;
args = mconsole_args;
}
else {
/* XXX The os_getpid() is not SMP correct */
- sprintf(pid_buf, "%d", CHOOSE_MODE(tracing_pid, os_getpid()));
+ sprintf(pid_buf, "%d", os_getpid());
args = pid_args;
}
pid = run_helper(pre_exec, &data, args);
- os_close_file(out_fds[0]);
- os_close_file(in_fds[1]);
+ close(out_fds[0]);
+ close(in_fds[1]);
- if(pid < 0){
+ if (pid < 0) {
err = -pid;
printk("harddog_open - run_helper failed, errno = %d\n", -err);
goto out_close_out;
}
- n = os_read_file(in_fds[0], &c, sizeof(c));
- if(n == 0){
+ n = read(in_fds[0], &c, sizeof(c));
+ if (n == 0) {
printk("harddog_open - EOF on watchdog pipe\n");
helper_wait(pid);
err = -EIO;
goto out_close_out;
}
- else if(n < 0){
+ else if (n < 0) {
printk("harddog_open - read of watchdog pipe failed, "
- "err = %d\n", -n);
+ "err = %d\n", errno);
helper_wait(pid);
err = n;
goto out_close_out;
@@ -98,19 +95,19 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock)
return 0;
out_close_in:
- os_close_file(in_fds[0]);
- os_close_file(in_fds[1]);
+ close(in_fds[0]);
+ close(in_fds[1]);
out_close_out:
- os_close_file(out_fds[0]);
- os_close_file(out_fds[1]);
+ close(out_fds[0]);
+ close(out_fds[1]);
out:
return err;
}
void stop_watchdog(int in_fd, int out_fd)
{
- os_close_file(in_fd);
- os_close_file(out_fd);
+ close(in_fd);
+ close(out_fd);
}
int ping_watchdog(int fd)
@@ -118,10 +115,11 @@ int ping_watchdog(int fd)
int n;
char c = '\n';
- n = os_write_file(fd, &c, sizeof(c));
- if(n != sizeof(c)){
- printk("ping_watchdog - write failed, err = %d\n", -n);
- if(n < 0)
+ n = write(fd, &c, sizeof(c));
+ if (n != sizeof(c)) {
+ printk("ping_watchdog - write failed, ret = %d, err = %d\n",
+ n, errno);
+ if (n < 0)
return n;
return -EIO;
}
diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c
index 10e08a8c17c3..ff1b22b69e9c 100644
--- a/arch/um/drivers/hostaudio_kern.c
+++ b/arch/um/drivers/hostaudio_kern.c
@@ -1,16 +1,14 @@
-/*
- * Copyright (C) 2002 Steve Schmidtke
+/*
+ * Copyright (C) 2002 Steve Schmidtke
* Licensed under the GPL
*/
+#include "linux/fs.h"
#include "linux/module.h"
-#include "linux/init.h"
#include "linux/slab.h"
-#include "linux/fs.h"
#include "linux/sound.h"
#include "linux/soundcard.h"
#include "asm/uaccess.h"
-#include "kern_util.h"
#include "init.h"
#include "os.h"
@@ -25,7 +23,8 @@ struct hostmixer_state {
#define HOSTAUDIO_DEV_DSP "/dev/sound/dsp"
#define HOSTAUDIO_DEV_MIXER "/dev/sound/mixer"
-/* Changed either at boot time or module load time. At boot, this is
+/*
+ * Changed either at boot time or module load time. At boot, this is
* single-threaded; at module load, multiple modules would each have
* their own copy of these variables.
*/
@@ -44,7 +43,7 @@ static char *mixer = HOSTAUDIO_DEV_MIXER;
static int set_dsp(char *name, int *add)
{
dsp = name;
- return(0);
+ return 0;
}
__uml_setup("dsp=", set_dsp, "dsp=<dsp device>\n" DSP_HELP);
@@ -52,7 +51,7 @@ __uml_setup("dsp=", set_dsp, "dsp=<dsp device>\n" DSP_HELP);
static int set_mixer(char *name, int *add)
{
mixer = name;
- return(0);
+ return 0;
}
__uml_setup("mixer=", set_mixer, "mixer=<mixer device>\n" MIXER_HELP);
@@ -77,23 +76,23 @@ static ssize_t hostaudio_read(struct file *file, char __user *buffer,
int err;
#ifdef DEBUG
- printk("hostaudio: read called, count = %d\n", count);
+ printk(KERN_DEBUG "hostaudio: read called, count = %d\n", count);
#endif
kbuf = kmalloc(count, GFP_KERNEL);
- if(kbuf == NULL)
- return(-ENOMEM);
+ if (kbuf == NULL)
+ return -ENOMEM;
err = os_read_file(state->fd, kbuf, count);
- if(err < 0)
+ if (err < 0)
goto out;
- if(copy_to_user(buffer, kbuf, err))
+ if (copy_to_user(buffer, kbuf, err))
err = -EFAULT;
out:
kfree(kbuf);
- return(err);
+ return err;
}
static ssize_t hostaudio_write(struct file *file, const char __user *buffer,
@@ -104,40 +103,40 @@ static ssize_t hostaudio_write(struct file *file, const char __user *buffer,
int err;
#ifdef DEBUG
- printk("hostaudio: write called, count = %d\n", count);
+ printk(KERN_DEBUG "hostaudio: write called, count = %d\n", count);
#endif
kbuf = kmalloc(count, GFP_KERNEL);
- if(kbuf == NULL)
- return(-ENOMEM);
+ if (kbuf == NULL)
+ return -ENOMEM;
err = -EFAULT;
- if(copy_from_user(kbuf, buffer, count))
+ if (copy_from_user(kbuf, buffer, count))
goto out;
err = os_write_file(state->fd, kbuf, count);
- if(err < 0)
+ if (err < 0)
goto out;
*ppos += err;
out:
kfree(kbuf);
- return(err);
+ return err;
}
-static unsigned int hostaudio_poll(struct file *file,
+static unsigned int hostaudio_poll(struct file *file,
struct poll_table_struct *wait)
{
unsigned int mask = 0;
#ifdef DEBUG
- printk("hostaudio: poll called (unimplemented)\n");
+ printk(KERN_DEBUG "hostaudio: poll called (unimplemented)\n");
#endif
- return(mask);
+ return mask;
}
-static int hostaudio_ioctl(struct inode *inode, struct file *file,
+static int hostaudio_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct hostaudio_state *state = file->private_data;
@@ -145,7 +144,7 @@ static int hostaudio_ioctl(struct inode *inode, struct file *file,
int err;
#ifdef DEBUG
- printk("hostaudio: ioctl called, cmd = %u\n", cmd);
+ printk(KERN_DEBUG "hostaudio: ioctl called, cmd = %u\n", cmd);
#endif
switch(cmd){
case SNDCTL_DSP_SPEED:
@@ -154,8 +153,8 @@ static int hostaudio_ioctl(struct inode *inode, struct file *file,
case SNDCTL_DSP_CHANNELS:
case SNDCTL_DSP_SUBDIVIDE:
case SNDCTL_DSP_SETFRAGMENT:
- if(get_user(data, (int __user *) arg))
- return(-EFAULT);
+ if (get_user(data, (int __user *) arg))
+ return EFAULT;
break;
default:
break;
@@ -170,14 +169,14 @@ static int hostaudio_ioctl(struct inode *inode, struct file *file,
case SNDCTL_DSP_CHANNELS:
case SNDCTL_DSP_SUBDIVIDE:
case SNDCTL_DSP_SETFRAGMENT:
- if(put_user(data, (int __user *) arg))
- return(-EFAULT);
+ if (put_user(data, (int __user *) arg))
+ return -EFAULT;
break;
default:
break;
}
- return(err);
+ return err;
}
static int hostaudio_open(struct inode *inode, struct file *file)
@@ -187,24 +186,26 @@ static int hostaudio_open(struct inode *inode, struct file *file)
int ret;
#ifdef DEBUG
- printk("hostaudio: open called (host: %s)\n", dsp);
+ printk(KERN_DEBUG "hostaudio: open called (host: %s)\n", dsp);
#endif
state = kmalloc(sizeof(struct hostaudio_state), GFP_KERNEL);
- if(state == NULL)
- return(-ENOMEM);
+ if (state == NULL)
+ return -ENOMEM;
- if(file->f_mode & FMODE_READ) r = 1;
- if(file->f_mode & FMODE_WRITE) w = 1;
+ if (file->f_mode & FMODE_READ)
+ r = 1;
+ if (file->f_mode & FMODE_WRITE)
+ w = 1;
ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0);
- if(ret < 0){
+ if (ret < 0) {
kfree(state);
- return(ret);
+ return ret;
}
state->fd = ret;
file->private_data = state;
- return(0);
+ return 0;
}
static int hostaudio_release(struct inode *inode, struct file *file)
@@ -212,26 +213,26 @@ static int hostaudio_release(struct inode *inode, struct file *file)
struct hostaudio_state *state = file->private_data;
#ifdef DEBUG
- printk("hostaudio: release called\n");
+ printk(KERN_DEBUG "hostaudio: release called\n");
#endif
os_close_file(state->fd);
kfree(state);
- return(0);
+ return 0;
}
/* /dev/mixer file operations */
-static int hostmixer_ioctl_mixdev(struct inode *inode, struct file *file,
+static int hostmixer_ioctl_mixdev(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct hostmixer_state *state = file->private_data;
#ifdef DEBUG
- printk("hostmixer: ioctl called\n");
+ printk(KERN_DEBUG "hostmixer: ioctl called\n");
#endif
- return(os_ioctl_generic(state->fd, cmd, arg));
+ return os_ioctl_generic(state->fd, cmd, arg);
}
static int hostmixer_open_mixdev(struct inode *inode, struct file *file)
@@ -241,26 +242,29 @@ static int hostmixer_open_mixdev(struct inode *inode, struct file *file)
int ret;
#ifdef DEBUG
- printk("hostmixer: open called (host: %s)\n", mixer);
+ printk(KERN_DEBUG "hostmixer: open called (host: %s)\n", mixer);
#endif
state = kmalloc(sizeof(struct hostmixer_state), GFP_KERNEL);
- if(state == NULL) return(-ENOMEM);
+ if (state == NULL)
+ return -ENOMEM;
- if(file->f_mode & FMODE_READ) r = 1;
- if(file->f_mode & FMODE_WRITE) w = 1;
+ if (file->f_mode & FMODE_READ)
+ r = 1;
+ if (file->f_mode & FMODE_WRITE)
+ w = 1;
ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0);
-
- if(ret < 0){
- printk("hostaudio_open_mixdev failed to open '%s', err = %d\n",
- dsp, -ret);
+
+ if (ret < 0) {
+ printk(KERN_ERR "hostaudio_open_mixdev failed to open '%s', "
+ "err = %d\n", dsp, -ret);
kfree(state);
- return(ret);
+ return ret;
}
file->private_data = state;
- return(0);
+ return 0;
}
static int hostmixer_release(struct inode *inode, struct file *file)
@@ -268,13 +272,13 @@ static int hostmixer_release(struct inode *inode, struct file *file)
struct hostmixer_state *state = file->private_data;
#ifdef DEBUG
- printk("hostmixer: release called\n");
+ printk(KERN_DEBUG "hostmixer: release called\n");
#endif
os_close_file(state->fd);
kfree(state);
- return(0);
+ return 0;
}
/* kernel module operations */
@@ -314,13 +318,13 @@ static int __init hostaudio_init_module(void)
dsp, mixer);
module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1);
- if(module_data.dev_audio < 0){
+ if (module_data.dev_audio < 0) {
printk(KERN_ERR "hostaudio: couldn't register DSP device!\n");
return -ENODEV;
}
module_data.dev_mixer = register_sound_mixer(&hostmixer_fops, -1);
- if(module_data.dev_mixer < 0){
+ if (module_data.dev_mixer < 0) {
printk(KERN_ERR "hostmixer: couldn't register mixer "
"device!\n");
unregister_sound_dsp(module_data.dev_audio);
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 3e0b68e297f2..83bf15a3dda8 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -1,22 +1,14 @@
/*
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/kernel.h"
-#include "linux/sched.h"
-#include "linux/slab.h"
-#include "linux/list.h"
+#include "linux/irqreturn.h"
#include "linux/kd.h"
-#include "linux/interrupt.h"
-#include "asm/uaccess.h"
#include "chan_kern.h"
+#include "irq_kern.h"
#include "irq_user.h"
-#include "line.h"
-#include "kern.h"
-#include "kern_util.h"
#include "os.h"
-#include "irq_kern.h"
#define LINE_BUFSIZE 4096
@@ -35,14 +27,15 @@ static void line_timer_cb(struct work_struct *work)
{
struct line *line = container_of(work, struct line, task.work);
- if(!line->throttled)
+ if (!line->throttled)
chan_interrupt(&line->chan_list, &line->task, line->tty,
line->driver->read_irq);
}
-/* Returns the free space inside the ring buffer of this line.
+/*
+ * Returns the free space inside the ring buffer of this line.
*
- * Should be called while holding line->lock (this does not modify datas).
+ * Should be called while holding line->lock (this does not modify data).
*/
static int write_room(struct line *line)
{
@@ -107,11 +100,12 @@ static int buffer_data(struct line *line, const char *buf, int len)
{
int end, room;
- if(line->buffer == NULL){
+ if (line->buffer == NULL) {
line->buffer = kmalloc(LINE_BUFSIZE, GFP_ATOMIC);
if (line->buffer == NULL) {
- printk("buffer_data - atomic allocation failed\n");
- return(0);
+ printk(KERN_ERR "buffer_data - atomic allocation "
+ "failed\n");
+ return 0;
}
line->head = line->buffer;
line->tail = line->buffer;
@@ -122,7 +116,7 @@ static int buffer_data(struct line *line, const char *buf, int len)
end = line->buffer + LINE_BUFSIZE - line->tail;
- if (len < end){
+ if (len < end) {
memcpy(line->tail, buf, len);
line->tail += len;
}
@@ -162,8 +156,10 @@ static int flush_buffer(struct line *line)
if (n < 0)
return n;
if (n == count) {
- /* We have flushed from ->head to buffer end, now we
- * must flush only from the beginning to ->tail.*/
+ /*
+ * We have flushed from ->head to buffer end, now we
+ * must flush only from the beginning to ->tail.
+ */
line->head = line->buffer;
} else {
line->head += n;
@@ -175,7 +171,7 @@ static int flush_buffer(struct line *line)
n = write_chan(&line->chan_list, line->head, count,
line->driver->write_irq);
- if(n < 0)
+ if (n < 0)
return n;
line->head += n;
@@ -189,19 +185,18 @@ void line_flush_buffer(struct tty_struct *tty)
int err;
/*XXX: copied from line_write, verify if it is correct!*/
- if(tty->stopped)
+ if (tty->stopped)
return;
spin_lock_irqsave(&line->lock, flags);
err = flush_buffer(line);
- /*if (err == 1)
- err = 0;*/
spin_unlock_irqrestore(&line->lock, flags);
- //return err;
}
-/* We map both ->flush_chars and ->put_char (which go in pair) onto ->flush_buffer
- * and ->write. Hope it's not that bad.*/
+/*
+ * We map both ->flush_chars and ->put_char (which go in pair) onto
+ * ->flush_buffer and ->write. Hope it's not that bad.
+ */
void line_flush_chars(struct tty_struct *tty)
{
line_flush_buffer(tty);
@@ -216,18 +211,15 @@ int line_write(struct tty_struct *tty, const unsigned char *buf, int len)
{
struct line *line = tty->driver_data;
unsigned long flags;
- int n, err, ret = 0;
+ int n, ret = 0;
- if(tty->stopped)
+ if (tty->stopped)
return 0;
spin_lock_irqsave(&line->lock, flags);
- if (line->head != line->tail) {
+ if (line->head != line->tail)
ret = buffer_data(line, buf, len);
- err = flush_buffer(line);
- if (err <= 0 && (err != -EAGAIN || !ret))
- ret = err;
- } else {
+ else {
n = write_chan(&line->chan_list, buf, len,
line->driver->write_irq);
if (n < 0) {
@@ -257,17 +249,17 @@ static const struct {
} tty_ioctls[] = {
/* don't print these, they flood the log ... */
{ TCGETS, NULL, "TCGETS" },
- { TCSETS, NULL, "TCSETS" },
- { TCSETSW, NULL, "TCSETSW" },
- { TCFLSH, NULL, "TCFLSH" },
- { TCSBRK, NULL, "TCSBRK" },
+ { TCSETS, NULL, "TCSETS" },
+ { TCSETSW, NULL, "TCSETSW" },
+ { TCFLSH, NULL, "TCFLSH" },
+ { TCSBRK, NULL, "TCSBRK" },
/* general tty stuff */
- { TCSETSF, KERN_DEBUG, "TCSETSF" },
- { TCGETA, KERN_DEBUG, "TCGETA" },
- { TIOCMGET, KERN_DEBUG, "TIOCMGET" },
- { TCSBRKP, KERN_DEBUG, "TCSBRKP" },
- { TIOCMSET, KERN_DEBUG, "TIOCMSET" },
+ { TCSETSF, KERN_DEBUG, "TCSETSF" },
+ { TCGETA, KERN_DEBUG, "TCGETA" },
+ { TIOCMGET, KERN_DEBUG, "TIOCMGET" },
+ { TCSBRKP, KERN_DEBUG, "TCSBRKP" },
+ { TIOCMSET, KERN_DEBUG, "TIOCMSET" },
/* linux-specific ones */
{ TIOCLINUX, KERN_INFO, "TIOCLINUX" },
@@ -324,12 +316,7 @@ int line_ioctl(struct tty_struct *tty, struct file * file,
for (i = 0; i < ARRAY_SIZE(tty_ioctls); i++)
if (cmd == tty_ioctls[i].cmd)
break;
- if (i < ARRAY_SIZE(tty_ioctls)) {
- if (NULL != tty_ioctls[i].level)
- printk("%s%s: %s: ioctl %s called\n",
- tty_ioctls[i].level, __FUNCTION__,
- tty->name, tty_ioctls[i].name);
- } else {
+ if (i == ARRAY_SIZE(tty_ioctls)) {
printk(KERN_ERR "%s: %s: unknown ioctl: 0x%x\n",
__FUNCTION__, tty->name, cmd);
}
@@ -355,11 +342,12 @@ void line_unthrottle(struct tty_struct *tty)
chan_interrupt(&line->chan_list, &line->task, tty,
line->driver->read_irq);
- /* Maybe there is enough stuff pending that calling the interrupt
+ /*
+ * Maybe there is enough stuff pending that calling the interrupt
* throttles us again. In this case, line->throttled will be 1
* again and we shouldn't turn the interrupt back on.
*/
- if(!line->throttled)
+ if (!line->throttled)
reactivate_chan(&line->chan_list, line->driver->read_irq);
}
@@ -370,27 +358,30 @@ static irqreturn_t line_write_interrupt(int irq, void *data)
struct tty_struct *tty = line->tty;
int err;
- /* Interrupts are disabled here because we registered the interrupt with
- * IRQF_DISABLED (see line_setup_irq).*/
+ /*
+ * Interrupts are disabled here because we registered the interrupt with
+ * IRQF_DISABLED (see line_setup_irq).
+ */
spin_lock(&line->lock);
err = flush_buffer(line);
if (err == 0) {
return IRQ_NONE;
- } else if(err < 0) {
+ } else if (err < 0) {
line->head = line->buffer;
line->tail = line->buffer;
}
spin_unlock(&line->lock);
- if(tty == NULL)
+ if (tty == NULL)
return IRQ_NONE;
if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) &&
(tty->ldisc.write_wakeup != NULL))
(tty->ldisc.write_wakeup)(tty);
- /* BLOCKING mode
+ /*
+ * BLOCKING mode
* In blocking mode, everything sleeps on tty->write_wait.
* Sleeping in the console driver would break non-blocking
* writes.
@@ -420,7 +411,8 @@ int line_setup_irq(int fd, int input, int output, struct line *line, void *data)
return err;
}
-/* Normally, a driver like this can rely mostly on the tty layer
+/*
+ * Normally, a driver like this can rely mostly on the tty layer
* locking, particularly when it comes to the driver structure.
* However, in this case, mconsole requests can come in "from the
* side", and race with opens and closes.
@@ -442,11 +434,11 @@ int line_open(struct line *lines, struct tty_struct *tty)
int err = -ENODEV;
spin_lock(&line->count_lock);
- if(!line->valid)
+ if (!line->valid)
goto out_unlock;
err = 0;
- if(tty->count > 1)
+ if (tty->count > 1)
goto out_unlock;
spin_unlock(&line->count_lock);
@@ -460,7 +452,7 @@ int line_open(struct line *lines, struct tty_struct *tty)
INIT_DELAYED_WORK(&line->task, line_timer_cb);
- if(!line->sigio){
+ if (!line->sigio) {
chan_enable_winch(&line->chan_list, tty);
line->sigio = 1;
}
@@ -481,20 +473,21 @@ void line_close(struct tty_struct *tty, struct file * filp)
{
struct line *line = tty->driver_data;
- /* If line_open fails (and tty->driver_data is never set),
+ /*
+ * If line_open fails (and tty->driver_data is never set),
* tty_open will call line_close. So just return in this case.
*/
- if(line == NULL)
+ if (line == NULL)
return;
/* We ignore the error anyway! */
flush_buffer(line);
spin_lock(&line->count_lock);
- if(!line->valid)
+ if (!line->valid)
goto out_unlock;
- if(tty->count > 1)
+ if (tty->count > 1)
goto out_unlock;
spin_unlock(&line->count_lock);
@@ -502,10 +495,10 @@ void line_close(struct tty_struct *tty, struct file * filp)
line->tty = NULL;
tty->driver_data = NULL;
- if(line->sigio){
+ if (line->sigio) {
unregister_winch(tty);
line->sigio = 0;
- }
+ }
return;
@@ -529,12 +522,12 @@ static int setup_one_line(struct line *lines, int n, char *init, int init_prio,
spin_lock(&line->count_lock);
- if(line->tty != NULL){
+ if (line->tty != NULL) {
*error_out = "Device is already open";
goto out;
}
- if (line->init_pri <= init_prio){
+ if (line->init_pri <= init_prio) {
line->init_pri = init_prio;
if (!strcmp(init, "none"))
line->valid = 0;
@@ -549,7 +542,8 @@ out:
return err;
}
-/* Common setup code for both startup command line and mconsole initialization.
+/*
+ * Common setup code for both startup command line and mconsole initialization.
* @lines contains the array (of size @num) to modify;
* @init is the setup string;
* @error_out is an error string in the case of failure;
@@ -561,14 +555,16 @@ int line_setup(struct line *lines, unsigned int num, char *init,
int i, n, err;
char *end;
- if(*init == '=') {
- /* We said con=/ssl= instead of con#=, so we are configuring all
- * consoles at once.*/
+ if (*init == '=') {
+ /*
+ * We said con=/ssl= instead of con#=, so we are configuring all
+ * consoles at once.
+ */
n = -1;
}
else {
n = simple_strtoul(init, &end, 0);
- if(*end != '='){
+ if (*end != '=') {
*error_out = "Couldn't parse device number";
return -EINVAL;
}
@@ -580,16 +576,16 @@ int line_setup(struct line *lines, unsigned int num, char *init,
*error_out = "Device number out of range";
return -EINVAL;
}
- else if (n >= 0){
+ else if (n >= 0) {
err = setup_one_line(lines, n, init, INIT_ONE, error_out);
- if(err)
+ if (err)
return err;
}
else {
- for(i = 0; i < num; i++){
+ for(i = 0; i < num; i++) {
err = setup_one_line(lines, i, init, INIT_ALL,
error_out);
- if(err)
+ if (err)
return err;
}
}
@@ -603,18 +599,18 @@ int line_config(struct line *lines, unsigned int num, char *str,
char *new;
int n;
- if(*str == '='){
+ if (*str == '=') {
*error_out = "Can't configure all devices from mconsole";
return -EINVAL;
}
new = kstrdup(str, GFP_KERNEL);
- if(new == NULL){
+ if (new == NULL) {
*error_out = "Failed to allocate memory";
return -ENOMEM;
}
n = line_setup(lines, num, new, error_out);
- if(n < 0)
+ if (n < 0)
return n;
line = &lines[n];
@@ -629,12 +625,12 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
int dev, n = 0;
dev = simple_strtoul(name, &end, 0);
- if((*end != '\0') || (end == name)){
+ if ((*end != '\0') || (end == name)) {
*error_out = "line_get_config failed to parse device number";
return 0;
}
- if((dev < 0) || (dev >= num)){
+ if ((dev < 0) || (dev >= num)) {
*error_out = "device number out of range";
return 0;
}
@@ -642,9 +638,9 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
line = &lines[dev];
spin_lock(&line->count_lock);
- if(!line->valid)
+ if (!line->valid)
CONFIG_CHUNK(str, size, n, "none", 1);
- else if(line->tty == NULL)
+ else if (line->tty == NULL)
CONFIG_CHUNK(str, size, n, line->init_str, 1);
else n = chan_config_string(&line->chan_list, str, size, error_out);
spin_unlock(&line->count_lock);
@@ -655,16 +651,16 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
int line_id(char **str, int *start_out, int *end_out)
{
char *end;
- int n;
+ int n;
n = simple_strtoul(*str, &end, 0);
- if((*end != '\0') || (end == *str))
- return -1;
+ if ((*end != '\0') || (end == *str))
+ return -1;
- *str = end;
- *start_out = n;
- *end_out = n;
- return n;
+ *str = end;
+ *start_out = n;
+ *end_out = n;
+ return n;
}
int line_remove(struct line *lines, unsigned int num, int n, char **error_out)
@@ -674,7 +670,7 @@ int line_remove(struct line *lines, unsigned int num, int n, char **error_out)
sprintf(config, "%d=none", n);
err = line_setup(lines, num, config, error_out);
- if(err >= 0)
+ if (err >= 0)
err = 0;
return err;
}
@@ -700,14 +696,14 @@ struct tty_driver *register_lines(struct line_driver *line_driver,
tty_set_operations(driver, ops);
if (tty_register_driver(driver)) {
- printk("%s: can't register %s driver\n",
- __FUNCTION__,line_driver->name);
+ printk(KERN_ERR "register_lines : can't register %s driver\n",
+ line_driver->name);
put_tty_driver(driver);
return NULL;
}
- for(i = 0; i < nlines; i++){
- if(!lines[i].valid)
+ for(i = 0; i < nlines; i++) {
+ if (!lines[i].valid)
tty_unregister_device(driver, i);
}
@@ -724,20 +720,20 @@ void lines_init(struct line *lines, int nlines, struct chan_opts *opts)
char *error;
int i;
- for(i = 0; i < nlines; i++){
+ for(i = 0; i < nlines; i++) {
line = &lines[i];
INIT_LIST_HEAD(&line->chan_list);
- if(line->init_str == NULL)
+ if (line->init_str == NULL)
continue;
line->init_str = kstrdup(line->init_str, GFP_KERNEL);
- if(line->init_str == NULL)
- printk("lines_init - kstrdup returned NULL\n");
+ if (line->init_str == NULL)
+ printk(KERN_ERR "lines_init - kstrdup returned NULL\n");
- if(parse_chan_pair(line->init_str, line, i, opts, &error)){
- printk("parse_chan_pair failed for device %d : %s\n",
- i, error);
+ if (parse_chan_pair(line->init_str, line, i, opts, &error)) {
+ printk(KERN_ERR "parse_chan_pair failed for "
+ "device %d : %s\n", i, error);
line->valid = 0;
}
}
@@ -775,14 +771,14 @@ static irqreturn_t winch_interrupt(int irq, void *data)
int err;
char c;
- if(winch->fd != -1){
+ if (winch->fd != -1) {
err = generic_read(winch->fd, &c, NULL);
- if(err < 0){
- if(err != -EAGAIN){
- printk("winch_interrupt : read failed, "
- "errno = %d\n", -err);
- printk("fd %d is losing SIGWINCH support\n",
- winch->tty_fd);
+ if (err < 0) {
+ if (err != -EAGAIN) {
+ printk(KERN_ERR "winch_interrupt : "
+ "read failed, errno = %d\n", -err);
+ printk(KERN_ERR "fd %d is losing SIGWINCH "
+ "support\n", winch->tty_fd);
free_winch(winch, 0);
return IRQ_HANDLED;
}
@@ -797,7 +793,7 @@ static irqreturn_t winch_interrupt(int irq, void *data)
kill_pgrp(tty->pgrp, SIGWINCH, 1);
}
out:
- if(winch->fd != -1)
+ if (winch->fd != -1)
reactivate_fd(winch->fd, WINCH_IRQ);
return IRQ_HANDLED;
}
@@ -809,7 +805,7 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty,
winch = kmalloc(sizeof(*winch), GFP_KERNEL);
if (winch == NULL) {
- printk("register_winch_irq - kmalloc failed\n");
+ printk(KERN_ERR "register_winch_irq - kmalloc failed\n");
goto cleanup;
}
@@ -823,7 +819,8 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty,
if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
"winch", winch) < 0) {
- printk("register_winch_irq - failed to register IRQ\n");
+ printk(KERN_ERR "register_winch_irq - failed to register "
+ "IRQ\n");
goto out_free;
}
@@ -849,13 +846,13 @@ static void unregister_winch(struct tty_struct *tty)
spin_lock(&winch_handler_lock);
- list_for_each(ele, &winch_handlers){
+ list_for_each(ele, &winch_handlers) {
winch = list_entry(ele, struct winch, list);
- if(winch->tty == tty){
+ if (winch->tty == tty) {
free_winch(winch, 1);
break;
- }
- }
+ }
+ }
spin_unlock(&winch_handler_lock);
}
@@ -866,7 +863,7 @@ static void winch_cleanup(void)
spin_lock(&winch_handler_lock);
- list_for_each_safe(ele, next, &winch_handlers){
+ list_for_each_safe(ele, next, &winch_handlers) {
winch = list_entry(ele, struct winch, list);
free_winch(winch, 1);
}
@@ -881,13 +878,13 @@ char *add_xterm_umid(char *base)
int len;
umid = get_umid();
- if(*umid == '\0')
+ if (*umid == '\0')
return base;
len = strlen(base) + strlen(" ()") + strlen(umid) + 1;
title = kmalloc(len, GFP_KERNEL);
- if(title == NULL){
- printk("Failed to allocate buffer for xterm title\n");
+ if (title == NULL) {
+ printk(KERN_ERR "Failed to allocate buffer for xterm title\n");
return base;
}
diff --git a/arch/um/drivers/mcast.h b/arch/um/drivers/mcast.h
index bc56af9d3e53..6fa282e896be 100644
--- a/arch/um/drivers/mcast.h
+++ b/arch/um/drivers/mcast.h
@@ -1,8 +1,11 @@
/*
- * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
+#ifndef __DRIVERS_MCAST_H
+#define __DRIVERS_MCAST_H
+
#include "net_user.h"
struct mcast_data {
@@ -18,13 +21,4 @@ extern const struct net_user_info mcast_user_info;
extern int mcast_user_write(int fd, void *buf, int len,
struct mcast_data *pri);
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
+#endif
diff --git a/arch/um/drivers/mcast_kern.c b/arch/um/drivers/mcast_kern.c
index e6b8e0dd72a8..822092f149be 100644
--- a/arch/um/drivers/mcast_kern.c
+++ b/arch/um/drivers/mcast_kern.c
@@ -1,24 +1,20 @@
/*
* user-mode-linux networking multicast transport
* Copyright (C) 2001 by Harald Welte <laforge@gnumonks.org>
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
*
* based on the existing uml-networking code, which is
- * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
* James Leu (jleu@mindspring.net).
* Copyright (C) 2001 by various other people who didn't put their name here.
*
* Licensed under the GPL.
*/
-#include "linux/kernel.h"
#include "linux/init.h"
-#include "linux/netdevice.h"
-#include "linux/etherdevice.h"
-#include "linux/in.h"
-#include "linux/inet.h"
-#include "net_kern.h"
-#include "net_user.h"
+#include <linux/netdevice.h>
#include "mcast.h"
+#include "net_kern.h"
struct mcast_init {
char *addr;
@@ -39,26 +35,20 @@ static void mcast_init(struct net_device *dev, void *data)
dpri->ttl = init->ttl;
dpri->dev = dev;
- printk("mcast backend ");
- printk("multicast address: %s:%u, TTL:%u ",
+ printk("mcast backend multicast address: %s:%u, TTL:%u\n",
dpri->addr, dpri->port, dpri->ttl);
-
- printk("\n");
}
-static int mcast_read(int fd, struct sk_buff **skb, struct uml_net_private *lp)
+static int mcast_read(int fd, struct sk_buff *skb, struct uml_net_private *lp)
{
- *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER);
- if(*skb == NULL) return(-ENOMEM);
- return(net_recvfrom(fd, skb_mac_header(*skb),
- (*skb)->dev->mtu + ETH_HEADER_OTHER));
+ return net_recvfrom(fd, skb_mac_header(skb),
+ skb->dev->mtu + ETH_HEADER_OTHER);
}
-static int mcast_write(int fd, struct sk_buff **skb,
- struct uml_net_private *lp)
+static int mcast_write(int fd, struct sk_buff *skb, struct uml_net_private *lp)
{
- return mcast_user_write(fd, (*skb)->data, (*skb)->len,
- (struct mcast_data *) &lp->user);
+ return mcast_user_write(fd, skb->data, skb->len,
+ (struct mcast_data *) &lp->user);
}
static const struct net_kern_info mcast_kern_info = {
@@ -81,34 +71,34 @@ int mcast_setup(char *str, char **mac_out, void *data)
remain = split_if_spec(str, mac_out, &init->addr, &port_str, &ttl_str,
NULL);
- if(remain != NULL){
+ if (remain != NULL) {
printk(KERN_ERR "mcast_setup - Extra garbage on "
"specification : '%s'\n", remain);
- return(0);
+ return 0;
}
-
- if(port_str != NULL){
+
+ if (port_str != NULL) {
init->port = simple_strtoul(port_str, &last, 10);
- if((*last != '\0') || (last == port_str)){
- printk(KERN_ERR "mcast_setup - Bad port : '%s'\n",
+ if ((*last != '\0') || (last == port_str)) {
+ printk(KERN_ERR "mcast_setup - Bad port : '%s'\n",
port_str);
- return(0);
+ return 0;
}
}
- if(ttl_str != NULL){
+ if (ttl_str != NULL) {
init->ttl = simple_strtoul(ttl_str, &last, 10);
- if((*last != '\0') || (last == ttl_str)){
- printk(KERN_ERR "mcast_setup - Bad ttl : '%s'\n",
+ if ((*last != '\0') || (last == ttl_str)) {
+ printk(KERN_ERR "mcast_setup - Bad ttl : '%s'\n",
ttl_str);
- return(0);
+ return 0;
}
}
printk(KERN_INFO "Configured mcast device: %s:%u-%u\n", init->addr,
init->port, init->ttl);
- return(1);
+ return 1;
}
static struct transport mcast_transport = {
diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c
index 236a3dfc297d..5f647d7a7292 100644
--- a/arch/um/drivers/mcast_user.c
+++ b/arch/um/drivers/mcast_user.c
@@ -1,9 +1,10 @@
/*
* user-mode-linux networking multicast transport
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Copyright (C) 2001 by Harald Welte <laforge@gnumonks.org>
*
* based on the existing uml-networking code, which is
- * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
* James Leu (jleu@mindspring.net).
* Copyright (C) 2001 by various other people who didn't put their name here.
*
@@ -11,28 +12,22 @@
*
*/
-#include <errno.h>
#include <unistd.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/time.h>
+#include <errno.h>
#include <netinet/in.h>
-#include "net_user.h"
#include "mcast.h"
-#include "kern_util.h"
-#include "user.h"
-#include "os.h"
+#include "net_user.h"
#include "um_malloc.h"
-
-#define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER)
+#include "user.h"
static struct sockaddr_in *new_addr(char *addr, unsigned short port)
{
struct sockaddr_in *sin;
sin = kmalloc(sizeof(struct sockaddr_in), UM_GFP_KERNEL);
- if(sin == NULL){
- printk("new_addr: allocation of sockaddr_in failed\n");
+ if (sin == NULL) {
+ printk(UM_KERN_ERR "new_addr: allocation of sockaddr_in "
+ "failed\n");
return NULL;
}
sin->sin_family = AF_INET;
@@ -71,17 +66,17 @@ static int mcast_open(void *data)
fd = socket(AF_INET, SOCK_DGRAM, 0);
- if (fd < 0){
+ if (fd < 0) {
err = -errno;
- printk("mcast_open : data socket failed, errno = %d\n",
- errno);
+ printk(UM_KERN_ERR "mcast_open : data socket failed, "
+ "errno = %d\n", errno);
goto out;
}
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
err = -errno;
- printk("mcast_open: SO_REUSEADDR failed, errno = %d\n",
- errno);
+ printk(UM_KERN_ERR "mcast_open: SO_REUSEADDR failed, "
+ "errno = %d\n", errno);
goto out_close;
}
@@ -89,45 +84,46 @@ static int mcast_open(void *data)
if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &pri->ttl,
sizeof(pri->ttl)) < 0) {
err = -errno;
- printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n",
- errno);
+ printk(UM_KERN_ERR "mcast_open: IP_MULTICAST_TTL failed, "
+ "error = %d\n", errno);
goto out_close;
}
/* set LOOP, so data does get fed back to local sockets */
if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) {
err = -errno;
- printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n",
- errno);
+ printk(UM_KERN_ERR "mcast_open: IP_MULTICAST_LOOP failed, "
+ "error = %d\n", errno);
goto out_close;
}
/* bind socket to mcast address */
if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) {
err = -errno;
- printk("mcast_open : data bind failed, errno = %d\n", errno);
+ printk(UM_KERN_ERR "mcast_open : data bind failed, "
+ "errno = %d\n", errno);
goto out_close;
}
/* subscribe to the multicast group */
mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr;
mreq.imr_interface.s_addr = 0;
- if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP,
+ if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP,
&mreq, sizeof(mreq)) < 0) {
err = -errno;
- printk("mcast_open: IP_ADD_MEMBERSHIP failed, error = %d\n",
- errno);
- printk("There appears not to be a multicast-capable network "
- "interface on the host.\n");
- printk("eth0 should be configured in order to use the "
- "multicast transport.\n");
+ printk(UM_KERN_ERR "mcast_open: IP_ADD_MEMBERSHIP failed, "
+ "error = %d\n", errno);
+ printk(UM_KERN_ERR "There appears not to be a multicast-"
+ "capable network interface on the host.\n");
+ printk(UM_KERN_ERR "eth0 should be configured in order to use "
+ "the multicast transport.\n");
goto out_close;
}
return fd;
out_close:
- os_close_file(fd);
+ close(fd);
out:
return err;
}
@@ -142,11 +138,11 @@ static void mcast_close(int fd, void *data)
mreq.imr_interface.s_addr = 0;
if (setsockopt(fd, SOL_IP, IP_DROP_MEMBERSHIP,
&mreq, sizeof(mreq)) < 0) {
- printk("mcast_open: IP_DROP_MEMBERSHIP failed, error = %d\n",
- errno);
+ printk(UM_KERN_ERR "mcast_open: IP_DROP_MEMBERSHIP failed, "
+ "error = %d\n", errno);
}
- os_close_file(fd);
+ close(fd);
}
int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri)
@@ -156,18 +152,13 @@ int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri)
return net_sendto(fd, buf, len, data_addr, sizeof(*data_addr));
}
-static int mcast_set_mtu(int mtu, void *data)
-{
- return mtu;
-}
-
const struct net_user_info mcast_user_info = {
.init = mcast_user_init,
.open = mcast_open,
.close = mcast_close,
.remove = mcast_remove,
- .set_mtu = mcast_set_mtu,
.add_address = NULL,
.delete_address = NULL,
- .max_packet = MAX_PACKET - ETH_HEADER_OTHER
+ .mtu = ETH_MAX_PACKET,
+ .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER,
};
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index d87090507401..0f3c7d14a6e3 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -1,44 +1,35 @@
/*
* Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org)
- * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/kernel.h"
-#include "linux/slab.h"
-#include "linux/init.h"
-#include "linux/notifier.h"
-#include "linux/reboot.h"
-#include "linux/utsname.h"
+#include "linux/console.h"
#include "linux/ctype.h"
#include "linux/interrupt.h"
-#include "linux/sysrq.h"
-#include "linux/workqueue.h"
+#include "linux/list.h"
+#include "linux/mm.h"
#include "linux/module.h"
-#include "linux/file.h"
-#include "linux/fs.h"
-#include "linux/namei.h"
+#include "linux/notifier.h"
+#include "linux/reboot.h"
#include "linux/proc_fs.h"
+#include "linux/slab.h"
#include "linux/syscalls.h"
-#include "linux/list.h"
-#include "linux/mm.h"
-#include "linux/console.h"
-#include "asm/irq.h"
+#include "linux/utsname.h"
+#include "linux/workqueue.h"
#include "asm/uaccess.h"
+#include "init.h"
+#include "irq_kern.h"
+#include "irq_user.h"
#include "kern_util.h"
-#include "kern.h"
#include "mconsole.h"
#include "mconsole_kern.h"
-#include "irq_user.h"
-#include "init.h"
#include "os.h"
-#include "irq_kern.h"
-#include "choose-mode.h"
static int do_unlink_socket(struct notifier_block *notifier,
unsigned long what, void *data)
{
- return(mconsole_unlink_socket());
+ return mconsole_unlink_socket();
}
@@ -59,10 +50,9 @@ static void mc_work_proc(struct work_struct *unused)
struct mconsole_entry *req;
unsigned long flags;
- while(!list_empty(&mc_requests)){
+ while (!list_empty(&mc_requests)) {
local_irq_save(flags);
- req = list_entry(mc_requests.next, struct mconsole_entry,
- list);
+ req = list_entry(mc_requests.next, struct mconsole_entry, list);
list_del(&req->list);
local_irq_restore(flags);
req->request.cmd->handler(&req->request);
@@ -80,12 +70,12 @@ static irqreturn_t mconsole_interrupt(int irq, void *dev_id)
static struct mc_request req; /* that's OK */
fd = (long) dev_id;
- while (mconsole_get_request(fd, &req)){
- if(req.cmd->context == MCONSOLE_INTR)
+ while (mconsole_get_request(fd, &req)) {
+ if (req.cmd->context == MCONSOLE_INTR)
(*req.cmd->handler)(&req);
else {
new = kmalloc(sizeof(*new), GFP_NOWAIT);
- if(new == NULL)
+ if (new == NULL)
mconsole_reply(&req, "Out of memory", 1, 0);
else {
new->request = req;
@@ -94,10 +84,10 @@ static irqreturn_t mconsole_interrupt(int irq, void *dev_id)
}
}
}
- if(!list_empty(&mc_requests))
+ if (!list_empty(&mc_requests))
schedule_work(&mconsole_work);
reactivate_fd(fd, MCONSOLE_IRQ);
- return(IRQ_HANDLED);
+ return IRQ_HANDLED;
}
void mconsole_version(struct mc_request *req)
@@ -105,8 +95,8 @@ void mconsole_version(struct mc_request *req)
char version[256];
sprintf(version, "%s %s %s %s %s", utsname()->sysname,
- utsname()->nodename, utsname()->release,
- utsname()->version, utsname()->machine);
+ utsname()->nodename, utsname()->release, utsname()->version,
+ utsname()->machine);
mconsole_reply(req, version, 0, 0);
}
@@ -118,7 +108,7 @@ void mconsole_log(struct mc_request *req)
ptr += strlen("log ");
len = req->len - (ptr - req->request.data);
- printk("%.*s", len, ptr);
+ printk(KERN_WARNING "%.*s", len, ptr);
mconsole_reply(req, "", 0, 0);
}
@@ -137,17 +127,17 @@ void mconsole_proc(struct mc_request *req)
char *ptr = req->request.data, *buf;
ptr += strlen("proc");
- while(isspace(*ptr)) ptr++;
+ while (isspace(*ptr)) ptr++;
proc = get_fs_type("proc");
- if(proc == NULL){
+ if (proc == NULL) {
mconsole_reply(req, "procfs not registered", 1, 0);
goto out;
}
super = (*proc->get_sb)(proc, 0, NULL, NULL);
put_filesystem(proc);
- if(super == NULL){
+ if (super == NULL) {
mconsole_reply(req, "Failed to get procfs superblock", 1, 0);
goto out;
}
@@ -162,29 +152,29 @@ void mconsole_proc(struct mc_request *req)
* if commenting out these two calls + the below read cycle. To
* make UML crash again, it was enough to readd either one.*/
err = link_path_walk(ptr, &nd);
- if(err){
+ if (err) {
mconsole_reply(req, "Failed to look up file", 1, 0);
goto out_kill;
}
file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
- if(IS_ERR(file)){
+ if (IS_ERR(file)) {
mconsole_reply(req, "Failed to open file", 1, 0);
goto out_kill;
}
/*END*/
buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
- if(buf == NULL){
+ if (buf == NULL) {
mconsole_reply(req, "Failed to allocate buffer", 1, 0);
goto out_fput;
}
- if((file->f_op != NULL) && (file->f_op->read != NULL)){
+ if ((file->f_op != NULL) && (file->f_op->read != NULL)) {
do {
n = (*file->f_op->read)(file, buf, PAGE_SIZE - 1,
&file->f_pos);
- if(n >= 0){
+ if (n >= 0) {
buf[n] = '\0';
mconsole_reply(req, buf, 0, (n > 0));
}
@@ -193,7 +183,7 @@ void mconsole_proc(struct mc_request *req)
1, 0);
goto out_free;
}
- } while(n > 0);
+ } while (n > 0);
}
else mconsole_reply(req, "", 0, 0);
@@ -217,18 +207,19 @@ void mconsole_proc(struct mc_request *req)
char *ptr = req->request.data;
ptr += strlen("proc");
- while(isspace(*ptr)) ptr++;
+ while (isspace(*ptr))
+ ptr++;
snprintf(path, sizeof(path), "/proc/%s", ptr);
fd = sys_open(path, 0, 0);
if (fd < 0) {
mconsole_reply(req, "Failed to open file", 1, 0);
- printk("open %s: %d\n",path,fd);
+ printk(KERN_ERR "open %s: %d\n",path,fd);
goto out;
}
buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
- if(buf == NULL){
+ if (buf == NULL) {
mconsole_reply(req, "Failed to allocate buffer", 1, 0);
goto out_close;
}
@@ -239,7 +230,7 @@ void mconsole_proc(struct mc_request *req)
mconsole_reply(req, "Read of file failed", 1, 0);
goto out_free;
}
- /*Begin the file content on his own line.*/
+ /* Begin the file content on his own line. */
if (first_chunk) {
mconsole_reply(req, "\n", 0, 1);
first_chunk = 0;
@@ -351,12 +342,12 @@ static struct mc_device *mconsole_find_dev(char *name)
struct list_head *ele;
struct mc_device *dev;
- list_for_each(ele, &mconsole_devices){
+ list_for_each(ele, &mconsole_devices) {
dev = list_entry(ele, struct mc_device, list);
- if(!strncmp(name, dev->name, strlen(dev->name)))
- return(dev);
+ if (!strncmp(name, dev->name, strlen(dev->name)))
+ return dev;
}
- return(NULL);
+ return NULL;
}
#define UNPLUGGED_PER_PAGE \
@@ -378,15 +369,15 @@ static int mem_config(char *str, char **error_out)
int err = -EINVAL, i, add;
char *ret;
- if(str[0] != '='){
+ if (str[0] != '=') {
*error_out = "Expected '=' after 'mem'";
goto out;
}
str++;
- if(str[0] == '-')
+ if (str[0] == '-')
add = 0;
- else if(str[0] == '+'){
+ else if (str[0] == '+') {
add = 1;
}
else {
@@ -396,7 +387,7 @@ static int mem_config(char *str, char **error_out)
str++;
diff = memparse(str, &ret);
- if(*ret != '\0'){
+ if (*ret != '\0') {
*error_out = "Failed to parse memory increment";
goto out;
}
@@ -404,17 +395,17 @@ static int mem_config(char *str, char **error_out)
diff /= PAGE_SIZE;
down(&plug_mem_mutex);
- for(i = 0; i < diff; i++){
+ for (i = 0; i < diff; i++) {
struct unplugged_pages *unplugged;
void *addr;
- if(add){
- if(list_empty(&unplugged_pages))
+ if (add) {
+ if (list_empty(&unplugged_pages))
break;
unplugged = list_entry(unplugged_pages.next,
struct unplugged_pages, list);
- if(unplug_index > 0)
+ if (unplug_index > 0)
addr = unplugged->pages[--unplug_index];
else {
list_del(&unplugged->list);
@@ -429,11 +420,11 @@ static int mem_config(char *str, char **error_out)
struct page *page;
page = alloc_page(GFP_ATOMIC);
- if(page == NULL)
+ if (page == NULL)
break;
unplugged = page_address(page);
- if(unplug_index == UNPLUGGED_PER_PAGE){
+ if (unplug_index == UNPLUGGED_PER_PAGE) {
list_add(&unplugged->list, &unplugged_pages);
unplug_index = 0;
}
@@ -445,9 +436,9 @@ static int mem_config(char *str, char **error_out)
struct unplugged_pages,
list);
err = os_drop_memory(addr, PAGE_SIZE);
- if(err){
- printk("Failed to release memory - "
- "errno = %d\n", err);
+ if (err) {
+ printk(KERN_ERR "Failed to release "
+ "memory - errno = %d\n", err);
*error_out = "Failed to release memory";
goto out_unlock;
}
@@ -501,10 +492,10 @@ static struct mc_device mem_mc = {
static int __init mem_mc_init(void)
{
- if(can_drop_memory())
+ if (can_drop_memory())
mconsole_register_dev(&mem_mc);
- else printk("Can't release memory to the host - memory hotplug won't "
- "be supported\n");
+ else printk(KERN_ERR "Can't release memory to the host - memory "
+ "hotplug won't be supported\n");
return 0;
}
@@ -519,7 +510,7 @@ static void mconsole_get_config(int (*get_config)(char *, char *, int,
char default_buf[CONFIG_BUF_SIZE], *error, *buf;
int n, size;
- if(get_config == NULL){
+ if (get_config == NULL) {
mconsole_reply(req, "No get_config routine defined", 1, 0);
return;
}
@@ -528,30 +519,30 @@ static void mconsole_get_config(int (*get_config)(char *, char *, int,
size = ARRAY_SIZE(default_buf);
buf = default_buf;
- while(1){
+ while (1) {
n = (*get_config)(name, buf, size, &error);
- if(error != NULL){
+ if (error != NULL) {
mconsole_reply(req, error, 1, 0);
goto out;
}
- if(n <= size){
+ if (n <= size) {
mconsole_reply(req, buf, 0, 0);
goto out;
}
- if(buf != default_buf)
+ if (buf != default_buf)
kfree(buf);
size = n;
buf = kmalloc(size, GFP_KERNEL);
- if(buf == NULL){
+ if (buf == NULL) {
mconsole_reply(req, "Failed to allocate buffer", 1, 0);
return;
}
}
out:
- if(buf != default_buf)
+ if (buf != default_buf)
kfree(buf);
}
@@ -562,19 +553,20 @@ void mconsole_config(struct mc_request *req)
int err;
ptr += strlen("config");
- while(isspace(*ptr)) ptr++;
+ while (isspace(*ptr))
+ ptr++;
dev = mconsole_find_dev(ptr);
- if(dev == NULL){
+ if (dev == NULL) {
mconsole_reply(req, "Bad configuration option", 1, 0);
return;
}
name = &ptr[strlen(dev->name)];
ptr = name;
- while((*ptr != '=') && (*ptr != '\0'))
+ while ((*ptr != '=') && (*ptr != '\0'))
ptr++;
- if(*ptr == '='){
+ if (*ptr == '=') {
err = (*dev->config)(name, &error_string);
mconsole_reply(req, error_string, err, 0);
}
@@ -589,9 +581,9 @@ void mconsole_remove(struct mc_request *req)
int err, start, end, n;
ptr += strlen("remove");
- while(isspace(*ptr)) ptr++;
+ while (isspace(*ptr)) ptr++;
dev = mconsole_find_dev(ptr);
- if(dev == NULL){
+ if (dev == NULL) {
mconsole_reply(req, "Bad remove option", 1, 0);
return;
}
@@ -600,11 +592,11 @@ void mconsole_remove(struct mc_request *req)
err = 1;
n = (*dev->id)(&ptr, &start, &end);
- if(n < 0){
+ if (n < 0) {
err_msg = "Couldn't parse device number";
goto out;
}
- else if((n < start) || (n > end)){
+ else if ((n < start) || (n > end)) {
sprintf(error, "Invalid device number - must be between "
"%d and %d", start, end);
err_msg = error;
@@ -613,16 +605,16 @@ void mconsole_remove(struct mc_request *req)
err_msg = NULL;
err = (*dev->remove)(n, &err_msg);
- switch(err){
+ switch(err) {
case 0:
err_msg = "";
break;
case -ENODEV:
- if(err_msg == NULL)
+ if (err_msg == NULL)
err_msg = "Device doesn't exist";
break;
case -EBUSY:
- if(err_msg == NULL)
+ if (err_msg == NULL)
err_msg = "Device is currently open";
break;
default:
@@ -640,35 +632,28 @@ struct mconsole_output {
static DEFINE_SPINLOCK(client_lock);
static LIST_HEAD(clients);
static char console_buf[MCONSOLE_MAX_DATA];
-static int console_index = 0;
static void console_write(struct console *console, const char *string,
- unsigned len)
+ unsigned int len)
{
struct list_head *ele;
int n;
- if(list_empty(&clients))
+ if (list_empty(&clients))
return;
- while(1){
- n = min((size_t) len, ARRAY_SIZE(console_buf) - console_index);
- strncpy(&console_buf[console_index], string, n);
- console_index += n;
+ while (len > 0) {
+ n = min((size_t) len, ARRAY_SIZE(console_buf));
+ strncpy(console_buf, string, n);
string += n;
len -= n;
- if(len == 0)
- return;
- list_for_each(ele, &clients){
+ list_for_each(ele, &clients) {
struct mconsole_output *entry;
entry = list_entry(ele, struct mconsole_output, list);
- mconsole_reply_len(entry->req, console_buf,
- console_index, 0, 1);
+ mconsole_reply_len(entry->req, console_buf, n, 0, 1);
}
-
- console_index = 0;
}
}
@@ -698,8 +683,7 @@ static void with_console(struct mc_request *req, void (*proc)(void *),
(*proc)(arg);
- mconsole_reply_len(req, console_buf, console_index, 0, 0);
- console_index = 0;
+ mconsole_reply_len(req, "", 0, 0, 0);
spin_lock_irqsave(&client_lock, flags);
list_del(&entry.list);
@@ -707,6 +691,9 @@ static void with_console(struct mc_request *req, void (*proc)(void *),
}
#ifdef CONFIG_MAGIC_SYSRQ
+
+#include <linux/sysrq.h>
+
static void sysrq_proc(void *arg)
{
char *op = arg;
@@ -718,12 +705,13 @@ void mconsole_sysrq(struct mc_request *req)
char *ptr = req->request.data;
ptr += strlen("sysrq");
- while(isspace(*ptr)) ptr++;
+ while (isspace(*ptr)) ptr++;
- /* With 'b', the system will shut down without a chance to reply,
+ /*
+ * With 'b', the system will shut down without a chance to reply,
* so in this case, we reply first.
*/
- if(*ptr == 'b')
+ if (*ptr == 'b')
mconsole_reply(req, "", 0, 0);
with_console(req, sysrq_proc, ptr);
@@ -735,8 +723,6 @@ void mconsole_sysrq(struct mc_request *req)
}
#endif
-#ifdef CONFIG_MODE_SKAS
-
static void stack_proc(void *arg)
{
struct task_struct *from = current, *to = arg;
@@ -745,29 +731,34 @@ static void stack_proc(void *arg)
switch_to(from, to, from);
}
-/* Mconsole stack trace
+/*
+ * Mconsole stack trace
* Added by Allan Graves, Jeff Dike
* Dumps a stacks registers to the linux console.
* Usage stack <pid>.
*/
-static void do_stack_trace(struct mc_request *req)
+void mconsole_stack(struct mc_request *req)
{
char *ptr = req->request.data;
int pid_requested= -1;
struct task_struct *from = NULL;
struct task_struct *to = NULL;
- /* Would be nice:
+ /*
+ * Would be nice:
* 1) Send showregs output to mconsole.
* 2) Add a way to stack dump all pids.
*/
ptr += strlen("stack");
- while(isspace(*ptr)) ptr++;
+ while (isspace(*ptr))
+ ptr++;
- /* Should really check for multiple pids or reject bad args here */
+ /*
+ * Should really check for multiple pids or reject bad args here
+ */
/* What do the arguments in mconsole_reply mean? */
- if(sscanf(ptr, "%d", &pid_requested) == 0){
+ if (sscanf(ptr, "%d", &pid_requested) == 0) {
mconsole_reply(req, "Please specify a pid", 1, 0);
return;
}
@@ -775,25 +766,15 @@ static void do_stack_trace(struct mc_request *req)
from = current;
to = find_task_by_pid(pid_requested);
- if((to == NULL) || (pid_requested == 0)) {
+ if ((to == NULL) || (pid_requested == 0)) {
mconsole_reply(req, "Couldn't find that pid", 1, 0);
return;
}
with_console(req, stack_proc, to);
}
-#endif /* CONFIG_MODE_SKAS */
-void mconsole_stack(struct mc_request *req)
-{
- /* This command doesn't work in TT mode, so let's check and then
- * get out of here
- */
- CHOOSE_MODE(mconsole_reply(req, "Sorry, this doesn't work in TT mode",
- 1, 0),
- do_stack_trace(req));
-}
-
-/* Changed by mconsole_setup, which is __setup, and called before SMP is
+/*
+ * Changed by mconsole_setup, which is __setup, and called before SMP is
* active.
*/
static char *notify_socket = NULL;
@@ -805,13 +786,14 @@ static int __init mconsole_init(void)
int err;
char file[256];
- if(umid_file_name("mconsole", file, sizeof(file))) return(-1);
+ if (umid_file_name("mconsole", file, sizeof(file)))
+ return -1;
snprintf(mconsole_socket_name, sizeof(file), "%s", file);
sock = os_create_unix_socket(file, sizeof(file), 1);
- if (sock < 0){
- printk("Failed to initialize management console\n");
- return(1);
+ if (sock < 0) {
+ printk(KERN_ERR "Failed to initialize management console\n");
+ return 1;
}
register_reboot_notifier(&reboot_notifier);
@@ -819,14 +801,14 @@ static int __init mconsole_init(void)
err = um_request_irq(MCONSOLE_IRQ, sock, IRQ_READ, mconsole_interrupt,
IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
"mconsole", (void *)sock);
- if (err){
- printk("Failed to get IRQ for management console\n");
- return(1);
+ if (err) {
+ printk(KERN_ERR "Failed to get IRQ for management console\n");
+ return 1;
}
- if(notify_socket != NULL){
+ if (notify_socket != NULL) {
notify_socket = kstrdup(notify_socket, GFP_KERNEL);
- if(notify_socket != NULL)
+ if (notify_socket != NULL)
mconsole_notify(notify_socket, MCONSOLE_SOCKET,
mconsole_socket_name,
strlen(mconsole_socket_name) + 1);
@@ -834,9 +816,9 @@ static int __init mconsole_init(void)
"string\n");
}
- printk("mconsole (version %d) initialized on %s\n",
+ printk(KERN_INFO "mconsole (version %d) initialized on %s\n",
MCONSOLE_VERSION, mconsole_socket_name);
- return(0);
+ return 0;
}
__initcall(mconsole_init);
@@ -847,10 +829,10 @@ static int write_proc_mconsole(struct file *file, const char __user *buffer,
char *buf;
buf = kmalloc(count + 1, GFP_KERNEL);
- if(buf == NULL)
- return(-ENOMEM);
+ if (buf == NULL)
+ return -ENOMEM;
- if(copy_from_user(buf, buffer, count)){
+ if (copy_from_user(buf, buffer, count)) {
count = -EFAULT;
goto out;
}
@@ -860,24 +842,26 @@ static int write_proc_mconsole(struct file *file, const char __user *buffer,
mconsole_notify(notify_socket, MCONSOLE_USER_NOTIFY, buf, count);
out:
kfree(buf);
- return(count);
+ return count;
}
static int create_proc_mconsole(void)
{
struct proc_dir_entry *ent;
- if(notify_socket == NULL) return(0);
+ if (notify_socket == NULL)
+ return 0;
ent = create_proc_entry("mconsole", S_IFREG | 0200, NULL);
- if(ent == NULL){
- printk(KERN_INFO "create_proc_mconsole : create_proc_entry failed\n");
- return(0);
+ if (ent == NULL) {
+ printk(KERN_INFO "create_proc_mconsole : create_proc_entry "
+ "failed\n");
+ return 0;
}
ent->read_proc = NULL;
ent->write_proc = write_proc_mconsole;
- return(0);
+ return 0;
}
static DEFINE_SPINLOCK(notify_spinlock);
@@ -894,19 +878,19 @@ void unlock_notify(void)
__initcall(create_proc_mconsole);
-#define NOTIFY "=notify:"
+#define NOTIFY "notify:"
static int mconsole_setup(char *str)
{
- if(!strncmp(str, NOTIFY, strlen(NOTIFY))){
+ if (!strncmp(str, NOTIFY, strlen(NOTIFY))) {
str += strlen(NOTIFY);
notify_socket = str;
}
else printk(KERN_ERR "mconsole_setup : Unknown option - '%s'\n", str);
- return(1);
+ return 1;
}
-__setup("mconsole", mconsole_setup);
+__setup("mconsole=", mconsole_setup);
__uml_help(mconsole_setup,
"mconsole=notify:<socket>\n"
@@ -921,11 +905,12 @@ static int notify_panic(struct notifier_block *self, unsigned long unused1,
{
char *message = ptr;
- if(notify_socket == NULL) return(0);
+ if (notify_socket == NULL)
+ return 0;
mconsole_notify(notify_socket, MCONSOLE_PANIC, message,
strlen(message) + 1);
- return(0);
+ return 0;
}
static struct notifier_block panic_exit_notifier = {
@@ -938,14 +923,14 @@ static int add_notifier(void)
{
atomic_notifier_chain_register(&panic_notifier_list,
&panic_exit_notifier);
- return(0);
+ return 0;
}
__initcall(add_notifier);
char *mconsole_notify_socket(void)
{
- return(notify_socket);
+ return notify_socket;
}
EXPORT_SYMBOL(mconsole_notify_socket);
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c
index f31e71546e52..430c024a19b0 100644
--- a/arch/um/drivers/mconsole_user.c
+++ b/arch/um/drivers/mconsole_user.c
@@ -1,25 +1,22 @@
/*
* Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org)
- * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include <stdio.h>
-#include <stdlib.h>
#include <errno.h>
-#include <signal.h>
+#include <string.h>
+#include <unistd.h>
#include <sys/socket.h>
-#include <sys/types.h>
#include <sys/uio.h>
#include <sys/un.h>
-#include <unistd.h>
-#include "user.h"
-#include "sysdep/ptrace.h"
+#include "kern_constants.h"
#include "mconsole.h"
-#include "os.h"
+#include "user.h"
static struct mconsole_command commands[] = {
- /* With uts namespaces, uts information becomes process-specific, so
+ /*
+ * With uts namespaces, uts information becomes process-specific, so
* we need a process context. If we try handling this in interrupt
* context, we may hit an exiting process without a valid uts
* namespace.
@@ -36,7 +33,7 @@ static struct mconsole_command commands[] = {
{ "go", mconsole_go, MCONSOLE_INTR },
{ "log", mconsole_log, MCONSOLE_INTR },
{ "proc", mconsole_proc, MCONSOLE_PROC },
- { "stack", mconsole_stack, MCONSOLE_INTR },
+ { "stack", mconsole_stack, MCONSOLE_INTR },
};
/* Initialized in mconsole_init, which is an initcall */
@@ -44,21 +41,21 @@ char mconsole_socket_name[256];
int mconsole_reply_v0(struct mc_request *req, char *reply)
{
- struct iovec iov;
- struct msghdr msg;
+ struct iovec iov;
+ struct msghdr msg;
- iov.iov_base = reply;
- iov.iov_len = strlen(reply);
+ iov.iov_base = reply;
+ iov.iov_len = strlen(reply);
- msg.msg_name = &(req->origin);
- msg.msg_namelen = req->originlen;
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- msg.msg_control = NULL;
- msg.msg_controllen = 0;
- msg.msg_flags = 0;
+ msg.msg_name = &(req->origin);
+ msg.msg_namelen = req->originlen;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
+ msg.msg_flags = 0;
- return sendmsg(req->originating_fd, &msg, 0);
+ return sendmsg(req->originating_fd, &msg, 0);
}
static struct mconsole_command *mconsole_parse(struct mc_request *req)
@@ -66,10 +63,10 @@ static struct mconsole_command *mconsole_parse(struct mc_request *req)
struct mconsole_command *cmd;
int i;
- for(i = 0; i < ARRAY_SIZE(commands); i++){
+ for (i = 0; i < ARRAY_SIZE(commands); i++) {
cmd = &commands[i];
- if(!strncmp(req->request.data, cmd->command,
- strlen(cmd->command))){
+ if (!strncmp(req->request.data, cmd->command,
+ strlen(cmd->command))) {
return cmd;
}
}
@@ -94,9 +91,9 @@ int mconsole_get_request(int fd, struct mc_request *req)
req->originating_fd = fd;
- if(req->request.magic != MCONSOLE_MAGIC){
+ if (req->request.magic != MCONSOLE_MAGIC) {
/* Unversioned request */
- len = MIN(sizeof(req->request.data) - 1,
+ len = MIN(sizeof(req->request.data) - 1,
strlen((char *) &req->request));
memmove(req->request.data, &req->request, len);
req->request.data[len] = '\0';
@@ -107,32 +104,33 @@ int mconsole_get_request(int fd, struct mc_request *req)
mconsole_reply_v0(req, "ERR Version 0 mconsole clients are "
"not supported by this driver");
- return(0);
+ return 0;
}
- if(req->request.len >= MCONSOLE_MAX_DATA){
+ if (req->request.len >= MCONSOLE_MAX_DATA) {
mconsole_reply(req, "Request too large", 1, 0);
- return(0);
+ return 0;
}
- if(req->request.version != MCONSOLE_VERSION){
- mconsole_reply(req, "This driver only supports version "
- STRING(MCONSOLE_VERSION) " clients", 1, 0);
+ if (req->request.version != MCONSOLE_VERSION) {
+ mconsole_reply(req, "This driver only supports version "
+ STRING(MCONSOLE_VERSION) " clients", 1, 0);
}
-
+
req->request.data[req->request.len] = '\0';
req->cmd = mconsole_parse(req);
- if(req->cmd == NULL){
+ if (req->cmd == NULL) {
mconsole_reply(req, "Unknown command", 1, 0);
- return(0);
+ return 0;
}
- return(1);
+ return 1;
}
int mconsole_reply_len(struct mc_request *req, const char *str, int total,
int err, int more)
{
- /* XXX This is a stack consumption problem. It'd be nice to
+ /*
+ * XXX This is a stack consumption problem. It'd be nice to
* make it global and serialize access to it, but there are a
* ton of callers to this function.
*/
@@ -147,7 +145,7 @@ int mconsole_reply_len(struct mc_request *req, const char *str, int total,
len = MIN(total, MCONSOLE_MAX_DATA - 1);
- if(len == total) reply.more = more;
+ if (len == total) reply.more = more;
else reply.more = 1;
memcpy(reply.data, str, len);
@@ -161,9 +159,10 @@ int mconsole_reply_len(struct mc_request *req, const char *str, int total,
n = sendto(req->originating_fd, &reply, len, 0,
(struct sockaddr *) req->origin, req->originlen);
- if(n < 0) return(-errno);
- } while(total > 0);
- return(0);
+ if (n < 0)
+ return -errno;
+ } while (total > 0);
+ return 0;
}
int mconsole_reply(struct mc_request *req, const char *str, int err, int more)
@@ -187,18 +186,18 @@ int mconsole_notify(char *sock_name, int type, const void *data, int len)
int n, err = 0;
lock_notify();
- if(notify_sock < 0){
+ if (notify_sock < 0) {
notify_sock = socket(PF_UNIX, SOCK_DGRAM, 0);
- if(notify_sock < 0){
+ if (notify_sock < 0) {
err = -errno;
- printk("mconsole_notify - socket failed, errno = %d\n",
- err);
+ printk(UM_KERN_ERR "mconsole_notify - socket failed, "
+ "errno = %d\n", errno);
}
}
unlock_notify();
-
- if(err)
- return(err);
+
+ if (err)
+ return err;
target.sun_family = AF_UNIX;
strcpy(target.sun_path, sock_name);
@@ -212,22 +211,12 @@ int mconsole_notify(char *sock_name, int type, const void *data, int len)
err = 0;
len = sizeof(packet) + packet.len - sizeof(packet.data);
- n = sendto(notify_sock, &packet, len, 0, (struct sockaddr *) &target,
+ n = sendto(notify_sock, &packet, len, 0, (struct sockaddr *) &target,
sizeof(target));
- if(n < 0){
+ if (n < 0) {
err = -errno;
- printk("mconsole_notify - sendto failed, errno = %d\n", errno);
+ printk(UM_KERN_ERR "mconsole_notify - sendto failed, "
+ "errno = %d\n", errno);
}
- return(err);
+ return err;
}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c
index 867666a02339..67b2f55a602f 100644
--- a/arch/um/drivers/mmapper_kern.c
+++ b/arch/um/drivers/mmapper_kern.c
@@ -9,27 +9,29 @@
*
*/
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/types.h>
#include <linux/fs.h>
+#include <linux/init.h>
#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/mm.h>
#include <asm/uaccess.h>
#include "mem_user.h"
-
+
/* These are set in mmapper_init, which is called at boot time */
static unsigned long mmapper_size;
-static unsigned long p_buf = 0;
-static char *v_buf = NULL;
+static unsigned long p_buf;
+static char *v_buf;
-static ssize_t
-mmapper_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+static ssize_t mmapper_read(struct file *file, char __user *buf, size_t count,
+ loff_t *ppos)
{
return simple_read_from_buffer(buf, count, ppos, v_buf, mmapper_size);
}
-static ssize_t
-mmapper_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+static ssize_t mmapper_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
{
if (*ppos > mmapper_size)
return -EINVAL;
@@ -39,48 +41,46 @@ mmapper_write(struct file *file, const char __user *buf, size_t count, loff_t *p
if (copy_from_user(&v_buf[*ppos], buf, count))
return -EFAULT;
-
+
return count;
}
-static int
-mmapper_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg)
+static int mmapper_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
{
- return(-ENOIOCTLCMD);
+ return -ENOIOCTLCMD;
}
-static int
-mmapper_mmap(struct file *file, struct vm_area_struct * vma)
+static int mmapper_mmap(struct file *file, struct vm_area_struct *vma)
{
int ret = -EINVAL;
int size;
if (vma->vm_pgoff != 0)
goto out;
-
+
size = vma->vm_end - vma->vm_start;
- if(size > mmapper_size) return(-EFAULT);
+ if (size > mmapper_size)
+ return -EFAULT;
- /* XXX A comment above remap_pfn_range says it should only be
+ /*
+ * XXX A comment above remap_pfn_range says it should only be
* called when the mm semaphore is held
*/
if (remap_pfn_range(vma, vma->vm_start, p_buf >> PAGE_SHIFT, size,
- vma->vm_page_prot))
+ vma->vm_page_prot))
goto out;
ret = 0;
out:
return ret;
}
-static int
-mmapper_open(struct inode *inode, struct file *file)
+static int mmapper_open(struct inode *inode, struct file *file)
{
return 0;
}
-static int
-mmapper_release(struct inode *inode, struct file *file)
+static int mmapper_release(struct inode *inode, struct file *file)
{
return 0;
}
@@ -95,7 +95,9 @@ static const struct file_operations mmapper_fops = {
.release = mmapper_release,
};
-/* No locking needed - only used (and modified) by below initcall and exitcall. */
+/*
+ * No locking needed - only used (and modified) by below initcall and exitcall.
+ */
static struct miscdevice mmapper_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "mmapper",
@@ -109,13 +111,13 @@ static int __init mmapper_init(void)
printk(KERN_INFO "Mapper v0.1\n");
v_buf = (char *) find_iomem("mmapper", &mmapper_size);
- if(mmapper_size == 0){
+ if (mmapper_size == 0) {
printk(KERN_ERR "mmapper_init - find_iomem failed\n");
goto out;
}
err = misc_register(&mmapper_dev);
- if(err){
+ if (err) {
printk(KERN_ERR "mmapper - misc_register failed, err = %d\n",
err);
goto out;
@@ -136,9 +138,3 @@ module_exit(mmapper_exit);
MODULE_AUTHOR("Greg Lonnon <glonnon@ridgerun.com>");
MODULE_DESCRIPTION("DSPLinux simulator mmapper driver");
-/*
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index d35d0c1ee7f4..73681f14f9fc 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -1,33 +1,28 @@
/*
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
* James Leu (jleu@mindspring.net).
* Copyright (C) 2001 by various other people who didn't put their name here.
* Licensed under the GPL.
*/
-#include "linux/kernel.h"
-#include "linux/netdevice.h"
-#include "linux/rtnetlink.h"
-#include "linux/skbuff.h"
-#include "linux/socket.h"
-#include "linux/spinlock.h"
-#include "linux/module.h"
-#include "linux/init.h"
-#include "linux/etherdevice.h"
-#include "linux/list.h"
-#include "linux/inetdevice.h"
-#include "linux/ctype.h"
-#include "linux/bootmem.h"
-#include "linux/ethtool.h"
-#include "linux/platform_device.h"
-#include "asm/uaccess.h"
-#include "kern_util.h"
-#include "net_kern.h"
-#include "net_user.h"
-#include "mconsole_kern.h"
+#include <linux/bootmem.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/inetdevice.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/netdevice.h>
+#include <linux/platform_device.h>
+#include <linux/rtnetlink.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
#include "init.h"
-#include "irq_user.h"
#include "irq_kern.h"
+#include "irq_user.h"
+#include "mconsole_kern.h"
+#include "net_kern.h"
+#include "net_user.h"
static inline void set_ether_mac(struct net_device *dev, unsigned char *addr)
{
@@ -39,6 +34,46 @@ static inline void set_ether_mac(struct net_device *dev, unsigned char *addr)
static DEFINE_SPINLOCK(opened_lock);
static LIST_HEAD(opened);
+/*
+ * The drop_skb is used when we can't allocate an skb. The
+ * packet is read into drop_skb in order to get the data off the
+ * connection to the host.
+ * It is reallocated whenever a maximum packet size is seen which is
+ * larger than any seen before. update_drop_skb is called from
+ * eth_configure when a new interface is added.
+ */
+static DEFINE_SPINLOCK(drop_lock);
+static struct sk_buff *drop_skb;
+static int drop_max;
+
+static int update_drop_skb(int max)
+{
+ struct sk_buff *new;
+ unsigned long flags;
+ int err = 0;
+
+ spin_lock_irqsave(&drop_lock, flags);
+
+ if (max <= drop_max)
+ goto out;
+
+ err = -ENOMEM;
+ new = dev_alloc_skb(max);
+ if (new == NULL)
+ goto out;
+
+ skb_put(new, max);
+
+ kfree_skb(drop_skb);
+ drop_skb = new;
+ drop_max = max;
+ err = 0;
+out:
+ spin_unlock_irqrestore(&drop_lock, flags);
+
+ return err;
+}
+
static int uml_net_rx(struct net_device *dev)
{
struct uml_net_private *lp = dev->priv;
@@ -46,16 +81,19 @@ static int uml_net_rx(struct net_device *dev)
struct sk_buff *skb;
/* If we can't allocate memory, try again next round. */
- skb = dev_alloc_skb(dev->mtu);
+ skb = dev_alloc_skb(lp->max_packet);
if (skb == NULL) {
+ drop_skb->dev = dev;
+ /* Read a packet into drop_skb and don't do anything with it. */
+ (*lp->read)(lp->fd, drop_skb, lp);
lp->stats.rx_dropped++;
return 0;
}
skb->dev = dev;
- skb_put(skb, dev->mtu);
+ skb_put(skb, lp->max_packet);
skb_reset_mac_header(skb);
- pkt_len = (*lp->read)(lp->fd, &skb, lp);
+ pkt_len = (*lp->read)(lp->fd, skb, lp);
if (pkt_len > 0) {
skb_trim(skb, pkt_len);
@@ -84,12 +122,12 @@ irqreturn_t uml_net_interrupt(int irq, void *dev_id)
struct uml_net_private *lp = dev->priv;
int err;
- if(!netif_running(dev))
- return(IRQ_NONE);
+ if (!netif_running(dev))
+ return IRQ_NONE;
spin_lock(&lp->lock);
- while((err = uml_net_rx(dev)) > 0) ;
- if(err < 0) {
+ while ((err = uml_net_rx(dev)) > 0) ;
+ if (err < 0) {
printk(KERN_ERR
"Device '%s' read returned %d, shutting it down\n",
dev->name, err);
@@ -115,20 +153,20 @@ static int uml_net_open(struct net_device *dev)
struct uml_net_private *lp = dev->priv;
int err;
- if(lp->fd >= 0){
+ if (lp->fd >= 0) {
err = -ENXIO;
goto out;
}
lp->fd = (*lp->open)(&lp->user);
- if(lp->fd < 0){
+ if (lp->fd < 0) {
err = lp->fd;
goto out;
}
err = um_request_irq(dev->irq, lp->fd, IRQ_READ, uml_net_interrupt,
IRQF_DISABLED | IRQF_SHARED, dev->name, dev);
- if(err != 0){
+ if (err != 0) {
printk(KERN_ERR "uml_net_open: failed to get irq(%d)\n", err);
err = -ENETUNREACH;
goto out_close;
@@ -141,7 +179,7 @@ static int uml_net_open(struct net_device *dev)
* is full when we get here. In this case, new data is never queued,
* SIGIOs never arrive, and the net never works.
*/
- while((err = uml_net_rx(dev)) > 0) ;
+ while ((err = uml_net_rx(dev)) > 0) ;
spin_lock(&opened_lock);
list_add(&lp->list, &opened);
@@ -149,7 +187,7 @@ static int uml_net_open(struct net_device *dev)
return 0;
out_close:
- if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user);
+ if (lp->close != NULL) (*lp->close)(lp->fd, &lp->user);
lp->fd = -1;
out:
return err;
@@ -162,7 +200,7 @@ static int uml_net_close(struct net_device *dev)
netif_stop_queue(dev);
free_irq(dev->irq, dev);
- if(lp->close != NULL)
+ if (lp->close != NULL)
(*lp->close)(lp->fd, &lp->user);
lp->fd = -1;
@@ -183,9 +221,9 @@ static int uml_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
spin_lock_irqsave(&lp->lock, flags);
- len = (*lp->write)(lp->fd, &skb, lp);
+ len = (*lp->write)(lp->fd, skb, lp);
- if(len == skb->len) {
+ if (len == skb->len) {
lp->stats.tx_packets++;
lp->stats.tx_bytes += skb->len;
dev->trans_start = jiffies;
@@ -194,7 +232,7 @@ static int uml_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* this is normally done in the interrupt when tx finishes */
netif_wake_queue(dev);
}
- else if(len == 0){
+ else if (len == 0) {
netif_start_queue(dev);
lp->stats.tx_dropped++;
}
@@ -218,8 +256,10 @@ static struct net_device_stats *uml_net_get_stats(struct net_device *dev)
static void uml_net_set_multicast_list(struct net_device *dev)
{
- if (dev->flags & IFF_PROMISC) return;
- else if (dev->mc_count) dev->flags |= IFF_ALLMULTI;
+ if (dev->flags & IFF_PROMISC)
+ return;
+ else if (dev->mc_count)
+ dev->flags |= IFF_ALLMULTI;
else dev->flags &= ~IFF_ALLMULTI;
}
@@ -243,22 +283,9 @@ static int uml_net_set_mac(struct net_device *dev, void *addr)
static int uml_net_change_mtu(struct net_device *dev, int new_mtu)
{
- struct uml_net_private *lp = dev->priv;
- int err = 0;
-
- spin_lock_irq(&lp->lock);
-
- new_mtu = (*lp->set_mtu)(new_mtu, &lp->user);
- if(new_mtu < 0){
- err = new_mtu;
- goto out;
- }
-
dev->mtu = new_mtu;
- out:
- spin_unlock_irq(&lp->lock);
- return err;
+ return 0;
}
static void uml_net_get_drvinfo(struct net_device *dev,
@@ -288,13 +315,13 @@ static void setup_etheraddr(char *str, unsigned char *addr, char *name)
char *end;
int i;
- if(str == NULL)
+ if (str == NULL)
goto random;
- for(i=0;i<6;i++){
+ for (i = 0;i < 6; i++) {
addr[i] = simple_strtoul(str, &end, 16);
- if((end == str) ||
- ((*end != ':') && (*end != ',') && (*end != '\0'))){
+ if ((end == str) ||
+ ((*end != ':') && (*end != ',') && (*end != '\0'))) {
printk(KERN_ERR
"setup_etheraddr: failed to parse '%s' "
"as an ethernet address\n", str);
@@ -349,7 +376,7 @@ static void net_device_release(struct device *dev)
struct net_device *netdev = device->dev;
struct uml_net_private *lp = netdev->priv;
- if(lp->remove != NULL)
+ if (lp->remove != NULL)
(*lp->remove)(&lp->user);
list_del(&device->list);
kfree(device);
@@ -413,7 +440,7 @@ static void eth_configure(int n, void *init, char *mac,
device->pdev.name = DRIVER_NAME;
device->pdev.dev.release = net_device_release;
device->pdev.dev.driver_data = device;
- if(platform_device_register(&device->pdev))
+ if (platform_device_register(&device->pdev))
goto out_free_netdev;
SET_NETDEV_DEV(dev,&device->pdev.dev);
@@ -430,6 +457,7 @@ static void eth_configure(int n, void *init, char *mac,
.dev = dev,
.fd = -1,
.mac = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0},
+ .max_packet = transport->user->max_packet,
.protocol = transport->kern->protocol,
.open = transport->user->open,
.close = transport->user->close,
@@ -437,8 +465,7 @@ static void eth_configure(int n, void *init, char *mac,
.read = transport->kern->read,
.write = transport->kern->write,
.add_address = transport->user->add_address,
- .delete_address = transport->user->delete_address,
- .set_mtu = transport->user->set_mtu });
+ .delete_address = transport->user->delete_address });
init_timer(&lp->tl);
spin_lock_init(&lp->lock);
@@ -450,7 +477,7 @@ static void eth_configure(int n, void *init, char *mac,
goto out_unregister;
set_ether_mac(dev, device->mac);
- dev->mtu = transport->user->max_packet;
+ dev->mtu = transport->user->mtu;
dev->open = uml_net_open;
dev->hard_start_xmit = uml_net_start_xmit;
dev->stop = uml_net_close;
@@ -463,6 +490,10 @@ static void eth_configure(int n, void *init, char *mac,
dev->watchdog_timeo = (HZ >> 1);
dev->irq = UM_ETH_IRQ;
+ err = update_drop_skb(lp->max_packet);
+ if (err)
+ goto out_undo_user_init;
+
rtnl_lock();
err = register_netdevice(dev);
rtnl_unlock();
@@ -493,9 +524,9 @@ static struct uml_net *find_device(int n)
struct list_head *ele;
spin_lock(&devices_lock);
- list_for_each(ele, &devices){
+ list_for_each(ele, &devices) {
device = list_entry(ele, struct uml_net, list);
- if(device->index == n)
+ if (device->index == n)
goto out;
}
device = NULL;
@@ -511,19 +542,19 @@ static int eth_parse(char *str, int *index_out, char **str_out,
int n, err = -EINVAL;;
n = simple_strtoul(str, &end, 0);
- if(end == str){
+ if (end == str) {
*error_out = "Bad device number";
return err;
}
str = end;
- if(*str != '='){
+ if (*str != '=') {
*error_out = "Expected '=' after device number";
return err;
}
str++;
- if(find_device(n)){
+ if (find_device(n)) {
*error_out = "Device already configured";
return err;
}
@@ -551,20 +582,20 @@ static int check_transport(struct transport *transport, char *eth, int n,
int len;
len = strlen(transport->name);
- if(strncmp(eth, transport->name, len))
+ if (strncmp(eth, transport->name, len))
return 0;
eth += len;
- if(*eth == ',')
+ if (*eth == ',')
eth++;
- else if(*eth != '\0')
+ else if (*eth != '\0')
return 0;
*init_out = kmalloc(transport->setup_size, GFP_KERNEL);
- if(*init_out == NULL)
+ if (*init_out == NULL)
return 1;
- if(!transport->setup(eth, mac_out, *init_out)){
+ if (!transport->setup(eth, mac_out, *init_out)) {
kfree(*init_out);
*init_out = NULL;
}
@@ -584,13 +615,13 @@ void register_transport(struct transport *new)
list_add(&new->list, &transports);
spin_unlock(&transports_lock);
- list_for_each_safe(ele, next, &eth_cmd_line){
+ list_for_each_safe(ele, next, &eth_cmd_line) {
eth = list_entry(ele, struct eth_init, list);
match = check_transport(new, eth->init, eth->index, &init,
&mac);
- if(!match)
+ if (!match)
continue;
- else if(init != NULL){
+ else if (init != NULL) {
eth_configure(eth->index, init, mac, new);
kfree(init);
}
@@ -607,11 +638,11 @@ static int eth_setup_common(char *str, int index)
int found = 0;
spin_lock(&transports_lock);
- list_for_each(ele, &transports){
+ list_for_each(ele, &transports) {
transport = list_entry(ele, struct transport, list);
- if(!check_transport(transport, str, index, &init, &mac))
+ if (!check_transport(transport, str, index, &init, &mac))
continue;
- if(init != NULL){
+ if (init != NULL) {
eth_configure(index, init, mac, transport);
kfree(init);
}
@@ -630,15 +661,15 @@ static int __init eth_setup(char *str)
int n, err;
err = eth_parse(str, &n, &str, &error);
- if(err){
+ if (err) {
printk(KERN_ERR "eth_setup - Couldn't parse '%s' : %s\n",
str, error);
return 1;
}
new = alloc_bootmem(sizeof(*new));
- if (new == NULL){
- printk("eth_init : alloc_bootmem failed\n");
+ if (new == NULL) {
+ printk(KERN_ERR "eth_init : alloc_bootmem failed\n");
return 1;
}
@@ -661,36 +692,36 @@ static int net_config(char *str, char **error_out)
int n, err;
err = eth_parse(str, &n, &str, error_out);
- if(err)
+ if (err)
return err;
/* This string is broken up and the pieces used by the underlying
* driver. So, it is freed only if eth_setup_common fails.
*/
str = kstrdup(str, GFP_KERNEL);
- if(str == NULL){
+ if (str == NULL) {
*error_out = "net_config failed to strdup string";
return -ENOMEM;
}
err = !eth_setup_common(str, n);
- if(err)
+ if (err)
kfree(str);
- return(err);
+ return err;
}
static int net_id(char **str, int *start_out, int *end_out)
{
- char *end;
- int n;
+ char *end;
+ int n;
n = simple_strtoul(*str, &end, 0);
- if((*end != '\0') || (end == *str))
+ if ((*end != '\0') || (end == *str))
return -1;
- *start_out = n;
- *end_out = n;
- *str = end;
- return n;
+ *start_out = n;
+ *end_out = n;
+ *str = end;
+ return n;
}
static int net_remove(int n, char **error_out)
@@ -700,12 +731,12 @@ static int net_remove(int n, char **error_out)
struct uml_net_private *lp;
device = find_device(n);
- if(device == NULL)
+ if (device == NULL)
return -ENODEV;
dev = device->dev;
lp = dev->priv;
- if(lp->fd > 0)
+ if (lp->fd > 0)
return -EBUSY;
unregister_netdev(dev);
platform_device_unregister(&device->pdev);
@@ -722,6 +753,7 @@ static struct mc_device net_mc = {
.remove = net_remove,
};
+#ifdef CONFIG_INET
static int uml_inetaddr_event(struct notifier_block *this, unsigned long event,
void *ptr)
{
@@ -731,13 +763,13 @@ static int uml_inetaddr_event(struct notifier_block *this, unsigned long event,
void (*proc)(unsigned char *, unsigned char *, void *);
unsigned char addr_buf[4], netmask_buf[4];
- if(dev->open != uml_net_open)
+ if (dev->open != uml_net_open)
return NOTIFY_DONE;
lp = dev->priv;
proc = NULL;
- switch (event){
+ switch (event) {
case NETDEV_UP:
proc = lp->add_address;
break;
@@ -745,7 +777,7 @@ static int uml_inetaddr_event(struct notifier_block *this, unsigned long event,
proc = lp->delete_address;
break;
}
- if(proc != NULL){
+ if (proc != NULL) {
memcpy(addr_buf, &ifa->ifa_address, sizeof(addr_buf));
memcpy(netmask_buf, &ifa->ifa_mask, sizeof(netmask_buf));
(*proc)(addr_buf, netmask_buf, &lp->user);
@@ -758,14 +790,13 @@ struct notifier_block uml_inetaddr_notifier = {
.notifier_call = uml_inetaddr_event,
};
-static int uml_net_init(void)
+static void inet_register(void)
{
struct list_head *ele;
struct uml_net_private *lp;
struct in_device *ip;
struct in_ifaddr *in;
- mconsole_register_dev(&net_mc);
register_inetaddr_notifier(&uml_inetaddr_notifier);
/* Devices may have been opened already, so the uml_inetaddr_notifier
@@ -773,19 +804,29 @@ static int uml_net_init(void)
* addresses which have already been set up get handled properly.
*/
spin_lock(&opened_lock);
- list_for_each(ele, &opened){
+ list_for_each(ele, &opened) {
lp = list_entry(ele, struct uml_net_private, list);
ip = lp->dev->ip_ptr;
- if(ip == NULL)
+ if (ip == NULL)
continue;
in = ip->ifa_list;
- while(in != NULL){
+ while (in != NULL) {
uml_inetaddr_event(NULL, NETDEV_UP, in);
in = in->ifa_next;
}
}
spin_unlock(&opened_lock);
+}
+#else
+static inline void inet_register(void)
+{
+}
+#endif
+static int uml_net_init(void)
+{
+ mconsole_register_dev(&net_mc);
+ inet_register();
return 0;
}
@@ -797,12 +838,12 @@ static void close_devices(void)
struct uml_net_private *lp;
spin_lock(&opened_lock);
- list_for_each(ele, &opened){
+ list_for_each(ele, &opened) {
lp = list_entry(ele, struct uml_net_private, list);
free_irq(lp->dev->irq, lp->dev);
- if((lp->close != NULL) && (lp->fd >= 0))
+ if ((lp->close != NULL) && (lp->fd >= 0))
(*lp->close)(lp->fd, &lp->user);
- if(lp->remove != NULL)
+ if (lp->remove != NULL)
(*lp->remove)(&lp->user);
}
spin_unlock(&opened_lock);
@@ -810,19 +851,6 @@ static void close_devices(void)
__uml_exitcall(close_devices);
-struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra)
-{
- if((skb != NULL) && (skb_tailroom(skb) < extra)){
- struct sk_buff *skb2;
-
- skb2 = skb_copy_expand(skb, 0, extra, GFP_ATOMIC);
- dev_kfree_skb(skb);
- skb = skb2;
- }
- if(skb != NULL) skb_put(skb, extra);
- return(skb);
-}
-
void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *,
void *),
void *arg)
@@ -832,9 +860,9 @@ void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *,
struct in_ifaddr *in;
unsigned char address[4], netmask[4];
- if(ip == NULL) return;
+ if (ip == NULL) return;
in = ip->ifa_list;
- while(in != NULL){
+ while (in != NULL) {
memcpy(address, &in->ifa_address, sizeof(address));
memcpy(netmask, &in->ifa_mask, sizeof(netmask));
(*cb)(address, netmask, arg);
@@ -849,15 +877,15 @@ int dev_netmask(void *d, void *m)
struct in_ifaddr *in;
__be32 *mask_out = m;
- if(ip == NULL)
- return(1);
+ if (ip == NULL)
+ return 1;
in = ip->ifa_list;
- if(in == NULL)
- return(1);
+ if (in == NULL)
+ return 1;
*mask_out = in->ifa_mask;
- return(0);
+ return 0;
}
void *get_output_buffer(int *len_out)
@@ -865,7 +893,7 @@ void *get_output_buffer(int *len_out)
void *ret;
ret = (void *) __get_free_pages(GFP_KERNEL, 0);
- if(ret) *len_out = PAGE_SIZE;
+ if (ret) *len_out = PAGE_SIZE;
else *len_out = 0;
return ret;
}
@@ -881,16 +909,16 @@ int tap_setup_common(char *str, char *type, char **dev_name, char **mac_out,
char *remain;
remain = split_if_spec(str, dev_name, mac_out, gate_addr, NULL);
- if(remain != NULL){
- printk("tap_setup_common - Extra garbage on specification : "
- "'%s'\n", remain);
- return(1);
+ if (remain != NULL) {
+ printk(KERN_ERR "tap_setup_common - Extra garbage on "
+ "specification : '%s'\n", remain);
+ return 1;
}
- return(0);
+ return 0;
}
unsigned short eth_protocol(struct sk_buff *skb)
{
- return(eth_type_trans(skb, skb->dev));
+ return eth_type_trans(skb, skb->dev);
}
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c
index da946e3e1bf2..90d7f2e8ead8 100644
--- a/arch/um/drivers/net_user.c
+++ b/arch/um/drivers/net_user.c
@@ -1,34 +1,32 @@
-/*
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+/*
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include <stddef.h>
-#include <stdarg.h>
-#include <unistd.h>
#include <stdio.h>
+#include <unistd.h>
+#include <stdarg.h>
#include <errno.h>
-#include <stdlib.h>
+#include <stddef.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/wait.h>
-#include <sys/time.h>
-#include "user.h"
-#include "kern_util.h"
#include "net_user.h"
+#include "kern_constants.h"
#include "os.h"
#include "um_malloc.h"
-#include "kern_constants.h"
+#include "user.h"
int tap_open_common(void *dev, char *gate_addr)
{
int tap_addr[4];
- if(gate_addr == NULL)
+ if (gate_addr == NULL)
return 0;
- if(sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0],
- &tap_addr[1], &tap_addr[2], &tap_addr[3]) != 4){
- printk("Invalid tap IP address - '%s'\n", gate_addr);
+ if (sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0],
+ &tap_addr[1], &tap_addr[2], &tap_addr[3]) != 4) {
+ printk(UM_KERN_ERR "Invalid tap IP address - '%s'\n",
+ gate_addr);
return -EINVAL;
}
return 0;
@@ -38,15 +36,15 @@ void tap_check_ips(char *gate_addr, unsigned char *eth_addr)
{
int tap_addr[4];
- if((gate_addr != NULL) &&
- (sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0],
- &tap_addr[1], &tap_addr[2], &tap_addr[3]) == 4) &&
- (eth_addr[0] == tap_addr[0]) &&
- (eth_addr[1] == tap_addr[1]) &&
- (eth_addr[2] == tap_addr[2]) &&
- (eth_addr[3] == tap_addr[3])){
- printk("The tap IP address and the UML eth IP address"
- " must be different\n");
+ if ((gate_addr != NULL) &&
+ (sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0],
+ &tap_addr[1], &tap_addr[2], &tap_addr[3]) == 4) &&
+ (eth_addr[0] == tap_addr[0]) &&
+ (eth_addr[1] == tap_addr[1]) &&
+ (eth_addr[2] == tap_addr[2]) &&
+ (eth_addr[3] == tap_addr[3])) {
+ printk(UM_KERN_ERR "The tap IP address and the UML eth IP "
+ "address must be different\n");
}
}
@@ -57,24 +55,28 @@ void read_output(int fd, char *output, int len)
char c;
char *str;
- if(output == NULL){
+ if (output == NULL) {
output = &c;
len = sizeof(c);
}
-
+
*output = '\0';
- ret = os_read_file(fd, &remain, sizeof(remain));
+ ret = read(fd, &remain, sizeof(remain));
if (ret != sizeof(remain)) {
+ if (ret < 0)
+ ret = -errno;
expected = sizeof(remain);
str = "length";
goto err;
}
- while(remain != 0){
+ while (remain != 0) {
expected = (remain < len) ? remain : len;
- ret = os_read_file(fd, output, expected);
+ ret = read(fd, output, expected);
if (ret != expected) {
+ if (ret < 0)
+ ret = -errno;
str = "data";
goto err;
}
@@ -85,20 +87,22 @@ void read_output(int fd, char *output, int len)
err:
if (ret < 0)
- printk("read_output - read of %s failed, errno = %d\n", str, -ret);
+ printk(UM_KERN_ERR "read_output - read of %s failed, "
+ "errno = %d\n", str, -ret);
else
- printk("read_output - read of %s failed, read only %d of %d bytes\n", str, ret, expected);
+ printk(UM_KERN_ERR "read_output - read of %s failed, read only "
+ "%d of %d bytes\n", str, ret, expected);
}
int net_read(int fd, void *buf, int len)
{
int n;
- n = os_read_file(fd, buf, len);
+ n = read(fd, buf, len);
- if(n == -EAGAIN)
+ if ((n < 0) && (errno == EAGAIN))
return 0;
- else if(n == 0)
+ else if (n == 0)
return -ENOTCONN;
return n;
}
@@ -108,12 +112,12 @@ int net_recvfrom(int fd, void *buf, int len)
int n;
CATCH_EINTR(n = recvfrom(fd, buf, len, 0, NULL, NULL));
- if(n < 0){
- if(errno == EAGAIN)
+ if (n < 0) {
+ if (errno == EAGAIN)
return 0;
return -errno;
}
- else if(n == 0)
+ else if (n == 0)
return -ENOTCONN;
return n;
}
@@ -122,11 +126,11 @@ int net_write(int fd, void *buf, int len)
{
int n;
- n = os_write_file(fd, buf, len);
+ n = write(fd, buf, len);
- if(n == -EAGAIN)
+ if ((n < 0) && (errno == EAGAIN))
return 0;
- else if(n == 0)
+ else if (n == 0)
return -ENOTCONN;
return n;
}
@@ -136,12 +140,12 @@ int net_send(int fd, void *buf, int len)
int n;
CATCH_EINTR(n = send(fd, buf, len, 0));
- if(n < 0){
- if(errno == EAGAIN)
+ if (n < 0) {
+ if (errno == EAGAIN)
return 0;
return -errno;
}
- else if(n == 0)
+ else if (n == 0)
return -ENOTCONN;
return n;
}
@@ -152,12 +156,12 @@ int net_sendto(int fd, void *buf, int len, void *to, int sock_len)
CATCH_EINTR(n = sendto(fd, buf, len, 0, (struct sockaddr *) to,
sock_len));
- if(n < 0){
- if(errno == EAGAIN)
+ if (n < 0) {
+ if (errno == EAGAIN)
return 0;
return -errno;
}
- else if(n == 0)
+ else if (n == 0)
return -ENOTCONN;
return n;
}
@@ -171,7 +175,7 @@ static void change_pre_exec(void *arg)
{
struct change_pre_exec_data *data = arg;
- os_close_file(data->close_me);
+ close(data->close_me);
dup2(data->stdout, 1);
}
@@ -181,8 +185,9 @@ static int change_tramp(char **argv, char *output, int output_len)
struct change_pre_exec_data pe_data;
err = os_pipe(fds, 1, 0);
- if(err < 0){
- printk("change_tramp - pipe failed, err = %d\n", -err);
+ if (err < 0) {
+ printk(UM_KERN_ERR "change_tramp - pipe failed, err = %d\n",
+ -err);
return err;
}
pe_data.close_me = fds[0];
@@ -192,8 +197,8 @@ static int change_tramp(char **argv, char *output, int output_len)
if (pid > 0) /* Avoid hang as we won't get data in failure case. */
read_output(fds[0], output, output_len);
- os_close_file(fds[0]);
- os_close_file(fds[1]);
+ close(fds[0]);
+ close(fds[1]);
if (pid > 0)
CATCH_EINTR(err = waitpid(pid, NULL, 0));
@@ -206,25 +211,26 @@ static void change(char *dev, char *what, unsigned char *addr,
char addr_buf[sizeof("255.255.255.255\0")];
char netmask_buf[sizeof("255.255.255.255\0")];
char version[sizeof("nnnnn\0")];
- char *argv[] = { "uml_net", version, what, dev, addr_buf,
+ char *argv[] = { "uml_net", version, what, dev, addr_buf,
netmask_buf, NULL };
char *output;
int output_len, pid;
sprintf(version, "%d", UML_NET_VERSION);
sprintf(addr_buf, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
- sprintf(netmask_buf, "%d.%d.%d.%d", netmask[0], netmask[1],
+ sprintf(netmask_buf, "%d.%d.%d.%d", netmask[0], netmask[1],
netmask[2], netmask[3]);
output_len = UM_KERN_PAGE_SIZE;
output = kmalloc(output_len, UM_GFP_KERNEL);
- if(output == NULL)
- printk("change : failed to allocate output buffer\n");
+ if (output == NULL)
+ printk(UM_KERN_ERR "change : failed to allocate output "
+ "buffer\n");
pid = change_tramp(argv, output, output_len);
- if(pid < 0) return;
+ if (pid < 0) return;
- if(output != NULL){
+ if (output != NULL) {
printk("%s", output);
kfree(output);
}
@@ -246,13 +252,13 @@ char *split_if_spec(char *str, ...)
va_list ap;
va_start(ap, str);
- while((arg = va_arg(ap, char **)) != NULL){
- if(*str == '\0')
+ while ((arg = va_arg(ap, char **)) != NULL) {
+ if (*str == '\0')
return NULL;
end = strchr(str, ',');
- if(end != str)
+ if (end != str)
*arg = str;
- if(end == NULL)
+ if (end == NULL)
return NULL;
*end++ = '\0';
str = end;
diff --git a/arch/um/drivers/null.c b/arch/um/drivers/null.c
index 9016c68beee8..2b45a1446c86 100644
--- a/arch/um/drivers/null.c
+++ b/arch/um/drivers/null.c
@@ -1,31 +1,36 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+/*
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
* Licensed under the GPL
*/
-#include <stdlib.h>
+#include <stddef.h>
#include <errno.h>
+#include <fcntl.h>
#include "chan_user.h"
#include "os.h"
-/* This address is used only as a unique identifer */
+/* This address is used only as a unique identifier */
static int null_chan;
static void *null_init(char *str, int device, const struct chan_opts *opts)
{
- return(&null_chan);
+ return &null_chan;
}
static int null_open(int input, int output, int primary, void *d,
char **dev_out)
{
+ int fd;
+
*dev_out = NULL;
- return(os_open_file(DEV_NULL, of_rdwr(OPENFLAGS()), 0));
+
+ fd = open(DEV_NULL, O_RDWR);
+ return (fd < 0) ? -errno : fd;
}
static int null_read(int fd, char *c_out, void *unused)
{
- return(-ENODEV);
+ return -ENODEV;
}
static void null_free(void *data)
@@ -44,14 +49,3 @@ const struct chan_ops null_ops = {
.free = null_free,
.winch = 0,
};
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/pcap_kern.c b/arch/um/drivers/pcap_kern.c
index c329931673d6..3a750dd39be1 100644
--- a/arch/um/drivers/pcap_kern.c
+++ b/arch/um/drivers/pcap_kern.c
@@ -1,13 +1,11 @@
/*
- * Copyright (C) 2002 Jeff Dike <jdike@karaya.com>
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL.
*/
#include "linux/init.h"
-#include "linux/netdevice.h"
-#include "linux/etherdevice.h"
+#include <linux/netdevice.h>
#include "net_kern.h"
-#include "net_user.h"
#include "pcap_user.h"
struct pcap_init {
@@ -33,19 +31,14 @@ void pcap_init(struct net_device *dev, void *data)
printk("pcap backend, host interface %s\n", ppri->host_if);
}
-static int pcap_read(int fd, struct sk_buff **skb,
- struct uml_net_private *lp)
+static int pcap_read(int fd, struct sk_buff *skb, struct uml_net_private *lp)
{
- *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER);
- if(*skb == NULL)
- return -ENOMEM;
-
- return pcap_user_read(fd, skb_mac_header(*skb),
- (*skb)->dev->mtu + ETH_HEADER_OTHER,
+ return pcap_user_read(fd, skb_mac_header(skb),
+ skb->dev->mtu + ETH_HEADER_OTHER,
(struct pcap_data *) &lp->user);
}
-static int pcap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp)
+static int pcap_write(int fd, struct sk_buff *skb, struct uml_net_private *lp)
{
return -EPERM;
}
@@ -71,28 +64,29 @@ int pcap_setup(char *str, char **mac_out, void *data)
remain = split_if_spec(str, &host_if, &init->filter,
&options[0], &options[1], mac_out, NULL);
- if(remain != NULL){
+ if (remain != NULL) {
printk(KERN_ERR "pcap_setup - Extra garbage on "
"specification : '%s'\n", remain);
return 0;
}
- if(host_if != NULL)
+ if (host_if != NULL)
init->host_if = host_if;
- for(i = 0; i < ARRAY_SIZE(options); i++){
- if(options[i] == NULL)
+ for (i = 0; i < ARRAY_SIZE(options); i++) {
+ if (options[i] == NULL)
continue;
- if(!strcmp(options[i], "promisc"))
+ if (!strcmp(options[i], "promisc"))
init->promisc = 1;
- else if(!strcmp(options[i], "nopromisc"))
+ else if (!strcmp(options[i], "nopromisc"))
init->promisc = 0;
- else if(!strcmp(options[i], "optimize"))
+ else if (!strcmp(options[i], "optimize"))
init->optimize = 1;
- else if(!strcmp(options[i], "nooptimize"))
+ else if (!strcmp(options[i], "nooptimize"))
init->optimize = 0;
else {
- printk("pcap_setup : bad option - '%s'\n", options[i]);
+ printk(KERN_ERR "pcap_setup : bad option - '%s'\n",
+ options[i]);
return 0;
}
}
diff --git a/arch/um/drivers/pcap_user.c b/arch/um/drivers/pcap_user.c
index 1316456e2a28..e9809356c530 100644
--- a/arch/um/drivers/pcap_user.c
+++ b/arch/um/drivers/pcap_user.c
@@ -1,21 +1,17 @@
/*
- * Copyright (C) 2002 Jeff Dike <jdike@karaya.com>
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL.
*/
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
#include <errno.h>
#include <pcap.h>
+#include <string.h>
#include <asm/types.h>
#include "net_user.h"
#include "pcap_user.h"
-#include "user.h"
-#include "um_malloc.h"
#include "kern_constants.h"
-
-#define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER)
+#include "um_malloc.h"
+#include "user.h"
#define PCAP_FD(p) (*(int *)(p))
@@ -25,8 +21,9 @@ static int pcap_user_init(void *data, void *dev)
pcap_t *p;
char errors[PCAP_ERRBUF_SIZE];
- p = pcap_open_live(pri->host_if, MAX_PACKET, pri->promisc, 0, errors);
- if(p == NULL){
+ p = pcap_open_live(pri->host_if, ETH_MAX_PACKET + ETH_HEADER_OTHER,
+ pri->promisc, 0, errors);
+ if (p == NULL) {
printk(UM_KERN_ERR "pcap_user_init : pcap_open_live failed - "
"'%s'\n", errors);
return -EINVAL;
@@ -43,50 +40,55 @@ static int pcap_open(void *data)
__u32 netmask;
int err;
- if(pri->pcap == NULL)
+ if (pri->pcap == NULL)
return -ENODEV;
- if(pri->filter != NULL){
+ if (pri->filter != NULL) {
err = dev_netmask(pri->dev, &netmask);
- if(err < 0){
+ if (err < 0) {
printk(UM_KERN_ERR "pcap_open : dev_netmask failed\n");
return -EIO;
}
- pri->compiled = kmalloc(sizeof(struct bpf_program), UM_GFP_KERNEL);
- if(pri->compiled == NULL){
+ pri->compiled = kmalloc(sizeof(struct bpf_program),
+ UM_GFP_KERNEL);
+ if (pri->compiled == NULL) {
printk(UM_KERN_ERR "pcap_open : kmalloc failed\n");
return -ENOMEM;
}
- err = pcap_compile(pri->pcap,
- (struct bpf_program *) pri->compiled,
+ err = pcap_compile(pri->pcap,
+ (struct bpf_program *) pri->compiled,
pri->filter, pri->optimize, netmask);
- if(err < 0){
+ if (err < 0) {
printk(UM_KERN_ERR "pcap_open : pcap_compile failed - "
"'%s'\n", pcap_geterr(pri->pcap));
- return -EIO;
+ goto out;
}
err = pcap_setfilter(pri->pcap, pri->compiled);
- if(err < 0){
+ if (err < 0) {
printk(UM_KERN_ERR "pcap_open : pcap_setfilter "
"failed - '%s'\n", pcap_geterr(pri->pcap));
- return -EIO;
+ goto out;
}
}
return PCAP_FD(pri->pcap);
+
+ out:
+ kfree(pri->compiled);
+ return -EIO;
}
static void pcap_remove(void *data)
{
struct pcap_data *pri = data;
- if(pri->compiled != NULL)
+ if (pri->compiled != NULL)
pcap_freecode(pri->compiled);
- if(pri->pcap != NULL)
+ if (pri->pcap != NULL)
pcap_close(pri->pcap);
}
@@ -95,7 +97,7 @@ struct pcap_handler_data {
int len;
};
-static void handler(u_char *data, const struct pcap_pkthdr *header,
+static void handler(u_char *data, const struct pcap_pkthdr *header,
const u_char *packet)
{
int len;
@@ -115,12 +117,12 @@ int pcap_user_read(int fd, void *buffer, int len, struct pcap_data *pri)
int n;
n = pcap_dispatch(pri->pcap, 1, handler, (u_char *) &hdata);
- if(n < 0){
+ if (n < 0) {
printk(UM_KERN_ERR "pcap_dispatch failed - %s\n",
pcap_geterr(pri->pcap));
return -EIO;
}
- else if(n == 0)
+ else if (n == 0)
return 0;
return hdata.len;
}
@@ -130,8 +132,8 @@ const struct net_user_info pcap_user_info = {
.open = pcap_open,
.close = NULL,
.remove = pcap_remove,
- .set_mtu = NULL,
.add_address = NULL,
.delete_address = NULL,
- .max_packet = MAX_PACKET - ETH_HEADER_OTHER
+ .mtu = ETH_MAX_PACKET,
+ .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER,
};
diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c
index 1c8efd95c421..330543b3129b 100644
--- a/arch/um/drivers/port_kern.c
+++ b/arch/um/drivers/port_kern.c
@@ -1,24 +1,16 @@
/*
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
* Licensed under the GPL
*/
-#include "linux/list.h"
-#include "linux/sched.h"
-#include "linux/slab.h"
+#include "linux/completion.h"
#include "linux/interrupt.h"
-#include "linux/spinlock.h"
-#include "linux/errno.h"
+#include "linux/list.h"
#include "asm/atomic.h"
-#include "asm/semaphore.h"
-#include "asm/errno.h"
-#include "kern_util.h"
-#include "kern.h"
-#include "irq_user.h"
-#include "irq_kern.h"
-#include "port.h"
#include "init.h"
+#include "irq_kern.h"
#include "os.h"
+#include "port.h"
struct port_list {
struct list_head list;
@@ -53,8 +45,8 @@ static irqreturn_t pipe_interrupt(int irq, void *data)
int fd;
fd = os_rcv_fd(conn->socket[0], &conn->helper_pid);
- if(fd < 0){
- if(fd == -EAGAIN)
+ if (fd < 0) {
+ if (fd == -EAGAIN)
return IRQ_NONE;
printk(KERN_ERR "pipe_interrupt : os_rcv_fd returned %d\n",
@@ -81,18 +73,18 @@ static irqreturn_t pipe_interrupt(int irq, void *data)
static int port_accept(struct port_list *port)
{
struct connection *conn;
- int fd, socket[2], pid, ret = 0;
+ int fd, socket[2], pid;
fd = port_connection(port->fd, socket, &pid);
- if(fd < 0){
- if(fd != -EAGAIN)
+ if (fd < 0) {
+ if (fd != -EAGAIN)
printk(KERN_ERR "port_accept : port_connection "
"returned %d\n", -fd);
goto out;
}
conn = kmalloc(sizeof(*conn), GFP_ATOMIC);
- if(conn == NULL){
+ if (conn == NULL) {
printk(KERN_ERR "port_accept : failed to allocate "
"connection\n");
goto out_close;
@@ -104,17 +96,17 @@ static int port_accept(struct port_list *port)
.telnetd_pid = pid,
.port = port });
- if(um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt,
+ if (um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt,
IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
- "telnetd", conn)){
+ "telnetd", conn)) {
printk(KERN_ERR "port_accept : failed to get IRQ for "
"telnetd\n");
goto out_free;
}
- if(atomic_read(&port->wait_count) == 0){
+ if (atomic_read(&port->wait_count) == 0) {
os_write_file(fd, NO_WAITER_MSG, sizeof(NO_WAITER_MSG));
- printk("No one waiting for port\n");
+ printk(KERN_ERR "No one waiting for port\n");
}
list_add(&conn->list, &port->pending);
return 1;
@@ -123,28 +115,29 @@ static int port_accept(struct port_list *port)
kfree(conn);
out_close:
os_close_file(fd);
- if(pid != -1)
- os_kill_process(pid, 1);
+ os_kill_process(pid, 1);
out:
- return ret;
+ return 0;
}
static DECLARE_MUTEX(ports_sem);
static LIST_HEAD(ports);
-void port_work_proc(struct work_struct *unused)
+static void port_work_proc(struct work_struct *unused)
{
struct port_list *port;
struct list_head *ele;
unsigned long flags;
local_irq_save(flags);
- list_for_each(ele, &ports){
+ list_for_each(ele, &ports) {
port = list_entry(ele, struct port_list, list);
- if(!port->has_connection)
+ if (!port->has_connection)
continue;
+
reactivate_fd(port->fd, ACCEPT_IRQ);
- while(port_accept(port)) ;
+ while (port_accept(port))
+ ;
port->has_connection = 0;
}
local_irq_restore(flags);
@@ -169,25 +162,27 @@ void *port_data(int port_num)
int fd;
down(&ports_sem);
- list_for_each(ele, &ports){
+ list_for_each(ele, &ports) {
port = list_entry(ele, struct port_list, list);
- if(port->port == port_num) goto found;
+ if (port->port == port_num)
+ goto found;
}
port = kmalloc(sizeof(struct port_list), GFP_KERNEL);
- if(port == NULL){
+ if (port == NULL) {
printk(KERN_ERR "Allocation of port list failed\n");
goto out;
}
fd = port_listen_fd(port_num);
- if(fd < 0){
+ if (fd < 0) {
printk(KERN_ERR "binding to port %d failed, errno = %d\n",
port_num, -fd);
goto out_free;
}
- if(um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt,
+
+ if (um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt,
IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
- "port", port)){
+ "port", port)) {
printk(KERN_ERR "Failed to get IRQ for port %d\n", port_num);
goto out_close;
}
@@ -206,7 +201,7 @@ void *port_data(int port_num)
found:
dev = kmalloc(sizeof(struct port_dev), GFP_KERNEL);
- if(dev == NULL){
+ if (dev == NULL) {
printk(KERN_ERR "Allocation of port device entry failed\n");
goto out;
}
@@ -216,10 +211,10 @@ void *port_data(int port_num)
.telnetd_pid = -1 });
goto out;
- out_free:
- kfree(port);
out_close:
os_close_file(fd);
+ out_free:
+ kfree(port);
out:
up(&ports_sem);
return dev;
@@ -233,9 +228,9 @@ int port_wait(void *data)
int fd;
atomic_inc(&port->wait_count);
- while(1){
+ while (1) {
fd = -ERESTARTSYS;
- if(wait_for_completion_interruptible(&port->done))
+ if (wait_for_completion_interruptible(&port->done))
goto out;
spin_lock(&port->lock);
@@ -258,7 +253,8 @@ int port_wait(void *data)
*/
free_irq(TELNETD_IRQ, conn);
- if(conn->fd >= 0) break;
+ if (conn->fd >= 0)
+ break;
os_close_file(conn->fd);
kfree(conn);
}
@@ -276,9 +272,9 @@ void port_remove_dev(void *d)
{
struct port_dev *dev = d;
- if(dev->helper_pid != -1)
+ if (dev->helper_pid != -1)
os_kill_process(dev->helper_pid, 0);
- if(dev->telnetd_pid != -1)
+ if (dev->telnetd_pid != -1)
os_kill_process(dev->telnetd_pid, 1);
dev->helper_pid = -1;
dev->telnetd_pid = -1;
@@ -297,7 +293,7 @@ static void free_port(void)
struct list_head *ele;
struct port_list *port;
- list_for_each(ele, &ports){
+ list_for_each(ele, &ports) {
port = list_entry(ele, struct port_list, list);
free_irq_by_fd(port->fd);
os_close_file(port->fd);
diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c
index c799b00012c7..addd75902656 100644
--- a/arch/um/drivers/port_user.c
+++ b/arch/um/drivers/port_user.c
@@ -1,24 +1,20 @@
/*
- * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
* Licensed under the GPL
*/
#include <stdio.h>
-#include <stddef.h>
#include <stdlib.h>
-#include <string.h>
#include <errno.h>
-#include <unistd.h>
#include <termios.h>
-#include <sys/socket.h>
-#include <sys/un.h>
+#include <unistd.h>
#include <netinet/in.h>
-#include "kern_util.h"
-#include "user.h"
#include "chan_user.h"
-#include "port.h"
+#include "kern_constants.h"
#include "os.h"
+#include "port.h"
#include "um_malloc.h"
+#include "user.h"
struct port_chan {
int raw;
@@ -34,24 +30,25 @@ static void *port_init(char *str, int device, const struct chan_opts *opts)
char *end;
int port;
- if(*str != ':'){
- printk("port_init : channel type 'port' must specify a "
- "port number\n");
+ if (*str != ':') {
+ printk(UM_KERN_ERR "port_init : channel type 'port' must "
+ "specify a port number\n");
return NULL;
}
str++;
port = strtoul(str, &end, 0);
- if((*end != '\0') || (end == str)){
- printk("port_init : couldn't parse port '%s'\n", str);
+ if ((*end != '\0') || (end == str)) {
+ printk(UM_KERN_ERR "port_init : couldn't parse port '%s'\n",
+ str);
return NULL;
}
kern_data = port_data(port);
- if(kern_data == NULL)
+ if (kern_data == NULL)
return NULL;
data = kmalloc(sizeof(*data), UM_GFP_KERNEL);
- if(data == NULL)
+ if (data == NULL)
goto err;
*data = ((struct port_chan) { .raw = opts->raw,
@@ -79,13 +76,13 @@ static int port_open(int input, int output, int primary, void *d,
int fd, err;
fd = port_wait(data->kernel_data);
- if((fd >= 0) && data->raw){
+ if ((fd >= 0) && data->raw) {
CATCH_EINTR(err = tcgetattr(fd, &data->tt));
- if(err)
+ if (err)
return err;
err = raw(fd);
- if(err)
+ if (err)
return err;
}
*dev_out = data->dev;
@@ -119,11 +116,11 @@ int port_listen_fd(int port)
int fd, err, arg;
fd = socket(PF_INET, SOCK_STREAM, 0);
- if(fd == -1)
+ if (fd == -1)
return -errno;
arg = 1;
- if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &arg, sizeof(arg)) < 0){
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &arg, sizeof(arg)) < 0) {
err = -errno;
goto out;
}
@@ -131,23 +128,23 @@ int port_listen_fd(int port)
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
- if(bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0){
+ if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
err = -errno;
goto out;
}
- if(listen(fd, 1) < 0){
+ if (listen(fd, 1) < 0) {
err = -errno;
goto out;
}
err = os_set_fd_block(fd, 0);
- if(err < 0)
+ if (err < 0)
goto out;
return fd;
out:
- os_close_file(fd);
+ close(fd);
return err;
}
@@ -163,10 +160,10 @@ void port_pre_exec(void *arg)
dup2(data->sock_fd, 0);
dup2(data->sock_fd, 1);
dup2(data->sock_fd, 2);
- os_close_file(data->sock_fd);
+ close(data->sock_fd);
dup2(data->pipe_fd, 3);
- os_shutdown_socket(3, 1, 0);
- os_close_file(data->pipe_fd);
+ shutdown(3, SHUT_RD);
+ close(data->pipe_fd);
}
int port_connection(int fd, int *socket, int *pid_out)
@@ -176,12 +173,12 @@ int port_connection(int fd, int *socket, int *pid_out)
"/usr/lib/uml/port-helper", NULL };
struct port_pre_exec_data data;
- new = os_accept_connection(fd);
- if(new < 0)
- return new;
+ new = accept(fd, NULL, 0);
+ if (new < 0)
+ return -errno;
err = os_pipe(socket, 0, 0);
- if(err < 0)
+ if (err < 0)
goto out_close;
data = ((struct port_pre_exec_data)
@@ -189,18 +186,18 @@ int port_connection(int fd, int *socket, int *pid_out)
.pipe_fd = socket[1] });
err = run_helper(port_pre_exec, &data, argv);
- if(err < 0)
+ if (err < 0)
goto out_shutdown;
*pid_out = err;
return new;
out_shutdown:
- os_shutdown_socket(socket[0], 1, 1);
- os_close_file(socket[0]);
- os_shutdown_socket(socket[1], 1, 1);
- os_close_file(socket[1]);
+ shutdown(socket[0], SHUT_RDWR);
+ close(socket[0]);
+ shutdown(socket[1], SHUT_RDWR);
+ close(socket[1]);
out_close:
- os_close_file(new);
+ close(new);
return err;
}
diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c
index 1e3fd619a837..49c79dda6046 100644
--- a/arch/um/drivers/pty.c
+++ b/arch/um/drivers/pty.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -6,16 +6,16 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
-#include <string.h>
-#include <fcntl.h>
#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
#include <termios.h>
#include <sys/stat.h>
#include "chan_user.h"
-#include "os.h"
-#include "user.h"
#include "kern_constants.h"
+#include "os.h"
#include "um_malloc.h"
+#include "user.h"
struct pty_chan {
void (*announce)(char *dev_name, int dev);
@@ -33,7 +33,7 @@ static void *pty_chan_init(char *str, int device, const struct chan_opts *opts)
if (data == NULL)
return NULL;
- *data = ((struct pty_chan) { .announce = opts->announce,
+ *data = ((struct pty_chan) { .announce = opts->announce,
.dev = device,
.raw = opts->raw });
return data;
@@ -56,11 +56,11 @@ static int pts_open(int input, int output, int primary, void *d,
if (data->raw) {
CATCH_EINTR(err = tcgetattr(fd, &data->tt));
if (err)
- return err;
+ goto out_close;
err = raw(fd);
if (err)
- return err;
+ goto out_close;
}
dev = ptsname(fd);
@@ -71,6 +71,10 @@ static int pts_open(int input, int output, int primary, void *d,
(*data->announce)(dev, data->dev);
return fd;
+
+out_close:
+ close(fd);
+ return err;
}
static int getmaster(char *line)
@@ -97,7 +101,7 @@ static int getmaster(char *line)
*tp = 't';
err = access(line, R_OK | W_OK);
*tp = 'p';
- if(!err)
+ if (!err)
return master;
close(master);
}
@@ -119,12 +123,14 @@ static int pty_open(int input, int output, int primary, void *d,
if (fd < 0)
return fd;
- if(data->raw){
+ if (data->raw) {
err = raw(fd);
- if (err)
+ if (err) {
+ close(fd);
return err;
+ }
}
-
+
if (data->announce)
(*data->announce)(dev, data->dev);
diff --git a/arch/um/drivers/slip_kern.c b/arch/um/drivers/slip_kern.c
index 125c44f77638..6b4a0f9e38de 100644
--- a/arch/um/drivers/slip_kern.c
+++ b/arch/um/drivers/slip_kern.c
@@ -1,11 +1,12 @@
-#include "linux/kernel.h"
-#include "linux/stddef.h"
-#include "linux/init.h"
-#include "linux/netdevice.h"
-#include "linux/if_arp.h"
+/*
+ * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL.
+ */
+
+#include <linux/if_arp.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
#include "net_kern.h"
-#include "net_user.h"
-#include "kern.h"
#include "slip.h"
struct slip_init {
@@ -30,10 +31,8 @@ void slip_init(struct net_device *dev, void *data)
slip_proto_init(&spri->slip);
dev->init = NULL;
- dev->header_cache_update = NULL;
- dev->hard_header_cache = NULL;
- dev->hard_header = NULL;
dev->hard_header_len = 0;
+ dev->header_ops = NULL;
dev->addr_len = 0;
dev->type = ARPHRD_SLIP;
dev->tx_queue_len = 256;
@@ -43,21 +42,19 @@ void slip_init(struct net_device *dev, void *data)
static unsigned short slip_protocol(struct sk_buff *skbuff)
{
- return(htons(ETH_P_IP));
+ return htons(ETH_P_IP);
}
-static int slip_read(int fd, struct sk_buff **skb,
- struct uml_net_private *lp)
+static int slip_read(int fd, struct sk_buff *skb, struct uml_net_private *lp)
{
- return(slip_user_read(fd, skb_mac_header(*skb), (*skb)->dev->mtu,
- (struct slip_data *) &lp->user));
+ return slip_user_read(fd, skb_mac_header(skb), skb->dev->mtu,
+ (struct slip_data *) &lp->user);
}
-static int slip_write(int fd, struct sk_buff **skb,
- struct uml_net_private *lp)
+static int slip_write(int fd, struct sk_buff *skb, struct uml_net_private *lp)
{
- return(slip_user_write(fd, (*skb)->data, (*skb)->len,
- (struct slip_data *) &lp->user));
+ return slip_user_write(fd, skb->data, skb->len,
+ (struct slip_data *) &lp->user);
}
const struct net_kern_info slip_kern_info = {
@@ -71,12 +68,11 @@ static int slip_setup(char *str, char **mac_out, void *data)
{
struct slip_init *init = data;
- *init = ((struct slip_init)
- { .gate_addr = NULL });
+ *init = ((struct slip_init) { .gate_addr = NULL });
- if(str[0] != '\0')
+ if (str[0] != '\0')
init->gate_addr = str;
- return(1);
+ return 1;
}
static struct transport slip_transport = {
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c
index c0b73c28cff0..5f06204d6871 100644
--- a/arch/um/drivers/slip_user.c
+++ b/arch/um/drivers/slip_user.c
@@ -1,21 +1,22 @@
+/*
+ * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL.
+ */
+
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
-#include <stddef.h>
-#include <sched.h>
-#include <string.h>
#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
#include <sys/termios.h>
#include <sys/wait.h>
-#include <sys/signal.h>
-#include "kern_util.h"
-#include "user.h"
+#include "kern_constants.h"
#include "net_user.h"
-#include "slip.h"
-#include "slip_common.h"
#include "os.h"
+#include "slip.h"
#include "um_malloc.h"
-#include "kern_constants.h"
+#include "user.h"
static int slip_user_init(void *data, void *dev)
{
@@ -31,8 +32,9 @@ static int set_up_tty(int fd)
struct termios tios;
if (tcgetattr(fd, &tios) < 0) {
- printk("could not get initial terminal attributes\n");
- return(-1);
+ printk(UM_KERN_ERR "could not get initial terminal "
+ "attributes\n");
+ return -1;
}
tios.c_cflag = CS8 | CREAD | HUPCL | CLOCAL;
@@ -48,10 +50,10 @@ static int set_up_tty(int fd)
cfsetispeed(&tios, B38400);
if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
- printk("failed to set terminal attributes\n");
- return(-1);
+ printk(UM_KERN_ERR "failed to set terminal attributes\n");
+ return -1;
}
- return(0);
+ return 0;
}
struct slip_pre_exec_data {
@@ -64,9 +66,11 @@ static void slip_pre_exec(void *arg)
{
struct slip_pre_exec_data *data = arg;
- if(data->stdin >= 0) dup2(data->stdin, 0);
+ if (data->stdin >= 0)
+ dup2(data->stdin, 0);
dup2(data->stdout, 1);
- if(data->close_me >= 0) os_close_file(data->close_me);
+ if (data->close_me >= 0)
+ close(data->close_me);
}
static int slip_tramp(char **argv, int fd)
@@ -76,8 +80,9 @@ static int slip_tramp(char **argv, int fd)
int status, pid, fds[2], err, output_len;
err = os_pipe(fds, 1, 0);
- if(err < 0){
- printk("slip_tramp : pipe failed, err = %d\n", -err);
+ if (err < 0) {
+ printk(UM_KERN_ERR "slip_tramp : pipe failed, err = %d\n",
+ -err);
goto out;
}
@@ -86,41 +91,42 @@ static int slip_tramp(char **argv, int fd)
pe_data.stdout = fds[1];
pe_data.close_me = fds[0];
err = run_helper(slip_pre_exec, &pe_data, argv);
- if(err < 0)
+ if (err < 0)
goto out_close;
pid = err;
output_len = UM_KERN_PAGE_SIZE;
output = kmalloc(output_len, UM_GFP_KERNEL);
- if(output == NULL){
- printk("slip_tramp : failed to allocate output buffer\n");
+ if (output == NULL) {
+ printk(UM_KERN_ERR "slip_tramp : failed to allocate output "
+ "buffer\n");
os_kill_process(pid, 1);
err = -ENOMEM;
goto out_free;
}
- os_close_file(fds[1]);
+ close(fds[1]);
read_output(fds[0], output, output_len);
printk("%s", output);
CATCH_EINTR(err = waitpid(pid, &status, 0));
- if(err < 0)
+ if (err < 0)
err = errno;
- else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)){
- printk("'%s' didn't exit with status 0\n", argv[0]);
+ else if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) {
+ printk(UM_KERN_ERR "'%s' didn't exit with status 0\n", argv[0]);
err = -EINVAL;
}
else err = 0;
- os_close_file(fds[0]);
+ close(fds[0]);
out_free:
kfree(output);
return err;
out_close:
- os_close_file(fds[0]);
- os_close_file(fds[1]);
+ close(fds[0]);
+ close(fds[1]);
out:
return err;
}
@@ -130,60 +136,64 @@ static int slip_open(void *data)
struct slip_data *pri = data;
char version_buf[sizeof("nnnnn\0")];
char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")];
- char *argv[] = { "uml_net", version_buf, "slip", "up", gate_buf,
+ char *argv[] = { "uml_net", version_buf, "slip", "up", gate_buf,
NULL };
int sfd, mfd, err;
err = get_pty();
- if(err < 0){
- printk("slip-open : Failed to open pty, err = %d\n", -err);
+ if (err < 0) {
+ printk(UM_KERN_ERR "slip-open : Failed to open pty, err = %d\n",
+ -err);
goto out;
}
mfd = err;
- err = os_open_file(ptsname(mfd), of_rdwr(OPENFLAGS()), 0);
- if(err < 0){
- printk("Couldn't open tty for slip line, err = %d\n", -err);
+ err = open(ptsname(mfd), O_RDWR, 0);
+ if (err < 0) {
+ printk(UM_KERN_ERR "Couldn't open tty for slip line, "
+ "err = %d\n", -err);
goto out_close;
}
sfd = err;
- if(set_up_tty(sfd))
+ if (set_up_tty(sfd))
goto out_close2;
pri->slave = sfd;
pri->slip.pos = 0;
pri->slip.esc = 0;
- if(pri->gate_addr != NULL){
+ if (pri->gate_addr != NULL) {
sprintf(version_buf, "%d", UML_NET_VERSION);
strcpy(gate_buf, pri->gate_addr);
err = slip_tramp(argv, sfd);
- if(err < 0){
- printk("slip_tramp failed - err = %d\n", -err);
+ if (err < 0) {
+ printk(UM_KERN_ERR "slip_tramp failed - err = %d\n",
+ -err);
goto out_close2;
}
err = os_get_ifname(pri->slave, pri->name);
- if(err < 0){
- printk("get_ifname failed, err = %d\n", -err);
+ if (err < 0) {
+ printk(UM_KERN_ERR "get_ifname failed, err = %d\n",
+ -err);
goto out_close2;
}
iter_addresses(pri->dev, open_addr, pri->name);
}
else {
err = os_set_slip(sfd);
- if(err < 0){
- printk("Failed to set slip discipline encapsulation - "
- "err = %d\n", -err);
+ if (err < 0) {
+ printk(UM_KERN_ERR "Failed to set slip discipline "
+ "encapsulation - err = %d\n", -err);
goto out_close2;
}
}
- return(mfd);
+ return mfd;
out_close2:
- os_close_file(sfd);
+ close(sfd);
out_close:
- os_close_file(mfd);
+ close(mfd);
out:
return err;
}
@@ -192,21 +202,21 @@ static void slip_close(int fd, void *data)
{
struct slip_data *pri = data;
char version_buf[sizeof("nnnnn\0")];
- char *argv[] = { "uml_net", version_buf, "slip", "down", pri->name,
+ char *argv[] = { "uml_net", version_buf, "slip", "down", pri->name,
NULL };
int err;
- if(pri->gate_addr != NULL)
+ if (pri->gate_addr != NULL)
iter_addresses(pri->dev, close_addr, pri->name);
sprintf(version_buf, "%d", UML_NET_VERSION);
err = slip_tramp(argv, pri->slave);
- if(err != 0)
- printk("slip_tramp failed - errno = %d\n", -err);
- os_close_file(fd);
- os_close_file(pri->slave);
+ if (err != 0)
+ printk(UM_KERN_ERR "slip_tramp failed - errno = %d\n", -err);
+ close(fd);
+ close(pri->slave);
pri->slave = -1;
}
@@ -220,17 +230,13 @@ int slip_user_write(int fd, void *buf, int len, struct slip_data *pri)
return slip_proto_write(fd, buf, len, &pri->slip);
}
-static int slip_set_mtu(int mtu, void *data)
-{
- return(mtu);
-}
-
static void slip_add_addr(unsigned char *addr, unsigned char *netmask,
void *data)
{
struct slip_data *pri = data;
- if(pri->slave < 0) return;
+ if (pri->slave < 0)
+ return;
open_addr(addr, netmask, pri->name);
}
@@ -239,7 +245,8 @@ static void slip_del_addr(unsigned char *addr, unsigned char *netmask,
{
struct slip_data *pri = data;
- if(pri->slave < 0) return;
+ if (pri->slave < 0)
+ return;
close_addr(addr, netmask, pri->name);
}
@@ -248,8 +255,8 @@ const struct net_user_info slip_user_info = {
.open = slip_open,
.close = slip_close,
.remove = NULL,
- .set_mtu = slip_set_mtu,
.add_address = slip_add_addr,
.delete_address = slip_del_addr,
- .max_packet = BUF_SIZE
+ .mtu = BUF_SIZE,
+ .max_packet = BUF_SIZE,
};
diff --git a/arch/um/drivers/slirp_kern.c b/arch/um/drivers/slirp_kern.c
index 0a0324a6d290..d987af277db9 100644
--- a/arch/um/drivers/slirp_kern.c
+++ b/arch/um/drivers/slirp_kern.c
@@ -1,11 +1,14 @@
-#include "linux/kernel.h"
-#include "linux/stddef.h"
+/*
+ * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL.
+ */
+
+#include <linux/if_arp.h>
#include "linux/init.h"
-#include "linux/netdevice.h"
-#include "linux/if_arp.h"
+#include <linux/netdevice.h>
+#include <linux/string.h>
#include "net_kern.h"
#include "net_user.h"
-#include "kern.h"
#include "slirp.h"
struct slirp_init {
@@ -31,37 +34,32 @@ void slirp_init(struct net_device *dev, void *data)
dev->init = NULL;
dev->hard_header_len = 0;
- dev->header_cache_update = NULL;
- dev->hard_header_cache = NULL;
- dev->hard_header = NULL;
+ dev->header_ops = NULL;
dev->addr_len = 0;
dev->type = ARPHRD_SLIP;
dev->tx_queue_len = 256;
dev->flags = IFF_NOARP;
printk("SLIRP backend - command line:");
- for(i=0;spri->argw.argv[i]!=NULL;i++) {
+ for (i = 0; spri->argw.argv[i] != NULL; i++)
printk(" '%s'",spri->argw.argv[i]);
- }
printk("\n");
}
static unsigned short slirp_protocol(struct sk_buff *skbuff)
{
- return(htons(ETH_P_IP));
+ return htons(ETH_P_IP);
}
-static int slirp_read(int fd, struct sk_buff **skb,
- struct uml_net_private *lp)
+static int slirp_read(int fd, struct sk_buff *skb, struct uml_net_private *lp)
{
- return(slirp_user_read(fd, skb_mac_header(*skb), (*skb)->dev->mtu,
- (struct slirp_data *) &lp->user));
+ return slirp_user_read(fd, skb_mac_header(skb), skb->dev->mtu,
+ (struct slirp_data *) &lp->user);
}
-static int slirp_write(int fd, struct sk_buff **skb,
- struct uml_net_private *lp)
+static int slirp_write(int fd, struct sk_buff *skb, struct uml_net_private *lp)
{
- return(slirp_user_write(fd, (*skb)->data, (*skb)->len,
- (struct slirp_data *) &lp->user));
+ return slirp_user_write(fd, skb->data, skb->len,
+ (struct slirp_data *) &lp->user);
}
const struct net_kern_info slirp_kern_info = {
@@ -76,31 +74,32 @@ static int slirp_setup(char *str, char **mac_out, void *data)
struct slirp_init *init = data;
int i=0;
- *init = ((struct slirp_init)
- { .argw = { { "slirp", NULL } } });
+ *init = ((struct slirp_init) { .argw = { { "slirp", NULL } } });
str = split_if_spec(str, mac_out, NULL);
- if(str == NULL) { /* no command line given after MAC addr */
- return(1);
- }
+ if (str == NULL) /* no command line given after MAC addr */
+ return 1;
do {
- if(i>=SLIRP_MAX_ARGS-1) {
- printk("slirp_setup: truncating slirp arguments\n");
+ if (i >= SLIRP_MAX_ARGS - 1) {
+ printk(KERN_WARNING "slirp_setup: truncating slirp "
+ "arguments\n");
break;
}
init->argw.argv[i++] = str;
while(*str && *str!=',') {
- if(*str=='_') *str=' ';
+ if (*str == '_')
+ *str=' ';
str++;
}
- if(*str!=',')
+ if (*str != ',')
break;
- *str++='\0';
- } while(1);
- init->argw.argv[i]=NULL;
- return(1);
+ *str++ = '\0';
+ } while (1);
+
+ init->argw.argv[i] = NULL;
+ return 1;
}
static struct transport slirp_transport = {
diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c
index 0e462f64f227..1865089ff41a 100644
--- a/arch/um/drivers/slirp_user.c
+++ b/arch/um/drivers/slirp_user.c
@@ -1,18 +1,17 @@
-#include <stdio.h>
-#include <stdlib.h>
+/*
+ * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL.
+ */
+
#include <unistd.h>
-#include <stddef.h>
-#include <sched.h>
-#include <string.h>
#include <errno.h>
+#include <string.h>
#include <sys/wait.h>
-#include <sys/signal.h>
-#include "kern_util.h"
-#include "user.h"
+#include "kern_constants.h"
#include "net_user.h"
-#include "slirp.h"
-#include "slip_common.h"
#include "os.h"
+#include "slirp.h"
+#include "user.h"
static int slirp_user_init(void *data, void *dev)
{
@@ -31,8 +30,10 @@ static void slirp_pre_exec(void *arg)
{
struct slirp_pre_exec_data *data = arg;
- if(data->stdin != -1) dup2(data->stdin, 0);
- if(data->stdout != -1) dup2(data->stdout, 1);
+ if (data->stdin != -1)
+ dup2(data->stdin, 0);
+ if (data->stdout != -1)
+ dup2(data->stdout, 1);
}
static int slirp_tramp(char **argv, int fd)
@@ -44,7 +45,7 @@ static int slirp_tramp(char **argv, int fd)
pe_data.stdout = fd;
pid = run_helper(slirp_pre_exec, &pe_data, argv);
- return(pid);
+ return pid;
}
static int slirp_open(void *data)
@@ -53,12 +54,12 @@ static int slirp_open(void *data)
int fds[2], pid, err;
err = os_pipe(fds, 1, 1);
- if(err)
- return(err);
+ if (err)
+ return err;
err = slirp_tramp(pri->argw.argv, fds[1]);
- if(err < 0){
- printk("slirp_tramp failed - errno = %d\n", -err);
+ if (err < 0) {
+ printk(UM_KERN_ERR "slirp_tramp failed - errno = %d\n", -err);
goto out;
}
pid = err;
@@ -68,10 +69,10 @@ static int slirp_open(void *data)
pri->slip.esc = 0;
pri->pid = err;
- return(fds[0]);
+ return fds[0];
out:
- os_close_file(fds[0]);
- os_close_file(fds[1]);
+ close(fds[0]);
+ close(fds[1]);
return err;
}
@@ -80,31 +81,33 @@ static void slirp_close(int fd, void *data)
struct slirp_data *pri = data;
int status,err;
- os_close_file(fd);
- os_close_file(pri->slave);
+ close(fd);
+ close(pri->slave);
pri->slave = -1;
- if(pri->pid<1) {
- printk("slirp_close: no child process to shut down\n");
+ if (pri->pid<1) {
+ printk(UM_KERN_ERR "slirp_close: no child process to shut "
+ "down\n");
return;
}
#if 0
- if(kill(pri->pid, SIGHUP)<0) {
- printk("slirp_close: sending hangup to %d failed (%d)\n",
- pri->pid, errno);
+ if (kill(pri->pid, SIGHUP)<0) {
+ printk(UM_KERN_ERR "slirp_close: sending hangup to %d failed "
+ "(%d)\n", pri->pid, errno);
}
#endif
CATCH_EINTR(err = waitpid(pri->pid, &status, WNOHANG));
- if(err < 0) {
- printk("slirp_close: waitpid returned %d\n", errno);
+ if (err < 0) {
+ printk(UM_KERN_ERR "slirp_close: waitpid returned %d\n", errno);
return;
}
- if(err == 0) {
- printk("slirp_close: process %d has not exited\n", pri->pid);
+ if (err == 0) {
+ printk(UM_KERN_ERR "slirp_close: process %d has not exited\n",
+ pri->pid);
return;
}
@@ -121,18 +124,13 @@ int slirp_user_write(int fd, void *buf, int len, struct slirp_data *pri)
return slip_proto_write(fd, buf, len, &pri->slip);
}
-static int slirp_set_mtu(int mtu, void *data)
-{
- return(mtu);
-}
-
const struct net_user_info slirp_user_info = {
.init = slirp_user_init,
.open = slirp_open,
.close = slirp_close,
.remove = NULL,
- .set_mtu = slirp_set_mtu,
.add_address = NULL,
.delete_address = NULL,
- .max_packet = BUF_SIZE
+ .mtu = BUF_SIZE,
+ .max_packet = BUF_SIZE,
};
diff --git a/arch/um/drivers/stderr_console.c b/arch/um/drivers/stderr_console.c
index 4739dd527b43..d07a97f8b994 100644
--- a/arch/um/drivers/stderr_console.c
+++ b/arch/um/drivers/stderr_console.c
@@ -8,7 +8,7 @@
/* trivial console driver -- simply dump everything to stderr */
/*
- * Don't register by default -- as this registeres very early in the
+ * Don't register by default -- as this registers very early in the
* boot process it becomes the default console.
*
* Initialized at init time.
diff --git a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c
index a9f87e19c5bf..c930fedc5172 100644
--- a/arch/um/drivers/tty.c
+++ b/arch/um/drivers/tty.c
@@ -1,16 +1,16 @@
/*
- * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
* Licensed under the GPL
*/
-#include <stdio.h>
-#include <termios.h>
#include <errno.h>
-#include <unistd.h>
+#include <fcntl.h>
+#include <termios.h>
#include "chan_user.h"
-#include "user.h"
+#include "kern_constants.h"
#include "os.h"
#include "um_malloc.h"
+#include "user.h"
struct tty_chan {
char *dev;
@@ -22,15 +22,15 @@ static void *tty_chan_init(char *str, int device, const struct chan_opts *opts)
{
struct tty_chan *data;
- if(*str != ':'){
- printk("tty_init : channel type 'tty' must specify "
+ if (*str != ':') {
+ printk(UM_KERN_ERR "tty_init : channel type 'tty' must specify "
"a device\n");
return NULL;
}
str++;
data = kmalloc(sizeof(*data), UM_GFP_KERNEL);
- if(data == NULL)
+ if (data == NULL)
return NULL;
*data = ((struct tty_chan) { .dev = str,
.raw = opts->raw });
@@ -42,19 +42,26 @@ static int tty_open(int input, int output, int primary, void *d,
char **dev_out)
{
struct tty_chan *data = d;
- int fd, err;
+ int fd, err, mode = 0;
+
+ if (input && output)
+ mode = O_RDWR;
+ else if (input)
+ mode = O_RDONLY;
+ else if (output)
+ mode = O_WRONLY;
- fd = os_open_file(data->dev, of_set_rw(OPENFLAGS(), input, output), 0);
- if(fd < 0)
- return fd;
+ fd = open(data->dev, mode);
+ if (fd < 0)
+ return -errno;
- if(data->raw){
+ if (data->raw) {
CATCH_EINTR(err = tcgetattr(fd, &data->tt));
- if(err)
+ if (err)
return err;
err = raw(fd);
- if(err)
+ if (err)
return err;
}
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 0eabe73c964d..7e6cdde62ead 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -35,6 +35,7 @@
#include "linux/genhd.h"
#include "linux/spinlock.h"
#include "linux/platform_device.h"
+#include "linux/scatterlist.h"
#include "asm/segment.h"
#include "asm/uaccess.h"
#include "asm/irq.h"
@@ -615,7 +616,7 @@ static int ubd_open_dev(struct ubd *ubd_dev)
blk_queue_max_sectors(ubd_dev->queue, 8 * sizeof(long));
err = -ENOMEM;
- ubd_dev->cow.bitmap = (void *) vmalloc(ubd_dev->cow.bitmap_len);
+ ubd_dev->cow.bitmap = vmalloc(ubd_dev->cow.bitmap_len);
if(ubd_dev->cow.bitmap == NULL){
printk(KERN_ERR "Failed to vmalloc COW bitmap\n");
goto error;
@@ -704,6 +705,7 @@ static int ubd_add(int n, char **error_out)
ubd_dev->size = ROUND_BLOCK(ubd_dev->size);
INIT_LIST_HEAD(&ubd_dev->restart);
+ sg_init_table(ubd_dev->sg, MAX_SG);
err = -ENOMEM;
ubd_dev->queue = blk_init_queue(do_ubd_request, &ubd_dev->lock);
@@ -1115,7 +1117,7 @@ static void do_ubd_request(struct request_queue *q)
}
prepare_request(req, io_req,
(unsigned long long) req->sector << 9,
- sg->offset, sg->length, sg->page);
+ sg->offset, sg->length, sg_page(sg));
last_sectors = sg->length >> 9;
n = os_write_file(thread_fd, &io_req,
diff --git a/arch/um/drivers/vde.h b/arch/um/drivers/vde.h
new file mode 100644
index 000000000000..fc3a05902ba1
--- /dev/null
+++ b/arch/um/drivers/vde.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2007 Luca Bigliardi (shammash@artha.org).
+ * Licensed under the GPL.
+ */
+
+#ifndef __UM_VDE_H__
+#define __UM_VDE_H__
+
+struct vde_data {
+ char *vde_switch;
+ char *descr;
+ void *args;
+ void *conn;
+ void *dev;
+};
+
+struct vde_init {
+ char *vde_switch;
+ char *descr;
+ int port;
+ char *group;
+ int mode;
+};
+
+extern const struct net_user_info vde_user_info;
+
+extern void vde_init_libstuff(struct vde_data *vpri, struct vde_init *init);
+
+extern int vde_user_read(void *conn, void *buf, int len);
+extern int vde_user_write(void *conn, void *buf, int len);
+
+#endif
diff --git a/arch/um/drivers/vde_kern.c b/arch/um/drivers/vde_kern.c
new file mode 100644
index 000000000000..add7e722defb
--- /dev/null
+++ b/arch/um/drivers/vde_kern.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2007 Luca Bigliardi (shammash@artha.org).
+ * Licensed under the GPL.
+ *
+ * Transport usage:
+ * ethN=vde,<vde_switch>,<mac addr>,<port>,<group>,<mode>,<description>
+ *
+ */
+
+#include "linux/init.h"
+#include <linux/netdevice.h>
+#include "net_kern.h"
+#include "net_user.h"
+#include "vde.h"
+
+static void vde_init(struct net_device *dev, void *data)
+{
+ struct vde_init *init = data;
+ struct uml_net_private *pri;
+ struct vde_data *vpri;
+
+ pri = dev->priv;
+ vpri = (struct vde_data *) pri->user;
+
+ vpri->vde_switch = init->vde_switch;
+ vpri->descr = init->descr ? init->descr : "UML vde_transport";
+ vpri->args = NULL;
+ vpri->conn = NULL;
+ vpri->dev = dev;
+
+ printk("vde backend - %s, ", vpri->vde_switch ?
+ vpri->vde_switch : "(default socket)");
+
+ vde_init_libstuff(vpri, init);
+
+ printk("\n");
+}
+
+static int vde_read(int fd, struct sk_buff *skb, struct uml_net_private *lp)
+{
+ struct vde_data *pri = (struct vde_data *) &lp->user;
+
+ if (pri->conn != NULL)
+ return vde_user_read(pri->conn, skb_mac_header(skb),
+ skb->dev->mtu + ETH_HEADER_OTHER);
+
+ printk(KERN_ERR "vde_read - we have no VDECONN to read from");
+ return -EBADF;
+}
+
+static int vde_write(int fd, struct sk_buff *skb, struct uml_net_private *lp)
+{
+ struct vde_data *pri = (struct vde_data *) &lp->user;
+
+ if (pri->conn != NULL)
+ return vde_user_write((void *)pri->conn, skb->data,
+ skb->len);
+
+ printk(KERN_ERR "vde_write - we have no VDECONN to write to");
+ return -EBADF;
+}
+
+static const struct net_kern_info vde_kern_info = {
+ .init = vde_init,
+ .protocol = eth_protocol,
+ .read = vde_read,
+ .write = vde_write,
+};
+
+static int vde_setup(char *str, char **mac_out, void *data)
+{
+ struct vde_init *init = data;
+ char *remain, *port_str = NULL, *mode_str = NULL, *last;
+
+ *init = ((struct vde_init)
+ { .vde_switch = NULL,
+ .descr = NULL,
+ .port = 0,
+ .group = NULL,
+ .mode = 0 });
+
+ remain = split_if_spec(str, &init->vde_switch, mac_out, &port_str,
+ &init->group, &mode_str, &init->descr, NULL);
+
+ if (remain != NULL)
+ printk(KERN_WARNING "vde_setup - Ignoring extra data :"
+ "'%s'\n", remain);
+
+ if (port_str != NULL) {
+ init->port = simple_strtoul(port_str, &last, 10);
+ if ((*last != '\0') || (last == port_str)) {
+ printk(KERN_ERR "vde_setup - Bad port : '%s'\n",
+ port_str);
+ return 0;
+ }
+ }
+
+ if (mode_str != NULL) {
+ init->mode = simple_strtoul(mode_str, &last, 8);
+ if ((*last != '\0') || (last == mode_str)) {
+ printk(KERN_ERR "vde_setup - Bad mode : '%s'\n",
+ mode_str);
+ return 0;
+ }
+ }
+
+ printk(KERN_INFO "Configured vde device: %s\n", init->vde_switch ?
+ init->vde_switch : "(default socket)");
+
+ return 1;
+}
+
+static struct transport vde_transport = {
+ .list = LIST_HEAD_INIT(vde_transport.list),
+ .name = "vde",
+ .setup = vde_setup,
+ .user = &vde_user_info,
+ .kern = &vde_kern_info,
+ .private_size = sizeof(struct vde_data),
+ .setup_size = sizeof(struct vde_init),
+};
+
+static int register_vde(void)
+{
+ register_transport(&vde_transport);
+ return 0;
+}
+
+late_initcall(register_vde);
diff --git a/arch/um/drivers/vde_user.c b/arch/um/drivers/vde_user.c
new file mode 100644
index 000000000000..d9941fe5f931
--- /dev/null
+++ b/arch/um/drivers/vde_user.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2007 Luca Bigliardi (shammash@artha.org).
+ * Licensed under the GPL.
+ */
+
+#include <stddef.h>
+#include <errno.h>
+#include <libvdeplug.h>
+#include "kern_constants.h"
+#include "net_user.h"
+#include "um_malloc.h"
+#include "user.h"
+#include "vde.h"
+
+static int vde_user_init(void *data, void *dev)
+{
+ struct vde_data *pri = data;
+ VDECONN *conn = NULL;
+ int err = -EINVAL;
+
+ pri->dev = dev;
+
+ conn = vde_open(pri->vde_switch, pri->descr, pri->args);
+
+ if (conn == NULL) {
+ err = -errno;
+ printk(UM_KERN_ERR "vde_user_init: vde_open failed, "
+ "errno = %d\n", errno);
+ return err;
+ }
+
+ printk(UM_KERN_INFO "vde backend - connection opened\n");
+
+ pri->conn = conn;
+
+ return 0;
+}
+
+static int vde_user_open(void *data)
+{
+ struct vde_data *pri = data;
+
+ if (pri->conn != NULL)
+ return vde_datafd(pri->conn);
+
+ printk(UM_KERN_WARNING "vde_open - we have no VDECONN to open");
+ return -EINVAL;
+}
+
+static void vde_remove(void *data)
+{
+ struct vde_data *pri = data;
+
+ if (pri->conn != NULL) {
+ printk(UM_KERN_INFO "vde backend - closing connection\n");
+ vde_close(pri->conn);
+ pri->conn = NULL;
+ kfree(pri->args);
+ pri->args = NULL;
+ return;
+ }
+
+ printk(UM_KERN_WARNING "vde_remove - we have no VDECONN to remove");
+}
+
+const struct net_user_info vde_user_info = {
+ .init = vde_user_init,
+ .open = vde_user_open,
+ .close = NULL,
+ .remove = vde_remove,
+ .add_address = NULL,
+ .delete_address = NULL,
+ .mtu = ETH_MAX_PACKET,
+ .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER,
+};
+
+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);
+ if (vpri->args == NULL) {
+ printk(UM_KERN_ERR "vde_init_libstuff - vde_open_args"
+ "allocation failed");
+ return;
+ }
+
+ args = vpri->args;
+
+ args->port = init->port;
+ 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");
+}
+
+int vde_user_read(void *conn, void *buf, int len)
+{
+ VDECONN *vconn = conn;
+ int rv;
+
+ if (vconn == NULL)
+ return 0;
+
+ rv = vde_recv(vconn, buf, len, 0);
+ if (rv < 0) {
+ if (errno == EAGAIN)
+ return 0;
+ return -errno;
+ }
+ else if (rv == 0)
+ return -ENOTCONN;
+
+ return rv;
+}
+
+int vde_user_write(void *conn, void *buf, int len)
+{
+ VDECONN *vconn = conn;
+
+ if (vconn == NULL)
+ return 0;
+
+ return vde_send(vconn, buf, len, 0);
+}
+
diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c
index fd817e541543..8a1c18a9b240 100644
--- a/arch/um/drivers/xterm.c
+++ b/arch/um/drivers/xterm.c
@@ -1,20 +1,21 @@
-/*
+/*
* Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include <stdlib.h>
+#include <stddef.h>
#include <stdio.h>
+#include <stdlib.h>
#include <unistd.h>
-#include <string.h>
#include <errno.h>
+#include <string.h>
#include <termios.h>
#include "chan_user.h"
+#include "kern_constants.h"
#include "os.h"
-#include "init.h"
+#include "um_malloc.h"
#include "user.h"
#include "xterm.h"
-#include "kern_constants.h"
struct xterm_chan {
int pid;
@@ -29,7 +30,7 @@ static void *xterm_init(char *str, int device, const struct chan_opts *opts)
{
struct xterm_chan *data;
- data = malloc(sizeof(*data));
+ data = kmalloc(sizeof(*data), UM_GFP_KERNEL);
if (data == NULL)
return NULL;
*data = ((struct xterm_chan) { .pid = -1,
@@ -95,8 +96,10 @@ static int xterm_open(int input, int output, int primary, void *d,
if (access(argv[4], X_OK) < 0)
argv[4] = "port-helper";
- /* Check that DISPLAY is set, this doesn't guarantee the xterm
- * will work but w/o it we can be pretty sure it won't. */
+ /*
+ * Check that DISPLAY is set, this doesn't guarantee the xterm
+ * will work but w/o it we can be pretty sure it won't.
+ */
if (getenv("DISPLAY") == NULL) {
printk(UM_KERN_ERR "xterm_open: $DISPLAY not set.\n");
return -ENODEV;
@@ -195,7 +198,7 @@ static int xterm_open(int input, int output, int primary, void *d,
static void xterm_close(int fd, void *d)
{
struct xterm_chan *data = d;
-
+
if (data->pid != -1)
os_kill_process(data->pid, 1);
data->pid = -1;
@@ -207,11 +210,6 @@ static void xterm_close(int fd, void *d)
os_close_file(fd);
}
-static void xterm_free(void *d)
-{
- free(d);
-}
-
const struct chan_ops xterm_ops = {
.type = "xterm",
.init = xterm_init,
@@ -221,6 +219,6 @@ const struct chan_ops xterm_ops = {
.write = generic_write,
.console_write = generic_console_write,
.window_size = generic_window_size,
- .free = xterm_free,
+ .free = generic_free,
.winch = 1,
};
diff --git a/arch/um/include/arch.h b/arch/um/include/arch.h
index 10ad52daa8c5..49c601ff2bac 100644
--- a/arch/um/include/arch.h
+++ b/arch/um/include/arch.h
@@ -9,7 +9,7 @@
#include "sysdep/ptrace.h"
extern void arch_check_bugs(void);
-extern int arch_fixup(unsigned long address, union uml_pt_regs *regs);
-extern int arch_handle_signal(int sig, union uml_pt_regs *regs);
+extern int arch_fixup(unsigned long address, struct uml_pt_regs *regs);
+extern int arch_handle_signal(int sig, struct uml_pt_regs *regs);
#endif
diff --git a/arch/um/include/as-layout.h b/arch/um/include/as-layout.h
index fccf187bf4e1..a5cdf953e04a 100644
--- a/arch/um/include/as-layout.h
+++ b/arch/um/include/as-layout.h
@@ -6,6 +6,28 @@
#ifndef __START_H__
#define __START_H__
+#include "uml-config.h"
+#include "kern_constants.h"
+
+/*
+ * Assembly doesn't want any casting, but C does, so define these
+ * without casts here, and define new symbols with casts inside the C
+ * section.
+ */
+#define ASM_STUB_CODE (UML_CONFIG_TOP_ADDR - 2 * UM_KERN_PAGE_SIZE)
+#define ASM_STUB_DATA (UML_CONFIG_TOP_ADDR - UM_KERN_PAGE_SIZE)
+#define ASM_STUB_START ASM_STUB_CODE
+
+/*
+ * This file is included by the assembly stubs, which just want the
+ * definitions above.
+ */
+#ifndef __ASSEMBLY__
+
+#define STUB_CODE ((unsigned long) ASM_STUB_CODE)
+#define STUB_DATA ((unsigned long) ASM_STUB_DATA)
+#define STUB_START ((unsigned long) ASM_STUB_START)
+
#include "sysdep/ptrace.h"
struct cpu_task {
@@ -28,8 +50,9 @@ extern unsigned long _unprotected_end;
extern unsigned long brk_start;
extern int linux_main(int argc, char **argv);
-extern void set_cmdline(char *cmd);
-extern void (*sig_info[])(int, union uml_pt_regs *);
+extern void (*sig_info[])(int, struct uml_pt_regs *);
+
+#endif
#endif
diff --git a/arch/um/include/choose-mode.h b/arch/um/include/choose-mode.h
deleted file mode 100644
index b87b36a87d91..000000000000
--- a/arch/um/include/choose-mode.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __CHOOSE_MODE_H__
-#define __CHOOSE_MODE_H__
-
-#include "uml-config.h"
-
-#if defined(UML_CONFIG_MODE_TT) && defined(UML_CONFIG_MODE_SKAS)
-#define CHOOSE_MODE(tt, skas) (mode_tt ? (tt) : (skas))
-
-extern int mode_tt;
-static inline void *__choose_mode(void *tt, void *skas) {
- return mode_tt ? tt : skas;
-}
-
-#define __CHOOSE_MODE(tt, skas) (*( (typeof(tt) *) __choose_mode(&(tt), &(skas))))
-
-#elif defined(UML_CONFIG_MODE_SKAS)
-#define CHOOSE_MODE(tt, skas) (skas)
-
-#elif defined(UML_CONFIG_MODE_TT)
-#define CHOOSE_MODE(tt, skas) (tt)
-
-#else
-#error CONFIG_MODE_SKAS and CONFIG_MODE_TT are both disabled
-#endif
-
-#define CHOOSE_MODE_PROC(tt, skas, args...) \
- CHOOSE_MODE(tt(args), skas(args))
-
-#ifndef __CHOOSE_MODE
-#define __CHOOSE_MODE(tt, skas) CHOOSE_MODE(tt, skas)
-#endif
-
-#endif
diff --git a/arch/um/include/common-offsets.h b/arch/um/include/common-offsets.h
index 6eee343e53eb..0edab695ed4e 100644
--- a/arch/um/include/common-offsets.h
+++ b/arch/um/include/common-offsets.h
@@ -1,15 +1,13 @@
/* for use by sys-$SUBARCH/kernel-offsets.c */
DEFINE(KERNEL_MADV_REMOVE, MADV_REMOVE);
-#ifdef CONFIG_MODE_TT
-OFFSET(HOST_TASK_EXTERN_PID, task_struct, thread.mode.tt.extern_pid);
-#endif
OFFSET(HOST_TASK_REGS, task_struct, thread.regs);
OFFSET(HOST_TASK_PID, task_struct, pid);
DEFINE(UM_KERN_PAGE_SIZE, PAGE_SIZE);
DEFINE(UM_KERN_PAGE_MASK, PAGE_MASK);
+DEFINE(UM_KERN_PAGE_SHIFT, PAGE_SHIFT);
DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC);
DEFINE_STR(UM_KERN_EMERG, KERN_EMERG);
@@ -34,3 +32,9 @@ DEFINE(UM_GFP_ATOMIC, GFP_ATOMIC);
DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx));
DEFINE(UM_THREAD_SIZE, THREAD_SIZE);
+
+DEFINE(UM_HZ, HZ);
+
+DEFINE(UM_USEC_PER_SEC, USEC_PER_SEC);
+DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC);
+DEFINE(UM_NSEC_PER_USEC, NSEC_PER_USEC);
diff --git a/arch/um/include/irq_user.h b/arch/um/include/irq_user.h
index 15d311b9be9e..884a9c17eea0 100644
--- a/arch/um/include/irq_user.h
+++ b/arch/um/include/irq_user.h
@@ -1,12 +1,12 @@
/*
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
#ifndef __IRQ_USER_H__
#define __IRQ_USER_H__
-#include "uml-config.h"
+#include "sysdep/ptrace.h"
struct irq_fd {
struct irq_fd *next;
@@ -21,7 +21,7 @@ struct irq_fd {
enum { IRQ_READ, IRQ_WRITE };
-extern void sigio_handler(int sig, union uml_pt_regs *regs);
+extern void sigio_handler(int sig, struct uml_pt_regs *regs);
extern int activate_fd(int irq, int fd, int type, void *dev_id);
extern void free_irq_by_irq_and_dev(unsigned int irq, void *dev_id);
extern void free_irq_by_fd(int fd);
@@ -30,8 +30,4 @@ extern void deactivate_fd(int fd, int irqnum);
extern int deactivate_all_fds(void);
extern int activate_ipi(int fd, int pid);
-#ifdef CONFIG_MODE_TT
-extern void forward_interrupts(int pid);
-#endif
-
#endif
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
index 6c2be26f1d7d..74ce8e5370a6 100644
--- a/arch/um/include/kern_util.h
+++ b/arch/um/include/kern_util.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -8,9 +8,8 @@
#include "sysdep/ptrace.h"
#include "sysdep/faultinfo.h"
-#include "uml-config.h"
-typedef void (*kern_hndl)(int, union uml_pt_regs *);
+typedef void (*kern_hndl)(int, struct uml_pt_regs *);
struct kern_handlers {
kern_hndl relay_signal;
@@ -34,9 +33,6 @@ extern int nsyscalls;
UML_ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1)
extern int kernel_fork(unsigned long flags, int (*fn)(void *), void * arg);
-#ifdef UML_CONFIG_MODE_TT
-extern unsigned long stack_sp(unsigned long page);
-#endif
extern int kernel_thread_proc(void *data);
extern void syscall_segv(int sig);
extern int current_pid(void);
@@ -44,7 +40,7 @@ extern unsigned long alloc_stack(int order, int atomic);
extern int do_signal(void);
extern int is_stack_fault(unsigned long sp);
extern unsigned long segv(struct faultinfo fi, unsigned long ip,
- int is_user, union uml_pt_regs *regs);
+ int is_user, struct uml_pt_regs *regs);
extern int handle_page_fault(unsigned long address, unsigned long ip,
int is_write, int is_user, int *code_out);
extern void syscall_ready(void);
@@ -57,7 +53,7 @@ extern int need_finish_fork(void);
extern void free_stack(unsigned long stack, int order);
extern void add_input_request(int op, void (*proc)(int), void *arg);
extern char *current_cmd(void);
-extern void timer_handler(int sig, union uml_pt_regs *regs);
+extern void timer_handler(int sig, struct uml_pt_regs *regs);
extern int set_signals(int enable);
extern int pid_to_processor_id(int pid);
extern void deliver_signals(void *t);
@@ -67,9 +63,8 @@ extern void finish_fork(void);
extern void paging_init(void);
extern void init_flush_vm(void);
extern void *syscall_sp(void *t);
-extern void syscall_trace(union uml_pt_regs *regs, int entryexit);
-extern int hz(void);
-extern unsigned int do_IRQ(int irq, union uml_pt_regs *regs);
+extern void syscall_trace(struct uml_pt_regs *regs, int entryexit);
+extern unsigned int do_IRQ(int irq, struct uml_pt_regs *regs);
extern void interrupt_end(void);
extern void initial_thread_cb(void (*proc)(void *), void *arg);
extern int debugger_signal(int status, int pid);
@@ -79,10 +74,9 @@ extern int init_ptrace_proxy(int idle_pid, int startup, int stop);
extern int init_parent_proxy(int pid);
extern int singlestepping(void *t);
extern void check_stack_overflow(void *ptr);
-extern void relay_signal(int sig, union uml_pt_regs *regs);
+extern void relay_signal(int sig, struct uml_pt_regs *regs);
extern int user_context(unsigned long sp);
-extern void timer_irq(union uml_pt_regs *regs);
-extern void unprotect_stack(unsigned long stack);
+extern void timer_irq(struct uml_pt_regs *regs);
extern void do_uml_exitcalls(void);
extern int attach_debugger(int idle_pid, int pid, int stop);
extern int config_gdb(char *str);
@@ -113,11 +107,9 @@ extern void time_init_kern(void);
/* Are we disallowed to sleep? Used to choose between GFP_KERNEL and GFP_ATOMIC. */
extern int __cant_sleep(void);
-extern void sigio_handler(int sig, union uml_pt_regs *regs);
-
-extern void copy_sc(union uml_pt_regs *regs, void *from);
-
+extern void sigio_handler(int sig, struct uml_pt_regs *regs);
+extern void copy_sc(struct uml_pt_regs *regs, void *from);
extern unsigned long to_irq_stack(unsigned long *mask_out);
unsigned long from_irq_stack(int nested);
-
+extern int start_uml(void);
#endif
diff --git a/arch/um/include/mconsole.h b/arch/um/include/mconsole.h
index b282839c1625..c139ae1d6826 100644
--- a/arch/um/include/mconsole.h
+++ b/arch/um/include/mconsole.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org)
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -63,7 +63,7 @@ struct mc_request
struct mconsole_request request;
struct mconsole_command *cmd;
- union uml_pt_regs regs;
+ struct uml_pt_regs regs;
};
extern char mconsole_socket_name[];
@@ -96,14 +96,3 @@ extern void lock_notify(void);
extern void unlock_notify(void);
#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/mem.h b/arch/um/include/mem.h
index e8ff0d8fa610..5cd40e99e8d5 100644
--- a/arch/um/include/mem.h
+++ b/arch/um/include/mem.h
@@ -1,18 +1,12 @@
/*
- * Copyright (C) 2002, 2003 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
#ifndef __MEM_H__
#define __MEM_H__
-#include "linux/types.h"
-
-extern int phys_mapping(unsigned long phys, __u64 *offset_out);
-extern int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w);
-extern int is_remapped(void *virt);
-extern int physmem_remove_mapping(void *virt);
-extern void physmem_forget_descriptor(int fd);
+extern int phys_mapping(unsigned long phys, unsigned long long *offset_out);
extern unsigned long uml_physmem;
static inline unsigned long to_phys(void *virt)
@@ -26,14 +20,3 @@ static inline void *to_virt(unsigned long phys)
}
#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/mode.h b/arch/um/include/mode.h
deleted file mode 100644
index 786cf563eb05..000000000000
--- a/arch/um/include/mode.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __MODE_H__
-#define __MODE_H__
-
-#include "uml-config.h"
-
-#ifdef UML_CONFIG_MODE_TT
-#include "mode-tt.h"
-#endif
-
-#ifdef UML_CONFIG_MODE_SKAS
-#include "mode-skas.h"
-#endif
-
-#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/mode_kern.h b/arch/um/include/mode_kern.h
deleted file mode 100644
index 88e5e77bf517..000000000000
--- a/arch/um/include/mode_kern.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __MODE_KERN_H__
-#define __MODE_KERN_H__
-
-#ifdef CONFIG_MODE_TT
-#include "mode_kern_tt.h"
-#endif
-
-#ifdef CONFIG_MODE_SKAS
-#include "mode_kern_skas.h"
-#endif
-
-#endif
diff --git a/arch/um/include/net_kern.h b/arch/um/include/net_kern.h
index 9237056b9103..d843c7924a7c 100644
--- a/arch/um/include/net_kern.h
+++ b/arch/um/include/net_kern.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -30,24 +30,24 @@ struct uml_net_private {
struct work_struct work;
int fd;
unsigned char mac[ETH_ALEN];
+ int max_packet;
unsigned short (*protocol)(struct sk_buff *);
int (*open)(void *);
void (*close)(int, void *);
void (*remove)(void *);
- int (*read)(int, struct sk_buff **skb, struct uml_net_private *);
- int (*write)(int, struct sk_buff **skb, struct uml_net_private *);
+ int (*read)(int, struct sk_buff *skb, struct uml_net_private *);
+ int (*write)(int, struct sk_buff *skb, struct uml_net_private *);
void (*add_address)(unsigned char *, unsigned char *, void *);
void (*delete_address)(unsigned char *, unsigned char *, void *);
- int (*set_mtu)(int mtu, void *);
char user[0];
};
struct net_kern_info {
void (*init)(struct net_device *, void *);
unsigned short (*protocol)(struct sk_buff *);
- int (*read)(int, struct sk_buff **skb, struct uml_net_private *);
- int (*write)(int, struct sk_buff **skb, struct uml_net_private *);
+ int (*read)(int, struct sk_buff *skb, struct uml_net_private *);
+ int (*write)(int, struct sk_buff *skb, struct uml_net_private *);
};
struct transport {
@@ -62,7 +62,6 @@ struct transport {
extern struct net_device *ether_init(int);
extern unsigned short ether_protocol(struct sk_buff *);
-extern struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra);
extern int tap_setup_common(char *str, char *type, char **dev_name,
char **mac_out, char **gate_addr);
extern void register_transport(struct transport *new);
diff --git a/arch/um/include/net_user.h b/arch/um/include/net_user.h
index cfe7c50634b9..63bee158cd8e 100644
--- a/arch/um/include/net_user.h
+++ b/arch/um/include/net_user.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -18,10 +18,10 @@ struct net_user_info {
int (*open)(void *);
void (*close)(int, void *);
void (*remove)(void *);
- int (*set_mtu)(int mtu, void *);
void (*add_address)(unsigned char *, unsigned char *, void *);
void (*delete_address)(unsigned char *, unsigned char *, void *);
int max_packet;
+ int mtu;
};
extern void ether_user_init(void *data, void *dev);
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 930b261ea483..fbf0a87c6eaa 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -1,20 +1,18 @@
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
#ifndef __OS_H__
#define __OS_H__
-#include "uml-config.h"
-#include "asm/types.h"
-#include "../os/include/file.h"
-#include "sysdep/ptrace.h"
-#include "kern_util.h"
-#include "skas/mm_id.h"
+#include <stdarg.h>
#include "irq_user.h"
+#include "kern_util.h"
+#include "longjmp.h"
+#include "mm_id.h"
#include "sysdep/tls.h"
-#include "sysdep/archsetjmp.h"
+#include "../os/include/file.h"
#define CATCH_EINTR(expr) while ((errno = 0, ((expr) < 0)) && (errno == EINTR))
@@ -130,18 +128,15 @@ static inline struct openflags of_cloexec(struct openflags flags)
extern int os_stat_file(const char *file_name, struct uml_stat *buf);
extern int os_stat_fd(const int fd, struct uml_stat *buf);
extern int os_access(const char *file, int mode);
-extern void os_print_error(int error, const char* str);
extern int os_get_exec_close(int fd, int *close_on_exec);
-extern int os_set_exec_close(int fd, int close_on_exec);
+extern int os_set_exec_close(int fd);
extern int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg);
-extern int os_window_size(int fd, int *rows, int *cols);
-extern int os_new_tty_pgrp(int fd, int pid);
extern int os_get_ifname(int fd, char *namebuf);
extern int os_set_slip(int fd);
extern int os_set_owner(int fd, int pid);
extern int os_mode_fd(int fd, int mode);
-extern int os_seek_file(int fd, __u64 offset);
+extern int os_seek_file(int fd, unsigned long long offset);
extern int os_open_file(char *file, struct openflags flags, int mode);
extern int os_read_file(int fd, void *buf, int len);
extern int os_write_file(int fd, const void *buf, int count);
@@ -179,11 +174,7 @@ extern void check_host_supports_tls(int *supports_tls, int *tls_min);
/* Make sure they are clear when running in TT mode. Required by
* SEGV_MAYBE_FIXABLE */
-#ifdef UML_CONFIG_MODE_SKAS
#define clear_can_do_skas() do { ptrace_faultinfo = proc_mm = 0; } while (0)
-#else
-#define clear_can_do_skas() do {} while (0)
-#endif
/* mem.c */
extern int create_mem_file(unsigned long long len);
@@ -194,20 +185,13 @@ extern int os_process_parent(int pid);
extern void os_stop_process(int pid);
extern void os_kill_process(int pid, int reap_child);
extern void os_kill_ptraced_process(int pid, int reap_child);
-#ifdef UML_CONFIG_MODE_TT
-extern void os_usr1_process(int pid);
-#endif
extern long os_ptrace_ldt(long pid, long addr, long data);
extern int os_getpid(void);
extern int os_getpgrp(void);
-#ifdef UML_CONFIG_MODE_TT
-extern void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int));
-extern void stop(void);
-#endif
extern void init_new_thread_signals(void);
-extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr);
+extern int run_kernel_thread(int (*fn)(void *), void *arg, jmp_buf **jmp_ptr);
extern int os_map_memory(void *virt, int fd, unsigned long long off,
unsigned long len, int r, int w, int x);
@@ -218,21 +202,9 @@ extern int os_drop_memory(void *addr, int length);
extern int can_drop_memory(void);
extern void os_flush_stdout(void);
-/* tt.c
- * for tt mode only (will be deleted in future...)
- */
-extern void forward_ipi(int fd, int pid);
-extern void kill_child_dead(int pid);
-extern int wait_for_stop(int pid, int sig, int cont_type, void *relay);
-extern int protect_memory(unsigned long addr, unsigned long len,
- int r, int w, int x, int must_succeed);
-extern void forward_pending_sigio(int target);
-extern int start_fork_tramp(void *arg, unsigned long temp_stack,
- int clone_flags, int (*tramp)(void *));
-
/* uaccess.c */
extern unsigned long __do_user_copy(void *to, const void *from, int n,
- void **fault_addr, void **fault_catcher,
+ void **fault_addr, jmp_buf **fault_catcher,
void (*op)(void *to, const void *from,
int n), int *faulted_out);
@@ -255,6 +227,7 @@ extern int set_umid(char *name);
extern char *get_umid(void);
/* signal.c */
+extern void timer_init(void);
extern void set_sigstack(void *sig_stack, int size);
extern void remove_sigstack(void);
extern void set_handler(int sig, void (*handler)(int), int flags, ...);
@@ -266,7 +239,6 @@ extern int set_signals(int enable);
/* trap.c */
extern void os_fill_handlinfo(struct kern_handlers h);
-extern void do_longjmp(void *p, int val);
/* util.c */
extern void stack_protections(unsigned long address);
@@ -277,17 +249,12 @@ extern int setjmp_wrapper(void (*proc)(void *, void *), ...);
extern void os_dump_core(void);
/* time.c */
-#define BILLION (1000 * 1000 * 1000)
-
-extern void switch_timers(int to_real);
-extern void idle_sleep(int secs);
-extern int set_interval(int is_virtual);
-#ifdef CONFIG_MODE_TT
-extern void enable_timer(void);
-#endif
-extern void disable_timer(void);
+extern void idle_sleep(unsigned long long nsecs);
+extern int set_interval(void);
+extern int timer_one_shot(int ticks);
+extern long long disable_timer(void);
extern void uml_idle_timer(void);
-extern unsigned long long os_nsecs(void);
+extern long long os_nsecs(void);
/* skas/mem.c */
extern long run_syscall_stub(struct mm_id * mm_idp,
@@ -308,7 +275,9 @@ extern int protect(struct mm_id * mm_idp, unsigned long addr,
extern int is_skas_winch(int pid, int fd, void *data);
extern int start_userspace(unsigned long stub_stack);
extern int copy_context_skas0(unsigned long stack, int pid);
-extern void userspace(union uml_pt_regs *regs);
+extern void save_registers(int pid, struct uml_pt_regs *regs);
+extern void restore_registers(int pid, struct uml_pt_regs *regs);
+extern void userspace(struct uml_pt_regs *regs);
extern void map_stub_pages(int fd, unsigned long code,
unsigned long data, unsigned long stack);
extern void new_thread(void *stack, jmp_buf *buf, void (*handler)(void));
diff --git a/arch/um/include/registers.h b/arch/um/include/registers.h
index f845b3629a6d..0e27406a43a4 100644
--- a/arch/um/include/registers.h
+++ b/arch/um/include/registers.h
@@ -9,13 +9,15 @@
#include "sysdep/ptrace.h"
#include "sysdep/archsetjmp.h"
-extern void init_thread_registers(union uml_pt_regs *to);
+extern void init_thread_registers(struct uml_pt_regs *to);
extern int save_fp_registers(int pid, unsigned long *fp_regs);
extern int restore_fp_registers(int pid, unsigned long *fp_regs);
-extern void save_registers(int pid, union uml_pt_regs *regs);
-extern void restore_registers(int pid, union uml_pt_regs *regs);
+extern int save_fpx_registers(int pid, unsigned long *fp_regs);
+extern int restore_fpx_registers(int pid, unsigned long *fp_regs);
+extern void save_registers(int pid, struct uml_pt_regs *regs);
+extern void restore_registers(int pid, struct uml_pt_regs *regs);
extern void init_registers(int pid);
-extern void get_safe_registers(unsigned long * regs, unsigned long * fp_regs);
+extern void get_safe_registers(unsigned long *regs);
extern unsigned long get_thread_reg(int reg, jmp_buf *buf);
#endif
diff --git a/arch/um/include/skas/mmu-skas.h b/arch/um/include/skas/mmu-skas.h
deleted file mode 100644
index b26986c0c3d2..000000000000
--- a/arch/um/include/skas/mmu-skas.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __SKAS_MMU_H
-#define __SKAS_MMU_H
-
-#include "mm_id.h"
-#include "asm/ldt.h"
-
-struct mmu_context_skas {
- struct mm_id id;
- unsigned long last_page_table;
-#ifdef CONFIG_3_LEVEL_PGTABLES
- unsigned long last_pmd;
-#endif
- uml_ldt_t ldt;
-};
-
-extern void switch_mm_skas(struct mm_id * mm_idp);
-
-#endif
diff --git a/arch/um/include/skas/mode-skas.h b/arch/um/include/skas/mode-skas.h
index 8bc6916bbbb1..e065feb000df 100644
--- a/arch/um/include/skas/mode-skas.h
+++ b/arch/um/include/skas/mode-skas.h
@@ -1,18 +1,11 @@
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
* Licensed under the GPL
*/
#ifndef __MODE_SKAS_H__
#define __MODE_SKAS_H__
-#include <sysdep/ptrace.h>
-
-extern unsigned long exec_regs[];
-extern unsigned long exec_fp_regs[];
-extern unsigned long exec_fpx_regs[];
-extern int have_fpx_regs;
-
extern void kill_off_processes_skas(void);
#endif
diff --git a/arch/um/include/skas/mode_kern_skas.h b/arch/um/include/skas/mode_kern_skas.h
deleted file mode 100644
index 8ee6285dfacc..000000000000
--- a/arch/um/include/skas/mode_kern_skas.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __SKAS_MODE_KERN_H__
-#define __SKAS_MODE_KERN_H__
-
-#include "linux/sched.h"
-#include "asm/page.h"
-#include "asm/ptrace.h"
-
-extern void flush_thread_skas(void);
-extern void switch_to_skas(void *prev, void *next);
-extern void start_thread_skas(struct pt_regs *regs, unsigned long eip,
- unsigned long esp);
-extern int copy_thread_skas(int nr, unsigned long clone_flags,
- unsigned long sp, unsigned long stack_top,
- struct task_struct *p, struct pt_regs *regs);
-extern void release_thread_skas(struct task_struct *task);
-extern void init_idle_skas(void);
-extern void flush_tlb_kernel_range_skas(unsigned long start,
- unsigned long end);
-extern void flush_tlb_kernel_vm_skas(void);
-extern void __flush_tlb_one_skas(unsigned long addr);
-extern void flush_tlb_range_skas(struct vm_area_struct *vma,
- unsigned long start, unsigned long end);
-extern void flush_tlb_mm_skas(struct mm_struct *mm);
-extern void force_flush_all_skas(void);
-extern long execute_syscall_skas(void *r);
-extern void before_mem_skas(unsigned long unused);
-extern unsigned long set_task_sizes_skas(unsigned long *task_size_out);
-extern int start_uml_skas(void);
-extern int external_pid_skas(struct task_struct *task);
-extern int thread_pid_skas(struct task_struct *task);
-extern void flush_tlb_page_skas(struct vm_area_struct *vma,
- unsigned long address);
-
-#define kmem_end_skas (host_task_size - 1024 * 1024)
-
-#endif
diff --git a/arch/um/include/skas/skas.h b/arch/um/include/skas/skas.h
index e88926b16072..b073f8a86bd3 100644
--- a/arch/um/include/skas/skas.h
+++ b/arch/um/include/skas/skas.h
@@ -1,12 +1,11 @@
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
#ifndef __SKAS_H
#define __SKAS_H
-#include "mm_id.h"
#include "sysdep/ptrace.h"
extern int userspace_pid[];
@@ -15,7 +14,7 @@ extern int skas_needs_stub;
extern int user_thread(unsigned long stack, int flags);
extern void new_thread_handler(void);
-extern void handle_syscall(union uml_pt_regs *regs);
+extern void handle_syscall(struct uml_pt_regs *regs);
extern int new_mm(unsigned long stack);
extern void get_skas_faultinfo(int pid, struct faultinfo * fi);
extern long execute_syscall_skas(void *r);
diff --git a/arch/um/include/skas/uaccess-skas.h b/arch/um/include/skas/uaccess-skas.h
deleted file mode 100644
index 224a75f4c025..000000000000
--- a/arch/um/include/skas/uaccess-skas.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __SKAS_UACCESS_H
-#define __SKAS_UACCESS_H
-
-#include "asm/errno.h"
-
-/* No SKAS-specific checking. */
-#define access_ok_skas(type, addr, size) 0
-
-extern int copy_from_user_skas(void *to, const void __user *from, int n);
-extern int copy_to_user_skas(void __user *to, const void *from, int n);
-extern int strncpy_from_user_skas(char *dst, const char __user *src, int count);
-extern int __clear_user_skas(void __user *mem, int len);
-extern int clear_user_skas(void __user *mem, int len);
-extern int strnlen_user_skas(const void __user *str, int len);
-
-#endif
diff --git a/arch/um/include/sysdep-i386/kernel-offsets.h b/arch/um/include/sysdep-i386/kernel-offsets.h
index 97ec9d894d75..5868526b5eef 100644
--- a/arch/um/include/sysdep-i386/kernel-offsets.h
+++ b/arch/um/include/sysdep-i386/kernel-offsets.h
@@ -17,6 +17,5 @@
void foo(void)
{
- OFFSET(HOST_TASK_DEBUGREGS, task_struct, thread.arch.debugregs);
#include <common-offsets.h>
}
diff --git a/arch/um/include/sysdep-i386/ptrace.h b/arch/um/include/sysdep-i386/ptrace.h
index 52b398bcafcf..11c08969d134 100644
--- a/arch/um/include/sysdep-i386/ptrace.h
+++ b/arch/um/include/sysdep-i386/ptrace.h
@@ -1,5 +1,5 @@
-/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+/*
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -9,17 +9,11 @@
#include "uml-config.h"
#include "user_constants.h"
#include "sysdep/faultinfo.h"
-#include "choose-mode.h"
#define MAX_REG_NR (UM_FRAME_SIZE / sizeof(unsigned long))
#define MAX_REG_OFFSET (UM_FRAME_SIZE)
-#ifdef UML_CONFIG_PT_PROXY
-extern void update_debugregs(int seq);
-#else
static inline void update_debugregs(int seq) {}
-#endif
-
/* syscall emulation path in ptrace */
@@ -31,12 +25,6 @@ void set_using_sysemu(int value);
int get_using_sysemu(void);
extern int sysemu_supported;
-#ifdef UML_CONFIG_MODE_TT
-#include "sysdep/sc.h"
-#endif
-
-#ifdef UML_CONFIG_MODE_SKAS
-
#include "skas_ptregs.h"
#define REGS_IP(r) ((r)[HOST_IP])
@@ -60,70 +48,36 @@ extern int sysemu_supported;
#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r))
-#endif
#ifndef PTRACE_SYSEMU_SINGLESTEP
#define PTRACE_SYSEMU_SINGLESTEP 32
#endif
-union uml_pt_regs {
-#ifdef UML_CONFIG_MODE_TT
- struct tt_regs {
- long syscall;
- void *sc;
- struct faultinfo faultinfo;
- } tt;
-#endif
-#ifdef UML_CONFIG_MODE_SKAS
- struct skas_regs {
- unsigned long regs[MAX_REG_NR];
- unsigned long fp[HOST_FP_SIZE];
- unsigned long xfp[HOST_XFP_SIZE];
- struct faultinfo faultinfo;
- long syscall;
- int is_user;
- } skas;
-#endif
+struct uml_pt_regs {
+ unsigned long gp[MAX_REG_NR];
+ struct faultinfo faultinfo;
+ long syscall;
+ int is_user;
};
#define EMPTY_UML_PT_REGS { }
-extern int mode_tt;
-
-#define UPT_SC(r) ((r)->tt.sc)
-#define UPT_IP(r) \
- __CHOOSE_MODE(SC_IP(UPT_SC(r)), REGS_IP((r)->skas.regs))
-#define UPT_SP(r) \
- __CHOOSE_MODE(SC_SP(UPT_SC(r)), REGS_SP((r)->skas.regs))
-#define UPT_EFLAGS(r) \
- __CHOOSE_MODE(SC_EFLAGS(UPT_SC(r)), REGS_EFLAGS((r)->skas.regs))
-#define UPT_EAX(r) \
- __CHOOSE_MODE(SC_EAX(UPT_SC(r)), REGS_EAX((r)->skas.regs))
-#define UPT_EBX(r) \
- __CHOOSE_MODE(SC_EBX(UPT_SC(r)), REGS_EBX((r)->skas.regs))
-#define UPT_ECX(r) \
- __CHOOSE_MODE(SC_ECX(UPT_SC(r)), REGS_ECX((r)->skas.regs))
-#define UPT_EDX(r) \
- __CHOOSE_MODE(SC_EDX(UPT_SC(r)), REGS_EDX((r)->skas.regs))
-#define UPT_ESI(r) \
- __CHOOSE_MODE(SC_ESI(UPT_SC(r)), REGS_ESI((r)->skas.regs))
-#define UPT_EDI(r) \
- __CHOOSE_MODE(SC_EDI(UPT_SC(r)), REGS_EDI((r)->skas.regs))
-#define UPT_EBP(r) \
- __CHOOSE_MODE(SC_EBP(UPT_SC(r)), REGS_EBP((r)->skas.regs))
-#define UPT_ORIG_EAX(r) \
- __CHOOSE_MODE((r)->tt.syscall, (r)->skas.syscall)
-#define UPT_CS(r) \
- __CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs))
-#define UPT_SS(r) \
- __CHOOSE_MODE(SC_SS(UPT_SC(r)), REGS_SS((r)->skas.regs))
-#define UPT_DS(r) \
- __CHOOSE_MODE(SC_DS(UPT_SC(r)), REGS_DS((r)->skas.regs))
-#define UPT_ES(r) \
- __CHOOSE_MODE(SC_ES(UPT_SC(r)), REGS_ES((r)->skas.regs))
-#define UPT_FS(r) \
- __CHOOSE_MODE(SC_FS(UPT_SC(r)), REGS_FS((r)->skas.regs))
-#define UPT_GS(r) \
- __CHOOSE_MODE(SC_GS(UPT_SC(r)), REGS_GS((r)->skas.regs))
+#define UPT_IP(r) REGS_IP((r)->gp)
+#define UPT_SP(r) REGS_SP((r)->gp)
+#define UPT_EFLAGS(r) REGS_EFLAGS((r)->gp)
+#define UPT_EAX(r) REGS_EAX((r)->gp)
+#define UPT_EBX(r) REGS_EBX((r)->gp)
+#define UPT_ECX(r) REGS_ECX((r)->gp)
+#define UPT_EDX(r) REGS_EDX((r)->gp)
+#define UPT_ESI(r) REGS_ESI((r)->gp)
+#define UPT_EDI(r) REGS_EDI((r)->gp)
+#define UPT_EBP(r) REGS_EBP((r)->gp)
+#define UPT_ORIG_EAX(r) ((r)->syscall)
+#define UPT_CS(r) REGS_CS((r)->gp)
+#define UPT_SS(r) REGS_SS((r)->gp)
+#define UPT_DS(r) REGS_DS((r)->gp)
+#define UPT_ES(r) REGS_ES((r)->gp)
+#define UPT_FS(r) REGS_FS((r)->gp)
+#define UPT_GS(r) REGS_GS((r)->gp)
#define UPT_SYSCALL_ARG1(r) UPT_EBX(r)
#define UPT_SYSCALL_ARG2(r) UPT_ECX(r)
@@ -134,20 +88,19 @@ extern int mode_tt;
extern int user_context(unsigned long sp);
-#define UPT_IS_USER(r) \
- CHOOSE_MODE(user_context(UPT_SP(r)), (r)->skas.is_user)
+#define UPT_IS_USER(r) ((r)->is_user)
struct syscall_args {
unsigned long args[6];
};
#define SYSCALL_ARGS(r) ((struct syscall_args) \
- { .args = { UPT_SYSCALL_ARG1(r), \
- UPT_SYSCALL_ARG2(r), \
- UPT_SYSCALL_ARG3(r), \
- UPT_SYSCALL_ARG4(r), \
- UPT_SYSCALL_ARG5(r), \
- UPT_SYSCALL_ARG6(r) } } )
+ { .args = { UPT_SYSCALL_ARG1(r), \
+ UPT_SYSCALL_ARG2(r), \
+ UPT_SYSCALL_ARG3(r), \
+ UPT_SYSCALL_ARG4(r), \
+ UPT_SYSCALL_ARG5(r), \
+ UPT_SYSCALL_ARG6(r) } } )
#define UPT_REG(regs, reg) \
({ unsigned long val; \
@@ -175,7 +128,6 @@ struct syscall_args {
} \
val; \
})
-
#define UPT_SET(regs, reg, val) \
do { \
@@ -204,29 +156,16 @@ struct syscall_args {
} while (0)
#define UPT_SET_SYSCALL_RETURN(r, res) \
- CHOOSE_MODE(SC_SET_SYSCALL_RETURN(UPT_SC(r), (res)), \
- REGS_SET_SYSCALL_RETURN((r)->skas.regs, (res)))
+ REGS_SET_SYSCALL_RETURN((r)->regs, (res))
-#define UPT_RESTART_SYSCALL(r) \
- CHOOSE_MODE(SC_RESTART_SYSCALL(UPT_SC(r)), \
- REGS_RESTART_SYSCALL((r)->skas.regs))
+#define UPT_RESTART_SYSCALL(r) REGS_RESTART_SYSCALL((r)->gp)
#define UPT_ORIG_SYSCALL(r) UPT_EAX(r)
#define UPT_SYSCALL_NR(r) UPT_ORIG_EAX(r)
#define UPT_SYSCALL_RET(r) UPT_EAX(r)
-#define UPT_FAULTINFO(r) \
- CHOOSE_MODE((&(r)->tt.faultinfo), (&(r)->skas.faultinfo))
+#define UPT_FAULTINFO(r) (&(r)->faultinfo)
-#endif
+extern void arch_init_registers(int pid);
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
+#endif
diff --git a/arch/um/include/sysdep-i386/sigcontext.h b/arch/um/include/sysdep-i386/sigcontext.h
index 23fd2644d7ed..67e77122aa45 100644
--- a/arch/um/include/sysdep-i386/sigcontext.h
+++ b/arch/um/include/sysdep-i386/sigcontext.h
@@ -1,19 +1,15 @@
/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
#ifndef __SYS_SIGCONTEXT_I386_H
#define __SYS_SIGCONTEXT_I386_H
-#include "uml-config.h"
-#include <sysdep/sc.h>
+#include "sysdep/sc.h"
#define IP_RESTART_SYSCALL(ip) ((ip) -= 2)
-#define SC_RESTART_SYSCALL(sc) IP_RESTART_SYSCALL(SC_IP(sc))
-#define SC_SET_SYSCALL_RETURN(sc, result) SC_EAX(sc) = (result)
-
#define GET_FAULTINFO_FROM_SC(fi,sc) \
{ \
(fi).cr2 = SC_CR2(sc); \
@@ -21,32 +17,10 @@
(fi).trap_no = SC_TRAPNO(sc); \
}
-/* ptrace expects that, at the start of a system call, %eax contains
- * -ENOSYS, so this makes it so.
- */
-#define SC_START_SYSCALL(sc) do SC_EAX(sc) = -ENOSYS; while(0)
-
/* This is Page Fault */
#define SEGV_IS_FIXABLE(fi) ((fi)->trap_no == 14)
/* SKAS3 has no trap_no on i386, but get_skas_faultinfo() sets it to 0. */
-#ifdef UML_CONFIG_MODE_SKAS
#define SEGV_MAYBE_FIXABLE(fi) ((fi)->trap_no == 0 && ptrace_faultinfo)
-#else
-#define SEGV_MAYBE_FIXABLE(fi) 0
-#endif
-
-extern unsigned long *sc_sigmask(void *sc_ptr);
-extern int sc_get_fpregs(unsigned long buf, void *sc_ptr);
#endif
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/sysdep-i386/stub.h b/arch/um/include/sysdep-i386/stub.h
index 4fffae75ba53..8c097b87fca7 100644
--- a/arch/um/include/sysdep-i386/stub.h
+++ b/arch/um/include/sysdep-i386/stub.h
@@ -9,7 +9,7 @@
#include <sys/mman.h>
#include <asm/ptrace.h>
#include <asm/unistd.h>
-#include <asm/page.h>
+#include "as-layout.h"
#include "stub-data.h"
#include "kern_constants.h"
#include "uml-config.h"
@@ -19,7 +19,7 @@ extern void stub_clone_handler(void);
#define STUB_SYSCALL_RET EAX
#define STUB_MMAP_NR __NR_mmap2
-#define MMAP_OFFSET(o) ((o) >> PAGE_SHIFT)
+#define MMAP_OFFSET(o) ((o) >> UM_KERN_PAGE_SHIFT)
static inline long stub_syscall0(long syscall)
{
@@ -90,12 +90,12 @@ static inline void remap_stack(int fd, unsigned long offset)
{
__asm__ volatile ("movl %%eax,%%ebp ; movl %0,%%eax ; int $0x80 ;"
"movl %7, %%ebx ; movl %%eax, (%%ebx)"
- : : "g" (STUB_MMAP_NR), "b" (UML_CONFIG_STUB_DATA),
- "c" (UM_KERN_PAGE_SIZE),
+ : : "g" (STUB_MMAP_NR), "b" (STUB_DATA),
+ "c" (UM_KERN_PAGE_SIZE),
"d" (PROT_READ | PROT_WRITE),
- "S" (MAP_FIXED | MAP_SHARED), "D" (fd),
- "a" (offset),
- "i" (&((struct stub_data *) UML_CONFIG_STUB_DATA)->err)
+ "S" (MAP_FIXED | MAP_SHARED), "D" (fd),
+ "a" (offset),
+ "i" (&((struct stub_data *) STUB_DATA)->err)
: "memory");
}
diff --git a/arch/um/include/sysdep-i386/thread.h b/arch/um/include/sysdep-i386/thread.h
deleted file mode 100644
index 243fed44d780..000000000000
--- a/arch/um/include/sysdep-i386/thread.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef __UM_THREAD_H
-#define __UM_THREAD_H
-
-#include <kern_constants.h>
-
-#define TASK_DEBUGREGS(task) ((unsigned long *) &(((char *) (task))[HOST_TASK_DEBUGREGS]))
-#ifdef UML_CONFIG_MODE_TT
-#define TASK_EXTERN_PID(task) *((int *) &(((char *) (task))[HOST_TASK_EXTERN_PID]))
-#endif
-
-#endif
diff --git a/arch/um/include/sysdep-x86_64/ptrace.h b/arch/um/include/sysdep-x86_64/ptrace.h
index 62403bd99661..9ea44d111f33 100644
--- a/arch/um/include/sysdep-x86_64/ptrace.h
+++ b/arch/um/include/sysdep-x86_64/ptrace.h
@@ -1,5 +1,6 @@
/*
* Copyright 2003 PathScale, Inc.
+ * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
*
* Licensed under the GPL
*/
@@ -14,11 +15,6 @@
#define MAX_REG_OFFSET (UM_FRAME_SIZE)
#define MAX_REG_NR ((MAX_REG_OFFSET) / sizeof(unsigned long))
-#ifdef UML_CONFIG_MODE_TT
-#include "sysdep/sc.h"
-#endif
-
-#ifdef UML_CONFIG_MODE_SKAS
#include "skas_ptregs.h"
#define REGS_IP(r) ((r)[HOST_IP])
@@ -88,78 +84,51 @@
#define REGS_ERR(r) ((r)->fault_type)
-#endif
-
-#include "choose-mode.h"
-
-/* XXX */
-union uml_pt_regs {
-#ifdef UML_CONFIG_MODE_TT
- struct tt_regs {
- long syscall;
- unsigned long orig_rax;
- void *sc;
- struct faultinfo faultinfo;
- } tt;
-#endif
-#ifdef UML_CONFIG_MODE_SKAS
- struct skas_regs {
- unsigned long regs[MAX_REG_NR];
- unsigned long fp[HOST_FP_SIZE];
- struct faultinfo faultinfo;
- long syscall;
- int is_user;
- } skas;
-#endif
+struct uml_pt_regs {
+ unsigned long gp[MAX_REG_NR];
+ struct faultinfo faultinfo;
+ long syscall;
+ int is_user;
};
#define EMPTY_UML_PT_REGS { }
-/* XXX */
-extern int mode_tt;
-
-#define UPT_RBX(r) __CHOOSE_MODE(SC_RBX(UPT_SC(r)), REGS_RBX((r)->skas.regs))
-#define UPT_RCX(r) __CHOOSE_MODE(SC_RCX(UPT_SC(r)), REGS_RCX((r)->skas.regs))
-#define UPT_RDX(r) __CHOOSE_MODE(SC_RDX(UPT_SC(r)), REGS_RDX((r)->skas.regs))
-#define UPT_RSI(r) __CHOOSE_MODE(SC_RSI(UPT_SC(r)), REGS_RSI((r)->skas.regs))
-#define UPT_RDI(r) __CHOOSE_MODE(SC_RDI(UPT_SC(r)), REGS_RDI((r)->skas.regs))
-#define UPT_RBP(r) __CHOOSE_MODE(SC_RBP(UPT_SC(r)), REGS_RBP((r)->skas.regs))
-#define UPT_RAX(r) __CHOOSE_MODE(SC_RAX(UPT_SC(r)), REGS_RAX((r)->skas.regs))
-#define UPT_R8(r) __CHOOSE_MODE(SC_R8(UPT_SC(r)), REGS_R8((r)->skas.regs))
-#define UPT_R9(r) __CHOOSE_MODE(SC_R9(UPT_SC(r)), REGS_R9((r)->skas.regs))
-#define UPT_R10(r) __CHOOSE_MODE(SC_R10(UPT_SC(r)), REGS_R10((r)->skas.regs))
-#define UPT_R11(r) __CHOOSE_MODE(SC_R11(UPT_SC(r)), REGS_R11((r)->skas.regs))
-#define UPT_R12(r) __CHOOSE_MODE(SC_R12(UPT_SC(r)), REGS_R12((r)->skas.regs))
-#define UPT_R13(r) __CHOOSE_MODE(SC_R13(UPT_SC(r)), REGS_R13((r)->skas.regs))
-#define UPT_R14(r) __CHOOSE_MODE(SC_R14(UPT_SC(r)), REGS_R14((r)->skas.regs))
-#define UPT_R15(r) __CHOOSE_MODE(SC_R15(UPT_SC(r)), REGS_R15((r)->skas.regs))
-#define UPT_CS(r) __CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs))
-#define UPT_FS_BASE(r) \
- __CHOOSE_MODE(SC_FS_BASE(UPT_SC(r)), REGS_FS_BASE((r)->skas.regs))
-#define UPT_FS(r) __CHOOSE_MODE(SC_FS(UPT_SC(r)), REGS_FS((r)->skas.regs))
-#define UPT_GS_BASE(r) \
- __CHOOSE_MODE(SC_GS_BASE(UPT_SC(r)), REGS_GS_BASE((r)->skas.regs))
-#define UPT_GS(r) __CHOOSE_MODE(SC_GS(UPT_SC(r)), REGS_GS((r)->skas.regs))
-#define UPT_DS(r) __CHOOSE_MODE(SC_DS(UPT_SC(r)), REGS_DS((r)->skas.regs))
-#define UPT_ES(r) __CHOOSE_MODE(SC_ES(UPT_SC(r)), REGS_ES((r)->skas.regs))
-#define UPT_CS(r) __CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs))
-#define UPT_SS(r) __CHOOSE_MODE(SC_SS(UPT_SC(r)), REGS_SS((r)->skas.regs))
-#define UPT_ORIG_RAX(r) \
- __CHOOSE_MODE((r)->tt.orig_rax, REGS_ORIG_RAX((r)->skas.regs))
-
-#define UPT_IP(r) __CHOOSE_MODE(SC_IP(UPT_SC(r)), REGS_IP((r)->skas.regs))
-#define UPT_SP(r) __CHOOSE_MODE(SC_SP(UPT_SC(r)), REGS_SP((r)->skas.regs))
-
-#define UPT_EFLAGS(r) \
- __CHOOSE_MODE(SC_EFLAGS(UPT_SC(r)), REGS_EFLAGS((r)->skas.regs))
-#define UPT_SC(r) ((r)->tt.sc)
-#define UPT_SYSCALL_NR(r) __CHOOSE_MODE((r)->tt.syscall, (r)->skas.syscall)
+#define UPT_RBX(r) REGS_RBX((r)->gp)
+#define UPT_RCX(r) REGS_RCX((r)->gp)
+#define UPT_RDX(r) REGS_RDX((r)->gp)
+#define UPT_RSI(r) REGS_RSI((r)->gp)
+#define UPT_RDI(r) REGS_RDI((r)->gp)
+#define UPT_RBP(r) REGS_RBP((r)->gp)
+#define UPT_RAX(r) REGS_RAX((r)->gp)
+#define UPT_R8(r) REGS_R8((r)->gp)
+#define UPT_R9(r) REGS_R9((r)->gp)
+#define UPT_R10(r) REGS_R10((r)->gp)
+#define UPT_R11(r) REGS_R11((r)->gp)
+#define UPT_R12(r) REGS_R12((r)->gp)
+#define UPT_R13(r) REGS_R13((r)->gp)
+#define UPT_R14(r) REGS_R14((r)->gp)
+#define UPT_R15(r) REGS_R15((r)->gp)
+#define UPT_CS(r) REGS_CS((r)->gp)
+#define UPT_FS_BASE(r) REGS_FS_BASE((r)->gp)
+#define UPT_FS(r) REGS_FS((r)->gp)
+#define UPT_GS_BASE(r) REGS_GS_BASE((r)->gp)
+#define UPT_GS(r) REGS_GS((r)->gp)
+#define UPT_DS(r) REGS_DS((r)->gp)
+#define UPT_ES(r) REGS_ES((r)->gp)
+#define UPT_CS(r) REGS_CS((r)->gp)
+#define UPT_SS(r) REGS_SS((r)->gp)
+#define UPT_ORIG_RAX(r) REGS_ORIG_RAX((r)->gp)
+
+#define UPT_IP(r) REGS_IP((r)->gp)
+#define UPT_SP(r) REGS_SP((r)->gp)
+
+#define UPT_EFLAGS(r) REGS_EFLAGS((r)->gp)
+#define UPT_SYSCALL_NR(r) ((r)->syscall)
#define UPT_SYSCALL_RET(r) UPT_RAX(r)
extern int user_context(unsigned long sp);
-#define UPT_IS_USER(r) \
- CHOOSE_MODE(user_context(UPT_SP(r)), (r)->skas.is_user)
+#define UPT_IS_USER(r) ((r)->is_user)
#define UPT_SYSCALL_ARG1(r) UPT_RDI(r)
#define UPT_SYSCALL_ARG2(r) UPT_RSI(r)
@@ -173,101 +142,99 @@ struct syscall_args {
};
#define SYSCALL_ARGS(r) ((struct syscall_args) \
- { .args = { UPT_SYSCALL_ARG1(r), \
- UPT_SYSCALL_ARG2(r), \
- UPT_SYSCALL_ARG3(r), \
- UPT_SYSCALL_ARG4(r), \
- UPT_SYSCALL_ARG5(r), \
- UPT_SYSCALL_ARG6(r) } } )
+ { .args = { UPT_SYSCALL_ARG1(r), \
+ UPT_SYSCALL_ARG2(r), \
+ UPT_SYSCALL_ARG3(r), \
+ UPT_SYSCALL_ARG4(r), \
+ UPT_SYSCALL_ARG5(r), \
+ UPT_SYSCALL_ARG6(r) } } )
#define UPT_REG(regs, reg) \
- ({ unsigned long val; \
- switch(reg){ \
- case R8: val = UPT_R8(regs); break; \
- case R9: val = UPT_R9(regs); break; \
- case R10: val = UPT_R10(regs); break; \
- case R11: val = UPT_R11(regs); break; \
- case R12: val = UPT_R12(regs); break; \
- case R13: val = UPT_R13(regs); break; \
- case R14: val = UPT_R14(regs); break; \
- case R15: val = UPT_R15(regs); break; \
- case RIP: val = UPT_IP(regs); break; \
- case RSP: val = UPT_SP(regs); break; \
- case RAX: val = UPT_RAX(regs); break; \
- case RBX: val = UPT_RBX(regs); break; \
- case RCX: val = UPT_RCX(regs); break; \
- case RDX: val = UPT_RDX(regs); break; \
- case RSI: val = UPT_RSI(regs); break; \
- case RDI: val = UPT_RDI(regs); break; \
- case RBP: val = UPT_RBP(regs); break; \
- case ORIG_RAX: val = UPT_ORIG_RAX(regs); break; \
- case CS: val = UPT_CS(regs); break; \
- case SS: val = UPT_SS(regs); break; \
- case FS_BASE: val = UPT_FS_BASE(regs); break; \
- case GS_BASE: val = UPT_GS_BASE(regs); break; \
- case DS: val = UPT_DS(regs); break; \
- case ES: val = UPT_ES(regs); break; \
- case FS : val = UPT_FS (regs); break; \
- case GS: val = UPT_GS(regs); break; \
- case EFLAGS: val = UPT_EFLAGS(regs); break; \
- default : \
- panic("Bad register in UPT_REG : %d\n", reg); \
- val = -1; \
- } \
- val; \
- })
+ ({ unsigned long val; \
+ switch(reg){ \
+ case R8: val = UPT_R8(regs); break; \
+ case R9: val = UPT_R9(regs); break; \
+ case R10: val = UPT_R10(regs); break; \
+ case R11: val = UPT_R11(regs); break; \
+ case R12: val = UPT_R12(regs); break; \
+ case R13: val = UPT_R13(regs); break; \
+ case R14: val = UPT_R14(regs); break; \
+ case R15: val = UPT_R15(regs); break; \
+ case RIP: val = UPT_IP(regs); break; \
+ case RSP: val = UPT_SP(regs); break; \
+ case RAX: val = UPT_RAX(regs); break; \
+ case RBX: val = UPT_RBX(regs); break; \
+ case RCX: val = UPT_RCX(regs); break; \
+ case RDX: val = UPT_RDX(regs); break; \
+ case RSI: val = UPT_RSI(regs); break; \
+ case RDI: val = UPT_RDI(regs); break; \
+ case RBP: val = UPT_RBP(regs); break; \
+ case ORIG_RAX: val = UPT_ORIG_RAX(regs); break; \
+ case CS: val = UPT_CS(regs); break; \
+ case SS: val = UPT_SS(regs); break; \
+ case FS_BASE: val = UPT_FS_BASE(regs); break; \
+ case GS_BASE: val = UPT_GS_BASE(regs); break; \
+ case DS: val = UPT_DS(regs); break; \
+ case ES: val = UPT_ES(regs); break; \
+ case FS : val = UPT_FS (regs); break; \
+ case GS: val = UPT_GS(regs); break; \
+ case EFLAGS: val = UPT_EFLAGS(regs); break; \
+ default : \
+ panic("Bad register in UPT_REG : %d\n", reg); \
+ val = -1; \
+ } \
+ val; \
+ })
#define UPT_SET(regs, reg, val) \
- ({ unsigned long __upt_val = val; \
- switch(reg){ \
- case R8: UPT_R8(regs) = __upt_val; break; \
- case R9: UPT_R9(regs) = __upt_val; break; \
- case R10: UPT_R10(regs) = __upt_val; break; \
- case R11: UPT_R11(regs) = __upt_val; break; \
- case R12: UPT_R12(regs) = __upt_val; break; \
- case R13: UPT_R13(regs) = __upt_val; break; \
- case R14: UPT_R14(regs) = __upt_val; break; \
- case R15: UPT_R15(regs) = __upt_val; break; \
- case RIP: UPT_IP(regs) = __upt_val; break; \
- case RSP: UPT_SP(regs) = __upt_val; break; \
- case RAX: UPT_RAX(regs) = __upt_val; break; \
- case RBX: UPT_RBX(regs) = __upt_val; break; \
- case RCX: UPT_RCX(regs) = __upt_val; break; \
- case RDX: UPT_RDX(regs) = __upt_val; break; \
- case RSI: UPT_RSI(regs) = __upt_val; break; \
- case RDI: UPT_RDI(regs) = __upt_val; break; \
- case RBP: UPT_RBP(regs) = __upt_val; break; \
- case ORIG_RAX: UPT_ORIG_RAX(regs) = __upt_val; break; \
- case CS: UPT_CS(regs) = __upt_val; break; \
- case SS: UPT_SS(regs) = __upt_val; break; \
- case FS_BASE: UPT_FS_BASE(regs) = __upt_val; break; \
- case GS_BASE: UPT_GS_BASE(regs) = __upt_val; break; \
- case DS: UPT_DS(regs) = __upt_val; break; \
- case ES: UPT_ES(regs) = __upt_val; break; \
- case FS: UPT_FS(regs) = __upt_val; break; \
- case GS: UPT_GS(regs) = __upt_val; break; \
- case EFLAGS: UPT_EFLAGS(regs) = __upt_val; break; \
- default : \
- panic("Bad register in UPT_SET : %d\n", reg); \
- break; \
- } \
- __upt_val; \
- })
+ ({ unsigned long __upt_val = val; \
+ switch(reg){ \
+ case R8: UPT_R8(regs) = __upt_val; break; \
+ case R9: UPT_R9(regs) = __upt_val; break; \
+ case R10: UPT_R10(regs) = __upt_val; break; \
+ case R11: UPT_R11(regs) = __upt_val; break; \
+ case R12: UPT_R12(regs) = __upt_val; break; \
+ case R13: UPT_R13(regs) = __upt_val; break; \
+ case R14: UPT_R14(regs) = __upt_val; break; \
+ case R15: UPT_R15(regs) = __upt_val; break; \
+ case RIP: UPT_IP(regs) = __upt_val; break; \
+ case RSP: UPT_SP(regs) = __upt_val; break; \
+ case RAX: UPT_RAX(regs) = __upt_val; break; \
+ case RBX: UPT_RBX(regs) = __upt_val; break; \
+ case RCX: UPT_RCX(regs) = __upt_val; break; \
+ case RDX: UPT_RDX(regs) = __upt_val; break; \
+ case RSI: UPT_RSI(regs) = __upt_val; break; \
+ case RDI: UPT_RDI(regs) = __upt_val; break; \
+ case RBP: UPT_RBP(regs) = __upt_val; break; \
+ case ORIG_RAX: UPT_ORIG_RAX(regs) = __upt_val; break; \
+ case CS: UPT_CS(regs) = __upt_val; break; \
+ case SS: UPT_SS(regs) = __upt_val; break; \
+ case FS_BASE: UPT_FS_BASE(regs) = __upt_val; break; \
+ case GS_BASE: UPT_GS_BASE(regs) = __upt_val; break; \
+ case DS: UPT_DS(regs) = __upt_val; break; \
+ case ES: UPT_ES(regs) = __upt_val; break; \
+ case FS: UPT_FS(regs) = __upt_val; break; \
+ case GS: UPT_GS(regs) = __upt_val; break; \
+ case EFLAGS: UPT_EFLAGS(regs) = __upt_val; break; \
+ default : \
+ panic("Bad register in UPT_SET : %d\n", reg); \
+ break; \
+ } \
+ __upt_val; \
+ })
#define UPT_SET_SYSCALL_RETURN(r, res) \
- CHOOSE_MODE(SC_SET_SYSCALL_RETURN(UPT_SC(r), (res)), \
- REGS_SET_SYSCALL_RETURN((r)->skas.regs, (res)))
+ REGS_SET_SYSCALL_RETURN((r)->regs, (res))
+
+#define UPT_RESTART_SYSCALL(r) REGS_RESTART_SYSCALL((r)->gp)
-#define UPT_RESTART_SYSCALL(r) \
- CHOOSE_MODE(SC_RESTART_SYSCALL(UPT_SC(r)), \
- REGS_RESTART_SYSCALL((r)->skas.regs))
+#define UPT_SEGV_IS_FIXABLE(r) REGS_SEGV_IS_FIXABLE(&r->skas)
-#define UPT_SEGV_IS_FIXABLE(r) \
- CHOOSE_MODE(SC_SEGV_IS_FIXABLE(UPT_SC(r)), \
- REGS_SEGV_IS_FIXABLE(&r->skas))
+#define UPT_FAULTINFO(r) (&(r)->faultinfo)
-#define UPT_FAULTINFO(r) \
- CHOOSE_MODE((&(r)->tt.faultinfo), (&(r)->skas.faultinfo))
+static inline void arch_init_registers(int pid)
+{
+}
#endif
diff --git a/arch/um/include/sysdep-x86_64/sigcontext.h b/arch/um/include/sysdep-x86_64/sigcontext.h
index 41073235e7ad..0155133b1458 100644
--- a/arch/um/include/sysdep-x86_64/sigcontext.h
+++ b/arch/um/include/sysdep-x86_64/sigcontext.h
@@ -11,43 +11,17 @@
#define IP_RESTART_SYSCALL(ip) ((ip) -= 2)
-#define SC_RESTART_SYSCALL(sc) IP_RESTART_SYSCALL(SC_IP(sc))
-#define SC_SET_SYSCALL_RETURN(sc, result) SC_RAX(sc) = (result)
-
-#define SC_FAULT_ADDR(sc) SC_CR2(sc)
-#define SC_FAULT_TYPE(sc) SC_ERR(sc)
-
-#define GET_FAULTINFO_FROM_SC(fi,sc) \
+#define GET_FAULTINFO_FROM_SC(fi, sc) \
{ \
(fi).cr2 = SC_CR2(sc); \
(fi).error_code = SC_ERR(sc); \
(fi).trap_no = SC_TRAPNO(sc); \
}
-/* ptrace expects that, at the start of a system call, %eax contains
- * -ENOSYS, so this makes it so.
- */
-
-#define SC_START_SYSCALL(sc) do SC_RAX(sc) = -ENOSYS; while(0)
-
/* This is Page Fault */
#define SEGV_IS_FIXABLE(fi) ((fi)->trap_no == 14)
/* No broken SKAS API, which doesn't pass trap_no, here. */
#define SEGV_MAYBE_FIXABLE(fi) 0
-extern unsigned long *sc_sigmask(void *sc_ptr);
-
#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
-
diff --git a/arch/um/include/sysdep-x86_64/stub.h b/arch/um/include/sysdep-x86_64/stub.h
index 92e989f81761..655f9c2de3ac 100644
--- a/arch/um/include/sysdep-x86_64/stub.h
+++ b/arch/um/include/sysdep-x86_64/stub.h
@@ -9,6 +9,7 @@
#include <sys/mman.h>
#include <asm/unistd.h>
#include <sysdep/ptrace_user.h>
+#include "as-layout.h"
#include "stub-data.h"
#include "kern_constants.h"
#include "uml-config.h"
@@ -94,13 +95,13 @@ static inline void remap_stack(long fd, unsigned long offset)
{
__asm__ volatile ("movq %4,%%r10 ; movq %5,%%r8 ; "
"movq %6, %%r9; " __syscall "; movq %7, %%rbx ; "
- "movq %%rax, (%%rbx)":
- : "a" (STUB_MMAP_NR), "D" (UML_CONFIG_STUB_DATA),
- "S" (UM_KERN_PAGE_SIZE),
- "d" (PROT_READ | PROT_WRITE),
- "g" (MAP_FIXED | MAP_SHARED), "g" (fd),
+ "movq %%rax, (%%rbx)":
+ : "a" (STUB_MMAP_NR), "D" (STUB_DATA),
+ "S" (UM_KERN_PAGE_SIZE),
+ "d" (PROT_READ | PROT_WRITE),
+ "g" (MAP_FIXED | MAP_SHARED), "g" (fd),
"g" (offset),
- "i" (&((struct stub_data *) UML_CONFIG_STUB_DATA)->err)
+ "i" (&((struct stub_data *) STUB_DATA)->err)
: __syscall_clobber, "r10", "r8", "r9" );
}
diff --git a/arch/um/include/sysdep-x86_64/thread.h b/arch/um/include/sysdep-x86_64/thread.h
deleted file mode 100644
index cbef3e1697f4..000000000000
--- a/arch/um/include/sysdep-x86_64/thread.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __UM_THREAD_H
-#define __UM_THREAD_H
-
-#include <kern_constants.h>
-
-#ifdef UML_CONFIG_MODE_TT
-#define TASK_EXTERN_PID(task) *((int *) &(((char *) (task))[HOST_TASK_EXTERN_PID]))
-#endif
-
-#endif
diff --git a/arch/um/include/task.h b/arch/um/include/task.h
index 6375ba7203c9..3fe726b3cf48 100644
--- a/arch/um/include/task.h
+++ b/arch/um/include/task.h
@@ -3,7 +3,7 @@
#include <kern_constants.h>
-#define TASK_REGS(task) ((union uml_pt_regs *) &(((char *) (task))[HOST_TASK_REGS]))
+#define TASK_REGS(task) ((struct uml_pt_regs *) &(((char *) (task))[HOST_TASK_REGS]))
#define TASK_PID(task) *((int *) &(((char *) (task))[HOST_TASK_PID]))
#endif
diff --git a/arch/um/include/tlb.h b/arch/um/include/tlb.h
index bcd1a4afb842..ecd2265b301b 100644
--- a/arch/um/include/tlb.h
+++ b/arch/um/include/tlb.h
@@ -8,34 +8,7 @@
#include "um_mmu.h"
-struct host_vm_op {
- enum { NONE, MMAP, MUNMAP, MPROTECT } type;
- union {
- struct {
- unsigned long addr;
- unsigned long len;
- unsigned int prot;
- int fd;
- __u64 offset;
- } mmap;
- struct {
- unsigned long addr;
- unsigned long len;
- } munmap;
- struct {
- unsigned long addr;
- unsigned long len;
- unsigned int prot;
- } mprotect;
- } u;
-};
-
extern void force_flush_all(void);
-extern void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
- unsigned long end_addr, int force,
- int (*do_ops)(union mm_context *,
- struct host_vm_op *, int, int,
- void **));
extern int flush_tlb_kernel_range_common(unsigned long start,
unsigned long end);
diff --git a/arch/um/include/tt/debug.h b/arch/um/include/tt/debug.h
deleted file mode 100644
index 9778fa838296..000000000000
--- a/arch/um/include/tt/debug.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) and
- * Lars Brinkhoff.
- * Licensed under the GPL
- */
-
-#ifndef __UML_TT_DEBUG_H
-#define __UML_TT_DEBUG_H
-
-extern int debugger_proxy(int status, pid_t pid);
-extern void child_proxy(pid_t pid, int status);
-extern void init_proxy (pid_t pid, int waiting, int status);
-extern int start_debugger(char *prog, int startup, int stop, int *debugger_fd);
-extern void fake_child_exit(void);
-extern int gdb_config(char *str);
-extern int gdb_remove(int unused);
-
-#endif
diff --git a/arch/um/include/tt/mmu-tt.h b/arch/um/include/tt/mmu-tt.h
deleted file mode 100644
index 572a78b22587..000000000000
--- a/arch/um/include/tt/mmu-tt.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __TT_MMU_H
-#define __TT_MMU_H
-
-struct mmu_context_tt {
-};
-
-#endif
diff --git a/arch/um/include/tt/mode-tt.h b/arch/um/include/tt/mode-tt.h
deleted file mode 100644
index 2823cd56eea2..000000000000
--- a/arch/um/include/tt/mode-tt.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __MODE_TT_H__
-#define __MODE_TT_H__
-
-#include "sysdep/ptrace.h"
-
-enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB };
-
-extern int tracing_pid;
-
-extern int tracer(int (*init_proc)(void *), void *sp);
-extern void sig_handler_common_tt(int sig, void *sc);
-extern void syscall_handler_tt(int sig, union uml_pt_regs *regs);
-extern void reboot_tt(void);
-extern void halt_tt(void);
-extern int is_tracer_winch(int pid, int fd, void *data);
-extern void kill_off_processes_tt(void);
-
-#endif
diff --git a/arch/um/include/tt/mode_kern_tt.h b/arch/um/include/tt/mode_kern_tt.h
deleted file mode 100644
index a4fc63057195..000000000000
--- a/arch/um/include/tt/mode_kern_tt.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __TT_MODE_KERN_H__
-#define __TT_MODE_KERN_H__
-
-#include "linux/sched.h"
-#include "asm/page.h"
-#include "asm/ptrace.h"
-#include "asm/uaccess.h"
-
-extern void switch_to_tt(void *prev, void *next);
-extern void flush_thread_tt(void);
-extern void start_thread_tt(struct pt_regs *regs, unsigned long eip,
- unsigned long esp);
-extern int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp,
- unsigned long stack_top, struct task_struct *p,
- struct pt_regs *regs);
-extern void release_thread_tt(struct task_struct *task);
-extern void initial_thread_cb_tt(void (*proc)(void *), void *arg);
-extern void init_idle_tt(void);
-extern void flush_tlb_kernel_range_tt(unsigned long start, unsigned long end);
-extern void flush_tlb_kernel_vm_tt(void);
-extern void __flush_tlb_one_tt(unsigned long addr);
-extern void flush_tlb_range_tt(struct vm_area_struct *vma,
- unsigned long start, unsigned long end);
-extern void flush_tlb_mm_tt(struct mm_struct *mm);
-extern void force_flush_all_tt(void);
-extern long execute_syscall_tt(void *r);
-extern void before_mem_tt(unsigned long brk_start);
-extern unsigned long set_task_sizes_tt(unsigned long *task_size_out);
-extern int start_uml_tt(void);
-extern int external_pid_tt(struct task_struct *task);
-extern int thread_pid_tt(struct task_struct *task);
-
-#define kmem_end_tt (host_task_size - ABOVE_KMEM)
-
-#endif
diff --git a/arch/um/include/tt/tt.h b/arch/um/include/tt/tt.h
deleted file mode 100644
index acb8356e1f98..000000000000
--- a/arch/um/include/tt/tt.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __TT_H__
-#define __TT_H__
-
-#include "sysdep/ptrace.h"
-
-extern int gdb_pid;
-extern int debug;
-extern int debug_stop;
-extern int debug_trace;
-
-extern int honeypot;
-
-extern int fork_tramp(void *sig_stack);
-extern int do_proc_op(void *t, int proc_id);
-extern int tracer(int (*init_proc)(void *), void *sp);
-extern void attach_process(int pid);
-extern void tracer_panic(char *format, ...)
- __attribute__ ((format (printf, 1, 2)));
-extern void set_init_pid(int pid);
-extern int set_user_mode(void *task);
-extern void set_tracing(void *t, int tracing);
-extern int is_tracing(void *task);
-extern void syscall_handler(int sig, union uml_pt_regs *regs);
-extern void exit_kernel(int pid, void *task);
-extern void do_syscall(void *task, int pid, int local_using_sysemu);
-extern void do_sigtrap(void *task);
-extern int is_valid_pid(int pid);
-extern void remap_data(void *segment_start, void *segment_end, int w);
-extern long execute_syscall_tt(void *r);
-
-#endif
-
diff --git a/arch/um/include/tt/uaccess-tt.h b/arch/um/include/tt/uaccess-tt.h
deleted file mode 100644
index 13a64f61fcf4..000000000000
--- a/arch/um/include/tt/uaccess-tt.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#ifndef __TT_UACCESS_H
-#define __TT_UACCESS_H
-
-#include "linux/string.h"
-#include "linux/sched.h"
-#include "asm/processor.h"
-#include "asm/errno.h"
-#include "asm/current.h"
-#include "asm/a.out.h"
-#include "uml_uaccess.h"
-
-#define ABOVE_KMEM (16 * 1024 * 1024)
-
-extern unsigned long end_vm;
-extern unsigned long uml_physmem;
-
-#define is_stack(addr, size) \
- (((unsigned long) (addr) < STACK_TOP) && \
- ((unsigned long) (addr) >= STACK_TOP - ABOVE_KMEM) && \
- (((unsigned long) (addr) + (size)) <= STACK_TOP))
-
-#define access_ok_tt(type, addr, size) \
- (is_stack(addr, size))
-
-extern int __do_copy_from_user(void *to, const void *from, int n,
- void **fault_addr, void **fault_catcher);
-extern int __do_strncpy_from_user(char *dst, const char *src, size_t n,
- void **fault_addr, void **fault_catcher);
-extern int __do_clear_user(void *mem, size_t len, void **fault_addr,
- void **fault_catcher);
-extern int __do_strnlen_user(const char *str, unsigned long n,
- void **fault_addr, void **fault_catcher);
-
-extern int copy_from_user_tt(void *to, const void __user *from, int n);
-extern int copy_to_user_tt(void __user *to, const void *from, int n);
-extern int strncpy_from_user_tt(char *dst, const char __user *src, int count);
-extern int __clear_user_tt(void __user *mem, int len);
-extern int clear_user_tt(void __user *mem, int len);
-extern int strnlen_user_tt(const void __user *str, int len);
-
-#endif
diff --git a/arch/um/include/um_mmu.h b/arch/um/include/um_mmu.h
index 0fa643238300..8855d8df512f 100644
--- a/arch/um/include/um_mmu.h
+++ b/arch/um/include/um_mmu.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -7,34 +7,22 @@
#define __ARCH_UM_MMU_H
#include "uml-config.h"
-#include "choose-mode.h"
+#include "mm_id.h"
+#include "asm/ldt.h"
-#ifdef UML_CONFIG_MODE_TT
-#include "mmu-tt.h"
+typedef struct mm_context {
+ struct mm_id id;
+ unsigned long last_page_table;
+#ifdef CONFIG_3_LEVEL_PGTABLES
+ unsigned long last_pmd;
#endif
+ struct uml_ldt ldt;
+} mm_context_t;
-#ifdef UML_CONFIG_MODE_SKAS
-#include "mmu-skas.h"
-#endif
+extern void __switch_mm(struct mm_id * mm_idp);
-typedef union mm_context {
-#ifdef UML_CONFIG_MODE_TT
- struct mmu_context_tt tt;
-#endif
-#ifdef UML_CONFIG_MODE_SKAS
- struct mmu_context_skas skas;
-#endif
-} mm_context_t;
+/* Avoid tangled inclusion with asm/ldt.h */
+extern long init_new_ldt(struct mm_context *to_mm, struct mm_context *from_mm);
+extern void free_ldt(struct mm_context *mm);
#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/um_uaccess.h b/arch/um/include/um_uaccess.h
index 5126a99b5961..fdfc06b85605 100644
--- a/arch/um/include/um_uaccess.h
+++ b/arch/um/include/um_uaccess.h
@@ -1,26 +1,16 @@
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
#ifndef __ARCH_UM_UACCESS_H
#define __ARCH_UM_UACCESS_H
-#include "choose-mode.h"
-
-#ifdef CONFIG_MODE_TT
-#include "uaccess-tt.h"
-#endif
-
-#ifdef CONFIG_MODE_SKAS
-#include "uaccess-skas.h"
-#endif
-
#include "asm/fixmap.h"
#define __under_task_size(addr, size) \
(((unsigned long) (addr) < TASK_SIZE) && \
- (((unsigned long) (addr) + (size)) < TASK_SIZE))
+ (((unsigned long) (addr) + (size)) < TASK_SIZE))
#define __access_ok_vsyscall(type, addr, size) \
((type == VERIFY_READ) && \
@@ -35,20 +25,14 @@
(__addr_range_nowrap(addr, size) && \
(__under_task_size(addr, size) || \
__access_ok_vsyscall(type, addr, size) || \
- segment_eq(get_fs(), KERNEL_DS) || \
- CHOOSE_MODE_PROC(access_ok_tt, access_ok_skas, type, addr, size)))
+ segment_eq(get_fs(), KERNEL_DS)))
-static inline int copy_from_user(void *to, const void __user *from, int n)
-{
- return(CHOOSE_MODE_PROC(copy_from_user_tt, copy_from_user_skas, to,
- from, n));
-}
+extern int copy_from_user(void *to, const void __user *from, int n);
+extern int copy_to_user(void __user *to, const void *from, int n);
-static inline int copy_to_user(void __user *to, const void *from, int n)
-{
- return(CHOOSE_MODE_PROC(copy_to_user_tt, copy_to_user_skas, to,
- from, n));
-}
+extern int __do_copy_to_user(void *to, const void *from, int n,
+ void **fault_addr, jmp_buf **fault_catcher);
+extern void __do_copy(void *to, const void *from, int n);
/*
* strncpy_from_user: - Copy a NUL terminated string from userspace.
@@ -69,11 +53,7 @@ static inline int copy_to_user(void __user *to, const void *from, int n)
* and returns @count.
*/
-static inline int strncpy_from_user(char *dst, const char __user *src, int count)
-{
- return(CHOOSE_MODE_PROC(strncpy_from_user_tt, strncpy_from_user_skas,
- dst, src, count));
-}
+extern int strncpy_from_user(char *dst, const char __user *src, int count);
/*
* __clear_user: - Zero a block of memory in user space, with less checking.
@@ -86,10 +66,7 @@ static inline int strncpy_from_user(char *dst, const char __user *src, int count
* Returns number of bytes that could not be cleared.
* On success, this will be zero.
*/
-static inline int __clear_user(void *mem, int len)
-{
- return(CHOOSE_MODE_PROC(__clear_user_tt, __clear_user_skas, mem, len));
-}
+extern int __clear_user(void __user *mem, int len);
/*
* clear_user: - Zero a block of memory in user space.
@@ -101,10 +78,7 @@ static inline int __clear_user(void *mem, int len)
* Returns number of bytes that could not be cleared.
* On success, this will be zero.
*/
-static inline int clear_user(void __user *mem, int len)
-{
- return(CHOOSE_MODE_PROC(clear_user_tt, clear_user_skas, mem, len));
-}
+extern int clear_user(void __user *mem, int len);
/*
* strlen_user: - Get the size of a string in user space.
@@ -117,20 +91,6 @@ static inline int clear_user(void __user *mem, int len)
* On exception, returns 0.
* If the string is too long, returns a value greater than @n.
*/
-static inline int strnlen_user(const void __user *str, long len)
-{
- return(CHOOSE_MODE_PROC(strnlen_user_tt, strnlen_user_skas, str, len));
-}
+extern int strnlen_user(const void __user *str, int len);
#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/uml_uaccess.h b/arch/um/include/uml_uaccess.h
deleted file mode 100644
index c0df11d06f5e..000000000000
--- a/arch/um/include/uml_uaccess.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __UML_UACCESS_H__
-#define __UML_UACCESS_H__
-
-extern int __do_copy_to_user(void *to, const void *from, int n,
- void **fault_addr, void **fault_catcher);
-void __do_copy(void *to, const void *from, int n);
-
-#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/user.h b/arch/um/include/user.h
index d380e6d91a90..1723fac6f40d 100644
--- a/arch/um/include/user.h
+++ b/arch/um/include/user.h
@@ -1,11 +1,13 @@
/*
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
#ifndef __USER_H__
#define __USER_H__
+#include "uml-config.h"
+
/*
* The usual definition - copied here because the kernel provides its own,
* fancier, type-safe, definition. Using that one would require
@@ -14,15 +16,26 @@
*/
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-/*
- * This will provide the size_t definition in both kernel and userspace builds
- */
+/* This is to get size_t */
+#ifdef __KERNEL__
#include <linux/types.h>
+#else
+#include <stddef.h>
+#endif
extern void panic(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
+
+#ifdef UML_CONFIG_PRINTK
extern int printk(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
+#else
+static inline int printk(const char *fmt, ...)
+{
+ return 0;
+}
+#endif
+
extern void schedule(void);
extern int in_aton(char *str);
extern int open_gdb_chan(void);
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index c5cf4a0827b0..499e5e95e609 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux,intel}.com)
# Licensed under the GPL
#
@@ -9,15 +9,12 @@ clean-files :=
obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \
physmem.o process.o ptrace.o reboot.o sigio.o \
signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o uaccess.o \
- um_arch.o umid.o
+ um_arch.o umid.o skas/
obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
obj-$(CONFIG_GPROF) += gprof_syms.o
obj-$(CONFIG_GCOV) += gmon_syms.o
-obj-$(CONFIG_MODE_TT) += tt/
-obj-$(CONFIG_MODE_SKAS) += skas/
-
USER_OBJS := config.o
include arch/um/scripts/Makefile.rules
diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S
index 41850906116e..3866f4960f04 100644
--- a/arch/um/kernel/dyn.lds.S
+++ b/arch/um/kernel/dyn.lds.S
@@ -10,8 +10,6 @@ SECTIONS
PROVIDE (__executable_start = START);
. = START + SIZEOF_HEADERS;
.interp : { *(.interp) }
- /* Used in arch/um/kernel/mem.c. Any memory between START and __binary_start
- * is remapped.*/
__binary_start = .;
. = ALIGN(4096); /* Init code and data */
_text = .;
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c
index ce6828fd396f..8196450451cd 100644
--- a/arch/um/kernel/exec.c
+++ b/arch/um/kernel/exec.c
@@ -1,35 +1,44 @@
/*
- * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/slab.h"
+#include "linux/stddef.h"
+#include "linux/fs.h"
#include "linux/smp_lock.h"
#include "linux/ptrace.h"
-#include "linux/fs.h"
-#include "asm/ptrace.h"
-#include "asm/pgtable.h"
-#include "asm/tlbflush.h"
+#include "linux/sched.h"
+#include "asm/current.h"
+#include "asm/processor.h"
#include "asm/uaccess.h"
-#include "kern_util.h"
#include "as-layout.h"
#include "mem_user.h"
-#include "kern.h"
-#include "irq_user.h"
-#include "tlb.h"
+#include "skas.h"
#include "os.h"
-#include "choose-mode.h"
-#include "mode_kern.h"
void flush_thread(void)
{
+ void *data = NULL;
+ unsigned long end = proc_mm ? task_size : STUB_START;
+ int ret;
+
arch_flush_thread(&current->thread.arch);
- CHOOSE_MODE(flush_thread_tt(), flush_thread_skas());
+
+ ret = unmap(&current->mm->context.id, 0, end, 1, &data);
+ if (ret) {
+ printk(KERN_ERR "flush_thread - clearing address space failed, "
+ "err = %d\n", ret);
+ force_sig(SIGKILL, current);
+ }
+
+ __switch_mm(&current->mm->context.id);
}
void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
{
- CHOOSE_MODE_PROC(start_thread_tt, start_thread_skas, regs, eip, esp);
+ set_fs(USER_DS);
+ PT_REGS_IP(regs) = eip;
+ PT_REGS_SP(regs) = esp;
}
#ifdef CONFIG_TTY_LOG
@@ -39,7 +48,7 @@ extern void log_exec(char **argv, void *tty);
static long execve1(char *file, char __user * __user *argv,
char __user *__user *env)
{
- long error;
+ long error;
#ifdef CONFIG_TTY_LOG
struct tty_struct *tty;
@@ -49,17 +58,16 @@ static long execve1(char *file, char __user * __user *argv,
log_exec(argv, tty);
mutex_unlock(&tty_mutex);
#endif
- error = do_execve(file, argv, env, &current->thread.regs);
- if (error == 0){
+ error = do_execve(file, argv, env, &current->thread.regs);
+ if (error == 0) {
task_lock(current);
- current->ptrace &= ~PT_DTRACE;
+ current->ptrace &= ~PT_DTRACE;
#ifdef SUBARCH_EXECVE1
SUBARCH_EXECVE1(&current->thread.regs.regs);
#endif
task_unlock(current);
- set_cmdline(current_cmd());
- }
- return(error);
+ }
+ return error;
}
long um_execve(char *file, char __user *__user *argv, char __user *__user *env)
@@ -67,9 +75,9 @@ long um_execve(char *file, char __user *__user *argv, char __user *__user *env)
long err;
err = execve1(file, argv, env);
- if(!err)
- do_longjmp(current->thread.exec_buf, 1);
- return(err);
+ if (!err)
+ UML_LONGJMP(current->thread.exec_buf, 1);
+ return err;
}
long sys_execve(char __user *file, char __user *__user *argv,
@@ -86,5 +94,5 @@ long sys_execve(char __user *file, char __user *__user *argv,
putname(filename);
out:
unlock_kernel();
- return(error);
+ return error;
}
diff --git a/arch/um/kernel/gmon_syms.c b/arch/um/kernel/gmon_syms.c
index 13aa115cd1b4..734f873cab12 100644
--- a/arch/um/kernel/gmon_syms.c
+++ b/arch/um/kernel/gmon_syms.c
@@ -12,8 +12,8 @@ EXPORT_SYMBOL(__bb_init_func);
* versions in libgcov.
*
* Since SuSE backported the fix, we cannot handle it depending on GCC version.
- * So, unconditinally export it. But also give it a weak declaration, which will
- * be overriden by any other one.
+ * So, unconditionally export it. But also give it a weak declaration, which will
+ * be overridden by any other one.
*/
extern void __gcov_init(void *) __attribute__((weak));
diff --git a/arch/um/kernel/init_task.c b/arch/um/kernel/init_task.c
index cba516e6c99a..dcfceca95052 100644
--- a/arch/um/kernel/init_task.c
+++ b/arch/um/kernel/init_task.c
@@ -3,16 +3,12 @@
* Licensed under the GPL
*/
-#include "linux/mm.h"
-#include "linux/fs.h"
-#include "linux/module.h"
#include "linux/sched.h"
#include "linux/init_task.h"
+#include "linux/fs.h"
+#include "linux/module.h"
#include "linux/mqueue.h"
#include "asm/uaccess.h"
-#include "asm/pgtable.h"
-#include "mem_user.h"
-#include "os.h"
static struct fs_struct init_fs = INIT_FS;
struct mm_struct init_mm = INIT_MM(init_mm);
@@ -46,8 +42,3 @@ union thread_union init_thread_union
union thread_union cpu0_irqstack
__attribute__((__section__(".data.init_irqstack"))) =
{ INIT_THREAD_INFO(init_task) };
-
-void unprotect_stack(unsigned long stack)
-{
- os_protect_memory((void *) stack, THREAD_SIZE, 1, 1, 0);
-}
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index cf0dd9cf8c43..ba11ccd6a8a3 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -1,37 +1,19 @@
/*
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
* Derived (i.e. mostly copied) from arch/i386/kernel/irq.c:
* Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
*/
-#include "linux/kernel.h"
-#include "linux/module.h"
-#include "linux/smp.h"
-#include "linux/kernel_stat.h"
+#include "linux/cpumask.h"
+#include "linux/hardirq.h"
#include "linux/interrupt.h"
-#include "linux/random.h"
-#include "linux/slab.h"
-#include "linux/file.h"
-#include "linux/proc_fs.h"
-#include "linux/init.h"
+#include "linux/kernel_stat.h"
+#include "linux/module.h"
#include "linux/seq_file.h"
-#include "linux/profile.h"
-#include "linux/hardirq.h"
-#include "asm/irq.h"
-#include "asm/hw_irq.h"
-#include "asm/atomic.h"
-#include "asm/signal.h"
-#include "asm/system.h"
-#include "asm/errno.h"
-#include "asm/uaccess.h"
+#include "as-layout.h"
#include "kern_util.h"
-#include "irq_user.h"
-#include "irq_kern.h"
#include "os.h"
-#include "sigio.h"
-#include "misc_constants.h"
-#include "as-layout.h"
/*
* Generic, controller-independent functions:
@@ -71,9 +53,8 @@ int show_interrupts(struct seq_file *p, void *v)
seq_putc(p, '\n');
skip:
spin_unlock_irqrestore(&irq_desc[i].lock, flags);
- } else if (i == NR_IRQS) {
+ } else if (i == NR_IRQS)
seq_putc(p, '\n');
- }
return 0;
}
@@ -91,7 +72,7 @@ static struct irq_fd **last_irq_ptr = &active_fds;
extern void free_irqs(void);
-void sigio_handler(int sig, union uml_pt_regs *regs)
+void sigio_handler(int sig, struct uml_pt_regs *regs)
{
struct irq_fd *irq_fd;
int n;
@@ -102,11 +83,13 @@ void sigio_handler(int sig, union uml_pt_regs *regs)
while (1) {
n = os_waiting_for_events(active_fds);
if (n <= 0) {
- if(n == -EINTR) continue;
+ if (n == -EINTR)
+ continue;
else break;
}
- for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) {
+ for (irq_fd = active_fds; irq_fd != NULL;
+ irq_fd = irq_fd->next) {
if (irq_fd->current_events != 0) {
irq_fd->current_events = 0;
do_IRQ(irq_fd->irq, regs);
@@ -138,8 +121,7 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
if (type == IRQ_READ)
events = UM_POLLIN | UM_POLLPRI;
- else
- events = UM_POLLOUT;
+ else events = UM_POLLOUT;
*new_fd = ((struct irq_fd) { .next = NULL,
.id = dev_id,
.fd = fd,
@@ -153,9 +135,10 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
spin_lock_irqsave(&irq_lock, flags);
for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) {
if ((irq_fd->fd == fd) && (irq_fd->type == type)) {
- printk("Registering fd %d twice\n", fd);
- printk("Irqs : %d, %d\n", irq_fd->irq, irq);
- printk("Ids : 0x%p, 0x%p\n", irq_fd->id, dev_id);
+ printk(KERN_ERR "Registering fd %d twice\n", fd);
+ printk(KERN_ERR "Irqs : %d, %d\n", irq_fd->irq, irq);
+ printk(KERN_ERR "Ids : 0x%p, 0x%p\n", irq_fd->id,
+ dev_id);
goto out_unlock;
}
}
@@ -171,7 +154,8 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
if (n == 0)
break;
- /* n > 0
+ /*
+ * n > 0
* It means we couldn't put new pollfd to current pollfds
* and tmp_fds is NULL or too small for new pollfds array.
* Needed size is equal to n as minimum.
@@ -197,7 +181,8 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
spin_unlock_irqrestore(&irq_lock, flags);
- /* This calls activate_fd, so it has to be outside the critical
+ /*
+ * This calls activate_fd, so it has to be outside the critical
* section.
*/
maybe_sigio_broken(fd, (type == IRQ_READ));
@@ -264,13 +249,14 @@ static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out)
i++;
}
if (irq == NULL) {
- printk("find_irq_by_fd doesn't have descriptor %d\n", fd);
+ printk(KERN_ERR "find_irq_by_fd doesn't have descriptor %d\n",
+ fd);
goto out;
}
fdi = os_get_pollfd(i);
if ((fdi != -1) && (fdi != fd)) {
- printk("find_irq_by_fd - mismatch between active_fds and "
- "pollfds, fd %d vs %d, need %d\n", irq->fd,
+ printk(KERN_ERR "find_irq_by_fd - mismatch between active_fds "
+ "and pollfds, fd %d vs %d, need %d\n", irq->fd,
fdi, fd);
irq = NULL;
goto out;
@@ -306,7 +292,7 @@ void deactivate_fd(int fd, int irqnum)
spin_lock_irqsave(&irq_lock, flags);
irq = find_irq_by_fd(fd, irqnum, &i);
- if(irq == NULL){
+ if (irq == NULL) {
spin_unlock_irqrestore(&irq_lock, flags);
return;
}
@@ -339,36 +325,12 @@ int deactivate_all_fds(void)
return 0;
}
-#ifdef CONFIG_MODE_TT
-void forward_interrupts(int pid)
-{
- struct irq_fd *irq;
- unsigned long flags;
- int err;
-
- spin_lock_irqsave(&irq_lock, flags);
- for (irq = active_fds; irq != NULL; irq = irq->next) {
- err = os_set_owner(irq->fd, pid);
- if (err < 0) {
- /* XXX Just remove the irq rather than
- * print out an infinite stream of these
- */
- printk("Failed to forward %d to pid %d, err = %d\n",
- irq->fd, pid, -err);
- }
-
- irq->pid = pid;
- }
- spin_unlock_irqrestore(&irq_lock, flags);
-}
-#endif
-
/*
- * do_IRQ handles all normal device IRQ's (the special
+ * do_IRQ handles all normal device IRQs (the special
* SMP cross-CPU interrupts have their own specific
* handlers).
*/
-unsigned int do_IRQ(int irq, union uml_pt_regs *regs)
+unsigned int do_IRQ(int irq, struct uml_pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs((struct pt_regs *)regs);
irq_enter();
@@ -385,19 +347,22 @@ int um_request_irq(unsigned int irq, int fd, int type,
{
int err;
- err = request_irq(irq, handler, irqflags, devname, dev_id);
- if (err)
- return err;
-
- if (fd != -1)
+ if (fd != -1) {
err = activate_fd(irq, fd, type, dev_id);
- return err;
+ if (err)
+ return err;
+ }
+
+ return request_irq(irq, handler, irqflags, devname, dev_id);
}
+
EXPORT_SYMBOL(um_request_irq);
EXPORT_SYMBOL(reactivate_fd);
-/* hw_interrupt_type must define (startup || enable) &&
- * (shutdown || disable) && end */
+/*
+ * hw_interrupt_type must define (startup || enable) &&
+ * (shutdown || disable) && end
+ */
static void dummy(unsigned int irq)
{
}
@@ -446,7 +411,8 @@ int init_aio_irq(int irq, char *name, irq_handler_t handler)
err = os_pipe(fds, 1, 1);
if (err) {
- printk("init_aio_irq - os_pipe failed, err = %d\n", -err);
+ printk(KERN_ERR "init_aio_irq - os_pipe failed, err = %d\n",
+ -err);
goto out;
}
@@ -454,7 +420,8 @@ int init_aio_irq(int irq, char *name, irq_handler_t handler)
IRQF_DISABLED | IRQF_SAMPLE_RANDOM, name,
(void *) (long) fds[0]);
if (err) {
- printk("init_aio_irq - : um_request_irq failed, err = %d\n",
+ printk(KERN_ERR "init_aio_irq - : um_request_irq failed, "
+ "err = %d\n",
err);
goto out_close;
}
@@ -525,8 +492,9 @@ unsigned long to_irq_stack(unsigned long *mask_out)
int nested;
mask = xchg(&pending_mask, *mask_out);
- if(mask != 0){
- /* If any interrupts come in at this point, we want to
+ if (mask != 0) {
+ /*
+ * If any interrupts come in at this point, we want to
* make sure that their bits aren't lost by our
* putting our bit in. So, this loop accumulates bits
* until xchg returns the same value that we put in.
@@ -538,13 +506,13 @@ unsigned long to_irq_stack(unsigned long *mask_out)
do {
old |= mask;
mask = xchg(&pending_mask, old);
- } while(mask != old);
+ } while (mask != old);
return 1;
}
ti = current_thread_info();
nested = (ti->real_thread != NULL);
- if(!nested){
+ if (!nested) {
struct task_struct *task;
struct thread_info *tti;
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c
index 7b3e53fb8070..1b388b41d95d 100644
--- a/arch/um/kernel/ksyms.c
+++ b/arch/um/kernel/ksyms.c
@@ -1,22 +1,15 @@
/*
- * Copyright (C) 2001 - 2004 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
#include "linux/module.h"
-#include "linux/string.h"
-#include "linux/smp_lock.h"
-#include "linux/spinlock.h"
-#include "linux/highmem.h"
-#include "asm/current.h"
-#include "asm/processor.h"
-#include "asm/unistd.h"
-#include "asm/pgalloc.h"
-#include "asm/pgtable.h"
-#include "asm/page.h"
+#include "linux/syscalls.h"
+#include "asm/a.out.h"
#include "asm/tlbflush.h"
-#include "kern_util.h"
+#include "asm/uaccess.h"
#include "as-layout.h"
+#include "kern_util.h"
#include "mem_user.h"
#include "os.h"
@@ -34,30 +27,19 @@ EXPORT_SYMBOL(get_kmem_end);
EXPORT_SYMBOL(high_physmem);
EXPORT_SYMBOL(empty_zero_page);
EXPORT_SYMBOL(um_virt_to_phys);
-EXPORT_SYMBOL(mode_tt);
EXPORT_SYMBOL(handle_page_fault);
EXPORT_SYMBOL(find_iomem);
-#ifdef CONFIG_MODE_TT
-EXPORT_SYMBOL(stop);
-EXPORT_SYMBOL(strncpy_from_user_tt);
-EXPORT_SYMBOL(copy_from_user_tt);
-EXPORT_SYMBOL(copy_to_user_tt);
-#endif
-
-#ifdef CONFIG_MODE_SKAS
-EXPORT_SYMBOL(strnlen_user_skas);
-EXPORT_SYMBOL(strncpy_from_user_skas);
-EXPORT_SYMBOL(copy_to_user_skas);
-EXPORT_SYMBOL(copy_from_user_skas);
-EXPORT_SYMBOL(clear_user_skas);
-#endif
+EXPORT_SYMBOL(strnlen_user);
+EXPORT_SYMBOL(strncpy_from_user);
+EXPORT_SYMBOL(copy_to_user);
+EXPORT_SYMBOL(copy_from_user);
+EXPORT_SYMBOL(clear_user);
EXPORT_SYMBOL(uml_strdup);
EXPORT_SYMBOL(os_stat_fd);
EXPORT_SYMBOL(os_stat_file);
EXPORT_SYMBOL(os_access);
-EXPORT_SYMBOL(os_print_error);
EXPORT_SYMBOL(os_get_exec_close);
EXPORT_SYMBOL(os_set_exec_close);
EXPORT_SYMBOL(os_getpid);
@@ -85,9 +67,6 @@ EXPORT_SYMBOL(run_helper);
EXPORT_SYMBOL(start_thread);
EXPORT_SYMBOL(dump_thread);
-EXPORT_SYMBOL(do_gettimeofday);
-EXPORT_SYMBOL(do_settimeofday);
-
#ifdef CONFIG_SMP
/* required for SMP */
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index d2b11f242698..59822dee438a 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -17,7 +17,7 @@
#include "as-layout.h"
#include "kern.h"
#include "mem_user.h"
-#include "uml_uaccess.h"
+#include "um_uaccess.h"
#include "os.h"
#include "linux/types.h"
#include "linux/string.h"
@@ -165,7 +165,7 @@ static void __init kmap_init(void)
kmap_prot = PAGE_KERNEL;
}
-static void init_highmem(void)
+static void __init init_highmem(void)
{
pgd_t *pgd;
pud_t *pud;
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
index 5ee7e851bbc1..e66432f42485 100644
--- a/arch/um/kernel/physmem.c
+++ b/arch/um/kernel/physmem.c
@@ -1,25 +1,17 @@
/*
- * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/mm.h"
-#include "linux/rbtree.h"
-#include "linux/slab.h"
-#include "linux/vmalloc.h"
#include "linux/bootmem.h"
-#include "linux/module.h"
+#include "linux/mm.h"
#include "linux/pfn.h"
-#include "asm/types.h"
-#include "asm/pgtable.h"
-#include "kern_util.h"
+#include "asm/page.h"
#include "as-layout.h"
-#include "mode_kern.h"
-#include "mem.h"
+#include "init.h"
+#include "kern.h"
#include "mem_user.h"
#include "os.h"
-#include "kern.h"
-#include "init.h"
static int physmem_fd = -1;
@@ -49,10 +41,10 @@ int __init init_maps(unsigned long physmem, unsigned long iomem,
total_len = phys_len + iomem_len + highmem_len;
map = alloc_bootmem_low_pages(total_len);
- if(map == NULL)
+ if (map == NULL)
return -ENOMEM;
- for(i = 0; i < total_pages; i++){
+ for (i = 0; i < total_pages; i++) {
p = &map[i];
memset(p, 0, sizeof(struct page));
SetPageReserved(p);
@@ -68,8 +60,8 @@ static unsigned long kmem_top = 0;
unsigned long get_kmem_end(void)
{
- if(kmem_top == 0)
- kmem_top = CHOOSE_MODE(kmem_end_tt, kmem_end_skas);
+ if (kmem_top == 0)
+ kmem_top = host_task_size - 1024 * 1024;
return kmem_top;
}
@@ -81,9 +73,9 @@ void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
fd = phys_mapping(phys, &offset);
err = os_map_memory((void *) virt, fd, offset, len, r, w, x);
- if(err) {
- if(err == -ENOMEM)
- printk("try increasing the host's "
+ if (err) {
+ if (err == -ENOMEM)
+ printk(KERN_ERR "try increasing the host's "
"/proc/sys/vm/max_map_count to <physical "
"memory size>/4096\n");
panic("map_memory(0x%lx, %d, 0x%llx, %ld, %d, %d, %d) failed, "
@@ -105,13 +97,16 @@ void __init setup_physmem(unsigned long start, unsigned long reserve_end,
offset = uml_reserved - uml_physmem;
err = os_map_memory((void *) uml_reserved, physmem_fd, offset,
- len - offset, 1, 1, 0);
- if(err < 0){
- os_print_error(err, "Mapping memory");
+ len - offset, 1, 1, 1);
+ if (err < 0) {
+ printf("setup_physmem - mapping %ld bytes of memory at 0x%p "
+ "failed - errno = %d\n", len - offset,
+ (void *) uml_reserved, err);
exit(1);
}
- /* Special kludge - This page will be mapped in to userspace processes
+ /*
+ * Special kludge - This page will be mapped in to userspace processes
* from physmem_fd, so it needs to be written out there.
*/
os_seek_file(physmem_fd, __pa(&__syscall_stub_start));
@@ -122,20 +117,20 @@ void __init setup_physmem(unsigned long start, unsigned long reserve_end,
len - bootmap_size - reserve);
}
-int phys_mapping(unsigned long phys, __u64 *offset_out)
+int phys_mapping(unsigned long phys, unsigned long long *offset_out)
{
int fd = -1;
- if(phys < physmem_size){
+ if (phys < physmem_size) {
fd = physmem_fd;
*offset_out = phys;
}
- else if(phys < __pa(end_iomem)){
+ else if (phys < __pa(end_iomem)) {
struct iomem_region *region = iomem_regions;
- while(region != NULL){
- if((phys >= region->phys) &&
- (phys < region->phys + region->size)){
+ while (region != NULL) {
+ if ((phys >= region->phys) &&
+ (phys < region->phys + region->size)) {
fd = region->fd;
*offset_out = phys - region->phys;
break;
@@ -143,7 +138,7 @@ int phys_mapping(unsigned long phys, __u64 *offset_out)
region = region->next;
}
}
- else if(phys < __pa(end_iomem) + highmem){
+ else if (phys < __pa(end_iomem) + highmem) {
fd = physmem_fd;
*offset_out = phys - iomem_size;
}
@@ -188,8 +183,8 @@ unsigned long find_iomem(char *driver, unsigned long *len_out)
{
struct iomem_region *region = iomem_regions;
- while(region != NULL){
- if(!strcmp(region->driver, driver)){
+ while (region != NULL) {
+ if (!strcmp(region->driver, driver)) {
*len_out = region->size;
return region->virt;
}
@@ -206,12 +201,12 @@ int setup_iomem(void)
unsigned long iomem_start = high_physmem + PAGE_SIZE;
int err;
- while(region != NULL){
+ while (region != NULL) {
err = os_map_memory((void *) iomem_start, region->fd, 0,
region->size, 1, 1, 0);
- if(err)
- printk("Mapping iomem region for driver '%s' failed, "
- "errno = %d\n", region->driver, -err);
+ if (err)
+ printk(KERN_ERR "Mapping iomem region for driver '%s' "
+ "failed, errno = %d\n", region->driver, -err);
else {
region->virt = iomem_start;
region->phys = __pa(region->virt);
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index bfa52f206bb6..0eae00b3e588 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -1,53 +1,30 @@
/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Copyright 2003 PathScale, Inc.
* Licensed under the GPL
*/
-#include "linux/kernel.h"
-#include "linux/sched.h"
-#include "linux/interrupt.h"
-#include "linux/string.h"
+#include "linux/stddef.h"
+#include "linux/err.h"
+#include "linux/hardirq.h"
#include "linux/mm.h"
-#include "linux/slab.h"
-#include "linux/utsname.h"
-#include "linux/fs.h"
-#include "linux/utime.h"
-#include "linux/smp_lock.h"
-#include "linux/module.h"
-#include "linux/init.h"
-#include "linux/capability.h"
-#include "linux/vmalloc.h"
-#include "linux/spinlock.h"
+#include "linux/personality.h"
#include "linux/proc_fs.h"
#include "linux/ptrace.h"
#include "linux/random.h"
-#include "linux/personality.h"
-#include "asm/unistd.h"
-#include "asm/mman.h"
-#include "asm/segment.h"
-#include "asm/stat.h"
+#include "linux/sched.h"
+#include "linux/tick.h"
+#include "linux/threads.h"
#include "asm/pgtable.h"
-#include "asm/processor.h"
-#include "asm/tlbflush.h"
#include "asm/uaccess.h"
-#include "asm/user.h"
-#include "kern_util.h"
#include "as-layout.h"
-#include "kern.h"
-#include "signal_kern.h"
-#include "init.h"
-#include "irq_user.h"
-#include "mem_user.h"
-#include "tlb.h"
-#include "frame_kern.h"
-#include "sigcontext.h"
+#include "kern_util.h"
#include "os.h"
-#include "mode.h"
-#include "mode_kern.h"
-#include "choose-mode.h"
+#include "skas.h"
+#include "tlb.h"
-/* This is a per-cpu array. A processor only modifies its entry and it only
+/*
+ * This is a per-cpu array. A processor only modifies its entry and it only
* cares about its entry, so it's OK if another processor is modifying its
* entry.
*/
@@ -55,15 +32,16 @@ struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } };
static inline int external_pid(struct task_struct *task)
{
- return CHOOSE_MODE_PROC(external_pid_tt, external_pid_skas, task);
+ /* FIXME: Need to look up userspace_pid by cpu */
+ return userspace_pid[0];
}
int pid_to_processor_id(int pid)
{
int i;
- for(i = 0; i < ncpus; i++){
- if(cpu_tasks[i].pid == pid)
+ for(i = 0; i < ncpus; i++) {
+ if (cpu_tasks[i].pid == pid)
return i;
}
return -1;
@@ -82,9 +60,9 @@ unsigned long alloc_stack(int order, int atomic)
if (atomic)
flags = GFP_ATOMIC;
page = __get_free_pages(flags, order);
- if(page == 0)
+ if (page == 0)
return 0;
- stack_protections(page);
+
return page;
}
@@ -105,6 +83,8 @@ static inline void set_current(struct task_struct *task)
{ external_pid(task), task });
}
+extern void arch_switch_to(struct task_struct *from, struct task_struct *to);
+
void *_switch_to(void *prev, void *next, void *last)
{
struct task_struct *from = prev;
@@ -114,9 +94,14 @@ void *_switch_to(void *prev, void *next, void *last)
set_current(to);
do {
- current->thread.saved_task = NULL ;
- CHOOSE_MODE_PROC(switch_to_tt, switch_to_skas, prev, next);
- if(current->thread.saved_task)
+ current->thread.saved_task = NULL;
+
+ switch_threads(&from->thread.switch_buf,
+ &to->thread.switch_buf);
+
+ arch_switch_to(current->thread.prev_sched, current);
+
+ if (current->thread.saved_task)
show_regs(&(current->thread.regs));
next= current->thread.saved_task;
prev= current;
@@ -128,20 +113,14 @@ void *_switch_to(void *prev, void *next, void *last)
void interrupt_end(void)
{
- if(need_resched())
+ if (need_resched())
schedule();
- if(test_tsk_thread_flag(current, TIF_SIGPENDING))
+ if (test_tsk_thread_flag(current, TIF_SIGPENDING))
do_signal();
}
-void release_thread(struct task_struct *task)
-{
- CHOOSE_MODE(release_thread_tt(task), release_thread_skas(task));
-}
-
void exit_thread(void)
{
- unprotect_stack((unsigned long) current_thread);
}
void *get_current(void)
@@ -149,28 +128,99 @@ void *get_current(void)
return current;
}
+extern void schedule_tail(struct task_struct *prev);
+
+/*
+ * This is called magically, by its address being stuffed in a jmp_buf
+ * and being longjmp-d to.
+ */
+void new_thread_handler(void)
+{
+ int (*fn)(void *), n;
+ void *arg;
+
+ if (current->thread.prev_sched != NULL)
+ schedule_tail(current->thread.prev_sched);
+ current->thread.prev_sched = NULL;
+
+ fn = current->thread.request.u.thread.proc;
+ arg = current->thread.request.u.thread.arg;
+
+ /*
+ * The return value is 1 if the kernel thread execs a process,
+ * 0 if it just exits
+ */
+ n = run_kernel_thread(fn, arg, &current->thread.exec_buf);
+ if (n == 1) {
+ /* Handle any immediate reschedules or signals */
+ interrupt_end();
+ userspace(&current->thread.regs.regs);
+ }
+ else do_exit(0);
+}
+
+/* Called magically, see new_thread_handler above */
+void fork_handler(void)
+{
+ force_flush_all();
+ if (current->thread.prev_sched == NULL)
+ panic("blech");
+
+ schedule_tail(current->thread.prev_sched);
+
+ /*
+ * XXX: if interrupt_end() calls schedule, this call to
+ * arch_switch_to isn't needed. We could want to apply this to
+ * improve performance. -bb
+ */
+ arch_switch_to(current->thread.prev_sched, current);
+
+ current->thread.prev_sched = NULL;
+
+ /* Handle any immediate reschedules or signals */
+ interrupt_end();
+
+ userspace(&current->thread.regs.regs);
+}
+
int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
unsigned long stack_top, struct task_struct * p,
struct pt_regs *regs)
{
- int ret;
+ void (*handler)(void);
+ int ret = 0;
p->thread = (struct thread_struct) INIT_THREAD;
- ret = CHOOSE_MODE_PROC(copy_thread_tt, copy_thread_skas, nr,
- clone_flags, sp, stack_top, p, regs);
- if (ret || !current->thread.forking)
- goto out;
+ if (current->thread.forking) {
+ memcpy(&p->thread.regs.regs, &regs->regs,
+ sizeof(p->thread.regs.regs));
+ REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.gp, 0);
+ if (sp != 0)
+ REGS_SP(p->thread.regs.regs.gp) = sp;
- clear_flushed_tls(p);
+ handler = fork_handler;
- /*
- * Set a new TLS for the child thread?
- */
- if (clone_flags & CLONE_SETTLS)
- ret = arch_copy_tls(p);
+ arch_copy_thread(&current->thread.arch, &p->thread.arch);
+ }
+ else {
+ init_thread_registers(&p->thread.regs.regs);
+ p->thread.request.u.thread = current->thread.request.u.thread;
+ handler = new_thread_handler;
+ }
+
+ new_thread(task_stack_page(p), &p->thread.switch_buf, handler);
+
+ if (current->thread.forking) {
+ clear_flushed_tls(p);
+
+ /*
+ * Set a new TLS for the child thread?
+ */
+ if (clone_flags & CLONE_SETTLS)
+ ret = arch_copy_tls(p);
+ }
-out:
return ret;
}
@@ -179,39 +229,35 @@ void initial_thread_cb(void (*proc)(void *), void *arg)
int save_kmalloc_ok = kmalloc_ok;
kmalloc_ok = 0;
- CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc,
- arg);
+ initial_thread_cb_skas(proc, arg);
kmalloc_ok = save_kmalloc_ok;
}
-#ifdef CONFIG_MODE_TT
-unsigned long stack_sp(unsigned long page)
-{
- return page + PAGE_SIZE - sizeof(void *);
-}
-#endif
-
void default_idle(void)
{
- CHOOSE_MODE(uml_idle_timer(), (void) 0);
+ unsigned long long nsecs;
- while(1){
+ while(1) {
/* endless idle loop with no priority at all */
/*
* although we are an idle CPU, we do not want to
* get into the scheduler unnecessarily.
*/
- if(need_resched())
+ if (need_resched())
schedule();
- idle_sleep(10);
+ tick_nohz_stop_sched_tick();
+ nsecs = disable_timer();
+ idle_sleep(nsecs);
+ tick_nohz_restart_sched_tick();
}
}
void cpu_idle(void)
{
- CHOOSE_MODE(init_idle_tt(), init_idle_skas());
+ cpu_tasks[current_thread->cpu].pid = os_getpid();
+ default_idle();
}
void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
@@ -223,26 +269,26 @@ void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
pte_t *pte;
pte_t ptent;
- if(task->mm == NULL)
+ if (task->mm == NULL)
return ERR_PTR(-EINVAL);
pgd = pgd_offset(task->mm, addr);
- if(!pgd_present(*pgd))
+ if (!pgd_present(*pgd))
return ERR_PTR(-EINVAL);
pud = pud_offset(pgd, addr);
- if(!pud_present(*pud))
+ if (!pud_present(*pud))
return ERR_PTR(-EINVAL);
pmd = pmd_offset(pud, addr);
- if(!pmd_present(*pmd))
+ if (!pmd_present(*pmd))
return ERR_PTR(-EINVAL);
pte = pte_offset_kernel(pmd, addr);
ptent = *pte;
- if(!pte_present(ptent))
+ if (!pte_present(ptent))
return ERR_PTR(-EINVAL);
- if(pte_out != NULL)
+ if (pte_out != NULL)
*pte_out = ptent;
return (void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK);
}
@@ -315,7 +361,7 @@ int smp_sigio_handler(void)
#ifdef CONFIG_SMP
int cpu = current_thread->cpu;
IPI_handler(cpu);
- if(cpu != 0)
+ if (cpu != 0)
return 1;
#endif
return 0;
@@ -343,7 +389,8 @@ int get_using_sysemu(void)
static int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data)
{
- if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) /*No overflow*/
+ if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size)
+ /* No overflow */
*eof = 1;
return strlen(buf);
@@ -358,7 +405,8 @@ static int proc_write_sysemu(struct file *file,const char __user *buf, unsigned
if (tmp[0] >= '0' && tmp[0] <= '2')
set_using_sysemu(tmp[0] - '0');
- return count; /*We use the first char, but pretend to write everything*/
+ /* We use the first char, but pretend to write everything */
+ return count;
}
int __init make_proc_sysemu(void)
@@ -388,10 +436,10 @@ int singlestepping(void * t)
struct task_struct *task = t ? t : current;
if ( ! (task->ptrace & PT_DTRACE) )
- return(0);
+ return 0;
if (task->thread.singlestep_syscall)
- return(1);
+ return 1;
return 2;
}
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index 6916c8888dba..47b57b497d55 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -1,35 +1,27 @@
-/*
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+/*
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/sched.h"
-#include "linux/mm.h"
-#include "linux/errno.h"
-#include "linux/smp_lock.h"
-#include "linux/security.h"
-#include "linux/ptrace.h"
#include "linux/audit.h"
+#include "linux/ptrace.h"
+#include "linux/sched.h"
+#include "asm/uaccess.h"
#ifdef CONFIG_PROC_MM
-#include "linux/proc_mm.h"
+#include "proc_mm.h"
#endif
-#include "asm/ptrace.h"
-#include "asm/uaccess.h"
-#include "kern_util.h"
#include "skas_ptrace.h"
-#include "sysdep/ptrace.h"
-#include "os.h"
static inline void set_singlestepping(struct task_struct *child, int on)
{
- if (on)
- child->ptrace |= PT_DTRACE;
- else
- child->ptrace &= ~PT_DTRACE;
- child->thread.singlestep_syscall = 0;
+ if (on)
+ child->ptrace |= PT_DTRACE;
+ else
+ child->ptrace &= ~PT_DTRACE;
+ child->thread.singlestep_syscall = 0;
#ifdef SUBARCH_SET_SINGLESTEPPING
- SUBARCH_SET_SINGLESTEPPING(child, on);
+ SUBARCH_SET_SINGLESTEPPING(child, on);
#endif
}
@@ -37,8 +29,8 @@ static inline void set_singlestepping(struct task_struct *child, int on)
* Called by kernel/ptrace.c when detaching..
*/
void ptrace_disable(struct task_struct *child)
-{
- set_singlestepping(child,0);
+{
+ set_singlestepping(child,0);
}
extern int peek_user(struct task_struct * child, long addr, long data);
@@ -50,40 +42,40 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
unsigned long __user *p = (void __user *)(unsigned long)data;
switch (request) {
- /* when I and D space are separate, these will need to be fixed. */
- case PTRACE_PEEKTEXT: /* read word at location addr. */
+ /* read word at location addr. */
+ case PTRACE_PEEKTEXT:
case PTRACE_PEEKDATA:
ret = generic_ptrace_peekdata(child, addr, data);
break;
/* read the word at location addr in the USER area. */
- case PTRACE_PEEKUSR:
- ret = peek_user(child, addr, data);
- break;
+ case PTRACE_PEEKUSR:
+ ret = peek_user(child, addr, data);
+ break;
- /* when I and D space are separate, this will have to be fixed. */
- case PTRACE_POKETEXT: /* write the word at location addr. */
+ /* write the word at location addr. */
+ case PTRACE_POKETEXT:
case PTRACE_POKEDATA:
ret = generic_ptrace_pokedata(child, addr, data);
break;
- case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
- ret = poke_user(child, addr, data);
- break;
+ /* write the word at location addr in the USER area */
+ case PTRACE_POKEUSR:
+ ret = poke_user(child, addr, data);
+ break;
- case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
- case PTRACE_CONT: { /* restart after signal. */
+ /* continue and stop at next (return from) syscall */
+ case PTRACE_SYSCALL:
+ /* restart after signal. */
+ case PTRACE_CONT: {
ret = -EIO;
if (!valid_signal(data))
break;
- set_singlestepping(child, 0);
- if (request == PTRACE_SYSCALL) {
+ set_singlestepping(child, 0);
+ if (request == PTRACE_SYSCALL)
set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- }
- else {
- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- }
+ else clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
child->exit_code = data;
wake_up_process(child);
ret = 0;
@@ -91,8 +83,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
}
/*
- * make the child exit. Best I can do is send it a sigkill.
- * perhaps it should be put in the status that it wants to
+ * make the child exit. Best I can do is send it a sigkill.
+ * perhaps it should be put in the status that it wants to
* exit.
*/
case PTRACE_KILL: {
@@ -100,7 +92,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
if (child->exit_state == EXIT_ZOMBIE) /* already dead */
break;
- set_singlestepping(child, 0);
+ set_singlestepping(child, 0);
child->exit_code = SIGKILL;
wake_up_process(child);
break;
@@ -111,7 +103,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
if (!valid_signal(data))
break;
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- set_singlestepping(child, 1);
+ set_singlestepping(child, 1);
child->exit_code = data;
/* give it a chance to run. */
wake_up_process(child);
@@ -119,11 +111,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
}
- case PTRACE_DETACH:
- /* detach a process that was attached. */
- ret = ptrace_detach(child, data);
- break;
-
#ifdef PTRACE_GETREGS
case PTRACE_GETREGS: { /* Get all gp regs from the child. */
if (!access_ok(VERIFY_WRITE, p, MAX_REG_OFFSET)) {
@@ -156,22 +143,14 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
#endif
#ifdef PTRACE_GETFPREGS
case PTRACE_GETFPREGS: /* Get the child FPU state. */
- ret = get_fpregs(data, child);
+ ret = get_fpregs((struct user_i387_struct __user *) data,
+ child);
break;
#endif
#ifdef PTRACE_SETFPREGS
case PTRACE_SETFPREGS: /* Set the child FPU state. */
- ret = set_fpregs(data, child);
- break;
-#endif
-#ifdef PTRACE_GETFPXREGS
- case PTRACE_GETFPXREGS: /* Get the child FPU state. */
- ret = get_fpxregs(data, child);
- break;
-#endif
-#ifdef PTRACE_SETFPXREGS
- case PTRACE_SETFPXREGS: /* Set the child FPU state. */
- ret = set_fpxregs(data, child);
+ ret = set_fpregs((struct user_i387_struct __user *) data,
+ child);
break;
#endif
case PTRACE_GET_THREAD_AREA:
@@ -185,14 +164,13 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
case PTRACE_FAULTINFO: {
- /* Take the info from thread->arch->faultinfo,
+ /*
+ * Take the info from thread->arch->faultinfo,
* but transfer max. sizeof(struct ptrace_faultinfo).
* On i386, ptrace_faultinfo is smaller!
*/
ret = copy_to_user(p, &child->thread.arch.faultinfo,
sizeof(struct ptrace_faultinfo));
- if(ret)
- break;
break;
}
@@ -200,12 +178,13 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
case PTRACE_LDT: {
struct ptrace_ldt ldt;
- if(copy_from_user(&ldt, p, sizeof(ldt))){
+ if (copy_from_user(&ldt, p, sizeof(ldt))) {
ret = -EIO;
break;
}
- /* This one is confusing, so just punt and return -EIO for
+ /*
+ * This one is confusing, so just punt and return -EIO for
* now
*/
ret = -EIO;
@@ -217,7 +196,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
struct mm_struct *old = child->mm;
struct mm_struct *new = proc_mm_get_mm(data);
- if(IS_ERR(new)){
+ if (IS_ERR(new)) {
ret = PTR_ERR(new);
break;
}
@@ -231,20 +210,22 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
}
#endif
#ifdef PTRACE_ARCH_PRCTL
- case PTRACE_ARCH_PRCTL:
- /* XXX Calls ptrace on the host - needs some SMP thinking */
- ret = arch_prctl_skas(child, data, (void *) addr);
- break;
+ case PTRACE_ARCH_PRCTL:
+ /* XXX Calls ptrace on the host - needs some SMP thinking */
+ ret = arch_prctl(child, data, (void *) addr);
+ break;
#endif
default:
ret = ptrace_request(child, request, addr, data);
+ if (ret == -EIO)
+ ret = subarch_ptrace(child, request, addr, data);
break;
}
return ret;
}
-void send_sigtrap(struct task_struct *tsk, union uml_pt_regs *regs,
+void send_sigtrap(struct task_struct *tsk, struct uml_pt_regs *regs,
int error_code)
{
struct siginfo info;
@@ -256,14 +237,15 @@ void send_sigtrap(struct task_struct *tsk, union uml_pt_regs *regs,
/* User-mode eip? */
info.si_addr = UPT_IS_USER(regs) ? (void __user *) UPT_IP(regs) : NULL;
- /* Send us the fakey SIGTRAP */
+ /* Send us the fake SIGTRAP */
force_sig_info(SIGTRAP, &info, tsk);
}
-/* XXX Check PT_DTRACE vs TIF_SINGLESTEP for singlestepping check and
+/*
+ * XXX Check PT_DTRACE vs TIF_SINGLESTEP for singlestepping check and
* PT_PTRACED vs TIF_SYSCALL_TRACE for syscall tracing check
*/
-void syscall_trace(union uml_pt_regs *regs, int entryexit)
+void syscall_trace(struct uml_pt_regs *regs, int entryexit)
{
int is_singlestep = (current->ptrace & PT_DTRACE) && entryexit;
int tracesysgood;
@@ -277,7 +259,7 @@ void syscall_trace(union uml_pt_regs *regs, int entryexit)
UPT_SYSCALL_ARG3(regs),
UPT_SYSCALL_ARG4(regs));
else audit_syscall_exit(AUDITSC_RESULT(UPT_SYSCALL_RET(regs)),
- UPT_SYSCALL_RET(regs));
+ UPT_SYSCALL_RET(regs));
}
/* Fake a debug trap */
@@ -290,15 +272,18 @@ void syscall_trace(union uml_pt_regs *regs, int entryexit)
if (!(current->ptrace & PT_PTRACED))
return;
- /* the 0x80 provides a way for the tracing parent to distinguish
- between a syscall stop and SIGTRAP delivery */
+ /*
+ * the 0x80 provides a way for the tracing parent to distinguish
+ * between a syscall stop and SIGTRAP delivery
+ */
tracesysgood = (current->ptrace & PT_TRACESYSGOOD);
ptrace_notify(SIGTRAP | (tracesysgood ? 0x80 : 0));
if (entryexit) /* force do_signal() --> is_syscall() */
set_thread_flag(TIF_SIGPENDING);
- /* this isn't the same as continuing with a signal, but it will do
+ /*
+ * this isn't the same as continuing with a signal, but it will do
* for normal use. strace only continues with a signal if the
* stopping signal is not SIGTRAP. -brl
*/
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
index 7e4305a1fd3c..04cebcf0679f 100644
--- a/arch/um/kernel/reboot.c
+++ b/arch/um/kernel/reboot.c
@@ -1,60 +1,53 @@
/*
- * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/module.h"
#include "linux/sched.h"
-#include "asm/smp.h"
-#include "kern_util.h"
-#include "kern.h"
#include "os.h"
-#include "mode.h"
-#include "choose-mode.h"
+#include "skas.h"
void (*pm_power_off)(void);
-#ifdef CONFIG_SMP
-static void kill_idlers(int me)
-{
-#ifdef CONFIG_MODE_TT
- struct task_struct *p;
- int i;
-
- for(i = 0; i < ARRAY_SIZE(idle_threads); i++){
- p = idle_threads[i];
- if((p != NULL) && (p->thread.mode.tt.extern_pid != me))
- os_kill_process(p->thread.mode.tt.extern_pid, 0);
- }
-#endif
-}
-#endif
-
static void kill_off_processes(void)
{
- CHOOSE_MODE(kill_off_processes_tt(), kill_off_processes_skas());
-#ifdef CONFIG_SMP
- kill_idlers(os_getpid());
-#endif
+ if(proc_mm)
+ /*
+ * FIXME: need to loop over userspace_pids
+ */
+ os_kill_ptraced_process(userspace_pid[0], 1);
+ else {
+ struct task_struct *p;
+ int pid, me;
+
+ me = os_getpid();
+ for_each_process(p){
+ if(p->mm == NULL)
+ continue;
+
+ pid = p->mm->context.id.u.pid;
+ os_kill_ptraced_process(pid, 1);
+ }
+ }
}
void uml_cleanup(void)
{
- kmalloc_ok = 0;
+ kmalloc_ok = 0;
do_uml_exitcalls();
kill_off_processes();
}
void machine_restart(char * __unused)
{
- uml_cleanup();
- CHOOSE_MODE(reboot_tt(), reboot_skas());
+ uml_cleanup();
+ reboot_skas();
}
void machine_power_off(void)
{
- uml_cleanup();
- CHOOSE_MODE(halt_tt(), halt_skas());
+ uml_cleanup();
+ halt_skas();
}
void machine_halt(void)
diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c
index c4020c3d7857..19cb97733937 100644
--- a/arch/um/kernel/signal.c
+++ b/arch/um/kernel/signal.c
@@ -1,29 +1,17 @@
/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/stddef.h"
-#include "linux/sys.h"
-#include "linux/sched.h"
-#include "linux/wait.h"
-#include "linux/kernel.h"
-#include "linux/smp_lock.h"
#include "linux/module.h"
-#include "linux/slab.h"
-#include "linux/tty.h"
-#include "linux/binfmts.h"
#include "linux/ptrace.h"
+#include "linux/sched.h"
+#include "asm/siginfo.h"
#include "asm/signal.h"
-#include "asm/uaccess.h"
#include "asm/unistd.h"
-#include "asm/ucontext.h"
-#include "kern_util.h"
-#include "signal_kern.h"
-#include "kern.h"
#include "frame_kern.h"
+#include "kern_util.h"
#include "sigcontext.h"
-#include "mode.h"
EXPORT_SYMBOL(block_signals);
EXPORT_SYMBOL(unblock_signals);
@@ -46,9 +34,9 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
current_thread_info()->restart_block.fn = do_no_restart_syscall;
/* Did we come from a system call? */
- if(PT_REGS_SYSCALL_NR(regs) >= 0){
+ if (PT_REGS_SYSCALL_NR(regs) >= 0) {
/* If so, check system call restarting.. */
- switch(PT_REGS_SYSCALL_RET(regs)){
+ switch(PT_REGS_SYSCALL_RET(regs)) {
case -ERESTART_RESTARTBLOCK:
case -ERESTARTNOHAND:
PT_REGS_SYSCALL_RET(regs) = -EINTR;
@@ -68,17 +56,17 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
}
sp = PT_REGS_SP(regs);
- if((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
+ if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
sp = current->sas_ss_sp + current->sas_ss_size;
#ifdef CONFIG_ARCH_HAS_SC_SIGNALS
- if(!(ka->sa.sa_flags & SA_SIGINFO))
+ if (!(ka->sa.sa_flags & SA_SIGINFO))
err = setup_signal_stack_sc(sp, signr, ka, regs, oldset);
else
#endif
err = setup_signal_stack_si(sp, signr, ka, regs, info, oldset);
- if(err){
+ if (err) {
spin_lock_irq(&current->sighand->siglock);
current->blocked = *oldset;
recalc_sigpending();
@@ -88,7 +76,7 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked, &current->blocked,
&ka->sa.sa_mask);
- if(!(ka->sa.sa_flags & SA_NODEFER))
+ if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked, signr);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
@@ -109,14 +97,16 @@ static int kern_do_signal(struct pt_regs *regs)
else
oldset = &current->blocked;
- while((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0){
+ while ((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0) {
handled_sig = 1;
/* Whee! Actually deliver the signal. */
- if(!handle_signal(regs, sig, &ka_copy, &info, oldset)){
- /* a signal was successfully delivered; the saved
+ if (!handle_signal(regs, sig, &ka_copy, &info, oldset)) {
+ /*
+ * a signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
- * clear the TIF_RESTORE_SIGMASK flag */
+ * clear the TIF_RESTORE_SIGMASK flag
+ */
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
break;
@@ -124,9 +114,9 @@ static int kern_do_signal(struct pt_regs *regs)
}
/* Did we come from a system call? */
- if(!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)){
+ if (!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)) {
/* Restart the system call - no handlers present */
- switch(PT_REGS_SYSCALL_RET(regs)){
+ switch(PT_REGS_SYSCALL_RET(regs)) {
case -ERESTARTNOHAND:
case -ERESTARTSYS:
case -ERESTARTNOINTR:
@@ -137,22 +127,25 @@ static int kern_do_signal(struct pt_regs *regs)
PT_REGS_ORIG_SYSCALL(regs) = __NR_restart_syscall;
PT_REGS_RESTART_SYSCALL(regs);
break;
- }
+ }
}
- /* This closes a way to execute a system call on the host. If
+ /*
+ * This closes a way to execute a system call on the host. If
* you set a breakpoint on a system call instruction and singlestep
* from it, the tracing thread used to PTRACE_SINGLESTEP the process
* rather than PTRACE_SYSCALL it, allowing the system call to execute
* on the host. The tracing thread will check this flag and
* PTRACE_SYSCALL if necessary.
*/
- if(current->ptrace & PT_DTRACE)
+ if (current->ptrace & PT_DTRACE)
current->thread.singlestep_syscall =
is_syscall(PT_REGS_IP(&current->thread.regs));
- /* if there's no signal to deliver, we just put the saved sigmask
- * back */
+ /*
+ * if there's no signal to deliver, we just put the saved sigmask
+ * back
+ */
if (!handled_sig && test_thread_flag(TIF_RESTORE_SIGMASK)) {
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile
index 3e3fa7e7e3cf..0b76d8869c94 100644
--- a/arch/um/kernel/skas/Makefile
+++ b/arch/um/kernel/skas/Makefile
@@ -1,9 +1,9 @@
#
-# Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com)
+# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
# Licensed under the GPL
#
-obj-y := clone.o exec.o mem.o mmu.o process.o syscall.o tlb.o uaccess.o
+obj-y := clone.o mmu.o process.o syscall.o uaccess.o
# clone.o is in the stub, so it can't be built with profiling
# GCC hardened also auto-enables -fpic, but we need %ebx so it can't work ->
diff --git a/arch/um/kernel/skas/clone.c b/arch/um/kernel/skas/clone.c
index 47b812b3bca8..8d07a7acb909 100644
--- a/arch/um/kernel/skas/clone.c
+++ b/arch/um/kernel/skas/clone.c
@@ -3,7 +3,7 @@
#include <sys/mman.h>
#include <sys/time.h>
#include <asm/unistd.h>
-#include <asm/page.h>
+#include "as-layout.h"
#include "ptrace_user.h"
#include "skas.h"
#include "stub-data.h"
@@ -21,12 +21,11 @@
void __attribute__ ((__section__ (".__syscall_stub")))
stub_clone_handler(void)
{
- struct stub_data *data = (struct stub_data *) UML_CONFIG_STUB_DATA;
+ struct stub_data *data = (struct stub_data *) STUB_DATA;
long err;
err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD,
- UML_CONFIG_STUB_DATA + UM_KERN_PAGE_SIZE / 2 -
- sizeof(void *));
+ STUB_DATA + UM_KERN_PAGE_SIZE / 2 - sizeof(void *));
if(err != 0)
goto out;
diff --git a/arch/um/kernel/skas/exec.c b/arch/um/kernel/skas/exec.c
deleted file mode 100644
index 580eb6468949..000000000000
--- a/arch/um/kernel/skas/exec.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include "linux/kernel.h"
-#include "asm/current.h"
-#include "asm/page.h"
-#include "asm/signal.h"
-#include "asm/ptrace.h"
-#include "asm/uaccess.h"
-#include "asm/mmu_context.h"
-#include "tlb.h"
-#include "skas.h"
-#include "um_mmu.h"
-#include "os.h"
-
-void flush_thread_skas(void)
-{
- void *data = NULL;
- unsigned long end = proc_mm ? task_size : CONFIG_STUB_START;
- int ret;
-
- ret = unmap(&current->mm->context.skas.id, 0, end, 1, &data);
- if(ret){
- printk("flush_thread_skas - clearing address space failed, "
- "err = %d\n", ret);
- force_sig(SIGKILL, current);
- }
-
- switch_mm_skas(&current->mm->context.skas.id);
-}
-
-void start_thread_skas(struct pt_regs *regs, unsigned long eip,
- unsigned long esp)
-{
- set_fs(USER_DS);
- PT_REGS_IP(regs) = eip;
- PT_REGS_SP(regs) = esp;
-}
diff --git a/arch/um/kernel/skas/mem.c b/arch/um/kernel/skas/mem.c
deleted file mode 100644
index 7c18dfcd7d8e..000000000000
--- a/arch/um/kernel/skas/mem.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include "linux/mm.h"
-#include "asm/pgtable.h"
-#include "mem_user.h"
-#include "skas.h"
-
-unsigned long set_task_sizes_skas(unsigned long *task_size_out)
-{
- /* Round up to the nearest 4M */
- unsigned long host_task_size = ROUND_4M((unsigned long)
- &host_task_size);
-
- if (!skas_needs_stub)
- *task_size_out = host_task_size;
- else *task_size_out = CONFIG_STUB_START & PGDIR_MASK;
-
- return host_task_size;
-}
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index 2c6d090a2e87..f859ec306cd5 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -1,20 +1,13 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+/*
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/sched.h"
-#include "linux/list.h"
-#include "linux/spinlock.h"
-#include "linux/slab.h"
-#include "linux/errno.h"
#include "linux/mm.h"
-#include "asm/current.h"
-#include "asm/segment.h"
-#include "asm/mmu.h"
+#include "linux/sched.h"
#include "asm/pgalloc.h"
#include "asm/pgtable.h"
-#include "asm/ldt.h"
+#include "as-layout.h"
#include "os.h"
#include "skas.h"
@@ -41,10 +34,11 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc,
if (!pte)
goto out_pte;
- /* There's an interaction between the skas0 stub pages, stack
+ /*
+ * There's an interaction between the skas0 stub pages, stack
* randomization, and the BUG at the end of exit_mmap. exit_mmap
- * checks that the number of page tables freed is the same as had
- * been allocated. If the stack is on the last page table page,
+ * checks that the number of page tables freed is the same as had
+ * been allocated. If the stack is on the last page table page,
* then the stack pte page will be freed, and if not, it won't. To
* avoid having to know where the stack is, or if the process mapped
* something at the top of its address space for some other reason,
@@ -54,76 +48,77 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc,
* destroy_context_skas.
*/
- mm->context.skas.last_page_table = pmd_page_vaddr(*pmd);
+ mm->context.last_page_table = pmd_page_vaddr(*pmd);
#ifdef CONFIG_3_LEVEL_PGTABLES
- mm->context.skas.last_pmd = (unsigned long) __va(pud_val(*pud));
+ mm->context.last_pmd = (unsigned long) __va(pud_val(*pud));
#endif
*pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT));
*pte = pte_mkread(*pte);
- return(0);
+ return 0;
out_pmd:
pud_free(pud);
out_pte:
pmd_free(pmd);
out:
- return(-ENOMEM);
+ return -ENOMEM;
}
-int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
+int init_new_context(struct task_struct *task, struct mm_struct *mm)
{
- struct mmu_context_skas *from_mm = NULL;
- struct mmu_context_skas *to_mm = &mm->context.skas;
+ struct mm_context *from_mm = NULL;
+ struct mm_context *to_mm = &mm->context;
unsigned long stack = 0;
int ret = -ENOMEM;
- if(skas_needs_stub){
+ if (skas_needs_stub) {
stack = get_zeroed_page(GFP_KERNEL);
- if(stack == 0)
+ if (stack == 0)
goto out;
- /* This zeros the entry that pgd_alloc didn't, needed since
+ /*
+ * This zeros the entry that pgd_alloc didn't, needed since
* we are about to reinitialize it, and want mm.nr_ptes to
* be accurate.
*/
mm->pgd[USER_PTRS_PER_PGD] = __pgd(0);
- ret = init_stub_pte(mm, CONFIG_STUB_CODE,
+ ret = init_stub_pte(mm, STUB_CODE,
(unsigned long) &__syscall_stub_start);
- if(ret)
+ if (ret)
goto out_free;
- ret = init_stub_pte(mm, CONFIG_STUB_DATA, stack);
- if(ret)
+ ret = init_stub_pte(mm, STUB_DATA, stack);
+ if (ret)
goto out_free;
mm->nr_ptes--;
}
to_mm->id.stack = stack;
- if(current->mm != NULL && current->mm != &init_mm)
- from_mm = &current->mm->context.skas;
+ if (current->mm != NULL && current->mm != &init_mm)
+ from_mm = &current->mm->context;
- if(proc_mm){
+ if (proc_mm) {
ret = new_mm(stack);
- if(ret < 0){
- printk("init_new_context_skas - new_mm failed, "
- "errno = %d\n", ret);
+ if (ret < 0) {
+ printk(KERN_ERR "init_new_context_skas - "
+ "new_mm failed, errno = %d\n", ret);
goto out_free;
}
to_mm->id.u.mm_fd = ret;
}
else {
- if(from_mm)
+ if (from_mm)
to_mm->id.u.pid = copy_context_skas0(stack,
from_mm->id.u.pid);
else to_mm->id.u.pid = start_userspace(stack);
}
ret = init_new_ldt(to_mm, from_mm);
- if(ret < 0){
- printk("init_new_context_skas - init_ldt"
+ if (ret < 0) {
+ printk(KERN_ERR "init_new_context_skas - init_ldt"
" failed, errno = %d\n", ret);
goto out_free;
}
@@ -131,22 +126,22 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
return 0;
out_free:
- if(to_mm->id.stack != 0)
+ if (to_mm->id.stack != 0)
free_page(to_mm->id.stack);
out:
return ret;
}
-void destroy_context_skas(struct mm_struct *mm)
+void destroy_context(struct mm_struct *mm)
{
- struct mmu_context_skas *mmu = &mm->context.skas;
+ struct mm_context *mmu = &mm->context;
- if(proc_mm)
+ if (proc_mm)
os_close_file(mmu->id.u.mm_fd);
else
os_kill_ptraced_process(mmu->id.u.pid, 1);
- if(!proc_mm || !ptrace_faultinfo){
+ if (!proc_mm || !ptrace_faultinfo) {
free_page(mmu->id.stack);
pte_lock_deinit(virt_to_page(mmu->last_page_table));
pte_free_kernel((pte_t *) mmu->last_page_table);
@@ -155,4 +150,6 @@ void destroy_context_skas(struct mm_struct *mm)
pmd_free((pmd_t *) mmu->last_pmd);
#endif
}
+
+ free_ldt(mmu);
}
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index 48051a98525f..fce389c2342f 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -1,146 +1,26 @@
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/sched.h"
-#include "linux/slab.h"
-#include "linux/ptrace.h"
-#include "linux/proc_fs.h"
-#include "linux/file.h"
-#include "linux/errno.h"
#include "linux/init.h"
-#include "asm/uaccess.h"
-#include "asm/atomic.h"
-#include "kern_util.h"
+#include "linux/sched.h"
#include "as-layout.h"
-#include "skas.h"
#include "os.h"
-#include "tlb.h"
-#include "kern.h"
-#include "mode.h"
-#include "registers.h"
-
-void switch_to_skas(void *prev, void *next)
-{
- struct task_struct *from, *to;
-
- from = prev;
- to = next;
-
- /* XXX need to check runqueues[cpu].idle */
- if(current->pid == 0)
- switch_timers(0);
-
- switch_threads(&from->thread.mode.skas.switch_buf,
- &to->thread.mode.skas.switch_buf);
-
- arch_switch_to_skas(current->thread.prev_sched, current);
-
- if(current->pid == 0)
- switch_timers(1);
-}
-
-extern void schedule_tail(struct task_struct *prev);
-
-/* This is called magically, by its address being stuffed in a jmp_buf
- * and being longjmp-d to.
- */
-void new_thread_handler(void)
-{
- int (*fn)(void *), n;
- void *arg;
-
- if(current->thread.prev_sched != NULL)
- schedule_tail(current->thread.prev_sched);
- current->thread.prev_sched = NULL;
-
- fn = current->thread.request.u.thread.proc;
- arg = current->thread.request.u.thread.arg;
-
- /* The return value is 1 if the kernel thread execs a process,
- * 0 if it just exits
- */
- n = run_kernel_thread(fn, arg, &current->thread.exec_buf);
- if(n == 1){
- /* Handle any immediate reschedules or signals */
- interrupt_end();
- userspace(&current->thread.regs.regs);
- }
- else do_exit(0);
-}
-
-void release_thread_skas(struct task_struct *task)
-{
-}
-
-/* Called magically, see new_thread_handler above */
-void fork_handler(void)
-{
- force_flush_all();
- if(current->thread.prev_sched == NULL)
- panic("blech");
-
- schedule_tail(current->thread.prev_sched);
-
- /* XXX: if interrupt_end() calls schedule, this call to
- * arch_switch_to_skas isn't needed. We could want to apply this to
- * improve performance. -bb */
- arch_switch_to_skas(current->thread.prev_sched, current);
-
- current->thread.prev_sched = NULL;
-
-/* Handle any immediate reschedules or signals */
- interrupt_end();
-
- userspace(&current->thread.regs.regs);
-}
-
-int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
- unsigned long stack_top, struct task_struct * p,
- struct pt_regs *regs)
-{
- void (*handler)(void);
-
- if(current->thread.forking){
- memcpy(&p->thread.regs.regs.skas, &regs->regs.skas,
- sizeof(p->thread.regs.regs.skas));
- REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0);
- if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp;
-
- handler = fork_handler;
-
- arch_copy_thread(&current->thread.arch, &p->thread.arch);
- }
- else {
- init_thread_registers(&p->thread.regs.regs);
- p->thread.request.u.thread = current->thread.request.u.thread;
- handler = new_thread_handler;
- }
-
- new_thread(task_stack_page(p), &p->thread.mode.skas.switch_buf,
- handler);
- return(0);
-}
+#include "skas.h"
int new_mm(unsigned long stack)
{
int fd;
fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0);
- if(fd < 0)
- return(fd);
+ if (fd < 0)
+ return fd;
- if(skas_needs_stub)
- map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack);
+ if (skas_needs_stub)
+ map_stub_pages(fd, STUB_CODE, STUB_DATA, stack);
- return(fd);
-}
-
-void init_idle_skas(void)
-{
- cpu_tasks[current_thread->cpu].pid = os_getpid();
- default_idle();
+ return fd;
}
extern void start_kernel(void);
@@ -158,67 +38,32 @@ static int __init start_kernel_proc(void *unused)
cpu_online_map = cpumask_of_cpu(0);
#endif
start_kernel();
- return(0);
+ return 0;
}
extern int userspace_pid[];
extern char cpu0_irqstack[];
-int __init start_uml_skas(void)
+int __init start_uml(void)
{
stack_protections((unsigned long) &cpu0_irqstack);
set_sigstack(cpu0_irqstack, THREAD_SIZE);
- if(proc_mm)
+ if (proc_mm)
userspace_pid[0] = start_userspace(0);
init_new_thread_signals();
init_task.thread.request.u.thread.proc = start_kernel_proc;
init_task.thread.request.u.thread.arg = NULL;
- return(start_idle_thread(task_stack_page(&init_task),
- &init_task.thread.mode.skas.switch_buf));
-}
-
-int external_pid_skas(struct task_struct *task)
-{
- /* FIXME: Need to look up userspace_pid by cpu */
- return(userspace_pid[0]);
-}
-
-int thread_pid_skas(struct task_struct *task)
-{
- /* FIXME: Need to look up userspace_pid by cpu */
- return(userspace_pid[0]);
-}
-
-void kill_off_processes_skas(void)
-{
- if(proc_mm)
- /*
- * FIXME: need to loop over userspace_pids in
- * kill_off_processes_skas
- */
- os_kill_ptraced_process(userspace_pid[0], 1);
- else {
- struct task_struct *p;
- int pid, me;
-
- me = os_getpid();
- for_each_process(p){
- if(p->mm == NULL)
- continue;
-
- pid = p->mm->context.skas.id.u.pid;
- os_kill_ptraced_process(pid, 1);
- }
- }
+ return start_idle_thread(task_stack_page(&init_task),
+ &init_task.thread.switch_buf);
}
unsigned long current_stub_stack(void)
{
- if(current->mm == NULL)
- return(0);
+ if (current->mm == NULL)
+ return 0;
- return(current->mm->context.skas.id.stack);
+ return current->mm->context.id.stack;
}
diff --git a/arch/um/kernel/skas/syscall.c b/arch/um/kernel/skas/syscall.c
index 0ae4eea21be4..50b476f2b38d 100644
--- a/arch/um/kernel/skas/syscall.c
+++ b/arch/um/kernel/skas/syscall.c
@@ -1,19 +1,15 @@
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/sys.h"
+#include "linux/kernel.h"
#include "linux/ptrace.h"
-#include "asm/errno.h"
-#include "asm/unistd.h"
-#include "asm/ptrace.h"
-#include "asm/current.h"
-#include "sysdep/syscalls.h"
#include "kern_util.h"
-#include "syscall.h"
+#include "sysdep/ptrace.h"
+#include "sysdep/syscalls.h"
-void handle_syscall(union uml_pt_regs *r)
+void handle_syscall(struct uml_pt_regs *r)
{
struct pt_regs *regs = container_of(r, struct pt_regs, regs);
long result;
@@ -24,7 +20,8 @@ void handle_syscall(union uml_pt_regs *r)
current->thread.nsyscalls++;
nsyscalls++;
- /* This should go in the declaration of syscall, but when I do that,
+ /*
+ * This should go in the declaration of syscall, but when I do that,
* strace -f -c bash -c 'ls ; ls' breaks, sometimes not tracing
* children at all, sometimes hanging when bash doesn't see the first
* ls exit.
@@ -33,11 +30,11 @@ void handle_syscall(union uml_pt_regs *r)
* in case it's a compiler bug.
*/
syscall = UPT_SYSCALL_NR(r);
- if((syscall >= NR_syscalls) || (syscall < 0))
+ if ((syscall >= NR_syscalls) || (syscall < 0))
result = -ENOSYS;
else result = EXECUTE_SYSCALL(syscall, regs);
- REGS_SET_SYSCALL_RETURN(r->skas.regs, result);
+ REGS_SET_SYSCALL_RETURN(r->gp, result);
syscall_trace(r, 1);
}
diff --git a/arch/um/kernel/skas/tlb.c b/arch/um/kernel/skas/tlb.c
deleted file mode 100644
index c0f0693743ba..000000000000
--- a/arch/um/kernel/skas/tlb.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Copyright 2003 PathScale, Inc.
- * Licensed under the GPL
- */
-
-#include "linux/stddef.h"
-#include "linux/sched.h"
-#include "linux/mm.h"
-#include "asm/page.h"
-#include "asm/pgtable.h"
-#include "asm/mmu.h"
-#include "mem_user.h"
-#include "mem.h"
-#include "skas.h"
-#include "os.h"
-#include "tlb.h"
-
-static int do_ops(union mm_context *mmu, struct host_vm_op *ops, int last,
- int finished, void **flush)
-{
- struct host_vm_op *op;
- int i, ret = 0;
-
- for(i = 0; i <= last && !ret; i++){
- op = &ops[i];
- switch(op->type){
- case MMAP:
- ret = map(&mmu->skas.id, op->u.mmap.addr,
- op->u.mmap.len, op->u.mmap.prot,
- op->u.mmap.fd, op->u.mmap.offset, finished,
- flush);
- break;
- case MUNMAP:
- ret = unmap(&mmu->skas.id, op->u.munmap.addr,
- op->u.munmap.len, finished, flush);
- break;
- case MPROTECT:
- ret = protect(&mmu->skas.id, op->u.mprotect.addr,
- op->u.mprotect.len, op->u.mprotect.prot,
- finished, flush);
- break;
- default:
- printk("Unknown op type %d in do_ops\n", op->type);
- break;
- }
- }
-
- return ret;
-}
-
-extern int proc_mm;
-
-static void fix_range(struct mm_struct *mm, unsigned long start_addr,
- unsigned long end_addr, int force)
-{
- if(!proc_mm && (end_addr > CONFIG_STUB_START))
- end_addr = CONFIG_STUB_START;
-
- fix_range_common(mm, start_addr, end_addr, force, do_ops);
-}
-
-void __flush_tlb_one_skas(unsigned long addr)
-{
- flush_tlb_kernel_range_common(addr, addr + PAGE_SIZE);
-}
-
-void flush_tlb_range_skas(struct vm_area_struct *vma, unsigned long start,
- unsigned long end)
-{
- if(vma->vm_mm == NULL)
- flush_tlb_kernel_range_common(start, end);
- else fix_range(vma->vm_mm, start, end, 0);
-}
-
-void flush_tlb_mm_skas(struct mm_struct *mm)
-{
- unsigned long end;
-
- /* Don't bother flushing if this address space is about to be
- * destroyed.
- */
- if(atomic_read(&mm->mm_users) == 0)
- return;
-
- end = proc_mm ? task_size : CONFIG_STUB_START;
- fix_range(mm, 0, end, 0);
-}
-
-void force_flush_all_skas(void)
-{
- struct mm_struct *mm = current->mm;
- struct vm_area_struct *vma = mm->mmap;
-
- while(vma != NULL) {
- fix_range(mm, vma->vm_start, vma->vm_end, 1);
- vma = vma->vm_next;
- }
-}
-
-void flush_tlb_page_skas(struct vm_area_struct *vma, unsigned long address)
-{
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte;
- struct mm_struct *mm = vma->vm_mm;
- void *flush = NULL;
- int r, w, x, prot, err = 0;
- struct mm_id *mm_id;
-
- pgd = pgd_offset(mm, address);
- if(!pgd_present(*pgd))
- goto kill;
-
- pud = pud_offset(pgd, address);
- if(!pud_present(*pud))
- goto kill;
-
- pmd = pmd_offset(pud, address);
- if(!pmd_present(*pmd))
- goto kill;
-
- pte = pte_offset_kernel(pmd, address);
-
- r = pte_read(*pte);
- w = pte_write(*pte);
- x = pte_exec(*pte);
- if (!pte_young(*pte)) {
- r = 0;
- w = 0;
- } else if (!pte_dirty(*pte)) {
- w = 0;
- }
-
- mm_id = &mm->context.skas.id;
- prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) |
- (x ? UM_PROT_EXEC : 0));
- if(pte_newpage(*pte)){
- if(pte_present(*pte)){
- unsigned long long offset;
- int fd;
-
- fd = phys_mapping(pte_val(*pte) & PAGE_MASK, &offset);
- err = map(mm_id, address, PAGE_SIZE, prot, fd, offset,
- 1, &flush);
- }
- else err = unmap(mm_id, address, PAGE_SIZE, 1, &flush);
- }
- else if(pte_newprot(*pte))
- err = protect(mm_id, address, PAGE_SIZE, prot, 1, &flush);
-
- if(err)
- goto kill;
-
- *pte = pte_mkuptodate(*pte);
-
- return;
-
-kill:
- printk("Failed to flush page for address 0x%lx\n", address);
- force_sig(SIGKILL, current);
-}
-
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c
index 8912cec0fe43..1d8b119f2d0e 100644
--- a/arch/um/kernel/skas/uaccess.c
+++ b/arch/um/kernel/skas/uaccess.c
@@ -1,18 +1,14 @@
/*
- * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/compiler.h"
-#include "linux/stddef.h"
-#include "linux/kernel.h"
-#include "linux/string.h"
-#include "linux/fs.h"
-#include "linux/hardirq.h"
+#include "linux/err.h"
#include "linux/highmem.h"
+#include "linux/mm.h"
+#include "asm/current.h"
#include "asm/page.h"
#include "asm/pgtable.h"
-#include "asm/uaccess.h"
#include "kern_util.h"
#include "os.h"
@@ -27,16 +23,16 @@ static unsigned long maybe_map(unsigned long virt, int is_write)
void *phys = um_virt_to_phys(current, virt, &pte);
int dummy_code;
- if(IS_ERR(phys) || (is_write && !pte_write(pte))){
+ if (IS_ERR(phys) || (is_write && !pte_write(pte))) {
err = handle_page_fault(virt, 0, is_write, 1, &dummy_code);
- if(err)
- return(-1UL);
+ if (err)
+ return -1UL;
phys = um_virt_to_phys(current, virt, NULL);
}
- if(IS_ERR(phys))
- phys = (void *) -1;
+ if (IS_ERR(phys))
+ phys = (void *) -1;
- return((unsigned long) phys);
+ return (unsigned long) phys;
}
static int do_op_one_page(unsigned long addr, int len, int is_write,
@@ -46,17 +42,18 @@ static int do_op_one_page(unsigned long addr, int len, int is_write,
int n;
addr = maybe_map(addr, is_write);
- if(addr == -1UL)
- return(-1);
+ if (addr == -1UL)
+ return -1;
page = phys_to_page(addr);
- addr = (unsigned long) kmap_atomic(page, KM_UML_USERCOPY) + (addr & ~PAGE_MASK);
+ addr = (unsigned long) kmap_atomic(page, KM_UML_USERCOPY) +
+ (addr & ~PAGE_MASK);
n = (*op)(addr, len, arg);
kunmap_atomic(page, KM_UML_USERCOPY);
- return(n);
+ return n;
}
static void do_buffer_op(void *jmpbuf, void *arg_ptr)
@@ -81,21 +78,21 @@ static void do_buffer_op(void *jmpbuf, void *arg_ptr)
current->thread.fault_catcher = jmpbuf;
n = do_op_one_page(addr, size, is_write, op, arg);
- if(n != 0){
+ if (n != 0) {
*res = (n < 0 ? remain : 0);
goto out;
}
addr += size;
remain -= size;
- if(remain == 0){
+ if (remain == 0) {
*res = 0;
goto out;
}
- while(addr < ((addr + remain) & PAGE_MASK)){
+ while(addr < ((addr + remain) & PAGE_MASK)) {
n = do_op_one_page(addr, PAGE_SIZE, is_write, op, arg);
- if(n != 0){
+ if (n != 0) {
*res = (n < 0 ? remain : 0);
goto out;
}
@@ -103,13 +100,13 @@ static void do_buffer_op(void *jmpbuf, void *arg_ptr)
addr += PAGE_SIZE;
remain -= PAGE_SIZE;
}
- if(remain == 0){
+ if (remain == 0) {
*res = 0;
goto out;
}
n = do_op_one_page(addr, remain, is_write, op, arg);
- if(n != 0)
+ if (n != 0)
*res = (n < 0 ? remain : 0);
else *res = 0;
out:
@@ -124,10 +121,10 @@ static int buffer_op(unsigned long addr, int len, int is_write,
faulted = setjmp_wrapper(do_buffer_op, addr, len, is_write, op, arg,
&res);
- if(!faulted)
- return(res);
+ if (!faulted)
+ return res;
- return(addr + len - (unsigned long) current->thread.fault_addr);
+ return addr + len - (unsigned long) current->thread.fault_addr;
}
static int copy_chunk_from_user(unsigned long from, int len, void *arg)
@@ -136,19 +133,19 @@ static int copy_chunk_from_user(unsigned long from, int len, void *arg)
memcpy((void *) to, (void *) from, len);
*to_ptr += len;
- return(0);
+ return 0;
}
-int copy_from_user_skas(void *to, const void __user *from, int n)
+int copy_from_user(void *to, const void __user *from, int n)
{
- if(segment_eq(get_fs(), KERNEL_DS)){
+ if (segment_eq(get_fs(), KERNEL_DS)) {
memcpy(to, (__force void*)from, n);
- return(0);
+ return 0;
}
- return(access_ok(VERIFY_READ, from, n) ?
+ return access_ok(VERIFY_READ, from, n) ?
buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to):
- n);
+ n;
}
static int copy_chunk_to_user(unsigned long to, int len, void *arg)
@@ -157,19 +154,19 @@ static int copy_chunk_to_user(unsigned long to, int len, void *arg)
memcpy((void *) to, (void *) from, len);
*from_ptr += len;
- return(0);
+ return 0;
}
-int copy_to_user_skas(void __user *to, const void *from, int n)
+int copy_to_user(void __user *to, const void *from, int n)
{
- if(segment_eq(get_fs(), KERNEL_DS)){
- memcpy((__force void*)to, from, n);
- return(0);
+ if (segment_eq(get_fs(), KERNEL_DS)) {
+ memcpy((__force void *) to, from, n);
+ return 0;
}
- return(access_ok(VERIFY_WRITE, to, n) ?
+ return access_ok(VERIFY_WRITE, to, n) ?
buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) :
- n);
+ n;
}
static int strncpy_chunk_from_user(unsigned long from, int len, void *arg)
@@ -181,51 +178,51 @@ static int strncpy_chunk_from_user(unsigned long from, int len, void *arg)
n = strnlen(to, len);
*to_ptr += n;
- if(n < len)
- return(1);
- return(0);
+ if (n < len)
+ return 1;
+ return 0;
}
-int strncpy_from_user_skas(char *dst, const char __user *src, int count)
+int strncpy_from_user(char *dst, const char __user *src, int count)
{
int n;
char *ptr = dst;
- if(segment_eq(get_fs(), KERNEL_DS)){
- strncpy(dst, (__force void*)src, count);
- return(strnlen(dst, count));
+ if (segment_eq(get_fs(), KERNEL_DS)) {
+ strncpy(dst, (__force void *) src, count);
+ return strnlen(dst, count);
}
- if(!access_ok(VERIFY_READ, src, 1))
- return(-EFAULT);
+ if (!access_ok(VERIFY_READ, src, 1))
+ return -EFAULT;
n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user,
&ptr);
- if(n != 0)
- return(-EFAULT);
- return(strnlen(dst, count));
+ if (n != 0)
+ return -EFAULT;
+ return strnlen(dst, count);
}
static int clear_chunk(unsigned long addr, int len, void *unused)
{
memset((void *) addr, 0, len);
- return(0);
+ return 0;
}
-int __clear_user_skas(void __user *mem, int len)
+int __clear_user(void __user *mem, int len)
{
- return(buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL));
+ return buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL);
}
-int clear_user_skas(void __user *mem, int len)
+int clear_user(void __user *mem, int len)
{
- if(segment_eq(get_fs(), KERNEL_DS)){
+ if (segment_eq(get_fs(), KERNEL_DS)) {
memset((__force void*)mem, 0, len);
- return(0);
+ return 0;
}
- return(access_ok(VERIFY_WRITE, mem, len) ?
- buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len);
+ return access_ok(VERIFY_WRITE, mem, len) ?
+ buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len;
}
static int strnlen_chunk(unsigned long str, int len, void *arg)
@@ -235,31 +232,20 @@ static int strnlen_chunk(unsigned long str, int len, void *arg)
n = strnlen((void *) str, len);
*len_ptr += n;
- if(n < len)
- return(1);
- return(0);
+ if (n < len)
+ return 1;
+ return 0;
}
-int strnlen_user_skas(const void __user *str, int len)
+int strnlen_user(const void __user *str, int len)
{
int count = 0, n;
- if(segment_eq(get_fs(), KERNEL_DS))
- return(strnlen((__force char*)str, len) + 1);
+ if (segment_eq(get_fs(), KERNEL_DS))
+ return strnlen((__force char*)str, len) + 1;
n = buffer_op((unsigned long) str, len, 0, strnlen_chunk, &count);
- if(n == 0)
- return(count + 1);
- return(-EFAULT);
+ if (n == 0)
+ return count + 1;
+ return -EFAULT;
}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c
index e6a7778006ad..36d89cf8d20b 100644
--- a/arch/um/kernel/smp.c
+++ b/arch/um/kernel/smp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -56,12 +56,12 @@ void smp_send_stop(void)
int i;
printk(KERN_INFO "Stopping all CPUs...");
- for(i = 0; i < num_online_cpus(); i++){
- if(i == current_thread->cpu)
+ for (i = 0; i < num_online_cpus(); i++) {
+ if (i == current_thread->cpu)
continue;
os_write_file(cpu_data[i].ipi_pipe[1], "S", 1);
}
- printk("done\n");
+ printk(KERN_INFO "done\n");
}
static cpumask_t smp_commenced_mask = CPU_MASK_NONE;
@@ -72,7 +72,7 @@ static int idle_proc(void *cpup)
int cpu = (int) cpup, err;
err = os_pipe(cpu_data[cpu].ipi_pipe, 1, 1);
- if(err < 0)
+ if (err < 0)
panic("CPU#%d failed to create IPI pipe, err = %d", cpu, -err);
os_set_fd_async(cpu_data[cpu].ipi_pipe[0],
@@ -80,7 +80,7 @@ static int idle_proc(void *cpup)
wmb();
if (cpu_test_and_set(cpu, cpu_callin_map)) {
- printk("huh, CPU#%d already present??\n", cpu);
+ printk(KERN_ERR "huh, CPU#%d already present??\n", cpu);
BUG();
}
@@ -95,12 +95,11 @@ static int idle_proc(void *cpup)
static struct task_struct *idle_thread(int cpu)
{
struct task_struct *new_task;
- unsigned char c;
current->thread.request.u.thread.proc = idle_proc;
current->thread.request.u.thread.arg = (void *) cpu;
new_task = fork_idle(cpu);
- if(IS_ERR(new_task))
+ if (IS_ERR(new_task))
panic("copy_process failed in idle_thread, error = %ld",
PTR_ERR(new_task));
@@ -108,9 +107,7 @@ static struct task_struct *idle_thread(int cpu)
{ .pid = new_task->thread.mode.tt.extern_pid,
.task = new_task } );
idle_threads[cpu] = new_task;
- CHOOSE_MODE(os_write_file(new_task->thread.mode.tt.switch_pipe[1], &c,
- sizeof(c)),
- ({ panic("skas mode doesn't support SMP"); }));
+ panic("skas mode doesn't support SMP");
return new_task;
}
@@ -129,14 +126,14 @@ void smp_prepare_cpus(unsigned int maxcpus)
cpu_set(me, cpu_callin_map);
err = os_pipe(cpu_data[me].ipi_pipe, 1, 1);
- if(err < 0)
+ if (err < 0)
panic("CPU#0 failed to create IPI pipe, errno = %d", -err);
os_set_fd_async(cpu_data[me].ipi_pipe[0],
current->thread.mode.tt.extern_pid);
- for(cpu = 1; cpu < ncpus; cpu++){
- printk("Booting processor %d...\n", cpu);
+ for (cpu = 1; cpu < ncpus; cpu++) {
+ printk(KERN_INFO "Booting processor %d...\n", cpu);
idle = idle_thread(cpu);
@@ -147,8 +144,8 @@ void smp_prepare_cpus(unsigned int maxcpus)
cpu_relax();
if (cpu_isset(cpu, cpu_callin_map))
- printk("done\n");
- else printk("failed\n");
+ printk(KERN_INFO "done\n");
+ else printk(KERN_INFO "failed\n");
}
}
@@ -190,13 +187,14 @@ void IPI_handler(int cpu)
break;
case 'S':
- printk("CPU#%d stopping\n", cpu);
- while(1)
+ printk(KERN_INFO "CPU#%d stopping\n", cpu);
+ while (1)
pause();
break;
default:
- printk("CPU#%d received unknown IPI [%c]!\n", cpu, c);
+ printk(KERN_ERR "CPU#%d received unknown IPI [%c]!\n",
+ cpu, c);
break;
}
}
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c
index 7b3b67333ff3..b9d92b2089ae 100644
--- a/arch/um/kernel/syscall.c
+++ b/arch/um/kernel/syscall.c
@@ -1,27 +1,17 @@
/*
- * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/sched.h"
#include "linux/file.h"
-#include "linux/smp_lock.h"
-#include "linux/mm.h"
#include "linux/fs.h"
+#include "linux/mm.h"
+#include "linux/sched.h"
#include "linux/utsname.h"
-#include "linux/msg.h"
-#include "linux/shm.h"
-#include "linux/sys.h"
-#include "linux/syscalls.h"
-#include "linux/unistd.h"
-#include "linux/slab.h"
-#include "linux/utime.h"
+#include "asm/current.h"
#include "asm/mman.h"
#include "asm/uaccess.h"
-#include "kern_util.h"
-#include "sysdep/syscalls.h"
-#include "mode_kern.h"
-#include "choose-mode.h"
+#include "asm/unistd.h"
/* Unlocked, I don't care if this is a bit off */
int nsyscalls = 0;
@@ -34,7 +24,7 @@ long sys_fork(void)
ret = do_fork(SIGCHLD, UPT_SP(&current->thread.regs.regs),
&current->thread.regs, 0, NULL, NULL);
current->thread.forking = 0;
- return(ret);
+ return ret;
}
long sys_vfork(void)
@@ -46,7 +36,7 @@ long sys_vfork(void)
UPT_SP(&current->thread.regs.regs),
&current->thread.regs, 0, NULL, NULL);
current->thread.forking = 0;
- return(ret);
+ return ret;
}
/* common code for old and new mmaps */
@@ -92,15 +82,15 @@ long old_mmap(unsigned long addr, unsigned long len,
*/
long sys_pipe(unsigned long __user * fildes)
{
- int fd[2];
- long error;
+ int fd[2];
+ long error;
- error = do_pipe(fd);
- if (!error) {
+ error = do_pipe(fd);
+ if (!error) {
if (copy_to_user(fildes, fd, sizeof(fd)))
- error = -EFAULT;
- }
- return error;
+ error = -EFAULT;
+ }
+ return error;
}
@@ -124,7 +114,7 @@ long sys_olduname(struct oldold_utsname __user * name)
if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
return -EFAULT;
- down_read(&uts_sem);
+ down_read(&uts_sem);
error = __copy_to_user(&name->sysname, &utsname()->sysname,
__OLD_UTS_LEN);
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index 259c49da7ff5..1ac746a9eae1 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -1,189 +1,126 @@
/*
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/kernel.h"
-#include "linux/module.h"
-#include "linux/unistd.h"
-#include "linux/stddef.h"
-#include "linux/spinlock.h"
-#include "linux/time.h"
-#include "linux/sched.h"
+#include "linux/clockchips.h"
#include "linux/interrupt.h"
-#include "linux/init.h"
-#include "linux/delay.h"
-#include "linux/hrtimer.h"
+#include "linux/jiffies.h"
+#include "linux/threads.h"
#include "asm/irq.h"
#include "asm/param.h"
-#include "asm/current.h"
#include "kern_util.h"
-#include "mode.h"
#include "os.h"
-int hz(void)
-{
- return(HZ);
-}
-
/*
* Scheduler clock - returns current time in nanosec units.
*/
unsigned long long sched_clock(void)
{
- return (unsigned long long)jiffies_64 * (1000000000 / HZ);
+ return (unsigned long long)jiffies_64 * (NSEC_PER_SEC / HZ);
}
-#ifdef CONFIG_UML_REAL_TIME_CLOCK
-static unsigned long long prev_nsecs[NR_CPUS];
-static long long delta[NR_CPUS]; /* Deviation per interval */
-#endif
+void timer_handler(int sig, struct uml_pt_regs *regs)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ do_IRQ(TIMER_IRQ, regs);
+ local_irq_restore(flags);
+}
-void timer_irq(union uml_pt_regs *regs)
+static void itimer_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
{
- unsigned long long ticks = 0;
-#ifdef CONFIG_UML_REAL_TIME_CLOCK
- int c = cpu();
- if(prev_nsecs[c]){
- /* We've had 1 tick */
- unsigned long long nsecs = os_nsecs();
-
- delta[c] += nsecs - prev_nsecs[c];
- prev_nsecs[c] = nsecs;
-
- /* Protect against the host clock being set backwards */
- if(delta[c] < 0)
- delta[c] = 0;
-
- ticks += (delta[c] * HZ) / BILLION;
- delta[c] -= (ticks * BILLION) / HZ;
- }
- else prev_nsecs[c] = os_nsecs();
-#else
- ticks = 1;
-#endif
- while(ticks > 0){
- do_IRQ(TIMER_IRQ, regs);
- ticks--;
+ switch(mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ set_interval();
+ break;
+
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_ONESHOT:
+ disable_timer();
+ break;
+
+ case CLOCK_EVT_MODE_RESUME:
+ break;
}
}
-/* Protects local_offset */
-static DEFINE_SPINLOCK(timer_spinlock);
-static unsigned long long local_offset = 0;
-
-static inline unsigned long long get_time(void)
+static int itimer_next_event(unsigned long delta,
+ struct clock_event_device *evt)
{
- unsigned long long nsecs;
- unsigned long flags;
-
- spin_lock_irqsave(&timer_spinlock, flags);
- nsecs = os_nsecs();
- nsecs += local_offset;
- spin_unlock_irqrestore(&timer_spinlock, flags);
-
- return nsecs;
+ return timer_one_shot(delta + 1);
}
-irqreturn_t um_timer(int irq, void *dev)
+static struct clock_event_device itimer_clockevent = {
+ .name = "itimer",
+ .rating = 250,
+ .cpumask = CPU_MASK_ALL,
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+ .set_mode = itimer_set_mode,
+ .set_next_event = itimer_next_event,
+ .shift = 32,
+ .irq = 0,
+};
+
+static irqreturn_t um_timer(int irq, void *dev)
{
- unsigned long long nsecs;
- unsigned long flags;
-
- write_seqlock_irqsave(&xtime_lock, flags);
-
- do_timer(1);
-
-#ifdef CONFIG_UML_REAL_TIME_CLOCK
- nsecs = get_time();
-#else
- nsecs = (unsigned long long) xtime.tv_sec * BILLION + xtime.tv_nsec +
- BILLION / HZ;
-#endif
- xtime.tv_sec = nsecs / NSEC_PER_SEC;
- xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC;
-
- write_sequnlock_irqrestore(&xtime_lock, flags);
+ (*itimer_clockevent.event_handler)(&itimer_clockevent);
return IRQ_HANDLED;
}
-static void register_timer(void)
+static cycle_t itimer_read(void)
+{
+ return os_nsecs();
+}
+
+static struct clocksource itimer_clocksource = {
+ .name = "itimer",
+ .rating = 300,
+ .read = itimer_read,
+ .mask = CLOCKSOURCE_MASK(64),
+ .mult = 1,
+ .shift = 0,
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static void __init setup_itimer(void)
{
int err;
err = request_irq(TIMER_IRQ, um_timer, IRQF_DISABLED, "timer", NULL);
- if(err != 0)
+ if (err != 0)
printk(KERN_ERR "register_timer : request_irq failed - "
"errno = %d\n", -err);
- err = set_interval(1);
- if(err != 0)
- printk(KERN_ERR "register_timer : set_interval failed - "
- "errno = %d\n", -err);
+ itimer_clockevent.mult = div_sc(HZ, NSEC_PER_SEC, 32);
+ itimer_clockevent.max_delta_ns =
+ clockevent_delta2ns(60 * HZ, &itimer_clockevent);
+ itimer_clockevent.min_delta_ns =
+ clockevent_delta2ns(1, &itimer_clockevent);
+ err = clocksource_register(&itimer_clocksource);
+ if (err) {
+ printk(KERN_ERR "clocksource_register returned %d\n", err);
+ return;
+ }
+ clockevents_register_device(&itimer_clockevent);
}
extern void (*late_time_init)(void);
-void time_init(void)
+void __init time_init(void)
{
long long nsecs;
- nsecs = os_nsecs();
- set_normalized_timespec(&wall_to_monotonic, -nsecs / BILLION,
- -nsecs % BILLION);
- set_normalized_timespec(&xtime, nsecs / BILLION, nsecs % BILLION);
- late_time_init = register_timer;
-}
-
-void do_gettimeofday(struct timeval *tv)
-{
-#ifdef CONFIG_UML_REAL_TIME_CLOCK
- unsigned long long nsecs = get_time();
-#else
- unsigned long long nsecs = (unsigned long long) xtime.tv_sec * BILLION +
- xtime.tv_nsec;
-#endif
- tv->tv_sec = nsecs / NSEC_PER_SEC;
- /* Careful about calculations here - this was originally done as
- * (nsecs - tv->tv_sec * NSEC_PER_SEC) / NSEC_PER_USEC
- * which gave bogus (> 1000000) values. Dunno why, suspect gcc
- * (4.0.0) miscompiled it, or there's a subtle 64/32-bit conversion
- * problem that I missed.
- */
- nsecs -= tv->tv_sec * NSEC_PER_SEC;
- tv->tv_usec = (unsigned long) nsecs / NSEC_PER_USEC;
-}
-
-static inline void set_time(unsigned long long nsecs)
-{
- unsigned long long now;
- unsigned long flags;
-
- spin_lock_irqsave(&timer_spinlock, flags);
- now = os_nsecs();
- local_offset = nsecs - now;
- spin_unlock_irqrestore(&timer_spinlock, flags);
-
- clock_was_set();
-}
-
-int do_settimeofday(struct timespec *tv)
-{
- set_time((unsigned long long) tv->tv_sec * NSEC_PER_SEC + tv->tv_nsec);
-
- return 0;
-}
+ timer_init();
-void timer_handler(int sig, union uml_pt_regs *regs)
-{
- if(current_thread->cpu == 0)
- timer_irq(regs);
- local_irq_disable();
- irq_enter();
- update_process_times(CHOOSE_MODE(
- (UPT_SC(regs) && user_context(UPT_SP(regs))),
- (regs)->skas.is_user));
- irq_exit();
- local_irq_enable();
+ nsecs = os_nsecs();
+ set_normalized_timespec(&wall_to_monotonic, -nsecs / NSEC_PER_SEC,
+ -nsecs % NSEC_PER_SEC);
+ set_normalized_timespec(&xtime, nsecs / NSEC_PER_SEC,
+ nsecs % NSEC_PER_SEC);
+ late_time_init = setup_itimer;
}
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c
index 8a8d52851443..f4a0e407eee4 100644
--- a/arch/um/kernel/tlb.c
+++ b/arch/um/kernel/tlb.c
@@ -1,130 +1,182 @@
/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
#include "linux/mm.h"
-#include "asm/page.h"
-#include "asm/pgalloc.h"
#include "asm/pgtable.h"
#include "asm/tlbflush.h"
-#include "choose-mode.h"
-#include "mode_kern.h"
#include "as-layout.h"
-#include "tlb.h"
-#include "mem.h"
#include "mem_user.h"
#include "os.h"
+#include "skas.h"
+#include "tlb.h"
+
+struct host_vm_change {
+ struct host_vm_op {
+ enum { NONE, MMAP, MUNMAP, MPROTECT } type;
+ union {
+ struct {
+ unsigned long addr;
+ unsigned long len;
+ unsigned int prot;
+ int fd;
+ __u64 offset;
+ } mmap;
+ struct {
+ unsigned long addr;
+ unsigned long len;
+ } munmap;
+ struct {
+ unsigned long addr;
+ unsigned long len;
+ unsigned int prot;
+ } mprotect;
+ } u;
+ } ops[1];
+ int index;
+ struct mm_id *id;
+ void *data;
+ int force;
+};
+
+#define INIT_HVC(mm, force) \
+ ((struct host_vm_change) \
+ { .ops = { { .type = NONE } }, \
+ .id = &mm->context.id, \
+ .data = NULL, \
+ .index = 0, \
+ .force = force })
+
+static int do_ops(struct host_vm_change *hvc, int end,
+ int finished)
+{
+ struct host_vm_op *op;
+ int i, ret = 0;
+
+ for (i = 0; i < end && !ret; i++) {
+ op = &hvc->ops[i];
+ switch(op->type) {
+ case MMAP:
+ ret = map(hvc->id, op->u.mmap.addr, op->u.mmap.len,
+ op->u.mmap.prot, op->u.mmap.fd,
+ op->u.mmap.offset, finished, &hvc->data);
+ break;
+ case MUNMAP:
+ ret = unmap(hvc->id, op->u.munmap.addr,
+ op->u.munmap.len, finished, &hvc->data);
+ break;
+ case MPROTECT:
+ ret = protect(hvc->id, op->u.mprotect.addr,
+ op->u.mprotect.len, op->u.mprotect.prot,
+ finished, &hvc->data);
+ break;
+ default:
+ printk(KERN_ERR "Unknown op type %d in do_ops\n",
+ op->type);
+ break;
+ }
+ }
+
+ return ret;
+}
static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
- unsigned int prot, struct host_vm_op *ops, int *index,
- int last_filled, union mm_context *mmu, void **flush,
- int (*do_ops)(union mm_context *, struct host_vm_op *,
- int, int, void **))
+ unsigned int prot, struct host_vm_change *hvc)
{
__u64 offset;
struct host_vm_op *last;
int fd, ret = 0;
fd = phys_mapping(phys, &offset);
- if(*index != -1){
- last = &ops[*index];
- if((last->type == MMAP) &&
+ if (hvc->index != 0) {
+ last = &hvc->ops[hvc->index - 1];
+ if ((last->type == MMAP) &&
(last->u.mmap.addr + last->u.mmap.len == virt) &&
(last->u.mmap.prot == prot) && (last->u.mmap.fd == fd) &&
- (last->u.mmap.offset + last->u.mmap.len == offset)){
+ (last->u.mmap.offset + last->u.mmap.len == offset)) {
last->u.mmap.len += len;
return 0;
}
}
- if(*index == last_filled){
- ret = (*do_ops)(mmu, ops, last_filled, 0, flush);
- *index = -1;
+ if (hvc->index == ARRAY_SIZE(hvc->ops)) {
+ ret = do_ops(hvc, ARRAY_SIZE(hvc->ops), 0);
+ hvc->index = 0;
}
- ops[++*index] = ((struct host_vm_op) { .type = MMAP,
- .u = { .mmap = {
- .addr = virt,
- .len = len,
- .prot = prot,
- .fd = fd,
- .offset = offset }
+ hvc->ops[hvc->index++] = ((struct host_vm_op)
+ { .type = MMAP,
+ .u = { .mmap = { .addr = virt,
+ .len = len,
+ .prot = prot,
+ .fd = fd,
+ .offset = offset }
} });
return ret;
}
static int add_munmap(unsigned long addr, unsigned long len,
- struct host_vm_op *ops, int *index, int last_filled,
- union mm_context *mmu, void **flush,
- int (*do_ops)(union mm_context *, struct host_vm_op *,
- int, int, void **))
+ struct host_vm_change *hvc)
{
struct host_vm_op *last;
int ret = 0;
- if(*index != -1){
- last = &ops[*index];
- if((last->type == MUNMAP) &&
- (last->u.munmap.addr + last->u.mmap.len == addr)){
+ if (hvc->index != 0) {
+ last = &hvc->ops[hvc->index - 1];
+ if ((last->type == MUNMAP) &&
+ (last->u.munmap.addr + last->u.mmap.len == addr)) {
last->u.munmap.len += len;
return 0;
}
}
- if(*index == last_filled){
- ret = (*do_ops)(mmu, ops, last_filled, 0, flush);
- *index = -1;
+ if (hvc->index == ARRAY_SIZE(hvc->ops)) {
+ ret = do_ops(hvc, ARRAY_SIZE(hvc->ops), 0);
+ hvc->index = 0;
}
- ops[++*index] = ((struct host_vm_op) { .type = MUNMAP,
- .u = { .munmap = {
- .addr = addr,
- .len = len } } });
+ hvc->ops[hvc->index++] = ((struct host_vm_op)
+ { .type = MUNMAP,
+ .u = { .munmap = { .addr = addr,
+ .len = len } } });
return ret;
}
static int add_mprotect(unsigned long addr, unsigned long len,
- unsigned int prot, struct host_vm_op *ops, int *index,
- int last_filled, union mm_context *mmu, void **flush,
- int (*do_ops)(union mm_context *, struct host_vm_op *,
- int, int, void **))
+ unsigned int prot, struct host_vm_change *hvc)
{
struct host_vm_op *last;
int ret = 0;
- if(*index != -1){
- last = &ops[*index];
- if((last->type == MPROTECT) &&
+ if (hvc->index != 0) {
+ last = &hvc->ops[hvc->index - 1];
+ if ((last->type == MPROTECT) &&
(last->u.mprotect.addr + last->u.mprotect.len == addr) &&
- (last->u.mprotect.prot == prot)){
+ (last->u.mprotect.prot == prot)) {
last->u.mprotect.len += len;
return 0;
}
}
- if(*index == last_filled){
- ret = (*do_ops)(mmu, ops, last_filled, 0, flush);
- *index = -1;
+ if (hvc->index == ARRAY_SIZE(hvc->ops)) {
+ ret = do_ops(hvc, ARRAY_SIZE(hvc->ops), 0);
+ hvc->index = 0;
}
- ops[++*index] = ((struct host_vm_op) { .type = MPROTECT,
- .u = { .mprotect = {
- .addr = addr,
- .len = len,
- .prot = prot } } });
+ hvc->ops[hvc->index++] = ((struct host_vm_op)
+ { .type = MPROTECT,
+ .u = { .mprotect = { .addr = addr,
+ .len = len,
+ .prot = prot } } });
return ret;
}
#define ADD_ROUND(n, inc) (((n) + (inc)) & ~((inc) - 1))
static inline int update_pte_range(pmd_t *pmd, unsigned long addr,
- unsigned long end, struct host_vm_op *ops,
- int last_op, int *op_index, int force,
- union mm_context *mmu, void **flush,
- int (*do_ops)(union mm_context *,
- struct host_vm_op *, int, int,
- void **))
+ unsigned long end,
+ struct host_vm_change *hvc)
{
pte_t *pte;
int r, w, x, prot, ret = 0;
@@ -142,29 +194,22 @@ static inline int update_pte_range(pmd_t *pmd, unsigned long addr,
}
prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) |
(x ? UM_PROT_EXEC : 0));
- if(force || pte_newpage(*pte)){
- if(pte_present(*pte))
+ if (hvc->force || pte_newpage(*pte)) {
+ if (pte_present(*pte))
ret = add_mmap(addr, pte_val(*pte) & PAGE_MASK,
- PAGE_SIZE, prot, ops, op_index,
- last_op, mmu, flush, do_ops);
- else ret = add_munmap(addr, PAGE_SIZE, ops, op_index,
- last_op, mmu, flush, do_ops);
+ PAGE_SIZE, prot, hvc);
+ else ret = add_munmap(addr, PAGE_SIZE, hvc);
}
- else if(pte_newprot(*pte))
- ret = add_mprotect(addr, PAGE_SIZE, prot, ops, op_index,
- last_op, mmu, flush, do_ops);
+ else if (pte_newprot(*pte))
+ ret = add_mprotect(addr, PAGE_SIZE, prot, hvc);
*pte = pte_mkuptodate(*pte);
} while (pte++, addr += PAGE_SIZE, ((addr != end) && !ret));
return ret;
}
static inline int update_pmd_range(pud_t *pud, unsigned long addr,
- unsigned long end, struct host_vm_op *ops,
- int last_op, int *op_index, int force,
- union mm_context *mmu, void **flush,
- int (*do_ops)(union mm_context *,
- struct host_vm_op *, int, int,
- void **))
+ unsigned long end,
+ struct host_vm_change *hvc)
{
pmd_t *pmd;
unsigned long next;
@@ -173,28 +218,20 @@ static inline int update_pmd_range(pud_t *pud, unsigned long addr,
pmd = pmd_offset(pud, addr);
do {
next = pmd_addr_end(addr, end);
- if(!pmd_present(*pmd)){
- if(force || pmd_newpage(*pmd)){
- ret = add_munmap(addr, next - addr, ops,
- op_index, last_op, mmu,
- flush, do_ops);
+ if (!pmd_present(*pmd)) {
+ if (hvc->force || pmd_newpage(*pmd)) {
+ ret = add_munmap(addr, next - addr, hvc);
pmd_mkuptodate(*pmd);
}
}
- else ret = update_pte_range(pmd, addr, next, ops, last_op,
- op_index, force, mmu, flush,
- do_ops);
+ else ret = update_pte_range(pmd, addr, next, hvc);
} while (pmd++, addr = next, ((addr != end) && !ret));
return ret;
}
static inline int update_pud_range(pgd_t *pgd, unsigned long addr,
- unsigned long end, struct host_vm_op *ops,
- int last_op, int *op_index, int force,
- union mm_context *mmu, void **flush,
- int (*do_ops)(union mm_context *,
- struct host_vm_op *, int, int,
- void **))
+ unsigned long end,
+ struct host_vm_change *hvc)
{
pud_t *pud;
unsigned long next;
@@ -203,56 +240,45 @@ static inline int update_pud_range(pgd_t *pgd, unsigned long addr,
pud = pud_offset(pgd, addr);
do {
next = pud_addr_end(addr, end);
- if(!pud_present(*pud)){
- if(force || pud_newpage(*pud)){
- ret = add_munmap(addr, next - addr, ops,
- op_index, last_op, mmu,
- flush, do_ops);
+ if (!pud_present(*pud)) {
+ if (hvc->force || pud_newpage(*pud)) {
+ ret = add_munmap(addr, next - addr, hvc);
pud_mkuptodate(*pud);
}
}
- else ret = update_pmd_range(pud, addr, next, ops, last_op,
- op_index, force, mmu, flush,
- do_ops);
+ else ret = update_pmd_range(pud, addr, next, hvc);
} while (pud++, addr = next, ((addr != end) && !ret));
return ret;
}
void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
- unsigned long end_addr, int force,
- int (*do_ops)(union mm_context *, struct host_vm_op *,
- int, int, void **))
+ unsigned long end_addr, int force)
{
pgd_t *pgd;
- union mm_context *mmu = &mm->context;
- struct host_vm_op ops[1];
+ struct host_vm_change hvc;
unsigned long addr = start_addr, next;
- int ret = 0, last_op = ARRAY_SIZE(ops) - 1, op_index = -1;
- void *flush = NULL;
+ int ret = 0;
- ops[0].type = NONE;
+ hvc = INIT_HVC(mm, force);
pgd = pgd_offset(mm, addr);
do {
next = pgd_addr_end(addr, end_addr);
- if(!pgd_present(*pgd)){
- if (force || pgd_newpage(*pgd)){
- ret = add_munmap(addr, next - addr, ops,
- &op_index, last_op, mmu,
- &flush, do_ops);
+ if (!pgd_present(*pgd)) {
+ if (force || pgd_newpage(*pgd)) {
+ ret = add_munmap(addr, next - addr, &hvc);
pgd_mkuptodate(*pgd);
}
}
- else ret = update_pud_range(pgd, addr, next, ops, last_op,
- &op_index, force, mmu, &flush,
- do_ops);
+ else ret = update_pud_range(pgd, addr, next, &hvc);
} while (pgd++, addr = next, ((addr != end_addr) && !ret));
- if(!ret)
- ret = (*do_ops)(mmu, ops, op_index, 1, &flush);
+ if (!ret)
+ ret = do_ops(&hvc, hvc.index, 1);
/* This is not an else because ret is modified above */
- if(ret) {
- printk("fix_range_common: failed, killing current process\n");
+ if (ret) {
+ printk(KERN_ERR "fix_range_common: failed, killing current "
+ "process\n");
force_sig(SIGKILL, current);
}
}
@@ -268,17 +294,17 @@ int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
int updated = 0, err;
mm = &init_mm;
- for(addr = start; addr < end;){
+ for (addr = start; addr < end;) {
pgd = pgd_offset(mm, addr);
- if(!pgd_present(*pgd)){
+ if (!pgd_present(*pgd)) {
last = ADD_ROUND(addr, PGDIR_SIZE);
- if(last > end)
+ if (last > end)
last = end;
- if(pgd_newpage(*pgd)){
+ if (pgd_newpage(*pgd)) {
updated = 1;
err = os_unmap_memory((void *) addr,
last - addr);
- if(err < 0)
+ if (err < 0)
panic("munmap failed, errno = %d\n",
-err);
}
@@ -287,15 +313,15 @@ int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
}
pud = pud_offset(pgd, addr);
- if(!pud_present(*pud)){
+ if (!pud_present(*pud)) {
last = ADD_ROUND(addr, PUD_SIZE);
- if(last > end)
+ if (last > end)
last = end;
- if(pud_newpage(*pud)){
+ if (pud_newpage(*pud)) {
updated = 1;
err = os_unmap_memory((void *) addr,
last - addr);
- if(err < 0)
+ if (err < 0)
panic("munmap failed, errno = %d\n",
-err);
}
@@ -304,15 +330,15 @@ int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
}
pmd = pmd_offset(pud, addr);
- if(!pmd_present(*pmd)){
+ if (!pmd_present(*pmd)) {
last = ADD_ROUND(addr, PMD_SIZE);
- if(last > end)
+ if (last > end)
last = end;
- if(pmd_newpage(*pmd)){
+ if (pmd_newpage(*pmd)) {
updated = 1;
err = os_unmap_memory((void *) addr,
last - addr);
- if(err < 0)
+ if (err < 0)
panic("munmap failed, errno = %d\n",
-err);
}
@@ -321,45 +347,110 @@ int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
}
pte = pte_offset_kernel(pmd, addr);
- if(!pte_present(*pte) || pte_newpage(*pte)){
+ if (!pte_present(*pte) || pte_newpage(*pte)) {
updated = 1;
err = os_unmap_memory((void *) addr,
PAGE_SIZE);
- if(err < 0)
+ if (err < 0)
panic("munmap failed, errno = %d\n",
-err);
- if(pte_present(*pte))
+ if (pte_present(*pte))
map_memory(addr,
pte_val(*pte) & PAGE_MASK,
PAGE_SIZE, 1, 1, 1);
}
- else if(pte_newprot(*pte)){
+ else if (pte_newprot(*pte)) {
updated = 1;
os_protect_memory((void *) addr, PAGE_SIZE, 1, 1, 1);
}
addr += PAGE_SIZE;
}
- return(updated);
+ return updated;
+}
+
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long address)
+{
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte;
+ struct mm_struct *mm = vma->vm_mm;
+ void *flush = NULL;
+ int r, w, x, prot, err = 0;
+ struct mm_id *mm_id;
+
+ address &= PAGE_MASK;
+ pgd = pgd_offset(mm, address);
+ if (!pgd_present(*pgd))
+ goto kill;
+
+ pud = pud_offset(pgd, address);
+ if (!pud_present(*pud))
+ goto kill;
+
+ pmd = pmd_offset(pud, address);
+ if (!pmd_present(*pmd))
+ goto kill;
+
+ pte = pte_offset_kernel(pmd, address);
+
+ r = pte_read(*pte);
+ w = pte_write(*pte);
+ x = pte_exec(*pte);
+ if (!pte_young(*pte)) {
+ r = 0;
+ w = 0;
+ } else if (!pte_dirty(*pte)) {
+ w = 0;
+ }
+
+ mm_id = &mm->context.id;
+ prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) |
+ (x ? UM_PROT_EXEC : 0));
+ if (pte_newpage(*pte)) {
+ if (pte_present(*pte)) {
+ unsigned long long offset;
+ int fd;
+
+ fd = phys_mapping(pte_val(*pte) & PAGE_MASK, &offset);
+ err = map(mm_id, address, PAGE_SIZE, prot, fd, offset,
+ 1, &flush);
+ }
+ else err = unmap(mm_id, address, PAGE_SIZE, 1, &flush);
+ }
+ else if (pte_newprot(*pte))
+ err = protect(mm_id, address, PAGE_SIZE, prot, 1, &flush);
+
+ if (err)
+ goto kill;
+
+ *pte = pte_mkuptodate(*pte);
+
+ return;
+
+kill:
+ printk(KERN_ERR "Failed to flush page for address 0x%lx\n", address);
+ force_sig(SIGKILL, current);
}
pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address)
{
- return(pgd_offset(mm, address));
+ return pgd_offset(mm, address);
}
pud_t *pud_offset_proc(pgd_t *pgd, unsigned long address)
{
- return(pud_offset(pgd, address));
+ return pud_offset(pgd, address);
}
pmd_t *pmd_offset_proc(pud_t *pud, unsigned long address)
{
- return(pmd_offset(pud, address));
+ return pmd_offset(pud, address);
}
pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address)
{
- return(pte_offset_kernel(pmd, address));
+ return pte_offset_kernel(pmd, address);
}
pte_t *addr_pte(struct task_struct *task, unsigned long addr)
@@ -368,7 +459,7 @@ pte_t *addr_pte(struct task_struct *task, unsigned long addr)
pud_t *pud = pud_offset(pgd, addr);
pmd_t *pmd = pmd_offset(pud, addr);
- return(pte_offset_map(pmd, addr));
+ return pte_offset_map(pmd, addr);
}
void flush_tlb_all(void)
@@ -378,35 +469,58 @@ void flush_tlb_all(void)
void flush_tlb_kernel_range(unsigned long start, unsigned long end)
{
- CHOOSE_MODE_PROC(flush_tlb_kernel_range_tt,
- flush_tlb_kernel_range_common, start, end);
+ flush_tlb_kernel_range_common(start, end);
}
void flush_tlb_kernel_vm(void)
{
- CHOOSE_MODE(flush_tlb_kernel_vm_tt(),
- flush_tlb_kernel_range_common(start_vm, end_vm));
+ flush_tlb_kernel_range_common(start_vm, end_vm);
}
void __flush_tlb_one(unsigned long addr)
{
- CHOOSE_MODE_PROC(__flush_tlb_one_tt, __flush_tlb_one_skas, addr);
+ flush_tlb_kernel_range_common(addr, addr + PAGE_SIZE);
+}
+
+static void fix_range(struct mm_struct *mm, unsigned long start_addr,
+ unsigned long end_addr, int force)
+{
+ if (!proc_mm && (end_addr > STUB_START))
+ end_addr = STUB_START;
+
+ fix_range_common(mm, start_addr, end_addr, force);
}
void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
unsigned long end)
{
- CHOOSE_MODE_PROC(flush_tlb_range_tt, flush_tlb_range_skas, vma, start,
- end);
+ if (vma->vm_mm == NULL)
+ flush_tlb_kernel_range_common(start, end);
+ else fix_range(vma->vm_mm, start, end, 0);
}
void flush_tlb_mm(struct mm_struct *mm)
{
- CHOOSE_MODE_PROC(flush_tlb_mm_tt, flush_tlb_mm_skas, mm);
+ unsigned long end;
+
+ /*
+ * Don't bother flushing if this address space is about to be
+ * destroyed.
+ */
+ if (atomic_read(&mm->mm_users) == 0)
+ return;
+
+ end = proc_mm ? task_size : STUB_START;
+ fix_range(mm, 0, end, 0);
}
void force_flush_all(void)
{
- CHOOSE_MODE(force_flush_all_tt(), force_flush_all_skas());
-}
+ struct mm_struct *mm = current->mm;
+ struct vm_area_struct *vma = mm->mmap;
+ while (vma != NULL) {
+ fix_range(mm, vma->vm_start, vma->vm_end, 1);
+ vma = vma->vm_next;
+ }
+}
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index 3850d53f79fd..cb3321f8e0a9 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -1,40 +1,24 @@
/*
- * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/kernel.h"
-#include "asm/errno.h"
-#include "linux/sched.h"
-#include "linux/mm.h"
-#include "linux/spinlock.h"
-#include "linux/init.h"
-#include "linux/ptrace.h"
-#include "asm/semaphore.h"
-#include "asm/pgtable.h"
-#include "asm/pgalloc.h"
-#include "asm/tlbflush.h"
-#include "asm/a.out.h"
-#include "asm/current.h"
-#include "asm/irq.h"
-#include "sysdep/sigcontext.h"
-#include "kern_util.h"
-#include "as-layout.h"
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/hardirq.h>
+#include <asm/current.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
#include "arch.h"
-#include "kern.h"
-#include "chan_kern.h"
-#include "mconsole_kern.h"
-#include "mem.h"
-#include "mem_kern.h"
-#include "sysdep/sigcontext.h"
-#include "sysdep/ptrace.h"
-#include "os.h"
-#ifdef CONFIG_MODE_SKAS
-#include "skas.h"
-#endif
+#include "as-layout.h"
+#include "kern_util.h"
#include "os.h"
+#include "sysdep/sigcontext.h"
-/* Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by segv(). */
+/*
+ * Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by
+ * segv().
+ */
int handle_page_fault(unsigned long address, unsigned long ip,
int is_write, int is_user, int *code_out)
{
@@ -48,31 +32,33 @@ int handle_page_fault(unsigned long address, unsigned long ip,
*code_out = SEGV_MAPERR;
- /* If the fault was during atomic operation, don't take the fault, just
- * fail. */
+ /*
+ * If the fault was during atomic operation, don't take the fault, just
+ * fail.
+ */
if (in_atomic())
goto out_nosemaphore;
down_read(&mm->mmap_sem);
vma = find_vma(mm, address);
- if(!vma)
+ if (!vma)
goto out;
- else if(vma->vm_start <= address)
+ else if (vma->vm_start <= address)
goto good_area;
- else if(!(vma->vm_flags & VM_GROWSDOWN))
+ else if (!(vma->vm_flags & VM_GROWSDOWN))
goto out;
- else if(is_user && !ARCH_IS_STACKGROW(address))
+ else if (is_user && !ARCH_IS_STACKGROW(address))
goto out;
- else if(expand_stack(vma, address))
+ else if (expand_stack(vma, address))
goto out;
good_area:
*code_out = SEGV_ACCERR;
- if(is_write && !(vma->vm_flags & VM_WRITE))
+ if (is_write && !(vma->vm_flags & VM_WRITE))
goto out;
/* Don't require VM_READ|VM_EXEC for write faults! */
- if(!is_write && !(vma->vm_flags & (VM_READ | VM_EXEC)))
+ if (!is_write && !(vma->vm_flags & (VM_READ | VM_EXEC)))
goto out;
do {
@@ -98,9 +84,10 @@ survive:
pud = pud_offset(pgd, address);
pmd = pmd_offset(pud, address);
pte = pte_offset_kernel(pmd, address);
- } while(!pte_present(*pte));
+ } while (!pte_present(*pte));
err = 0;
- /* The below warning was added in place of
+ /*
+ * The below warning was added in place of
* pte_mkyoung(); if (is_write) pte_mkdirty();
* If it's triggered, we'd see normally a hang here (a clean pte is
* marked read-only to emulate the dirty bit).
@@ -114,14 +101,14 @@ survive:
out:
up_read(&mm->mmap_sem);
out_nosemaphore:
- return(err);
+ return err;
/*
* We ran out of memory, or some other thing happened to us that made
* us unable to handle the page fault gracefully.
*/
out_of_memory:
- if (is_init(current)) {
+ if (is_global_init(current)) {
up_read(&mm->mmap_sem);
yield();
down_read(&mm->mmap_sem);
@@ -141,11 +128,11 @@ static void bad_segv(struct faultinfo fi, unsigned long ip)
force_sig_info(SIGSEGV, &si, current);
}
-static void segv_handler(int sig, union uml_pt_regs *regs)
+static void segv_handler(int sig, struct uml_pt_regs *regs)
{
struct faultinfo * fi = UPT_FAULTINFO(regs);
- if(UPT_IS_USER(regs) && !SEGV_IS_FIXABLE(fi)){
+ if (UPT_IS_USER(regs) && !SEGV_IS_FIXABLE(fi)) {
bad_segv(*fi, UPT_IP(regs));
return;
}
@@ -159,45 +146,49 @@ static void segv_handler(int sig, union uml_pt_regs *regs)
* give us bad data!
*/
unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
- union uml_pt_regs *regs)
+ struct uml_pt_regs *regs)
{
struct siginfo si;
- void *catcher;
+ jmp_buf *catcher;
int err;
int is_write = FAULT_WRITE(fi);
unsigned long address = FAULT_ADDRESS(fi);
- if(!is_user && (address >= start_vm) && (address < end_vm)){
+ if (!is_user && (address >= start_vm) && (address < end_vm)) {
flush_tlb_kernel_vm();
return 0;
}
- else if(current->mm == NULL) {
+ else if (current->mm == NULL) {
show_regs(container_of(regs, struct pt_regs, regs));
- panic("Segfault with no mm");
+ panic("Segfault with no mm");
}
if (SEGV_IS_FIXABLE(&fi) || SEGV_MAYBE_FIXABLE(&fi))
- err = handle_page_fault(address, ip, is_write, is_user, &si.si_code);
+ err = handle_page_fault(address, ip, is_write, is_user,
+ &si.si_code);
else {
err = -EFAULT;
- /* A thread accessed NULL, we get a fault, but CR2 is invalid.
- * This code is used in __do_copy_from_user() of TT mode. */
+ /*
+ * A thread accessed NULL, we get a fault, but CR2 is invalid.
+ * This code is used in __do_copy_from_user() of TT mode.
+ * XXX tt mode is gone, so maybe this isn't needed any more
+ */
address = 0;
}
catcher = current->thread.fault_catcher;
- if(!err)
+ if (!err)
return 0;
- else if(catcher != NULL){
+ else if (catcher != NULL) {
current->thread.fault_addr = (void *) address;
- do_longjmp(catcher, 1);
+ UML_LONGJMP(catcher, 1);
}
- else if(current->thread.fault_addr != NULL)
+ else if (current->thread.fault_addr != NULL)
panic("fault_addr set but no fault catcher");
- else if(!is_user && arch_fixup(ip, regs))
+ else if (!is_user && arch_fixup(ip, regs))
return 0;
- if(!is_user) {
+ if (!is_user) {
show_regs(container_of(regs, struct pt_regs, regs));
panic("Kernel mode fault at addr 0x%lx, ip 0x%lx",
address, ip);
@@ -211,7 +202,7 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
current->thread.arch.faultinfo = fi;
force_sig_info(SIGBUS, &si, current);
} else if (err == -ENOMEM) {
- printk("VM: killing process %s\n", current->comm);
+ printk(KERN_INFO "VM: killing process %s\n", current->comm);
do_exit(SIGKILL);
} else {
BUG_ON(err != -EFAULT);
@@ -223,15 +214,15 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
return 0;
}
-void relay_signal(int sig, union uml_pt_regs *regs)
+void relay_signal(int sig, struct uml_pt_regs *regs)
{
- if(arch_handle_signal(sig, regs))
+ if (arch_handle_signal(sig, regs))
return;
- if(!UPT_IS_USER(regs)){
- if(sig == SIGBUS)
- printk("Bus error - the host /dev/shm or /tmp mount "
- "likely just ran out of space\n");
+ if (!UPT_IS_USER(regs)) {
+ if (sig == SIGBUS)
+ printk(KERN_ERR "Bus error - the host /dev/shm or /tmp "
+ "mount likely just ran out of space\n");
panic("Kernel mode signal %d", sig);
}
@@ -239,14 +230,14 @@ void relay_signal(int sig, union uml_pt_regs *regs)
force_sig(sig, current);
}
-static void bus_handler(int sig, union uml_pt_regs *regs)
+static void bus_handler(int sig, struct uml_pt_regs *regs)
{
- if(current->thread.fault_catcher != NULL)
- do_longjmp(current->thread.fault_catcher, 1);
+ if (current->thread.fault_catcher != NULL)
+ UML_LONGJMP(current->thread.fault_catcher, 1);
else relay_signal(sig, regs);
}
-static void winch(int sig, union uml_pt_regs *regs)
+static void winch(int sig, struct uml_pt_regs *regs)
{
do_IRQ(WINCH_IRQ, regs);
}
diff --git a/arch/um/kernel/tt/Makefile b/arch/um/kernel/tt/Makefile
deleted file mode 100644
index 6939e5af8472..000000000000
--- a/arch/um/kernel/tt/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
-# Licensed under the GPL
-#
-
-obj-y = exec_kern.o exec_user.o gdb.o ksyms.o mem.o mem_user.o process_kern.o \
- syscall_kern.o syscall_user.o tlb.o tracer.o trap_user.o \
- uaccess.o uaccess_user.o
-
-obj-$(CONFIG_PT_PROXY) += gdb_kern.o ptproxy/
-
-USER_OBJS := gdb.o tracer.o
-
-include arch/um/scripts/Makefile.rules
diff --git a/arch/um/kernel/tt/exec_kern.c b/arch/um/kernel/tt/exec_kern.c
deleted file mode 100644
index 40126cb51801..000000000000
--- a/arch/um/kernel/tt/exec_kern.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include "linux/kernel.h"
-#include "linux/mm.h"
-#include "asm/signal.h"
-#include "asm/ptrace.h"
-#include "asm/uaccess.h"
-#include "asm/pgalloc.h"
-#include "asm/tlbflush.h"
-#include "kern_util.h"
-#include "irq_user.h"
-#include "mem_user.h"
-#include "os.h"
-#include "tlb.h"
-#include "mode.h"
-
-static int exec_tramp(void *sig_stack)
-{
- init_new_thread_stack(sig_stack, NULL);
- init_new_thread_signals();
- os_stop_process(os_getpid());
- return(0);
-}
-
-void flush_thread_tt(void)
-{
- unsigned long stack;
- int new_pid;
-
- stack = alloc_stack(0, 0);
- if(stack == 0){
- printk(KERN_ERR
- "flush_thread : failed to allocate temporary stack\n");
- do_exit(SIGKILL);
- }
-
- new_pid = start_fork_tramp(task_stack_page(current), stack, 0, exec_tramp);
- if(new_pid < 0){
- printk(KERN_ERR
- "flush_thread : new thread failed, errno = %d\n",
- -new_pid);
- do_exit(SIGKILL);
- }
-
- if(current_thread->cpu == 0)
- forward_interrupts(new_pid);
- current->thread.request.op = OP_EXEC;
- current->thread.request.u.exec.pid = new_pid;
- unprotect_stack((unsigned long) current_thread);
- os_usr1_process(os_getpid());
- change_sig(SIGUSR1, 1);
-
- change_sig(SIGUSR1, 0);
- enable_timer();
- free_page(stack);
- protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1);
- stack_protections((unsigned long) current_thread);
- force_flush_all();
- unblock_signals();
-}
-
-void start_thread_tt(struct pt_regs *regs, unsigned long eip,
- unsigned long esp)
-{
- set_fs(USER_DS);
- flush_tlb_mm(current->mm);
- PT_REGS_IP(regs) = eip;
- PT_REGS_SP(regs) = esp;
- PT_FIX_EXEC_STACK(esp);
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/tt/exec_user.c b/arch/um/kernel/tt/exec_user.c
deleted file mode 100644
index 7b5f2181cf51..000000000000
--- a/arch/um/kernel/tt/exec_user.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <sched.h>
-#include <errno.h>
-#include <sys/wait.h>
-#include <signal.h>
-#include "kern_util.h"
-#include "user.h"
-#include "ptrace_user.h"
-#include "os.h"
-
-void do_exec(int old_pid, int new_pid)
-{
- unsigned long regs[FRAME_SIZE];
- int err;
-
- if((ptrace(PTRACE_ATTACH, new_pid, 0, 0) < 0) ||
- (ptrace(PTRACE_CONT, new_pid, 0, 0) < 0))
- tracer_panic("do_exec failed to attach proc - errno = %d",
- errno);
-
- CATCH_EINTR(err = waitpid(new_pid, 0, WUNTRACED));
- if (err < 0)
- tracer_panic("do_exec failed to attach proc in waitpid - errno = %d",
- errno);
-
- if(ptrace_getregs(old_pid, regs) < 0)
- tracer_panic("do_exec failed to get registers - errno = %d",
- errno);
-
- os_kill_ptraced_process(old_pid, 0);
-
- if (ptrace(PTRACE_OLDSETOPTIONS, new_pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0)
- tracer_panic("do_exec: PTRACE_SETOPTIONS failed, errno = %d", errno);
-
- if(ptrace_setregs(new_pid, regs) < 0)
- tracer_panic("do_exec failed to start new proc - errno = %d",
- errno);
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/tt/gdb.c b/arch/um/kernel/tt/gdb.c
deleted file mode 100644
index 030e4658f36b..000000000000
--- a/arch/um/kernel/tt/gdb.c
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <signal.h>
-#include <sys/types.h>
-#include "ptrace_user.h"
-#include "uml-config.h"
-#include "kern_constants.h"
-#include "chan_user.h"
-#include "init.h"
-#include "user.h"
-#include "debug.h"
-#include "kern_util.h"
-#include "tt.h"
-#include "sysdep/thread.h"
-#include "os.h"
-
-extern int debugger_pid;
-extern int debugger_fd;
-extern int debugger_parent;
-
-int detach(int pid, int sig)
-{
- return(ptrace(PTRACE_DETACH, pid, 0, sig));
-}
-
-int attach(int pid)
-{
- int err;
-
- err = ptrace(PTRACE_ATTACH, pid, 0, 0);
- if(err < 0) return(-errno);
- else return(err);
-}
-
-int cont(int pid)
-{
- return(ptrace(PTRACE_CONT, pid, 0, 0));
-}
-
-#ifdef UML_CONFIG_PT_PROXY
-
-int debugger_signal(int status, pid_t pid)
-{
- return(debugger_proxy(status, pid));
-}
-
-void child_signal(pid_t pid, int status)
-{
- child_proxy(pid, status);
-}
-
-static void gdb_announce(char *dev_name, int dev)
-{
- printf("gdb assigned device '%s'\n", dev_name);
-}
-
-static struct chan_opts opts = {
- .announce = gdb_announce,
- .xterm_title = "UML kernel debugger",
- .raw = 0,
- .tramp_stack = 0,
- .in_kernel = 0,
-};
-
-/* Accessed by the tracing thread, which automatically serializes access */
-static void *xterm_data;
-static int xterm_fd;
-
-extern void *xterm_init(char *, int, struct chan_opts *);
-extern int xterm_open(int, int, int, void *, char **);
-extern void xterm_close(int, void *);
-
-int open_gdb_chan(void)
-{
- char stack[UM_KERN_PAGE_SIZE], *dummy;
-
- opts.tramp_stack = (unsigned long) stack;
- xterm_data = xterm_init("", 0, &opts);
- xterm_fd = xterm_open(1, 1, 1, xterm_data, &dummy);
- return(xterm_fd);
-}
-
-static void exit_debugger_cb(void *unused)
-{
- if(debugger_pid != -1){
- if(gdb_pid != -1){
- fake_child_exit();
- gdb_pid = -1;
- }
- else kill_child_dead(debugger_pid);
- debugger_pid = -1;
- if(debugger_parent != -1)
- detach(debugger_parent, SIGINT);
- }
- if(xterm_data != NULL) xterm_close(xterm_fd, xterm_data);
-}
-
-static void exit_debugger(void)
-{
- initial_thread_cb(exit_debugger_cb, NULL);
-}
-
-__uml_exitcall(exit_debugger);
-
-struct gdb_data {
- char *str;
- int err;
-};
-
-extern char *linux_prog;
-
-static void config_gdb_cb(void *arg)
-{
- struct gdb_data *data = arg;
- void *task;
- int pid;
-
- data->err = -1;
- if(debugger_pid != -1) exit_debugger_cb(NULL);
- if(!strncmp(data->str, "pid,", strlen("pid,"))){
- data->str += strlen("pid,");
- pid = strtoul(data->str, NULL, 0);
- task = cpu_tasks[0].task;
- debugger_pid = attach_debugger(TASK_EXTERN_PID(task), pid, 0);
- if(debugger_pid != -1){
- data->err = 0;
- gdb_pid = pid;
- }
- return;
- }
- data->err = 0;
- debugger_pid = start_debugger(linux_prog, 0, 0, &debugger_fd);
- init_proxy(debugger_pid, 0, 0);
-}
-
-int gdb_config(char *str, char **error_out)
-{
- struct gdb_data data;
-
- if(*str++ != '=') return(-1);
- data.str = str;
- initial_thread_cb(config_gdb_cb, &data);
- return(data.err);
-}
-
-void remove_gdb_cb(void *unused)
-{
- exit_debugger_cb(NULL);
-}
-
-int gdb_remove(int unused, char **error_out)
-{
- initial_thread_cb(remove_gdb_cb, NULL);
- return 0;
-}
-
-void signal_usr1(int sig)
-{
- if(debugger_pid != -1){
- printf("The debugger is already running\n");
- return;
- }
- debugger_pid = start_debugger(linux_prog, 0, 0, &debugger_fd);
- init_proxy(debugger_pid, 0, 0);
-}
-
-int init_ptrace_proxy(int idle_pid, int startup, int stop)
-{
- int pid, status;
-
- pid = start_debugger(linux_prog, startup, stop, &debugger_fd);
- status = wait_for_stop(idle_pid, SIGSTOP, PTRACE_CONT, NULL);
- if(pid < 0){
- cont(idle_pid);
- return(-1);
- }
- init_proxy(pid, 1, status);
- return(pid);
-}
-
-int attach_debugger(int idle_pid, int pid, int stop)
-{
- int status = 0, err;
-
- err = attach(pid);
- if(err < 0){
- printf("Failed to attach pid %d, errno = %d\n", pid, -err);
- return(-1);
- }
- if(stop) status = wait_for_stop(idle_pid, SIGSTOP, PTRACE_CONT, NULL);
- init_proxy(pid, 1, status);
- return(pid);
-}
-
-#ifdef notdef /* Put this back in when it does something useful */
-static int __init uml_gdb_init_setup(char *line, int *add)
-{
- gdb_init = uml_strdup(line);
- return 0;
-}
-
-__uml_setup("gdb=", uml_gdb_init_setup,
-"gdb=<channel description>\n\n"
-);
-#endif
-
-static int __init uml_gdb_pid_setup(char *line, int *add)
-{
- gdb_pid = strtoul(line, NULL, 0);
- *add = 0;
- return 0;
-}
-
-__uml_setup("gdb-pid=", uml_gdb_pid_setup,
-"gdb-pid=<pid>\n"
-" gdb-pid is used to attach an external debugger to UML. This may be\n"
-" an already-running gdb or a debugger-like process like strace.\n\n"
-);
-
-#else
-
-int debugger_signal(int status, pid_t pid){ return(0); }
-void child_signal(pid_t pid, int status){ }
-int init_ptrace_proxy(int idle_pid, int startup, int stop)
-{
- printf("debug requested when CONFIG_PT_PROXY is off\n");
- kill_child_dead(idle_pid);
- exit(1);
-}
-
-void signal_usr1(int sig)
-{
- printf("debug requested when CONFIG_PT_PROXY is off\n");
-}
-
-int attach_debugger(int idle_pid, int pid, int stop)
-{
- printf("attach_debugger called when CONFIG_PT_PROXY "
- "is off\n");
- return(-1);
-}
-
-int config_gdb(char *str)
-{
- return(-1);
-}
-
-int remove_gdb(void)
-{
- return(-1);
-}
-
-int init_parent_proxy(int pid)
-{
- return(-1);
-}
-
-void debugger_parent_signal(int status, int pid)
-{
-}
-
-#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/tt/gdb_kern.c b/arch/um/kernel/tt/gdb_kern.c
deleted file mode 100644
index 03b06bc00771..000000000000
--- a/arch/um/kernel/tt/gdb_kern.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include "linux/init.h"
-#include "mconsole_kern.h"
-
-#ifdef CONFIG_MCONSOLE
-
-extern int gdb_config(char *str, char **error_out);
-extern int gdb_remove(int n, char **error_out);
-
-static struct mc_device gdb_mc = {
- .list = INIT_LIST_HEAD(gdb_mc.list),
- .name = "gdb",
- .config = gdb_config,
- .remove = gdb_remove,
-};
-
-int gdb_mc_init(void)
-{
- mconsole_register_dev(&gdb_mc);
- return(0);
-}
-
-__initcall(gdb_mc_init);
-
-#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/tt/include/mode-tt.h b/arch/um/kernel/tt/include/mode-tt.h
deleted file mode 100644
index e171e15fead5..000000000000
--- a/arch/um/kernel/tt/include/mode-tt.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __MODE_TT_H__
-#define __MODE_TT_H__
-
-#include "sysdep/ptrace.h"
-
-enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB };
-
-extern int tracing_pid;
-
-extern int tracer(int (*init_proc)(void *), void *sp);
-extern void sig_handler_common_tt(int sig, void *sc);
-extern void syscall_handler_tt(int sig, union uml_pt_regs *regs);
-extern void reboot_tt(void);
-extern void halt_tt(void);
-extern int is_tracer_winch(int pid, int fd, void *data);
-extern void kill_off_processes_tt(void);
-
-#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/tt/ksyms.c b/arch/um/kernel/tt/ksyms.c
deleted file mode 100644
index 84a9385a8fef..000000000000
--- a/arch/um/kernel/tt/ksyms.c
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include "linux/module.h"
-#include "asm/uaccess.h"
-#include "mode.h"
-
-EXPORT_SYMBOL(__do_copy_from_user);
-EXPORT_SYMBOL(__do_copy_to_user);
-EXPORT_SYMBOL(__do_strncpy_from_user);
-EXPORT_SYMBOL(__do_strnlen_user);
-EXPORT_SYMBOL(__do_clear_user);
-EXPORT_SYMBOL(clear_user_tt);
-
-EXPORT_SYMBOL(tracing_pid);
-EXPORT_SYMBOL(honeypot);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/tt/mem.c b/arch/um/kernel/tt/mem.c
deleted file mode 100644
index d0c3c4975f28..000000000000
--- a/arch/um/kernel/tt/mem.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include "linux/stddef.h"
-#include "linux/mm.h"
-#include "asm/uaccess.h"
-#include "mem_user.h"
-#include "kern_util.h"
-#include "kern.h"
-#include "tt.h"
-
-void before_mem_tt(unsigned long brk_start)
-{
- if(debug)
- remap_data(UML_ROUND_DOWN(&_stext), UML_ROUND_UP(&_etext), 1);
- remap_data(UML_ROUND_DOWN(&_sdata), UML_ROUND_UP(&_edata), 1);
- remap_data(UML_ROUND_DOWN(&__bss_start), UML_ROUND_UP(&_end), 1);
-}
-
-#define SIZE ((CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS) * 0x20000000)
-#define START (CONFIG_TOP_ADDR - SIZE)
-
-unsigned long set_task_sizes_tt(unsigned long *task_size_out)
-{
- unsigned long host_task_size;
-
- /* Round up to the nearest 4M */
- host_task_size = ROUND_4M((unsigned long) &host_task_size);
- *task_size_out = START;
-
- return host_task_size;
-}
diff --git a/arch/um/kernel/tt/mem_user.c b/arch/um/kernel/tt/mem_user.c
deleted file mode 100644
index 9774f6360c32..000000000000
--- a/arch/um/kernel/tt/mem_user.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/mman.h>
-#include "tt.h"
-#include "mem_user.h"
-#include "os.h"
-
-void remap_data(void *segment_start, void *segment_end, int w)
-{
- void *addr;
- unsigned long size;
- int data, prot;
-
- if(w) prot = PROT_WRITE;
- else prot = 0;
- prot |= PROT_READ | PROT_EXEC;
- size = (unsigned long) segment_end -
- (unsigned long) segment_start;
- data = create_mem_file(size);
- addr = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, data, 0);
- if(addr == MAP_FAILED){
- perror("mapping new data segment");
- exit(1);
- }
- memcpy(addr, segment_start, size);
- if(switcheroo(data, prot, addr, segment_start, size) < 0){
- printf("switcheroo failed\n");
- exit(1);
- }
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c
deleted file mode 100644
index 74347adf81bf..000000000000
--- a/arch/um/kernel/tt/process_kern.c
+++ /dev/null
@@ -1,461 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include "linux/sched.h"
-#include "linux/signal.h"
-#include "linux/kernel.h"
-#include "linux/interrupt.h"
-#include "linux/ptrace.h"
-#include "asm/system.h"
-#include "asm/pgalloc.h"
-#include "asm/ptrace.h"
-#include "asm/tlbflush.h"
-#include "irq_user.h"
-#include "kern_util.h"
-#include "os.h"
-#include "kern.h"
-#include "sigcontext.h"
-#include "mem_user.h"
-#include "tlb.h"
-#include "mode.h"
-#include "mode_kern.h"
-#include "init.h"
-#include "tt.h"
-
-void switch_to_tt(void *prev, void *next)
-{
- struct task_struct *from, *to, *prev_sched;
- unsigned long flags;
- int err, vtalrm, alrm, prof, cpu;
- char c;
-
- from = prev;
- to = next;
-
- cpu = task_thread_info(from)->cpu;
- if(cpu == 0)
- forward_interrupts(to->thread.mode.tt.extern_pid);
-#ifdef CONFIG_SMP
- forward_ipi(cpu_data[cpu].ipi_pipe[0], to->thread.mode.tt.extern_pid);
-#endif
- local_irq_save(flags);
-
- vtalrm = change_sig(SIGVTALRM, 0);
- alrm = change_sig(SIGALRM, 0);
- prof = change_sig(SIGPROF, 0);
-
- forward_pending_sigio(to->thread.mode.tt.extern_pid);
-
- c = 0;
-
- /* Notice that here we "up" the semaphore on which "to" is waiting, and
- * below (the read) we wait on this semaphore (which is implemented by
- * switch_pipe) and go sleeping. Thus, after that, we have resumed in
- * "to", and can't use any more the value of "from" (which is outdated),
- * nor the value in "to" (since it was the task which stole us the CPU,
- * which we don't care about). */
-
- err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c));
- if(err != sizeof(c))
- panic("write of switch_pipe failed, err = %d", -err);
-
- if(from->thread.mode.tt.switch_pipe[0] == -1)
- os_kill_process(os_getpid(), 0);
-
- err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c,
- sizeof(c));
- if(err != sizeof(c))
- panic("read of switch_pipe failed, errno = %d", -err);
-
- /* If the process that we have just scheduled away from has exited,
- * then it needs to be killed here. The reason is that, even though
- * it will kill itself when it next runs, that may be too late. Its
- * stack will be freed, possibly before then, and if that happens,
- * we have a use-after-free situation. So, it gets killed here
- * in case it has not already killed itself.
- */
- prev_sched = current->thread.prev_sched;
- if(prev_sched->thread.mode.tt.switch_pipe[0] == -1)
- os_kill_process(prev_sched->thread.mode.tt.extern_pid, 1);
-
- change_sig(SIGVTALRM, vtalrm);
- change_sig(SIGALRM, alrm);
- change_sig(SIGPROF, prof);
-
- arch_switch_to_tt(prev_sched, current);
-
- flush_tlb_all();
- local_irq_restore(flags);
-}
-
-void release_thread_tt(struct task_struct *task)
-{
- int pid = task->thread.mode.tt.extern_pid;
-
- /*
- * We first have to kill the other process, before
- * closing its switch_pipe. Else it might wake up
- * and receive "EOF" before we could kill it.
- */
- if(os_getpid() != pid)
- os_kill_process(pid, 0);
-
- os_close_file(task->thread.mode.tt.switch_pipe[0]);
- os_close_file(task->thread.mode.tt.switch_pipe[1]);
- /* use switch_pipe as flag: thread is released */
- task->thread.mode.tt.switch_pipe[0] = -1;
-}
-
-void suspend_new_thread(int fd)
-{
- int err;
- char c;
-
- os_stop_process(os_getpid());
- err = os_read_file(fd, &c, sizeof(c));
- if(err != sizeof(c))
- panic("read failed in suspend_new_thread, err = %d", -err);
-}
-
-void schedule_tail(struct task_struct *prev);
-
-static void new_thread_handler(int sig)
-{
- unsigned long disable;
- int (*fn)(void *);
- void *arg;
-
- fn = current->thread.request.u.thread.proc;
- arg = current->thread.request.u.thread.arg;
-
- UPT_SC(&current->thread.regs.regs) = (void *) (&sig + 1);
- disable = (1 << (SIGVTALRM - 1)) | (1 << (SIGALRM - 1)) |
- (1 << (SIGIO - 1)) | (1 << (SIGPROF - 1));
- SC_SIGMASK(UPT_SC(&current->thread.regs.regs)) &= ~disable;
-
- suspend_new_thread(current->thread.mode.tt.switch_pipe[0]);
-
- force_flush_all();
- if(current->thread.prev_sched != NULL)
- schedule_tail(current->thread.prev_sched);
- current->thread.prev_sched = NULL;
-
- init_new_thread_signals();
- enable_timer();
- free_page(current->thread.temp_stack);
- set_cmdline("(kernel thread)");
-
- change_sig(SIGUSR1, 1);
- change_sig(SIGPROF, 1);
- local_irq_enable();
- if(!run_kernel_thread(fn, arg, &current->thread.exec_buf))
- do_exit(0);
-
- /* XXX No set_user_mode here because a newly execed process will
- * immediately segfault on its non-existent IP, coming straight back
- * to the signal handler, which will call set_user_mode on its way
- * out. This should probably change since it's confusing.
- */
-}
-
-static int new_thread_proc(void *stack)
-{
- /* local_irq_disable is needed to block out signals until this thread is
- * properly scheduled. Otherwise, the tracing thread will get mighty
- * upset about any signals that arrive before that.
- * This has the complication that it sets the saved signal mask in
- * the sigcontext to block signals. This gets restored when this
- * thread (or a descendant, since they get a copy of this sigcontext)
- * returns to userspace.
- * So, this is compensated for elsewhere.
- * XXX There is still a small window until local_irq_disable() actually
- * finishes where signals are possible - shouldn't be a problem in
- * practice since SIGIO hasn't been forwarded here yet, and the
- * local_irq_disable should finish before a SIGVTALRM has time to be
- * delivered.
- */
-
- local_irq_disable();
- init_new_thread_stack(stack, new_thread_handler);
- os_usr1_process(os_getpid());
- change_sig(SIGUSR1, 1);
- return(0);
-}
-
-/* Signal masking - signals are blocked at the start of fork_tramp. They
- * are re-enabled when finish_fork_handler is entered by fork_tramp hitting
- * itself with a SIGUSR1. set_user_mode has to be run with SIGUSR1 off,
- * so it is blocked before it's called. They are re-enabled on sigreturn
- * despite the fact that they were blocked when the SIGUSR1 was issued because
- * copy_thread copies the parent's sigcontext, including the signal mask
- * onto the signal frame.
- */
-
-void finish_fork_handler(int sig)
-{
- UPT_SC(&current->thread.regs.regs) = (void *) (&sig + 1);
- suspend_new_thread(current->thread.mode.tt.switch_pipe[0]);
-
- force_flush_all();
- if(current->thread.prev_sched != NULL)
- schedule_tail(current->thread.prev_sched);
- current->thread.prev_sched = NULL;
-
- enable_timer();
- change_sig(SIGVTALRM, 1);
- local_irq_enable();
- if(current->mm != current->parent->mm)
- protect_memory(uml_reserved, high_physmem - uml_reserved, 1,
- 1, 0, 1);
- stack_protections((unsigned long) current_thread);
-
- free_page(current->thread.temp_stack);
- local_irq_disable();
- change_sig(SIGUSR1, 0);
- set_user_mode(current);
-}
-
-int fork_tramp(void *stack)
-{
- local_irq_disable();
- arch_init_thread();
- init_new_thread_stack(stack, finish_fork_handler);
-
- os_usr1_process(os_getpid());
- change_sig(SIGUSR1, 1);
- return(0);
-}
-
-int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp,
- unsigned long stack_top, struct task_struct * p,
- struct pt_regs *regs)
-{
- int (*tramp)(void *);
- int new_pid, err;
- unsigned long stack;
-
- if(current->thread.forking)
- tramp = fork_tramp;
- else {
- tramp = new_thread_proc;
- p->thread.request.u.thread = current->thread.request.u.thread;
- }
-
- err = os_pipe(p->thread.mode.tt.switch_pipe, 1, 1);
- if(err < 0){
- printk("copy_thread : pipe failed, err = %d\n", -err);
- return(err);
- }
-
- stack = alloc_stack(0, 0);
- if(stack == 0){
- printk(KERN_ERR "copy_thread : failed to allocate "
- "temporary stack\n");
- return(-ENOMEM);
- }
-
- clone_flags &= CLONE_VM;
- p->thread.temp_stack = stack;
- new_pid = start_fork_tramp(task_stack_page(p), stack, clone_flags, tramp);
- if(new_pid < 0){
- printk(KERN_ERR "copy_thread : clone failed - errno = %d\n",
- -new_pid);
- return(new_pid);
- }
-
- if(current->thread.forking){
- sc_to_sc(UPT_SC(&p->thread.regs.regs), UPT_SC(&regs->regs));
- SC_SET_SYSCALL_RETURN(UPT_SC(&p->thread.regs.regs), 0);
- if(sp != 0)
- SC_SP(UPT_SC(&p->thread.regs.regs)) = sp;
- }
- p->thread.mode.tt.extern_pid = new_pid;
-
- current->thread.request.op = OP_FORK;
- current->thread.request.u.fork.pid = new_pid;
- os_usr1_process(os_getpid());
-
- /* Enable the signal and then disable it to ensure that it is handled
- * here, and nowhere else.
- */
- change_sig(SIGUSR1, 1);
-
- change_sig(SIGUSR1, 0);
- err = 0;
- return(err);
-}
-
-void reboot_tt(void)
-{
- current->thread.request.op = OP_REBOOT;
- os_usr1_process(os_getpid());
- change_sig(SIGUSR1, 1);
-}
-
-void halt_tt(void)
-{
- current->thread.request.op = OP_HALT;
- os_usr1_process(os_getpid());
- change_sig(SIGUSR1, 1);
-}
-
-void kill_off_processes_tt(void)
-{
- struct task_struct *p;
- int me;
-
- me = os_getpid();
- for_each_process(p){
- if(p->thread.mode.tt.extern_pid != me)
- os_kill_process(p->thread.mode.tt.extern_pid, 0);
- }
- if(init_task.thread.mode.tt.extern_pid != me)
- os_kill_process(init_task.thread.mode.tt.extern_pid, 0);
-}
-
-void initial_thread_cb_tt(void (*proc)(void *), void *arg)
-{
- if(os_getpid() == tracing_pid){
- (*proc)(arg);
- }
- else {
- current->thread.request.op = OP_CB;
- current->thread.request.u.cb.proc = proc;
- current->thread.request.u.cb.arg = arg;
- os_usr1_process(os_getpid());
- change_sig(SIGUSR1, 1);
-
- change_sig(SIGUSR1, 0);
- }
-}
-
-int do_proc_op(void *t, int proc_id)
-{
- struct task_struct *task;
- struct thread_struct *thread;
- int op, pid;
-
- task = t;
- thread = &task->thread;
- op = thread->request.op;
- switch(op){
- case OP_NONE:
- case OP_TRACE_ON:
- break;
- case OP_EXEC:
- pid = thread->request.u.exec.pid;
- do_exec(thread->mode.tt.extern_pid, pid);
- thread->mode.tt.extern_pid = pid;
- cpu_tasks[task_thread_info(task)->cpu].pid = pid;
- break;
- case OP_FORK:
- attach_process(thread->request.u.fork.pid);
- break;
- case OP_CB:
- (*thread->request.u.cb.proc)(thread->request.u.cb.arg);
- break;
- case OP_REBOOT:
- case OP_HALT:
- break;
- default:
- tracer_panic("Bad op in do_proc_op");
- break;
- }
- thread->request.op = OP_NONE;
- return(op);
-}
-
-void init_idle_tt(void)
-{
- default_idle();
-}
-
-extern void start_kernel(void);
-
-static int start_kernel_proc(void *unused)
-{
- int pid;
-
- block_signals();
- pid = os_getpid();
-
- cpu_tasks[0].pid = pid;
- cpu_tasks[0].task = current;
-#ifdef CONFIG_SMP
- cpu_online_map = cpumask_of_cpu(0);
-#endif
- if(debug) os_stop_process(pid);
- start_kernel();
- return(0);
-}
-
-void set_tracing(void *task, int tracing)
-{
- ((struct task_struct *) task)->thread.mode.tt.tracing = tracing;
-}
-
-int is_tracing(void *t)
-{
- return (((struct task_struct *) t)->thread.mode.tt.tracing);
-}
-
-int set_user_mode(void *t)
-{
- struct task_struct *task;
-
- task = t ? t : current;
- if(task->thread.mode.tt.tracing)
- return(1);
- task->thread.request.op = OP_TRACE_ON;
- os_usr1_process(os_getpid());
- return(0);
-}
-
-void set_init_pid(int pid)
-{
- int err;
-
- init_task.thread.mode.tt.extern_pid = pid;
- err = os_pipe(init_task.thread.mode.tt.switch_pipe, 1, 1);
- if(err)
- panic("Can't create switch pipe for init_task, errno = %d",
- -err);
-}
-
-int start_uml_tt(void)
-{
- void *sp;
- int pages;
-
- pages = (1 << CONFIG_KERNEL_STACK_ORDER);
- sp = task_stack_page(&init_task) +
- pages * PAGE_SIZE - sizeof(unsigned long);
- return(tracer(start_kernel_proc, sp));
-}
-
-int external_pid_tt(struct task_struct *task)
-{
- return(task->thread.mode.tt.extern_pid);
-}
-
-int thread_pid_tt(struct task_struct *task)
-{
- return(task->thread.mode.tt.extern_pid);
-}
-
-int is_valid_pid(int pid)
-{
- struct task_struct *task;
-
- read_lock(&tasklist_lock);
- for_each_process(task){
- if(task->thread.mode.tt.extern_pid == pid){
- read_unlock(&tasklist_lock);
- return(1);
- }
- }
- read_unlock(&tasklist_lock);
- return(0);
-}
diff --git a/arch/um/kernel/tt/ptproxy/Makefile b/arch/um/kernel/tt/ptproxy/Makefile
deleted file mode 100644
index 3ad5b774de59..000000000000
--- a/arch/um/kernel/tt/ptproxy/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-#
-# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-# Licensed under the GPL
-#
-
-obj-y = proxy.o ptrace.o sysdep.o wait.o
-
-USER_OBJS := $(obj-y)
-
-include arch/um/scripts/Makefile.rules
diff --git a/arch/um/kernel/tt/ptproxy/proxy.c b/arch/um/kernel/tt/ptproxy/proxy.c
deleted file mode 100644
index 420c23f311f3..000000000000
--- a/arch/um/kernel/tt/ptproxy/proxy.c
+++ /dev/null
@@ -1,377 +0,0 @@
-/**********************************************************************
-proxy.c
-
-Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
-terms and conditions.
-
-Jeff Dike (jdike@karaya.com) : Modified for integration into uml
-**********************************************************************/
-
-/* XXX This file shouldn't refer to CONFIG_* */
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <signal.h>
-#include <string.h>
-#include <termios.h>
-#include <sys/wait.h>
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <asm/unistd.h>
-#include "ptrace_user.h"
-
-#include "ptproxy.h"
-#include "sysdep.h"
-#include "wait.h"
-
-#include "user.h"
-#include "os.h"
-#include "tempfile.h"
-
-static int debugger_wait(debugger_state *debugger, int *status, int options,
- int (*syscall)(debugger_state *debugger, pid_t child),
- int (*normal_return)(debugger_state *debugger,
- pid_t unused),
- int (*wait_return)(debugger_state *debugger,
- pid_t unused))
-{
- if(debugger->real_wait){
- debugger->handle_trace = normal_return;
- syscall_continue(debugger->pid);
- debugger->real_wait = 0;
- return(1);
- }
- debugger->wait_status_ptr = status;
- debugger->wait_options = options;
- if((debugger->debugee != NULL) && debugger->debugee->event){
- syscall_continue(debugger->pid);
- wait_for_stop(debugger->pid, SIGTRAP, PTRACE_SYSCALL,
- NULL);
- (*wait_return)(debugger, -1);
- return(0);
- }
- else if(debugger->wait_options & WNOHANG){
- syscall_cancel(debugger->pid, 0);
- debugger->handle_trace = syscall;
- return(0);
- }
- else {
- syscall_pause(debugger->pid);
- debugger->handle_trace = wait_return;
- debugger->waiting = 1;
- }
- return(1);
-}
-
-/*
- * Handle debugger trap, i.e. syscall.
- */
-
-int debugger_syscall(debugger_state *debugger, pid_t child)
-{
- long arg1, arg2, arg3, arg4, arg5, result;
- int syscall, ret = 0;
-
- syscall = get_syscall(debugger->pid, &arg1, &arg2, &arg3, &arg4,
- &arg5);
-
- switch(syscall){
- case __NR_execve:
- /* execve never returns */
- debugger->handle_trace = debugger_syscall;
- break;
-
- case __NR_ptrace:
- if(debugger->debugee->pid != 0) arg2 = debugger->debugee->pid;
- if(!debugger->debugee->in_context)
- child = debugger->debugee->pid;
- result = proxy_ptrace(debugger, arg1, arg2, arg3, arg4, child,
- &ret);
- syscall_cancel(debugger->pid, result);
- debugger->handle_trace = debugger_syscall;
- return(ret);
-
-#ifdef __NR_waitpid
- case __NR_waitpid:
-#endif
- case __NR_wait4:
- if(!debugger_wait(debugger, (int *) arg2, arg3,
- debugger_syscall, debugger_normal_return,
- proxy_wait_return))
- return(0);
- break;
-
- case __NR_kill:
- if(!debugger->debugee->in_context)
- child = debugger->debugee->pid;
- if(arg1 == debugger->debugee->pid){
- result = kill(child, arg2);
- syscall_cancel(debugger->pid, result);
- debugger->handle_trace = debugger_syscall;
- return(0);
- }
- else debugger->handle_trace = debugger_normal_return;
- break;
-
- default:
- debugger->handle_trace = debugger_normal_return;
- }
-
- syscall_continue(debugger->pid);
- return(0);
-}
-
-/* Used by the tracing thread */
-static debugger_state parent;
-static int parent_syscall(debugger_state *debugger, int pid);
-
-int init_parent_proxy(int pid)
-{
- parent = ((debugger_state) { .pid = pid,
- .wait_options = 0,
- .wait_status_ptr = NULL,
- .waiting = 0,
- .real_wait = 0,
- .expecting_child = 0,
- .handle_trace = parent_syscall,
- .debugee = NULL } );
- return(0);
-}
-
-int parent_normal_return(debugger_state *debugger, pid_t unused)
-{
- debugger->handle_trace = parent_syscall;
- syscall_continue(debugger->pid);
- return(0);
-}
-
-static int parent_syscall(debugger_state *debugger, int pid)
-{
- long arg1, arg2, arg3, arg4, arg5;
- int syscall;
-
- syscall = get_syscall(pid, &arg1, &arg2, &arg3, &arg4, &arg5);
-
- if((syscall == __NR_wait4)
-#ifdef __NR_waitpid
- || (syscall == __NR_waitpid)
-#endif
- ){
- debugger_wait(&parent, (int *) arg2, arg3, parent_syscall,
- parent_normal_return, parent_wait_return);
- }
- else ptrace(PTRACE_SYSCALL, pid, 0, 0);
- return(0);
-}
-
-int debugger_normal_return(debugger_state *debugger, pid_t unused)
-{
- debugger->handle_trace = debugger_syscall;
- syscall_continue(debugger->pid);
- return(0);
-}
-
-void debugger_cancelled_return(debugger_state *debugger, int result)
-{
- debugger->handle_trace = debugger_syscall;
- syscall_set_result(debugger->pid, result);
- syscall_continue(debugger->pid);
-}
-
-/* Used by the tracing thread */
-static debugger_state debugger;
-static debugee_state debugee;
-
-void init_proxy (pid_t debugger_pid, int stopped, int status)
-{
- debugger.pid = debugger_pid;
- debugger.handle_trace = debugger_syscall;
- debugger.debugee = &debugee;
- debugger.waiting = 0;
- debugger.real_wait = 0;
- debugger.expecting_child = 0;
-
- debugee.pid = 0;
- debugee.traced = 0;
- debugee.stopped = stopped;
- debugee.event = 0;
- debugee.zombie = 0;
- debugee.died = 0;
- debugee.wait_status = status;
- debugee.in_context = 1;
-}
-
-int debugger_proxy(int status, int pid)
-{
- int ret = 0, sig;
-
- if(WIFSTOPPED(status)){
- sig = WSTOPSIG(status);
- if (sig == SIGTRAP)
- ret = (*debugger.handle_trace)(&debugger, pid);
-
- else if(sig == SIGCHLD){
- if(debugger.expecting_child){
- ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig);
- debugger.expecting_child = 0;
- }
- else if(debugger.waiting)
- real_wait_return(&debugger);
- else {
- ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig);
- debugger.real_wait = 1;
- }
- }
- else ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig);
- }
- else if(WIFEXITED(status)){
- tracer_panic("debugger (pid %d) exited with status %d",
- debugger.pid, WEXITSTATUS(status));
- }
- else if(WIFSIGNALED(status)){
- tracer_panic("debugger (pid %d) exited with signal %d",
- debugger.pid, WTERMSIG(status));
- }
- else {
- tracer_panic("proxy got unknown status (0x%x) on debugger "
- "(pid %d)", status, debugger.pid);
- }
- return(ret);
-}
-
-void child_proxy(pid_t pid, int status)
-{
- debugee.event = 1;
- debugee.wait_status = status;
-
- if(WIFSTOPPED(status)){
- debugee.stopped = 1;
- debugger.expecting_child = 1;
- kill(debugger.pid, SIGCHLD);
- }
- else if(WIFEXITED(status) || WIFSIGNALED(status)){
- debugee.zombie = 1;
- debugger.expecting_child = 1;
- kill(debugger.pid, SIGCHLD);
- }
- else panic("proxy got unknown status (0x%x) on child (pid %d)",
- status, pid);
-}
-
-void debugger_parent_signal(int status, int pid)
-{
- int sig;
-
- if(WIFSTOPPED(status)){
- sig = WSTOPSIG(status);
- if(sig == SIGTRAP) (*parent.handle_trace)(&parent, pid);
- else ptrace(PTRACE_SYSCALL, pid, 0, sig);
- }
-}
-
-void fake_child_exit(void)
-{
- int status, pid;
-
- child_proxy(1, W_EXITCODE(0, 0));
- while(debugger.waiting == 1){
- CATCH_EINTR(pid = waitpid(debugger.pid, &status, WUNTRACED));
- if(pid != debugger.pid){
- printk("fake_child_exit - waitpid failed, "
- "errno = %d\n", errno);
- return;
- }
- debugger_proxy(status, debugger.pid);
- }
- CATCH_EINTR(pid = waitpid(debugger.pid, &status, WUNTRACED));
- if(pid != debugger.pid){
- printk("fake_child_exit - waitpid failed, "
- "errno = %d\n", errno);
- return;
- }
- if(ptrace(PTRACE_DETACH, debugger.pid, 0, SIGCONT) < 0)
- printk("fake_child_exit - PTRACE_DETACH failed, errno = %d\n",
- errno);
-}
-
-char gdb_init_string[] =
-"att 1 \n\
-b panic \n\
-b stop \n\
-handle SIGWINCH nostop noprint pass \n\
-";
-
-int start_debugger(char *prog, int startup, int stop, int *fd_out)
-{
- int slave, child;
-
- slave = open_gdb_chan();
- child = fork();
- if(child == 0){
- char *tempname = NULL;
- int fd;
-
- if(setsid() < 0) perror("setsid");
- if((dup2(slave, 0) < 0) || (dup2(slave, 1) < 0) ||
- (dup2(slave, 2) < 0)){
- printk("start_debugger : dup2 failed, errno = %d\n",
- errno);
- exit(1);
- }
- if(ioctl(0, TIOCSCTTY, 0) < 0){
- printk("start_debugger : TIOCSCTTY failed, "
- "errno = %d\n", errno);
- exit(1);
- }
- if(tcsetpgrp (1, os_getpid()) < 0){
- printk("start_debugger : tcsetpgrp failed, "
- "errno = %d\n", errno);
-#ifdef notdef
- exit(1);
-#endif
- }
- fd = make_tempfile("/tmp/gdb_init-XXXXXX", &tempname, 0);
- if(fd < 0){
- printk("start_debugger : make_tempfile failed,"
- "err = %d\n", -fd);
- exit(1);
- }
- os_write_file(fd, gdb_init_string,
- sizeof(gdb_init_string) - 1);
- if(startup){
- if(stop){
- os_write_file(fd, "b start_kernel\n",
- strlen("b start_kernel\n"));
- }
- os_write_file(fd, "c\n", strlen("c\n"));
- }
- if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){
- printk("start_debugger : PTRACE_TRACEME failed, "
- "errno = %d\n", errno);
- exit(1);
- }
- execlp("gdb", "gdb", "--command", tempname, prog, NULL);
- printk("start_debugger : exec of gdb failed, errno = %d\n",
- errno);
- }
- if(child < 0){
- printk("start_debugger : fork for gdb failed, errno = %d\n",
- errno);
- return(-1);
- }
- *fd_out = slave;
- return(child);
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/tt/ptproxy/ptproxy.h b/arch/um/kernel/tt/ptproxy/ptproxy.h
deleted file mode 100644
index 5eb0285b1968..000000000000
--- a/arch/um/kernel/tt/ptproxy/ptproxy.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/**********************************************************************
-ptproxy.h
-
-Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
-terms and conditions.
-**********************************************************************/
-
-#ifndef __PTPROXY_H
-#define __PTPROXY_H
-
-#include <sys/types.h>
-
-typedef struct debugger debugger_state;
-typedef struct debugee debugee_state;
-
-struct debugger
-{
- pid_t pid;
- int wait_options;
- int *wait_status_ptr;
- unsigned int waiting : 1;
- unsigned int real_wait : 1;
- unsigned int expecting_child : 1;
- int (*handle_trace) (debugger_state *, pid_t);
-
- debugee_state *debugee;
-};
-
-struct debugee
-{
- pid_t pid;
- int wait_status;
- unsigned int died : 1;
- unsigned int event : 1;
- unsigned int stopped : 1;
- unsigned int trace_singlestep : 1;
- unsigned int trace_syscall : 1;
- unsigned int traced : 1;
- unsigned int zombie : 1;
- unsigned int in_context : 1;
-};
-
-extern int debugger_syscall(debugger_state *debugger, pid_t pid);
-extern int debugger_normal_return (debugger_state *debugger, pid_t unused);
-
-extern long proxy_ptrace (struct debugger *, int, pid_t, long, long, pid_t,
- int *strace_out);
-extern void debugger_cancelled_return(debugger_state *debugger, int result);
-
-#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/tt/ptproxy/ptrace.c b/arch/um/kernel/tt/ptproxy/ptrace.c
deleted file mode 100644
index 4b4f6179b212..000000000000
--- a/arch/um/kernel/tt/ptproxy/ptrace.c
+++ /dev/null
@@ -1,237 +0,0 @@
-/**********************************************************************
-ptrace.c
-
-Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
-terms and conditions.
-
-Jeff Dike (jdike@karaya.com) : Modified for integration into uml
-**********************************************************************/
-
-#include <errno.h>
-#include <unistd.h>
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-
-#include "ptproxy.h"
-#include "debug.h"
-#include "kern_util.h"
-#include "ptrace_user.h"
-#include "tt.h"
-#include "os.h"
-
-long proxy_ptrace(struct debugger *debugger, int arg1, pid_t arg2,
- long arg3, long arg4, pid_t child, int *ret)
-{
- sigset_t relay;
- long result;
- int status;
-
- *ret = 0;
- if(debugger->debugee->died) return(-ESRCH);
-
- switch(arg1){
- case PTRACE_ATTACH:
- if(debugger->debugee->traced) return(-EPERM);
-
- debugger->debugee->pid = arg2;
- debugger->debugee->traced = 1;
-
- if(is_valid_pid(arg2) && (arg2 != child)){
- debugger->debugee->in_context = 0;
- kill(arg2, SIGSTOP);
- debugger->debugee->event = 1;
- debugger->debugee->wait_status = W_STOPCODE(SIGSTOP);
- }
- else {
- debugger->debugee->in_context = 1;
- if(debugger->debugee->stopped)
- child_proxy(child, W_STOPCODE(SIGSTOP));
- else kill(child, SIGSTOP);
- }
-
- return(0);
-
- case PTRACE_DETACH:
- if(!debugger->debugee->traced) return(-EPERM);
-
- debugger->debugee->traced = 0;
- debugger->debugee->pid = 0;
- if(!debugger->debugee->in_context)
- kill(child, SIGCONT);
-
- return(0);
-
- case PTRACE_CONT:
- if(!debugger->debugee->in_context) return(-EPERM);
- *ret = PTRACE_CONT;
- return(ptrace(PTRACE_CONT, child, arg3, arg4));
-
-#ifdef UM_HAVE_GETFPREGS
- case PTRACE_GETFPREGS:
- {
- long regs[FP_FRAME_SIZE];
- int i, result;
-
- result = ptrace(PTRACE_GETFPREGS, child, 0, regs);
- if(result == -1) return(-errno);
-
- for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
- ptrace(PTRACE_POKEDATA, debugger->pid, arg4 + 4 * i,
- regs[i]);
- return(result);
- }
-#endif
-
-#ifdef UM_HAVE_GETFPXREGS
- case PTRACE_GETFPXREGS:
- {
- long regs[FPX_FRAME_SIZE];
- int i, result;
-
- result = ptrace(PTRACE_GETFPXREGS, child, 0, regs);
- if(result == -1) return(-errno);
-
- for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
- ptrace(PTRACE_POKEDATA, debugger->pid, arg4 + 4 * i,
- regs[i]);
- return(result);
- }
-#endif
-
-#ifdef UM_HAVE_GETREGS
- case PTRACE_GETREGS:
- {
- long regs[FRAME_SIZE];
- int i, result;
-
- result = ptrace(PTRACE_GETREGS, child, 0, regs);
- if(result == -1) return(-errno);
-
- for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
- ptrace (PTRACE_POKEDATA, debugger->pid,
- arg4 + 4 * i, regs[i]);
- return(result);
- }
- break;
-#endif
-
- case PTRACE_KILL:
- result = ptrace(PTRACE_KILL, child, arg3, arg4);
- if(result == -1) return(-errno);
-
- return(result);
-
- case PTRACE_PEEKDATA:
- case PTRACE_PEEKTEXT:
- case PTRACE_PEEKUSR:
- /* The value being read out could be -1, so we have to
- * check errno to see if there's an error, and zero it
- * beforehand so we're not faked out by an old error
- */
-
- errno = 0;
- result = ptrace(arg1, child, arg3, 0);
- if((result == -1) && (errno != 0)) return(-errno);
-
- result = ptrace(PTRACE_POKEDATA, debugger->pid, arg4, result);
- if(result == -1) return(-errno);
-
- return(result);
-
- case PTRACE_POKEDATA:
- case PTRACE_POKETEXT:
- case PTRACE_POKEUSR:
- result = ptrace(arg1, child, arg3, arg4);
- if(result == -1) return(-errno);
-
- if(arg1 == PTRACE_POKEUSR) ptrace_pokeuser(arg3, arg4);
- return(result);
-
-#ifdef UM_HAVE_SETFPREGS
- case PTRACE_SETFPREGS:
- {
- long regs[FP_FRAME_SIZE];
- int i;
-
- for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
- regs[i] = ptrace (PTRACE_PEEKDATA, debugger->pid,
- arg4 + 4 * i, 0);
- result = ptrace(PTRACE_SETFPREGS, child, 0, regs);
- if(result == -1) return(-errno);
-
- return(result);
- }
-#endif
-
-#ifdef UM_HAVE_SETFPXREGS
- case PTRACE_SETFPXREGS:
- {
- long regs[FPX_FRAME_SIZE];
- int i;
-
- for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
- regs[i] = ptrace (PTRACE_PEEKDATA, debugger->pid,
- arg4 + 4 * i, 0);
- result = ptrace(PTRACE_SETFPXREGS, child, 0, regs);
- if(result == -1) return(-errno);
-
- return(result);
- }
-#endif
-
-#ifdef UM_HAVE_SETREGS
- case PTRACE_SETREGS:
- {
- long regs[FRAME_SIZE];
- int i;
-
- for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
- regs[i] = ptrace(PTRACE_PEEKDATA, debugger->pid,
- arg4 + 4 * i, 0);
- result = ptrace(PTRACE_SETREGS, child, 0, regs);
- if(result == -1) return(-errno);
-
- return(result);
- }
-#endif
-
- case PTRACE_SINGLESTEP:
- if(!debugger->debugee->in_context) return(-EPERM);
- sigemptyset(&relay);
- sigaddset(&relay, SIGSEGV);
- sigaddset(&relay, SIGILL);
- sigaddset(&relay, SIGBUS);
- result = ptrace(PTRACE_SINGLESTEP, child, arg3, arg4);
- if(result == -1) return(-errno);
-
- status = wait_for_stop(child, SIGTRAP, PTRACE_SINGLESTEP,
- &relay);
- child_proxy(child, status);
- return(result);
-
- case PTRACE_SYSCALL:
- if(!debugger->debugee->in_context) return(-EPERM);
- result = ptrace(PTRACE_SYSCALL, child, arg3, arg4);
- if(result == -1) return(-errno);
-
- *ret = PTRACE_SYSCALL;
- return(result);
-
- case PTRACE_TRACEME:
- default:
- return(-EINVAL);
- }
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/tt/ptproxy/sysdep.c b/arch/um/kernel/tt/ptproxy/sysdep.c
deleted file mode 100644
index e0e1ab0588ad..000000000000
--- a/arch/um/kernel/tt/ptproxy/sysdep.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/**********************************************************************
-sysdep.c
-
-Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
-terms and conditions.
-**********************************************************************/
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <linux/unistd.h>
-#include "ptrace_user.h"
-#include "user.h"
-#include "os.h"
-
-int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3, long *arg4,
- long *arg5)
-{
- *arg1 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG1_OFFSET, 0);
- *arg2 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG2_OFFSET, 0);
- *arg3 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG3_OFFSET, 0);
- *arg4 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG4_OFFSET, 0);
- *arg5 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG5_OFFSET, 0);
- return(ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET, 0));
-}
-
-void syscall_cancel(pid_t pid, int result)
-{
- if((ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
- __NR_getpid) < 0) ||
- (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) ||
- (wait_for_stop(pid, SIGTRAP, PTRACE_SYSCALL, NULL) < 0) ||
- (ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, result) < 0) ||
- (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0))
- printk("ptproxy: couldn't cancel syscall: errno = %d\n",
- errno);
-}
-
-void syscall_set_result(pid_t pid, long result)
-{
- ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, result);
-}
-
-void syscall_continue(pid_t pid)
-{
- ptrace(PTRACE_SYSCALL, pid, 0, 0);
-}
-
-int syscall_pause(pid_t pid)
-{
- if(ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, __NR_pause) < 0){
- printk("syscall_change - ptrace failed, errno = %d\n", errno);
- return(-1);
- }
- return(0);
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/tt/ptproxy/sysdep.h b/arch/um/kernel/tt/ptproxy/sysdep.h
deleted file mode 100644
index 735f488049aa..000000000000
--- a/arch/um/kernel/tt/ptproxy/sysdep.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/**********************************************************************
-sysdep.h
-
-Copyright (C) 1999 Lars Brinkhoff.
-Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
-See the file COPYING for licensing terms and conditions.
-**********************************************************************/
-
-extern int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3,
- long *arg4, long *arg5);
-extern void syscall_cancel (pid_t pid, long result);
-extern void syscall_set_result (pid_t pid, long result);
-extern void syscall_continue (pid_t pid);
-extern int syscall_pause(pid_t pid);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/tt/ptproxy/wait.c b/arch/um/kernel/tt/ptproxy/wait.c
deleted file mode 100644
index bdd4af4b65fc..000000000000
--- a/arch/um/kernel/tt/ptproxy/wait.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/**********************************************************************
-wait.c
-
-Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
-terms and conditions.
-
-**********************************************************************/
-
-#include <errno.h>
-#include <signal.h>
-#include <sys/wait.h>
-
-#include "ptproxy.h"
-#include "sysdep.h"
-#include "wait.h"
-#include "ptrace_user.h"
-#include "sysdep/ptrace.h"
-#include "sysdep/sigcontext.h"
-
-int proxy_wait_return(struct debugger *debugger, pid_t unused)
-{
- debugger->waiting = 0;
-
- if(debugger->debugee->died || (debugger->wait_options & __WCLONE)){
- debugger_cancelled_return(debugger, -ECHILD);
- return(0);
- }
-
- if(debugger->debugee->zombie && debugger->debugee->event)
- debugger->debugee->died = 1;
-
- if(debugger->debugee->event){
- debugger->debugee->event = 0;
- ptrace(PTRACE_POKEDATA, debugger->pid,
- debugger->wait_status_ptr,
- debugger->debugee->wait_status);
- /* if (wait4)
- ptrace (PTRACE_POKEDATA, pid, rusage_ptr, ...); */
- debugger_cancelled_return(debugger, debugger->debugee->pid);
- return(0);
- }
-
- /* pause will return -EINTR, which happens to be right for wait */
- debugger_normal_return(debugger, -1);
- return(0);
-}
-
-int parent_wait_return(struct debugger *debugger, pid_t unused)
-{
- return(debugger_normal_return(debugger, -1));
-}
-
-int real_wait_return(struct debugger *debugger)
-{
- unsigned long ip;
- int pid;
-
- pid = debugger->pid;
-
- ip = ptrace(PTRACE_PEEKUSR, pid, PT_IP_OFFSET, 0);
- IP_RESTART_SYSCALL(ip);
-
- if(ptrace(PTRACE_POKEUSR, pid, PT_IP_OFFSET, ip) < 0)
- tracer_panic("real_wait_return : Failed to restart system "
- "call, errno = %d\n", errno);
-
- if((ptrace(PTRACE_SYSCALL, debugger->pid, 0, SIGCHLD) < 0) ||
- (ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) ||
- (ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) ||
- debugger_normal_return(debugger, -1))
- tracer_panic("real_wait_return : gdb failed to wait, "
- "errno = %d\n", errno);
- return(0);
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/tt/ptproxy/wait.h b/arch/um/kernel/tt/ptproxy/wait.h
deleted file mode 100644
index 542e73ee2cee..000000000000
--- a/arch/um/kernel/tt/ptproxy/wait.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/**********************************************************************
-wait.h
-
-Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
-terms and conditions.
-**********************************************************************/
-
-#ifndef __PTPROXY_WAIT_H
-#define __PTPROXY_WAIT_H
-
-extern int proxy_wait_return(struct debugger *debugger, pid_t unused);
-extern int real_wait_return(struct debugger *debugger);
-extern int parent_wait_return(struct debugger *debugger, pid_t unused);
-
-#endif
diff --git a/arch/um/kernel/tt/syscall_kern.c b/arch/um/kernel/tt/syscall_kern.c
deleted file mode 100644
index 293caa6d0c2d..000000000000
--- a/arch/um/kernel/tt/syscall_kern.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#include "linux/types.h"
-#include "linux/utime.h"
-#include "linux/sys.h"
-#include "linux/ptrace.h"
-#include "asm/unistd.h"
-#include "asm/ptrace.h"
-#include "asm/uaccess.h"
-#include "asm/stat.h"
-#include "sysdep/syscalls.h"
-#include "sysdep/sigcontext.h"
-#include "kern_util.h"
-#include "syscall.h"
-
-void syscall_handler_tt(int sig, struct pt_regs *regs)
-{
- void *sc;
- long result;
- int syscall;
-
- sc = UPT_SC(&regs->regs);
- SC_START_SYSCALL(sc);
-
- syscall = UPT_SYSCALL_NR(&regs->regs);
- syscall_trace(&regs->regs, 0);
-
- current->thread.nsyscalls++;
- nsyscalls++;
-
- if((syscall >= NR_syscalls) || (syscall < 0))
- result = -ENOSYS;
- else result = EXECUTE_SYSCALL(syscall, regs);
-
- /* regs->sc may have changed while the system call ran (there may
- * have been an interrupt or segfault), so it needs to be refreshed.
- */
- UPT_SC(&regs->regs) = sc;
-
- SC_SET_SYSCALL_RETURN(sc, result);
-
- syscall_trace(&regs->regs, 1);
-}
diff --git a/arch/um/kernel/tt/syscall_user.c b/arch/um/kernel/tt/syscall_user.c
deleted file mode 100644
index f52b47aff1d2..000000000000
--- a/arch/um/kernel/tt/syscall_user.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <unistd.h>
-#include <signal.h>
-#include <errno.h>
-#include <asm/unistd.h>
-#include "sysdep/ptrace.h"
-#include "sigcontext.h"
-#include "ptrace_user.h"
-#include "task.h"
-#include "kern_util.h"
-#include "syscall.h"
-#include "tt.h"
-
-void do_sigtrap(void *task)
-{
- UPT_SYSCALL_NR(TASK_REGS(task)) = -1;
-}
-
-void do_syscall(void *task, int pid, int local_using_sysemu)
-{
- unsigned long proc_regs[FRAME_SIZE];
-
- if(ptrace_getregs(pid, proc_regs) < 0)
- tracer_panic("Couldn't read registers");
-
- UPT_SYSCALL_NR(TASK_REGS(task)) = PT_SYSCALL_NR(proc_regs);
-
-#ifdef UPT_ORIGGPR2
- UPT_ORIGGPR2(TASK_REGS(task)) = REGS_ORIGGPR2(proc_regs);
-#endif
-
- if(((unsigned long *) PT_IP(proc_regs) >= &_stext) &&
- ((unsigned long *) PT_IP(proc_regs) <= &_etext))
- tracer_panic("I'm tracing myself and I can't get out");
-
- /* advanced sysemu mode set syscall number to -1 automatically */
- if (local_using_sysemu==2)
- return;
-
- /* syscall number -1 in sysemu skips syscall restarting in host */
- if(ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
- local_using_sysemu ? -1 : __NR_getpid) < 0)
- tracer_panic("do_syscall : Nullifying syscall failed, "
- "errno = %d", errno);
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/tt/tlb.c b/arch/um/kernel/tt/tlb.c
deleted file mode 100644
index 7caa24fe05df..000000000000
--- a/arch/um/kernel/tt/tlb.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Copyright 2003 PathScale, Inc.
- * Licensed under the GPL
- */
-
-#include "linux/stddef.h"
-#include "linux/kernel.h"
-#include "linux/sched.h"
-#include "linux/mm.h"
-#include "asm/page.h"
-#include "asm/pgtable.h"
-#include "asm/uaccess.h"
-#include "asm/tlbflush.h"
-#include "mem_user.h"
-#include "os.h"
-#include "tlb.h"
-
-static int do_ops(union mm_context *mmu, struct host_vm_op *ops, int last,
- int finished, void **flush)
-{
- struct host_vm_op *op;
- int i, ret=0;
-
- for(i = 0; i <= last && !ret; i++){
- op = &ops[i];
- switch(op->type){
- case MMAP:
- ret = os_map_memory((void *) op->u.mmap.addr,
- op->u.mmap.fd, op->u.mmap.offset,
- op->u.mmap.len, op->u.mmap.r,
- op->u.mmap.w, op->u.mmap.x);
- break;
- case MUNMAP:
- ret = os_unmap_memory((void *) op->u.munmap.addr,
- op->u.munmap.len);
- break;
- case MPROTECT:
- ret = protect_memory(op->u.mprotect.addr,
- op->u.munmap.len,
- op->u.mprotect.r,
- op->u.mprotect.w,
- op->u.mprotect.x, 1);
- protect_memory(op->u.mprotect.addr, op->u.munmap.len,
- op->u.mprotect.r, op->u.mprotect.w,
- op->u.mprotect.x, 1);
- break;
- default:
- printk("Unknown op type %d in do_ops\n", op->type);
- break;
- }
- }
-
- return ret;
-}
-
-static void fix_range(struct mm_struct *mm, unsigned long start_addr,
- unsigned long end_addr, int force)
-{
- if((current->thread.mode.tt.extern_pid != -1) &&
- (current->thread.mode.tt.extern_pid != os_getpid()))
- panic("fix_range fixing wrong address space, current = 0x%p",
- current);
-
- fix_range_common(mm, start_addr, end_addr, force, do_ops);
-}
-
-atomic_t vmchange_seq = ATOMIC_INIT(1);
-
-void flush_tlb_kernel_range_tt(unsigned long start, unsigned long end)
-{
- if(flush_tlb_kernel_range_common(start, end))
- atomic_inc(&vmchange_seq);
-}
-
-void flush_tlb_kernel_vm_tt(void)
-{
- flush_tlb_kernel_range(start_vm, end_vm);
-}
-
-void __flush_tlb_one_tt(unsigned long addr)
-{
- flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
-}
-
-void flush_tlb_range_tt(struct vm_area_struct *vma, unsigned long start,
- unsigned long end)
-{
- if(vma->vm_mm != current->mm) return;
-
- /* Assumes that the range start ... end is entirely within
- * either process memory or kernel vm
- */
- if((start >= start_vm) && (start < end_vm)){
- if(flush_tlb_kernel_range_common(start, end))
- atomic_inc(&vmchange_seq);
- }
- else fix_range(vma->vm_mm, start, end, 0);
-}
-
-void flush_tlb_mm_tt(struct mm_struct *mm)
-{
- unsigned long seq;
-
- if(mm != current->mm) return;
-
- fix_range(mm, 0, STACK_TOP, 0);
-
- seq = atomic_read(&vmchange_seq);
- if(current->thread.mode.tt.vm_seq == seq)
- return;
- current->thread.mode.tt.vm_seq = seq;
- flush_tlb_kernel_range_common(start_vm, end_vm);
-}
-
-void force_flush_all_tt(void)
-{
- fix_range(current->mm, 0, STACK_TOP, 1);
- flush_tlb_kernel_range_common(start_vm, end_vm);
-}
diff --git a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c
deleted file mode 100644
index c23588393f6e..000000000000
--- a/arch/um/kernel/tt/tracer.c
+++ /dev/null
@@ -1,461 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <signal.h>
-#include <errno.h>
-#include <sched.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-#include "user.h"
-#include "sysdep/ptrace.h"
-#include "sigcontext.h"
-#include "sysdep/sigcontext.h"
-#include "os.h"
-#include "mem_user.h"
-#include "process.h"
-#include "kern_util.h"
-#include "chan_user.h"
-#include "ptrace_user.h"
-#include "irq_user.h"
-#include "mode.h"
-#include "tt.h"
-
-static int tracer_winch[2];
-
-int is_tracer_winch(int pid, int fd, void *data)
-{
- if(pid != os_getpgrp())
- return(0);
-
- register_winch_irq(tracer_winch[0], fd, -1, data);
- return(1);
-}
-
-static void tracer_winch_handler(int sig)
-{
- int n;
- char c = 1;
-
- n = os_write_file(tracer_winch[1], &c, sizeof(c));
- if(n != sizeof(c))
- printk("tracer_winch_handler - write failed, err = %d\n", -n);
-}
-
-/* Called only by the tracing thread during initialization */
-
-static void setup_tracer_winch(void)
-{
- int err;
-
- err = os_pipe(tracer_winch, 1, 1);
- if(err < 0){
- printk("setup_tracer_winch : os_pipe failed, err = %d\n", -err);
- return;
- }
- signal(SIGWINCH, tracer_winch_handler);
-}
-
-void attach_process(int pid)
-{
- if((ptrace(PTRACE_ATTACH, pid, 0, 0) < 0) ||
- (ptrace(PTRACE_CONT, pid, 0, 0) < 0))
- tracer_panic("OP_FORK failed to attach pid");
- wait_for_stop(pid, SIGSTOP, PTRACE_CONT, NULL);
- if (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0)
- tracer_panic("OP_FORK: PTRACE_SETOPTIONS failed, errno = %d", errno);
- if(ptrace(PTRACE_CONT, pid, 0, 0) < 0)
- tracer_panic("OP_FORK failed to continue process");
-}
-
-void tracer_panic(char *format, ...)
-{
- va_list ap;
-
- va_start(ap, format);
- vprintf(format, ap);
- va_end(ap);
- printf("\n");
- while(1) pause();
-}
-
-static void tracer_segv(int sig, struct sigcontext sc)
-{
- struct faultinfo fi;
- GET_FAULTINFO_FROM_SC(fi, &sc);
- printf("Tracing thread segfault at address 0x%lx, ip 0x%lx\n",
- FAULT_ADDRESS(fi), SC_IP(&sc));
- while(1)
- pause();
-}
-
-/* Changed early in boot, and then only read */
-int debug = 0;
-int debug_stop = 1;
-int debug_parent = 0;
-int honeypot = 0;
-
-static int signal_tramp(void *arg)
-{
- int (*proc)(void *);
-
- if(honeypot && munmap((void *) (host_task_size - 0x10000000),
- 0x10000000))
- panic("Unmapping stack failed");
- if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0)
- panic("ptrace PTRACE_TRACEME failed");
- os_stop_process(os_getpid());
- change_sig(SIGWINCH, 0);
- signal(SIGUSR1, SIG_IGN);
- change_sig(SIGCHLD, 0);
- signal(SIGSEGV, (__sighandler_t) sig_handler);
- set_cmdline("(idle thread)");
- set_init_pid(os_getpid());
- init_irq_signals(0);
- proc = arg;
- return((*proc)(NULL));
-}
-
-static void sleeping_process_signal(int pid, int sig)
-{
- switch(sig){
- /* These two result from UML being ^Z-ed and bg-ed. PTRACE_CONT is
- * right because the process must be in the kernel already.
- */
- case SIGCONT:
- case SIGTSTP:
- if(ptrace(PTRACE_CONT, pid, 0, sig) < 0)
- tracer_panic("sleeping_process_signal : Failed to "
- "continue pid %d, signal = %d, "
- "errno = %d\n", pid, sig, errno);
- break;
-
- /* This happens when the debugger (e.g. strace) is doing system call
- * tracing on the kernel. During a context switch, the current task
- * will be set to the incoming process and the outgoing process will
- * hop into write and then read. Since it's not the current process
- * any more, the trace of those will land here. So, we need to just
- * PTRACE_SYSCALL it.
- */
- case (SIGTRAP + 0x80):
- if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
- tracer_panic("sleeping_process_signal : Failed to "
- "PTRACE_SYSCALL pid %d, errno = %d\n",
- pid, errno);
- break;
- case SIGSTOP:
- break;
- default:
- tracer_panic("sleeping process %d got unexpected "
- "signal : %d\n", pid, sig);
- break;
- }
-}
-
-/* Accessed only by the tracing thread */
-int debugger_pid = -1;
-int debugger_parent = -1;
-int debugger_fd = -1;
-int gdb_pid = -1;
-
-struct {
- int pid;
- int signal;
- unsigned long addr;
- struct timeval time;
-} signal_record[1024][32];
-
-int signal_index[32];
-int nsignals = 0;
-int debug_trace = 0;
-
-extern void signal_usr1(int sig);
-
-int tracing_pid = -1;
-
-int tracer(int (*init_proc)(void *), void *sp)
-{
- void *task = NULL;
- int status, pid = 0, sig = 0, cont_type, tracing = 0, op = 0;
- int proc_id = 0, n, err, old_tracing = 0, strace = 0;
- int local_using_sysemu = 0;
-
- signal(SIGPIPE, SIG_IGN);
- setup_tracer_winch();
- tracing_pid = os_getpid();
- printf("tracing thread pid = %d\n", tracing_pid);
-
- pid = clone(signal_tramp, sp, CLONE_FILES | SIGCHLD, init_proc);
- CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
- if(n < 0){
- printf("waitpid on idle thread failed, errno = %d\n", errno);
- exit(1);
- }
- if (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0) {
- printf("Failed to PTRACE_SETOPTIONS for idle thread, errno = %d\n", errno);
- exit(1);
- }
- if((ptrace(PTRACE_CONT, pid, 0, 0) < 0)){
- printf("Failed to continue idle thread, errno = %d\n", errno);
- exit(1);
- }
-
- signal(SIGSEGV, (sighandler_t) tracer_segv);
- signal(SIGUSR1, signal_usr1);
- if(debug_trace){
- printf("Tracing thread pausing to be attached\n");
- stop();
- }
- if(debug){
- if(gdb_pid != -1)
- debugger_pid = attach_debugger(pid, gdb_pid, 1);
- else debugger_pid = init_ptrace_proxy(pid, 1, debug_stop);
- if(debug_parent){
- debugger_parent = os_process_parent(debugger_pid);
- init_parent_proxy(debugger_parent);
- err = attach(debugger_parent);
- if(err){
- printf("Failed to attach debugger parent %d, "
- "errno = %d\n", debugger_parent, -err);
- debugger_parent = -1;
- }
- else {
- if(ptrace(PTRACE_SYSCALL, debugger_parent,
- 0, 0) < 0){
- printf("Failed to continue debugger "
- "parent, errno = %d\n", errno);
- debugger_parent = -1;
- }
- }
- }
- }
- set_cmdline("(tracing thread)");
- while(1){
- CATCH_EINTR(pid = waitpid(-1, &status, WUNTRACED));
- if(pid <= 0){
- if(errno != ECHILD){
- printf("wait failed - errno = %d\n", errno);
- }
- continue;
- }
- if(pid == debugger_pid){
- int cont = 0;
-
- if(WIFEXITED(status) || WIFSIGNALED(status))
- debugger_pid = -1;
- /* XXX Figure out how to deal with gdb and SMP */
- else cont = debugger_signal(status, cpu_tasks[0].pid);
- if(cont == PTRACE_SYSCALL) strace = 1;
- continue;
- }
- else if(pid == debugger_parent){
- debugger_parent_signal(status, pid);
- continue;
- }
- nsignals++;
- if(WIFEXITED(status)) ;
-#ifdef notdef
- {
- printf("Child %d exited with status %d\n", pid,
- WEXITSTATUS(status));
- }
-#endif
- else if(WIFSIGNALED(status)){
- sig = WTERMSIG(status);
- if(sig != 9){
- printf("Child %d exited with signal %d\n", pid,
- sig);
- }
- }
- else if(WIFSTOPPED(status)){
- proc_id = pid_to_processor_id(pid);
- sig = WSTOPSIG(status);
- if(proc_id == -1){
- sleeping_process_signal(pid, sig);
- continue;
- }
-
- task = cpu_tasks[proc_id].task;
- tracing = is_tracing(task);
- old_tracing = tracing;
-
- /* Assume: no syscall, when coming from user */
- if ( tracing )
- do_sigtrap(task);
-
- switch(sig){
- case SIGUSR1:
- sig = 0;
- op = do_proc_op(task, proc_id);
- switch(op){
- /*
- * This is called when entering user mode; after
- * this, we start intercepting syscalls.
- *
- * In fact, a process is started in kernel mode,
- * so with is_tracing() == 0 (and that is reset
- * when executing syscalls, since UML kernel has
- * the right to do syscalls);
- */
- case OP_TRACE_ON:
- arch_leave_kernel(task, pid);
- tracing = 1;
- break;
- case OP_REBOOT:
- case OP_HALT:
- unmap_physmem();
- kmalloc_ok = 0;
- os_kill_ptraced_process(pid, 0);
- /* Now let's reap remaining zombies */
- errno = 0;
- do {
- waitpid(-1, &status,
- WUNTRACED);
- } while (errno != ECHILD);
- return(op == OP_REBOOT);
- case OP_NONE:
- printf("Detaching pid %d\n", pid);
- detach(pid, SIGSTOP);
- continue;
- default:
- break;
- }
- /* OP_EXEC switches host processes on us,
- * we want to continue the new one.
- */
- pid = cpu_tasks[proc_id].pid;
- break;
- case (SIGTRAP + 0x80):
- if(!tracing && (debugger_pid != -1)){
- child_signal(pid, status & 0x7fff);
- continue;
- }
- tracing = 0;
- /* local_using_sysemu has been already set
- * below, since if we are here, is_tracing() on
- * the traced task was 1, i.e. the process had
- * already run through one iteration of the
- * loop which executed a OP_TRACE_ON request.*/
- do_syscall(task, pid, local_using_sysemu);
- sig = SIGUSR2;
- break;
- case SIGTRAP:
- if(!tracing && (debugger_pid != -1)){
- child_signal(pid, status);
- continue;
- }
- tracing = 0;
- break;
- case SIGPROF:
- if(tracing) sig = 0;
- break;
- case SIGCHLD:
- case SIGHUP:
- sig = 0;
- break;
- case SIGSEGV:
- case SIGIO:
- case SIGALRM:
- case SIGVTALRM:
- case SIGFPE:
- case SIGBUS:
- case SIGILL:
- case SIGWINCH:
-
- default:
- tracing = 0;
- break;
- }
- set_tracing(task, tracing);
-
- if(!tracing && old_tracing)
- arch_enter_kernel(task, pid);
-
- if(!tracing && (debugger_pid != -1) && (sig != 0) &&
- (sig != SIGALRM) && (sig != SIGVTALRM) &&
- (sig != SIGSEGV) && (sig != SIGTRAP) &&
- (sig != SIGUSR2) && (sig != SIGIO) &&
- (sig != SIGFPE)){
- child_signal(pid, status);
- continue;
- }
-
- local_using_sysemu = get_using_sysemu();
-
- if(tracing)
- cont_type = SELECT_PTRACE_OPERATION(local_using_sysemu,
- singlestepping(task));
- else if((debugger_pid != -1) && strace)
- cont_type = PTRACE_SYSCALL;
- else
- cont_type = PTRACE_CONT;
-
- if(ptrace(cont_type, pid, 0, sig) != 0){
- tracer_panic("ptrace failed to continue "
- "process - errno = %d\n",
- errno);
- }
- }
- }
- return(0);
-}
-
-static int __init uml_debug_setup(char *line, int *add)
-{
- char *next;
-
- debug = 1;
- *add = 0;
- if(*line != '=') return(0);
- line++;
-
- while(line != NULL){
- next = strchr(line, ',');
- if(next) *next++ = '\0';
-
- if(!strcmp(line, "go")) debug_stop = 0;
- else if(!strcmp(line, "parent")) debug_parent = 1;
- else printf("Unknown debug option : '%s'\n", line);
-
- line = next;
- }
- return(0);
-}
-
-__uml_setup("debug", uml_debug_setup,
-"debug\n"
-" Starts up the kernel under the control of gdb. See the \n"
-" kernel debugging tutorial and the debugging session pages\n"
-" at http://user-mode-linux.sourceforge.net/ for more information.\n\n"
-);
-
-static int __init uml_debugtrace_setup(char *line, int *add)
-{
- debug_trace = 1;
- return 0;
-}
-__uml_setup("debugtrace", uml_debugtrace_setup,
-"debugtrace\n"
-" Causes the tracing thread to pause until it is attached by a\n"
-" debugger and continued. This is mostly for debugging crashes\n"
-" early during boot, and should be pretty much obsoleted by\n"
-" the debug switch.\n\n"
-);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/tt/trap_user.c b/arch/um/kernel/tt/trap_user.c
deleted file mode 100644
index 3032eb5e2467..000000000000
--- a/arch/um/kernel/tt/trap_user.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <stdlib.h>
-#include <errno.h>
-#include <signal.h>
-#include "sysdep/ptrace.h"
-#include "sysdep/sigcontext.h"
-#include "kern_util.h"
-#include "task.h"
-#include "tt.h"
-#include "os.h"
-
-void sig_handler_common_tt(int sig, void *sc_ptr)
-{
- struct sigcontext *sc = sc_ptr;
- struct tt_regs save_regs, *r;
- int save_errno = errno, is_user = 0;
- void (*handler)(int, union uml_pt_regs *);
-
- /* This is done because to allow SIGSEGV to be delivered inside a SEGV
- * handler. This can happen in copy_user, and if SEGV is disabled,
- * the process will die.
- */
- if(sig == SIGSEGV)
- change_sig(SIGSEGV, 1);
-
- r = &TASK_REGS(get_current())->tt;
- if ( sig == SIGFPE || sig == SIGSEGV ||
- sig == SIGBUS || sig == SIGILL ||
- sig == SIGTRAP ) {
- GET_FAULTINFO_FROM_SC(r->faultinfo, sc);
- }
- save_regs = *r;
- if (sc)
- is_user = user_context(SC_SP(sc));
- r->sc = sc;
- if(sig != SIGUSR2)
- r->syscall = -1;
-
- handler = sig_info[sig];
-
- /* unblock SIGALRM, SIGVTALRM, SIGIO if sig isn't IRQ signal */
- if (sig != SIGIO && sig != SIGWINCH &&
- sig != SIGVTALRM && sig != SIGALRM)
- unblock_signals();
-
- handler(sig, (union uml_pt_regs *) r);
-
- if(is_user){
- interrupt_end();
- block_signals();
- set_user_mode(NULL);
- }
- *r = save_regs;
- errno = save_errno;
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/tt/uaccess.c b/arch/um/kernel/tt/uaccess.c
deleted file mode 100644
index 1cb60726567e..000000000000
--- a/arch/um/kernel/tt/uaccess.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#include "linux/sched.h"
-#include "asm/uaccess.h"
-
-int copy_from_user_tt(void *to, const void __user *from, int n)
-{
- if(!access_ok(VERIFY_READ, from, n))
- return(n);
-
- return(__do_copy_from_user(to, from, n, &current->thread.fault_addr,
- &current->thread.fault_catcher));
-}
-
-int copy_to_user_tt(void __user *to, const void *from, int n)
-{
- if(!access_ok(VERIFY_WRITE, to, n))
- return(n);
-
- return(__do_copy_to_user(to, from, n, &current->thread.fault_addr,
- &current->thread.fault_catcher));
-}
-
-int strncpy_from_user_tt(char *dst, const char __user *src, int count)
-{
- int n;
-
- if(!access_ok(VERIFY_READ, src, 1))
- return(-EFAULT);
-
- n = __do_strncpy_from_user(dst, src, count,
- &current->thread.fault_addr,
- &current->thread.fault_catcher);
- if(n < 0) return(-EFAULT);
- return(n);
-}
-
-int __clear_user_tt(void __user *mem, int len)
-{
- return(__do_clear_user(mem, len,
- &current->thread.fault_addr,
- &current->thread.fault_catcher));
-}
-
-int clear_user_tt(void __user *mem, int len)
-{
- if(!access_ok(VERIFY_WRITE, mem, len))
- return(len);
-
- return(__do_clear_user(mem, len, &current->thread.fault_addr,
- &current->thread.fault_catcher));
-}
-
-int strnlen_user_tt(const void __user *str, int len)
-{
- return(__do_strnlen_user(str, len,
- &current->thread.fault_addr,
- &current->thread.fault_catcher));
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/tt/uaccess_user.c b/arch/um/kernel/tt/uaccess_user.c
deleted file mode 100644
index 0e5c82c5e5b7..000000000000
--- a/arch/um/kernel/tt/uaccess_user.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk)
- * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <string.h>
-#include "uml_uaccess.h"
-#include "task.h"
-#include "kern_util.h"
-#include "os.h"
-#include "longjmp.h"
-
-int __do_copy_from_user(void *to, const void *from, int n,
- void **fault_addr, void **fault_catcher)
-{
- struct tt_regs save = TASK_REGS(get_current())->tt;
- unsigned long fault;
- int faulted;
-
- fault = __do_user_copy(to, from, n, fault_addr, fault_catcher,
- __do_copy, &faulted);
- TASK_REGS(get_current())->tt = save;
-
- if(!faulted)
- return 0;
- else if (fault)
- return n - (fault - (unsigned long) from);
- else
- /* In case of a general protection fault, we don't have the
- * fault address, so NULL is used instead. Pretend we didn't
- * copy anything. */
- return n;
-}
-
-static void __do_strncpy(void *dst, const void *src, int count)
-{
- strncpy(dst, src, count);
-}
-
-int __do_strncpy_from_user(char *dst, const char *src, unsigned long count,
- void **fault_addr, void **fault_catcher)
-{
- struct tt_regs save = TASK_REGS(get_current())->tt;
- unsigned long fault;
- int faulted;
-
- fault = __do_user_copy(dst, src, count, fault_addr, fault_catcher,
- __do_strncpy, &faulted);
- TASK_REGS(get_current())->tt = save;
-
- if(!faulted) return(strlen(dst));
- else return(-1);
-}
-
-static void __do_clear(void *to, const void *from, int n)
-{
- memset(to, 0, n);
-}
-
-int __do_clear_user(void *mem, unsigned long len,
- void **fault_addr, void **fault_catcher)
-{
- struct tt_regs save = TASK_REGS(get_current())->tt;
- unsigned long fault;
- int faulted;
-
- fault = __do_user_copy(mem, NULL, len, fault_addr, fault_catcher,
- __do_clear, &faulted);
- TASK_REGS(get_current())->tt = save;
-
- if(!faulted) return(0);
- else return(len - (fault - (unsigned long) mem));
-}
-
-int __do_strnlen_user(const char *str, unsigned long n,
- void **fault_addr, void **fault_catcher)
-{
- struct tt_regs save = TASK_REGS(get_current())->tt;
- int ret;
- unsigned long *faddrp = (unsigned long *)fault_addr;
- jmp_buf jbuf;
-
- *fault_catcher = &jbuf;
- if(UML_SETJMP(&jbuf) == 0)
- ret = strlen(str) + 1;
- else ret = *faddrp - (unsigned long) str;
-
- *fault_addr = NULL;
- *fault_catcher = NULL;
-
- TASK_REGS(get_current())->tt = save;
- return ret;
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/uaccess.c b/arch/um/kernel/uaccess.c
index 054e3de0784e..d7436aacd26f 100644
--- a/arch/um/kernel/uaccess.c
+++ b/arch/um/kernel/uaccess.c
@@ -18,7 +18,7 @@ void __do_copy(void *to, const void *from, int n)
int __do_copy_to_user(void *to, const void *from, int n,
- void **fault_addr, void **fault_catcher)
+ void **fault_addr, jmp_buf **fault_catcher)
{
unsigned long fault;
int faulted;
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index ecc458fe51b9..f1c71393f578 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -1,46 +1,24 @@
/*
- * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/kernel.h"
-#include "linux/sched.h"
-#include "linux/notifier.h"
-#include "linux/mm.h"
-#include "linux/types.h"
-#include "linux/tty.h"
-#include "linux/init.h"
-#include "linux/bootmem.h"
-#include "linux/spinlock.h"
-#include "linux/utsname.h"
-#include "linux/sysrq.h"
-#include "linux/seq_file.h"
#include "linux/delay.h"
+#include "linux/mm.h"
#include "linux/module.h"
+#include "linux/seq_file.h"
+#include "linux/string.h"
#include "linux/utsname.h"
-#include "asm/page.h"
#include "asm/pgtable.h"
-#include "asm/ptrace.h"
-#include "asm/elf.h"
-#include "asm/user.h"
+#include "asm/processor.h"
#include "asm/setup.h"
-#include "ubd_user.h"
-#include "asm/current.h"
-#include "kern_util.h"
-#include "as-layout.h"
#include "arch.h"
+#include "as-layout.h"
+#include "init.h"
#include "kern.h"
#include "mem_user.h"
-#include "mem.h"
-#include "initrd.h"
-#include "init.h"
#include "os.h"
-#include "choose-mode.h"
-#include "mode_kern.h"
-#include "mode.h"
-#ifdef UML_CONFIG_MODE_SKAS
#include "skas.h"
-#endif
#define DEFAULT_COMMAND_LINE "root=98:0"
@@ -53,7 +31,7 @@ static void __init add_arg(char *arg)
printf("add_arg: Too many command line arguments!\n");
exit(1);
}
- if(strlen(command_line) > 0)
+ if (strlen(command_line) > 0)
strcat(command_line, " ");
strcat(command_line, arg);
}
@@ -70,8 +48,8 @@ struct cpuinfo_um boot_cpu_data = {
unsigned long thread_saved_pc(struct task_struct *task)
{
- return os_process_pc(CHOOSE_MODE_PROC(thread_pid_tt, thread_pid_skas,
- task));
+ /* FIXME: Need to look up userspace_pid by cpu */
+ return os_process_pc(userspace_pid[0]);
}
/* Changed in setup_arch, which is called in early boot */
@@ -90,7 +68,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
seq_printf(m, "processor\t: %d\n", index);
seq_printf(m, "vendor_id\t: User Mode Linux\n");
seq_printf(m, "model name\t: UML\n");
- seq_printf(m, "mode\t\t: %s\n", CHOOSE_MODE("tt", "skas"));
+ seq_printf(m, "mode\t\t: skas\n");
seq_printf(m, "host\t\t: %s\n", host_info);
seq_printf(m, "bogomips\t: %lu.%02lu\n\n",
loops_per_jiffy/(500000/HZ),
@@ -132,44 +110,13 @@ unsigned long end_vm;
/* Set in uml_ncpus_setup */
int ncpus = 1;
-#ifdef CONFIG_CMDLINE_ON_HOST
-/* Pointer set in linux_main, the array itself is private to each thread,
- * and changed at address space creation time so this poses no concurrency
- * problems.
- */
-static char *argv1_begin = NULL;
-static char *argv1_end = NULL;
-#endif
-
/* Set in early boot */
static int have_root __initdata = 0;
/* Set in uml_mem_setup and modified in linux_main */
long long physmem_size = 32 * 1024 * 1024;
-void set_cmdline(char *cmd)
-{
-#ifdef CONFIG_CMDLINE_ON_HOST
- char *umid, *ptr;
-
- if(CHOOSE_MODE(honeypot, 0)) return;
-
- umid = get_umid();
- if(*umid != '\0'){
- snprintf(argv1_begin,
- (argv1_end - argv1_begin) * sizeof(*ptr),
- "(%s) ", umid);
- ptr = &argv1_begin[strlen(argv1_begin)];
- }
- else ptr = argv1_begin;
-
- snprintf(ptr, (argv1_end - ptr) * sizeof(*ptr), "[%s]", cmd);
- memset(argv1_begin + strlen(argv1_begin), '\0',
- argv1_end - argv1_begin - strlen(argv1_begin));
-#endif
-}
-
-static char *usage_string =
+static char *usage_string =
"User Mode Linux v%s\n"
" available at http://user-mode-linux.sourceforge.net/\n\n";
@@ -201,13 +148,10 @@ __uml_setup("root=", uml_root_setup,
" root=/dev/ubd5\n\n"
);
-#ifndef CONFIG_MODE_TT
-
static int __init no_skas_debug_setup(char *line, int *add)
{
printf("'debug' is not necessary to gdb UML in skas mode - run \n");
- printf("'gdb linux' and disable CONFIG_CMDLINE_ON_HOST if gdb \n");
- printf("doesn't work as expected\n");
+ printf("'gdb linux'");
return 0;
}
@@ -217,8 +161,6 @@ __uml_setup("debug", no_skas_debug_setup,
" this flag is not needed to run gdb on UML in skas mode\n\n"
);
-#endif
-
#ifdef CONFIG_SMP
static int __init uml_ncpus_setup(char *line, int *add)
{
@@ -232,56 +174,10 @@ static int __init uml_ncpus_setup(char *line, int *add)
__uml_setup("ncpus=", uml_ncpus_setup,
"ncpus=<# of desired CPUs>\n"
-" This tells an SMP kernel how many virtual processors to start.\n\n"
+" This tells an SMP kernel how many virtual processors to start.\n\n"
);
#endif
-static int force_tt = 0;
-
-#if defined(CONFIG_MODE_TT) && defined(CONFIG_MODE_SKAS)
-#define DEFAULT_TT 0
-
-static int __init mode_tt_setup(char *line, int *add)
-{
- force_tt = 1;
- return 0;
-}
-
-#else
-#ifdef CONFIG_MODE_SKAS
-
-#define DEFAULT_TT 0
-
-static int __init mode_tt_setup(char *line, int *add)
-{
- printf("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n");
- return 0;
-}
-
-#else
-#ifdef CONFIG_MODE_TT
-
-#define DEFAULT_TT 1
-
-static int __init mode_tt_setup(char *line, int *add)
-{
- printf("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n");
- return 0;
-}
-
-#endif
-#endif
-#endif
-
-__uml_setup("mode=tt", mode_tt_setup,
-"mode=tt\n"
-" When both CONFIG_MODE_TT and CONFIG_MODE_SKAS are enabled, this option\n"
-" forces UML to run in tt (tracing thread) mode. It is not the default\n"
-" because it's slower and less secure than skas mode.\n\n"
-);
-
-int mode_tt = DEFAULT_TT;
-
static int __init Usage(char *line, int *add)
{
const char **p;
@@ -310,9 +206,8 @@ static int __init uml_checksetup(char *line, int *add)
int n;
n = strlen(p->str);
- if(!strncmp(line, p->str, n)){
- if (p->setup_func(line + n, add)) return 1;
- }
+ if (!strncmp(line, p->str, n) && p->setup_func(line + n, add))
+ return 1;
p++;
}
return 0;
@@ -323,7 +218,7 @@ static void __init uml_postsetup(void)
initcall_t *p;
p = &__uml_postsetup_start;
- while(p < &__uml_postsetup_end){
+ while(p < &__uml_postsetup_end) {
(*p)();
p++;
}
@@ -339,6 +234,20 @@ EXPORT_SYMBOL(end_iomem);
extern char __binary_start;
+static unsigned long set_task_sizes_skas(unsigned long *task_size_out)
+{
+ /* Round up to the nearest 4M */
+ unsigned long host_task_size = ROUND_4M((unsigned long)
+ &host_task_size);
+
+ if (!skas_needs_stub)
+ *task_size_out = host_task_size;
+ else
+ *task_size_out = STUB_START & PGDIR_MASK;
+
+ return host_task_size;
+}
+
int __init linux_main(int argc, char **argv)
{
unsigned long avail, diff;
@@ -346,45 +255,30 @@ int __init linux_main(int argc, char **argv)
unsigned int i, add;
char * mode;
- for (i = 1; i < argc; i++){
- if((i == 1) && (argv[i][0] == ' ')) continue;
+ for (i = 1; i < argc; i++) {
+ if ((i == 1) && (argv[i][0] == ' '))
+ continue;
add = 1;
uml_checksetup(argv[i], &add);
if (add)
add_arg(argv[i]);
}
- if(have_root == 0)
+ if (have_root == 0)
add_arg(DEFAULT_COMMAND_LINE);
+ /* OS sanity checks that need to happen before the kernel runs */
os_early_checks();
- if (force_tt)
- clear_can_do_skas();
- mode_tt = force_tt ? 1 : !can_do_skas();
-#ifndef CONFIG_MODE_TT
- if (mode_tt) {
- /*Since CONFIG_MODE_TT is #undef'ed, force_tt cannot be 1. So,
- * can_do_skas() returned 0, and the message is correct. */
- printf("Support for TT mode is disabled, and no SKAS support is present on the host.\n");
- exit(1);
- }
-#endif
-#ifndef CONFIG_MODE_SKAS
- mode = "TT";
-#else
- /* Show to the user the result of selection */
- if (mode_tt)
- mode = "TT";
- else if (proc_mm && ptrace_faultinfo)
+ can_do_skas();
+
+ if (proc_mm && ptrace_faultinfo)
mode = "SKAS3";
else
mode = "SKAS0";
-#endif
printf("UML running in %s mode\n", mode);
- host_task_size = CHOOSE_MODE_PROC(set_task_sizes_tt,
- set_task_sizes_skas, &task_size);
+ host_task_size = set_task_sizes_skas(&task_size);
/*
* Setting up handlers to 'sig_info' struct
@@ -392,13 +286,15 @@ int __init linux_main(int argc, char **argv)
os_fill_handlinfo(handlinfo_kern);
brk_start = (unsigned long) sbrk(0);
- CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start);
- /* Increase physical memory size for exec-shield users
- so they actually get what they asked for. This should
- add zero for non-exec shield users */
+
+ /*
+ * Increase physical memory size for exec-shield users
+ * so they actually get what they asked for. This should
+ * add zero for non-exec shield users
+ */
diff = UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end);
- if(diff > 1024 * 1024){
+ if (diff > 1024 * 1024) {
printf("Adding %ld bytes to physical memory to account for "
"exec-shield gap\n", diff);
physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end);
@@ -411,20 +307,16 @@ int __init linux_main(int argc, char **argv)
setup_machinename(init_utsname()->machine);
-#ifdef CONFIG_CMDLINE_ON_HOST
- argv1_begin = argv[1];
- argv1_end = &argv[1][strlen(argv[1])];
-#endif
-
highmem = 0;
iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK;
max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC;
- /* Zones have to begin on a 1 << MAX_ORDER page boundary,
+ /*
+ * Zones have to begin on a 1 << MAX_ORDER page boundary,
* so this makes sure that's true for highmem
*/
max_physmem &= ~((1 << (PAGE_SHIFT + MAX_ORDER)) - 1);
- if(physmem_size + iomem_size > max_physmem){
+ if (physmem_size + iomem_size > max_physmem) {
highmem = physmem_size + iomem_size - max_physmem;
physmem_size -= highmem;
#ifndef CONFIG_HIGHMEM
@@ -441,7 +333,7 @@ int __init linux_main(int argc, char **argv)
start_vm = VMALLOC_START;
setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem);
- if(init_maps(physmem_size, iomem_size, highmem)){
+ if (init_maps(physmem_size, iomem_size, highmem)) {
printf("Failed to allocate mem_map for %Lu bytes of physical "
"memory and %Lu bytes of highmem\n", physmem_size,
highmem);
@@ -450,10 +342,11 @@ int __init linux_main(int argc, char **argv)
virtmem_size = physmem_size;
avail = get_kmem_end() - start_vm;
- if(physmem_size > avail) virtmem_size = avail;
+ if (physmem_size > avail)
+ virtmem_size = avail;
end_vm = start_vm + virtmem_size;
- if(virtmem_size < physmem_size)
+ if (virtmem_size < physmem_size)
printf("Kernel virtual memory size shrunk to %lu bytes\n",
virtmem_size);
@@ -462,7 +355,7 @@ int __init linux_main(int argc, char **argv)
stack_protections((unsigned long) &init_thread_info);
os_flush_stdout();
- return CHOOSE_MODE(start_uml_tt(), start_uml_skas());
+ return start_uml();
}
extern int uml_exitcode;
diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S
index 81acdc24348e..13df191e2b41 100644
--- a/arch/um/kernel/uml.lds.S
+++ b/arch/um/kernel/uml.lds.S
@@ -18,13 +18,6 @@ SECTIONS
. = START + SIZEOF_HEADERS;
-#ifdef MODE_TT
- .remap_data : { UNMAP_PATH (.data .bss) }
- .remap : { UNMAP_PATH (.text) }
-
- . = ALIGN(4096); /* Init code and data */
-#endif
-
_text = .;
_stext = .;
__init_begin = .;
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index 2f8c79464015..8e129af8170d 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -1,23 +1,18 @@
#
-# Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+# Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
# Licensed under the GPL
#
obj-y = aio.o elf_aux.o execvp.o file.o helper.o irq.o main.o mem.o process.o \
- sigio.o signal.o start_up.o time.o trap.o tty.o uaccess.o umid.o tls.o \
- user_syms.o util.o drivers/ sys-$(SUBARCH)/
-
-obj-$(CONFIG_MODE_SKAS) += skas/
-
-obj-$(CONFIG_MODE_TT) += tt.o
-user-objs-$(CONFIG_MODE_TT) += tt.o
+ registers.o sigio.o signal.o start_up.o time.o trap.o tty.o uaccess.o \
+ umid.o tls.o user_syms.o util.o drivers/ sys-$(SUBARCH)/ skas/
obj-$(CONFIG_TTY_LOG) += tty_log.o
user-objs-$(CONFIG_TTY_LOG) += tty_log.o
USER_OBJS := $(user-objs-y) aio.o elf_aux.o execvp.o file.o helper.o irq.o \
- main.o mem.o process.o sigio.o signal.o start_up.o time.o trap.o tty.o \
- tls.o uaccess.o umid.o util.o
+ main.o mem.o process.o registers.o sigio.o signal.o start_up.o time.o \
+ trap.o tty.o tls.o uaccess.o umid.o util.o
CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH)
diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c
index 59348359f9ab..4158118c4a56 100644
--- a/arch/um/os-Linux/aio.c
+++ b/arch/um/os-Linux/aio.c
@@ -1,20 +1,19 @@
/*
- * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include <stdlib.h>
#include <unistd.h>
+#include <sched.h>
#include <signal.h>
#include <errno.h>
-#include <sched.h>
-#include <sys/syscall.h>
-#include "os.h"
+#include <sys/time.h>
+#include <asm/unistd.h>
#include "aio.h"
#include "init.h"
-#include "user.h"
-#include "mode.h"
#include "kern_constants.h"
+#include "os.h"
+#include "user.h"
struct aio_thread_req {
enum aio_type type;
@@ -28,7 +27,8 @@ struct aio_thread_req {
#if defined(HAVE_AIO_ABI)
#include <linux/aio_abi.h>
-/* If we have the headers, we are going to build with AIO enabled.
+/*
+ * If we have the headers, we are going to build with AIO enabled.
* If we don't have aio in libc, we define the necessary stubs here.
*/
@@ -52,7 +52,8 @@ static long io_getevents(aio_context_t ctx_id, long min_nr, long nr,
#endif
-/* The AIO_MMAP cases force the mmapped page into memory here
+/*
+ * The AIO_MMAP cases force the mmapped page into memory here
* rather than in whatever place first touches the data. I used
* to do this by touching the page, but that's delicate because
* gcc is prone to optimizing that away. So, what's done here
@@ -106,12 +107,12 @@ static int aio_thread(void *arg)
signal(SIGWINCH, SIG_IGN);
- while(1){
+ while (1) {
n = io_getevents(ctx, 1, 1, &event, NULL);
- if(n < 0){
- if(errno == EINTR)
+ if (n < 0) {
+ if (errno == EINTR)
continue;
- printk("aio_thread - io_getevents failed, "
+ printk(UM_KERN_ERR "aio_thread - io_getevents failed, "
"errno = %d\n", errno);
}
else {
@@ -120,9 +121,9 @@ static int aio_thread(void *arg)
.err = event.res });
reply_fd = ((struct aio_context *) reply.data)->reply_fd;
err = write(reply_fd, &reply, sizeof(reply));
- if(err != sizeof(reply))
- printk("aio_thread - write failed, fd = %d, "
- "err = %d\n", reply_fd, errno);
+ if (err != sizeof(reply))
+ printk(UM_KERN_ERR "aio_thread - write failed, "
+ "fd = %d, err = %d\n", reply_fd, errno);
}
}
return 0;
@@ -137,10 +138,10 @@ static int do_not_aio(struct aio_thread_req *req)
int n;
actual = lseek64(req->io_fd, req->offset, SEEK_SET);
- if(actual != req->offset)
+ if (actual != req->offset)
return -errno;
- switch(req->type){
+ switch(req->type) {
case AIO_READ:
n = read(req->io_fd, req->buf, req->len);
break;
@@ -151,11 +152,12 @@ static int do_not_aio(struct aio_thread_req *req)
n = read(req->io_fd, &c, sizeof(c));
break;
default:
- printk("do_not_aio - bad request type : %d\n", req->type);
+ printk(UM_KERN_ERR "do_not_aio - bad request type : %d\n",
+ req->type);
return -EINVAL;
}
- if(n < 0)
+ if (n < 0)
return -errno;
return 0;
}
@@ -173,16 +175,18 @@ static int not_aio_thread(void *arg)
int err;
signal(SIGWINCH, SIG_IGN);
- while(1){
+ while (1) {
err = read(aio_req_fd_r, &req, sizeof(req));
- if(err != sizeof(req)){
- if(err < 0)
- printk("not_aio_thread - read failed, "
- "fd = %d, err = %d\n", aio_req_fd_r,
+ if (err != sizeof(req)) {
+ if (err < 0)
+ printk(UM_KERN_ERR "not_aio_thread - "
+ "read failed, fd = %d, err = %d\n",
+ aio_req_fd_r,
errno);
else {
- printk("not_aio_thread - short read, fd = %d, "
- "length = %d\n", aio_req_fd_r, err);
+ printk(UM_KERN_ERR "not_aio_thread - short "
+ "read, fd = %d, length = %d\n",
+ aio_req_fd_r, err);
}
continue;
}
@@ -190,9 +194,9 @@ static int not_aio_thread(void *arg)
reply = ((struct aio_thread_reply) { .data = req.aio,
.err = err });
err = write(req.aio->reply_fd, &reply, sizeof(reply));
- if(err != sizeof(reply))
- printk("not_aio_thread - write failed, fd = %d, "
- "err = %d\n", req.aio->reply_fd, errno);
+ if (err != sizeof(reply))
+ printk(UM_KERN_ERR "not_aio_thread - write failed, "
+ "fd = %d, err = %d\n", req.aio->reply_fd, errno);
}
return 0;
@@ -203,35 +207,36 @@ static int init_aio_24(void)
int fds[2], err;
err = os_pipe(fds, 1, 1);
- if(err)
+ if (err)
goto out;
aio_req_fd_w = fds[0];
aio_req_fd_r = fds[1];
err = os_set_fd_block(aio_req_fd_w, 0);
- if(err)
+ if (err)
goto out_close_pipe;
err = run_helper_thread(not_aio_thread, NULL,
CLONE_FILES | CLONE_VM | SIGCHLD, &aio_stack);
- if(err < 0)
+ if (err < 0)
goto out_close_pipe;
aio_pid = err;
goto out;
out_close_pipe:
- os_close_file(fds[0]);
- os_close_file(fds[1]);
+ close(fds[0]);
+ close(fds[1]);
aio_req_fd_w = -1;
aio_req_fd_r = -1;
out:
#ifndef HAVE_AIO_ABI
- printk("/usr/include/linux/aio_abi.h not present during build\n");
+ printk(UM_KERN_INFO "/usr/include/linux/aio_abi.h not present during "
+ "build\n");
#endif
- printk("2.6 host AIO support not used - falling back to I/O "
- "thread\n");
+ printk(UM_KERN_INFO "2.6 host AIO support not used - falling back to "
+ "I/O thread\n");
return 0;
}
@@ -241,21 +246,21 @@ static int init_aio_26(void)
{
int err;
- if(io_setup(256, &ctx)){
+ if (io_setup(256, &ctx)) {
err = -errno;
- printk("aio_thread failed to initialize context, err = %d\n",
- errno);
+ printk(UM_KERN_ERR "aio_thread failed to initialize context, "
+ "err = %d\n", errno);
return err;
}
err = run_helper_thread(aio_thread, NULL,
CLONE_FILES | CLONE_VM | SIGCHLD, &aio_stack);
- if(err < 0)
+ if (err < 0)
return err;
aio_pid = err;
- printk("Using 2.6 host AIO\n");
+ printk(UM_KERN_INFO "Using 2.6 host AIO\n");
return 0;
}
@@ -266,13 +271,13 @@ static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len,
int err;
err = do_aio(ctx, type, io_fd, buf, len, offset, aio);
- if(err){
+ if (err) {
reply = ((struct aio_thread_reply) { .data = aio,
.err = err });
err = write(aio->reply_fd, &reply, sizeof(reply));
- if(err != sizeof(reply)){
+ if (err != sizeof(reply)) {
err = -errno;
- printk("submit_aio_26 - write failed, "
+ printk(UM_KERN_ERR "submit_aio_26 - write failed, "
"fd = %d, err = %d\n", aio->reply_fd, -err);
}
else err = 0;
@@ -320,28 +325,24 @@ static int init_aio(void)
{
int err;
- CHOOSE_MODE(({ if(!aio_24){
- printk("Disabling 2.6 AIO in tt mode\n");
- aio_24 = 1;
- } }), (void) 0);
-
- if(!aio_24){
+ if (!aio_24) {
err = init_aio_26();
- if(err && (errno == ENOSYS)){
- printk("2.6 AIO not supported on the host - "
- "reverting to 2.4 AIO\n");
+ if (err && (errno == ENOSYS)) {
+ printk(UM_KERN_INFO "2.6 AIO not supported on the "
+ "host - reverting to 2.4 AIO\n");
aio_24 = 1;
}
else return err;
}
- if(aio_24)
+ if (aio_24)
return init_aio_24();
return 0;
}
-/* The reason for the __initcall/__uml_exitcall asymmetry is that init_aio
+/*
+ * The reason for the __initcall/__uml_exitcall asymmetry is that init_aio
* needs to be called when the kernel is running because it calls run_helper,
* which needs get_free_page. exit_aio is a __uml_exitcall because the generic
* kernel does not run __exitcalls on shutdown, and can't because many of them
@@ -372,7 +373,7 @@ static int submit_aio_24(enum aio_type type, int io_fd, char *buf, int len,
int err;
err = write(aio_req_fd_w, &req, sizeof(req));
- if(err == sizeof(req))
+ if (err == sizeof(req))
err = 0;
else err = -errno;
@@ -384,9 +385,8 @@ int submit_aio(enum aio_type type, int io_fd, char *buf, int len,
struct aio_context *aio)
{
aio->reply_fd = reply_fd;
- if(aio_24)
+ if (aio_24)
return submit_aio_24(type, io_fd, buf, len, offset, aio);
- else {
+ else
return submit_aio_26(type, io_fd, buf, len, offset, aio);
- }
}
diff --git a/arch/um/os-Linux/drivers/etap.h b/arch/um/os-Linux/drivers/etap.h
index 57ecdaf2f67e..ddffd41c3f3f 100644
--- a/arch/um/os-Linux/drivers/etap.h
+++ b/arch/um/os-Linux/drivers/etap.h
@@ -1,8 +1,11 @@
/*
- * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
+#ifndef __DRIVERS_ETAP_H
+#define __DRIVERS_ETAP_H
+
#include "net_user.h"
struct ethertap_data {
@@ -15,13 +18,4 @@ struct ethertap_data {
extern const struct net_user_info ethertap_user_info;
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
+#endif
diff --git a/arch/um/os-Linux/drivers/ethertap_kern.c b/arch/um/os-Linux/drivers/ethertap_kern.c
index 12689141414d..04f11b9f1ac0 100644
--- a/arch/um/os-Linux/drivers/ethertap_kern.c
+++ b/arch/um/os-Linux/drivers/ethertap_kern.c
@@ -1,16 +1,15 @@
/*
- * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
* James Leu (jleu@mindspring.net).
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Copyright (C) 2001 by various other people who didn't put their name here.
* Licensed under the GPL.
*/
#include "linux/init.h"
-#include "linux/netdevice.h"
-#include "linux/etherdevice.h"
-#include "net_kern.h"
-#include "net_user.h"
+#include <linux/netdevice.h>
#include "etap.h"
+#include "net_kern.h"
struct ethertap_init {
char *dev_name;
@@ -37,32 +36,24 @@ static void etap_init(struct net_device *dev, void *data)
printk("\n");
}
-static int etap_read(int fd, struct sk_buff **skb, struct uml_net_private *lp)
+static int etap_read(int fd, struct sk_buff *skb, struct uml_net_private *lp)
{
int len;
- *skb = ether_adjust_skb(*skb, ETH_HEADER_ETHERTAP);
- if(*skb == NULL) return(-ENOMEM);
- len = net_recvfrom(fd, skb_mac_header(*skb),
- (*skb)->dev->mtu + 2 * ETH_HEADER_ETHERTAP);
- if(len <= 0) return(len);
- skb_pull(*skb, 2);
+ len = net_recvfrom(fd, skb_mac_header(skb),
+ skb->dev->mtu + 2 + ETH_HEADER_ETHERTAP);
+ if (len <= 0)
+ return(len);
+
+ skb_pull(skb, 2);
len -= 2;
- return(len);
+ return len;
}
-static int etap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp)
+static int etap_write(int fd, struct sk_buff *skb, struct uml_net_private *lp)
{
- if(skb_headroom(*skb) < 2){
- struct sk_buff *skb2;
-
- skb2 = skb_realloc_headroom(*skb, 2);
- dev_kfree_skb(*skb);
- if (skb2 == NULL) return(-ENOMEM);
- *skb = skb2;
- }
- skb_push(*skb, 2);
- return(net_send(fd, (*skb)->data, (*skb)->len));
+ skb_push(skb, 2);
+ return net_send(fd, skb->data, skb->len);
}
const struct net_kern_info ethertap_kern_info = {
@@ -79,15 +70,15 @@ int ethertap_setup(char *str, char **mac_out, void *data)
*init = ((struct ethertap_init)
{ .dev_name = NULL,
.gate_addr = NULL });
- if(tap_setup_common(str, "ethertap", &init->dev_name, mac_out,
+ if (tap_setup_common(str, "ethertap", &init->dev_name, mac_out,
&init->gate_addr))
- return(0);
- if(init->dev_name == NULL){
- printk("ethertap_setup : Missing tap device name\n");
- return(0);
+ return 0;
+ if (init->dev_name == NULL) {
+ printk(KERN_ERR "ethertap_setup : Missing tap device name\n");
+ return 0;
}
- return(1);
+ return 1;
}
static struct transport ethertap_transport = {
@@ -97,6 +88,7 @@ static struct transport ethertap_transport = {
.user = &ethertap_user_info,
.kern = &ethertap_kern_info,
.private_size = sizeof(struct ethertap_data),
+ .setup_size = sizeof(struct ethertap_init),
};
static int register_ethertap(void)
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c
index 61d3953c7ac9..4ff553603449 100644
--- a/arch/um/os-Linux/drivers/ethertap_user.c
+++ b/arch/um/os-Linux/drivers/ethertap_user.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
* James Leu (jleu@mindspring.net).
* Copyright (C) 2001 by various other people who didn't put their name here.
@@ -7,20 +8,16 @@
#include <stdio.h>
#include <unistd.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <sys/errno.h>
+#include <errno.h>
+#include <string.h>
#include <sys/socket.h>
#include <sys/wait.h>
-#include <sys/un.h>
-#include <net/if.h>
-#include "user.h"
-#include "kern_util.h"
-#include "net_user.h"
#include "etap.h"
+#include "kern_constants.h"
#include "os.h"
+#include "net_user.h"
#include "um_malloc.h"
-#include "kern_constants.h"
+#include "user.h"
#define MAX_PACKET ETH_MAX_PACKET
@@ -49,16 +46,18 @@ static void etap_change(int op, unsigned char *addr, unsigned char *netmask,
memcpy(change.addr, addr, sizeof(change.addr));
memcpy(change.netmask, netmask, sizeof(change.netmask));
CATCH_EINTR(n = write(fd, &change, sizeof(change)));
- if(n != sizeof(change)){
- printk("etap_change - request failed, err = %d\n", errno);
+ if (n != sizeof(change)) {
+ printk(UM_KERN_ERR "etap_change - request failed, err = %d\n",
+ errno);
return;
}
output = kmalloc(UM_KERN_PAGE_SIZE, UM_GFP_KERNEL);
- if(output == NULL)
- printk("etap_change : Failed to allocate output buffer\n");
+ if (output == NULL)
+ printk(UM_KERN_ERR "etap_change : Failed to allocate output "
+ "buffer\n");
read_output(fd, output, UM_KERN_PAGE_SIZE);
- if(output != NULL){
+ if (output != NULL) {
printk("%s", output);
kfree(output);
}
@@ -87,11 +86,11 @@ static void etap_pre_exec(void *arg)
struct etap_pre_exec_data *data = arg;
dup2(data->control_remote, 1);
- os_close_file(data->data_me);
- os_close_file(data->control_me);
+ close(data->data_me);
+ close(data->control_me);
}
-static int etap_tramp(char *dev, char *gate, int control_me,
+static int etap_tramp(char *dev, char *gate, int control_me,
int control_remote, int data_me, int data_remote)
{
struct etap_pre_exec_data pe_data;
@@ -101,13 +100,13 @@ static int etap_tramp(char *dev, char *gate, int control_me,
char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")];
char *setup_args[] = { "uml_net", version_buf, "ethertap", dev,
data_fd_buf, gate_buf, NULL };
- char *nosetup_args[] = { "uml_net", version_buf, "ethertap",
+ char *nosetup_args[] = { "uml_net", version_buf, "ethertap",
dev, data_fd_buf, NULL };
char **args, c;
sprintf(data_fd_buf, "%d", data_remote);
sprintf(version_buf, "%d", UML_NET_VERSION);
- if(gate != NULL){
+ if (gate != NULL) {
strcpy(gate_buf, gate);
args = setup_args;
}
@@ -119,24 +118,26 @@ static int etap_tramp(char *dev, char *gate, int control_me,
pe_data.data_me = data_me;
pid = run_helper(etap_pre_exec, &pe_data, args);
- if(pid < 0)
+ if (pid < 0)
err = pid;
- os_close_file(data_remote);
- os_close_file(control_remote);
+ close(data_remote);
+ close(control_remote);
CATCH_EINTR(n = read(control_me, &c, sizeof(c)));
- if(n != sizeof(c)){
+ if (n != sizeof(c)) {
err = -errno;
- printk("etap_tramp : read of status failed, err = %d\n", -err);
+ printk(UM_KERN_ERR "etap_tramp : read of status failed, "
+ "err = %d\n", -err);
return err;
}
- if(c != 1){
- printk("etap_tramp : uml_net failed\n");
+ if (c != 1) {
+ printk(UM_KERN_ERR "etap_tramp : uml_net failed\n");
err = -EINVAL;
CATCH_EINTR(n = waitpid(pid, &status, 0));
- if(n < 0)
+ if (n < 0)
err = -errno;
- else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 1))
- printk("uml_net didn't exit with status 1\n");
+ else if (!WIFEXITED(status) || (WEXITSTATUS(status) != 1))
+ printk(UM_KERN_ERR "uml_net didn't exit with "
+ "status 1\n");
}
return err;
}
@@ -148,43 +149,56 @@ static int etap_open(void *data)
int data_fds[2], control_fds[2], err, output_len;
err = tap_open_common(pri->dev, pri->gate_addr);
- if(err)
+ if (err)
return err;
- err = os_pipe(data_fds, 0, 0);
- if(err < 0){
- printk("data os_pipe failed - err = %d\n", -err);
+ err = socketpair(AF_UNIX, SOCK_DGRAM, 0, data_fds);
+ if (err) {
+ err = -errno;
+ printk(UM_KERN_ERR "etap_open - data socketpair failed - "
+ "err = %d\n", errno);
return err;
}
- err = os_pipe(control_fds, 1, 0);
- if(err < 0){
- printk("control os_pipe failed - err = %d\n", -err);
- return err;
+ err = socketpair(AF_UNIX, SOCK_STREAM, 0, control_fds);
+ if (err) {
+ err = -errno;
+ printk(UM_KERN_ERR "etap_open - control socketpair failed - "
+ "err = %d\n", errno);
+ goto out_close_data;
}
- err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0],
+ err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0],
control_fds[1], data_fds[0], data_fds[1]);
output_len = UM_KERN_PAGE_SIZE;
output = kmalloc(output_len, UM_GFP_KERNEL);
read_output(control_fds[0], output, output_len);
- if(output == NULL)
- printk("etap_open : failed to allocate output buffer\n");
+ if (output == NULL)
+ printk(UM_KERN_ERR "etap_open : failed to allocate output "
+ "buffer\n");
else {
printk("%s", output);
kfree(output);
}
- if(err < 0){
- printk("etap_tramp failed - err = %d\n", -err);
- return err;
+ if (err < 0) {
+ printk(UM_KERN_ERR "etap_tramp failed - err = %d\n", -err);
+ goto out_close_control;
}
pri->data_fd = data_fds[0];
pri->control_fd = control_fds[0];
iter_addresses(pri->dev, etap_open_addr, &pri->control_fd);
return data_fds[0];
+
+out_close_control:
+ close(control_fds[0]);
+ close(control_fds[1]);
+out_close_data:
+ close(data_fds[0]);
+ close(data_fds[1]);
+ return err;
}
static void etap_close(int fd, void *data)
@@ -192,37 +206,41 @@ static void etap_close(int fd, void *data)
struct ethertap_data *pri = data;
iter_addresses(pri->dev, etap_close_addr, &pri->control_fd);
- os_close_file(fd);
- os_shutdown_socket(pri->data_fd, 1, 1);
- os_close_file(pri->data_fd);
+ close(fd);
+
+ if (shutdown(pri->data_fd, SHUT_RDWR) < 0)
+ printk(UM_KERN_ERR "etap_close - shutdown data socket failed, "
+ "errno = %d\n", errno);
+
+ if (shutdown(pri->control_fd, SHUT_RDWR) < 0)
+ printk(UM_KERN_ERR "etap_close - shutdown control socket "
+ "failed, errno = %d\n", errno);
+
+ close(pri->data_fd);
pri->data_fd = -1;
- os_close_file(pri->control_fd);
+ close(pri->control_fd);
pri->control_fd = -1;
}
-static int etap_set_mtu(int mtu, void *data)
-{
- return mtu;
-}
-
static void etap_add_addr(unsigned char *addr, unsigned char *netmask,
void *data)
{
struct ethertap_data *pri = data;
tap_check_ips(pri->gate_addr, addr);
- if(pri->control_fd == -1)
+ if (pri->control_fd == -1)
return;
etap_open_addr(addr, netmask, &pri->control_fd);
}
-static void etap_del_addr(unsigned char *addr, unsigned char *netmask,
+static void etap_del_addr(unsigned char *addr, unsigned char *netmask,
void *data)
{
struct ethertap_data *pri = data;
- if(pri->control_fd == -1)
+ if (pri->control_fd == -1)
return;
+
etap_close_addr(addr, netmask, &pri->control_fd);
}
@@ -231,8 +249,8 @@ const struct net_user_info ethertap_user_info = {
.open = etap_open,
.close = etap_close,
.remove = NULL,
- .set_mtu = etap_set_mtu,
.add_address = etap_add_addr,
.delete_address = etap_del_addr,
- .max_packet = MAX_PACKET - ETH_HEADER_ETHERTAP
+ .mtu = ETH_MAX_PACKET,
+ .max_packet = ETH_MAX_PACKET + ETH_HEADER_ETHERTAP,
};
diff --git a/arch/um/os-Linux/drivers/tuntap.h b/arch/um/os-Linux/drivers/tuntap.h
index d3e8d3af6245..f17c31586c84 100644
--- a/arch/um/os-Linux/drivers/tuntap.h
+++ b/arch/um/os-Linux/drivers/tuntap.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -19,14 +19,3 @@ struct tuntap_data {
extern const struct net_user_info tuntap_user_info;
#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/os-Linux/drivers/tuntap_kern.c b/arch/um/os-Linux/drivers/tuntap_kern.c
index f1714e7fb1d0..9d384807b077 100644
--- a/arch/um/os-Linux/drivers/tuntap_kern.c
+++ b/arch/um/os-Linux/drivers/tuntap_kern.c
@@ -1,16 +1,13 @@
-/*
- * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
+/*
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/stddef.h"
-#include "linux/netdevice.h"
-#include "linux/etherdevice.h"
-#include "linux/skbuff.h"
-#include "linux/init.h"
-#include "asm/errno.h"
+#include <linux/netdevice.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <asm/errno.h>
#include "net_kern.h"
-#include "net_user.h"
#include "tuntap.h"
struct tuntap_init {
@@ -38,19 +35,15 @@ static void tuntap_init(struct net_device *dev, void *data)
printk("\n");
}
-static int tuntap_read(int fd, struct sk_buff **skb,
- struct uml_net_private *lp)
+static int tuntap_read(int fd, struct sk_buff *skb, struct uml_net_private *lp)
{
- *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER);
- if(*skb == NULL) return(-ENOMEM);
- return(net_read(fd, skb_mac_header(*skb),
- (*skb)->dev->mtu + ETH_HEADER_OTHER));
+ return net_read(fd, skb_mac_header(skb),
+ skb->dev->mtu + ETH_HEADER_OTHER);
}
-static int tuntap_write(int fd, struct sk_buff **skb,
- struct uml_net_private *lp)
+static int tuntap_write(int fd, struct sk_buff *skb, struct uml_net_private *lp)
{
- return(net_write(fd, (*skb)->data, (*skb)->len));
+ return net_write(fd, skb->data, skb->len);
}
const struct net_kern_info tuntap_kern_info = {
@@ -67,11 +60,11 @@ int tuntap_setup(char *str, char **mac_out, void *data)
*init = ((struct tuntap_init)
{ .dev_name = NULL,
.gate_addr = NULL });
- if(tap_setup_common(str, "tuntap", &init->dev_name, mac_out,
+ if (tap_setup_common(str, "tuntap", &init->dev_name, mac_out,
&init->gate_addr))
- return(0);
+ return 0;
- return(1);
+ return 1;
}
static struct transport tuntap_transport = {
diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c
index f848b4ea9343..6c55d3c8ead8 100644
--- a/arch/um/os-Linux/drivers/tuntap_user.c
+++ b/arch/um/os-Linux/drivers/tuntap_user.c
@@ -1,27 +1,22 @@
/*
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
#include <stdio.h>
-#include <stddef.h>
-#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
-#include <sys/wait.h>
+#include <string.h>
+#include <linux/if_tun.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
#include <sys/socket.h>
-#include <sys/un.h>
+#include <sys/wait.h>
#include <sys/uio.h>
-#include <sys/ioctl.h>
-#include <net/if.h>
-#include <linux/if_tun.h>
-#include "net_user.h"
+#include "kern_constants.h"
+#include "os.h"
#include "tuntap.h"
-#include "kern_util.h"
#include "user.h"
-#include "os.h"
-
-#define MAX_PACKET ETH_MAX_PACKET
static int tuntap_user_init(void *data, void *dev)
{
@@ -37,7 +32,7 @@ static void tuntap_add_addr(unsigned char *addr, unsigned char *netmask,
struct tuntap_data *pri = data;
tap_check_ips(pri->gate_addr, addr);
- if((pri->fd == -1) || pri->fixed_config)
+ if ((pri->fd == -1) || pri->fixed_config)
return;
open_addr(addr, netmask, pri->dev_name);
}
@@ -47,7 +42,7 @@ static void tuntap_del_addr(unsigned char *addr, unsigned char *netmask,
{
struct tuntap_data *pri = data;
- if((pri->fd == -1) || pri->fixed_config)
+ if ((pri->fd == -1) || pri->fixed_config)
return;
close_addr(addr, netmask, pri->dev_name);
}
@@ -62,7 +57,7 @@ static void tuntap_pre_exec(void *arg)
struct tuntap_pre_exec_data *data = arg;
dup2(data->stdout, 1);
- os_close_file(data->close_me);
+ close(data->close_me);
}
static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote,
@@ -85,14 +80,14 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote,
pid = run_helper(tuntap_pre_exec, &data, argv);
- if(pid < 0)
+ if (pid < 0)
return -pid;
- os_close_file(remote);
+ close(remote);
msg.msg_name = NULL;
msg.msg_namelen = 0;
- if(buffer != NULL){
+ if (buffer != NULL) {
iov = ((struct iovec) { buffer, buffer_len });
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
@@ -106,26 +101,28 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote,
msg.msg_flags = 0;
n = recvmsg(me, &msg, 0);
*used_out = n;
- if(n < 0){
+ if (n < 0) {
err = -errno;
- printk("tuntap_open_tramp : recvmsg failed - errno = %d\n",
- errno);
+ printk(UM_KERN_ERR "tuntap_open_tramp : recvmsg failed - "
+ "errno = %d\n", errno);
return err;
}
CATCH_EINTR(waitpid(pid, NULL, 0));
cmsg = CMSG_FIRSTHDR(&msg);
- if(cmsg == NULL){
- printk("tuntap_open_tramp : didn't receive a message\n");
+ if (cmsg == NULL) {
+ printk(UM_KERN_ERR "tuntap_open_tramp : didn't receive a "
+ "message\n");
return -EINVAL;
}
- if((cmsg->cmsg_level != SOL_SOCKET) ||
- (cmsg->cmsg_type != SCM_RIGHTS)){
- printk("tuntap_open_tramp : didn't receive a descriptor\n");
+ if ((cmsg->cmsg_level != SOL_SOCKET) ||
+ (cmsg->cmsg_type != SCM_RIGHTS)) {
+ printk(UM_KERN_ERR "tuntap_open_tramp : didn't receive a "
+ "descriptor\n");
return -EINVAL;
}
*fd_out = ((int *) CMSG_DATA(cmsg))[0];
- os_set_exec_close(*fd_out, 1);
+ os_set_exec_close(*fd_out);
return 0;
}
@@ -137,47 +134,51 @@ static int tuntap_open(void *data)
int err, fds[2], len, used;
err = tap_open_common(pri->dev, pri->gate_addr);
- if(err < 0)
+ if (err < 0)
return err;
- if(pri->fixed_config){
+ if (pri->fixed_config) {
pri->fd = os_open_file("/dev/net/tun",
of_cloexec(of_rdwr(OPENFLAGS())), 0);
- if(pri->fd < 0){
- printk("Failed to open /dev/net/tun, err = %d\n",
- -pri->fd);
+ if (pri->fd < 0) {
+ printk(UM_KERN_ERR "Failed to open /dev/net/tun, "
+ "err = %d\n", -pri->fd);
return pri->fd;
}
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name));
- if(ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0){
+ if (ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0) {
err = -errno;
- printk("TUNSETIFF failed, errno = %d\n", errno);
- os_close_file(pri->fd);
+ printk(UM_KERN_ERR "TUNSETIFF failed, errno = %d\n",
+ errno);
+ close(pri->fd);
return err;
}
}
else {
- err = os_pipe(fds, 0, 0);
- if(err < 0){
- printk("tuntap_open : os_pipe failed - err = %d\n",
- -err);
+ err = socketpair(AF_UNIX, SOCK_DGRAM, 0, fds);
+ if (err) {
+ err = -errno;
+ printk(UM_KERN_ERR "tuntap_open : socketpair failed - "
+ "errno = %d\n", errno);
return err;
}
buffer = get_output_buffer(&len);
- if(buffer != NULL) len--;
+ if (buffer != NULL)
+ len--;
used = 0;
err = tuntap_open_tramp(pri->gate_addr, &pri->fd, fds[0],
fds[1], buffer, len, &used);
output = buffer;
- if(err < 0) {
+ if (err < 0) {
printk("%s", output);
free_output_buffer(buffer);
- printk("tuntap_open_tramp failed - err = %d\n", -err);
+ printk(UM_KERN_ERR "tuntap_open_tramp failed - "
+ "err = %d\n", -err);
return err;
}
@@ -186,7 +187,7 @@ static int tuntap_open(void *data)
printk("%s", output);
free_output_buffer(buffer);
- os_close_file(fds[0]);
+ close(fds[0]);
iter_addresses(pri->dev, open_addr, pri->dev_name);
}
@@ -197,24 +198,19 @@ static void tuntap_close(int fd, void *data)
{
struct tuntap_data *pri = data;
- if(!pri->fixed_config)
+ if (!pri->fixed_config)
iter_addresses(pri->dev, close_addr, pri->dev_name);
- os_close_file(fd);
+ close(fd);
pri->fd = -1;
}
-static int tuntap_set_mtu(int mtu, void *data)
-{
- return mtu;
-}
-
const struct net_user_info tuntap_user_info = {
.init = tuntap_user_init,
.open = tuntap_open,
.close = tuntap_close,
.remove = NULL,
- .set_mtu = tuntap_set_mtu,
.add_address = tuntap_add_addr,
.delete_address = tuntap_del_addr,
- .max_packet = MAX_PACKET
+ .mtu = ETH_MAX_PACKET,
+ .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER,
};
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
index c3ecc2a84e0c..f83462758627 100644
--- a/arch/um/os-Linux/file.c
+++ b/arch/um/os-Linux/file.c
@@ -82,13 +82,6 @@ int os_access(const char* file, int mode)
return 0;
}
-void os_print_error(int error, const char* str)
-{
- errno = error < 0 ? -error : error;
-
- perror(str);
-}
-
/* FIXME? required only by hostaudio (because it passes ioctls verbatim) */
int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg)
{
@@ -101,30 +94,6 @@ int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg)
return err;
}
-int os_window_size(int fd, int *rows, int *cols)
-{
- struct winsize size;
-
- if(ioctl(fd, TIOCGWINSZ, &size) < 0)
- return -errno;
-
- *rows = size.ws_row;
- *cols = size.ws_col;
-
- return 0;
-}
-
-int os_new_tty_pgrp(int fd, int pid)
-{
- if(ioctl(fd, TIOCSCTTY, 0) < 0)
- return -errno;
-
- if(tcsetpgrp(fd, pid) < 0)
- return -errno;
-
- return 0;
-}
-
/* FIXME: ensure namebuf in os_get_if_name is big enough */
int os_get_ifname(int fd, char* namebuf)
{
@@ -205,19 +174,19 @@ int os_file_mode(char *file, struct openflags *mode_out)
*mode_out = OPENFLAGS();
- err = os_access(file, OS_ACC_W_OK);
- if((err < 0) && (err != -EACCES))
- return(err);
-
- *mode_out = of_write(*mode_out);
-
- err = os_access(file, OS_ACC_R_OK);
- if((err < 0) && (err != -EACCES))
- return(err);
+ err = access(file, W_OK);
+ if(err && (errno != EACCES))
+ return -errno;
+ else if(!err)
+ *mode_out = of_write(*mode_out);
- *mode_out = of_read(*mode_out);
+ err = access(file, R_OK);
+ if(err && (errno != EACCES))
+ return -errno;
+ else if(!err)
+ *mode_out = of_read(*mode_out);
- return(0);
+ return err;
}
int os_open_file(char *file, struct openflags flags, int mode)
@@ -236,15 +205,15 @@ int os_open_file(char *file, struct openflags flags, int mode)
fd = open64(file, f, mode);
if(fd < 0)
- return(-errno);
+ return -errno;
if(flags.cl && fcntl(fd, F_SETFD, 1)){
err = -errno;
- os_close_file(fd);
+ close(fd);
return err;
}
- return(fd);
+ return fd;
}
int os_connect_socket(char *name)
@@ -280,9 +249,9 @@ void os_close_file(int fd)
close(fd);
}
-int os_seek_file(int fd, __u64 offset)
+int os_seek_file(int fd, unsigned long long offset)
{
- __u64 actual;
+ unsigned long long actual;
actual = lseek64(fd, offset, SEEK_SET);
if(actual != offset)
@@ -316,31 +285,33 @@ int os_file_size(char *file, unsigned long long *size_out)
err = os_stat_file(file, &buf);
if(err < 0){
printk("Couldn't stat \"%s\" : err = %d\n", file, -err);
- return(err);
+ return err;
}
if(S_ISBLK(buf.ust_mode)){
int fd;
long blocks;
- fd = os_open_file(file, of_read(OPENFLAGS()), 0);
- if(fd < 0){
- printk("Couldn't open \"%s\", errno = %d\n", file, -fd);
- return(fd);
+ fd = open(file, O_RDONLY, 0);
+ if(fd < 0) {
+ err = -errno;
+ printk("Couldn't open \"%s\", errno = %d\n", file,
+ errno);
+ return err;
}
if(ioctl(fd, BLKGETSIZE, &blocks) < 0){
err = -errno;
printk("Couldn't get the block size of \"%s\", "
"errno = %d\n", file, errno);
- os_close_file(fd);
- return(err);
+ close(fd);
+ return err;
}
*size_out = ((long long) blocks) * 512;
- os_close_file(fd);
- return(0);
+ close(fd);
}
- *size_out = buf.ust_size;
- return(0);
+ else *size_out = buf.ust_size;
+
+ return 0;
}
int os_file_modtime(char *file, unsigned long *modtime)
@@ -358,35 +329,28 @@ int os_file_modtime(char *file, unsigned long *modtime)
return 0;
}
-int os_get_exec_close(int fd, int* close_on_exec)
+int os_get_exec_close(int fd, int *close_on_exec)
{
int ret;
- do {
- ret = fcntl(fd, F_GETFD);
- } while((ret < 0) && (errno == EINTR)) ;
+ CATCH_EINTR(ret = fcntl(fd, F_GETFD));
if(ret < 0)
- return(-errno);
+ return -errno;
- *close_on_exec = (ret&FD_CLOEXEC) ? 1 : 0;
- return(ret);
+ *close_on_exec = (ret & FD_CLOEXEC) ? 1 : 0;
+ return ret;
}
-int os_set_exec_close(int fd, int close_on_exec)
+int os_set_exec_close(int fd)
{
- int flag, err;
-
- if(close_on_exec) flag = FD_CLOEXEC;
- else flag = 0;
+ int err;
- do {
- err = fcntl(fd, F_SETFD, flag);
- } while((err < 0) && (errno == EINTR)) ;
+ CATCH_EINTR(err = fcntl(fd, F_SETFD, FD_CLOEXEC));
if(err < 0)
- return(-errno);
- return(err);
+ return -errno;
+ return err;
}
int os_pipe(int *fds, int stream, int close_on_exec)
@@ -395,16 +359,16 @@ int os_pipe(int *fds, int stream, int close_on_exec)
err = socketpair(AF_UNIX, type, 0, fds);
if(err < 0)
- return(-errno);
+ return -errno;
if(!close_on_exec)
- return(0);
+ return 0;
- err = os_set_exec_close(fds[0], 1);
+ err = os_set_exec_close(fds[0]);
if(err < 0)
goto error;
- err = os_set_exec_close(fds[1], 1);
+ err = os_set_exec_close(fds[1]);
if(err < 0)
goto error;
@@ -412,9 +376,9 @@ int os_pipe(int *fds, int stream, int close_on_exec)
error:
printk("os_pipe : Setting FD_CLOEXEC failed, err = %d\n", -err);
- os_close_file(fds[1]);
- os_close_file(fds[0]);
- return(err);
+ close(fds[1]);
+ close(fds[0]);
+ return err;
}
int os_set_fd_async(int fd, int owner)
@@ -532,8 +496,7 @@ int os_rcv_fd(int fd, int *helper_pid_out)
n = recvmsg(fd, &msg, 0);
if(n < 0)
return -errno;
-
- else if(n != sizeof(iov.iov_len))
+ else if(n != iov.iov_len)
*helper_pid_out = -1;
cmsg = CMSG_FIRSTHDR(&msg);
@@ -561,7 +524,7 @@ int os_create_unix_socket(char *file, int len, int close_on_exec)
return -errno;
if(close_on_exec) {
- err = os_set_exec_close(sock, 1);
+ err = os_set_exec_close(sock);
if(err < 0)
printk("create_unix_socket : close_on_exec failed, "
"err = %d", -err);
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index d81af7b8587a..7a72dbb61b0d 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -11,6 +11,7 @@
#include <limits.h>
#include <sys/signal.h>
#include <sys/wait.h>
+#include <sys/socket.h>
#include "user.h"
#include "kern_util.h"
#include "os.h"
@@ -54,13 +55,14 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
if (stack == 0)
return -ENOMEM;
- ret = os_pipe(fds, 1, 0);
+ ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
if (ret < 0) {
- printk("run_helper : pipe failed, ret = %d\n", -ret);
+ ret = -errno;
+ printk("run_helper : pipe failed, errno = %d\n", errno);
goto out_free;
}
- ret = os_set_exec_close(fds[1], 1);
+ ret = os_set_exec_close(fds[1]);
if (ret < 0) {
printk("run_helper : setting FD_CLOEXEC failed, ret = %d\n",
-ret);
diff --git a/arch/um/os-Linux/irq.c b/arch/um/os-Linux/irq.c
index a633fa8e0a94..6aa6f95d6524 100644
--- a/arch/um/os-Linux/irq.c
+++ b/arch/um/os-Linux/irq.c
@@ -145,11 +145,7 @@ void init_irq_signals(int on_sigstack)
flags = on_sigstack ? SA_ONSTACK : 0;
- set_handler(SIGVTALRM, (__sighandler_t) alarm_handler,
- flags | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1);
- set_handler(SIGALRM, (__sighandler_t) alarm_handler,
- flags | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1);
set_handler(SIGIO, (__sighandler_t) sig_handler, flags | SA_RESTART,
- SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
+ SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
signal(SIGWINCH, SIG_IGN);
}
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index e85f4995a011..82c3778627b8 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -1,33 +1,21 @@
/*
- * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
-#include <signal.h>
+#include <unistd.h>
#include <errno.h>
+#include <signal.h>
+#include <string.h>
#include <sys/resource.h>
-#include <sys/mman.h>
-#include <sys/user.h>
-#include <asm/page.h>
-#include "kern_util.h"
#include "as-layout.h"
-#include "mem_user.h"
-#include "irq_user.h"
-#include "user.h"
#include "init.h"
-#include "mode.h"
-#include "choose-mode.h"
-#include "uml-config.h"
+#include "kern_constants.h"
+#include "kern_util.h"
#include "os.h"
#include "um_malloc.h"
-#include "kern_constants.h"
-
-/* Set in main, unchanged thereafter */
-char *linux_prog;
#define PGD_BOUND (4 * 1024 * 1024)
#define STACKSIZE (8 * 1024 * 1024)
@@ -37,13 +25,13 @@ static void set_stklim(void)
{
struct rlimit lim;
- if(getrlimit(RLIMIT_STACK, &lim) < 0){
+ if (getrlimit(RLIMIT_STACK, &lim) < 0) {
perror("getrlimit");
exit(1);
}
- if((lim.rlim_cur == RLIM_INFINITY) || (lim.rlim_cur > STACKSIZE)){
+ if ((lim.rlim_cur == RLIM_INFINITY) || (lim.rlim_cur > STACKSIZE)) {
lim.rlim_cur = STACKSIZE;
- if(setrlimit(RLIMIT_STACK, &lim) < 0){
+ if (setrlimit(RLIMIT_STACK, &lim) < 0) {
perror("setrlimit");
exit(1);
}
@@ -55,7 +43,7 @@ static __init void do_uml_initcalls(void)
initcall_t *call;
call = &__uml_initcall_start;
- while (call < &__uml_initcall_end){
+ while (call < &__uml_initcall_end) {
(*call)();
call++;
}
@@ -74,7 +62,8 @@ static void install_fatal_handler(int sig)
/* All signals are enabled in this handler ... */
sigemptyset(&action.sa_mask);
- /* ... including the signal being handled, plus we want the
+ /*
+ * ... including the signal being handled, plus we want the
* handler reset to the default behavior, so that if an exit
* handler is hanging for some reason, the UML will just die
* after this signal is sent a second time.
@@ -82,7 +71,7 @@ static void install_fatal_handler(int sig)
action.sa_flags = SA_RESETHAND | SA_NODEFER;
action.sa_restorer = NULL;
action.sa_handler = last_ditch_exit;
- if(sigaction(sig, &action, NULL) < 0){
+ if (sigaction(sig, &action, NULL) < 0) {
printf("failed to install handler for signal %d - errno = %d\n",
errno);
exit(1);
@@ -98,7 +87,8 @@ static void setup_env_path(void)
int path_len = 0;
old_path = getenv("PATH");
- /* if no PATH variable is set or it has an empty value
+ /*
+ * if no PATH variable is set or it has an empty value
* just use the default + /usr/lib/uml
*/
if (!old_path || (path_len = strlen(old_path)) == 0) {
@@ -126,93 +116,68 @@ int __init main(int argc, char **argv, char **envp)
char **new_argv;
int ret, i, err;
-#ifdef UML_CONFIG_CMDLINE_ON_HOST
- /* Allocate memory for thread command lines */
- if(argc < 2 || strlen(argv[1]) < THREAD_NAME_LEN - 1){
-
- char padding[THREAD_NAME_LEN] = {
- [ 0 ... THREAD_NAME_LEN - 2] = ' ', '\0'
- };
-
- new_argv = malloc((argc + 2) * sizeof(char*));
- if(!new_argv) {
- perror("Allocating extended argv");
- exit(1);
- }
-
- new_argv[0] = argv[0];
- new_argv[1] = padding;
-
- for(i = 2; i <= argc; i++)
- new_argv[i] = argv[i - 1];
- new_argv[argc + 1] = NULL;
-
- execvp(new_argv[0], new_argv);
- perror("execing with extended args");
- exit(1);
- }
-#endif
-
- linux_prog = argv[0];
-
set_stklim();
setup_env_path();
new_argv = malloc((argc + 1) * sizeof(char *));
- if(new_argv == NULL){
+ if (new_argv == NULL) {
perror("Mallocing argv");
exit(1);
}
- for(i=0;i<argc;i++){
+ for (i = 0; i < argc; i++) {
new_argv[i] = strdup(argv[i]);
- if(new_argv[i] == NULL){
+ if (new_argv[i] == NULL) {
perror("Mallocing an arg");
exit(1);
}
}
new_argv[argc] = NULL;
- /* Allow these signals to bring down a UML if all other
+ /*
+ * Allow these signals to bring down a UML if all other
* methods of control fail.
*/
install_fatal_handler(SIGINT);
install_fatal_handler(SIGTERM);
install_fatal_handler(SIGHUP);
- scan_elf_aux( envp);
+ scan_elf_aux(envp);
do_uml_initcalls();
ret = linux_main(argc, argv);
- /* Disable SIGPROF - I have no idea why libc doesn't do this or turn
+ /*
+ * Disable SIGPROF - I have no idea why libc doesn't do this or turn
* off the profiling time, but UML dies with a SIGPROF just before
* exiting when profiling is active.
*/
change_sig(SIGPROF, 0);
- /* This signal stuff used to be in the reboot case. However,
+ /*
+ * This signal stuff used to be in the reboot case. However,
* sometimes a SIGVTALRM can come in when we're halting (reproducably
* when writing out gcov information, presumably because that takes
* some time) and cause a segfault.
*/
- /* stop timers and set SIG*ALRM to be ignored */
+ /* stop timers and set SIGVTALRM to be ignored */
disable_timer();
/* disable SIGIO for the fds and set SIGIO to be ignored */
err = deactivate_all_fds();
- if(err)
+ if (err)
printf("deactivate_all_fds failed, errno = %d\n", -err);
- /* Let any pending signals fire now. This ensures
+ /*
+ * Let any pending signals fire now. This ensures
* that they won't be delivered after the exec, when
* they are definitely not expected.
*/
unblock_signals();
/* Reboot */
- if(ret){
+ if (ret) {
printf("\n");
execvp(new_argv[0], new_argv);
perror("Failed to exec kernel");
@@ -222,26 +187,24 @@ int __init main(int argc, char **argv, char **envp)
return uml_exitcode;
}
-#define CAN_KMALLOC() \
- (kmalloc_ok && CHOOSE_MODE((os_getpid() != tracing_pid), 1))
-
extern void *__real_malloc(int);
void *__wrap_malloc(int size)
{
void *ret;
- if(!CAN_KMALLOC())
+ if (!kmalloc_ok)
return __real_malloc(size);
- else if(size <= UM_KERN_PAGE_SIZE)
+ else if (size <= UM_KERN_PAGE_SIZE)
/* finding contiguous pages can be hard*/
ret = kmalloc(size, UM_GFP_KERNEL);
else ret = vmalloc(size);
- /* glibc people insist that if malloc fails, errno should be
+ /*
+ * glibc people insist that if malloc fails, errno should be
* set by malloc as well. So we do.
*/
- if(ret == NULL)
+ if (ret == NULL)
errno = ENOMEM;
return ret;
@@ -251,7 +214,7 @@ void *__wrap_calloc(int n, int size)
{
void *ptr = __wrap_malloc(n * size);
- if(ptr == NULL)
+ if (ptr == NULL)
return NULL;
memset(ptr, 0, n * size);
return ptr;
@@ -265,7 +228,8 @@ void __wrap_free(void *ptr)
{
unsigned long addr = (unsigned long) ptr;
- /* We need to know how the allocation happened, so it can be correctly
+ /*
+ * We need to know how the allocation happened, so it can be correctly
* freed. This is done by seeing what region of memory the pointer is
* in -
* physical memory - kmalloc/kfree
@@ -283,12 +247,12 @@ void __wrap_free(void *ptr)
* there is a possibility for memory leaks.
*/
- if((addr >= uml_physmem) && (addr < high_physmem)){
- if(CAN_KMALLOC())
+ if ((addr >= uml_physmem) && (addr < high_physmem)) {
+ if (kmalloc_ok)
kfree(ptr);
}
- else if((addr >= start_vm) && (addr < end_vm)){
- if(CAN_KMALLOC())
+ else if ((addr >= start_vm) && (addr < end_vm)) {
+ if (kmalloc_ok)
vfree(ptr);
}
else __real_free(ptr);
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index c6378c6d10d2..436f8d20b20f 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -218,7 +218,7 @@ int __init create_tmp_file(unsigned long long len)
err = fchmod(fd, 0777);
if(err < 0){
- perror("os_mode_fd");
+ perror("fchmod");
exit(1);
}
@@ -226,7 +226,7 @@ int __init create_tmp_file(unsigned long long len)
* increase the file size by one byte, to the desired length.
*/
if (lseek64(fd, len - 1, SEEK_SET) < 0) {
- perror("os_seek_file");
+ perror("lseek64");
exit(1);
}
@@ -247,7 +247,7 @@ int __init create_mem_file(unsigned long long len)
fd = create_tmp_file(len);
- err = os_set_exec_close(fd, 1);
+ err = os_set_exec_close(fd);
if(err < 0){
errno = -err;
perror("exec_close");
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index e9c143297512..37781db4ceca 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -1,27 +1,24 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@addtoit.com)
+/*
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include <unistd.h>
#include <stdio.h>
+#include <unistd.h>
#include <errno.h>
#include <signal.h>
+#include <fcntl.h>
#include <sys/mman.h>
+#include <sys/ptrace.h>
#include <sys/wait.h>
-#include <sys/mman.h>
-#include <sys/syscall.h>
-#include "ptrace_user.h"
+#include <asm/unistd.h>
+#include "init.h"
+#include "kern_constants.h"
+#include "longjmp.h"
#include "os.h"
-#include "user.h"
#include "process.h"
-#include "irq_user.h"
-#include "kern_util.h"
-#include "longjmp.h"
#include "skas_ptrace.h"
-#include "kern_constants.h"
-#include "uml-config.h"
-#include "init.h"
+#include "user.h"
#define ARBITRARY_ADDR -1
#define FAILURE_PID -1
@@ -32,30 +29,32 @@
unsigned long os_process_pc(int pid)
{
char proc_stat[STAT_PATH_LEN], buf[256];
- unsigned long pc;
+ unsigned long pc = ARBITRARY_ADDR;
int fd, err;
sprintf(proc_stat, "/proc/%d/stat", pid);
- fd = os_open_file(proc_stat, of_read(OPENFLAGS()), 0);
- if(fd < 0){
- printk("os_process_pc - couldn't open '%s', err = %d\n",
- proc_stat, -fd);
- return ARBITRARY_ADDR;
+ fd = open(proc_stat, O_RDONLY, 0);
+ if (fd < 0) {
+ printk(UM_KERN_ERR "os_process_pc - couldn't open '%s', "
+ "errno = %d\n", proc_stat, errno);
+ goto out;
}
CATCH_EINTR(err = read(fd, buf, sizeof(buf)));
- if(err < 0){
- printk("os_process_pc - couldn't read '%s', err = %d\n",
- proc_stat, errno);
- os_close_file(fd);
- return ARBITRARY_ADDR;
+ if (err < 0) {
+ printk(UM_KERN_ERR "os_process_pc - couldn't read '%s', "
+ "err = %d\n", proc_stat, errno);
+ goto out_close;
}
os_close_file(fd);
pc = ARBITRARY_ADDR;
- if(sscanf(buf, "%*d " COMM_SCANF " %*c %*d %*d %*d %*d %*d %*d %*d "
- "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
- "%*d %*d %*d %*d %*d %lu", &pc) != 1){
- printk("os_process_pc - couldn't find pc in '%s'\n", buf);
- }
+ if (sscanf(buf, "%*d " COMM_SCANF " %*c %*d %*d %*d %*d %*d %*d %*d "
+ "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
+ "%*d %*d %*d %*d %*d %lu", &pc) != 1)
+ printk(UM_KERN_ERR "os_process_pc - couldn't find pc in '%s'\n",
+ buf);
+ out_close:
+ close(fd);
+ out:
return pc;
}
@@ -63,30 +62,32 @@ int os_process_parent(int pid)
{
char stat[STAT_PATH_LEN];
char data[256];
- int parent, n, fd;
+ int parent = FAILURE_PID, n, fd;
- if(pid == -1)
- return -1;
+ if (pid == -1)
+ return parent;
snprintf(stat, sizeof(stat), "/proc/%d/stat", pid);
- fd = os_open_file(stat, of_read(OPENFLAGS()), 0);
- if(fd < 0){
- printk("Couldn't open '%s', err = %d\n", stat, -fd);
- return FAILURE_PID;
+ fd = open(stat, O_RDONLY, 0);
+ if (fd < 0) {
+ printk(UM_KERN_ERR "Couldn't open '%s', errno = %d\n", stat,
+ errno);
+ return parent;
}
CATCH_EINTR(n = read(fd, data, sizeof(data)));
- os_close_file(fd);
+ close(fd);
- if(n < 0){
- printk("Couldn't read '%s', err = %d\n", stat, errno);
- return FAILURE_PID;
+ if (n < 0) {
+ printk(UM_KERN_ERR "Couldn't read '%s', errno = %d\n", stat,
+ errno);
+ return parent;
}
parent = FAILURE_PID;
n = sscanf(data, "%*d " COMM_SCANF " %*c %d", &parent);
- if(n != 1)
- printk("Failed to scan '%s'\n", data);
+ if (n != 1)
+ printk(UM_KERN_ERR "Failed to scan '%s'\n", data);
return parent;
}
@@ -99,9 +100,8 @@ void os_stop_process(int pid)
void os_kill_process(int pid, int reap_child)
{
kill(pid, SIGKILL);
- if(reap_child)
+ if (reap_child)
CATCH_EINTR(waitpid(pid, NULL, 0));
-
}
/* This is here uniquely to have access to the userspace errno, i.e. the one
@@ -129,17 +129,10 @@ void os_kill_ptraced_process(int pid, int reap_child)
kill(pid, SIGKILL);
ptrace(PTRACE_KILL, pid);
ptrace(PTRACE_CONT, pid);
- if(reap_child)
+ if (reap_child)
CATCH_EINTR(waitpid(pid, NULL, 0));
}
-#ifdef UML_CONFIG_MODE_TT
-void os_usr1_process(int pid)
-{
- kill(pid, SIGUSR1);
-}
-#endif
-
/* Don't use the glibc version, which caches the result in TLS. It misses some
* syscalls, and also breaks with clone(), which does not unshare the TLS.
*/
@@ -160,34 +153,35 @@ int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len,
void *loc;
int prot;
- prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
+ prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
(x ? PROT_EXEC : 0);
loc = mmap64((void *) virt, len, prot, MAP_SHARED | MAP_FIXED,
fd, off);
- if(loc == MAP_FAILED)
+ if (loc == MAP_FAILED)
return -errno;
return 0;
}
int os_protect_memory(void *addr, unsigned long len, int r, int w, int x)
{
- int prot = ((r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
+ int prot = ((r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
(x ? PROT_EXEC : 0));
- if(mprotect(addr, len, prot) < 0)
+ if (mprotect(addr, len, prot) < 0)
return -errno;
- return 0;
+
+ return 0;
}
int os_unmap_memory(void *addr, int len)
{
- int err;
+ int err;
- err = munmap(addr, len);
- if(err < 0)
+ err = munmap(addr, len);
+ if (err < 0)
return -errno;
- return 0;
+ return 0;
}
#ifndef MADV_REMOVE
@@ -199,7 +193,7 @@ int os_drop_memory(void *addr, int length)
int err;
err = madvise(addr, length, MADV_REMOVE);
- if(err < 0)
+ if (err < 0)
err = -errno;
return err;
}
@@ -209,22 +203,24 @@ int __init can_drop_memory(void)
void *addr;
int fd, ok = 0;
- printk("Checking host MADV_REMOVE support...");
+ printk(UM_KERN_INFO "Checking host MADV_REMOVE support...");
fd = create_mem_file(UM_KERN_PAGE_SIZE);
- if(fd < 0){
- printk("Creating test memory file failed, err = %d\n", -fd);
+ if (fd < 0) {
+ printk(UM_KERN_ERR "Creating test memory file failed, "
+ "err = %d\n", -fd);
goto out;
}
addr = mmap64(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
- if(addr == MAP_FAILED){
- printk("Mapping test memory file failed, err = %d\n", -errno);
+ if (addr == MAP_FAILED) {
+ printk(UM_KERN_ERR "Mapping test memory file failed, "
+ "err = %d\n", -errno);
goto out_close;
}
- if(madvise(addr, UM_KERN_PAGE_SIZE, MADV_REMOVE) != 0){
- printk("MADV_REMOVE failed, err = %d\n", -errno);
+ if (madvise(addr, UM_KERN_PAGE_SIZE, MADV_REMOVE) != 0) {
+ printk(UM_KERN_ERR "MADV_REMOVE failed, err = %d\n", -errno);
goto out_unmap;
}
@@ -239,58 +235,31 @@ out:
return ok;
}
-#ifdef UML_CONFIG_MODE_TT
-void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int))
-{
- int flags = 0, pages;
-
- if(sig_stack != NULL){
- pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER);
- set_sigstack(sig_stack, pages * UM_KERN_PAGE_SIZE);
- flags = SA_ONSTACK;
- }
- if(usr1_handler){
- struct sigaction sa;
-
- sa.sa_handler = usr1_handler;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = flags;
- sa.sa_restorer = NULL;
- if(sigaction(SIGUSR1, &sa, NULL) < 0)
- panic("init_new_thread_stack - sigaction failed - "
- "errno = %d\n", errno);
- }
-}
-#endif
-
void init_new_thread_signals(void)
{
set_handler(SIGSEGV, (__sighandler_t) sig_handler, SA_ONSTACK,
- SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
+ SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
set_handler(SIGTRAP, (__sighandler_t) sig_handler, SA_ONSTACK,
- SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
+ SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
set_handler(SIGFPE, (__sighandler_t) sig_handler, SA_ONSTACK,
- SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
+ SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
set_handler(SIGILL, (__sighandler_t) sig_handler, SA_ONSTACK,
- SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
+ SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
set_handler(SIGBUS, (__sighandler_t) sig_handler, SA_ONSTACK,
- SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
- set_handler(SIGUSR2, (__sighandler_t) sig_handler,
- SA_ONSTACK, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM,
- -1);
+ SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
signal(SIGHUP, SIG_IGN);
init_irq_signals(1);
}
-int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr)
+int run_kernel_thread(int (*fn)(void *), void *arg, jmp_buf **jmp_ptr)
{
jmp_buf buf;
int n;
*jmp_ptr = &buf;
n = UML_SETJMP(&buf);
- if(n != 0)
+ if (n != 0)
return n;
(*fn)(arg);
return 0;
diff --git a/arch/um/os-Linux/registers.c b/arch/um/os-Linux/registers.c
new file mode 100644
index 000000000000..a32ba6ab1211
--- /dev/null
+++ b/arch/um/os-Linux/registers.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2004 PathScale, Inc
+ * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <sys/ptrace.h>
+#include "sysdep/ptrace.h"
+#include "user.h"
+
+/* This is set once at boot time and not changed thereafter */
+
+static unsigned long exec_regs[MAX_REG_NR];
+
+void init_thread_registers(struct uml_pt_regs *to)
+{
+ memcpy(to->gp, exec_regs, sizeof(to->gp));
+}
+
+void save_registers(int pid, struct uml_pt_regs *regs)
+{
+ int err;
+
+ err = ptrace(PTRACE_GETREGS, pid, 0, regs->gp);
+ if (err < 0)
+ panic("save_registers - saving registers failed, errno = %d\n",
+ errno);
+}
+
+void restore_registers(int pid, struct uml_pt_regs *regs)
+{
+ int err;
+
+ err = ptrace(PTRACE_SETREGS, pid, 0, regs->gp);
+ if (err < 0)
+ panic("restore_registers - saving registers failed, "
+ "errno = %d\n", errno);
+}
+
+void init_registers(int pid)
+{
+ int err;
+
+ err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs);
+ if (err)
+ panic("check_ptrace : PTRACE_GETREGS failed, errno = %d",
+ errno);
+
+ arch_init_registers(pid);
+}
+
+void get_safe_registers(unsigned long *regs)
+{
+ memcpy(regs, exec_regs, sizeof(exec_regs));
+}
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index b98f7ea2d2f6..e9800b0b5689 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -1,26 +1,21 @@
/*
* Copyright (C) 2004 PathScale, Inc
+ * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include <signal.h>
-#include <stdio.h>
-#include <unistd.h>
#include <stdlib.h>
-#include <errno.h>
#include <stdarg.h>
-#include <string.h>
-#include <sys/mman.h>
-#include "user.h"
-#include "signal_kern.h"
-#include "sysdep/sigcontext.h"
-#include "sysdep/barrier.h"
-#include "sigcontext.h"
-#include "mode.h"
+#include <errno.h>
+#include <signal.h>
+#include <strings.h>
#include "os.h"
+#include "sysdep/barrier.h"
+#include "sysdep/sigcontext.h"
+#include "user.h"
-/* These are the asynchronous signals. SIGVTALRM and SIGARLM are handled
- * together under SIGVTALRM_BIT. SIGPROF is excluded because we want to
+/*
+ * These are the asynchronous signals. SIGPROF is excluded because we want to
* be able to profile all of UML, not just the non-critical sections. If
* profiling is not thread-safe, then that is not my problem. We can disable
* profiling when SMP is enabled in that case.
@@ -31,10 +26,8 @@
#define SIGVTALRM_BIT 1
#define SIGVTALRM_MASK (1 << SIGVTALRM_BIT)
-#define SIGALRM_BIT 2
-#define SIGALRM_MASK (1 << SIGALRM_BIT)
-
-/* These are used by both the signal handlers and
+/*
+ * These are used by both the signal handlers and
* block/unblock_signals. I don't want modifications cached in a
* register - they must go straight to memory.
*/
@@ -46,34 +39,27 @@ void sig_handler(int sig, struct sigcontext *sc)
int enabled;
enabled = signals_enabled;
- if(!enabled && (sig == SIGIO)){
+ if (!enabled && (sig == SIGIO)) {
pending |= SIGIO_MASK;
return;
}
block_signals();
- CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas,
- sig, sc);
+ sig_handler_common_skas(sig, sc);
set_signals(enabled);
}
-static void real_alarm_handler(int sig, struct sigcontext *sc)
+static void real_alarm_handler(struct sigcontext *sc)
{
- union uml_pt_regs regs;
+ struct uml_pt_regs regs;
- if(sig == SIGALRM)
- switch_timers(0);
-
- if(sc != NULL)
+ if (sc != NULL)
copy_sc(&regs, sc);
- regs.skas.is_user = 0;
+ regs.is_user = 0;
unblock_signals();
- timer_handler(sig, &regs);
-
- if(sig == SIGALRM)
- switch_timers(1);
+ timer_handler(SIGVTALRM, &regs);
}
void alarm_handler(int sig, struct sigcontext *sc)
@@ -81,27 +67,30 @@ void alarm_handler(int sig, struct sigcontext *sc)
int enabled;
enabled = signals_enabled;
- if(!signals_enabled){
- if(sig == SIGVTALRM)
- pending |= SIGVTALRM_MASK;
- else pending |= SIGALRM_MASK;
-
+ if (!signals_enabled) {
+ pending |= SIGVTALRM_MASK;
return;
}
block_signals();
- real_alarm_handler(sig, sc);
+ real_alarm_handler(sc);
set_signals(enabled);
}
+void timer_init(void)
+{
+ set_handler(SIGVTALRM, (__sighandler_t) alarm_handler,
+ SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, -1);
+}
+
void set_sigstack(void *sig_stack, int size)
{
stack_t stack = ((stack_t) { .ss_flags = 0,
.ss_sp = (__ptr_t) sig_stack,
.ss_size = size - sizeof(void *) });
- if(sigaltstack(&stack, NULL) != 0)
+ if (sigaltstack(&stack, NULL) != 0)
panic("enabling signal stack failed, errno = %d\n", errno);
}
@@ -111,7 +100,7 @@ void remove_sigstack(void)
.ss_sp = NULL,
.ss_size = 0 });
- if(sigaltstack(&stack, NULL) != 0)
+ if (sigaltstack(&stack, NULL) != 0)
panic("disabling signal stack failed, errno = %d\n", errno);
}
@@ -135,26 +124,27 @@ void handle_signal(int sig, struct sigcontext *sc)
* with this interrupt.
*/
bail = to_irq_stack(&pending);
- if(bail)
+ if (bail)
return;
nested = pending & 1;
pending &= ~1;
- while((sig = ffs(pending)) != 0){
+ while ((sig = ffs(pending)) != 0){
sig--;
pending &= ~(1 << sig);
(*handlers[sig])(sig, sc);
}
- /* Again, pending comes back with a mask of signals
+ /*
+ * Again, pending comes back with a mask of signals
* that arrived while tearing down the stack. If this
* is non-zero, we just go back, set up the stack
* again, and handle the new interrupts.
*/
- if(!nested)
+ if (!nested)
pending = from_irq_stack(nested);
- } while(pending);
+ } while (pending);
}
extern void hard_handler(int sig);
@@ -172,18 +162,18 @@ void set_handler(int sig, void (*handler)(int), int flags, ...)
sigemptyset(&action.sa_mask);
va_start(ap, flags);
- while((mask = va_arg(ap, int)) != -1)
+ while ((mask = va_arg(ap, int)) != -1)
sigaddset(&action.sa_mask, mask);
va_end(ap);
action.sa_flags = flags;
action.sa_restorer = NULL;
- if(sigaction(sig, &action, NULL) < 0)
+ if (sigaction(sig, &action, NULL) < 0)
panic("sigaction failed - errno = %d\n", errno);
sigemptyset(&sig_mask);
sigaddset(&sig_mask, sig);
- if(sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0)
+ if (sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0)
panic("sigprocmask failed - errno = %d\n", errno);
}
@@ -194,13 +184,14 @@ int change_sig(int signal, int on)
sigemptyset(&sigset);
sigaddset(&sigset, signal);
sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old);
- return(!sigismember(&old, signal));
+ return !sigismember(&old, signal);
}
void block_signals(void)
{
signals_enabled = 0;
- /* This must return with signals disabled, so this barrier
+ /*
+ * This must return with signals disabled, so this barrier
* ensures that writes are flushed out before the return.
* This might matter if gcc figures out how to inline this and
* decides to shuffle this code into the caller.
@@ -212,27 +203,31 @@ void unblock_signals(void)
{
int save_pending;
- if(signals_enabled == 1)
+ if (signals_enabled == 1)
return;
- /* We loop because the IRQ handler returns with interrupts off. So,
+ /*
+ * We loop because the IRQ handler returns with interrupts off. So,
* interrupts may have arrived and we need to re-enable them and
* recheck pending.
*/
- while(1){
- /* Save and reset save_pending after enabling signals. This
+ while(1) {
+ /*
+ * Save and reset save_pending after enabling signals. This
* way, pending won't be changed while we're reading it.
*/
signals_enabled = 1;
- /* Setting signals_enabled and reading pending must
+ /*
+ * Setting signals_enabled and reading pending must
* happen in this order.
*/
mb();
save_pending = pending;
- if(save_pending == 0){
- /* This must return with signals enabled, so
+ if (save_pending == 0) {
+ /*
+ * This must return with signals enabled, so
* this barrier ensures that writes are
* flushed out before the return. This might
* matter if gcc figures out how to inline
@@ -245,26 +240,24 @@ void unblock_signals(void)
pending = 0;
- /* We have pending interrupts, so disable signals, as the
+ /*
+ * We have pending interrupts, so disable signals, as the
* handlers expect them off when they are called. They will
* be enabled again above.
*/
signals_enabled = 0;
- /* Deal with SIGIO first because the alarm handler might
+ /*
+ * Deal with SIGIO first because the alarm handler might
* schedule, leaving the pending SIGIO stranded until we come
* back here.
*/
- if(save_pending & SIGIO_MASK)
- CHOOSE_MODE_PROC(sig_handler_common_tt,
- sig_handler_common_skas, SIGIO, NULL);
-
- if(save_pending & SIGALRM_MASK)
- real_alarm_handler(SIGALRM, NULL);
+ if (save_pending & SIGIO_MASK)
+ sig_handler_common_skas(SIGIO, NULL);
- if(save_pending & SIGVTALRM_MASK)
- real_alarm_handler(SIGVTALRM, NULL);
+ if (save_pending & SIGVTALRM_MASK)
+ real_alarm_handler(NULL);
}
}
@@ -276,11 +269,11 @@ int get_signals(void)
int set_signals(int enable)
{
int ret;
- if(signals_enabled == enable)
+ if (signals_enabled == enable)
return enable;
ret = signals_enabled;
- if(enable)
+ if (enable)
unblock_signals();
else block_signals();
diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c
index 0f7df4eb903f..484e68f9f7ae 100644
--- a/arch/um/os-Linux/skas/mem.c
+++ b/arch/um/os-Linux/skas/mem.c
@@ -1,31 +1,26 @@
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include <signal.h>
+#include <stddef.h>
+#include <unistd.h>
#include <errno.h>
#include <string.h>
-#include <unistd.h>
#include <sys/mman.h>
-#include <sys/wait.h>
-#include <asm/page.h>
-#include <asm/unistd.h>
-#include "mem_user.h"
-#include "mem.h"
-#include "skas.h"
-#include "user.h"
+#include "init.h"
+#include "kern_constants.h"
+#include "as-layout.h"
+#include "mm_id.h"
#include "os.h"
#include "proc_mm.h"
#include "ptrace_user.h"
-#include "kern_util.h"
-#include "task.h"
#include "registers.h"
-#include "uml-config.h"
+#include "skas.h"
+#include "user.h"
#include "sysdep/ptrace.h"
#include "sysdep/stub.h"
-#include "init.h"
-#include "kern_constants.h"
+#include "uml-config.h"
extern unsigned long batch_syscall_stub, __syscall_stub_start;
@@ -34,7 +29,7 @@ extern void wait_stub_done(int pid);
static inline unsigned long *check_init_stack(struct mm_id * mm_idp,
unsigned long *stack)
{
- if(stack == NULL) {
+ if (stack == NULL) {
stack = (unsigned long *) mm_idp->stack + 2;
*stack = 0;
}
@@ -45,8 +40,8 @@ static unsigned long syscall_regs[MAX_REG_NR];
static int __init init_syscall_regs(void)
{
- get_safe_registers(syscall_regs, NULL);
- syscall_regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
+ get_safe_registers(syscall_regs);
+ syscall_regs[REGS_IP_INDEX] = STUB_CODE +
((unsigned long) &batch_syscall_stub -
(unsigned long) &__syscall_stub_start);
return 0;
@@ -68,29 +63,30 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr)
unsigned long * syscall;
int err, pid = mm_idp->u.pid;
- if(proc_mm)
+ if (proc_mm)
/* FIXME: Need to look up userspace_pid by cpu */
pid = userspace_pid[0];
multi_count++;
n = ptrace_setregs(pid, syscall_regs);
- if(n < 0){
- printk("Registers - \n");
- for(i = 0; i < MAX_REG_NR; i++)
- printk("\t%d\t0x%lx\n", i, syscall_regs[i]);
+ if (n < 0) {
+ printk(UM_KERN_ERR "Registers - \n");
+ for (i = 0; i < MAX_REG_NR; i++)
+ printk(UM_KERN_ERR "\t%d\t0x%lx\n", i, syscall_regs[i]);
panic("do_syscall_stub : PTRACE_SETREGS failed, errno = %d\n",
-n);
}
err = ptrace(PTRACE_CONT, pid, 0, 0);
- if(err)
+ if (err)
panic("Failed to continue stub, pid = %d, errno = %d\n", pid,
errno);
wait_stub_done(pid);
- /* When the stub stops, we find the following values on the
+ /*
+ * When the stub stops, we find the following values on the
* beginning of the stack:
* (long )return_value
* (long )offset to failed sycall-data (0, if no error)
@@ -98,26 +94,26 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr)
ret = *((unsigned long *) mm_idp->stack);
offset = *((unsigned long *) mm_idp->stack + 1);
if (offset) {
- data = (unsigned long *)(mm_idp->stack +
- offset - UML_CONFIG_STUB_DATA);
- printk("do_syscall_stub : ret = %ld, offset = %ld, "
+ data = (unsigned long *)(mm_idp->stack + offset - STUB_DATA);
+ printk(UM_KERN_ERR "do_syscall_stub : ret = %ld, offset = %ld, "
"data = %p\n", ret, offset, data);
syscall = (unsigned long *)((unsigned long)data + data[0]);
- printk("do_syscall_stub: syscall %ld failed, return value = "
- "0x%lx, expected return value = 0x%lx\n",
+ printk(UM_KERN_ERR "do_syscall_stub: syscall %ld failed, "
+ "return value = 0x%lx, expected return value = 0x%lx\n",
syscall[0], ret, syscall[7]);
- printk(" syscall parameters: "
+ printk(UM_KERN_ERR " syscall parameters: "
"0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n",
syscall[1], syscall[2], syscall[3],
syscall[4], syscall[5], syscall[6]);
- for(n = 1; n < data[0]/sizeof(long); n++) {
- if(n == 1)
- printk(" additional syscall data:");
- if(n % 4 == 1)
- printk("\n ");
+ for (n = 1; n < data[0]/sizeof(long); n++) {
+ if (n == 1)
+ printk(UM_KERN_ERR " additional syscall "
+ "data:");
+ if (n % 4 == 1)
+ printk("\n" UM_KERN_ERR " ");
printk(" 0x%lx", data[n]);
}
- if(n > 1)
+ if (n > 1)
printk("\n");
}
else ret = 0;
@@ -133,7 +129,7 @@ long run_syscall_stub(struct mm_id * mm_idp, int syscall,
{
unsigned long *stack = check_init_stack(mm_idp, *addr);
- if(done && *addr == NULL)
+ if (done && *addr == NULL)
single_count++;
*stack += sizeof(long);
@@ -150,8 +146,8 @@ long run_syscall_stub(struct mm_id * mm_idp, int syscall,
*stack = 0;
multi_op_count++;
- if(!done && ((((unsigned long) stack) & ~UM_KERN_PAGE_MASK) <
- UM_KERN_PAGE_SIZE - 10 * sizeof(long))){
+ if (!done && ((((unsigned long) stack) & ~UM_KERN_PAGE_MASK) <
+ UM_KERN_PAGE_SIZE - 10 * sizeof(long))) {
*addr = stack;
return 0;
}
@@ -166,14 +162,15 @@ long syscall_stub_data(struct mm_id * mm_idp,
unsigned long *stack;
int ret = 0;
- /* If *addr still is uninitialized, it *must* contain NULL.
+ /*
+ * If *addr still is uninitialized, it *must* contain NULL.
* Thus in this case do_syscall_stub correctly won't be called.
*/
- if((((unsigned long) *addr) & ~UM_KERN_PAGE_MASK) >=
+ if ((((unsigned long) *addr) & ~UM_KERN_PAGE_MASK) >=
UM_KERN_PAGE_SIZE - (10 + data_count) * sizeof(long)) {
ret = do_syscall_stub(mm_idp, addr);
/* in case of error, don't overwrite data on stack */
- if(ret)
+ if (ret)
return ret;
}
@@ -185,7 +182,7 @@ long syscall_stub_data(struct mm_id * mm_idp,
memcpy(stack + 1, data, data_count * sizeof(long));
*stub_addr = (void *)(((unsigned long)(stack + 1) &
- ~UM_KERN_PAGE_MASK) + UML_CONFIG_STUB_DATA);
+ ~UM_KERN_PAGE_MASK) + STUB_DATA);
return 0;
}
@@ -195,7 +192,7 @@ int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, int prot,
{
int ret;
- if(proc_mm){
+ if (proc_mm) {
struct proc_mm_op map;
int fd = mm_idp->u.mm_fd;
@@ -211,9 +208,10 @@ int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, int prot,
.offset= offset
} } } );
CATCH_EINTR(ret = write(fd, &map, sizeof(map)));
- if(ret != sizeof(map)){
+ if (ret != sizeof(map)) {
ret = -errno;
- printk("map : /proc/mm map failed, err = %d\n", -ret);
+ printk(UM_KERN_ERR "map : /proc/mm map failed, "
+ "err = %d\n", -ret);
}
else ret = 0;
}
@@ -234,7 +232,7 @@ int unmap(struct mm_id * mm_idp, unsigned long addr, unsigned long len,
{
int ret;
- if(proc_mm){
+ if (proc_mm) {
struct proc_mm_op unmap;
int fd = mm_idp->u.mm_fd;
@@ -245,9 +243,10 @@ int unmap(struct mm_id * mm_idp, unsigned long addr, unsigned long len,
(unsigned long) addr,
.len = len } } } );
CATCH_EINTR(ret = write(fd, &unmap, sizeof(unmap)));
- if(ret != sizeof(unmap)){
+ if (ret != sizeof(unmap)) {
ret = -errno;
- printk("unmap - proc_mm write returned %d\n", ret);
+ printk(UM_KERN_ERR "unmap - proc_mm write returned "
+ "%d\n", ret);
}
else ret = 0;
}
@@ -268,7 +267,7 @@ int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len,
struct proc_mm_op protect;
int ret;
- if(proc_mm){
+ if (proc_mm) {
int fd = mm_idp->u.mm_fd;
protect = ((struct proc_mm_op) { .op = MM_MPROTECT,
@@ -280,9 +279,9 @@ int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len,
.prot = prot } } } );
CATCH_EINTR(ret = write(fd, &protect, sizeof(protect)));
- if(ret != sizeof(protect)){
+ if (ret != sizeof(protect)) {
ret = -errno;
- printk("protect failed, err = %d", -ret);
+ printk(UM_KERN_ERR "protect failed, err = %d", -ret);
}
else ret = 0;
}
@@ -295,7 +294,3 @@ int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len,
return ret;
}
-
-void before_mem_skas(unsigned long unused)
-{
-}
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index ba9af8d62055..d77c81d7068a 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -1,48 +1,38 @@
/*
- * Copyright (C) 2002- 2004 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2002- 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
#include <stdlib.h>
-#include <string.h>
#include <unistd.h>
-#include <errno.h>
-#include <signal.h>
#include <sched.h>
-#include "ptrace_user.h"
-#include <sys/wait.h>
+#include <errno.h>
+#include <string.h>
#include <sys/mman.h>
-#include <sys/user.h>
-#include <sys/time.h>
-#include <sys/syscall.h>
-#include <asm/types.h>
-#include "user.h"
-#include "sysdep/ptrace.h"
-#include "kern_util.h"
-#include "skas.h"
-#include "stub-data.h"
-#include "mm_id.h"
-#include "sysdep/sigcontext.h"
-#include "sysdep/stub.h"
-#include "os.h"
-#include "proc_mm.h"
-#include "skas_ptrace.h"
+#include <sys/ptrace.h>
+#include <sys/wait.h>
+#include <asm/unistd.h>
+#include "as-layout.h"
#include "chan_user.h"
-#include "registers.h"
+#include "kern_constants.h"
#include "mem.h"
-#include "uml-config.h"
+#include "os.h"
#include "process.h"
-#include "longjmp.h"
-#include "kern_constants.h"
-#include "as-layout.h"
+#include "proc_mm.h"
+#include "ptrace_user.h"
+#include "registers.h"
+#include "skas.h"
+#include "skas_ptrace.h"
+#include "user.h"
+#include "sysdep/stub.h"
int is_skas_winch(int pid, int fd, void *data)
{
- if(pid != os_getpgrp())
- return(0);
+ if (pid != getpgrp())
+ return 0;
register_winch_irq(-1, fd, -1, data, 0);
- return(1);
+ return 1;
}
static int ptrace_dump_regs(int pid)
@@ -50,13 +40,12 @@ static int ptrace_dump_regs(int pid)
unsigned long regs[MAX_REG_NR];
int i;
- if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
+ if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
return -errno;
- else {
- printk("Stub registers -\n");
- for(i = 0; i < ARRAY_SIZE(regs); i++)
- printk("\t%d - %lx\n", i, regs[i]);
- }
+
+ printk(UM_KERN_ERR "Stub registers -\n");
+ for (i = 0; i < ARRAY_SIZE(regs); i++)
+ printk(UM_KERN_ERR "\t%d - %lx\n", i, regs[i]);
return 0;
}
@@ -74,27 +63,28 @@ void wait_stub_done(int pid)
{
int n, status, err;
- while(1){
+ while (1) {
CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
- if((n < 0) || !WIFSTOPPED(status))
+ if ((n < 0) || !WIFSTOPPED(status))
goto bad_wait;
- if(((1 << WSTOPSIG(status)) & STUB_SIG_MASK) == 0)
+ if (((1 << WSTOPSIG(status)) & STUB_SIG_MASK) == 0)
break;
err = ptrace(PTRACE_CONT, pid, 0, 0);
- if(err)
+ if (err)
panic("wait_stub_done : continue failed, errno = %d\n",
errno);
}
- if(((1 << WSTOPSIG(status)) & STUB_DONE_MASK) != 0)
+ if (((1 << WSTOPSIG(status)) & STUB_DONE_MASK) != 0)
return;
bad_wait:
err = ptrace_dump_regs(pid);
- if(err)
- printk("Failed to get registers from stub, errno = %d\n", -err);
+ if (err)
+ printk(UM_KERN_ERR "Failed to get registers from stub, "
+ "errno = %d\n", -err);
panic("wait_stub_done : failed to wait for SIGUSR1/SIGTRAP, pid = %d, "
"n = %d, errno = %d, status = 0x%x\n", pid, n, errno, status);
}
@@ -105,9 +95,9 @@ void get_skas_faultinfo(int pid, struct faultinfo * fi)
{
int err;
- if(ptrace_faultinfo){
+ if (ptrace_faultinfo) {
err = ptrace(PTRACE_FAULTINFO, pid, 0, fi);
- if(err)
+ if (err)
panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, "
"errno = %d\n", errno);
@@ -119,52 +109,57 @@ void get_skas_faultinfo(int pid, struct faultinfo * fi)
}
else {
err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV);
- if(err)
+ if (err)
panic("Failed to continue stub, pid = %d, errno = %d\n",
pid, errno);
wait_stub_done(pid);
- /* faultinfo is prepared by the stub-segv-handler at start of
+ /*
+ * faultinfo is prepared by the stub-segv-handler at start of
* the stub stack page. We just have to copy it.
*/
memcpy(fi, (void *)current_stub_stack(), sizeof(*fi));
}
}
-static void handle_segv(int pid, union uml_pt_regs * regs)
+static void handle_segv(int pid, struct uml_pt_regs * regs)
{
- get_skas_faultinfo(pid, &regs->skas.faultinfo);
- segv(regs->skas.faultinfo, 0, 1, NULL);
+ get_skas_faultinfo(pid, &regs->faultinfo);
+ segv(regs->faultinfo, 0, 1, NULL);
}
-/*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/
-static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu)
+/*
+ * To use the same value of using_sysemu as the caller, ask it that value
+ * (in local_using_sysemu
+ */
+static void handle_trap(int pid, struct uml_pt_regs *regs,
+ int local_using_sysemu)
{
int err, status;
/* Mark this as a syscall */
- UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->skas.regs);
+ UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->gp);
if (!local_using_sysemu)
{
err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
__NR_getpid);
- if(err < 0)
- panic("handle_trap - nullifying syscall failed errno = %d\n",
- errno);
+ if (err < 0)
+ panic("handle_trap - nullifying syscall failed, "
+ "errno = %d\n", errno);
err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
- if(err < 0)
- panic("handle_trap - continuing to end of syscall failed, "
- "errno = %d\n", errno);
+ if (err < 0)
+ panic("handle_trap - continuing to end of syscall "
+ "failed, errno = %d\n", errno);
CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
- if((err < 0) || !WIFSTOPPED(status) ||
- (WSTOPSIG(status) != SIGTRAP + 0x80)){
+ if ((err < 0) || !WIFSTOPPED(status) ||
+ (WSTOPSIG(status) != SIGTRAP + 0x80)) {
err = ptrace_dump_regs(pid);
- if(err)
- printk("Failed to get registers from process, "
- "errno = %d\n", -err);
+ if (err)
+ printk(UM_KERN_ERR "Failed to get registers "
+ "from process, errno = %d\n", -err);
panic("handle_trap - failed to wait at end of syscall, "
"errno = %d, status = %d\n", errno, status);
}
@@ -182,63 +177,64 @@ static int userspace_tramp(void *stack)
ptrace(PTRACE_TRACEME, 0, 0, 0);
- init_new_thread_signals();
- err = set_interval(1);
- if(err)
+ signal(SIGTERM, SIG_DFL);
+ err = set_interval();
+ if (err)
panic("userspace_tramp - setting timer failed, errno = %d\n",
err);
- if(!proc_mm){
- /* This has a pte, but it can't be mapped in with the usual
+ if (!proc_mm) {
+ /*
+ * This has a pte, but it can't be mapped in with the usual
* tlb_flush mechanism because this is part of that mechanism
*/
int fd;
- __u64 offset;
+ unsigned long long offset;
fd = phys_mapping(to_phys(&__syscall_stub_start), &offset);
- addr = mmap64((void *) UML_CONFIG_STUB_CODE, UM_KERN_PAGE_SIZE,
+ addr = mmap64((void *) STUB_CODE, UM_KERN_PAGE_SIZE,
PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset);
- if(addr == MAP_FAILED){
- printk("mapping mmap stub failed, errno = %d\n",
- errno);
+ if (addr == MAP_FAILED) {
+ printk(UM_KERN_ERR "mapping mmap stub at 0x%lx failed, "
+ "errno = %d\n", STUB_CODE, errno);
exit(1);
}
- if(stack != NULL){
+ if (stack != NULL) {
fd = phys_mapping(to_phys(stack), &offset);
- addr = mmap((void *) UML_CONFIG_STUB_DATA,
+ addr = mmap((void *) STUB_DATA,
UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
MAP_FIXED | MAP_SHARED, fd, offset);
- if(addr == MAP_FAILED){
- printk("mapping segfault stack failed, "
- "errno = %d\n", errno);
+ if (addr == MAP_FAILED) {
+ printk(UM_KERN_ERR "mapping segfault stack "
+ "at 0x%lx failed, errno = %d\n",
+ STUB_DATA, errno);
exit(1);
}
}
}
- if(!ptrace_faultinfo && (stack != NULL)){
+ if (!ptrace_faultinfo && (stack != NULL)) {
struct sigaction sa;
- unsigned long v = UML_CONFIG_STUB_CODE +
+ unsigned long v = STUB_CODE +
(unsigned long) stub_segv_handler -
(unsigned long) &__syscall_stub_start;
- set_sigstack((void *) UML_CONFIG_STUB_DATA, UM_KERN_PAGE_SIZE);
+ set_sigstack((void *) STUB_DATA, UM_KERN_PAGE_SIZE);
sigemptyset(&sa.sa_mask);
sigaddset(&sa.sa_mask, SIGIO);
sigaddset(&sa.sa_mask, SIGWINCH);
- sigaddset(&sa.sa_mask, SIGALRM);
sigaddset(&sa.sa_mask, SIGVTALRM);
sigaddset(&sa.sa_mask, SIGUSR1);
sa.sa_flags = SA_ONSTACK;
sa.sa_handler = (void *) v;
sa.sa_restorer = NULL;
- if(sigaction(SIGSEGV, &sa, NULL) < 0)
+ if (sigaction(SIGSEGV, &sa, NULL) < 0)
panic("userspace_tramp - setting SIGSEGV handler "
"failed - errno = %d\n", errno);
}
- os_stop_process(os_getpid());
- return(0);
+ kill(os_getpid(), SIGSTOP);
+ return 0;
}
/* Each element set once, and only accessed by a single processor anyway */
@@ -255,44 +251,55 @@ int start_userspace(unsigned long stub_stack)
stack = mmap(NULL, UM_KERN_PAGE_SIZE,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if(stack == MAP_FAILED)
+ if (stack == MAP_FAILED)
panic("start_userspace : mmap failed, errno = %d", errno);
sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *);
flags = CLONE_FILES | SIGCHLD;
- if(proc_mm) flags |= CLONE_VM;
+ if (proc_mm)
+ flags |= CLONE_VM;
+
pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack);
- if(pid < 0)
+ if (pid < 0)
panic("start_userspace : clone failed, errno = %d", errno);
do {
CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
- if(n < 0)
+ if (n < 0)
panic("start_userspace : wait failed, errno = %d",
errno);
- } while(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM));
+ } while (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM));
- if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP))
+ if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP))
panic("start_userspace : expected SIGSTOP, got status = %d",
status);
- if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, (void *)PTRACE_O_TRACESYSGOOD) < 0)
- panic("start_userspace : PTRACE_OLDSETOPTIONS failed, errno=%d\n",
- errno);
+ if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
+ (void *) PTRACE_O_TRACESYSGOOD) < 0)
+ panic("start_userspace : PTRACE_OLDSETOPTIONS failed, "
+ "errno = %d\n", errno);
- if(munmap(stack, UM_KERN_PAGE_SIZE) < 0)
+ if (munmap(stack, UM_KERN_PAGE_SIZE) < 0)
panic("start_userspace : munmap failed, errno = %d\n", errno);
- return(pid);
+ return pid;
}
-void userspace(union uml_pt_regs *regs)
+void userspace(struct uml_pt_regs *regs)
{
+ struct itimerval timer;
+ unsigned long long nsecs, now;
int err, status, op, pid = userspace_pid[0];
/* To prevent races if using_sysemu changes under us.*/
int local_using_sysemu;
- while(1){
+ if (getitimer(ITIMER_VIRTUAL, &timer))
+ printk("Failed to get itimer, errno = %d\n", errno);
+ nsecs = timer.it_value.tv_sec * UM_NSEC_PER_SEC +
+ timer.it_value.tv_usec * UM_NSEC_PER_USEC;
+ nsecs += os_nsecs();
+
+ while (1) {
restore_registers(pid, regs);
/* Now we set local_using_sysemu to be used for one loop */
@@ -302,26 +309,28 @@ void userspace(union uml_pt_regs *regs)
singlestepping(NULL));
err = ptrace(op, pid, 0, 0);
- if(err)
+ if (err)
panic("userspace - could not resume userspace process, "
"pid=%d, ptrace operation = %d, errno = %d\n",
pid, op, errno);
CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
- if(err < 0)
+ if (err < 0)
panic("userspace - waitpid failed, errno = %d\n",
errno);
- regs->skas.is_user = 1;
+ regs->is_user = 1;
save_registers(pid, regs);
UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */
- if(WIFSTOPPED(status)){
+ if (WIFSTOPPED(status)) {
int sig = WSTOPSIG(status);
- switch(sig){
+ switch(sig) {
case SIGSEGV:
- if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo){
- get_skas_faultinfo(pid, &regs->skas.faultinfo);
+ if (PTRACE_FULL_FAULTINFO ||
+ !ptrace_faultinfo) {
+ get_skas_faultinfo(pid,
+ &regs->faultinfo);
(*sig_info[SIGSEGV])(SIGSEGV, regs);
}
else handle_segv(pid, regs);
@@ -332,8 +341,20 @@ void userspace(union uml_pt_regs *regs)
case SIGTRAP:
relay_signal(SIGTRAP, regs);
break;
- case SIGIO:
case SIGVTALRM:
+ now = os_nsecs();
+ if(now < nsecs)
+ break;
+ block_signals();
+ (*sig_info[sig])(sig, regs);
+ unblock_signals();
+ nsecs = timer.it_value.tv_sec *
+ UM_NSEC_PER_SEC +
+ timer.it_value.tv_usec *
+ UM_NSEC_PER_USEC;
+ nsecs += os_nsecs();
+ break;
+ case SIGIO:
case SIGILL:
case SIGBUS:
case SIGFPE:
@@ -343,30 +364,29 @@ void userspace(union uml_pt_regs *regs)
unblock_signals();
break;
default:
- printk("userspace - child stopped with signal "
- "%d\n", sig);
+ printk(UM_KERN_ERR "userspace - child stopped "
+ "with signal %d\n", sig);
}
pid = userspace_pid[0];
interrupt_end();
/* Avoid -ERESTARTSYS handling in host */
- if(PT_SYSCALL_NR_OFFSET != PT_SYSCALL_RET_OFFSET)
- PT_SYSCALL_NR(regs->skas.regs) = -1;
+ if (PT_SYSCALL_NR_OFFSET != PT_SYSCALL_RET_OFFSET)
+ PT_SYSCALL_NR(regs->gp) = -1;
}
}
}
static unsigned long thread_regs[MAX_REG_NR];
-static unsigned long thread_fp_regs[HOST_FP_SIZE];
static int __init init_thread_regs(void)
{
- get_safe_registers(thread_regs, thread_fp_regs);
+ get_safe_registers(thread_regs);
/* Set parent's instruction pointer to start of clone-stub */
- thread_regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
+ thread_regs[REGS_IP_INDEX] = STUB_CODE +
(unsigned long) stub_clone_handler -
(unsigned long) &__syscall_stub_start;
- thread_regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + UM_KERN_PAGE_SIZE -
+ thread_regs[REGS_SP_INDEX] = STUB_DATA + UM_KERN_PAGE_SIZE -
sizeof(void *);
#ifdef __SIGNAL_FRAMESIZE
thread_regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE;
@@ -378,53 +398,53 @@ __initcall(init_thread_regs);
int copy_context_skas0(unsigned long new_stack, int pid)
{
+ struct timeval tv = { .tv_sec = 0, .tv_usec = UM_USEC_PER_SEC / UM_HZ };
int err;
unsigned long current_stack = current_stub_stack();
struct stub_data *data = (struct stub_data *) current_stack;
struct stub_data *child_data = (struct stub_data *) new_stack;
- __u64 new_offset;
+ unsigned long long new_offset;
int new_fd = phys_mapping(to_phys((void *)new_stack), &new_offset);
- /* prepare offset and fd of child's stack as argument for parent's
+ /*
+ * prepare offset and fd of child's stack as argument for parent's
* and child's mmap2 calls
*/
*data = ((struct stub_data) { .offset = MMAP_OFFSET(new_offset),
.fd = new_fd,
.timer = ((struct itimerval)
- { { 0, 1000000 / hz() },
- { 0, 1000000 / hz() }})});
+ { .it_value = tv,
+ .it_interval = tv }) });
+
err = ptrace_setregs(pid, thread_regs);
- if(err < 0)
+ if (err < 0)
panic("copy_context_skas0 : PTRACE_SETREGS failed, "
"pid = %d, errno = %d\n", pid, -err);
- err = ptrace_setfpregs(pid, thread_fp_regs);
- if(err < 0)
- panic("copy_context_skas0 : PTRACE_SETFPREGS failed, "
- "pid = %d, errno = %d\n", pid, -err);
-
/* set a well known return code for detection of child write failure */
child_data->err = 12345678;
- /* Wait, until parent has finished its work: read child's pid from
+ /*
+ * Wait, until parent has finished its work: read child's pid from
* parent's stack, and check, if bad result.
*/
err = ptrace(PTRACE_CONT, pid, 0, 0);
- if(err)
+ if (err)
panic("Failed to continue new process, pid = %d, "
"errno = %d\n", pid, errno);
wait_stub_done(pid);
pid = data->err;
- if(pid < 0)
+ if (pid < 0)
panic("copy_context_skas0 - stub-parent reports error %d\n",
-pid);
- /* Wait, until child has finished too: read child's result from
+ /*
+ * Wait, until child has finished too: read child's result from
* child's stack and check it.
*/
wait_stub_done(pid);
- if (child_data->err != UML_CONFIG_STUB_DATA)
+ if (child_data->err != STUB_DATA)
panic("copy_context_skas0 - stub-child reports error %ld\n",
child_data->err);
@@ -446,7 +466,7 @@ void map_stub_pages(int fd, unsigned long code,
{
struct proc_mm_op mmop;
int n;
- __u64 code_offset;
+ unsigned long long code_offset;
int code_fd = phys_mapping(to_phys((void *) &__syscall_stub_start),
&code_offset);
@@ -461,16 +481,17 @@ void map_stub_pages(int fd, unsigned long code,
.offset = code_offset
} } });
CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop)));
- if(n != sizeof(mmop)){
+ if (n != sizeof(mmop)) {
n = errno;
- printk("mmap args - addr = 0x%lx, fd = %d, offset = %llx\n",
- code, code_fd, (unsigned long long) code_offset);
+ printk(UM_KERN_ERR "mmap args - addr = 0x%lx, fd = %d, "
+ "offset = %llx\n", code, code_fd,
+ (unsigned long long) code_offset);
panic("map_stub_pages : /proc/mm map for code failed, "
"err = %d\n", n);
}
- if ( stack ) {
- __u64 map_offset;
+ if (stack) {
+ unsigned long long map_offset;
int map_fd = phys_mapping(to_phys((void *)stack), &map_offset);
mmop = ((struct proc_mm_op)
{ .op = MM_MMAP,
@@ -484,7 +505,7 @@ void map_stub_pages(int fd, unsigned long code,
.offset = map_offset
} } });
CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop)));
- if(n != sizeof(mmop))
+ if (n != sizeof(mmop))
panic("map_stub_pages : /proc/mm map for data failed, "
"err = %d\n", errno);
}
@@ -504,7 +525,7 @@ void new_thread(void *stack, jmp_buf *buf, void (*handler)(void))
void switch_threads(jmp_buf *me, jmp_buf *you)
{
- if(UML_SETJMP(me) == 0)
+ if (UML_SETJMP(me) == 0)
UML_LONGJMP(you, 1);
}
@@ -520,8 +541,7 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf)
int n;
set_handler(SIGWINCH, (__sighandler_t) sig_handler,
- SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM,
- SIGVTALRM, -1);
+ SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGVTALRM, -1);
/*
* Can't use UML_SETJMP or UML_LONGJMP here because they save
@@ -532,7 +552,7 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf)
* after returning to the jumper.
*/
n = setjmp(initial_jmpbuf);
- switch(n){
+ switch(n) {
case INIT_JMP_NEW_THREAD:
(*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler;
(*switch_buf)[0].JB_SP = (unsigned long) stack +
@@ -544,10 +564,10 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf)
break;
case INIT_JMP_HALT:
kmalloc_ok = 0;
- return(0);
+ return 0;
case INIT_JMP_REBOOT:
kmalloc_ok = 0;
- return(1);
+ return 1;
default:
panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
}
@@ -563,7 +583,7 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg)
cb_back = &here;
block_signals();
- if(UML_SETJMP(&here) == 0)
+ if (UML_SETJMP(&here) == 0)
UML_LONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK);
unblock_signals();
@@ -584,16 +604,16 @@ void reboot_skas(void)
UML_LONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT);
}
-void switch_mm_skas(struct mm_id *mm_idp)
+void __switch_mm(struct mm_id *mm_idp)
{
int err;
- /* FIXME: need cpu pid in switch_mm_skas */
- if(proc_mm){
+ /* FIXME: need cpu pid in __switch_mm */
+ if (proc_mm) {
err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0,
mm_idp->u.mm_fd);
- if(err)
- panic("switch_mm_skas - PTRACE_SWITCH_MM failed, "
+ if (err)
+ panic("__switch_mm - PTRACE_SWITCH_MM failed, "
"errno = %d\n", errno);
}
else userspace_pid[0] = mm_idp->u.pid;
diff --git a/arch/um/os-Linux/skas/trap.c b/arch/um/os-Linux/skas/trap.c
index 3b600c2e63b8..3b1b9244f468 100644
--- a/arch/um/os-Linux/skas/trap.c
+++ b/arch/um/os-Linux/skas/trap.c
@@ -1,37 +1,43 @@
/*
- * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include <signal.h>
-#include <errno.h>
+#if 0
#include "kern_util.h"
-#include "as-layout.h"
-#include "task.h"
-#include "sigcontext.h"
#include "skas.h"
#include "ptrace_user.h"
-#include "sysdep/ptrace.h"
#include "sysdep/ptrace_user.h"
+#endif
+
+#include <errno.h>
+#include <signal.h>
+#include "sysdep/ptrace.h"
+#include "kern_constants.h"
+#include "as-layout.h"
#include "os.h"
+#include "sigcontext.h"
+#include "task.h"
-static union uml_pt_regs ksig_regs[UM_NR_CPUS];
+static struct uml_pt_regs ksig_regs[UM_NR_CPUS];
void sig_handler_common_skas(int sig, void *sc_ptr)
{
struct sigcontext *sc = sc_ptr;
- union uml_pt_regs *r;
- void (*handler)(int, union uml_pt_regs *);
+ struct uml_pt_regs *r;
+ void (*handler)(int, struct uml_pt_regs *);
int save_user, save_errno = errno;
- /* This is done because to allow SIGSEGV to be delivered inside a SEGV
+ /*
+ * This is done because to allow SIGSEGV to be delivered inside a SEGV
* handler. This can happen in copy_user, and if SEGV is disabled,
* the process will die.
* XXX Figure out why this is better than SA_NODEFER
*/
- if(sig == SIGSEGV) {
+ if (sig == SIGSEGV) {
change_sig(SIGSEGV, 1);
- /* For segfaults, we want the data from the
+ /*
+ * For segfaults, we want the data from the
* sigcontext. In this case, we don't want to mangle
* the process registers, so use a static set of
* registers. For other signals, the process
@@ -42,25 +48,22 @@ void sig_handler_common_skas(int sig, void *sc_ptr)
}
else r = TASK_REGS(get_current());
- save_user = r->skas.is_user;
- r->skas.is_user = 0;
- if ( sig == SIGFPE || sig == SIGSEGV ||
- sig == SIGBUS || sig == SIGILL ||
- sig == SIGTRAP ) {
- GET_FAULTINFO_FROM_SC(r->skas.faultinfo, sc);
- }
+ save_user = r->is_user;
+ r->is_user = 0;
+ if ((sig == SIGFPE) || (sig == SIGSEGV) || (sig == SIGBUS) ||
+ (sig == SIGILL) || (sig == SIGTRAP))
+ GET_FAULTINFO_FROM_SC(r->faultinfo, sc);
change_sig(SIGUSR1, 1);
handler = sig_info[sig];
- /* unblock SIGALRM, SIGVTALRM, SIGIO if sig isn't IRQ signal */
- if (sig != SIGIO && sig != SIGWINCH &&
- sig != SIGVTALRM && sig != SIGALRM)
+ /* unblock SIGVTALRM, SIGIO if sig isn't IRQ signal */
+ if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGVTALRM))
unblock_signals();
handler(sig, r);
errno = save_errno;
- r->skas.is_user = save_user;
+ r->is_user = save_user;
}
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 46f613975c19..7b81f6c08a5e 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -1,75 +1,65 @@
/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include <pty.h>
#include <stdio.h>
-#include <stddef.h>
-#include <stdarg.h>
#include <stdlib.h>
-#include <string.h>
+#include <stdarg.h>
#include <unistd.h>
-#include <signal.h>
-#include <sched.h>
-#include <fcntl.h>
#include <errno.h>
-#include <sys/time.h>
-#include <sys/wait.h>
+#include <fcntl.h>
+#include <sched.h>
+#include <signal.h>
+#include <string.h>
#include <sys/mman.h>
-#include <sys/resource.h>
+#include <sys/ptrace.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
#include <asm/unistd.h>
-#include <asm/page.h>
-#include <sys/types.h>
-#include "kern_util.h"
-#include "user.h"
-#include "signal_kern.h"
-#include "sysdep/ptrace.h"
-#include "sysdep/sigcontext.h"
-#include "irq_user.h"
-#include "ptrace_user.h"
-#include "mem_user.h"
#include "init.h"
-#include "os.h"
-#include "uml-config.h"
-#include "choose-mode.h"
-#include "mode.h"
-#include "tempfile.h"
#include "kern_constants.h"
-
-#ifdef UML_CONFIG_MODE_SKAS
-#include "skas.h"
-#include "skas_ptrace.h"
+#include "os.h"
+#include "mem_user.h"
+#include "ptrace_user.h"
#include "registers.h"
-#endif
+#include "skas_ptrace.h"
-static int ptrace_child(void *arg)
+static int ptrace_child(void)
{
int ret;
+ /* Calling os_getpid because some libcs cached getpid incorrectly */
int pid = os_getpid(), ppid = getppid();
int sc_result;
change_sig(SIGWINCH, 0);
- if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){
+ if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) {
perror("ptrace");
- os_kill_process(pid, 0);
+ kill(pid, SIGKILL);
}
kill(pid, SIGSTOP);
- /*This syscall will be intercepted by the parent. Don't call more than
- * once, please.*/
+ /*
+ * This syscall will be intercepted by the parent. Don't call more than
+ * once, please.
+ */
sc_result = os_getpid();
if (sc_result == pid)
- ret = 1; /*Nothing modified by the parent, we are running
- normally.*/
+ /* Nothing modified by the parent, we are running normally. */
+ ret = 1;
else if (sc_result == ppid)
- ret = 0; /*Expected in check_ptrace and check_sysemu when they
- succeed in modifying the stack frame*/
+ /*
+ * Expected in check_ptrace and check_sysemu when they succeed
+ * in modifying the stack frame
+ */
+ ret = 0;
else
- ret = 2; /*Serious trouble! This could be caused by a bug in
- host 2.6 SKAS3/2.6 patch before release -V6, together
- with a bug in the UML code itself.*/
+ /* Serious trouble! This could be caused by a bug in host 2.6
+ * SKAS3/2.6 patch before release -V6, together with a bug in
+ * the UML code itself.
+ */
+ ret = 2;
_exit(ret);
}
@@ -101,29 +91,23 @@ static void non_fatal(char *fmt, ...)
fflush(stdout);
}
-static int start_ptraced_child(void **stack_out)
+static int start_ptraced_child(void)
{
- void *stack;
- unsigned long sp;
int pid, n, status;
- stack = mmap(NULL, UM_KERN_PAGE_SIZE,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if(stack == MAP_FAILED)
- fatal_perror("check_ptrace : mmap failed");
- sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *);
- pid = clone(ptrace_child, (void *) sp, SIGCHLD, NULL);
- if(pid < 0)
- fatal_perror("start_ptraced_child : clone failed");
+ pid = fork();
+ if (pid == 0)
+ ptrace_child();
+ else if (pid < 0)
+ fatal_perror("start_ptraced_child : fork failed");
+
CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
- if(n < 0)
- fatal_perror("check_ptrace : clone failed");
- if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP))
+ if (n < 0)
+ fatal_perror("check_ptrace : waitpid failed");
+ if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP))
fatal("check_ptrace : expected SIGSTOP, got status = %d",
status);
- *stack_out = stack;
return pid;
}
@@ -133,15 +117,14 @@ static int start_ptraced_child(void **stack_out)
* So only for SYSEMU features we test mustpanic, while normal host features
* must work anyway!
*/
-static int stop_ptraced_child(int pid, void *stack, int exitcode,
- int mustexit)
+static int stop_ptraced_child(int pid, int exitcode, int mustexit)
{
int status, n, ret = 0;
- if(ptrace(PTRACE_CONT, pid, 0, 0) < 0)
+ if (ptrace(PTRACE_CONT, pid, 0, 0) < 0)
fatal_perror("stop_ptraced_child : ptrace failed");
CATCH_EINTR(n = waitpid(pid, &status, 0));
- if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) {
+ if (!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) {
int exit_with = WEXITSTATUS(status);
if (exit_with == 2)
non_fatal("check_ptrace : child exited with status 2. "
@@ -154,8 +137,6 @@ static int stop_ptraced_child(int pid, void *stack, int exitcode,
ret = -1;
}
- if(munmap(stack, UM_KERN_PAGE_SIZE) < 0)
- fatal_perror("check_ptrace : munmap failed");
return ret;
}
@@ -207,40 +188,39 @@ __uml_setup("nosysemu", nosysemu_cmd_param,
static void __init check_sysemu(void)
{
- void *stack;
unsigned long regs[MAX_REG_NR];
int pid, n, status, count=0;
non_fatal("Checking syscall emulation patch for ptrace...");
sysemu_supported = 0;
- pid = start_ptraced_child(&stack);
+ pid = start_ptraced_child();
- if(ptrace(PTRACE_SYSEMU, pid, 0, 0) < 0)
+ if (ptrace(PTRACE_SYSEMU, pid, 0, 0) < 0)
goto fail;
CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
if (n < 0)
fatal_perror("check_sysemu : wait failed");
- if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
+ if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
fatal("check_sysemu : expected SIGTRAP, got status = %d",
status);
- if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
+ if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
fatal_perror("check_sysemu : PTRACE_GETREGS failed");
- if(PT_SYSCALL_NR(regs) != __NR_getpid){
+ if (PT_SYSCALL_NR(regs) != __NR_getpid) {
non_fatal("check_sysemu got system call number %d, "
"expected %d...", PT_SYSCALL_NR(regs), __NR_getpid);
goto fail;
}
n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, os_getpid());
- if(n < 0){
+ if (n < 0) {
non_fatal("check_sysemu : failed to modify system call "
"return");
goto fail;
}
- if (stop_ptraced_child(pid, stack, 0, 0) < 0)
+ if (stop_ptraced_child(pid, 0, 0) < 0)
goto fail_stopped;
sysemu_supported = 1;
@@ -248,90 +228,90 @@ static void __init check_sysemu(void)
set_using_sysemu(!force_sysemu_disabled);
non_fatal("Checking advanced syscall emulation patch for ptrace...");
- pid = start_ptraced_child(&stack);
+ pid = start_ptraced_child();
- if((ptrace(PTRACE_OLDSETOPTIONS, pid, 0,
+ if ((ptrace(PTRACE_OLDSETOPTIONS, pid, 0,
(void *) PTRACE_O_TRACESYSGOOD) < 0))
fatal_perror("check_ptrace: PTRACE_OLDSETOPTIONS failed");
- while(1){
+ while (1) {
count++;
- if(ptrace(PTRACE_SYSEMU_SINGLESTEP, pid, 0, 0) < 0)
+ if (ptrace(PTRACE_SYSEMU_SINGLESTEP, pid, 0, 0) < 0)
goto fail;
CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
- if(n < 0)
+ if (n < 0)
fatal_perror("check_ptrace : wait failed");
- if(WIFSTOPPED(status) && (WSTOPSIG(status) == (SIGTRAP|0x80))){
+ if (WIFSTOPPED(status) &&
+ (WSTOPSIG(status) == (SIGTRAP|0x80))) {
if (!count)
fatal("check_ptrace : SYSEMU_SINGLESTEP "
"doesn't singlestep");
n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET,
os_getpid());
- if(n < 0)
+ if (n < 0)
fatal_perror("check_sysemu : failed to modify "
"system call return");
break;
}
- else if(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGTRAP))
+ else if (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGTRAP))
count++;
else
fatal("check_ptrace : expected SIGTRAP or "
"(SIGTRAP | 0x80), got status = %d", status);
}
- if (stop_ptraced_child(pid, stack, 0, 0) < 0)
+ if (stop_ptraced_child(pid, 0, 0) < 0)
goto fail_stopped;
sysemu_supported = 2;
non_fatal("OK\n");
- if ( !force_sysemu_disabled )
+ if (!force_sysemu_disabled)
set_using_sysemu(sysemu_supported);
return;
fail:
- stop_ptraced_child(pid, stack, 1, 0);
+ stop_ptraced_child(pid, 1, 0);
fail_stopped:
non_fatal("missing\n");
}
static void __init check_ptrace(void)
{
- void *stack;
int pid, syscall, n, status;
non_fatal("Checking that ptrace can change system call numbers...");
- pid = start_ptraced_child(&stack);
+ pid = start_ptraced_child();
- if((ptrace(PTRACE_OLDSETOPTIONS, pid, 0,
+ if ((ptrace(PTRACE_OLDSETOPTIONS, pid, 0,
(void *) PTRACE_O_TRACESYSGOOD) < 0))
fatal_perror("check_ptrace: PTRACE_OLDSETOPTIONS failed");
- while(1){
- if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
+ while (1) {
+ if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
fatal_perror("check_ptrace : ptrace failed");
CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
- if(n < 0)
+ if (n < 0)
fatal_perror("check_ptrace : wait failed");
- if(!WIFSTOPPED(status) ||
+ if (!WIFSTOPPED(status) ||
(WSTOPSIG(status) != (SIGTRAP | 0x80)))
fatal("check_ptrace : expected (SIGTRAP|0x80), "
"got status = %d", status);
syscall = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET,
0);
- if(syscall == __NR_getpid){
+ if (syscall == __NR_getpid) {
n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
__NR_getppid);
- if(n < 0)
+ if (n < 0)
fatal_perror("check_ptrace : failed to modify "
"system call");
break;
}
}
- stop_ptraced_child(pid, stack, 0, 1);
+ stop_ptraced_child(pid, 0, 1);
non_fatal("OK\n");
check_sysemu();
}
@@ -343,18 +323,18 @@ static void __init check_coredump_limit(void)
struct rlimit lim;
int err = getrlimit(RLIMIT_CORE, &lim);
- if(err){
+ if (err) {
perror("Getting core dump limit");
return;
}
printf("Core dump limits :\n\tsoft - ");
- if(lim.rlim_cur == RLIM_INFINITY)
+ if (lim.rlim_cur == RLIM_INFINITY)
printf("NONE\n");
else printf("%lu\n", lim.rlim_cur);
printf("\thard - ");
- if(lim.rlim_max == RLIM_INFINITY)
+ if (lim.rlim_max == RLIM_INFINITY)
printf("NONE\n");
else printf("%lu\n", lim.rlim_max);
}
@@ -408,20 +388,18 @@ __uml_setup("noptraceldt", noptraceldt_cmd_param,
" To support PTRACE_LDT, the host needs to be patched using\n"
" the current skas3 patch.\n\n");
-#ifdef UML_CONFIG_MODE_SKAS
static inline void check_skas3_ptrace_faultinfo(void)
{
struct ptrace_faultinfo fi;
- void *stack;
int pid, n;
non_fatal(" - PTRACE_FAULTINFO...");
- pid = start_ptraced_child(&stack);
+ pid = start_ptraced_child();
n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi);
if (n < 0) {
ptrace_faultinfo = 0;
- if(errno == EIO)
+ if (errno == EIO)
non_fatal("not found\n");
else
perror("not found");
@@ -434,13 +412,12 @@ static inline void check_skas3_ptrace_faultinfo(void)
}
init_registers(pid);
- stop_ptraced_child(pid, stack, 1, 1);
+ stop_ptraced_child(pid, 1, 1);
}
static inline void check_skas3_ptrace_ldt(void)
{
#ifdef PTRACE_LDT
- void *stack;
int pid, n;
unsigned char ldtbuf[40];
struct ptrace_ldt ldt_op = (struct ptrace_ldt) {
@@ -449,11 +426,11 @@ static inline void check_skas3_ptrace_ldt(void)
.bytecount = sizeof(ldtbuf)};
non_fatal(" - PTRACE_LDT...");
- pid = start_ptraced_child(&stack);
+ pid = start_ptraced_child();
n = ptrace(PTRACE_LDT, pid, 0, (unsigned long) &ldt_op);
if (n < 0) {
- if(errno == EIO)
+ if (errno == EIO)
non_fatal("not found\n");
else {
perror("not found");
@@ -461,13 +438,13 @@ static inline void check_skas3_ptrace_ldt(void)
ptrace_ldt = 0;
}
else {
- if(ptrace_ldt)
+ if (ptrace_ldt)
non_fatal("found\n");
else
non_fatal("found, but use is disabled\n");
}
- stop_ptraced_child(pid, stack, 1, 1);
+ stop_ptraced_child(pid, 1, 1);
#else
/* PTRACE_LDT might be disabled via cmdline option.
* We want to override this, else we might use the stub
@@ -484,12 +461,9 @@ static inline void check_skas3_proc_mm(void)
proc_mm = 0;
perror("not found");
}
- else {
- if (!proc_mm)
- non_fatal("found but disabled on command line\n");
- else
- non_fatal("found\n");
- }
+ else if (!proc_mm)
+ non_fatal("found but disabled on command line\n");
+ else non_fatal("found\n");
}
int can_do_skas(void)
@@ -500,17 +474,11 @@ int can_do_skas(void)
check_skas3_ptrace_faultinfo();
check_skas3_ptrace_ldt();
- if(!proc_mm || !ptrace_faultinfo || !ptrace_ldt)
+ if (!proc_mm || !ptrace_faultinfo || !ptrace_ldt)
skas_needs_stub = 1;
return 1;
}
-#else
-int can_do_skas(void)
-{
- return 0;
-}
-#endif
int __init parse_iomem(char *str, int *add)
{
@@ -521,25 +489,25 @@ int __init parse_iomem(char *str, int *add)
driver = str;
file = strchr(str,',');
- if(file == NULL){
+ if (file == NULL) {
printf("parse_iomem : failed to parse iomem\n");
goto out;
}
*file = '\0';
file++;
fd = open(file, O_RDWR, 0);
- if(fd < 0){
- os_print_error(fd, "parse_iomem - Couldn't open io file");
+ if (fd < 0) {
+ perror("parse_iomem - Couldn't open io file");
goto out;
}
- if(fstat64(fd, &buf) < 0){
+ if (fstat64(fd, &buf) < 0) {
perror("parse_iomem - cannot stat_fd file");
goto out_close;
}
new = malloc(sizeof(*new));
- if(new == NULL){
+ if (new == NULL) {
perror("Couldn't allocate iomem_region struct");
goto out_close;
}
diff --git a/arch/um/os-Linux/sys-i386/Makefile b/arch/um/os-Linux/sys-i386/Makefile
index 37806621b25d..a841262c594a 100644
--- a/arch/um/os-Linux/sys-i386/Makefile
+++ b/arch/um/os-Linux/sys-i386/Makefile
@@ -1,9 +1,9 @@
#
-# Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+# Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
# Licensed under the GPL
#
-obj-$(CONFIG_MODE_SKAS) = registers.o signal.o tls.o
+obj-y = registers.o signal.o tls.o
USER_OBJS := $(obj-y)
diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c
index 84b44f9cd42a..d1997ca76e5c 100644
--- a/arch/um/os-Linux/sys-i386/registers.c
+++ b/arch/um/os-Linux/sys-i386/registers.c
@@ -1,144 +1,73 @@
/*
* Copyright (C) 2004 PathScale, Inc
+ * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
#include <errno.h>
-#include <string.h>
-#include "sysdep/ptrace_user.h"
-#include "sysdep/ptrace.h"
-#include "uml-config.h"
-#include "skas_ptregs.h"
-#include "registers.h"
+#include "kern_constants.h"
#include "longjmp.h"
#include "user.h"
+#include "sysdep/ptrace_user.h"
-/* These are set once at boot time and not changed thereafter */
-
-static unsigned long exec_regs[MAX_REG_NR];
-static unsigned long exec_fp_regs[HOST_FP_SIZE];
-static unsigned long exec_fpx_regs[HOST_XFP_SIZE];
-static int have_fpx_regs = 1;
-
-void init_thread_registers(union uml_pt_regs *to)
-{
- memcpy(to->skas.regs, exec_regs, sizeof(to->skas.regs));
- memcpy(to->skas.fp, exec_fp_regs, sizeof(to->skas.fp));
- if(have_fpx_regs)
- memcpy(to->skas.xfp, exec_fpx_regs, sizeof(to->skas.xfp));
-}
-
-/* XXX These need to use [GS]ETFPXREGS and copy_sc_{to,from}_user_skas needs
- * to pass in a sufficiently large buffer
- */
int save_fp_registers(int pid, unsigned long *fp_regs)
{
- if(ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
+ if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
return -errno;
return 0;
}
int restore_fp_registers(int pid, unsigned long *fp_regs)
{
- if(ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0)
+ if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0)
return -errno;
return 0;
}
-static int move_registers(int pid, int int_op, union uml_pt_regs *regs,
- int fp_op, unsigned long *fp_regs)
+int save_fpx_registers(int pid, unsigned long *fp_regs)
{
- if(ptrace(int_op, pid, 0, regs->skas.regs) < 0)
- return -errno;
-
- if(ptrace(fp_op, pid, 0, fp_regs) < 0)
+ if (ptrace(PTRACE_GETFPXREGS, pid, 0, fp_regs) < 0)
return -errno;
-
return 0;
}
-void save_registers(int pid, union uml_pt_regs *regs)
+int restore_fpx_registers(int pid, unsigned long *fp_regs)
{
- unsigned long *fp_regs;
- int err, fp_op;
-
- if(have_fpx_regs){
- fp_op = PTRACE_GETFPXREGS;
- fp_regs = regs->skas.xfp;
- }
- else {
- fp_op = PTRACE_GETFPREGS;
- fp_regs = regs->skas.fp;
- }
-
- err = move_registers(pid, PTRACE_GETREGS, regs, fp_op, fp_regs);
- if(err)
- panic("save_registers - saving registers failed, errno = %d\n",
- -err);
+ if (ptrace(PTRACE_SETFPXREGS, pid, 0, fp_regs) < 0)
+ return -errno;
+ return 0;
}
-void restore_registers(int pid, union uml_pt_regs *regs)
+unsigned long get_thread_reg(int reg, jmp_buf *buf)
{
- unsigned long *fp_regs;
- int err, fp_op;
-
- if(have_fpx_regs){
- fp_op = PTRACE_SETFPXREGS;
- fp_regs = regs->skas.xfp;
- }
- else {
- fp_op = PTRACE_SETFPREGS;
- fp_regs = regs->skas.fp;
+ switch (reg) {
+ case EIP:
+ return buf[0]->__eip;
+ case UESP:
+ return buf[0]->__esp;
+ case EBP:
+ return buf[0]->__ebp;
+ default:
+ printk(UM_KERN_ERR "get_thread_regs - unknown register %d\n",
+ reg);
+ return 0;
}
-
- err = move_registers(pid, PTRACE_SETREGS, regs, fp_op, fp_regs);
- if(err)
- panic("restore_registers - saving registers failed, "
- "errno = %d\n", -err);
}
-void init_registers(int pid)
+int have_fpx_regs = 1;
+
+void arch_init_registers(int pid)
{
+ unsigned long fpx_regs[HOST_XFP_SIZE];
int err;
- memset(exec_regs, 0, sizeof(exec_regs));
- err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs);
- if(err)
- panic("check_ptrace : PTRACE_GETREGS failed, errno = %d",
- errno);
-
- errno = 0;
- err = ptrace(PTRACE_GETFPXREGS, pid, 0, exec_fpx_regs);
+ err = ptrace(PTRACE_GETFPXREGS, pid, 0, fpx_regs);
if(!err)
return;
+
if(errno != EIO)
panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d",
errno);
have_fpx_regs = 0;
-
- err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs);
- if(err)
- panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d",
- errno);
-}
-
-void get_safe_registers(unsigned long *regs, unsigned long *fp_regs)
-{
- memcpy(regs, exec_regs, sizeof(exec_regs));
- if(fp_regs != NULL)
- memcpy(fp_regs, exec_fp_regs,
- HOST_FP_SIZE * sizeof(unsigned long));
-}
-
-unsigned long get_thread_reg(int reg, jmp_buf *buf)
-{
- switch(reg){
- case EIP: return buf[0]->__eip;
- case UESP: return buf[0]->__esp;
- case EBP: return buf[0]->__ebp;
- default:
- printk("get_thread_regs - unknown register %d\n", reg);
- return 0;
- }
}
diff --git a/arch/um/os-Linux/sys-x86_64/Makefile b/arch/um/os-Linux/sys-x86_64/Makefile
index 7955e061a678..a42a4ef02e1e 100644
--- a/arch/um/os-Linux/sys-x86_64/Makefile
+++ b/arch/um/os-Linux/sys-x86_64/Makefile
@@ -1,9 +1,9 @@
#
-# Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+# Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
# Licensed under the GPL
#
-obj-$(CONFIG_MODE_SKAS) = registers.o prctl.o signal.o
+obj-y = registers.o prctl.o signal.o
USER_OBJS := $(obj-y)
diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c
index 9467315b8059..9bfa789992de 100644
--- a/arch/um/os-Linux/sys-x86_64/registers.c
+++ b/arch/um/os-Linux/sys-x86_64/registers.c
@@ -1,23 +1,15 @@
/*
- * Copyright (C) 2004 PathScale, Inc
+ * Copyright (C) 2006-2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
#include <errno.h>
#include <sys/ptrace.h>
-#include <string.h>
-#include "ptrace_user.h"
-#include "uml-config.h"
-#include "skas_ptregs.h"
-#include "registers.h"
+#define __FRAME_OFFSETS
+#include <asm/ptrace.h>
#include "longjmp.h"
#include "user.h"
-/* These are set once at boot time and not changed thereafter */
-
-static unsigned long exec_regs[MAX_REG_NR];
-static unsigned long exec_fp_regs[HOST_FP_SIZE];
-
int save_fp_registers(int pid, unsigned long *fp_regs)
{
if(ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
@@ -32,67 +24,6 @@ int restore_fp_registers(int pid, unsigned long *fp_regs)
return 0;
}
-void init_thread_registers(union uml_pt_regs *to)
-{
- memcpy(to->skas.regs, exec_regs, sizeof(to->skas.regs));
- memcpy(to->skas.fp, exec_fp_regs, sizeof(to->skas.fp));
-}
-
-static int move_registers(int pid, int int_op, int fp_op,
- union uml_pt_regs *regs)
-{
- if(ptrace(int_op, pid, 0, regs->skas.regs) < 0)
- return -errno;
-
- if(ptrace(fp_op, pid, 0, regs->skas.fp) < 0)
- return -errno;
-
- return 0;
-}
-
-void save_registers(int pid, union uml_pt_regs *regs)
-{
- int err;
-
- err = move_registers(pid, PTRACE_GETREGS, PTRACE_GETFPREGS, regs);
- if(err)
- panic("save_registers - saving registers failed, errno = %d\n",
- -err);
-}
-
-void restore_registers(int pid, union uml_pt_regs *regs)
-{
- int err;
-
- err = move_registers(pid, PTRACE_SETREGS, PTRACE_SETFPREGS, regs);
- if(err)
- panic("restore_registers - saving registers failed, "
- "errno = %d\n", -err);
-}
-
-void init_registers(int pid)
-{
- int err;
-
- err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs);
- if(err)
- panic("check_ptrace : PTRACE_GETREGS failed, errno = %d",
- errno);
-
- err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs);
- if(err)
- panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d",
- errno);
-}
-
-void get_safe_registers(unsigned long *regs, unsigned long *fp_regs)
-{
- memcpy(regs, exec_regs, sizeof(exec_regs));
- if(fp_regs != NULL)
- memcpy(fp_regs, exec_fp_regs,
- HOST_FP_SIZE * sizeof(unsigned long));
-}
-
unsigned long get_thread_reg(int reg, jmp_buf *buf)
{
switch(reg){
diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c
index 5de169b168f6..e34e1effe0f5 100644
--- a/arch/um/os-Linux/time.c
+++ b/arch/um/os-Linux/time.c
@@ -1,101 +1,86 @@
/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
+#include <stddef.h>
+#include <errno.h>
+#include <signal.h>
#include <time.h>
#include <sys/time.h>
-#include <signal.h>
-#include <errno.h>
-#include "kern_util.h"
-#include "user.h"
-#include "process.h"
#include "kern_constants.h"
#include "os.h"
-#include "uml-config.h"
+#include "user.h"
-int set_interval(int is_virtual)
+int set_interval(void)
{
- int usec = 1000000/hz();
- int timer_type = is_virtual ? ITIMER_VIRTUAL : ITIMER_REAL;
+ int usec = UM_USEC_PER_SEC / UM_HZ;
struct itimerval interval = ((struct itimerval) { { 0, usec },
{ 0, usec } });
- if(setitimer(timer_type, &interval, NULL) == -1)
+ if (setitimer(ITIMER_VIRTUAL, &interval, NULL) == -1)
return -errno;
return 0;
}
-#ifdef UML_CONFIG_MODE_TT
-void enable_timer(void)
+int timer_one_shot(int ticks)
{
- set_interval(1);
-}
-#endif
+ unsigned long usec = ticks * UM_USEC_PER_SEC / UM_HZ;
+ unsigned long sec = usec / UM_USEC_PER_SEC;
+ struct itimerval interval;
-void disable_timer(void)
-{
- struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }});
- if((setitimer(ITIMER_VIRTUAL, &disable, NULL) < 0) ||
- (setitimer(ITIMER_REAL, &disable, NULL) < 0))
- printk("disnable_timer - setitimer failed, errno = %d\n",
- errno);
- /* If there are signals already queued, after unblocking ignore them */
- signal(SIGALRM, SIG_IGN);
- signal(SIGVTALRM, SIG_IGN);
+ usec %= UM_USEC_PER_SEC;
+ interval = ((struct itimerval) { { 0, 0 }, { sec, usec } });
+
+ if (setitimer(ITIMER_VIRTUAL, &interval, NULL) == -1)
+ return -errno;
+
+ return 0;
}
-void switch_timers(int to_real)
+/**
+ * timeval_to_ns - Convert timeval to nanoseconds
+ * @ts: pointer to the timeval variable to be converted
+ *
+ * Returns the scalar nanosecond representation of the timeval
+ * parameter.
+ *
+ * Ripped from linux/time.h because it's a kernel header, and thus
+ * unusable from here.
+ */
+static inline long long timeval_to_ns(const struct timeval *tv)
{
- struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }});
- struct itimerval enable = ((struct itimerval) { { 0, 1000000/hz() },
- { 0, 1000000/hz() }});
- int old, new;
-
- if(to_real){
- old = ITIMER_VIRTUAL;
- new = ITIMER_REAL;
- }
- else {
- old = ITIMER_REAL;
- new = ITIMER_VIRTUAL;
- }
-
- if((setitimer(old, &disable, NULL) < 0) ||
- (setitimer(new, &enable, NULL)))
- printk("switch_timers - setitimer failed, errno = %d\n",
- errno);
+ return ((long long) tv->tv_sec * UM_NSEC_PER_SEC) +
+ tv->tv_usec * UM_NSEC_PER_USEC;
}
-#ifdef UML_CONFIG_MODE_TT
-void uml_idle_timer(void)
+long long disable_timer(void)
{
- if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR)
- panic("Couldn't unset SIGVTALRM handler");
+ struct itimerval time = ((struct itimerval) { { 0, 0 }, { 0, 0 } });
+
+ if(setitimer(ITIMER_VIRTUAL, &time, &time) < 0)
+ printk(UM_KERN_ERR "disable_timer - setitimer failed, "
+ "errno = %d\n", errno);
- set_handler(SIGALRM, (__sighandler_t) alarm_handler,
- SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
- set_interval(0);
+ return timeval_to_ns(&time.it_value);
}
-#endif
-unsigned long long os_nsecs(void)
+long long os_nsecs(void)
{
struct timeval tv;
gettimeofday(&tv, NULL);
- return((unsigned long long) tv.tv_sec * BILLION + tv.tv_usec * 1000);
+ return timeval_to_ns(&tv);
}
-void idle_sleep(int secs)
+extern void alarm_handler(int sig, struct sigcontext *sc);
+
+void idle_sleep(unsigned long long nsecs)
{
- struct timespec ts;
+ struct timespec ts = { .tv_sec = nsecs / UM_NSEC_PER_SEC,
+ .tv_nsec = nsecs % UM_NSEC_PER_SEC };
- ts.tv_sec = secs;
- ts.tv_nsec = 0;
- nanosleep(&ts, NULL);
+ if (nanosleep(&ts, &ts) == 0)
+ alarm_handler(SIGVTALRM, NULL);
}
diff --git a/arch/um/os-Linux/tls.c b/arch/um/os-Linux/tls.c
index 16215b990804..73277801ef14 100644
--- a/arch/um/os-Linux/tls.c
+++ b/arch/um/os-Linux/tls.c
@@ -1,18 +1,9 @@
#include <errno.h>
-#include <unistd.h>
#include <sys/ptrace.h>
-#include <sys/syscall.h>
-#include <asm/ldt.h>
#include "sysdep/tls.h"
-#include "uml-config.h"
/* TLS support - we basically rely on the host's one.*/
-/* In TT mode, this should be called only by the tracing thread, and makes sense
- * only for PTRACE_SET_THREAD_AREA. In SKAS mode, it's used normally.
- *
- */
-
#ifndef PTRACE_GET_THREAD_AREA
#define PTRACE_GET_THREAD_AREA 25
#endif
@@ -32,8 +23,6 @@ int os_set_thread_area(user_desc_t *info, int pid)
return ret;
}
-#ifdef UML_CONFIG_MODE_SKAS
-
int os_get_thread_area(user_desc_t *info, int pid)
{
int ret;
@@ -44,32 +33,3 @@ int os_get_thread_area(user_desc_t *info, int pid)
ret = -errno;
return ret;
}
-
-#endif
-
-#ifdef UML_CONFIG_MODE_TT
-#include "linux/unistd.h"
-
-int do_set_thread_area_tt(user_desc_t *info)
-{
- int ret;
-
- ret = syscall(__NR_set_thread_area,info);
- if (ret < 0) {
- ret = -errno;
- }
- return ret;
-}
-
-int do_get_thread_area_tt(user_desc_t *info)
-{
- int ret;
-
- ret = syscall(__NR_get_thread_area,info);
- if (ret < 0) {
- ret = -errno;
- }
- return ret;
-}
-
-#endif /* UML_CONFIG_MODE_TT */
diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c
index 295da657931a..2a1c9843e32e 100644
--- a/arch/um/os-Linux/trap.c
+++ b/arch/um/os-Linux/trap.c
@@ -1,22 +1,14 @@
/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include <stdlib.h>
#include <signal.h>
-#include "kern_util.h"
#include "os.h"
-#include "mode.h"
-#include "longjmp.h"
-
-void usr2_handler(int sig, union uml_pt_regs *regs)
-{
- CHOOSE_MODE(syscall_handler_tt(sig, regs), (void) 0);
-}
+#include "sysdep/ptrace.h"
/* Initialized from linux_main() */
-void (*sig_info[NSIG])(int, union uml_pt_regs *);
+void (*sig_info[NSIG])(int, struct uml_pt_regs *);
void os_fill_handlinfo(struct kern_handlers h)
{
@@ -28,13 +20,4 @@ void os_fill_handlinfo(struct kern_handlers h)
sig_info[SIGSEGV] = h.page_fault;
sig_info[SIGIO] = h.sigio_handler;
sig_info[SIGVTALRM] = h.timer_handler;
- sig_info[SIGALRM] = h.timer_handler;
- sig_info[SIGUSR2] = usr2_handler;
-}
-
-void do_longjmp(void *b, int val)
-{
- jmp_buf *buf = b;
-
- UML_LONGJMP(buf, val);
}
diff --git a/arch/um/os-Linux/tt.c b/arch/um/os-Linux/tt.c
deleted file mode 100644
index bcf9359c4e9f..000000000000
--- a/arch/um/os-Linux/tt.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <signal.h>
-#include <sched.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <sys/time.h>
-#include <sys/ptrace.h>
-#include <linux/ptrace.h>
-#include <sys/wait.h>
-#include <sys/mman.h>
-#include <asm/ptrace.h>
-#include <asm/unistd.h>
-#include <asm/page.h>
-#include "kern_util.h"
-#include "user.h"
-#include "signal_kern.h"
-#include "sysdep/ptrace.h"
-#include "sysdep/sigcontext.h"
-#include "irq_user.h"
-#include "ptrace_user.h"
-#include "init.h"
-#include "os.h"
-#include "uml-config.h"
-#include "choose-mode.h"
-#include "mode.h"
-#include "tempfile.h"
-#include "kern_constants.h"
-
-int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x,
- int must_succeed)
-{
- int err;
-
- err = os_protect_memory((void *) addr, len, r, w, x);
- if(err < 0){
- if(must_succeed)
- panic("protect failed, err = %d", -err);
- else return(err);
- }
- return(0);
-}
-
-void kill_child_dead(int pid)
-{
- kill(pid, SIGKILL);
- kill(pid, SIGCONT);
- do {
- int n;
- CATCH_EINTR(n = waitpid(pid, NULL, 0));
- if (n > 0)
- kill(pid, SIGCONT);
- else
- break;
- } while(1);
-}
-
-void stop(void)
-{
- while(1) sleep(1000000);
-}
-
-int wait_for_stop(int pid, int sig, int cont_type, void *relay)
-{
- sigset_t *relay_signals = relay;
- int status, ret;
-
- while(1){
- CATCH_EINTR(ret = waitpid(pid, &status, WUNTRACED));
- if((ret < 0) ||
- !WIFSTOPPED(status) || (WSTOPSIG(status) != sig)){
- if(ret < 0){
- printk("wait failed, errno = %d\n",
- errno);
- }
- else if(WIFEXITED(status))
- printk("process %d exited with status %d\n",
- pid, WEXITSTATUS(status));
- else if(WIFSIGNALED(status))
- printk("process %d exited with signal %d\n",
- pid, WTERMSIG(status));
- else if((WSTOPSIG(status) == SIGVTALRM) ||
- (WSTOPSIG(status) == SIGALRM) ||
- (WSTOPSIG(status) == SIGIO) ||
- (WSTOPSIG(status) == SIGPROF) ||
- (WSTOPSIG(status) == SIGCHLD) ||
- (WSTOPSIG(status) == SIGWINCH) ||
- (WSTOPSIG(status) == SIGINT)){
- ptrace(cont_type, pid, 0, WSTOPSIG(status));
- continue;
- }
- else if((relay_signals != NULL) &&
- sigismember(relay_signals, WSTOPSIG(status))){
- ptrace(cont_type, pid, 0, WSTOPSIG(status));
- continue;
- }
- else printk("process %d stopped with signal %d\n",
- pid, WSTOPSIG(status));
- panic("wait_for_stop failed to wait for %d to stop "
- "with %d\n", pid, sig);
- }
- return(status);
- }
-}
-
-void forward_ipi(int fd, int pid)
-{
- int err;
-
- err = os_set_owner(fd, pid);
- if(err < 0)
- printk("forward_ipi: set_owner failed, fd = %d, me = %d, "
- "target = %d, err = %d\n", fd, os_getpid(), pid, -err);
-}
-
-/*
- *-------------------------
- * only for tt mode (will be deleted in future...)
- *-------------------------
- */
-
-struct tramp {
- int (*tramp)(void *);
- void *tramp_data;
- unsigned long temp_stack;
- int flags;
- int pid;
-};
-
-/* See above for why sigkill is here */
-
-int sigkill = SIGKILL;
-
-int outer_tramp(void *arg)
-{
- struct tramp *t;
- int sig = sigkill;
-
- t = arg;
- t->pid = clone(t->tramp, (void *) t->temp_stack + UM_KERN_PAGE_SIZE/2,
- t->flags, t->tramp_data);
- if(t->pid > 0) wait_for_stop(t->pid, SIGSTOP, PTRACE_CONT, NULL);
- kill(os_getpid(), sig);
- _exit(0);
-}
-
-int start_fork_tramp(void *thread_arg, unsigned long temp_stack,
- int clone_flags, int (*tramp)(void *))
-{
- struct tramp arg;
- unsigned long sp;
- int new_pid, status, err;
-
- /* The trampoline will run on the temporary stack */
- sp = stack_sp(temp_stack);
-
- clone_flags |= CLONE_FILES | SIGCHLD;
-
- arg.tramp = tramp;
- arg.tramp_data = thread_arg;
- arg.temp_stack = temp_stack;
- arg.flags = clone_flags;
-
- /* Start the process and wait for it to kill itself */
- new_pid = clone(outer_tramp, (void *) sp, clone_flags, &arg);
- if(new_pid < 0)
- return(new_pid);
-
- CATCH_EINTR(err = waitpid(new_pid, &status, 0));
- if(err < 0)
- panic("Waiting for outer trampoline failed - errno = %d",
- errno);
-
- if(!WIFSIGNALED(status) || (WTERMSIG(status) != SIGKILL))
- panic("outer trampoline didn't exit with SIGKILL, "
- "status = %d", status);
-
- return(arg.pid);
-}
-
-void forward_pending_sigio(int target)
-{
- sigset_t sigs;
-
- if(sigpending(&sigs))
- panic("forward_pending_sigio : sigpending failed");
- if(sigismember(&sigs, SIGIO))
- kill(target, SIGIO);
-}
-
diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c
index bbb73a650370..8d27b6d1df91 100644
--- a/arch/um/os-Linux/uaccess.c
+++ b/arch/um/os-Linux/uaccess.c
@@ -8,7 +8,7 @@
#include "longjmp.h"
unsigned long __do_user_copy(void *to, const void *from, int n,
- void **fault_addr, void **fault_catcher,
+ void **fault_addr, jmp_buf **fault_catcher,
void (*op)(void *to, const void *from,
int n), int *faulted_out)
{
diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c
index b462863f7172..106fa8641553 100644
--- a/arch/um/os-Linux/umid.c
+++ b/arch/um/os-Linux/umid.c
@@ -1,17 +1,21 @@
+/*
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
#include <stdio.h>
-#include <unistd.h>
#include <stdlib.h>
-#include <string.h>
+#include <dirent.h>
#include <errno.h>
+#include <fcntl.h>
#include <signal.h>
-#include <dirent.h>
-#include <sys/fcntl.h>
+#include <string.h>
+#include <unistd.h>
#include <sys/stat.h>
-#include <sys/param.h>
#include "init.h"
+#include "kern_constants.h"
#include "os.h"
#include "user.h"
-#include "mode.h"
#define UML_DIR "~/.uml/"
@@ -28,13 +32,13 @@ static int __init make_uml_dir(void)
char dir[512] = { '\0' };
int len, err;
- if(*uml_dir == '~'){
+ if (*uml_dir == '~') {
char *home = getenv("HOME");
err = -ENOENT;
- if(home == NULL){
- printk("make_uml_dir : no value in environment for "
- "$HOME\n");
+ if (home == NULL) {
+ printk(UM_KERN_ERR "make_uml_dir : no value in "
+ "environment for $HOME\n");
goto err;
}
strlcpy(dir, home, sizeof(dir));
@@ -53,7 +57,7 @@ static int __init make_uml_dir(void)
}
strcpy(uml_dir, dir);
- if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){
+ if ((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)) {
printf("Failed to mkdir '%s': %s\n", uml_dir, strerror(errno));
err = -errno;
goto err_free;
@@ -70,8 +74,8 @@ err:
/*
* Unlinks the files contained in @dir and then removes @dir.
* Doesn't handle directory trees, so it's not like rm -rf, but almost such. We
- * ignore ENOENT errors for anything (they happen, strangely enough - possibly due
- * to races between multiple dying UML threads).
+ * ignore ENOENT errors for anything (they happen, strangely enough - possibly
+ * due to races between multiple dying UML threads).
*/
static int remove_files_and_dir(char *dir)
{
@@ -116,7 +120,8 @@ out:
return ret;
}
-/* This says that there isn't already a user of the specified directory even if
+/*
+ * This says that there isn't already a user of the specified directory even if
* there are errors during the checking. This is because if these errors
* happen, the directory is unusable by the pre-existing UML, so we might as
* well take it over. This could happen either by
@@ -134,44 +139,45 @@ static inline int is_umdir_used(char *dir)
int dead, fd, p, n, err;
n = snprintf(file, sizeof(file), "%s/pid", dir);
- if(n >= sizeof(file)){
- printk("is_umdir_used - pid filename too long\n");
+ if (n >= sizeof(file)) {
+ printk(UM_KERN_ERR "is_umdir_used - pid filename too long\n");
err = -E2BIG;
goto out;
}
dead = 0;
fd = open(file, O_RDONLY);
- if(fd < 0) {
+ if (fd < 0) {
fd = -errno;
- if(fd != -ENOENT){
- printk("is_umdir_used : couldn't open pid file '%s', "
- "err = %d\n", file, -fd);
+ if (fd != -ENOENT) {
+ printk(UM_KERN_ERR "is_umdir_used : couldn't open pid "
+ "file '%s', err = %d\n", file, -fd);
}
goto out;
}
err = 0;
n = read(fd, pid, sizeof(pid));
- if(n < 0){
- printk("is_umdir_used : couldn't read pid file '%s', "
- "err = %d\n", file, errno);
+ if (n < 0) {
+ printk(UM_KERN_ERR "is_umdir_used : couldn't read pid file "
+ "'%s', err = %d\n", file, errno);
goto out_close;
- } else if(n == 0){
- printk("is_umdir_used : couldn't read pid file '%s', "
- "0-byte read\n", file);
+ } else if (n == 0) {
+ printk(UM_KERN_ERR "is_umdir_used : couldn't read pid file "
+ "'%s', 0-byte read\n", file);
goto out_close;
}
p = strtoul(pid, &end, 0);
- if(end == pid){
- printk("is_umdir_used : couldn't parse pid file '%s', "
- "errno = %d\n", file, errno);
+ if (end == pid) {
+ printk(UM_KERN_ERR "is_umdir_used : couldn't parse pid file "
+ "'%s', errno = %d\n", file, errno);
goto out_close;
}
- if((kill(p, 0) == 0) || (errno != ESRCH)){
- printk("umid \"%s\" is already in use by pid %d\n", umid, p);
+ if ((kill(p, 0) == 0) || (errno != ESRCH)) {
+ printk(UM_KERN_ERR "umid \"%s\" is already in use by pid %d\n",
+ umid, p);
return 1;
}
@@ -195,8 +201,8 @@ static int umdir_take_if_dead(char *dir)
ret = remove_files_and_dir(dir);
if (ret) {
- printk("is_umdir_used - remove_files_and_dir failed with "
- "err = %d\n", ret);
+ printk(UM_KERN_ERR "is_umdir_used - remove_files_and_dir "
+ "failed with err = %d\n", ret);
}
return ret;
}
@@ -207,27 +213,28 @@ static void __init create_pid_file(void)
char pid[sizeof("nnnnn\0")];
int fd, n;
- if(umid_file_name("pid", file, sizeof(file)))
+ if (umid_file_name("pid", file, sizeof(file)))
return;
fd = open(file, O_RDWR | O_CREAT | O_EXCL, 0644);
- if(fd < 0){
- printk("Open of machine pid file \"%s\" failed: %s\n",
- file, strerror(errno));
+ if (fd < 0) {
+ printk(UM_KERN_ERR "Open of machine pid file \"%s\" failed: "
+ "%s\n", file, strerror(errno));
return;
}
snprintf(pid, sizeof(pid), "%d\n", getpid());
n = write(fd, pid, strlen(pid));
- if(n != strlen(pid))
- printk("Write of pid file failed - err = %d\n", errno);
+ if (n != strlen(pid))
+ printk(UM_KERN_ERR "Write of pid file failed - err = %d\n",
+ errno);
close(fd);
}
int __init set_umid(char *name)
{
- if(strlen(name) > UMID_LEN - 1)
+ if (strlen(name) > UMID_LEN - 1)
return -E2BIG;
strlcpy(umid, name, sizeof(umid));
@@ -243,18 +250,18 @@ int __init make_umid(void)
int fd, err;
char tmp[256];
- if(umid_setup)
+ if (umid_setup)
return 0;
make_uml_dir();
- if(*umid == '\0'){
+ if (*umid == '\0') {
strlcpy(tmp, uml_dir, sizeof(tmp));
strlcat(tmp, "XXXXXX", sizeof(tmp));
fd = mkstemp(tmp);
- if(fd < 0){
- printk("make_umid - mkstemp(%s) failed: %s\n",
- tmp, strerror(errno));
+ if (fd < 0) {
+ printk(UM_KERN_ERR "make_umid - mkstemp(%s) failed: "
+ "%s\n", tmp, strerror(errno));
err = -errno;
goto err;
}
@@ -263,11 +270,12 @@ int __init make_umid(void)
set_umid(&tmp[strlen(uml_dir)]);
- /* There's a nice tiny little race between this unlink and
+ /*
+ * There's a nice tiny little race between this unlink and
* the mkdir below. It'd be nice if there were a mkstemp
* for directories.
*/
- if(unlink(tmp)){
+ if (unlink(tmp)) {
err = -errno;
goto err;
}
@@ -275,9 +283,9 @@ int __init make_umid(void)
snprintf(tmp, sizeof(tmp), "%s%s", uml_dir, umid);
err = mkdir(tmp, 0777);
- if(err < 0){
+ if (err < 0) {
err = -errno;
- if(err != -EEXIST)
+ if (err != -EEXIST)
goto err;
if (umdir_take_if_dead(tmp) < 0)
@@ -285,9 +293,10 @@ int __init make_umid(void)
err = mkdir(tmp, 0777);
}
- if(err){
+ if (err) {
err = -errno;
- printk("Failed to create '%s' - err = %d\n", umid, -errno);
+ printk(UM_KERN_ERR "Failed to create '%s' - err = %d\n", umid,
+ errno);
goto err;
}
@@ -302,14 +311,15 @@ int __init make_umid(void)
static int __init make_umid_init(void)
{
- if(!make_umid())
+ if (!make_umid())
return 0;
- /* If initializing with the given umid failed, then try again with
+ /*
+ * If initializing with the given umid failed, then try again with
* a random one.
*/
- printk("Failed to initialize umid \"%s\", trying with a random umid\n",
- umid);
+ printk(UM_KERN_ERR "Failed to initialize umid \"%s\", trying with a "
+ "random umid\n", umid);
*umid = '\0';
make_umid();
@@ -323,12 +333,12 @@ int __init umid_file_name(char *name, char *buf, int len)
int n, err;
err = make_umid();
- if(err)
+ if (err)
return err;
n = snprintf(buf, len, "%s%s/%s", uml_dir, umid, name);
- if(n >= len){
- printk("umid_file_name : buffer too short\n");
+ if (n >= len) {
+ printk(UM_KERN_ERR "umid_file_name : buffer too short\n");
return -E2BIG;
}
@@ -342,21 +352,22 @@ char *get_umid(void)
static int __init set_uml_dir(char *name, int *add)
{
- if(*name == '\0'){
+ if (*name == '\0') {
printf("uml_dir can't be an empty string\n");
return 0;
}
- if(name[strlen(name) - 1] == '/'){
+ if (name[strlen(name) - 1] == '/') {
uml_dir = name;
return 0;
}
uml_dir = malloc(strlen(name) + 2);
- if(uml_dir == NULL){
+ if (uml_dir == NULL) {
printf("Failed to malloc uml_dir - error = %d\n", errno);
- /* Return 0 here because do_initcalls doesn't look at
+ /*
+ * Return 0 here because do_initcalls doesn't look at
* the return value.
*/
return 0;
@@ -377,7 +388,7 @@ static void remove_umid_dir(void)
sprintf(dir, "%s%s", uml_dir, umid);
err = remove_files_and_dir(dir);
- if(err)
+ if (err)
printf("remove_umid_dir - remove_files_and_dir failed with "
"err = %d\n", err);
}
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
index 7cbcf484e13d..ef095436a78c 100644
--- a/arch/um/os-Linux/util.c
+++ b/arch/um/os-Linux/util.c
@@ -105,6 +105,44 @@ int setjmp_wrapper(void (*proc)(void *, void *), ...)
void os_dump_core(void)
{
+ int pid;
+
signal(SIGSEGV, SIG_DFL);
+
+ /*
+ * We are about to SIGTERM this entire process group to ensure that
+ * nothing is around to run after the kernel exits. The
+ * kernel wants to abort, not die through SIGTERM, so we
+ * ignore it here.
+ */
+
+ signal(SIGTERM, SIG_IGN);
+ kill(0, SIGTERM);
+ /*
+ * Most of the other processes associated with this UML are
+ * likely sTopped, so give them a SIGCONT so they see the
+ * SIGTERM.
+ */
+ kill(0, SIGCONT);
+
+ /*
+ * Now, having sent signals to everyone but us, make sure they
+ * die by ptrace. Processes can survive what's been done to
+ * them so far - the mechanism I understand is receiving a
+ * SIGSEGV and segfaulting immediately upon return. There is
+ * always a SIGSEGV pending, and (I'm guessing) signals are
+ * processed in numeric order so the SIGTERM (signal 15 vs
+ * SIGSEGV being signal 11) is never handled.
+ *
+ * Run a waitpid loop until we get some kind of error.
+ * Hopefully, it's ECHILD, but there's not a lot we can do if
+ * it's something else. Tell os_kill_ptraced_process not to
+ * wait for the child to report its death because there's
+ * nothing reasonable to do if that fails.
+ */
+
+ while ((pid = waitpid(-1, NULL, WNOHANG)) > 0)
+ os_kill_ptraced_process(pid, 0);
+
abort();
}
diff --git a/arch/um/scripts/Makefile.rules b/arch/um/scripts/Makefile.rules
index bf23dd3e24d0..61107b68e05b 100644
--- a/arch/um/scripts/Makefile.rules
+++ b/arch/um/scripts/Makefile.rules
@@ -21,7 +21,7 @@ $(UNPROFILE_OBJS:.o=.%): \
$(UNPROFILE_OBJS) : CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ \
-Dunix -D__unix__ -D__$(SUBARCH)__ $(CF)
-# The stubs and unmap.o can't try to call mcount or update basic block data
+# The stubs can't try to call mcount or update basic block data
define unprofile
$(patsubst -pg,,$(patsubst -fprofile-arcs -ftest-coverage,,$(1)))
endef
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
index a4618b6b85b9..964dc1a04c37 100644
--- a/arch/um/sys-i386/Makefile
+++ b/arch/um/sys-i386/Makefile
@@ -1,23 +1,21 @@
+#
+# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+#
+
obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
- ptrace_user.o setjmp.o signal.o sigcontext.o syscalls.o sysrq.o \
+ ptrace_user.o setjmp.o signal.o stub.o stub_segv.o syscalls.o sysrq.o \
sys_call_table.o tls.o
-obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o
-
subarch-obj-y = lib/bitops_32.o lib/semaphore_32.o lib/string_32.o
subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem_32.o
subarch-obj-$(CONFIG_MODULES) += kernel/module_32.o
-USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o
+USER_OBJS := bugs.o ptrace_user.o fault.o
USER_OBJS += user-offsets.s
extra-y += user-offsets.s
-extra-$(CONFIG_MODE_TT) += unmap.o
-
UNPROFILE_OBJS := stub_segv.o
CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING)
include arch/um/scripts/Makefile.rules
-
-$(obj)/unmap.%: _c_flags = $(call unprofile,$(CFLAGS))
diff --git a/arch/um/sys-i386/bug.c b/arch/um/sys-i386/bug.c
index 200c8ba2879b..a4360b5207db 100644
--- a/arch/um/sys-i386/bug.c
+++ b/arch/um/sys-i386/bug.c
@@ -6,7 +6,7 @@
#include <linux/uaccess.h>
/* Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because
- * that's not relevent in skas mode.
+ * that's not relevant in skas mode.
*/
int is_valid_bugaddr(unsigned long eip)
diff --git a/arch/um/sys-i386/bugs.c b/arch/um/sys-i386/bugs.c
index 0393e44813e7..806895d73bcc 100644
--- a/arch/um/sys-i386/bugs.c
+++ b/arch/um/sys-i386/bugs.c
@@ -1,18 +1,15 @@
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include <unistd.h>
#include <errno.h>
+#include <signal.h>
#include <string.h>
-#include <sys/signal.h>
-#include <asm/ldt.h>
-#include "kern_util.h"
-#include "user.h"
-#include "sysdep/ptrace.h"
-#include "task.h"
+#include "kern_constants.h"
#include "os.h"
+#include "task.h"
+#include "user.h"
#define MAXTOKEN 64
@@ -30,18 +27,20 @@ static char token(int fd, char *buf, int len, char stop)
do {
n = os_read_file(fd, ptr, sizeof(*ptr));
c = *ptr++;
- if(n != sizeof(*ptr)){
- if(n == 0)
+ if (n != sizeof(*ptr)) {
+ if (n == 0)
return 0;
- printk("Reading /proc/cpuinfo failed, err = %d\n", -n);
- if(n < 0)
+ printk(UM_KERN_ERR "Reading /proc/cpuinfo failed, "
+ "err = %d\n", -n);
+ if (n < 0)
return n;
else return -EIO;
}
- } while((c != '\n') && (c != stop) && (ptr < end));
+ } while ((c != '\n') && (c != stop) && (ptr < end));
- if(ptr == end){
- printk("Failed to find '%c' in /proc/cpuinfo\n", stop);
+ if (ptr == end) {
+ printk(UM_KERN_ERR "Failed to find '%c' in /proc/cpuinfo\n",
+ stop);
return -1;
}
*(ptr - 1) = '\0';
@@ -54,26 +53,27 @@ static int find_cpuinfo_line(int fd, char *key, char *scratch, int len)
char c;
scratch[len - 1] = '\0';
- while(1){
+ while (1) {
c = token(fd, scratch, len - 1, ':');
- if(c <= 0)
+ if (c <= 0)
return 0;
- else if(c != ':'){
- printk("Failed to find ':' in /proc/cpuinfo\n");
+ else if (c != ':') {
+ printk(UM_KERN_ERR "Failed to find ':' in "
+ "/proc/cpuinfo\n");
return 0;
}
- if(!strncmp(scratch, key, strlen(key)))
+ if (!strncmp(scratch, key, strlen(key)))
return 1;
do {
n = os_read_file(fd, &c, sizeof(c));
- if(n != sizeof(c)){
- printk("Failed to find newline in "
+ if (n != sizeof(c)) {
+ printk(UM_KERN_ERR "Failed to find newline in "
"/proc/cpuinfo, err = %d\n", -n);
return 0;
}
- } while(c != '\n');
+ } while (c != '\n');
}
return 0;
}
@@ -83,46 +83,50 @@ static int check_cpu_flag(char *feature, int *have_it)
char buf[MAXTOKEN], c;
int fd, len = ARRAY_SIZE(buf);
- printk("Checking for host processor %s support...", feature);
+ printk(UM_KERN_INFO "Checking for host processor %s support...",
+ feature);
fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0);
- if(fd < 0){
- printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd);
+ if (fd < 0) {
+ printk(UM_KERN_ERR "Couldn't open /proc/cpuinfo, err = %d\n",
+ -fd);
return 0;
}
*have_it = 0;
- if(!find_cpuinfo_line(fd, "flags", buf, ARRAY_SIZE(buf)))
+ if (!find_cpuinfo_line(fd, "flags", buf, ARRAY_SIZE(buf)))
goto out;
c = token(fd, buf, len - 1, ' ');
- if(c < 0)
+ if (c < 0)
goto out;
- else if(c != ' '){
- printk("Failed to find ' ' in /proc/cpuinfo\n");
+ else if (c != ' ') {
+ printk(UM_KERN_ERR "Failed to find ' ' in /proc/cpuinfo\n");
goto out;
}
- while(1){
+ while (1) {
c = token(fd, buf, len - 1, ' ');
- if(c < 0)
+ if (c < 0)
goto out;
- else if(c == '\n') break;
+ else if (c == '\n')
+ break;
- if(!strcmp(buf, feature)){
+ if (!strcmp(buf, feature)) {
*have_it = 1;
goto out;
}
}
out:
- if(*have_it == 0)
+ if (*have_it == 0)
printk("No\n");
- else if(*have_it == 1)
+ else if (*have_it == 1)
printk("Yes\n");
os_close_file(fd);
return 1;
}
-#if 0 /* This doesn't work in tt mode, plus it's causing compilation problems
+#if 0 /*
+ * This doesn't work in tt mode, plus it's causing compilation problems
* for some people.
*/
static void disable_lcall(void)
@@ -135,8 +139,9 @@ static void disable_lcall(void)
ldt.base_addr = 0;
ldt.limit = 0;
err = modify_ldt(1, &ldt, sizeof(ldt));
- if(err)
- printk("Failed to disable lcall7 - errno = %d\n", errno);
+ if (err)
+ printk(UM_KERN_ERR "Failed to disable lcall7 - errno = %d\n",
+ errno);
}
#endif
@@ -151,40 +156,41 @@ void arch_check_bugs(void)
{
int have_it;
- if(os_access("/proc/cpuinfo", OS_ACC_R_OK) < 0){
- printk("/proc/cpuinfo not available - skipping CPU capability "
- "checks\n");
+ if (os_access("/proc/cpuinfo", OS_ACC_R_OK) < 0) {
+ printk(UM_KERN_ERR "/proc/cpuinfo not available - skipping CPU "
+ "capability checks\n");
return;
}
- if(check_cpu_flag("cmov", &have_it))
+ if (check_cpu_flag("cmov", &have_it))
host_has_cmov = have_it;
- if(check_cpu_flag("xmm", &have_it))
+ if (check_cpu_flag("xmm", &have_it))
host_has_xmm = have_it;
}
-int arch_handle_signal(int sig, union uml_pt_regs *regs)
+int arch_handle_signal(int sig, struct uml_pt_regs *regs)
{
unsigned char tmp[2];
- /* This is testing for a cmov (0x0f 0x4x) instruction causing a
+ /*
+ * This is testing for a cmov (0x0f 0x4x) instruction causing a
* SIGILL in init.
*/
- if((sig != SIGILL) || (TASK_PID(get_current()) != 1))
+ if ((sig != SIGILL) || (TASK_PID(get_current()) != 1))
return 0;
if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2))
panic("SIGILL in init, could not read instructions!\n");
- if((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40))
+ if ((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40))
return 0;
- if(host_has_cmov == 0)
+ if (host_has_cmov == 0)
panic("SIGILL caused by cmov, which this processor doesn't "
"implement, boot a filesystem compiled for older "
"processors");
- else if(host_has_cmov == 1)
+ else if (host_has_cmov == 1)
panic("SIGILL caused by cmov, which this processor claims to "
"implement");
- else if(host_has_cmov == -1)
+ else if (host_has_cmov == -1)
panic("SIGILL caused by cmov, couldn't tell if this processor "
"implements it, boot a filesystem compiled for older "
"processors");
diff --git a/arch/um/sys-i386/fault.c b/arch/um/sys-i386/fault.c
index 745b4fd49e9f..d670f68532f4 100644
--- a/arch/um/sys-i386/fault.c
+++ b/arch/um/sys-i386/fault.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -15,14 +15,14 @@ struct exception_table_entry
const struct exception_table_entry *search_exception_tables(unsigned long add);
/* Compare this to arch/i386/mm/extable.c:fixup_exception() */
-int arch_fixup(unsigned long address, union uml_pt_regs *regs)
+int arch_fixup(unsigned long address, struct uml_pt_regs *regs)
{
const struct exception_table_entry *fixup;
fixup = search_exception_tables(address);
- if(fixup != 0){
+ if (fixup != 0) {
UPT_IP(regs) = fixup->fixup;
- return(1);
+ return 1;
}
- return(0);
+ return 0;
}
diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c
index a939a7ef0227..67c0958eb984 100644
--- a/arch/um/sys-i386/ldt.c
+++ b/arch/um/sys-i386/ldt.c
@@ -1,106 +1,30 @@
/*
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/sched.h"
-#include "linux/slab.h"
-#include "linux/types.h"
-#include "linux/errno.h"
-#include "linux/spinlock.h"
-#include "asm/uaccess.h"
-#include "asm/smp.h"
-#include "asm/ldt.h"
+#include "linux/mm.h"
#include "asm/unistd.h"
-#include "choose-mode.h"
-#include "kern.h"
-#include "mode_kern.h"
#include "os.h"
-
-extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
-
-#ifdef CONFIG_MODE_TT
-
-static long do_modify_ldt_tt(int func, void __user *ptr,
- unsigned long bytecount)
-{
- struct user_desc info;
- int res = 0;
- void *buf = NULL;
- void *p = NULL; /* What we pass to host. */
-
- switch(func){
- case 1:
- case 0x11: /* write_ldt */
- /* Do this check now to avoid overflows. */
- if (bytecount != sizeof(struct user_desc)) {
- res = -EINVAL;
- goto out;
- }
-
- if(copy_from_user(&info, ptr, sizeof(info))) {
- res = -EFAULT;
- goto out;
- }
-
- p = &info;
- break;
- case 0:
- case 2: /* read_ldt */
-
- /* The use of info avoids kmalloc on the write case, not on the
- * read one. */
- buf = kmalloc(bytecount, GFP_KERNEL);
- if (!buf) {
- res = -ENOMEM;
- goto out;
- }
- p = buf;
- break;
- default:
- res = -ENOSYS;
- goto out;
- }
-
- res = modify_ldt(func, p, bytecount);
- if(res < 0)
- goto out;
-
- switch(func){
- case 0:
- case 2:
- /* Modify_ldt was for reading and returned the number of read
- * bytes.*/
- if(copy_to_user(ptr, p, res))
- res = -EFAULT;
- break;
- }
-
-out:
- kfree(buf);
- return res;
-}
-
-#endif
-
-#ifdef CONFIG_MODE_SKAS
-
+#include "proc_mm.h"
#include "skas.h"
#include "skas_ptrace.h"
-#include "asm/mmu_context.h"
-#include "proc_mm.h"
+#include "sysdep/tls.h"
+
+extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc,
void **addr, int done)
{
long res;
- if(proc_mm){
- /* This is a special handling for the case, that the mm to
+ if (proc_mm) {
+ /*
+ * This is a special handling for the case, that the mm to
* modify isn't current->active_mm.
* If this is called directly by modify_ldt,
* (current->active_mm->context.skas.u == mm_idp)
- * will be true. So no call to switch_mm_skas(mm_idp) is done.
+ * will be true. So no call to __switch_mm(mm_idp) is done.
* If this is called in case of init_new_ldt or PTRACE_LDT,
* mm_idp won't belong to current->active_mm, but child->mm.
* So we need to switch child's mm into our userspace, then
@@ -108,12 +32,12 @@ long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc,
*
* Note: I'm unsure: should interrupts be disabled here?
*/
- if(!current->active_mm || current->active_mm == &init_mm ||
- mm_idp != &current->active_mm->context.skas.id)
- switch_mm_skas(mm_idp);
+ if (!current->active_mm || current->active_mm == &init_mm ||
+ mm_idp != &current->active_mm->context.id)
+ __switch_mm(mm_idp);
}
- if(ptrace_ldt) {
+ if (ptrace_ldt) {
struct ptrace_ldt ldt_op = (struct ptrace_ldt) {
.func = func,
.ptr = desc,
@@ -121,7 +45,7 @@ long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc,
u32 cpu;
int pid;
- if(!proc_mm)
+ if (!proc_mm)
pid = mm_idp->u.pid;
else {
cpu = get_cpu();
@@ -130,7 +54,7 @@ long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc,
res = os_ptrace_ldt(pid, 0, (unsigned long) &ldt_op);
- if(proc_mm)
+ if (proc_mm)
put_cpu();
}
else {
@@ -139,7 +63,7 @@ long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc,
(sizeof(*desc) + sizeof(long) - 1) &
~(sizeof(long) - 1),
addr, &stub_addr);
- if(!res){
+ if (!res) {
unsigned long args[] = { func,
(unsigned long)stub_addr,
sizeof(*desc),
@@ -149,13 +73,14 @@ long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc,
}
}
- if(proc_mm){
- /* This is the second part of special handling, that makes
+ if (proc_mm) {
+ /*
+ * This is the second part of special handling, that makes
* PTRACE_LDT possible to implement.
*/
- if(current->active_mm && current->active_mm != &init_mm &&
- mm_idp != &current->active_mm->context.skas.id)
- switch_mm_skas(&current->active_mm->context.skas.id);
+ if (current->active_mm && current->active_mm != &init_mm &&
+ mm_idp != &current->active_mm->context.id)
+ __switch_mm(&current->active_mm->context.id);
}
return res;
@@ -170,21 +95,22 @@ static long read_ldt_from_host(void __user * ptr, unsigned long bytecount)
.ptr = kmalloc(bytecount, GFP_KERNEL)};
u32 cpu;
- if(ptrace_ldt.ptr == NULL)
+ if (ptrace_ldt.ptr == NULL)
return -ENOMEM;
- /* This is called from sys_modify_ldt only, so userspace_pid gives
+ /*
+ * This is called from sys_modify_ldt only, so userspace_pid gives
* us the right number
*/
cpu = get_cpu();
res = os_ptrace_ldt(userspace_pid[cpu], 0, (unsigned long) &ptrace_ldt);
put_cpu();
- if(res < 0)
+ if (res < 0)
goto out;
n = copy_to_user(ptr, ptrace_ldt.ptr, res);
- if(n != 0)
+ if (n != 0)
res = -EFAULT;
out:
@@ -209,35 +135,34 @@ static int read_ldt(void __user * ptr, unsigned long bytecount)
{
int i, err = 0;
unsigned long size;
- uml_ldt_t * ldt = &current->mm->context.skas.ldt;
+ uml_ldt_t * ldt = &current->mm->context.ldt;
- if(!ldt->entry_count)
+ if (!ldt->entry_count)
goto out;
- if(bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES)
+ if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES)
bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES;
err = bytecount;
- if(ptrace_ldt){
+ if (ptrace_ldt)
return read_ldt_from_host(ptr, bytecount);
- }
down(&ldt->semaphore);
- if(ldt->entry_count <= LDT_DIRECT_ENTRIES){
+ if (ldt->entry_count <= LDT_DIRECT_ENTRIES) {
size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES;
- if(size > bytecount)
+ if (size > bytecount)
size = bytecount;
- if(copy_to_user(ptr, ldt->u.entries, size))
+ if (copy_to_user(ptr, ldt->u.entries, size))
err = -EFAULT;
bytecount -= size;
ptr += size;
}
else {
- for(i=0; i<ldt->entry_count/LDT_ENTRIES_PER_PAGE && bytecount;
- i++){
+ for (i=0; i<ldt->entry_count/LDT_ENTRIES_PER_PAGE && bytecount;
+ i++) {
size = PAGE_SIZE;
- if(size > bytecount)
+ if (size > bytecount)
size = bytecount;
- if(copy_to_user(ptr, ldt->u.pages[i], size)){
+ if (copy_to_user(ptr, ldt->u.pages[i], size)) {
err = -EFAULT;
break;
}
@@ -247,10 +172,10 @@ static int read_ldt(void __user * ptr, unsigned long bytecount)
}
up(&ldt->semaphore);
- if(bytecount == 0 || err == -EFAULT)
+ if (bytecount == 0 || err == -EFAULT)
goto out;
- if(clear_user(ptr, bytecount))
+ if (clear_user(ptr, bytecount))
err = -EFAULT;
out:
@@ -261,15 +186,16 @@ static int read_default_ldt(void __user * ptr, unsigned long bytecount)
{
int err;
- if(bytecount > 5*LDT_ENTRY_SIZE)
+ if (bytecount > 5*LDT_ENTRY_SIZE)
bytecount = 5*LDT_ENTRY_SIZE;
err = bytecount;
- /* UML doesn't support lcall7 and lcall27.
+ /*
+ * UML doesn't support lcall7 and lcall27.
* So, we don't really have a default ldt, but emulate
* an empty ldt of common host default ldt size.
*/
- if(clear_user(ptr, bytecount))
+ if (clear_user(ptr, bytecount))
err = -EFAULT;
return err;
@@ -277,60 +203,60 @@ static int read_default_ldt(void __user * ptr, unsigned long bytecount)
static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
{
- uml_ldt_t * ldt = &current->mm->context.skas.ldt;
- struct mm_id * mm_idp = &current->mm->context.skas.id;
+ uml_ldt_t * ldt = &current->mm->context.ldt;
+ struct mm_id * mm_idp = &current->mm->context.id;
int i, err;
struct user_desc ldt_info;
struct ldt_entry entry0, *ldt_p;
void *addr = NULL;
err = -EINVAL;
- if(bytecount != sizeof(ldt_info))
+ if (bytecount != sizeof(ldt_info))
goto out;
err = -EFAULT;
- if(copy_from_user(&ldt_info, ptr, sizeof(ldt_info)))
+ if (copy_from_user(&ldt_info, ptr, sizeof(ldt_info)))
goto out;
err = -EINVAL;
- if(ldt_info.entry_number >= LDT_ENTRIES)
+ if (ldt_info.entry_number >= LDT_ENTRIES)
goto out;
- if(ldt_info.contents == 3){
+ if (ldt_info.contents == 3) {
if (func == 1)
goto out;
if (ldt_info.seg_not_present == 0)
goto out;
}
- if(!ptrace_ldt)
- down(&ldt->semaphore);
+ if (!ptrace_ldt)
+ down(&ldt->semaphore);
err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1);
- if(err)
+ if (err)
goto out_unlock;
- else if(ptrace_ldt) {
- /* With PTRACE_LDT available, this is used as a flag only */
- ldt->entry_count = 1;
- goto out;
- }
-
- if(ldt_info.entry_number >= ldt->entry_count &&
- ldt_info.entry_number >= LDT_DIRECT_ENTRIES){
- for(i=ldt->entry_count/LDT_ENTRIES_PER_PAGE;
- i*LDT_ENTRIES_PER_PAGE <= ldt_info.entry_number;
- i++){
- if(i == 0)
+ else if (ptrace_ldt) {
+ /* With PTRACE_LDT available, this is used as a flag only */
+ ldt->entry_count = 1;
+ goto out;
+ }
+
+ if (ldt_info.entry_number >= ldt->entry_count &&
+ ldt_info.entry_number >= LDT_DIRECT_ENTRIES) {
+ for (i=ldt->entry_count/LDT_ENTRIES_PER_PAGE;
+ i*LDT_ENTRIES_PER_PAGE <= ldt_info.entry_number;
+ i++) {
+ if (i == 0)
memcpy(&entry0, ldt->u.entries,
sizeof(entry0));
ldt->u.pages[i] = (struct ldt_entry *)
__get_free_page(GFP_KERNEL|__GFP_ZERO);
- if(!ldt->u.pages[i]){
+ if (!ldt->u.pages[i]) {
err = -ENOMEM;
/* Undo the change in host */
memset(&ldt_info, 0, sizeof(ldt_info));
write_ldt_entry(mm_idp, 1, &ldt_info, &addr, 1);
goto out_unlock;
}
- if(i == 0) {
+ if (i == 0) {
memcpy(ldt->u.pages[0], &entry0,
sizeof(entry0));
memcpy(ldt->u.pages[0]+1, ldt->u.entries+1,
@@ -339,17 +265,17 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
ldt->entry_count = (i + 1) * LDT_ENTRIES_PER_PAGE;
}
}
- if(ldt->entry_count <= ldt_info.entry_number)
+ if (ldt->entry_count <= ldt_info.entry_number)
ldt->entry_count = ldt_info.entry_number + 1;
- if(ldt->entry_count <= LDT_DIRECT_ENTRIES)
+ if (ldt->entry_count <= LDT_DIRECT_ENTRIES)
ldt_p = ldt->u.entries + ldt_info.entry_number;
else
ldt_p = ldt->u.pages[ldt_info.entry_number/LDT_ENTRIES_PER_PAGE] +
ldt_info.entry_number%LDT_ENTRIES_PER_PAGE;
- if(ldt_info.base_addr == 0 && ldt_info.limit == 0 &&
- (func == 1 || LDT_empty(&ldt_info))){
+ if (ldt_info.base_addr == 0 && ldt_info.limit == 0 &&
+ (func == 1 || LDT_empty(&ldt_info))) {
ldt_p->a = 0;
ldt_p->b = 0;
}
@@ -400,7 +326,7 @@ static void ldt_get_host_info(void)
spin_lock(&host_ldt_lock);
- if(host_ldt_entries != NULL){
+ if (host_ldt_entries != NULL) {
spin_unlock(&host_ldt_lock);
return;
}
@@ -408,49 +334,49 @@ static void ldt_get_host_info(void)
spin_unlock(&host_ldt_lock);
- for(i = LDT_PAGES_MAX-1, order=0; i; i>>=1, order++);
+ for (i = LDT_PAGES_MAX-1, order=0; i; i>>=1, order++)
+ ;
ldt = (struct ldt_entry *)
__get_free_pages(GFP_KERNEL|__GFP_ZERO, order);
- if(ldt == NULL) {
- printk("ldt_get_host_info: couldn't allocate buffer for host "
- "ldt\n");
+ if (ldt == NULL) {
+ printk(KERN_ERR "ldt_get_host_info: couldn't allocate buffer "
+ "for host ldt\n");
return;
}
ret = modify_ldt(0, ldt, (1<<order)*PAGE_SIZE);
- if(ret < 0) {
- printk("ldt_get_host_info: couldn't read host ldt\n");
+ if (ret < 0) {
+ printk(KERN_ERR "ldt_get_host_info: couldn't read host ldt\n");
goto out_free;
}
- if(ret == 0) {
+ if (ret == 0) {
/* default_ldt is active, simply write an empty entry 0 */
host_ldt_entries = dummy_list;
goto out_free;
}
- for(i=0, size=0; i<ret/LDT_ENTRY_SIZE; i++){
- if(ldt[i].a != 0 || ldt[i].b != 0)
+ for (i=0, size=0; i<ret/LDT_ENTRY_SIZE; i++) {
+ if (ldt[i].a != 0 || ldt[i].b != 0)
size++;
}
- if(size < ARRAY_SIZE(dummy_list))
+ if (size < ARRAY_SIZE(dummy_list))
host_ldt_entries = dummy_list;
else {
size = (size + 1) * sizeof(dummy_list[0]);
tmp = kmalloc(size, GFP_KERNEL);
- if(tmp == NULL) {
- printk("ldt_get_host_info: couldn't allocate host ldt "
- "list\n");
+ if (tmp == NULL) {
+ printk(KERN_ERR "ldt_get_host_info: couldn't allocate "
+ "host ldt list\n");
goto out_free;
}
host_ldt_entries = tmp;
}
- for(i=0, k=0; i<ret/LDT_ENTRY_SIZE; i++){
- if(ldt[i].a != 0 || ldt[i].b != 0) {
+ for (i=0, k=0; i<ret/LDT_ENTRY_SIZE; i++) {
+ if (ldt[i].a != 0 || ldt[i].b != 0)
host_ldt_entries[k++] = i;
- }
}
host_ldt_entries[k] = -1;
@@ -458,8 +384,7 @@ out_free:
free_pages((unsigned long)ldt, order);
}
-long init_new_ldt(struct mmu_context_skas * new_mm,
- struct mmu_context_skas * from_mm)
+long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm)
{
struct user_desc desc;
short * num_p;
@@ -469,15 +394,15 @@ long init_new_ldt(struct mmu_context_skas * new_mm,
struct proc_mm_op copy;
- if(!ptrace_ldt)
+ if (!ptrace_ldt)
init_MUTEX(&new_mm->ldt.semaphore);
- if(!from_mm){
+ if (!from_mm) {
memset(&desc, 0, sizeof(desc));
/*
* We have to initialize a clean ldt.
*/
- if(proc_mm) {
+ if (proc_mm) {
/*
* If the new mm was created using proc_mm, host's
* default-ldt currently is assigned, which normally
@@ -485,8 +410,7 @@ long init_new_ldt(struct mmu_context_skas * new_mm,
* To remove these gates, we simply write an empty
* entry as number 0 to the host.
*/
- err = write_ldt_entry(&new_mm->id, 1, &desc,
- &addr, 1);
+ err = write_ldt_entry(&new_mm->id, 1, &desc, &addr, 1);
}
else{
/*
@@ -495,11 +419,11 @@ long init_new_ldt(struct mmu_context_skas * new_mm,
* will be reset in the following loop
*/
ldt_get_host_info();
- for(num_p=host_ldt_entries; *num_p != -1; num_p++){
+ for (num_p=host_ldt_entries; *num_p != -1; num_p++) {
desc.entry_number = *num_p;
err = write_ldt_entry(&new_mm->id, 1, &desc,
&addr, *(num_p + 1) == -1);
- if(err)
+ if (err)
break;
}
}
@@ -508,8 +432,9 @@ long init_new_ldt(struct mmu_context_skas * new_mm,
goto out;
}
- if(proc_mm){
- /* We have a valid from_mm, so we now have to copy the LDT of
+ if (proc_mm) {
+ /*
+ * We have a valid from_mm, so we now have to copy the LDT of
* from_mm to new_mm, because using proc_mm an new mm with
* an empty/default LDT was created in new_mm()
*/
@@ -518,27 +443,27 @@ long init_new_ldt(struct mmu_context_skas * new_mm,
{ .copy_segments =
from_mm->id.u.mm_fd } } );
i = os_write_file(new_mm->id.u.mm_fd, &copy, sizeof(copy));
- if(i != sizeof(copy))
- printk("new_mm : /proc/mm copy_segments failed, "
- "err = %d\n", -i);
+ if (i != sizeof(copy))
+ printk(KERN_ERR "new_mm : /proc/mm copy_segments "
+ "failed, err = %d\n", -i);
}
- if(!ptrace_ldt) {
- /* Our local LDT is used to supply the data for
+ if (!ptrace_ldt) {
+ /*
+ * Our local LDT is used to supply the data for
* modify_ldt(READLDT), if PTRACE_LDT isn't available,
* i.e., we have to use the stub for modify_ldt, which
* can't handle the big read buffer of up to 64kB.
*/
down(&from_mm->ldt.semaphore);
- if(from_mm->ldt.entry_count <= LDT_DIRECT_ENTRIES){
+ if (from_mm->ldt.entry_count <= LDT_DIRECT_ENTRIES)
memcpy(new_mm->ldt.u.entries, from_mm->ldt.u.entries,
sizeof(new_mm->ldt.u.entries));
- }
- else{
+ else {
i = from_mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE;
- while(i-->0){
+ while (i-->0) {
page = __get_free_page(GFP_KERNEL|__GFP_ZERO);
- if (!page){
+ if (!page) {
err = -ENOMEM;
break;
}
@@ -557,22 +482,19 @@ long init_new_ldt(struct mmu_context_skas * new_mm,
}
-void free_ldt(struct mmu_context_skas * mm)
+void free_ldt(struct mm_context *mm)
{
int i;
- if(!ptrace_ldt && mm->ldt.entry_count > LDT_DIRECT_ENTRIES){
+ if (!ptrace_ldt && mm->ldt.entry_count > LDT_DIRECT_ENTRIES) {
i = mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE;
- while(i-- > 0){
- free_page((long )mm->ldt.u.pages[i]);
- }
+ while (i-- > 0)
+ free_page((long) mm->ldt.u.pages[i]);
}
mm->ldt.entry_count = 0;
}
-#endif
int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount)
{
- return CHOOSE_MODE_PROC(do_modify_ldt_tt, do_modify_ldt_skas, func,
- ptr, bytecount);
+ return do_modify_ldt_skas(func, ptr, bytecount);
}
diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c
index 28bf01150323..bd3da8a61f64 100644
--- a/arch/um/sys-i386/ptrace.c
+++ b/arch/um/sys-i386/ptrace.c
@@ -1,35 +1,26 @@
-/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+/*
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include <linux/compiler.h>
-#include "linux/sched.h"
#include "linux/mm.h"
-#include "asm/elf.h"
-#include "asm/ptrace.h"
+#include "linux/sched.h"
#include "asm/uaccess.h"
-#include "asm/unistd.h"
-#include "sysdep/ptrace.h"
-#include "sysdep/sigcontext.h"
-#include "sysdep/sc.h"
+#include "skas.h"
-void arch_switch_to_tt(struct task_struct *from, struct task_struct *to)
-{
- update_debugregs(to->thread.arch.debugregs_seq);
- arch_switch_tls_tt(from, to);
-}
+extern int arch_switch_tls(struct task_struct *from, struct task_struct *to);
-void arch_switch_to_skas(struct task_struct *from, struct task_struct *to)
+void arch_switch_to(struct task_struct *from, struct task_struct *to)
{
- int err = arch_switch_tls_skas(from, to);
+ int err = arch_switch_tls(from, to);
if (!err)
return;
if (err != -EINVAL)
- printk(KERN_WARNING "arch_switch_tls_skas failed, errno %d, not EINVAL\n", -err);
+ printk(KERN_WARNING "arch_switch_tls failed, errno %d, "
+ "not EINVAL\n", -err);
else
- printk(KERN_WARNING "arch_switch_tls_skas failed, errno = EINVAL\n");
+ printk(KERN_WARNING "arch_switch_tls failed, errno = EINVAL\n");
}
int is_syscall(unsigned long addr)
@@ -38,21 +29,21 @@ int is_syscall(unsigned long addr)
int n;
n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
- if(n){
+ if (n) {
/* access_process_vm() grants access to vsyscall and stub,
* while copy_from_user doesn't. Maybe access_process_vm is
* slow, but that doesn't matter, since it will be called only
* in case of singlestepping, if copy_from_user failed.
*/
n = access_process_vm(current, addr, &instr, sizeof(instr), 0);
- if(n != sizeof(instr)) {
- printk("is_syscall : failed to read instruction from "
- "0x%lx\n", addr);
- return(1);
+ if (n != sizeof(instr)) {
+ printk(KERN_ERR "is_syscall : failed to read "
+ "instruction from 0x%lx\n", addr);
+ return 1;
}
}
/* int 0x80 or sysenter */
- return((instr == 0x80cd) || (instr == 0x340f));
+ return (instr == 0x80cd) || (instr == 0x340f);
}
/* determines which flags the user has access to. */
@@ -96,21 +87,21 @@ int putreg(struct task_struct *child, int regno, unsigned long value)
int poke_user(struct task_struct *child, long addr, long data)
{
- if ((addr & 3) || addr < 0)
- return -EIO;
-
- if (addr < MAX_REG_OFFSET)
- return putreg(child, addr, data);
+ if ((addr & 3) || addr < 0)
+ return -EIO;
- else if((addr >= offsetof(struct user, u_debugreg[0])) &&
- (addr <= offsetof(struct user, u_debugreg[7]))){
- addr -= offsetof(struct user, u_debugreg[0]);
- addr = addr >> 2;
- if((addr == 4) || (addr == 5)) return -EIO;
- child->thread.arch.debugregs[addr] = data;
- return 0;
- }
- return -EIO;
+ if (addr < MAX_REG_OFFSET)
+ return putreg(child, addr, data);
+ else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
+ (addr <= offsetof(struct user, u_debugreg[7]))) {
+ addr -= offsetof(struct user, u_debugreg[0]);
+ addr = addr >> 2;
+ if ((addr == 4) || (addr == 5))
+ return -EIO;
+ child->thread.arch.debugregs[addr] = data;
+ return 0;
+ }
+ return -EIO;
}
unsigned long getreg(struct task_struct *child, int regno)
@@ -133,20 +124,20 @@ unsigned long getreg(struct task_struct *child, int regno)
return retval;
}
+/* read the word at location addr in the USER area. */
int peek_user(struct task_struct *child, long addr, long data)
{
-/* read the word at location addr in the USER area. */
unsigned long tmp;
if ((addr & 3) || addr < 0)
return -EIO;
tmp = 0; /* Default return condition */
- if(addr < MAX_REG_OFFSET){
+ if (addr < MAX_REG_OFFSET) {
tmp = getreg(child, addr);
}
- else if((addr >= offsetof(struct user, u_debugreg[0])) &&
- (addr <= offsetof(struct user, u_debugreg[7]))){
+ else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
+ (addr <= offsetof(struct user, u_debugreg[7]))) {
addr -= offsetof(struct user, u_debugreg[0]);
addr = addr >> 2;
tmp = child->thread.arch.debugregs[addr];
@@ -154,277 +145,68 @@ int peek_user(struct task_struct *child, long addr, long data)
return put_user(tmp, (unsigned long __user *) data);
}
-struct i387_fxsave_struct {
- unsigned short cwd;
- unsigned short swd;
- unsigned short twd;
- unsigned short fop;
- long fip;
- long fcs;
- long foo;
- long fos;
- long mxcsr;
- long reserved;
- long st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */
- long xmm_space[32]; /* 8*16 bytes for each XMM-reg = 128 bytes */
- long padding[56];
-};
-
-/*
- * FPU tag word conversions.
- */
-
-static inline unsigned short twd_i387_to_fxsr( unsigned short twd )
+int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
{
- unsigned int tmp; /* to avoid 16 bit prefixes in the code */
-
- /* Transform each pair of bits into 01 (valid) or 00 (empty) */
- tmp = ~twd;
- tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */
- /* and move the valid bits to the lower byte. */
- tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */
- tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */
- tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */
- return tmp;
-}
+ int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
+ long fpregs[HOST_FP_SIZE];
-static inline unsigned long twd_fxsr_to_i387( struct i387_fxsave_struct *fxsave )
-{
- struct _fpxreg *st = NULL;
- unsigned long twd = (unsigned long) fxsave->twd;
- unsigned long tag;
- unsigned long ret = 0xffff0000;
- int i;
+ BUG_ON(sizeof(*buf) != sizeof(fpregs));
+ err = save_fp_registers(userspace_pid[cpu], fpregs);
+ if (err)
+ return err;
-#define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16);
+ n = copy_to_user(buf, fpregs, sizeof(fpregs));
+ if(n > 0)
+ return -EFAULT;
- for ( i = 0 ; i < 8 ; i++ ) {
- if ( twd & 0x1 ) {
- st = (struct _fpxreg *) FPREG_ADDR( fxsave, i );
-
- switch ( st->exponent & 0x7fff ) {
- case 0x7fff:
- tag = 2; /* Special */
- break;
- case 0x0000:
- if ( !st->significand[0] &&
- !st->significand[1] &&
- !st->significand[2] &&
- !st->significand[3] ) {
- tag = 1; /* Zero */
- } else {
- tag = 2; /* Special */
- }
- break;
- default:
- if ( st->significand[3] & 0x8000 ) {
- tag = 0; /* Valid */
- } else {
- tag = 2; /* Special */
- }
- break;
- }
- } else {
- tag = 3; /* Empty */
- }
- ret |= (tag << (2 * i));
- twd = twd >> 1;
- }
- return ret;
+ return n;
}
-/*
- * FXSR floating point environment conversions.
- */
-
-#ifdef CONFIG_MODE_TT
-static inline int convert_fxsr_to_user_tt(struct _fpstate __user *buf,
- struct pt_regs *regs)
+int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
{
- struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs));
- unsigned long env[7];
- struct _fpreg __user *to;
- struct _fpxreg *from;
- int i;
+ int n, cpu = ((struct thread_info *) child->stack)->cpu;
+ long fpregs[HOST_FP_SIZE];
- env[0] = (unsigned long)fxsave->cwd | 0xffff0000;
- env[1] = (unsigned long)fxsave->swd | 0xffff0000;
- env[2] = twd_fxsr_to_i387(fxsave);
- env[3] = fxsave->fip;
- env[4] = fxsave->fcs | ((unsigned long)fxsave->fop << 16);
- env[5] = fxsave->foo;
- env[6] = fxsave->fos;
+ BUG_ON(sizeof(*buf) != sizeof(fpregs));
+ n = copy_from_user(fpregs, buf, sizeof(fpregs));
+ if (n > 0)
+ return -EFAULT;
- if ( __copy_to_user( buf, env, 7 * sizeof(unsigned long) ) )
- return 1;
-
- to = &buf->_st[0];
- from = (struct _fpxreg *) &fxsave->st_space[0];
- for ( i = 0 ; i < 8 ; i++, to++, from++ ) {
- if ( __copy_to_user( to, from, sizeof(*to) ) )
- return 1;
- }
- return 0;
+ return restore_fp_registers(userspace_pid[cpu], fpregs);
}
-#endif
-static inline int convert_fxsr_to_user(struct _fpstate __user *buf,
- struct pt_regs *regs)
+int get_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child)
{
- return(CHOOSE_MODE(convert_fxsr_to_user_tt(buf, regs), 0));
-}
+ int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
+ long fpregs[HOST_XFP_SIZE];
-#ifdef CONFIG_MODE_TT
-static inline int convert_fxsr_from_user_tt(struct pt_regs *regs,
- struct _fpstate __user *buf)
-{
- struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs));
- unsigned long env[7];
- struct _fpxreg *to;
- struct _fpreg __user *from;
- int i;
-
- if ( __copy_from_user( env, buf, 7 * sizeof(long) ) )
- return 1;
+ BUG_ON(sizeof(*buf) != sizeof(fpregs));
+ err = save_fpx_registers(userspace_pid[cpu], fpregs);
+ if (err)
+ return err;
- fxsave->cwd = (unsigned short)(env[0] & 0xffff);
- fxsave->swd = (unsigned short)(env[1] & 0xffff);
- fxsave->twd = twd_i387_to_fxsr((unsigned short)(env[2] & 0xffff));
- fxsave->fip = env[3];
- fxsave->fop = (unsigned short)((env[4] & 0xffff0000) >> 16);
- fxsave->fcs = (env[4] & 0xffff);
- fxsave->foo = env[5];
- fxsave->fos = env[6];
+ n = copy_to_user(buf, fpregs, sizeof(fpregs));
+ if(n > 0)
+ return -EFAULT;
- to = (struct _fpxreg *) &fxsave->st_space[0];
- from = &buf->_st[0];
- for ( i = 0 ; i < 8 ; i++, to++, from++ ) {
- if ( __copy_from_user( to, from, sizeof(*from) ) )
- return 1;
- }
- return 0;
-}
-#endif
-
-static inline int convert_fxsr_from_user(struct pt_regs *regs,
- struct _fpstate __user *buf)
-{
- return(CHOOSE_MODE(convert_fxsr_from_user_tt(regs, buf), 0));
-}
-
-int get_fpregs(unsigned long buf, struct task_struct *child)
-{
- int err;
-
- err = convert_fxsr_to_user((struct _fpstate __user *) buf,
- &child->thread.regs);
- if(err) return(-EFAULT);
- else return(0);
-}
-
-int set_fpregs(unsigned long buf, struct task_struct *child)
-{
- int err;
-
- err = convert_fxsr_from_user(&child->thread.regs,
- (struct _fpstate __user *) buf);
- if(err) return(-EFAULT);
- else return(0);
-}
-
-#ifdef CONFIG_MODE_TT
-int get_fpxregs_tt(unsigned long buf, struct task_struct *tsk)
-{
- struct pt_regs *regs = &tsk->thread.regs;
- struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs));
- int err;
-
- err = __copy_to_user((void __user *) buf, fxsave,
- sizeof(struct user_fxsr_struct));
- if(err) return -EFAULT;
- else return 0;
-}
-#endif
-
-int get_fpxregs(unsigned long buf, struct task_struct *tsk)
-{
- return(CHOOSE_MODE(get_fpxregs_tt(buf, tsk), 0));
-}
-
-#ifdef CONFIG_MODE_TT
-int set_fpxregs_tt(unsigned long buf, struct task_struct *tsk)
-{
- struct pt_regs *regs = &tsk->thread.regs;
- struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs));
- int err;
-
- err = __copy_from_user(fxsave, (void __user *) buf,
- sizeof(struct user_fxsr_struct) );
- if(err) return -EFAULT;
- else return 0;
-}
-#endif
-
-int set_fpxregs(unsigned long buf, struct task_struct *tsk)
-{
- return(CHOOSE_MODE(set_fpxregs_tt(buf, tsk), 0));
-}
-
-#ifdef notdef
-int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
-{
- fpu->cwd = (((SC_FP_CW(PT_REGS_SC(regs)) & 0xffff) << 16) |
- (SC_FP_SW(PT_REGS_SC(regs)) & 0xffff));
- fpu->swd = SC_FP_CSSEL(PT_REGS_SC(regs)) & 0xffff;
- fpu->twd = SC_FP_IPOFF(PT_REGS_SC(regs));
- fpu->fip = SC_FP_CSSEL(PT_REGS_SC(regs)) & 0xffff;
- fpu->fcs = SC_FP_DATAOFF(PT_REGS_SC(regs));
- fpu->foo = SC_FP_DATASEL(PT_REGS_SC(regs));
- fpu->fos = 0;
- memcpy(fpu->st_space, (void *) SC_FP_ST(PT_REGS_SC(regs)),
- sizeof(fpu->st_space));
- return(1);
+ return n;
}
-#endif
-#ifdef CONFIG_MODE_TT
-static inline void copy_fpu_fxsave_tt(struct pt_regs *regs,
- struct user_i387_struct *buf)
+int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child)
{
- struct i387_fxsave_struct *fpu = SC_FXSR_ENV(PT_REGS_SC(regs));
- unsigned short *to;
- unsigned short *from;
- int i;
+ int n, cpu = ((struct thread_info *) child->stack)->cpu;
+ long fpregs[HOST_XFP_SIZE];
- memcpy( buf, fpu, 7 * sizeof(long) );
+ BUG_ON(sizeof(*buf) != sizeof(fpregs));
+ n = copy_from_user(fpregs, buf, sizeof(fpregs));
+ if (n > 0)
+ return -EFAULT;
- to = (unsigned short *) &buf->st_space[0];
- from = (unsigned short *) &fpu->st_space[0];
- for ( i = 0 ; i < 8 ; i++, to += 5, from += 8 ) {
- memcpy( to, from, 5 * sizeof(unsigned short) );
- }
+ return restore_fpx_registers(userspace_pid[cpu], fpregs);
}
-#endif
-static inline void copy_fpu_fxsave(struct pt_regs *regs,
- struct user_i387_struct *buf)
+long subarch_ptrace(struct task_struct *child, long request, long addr,
+ long data)
{
- (void) CHOOSE_MODE(copy_fpu_fxsave_tt(regs, buf), 0);
+ return -EIO;
}
-
-int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu )
-{
- copy_fpu_fxsave(regs, (struct user_i387_struct *) fpu);
- return(1);
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/sys-i386/ptrace_user.c b/arch/um/sys-i386/ptrace_user.c
index 40ff0c831bd0..5cf97bc229b9 100644
--- a/arch/um/sys-i386/ptrace_user.c
+++ b/arch/um/sys-i386/ptrace_user.c
@@ -1,20 +1,10 @@
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include <stdio.h>
-#include <stddef.h>
#include <errno.h>
-#include <unistd.h>
-#include "ptrace_user.h"
-/* Grr, asm/user.h includes asm/ptrace.h, so has to follow ptrace_user.h */
-#include <asm/user.h>
-#include "kern_util.h"
-#include "sysdep/thread.h"
-#include "user.h"
-#include "os.h"
-#include "uml-config.h"
+#include <sys/ptrace.h>
int ptrace_getregs(long pid, unsigned long *regs_out)
{
@@ -43,89 +33,3 @@ int ptrace_setfpregs(long pid, unsigned long *regs)
return -errno;
return 0;
}
-
-#ifdef UML_CONFIG_MODE_TT
-
-static void write_debugregs(int pid, unsigned long *regs)
-{
- struct user *dummy;
- int nregs, i;
-
- dummy = NULL;
- nregs = ARRAY_SIZE(dummy->u_debugreg);
- for(i = 0; i < nregs; i++){
- if((i == 4) || (i == 5)) continue;
- if(ptrace(PTRACE_POKEUSR, pid, &dummy->u_debugreg[i],
- regs[i]) < 0)
- printk("write_debugregs - ptrace failed on "
- "register %d, value = 0x%lx, errno = %d\n", i,
- regs[i], errno);
- }
-}
-
-static void read_debugregs(int pid, unsigned long *regs)
-{
- struct user *dummy;
- int nregs, i;
-
- dummy = NULL;
- nregs = ARRAY_SIZE(dummy->u_debugreg);
- for(i = 0; i < nregs; i++){
- regs[i] = ptrace(PTRACE_PEEKUSR, pid,
- &dummy->u_debugreg[i], 0);
- }
-}
-
-/* Accessed only by the tracing thread */
-static unsigned long kernel_debugregs[8] = { [ 0 ... 7 ] = 0 };
-
-void arch_enter_kernel(void *task, int pid)
-{
- read_debugregs(pid, TASK_DEBUGREGS(task));
- write_debugregs(pid, kernel_debugregs);
-}
-
-void arch_leave_kernel(void *task, int pid)
-{
- read_debugregs(pid, kernel_debugregs);
- write_debugregs(pid, TASK_DEBUGREGS(task));
-}
-
-#ifdef UML_CONFIG_PT_PROXY
-/* Accessed only by the tracing thread */
-static int debugregs_seq;
-
-/* Only called by the ptrace proxy */
-void ptrace_pokeuser(unsigned long addr, unsigned long data)
-{
- if((addr < offsetof(struct user, u_debugreg[0])) ||
- (addr > offsetof(struct user, u_debugreg[7])))
- return;
- addr -= offsetof(struct user, u_debugreg[0]);
- addr = addr >> 2;
- if(kernel_debugregs[addr] == data) return;
-
- kernel_debugregs[addr] = data;
- debugregs_seq++;
-}
-
-static void update_debugregs_cb(void *arg)
-{
- int pid = *((int *) arg);
-
- write_debugregs(pid, kernel_debugregs);
-}
-
-/* Optimized out in its header when not defined */
-void update_debugregs(int seq)
-{
- int me;
-
- if(seq == debugregs_seq) return;
-
- me = os_getpid();
- initial_thread_cb(update_debugregs_cb, &me);
-}
-#endif
-
-#endif
diff --git a/arch/um/sys-i386/sigcontext.c b/arch/um/sys-i386/sigcontext.c
deleted file mode 100644
index 467d489c31cd..000000000000
--- a/arch/um/sys-i386/sigcontext.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <stddef.h>
-#include <string.h>
-#include <asm/ptrace.h>
-#include <asm/sigcontext.h>
-#include "sysdep/ptrace.h"
-#include "kern_util.h"
-
-void sc_to_sc(void *to_ptr, void *from_ptr)
-{
- struct sigcontext *to = to_ptr, *from = from_ptr;
-
- memcpy(to, from, sizeof(*to) + sizeof(struct _fpstate));
- if(from->fpstate != NULL)
- to->fpstate = (struct _fpstate *) (to + 1);
-}
-
-unsigned long *sc_sigmask(void *sc_ptr)
-{
- struct sigcontext *sc = sc_ptr;
- return &sc->oldmask;
-}
-
-int sc_get_fpregs(unsigned long buf, void *sc_ptr)
-{
- struct sigcontext *sc = sc_ptr;
- struct _fpstate *from = sc->fpstate, *to = (struct _fpstate *) buf;
- int err = 0;
-
- if(from == NULL){
- err |= clear_user_proc(&to->cw, sizeof(to->cw));
- err |= clear_user_proc(&to->sw, sizeof(to->sw));
- err |= clear_user_proc(&to->tag, sizeof(to->tag));
- err |= clear_user_proc(&to->ipoff, sizeof(to->ipoff));
- err |= clear_user_proc(&to->cssel, sizeof(to->cssel));
- err |= clear_user_proc(&to->dataoff, sizeof(to->dataoff));
- err |= clear_user_proc(&to->datasel, sizeof(to->datasel));
- err |= clear_user_proc(&to->_st, sizeof(to->_st));
- }
- else {
- err |= copy_to_user_proc(&to->cw, &from->cw, sizeof(to->cw));
- err |= copy_to_user_proc(&to->sw, &from->sw, sizeof(to->sw));
- err |= copy_to_user_proc(&to->tag, &from->tag,
- sizeof(to->tag));
- err |= copy_to_user_proc(&to->ipoff, &from->ipoff,
- sizeof(to->ipoff));
- err |= copy_to_user_proc(&to->cssel,& from->cssel,
- sizeof(to->cssel));
- err |= copy_to_user_proc(&to->dataoff, &from->dataoff,
- sizeof(to->dataoff));
- err |= copy_to_user_proc(&to->datasel, &from->datasel,
- sizeof(to->datasel));
- err |= copy_to_user_proc(to->_st, from->_st, sizeof(to->_st));
- }
- return(err);
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c
index 1cbf95f6858a..0147227ce18d 100644
--- a/arch/um/sys-i386/signal.c
+++ b/arch/um/sys-i386/signal.c
@@ -1,189 +1,293 @@
/*
- * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/signal.h"
#include "linux/ptrace.h"
-#include "asm/current.h"
-#include "asm/ucontext.h"
-#include "asm/uaccess.h"
#include "asm/unistd.h"
+#include "asm/uaccess.h"
+#include "asm/ucontext.h"
#include "frame_kern.h"
-#include "sigcontext.h"
-#include "registers.h"
-#include "mode.h"
-
-#ifdef CONFIG_MODE_SKAS
-
#include "skas.h"
-void copy_sc(union uml_pt_regs *regs, void *from)
+void copy_sc(struct uml_pt_regs *regs, void *from)
{
struct sigcontext *sc = from;
- REGS_GS(regs->skas.regs) = sc->gs;
- REGS_FS(regs->skas.regs) = sc->fs;
- REGS_ES(regs->skas.regs) = sc->es;
- REGS_DS(regs->skas.regs) = sc->ds;
- REGS_EDI(regs->skas.regs) = sc->edi;
- REGS_ESI(regs->skas.regs) = sc->esi;
- REGS_EBP(regs->skas.regs) = sc->ebp;
- REGS_SP(regs->skas.regs) = sc->esp;
- REGS_EBX(regs->skas.regs) = sc->ebx;
- REGS_EDX(regs->skas.regs) = sc->edx;
- REGS_ECX(regs->skas.regs) = sc->ecx;
- REGS_EAX(regs->skas.regs) = sc->eax;
- REGS_IP(regs->skas.regs) = sc->eip;
- REGS_CS(regs->skas.regs) = sc->cs;
- REGS_EFLAGS(regs->skas.regs) = sc->eflags;
- REGS_SS(regs->skas.regs) = sc->ss;
+ REGS_GS(regs->gp) = sc->gs;
+ REGS_FS(regs->gp) = sc->fs;
+ REGS_ES(regs->gp) = sc->es;
+ REGS_DS(regs->gp) = sc->ds;
+ REGS_EDI(regs->gp) = sc->edi;
+ REGS_ESI(regs->gp) = sc->esi;
+ REGS_EBP(regs->gp) = sc->ebp;
+ REGS_SP(regs->gp) = sc->esp;
+ REGS_EBX(regs->gp) = sc->ebx;
+ REGS_EDX(regs->gp) = sc->edx;
+ REGS_ECX(regs->gp) = sc->ecx;
+ REGS_EAX(regs->gp) = sc->eax;
+ REGS_IP(regs->gp) = sc->eip;
+ REGS_CS(regs->gp) = sc->cs;
+ REGS_EFLAGS(regs->gp) = sc->eflags;
+ REGS_SS(regs->gp) = sc->ss;
}
-static int copy_sc_from_user_skas(struct pt_regs *regs,
- struct sigcontext __user *from)
+/*
+ * FPU tag word conversions.
+ */
+
+static inline unsigned short twd_i387_to_fxsr(unsigned short twd)
{
- struct sigcontext sc;
- unsigned long fpregs[HOST_FP_SIZE];
- int err;
+ unsigned int tmp; /* to avoid 16 bit prefixes in the code */
+
+ /* Transform each pair of bits into 01 (valid) or 00 (empty) */
+ tmp = ~twd;
+ tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */
+ /* and move the valid bits to the lower byte. */
+ tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */
+ tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */
+ tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */
+ return tmp;
+}
- err = copy_from_user(&sc, from, sizeof(sc));
- err |= copy_from_user(fpregs, sc.fpstate, sizeof(fpregs));
- if(err)
- return err;
+static inline unsigned long twd_fxsr_to_i387(struct user_fxsr_struct *fxsave)
+{
+ struct _fpxreg *st = NULL;
+ unsigned long twd = (unsigned long) fxsave->twd;
+ unsigned long tag;
+ unsigned long ret = 0xffff0000;
+ int i;
+
+#define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16);
+
+ for (i = 0; i < 8; i++) {
+ if (twd & 0x1) {
+ st = (struct _fpxreg *) FPREG_ADDR(fxsave, i);
+
+ switch (st->exponent & 0x7fff) {
+ case 0x7fff:
+ tag = 2; /* Special */
+ break;
+ case 0x0000:
+ if ( !st->significand[0] &&
+ !st->significand[1] &&
+ !st->significand[2] &&
+ !st->significand[3] ) {
+ tag = 1; /* Zero */
+ } else {
+ tag = 2; /* Special */
+ }
+ break;
+ default:
+ if (st->significand[3] & 0x8000) {
+ tag = 0; /* Valid */
+ } else {
+ tag = 2; /* Special */
+ }
+ break;
+ }
+ } else {
+ tag = 3; /* Empty */
+ }
+ ret |= (tag << (2 * i));
+ twd = twd >> 1;
+ }
+ return ret;
+}
- copy_sc(&regs->regs, &sc);
+static int convert_fxsr_to_user(struct _fpstate __user *buf,
+ struct user_fxsr_struct *fxsave)
+{
+ unsigned long env[7];
+ struct _fpreg __user *to;
+ struct _fpxreg *from;
+ int i;
+
+ env[0] = (unsigned long)fxsave->cwd | 0xffff0000ul;
+ env[1] = (unsigned long)fxsave->swd | 0xffff0000ul;
+ env[2] = twd_fxsr_to_i387(fxsave);
+ env[3] = fxsave->fip;
+ env[4] = fxsave->fcs | ((unsigned long)fxsave->fop << 16);
+ env[5] = fxsave->foo;
+ env[6] = fxsave->fos;
+
+ if (__copy_to_user(buf, env, 7 * sizeof(unsigned long)))
+ return 1;
- err = restore_fp_registers(userspace_pid[0], fpregs);
- if(err < 0) {
- printk("copy_sc_from_user_skas - PTRACE_SETFPREGS failed, "
- "errno = %d\n", -err);
- return err;
- }
+ to = &buf->_st[0];
+ from = (struct _fpxreg *) &fxsave->st_space[0];
+ for (i = 0; i < 8; i++, to++, from++) {
+ unsigned long __user *t = (unsigned long __user *)to;
+ unsigned long *f = (unsigned long *)from;
+ if (__put_user(*f, t) ||
+ __put_user(*(f + 1), t + 1) ||
+ __put_user(from->exponent, &to->exponent))
+ return 1;
+ }
return 0;
}
-int copy_sc_to_user_skas(struct sigcontext __user *to, struct _fpstate __user *to_fp,
- struct pt_regs *regs, unsigned long sp)
+static int convert_fxsr_from_user(struct user_fxsr_struct *fxsave,
+ struct _fpstate __user *buf)
{
- struct sigcontext sc;
- unsigned long fpregs[HOST_FP_SIZE];
- struct faultinfo * fi = &current->thread.arch.faultinfo;
- int err;
+ unsigned long env[7];
+ struct _fpxreg *to;
+ struct _fpreg __user *from;
+ int i;
- sc.gs = REGS_GS(regs->regs.skas.regs);
- sc.fs = REGS_FS(regs->regs.skas.regs);
- sc.es = REGS_ES(regs->regs.skas.regs);
- sc.ds = REGS_DS(regs->regs.skas.regs);
- sc.edi = REGS_EDI(regs->regs.skas.regs);
- sc.esi = REGS_ESI(regs->regs.skas.regs);
- sc.ebp = REGS_EBP(regs->regs.skas.regs);
- sc.esp = sp;
- sc.ebx = REGS_EBX(regs->regs.skas.regs);
- sc.edx = REGS_EDX(regs->regs.skas.regs);
- sc.ecx = REGS_ECX(regs->regs.skas.regs);
- sc.eax = REGS_EAX(regs->regs.skas.regs);
- sc.eip = REGS_IP(regs->regs.skas.regs);
- sc.cs = REGS_CS(regs->regs.skas.regs);
- sc.eflags = REGS_EFLAGS(regs->regs.skas.regs);
- sc.esp_at_signal = regs->regs.skas.regs[UESP];
- sc.ss = regs->regs.skas.regs[SS];
- sc.cr2 = fi->cr2;
- sc.err = fi->error_code;
- sc.trapno = fi->trap_no;
-
- err = save_fp_registers(userspace_pid[0], fpregs);
- if(err < 0){
- printk("copy_sc_to_user_skas - PTRACE_GETFPREGS failed, "
- "errno = %d\n", err);
+ if (copy_from_user( env, buf, 7 * sizeof(long)))
return 1;
- }
- to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1));
- sc.fpstate = to_fp;
- if(err)
- return err;
-
- return copy_to_user(to, &sc, sizeof(sc)) ||
- copy_to_user(to_fp, fpregs, sizeof(fpregs));
+ fxsave->cwd = (unsigned short)(env[0] & 0xffff);
+ fxsave->swd = (unsigned short)(env[1] & 0xffff);
+ fxsave->twd = twd_i387_to_fxsr((unsigned short)(env[2] & 0xffff));
+ fxsave->fip = env[3];
+ fxsave->fop = (unsigned short)((env[4] & 0xffff0000ul) >> 16);
+ fxsave->fcs = (env[4] & 0xffff);
+ fxsave->foo = env[5];
+ fxsave->fos = env[6];
+
+ to = (struct _fpxreg *) &fxsave->st_space[0];
+ from = &buf->_st[0];
+ for (i = 0; i < 8; i++, to++, from++) {
+ unsigned long *t = (unsigned long *)to;
+ unsigned long __user *f = (unsigned long __user *)from;
+
+ if (__get_user(*t, f) ||
+ __get_user(*(t + 1), f + 1) ||
+ __get_user(to->exponent, &from->exponent))
+ return 1;
+ }
+ return 0;
}
-#endif
-#ifdef CONFIG_MODE_TT
+extern int have_fpx_regs;
-/* These copy a sigcontext to/from userspace. They copy the fpstate pointer,
- * blowing away the old, good one. So, that value is saved, and then restored
- * after the sigcontext copy. In copy_from, the variable holding the saved
- * fpstate pointer, and the sigcontext that it should be restored to are both
- * in the kernel, so we can just restore using an assignment. In copy_to, the
- * saved pointer is in the kernel, but the sigcontext is in userspace, so we
- * copy_to_user it.
- */
-int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext __user *from,
- int fpsize)
+static int copy_sc_from_user(struct pt_regs *regs,
+ struct sigcontext __user *from)
{
- struct _fpstate *to_fp;
- struct _fpstate __user *from_fp;
- unsigned long sigs;
+ struct sigcontext sc;
int err;
- to_fp = to->fpstate;
- sigs = to->oldmask;
- err = copy_from_user(to, from, sizeof(*to));
- from_fp = to->fpstate;
- to->oldmask = sigs;
- to->fpstate = to_fp;
- if(to_fp != NULL)
- err |= copy_from_user(to_fp, from_fp, fpsize);
- return err;
+ err = copy_from_user(&sc, from, sizeof(sc));
+ if (err)
+ return err;
+
+ copy_sc(&regs->regs, &sc);
+ if (have_fpx_regs) {
+ struct user_fxsr_struct fpx;
+
+ err = copy_from_user(&fpx, &sc.fpstate->_fxsr_env[0],
+ sizeof(struct user_fxsr_struct));
+ if (err)
+ return 1;
+
+ err = convert_fxsr_from_user(&fpx, sc.fpstate);
+ if (err)
+ return 1;
+
+ err = restore_fpx_registers(userspace_pid[current_thread->cpu],
+ (unsigned long *) &fpx);
+ if (err < 0) {
+ printk(KERN_ERR "copy_sc_from_user - "
+ "restore_fpx_registers failed, errno = %d\n",
+ -err);
+ return 1;
+ }
+ }
+ else {
+ struct user_i387_struct fp;
+
+ err = copy_from_user(&fp, sc.fpstate,
+ sizeof(struct user_i387_struct));
+ if (err)
+ return 1;
+
+ err = restore_fp_registers(userspace_pid[current_thread->cpu],
+ (unsigned long *) &fp);
+ if (err < 0) {
+ printk(KERN_ERR "copy_sc_from_user - "
+ "restore_fp_registers failed, errno = %d\n",
+ -err);
+ return 1;
+ }
+ }
+
+ return 0;
}
-int copy_sc_to_user_tt(struct sigcontext __user *to, struct _fpstate __user *fp,
- struct sigcontext *from, int fpsize, unsigned long sp)
+static int copy_sc_to_user(struct sigcontext __user *to,
+ struct _fpstate __user *to_fp, struct pt_regs *regs,
+ unsigned long sp)
{
- struct _fpstate __user *to_fp;
- struct _fpstate *from_fp;
+ struct sigcontext sc;
+ struct faultinfo * fi = &current->thread.arch.faultinfo;
int err;
- to_fp = (fp ? fp : (struct _fpstate __user *) (to + 1));
- from_fp = from->fpstate;
- err = copy_to_user(to, from, sizeof(*to));
+ sc.gs = REGS_GS(regs->regs.gp);
+ sc.fs = REGS_FS(regs->regs.gp);
+ sc.es = REGS_ES(regs->regs.gp);
+ sc.ds = REGS_DS(regs->regs.gp);
+ sc.edi = REGS_EDI(regs->regs.gp);
+ sc.esi = REGS_ESI(regs->regs.gp);
+ sc.ebp = REGS_EBP(regs->regs.gp);
+ sc.esp = sp;
+ sc.ebx = REGS_EBX(regs->regs.gp);
+ sc.edx = REGS_EDX(regs->regs.gp);
+ sc.ecx = REGS_ECX(regs->regs.gp);
+ sc.eax = REGS_EAX(regs->regs.gp);
+ sc.eip = REGS_IP(regs->regs.gp);
+ sc.cs = REGS_CS(regs->regs.gp);
+ sc.eflags = REGS_EFLAGS(regs->regs.gp);
+ sc.esp_at_signal = regs->regs.gp[UESP];
+ sc.ss = regs->regs.gp[SS];
+ sc.cr2 = fi->cr2;
+ sc.err = fi->error_code;
+ sc.trapno = fi->trap_no;
- /* The SP in the sigcontext is the updated one for the signal
- * delivery. The sp passed in is the original, and this needs
- * to be restored, so we stick it in separately.
- */
- err |= copy_to_user(&SC_SP(to), &sp, sizeof(sp));
+ to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1));
+ sc.fpstate = to_fp;
- if(from_fp != NULL){
- err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate));
- err |= copy_to_user(to_fp, from_fp, fpsize);
+ if (have_fpx_regs) {
+ struct user_fxsr_struct fpx;
+
+ err = save_fpx_registers(userspace_pid[current_thread->cpu],
+ (unsigned long *) &fpx);
+ if (err < 0){
+ printk(KERN_ERR "copy_sc_to_user - save_fpx_registers "
+ "failed, errno = %d\n", err);
+ return 1;
+ }
+
+ err = convert_fxsr_to_user(to_fp, &fpx);
+ if (err)
+ return 1;
+
+ err |= __put_user(fpx.swd, &to_fp->status);
+ err |= __put_user(X86_FXSR_MAGIC, &to_fp->magic);
+ if (err)
+ return 1;
+
+ if (copy_to_user(&to_fp->_fxsr_env[0], &fpx,
+ sizeof(struct user_fxsr_struct)))
+ return 1;
}
- return err;
-}
-#endif
-
-static int copy_sc_from_user(struct pt_regs *to, void __user *from)
-{
- int ret;
+ else {
+ struct user_i387_struct fp;
- ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from,
- sizeof(struct _fpstate)),
- copy_sc_from_user_skas(to, from));
- return ret;
-}
+ err = save_fp_registers(userspace_pid[current_thread->cpu],
+ (unsigned long *) &fp);
+ if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct)))
+ return 1;
+ }
-static int copy_sc_to_user(struct sigcontext __user *to, struct _fpstate __user *fp,
- struct pt_regs *from, unsigned long sp)
-{
- return CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs),
- sizeof(*fp), sp),
- copy_sc_to_user_skas(to, fp, from, sp));
+ return copy_to_user(to, &sc, sizeof(sc));
}
-static int copy_ucontext_to_user(struct ucontext __user *uc, struct _fpstate __user *fp,
- sigset_t *set, unsigned long sp)
+static int copy_ucontext_to_user(struct ucontext __user *uc,
+ struct _fpstate __user *fp, sigset_t *set,
+ unsigned long sp)
{
int err = 0;
@@ -233,7 +337,7 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
return 1;
restorer = frame->retcode;
- if(ka->sa.sa_flags & SA_RESTORER)
+ if (ka->sa.sa_flags & SA_RESTORER)
restorer = ka->sa.sa_restorer;
/* Update SP now because the page fault handler refuses to extend
@@ -265,7 +369,7 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
err |= __put_user(__NR_sigreturn, (int __user *)(frame->retcode+2));
err |= __put_user(0x80cd, (short __user *)(frame->retcode+6));
- if(err)
+ if (err)
goto err;
PT_REGS_SP(regs) = (unsigned long) frame;
@@ -298,7 +402,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
return 1;
restorer = frame->retcode;
- if(ka->sa.sa_flags & SA_RESTORER)
+ if (ka->sa.sa_flags & SA_RESTORER)
restorer = ka->sa.sa_restorer;
/* See comment above about why this is here */
@@ -323,7 +427,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
err |= __put_user(__NR_rt_sigreturn, (int __user *)(frame->retcode+1));
err |= __put_user(0x80cd, (short __user *)(frame->retcode+5));
- if(err)
+ if (err)
goto err;
PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
@@ -350,8 +454,8 @@ long sys_sigreturn(struct pt_regs regs)
unsigned long __user *extramask = frame->extramask;
int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
- if(copy_from_user(&set.sig[0], oldmask, sizeof(set.sig[0])) ||
- copy_from_user(&set.sig[1], extramask, sig_size))
+ if (copy_from_user(&set.sig[0], oldmask, sizeof(set.sig[0])) ||
+ copy_from_user(&set.sig[1], extramask, sig_size))
goto segfault;
sigdelsetmask(&set, ~_BLOCKABLE);
@@ -361,7 +465,7 @@ long sys_sigreturn(struct pt_regs regs)
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
- if(copy_sc_from_user(&current->thread.regs, sc))
+ if (copy_sc_from_user(&current->thread.regs, sc))
goto segfault;
/* Avoid ERESTART handling */
@@ -376,12 +480,13 @@ long sys_sigreturn(struct pt_regs regs)
long sys_rt_sigreturn(struct pt_regs regs)
{
unsigned long sp = PT_REGS_SP(&current->thread.regs);
- struct rt_sigframe __user *frame = (struct rt_sigframe __user *) (sp - 4);
+ struct rt_sigframe __user *frame =
+ (struct rt_sigframe __user *) (sp - 4);
sigset_t set;
struct ucontext __user *uc = &frame->uc;
int sig_size = _NSIG_WORDS * sizeof(unsigned long);
- if(copy_from_user(&set, &uc->uc_sigmask, sig_size))
+ if (copy_from_user(&set, &uc->uc_sigmask, sig_size))
goto segfault;
sigdelsetmask(&set, ~_BLOCKABLE);
@@ -391,7 +496,7 @@ long sys_rt_sigreturn(struct pt_regs regs)
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
- if(copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext))
+ if (copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext))
goto segfault;
/* Avoid ERESTART handling */
diff --git a/arch/um/sys-i386/stub.S b/arch/um/sys-i386/stub.S
index 6a70d9ab5c29..e730772c401b 100644
--- a/arch/um/sys-i386/stub.S
+++ b/arch/um/sys-i386/stub.S
@@ -1,4 +1,5 @@
#include "uml-config.h"
+#include "as-layout.h"
.globl syscall_stub
.section .__syscall_stub, "x"
@@ -6,7 +7,7 @@
.globl batch_syscall_stub
batch_syscall_stub:
/* load pointer to first operation */
- mov $(UML_CONFIG_STUB_DATA+8), %esp
+ mov $(ASM_STUB_DATA+8), %esp
again:
/* load length of additional data */
@@ -14,12 +15,12 @@ again:
/* if(length == 0) : end of list */
/* write possible 0 to header */
- mov %eax, UML_CONFIG_STUB_DATA+4
+ mov %eax, ASM_STUB_DATA+4
cmpl $0, %eax
jz done
/* save current pointer */
- mov %esp, UML_CONFIG_STUB_DATA+4
+ mov %esp, ASM_STUB_DATA+4
/* skip additional data */
add %eax, %esp
@@ -45,7 +46,7 @@ again:
done:
/* save return value */
- mov %eax, UML_CONFIG_STUB_DATA
+ mov %eax, ASM_STUB_DATA
/* stop */
int3
diff --git a/arch/um/sys-i386/stub_segv.c b/arch/um/sys-i386/stub_segv.c
index 2355dc19c46c..b3999cb76bfd 100644
--- a/arch/um/sys-i386/stub_segv.c
+++ b/arch/um/sys-i386/stub_segv.c
@@ -6,6 +6,7 @@
#include <signal.h>
#include <sys/select.h> /* The only way I can see to get sigset_t */
#include <asm/unistd.h>
+#include "as-layout.h"
#include "uml-config.h"
#include "sysdep/stub.h"
#include "sysdep/sigcontext.h"
@@ -17,8 +18,7 @@ stub_segv_handler(int sig)
struct sigcontext *sc = (struct sigcontext *) (&sig + 1);
int pid;
- GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA),
- sc);
+ GET_FAULTINFO_FROM_SC(*((struct faultinfo *) STUB_DATA), sc);
pid = stub_syscall0(__NR_getpid);
stub_syscall2(__NR_kill, pid, SIGUSR1);
diff --git a/arch/um/sys-i386/syscalls.c b/arch/um/sys-i386/syscalls.c
index 710d5fb807e1..e2d142684412 100644
--- a/arch/um/sys-i386/syscalls.c
+++ b/arch/um/sys-i386/syscalls.c
@@ -5,7 +5,7 @@
#include "linux/sched.h"
#include "linux/shm.h"
-#include "asm/ipc.h"
+#include "linux/ipc.h"
#include "asm/mman.h"
#include "asm/uaccess.h"
#include "asm/unistd.h"
diff --git a/arch/um/sys-i386/tls.c b/arch/um/sys-i386/tls.c
index fea8e5e15cc4..fcaff86b000c 100644
--- a/arch/um/sys-i386/tls.c
+++ b/arch/um/sys-i386/tls.c
@@ -3,25 +3,12 @@
* Licensed under the GPL
*/
-#include "linux/kernel.h"
+#include "linux/percpu.h"
#include "linux/sched.h"
-#include "linux/slab.h"
-#include "linux/types.h"
#include "asm/uaccess.h"
-#include "asm/ptrace.h"
-#include "asm/segment.h"
-#include "asm/smp.h"
-#include "asm/desc.h"
-#include "choose-mode.h"
-#include "kern.h"
-#include "kern_util.h"
-#include "mode_kern.h"
#include "os.h"
-#include "mode.h"
-
-#ifdef CONFIG_MODE_SKAS
#include "skas.h"
-#endif
+#include "sysdep/tls.h"
/*
* If needed we can detect when it's uninitialized.
@@ -31,8 +18,7 @@
static int host_supports_tls = -1;
int host_gdt_entry_tls_min;
-#ifdef CONFIG_MODE_SKAS
-int do_set_thread_area_skas(struct user_desc *info)
+int do_set_thread_area(struct user_desc *info)
{
int ret;
u32 cpu;
@@ -43,7 +29,7 @@ int do_set_thread_area_skas(struct user_desc *info)
return ret;
}
-int do_get_thread_area_skas(struct user_desc *info)
+int do_get_thread_area(struct user_desc *info)
{
int ret;
u32 cpu;
@@ -53,14 +39,13 @@ int do_get_thread_area_skas(struct user_desc *info)
put_cpu();
return ret;
}
-#endif
/*
* sys_get_thread_area: get a yet unused TLS descriptor index.
* XXX: Consider leaving one free slot for glibc usage at first place. This must
* be done here (and by changing GDT_ENTRY_TLS_* macros) and nowhere else.
*
- * Also, this must be tested when compiling in SKAS mode with dinamic linking
+ * Also, this must be tested when compiling in SKAS mode with dynamic linking
* and running against NPTL.
*/
static int get_free_idx(struct task_struct* task)
@@ -82,7 +67,8 @@ static inline void clear_user_desc(struct user_desc* info)
/* Postcondition: LDT_empty(info) returns true. */
memset(info, 0, sizeof(*info));
- /* Check the LDT_empty or the i386 sys_get_thread_area code - we obtain
+ /*
+ * Check the LDT_empty or the i386 sys_get_thread_area code - we obtain
* indeed an empty user_desc.
*/
info->read_exec_only = 1;
@@ -97,10 +83,13 @@ static int load_TLS(int flags, struct task_struct *to)
int idx;
for (idx = GDT_ENTRY_TLS_MIN; idx < GDT_ENTRY_TLS_MAX; idx++) {
- struct uml_tls_struct* curr = &to->thread.arch.tls_array[idx - GDT_ENTRY_TLS_MIN];
+ struct uml_tls_struct* curr =
+ &to->thread.arch.tls_array[idx - GDT_ENTRY_TLS_MIN];
- /* Actually, now if it wasn't flushed it gets cleared and
- * flushed to the host, which will clear it.*/
+ /*
+ * Actually, now if it wasn't flushed it gets cleared and
+ * flushed to the host, which will clear it.
+ */
if (!curr->present) {
if (!curr->flushed) {
clear_user_desc(&curr->tls);
@@ -124,7 +113,8 @@ out:
return ret;
}
-/* Verify if we need to do a flush for the new process, i.e. if there are any
+/*
+ * Verify if we need to do a flush for the new process, i.e. if there are any
* present desc's, only if they haven't been flushed.
*/
static inline int needs_TLS_update(struct task_struct *task)
@@ -133,10 +123,13 @@ static inline int needs_TLS_update(struct task_struct *task)
int ret = 0;
for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) {
- struct uml_tls_struct* curr = &task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN];
+ struct uml_tls_struct* curr =
+ &task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN];
- /* Can't test curr->present, we may need to clear a descriptor
- * which had a value. */
+ /*
+ * Can't test curr->present, we may need to clear a descriptor
+ * which had a value.
+ */
if (curr->flushed)
continue;
ret = 1;
@@ -145,7 +138,8 @@ static inline int needs_TLS_update(struct task_struct *task)
return ret;
}
-/* On a newly forked process, the TLS descriptors haven't yet been flushed. So
+/*
+ * On a newly forked process, the TLS descriptors haven't yet been flushed. So
* we mark them as such and the first switch_to will do the job.
*/
void clear_flushed_tls(struct task_struct *task)
@@ -153,10 +147,13 @@ void clear_flushed_tls(struct task_struct *task)
int i;
for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) {
- struct uml_tls_struct* curr = &task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN];
+ struct uml_tls_struct* curr =
+ &task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN];
- /* Still correct to do this, if it wasn't present on the host it
- * will remain as flushed as it was. */
+ /*
+ * Still correct to do this, if it wasn't present on the host it
+ * will remain as flushed as it was.
+ */
if (!curr->present)
continue;
@@ -164,40 +161,33 @@ void clear_flushed_tls(struct task_struct *task)
}
}
-/* In SKAS0 mode, currently, multiple guest threads sharing the same ->mm have a
+/*
+ * In SKAS0 mode, currently, multiple guest threads sharing the same ->mm have a
* common host process. So this is needed in SKAS0 too.
*
* However, if each thread had a different host process (and this was discussed
* for SMP support) this won't be needed.
*
* And this will not need be used when (and if) we'll add support to the host
- * SKAS patch. */
+ * SKAS patch.
+ */
-int arch_switch_tls_skas(struct task_struct *from, struct task_struct *to)
+int arch_switch_tls(struct task_struct *from, struct task_struct *to)
{
if (!host_supports_tls)
return 0;
- /* We have no need whatsoever to switch TLS for kernel threads; beyond
+ /*
+ * We have no need whatsoever to switch TLS for kernel threads; beyond
* that, that would also result in us calling os_set_thread_area with
- * userspace_pid[cpu] == 0, which gives an error. */
+ * userspace_pid[cpu] == 0, which gives an error.
+ */
if (likely(to->mm))
return load_TLS(O_FORCE, to);
return 0;
}
-int arch_switch_tls_tt(struct task_struct *from, struct task_struct *to)
-{
- if (!host_supports_tls)
- return 0;
-
- if (needs_TLS_update(to))
- return load_TLS(0, to);
-
- return 0;
-}
-
static int set_tls_entry(struct task_struct* task, struct user_desc *info,
int idx, int flushed)
{
@@ -251,17 +241,20 @@ static int get_tls_entry(struct task_struct* task, struct user_desc *info, int i
*info = t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].tls;
out:
- /* Temporary debugging check, to make sure that things have been
+ /*
+ * Temporary debugging check, to make sure that things have been
* flushed. This could be triggered if load_TLS() failed.
*/
- if (unlikely(task == current && !t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].flushed)) {
+ if (unlikely(task == current &&
+ !t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].flushed)) {
printk(KERN_ERR "get_tls_entry: task with pid %d got here "
"without flushed TLS.", current->pid);
}
return 0;
clear:
- /* When the TLS entry has not been set, the values read to user in the
+ /*
+ * When the TLS entry has not been set, the values read to user in the
* tls_array are 0 (because it's cleared at boot, see
* arch/i386/kernel/head.S:cpu_gdt_table). Emulate that.
*/
@@ -293,7 +286,7 @@ asmlinkage int sys_set_thread_area(struct user_desc __user *user_desc)
return -EFAULT;
}
- ret = CHOOSE_MODE_PROC(do_set_thread_area_tt, do_set_thread_area_skas, &info);
+ ret = do_set_thread_area(&info);
if (ret)
return ret;
return set_tls_entry(current, &info, idx, 1);
@@ -363,8 +356,10 @@ out:
}
-/* XXX: This part is probably common to i386 and x86-64. Don't create a common
- * file for now, do that when implementing x86-64 support.*/
+/*
+ * XXX: This part is probably common to i386 and x86-64. Don't create a common
+ * file for now, do that when implementing x86-64 support.
+ */
static int __init __setup_host_supports_tls(void)
{
check_host_supports_tls(&host_supports_tls, &host_gdt_entry_tls_min);
diff --git a/arch/um/sys-i386/unmap.c b/arch/um/sys-i386/unmap.c
deleted file mode 100644
index 1b0ad0e4adcd..000000000000
--- a/arch/um/sys-i386/unmap.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <linux/mman.h>
-#include <asm/unistd.h>
-
-static int errno;
-
-static inline _syscall2(int,munmap,void *,start,size_t,len)
-static inline _syscall6(void *,mmap2,void *,addr,size_t,len,int,prot,int,flags,int,fd,off_t,offset)
-int switcheroo(int fd, int prot, void *from, void *to, int size)
-{
- if(munmap(to, size) < 0){
- return(-1);
- }
- if(mmap2(to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) == (void*) -1 ){
- return(-1);
- }
- if(munmap(from, size) < 0){
- return(-1);
- }
- return(0);
-}
diff --git a/arch/um/sys-i386/user-offsets.c b/arch/um/sys-i386/user-offsets.c
index 29118cf5ff25..514241526a1b 100644
--- a/arch/um/sys-i386/user-offsets.c
+++ b/arch/um/sys-i386/user-offsets.c
@@ -2,9 +2,9 @@
#include <stddef.h>
#include <signal.h>
#include <sys/poll.h>
+#include <sys/user.h>
#include <sys/mman.h>
#include <asm/ptrace.h>
-#include <asm/user.h>
#define DEFINE(sym, val) \
asm volatile("\n->" #sym " %0 " #val : : "i" (val))
@@ -48,8 +48,8 @@ void foo(void)
OFFSET(HOST_SC_FP_ST, _fpstate, _st);
OFFSET(HOST_SC_FXSR_ENV, _fpstate, _fxsr_env);
- DEFINE_LONGS(HOST_FP_SIZE, sizeof(struct user_i387_struct));
- DEFINE_LONGS(HOST_XFP_SIZE, sizeof(struct user_fxsr_struct));
+ DEFINE_LONGS(HOST_FP_SIZE, sizeof(struct user_fpregs_struct));
+ DEFINE_LONGS(HOST_XFP_SIZE, sizeof(struct user_fpxregs_struct));
DEFINE(HOST_IP, EIP);
DEFINE(HOST_SP, UESP);
diff --git a/arch/um/sys-ppc/Makefile b/arch/um/sys-ppc/Makefile
index af200268fddb..a9814a7ae60e 100644
--- a/arch/um/sys-ppc/Makefile
+++ b/arch/um/sys-ppc/Makefile
@@ -1,7 +1,7 @@
OBJ = built-in.o
.S.o:
- $(CC) $(AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
+ $(CC) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
OBJS = ptrace.o sigcontext.o semaphore.o checksum.o miscthings.o misc.o \
ptrace_user.o sysrq.o
@@ -57,13 +57,13 @@ ppc_defs.h: mk_defs.c ppc_defs.head \
checksum.o: checksum.S
rm -f asm
ln -s $(TOPDIR)/include/asm-ppc asm
- $(CC) $(EXTRA_AFLAGS) $(AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
+ $(CC) $(EXTRA_AFLAGS) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
rm -f asm
misc.o: misc.S ppc_defs.h
rm -f asm
ln -s $(TOPDIR)/include/asm-ppc asm
- $(CC) $(EXTRA_AFLAGS) $(AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
+ $(CC) $(EXTRA_AFLAGS) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
rm -f asm
clean-files := $(OBJS) ppc_defs.h checksum.S semaphore.c mk_defs.c
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile
index ea8185d85404..3c22de532088 100644
--- a/arch/um/sys-x86_64/Makefile
+++ b/arch/um/sys-x86_64/Makefile
@@ -5,10 +5,9 @@
#
obj-y = bug.o bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \
- setjmp.o sigcontext.o signal.o syscalls.o syscall_table.o sysrq.o \
- ksyms.o tls.o
+ setjmp.o signal.o stub.o stub_segv.o syscalls.o syscall_table.o \
+ sysrq.o ksyms.o tls.o
-obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o
obj-$(CONFIG_MODULES) += um_module.o
subarch-obj-y = lib/bitops_64.o lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o
@@ -16,16 +15,12 @@ subarch-obj-$(CONFIG_MODULES) += kernel/module_64.o
ldt-y = ../sys-i386/ldt.o
-USER_OBJS := ptrace_user.o sigcontext.o
+USER_OBJS := ptrace_user.o
USER_OBJS += user-offsets.s
extra-y += user-offsets.s
-extra-$(CONFIG_MODE_TT) += unmap.o
-
UNPROFILE_OBJS := stub_segv.o
CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING)
include arch/um/scripts/Makefile.rules
-
-$(obj)/unmap.%: _c_flags = $(call unprofile,$(CFLAGS))
diff --git a/arch/um/sys-x86_64/bug.c b/arch/um/sys-x86_64/bug.c
index 200c8ba2879b..a4360b5207db 100644
--- a/arch/um/sys-x86_64/bug.c
+++ b/arch/um/sys-x86_64/bug.c
@@ -6,7 +6,7 @@
#include <linux/uaccess.h>
/* Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because
- * that's not relevent in skas mode.
+ * that's not relevant in skas mode.
*/
int is_valid_bugaddr(unsigned long eip)
diff --git a/arch/um/sys-x86_64/bugs.c b/arch/um/sys-x86_64/bugs.c
index 095478890371..506b6765bbcb 100644
--- a/arch/um/sys-x86_64/bugs.c
+++ b/arch/um/sys-x86_64/bugs.c
@@ -14,7 +14,7 @@ void arch_check_bugs(void)
{
}
-int arch_handle_signal(int sig, union uml_pt_regs *regs)
+int arch_handle_signal(int sig, struct uml_pt_regs *regs)
{
return 0;
}
diff --git a/arch/um/sys-x86_64/fault.c b/arch/um/sys-x86_64/fault.c
index 4636b1465b6c..ce85117fc64e 100644
--- a/arch/um/sys-x86_64/fault.c
+++ b/arch/um/sys-x86_64/fault.c
@@ -14,14 +14,15 @@ struct exception_table_entry
};
const struct exception_table_entry *search_exception_tables(unsigned long add);
-int arch_fixup(unsigned long address, union uml_pt_regs *regs)
+
+int arch_fixup(unsigned long address, struct uml_pt_regs *regs)
{
const struct exception_table_entry *fixup;
fixup = search_exception_tables(address);
- if(fixup != 0){
+ if (fixup != 0) {
UPT_IP(regs) = fixup->fixup;
- return(1);
+ return 1;
}
- return(0);
+ return 0;
}
diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c
index 1970d78aa528..b7631b0e9ddc 100644
--- a/arch/um/sys-x86_64/ptrace.c
+++ b/arch/um/sys-x86_64/ptrace.c
@@ -1,5 +1,6 @@
/*
* Copyright 2003 PathScale, Inc.
+ * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
*
* Licensed under the GPL
*/
@@ -12,17 +13,10 @@
#include <asm/uaccess.h>
#include <asm/elf.h>
-/* XXX x86_64 */
-unsigned long not_ss;
-unsigned long not_ds;
-unsigned long not_es;
-
-#define SC_SS(r) (not_ss)
-#define SC_DS(r) (not_ds)
-#define SC_ES(r) (not_es)
-
-/* determines which flags the user has access to. */
-/* 1 = access 0 = no access */
+/*
+ * determines which flags the user has access to.
+ * 1 = access 0 = no access
+ */
#define FLAG_MASK 0x44dd5UL
int putreg(struct task_struct *child, int regno, unsigned long value)
@@ -66,20 +60,21 @@ int putreg(struct task_struct *child, int regno, unsigned long value)
int poke_user(struct task_struct *child, long addr, long data)
{
- if ((addr & 3) || addr < 0)
- return -EIO;
-
- if (addr < MAX_REG_OFFSET)
- return putreg(child, addr, data);
- else if((addr >= offsetof(struct user, u_debugreg[0])) &&
- (addr <= offsetof(struct user, u_debugreg[7]))){
- addr -= offsetof(struct user, u_debugreg[0]);
- addr = addr >> 2;
- if((addr == 4) || (addr == 5)) return -EIO;
- child->thread.arch.debugregs[addr] = data;
- return 0;
- }
- return -EIO;
+ if ((addr & 3) || addr < 0)
+ return -EIO;
+
+ if (addr < MAX_REG_OFFSET)
+ return putreg(child, addr, data);
+ else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
+ (addr <= offsetof(struct user, u_debugreg[7]))){
+ addr -= offsetof(struct user, u_debugreg[0]);
+ addr = addr >> 2;
+ if ((addr == 4) || (addr == 5))
+ return -EIO;
+ child->thread.arch.debugregs[addr] = data;
+ return 0;
+ }
+ return -EIO;
}
unsigned long getreg(struct task_struct *child, int regno)
@@ -107,29 +102,22 @@ unsigned long getreg(struct task_struct *child, int regno)
int peek_user(struct task_struct *child, long addr, long data)
{
/* read the word at location addr in the USER area. */
- unsigned long tmp;
-
- if ((addr & 3) || addr < 0)
- return -EIO;
-
- tmp = 0; /* Default return condition */
- if(addr < MAX_REG_OFFSET){
- tmp = getreg(child, addr);
- }
- else if((addr >= offsetof(struct user, u_debugreg[0])) &&
- (addr <= offsetof(struct user, u_debugreg[7]))){
- addr -= offsetof(struct user, u_debugreg[0]);
- addr = addr >> 2;
- tmp = child->thread.arch.debugregs[addr];
- }
- return put_user(tmp, (unsigned long *) data);
-}
+ unsigned long tmp;
-void arch_switch(void)
-{
-/* XXX
- printk("arch_switch\n");
-*/
+ if ((addr & 3) || addr < 0)
+ return -EIO;
+
+ tmp = 0; /* Default return condition */
+ if (addr < MAX_REG_OFFSET){
+ tmp = getreg(child, addr);
+ }
+ else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
+ (addr <= offsetof(struct user, u_debugreg[7]))){
+ addr -= offsetof(struct user, u_debugreg[0]);
+ addr = addr >> 2;
+ tmp = child->thread.arch.debugregs[addr];
+ }
+ return put_user(tmp, (unsigned long *) data);
}
/* XXX Mostly copied from sys-i386 */
@@ -139,54 +127,68 @@ int is_syscall(unsigned long addr)
int n;
n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
- if(n){
+ if (n){
/* access_process_vm() grants access to vsyscall and stub,
* while copy_from_user doesn't. Maybe access_process_vm is
* slow, but that doesn't matter, since it will be called only
* in case of singlestepping, if copy_from_user failed.
*/
n = access_process_vm(current, addr, &instr, sizeof(instr), 0);
- if(n != sizeof(instr)) {
+ if (n != sizeof(instr)) {
printk("is_syscall : failed to read instruction from "
"0x%lx\n", addr);
- return(1);
+ return 1;
}
}
/* sysenter */
- return(instr == 0x050f);
+ return instr == 0x050f;
}
-int get_fpregs(unsigned long buf, struct task_struct *child)
+int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
{
- panic("get_fpregs");
- return(0);
-}
+ int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
+ long fpregs[HOST_FP_SIZE];
-int set_fpregs(unsigned long buf, struct task_struct *child)
-{
- panic("set_fpregs");
- return(0);
+ BUG_ON(sizeof(*buf) != sizeof(fpregs));
+ err = save_fp_registers(userspace_pid[cpu], fpregs);
+ if (err)
+ return err;
+
+ n = copy_to_user(buf, fpregs, sizeof(fpregs));
+ if(n > 0)
+ return -EFAULT;
+
+ return n;
}
-int get_fpxregs(unsigned long buf, struct task_struct *tsk)
+int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
{
- panic("get_fpxregs");
- return(0);
+ int n, cpu = ((struct thread_info *) child->stack)->cpu;
+ long fpregs[HOST_FP_SIZE];
+
+ BUG_ON(sizeof(*buf) != sizeof(fpregs));
+ n = copy_from_user(fpregs, buf, sizeof(fpregs));
+ if (n > 0)
+ return -EFAULT;
+
+ return restore_fp_registers(userspace_pid[cpu], fpregs);
}
-int set_fpxregs(unsigned long buf, struct task_struct *tsk)
+long subarch_ptrace(struct task_struct *child, long request, long addr,
+ long data)
{
- panic("set_fxpregs");
- return(0);
-}
+ int ret = -EIO;
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
+ switch (request) {
+ case PTRACE_GETFPXREGS: /* Get the child FPU state. */
+ ret = get_fpregs((struct user_i387_struct __user *) data,
+ child);
+ break;
+ case PTRACE_SETFPXREGS: /* Set the child FPU state. */
+ ret = set_fpregs((struct user_i387_struct __user *) data,
+ child);
+ break;
+ }
+
+ return ret;
+}
diff --git a/arch/um/sys-x86_64/sigcontext.c b/arch/um/sys-x86_64/sigcontext.c
deleted file mode 100644
index c88e64def6f2..000000000000
--- a/arch/um/sys-x86_64/sigcontext.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <signal.h>
-#include "user.h"
-
-void sc_to_sc(void *to_ptr, void *from_ptr)
-{
- struct sigcontext *to = to_ptr, *from = from_ptr;
- int size = sizeof(*to); /* + sizeof(struct _fpstate); */
-
- memcpy(to, from, size);
- if(from->fpstate != NULL)
- to->fpstate = (struct _fpstate *) (to + 1);
-
- to->fpstate = NULL;
-}
-
-unsigned long *sc_sigmask(void *sc_ptr)
-{
- struct sigcontext *sc = sc_ptr;
-
- return(&sc->oldmask);
-}
-
-/* Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c
index fe8ec04d35bb..1778d33808f4 100644
--- a/arch/um/sys-x86_64/signal.c
+++ b/arch/um/sys-x86_64/signal.c
@@ -1,111 +1,121 @@
/*
* Copyright (C) 2003 PathScale, Inc.
+ * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/stddef.h"
-#include "linux/errno.h"
#include "linux/personality.h"
#include "linux/ptrace.h"
-#include "asm/current.h"
+#include "asm/unistd.h"
#include "asm/uaccess.h"
-#include "asm/sigcontext.h"
-#include "asm/ptrace.h"
-#include "asm/arch/ucontext.h"
-#include "choose-mode.h"
-#include "sysdep/ptrace.h"
+#include "asm/ucontext.h"
#include "frame_kern.h"
-
-#ifdef CONFIG_MODE_SKAS
-
#include "skas.h"
-void copy_sc(union uml_pt_regs *regs, void *from)
+void copy_sc(struct uml_pt_regs *regs, void *from)
{
struct sigcontext *sc = from;
-#define GETREG(regs, regno, sc, regname) \
- (regs)->skas.regs[(regno) / sizeof(unsigned long)] = (sc)->regname
-
- GETREG(regs, R8, sc, r8);
- GETREG(regs, R9, sc, r9);
- GETREG(regs, R10, sc, r10);
- GETREG(regs, R11, sc, r11);
- GETREG(regs, R12, sc, r12);
- GETREG(regs, R13, sc, r13);
- GETREG(regs, R14, sc, r14);
- GETREG(regs, R15, sc, r15);
- GETREG(regs, RDI, sc, rdi);
- GETREG(regs, RSI, sc, rsi);
- GETREG(regs, RBP, sc, rbp);
- GETREG(regs, RBX, sc, rbx);
- GETREG(regs, RDX, sc, rdx);
- GETREG(regs, RAX, sc, rax);
- GETREG(regs, RCX, sc, rcx);
- GETREG(regs, RSP, sc, rsp);
- GETREG(regs, RIP, sc, rip);
- GETREG(regs, EFLAGS, sc, eflags);
- GETREG(regs, CS, sc, cs);
+#define GETREG(regs, regno, sc, regname) \
+ (regs)->gp[(regno) / sizeof(unsigned long)] = (sc)->regname
+
+ GETREG(regs, R8, sc, r8);
+ GETREG(regs, R9, sc, r9);
+ GETREG(regs, R10, sc, r10);
+ GETREG(regs, R11, sc, r11);
+ GETREG(regs, R12, sc, r12);
+ GETREG(regs, R13, sc, r13);
+ GETREG(regs, R14, sc, r14);
+ GETREG(regs, R15, sc, r15);
+ GETREG(regs, RDI, sc, rdi);
+ GETREG(regs, RSI, sc, rsi);
+ GETREG(regs, RBP, sc, rbp);
+ GETREG(regs, RBX, sc, rbx);
+ GETREG(regs, RDX, sc, rdx);
+ GETREG(regs, RAX, sc, rax);
+ GETREG(regs, RCX, sc, rcx);
+ GETREG(regs, RSP, sc, rsp);
+ GETREG(regs, RIP, sc, rip);
+ GETREG(regs, EFLAGS, sc, eflags);
+ GETREG(regs, CS, sc, cs);
#undef GETREG
}
-static int copy_sc_from_user_skas(struct pt_regs *regs,
- struct sigcontext __user *from)
+static int copy_sc_from_user(struct pt_regs *regs,
+ struct sigcontext __user *from,
+ struct _fpstate __user *fpp)
{
- int err = 0;
-
-#define GETREG(regs, regno, sc, regname) \
- __get_user((regs)->regs.skas.regs[(regno) / sizeof(unsigned long)], \
- &(sc)->regname)
-
- err |= GETREG(regs, R8, from, r8);
- err |= GETREG(regs, R9, from, r9);
- err |= GETREG(regs, R10, from, r10);
- err |= GETREG(regs, R11, from, r11);
- err |= GETREG(regs, R12, from, r12);
- err |= GETREG(regs, R13, from, r13);
- err |= GETREG(regs, R14, from, r14);
- err |= GETREG(regs, R15, from, r15);
- err |= GETREG(regs, RDI, from, rdi);
- err |= GETREG(regs, RSI, from, rsi);
- err |= GETREG(regs, RBP, from, rbp);
- err |= GETREG(regs, RBX, from, rbx);
- err |= GETREG(regs, RDX, from, rdx);
- err |= GETREG(regs, RAX, from, rax);
- err |= GETREG(regs, RCX, from, rcx);
- err |= GETREG(regs, RSP, from, rsp);
- err |= GETREG(regs, RIP, from, rip);
- err |= GETREG(regs, EFLAGS, from, eflags);
- err |= GETREG(regs, CS, from, cs);
+ struct user_i387_struct fp;
+ int err = 0;
+
+#define GETREG(regs, regno, sc, regname) \
+ __get_user((regs)->regs.gp[(regno) / sizeof(unsigned long)], \
+ &(sc)->regname)
+
+ err |= GETREG(regs, R8, from, r8);
+ err |= GETREG(regs, R9, from, r9);
+ err |= GETREG(regs, R10, from, r10);
+ err |= GETREG(regs, R11, from, r11);
+ err |= GETREG(regs, R12, from, r12);
+ err |= GETREG(regs, R13, from, r13);
+ err |= GETREG(regs, R14, from, r14);
+ err |= GETREG(regs, R15, from, r15);
+ err |= GETREG(regs, RDI, from, rdi);
+ err |= GETREG(regs, RSI, from, rsi);
+ err |= GETREG(regs, RBP, from, rbp);
+ err |= GETREG(regs, RBX, from, rbx);
+ err |= GETREG(regs, RDX, from, rdx);
+ err |= GETREG(regs, RAX, from, rax);
+ err |= GETREG(regs, RCX, from, rcx);
+ err |= GETREG(regs, RSP, from, rsp);
+ err |= GETREG(regs, RIP, from, rip);
+ err |= GETREG(regs, EFLAGS, from, eflags);
+ err |= GETREG(regs, CS, from, cs);
+ if (err)
+ return 1;
#undef GETREG
- return err;
+ err = copy_from_user(&fp, fpp, sizeof(struct user_i387_struct));
+ if (err)
+ return 1;
+
+ err = restore_fp_registers(userspace_pid[current_thread->cpu],
+ (unsigned long *) &fp);
+ if (err < 0) {
+ printk(KERN_ERR "copy_sc_from_user - "
+ "restore_fp_registers failed, errno = %d\n",
+ -err);
+ return 1;
+ }
+
+ return 0;
}
-int copy_sc_to_user_skas(struct sigcontext __user *to,
- struct _fpstate __user *to_fp,
- struct pt_regs *regs, unsigned long mask,
- unsigned long sp)
+static int copy_sc_to_user(struct sigcontext __user *to,
+ struct _fpstate __user *to_fp, struct pt_regs *regs,
+ unsigned long mask, unsigned long sp)
{
- struct faultinfo * fi = &current->thread.arch.faultinfo;
+ struct faultinfo * fi = &current->thread.arch.faultinfo;
+ struct user_i387_struct fp;
int err = 0;
err |= __put_user(0, &to->gs);
err |= __put_user(0, &to->fs);
-#define PUTREG(regs, regno, sc, regname) \
- __put_user((regs)->regs.skas.regs[(regno) / sizeof(unsigned long)], \
- &(sc)->regname)
+#define PUTREG(regs, regno, sc, regname) \
+ __put_user((regs)->regs.gp[(regno) / sizeof(unsigned long)], \
+ &(sc)->regname)
err |= PUTREG(regs, RDI, to, rdi);
err |= PUTREG(regs, RSI, to, rsi);
err |= PUTREG(regs, RBP, to, rbp);
- /* Must use orignal RSP, which is passed in, rather than what's in
- * the pt_regs, because that's already been updated to point at the
- * signal frame.
- */
+ /*
+ * Must use orignal RSP, which is passed in, rather than what's in
+ * the pt_regs, because that's already been updated to point at the
+ * signal frame.
+ */
err |= __put_user(sp, &to->rsp);
err |= PUTREG(regs, RBX, to, rbx);
err |= PUTREG(regs, RDX, to, rdx);
@@ -121,91 +131,38 @@ int copy_sc_to_user_skas(struct sigcontext __user *to,
err |= PUTREG(regs, R15, to, r15);
err |= PUTREG(regs, CS, to, cs); /* XXX x86_64 doesn't do this */
- err |= __put_user(fi->cr2, &to->cr2);
- err |= __put_user(fi->error_code, &to->err);
- err |= __put_user(fi->trap_no, &to->trapno);
+ err |= __put_user(fi->cr2, &to->cr2);
+ err |= __put_user(fi->error_code, &to->err);
+ err |= __put_user(fi->trap_no, &to->trapno);
err |= PUTREG(regs, RIP, to, rip);
err |= PUTREG(regs, EFLAGS, to, eflags);
#undef PUTREG
err |= __put_user(mask, &to->oldmask);
-
- return(err);
-}
-
-#endif
-
-#ifdef CONFIG_MODE_TT
-int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext __user *from,
- int fpsize)
-{
- struct _fpstate *to_fp;
- struct _fpstate __user *from_fp;
- unsigned long sigs;
- int err;
-
- to_fp = to->fpstate;
- sigs = to->oldmask;
- err = copy_from_user(to, from, sizeof(*to));
- from_fp = to->fpstate;
- to->fpstate = to_fp;
- to->oldmask = sigs;
- if(to_fp != NULL)
- err |= copy_from_user(to_fp, from_fp, fpsize);
- return(err);
-}
-
-int copy_sc_to_user_tt(struct sigcontext __user *to, struct _fpstate __user *fp,
- struct sigcontext *from, int fpsize, unsigned long sp)
-{
- struct _fpstate __user *to_fp;
- struct _fpstate *from_fp;
- int err;
-
- to_fp = (fp ? fp : (struct _fpstate __user *) (to + 1));
- from_fp = from->fpstate;
- err = copy_to_user(to, from, sizeof(*to));
- /* The SP in the sigcontext is the updated one for the signal
- * delivery. The sp passed in is the original, and this needs
- * to be restored, so we stick it in separately.
- */
- err |= copy_to_user(&SC_SP(to), &sp, sizeof(sp));
-
- if(from_fp != NULL){
- err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate));
- err |= copy_to_user(to_fp, from_fp, fpsize);
+ if (err)
+ return 1;
+
+ err = save_fp_registers(userspace_pid[current_thread->cpu],
+ (unsigned long *) &fp);
+ if (err < 0) {
+ printk(KERN_ERR "copy_sc_from_user - restore_fp_registers "
+ "failed, errno = %d\n", -err);
+ return 1;
}
- return err;
-}
-#endif
-
-static int copy_sc_from_user(struct pt_regs *to, void __user *from)
-{
- int ret;
-
- ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from,
- sizeof(struct _fpstate)),
- copy_sc_from_user_skas(to, from));
- return(ret);
-}
+ if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct)))
+ return 1;
-static int copy_sc_to_user(struct sigcontext __user *to,
- struct _fpstate __user *fp,
- struct pt_regs *from, unsigned long mask,
- unsigned long sp)
-{
- return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs),
- sizeof(*fp), sp),
- copy_sc_to_user_skas(to, fp, from, mask, sp)));
+ return err;
}
struct rt_sigframe
{
- char __user *pretcode;
- struct ucontext uc;
- struct siginfo info;
+ char __user *pretcode;
+ struct ucontext uc;
+ struct siginfo info;
+ struct _fpstate fpstate;
};
#define round_down(m, n) (((m) / (n)) * (n))
@@ -215,7 +172,6 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
siginfo_t *info, sigset_t *set)
{
struct rt_sigframe __user *frame;
- struct _fpstate __user *fp = NULL;
unsigned long save_sp = PT_REGS_RSP(regs);
int err = 0;
struct task_struct *me = current;
@@ -223,15 +179,8 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
frame = (struct rt_sigframe __user *)
round_down(stack_top - sizeof(struct rt_sigframe), 16);
/* Subtract 128 for a red zone and 8 for proper alignment */
- frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128 - 8);
-
- if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate)))
- goto out;
+ frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128 - 8);
-#if 0 /* XXX */
- if (save_i387(fp) < 0)
- err |= -1;
-#endif
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto out;
@@ -241,7 +190,8 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
goto out;
}
- /* Update SP now because the page fault handler refuses to extend
+ /*
+ * Update SP now because the page fault handler refuses to extend
* the stack if the faulting address is too far below the current
* SP, which frame now certainly is. If there's an error, the original
* value is restored on the way out.
@@ -258,9 +208,9 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
err |= __put_user(sas_ss_flags(save_sp),
&frame->uc.uc_stack.ss_flags);
err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size);
- err |= copy_sc_to_user(&frame->uc.uc_mcontext, fp, regs, set->sig[0],
- save_sp);
- err |= __put_user(fp, &frame->uc.uc_mcontext.fpstate);
+ err |= copy_sc_to_user(&frame->uc.uc_mcontext, &frame->fpstate, regs,
+ set->sig[0], save_sp);
+ err |= __put_user(&frame->fpstate, &frame->uc.uc_mcontext.fpstate);
if (sizeof(*set) == 16) {
__put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]);
__put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]);
@@ -269,8 +219,10 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
err |= __copy_to_user(&frame->uc.uc_sigmask, set,
sizeof(*set));
- /* Set up to return from userspace. If provided, use a stub
- already in userspace. */
+ /*
+ * Set up to return from userspace. If provided, use a stub
+ * already in userspace.
+ */
/* x86-64 should always use SA_RESTORER. */
if (ka->sa.sa_flags & SA_RESTORER)
err |= __put_user(ka->sa.sa_restorer, &frame->pretcode);
@@ -292,8 +244,10 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
/* In case the signal handler was declared without prototypes */
PT_REGS_RAX(regs) = 0;
- /* This also works for non SA_SIGINFO handlers because they expect the
- next argument after the signal number on the stack. */
+ /*
+ * This also works for non SA_SIGINFO handlers because they expect the
+ * next argument after the signal number on the stack.
+ */
PT_REGS_RSI(regs) = (unsigned long) &frame->info;
PT_REGS_RDX(regs) = (unsigned long) &frame->uc;
PT_REGS_RIP(regs) = (unsigned long) ka->sa.sa_handler;
@@ -313,7 +267,7 @@ long sys_rt_sigreturn(struct pt_regs *regs)
struct ucontext __user *uc = &frame->uc;
sigset_t set;
- if(copy_from_user(&set, &uc->uc_sigmask, sizeof(set)))
+ if (copy_from_user(&set, &uc->uc_sigmask, sizeof(set)))
goto segfault;
sigdelsetmask(&set, ~_BLOCKABLE);
@@ -323,24 +277,15 @@ long sys_rt_sigreturn(struct pt_regs *regs)
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
- if(copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext))
+ if (copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext,
+ &frame->fpstate))
goto segfault;
/* Avoid ERESTART handling */
PT_REGS_SYSCALL_NR(&current->thread.regs) = -1;
- return(PT_REGS_SYSCALL_RET(&current->thread.regs));
+ return PT_REGS_SYSCALL_RET(&current->thread.regs);
segfault:
force_sig(SIGSEGV, current);
return 0;
}
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/sys-x86_64/stub.S b/arch/um/sys-x86_64/stub.S
index 03c279735784..4afe204a6af7 100644
--- a/arch/um/sys-x86_64/stub.S
+++ b/arch/um/sys-x86_64/stub.S
@@ -1,4 +1,5 @@
#include "uml-config.h"
+#include "as-layout.h"
.globl syscall_stub
.section .__syscall_stub, "x"
@@ -7,18 +8,18 @@ syscall_stub:
/* We don't have 64-bit constants, so this constructs the address
* we need.
*/
- movq $(UML_CONFIG_STUB_DATA >> 32), %rbx
+ movq $(ASM_STUB_DATA >> 32), %rbx
salq $32, %rbx
- movq $(UML_CONFIG_STUB_DATA & 0xffffffff), %rcx
+ movq $(ASM_STUB_DATA & 0xffffffff), %rcx
or %rcx, %rbx
movq %rax, (%rbx)
int3
.globl batch_syscall_stub
batch_syscall_stub:
- mov $(UML_CONFIG_STUB_DATA >> 32), %rbx
+ mov $(ASM_STUB_DATA >> 32), %rbx
sal $32, %rbx
- mov $(UML_CONFIG_STUB_DATA & 0xffffffff), %rax
+ mov $(ASM_STUB_DATA & 0xffffffff), %rax
or %rax, %rbx
/* load pointer to first operation */
mov %rbx, %rsp
diff --git a/arch/um/sys-x86_64/stub_segv.c b/arch/um/sys-x86_64/stub_segv.c
index 652fa34c2cd3..3afb590f0072 100644
--- a/arch/um/sys-x86_64/stub_segv.c
+++ b/arch/um/sys-x86_64/stub_segv.c
@@ -6,6 +6,7 @@
#include <stddef.h>
#include <signal.h>
#include <asm/unistd.h>
+#include "as-layout.h"
#include "uml-config.h"
#include "sysdep/sigcontext.h"
#include "sysdep/faultinfo.h"
@@ -33,7 +34,7 @@ stub_segv_handler(int sig)
int pid;
__asm__ __volatile__("movq %%rdx, %0" : "=g" (uc) :);
- GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA),
+ GET_FAULTINFO_FROM_SC(*((struct faultinfo *) STUB_DATA),
&uc->uc_mcontext);
pid = stub_syscall0(__NR_getpid);
diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c
index b3f6350cac44..86f6b18410ee 100644
--- a/arch/um/sys-x86_64/syscalls.c
+++ b/arch/um/sys-x86_64/syscalls.c
@@ -1,70 +1,36 @@
/*
+ * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Copyright 2003 PathScale, Inc.
*
* Licensed under the GPL
*/
#include "linux/linkage.h"
-#include "linux/slab.h"
-#include "linux/shm.h"
-#include "linux/utsname.h"
#include "linux/personality.h"
-#include "asm/uaccess.h"
-#define __FRAME_OFFSETS
-#include "asm/ptrace.h"
-#include "asm/unistd.h"
+#include "linux/utsname.h"
#include "asm/prctl.h" /* XXX This should get the constants from libc */
-#include "choose-mode.h"
-#include "kern.h"
+#include "asm/uaccess.h"
#include "os.h"
asmlinkage long sys_uname64(struct new_utsname __user * name)
{
int err;
+
down_read(&uts_sem);
err = copy_to_user(name, utsname(), sizeof (*name));
up_read(&uts_sem);
+
if (personality(current->personality) == PER_LINUX32)
err |= copy_to_user(&name->machine, "i686", 5);
- return err ? -EFAULT : 0;
-}
-
-#ifdef CONFIG_MODE_TT
-extern long arch_prctl(int code, unsigned long addr);
-
-static long arch_prctl_tt(int code, unsigned long addr)
-{
- unsigned long tmp;
- long ret;
-
- switch(code){
- case ARCH_SET_GS:
- case ARCH_SET_FS:
- ret = arch_prctl(code, addr);
- break;
- case ARCH_GET_FS:
- case ARCH_GET_GS:
- ret = arch_prctl(code, (unsigned long) &tmp);
- if(!ret)
- ret = put_user(tmp, (long __user *)addr);
- break;
- default:
- ret = -EINVAL;
- break;
- }
- return(ret);
+ return err ? -EFAULT : 0;
}
-#endif
-
-#ifdef CONFIG_MODE_SKAS
-long arch_prctl_skas(struct task_struct *task, int code,
- unsigned long __user *addr)
+long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr)
{
- unsigned long *ptr = addr, tmp;
+ unsigned long *ptr = addr, tmp;
long ret;
- int pid = task->mm->context.skas.id.u.pid;
+ int pid = task->mm->context.id.u.pid;
/*
* With ARCH_SET_FS (and ARCH_SET_GS is treated similarly to
@@ -79,52 +45,50 @@ long arch_prctl_skas(struct task_struct *task, int code,
* arch_prctl is run on the host, then the registers are read
* back.
*/
- switch(code){
+ switch (code) {
case ARCH_SET_FS:
case ARCH_SET_GS:
- restore_registers(pid, &current->thread.regs.regs);
- break;
- case ARCH_GET_FS:
- case ARCH_GET_GS:
- /*
- * With these two, we read to a local pointer and
- * put_user it to the userspace pointer that we were
- * given. If addr isn't valid (because it hasn't been
- * faulted in or is just bogus), we want put_user to
- * fault it in (or return -EFAULT) instead of having
- * the host return -EFAULT.
- */
- ptr = &tmp;
- }
+ restore_registers(pid, &current->thread.regs.regs);
+ break;
+ case ARCH_GET_FS:
+ case ARCH_GET_GS:
+ /*
+ * With these two, we read to a local pointer and
+ * put_user it to the userspace pointer that we were
+ * given. If addr isn't valid (because it hasn't been
+ * faulted in or is just bogus), we want put_user to
+ * fault it in (or return -EFAULT) instead of having
+ * the host return -EFAULT.
+ */
+ ptr = &tmp;
+ }
- ret = os_arch_prctl(pid, code, ptr);
- if(ret)
- return ret;
+ ret = os_arch_prctl(pid, code, ptr);
+ if (ret)
+ return ret;
- switch(code){
+ switch (code) {
case ARCH_SET_FS:
current->thread.arch.fs = (unsigned long) ptr;
save_registers(pid, &current->thread.regs.regs);
break;
case ARCH_SET_GS:
- save_registers(pid, &current->thread.regs.regs);
+ save_registers(pid, &current->thread.regs.regs);
break;
case ARCH_GET_FS:
ret = put_user(tmp, addr);
- break;
+ break;
case ARCH_GET_GS:
ret = put_user(tmp, addr);
- break;
+ break;
}
return ret;
}
-#endif
long sys_arch_prctl(int code, unsigned long addr)
{
- return CHOOSE_MODE_PROC(arch_prctl_tt, arch_prctl_skas, current, code,
- (unsigned long __user *) addr);
+ return arch_prctl(current, code, (unsigned long __user *) addr);
}
long sys_clone(unsigned long clone_flags, unsigned long newsp,
@@ -141,10 +105,10 @@ long sys_clone(unsigned long clone_flags, unsigned long newsp,
return ret;
}
-void arch_switch_to_skas(struct task_struct *from, struct task_struct *to)
+void arch_switch_to(struct task_struct *from, struct task_struct *to)
{
- if((to->thread.arch.fs == 0) || (to->mm == NULL))
- return;
+ if ((to->thread.arch.fs == 0) || (to->mm == NULL))
+ return;
- arch_prctl_skas(to, ARCH_SET_FS, (void __user *) to->thread.arch.fs);
+ arch_prctl(to, ARCH_SET_FS, (void __user *) to->thread.arch.fs);
}
diff --git a/arch/um/sys-x86_64/sysrq.c b/arch/um/sys-x86_64/sysrq.c
index ce3e07fcf283..765444031819 100644
--- a/arch/um/sys-x86_64/sysrq.c
+++ b/arch/um/sys-x86_64/sysrq.c
@@ -15,8 +15,8 @@ void __show_regs(struct pt_regs * regs)
{
printk("\n");
print_modules();
- printk("Pid: %d, comm: %.20s %s %s\n",
- current->pid, current->comm, print_tainted(), init_utsname()->release);
+ printk("Pid: %d, comm: %.20s %s %s\n", task_pid_nr(current),
+ current->comm, print_tainted(), init_utsname()->release);
printk("RIP: %04lx:[<%016lx>] ", PT_REGS_CS(regs) & 0xffff,
PT_REGS_RIP(regs));
printk("\nRSP: %016lx EFLAGS: %08lx\n", PT_REGS_RSP(regs),
diff --git a/arch/um/sys-x86_64/tls.c b/arch/um/sys-x86_64/tls.c
index febbc94be25f..f7ba46200ecd 100644
--- a/arch/um/sys-x86_64/tls.c
+++ b/arch/um/sys-x86_64/tls.c
@@ -11,7 +11,7 @@ int arch_copy_tls(struct task_struct *t)
* (which is argument 5, child_tid, of clone) so it can be set
* during context switches.
*/
- t->thread.arch.fs = t->thread.regs.regs.skas.regs[R8 / sizeof(long)];
+ t->thread.arch.fs = t->thread.regs.regs.gp[R8 / sizeof(long)];
- return 0;
+ return 0;
}
diff --git a/arch/um/sys-x86_64/unmap.c b/arch/um/sys-x86_64/unmap.c
deleted file mode 100644
index f4a4bffd8a18..000000000000
--- a/arch/um/sys-x86_64/unmap.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <linux/mman.h>
-#include <asm/unistd.h>
-
-static int errno;
-
-static inline _syscall2(int,munmap,void *,start,size_t,len)
-static inline _syscall6(void *,mmap,void *,addr,size_t,len,int,prot,int,flags,int,fd,off_t,offset)
-int switcheroo(int fd, int prot, void *from, void *to, int size)
-{
- if(munmap(to, size) < 0){
- return(-1);
- }
- if(mmap(to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) == (void*) -1){
- return(-1);
- }
- if(munmap(from, size) < 0){
- return(-1);
- }
- return(0);
-}
diff --git a/arch/um/sys-x86_64/user-offsets.c b/arch/um/sys-x86_64/user-offsets.c
index 0d5fd764c21f..f1ef2a8dfbc6 100644
--- a/arch/um/sys-x86_64/user-offsets.c
+++ b/arch/um/sys-x86_64/user-offsets.c
@@ -3,17 +3,10 @@
#include <signal.h>
#include <sys/poll.h>
#include <sys/mman.h>
+#include <sys/user.h>
#define __FRAME_OFFSETS
#include <asm/ptrace.h>
#include <asm/types.h>
-/* For some reason, x86_64 defines u64 and u32 only in <pci/types.h>, which I
- * refuse to include here, even though they're used throughout the headers.
- * These are used in asm/user.h, and that include can't be avoided because of
- * the sizeof(struct user_regs_struct) below.
- */
-typedef __u64 u64;
-typedef __u32 u32;
-#include <asm/user.h>
#define DEFINE(sym, val) \
asm volatile("\n->" #sym " %0 " #val : : "i" (val))
diff --git a/arch/v850/Kconfig b/arch/v850/Kconfig
index ace479ab273f..b6a50b8b38de 100644
--- a/arch/v850/Kconfig
+++ b/arch/v850/Kconfig
@@ -331,6 +331,8 @@ source "sound/Kconfig"
source "drivers/usb/Kconfig"
+source "kernel/Kconfig.instrumentation"
+
source "arch/v850/Kconfig.debug"
source "security/Kconfig"
diff --git a/arch/v850/Makefile b/arch/v850/Makefile
index 8be9aacb20a7..8b629df0029a 100644
--- a/arch/v850/Makefile
+++ b/arch/v850/Makefile
@@ -16,11 +16,11 @@
arch_dir = arch/v850
-CFLAGS += -mv850e
+KBUILD_CFLAGS += -mv850e
# r16 is a fixed pointer to the current task
-CFLAGS += -ffixed-r16 -mno-prolog-function
-CFLAGS += -fno-builtin
-CFLAGS += -D__linux__ -DUTS_SYSNAME=\"uClinux\"
+KBUILD_CFLAGS += -ffixed-r16 -mno-prolog-function
+KBUILD_CFLAGS += -fno-builtin
+KBUILD_CFLAGS += -D__linux__ -DUTS_SYSNAME=\"uClinux\"
# By default, build a kernel that runs on the gdb v850 simulator.
KBUILD_DEFCONFIG := sim_defconfig
diff --git a/arch/v850/kernel/fpga85e2c.c b/arch/v850/kernel/fpga85e2c.c
index 5c4923558a75..ab9cf16a85c8 100644
--- a/arch/v850/kernel/fpga85e2c.c
+++ b/arch/v850/kernel/fpga85e2c.c
@@ -160,5 +160,8 @@ static void make_reg_snap (int irq, void *dummy, struct pt_regs *regs)
static int reg_snap_dev_id;
static struct irqaction reg_snap_action = {
- make_reg_snap, 0, CPU_MASK_NONE, "reg_snap", &reg_snap_dev_id, 0
+ .handler = make_reg_snap,
+ .mask = CPU_MASK_NONE,
+ .name = "reg_snap",
+ .dev_id = &reg_snap_dev_id,
};
diff --git a/arch/v850/kernel/me2.c b/arch/v850/kernel/me2.c
index 38be5c194f6b..007115dc9ce0 100644
--- a/arch/v850/kernel/me2.c
+++ b/arch/v850/kernel/me2.c
@@ -58,13 +58,13 @@ void __init me2_init_irqs (void)
void me2_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud)
{
if (chan == 0) {
- /* Specify that the relevent pins on the chip should do
+ /* Specify that the relevant pins on the chip should do
serial I/O, not direct I/O. */
ME2_PORT1_PMC |= 0xC;
/* Specify that we're using the UART, not the CSI device. */
ME2_PORT1_PFC |= 0xC;
} else if (chan == 1) {
- /* Specify that the relevent pins on the chip should do
+ /* Specify that the relevant pins on the chip should do
serial I/O, not direct I/O. */
ME2_PORT2_PMC |= 0x6;
/* Specify that we're using the UART, not the CSI device. */
diff --git a/arch/v850/kernel/rte_mb_a_pci.c b/arch/v850/kernel/rte_mb_a_pci.c
index 35a4bd5515cb..7165478824e7 100644
--- a/arch/v850/kernel/rte_mb_a_pci.c
+++ b/arch/v850/kernel/rte_mb_a_pci.c
@@ -179,7 +179,7 @@ static int __devinit pcibios_init (void)
default uses. */
/* Significant address bits used for decoding PCI GCS5 space
- accessess. */
+ accesses. */
MB_A_PCI_DMRR = ~(MB_A_PCI_MEM_SIZE - 1);
/* I don't understand this, but the SolutionGear example code
@@ -775,7 +775,7 @@ pci_alloc_consistent (struct pci_dev *pdev, size_t size, dma_addr_t *dma_addr)
/* Free and unmap a consistent DMA buffer. CPU_ADDR and DMA_ADDR must
be values that were returned from pci_alloc_consistent. SIZE must be
the same as what as passed into pci_alloc_consistent. References to
- the memory and mappings assosciated with CPU_ADDR or DMA_ADDR past
+ the memory and mappings associated with CPU_ADDR or DMA_ADDR past
this call are illegal. */
void
pci_free_consistent (struct pci_dev *pdev, size_t size, void *cpu_addr,
diff --git a/arch/v850/kernel/syscalls.c b/arch/v850/kernel/syscalls.c
index f9f00ccf5324..0a4df4d6e05f 100644
--- a/arch/v850/kernel/syscalls.c
+++ b/arch/v850/kernel/syscalls.c
@@ -30,7 +30,6 @@
#include <linux/file.h>
#include <asm/uaccess.h>
-#include <asm/ipc.h>
#include <asm/semaphore.h>
#include <asm/unistd.h>
diff --git a/arch/v850/kernel/time.c b/arch/v850/kernel/time.c
index f0905b03523b..d810c93fe665 100644
--- a/arch/v850/kernel/time.c
+++ b/arch/v850/kernel/time.c
@@ -92,12 +92,11 @@ static irqreturn_t timer_interrupt (int irq, void *dummy, struct pt_regs *regs)
static int timer_dev_id;
static struct irqaction timer_irqaction = {
- timer_interrupt,
- IRQF_DISABLED,
- CPU_MASK_NONE,
- "timer",
- &timer_dev_id,
- NULL
+ .handler = timer_interrupt,
+ .flags = IRQF_DISABLED,
+ .mask = CPU_MASK_NONE,
+ .name = "timer",
+ .dev_id = &timer_dev_id,
};
void time_init (void)
diff --git a/arch/i386/Kconfig b/arch/x86/Kconfig
index bf9aafad4978..1eb59971af5d 100644
--- a/arch/i386/Kconfig
+++ b/arch/x86/Kconfig
@@ -1,18 +1,24 @@
-#
-# For a description of the syntax of this configuration file,
-# see Documentation/kbuild/kconfig-language.txt.
-#
+# x86 configuration
+mainmenu "Linux Kernel Configuration for x86"
-mainmenu "Linux Kernel Configuration"
+# Select 32 or 64 bit
+config 64BIT
+ bool "64-bit kernel"
+ default n
+ help
+ Say yes to build a 64-bit kernel - formerly known as x86_64
+ Say no to build a 32-bit kernel - formerly known as i386
config X86_32
+ def_bool !64BIT
+
+config X86_64
+ def_bool 64BIT
+
+### Arch settings
+config X86
bool
default y
- help
- This is Linux's home port. Linux was originally native to the Intel
- 386, and runs on all the later x86 processors including the Intel
- 486, 586, Pentiums, and various instruction-set-compatible chips by
- AMD, Cyrix, and others.
config GENERIC_TIME
bool
@@ -33,7 +39,7 @@ config GENERIC_CLOCKEVENTS
config GENERIC_CLOCKEVENTS_BROADCAST
bool
default y
- depends on X86_LOCAL_APIC
+ depends on X86_64 || (X86_32 && X86_LOCAL_APIC)
config LOCKDEP_SUPPORT
bool
@@ -47,10 +53,6 @@ config SEMAPHORE_SLEEPERS
bool
default y
-config X86
- bool
- default y
-
config MMU
bool
default y
@@ -61,7 +63,7 @@ config ZONE_DMA
config QUICKLIST
bool
- default y
+ default X86_32
config SBUS
bool
@@ -91,6 +93,76 @@ config DMI
bool
default y
+config RWSEM_GENERIC_SPINLOCK
+ def_bool !X86_XADD
+
+config RWSEM_XCHGADD_ALGORITHM
+ def_bool X86_XADD
+
+config ARCH_HAS_ILOG2_U32
+ def_bool n
+
+config ARCH_HAS_ILOG2_U64
+ def_bool n
+
+config GENERIC_CALIBRATE_DELAY
+ def_bool y
+
+config GENERIC_TIME_VSYSCALL
+ bool
+ default X86_64
+
+
+
+
+
+config ZONE_DMA32
+ bool
+ default X86_64
+
+config ARCH_POPULATES_NODE_MAP
+ def_bool y
+
+config AUDIT_ARCH
+ bool
+ default X86_64
+
+# Use the generic interrupt handling code in kernel/irq/:
+config GENERIC_HARDIRQS
+ bool
+ default y
+
+config GENERIC_IRQ_PROBE
+ bool
+ default y
+
+config GENERIC_PENDING_IRQ
+ bool
+ depends on GENERIC_HARDIRQS && SMP
+ default y
+
+config X86_SMP
+ bool
+ depends on X86_32 && SMP && !X86_VOYAGER
+ default y
+
+config X86_HT
+ bool
+ depends on SMP && !(X86_VISWS || X86_VOYAGER || MK8)
+ default y
+
+config X86_BIOS_REBOOT
+ bool
+ depends on X86_32 && !(X86_VISWS || X86_VOYAGER)
+ default y
+
+config X86_TRAMPOLINE
+ bool
+ depends on X86_SMP || (X86_VOYAGER && SMP)
+ default y
+
+config KTIME_SCALAR
+ def_bool X86_32
source "init/Kconfig"
menu "Processor type and features"
@@ -137,6 +209,7 @@ config X86_PC
config X86_ELAN
bool "AMD Elan"
+ depends on X86_32
help
Select this for an AMD Elan processor.
@@ -146,6 +219,8 @@ config X86_ELAN
config X86_VOYAGER
bool "Voyager (NCR)"
+ depends on X86_32
+ select SMP if !BROKEN
help
Voyager is an MCA-based 32-way capable SMP architecture proprietary
to NCR Corp. Machine classes 345x/35xx/4100/51xx are Voyager-based.
@@ -159,6 +234,7 @@ config X86_NUMAQ
bool "NUMAQ (IBM/Sequent)"
select SMP
select NUMA
+ depends on X86_32
help
This option is used for getting Linux to run on a (IBM/Sequent) NUMA
multiquad box. This changes the way that processors are bootstrapped,
@@ -168,7 +244,7 @@ config X86_NUMAQ
config X86_SUMMIT
bool "Summit/EXA (IBM x440)"
- depends on SMP
+ depends on X86_32 && SMP
help
This option is needed for IBM systems that use the Summit/EXA chipset.
In particular, it is needed for the x440.
@@ -178,7 +254,7 @@ config X86_SUMMIT
config X86_BIGSMP
bool "Support for other sub-arch SMP systems with more than 8 CPUs"
- depends on SMP
+ depends on X86_32 && SMP
help
This option is needed for the systems that have more than 8 CPUs
and if the system is not of any sub-arch type above.
@@ -187,6 +263,7 @@ config X86_BIGSMP
config X86_VISWS
bool "SGI 320/540 (Visual Workstation)"
+ depends on X86_32
help
The SGI Visual Workstation series is an IA32-based workstation
based on SGI systems chips with some legacy PC hardware attached.
@@ -198,6 +275,7 @@ config X86_VISWS
config X86_GENERICARCH
bool "Generic architecture (Summit, bigsmp, ES7000, default)"
+ depends on X86_32
help
This option compiles in the Summit, bigsmp, ES7000, default subarchitectures.
It is intended for a generic binary kernel.
@@ -205,18 +283,27 @@ config X86_GENERICARCH
config X86_ES7000
bool "Support for Unisys ES7000 IA32 series"
- depends on SMP
+ depends on X86_32 && SMP
help
Support for Unisys ES7000 systems. Say 'Y' here if this kernel is
supposed to run on an IA32-based Unisys ES7000 system.
Only choose this option if you have such a system, otherwise you
should say N here.
+config X86_VSMP
+ bool "Support for ScaleMP vSMP"
+ depends on X86_64 && PCI
+ help
+ Support for ScaleMP vSMP systems. Say 'Y' here if this kernel is
+ supposed to run on these EM64T-based machines. Only choose this option
+ if you have one of these machines.
+
endchoice
config SCHED_NO_NO_OMIT_FRAME_POINTER
bool "Single-depth WCHAN output"
default y
+ depends on X86_32
help
Calculate simpler /proc/<PID>/wchan values. If this option
is disabled then wchan values will recurse back to the
@@ -226,32 +313,45 @@ config SCHED_NO_NO_OMIT_FRAME_POINTER
If in doubt, say "Y".
config PARAVIRT
- bool "Paravirtualization support (EXPERIMENTAL)"
- depends on EXPERIMENTAL
- depends on !(X86_VISWS || X86_VOYAGER)
+ bool
+ depends on X86_32 && !(X86_VISWS || X86_VOYAGER)
+ help
+ This changes the kernel so it can modify itself when it is run
+ under a hypervisor, potentially improving performance significantly
+ over full virtualization. However, when run without a hypervisor
+ the kernel is theoretically slower and slightly larger.
+
+menuconfig PARAVIRT_GUEST
+ bool "Paravirtualized guest support"
+ depends on X86_32
help
- Paravirtualization is a way of running multiple instances of
- Linux on the same machine, under a hypervisor. This option
- changes the kernel so it can modify itself when it is run
- under a hypervisor, improving performance significantly.
- However, when run without a hypervisor the kernel is
- theoretically slower. If in doubt, say N.
+ Say Y here to get to see options related to running Linux under
+ various hypervisors. This option alone does not add any kernel code.
+
+ If you say N, all options in this submenu will be skipped and disabled.
+
+if PARAVIRT_GUEST
source "arch/x86/xen/Kconfig"
config VMI
- bool "VMI Paravirt-ops support"
- depends on PARAVIRT
+ bool "VMI Guest support"
+ select PARAVIRT
+ depends on !(X86_VISWS || X86_VOYAGER)
help
VMI provides a paravirtualized interface to the VMware ESX server
(it could be used by other hypervisors in theory too, but is not
at the moment), by linking the kernel to a GPL-ed ROM module
provided by the hypervisor.
+source "arch/x86/lguest/Kconfig"
+
+endif
+
config ACPI_SRAT
bool
default y
- depends on ACPI && NUMA && (X86_SUMMIT || X86_GENERICARCH)
+ depends on X86_32 && ACPI && NUMA && (X86_SUMMIT || X86_GENERICARCH)
select ACPI_NUMA
config HAVE_ARCH_PARSE_SRAT
@@ -262,36 +362,104 @@ config HAVE_ARCH_PARSE_SRAT
config X86_SUMMIT_NUMA
bool
default y
- depends on NUMA && (X86_SUMMIT || X86_GENERICARCH)
+ depends on X86_32 && NUMA && (X86_SUMMIT || X86_GENERICARCH)
config X86_CYCLONE_TIMER
bool
default y
- depends on X86_SUMMIT || X86_GENERICARCH
+ depends on X86_32 && X86_SUMMIT || X86_GENERICARCH
config ES7000_CLUSTERED_APIC
bool
default y
depends on SMP && X86_ES7000 && MPENTIUMIII
-source "arch/i386/Kconfig.cpu"
+source "arch/x86/Kconfig.cpu"
config HPET_TIMER
- bool "HPET Timer Support"
+ bool
+ prompt "HPET Timer Support" if X86_32
+ default X86_64
help
- This enables the use of the HPET for the kernel's internal timer.
- HPET is the next generation timer replacing legacy 8254s.
- You can safely choose Y here. However, HPET will only be
- activated if the platform and the BIOS support this feature.
- Otherwise the 8254 will be used for timing services.
+ Use the IA-PC HPET (High Precision Event Timer) to manage
+ time in preference to the PIT and RTC, if a HPET is
+ present.
+ HPET is the next generation timer replacing legacy 8254s.
+ The HPET provides a stable time base on SMP
+ systems, unlike the TSC, but it is more expensive to access,
+ as it is off-chip. You can find the HPET spec at
+ <http://www.intel.com/hardwaredesign/hpetspec.htm>.
+
+ You can safely choose Y here. However, HPET will only be
+ activated if the platform and the BIOS support this feature.
+ Otherwise the 8254 will be used for timing services.
- Choose N to continue using the legacy 8254 timer.
+ Choose N to continue using the legacy 8254 timer.
config HPET_EMULATE_RTC
bool
depends on HPET_TIMER && RTC=y
default y
+# Mark as embedded because too many people got it wrong.
+# The code disables itself when not needed.
+config GART_IOMMU
+ bool "GART IOMMU support" if EMBEDDED
+ default y
+ select SWIOTLB
+ select AGP
+ depends on X86_64 && PCI
+ help
+ Support for full DMA access of devices with 32bit memory access only
+ on systems with more than 3GB. This is usually needed for USB,
+ sound, many IDE/SATA chipsets and some other devices.
+ Provides a driver for the AMD Athlon64/Opteron/Turion/Sempron GART
+ based hardware IOMMU and a software bounce buffer based IOMMU used
+ on Intel systems and as fallback.
+ The code is only active when needed (enough memory and limited
+ device) unless CONFIG_IOMMU_DEBUG or iommu=force is specified
+ too.
+
+config CALGARY_IOMMU
+ bool "IBM Calgary IOMMU support"
+ select SWIOTLB
+ depends on X86_64 && PCI && EXPERIMENTAL
+ help
+ Support for hardware IOMMUs in IBM's xSeries x366 and x460
+ systems. Needed to run systems with more than 3GB of memory
+ properly with 32-bit PCI devices that do not support DAC
+ (Double Address Cycle). Calgary also supports bus level
+ isolation, where all DMAs pass through the IOMMU. This
+ prevents them from going anywhere except their intended
+ destination. This catches hard-to-find kernel bugs and
+ mis-behaving drivers and devices that do not use the DMA-API
+ properly to set up their DMA buffers. The IOMMU can be
+ turned off at boot time with the iommu=off parameter.
+ Normally the kernel will make the right choice by itself.
+ If unsure, say Y.
+
+config CALGARY_IOMMU_ENABLED_BY_DEFAULT
+ bool "Should Calgary be enabled by default?"
+ default y
+ depends on CALGARY_IOMMU
+ help
+ Should Calgary be enabled by default? if you choose 'y', Calgary
+ will be used (if it exists). If you choose 'n', Calgary will not be
+ used even if it exists. If you choose 'n' and would like to use
+ Calgary anyway, pass 'iommu=calgary' on the kernel command line.
+ If unsure, say Y.
+
+# need this always selected by IOMMU for the VIA workaround
+config SWIOTLB
+ bool
+ help
+ Support for software bounce buffers used on x86-64 systems
+ which don't have a hardware IOMMU (e.g. the current generation
+ of Intel's x86-64 CPUs). Using this PCI devices which can only
+ access 32-bits of memory can be used on systems with more than
+ 3 GB of memory. If unsure, say Y.
+
+
config NR_CPUS
int "Maximum number of CPUs (2-255)"
range 2 255
@@ -308,7 +476,7 @@ config NR_CPUS
config SCHED_SMT
bool "SMT (Hyperthreading) scheduler support"
- depends on X86_HT
+ depends on (X86_64 && SMP) || (X86_32 && X86_HT)
help
SMT scheduler support improves the CPU scheduler's decision making
when dealing with Intel Pentium 4 chips with HyperThreading at a
@@ -317,7 +485,7 @@ config SCHED_SMT
config SCHED_MC
bool "Multi-core scheduler support"
- depends on X86_HT
+ depends on (X86_64 && SMP) || (X86_32 && X86_HT)
default y
help
Multi-core scheduler support improves the CPU scheduler's decision
@@ -328,7 +496,7 @@ source "kernel/Kconfig.preempt"
config X86_UP_APIC
bool "Local APIC support on uniprocessors"
- depends on !SMP && !(X86_VISWS || X86_VOYAGER || X86_GENERICARCH)
+ depends on X86_32 && !SMP && !(X86_VISWS || X86_VOYAGER || X86_GENERICARCH)
help
A local APIC (Advanced Programmable Interrupt Controller) is an
integrated interrupt controller in the CPU. If you have a single-CPU
@@ -353,17 +521,17 @@ config X86_UP_IOAPIC
config X86_LOCAL_APIC
bool
- depends on X86_UP_APIC || ((X86_VISWS || SMP) && !X86_VOYAGER) || X86_GENERICARCH
+ depends on X86_64 || (X86_32 && (X86_UP_APIC || ((X86_VISWS || SMP) && !X86_VOYAGER) || X86_GENERICARCH))
default y
config X86_IO_APIC
bool
- depends on X86_UP_IOAPIC || (SMP && !(X86_VISWS || X86_VOYAGER)) || X86_GENERICARCH
+ depends on X86_64 || (X86_32 && (X86_UP_IOAPIC || (SMP && !(X86_VISWS || X86_VOYAGER)) || X86_GENERICARCH))
default y
config X86_VISWS_APIC
bool
- depends on X86_VISWS
+ depends on X86_32 && X86_VISWS
default y
config X86_MCE
@@ -383,29 +551,46 @@ config X86_MCE
to disable it. MCE support simply ignores non-MCE processors like
the 386 and 486, so nearly everyone can say Y here.
+config X86_MCE_INTEL
+ bool "Intel MCE features"
+ depends on X86_64 && X86_MCE && X86_LOCAL_APIC
+ default y
+ help
+ Additional support for intel specific MCE features such as
+ the thermal monitor.
+
+config X86_MCE_AMD
+ bool "AMD MCE features"
+ depends on X86_64 && X86_MCE && X86_LOCAL_APIC
+ default y
+ help
+ Additional support for AMD specific MCE features such as
+ the DRAM Error Threshold.
+
config X86_MCE_NONFATAL
tristate "Check for non-fatal errors on AMD Athlon/Duron / Intel Pentium 4"
- depends on X86_MCE
+ depends on X86_32 && X86_MCE
help
Enabling this feature starts a timer that triggers every 5 seconds which
will look at the machine check registers to see if anything happened.
Non-fatal problems automatically get corrected (but still logged).
Disable this if you don't want to see these messages.
- Seeing the messages this option prints out may be indicative of dying hardware,
+ Seeing the messages this option prints out may be indicative of dying
or out-of-spec (ie, overclocked) hardware.
This option only does something on certain CPUs.
(AMD Athlon/Duron and Intel Pentium 4)
config X86_MCE_P4THERMAL
bool "check for P4 thermal throttling interrupt."
- depends on X86_MCE && (X86_UP_APIC || SMP) && !X86_VISWS
+ depends on X86_32 && X86_MCE && (X86_UP_APIC || SMP) && !X86_VISWS
help
Enabling this feature will cause a message to be printed when the P4
enters thermal throttling.
config VM86
- default y
bool "Enable VM86 support" if EMBEDDED
+ default y
+ depends on X86_32
help
This option is required by programs like DOSEMU to run 16-bit legacy
code on X86 processors. It also may be needed by software like
@@ -414,6 +599,7 @@ config VM86
config TOSHIBA
tristate "Toshiba Laptop support"
+ depends on X86_32
---help---
This adds a driver to safely access the System Management Mode of
the CPU on Toshiba portables with a genuine Toshiba BIOS. It does
@@ -429,6 +615,7 @@ config TOSHIBA
config I8K
tristate "Dell laptop support"
+ depends on X86_32
---help---
This adds a driver to safely access the System Management Mode
of the CPU on the Dell Inspiron 8000. The System Management Mode
@@ -449,7 +636,7 @@ config I8K
config X86_REBOOTFIXUPS
bool "Enable X86 board specific fixups for reboot"
- depends on X86
+ depends on X86_32 && X86
default n
---help---
This enables chipset and/or board specific fixups to be done
@@ -504,12 +691,11 @@ config X86_CPUID
with major 203 and minors 0 to 31 for /dev/cpu/0/cpuid to
/dev/cpu/31/cpuid.
-source "drivers/firmware/Kconfig"
-
choice
prompt "High Memory Support"
default HIGHMEM4G if !X86_NUMAQ
default HIGHMEM64G if X86_NUMAQ
+ depends on X86_32
config NOHIGHMEM
bool "off"
@@ -569,6 +755,7 @@ choice
depends on EXPERIMENTAL
prompt "Memory split" if EMBEDDED
default VMSPLIT_3G
+ depends on X86_32
help
Select the desired split between kernel and user memory.
@@ -606,16 +793,17 @@ config PAGE_OFFSET
default 0x78000000 if VMSPLIT_2G_OPT
default 0x40000000 if VMSPLIT_1G
default 0xC0000000
+ depends on X86_32
config HIGHMEM
bool
- depends on HIGHMEM64G || HIGHMEM4G
+ depends on X86_32 && (HIGHMEM64G || HIGHMEM4G)
default y
config X86_PAE
bool "PAE (Physical Address Extension) Support"
default n
- depends on !HIGHMEM4G
+ depends on X86_32 && !HIGHMEM4G
select RESOURCES_64BIT
help
PAE is required for NX support, and furthermore enables
@@ -626,46 +814,82 @@ config X86_PAE
# Common NUMA Features
config NUMA
bool "Numa Memory Allocation and Scheduler Support (EXPERIMENTAL)"
- depends on SMP && HIGHMEM64G && (X86_NUMAQ || (X86_SUMMIT || X86_GENERICARCH) && ACPI) && EXPERIMENTAL
+ depends on SMP
+ depends on X86_64 || (X86_32 && HIGHMEM64G && (X86_NUMAQ || (X86_SUMMIT || X86_GENERICARCH) && ACPI) && EXPERIMENTAL)
default n if X86_PC
default y if (X86_NUMAQ || X86_SUMMIT)
help
- NUMA support for i386. This is currently high experimental
- and should be only used for kernel development. It might also
- cause boot failures.
+ Enable NUMA (Non Uniform Memory Access) support.
+ The kernel will try to allocate memory used by a CPU on the
+ local memory controller of the CPU and add some more
+ NUMA awareness to the kernel.
+
+ For i386 this is currently highly experimental and should be only
+ used for kernel development. It might also cause boot failures.
+ For x86_64 this is recommended on all multiprocessor Opteron systems.
+ If the system is EM64T, you should say N unless your system is
+ EM64T NUMA.
comment "NUMA (Summit) requires SMP, 64GB highmem support, ACPI"
- depends on X86_SUMMIT && (!HIGHMEM64G || !ACPI)
+ depends on X86_32 && X86_SUMMIT && (!HIGHMEM64G || !ACPI)
+
+config K8_NUMA
+ bool "Old style AMD Opteron NUMA detection"
+ depends on X86_64 && NUMA && PCI
+ default y
+ help
+ Enable K8 NUMA node topology detection. You should say Y here if
+ you have a multi processor AMD K8 system. This uses an old
+ method to read the NUMA configuration directly from the builtin
+ Northbridge of Opteron. It is recommended to use X86_64_ACPI_NUMA
+ instead, which also takes priority if both are compiled in.
+
+config X86_64_ACPI_NUMA
+ bool "ACPI NUMA detection"
+ depends on X86_64 && NUMA && ACPI && PCI
+ select ACPI_NUMA
+ default y
+ help
+ Enable ACPI SRAT based node topology detection.
+
+config NUMA_EMU
+ bool "NUMA emulation"
+ depends on X86_64 && NUMA
+ help
+ Enable NUMA emulation. A flat machine will be split
+ into virtual nodes when booted with "numa=fake=N", where N is the
+ number of nodes. This is only useful for debugging.
config NODES_SHIFT
int
+ default "6" if X86_64
default "4" if X86_NUMAQ
default "3"
depends on NEED_MULTIPLE_NODES
config HAVE_ARCH_BOOTMEM_NODE
bool
- depends on NUMA
+ depends on X86_32 && NUMA
default y
config ARCH_HAVE_MEMORY_PRESENT
bool
- depends on DISCONTIGMEM
+ depends on X86_32 && DISCONTIGMEM
default y
config NEED_NODE_MEMMAP_SIZE
bool
- depends on DISCONTIGMEM || SPARSEMEM
+ depends on X86_32 && (DISCONTIGMEM || SPARSEMEM)
default y
config HAVE_ARCH_ALLOC_REMAP
bool
- depends on NUMA
+ depends on X86_32 && NUMA
default y
config ARCH_FLATMEM_ENABLE
def_bool y
- depends on (ARCH_SELECT_MEMORY_MODEL && X86_PC)
+ depends on (X86_32 && ARCH_SELECT_MEMORY_MODEL && X86_PC) || (X86_64 && !NUMA)
config ARCH_DISCONTIGMEM_ENABLE
def_bool y
@@ -677,21 +901,23 @@ config ARCH_DISCONTIGMEM_DEFAULT
config ARCH_SPARSEMEM_ENABLE
def_bool y
- depends on (NUMA || (X86_PC && EXPERIMENTAL))
- select SPARSEMEM_STATIC
+ depends on NUMA || (EXPERIMENTAL && (X86_PC || X86_64))
+ select SPARSEMEM_STATIC if X86_32
+ select SPARSEMEM_VMEMMAP_ENABLE if X86_64
config ARCH_SELECT_MEMORY_MODEL
def_bool y
- depends on ARCH_SPARSEMEM_ENABLE
+ depends on X86_32 && ARCH_SPARSEMEM_ENABLE
-config ARCH_POPULATES_NODE_MAP
- def_bool y
+config ARCH_MEMORY_PROBE
+ def_bool X86_64
+ depends on MEMORY_HOTPLUG
source "mm/Kconfig"
config HIGHPTE
bool "Allocate 3rd-level pagetables from highmem"
- depends on HIGHMEM4G || HIGHMEM64G
+ depends on X86_32 && (HIGHMEM4G || HIGHMEM64G)
help
The VM uses one page table entry for each page of physical memory.
For systems with a lot of RAM, this can be wasteful of precious
@@ -699,7 +925,8 @@ config HIGHPTE
entries in high memory.
config MATH_EMULATION
- bool "Math emulation"
+ bool
+ prompt "Math emulation" if X86_32
---help---
Linux can emulate a math coprocessor (used for floating point
operations) if you don't have one. 486DX and Pentium processors have
@@ -759,7 +986,7 @@ config MTRR
config EFI
bool "Boot from EFI support"
- depends on ACPI
+ depends on X86_32 && ACPI
default n
---help---
This enables the kernel to boot on EFI platforms using
@@ -776,18 +1003,18 @@ config EFI
kernel should continue to boot on existing non-EFI platforms.
config IRQBALANCE
- bool "Enable kernel irq balancing"
- depends on SMP && X86_IO_APIC
+ bool "Enable kernel irq balancing"
+ depends on X86_32 && SMP && X86_IO_APIC
default y
help
- The default yes will allow the kernel to do irq load balancing.
+ The default yes will allow the kernel to do irq load balancing.
Saying no will keep the kernel from doing irq load balancing.
# turning this on wastes a bunch of space.
# Summit needs it only when NUMA is on
config BOOT_IOREMAP
bool
- depends on (((X86_SUMMIT || X86_GENERICARCH) && NUMA) || (X86 && EFI))
+ depends on X86_32 && (((X86_SUMMIT || X86_GENERICARCH) && NUMA) || (X86 && EFI))
default y
config SECCOMP
@@ -807,6 +1034,30 @@ config SECCOMP
If unsure, say Y. Only embedded should say N here.
+config CC_STACKPROTECTOR
+ bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
+ depends on X86_64 && EXPERIMENTAL
+ help
+ This option turns on the -fstack-protector GCC feature. This
+ feature puts, at the beginning of critical functions, a canary
+ value on the stack just before the return address, and validates
+ the value just before actually returning. Stack based buffer
+ overflows (that need to overwrite this return address) now also
+ overwrite the canary, which gets detected and the attack is then
+ neutralized via a kernel panic.
+
+ This feature requires gcc version 4.2 or above, or a distribution
+ gcc with the feature backported. Older versions are automatically
+ detected and for those versions, this configuration option is ignored.
+
+config CC_STACKPROTECTOR_ALL
+ bool "Use stack-protector for all functions"
+ depends on CC_STACKPROTECTOR
+ help
+ Normally, GCC only inserts the canary value protection for
+ functions that use large-ish on-stack buffers. By enabling
+ this option, GCC will be asked to do this for ALL functions.
+
source kernel/Kconfig.hz
config KEXEC
@@ -828,20 +1079,22 @@ config KEXEC
config CRASH_DUMP
bool "kernel crash dumps (EXPERIMENTAL)"
depends on EXPERIMENTAL
- depends on HIGHMEM
+ depends on X86_64 || (X86_32 && HIGHMEM)
help
Generate crash dump after being started by kexec.
- This should be normally only set in special crash dump kernels
+ This should be normally only set in special crash dump kernels
which are loaded in the main kernel with kexec-tools into
a specially reserved region and then later executed after
a crash by kdump/kexec. The crash dump kernel must be compiled
- to a memory address not used by the main kernel or BIOS using
- PHYSICAL_START.
+ to a memory address not used by the main kernel or BIOS using
+ PHYSICAL_START, or it must be built as a relocatable image
+ (CONFIG_RELOCATABLE=y).
For more details see Documentation/kdump/kdump.txt
config PHYSICAL_START
hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP)
default "0x1000000" if X86_NUMAQ
+ default "0x200000" if X86_64
default "0x100000"
help
This gives the physical address where the kernel is loaded.
@@ -882,37 +1135,43 @@ config PHYSICAL_START
Don't change this unless you know what you are doing.
config RELOCATABLE
- bool "Build a relocatable kernel(EXPERIMENTAL)"
+ bool "Build a relocatable kernel (EXPERIMENTAL)"
depends on EXPERIMENTAL
help
This builds a kernel image that retains relocation information
- so it can be loaded someplace besides the default 1MB.
+ so it can be loaded someplace besides the default 1MB.
The relocations tend to make the kernel binary about 10% larger,
- but are discarded at runtime.
+ but are discarded at runtime.
One use is for the kexec on panic case where the recovery kernel
- must live at a different physical address than the primary
- kernel.
+ must live at a different physical address than the primary
+ kernel.
+
+ Note: If CONFIG_RELOCATABLE=y, then the kernel runs from the address
+ it has been loaded at and the compile time physical address
+ (CONFIG_PHYSICAL_START) is ignored.
config PHYSICAL_ALIGN
- hex "Alignment value to which kernel should be aligned"
- default "0x100000"
+ hex
+ prompt "Alignment value to which kernel should be aligned" if X86_32
+ default "0x100000" if X86_32
+ default "0x200000" if X86_64
range 0x2000 0x400000
help
This value puts the alignment restrictions on physical address
- where kernel is loaded and run from. Kernel is compiled for an
- address which meets above alignment restriction.
-
- If bootloader loads the kernel at a non-aligned address and
- CONFIG_RELOCATABLE is set, kernel will move itself to nearest
- address aligned to above value and run from there.
-
- If bootloader loads the kernel at a non-aligned address and
- CONFIG_RELOCATABLE is not set, kernel will ignore the run time
- load address and decompress itself to the address it has been
- compiled for and run from there. The address for which kernel is
- compiled already meets above alignment restrictions. Hence the
- end result is that kernel runs from a physical address meeting
+ where kernel is loaded and run from. Kernel is compiled for an
+ address which meets above alignment restriction.
+
+ If bootloader loads the kernel at a non-aligned address and
+ CONFIG_RELOCATABLE is set, kernel will move itself to nearest
+ address aligned to above value and run from there.
+
+ If bootloader loads the kernel at a non-aligned address and
+ CONFIG_RELOCATABLE is not set, kernel will ignore the run time
+ load address and decompress itself to the address it has been
+ compiled for and run from there. The address for which kernel is
+ compiled already meets above alignment restrictions. Hence the
+ end result is that kernel runs from a physical address meeting
above alignment restrictions.
Don't change this unless you know what you are doing.
@@ -924,10 +1183,13 @@ config HOTPLUG_CPU
Say Y here to experiment with turning CPUs off and on, and to
enable suspend on SMP systems. CPUs can be controlled through
/sys/devices/system/cpu.
+ Say N if you want to disable CPU hotplug and don't need to
+ suspend.
config COMPAT_VDSO
bool "Compat VDSO support"
default y
+ depends on X86_32
help
Map the VDSO to the predictable old-style address too.
---help---
@@ -941,18 +1203,35 @@ endmenu
config ARCH_ENABLE_MEMORY_HOTPLUG
def_bool y
- depends on HIGHMEM
+ depends on X86_64 || (X86_32 && HIGHMEM)
+
+config MEMORY_HOTPLUG_RESERVE
+ def_bool X86_64
+ depends on (MEMORY_HOTPLUG && DISCONTIGMEM)
-menu "Power management options (ACPI, APM)"
+config HAVE_ARCH_EARLY_PFN_TO_NID
+ def_bool X86_64
+ depends on NUMA
+
+config OUT_OF_LINE_PFN_TO_PAGE
+ def_bool X86_64
+ depends on DISCONTIGMEM
+
+menu "Power management options"
depends on !X86_VOYAGER
-source kernel/power/Kconfig
+config ARCH_HIBERNATION_HEADER
+ bool
+ depends on X86_64 && HIBERNATION
+ default y
+
+source "kernel/power/Kconfig"
source "drivers/acpi/Kconfig"
menuconfig APM
tristate "APM (Advanced Power Management) BIOS support"
- depends on PM_SLEEP && !X86_VISWS
+ depends on X86_32 && PM_SLEEP && !X86_VISWS
---help---
APM is a BIOS specification for saving power using several different
techniques. This is mostly useful for battery powered laptops with
@@ -1080,9 +1359,12 @@ endif # APM
source "arch/x86/kernel/cpu/cpufreq/Kconfig"
+source "drivers/cpuidle/Kconfig"
+
endmenu
-menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
+
+menu "Bus options (PCI etc.)"
config PCI
bool "PCI support" if !X86_VISWS
@@ -1102,7 +1384,7 @@ config PCI
choice
prompt "PCI access mode"
- depends on PCI && !X86_VISWS
+ depends on X86_32 && PCI && !X86_VISWS
default PCI_GOANY
---help---
On PCI systems, the BIOS can be used to detect the PCI devices and
@@ -1135,17 +1417,18 @@ endchoice
config PCI_BIOS
bool
- depends on !X86_VISWS && PCI && (PCI_GOBIOS || PCI_GOANY)
+ depends on X86_32 && !X86_VISWS && PCI && (PCI_GOBIOS || PCI_GOANY)
default y
+# x86-64 doesn't support PCI BIOS access from long mode so always go direct.
config PCI_DIRECT
bool
- depends on PCI && ((PCI_GODIRECT || PCI_GOANY) || X86_VISWS)
+ depends on PCI && (X86_64 || (PCI_GODIRECT || PCI_GOANY) || X86_VISWS)
default y
config PCI_MMCONFIG
bool
- depends on PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY)
+ depends on X86_32 && PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY)
default y
config PCI_DOMAINS
@@ -1153,14 +1436,52 @@ config PCI_DOMAINS
depends on PCI
default y
+config PCI_MMCONFIG
+ bool "Support mmconfig PCI config space access"
+ depends on X86_64 && PCI && ACPI
+
+config DMAR
+ bool "Support for DMA Remapping Devices (EXPERIMENTAL)"
+ depends on X86_64 && PCI_MSI && ACPI && EXPERIMENTAL
+ help
+ DMA remapping (DMAR) devices support enables independent address
+ translations for Direct Memory Access (DMA) from devices.
+ These DMA remapping devices are reported via ACPI tables
+ and include PCI device scope covered by these DMA
+ remapping devices.
+
+config DMAR_GFX_WA
+ bool "Support for Graphics workaround"
+ depends on DMAR
+ default y
+ help
+ Current Graphics drivers tend to use physical address
+ for DMA and avoid using DMA APIs. Setting this config
+ option permits the IOMMU driver to set a unity map for
+ all the OS-visible memory. Hence the driver can continue
+ to use physical addresses for DMA.
+
+config DMAR_FLOPPY_WA
+ bool
+ depends on DMAR
+ default y
+ help
+ Floppy disk drivers are know to bypass DMA API calls
+ thereby failing to work when IOMMU is enabled. This
+ workaround will setup a 1:1 mapping for the first
+ 16M to make floppy (an ISA device) work.
+
source "drivers/pci/pcie/Kconfig"
source "drivers/pci/Kconfig"
+# x86_64 have no ISA slots, but do have ISA-style DMA.
config ISA_DMA_API
bool
default y
+if X86_32
+
config ISA
bool "ISA support"
depends on !(X86_VOYAGER || X86_VISWS)
@@ -1232,9 +1553,11 @@ config GEODE_MFGPT_TIMER
MFGPTs have a better resolution and max interval than the
generic PIT, and are suitable for use as high-res timers.
+endif # X86_32
+
config K8_NB
def_bool y
- depends on AGP_AMD64
+ depends on AGP_AMD64 || (X86_64 && (GART_IOMMU || (PCI && NUMA)))
source "drivers/pcmcia/Kconfig"
@@ -1242,88 +1565,56 @@ source "drivers/pci/hotplug/Kconfig"
endmenu
-menu "Executable file formats"
+
+menu "Executable file formats / Emulations"
source "fs/Kconfig.binfmt"
-endmenu
+config IA32_EMULATION
+ bool "IA32 Emulation"
+ depends on X86_64
+ help
+ Include code to run 32-bit programs under a 64-bit kernel. You should
+ likely turn this on, unless you're 100% sure that you don't have any
+ 32-bit programs left.
-source "net/Kconfig"
+config IA32_AOUT
+ tristate "IA32 a.out support"
+ depends on IA32_EMULATION
+ help
+ Support old a.out binaries in the 32bit emulation.
-source "drivers/Kconfig"
+config COMPAT
+ bool
+ depends on IA32_EMULATION
+ default y
-source "fs/Kconfig"
+config COMPAT_FOR_U64_ALIGNMENT
+ def_bool COMPAT
+ depends on X86_64
-menuconfig INSTRUMENTATION
- bool "Instrumentation Support"
- depends on EXPERIMENTAL
+config SYSVIPC_COMPAT
+ bool
+ depends on X86_64 && COMPAT && SYSVIPC
default y
- ---help---
- Say Y here to get to see options related to performance measurement,
- debugging, and testing. This option alone does not add any kernel code.
- If you say N, all options in this submenu will be skipped and disabled.
+endmenu
-if INSTRUMENTATION
-source "arch/x86/oprofile/Kconfig"
+source "net/Kconfig"
-config KPROBES
- bool "Kprobes"
- depends on KALLSYMS && MODULES
- help
- Kprobes allows you to trap at almost any kernel address and
- execute a callback function. register_kprobe() establishes
- a probepoint and specifies the callback. Kprobes is useful
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
+source "drivers/Kconfig"
-endif # INSTRUMENTATION
+source "drivers/firmware/Kconfig"
+
+source "fs/Kconfig"
-source "arch/i386/Kconfig.debug"
+source "kernel/Kconfig.instrumentation"
+
+source "arch/x86/Kconfig.debug"
source "security/Kconfig"
source "crypto/Kconfig"
source "lib/Kconfig"
-
-#
-# Use the generic interrupt handling code in kernel/irq/:
-#
-config GENERIC_HARDIRQS
- bool
- default y
-
-config GENERIC_IRQ_PROBE
- bool
- default y
-
-config GENERIC_PENDING_IRQ
- bool
- depends on GENERIC_HARDIRQS && SMP
- default y
-
-config X86_SMP
- bool
- depends on SMP && !X86_VOYAGER
- default y
-
-config X86_HT
- bool
- depends on SMP && !(X86_VISWS || X86_VOYAGER)
- default y
-
-config X86_BIOS_REBOOT
- bool
- depends on !(X86_VISWS || X86_VOYAGER)
- default y
-
-config X86_TRAMPOLINE
- bool
- depends on X86_SMP || (X86_VOYAGER && SMP)
- default y
-
-config KTIME_SCALAR
- bool
- default y
diff --git a/arch/i386/Kconfig.cpu b/arch/x86/Kconfig.cpu
index 11a24d54f27b..c30162202dc4 100644
--- a/arch/i386/Kconfig.cpu
+++ b/arch/x86/Kconfig.cpu
@@ -3,11 +3,12 @@ if !X86_ELAN
choice
prompt "Processor family"
- default M686
+ default M686 if X86_32
+ default GENERIC_CPU if X86_64
config M386
bool "386"
- depends on !UML
+ depends on X86_32 && !UML
---help---
This is the processor type of your CPU. This information is used for
optimizing purposes. In order to compile a kernel that can run on
@@ -49,6 +50,7 @@ config M386
config M486
bool "486"
+ depends on X86_32
help
Select this for a 486 series processor, either Intel or one of the
compatible processors from AMD, Cyrix, IBM, or Intel. Includes DX,
@@ -57,6 +59,7 @@ config M486
config M586
bool "586/K5/5x86/6x86/6x86MX"
+ depends on X86_32
help
Select this for an 586 or 686 series processor such as the AMD K5,
the Cyrix 5x86, 6x86 and 6x86MX. This choice does not
@@ -64,18 +67,21 @@ config M586
config M586TSC
bool "Pentium-Classic"
+ depends on X86_32
help
Select this for a Pentium Classic processor with the RDTSC (Read
Time Stamp Counter) instruction for benchmarking.
config M586MMX
bool "Pentium-MMX"
+ depends on X86_32
help
Select this for a Pentium with the MMX graphics/multimedia
extended instructions.
config M686
bool "Pentium-Pro"
+ depends on X86_32
help
Select this for Intel Pentium Pro chips. This enables the use of
Pentium Pro extended instructions, and disables the init-time guard
@@ -83,6 +89,7 @@ config M686
config MPENTIUMII
bool "Pentium-II/Celeron(pre-Coppermine)"
+ depends on X86_32
help
Select this for Intel chips based on the Pentium-II and
pre-Coppermine Celeron core. This option enables an unaligned
@@ -92,6 +99,7 @@ config MPENTIUMII
config MPENTIUMIII
bool "Pentium-III/Celeron(Coppermine)/Pentium-III Xeon"
+ depends on X86_32
help
Select this for Intel chips based on the Pentium-III and
Celeron-Coppermine core. This option enables use of some
@@ -100,28 +108,50 @@ config MPENTIUMIII
config MPENTIUMM
bool "Pentium M"
+ depends on X86_32
help
Select this for Intel Pentium M (not Pentium-4 M)
notebook chips.
-config MCORE2
- bool "Core 2/newer Xeon"
- help
- Select this for Intel Core 2 and newer Core 2 Xeons (Xeon 51xx and 53xx)
- CPUs. You can distinguish newer from older Xeons by the CPU family
- in /proc/cpuinfo. Newer ones have 6.
-
config MPENTIUM4
bool "Pentium-4/Celeron(P4-based)/Pentium-4 M/older Xeon"
+ depends on X86_32
help
Select this for Intel Pentium 4 chips. This includes the
- Pentium 4, P4-based Celeron and Xeon, and Pentium-4 M
- (not Pentium M) chips. This option enables compile flags
- optimized for the chip, uses the correct cache shift, and
- applies any applicable Pentium III optimizations.
+ Pentium 4, Pentium D, P4-based Celeron and Xeon, and
+ Pentium-4 M (not Pentium M) chips. This option enables compile
+ flags optimized for the chip, uses the correct cache line size, and
+ applies any applicable optimizations.
+
+ CPUIDs: F[0-6][1-A] (in /proc/cpuinfo show = cpu family : 15 )
+
+ Select this for:
+ Pentiums (Pentium 4, Pentium D, Celeron, Celeron D) corename:
+ -Willamette
+ -Northwood
+ -Mobile Pentium 4
+ -Mobile Pentium 4 M
+ -Extreme Edition (Gallatin)
+ -Prescott
+ -Prescott 2M
+ -Cedar Mill
+ -Presler
+ -Smithfiled
+ Xeons (Intel Xeon, Xeon MP, Xeon LV, Xeon MV) corename:
+ -Foster
+ -Prestonia
+ -Gallatin
+ -Nocona
+ -Irwindale
+ -Cranford
+ -Potomac
+ -Paxville
+ -Dempsey
+
config MK6
bool "K6/K6-II/K6-III"
+ depends on X86_32
help
Select this for an AMD K6-family processor. Enables use of
some extended instructions, and passes appropriate optimization
@@ -129,6 +159,7 @@ config MK6
config MK7
bool "Athlon/Duron/K7"
+ depends on X86_32
help
Select this for an AMD Athlon K7-family processor. Enables use of
some extended instructions, and passes appropriate optimization
@@ -143,6 +174,7 @@ config MK8
config MCRUSOE
bool "Crusoe"
+ depends on X86_32
help
Select this for a Transmeta Crusoe processor. Treats the processor
like a 586 with TSC, and sets some GCC optimization flags (like a
@@ -150,11 +182,13 @@ config MCRUSOE
config MEFFICEON
bool "Efficeon"
+ depends on X86_32
help
Select this for a Transmeta Efficeon processor.
config MWINCHIPC6
bool "Winchip-C6"
+ depends on X86_32
help
Select this for an IDT Winchip C6 chip. Linux and GCC
treat this chip as a 586TSC with some extended instructions
@@ -162,6 +196,7 @@ config MWINCHIPC6
config MWINCHIP2
bool "Winchip-2"
+ depends on X86_32
help
Select this for an IDT Winchip-2. Linux and GCC
treat this chip as a 586TSC with some extended instructions
@@ -169,6 +204,7 @@ config MWINCHIP2
config MWINCHIP3D
bool "Winchip-2A/Winchip-3"
+ depends on X86_32
help
Select this for an IDT Winchip-2A or 3. Linux and GCC
treat this chip as a 586TSC with some extended instructions
@@ -178,16 +214,19 @@ config MWINCHIP3D
config MGEODEGX1
bool "GeodeGX1"
+ depends on X86_32
help
Select this for a Geode GX1 (Cyrix MediaGX) chip.
config MGEODE_LX
bool "Geode GX/LX"
+ depends on X86_32
help
Select this for AMD Geode GX and LX processors.
config MCYRIXIII
bool "CyrixIII/VIA-C3"
+ depends on X86_32
help
Select this for a Cyrix III or C3 chip. Presently Linux and GCC
treat this chip as a generic 586. Whilst the CPU is 686 class,
@@ -199,6 +238,7 @@ config MCYRIXIII
config MVIAC3_2
bool "VIA C3-2 (Nehemiah)"
+ depends on X86_32
help
Select this for a VIA C3 "Nehemiah". Selecting this enables usage
of SSE and tells gcc to treat the CPU as a 686.
@@ -206,15 +246,42 @@ config MVIAC3_2
config MVIAC7
bool "VIA C7"
+ depends on X86_32
help
Select this for a VIA C7. Selecting this uses the correct cache
shift and tells gcc to treat the CPU as a 686.
+config MPSC
+ bool "Intel P4 / older Netburst based Xeon"
+ depends on X86_64
+ help
+ Optimize for Intel Pentium 4, Pentium D and older Nocona/Dempsey
+ Xeon CPUs with Intel 64bit which is compatible with x86-64.
+ Note that the latest Xeons (Xeon 51xx and 53xx) are not based on the
+ Netburst core and shouldn't use this option. You can distinguish them
+ using the cpu family field
+ in /proc/cpuinfo. Family 15 is an older Xeon, Family 6 a newer one.
+
+config MCORE2
+ bool "Core 2/newer Xeon"
+ help
+ Select this for Intel Core 2 and newer Core 2 Xeons (Xeon 51xx and 53xx)
+ CPUs. You can distinguish newer from older Xeons by the CPU family
+ in /proc/cpuinfo. Newer ones have 6 and older ones 15 (not a typo)
+
+config GENERIC_CPU
+ bool "Generic-x86-64"
+ depends on X86_64
+ help
+ Generic x86-64 CPU.
+ Run equally well on all x86-64 CPUs.
+
endchoice
config X86_GENERIC
- bool "Generic x86 support"
- help
+ bool "Generic x86 support"
+ depends on X86_32
+ help
Instead of just including optimizations for the selected
x86 variant (e.g. PII, Crusoe or Athlon), include some more
generic optimizations as well. This will make the kernel
@@ -227,44 +294,31 @@ endif
#
# Define implied options from the CPU selection here
-#
+config X86_L1_CACHE_BYTES
+ int
+ default "128" if GENERIC_CPU || MPSC
+ default "64" if MK8 || MCORE2
+ depends on X86_64
+
+config X86_INTERNODE_CACHE_BYTES
+ int
+ default "4096" if X86_VSMP
+ default X86_L1_CACHE_BYTES if !X86_VSMP
+ depends on X86_64
+
config X86_CMPXCHG
- bool
- depends on !M386
- default y
+ def_bool X86_64 || (X86_32 && !M386)
config X86_L1_CACHE_SHIFT
int
- default "7" if MPENTIUM4 || X86_GENERIC
+ default "7" if MPENTIUM4 || X86_GENERIC || GENERIC_CPU || MPSC
default "4" if X86_ELAN || M486 || M386 || MGEODEGX1
default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODE_LX
default "6" if MK7 || MK8 || MPENTIUMM || MCORE2 || MVIAC7
config X86_XADD
bool
- depends on !M386
- default y
-
-config RWSEM_GENERIC_SPINLOCK
- bool
- depends on !X86_XADD
- default y
-
-config RWSEM_XCHGADD_ALGORITHM
- bool
- depends on X86_XADD
- default y
-
-config ARCH_HAS_ILOG2_U32
- bool
- default n
-
-config ARCH_HAS_ILOG2_U64
- bool
- default n
-
-config GENERIC_CALIBRATE_DELAY
- bool
+ depends on X86_32 && !M386
default y
config X86_PPRO_FENCE
@@ -279,22 +333,22 @@ config X86_F00F_BUG
config X86_WP_WORKS_OK
bool
- depends on !M386
+ depends on X86_32 && !M386
default y
config X86_INVLPG
bool
- depends on !M386
+ depends on X86_32 && !M386
default y
config X86_BSWAP
bool
- depends on !M386
+ depends on X86_32 && !M386
default y
config X86_POPAD_OK
bool
- depends on !M386
+ depends on X86_32 && !M386
default y
config X86_ALIGNMENT_16
@@ -304,7 +358,7 @@ config X86_ALIGNMENT_16
config X86_GOOD_APIC
bool
- depends on MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || MK8 || MEFFICEON || MCORE2 || MVIAC7
+ depends on MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || MK8 || MEFFICEON || MCORE2 || MVIAC7 || X86_64
default y
config X86_INTEL_USERCOPY
@@ -329,7 +383,7 @@ config X86_OOSTORE
config X86_TSC
bool
- depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MVIAC7 || MGEODEGX1 || MGEODE_LX || MCORE2) && !X86_NUMAQ
+ depends on ((MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MVIAC7 || MGEODEGX1 || MGEODE_LX || MCORE2) && !X86_NUMAQ) || X86_64
default y
# this should be set for all -march=.. options where the compiler
@@ -341,6 +395,7 @@ config X86_CMOV
config X86_MINIMUM_CPU_FAMILY
int
- default "4" if X86_XADD || X86_CMPXCHG || X86_BSWAP || X86_WP_WORKS_OK
+ default "64" if X86_64
+ default "4" if X86_32 && (X86_XADD || X86_CMPXCHG || X86_BSWAP || X86_WP_WORKS_OK)
default "3"
diff --git a/arch/i386/Kconfig.debug b/arch/x86/Kconfig.debug
index f03531eacdfb..761ca7b5f120 100644
--- a/arch/i386/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -1,13 +1,12 @@
menu "Kernel hacking"
config TRACE_IRQFLAGS_SUPPORT
- bool
- default y
+ def_bool y
source "lib/Kconfig.debug"
config EARLY_PRINTK
- bool "Early printk" if EMBEDDED && DEBUG_KERNEL
+ bool "Early printk" if EMBEDDED && DEBUG_KERNEL && X86_32
default y
help
Write kernel log output directly into the VGA buffer or to a serial
@@ -37,10 +36,12 @@ config DEBUG_STACK_USAGE
comment "Page alloc debug is incompatible with Software Suspend on i386"
depends on DEBUG_KERNEL && HIBERNATION
+ depends on X86_32
config DEBUG_PAGEALLOC
bool "Debug page memory allocations"
depends on DEBUG_KERNEL && !HIBERNATION && !HUGETLBFS
+ depends on X86_32
help
Unmap pages from the kernel linear mapping after free_pages().
This results in a large slowdown, but helps to find certain types
@@ -59,6 +60,7 @@ config DEBUG_RODATA
config 4KSTACKS
bool "Use 4Kb for kernel stacks instead of 8Kb"
depends on DEBUG_KERNEL
+ depends on X86_32
help
If you say Y here the kernel will use a 4Kb stacksize for the
kernel stack attached to each process/thread. This facilitates
@@ -67,22 +69,47 @@ config 4KSTACKS
will also use IRQ stacks to compensate for the reduced stackspace.
config X86_FIND_SMP_CONFIG
- bool
+ def_bool y
depends on X86_LOCAL_APIC || X86_VOYAGER
- default y
+ depends on X86_32
config X86_MPPARSE
- bool
+ def_bool y
depends on X86_LOCAL_APIC && !X86_VISWS
- default y
+ depends on X86_32
config DOUBLEFAULT
default y
bool "Enable doublefault exception handler" if EMBEDDED
+ depends on X86_32
+ help
+ This option allows trapping of rare doublefault exceptions that
+ would otherwise cause a system to silently reboot. Disabling this
+ option saves about 4k and might cause you much additional grey
+ hair.
+
+config IOMMU_DEBUG
+ bool "Enable IOMMU debugging"
+ depends on GART_IOMMU && DEBUG_KERNEL
+ depends on X86_64
+ help
+ Force the IOMMU to on even when you have less than 4GB of
+ memory and add debugging code. On overflow always panic. And
+ allow to enable IOMMU leak tracing. Can be disabled at boot
+ time with iommu=noforce. This will also enable scatter gather
+ list merging. Currently not recommended for production
+ code. When you use it make sure you have a big enough
+ IOMMU/AGP aperture. Most of the options enabled by this can
+ be set more finegrained using the iommu= command line
+ options. See Documentation/x86_64/boot-options.txt for more
+ details.
+
+config IOMMU_LEAK
+ bool "IOMMU leak tracing"
+ depends on DEBUG_KERNEL
+ depends on IOMMU_DEBUG
help
- This option allows trapping of rare doublefault exceptions that
- would otherwise cause a system to silently reboot. Disabling this
- option saves about 4k and might cause you much additional grey
- hair.
+ Add a simple leak tracer to the IOMMU code. This is useful when you
+ are debugging a buggy device driver that leaks IOMMU mappings.
endmenu
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
new file mode 100644
index 000000000000..116b03a45636
--- /dev/null
+++ b/arch/x86/Makefile
@@ -0,0 +1,20 @@
+# Unified Makefile for i386 and x86_64
+
+# select defconfig based on actual architecture
+ifeq ($(ARCH),x86)
+ KBUILD_DEFCONFIG := i386_defconfig
+else
+ KBUILD_DEFCONFIG := $(ARCH)_defconfig
+endif
+
+# No need to remake these files
+$(srctree)/arch/x86/Makefile%: ;
+
+ifeq ($(CONFIG_X86_32),y)
+ include $(srctree)/arch/x86/Makefile_32
+else
+ include $(srctree)/arch/x86/Makefile_64
+endif
+
+
+
diff --git a/arch/i386/Makefile b/arch/x86/Makefile_32
index 5e50dbf00f3e..50394da2f6c1 100644
--- a/arch/i386/Makefile
+++ b/arch/x86/Makefile_32
@@ -1,5 +1,5 @@
#
-# i386/Makefile
+# i386 Makefile
#
# This file is included by the global makefile so that you can add your own
# architecture-specific flags and dependencies. Remember to do have actions
@@ -17,8 +17,11 @@
# 20050320 Kianusch Sayah Karadji <kianusch@sk-tech.net>
# Added support for GEODE CPU
-# Fill in SRCARCH
-SRCARCH := x86
+# BITS is used as extension for files which are available in a 32 bit
+# and a 64 bit version to simplify shared Makefiles.
+# e.g.: obj-y += foo_$(BITS).o
+BITS := 32
+export BITS
HAS_BIARCH := $(call cc-option-yn, -m32)
ifeq ($(HAS_BIARCH),y)
@@ -34,13 +37,13 @@ LDFLAGS_vmlinux := --emit-relocs
endif
CHECKFLAGS += -D__i386__
-CFLAGS += -pipe -msoft-float -mregparm=3 -freg-struct-return
+KBUILD_CFLAGS += -pipe -msoft-float -mregparm=3 -freg-struct-return
# prevent gcc from keeping the stack 16 byte aligned
-CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2)
+KBUILD_CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2)
# CPU-specific tuning. Anything which can be shared with UML should go here.
-include $(srctree)/arch/i386/Makefile.cpu
+include $(srctree)/arch/x86/Makefile_32.cpu
# temporary until string.h is fixed
cflags-y += -ffreestanding
@@ -51,17 +54,17 @@ cflags-y += -maccumulate-outgoing-args
# Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use
# a lot more stack due to the lack of sharing of stacklots:
-CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then echo $(call cc-option,-fno-unit-at-a-time); fi ;)
+KBUILD_CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then echo $(call cc-option,-fno-unit-at-a-time); fi ;)
# do binutils support CFI?
cflags-y += $(call as-instr,.cfi_startproc\n.cfi_rel_offset esp${comma}0\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
-AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_rel_offset esp${comma}0\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
+KBUILD_AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_rel_offset esp${comma}0\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
# is .cfi_signal_frame supported too?
cflags-y += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,)
-AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,)
+KBUILD_AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,)
-CFLAGS += $(cflags-y)
+KBUILD_CFLAGS += $(cflags-y)
# Default subarch .c files
mcore-y := arch/x86/mach-default
@@ -99,10 +102,13 @@ core-$(CONFIG_X86_ES7000) := arch/x86/mach-es7000/
# Xen paravirtualization support
core-$(CONFIG_XEN) += arch/x86/xen/
+# lguest paravirtualization support
+core-$(CONFIG_LGUEST_GUEST) += arch/x86/lguest/
+
# default subarch .h files
mflags-y += -Iinclude/asm-x86/mach-default
-head-y := arch/x86/kernel/head_32.o arch/x86/kernel/init_task_32.o
+head-y := arch/x86/kernel/head_32.o arch/x86/kernel/init_task.o
libs-y += arch/x86/lib/
core-y += arch/x86/kernel/ \
@@ -116,8 +122,8 @@ drivers-$(CONFIG_OPROFILE) += arch/x86/oprofile/
drivers-$(CONFIG_PM) += arch/x86/power/
drivers-$(CONFIG_FB) += arch/x86/video/
-CFLAGS += $(mflags-y)
-AFLAGS += $(mflags-y)
+KBUILD_CFLAGS += $(mflags-y)
+KBUILD_AFLAGS += $(mflags-y)
boot := arch/x86/boot
@@ -131,9 +137,9 @@ all: bzImage
zImage zlilo zdisk: KBUILD_IMAGE := arch/x86/boot/zImage
zImage bzImage: vmlinux
- $(Q)mkdir -p $(objtree)/arch/i386/boot
- $(Q)ln -fsn $(objtree)/arch/x86/boot/bzImage $(objtree)/arch/i386/boot/bzImage
$(Q)$(MAKE) $(build)=$(boot) $(KBUILD_IMAGE)
+ $(Q)mkdir -p $(objtree)/arch/i386/boot
+ $(Q)ln -fsn ../../x86/boot/bzImage $(objtree)/arch/i386/boot/bzImage
compressed: zImage
@@ -154,7 +160,7 @@ archclean:
$(Q)$(MAKE) $(clean)=arch/x86/boot
define archhelp
- echo '* bzImage - Compressed kernel image (arch/$(ARCH)/boot/bzImage)'
+ echo '* bzImage - Compressed kernel image (arch/x86/boot/bzImage)'
echo ' install - Install kernel using'
echo ' (your) ~/bin/installkernel or'
echo ' (distribution) /sbin/installkernel or'
@@ -164,6 +170,6 @@ define archhelp
echo ' isoimage - Create a boot CD-ROM image'
endef
-CLEAN_FILES += arch/$(ARCH)/boot/fdimage \
- arch/$(ARCH)/boot/image.iso \
- arch/$(ARCH)/boot/mtools.conf
+CLEAN_FILES += arch/x86/boot/fdimage \
+ arch/x86/boot/image.iso \
+ arch/x86/boot/mtools.conf
diff --git a/arch/i386/Makefile.cpu b/arch/x86/Makefile_32.cpu
index e372b584e919..e372b584e919 100644
--- a/arch/i386/Makefile.cpu
+++ b/arch/x86/Makefile_32.cpu
diff --git a/arch/x86_64/Makefile b/arch/x86/Makefile_64
index 8bffb94c71b5..a804860022e6 100644
--- a/arch/x86_64/Makefile
+++ b/arch/x86/Makefile_64
@@ -1,5 +1,5 @@
#
-# x86_64/Makefile
+# x86_64 Makefile
#
# This file is included by the global makefile so that you can add your own
# architecture-specific flags and dependencies. Remember to do have actions
@@ -21,8 +21,11 @@
#
# $Id: Makefile,v 1.31 2002/03/22 15:56:07 ak Exp $
-# Fill in SRCARCH
-SRCARCH := x86
+# BITS is used as extension for files which are available in a 32 bit
+# and a 64 bit version to simplify shared Makefiles.
+# e.g.: obj-y += foo_$(BITS).o
+BITS := 64
+export BITS
LDFLAGS := -m elf_x86_64
OBJCOPYFLAGS := -O binary -R .note -R .comment -S
@@ -61,20 +64,20 @@ cflags-y += -maccumulate-outgoing-args
# do binutils support CFI?
cflags-y += $(call as-instr,.cfi_startproc\n.cfi_rel_offset rsp${comma}0\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
-AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_rel_offset rsp${comma}0\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
+KBUILD_AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_rel_offset rsp${comma}0\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
# is .cfi_signal_frame supported too?
cflags-y += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,)
-AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,)
+KBUILD_AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,)
cflags-$(CONFIG_CC_STACKPROTECTOR) += $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-x86_64-has-stack-protector.sh "$(CC)" -fstack-protector )
cflags-$(CONFIG_CC_STACKPROTECTOR_ALL) += $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-x86_64-has-stack-protector.sh "$(CC)" -fstack-protector-all )
-CFLAGS += $(cflags-y)
+KBUILD_CFLAGS += $(cflags-y)
CFLAGS_KERNEL += $(cflags-kernel-y)
-AFLAGS += -m64
+KBUILD_AFLAGS += -m64
-head-y := arch/x86/kernel/head_64.o arch/x86/kernel/head64.o arch/x86/kernel/init_task_64.o
+head-y := arch/x86/kernel/head_64.o arch/x86/kernel/head64.o arch/x86/kernel/init_task.o
libs-y += arch/x86/lib/
core-y += arch/x86/kernel/ \
@@ -97,9 +100,9 @@ BOOTIMAGE := arch/x86/boot/bzImage
KBUILD_IMAGE := $(BOOTIMAGE)
bzImage: vmlinux
- $(Q)mkdir -p $(objtree)/arch/x86_64/boot
- $(Q)ln -fsn $(objtree)/arch/x86/boot/bzImage $(objtree)/arch/x86_64/boot/bzImage
$(Q)$(MAKE) $(build)=$(boot) $(BOOTIMAGE)
+ $(Q)mkdir -p $(objtree)/arch/x86_64/boot
+ $(Q)ln -fsn ../../x86/boot/bzImage $(objtree)/arch/x86_64/boot/bzImage
bzlilo: vmlinux
$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) zlilo
@@ -110,15 +113,21 @@ bzdisk: vmlinux
fdimage fdimage144 fdimage288 isoimage: vmlinux
$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@
-install:
+install: vdso_install
$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@
+vdso_install:
+ifeq ($(CONFIG_IA32_EMULATION),y)
+ $(Q)$(MAKE) $(build)=arch/x86/ia32 $@
+endif
+ $(Q)$(MAKE) $(build)=arch/x86/vdso $@
+
archclean:
$(Q)rm -rf $(objtree)/arch/x86_64/boot
$(Q)$(MAKE) $(clean)=$(boot)
define archhelp
- echo '* bzImage - Compressed kernel image (arch/$(ARCH)/boot/bzImage)'
+ echo '* bzImage - Compressed kernel image (arch/x86/boot/bzImage)'
echo ' install - Install kernel using'
echo ' (your) ~/bin/installkernel or'
echo ' (distribution) /sbin/installkernel or'
@@ -128,8 +137,8 @@ define archhelp
echo ' isoimage - Create a boot CD-ROM image'
endef
-CLEAN_FILES += arch/$(ARCH)/boot/fdimage \
- arch/$(ARCH)/boot/image.iso \
- arch/$(ARCH)/boot/mtools.conf
+CLEAN_FILES += arch/x86/boot/fdimage \
+ arch/x86/boot/image.iso \
+ arch/x86/boot/mtools.conf
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index cb1035f2b7e9..7a3116ccf387 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -39,6 +39,7 @@ setup-y += printf.o string.o tty.o video.o version.o voyager.o
setup-y += video-vga.o
setup-y += video-vesa.o
setup-y += video-bios.o
+
targets += $(setup-y)
hostprogs-y := tools/build
@@ -48,10 +49,10 @@ HOSTCFLAGS_build.o := $(LINUXINCLUDE)
# How to compile the 16-bit code. Note we always compile for -march=i386,
# that way we can complain to the user if the CPU is insufficient.
-cflags-i386 :=
-cflags-x86_64 := -m32
-CFLAGS := $(LINUXINCLUDE) -g -Os -D_SETUP -D__KERNEL__ \
- $(cflags-$(ARCH)) \
+cflags-$(CONFIG_X86_32) :=
+cflags-$(CONFIG_X86_64) := -m32
+KBUILD_CFLAGS := $(LINUXINCLUDE) -g -Os -D_SETUP -D__KERNEL__ \
+ $(cflags-y) \
-Wall -Wstrict-prototypes \
-march=i386 -mregparm=3 \
-include $(srctree)/$(src)/code16gcc.h \
@@ -61,13 +62,13 @@ CFLAGS := $(LINUXINCLUDE) -g -Os -D_SETUP -D__KERNEL__ \
$(call cc-option, -fno-unit-at-a-time)) \
$(call cc-option, -fno-stack-protector) \
$(call cc-option, -mpreferred-stack-boundary=2)
-AFLAGS := $(CFLAGS) -D__ASSEMBLY__
+KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__
$(obj)/zImage: IMAGE_OFFSET := 0x1000
-$(obj)/zImage: EXTRA_AFLAGS := $(SVGA_MODE) $(RAMDISK)
+$(obj)/zImage: asflags-y := $(SVGA_MODE) $(RAMDISK)
$(obj)/bzImage: IMAGE_OFFSET := 0x100000
-$(obj)/bzImage: EXTRA_CFLAGS := -D__BIG_KERNEL__
-$(obj)/bzImage: EXTRA_AFLAGS := $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__
+$(obj)/bzImage: ccflags-y := -D__BIG_KERNEL__
+$(obj)/bzImage: asflags-y := $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__
$(obj)/bzImage: BUILDFLAGS := -b
quiet_cmd_image = BUILD $@
diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h
index 20bab9431acb..d2b5adf46512 100644
--- a/arch/x86/boot/boot.h
+++ b/arch/x86/boot/boot.h
@@ -17,13 +17,15 @@
#ifndef BOOT_BOOT_H
#define BOOT_BOOT_H
+#define STACK_SIZE 512 /* Minimum number of bytes for stack */
+
#ifndef __ASSEMBLY__
#include <stdarg.h>
#include <linux/types.h>
#include <linux/edd.h>
#include <asm/boot.h>
-#include <asm/bootparam.h>
+#include <asm/setup.h>
/* Useful macros */
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
@@ -198,8 +200,6 @@ static inline int isdigit(int ch)
}
/* Heap -- available for dynamic lists. */
-#define STACK_SIZE 512 /* Minimum number of bytes for stack */
-
extern char _end[];
extern char *HEAP;
extern char *heap_end;
@@ -216,9 +216,9 @@ static inline char *__get_heap(size_t s, size_t a, size_t n)
#define GET_HEAP(type, n) \
((type *)__get_heap(sizeof(type),__alignof__(type),(n)))
-static inline int heap_free(void)
+static inline bool heap_free(size_t n)
{
- return heap_end-HEAP;
+ return (int)(heap_end-HEAP) >= (int)n;
}
/* copy.S */
diff --git a/arch/x86/boot/compressed/Makefile_32 b/arch/x86/boot/compressed/Makefile_32
index 22613c652d22..e43ff7c56e6e 100644
--- a/arch/x86/boot/compressed/Makefile_32
+++ b/arch/x86/boot/compressed/Makefile_32
@@ -11,7 +11,7 @@ EXTRA_AFLAGS := -traditional
LDFLAGS_vmlinux := -T
hostprogs-y := relocs
-CFLAGS := -m32 -D__KERNEL__ $(LINUX_INCLUDE) -O2 \
+KBUILD_CFLAGS := -m32 -D__KERNEL__ $(LINUX_INCLUDE) -O2 \
-fno-strict-aliasing -fPIC \
$(call cc-option,-ffreestanding) \
$(call cc-option,-fno-stack-protector)
diff --git a/arch/x86/boot/compressed/Makefile_64 b/arch/x86/boot/compressed/Makefile_64
index dc6b3380cc45..7801e8dd90b2 100644
--- a/arch/x86/boot/compressed/Makefile_64
+++ b/arch/x86/boot/compressed/Makefile_64
@@ -6,11 +6,11 @@
targets := vmlinux vmlinux.bin vmlinux.bin.gz head_64.o misc_64.o piggy.o
-CFLAGS := -m64 -D__KERNEL__ $(LINUXINCLUDE) -O2 \
+KBUILD_CFLAGS := -m64 -D__KERNEL__ $(LINUXINCLUDE) -O2 \
-fno-strict-aliasing -fPIC -mcmodel=small \
$(call cc-option, -ffreestanding) \
$(call cc-option, -fno-stack-protector)
-AFLAGS := $(CFLAGS) -D__ASSEMBLY__
+KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__
LDFLAGS := -m elf_x86_64
LDFLAGS_vmlinux := -T
diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
index f35ea2237522..036e635f18a3 100644
--- a/arch/x86/boot/compressed/head_32.S
+++ b/arch/x86/boot/compressed/head_32.S
@@ -27,12 +27,18 @@
#include <asm/segment.h>
#include <asm/page.h>
#include <asm/boot.h>
+#include <asm/asm-offsets.h>
.section ".text.head","ax",@progbits
.globl startup_32
startup_32:
cld
+ /* test KEEP_SEGMENTS flag to see if the bootloader is asking
+ * us to not reload segments */
+ testb $(1<<6), BP_loadflags(%esi)
+ jnz 1f
+
cli
movl $(__BOOT_DS),%eax
movl %eax,%ds
@@ -40,6 +46,7 @@ startup_32:
movl %eax,%fs
movl %eax,%gs
movl %eax,%ss
+1:
/* Calculate the delta between where we were compiled to run
* at and where we were actually loaded at. This can only be done
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index 49467640751f..1ccb38a7f0d2 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -29,6 +29,7 @@
#include <asm/pgtable.h>
#include <asm/page.h>
#include <asm/msr.h>
+#include <asm/asm-offsets.h>
.section ".text.head"
.code32
@@ -36,11 +37,17 @@
startup_32:
cld
+ /* test KEEP_SEGMENTS flag to see if the bootloader is asking
+ * us to not reload segments */
+ testb $(1<<6), BP_loadflags(%esi)
+ jnz 1f
+
cli
movl $(__KERNEL_DS), %eax
movl %eax, %ds
movl %eax, %es
movl %eax, %ss
+1:
/* Calculate the delta between where we were compiled to run
* at and where we were actually loaded at. This can only be done
diff --git a/arch/x86/boot/compressed/misc_32.c b/arch/x86/boot/compressed/misc_32.c
index b28505c544c9..b74d60d1b2fa 100644
--- a/arch/x86/boot/compressed/misc_32.c
+++ b/arch/x86/boot/compressed/misc_32.c
@@ -25,7 +25,7 @@
/*
* Getting to provable safe in place decompression is hard.
- * Worst case behaviours need to be analized.
+ * Worst case behaviours need to be analyzed.
* Background information:
*
* The file layout is:
@@ -94,7 +94,7 @@
* Adding 32768 instead of 32767 just makes for round numbers.
* Adding the decompressor_size is necessary as it musht live after all
* of the data as well. Last I measured the decompressor is about 14K.
- * 10K of actuall data and 4K of bss.
+ * 10K of actual data and 4K of bss.
*
*/
@@ -247,6 +247,9 @@ static void putstr(const char *s)
int x,y,pos;
char c;
+ if (RM_SCREEN_INFO.orig_video_mode == 0 && lines == 0 && cols == 0)
+ return;
+
x = RM_SCREEN_INFO.orig_x;
y = RM_SCREEN_INFO.orig_y;
diff --git a/arch/x86/boot/compressed/misc_64.c b/arch/x86/boot/compressed/misc_64.c
index f932b0e89096..6ea015aa65e4 100644
--- a/arch/x86/boot/compressed/misc_64.c
+++ b/arch/x86/boot/compressed/misc_64.c
@@ -25,7 +25,7 @@
/*
* Getting to provable safe in place decompression is hard.
- * Worst case behaviours need to be analized.
+ * Worst case behaviours need to be analyzed.
* Background information:
*
* The file layout is:
@@ -94,7 +94,7 @@
* Adding 32768 instead of 32767 just makes for round numbers.
* Adding the decompressor_size is necessary as it musht live after all
* of the data as well. Last I measured the decompressor is about 14K.
- * 10K of actuall data and 4K of bss.
+ * 10K of actual data and 4K of bss.
*
*/
diff --git a/arch/x86/boot/compressed/relocs.c b/arch/x86/boot/compressed/relocs.c
index 2d77ee728f92..7a0d00b2cf28 100644
--- a/arch/x86/boot/compressed/relocs.c
+++ b/arch/x86/boot/compressed/relocs.c
@@ -38,11 +38,9 @@ static const char* safe_abs_relocs[] = {
static int is_safe_abs_reloc(const char* sym_name)
{
- int i, array_size;
-
- array_size = sizeof(safe_abs_relocs)/sizeof(char*);
+ int i;
- for(i = 0; i < array_size; i++) {
+ for(i = 0; i < ARRAY_SIZE(safe_abs_relocs); i++) {
if (!strcmp(sym_name, safe_abs_relocs[i]))
/* Match found */
return 1;
diff --git a/arch/x86/boot/cpucheck.c b/arch/x86/boot/cpucheck.c
index e655a89c5510..769065bd23d7 100644
--- a/arch/x86/boot/cpucheck.c
+++ b/arch/x86/boot/cpucheck.c
@@ -42,13 +42,7 @@ static struct cpu_features cpu;
static u32 cpu_vendor[3];
static u32 err_flags[NCAPINTS];
-#ifdef CONFIG_X86_64
-static const int req_level = 64;
-#elif defined(CONFIG_X86_MINIMUM_CPU_FAMILY)
static const int req_level = CONFIG_X86_MINIMUM_CPU_FAMILY;
-#else
-static const int req_level = 3;
-#endif
static const u32 req_flags[NCAPINTS] =
{
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
index f3140e596d40..6ef5a060fa11 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -119,7 +119,7 @@ _start:
# Part 2 of the header, from the old setup.S
.ascii "HdrS" # header signature
- .word 0x0206 # header version number (>= 0x0105)
+ .word 0x0207 # header version number (>= 0x0105)
# or else old loadlin-1.5 will fail)
.globl realmode_swtch
realmode_swtch: .word 0, 0 # default_switch, SETUPSEG
@@ -173,7 +173,8 @@ ramdisk_size: .long 0 # its size in bytes
bootsect_kludge:
.long 0 # obsolete
-heap_end_ptr: .word _end+1024 # (Header version 0x0201 or later)
+heap_end_ptr: .word _end+STACK_SIZE-512
+ # (Header version 0x0201 or later)
# space from here (exclusive) down to
# end of setup code can be used by setup
# for local heap purposes.
@@ -214,6 +215,11 @@ cmdline_size: .long COMMAND_LINE_SIZE-1 #length of the command line,
#added with boot protocol
#version 2.06
+hardware_subarch: .long 0 # subarchitecture, added with 2.07
+ # default to 0 for normal x86 PC
+
+hardware_subarch_data: .quad 0
+
# End of setup header #####################################################
.section ".inittext", "ax"
@@ -225,28 +231,53 @@ start_of_setup:
int $0x13
#endif
-# We will have entered with %cs = %ds+0x20, normalize %cs so
-# it is on par with the other segments.
- pushw %ds
- pushw $setup2
- lretw
-
-setup2:
# Force %es = %ds
movw %ds, %ax
movw %ax, %es
cld
-# Stack paranoia: align the stack and make sure it is good
-# for both 16- and 32-bit references. In particular, if we
-# were meant to have been using the full 16-bit segment, the
-# caller might have set %sp to zero, which breaks %esp-based
-# references.
- andw $~3, %sp # dword align (might as well...)
- jnz 1f
- movw $0xfffc, %sp # Make sure we're not zero
-1: movzwl %sp, %esp # Clear upper half of %esp
- sti
+# Apparently some ancient versions of LILO invoked the kernel
+# with %ss != %ds, which happened to work by accident for the
+# old code. If the CAN_USE_HEAP flag is set in loadflags, or
+# %ss != %ds, then adjust the stack pointer.
+
+ # Smallest possible stack we can tolerate
+ movw $(_end+STACK_SIZE), %cx
+
+ movw heap_end_ptr, %dx
+ addw $512, %dx
+ jnc 1f
+ xorw %dx, %dx # Wraparound - whole segment available
+1: testb $CAN_USE_HEAP, loadflags
+ jnz 2f
+
+ # No CAN_USE_HEAP
+ movw %ss, %dx
+ cmpw %ax, %dx # %ds == %ss?
+ movw %sp, %dx
+ # If so, assume %sp is reasonably set, otherwise use
+ # the smallest possible stack.
+ jne 4f # -> Smallest possible stack...
+
+ # Make sure the stack is at least minimum size. Take a value
+ # of zero to mean "full segment."
+2:
+ andw $~3, %dx # dword align (might as well...)
+ jnz 3f
+ movw $0xfffc, %dx # Make sure we're not zero
+3: cmpw %cx, %dx
+ jnb 5f
+4: movw %cx, %dx # Minimum value we can possibly use
+5: movw %ax, %ss
+ movzwl %dx, %esp # Clear upper half of %esp
+ sti # Now we should have a working stack
+
+# We will have entered with %cs = %ds+0x20, normalize %cs so
+# it is on par with the other segments.
+ pushw %ds
+ pushw $6f
+ lretw
+6:
# Check signature at end of setup
cmpl $0x5a5aaa55, setup_sig
diff --git a/arch/x86/boot/main.c b/arch/x86/boot/main.c
index 0eeef3989a17..1f95750ede28 100644
--- a/arch/x86/boot/main.c
+++ b/arch/x86/boot/main.c
@@ -26,8 +26,6 @@ char *heap_end = _end; /* Default end of heap = no heap */
* screws up the old-style command line protocol, adjust by
* filling in the new-style command line pointer instead.
*/
-#define OLD_CL_MAGIC 0xA33F
-#define OLD_CL_ADDRESS 0x20
static void copy_boot_params(void)
{
diff --git a/arch/x86/boot/pmjump.S b/arch/x86/boot/pmjump.S
index 2e559233725a..fa6bed1fac14 100644
--- a/arch/x86/boot/pmjump.S
+++ b/arch/x86/boot/pmjump.S
@@ -28,17 +28,19 @@
* void protected_mode_jump(u32 entrypoint, u32 bootparams);
*/
protected_mode_jump:
- xorl %ebx, %ebx # Flag to indicate this is a boot
movl %edx, %esi # Pointer to boot_params table
movl %eax, 2f # Patch ljmpl instruction
- jmp 1f # Short jump to flush instruction q.
-1:
movw $__BOOT_DS, %cx
+ xorl %ebx, %ebx # Per the 32-bit boot protocol
+ xorl %ebp, %ebp # Per the 32-bit boot protocol
+ xorl %edi, %edi # Per the 32-bit boot protocol
movl %cr0, %edx
orb $1, %dl # Protected mode (PE) bit
movl %edx, %cr0
+ jmp 1f # Short jump to serialize on 386/486
+1:
movw %cx, %ds
movw %cx, %es
diff --git a/arch/x86/boot/video-bios.c b/arch/x86/boot/video-bios.c
index 68e65d95cdfd..ed0672a81870 100644
--- a/arch/x86/boot/video-bios.c
+++ b/arch/x86/boot/video-bios.c
@@ -79,7 +79,7 @@ static int bios_probe(void)
video_bios.modes = GET_HEAP(struct mode_info, 0);
for (mode = 0x14; mode <= 0x7f; mode++) {
- if (heap_free() < sizeof(struct mode_info))
+ if (!heap_free(sizeof(struct mode_info)))
break;
if (mode_defined(VIDEO_FIRST_BIOS+mode))
diff --git a/arch/x86/boot/video-vesa.c b/arch/x86/boot/video-vesa.c
index 192190710710..4716b9a96357 100644
--- a/arch/x86/boot/video-vesa.c
+++ b/arch/x86/boot/video-vesa.c
@@ -57,7 +57,7 @@ static int vesa_probe(void)
while ((mode = rdfs16(mode_ptr)) != 0xffff) {
mode_ptr += 2;
- if (heap_free() < sizeof(struct mode_info))
+ if (!heap_free(sizeof(struct mode_info)))
break; /* Heap full, can't save mode info */
if (mode & ~0x1ff)
diff --git a/arch/x86/boot/video.c b/arch/x86/boot/video.c
index e4ba897bf9a3..ad9712f01739 100644
--- a/arch/x86/boot/video.c
+++ b/arch/x86/boot/video.c
@@ -371,7 +371,7 @@ static void save_screen(void)
saved.curx = boot_params.screen_info.orig_x;
saved.cury = boot_params.screen_info.orig_y;
- if (heap_free() < saved.x*saved.y*sizeof(u16)+512)
+ if (!heap_free(saved.x*saved.y*sizeof(u16)+512))
return; /* Not enough heap to save the screen */
saved.data = GET_HEAP(u16, saved.x*saved.y);
diff --git a/arch/i386/defconfig b/arch/x86/configs/i386_defconfig
index 54ee1764fdae..54ee1764fdae 100644
--- a/arch/i386/defconfig
+++ b/arch/x86/configs/i386_defconfig
diff --git a/arch/x86_64/defconfig b/arch/x86/configs/x86_64_defconfig
index b091c5e35558..38a83f9c966f 100644
--- a/arch/x86_64/defconfig
+++ b/arch/x86/configs/x86_64_defconfig
@@ -170,7 +170,7 @@ CONFIG_HOTPLUG_CPU=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_HPET_TIMER=y
CONFIG_HPET_EMULATE_RTC=y
-CONFIG_IOMMU=y
+CONFIG_GART_IOMMU=y
# CONFIG_CALGARY_IOMMU is not set
CONFIG_SWIOTLB=y
CONFIG_X86_MCE=y
diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile
index 18dcdc6fb7aa..46bb609e2444 100644
--- a/arch/x86/crypto/Makefile
+++ b/arch/x86/crypto/Makefile
@@ -1,5 +1,15 @@
-ifeq ($(CONFIG_X86_32),y)
-include ${srctree}/arch/x86/crypto/Makefile_32
-else
-include ${srctree}/arch/x86/crypto/Makefile_64
-endif
+#
+# Arch-specific CryptoAPI modules.
+#
+
+obj-$(CONFIG_CRYPTO_AES_586) += aes-i586.o
+obj-$(CONFIG_CRYPTO_TWOFISH_586) += twofish-i586.o
+
+obj-$(CONFIG_CRYPTO_AES_X86_64) += aes-x86_64.o
+obj-$(CONFIG_CRYPTO_TWOFISH_X86_64) += twofish-x86_64.o
+
+aes-i586-y := aes-i586-asm_32.o aes_32.o
+twofish-i586-y := twofish-i586-asm_32.o twofish_32.o
+
+aes-x86_64-y := aes-x86_64-asm_64.o aes_64.o
+twofish-x86_64-y := twofish-x86_64-asm_64.o twofish_64.o
diff --git a/arch/x86/crypto/Makefile_32 b/arch/x86/crypto/Makefile_32
deleted file mode 100644
index 2d873a2388ed..000000000000
--- a/arch/x86/crypto/Makefile_32
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# x86/crypto/Makefile
-#
-# Arch-specific CryptoAPI modules.
-#
-
-obj-$(CONFIG_CRYPTO_AES_586) += aes-i586.o
-obj-$(CONFIG_CRYPTO_TWOFISH_586) += twofish-i586.o
-
-aes-i586-y := aes-i586-asm_32.o aes_32.o
-twofish-i586-y := twofish-i586-asm_32.o twofish_32.o
-
diff --git a/arch/x86/crypto/Makefile_64 b/arch/x86/crypto/Makefile_64
deleted file mode 100644
index b40896276e93..000000000000
--- a/arch/x86/crypto/Makefile_64
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# x86/crypto/Makefile
-#
-# Arch-specific CryptoAPI modules.
-#
-
-obj-$(CONFIG_CRYPTO_AES_X86_64) += aes-x86_64.o
-obj-$(CONFIG_CRYPTO_TWOFISH_X86_64) += twofish-x86_64.o
-
-aes-x86_64-y := aes-x86_64-asm_64.o aes_64.o
-twofish-x86_64-y := twofish-x86_64-asm_64.o twofish_64.o
-
diff --git a/arch/x86/ia32/Makefile b/arch/x86/ia32/Makefile
index cdae36435e21..e2edda255a84 100644
--- a/arch/x86/ia32/Makefile
+++ b/arch/x86/ia32/Makefile
@@ -18,18 +18,35 @@ $(obj)/syscall32_syscall.o: \
$(foreach F,sysenter syscall,$(obj)/vsyscall-$F.so)
# Teach kbuild about targets
-targets := $(foreach F,sysenter syscall,vsyscall-$F.o vsyscall-$F.so)
+targets := $(foreach F,$(addprefix vsyscall-,sysenter syscall),\
+ $F.o $F.so $F.so.dbg)
# The DSO images are built using a special linker script
quiet_cmd_syscall = SYSCALL $@
- cmd_syscall = $(CC) -m32 -nostdlib -shared -s \
+ cmd_syscall = $(CC) -m32 -nostdlib -shared \
$(call ld-option, -Wl$(comma)--hash-style=sysv) \
-Wl,-soname=linux-gate.so.1 -o $@ \
-Wl,-T,$(filter-out FORCE,$^)
-$(obj)/vsyscall-sysenter.so $(obj)/vsyscall-syscall.so: \
-$(obj)/vsyscall-%.so: $(src)/vsyscall.lds $(obj)/vsyscall-%.o FORCE
+$(obj)/%.so: OBJCOPYFLAGS := -S
+$(obj)/%.so: $(obj)/%.so.dbg FORCE
+ $(call if_changed,objcopy)
+
+$(obj)/vsyscall-sysenter.so.dbg $(obj)/vsyscall-syscall.so.dbg: \
+$(obj)/vsyscall-%.so.dbg: $(src)/vsyscall.lds $(obj)/vsyscall-%.o FORCE
$(call if_changed,syscall)
AFLAGS_vsyscall-sysenter.o = -m32 -Wa,-32
AFLAGS_vsyscall-syscall.o = -m32 -Wa,-32
+
+vdsos := vdso32-sysenter.so vdso32-syscall.so
+
+quiet_cmd_vdso_install = INSTALL $@
+ cmd_vdso_install = cp $(@:vdso32-%.so=$(obj)/vsyscall-%.so.dbg) \
+ $(MODLIB)/vdso/$@
+
+$(vdsos):
+ @mkdir -p $(MODLIB)/vdso
+ $(call cmd,vdso_install)
+
+vdso_install: $(vdsos)
diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c
index 08781370256d..f82e1a94fcb7 100644
--- a/arch/x86/ia32/ia32_aout.c
+++ b/arch/x86/ia32/ia32_aout.c
@@ -40,7 +40,7 @@ static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs);
static int load_aout_library(struct file*);
#ifdef CORE_DUMP
-static int aout_core_dump(long signr, struct pt_regs * regs, struct file *file);
+static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit);
/*
* fill in the user structure for a core dump..
@@ -148,7 +148,7 @@ if (file->f_op->llseek) { \
* dumping of the process results in another error..
*/
-static int aout_core_dump(long signr, struct pt_regs * regs, struct file *file)
+static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit)
{
mm_segment_t fs;
int has_dumped = 0;
@@ -168,13 +168,11 @@ static int aout_core_dump(long signr, struct pt_regs * regs, struct file *file)
/* If the size of the dump file exceeds the rlimit, then see what would happen
if we wrote the stack, but not the data area. */
- if ((dump.u_dsize+dump.u_ssize+1) * PAGE_SIZE >
- current->signal->rlim[RLIMIT_CORE].rlim_cur)
+ if ((dump.u_dsize + dump.u_ssize + 1) * PAGE_SIZE > limit)
dump.u_dsize = 0;
/* Make sure we have enough room to write the stack and data areas. */
- if ((dump.u_ssize+1) * PAGE_SIZE >
- current->signal->rlim[RLIMIT_CORE].rlim_cur)
+ if ((dump.u_ssize + 1) * PAGE_SIZE > limit)
dump.u_ssize = 0;
/* make sure we actually have a data and stack area to dump */
@@ -422,6 +420,8 @@ beyond_if:
(regs)->eflags = 0x200;
(regs)->cs = __USER32_CS;
(regs)->ss = __USER32_DS;
+ regs->r8 = regs->r9 = regs->r10 = regs->r11 =
+ regs->r12 = regs->r13 = regs->r14 = regs->r15 = 0;
set_fs(USER_DS);
if (unlikely(current->ptrace & PT_PTRACED)) {
if (current->ptrace & PT_TRACE_EXEC)
diff --git a/arch/x86/ia32/ia32_binfmt.c b/arch/x86/ia32/ia32_binfmt.c
index dffd2ac72747..55822d2cf053 100644
--- a/arch/x86/ia32/ia32_binfmt.c
+++ b/arch/x86/ia32/ia32_binfmt.c
@@ -5,10 +5,6 @@
* This tricks binfmt_elf.c into loading 32bit binaries using lots
* of ugly preprocessor tricks. Talk about very very poor man's inheritance.
*/
-#define __ASM_X86_64_ELF_H 1
-
-#undef ELF_CLASS
-#define ELF_CLASS ELFCLASS32
#include <linux/types.h>
#include <linux/stddef.h>
@@ -19,6 +15,7 @@
#include <linux/binfmts.h>
#include <linux/mm.h>
#include <linux/security.h>
+#include <linux/elfcore-compat.h>
#include <asm/segment.h>
#include <asm/ptrace.h>
@@ -31,6 +28,20 @@
#include <asm/ia32.h>
#include <asm/vsyscall32.h>
+#undef ELF_ARCH
+#undef ELF_CLASS
+#define ELF_CLASS ELFCLASS32
+#define ELF_ARCH EM_386
+
+#undef elfhdr
+#undef elf_phdr
+#undef elf_note
+#undef elf_addr_t
+#define elfhdr elf32_hdr
+#define elf_phdr elf32_phdr
+#define elf_note elf32_note
+#define elf_addr_t Elf32_Off
+
#define ELF_NAME "elf/i386"
#define AT_SYSINFO 32
@@ -48,77 +59,20 @@ int sysctl_vsyscall32 = 1;
} while(0)
struct file;
-struct elf_phdr;
#define IA32_EMULATOR 1
-#define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x1000000)
-
-#undef ELF_ARCH
-#define ELF_ARCH EM_386
-
-#define ELF_DATA ELFDATA2LSB
+#undef ELF_ET_DYN_BASE
-#define USE_ELF_CORE_DUMP 1
-
-/* Override elfcore.h */
-#define _LINUX_ELFCORE_H 1
-typedef unsigned int elf_greg_t;
-
-#define ELF_NGREG (sizeof (struct user_regs_struct32) / sizeof(elf_greg_t))
-typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-
-struct elf_siginfo
-{
- int si_signo; /* signal number */
- int si_code; /* extra code */
- int si_errno; /* errno */
-};
+#define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x1000000)
#define jiffies_to_timeval(a,b) do { (b)->tv_usec = 0; (b)->tv_sec = (a)/HZ; }while(0)
-struct elf_prstatus
-{
- struct elf_siginfo pr_info; /* Info associated with signal */
- short pr_cursig; /* Current signal */
- unsigned int pr_sigpend; /* Set of pending signals */
- unsigned int pr_sighold; /* Set of held signals */
- pid_t pr_pid;
- pid_t pr_ppid;
- pid_t pr_pgrp;
- pid_t pr_sid;
- struct compat_timeval pr_utime; /* User time */
- struct compat_timeval pr_stime; /* System time */
- struct compat_timeval pr_cutime; /* Cumulative user time */
- struct compat_timeval pr_cstime; /* Cumulative system time */
- elf_gregset_t pr_reg; /* GP registers */
- int pr_fpvalid; /* True if math co-processor being used. */
-};
-
-#define ELF_PRARGSZ (80) /* Number of chars for args */
-
-struct elf_prpsinfo
-{
- char pr_state; /* numeric process state */
- char pr_sname; /* char for pr_state */
- char pr_zomb; /* zombie */
- char pr_nice; /* nice val */
- unsigned int pr_flag; /* flags */
- __u16 pr_uid;
- __u16 pr_gid;
- pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid;
- /* Lots missing */
- char pr_fname[16]; /* filename of executable */
- char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
-};
-
-#define __STR(x) #x
-#define STR(x) __STR(x)
-
#define _GET_SEG(x) \
- ({ __u32 seg; asm("movl %%" STR(x) ",%0" : "=r"(seg)); seg; })
+ ({ __u32 seg; asm("movl %%" __stringify(x) ",%0" : "=r"(seg)); seg; })
/* Assumes current==process to be dumped */
+#undef ELF_CORE_COPY_REGS
#define ELF_CORE_COPY_REGS(pr_reg, regs) \
pr_reg[0] = regs->rbx; \
pr_reg[1] = regs->rcx; \
@@ -138,36 +92,41 @@ struct elf_prpsinfo
pr_reg[15] = regs->rsp; \
pr_reg[16] = regs->ss;
-#define user user32
+
+#define elf_prstatus compat_elf_prstatus
+#define elf_prpsinfo compat_elf_prpsinfo
+#define elf_fpregset_t struct user_i387_ia32_struct
+#define elf_fpxregset_t struct user32_fxsr_struct
+#define user user32
#undef elf_read_implies_exec
#define elf_read_implies_exec(ex, executable_stack) (executable_stack != EXSTACK_DISABLE_X)
-//#include <asm/ia32.h>
-#include <linux/elf.h>
-
-typedef struct user_i387_ia32_struct elf_fpregset_t;
-typedef struct user32_fxsr_struct elf_fpxregset_t;
-
-static inline void elf_core_copy_regs(elf_gregset_t *elfregs, struct pt_regs *regs)
+#define elf_core_copy_regs elf32_core_copy_regs
+static inline void elf32_core_copy_regs(compat_elf_gregset_t *elfregs,
+ struct pt_regs *regs)
{
- ELF_CORE_COPY_REGS((*elfregs), regs)
+ ELF_CORE_COPY_REGS((&elfregs->ebx), regs)
}
-static inline int elf_core_copy_task_regs(struct task_struct *t, elf_gregset_t* elfregs)
+#define elf_core_copy_task_regs elf32_core_copy_task_regs
+static inline int elf32_core_copy_task_regs(struct task_struct *t,
+ compat_elf_gregset_t* elfregs)
{
struct pt_regs *pp = task_pt_regs(t);
- ELF_CORE_COPY_REGS((*elfregs), pp);
+ ELF_CORE_COPY_REGS((&elfregs->ebx), pp);
/* fix wrong segments */
- (*elfregs)[7] = t->thread.ds;
- (*elfregs)[9] = t->thread.fsindex;
- (*elfregs)[10] = t->thread.gsindex;
- (*elfregs)[8] = t->thread.es;
+ elfregs->ds = t->thread.ds;
+ elfregs->fs = t->thread.fsindex;
+ elfregs->gs = t->thread.gsindex;
+ elfregs->es = t->thread.es;
return 1;
}
+#define elf_core_copy_task_fpregs elf32_core_copy_task_fpregs
static inline int
-elf_core_copy_task_fpregs(struct task_struct *tsk, struct pt_regs *regs, elf_fpregset_t *fpu)
+elf32_core_copy_task_fpregs(struct task_struct *tsk, struct pt_regs *regs,
+ elf_fpregset_t *fpu)
{
struct _fpstate_ia32 *fpstate = (void*)fpu;
mm_segment_t oldfs = get_fs();
@@ -188,8 +147,10 @@ elf_core_copy_task_fpregs(struct task_struct *tsk, struct pt_regs *regs, elf_fpr
}
#define ELF_CORE_COPY_XFPREGS 1
+#define ELF_CORE_XFPREG_TYPE NT_PRXFPREG
+#define elf_core_copy_task_xfpregs elf32_core_copy_task_xfpregs
static inline int
-elf_core_copy_task_xfpregs(struct task_struct *t, elf_fpxregset_t *xfpu)
+elf32_core_copy_task_xfpregs(struct task_struct *t, elf_fpxregset_t *xfpu)
{
struct pt_regs *regs = task_pt_regs(t);
if (!tsk_used_math(t))
@@ -208,6 +169,10 @@ elf_core_copy_task_xfpregs(struct task_struct *t, elf_fpxregset_t *xfpu)
extern int force_personality32;
+#undef ELF_EXEC_PAGESIZE
+#undef ELF_HWCAP
+#undef ELF_PLATFORM
+#undef SET_PERSONALITY
#define ELF_EXEC_PAGESIZE PAGE_SIZE
#define ELF_HWCAP (boot_cpu_data.x86_capability[0])
#define ELF_PLATFORM ("i686")
@@ -233,6 +198,7 @@ do { \
#define load_elf_binary load_elf32_binary
+#undef ELF_PLAT_INIT
#define ELF_PLAT_INIT(r, load_addr) elf32_init(r)
#undef start_thread
@@ -291,7 +257,6 @@ static void elf32_init(struct pt_regs *regs)
static ctl_table abi_table2[] = {
{
- .ctl_name = 99,
.procname = "vsyscall32",
.data = &sysctl_vsyscall32,
.maxlen = sizeof(int),
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index 18b231810908..df588f0f76e1 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -159,20 +159,16 @@ sysenter_do_call:
sysenter_tracesys:
CFI_RESTORE_STATE
+ xchgl %r9d,%ebp
SAVE_REST
CLEAR_RREGS
+ movq %r9,R9(%rsp)
movq $-ENOSYS,RAX(%rsp) /* really needed? */
movq %rsp,%rdi /* &pt_regs -> arg1 */
call syscall_trace_enter
LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */
RESTORE_REST
- movl %ebp, %ebp
- /* no need to do an access_ok check here because rbp has been
- 32bit zero extended */
-1: movl (%rbp),%r9d
- .section __ex_table,"a"
- .quad 1b,ia32_badarg
- .previous
+ xchgl %ebp,%r9d
jmp sysenter_do_call
CFI_ENDPROC
ENDPROC(ia32_sysenter_target)
@@ -262,20 +258,17 @@ cstar_do_call:
cstar_tracesys:
CFI_RESTORE_STATE
+ xchgl %r9d,%ebp
SAVE_REST
CLEAR_RREGS
+ movq %r9,R9(%rsp)
movq $-ENOSYS,RAX(%rsp) /* really needed? */
movq %rsp,%rdi /* &pt_regs -> arg1 */
call syscall_trace_enter
LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */
RESTORE_REST
+ xchgl %ebp,%r9d
movl RSP-ARGOFFSET(%rsp), %r8d
- /* no need to do an access_ok check here because r8 has been
- 32bit zero extended */
-1: movl (%r8),%r9d
- .section __ex_table,"a"
- .quad 1b,ia32_badarg
- .previous
jmp cstar_do_call
END(ia32_cstar_target)
diff --git a/arch/x86/ia32/ipc32.c b/arch/x86/ia32/ipc32.c
index 2e1869ec4db4..7b3342e5aab5 100644
--- a/arch/x86/ia32/ipc32.c
+++ b/arch/x86/ia32/ipc32.c
@@ -9,8 +9,6 @@
#include <linux/ipc.h>
#include <linux/compat.h>
-#include <asm/ipc.h>
-
asmlinkage long
sys32_ipc(u32 call, int first, int second, int third,
compat_uptr_t ptr, u32 fifth)
diff --git a/arch/x86/kernel/.gitignore b/arch/x86/kernel/.gitignore
index 40836ad9079c..4ea38a39aed4 100644
--- a/arch/x86/kernel/.gitignore
+++ b/arch/x86/kernel/.gitignore
@@ -1 +1,2 @@
vsyscall.lds
+vsyscall_32.lds
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 45855c97923e..38573340b143 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -3,3 +3,7 @@ include ${srctree}/arch/x86/kernel/Makefile_32
else
include ${srctree}/arch/x86/kernel/Makefile_64
endif
+
+# Workaround to delete .lds files with make clean
+# The problem is that we do not enter Makefile_32 with make clean.
+clean-files := vsyscall*.lds vsyscall*.so
diff --git a/arch/x86/kernel/Makefile_32 b/arch/x86/kernel/Makefile_32
index 7ff02063b858..a7bc93c27662 100644
--- a/arch/x86/kernel/Makefile_32
+++ b/arch/x86/kernel/Makefile_32
@@ -2,7 +2,8 @@
# Makefile for the linux kernel.
#
-extra-y := head_32.o init_task_32.o vmlinux.lds
+extra-y := head_32.o init_task.o vmlinux.lds
+CPPFLAGS_vmlinux.lds += -Ui386
obj-y := process_32.o signal_32.o entry_32.o traps_32.o irq_32.o \
ptrace_32.o time_32.o ioport_32.o ldt_32.o setup_32.o i8259_32.o sys_i386_32.o \
@@ -17,6 +18,7 @@ obj-$(CONFIG_MCA) += mca_32.o
obj-$(CONFIG_X86_MSR) += msr.o
obj-$(CONFIG_X86_CPUID) += cpuid.o
obj-$(CONFIG_MICROCODE) += microcode.o
+obj-$(CONFIG_PCI) += early-quirks.o
obj-$(CONFIG_APM) += apm_32.o
obj-$(CONFIG_X86_SMP) += smp_32.o smpboot_32.o tsc_sync.o
obj-$(CONFIG_SMP) += smpcommon_32.o
@@ -25,7 +27,7 @@ obj-$(CONFIG_X86_MPPARSE) += mpparse_32.o
obj-$(CONFIG_X86_LOCAL_APIC) += apic_32.o nmi_32.o
obj-$(CONFIG_X86_IO_APIC) += io_apic_32.o
obj-$(CONFIG_X86_REBOOTFIXUPS) += reboot_fixups_32.o
-obj-$(CONFIG_KEXEC) += machine_kexec_32.o relocate_kernel_32.o crash_32.o
+obj-$(CONFIG_KEXEC) += machine_kexec_32.o relocate_kernel_32.o crash.o
obj-$(CONFIG_CRASH_DUMP) += crash_dump_32.o
obj-$(CONFIG_X86_NUMAQ) += numaq_32.o
obj-$(CONFIG_X86_SUMMIT_NUMA) += summit_32.o
@@ -51,7 +53,7 @@ obj-$(CONFIG_SCx200) += scx200_32.o
# We must build both images before we can assemble it.
# Note: kbuild does not track this dependency due to usage of .incbin
$(obj)/vsyscall_32.o: $(obj)/vsyscall-int80_32.so $(obj)/vsyscall-sysenter_32.so
-targets += $(foreach F,int80 sysenter,vsyscall-$F.o vsyscall-$F.so)
+targets += $(foreach F,int80 sysenter,vsyscall-$F_32.o vsyscall-$F_32.so)
targets += vsyscall-note_32.o vsyscall_32.lds
# The DSO images are built using a special linker script.
@@ -59,7 +61,7 @@ quiet_cmd_syscall = SYSCALL $@
cmd_syscall = $(CC) -m elf_i386 -nostdlib $(SYSCFLAGS_$(@F)) \
-Wl,-T,$(filter-out FORCE,$^) -o $@
-export CPPFLAGS_vsyscall_32.lds += -P -C -U$(ARCH)
+export CPPFLAGS_vsyscall_32.lds += -P -C -Ui386
vsyscall-flags = -shared -s -Wl,-soname=linux-gate.so.1 \
$(call ld-option, -Wl$(comma)--hash-style=sysv)
diff --git a/arch/x86/kernel/Makefile_64 b/arch/x86/kernel/Makefile_64
index 43da66213a47..5a88890d8ee9 100644
--- a/arch/x86/kernel/Makefile_64
+++ b/arch/x86/kernel/Makefile_64
@@ -2,34 +2,32 @@
# Makefile for the linux kernel.
#
-extra-y := head_64.o head64.o init_task_64.o vmlinux.lds
+extra-y := head_64.o head64.o init_task.o vmlinux.lds
+CPPFLAGS_vmlinux.lds += -Ux86_64
EXTRA_AFLAGS := -traditional
+
obj-y := process_64.o signal_64.o entry_64.o traps_64.o irq_64.o \
ptrace_64.o time_64.o ioport_64.o ldt_64.o setup_64.o i8259_64.o sys_x86_64.o \
x8664_ksyms_64.o i387_64.o syscall_64.o vsyscall_64.o \
setup64.o bootflag.o e820_64.o reboot_64.o quirks.o i8237.o \
pci-dma_64.o pci-nommu_64.o alternative.o hpet.o tsc_64.o bugs_64.o \
- perfctr-watchdog.o i8253.o
+ i8253.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
-obj-$(CONFIG_X86_MCE) += mce_64.o therm_throt.o
-obj-$(CONFIG_X86_MCE_INTEL) += mce_intel_64.o
-obj-$(CONFIG_X86_MCE_AMD) += mce_amd_64.o
-obj-$(CONFIG_MTRR) += cpu/mtrr/
-obj-$(CONFIG_ACPI) += acpi/
+obj-y += cpu/
+obj-y += acpi/
obj-$(CONFIG_X86_MSR) += msr.o
obj-$(CONFIG_MICROCODE) += microcode.o
obj-$(CONFIG_X86_CPUID) += cpuid.o
obj-$(CONFIG_SMP) += smp_64.o smpboot_64.o trampoline_64.o tsc_sync.o
obj-y += apic_64.o nmi_64.o
obj-y += io_apic_64.o mpparse_64.o genapic_64.o genapic_flat_64.o
-obj-$(CONFIG_KEXEC) += machine_kexec_64.o relocate_kernel_64.o crash_64.o
+obj-$(CONFIG_KEXEC) += machine_kexec_64.o relocate_kernel_64.o crash.o
obj-$(CONFIG_CRASH_DUMP) += crash_dump_64.o
obj-$(CONFIG_PM) += suspend_64.o
obj-$(CONFIG_HIBERNATION) += suspend_asm_64.o
-obj-$(CONFIG_CPU_FREQ) += cpu/cpufreq/
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
-obj-$(CONFIG_IOMMU) += pci-gart_64.o aperture_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_SWIOTLB) += pci-swiotlb_64.o
obj-$(CONFIG_KPROBES) += kprobes_64.o
@@ -39,16 +37,9 @@ obj-$(CONFIG_K8_NB) += k8.o
obj-$(CONFIG_AUDIT) += audit_64.o
obj-$(CONFIG_MODULES) += module_64.o
-obj-$(CONFIG_PCI) += early-quirks_64.o
+obj-$(CONFIG_PCI) += early-quirks.o
obj-y += topology.o
-obj-y += intel_cacheinfo.o
-obj-y += addon_cpuid_features.o
obj-y += pcspeaker.o
CFLAGS_vsyscall_64.o := $(PROFILING) -g0
-
-therm_throt-y += cpu/mcheck/therm_throt.o
-intel_cacheinfo-y += cpu/intel_cacheinfo.o
-addon_cpuid_features-y += cpu/addon_cpuid_features.o
-perfctr-watchdog-y += cpu/perfctr-watchdog.o
diff --git a/arch/x86/kernel/acpi/Makefile b/arch/x86/kernel/acpi/Makefile
index 3d5671939542..1351c3982ee4 100644
--- a/arch/x86/kernel/acpi/Makefile
+++ b/arch/x86/kernel/acpi/Makefile
@@ -1,5 +1,7 @@
-ifeq ($(CONFIG_X86_32),y)
-include ${srctree}/arch/x86/kernel/acpi/Makefile_32
-else
-include ${srctree}/arch/x86/kernel/acpi/Makefile_64
+obj-$(CONFIG_ACPI) += boot.o
+obj-$(CONFIG_ACPI_SLEEP) += sleep_$(BITS).o wakeup_$(BITS).o
+
+ifneq ($(CONFIG_ACPI_PROCESSOR),)
+obj-y += cstate.o processor.o
endif
+
diff --git a/arch/x86/kernel/acpi/Makefile_32 b/arch/x86/kernel/acpi/Makefile_32
deleted file mode 100644
index a4852a2e9190..000000000000
--- a/arch/x86/kernel/acpi/Makefile_32
+++ /dev/null
@@ -1,10 +0,0 @@
-obj-$(CONFIG_ACPI) += boot.o
-ifneq ($(CONFIG_PCI),)
-obj-$(CONFIG_X86_IO_APIC) += earlyquirk_32.o
-endif
-obj-$(CONFIG_ACPI_SLEEP) += sleep_32.o wakeup_32.o
-
-ifneq ($(CONFIG_ACPI_PROCESSOR),)
-obj-y += cstate.o processor.o
-endif
-
diff --git a/arch/x86/kernel/acpi/Makefile_64 b/arch/x86/kernel/acpi/Makefile_64
deleted file mode 100644
index 629425bc002d..000000000000
--- a/arch/x86/kernel/acpi/Makefile_64
+++ /dev/null
@@ -1,7 +0,0 @@
-obj-y := boot.o
-obj-$(CONFIG_ACPI_SLEEP) += sleep_64.o wakeup_64.o
-
-ifneq ($(CONFIG_ACPI_PROCESSOR),)
-obj-y += processor.o cstate.o
-endif
-
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index afd2afe9102d..289247d974c6 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -99,7 +99,7 @@ static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
/*
* The default interrupt routing model is PIC (8259). This gets
- * overriden if IOAPICs are enumerated (below).
+ * overridden if IOAPICs are enumerated (below).
*/
enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_PIC;
@@ -414,8 +414,8 @@ acpi_parse_nmi_src(struct acpi_subtable_header * header, const unsigned long end
*
* Port 0x4d0-4d1 are ECLR1 and ECLR2, the Edge/Level Control Registers
* for the 8259 PIC. bit[n] = 1 means irq[n] is Level, otherwise Edge.
- * ECLR1 is IRQ's 0-7 (IRQ 0, 1, 2 must be 0)
- * ECLR2 is IRQ's 8-15 (IRQ 8, 13 must be 0)
+ * ECLR1 is IRQs 0-7 (IRQ 0, 1, 2 must be 0)
+ * ECLR2 is IRQs 8-15 (IRQ 8, 13 must be 0)
*/
void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
@@ -427,7 +427,7 @@ void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
old = inb(0x4d0) | (inb(0x4d1) << 8);
/*
- * If we use ACPI to set PCI irq's, then we should clear ELCR
+ * If we use ACPI to set PCI IRQs, then we should clear ELCR
* since we will set it correctly as we enable the PCI irq
* routing.
*/
@@ -555,7 +555,7 @@ EXPORT_SYMBOL(acpi_map_lsapic);
int acpi_unmap_lsapic(int cpu)
{
- x86_cpu_to_apicid[cpu] = -1;
+ per_cpu(x86_cpu_to_apicid, cpu) = -1;
cpu_clear(cpu, cpu_present_map);
num_processors--;
diff --git a/arch/x86/kernel/acpi/cstate.c b/arch/x86/kernel/acpi/cstate.c
index 2d39f55d29a8..10b67170b133 100644
--- a/arch/x86/kernel/acpi/cstate.c
+++ b/arch/x86/kernel/acpi/cstate.c
@@ -29,7 +29,7 @@
void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags,
unsigned int cpu)
{
- struct cpuinfo_x86 *c = cpu_data + cpu;
+ struct cpuinfo_x86 *c = &cpu_data(cpu);
flags->bm_check = 0;
if (num_online_cpus() == 1)
@@ -72,7 +72,7 @@ int acpi_processor_ffh_cstate_probe(unsigned int cpu,
struct acpi_processor_cx *cx, struct acpi_power_register *reg)
{
struct cstate_entry *percpu_entry;
- struct cpuinfo_x86 *c = cpu_data + cpu;
+ struct cpuinfo_x86 *c = &cpu_data(cpu);
cpumask_t saved_mask;
int retval;
diff --git a/arch/x86/kernel/acpi/earlyquirk_32.c b/arch/x86/kernel/acpi/earlyquirk_32.c
deleted file mode 100644
index 23f78efc577d..000000000000
--- a/arch/x86/kernel/acpi/earlyquirk_32.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Do early PCI probing for bug detection when the main PCI subsystem is
- * not up yet.
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/acpi.h>
-
-#include <asm/pci-direct.h>
-#include <asm/acpi.h>
-#include <asm/apic.h>
-
-#ifdef CONFIG_ACPI
-
-static int __init nvidia_hpet_check(struct acpi_table_header *header)
-{
- return 0;
-}
-#endif
-
-static int __init check_bridge(int vendor, int device)
-{
-#ifdef CONFIG_ACPI
- static int warned;
- /* According to Nvidia all timer overrides are bogus unless HPET
- is enabled. */
- if (!acpi_use_timer_override && vendor == PCI_VENDOR_ID_NVIDIA) {
- if (!warned && acpi_table_parse(ACPI_SIG_HPET,
- nvidia_hpet_check)) {
- warned = 1;
- acpi_skip_timer_override = 1;
- printk(KERN_INFO "Nvidia board "
- "detected. Ignoring ACPI "
- "timer override.\n");
- printk(KERN_INFO "If you got timer trouble "
- "try acpi_use_timer_override\n");
-
- }
- }
-#endif
- if (vendor == PCI_VENDOR_ID_ATI && timer_over_8254 == 1) {
- timer_over_8254 = 0;
- printk(KERN_INFO "ATI board detected. Disabling timer routing "
- "over 8254.\n");
- }
- return 0;
-}
-
-void __init check_acpi_pci(void)
-{
- int num, slot, func;
-
- /* Assume the machine supports type 1. If not it will
- always read ffffffff and should not have any side effect.
- Actually a few buggy systems can machine check. Allow the user
- to disable it by command line option at least -AK */
- if (!early_pci_allowed())
- return;
-
- /* Poor man's PCI discovery */
- for (num = 0; num < 32; num++) {
- for (slot = 0; slot < 32; slot++) {
- for (func = 0; func < 8; func++) {
- u32 class;
- u32 vendor;
- class = read_pci_config(num, slot, func,
- PCI_CLASS_REVISION);
- if (class == 0xffffffff)
- break;
-
- if ((class >> 16) != PCI_CLASS_BRIDGE_PCI)
- continue;
-
- vendor = read_pci_config(num, slot, func,
- PCI_VENDOR_ID);
-
- if (check_bridge(vendor & 0xffff, vendor >> 16))
- return;
- }
-
- }
- }
-}
diff --git a/arch/x86/kernel/acpi/processor.c b/arch/x86/kernel/acpi/processor.c
index b54fded49834..f63e5ff0aca1 100644
--- a/arch/x86/kernel/acpi/processor.c
+++ b/arch/x86/kernel/acpi/processor.c
@@ -62,8 +62,7 @@ static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c)
/* Initialize _PDC data based on the CPU vendor */
void arch_acpi_processor_init_pdc(struct acpi_processor *pr)
{
- unsigned int cpu = pr->id;
- struct cpuinfo_x86 *c = cpu_data + cpu;
+ struct cpuinfo_x86 *c = &cpu_data(pr->id);
pr->pdc = NULL;
if (c->x86_vendor == X86_VENDOR_INTEL)
diff --git a/arch/x86/kernel/acpi/wakeup_32.S b/arch/x86/kernel/acpi/wakeup_32.S
index f22ba8534d26..a97313b1270e 100644
--- a/arch/x86/kernel/acpi/wakeup_32.S
+++ b/arch/x86/kernel/acpi/wakeup_32.S
@@ -11,7 +11,7 @@
#
# If physical address of wakeup_code is 0x12345, BIOS should call us with
# cs = 0x1234, eip = 0x05
-#
+#
#define BEEP \
inb $97, %al; \
@@ -52,7 +52,6 @@ wakeup_code:
BEEP
1:
mov $(wakeup_stack - wakeup_code), %sp # Private stack is needed for ASUS board
- movw $0x0e00 + 'S', %fs:(0x12)
pushl $0 # Kill any dangerous flags
popfl
@@ -90,9 +89,6 @@ wakeup_code:
# make sure %cr4 is set correctly (features, etc)
movl real_save_cr4 - wakeup_code, %eax
movl %eax, %cr4
- movw $0xb800, %ax
- movw %ax,%fs
- movw $0x0e00 + 'i', %fs:(0x12)
# need a gdt -- use lgdtl to force 32-bit operands, in case
# the GDT is located past 16 megabytes.
@@ -102,8 +98,6 @@ wakeup_code:
movl %eax, %cr0
jmp 1f
1:
- movw $0x0e00 + 'n', %fs:(0x14)
-
movl real_magic - wakeup_code, %eax
cmpl $0x12345678, %eax
jne bogus_real_magic
@@ -122,13 +116,11 @@ real_save_cr4: .long 0
real_magic: .long 0
video_mode: .long 0
realmode_flags: .long 0
-beep_flags: .long 0
real_efer_save_restore: .long 0
real_save_efer_edx: .long 0
real_save_efer_eax: .long 0
bogus_real_magic:
- movw $0x0e00 + 'B', %fs:(0x12)
jmp bogus_real_magic
/* This code uses an extended set of video mode numbers. These include:
@@ -194,7 +186,6 @@ wakeup_pmode_return:
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
- movw $0x0e00 + 'u', 0xb8016
# reload the gdt, as we need the full 32 bit address
lgdt saved_gdt
@@ -218,7 +209,6 @@ wakeup_pmode_return:
jmp *%eax
bogus_magic:
- movw $0x0e00 + 'B', 0xb8018
jmp bogus_magic
diff --git a/arch/x86/kernel/acpi/wakeup_64.S b/arch/x86/kernel/acpi/wakeup_64.S
index 8b4357e1efe0..5ed3bc5c61d7 100644
--- a/arch/x86/kernel/acpi/wakeup_64.S
+++ b/arch/x86/kernel/acpi/wakeup_64.S
@@ -4,6 +4,7 @@
#include <asm/pgtable.h>
#include <asm/page.h>
#include <asm/msr.h>
+#include <asm/asm-offsets.h>
# Copyright 2003 Pavel Machek <pavel@suse.cz>, distribute under GPLv2
#
@@ -41,7 +42,6 @@ wakeup_code:
# Running in *copy* of this code, somewhere in low 1MB.
- movb $0xa1, %al ; outb %al, $0x80
cli
cld
# setup data segment
@@ -65,11 +65,6 @@ wakeup_code:
cmpl $0x12345678, %eax
jne bogus_real_magic
- call verify_cpu # Verify the cpu supports long
- # mode
- testl %eax, %eax
- jnz no_longmode
-
testl $1, realmode_flags - wakeup_code
jz 1f
lcall $0xc000,$3
@@ -84,12 +79,6 @@ wakeup_code:
call mode_set
1:
- movw $0xb800, %ax
- movw %ax,%fs
- movw $0x0e00 + 'L', %fs:(0x10)
-
- movb $0xa2, %al ; outb %al, $0x80
-
mov %ds, %ax # Find 32bit wakeup_code addr
movzx %ax, %esi # (Convert %ds:gdt to a liner ptr)
shll $4, %esi
@@ -117,14 +106,10 @@ wakeup_32_vector:
.code32
wakeup_32:
# Running in this code, but at low address; paging is not yet turned on.
- movb $0xa5, %al ; outb %al, $0x80
movl $__KERNEL_DS, %eax
movl %eax, %ds
- movw $0x0e00 + 'i', %ds:(0xb8012)
- movb $0xa8, %al ; outb %al, $0x80;
-
/*
* Prepare for entering 64bits mode
*/
@@ -200,16 +185,11 @@ wakeup_long64:
*/
lgdt cpu_gdt_descr
- movw $0x0e00 + 'n', %ds:(0xb8014)
- movb $0xa9, %al ; outb %al, $0x80
-
movq saved_magic, %rax
movq $0x123456789abcdef0, %rdx
cmpq %rdx, %rax
jne bogus_64_magic
- movw $0x0e00 + 'u', %ds:(0xb8016)
-
nop
nop
movw $__KERNEL_DS, %ax
@@ -220,13 +200,11 @@ wakeup_long64:
movw %ax, %gs
movq saved_rsp, %rsp
- movw $0x0e00 + 'x', %ds:(0xb8018)
movq saved_rbx, %rbx
movq saved_rdi, %rdi
movq saved_rsi, %rsi
movq saved_rbp, %rbp
- movw $0x0e00 + '!', %ds:(0xb801a)
movq saved_rip, %rax
jmp *%rax
@@ -256,21 +234,12 @@ realmode_flags: .quad 0
.code16
bogus_real_magic:
- movb $0xba,%al ; outb %al,$0x80
jmp bogus_real_magic
.code64
bogus_64_magic:
- movb $0xb3,%al ; outb %al,$0x80
jmp bogus_64_magic
-.code16
-no_longmode:
- movb $0xbc,%al ; outb %al,$0x80
- jmp no_longmode
-
-#include "../verify_cpu_64.S"
-
/* This code uses an extended set of video mode numbers. These include:
* Aliases for standard modes
* NORMAL_VGA (-1)
@@ -374,31 +343,32 @@ do_suspend_lowlevel:
xorl %eax, %eax
call save_processor_state
- movq %rsp, saved_context_esp(%rip)
- movq %rax, saved_context_eax(%rip)
- movq %rbx, saved_context_ebx(%rip)
- movq %rcx, saved_context_ecx(%rip)
- movq %rdx, saved_context_edx(%rip)
- movq %rbp, saved_context_ebp(%rip)
- movq %rsi, saved_context_esi(%rip)
- movq %rdi, saved_context_edi(%rip)
- movq %r8, saved_context_r08(%rip)
- movq %r9, saved_context_r09(%rip)
- movq %r10, saved_context_r10(%rip)
- movq %r11, saved_context_r11(%rip)
- movq %r12, saved_context_r12(%rip)
- movq %r13, saved_context_r13(%rip)
- movq %r14, saved_context_r14(%rip)
- movq %r15, saved_context_r15(%rip)
- pushfq ; popq saved_context_eflags(%rip)
+ movq $saved_context, %rax
+ movq %rsp, pt_regs_rsp(%rax)
+ movq %rbp, pt_regs_rbp(%rax)
+ movq %rsi, pt_regs_rsi(%rax)
+ movq %rdi, pt_regs_rdi(%rax)
+ movq %rbx, pt_regs_rbx(%rax)
+ movq %rcx, pt_regs_rcx(%rax)
+ movq %rdx, pt_regs_rdx(%rax)
+ movq %r8, pt_regs_r8(%rax)
+ movq %r9, pt_regs_r9(%rax)
+ movq %r10, pt_regs_r10(%rax)
+ movq %r11, pt_regs_r11(%rax)
+ movq %r12, pt_regs_r12(%rax)
+ movq %r13, pt_regs_r13(%rax)
+ movq %r14, pt_regs_r14(%rax)
+ movq %r15, pt_regs_r15(%rax)
+ pushfq
+ popq pt_regs_eflags(%rax)
movq $.L97, saved_rip(%rip)
- movq %rsp,saved_rsp
- movq %rbp,saved_rbp
- movq %rbx,saved_rbx
- movq %rdi,saved_rdi
- movq %rsi,saved_rsi
+ movq %rsp, saved_rsp
+ movq %rbp, saved_rbp
+ movq %rbx, saved_rbx
+ movq %rdi, saved_rdi
+ movq %rsi, saved_rsi
addq $8, %rsp
movl $3, %edi
@@ -409,32 +379,35 @@ do_suspend_lowlevel:
.L99:
.align 4
movl $24, %eax
- movw %ax, %ds
- movq saved_context+58(%rip), %rax
- movq %rax, %cr4
- movq saved_context+50(%rip), %rax
- movq %rax, %cr3
- movq saved_context+42(%rip), %rax
- movq %rax, %cr2
- movq saved_context+34(%rip), %rax
- movq %rax, %cr0
- pushq saved_context_eflags(%rip) ; popfq
- movq saved_context_esp(%rip), %rsp
- movq saved_context_ebp(%rip), %rbp
- movq saved_context_eax(%rip), %rax
- movq saved_context_ebx(%rip), %rbx
- movq saved_context_ecx(%rip), %rcx
- movq saved_context_edx(%rip), %rdx
- movq saved_context_esi(%rip), %rsi
- movq saved_context_edi(%rip), %rdi
- movq saved_context_r08(%rip), %r8
- movq saved_context_r09(%rip), %r9
- movq saved_context_r10(%rip), %r10
- movq saved_context_r11(%rip), %r11
- movq saved_context_r12(%rip), %r12
- movq saved_context_r13(%rip), %r13
- movq saved_context_r14(%rip), %r14
- movq saved_context_r15(%rip), %r15
+ movw %ax, %ds
+
+ /* We don't restore %rax, it must be 0 anyway */
+ movq $saved_context, %rax
+ movq saved_context_cr4(%rax), %rbx
+ movq %rbx, %cr4
+ movq saved_context_cr3(%rax), %rbx
+ movq %rbx, %cr3
+ movq saved_context_cr2(%rax), %rbx
+ movq %rbx, %cr2
+ movq saved_context_cr0(%rax), %rbx
+ movq %rbx, %cr0
+ pushq pt_regs_eflags(%rax)
+ popfq
+ movq pt_regs_rsp(%rax), %rsp
+ movq pt_regs_rbp(%rax), %rbp
+ movq pt_regs_rsi(%rax), %rsi
+ movq pt_regs_rdi(%rax), %rdi
+ movq pt_regs_rbx(%rax), %rbx
+ movq pt_regs_rcx(%rax), %rcx
+ movq pt_regs_rdx(%rax), %rdx
+ movq pt_regs_r8(%rax), %r8
+ movq pt_regs_r9(%rax), %r9
+ movq pt_regs_r10(%rax), %r10
+ movq pt_regs_r11(%rax), %r11
+ movq pt_regs_r12(%rax), %r12
+ movq pt_regs_r13(%rax), %r13
+ movq pt_regs_r14(%rax), %r14
+ movq pt_regs_r15(%rax), %r15
xorl %eax, %eax
addq $8, %rsp
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index 11b03d3c6fda..d6405e0842b5 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -63,11 +63,11 @@ __setup("noreplace-paravirt", setup_noreplace_paravirt);
/* Use inline assembly to define this because the nops are defined
as inline assembly strings in the include files and we cannot
get them easily into strings. */
-asm("\t.data\nintelnops: "
+asm("\t.section .rodata, \"a\"\nintelnops: "
GENERIC_NOP1 GENERIC_NOP2 GENERIC_NOP3 GENERIC_NOP4 GENERIC_NOP5 GENERIC_NOP6
GENERIC_NOP7 GENERIC_NOP8);
-extern unsigned char intelnops[];
-static unsigned char *intel_nops[ASM_NOP_MAX+1] = {
+extern const unsigned char intelnops[];
+static const unsigned char *const intel_nops[ASM_NOP_MAX+1] = {
NULL,
intelnops,
intelnops + 1,
@@ -81,11 +81,11 @@ static unsigned char *intel_nops[ASM_NOP_MAX+1] = {
#endif
#ifdef K8_NOP1
-asm("\t.data\nk8nops: "
+asm("\t.section .rodata, \"a\"\nk8nops: "
K8_NOP1 K8_NOP2 K8_NOP3 K8_NOP4 K8_NOP5 K8_NOP6
K8_NOP7 K8_NOP8);
-extern unsigned char k8nops[];
-static unsigned char *k8_nops[ASM_NOP_MAX+1] = {
+extern const unsigned char k8nops[];
+static const unsigned char *const k8_nops[ASM_NOP_MAX+1] = {
NULL,
k8nops,
k8nops + 1,
@@ -99,11 +99,11 @@ static unsigned char *k8_nops[ASM_NOP_MAX+1] = {
#endif
#ifdef K7_NOP1
-asm("\t.data\nk7nops: "
+asm("\t.section .rodata, \"a\"\nk7nops: "
K7_NOP1 K7_NOP2 K7_NOP3 K7_NOP4 K7_NOP5 K7_NOP6
K7_NOP7 K7_NOP8);
-extern unsigned char k7nops[];
-static unsigned char *k7_nops[ASM_NOP_MAX+1] = {
+extern const unsigned char k7nops[];
+static const unsigned char *const k7_nops[ASM_NOP_MAX+1] = {
NULL,
k7nops,
k7nops + 1,
@@ -116,28 +116,49 @@ static unsigned char *k7_nops[ASM_NOP_MAX+1] = {
};
#endif
+#ifdef P6_NOP1
+asm("\t.section .rodata, \"a\"\np6nops: "
+ P6_NOP1 P6_NOP2 P6_NOP3 P6_NOP4 P6_NOP5 P6_NOP6
+ P6_NOP7 P6_NOP8);
+extern const unsigned char p6nops[];
+static const unsigned char *const p6_nops[ASM_NOP_MAX+1] = {
+ NULL,
+ p6nops,
+ p6nops + 1,
+ p6nops + 1 + 2,
+ p6nops + 1 + 2 + 3,
+ p6nops + 1 + 2 + 3 + 4,
+ p6nops + 1 + 2 + 3 + 4 + 5,
+ p6nops + 1 + 2 + 3 + 4 + 5 + 6,
+ p6nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
+};
+#endif
+
#ifdef CONFIG_X86_64
extern char __vsyscall_0;
-static inline unsigned char** find_nop_table(void)
+static inline const unsigned char*const * find_nop_table(void)
{
- return k8_nops;
+ return boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
+ boot_cpu_data.x86 < 6 ? k8_nops : p6_nops;
}
#else /* CONFIG_X86_64 */
-static struct nop {
+static const struct nop {
int cpuid;
- unsigned char **noptable;
+ const unsigned char *const *noptable;
} noptypes[] = {
{ X86_FEATURE_K8, k8_nops },
{ X86_FEATURE_K7, k7_nops },
+ { X86_FEATURE_P4, p6_nops },
+ { X86_FEATURE_P3, p6_nops },
{ -1, NULL }
};
-static unsigned char** find_nop_table(void)
+static const unsigned char*const * find_nop_table(void)
{
- unsigned char **noptable = intel_nops;
+ const unsigned char *const *noptable = intel_nops;
int i;
for (i = 0; noptypes[i].cpuid >= 0; i++) {
@@ -154,7 +175,7 @@ static unsigned char** find_nop_table(void)
/* Use this to add nops to a buffer, then text_poke the whole buffer. */
static void add_nops(void *insns, unsigned int len)
{
- unsigned char **noptable = find_nop_table();
+ const unsigned char *const *noptable = find_nop_table();
while (len > 0) {
unsigned int noplen = len;
@@ -336,14 +357,14 @@ void alternatives_smp_switch(int smp)
if (smp) {
printk(KERN_INFO "SMP alternatives: switching to SMP code\n");
clear_bit(X86_FEATURE_UP, boot_cpu_data.x86_capability);
- clear_bit(X86_FEATURE_UP, cpu_data[0].x86_capability);
+ clear_bit(X86_FEATURE_UP, cpu_data(0).x86_capability);
list_for_each_entry(mod, &smp_alt_modules, next)
alternatives_smp_lock(mod->locks, mod->locks_end,
mod->text, mod->text_end);
} else {
printk(KERN_INFO "SMP alternatives: switching to UP code\n");
set_bit(X86_FEATURE_UP, boot_cpu_data.x86_capability);
- set_bit(X86_FEATURE_UP, cpu_data[0].x86_capability);
+ set_bit(X86_FEATURE_UP, cpu_data(0).x86_capability);
list_for_each_entry(mod, &smp_alt_modules, next)
alternatives_smp_unlock(mod->locks, mod->locks_end,
mod->text, mod->text_end);
@@ -369,8 +390,8 @@ void apply_paravirt(struct paravirt_patch_site *start,
BUG_ON(p->len > MAX_PATCH_LEN);
/* prep the buffer with the original instructions */
memcpy(insnbuf, p->instr, p->len);
- used = paravirt_ops.patch(p->instrtype, p->clobbers, insnbuf,
- (unsigned long)p->instr, p->len);
+ used = pv_init_ops.patch(p->instrtype, p->clobbers, insnbuf,
+ (unsigned long)p->instr, p->len);
BUG_ON(used > p->len);
@@ -411,13 +432,10 @@ void __init alternative_instructions(void)
if (1 == num_possible_cpus()) {
printk(KERN_INFO "SMP alternatives: switching to UP code\n");
set_bit(X86_FEATURE_UP, boot_cpu_data.x86_capability);
- set_bit(X86_FEATURE_UP, cpu_data[0].x86_capability);
+ set_bit(X86_FEATURE_UP, cpu_data(0).x86_capability);
alternatives_smp_unlock(__smp_locks, __smp_locks_end,
_text, _etext);
}
- free_init_pages("SMP alternatives",
- (unsigned long)__smp_locks,
- (unsigned long)__smp_locks_end);
} else {
alternatives_smp_module_add(NULL, "core kernel",
__smp_locks, __smp_locks_end,
@@ -428,6 +446,11 @@ void __init alternative_instructions(void)
apply_paravirt(__parainstructions, __parainstructions_end);
local_irq_restore(flags);
+ if (smp_alt_once)
+ free_init_pages("SMP alternatives",
+ (unsigned long)__smp_locks,
+ (unsigned long)__smp_locks_end);
+
restart_nmi();
#ifdef CONFIG_X86_MCE
restart_mce();
diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c
index 8f681cae7bf7..5b6992799c9d 100644
--- a/arch/x86/kernel/aperture_64.c
+++ b/arch/x86/kernel/aperture_64.c
@@ -20,14 +20,14 @@
#include <linux/ioport.h>
#include <asm/e820.h>
#include <asm/io.h>
-#include <asm/iommu.h>
+#include <asm/gart.h>
#include <asm/pci-direct.h>
#include <asm/dma.h>
#include <asm/k8.h>
-int iommu_aperture;
-int iommu_aperture_disabled __initdata = 0;
-int iommu_aperture_allowed __initdata = 0;
+int gart_iommu_aperture;
+int gart_iommu_aperture_disabled __initdata = 0;
+int gart_iommu_aperture_allowed __initdata = 0;
int fallback_aper_order __initdata = 1; /* 64MB */
int fallback_aper_force __initdata = 0;
@@ -204,14 +204,15 @@ static __u32 __init search_agp_bridge(u32 *order, int *valid_agp)
return 0;
}
-void __init iommu_hole_init(void)
+void __init gart_iommu_hole_init(void)
{
int fix, num;
u32 aper_size, aper_alloc = 0, aper_order = 0, last_aper_order = 0;
u64 aper_base, last_aper_base = 0;
int valid_agp = 0;
- if (iommu_aperture_disabled || !fix_aperture || !early_pci_allowed())
+ if (gart_iommu_aperture_disabled || !fix_aperture ||
+ !early_pci_allowed())
return;
printk(KERN_INFO "Checking aperture...\n");
@@ -222,7 +223,7 @@ void __init iommu_hole_init(void)
continue;
iommu_detected = 1;
- iommu_aperture = 1;
+ gart_iommu_aperture = 1;
aper_order = (read_pci_config(0, num, 3, 0x90) >> 1) & 7;
aper_size = (32 * 1024 * 1024) << aper_order;
diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c
index 3d67ae18d762..08b07c176962 100644
--- a/arch/x86/kernel/apic_32.c
+++ b/arch/x86/kernel/apic_32.c
@@ -947,7 +947,7 @@ void __devinit setup_local_APIC(void)
* Set up LVT0, LVT1:
*
* set up through-local-APIC on the BP's LINT0. This is not
- * strictly necessery in pure symmetric-IO mode, but sometimes
+ * strictly necessary in pure symmetric-IO mode, but sometimes
* we delegate interrupts to the 8259A.
*/
/*
@@ -998,7 +998,7 @@ void __devinit setup_local_APIC(void)
} else {
if (esr_disable)
/*
- * Something untraceble is creating bad interrupts on
+ * Something untraceable is creating bad interrupts on
* secondary quads ... for the moment, just leave the
* ESR disabled - we can't do anything useful with the
* errors anyway - mbligh
@@ -1277,6 +1277,7 @@ void smp_spurious_interrupt(struct pt_regs *regs)
/* see sw-dev-man vol 3, chapter 7.4.13.5 */
printk(KERN_INFO "spurious APIC interrupt on CPU#%d, "
"should never happen.\n", smp_processor_id());
+ __get_cpu_var(irq_stat).irq_spurious_count++;
irq_exit();
}
diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c
index 09b82093bc75..f28ccb588fba 100644
--- a/arch/x86/kernel/apic_64.c
+++ b/arch/x86/kernel/apic_64.c
@@ -287,6 +287,20 @@ void disable_local_APIC(void)
apic_write(APIC_SPIV, value);
}
+void lapic_shutdown(void)
+{
+ unsigned long flags;
+
+ if (!cpu_has_apic)
+ return;
+
+ local_irq_save(flags);
+
+ disable_local_APIC();
+
+ local_irq_restore(flags);
+}
+
/*
* This is to verify that we're looking at a real local APIC.
* Check these against your board if the CPUs aren't getting
@@ -974,15 +988,12 @@ void __init setup_boot_APIC_clock (void)
*/
void __cpuinit check_boot_apic_timer_broadcast(void)
{
- struct clock_event_device *levt = &per_cpu(lapic_events, boot_cpu_id);
-
if (!disable_apic_timer ||
(lapic_clockevent.features & CLOCK_EVT_FEAT_DUMMY))
return;
printk(KERN_INFO "AMD C1E detected late. Force timer broadcast.\n");
lapic_clockevent.features |= CLOCK_EVT_FEAT_DUMMY;
- levt->features |= CLOCK_EVT_FEAT_DUMMY;
local_irq_enable();
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_FORCE, &boot_cpu_id);
@@ -1143,6 +1154,7 @@ asmlinkage void smp_spurious_interrupt(void)
if (v & (1 << (SPURIOUS_APIC_VECTOR & 0x1f)))
ack_APIC_irq();
+ add_pda(irq_spurious_count, 1);
irq_exit();
}
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c
index 32f2365c26ed..17089a041028 100644
--- a/arch/x86/kernel/apm_32.c
+++ b/arch/x86/kernel/apm_32.c
@@ -57,7 +57,7 @@
* screen-blanking and gpm (Stephen Rothwell); Linux 1.99.4
* 1.2a:Simple change to stop mysterious bug reports with SMP also added
* levels to the printk calls. APM is not defined for SMP machines.
- * The new replacment for it is, but Linux doesn't yet support this.
+ * The new replacement for it is, but Linux doesn't yet support this.
* Alan Cox Linux 2.1.55
* 1.3: Set up a valid data descriptor 0x40 for buggy BIOS's
* 1.4: Upgraded to support APM 1.2. Integrated ThinkPad suspend patch by
diff --git a/arch/x86/kernel/asm-offsets_32.c b/arch/x86/kernel/asm-offsets_32.c
index 8029742c0fc1..0e45981b2dd7 100644
--- a/arch/x86/kernel/asm-offsets_32.c
+++ b/arch/x86/kernel/asm-offsets_32.c
@@ -15,6 +15,7 @@
#include <asm/fixmap.h>
#include <asm/processor.h>
#include <asm/thread_info.h>
+#include <asm/bootparam.h>
#include <asm/elf.h>
#include <xen/interface/xen.h>
@@ -116,12 +117,14 @@ void foo(void)
#ifdef CONFIG_PARAVIRT
BLANK();
- OFFSET(PARAVIRT_enabled, paravirt_ops, paravirt_enabled);
- OFFSET(PARAVIRT_irq_disable, paravirt_ops, irq_disable);
- OFFSET(PARAVIRT_irq_enable, paravirt_ops, irq_enable);
- OFFSET(PARAVIRT_irq_enable_sysexit, paravirt_ops, irq_enable_sysexit);
- OFFSET(PARAVIRT_iret, paravirt_ops, iret);
- OFFSET(PARAVIRT_read_cr0, paravirt_ops, read_cr0);
+ OFFSET(PARAVIRT_enabled, pv_info, paravirt_enabled);
+ OFFSET(PARAVIRT_PATCH_pv_cpu_ops, paravirt_patch_template, pv_cpu_ops);
+ OFFSET(PARAVIRT_PATCH_pv_irq_ops, paravirt_patch_template, pv_irq_ops);
+ OFFSET(PV_IRQ_irq_disable, pv_irq_ops, irq_disable);
+ OFFSET(PV_IRQ_irq_enable, pv_irq_ops, irq_enable);
+ OFFSET(PV_CPU_iret, pv_cpu_ops, iret);
+ OFFSET(PV_CPU_irq_enable_sysexit, pv_cpu_ops, irq_enable_sysexit);
+ OFFSET(PV_CPU_read_cr0, pv_cpu_ops, read_cr0);
#endif
#ifdef CONFIG_XEN
@@ -133,6 +136,7 @@ void foo(void)
#ifdef CONFIG_LGUEST_GUEST
BLANK();
OFFSET(LGUEST_DATA_irq_enabled, lguest_data, irq_enabled);
+ OFFSET(LGUEST_DATA_pgdir, lguest_data, pgdir);
OFFSET(LGUEST_PAGES_host_gdt_desc, lguest_pages, state.host_gdt_desc);
OFFSET(LGUEST_PAGES_host_idt_desc, lguest_pages, state.host_idt_desc);
OFFSET(LGUEST_PAGES_host_cr3, lguest_pages, state.host_cr3);
@@ -144,4 +148,10 @@ void foo(void)
OFFSET(LGUEST_PAGES_regs_errcode, lguest_pages, regs.errcode);
OFFSET(LGUEST_PAGES_regs, lguest_pages, regs);
#endif
+
+ BLANK();
+ OFFSET(BP_scratch, boot_params, scratch);
+ OFFSET(BP_loadflags, boot_params, hdr.loadflags);
+ OFFSET(BP_hardware_subarch, boot_params, hdr.hardware_subarch);
+ OFFSET(BP_version, boot_params, hdr.version);
}
diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c
index 778953bc636c..d1b6ed98774e 100644
--- a/arch/x86/kernel/asm-offsets_64.c
+++ b/arch/x86/kernel/asm-offsets_64.c
@@ -15,12 +15,16 @@
#include <asm/segment.h>
#include <asm/thread_info.h>
#include <asm/ia32.h>
+#include <asm/bootparam.h>
#define DEFINE(sym, val) \
asm volatile("\n->" #sym " %0 " #val : : "i" (val))
#define BLANK() asm volatile("\n->" : : )
+#define OFFSET(sym, str, mem) \
+ DEFINE(sym, offsetof(struct str, mem))
+
#define __NO_STUBS 1
#undef __SYSCALL
#undef _ASM_X86_64_UNISTD_H_
@@ -76,10 +80,44 @@ int main(void)
DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address));
DEFINE(pbe_next, offsetof(struct pbe, next));
BLANK();
+#define ENTRY(entry) DEFINE(pt_regs_ ## entry, offsetof(struct pt_regs, entry))
+ ENTRY(rbx);
+ ENTRY(rbx);
+ ENTRY(rcx);
+ ENTRY(rdx);
+ ENTRY(rsp);
+ ENTRY(rbp);
+ ENTRY(rsi);
+ ENTRY(rdi);
+ ENTRY(r8);
+ ENTRY(r9);
+ ENTRY(r10);
+ ENTRY(r11);
+ ENTRY(r12);
+ ENTRY(r13);
+ ENTRY(r14);
+ ENTRY(r15);
+ ENTRY(eflags);
+ BLANK();
+#undef ENTRY
+#define ENTRY(entry) DEFINE(saved_context_ ## entry, offsetof(struct saved_context, entry))
+ ENTRY(cr0);
+ ENTRY(cr2);
+ ENTRY(cr3);
+ ENTRY(cr4);
+ ENTRY(cr8);
+ BLANK();
+#undef ENTRY
DEFINE(TSS_ist, offsetof(struct tss_struct, ist));
BLANK();
DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx));
BLANK();
DEFINE(__NR_syscall_max, sizeof(syscalls) - 1);
+
+ BLANK();
+ OFFSET(BP_scratch, boot_params, scratch);
+ OFFSET(BP_loadflags, boot_params, hdr.loadflags);
+ OFFSET(BP_hardware_subarch, boot_params, hdr.hardware_subarch);
+ OFFSET(BP_version, boot_params, hdr.version);
return 0;
}
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
index 778396c78d65..cfdb2f3bd763 100644
--- a/arch/x86/kernel/cpu/Makefile
+++ b/arch/x86/kernel/cpu/Makefile
@@ -2,19 +2,19 @@
# Makefile for x86-compatible CPU details and quirks
#
-obj-y := common.o proc.o bugs.o
+obj-y := intel_cacheinfo.o addon_cpuid_features.o
-obj-y += amd.o
-obj-y += cyrix.o
-obj-y += centaur.o
-obj-y += transmeta.o
-obj-y += intel.o intel_cacheinfo.o addon_cpuid_features.o
-obj-y += nexgen.o
-obj-y += umc.o
+obj-$(CONFIG_X86_32) += common.o proc.o bugs.o
+obj-$(CONFIG_X86_32) += amd.o
+obj-$(CONFIG_X86_32) += cyrix.o
+obj-$(CONFIG_X86_32) += centaur.o
+obj-$(CONFIG_X86_32) += transmeta.o
+obj-$(CONFIG_X86_32) += intel.o
+obj-$(CONFIG_X86_32) += nexgen.o
+obj-$(CONFIG_X86_32) += umc.o
-obj-$(CONFIG_X86_MCE) += mcheck/
-
-obj-$(CONFIG_MTRR) += mtrr/
-obj-$(CONFIG_CPU_FREQ) += cpufreq/
+obj-$(CONFIG_X86_MCE) += mcheck/
+obj-$(CONFIG_MTRR) += mtrr/
+obj-$(CONFIG_CPU_FREQ) += cpufreq/
obj-$(CONFIG_X86_LOCAL_APIC) += perfctr-watchdog.o
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index dcf6bbb1c7c0..1ff88c7f45cf 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -4,6 +4,7 @@
#include <asm/io.h>
#include <asm/processor.h>
#include <asm/apic.h>
+#include <asm/mach_apic.h>
#include "cpu.h"
@@ -45,13 +46,17 @@ static __cpuinit int amd_apic_timer_broken(void)
case CPUID_XFAM_10H:
case CPUID_XFAM_11H:
rdmsr(MSR_K8_ENABLE_C1E, lo, hi);
- if (lo & ENABLE_C1E_MASK)
+ if (lo & ENABLE_C1E_MASK) {
+ if (smp_processor_id() != boot_cpu_physical_apicid)
+ printk(KERN_INFO "AMD C1E detected late. "
+ " Force timer broadcast.\n");
return 1;
- break;
- default:
- /* err on the side of caution */
+ }
+ break;
+ default:
+ /* err on the side of caution */
return 1;
- }
+ }
return 0;
}
#endif
@@ -261,7 +266,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
#ifdef CONFIG_X86_HT
/*
* On a AMD multi core setup the lower bits of the APIC id
- * distingush the cores.
+ * distinguish the cores.
*/
if (c->x86_max_cores > 1) {
int cpu = smp_processor_id();
diff --git a/arch/x86/kernel/cpu/centaur.c b/arch/x86/kernel/cpu/centaur.c
index 473eac883c7b..9681fa15ddf0 100644
--- a/arch/x86/kernel/cpu/centaur.c
+++ b/arch/x86/kernel/cpu/centaur.c
@@ -53,7 +53,7 @@ static u32 __cpuinit ramtop(void) /* 16388 */
continue;
/*
* Don't MCR over reserved space. Ignore the ISA hole
- * we frob around that catastrophy already
+ * we frob around that catastrophe already
*/
if (e820.map[i].type == E820_RESERVED)
@@ -287,7 +287,7 @@ static void __cpuinit init_c3(struct cpuinfo_x86 *c)
c->x86_capability[5] = cpuid_edx(0xC0000001);
}
- /* Cyrix III family needs CX8 & PGE explicity enabled. */
+ /* Cyrix III family needs CX8 & PGE explicitly enabled. */
if (c->x86_model >=6 && c->x86_model <= 9) {
rdmsr (MSR_VIA_FCR, lo, hi);
lo |= (1<<1 | 1<<7);
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index d506201d397c..e2fcf2051bdb 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -207,7 +207,7 @@ static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c, int early)
static int __init x86_fxsr_setup(char * s)
{
- /* Tell all the other CPU's to not use it... */
+ /* Tell all the other CPUs to not use it... */
disable_x86_fxsr = 1;
/*
diff --git a/arch/x86/kernel/cpu/cpufreq/Kconfig b/arch/x86/kernel/cpu/cpufreq/Kconfig
index d8c6f132dc7a..151eda0a23fc 100644
--- a/arch/x86/kernel/cpu/cpufreq/Kconfig
+++ b/arch/x86/kernel/cpu/cpufreq/Kconfig
@@ -19,6 +19,9 @@ config X86_ACPI_CPUFREQ
Processor Performance States.
This driver also supports Intel Enhanced Speedstep.
+ To compile this driver as a module, choose M here: the
+ module will be called acpi-cpufreq.
+
For details, take a look at <file:Documentation/cpu-freq/>.
If in doubt, say N.
@@ -26,7 +29,7 @@ config X86_ACPI_CPUFREQ
config ELAN_CPUFREQ
tristate "AMD Elan SC400 and SC410"
select CPU_FREQ_TABLE
- depends on X86_ELAN
+ depends on X86_32 && X86_ELAN
---help---
This adds the CPUFreq driver for AMD Elan SC400 and SC410
processors.
@@ -42,7 +45,7 @@ config ELAN_CPUFREQ
config SC520_CPUFREQ
tristate "AMD Elan SC520"
select CPU_FREQ_TABLE
- depends on X86_ELAN
+ depends on X86_32 && X86_ELAN
---help---
This adds the CPUFreq driver for AMD Elan SC520 processor.
@@ -54,6 +57,7 @@ config SC520_CPUFREQ
config X86_POWERNOW_K6
tristate "AMD Mobile K6-2/K6-3 PowerNow!"
select CPU_FREQ_TABLE
+ depends on X86_32
help
This adds the CPUFreq driver for mobile AMD K6-2+ and mobile
AMD K6-3+ processors.
@@ -65,6 +69,7 @@ config X86_POWERNOW_K6
config X86_POWERNOW_K7
tristate "AMD Mobile Athlon/Duron PowerNow!"
select CPU_FREQ_TABLE
+ depends on X86_32
help
This adds the CPUFreq driver for mobile AMD K7 mobile processors.
@@ -76,23 +81,27 @@ config X86_POWERNOW_K7_ACPI
bool
depends on X86_POWERNOW_K7 && ACPI_PROCESSOR
depends on !(X86_POWERNOW_K7 = y && ACPI_PROCESSOR = m)
+ depends on X86_32
default y
config X86_POWERNOW_K8
tristate "AMD Opteron/Athlon64 PowerNow!"
select CPU_FREQ_TABLE
- depends on EXPERIMENTAL
help
This adds the CPUFreq driver for mobile AMD Opteron/Athlon64 processors.
+ To compile this driver as a module, choose M here: the
+ module will be called powernow-k8.
+
For details, take a look at <file:Documentation/cpu-freq/>.
If in doubt, say N.
config X86_POWERNOW_K8_ACPI
- bool "ACPI Support"
- select ACPI_PROCESSOR
- depends on ACPI && X86_POWERNOW_K8
+ bool
+ prompt "ACPI Support" if X86_32
+ depends on ACPI && X86_POWERNOW_K8 && ACPI_PROCESSOR
+ depends on !(X86_POWERNOW_K8 = y && ACPI_PROCESSOR = m)
default y
help
This provides access to the K8s Processor Performance States via ACPI.
@@ -104,7 +113,7 @@ config X86_POWERNOW_K8_ACPI
config X86_GX_SUSPMOD
tristate "Cyrix MediaGX/NatSemi Geode Suspend Modulation"
- depends on PCI
+ depends on X86_32 && PCI
help
This add the CPUFreq driver for NatSemi Geode processors which
support suspend modulation.
@@ -114,15 +123,20 @@ config X86_GX_SUSPMOD
If in doubt, say N.
config X86_SPEEDSTEP_CENTRINO
- tristate "Intel Enhanced SpeedStep"
+ tristate "Intel Enhanced SpeedStep (deprecated)"
select CPU_FREQ_TABLE
- select X86_SPEEDSTEP_CENTRINO_TABLE
+ select X86_SPEEDSTEP_CENTRINO_TABLE if X86_32
+ depends on X86_32 || (X86_64 && ACPI_PROCESSOR)
help
+ This is deprecated and this functionality is now merged into
+ acpi_cpufreq (X86_ACPI_CPUFREQ). Use that driver instead of
+ speedstep_centrino.
This adds the CPUFreq driver for Enhanced SpeedStep enabled
- mobile CPUs. This means Intel Pentium M (Centrino) CPUs. However,
- you also need to say Y to "Use ACPI tables to decode..." below
- [which might imply enabling ACPI] if you want to use this driver
- on non-Banias CPUs.
+ mobile CPUs. This means Intel Pentium M (Centrino) CPUs
+ or 64bit enabled Intel Xeons.
+
+ To compile this driver as a module, choose M here: the
+ module will be called speedstep-centrino.
For details, take a look at <file:Documentation/cpu-freq/>.
@@ -130,7 +144,7 @@ config X86_SPEEDSTEP_CENTRINO
config X86_SPEEDSTEP_CENTRINO_TABLE
bool "Built-in tables for Banias CPUs"
- depends on X86_SPEEDSTEP_CENTRINO
+ depends on X86_32 && X86_SPEEDSTEP_CENTRINO
default y
help
Use built-in tables for Banias CPUs if ACPI encoding
@@ -141,6 +155,7 @@ config X86_SPEEDSTEP_CENTRINO_TABLE
config X86_SPEEDSTEP_ICH
tristate "Intel Speedstep on ICH-M chipsets (ioport interface)"
select CPU_FREQ_TABLE
+ depends on X86_32
help
This adds the CPUFreq driver for certain mobile Intel Pentium III
(Coppermine), all mobile Intel Pentium III-M (Tualatin) and all
@@ -154,7 +169,7 @@ config X86_SPEEDSTEP_ICH
config X86_SPEEDSTEP_SMI
tristate "Intel SpeedStep on 440BX/ZX/MX chipsets (SMI interface)"
select CPU_FREQ_TABLE
- depends on EXPERIMENTAL
+ depends on X86_32 && EXPERIMENTAL
help
This adds the CPUFreq driver for certain mobile Intel Pentium III
(Coppermine), all mobile Intel Pentium III-M (Tualatin)
@@ -169,15 +184,24 @@ config X86_P4_CLOCKMOD
select CPU_FREQ_TABLE
help
This adds the CPUFreq driver for Intel Pentium 4 / XEON
- processors.
+ processors. When enabled it will lower CPU temperature by skipping
+ clocks.
+
+ This driver should be only used in exceptional
+ circumstances when very low power is needed because it causes severe
+ slowdowns and noticeable latencies. Normally Speedstep should be used
+ instead.
+
+ To compile this driver as a module, choose M here: the
+ module will be called p4-clockmod.
For details, take a look at <file:Documentation/cpu-freq/>.
- If in doubt, say N.
+ Unless you are absolutely sure say N.
config X86_CPUFREQ_NFORCE2
tristate "nVidia nForce2 FSB changing"
- depends on EXPERIMENTAL
+ depends on X86_32 && EXPERIMENTAL
help
This adds the CPUFreq driver for FSB changing on nVidia nForce2
platforms.
@@ -188,6 +212,7 @@ config X86_CPUFREQ_NFORCE2
config X86_LONGRUN
tristate "Transmeta LongRun"
+ depends on X86_32
help
This adds the CPUFreq driver for Transmeta Crusoe and Efficeon processors
which support LongRun.
@@ -199,7 +224,7 @@ config X86_LONGRUN
config X86_LONGHAUL
tristate "VIA Cyrix III Longhaul"
select CPU_FREQ_TABLE
- depends on ACPI_PROCESSOR
+ depends on X86_32 && ACPI_PROCESSOR
help
This adds the CPUFreq driver for VIA Samuel/CyrixIII,
VIA Cyrix Samuel/C3, VIA Cyrix Ezra and VIA Cyrix Ezra-T
@@ -212,7 +237,7 @@ config X86_LONGHAUL
config X86_E_POWERSAVER
tristate "VIA C7 Enhanced PowerSaver (EXPERIMENTAL)"
select CPU_FREQ_TABLE
- depends on EXPERIMENTAL
+ depends on X86_32 && EXPERIMENTAL
help
This adds the CPUFreq driver for VIA C7 processors.
@@ -233,11 +258,11 @@ config X86_ACPI_CPUFREQ_PROC_INTF
config X86_SPEEDSTEP_LIB
tristate
- default X86_SPEEDSTEP_ICH || X86_SPEEDSTEP_SMI || X86_P4_CLOCKMOD
+ default (X86_SPEEDSTEP_ICH || X86_SPEEDSTEP_SMI || X86_P4_CLOCKMOD)
config X86_SPEEDSTEP_RELAXED_CAP_CHECK
bool "Relaxed speedstep capability checks"
- depends on (X86_SPEEDSTEP_SMI || X86_SPEEDSTEP_ICH)
+ depends on X86_32 && (X86_SPEEDSTEP_SMI || X86_SPEEDSTEP_ICH)
help
Don't perform all checks for a speedstep capable system which would
normally be done. Some ancient or strange systems, though speedstep
diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
index ffd01e5dcb52..fea0af0476b9 100644
--- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
+++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -77,7 +77,7 @@ static unsigned int acpi_pstate_strict;
static int check_est_cpu(unsigned int cpuid)
{
- struct cpuinfo_x86 *cpu = &cpu_data[cpuid];
+ struct cpuinfo_x86 *cpu = &cpu_data(cpuid);
if (cpu->x86_vendor != X86_VENDOR_INTEL ||
!cpu_has(cpu, X86_FEATURE_EST))
@@ -560,7 +560,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
unsigned int cpu = policy->cpu;
struct acpi_cpufreq_data *data;
unsigned int result = 0;
- struct cpuinfo_x86 *c = &cpu_data[policy->cpu];
+ struct cpuinfo_x86 *c = &cpu_data(policy->cpu);
struct acpi_processor_performance *perf;
dprintk("acpi_cpufreq_cpu_init\n");
@@ -595,7 +595,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
dmi_check_system(sw_any_bug_dmi_table);
if (bios_with_sw_any_bug && cpus_weight(policy->cpus) == 1) {
policy->shared_type = CPUFREQ_SHARED_TYPE_ALL;
- policy->cpus = cpu_core_map[cpu];
+ policy->cpus = per_cpu(cpu_core_map, cpu);
}
#endif
diff --git a/arch/x86/kernel/cpu/cpufreq/cpufreq-nforce2.c b/arch/x86/kernel/cpu/cpufreq/cpufreq-nforce2.c
index 32f0bda3fc95..f03e9153618e 100644
--- a/arch/x86/kernel/cpu/cpufreq/cpufreq-nforce2.c
+++ b/arch/x86/kernel/cpu/cpufreq/cpufreq-nforce2.c
@@ -260,7 +260,7 @@ static int nforce2_target(struct cpufreq_policy *policy,
freqs.old = nforce2_get(policy->cpu);
freqs.new = target_fsb * fid * 100;
- freqs.cpu = 0; /* Only one CPU on nForce2 plattforms */
+ freqs.cpu = 0; /* Only one CPU on nForce2 platforms */
if (freqs.old == freqs.new)
return 0;
diff --git a/arch/x86/kernel/cpu/cpufreq/e_powersaver.c b/arch/x86/kernel/cpu/cpufreq/e_powersaver.c
index c11baaf9f2b4..326a4c81f684 100644
--- a/arch/x86/kernel/cpu/cpufreq/e_powersaver.c
+++ b/arch/x86/kernel/cpu/cpufreq/e_powersaver.c
@@ -305,7 +305,7 @@ static struct cpufreq_driver eps_driver = {
static int __init eps_init(void)
{
- struct cpuinfo_x86 *c = cpu_data;
+ struct cpuinfo_x86 *c = &cpu_data(0);
/* This driver will work only on Centaur C7 processors with
* Enhanced SpeedStep/PowerSaver registers */
diff --git a/arch/x86/kernel/cpu/cpufreq/elanfreq.c b/arch/x86/kernel/cpu/cpufreq/elanfreq.c
index 1e7ae7dafcf6..94619c22f563 100644
--- a/arch/x86/kernel/cpu/cpufreq/elanfreq.c
+++ b/arch/x86/kernel/cpu/cpufreq/elanfreq.c
@@ -199,7 +199,7 @@ static int elanfreq_target (struct cpufreq_policy *policy,
static int elanfreq_cpu_init(struct cpufreq_policy *policy)
{
- struct cpuinfo_x86 *c = cpu_data;
+ struct cpuinfo_x86 *c = &cpu_data(0);
unsigned int i;
int result;
@@ -280,7 +280,7 @@ static struct cpufreq_driver elanfreq_driver = {
static int __init elanfreq_init(void)
{
- struct cpuinfo_x86 *c = cpu_data;
+ struct cpuinfo_x86 *c = &cpu_data(0);
/* Test if we have the right hardware */
if ((c->x86_vendor != X86_VENDOR_AMD) ||
diff --git a/arch/x86/kernel/cpu/cpufreq/gx-suspmod.c b/arch/x86/kernel/cpu/cpufreq/gx-suspmod.c
index ed2bda127c44..2ed7db2fd257 100644
--- a/arch/x86/kernel/cpu/cpufreq/gx-suspmod.c
+++ b/arch/x86/kernel/cpu/cpufreq/gx-suspmod.c
@@ -12,12 +12,12 @@
* of any nature resulting due to the use of this software. This
* software is provided AS-IS with no warranties.
*
- * Theoritical note:
+ * Theoretical note:
*
* (see Geode(tm) CS5530 manual (rev.4.1) page.56)
*
* CPU frequency control on NatSemi Geode GX1/GXLV processor and CS55x0
- * are based on Suspend Moduration.
+ * are based on Suspend Modulation.
*
* Suspend Modulation works by asserting and de-asserting the SUSP# pin
* to CPU(GX1/GXLV) for configurable durations. When asserting SUSP#
@@ -101,11 +101,11 @@
/* SUSCFG bits */
#define SUSMOD (1<<0) /* enable/disable suspend modulation */
-/* the belows support only with cs5530 (after rev.1.2)/cs5530A */
+/* the below is supported only with cs5530 (after rev.1.2)/cs5530A */
#define SMISPDUP (1<<1) /* select how SMI re-enable suspend modulation: */
/* IRQTC timer or read SMI speedup disable reg.(F1BAR[08-09h]) */
#define SUSCFG (1<<2) /* enable powering down a GXLV processor. "Special 3Volt Suspend" mode */
-/* the belows support only with cs5530A */
+/* the below is supported only with cs5530A */
#define PWRSVE_ISA (1<<3) /* stop ISA clock */
#define PWRSVE (1<<4) /* active idle */
diff --git a/arch/x86/kernel/cpu/cpufreq/longhaul.c b/arch/x86/kernel/cpu/cpufreq/longhaul.c
index 5045f5d583c8..749d00cb2ebd 100644
--- a/arch/x86/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/x86/kernel/cpu/cpufreq/longhaul.c
@@ -780,7 +780,7 @@ static int longhaul_setup_southbridge(void)
static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
{
- struct cpuinfo_x86 *c = cpu_data;
+ struct cpuinfo_x86 *c = &cpu_data(0);
char *cpuname=NULL;
int ret;
u32 lo, hi;
@@ -959,7 +959,7 @@ static struct cpufreq_driver longhaul_driver = {
static int __init longhaul_init(void)
{
- struct cpuinfo_x86 *c = cpu_data;
+ struct cpuinfo_x86 *c = &cpu_data(0);
if (c->x86_vendor != X86_VENDOR_CENTAUR || c->x86 != 6)
return -ENODEV;
diff --git a/arch/x86/kernel/cpu/cpufreq/longrun.c b/arch/x86/kernel/cpu/cpufreq/longrun.c
index b2689514295a..af4a867a097c 100644
--- a/arch/x86/kernel/cpu/cpufreq/longrun.c
+++ b/arch/x86/kernel/cpu/cpufreq/longrun.c
@@ -172,7 +172,7 @@ static unsigned int __init longrun_determine_freqs(unsigned int *low_freq,
u32 save_lo, save_hi;
u32 eax, ebx, ecx, edx;
u32 try_hi;
- struct cpuinfo_x86 *c = cpu_data;
+ struct cpuinfo_x86 *c = &cpu_data(0);
if (!low_freq || !high_freq)
return -EINVAL;
@@ -298,7 +298,7 @@ static struct cpufreq_driver longrun_driver = {
*/
static int __init longrun_init(void)
{
- struct cpuinfo_x86 *c = cpu_data;
+ struct cpuinfo_x86 *c = &cpu_data(0);
if (c->x86_vendor != X86_VENDOR_TRANSMETA ||
!cpu_has(c, X86_FEATURE_LONGRUN))
diff --git a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c
index 8eb414b906d2..14791ec55cfd 100644
--- a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c
+++ b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c
@@ -195,12 +195,12 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c)
static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
{
- struct cpuinfo_x86 *c = &cpu_data[policy->cpu];
+ struct cpuinfo_x86 *c = &cpu_data(policy->cpu);
int cpuid = 0;
unsigned int i;
#ifdef CONFIG_SMP
- policy->cpus = cpu_sibling_map[policy->cpu];
+ policy->cpus = per_cpu(cpu_sibling_map, policy->cpu);
#endif
/* Errata workaround */
@@ -279,7 +279,7 @@ static struct cpufreq_driver p4clockmod_driver = {
static int __init cpufreq_p4_init(void)
{
- struct cpuinfo_x86 *c = cpu_data;
+ struct cpuinfo_x86 *c = &cpu_data(0);
int ret;
/*
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k6.c b/arch/x86/kernel/cpu/cpufreq/powernow-k6.c
index 6d0285339317..eb9b62b0830c 100644
--- a/arch/x86/kernel/cpu/cpufreq/powernow-k6.c
+++ b/arch/x86/kernel/cpu/cpufreq/powernow-k6.c
@@ -1,6 +1,6 @@
/*
* This file was based upon code in Powertweak Linux (http://powertweak.sf.net)
- * (C) 2000-2003 Dave Jones, Arjan van de Ven, Janne Pänkälä, Dominik Brodowski.
+ * (C) 2000-2003 Dave Jones, Arjan van de Ven, Janne Pänkälä, Dominik Brodowski.
*
* Licensed under the terms of the GNU GPL License version 2.
*
@@ -215,7 +215,7 @@ static struct cpufreq_driver powernow_k6_driver = {
*/
static int __init powernow_k6_init(void)
{
- struct cpuinfo_x86 *c = cpu_data;
+ struct cpuinfo_x86 *c = &cpu_data(0);
if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 != 5) ||
((c->x86_model != 12) && (c->x86_model != 13)))
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k7.c b/arch/x86/kernel/cpu/cpufreq/powernow-k7.c
index 7decd6a50ffa..b5a9863d6cdc 100644
--- a/arch/x86/kernel/cpu/cpufreq/powernow-k7.c
+++ b/arch/x86/kernel/cpu/cpufreq/powernow-k7.c
@@ -114,7 +114,7 @@ static int check_fsb(unsigned int fsbspeed)
static int check_powernow(void)
{
- struct cpuinfo_x86 *c = cpu_data;
+ struct cpuinfo_x86 *c = &cpu_data(0);
unsigned int maxei, eax, ebx, ecx, edx;
if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 !=6)) {
@@ -565,7 +565,7 @@ static unsigned int powernow_get(unsigned int cpu)
}
-static int __init acer_cpufreq_pst(struct dmi_system_id *d)
+static int __init acer_cpufreq_pst(const struct dmi_system_id *d)
{
printk(KERN_WARNING "%s laptop with broken PST tables in BIOS detected.\n", d->ident);
printk(KERN_WARNING "You need to downgrade to 3A21 (09/09/2002), or try a newer BIOS than 3A71 (01/20/2003)\n");
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
index f105ffd09960..99e1ef9939be 100644
--- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
@@ -57,7 +57,7 @@ static struct powernow_k8_data *powernow_data[NR_CPUS];
static int cpu_family = CPU_OPTERON;
#ifndef CONFIG_SMP
-static cpumask_t cpu_core_map[1];
+DEFINE_PER_CPU(cpumask_t, cpu_core_map);
#endif
/* Return a frequency in MHz, given an input fid */
@@ -144,7 +144,7 @@ static void count_off_irt(struct powernow_k8_data *data)
return;
}
-/* the voltage stabalization time */
+/* the voltage stabilization time */
static void count_off_vst(struct powernow_k8_data *data)
{
udelay(data->vstable * VST_UNITS_20US);
@@ -643,7 +643,7 @@ static int fill_powernow_table(struct powernow_k8_data *data, struct pst_s *pst,
dprintk("cfid 0x%x, cvid 0x%x\n", data->currfid, data->currvid);
data->powernow_table = powernow_table;
- if (first_cpu(cpu_core_map[data->cpu]) == data->cpu)
+ if (first_cpu(per_cpu(cpu_core_map, data->cpu)) == data->cpu)
print_basics(data);
for (j = 0; j < data->numps; j++)
@@ -797,7 +797,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
/* fill in data */
data->numps = data->acpi_data.state_count;
- if (first_cpu(cpu_core_map[data->cpu]) == data->cpu)
+ if (first_cpu(per_cpu(cpu_core_map, data->cpu)) == data->cpu)
print_basics(data);
powernow_k8_acpi_pst_values(data, 0);
@@ -1171,7 +1171,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
if (cpu_family == CPU_HW_PSTATE)
pol->cpus = cpumask_of_cpu(pol->cpu);
else
- pol->cpus = cpu_core_map[pol->cpu];
+ pol->cpus = per_cpu(cpu_core_map, pol->cpu);
data->available_cores = &(pol->cpus);
/* Take a crude guess here.
@@ -1237,7 +1237,7 @@ static unsigned int powernowk8_get (unsigned int cpu)
cpumask_t oldmask = current->cpus_allowed;
unsigned int khz = 0;
- data = powernow_data[first_cpu(cpu_core_map[cpu])];
+ data = powernow_data[first_cpu(per_cpu(cpu_core_map, cpu))];
if (!data)
return -EINVAL;
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.h b/arch/x86/kernel/cpu/cpufreq/powernow-k8.h
index 8ae88f181286..afd2b520d35c 100644
--- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.h
+++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.h
@@ -140,10 +140,10 @@ struct powernow_k8_data {
#define PLL_LOCK_CONVERSION (1000/5) /* ms to ns, then divide by clock period */
#define MAXIMUM_VID_STEPS 1 /* Current cpus only allow a single step of 25mV */
-#define VST_UNITS_20US 20 /* Voltage Stabalization Time is in units of 20us */
+#define VST_UNITS_20US 20 /* Voltage Stabilization Time is in units of 20us */
/*
- * Most values of interest are enocoded in a single field of the _PSS
+ * Most values of interest are encoded in a single field of the _PSS
* entries: the "control" value.
*/
diff --git a/arch/x86/kernel/cpu/cpufreq/sc520_freq.c b/arch/x86/kernel/cpu/cpufreq/sc520_freq.c
index d9f3e90a7ae0..42da9bd677d6 100644
--- a/arch/x86/kernel/cpu/cpufreq/sc520_freq.c
+++ b/arch/x86/kernel/cpu/cpufreq/sc520_freq.c
@@ -102,7 +102,7 @@ static int sc520_freq_target (struct cpufreq_policy *policy,
static int sc520_freq_cpu_init(struct cpufreq_policy *policy)
{
- struct cpuinfo_x86 *c = cpu_data;
+ struct cpuinfo_x86 *c = &cpu_data(0);
int result;
/* capability check */
@@ -151,7 +151,7 @@ static struct cpufreq_driver sc520_freq_driver = {
static int __init sc520_freq_init(void)
{
- struct cpuinfo_x86 *c = cpu_data;
+ struct cpuinfo_x86 *c = &cpu_data(0);
int err;
/* Test if we have the right hardware */
diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
index 811d47438546..3031f1196192 100644
--- a/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
+++ b/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
@@ -230,7 +230,7 @@ static struct cpu_model models[] =
static int centrino_cpu_init_table(struct cpufreq_policy *policy)
{
- struct cpuinfo_x86 *cpu = &cpu_data[policy->cpu];
+ struct cpuinfo_x86 *cpu = &cpu_data(policy->cpu);
struct cpu_model *model;
for(model = models; model->cpu_id != NULL; model++)
@@ -340,7 +340,7 @@ static unsigned int get_cur_freq(unsigned int cpu)
static int centrino_cpu_init(struct cpufreq_policy *policy)
{
- struct cpuinfo_x86 *cpu = &cpu_data[policy->cpu];
+ struct cpuinfo_x86 *cpu = &cpu_data(policy->cpu);
unsigned freq;
unsigned l, h;
int ret;
@@ -612,7 +612,7 @@ static struct cpufreq_driver centrino_driver = {
*/
static int __init centrino_init(void)
{
- struct cpuinfo_x86 *cpu = cpu_data;
+ struct cpuinfo_x86 *cpu = &cpu_data(0);
if (!cpu_has(cpu, X86_FEATURE_EST))
return -ENODEV;
diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c b/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c
index 36685e8f7be1..14d68aa301ee 100644
--- a/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c
+++ b/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c
@@ -322,7 +322,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
/* only run on CPU to be set, or on its sibling */
#ifdef CONFIG_SMP
- policy->cpus = cpu_sibling_map[policy->cpu];
+ policy->cpus = per_cpu(cpu_sibling_map, policy->cpu);
#endif
cpus_allowed = current->cpus_allowed;
diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c b/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c
index b1acc8ce3167..76c3ab0da468 100644
--- a/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c
+++ b/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c
@@ -228,7 +228,7 @@ EXPORT_SYMBOL_GPL(speedstep_get_processor_frequency);
unsigned int speedstep_detect_processor (void)
{
- struct cpuinfo_x86 *c = cpu_data;
+ struct cpuinfo_x86 *c = &cpu_data(0);
u32 ebx, msr_lo, msr_hi;
dprintk("x86: %x, model: %x\n", c->x86, c->x86_model);
diff --git a/arch/x86/kernel/cpu/cyrix.c b/arch/x86/kernel/cpu/cyrix.c
index 122d2d75aa9f..88d66fb8411d 100644
--- a/arch/x86/kernel/cpu/cyrix.c
+++ b/arch/x86/kernel/cpu/cyrix.c
@@ -93,7 +93,7 @@ static void __cpuinit check_cx686_slop(struct cpuinfo_x86 *c)
local_irq_save(flags);
ccr3 = getCx86(CX86_CCR3);
- setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */
+ setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */
ccr5 = getCx86(CX86_CCR5);
if (ccr5 & 2)
setCx86(CX86_CCR5, ccr5 & 0xfd); /* reset SLOP */
@@ -115,9 +115,9 @@ static void __cpuinit set_cx86_reorder(void)
printk(KERN_INFO "Enable Memory access reorder on Cyrix/NSC processor.\n");
ccr3 = getCx86(CX86_CCR3);
- setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN  */
+ setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */
- /* Load/Store Serialize to mem access disable (=reorder it)  */
+ /* Load/Store Serialize to mem access disable (=reorder it) */
setCx86(CX86_PCR0, getCx86(CX86_PCR0) & ~0x80);
/* set load/store serialize from 1GB to 4GB */
ccr3 |= 0xe0;
@@ -146,7 +146,7 @@ static void __cpuinit set_cx86_inc(void)
printk(KERN_INFO "Enable Incrementor on Cyrix/NSC processor.\n");
ccr3 = getCx86(CX86_CCR3);
- setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN  */
+ setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */
/* PCR1 -- Performance Control */
/* Incrementor on, whatever that is */
setCx86(CX86_PCR1, getCx86(CX86_PCR1) | 0x02);
@@ -256,7 +256,7 @@ static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
u32 vendor, device;
/* It isn't really a PCI quirk directly, but the cure is the
same. The MediaGX has deep magic SMM stuff that handles the
- SB emulation. It thows away the fifo on disable_dma() which
+ SB emulation. It throws away the fifo on disable_dma() which
is wrong and ruins the audio.
Bug2: VSA1 has a wrap bug so that using maximum sized DMA
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index dc4e08147b1f..cc8c501b9f39 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -8,6 +8,7 @@
#include <linux/module.h>
#include <asm/processor.h>
+#include <asm/pgtable.h>
#include <asm/msr.h>
#include <asm/uaccess.h>
@@ -19,8 +20,6 @@
#include <mach_apic.h>
#endif
-extern int trap_init_f00f_bug(void);
-
#ifdef CONFIG_X86_INTEL_USERCOPY
/*
* Alignment at which movsl is preferred for bulk memory copies.
@@ -95,6 +94,20 @@ static int __cpuinit num_cpu_cores(struct cpuinfo_x86 *c)
return 1;
}
+#ifdef CONFIG_X86_F00F_BUG
+static void __cpuinit trap_init_f00f_bug(void)
+{
+ __set_fixmap(FIX_F00F_IDT, __pa(&idt_table), PAGE_KERNEL_RO);
+
+ /*
+ * Update the IDT descriptor and reload the IDT so that
+ * it uses the read-only mapped virtual address.
+ */
+ idt_descr.address = fix_to_virt(FIX_F00F_IDT);
+ load_idt(&idt_descr);
+}
+#endif
+
static void __cpuinit init_intel(struct cpuinfo_x86 *c)
{
unsigned int l2 = 0;
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c
index db6c25aa5776..9921b01fe199 100644
--- a/arch/x86/kernel/cpu/intel_cacheinfo.c
+++ b/arch/x86/kernel/cpu/intel_cacheinfo.c
@@ -170,15 +170,15 @@ union l3_cache {
unsigned val;
};
-static const unsigned short assocs[] = {
+static unsigned short assocs[] __cpuinitdata = {
[1] = 1, [2] = 2, [4] = 4, [6] = 8,
[8] = 16, [0xa] = 32, [0xb] = 48,
[0xc] = 64,
[0xf] = 0xffff // ??
};
-static const unsigned char levels[] = { 1, 1, 2, 3 };
-static const unsigned char types[] = { 1, 2, 3, 3 };
+static unsigned char levels[] __cpuinitdata = { 1, 1, 2, 3 };
+static unsigned char types[] __cpuinitdata = { 1, 2, 3, 3 };
static void __cpuinit amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax,
union _cpuid4_leaf_ebx *ebx,
@@ -295,7 +295,7 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
unsigned int new_l2 = 0, new_l3 = 0, i; /* Cache sizes from cpuid(4) */
unsigned int l2_id = 0, l3_id = 0, num_threads_sharing, index_msb;
#ifdef CONFIG_X86_HT
- unsigned int cpu = (c == &boot_cpu_data) ? 0 : (c - cpu_data);
+ unsigned int cpu = c->cpu_index;
#endif
if (c->cpuid_level > 3) {
@@ -417,14 +417,14 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
if (new_l2) {
l2 = new_l2;
#ifdef CONFIG_X86_HT
- cpu_llc_id[cpu] = l2_id;
+ per_cpu(cpu_llc_id, cpu) = l2_id;
#endif
}
if (new_l3) {
l3 = new_l3;
#ifdef CONFIG_X86_HT
- cpu_llc_id[cpu] = l3_id;
+ per_cpu(cpu_llc_id, cpu) = l3_id;
#endif
}
@@ -459,7 +459,7 @@ static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
struct _cpuid4_info *this_leaf, *sibling_leaf;
unsigned long num_threads_sharing;
int index_msb, i;
- struct cpuinfo_x86 *c = cpu_data;
+ struct cpuinfo_x86 *c = &cpu_data(cpu);
this_leaf = CPUID4_INFO_IDX(cpu, index);
num_threads_sharing = 1 + this_leaf->eax.split.num_threads_sharing;
@@ -470,8 +470,8 @@ static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
index_msb = get_count_order(num_threads_sharing);
for_each_online_cpu(i) {
- if (c[i].apicid >> index_msb ==
- c[cpu].apicid >> index_msb) {
+ if (cpu_data(i).apicid >> index_msb ==
+ c->apicid >> index_msb) {
cpu_set(i, this_leaf->shared_cpu_map);
if (i != cpu && cpuid4_info[i]) {
sibling_leaf = CPUID4_INFO_IDX(i, index);
@@ -493,12 +493,17 @@ static void __cpuinit cache_remove_shared_cpu_map(unsigned int cpu, int index)
}
}
#else
-static void __init cache_shared_cpu_map_setup(unsigned int cpu, int index) {}
-static void __init cache_remove_shared_cpu_map(unsigned int cpu, int index) {}
+static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index) {}
+static void __cpuinit cache_remove_shared_cpu_map(unsigned int cpu, int index) {}
#endif
static void free_cache_attributes(unsigned int cpu)
{
+ int i;
+
+ for (i = 0; i < num_cache_leaves; i++)
+ cache_remove_shared_cpu_map(cpu, i);
+
kfree(cpuid4_info[cpu]);
cpuid4_info[cpu] = NULL;
}
@@ -506,8 +511,8 @@ static void free_cache_attributes(unsigned int cpu)
static int __cpuinit detect_cache_attributes(unsigned int cpu)
{
struct _cpuid4_info *this_leaf;
- unsigned long j;
- int retval;
+ unsigned long j;
+ int retval;
cpumask_t oldmask;
if (num_cache_leaves == 0)
@@ -524,19 +529,26 @@ static int __cpuinit detect_cache_attributes(unsigned int cpu)
goto out;
/* Do cpuid and store the results */
- retval = 0;
for (j = 0; j < num_cache_leaves; j++) {
this_leaf = CPUID4_INFO_IDX(cpu, j);
retval = cpuid4_cache_lookup(j, this_leaf);
- if (unlikely(retval < 0))
+ if (unlikely(retval < 0)) {
+ int i;
+
+ for (i = 0; i < j; i++)
+ cache_remove_shared_cpu_map(cpu, i);
break;
+ }
cache_shared_cpu_map_setup(cpu, j);
}
set_cpus_allowed(current, oldmask);
out:
- if (retval)
- free_cache_attributes(cpu);
+ if (retval) {
+ kfree(cpuid4_info[cpu]);
+ cpuid4_info[cpu] = NULL;
+ }
+
return retval;
}
@@ -669,7 +681,7 @@ static struct kobj_type ktype_percpu_entry = {
.sysfs_ops = &sysfs_ops,
};
-static void cpuid4_cache_sysfs_exit(unsigned int cpu)
+static void __cpuinit cpuid4_cache_sysfs_exit(unsigned int cpu)
{
kfree(cache_kobject[cpu]);
kfree(index_kobject[cpu]);
@@ -680,13 +692,14 @@ static void cpuid4_cache_sysfs_exit(unsigned int cpu)
static int __cpuinit cpuid4_cache_sysfs_init(unsigned int cpu)
{
+ int err;
if (num_cache_leaves == 0)
return -ENOENT;
- detect_cache_attributes(cpu);
- if (cpuid4_info[cpu] == NULL)
- return -ENOENT;
+ err = detect_cache_attributes(cpu);
+ if (err)
+ return err;
/* Allocate all required memory */
cache_kobject[cpu] = kzalloc(sizeof(struct kobject), GFP_KERNEL);
@@ -705,13 +718,15 @@ err_out:
return -ENOMEM;
}
+static cpumask_t cache_dev_map = CPU_MASK_NONE;
+
/* Add/Remove cache interface for CPU device */
static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
{
unsigned int cpu = sys_dev->id;
unsigned long i, j;
struct _index_kobject *this_object;
- int retval = 0;
+ int retval;
retval = cpuid4_cache_sysfs_init(cpu);
if (unlikely(retval < 0))
@@ -721,6 +736,10 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
kobject_set_name(cache_kobject[cpu], "%s", "cache");
cache_kobject[cpu]->ktype = &ktype_percpu_entry;
retval = kobject_register(cache_kobject[cpu]);
+ if (retval < 0) {
+ cpuid4_cache_sysfs_exit(cpu);
+ return retval;
+ }
for (i = 0; i < num_cache_leaves; i++) {
this_object = INDEX_KOBJECT_PTR(cpu,i);
@@ -740,6 +759,9 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
break;
}
}
+ if (!retval)
+ cpu_set(cpu, cache_dev_map);
+
return retval;
}
@@ -750,13 +772,14 @@ static void __cpuinit cache_remove_dev(struct sys_device * sys_dev)
if (cpuid4_info[cpu] == NULL)
return;
- for (i = 0; i < num_cache_leaves; i++) {
- cache_remove_shared_cpu_map(cpu, i);
+ if (!cpu_isset(cpu, cache_dev_map))
+ return;
+ cpu_clear(cpu, cache_dev_map);
+
+ for (i = 0; i < num_cache_leaves; i++)
kobject_unregister(&(INDEX_KOBJECT_PTR(cpu,i)->kobj));
- }
kobject_unregister(cache_kobject[cpu]);
cpuid4_cache_sysfs_exit(cpu);
- return;
}
static int __cpuinit cacheinfo_cpu_callback(struct notifier_block *nfb,
@@ -781,7 +804,7 @@ static int __cpuinit cacheinfo_cpu_callback(struct notifier_block *nfb,
static struct notifier_block __cpuinitdata cacheinfo_cpu_notifier =
{
- .notifier_call = cacheinfo_cpu_callback,
+ .notifier_call = cacheinfo_cpu_callback,
};
static int __cpuinit cache_sysfs_init(void)
@@ -791,13 +814,15 @@ static int __cpuinit cache_sysfs_init(void)
if (num_cache_leaves == 0)
return 0;
- register_hotcpu_notifier(&cacheinfo_cpu_notifier);
-
for_each_online_cpu(i) {
- cacheinfo_cpu_callback(&cacheinfo_cpu_notifier, CPU_ONLINE,
- (void *)(long)i);
- }
+ int err;
+ struct sys_device *sys_dev = get_cpu_sysdev(i);
+ err = cache_add_dev(sys_dev);
+ if (err)
+ return err;
+ }
+ register_hotcpu_notifier(&cacheinfo_cpu_notifier);
return 0;
}
diff --git a/arch/x86/kernel/cpu/mcheck/Makefile b/arch/x86/kernel/cpu/mcheck/Makefile
index f1ebe1c1c17a..d7d2323bbb69 100644
--- a/arch/x86/kernel/cpu/mcheck/Makefile
+++ b/arch/x86/kernel/cpu/mcheck/Makefile
@@ -1,2 +1,6 @@
-obj-y = mce.o k7.o p4.o p5.o p6.o winchip.o therm_throt.o
-obj-$(CONFIG_X86_MCE_NONFATAL) += non-fatal.o
+obj-y = mce_$(BITS).o therm_throt.o
+
+obj-$(CONFIG_X86_32) += k7.o p4.o p5.o p6.o winchip.o
+obj-$(CONFIG_X86_MCE_INTEL) += mce_intel_64.o
+obj-$(CONFIG_X86_MCE_AMD) += mce_amd_64.o
+obj-$(CONFIG_X86_MCE_NONFATAL) += non-fatal.o
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce_32.c
index 34c781eddee4..34c781eddee4 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_32.c
diff --git a/arch/x86/kernel/mce_64.c b/arch/x86/kernel/cpu/mcheck/mce_64.c
index a66d607f5b92..447b351f1f2a 100644
--- a/arch/x86/kernel/mce_64.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_64.c
@@ -1,8 +1,8 @@
/*
* Machine check handler.
* K8 parts Copyright 2002,2003 Andi Kleen, SuSE Labs.
- * Rest from unknown author(s).
- * 2004 Andi Kleen. Rewrote most of it.
+ * Rest from unknown author(s).
+ * 2004 Andi Kleen. Rewrote most of it.
*/
#include <linux/init.h>
@@ -23,7 +23,7 @@
#include <linux/ctype.h>
#include <linux/kmod.h>
#include <linux/kdebug.h>
-#include <asm/processor.h>
+#include <asm/processor.h>
#include <asm/msr.h>
#include <asm/mce.h>
#include <asm/uaccess.h>
@@ -63,10 +63,10 @@ static DECLARE_WAIT_QUEUE_HEAD(mce_wait);
* separate MCEs from kernel messages to avoid bogus bug reports.
*/
-struct mce_log mcelog = {
+struct mce_log mcelog = {
MCE_LOG_SIGNATURE,
MCE_LOG_LEN,
-};
+};
void mce_log(struct mce *mce)
{
@@ -76,9 +76,6 @@ void mce_log(struct mce *mce)
wmb();
for (;;) {
entry = rcu_dereference(mcelog.next);
- /* The rmb forces the compiler to reload next in each
- iteration */
- rmb();
for (;;) {
/* When the buffer fills up discard new entries. Assume
that the earlier errors are the more interesting. */
@@ -114,42 +111,42 @@ static void print_mce(struct mce *m)
"CPU %d: Machine Check Exception: %16Lx Bank %d: %016Lx\n",
m->cpu, m->mcgstatus, m->bank, m->status);
if (m->rip) {
- printk(KERN_EMERG
- "RIP%s %02x:<%016Lx> ",
+ printk(KERN_EMERG "RIP%s %02x:<%016Lx> ",
!(m->mcgstatus & MCG_STATUS_EIPV) ? " !INEXACT!" : "",
m->cs, m->rip);
if (m->cs == __KERNEL_CS)
print_symbol("{%s}", m->rip);
printk("\n");
}
- printk(KERN_EMERG "TSC %Lx ", m->tsc);
+ printk(KERN_EMERG "TSC %Lx ", m->tsc);
if (m->addr)
printk("ADDR %Lx ", m->addr);
if (m->misc)
- printk("MISC %Lx ", m->misc);
+ printk("MISC %Lx ", m->misc);
printk("\n");
printk(KERN_EMERG "This is not a software problem!\n");
- printk(KERN_EMERG
- "Run through mcelog --ascii to decode and contact your hardware vendor\n");
+ printk(KERN_EMERG "Run through mcelog --ascii to decode "
+ "and contact your hardware vendor\n");
}
static void mce_panic(char *msg, struct mce *backup, unsigned long start)
-{
+{
int i;
oops_begin();
for (i = 0; i < MCE_LOG_LEN; i++) {
unsigned long tsc = mcelog.entry[i].tsc;
+
if (time_before(tsc, start))
continue;
- print_mce(&mcelog.entry[i]);
+ print_mce(&mcelog.entry[i]);
if (backup && mcelog.entry[i].tsc == backup->tsc)
backup = NULL;
}
if (backup)
print_mce(backup);
panic(msg);
-}
+}
static int mce_available(struct cpuinfo_x86 *c)
{
@@ -173,10 +170,9 @@ static inline void mce_get_rip(struct mce *m, struct pt_regs *regs)
}
}
-/*
+/*
* The actual machine check handler
*/
-
void do_machine_check(struct pt_regs * regs, long error_code)
{
struct mce m, panicm;
@@ -197,7 +193,8 @@ void do_machine_check(struct pt_regs * regs, long error_code)
atomic_inc(&mce_entry);
if (regs)
- notify_die(DIE_NMI, "machine check", regs, error_code, 18, SIGKILL);
+ notify_die(DIE_NMI, "machine check", regs, error_code, 18,
+ SIGKILL);
if (!banks)
goto out2;
@@ -207,15 +204,15 @@ void do_machine_check(struct pt_regs * regs, long error_code)
/* if the restart IP is not valid, we're done for */
if (!(m.mcgstatus & MCG_STATUS_RIPV))
no_way_out = 1;
-
+
rdtscll(mcestart);
barrier();
for (i = 0; i < banks; i++) {
if (!bank[i])
continue;
-
- m.misc = 0;
+
+ m.misc = 0;
m.addr = 0;
m.bank = i;
m.tsc = 0;
@@ -323,7 +320,7 @@ void do_machine_check(struct pt_regs * regs, long error_code)
#ifdef CONFIG_X86_MCE_INTEL
/***
* mce_log_therm_throt_event - Logs the thermal throttling event to mcelog
- * @cpu: The CPU on which the event occured.
+ * @cpu: The CPU on which the event occurred.
* @status: Event status information
*
* This function should be called by the thermal interrupt after the
@@ -375,7 +372,7 @@ static void mcheck_timer(struct work_struct *work)
if (mce_notify_user()) {
next_interval = max(next_interval/2, HZ/100);
} else {
- next_interval = min(next_interval*2,
+ next_interval = min(next_interval * 2,
(int)round_jiffies_relative(check_interval*HZ));
}
@@ -426,18 +423,18 @@ static struct notifier_block mce_idle_notifier = {
};
static __init int periodic_mcheck_init(void)
-{
+{
next_interval = check_interval * HZ;
if (next_interval)
schedule_delayed_work(&mcheck_work,
round_jiffies_relative(next_interval));
idle_notifier_register(&mce_idle_notifier);
return 0;
-}
+}
__initcall(periodic_mcheck_init);
-/*
+/*
* Initialize Machine Checks for a CPU.
*/
static void mce_init(void *dummy)
@@ -447,9 +444,9 @@ static void mce_init(void *dummy)
rdmsrl(MSR_IA32_MCG_CAP, cap);
banks = cap & 0xff;
- if (banks > NR_BANKS) {
+ if (banks > NR_BANKS) {
printk(KERN_INFO "MCE: warning: using only %d banks\n", banks);
- banks = NR_BANKS;
+ banks = NR_BANKS;
}
/* Use accurate RIP reporting if available. */
if ((cap & (1<<9)) && ((cap >> 16) & 0xff) >= 9)
@@ -467,15 +464,15 @@ static void mce_init(void *dummy)
for (i = 0; i < banks; i++) {
wrmsrl(MSR_IA32_MC0_CTL+4*i, bank[i]);
wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0);
- }
+ }
}
/* Add per CPU specific workarounds here */
static void __cpuinit mce_cpu_quirks(struct cpuinfo_x86 *c)
-{
+{
/* This should be disabled by the BIOS, but isn't always */
if (c->x86_vendor == X86_VENDOR_AMD && c->x86 == 15) {
- /* disable GART TBL walk error reporting, which trips off
+ /* disable GART TBL walk error reporting, which trips off
incorrectly with the IOMMU & 3ware & Cerberus. */
clear_bit(10, &bank[4]);
/* Lots of broken BIOS around that don't clear them
@@ -483,7 +480,7 @@ static void __cpuinit mce_cpu_quirks(struct cpuinfo_x86 *c)
mce_bootlog = 0;
}
-}
+}
static void __cpuinit mce_cpu_features(struct cpuinfo_x86 *c)
{
@@ -499,15 +496,15 @@ static void __cpuinit mce_cpu_features(struct cpuinfo_x86 *c)
}
}
-/*
+/*
* Called for each booted CPU to set up machine checks.
- * Must be called with preempt off.
+ * Must be called with preempt off.
*/
void __cpuinit mcheck_init(struct cpuinfo_x86 *c)
{
static cpumask_t mce_cpus = CPU_MASK_NONE;
- mce_cpu_quirks(c);
+ mce_cpu_quirks(c);
if (mce_dont_init ||
cpu_test_and_set(smp_processor_id(), mce_cpus) ||
@@ -556,13 +553,15 @@ static int mce_release(struct inode *inode, struct file *file)
return 0;
}
-static void collect_tscs(void *data)
-{
+static void collect_tscs(void *data)
+{
unsigned long *cpu_tsc = (unsigned long *)data;
+
rdtscll(cpu_tsc[smp_processor_id()]);
-}
+}
-static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize, loff_t *off)
+static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize,
+ loff_t *off)
{
unsigned long *cpu_tsc;
static DECLARE_MUTEX(mce_read_sem);
@@ -574,19 +573,20 @@ static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize, loff
if (!cpu_tsc)
return -ENOMEM;
- down(&mce_read_sem);
+ down(&mce_read_sem);
next = rcu_dereference(mcelog.next);
/* Only supports full reads right now */
- if (*off != 0 || usize < MCE_LOG_LEN*sizeof(struct mce)) {
+ if (*off != 0 || usize < MCE_LOG_LEN*sizeof(struct mce)) {
up(&mce_read_sem);
kfree(cpu_tsc);
return -EINVAL;
}
err = 0;
- for (i = 0; i < next; i++) {
+ for (i = 0; i < next; i++) {
unsigned long start = jiffies;
+
while (!mcelog.entry[i].finished) {
if (time_after_eq(jiffies, start + 2)) {
memset(mcelog.entry + i,0, sizeof(struct mce));
@@ -596,31 +596,34 @@ static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize, loff
}
smp_rmb();
err |= copy_to_user(buf, mcelog.entry + i, sizeof(struct mce));
- buf += sizeof(struct mce);
+ buf += sizeof(struct mce);
timeout:
;
- }
+ }
memset(mcelog.entry, 0, next * sizeof(struct mce));
mcelog.next = 0;
synchronize_sched();
- /* Collect entries that were still getting written before the synchronize. */
-
+ /*
+ * Collect entries that were still getting written before the
+ * synchronize.
+ */
on_each_cpu(collect_tscs, cpu_tsc, 1, 1);
- for (i = next; i < MCE_LOG_LEN; i++) {
- if (mcelog.entry[i].finished &&
- mcelog.entry[i].tsc < cpu_tsc[mcelog.entry[i].cpu]) {
- err |= copy_to_user(buf, mcelog.entry+i, sizeof(struct mce));
+ for (i = next; i < MCE_LOG_LEN; i++) {
+ if (mcelog.entry[i].finished &&
+ mcelog.entry[i].tsc < cpu_tsc[mcelog.entry[i].cpu]) {
+ err |= copy_to_user(buf, mcelog.entry+i,
+ sizeof(struct mce));
smp_rmb();
buf += sizeof(struct mce);
memset(&mcelog.entry[i], 0, sizeof(struct mce));
}
- }
+ }
up(&mce_read_sem);
kfree(cpu_tsc);
- return err ? -EFAULT : buf - ubuf;
+ return err ? -EFAULT : buf - ubuf;
}
static unsigned int mce_poll(struct file *file, poll_table *wait)
@@ -631,26 +634,29 @@ static unsigned int mce_poll(struct file *file, poll_table *wait)
return 0;
}
-static int mce_ioctl(struct inode *i, struct file *f,unsigned int cmd, unsigned long arg)
+static int mce_ioctl(struct inode *i, struct file *f,unsigned int cmd,
+ unsigned long arg)
{
int __user *p = (int __user *)arg;
+
if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
+ return -EPERM;
switch (cmd) {
- case MCE_GET_RECORD_LEN:
+ case MCE_GET_RECORD_LEN:
return put_user(sizeof(struct mce), p);
case MCE_GET_LOG_LEN:
- return put_user(MCE_LOG_LEN, p);
+ return put_user(MCE_LOG_LEN, p);
case MCE_GETCLEAR_FLAGS: {
unsigned flags;
- do {
+
+ do {
flags = mcelog.flags;
- } while (cmpxchg(&mcelog.flags, flags, 0) != flags);
- return put_user(flags, p);
+ } while (cmpxchg(&mcelog.flags, flags, 0) != flags);
+ return put_user(flags, p);
}
default:
- return -ENOTTY;
- }
+ return -ENOTTY;
+ }
}
static const struct file_operations mce_chrdev_ops = {
@@ -681,25 +687,22 @@ void __init restart_mce(void)
set_in_cr4(X86_CR4_MCE);
}
-/*
- * Old style boot options parsing. Only for compatibility.
+/*
+ * Old style boot options parsing. Only for compatibility.
*/
-
static int __init mcheck_disable(char *str)
{
mce_dont_init = 1;
return 1;
}
-/* mce=off disables machine check. Note you can reenable it later
+/* mce=off disables machine check. Note you can re-enable it later
using sysfs.
mce=TOLERANCELEVEL (number, see above)
mce=bootlog Log MCEs from before booting. Disabled by default on AMD.
mce=nobootlog Don't log MCEs from before booting. */
static int __init mcheck_enable(char *str)
{
- if (*str == '=')
- str++;
if (!strcmp(str, "off"))
mce_dont_init = 1;
else if (!strcmp(str, "bootlog") || !strcmp(str,"nobootlog"))
@@ -707,16 +710,16 @@ static int __init mcheck_enable(char *str)
else if (isdigit(str[0]))
get_option(&str, &tolerant);
else
- printk("mce= argument %s ignored. Please use /sys", str);
+ printk("mce= argument %s ignored. Please use /sys", str);
return 1;
}
__setup("nomce", mcheck_disable);
-__setup("mce", mcheck_enable);
+__setup("mce=", mcheck_enable);
-/*
+/*
* Sysfs support
- */
+ */
/* On resume clear all MCE state. Don't want to see leftovers from the BIOS.
Only one CPU is active at this time, the others get readded later using
@@ -728,12 +731,12 @@ static int mce_resume(struct sys_device *dev)
}
/* Reinit MCEs after user configuration changes */
-static void mce_restart(void)
-{
+static void mce_restart(void)
+{
if (next_interval)
cancel_delayed_work(&mcheck_work);
/* Timer race is harmless here */
- on_each_cpu(mce_init, NULL, 1, 1);
+ on_each_cpu(mce_init, NULL, 1, 1);
next_interval = check_interval * HZ;
if (next_interval)
schedule_delayed_work(&mcheck_work,
@@ -749,17 +752,17 @@ DEFINE_PER_CPU(struct sys_device, device_mce);
/* Why are there no generic functions for this? */
#define ACCESSOR(name, var, start) \
- static ssize_t show_ ## name(struct sys_device *s, char *buf) { \
- return sprintf(buf, "%lx\n", (unsigned long)var); \
- } \
+ static ssize_t show_ ## name(struct sys_device *s, char *buf) { \
+ return sprintf(buf, "%lx\n", (unsigned long)var); \
+ } \
static ssize_t set_ ## name(struct sys_device *s,const char *buf,size_t siz) { \
- char *end; \
- unsigned long new = simple_strtoul(buf, &end, 0); \
- if (end == buf) return -EINVAL; \
- var = new; \
- start; \
- return end-buf; \
- } \
+ char *end; \
+ unsigned long new = simple_strtoul(buf, &end, 0); \
+ if (end == buf) return -EINVAL; \
+ var = new; \
+ start; \
+ return end-buf; \
+ } \
static SYSDEV_ATTR(name, 0644, show_ ## name, set_ ## name);
/* TBD should generate these dynamically based on number of available banks */
@@ -799,24 +802,41 @@ static struct sysdev_attribute *mce_attributes[] = {
NULL
};
+static cpumask_t mce_device_initialized = CPU_MASK_NONE;
+
/* Per cpu sysdev init. All of the cpus still share the same ctl bank */
static __cpuinit int mce_create_device(unsigned int cpu)
{
int err;
int i;
- if (!mce_available(&cpu_data[cpu]))
+
+ if (!mce_available(&cpu_data(cpu)))
return -EIO;
+ memset(&per_cpu(device_mce, cpu).kobj, 0, sizeof(struct kobject));
per_cpu(device_mce,cpu).id = cpu;
per_cpu(device_mce,cpu).cls = &mce_sysclass;
err = sysdev_register(&per_cpu(device_mce,cpu));
+ if (err)
+ return err;
+
+ for (i = 0; mce_attributes[i]; i++) {
+ err = sysdev_create_file(&per_cpu(device_mce,cpu),
+ mce_attributes[i]);
+ if (err)
+ goto error;
+ }
+ cpu_set(cpu, mce_device_initialized);
- if (!err) {
- for (i = 0; mce_attributes[i]; i++)
- sysdev_create_file(&per_cpu(device_mce,cpu),
- mce_attributes[i]);
+ return 0;
+error:
+ while (i--) {
+ sysdev_remove_file(&per_cpu(device_mce,cpu),
+ mce_attributes[i]);
}
+ sysdev_unregister(&per_cpu(device_mce,cpu));
+
return err;
}
@@ -824,11 +844,14 @@ static void mce_remove_device(unsigned int cpu)
{
int i;
+ if (!cpu_isset(cpu, mce_device_initialized))
+ return;
+
for (i = 0; mce_attributes[i]; i++)
sysdev_remove_file(&per_cpu(device_mce,cpu),
mce_attributes[i]);
sysdev_unregister(&per_cpu(device_mce,cpu));
- memset(&per_cpu(device_mce, cpu).kobj, 0, sizeof(struct kobject));
+ cpu_clear(cpu, mce_device_initialized);
}
/* Get notified when a cpu comes on/off. Be hotplug friendly. */
@@ -862,9 +885,13 @@ static __init int mce_init_device(void)
if (!mce_available(&boot_cpu_data))
return -EIO;
err = sysdev_class_register(&mce_sysclass);
+ if (err)
+ return err;
for_each_online_cpu(i) {
- mce_create_device(i);
+ err = mce_create_device(i);
+ if (err)
+ return err;
}
register_hotcpu_notifier(&mce_cpu_notifier);
diff --git a/arch/x86/kernel/mce_amd_64.c b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c
index 2f8a7f18b0fe..752fb16a817d 100644
--- a/arch/x86/kernel/mce_amd_64.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c
@@ -237,6 +237,7 @@ asmlinkage void mce_threshold_interrupt(void)
}
}
out:
+ add_pda(irq_threshold_count, 1);
irq_exit();
}
@@ -471,11 +472,11 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
sprintf(name, "threshold_bank%i", bank);
#ifdef CONFIG_SMP
- if (cpu_data[cpu].cpu_core_id && shared_bank[bank]) { /* symlink */
- i = first_cpu(cpu_core_map[cpu]);
+ if (cpu_data(cpu).cpu_core_id && shared_bank[bank]) { /* symlink */
+ i = first_cpu(per_cpu(cpu_core_map, cpu));
/* first core not up yet */
- if (cpu_data[i].cpu_core_id)
+ if (cpu_data(i).cpu_core_id)
goto out;
/* already linked */
@@ -492,7 +493,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
if (err)
goto out;
- b->cpus = cpu_core_map[cpu];
+ b->cpus = per_cpu(cpu_core_map, cpu);
per_cpu(threshold_banks, cpu)[bank] = b;
goto out;
}
@@ -509,7 +510,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
#ifndef CONFIG_SMP
b->cpus = CPU_MASK_ALL;
#else
- b->cpus = cpu_core_map[cpu];
+ b->cpus = per_cpu(cpu_core_map, cpu);
#endif
err = kobject_register(&b->kobj);
if (err)
diff --git a/arch/x86/kernel/mce_intel_64.c b/arch/x86/kernel/cpu/mcheck/mce_intel_64.c
index 6551505d8a2c..c17eaf5dd6dd 100644
--- a/arch/x86/kernel/mce_intel_64.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_intel_64.c
@@ -26,6 +26,7 @@ asmlinkage void smp_thermal_interrupt(void)
if (therm_throt_process(msr_val & 1))
mce_log_therm_throt_event(smp_processor_id(), msr_val);
+ add_pda(irq_thermal_count, 1);
irq_exit();
}
diff --git a/arch/x86/kernel/cpu/mcheck/p4.c b/arch/x86/kernel/cpu/mcheck/p4.c
index 1509edfb2313..be4dabfee1f5 100644
--- a/arch/x86/kernel/cpu/mcheck/p4.c
+++ b/arch/x86/kernel/cpu/mcheck/p4.c
@@ -61,6 +61,7 @@ fastcall void smp_thermal_interrupt(struct pt_regs *regs)
{
irq_enter();
vendor_thermal_interrupt(regs);
+ __get_cpu_var(irq_stat).irq_thermal_count++;
irq_exit();
}
diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c
index 1203dc5ab87a..24885be5c48c 100644
--- a/arch/x86/kernel/cpu/mcheck/therm_throt.c
+++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c
@@ -131,17 +131,19 @@ static __cpuinit int thermal_throttle_cpu_callback(struct notifier_block *nfb,
{
unsigned int cpu = (unsigned long)hcpu;
struct sys_device *sys_dev;
- int err;
+ int err = 0;
sys_dev = get_cpu_sysdev(cpu);
switch (action) {
- case CPU_ONLINE:
- case CPU_ONLINE_FROZEN:
+ case CPU_UP_PREPARE:
+ case CPU_UP_PREPARE_FROZEN:
mutex_lock(&therm_cpu_lock);
err = thermal_throttle_add_dev(sys_dev);
mutex_unlock(&therm_cpu_lock);
WARN_ON(err);
break;
+ case CPU_UP_CANCELED:
+ case CPU_UP_CANCELED_FROZEN:
case CPU_DEAD:
case CPU_DEAD_FROZEN:
mutex_lock(&therm_cpu_lock);
@@ -149,10 +151,10 @@ static __cpuinit int thermal_throttle_cpu_callback(struct notifier_block *nfb,
mutex_unlock(&therm_cpu_lock);
break;
}
- return NOTIFY_OK;
+ return err ? NOTIFY_BAD : NOTIFY_OK;
}
-static struct notifier_block thermal_throttle_cpu_notifier =
+static struct notifier_block thermal_throttle_cpu_notifier __cpuinitdata =
{
.notifier_call = thermal_throttle_cpu_callback,
};
diff --git a/arch/x86/kernel/cpu/mtrr/cyrix.c b/arch/x86/kernel/cpu/mtrr/cyrix.c
index 2287d4863a8a..9964be3de2b7 100644
--- a/arch/x86/kernel/cpu/mtrr/cyrix.c
+++ b/arch/x86/kernel/cpu/mtrr/cyrix.c
@@ -147,10 +147,10 @@ static void prepare_set(void)
write_cr0(cr0);
wbinvd();
- /* Cyrix ARRs - everything else were excluded at the top */
+ /* Cyrix ARRs - everything else was excluded at the top */
ccr3 = getCx86(CX86_CCR3);
- /* Cyrix ARRs - everything else were excluded at the top */
+ /* Cyrix ARRs - everything else was excluded at the top */
setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10);
}
diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c
index 56f64e34829f..992f08dfbb6c 100644
--- a/arch/x86/kernel/cpu/mtrr/generic.c
+++ b/arch/x86/kernel/cpu/mtrr/generic.c
@@ -182,7 +182,7 @@ static inline void k8_enable_fixed_iorrs(void)
/**
* Checks and updates an fixed-range MTRR if it differs from the value it
- * should have. If K8 extenstions are wanted, update the K8 SYSCFG MSR also.
+ * should have. If K8 extentions are wanted, update the K8 SYSCFG MSR also.
* see AMD publication no. 24593, chapter 7.8.1, page 233 for more information
* \param msr MSR address of the MTTR which should be checked and updated
* \param changed pointer which indicates whether the MTRR needed to be changed
diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c
index c48b6fea5ab4..3b20613325dc 100644
--- a/arch/x86/kernel/cpu/mtrr/main.c
+++ b/arch/x86/kernel/cpu/mtrr/main.c
@@ -139,13 +139,12 @@ struct set_mtrr_data {
mtrr_type smp_type;
};
-#ifdef CONFIG_SMP
-
static void ipi_handler(void *info)
/* [SUMMARY] Synchronisation handler. Executed by "other" CPUs.
[RETURNS] Nothing.
*/
{
+#ifdef CONFIG_SMP
struct set_mtrr_data *data = info;
unsigned long flags;
@@ -168,9 +167,8 @@ static void ipi_handler(void *info)
atomic_dec(&data->count);
local_irq_restore(flags);
-}
-
#endif
+}
static inline int types_compatible(mtrr_type type1, mtrr_type type2) {
return type1 == MTRR_TYPE_UNCACHABLE ||
@@ -738,13 +736,7 @@ void mtrr_ap_init(void)
*/
void mtrr_save_state(void)
{
- int cpu = get_cpu();
-
- if (cpu == 0)
- mtrr_save_fixed_ranges(NULL);
- else
- smp_call_function_single(0, mtrr_save_fixed_ranges, NULL, 1, 1);
- put_cpu();
+ smp_call_function_single(0, mtrr_save_fixed_ranges, NULL, 1, 1);
}
static int __init mtrr_init_finialize(void)
@@ -754,7 +746,7 @@ static int __init mtrr_init_finialize(void)
if (use_intel())
mtrr_state_warn();
else {
- /* The CPUs haven't MTRR and seemes not support SMP. They have
+ /* The CPUs haven't MTRR and seem to not support SMP. They have
* specific drivers, we use a tricky method to support
* suspend/resume for them.
* TBD: is there any system with such CPU which supports
diff --git a/arch/x86/kernel/cpu/perfctr-watchdog.c b/arch/x86/kernel/cpu/perfctr-watchdog.c
index 93fecd4b03de..c02541e6e653 100644
--- a/arch/x86/kernel/cpu/perfctr-watchdog.c
+++ b/arch/x86/kernel/cpu/perfctr-watchdog.c
@@ -34,7 +34,7 @@ struct wd_ops {
u64 checkbit;
};
-static struct wd_ops *wd_ops;
+static const struct wd_ops *wd_ops;
/* this number is calculated from Intel's MSR_P4_CRU_ESCR5 register and it's
* offset from MSR_P4_BSU_ESCR0. It will be the max for all platforms (for now)
@@ -120,7 +120,9 @@ int reserve_perfctr_nmi(unsigned int msr)
unsigned int counter;
counter = nmi_perfctr_msr_to_bit(msr);
- BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+ /* register not managed by the allocator? */
+ if (counter > NMI_MAX_COUNTER_BITS)
+ return 1;
if (!test_and_set_bit(counter, perfctr_nmi_owner))
return 1;
@@ -132,7 +134,9 @@ void release_perfctr_nmi(unsigned int msr)
unsigned int counter;
counter = nmi_perfctr_msr_to_bit(msr);
- BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+ /* register not managed by the allocator? */
+ if (counter > NMI_MAX_COUNTER_BITS)
+ return;
clear_bit(counter, perfctr_nmi_owner);
}
@@ -142,7 +146,9 @@ int reserve_evntsel_nmi(unsigned int msr)
unsigned int counter;
counter = nmi_evntsel_msr_to_bit(msr);
- BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+ /* register not managed by the allocator? */
+ if (counter > NMI_MAX_COUNTER_BITS)
+ return 1;
if (!test_and_set_bit(counter, evntsel_nmi_owner))
return 1;
@@ -154,7 +160,9 @@ void release_evntsel_nmi(unsigned int msr)
unsigned int counter;
counter = nmi_evntsel_msr_to_bit(msr);
- BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+ /* register not managed by the allocator? */
+ if (counter > NMI_MAX_COUNTER_BITS)
+ return;
clear_bit(counter, evntsel_nmi_owner);
}
@@ -317,7 +325,7 @@ static void single_msr_rearm(struct nmi_watchdog_ctlblk *wd, unsigned nmi_hz)
write_watchdog_counter(wd->perfctr_msr, NULL, nmi_hz);
}
-static struct wd_ops k7_wd_ops = {
+static const struct wd_ops k7_wd_ops = {
.reserve = single_msr_reserve,
.unreserve = single_msr_unreserve,
.setup = setup_k7_watchdog,
@@ -380,7 +388,7 @@ static void p6_rearm(struct nmi_watchdog_ctlblk *wd, unsigned nmi_hz)
write_watchdog_counter32(wd->perfctr_msr, NULL,nmi_hz);
}
-static struct wd_ops p6_wd_ops = {
+static const struct wd_ops p6_wd_ops = {
.reserve = single_msr_reserve,
.unreserve = single_msr_unreserve,
.setup = setup_p6_watchdog,
@@ -532,7 +540,7 @@ static void p4_rearm(struct nmi_watchdog_ctlblk *wd, unsigned nmi_hz)
write_watchdog_counter(wd->perfctr_msr, NULL, nmi_hz);
}
-static struct wd_ops p4_wd_ops = {
+static const struct wd_ops p4_wd_ops = {
.reserve = p4_reserve,
.unreserve = p4_unreserve,
.setup = setup_p4_watchdog,
@@ -550,6 +558,8 @@ static struct wd_ops p4_wd_ops = {
#define ARCH_PERFMON_NMI_EVENT_SEL ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL
#define ARCH_PERFMON_NMI_EVENT_UMASK ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK
+static struct wd_ops intel_arch_wd_ops;
+
static int setup_intel_arch_watchdog(unsigned nmi_hz)
{
unsigned int ebx;
@@ -591,11 +601,11 @@ static int setup_intel_arch_watchdog(unsigned nmi_hz)
wd->perfctr_msr = perfctr_msr;
wd->evntsel_msr = evntsel_msr;
wd->cccr_msr = 0; //unused
- wd_ops->checkbit = 1ULL << (eax.split.bit_width - 1);
+ intel_arch_wd_ops.checkbit = 1ULL << (eax.split.bit_width - 1);
return 1;
}
-static struct wd_ops intel_arch_wd_ops = {
+static struct wd_ops intel_arch_wd_ops __read_mostly = {
.reserve = single_msr_reserve,
.unreserve = single_msr_unreserve,
.setup = setup_intel_arch_watchdog,
diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c
index 1e31b6caffb1..066f8c6af4df 100644
--- a/arch/x86/kernel/cpu/proc.c
+++ b/arch/x86/kernel/cpu/proc.c
@@ -49,7 +49,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
/* Intel-defined (#2) */
"pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est",
"tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL,
- NULL, NULL, "dca", NULL, NULL, NULL, NULL, "popcnt",
+ NULL, NULL, "dca", "sse4_1", "sse4_2", NULL, NULL, "popcnt",
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* VIA/Cyrix/Centaur-defined */
@@ -59,10 +59,10 @@ static int show_cpuinfo(struct seq_file *m, void *v)
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* AMD-defined (#2) */
- "lahf_lm", "cmp_legacy", "svm", "extapic", "cr8_legacy",
- "altmovcr8", "abm", "sse4a",
- "misalignsse", "3dnowprefetch",
- "osvw", "ibs", NULL, NULL, NULL, NULL,
+ "lahf_lm", "cmp_legacy", "svm", "extapic",
+ "cr8_legacy", "abm", "sse4a", "misalignsse",
+ "3dnowprefetch", "osvw", "ibs", "sse5",
+ "skinit", "wdt", NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -85,12 +85,13 @@ static int show_cpuinfo(struct seq_file *m, void *v)
/* nothing */
};
struct cpuinfo_x86 *c = v;
- int i, n = c - cpu_data;
+ int i, n = 0;
int fpu_exception;
#ifdef CONFIG_SMP
if (!cpu_online(n))
return 0;
+ n = c->cpu_index;
#endif
seq_printf(m, "processor\t: %d\n"
"vendor_id\t: %s\n"
@@ -122,7 +123,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
#ifdef CONFIG_X86_HT
if (c->x86_max_cores * smp_num_siblings > 1) {
seq_printf(m, "physical id\t: %d\n", c->phys_proc_id);
- seq_printf(m, "siblings\t: %d\n", cpus_weight(cpu_core_map[n]));
+ seq_printf(m, "siblings\t: %d\n",
+ cpus_weight(per_cpu(cpu_core_map, n)));
seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id);
seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
}
@@ -174,11 +176,15 @@ static int show_cpuinfo(struct seq_file *m, void *v)
static void *c_start(struct seq_file *m, loff_t *pos)
{
- return *pos < NR_CPUS ? cpu_data + *pos : NULL;
+ if (*pos == 0) /* just in case, cpu 0 is not the first */
+ *pos = first_cpu(cpu_possible_map);
+ if ((*pos) < NR_CPUS && cpu_possible(*pos))
+ return &cpu_data(*pos);
+ return NULL;
}
static void *c_next(struct seq_file *m, void *v, loff_t *pos)
{
- ++*pos;
+ *pos = next_cpu(*pos, cpu_possible_map);
return c_start(m, pos);
}
static void c_stop(struct seq_file *m, void *v)
diff --git a/arch/x86/kernel/cpufreq/Kconfig b/arch/x86/kernel/cpufreq/Kconfig
deleted file mode 100644
index a3fd51926cbd..000000000000
--- a/arch/x86/kernel/cpufreq/Kconfig
+++ /dev/null
@@ -1,108 +0,0 @@
-#
-# CPU Frequency scaling
-#
-
-menu "CPU Frequency scaling"
-
-source "drivers/cpufreq/Kconfig"
-
-if CPU_FREQ
-
-comment "CPUFreq processor drivers"
-
-config X86_POWERNOW_K8
- tristate "AMD Opteron/Athlon64 PowerNow!"
- select CPU_FREQ_TABLE
- help
- This adds the CPUFreq driver for mobile AMD Opteron/Athlon64 processors.
-
- To compile this driver as a module, choose M here: the
- module will be called powernow-k8.
-
- For details, take a look at <file:Documentation/cpu-freq/>.
-
- If in doubt, say N.
-
-config X86_POWERNOW_K8_ACPI
- bool
- depends on X86_POWERNOW_K8 && ACPI_PROCESSOR
- depends on !(X86_POWERNOW_K8 = y && ACPI_PROCESSOR = m)
- default y
-
-config X86_SPEEDSTEP_CENTRINO
- tristate "Intel Enhanced SpeedStep (deprecated)"
- select CPU_FREQ_TABLE
- depends on ACPI_PROCESSOR
- help
- This is deprecated and this functionality is now merged into
- acpi_cpufreq (X86_ACPI_CPUFREQ). Use that driver instead of
- speedstep_centrino.
- This adds the CPUFreq driver for Enhanced SpeedStep enabled
- mobile CPUs. This means Intel Pentium M (Centrino) CPUs
- or 64bit enabled Intel Xeons.
-
- To compile this driver as a module, choose M here: the
- module will be called speedstep-centrino.
-
- For details, take a look at <file:Documentation/cpu-freq/>.
-
- If in doubt, say N.
-
-config X86_ACPI_CPUFREQ
- tristate "ACPI Processor P-States driver"
- select CPU_FREQ_TABLE
- depends on ACPI_PROCESSOR
- help
- This driver adds a CPUFreq driver which utilizes the ACPI
- Processor Performance States.
- This driver also supports Intel Enhanced Speedstep.
-
- To compile this driver as a module, choose M here: the
- module will be called acpi-cpufreq.
-
- For details, take a look at <file:Documentation/cpu-freq/>.
-
- If in doubt, say N.
-
-comment "shared options"
-
-config X86_ACPI_CPUFREQ_PROC_INTF
- bool "/proc/acpi/processor/../performance interface (deprecated)"
- depends on PROC_FS
- depends on X86_ACPI_CPUFREQ || X86_POWERNOW_K8_ACPI
- help
- This enables the deprecated /proc/acpi/processor/../performance
- interface. While it is helpful for debugging, the generic,
- cross-architecture cpufreq interfaces should be used.
-
- If in doubt, say N.
-
-config X86_P4_CLOCKMOD
- tristate "Intel Pentium 4 clock modulation"
- depends on EMBEDDED
- select CPU_FREQ_TABLE
- help
- This adds the clock modulation driver for Intel Pentium 4 / XEON
- processors. When enabled it will lower CPU temperature by skipping
- clocks.
-
- This driver should be only used in exceptional
- circumstances when very low power is needed because it causes severe
- slowdowns and noticeable latencies. Normally Speedstep should be used
- instead.
-
- To compile this driver as a module, choose M here: the
- module will be called p4-clockmod.
-
- For details, take a look at <file:Documentation/cpu-freq/>.
-
- Unless you are absolutely sure say N.
-
-
-config X86_SPEEDSTEP_LIB
- tristate
- default X86_P4_CLOCKMOD
-
-endif
-
-endmenu
diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c
index f4548c93ccf5..05c9936a16cc 100644
--- a/arch/x86/kernel/cpuid.c
+++ b/arch/x86/kernel/cpuid.c
@@ -43,8 +43,6 @@
static struct class *cpuid_class;
-#ifdef CONFIG_SMP
-
struct cpuid_command {
u32 reg;
u32 *data;
@@ -62,25 +60,11 @@ static inline void do_cpuid(int cpu, u32 reg, u32 * data)
{
struct cpuid_command cmd;
- preempt_disable();
- if (cpu == smp_processor_id()) {
- cpuid(reg, &data[0], &data[1], &data[2], &data[3]);
- } else {
- cmd.reg = reg;
- cmd.data = data;
+ cmd.reg = reg;
+ cmd.data = data;
- smp_call_function_single(cpu, cpuid_smp_cpuid, &cmd, 1, 1);
- }
- preempt_enable();
+ smp_call_function_single(cpu, cpuid_smp_cpuid, &cmd, 1, 1);
}
-#else /* ! CONFIG_SMP */
-
-static inline void do_cpuid(int cpu, u32 reg, u32 * data)
-{
- cpuid(reg, &data[0], &data[1], &data[2], &data[3]);
-}
-
-#endif /* ! CONFIG_SMP */
static loff_t cpuid_seek(struct file *file, loff_t offset, int orig)
{
@@ -130,7 +114,7 @@ static ssize_t cpuid_read(struct file *file, char __user *buf,
static int cpuid_open(struct inode *inode, struct file *file)
{
unsigned int cpu = iminor(file->f_path.dentry->d_inode);
- struct cpuinfo_x86 *c = &(cpu_data)[cpu];
+ struct cpuinfo_x86 *c = &cpu_data(cpu);
if (cpu >= NR_CPUS || !cpu_online(cpu))
return -ENXIO; /* No such CPU */
@@ -150,32 +134,40 @@ static const struct file_operations cpuid_fops = {
.open = cpuid_open,
};
-static int cpuid_device_create(int i)
+static __cpuinit int cpuid_device_create(int cpu)
{
- int err = 0;
struct device *dev;
- dev = device_create(cpuid_class, NULL, MKDEV(CPUID_MAJOR, i), "cpu%d",i);
- if (IS_ERR(dev))
- err = PTR_ERR(dev);
- return err;
+ dev = device_create(cpuid_class, NULL, MKDEV(CPUID_MAJOR, cpu),
+ "cpu%d", cpu);
+ return IS_ERR(dev) ? PTR_ERR(dev) : 0;
+}
+
+static void cpuid_device_destroy(int cpu)
+{
+ device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu));
}
-static int cpuid_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
+static int __cpuinit cpuid_class_cpu_callback(struct notifier_block *nfb,
+ unsigned long action,
+ void *hcpu)
{
unsigned int cpu = (unsigned long)hcpu;
+ int err = 0;
switch (action) {
- case CPU_ONLINE:
- case CPU_ONLINE_FROZEN:
- cpuid_device_create(cpu);
+ case CPU_UP_PREPARE:
+ case CPU_UP_PREPARE_FROZEN:
+ err = cpuid_device_create(cpu);
break;
+ case CPU_UP_CANCELED:
+ case CPU_UP_CANCELED_FROZEN:
case CPU_DEAD:
case CPU_DEAD_FROZEN:
- device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu));
+ cpuid_device_destroy(cpu);
break;
}
- return NOTIFY_OK;
+ return err ? NOTIFY_BAD : NOTIFY_OK;
}
static struct notifier_block __cpuinitdata cpuid_class_cpu_notifier =
@@ -212,7 +204,7 @@ static int __init cpuid_init(void)
out_class:
i = 0;
for_each_online_cpu(i) {
- device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, i));
+ cpuid_device_destroy(i);
}
class_destroy(cpuid_class);
out_chrdev:
@@ -226,7 +218,7 @@ static void __exit cpuid_exit(void)
int cpu = 0;
for_each_online_cpu(cpu)
- device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu));
+ cpuid_device_destroy(cpu);
class_destroy(cpuid_class);
unregister_chrdev(CPUID_MAJOR, "cpu/cpuid");
unregister_hotcpu_notifier(&cpuid_class_cpu_notifier);
diff --git a/arch/x86/kernel/crash_32.c b/arch/x86/kernel/crash.c
index 53589d1b1a05..8bb482ff091b 100644
--- a/arch/x86/kernel/crash_32.c
+++ b/arch/x86/kernel/crash.c
@@ -1,5 +1,5 @@
/*
- * Architecture specific (i386) functions for kexec based crash dumps.
+ * Architecture specific (i386/x86_64) functions for kexec based crash dumps.
*
* Created by: Hariprasad Nellitheertha (hari@in.ibm.com)
*
@@ -25,8 +25,11 @@
#include <linux/kdebug.h>
#include <asm/smp.h>
+#ifdef CONFIG_X86_32
#include <mach_ipi.h>
-
+#else
+#include <asm/mach_apic.h>
+#endif
/* This keeps a track of which one is crashing cpu. */
static int crashing_cpu;
@@ -38,7 +41,9 @@ static int crash_nmi_callback(struct notifier_block *self,
unsigned long val, void *data)
{
struct pt_regs *regs;
+#ifdef CONFIG_X86_32
struct pt_regs fixed_regs;
+#endif
int cpu;
if (val != DIE_NMI_IPI)
@@ -55,10 +60,12 @@ static int crash_nmi_callback(struct notifier_block *self,
return NOTIFY_STOP;
local_irq_disable();
+#ifdef CONFIG_X86_32
if (!user_mode_vm(regs)) {
crash_fixup_ss_esp(&fixed_regs, regs);
regs = &fixed_regs;
}
+#endif
crash_save_cpu(regs, cpu);
disable_local_APIC();
atomic_dec(&waiting_for_crash_ipi);
diff --git a/arch/x86/kernel/crash_64.c b/arch/x86/kernel/crash_64.c
deleted file mode 100644
index 13432a1ae904..000000000000
--- a/arch/x86/kernel/crash_64.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Architecture specific (x86_64) functions for kexec based crash dumps.
- *
- * Created by: Hariprasad Nellitheertha (hari@in.ibm.com)
- *
- * Copyright (C) IBM Corporation, 2004. All rights reserved.
- *
- */
-
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/smp.h>
-#include <linux/irq.h>
-#include <linux/reboot.h>
-#include <linux/kexec.h>
-#include <linux/delay.h>
-#include <linux/elf.h>
-#include <linux/elfcore.h>
-#include <linux/kdebug.h>
-
-#include <asm/processor.h>
-#include <asm/hardirq.h>
-#include <asm/nmi.h>
-#include <asm/hw_irq.h>
-#include <asm/mach_apic.h>
-
-/* This keeps a track of which one is crashing cpu. */
-static int crashing_cpu;
-
-#ifdef CONFIG_SMP
-static atomic_t waiting_for_crash_ipi;
-
-static int crash_nmi_callback(struct notifier_block *self,
- unsigned long val, void *data)
-{
- struct pt_regs *regs;
- int cpu;
-
- if (val != DIE_NMI_IPI)
- return NOTIFY_OK;
-
- regs = ((struct die_args *)data)->regs;
- cpu = raw_smp_processor_id();
-
- /*
- * Don't do anything if this handler is invoked on crashing cpu.
- * Otherwise, system will completely hang. Crashing cpu can get
- * an NMI if system was initially booted with nmi_watchdog parameter.
- */
- if (cpu == crashing_cpu)
- return NOTIFY_STOP;
- local_irq_disable();
-
- crash_save_cpu(regs, cpu);
- disable_local_APIC();
- atomic_dec(&waiting_for_crash_ipi);
- /* Assume hlt works */
- for(;;)
- halt();
-
- return 1;
-}
-
-static void smp_send_nmi_allbutself(void)
-{
- send_IPI_allbutself(NMI_VECTOR);
-}
-
-/*
- * This code is a best effort heuristic to get the
- * other cpus to stop executing. So races with
- * cpu hotplug shouldn't matter.
- */
-
-static struct notifier_block crash_nmi_nb = {
- .notifier_call = crash_nmi_callback,
-};
-
-static void nmi_shootdown_cpus(void)
-{
- unsigned long msecs;
-
- atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
- if (register_die_notifier(&crash_nmi_nb))
- return; /* return what? */
-
- /*
- * Ensure the new callback function is set before sending
- * out the NMI
- */
- wmb();
-
- smp_send_nmi_allbutself();
-
- msecs = 1000; /* Wait at most a second for the other cpus to stop */
- while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) {
- mdelay(1);
- msecs--;
- }
- /* Leave the nmi callback set */
- disable_local_APIC();
-}
-#else
-static void nmi_shootdown_cpus(void)
-{
- /* There are no cpus to shootdown */
-}
-#endif
-
-void machine_crash_shutdown(struct pt_regs *regs)
-{
- /*
- * This function is only called after the system
- * has panicked or is otherwise in a critical state.
- * The minimum amount of code to allow a kexec'd kernel
- * to run successfully needs to happen here.
- *
- * In practice this means shooting down the other cpus in
- * an SMP system.
- */
- /* The kernel is broken so disable interrupts */
- local_irq_disable();
-
- /* Make a note of crashing cpu. Will be used in NMI callback.*/
- crashing_cpu = smp_processor_id();
- nmi_shootdown_cpus();
-
- if(cpu_has_apic)
- disable_local_APIC();
-
- disable_IO_APIC();
-
- crash_save_cpu(regs, smp_processor_id());
-}
diff --git a/arch/x86/kernel/crash_dump_32.c b/arch/x86/kernel/crash_dump_32.c
index 32e75d0731a9..72d0c56c1b48 100644
--- a/arch/x86/kernel/crash_dump_32.c
+++ b/arch/x86/kernel/crash_dump_32.c
@@ -47,6 +47,7 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
if (!kdump_buf_page) {
printk(KERN_WARNING "Kdump: Kdump buffer page not"
" allocated\n");
+ kunmap_atomic(vaddr, KM_PTE0);
return -EFAULT;
}
copy_page(kdump_buf_page, vaddr);
diff --git a/arch/x86/kernel/e820_32.c b/arch/x86/kernel/e820_32.c
index 3c86b979a40a..18f500d185a2 100644
--- a/arch/x86/kernel/e820_32.c
+++ b/arch/x86/kernel/e820_32.c
@@ -51,6 +51,13 @@ struct resource code_resource = {
.flags = IORESOURCE_BUSY | IORESOURCE_MEM
};
+struct resource bss_resource = {
+ .name = "Kernel bss",
+ .start = 0,
+ .end = 0,
+ .flags = IORESOURCE_BUSY | IORESOURCE_MEM
+};
+
static struct resource system_rom_resource = {
.name = "System ROM",
.start = 0xf0000,
@@ -254,7 +261,9 @@ static void __init probe_roms(void)
* and also for regions reported as reserved by the e820.
*/
static void __init
-legacy_init_iomem_resources(struct resource *code_resource, struct resource *data_resource)
+legacy_init_iomem_resources(struct resource *code_resource,
+ struct resource *data_resource,
+ struct resource *bss_resource)
{
int i;
@@ -287,8 +296,10 @@ legacy_init_iomem_resources(struct resource *code_resource, struct resource *dat
*/
request_resource(res, code_resource);
request_resource(res, data_resource);
+ request_resource(res, bss_resource);
#ifdef CONFIG_KEXEC
- request_resource(res, &crashk_res);
+ if (crashk_res.start != crashk_res.end)
+ request_resource(res, &crashk_res);
#endif
}
}
@@ -306,9 +317,11 @@ static int __init request_standard_resources(void)
printk("Setting up standard PCI resources\n");
if (efi_enabled)
- efi_initialize_iomem_resources(&code_resource, &data_resource);
+ efi_initialize_iomem_resources(&code_resource,
+ &data_resource, &bss_resource);
else
- legacy_init_iomem_resources(&code_resource, &data_resource);
+ legacy_init_iomem_resources(&code_resource,
+ &data_resource, &bss_resource);
/* EFI systems may still have VGA */
request_resource(&iomem_resource, &video_ram_resource);
@@ -705,7 +718,7 @@ void __init e820_register_memory(void)
int i;
/*
- * Search for the bigest gap in the low 32 bits of the e820
+ * Search for the biggest gap in the low 32 bits of the e820
* memory space.
*/
last = 0x100000000ull;
diff --git a/arch/x86/kernel/e820_64.c b/arch/x86/kernel/e820_64.c
index 0f4d5e209e9b..04698e0b056c 100644
--- a/arch/x86/kernel/e820_64.c
+++ b/arch/x86/kernel/e820_64.c
@@ -24,7 +24,7 @@
#include <asm/page.h>
#include <asm/e820.h>
#include <asm/proto.h>
-#include <asm/bootsetup.h>
+#include <asm/setup.h>
#include <asm/sections.h>
struct e820map e820;
@@ -47,7 +47,7 @@ unsigned long end_pfn_map;
*/
static unsigned long __initdata end_user_pfn = MAXMEM>>PAGE_SHIFT;
-extern struct resource code_resource, data_resource;
+extern struct resource code_resource, data_resource, bss_resource;
/* Check for some hardcoded bad areas that early boot is not allowed to touch */
static inline int bad_addr(unsigned long *addrp, unsigned long size)
@@ -68,10 +68,15 @@ static inline int bad_addr(unsigned long *addrp, unsigned long size)
/* initrd */
#ifdef CONFIG_BLK_DEV_INITRD
- if (LOADER_TYPE && INITRD_START && last >= INITRD_START &&
- addr < INITRD_START+INITRD_SIZE) {
- *addrp = PAGE_ALIGN(INITRD_START + INITRD_SIZE);
- return 1;
+ if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image) {
+ unsigned long ramdisk_image = boot_params.hdr.ramdisk_image;
+ unsigned long ramdisk_size = boot_params.hdr.ramdisk_size;
+ unsigned long ramdisk_end = ramdisk_image+ramdisk_size;
+
+ if (last >= ramdisk_image && addr < ramdisk_end) {
+ *addrp = PAGE_ALIGN(ramdisk_end);
+ return 1;
+ }
}
#endif
/* kernel code */
@@ -220,8 +225,10 @@ void __init e820_reserve_resources(void)
*/
request_resource(res, &code_resource);
request_resource(res, &data_resource);
+ request_resource(res, &bss_resource);
#ifdef CONFIG_KEXEC
- request_resource(res, &crashk_res);
+ if (crashk_res.start != crashk_res.end)
+ request_resource(res, &crashk_res);
#endif
}
}
@@ -594,8 +601,8 @@ void __init setup_memory_region(void)
* Otherwise fake a memory map; one section from 0k->640k,
* the next section from 1mb->appropriate_mem_k
*/
- sanitize_e820_map(E820_MAP, &E820_MAP_NR);
- if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0)
+ sanitize_e820_map(boot_params.e820_map, &boot_params.e820_entries);
+ if (copy_e820_map(boot_params.e820_map, boot_params.e820_entries) < 0)
early_panic("Cannot find a valid memory map");
printk(KERN_INFO "BIOS-provided physical RAM map:\n");
e820_print_map("BIOS-e820");
@@ -723,3 +730,22 @@ __init void e820_setup_gap(void)
printk(KERN_INFO "Allocating PCI resources starting at %lx (gap: %lx:%lx)\n",
pci_mem_start, gapstart, gapsize);
}
+
+int __init arch_get_ram_range(int slot, u64 *addr, u64 *size)
+{
+ int i;
+
+ if (slot < 0 || slot >= e820.nr_map)
+ return -1;
+ for (i = slot; i < e820.nr_map; i++) {
+ if (e820.map[i].type != E820_RAM)
+ continue;
+ break;
+ }
+ if (i == e820.nr_map || e820.map[i].addr > (max_pfn << PAGE_SHIFT))
+ return -1;
+ *addr = e820.map[i].addr;
+ *size = min_t(u64, e820.map[i].size + e820.map[i].addr,
+ max_pfn << PAGE_SHIFT) - *addr;
+ return i + 1;
+}
diff --git a/arch/x86/kernel/early-quirks_64.c b/arch/x86/kernel/early-quirks.c
index 13aa4fd728f3..88bb83ec895f 100644
--- a/arch/x86/kernel/early-quirks_64.c
+++ b/arch/x86/kernel/early-quirks.c
@@ -13,33 +13,41 @@
#include <linux/acpi.h>
#include <linux/pci_ids.h>
#include <asm/pci-direct.h>
-#include <asm/proto.h>
-#include <asm/iommu.h>
#include <asm/dma.h>
+#include <asm/io_apic.h>
+#include <asm/apic.h>
+
+#ifdef CONFIG_GART_IOMMU
+#include <asm/gart.h>
+#endif
static void __init via_bugs(void)
{
-#ifdef CONFIG_IOMMU
+#ifdef CONFIG_GART_IOMMU
if ((end_pfn > MAX_DMA32_PFN || force_iommu) &&
- !iommu_aperture_allowed) {
+ !gart_iommu_aperture_allowed) {
printk(KERN_INFO
- "Looks like a VIA chipset. Disabling IOMMU. Override with iommu=allowed\n");
- iommu_aperture_disabled = 1;
+ "Looks like a VIA chipset. Disabling IOMMU."
+ " Override with iommu=allowed\n");
+ gart_iommu_aperture_disabled = 1;
}
#endif
}
#ifdef CONFIG_ACPI
+#ifdef CONFIG_X86_IO_APIC
static int __init nvidia_hpet_check(struct acpi_table_header *header)
{
return 0;
}
-#endif
+#endif /* CONFIG_X86_IO_APIC */
+#endif /* CONFIG_ACPI */
static void __init nvidia_bugs(void)
{
#ifdef CONFIG_ACPI
+#ifdef CONFIG_X86_IO_APIC
/*
* All timer overrides on Nvidia are
* wrong unless HPET is enabled.
@@ -59,17 +67,20 @@ static void __init nvidia_bugs(void)
"try acpi_use_timer_override\n");
}
#endif
+#endif
/* RED-PEN skip them on mptables too? */
}
static void __init ati_bugs(void)
{
+#ifdef CONFIG_X86_IO_APIC
if (timer_over_8254 == 1) {
timer_over_8254 = 0;
printk(KERN_INFO
- "ATI board detected. Disabling timer routing over 8254.\n");
+ "ATI board detected. Disabling timer routing over 8254.\n");
}
+#endif
}
struct chipset {
@@ -104,7 +115,7 @@ void __init early_quirks(void)
if (class == 0xffffffff)
break;
- if ((class >> 16) != PCI_CLASS_BRIDGE_PCI)
+ if ((class >> 16) != PCI_CLASS_BRIDGE_PCI)
continue;
vendor = read_pci_config(num, slot, func,
diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
index fd9aff3f3890..b7d6c23f2871 100644
--- a/arch/x86/kernel/early_printk.c
+++ b/arch/x86/kernel/early_printk.c
@@ -6,15 +6,10 @@
#include <asm/io.h>
#include <asm/processor.h>
#include <asm/fcntl.h>
+#include <asm/setup.h>
#include <xen/hvc-console.h>
/* Simple VGA output */
-
-#ifdef __i386__
-#include <asm/setup.h>
-#else
-#include <asm/bootsetup.h>
-#endif
#define VGABASE (__ISA_IO_base + 0xb8000)
static int max_ypos = 25, max_xpos = 80;
@@ -234,10 +229,10 @@ static int __init setup_early_printk(char *buf)
early_serial_init(buf);
early_console = &early_serial_console;
} else if (!strncmp(buf, "vga", 3)
- && SCREEN_INFO.orig_video_isVGA == 1) {
- max_xpos = SCREEN_INFO.orig_video_cols;
- max_ypos = SCREEN_INFO.orig_video_lines;
- current_ypos = SCREEN_INFO.orig_y;
+ && boot_params.screen_info.orig_video_isVGA == 1) {
+ max_xpos = boot_params.screen_info.orig_video_cols;
+ max_ypos = boot_params.screen_info.orig_video_lines;
+ current_ypos = boot_params.screen_info.orig_y;
early_console = &early_vga_console;
} else if (!strncmp(buf, "simnow", 6)) {
simnow_init(buf + 6);
diff --git a/arch/x86/kernel/efi_32.c b/arch/x86/kernel/efi_32.c
index 2452c6fbe992..e2be78f49399 100644
--- a/arch/x86/kernel/efi_32.c
+++ b/arch/x86/kernel/efi_32.c
@@ -331,11 +331,13 @@ void __init efi_init(void)
memset(&efi, 0, sizeof(efi) );
memset(&efi_phys, 0, sizeof(efi_phys));
- efi_phys.systab = EFI_SYSTAB;
- memmap.phys_map = EFI_MEMMAP;
- memmap.nr_map = EFI_MEMMAP_SIZE/EFI_MEMDESC_SIZE;
- memmap.desc_version = EFI_MEMDESC_VERSION;
- memmap.desc_size = EFI_MEMDESC_SIZE;
+ efi_phys.systab =
+ (efi_system_table_t *)boot_params.efi_info.efi_systab;
+ memmap.phys_map = (void *)boot_params.efi_info.efi_memmap;
+ memmap.nr_map = boot_params.efi_info.efi_memmap_size/
+ boot_params.efi_info.efi_memdesc_size;
+ memmap.desc_version = boot_params.efi_info.efi_memdesc_version;
+ memmap.desc_size = boot_params.efi_info.efi_memdesc_size;
efi.systab = (efi_system_table_t *)
boot_ioremap((unsigned long) efi_phys.systab,
@@ -446,7 +448,8 @@ void __init efi_init(void)
printk(KERN_ERR PFX "Could not map the runtime service table!\n");
/* Map the EFI memory map for use until paging_init() */
- memmap.map = boot_ioremap((unsigned long) EFI_MEMMAP, EFI_MEMMAP_SIZE);
+ memmap.map = boot_ioremap(boot_params.efi_info.efi_memmap,
+ boot_params.efi_info.efi_memmap_size);
if (memmap.map == NULL)
printk(KERN_ERR PFX "Could not map the EFI memory map!\n");
@@ -600,7 +603,8 @@ void __init efi_enter_virtual_mode(void)
void __init
efi_initialize_iomem_resources(struct resource *code_resource,
- struct resource *data_resource)
+ struct resource *data_resource,
+ struct resource *bss_resource)
{
struct resource *res;
efi_memory_desc_t *md;
@@ -672,6 +676,7 @@ efi_initialize_iomem_resources(struct resource *code_resource,
if (md->type == EFI_CONVENTIONAL_MEMORY) {
request_resource(res, code_resource);
request_resource(res, data_resource);
+ request_resource(res, bss_resource);
#ifdef CONFIG_KEXEC
request_resource(res, &crashk_res);
#endif
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index 8099fea0a72f..dc7f938e5015 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -437,7 +437,7 @@ ldt_ss:
* is still available to implement the setting of the high
* 16-bits in the INTERRUPT_RETURN paravirt-op.
*/
- cmpl $0, paravirt_ops+PARAVIRT_enabled
+ cmpl $0, pv_info+PARAVIRT_enabled
jne restore_nocheck
#endif
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index f1cacd4897f7..3a058bb16409 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -988,7 +988,7 @@ child_rip:
movq %rsi, %rdi
call *%rax
# exit
- xorl %edi, %edi
+ mov %eax, %edi
call do_exit
CFI_ENDPROC
ENDPROC(child_rip)
diff --git a/arch/x86/kernel/genapic_64.c b/arch/x86/kernel/genapic_64.c
index 47496a40e84f..ce703e21c912 100644
--- a/arch/x86/kernel/genapic_64.c
+++ b/arch/x86/kernel/genapic_64.c
@@ -24,12 +24,19 @@
#include <acpi/acpi_bus.h>
#endif
-/* which logical CPU number maps to which CPU (physical APIC ID) */
-u8 x86_cpu_to_apicid[NR_CPUS] __read_mostly
+/*
+ * which logical CPU number maps to which CPU (physical APIC ID)
+ *
+ * The following static array is used during kernel startup
+ * and the x86_cpu_to_apicid_ptr contains the address of the
+ * array during this time. Is it zeroed when the per_cpu
+ * data area is removed.
+ */
+u8 x86_cpu_to_apicid_init[NR_CPUS] __initdata
= { [0 ... NR_CPUS-1] = BAD_APICID };
-EXPORT_SYMBOL(x86_cpu_to_apicid);
-
-u8 x86_cpu_to_log_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
+void *x86_cpu_to_apicid_ptr;
+DEFINE_PER_CPU(u8, x86_cpu_to_apicid) = BAD_APICID;
+EXPORT_PER_CPU_SYMBOL(x86_cpu_to_apicid);
struct genapic __read_mostly *genapic = &apic_flat;
diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c
index ecb01eefdd27..07352b74bda6 100644
--- a/arch/x86/kernel/genapic_flat_64.c
+++ b/arch/x86/kernel/genapic_flat_64.c
@@ -52,7 +52,6 @@ static void flat_init_apic_ldr(void)
num = smp_processor_id();
id = 1UL << num;
- x86_cpu_to_log_apicid[num] = id;
apic_write(APIC_DFR, APIC_DFR_FLAT);
val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
val |= SET_APIC_LOGICAL_ID(id);
@@ -173,7 +172,7 @@ static unsigned int physflat_cpu_mask_to_apicid(cpumask_t cpumask)
*/
cpu = first_cpu(cpumask);
if ((unsigned)cpu < NR_CPUS)
- return x86_cpu_to_apicid[cpu];
+ return per_cpu(x86_cpu_to_apicid, cpu);
else
return BAD_APICID;
}
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 8561f626edad..6b3469311e42 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -14,7 +14,6 @@
#include <asm/processor.h>
#include <asm/proto.h>
#include <asm/smp.h>
-#include <asm/bootsetup.h>
#include <asm/setup.h>
#include <asm/desc.h>
#include <asm/pgtable.h>
@@ -36,26 +35,15 @@ static void __init clear_bss(void)
(unsigned long) __bss_stop - (unsigned long) __bss_start);
}
-#define NEW_CL_POINTER 0x228 /* Relative to real mode data */
-#define OLD_CL_MAGIC_ADDR 0x20
-#define OLD_CL_MAGIC 0xA33F
-#define OLD_CL_OFFSET 0x22
-
static void __init copy_bootdata(char *real_mode_data)
{
- unsigned long new_data;
char * command_line;
- memcpy(x86_boot_params, real_mode_data, BOOT_PARAM_SIZE);
- new_data = *(u32 *) (x86_boot_params + NEW_CL_POINTER);
- if (!new_data) {
- if (OLD_CL_MAGIC != *(u16 *)(real_mode_data + OLD_CL_MAGIC_ADDR)) {
- return;
- }
- new_data = __pa(real_mode_data) + *(u16 *)(real_mode_data + OLD_CL_OFFSET);
+ memcpy(&boot_params, real_mode_data, sizeof boot_params);
+ if (boot_params.hdr.cmd_line_ptr) {
+ command_line = __va(boot_params.hdr.cmd_line_ptr);
+ memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
}
- command_line = __va(new_data);
- memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
}
void __init x86_64_start_kernel(char * real_mode_data)
@@ -70,7 +58,7 @@ void __init x86_64_start_kernel(char * real_mode_data)
for (i = 0; i < IDT_ENTRIES; i++)
set_intr_gate(i, early_idt_handler);
- asm volatile("lidt %0" :: "m" (idt_descr));
+ load_idt((const struct desc_ptr *)&idt_descr);
early_printk("Kernel alive\n");
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index 9150ca9b5f80..374b7ece8961 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -51,6 +51,15 @@
*/
LOW_PAGES = 1<<(32-PAGE_SHIFT_asm)
+/*
+ * To preserve the DMA pool in PAGEALLOC kernels, we'll allocate
+ * pagetables from above the 16MB DMA limit, so we'll have to set
+ * up pagetables 16MB more (worst-case):
+ */
+#ifdef CONFIG_DEBUG_PAGEALLOC
+LOW_PAGES = LOW_PAGES + 0x1000000
+#endif
+
#if PTRS_PER_PMD > 1
PAGE_TABLE_SIZE = (LOW_PAGES / PTRS_PER_PMD) + PTRS_PER_PGD
#else
@@ -70,22 +79,30 @@ INIT_MAP_BEYOND_END = BOOTBITMAP_SIZE + (PAGE_TABLE_SIZE + ALLOCATOR_SLOP)*PAGE_
*/
.section .text.head,"ax",@progbits
ENTRY(startup_32)
+ /* check to see if KEEP_SEGMENTS flag is meaningful */
+ cmpw $0x207, BP_version(%esi)
+ jb 1f
+
+ /* test KEEP_SEGMENTS flag to see if the bootloader is asking
+ us to not reload segments */
+ testb $(1<<6), BP_loadflags(%esi)
+ jnz 2f
/*
* Set segments to known values.
*/
- cld
- lgdt boot_gdt_descr - __PAGE_OFFSET
+1: lgdt boot_gdt_descr - __PAGE_OFFSET
movl $(__BOOT_DS),%eax
movl %eax,%ds
movl %eax,%es
movl %eax,%fs
movl %eax,%gs
+2:
/*
* Clear BSS first so that there are no surprises...
- * No need to cld as DF is already clear from cld above...
*/
+ cld
xorl %eax,%eax
movl $__bss_start - __PAGE_OFFSET,%edi
movl $__bss_stop - __PAGE_OFFSET,%ecx
@@ -107,18 +124,42 @@ ENTRY(startup_32)
movsl
movl boot_params - __PAGE_OFFSET + NEW_CL_POINTER,%esi
andl %esi,%esi
- jnz 2f # New command line protocol
- cmpw $(OLD_CL_MAGIC),OLD_CL_MAGIC_ADDR
- jne 1f
- movzwl OLD_CL_OFFSET,%esi
- addl $(OLD_CL_BASE_ADDR),%esi
-2:
+ jz 1f # No comand line
movl $(boot_command_line - __PAGE_OFFSET),%edi
movl $(COMMAND_LINE_SIZE/4),%ecx
rep
movsl
1:
+#ifdef CONFIG_PARAVIRT
+ cmpw $0x207, (boot_params + BP_version - __PAGE_OFFSET)
+ jb default_entry
+
+ /* Paravirt-compatible boot parameters. Look to see what architecture
+ we're booting under. */
+ movl (boot_params + BP_hardware_subarch - __PAGE_OFFSET), %eax
+ cmpl $num_subarch_entries, %eax
+ jae bad_subarch
+
+ movl subarch_entries - __PAGE_OFFSET(,%eax,4), %eax
+ subl $__PAGE_OFFSET, %eax
+ jmp *%eax
+
+bad_subarch:
+WEAK(lguest_entry)
+WEAK(xen_entry)
+ /* Unknown implementation; there's really
+ nothing we can do at this point. */
+ ud2a
+.data
+subarch_entries:
+ .long default_entry /* normal x86/PC */
+ .long lguest_entry /* lguest hypervisor */
+ .long xen_entry /* Xen hypervisor */
+num_subarch_entries = (. - subarch_entries) / 4
+.previous
+#endif /* CONFIG_PARAVIRT */
+
/*
* Initialize page tables. This creates a PDE and a set of page
* tables, which are located immediately beyond _end. The variable
@@ -131,6 +172,7 @@ ENTRY(startup_32)
*/
page_pde_offset = (__PAGE_OFFSET >> 20);
+default_entry:
movl $(pg0 - __PAGE_OFFSET), %edi
movl $(swapper_pg_dir - __PAGE_OFFSET), %edx
movl $0x007, %eax /* 0x007 = PRESENT+RW+USER */
@@ -443,6 +485,7 @@ early_page_fault:
early_fault:
cld
#ifdef CONFIG_PRINTK
+ pusha
movl $(__KERNEL_DS),%eax
movl %eax,%ds
movl %eax,%es
@@ -534,8 +577,15 @@ int_msg:
.asciz "Unknown interrupt or fault at EIP %p %p %p\n"
fault_msg:
- .ascii "Int %d: CR2 %p err %p EIP %p CS %p flags %p\n"
- .asciz "Stack: %p %p %p %p %p %p %p %p\n"
+ .ascii \
+/* fault info: */ "BUG: Int %d: CR2 %p\n" \
+/* pusha regs: */ " EDI %p ESI %p EBP %p ESP %p\n" \
+ " EBX %p EDX %p ECX %p EAX %p\n" \
+/* fault frame: */ " err %p EIP %p CS %p flg %p\n" \
+ \
+ "Stack: %p %p %p %p %p %p %p %p\n" \
+ " %p %p %p %p %p %p %p %p\n" \
+ " %p %p %p %p %p %p %p %p\n"
#include "../../x86/xen/xen-head.S"
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index f8367074da0d..53303f2e5475 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -69,12 +69,15 @@ static inline void hpet_clear_mapping(void)
* HPET command line enable / disable
*/
static int boot_hpet_disable;
+int hpet_force_user;
static int __init hpet_setup(char* str)
{
if (str) {
if (!strncmp("disable", str, 7))
boot_hpet_disable = 1;
+ if (!strncmp("force", str, 5))
+ hpet_force_user = 1;
}
return 1;
}
@@ -350,7 +353,7 @@ static int hpet_clocksource_register(void)
*
* hpet period is in femto seconds per cycle
* so we need to convert this to ns/cyc units
- * aproximated by mult/2^shift
+ * approximated by mult/2^shift
*
* fsec/cyc * 1nsec/1000000fsec = nsec/cyc = mult/2^shift
* fsec/cyc * 1ns/1000000fsec * 2^shift = mult
diff --git a/arch/x86/kernel/i386_ksyms_32.c b/arch/x86/kernel/i386_ksyms_32.c
index e3d4b73bfdb0..edd39ccf139e 100644
--- a/arch/x86/kernel/i386_ksyms_32.c
+++ b/arch/x86/kernel/i386_ksyms_32.c
@@ -1,4 +1,5 @@
#include <linux/module.h>
+#include <asm/semaphore.h>
#include <asm/checksum.h>
#include <asm/desc.h>
diff --git a/arch/x86/kernel/i387_64.c b/arch/x86/kernel/i387_64.c
index 56c1f1147109..bfaff28fb134 100644
--- a/arch/x86/kernel/i387_64.c
+++ b/arch/x86/kernel/i387_64.c
@@ -92,13 +92,14 @@ int save_i387(struct _fpstate __user *buf)
if (task_thread_info(tsk)->status & TS_USEDFPU) {
err = save_i387_checking((struct i387_fxsave_struct __user *)buf);
if (err) return err;
+ task_thread_info(tsk)->status &= ~TS_USEDFPU;
stts();
- } else {
- if (__copy_to_user(buf, &tsk->thread.i387.fxsave,
+ } else {
+ if (__copy_to_user(buf, &tsk->thread.i387.fxsave,
sizeof(struct i387_fxsave_struct)))
return -1;
- }
- return 1;
+ }
+ return 1;
}
/*
diff --git a/arch/x86/kernel/i8253.c b/arch/x86/kernel/i8253.c
index 5cc8841ca2c6..a42c80745325 100644
--- a/arch/x86/kernel/i8253.c
+++ b/arch/x86/kernel/i8253.c
@@ -86,7 +86,7 @@ static int pit_next_event(unsigned long delta, struct clock_event_device *evt)
* On UP the PIT can serve all of the possible timer functions. On SMP systems
* it can be solely used for the global tick.
*
- * The profiling and update capabilites are switched off once the local apic is
+ * The profiling and update capabilities are switched off once the local apic is
* registered. This mechanism replaces the previous #ifdef LOCAL_APIC -
* !using_apic_timer decisions in do_timer_interrupt_hook()
*/
diff --git a/arch/x86/kernel/i8259_32.c b/arch/x86/kernel/i8259_32.c
index 679bb33acbf1..f634fc715c99 100644
--- a/arch/x86/kernel/i8259_32.c
+++ b/arch/x86/kernel/i8259_32.c
@@ -349,7 +349,11 @@ static irqreturn_t math_error_irq(int cpl, void *dev_id)
* New motherboards sometimes make IRQ 13 be a PCI interrupt,
* so allow interrupt sharing.
*/
-static struct irqaction fpu_irq = { math_error_irq, 0, CPU_MASK_NONE, "fpu", NULL, NULL };
+static struct irqaction fpu_irq = {
+ .handler = math_error_irq,
+ .mask = CPU_MASK_NONE,
+ .name = "fpu",
+};
void __init init_ISA_irqs (void)
{
@@ -399,7 +403,8 @@ void __init native_init_IRQ(void)
int vector = FIRST_EXTERNAL_VECTOR + i;
if (i >= NR_IRQS)
break;
- if (vector != SYSCALL_VECTOR)
+ /* SYSCALL_VECTOR was reserved in trap_init. */
+ if (!test_bit(vector, used_vectors))
set_intr_gate(vector, interrupt[i]);
}
diff --git a/arch/x86/kernel/i8259_64.c b/arch/x86/kernel/i8259_64.c
index eb72976cc13c..3f27ea0b9816 100644
--- a/arch/x86/kernel/i8259_64.c
+++ b/arch/x86/kernel/i8259_64.c
@@ -395,7 +395,11 @@ device_initcall(i8259A_init_sysfs);
* IRQ2 is cascade interrupt to second interrupt controller
*/
-static struct irqaction irq2 = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL};
+static struct irqaction irq2 = {
+ .handler = no_action,
+ .mask = CPU_MASK_NONE,
+ .name = "cascade",
+};
DEFINE_PER_CPU(vector_irq_t, vector_irq) = {
[0 ... IRQ0_VECTOR - 1] = -1,
[IRQ0_VECTOR] = 0,
diff --git a/arch/x86/kernel/init_task_32.c b/arch/x86/kernel/init_task.c
index d26fc063a760..468c9c437842 100644
--- a/arch/x86/kernel/init_task_32.c
+++ b/arch/x86/kernel/init_task.c
@@ -15,7 +15,6 @@ static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
struct mm_struct init_mm = INIT_MM(init_mm);
-
EXPORT_SYMBOL(init_mm);
/*
@@ -25,7 +24,7 @@ EXPORT_SYMBOL(init_mm);
* way process stacks are handled. This is done by having a special
* "init_task" linker map entry..
*/
-union thread_union init_thread_union
+union thread_union init_thread_union
__attribute__((__section__(".data.init_task"))) =
{ INIT_THREAD_INFO(init_task) };
@@ -35,12 +34,14 @@ union thread_union init_thread_union
* All other task structs will be allocated on slabs in fork.c
*/
struct task_struct init_task = INIT_TASK(init_task);
-
EXPORT_SYMBOL(init_task);
/*
* per-CPU TSS segments. Threads are completely 'soft' on Linux,
- * no more per-task TSS's.
- */
+ * no more per-task TSS's. The TSS size is kept cacheline-aligned
+ * so they are allowed to end up in the .data.cacheline_aligned
+ * section. Since TSS's are completely CPU-local, we want them
+ * on exact cacheline boundaries, to eliminate cacheline ping-pong.
+ */
DEFINE_PER_CPU_SHARED_ALIGNED(struct tss_struct, init_tss) = INIT_TSS;
diff --git a/arch/x86/kernel/init_task_64.c b/arch/x86/kernel/init_task_64.c
deleted file mode 100644
index 4ff33d4f8551..000000000000
--- a/arch/x86/kernel/init_task_64.c
+++ /dev/null
@@ -1,54 +0,0 @@
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/init_task.h>
-#include <linux/fs.h>
-#include <linux/mqueue.h>
-
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>
-#include <asm/desc.h>
-
-static struct fs_struct init_fs = INIT_FS;
-static struct files_struct init_files = INIT_FILES;
-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-struct mm_struct init_mm = INIT_MM(init_mm);
-
-EXPORT_SYMBOL(init_mm);
-
-/*
- * Initial task structure.
- *
- * We need to make sure that this is 8192-byte aligned due to the
- * way process stacks are handled. This is done by having a special
- * "init_task" linker map entry..
- */
-union thread_union init_thread_union
- __attribute__((__section__(".data.init_task"))) =
- { INIT_THREAD_INFO(init_task) };
-
-/*
- * Initial task structure.
- *
- * All other task structs will be allocated on slabs in fork.c
- */
-struct task_struct init_task = INIT_TASK(init_task);
-
-EXPORT_SYMBOL(init_task);
-/*
- * per-CPU TSS segments. Threads are completely 'soft' on Linux,
- * no more per-task TSS's. The TSS size is kept cacheline-aligned
- * so they are allowed to end up in the .data.cacheline_aligned
- * section. Since TSS's are completely CPU-local, we want them
- * on exact cacheline boundaries, to eliminate cacheline ping-pong.
- */
-DEFINE_PER_CPU_SHARED_ALIGNED(struct tss_struct, init_tss) = INIT_TSS;
-
-/* Copies of the original ist values from the tss are only accessed during
- * debugging, no special alignment required.
- */
-DEFINE_PER_CPU(struct orig_ist, orig_ist);
-
-#define ALIGN_TO_4K __attribute__((section(".data.init_task")))
diff --git a/arch/x86/kernel/io_apic_32.c b/arch/x86/kernel/io_apic_32.c
index e2f4a1c68547..f35c6eb33da9 100644
--- a/arch/x86/kernel/io_apic_32.c
+++ b/arch/x86/kernel/io_apic_32.c
@@ -378,7 +378,7 @@ static struct irq_cpu_info {
#define IRQ_ALLOWED(cpu, allowed_mask) cpu_isset(cpu, allowed_mask)
-#define CPU_TO_PACKAGEINDEX(i) (first_cpu(cpu_sibling_map[i]))
+#define CPU_TO_PACKAGEINDEX(i) (first_cpu(per_cpu(cpu_sibling_map, i)))
static cpumask_t balance_irq_affinity[NR_IRQS] = {
[0 ... NR_IRQS-1] = CPU_MASK_ALL
@@ -584,7 +584,7 @@ tryanotherirq:
imbalance = move_this_load;
- /* For physical_balance case, we accumlated both load
+ /* For physical_balance case, we accumulated both load
* values in the one of the siblings cpu_irq[],
* to use the same code for physical and logical processors
* as much as possible.
@@ -598,7 +598,7 @@ tryanotherirq:
* (A+B)/2 vs B
*/
load = CPU_IRQ(min_loaded) >> 1;
- for_each_cpu_mask(j, cpu_sibling_map[min_loaded]) {
+ for_each_cpu_mask(j, per_cpu(cpu_sibling_map, min_loaded)) {
if (load > CPU_IRQ(j)) {
/* This won't change cpu_sibling_map[min_loaded] */
load = CPU_IRQ(j);
@@ -1198,7 +1198,7 @@ static u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_DEVICE_VECTOR , 0 }
static int __assign_irq_vector(int irq)
{
static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0;
- int vector, offset, i;
+ int vector, offset;
BUG_ON((unsigned)irq >= NR_IRQ_VECTORS);
@@ -1215,11 +1215,8 @@ next:
}
if (vector == current_vector)
return -ENOSPC;
- if (vector == SYSCALL_VECTOR)
+ if (test_and_set_bit(vector, used_vectors))
goto next;
- for (i = 0; i < NR_IRQ_VECTORS; i++)
- if (irq_vector[i] == vector)
- goto next;
current_vector = vector;
current_offset = offset;
@@ -1296,6 +1293,11 @@ static void __init setup_IO_APIC_irqs(void)
continue;
}
+ if (!first_notcon) {
+ apic_printk(APIC_VERBOSE, " not connected.\n");
+ first_notcon = 1;
+ }
+
entry.trigger = irq_trigger(idx);
entry.polarity = irq_polarity(idx);
@@ -2290,6 +2292,12 @@ static inline void __init check_timer(void)
void __init setup_IO_APIC(void)
{
+ int i;
+
+ /* Reserve all the system vectors. */
+ for (i = FIRST_SYSTEM_VECTOR; i < NR_VECTORS; i++)
+ set_bit(i, used_vectors);
+
enable_IO_APIC();
if (acpi_ioapic)
@@ -2467,7 +2475,7 @@ void destroy_irq(unsigned int irq)
}
/*
- * MSI mesage composition
+ * MSI message composition
*/
#ifdef CONFIG_PCI_MSI
static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c
index 966fa1062491..953328b55a30 100644
--- a/arch/x86/kernel/io_apic_64.c
+++ b/arch/x86/kernel/io_apic_64.c
@@ -31,6 +31,7 @@
#include <linux/sysdev.h>
#include <linux/msi.h>
#include <linux/htirq.h>
+#include <linux/dmar.h>
#ifdef CONFIG_ACPI
#include <acpi/acpi_bus.h>
#endif
@@ -875,6 +876,10 @@ static void __init setup_IO_APIC_irqs(void)
apic_printk(APIC_VERBOSE, ", %d-%d", mp_ioapics[apic].mpc_apicid, pin);
continue;
}
+ if (!first_notcon) {
+ apic_printk(APIC_VERBOSE, " not connected.\n");
+ first_notcon = 1;
+ }
irq = pin_2_irq(idx, apic, pin);
add_pin_to_irq(irq, apic, pin);
@@ -885,7 +890,7 @@ static void __init setup_IO_APIC_irqs(void)
}
if (!first_notcon)
- apic_printk(APIC_VERBOSE," not connected.\n");
+ apic_printk(APIC_VERBOSE, " not connected.\n");
}
/*
@@ -1766,7 +1771,7 @@ __setup("no_timer_check", notimercheck);
/*
*
- * IRQ's that are handled by the PIC in the MPS IOAPIC case.
+ * IRQs that are handled by the PIC in the MPS IOAPIC case.
* - IRQ2 is the cascade IRQ, and cannot be a io-apic IRQ.
* Linux doesn't really care, as it's not actually used
* for any interrupt handling anyway.
@@ -1845,7 +1850,7 @@ static struct sysdev_class ioapic_sysdev_class = {
static int __init ioapic_init_sysfs(void)
{
struct sys_device * dev;
- int i, size, error = 0;
+ int i, size, error;
error = sysdev_class_register(&ioapic_sysdev_class);
if (error)
@@ -1854,12 +1859,11 @@ static int __init ioapic_init_sysfs(void)
for (i = 0; i < nr_ioapics; i++ ) {
size = sizeof(struct sys_device) + nr_ioapic_registers[i]
* sizeof(struct IO_APIC_route_entry);
- mp_ioapic_data[i] = kmalloc(size, GFP_KERNEL);
+ mp_ioapic_data[i] = kzalloc(size, GFP_KERNEL);
if (!mp_ioapic_data[i]) {
printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
continue;
}
- memset(mp_ioapic_data[i], 0, size);
dev = &mp_ioapic_data[i]->dev;
dev->id = i;
dev->cls = &ioapic_sysdev_class;
@@ -1918,7 +1922,7 @@ void destroy_irq(unsigned int irq)
}
/*
- * MSI mesage composition
+ * MSI message composition
*/
#ifdef CONFIG_PCI_MSI
static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
@@ -2028,8 +2032,64 @@ void arch_teardown_msi_irq(unsigned int irq)
destroy_irq(irq);
}
-#endif /* CONFIG_PCI_MSI */
+#ifdef CONFIG_DMAR
+#ifdef CONFIG_SMP
+static void dmar_msi_set_affinity(unsigned int irq, cpumask_t mask)
+{
+ struct irq_cfg *cfg = irq_cfg + irq;
+ struct msi_msg msg;
+ unsigned int dest;
+ cpumask_t tmp;
+ cpus_and(tmp, mask, cpu_online_map);
+ if (cpus_empty(tmp))
+ return;
+
+ if (assign_irq_vector(irq, mask))
+ return;
+
+ cpus_and(tmp, cfg->domain, mask);
+ dest = cpu_mask_to_apicid(tmp);
+
+ dmar_msi_read(irq, &msg);
+
+ msg.data &= ~MSI_DATA_VECTOR_MASK;
+ msg.data |= MSI_DATA_VECTOR(cfg->vector);
+ msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
+ msg.address_lo |= MSI_ADDR_DEST_ID(dest);
+
+ dmar_msi_write(irq, &msg);
+ irq_desc[irq].affinity = mask;
+}
+#endif /* CONFIG_SMP */
+
+struct irq_chip dmar_msi_type = {
+ .name = "DMAR_MSI",
+ .unmask = dmar_msi_unmask,
+ .mask = dmar_msi_mask,
+ .ack = ack_apic_edge,
+#ifdef CONFIG_SMP
+ .set_affinity = dmar_msi_set_affinity,
+#endif
+ .retrigger = ioapic_retrigger_irq,
+};
+
+int arch_setup_dmar_msi(unsigned int irq)
+{
+ int ret;
+ struct msi_msg msg;
+
+ ret = msi_compose_msg(NULL, irq, &msg);
+ if (ret < 0)
+ return ret;
+ dmar_msi_write(irq, &msg);
+ set_irq_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq,
+ "edge");
+ return 0;
+}
+#endif
+
+#endif /* CONFIG_PCI_MSI */
/*
* Hypertransport interrupt support
*/
diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c
index e173b763f148..d3fde94f7345 100644
--- a/arch/x86/kernel/irq_32.c
+++ b/arch/x86/kernel/irq_32.c
@@ -255,9 +255,17 @@ int show_interrupts(struct seq_file *p, void *v)
}
if (i < NR_IRQS) {
+ unsigned any_count = 0;
+
spin_lock_irqsave(&irq_desc[i].lock, flags);
+#ifndef CONFIG_SMP
+ any_count = kstat_irqs(i);
+#else
+ for_each_online_cpu(j)
+ any_count |= kstat_cpu(j).irqs[i];
+#endif
action = irq_desc[i].action;
- if (!action)
+ if (!action && !any_count)
goto skip;
seq_printf(p, "%3d: ",i);
#ifndef CONFIG_SMP
@@ -268,10 +276,12 @@ int show_interrupts(struct seq_file *p, void *v)
#endif
seq_printf(p, " %8s", irq_desc[i].chip->name);
seq_printf(p, "-%-8s", irq_desc[i].name);
- seq_printf(p, " %s", action->name);
- for (action=action->next; action; action = action->next)
- seq_printf(p, ", %s", action->name);
+ if (action) {
+ seq_printf(p, " %s", action->name);
+ while ((action = action->next) != NULL)
+ seq_printf(p, ", %s", action->name);
+ }
seq_putc(p, '\n');
skip:
@@ -280,14 +290,41 @@ skip:
seq_printf(p, "NMI: ");
for_each_online_cpu(j)
seq_printf(p, "%10u ", nmi_count(j));
- seq_putc(p, '\n');
+ seq_printf(p, " Non-maskable interrupts\n");
#ifdef CONFIG_X86_LOCAL_APIC
seq_printf(p, "LOC: ");
for_each_online_cpu(j)
seq_printf(p, "%10u ",
per_cpu(irq_stat,j).apic_timer_irqs);
- seq_putc(p, '\n');
+ seq_printf(p, " Local timer interrupts\n");
#endif
+#ifdef CONFIG_SMP
+ seq_printf(p, "RES: ");
+ for_each_online_cpu(j)
+ seq_printf(p, "%10u ",
+ per_cpu(irq_stat,j).irq_resched_count);
+ seq_printf(p, " Rescheduling interrupts\n");
+ seq_printf(p, "CAL: ");
+ for_each_online_cpu(j)
+ seq_printf(p, "%10u ",
+ per_cpu(irq_stat,j).irq_call_count);
+ seq_printf(p, " function call interrupts\n");
+ seq_printf(p, "TLB: ");
+ for_each_online_cpu(j)
+ seq_printf(p, "%10u ",
+ per_cpu(irq_stat,j).irq_tlb_count);
+ seq_printf(p, " TLB shootdowns\n");
+#endif
+ seq_printf(p, "TRM: ");
+ for_each_online_cpu(j)
+ seq_printf(p, "%10u ",
+ per_cpu(irq_stat,j).irq_thermal_count);
+ seq_printf(p, " Thermal event interrupts\n");
+ seq_printf(p, "SPU: ");
+ for_each_online_cpu(j)
+ seq_printf(p, "%10u ",
+ per_cpu(irq_stat,j).irq_spurious_count);
+ seq_printf(p, " Spurious interrupts\n");
seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
#if defined(CONFIG_X86_IO_APIC)
seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c
index 865669efc540..6b5c730d67b9 100644
--- a/arch/x86/kernel/irq_64.c
+++ b/arch/x86/kernel/irq_64.c
@@ -62,9 +62,17 @@ int show_interrupts(struct seq_file *p, void *v)
}
if (i < NR_IRQS) {
+ unsigned any_count = 0;
+
spin_lock_irqsave(&irq_desc[i].lock, flags);
+#ifndef CONFIG_SMP
+ any_count = kstat_irqs(i);
+#else
+ for_each_online_cpu(j)
+ any_count |= kstat_cpu(j).irqs[i];
+#endif
action = irq_desc[i].action;
- if (!action)
+ if (!action && !any_count)
goto skip;
seq_printf(p, "%3d: ",i);
#ifndef CONFIG_SMP
@@ -76,9 +84,11 @@ int show_interrupts(struct seq_file *p, void *v)
seq_printf(p, " %8s", irq_desc[i].chip->name);
seq_printf(p, "-%-8s", irq_desc[i].name);
- seq_printf(p, " %s", action->name);
- for (action=action->next; action; action = action->next)
- seq_printf(p, ", %s", action->name);
+ if (action) {
+ seq_printf(p, " %s", action->name);
+ while ((action = action->next) != NULL)
+ seq_printf(p, ", %s", action->name);
+ }
seq_putc(p, '\n');
skip:
spin_unlock_irqrestore(&irq_desc[i].lock, flags);
@@ -86,11 +96,37 @@ skip:
seq_printf(p, "NMI: ");
for_each_online_cpu(j)
seq_printf(p, "%10u ", cpu_pda(j)->__nmi_count);
- seq_putc(p, '\n');
+ seq_printf(p, " Non-maskable interrupts\n");
seq_printf(p, "LOC: ");
for_each_online_cpu(j)
seq_printf(p, "%10u ", cpu_pda(j)->apic_timer_irqs);
- seq_putc(p, '\n');
+ seq_printf(p, " Local timer interrupts\n");
+#ifdef CONFIG_SMP
+ seq_printf(p, "RES: ");
+ for_each_online_cpu(j)
+ seq_printf(p, "%10u ", cpu_pda(j)->irq_resched_count);
+ seq_printf(p, " Rescheduling interrupts\n");
+ seq_printf(p, "CAL: ");
+ for_each_online_cpu(j)
+ seq_printf(p, "%10u ", cpu_pda(j)->irq_call_count);
+ seq_printf(p, " function call interrupts\n");
+ seq_printf(p, "TLB: ");
+ for_each_online_cpu(j)
+ seq_printf(p, "%10u ", cpu_pda(j)->irq_tlb_count);
+ seq_printf(p, " TLB shootdowns\n");
+#endif
+ seq_printf(p, "TRM: ");
+ for_each_online_cpu(j)
+ seq_printf(p, "%10u ", cpu_pda(j)->irq_thermal_count);
+ seq_printf(p, " Thermal event interrupts\n");
+ seq_printf(p, "THR: ");
+ for_each_online_cpu(j)
+ seq_printf(p, "%10u ", cpu_pda(j)->irq_threshold_count);
+ seq_printf(p, " Threshold APIC interrupts\n");
+ seq_printf(p, "SPU: ");
+ for_each_online_cpu(j)
+ seq_printf(p, "%10u ", cpu_pda(j)->irq_spurious_count);
+ seq_printf(p, " Spurious interrupts\n");
seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
}
return 0;
diff --git a/arch/x86/kernel/kprobes_32.c b/arch/x86/kernel/kprobes_32.c
index e7d0d3c2ef64..d87a523070d1 100644
--- a/arch/x86/kernel/kprobes_32.c
+++ b/arch/x86/kernel/kprobes_32.c
@@ -41,6 +41,13 @@ void jprobe_return_end(void);
DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
+struct kretprobe_blackpoint kretprobe_blacklist[] = {
+ {"__switch_to", }, /* This function switches only current task, but
+ doesn't switch kernel stack.*/
+ {NULL, NULL} /* Terminator */
+};
+const int kretprobe_blacklist_size = ARRAY_SIZE(kretprobe_blacklist);
+
/* insert a jmp code */
static __always_inline void set_jmp_op(void *from, void *to)
{
@@ -557,12 +564,7 @@ static int __kprobes post_kprobe_handler(struct pt_regs *regs)
resume_execution(cur, regs, kcb);
regs->eflags |= kcb->kprobe_saved_eflags;
-#ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT
- if (raw_irqs_disabled_flags(regs->eflags))
- trace_hardirqs_off();
- else
- trace_hardirqs_on();
-#endif
+ trace_hardirqs_fixup_flags(regs->eflags);
/*Restore back the original saved kprobes variables and continue. */
if (kcb->kprobe_status == KPROBE_REENTER) {
@@ -584,7 +586,7 @@ out:
return 1;
}
-static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
{
struct kprobe *cur = kprobe_running();
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
@@ -666,7 +668,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
ret = NOTIFY_STOP;
break;
case DIE_GPF:
- case DIE_PAGE_FAULT:
/* kprobe_running() needs smp_processor_id() */
preempt_disable();
if (kprobe_running() &&
diff --git a/arch/x86/kernel/kprobes_64.c b/arch/x86/kernel/kprobes_64.c
index 62e28e52d784..3db3611933d8 100644
--- a/arch/x86/kernel/kprobes_64.c
+++ b/arch/x86/kernel/kprobes_64.c
@@ -48,6 +48,13 @@ static void __kprobes arch_copy_kprobe(struct kprobe *p);
DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
+struct kretprobe_blackpoint kretprobe_blacklist[] = {
+ {"__switch_to", }, /* This function switches only current task, but
+ doesn't switch kernel stack.*/
+ {NULL, NULL} /* Terminator */
+};
+const int kretprobe_blacklist_size = ARRAY_SIZE(kretprobe_blacklist);
+
/*
* returns non-zero if opcode modifies the interrupt flag.
*/
@@ -544,12 +551,7 @@ int __kprobes post_kprobe_handler(struct pt_regs *regs)
resume_execution(cur, regs, kcb);
regs->eflags |= kcb->kprobe_saved_rflags;
-#ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT
- if (raw_irqs_disabled_flags(regs->eflags))
- trace_hardirqs_off();
- else
- trace_hardirqs_on();
-#endif
+ trace_hardirqs_fixup_flags(regs->eflags);
/* Restore the original saved kprobes variables and continue. */
if (kcb->kprobe_status == KPROBE_REENTER) {
@@ -657,7 +659,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
ret = NOTIFY_STOP;
break;
case DIE_GPF:
- case DIE_PAGE_FAULT:
/* kprobe_running() needs smp_processor_id() */
preempt_disable();
if (kprobe_running() &&
diff --git a/arch/x86/kernel/ldt_32.c b/arch/x86/kernel/ldt_32.c
index a8b18421863a..9ff90a27c45f 100644
--- a/arch/x86/kernel/ldt_32.c
+++ b/arch/x86/kernel/ldt_32.c
@@ -92,13 +92,13 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
struct mm_struct * old_mm;
int retval = 0;
- init_MUTEX(&mm->context.sem);
+ mutex_init(&mm->context.lock);
mm->context.size = 0;
old_mm = current->mm;
if (old_mm && old_mm->context.size > 0) {
- down(&old_mm->context.sem);
+ mutex_lock(&old_mm->context.lock);
retval = copy_ldt(&mm->context, &old_mm->context);
- up(&old_mm->context.sem);
+ mutex_unlock(&old_mm->context.lock);
}
return retval;
}
@@ -130,7 +130,7 @@ static int read_ldt(void __user * ptr, unsigned long bytecount)
if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES)
bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES;
- down(&mm->context.sem);
+ mutex_lock(&mm->context.lock);
size = mm->context.size*LDT_ENTRY_SIZE;
if (size > bytecount)
size = bytecount;
@@ -138,7 +138,7 @@ static int read_ldt(void __user * ptr, unsigned long bytecount)
err = 0;
if (copy_to_user(ptr, mm->context.ldt, size))
err = -EFAULT;
- up(&mm->context.sem);
+ mutex_unlock(&mm->context.lock);
if (err < 0)
goto error_return;
if (size != bytecount) {
@@ -194,7 +194,7 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int oldmode)
goto out;
}
- down(&mm->context.sem);
+ mutex_lock(&mm->context.lock);
if (ldt_info.entry_number >= mm->context.size) {
error = alloc_ldt(&current->mm->context, ldt_info.entry_number+1, 1);
if (error < 0)
@@ -221,7 +221,7 @@ install:
error = 0;
out_unlock:
- up(&mm->context.sem);
+ mutex_unlock(&mm->context.lock);
out:
return error;
}
diff --git a/arch/x86/kernel/ldt_64.c b/arch/x86/kernel/ldt_64.c
index 3796523d616a..60e57abb8e90 100644
--- a/arch/x86/kernel/ldt_64.c
+++ b/arch/x86/kernel/ldt_64.c
@@ -96,13 +96,13 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
struct mm_struct * old_mm;
int retval = 0;
- init_MUTEX(&mm->context.sem);
+ mutex_init(&mm->context.lock);
mm->context.size = 0;
old_mm = current->mm;
if (old_mm && old_mm->context.size > 0) {
- down(&old_mm->context.sem);
+ mutex_lock(&old_mm->context.lock);
retval = copy_ldt(&mm->context, &old_mm->context);
- up(&old_mm->context.sem);
+ mutex_unlock(&old_mm->context.lock);
}
return retval;
}
@@ -133,7 +133,7 @@ static int read_ldt(void __user * ptr, unsigned long bytecount)
if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES)
bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES;
- down(&mm->context.sem);
+ mutex_lock(&mm->context.lock);
size = mm->context.size*LDT_ENTRY_SIZE;
if (size > bytecount)
size = bytecount;
@@ -141,7 +141,7 @@ static int read_ldt(void __user * ptr, unsigned long bytecount)
err = 0;
if (copy_to_user(ptr, mm->context.ldt, size))
err = -EFAULT;
- up(&mm->context.sem);
+ mutex_unlock(&mm->context.lock);
if (err < 0)
goto error_return;
if (size != bytecount) {
@@ -193,7 +193,7 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int oldmode)
goto out;
}
- down(&mm->context.sem);
+ mutex_lock(&mm->context.lock);
if (ldt_info.entry_number >= (unsigned)mm->context.size) {
error = alloc_ldt(&current->mm->context, ldt_info.entry_number+1, 1);
if (error < 0)
@@ -223,7 +223,7 @@ install:
error = 0;
out_unlock:
- up(&mm->context.sem);
+ mutex_unlock(&mm->context.lock);
out:
return error;
}
diff --git a/arch/x86/kernel/machine_kexec_32.c b/arch/x86/kernel/machine_kexec_32.c
index deda9a221cf2..11b935f4f886 100644
--- a/arch/x86/kernel/machine_kexec_32.c
+++ b/arch/x86/kernel/machine_kexec_32.c
@@ -10,6 +10,7 @@
#include <linux/kexec.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/numa.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
@@ -148,24 +149,14 @@ NORET_TYPE void machine_kexec(struct kimage *image)
image->start, cpu_has_pae);
}
-/* crashkernel=size@addr specifies the location to reserve for
- * a crash kernel. By reserving this memory we guarantee
- * that linux never sets it up as a DMA target.
- * Useful for holding code to do something appropriate
- * after a kernel panic.
- */
-static int __init parse_crashkernel(char *arg)
+void arch_crash_save_vmcoreinfo(void)
{
- unsigned long size, base;
- size = memparse(arg, &arg);
- if (*arg == '@') {
- base = memparse(arg+1, &arg);
- /* FIXME: Do I want a sanity check
- * to validate the memory range?
- */
- crashk_res.start = base;
- crashk_res.end = base + size - 1;
- }
- return 0;
+#ifdef CONFIG_ARCH_DISCONTIGMEM_ENABLE
+ VMCOREINFO_SYMBOL(node_data);
+ VMCOREINFO_LENGTH(node_data, MAX_NUMNODES);
+#endif
+#ifdef CONFIG_X86_PAE
+ VMCOREINFO_CONFIG(X86_PAE);
+#endif
}
-early_param("crashkernel", parse_crashkernel);
+
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index cd1899a2f0c5..aa3d2c8f7737 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -10,6 +10,7 @@
#include <linux/kexec.h>
#include <linux/string.h>
#include <linux/reboot.h>
+#include <linux/numa.h>
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
#include <asm/mmu_context.h>
@@ -230,30 +231,13 @@ NORET_TYPE void machine_kexec(struct kimage *image)
image->start);
}
-/* crashkernel=size@addr specifies the location to reserve for
- * a crash kernel. By reserving this memory we guarantee
- * that linux never set's it up as a DMA target.
- * Useful for holding code to do something appropriate
- * after a kernel panic.
- */
-static int __init setup_crashkernel(char *arg)
+void arch_crash_save_vmcoreinfo(void)
{
- unsigned long size, base;
- char *p;
- if (!arg)
- return -EINVAL;
- size = memparse(arg, &p);
- if (arg == p)
- return -EINVAL;
- if (*p == '@') {
- base = memparse(p+1, &p);
- /* FIXME: Do I want a sanity check to validate the
- * memory range? Yes you do, but it's too early for
- * e820 -AK */
- crashk_res.start = base;
- crashk_res.end = base + size - 1;
- }
- return 0;
+ VMCOREINFO_SYMBOL(init_level4_pgt);
+
+#ifdef CONFIG_ARCH_DISCONTIGMEM_ENABLE
+ VMCOREINFO_SYMBOL(node_data);
+ VMCOREINFO_LENGTH(node_data, MAX_NUMNODES);
+#endif
}
-early_param("crashkernel", setup_crashkernel);
diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c
index 09cf78110358..09c315214a5e 100644
--- a/arch/x86/kernel/microcode.c
+++ b/arch/x86/kernel/microcode.c
@@ -132,7 +132,7 @@ static struct ucode_cpu_info {
static void collect_cpu_info(int cpu_num)
{
- struct cpuinfo_x86 *c = cpu_data + cpu_num;
+ struct cpuinfo_x86 *c = &cpu_data(cpu_num);
struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
unsigned int val[2];
@@ -522,7 +522,7 @@ static struct platform_device *microcode_pdev;
static int cpu_request_microcode(int cpu)
{
char name[30];
- struct cpuinfo_x86 *c = cpu_data + cpu;
+ struct cpuinfo_x86 *c = &cpu_data(cpu);
const struct firmware *firmware;
void *buf;
unsigned long size;
@@ -570,7 +570,7 @@ static int cpu_request_microcode(int cpu)
static int apply_microcode_check_cpu(int cpu)
{
- struct cpuinfo_x86 *c = cpu_data + cpu;
+ struct cpuinfo_x86 *c = &cpu_data(cpu);
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
cpumask_t old;
unsigned int val[2];
diff --git a/arch/x86/kernel/mpparse_32.c b/arch/x86/kernel/mpparse_32.c
index 13abb4ebfb79..7a05a7f6099a 100644
--- a/arch/x86/kernel/mpparse_32.c
+++ b/arch/x86/kernel/mpparse_32.c
@@ -1001,7 +1001,7 @@ void __init mp_config_acpi_legacy_irqs (void)
/*
* Use the default configuration for the IRQs 0-15. Unless
- * overriden by (MADT) interrupt source override entries.
+ * overridden by (MADT) interrupt source override entries.
*/
for (i = 0; i < 16; i++) {
int idx;
diff --git a/arch/x86/kernel/mpparse_64.c b/arch/x86/kernel/mpparse_64.c
index 8bf0ca03ac8e..ef4aab123581 100644
--- a/arch/x86/kernel/mpparse_64.c
+++ b/arch/x86/kernel/mpparse_64.c
@@ -57,6 +57,8 @@ unsigned long mp_lapic_addr = 0;
/* Processor that is doing the boot up */
unsigned int boot_cpu_id = -1U;
+EXPORT_SYMBOL(boot_cpu_id);
+
/* Internal processor count */
unsigned int num_processors __cpuinitdata = 0;
@@ -86,7 +88,7 @@ static int __init mpf_checksum(unsigned char *mp, int len)
return sum & 0xFF;
}
-static void __cpuinit MP_processor_info (struct mpc_config_processor *m)
+static void __cpuinit MP_processor_info(struct mpc_config_processor *m)
{
int cpu;
cpumask_t tmp_map;
@@ -123,7 +125,18 @@ static void __cpuinit MP_processor_info (struct mpc_config_processor *m)
cpu = 0;
}
bios_cpu_apicid[cpu] = m->mpc_apicid;
- x86_cpu_to_apicid[cpu] = m->mpc_apicid;
+ /*
+ * We get called early in the the start_kernel initialization
+ * process when the per_cpu data area is not yet setup, so we
+ * use a static array that is removed after the per_cpu data
+ * area is created.
+ */
+ if (x86_cpu_to_apicid_ptr) {
+ u8 *x86_cpu_to_apicid = (u8 *)x86_cpu_to_apicid_ptr;
+ x86_cpu_to_apicid[cpu] = m->mpc_apicid;
+ } else {
+ per_cpu(x86_cpu_to_apicid, cpu) = m->mpc_apicid;
+ }
cpu_set(cpu, cpu_possible_map);
cpu_set(cpu, cpu_present_map);
diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c
index c044de310b69..ee6eba4ecfea 100644
--- a/arch/x86/kernel/msr.c
+++ b/arch/x86/kernel/msr.c
@@ -112,7 +112,7 @@ static ssize_t msr_write(struct file *file, const char __user *buf,
static int msr_open(struct inode *inode, struct file *file)
{
unsigned int cpu = iminor(file->f_path.dentry->d_inode);
- struct cpuinfo_x86 *c = &(cpu_data)[cpu];
+ struct cpuinfo_x86 *c = &cpu_data(cpu);
if (cpu >= NR_CPUS || !cpu_online(cpu))
return -ENXIO; /* No such CPU */
@@ -133,37 +133,42 @@ static const struct file_operations msr_fops = {
.open = msr_open,
};
-static int msr_device_create(int i)
+static int __cpuinit msr_device_create(int cpu)
{
- int err = 0;
struct device *dev;
- dev = device_create(msr_class, NULL, MKDEV(MSR_MAJOR, i), "msr%d",i);
- if (IS_ERR(dev))
- err = PTR_ERR(dev);
- return err;
+ dev = device_create(msr_class, NULL, MKDEV(MSR_MAJOR, cpu),
+ "msr%d", cpu);
+ return IS_ERR(dev) ? PTR_ERR(dev) : 0;
}
-static int msr_class_cpu_callback(struct notifier_block *nfb,
+static void msr_device_destroy(int cpu)
+{
+ device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu));
+}
+
+static int __cpuinit msr_class_cpu_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned long)hcpu;
+ int err = 0;
switch (action) {
- case CPU_ONLINE:
- case CPU_ONLINE_FROZEN:
- msr_device_create(cpu);
+ case CPU_UP_PREPARE:
+ case CPU_UP_PREPARE_FROZEN:
+ err = msr_device_create(cpu);
break;
+ case CPU_UP_CANCELED:
+ case CPU_UP_CANCELED_FROZEN:
case CPU_DEAD:
case CPU_DEAD_FROZEN:
- device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu));
+ msr_device_destroy(cpu);
break;
}
- return NOTIFY_OK;
+ return err ? NOTIFY_BAD : NOTIFY_OK;
}
-static struct notifier_block __cpuinitdata msr_class_cpu_notifier =
-{
+static struct notifier_block __cpuinitdata msr_class_cpu_notifier = {
.notifier_call = msr_class_cpu_callback,
};
@@ -196,7 +201,7 @@ static int __init msr_init(void)
out_class:
i = 0;
for_each_online_cpu(i)
- device_destroy(msr_class, MKDEV(MSR_MAJOR, i));
+ msr_device_destroy(i);
class_destroy(msr_class);
out_chrdev:
unregister_chrdev(MSR_MAJOR, "cpu/msr");
@@ -208,7 +213,7 @@ static void __exit msr_exit(void)
{
int cpu = 0;
for_each_online_cpu(cpu)
- device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu));
+ msr_device_destroy(cpu);
class_destroy(msr_class);
unregister_chrdev(MSR_MAJOR, "cpu/msr");
unregister_hotcpu_notifier(&msr_class_cpu_notifier);
diff --git a/arch/x86/kernel/nmi_32.c b/arch/x86/kernel/nmi_32.c
index f803ed0ed1c4..600fd404e440 100644
--- a/arch/x86/kernel/nmi_32.c
+++ b/arch/x86/kernel/nmi_32.c
@@ -51,13 +51,13 @@ static int unknown_nmi_panic_callback(struct pt_regs *regs, int cpu);
static int endflag __initdata = 0;
-#ifdef CONFIG_SMP
/* The performance counters used by NMI_LOCAL_APIC don't trigger when
* the CPU is idle. To make sure the NMI watchdog really ticks on all
* CPUs during the test make them busy.
*/
static __init void nmi_cpu_busy(void *data)
{
+#ifdef CONFIG_SMP
local_irq_enable_in_hardirq();
/* Intentionally don't use cpu_relax here. This is
to make sure that the performance counter really ticks,
@@ -67,8 +67,8 @@ static __init void nmi_cpu_busy(void *data)
care if they get somewhat less cycles. */
while (endflag == 0)
mb();
-}
#endif
+}
static int __init check_nmi_watchdog(void)
{
diff --git a/arch/x86/kernel/paravirt_32.c b/arch/x86/kernel/paravirt_32.c
index 739cfb207dd7..6a80d67c2121 100644
--- a/arch/x86/kernel/paravirt_32.c
+++ b/arch/x86/kernel/paravirt_32.c
@@ -42,32 +42,33 @@ void _paravirt_nop(void)
static void __init default_banner(void)
{
printk(KERN_INFO "Booting paravirtualized kernel on %s\n",
- paravirt_ops.name);
+ pv_info.name);
}
char *memory_setup(void)
{
- return paravirt_ops.memory_setup();
+ return pv_init_ops.memory_setup();
}
/* Simple instruction patching code. */
-#define DEF_NATIVE(name, code) \
- extern const char start_##name[], end_##name[]; \
- asm("start_" #name ": " code "; end_" #name ":")
-
-DEF_NATIVE(irq_disable, "cli");
-DEF_NATIVE(irq_enable, "sti");
-DEF_NATIVE(restore_fl, "push %eax; popf");
-DEF_NATIVE(save_fl, "pushf; pop %eax");
-DEF_NATIVE(iret, "iret");
-DEF_NATIVE(irq_enable_sysexit, "sti; sysexit");
-DEF_NATIVE(read_cr2, "mov %cr2, %eax");
-DEF_NATIVE(write_cr3, "mov %eax, %cr3");
-DEF_NATIVE(read_cr3, "mov %cr3, %eax");
-DEF_NATIVE(clts, "clts");
-DEF_NATIVE(read_tsc, "rdtsc");
-
-DEF_NATIVE(ud2a, "ud2a");
+#define DEF_NATIVE(ops, name, code) \
+ extern const char start_##ops##_##name[], end_##ops##_##name[]; \
+ asm("start_" #ops "_" #name ": " code "; end_" #ops "_" #name ":")
+
+DEF_NATIVE(pv_irq_ops, irq_disable, "cli");
+DEF_NATIVE(pv_irq_ops, irq_enable, "sti");
+DEF_NATIVE(pv_irq_ops, restore_fl, "push %eax; popf");
+DEF_NATIVE(pv_irq_ops, save_fl, "pushf; pop %eax");
+DEF_NATIVE(pv_cpu_ops, iret, "iret");
+DEF_NATIVE(pv_cpu_ops, irq_enable_sysexit, "sti; sysexit");
+DEF_NATIVE(pv_mmu_ops, read_cr2, "mov %cr2, %eax");
+DEF_NATIVE(pv_mmu_ops, write_cr3, "mov %eax, %cr3");
+DEF_NATIVE(pv_mmu_ops, read_cr3, "mov %cr3, %eax");
+DEF_NATIVE(pv_cpu_ops, clts, "clts");
+DEF_NATIVE(pv_cpu_ops, read_tsc, "rdtsc");
+
+/* Undefined instruction for dealing with missing ops pointers. */
+static const unsigned char ud2a[] = { 0x0f, 0x0b };
static unsigned native_patch(u8 type, u16 clobbers, void *ibuf,
unsigned long addr, unsigned len)
@@ -76,37 +77,29 @@ static unsigned native_patch(u8 type, u16 clobbers, void *ibuf,
unsigned ret;
switch(type) {
-#define SITE(x) case PARAVIRT_PATCH(x): start = start_##x; end = end_##x; goto patch_site
- SITE(irq_disable);
- SITE(irq_enable);
- SITE(restore_fl);
- SITE(save_fl);
- SITE(iret);
- SITE(irq_enable_sysexit);
- SITE(read_cr2);
- SITE(read_cr3);
- SITE(write_cr3);
- SITE(clts);
- SITE(read_tsc);
+#define SITE(ops, x) \
+ case PARAVIRT_PATCH(ops.x): \
+ start = start_##ops##_##x; \
+ end = end_##ops##_##x; \
+ goto patch_site
+
+ SITE(pv_irq_ops, irq_disable);
+ SITE(pv_irq_ops, irq_enable);
+ SITE(pv_irq_ops, restore_fl);
+ SITE(pv_irq_ops, save_fl);
+ SITE(pv_cpu_ops, iret);
+ SITE(pv_cpu_ops, irq_enable_sysexit);
+ SITE(pv_mmu_ops, read_cr2);
+ SITE(pv_mmu_ops, read_cr3);
+ SITE(pv_mmu_ops, write_cr3);
+ SITE(pv_cpu_ops, clts);
+ SITE(pv_cpu_ops, read_tsc);
#undef SITE
patch_site:
ret = paravirt_patch_insns(ibuf, len, start, end);
break;
- case PARAVIRT_PATCH(make_pgd):
- case PARAVIRT_PATCH(make_pte):
- case PARAVIRT_PATCH(pgd_val):
- case PARAVIRT_PATCH(pte_val):
-#ifdef CONFIG_X86_PAE
- case PARAVIRT_PATCH(make_pmd):
- case PARAVIRT_PATCH(pmd_val):
-#endif
- /* These functions end up returning exactly what
- they're passed, in the same registers. */
- ret = paravirt_patch_nop();
- break;
-
default:
ret = paravirt_patch_default(type, clobbers, ibuf, addr, len);
break;
@@ -150,7 +143,7 @@ unsigned paravirt_patch_call(void *insnbuf,
return 5;
}
-unsigned paravirt_patch_jmp(const void *target, void *insnbuf,
+unsigned paravirt_patch_jmp(void *insnbuf, const void *target,
unsigned long addr, unsigned len)
{
struct branch *b = insnbuf;
@@ -165,22 +158,37 @@ unsigned paravirt_patch_jmp(const void *target, void *insnbuf,
return 5;
}
+/* Neat trick to map patch type back to the call within the
+ * corresponding structure. */
+static void *get_call_destination(u8 type)
+{
+ struct paravirt_patch_template tmpl = {
+ .pv_init_ops = pv_init_ops,
+ .pv_time_ops = pv_time_ops,
+ .pv_cpu_ops = pv_cpu_ops,
+ .pv_irq_ops = pv_irq_ops,
+ .pv_apic_ops = pv_apic_ops,
+ .pv_mmu_ops = pv_mmu_ops,
+ };
+ return *((void **)&tmpl + type);
+}
+
unsigned paravirt_patch_default(u8 type, u16 clobbers, void *insnbuf,
unsigned long addr, unsigned len)
{
- void *opfunc = *((void **)&paravirt_ops + type);
+ void *opfunc = get_call_destination(type);
unsigned ret;
if (opfunc == NULL)
/* If there's no function, patch it with a ud2a (BUG) */
- ret = paravirt_patch_insns(insnbuf, len, start_ud2a, end_ud2a);
+ ret = paravirt_patch_insns(insnbuf, len, ud2a, ud2a+sizeof(ud2a));
else if (opfunc == paravirt_nop)
/* If the operation is a nop, then nop the callsite */
ret = paravirt_patch_nop();
- else if (type == PARAVIRT_PATCH(iret) ||
- type == PARAVIRT_PATCH(irq_enable_sysexit))
+ else if (type == PARAVIRT_PATCH(pv_cpu_ops.iret) ||
+ type == PARAVIRT_PATCH(pv_cpu_ops.irq_enable_sysexit))
/* If operation requires a jmp, then jmp */
- ret = paravirt_patch_jmp(opfunc, insnbuf, addr, len);
+ ret = paravirt_patch_jmp(insnbuf, opfunc, addr, len);
else
/* Otherwise call the function; assume target could
clobber any caller-save reg */
@@ -205,7 +213,7 @@ unsigned paravirt_patch_insns(void *insnbuf, unsigned len,
void init_IRQ(void)
{
- paravirt_ops.init_IRQ();
+ pv_irq_ops.init_IRQ();
}
static void native_flush_tlb(void)
@@ -233,7 +241,7 @@ extern void native_irq_enable_sysexit(void);
static int __init print_banner(void)
{
- paravirt_ops.banner();
+ pv_init_ops.banner();
return 0;
}
core_initcall(print_banner);
@@ -273,47 +281,96 @@ int paravirt_disable_iospace(void)
return ret;
}
-struct paravirt_ops paravirt_ops = {
+static DEFINE_PER_CPU(enum paravirt_lazy_mode, paravirt_lazy_mode) = PARAVIRT_LAZY_NONE;
+
+static inline void enter_lazy(enum paravirt_lazy_mode mode)
+{
+ BUG_ON(x86_read_percpu(paravirt_lazy_mode) != PARAVIRT_LAZY_NONE);
+ BUG_ON(preemptible());
+
+ x86_write_percpu(paravirt_lazy_mode, mode);
+}
+
+void paravirt_leave_lazy(enum paravirt_lazy_mode mode)
+{
+ BUG_ON(x86_read_percpu(paravirt_lazy_mode) != mode);
+ BUG_ON(preemptible());
+
+ x86_write_percpu(paravirt_lazy_mode, PARAVIRT_LAZY_NONE);
+}
+
+void paravirt_enter_lazy_mmu(void)
+{
+ enter_lazy(PARAVIRT_LAZY_MMU);
+}
+
+void paravirt_leave_lazy_mmu(void)
+{
+ paravirt_leave_lazy(PARAVIRT_LAZY_MMU);
+}
+
+void paravirt_enter_lazy_cpu(void)
+{
+ enter_lazy(PARAVIRT_LAZY_CPU);
+}
+
+void paravirt_leave_lazy_cpu(void)
+{
+ paravirt_leave_lazy(PARAVIRT_LAZY_CPU);
+}
+
+enum paravirt_lazy_mode paravirt_get_lazy_mode(void)
+{
+ return x86_read_percpu(paravirt_lazy_mode);
+}
+
+struct pv_info pv_info = {
.name = "bare hardware",
.paravirt_enabled = 0,
.kernel_rpl = 0,
.shared_kernel_pmd = 1, /* Only used when CONFIG_X86_PAE is set */
+};
- .patch = native_patch,
+struct pv_init_ops pv_init_ops = {
+ .patch = native_patch,
.banner = default_banner,
.arch_setup = paravirt_nop,
.memory_setup = machine_specific_memory_setup,
+};
+
+struct pv_time_ops pv_time_ops = {
+ .time_init = hpet_time_init,
.get_wallclock = native_get_wallclock,
.set_wallclock = native_set_wallclock,
- .time_init = hpet_time_init,
+ .sched_clock = native_sched_clock,
+ .get_cpu_khz = native_calculate_cpu_khz,
+};
+
+struct pv_irq_ops pv_irq_ops = {
.init_IRQ = native_init_IRQ,
+ .save_fl = native_save_fl,
+ .restore_fl = native_restore_fl,
+ .irq_disable = native_irq_disable,
+ .irq_enable = native_irq_enable,
+ .safe_halt = native_safe_halt,
+ .halt = native_halt,
+};
+struct pv_cpu_ops pv_cpu_ops = {
.cpuid = native_cpuid,
.get_debugreg = native_get_debugreg,
.set_debugreg = native_set_debugreg,
.clts = native_clts,
.read_cr0 = native_read_cr0,
.write_cr0 = native_write_cr0,
- .read_cr2 = native_read_cr2,
- .write_cr2 = native_write_cr2,
- .read_cr3 = native_read_cr3,
- .write_cr3 = native_write_cr3,
.read_cr4 = native_read_cr4,
.read_cr4_safe = native_read_cr4_safe,
.write_cr4 = native_write_cr4,
- .save_fl = native_save_fl,
- .restore_fl = native_restore_fl,
- .irq_disable = native_irq_disable,
- .irq_enable = native_irq_enable,
- .safe_halt = native_safe_halt,
- .halt = native_halt,
.wbinvd = native_wbinvd,
.read_msr = native_read_msr_safe,
.write_msr = native_write_msr_safe,
.read_tsc = native_read_tsc,
.read_pmc = native_read_pmc,
- .sched_clock = native_sched_clock,
- .get_cpu_khz = native_calculate_cpu_khz,
.load_tr_desc = native_load_tr_desc,
.set_ldt = native_set_ldt,
.load_gdt = native_load_gdt,
@@ -327,9 +384,19 @@ struct paravirt_ops paravirt_ops = {
.write_idt_entry = write_dt_entry,
.load_esp0 = native_load_esp0,
+ .irq_enable_sysexit = native_irq_enable_sysexit,
+ .iret = native_iret,
+
.set_iopl_mask = native_set_iopl_mask,
.io_delay = native_io_delay,
+ .lazy_mode = {
+ .enter = paravirt_nop,
+ .leave = paravirt_nop,
+ },
+};
+
+struct pv_apic_ops pv_apic_ops = {
#ifdef CONFIG_X86_LOCAL_APIC
.apic_write = native_apic_write,
.apic_write_atomic = native_apic_write_atomic,
@@ -338,11 +405,17 @@ struct paravirt_ops paravirt_ops = {
.setup_secondary_clock = setup_secondary_APIC_clock,
.startup_ipi_hook = paravirt_nop,
#endif
- .set_lazy_mode = paravirt_nop,
+};
+struct pv_mmu_ops pv_mmu_ops = {
.pagetable_setup_start = native_pagetable_setup_start,
.pagetable_setup_done = native_pagetable_setup_done,
+ .read_cr2 = native_read_cr2,
+ .write_cr2 = native_write_cr2,
+ .read_cr3 = native_read_cr3,
+ .write_cr3 = native_write_cr3,
+
.flush_tlb_user = native_flush_tlb,
.flush_tlb_kernel = native_flush_tlb_global,
.flush_tlb_single = native_flush_tlb_single,
@@ -381,12 +454,19 @@ struct paravirt_ops paravirt_ops = {
.make_pte = native_make_pte,
.make_pgd = native_make_pgd,
- .irq_enable_sysexit = native_irq_enable_sysexit,
- .iret = native_iret,
-
.dup_mmap = paravirt_nop,
.exit_mmap = paravirt_nop,
.activate_mm = paravirt_nop,
+
+ .lazy_mode = {
+ .enter = paravirt_nop,
+ .leave = paravirt_nop,
+ },
};
-EXPORT_SYMBOL(paravirt_ops);
+EXPORT_SYMBOL_GPL(pv_time_ops);
+EXPORT_SYMBOL_GPL(pv_cpu_ops);
+EXPORT_SYMBOL_GPL(pv_mmu_ops);
+EXPORT_SYMBOL_GPL(pv_apic_ops);
+EXPORT_SYMBOL_GPL(pv_info);
+EXPORT_SYMBOL (pv_irq_ops);
diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
index 71da01e73f03..6bf1f716909d 100644
--- a/arch/x86/kernel/pci-calgary_64.c
+++ b/arch/x86/kernel/pci-calgary_64.c
@@ -35,7 +35,8 @@
#include <linux/pci_ids.h>
#include <linux/pci.h>
#include <linux/delay.h>
-#include <asm/iommu.h>
+#include <linux/scatterlist.h>
+#include <asm/gart.h>
#include <asm/calgary.h>
#include <asm/tce.h>
#include <asm/pci-direct.h>
@@ -221,10 +222,10 @@ static inline unsigned int num_dma_pages(unsigned long dma, unsigned int dmalen)
return npages;
}
-static inline int translate_phb(struct pci_dev* dev)
+static inline int translation_enabled(struct iommu_table *tbl)
{
- int disabled = bus_info[dev->bus->number].translation_disabled;
- return !disabled;
+ /* only PHBs with translation enabled have an IOMMU table */
+ return (tbl != NULL);
}
static void iommu_range_reserve(struct iommu_table *tbl,
@@ -384,33 +385,36 @@ static void calgary_unmap_sg(struct device *dev,
struct scatterlist *sglist, int nelems, int direction)
{
struct iommu_table *tbl = find_iommu_table(dev);
+ struct scatterlist *s;
+ int i;
- if (!translate_phb(to_pci_dev(dev)))
+ if (!translation_enabled(tbl))
return;
- while (nelems--) {
+ for_each_sg(sglist, s, nelems, i) {
unsigned int npages;
- dma_addr_t dma = sglist->dma_address;
- unsigned int dmalen = sglist->dma_length;
+ dma_addr_t dma = s->dma_address;
+ unsigned int dmalen = s->dma_length;
if (dmalen == 0)
break;
npages = num_dma_pages(dma, dmalen);
iommu_free(tbl, dma, npages);
- sglist++;
}
}
static int calgary_nontranslate_map_sg(struct device* dev,
struct scatterlist *sg, int nelems, int direction)
{
+ struct scatterlist *s;
int i;
- for (i = 0; i < nelems; i++ ) {
- struct scatterlist *s = &sg[i];
- BUG_ON(!s->page);
- s->dma_address = virt_to_bus(page_address(s->page) +s->offset);
+ for_each_sg(sg, s, nelems, i) {
+ struct page *p = sg_page(s);
+
+ BUG_ON(!p);
+ s->dma_address = virt_to_bus(sg_virt(s));
s->dma_length = s->length;
}
return nelems;
@@ -420,19 +424,19 @@ static int calgary_map_sg(struct device *dev, struct scatterlist *sg,
int nelems, int direction)
{
struct iommu_table *tbl = find_iommu_table(dev);
+ struct scatterlist *s;
unsigned long vaddr;
unsigned int npages;
unsigned long entry;
int i;
- if (!translate_phb(to_pci_dev(dev)))
+ if (!translation_enabled(tbl))
return calgary_nontranslate_map_sg(dev, sg, nelems, direction);
- for (i = 0; i < nelems; i++ ) {
- struct scatterlist *s = &sg[i];
- BUG_ON(!s->page);
+ for_each_sg(sg, s, nelems, i) {
+ BUG_ON(!sg_page(s));
- vaddr = (unsigned long)page_address(s->page) + s->offset;
+ vaddr = (unsigned long) sg_virt(s);
npages = num_dma_pages(vaddr, s->length);
entry = iommu_range_alloc(tbl, npages);
@@ -454,9 +458,9 @@ static int calgary_map_sg(struct device *dev, struct scatterlist *sg,
return nelems;
error:
calgary_unmap_sg(dev, sg, nelems, direction);
- for (i = 0; i < nelems; i++) {
- sg[i].dma_address = bad_dma_address;
- sg[i].dma_length = 0;
+ for_each_sg(sg, s, nelems, i) {
+ sg->dma_address = bad_dma_address;
+ sg->dma_length = 0;
}
return 0;
}
@@ -472,7 +476,7 @@ static dma_addr_t calgary_map_single(struct device *dev, void *vaddr,
uaddr = (unsigned long)vaddr;
npages = num_dma_pages(uaddr, size);
- if (translate_phb(to_pci_dev(dev)))
+ if (translation_enabled(tbl))
dma_handle = iommu_alloc(tbl, vaddr, npages, direction);
else
dma_handle = virt_to_bus(vaddr);
@@ -486,7 +490,7 @@ static void calgary_unmap_single(struct device *dev, dma_addr_t dma_handle,
struct iommu_table *tbl = find_iommu_table(dev);
unsigned int npages;
- if (!translate_phb(to_pci_dev(dev)))
+ if (!translation_enabled(tbl))
return;
npages = num_dma_pages(dma_handle, size);
@@ -511,7 +515,7 @@ static void* calgary_alloc_coherent(struct device *dev, size_t size,
goto error;
memset(ret, 0, size);
- if (translate_phb(to_pci_dev(dev))) {
+ if (translation_enabled(tbl)) {
/* set up tces to cover the allocated range */
mapping = iommu_alloc(tbl, ret, npages, DMA_BIDIRECTIONAL);
if (mapping == bad_dma_address)
@@ -1192,7 +1196,7 @@ static int __init calgary_init(void)
{
int ret;
struct pci_dev *dev = NULL;
- void *tce_space;
+ struct calgary_bus_info *info;
ret = calgary_locate_bbars();
if (ret)
@@ -1204,12 +1208,14 @@ static int __init calgary_init(void)
break;
if (!is_cal_pci_dev(dev->device))
continue;
- if (!translate_phb(dev)) {
+
+ info = &bus_info[dev->bus->number];
+ if (info->translation_disabled) {
calgary_init_one_nontraslated(dev);
continue;
}
- tce_space = bus_info[dev->bus->number].tce_space;
- if (!tce_space && !translate_empty_slots)
+
+ if (!info->tce_space && !translate_empty_slots)
continue;
ret = calgary_init_one(dev);
@@ -1227,11 +1233,13 @@ error:
break;
if (!is_cal_pci_dev(dev->device))
continue;
- if (!translate_phb(dev)) {
+
+ info = &bus_info[dev->bus->number];
+ if (info->translation_disabled) {
pci_dev_put(dev);
continue;
}
- if (!bus_info[dev->bus->number].tce_space && !translate_empty_slots)
+ if (!info->tce_space && !translate_empty_slots)
continue;
calgary_disable_translation(dev);
@@ -1544,7 +1552,7 @@ static void __init calgary_fixup_one_tce_space(struct pci_dev *dev)
static int __init calgary_fixup_tce_spaces(void)
{
struct pci_dev *dev = NULL;
- void *tce_space;
+ struct calgary_bus_info *info;
if (no_iommu || swiotlb || !calgary_detected)
return -ENODEV;
@@ -1557,11 +1565,12 @@ static int __init calgary_fixup_tce_spaces(void)
break;
if (!is_cal_pci_dev(dev->device))
continue;
- if (!translate_phb(dev))
+
+ info = &bus_info[dev->bus->number];
+ if (info->translation_disabled)
continue;
- tce_space = bus_info[dev->bus->number].tce_space;
- if (!tce_space)
+ if (!info->tce_space)
continue;
calgary_fixup_one_tce_space(dev);
diff --git a/arch/x86/kernel/pci-dma_32.c b/arch/x86/kernel/pci-dma_32.c
index 0aae2f3847a5..51330321a5d3 100644
--- a/arch/x86/kernel/pci-dma_32.c
+++ b/arch/x86/kernel/pci-dma_32.c
@@ -12,7 +12,6 @@
#include <linux/string.h>
#include <linux/pci.h>
#include <linux/module.h>
-#include <linux/pci.h>
#include <asm/io.h>
struct dma_coherent_mem {
diff --git a/arch/x86/kernel/pci-dma_64.c b/arch/x86/kernel/pci-dma_64.c
index 9576a2eb375e..aa805b11b24f 100644
--- a/arch/x86/kernel/pci-dma_64.c
+++ b/arch/x86/kernel/pci-dma_64.c
@@ -7,11 +7,12 @@
#include <linux/string.h>
#include <linux/pci.h>
#include <linux/module.h>
+#include <linux/dmar.h>
#include <asm/io.h>
-#include <asm/iommu.h>
+#include <asm/gart.h>
#include <asm/calgary.h>
-int iommu_merge __read_mostly = 0;
+int iommu_merge __read_mostly = 1;
EXPORT_SYMBOL(iommu_merge);
dma_addr_t bad_dma_address __read_mostly;
@@ -51,11 +52,9 @@ dma_alloc_pages(struct device *dev, gfp_t gfp, unsigned order)
{
struct page *page;
int node;
-#ifdef CONFIG_PCI
- if (dev->bus == &pci_bus_type)
- node = pcibus_to_node(to_pci_dev(dev)->bus);
- else
-#endif
+
+ node = dev_to_node(dev);
+ if (node == -1)
node = numa_node_id();
if (node < first_node(node_online_map))
@@ -276,7 +275,7 @@ __init int iommu_setup(char *p)
swiotlb = 1;
#endif
-#ifdef CONFIG_IOMMU
+#ifdef CONFIG_GART_IOMMU
gart_parse_options(p);
#endif
@@ -299,14 +298,16 @@ void __init pci_iommu_alloc(void)
* The order of these functions is important for
* fall-back/fail-over reasons
*/
-#ifdef CONFIG_IOMMU
- iommu_hole_init();
+#ifdef CONFIG_GART_IOMMU
+ gart_iommu_hole_init();
#endif
#ifdef CONFIG_CALGARY_IOMMU
detect_calgary();
#endif
+ detect_intel_iommu();
+
#ifdef CONFIG_SWIOTLB
pci_swiotlb_init();
#endif
@@ -318,7 +319,9 @@ static int __init pci_iommu_init(void)
calgary_iommu_init();
#endif
-#ifdef CONFIG_IOMMU
+ intel_iommu_init();
+
+#ifdef CONFIG_GART_IOMMU
gart_iommu_init();
#endif
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c
index 4918c575d582..06bcba536045 100644
--- a/arch/x86/kernel/pci-gart_64.c
+++ b/arch/x86/kernel/pci-gart_64.c
@@ -8,6 +8,7 @@
* See Documentation/DMA-mapping.txt for the interface specification.
*
* Copyright 2002 Andi Kleen, SuSE Labs.
+ * Subject to the GNU General Public License v2 only.
*/
#include <linux/types.h>
@@ -23,22 +24,23 @@
#include <linux/interrupt.h>
#include <linux/bitops.h>
#include <linux/kdebug.h>
+#include <linux/scatterlist.h>
#include <asm/atomic.h>
#include <asm/io.h>
#include <asm/mtrr.h>
#include <asm/pgtable.h>
#include <asm/proto.h>
-#include <asm/iommu.h>
+#include <asm/gart.h>
#include <asm/cacheflush.h>
#include <asm/swiotlb.h>
#include <asm/dma.h>
#include <asm/k8.h>
-unsigned long iommu_bus_base; /* GART remapping area (physical) */
+static unsigned long iommu_bus_base; /* GART remapping area (physical) */
static unsigned long iommu_size; /* size of remapping area bytes */
static unsigned long iommu_pages; /* .. and in pages */
-u32 *iommu_gatt_base; /* Remapping table */
+static u32 *iommu_gatt_base; /* Remapping table */
/* If this is disabled the IOMMU will use an optimized flushing strategy
of only flushing when an mapping is reused. With it true the GART is flushed
@@ -133,8 +135,8 @@ static void flush_gart(void)
/* Debugging aid for drivers that don't free their IOMMU tables */
static void **iommu_leak_tab;
static int leak_trace;
-int iommu_leak_pages = 20;
-void dump_leak(void)
+static int iommu_leak_pages = 20;
+static void dump_leak(void)
{
int i;
static int dump;
@@ -278,10 +280,10 @@ static void gart_unmap_single(struct device *dev, dma_addr_t dma_addr,
*/
static void gart_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
{
+ struct scatterlist *s;
int i;
- for (i = 0; i < nents; i++) {
- struct scatterlist *s = &sg[i];
+ for_each_sg(sg, s, nents, i) {
if (!s->dma_length || !s->length)
break;
gart_unmap_single(dev, s->dma_address, s->dma_length, dir);
@@ -292,15 +294,15 @@ static void gart_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg,
int nents, int dir)
{
+ struct scatterlist *s;
int i;
#ifdef CONFIG_IOMMU_DEBUG
printk(KERN_DEBUG "dma_map_sg overflow\n");
#endif
- for (i = 0; i < nents; i++ ) {
- struct scatterlist *s = &sg[i];
- unsigned long addr = page_to_phys(s->page) + s->offset;
+ for_each_sg(sg, s, nents, i) {
+ unsigned long addr = sg_phys(s);
if (nonforced_iommu(dev, addr, s->length)) {
addr = dma_map_area(dev, addr, s->length, dir);
if (addr == bad_dma_address) {
@@ -319,24 +321,23 @@ static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg,
}
/* Map multiple scatterlist entries continuous into the first. */
-static int __dma_map_cont(struct scatterlist *sg, int start, int stopat,
+static int __dma_map_cont(struct scatterlist *start, int nelems,
struct scatterlist *sout, unsigned long pages)
{
unsigned long iommu_start = alloc_iommu(pages);
unsigned long iommu_page = iommu_start;
+ struct scatterlist *s;
int i;
if (iommu_start == -1)
return -1;
-
- for (i = start; i < stopat; i++) {
- struct scatterlist *s = &sg[i];
+
+ for_each_sg(start, s, nelems, i) {
unsigned long pages, addr;
unsigned long phys_addr = s->dma_address;
- BUG_ON(i > start && s->offset);
- if (i == start) {
- *sout = *s;
+ BUG_ON(s != start && s->offset);
+ if (s == start) {
sout->dma_address = iommu_bus_base;
sout->dma_address += iommu_page*PAGE_SIZE + s->offset;
sout->dma_length = s->length;
@@ -357,30 +358,32 @@ static int __dma_map_cont(struct scatterlist *sg, int start, int stopat,
return 0;
}
-static inline int dma_map_cont(struct scatterlist *sg, int start, int stopat,
+static inline int dma_map_cont(struct scatterlist *start, int nelems,
struct scatterlist *sout,
unsigned long pages, int need)
{
- if (!need) {
- BUG_ON(stopat - start != 1);
- *sout = sg[start];
- sout->dma_length = sg[start].length;
+ if (!need) {
+ BUG_ON(nelems != 1);
+ sout->dma_address = start->dma_address;
+ sout->dma_length = start->length;
return 0;
- }
- return __dma_map_cont(sg, start, stopat, sout, pages);
+ }
+ return __dma_map_cont(start, nelems, sout, pages);
}
/*
* DMA map all entries in a scatterlist.
* Merge chunks that have page aligned sizes into a continuous mapping.
*/
-int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
+static int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+ int dir)
{
int i;
int out;
int start;
unsigned long pages = 0;
int need = 0, nextneed;
+ struct scatterlist *s, *ps, *start_sg, *sgmap;
if (nents == 0)
return 0;
@@ -390,9 +393,10 @@ int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
out = 0;
start = 0;
- for (i = 0; i < nents; i++) {
- struct scatterlist *s = &sg[i];
- dma_addr_t addr = page_to_phys(s->page) + s->offset;
+ start_sg = sgmap = sg;
+ ps = NULL; /* shut up gcc */
+ for_each_sg(sg, s, nents, i) {
+ dma_addr_t addr = sg_phys(s);
s->dma_address = addr;
BUG_ON(s->length == 0);
@@ -400,34 +404,38 @@ int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
/* Handle the previous not yet processed entries */
if (i > start) {
- struct scatterlist *ps = &sg[i-1];
/* Can only merge when the last chunk ends on a page
boundary and the new one doesn't have an offset. */
if (!iommu_merge || !nextneed || !need || s->offset ||
- (ps->offset + ps->length) % PAGE_SIZE) {
- if (dma_map_cont(sg, start, i, sg+out, pages,
- need) < 0)
+ (ps->offset + ps->length) % PAGE_SIZE) {
+ if (dma_map_cont(start_sg, i - start, sgmap,
+ pages, need) < 0)
goto error;
out++;
+ sgmap = sg_next(sgmap);
pages = 0;
- start = i;
+ start = i;
+ start_sg = s;
}
}
need = nextneed;
pages += to_pages(s->offset, s->length);
+ ps = s;
}
- if (dma_map_cont(sg, start, i, sg+out, pages, need) < 0)
+ if (dma_map_cont(start_sg, i - start, sgmap, pages, need) < 0)
goto error;
out++;
flush_gart();
- if (out < nents)
- sg[out].dma_length = 0;
+ if (out < nents) {
+ sgmap = sg_next(sgmap);
+ sgmap->dma_length = 0;
+ }
return out;
error:
flush_gart();
- gart_unmap_sg(dev, sg, nents, dir);
+ gart_unmap_sg(dev, sg, out, dir);
/* When it was forced or merged try again in a dumb way */
if (force_iommu || iommu_merge) {
out = dma_map_sg_nonforce(dev, sg, nents, dir);
@@ -437,8 +445,8 @@ error:
if (panic_on_overflow)
panic("dma_map_sg: overflow on %lu pages\n", pages);
iommu_full(dev, pages << PAGE_SHIFT, dir);
- for (i = 0; i < nents; i++)
- sg[i].dma_address = bad_dma_address;
+ for_each_sg(sg, s, nents, i)
+ s->dma_address = bad_dma_address;
return 0;
}
@@ -619,12 +627,12 @@ void __init gart_iommu_init(void)
return;
/* Did we detect a different HW IOMMU? */
- if (iommu_detected && !iommu_aperture)
+ if (iommu_detected && !gart_iommu_aperture)
return;
if (no_iommu ||
(!force_iommu && end_pfn <= MAX_DMA32_PFN) ||
- !iommu_aperture ||
+ !gart_iommu_aperture ||
(no_agp && init_k8_gatt(&info) < 0)) {
if (end_pfn > MAX_DMA32_PFN) {
printk(KERN_ERR "WARNING more than 4GB of memory "
@@ -725,9 +733,9 @@ void __init gart_parse_options(char *p)
fix_aperture = 0;
/* duplicated from pci-dma.c */
if (!strncmp(p,"force",5))
- iommu_aperture_allowed = 1;
+ gart_iommu_aperture_allowed = 1;
if (!strncmp(p,"allowed",7))
- iommu_aperture_allowed = 1;
+ gart_iommu_aperture_allowed = 1;
if (!strncmp(p, "memaper", 7)) {
fallback_aper_force = 1;
p += 7;
diff --git a/arch/x86/kernel/pci-nommu_64.c b/arch/x86/kernel/pci-nommu_64.c
index 2a34c6c025a9..ab08e1832228 100644
--- a/arch/x86/kernel/pci-nommu_64.c
+++ b/arch/x86/kernel/pci-nommu_64.c
@@ -5,8 +5,9 @@
#include <linux/pci.h>
#include <linux/string.h>
#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
-#include <asm/iommu.h>
+#include <asm/gart.h>
#include <asm/processor.h>
#include <asm/dma.h>
@@ -57,12 +58,12 @@ static void nommu_unmap_single(struct device *dev, dma_addr_t addr,size_t size,
static int nommu_map_sg(struct device *hwdev, struct scatterlist *sg,
int nents, int direction)
{
+ struct scatterlist *s;
int i;
- for (i = 0; i < nents; i++ ) {
- struct scatterlist *s = &sg[i];
- BUG_ON(!s->page);
- s->dma_address = virt_to_bus(page_address(s->page) +s->offset);
+ for_each_sg(sg, s, nents, i) {
+ BUG_ON(!sg_page(s));
+ s->dma_address = virt_to_bus(sg_virt(s));
if (!check_addr("map_sg", hwdev, s->dma_address, s->length))
return 0;
s->dma_length = s->length;
diff --git a/arch/x86/kernel/pci-swiotlb_64.c b/arch/x86/kernel/pci-swiotlb_64.c
index b2f405ea7c85..102866d729a5 100644
--- a/arch/x86/kernel/pci-swiotlb_64.c
+++ b/arch/x86/kernel/pci-swiotlb_64.c
@@ -5,7 +5,7 @@
#include <linux/module.h>
#include <linux/dma-mapping.h>
-#include <asm/iommu.h>
+#include <asm/gart.h>
#include <asm/swiotlb.h>
#include <asm/dma.h>
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index 097aeafce5ff..7b899584d290 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -295,34 +295,52 @@ static int __init idle_setup(char *str)
}
early_param("idle", idle_setup);
-void show_regs(struct pt_regs * regs)
+void __show_registers(struct pt_regs *regs, int all)
{
unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L;
unsigned long d0, d1, d2, d3, d6, d7;
+ unsigned long esp;
+ unsigned short ss, gs;
+
+ if (user_mode_vm(regs)) {
+ esp = regs->esp;
+ ss = regs->xss & 0xffff;
+ savesegment(gs, gs);
+ } else {
+ esp = (unsigned long) (&regs->esp);
+ savesegment(ss, ss);
+ savesegment(gs, gs);
+ }
printk("\n");
- printk("Pid: %d, comm: %20s\n", current->pid, current->comm);
- printk("EIP: %04x:[<%08lx>] CPU: %d\n",0xffff & regs->xcs,regs->eip, smp_processor_id());
+ printk("Pid: %d, comm: %s %s (%s %.*s)\n",
+ task_pid_nr(current), current->comm,
+ print_tainted(), init_utsname()->release,
+ (int)strcspn(init_utsname()->version, " "),
+ init_utsname()->version);
+
+ printk("EIP: %04x:[<%08lx>] EFLAGS: %08lx CPU: %d\n",
+ 0xffff & regs->xcs, regs->eip, regs->eflags,
+ smp_processor_id());
print_symbol("EIP is at %s\n", regs->eip);
- if (user_mode_vm(regs))
- printk(" ESP: %04x:%08lx",0xffff & regs->xss,regs->esp);
- printk(" EFLAGS: %08lx %s (%s %.*s)\n",
- regs->eflags, print_tainted(), init_utsname()->release,
- (int)strcspn(init_utsname()->version, " "),
- init_utsname()->version);
printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
- regs->eax,regs->ebx,regs->ecx,regs->edx);
- printk("ESI: %08lx EDI: %08lx EBP: %08lx",
- regs->esi, regs->edi, regs->ebp);
- printk(" DS: %04x ES: %04x FS: %04x\n",
- 0xffff & regs->xds,0xffff & regs->xes, 0xffff & regs->xfs);
+ regs->eax, regs->ebx, regs->ecx, regs->edx);
+ printk("ESI: %08lx EDI: %08lx EBP: %08lx ESP: %08lx\n",
+ regs->esi, regs->edi, regs->ebp, esp);
+ printk(" DS: %04x ES: %04x FS: %04x GS: %04x SS: %04x\n",
+ regs->xds & 0xffff, regs->xes & 0xffff,
+ regs->xfs & 0xffff, gs, ss);
+
+ if (!all)
+ return;
cr0 = read_cr0();
cr2 = read_cr2();
cr3 = read_cr3();
cr4 = read_cr4_safe();
- printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", cr0, cr2, cr3, cr4);
+ printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n",
+ cr0, cr2, cr3, cr4);
get_debugreg(d0, 0);
get_debugreg(d1, 1);
@@ -330,10 +348,16 @@ void show_regs(struct pt_regs * regs)
get_debugreg(d3, 3);
printk("DR0: %08lx DR1: %08lx DR2: %08lx DR3: %08lx\n",
d0, d1, d2, d3);
+
get_debugreg(d6, 6);
get_debugreg(d7, 7);
- printk("DR6: %08lx DR7: %08lx\n", d6, d7);
+ printk("DR6: %08lx DR7: %08lx\n",
+ d6, d7);
+}
+void show_regs(struct pt_regs *regs)
+{
+ __show_registers(regs, 1);
show_trace(NULL, regs, &regs->esp);
}
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 7352d4b377e6..6309b275cb9c 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -581,7 +581,7 @@ static inline void __switch_to_xtra(struct task_struct *prev_p,
*
* Kprobes not supported here. Set the probe on schedule instead.
*/
-__kprobes struct task_struct *
+struct task_struct *
__switch_to(struct task_struct *prev_p, struct task_struct *next_p)
{
struct thread_struct *prev = &prev_p->thread,
diff --git a/arch/x86/kernel/ptrace_32.c b/arch/x86/kernel/ptrace_32.c
index 0cecd7513c97..ff5431cc03ee 100644
--- a/arch/x86/kernel/ptrace_32.c
+++ b/arch/x86/kernel/ptrace_32.c
@@ -165,7 +165,7 @@ static unsigned long convert_eip_to_linear(struct task_struct *child, struct pt_
seg &= ~7UL;
- down(&child->mm->context.sem);
+ mutex_lock(&child->mm->context.lock);
if (unlikely((seg >> 3) >= child->mm->context.size))
addr = -1L; /* bogus selector, access would fault */
else {
@@ -179,7 +179,7 @@ static unsigned long convert_eip_to_linear(struct task_struct *child, struct pt_
addr &= 0xffff;
addr += base;
}
- up(&child->mm->context.sem);
+ mutex_unlock(&child->mm->context.lock);
}
return addr;
}
@@ -524,11 +524,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
ret = 0;
break;
- case PTRACE_DETACH:
- /* detach a process that was attached. */
- ret = ptrace_detach(child, data);
- break;
-
case PTRACE_GETREGS: { /* Get all gp regs from the child. */
if (!access_ok(VERIFY_WRITE, datap, FRAME_SIZE*sizeof(long))) {
ret = -EIO;
@@ -637,7 +632,7 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code)
/* User-mode eip? */
info.si_addr = user_mode_vm(regs) ? (void __user *) regs->eip : NULL;
- /* Send us the fakey SIGTRAP */
+ /* Send us the fake SIGTRAP */
force_sig_info(SIGTRAP, &info, tsk);
}
diff --git a/arch/x86/kernel/ptrace_64.c b/arch/x86/kernel/ptrace_64.c
index c0cac42df3b6..607085f3f08a 100644
--- a/arch/x86/kernel/ptrace_64.c
+++ b/arch/x86/kernel/ptrace_64.c
@@ -103,7 +103,7 @@ unsigned long convert_rip_to_linear(struct task_struct *child, struct pt_regs *r
seg &= ~7UL;
- down(&child->mm->context.sem);
+ mutex_lock(&child->mm->context.lock);
if (unlikely((seg >> 3) >= child->mm->context.size))
addr = -1L; /* bogus selector, access would fault */
else {
@@ -117,7 +117,7 @@ unsigned long convert_rip_to_linear(struct task_struct *child, struct pt_regs *r
addr &= 0xffff;
addr += base;
}
- up(&child->mm->context.sem);
+ mutex_unlock(&child->mm->context.lock);
}
return addr;
@@ -500,11 +500,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
ret = 0;
break;
- case PTRACE_DETACH:
- /* detach a process that was attached. */
- ret = ptrace_detach(child, data);
- break;
-
case PTRACE_GETREGS: { /* Get all gp regs from the child. */
if (!access_ok(VERIFY_WRITE, (unsigned __user *)data,
sizeof(struct user_regs_struct))) {
diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c
index d769e204f942..fab30e134836 100644
--- a/arch/x86/kernel/quirks.c
+++ b/arch/x86/kernel/quirks.c
@@ -45,9 +45,12 @@ static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
if (!(config & 0x2))
pci_write_config_byte(dev, 0xf4, config);
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH, quirk_intel_irqbalance);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quirk_intel_irqbalance);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, quirk_intel_irqbalance);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH,
+ quirk_intel_irqbalance);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH,
+ quirk_intel_irqbalance);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH,
+ quirk_intel_irqbalance);
#endif
#if defined(CONFIG_HPET_TIMER)
@@ -56,7 +59,9 @@ unsigned long force_hpet_address;
static enum {
NONE_FORCE_HPET_RESUME,
OLD_ICH_FORCE_HPET_RESUME,
- ICH_FORCE_HPET_RESUME
+ ICH_FORCE_HPET_RESUME,
+ VT8237_FORCE_HPET_RESUME,
+ NVIDIA_FORCE_HPET_RESUME,
} force_hpet_resume_type;
static void __iomem *rcba_base;
@@ -146,17 +151,17 @@ static void ich_force_enable_hpet(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_0,
- ich_force_enable_hpet);
+ ich_force_enable_hpet);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1,
- ich_force_enable_hpet);
+ ich_force_enable_hpet);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0,
- ich_force_enable_hpet);
+ ich_force_enable_hpet);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1,
- ich_force_enable_hpet);
+ ich_force_enable_hpet);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31,
- ich_force_enable_hpet);
+ ich_force_enable_hpet);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_1,
- ich_force_enable_hpet);
+ ich_force_enable_hpet);
static struct pci_dev *cached_dev;
@@ -232,10 +237,140 @@ static void old_ich_force_enable_hpet(struct pci_dev *dev)
printk(KERN_DEBUG "Failed to force enable HPET\n");
}
+/*
+ * Undocumented chipset features. Make sure that the user enforced
+ * this.
+ */
+static void old_ich_force_enable_hpet_user(struct pci_dev *dev)
+{
+ if (hpet_force_user)
+ old_ich_force_enable_hpet(dev);
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0,
+ old_ich_force_enable_hpet_user);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12,
+ old_ich_force_enable_hpet_user);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0,
+ old_ich_force_enable_hpet_user);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12,
+ old_ich_force_enable_hpet_user);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0,
- old_ich_force_enable_hpet);
+ old_ich_force_enable_hpet);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_12,
- old_ich_force_enable_hpet);
+ old_ich_force_enable_hpet);
+
+
+static void vt8237_force_hpet_resume(void)
+{
+ u32 val;
+
+ if (!force_hpet_address || !cached_dev)
+ return;
+
+ val = 0xfed00000 | 0x80;
+ pci_write_config_dword(cached_dev, 0x68, val);
+
+ pci_read_config_dword(cached_dev, 0x68, &val);
+ if (val & 0x80)
+ printk(KERN_DEBUG "Force enabled HPET at resume\n");
+ else
+ BUG();
+}
+
+static void vt8237_force_enable_hpet(struct pci_dev *dev)
+{
+ u32 uninitialized_var(val);
+
+ if (!hpet_force_user || hpet_address || force_hpet_address)
+ return;
+
+ pci_read_config_dword(dev, 0x68, &val);
+ /*
+ * Bit 7 is HPET enable bit.
+ * Bit 31:10 is HPET base address (contrary to what datasheet claims)
+ */
+ if (val & 0x80) {
+ force_hpet_address = (val & ~0x3ff);
+ printk(KERN_DEBUG "HPET at base address 0x%lx\n",
+ force_hpet_address);
+ return;
+ }
+
+ /*
+ * HPET is disabled. Trying enabling at FED00000 and check
+ * whether it sticks
+ */
+ val = 0xfed00000 | 0x80;
+ pci_write_config_dword(dev, 0x68, val);
+
+ pci_read_config_dword(dev, 0x68, &val);
+ if (val & 0x80) {
+ force_hpet_address = (val & ~0x3ff);
+ printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
+ force_hpet_address);
+ cached_dev = dev;
+ force_hpet_resume_type = VT8237_FORCE_HPET_RESUME;
+ return;
+ }
+
+ printk(KERN_DEBUG "Failed to force enable HPET\n");
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235,
+ vt8237_force_enable_hpet);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237,
+ vt8237_force_enable_hpet);
+
+/*
+ * Undocumented chipset feature taken from LinuxBIOS.
+ */
+static void nvidia_force_hpet_resume(void)
+{
+ pci_write_config_dword(cached_dev, 0x44, 0xfed00001);
+ printk(KERN_DEBUG "Force enabled HPET at resume\n");
+}
+
+static void nvidia_force_enable_hpet(struct pci_dev *dev)
+{
+ u32 uninitialized_var(val);
+
+ if (!hpet_force_user || hpet_address || force_hpet_address)
+ return;
+
+ pci_write_config_dword(dev, 0x44, 0xfed00001);
+ pci_read_config_dword(dev, 0x44, &val);
+ force_hpet_address = val & 0xfffffffe;
+ force_hpet_resume_type = NVIDIA_FORCE_HPET_RESUME;
+ printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
+ force_hpet_address);
+ cached_dev = dev;
+ return;
+}
+
+/* ISA Bridges */
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0050,
+ nvidia_force_enable_hpet);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0051,
+ nvidia_force_enable_hpet);
+
+/* LPC bridges */
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0360,
+ nvidia_force_enable_hpet);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0361,
+ nvidia_force_enable_hpet);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0362,
+ nvidia_force_enable_hpet);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0363,
+ nvidia_force_enable_hpet);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0364,
+ nvidia_force_enable_hpet);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0365,
+ nvidia_force_enable_hpet);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0366,
+ nvidia_force_enable_hpet);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0367,
+ nvidia_force_enable_hpet);
void force_hpet_resume(void)
{
@@ -246,6 +381,12 @@ void force_hpet_resume(void)
case OLD_ICH_FORCE_HPET_RESUME:
return old_ich_force_hpet_resume();
+ case VT8237_FORCE_HPET_RESUME:
+ return vt8237_force_hpet_resume();
+
+ case NVIDIA_FORCE_HPET_RESUME:
+ return nvidia_force_hpet_resume();
+
default:
break;
}
diff --git a/arch/x86/kernel/reboot_64.c b/arch/x86/kernel/reboot_64.c
index 368db2b9c5ac..71b13c5f5817 100644
--- a/arch/x86/kernel/reboot_64.c
+++ b/arch/x86/kernel/reboot_64.c
@@ -11,12 +11,13 @@
#include <linux/sched.h>
#include <asm/io.h>
#include <asm/delay.h>
+#include <asm/desc.h>
#include <asm/hw_irq.h>
#include <asm/system.h>
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
#include <asm/apic.h>
-#include <asm/iommu.h>
+#include <asm/gart.h>
/*
* Power off function, if any
@@ -136,7 +137,7 @@ void machine_emergency_restart(void)
}
case BOOT_TRIPLE:
- __asm__ __volatile__("lidt (%0)": :"r" (&no_idt));
+ load_idt((const struct desc_ptr *)&no_idt);
__asm__ __volatile__("int3");
reboot_type = BOOT_KBD;
diff --git a/arch/x86/kernel/reboot_fixups_32.c b/arch/x86/kernel/reboot_fixups_32.c
index 8b30b26ad069..1a07bbea7be3 100644
--- a/arch/x86/kernel/reboot_fixups_32.c
+++ b/arch/x86/kernel/reboot_fixups_32.c
@@ -12,6 +12,7 @@
#include <linux/interrupt.h>
#include <asm/reboot_fixups.h>
#include <asm/msr.h>
+#include <asm/geode.h>
static void cs5530a_warm_reset(struct pci_dev *dev)
{
@@ -24,11 +25,8 @@ static void cs5530a_warm_reset(struct pci_dev *dev)
static void cs5536_warm_reset(struct pci_dev *dev)
{
- /*
- * 6.6.2.12 Soft Reset (DIVIL_SOFT_RESET)
- * writing 1 to the LSB of this MSR causes a hard reset.
- */
- wrmsrl(0x51400017, 1ULL);
+ /* writing 1 to the LSB of this MSR causes a hard reset */
+ wrmsrl(MSR_DIVIL_SOFT_RESET, 1ULL);
udelay(50); /* shouldn't get here but be safe and spin a while */
}
diff --git a/arch/x86/kernel/setup64.c b/arch/x86/kernel/setup64.c
index 1200aaac403e..3558ac78c926 100644
--- a/arch/x86/kernel/setup64.c
+++ b/arch/x86/kernel/setup64.c
@@ -11,7 +11,6 @@
#include <linux/bootmem.h>
#include <linux/bitops.h>
#include <linux/module.h>
-#include <asm/bootsetup.h>
#include <asm/pda.h>
#include <asm/pgtable.h>
#include <asm/processor.h>
@@ -23,8 +22,9 @@
#include <asm/percpu.h>
#include <asm/proto.h>
#include <asm/sections.h>
+#include <asm/setup.h>
-char x86_boot_params[BOOT_PARAM_SIZE] __initdata;
+struct boot_params __initdata boot_params;
cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE;
@@ -185,6 +185,12 @@ void __cpuinit check_efer(void)
unsigned long kernel_eflags;
/*
+ * Copies of the original ist values from the tss are only accessed during
+ * debugging, no special alignment required.
+ */
+DEFINE_PER_CPU(struct orig_ist, orig_ist);
+
+/*
* cpu_init() initializes state that is per-CPU. Some data is already
* initialized (naturally) in the bootstrap process, such as the GDT
* and IDT. We reload them nevertheless, this function acts as a
@@ -224,8 +230,8 @@ void __cpuinit cpu_init (void)
memcpy(cpu_gdt(cpu), cpu_gdt_table, GDT_SIZE);
cpu_gdt_descr[cpu].size = GDT_SIZE;
- asm volatile("lgdt %0" :: "m" (cpu_gdt_descr[cpu]));
- asm volatile("lidt %0" :: "m" (idt_descr));
+ load_gdt((const struct desc_ptr *)&cpu_gdt_descr[cpu]);
+ load_idt((const struct desc_ptr *)&idt_descr);
memset(me->thread.tls_array, 0, GDT_ENTRY_TLS_ENTRIES * 8);
syscall_init();
diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c
index c8e1bc38d421..e1e18c34c821 100644
--- a/arch/x86/kernel/setup_32.c
+++ b/arch/x86/kernel/setup_32.c
@@ -60,6 +60,7 @@
#include <asm/vmi.h>
#include <setup_arch.h>
#include <bios_ebda.h>
+#include <asm/cacheflush.h>
/* This value is set up by the early boot code to point to the value
immediately after the boot time page tables. It contains a *physical*
@@ -73,6 +74,7 @@ int disable_pse __devinitdata = 0;
*/
extern struct resource code_resource;
extern struct resource data_resource;
+extern struct resource bss_resource;
/* cpu data as detected by the assembly code in head.S */
struct cpuinfo_x86 new_cpu_data __cpuinitdata = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
@@ -84,9 +86,6 @@ unsigned long mmu_cr4_features;
/* for MCA, but anyone else can use it if they want */
unsigned int machine_id;
-#ifdef CONFIG_MCA
-EXPORT_SYMBOL(machine_id);
-#endif
unsigned int machine_submodel_id;
unsigned int BIOS_revision;
unsigned int mca_pentium_flag;
@@ -137,10 +136,11 @@ EXPORT_SYMBOL(edd);
*/
static inline void copy_edd(void)
{
- memcpy(edd.mbr_signature, EDD_MBR_SIGNATURE, sizeof(edd.mbr_signature));
- memcpy(edd.edd_info, EDD_BUF, sizeof(edd.edd_info));
- edd.mbr_signature_nr = EDD_MBR_SIG_NR;
- edd.edd_info_nr = EDD_NR;
+ memcpy(edd.mbr_signature, boot_params.edd_mbr_sig_buffer,
+ sizeof(edd.mbr_signature));
+ memcpy(edd.edd_info, boot_params.eddbuf, sizeof(edd.edd_info));
+ edd.mbr_signature_nr = boot_params.edd_mbr_sig_buf_entries;
+ edd.edd_info_nr = boot_params.eddbuf_entries;
}
#else
static inline void copy_edd(void)
@@ -377,6 +377,49 @@ extern unsigned long __init setup_memory(void);
extern void zone_sizes_init(void);
#endif /* !CONFIG_NEED_MULTIPLE_NODES */
+static inline unsigned long long get_total_mem(void)
+{
+ unsigned long long total;
+
+ total = max_low_pfn - min_low_pfn;
+#ifdef CONFIG_HIGHMEM
+ total += highend_pfn - highstart_pfn;
+#endif
+
+ return total << PAGE_SHIFT;
+}
+
+#ifdef CONFIG_KEXEC
+static void __init reserve_crashkernel(void)
+{
+ unsigned long long total_mem;
+ unsigned long long crash_size, crash_base;
+ int ret;
+
+ total_mem = get_total_mem();
+
+ ret = parse_crashkernel(boot_command_line, total_mem,
+ &crash_size, &crash_base);
+ if (ret == 0 && crash_size > 0) {
+ if (crash_base > 0) {
+ printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
+ "for crashkernel (System RAM: %ldMB)\n",
+ (unsigned long)(crash_size >> 20),
+ (unsigned long)(crash_base >> 20),
+ (unsigned long)(total_mem >> 20));
+ crashk_res.start = crash_base;
+ crashk_res.end = crash_base + crash_size - 1;
+ reserve_bootmem(crash_base, crash_size);
+ } else
+ printk(KERN_INFO "crashkernel reservation failed - "
+ "you have to specify a base address\n");
+ }
+}
+#else
+static inline void __init reserve_crashkernel(void)
+{}
+#endif
+
void __init setup_bootmem_allocator(void)
{
unsigned long bootmap_size;
@@ -434,26 +477,25 @@ void __init setup_bootmem_allocator(void)
#endif
numa_kva_reserve();
#ifdef CONFIG_BLK_DEV_INITRD
- if (LOADER_TYPE && INITRD_START) {
- if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
- reserve_bootmem(INITRD_START, INITRD_SIZE);
- initrd_start = INITRD_START + PAGE_OFFSET;
- initrd_end = initrd_start+INITRD_SIZE;
- }
- else {
+ if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image) {
+ unsigned long ramdisk_image = boot_params.hdr.ramdisk_image;
+ unsigned long ramdisk_size = boot_params.hdr.ramdisk_size;
+ unsigned long ramdisk_end = ramdisk_image + ramdisk_size;
+ unsigned long end_of_lowmem = max_low_pfn << PAGE_SHIFT;
+
+ if (ramdisk_end <= end_of_lowmem) {
+ reserve_bootmem(ramdisk_image, ramdisk_size);
+ initrd_start = ramdisk_image + PAGE_OFFSET;
+ initrd_end = initrd_start+ramdisk_size;
+ } else {
printk(KERN_ERR "initrd extends beyond end of memory "
- "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
- INITRD_START + INITRD_SIZE,
- max_low_pfn << PAGE_SHIFT);
+ "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+ ramdisk_end, end_of_lowmem);
initrd_start = 0;
}
}
#endif
-#ifdef CONFIG_KEXEC
- if (crashk_res.start != crashk_res.end)
- reserve_bootmem(crashk_res.start,
- crashk_res.end - crashk_res.start + 1);
-#endif
+ reserve_crashkernel();
}
/*
@@ -512,28 +554,29 @@ void __init setup_arch(char **cmdline_p)
* the system table is valid. If not, then initialize normally.
*/
#ifdef CONFIG_EFI
- if ((LOADER_TYPE == 0x50) && EFI_SYSTAB)
+ if ((boot_params.hdr.type_of_loader == 0x50) &&
+ boot_params.efi_info.efi_systab)
efi_enabled = 1;
#endif
- ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
- screen_info = SCREEN_INFO;
- edid_info = EDID_INFO;
- apm_info.bios = APM_BIOS_INFO;
- ist_info = IST_INFO;
- saved_videomode = VIDEO_MODE;
- if( SYS_DESC_TABLE.length != 0 ) {
- set_mca_bus(SYS_DESC_TABLE.table[3] & 0x2);
- machine_id = SYS_DESC_TABLE.table[0];
- machine_submodel_id = SYS_DESC_TABLE.table[1];
- BIOS_revision = SYS_DESC_TABLE.table[2];
+ ROOT_DEV = old_decode_dev(boot_params.hdr.root_dev);
+ screen_info = boot_params.screen_info;
+ edid_info = boot_params.edid_info;
+ apm_info.bios = boot_params.apm_bios_info;
+ ist_info = boot_params.ist_info;
+ saved_videomode = boot_params.hdr.vid_mode;
+ if( boot_params.sys_desc_table.length != 0 ) {
+ set_mca_bus(boot_params.sys_desc_table.table[3] & 0x2);
+ machine_id = boot_params.sys_desc_table.table[0];
+ machine_submodel_id = boot_params.sys_desc_table.table[1];
+ BIOS_revision = boot_params.sys_desc_table.table[2];
}
- bootloader_type = LOADER_TYPE;
+ bootloader_type = boot_params.hdr.type_of_loader;
#ifdef CONFIG_BLK_DEV_RAM
- rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
- rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
- rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
+ rd_image_start = boot_params.hdr.ram_size & RAMDISK_IMAGE_START_MASK;
+ rd_prompt = ((boot_params.hdr.ram_size & RAMDISK_PROMPT_FLAG) != 0);
+ rd_doload = ((boot_params.hdr.ram_size & RAMDISK_LOAD_FLAG) != 0);
#endif
ARCH_SETUP
if (efi_enabled)
@@ -545,7 +588,7 @@ void __init setup_arch(char **cmdline_p)
copy_edd();
- if (!MOUNT_ROOT_RDONLY)
+ if (!boot_params.hdr.root_flags)
root_mountflags &= ~MS_RDONLY;
init_mm.start_code = (unsigned long) _text;
init_mm.end_code = (unsigned long) _etext;
@@ -556,6 +599,8 @@ void __init setup_arch(char **cmdline_p)
code_resource.end = virt_to_phys(_etext)-1;
data_resource.start = virt_to_phys(_etext);
data_resource.end = virt_to_phys(_edata)-1;
+ bss_resource.start = virt_to_phys(&__bss_start);
+ bss_resource.end = virt_to_phys(&__bss_stop)-1;
parse_early_param();
@@ -580,7 +625,7 @@ void __init setup_arch(char **cmdline_p)
/*
* NOTE: before this point _nobody_ is allowed to allocate
* any memory using the bootmem allocator. Although the
- * alloctor is now initialised only the first 8Mb of the kernel
+ * allocator is now initialised only the first 8Mb of the kernel
* virtual address space has been mapped. All allocations before
* paging_init() has completed must use the alloc_bootmem_low_pages()
* variant (which allocates DMA'able memory) and care must be taken
@@ -617,9 +662,7 @@ void __init setup_arch(char **cmdline_p)
#endif
#ifdef CONFIG_PCI
-#ifdef CONFIG_X86_IO_APIC
- check_acpi_pci(); /* Checks more than just ACPI actually */
-#endif
+ early_quirks();
#endif
#ifdef CONFIG_ACPI
diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c
index b7da90e79c78..238633d3d09a 100644
--- a/arch/x86/kernel/setup_64.c
+++ b/arch/x86/kernel/setup_64.c
@@ -52,13 +52,13 @@
#include <asm/dma.h>
#include <asm/mpspec.h>
#include <asm/mmu_context.h>
-#include <asm/bootsetup.h>
#include <asm/proto.h>
#include <asm/setup.h>
#include <asm/mach_apic.h>
#include <asm/numa.h>
#include <asm/sections.h>
#include <asm/dmi.h>
+#include <asm/cacheflush.h>
/*
* Machine setup..
@@ -134,6 +134,12 @@ struct resource code_resource = {
.end = 0,
.flags = IORESOURCE_RAM,
};
+struct resource bss_resource = {
+ .name = "Kernel bss",
+ .start = 0,
+ .end = 0,
+ .flags = IORESOURCE_RAM,
+};
#ifdef CONFIG_PROC_VMCORE
/* elfcorehdr= specifies the location of elf core header
@@ -180,10 +186,11 @@ EXPORT_SYMBOL(edd);
*/
static inline void copy_edd(void)
{
- memcpy(edd.mbr_signature, EDD_MBR_SIGNATURE, sizeof(edd.mbr_signature));
- memcpy(edd.edd_info, EDD_BUF, sizeof(edd.edd_info));
- edd.mbr_signature_nr = EDD_MBR_SIG_NR;
- edd.edd_info_nr = EDD_NR;
+ memcpy(edd.mbr_signature, boot_params.edd_mbr_sig_buffer,
+ sizeof(edd.mbr_signature));
+ memcpy(edd.edd_info, boot_params.eddbuf, sizeof(edd.edd_info));
+ edd.mbr_signature_nr = boot_params.edd_mbr_sig_buf_entries;
+ edd.edd_info_nr = boot_params.eddbuf_entries;
}
#else
static inline void copy_edd(void)
@@ -191,6 +198,37 @@ static inline void copy_edd(void)
}
#endif
+#ifdef CONFIG_KEXEC
+static void __init reserve_crashkernel(void)
+{
+ unsigned long long free_mem;
+ unsigned long long crash_size, crash_base;
+ int ret;
+
+ free_mem = ((unsigned long long)max_low_pfn - min_low_pfn) << PAGE_SHIFT;
+
+ ret = parse_crashkernel(boot_command_line, free_mem,
+ &crash_size, &crash_base);
+ if (ret == 0 && crash_size) {
+ if (crash_base > 0) {
+ printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
+ "for crashkernel (System RAM: %ldMB)\n",
+ (unsigned long)(crash_size >> 20),
+ (unsigned long)(crash_base >> 20),
+ (unsigned long)(free_mem >> 20));
+ crashk_res.start = crash_base;
+ crashk_res.end = crash_base + crash_size - 1;
+ reserve_bootmem(crash_base, crash_size);
+ } else
+ printk(KERN_INFO "crashkernel reservation failed - "
+ "you have to specify a base address\n");
+ }
+}
+#else
+static inline void __init reserve_crashkernel(void)
+{}
+#endif
+
#define EBDA_ADDR_POINTER 0x40E
unsigned __initdata ebda_addr;
@@ -220,21 +258,21 @@ void __init setup_arch(char **cmdline_p)
{
printk(KERN_INFO "Command line: %s\n", boot_command_line);
- ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
- screen_info = SCREEN_INFO;
- edid_info = EDID_INFO;
- saved_video_mode = SAVED_VIDEO_MODE;
- bootloader_type = LOADER_TYPE;
+ ROOT_DEV = old_decode_dev(boot_params.hdr.root_dev);
+ screen_info = boot_params.screen_info;
+ edid_info = boot_params.edid_info;
+ saved_video_mode = boot_params.hdr.vid_mode;
+ bootloader_type = boot_params.hdr.type_of_loader;
#ifdef CONFIG_BLK_DEV_RAM
- rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
- rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
- rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
+ rd_image_start = boot_params.hdr.ram_size & RAMDISK_IMAGE_START_MASK;
+ rd_prompt = ((boot_params.hdr.ram_size & RAMDISK_PROMPT_FLAG) != 0);
+ rd_doload = ((boot_params.hdr.ram_size & RAMDISK_LOAD_FLAG) != 0);
#endif
setup_memory_region();
copy_edd();
- if (!MOUNT_ROOT_RDONLY)
+ if (!boot_params.hdr.root_flags)
root_mountflags &= ~MS_RDONLY;
init_mm.start_code = (unsigned long) &_text;
init_mm.end_code = (unsigned long) &_etext;
@@ -245,6 +283,8 @@ void __init setup_arch(char **cmdline_p)
code_resource.end = virt_to_phys(&_etext)-1;
data_resource.start = virt_to_phys(&_etext);
data_resource.end = virt_to_phys(&_edata)-1;
+ bss_resource.start = virt_to_phys(&__bss_start);
+ bss_resource.end = virt_to_phys(&__bss_stop)-1;
early_identify_cpu(&boot_cpu_data);
@@ -271,6 +311,11 @@ void __init setup_arch(char **cmdline_p)
dmi_scan_machine();
+#ifdef CONFIG_SMP
+ /* setup to use the static apicid table during kernel startup */
+ x86_cpu_to_apicid_ptr = (void *)&x86_cpu_to_apicid_init;
+#endif
+
#ifdef CONFIG_ACPI
/*
* Initialize the ACPI boot-time table parser (gets the RSDP and SDT).
@@ -339,28 +384,25 @@ void __init setup_arch(char **cmdline_p)
*/
find_smp_config();
#ifdef CONFIG_BLK_DEV_INITRD
- if (LOADER_TYPE && INITRD_START) {
- if (INITRD_START + INITRD_SIZE <= (end_pfn << PAGE_SHIFT)) {
- reserve_bootmem_generic(INITRD_START, INITRD_SIZE);
- initrd_start = INITRD_START + PAGE_OFFSET;
- initrd_end = initrd_start+INITRD_SIZE;
- }
- else {
+ if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image) {
+ unsigned long ramdisk_image = boot_params.hdr.ramdisk_image;
+ unsigned long ramdisk_size = boot_params.hdr.ramdisk_size;
+ unsigned long ramdisk_end = ramdisk_image + ramdisk_size;
+ unsigned long end_of_mem = end_pfn << PAGE_SHIFT;
+
+ if (ramdisk_end <= end_of_mem) {
+ reserve_bootmem_generic(ramdisk_image, ramdisk_size);
+ initrd_start = ramdisk_image + PAGE_OFFSET;
+ initrd_end = initrd_start+ramdisk_size;
+ } else {
printk(KERN_ERR "initrd extends beyond end of memory "
- "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
- (unsigned long)(INITRD_START + INITRD_SIZE),
- (unsigned long)(end_pfn << PAGE_SHIFT));
+ "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+ ramdisk_end, end_of_mem);
initrd_start = 0;
}
}
#endif
-#ifdef CONFIG_KEXEC
- if (crashk_res.start != crashk_res.end) {
- reserve_bootmem_generic(crashk_res.start,
- crashk_res.end - crashk_res.start + 1);
- }
-#endif
-
+ reserve_crashkernel();
paging_init();
#ifdef CONFIG_PCI
@@ -526,7 +568,7 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
but in the same order as the HT nodeids.
If that doesn't result in a usable node fall back to the
path for the previous case. */
- int ht_nodeid = apicid - (cpu_data[0].phys_proc_id << bits);
+ int ht_nodeid = apicid - (cpu_data(0).phys_proc_id << bits);
if (ht_nodeid >= 0 &&
apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
node = apicid_to_node[ht_nodeid];
@@ -601,7 +643,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
level = cpuid_eax(1);
if (c->x86 == 15 && ((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58))
set_bit(X86_FEATURE_REP_GOOD, &c->x86_capability);
- if (c->x86 == 0x10)
+ if (c->x86 == 0x10 || c->x86 == 0x11)
set_bit(X86_FEATURE_REP_GOOD, &c->x86_capability);
/* Enable workaround for FXSAVE leak */
@@ -850,6 +892,7 @@ void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c)
#ifdef CONFIG_SMP
c->phys_proc_id = (cpuid_ebx(1) >> 24) & 0xff;
+ c->cpu_index = 0;
#endif
}
@@ -956,6 +999,7 @@ void __cpuinit print_cpu_info(struct cpuinfo_x86 *c)
static int show_cpuinfo(struct seq_file *m, void *v)
{
struct cpuinfo_x86 *c = v;
+ int cpu = 0;
/*
* These flag bits must match the definitions in <asm/cpufeature.h>.
@@ -965,7 +1009,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
* applications want to get the raw CPUID data, they should access
* /dev/cpu/<cpu_nr>/cpuid instead.
*/
- static char *x86_cap_flags[] = {
+ static const char *const x86_cap_flags[] = {
/* Intel-defined */
"fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
"cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
@@ -996,7 +1040,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
/* Intel-defined (#2) */
"pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est",
"tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL,
- NULL, NULL, "dca", NULL, NULL, NULL, NULL, "popcnt",
+ NULL, NULL, "dca", "sse4_1", "sse4_2", NULL, NULL, "popcnt",
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* VIA/Cyrix/Centaur-defined */
@@ -1006,10 +1050,10 @@ static int show_cpuinfo(struct seq_file *m, void *v)
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* AMD-defined (#2) */
- "lahf_lm", "cmp_legacy", "svm", "extapic", "cr8_legacy",
- "altmovcr8", "abm", "sse4a",
- "misalignsse", "3dnowprefetch",
- "osvw", "ibs", NULL, NULL, NULL, NULL,
+ "lahf_lm", "cmp_legacy", "svm", "extapic",
+ "cr8_legacy", "abm", "sse4a", "misalignsse",
+ "3dnowprefetch", "osvw", "ibs", "sse5",
+ "skinit", "wdt", NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -1019,7 +1063,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
- static char *x86_power_flags[] = {
+ static const char *const x86_power_flags[] = {
"ts", /* temperature sensor */
"fid", /* frequency id control */
"vid", /* voltage id control */
@@ -1034,8 +1078,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)
#ifdef CONFIG_SMP
- if (!cpu_online(c-cpu_data))
+ if (!cpu_online(c->cpu_index))
return 0;
+ cpu = c->cpu_index;
#endif
seq_printf(m,"processor\t: %u\n"
@@ -1043,7 +1088,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
"cpu family\t: %d\n"
"model\t\t: %d\n"
"model name\t: %s\n",
- (unsigned)(c-cpu_data),
+ (unsigned)cpu,
c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown",
c->x86,
(int)c->x86_model,
@@ -1055,7 +1100,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
seq_printf(m, "stepping\t: unknown\n");
if (cpu_has(c,X86_FEATURE_TSC)) {
- unsigned int freq = cpufreq_quick_get((unsigned)(c-cpu_data));
+ unsigned int freq = cpufreq_quick_get((unsigned)cpu);
if (!freq)
freq = cpu_khz;
seq_printf(m, "cpu MHz\t\t: %u.%03u\n",
@@ -1068,9 +1113,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)
#ifdef CONFIG_SMP
if (smp_num_siblings * c->x86_max_cores > 1) {
- int cpu = c - cpu_data;
seq_printf(m, "physical id\t: %d\n", c->phys_proc_id);
- seq_printf(m, "siblings\t: %d\n", cpus_weight(cpu_core_map[cpu]));
+ seq_printf(m, "siblings\t: %d\n",
+ cpus_weight(per_cpu(cpu_core_map, cpu)));
seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id);
seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
}
@@ -1125,12 +1170,16 @@ static int show_cpuinfo(struct seq_file *m, void *v)
static void *c_start(struct seq_file *m, loff_t *pos)
{
- return *pos < NR_CPUS ? cpu_data + *pos : NULL;
+ if (*pos == 0) /* just in case, cpu 0 is not the first */
+ *pos = first_cpu(cpu_possible_map);
+ if ((*pos) < NR_CPUS && cpu_possible(*pos))
+ return &cpu_data(*pos);
+ return NULL;
}
static void *c_next(struct seq_file *m, void *v, loff_t *pos)
{
- ++*pos;
+ *pos = next_cpu(*pos, cpu_possible_map);
return c_start(m, pos);
}
diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c
index d01d51fcce2a..9bdd83022f5f 100644
--- a/arch/x86/kernel/signal_32.c
+++ b/arch/x86/kernel/signal_32.c
@@ -200,8 +200,8 @@ badframe:
if (show_unhandled_signals && printk_ratelimit())
printk("%s%s[%d] bad frame in sigreturn frame:%p eip:%lx"
" esp:%lx oeax:%lx\n",
- current->pid > 1 ? KERN_INFO : KERN_EMERG,
- current->comm, current->pid, frame, regs->eip,
+ task_pid_nr(current) > 1 ? KERN_INFO : KERN_EMERG,
+ current->comm, task_pid_nr(current), frame, regs->eip,
regs->esp, regs->orig_eax);
force_sig(SIGSEGV, current);
@@ -385,7 +385,6 @@ static int setup_frame(int sig, struct k_sigaction *ka,
regs->edx = (unsigned long) 0;
regs->ecx = (unsigned long) 0;
- set_fs(USER_DS);
regs->xds = __USER_DS;
regs->xes = __USER_DS;
regs->xss = __USER_DS;
@@ -479,7 +478,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
regs->edx = (unsigned long) &frame->info;
regs->ecx = (unsigned long) &frame->uc;
- set_fs(USER_DS);
regs->xds = __USER_DS;
regs->xes = __USER_DS;
regs->xss = __USER_DS;
@@ -596,7 +594,7 @@ static void fastcall do_signal(struct pt_regs *regs)
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) {
- /* Reenable any watchpoints before delivering the
+ /* Re-enable any watchpoints before delivering the
* signal to user space. The processor register will
* have been cleared if the watchpoint triggered
* inside the kernel.
diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c
index 683802bec419..ab086b0357fc 100644
--- a/arch/x86/kernel/signal_64.c
+++ b/arch/x86/kernel/signal_64.c
@@ -410,7 +410,7 @@ static void do_signal(struct pt_regs *regs)
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) {
- /* Reenable any watchpoints before delivering the
+ /* Re-enable any watchpoints before delivering the
* signal to user space. The processor register will
* have been cleared if the watchpoint triggered
* inside the kernel.
diff --git a/arch/x86/kernel/smp_32.c b/arch/x86/kernel/smp_32.c
index 2d35d8502029..fcaa026eb807 100644
--- a/arch/x86/kernel/smp_32.c
+++ b/arch/x86/kernel/smp_32.c
@@ -69,7 +69,7 @@
*
* B stepping CPUs may hang. There are hardware work arounds
* for this. We warn about it in case your board doesn't have the work
- * arounds. Basically thats so I can tell anyone with a B stepping
+ * arounds. Basically that's so I can tell anyone with a B stepping
* CPU and SMP problems "tough".
*
* Specific items [From Pentium Processor Specification Update]
@@ -273,7 +273,7 @@ void leave_mm(unsigned long cpu)
* 1a1) cpu_clear(cpu, old_mm->cpu_vm_mask);
* Stop ipi delivery for the old mm. This is not synchronized with
* the other cpus, but smp_invalidate_interrupt ignore flush ipis
- * for the wrong mm, and in the worst case we perform a superflous
+ * for the wrong mm, and in the worst case we perform a superfluous
* tlb flush.
* 1a2) set cpu_tlbstate to TLBSTATE_OK
* Now the smp_invalidate_interrupt won't call leave_mm if cpu0
@@ -342,6 +342,7 @@ fastcall void smp_invalidate_interrupt(struct pt_regs *regs)
smp_mb__after_clear_bit();
out:
put_cpu_no_resched();
+ __get_cpu_var(irq_stat).irq_tlb_count++;
}
void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm,
@@ -609,7 +610,7 @@ static void stop_this_cpu (void * dummy)
*/
cpu_clear(smp_processor_id(), cpu_online_map);
disable_local_APIC();
- if (cpu_data[smp_processor_id()].hlt_works_ok)
+ if (cpu_data(smp_processor_id()).hlt_works_ok)
for(;;) halt();
for (;;);
}
@@ -640,6 +641,7 @@ static void native_smp_send_stop(void)
fastcall void smp_reschedule_interrupt(struct pt_regs *regs)
{
ack_APIC_irq();
+ __get_cpu_var(irq_stat).irq_resched_count++;
}
fastcall void smp_call_function_interrupt(struct pt_regs *regs)
@@ -660,6 +662,7 @@ fastcall void smp_call_function_interrupt(struct pt_regs *regs)
*/
irq_enter();
(*func)(info);
+ __get_cpu_var(irq_stat).irq_call_count++;
irq_exit();
if (wait) {
@@ -673,7 +676,7 @@ static int convert_apicid_to_cpu(int apic_id)
int i;
for (i = 0; i < NR_CPUS; i++) {
- if (x86_cpu_to_apicid[i] == apic_id)
+ if (per_cpu(x86_cpu_to_apicid, i) == apic_id)
return i;
}
return -1;
@@ -705,3 +708,4 @@ struct smp_ops smp_ops = {
.smp_send_reschedule = native_smp_send_reschedule,
.smp_call_function_mask = native_smp_call_function_mask,
};
+EXPORT_SYMBOL_GPL(smp_ops);
diff --git a/arch/x86/kernel/smp_64.c b/arch/x86/kernel/smp_64.c
index df4a82812adb..03fa6ed559c6 100644
--- a/arch/x86/kernel/smp_64.c
+++ b/arch/x86/kernel/smp_64.c
@@ -163,6 +163,7 @@ asmlinkage void smp_invalidate_interrupt(struct pt_regs *regs)
out:
ack_APIC_irq();
cpu_clear(cpu, f->flush_cpumask);
+ add_pda(irq_tlb_count, 1);
}
static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
@@ -321,17 +322,27 @@ void unlock_ipi_call_lock(void)
}
/*
- * this function sends a 'generic call function' IPI to one other CPU
- * in the system.
- *
- * cpu is a standard Linux logical CPU number.
+ * this function sends a 'generic call function' IPI to all other CPU
+ * of the system defined in the mask.
*/
-static void
-__smp_call_function_single(int cpu, void (*func) (void *info), void *info,
- int nonatomic, int wait)
+
+static int
+__smp_call_function_mask(cpumask_t mask,
+ void (*func)(void *), void *info,
+ int wait)
{
struct call_data_struct data;
- int cpus = 1;
+ cpumask_t allbutself;
+ int cpus;
+
+ allbutself = cpu_online_map;
+ cpu_clear(smp_processor_id(), allbutself);
+
+ cpus_and(mask, mask, allbutself);
+ cpus = cpus_weight(mask);
+
+ if (!cpus)
+ return 0;
data.func = func;
data.info = info;
@@ -342,19 +353,55 @@ __smp_call_function_single(int cpu, void (*func) (void *info), void *info,
call_data = &data;
wmb();
- /* Send a message to all other CPUs and wait for them to respond */
- send_IPI_mask(cpumask_of_cpu(cpu), CALL_FUNCTION_VECTOR);
+
+ /* Send a message to other CPUs */
+ if (cpus_equal(mask, allbutself))
+ send_IPI_allbutself(CALL_FUNCTION_VECTOR);
+ else
+ send_IPI_mask(mask, CALL_FUNCTION_VECTOR);
/* Wait for response */
while (atomic_read(&data.started) != cpus)
cpu_relax();
if (!wait)
- return;
+ return 0;
while (atomic_read(&data.finished) != cpus)
cpu_relax();
+
+ return 0;
+}
+/**
+ * smp_call_function_mask(): Run a function on a set of other CPUs.
+ * @mask: The set of cpus to run on. Must not include the current cpu.
+ * @func: The function to run. This must be fast and non-blocking.
+ * @info: An arbitrary pointer to pass to the function.
+ * @wait: If true, wait (atomically) until function has completed on other CPUs.
+ *
+ * Returns 0 on success, else a negative status code.
+ *
+ * If @wait is true, then returns once @func has returned; otherwise
+ * it returns just before the target cpu calls @func.
+ *
+ * You must not call this function with disabled interrupts or from a
+ * hardware interrupt handler or from a bottom half handler.
+ */
+int smp_call_function_mask(cpumask_t mask,
+ void (*func)(void *), void *info,
+ int wait)
+{
+ int ret;
+
+ /* Can deadlock when called with interrupts disabled */
+ WARN_ON(irqs_disabled());
+
+ spin_lock(&call_lock);
+ ret = __smp_call_function_mask(mask, func, info, wait);
+ spin_unlock(&call_lock);
+ return ret;
}
+EXPORT_SYMBOL(smp_call_function_mask);
/*
* smp_call_function_single - Run a function on a specific CPU
@@ -373,6 +420,7 @@ int smp_call_function_single (int cpu, void (*func) (void *info), void *info,
int nonatomic, int wait)
{
/* prevent preemption and reschedule on another processor */
+ int ret;
int me = get_cpu();
/* Can deadlock when called with interrupts disabled */
@@ -386,51 +434,14 @@ int smp_call_function_single (int cpu, void (*func) (void *info), void *info,
return 0;
}
- spin_lock(&call_lock);
- __smp_call_function_single(cpu, func, info, nonatomic, wait);
- spin_unlock(&call_lock);
+ ret = smp_call_function_mask(cpumask_of_cpu(cpu), func, info, wait);
+
put_cpu();
- return 0;
+ return ret;
}
EXPORT_SYMBOL(smp_call_function_single);
/*
- * this function sends a 'generic call function' IPI to all other CPUs
- * in the system.
- */
-static void __smp_call_function (void (*func) (void *info), void *info,
- int nonatomic, int wait)
-{
- struct call_data_struct data;
- int cpus = num_online_cpus()-1;
-
- if (!cpus)
- return;
-
- data.func = func;
- data.info = info;
- atomic_set(&data.started, 0);
- data.wait = wait;
- if (wait)
- atomic_set(&data.finished, 0);
-
- call_data = &data;
- wmb();
- /* Send a message to all other CPUs and wait for them to respond */
- send_IPI_allbutself(CALL_FUNCTION_VECTOR);
-
- /* Wait for response */
- while (atomic_read(&data.started) != cpus)
- cpu_relax();
-
- if (!wait)
- return;
-
- while (atomic_read(&data.finished) != cpus)
- cpu_relax();
-}
-
-/*
* smp_call_function - run a function on all other CPUs.
* @func: The function to run. This must be fast and non-blocking.
* @info: An arbitrary pointer to pass to the function.
@@ -448,10 +459,7 @@ static void __smp_call_function (void (*func) (void *info), void *info,
int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
int wait)
{
- spin_lock(&call_lock);
- __smp_call_function(func,info,nonatomic,wait);
- spin_unlock(&call_lock);
- return 0;
+ return smp_call_function_mask(cpu_online_map, func, info, wait);
}
EXPORT_SYMBOL(smp_call_function);
@@ -478,7 +486,7 @@ void smp_send_stop(void)
/* Don't deadlock on the call lock in panic */
nolock = !spin_trylock(&call_lock);
local_irq_save(flags);
- __smp_call_function(stop_this_cpu, NULL, 0, 0);
+ __smp_call_function_mask(cpu_online_map, stop_this_cpu, NULL, 0);
if (!nolock)
spin_unlock(&call_lock);
disable_local_APIC();
@@ -493,6 +501,7 @@ void smp_send_stop(void)
asmlinkage void smp_reschedule_interrupt(void)
{
ack_APIC_irq();
+ add_pda(irq_resched_count, 1);
}
asmlinkage void smp_call_function_interrupt(void)
@@ -514,6 +523,7 @@ asmlinkage void smp_call_function_interrupt(void)
exit_idle();
irq_enter();
(*func)(info);
+ add_pda(irq_call_count, 1);
irq_exit();
if (wait) {
mb();
diff --git a/arch/x86/kernel/smpboot_32.c b/arch/x86/kernel/smpboot_32.c
index e4f61d1c6248..ef0f34ede1ab 100644
--- a/arch/x86/kernel/smpboot_32.c
+++ b/arch/x86/kernel/smpboot_32.c
@@ -67,15 +67,15 @@ int smp_num_siblings = 1;
EXPORT_SYMBOL(smp_num_siblings);
/* Last level cache ID of each logical CPU */
-int cpu_llc_id[NR_CPUS] __cpuinitdata = {[0 ... NR_CPUS-1] = BAD_APICID};
+DEFINE_PER_CPU(u8, cpu_llc_id) = BAD_APICID;
/* representing HT siblings of each logical CPU */
-cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly;
-EXPORT_SYMBOL(cpu_sibling_map);
+DEFINE_PER_CPU(cpumask_t, cpu_sibling_map);
+EXPORT_PER_CPU_SYMBOL(cpu_sibling_map);
/* representing HT and core siblings of each logical CPU */
-cpumask_t cpu_core_map[NR_CPUS] __read_mostly;
-EXPORT_SYMBOL(cpu_core_map);
+DEFINE_PER_CPU(cpumask_t, cpu_core_map);
+EXPORT_PER_CPU_SYMBOL(cpu_core_map);
/* bitmap of online cpus */
cpumask_t cpu_online_map __read_mostly;
@@ -89,12 +89,20 @@ EXPORT_SYMBOL(cpu_possible_map);
static cpumask_t smp_commenced_mask;
/* Per CPU bogomips and other parameters */
-struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
-EXPORT_SYMBOL(cpu_data);
+DEFINE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info);
+EXPORT_PER_CPU_SYMBOL(cpu_info);
-u8 x86_cpu_to_apicid[NR_CPUS] __read_mostly =
- { [0 ... NR_CPUS-1] = 0xff };
-EXPORT_SYMBOL(x86_cpu_to_apicid);
+/*
+ * The following static array is used during kernel startup
+ * and the x86_cpu_to_apicid_ptr contains the address of the
+ * array during this time. Is it zeroed when the per_cpu
+ * data area is removed.
+ */
+u8 x86_cpu_to_apicid_init[NR_CPUS] __initdata =
+ { [0 ... NR_CPUS-1] = BAD_APICID };
+void *x86_cpu_to_apicid_ptr;
+DEFINE_PER_CPU(u8, x86_cpu_to_apicid) = BAD_APICID;
+EXPORT_PER_CPU_SYMBOL(x86_cpu_to_apicid);
u8 apicid_2_node[MAX_APICID];
@@ -102,8 +110,8 @@ u8 apicid_2_node[MAX_APICID];
* Trampoline 80x86 program as an array.
*/
-extern unsigned char trampoline_data [];
-extern unsigned char trampoline_end [];
+extern const unsigned char trampoline_data [];
+extern const unsigned char trampoline_end [];
static unsigned char *trampoline_base;
static int trampoline_exec;
@@ -118,7 +126,7 @@ DEFINE_PER_CPU(int, cpu_state) = { 0 };
* has made sure it's suitably aligned.
*/
-static unsigned long __devinit setup_trampoline(void)
+static unsigned long __cpuinit setup_trampoline(void)
{
memcpy(trampoline_base, trampoline_data, trampoline_end - trampoline_data);
return virt_to_phys(trampoline_base);
@@ -150,9 +158,10 @@ void __init smp_alloc_memory(void)
void __cpuinit smp_store_cpu_info(int id)
{
- struct cpuinfo_x86 *c = cpu_data + id;
+ struct cpuinfo_x86 *c = &cpu_data(id);
*c = boot_cpu_data;
+ c->cpu_index = id;
if (id!=0)
identify_secondary_cpu(c);
/*
@@ -294,13 +303,13 @@ static int cpucount;
/* maps the cpu to the sched domain representing multi-core */
cpumask_t cpu_coregroup_map(int cpu)
{
- struct cpuinfo_x86 *c = cpu_data + cpu;
+ struct cpuinfo_x86 *c = &cpu_data(cpu);
/*
* For perf, we return last level cache shared map.
* And for power savings, we return cpu_core_map
*/
if (sched_mc_power_savings || sched_smt_power_savings)
- return cpu_core_map[cpu];
+ return per_cpu(cpu_core_map, cpu);
else
return c->llc_shared_map;
}
@@ -311,61 +320,61 @@ static cpumask_t cpu_sibling_setup_map;
void __cpuinit set_cpu_sibling_map(int cpu)
{
int i;
- struct cpuinfo_x86 *c = cpu_data;
+ struct cpuinfo_x86 *c = &cpu_data(cpu);
cpu_set(cpu, cpu_sibling_setup_map);
if (smp_num_siblings > 1) {
for_each_cpu_mask(i, cpu_sibling_setup_map) {
- if (c[cpu].phys_proc_id == c[i].phys_proc_id &&
- c[cpu].cpu_core_id == c[i].cpu_core_id) {
- cpu_set(i, cpu_sibling_map[cpu]);
- cpu_set(cpu, cpu_sibling_map[i]);
- cpu_set(i, cpu_core_map[cpu]);
- cpu_set(cpu, cpu_core_map[i]);
- cpu_set(i, c[cpu].llc_shared_map);
- cpu_set(cpu, c[i].llc_shared_map);
+ if (c->phys_proc_id == cpu_data(i).phys_proc_id &&
+ c->cpu_core_id == cpu_data(i).cpu_core_id) {
+ cpu_set(i, per_cpu(cpu_sibling_map, cpu));
+ cpu_set(cpu, per_cpu(cpu_sibling_map, i));
+ cpu_set(i, per_cpu(cpu_core_map, cpu));
+ cpu_set(cpu, per_cpu(cpu_core_map, i));
+ cpu_set(i, c->llc_shared_map);
+ cpu_set(cpu, cpu_data(i).llc_shared_map);
}
}
} else {
- cpu_set(cpu, cpu_sibling_map[cpu]);
+ cpu_set(cpu, per_cpu(cpu_sibling_map, cpu));
}
- cpu_set(cpu, c[cpu].llc_shared_map);
+ cpu_set(cpu, c->llc_shared_map);
if (current_cpu_data.x86_max_cores == 1) {
- cpu_core_map[cpu] = cpu_sibling_map[cpu];
- c[cpu].booted_cores = 1;
+ per_cpu(cpu_core_map, cpu) = per_cpu(cpu_sibling_map, cpu);
+ c->booted_cores = 1;
return;
}
for_each_cpu_mask(i, cpu_sibling_setup_map) {
- if (cpu_llc_id[cpu] != BAD_APICID &&
- cpu_llc_id[cpu] == cpu_llc_id[i]) {
- cpu_set(i, c[cpu].llc_shared_map);
- cpu_set(cpu, c[i].llc_shared_map);
+ if (per_cpu(cpu_llc_id, cpu) != BAD_APICID &&
+ per_cpu(cpu_llc_id, cpu) == per_cpu(cpu_llc_id, i)) {
+ cpu_set(i, c->llc_shared_map);
+ cpu_set(cpu, cpu_data(i).llc_shared_map);
}
- if (c[cpu].phys_proc_id == c[i].phys_proc_id) {
- cpu_set(i, cpu_core_map[cpu]);
- cpu_set(cpu, cpu_core_map[i]);
+ if (c->phys_proc_id == cpu_data(i).phys_proc_id) {
+ cpu_set(i, per_cpu(cpu_core_map, cpu));
+ cpu_set(cpu, per_cpu(cpu_core_map, i));
/*
* Does this new cpu bringup a new core?
*/
- if (cpus_weight(cpu_sibling_map[cpu]) == 1) {
+ if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1) {
/*
* for each core in package, increment
* the booted_cores for this new cpu
*/
- if (first_cpu(cpu_sibling_map[i]) == i)
- c[cpu].booted_cores++;
+ if (first_cpu(per_cpu(cpu_sibling_map, i)) == i)
+ c->booted_cores++;
/*
* increment the core count for all
* the other cpus in this package
*/
if (i != cpu)
- c[i].booted_cores++;
- } else if (i != cpu && !c[cpu].booted_cores)
- c[cpu].booted_cores = c[i].booted_cores;
+ cpu_data(i).booted_cores++;
+ } else if (i != cpu && !c->booted_cores)
+ c->booted_cores = cpu_data(i).booted_cores;
}
}
}
@@ -412,7 +421,7 @@ static void __cpuinit start_secondary(void *unused)
/*
* We need to hold call_lock, so there is no inconsistency
* between the time smp_call_function() determines number of
- * IPI receipients, and the time when the determination is made
+ * IPI recipients, and the time when the determination is made
* for which cpus receive the IPI. Holding this
* lock helps us to not include this cpu in a currently in progress
* smp_call_function().
@@ -804,7 +813,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu)
irq_ctx_init(cpu);
- x86_cpu_to_apicid[cpu] = apicid;
+ per_cpu(x86_cpu_to_apicid, cpu) = apicid;
/*
* This grunge runs the startup process for
* the targeted processor.
@@ -844,7 +853,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu)
/* number CPUs logically, starting from 1 (BSP is 0) */
Dprintk("OK.\n");
printk("CPU%d: ", cpu);
- print_cpu_info(&cpu_data[cpu]);
+ print_cpu_info(&cpu_data(cpu));
Dprintk("CPU has booted.\n");
} else {
boot_error= 1;
@@ -866,7 +875,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu)
cpu_clear(cpu, cpu_initialized); /* was set by cpu_init() */
cpucount--;
} else {
- x86_cpu_to_apicid[cpu] = apicid;
+ per_cpu(x86_cpu_to_apicid, cpu) = apicid;
cpu_set(cpu, cpu_present_map);
}
@@ -915,7 +924,7 @@ static int __cpuinit __smp_prepare_cpu(int cpu)
struct warm_boot_cpu_info info;
int apicid, ret;
- apicid = x86_cpu_to_apicid[cpu];
+ apicid = per_cpu(x86_cpu_to_apicid, cpu);
if (apicid == BAD_APICID) {
ret = -ENODEV;
goto exit;
@@ -961,11 +970,11 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
*/
smp_store_cpu_info(0); /* Final full version of the data */
printk("CPU%d: ", 0);
- print_cpu_info(&cpu_data[0]);
+ print_cpu_info(&cpu_data(0));
boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
boot_cpu_logical_apicid = logical_smp_processor_id();
- x86_cpu_to_apicid[0] = boot_cpu_physical_apicid;
+ per_cpu(x86_cpu_to_apicid, 0) = boot_cpu_physical_apicid;
current_thread_info()->cpu = 0;
@@ -983,8 +992,8 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
printk(KERN_NOTICE "Local APIC not detected."
" Using dummy APIC emulation.\n");
map_cpu_to_logical_apicid();
- cpu_set(0, cpu_sibling_map[0]);
- cpu_set(0, cpu_core_map[0]);
+ cpu_set(0, per_cpu(cpu_sibling_map, 0));
+ cpu_set(0, per_cpu(cpu_core_map, 0));
return;
}
@@ -1008,8 +1017,9 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n");
smpboot_clear_io_apic_irqs();
phys_cpu_present_map = physid_mask_of_physid(0);
- cpu_set(0, cpu_sibling_map[0]);
- cpu_set(0, cpu_core_map[0]);
+ map_cpu_to_logical_apicid();
+ cpu_set(0, per_cpu(cpu_sibling_map, 0));
+ cpu_set(0, per_cpu(cpu_core_map, 0));
return;
}
@@ -1021,10 +1031,17 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
if (!max_cpus) {
smp_found_config = 0;
printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n");
+
+ if (nmi_watchdog == NMI_LOCAL_APIC) {
+ printk(KERN_INFO "activating minimal APIC for NMI watchdog use.\n");
+ connect_bsp_APIC();
+ setup_local_APIC();
+ }
smpboot_clear_io_apic_irqs();
phys_cpu_present_map = physid_mask_of_physid(0);
- cpu_set(0, cpu_sibling_map[0]);
- cpu_set(0, cpu_core_map[0]);
+ map_cpu_to_logical_apicid();
+ cpu_set(0, per_cpu(cpu_sibling_map, 0));
+ cpu_set(0, per_cpu(cpu_core_map, 0));
return;
}
@@ -1076,7 +1093,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
Dprintk("Before bogomips.\n");
for (cpu = 0; cpu < NR_CPUS; cpu++)
if (cpu_isset(cpu, cpu_callout_map))
- bogosum += cpu_data[cpu].loops_per_jiffy;
+ bogosum += cpu_data(cpu).loops_per_jiffy;
printk(KERN_INFO
"Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
cpucount+1,
@@ -1102,16 +1119,16 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
Dprintk("Boot done.\n");
/*
- * construct cpu_sibling_map[], so that we can tell sibling CPUs
+ * construct cpu_sibling_map, so that we can tell sibling CPUs
* efficiently.
*/
for (cpu = 0; cpu < NR_CPUS; cpu++) {
- cpus_clear(cpu_sibling_map[cpu]);
- cpus_clear(cpu_core_map[cpu]);
+ cpus_clear(per_cpu(cpu_sibling_map, cpu));
+ cpus_clear(per_cpu(cpu_core_map, cpu));
}
- cpu_set(0, cpu_sibling_map[0]);
- cpu_set(0, cpu_core_map[0]);
+ cpu_set(0, per_cpu(cpu_sibling_map, 0));
+ cpu_set(0, per_cpu(cpu_core_map, 0));
smpboot_setup_io_apic();
@@ -1146,23 +1163,23 @@ void __init native_smp_prepare_boot_cpu(void)
void remove_siblinginfo(int cpu)
{
int sibling;
- struct cpuinfo_x86 *c = cpu_data;
+ struct cpuinfo_x86 *c = &cpu_data(cpu);
- for_each_cpu_mask(sibling, cpu_core_map[cpu]) {
- cpu_clear(cpu, cpu_core_map[sibling]);
- /*
+ for_each_cpu_mask(sibling, per_cpu(cpu_core_map, cpu)) {
+ cpu_clear(cpu, per_cpu(cpu_core_map, sibling));
+ /*/
* last thread sibling in this cpu core going down
*/
- if (cpus_weight(cpu_sibling_map[cpu]) == 1)
- c[sibling].booted_cores--;
+ if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1)
+ cpu_data(sibling).booted_cores--;
}
- for_each_cpu_mask(sibling, cpu_sibling_map[cpu])
- cpu_clear(cpu, cpu_sibling_map[sibling]);
- cpus_clear(cpu_sibling_map[cpu]);
- cpus_clear(cpu_core_map[cpu]);
- c[cpu].phys_proc_id = 0;
- c[cpu].cpu_core_id = 0;
+ for_each_cpu_mask(sibling, per_cpu(cpu_sibling_map, cpu))
+ cpu_clear(cpu, per_cpu(cpu_sibling_map, sibling));
+ cpus_clear(per_cpu(cpu_sibling_map, cpu));
+ cpus_clear(per_cpu(cpu_core_map, cpu));
+ c->phys_proc_id = 0;
+ c->cpu_core_id = 0;
cpu_clear(cpu, cpu_sibling_setup_map);
}
diff --git a/arch/x86/kernel/smpboot_64.c b/arch/x86/kernel/smpboot_64.c
index 720a7d1f8862..500670c93d81 100644
--- a/arch/x86/kernel/smpboot_64.c
+++ b/arch/x86/kernel/smpboot_64.c
@@ -65,7 +65,7 @@ int smp_num_siblings = 1;
EXPORT_SYMBOL(smp_num_siblings);
/* Last level cache ID of each logical CPU */
-u8 cpu_llc_id[NR_CPUS] __cpuinitdata = {[0 ... NR_CPUS-1] = BAD_APICID};
+DEFINE_PER_CPU(u8, cpu_llc_id) = BAD_APICID;
/* Bitmask of currently online CPUs */
cpumask_t cpu_online_map __read_mostly;
@@ -84,26 +84,26 @@ cpumask_t cpu_possible_map;
EXPORT_SYMBOL(cpu_possible_map);
/* Per CPU bogomips and other parameters */
-struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
-EXPORT_SYMBOL(cpu_data);
+DEFINE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info);
+EXPORT_PER_CPU_SYMBOL(cpu_info);
/* Set when the idlers are all forked */
int smp_threads_ready;
/* representing HT siblings of each logical CPU */
-cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly;
-EXPORT_SYMBOL(cpu_sibling_map);
+DEFINE_PER_CPU(cpumask_t, cpu_sibling_map);
+EXPORT_PER_CPU_SYMBOL(cpu_sibling_map);
/* representing HT and core siblings of each logical CPU */
-cpumask_t cpu_core_map[NR_CPUS] __read_mostly;
-EXPORT_SYMBOL(cpu_core_map);
+DEFINE_PER_CPU(cpumask_t, cpu_core_map);
+EXPORT_PER_CPU_SYMBOL(cpu_core_map);
/*
* Trampoline 80x86 program as an array.
*/
-extern unsigned char trampoline_data[];
-extern unsigned char trampoline_end[];
+extern const unsigned char trampoline_data[];
+extern const unsigned char trampoline_end[];
/* State of each CPU */
DEFINE_PER_CPU(int, cpu_state) = { 0 };
@@ -138,9 +138,10 @@ static unsigned long __cpuinit setup_trampoline(void)
static void __cpuinit smp_store_cpu_info(int id)
{
- struct cpuinfo_x86 *c = cpu_data + id;
+ struct cpuinfo_x86 *c = &cpu_data(id);
*c = boot_cpu_data;
+ c->cpu_index = id;
identify_cpu(c);
print_cpu_info(c);
}
@@ -237,13 +238,13 @@ void __cpuinit smp_callin(void)
/* maps the cpu to the sched domain representing multi-core */
cpumask_t cpu_coregroup_map(int cpu)
{
- struct cpuinfo_x86 *c = cpu_data + cpu;
+ struct cpuinfo_x86 *c = &cpu_data(cpu);
/*
* For perf, we return last level cache shared map.
* And for power savings, we return cpu_core_map
*/
if (sched_mc_power_savings || sched_smt_power_savings)
- return cpu_core_map[cpu];
+ return per_cpu(cpu_core_map, cpu);
else
return c->llc_shared_map;
}
@@ -254,61 +255,61 @@ static cpumask_t cpu_sibling_setup_map;
static inline void set_cpu_sibling_map(int cpu)
{
int i;
- struct cpuinfo_x86 *c = cpu_data;
+ struct cpuinfo_x86 *c = &cpu_data(cpu);
cpu_set(cpu, cpu_sibling_setup_map);
if (smp_num_siblings > 1) {
for_each_cpu_mask(i, cpu_sibling_setup_map) {
- if (c[cpu].phys_proc_id == c[i].phys_proc_id &&
- c[cpu].cpu_core_id == c[i].cpu_core_id) {
- cpu_set(i, cpu_sibling_map[cpu]);
- cpu_set(cpu, cpu_sibling_map[i]);
- cpu_set(i, cpu_core_map[cpu]);
- cpu_set(cpu, cpu_core_map[i]);
- cpu_set(i, c[cpu].llc_shared_map);
- cpu_set(cpu, c[i].llc_shared_map);
+ if (c->phys_proc_id == cpu_data(i).phys_proc_id &&
+ c->cpu_core_id == cpu_data(i).cpu_core_id) {
+ cpu_set(i, per_cpu(cpu_sibling_map, cpu));
+ cpu_set(cpu, per_cpu(cpu_sibling_map, i));
+ cpu_set(i, per_cpu(cpu_core_map, cpu));
+ cpu_set(cpu, per_cpu(cpu_core_map, i));
+ cpu_set(i, c->llc_shared_map);
+ cpu_set(cpu, cpu_data(i).llc_shared_map);
}
}
} else {
- cpu_set(cpu, cpu_sibling_map[cpu]);
+ cpu_set(cpu, per_cpu(cpu_sibling_map, cpu));
}
- cpu_set(cpu, c[cpu].llc_shared_map);
+ cpu_set(cpu, c->llc_shared_map);
if (current_cpu_data.x86_max_cores == 1) {
- cpu_core_map[cpu] = cpu_sibling_map[cpu];
- c[cpu].booted_cores = 1;
+ per_cpu(cpu_core_map, cpu) = per_cpu(cpu_sibling_map, cpu);
+ c->booted_cores = 1;
return;
}
for_each_cpu_mask(i, cpu_sibling_setup_map) {
- if (cpu_llc_id[cpu] != BAD_APICID &&
- cpu_llc_id[cpu] == cpu_llc_id[i]) {
- cpu_set(i, c[cpu].llc_shared_map);
- cpu_set(cpu, c[i].llc_shared_map);
+ if (per_cpu(cpu_llc_id, cpu) != BAD_APICID &&
+ per_cpu(cpu_llc_id, cpu) == per_cpu(cpu_llc_id, i)) {
+ cpu_set(i, c->llc_shared_map);
+ cpu_set(cpu, cpu_data(i).llc_shared_map);
}
- if (c[cpu].phys_proc_id == c[i].phys_proc_id) {
- cpu_set(i, cpu_core_map[cpu]);
- cpu_set(cpu, cpu_core_map[i]);
+ if (c->phys_proc_id == cpu_data(i).phys_proc_id) {
+ cpu_set(i, per_cpu(cpu_core_map, cpu));
+ cpu_set(cpu, per_cpu(cpu_core_map, i));
/*
* Does this new cpu bringup a new core?
*/
- if (cpus_weight(cpu_sibling_map[cpu]) == 1) {
+ if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1) {
/*
* for each core in package, increment
* the booted_cores for this new cpu
*/
- if (first_cpu(cpu_sibling_map[i]) == i)
- c[cpu].booted_cores++;
+ if (first_cpu(per_cpu(cpu_sibling_map, i)) == i)
+ c->booted_cores++;
/*
* increment the core count for all
* the other cpus in this package
*/
if (i != cpu)
- c[i].booted_cores++;
- } else if (i != cpu && !c[cpu].booted_cores)
- c[cpu].booted_cores = c[i].booted_cores;
+ cpu_data(i).booted_cores++;
+ } else if (i != cpu && !c->booted_cores)
+ c->booted_cores = cpu_data(i).booted_cores;
}
}
}
@@ -350,7 +351,7 @@ void __cpuinit start_secondary(void)
/*
* We need to hold call_lock, so there is no inconsistency
* between the time smp_call_function() determines number of
- * IPI receipients, and the time when the determination is made
+ * IPI recipients, and the time when the determination is made
* for which cpus receive the IPI in genapic_flat.c. Holding this
* lock helps us to not include this cpu in a currently in progress
* smp_call_function().
@@ -387,7 +388,7 @@ static void inquire_remote_apic(int apicid)
printk(KERN_INFO "Inquiring remote APIC #%d...\n", apicid);
- for (i = 0; i < sizeof(regs) / sizeof(*regs); i++) {
+ for (i = 0; i < ARRAY_SIZE(regs); i++) {
printk("... APIC #%d %s: ", apicid, names[i]);
/*
@@ -694,8 +695,7 @@ do_rest:
clear_node_cpumask(cpu); /* was set by numa_add_cpu */
cpu_clear(cpu, cpu_present_map);
cpu_clear(cpu, cpu_possible_map);
- x86_cpu_to_apicid[cpu] = BAD_APICID;
- x86_cpu_to_log_apicid[cpu] = BAD_APICID;
+ per_cpu(x86_cpu_to_apicid, cpu) = BAD_APICID;
return -EIO;
}
@@ -735,8 +735,8 @@ static __init void disable_smp(void)
phys_cpu_present_map = physid_mask_of_physid(boot_cpu_id);
else
phys_cpu_present_map = physid_mask_of_physid(0);
- cpu_set(0, cpu_sibling_map[0]);
- cpu_set(0, cpu_core_map[0]);
+ cpu_set(0, per_cpu(cpu_sibling_map, 0));
+ cpu_set(0, per_cpu(cpu_core_map, 0));
}
#ifdef CONFIG_HOTPLUG_CPU
@@ -842,6 +842,26 @@ static int __init smp_sanity_check(unsigned max_cpus)
}
/*
+ * Copy apicid's found by MP_processor_info from initial array to the per cpu
+ * data area. The x86_cpu_to_apicid_init array is then expendable and the
+ * x86_cpu_to_apicid_ptr is zeroed indicating that the static array is no
+ * longer available.
+ */
+void __init smp_set_apicids(void)
+{
+ int cpu;
+
+ for_each_cpu_mask(cpu, cpu_possible_map) {
+ if (per_cpu_offset(cpu))
+ per_cpu(x86_cpu_to_apicid, cpu) =
+ x86_cpu_to_apicid_init[cpu];
+ }
+
+ /* indicate the static array will be going away soon */
+ x86_cpu_to_apicid_ptr = NULL;
+}
+
+/*
* Prepare for SMP bootup. The MP table or ACPI has been read
* earlier. Just do some sanity checking here and enable APIC mode.
*/
@@ -850,6 +870,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
nmi_watchdog_default();
current_cpu_data = boot_cpu_data;
current_thread_info()->cpu = 0; /* needed? */
+ smp_set_apicids();
set_cpu_sibling_map(0);
if (smp_sanity_check(max_cpus) < 0) {
@@ -969,23 +990,23 @@ void __init smp_cpus_done(unsigned int max_cpus)
static void remove_siblinginfo(int cpu)
{
int sibling;
- struct cpuinfo_x86 *c = cpu_data;
+ struct cpuinfo_x86 *c = &cpu_data(cpu);
- for_each_cpu_mask(sibling, cpu_core_map[cpu]) {
- cpu_clear(cpu, cpu_core_map[sibling]);
+ for_each_cpu_mask(sibling, per_cpu(cpu_core_map, cpu)) {
+ cpu_clear(cpu, per_cpu(cpu_core_map, sibling));
/*
* last thread sibling in this cpu core going down
*/
- if (cpus_weight(cpu_sibling_map[cpu]) == 1)
- c[sibling].booted_cores--;
+ if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1)
+ cpu_data(sibling).booted_cores--;
}
- for_each_cpu_mask(sibling, cpu_sibling_map[cpu])
- cpu_clear(cpu, cpu_sibling_map[sibling]);
- cpus_clear(cpu_sibling_map[cpu]);
- cpus_clear(cpu_core_map[cpu]);
- c[cpu].phys_proc_id = 0;
- c[cpu].cpu_core_id = 0;
+ for_each_cpu_mask(sibling, per_cpu(cpu_sibling_map, cpu))
+ cpu_clear(cpu, per_cpu(cpu_sibling_map, sibling));
+ cpus_clear(per_cpu(cpu_sibling_map, cpu));
+ cpus_clear(per_cpu(cpu_core_map, cpu));
+ c->phys_proc_id = 0;
+ c->cpu_core_id = 0;
cpu_clear(cpu, cpu_sibling_setup_map);
}
diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c
index 413e527cdeb9..6fa6cf036c70 100644
--- a/arch/x86/kernel/stacktrace.c
+++ b/arch/x86/kernel/stacktrace.c
@@ -33,7 +33,7 @@ static void save_stack_address(void *data, unsigned long addr)
trace->entries[trace->nr_entries++] = addr;
}
-static struct stacktrace_ops save_stack_ops = {
+static const struct stacktrace_ops save_stack_ops = {
.warning = save_stack_warning,
.warning_symbol = save_stack_warning_symbol,
.stack = save_stack_stack,
diff --git a/arch/x86/kernel/summit_32.c b/arch/x86/kernel/summit_32.c
index 91c7acc8d999..72f463401592 100644
--- a/arch/x86/kernel/summit_32.c
+++ b/arch/x86/kernel/summit_32.c
@@ -64,7 +64,7 @@ static int __init setup_pci_node_map_for_wpeg(int wpeg_num, int last_bus)
switch (rio_devs[wpeg_num]->type){
case CompatWPEG:
- /* The Compatability Winnipeg controls the 2 legacy buses,
+ /* The Compatibility Winnipeg controls the 2 legacy buses,
* the 66MHz PCI bus [2 slots] and the 2 "extra" buses in case
* a PCI-PCI bridge card is used in either slot: total 5 buses.
*/
diff --git a/arch/x86/kernel/suspend_64.c b/arch/x86/kernel/suspend_64.c
index 573c0a6e0ac6..db284ef44d53 100644
--- a/arch/x86/kernel/suspend_64.c
+++ b/arch/x86/kernel/suspend_64.c
@@ -19,12 +19,6 @@ extern const void __nosave_begin, __nosave_end;
struct saved_context saved_context;
-unsigned long saved_context_eax, saved_context_ebx, saved_context_ecx, saved_context_edx;
-unsigned long saved_context_esp, saved_context_ebp, saved_context_esi, saved_context_edi;
-unsigned long saved_context_r08, saved_context_r09, saved_context_r10, saved_context_r11;
-unsigned long saved_context_r12, saved_context_r13, saved_context_r14, saved_context_r15;
-unsigned long saved_context_eflags;
-
void __save_processor_state(struct saved_context *ctxt)
{
kernel_fpu_begin();
@@ -32,9 +26,9 @@ void __save_processor_state(struct saved_context *ctxt)
/*
* descriptor tables
*/
- asm volatile ("sgdt %0" : "=m" (ctxt->gdt_limit));
- asm volatile ("sidt %0" : "=m" (ctxt->idt_limit));
- asm volatile ("str %0" : "=m" (ctxt->tr));
+ store_gdt((struct desc_ptr *)&ctxt->gdt_limit);
+ store_idt((struct desc_ptr *)&ctxt->idt_limit);
+ store_tr(ctxt->tr);
/* XMM0..XMM15 should be handled by kernel_fpu_begin(). */
/*
@@ -91,8 +85,9 @@ void __restore_processor_state(struct saved_context *ctxt)
* now restore the descriptor tables to their proper values
* ltr is done i fix_processor_context().
*/
- asm volatile ("lgdt %0" :: "m" (ctxt->gdt_limit));
- asm volatile ("lidt %0" :: "m" (ctxt->idt_limit));
+ load_gdt((const struct desc_ptr *)&ctxt->gdt_limit);
+ load_idt((const struct desc_ptr *)&ctxt->idt_limit);
+
/*
* segment registers
@@ -123,7 +118,7 @@ void fix_processor_context(void)
int cpu = smp_processor_id();
struct tss_struct *t = &per_cpu(init_tss, cpu);
- set_tss_desc(cpu,t); /* This just modifies memory; should not be neccessary. But... This is neccessary, because 386 hardware has concept of busy TSS or some similar stupidity. */
+ set_tss_desc(cpu,t); /* This just modifies memory; should not be necessary. But... This is necessary, because 386 hardware has concept of busy TSS or some similar stupidity. */
cpu_gdt(cpu)[GDT_ENTRY_TSS].type = 9;
@@ -150,8 +145,22 @@ void fix_processor_context(void)
/* Defined in arch/x86_64/kernel/suspend_asm.S */
extern int restore_image(void);
+/*
+ * Address to jump to in the last phase of restore in order to get to the image
+ * kernel's text (this value is passed in the image header).
+ */
+unsigned long restore_jump_address;
+
+/*
+ * Value of the cr3 register from before the hibernation (this value is passed
+ * in the image header).
+ */
+unsigned long restore_cr3;
+
pgd_t *temp_level4_pgt;
+void *relocated_restore_code;
+
static int res_phys_pud_init(pud_t *pud, unsigned long address, unsigned long end)
{
long i, j;
@@ -175,7 +184,7 @@ static int res_phys_pud_init(pud_t *pud, unsigned long address, unsigned long en
if (paddr >= end)
break;
- pe = _PAGE_NX | _PAGE_PSE | _KERNPG_TABLE | paddr;
+ pe = __PAGE_KERNEL_LARGE_EXEC | paddr;
pe &= __supported_pte_mask;
set_pmd(pmd, __pmd(pe));
}
@@ -183,25 +192,42 @@ static int res_phys_pud_init(pud_t *pud, unsigned long address, unsigned long en
return 0;
}
+static int res_kernel_text_pud_init(pud_t *pud, unsigned long start)
+{
+ pmd_t *pmd;
+ unsigned long paddr;
+
+ pmd = (pmd_t *)get_safe_page(GFP_ATOMIC);
+ if (!pmd)
+ return -ENOMEM;
+ set_pud(pud + pud_index(start), __pud(__pa(pmd) | _KERNPG_TABLE));
+ for (paddr = 0; paddr < KERNEL_TEXT_SIZE; pmd++, paddr += PMD_SIZE) {
+ unsigned long pe;
+
+ pe = __PAGE_KERNEL_LARGE_EXEC | _PAGE_GLOBAL | paddr;
+ pe &= __supported_pte_mask;
+ set_pmd(pmd, __pmd(pe));
+ }
+
+ return 0;
+}
+
static int set_up_temporary_mappings(void)
{
unsigned long start, end, next;
+ pud_t *pud;
int error;
temp_level4_pgt = (pgd_t *)get_safe_page(GFP_ATOMIC);
if (!temp_level4_pgt)
return -ENOMEM;
- /* It is safe to reuse the original kernel mapping */
- set_pgd(temp_level4_pgt + pgd_index(__START_KERNEL_map),
- init_level4_pgt[pgd_index(__START_KERNEL_map)]);
-
/* Set up the direct mapping from scratch */
start = (unsigned long)pfn_to_kaddr(0);
end = (unsigned long)pfn_to_kaddr(end_pfn);
for (; start < end; start = next) {
- pud_t *pud = (pud_t *)get_safe_page(GFP_ATOMIC);
+ pud = (pud_t *)get_safe_page(GFP_ATOMIC);
if (!pud)
return -ENOMEM;
next = start + PGDIR_SIZE;
@@ -212,7 +238,17 @@ static int set_up_temporary_mappings(void)
set_pgd(temp_level4_pgt + pgd_index(start),
mk_kernel_pgd(__pa(pud)));
}
- return 0;
+
+ /* Set up the kernel text mapping from scratch */
+ pud = (pud_t *)get_safe_page(GFP_ATOMIC);
+ if (!pud)
+ return -ENOMEM;
+ error = res_kernel_text_pud_init(pud, __START_KERNEL_map);
+ if (!error)
+ set_pgd(temp_level4_pgt + pgd_index(__START_KERNEL_map),
+ __pgd(__pa(pud) | _PAGE_TABLE));
+
+ return error;
}
int swsusp_arch_resume(void)
@@ -222,6 +258,13 @@ int swsusp_arch_resume(void)
/* We have got enough memory and from now on we cannot recover */
if ((error = set_up_temporary_mappings()))
return error;
+
+ relocated_restore_code = (void *)get_safe_page(GFP_ATOMIC);
+ if (!relocated_restore_code)
+ return -ENOMEM;
+ memcpy(relocated_restore_code, &core_restore_code,
+ &restore_registers - &core_restore_code);
+
restore_image();
return 0;
}
@@ -236,4 +279,43 @@ int pfn_is_nosave(unsigned long pfn)
unsigned long nosave_end_pfn = PAGE_ALIGN(__pa_symbol(&__nosave_end)) >> PAGE_SHIFT;
return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn);
}
+
+struct restore_data_record {
+ unsigned long jump_address;
+ unsigned long cr3;
+ unsigned long magic;
+};
+
+#define RESTORE_MAGIC 0x0123456789ABCDEFUL
+
+/**
+ * arch_hibernation_header_save - populate the architecture specific part
+ * of a hibernation image header
+ * @addr: address to save the data at
+ */
+int arch_hibernation_header_save(void *addr, unsigned int max_size)
+{
+ struct restore_data_record *rdr = addr;
+
+ if (max_size < sizeof(struct restore_data_record))
+ return -EOVERFLOW;
+ rdr->jump_address = restore_jump_address;
+ rdr->cr3 = restore_cr3;
+ rdr->magic = RESTORE_MAGIC;
+ return 0;
+}
+
+/**
+ * arch_hibernation_header_restore - read the architecture specific data
+ * from the hibernation image header
+ * @addr: address to read the data from
+ */
+int arch_hibernation_header_restore(void *addr)
+{
+ struct restore_data_record *rdr = addr;
+
+ restore_jump_address = rdr->jump_address;
+ restore_cr3 = rdr->cr3;
+ return (rdr->magic == RESTORE_MAGIC) ? 0 : -EINVAL;
+}
#endif /* CONFIG_HIBERNATION */
diff --git a/arch/x86/kernel/suspend_asm_64.S b/arch/x86/kernel/suspend_asm_64.S
index 16d183f67bc1..72f952103e50 100644
--- a/arch/x86/kernel/suspend_asm_64.S
+++ b/arch/x86/kernel/suspend_asm_64.S
@@ -2,8 +2,8 @@
*
* Distribute under GPLv2.
*
- * swsusp_arch_resume may not use any stack, nor any variable that is
- * not "NoSave" during copying pages:
+ * swsusp_arch_resume must not use any stack or any nonlocal variables while
+ * copying pages:
*
* Its rewriting one kernel image with another. What is stack in "old"
* image could very well be data page in "new" image, and overwriting
@@ -17,24 +17,31 @@
#include <asm/asm-offsets.h>
ENTRY(swsusp_arch_suspend)
+ movq $saved_context, %rax
+ movq %rsp, pt_regs_rsp(%rax)
+ movq %rbp, pt_regs_rbp(%rax)
+ movq %rsi, pt_regs_rsi(%rax)
+ movq %rdi, pt_regs_rdi(%rax)
+ movq %rbx, pt_regs_rbx(%rax)
+ movq %rcx, pt_regs_rcx(%rax)
+ movq %rdx, pt_regs_rdx(%rax)
+ movq %r8, pt_regs_r8(%rax)
+ movq %r9, pt_regs_r9(%rax)
+ movq %r10, pt_regs_r10(%rax)
+ movq %r11, pt_regs_r11(%rax)
+ movq %r12, pt_regs_r12(%rax)
+ movq %r13, pt_regs_r13(%rax)
+ movq %r14, pt_regs_r14(%rax)
+ movq %r15, pt_regs_r15(%rax)
+ pushfq
+ popq pt_regs_eflags(%rax)
- movq %rsp, saved_context_esp(%rip)
- movq %rax, saved_context_eax(%rip)
- movq %rbx, saved_context_ebx(%rip)
- movq %rcx, saved_context_ecx(%rip)
- movq %rdx, saved_context_edx(%rip)
- movq %rbp, saved_context_ebp(%rip)
- movq %rsi, saved_context_esi(%rip)
- movq %rdi, saved_context_edi(%rip)
- movq %r8, saved_context_r08(%rip)
- movq %r9, saved_context_r09(%rip)
- movq %r10, saved_context_r10(%rip)
- movq %r11, saved_context_r11(%rip)
- movq %r12, saved_context_r12(%rip)
- movq %r13, saved_context_r13(%rip)
- movq %r14, saved_context_r14(%rip)
- movq %r15, saved_context_r15(%rip)
- pushfq ; popq saved_context_eflags(%rip)
+ /* save the address of restore_registers */
+ movq $restore_registers, %rax
+ movq %rax, restore_jump_address(%rip)
+ /* save cr3 */
+ movq %cr3, %rax
+ movq %rax, restore_cr3(%rip)
call swsusp_save
ret
@@ -54,7 +61,17 @@ ENTRY(restore_image)
movq %rcx, %cr3;
movq %rax, %cr4; # turn PGE back on
+ /* prepare to jump to the image kernel */
+ movq restore_jump_address(%rip), %rax
+ movq restore_cr3(%rip), %rbx
+
+ /* prepare to copy image data to their original locations */
movq restore_pblist(%rip), %rdx
+ movq relocated_restore_code(%rip), %rcx
+ jmpq *%rcx
+
+ /* code below has been relocated to a safe page */
+ENTRY(core_restore_code)
loop:
testq %rdx, %rdx
jz done
@@ -62,7 +79,7 @@ loop:
/* get addresses from the pbe and copy the page */
movq pbe_address(%rdx), %rsi
movq pbe_orig_address(%rdx), %rdi
- movq $512, %rcx
+ movq $(PAGE_SIZE >> 3), %rcx
rep
movsq
@@ -70,10 +87,22 @@ loop:
movq pbe_next(%rdx), %rdx
jmp loop
done:
+ /* jump to the restore_registers address from the image header */
+ jmpq *%rax
+ /*
+ * NOTE: This assumes that the boot kernel's text mapping covers the
+ * image kernel's page containing restore_registers and the address of
+ * this page is the same as in the image kernel's text mapping (it
+ * should always be true, because the text mapping is linear, starting
+ * from 0, and is supposed to cover the entire kernel text for every
+ * kernel).
+ *
+ * code below belongs to the image kernel
+ */
+
+ENTRY(restore_registers)
/* go back to the original page tables */
- movq $(init_level4_pgt - __START_KERNEL_map), %rax
- addq phys_base(%rip), %rax
- movq %rax, %cr3
+ movq %rbx, %cr3
/* Flush TLB, including "global" things (vmalloc) */
movq mmu_cr4_features(%rip), %rax
@@ -84,27 +113,29 @@ done:
movq %rcx, %cr3
movq %rax, %cr4; # turn PGE back on
- movl $24, %eax
- movl %eax, %ds
-
- movq saved_context_esp(%rip), %rsp
- movq saved_context_ebp(%rip), %rbp
- /* Don't restore %rax, it must be 0 anyway */
- movq saved_context_ebx(%rip), %rbx
- movq saved_context_ecx(%rip), %rcx
- movq saved_context_edx(%rip), %rdx
- movq saved_context_esi(%rip), %rsi
- movq saved_context_edi(%rip), %rdi
- movq saved_context_r08(%rip), %r8
- movq saved_context_r09(%rip), %r9
- movq saved_context_r10(%rip), %r10
- movq saved_context_r11(%rip), %r11
- movq saved_context_r12(%rip), %r12
- movq saved_context_r13(%rip), %r13
- movq saved_context_r14(%rip), %r14
- movq saved_context_r15(%rip), %r15
- pushq saved_context_eflags(%rip) ; popfq
+ /* We don't restore %rax, it must be 0 anyway */
+ movq $saved_context, %rax
+ movq pt_regs_rsp(%rax), %rsp
+ movq pt_regs_rbp(%rax), %rbp
+ movq pt_regs_rsi(%rax), %rsi
+ movq pt_regs_rdi(%rax), %rdi
+ movq pt_regs_rbx(%rax), %rbx
+ movq pt_regs_rcx(%rax), %rcx
+ movq pt_regs_rdx(%rax), %rdx
+ movq pt_regs_r8(%rax), %r8
+ movq pt_regs_r9(%rax), %r9
+ movq pt_regs_r10(%rax), %r10
+ movq pt_regs_r11(%rax), %r11
+ movq pt_regs_r12(%rax), %r12
+ movq pt_regs_r13(%rax), %r13
+ movq pt_regs_r14(%rax), %r14
+ movq pt_regs_r15(%rax), %r15
+ pushq pt_regs_eflags(%rax)
+ popfq
xorq %rax, %rax
+ /* tell the hibernation core that we've just restored the memory */
+ movq %rax, in_suspend(%rip)
+
ret
diff --git a/arch/x86/kernel/sys_i386_32.c b/arch/x86/kernel/sys_i386_32.c
index f8bae9ba0324..a86d26f036e1 100644
--- a/arch/x86/kernel/sys_i386_32.c
+++ b/arch/x86/kernel/sys_i386_32.c
@@ -17,10 +17,10 @@
#include <linux/mman.h>
#include <linux/file.h>
#include <linux/utsname.h>
+#include <linux/ipc.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
-#include <asm/ipc.h>
/*
* sys_pipe() is the normal C calling standard for creating
diff --git a/arch/x86/kernel/tce_64.c b/arch/x86/kernel/tce_64.c
index e3f2569b2c44..9e540fee7009 100644
--- a/arch/x86/kernel/tce_64.c
+++ b/arch/x86/kernel/tce_64.c
@@ -40,9 +40,9 @@ static inline void flush_tce(void* tceaddr)
{
/* a single tce can't cross a cache line */
if (cpu_has_clflush)
- asm volatile("clflush (%0)" :: "r" (tceaddr));
+ clflush(tceaddr);
else
- asm volatile("wbinvd":::"memory");
+ wbinvd();
}
void tce_build(struct iommu_table *tbl, unsigned long index,
diff --git a/arch/x86/kernel/topology.c b/arch/x86/kernel/topology.c
index c25f23eb397c..8caa0b777466 100644
--- a/arch/x86/kernel/topology.c
+++ b/arch/x86/kernel/topology.c
@@ -44,15 +44,15 @@ int arch_register_cpu(int num)
* Also certain PCI quirks require not to enable hotplug control
* for all CPU's.
*/
- if (num && enable_cpu_hotplug)
+#ifdef CONFIG_HOTPLUG_CPU
+ if (num)
cpu_devices[num].cpu.hotpluggable = 1;
+#endif
return register_cpu(&cpu_devices[num].cpu, num);
}
#ifdef CONFIG_HOTPLUG_CPU
-int enable_cpu_hotplug = 1;
-
void arch_unregister_cpu(int num) {
return unregister_cpu(&cpu_devices[num].cpu);
}
diff --git a/arch/x86/kernel/trampoline_32.S b/arch/x86/kernel/trampoline_32.S
index f62815f8d06a..9bcc1c6aca3d 100644
--- a/arch/x86/kernel/trampoline_32.S
+++ b/arch/x86/kernel/trampoline_32.S
@@ -36,11 +36,11 @@
#include <asm/segment.h>
#include <asm/page.h>
-.data
-
/* We can free up trampoline after bootup if cpu hotplug is not supported. */
#ifndef CONFIG_HOTPLUG_CPU
.section ".init.data","aw",@progbits
+#else
+.section .rodata,"a",@progbits
#endif
.code16
diff --git a/arch/x86/kernel/trampoline_64.S b/arch/x86/kernel/trampoline_64.S
index 607983b0d27b..e30b67c6a9f5 100644
--- a/arch/x86/kernel/trampoline_64.S
+++ b/arch/x86/kernel/trampoline_64.S
@@ -33,7 +33,12 @@
#include <asm/msr.h>
#include <asm/segment.h>
-.data
+/* We can free up trampoline after bootup if cpu hotplug is not supported. */
+#ifndef CONFIG_HOTPLUG_CPU
+.section .init.data, "aw", @progbits
+#else
+.section .rodata, "a", @progbits
+#endif
.code16
diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c
index 05c27ecaf2a7..298d13ed3ab3 100644
--- a/arch/x86/kernel/traps_32.c
+++ b/arch/x86/kernel/traps_32.c
@@ -63,6 +63,9 @@
int panic_on_unrecovered_nmi;
+DECLARE_BITMAP(used_vectors, NR_VECTORS);
+EXPORT_SYMBOL_GPL(used_vectors);
+
asmlinkage int system_call(void);
/* Do we ignore FPU interrupts ? */
@@ -112,7 +115,7 @@ struct stack_frame {
static inline unsigned long print_context_stack(struct thread_info *tinfo,
unsigned long *stack, unsigned long ebp,
- struct stacktrace_ops *ops, void *data)
+ const struct stacktrace_ops *ops, void *data)
{
#ifdef CONFIG_FRAME_POINTER
struct stack_frame *frame = (struct stack_frame *)ebp;
@@ -149,7 +152,7 @@ static inline unsigned long print_context_stack(struct thread_info *tinfo,
void dump_trace(struct task_struct *task, struct pt_regs *regs,
unsigned long *stack,
- struct stacktrace_ops *ops, void *data)
+ const struct stacktrace_ops *ops, void *data)
{
unsigned long ebp = 0;
@@ -221,7 +224,7 @@ static void print_trace_address(void *data, unsigned long addr)
touch_nmi_watchdog();
}
-static struct stacktrace_ops print_trace_ops = {
+static const struct stacktrace_ops print_trace_ops = {
.warning = print_trace_warning,
.warning_symbol = print_trace_warning_symbol,
.stack = print_trace_stack,
@@ -288,48 +291,24 @@ EXPORT_SYMBOL(dump_stack);
void show_registers(struct pt_regs *regs)
{
int i;
- int in_kernel = 1;
- unsigned long esp;
- unsigned short ss, gs;
-
- esp = (unsigned long) (&regs->esp);
- savesegment(ss, ss);
- savesegment(gs, gs);
- if (user_mode_vm(regs)) {
- in_kernel = 0;
- esp = regs->esp;
- ss = regs->xss & 0xffff;
- }
+
print_modules();
- printk(KERN_EMERG "CPU: %d\n"
- KERN_EMERG "EIP: %04x:[<%08lx>] %s VLI\n"
- KERN_EMERG "EFLAGS: %08lx (%s %.*s)\n",
- smp_processor_id(), 0xffff & regs->xcs, regs->eip,
- print_tainted(), regs->eflags, init_utsname()->release,
- (int)strcspn(init_utsname()->version, " "),
- init_utsname()->version);
- print_symbol(KERN_EMERG "EIP is at %s\n", regs->eip);
- printk(KERN_EMERG "eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n",
- regs->eax, regs->ebx, regs->ecx, regs->edx);
- printk(KERN_EMERG "esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n",
- regs->esi, regs->edi, regs->ebp, esp);
- printk(KERN_EMERG "ds: %04x es: %04x fs: %04x gs: %04x ss: %04x\n",
- regs->xds & 0xffff, regs->xes & 0xffff, regs->xfs & 0xffff, gs, ss);
+ __show_registers(regs, 0);
printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)",
- TASK_COMM_LEN, current->comm, current->pid,
+ TASK_COMM_LEN, current->comm, task_pid_nr(current),
current_thread_info(), current, task_thread_info(current));
/*
* When in-kernel, we also print out the stack and code at the
* time of the fault..
*/
- if (in_kernel) {
+ if (!user_mode_vm(regs)) {
u8 *eip;
unsigned int code_prologue = code_bytes * 43 / 64;
unsigned int code_len = code_bytes;
unsigned char c;
printk("\n" KERN_EMERG "Stack: ");
- show_stack_log_lvl(NULL, regs, (unsigned long *)esp, KERN_EMERG);
+ show_stack_log_lvl(NULL, regs, &regs->esp, KERN_EMERG);
printk(KERN_EMERG "Code: ");
@@ -374,11 +353,11 @@ int is_valid_bugaddr(unsigned long eip)
void die(const char * str, struct pt_regs * regs, long err)
{
static struct {
- spinlock_t lock;
+ raw_spinlock_t lock;
u32 lock_owner;
int lock_owner_depth;
} die = {
- .lock = __SPIN_LOCK_UNLOCKED(die.lock),
+ .lock = __RAW_SPIN_LOCK_UNLOCKED,
.lock_owner = -1,
.lock_owner_depth = 0
};
@@ -389,40 +368,34 @@ void die(const char * str, struct pt_regs * regs, long err)
if (die.lock_owner != raw_smp_processor_id()) {
console_verbose();
- spin_lock_irqsave(&die.lock, flags);
+ __raw_spin_lock(&die.lock);
+ raw_local_save_flags(flags);
die.lock_owner = smp_processor_id();
die.lock_owner_depth = 0;
bust_spinlocks(1);
}
else
- local_save_flags(flags);
+ raw_local_save_flags(flags);
if (++die.lock_owner_depth < 3) {
- int nl = 0;
unsigned long esp;
unsigned short ss;
report_bug(regs->eip, regs);
- printk(KERN_EMERG "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
+ printk(KERN_EMERG "%s: %04lx [#%d] ", str, err & 0xffff,
+ ++die_counter);
#ifdef CONFIG_PREEMPT
- printk(KERN_EMERG "PREEMPT ");
- nl = 1;
+ printk("PREEMPT ");
#endif
#ifdef CONFIG_SMP
- if (!nl)
- printk(KERN_EMERG);
printk("SMP ");
- nl = 1;
#endif
#ifdef CONFIG_DEBUG_PAGEALLOC
- if (!nl)
- printk(KERN_EMERG);
printk("DEBUG_PAGEALLOC");
- nl = 1;
#endif
- if (nl)
- printk("\n");
+ printk("\n");
+
if (notify_die(DIE_OOPS, str, regs, err,
current->thread.trap_no, SIGSEGV) !=
NOTIFY_STOP) {
@@ -446,7 +419,8 @@ void die(const char * str, struct pt_regs * regs, long err)
bust_spinlocks(0);
die.lock_owner = -1;
add_taint(TAINT_DIE);
- spin_unlock_irqrestore(&die.lock, flags);
+ __raw_spin_unlock(&die.lock);
+ raw_local_irq_restore(flags);
if (!regs)
return;
@@ -629,7 +603,7 @@ fastcall void __kprobes do_general_protection(struct pt_regs * regs,
printk_ratelimit())
printk(KERN_INFO
"%s[%d] general protection eip:%lx esp:%lx error:%lx\n",
- current->comm, current->pid,
+ current->comm, task_pid_nr(current),
regs->eip, regs->esp, error_code);
force_sig(SIGSEGV, current);
@@ -815,6 +789,8 @@ void restart_nmi(void)
#ifdef CONFIG_KPROBES
fastcall void __kprobes do_int3(struct pt_regs *regs, long error_code)
{
+ trace_hardirqs_fixup();
+
if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
== NOTIFY_STOP)
return;
@@ -1112,20 +1088,6 @@ asmlinkage void math_emulate(long arg)
#endif /* CONFIG_MATH_EMULATION */
-#ifdef CONFIG_X86_F00F_BUG
-void __init trap_init_f00f_bug(void)
-{
- __set_fixmap(FIX_F00F_IDT, __pa(&idt_table), PAGE_KERNEL_RO);
-
- /*
- * Update the IDT descriptor and reload the IDT so that
- * it uses the read-only mapped virtual address.
- */
- idt_descr.address = fix_to_virt(FIX_F00F_IDT);
- load_idt(&idt_descr);
-}
-#endif
-
/*
* This needs to use 'idt_table' rather than 'idt', and
* thus use the _nonmapped_ version of the IDT, as the
@@ -1163,6 +1125,8 @@ static void __init set_task_gate(unsigned int n, unsigned int gdt_entry)
void __init trap_init(void)
{
+ int i;
+
#ifdef CONFIG_EISA
void __iomem *p = ioremap(0x0FFFD9, 4);
if (readl(p) == 'E'+('I'<<8)+('S'<<16)+('A'<<24)) {
@@ -1222,6 +1186,11 @@ void __init trap_init(void)
set_system_gate(SYSCALL_VECTOR,&system_call);
+ /* Reserve all the builtin and the syscall vector. */
+ for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++)
+ set_bit(i, used_vectors);
+ set_bit(SYSCALL_VECTOR, used_vectors);
+
/*
* Should be a barrier for any external CPU state.
*/
diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c
index bc7116acf8ff..4a6bd4965f56 100644
--- a/arch/x86/kernel/traps_64.c
+++ b/arch/x86/kernel/traps_64.c
@@ -201,7 +201,7 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
#define MSG(txt) ops->warning(data, txt)
/*
- * x86-64 can have upto three kernel stacks:
+ * x86-64 can have up to three kernel stacks:
* process stack
* interrupt stack
* severe exception (double fault, nmi, stack fault, debug, mce) hardware stack
@@ -215,7 +215,7 @@ static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
void dump_trace(struct task_struct *tsk, struct pt_regs *regs,
unsigned long *stack,
- struct stacktrace_ops *ops, void *data)
+ const struct stacktrace_ops *ops, void *data)
{
const unsigned cpu = get_cpu();
unsigned long *irqstack_end = (unsigned long*)cpu_pda(cpu)->irqstackptr;
@@ -336,7 +336,7 @@ static void print_trace_address(void *data, unsigned long addr)
printk_address(addr);
}
-static struct stacktrace_ops print_trace_ops = {
+static const struct stacktrace_ops print_trace_ops = {
.warning = print_trace_warning,
.warning_symbol = print_trace_warning_symbol,
.stack = print_trace_stack,
@@ -462,7 +462,7 @@ void out_of_line_bug(void)
EXPORT_SYMBOL(out_of_line_bug);
#endif
-static DEFINE_SPINLOCK(die_lock);
+static raw_spinlock_t die_lock = __RAW_SPIN_LOCK_UNLOCKED;
static int die_owner = -1;
static unsigned int die_nest_count;
@@ -474,13 +474,13 @@ unsigned __kprobes long oops_begin(void)
oops_enter();
/* racy, but better than risking deadlock. */
- local_irq_save(flags);
+ raw_local_irq_save(flags);
cpu = smp_processor_id();
- if (!spin_trylock(&die_lock)) {
+ if (!__raw_spin_trylock(&die_lock)) {
if (cpu == die_owner)
/* nested oops. should stop eventually */;
else
- spin_lock(&die_lock);
+ __raw_spin_lock(&die_lock);
}
die_nest_count++;
die_owner = cpu;
@@ -494,12 +494,10 @@ void __kprobes oops_end(unsigned long flags)
die_owner = -1;
bust_spinlocks(0);
die_nest_count--;
- if (die_nest_count)
- /* We still own the lock */
- local_irq_restore(flags);
- else
+ if (!die_nest_count)
/* Nest count reaches zero, release the lock. */
- spin_unlock_irqrestore(&die_lock, flags);
+ __raw_spin_unlock(&die_lock);
+ raw_local_irq_restore(flags);
if (panic_on_oops)
panic("Fatal exception");
oops_exit();
@@ -809,6 +807,8 @@ asmlinkage __kprobes void default_do_nmi(struct pt_regs *regs)
/* runs on IST stack. */
asmlinkage void __kprobes do_int3(struct pt_regs * regs, long error_code)
{
+ trace_hardirqs_fixup();
+
if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) == NOTIFY_STOP) {
return;
}
diff --git a/arch/x86/kernel/tsc_32.c b/arch/x86/kernel/tsc_32.c
index b85ad754f70e..9ebc0dab66b4 100644
--- a/arch/x86/kernel/tsc_32.c
+++ b/arch/x86/kernel/tsc_32.c
@@ -59,7 +59,7 @@ int check_tsc_unstable(void)
}
EXPORT_SYMBOL_GPL(check_tsc_unstable);
-/* Accellerators for sched_clock()
+/* Accelerators for sched_clock()
* convert from cycles(64bits) => nanoseconds (64bits)
* basic equation:
* ns = cycles / (freq / ns_per_sec)
@@ -74,7 +74,7 @@ EXPORT_SYMBOL_GPL(check_tsc_unstable);
* And since SC is a constant power of two, we can convert the div
* into a shift.
*
- * We can use khz divisor instead of mhz to keep a better percision, since
+ * We can use khz divisor instead of mhz to keep a better precision, since
* cyc2ns_scale is limited to 10^6 * 2^10, which fits in 32 bits.
* (mathieu.desnoyers@polymtl.ca)
*
@@ -131,38 +131,43 @@ unsigned long native_calculate_cpu_khz(void)
{
unsigned long long start, end;
unsigned long count;
- u64 delta64;
+ u64 delta64 = (u64)ULLONG_MAX;
int i;
unsigned long flags;
local_irq_save(flags);
- /* run 3 times to ensure the cache is warm */
+ /* run 3 times to ensure the cache is warm and to get an accurate reading */
for (i = 0; i < 3; i++) {
mach_prepare_counter();
rdtscll(start);
mach_countup(&count);
rdtscll(end);
- }
- /*
- * Error: ECTCNEVERSET
- * The CTC wasn't reliable: we got a hit on the very first read,
- * or the CPU was so fast/slow that the quotient wouldn't fit in
- * 32 bits..
- */
- if (count <= 1)
- goto err;
- delta64 = end - start;
+ /*
+ * Error: ECTCNEVERSET
+ * The CTC wasn't reliable: we got a hit on the very first read,
+ * or the CPU was so fast/slow that the quotient wouldn't fit in
+ * 32 bits..
+ */
+ if (count <= 1)
+ continue;
+
+ /* cpu freq too slow: */
+ if ((end - start) <= CALIBRATE_TIME_MSEC)
+ continue;
+
+ /*
+ * We want the minimum time of all runs in case one of them
+ * is inaccurate due to SMI or other delay
+ */
+ delta64 = min(delta64, (end - start));
+ }
- /* cpu freq too fast: */
+ /* cpu freq too fast (or every run was bad): */
if (delta64 > (1ULL<<32))
goto err;
- /* cpu freq too slow: */
- if (delta64 <= CALIBRATE_TIME_MSEC)
- goto err;
-
delta64 += CALIBRATE_TIME_MSEC/2; /* round for do_div */
do_div(delta64,CALIBRATE_TIME_MSEC);
@@ -181,8 +186,8 @@ int recalibrate_cpu_khz(void)
if (cpu_has_tsc) {
cpu_khz = calculate_cpu_khz();
tsc_khz = cpu_khz;
- cpu_data[0].loops_per_jiffy =
- cpufreq_scale(cpu_data[0].loops_per_jiffy,
+ cpu_data(0).loops_per_jiffy =
+ cpufreq_scale(cpu_data(0).loops_per_jiffy,
cpu_khz_old, cpu_khz);
return 0;
} else
@@ -215,7 +220,7 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data)
return 0;
}
ref_freq = freq->old;
- loops_per_jiffy_ref = cpu_data[freq->cpu].loops_per_jiffy;
+ loops_per_jiffy_ref = cpu_data(freq->cpu).loops_per_jiffy;
cpu_khz_ref = cpu_khz;
}
@@ -223,7 +228,7 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data)
(val == CPUFREQ_POSTCHANGE && freq->old > freq->new) ||
(val == CPUFREQ_RESUMECHANGE)) {
if (!(freq->flags & CPUFREQ_CONST_LOOPS))
- cpu_data[freq->cpu].loops_per_jiffy =
+ cpu_data(freq->cpu).loops_per_jiffy =
cpufreq_scale(loops_per_jiffy_ref,
ref_freq, freq->new);
@@ -349,10 +354,10 @@ __cpuinit int unsynchronized_tsc(void)
static void __init check_geode_tsc_reliable(void)
{
- unsigned long val;
+ unsigned long res_low, res_high;
- rdmsrl(MSR_GEODE_BUSCONT_CONF0, val);
- if ((val & RTSC_SUSP))
+ rdmsr_safe(MSR_GEODE_BUSCONT_CONF0, &res_low, &res_high);
+ if (res_low & RTSC_SUSP)
clocksource_tsc.flags &= ~CLOCK_SOURCE_MUST_VERIFY;
}
#else
diff --git a/arch/x86/kernel/tsc_64.c b/arch/x86/kernel/tsc_64.c
index 9f22e542c374..9c70af45b42b 100644
--- a/arch/x86/kernel/tsc_64.c
+++ b/arch/x86/kernel/tsc_64.c
@@ -73,13 +73,13 @@ static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
struct cpufreq_freqs *freq = data;
unsigned long *lpj, dummy;
- if (cpu_has(&cpu_data[freq->cpu], X86_FEATURE_CONSTANT_TSC))
+ if (cpu_has(&cpu_data(freq->cpu), X86_FEATURE_CONSTANT_TSC))
return 0;
lpj = &dummy;
if (!(freq->flags & CPUFREQ_CONST_LOOPS))
#ifdef CONFIG_SMP
- lpj = &cpu_data[freq->cpu].loops_per_jiffy;
+ lpj = &cpu_data(freq->cpu).loops_per_jiffy;
#else
lpj = &boot_cpu_data.loops_per_jiffy;
#endif
diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c
index 18673e0f193b..f02bad68abaa 100644
--- a/arch/x86/kernel/vmi_32.c
+++ b/arch/x86/kernel/vmi_32.c
@@ -134,21 +134,21 @@ static unsigned vmi_patch(u8 type, u16 clobbers, void *insns,
unsigned long eip, unsigned len)
{
switch (type) {
- case PARAVIRT_PATCH(irq_disable):
+ case PARAVIRT_PATCH(pv_irq_ops.irq_disable):
return patch_internal(VMI_CALL_DisableInterrupts, len,
insns, eip);
- case PARAVIRT_PATCH(irq_enable):
+ case PARAVIRT_PATCH(pv_irq_ops.irq_enable):
return patch_internal(VMI_CALL_EnableInterrupts, len,
insns, eip);
- case PARAVIRT_PATCH(restore_fl):
+ case PARAVIRT_PATCH(pv_irq_ops.restore_fl):
return patch_internal(VMI_CALL_SetInterruptMask, len,
insns, eip);
- case PARAVIRT_PATCH(save_fl):
+ case PARAVIRT_PATCH(pv_irq_ops.save_fl):
return patch_internal(VMI_CALL_GetInterruptMask, len,
insns, eip);
- case PARAVIRT_PATCH(iret):
+ case PARAVIRT_PATCH(pv_cpu_ops.iret):
return patch_internal(VMI_CALL_IRET, len, insns, eip);
- case PARAVIRT_PATCH(irq_enable_sysexit):
+ case PARAVIRT_PATCH(pv_cpu_ops.irq_enable_sysexit):
return patch_internal(VMI_CALL_SYSEXIT, len, insns, eip);
default:
break;
@@ -552,24 +552,22 @@ vmi_startup_ipi_hook(int phys_apicid, unsigned long start_eip,
}
#endif
-static void vmi_set_lazy_mode(enum paravirt_lazy_mode mode)
+static void vmi_enter_lazy_cpu(void)
{
- static DEFINE_PER_CPU(enum paravirt_lazy_mode, lazy_mode);
-
- if (!vmi_ops.set_lazy_mode)
- return;
+ paravirt_enter_lazy_cpu();
+ vmi_ops.set_lazy_mode(2);
+}
- /* Modes should never nest or overlap */
- BUG_ON(__get_cpu_var(lazy_mode) && !(mode == PARAVIRT_LAZY_NONE ||
- mode == PARAVIRT_LAZY_FLUSH));
+static void vmi_enter_lazy_mmu(void)
+{
+ paravirt_enter_lazy_mmu();
+ vmi_ops.set_lazy_mode(1);
+}
- if (mode == PARAVIRT_LAZY_FLUSH) {
- vmi_ops.set_lazy_mode(0);
- vmi_ops.set_lazy_mode(__get_cpu_var(lazy_mode));
- } else {
- vmi_ops.set_lazy_mode(mode);
- __get_cpu_var(lazy_mode) = mode;
- }
+static void vmi_leave_lazy(void)
+{
+ paravirt_leave_lazy(paravirt_get_lazy_mode());
+ vmi_ops.set_lazy_mode(0);
}
static inline int __init check_vmi_rom(struct vrom_header *rom)
@@ -690,9 +688,9 @@ do { \
reloc = call_vrom_long_func(vmi_rom, get_reloc, \
VMI_CALL_##vmicall); \
if (rel->type == VMI_RELOCATION_CALL_REL) \
- paravirt_ops.opname = (void *)rel->eip; \
+ opname = (void *)rel->eip; \
else if (rel->type == VMI_RELOCATION_NOP) \
- paravirt_ops.opname = (void *)vmi_nop; \
+ opname = (void *)vmi_nop; \
else if (rel->type != VMI_RELOCATION_NONE) \
printk(KERN_WARNING "VMI: Unknown relocation " \
"type %d for " #vmicall"\n",\
@@ -712,7 +710,7 @@ do { \
VMI_CALL_##vmicall); \
BUG_ON(rel->type == VMI_RELOCATION_JUMP_REL); \
if (rel->type == VMI_RELOCATION_CALL_REL) { \
- paravirt_ops.opname = wrapper; \
+ opname = wrapper; \
vmi_ops.cache = (void *)rel->eip; \
} \
} while (0)
@@ -732,11 +730,11 @@ static inline int __init activate_vmi(void)
}
savesegment(cs, kernel_cs);
- paravirt_ops.paravirt_enabled = 1;
- paravirt_ops.kernel_rpl = kernel_cs & SEGMENT_RPL_MASK;
+ pv_info.paravirt_enabled = 1;
+ pv_info.kernel_rpl = kernel_cs & SEGMENT_RPL_MASK;
+ pv_info.name = "vmi";
- paravirt_ops.patch = vmi_patch;
- paravirt_ops.name = "vmi";
+ pv_init_ops.patch = vmi_patch;
/*
* Many of these operations are ABI compatible with VMI.
@@ -754,26 +752,26 @@ static inline int __init activate_vmi(void)
*/
/* CPUID is special, so very special it gets wrapped like a present */
- para_wrap(cpuid, vmi_cpuid, cpuid, CPUID);
-
- para_fill(clts, CLTS);
- para_fill(get_debugreg, GetDR);
- para_fill(set_debugreg, SetDR);
- para_fill(read_cr0, GetCR0);
- para_fill(read_cr2, GetCR2);
- para_fill(read_cr3, GetCR3);
- para_fill(read_cr4, GetCR4);
- para_fill(write_cr0, SetCR0);
- para_fill(write_cr2, SetCR2);
- para_fill(write_cr3, SetCR3);
- para_fill(write_cr4, SetCR4);
- para_fill(save_fl, GetInterruptMask);
- para_fill(restore_fl, SetInterruptMask);
- para_fill(irq_disable, DisableInterrupts);
- para_fill(irq_enable, EnableInterrupts);
-
- para_fill(wbinvd, WBINVD);
- para_fill(read_tsc, RDTSC);
+ para_wrap(pv_cpu_ops.cpuid, vmi_cpuid, cpuid, CPUID);
+
+ para_fill(pv_cpu_ops.clts, CLTS);
+ para_fill(pv_cpu_ops.get_debugreg, GetDR);
+ para_fill(pv_cpu_ops.set_debugreg, SetDR);
+ para_fill(pv_cpu_ops.read_cr0, GetCR0);
+ para_fill(pv_mmu_ops.read_cr2, GetCR2);
+ para_fill(pv_mmu_ops.read_cr3, GetCR3);
+ para_fill(pv_cpu_ops.read_cr4, GetCR4);
+ para_fill(pv_cpu_ops.write_cr0, SetCR0);
+ para_fill(pv_mmu_ops.write_cr2, SetCR2);
+ para_fill(pv_mmu_ops.write_cr3, SetCR3);
+ para_fill(pv_cpu_ops.write_cr4, SetCR4);
+ para_fill(pv_irq_ops.save_fl, GetInterruptMask);
+ para_fill(pv_irq_ops.restore_fl, SetInterruptMask);
+ para_fill(pv_irq_ops.irq_disable, DisableInterrupts);
+ para_fill(pv_irq_ops.irq_enable, EnableInterrupts);
+
+ para_fill(pv_cpu_ops.wbinvd, WBINVD);
+ para_fill(pv_cpu_ops.read_tsc, RDTSC);
/* The following we emulate with trap and emulate for now */
/* paravirt_ops.read_msr = vmi_rdmsr */
@@ -781,29 +779,38 @@ static inline int __init activate_vmi(void)
/* paravirt_ops.rdpmc = vmi_rdpmc */
/* TR interface doesn't pass TR value, wrap */
- para_wrap(load_tr_desc, vmi_set_tr, set_tr, SetTR);
+ para_wrap(pv_cpu_ops.load_tr_desc, vmi_set_tr, set_tr, SetTR);
/* LDT is special, too */
- para_wrap(set_ldt, vmi_set_ldt, _set_ldt, SetLDT);
-
- para_fill(load_gdt, SetGDT);
- para_fill(load_idt, SetIDT);
- para_fill(store_gdt, GetGDT);
- para_fill(store_idt, GetIDT);
- para_fill(store_tr, GetTR);
- paravirt_ops.load_tls = vmi_load_tls;
- para_fill(write_ldt_entry, WriteLDTEntry);
- para_fill(write_gdt_entry, WriteGDTEntry);
- para_fill(write_idt_entry, WriteIDTEntry);
- para_wrap(load_esp0, vmi_load_esp0, set_kernel_stack, UpdateKernelStack);
- para_fill(set_iopl_mask, SetIOPLMask);
- para_fill(io_delay, IODelay);
- para_wrap(set_lazy_mode, vmi_set_lazy_mode, set_lazy_mode, SetLazyMode);
+ para_wrap(pv_cpu_ops.set_ldt, vmi_set_ldt, _set_ldt, SetLDT);
+
+ para_fill(pv_cpu_ops.load_gdt, SetGDT);
+ para_fill(pv_cpu_ops.load_idt, SetIDT);
+ para_fill(pv_cpu_ops.store_gdt, GetGDT);
+ para_fill(pv_cpu_ops.store_idt, GetIDT);
+ para_fill(pv_cpu_ops.store_tr, GetTR);
+ pv_cpu_ops.load_tls = vmi_load_tls;
+ para_fill(pv_cpu_ops.write_ldt_entry, WriteLDTEntry);
+ para_fill(pv_cpu_ops.write_gdt_entry, WriteGDTEntry);
+ para_fill(pv_cpu_ops.write_idt_entry, WriteIDTEntry);
+ para_wrap(pv_cpu_ops.load_esp0, vmi_load_esp0, set_kernel_stack, UpdateKernelStack);
+ para_fill(pv_cpu_ops.set_iopl_mask, SetIOPLMask);
+ para_fill(pv_cpu_ops.io_delay, IODelay);
+
+ para_wrap(pv_cpu_ops.lazy_mode.enter, vmi_enter_lazy_cpu,
+ set_lazy_mode, SetLazyMode);
+ para_wrap(pv_cpu_ops.lazy_mode.leave, vmi_leave_lazy,
+ set_lazy_mode, SetLazyMode);
+
+ para_wrap(pv_mmu_ops.lazy_mode.enter, vmi_enter_lazy_mmu,
+ set_lazy_mode, SetLazyMode);
+ para_wrap(pv_mmu_ops.lazy_mode.leave, vmi_leave_lazy,
+ set_lazy_mode, SetLazyMode);
/* user and kernel flush are just handled with different flags to FlushTLB */
- para_wrap(flush_tlb_user, vmi_flush_tlb_user, _flush_tlb, FlushTLB);
- para_wrap(flush_tlb_kernel, vmi_flush_tlb_kernel, _flush_tlb, FlushTLB);
- para_fill(flush_tlb_single, InvalPage);
+ para_wrap(pv_mmu_ops.flush_tlb_user, vmi_flush_tlb_user, _flush_tlb, FlushTLB);
+ para_wrap(pv_mmu_ops.flush_tlb_kernel, vmi_flush_tlb_kernel, _flush_tlb, FlushTLB);
+ para_fill(pv_mmu_ops.flush_tlb_single, InvalPage);
/*
* Until a standard flag format can be agreed on, we need to
@@ -819,41 +826,41 @@ static inline int __init activate_vmi(void)
#endif
if (vmi_ops.set_pte) {
- paravirt_ops.set_pte = vmi_set_pte;
- paravirt_ops.set_pte_at = vmi_set_pte_at;
- paravirt_ops.set_pmd = vmi_set_pmd;
+ pv_mmu_ops.set_pte = vmi_set_pte;
+ pv_mmu_ops.set_pte_at = vmi_set_pte_at;
+ pv_mmu_ops.set_pmd = vmi_set_pmd;
#ifdef CONFIG_X86_PAE
- paravirt_ops.set_pte_atomic = vmi_set_pte_atomic;
- paravirt_ops.set_pte_present = vmi_set_pte_present;
- paravirt_ops.set_pud = vmi_set_pud;
- paravirt_ops.pte_clear = vmi_pte_clear;
- paravirt_ops.pmd_clear = vmi_pmd_clear;
+ pv_mmu_ops.set_pte_atomic = vmi_set_pte_atomic;
+ pv_mmu_ops.set_pte_present = vmi_set_pte_present;
+ pv_mmu_ops.set_pud = vmi_set_pud;
+ pv_mmu_ops.pte_clear = vmi_pte_clear;
+ pv_mmu_ops.pmd_clear = vmi_pmd_clear;
#endif
}
if (vmi_ops.update_pte) {
- paravirt_ops.pte_update = vmi_update_pte;
- paravirt_ops.pte_update_defer = vmi_update_pte_defer;
+ pv_mmu_ops.pte_update = vmi_update_pte;
+ pv_mmu_ops.pte_update_defer = vmi_update_pte_defer;
}
vmi_ops.allocate_page = vmi_get_function(VMI_CALL_AllocatePage);
if (vmi_ops.allocate_page) {
- paravirt_ops.alloc_pt = vmi_allocate_pt;
- paravirt_ops.alloc_pd = vmi_allocate_pd;
- paravirt_ops.alloc_pd_clone = vmi_allocate_pd_clone;
+ pv_mmu_ops.alloc_pt = vmi_allocate_pt;
+ pv_mmu_ops.alloc_pd = vmi_allocate_pd;
+ pv_mmu_ops.alloc_pd_clone = vmi_allocate_pd_clone;
}
vmi_ops.release_page = vmi_get_function(VMI_CALL_ReleasePage);
if (vmi_ops.release_page) {
- paravirt_ops.release_pt = vmi_release_pt;
- paravirt_ops.release_pd = vmi_release_pd;
+ pv_mmu_ops.release_pt = vmi_release_pt;
+ pv_mmu_ops.release_pd = vmi_release_pd;
}
/* Set linear is needed in all cases */
vmi_ops.set_linear_mapping = vmi_get_function(VMI_CALL_SetLinearMapping);
#ifdef CONFIG_HIGHPTE
if (vmi_ops.set_linear_mapping)
- paravirt_ops.kmap_atomic_pte = vmi_kmap_atomic_pte;
+ pv_mmu_ops.kmap_atomic_pte = vmi_kmap_atomic_pte;
#endif
/*
@@ -863,17 +870,17 @@ static inline int __init activate_vmi(void)
* the backend. They are performance critical anyway, so requiring
* a patch is not a big problem.
*/
- paravirt_ops.irq_enable_sysexit = (void *)0xfeedbab0;
- paravirt_ops.iret = (void *)0xbadbab0;
+ pv_cpu_ops.irq_enable_sysexit = (void *)0xfeedbab0;
+ pv_cpu_ops.iret = (void *)0xbadbab0;
#ifdef CONFIG_SMP
- para_wrap(startup_ipi_hook, vmi_startup_ipi_hook, set_initial_ap_state, SetInitialAPState);
+ para_wrap(pv_apic_ops.startup_ipi_hook, vmi_startup_ipi_hook, set_initial_ap_state, SetInitialAPState);
#endif
#ifdef CONFIG_X86_LOCAL_APIC
- para_fill(apic_read, APICRead);
- para_fill(apic_write, APICWrite);
- para_fill(apic_write_atomic, APICWrite);
+ para_fill(pv_apic_ops.apic_read, APICRead);
+ para_fill(pv_apic_ops.apic_write, APICWrite);
+ para_fill(pv_apic_ops.apic_write_atomic, APICWrite);
#endif
/*
@@ -891,15 +898,15 @@ static inline int __init activate_vmi(void)
vmi_timer_ops.set_alarm = vmi_get_function(VMI_CALL_SetAlarm);
vmi_timer_ops.cancel_alarm =
vmi_get_function(VMI_CALL_CancelAlarm);
- paravirt_ops.time_init = vmi_time_init;
- paravirt_ops.get_wallclock = vmi_get_wallclock;
- paravirt_ops.set_wallclock = vmi_set_wallclock;
+ pv_time_ops.time_init = vmi_time_init;
+ pv_time_ops.get_wallclock = vmi_get_wallclock;
+ pv_time_ops.set_wallclock = vmi_set_wallclock;
#ifdef CONFIG_X86_LOCAL_APIC
- paravirt_ops.setup_boot_clock = vmi_time_bsp_init;
- paravirt_ops.setup_secondary_clock = vmi_time_ap_init;
+ pv_apic_ops.setup_boot_clock = vmi_time_bsp_init;
+ pv_apic_ops.setup_secondary_clock = vmi_time_ap_init;
#endif
- paravirt_ops.sched_clock = vmi_sched_clock;
- paravirt_ops.get_cpu_khz = vmi_cpu_khz;
+ pv_time_ops.sched_clock = vmi_sched_clock;
+ pv_time_ops.get_cpu_khz = vmi_cpu_khz;
/* We have true wallclock functions; disable CMOS clock sync */
no_sync_cmos_clock = 1;
@@ -908,7 +915,7 @@ static inline int __init activate_vmi(void)
disable_vmi_timer = 1;
}
- para_fill(safe_halt, Halt);
+ para_fill(pv_irq_ops.safe_halt, Halt);
/*
* Alternative instruction rewriting doesn't happen soon enough
diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c
index 93847d848157..ad4005c6d4a1 100644
--- a/arch/x86/kernel/vsyscall_64.c
+++ b/arch/x86/kernel/vsyscall_64.c
@@ -48,12 +48,12 @@
({unsigned long v; \
extern char __vsyscall_0; \
asm("" : "=r" (v) : "0" (x)); \
- ((v - VSYSCALL_FIRST_PAGE) + __pa_symbol(&__vsyscall_0)); })
+ ((v - VSYSCALL_START) + __pa_symbol(&__vsyscall_0)); })
/*
* vsyscall_gtod_data contains data that is :
* - readonly from vsyscalls
- * - writen by timer interrupt or systcl (/proc/sys/kernel/vsyscall64)
+ * - written by timer interrupt or systcl (/proc/sys/kernel/vsyscall64)
* Try to keep this structure as small as possible to avoid cache line ping pongs
*/
int __vgetcpu_mode __section_vgetcpu_mode;
@@ -64,6 +64,16 @@ struct vsyscall_gtod_data __vsyscall_gtod_data __section_vsyscall_gtod_data =
.sysctl_enabled = 1,
};
+void update_vsyscall_tz(void)
+{
+ unsigned long flags;
+
+ write_seqlock_irqsave(&vsyscall_gtod_data.lock, flags);
+ /* sys_tz has changed */
+ vsyscall_gtod_data.sys_tz = sys_tz;
+ write_sequnlock_irqrestore(&vsyscall_gtod_data.lock, flags);
+}
+
void update_vsyscall(struct timespec *wall_time, struct clocksource *clock)
{
unsigned long flags;
@@ -77,8 +87,6 @@ void update_vsyscall(struct timespec *wall_time, struct clocksource *clock)
vsyscall_gtod_data.clock.shift = clock->shift;
vsyscall_gtod_data.wall_time_sec = wall_time->tv_sec;
vsyscall_gtod_data.wall_time_nsec = wall_time->tv_nsec;
- vsyscall_gtod_data.sys_tz = sys_tz;
- vsyscall_gtod_data.wall_time_nsec = wall_time->tv_nsec;
vsyscall_gtod_data.wall_to_monotonic = wall_to_monotonic;
write_sequnlock_irqrestore(&vsyscall_gtod_data.lock, flags);
}
@@ -164,7 +172,7 @@ time_t __vsyscall(1) vtime(time_t *t)
if (unlikely(!__vsyscall_gtod_data.sysctl_enabled))
return time_syscall(t);
- vgettimeofday(&tv, 0);
+ vgettimeofday(&tv, NULL);
result = tv.tv_sec;
if (t)
*t = result;
@@ -258,18 +266,10 @@ out:
return ret;
}
-static int vsyscall_sysctl_nostrat(ctl_table *t, int __user *name, int nlen,
- void __user *oldval, size_t __user *oldlenp,
- void __user *newval, size_t newlen)
-{
- return -ENOSYS;
-}
-
static ctl_table kernel_table2[] = {
- { .ctl_name = 99, .procname = "vsyscall64",
+ { .procname = "vsyscall64",
.data = &vsyscall_gtod_data.sysctl_enabled, .maxlen = sizeof(int),
.mode = 0644,
- .strategy = vsyscall_sysctl_nostrat,
.proc_handler = vsyscall_sysctl_change },
{}
};
@@ -289,9 +289,9 @@ static void __cpuinit vsyscall_set_cpu(int cpu)
unsigned long *d;
unsigned long node = 0;
#ifdef CONFIG_NUMA
- node = cpu_to_node[cpu];
+ node = cpu_to_node(cpu);
#endif
- if (cpu_has(&cpu_data[cpu], X86_FEATURE_RDTSCP))
+ if (cpu_has(&cpu_data(cpu), X86_FEATURE_RDTSCP))
write_rdtscp_aux((node << 12) | cpu);
/* Store cpu number in limit so that it can be loaded quickly
diff --git a/arch/x86/lguest/Kconfig b/arch/x86/lguest/Kconfig
new file mode 100644
index 000000000000..c4dffbeea5e1
--- /dev/null
+++ b/arch/x86/lguest/Kconfig
@@ -0,0 +1,14 @@
+config LGUEST_GUEST
+ bool "Lguest guest support"
+ select PARAVIRT
+ depends on !X86_PAE
+ select VIRTIO
+ select VIRTIO_RING
+ select VIRTIO_CONSOLE
+ help
+ Lguest is a tiny in-kernel hypervisor. Selecting this will
+ allow your kernel to boot under lguest. This option will increase
+ your kernel size by about 6k. If in doubt, say N.
+
+ If you say Y here, make sure you say Y (or M) to the virtio block
+ and net drivers which lguest needs.
diff --git a/arch/x86/lguest/Makefile b/arch/x86/lguest/Makefile
new file mode 100644
index 000000000000..27f0c9ed7f60
--- /dev/null
+++ b/arch/x86/lguest/Makefile
@@ -0,0 +1 @@
+obj-y := i386_head.o boot.o
diff --git a/drivers/lguest/lguest.c b/arch/x86/lguest/boot.c
index ee1c6d05c3d3..92c56117eae5 100644
--- a/drivers/lguest/lguest.c
+++ b/arch/x86/lguest/boot.c
@@ -23,7 +23,7 @@
*
* So how does the kernel know it's a Guest? The Guest starts at a special
* entry point marked with a magic string, which sets up a few things then
- * calls here. We replace the native functions in "struct paravirt_ops"
+ * calls here. We replace the native functions various "paravirt" structures
* with our Guest versions, then boot like normal. :*/
/*
@@ -55,7 +55,8 @@
#include <linux/clockchips.h>
#include <linux/lguest.h>
#include <linux/lguest_launcher.h>
-#include <linux/lguest_bus.h>
+#include <linux/virtio_console.h>
+#include <linux/pm.h>
#include <asm/paravirt.h>
#include <asm/param.h>
#include <asm/page.h>
@@ -65,6 +66,7 @@
#include <asm/e820.h>
#include <asm/mce.h>
#include <asm/io.h>
+#include <asm/i387.h>
/*G:010 Welcome to the Guest!
*
@@ -85,55 +87,13 @@ struct lguest_data lguest_data = {
.hcall_status = { [0 ... LHCALL_RING_SIZE-1] = 0xFF },
.noirq_start = (u32)lguest_noirq_start,
.noirq_end = (u32)lguest_noirq_end,
+ .kernel_address = PAGE_OFFSET,
.blocked_interrupts = { 1 }, /* Block timer interrupts */
+ .syscall_vec = SYSCALL_VECTOR,
};
-struct lguest_device_desc *lguest_devices;
static cycle_t clock_base;
-/*G:035 Notice the lazy_hcall() above, rather than hcall(). This is our first
- * real optimization trick!
- *
- * When lazy_mode is set, it means we're allowed to defer all hypercalls and do
- * them as a batch when lazy_mode is eventually turned off. Because hypercalls
- * are reasonably expensive, batching them up makes sense. For example, a
- * large mmap might update dozens of page table entries: that code calls
- * lguest_lazy_mode(PARAVIRT_LAZY_MMU), does the dozen updates, then calls
- * lguest_lazy_mode(PARAVIRT_LAZY_NONE).
- *
- * So, when we're in lazy mode, we call async_hypercall() to store the call for
- * future processing. When lazy mode is turned off we issue a hypercall to
- * flush the stored calls.
- *
- * There's also a hack where "mode" is set to "PARAVIRT_LAZY_FLUSH" which
- * indicates we're to flush any outstanding calls immediately. This is used
- * when an interrupt handler does a kmap_atomic(): the page table changes must
- * happen immediately even if we're in the middle of a batch. Usually we're
- * not, though, so there's nothing to do. */
-static enum paravirt_lazy_mode lazy_mode; /* Note: not SMP-safe! */
-static void lguest_lazy_mode(enum paravirt_lazy_mode mode)
-{
- if (mode == PARAVIRT_LAZY_FLUSH) {
- if (unlikely(lazy_mode != PARAVIRT_LAZY_NONE))
- hcall(LHCALL_FLUSH_ASYNC, 0, 0, 0);
- } else {
- lazy_mode = mode;
- if (mode == PARAVIRT_LAZY_NONE)
- hcall(LHCALL_FLUSH_ASYNC, 0, 0, 0);
- }
-}
-
-static void lazy_hcall(unsigned long call,
- unsigned long arg1,
- unsigned long arg2,
- unsigned long arg3)
-{
- if (lazy_mode == PARAVIRT_LAZY_NONE)
- hcall(call, arg1, arg2, arg3);
- else
- async_hcall(call, arg1, arg2, arg3);
-}
-
-/* async_hcall() is pretty simple: I'm quite proud of it really. We have a
+/*G:037 async_hcall() is pretty simple: I'm quite proud of it really. We have a
* ring buffer of stored hypercalls which the Host will run though next time we
* do a normal hypercall. Each entry in the ring has 4 slots for the hypercall
* arguments, and a "hcall_status" word which is 0 if the call is ready to go,
@@ -143,8 +103,8 @@ static void lazy_hcall(unsigned long call,
* full and we just make the hypercall directly. This has the nice side
* effect of causing the Host to run all the stored calls in the ring buffer
* which empties it for next time! */
-void async_hcall(unsigned long call,
- unsigned long arg1, unsigned long arg2, unsigned long arg3)
+static void async_hcall(unsigned long call, unsigned long arg1,
+ unsigned long arg2, unsigned long arg3)
{
/* Note: This code assumes we're uniprocessor. */
static unsigned int next_call;
@@ -158,10 +118,10 @@ void async_hcall(unsigned long call,
/* Table full, so do normal hcall which will flush table. */
hcall(call, arg1, arg2, arg3);
} else {
- lguest_data.hcalls[next_call].eax = call;
- lguest_data.hcalls[next_call].edx = arg1;
- lguest_data.hcalls[next_call].ebx = arg2;
- lguest_data.hcalls[next_call].ecx = arg3;
+ lguest_data.hcalls[next_call].arg0 = call;
+ lguest_data.hcalls[next_call].arg1 = arg1;
+ lguest_data.hcalls[next_call].arg2 = arg2;
+ lguest_data.hcalls[next_call].arg3 = arg3;
/* Arguments must all be written before we mark it to go */
wmb();
lguest_data.hcall_status[next_call] = 0;
@@ -170,51 +130,41 @@ void async_hcall(unsigned long call,
}
local_irq_restore(flags);
}
-/*:*/
-
-/* Wrappers for the SEND_DMA and BIND_DMA hypercalls. This is mainly because
- * Jeff Garzik complained that __pa() should never appear in drivers, and this
- * helps remove most of them. But also, it wraps some ugliness. */
-void lguest_send_dma(unsigned long key, struct lguest_dma *dma)
-{
- /* The hcall might not write this if something goes wrong */
- dma->used_len = 0;
- hcall(LHCALL_SEND_DMA, key, __pa(dma), 0);
-}
-
-int lguest_bind_dma(unsigned long key, struct lguest_dma *dmas,
- unsigned int num, u8 irq)
-{
- /* This is the only hypercall which actually wants 5 arguments, and we
- * only support 4. Fortunately the interrupt number is always less
- * than 256, so we can pack it with the number of dmas in the final
- * argument. */
- if (!hcall(LHCALL_BIND_DMA, key, __pa(dmas), (num << 8) | irq))
- return -ENOMEM;
- return 0;
-}
-/* Unbinding is the same hypercall as binding, but with 0 num & irq. */
-void lguest_unbind_dma(unsigned long key, struct lguest_dma *dmas)
-{
- hcall(LHCALL_BIND_DMA, key, __pa(dmas), 0);
-}
-
-/* For guests, device memory can be used as normal memory, so we cast away the
- * __iomem to quieten sparse. */
-void *lguest_map(unsigned long phys_addr, unsigned long pages)
+/*G:035 Notice the lazy_hcall() above, rather than hcall(). This is our first
+ * real optimization trick!
+ *
+ * When lazy_mode is set, it means we're allowed to defer all hypercalls and do
+ * them as a batch when lazy_mode is eventually turned off. Because hypercalls
+ * are reasonably expensive, batching them up makes sense. For example, a
+ * large munmap might update dozens of page table entries: that code calls
+ * paravirt_enter_lazy_mmu(), does the dozen updates, then calls
+ * lguest_leave_lazy_mode().
+ *
+ * So, when we're in lazy mode, we call async_hcall() to store the call for
+ * future processing. */
+static void lazy_hcall(unsigned long call,
+ unsigned long arg1,
+ unsigned long arg2,
+ unsigned long arg3)
{
- return (__force void *)ioremap(phys_addr, PAGE_SIZE*pages);
+ if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE)
+ hcall(call, arg1, arg2, arg3);
+ else
+ async_hcall(call, arg1, arg2, arg3);
}
-void lguest_unmap(void *addr)
+/* When lazy mode is turned off reset the per-cpu lazy mode variable and then
+ * issue a hypercall to flush any stored calls. */
+static void lguest_leave_lazy_mode(void)
{
- iounmap((__force void __iomem *)addr);
+ paravirt_leave_lazy(paravirt_get_lazy_mode());
+ hcall(LHCALL_FLUSH_ASYNC, 0, 0, 0);
}
/*G:033
- * Here are our first native-instruction replacements: four functions for
- * interrupt control.
+ * After that diversion we return to our first native-instruction
+ * replacements: four functions for interrupt control.
*
* The simplest way of implementing these would be to have "turn interrupts
* off" and "turn interrupts on" hypercalls. Unfortunately, this is too slow:
@@ -233,7 +183,7 @@ static unsigned long save_fl(void)
return lguest_data.irq_enabled;
}
-/* "restore_flags" just sets the flags back to the value given. */
+/* restore_flags() just sets the flags back to the value given. */
static void restore_fl(unsigned long flags)
{
lguest_data.irq_enabled = flags;
@@ -331,7 +281,7 @@ static void lguest_load_tls(struct thread_struct *t, unsigned int cpu)
}
/*G:038 That's enough excitement for now, back to ploughing through each of
- * the paravirt_ops (we're about 1/3 of the way through).
+ * the different pv_ops structures (we're about 1/3 of the way through).
*
* This is the Local Descriptor Table, another weird Intel thingy. Linux only
* uses this for some strange applications like Wine. We don't do anything
@@ -406,7 +356,7 @@ static void lguest_cpuid(unsigned int *eax, unsigned int *ebx,
* it. The Host needs to know when the Guest wants to change them, so we have
* a whole series of functions like read_cr0() and write_cr0().
*
- * We start with CR0. CR0 allows you to turn on and off all kinds of basic
+ * We start with cr0. cr0 allows you to turn on and off all kinds of basic
* features, but Linux only really cares about one: the horrifically-named Task
* Switched (TS) bit at bit 3 (ie. 8)
*
@@ -421,8 +371,7 @@ static void lguest_cpuid(unsigned int *eax, unsigned int *ebx,
static unsigned long current_cr0, current_cr3;
static void lguest_write_cr0(unsigned long val)
{
- /* 8 == TS bit. */
- lazy_hcall(LHCALL_TS, val & 8, 0, 0);
+ lazy_hcall(LHCALL_TS, val & X86_CR0_TS, 0, 0);
current_cr0 = val;
}
@@ -437,10 +386,10 @@ static unsigned long lguest_read_cr0(void)
static void lguest_clts(void)
{
lazy_hcall(LHCALL_TS, 0, 0, 0);
- current_cr0 &= ~8U;
+ current_cr0 &= ~X86_CR0_TS;
}
-/* CR2 is the virtual address of the last page fault, which the Guest only ever
+/* cr2 is the virtual address of the last page fault, which the Guest only ever
* reads. The Host kindly writes this into our "struct lguest_data", so we
* just read it out of there. */
static unsigned long lguest_read_cr2(void)
@@ -448,7 +397,7 @@ static unsigned long lguest_read_cr2(void)
return lguest_data.cr2;
}
-/* CR3 is the current toplevel pagetable page: the principle is the same as
+/* cr3 is the current toplevel pagetable page: the principle is the same as
* cr0. Keep a local copy, and tell the Host when it changes. */
static void lguest_write_cr3(unsigned long cr3)
{
@@ -461,7 +410,7 @@ static unsigned long lguest_read_cr3(void)
return current_cr3;
}
-/* CR4 is used to enable and disable PGE, but we don't care. */
+/* cr4 is used to enable and disable PGE, but we don't care. */
static unsigned long lguest_read_cr4(void)
{
return 0;
@@ -482,7 +431,7 @@ static void lguest_write_cr4(unsigned long val)
* maps virtual addresses to physical addresses using "page tables". We could
* use one huge index of 1 million entries: each address is 4 bytes, so that's
* 1024 pages just to hold the page tables. But since most virtual addresses
- * are unused, we use a two level index which saves space. The CR3 register
+ * are unused, we use a two level index which saves space. The cr3 register
* contains the physical address of the top level "page directory" page, which
* contains physical addresses of up to 1024 second-level pages. Each of these
* second level pages contains up to 1024 physical addresses of actual pages,
@@ -490,7 +439,7 @@ static void lguest_write_cr4(unsigned long val)
*
* Here's a diagram, where arrows indicate physical addresses:
*
- * CR3 ---> +---------+
+ * cr3 ---> +---------+
* | --------->+---------+
* | | | PADDR1 |
* Top-level | | PADDR2 |
@@ -548,8 +497,7 @@ static void lguest_set_pmd(pmd_t *pmdp, pmd_t pmdval)
*
* ... except in early boot when the kernel sets up the initial pagetables,
* which makes booting astonishingly slow. So we don't even tell the Host
- * anything changed until we've done the first page table switch.
- */
+ * anything changed until we've done the first page table switch. */
static void lguest_set_pte(pte_t *ptep, pte_t pteval)
{
*ptep = pteval;
@@ -558,7 +506,7 @@ static void lguest_set_pte(pte_t *ptep, pte_t pteval)
lazy_hcall(LHCALL_FLUSH_TLB, 1, 0, 0);
}
-/* Unfortunately for Lguest, the paravirt_ops for page tables were based on
+/* Unfortunately for Lguest, the pv_mmu_ops for page tables were based on
* native page table operations. On native hardware you can set a new page
* table entry whenever you want, but if you want to remove one you have to do
* a TLB flush (a TLB is a little cache of page table entries kept by the CPU).
@@ -692,6 +640,7 @@ static struct clocksource lguest_clock = {
.mask = CLOCKSOURCE_MASK(64),
.mult = 1 << 22,
.shift = 22,
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
/* The "scheduler clock" is just our real clock, adjusted to start at zero */
@@ -769,20 +718,18 @@ static void lguest_time_init(void)
/* Set up the timer interrupt (0) to go to our simple timer routine */
set_irq_handler(0, lguest_time_irq);
- /* Our clock structure look like arch/i386/kernel/tsc.c if we can use
- * the TSC, otherwise it's a dumb nanosecond-resolution clock. Either
- * way, the "rating" is initialized so high that it's always chosen
- * over any other clocksource. */
- if (lguest_data.tsc_khz) {
+ /* Our clock structure looks like arch/x86/kernel/tsc_32.c if we can
+ * use the TSC, otherwise it's a dumb nanosecond-resolution clock.
+ * Either way, the "rating" is set so high that it's always chosen over
+ * any other clocksource. */
+ if (lguest_data.tsc_khz)
lguest_clock.mult = clocksource_khz2mult(lguest_data.tsc_khz,
lguest_clock.shift);
- lguest_clock.flags = CLOCK_SOURCE_IS_CONTINUOUS;
- }
clock_base = lguest_clock_read();
clocksource_register(&lguest_clock);
/* Now we've set up our clock, we can use it as the scheduler clock */
- paravirt_ops.sched_clock = lguest_sched_clock;
+ pv_time_ops.sched_clock = lguest_sched_clock;
/* We can't set cpumask in the initializer: damn C limitations! Set it
* here and register our timer device. */
@@ -800,7 +747,7 @@ static void lguest_time_init(void)
* to work. They're pretty simple.
*/
-/* The Guest needs to tell the host what stack it expects traps to use. For
+/* The Guest needs to tell the Host what stack it expects traps to use. For
* native hardware, this is part of the Task State Segment mentioned above in
* lguest_load_tr_desc(), but to help hypervisors there's this special call.
*
@@ -893,16 +840,38 @@ static __init char *lguest_memory_setup(void)
/* The Linux bootloader header contains an "e820" memory map: the
* Launcher populated the first entry with our memory limit. */
- add_memory_region(E820_MAP->addr, E820_MAP->size, E820_MAP->type);
+ add_memory_region(boot_params.e820_map[0].addr,
+ boot_params.e820_map[0].size,
+ boot_params.e820_map[0].type);
/* This string is for the boot messages. */
return "LGUEST";
}
+/* We will eventually use the virtio console device to produce console output,
+ * but before that is set up we use LHCALL_NOTIFY on normal memory to produce
+ * console output. */
+static __init int early_put_chars(u32 vtermno, const char *buf, int count)
+{
+ char scratch[17];
+ unsigned int len = count;
+
+ /* We use a nul-terminated string, so we have to make a copy. Icky,
+ * huh? */
+ if (len > sizeof(scratch) - 1)
+ len = sizeof(scratch) - 1;
+ scratch[len] = '\0';
+ memcpy(scratch, buf, len);
+ hcall(LHCALL_NOTIFY, __pa(scratch), 0, 0);
+
+ /* This routine returns the number of bytes actually written. */
+ return len;
+}
+
/*G:050
* Patching (Powerfully Placating Performance Pedants)
*
- * We have already seen that "struct paravirt_ops" lets us replace simple
+ * We have already seen that pv_ops structures let us replace simple
* native instructions with calls to the appropriate back end all throughout
* the kernel. This allows the same kernel to run as a Guest and as a native
* kernel, but it's slow because of all the indirect branches.
@@ -915,7 +884,7 @@ static __init char *lguest_memory_setup(void)
* Our current solution is to allow the paravirt back end to optionally patch
* over the indirect calls to replace them with something more efficient. We
* patch the four most commonly called functions: disable interrupts, enable
- * interrupts, restore interrupts and save interrupts. We usually have 10
+ * interrupts, restore interrupts and save interrupts. We usually have 6 or 10
* bytes to patch into: the Guest versions of these operations are small enough
* that we can fit comfortably.
*
@@ -927,10 +896,10 @@ static const struct lguest_insns
{
const char *start, *end;
} lguest_insns[] = {
- [PARAVIRT_PATCH(irq_disable)] = { lgstart_cli, lgend_cli },
- [PARAVIRT_PATCH(irq_enable)] = { lgstart_sti, lgend_sti },
- [PARAVIRT_PATCH(restore_fl)] = { lgstart_popf, lgend_popf },
- [PARAVIRT_PATCH(save_fl)] = { lgstart_pushf, lgend_pushf },
+ [PARAVIRT_PATCH(pv_irq_ops.irq_disable)] = { lgstart_cli, lgend_cli },
+ [PARAVIRT_PATCH(pv_irq_ops.irq_enable)] = { lgstart_sti, lgend_sti },
+ [PARAVIRT_PATCH(pv_irq_ops.restore_fl)] = { lgstart_popf, lgend_popf },
+ [PARAVIRT_PATCH(pv_irq_ops.save_fl)] = { lgstart_pushf, lgend_pushf },
};
/* Now our patch routine is fairly simple (based on the native one in
@@ -957,81 +926,83 @@ static unsigned lguest_patch(u8 type, u16 clobber, void *ibuf,
return insn_len;
}
-/*G:030 Once we get to lguest_init(), we know we're a Guest. The paravirt_ops
- * structure in the kernel provides a single point for (almost) every routine
- * we have to override to avoid privileged instructions. */
-__init void lguest_init(void *boot)
+/*G:030 Once we get to lguest_init(), we know we're a Guest. The pv_ops
+ * structures in the kernel provide points for (almost) every routine we have
+ * to override to avoid privileged instructions. */
+__init void lguest_init(void)
{
- /* Copy boot parameters first: the Launcher put the physical location
- * in %esi, and head.S converted that to a virtual address and handed
- * it to us. We use "__memcpy" because "memcpy" sometimes tries to do
- * tricky things to go faster, and we're not ready for that. */
- __memcpy(&boot_params, boot, PARAM_SIZE);
- /* The boot parameters also tell us where the command-line is: save
- * that, too. */
- __memcpy(boot_command_line, __va(boot_params.hdr.cmd_line_ptr),
- COMMAND_LINE_SIZE);
-
/* We're under lguest, paravirt is enabled, and we're running at
* privilege level 1, not 0 as normal. */
- paravirt_ops.name = "lguest";
- paravirt_ops.paravirt_enabled = 1;
- paravirt_ops.kernel_rpl = 1;
+ pv_info.name = "lguest";
+ pv_info.paravirt_enabled = 1;
+ pv_info.kernel_rpl = 1;
/* We set up all the lguest overrides for sensitive operations. These
* are detailed with the operations themselves. */
- paravirt_ops.save_fl = save_fl;
- paravirt_ops.restore_fl = restore_fl;
- paravirt_ops.irq_disable = irq_disable;
- paravirt_ops.irq_enable = irq_enable;
- paravirt_ops.load_gdt = lguest_load_gdt;
- paravirt_ops.memory_setup = lguest_memory_setup;
- paravirt_ops.cpuid = lguest_cpuid;
- paravirt_ops.write_cr3 = lguest_write_cr3;
- paravirt_ops.flush_tlb_user = lguest_flush_tlb_user;
- paravirt_ops.flush_tlb_single = lguest_flush_tlb_single;
- paravirt_ops.flush_tlb_kernel = lguest_flush_tlb_kernel;
- paravirt_ops.set_pte = lguest_set_pte;
- paravirt_ops.set_pte_at = lguest_set_pte_at;
- paravirt_ops.set_pmd = lguest_set_pmd;
+
+ /* interrupt-related operations */
+ pv_irq_ops.init_IRQ = lguest_init_IRQ;
+ pv_irq_ops.save_fl = save_fl;
+ pv_irq_ops.restore_fl = restore_fl;
+ pv_irq_ops.irq_disable = irq_disable;
+ pv_irq_ops.irq_enable = irq_enable;
+ pv_irq_ops.safe_halt = lguest_safe_halt;
+
+ /* init-time operations */
+ pv_init_ops.memory_setup = lguest_memory_setup;
+ pv_init_ops.patch = lguest_patch;
+
+ /* Intercepts of various cpu instructions */
+ pv_cpu_ops.load_gdt = lguest_load_gdt;
+ pv_cpu_ops.cpuid = lguest_cpuid;
+ pv_cpu_ops.load_idt = lguest_load_idt;
+ pv_cpu_ops.iret = lguest_iret;
+ pv_cpu_ops.load_esp0 = lguest_load_esp0;
+ pv_cpu_ops.load_tr_desc = lguest_load_tr_desc;
+ pv_cpu_ops.set_ldt = lguest_set_ldt;
+ pv_cpu_ops.load_tls = lguest_load_tls;
+ pv_cpu_ops.set_debugreg = lguest_set_debugreg;
+ pv_cpu_ops.clts = lguest_clts;
+ pv_cpu_ops.read_cr0 = lguest_read_cr0;
+ pv_cpu_ops.write_cr0 = lguest_write_cr0;
+ pv_cpu_ops.read_cr4 = lguest_read_cr4;
+ pv_cpu_ops.write_cr4 = lguest_write_cr4;
+ pv_cpu_ops.write_gdt_entry = lguest_write_gdt_entry;
+ pv_cpu_ops.write_idt_entry = lguest_write_idt_entry;
+ pv_cpu_ops.wbinvd = lguest_wbinvd;
+ pv_cpu_ops.lazy_mode.enter = paravirt_enter_lazy_cpu;
+ pv_cpu_ops.lazy_mode.leave = lguest_leave_lazy_mode;
+
+ /* pagetable management */
+ pv_mmu_ops.write_cr3 = lguest_write_cr3;
+ pv_mmu_ops.flush_tlb_user = lguest_flush_tlb_user;
+ pv_mmu_ops.flush_tlb_single = lguest_flush_tlb_single;
+ pv_mmu_ops.flush_tlb_kernel = lguest_flush_tlb_kernel;
+ pv_mmu_ops.set_pte = lguest_set_pte;
+ pv_mmu_ops.set_pte_at = lguest_set_pte_at;
+ pv_mmu_ops.set_pmd = lguest_set_pmd;
+ pv_mmu_ops.read_cr2 = lguest_read_cr2;
+ pv_mmu_ops.read_cr3 = lguest_read_cr3;
+ pv_mmu_ops.lazy_mode.enter = paravirt_enter_lazy_mmu;
+ pv_mmu_ops.lazy_mode.leave = lguest_leave_lazy_mode;
+
#ifdef CONFIG_X86_LOCAL_APIC
- paravirt_ops.apic_write = lguest_apic_write;
- paravirt_ops.apic_write_atomic = lguest_apic_write;
- paravirt_ops.apic_read = lguest_apic_read;
+ /* apic read/write intercepts */
+ pv_apic_ops.apic_write = lguest_apic_write;
+ pv_apic_ops.apic_write_atomic = lguest_apic_write;
+ pv_apic_ops.apic_read = lguest_apic_read;
#endif
- paravirt_ops.load_idt = lguest_load_idt;
- paravirt_ops.iret = lguest_iret;
- paravirt_ops.load_esp0 = lguest_load_esp0;
- paravirt_ops.load_tr_desc = lguest_load_tr_desc;
- paravirt_ops.set_ldt = lguest_set_ldt;
- paravirt_ops.load_tls = lguest_load_tls;
- paravirt_ops.set_debugreg = lguest_set_debugreg;
- paravirt_ops.clts = lguest_clts;
- paravirt_ops.read_cr0 = lguest_read_cr0;
- paravirt_ops.write_cr0 = lguest_write_cr0;
- paravirt_ops.init_IRQ = lguest_init_IRQ;
- paravirt_ops.read_cr2 = lguest_read_cr2;
- paravirt_ops.read_cr3 = lguest_read_cr3;
- paravirt_ops.read_cr4 = lguest_read_cr4;
- paravirt_ops.write_cr4 = lguest_write_cr4;
- paravirt_ops.write_gdt_entry = lguest_write_gdt_entry;
- paravirt_ops.write_idt_entry = lguest_write_idt_entry;
- paravirt_ops.patch = lguest_patch;
- paravirt_ops.safe_halt = lguest_safe_halt;
- paravirt_ops.get_wallclock = lguest_get_wallclock;
- paravirt_ops.time_init = lguest_time_init;
- paravirt_ops.set_lazy_mode = lguest_lazy_mode;
- paravirt_ops.wbinvd = lguest_wbinvd;
+
+ /* time operations */
+ pv_time_ops.get_wallclock = lguest_get_wallclock;
+ pv_time_ops.time_init = lguest_time_init;
+
/* Now is a good time to look at the implementations of these functions
* before returning to the rest of lguest_init(). */
/*G:070 Now we've seen all the paravirt_ops, we return to
* lguest_init() where the rest of the fairly chaotic boot setup
- * occurs.
- *
- * The Host expects our first hypercall to tell it where our "struct
- * lguest_data" is, so we do that first. */
- hcall(LHCALL_LGUEST_INIT, __pa(&lguest_data), 0, 0);
+ * occurs. */
/* The native boot code sets up initial page tables immediately after
* the kernel itself, and sets init_pg_tables_end so they're not
@@ -1044,13 +1015,8 @@ __init void lguest_init(void *boot)
* the normal data segment to get through booting. */
asm volatile ("mov %0, %%fs" : : "r" (__KERNEL_DS) : "memory");
- /* Clear the part of the kernel data which is expected to be zero.
- * Normally it will be anyway, but if we're loading from a bzImage with
- * CONFIG_RELOCATALE=y, the relocations will be sitting here. */
- memset(__bss_start, 0, __bss_stop - __bss_start);
-
/* The Host uses the top of the Guest's virtual address space for the
- * Host<->Guest Switcher, and it tells us how much it needs in
+ * Host<->Guest Switcher, and it tells us how big that is in
* lguest_data.reserve_mem, set up on the LGUEST_INIT hypercall. */
reserve_top_address(lguest_data.reserve_mem);
@@ -1086,6 +1052,9 @@ __init void lguest_init(void *boot)
* adapted for lguest's use. */
add_preferred_console("hvc", 0, NULL);
+ /* Register our very early console. */
+ virtio_cons_early_init(early_put_chars);
+
/* Last of all, we set the power management poweroff hook to point to
* the Guest routine to power off. */
pm_power_off = lguest_power_off;
@@ -1097,6 +1066,6 @@ __init void lguest_init(void *boot)
/*
* This marks the end of stage II of our journey, The Guest.
*
- * It is now time for us to explore the nooks and crannies of the three Guest
- * devices and complete our understanding of the Guest in "make Drivers".
+ * It is now time for us to explore the layer of virtual drivers and complete
+ * our understanding of the Guest in "make Drivers".
*/
diff --git a/drivers/lguest/lguest_asm.S b/arch/x86/lguest/i386_head.S
index 1ddcd5cd20f6..95b6fbcded63 100644
--- a/drivers/lguest/lguest_asm.S
+++ b/arch/x86/lguest/i386_head.S
@@ -1,25 +1,49 @@
#include <linux/linkage.h>
#include <linux/lguest.h>
+#include <asm/lguest_hcall.h>
#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
#include <asm/processor-flags.h>
-/*G:020 This is where we begin: we have a magic signature which the launcher
- * looks for. The plan is that the Linux boot protocol will be extended with a
- * "platform type" field which will guide us here from the normal entry point,
- * but for the moment this suffices. The normal boot code uses %esi for the
- * boot header, so we do too. We convert it to a virtual address by adding
- * PAGE_OFFSET, and hand it to lguest_init() as its argument (ie. %eax).
+/*G:020 This is where we begin: head.S notes that the boot header's platform
+ * type field is "1" (lguest), so calls us here.
+ *
+ * WARNING: be very careful here! We're running at addresses equal to physical
+ * addesses (around 0), not above PAGE_OFFSET as most code expectes
+ * (eg. 0xC0000000). Jumps are relative, so they're OK, but we can't touch any
+ * data.
*
* The .section line puts this code in .init.text so it will be discarded after
* boot. */
.section .init.text, "ax", @progbits
-.ascii "GenuineLguest"
- /* Set up initial stack. */
- movl $(init_thread_union+THREAD_SIZE),%esp
- movl %esi, %eax
- addl $__PAGE_OFFSET, %eax
- jmp lguest_init
+ENTRY(lguest_entry)
+ /* We make the "initialization" hypercall now to tell the Host about
+ * us, and also find out where it put our page tables. */
+ movl $LHCALL_LGUEST_INIT, %eax
+ movl $lguest_data - __PAGE_OFFSET, %edx
+ int $LGUEST_TRAP_ENTRY
+
+ /* The Host put the toplevel pagetable in lguest_data.pgdir. The movsl
+ * instruction uses %esi implicitly as the source for the copy we'
+ * about to do. */
+ movl lguest_data - __PAGE_OFFSET + LGUEST_DATA_pgdir, %esi
+
+ /* Copy first 32 entries of page directory to __PAGE_OFFSET entries.
+ * This means the first 128M of kernel memory will be mapped at
+ * PAGE_OFFSET where the kernel expects to run. This will get it far
+ * enough through boot to switch to its own pagetables. */
+ movl $32, %ecx
+ movl %esi, %edi
+ addl $((__PAGE_OFFSET >> 22) * 4), %edi
+ rep
+ movsl
+
+ /* Set up the initial stack so we can run C code. */
+ movl $(init_thread_union+THREAD_SIZE),%esp
+
+ /* Jumps are relative, and we're running __PAGE_OFFSET too low at the
+ * moment. */
+ jmp lguest_init+__PAGE_OFFSET
/*G:055 We create a macro which puts the assembler code between lgstart_ and
* lgend_ markers. These templates are put in the .text section: they can't be
diff --git a/arch/x86/lib/bitstr_64.c b/arch/x86/lib/bitstr_64.c
index 24676609a6ac..7445caf1b5de 100644
--- a/arch/x86/lib/bitstr_64.c
+++ b/arch/x86/lib/bitstr_64.c
@@ -14,7 +14,7 @@ find_next_zero_string(unsigned long *bitmap, long start, long nbits, int len)
/* could test bitsliced, but it's hardly worth it */
end = n+len;
- if (end >= nbits)
+ if (end > nbits)
return -1;
for (i = n+1; i < end; i++) {
if (test_bit(i, bitmap)) {
diff --git a/arch/x86/lib/delay_32.c b/arch/x86/lib/delay_32.c
index f6edb11364df..aad9d95469dc 100644
--- a/arch/x86/lib/delay_32.c
+++ b/arch/x86/lib/delay_32.c
@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/sched.h>
+#include <linux/preempt.h>
#include <linux/delay.h>
#include <asm/processor.h>
@@ -42,11 +43,13 @@ static void delay_tsc(unsigned long loops)
{
unsigned long bclock, now;
+ preempt_disable(); /* TSC's are per-cpu */
rdtscl(bclock);
do {
rep_nop();
rdtscl(now);
} while ((now-bclock) < loops);
+ preempt_enable();
}
/*
@@ -82,7 +85,7 @@ inline void __const_udelay(unsigned long xloops)
__asm__("mull %0"
:"=d" (xloops), "=&a" (d0)
:"1" (xloops), "0"
- (cpu_data[raw_smp_processor_id()].loops_per_jiffy * (HZ/4)));
+ (cpu_data(raw_smp_processor_id()).loops_per_jiffy * (HZ/4)));
__delay(++xloops);
}
diff --git a/arch/x86/lib/delay_64.c b/arch/x86/lib/delay_64.c
index 2dbebd308347..45cdd3fbd91c 100644
--- a/arch/x86/lib/delay_64.c
+++ b/arch/x86/lib/delay_64.c
@@ -10,7 +10,9 @@
#include <linux/module.h>
#include <linux/sched.h>
+#include <linux/preempt.h>
#include <linux/delay.h>
+
#include <asm/delay.h>
#include <asm/msr.h>
@@ -27,20 +29,22 @@ int read_current_timer(unsigned long *timer_value)
void __delay(unsigned long loops)
{
unsigned bclock, now;
-
+
+ preempt_disable(); /* TSC's are pre-cpu */
rdtscl(bclock);
- do
- {
+ do {
rep_nop();
rdtscl(now);
}
- while((now-bclock) < loops);
+ while ((now-bclock) < loops);
+ preempt_enable();
}
EXPORT_SYMBOL(__delay);
inline void __const_udelay(unsigned long xloops)
{
- __delay(((xloops * HZ * cpu_data[raw_smp_processor_id()].loops_per_jiffy) >> 32) + 1);
+ __delay(((xloops * HZ *
+ cpu_data(raw_smp_processor_id()).loops_per_jiffy) >> 32) + 1);
}
EXPORT_SYMBOL(__const_udelay);
diff --git a/arch/x86/lib/msr-on-cpu.c b/arch/x86/lib/msr-on-cpu.c
index 7767962f25d3..57d043fa893e 100644
--- a/arch/x86/lib/msr-on-cpu.c
+++ b/arch/x86/lib/msr-on-cpu.c
@@ -26,27 +26,18 @@ static void __rdmsr_safe_on_cpu(void *info)
static int _rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h, int safe)
{
int err = 0;
- preempt_disable();
- if (smp_processor_id() == cpu)
- if (safe)
- err = rdmsr_safe(msr_no, l, h);
- else
- rdmsr(msr_no, *l, *h);
- else {
- struct msr_info rv;
-
- rv.msr_no = msr_no;
- if (safe) {
- smp_call_function_single(cpu, __rdmsr_safe_on_cpu,
- &rv, 0, 1);
- err = rv.err;
- } else {
- smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 0, 1);
- }
- *l = rv.l;
- *h = rv.h;
+ struct msr_info rv;
+
+ rv.msr_no = msr_no;
+ if (safe) {
+ smp_call_function_single(cpu, __rdmsr_safe_on_cpu, &rv, 0, 1);
+ err = rv.err;
+ } else {
+ smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 0, 1);
}
- preempt_enable();
+ *l = rv.l;
+ *h = rv.h;
+
return err;
}
@@ -67,27 +58,18 @@ static void __wrmsr_safe_on_cpu(void *info)
static int _wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h, int safe)
{
int err = 0;
- preempt_disable();
- if (smp_processor_id() == cpu)
- if (safe)
- err = wrmsr_safe(msr_no, l, h);
- else
- wrmsr(msr_no, l, h);
- else {
- struct msr_info rv;
-
- rv.msr_no = msr_no;
- rv.l = l;
- rv.h = h;
- if (safe) {
- smp_call_function_single(cpu, __wrmsr_safe_on_cpu,
- &rv, 0, 1);
- err = rv.err;
- } else {
- smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 0, 1);
- }
+ struct msr_info rv;
+
+ rv.msr_no = msr_no;
+ rv.l = l;
+ rv.h = h;
+ if (safe) {
+ smp_call_function_single(cpu, __wrmsr_safe_on_cpu, &rv, 0, 1);
+ err = rv.err;
+ } else {
+ smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 0, 1);
}
- preempt_enable();
+
return err;
}
diff --git a/arch/x86/lib/rwlock_64.S b/arch/x86/lib/rwlock_64.S
index 0cde1f807314..05ea55f71405 100644
--- a/arch/x86/lib/rwlock_64.S
+++ b/arch/x86/lib/rwlock_64.S
@@ -2,7 +2,7 @@
#include <linux/linkage.h>
#include <asm/rwlock.h>
-#include <asm/alternative-asm.i>
+#include <asm/alternative-asm.h>
#include <asm/dwarf2.h>
/* rdi: pointer to rwlock_t */
diff --git a/arch/x86/lib/semaphore_32.S b/arch/x86/lib/semaphore_32.S
index c01eb39c0b43..444fba400983 100644
--- a/arch/x86/lib/semaphore_32.S
+++ b/arch/x86/lib/semaphore_32.S
@@ -15,8 +15,8 @@
#include <linux/linkage.h>
#include <asm/rwlock.h>
-#include <asm/alternative-asm.i>
-#include <asm/frame.i>
+#include <asm/alternative-asm.h>
+#include <asm/frame.h>
#include <asm/dwarf2.h>
/*
diff --git a/arch/x86/lib/string_32.c b/arch/x86/lib/string_32.c
index 2c773fefa3dd..c2c0504a3071 100644
--- a/arch/x86/lib/string_32.c
+++ b/arch/x86/lib/string_32.c
@@ -160,26 +160,6 @@ char *strchr(const char * s, int c)
EXPORT_SYMBOL(strchr);
#endif
-#ifdef __HAVE_ARCH_STRRCHR
-char *strrchr(const char * s, int c)
-{
- int d0, d1;
- char * res;
- asm volatile( "movb %%al,%%ah\n"
- "1:\tlodsb\n\t"
- "cmpb %%ah,%%al\n\t"
- "jne 2f\n\t"
- "leal -1(%%esi),%0\n"
- "2:\ttestb %%al,%%al\n\t"
- "jne 1b"
- :"=g" (res), "=&S" (d0), "=&a" (d1)
- :"0" (0),"1" (s),"2" (c)
- :"memory");
- return res;
-}
-EXPORT_SYMBOL(strrchr);
-#endif
-
#ifdef __HAVE_ARCH_STRLEN
size_t strlen(const char * s)
{
diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c
index 9f38b12b4af1..8bab2b2efaff 100644
--- a/arch/x86/lib/usercopy_32.c
+++ b/arch/x86/lib/usercopy_32.c
@@ -748,7 +748,7 @@ survive:
retval = get_user_pages(current, current->mm,
(unsigned long )to, 1, 1, 0, &pg, NULL);
- if (retval == -ENOMEM && is_init(current)) {
+ if (retval == -ENOMEM && is_global_init(current)) {
up_read(&current->mm->mmap_sem);
congestion_wait(WRITE, HZ/50);
goto survive;
diff --git a/arch/x86/mach-default/setup.c b/arch/x86/mach-default/setup.c
index 7f635c7a2381..0c28a071824c 100644
--- a/arch/x86/mach-default/setup.c
+++ b/arch/x86/mach-default/setup.c
@@ -35,7 +35,11 @@ void __init pre_intr_init_hook(void)
/*
* IRQ2 is cascade interrupt to second interrupt controller
*/
-static struct irqaction irq2 = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL};
+static struct irqaction irq2 = {
+ .handler = no_action,
+ .mask = CPU_MASK_NONE,
+ .name = "cascade",
+};
/**
* intr_init_hook - post gate setup interrupt initialisation
@@ -104,7 +108,7 @@ void __init time_init_hook(void)
* mca_nmi_hook - hook into MCA specific NMI chain
*
* Description:
- * The MCA (Microchannel Arcitecture) has an NMI chain for NMI sources
+ * 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.
**/
@@ -127,7 +131,7 @@ static __init int no_ipi_broadcast(char *str)
return 1;
}
-__setup("no_ipi_broadcast", no_ipi_broadcast);
+__setup("no_ipi_broadcast=", no_ipi_broadcast);
static int __init print_ipi_mode(void)
{
@@ -159,16 +163,18 @@ char * __init machine_specific_memory_setup(void)
* Otherwise fake a memory map; one section from 0k->640k,
* the next section from 1mb->appropriate_mem_k
*/
- sanitize_e820_map(E820_MAP, &E820_MAP_NR);
- if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0) {
+ sanitize_e820_map(boot_params.e820_map, &boot_params.e820_entries);
+ if (copy_e820_map(boot_params.e820_map, boot_params.e820_entries)
+ < 0) {
unsigned long mem_size;
/* compare results from other methods and take the greater */
- if (ALT_MEM_K < EXT_MEM_K) {
- mem_size = EXT_MEM_K;
+ if (boot_params.alt_mem_k
+ < boot_params.screen_info.ext_mem_k) {
+ mem_size = boot_params.screen_info.ext_mem_k;
who = "BIOS-88";
} else {
- mem_size = ALT_MEM_K;
+ mem_size = boot_params.alt_mem_k;
who = "BIOS-e801";
}
diff --git a/arch/x86/mach-es7000/es7000plat.c b/arch/x86/mach-es7000/es7000plat.c
index ab99072d3f9a..f5d6f7d8b86e 100644
--- a/arch/x86/mach-es7000/es7000plat.c
+++ b/arch/x86/mach-es7000/es7000plat.c
@@ -46,11 +46,11 @@
* ES7000 Globals
*/
-volatile unsigned long *psai = NULL;
-struct mip_reg *mip_reg;
-struct mip_reg *host_reg;
-int mip_port;
-unsigned long mip_addr, host_addr;
+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;
/*
* GSI override for ES7000 platforms.
@@ -288,28 +288,8 @@ es7000_start_cpu(int cpu, unsigned long eip)
}
-int
-es7000_stop_cpu(int cpu)
-{
- int startup;
-
- if (psai == NULL)
- return -1;
-
- startup= (0x1000000 | cpu);
-
- while ((*psai & 0xff00ffff) != startup)
- ;
-
- startup = (*psai & 0xff0000) >> 16;
- *psai &= 0xffffff;
-
- return 0;
-
-}
-
void __init
-es7000_sw_apic()
+es7000_sw_apic(void)
{
if (es7000_plat) {
int mip_status;
diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c
index 8685208d8512..1af0cc7648f0 100644
--- a/arch/x86/mach-generic/default.c
+++ b/arch/x86/mach-generic/default.c
@@ -1,5 +1,5 @@
/*
- * Default generic APIC driver. This handles upto 8 CPUs.
+ * Default generic APIC driver. This handles up to 8 CPUs.
*/
#define APIC_DEFINITION 1
#include <linux/threads.h>
diff --git a/arch/x86/mach-generic/probe.c b/arch/x86/mach-generic/probe.c
index 74f3da634423..f410d3cb5659 100644
--- a/arch/x86/mach-generic/probe.c
+++ b/arch/x86/mach-generic/probe.c
@@ -22,7 +22,7 @@ extern struct genapic apic_default;
struct genapic *genapic = &apic_default;
-struct genapic *apic_probe[] __initdata = {
+static struct genapic *apic_probe[] __initdata = {
&apic_summit,
&apic_bigsmp,
&apic_es7000,
@@ -56,7 +56,7 @@ void __init generic_bigsmp_probe(void)
/*
* This routine is used to switch to bigsmp mode when
* - There is no apic= option specified by the user
- * - generic_apic_probe() has choosen apic_default as the sub_arch
+ * - generic_apic_probe() has chosen apic_default as the sub_arch
* - we find more than 8 CPUs in acpi LAPIC listing with xAPIC support
*/
diff --git a/arch/x86/mach-visws/setup.c b/arch/x86/mach-visws/setup.c
index 1f81f10e03a0..de4c9dbd086f 100644
--- a/arch/x86/mach-visws/setup.c
+++ b/arch/x86/mach-visws/setup.c
@@ -152,7 +152,7 @@ char * __init machine_specific_memory_setup(void)
{
long long gfx_mem_size = 8 * MB;
- mem_size = ALT_MEM_K;
+ mem_size = boot_params.alt_mem_k;
if (!mem_size) {
printk(KERN_WARNING "Bootloader didn't set memory size, upgrade it !\n");
diff --git a/arch/x86/mach-voyager/setup.c b/arch/x86/mach-voyager/setup.c
index 2b55694e6400..3bef977cb29b 100644
--- a/arch/x86/mach-voyager/setup.c
+++ b/arch/x86/mach-voyager/setup.c
@@ -18,7 +18,11 @@ void __init pre_intr_init_hook(void)
/*
* IRQ2 is cascade interrupt to second interrupt controller
*/
-static struct irqaction irq2 = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL};
+static struct irqaction irq2 = {
+ .handler = no_action,
+ .mask = CPU_MASK_NONE,
+ .name = "cascade",
+};
void __init intr_init_hook(void)
{
@@ -83,7 +87,7 @@ char * __init machine_specific_memory_setup(void)
if(inb(catbase) != VOYAGER_DINO) {
printk(KERN_ERR "Voyager: Failed to get DINO for L4, setting tom to EXT_MEM_K\n");
- tom = (EXT_MEM_K)<<10;
+ tom = (boot_params.screen_info.ext_mem_k)<<10;
}
who = "Voyager-TOM";
add_memory_region(0, 0x9f000, E820_RAM);
@@ -104,16 +108,18 @@ char * __init machine_specific_memory_setup(void)
* Otherwise fake a memory map; one section from 0k->640k,
* the next section from 1mb->appropriate_mem_k
*/
- sanitize_e820_map(E820_MAP, &E820_MAP_NR);
- if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0) {
+ sanitize_e820_map(boot_params.e820_map, &boot_params.e820_entries);
+ if (copy_e820_map(boot_params.e820_map, boot_params.e820_entries)
+ < 0) {
unsigned long mem_size;
/* compare results from other methods and take the greater */
- if (ALT_MEM_K < EXT_MEM_K) {
- mem_size = EXT_MEM_K;
+ if (boot_params.alt_mem_k
+ < boot_params.screen_info.ext_mem_k) {
+ mem_size = boot_params.screen_info.ext_mem_k;
who = "BIOS-88";
} else {
- mem_size = ALT_MEM_K;
+ mem_size = boot_params.alt_mem_k;
who = "BIOS-e801";
}
diff --git a/arch/x86/mach-voyager/voyager_smp.c b/arch/x86/mach-voyager/voyager_smp.c
index b87f8548e75a..69371434b0cf 100644
--- a/arch/x86/mach-voyager/voyager_smp.c
+++ b/arch/x86/mach-voyager/voyager_smp.c
@@ -29,15 +29,15 @@
#include <asm/arch_hooks.h>
/* TLB state -- visible externally, indexed physically */
-DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate) ____cacheline_aligned = { &init_mm, 0 };
+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 */
-struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
-EXPORT_SYMBOL(cpu_data);
+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;
@@ -389,7 +389,7 @@ find_smp_config(void)
/* The boot CPU must be extended */
voyager_extended_vic_processors = 1<<boot_cpu_id;
- /* initially, all of the first 8 cpu's can boot */
+ /* 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 */
@@ -430,7 +430,7 @@ find_smp_config(void)
void __init
smp_store_cpu_info(int id)
{
- struct cpuinfo_x86 *c=&cpu_data[id];
+ struct cpuinfo_x86 *c = &cpu_data(id);
*c = boot_cpu_data;
@@ -442,8 +442,8 @@ static __u32 __init
setup_trampoline(void)
{
/* these two are global symbols in trampoline.S */
- extern __u8 trampoline_end[];
- extern __u8 trampoline_data[];
+ extern const __u8 trampoline_end[];
+ extern const __u8 trampoline_data[];
memcpy((__u8 *)trampoline_base, trampoline_data,
trampoline_end - trampoline_data);
@@ -634,7 +634,7 @@ do_boot_cpu(__u8 cpu)
cpu, smp_processor_id()));
printk("CPU%d: ", cpu);
- print_cpu_info(&cpu_data[cpu]);
+ print_cpu_info(&cpu_data(cpu));
wmb();
cpu_set(cpu, cpu_callout_map);
cpu_set(cpu, cpu_present_map);
@@ -683,7 +683,7 @@ smp_boot_cpus(void)
*/
smp_store_cpu_info(boot_cpu_id);
printk("CPU%d: ", boot_cpu_id);
- print_cpu_info(&cpu_data[boot_cpu_id]);
+ print_cpu_info(&cpu_data(boot_cpu_id));
if(is_cpu_quad()) {
/* booting on a Quad CPU */
@@ -714,7 +714,7 @@ smp_boot_cpus(void)
unsigned long bogosum = 0;
for (i = 0; i < NR_CPUS; i++)
if (cpu_isset(i, cpu_online_map))
- bogosum += cpu_data[i].loops_per_jiffy;
+ bogosum += cpu_data(i).loops_per_jiffy;
printk(KERN_INFO "Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
cpucount+1,
bogosum/(500000/HZ),
@@ -1010,7 +1010,7 @@ static struct call_data_struct * call_data;
/* 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 CPU's - set up the function then broadcast a
+ * 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)
@@ -1037,6 +1037,7 @@ smp_call_function_interrupt(void)
*/
irq_enter();
(*func)(info);
+ __get_cpu_var(irq_stat).irq_call_count++;
irq_exit();
if (wait) {
mb();
@@ -1094,7 +1095,7 @@ voyager_smp_call_function_mask (cpumask_t cpumask,
* CPI here. We don't use this actually for counting so losing
* ticks doesn't matter
*
- * FIXME: For those CPU's which actually have a local APIC, we could
+ * 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
@@ -1286,7 +1287,7 @@ smp_local_timer_interrupt(void)
/*
* We take the 'long' return path, and there every subsystem
- * grabs the apropriate locks (kernel lock/ irq lock).
+ * 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.
@@ -1758,7 +1759,7 @@ set_vic_irq_affinity(unsigned int irq, cpumask_t mask)
real_mask = cpus_addr(mask)[0] & voyager_extended_vic_processors;
if(cpus_addr(mask)[0] == 0)
- /* can't have no cpu's to accept the interrupt -- extremely
+ /* can't have no CPUs to accept the interrupt -- extremely
* bad things will happen */
return;
@@ -1790,7 +1791,7 @@ set_vic_irq_affinity(unsigned int irq, cpumask_t mask)
}
/* this is magic, we now have the correct affinity maps, so
* enable the interrupt. This will send an enable CPI to
- * those cpu's who need to enable it in their local masks,
+ * 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
diff --git a/arch/x86/mach-voyager/voyager_thread.c b/arch/x86/mach-voyager/voyager_thread.c
index f9d595338159..50f9366c411e 100644
--- a/arch/x86/mach-voyager/voyager_thread.c
+++ b/arch/x86/mach-voyager/voyager_thread.c
@@ -64,7 +64,7 @@ check_from_kernel(void)
{
if(voyager_status.switch_off) {
- /* FIXME: This should be configureable via proc */
+ /* 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"));
diff --git a/arch/x86/math-emu/Makefile b/arch/x86/math-emu/Makefile
index 9c943fa6ce6b..9b0c63b60302 100644
--- a/arch/x86/math-emu/Makefile
+++ b/arch/x86/math-emu/Makefile
@@ -5,8 +5,7 @@
#DEBUG = -DDEBUGGING
DEBUG =
PARANOID = -DPARANOID
-CFLAGS := $(CFLAGS) $(PARANOID) $(DEBUG) -fno-builtin $(MATH_EMULATION)
-
+EXTRA_CFLAGS := $(PARANOID) $(DEBUG) -fno-builtin $(MATH_EMULATION)
EXTRA_AFLAGS := $(PARANOID)
# From 'C' language sources:
diff --git a/arch/x86/mm/boot_ioremap_32.c b/arch/x86/mm/boot_ioremap_32.c
index 4de95a17a7d4..f14da2a53ece 100644
--- a/arch/x86/mm/boot_ioremap_32.c
+++ b/arch/x86/mm/boot_ioremap_32.c
@@ -10,7 +10,7 @@
/*
* We need to use the 2-level pagetable functions, but CONFIG_X86_PAE
- * keeps that from happenning. If anyone has a better way, I'm listening.
+ * keeps that from happening. If anyone has a better way, I'm listening.
*
* boot_pte_t is defined only if this all works correctly
*/
diff --git a/arch/x86/mm/discontig_32.c b/arch/x86/mm/discontig_32.c
index 860e912a3fbb..13a474d3c6e9 100644
--- a/arch/x86/mm/discontig_32.c
+++ b/arch/x86/mm/discontig_32.c
@@ -40,7 +40,7 @@
struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
EXPORT_SYMBOL(node_data);
-bootmem_data_t node0_bdata;
+static bootmem_data_t node0_bdata;
/*
* numa interface - we expect the numa architecture specific code to have
@@ -103,14 +103,14 @@ extern unsigned long highend_pfn, highstart_pfn;
#define LARGE_PAGE_BYTES (PTRS_PER_PTE * PAGE_SIZE)
-unsigned long node_remap_start_pfn[MAX_NUMNODES];
+static unsigned long node_remap_start_pfn[MAX_NUMNODES];
unsigned long node_remap_size[MAX_NUMNODES];
-unsigned long node_remap_offset[MAX_NUMNODES];
-void *node_remap_start_vaddr[MAX_NUMNODES];
+static unsigned long node_remap_offset[MAX_NUMNODES];
+static void *node_remap_start_vaddr[MAX_NUMNODES];
void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags);
-void *node_remap_end_vaddr[MAX_NUMNODES];
-void *node_remap_alloc_vaddr[MAX_NUMNODES];
+static void *node_remap_end_vaddr[MAX_NUMNODES];
+static void *node_remap_alloc_vaddr[MAX_NUMNODES];
static unsigned long kva_start_pfn;
static unsigned long kva_pages;
/*
@@ -273,7 +273,7 @@ unsigned long __init setup_memory(void)
* When mapping a NUMA machine we allocate the node_mem_map arrays
* from node local memory. They are then mapped directly into KVA
* between zone normal and vmalloc space. Calculate the size of
- * this space and use it to adjust the boundry between ZONE_NORMAL
+ * this space and use it to adjust the boundary between ZONE_NORMAL
* and ZONE_HIGHMEM.
*/
find_max_pfn();
@@ -288,8 +288,9 @@ unsigned long __init setup_memory(void)
#ifdef CONFIG_BLK_DEV_INITRD
/* Numa kva area is below the initrd */
- if (LOADER_TYPE && INITRD_START)
- kva_start_pfn = PFN_DOWN(INITRD_START) - kva_pages;
+ if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image)
+ kva_start_pfn = PFN_DOWN(boot_params.hdr.ramdisk_image)
+ - kva_pages;
#endif
kva_start_pfn -= kva_start_pfn & (PTRS_PER_PTE-1);
@@ -403,7 +404,7 @@ void __init set_highmem_pages_init(int bad_ppro)
}
#ifdef CONFIG_MEMORY_HOTPLUG
-int paddr_to_nid(u64 addr)
+static int paddr_to_nid(u64 addr)
{
int nid;
unsigned long pfn = PFN_DOWN(addr);
diff --git a/arch/x86/mm/fault_32.c b/arch/x86/mm/fault_32.c
index fcb38e7f3543..a2273d44aa27 100644
--- a/arch/x86/mm/fault_32.c
+++ b/arch/x86/mm/fault_32.c
@@ -25,6 +25,7 @@
#include <linux/kprobes.h>
#include <linux/uaccess.h>
#include <linux/kdebug.h>
+#include <linux/kprobes.h>
#include <asm/system.h>
#include <asm/desc.h>
@@ -32,33 +33,27 @@
extern void die(const char *,struct pt_regs *,long);
-static ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
-
-int register_page_fault_notifier(struct notifier_block *nb)
+#ifdef CONFIG_KPROBES
+static inline int notify_page_fault(struct pt_regs *regs)
{
- vmalloc_sync_all();
- return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
-}
-EXPORT_SYMBOL_GPL(register_page_fault_notifier);
+ int ret = 0;
+
+ /* kprobe_running() needs smp_processor_id() */
+ if (!user_mode_vm(regs)) {
+ preempt_disable();
+ if (kprobe_running() && kprobe_fault_handler(regs, 14))
+ ret = 1;
+ preempt_enable();
+ }
-int unregister_page_fault_notifier(struct notifier_block *nb)
-{
- return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb);
+ return ret;
}
-EXPORT_SYMBOL_GPL(unregister_page_fault_notifier);
-
-static inline int notify_page_fault(struct pt_regs *regs, long err)
+#else
+static inline int notify_page_fault(struct pt_regs *regs)
{
- struct die_args args = {
- .regs = regs,
- .str = "page fault",
- .err = err,
- .trapnr = 14,
- .signr = SIGSEGV
- };
- return atomic_notifier_call_chain(&notify_page_fault_chain,
- DIE_PAGE_FAULT, &args);
+ return 0;
}
+#endif
/*
* Return EIP plus the CS segment base. The segment limit is also
@@ -110,7 +105,7 @@ static inline unsigned long get_segment_eip(struct pt_regs *regs,
LDT and other horrors are only used in user space. */
if (seg & (1<<2)) {
/* Must lock the LDT while reading it. */
- down(&current->mm->context.sem);
+ mutex_lock(&current->mm->context.lock);
desc = current->mm->context.ldt;
desc = (void *)desc + (seg & ~7);
} else {
@@ -123,7 +118,7 @@ static inline unsigned long get_segment_eip(struct pt_regs *regs,
base = get_desc_base((unsigned long *)desc);
if (seg & (1<<2)) {
- up(&current->mm->context.sem);
+ mutex_unlock(&current->mm->context.lock);
} else
put_cpu();
@@ -308,6 +303,11 @@ fastcall void __kprobes do_page_fault(struct pt_regs *regs,
int write, si_code;
int fault;
+ /*
+ * We can fault from pretty much anywhere, with unknown IRQ state.
+ */
+ trace_hardirqs_fixup();
+
/* get the address */
address = read_cr2();
@@ -331,7 +331,7 @@ fastcall void __kprobes do_page_fault(struct pt_regs *regs,
if (unlikely(address >= TASK_SIZE)) {
if (!(error_code & 0x0000000d) && vmalloc_fault(address) >= 0)
return;
- if (notify_page_fault(regs, error_code) == NOTIFY_STOP)
+ if (notify_page_fault(regs))
return;
/*
* Don't take the mm semaphore here. If we fixup a prefetch
@@ -340,7 +340,7 @@ fastcall void __kprobes do_page_fault(struct pt_regs *regs,
goto bad_area_nosemaphore;
}
- if (notify_page_fault(regs, error_code) == NOTIFY_STOP)
+ if (notify_page_fault(regs))
return;
/* It's safe to allow irq's after cr2 has been saved and the vmalloc
@@ -359,7 +359,7 @@ fastcall void __kprobes do_page_fault(struct pt_regs *regs,
/* 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. Unfortunatly, in the case of an
+ * 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
@@ -367,7 +367,7 @@ fastcall void __kprobes do_page_fault(struct pt_regs *regs,
* exceptions table.
*
* As the vast majority of faults will be valid we will only perform
- * the source reference check when there is a possibilty of a 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.
@@ -476,8 +476,8 @@ bad_area_nosemaphore:
printk_ratelimit()) {
printk("%s%s[%d]: segfault at %08lx eip %08lx "
"esp %08lx error %lx\n",
- tsk->pid > 1 ? KERN_INFO : KERN_EMERG,
- tsk->comm, tsk->pid, address, regs->eip,
+ task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG,
+ tsk->comm, task_pid_nr(tsk), address, regs->eip,
regs->esp, error_code);
}
tsk->thread.cr2 = address;
@@ -544,23 +544,22 @@ no_context:
printk(KERN_ALERT "BUG: unable to handle kernel paging"
" request");
printk(" at virtual address %08lx\n",address);
- printk(KERN_ALERT " printing eip:\n");
- printk("%08lx\n", regs->eip);
+ printk(KERN_ALERT "printing eip: %08lx ", regs->eip);
page = read_cr3();
page = ((__typeof__(page) *) __va(page))[address >> PGDIR_SHIFT];
#ifdef CONFIG_X86_PAE
- printk(KERN_ALERT "*pdpt = %016Lx\n", page);
+ 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)];
- printk(KERN_ALERT "*pde = %016Lx\n", page);
+ printk(KERN_CONT "*pde = %016Lx ", page);
page &= ~_PAGE_NX;
}
#else
- printk(KERN_ALERT "*pde = %08lx\n", page);
+ printk("*pde = %08lx ", page);
#endif
/*
@@ -570,12 +569,15 @@ no_context:
* it's allocated already.
*/
if ((page >> PAGE_SHIFT) < max_low_pfn
- && (page & _PAGE_PRESENT)) {
+ && (page & _PAGE_PRESENT)
+ && !(page & _PAGE_PSE)) {
page &= PAGE_MASK;
page = ((__typeof__(page) *) __va(page))[(address >> PAGE_SHIFT)
& (PTRS_PER_PTE - 1)];
- printk(KERN_ALERT "*pte = %0*Lx\n", sizeof(page)*2, (u64)page);
+ printk("*pte = %0*Lx ", sizeof(page)*2, (u64)page);
}
+
+ printk("\n");
}
tsk->thread.cr2 = address;
@@ -591,14 +593,14 @@ no_context:
*/
out_of_memory:
up_read(&mm->mmap_sem);
- if (is_init(tsk)) {
+ if (is_global_init(tsk)) {
yield();
down_read(&mm->mmap_sem);
goto survive;
}
printk("VM: killing process %s\n", tsk->comm);
if (error_code & 4)
- do_exit(SIGKILL);
+ do_group_exit(SIGKILL);
goto no_context;
do_sigbus:
diff --git a/arch/x86/mm/fault_64.c b/arch/x86/mm/fault_64.c
index 54816adb8e93..0e26230669ca 100644
--- a/arch/x86/mm/fault_64.c
+++ b/arch/x86/mm/fault_64.c
@@ -25,6 +25,7 @@
#include <linux/kprobes.h>
#include <linux/uaccess.h>
#include <linux/kdebug.h>
+#include <linux/kprobes.h>
#include <asm/system.h>
#include <asm/pgalloc.h>
@@ -40,34 +41,27 @@
#define PF_RSVD (1<<3)
#define PF_INSTR (1<<4)
-static ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
-
-/* Hook to register for page fault notifications */
-int register_page_fault_notifier(struct notifier_block *nb)
+#ifdef CONFIG_KPROBES
+static inline int notify_page_fault(struct pt_regs *regs)
{
- vmalloc_sync_all();
- return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
-}
-EXPORT_SYMBOL_GPL(register_page_fault_notifier);
+ int ret = 0;
+
+ /* kprobe_running() needs smp_processor_id() */
+ if (!user_mode(regs)) {
+ preempt_disable();
+ if (kprobe_running() && kprobe_fault_handler(regs, 14))
+ ret = 1;
+ preempt_enable();
+ }
-int unregister_page_fault_notifier(struct notifier_block *nb)
-{
- return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb);
+ return ret;
}
-EXPORT_SYMBOL_GPL(unregister_page_fault_notifier);
-
-static inline int notify_page_fault(struct pt_regs *regs, long err)
+#else
+static inline int notify_page_fault(struct pt_regs *regs)
{
- struct die_args args = {
- .regs = regs,
- .str = "page fault",
- .err = err,
- .trapnr = 14,
- .signr = SIGSEGV
- };
- return atomic_notifier_call_chain(&notify_page_fault_chain,
- DIE_PAGE_FAULT, &args);
+ return 0;
}
+#endif
/* Sometimes the CPU reports invalid exceptions on prefetch.
Check that here and ignore.
@@ -175,7 +169,7 @@ void dump_pagetable(unsigned long address)
pmd = pmd_offset(pud, address);
if (bad_address(pmd)) goto bad;
printk("PMD %lx ", pmd_val(*pmd));
- if (!pmd_present(*pmd)) goto ret;
+ if (!pmd_present(*pmd) || pmd_large(*pmd)) goto ret;
pte = pte_offset_kernel(pmd, address);
if (bad_address(pte)) goto bad;
@@ -291,7 +285,6 @@ static int vmalloc_fault(unsigned long address)
return 0;
}
-static int page_fault_trace;
int show_unhandled_signals = 1;
/*
@@ -311,6 +304,11 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
unsigned long flags;
siginfo_t info;
+ /*
+ * We can fault from pretty much anywhere, with unknown IRQ state.
+ */
+ trace_hardirqs_fixup();
+
tsk = current;
mm = tsk->mm;
prefetchw(&mm->mmap_sem);
@@ -345,7 +343,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
if (vmalloc_fault(address) >= 0)
return;
}
- if (notify_page_fault(regs, error_code) == NOTIFY_STOP)
+ if (notify_page_fault(regs))
return;
/*
* Don't take the mm semaphore here. If we fixup a prefetch
@@ -354,16 +352,12 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
goto bad_area_nosemaphore;
}
- if (notify_page_fault(regs, error_code) == NOTIFY_STOP)
+ if (notify_page_fault(regs))
return;
if (likely(regs->eflags & X86_EFLAGS_IF))
local_irq_enable();
- if (unlikely(page_fault_trace))
- printk("pagefault rip:%lx rsp:%lx cs:%lu ss:%lu address %lx error %lx\n",
- regs->rip,regs->rsp,regs->cs,regs->ss,address,error_code);
-
if (unlikely(error_code & PF_RSVD))
pgtable_bad(address, regs, error_code);
@@ -384,7 +378,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
again:
/* 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. Unfortunatly, in the case of an
+ * 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
@@ -392,7 +386,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
* exceptions table.
*
* As the vast majority of faults will be valid we will only perform
- * the source reference check when there is a possibilty of a 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.
@@ -494,7 +488,7 @@ bad_area_nosemaphore:
if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
printk_ratelimit()) {
printk(
- "%s%s[%d]: segfault at %016lx rip %016lx rsp %016lx error %lx\n",
+ "%s%s[%d]: segfault at %lx rip %lx rsp %lx error %lx\n",
tsk->pid > 1 ? KERN_INFO : KERN_EMERG,
tsk->comm, tsk->pid, address, regs->rip,
regs->rsp, error_code);
@@ -560,7 +554,7 @@ no_context:
*/
out_of_memory:
up_read(&mm->mmap_sem);
- if (is_init(current)) {
+ if (is_global_init(current)) {
yield();
goto again;
}
@@ -627,10 +621,3 @@ void vmalloc_sync_all(void)
BUILD_BUG_ON(!(((MODULES_END - 1) & PGDIR_MASK) ==
(__START_KERNEL & PGDIR_MASK)));
}
-
-static int __init enable_pagefaulttrace(char *str)
-{
- page_fault_trace = 1;
- return 1;
-}
-__setup("pagefaulttrace", enable_pagefaulttrace);
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
index 730a5b177b1f..c7d19471261d 100644
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -85,13 +85,20 @@ static pmd_t * __init one_md_table_init(pgd_t *pgd)
static pte_t * __init one_page_table_init(pmd_t *pmd)
{
if (!(pmd_val(*pmd) & _PAGE_PRESENT)) {
- pte_t *page_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+ pte_t *page_table = NULL;
+
+#ifdef CONFIG_DEBUG_PAGEALLOC
+ page_table = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
+#endif
+ if (!page_table)
+ page_table =
+ (pte_t *)alloc_bootmem_low_pages(PAGE_SIZE);
paravirt_alloc_pt(&init_mm, __pa(page_table) >> PAGE_SHIFT);
set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));
BUG_ON(page_table != pte_offset_kernel(pmd, 0));
}
-
+
return pte_offset_kernel(pmd, 0);
}
@@ -735,35 +742,18 @@ int arch_add_memory(int nid, u64 start, u64 size)
return __add_pages(zone, start_pfn, nr_pages);
}
-int remove_memory(u64 start, u64 size)
-{
- return -EINVAL;
-}
-EXPORT_SYMBOL_GPL(remove_memory);
#endif
struct kmem_cache *pmd_cache;
void __init pgtable_cache_init(void)
{
- size_t pgd_size = PTRS_PER_PGD*sizeof(pgd_t);
-
- if (PTRS_PER_PMD > 1) {
+ if (PTRS_PER_PMD > 1)
pmd_cache = kmem_cache_create("pmd",
- PTRS_PER_PMD*sizeof(pmd_t),
- PTRS_PER_PMD*sizeof(pmd_t),
- SLAB_PANIC,
- pmd_ctor);
- if (!SHARED_KERNEL_PMD) {
- /* If we're in PAE mode and have a non-shared
- kernel pmd, then the pgd size must be a
- page size. This is because the pgd_list
- links through the page structure, so there
- can only be one pgd per page for this to
- work. */
- pgd_size = PAGE_SIZE;
- }
- }
+ PTRS_PER_PMD*sizeof(pmd_t),
+ PTRS_PER_PMD*sizeof(pmd_t),
+ SLAB_PANIC,
+ pmd_ctor);
}
/*
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 458893b376f8..a7308b2cd058 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -474,12 +474,6 @@ error:
}
EXPORT_SYMBOL_GPL(arch_add_memory);
-int remove_memory(u64 start, u64 size)
-{
- return -EINVAL;
-}
-EXPORT_SYMBOL_GPL(remove_memory);
-
#if !defined(CONFIG_ACPI_NUMA) && defined(CONFIG_NUMA)
int memory_add_physaddr_to_nid(u64 start)
{
@@ -734,12 +728,6 @@ int in_gate_area_no_task(unsigned long addr)
return (addr >= VSYSCALL_START) && (addr < VSYSCALL_END);
}
-void * __init alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size)
-{
- return __alloc_bootmem_core(pgdat->bdata, size,
- SMP_CACHE_BYTES, (4UL*1024*1024*1024), 0);
-}
-
const char *arch_vma_name(struct vm_area_struct *vma)
{
if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso)
@@ -748,3 +736,48 @@ const char *arch_vma_name(struct vm_area_struct *vma)
return "[vsyscall]";
return NULL;
}
+
+#ifdef CONFIG_SPARSEMEM_VMEMMAP
+/*
+ * Initialise the sparsemem vmemmap using huge-pages at the PMD level.
+ */
+int __meminit vmemmap_populate(struct page *start_page,
+ unsigned long size, int node)
+{
+ unsigned long addr = (unsigned long)start_page;
+ unsigned long end = (unsigned long)(start_page + size);
+ unsigned long next;
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+
+ for (; addr < end; addr = next) {
+ next = pmd_addr_end(addr, end);
+
+ pgd = vmemmap_pgd_populate(addr, node);
+ if (!pgd)
+ return -ENOMEM;
+ pud = vmemmap_pud_populate(pgd, addr, node);
+ if (!pud)
+ return -ENOMEM;
+
+ pmd = pmd_offset(pud, addr);
+ if (pmd_none(*pmd)) {
+ pte_t entry;
+ void *p = vmemmap_alloc_block(PMD_SIZE, node);
+ if (!p)
+ return -ENOMEM;
+
+ entry = pfn_pte(__pa(p) >> PAGE_SHIFT, PAGE_KERNEL);
+ mk_pte_huge(entry);
+ set_pmd(pmd, __pmd(pte_val(entry)));
+
+ printk(KERN_DEBUG " [%lx-%lx] PMD ->%p on node %d\n",
+ addr, addr + PMD_SIZE - 1, p, node);
+ } else
+ vmemmap_verify((pte_t *)pmd, node, addr, next);
+ }
+
+ return 0;
+}
+#endif
diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c
index 6da235522269..3d6926ba8995 100644
--- a/arch/x86/mm/numa_64.c
+++ b/arch/x86/mm/numa_64.c
@@ -166,7 +166,7 @@ early_node_mem(int nodeid, unsigned long start, unsigned long end,
return __va(mem);
ptr = __alloc_bootmem_nopanic(size,
SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS));
- if (ptr == 0) {
+ if (ptr == NULL) {
printk(KERN_ERR "Cannot find %lu bytes in node %d\n",
size, nodeid);
return NULL;
@@ -261,7 +261,7 @@ void __init numa_init_array(void)
We round robin the existing nodes. */
rr = first_node(node_online_map);
for (i = 0; i < NR_CPUS; i++) {
- if (cpu_to_node[i] != NUMA_NO_NODE)
+ if (cpu_to_node(i) != NUMA_NO_NODE)
continue;
numa_set_node(i, rr);
rr = next_node(rr, node_online_map);
@@ -543,7 +543,7 @@ __cpuinit void numa_add_cpu(int cpu)
void __cpuinit numa_set_node(int cpu, int node)
{
cpu_pda(cpu)->nodenumber = node;
- cpu_to_node[cpu] = node;
+ cpu_to_node(cpu) = node;
}
unsigned long __init numa_free_all_bootmem(void)
@@ -612,7 +612,7 @@ void __init init_cpu_to_node(void)
{
int i;
for (i = 0; i < NR_CPUS; i++) {
- u8 apicid = x86_cpu_to_apicid[i];
+ u8 apicid = x86_cpu_to_apicid_init[i];
if (apicid == BAD_APICID)
continue;
if (apicid_to_node[apicid] == NUMA_NO_NODE)
diff --git a/arch/x86/mm/pageattr_32.c b/arch/x86/mm/pageattr_32.c
index 4241a74d16c8..260073c07600 100644
--- a/arch/x86/mm/pageattr_32.c
+++ b/arch/x86/mm/pageattr_32.c
@@ -70,10 +70,10 @@ static struct page *split_large_page(unsigned long address, pgprot_t prot,
static void cache_flush_page(struct page *p)
{
- unsigned long adr = (unsigned long)page_address(p);
+ void *adr = page_address(p);
int i;
for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size)
- asm volatile("clflush (%0)" :: "r" (adr + i));
+ clflush(adr+i);
}
static void flush_kernel_map(void *arg)
diff --git a/arch/x86/mm/pageattr_64.c b/arch/x86/mm/pageattr_64.c
index 10b9809ce821..c40afbaaf93d 100644
--- a/arch/x86/mm/pageattr_64.c
+++ b/arch/x86/mm/pageattr_64.c
@@ -61,11 +61,11 @@ static struct page *split_large_page(unsigned long address, pgprot_t prot,
return base;
}
-static void cache_flush_page(void *adr)
+void clflush_cache_range(void *adr, int size)
{
int i;
- for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size)
- asm volatile("clflush (%0)" :: "r" (adr + i));
+ for (i = 0; i < size; i += boot_cpu_data.x86_clflush_size)
+ clflush(adr+i);
}
static void flush_kernel_map(void *arg)
@@ -80,7 +80,7 @@ static void flush_kernel_map(void *arg)
asm volatile("wbinvd" ::: "memory");
else list_for_each_entry(pg, l, lru) {
void *adr = page_address(pg);
- cache_flush_page(adr);
+ clflush_cache_range(adr, PAGE_SIZE);
}
__flush_tlb_all();
}
@@ -148,6 +148,7 @@ __change_page_attr(unsigned long address, unsigned long pfn, pgprot_t prot,
split = split_large_page(address, prot, ref_prot2);
if (!split)
return -ENOMEM;
+ pgprot_val(ref_prot2) &= ~_PAGE_NX;
set_pte(kpte, mk_pte(split, ref_prot2));
kpte_page = split;
}
@@ -229,9 +230,14 @@ void global_flush_tlb(void)
struct page *pg, *next;
struct list_head l;
- down_read(&init_mm.mmap_sem);
+ /*
+ * Write-protect the semaphore, to exclude two contexts
+ * doing a list_replace_init() call in parallel and to
+ * exclude new additions to the deferred_pages list:
+ */
+ down_write(&init_mm.mmap_sem);
list_replace_init(&deferred_pages, &l);
- up_read(&init_mm.mmap_sem);
+ up_write(&init_mm.mmap_sem);
flush_map(&l);
diff --git a/arch/x86/mm/pgtable_32.c b/arch/x86/mm/pgtable_32.c
index 01437c46baae..be61a1d845a4 100644
--- a/arch/x86/mm/pgtable_32.c
+++ b/arch/x86/mm/pgtable_32.c
@@ -6,6 +6,7 @@
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/mm.h>
+#include <linux/nmi.h>
#include <linux/swap.h>
#include <linux/smp.h>
#include <linux/highmem.h>
@@ -39,6 +40,8 @@ void show_mem(void)
for_each_online_pgdat(pgdat) {
pgdat_resize_lock(pgdat, &flags);
for (i = 0; i < pgdat->node_spanned_pages; ++i) {
+ if (unlikely(i % MAX_ORDER_NR_PAGES == 0))
+ touch_nmi_watchdog();
page = pgdat_page_nr(pgdat, i);
total++;
if (PageHighMem(page))
@@ -97,8 +100,7 @@ static void set_pte_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags)
}
pte = pte_offset_kernel(pmd, vaddr);
if (pgprot_val(flags))
- /* <pfn,flags> stored as-is, to permit clearing entries */
- set_pte(pte, pfn_pte(pfn, flags));
+ set_pte_present(&init_mm, vaddr, pte, pfn_pte(pfn, flags));
else
pte_clear(&init_mm, vaddr, pte);
@@ -193,7 +195,7 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
return pte;
}
-void pmd_ctor(void *pmd, struct kmem_cache *cache, unsigned long flags)
+void pmd_ctor(struct kmem_cache *cache, void *pmd)
{
memset(pmd, 0, PTRS_PER_PMD*sizeof(pmd_t));
}
diff --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c
index acdf03e19146..ea85172fc0cc 100644
--- a/arch/x86/mm/srat_64.c
+++ b/arch/x86/mm/srat_64.c
@@ -218,7 +218,7 @@ static inline int save_add_info(void) {return 0;}
/*
* Update nodes_add and decide if to include add are in the zone.
* Both SPARSE and RESERVE need nodes_add infomation.
- * This code supports one contigious hot add area per node.
+ * This code supports one contiguous hot add area per node.
*/
static int reserve_hotadd(int node, unsigned long start, unsigned long end)
{
@@ -431,9 +431,9 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end)
setup_node_bootmem(i, nodes[i].start, nodes[i].end);
for (i = 0; i < NR_CPUS; i++) {
- if (cpu_to_node[i] == NUMA_NO_NODE)
+ if (cpu_to_node(i) == NUMA_NO_NODE)
continue;
- if (!node_isset(cpu_to_node[i], node_possible_map))
+ if (!node_isset(cpu_to_node(i), node_possible_map))
numa_set_node(i, NUMA_NO_NODE);
}
numa_init_array();
diff --git a/arch/x86/oprofile/Kconfig b/arch/x86/oprofile/Kconfig
deleted file mode 100644
index d8a84088471a..000000000000
--- a/arch/x86/oprofile/Kconfig
+++ /dev/null
@@ -1,17 +0,0 @@
-config PROFILING
- bool "Profiling support (EXPERIMENTAL)"
- help
- Say Y here to enable the extended profiling support mechanisms used
- by profilers such as OProfile.
-
-
-config OPROFILE
- tristate "OProfile system profiling (EXPERIMENTAL)"
- depends on PROFILING
- help
- OProfile is a profiling system capable of profiling the
- whole system, include the kernel, kernel modules, libraries,
- and applications.
-
- If unsure, say N.
-
diff --git a/arch/x86/oprofile/backtrace.c b/arch/x86/oprofile/backtrace.c
index c049ce414f01..0ed046a187f7 100644
--- a/arch/x86/oprofile/backtrace.c
+++ b/arch/x86/oprofile/backtrace.c
@@ -13,25 +13,45 @@
#include <linux/mm.h>
#include <asm/ptrace.h>
#include <asm/uaccess.h>
+#include <asm/stacktrace.h>
-struct frame_head {
- struct frame_head * ebp;
- unsigned long ret;
-} __attribute__((packed));
+static void backtrace_warning_symbol(void *data, char *msg,
+ unsigned long symbol)
+{
+ /* Ignore warnings */
+}
-static struct frame_head *
-dump_kernel_backtrace(struct frame_head * head)
+static void backtrace_warning(void *data, char *msg)
{
- oprofile_add_trace(head->ret);
+ /* Ignore warnings */
+}
- /* frame pointers should strictly progress back up the stack
- * (towards higher addresses) */
- if (head >= head->ebp)
- return NULL;
+static int backtrace_stack(void *data, char *name)
+{
+ /* Yes, we want all stacks */
+ return 0;
+}
+
+static void backtrace_address(void *data, unsigned long addr)
+{
+ unsigned int *depth = data;
- return head->ebp;
+ if ((*depth)--)
+ oprofile_add_trace(addr);
}
+static struct stacktrace_ops backtrace_ops = {
+ .warning = backtrace_warning,
+ .warning_symbol = backtrace_warning_symbol,
+ .stack = backtrace_stack,
+ .address = backtrace_address,
+};
+
+struct frame_head {
+ struct frame_head *ebp;
+ unsigned long ret;
+} __attribute__((packed));
+
static struct frame_head *
dump_user_backtrace(struct frame_head * head)
{
@@ -53,72 +73,16 @@ dump_user_backtrace(struct frame_head * head)
return bufhead[0].ebp;
}
-/*
- * | | /\ Higher addresses
- * | |
- * --------------- stack base (address of current_thread_info)
- * | thread info |
- * . .
- * | stack |
- * --------------- saved regs->ebp value if valid (frame_head address)
- * . .
- * --------------- saved regs->rsp value if x86_64
- * | |
- * --------------- struct pt_regs * stored on stack if 32-bit
- * | |
- * . .
- * | |
- * --------------- %esp
- * | |
- * | | \/ Lower addresses
- *
- * Thus, regs (or regs->rsp for x86_64) <-> stack base restricts the
- * valid(ish) ebp values. Note: (1) for x86_64, NMI and several other
- * exceptions use special stacks, maintained by the interrupt stack table
- * (IST). These stacks are set up in trap_init() in
- * arch/x86_64/kernel/traps.c. Thus, for x86_64, regs now does not point
- * to the kernel stack; instead, it points to some location on the NMI
- * stack. On the other hand, regs->rsp is the stack pointer saved when the
- * NMI occurred. (2) For 32-bit, regs->esp is not valid because the
- * processor does not save %esp on the kernel stack when interrupts occur
- * in the kernel mode.
- */
-#ifdef CONFIG_FRAME_POINTER
-static int valid_kernel_stack(struct frame_head * head, struct pt_regs * regs)
-{
- unsigned long headaddr = (unsigned long)head;
-#ifdef CONFIG_X86_64
- unsigned long stack = (unsigned long)regs->rsp;
-#else
- unsigned long stack = (unsigned long)regs;
-#endif
- unsigned long stack_base = (stack & ~(THREAD_SIZE - 1)) + THREAD_SIZE;
-
- return headaddr > stack && headaddr < stack_base;
-}
-#else
-/* without fp, it's just junk */
-static int valid_kernel_stack(struct frame_head * head, struct pt_regs * regs)
-{
- return 0;
-}
-#endif
-
-
void
x86_backtrace(struct pt_regs * const regs, unsigned int depth)
{
- struct frame_head *head;
-
-#ifdef CONFIG_X86_64
- head = (struct frame_head *)regs->rbp;
-#else
- head = (struct frame_head *)regs->ebp;
-#endif
+ struct frame_head *head = (struct frame_head *)frame_pointer(regs);
+ unsigned long stack = stack_pointer(regs);
if (!user_mode_vm(regs)) {
- while (depth-- && valid_kernel_stack(head, regs))
- head = dump_kernel_backtrace(head);
+ if (depth)
+ dump_trace(NULL, regs, (unsigned long *)stack,
+ &backtrace_ops, &depth);
return;
}
diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c
index 11b7a51566a8..2d0eeac7251f 100644
--- a/arch/x86/oprofile/nmi_int.c
+++ b/arch/x86/oprofile/nmi_int.c
@@ -269,7 +269,6 @@ static void nmi_cpu_shutdown(void * dummy)
apic_write(APIC_LVTPC, saved_lvtpc[cpu]);
apic_write(APIC_LVTERR, v);
nmi_restore_registers(msrs);
- model->shutdown(msrs);
}
@@ -278,6 +277,7 @@ static void nmi_shutdown(void)
nmi_enabled = 0;
on_each_cpu(nmi_cpu_shutdown, NULL, 0, 1);
unregister_die_notifier(&profile_exceptions_nb);
+ model->shutdown(cpu_msrs);
free_msrs();
}
diff --git a/arch/x86/oprofile/op_model_p4.c b/arch/x86/oprofile/op_model_p4.c
index 47925927b12f..56b4757a1f47 100644
--- a/arch/x86/oprofile/op_model_p4.c
+++ b/arch/x86/oprofile/op_model_p4.c
@@ -379,7 +379,7 @@ static unsigned int get_stagger(void)
{
#ifdef CONFIG_SMP
int cpu = smp_processor_id();
- return (cpu != first_cpu(cpu_sibling_map[cpu]));
+ return (cpu != first_cpu(per_cpu(cpu_sibling_map, cpu)));
#endif
return 0;
}
diff --git a/arch/x86/oprofile/op_x86_model.h b/arch/x86/oprofile/op_x86_model.h
index abb1aa95b979..45b605fa71d0 100644
--- a/arch/x86/oprofile/op_x86_model.h
+++ b/arch/x86/oprofile/op_x86_model.h
@@ -29,7 +29,7 @@ struct op_msrs {
struct pt_regs;
/* The model vtable abstracts the differences between
- * various x86 CPU model's perfctr support.
+ * various x86 CPU models' perfctr support.
*/
struct op_x86_model_spec {
unsigned int const num_counters;
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 2d71bbc411d2..f4386990b150 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -289,6 +289,22 @@ static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL685c G1"),
},
},
+ {
+ .callback = set_bf_sort,
+ .ident = "HP ProLiant DL385 G2",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL385 G2"),
+ },
+ },
+ {
+ .callback = set_bf_sort,
+ .ident = "HP ProLiant DL585 G2",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL585 G2"),
+ },
+ },
#ifdef __i386__
{
.callback = assign_all_busses,
diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c
index c52150fdf82b..88d8f5c0ecb5 100644
--- a/arch/x86/pci/irq.c
+++ b/arch/x86/pci/irq.c
@@ -169,7 +169,7 @@ void eisa_set_level_irq(unsigned int irq)
}
/*
- * Common IRQ routing practice: nybbles in config space,
+ * Common IRQ routing practice: nibbles in config space,
* offset by some magic constant.
*/
static unsigned int read_config_nybble(struct pci_dev *router, unsigned offset, unsigned nr)
@@ -585,7 +585,7 @@ static __init int via_router_probe(struct irq_router *r,
/* FIXME: We should move some of the quirk fixup stuff here */
/*
- * work arounds for some buggy BIOSes
+ * workarounds for some buggy BIOSes
*/
if (device == PCI_DEVICE_ID_VIA_82C586_0) {
switch(router->device) {
diff --git a/arch/x86/vdso/Makefile b/arch/x86/vdso/Makefile
index 8d03de029d9b..e7bff0fbac23 100644
--- a/arch/x86/vdso/Makefile
+++ b/arch/x86/vdso/Makefile
@@ -13,29 +13,36 @@ vobjs := $(foreach F,$(vobjs-y),$(obj)/$F)
$(obj)/vdso.o: $(obj)/vdso.so
-targets += vdso.so vdso.lds $(vobjs-y) vdso-syms.o
+targets += vdso.so vdso.so.dbg vdso.lds $(vobjs-y) vdso-syms.o
# The DSO images are built using a special linker script.
quiet_cmd_syscall = SYSCALL $@
cmd_syscall = $(CC) -m elf_x86_64 -nostdlib $(SYSCFLAGS_$(@F)) \
-Wl,-T,$(filter-out FORCE,$^) -o $@
-export CPPFLAGS_vdso.lds += -P -C -U$(ARCH)
+export CPPFLAGS_vdso.lds += -P -C
vdso-flags = -fPIC -shared -Wl,-soname=linux-vdso.so.1 \
$(call ld-option, -Wl$(comma)--hash-style=sysv) \
-Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096
SYSCFLAGS_vdso.so = $(vdso-flags)
+SYSCFLAGS_vdso.so.dbg = $(vdso-flags)
$(obj)/vdso.o: $(src)/vdso.S $(obj)/vdso.so
$(obj)/vdso.so: $(src)/vdso.lds $(vobjs) FORCE
+
+$(obj)/vdso.so.dbg: $(src)/vdso.lds $(vobjs) FORCE
$(call if_changed,syscall)
+$(obj)/%.so: OBJCOPYFLAGS := -S
+$(obj)/%.so: $(obj)/%.so.dbg FORCE
+ $(call if_changed,objcopy)
+
CFL := $(PROFILING) -mcmodel=small -fPIC -g0 -O2 -fasynchronous-unwind-tables -m64
-$(obj)/vclock_gettime.o: CFLAGS = $(CFL)
-$(obj)/vgetcpu.o: CFLAGS = $(CFL)
+$(obj)/vclock_gettime.o: KBUILD_CFLAGS = $(CFL)
+$(obj)/vgetcpu.o: KBUILD_CFLAGS = $(CFL)
# We also create a special relocatable object that should mirror the symbol
# table and layout of the linked DSO. With ld -R we can then refer to
@@ -47,3 +54,11 @@ $(obj)/built-in.o: ld_flags += -R $(obj)/vdso-syms.o
SYSCFLAGS_vdso-syms.o = -r -d
$(obj)/vdso-syms.o: $(src)/vdso.lds $(vobjs) FORCE
$(call if_changed,syscall)
+
+quiet_cmd_vdso_install = INSTALL $@
+ cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
+vdso.so:
+ @mkdir -p $(MODLIB)/vdso
+ $(call cmd,vdso_install)
+
+vdso_install: vdso.so
diff --git a/arch/x86/vdso/vdso.lds.S b/arch/x86/vdso/vdso.lds.S
index b9a60e665d08..667d3245d972 100644
--- a/arch/x86/vdso/vdso.lds.S
+++ b/arch/x86/vdso/vdso.lds.S
@@ -26,13 +26,16 @@ SECTIONS
is insufficient, ld -shared will barf. Just increase it here. */
. = VDSO_PRELINK + VDSO_TEXT_OFFSET;
- .text : { *(.text) } :text
- .text.ptr : { *(.text.ptr) } :text
- . = VDSO_PRELINK + 0x900;
- .data : { *(.data) } :text
- .bss : { *(.bss) } :text
+ .text : { *(.text*) } :text
+ .rodata : { *(.rodata*) } :text
+ .data : {
+ *(.data*)
+ *(.sdata*)
+ *(.bss*)
+ *(.dynbss*)
+ } :text
- .altinstructions : { *(.altinstructions) } :text
+ .altinstructions : { *(.altinstructions) } :text
.altinstr_replacement : { *(.altinstr_replacement) } :text
.note : { *(.note.*) } :text :note
@@ -42,7 +45,6 @@ SECTIONS
.useless : {
*(.got.plt) *(.got)
*(.gnu.linkonce.d.*)
- *(.dynbss)
*(.gnu.linkonce.b.*)
} :text
}
diff --git a/arch/x86/vdso/vvar.c b/arch/x86/vdso/vvar.c
index 6fc22219a472..1b7e703684f9 100644
--- a/arch/x86/vdso/vvar.c
+++ b/arch/x86/vdso/vvar.c
@@ -8,5 +8,5 @@
#include <asm/timex.h>
#include <asm/vgtod.h>
-#define VEXTERN(x) typeof (__ ## x) *vdso_ ## x = (void *)VMAGIC;
+#define VEXTERN(x) typeof (__ ## x) *const vdso_ ## x = (void *)VMAGIC;
#include "vextern.h"
diff --git a/arch/x86/xen/Kconfig b/arch/x86/xen/Kconfig
index 9df99e1885a4..fbfa55ce0d55 100644
--- a/arch/x86/xen/Kconfig
+++ b/arch/x86/xen/Kconfig
@@ -3,8 +3,9 @@
#
config XEN
- bool "Enable support for Xen hypervisor"
- depends on PARAVIRT && X86_CMPXCHG && X86_TSC && !NEED_MULTIPLE_NODES
+ bool "Xen guest support"
+ select PARAVIRT
+ depends on X86_CMPXCHG && X86_TSC && !NEED_MULTIPLE_NODES && !(X86_VISWS || X86_VOYAGER)
help
This is the Linux Xen port. Enabling this will allow the
kernel to boot in a paravirtualized environment under the
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index f01bfcd4bdee..94c39aaf695f 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -25,7 +25,6 @@
#include <linux/mm.h>
#include <linux/page-flags.h>
#include <linux/highmem.h>
-#include <linux/smp.h>
#include <xen/interface/xen.h>
#include <xen/interface/physdev.h>
@@ -52,11 +51,25 @@
EXPORT_SYMBOL_GPL(hypercall_page);
-DEFINE_PER_CPU(enum paravirt_lazy_mode, xen_lazy_mode);
-
DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu);
DEFINE_PER_CPU(struct vcpu_info, xen_vcpu_info);
-DEFINE_PER_CPU(unsigned long, xen_cr3);
+
+/*
+ * Note about cr3 (pagetable base) values:
+ *
+ * xen_cr3 contains the current logical cr3 value; it contains the
+ * last set cr3. This may not be the current effective cr3, because
+ * its update may be being lazily deferred. However, a vcpu looking
+ * at its own cr3 can use this value knowing that it everything will
+ * be self-consistent.
+ *
+ * xen_current_cr3 contains the actual vcpu cr3; it is set once the
+ * hypercall to set the vcpu cr3 is complete (so it may be a little
+ * out of date, but it will never be set early). If one vcpu is
+ * looking at another vcpu's cr3 value, it should use this variable.
+ */
+DEFINE_PER_CPU(unsigned long, xen_cr3); /* cr3 stored as physaddr */
+DEFINE_PER_CPU(unsigned long, xen_current_cr3); /* actual vcpu cr3 */
struct start_info *xen_start_info;
EXPORT_SYMBOL_GPL(xen_start_info);
@@ -100,7 +113,7 @@ static void __init xen_vcpu_setup(int cpu)
info.mfn = virt_to_mfn(vcpup);
info.offset = offset_in_page(vcpup);
- printk(KERN_DEBUG "trying to map vcpu_info %d at %p, mfn %x, offset %d\n",
+ printk(KERN_DEBUG "trying to map vcpu_info %d at %p, mfn %llx, offset %d\n",
cpu, vcpup, info.mfn, info.offset);
/* Check to see if the hypervisor will put the vcpu_info
@@ -124,7 +137,7 @@ static void __init xen_vcpu_setup(int cpu)
static void __init xen_banner(void)
{
printk(KERN_INFO "Booting paravirtualized kernel on %s\n",
- paravirt_ops.name);
+ pv_info.name);
printk(KERN_INFO "Hypervisor signature: %s\n", xen_start_info->magic);
}
@@ -249,29 +262,10 @@ static void xen_halt(void)
xen_safe_halt();
}
-static void xen_set_lazy_mode(enum paravirt_lazy_mode mode)
+static void xen_leave_lazy(void)
{
- BUG_ON(preemptible());
-
- switch (mode) {
- case PARAVIRT_LAZY_NONE:
- BUG_ON(x86_read_percpu(xen_lazy_mode) == PARAVIRT_LAZY_NONE);
- break;
-
- case PARAVIRT_LAZY_MMU:
- case PARAVIRT_LAZY_CPU:
- BUG_ON(x86_read_percpu(xen_lazy_mode) != PARAVIRT_LAZY_NONE);
- break;
-
- case PARAVIRT_LAZY_FLUSH:
- /* flush if necessary, but don't change state */
- if (x86_read_percpu(xen_lazy_mode) != PARAVIRT_LAZY_NONE)
- xen_mc_flush();
- return;
- }
-
+ paravirt_leave_lazy(paravirt_get_lazy_mode());
xen_mc_flush();
- x86_write_percpu(xen_lazy_mode, mode);
}
static unsigned long xen_store_tr(void)
@@ -358,7 +352,7 @@ static void xen_load_tls(struct thread_struct *t, unsigned int cpu)
* loaded properly. This will go away as soon as Xen has been
* modified to not save/restore %gs for normal hypercalls.
*/
- if (xen_get_lazy_mode() == PARAVIRT_LAZY_CPU)
+ if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_CPU)
loadsegment(gs, 0);
}
@@ -632,32 +626,36 @@ static unsigned long xen_read_cr3(void)
return x86_read_percpu(xen_cr3);
}
+static void set_current_cr3(void *v)
+{
+ x86_write_percpu(xen_current_cr3, (unsigned long)v);
+}
+
static void xen_write_cr3(unsigned long cr3)
{
+ struct mmuext_op *op;
+ struct multicall_space mcs;
+ unsigned long mfn = pfn_to_mfn(PFN_DOWN(cr3));
+
BUG_ON(preemptible());
- if (cr3 == x86_read_percpu(xen_cr3)) {
- /* just a simple tlb flush */
- xen_flush_tlb();
- return;
- }
+ mcs = xen_mc_entry(sizeof(*op)); /* disables interrupts */
+ /* Update while interrupts are disabled, so its atomic with
+ respect to ipis */
x86_write_percpu(xen_cr3, cr3);
+ op = mcs.args;
+ op->cmd = MMUEXT_NEW_BASEPTR;
+ op->arg1.mfn = mfn;
- {
- struct mmuext_op *op;
- struct multicall_space mcs = xen_mc_entry(sizeof(*op));
- unsigned long mfn = pfn_to_mfn(PFN_DOWN(cr3));
-
- op = mcs.args;
- op->cmd = MMUEXT_NEW_BASEPTR;
- op->arg1.mfn = mfn;
+ MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
- MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
+ /* Update xen_update_cr3 once the batch has actually
+ been submitted. */
+ xen_mc_callback(set_current_cr3, (void *)cr3);
- xen_mc_issue(PARAVIRT_LAZY_CPU);
- }
+ xen_mc_issue(PARAVIRT_LAZY_CPU); /* interrupts restored */
}
/* Early in boot, while setting up the initial pagetable, assume
@@ -668,6 +666,15 @@ static __init void xen_alloc_pt_init(struct mm_struct *mm, u32 pfn)
make_lowmem_page_readonly(__va(PFN_PHYS(pfn)));
}
+static void pin_pagetable_pfn(unsigned level, unsigned long pfn)
+{
+ struct mmuext_op op;
+ op.cmd = level;
+ op.arg1.mfn = pfn_to_mfn(pfn);
+ if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF))
+ BUG();
+}
+
/* This needs to make sure the new pte page is pinned iff its being
attached to a pinned pagetable. */
static void xen_alloc_pt(struct mm_struct *mm, u32 pfn)
@@ -677,9 +684,10 @@ static void xen_alloc_pt(struct mm_struct *mm, u32 pfn)
if (PagePinned(virt_to_page(mm->pgd))) {
SetPagePinned(page);
- if (!PageHighMem(page))
+ if (!PageHighMem(page)) {
make_lowmem_page_readonly(__va(PFN_PHYS(pfn)));
- else
+ pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn);
+ } else
/* make sure there are no stray mappings of
this page */
kmap_flush_unused();
@@ -692,8 +700,10 @@ static void xen_release_pt(u32 pfn)
struct page *page = pfn_to_page(pfn);
if (PagePinned(page)) {
- if (!PageHighMem(page))
+ if (!PageHighMem(page)) {
+ pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, pfn);
make_lowmem_page_readwrite(__va(PFN_PHYS(pfn)));
+ }
}
}
@@ -738,7 +748,7 @@ static __init void xen_pagetable_setup_start(pgd_t *base)
pgd_t *xen_pgd = (pgd_t *)xen_start_info->pt_base;
/* special set_pte for pagetable initialization */
- paravirt_ops.set_pte = xen_set_pte_init;
+ pv_mmu_ops.set_pte = xen_set_pte_init;
init_mm.pgd = base;
/*
@@ -785,8 +795,8 @@ static __init void xen_pagetable_setup_done(pgd_t *base)
{
/* This will work as long as patching hasn't happened yet
(which it hasn't) */
- paravirt_ops.alloc_pt = xen_alloc_pt;
- paravirt_ops.set_pte = xen_set_pte;
+ pv_mmu_ops.alloc_pt = xen_alloc_pt;
+ pv_mmu_ops.set_pte = xen_set_pte;
if (!xen_feature(XENFEAT_auto_translated_physmap)) {
/*
@@ -808,15 +818,15 @@ static __init void xen_pagetable_setup_done(pgd_t *base)
/* Actually pin the pagetable down, but we can't set PG_pinned
yet because the page structures don't exist yet. */
{
- struct mmuext_op op;
+ unsigned level;
+
#ifdef CONFIG_X86_PAE
- op.cmd = MMUEXT_PIN_L3_TABLE;
+ level = MMUEXT_PIN_L3_TABLE;
#else
- op.cmd = MMUEXT_PIN_L3_TABLE;
+ level = MMUEXT_PIN_L2_TABLE;
#endif
- op.arg1.mfn = pfn_to_mfn(PFN_DOWN(__pa(base)));
- if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF))
- BUG();
+
+ pin_pagetable_pfn(level, PFN_DOWN(__pa(base)));
}
}
@@ -833,12 +843,12 @@ void __init xen_setup_vcpu_info_placement(void)
if (have_vcpu_info_placement) {
printk(KERN_INFO "Xen: using vcpu_info placement\n");
- paravirt_ops.save_fl = xen_save_fl_direct;
- paravirt_ops.restore_fl = xen_restore_fl_direct;
- paravirt_ops.irq_disable = xen_irq_disable_direct;
- paravirt_ops.irq_enable = xen_irq_enable_direct;
- paravirt_ops.read_cr2 = xen_read_cr2_direct;
- paravirt_ops.iret = xen_iret_direct;
+ pv_irq_ops.save_fl = xen_save_fl_direct;
+ pv_irq_ops.restore_fl = xen_restore_fl_direct;
+ pv_irq_ops.irq_disable = xen_irq_disable_direct;
+ pv_irq_ops.irq_enable = xen_irq_enable_direct;
+ pv_mmu_ops.read_cr2 = xen_read_cr2_direct;
+ pv_cpu_ops.iret = xen_iret_direct;
}
}
@@ -850,8 +860,8 @@ static unsigned xen_patch(u8 type, u16 clobbers, void *insnbuf,
start = end = reloc = NULL;
-#define SITE(x) \
- case PARAVIRT_PATCH(x): \
+#define SITE(op, x) \
+ case PARAVIRT_PATCH(op.x): \
if (have_vcpu_info_placement) { \
start = (char *)xen_##x##_direct; \
end = xen_##x##_direct_end; \
@@ -860,10 +870,10 @@ static unsigned xen_patch(u8 type, u16 clobbers, void *insnbuf,
goto patch_site
switch (type) {
- SITE(irq_enable);
- SITE(irq_disable);
- SITE(save_fl);
- SITE(restore_fl);
+ SITE(pv_irq_ops, irq_enable);
+ SITE(pv_irq_ops, irq_disable);
+ SITE(pv_irq_ops, save_fl);
+ SITE(pv_irq_ops, restore_fl);
#undef SITE
patch_site:
@@ -895,26 +905,32 @@ static unsigned xen_patch(u8 type, u16 clobbers, void *insnbuf,
return ret;
}
-static const struct paravirt_ops xen_paravirt_ops __initdata = {
+static const struct pv_info xen_info __initdata = {
.paravirt_enabled = 1,
.shared_kernel_pmd = 0,
.name = "Xen",
- .banner = xen_banner,
+};
+static const struct pv_init_ops xen_init_ops __initdata = {
.patch = xen_patch,
+ .banner = xen_banner,
.memory_setup = xen_memory_setup,
.arch_setup = xen_arch_setup,
- .init_IRQ = xen_init_IRQ,
.post_allocator_init = xen_mark_init_mm_pinned,
+};
+static const struct pv_time_ops xen_time_ops __initdata = {
.time_init = xen_time_init,
+
.set_wallclock = xen_set_wallclock,
.get_wallclock = xen_get_wallclock,
.get_cpu_khz = xen_cpu_khz,
.sched_clock = xen_sched_clock,
+};
+static const struct pv_cpu_ops xen_cpu_ops __initdata = {
.cpuid = xen_cpuid,
.set_debugreg = xen_set_debugreg,
@@ -925,22 +941,10 @@ static const struct paravirt_ops xen_paravirt_ops __initdata = {
.read_cr0 = native_read_cr0,
.write_cr0 = native_write_cr0,
- .read_cr2 = xen_read_cr2,
- .write_cr2 = xen_write_cr2,
-
- .read_cr3 = xen_read_cr3,
- .write_cr3 = xen_write_cr3,
-
.read_cr4 = native_read_cr4,
.read_cr4_safe = native_read_cr4_safe,
.write_cr4 = xen_write_cr4,
- .save_fl = xen_save_fl,
- .restore_fl = xen_restore_fl,
- .irq_disable = xen_irq_disable,
- .irq_enable = xen_irq_enable,
- .safe_halt = xen_safe_halt,
- .halt = xen_halt,
.wbinvd = native_wbinvd,
.read_msr = native_read_msr_safe,
@@ -969,6 +973,23 @@ static const struct paravirt_ops xen_paravirt_ops __initdata = {
.set_iopl_mask = xen_set_iopl_mask,
.io_delay = xen_io_delay,
+ .lazy_mode = {
+ .enter = paravirt_enter_lazy_cpu,
+ .leave = xen_leave_lazy,
+ },
+};
+
+static const struct pv_irq_ops xen_irq_ops __initdata = {
+ .init_IRQ = xen_init_IRQ,
+ .save_fl = xen_save_fl,
+ .restore_fl = xen_restore_fl,
+ .irq_disable = xen_irq_disable,
+ .irq_enable = xen_irq_enable,
+ .safe_halt = xen_safe_halt,
+ .halt = xen_halt,
+};
+
+static const struct pv_apic_ops xen_apic_ops __initdata = {
#ifdef CONFIG_X86_LOCAL_APIC
.apic_write = xen_apic_write,
.apic_write_atomic = xen_apic_write,
@@ -977,6 +998,17 @@ static const struct paravirt_ops xen_paravirt_ops __initdata = {
.setup_secondary_clock = paravirt_nop,
.startup_ipi_hook = paravirt_nop,
#endif
+};
+
+static const struct pv_mmu_ops xen_mmu_ops __initdata = {
+ .pagetable_setup_start = xen_pagetable_setup_start,
+ .pagetable_setup_done = xen_pagetable_setup_done,
+
+ .read_cr2 = xen_read_cr2,
+ .write_cr2 = xen_write_cr2,
+
+ .read_cr3 = xen_read_cr3,
+ .write_cr3 = xen_write_cr3,
.flush_tlb_user = xen_flush_tlb,
.flush_tlb_kernel = xen_flush_tlb,
@@ -986,9 +1018,6 @@ static const struct paravirt_ops xen_paravirt_ops __initdata = {
.pte_update = paravirt_nop,
.pte_update_defer = paravirt_nop,
- .pagetable_setup_start = xen_pagetable_setup_start,
- .pagetable_setup_done = xen_pagetable_setup_done,
-
.alloc_pt = xen_alloc_pt_init,
.release_pt = xen_release_pt,
.alloc_pd = paravirt_nop,
@@ -1024,7 +1053,10 @@ static const struct paravirt_ops xen_paravirt_ops __initdata = {
.dup_mmap = xen_dup_mmap,
.exit_mmap = xen_exit_mmap,
- .set_lazy_mode = xen_set_lazy_mode,
+ .lazy_mode = {
+ .enter = paravirt_enter_lazy_mmu,
+ .leave = xen_leave_lazy,
+ },
};
#ifdef CONFIG_SMP
@@ -1080,6 +1112,17 @@ static const struct machine_ops __initdata xen_machine_ops = {
};
+static void __init xen_reserve_top(void)
+{
+ unsigned long top = HYPERVISOR_VIRT_START;
+ struct xen_platform_parameters pp;
+
+ if (HYPERVISOR_xen_version(XENVER_platform_parameters, &pp) == 0)
+ top = pp.virt_start;
+
+ reserve_top_address(-top + 2 * PAGE_SIZE);
+}
+
/* First C function to be called on Xen boot */
asmlinkage void __init xen_start_kernel(void)
{
@@ -1091,7 +1134,14 @@ asmlinkage void __init xen_start_kernel(void)
BUG_ON(memcmp(xen_start_info->magic, "xen-3.0", 7) != 0);
/* Install Xen paravirt ops */
- paravirt_ops = xen_paravirt_ops;
+ pv_info = xen_info;
+ pv_init_ops = xen_init_ops;
+ pv_time_ops = xen_time_ops;
+ pv_cpu_ops = xen_cpu_ops;
+ pv_irq_ops = xen_irq_ops;
+ pv_apic_ops = xen_apic_ops;
+ pv_mmu_ops = xen_mmu_ops;
+
machine_ops = xen_machine_ops;
#ifdef CONFIG_SMP
@@ -1113,6 +1163,7 @@ asmlinkage void __init xen_start_kernel(void)
/* keep using Xen gdt for now; no urgent need to change it */
x86_write_percpu(xen_cr3, __pa(pgd));
+ x86_write_percpu(xen_current_cr3, __pa(pgd));
#ifdef CONFIG_SMP
/* Don't do the full vcpu_info placement stuff until we have a
@@ -1124,12 +1175,12 @@ asmlinkage void __init xen_start_kernel(void)
xen_setup_vcpu_info_placement();
#endif
- paravirt_ops.kernel_rpl = 1;
+ pv_info.kernel_rpl = 1;
if (xen_feature(XENFEAT_supervisor_mode_kernel))
- paravirt_ops.kernel_rpl = 0;
+ pv_info.kernel_rpl = 0;
/* set the limit of our address space */
- reserve_top_address(-HYPERVISOR_VIRT_START + 2 * PAGE_SIZE);
+ xen_reserve_top();
/* set up basic CPUID stuff */
cpu_detect(&new_cpu_data);
@@ -1137,9 +1188,10 @@ asmlinkage void __init xen_start_kernel(void)
new_cpu_data.x86_capability[0] = cpuid_edx(1);
/* Poke various useful things into boot_params */
- LOADER_TYPE = (9 << 4) | 0;
- INITRD_START = xen_start_info->mod_start ? __pa(xen_start_info->mod_start) : 0;
- INITRD_SIZE = xen_start_info->mod_len;
+ boot_params.hdr.type_of_loader = (9 << 4) | 0;
+ boot_params.hdr.ramdisk_image = xen_start_info->mod_start
+ ? __pa(xen_start_info->mod_start) : 0;
+ boot_params.hdr.ramdisk_size = xen_start_info->mod_len;
/* Start the world */
start_kernel();
diff --git a/arch/x86/xen/events.c b/arch/x86/xen/events.c
index da1b173547a1..6d1da5809e6f 100644
--- a/arch/x86/xen/events.c
+++ b/arch/x86/xen/events.c
@@ -383,7 +383,7 @@ static void unbind_from_irq(unsigned int irq)
}
int bind_evtchn_to_irqhandler(unsigned int evtchn,
- irqreturn_t (*handler)(int, void *),
+ irq_handler_t handler,
unsigned long irqflags,
const char *devname, void *dev_id)
{
@@ -402,7 +402,7 @@ int bind_evtchn_to_irqhandler(unsigned int evtchn,
EXPORT_SYMBOL_GPL(bind_evtchn_to_irqhandler);
int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu,
- irqreturn_t (*handler)(int, void *),
+ irq_handler_t handler,
unsigned long irqflags, const char *devname, void *dev_id)
{
unsigned int irq;
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 874db0cd1d2a..b2e32f9d0071 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -41,7 +41,6 @@
#include <linux/sched.h>
#include <linux/highmem.h>
#include <linux/bug.h>
-#include <linux/sched.h>
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
@@ -155,7 +154,7 @@ void xen_set_pte_at(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, pte_t pteval)
{
if (mm == current->mm || mm == &init_mm) {
- if (xen_get_lazy_mode() == PARAVIRT_LAZY_MMU) {
+ if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU) {
struct multicall_space mcs;
mcs = xen_mc_entry(0);
@@ -304,7 +303,12 @@ pgd_t xen_make_pgd(unsigned long pgd)
}
#endif /* CONFIG_X86_PAE */
-
+enum pt_level {
+ PT_PGD,
+ PT_PUD,
+ PT_PMD,
+ PT_PTE
+};
/*
(Yet another) pagetable walker. This one is intended for pinning a
@@ -316,7 +320,7 @@ pgd_t xen_make_pgd(unsigned long pgd)
FIXADDR_TOP. But the important bit is that we don't pin beyond
there, because then we start getting into Xen's ptes.
*/
-static int pgd_walk(pgd_t *pgd_base, int (*func)(struct page *, unsigned),
+static int pgd_walk(pgd_t *pgd_base, int (*func)(struct page *, enum pt_level),
unsigned long limit)
{
pgd_t *pgd = pgd_base;
@@ -341,7 +345,7 @@ static int pgd_walk(pgd_t *pgd_base, int (*func)(struct page *, unsigned),
pud = pud_offset(pgd, 0);
if (PTRS_PER_PUD > 1) /* not folded */
- flush |= (*func)(virt_to_page(pud), 0);
+ flush |= (*func)(virt_to_page(pud), PT_PUD);
for (; addr != pud_limit; pud++, addr = pud_next) {
pmd_t *pmd;
@@ -360,7 +364,7 @@ static int pgd_walk(pgd_t *pgd_base, int (*func)(struct page *, unsigned),
pmd = pmd_offset(pud, 0);
if (PTRS_PER_PMD > 1) /* not folded */
- flush |= (*func)(virt_to_page(pmd), 0);
+ flush |= (*func)(virt_to_page(pmd), PT_PMD);
for (; addr != pmd_limit; pmd++) {
addr += (PAGE_SIZE * PTRS_PER_PTE);
@@ -372,17 +376,47 @@ static int pgd_walk(pgd_t *pgd_base, int (*func)(struct page *, unsigned),
if (pmd_none(*pmd))
continue;
- flush |= (*func)(pmd_page(*pmd), 0);
+ flush |= (*func)(pmd_page(*pmd), PT_PTE);
}
}
}
- flush |= (*func)(virt_to_page(pgd_base), UVMF_TLB_FLUSH);
+ flush |= (*func)(virt_to_page(pgd_base), PT_PGD);
return flush;
}
-static int pin_page(struct page *page, unsigned flags)
+static spinlock_t *lock_pte(struct page *page)
+{
+ spinlock_t *ptl = NULL;
+
+#if NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS
+ ptl = __pte_lockptr(page);
+ spin_lock(ptl);
+#endif
+
+ return ptl;
+}
+
+static void do_unlock(void *v)
+{
+ spinlock_t *ptl = v;
+ spin_unlock(ptl);
+}
+
+static void xen_do_pin(unsigned level, unsigned long pfn)
+{
+ struct mmuext_op *op;
+ struct multicall_space mcs;
+
+ mcs = __xen_mc_entry(sizeof(*op));
+ op = mcs.args;
+ op->cmd = level;
+ op->arg1.mfn = pfn_to_mfn(pfn);
+ MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
+}
+
+static int pin_page(struct page *page, enum pt_level level)
{
unsigned pgfl = test_and_set_bit(PG_pinned, &page->flags);
int flush;
@@ -397,12 +431,26 @@ static int pin_page(struct page *page, unsigned flags)
void *pt = lowmem_page_address(page);
unsigned long pfn = page_to_pfn(page);
struct multicall_space mcs = __xen_mc_entry(0);
+ spinlock_t *ptl;
flush = 0;
+ ptl = NULL;
+ if (level == PT_PTE)
+ ptl = lock_pte(page);
+
MULTI_update_va_mapping(mcs.mc, (unsigned long)pt,
pfn_pte(pfn, PAGE_KERNEL_RO),
- flags);
+ level == PT_PGD ? UVMF_TLB_FLUSH : 0);
+
+ if (level == PT_PTE)
+ xen_do_pin(MMUEXT_PIN_L1_TABLE, pfn);
+
+ if (ptl) {
+ /* Queue a deferred unlock for when this batch
+ is completed. */
+ xen_mc_callback(do_unlock, ptl);
+ }
}
return flush;
@@ -413,8 +461,7 @@ static int pin_page(struct page *page, unsigned flags)
read-only, and can be pinned. */
void xen_pgd_pin(pgd_t *pgd)
{
- struct multicall_space mcs;
- struct mmuext_op *op;
+ unsigned level;
xen_mc_batch();
@@ -425,16 +472,13 @@ void xen_pgd_pin(pgd_t *pgd)
xen_mc_batch();
}
- mcs = __xen_mc_entry(sizeof(*op));
- op = mcs.args;
-
#ifdef CONFIG_X86_PAE
- op->cmd = MMUEXT_PIN_L3_TABLE;
+ level = MMUEXT_PIN_L3_TABLE;
#else
- op->cmd = MMUEXT_PIN_L2_TABLE;
+ level = MMUEXT_PIN_L2_TABLE;
#endif
- op->arg1.mfn = pfn_to_mfn(PFN_DOWN(__pa(pgd)));
- MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
+
+ xen_do_pin(level, PFN_DOWN(__pa(pgd)));
xen_mc_issue(0);
}
@@ -442,7 +486,7 @@ void xen_pgd_pin(pgd_t *pgd)
/* The init_mm pagetable is really pinned as soon as its created, but
that's before we have page structures to store the bits. So do all
the book-keeping now. */
-static __init int mark_pinned(struct page *page, unsigned flags)
+static __init int mark_pinned(struct page *page, enum pt_level level)
{
SetPagePinned(page);
return 0;
@@ -453,18 +497,32 @@ void __init xen_mark_init_mm_pinned(void)
pgd_walk(init_mm.pgd, mark_pinned, FIXADDR_TOP);
}
-static int unpin_page(struct page *page, unsigned flags)
+static int unpin_page(struct page *page, enum pt_level level)
{
unsigned pgfl = test_and_clear_bit(PG_pinned, &page->flags);
if (pgfl && !PageHighMem(page)) {
void *pt = lowmem_page_address(page);
unsigned long pfn = page_to_pfn(page);
- struct multicall_space mcs = __xen_mc_entry(0);
+ spinlock_t *ptl = NULL;
+ struct multicall_space mcs;
+
+ if (level == PT_PTE) {
+ ptl = lock_pte(page);
+
+ xen_do_pin(MMUEXT_UNPIN_TABLE, pfn);
+ }
+
+ mcs = __xen_mc_entry(0);
MULTI_update_va_mapping(mcs.mc, (unsigned long)pt,
pfn_pte(pfn, PAGE_KERNEL),
- flags);
+ level == PT_PGD ? UVMF_TLB_FLUSH : 0);
+
+ if (ptl) {
+ /* unlock when batch completed */
+ xen_mc_callback(do_unlock, ptl);
+ }
}
return 0; /* never need to flush on unpin */
@@ -473,18 +531,9 @@ static int unpin_page(struct page *page, unsigned flags)
/* Release a pagetables pages back as normal RW */
static void xen_pgd_unpin(pgd_t *pgd)
{
- struct mmuext_op *op;
- struct multicall_space mcs;
-
xen_mc_batch();
- mcs = __xen_mc_entry(sizeof(*op));
-
- op = mcs.args;
- op->cmd = MMUEXT_UNPIN_TABLE;
- op->arg1.mfn = pfn_to_mfn(PFN_DOWN(__pa(pgd)));
-
- MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
+ xen_do_pin(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd)));
pgd_walk(pgd, unpin_page, TASK_SIZE);
@@ -515,20 +564,43 @@ static void drop_other_mm_ref(void *info)
if (__get_cpu_var(cpu_tlbstate).active_mm == mm)
leave_mm(smp_processor_id());
+
+ /* If this cpu still has a stale cr3 reference, then make sure
+ it has been flushed. */
+ if (x86_read_percpu(xen_current_cr3) == __pa(mm->pgd)) {
+ load_cr3(swapper_pg_dir);
+ arch_flush_lazy_cpu_mode();
+ }
}
static void drop_mm_ref(struct mm_struct *mm)
{
+ cpumask_t mask;
+ unsigned cpu;
+
if (current->active_mm == mm) {
if (current->mm == mm)
load_cr3(swapper_pg_dir);
else
leave_mm(smp_processor_id());
+ arch_flush_lazy_cpu_mode();
}
- if (!cpus_empty(mm->cpu_vm_mask))
- xen_smp_call_function_mask(mm->cpu_vm_mask, drop_other_mm_ref,
- mm, 1);
+ /* Get the "official" set of cpus referring to our pagetable. */
+ mask = mm->cpu_vm_mask;
+
+ /* It's possible that a vcpu may have a stale reference to our
+ cr3, because its in lazy mode, and it hasn't yet flushed
+ its set of pending hypercalls yet. In this case, we can
+ look at its actual current cr3 value, and force it to flush
+ if needed. */
+ for_each_online_cpu(cpu) {
+ if (per_cpu(xen_current_cr3, cpu) == __pa(mm->pgd))
+ cpu_set(cpu, mask);
+ }
+
+ if (!cpus_empty(mask))
+ xen_smp_call_function_mask(mask, drop_other_mm_ref, mm, 1);
}
#else
static void drop_mm_ref(struct mm_struct *mm)
@@ -563,5 +635,6 @@ void xen_exit_mmap(struct mm_struct *mm)
/* pgd may not be pinned in the error exit path of execve */
if (PagePinned(virt_to_page(mm->pgd)))
xen_pgd_unpin(mm->pgd);
+
spin_unlock(&mm->page_table_lock);
}
diff --git a/arch/x86/xen/multicalls.c b/arch/x86/xen/multicalls.c
index c837e8e463db..5e6f36f6d876 100644
--- a/arch/x86/xen/multicalls.c
+++ b/arch/x86/xen/multicalls.c
@@ -26,13 +26,22 @@
#include "multicalls.h"
+#define MC_DEBUG 1
+
#define MC_BATCH 32
#define MC_ARGS (MC_BATCH * 16 / sizeof(u64))
struct mc_buffer {
struct multicall_entry entries[MC_BATCH];
+#if MC_DEBUG
+ struct multicall_entry debug[MC_BATCH];
+#endif
u64 args[MC_ARGS];
- unsigned mcidx, argidx;
+ struct callback {
+ void (*fn)(void *);
+ void *data;
+ } callbacks[MC_BATCH];
+ unsigned mcidx, argidx, cbidx;
};
static DEFINE_PER_CPU(struct mc_buffer, mc_buffer);
@@ -43,6 +52,7 @@ void xen_mc_flush(void)
struct mc_buffer *b = &__get_cpu_var(mc_buffer);
int ret = 0;
unsigned long flags;
+ int i;
BUG_ON(preemptible());
@@ -51,13 +61,31 @@ void xen_mc_flush(void)
local_irq_save(flags);
if (b->mcidx) {
- int i;
+#if MC_DEBUG
+ memcpy(b->debug, b->entries,
+ b->mcidx * sizeof(struct multicall_entry));
+#endif
if (HYPERVISOR_multicall(b->entries, b->mcidx) != 0)
BUG();
for (i = 0; i < b->mcidx; i++)
if (b->entries[i].result < 0)
ret++;
+
+#if MC_DEBUG
+ if (ret) {
+ printk(KERN_ERR "%d multicall(s) failed: cpu %d\n",
+ ret, smp_processor_id());
+ for(i = 0; i < b->mcidx; i++) {
+ printk(" call %2d/%d: op=%lu arg=[%lx] result=%ld\n",
+ i+1, b->mcidx,
+ b->debug[i].op,
+ b->debug[i].args[0],
+ b->entries[i].result);
+ }
+ }
+#endif
+
b->mcidx = 0;
b->argidx = 0;
} else
@@ -65,6 +93,13 @@ void xen_mc_flush(void)
local_irq_restore(flags);
+ for(i = 0; i < b->cbidx; i++) {
+ struct callback *cb = &b->callbacks[i];
+
+ (*cb->fn)(cb->data);
+ }
+ b->cbidx = 0;
+
BUG_ON(ret);
}
@@ -88,3 +123,16 @@ struct multicall_space __xen_mc_entry(size_t args)
return ret;
}
+
+void xen_mc_callback(void (*fn)(void *), void *data)
+{
+ struct mc_buffer *b = &__get_cpu_var(mc_buffer);
+ struct callback *cb;
+
+ if (b->cbidx == MC_BATCH)
+ xen_mc_flush();
+
+ cb = &b->callbacks[b->cbidx++];
+ cb->fn = fn;
+ cb->data = data;
+}
diff --git a/arch/x86/xen/multicalls.h b/arch/x86/xen/multicalls.h
index e6f7530b156c..8bae996d99a3 100644
--- a/arch/x86/xen/multicalls.h
+++ b/arch/x86/xen/multicalls.h
@@ -35,11 +35,14 @@ void xen_mc_flush(void);
/* Issue a multicall if we're not in a lazy mode */
static inline void xen_mc_issue(unsigned mode)
{
- if ((xen_get_lazy_mode() & mode) == 0)
+ if ((paravirt_get_lazy_mode() & mode) == 0)
xen_mc_flush();
/* restore flags saved in xen_mc_batch */
local_irq_restore(x86_read_percpu(xen_mc_irq_flags));
}
+/* Set up a callback to be called when the current batch is flushed */
+void xen_mc_callback(void (*fn)(void *), void *data);
+
#endif /* _XEN_MULTICALLS_H */
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index 557b8e24706a..c1b131bcdcbe 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -147,8 +147,13 @@ void __init xen_smp_prepare_boot_cpu(void)
make_lowmem_page_readwrite(&per_cpu__gdt_page);
for (cpu = 0; cpu < NR_CPUS; cpu++) {
- cpus_clear(cpu_sibling_map[cpu]);
- cpus_clear(cpu_core_map[cpu]);
+ cpus_clear(per_cpu(cpu_sibling_map, cpu));
+ /*
+ * cpu_core_map lives in a per cpu area that is cleared
+ * when the per cpu array is allocated.
+ *
+ * cpus_clear(per_cpu(cpu_core_map, cpu));
+ */
}
xen_setup_vcpu_info_placement();
@@ -159,8 +164,13 @@ void __init xen_smp_prepare_cpus(unsigned int max_cpus)
unsigned cpu;
for (cpu = 0; cpu < NR_CPUS; cpu++) {
- cpus_clear(cpu_sibling_map[cpu]);
- cpus_clear(cpu_core_map[cpu]);
+ cpus_clear(per_cpu(cpu_sibling_map, cpu));
+ /*
+ * cpu_core_ map will be zeroed when the per
+ * cpu area is allocated.
+ *
+ * cpus_clear(per_cpu(cpu_core_map, cpu));
+ */
}
smp_store_cpu_info(0);
@@ -346,6 +356,7 @@ static irqreturn_t xen_call_function_interrupt(int irq, void *dev_id)
*/
irq_enter();
(*func)(info);
+ __get_cpu_var(irq_stat).irq_call_count++;
irq_exit();
if (wait) {
@@ -360,7 +371,8 @@ int xen_smp_call_function_mask(cpumask_t mask, void (*func)(void *),
void *info, int wait)
{
struct call_data_struct data;
- int cpus;
+ int cpus, cpu;
+ bool yield;
/* Holding any lock stops cpus from going down. */
spin_lock(&call_lock);
@@ -389,9 +401,14 @@ int xen_smp_call_function_mask(cpumask_t mask, void (*func)(void *),
/* Send a message to other CPUs and wait for them to respond */
xen_send_IPI_mask(mask, XEN_CALL_FUNCTION_VECTOR);
- /* Make sure other vcpus get a chance to run.
- XXX too severe? Maybe we should check the other CPU's states? */
- HYPERVISOR_sched_op(SCHEDOP_yield, 0);
+ /* Make sure other vcpus get a chance to run if they need to. */
+ yield = false;
+ for_each_cpu_mask(cpu, mask)
+ if (xen_vcpu_stolen(cpu))
+ yield = true;
+
+ if (yield)
+ HYPERVISOR_sched_op(SCHEDOP_yield, 0);
/* Wait for response */
while (atomic_read(&data.started) != cpus ||
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
index dfd6db69ead5..d083ff5ef088 100644
--- a/arch/x86/xen/time.c
+++ b/arch/x86/xen/time.c
@@ -105,6 +105,12 @@ static void get_runstate_snapshot(struct vcpu_runstate_info *res)
} while (get64(&state->state_entry_time) != state_time);
}
+/* return true when a vcpu could run but has no real cpu to run on */
+bool xen_vcpu_stolen(int vcpu)
+{
+ return per_cpu(runstate, vcpu).state == RUNSTATE_runnable;
+}
+
static void setup_runstate_info(int cpu)
{
struct vcpu_register_runstate_memory_area area;
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index b9aaea45f07f..b02a909bfd4c 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -11,6 +11,7 @@ void xen_copy_trap_info(struct trap_info *traps);
DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu);
DECLARE_PER_CPU(unsigned long, xen_cr3);
+DECLARE_PER_CPU(unsigned long, xen_current_cr3);
extern struct start_info *xen_start_info;
extern struct shared_info *HYPERVISOR_shared_info;
@@ -27,14 +28,9 @@ unsigned long xen_get_wallclock(void);
int xen_set_wallclock(unsigned long time);
unsigned long long xen_sched_clock(void);
-void xen_mark_init_mm_pinned(void);
-
-DECLARE_PER_CPU(enum paravirt_lazy_mode, xen_lazy_mode);
+bool xen_vcpu_stolen(int vcpu);
-static inline unsigned xen_get_lazy_mode(void)
-{
- return x86_read_percpu(xen_lazy_mode);
-}
+void xen_mark_init_mm_pinned(void);
void __init xen_fill_possible_map(void);
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
deleted file mode 100644
index cf013cb85ea4..000000000000
--- a/arch/x86_64/Kconfig
+++ /dev/null
@@ -1,819 +0,0 @@
-#
-# For a description of the syntax of this configuration file,
-# see Documentation/kbuild/kconfig-language.txt.
-#
-# Note: ISA is disabled and will hopefully never be enabled.
-# If you managed to buy an ISA x86-64 box you'll have to fix all the
-# ISA drivers you need yourself.
-#
-
-mainmenu "Linux Kernel Configuration"
-
-config X86_64
- bool
- default y
- help
- Port to the x86-64 architecture. x86-64 is a 64-bit extension to the
- classical 32-bit x86 architecture. For details see
- <http://www.x86-64.org/>.
-
-config 64BIT
- def_bool y
-
-config X86
- bool
- default y
-
-config GENERIC_TIME
- bool
- default y
-
-config GENERIC_TIME_VSYSCALL
- bool
- default y
-
-config GENERIC_CMOS_UPDATE
- bool
- default y
-
-config CLOCKSOURCE_WATCHDOG
- bool
- default y
-
-config GENERIC_CLOCKEVENTS
- bool
- default y
-
-config GENERIC_CLOCKEVENTS_BROADCAST
- bool
- default y
-
-config ZONE_DMA32
- bool
- default y
-
-config LOCKDEP_SUPPORT
- bool
- default y
-
-config STACKTRACE_SUPPORT
- bool
- default y
-
-config SEMAPHORE_SLEEPERS
- bool
- default y
-
-config MMU
- bool
- default y
-
-config ZONE_DMA
- bool
- default y
-
-config ISA
- bool
-
-config SBUS
- bool
-
-config RWSEM_GENERIC_SPINLOCK
- bool
- default y
-
-config RWSEM_XCHGADD_ALGORITHM
- bool
-
-config GENERIC_HWEIGHT
- bool
- default y
-
-config GENERIC_CALIBRATE_DELAY
- bool
- default y
-
-config X86_CMPXCHG
- bool
- default y
-
-config EARLY_PRINTK
- bool
- default y
-
-config GENERIC_ISA_DMA
- bool
- default y
-
-config GENERIC_IOMAP
- bool
- default y
-
-config ARCH_MAY_HAVE_PC_FDC
- bool
- default y
-
-config ARCH_POPULATES_NODE_MAP
- def_bool y
-
-config DMI
- bool
- default y
-
-config AUDIT_ARCH
- bool
- default y
-
-config GENERIC_BUG
- bool
- default y
- depends on BUG
-
-config ARCH_HAS_ILOG2_U32
- bool
- default n
-
-config ARCH_HAS_ILOG2_U64
- bool
- default n
-
-source "init/Kconfig"
-
-
-menu "Processor type and features"
-
-source "kernel/time/Kconfig"
-
-choice
- prompt "Subarchitecture Type"
- default X86_PC
-
-config X86_PC
- bool "PC-compatible"
- help
- Choose this option if your computer is a standard PC or compatible.
-
-config X86_VSMP
- bool "Support for ScaleMP vSMP"
- depends on PCI
- help
- Support for ScaleMP vSMP systems. Say 'Y' here if this kernel is
- supposed to run on these EM64T-based machines. Only choose this option
- if you have one of these machines.
-
-endchoice
-
-choice
- prompt "Processor family"
- default GENERIC_CPU
-
-config MK8
- bool "AMD-Opteron/Athlon64"
- help
- Optimize for AMD Opteron/Athlon64/Hammer/K8 CPUs.
-
-config MPSC
- bool "Intel P4 / older Netburst based Xeon"
- help
- Optimize for Intel Pentium 4 and older Nocona/Dempsey Xeon CPUs
- with Intel Extended Memory 64 Technology(EM64T). For details see
- <http://www.intel.com/technology/64bitextensions/>.
- Note that the latest Xeons (Xeon 51xx and 53xx) are not based on the
- Netburst core and shouldn't use this option. You can distinguish them
- using the cpu family field
- in /proc/cpuinfo. Family 15 is an older Xeon, Family 6 a newer one
- (this rule only applies to systems that support EM64T)
-
-config MCORE2
- bool "Intel Core2 / newer Xeon"
- help
- Optimize for Intel Core2 and newer Xeons (51xx)
- You can distinguish the newer Xeons from the older ones using
- the cpu family field in /proc/cpuinfo. 15 is an older Xeon
- (use CONFIG_MPSC then), 6 is a newer one. This rule only
- applies to CPUs that support EM64T.
-
-config GENERIC_CPU
- bool "Generic-x86-64"
- help
- Generic x86-64 CPU.
- Run equally well on all x86-64 CPUs.
-
-endchoice
-
-#
-# Define implied options from the CPU selection here
-#
-config X86_L1_CACHE_BYTES
- int
- default "128" if GENERIC_CPU || MPSC
- default "64" if MK8 || MCORE2
-
-config X86_L1_CACHE_SHIFT
- int
- default "7" if GENERIC_CPU || MPSC
- default "6" if MK8 || MCORE2
-
-config X86_INTERNODE_CACHE_BYTES
- int
- default "4096" if X86_VSMP
- default X86_L1_CACHE_BYTES if !X86_VSMP
-
-config X86_TSC
- bool
- default y
-
-config X86_GOOD_APIC
- bool
- default y
-
-config MICROCODE
- tristate "/dev/cpu/microcode - Intel CPU microcode support"
- select FW_LOADER
- ---help---
- If you say Y here the 'File systems' section, you will be
- able to update the microcode on Intel processors. You will
- obviously need the actual microcode binary data itself which is
- not shipped with the Linux kernel.
-
- For latest news and information on obtaining all the required
- ingredients for this driver, check:
- <http://www.urbanmyth.org/microcode/>.
-
- To compile this driver as a module, choose M here: the
- module will be called microcode.
- If you use modprobe or kmod you may also want to add the line
- 'alias char-major-10-184 microcode' to your /etc/modules.conf file.
-
-config MICROCODE_OLD_INTERFACE
- bool
- depends on MICROCODE
- default y
-
-config X86_MSR
- tristate "/dev/cpu/*/msr - Model-specific register support"
- help
- This device gives privileged processes access to the x86
- Model-Specific Registers (MSRs). It is a character device with
- major 202 and minors 0 to 31 for /dev/cpu/0/msr to /dev/cpu/31/msr.
- MSR accesses are directed to a specific CPU on multi-processor
- systems.
-
-config X86_CPUID
- tristate "/dev/cpu/*/cpuid - CPU information support"
- help
- This device gives processes access to the x86 CPUID instruction to
- be executed on a specific processor. It is a character device
- with major 203 and minors 0 to 31 for /dev/cpu/0/cpuid to
- /dev/cpu/31/cpuid.
-
-config X86_HT
- bool
- depends on SMP && !MK8
- default y
-
-config MATH_EMULATION
- bool
-
-config MCA
- bool
-
-config EISA
- bool
-
-config X86_IO_APIC
- bool
- default y
-
-config X86_LOCAL_APIC
- bool
- default y
-
-config MTRR
- bool "MTRR (Memory Type Range Register) support"
- ---help---
- On Intel P6 family processors (Pentium Pro, Pentium II and later)
- the Memory Type Range Registers (MTRRs) may be used to control
- processor access to memory ranges. This is most useful if you have
- a video (VGA) card on a PCI or AGP bus. Enabling write-combining
- allows bus write transfers to be combined into a larger transfer
- before bursting over the PCI/AGP bus. This can increase performance
- of image write operations 2.5 times or more. Saying Y here creates a
- /proc/mtrr file which may be used to manipulate your processor's
- MTRRs. Typically the X server should use this.
-
- This code has a reasonably generic interface so that similar
- control registers on other processors can be easily supported
- as well.
-
- Saying Y here also fixes a problem with buggy SMP BIOSes which only
- set the MTRRs for the boot CPU and not for the secondary CPUs. This
- can lead to all sorts of problems, so it's good to say Y here.
-
- Just say Y here, all x86-64 machines support MTRRs.
-
- See <file:Documentation/mtrr.txt> for more information.
-
-config SMP
- bool "Symmetric multi-processing support"
- ---help---
- This enables support for systems with more than one CPU. If you have
- a system with only one CPU, like most personal computers, say N. If
- you have a system with more than one CPU, say Y.
-
- If you say N here, the kernel will run on single and multiprocessor
- machines, but will use only one CPU of a multiprocessor machine. If
- you say Y here, the kernel will run on many, but not all,
- singleprocessor machines. On a singleprocessor machine, the kernel
- will run faster if you say N here.
-
- If you don't know what to do here, say N.
-
-config SCHED_SMT
- bool "SMT (Hyperthreading) scheduler support"
- depends on SMP
- default n
- help
- SMT scheduler support improves the CPU scheduler's decision making
- when dealing with Intel Pentium 4 chips with HyperThreading at a
- cost of slightly increased overhead in some places. If unsure say
- N here.
-
-config SCHED_MC
- bool "Multi-core scheduler support"
- depends on SMP
- default y
- help
- Multi-core scheduler support improves the CPU scheduler's decision
- making when dealing with multi-core CPU chips at a cost of slightly
- increased overhead in some places. If unsure say N here.
-
-source "kernel/Kconfig.preempt"
-
-config NUMA
- bool "Non Uniform Memory Access (NUMA) Support"
- depends on SMP
- help
- Enable NUMA (Non Uniform Memory Access) support. The kernel
- will try to allocate memory used by a CPU on the local memory
- controller of the CPU and add some more NUMA awareness to the kernel.
- This code is recommended on all multiprocessor Opteron systems.
- If the system is EM64T, you should say N unless your system is EM64T
- NUMA.
-
-config K8_NUMA
- bool "Old style AMD Opteron NUMA detection"
- depends on NUMA && PCI
- default y
- help
- Enable K8 NUMA node topology detection. You should say Y here if
- you have a multi processor AMD K8 system. This uses an old
- method to read the NUMA configuration directly from the builtin
- Northbridge of Opteron. It is recommended to use X86_64_ACPI_NUMA
- instead, which also takes priority if both are compiled in.
-
-config NODES_SHIFT
- int
- default "6"
- depends on NEED_MULTIPLE_NODES
-
-# Dummy CONFIG option to select ACPI_NUMA from drivers/acpi/Kconfig.
-
-config X86_64_ACPI_NUMA
- bool "ACPI NUMA detection"
- depends on NUMA
- select ACPI
- select PCI
- select ACPI_NUMA
- default y
- help
- Enable ACPI SRAT based node topology detection.
-
-config NUMA_EMU
- bool "NUMA emulation"
- depends on NUMA
- help
- Enable NUMA emulation. A flat machine will be split
- into virtual nodes when booted with "numa=fake=N", where N is the
- number of nodes. This is only useful for debugging.
-
-config ARCH_DISCONTIGMEM_ENABLE
- bool
- depends on NUMA
- default y
-
-config ARCH_DISCONTIGMEM_DEFAULT
- def_bool y
- depends on NUMA
-
-config ARCH_SPARSEMEM_ENABLE
- def_bool y
- depends on (NUMA || EXPERIMENTAL)
-
-config ARCH_MEMORY_PROBE
- def_bool y
- depends on MEMORY_HOTPLUG
-
-config ARCH_FLATMEM_ENABLE
- def_bool y
- depends on !NUMA
-
-source "mm/Kconfig"
-
-config MEMORY_HOTPLUG_RESERVE
- def_bool y
- depends on (MEMORY_HOTPLUG && DISCONTIGMEM)
-
-config HAVE_ARCH_EARLY_PFN_TO_NID
- def_bool y
- depends on NUMA
-
-config OUT_OF_LINE_PFN_TO_PAGE
- def_bool y
- depends on DISCONTIGMEM
-
-config NR_CPUS
- int "Maximum number of CPUs (2-255)"
- range 2 255
- depends on SMP
- default "8"
- help
- This allows you to specify the maximum number of CPUs which this
- kernel will support. Current maximum is 255 CPUs due to
- APIC addressing limits. Less depending on the hardware.
-
- This is purely to save memory - each supported CPU requires
- memory in the static kernel configuration.
-
-config PHYSICAL_ALIGN
- hex
- default "0x200000"
-
-config HOTPLUG_CPU
- bool "Support for suspend on SMP and hot-pluggable CPUs (EXPERIMENTAL)"
- depends on SMP && HOTPLUG && EXPERIMENTAL
- help
- Say Y here to experiment with turning CPUs off and on. CPUs
- can be controlled through /sys/devices/system/cpu/cpu#.
- This is also required for suspend/hibernation on SMP systems.
-
- Say N if you want to disable CPU hotplug and don't need to
- suspend.
-
-config ARCH_ENABLE_MEMORY_HOTPLUG
- def_bool y
-
-config HPET_TIMER
- bool
- default y
- help
- Use the IA-PC HPET (High Precision Event Timer) to manage
- time in preference to the PIT and RTC, if a HPET is
- present. The HPET provides a stable time base on SMP
- systems, unlike the TSC, but it is more expensive to access,
- as it is off-chip. You can find the HPET spec at
- <http://www.intel.com/hardwaredesign/hpetspec.htm>.
-
-config HPET_EMULATE_RTC
- bool "Provide RTC interrupt"
- depends on HPET_TIMER && RTC=y
-
-# Mark as embedded because too many people got it wrong.
-# The code disables itself when not needed.
-config IOMMU
- bool "IOMMU support" if EMBEDDED
- default y
- select SWIOTLB
- select AGP
- depends on PCI
- help
- Support for full DMA access of devices with 32bit memory access only
- on systems with more than 3GB. This is usually needed for USB,
- sound, many IDE/SATA chipsets and some other devices.
- Provides a driver for the AMD Athlon64/Opteron/Turion/Sempron GART
- based hardware IOMMU and a software bounce buffer based IOMMU used
- on Intel systems and as fallback.
- The code is only active when needed (enough memory and limited
- device) unless CONFIG_IOMMU_DEBUG or iommu=force is specified
- too.
-
-config CALGARY_IOMMU
- bool "IBM Calgary IOMMU support"
- select SWIOTLB
- depends on PCI && EXPERIMENTAL
- help
- Support for hardware IOMMUs in IBM's xSeries x366 and x460
- systems. Needed to run systems with more than 3GB of memory
- properly with 32-bit PCI devices that do not support DAC
- (Double Address Cycle). Calgary also supports bus level
- isolation, where all DMAs pass through the IOMMU. This
- prevents them from going anywhere except their intended
- destination. This catches hard-to-find kernel bugs and
- mis-behaving drivers and devices that do not use the DMA-API
- properly to set up their DMA buffers. The IOMMU can be
- turned off at boot time with the iommu=off parameter.
- Normally the kernel will make the right choice by itself.
- If unsure, say Y.
-
-config CALGARY_IOMMU_ENABLED_BY_DEFAULT
- bool "Should Calgary be enabled by default?"
- default y
- depends on CALGARY_IOMMU
- help
- Should Calgary be enabled by default? if you choose 'y', Calgary
- will be used (if it exists). If you choose 'n', Calgary will not be
- used even if it exists. If you choose 'n' and would like to use
- Calgary anyway, pass 'iommu=calgary' on the kernel command line.
- If unsure, say Y.
-
-# need this always selected by IOMMU for the VIA workaround
-config SWIOTLB
- bool
- help
- Support for software bounce buffers used on x86-64 systems
- which don't have a hardware IOMMU (e.g. the current generation
- of Intel's x86-64 CPUs). Using this PCI devices which can only
- access 32-bits of memory can be used on systems with more than
- 3 GB of memory. If unsure, say Y.
-
-config X86_MCE
- bool "Machine check support" if EMBEDDED
- default y
- help
- Include a machine check error handler to report hardware errors.
- This version will require the mcelog utility to decode some
- machine check error logs. See
- ftp://ftp.x86-64.org/pub/linux/tools/mcelog
-
-config X86_MCE_INTEL
- bool "Intel MCE features"
- depends on X86_MCE && X86_LOCAL_APIC
- default y
- help
- Additional support for intel specific MCE features such as
- the thermal monitor.
-
-config X86_MCE_AMD
- bool "AMD MCE features"
- depends on X86_MCE && X86_LOCAL_APIC
- default y
- help
- Additional support for AMD specific MCE features such as
- the DRAM Error Threshold.
-
-config KEXEC
- bool "kexec system call"
- help
- kexec is a system call that implements the ability to shutdown your
- current kernel, and to start another kernel. It is like a reboot
- but it is independent of the system firmware. And like a reboot
- you can start any kernel with it, not just Linux.
-
- The name comes from the similarity to the exec system call.
-
- It is an ongoing process to be certain the hardware in a machine
- is properly shutdown, so do not be surprised if this code does not
- initially work for you. It may help to enable device hotplugging
- support. As of this writing the exact hardware interface is
- strongly in flux, so no good recommendation can be made.
-
-config CRASH_DUMP
- bool "kernel crash dumps (EXPERIMENTAL)"
- depends on EXPERIMENTAL
- help
- Generate crash dump after being started by kexec.
- This should be normally only set in special crash dump kernels
- which are loaded in the main kernel with kexec-tools into
- a specially reserved region and then later executed after
- a crash by kdump/kexec. The crash dump kernel must be compiled
- to a memory address not used by the main kernel or BIOS using
- PHYSICAL_START.
- For more details see Documentation/kdump/kdump.txt
-
-config RELOCATABLE
- bool "Build a relocatable kernel(EXPERIMENTAL)"
- depends on EXPERIMENTAL
- help
- Builds a relocatable kernel. This enables loading and running
- a kernel binary from a different physical address than it has
- been compiled for.
-
- One use is for the kexec on panic case where the recovery kernel
- must live at a different physical address than the primary
- kernel.
-
- Note: If CONFIG_RELOCATABLE=y, then kernel run from the address
- it has been loaded at and compile time physical address
- (CONFIG_PHYSICAL_START) is ignored.
-
-config PHYSICAL_START
- hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP)
- default "0x200000"
- help
- This gives the physical address where the kernel is loaded. It
- should be aligned to 2MB boundary.
-
- If kernel is a not relocatable (CONFIG_RELOCATABLE=n) then
- bzImage will decompress itself to above physical address and
- run from there. Otherwise, bzImage will run from the address where
- it has been loaded by the boot loader and will ignore above physical
- address.
-
- In normal kdump cases one does not have to set/change this option
- as now bzImage can be compiled as a completely relocatable image
- (CONFIG_RELOCATABLE=y) and be used to load and run from a different
- address. This option is mainly useful for the folks who don't want
- to use a bzImage for capturing the crash dump and want to use a
- vmlinux instead.
-
- So if you are using bzImage for capturing the crash dump, leave
- the value here unchanged to 0x200000 and set CONFIG_RELOCATABLE=y.
- Otherwise if you plan to use vmlinux for capturing the crash dump
- change this value to start of the reserved region (Typically 16MB
- 0x1000000). In other words, it can be set based on the "X" value as
- specified in the "crashkernel=YM@XM" command line boot parameter
- passed to the panic-ed kernel. Typically this parameter is set as
- crashkernel=64M@16M. Please take a look at
- Documentation/kdump/kdump.txt for more details about crash dumps.
-
- Usage of bzImage for capturing the crash dump is advantageous as
- one does not have to build two kernels. Same kernel can be used
- as production kernel and capture kernel.
-
- Don't change this unless you know what you are doing.
-
-config SECCOMP
- bool "Enable seccomp to safely compute untrusted bytecode"
- depends on PROC_FS
- default y
- help
- This kernel feature is useful for number crunching applications
- that may need to compute untrusted bytecode during their
- execution. By using pipes or other transports made available to
- the process as file descriptors supporting the read/write
- syscalls, it's possible to isolate those applications in
- their own address space using seccomp. Once seccomp is
- enabled via /proc/<pid>/seccomp, it cannot be disabled
- and the task is only allowed to execute a few safe syscalls
- defined by each seccomp mode.
-
- If unsure, say Y. Only embedded should say N here.
-
-config CC_STACKPROTECTOR
- bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
- depends on EXPERIMENTAL
- help
- This option turns on the -fstack-protector GCC feature. This
- feature puts, at the beginning of critical functions, a canary
- value on the stack just before the return address, and validates
- the value just before actually returning. Stack based buffer
- overflows (that need to overwrite this return address) now also
- overwrite the canary, which gets detected and the attack is then
- neutralized via a kernel panic.
-
- This feature requires gcc version 4.2 or above, or a distribution
- gcc with the feature backported. Older versions are automatically
- detected and for those versions, this configuration option is ignored.
-
-config CC_STACKPROTECTOR_ALL
- bool "Use stack-protector for all functions"
- depends on CC_STACKPROTECTOR
- help
- Normally, GCC only inserts the canary value protection for
- functions that use large-ish on-stack buffers. By enabling
- this option, GCC will be asked to do this for ALL functions.
-
-source kernel/Kconfig.hz
-
-config K8_NB
- def_bool y
- depends on AGP_AMD64 || IOMMU || (PCI && NUMA)
-
-endmenu
-
-#
-# Use the generic interrupt handling code in kernel/irq/:
-#
-config GENERIC_HARDIRQS
- bool
- default y
-
-config GENERIC_IRQ_PROBE
- bool
- default y
-
-# we have no ISA slots, but we do have ISA-style DMA.
-config ISA_DMA_API
- bool
- default y
-
-config GENERIC_PENDING_IRQ
- bool
- depends on GENERIC_HARDIRQS && SMP
- default y
-
-menu "Power management options"
-
-source kernel/power/Kconfig
-
-source "drivers/acpi/Kconfig"
-
-source "arch/x86/kernel/cpufreq/Kconfig"
-
-endmenu
-
-menu "Bus options (PCI etc.)"
-
-config PCI
- bool "PCI support"
- select ARCH_SUPPORTS_MSI if (X86_LOCAL_APIC && X86_IO_APIC)
-
-# x86-64 doesn't support PCI BIOS access from long mode so always go direct.
-config PCI_DIRECT
- bool
- depends on PCI
- default y
-
-config PCI_MMCONFIG
- bool "Support mmconfig PCI config space access"
- depends on PCI && ACPI
-
-config PCI_DOMAINS
- bool
- depends on PCI
- default y
-
-source "drivers/pci/pcie/Kconfig"
-
-source "drivers/pci/Kconfig"
-
-source "drivers/pcmcia/Kconfig"
-
-source "drivers/pci/hotplug/Kconfig"
-
-endmenu
-
-
-menu "Executable file formats / Emulations"
-
-source "fs/Kconfig.binfmt"
-
-config IA32_EMULATION
- bool "IA32 Emulation"
- help
- Include code to run 32-bit programs under a 64-bit kernel. You should likely
- turn this on, unless you're 100% sure that you don't have any 32-bit programs
- left.
-
-config IA32_AOUT
- tristate "IA32 a.out support"
- depends on IA32_EMULATION
- help
- Support old a.out binaries in the 32bit emulation.
-
-config COMPAT
- bool
- depends on IA32_EMULATION
- default y
-
-config COMPAT_FOR_U64_ALIGNMENT
- def_bool COMPAT
-
-config SYSVIPC_COMPAT
- bool
- depends on COMPAT && SYSVIPC
- default y
-
-endmenu
-
-source "net/Kconfig"
-
-source drivers/Kconfig
-
-source "drivers/firmware/Kconfig"
-
-source fs/Kconfig
-
-menu "Instrumentation Support"
- depends on EXPERIMENTAL
-
-source "arch/x86/oprofile/Kconfig"
-
-config KPROBES
- bool "Kprobes"
- depends on KALLSYMS && MODULES
- help
- Kprobes allows you to trap at almost any kernel address and
- execute a callback function. register_kprobe() establishes
- a probepoint and specifies the callback. Kprobes is useful
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-endmenu
-
-source "arch/x86_64/Kconfig.debug"
-
-source "security/Kconfig"
-
-source "crypto/Kconfig"
-
-source "lib/Kconfig"
diff --git a/arch/x86_64/Kconfig.debug b/arch/x86_64/Kconfig.debug
deleted file mode 100644
index 775d211a5cf9..000000000000
--- a/arch/x86_64/Kconfig.debug
+++ /dev/null
@@ -1,61 +0,0 @@
-menu "Kernel hacking"
-
-config TRACE_IRQFLAGS_SUPPORT
- bool
- default y
-
-source "lib/Kconfig.debug"
-
-config DEBUG_RODATA
- bool "Write protect kernel read-only data structures"
- depends on DEBUG_KERNEL
- help
- Mark the kernel read-only data as write-protected in the pagetables,
- in order to catch accidental (and incorrect) writes to such const data.
- This option may have a slight performance impact because a portion
- of the kernel code won't be covered by a 2MB TLB anymore.
- If in doubt, say "N".
-
-config IOMMU_DEBUG
- depends on IOMMU && DEBUG_KERNEL
- bool "Enable IOMMU debugging"
- help
- Force the IOMMU to on even when you have less than 4GB of
- memory and add debugging code. On overflow always panic. And
- allow to enable IOMMU leak tracing. Can be disabled at boot
- time with iommu=noforce. This will also enable scatter gather
- list merging. Currently not recommended for production
- code. When you use it make sure you have a big enough
- IOMMU/AGP aperture. Most of the options enabled by this can
- be set more finegrained using the iommu= command line
- options. See Documentation/x86_64/boot-options.txt for more
- details.
-
-config IOMMU_LEAK
- bool "IOMMU leak tracing"
- depends on DEBUG_KERNEL
- depends on IOMMU_DEBUG
- help
- 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 DEBUG_STACKOVERFLOW
- bool "Check for stack overflows"
- depends on DEBUG_KERNEL
- help
- This option will cause messages to be printed if free stack space
- drops below a certain limit.
-
-config DEBUG_STACK_USAGE
- bool "Stack utilization instrumentation"
- depends on DEBUG_KERNEL
- help
- Enables the display of the minimum amount of free stack which each
- task has ever had available in the sysrq-T and sysrq-P debug output.
-
- This option will slow down process creation somewhat.
-
-#config X86_REMOTE_DEBUG
-# bool "kgdb debugging stub"
-
-endmenu
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index 7fbb44bea37f..d3cb3d6af4c8 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -1,5 +1,5 @@
# For a description of the syntax of this configuration file,
-# see Documentation/kbuild/config-language.txt.
+# see Documentation/kbuild/kconfig-language.txt.
mainmenu "Linux/Xtensa Kernel Configuration"
@@ -251,6 +251,8 @@ config EMBEDDED_RAMDISK_IMAGE
provide one yourself.
endmenu
+source "kernel/Kconfig.instrumentation"
+
source "arch/xtensa/Kconfig.debug"
source "security/Kconfig"
diff --git a/arch/xtensa/Makefile b/arch/xtensa/Makefile
index acf05be24929..56685a883347 100644
--- a/arch/xtensa/Makefile
+++ b/arch/xtensa/Makefile
@@ -28,11 +28,9 @@ PLATFORM = $(platform-y)
export PLATFORM
# temporarily until string.h is fixed
-cflags-y += -ffreestanding
+KBUILD_CFLAGS += -ffreestanding
-cflags-y += -pipe -mlongcalls
-
-CFLAGS += $(cflags-y)
+KBUILD_CFLAGS += -pipe -mlongcalls
KBUILD_DEFCONFIG := iss_defconfig
@@ -56,7 +54,7 @@ endif
#
-LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
+LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
head-y := arch/xtensa/kernel/head.o
core-y += arch/xtensa/kernel/ arch/xtensa/mm/
diff --git a/arch/xtensa/boot/Makefile b/arch/xtensa/boot/Makefile
index 820b31d10ae4..40aa55b485be 100644
--- a/arch/xtensa/boot/Makefile
+++ b/arch/xtensa/boot/Makefile
@@ -8,13 +8,13 @@
#
-CFLAGS += -fno-builtin -Iarch/$(ARCH)/boot/include
+# KBUILD_CFLAGS used when building rest of boot (takes effect recursively)
+KBUILD_CFLAGS += -fno-builtin -Iarch/$(ARCH)/boot/include
HOSTFLAGS += -Iarch/$(ARCH)/boot/include
BIG_ENDIAN := $(shell echo -e __XTENSA_EB__ | $(CC) -E - | grep -v "\#")
-export CFLAGS
-export AFLAGS
+export EXTRA_CFLAGS
export BIG_ENDIAN
subdir-y := lib
diff --git a/arch/xtensa/boot/boot-redboot/Makefile b/arch/xtensa/boot/boot-redboot/Makefile
index f53262c2e1f3..74d15d08077b 100644
--- a/arch/xtensa/boot/boot-redboot/Makefile
+++ b/arch/xtensa/boot/boot-redboot/Makefile
@@ -19,7 +19,7 @@ boot-y := bootstrap.o
OBJS := $(addprefix $(obj)/,$(boot-y))
LIBS := arch/xtensa/boot/lib/lib.a arch/xtensa/lib/lib.a
-LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
+LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
zImage: vmlinux $(OBJS) $(LIBS)
$(OBJCOPY) --strip-all -R .comment -R .xt.insn -O binary \
diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c
index 06a13d9b69db..5533c7850d53 100644
--- a/arch/xtensa/kernel/ptrace.c
+++ b/arch/xtensa/kernel/ptrace.c
@@ -304,10 +304,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
ret = put_user(sizeof(elf_fpregset_t), (unsigned long *) data);
break;
- case PTRACE_DETACH: /* detach a process that was attached. */
- ret = ptrace_detach(child, data);
- break;
-
default:
ret = ptrace_request(child, request, addr, data);
goto out;
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c
index 8be99c777d9d..397bcd6ad08d 100644
--- a/arch/xtensa/kernel/traps.c
+++ b/arch/xtensa/kernel/traps.c
@@ -176,7 +176,7 @@ void do_unhandled(struct pt_regs *regs, unsigned long exccause)
printk("Caught unhandled exception in '%s' "
"(pid = %d, pc = %#010lx) - should not happen\n"
"\tEXCCAUSE is %ld\n",
- current->comm, current->pid, regs->pc, exccause);
+ current->comm, task_pid_nr(current), regs->pc, exccause);
force_sig(SIGILL, current);
}
@@ -228,7 +228,7 @@ do_illegal_instruction(struct pt_regs *regs)
/* If in user mode, send SIGILL signal to current process. */
printk("Illegal Instruction in '%s' (pid = %d, pc = %#010lx)\n",
- current->comm, current->pid, regs->pc);
+ current->comm, task_pid_nr(current), regs->pc);
force_sig(SIGILL, current);
}
@@ -254,7 +254,7 @@ do_unaligned_user (struct pt_regs *regs)
current->thread.error_code = -3;
printk("Unaligned memory access to %08lx in '%s' "
"(pid = %d, pc = %#010lx)\n",
- regs->excvaddr, current->comm, current->pid, regs->pc);
+ regs->excvaddr, current->comm, task_pid_nr(current), regs->pc);
info.si_signo = SIGBUS;
info.si_errno = 0;
info.si_code = BUS_ADRALN;
diff --git a/arch/xtensa/mm/fault.c b/arch/xtensa/mm/fault.c
index 45d28f217c03..33f366be323f 100644
--- a/arch/xtensa/mm/fault.c
+++ b/arch/xtensa/mm/fault.c
@@ -145,14 +145,14 @@ bad_area:
*/
out_of_memory:
up_read(&mm->mmap_sem);
- if (is_init(current)) {
+ if (is_global_init(current)) {
yield();
down_read(&mm->mmap_sem);
goto survive;
}
printk("VM: killing process %s\n", current->comm);
if (user_mode(regs))
- do_exit(SIGKILL);
+ do_group_exit(SIGKILL);
bad_page_fault(regs, address, SIGKILL);
return;
diff --git a/arch/xtensa/platform-iss/network.c b/arch/xtensa/platform-iss/network.c
index f09962fa98c0..b61fb36674e7 100644
--- a/arch/xtensa/platform-iss/network.c
+++ b/arch/xtensa/platform-iss/network.c
@@ -798,7 +798,7 @@ static int iss_net_setup(char *str)
#undef ERR
-__setup("eth", iss_net_setup);
+__setup("eth=", iss_net_setup);
/*
* Initialize all ISS Ethernet devices previously registered in iss_net_setup.
diff --git a/block/blktrace.c b/block/blktrace.c
index 775471ef84a5..d00ac3993c18 100644
--- a/block/blktrace.c
+++ b/block/blktrace.c
@@ -550,7 +550,7 @@ static void blk_trace_set_ht_offsets(void)
for_each_online_cpu(cpu) {
unsigned long long *cpu_off, *sibling_off;
- for_each_cpu_mask(i, cpu_sibling_map[cpu]) {
+ for_each_cpu_mask(i, per_cpu(cpu_sibling_map, cpu)) {
if (i == cpu)
continue;
diff --git a/block/bsg.c b/block/bsg.c
index b8ddfc66f210..8e181ab3afb9 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -908,7 +908,7 @@ static long bsg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
}
-static struct file_operations bsg_fops = {
+static const struct file_operations bsg_fops = {
.read = bsg_read,
.write = bsg_write,
.poll = bsg_poll,
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 54dc05439009..0b4a47905575 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -789,6 +789,20 @@ static inline void cfq_slice_expired(struct cfq_data *cfqd, int timed_out)
__cfq_slice_expired(cfqd, cfqq, timed_out);
}
+static int start_idle_class_timer(struct cfq_data *cfqd)
+{
+ unsigned long end = cfqd->last_end_request + CFQ_IDLE_GRACE;
+ unsigned long now = jiffies;
+
+ if (time_before(now, end) &&
+ time_after_eq(now, cfqd->last_end_request)) {
+ mod_timer(&cfqd->idle_class_timer, end);
+ return 1;
+ }
+
+ return 0;
+}
+
/*
* Get next queue for service. Unless we have a queue preemption,
* we'll simply select the first cfqq in the service tree.
@@ -805,19 +819,14 @@ static struct cfq_queue *cfq_get_next_queue(struct cfq_data *cfqd)
cfqq = rb_entry(n, struct cfq_queue, rb_node);
if (cfq_class_idle(cfqq)) {
- unsigned long end;
-
/*
* if we have idle queues and no rt or be queues had
* pending requests, either allow immediate service if
* the grace period has passed or arm the idle grace
* timer
*/
- end = cfqd->last_end_request + CFQ_IDLE_GRACE;
- if (time_before(jiffies, end)) {
- mod_timer(&cfqd->idle_class_timer, end);
+ if (start_idle_class_timer(cfqd))
cfqq = NULL;
- }
}
return cfqq;
@@ -1443,8 +1452,11 @@ cfq_get_queue(struct cfq_data *cfqd, int is_sync, struct task_struct *tsk,
cfqq = *async_cfqq;
}
- if (!cfqq)
+ if (!cfqq) {
cfqq = cfq_find_alloc_queue(cfqd, is_sync, tsk, gfp_mask);
+ if (!cfqq)
+ return NULL;
+ }
/*
* pin the queue now that it's allocated, scheduler exit will prune it
@@ -2033,17 +2045,14 @@ out_cont:
static void cfq_idle_class_timer(unsigned long data)
{
struct cfq_data *cfqd = (struct cfq_data *) data;
- unsigned long flags, end;
+ unsigned long flags;
spin_lock_irqsave(cfqd->queue->queue_lock, flags);
/*
* race with a non-idle queue, reset timer
*/
- end = cfqd->last_end_request + CFQ_IDLE_GRACE;
- if (!time_after_eq(jiffies, end))
- mod_timer(&cfqd->idle_class_timer, end);
- else
+ if (!start_idle_class_timer(cfqd))
cfq_schedule_dispatch(cfqd);
spin_unlock_irqrestore(cfqd->queue->queue_lock, flags);
@@ -2053,7 +2062,7 @@ static void cfq_shutdown_timer_wq(struct cfq_data *cfqd)
{
del_timer_sync(&cfqd->idle_slice_timer);
del_timer_sync(&cfqd->idle_class_timer);
- blk_sync_queue(cfqd->queue);
+ kblockd_flush_work(&cfqd->unplug_work);
}
static void cfq_put_async_queues(struct cfq_data *cfqd)
@@ -2065,9 +2074,10 @@ static void cfq_put_async_queues(struct cfq_data *cfqd)
cfq_put_queue(cfqd->async_cfqq[0][i]);
if (cfqd->async_cfqq[1][i])
cfq_put_queue(cfqd->async_cfqq[1][i]);
- if (cfqd->async_idle_cfqq)
- cfq_put_queue(cfqd->async_idle_cfqq);
}
+
+ if (cfqd->async_idle_cfqq)
+ cfq_put_queue(cfqd->async_idle_cfqq);
}
static void cfq_exit_queue(elevator_t *e)
@@ -2122,6 +2132,7 @@ static void *cfq_init_queue(struct request_queue *q)
INIT_WORK(&cfqd->unplug_work, cfq_kick_queue);
+ cfqd->last_end_request = jiffies;
cfqd->cfq_quantum = cfq_quantum;
cfqd->cfq_fifo_expire[0] = cfq_fifo_expire[0];
cfqd->cfq_fifo_expire[1] = cfq_fifo_expire[1];
diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c
index f84093b97f70..cae0a852619e 100644
--- a/block/compat_ioctl.c
+++ b/block/compat_ioctl.c
@@ -581,7 +581,7 @@ static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file,
{
int ret;
- switch (arg) {
+ switch (cmd) {
case HDIO_GET_UNMASKINTR:
case HDIO_GET_MULTCOUNT:
case HDIO_GET_KEEPSETTINGS:
diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c
index 1a511ffaf8a4..a054eef8dff6 100644
--- a/block/deadline-iosched.c
+++ b/block/deadline-iosched.c
@@ -55,6 +55,20 @@ static void deadline_move_request(struct deadline_data *, struct request *);
#define RQ_RB_ROOT(dd, rq) (&(dd)->sort_list[rq_data_dir((rq))])
+/*
+ * get the request after `rq' in sector-sorted order
+ */
+static inline struct request *
+deadline_latter_request(struct request *rq)
+{
+ struct rb_node *node = rb_next(&rq->rb_node);
+
+ if (node)
+ return rb_entry_rq(node);
+
+ return NULL;
+}
+
static void
deadline_add_rq_rb(struct deadline_data *dd, struct request *rq)
{
@@ -74,13 +88,8 @@ deadline_del_rq_rb(struct deadline_data *dd, struct request *rq)
{
const int data_dir = rq_data_dir(rq);
- if (dd->next_rq[data_dir] == rq) {
- struct rb_node *rbnext = rb_next(&rq->rb_node);
-
- dd->next_rq[data_dir] = NULL;
- if (rbnext)
- dd->next_rq[data_dir] = rb_entry_rq(rbnext);
- }
+ if (dd->next_rq[data_dir] == rq)
+ dd->next_rq[data_dir] = deadline_latter_request(rq);
elv_rb_del(RQ_RB_ROOT(dd, rq), rq);
}
@@ -198,14 +207,11 @@ static void
deadline_move_request(struct deadline_data *dd, struct request *rq)
{
const int data_dir = rq_data_dir(rq);
- struct rb_node *rbnext = rb_next(&rq->rb_node);
dd->next_rq[READ] = NULL;
dd->next_rq[WRITE] = NULL;
+ dd->next_rq[data_dir] = deadline_latter_request(rq);
- if (rbnext)
- dd->next_rq[data_dir] = rb_entry_rq(rbnext);
-
dd->last_sector = rq->sector + rq->nr_sectors;
/*
@@ -301,30 +307,23 @@ dispatch_find_request:
/*
* we are not running a batch, find best request for selected data_dir
*/
- if (deadline_check_fifo(dd, data_dir)) {
- /* An expired request exists - satisfy it */
- dd->batching = 0;
+ if (deadline_check_fifo(dd, data_dir) || !dd->next_rq[data_dir]) {
+ /*
+ * A deadline has expired, the last request was in the other
+ * direction, or we have run out of higher-sectored requests.
+ * Start again from the request with the earliest expiry time.
+ */
rq = rq_entry_fifo(dd->fifo_list[data_dir].next);
-
- } else if (dd->next_rq[data_dir]) {
+ } else {
/*
* The last req was the same dir and we have a next request in
* sort order. No expired requests so continue on from here.
*/
rq = dd->next_rq[data_dir];
- } else {
- struct rb_node *node;
- /*
- * The last req was the other direction or we have run out of
- * higher-sectored requests. Go back to the lowest sectored
- * request (1 way elevator) and start a new batch.
- */
- dd->batching = 0;
- node = rb_first(&dd->sort_list[data_dir]);
- if (node)
- rq = rb_entry_rq(node);
}
+ dd->batching = 0;
+
dispatch_request:
/*
* rq is the selected appropriate request.
diff --git a/block/elevator.c b/block/elevator.c
index b9c518afe1f8..446aea2a3cfb 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -390,7 +390,7 @@ EXPORT_SYMBOL(elv_rb_find);
/*
* Insert rq into dispatch queue of q. Queue lock must be held on
- * entry. rq is sort insted into the dispatch queue. To be used by
+ * entry. rq is sort instead into the dispatch queue. To be used by
* specific elevators.
*/
void elv_dispatch_sort(struct request_queue *q, struct request *rq)
@@ -712,6 +712,14 @@ struct request *elv_next_request(struct request_queue *q)
int ret;
while ((rq = __elv_next_request(q)) != NULL) {
+ /*
+ * Kill the empty barrier place holder, the driver must
+ * not ever see it.
+ */
+ if (blk_empty_barrier(rq)) {
+ end_queued_request(rq, 1);
+ continue;
+ }
if (!(rq->cmd_flags & REQ_STARTED)) {
/*
* This is the first time the device driver
@@ -751,15 +759,8 @@ struct request *elv_next_request(struct request_queue *q)
rq = NULL;
break;
} else if (ret == BLKPREP_KILL) {
- int nr_bytes = rq->hard_nr_sectors << 9;
-
- if (!nr_bytes)
- nr_bytes = rq->data_len;
-
- blkdev_dequeue_request(rq);
rq->cmd_flags |= REQ_QUIET;
- end_that_request_chunk(rq, 0, nr_bytes);
- end_that_request_last(rq, 0);
+ end_queued_request(rq, 0);
} else {
printk(KERN_ERR "%s: bad return=%d\n", __FUNCTION__,
ret);
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index d875673e76cd..3b927be03850 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -30,6 +30,7 @@
#include <linux/cpu.h>
#include <linux/blktrace_api.h>
#include <linux/fault-inject.h>
+#include <linux/scatterlist.h>
/*
* for max sense size
@@ -38,7 +39,7 @@
static void blk_unplug_work(struct work_struct *work);
static void blk_unplug_timeout(unsigned long data);
-static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io);
+static void drive_stat_acct(struct request *rq, int new_io);
static void init_request_from_bio(struct request *req, struct bio *bio);
static int __make_request(struct request_queue *q, struct bio *bio);
static struct io_context *current_io_context(gfp_t gfp_flags, int node);
@@ -304,23 +305,6 @@ int blk_queue_ordered(struct request_queue *q, unsigned ordered,
EXPORT_SYMBOL(blk_queue_ordered);
-/**
- * blk_queue_issue_flush_fn - set function for issuing a flush
- * @q: the request queue
- * @iff: the function to be called issuing the flush
- *
- * Description:
- * If a driver supports issuing a flush command, the support is notified
- * to the block layer by defining it through this call.
- *
- **/
-void blk_queue_issue_flush_fn(struct request_queue *q, issue_flush_fn *iff)
-{
- q->issue_flush_fn = iff;
-}
-
-EXPORT_SYMBOL(blk_queue_issue_flush_fn);
-
/*
* Cache flushing for ordered writes handling
*/
@@ -377,10 +361,12 @@ void blk_ordered_complete_seq(struct request_queue *q, unsigned seq, int error)
/*
* Okay, sequence complete.
*/
- rq = q->orig_bar_rq;
- uptodate = q->orderr ? q->orderr : 1;
+ uptodate = 1;
+ if (q->orderr)
+ uptodate = q->orderr;
q->ordseq = 0;
+ rq = q->orig_bar_rq;
end_that_request_first(rq, uptodate, rq->hard_nr_sectors);
end_that_request_last(rq, uptodate);
@@ -445,7 +431,8 @@ static inline struct request *start_ordered(struct request_queue *q,
rq_init(q, rq);
if (bio_data_dir(q->orig_bar_rq->bio) == WRITE)
rq->cmd_flags |= REQ_RW;
- rq->cmd_flags |= q->ordered & QUEUE_ORDERED_FUA ? REQ_FUA : 0;
+ if (q->ordered & QUEUE_ORDERED_FUA)
+ rq->cmd_flags |= REQ_FUA;
rq->elevator_private = NULL;
rq->elevator_private2 = NULL;
init_request_from_bio(rq, q->orig_bar_rq->bio);
@@ -455,9 +442,12 @@ static inline struct request *start_ordered(struct request_queue *q,
* Queue ordered sequence. As we stack them at the head, we
* need to queue in reverse order. Note that we rely on that
* no fs request uses ELEVATOR_INSERT_FRONT and thus no fs
- * request gets inbetween ordered sequence.
+ * request gets inbetween ordered sequence. If this request is
+ * an empty barrier, we don't need to do a postflush ever since
+ * there will be no data written between the pre and post flush.
+ * Hence a single flush will suffice.
*/
- if (q->ordered & QUEUE_ORDERED_POSTFLUSH)
+ if ((q->ordered & QUEUE_ORDERED_POSTFLUSH) && !blk_empty_barrier(rq))
queue_flush(q, QUEUE_ORDERED_POSTFLUSH);
else
q->ordseq |= QUEUE_ORDSEQ_POSTFLUSH;
@@ -481,7 +471,7 @@ static inline struct request *start_ordered(struct request_queue *q,
int blk_do_ordered(struct request_queue *q, struct request **rqp)
{
struct request *rq = *rqp;
- int is_barrier = blk_fs_request(rq) && blk_barrier_rq(rq);
+ const int is_barrier = blk_fs_request(rq) && blk_barrier_rq(rq);
if (!q->ordseq) {
if (!is_barrier)
@@ -801,7 +791,6 @@ static int __blk_free_tags(struct blk_queue_tag *bqt)
retval = atomic_dec_and_test(&bqt->refcnt);
if (retval) {
BUG_ON(bqt->busy);
- BUG_ON(!list_empty(&bqt->busy_list));
kfree(bqt->tag_index);
bqt->tag_index = NULL;
@@ -913,7 +902,6 @@ static struct blk_queue_tag *__blk_queue_init_tags(struct request_queue *q,
if (init_tag_map(q, tags, depth))
goto fail;
- INIT_LIST_HEAD(&tags->busy_list);
tags->busy = 0;
atomic_set(&tags->refcnt, 1);
return tags;
@@ -964,6 +952,7 @@ int blk_queue_init_tags(struct request_queue *q, int depth,
*/
q->queue_tags = tags;
q->queue_flags |= (1 << QUEUE_FLAG_QUEUED);
+ INIT_LIST_HEAD(&q->tag_busy_list);
return 0;
fail:
kfree(tags);
@@ -1067,18 +1056,16 @@ void blk_queue_end_tag(struct request_queue *q, struct request *rq)
bqt->tag_index[tag] = NULL;
- /*
- * We use test_and_clear_bit's memory ordering properties here.
- * The tag_map bit acts as a lock for tag_index[bit], so we need
- * a barrer before clearing the bit (precisely: release semantics).
- * Could use clear_bit_unlock when it is merged.
- */
- if (unlikely(!test_and_clear_bit(tag, bqt->tag_map))) {
+ if (unlikely(!test_bit(tag, bqt->tag_map))) {
printk(KERN_ERR "%s: attempt to clear non-busy tag (%d)\n",
__FUNCTION__, tag);
return;
}
-
+ /*
+ * The tag_map bit acts as a lock for tag_index[bit], so we need
+ * unlock memory barrier semantics.
+ */
+ clear_bit_unlock(tag, bqt->tag_map);
bqt->busy--;
}
@@ -1124,17 +1111,17 @@ int blk_queue_start_tag(struct request_queue *q, struct request *rq)
if (tag >= bqt->max_depth)
return 1;
- } while (test_and_set_bit(tag, bqt->tag_map));
+ } while (test_and_set_bit_lock(tag, bqt->tag_map));
/*
- * We rely on test_and_set_bit providing lock memory ordering semantics
- * (could use test_and_set_bit_lock when it is merged).
+ * We need lock ordering semantics given by test_and_set_bit_lock.
+ * See blk_queue_end_tag for details.
*/
rq->cmd_flags |= REQ_QUEUED;
rq->tag = tag;
bqt->tag_index[tag] = rq;
blkdev_dequeue_request(rq);
- list_add(&rq->queuelist, &bqt->busy_list);
+ list_add(&rq->queuelist, &q->tag_busy_list);
bqt->busy++;
return 0;
}
@@ -1155,24 +1142,10 @@ EXPORT_SYMBOL(blk_queue_start_tag);
**/
void blk_queue_invalidate_tags(struct request_queue *q)
{
- struct blk_queue_tag *bqt = q->queue_tags;
struct list_head *tmp, *n;
- struct request *rq;
-
- list_for_each_safe(tmp, n, &bqt->busy_list) {
- rq = list_entry_rq(tmp);
-
- if (rq->tag == -1) {
- printk(KERN_ERR
- "%s: bad tag found on list\n", __FUNCTION__);
- list_del_init(&rq->queuelist);
- rq->cmd_flags &= ~REQ_QUEUED;
- } else
- blk_queue_end_tag(q, rq);
- rq->cmd_flags &= ~REQ_STARTED;
- __elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 0);
- }
+ list_for_each_safe(tmp, n, &q->tag_busy_list)
+ blk_requeue_request(q, list_entry_rq(tmp));
}
EXPORT_SYMBOL(blk_queue_invalidate_tags);
@@ -1329,10 +1302,11 @@ static int blk_hw_contig_segment(struct request_queue *q, struct bio *bio,
* must make sure sg can hold rq->nr_phys_segments entries
*/
int blk_rq_map_sg(struct request_queue *q, struct request *rq,
- struct scatterlist *sg)
+ struct scatterlist *sglist)
{
struct bio_vec *bvec, *bvprv;
struct req_iterator iter;
+ struct scatterlist *sg;
int nsegs, cluster;
nsegs = 0;
@@ -1342,11 +1316,12 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq,
* for each bio in rq
*/
bvprv = NULL;
+ sg = NULL;
rq_for_each_segment(bvec, rq, iter) {
int nbytes = bvec->bv_len;
if (bvprv && cluster) {
- if (sg[nsegs - 1].length + nbytes > q->max_segment_size)
+ if (sg->length + nbytes > q->max_segment_size)
goto new_segment;
if (!BIOVEC_PHYS_MERGEABLE(bvprv, bvec))
@@ -1354,19 +1329,35 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq,
if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bvec))
goto new_segment;
- sg[nsegs - 1].length += nbytes;
+ sg->length += nbytes;
} else {
new_segment:
- memset(&sg[nsegs],0,sizeof(struct scatterlist));
- sg[nsegs].page = bvec->bv_page;
- sg[nsegs].length = nbytes;
- sg[nsegs].offset = bvec->bv_offset;
+ if (!sg)
+ sg = sglist;
+ else {
+ /*
+ * If the driver previously mapped a shorter
+ * list, we could see a termination bit
+ * prematurely unless it fully inits the sg
+ * table on each mapping. We KNOW that there
+ * must be more entries here or the driver
+ * would be buggy, so force clear the
+ * termination bit to avoid doing a full
+ * sg_init_table() in drivers for each command.
+ */
+ sg->page_link &= ~0x02;
+ sg = sg_next(sg);
+ }
+ sg_set_page(sg, bvec->bv_page, nbytes, bvec->bv_offset);
nsegs++;
}
bvprv = bvec;
} /* segments in rq */
+ if (sg)
+ sg_mark_end(sg);
+
return nsegs;
}
@@ -1630,15 +1621,7 @@ static void blk_backing_dev_unplug(struct backing_dev_info *bdi,
{
struct request_queue *q = bdi->unplug_io_data;
- /*
- * devices don't necessarily have an ->unplug_fn defined
- */
- if (q->unplug_fn) {
- blk_add_trace_pdu_int(q, BLK_TA_UNPLUG_IO, NULL,
- q->rq.count[READ] + q->rq.count[WRITE]);
-
- q->unplug_fn(q);
- }
+ blk_unplug(q);
}
static void blk_unplug_work(struct work_struct *work)
@@ -1662,6 +1645,20 @@ static void blk_unplug_timeout(unsigned long data)
kblockd_schedule_work(&q->unplug_work);
}
+void blk_unplug(struct request_queue *q)
+{
+ /*
+ * devices don't necessarily have an ->unplug_fn defined
+ */
+ if (q->unplug_fn) {
+ blk_add_trace_pdu_int(q, BLK_TA_UNPLUG_IO, NULL,
+ q->rq.count[READ] + q->rq.count[WRITE]);
+
+ q->unplug_fn(q);
+ }
+}
+EXPORT_SYMBOL(blk_unplug);
+
/**
* blk_start_queue - restart a previously stopped queue
* @q: The &struct request_queue in question
@@ -1730,6 +1727,7 @@ EXPORT_SYMBOL(blk_stop_queue);
void blk_sync_queue(struct request_queue *q)
{
del_timer_sync(&q->unplug_timer);
+ kblockd_flush_work(&q->unplug_work);
}
EXPORT_SYMBOL(blk_sync_queue);
@@ -1793,6 +1791,7 @@ static void blk_release_queue(struct kobject *kobj)
blk_trace_shutdown(q);
+ bdi_destroy(&q->backing_dev_info);
kmem_cache_free(requestq_cachep, q);
}
@@ -1846,21 +1845,27 @@ static struct kobj_type queue_ktype;
struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
{
struct request_queue *q;
+ int err;
q = kmem_cache_alloc_node(requestq_cachep,
gfp_mask | __GFP_ZERO, node_id);
if (!q)
return NULL;
+ q->backing_dev_info.unplug_io_fn = blk_backing_dev_unplug;
+ q->backing_dev_info.unplug_io_data = q;
+ err = bdi_init(&q->backing_dev_info);
+ if (err) {
+ kmem_cache_free(requestq_cachep, q);
+ return NULL;
+ }
+
init_timer(&q->unplug_timer);
kobject_set_name(&q->kobj, "%s", "queue");
q->kobj.ktype = &queue_ktype;
kobject_init(&q->kobj);
- q->backing_dev_info.unplug_io_fn = blk_backing_dev_unplug;
- q->backing_dev_info.unplug_io_data = q;
-
mutex_init(&q->sysfs_lock);
return q;
@@ -2326,7 +2331,7 @@ void blk_insert_request(struct request_queue *q, struct request *rq,
if (blk_rq_tagged(rq))
blk_queue_end_tag(q, rq);
- drive_stat_acct(rq, rq->nr_sectors, 1);
+ drive_stat_acct(rq, 1);
__elv_add_request(q, rq, where, 0);
blk_start_queueing(q);
spin_unlock_irqrestore(q->queue_lock, flags);
@@ -2660,6 +2665,14 @@ int blk_execute_rq(struct request_queue *q, struct gendisk *bd_disk,
EXPORT_SYMBOL(blk_execute_rq);
+static void bio_end_empty_barrier(struct bio *bio, int err)
+{
+ if (err)
+ clear_bit(BIO_UPTODATE, &bio->bi_flags);
+
+ complete(bio->bi_private);
+}
+
/**
* blkdev_issue_flush - queue a flush
* @bdev: blockdev to issue flush for
@@ -2672,7 +2685,10 @@ EXPORT_SYMBOL(blk_execute_rq);
*/
int blkdev_issue_flush(struct block_device *bdev, sector_t *error_sector)
{
+ DECLARE_COMPLETION_ONSTACK(wait);
struct request_queue *q;
+ struct bio *bio;
+ int ret;
if (bdev->bd_disk == NULL)
return -ENXIO;
@@ -2680,15 +2696,37 @@ int blkdev_issue_flush(struct block_device *bdev, sector_t *error_sector)
q = bdev_get_queue(bdev);
if (!q)
return -ENXIO;
- if (!q->issue_flush_fn)
- return -EOPNOTSUPP;
- return q->issue_flush_fn(q, bdev->bd_disk, error_sector);
+ bio = bio_alloc(GFP_KERNEL, 0);
+ if (!bio)
+ return -ENOMEM;
+
+ bio->bi_end_io = bio_end_empty_barrier;
+ bio->bi_private = &wait;
+ bio->bi_bdev = bdev;
+ submit_bio(1 << BIO_RW_BARRIER, bio);
+
+ wait_for_completion(&wait);
+
+ /*
+ * The driver must store the error location in ->bi_sector, if
+ * it supports it. For non-stacked drivers, this should be copied
+ * from rq->sector.
+ */
+ if (error_sector)
+ *error_sector = bio->bi_sector;
+
+ ret = 0;
+ if (!bio_flagged(bio, BIO_UPTODATE))
+ ret = -EIO;
+
+ bio_put(bio);
+ return ret;
}
EXPORT_SYMBOL(blkdev_issue_flush);
-static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io)
+static void drive_stat_acct(struct request *rq, int new_io)
{
int rw = rq_data_dir(rq);
@@ -2710,7 +2748,7 @@ static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io)
*/
static inline void add_request(struct request_queue * q, struct request * req)
{
- drive_stat_acct(req, req->nr_sectors, 1);
+ drive_stat_acct(req, 1);
/*
* elevator indicated where it wants this request to be
@@ -2967,7 +3005,7 @@ static int __make_request(struct request_queue *q, struct bio *bio)
req->biotail = bio;
req->nr_sectors = req->hard_nr_sectors += nr_sectors;
req->ioprio = ioprio_best(req->ioprio, prio);
- drive_stat_acct(req, nr_sectors, 0);
+ drive_stat_acct(req, 0);
if (!attempt_back_merge(q, req))
elv_merged_request(q, req, el_ret);
goto out;
@@ -2994,7 +3032,7 @@ static int __make_request(struct request_queue *q, struct bio *bio)
req->sector = req->hard_sector = bio->bi_sector;
req->nr_sectors = req->hard_nr_sectors += nr_sectors;
req->ioprio = ioprio_best(req->ioprio, prio);
- drive_stat_acct(req, nr_sectors, 0);
+ drive_stat_acct(req, 0);
if (!attempt_front_merge(q, req))
elv_merged_request(q, req, el_ret);
goto out;
@@ -3051,7 +3089,7 @@ static inline void blk_partition_remap(struct bio *bio)
{
struct block_device *bdev = bio->bi_bdev;
- if (bdev != bdev->bd_contains) {
+ if (bio_sectors(bio) && bdev != bdev->bd_contains) {
struct hd_struct *p = bdev->bd_part;
const int rw = bio_data_dir(bio);
@@ -3117,6 +3155,35 @@ static inline int should_fail_request(struct bio *bio)
#endif /* CONFIG_FAIL_MAKE_REQUEST */
+/*
+ * Check whether this bio extends beyond the end of the device.
+ */
+static inline int bio_check_eod(struct bio *bio, unsigned int nr_sectors)
+{
+ sector_t maxsector;
+
+ if (!nr_sectors)
+ return 0;
+
+ /* Test device or partition size, when known. */
+ maxsector = bio->bi_bdev->bd_inode->i_size >> 9;
+ if (maxsector) {
+ sector_t sector = bio->bi_sector;
+
+ if (maxsector < nr_sectors || maxsector - nr_sectors < sector) {
+ /*
+ * This may well happen - the kernel calls bread()
+ * without checking the size of the device, e.g., when
+ * mounting a device.
+ */
+ handle_bad_sector(bio);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
/**
* generic_make_request: hand a buffer to its device driver for I/O
* @bio: The bio describing the location in memory and on the device.
@@ -3144,27 +3211,15 @@ static inline int should_fail_request(struct bio *bio)
static inline void __generic_make_request(struct bio *bio)
{
struct request_queue *q;
- sector_t maxsector;
sector_t old_sector;
int ret, nr_sectors = bio_sectors(bio);
dev_t old_dev;
+ int err = -EIO;
might_sleep();
- /* Test device or partition size, when known. */
- maxsector = bio->bi_bdev->bd_inode->i_size >> 9;
- if (maxsector) {
- sector_t sector = bio->bi_sector;
- if (maxsector < nr_sectors || maxsector - nr_sectors < sector) {
- /*
- * This may well happen - the kernel calls bread()
- * without checking the size of the device, e.g., when
- * mounting a device.
- */
- handle_bad_sector(bio);
- goto end_io;
- }
- }
+ if (bio_check_eod(bio, nr_sectors))
+ goto end_io;
/*
* Resolve the mapping until finished. (drivers are
@@ -3187,11 +3242,11 @@ static inline void __generic_make_request(struct bio *bio)
bdevname(bio->bi_bdev, b),
(long long) bio->bi_sector);
end_io:
- bio_endio(bio, -EIO);
+ bio_endio(bio, err);
break;
}
- if (unlikely(bio_sectors(bio) > q->max_hw_sectors)) {
+ if (unlikely(nr_sectors > q->max_hw_sectors)) {
printk("bio too big device %s (%u > %u)\n",
bdevname(bio->bi_bdev, b),
bio_sectors(bio),
@@ -3212,7 +3267,7 @@ end_io:
blk_partition_remap(bio);
if (old_sector != -1)
- blk_add_trace_remap(q, bio, old_dev, bio->bi_sector,
+ blk_add_trace_remap(q, bio, old_dev, bio->bi_sector,
old_sector);
blk_add_trace_bio(q, bio, BLK_TA_QUEUE);
@@ -3220,20 +3275,11 @@ end_io:
old_sector = bio->bi_sector;
old_dev = bio->bi_bdev->bd_dev;
- maxsector = bio->bi_bdev->bd_inode->i_size >> 9;
- if (maxsector) {
- sector_t sector = bio->bi_sector;
-
- if (maxsector < nr_sectors ||
- maxsector - nr_sectors < sector) {
- /*
- * This may well happen - partitions are not
- * checked to make sure they are within the size
- * of the whole device.
- */
- handle_bad_sector(bio);
- goto end_io;
- }
+ if (bio_check_eod(bio, nr_sectors))
+ goto end_io;
+ if (bio_empty_barrier(bio) && !q->prepare_flush_fn) {
+ err = -EOPNOTSUPP;
+ goto end_io;
}
ret = q->make_request_fn(q, bio);
@@ -3307,23 +3353,32 @@ void submit_bio(int rw, struct bio *bio)
{
int count = bio_sectors(bio);
- BIO_BUG_ON(!bio->bi_size);
- BIO_BUG_ON(!bio->bi_io_vec);
bio->bi_rw |= rw;
- if (rw & WRITE) {
- count_vm_events(PGPGOUT, count);
- } else {
- task_io_account_read(bio->bi_size);
- count_vm_events(PGPGIN, count);
- }
- if (unlikely(block_dump)) {
- char b[BDEVNAME_SIZE];
- printk(KERN_DEBUG "%s(%d): %s block %Lu on %s\n",
- current->comm, current->pid,
- (rw & WRITE) ? "WRITE" : "READ",
- (unsigned long long)bio->bi_sector,
- bdevname(bio->bi_bdev,b));
+ /*
+ * If it's a regular read/write or a barrier with data attached,
+ * go through the normal accounting stuff before submission.
+ */
+ if (!bio_empty_barrier(bio)) {
+
+ BIO_BUG_ON(!bio->bi_size);
+ BIO_BUG_ON(!bio->bi_io_vec);
+
+ if (rw & WRITE) {
+ count_vm_events(PGPGOUT, count);
+ } else {
+ task_io_account_read(bio->bi_size);
+ count_vm_events(PGPGIN, count);
+ }
+
+ if (unlikely(block_dump)) {
+ char b[BDEVNAME_SIZE];
+ printk(KERN_DEBUG "%s(%d): %s block %Lu on %s\n",
+ current->comm, task_pid_nr(current),
+ (rw & WRITE) ? "WRITE" : "READ",
+ (unsigned long long)bio->bi_sector,
+ bdevname(bio->bi_bdev,b));
+ }
}
generic_make_request(bio);
@@ -3399,6 +3454,14 @@ static int __end_that_request_first(struct request *req, int uptodate,
while ((bio = req->bio) != NULL) {
int nbytes;
+ /*
+ * For an empty barrier request, the low level driver must
+ * store a potential error location in ->sector. We pass
+ * that back up in ->bi_sector.
+ */
+ if (blk_empty_barrier(req))
+ bio->bi_sector = req->sector;
+
if (nr_bytes >= bio->bi_size) {
req->bio = bio->bi_next;
nbytes = bio->bi_size;
@@ -3564,7 +3627,7 @@ static struct notifier_block blk_cpu_notifier __cpuinitdata = {
* Description:
* Ends all I/O on a request. It does not handle partial completions,
* unless the driver actually implements this in its completion callback
- * through requeueing. Theh actual completion happens out-of-order,
+ * through requeueing. The actual completion happens out-of-order,
* through a softirq handler. The user must have registered a completion
* callback through blk_queue_softirq_done().
**/
@@ -3627,15 +3690,83 @@ void end_that_request_last(struct request *req, int uptodate)
EXPORT_SYMBOL(end_that_request_last);
-void end_request(struct request *req, int uptodate)
+static inline void __end_request(struct request *rq, int uptodate,
+ unsigned int nr_bytes, int dequeue)
{
- if (!end_that_request_first(req, uptodate, req->hard_cur_sectors)) {
- add_disk_randomness(req->rq_disk);
- blkdev_dequeue_request(req);
- end_that_request_last(req, uptodate);
+ if (!end_that_request_chunk(rq, uptodate, nr_bytes)) {
+ if (dequeue)
+ blkdev_dequeue_request(rq);
+ add_disk_randomness(rq->rq_disk);
+ end_that_request_last(rq, uptodate);
}
}
+static unsigned int rq_byte_size(struct request *rq)
+{
+ if (blk_fs_request(rq))
+ return rq->hard_nr_sectors << 9;
+
+ return rq->data_len;
+}
+
+/**
+ * end_queued_request - end all I/O on a queued request
+ * @rq: the request being processed
+ * @uptodate: error value or 0/1 uptodate flag
+ *
+ * Description:
+ * Ends all I/O on a request, and removes it from the block layer queues.
+ * Not suitable for normal IO completion, unless the driver still has
+ * the request attached to the block layer.
+ *
+ **/
+void end_queued_request(struct request *rq, int uptodate)
+{
+ __end_request(rq, uptodate, rq_byte_size(rq), 1);
+}
+EXPORT_SYMBOL(end_queued_request);
+
+/**
+ * end_dequeued_request - end all I/O on a dequeued request
+ * @rq: the request being processed
+ * @uptodate: error value or 0/1 uptodate flag
+ *
+ * Description:
+ * Ends all I/O on a request. The request must already have been
+ * dequeued using blkdev_dequeue_request(), as is normally the case
+ * for most drivers.
+ *
+ **/
+void end_dequeued_request(struct request *rq, int uptodate)
+{
+ __end_request(rq, uptodate, rq_byte_size(rq), 0);
+}
+EXPORT_SYMBOL(end_dequeued_request);
+
+
+/**
+ * end_request - end I/O on the current segment of the request
+ * @req: the request being processed
+ * @uptodate: error value or 0/1 uptodate flag
+ *
+ * Description:
+ * Ends I/O on the current segment of a request. If that is the only
+ * remaining segment, the request is also completed and freed.
+ *
+ * This is a remnant of how older block drivers handled IO completions.
+ * Modern drivers typically end IO on the full request in one go, unless
+ * they have a residual value to account for. For that case this function
+ * isn't really useful, unless the residual just happens to be the
+ * full current segment. In other words, don't use this function in new
+ * code. Either use end_request_completely(), or the
+ * end_that_request_chunk() (along with end_that_request_last()) for
+ * partial completions.
+ *
+ **/
+void end_request(struct request *req, int uptodate)
+{
+ __end_request(req, uptodate, req->hard_cur_sectors << 9, 1);
+}
EXPORT_SYMBOL(end_request);
static void blk_rq_bio_prep(struct request_queue *q, struct request *rq,
@@ -3928,7 +4059,6 @@ queue_max_sectors_store(struct request_queue *q, const char *page, size_t count)
max_hw_sectors_kb = q->max_hw_sectors >> 1,
page_kb = 1 << (PAGE_CACHE_SHIFT - 10);
ssize_t ret = queue_var_store(&max_sectors_kb, page, count);
- int ra_kb;
if (max_sectors_kb > max_hw_sectors_kb || max_sectors_kb < page_kb)
return -EINVAL;
@@ -3937,14 +4067,6 @@ queue_max_sectors_store(struct request_queue *q, const char *page, size_t count)
* values synchronously:
*/
spin_lock_irq(q->queue_lock);
- /*
- * Trim readahead window as well, if necessary:
- */
- ra_kb = q->backing_dev_info.ra_pages << (PAGE_CACHE_SHIFT - 10);
- if (ra_kb > max_sectors_kb)
- q->backing_dev_info.ra_pages =
- max_sectors_kb >> (PAGE_CACHE_SHIFT - 10);
-
q->max_sectors = max_sectors_kb << 1;
spin_unlock_irq(q->queue_lock);
@@ -3958,7 +4080,23 @@ static ssize_t queue_max_hw_sectors_show(struct request_queue *q, char *page)
return queue_var_show(max_hw_sectors_kb, (page));
}
+static ssize_t queue_max_segments_show(struct request_queue *q, char *page)
+{
+ return queue_var_show(q->max_phys_segments, page);
+}
+
+static ssize_t queue_max_segments_store(struct request_queue *q,
+ const char *page, size_t count)
+{
+ unsigned long segments;
+ ssize_t ret = queue_var_store(&segments, page, count);
+ spin_lock_irq(q->queue_lock);
+ q->max_phys_segments = segments;
+ spin_unlock_irq(q->queue_lock);
+
+ return ret;
+}
static struct queue_sysfs_entry queue_requests_entry = {
.attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR },
.show = queue_requests_show,
@@ -3982,6 +4120,12 @@ static struct queue_sysfs_entry queue_max_hw_sectors_entry = {
.show = queue_max_hw_sectors_show,
};
+static struct queue_sysfs_entry queue_max_segments_entry = {
+ .attr = {.name = "max_segments", .mode = S_IRUGO | S_IWUSR },
+ .show = queue_max_segments_show,
+ .store = queue_max_segments_store,
+};
+
static struct queue_sysfs_entry queue_iosched_entry = {
.attr = {.name = "scheduler", .mode = S_IRUGO | S_IWUSR },
.show = elv_iosched_show,
@@ -3993,6 +4137,7 @@ static struct attribute *default_attrs[] = {
&queue_ra_entry.attr,
&queue_max_hw_sectors_entry.attr,
&queue_max_sectors_entry.attr,
+ &queue_max_segments_entry.attr,
&queue_iosched_entry.attr,
NULL,
};
diff --git a/crypto/anubis.c b/crypto/anubis.c
index 1c771f7f4dc5..4ff0e1e243ad 100644
--- a/crypto/anubis.c
+++ b/crypto/anubis.c
@@ -33,7 +33,6 @@
#include <linux/module.h>
#include <linux/mm.h>
#include <asm/byteorder.h>
-#include <asm/scatterlist.h>
#include <linux/crypto.h>
#include <linux/types.h>
diff --git a/crypto/api.c b/crypto/api.c
index 4ccc5af6c265..1f5c72477356 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -6,7 +6,7 @@
* Copyright (c) 2005 Herbert Xu <herbert@gondor.apana.org.au>
*
* Portions derived from Cryptoapi, by Alexander Kjeldaas <astor@fast.no>
- * and Nettle, by Niels Möller.
+ * and Nettle, by Niels Möller.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/crypto/blowfish.c b/crypto/blowfish.c
index 55238c4e37f0..80c3fd8be97c 100644
--- a/crypto/blowfish.c
+++ b/crypto/blowfish.c
@@ -20,7 +20,6 @@
#include <linux/module.h>
#include <linux/mm.h>
#include <asm/byteorder.h>
-#include <asm/scatterlist.h>
#include <linux/crypto.h>
#include <linux/types.h>
diff --git a/crypto/compress.c b/crypto/compress.c
index 0a6570048c1e..1ee357085d3a 100644
--- a/crypto/compress.c
+++ b/crypto/compress.c
@@ -14,7 +14,6 @@
#include <linux/types.h>
#include <linux/crypto.h>
#include <linux/errno.h>
-#include <asm/scatterlist.h>
#include <linux/string.h>
#include "internal.h"
diff --git a/crypto/crypto_null.c b/crypto/crypto_null.c
index 24dbb5d8617e..29f77477d701 100644
--- a/crypto/crypto_null.c
+++ b/crypto/crypto_null.c
@@ -19,7 +19,6 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mm.h>
-#include <asm/scatterlist.h>
#include <linux/crypto.h>
#include <linux/string.h>
diff --git a/crypto/digest.c b/crypto/digest.c
index 1bf7414aeb9e..8871dec8cae7 100644
--- a/crypto/digest.c
+++ b/crypto/digest.c
@@ -41,7 +41,7 @@ static int update2(struct hash_desc *desc,
return 0;
for (;;) {
- struct page *pg = sg->page;
+ struct page *pg = sg_page(sg);
unsigned int offset = sg->offset;
unsigned int l = sg->length;
@@ -77,7 +77,7 @@ static int update2(struct hash_desc *desc,
if (!nbytes)
break;
- sg = sg_next(sg);
+ sg = scatterwalk_sg_next(sg);
}
return 0;
diff --git a/crypto/fcrypt.c b/crypto/fcrypt.c
index 9c2bb535b09a..d161949fdb94 100644
--- a/crypto/fcrypt.c
+++ b/crypto/fcrypt.c
@@ -10,7 +10,7 @@
*
* Based on code:
*
- * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan
+ * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
diff --git a/crypto/hmac.c b/crypto/hmac.c
index 8802fb6dd5a6..0f05be769c34 100644
--- a/crypto/hmac.c
+++ b/crypto/hmac.c
@@ -61,7 +61,7 @@ static int hmac_setkey(struct crypto_hash *parent,
desc.tfm = tfm;
desc.flags = crypto_hash_get_flags(parent);
desc.flags &= CRYPTO_TFM_REQ_MAY_SLEEP;
- sg_set_buf(&tmp, inkey, keylen);
+ sg_init_one(&tmp, inkey, keylen);
err = crypto_hash_digest(&desc, &tmp, keylen, digest);
if (err)
@@ -96,7 +96,7 @@ static int hmac_init(struct hash_desc *pdesc)
desc.tfm = ctx->child;
desc.flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
- sg_set_buf(&tmp, ipad, bs);
+ sg_init_one(&tmp, ipad, bs);
err = crypto_hash_init(&desc);
if (unlikely(err))
@@ -131,7 +131,7 @@ static int hmac_final(struct hash_desc *pdesc, u8 *out)
desc.tfm = ctx->child;
desc.flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
- sg_set_buf(&tmp, opad, bs + ds);
+ sg_init_one(&tmp, opad, bs + ds);
err = crypto_hash_final(&desc, digest);
if (unlikely(err))
@@ -158,9 +158,11 @@ static int hmac_digest(struct hash_desc *pdesc, struct scatterlist *sg,
desc.tfm = ctx->child;
desc.flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
+ sg_init_table(sg1, 2);
sg_set_buf(sg1, ipad, bs);
- sg1[1].page = (void *)sg;
- sg1[1].length = 0;
+ sg_set_page(&sg1[1], (void *) sg, 0, 0);
+
+ sg_init_table(sg2, 1);
sg_set_buf(sg2, opad, bs + ds);
err = crypto_hash_digest(&desc, sg1, nbytes + bs, digest);
diff --git a/crypto/khazad.c b/crypto/khazad.c
index 9fa24a2dd6ff..704ebfe26b55 100644
--- a/crypto/khazad.c
+++ b/crypto/khazad.c
@@ -23,7 +23,6 @@
#include <linux/module.h>
#include <linux/mm.h>
#include <asm/byteorder.h>
-#include <asm/scatterlist.h>
#include <linux/crypto.h>
#include <linux/types.h>
diff --git a/crypto/scatterwalk.c b/crypto/scatterwalk.c
index 3052f6507f53..b9bbda0bb9f9 100644
--- a/crypto/scatterwalk.c
+++ b/crypto/scatterwalk.c
@@ -54,7 +54,7 @@ static void scatterwalk_pagedone(struct scatter_walk *walk, int out,
if (out) {
struct page *page;
- page = walk->sg->page + ((walk->offset - 1) >> PAGE_SHIFT);
+ page = sg_page(walk->sg) + ((walk->offset - 1) >> PAGE_SHIFT);
flush_dcache_page(page);
}
@@ -62,7 +62,7 @@ static void scatterwalk_pagedone(struct scatter_walk *walk, int out,
walk->offset += PAGE_SIZE - 1;
walk->offset &= PAGE_MASK;
if (walk->offset >= walk->sg->offset + walk->sg->length)
- scatterwalk_start(walk, sg_next(walk->sg));
+ scatterwalk_start(walk, scatterwalk_sg_next(walk->sg));
}
}
diff --git a/crypto/scatterwalk.h b/crypto/scatterwalk.h
index 500a220ad908..87ed681cceba 100644
--- a/crypto/scatterwalk.h
+++ b/crypto/scatterwalk.h
@@ -20,15 +20,15 @@
#include "internal.h"
-static inline struct scatterlist *sg_next(struct scatterlist *sg)
+static inline struct scatterlist *scatterwalk_sg_next(struct scatterlist *sg)
{
- return (++sg)->length ? sg : (void *)sg->page;
+ return (++sg)->length ? sg : (void *) sg_page(sg);
}
static inline unsigned long scatterwalk_samebuf(struct scatter_walk *walk_in,
struct scatter_walk *walk_out)
{
- return !(((walk_in->sg->page - walk_out->sg->page) << PAGE_SHIFT) +
+ return !(((sg_page(walk_in->sg) - sg_page(walk_out->sg)) << PAGE_SHIFT) +
(int)(walk_in->offset - walk_out->offset));
}
@@ -60,7 +60,7 @@ static inline unsigned int scatterwalk_aligned(struct scatter_walk *walk,
static inline struct page *scatterwalk_page(struct scatter_walk *walk)
{
- return walk->sg->page + (walk->offset >> PAGE_SHIFT);
+ return sg_page(walk->sg) + (walk->offset >> PAGE_SHIFT);
}
static inline void scatterwalk_unmap(void *vaddr, int out)
diff --git a/crypto/sha1_generic.c b/crypto/sha1_generic.c
index 48a3c3e0bf5f..68c62f528eb5 100644
--- a/crypto/sha1_generic.c
+++ b/crypto/sha1_generic.c
@@ -23,7 +23,6 @@
#include <linux/cryptohash.h>
#include <linux/types.h>
#include <crypto/sha.h>
-#include <asm/scatterlist.h>
#include <asm/byteorder.h>
struct sha1_ctx {
diff --git a/crypto/sha256_generic.c b/crypto/sha256_generic.c
index 5f4332edcf6b..fd3918be58b5 100644
--- a/crypto/sha256_generic.c
+++ b/crypto/sha256_generic.c
@@ -22,7 +22,6 @@
#include <linux/crypto.h>
#include <linux/types.h>
#include <crypto/sha.h>
-#include <asm/scatterlist.h>
#include <asm/byteorder.h>
struct sha256_ctx {
diff --git a/crypto/sha512.c b/crypto/sha512.c
index e736596ca574..c39c803ecc02 100644
--- a/crypto/sha512.c
+++ b/crypto/sha512.c
@@ -19,7 +19,6 @@
#include <linux/types.h>
#include <crypto/sha.h>
-#include <asm/scatterlist.h>
#include <asm/byteorder.h>
struct sha512_ctx {
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index 18d489c8b935..24141fb6f5cb 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -139,7 +139,7 @@ static void test_hash(char *algo, struct hash_testvec *template,
printk("test %u:\n", i + 1);
memset(result, 0, 64);
- sg_set_buf(&sg[0], hash_tv[i].plaintext, hash_tv[i].psize);
+ sg_init_one(&sg[0], hash_tv[i].plaintext, hash_tv[i].psize);
if (hash_tv[i].ksize) {
ret = crypto_hash_setkey(tfm, hash_tv[i].key,
@@ -176,6 +176,7 @@ static void test_hash(char *algo, struct hash_testvec *template,
memset(result, 0, 64);
temp = 0;
+ sg_init_table(sg, hash_tv[i].np);
for (k = 0; k < hash_tv[i].np; k++) {
memcpy(&xbuf[IDX[k]],
hash_tv[i].plaintext + temp,
@@ -289,8 +290,8 @@ static void test_cipher(char *algo, int enc,
goto out;
}
- sg_set_buf(&sg[0], cipher_tv[i].input,
- cipher_tv[i].ilen);
+ sg_init_one(&sg[0], cipher_tv[i].input,
+ cipher_tv[i].ilen);
ablkcipher_request_set_crypt(req, sg, sg,
cipher_tv[i].ilen,
@@ -317,7 +318,7 @@ static void test_cipher(char *algo, int enc,
goto out;
}
- q = kmap(sg[0].page) + sg[0].offset;
+ q = kmap(sg_page(&sg[0])) + sg[0].offset;
hexdump(q, cipher_tv[i].rlen);
printk("%s\n",
@@ -353,6 +354,7 @@ static void test_cipher(char *algo, int enc,
}
temp = 0;
+ sg_init_table(sg, cipher_tv[i].np);
for (k = 0; k < cipher_tv[i].np; k++) {
memcpy(&xbuf[IDX[k]],
cipher_tv[i].input + temp,
@@ -390,7 +392,7 @@ static void test_cipher(char *algo, int enc,
temp = 0;
for (k = 0; k < cipher_tv[i].np; k++) {
printk("page %u\n", k);
- q = kmap(sg[k].page) + sg[k].offset;
+ q = kmap(sg_page(&sg[k])) + sg[k].offset;
hexdump(q, cipher_tv[i].tap[k]);
printk("%s\n",
memcmp(q, cipher_tv[i].result + temp,
@@ -414,7 +416,7 @@ static int test_cipher_jiffies(struct blkcipher_desc *desc, int enc, char *p,
int bcount;
int ret;
- sg_set_buf(sg, p, blen);
+ sg_init_one(sg, p, blen);
for (start = jiffies, end = start + sec * HZ, bcount = 0;
time_before(jiffies, end); bcount++) {
@@ -440,7 +442,7 @@ static int test_cipher_cycles(struct blkcipher_desc *desc, int enc, char *p,
int ret = 0;
int i;
- sg_set_buf(sg, p, blen);
+ sg_init_one(sg, p, blen);
local_bh_disable();
local_irq_disable();
@@ -570,6 +572,8 @@ static int test_hash_jiffies_digest(struct hash_desc *desc, char *p, int blen,
int bcount;
int ret;
+ sg_init_table(sg, 1);
+
for (start = jiffies, end = start + sec * HZ, bcount = 0;
time_before(jiffies, end); bcount++) {
sg_set_buf(sg, p, blen);
@@ -595,6 +599,8 @@ static int test_hash_jiffies(struct hash_desc *desc, char *p, int blen,
if (plen == blen)
return test_hash_jiffies_digest(desc, p, blen, out, sec);
+ sg_init_table(sg, 1);
+
for (start = jiffies, end = start + sec * HZ, bcount = 0;
time_before(jiffies, end); bcount++) {
ret = crypto_hash_init(desc);
@@ -626,6 +632,8 @@ static int test_hash_cycles_digest(struct hash_desc *desc, char *p, int blen,
int i;
int ret;
+ sg_init_table(sg, 1);
+
local_bh_disable();
local_irq_disable();
@@ -677,6 +685,8 @@ static int test_hash_cycles(struct hash_desc *desc, char *p, int blen,
if (plen == blen)
return test_hash_cycles_digest(desc, p, blen, out);
+ sg_init_table(sg, 1);
+
local_bh_disable();
local_irq_disable();
diff --git a/crypto/tea.c b/crypto/tea.c
index 1c54e26fa529..6893b3fdf9d6 100644
--- a/crypto/tea.c
+++ b/crypto/tea.c
@@ -23,7 +23,6 @@
#include <linux/module.h>
#include <linux/mm.h>
#include <asm/byteorder.h>
-#include <asm/scatterlist.h>
#include <linux/crypto.h>
#include <linux/types.h>
diff --git a/crypto/tgr192.c b/crypto/tgr192.c
index a0fadf3dd3e2..2e7ea1680c7f 100644
--- a/crypto/tgr192.c
+++ b/crypto/tgr192.c
@@ -25,7 +25,6 @@
#include <linux/module.h>
#include <linux/mm.h>
#include <asm/byteorder.h>
-#include <asm/scatterlist.h>
#include <linux/crypto.h>
#include <linux/types.h>
diff --git a/crypto/wp512.c b/crypto/wp512.c
index 727d05a19ff4..f746952b93fc 100644
--- a/crypto/wp512.c
+++ b/crypto/wp512.c
@@ -23,7 +23,6 @@
#include <linux/module.h>
#include <linux/mm.h>
#include <asm/byteorder.h>
-#include <asm/scatterlist.h>
#include <linux/crypto.h>
#include <linux/types.h>
diff --git a/crypto/xcbc.c b/crypto/xcbc.c
index 9f502b86e0ea..ac68f3b62fde 100644
--- a/crypto/xcbc.c
+++ b/crypto/xcbc.c
@@ -120,7 +120,7 @@ static int crypto_xcbc_digest_update2(struct hash_desc *pdesc,
do {
- struct page *pg = sg[i].page;
+ struct page *pg = sg_page(&sg[i]);
unsigned int offset = sg[i].offset;
unsigned int slen = sg[i].length;
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 7bdae47d6b91..f4076d9e9902 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -58,6 +58,8 @@ source "drivers/power/Kconfig"
source "drivers/hwmon/Kconfig"
+source "drivers/watchdog/Kconfig"
+
source "drivers/ssb/Kconfig"
source "drivers/mfd/Kconfig"
@@ -84,11 +86,13 @@ source "drivers/rtc/Kconfig"
source "drivers/dma/Kconfig"
+source "drivers/dca/Kconfig"
+
source "drivers/auxdisplay/Kconfig"
source "drivers/kvm/Kconfig"
source "drivers/uio/Kconfig"
-source "drivers/lguest/Kconfig"
+source "drivers/virtio/Kconfig"
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index a168eacdcd9c..8cb37e3557d4 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -34,7 +34,6 @@ obj-$(CONFIG_NUBUS) += nubus/
obj-$(CONFIG_ATM) += atm/
obj-y += macintosh/
obj-$(CONFIG_IDE) += ide/
-obj-$(CONFIG_FC4) += fc4/
obj-$(CONFIG_SCSI) += scsi/
obj-$(CONFIG_ATA) += ata/
obj-$(CONFIG_FUSION) += message/
@@ -66,7 +65,7 @@ obj-y += i2c/
obj-$(CONFIG_W1) += w1/
obj-$(CONFIG_POWER_SUPPLY) += power/
obj-$(CONFIG_HWMON) += hwmon/
-obj-$(CONFIG_WATCHDOG) += char/watchdog/
+obj-$(CONFIG_WATCHDOG) += watchdog/
obj-$(CONFIG_PHONE) += telephony/
obj-$(CONFIG_MD) += md/
obj-$(CONFIG_BT) += bluetooth/
@@ -76,6 +75,7 @@ obj-$(CONFIG_MCA) += mca/
obj-$(CONFIG_EISA) += eisa/
obj-$(CONFIG_LGUEST_GUEST) += lguest/
obj-$(CONFIG_CPU_FREQ) += cpufreq/
+obj-$(CONFIG_CPU_IDLE) += cpuidle/
obj-$(CONFIG_MMC) += mmc/
obj-$(CONFIG_NEW_LEDS) += leds/
obj-$(CONFIG_INFINIBAND) += infiniband/
@@ -85,7 +85,9 @@ obj-$(CONFIG_CRYPTO) += crypto/
obj-$(CONFIG_SUPERH) += sh/
obj-$(CONFIG_GENERIC_TIME) += clocksource/
obj-$(CONFIG_DMA_ENGINE) += dma/
+obj-$(CONFIG_DCA) += dca/
obj-$(CONFIG_HID) += hid/
obj-$(CONFIG_PPC_PS3) += ps3/
obj-$(CONFIG_OF) += of/
obj-$(CONFIG_SSB) += ssb/
+obj-$(CONFIG_VIRTIO) += virtio/
diff --git a/drivers/acorn/char/defkeymap-l7200.c b/drivers/acorn/char/defkeymap-l7200.c
index 9e18ce742e38..28a5fbc6aa1a 100644
--- a/drivers/acorn/char/defkeymap-l7200.c
+++ b/drivers/acorn/char/defkeymap-l7200.c
@@ -346,7 +346,7 @@ char *func_table[MAX_NR_FUNC] = {
0,
};
-struct kbdiacr accent_table[MAX_DIACR] = {
+struct kbdiacruc accent_table[MAX_DIACR] = {
{'`', 'A', '\300'}, {'`', 'a', '\340'},
{'\'', 'A', '\301'}, {'\'', 'a', '\341'},
{'^', 'A', '\302'}, {'^', 'a', '\342'},
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 4875f0149eb4..087a7028ae84 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -3,7 +3,7 @@
#
menuconfig ACPI
- bool "ACPI Support (Advanced Configuration and Power Interface) Support"
+ bool "ACPI (Advanced Configuration and Power Interface) Support"
depends on !X86_NUMAQ
depends on !X86_VISWS
depends on !IA64_HP_SIM
@@ -50,9 +50,10 @@ config ACPI_SLEEP
config ACPI_PROCFS
bool "Deprecated /proc/acpi files"
depends on PROC_FS
+ default y
---help---
For backwards compatibility, this option allows
- depricated /proc/acpi/ files to exist, even when
+ deprecated /proc/acpi/ files to exist, even when
they have been replaced by functions in /sys.
The deprecated files (and their replacements) include:
@@ -60,6 +61,7 @@ config ACPI_PROCFS
/proc/acpi/info (/sys/modules/acpi/parameters/acpica_version)
/proc/acpi/dsdt (/sys/firmware/acpi/tables/DSDT)
/proc/acpi/fadt (/sys/firmware/acpi/tables/FACP)
+ /proc/acpi/battery (/sys/class/power_supply)
/proc/acpi/debug_layer (/sys/module/acpi/parameters/debug_layer)
/proc/acpi/debug_level (/sys/module/acpi/parameters/debug_level)
@@ -89,6 +91,7 @@ config ACPI_PROC_EVENT
config ACPI_AC
tristate "AC Adapter"
depends on X86
+ select POWER_SUPPLY
default y
help
This driver adds support for the AC Adapter object, which indicates
@@ -98,6 +101,7 @@ config ACPI_AC
config ACPI_BATTERY
tristate "Battery"
depends on X86
+ select POWER_SUPPLY
default y
help
This driver adds support for battery information through
@@ -117,6 +121,7 @@ config ACPI_BUTTON
config ACPI_VIDEO
tristate "Video"
depends on X86 && BACKLIGHT_CLASS_DEVICE && VIDEO_OUTPUT_CONTROL
+ depends on INPUT
help
This driver implement the ACPI Extensions For Display Adapters
for integrated graphics devices on motherboard, as specified in
@@ -349,12 +354,11 @@ config ACPI_HOTPLUG_MEMORY
$>modprobe acpi_memhotplug
config ACPI_SBS
- tristate "Smart Battery System (EXPERIMENTAL)"
+ tristate "Smart Battery System"
depends on X86
- depends on EXPERIMENTAL
+ select POWER_SUPPLY
help
- This driver adds support for the Smart Battery System.
- A "Smart Battery" is quite old and quite rare compared
- to today's ACPI "Control Method" battery.
+ This driver adds support for the Smart Battery System, another
+ type of access to battery information, found on some laptops.
endif # ACPI
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index d4336f1730e9..54e3ab0e5fc0 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -60,3 +60,4 @@ obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o
obj-y += cm_sbs.o
obj-$(CONFIG_ACPI_SBS) += sbs.o
+obj-$(CONFIG_ACPI_SBS) += sbshc.o
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index 26d70702b313..30238f6ff232 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -27,8 +27,11 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
+#ifdef CONFIG_ACPI_PROCFS
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#endif
+#include <linux/power_supply.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
@@ -48,12 +51,15 @@ MODULE_AUTHOR("Paul Diefenbaugh");
MODULE_DESCRIPTION("ACPI AC Adapter Driver");
MODULE_LICENSE("GPL");
+#ifdef CONFIG_ACPI_PROCFS
extern struct proc_dir_entry *acpi_lock_ac_dir(void);
extern void *acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir);
+static int acpi_ac_open_fs(struct inode *inode, struct file *file);
+#endif
static int acpi_ac_add(struct acpi_device *device);
static int acpi_ac_remove(struct acpi_device *device, int type);
-static int acpi_ac_open_fs(struct inode *inode, struct file *file);
+static int acpi_ac_resume(struct acpi_device *device);
const static struct acpi_device_id ac_device_ids[] = {
{"ACPI0003", 0},
@@ -68,20 +74,45 @@ static struct acpi_driver acpi_ac_driver = {
.ops = {
.add = acpi_ac_add,
.remove = acpi_ac_remove,
+ .resume = acpi_ac_resume,
},
};
struct acpi_ac {
+ struct power_supply charger;
struct acpi_device * device;
unsigned long state;
};
+#define to_acpi_ac(x) container_of(x, struct acpi_ac, charger);
+
+#ifdef CONFIG_ACPI_PROCFS
static const struct file_operations acpi_ac_fops = {
.open = acpi_ac_open_fs,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
+#endif
+
+static int get_ac_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct acpi_ac *ac = to_acpi_ac(psy);
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = ac->state;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static enum power_supply_property ac_props[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+};
/* --------------------------------------------------------------------------
AC Adapter Management
@@ -105,6 +136,7 @@ static int acpi_ac_get_state(struct acpi_ac *ac)
return 0;
}
+#ifdef CONFIG_ACPI_PROCFS
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
@@ -184,6 +216,7 @@ static int acpi_ac_remove_fs(struct acpi_device *device)
return 0;
}
+#endif
/* --------------------------------------------------------------------------
Driver Model
@@ -208,6 +241,7 @@ static void acpi_ac_notify(acpi_handle handle, u32 event, void *data)
acpi_bus_generate_netlink_event(device->pnp.device_class,
device->dev.bus_id, event,
(u32) ac->state);
+ kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE);
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
@@ -241,10 +275,17 @@ static int acpi_ac_add(struct acpi_device *device)
if (result)
goto end;
+#ifdef CONFIG_ACPI_PROCFS
result = acpi_ac_add_fs(device);
+#endif
if (result)
goto end;
-
+ ac->charger.name = acpi_device_bid(device);
+ ac->charger.type = POWER_SUPPLY_TYPE_MAINS;
+ ac->charger.properties = ac_props;
+ ac->charger.num_properties = ARRAY_SIZE(ac_props);
+ ac->charger.get_property = get_ac_property;
+ power_supply_register(&ac->device->dev, &ac->charger);
status = acpi_install_notify_handler(device->handle,
ACPI_ALL_NOTIFY, acpi_ac_notify,
ac);
@@ -259,13 +300,30 @@ static int acpi_ac_add(struct acpi_device *device)
end:
if (result) {
+#ifdef CONFIG_ACPI_PROCFS
acpi_ac_remove_fs(device);
+#endif
kfree(ac);
}
return result;
}
+static int acpi_ac_resume(struct acpi_device *device)
+{
+ struct acpi_ac *ac;
+ unsigned old_state;
+ if (!device || !acpi_driver_data(device))
+ return -EINVAL;
+ ac = acpi_driver_data(device);
+ old_state = ac->state;
+ if (acpi_ac_get_state(ac))
+ return 0;
+ if (old_state != ac->state)
+ kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE);
+ return 0;
+}
+
static int acpi_ac_remove(struct acpi_device *device, int type)
{
acpi_status status = AE_OK;
@@ -279,8 +337,11 @@ static int acpi_ac_remove(struct acpi_device *device, int type)
status = acpi_remove_notify_handler(device->handle,
ACPI_ALL_NOTIFY, acpi_ac_notify);
-
+ if (ac->charger.dev)
+ power_supply_unregister(&ac->charger);
+#ifdef CONFIG_ACPI_PROCFS
acpi_ac_remove_fs(device);
+#endif
kfree(ac);
@@ -294,13 +355,17 @@ static int __init acpi_ac_init(void)
if (acpi_disabled)
return -ENODEV;
+#ifdef CONFIG_ACPI_PROCFS
acpi_ac_dir = acpi_lock_ac_dir();
if (!acpi_ac_dir)
return -ENODEV;
+#endif
result = acpi_bus_register_driver(&acpi_ac_driver);
if (result < 0) {
+#ifdef CONFIG_ACPI_PROCFS
acpi_unlock_ac_dir(acpi_ac_dir);
+#endif
return -ENODEV;
}
@@ -312,7 +377,9 @@ static void __exit acpi_ac_exit(void)
acpi_bus_unregister_driver(&acpi_ac_driver);
+#ifdef CONFIG_ACPI_PROCFS
acpi_unlock_ac_dir(acpi_ac_dir);
+#endif
return;
}
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 9b2c0f74f869..192c244f6190 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -1,6 +1,8 @@
/*
- * acpi_battery.c - ACPI Battery Driver ($Revision: 37 $)
+ * battery.c - ACPI Battery Driver (Revision: 2.0)
*
+ * Copyright (C) 2007 Alexey Starikovskiy <astarikovskiy@suse.de>
+ * Copyright (C) 2004-2007 Vladimir Lebedev <vladimir.p.lebedev@intel.com>
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
*
@@ -27,244 +29,299 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
+#include <linux/jiffies.h>
+
+#ifdef CONFIG_ACPI_PROCFS
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <asm/uaccess.h>
+#endif
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-#define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF
+#include <linux/power_supply.h>
-#define ACPI_BATTERY_FORMAT_BIF "NNNNNNNNNSSSS"
-#define ACPI_BATTERY_FORMAT_BST "NNNN"
+#define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF
#define ACPI_BATTERY_COMPONENT 0x00040000
#define ACPI_BATTERY_CLASS "battery"
#define ACPI_BATTERY_DEVICE_NAME "Battery"
#define ACPI_BATTERY_NOTIFY_STATUS 0x80
#define ACPI_BATTERY_NOTIFY_INFO 0x81
-#define ACPI_BATTERY_UNITS_WATTS "mW"
-#define ACPI_BATTERY_UNITS_AMPS "mA"
#define _COMPONENT ACPI_BATTERY_COMPONENT
-#define ACPI_BATTERY_UPDATE_TIME 0
-
-#define ACPI_BATTERY_NONE_UPDATE 0
-#define ACPI_BATTERY_EASY_UPDATE 1
-#define ACPI_BATTERY_INIT_UPDATE 2
-
ACPI_MODULE_NAME("battery");
MODULE_AUTHOR("Paul Diefenbaugh");
+MODULE_AUTHOR("Alexey Starikovskiy <astarikovskiy@suse.de>");
MODULE_DESCRIPTION("ACPI Battery Driver");
MODULE_LICENSE("GPL");
-static unsigned int update_time = ACPI_BATTERY_UPDATE_TIME;
-
-/* 0 - every time, > 0 - by update_time */
-module_param(update_time, uint, 0644);
+static unsigned int cache_time = 1000;
+module_param(cache_time, uint, 0644);
+MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
+#ifdef CONFIG_ACPI_PROCFS
extern struct proc_dir_entry *acpi_lock_battery_dir(void);
extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
-static int acpi_battery_add(struct acpi_device *device);
-static int acpi_battery_remove(struct acpi_device *device, int type);
-static int acpi_battery_resume(struct acpi_device *device);
+enum acpi_battery_files {
+ info_tag = 0,
+ state_tag,
+ alarm_tag,
+ ACPI_BATTERY_NUMFILES,
+};
+
+#endif
static const struct acpi_device_id battery_device_ids[] = {
{"PNP0C0A", 0},
{"", 0},
};
-MODULE_DEVICE_TABLE(acpi, battery_device_ids);
-
-static struct acpi_driver acpi_battery_driver = {
- .name = "battery",
- .class = ACPI_BATTERY_CLASS,
- .ids = battery_device_ids,
- .ops = {
- .add = acpi_battery_add,
- .resume = acpi_battery_resume,
- .remove = acpi_battery_remove,
- },
-};
-struct acpi_battery_state {
- acpi_integer state;
- acpi_integer present_rate;
- acpi_integer remaining_capacity;
- acpi_integer present_voltage;
-};
-
-struct acpi_battery_info {
- acpi_integer power_unit;
- acpi_integer design_capacity;
- acpi_integer last_full_capacity;
- acpi_integer battery_technology;
- acpi_integer design_voltage;
- acpi_integer design_capacity_warning;
- acpi_integer design_capacity_low;
- acpi_integer battery_capacity_granularity_1;
- acpi_integer battery_capacity_granularity_2;
- acpi_string model_number;
- acpi_string serial_number;
- acpi_string battery_type;
- acpi_string oem_info;
-};
-
-enum acpi_battery_files{
- ACPI_BATTERY_INFO = 0,
- ACPI_BATTERY_STATE,
- ACPI_BATTERY_ALARM,
- ACPI_BATTERY_NUMFILES,
-};
+MODULE_DEVICE_TABLE(acpi, battery_device_ids);
-struct acpi_battery_flags {
- u8 battery_present_prev;
- u8 alarm_present;
- u8 init_update;
- u8 update[ACPI_BATTERY_NUMFILES];
- u8 power_unit;
-};
struct acpi_battery {
- struct mutex mutex;
+ struct mutex lock;
+ struct power_supply bat;
struct acpi_device *device;
- struct acpi_battery_flags flags;
- struct acpi_buffer bif_data;
- struct acpi_buffer bst_data;
- unsigned long alarm;
- unsigned long update_time[ACPI_BATTERY_NUMFILES];
+ unsigned long update_time;
+ int current_now;
+ int capacity_now;
+ int voltage_now;
+ int design_capacity;
+ int full_charge_capacity;
+ int technology;
+ int design_voltage;
+ int design_capacity_warning;
+ int design_capacity_low;
+ int capacity_granularity_1;
+ int capacity_granularity_2;
+ int alarm;
+ char model_number[32];
+ char serial_number[32];
+ char type[32];
+ char oem_info[32];
+ int state;
+ int power_unit;
+ u8 alarm_present;
};
+#define to_acpi_battery(x) container_of(x, struct acpi_battery, bat);
+
inline int acpi_battery_present(struct acpi_battery *battery)
{
return battery->device->status.battery_present;
}
-inline char *acpi_battery_power_units(struct acpi_battery *battery)
-{
- if (battery->flags.power_unit)
- return ACPI_BATTERY_UNITS_AMPS;
- else
- return ACPI_BATTERY_UNITS_WATTS;
-}
-inline acpi_handle acpi_battery_handle(struct acpi_battery *battery)
+static int acpi_battery_technology(struct acpi_battery *battery)
{
- return battery->device->handle;
+ if (!strcasecmp("NiCd", battery->type))
+ return POWER_SUPPLY_TECHNOLOGY_NiCd;
+ if (!strcasecmp("NiMH", battery->type))
+ return POWER_SUPPLY_TECHNOLOGY_NiMH;
+ if (!strcasecmp("LION", battery->type))
+ return POWER_SUPPLY_TECHNOLOGY_LION;
+ if (!strcasecmp("LI-ION", battery->type))
+ return POWER_SUPPLY_TECHNOLOGY_LION;
+ if (!strcasecmp("LiP", battery->type))
+ return POWER_SUPPLY_TECHNOLOGY_LIPO;
+ return POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
}
-/* --------------------------------------------------------------------------
- Battery Management
- -------------------------------------------------------------------------- */
+static int acpi_battery_get_state(struct acpi_battery *battery);
-static void acpi_battery_check_result(struct acpi_battery *battery, int result)
+static int acpi_battery_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
{
- if (!battery)
- return;
+ struct acpi_battery *battery = to_acpi_battery(psy);
- if (result) {
- battery->flags.init_update = 1;
+ if (acpi_battery_present(battery)) {
+ /* run battery update only if it is present */
+ acpi_battery_get_state(battery);
+ } else if (psp != POWER_SUPPLY_PROP_PRESENT)
+ return -ENODEV;
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ if (battery->state & 0x01)
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ else if (battery->state & 0x02)
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ else if (battery->state == 0)
+ val->intval = POWER_SUPPLY_STATUS_FULL;
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = acpi_battery_present(battery);
+ break;
+ case POWER_SUPPLY_PROP_TECHNOLOGY:
+ val->intval = acpi_battery_technology(battery);
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+ val->intval = battery->design_voltage * 1000;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ val->intval = battery->voltage_now * 1000;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+ val->intval = battery->current_now * 1000;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+ case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
+ val->intval = battery->design_capacity * 1000;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL:
+ case POWER_SUPPLY_PROP_ENERGY_FULL:
+ val->intval = battery->full_charge_capacity * 1000;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_NOW:
+ case POWER_SUPPLY_PROP_ENERGY_NOW:
+ val->intval = battery->capacity_now * 1000;
+ break;
+ case POWER_SUPPLY_PROP_MODEL_NAME:
+ val->strval = battery->model_number;
+ break;
+ case POWER_SUPPLY_PROP_MANUFACTURER:
+ val->strval = battery->oem_info;
+ break;
+ default:
+ return -EINVAL;
}
+ return 0;
}
-static int acpi_battery_extract_package(struct acpi_battery *battery,
- union acpi_object *package,
- struct acpi_buffer *format,
- struct acpi_buffer *data,
- char *package_name)
+static enum power_supply_property charge_battery_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+ POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+ POWER_SUPPLY_PROP_CHARGE_FULL,
+ POWER_SUPPLY_PROP_CHARGE_NOW,
+ POWER_SUPPLY_PROP_MODEL_NAME,
+ POWER_SUPPLY_PROP_MANUFACTURER,
+};
+
+static enum power_supply_property energy_battery_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+ POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
+ POWER_SUPPLY_PROP_ENERGY_FULL,
+ POWER_SUPPLY_PROP_ENERGY_NOW,
+ POWER_SUPPLY_PROP_MODEL_NAME,
+ POWER_SUPPLY_PROP_MANUFACTURER,
+};
+
+#ifdef CONFIG_ACPI_PROCFS
+inline char *acpi_battery_units(struct acpi_battery *battery)
{
- acpi_status status = AE_OK;
- struct acpi_buffer data_null = { 0, NULL };
+ return (battery->power_unit)?"mA":"mW";
+}
+#endif
- status = acpi_extract_package(package, format, &data_null);
- if (status != AE_BUFFER_OVERFLOW) {
- ACPI_EXCEPTION((AE_INFO, status, "Extracting size %s",
- package_name));
- return -ENODEV;
- }
+/* --------------------------------------------------------------------------
+ Battery Management
+ -------------------------------------------------------------------------- */
+struct acpi_offsets {
+ size_t offset; /* offset inside struct acpi_sbs_battery */
+ u8 mode; /* int or string? */
+};
- if (data_null.length != data->length) {
- kfree(data->pointer);
- data->pointer = kzalloc(data_null.length, GFP_KERNEL);
- if (!data->pointer) {
- ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY, "kzalloc()"));
- return -ENOMEM;
- }
- data->length = data_null.length;
- }
+static struct acpi_offsets state_offsets[] = {
+ {offsetof(struct acpi_battery, state), 0},
+ {offsetof(struct acpi_battery, current_now), 0},
+ {offsetof(struct acpi_battery, capacity_now), 0},
+ {offsetof(struct acpi_battery, voltage_now), 0},
+};
- status = acpi_extract_package(package, format, data);
- if (ACPI_FAILURE(status)) {
- ACPI_EXCEPTION((AE_INFO, status, "Extracting %s",
- package_name));
- return -ENODEV;
- }
+static struct acpi_offsets info_offsets[] = {
+ {offsetof(struct acpi_battery, power_unit), 0},
+ {offsetof(struct acpi_battery, design_capacity), 0},
+ {offsetof(struct acpi_battery, full_charge_capacity), 0},
+ {offsetof(struct acpi_battery, technology), 0},
+ {offsetof(struct acpi_battery, design_voltage), 0},
+ {offsetof(struct acpi_battery, design_capacity_warning), 0},
+ {offsetof(struct acpi_battery, design_capacity_low), 0},
+ {offsetof(struct acpi_battery, capacity_granularity_1), 0},
+ {offsetof(struct acpi_battery, capacity_granularity_2), 0},
+ {offsetof(struct acpi_battery, model_number), 1},
+ {offsetof(struct acpi_battery, serial_number), 1},
+ {offsetof(struct acpi_battery, type), 1},
+ {offsetof(struct acpi_battery, oem_info), 1},
+};
+static int extract_package(struct acpi_battery *battery,
+ union acpi_object *package,
+ struct acpi_offsets *offsets, int num)
+{
+ int i;
+ union acpi_object *element;
+ if (package->type != ACPI_TYPE_PACKAGE)
+ return -EFAULT;
+ for (i = 0; i < num; ++i) {
+ if (package->package.count <= i)
+ return -EFAULT;
+ element = &package->package.elements[i];
+ if (offsets[i].mode) {
+ u8 *ptr = (u8 *)battery + offsets[i].offset;
+ if (element->type == ACPI_TYPE_STRING ||
+ element->type == ACPI_TYPE_BUFFER)
+ strncpy(ptr, element->string.pointer, 32);
+ else if (element->type == ACPI_TYPE_INTEGER) {
+ strncpy(ptr, (u8 *)&element->integer.value,
+ sizeof(acpi_integer));
+ ptr[sizeof(acpi_integer)] = 0;
+ } else return -EFAULT;
+ } else {
+ if (element->type == ACPI_TYPE_INTEGER) {
+ int *x = (int *)((u8 *)battery +
+ offsets[i].offset);
+ *x = element->integer.value;
+ } else return -EFAULT;
+ }
+ }
return 0;
}
static int acpi_battery_get_status(struct acpi_battery *battery)
{
- int result = 0;
-
- result = acpi_bus_get_status(battery->device);
- if (result) {
+ if (acpi_bus_get_status(battery->device)) {
ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Evaluating _STA"));
return -ENODEV;
}
- return result;
+ return 0;
}
static int acpi_battery_get_info(struct acpi_battery *battery)
{
- int result = 0;
+ int result = -EFAULT;
acpi_status status = 0;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
- struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BIF),
- ACPI_BATTERY_FORMAT_BIF
- };
- union acpi_object *package = NULL;
- struct acpi_buffer *data = NULL;
- struct acpi_battery_info *bif = NULL;
-
- battery->update_time[ACPI_BATTERY_INFO] = get_seconds();
if (!acpi_battery_present(battery))
return 0;
+ mutex_lock(&battery->lock);
+ status = acpi_evaluate_object(battery->device->handle, "_BIF",
+ NULL, &buffer);
+ mutex_unlock(&battery->lock);
- /* Evaluate _BIF */
-
- status =
- acpi_evaluate_object(acpi_battery_handle(battery), "_BIF", NULL,
- &buffer);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF"));
return -ENODEV;
}
- package = buffer.pointer;
-
- data = &battery->bif_data;
-
- /* Extract Package Data */
-
- result =
- acpi_battery_extract_package(battery, package, &format, data,
- "_BIF");
- if (result)
- goto end;
-
- end:
-
+ result = extract_package(battery, buffer.pointer,
+ info_offsets, ARRAY_SIZE(info_offsets));
kfree(buffer.pointer);
-
- if (!result) {
- bif = data->pointer;
- battery->flags.power_unit = bif->power_unit;
- }
-
return result;
}
@@ -273,342 +330,256 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
int result = 0;
acpi_status status = 0;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
- struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BST),
- ACPI_BATTERY_FORMAT_BST
- };
- union acpi_object *package = NULL;
- struct acpi_buffer *data = NULL;
-
- battery->update_time[ACPI_BATTERY_STATE] = get_seconds();
if (!acpi_battery_present(battery))
return 0;
- /* Evaluate _BST */
+ if (battery->update_time &&
+ time_before(jiffies, battery->update_time +
+ msecs_to_jiffies(cache_time)))
+ return 0;
+
+ mutex_lock(&battery->lock);
+ status = acpi_evaluate_object(battery->device->handle, "_BST",
+ NULL, &buffer);
+ mutex_unlock(&battery->lock);
- status =
- acpi_evaluate_object(acpi_battery_handle(battery), "_BST", NULL,
- &buffer);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST"));
return -ENODEV;
}
- package = buffer.pointer;
-
- data = &battery->bst_data;
-
- /* Extract Package Data */
-
- result =
- acpi_battery_extract_package(battery, package, &format, data,
- "_BST");
- if (result)
- goto end;
-
- end:
+ result = extract_package(battery, buffer.pointer,
+ state_offsets, ARRAY_SIZE(state_offsets));
+ battery->update_time = jiffies;
kfree(buffer.pointer);
-
return result;
}
-static int acpi_battery_get_alarm(struct acpi_battery *battery)
-{
- battery->update_time[ACPI_BATTERY_ALARM] = get_seconds();
-
- return 0;
-}
-
-static int acpi_battery_set_alarm(struct acpi_battery *battery,
- unsigned long alarm)
+static int acpi_battery_set_alarm(struct acpi_battery *battery)
{
acpi_status status = 0;
- union acpi_object arg0 = { ACPI_TYPE_INTEGER };
+ union acpi_object arg0 = { .type = ACPI_TYPE_INTEGER };
struct acpi_object_list arg_list = { 1, &arg0 };
- battery->update_time[ACPI_BATTERY_ALARM] = get_seconds();
-
- if (!acpi_battery_present(battery))
+ if (!acpi_battery_present(battery)|| !battery->alarm_present)
return -ENODEV;
- if (!battery->flags.alarm_present)
- return -ENODEV;
+ arg0.integer.value = battery->alarm;
- arg0.integer.value = alarm;
-
- status =
- acpi_evaluate_object(acpi_battery_handle(battery), "_BTP",
+ mutex_lock(&battery->lock);
+ status = acpi_evaluate_object(battery->device->handle, "_BTP",
&arg_list, NULL);
+ mutex_unlock(&battery->lock);
+
if (ACPI_FAILURE(status))
return -ENODEV;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Alarm set to %d\n", (u32) alarm));
-
- battery->alarm = alarm;
-
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Alarm set to %d\n", battery->alarm));
return 0;
}
static int acpi_battery_init_alarm(struct acpi_battery *battery)
{
- int result = 0;
acpi_status status = AE_OK;
acpi_handle handle = NULL;
- struct acpi_battery_info *bif = battery->bif_data.pointer;
- unsigned long alarm = battery->alarm;
/* See if alarms are supported, and if so, set default */
-
- status = acpi_get_handle(acpi_battery_handle(battery), "_BTP", &handle);
- if (ACPI_SUCCESS(status)) {
- battery->flags.alarm_present = 1;
- if (!alarm && bif) {
- alarm = bif->design_capacity_warning;
- }
- result = acpi_battery_set_alarm(battery, alarm);
- if (result)
- goto end;
- } else {
- battery->flags.alarm_present = 0;
+ status = acpi_get_handle(battery->device->handle, "_BTP", &handle);
+ if (ACPI_FAILURE(status)) {
+ battery->alarm_present = 0;
+ return 0;
}
-
- end:
-
- return result;
+ battery->alarm_present = 1;
+ if (!battery->alarm)
+ battery->alarm = battery->design_capacity_warning;
+ return acpi_battery_set_alarm(battery);
}
-static int acpi_battery_init_update(struct acpi_battery *battery)
+static ssize_t acpi_battery_alarm_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
- int result = 0;
-
- result = acpi_battery_get_status(battery);
- if (result)
- return result;
-
- battery->flags.battery_present_prev = acpi_battery_present(battery);
-
- if (acpi_battery_present(battery)) {
- result = acpi_battery_get_info(battery);
- if (result)
- return result;
- result = acpi_battery_get_state(battery);
- if (result)
- return result;
-
- acpi_battery_init_alarm(battery);
- }
-
- return result;
+ struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
+ return sprintf(buf, "%d\n", battery->alarm * 1000);
}
-static int acpi_battery_update(struct acpi_battery *battery,
- int update, int *update_result_ptr)
+static ssize_t acpi_battery_alarm_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
- int result = 0;
- int update_result = ACPI_BATTERY_NONE_UPDATE;
-
- if (!acpi_battery_present(battery)) {
- update = 1;
- }
+ unsigned long x;
+ struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
+ if (sscanf(buf, "%ld\n", &x) == 1)
+ battery->alarm = x/1000;
+ if (acpi_battery_present(battery))
+ acpi_battery_set_alarm(battery);
+ return count;
+}
- if (battery->flags.init_update) {
- result = acpi_battery_init_update(battery);
- if (result)
- goto end;
- update_result = ACPI_BATTERY_INIT_UPDATE;
- } else if (update) {
- result = acpi_battery_get_status(battery);
- if (result)
- goto end;
- if ((!battery->flags.battery_present_prev & acpi_battery_present(battery))
- || (battery->flags.battery_present_prev & !acpi_battery_present(battery))) {
- result = acpi_battery_init_update(battery);
- if (result)
- goto end;
- update_result = ACPI_BATTERY_INIT_UPDATE;
- } else {
- update_result = ACPI_BATTERY_EASY_UPDATE;
- }
- }
+static struct device_attribute alarm_attr = {
+ .attr = {.name = "alarm", .mode = 0644, .owner = THIS_MODULE},
+ .show = acpi_battery_alarm_show,
+ .store = acpi_battery_alarm_store,
+};
- end:
+static int sysfs_add_battery(struct acpi_battery *battery)
+{
+ int result;
- battery->flags.init_update = (result != 0);
+ battery->update_time = 0;
+ result = acpi_battery_get_info(battery);
+ acpi_battery_init_alarm(battery);
+ if (result)
+ return result;
+ if (battery->power_unit) {
+ battery->bat.properties = charge_battery_props;
+ battery->bat.num_properties =
+ ARRAY_SIZE(charge_battery_props);
+ } else {
+ battery->bat.properties = energy_battery_props;
+ battery->bat.num_properties =
+ ARRAY_SIZE(energy_battery_props);
+ }
- *update_result_ptr = update_result;
+ battery->bat.name = acpi_device_bid(battery->device);
+ battery->bat.type = POWER_SUPPLY_TYPE_BATTERY;
+ battery->bat.get_property = acpi_battery_get_property;
- return result;
+ result = power_supply_register(&battery->device->dev, &battery->bat);
+ if (result)
+ return result;
+ return device_create_file(battery->bat.dev, &alarm_attr);
}
-static void acpi_battery_notify_update(struct acpi_battery *battery)
+static void sysfs_remove_battery(struct acpi_battery *battery)
{
- acpi_battery_get_status(battery);
-
- if (battery->flags.init_update) {
+ if (!battery->bat.dev)
return;
- }
+ device_remove_file(battery->bat.dev, &alarm_attr);
+ power_supply_unregister(&battery->bat);
+ battery->bat.dev = NULL;
+}
- if ((!battery->flags.battery_present_prev &
- acpi_battery_present(battery)) ||
- (battery->flags.battery_present_prev &
- !acpi_battery_present(battery))) {
- battery->flags.init_update = 1;
- } else {
- battery->flags.update[ACPI_BATTERY_INFO] = 1;
- battery->flags.update[ACPI_BATTERY_STATE] = 1;
- battery->flags.update[ACPI_BATTERY_ALARM] = 1;
+static int acpi_battery_update(struct acpi_battery *battery)
+{
+ int result = acpi_battery_get_status(battery);
+ if (result)
+ return result;
+ if (!acpi_battery_present(battery)) {
+ sysfs_remove_battery(battery);
+ return 0;
}
+ if (!battery->bat.dev)
+ sysfs_add_battery(battery);
+ return acpi_battery_get_state(battery);
}
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
+#ifdef CONFIG_ACPI_PROCFS
static struct proc_dir_entry *acpi_battery_dir;
static int acpi_battery_print_info(struct seq_file *seq, int result)
{
struct acpi_battery *battery = seq->private;
- struct acpi_battery_info *bif = NULL;
- char *units = "?";
if (result)
goto end;
- if (acpi_battery_present(battery))
- seq_printf(seq, "present: yes\n");
- else {
- seq_printf(seq, "present: no\n");
- goto end;
- }
-
- bif = battery->bif_data.pointer;
- if (!bif) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR, "BIF buffer is NULL"));
- result = -ENODEV;
+ seq_printf(seq, "present: %s\n",
+ acpi_battery_present(battery)?"yes":"no");
+ if (!acpi_battery_present(battery))
goto end;
- }
-
- /* Battery Units */
-
- units = acpi_battery_power_units(battery);
-
- if (bif->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
+ if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
seq_printf(seq, "design capacity: unknown\n");
else
seq_printf(seq, "design capacity: %d %sh\n",
- (u32) bif->design_capacity, units);
+ battery->design_capacity,
+ acpi_battery_units(battery));
- if (bif->last_full_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
+ if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
seq_printf(seq, "last full capacity: unknown\n");
else
seq_printf(seq, "last full capacity: %d %sh\n",
- (u32) bif->last_full_capacity, units);
+ battery->full_charge_capacity,
+ acpi_battery_units(battery));
- switch ((u32) bif->battery_technology) {
- case 0:
- seq_printf(seq, "battery technology: non-rechargeable\n");
- break;
- case 1:
- seq_printf(seq, "battery technology: rechargeable\n");
- break;
- default:
- seq_printf(seq, "battery technology: unknown\n");
- break;
- }
+ seq_printf(seq, "battery technology: %srechargeable\n",
+ (!battery->technology)?"non-":"");
- if (bif->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
+ if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
seq_printf(seq, "design voltage: unknown\n");
else
seq_printf(seq, "design voltage: %d mV\n",
- (u32) bif->design_voltage);
+ battery->design_voltage);
seq_printf(seq, "design capacity warning: %d %sh\n",
- (u32) bif->design_capacity_warning, units);
+ battery->design_capacity_warning,
+ acpi_battery_units(battery));
seq_printf(seq, "design capacity low: %d %sh\n",
- (u32) bif->design_capacity_low, units);
+ battery->design_capacity_low,
+ acpi_battery_units(battery));
seq_printf(seq, "capacity granularity 1: %d %sh\n",
- (u32) bif->battery_capacity_granularity_1, units);
+ battery->capacity_granularity_1,
+ acpi_battery_units(battery));
seq_printf(seq, "capacity granularity 2: %d %sh\n",
- (u32) bif->battery_capacity_granularity_2, units);
- seq_printf(seq, "model number: %s\n", bif->model_number);
- seq_printf(seq, "serial number: %s\n", bif->serial_number);
- seq_printf(seq, "battery type: %s\n", bif->battery_type);
- seq_printf(seq, "OEM info: %s\n", bif->oem_info);
-
+ battery->capacity_granularity_2,
+ acpi_battery_units(battery));
+ seq_printf(seq, "model number: %s\n", battery->model_number);
+ seq_printf(seq, "serial number: %s\n", battery->serial_number);
+ seq_printf(seq, "battery type: %s\n", battery->type);
+ seq_printf(seq, "OEM info: %s\n", battery->oem_info);
end:
-
if (result)
seq_printf(seq, "ERROR: Unable to read battery info\n");
-
return result;
}
static int acpi_battery_print_state(struct seq_file *seq, int result)
{
struct acpi_battery *battery = seq->private;
- struct acpi_battery_state *bst = NULL;
- char *units = "?";
if (result)
goto end;
- if (acpi_battery_present(battery))
- seq_printf(seq, "present: yes\n");
- else {
- seq_printf(seq, "present: no\n");
+ seq_printf(seq, "present: %s\n",
+ acpi_battery_present(battery)?"yes":"no");
+ if (!acpi_battery_present(battery))
goto end;
- }
- bst = battery->bst_data.pointer;
- if (!bst) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR, "BST buffer is NULL"));
- result = -ENODEV;
- goto end;
- }
-
- /* Battery Units */
-
- units = acpi_battery_power_units(battery);
-
- if (!(bst->state & 0x04))
- seq_printf(seq, "capacity state: ok\n");
- else
- seq_printf(seq, "capacity state: critical\n");
-
- if ((bst->state & 0x01) && (bst->state & 0x02)) {
+ seq_printf(seq, "capacity state: %s\n",
+ (battery->state & 0x04)?"critical":"ok");
+ if ((battery->state & 0x01) && (battery->state & 0x02))
seq_printf(seq,
"charging state: charging/discharging\n");
- } else if (bst->state & 0x01)
+ else if (battery->state & 0x01)
seq_printf(seq, "charging state: discharging\n");
- else if (bst->state & 0x02)
+ else if (battery->state & 0x02)
seq_printf(seq, "charging state: charging\n");
- else {
+ else
seq_printf(seq, "charging state: charged\n");
- }
- if (bst->present_rate == ACPI_BATTERY_VALUE_UNKNOWN)
+ if (battery->current_now == ACPI_BATTERY_VALUE_UNKNOWN)
seq_printf(seq, "present rate: unknown\n");
else
seq_printf(seq, "present rate: %d %s\n",
- (u32) bst->present_rate, units);
+ battery->current_now, acpi_battery_units(battery));
- if (bst->remaining_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
+ if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
seq_printf(seq, "remaining capacity: unknown\n");
else
seq_printf(seq, "remaining capacity: %d %sh\n",
- (u32) bst->remaining_capacity, units);
-
- if (bst->present_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
+ battery->capacity_now, acpi_battery_units(battery));
+ if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
seq_printf(seq, "present voltage: unknown\n");
else
seq_printf(seq, "present voltage: %d mV\n",
- (u32) bst->present_voltage);
-
+ battery->voltage_now);
end:
-
- if (result) {
+ if (result)
seq_printf(seq, "ERROR: Unable to read battery state\n");
- }
return result;
}
@@ -616,7 +587,6 @@ static int acpi_battery_print_state(struct seq_file *seq, int result)
static int acpi_battery_print_alarm(struct seq_file *seq, int result)
{
struct acpi_battery *battery = seq->private;
- char *units = "?";
if (result)
goto end;
@@ -625,189 +595,117 @@ static int acpi_battery_print_alarm(struct seq_file *seq, int result)
seq_printf(seq, "present: no\n");
goto end;
}
-
- /* Battery Units */
-
- units = acpi_battery_power_units(battery);
-
seq_printf(seq, "alarm: ");
if (!battery->alarm)
seq_printf(seq, "unsupported\n");
else
- seq_printf(seq, "%lu %sh\n", battery->alarm, units);
-
+ seq_printf(seq, "%u %sh\n", battery->alarm,
+ acpi_battery_units(battery));
end:
-
if (result)
seq_printf(seq, "ERROR: Unable to read battery alarm\n");
-
return result;
}
-static ssize_t
-acpi_battery_write_alarm(struct file *file,
- const char __user * buffer,
- size_t count, loff_t * ppos)
+static ssize_t acpi_battery_write_alarm(struct file *file,
+ const char __user * buffer,
+ size_t count, loff_t * ppos)
{
int result = 0;
char alarm_string[12] = { '\0' };
struct seq_file *m = file->private_data;
struct acpi_battery *battery = m->private;
- int update_result = ACPI_BATTERY_NONE_UPDATE;
if (!battery || (count > sizeof(alarm_string) - 1))
return -EINVAL;
-
- mutex_lock(&battery->mutex);
-
- result = acpi_battery_update(battery, 1, &update_result);
- if (result) {
- result = -ENODEV;
- goto end;
- }
-
if (!acpi_battery_present(battery)) {
result = -ENODEV;
goto end;
}
-
if (copy_from_user(alarm_string, buffer, count)) {
result = -EFAULT;
goto end;
}
-
alarm_string[count] = '\0';
-
- result = acpi_battery_set_alarm(battery,
- simple_strtoul(alarm_string, NULL, 0));
- if (result)
- goto end;
-
+ battery->alarm = simple_strtol(alarm_string, NULL, 0);
+ result = acpi_battery_set_alarm(battery);
end:
-
- acpi_battery_check_result(battery, result);
-
if (!result)
- result = count;
-
- mutex_unlock(&battery->mutex);
-
+ return count;
return result;
}
typedef int(*print_func)(struct seq_file *seq, int result);
-typedef int(*get_func)(struct acpi_battery *battery);
-
-static struct acpi_read_mux {
- print_func print;
- get_func get;
-} acpi_read_funcs[ACPI_BATTERY_NUMFILES] = {
- {.get = acpi_battery_get_info, .print = acpi_battery_print_info},
- {.get = acpi_battery_get_state, .print = acpi_battery_print_state},
- {.get = acpi_battery_get_alarm, .print = acpi_battery_print_alarm},
+
+static print_func acpi_print_funcs[ACPI_BATTERY_NUMFILES] = {
+ acpi_battery_print_info,
+ acpi_battery_print_state,
+ acpi_battery_print_alarm,
};
static int acpi_battery_read(int fid, struct seq_file *seq)
{
struct acpi_battery *battery = seq->private;
- int result = 0;
- int update_result = ACPI_BATTERY_NONE_UPDATE;
- int update = 0;
-
- mutex_lock(&battery->mutex);
-
- update = (get_seconds() - battery->update_time[fid] >= update_time);
- update = (update | battery->flags.update[fid]);
-
- result = acpi_battery_update(battery, update, &update_result);
- if (result)
- goto end;
-
- if (update_result == ACPI_BATTERY_EASY_UPDATE) {
- result = acpi_read_funcs[fid].get(battery);
- if (result)
- goto end;
+ int result = acpi_battery_update(battery);
+ return acpi_print_funcs[fid](seq, result);
+}
+
+#define DECLARE_FILE_FUNCTIONS(_name) \
+static int acpi_battery_read_##_name(struct seq_file *seq, void *offset) \
+{ \
+ return acpi_battery_read(_name##_tag, seq); \
+} \
+static int acpi_battery_##_name##_open_fs(struct inode *inode, struct file *file) \
+{ \
+ return single_open(file, acpi_battery_read_##_name, PDE(inode)->data); \
+}
+
+DECLARE_FILE_FUNCTIONS(info);
+DECLARE_FILE_FUNCTIONS(state);
+DECLARE_FILE_FUNCTIONS(alarm);
+
+#undef DECLARE_FILE_FUNCTIONS
+
+#define FILE_DESCRIPTION_RO(_name) \
+ { \
+ .name = __stringify(_name), \
+ .mode = S_IRUGO, \
+ .ops = { \
+ .open = acpi_battery_##_name##_open_fs, \
+ .read = seq_read, \
+ .llseek = seq_lseek, \
+ .release = single_release, \
+ .owner = THIS_MODULE, \
+ }, \
+ }
+
+#define FILE_DESCRIPTION_RW(_name) \
+ { \
+ .name = __stringify(_name), \
+ .mode = S_IFREG | S_IRUGO | S_IWUSR, \
+ .ops = { \
+ .open = acpi_battery_##_name##_open_fs, \
+ .read = seq_read, \
+ .llseek = seq_lseek, \
+ .write = acpi_battery_write_##_name, \
+ .release = single_release, \
+ .owner = THIS_MODULE, \
+ }, \
}
- end:
- result = acpi_read_funcs[fid].print(seq, result);
- acpi_battery_check_result(battery, result);
- battery->flags.update[fid] = result;
- mutex_unlock(&battery->mutex);
- return result;
-}
-
-static int acpi_battery_read_info(struct seq_file *seq, void *offset)
-{
- return acpi_battery_read(ACPI_BATTERY_INFO, seq);
-}
-
-static int acpi_battery_read_state(struct seq_file *seq, void *offset)
-{
- return acpi_battery_read(ACPI_BATTERY_STATE, seq);
-}
-
-static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
-{
- return acpi_battery_read(ACPI_BATTERY_ALARM, seq);
-}
-
-static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
-{
- return single_open(file, acpi_battery_read_info, PDE(inode)->data);
-}
-
-static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
-{
- return single_open(file, acpi_battery_read_state, PDE(inode)->data);
-}
-
-static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file)
-{
- return single_open(file, acpi_battery_read_alarm, PDE(inode)->data);
-}
-
static struct battery_file {
struct file_operations ops;
mode_t mode;
char *name;
} acpi_battery_file[] = {
- {
- .name = "info",
- .mode = S_IRUGO,
- .ops = {
- .open = acpi_battery_info_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
- },
- },
- {
- .name = "state",
- .mode = S_IRUGO,
- .ops = {
- .open = acpi_battery_state_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
- },
- },
- {
- .name = "alarm",
- .mode = S_IFREG | S_IRUGO | S_IWUSR,
- .ops = {
- .open = acpi_battery_alarm_open_fs,
- .read = seq_read,
- .write = acpi_battery_write_alarm,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
- },
- },
+ FILE_DESCRIPTION_RO(info),
+ FILE_DESCRIPTION_RO(state),
+ FILE_DESCRIPTION_RW(alarm),
};
+#undef FILE_DESCRIPTION_RO
+#undef FILE_DESCRIPTION_RW
+
static int acpi_battery_add_fs(struct acpi_device *device)
{
struct proc_dir_entry *entry = NULL;
@@ -832,25 +730,24 @@ static int acpi_battery_add_fs(struct acpi_device *device)
entry->owner = THIS_MODULE;
}
}
-
return 0;
}
-static int acpi_battery_remove_fs(struct acpi_device *device)
+static void acpi_battery_remove_fs(struct acpi_device *device)
{
int i;
- if (acpi_device_dir(device)) {
- for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) {
- remove_proc_entry(acpi_battery_file[i].name,
+ if (!acpi_device_dir(device))
+ return;
+ for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i)
+ remove_proc_entry(acpi_battery_file[i].name,
acpi_device_dir(device));
- }
- remove_proc_entry(acpi_device_bid(device), acpi_battery_dir);
- acpi_device_dir(device) = NULL;
- }
- return 0;
+ remove_proc_entry(acpi_device_bid(device), acpi_battery_dir);
+ acpi_device_dir(device) = NULL;
}
+#endif
+
/* --------------------------------------------------------------------------
Driver Interface
-------------------------------------------------------------------------- */
@@ -858,33 +755,19 @@ static int acpi_battery_remove_fs(struct acpi_device *device)
static void acpi_battery_notify(acpi_handle handle, u32 event, void *data)
{
struct acpi_battery *battery = data;
- struct acpi_device *device = NULL;
-
+ struct acpi_device *device;
if (!battery)
return;
-
device = battery->device;
-
- switch (event) {
- case ACPI_BATTERY_NOTIFY_STATUS:
- case ACPI_BATTERY_NOTIFY_INFO:
- case ACPI_NOTIFY_BUS_CHECK:
- case ACPI_NOTIFY_DEVICE_CHECK:
- device = battery->device;
- acpi_battery_notify_update(battery);
- acpi_bus_generate_proc_event(device, event,
+ acpi_battery_update(battery);
+ acpi_bus_generate_proc_event(device, event,
+ acpi_battery_present(battery));
+ acpi_bus_generate_netlink_event(device->pnp.device_class,
+ device->dev.bus_id, event,
acpi_battery_present(battery));
- acpi_bus_generate_netlink_event(device->pnp.device_class,
- device->dev.bus_id, event,
- acpi_battery_present(battery));
- break;
- default:
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Unsupported event [0x%x]\n", event));
- break;
- }
-
- return;
+ /* acpi_batter_update could remove power_supply object */
+ if (battery->bat.dev)
+ kobject_uevent(&battery->bat.dev->kobj, KOBJ_CHANGE);
}
static int acpi_battery_add(struct acpi_device *device)
@@ -892,33 +775,22 @@ static int acpi_battery_add(struct acpi_device *device)
int result = 0;
acpi_status status = 0;
struct acpi_battery *battery = NULL;
-
if (!device)
return -EINVAL;
-
battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL);
if (!battery)
return -ENOMEM;
-
- mutex_init(&battery->mutex);
-
- mutex_lock(&battery->mutex);
-
battery->device = device;
strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
acpi_driver_data(device) = battery;
-
- result = acpi_battery_get_status(battery);
- if (result)
- goto end;
-
- battery->flags.init_update = 1;
-
+ mutex_init(&battery->lock);
+ acpi_battery_update(battery);
+#ifdef CONFIG_ACPI_PROCFS
result = acpi_battery_add_fs(device);
if (result)
goto end;
-
+#endif
status = acpi_install_notify_handler(device->handle,
ACPI_ALL_NOTIFY,
acpi_battery_notify, battery);
@@ -927,20 +799,16 @@ static int acpi_battery_add(struct acpi_device *device)
result = -ENODEV;
goto end;
}
-
printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n",
ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
device->status.battery_present ? "present" : "absent");
-
end:
-
if (result) {
+#ifdef CONFIG_ACPI_PROCFS
acpi_battery_remove_fs(device);
+#endif
kfree(battery);
}
-
- mutex_unlock(&battery->mutex);
-
return result;
}
@@ -951,27 +819,16 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
if (!device || !acpi_driver_data(device))
return -EINVAL;
-
battery = acpi_driver_data(device);
-
- mutex_lock(&battery->mutex);
-
status = acpi_remove_notify_handler(device->handle,
ACPI_ALL_NOTIFY,
acpi_battery_notify);
-
+#ifdef CONFIG_ACPI_PROCFS
acpi_battery_remove_fs(device);
-
- kfree(battery->bif_data.pointer);
-
- kfree(battery->bst_data.pointer);
-
- mutex_unlock(&battery->mutex);
-
- mutex_destroy(&battery->mutex);
-
+#endif
+ sysfs_remove_battery(battery);
+ mutex_destroy(&battery->lock);
kfree(battery);
-
return 0;
}
@@ -979,44 +836,49 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
static int acpi_battery_resume(struct acpi_device *device)
{
struct acpi_battery *battery;
-
if (!device)
return -EINVAL;
-
- battery = device->driver_data;
-
- battery->flags.init_update = 1;
-
+ battery = acpi_driver_data(device);
+ battery->update_time = 0;
+ acpi_battery_update(battery);
return 0;
}
+static struct acpi_driver acpi_battery_driver = {
+ .name = "battery",
+ .class = ACPI_BATTERY_CLASS,
+ .ids = battery_device_ids,
+ .ops = {
+ .add = acpi_battery_add,
+ .resume = acpi_battery_resume,
+ .remove = acpi_battery_remove,
+ },
+};
+
static int __init acpi_battery_init(void)
{
- int result;
-
if (acpi_disabled)
return -ENODEV;
-
+#ifdef CONFIG_ACPI_PROCFS
acpi_battery_dir = acpi_lock_battery_dir();
if (!acpi_battery_dir)
return -ENODEV;
-
- result = acpi_bus_register_driver(&acpi_battery_driver);
- if (result < 0) {
+#endif
+ if (acpi_bus_register_driver(&acpi_battery_driver) < 0) {
+#ifdef CONFIG_ACPI_PROCFS
acpi_unlock_battery_dir(acpi_battery_dir);
+#endif
return -ENODEV;
}
-
return 0;
}
static void __exit acpi_battery_exit(void)
{
acpi_bus_unregister_driver(&acpi_battery_driver);
-
+#ifdef CONFIG_ACPI_PROCFS
acpi_unlock_battery_dir(acpi_battery_dir);
-
- return;
+#endif
}
module_init(acpi_battery_init);
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index cbfc81579c9a..49d432d0a12c 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -198,12 +198,10 @@ int acpi_bus_set_power(acpi_handle handle, int state)
return -ENODEV;
}
/*
- * Get device's current power state if it's unknown
- * This means device power state isn't initialized or previous setting failed
+ * Get device's current power state
*/
- if ((device->power.state == ACPI_STATE_UNKNOWN) || device->flags.force_power_state)
- acpi_bus_get_power(device->handle, &device->power.state);
- if ((state == device->power.state) && !device->flags.force_power_state) {
+ acpi_bus_get_power(device->handle, &device->power.state);
+ if (state == device->power.state) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n",
state));
return 0;
@@ -286,15 +284,11 @@ DECLARE_WAIT_QUEUE_HEAD(acpi_bus_event_queue);
extern int event_is_open;
-int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
+int acpi_bus_generate_proc_event4(const char *device_class, const char *bus_id, u8 type, int data)
{
- struct acpi_bus_event *event = NULL;
+ struct acpi_bus_event *event;
unsigned long flags = 0;
-
- if (!device)
- return -EINVAL;
-
/* drop event on the floor if no one's listening */
if (!event_is_open)
return 0;
@@ -303,8 +297,8 @@ int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
if (!event)
return -ENOMEM;
- strcpy(event->device_class, device->pnp.device_class);
- strcpy(event->bus_id, device->pnp.bus_id);
+ strcpy(event->device_class, device_class);
+ strcpy(event->bus_id, bus_id);
event->type = type;
event->data = data;
@@ -315,6 +309,17 @@ int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
wake_up_interruptible(&acpi_bus_event_queue);
return 0;
+
+}
+
+EXPORT_SYMBOL_GPL(acpi_bus_generate_proc_event4);
+
+int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
+{
+ if (!device)
+ return -EINVAL;
+ return acpi_bus_generate_proc_event4(device->pnp.device_class,
+ device->pnp.bus_id, type, data);
}
EXPORT_SYMBOL(acpi_bus_generate_proc_event);
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 2e79a3395ecf..24a7865a57cb 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -78,6 +78,7 @@ MODULE_DEVICE_TABLE(acpi, button_device_ids);
static int acpi_button_add(struct acpi_device *device);
static int acpi_button_remove(struct acpi_device *device, int type);
+static int acpi_button_resume(struct acpi_device *device);
static int acpi_button_info_open_fs(struct inode *inode, struct file *file);
static int acpi_button_state_open_fs(struct inode *inode, struct file *file);
@@ -87,6 +88,7 @@ static struct acpi_driver acpi_button_driver = {
.ids = button_device_ids,
.ops = {
.add = acpi_button_add,
+ .resume = acpi_button_resume,
.remove = acpi_button_remove,
},
};
@@ -253,6 +255,19 @@ static int acpi_button_remove_fs(struct acpi_device *device)
/* --------------------------------------------------------------------------
Driver Interface
-------------------------------------------------------------------------- */
+static int acpi_lid_send_state(struct acpi_button *button)
+{
+ unsigned long state;
+ acpi_status status;
+
+ status = acpi_evaluate_integer(button->device->handle, "_LID", NULL,
+ &state);
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
+ /* input layer checks if event is redundant */
+ input_report_switch(button->input, SW_LID, !state);
+ return 0;
+}
static void acpi_button_notify(acpi_handle handle, u32 event, void *data)
{
@@ -265,15 +280,8 @@ static void acpi_button_notify(acpi_handle handle, u32 event, void *data)
switch (event) {
case ACPI_BUTTON_NOTIFY_STATUS:
input = button->input;
-
if (button->type == ACPI_BUTTON_TYPE_LID) {
- struct acpi_handle *handle = button->device->handle;
- unsigned long state;
-
- if (!ACPI_FAILURE(acpi_evaluate_integer(handle, "_LID",
- NULL, &state)))
- input_report_switch(input, SW_LID, !state);
-
+ acpi_lid_send_state(button);
} else {
int keycode = test_bit(KEY_SLEEP, input->keybit) ?
KEY_SLEEP : KEY_POWER;
@@ -336,6 +344,17 @@ static int acpi_button_install_notify_handlers(struct acpi_button *button)
return ACPI_FAILURE(status) ? -ENODEV : 0;
}
+static int acpi_button_resume(struct acpi_device *device)
+{
+ struct acpi_button *button;
+ if (!device)
+ return -EINVAL;
+ button = acpi_driver_data(device);
+ if (button && button->type == ACPI_BUTTON_TYPE_LID)
+ return acpi_lid_send_state(button);
+ return 0;
+}
+
static void acpi_button_remove_notify_handlers(struct acpi_button *button)
{
switch (button->type) {
@@ -434,18 +453,18 @@ static int acpi_button_add(struct acpi_device *device)
switch (button->type) {
case ACPI_BUTTON_TYPE_POWER:
case ACPI_BUTTON_TYPE_POWERF:
- input->evbit[0] = BIT(EV_KEY);
+ input->evbit[0] = BIT_MASK(EV_KEY);
set_bit(KEY_POWER, input->keybit);
break;
case ACPI_BUTTON_TYPE_SLEEP:
case ACPI_BUTTON_TYPE_SLEEPF:
- input->evbit[0] = BIT(EV_KEY);
+ input->evbit[0] = BIT_MASK(EV_KEY);
set_bit(KEY_SLEEP, input->keybit);
break;
case ACPI_BUTTON_TYPE_LID:
- input->evbit[0] = BIT(EV_SW);
+ input->evbit[0] = BIT_MASK(EV_SW);
set_bit(SW_LID, input->swbit);
break;
}
@@ -453,6 +472,8 @@ static int acpi_button_add(struct acpi_device *device)
error = input_register_device(input);
if (error)
goto err_remove_handlers;
+ if (button->type == ACPI_BUTTON_TYPE_LID)
+ acpi_lid_send_state(button);
if (device->wakeup.flags.valid) {
/* Button's GPE is run-wake GPE */
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 3f7935ab0cf5..06b78e5e33a1 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -65,16 +65,18 @@ enum ec_command {
/* EC events */
enum ec_event {
ACPI_EC_EVENT_OBF_1 = 1, /* Output buffer full */
- ACPI_EC_EVENT_IBF_0, /* Input buffer empty */
+ ACPI_EC_EVENT_IBF_0, /* Input buffer empty */
};
#define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */
#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */
-static enum ec_mode {
- EC_INTR = 1, /* Output buffer full */
- EC_POLL, /* Input buffer empty */
-} acpi_ec_mode = EC_INTR;
+enum {
+ EC_FLAGS_WAIT_GPE = 0, /* Don't check status until GPE arrives */
+ EC_FLAGS_QUERY_PENDING, /* Query is pending */
+ EC_FLAGS_GPE_MODE, /* Expect GPE to be sent for status change */
+ EC_FLAGS_ONLY_IBF_GPE, /* Expect GPE only for IBF = 0 event */
+};
static int acpi_ec_remove(struct acpi_device *device, int type);
static int acpi_ec_start(struct acpi_device *device);
@@ -116,11 +118,11 @@ static struct acpi_ec {
unsigned long command_addr;
unsigned long data_addr;
unsigned long global_lock;
+ unsigned long flags;
struct mutex lock;
- atomic_t query_pending;
- atomic_t event_count;
wait_queue_head_t wait;
struct list_head list;
+ u8 handlers_installed;
} *boot_ec, *first_ec;
/* --------------------------------------------------------------------------
@@ -147,45 +149,54 @@ static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data)
outb(data, ec->data_addr);
}
-static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event,
- unsigned old_count)
+static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event)
{
- u8 status = acpi_ec_read_status(ec);
- if (old_count == atomic_read(&ec->event_count))
+ if (test_bit(EC_FLAGS_WAIT_GPE, &ec->flags))
return 0;
if (event == ACPI_EC_EVENT_OBF_1) {
- if (status & ACPI_EC_FLAG_OBF)
+ if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_OBF)
return 1;
} else if (event == ACPI_EC_EVENT_IBF_0) {
- if (!(status & ACPI_EC_FLAG_IBF))
+ if (!(acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF))
return 1;
}
return 0;
}
-static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event,
- unsigned count, int force_poll)
+static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll)
{
- if (unlikely(force_poll) || acpi_ec_mode == EC_POLL) {
+ if (likely(test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) &&
+ likely(!force_poll)) {
+ if (wait_event_timeout(ec->wait, acpi_ec_check_status(ec, event),
+ msecs_to_jiffies(ACPI_EC_DELAY)))
+ return 0;
+ clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
+ if (acpi_ec_check_status(ec, event)) {
+ if (event == ACPI_EC_EVENT_OBF_1) {
+ /* miss OBF = 1 GPE, don't expect it anymore */
+ printk(KERN_INFO PREFIX "missing OBF_1 confirmation,"
+ "switching to degraded mode.\n");
+ set_bit(EC_FLAGS_ONLY_IBF_GPE, &ec->flags);
+ } else {
+ /* missing GPEs, switch back to poll mode */
+ printk(KERN_INFO PREFIX "missing IBF_1 confirmations,"
+ "switch off interrupt mode.\n");
+ clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
+ }
+ return 0;
+ }
+ } else {
unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
+ clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
while (time_before(jiffies, delay)) {
- if (acpi_ec_check_status(ec, event, 0))
+ if (acpi_ec_check_status(ec, event))
return 0;
}
- } else {
- if (wait_event_timeout(ec->wait,
- acpi_ec_check_status(ec, event, count),
- msecs_to_jiffies(ACPI_EC_DELAY)) ||
- acpi_ec_check_status(ec, event, 0)) {
- return 0;
- } else {
- printk(KERN_ERR PREFIX "acpi_ec_wait timeout,"
+ }
+ printk(KERN_ERR PREFIX "acpi_ec_wait timeout,"
" status = %d, expect_event = %d\n",
acpi_ec_read_status(ec), event);
- }
- }
-
return -ETIME;
}
@@ -195,39 +206,42 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
int force_poll)
{
int result = 0;
- unsigned count = atomic_read(&ec->event_count);
+ set_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
acpi_ec_write_cmd(ec, command);
for (; wdata_len > 0; --wdata_len) {
- result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count, force_poll);
+ result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll);
if (result) {
printk(KERN_ERR PREFIX
"write_cmd timeout, command = %d\n", command);
goto end;
}
- count = atomic_read(&ec->event_count);
+ set_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
acpi_ec_write_data(ec, *(wdata++));
}
if (!rdata_len) {
- result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count, force_poll);
+ result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll);
if (result) {
printk(KERN_ERR PREFIX
"finish-write timeout, command = %d\n", command);
goto end;
}
- } else if (command == ACPI_EC_COMMAND_QUERY) {
- atomic_set(&ec->query_pending, 0);
- }
+ } else if (command == ACPI_EC_COMMAND_QUERY)
+ clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
for (; rdata_len > 0; --rdata_len) {
- result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, count, force_poll);
+ if (test_bit(EC_FLAGS_ONLY_IBF_GPE, &ec->flags))
+ force_poll = 1;
+ result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, force_poll);
if (result) {
printk(KERN_ERR PREFIX "read timeout, command = %d\n",
command);
goto end;
}
- count = atomic_read(&ec->event_count);
+ /* Don't expect GPE after last read */
+ if (rdata_len > 1)
+ set_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
*(rdata++) = acpi_ec_read_data(ec);
}
end:
@@ -257,10 +271,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
}
}
- /* Make sure GPE is enabled before doing transaction */
- acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
-
- status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0, 0);
+ status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0);
if (status) {
printk(KERN_ERR PREFIX
"input buffer is not empty, aborting transaction\n");
@@ -425,7 +436,7 @@ int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
handler->func = func;
handler->data = data;
mutex_lock(&ec->lock);
- list_add_tail(&handler->node, &ec->list);
+ list_add(&handler->node, &ec->list);
mutex_unlock(&ec->lock);
return 0;
}
@@ -434,13 +445,12 @@ EXPORT_SYMBOL_GPL(acpi_ec_add_query_handler);
void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
{
- struct acpi_ec_query_handler *handler;
+ struct acpi_ec_query_handler *handler, *tmp;
mutex_lock(&ec->lock);
- list_for_each_entry(handler, &ec->list, node) {
+ list_for_each_entry_safe(handler, tmp, &ec->list, node) {
if (query_bit == handler->query_bit) {
list_del(&handler->node);
kfree(handler);
- break;
}
}
mutex_unlock(&ec->lock);
@@ -476,23 +486,24 @@ static void acpi_ec_gpe_query(void *ec_cxt)
static u32 acpi_ec_gpe_handler(void *data)
{
acpi_status status = AE_OK;
- u8 value;
struct acpi_ec *ec = data;
- atomic_inc(&ec->event_count);
-
- if (acpi_ec_mode == EC_INTR) {
+ clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
+ if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags))
wake_up(&ec->wait);
- }
- value = acpi_ec_read_status(ec);
- if ((value & ACPI_EC_FLAG_SCI) && !atomic_read(&ec->query_pending)) {
- atomic_set(&ec->query_pending, 1);
- status =
- acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, ec);
+ if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_SCI) {
+ if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags))
+ status = acpi_os_execute(OSL_EC_BURST_HANDLER,
+ acpi_ec_gpe_query, ec);
+ } else if (unlikely(!test_bit(EC_FLAGS_GPE_MODE, &ec->flags))) {
+ /* this is non-query, must be confirmation */
+ printk(KERN_INFO PREFIX "non-query interrupt received,"
+ " switching to interrupt mode\n");
+ set_bit(EC_FLAGS_GPE_MODE, &ec->flags);
}
- return status == AE_OK ?
+ return ACPI_SUCCESS(status) ?
ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
}
@@ -641,13 +652,10 @@ static struct acpi_ec *make_acpi_ec(void)
struct acpi_ec *ec = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL);
if (!ec)
return NULL;
-
- atomic_set(&ec->query_pending, 1);
- atomic_set(&ec->event_count, 1);
+ ec->flags = 1 << EC_FLAGS_QUERY_PENDING;
mutex_init(&ec->lock);
init_waitqueue_head(&ec->wait);
INIT_LIST_HEAD(&ec->list);
-
return ec;
}
@@ -680,32 +688,50 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe);
if (ACPI_FAILURE(status))
return status;
-
/* Find and register all query methods */
acpi_walk_namespace(ACPI_TYPE_METHOD, handle, 1,
acpi_ec_register_query_methods, ec, NULL);
-
/* Use the global lock for all EC transactions? */
acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock);
-
ec->handle = handle;
-
- printk(KERN_INFO PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n",
- ec->gpe, ec->command_addr, ec->data_addr);
-
return AE_CTRL_TERMINATE;
}
+static void ec_remove_handlers(struct acpi_ec *ec)
+{
+ if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle,
+ ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
+ printk(KERN_ERR PREFIX "failed to remove space handler\n");
+ if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe,
+ &acpi_ec_gpe_handler)))
+ printk(KERN_ERR PREFIX "failed to remove gpe handler\n");
+ ec->handlers_installed = 0;
+}
+
static int acpi_ec_add(struct acpi_device *device)
{
struct acpi_ec *ec = NULL;
if (!device)
return -EINVAL;
-
strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_EC_CLASS);
+ /* Check for boot EC */
+ if (boot_ec) {
+ if (boot_ec->handle == device->handle) {
+ /* Pre-loaded EC from DSDT, just move pointer */
+ ec = boot_ec;
+ boot_ec = NULL;
+ goto end;
+ } else if (boot_ec->handle == ACPI_ROOT_OBJECT) {
+ /* ECDT-based EC, time to shut it down */
+ ec_remove_handlers(boot_ec);
+ kfree(boot_ec);
+ first_ec = boot_ec = NULL;
+ }
+ }
+
ec = make_acpi_ec();
if (!ec)
return -ENOMEM;
@@ -715,25 +741,16 @@ static int acpi_ec_add(struct acpi_device *device)
kfree(ec);
return -EINVAL;
}
-
- /* Check if we found the boot EC */
- if (boot_ec) {
- if (boot_ec->gpe == ec->gpe) {
- /* We might have incorrect info for GL at boot time */
- mutex_lock(&boot_ec->lock);
- boot_ec->global_lock = ec->global_lock;
- /* Copy handlers from new ec into boot ec */
- list_splice(&ec->list, &boot_ec->list);
- mutex_unlock(&boot_ec->lock);
- kfree(ec);
- ec = boot_ec;
- }
- } else
- first_ec = ec;
ec->handle = device->handle;
+ end:
+ if (!first_ec)
+ first_ec = ec;
acpi_driver_data(device) = ec;
-
acpi_ec_add_fs(device);
+ printk(KERN_INFO PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n",
+ ec->gpe, ec->command_addr, ec->data_addr);
+ printk(KERN_INFO PREFIX "driver started in %s mode\n",
+ (test_bit(EC_FLAGS_GPE_MODE, &ec->flags))?"interrupt":"poll");
return 0;
}
@@ -756,10 +773,7 @@ static int acpi_ec_remove(struct acpi_device *device, int type)
acpi_driver_data(device) = NULL;
if (ec == first_ec)
first_ec = NULL;
-
- /* Don't touch boot EC */
- if (boot_ec != ec)
- kfree(ec);
+ kfree(ec);
return 0;
}
@@ -789,6 +803,8 @@ ec_parse_io_ports(struct acpi_resource *resource, void *context)
static int ec_install_handlers(struct acpi_ec *ec)
{
acpi_status status;
+ if (ec->handlers_installed)
+ return 0;
status = acpi_install_gpe_handler(NULL, ec->gpe,
ACPI_GPE_EDGE_TRIGGERED,
&acpi_ec_gpe_handler, ec);
@@ -807,6 +823,7 @@ static int ec_install_handlers(struct acpi_ec *ec)
return -ENODEV;
}
+ ec->handlers_installed = 1;
return 0;
}
@@ -823,41 +840,22 @@ static int acpi_ec_start(struct acpi_device *device)
if (!ec)
return -EINVAL;
- /* Boot EC is already working */
- if (ec != boot_ec)
- ret = ec_install_handlers(ec);
+ ret = ec_install_handlers(ec);
/* EC is fully operational, allow queries */
- atomic_set(&ec->query_pending, 0);
-
+ clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
return ret;
}
static int acpi_ec_stop(struct acpi_device *device, int type)
{
- acpi_status status;
struct acpi_ec *ec;
-
if (!device)
return -EINVAL;
-
ec = acpi_driver_data(device);
if (!ec)
return -EINVAL;
-
- /* Don't touch boot EC */
- if (ec == boot_ec)
- return 0;
-
- status = acpi_remove_address_space_handler(ec->handle,
- ACPI_ADR_SPACE_EC,
- &acpi_ec_space_handler);
- if (ACPI_FAILURE(status))
- return -ENODEV;
-
- status = acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler);
- if (ACPI_FAILURE(status))
- return -ENODEV;
+ ec_remove_handlers(ec);
return 0;
}
@@ -877,7 +875,7 @@ int __init acpi_ec_ecdt_probe(void)
status = acpi_get_table(ACPI_SIG_ECDT, 1,
(struct acpi_table_header **)&ecdt_ptr);
if (ACPI_SUCCESS(status)) {
- printk(KERN_INFO PREFIX "EC description table is found, configuring boot EC\n\n");
+ printk(KERN_INFO PREFIX "EC description table is found, configuring boot EC\n");
boot_ec->command_addr = ecdt_ptr->control.address;
boot_ec->data_addr = ecdt_ptr->data.address;
boot_ec->gpe = ecdt_ptr->gpe;
@@ -899,7 +897,6 @@ int __init acpi_ec_ecdt_probe(void)
error:
kfree(boot_ec);
boot_ec = NULL;
-
return -ENODEV;
}
@@ -937,20 +934,4 @@ static void __exit acpi_ec_exit(void)
return;
}
-#endif /* 0 */
-
-static int __init acpi_ec_set_intr_mode(char *str)
-{
- int intr;
-
- if (!get_option(&str, &intr))
- return 0;
-
- acpi_ec_mode = (intr) ? EC_INTR : EC_POLL;
-
- printk(KERN_NOTICE PREFIX "%s mode.\n", intr ? "interrupt" : "polling");
-
- return 1;
-}
-
-__setup("ec_intr=", acpi_ec_set_intr_mode);
+#endif /* 0 */
diff --git a/drivers/acpi/events/evevent.c b/drivers/acpi/events/evevent.c
index a1f87b5def2a..e41287815ea1 100644
--- a/drivers/acpi/events/evevent.c
+++ b/drivers/acpi/events/evevent.c
@@ -239,10 +239,8 @@ u32 acpi_ev_fixed_event_detect(void)
* Read the fixed feature status and enable registers, as all the cases
* depend on their values. Ignore errors here.
*/
- (void)acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1_STATUS, &fixed_status);
- (void)acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1_ENABLE, &fixed_enable);
+ (void)acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, &fixed_status);
+ (void)acpi_hw_register_read(ACPI_REGISTER_PM1_ENABLE, &fixed_enable);
ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS,
"Fixed Event Block: Enable %08X Status %08X\n",
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index c81f6bdb68b8..a5a5532db268 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -47,8 +47,6 @@ MODULE_LICENSE("GPL");
static int acpi_fan_add(struct acpi_device *device);
static int acpi_fan_remove(struct acpi_device *device, int type);
-static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state);
-static int acpi_fan_resume(struct acpi_device *device);
static const struct acpi_device_id fan_device_ids[] = {
{"PNP0C0B", 0},
@@ -63,15 +61,9 @@ static struct acpi_driver acpi_fan_driver = {
.ops = {
.add = acpi_fan_add,
.remove = acpi_fan_remove,
- .suspend = acpi_fan_suspend,
- .resume = acpi_fan_resume,
},
};
-struct acpi_fan {
- struct acpi_device * device;
-};
-
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
@@ -80,12 +72,12 @@ static struct proc_dir_entry *acpi_fan_dir;
static int acpi_fan_read_state(struct seq_file *seq, void *offset)
{
- struct acpi_fan *fan = seq->private;
+ struct acpi_device *device = seq->private;
int state = 0;
- if (fan) {
- if (acpi_bus_get_power(fan->device->handle, &state))
+ if (device) {
+ if (acpi_bus_get_power(device->handle, &state))
seq_printf(seq, "status: ERROR\n");
else
seq_printf(seq, "status: %s\n",
@@ -105,11 +97,10 @@ acpi_fan_write_state(struct file *file, const char __user * buffer,
{
int result = 0;
struct seq_file *m = file->private_data;
- struct acpi_fan *fan = m->private;
+ struct acpi_device *device = m->private;
char state_string[12] = { '\0' };
-
- if (!fan || (count > sizeof(state_string) - 1))
+ if (count > sizeof(state_string) - 1)
return -EINVAL;
if (copy_from_user(state_string, buffer, count))
@@ -117,7 +108,7 @@ acpi_fan_write_state(struct file *file, const char __user * buffer,
state_string[count] = '\0';
- result = acpi_bus_set_power(fan->device->handle,
+ result = acpi_bus_set_power(device->handle,
simple_strtoul(state_string, NULL, 0));
if (result)
return result;
@@ -158,7 +149,7 @@ static int acpi_fan_add_fs(struct acpi_device *device)
return -ENODEV;
else {
entry->proc_fops = &acpi_fan_state_ops;
- entry->data = acpi_driver_data(device);
+ entry->data = device;
entry->owner = THIS_MODULE;
}
@@ -191,14 +182,8 @@ static int acpi_fan_add(struct acpi_device *device)
if (!device)
return -EINVAL;
- fan = kzalloc(sizeof(struct acpi_fan), GFP_KERNEL);
- if (!fan)
- return -ENOMEM;
-
- fan->device = device;
strcpy(acpi_device_name(device), "Fan");
strcpy(acpi_device_class(device), ACPI_FAN_CLASS);
- acpi_driver_data(device) = fan;
result = acpi_bus_get_power(device->handle, &state);
if (result) {
@@ -206,10 +191,6 @@ static int acpi_fan_add(struct acpi_device *device)
goto end;
}
- device->flags.force_power_state = 1;
- acpi_bus_set_power(device->handle, state);
- device->flags.force_power_state = 0;
-
result = acpi_fan_add_fs(device);
if (result)
goto end;
@@ -227,53 +208,14 @@ static int acpi_fan_add(struct acpi_device *device)
static int acpi_fan_remove(struct acpi_device *device, int type)
{
- struct acpi_fan *fan = NULL;
-
-
if (!device || !acpi_driver_data(device))
return -EINVAL;
- fan = acpi_driver_data(device);
-
acpi_fan_remove_fs(device);
- kfree(fan);
-
return 0;
}
-static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state)
-{
- if (!device)
- return -EINVAL;
-
- acpi_bus_set_power(device->handle, ACPI_STATE_D0);
-
- return AE_OK;
-}
-
-static int acpi_fan_resume(struct acpi_device *device)
-{
- int result = 0;
- int power_state = 0;
-
- if (!device)
- return -EINVAL;
-
- result = acpi_bus_get_power(device->handle, &power_state);
- if (result) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error reading fan power state\n"));
- return result;
- }
-
- device->flags.force_power_state = 1;
- acpi_bus_set_power(device->handle, power_state);
- device->flags.force_power_state = 0;
-
- return result;
-}
-
static int __init acpi_fan_init(void)
{
int result = 0;
diff --git a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/hardware/hwregs.c
index 1d371fa663f2..73f9c5fb1ba7 100644
--- a/drivers/acpi/hardware/hwregs.c
+++ b/drivers/acpi/hardware/hwregs.c
@@ -75,8 +75,7 @@ acpi_status acpi_hw_clear_acpi_status(void)
lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
- status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1_STATUS,
+ status = acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS,
ACPI_BITMASK_ALL_FIXED_STATUS);
if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
@@ -259,7 +258,7 @@ struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id)
*
******************************************************************************/
-acpi_status acpi_get_register(u32 register_id, u32 * return_value)
+acpi_status acpi_get_register_unlocked(u32 register_id, u32 * return_value)
{
u32 register_value = 0;
struct acpi_bit_register_info *bit_reg_info;
@@ -276,8 +275,7 @@ acpi_status acpi_get_register(u32 register_id, u32 * return_value)
/* Read from the register */
- status = acpi_hw_register_read(ACPI_MTX_LOCK,
- bit_reg_info->parent_register,
+ status = acpi_hw_register_read(bit_reg_info->parent_register,
&register_value);
if (ACPI_SUCCESS(status)) {
@@ -298,6 +296,16 @@ acpi_status acpi_get_register(u32 register_id, u32 * return_value)
return_ACPI_STATUS(status);
}
+acpi_status acpi_get_register(u32 register_id, u32 * return_value)
+{
+ acpi_status status;
+ acpi_cpu_flags flags;
+ flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
+ status = acpi_get_register_unlocked(register_id, return_value);
+ acpi_os_release_lock(acpi_gbl_hardware_lock, flags);
+ return status;
+}
+
ACPI_EXPORT_SYMBOL(acpi_get_register)
/*******************************************************************************
@@ -335,8 +343,7 @@ acpi_status acpi_set_register(u32 register_id, u32 value)
/* Always do a register read first so we can insert the new bits */
- status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
- bit_reg_info->parent_register,
+ status = acpi_hw_register_read(bit_reg_info->parent_register,
&register_value);
if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
@@ -363,8 +370,7 @@ acpi_status acpi_set_register(u32 register_id, u32 value)
bit_reg_info->
access_bit_mask);
if (value) {
- status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1_STATUS,
+ status = acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS,
(u16) value);
register_value = 0;
}
@@ -377,8 +383,7 @@ acpi_status acpi_set_register(u32 register_id, u32 value)
bit_reg_info->access_bit_mask,
value);
- status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1_ENABLE,
+ status = acpi_hw_register_write(ACPI_REGISTER_PM1_ENABLE,
(u16) register_value);
break;
@@ -397,15 +402,13 @@ acpi_status acpi_set_register(u32 register_id, u32 value)
bit_reg_info->access_bit_mask,
value);
- status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1_CONTROL,
+ status = acpi_hw_register_write(ACPI_REGISTER_PM1_CONTROL,
(u16) register_value);
break;
case ACPI_REGISTER_PM2_CONTROL:
- status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM2_CONTROL,
+ status = acpi_hw_register_read(ACPI_REGISTER_PM2_CONTROL,
&register_value);
if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
@@ -430,8 +433,7 @@ acpi_status acpi_set_register(u32 register_id, u32 value)
xpm2_control_block.
address)));
- status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM2_CONTROL,
+ status = acpi_hw_register_write(ACPI_REGISTER_PM2_CONTROL,
(u8) (register_value));
break;
@@ -461,8 +463,7 @@ ACPI_EXPORT_SYMBOL(acpi_set_register)
*
* FUNCTION: acpi_hw_register_read
*
- * PARAMETERS: use_lock - Lock hardware? True/False
- * register_id - ACPI Register ID
+ * PARAMETERS: register_id - ACPI Register ID
* return_value - Where the register value is returned
*
* RETURN: Status and the value read.
@@ -471,19 +472,14 @@ ACPI_EXPORT_SYMBOL(acpi_set_register)
*
******************************************************************************/
acpi_status
-acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value)
+acpi_hw_register_read(u32 register_id, u32 * return_value)
{
u32 value1 = 0;
u32 value2 = 0;
acpi_status status;
- acpi_cpu_flags lock_flags = 0;
ACPI_FUNCTION_TRACE(hw_register_read);
- if (ACPI_MTX_LOCK == use_lock) {
- lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
- }
-
switch (register_id) {
case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */
@@ -491,7 +487,7 @@ acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value)
acpi_hw_low_level_read(16, &value1,
&acpi_gbl_FADT.xpm1a_event_block);
if (ACPI_FAILURE(status)) {
- goto unlock_and_exit;
+ goto exit;
}
/* PM1B is optional */
@@ -507,7 +503,7 @@ acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value)
status =
acpi_hw_low_level_read(16, &value1, &acpi_gbl_xpm1a_enable);
if (ACPI_FAILURE(status)) {
- goto unlock_and_exit;
+ goto exit;
}
/* PM1B is optional */
@@ -523,7 +519,7 @@ acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value)
acpi_hw_low_level_read(16, &value1,
&acpi_gbl_FADT.xpm1a_control_block);
if (ACPI_FAILURE(status)) {
- goto unlock_and_exit;
+ goto exit;
}
status =
@@ -558,10 +554,7 @@ acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value)
break;
}
- unlock_and_exit:
- if (ACPI_MTX_LOCK == use_lock) {
- acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
- }
+ exit:
if (ACPI_SUCCESS(status)) {
*return_value = value1;
@@ -574,8 +567,7 @@ acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value)
*
* FUNCTION: acpi_hw_register_write
*
- * PARAMETERS: use_lock - Lock hardware? True/False
- * register_id - ACPI Register ID
+ * PARAMETERS: register_id - ACPI Register ID
* Value - The value to write
*
* RETURN: Status
@@ -597,28 +589,22 @@ acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value)
*
******************************************************************************/
-acpi_status acpi_hw_register_write(u8 use_lock, u32 register_id, u32 value)
+acpi_status acpi_hw_register_write(u32 register_id, u32 value)
{
acpi_status status;
- acpi_cpu_flags lock_flags = 0;
u32 read_value;
ACPI_FUNCTION_TRACE(hw_register_write);
- if (ACPI_MTX_LOCK == use_lock) {
- lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
- }
-
switch (register_id) {
case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */
/* Perform a read first to preserve certain bits (per ACPI spec) */
- status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1_STATUS,
+ status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS,
&read_value);
if (ACPI_FAILURE(status)) {
- goto unlock_and_exit;
+ goto exit;
}
/* Insert the bits to be preserved */
@@ -632,7 +618,7 @@ acpi_status acpi_hw_register_write(u8 use_lock, u32 register_id, u32 value)
acpi_hw_low_level_write(16, value,
&acpi_gbl_FADT.xpm1a_event_block);
if (ACPI_FAILURE(status)) {
- goto unlock_and_exit;
+ goto exit;
}
/* PM1B is optional */
@@ -647,7 +633,7 @@ acpi_status acpi_hw_register_write(u8 use_lock, u32 register_id, u32 value)
status =
acpi_hw_low_level_write(16, value, &acpi_gbl_xpm1a_enable);
if (ACPI_FAILURE(status)) {
- goto unlock_and_exit;
+ goto exit;
}
/* PM1B is optional */
@@ -661,11 +647,10 @@ acpi_status acpi_hw_register_write(u8 use_lock, u32 register_id, u32 value)
/*
* Perform a read first to preserve certain bits (per ACPI spec)
*/
- status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1_CONTROL,
+ status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL,
&read_value);
if (ACPI_FAILURE(status)) {
- goto unlock_and_exit;
+ goto exit;
}
/* Insert the bits to be preserved */
@@ -679,7 +664,7 @@ acpi_status acpi_hw_register_write(u8 use_lock, u32 register_id, u32 value)
acpi_hw_low_level_write(16, value,
&acpi_gbl_FADT.xpm1a_control_block);
if (ACPI_FAILURE(status)) {
- goto unlock_and_exit;
+ goto exit;
}
status =
@@ -728,11 +713,7 @@ acpi_status acpi_hw_register_write(u8 use_lock, u32 register_id, u32 value)
break;
}
- unlock_and_exit:
- if (ACPI_MTX_LOCK == use_lock) {
- acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
- }
-
+ exit:
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c
index cf69c0040a39..81b248429703 100644
--- a/drivers/acpi/hardware/hwsleep.c
+++ b/drivers/acpi/hardware/hwsleep.c
@@ -234,15 +234,11 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state)
"While executing method _SST"));
}
- /*
- * 1) Disable/Clear all GPEs
- */
+ /* Disable/Clear all GPEs */
+
status = acpi_hw_disable_all_gpes();
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
- return_ACPI_STATUS(AE_OK);
+ return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep)
@@ -313,8 +309,7 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
/* Get current value of PM1A control */
- status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol);
+ status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
@@ -341,15 +336,13 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
/* Write #1: fill in SLP_TYP data */
- status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1A_CONTROL,
+ status = acpi_hw_register_write(ACPI_REGISTER_PM1A_CONTROL,
PM1Acontrol);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
- status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1B_CONTROL,
+ status = acpi_hw_register_write(ACPI_REGISTER_PM1B_CONTROL,
PM1Bcontrol);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
@@ -364,15 +357,13 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
ACPI_FLUSH_CPU_CACHE();
- status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1A_CONTROL,
+ status = acpi_hw_register_write(ACPI_REGISTER_PM1A_CONTROL,
PM1Acontrol);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
- status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1B_CONTROL,
+ status = acpi_hw_register_write(ACPI_REGISTER_PM1B_CONTROL,
PM1Bcontrol);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
@@ -392,8 +383,7 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
*/
acpi_os_stall(10000000);
- status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1_CONTROL,
+ status = acpi_hw_register_write(ACPI_REGISTER_PM1_CONTROL,
sleep_enable_reg_info->
access_bit_mask);
if (ACPI_FAILURE(status)) {
@@ -404,7 +394,8 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
/* Wait until we enter sleep state */
do {
- status = acpi_get_register(ACPI_BITREG_WAKE_STATUS, &in_value);
+ status = acpi_get_register_unlocked(ACPI_BITREG_WAKE_STATUS,
+ &in_value);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
@@ -520,8 +511,7 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state)
/* Get current value of PM1A control */
- status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1_CONTROL,
+ status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL,
&PM1Acontrol);
if (ACPI_SUCCESS(status)) {
@@ -543,11 +533,9 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state)
/* Just ignore any errors */
- (void)acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1A_CONTROL,
+ (void)acpi_hw_register_write(ACPI_REGISTER_PM1A_CONTROL,
PM1Acontrol);
- (void)acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1B_CONTROL,
+ (void)acpi_hw_register_write(ACPI_REGISTER_PM1B_CONTROL,
PM1Bcontrol);
}
}
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 352cf81af581..aabc6ca4a81c 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -1043,14 +1043,6 @@ static int __init acpi_wake_gpes_always_on_setup(char *str)
__setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup);
/*
- * max_cstate is defined in the base kernel so modules can
- * change it w/o depending on the state of the processor module.
- */
-unsigned int max_cstate = ACPI_PROCESSOR_MAX_POWER;
-
-EXPORT_SYMBOL(max_cstate);
-
-/*
* Acquire a spinlock.
*
* handle is a pointer to the spinlock_t.
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 57b9a2998fd0..af1769a20c7a 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -86,7 +86,6 @@ struct acpi_power_resource {
acpi_bus_id name;
u32 system_level;
u32 order;
- int state;
struct mutex resource_lock;
struct list_head reference;
};
@@ -128,33 +127,31 @@ acpi_power_get_context(acpi_handle handle,
return 0;
}
-static int acpi_power_get_state(struct acpi_power_resource *resource)
+static int acpi_power_get_state(struct acpi_power_resource *resource, int *state)
{
acpi_status status = AE_OK;
unsigned long sta = 0;
- if (!resource)
+ if (!resource || !state)
return -EINVAL;
status = acpi_evaluate_integer(resource->device->handle, "_STA", NULL, &sta);
if (ACPI_FAILURE(status))
return -ENODEV;
- if (sta & 0x01)
- resource->state = ACPI_POWER_RESOURCE_STATE_ON;
- else
- resource->state = ACPI_POWER_RESOURCE_STATE_OFF;
+ *state = (sta & 0x01)?ACPI_POWER_RESOURCE_STATE_ON:
+ ACPI_POWER_RESOURCE_STATE_OFF;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n",
- resource->name, resource->state ? "on" : "off"));
+ resource->name, state ? "on" : "off"));
return 0;
}
static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
{
- int result = 0;
+ int result = 0, state1;
struct acpi_power_resource *resource = NULL;
u32 i = 0;
@@ -168,11 +165,11 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
result = acpi_power_get_context(list->handles[i], &resource);
if (result)
return result;
- result = acpi_power_get_state(resource);
+ result = acpi_power_get_state(resource, &state1);
if (result)
return result;
- *state = resource->state;
+ *state = state1;
if (*state != ACPI_POWER_RESOURCE_STATE_ON)
break;
@@ -186,7 +183,7 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
static int acpi_power_on(acpi_handle handle, struct acpi_device *dev)
{
- int result = 0;
+ int result = 0, state;
int found = 0;
acpi_status status = AE_OK;
struct acpi_power_resource *resource = NULL;
@@ -224,20 +221,14 @@ static int acpi_power_on(acpi_handle handle, struct acpi_device *dev)
}
mutex_unlock(&resource->resource_lock);
- if (resource->state == ACPI_POWER_RESOURCE_STATE_ON) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already on\n",
- resource->name));
- return 0;
- }
-
status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL);
if (ACPI_FAILURE(status))
return -ENODEV;
- result = acpi_power_get_state(resource);
+ result = acpi_power_get_state(resource, &state);
if (result)
return result;
- if (resource->state != ACPI_POWER_RESOURCE_STATE_ON)
+ if (state != ACPI_POWER_RESOURCE_STATE_ON)
return -ENOEXEC;
/* Update the power resource's _device_ power state */
@@ -250,7 +241,7 @@ static int acpi_power_on(acpi_handle handle, struct acpi_device *dev)
static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev)
{
- int result = 0;
+ int result = 0, state;
acpi_status status = AE_OK;
struct acpi_power_resource *resource = NULL;
struct list_head *node, *next;
@@ -281,20 +272,14 @@ static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev)
}
mutex_unlock(&resource->resource_lock);
- if (resource->state == ACPI_POWER_RESOURCE_STATE_OFF) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already off\n",
- resource->name));
- return 0;
- }
-
status = acpi_evaluate_object(resource->device->handle, "_OFF", NULL, NULL);
if (ACPI_FAILURE(status))
return -ENODEV;
- result = acpi_power_get_state(resource);
+ result = acpi_power_get_state(resource, &state);
if (result)
return result;
- if (resource->state != ACPI_POWER_RESOURCE_STATE_OFF)
+ if (state != ACPI_POWER_RESOURCE_STATE_OFF)
return -ENOEXEC;
/* Update the power resource's _device_ power state */
@@ -494,7 +479,7 @@ static struct proc_dir_entry *acpi_power_dir;
static int acpi_power_seq_show(struct seq_file *seq, void *offset)
{
int count = 0;
- int result = 0;
+ int result = 0, state;
struct acpi_power_resource *resource = NULL;
struct list_head *node, *next;
struct acpi_power_reference *ref;
@@ -505,12 +490,12 @@ static int acpi_power_seq_show(struct seq_file *seq, void *offset)
if (!resource)
goto end;
- result = acpi_power_get_state(resource);
+ result = acpi_power_get_state(resource, &state);
if (result)
goto end;
seq_puts(seq, "state: ");
- switch (resource->state) {
+ switch (state) {
case ACPI_POWER_RESOURCE_STATE_ON:
seq_puts(seq, "on\n");
break;
@@ -591,7 +576,7 @@ static int acpi_power_remove_fs(struct acpi_device *device)
static int acpi_power_add(struct acpi_device *device)
{
- int result = 0;
+ int result = 0, state;
acpi_status status = AE_OK;
struct acpi_power_resource *resource = NULL;
union acpi_object acpi_object;
@@ -622,11 +607,11 @@ static int acpi_power_add(struct acpi_device *device)
resource->system_level = acpi_object.power_resource.system_level;
resource->order = acpi_object.power_resource.resource_order;
- result = acpi_power_get_state(resource);
+ result = acpi_power_get_state(resource, &state);
if (result)
goto end;
- switch (resource->state) {
+ switch (state) {
case ACPI_POWER_RESOURCE_STATE_ON:
device->power.state = ACPI_STATE_D0;
break;
@@ -643,7 +628,7 @@ static int acpi_power_add(struct acpi_device *device)
goto end;
printk(KERN_INFO PREFIX "%s [%s] (%s)\n", acpi_device_name(device),
- acpi_device_bid(device), resource->state ? "on" : "off");
+ acpi_device_bid(device), state ? "on" : "off");
end:
if (result)
@@ -680,7 +665,7 @@ static int acpi_power_remove(struct acpi_device *device, int type)
static int acpi_power_resume(struct acpi_device *device)
{
- int result = 0;
+ int result = 0, state;
struct acpi_power_resource *resource = NULL;
struct acpi_power_reference *ref;
@@ -689,12 +674,12 @@ static int acpi_power_resume(struct acpi_device *device)
resource = (struct acpi_power_resource *)acpi_driver_data(device);
- result = acpi_power_get_state(resource);
+ result = acpi_power_get_state(resource, &state);
if (result)
return result;
mutex_lock(&resource->resource_lock);
- if ((resource->state == ACPI_POWER_RESOURCE_STATE_OFF) &&
+ if (state == ACPI_POWER_RESOURCE_STATE_OFF &&
!list_empty(&resource->reference)) {
ref = container_of(resource->reference.next, struct acpi_power_reference, node);
mutex_unlock(&resource->resource_lock);
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 9f11dc296cdd..235a51e328c3 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -44,6 +44,7 @@
#include <linux/seq_file.h>
#include <linux/dmi.h>
#include <linux/moduleparam.h>
+#include <linux/cpuidle.h>
#include <asm/io.h>
#include <asm/system.h>
@@ -421,12 +422,6 @@ static int map_lsapic_id(struct acpi_subtable_header *entry,
return 0;
}
-#ifdef CONFIG_IA64
-#define arch_cpu_to_apicid ia64_cpu_to_sapicid
-#else
-#define arch_cpu_to_apicid x86_cpu_to_apicid
-#endif
-
static int map_madt_entry(u32 acpi_id)
{
unsigned long madt_end, entry;
@@ -500,7 +495,7 @@ static int get_cpu_id(acpi_handle handle, u32 acpi_id)
return apic_id;
for (i = 0; i < NR_CPUS; ++i) {
- if (arch_cpu_to_apicid[i] == apic_id)
+ if (cpu_physical_id(i) == apic_id)
return i;
}
return -1;
@@ -1049,11 +1044,13 @@ static int __init acpi_processor_init(void)
return -ENOMEM;
acpi_processor_dir->owner = THIS_MODULE;
+ result = cpuidle_register_driver(&acpi_idle_driver);
+ if (result < 0)
+ goto out_proc;
+
result = acpi_bus_register_driver(&acpi_processor_driver);
- if (result < 0) {
- remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
- return result;
- }
+ if (result < 0)
+ goto out_cpuidle;
acpi_processor_install_hotplug_notify();
@@ -1062,11 +1059,18 @@ static int __init acpi_processor_init(void)
acpi_processor_ppc_init();
return 0;
+
+out_cpuidle:
+ cpuidle_unregister_driver(&acpi_idle_driver);
+
+out_proc:
+ remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
+
+ return result;
}
static void __exit acpi_processor_exit(void)
{
-
acpi_processor_ppc_exit();
acpi_thermal_cpufreq_exit();
@@ -1075,6 +1079,8 @@ static void __exit acpi_processor_exit(void)
acpi_bus_unregister_driver(&acpi_processor_driver);
+ cpuidle_unregister_driver(&acpi_idle_driver);
+
remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
return;
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 1f6fb38de017..f996d0e37689 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -40,6 +40,7 @@
#include <linux/sched.h> /* need_resched() */
#include <linux/latency.h>
#include <linux/clockchips.h>
+#include <linux/cpuidle.h>
/*
* Include the apic definitions for x86 to have the APIC timer related defines
@@ -64,14 +65,22 @@ ACPI_MODULE_NAME("processor_idle");
#define ACPI_PROCESSOR_FILE_POWER "power"
#define US_TO_PM_TIMER_TICKS(t) ((t * (PM_TIMER_FREQUENCY/1000)) / 1000)
#define PM_TIMER_TICK_NS (1000000000ULL/PM_TIMER_FREQUENCY)
+#ifndef CONFIG_CPU_IDLE
#define C2_OVERHEAD 4 /* 1us (3.579 ticks per us) */
#define C3_OVERHEAD 4 /* 1us (3.579 ticks per us) */
static void (*pm_idle_save) (void) __read_mostly;
-module_param(max_cstate, uint, 0644);
+#else
+#define C2_OVERHEAD 1 /* 1us */
+#define C3_OVERHEAD 1 /* 1us */
+#endif
+#define PM_TIMER_TICKS_TO_US(p) (((p) * 1000)/(PM_TIMER_FREQUENCY/1000))
+static unsigned int max_cstate __read_mostly = ACPI_PROCESSOR_MAX_POWER;
+module_param(max_cstate, uint, 0000);
static unsigned int nocst __read_mostly;
module_param(nocst, uint, 0000);
+#ifndef CONFIG_CPU_IDLE
/*
* bm_history -- bit-mask with a bit per jiffy of bus-master activity
* 1000 HZ: 0xFFFFFFFF: 32 jiffies = 32ms
@@ -82,9 +91,10 @@ module_param(nocst, uint, 0000);
static unsigned int bm_history __read_mostly =
(HZ >= 800 ? 0xFFFFFFFF : ((1U << (HZ / 25)) - 1));
module_param(bm_history, uint, 0644);
-/* --------------------------------------------------------------------------
- Power Management
- -------------------------------------------------------------------------- */
+
+static int acpi_processor_set_power_policy(struct acpi_processor *pr);
+
+#endif
/*
* IBM ThinkPad R40e crashes mysteriously when going into C2 or C3.
@@ -177,6 +187,18 @@ static inline u32 ticks_elapsed(u32 t1, u32 t2)
return ((0xFFFFFFFF - t1) + t2);
}
+static inline u32 ticks_elapsed_in_us(u32 t1, u32 t2)
+{
+ if (t2 >= t1)
+ return PM_TIMER_TICKS_TO_US(t2 - t1);
+ else if (!(acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER))
+ return PM_TIMER_TICKS_TO_US(((0x00FFFFFF - t1) + t2) & 0x00FFFFFF);
+ else
+ return PM_TIMER_TICKS_TO_US((0xFFFFFFFF - t1) + t2);
+}
+
+#ifndef CONFIG_CPU_IDLE
+
static void
acpi_processor_power_activate(struct acpi_processor *pr,
struct acpi_processor_cx *new)
@@ -248,6 +270,7 @@ static void acpi_cstate_enter(struct acpi_processor_cx *cstate)
unused = inl(acpi_gbl_FADT.xpm_timer_block.address);
}
}
+#endif /* !CONFIG_CPU_IDLE */
#ifdef ARCH_APICTIMER_STOPS_ON_C3
@@ -330,6 +353,7 @@ int acpi_processor_resume(struct acpi_device * device)
return 0;
}
+#ifndef CONFIG_CPU_IDLE
static void acpi_processor_idle(void)
{
struct acpi_processor *pr = NULL;
@@ -427,7 +451,7 @@ static void acpi_processor_idle(void)
* an SMP system. We do it here instead of doing it at _CST/P_LVL
* detection phase, to work cleanly with logical CPU hotplug.
*/
- if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) &&
+ if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) &&
!pr->flags.has_cst && !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
cx = &pr->power.states[ACPI_STATE_C1];
#endif
@@ -727,6 +751,7 @@ static int acpi_processor_set_power_policy(struct acpi_processor *pr)
return 0;
}
+#endif /* !CONFIG_CPU_IDLE */
static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr)
{
@@ -744,7 +769,7 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr)
#ifndef CONFIG_HOTPLUG_CPU
/*
* Check for P_LVL2_UP flag before entering C2 and above on
- * an SMP system.
+ * an SMP system.
*/
if ((num_online_cpus() > 1) &&
!(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
@@ -945,7 +970,12 @@ static void acpi_processor_power_verify_c2(struct acpi_processor_cx *cx)
* Normalize the C2 latency to expidite policy
*/
cx->valid = 1;
+
+#ifndef CONFIG_CPU_IDLE
cx->latency_ticks = US_TO_PM_TIMER_TICKS(cx->latency);
+#else
+ cx->latency_ticks = cx->latency;
+#endif
return;
}
@@ -1025,7 +1055,12 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr,
* use this in our C3 policy
*/
cx->valid = 1;
+
+#ifndef CONFIG_CPU_IDLE
cx->latency_ticks = US_TO_PM_TIMER_TICKS(cx->latency);
+#else
+ cx->latency_ticks = cx->latency;
+#endif
return;
}
@@ -1090,6 +1125,7 @@ static int acpi_processor_get_power_info(struct acpi_processor *pr)
pr->power.count = acpi_processor_power_verify(pr);
+#ifndef CONFIG_CPU_IDLE
/*
* Set Default Policy
* ------------------
@@ -1101,6 +1137,7 @@ static int acpi_processor_get_power_info(struct acpi_processor *pr)
result = acpi_processor_set_power_policy(pr);
if (result)
return result;
+#endif
/*
* if one state of type C2 or C3 is available, mark this
@@ -1117,35 +1154,6 @@ static int acpi_processor_get_power_info(struct acpi_processor *pr)
return 0;
}
-int acpi_processor_cst_has_changed(struct acpi_processor *pr)
-{
- int result = 0;
-
-
- if (!pr)
- return -EINVAL;
-
- if (nocst) {
- return -ENODEV;
- }
-
- if (!pr->flags.power_setup_done)
- return -ENODEV;
-
- /* Fall back to the default idle loop */
- pm_idle = pm_idle_save;
- synchronize_sched(); /* Relies on interrupts forcing exit from idle. */
-
- pr->flags.power = 0;
- result = acpi_processor_get_power_info(pr);
- if ((pr->flags.power == 1) && (pr->flags.power_setup_done))
- pm_idle = acpi_processor_idle;
-
- return result;
-}
-
-/* proc interface */
-
static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset)
{
struct acpi_processor *pr = seq->private;
@@ -1227,6 +1235,35 @@ static const struct file_operations acpi_processor_power_fops = {
.release = single_release,
};
+#ifndef CONFIG_CPU_IDLE
+
+int acpi_processor_cst_has_changed(struct acpi_processor *pr)
+{
+ int result = 0;
+
+
+ if (!pr)
+ return -EINVAL;
+
+ if (nocst) {
+ return -ENODEV;
+ }
+
+ if (!pr->flags.power_setup_done)
+ return -ENODEV;
+
+ /* Fall back to the default idle loop */
+ pm_idle = pm_idle_save;
+ synchronize_sched(); /* Relies on interrupts forcing exit from idle. */
+
+ pr->flags.power = 0;
+ result = acpi_processor_get_power_info(pr);
+ if ((pr->flags.power == 1) && (pr->flags.power_setup_done))
+ pm_idle = acpi_processor_idle;
+
+ return result;
+}
+
#ifdef CONFIG_SMP
static void smp_callback(void *v)
{
@@ -1249,7 +1286,366 @@ static int acpi_processor_latency_notify(struct notifier_block *b,
static struct notifier_block acpi_processor_latency_notifier = {
.notifier_call = acpi_processor_latency_notify,
};
+
+#endif
+
+#else /* CONFIG_CPU_IDLE */
+
+/**
+ * acpi_idle_bm_check - checks if bus master activity was detected
+ */
+static int acpi_idle_bm_check(void)
+{
+ u32 bm_status = 0;
+
+ acpi_get_register(ACPI_BITREG_BUS_MASTER_STATUS, &bm_status);
+ if (bm_status)
+ acpi_set_register(ACPI_BITREG_BUS_MASTER_STATUS, 1);
+ /*
+ * PIIX4 Erratum #18: Note that BM_STS doesn't always reflect
+ * the true state of bus mastering activity; forcing us to
+ * manually check the BMIDEA bit of each IDE channel.
+ */
+ else if (errata.piix4.bmisx) {
+ if ((inb_p(errata.piix4.bmisx + 0x02) & 0x01)
+ || (inb_p(errata.piix4.bmisx + 0x0A) & 0x01))
+ bm_status = 1;
+ }
+ return bm_status;
+}
+
+/**
+ * acpi_idle_update_bm_rld - updates the BM_RLD bit depending on target state
+ * @pr: the processor
+ * @target: the new target state
+ */
+static inline void acpi_idle_update_bm_rld(struct acpi_processor *pr,
+ struct acpi_processor_cx *target)
+{
+ if (pr->flags.bm_rld_set && target->type != ACPI_STATE_C3) {
+ acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0);
+ pr->flags.bm_rld_set = 0;
+ }
+
+ if (!pr->flags.bm_rld_set && target->type == ACPI_STATE_C3) {
+ acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1);
+ pr->flags.bm_rld_set = 1;
+ }
+}
+
+/**
+ * acpi_idle_do_entry - a helper function that does C2 and C3 type entry
+ * @cx: cstate data
+ */
+static inline void acpi_idle_do_entry(struct acpi_processor_cx *cx)
+{
+ if (cx->space_id == ACPI_CSTATE_FFH) {
+ /* Call into architectural FFH based C-state */
+ acpi_processor_ffh_cstate_enter(cx);
+ } else {
+ int unused;
+ /* IO port based C-state */
+ inb(cx->address);
+ /* Dummy wait op - must do something useless after P_LVL2 read
+ because chipsets cannot guarantee that STPCLK# signal
+ gets asserted in time to freeze execution properly. */
+ unused = inl(acpi_gbl_FADT.xpm_timer_block.address);
+ }
+}
+
+/**
+ * acpi_idle_enter_c1 - enters an ACPI C1 state-type
+ * @dev: the target CPU
+ * @state: the state data
+ *
+ * This is equivalent to the HALT instruction.
+ */
+static int acpi_idle_enter_c1(struct cpuidle_device *dev,
+ struct cpuidle_state *state)
+{
+ struct acpi_processor *pr;
+ struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
+ pr = processors[smp_processor_id()];
+
+ if (unlikely(!pr))
+ return 0;
+
+ if (pr->flags.bm_check)
+ acpi_idle_update_bm_rld(pr, cx);
+
+ current_thread_info()->status &= ~TS_POLLING;
+ /*
+ * TS_POLLING-cleared state must be visible before we test
+ * NEED_RESCHED:
+ */
+ smp_mb();
+ if (!need_resched())
+ safe_halt();
+ current_thread_info()->status |= TS_POLLING;
+
+ cx->usage++;
+
+ return 0;
+}
+
+/**
+ * acpi_idle_enter_simple - enters an ACPI state without BM handling
+ * @dev: the target CPU
+ * @state: the state data
+ */
+static int acpi_idle_enter_simple(struct cpuidle_device *dev,
+ struct cpuidle_state *state)
+{
+ struct acpi_processor *pr;
+ struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
+ u32 t1, t2;
+ pr = processors[smp_processor_id()];
+
+ if (unlikely(!pr))
+ return 0;
+
+ if (acpi_idle_suspend)
+ return(acpi_idle_enter_c1(dev, state));
+
+ if (pr->flags.bm_check)
+ acpi_idle_update_bm_rld(pr, cx);
+
+ local_irq_disable();
+ current_thread_info()->status &= ~TS_POLLING;
+ /*
+ * TS_POLLING-cleared state must be visible before we test
+ * NEED_RESCHED:
+ */
+ smp_mb();
+
+ if (unlikely(need_resched())) {
+ current_thread_info()->status |= TS_POLLING;
+ local_irq_enable();
+ return 0;
+ }
+
+ if (cx->type == ACPI_STATE_C3)
+ ACPI_FLUSH_CPU_CACHE();
+
+ t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
+ acpi_state_timer_broadcast(pr, cx, 1);
+ acpi_idle_do_entry(cx);
+ t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
+
+#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC)
+ /* TSC could halt in idle, so notify users */
+ mark_tsc_unstable("TSC halts in idle");;
+#endif
+
+ local_irq_enable();
+ current_thread_info()->status |= TS_POLLING;
+
+ cx->usage++;
+
+ acpi_state_timer_broadcast(pr, cx, 0);
+ cx->time += ticks_elapsed(t1, t2);
+ return ticks_elapsed_in_us(t1, t2);
+}
+
+static int c3_cpu_count;
+static DEFINE_SPINLOCK(c3_lock);
+
+/**
+ * acpi_idle_enter_bm - enters C3 with proper BM handling
+ * @dev: the target CPU
+ * @state: the state data
+ *
+ * If BM is detected, the deepest non-C3 idle state is entered instead.
+ */
+static int acpi_idle_enter_bm(struct cpuidle_device *dev,
+ struct cpuidle_state *state)
+{
+ struct acpi_processor *pr;
+ struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
+ u32 t1, t2;
+ pr = processors[smp_processor_id()];
+
+ if (unlikely(!pr))
+ return 0;
+
+ if (acpi_idle_suspend)
+ return(acpi_idle_enter_c1(dev, state));
+
+ local_irq_disable();
+ current_thread_info()->status &= ~TS_POLLING;
+ /*
+ * TS_POLLING-cleared state must be visible before we test
+ * NEED_RESCHED:
+ */
+ smp_mb();
+
+ if (unlikely(need_resched())) {
+ current_thread_info()->status |= TS_POLLING;
+ local_irq_enable();
+ return 0;
+ }
+
+ /*
+ * Must be done before busmaster disable as we might need to
+ * access HPET !
+ */
+ acpi_state_timer_broadcast(pr, cx, 1);
+
+ if (acpi_idle_bm_check()) {
+ cx = pr->power.bm_state;
+
+ acpi_idle_update_bm_rld(pr, cx);
+
+ t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
+ acpi_idle_do_entry(cx);
+ t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
+ } else {
+ acpi_idle_update_bm_rld(pr, cx);
+
+ spin_lock(&c3_lock);
+ c3_cpu_count++;
+ /* Disable bus master arbitration when all CPUs are in C3 */
+ if (c3_cpu_count == num_online_cpus())
+ acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1);
+ spin_unlock(&c3_lock);
+
+ t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
+ acpi_idle_do_entry(cx);
+ t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
+
+ spin_lock(&c3_lock);
+ /* Re-enable bus master arbitration */
+ if (c3_cpu_count == num_online_cpus())
+ acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0);
+ c3_cpu_count--;
+ spin_unlock(&c3_lock);
+ }
+
+#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC)
+ /* TSC could halt in idle, so notify users */
+ mark_tsc_unstable("TSC halts in idle");
+#endif
+
+ local_irq_enable();
+ current_thread_info()->status |= TS_POLLING;
+
+ cx->usage++;
+
+ acpi_state_timer_broadcast(pr, cx, 0);
+ cx->time += ticks_elapsed(t1, t2);
+ return ticks_elapsed_in_us(t1, t2);
+}
+
+struct cpuidle_driver acpi_idle_driver = {
+ .name = "acpi_idle",
+ .owner = THIS_MODULE,
+};
+
+/**
+ * acpi_processor_setup_cpuidle - prepares and configures CPUIDLE
+ * @pr: the ACPI processor
+ */
+static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
+{
+ int i, count = 0;
+ struct acpi_processor_cx *cx;
+ struct cpuidle_state *state;
+ struct cpuidle_device *dev = &pr->power.dev;
+
+ if (!pr->flags.power_setup_done)
+ return -EINVAL;
+
+ if (pr->flags.power == 0) {
+ return -EINVAL;
+ }
+
+ for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) {
+ cx = &pr->power.states[i];
+ state = &dev->states[count];
+
+ if (!cx->valid)
+ continue;
+
+#ifdef CONFIG_HOTPLUG_CPU
+ if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) &&
+ !pr->flags.has_cst &&
+ !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
+ continue;
#endif
+ cpuidle_set_statedata(state, cx);
+
+ snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i);
+ state->exit_latency = cx->latency;
+ state->target_residency = cx->latency * 6;
+ state->power_usage = cx->power;
+
+ state->flags = 0;
+ switch (cx->type) {
+ case ACPI_STATE_C1:
+ state->flags |= CPUIDLE_FLAG_SHALLOW;
+ state->enter = acpi_idle_enter_c1;
+ break;
+
+ case ACPI_STATE_C2:
+ state->flags |= CPUIDLE_FLAG_BALANCED;
+ state->flags |= CPUIDLE_FLAG_TIME_VALID;
+ state->enter = acpi_idle_enter_simple;
+ break;
+
+ case ACPI_STATE_C3:
+ state->flags |= CPUIDLE_FLAG_DEEP;
+ state->flags |= CPUIDLE_FLAG_TIME_VALID;
+ state->flags |= CPUIDLE_FLAG_CHECK_BM;
+ state->enter = pr->flags.bm_check ?
+ acpi_idle_enter_bm :
+ acpi_idle_enter_simple;
+ break;
+ }
+
+ count++;
+ }
+
+ dev->state_count = count;
+
+ if (!count)
+ return -EINVAL;
+
+ /* find the deepest state that can handle active BM */
+ if (pr->flags.bm_check) {
+ for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++)
+ if (pr->power.states[i].type == ACPI_STATE_C3)
+ break;
+ pr->power.bm_state = &pr->power.states[i-1];
+ }
+
+ return 0;
+}
+
+int acpi_processor_cst_has_changed(struct acpi_processor *pr)
+{
+ int ret;
+
+ if (!pr)
+ return -EINVAL;
+
+ if (nocst) {
+ return -ENODEV;
+ }
+
+ if (!pr->flags.power_setup_done)
+ return -ENODEV;
+
+ cpuidle_pause_and_lock();
+ cpuidle_disable_device(&pr->power.dev);
+ acpi_processor_get_power_info(pr);
+ acpi_processor_setup_cpuidle(pr);
+ ret = cpuidle_enable_device(&pr->power.dev);
+ cpuidle_resume_and_unlock();
+
+ return ret;
+}
+
+#endif /* CONFIG_CPU_IDLE */
int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
struct acpi_device *device)
@@ -1267,7 +1663,7 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
"ACPI: processor limited to max C-state %d\n",
max_cstate);
first_run++;
-#ifdef CONFIG_SMP
+#if !defined (CONFIG_CPU_IDLE) && defined (CONFIG_SMP)
register_latency_notifier(&acpi_processor_latency_notifier);
#endif
}
@@ -1285,6 +1681,7 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
}
acpi_processor_get_power_info(pr);
+ pr->flags.power_setup_done = 1;
/*
* Install the idle handler if processor power management is supported.
@@ -1292,6 +1689,13 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
* platforms that only support C1.
*/
if ((pr->flags.power) && (!boot_option_idle_override)) {
+#ifdef CONFIG_CPU_IDLE
+ acpi_processor_setup_cpuidle(pr);
+ pr->power.dev.cpu = pr->id;
+ if (cpuidle_register_device(&pr->power.dev))
+ return -EIO;
+#endif
+
printk(KERN_INFO PREFIX "CPU%d (power states:", pr->id);
for (i = 1; i <= pr->power.count; i++)
if (pr->power.states[i].valid)
@@ -1299,10 +1703,12 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
pr->power.states[i].type);
printk(")\n");
+#ifndef CONFIG_CPU_IDLE
if (pr->id == 0) {
pm_idle_save = pm_idle;
pm_idle = acpi_processor_idle;
}
+#endif
}
/* 'power' [R] */
@@ -1316,21 +1722,24 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
entry->owner = THIS_MODULE;
}
- pr->flags.power_setup_done = 1;
-
return 0;
}
int acpi_processor_power_exit(struct acpi_processor *pr,
struct acpi_device *device)
{
-
+#ifdef CONFIG_CPU_IDLE
+ if ((pr->flags.power) && (!boot_option_idle_override))
+ cpuidle_unregister_device(&pr->power.dev);
+#endif
pr->flags.power_setup_done = 0;
if (acpi_device_dir(device))
remove_proc_entry(ACPI_PROCESSOR_FILE_POWER,
acpi_device_dir(device));
+#ifndef CONFIG_CPU_IDLE
+
/* Unregister the idle handler when processor #0 is removed. */
if (pr->id == 0) {
pm_idle = pm_idle_save;
@@ -1345,6 +1754,7 @@ int acpi_processor_power_exit(struct acpi_processor *pr,
unregister_latency_notifier(&acpi_processor_latency_notifier);
#endif
}
+#endif
return 0;
}
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
index a578986e3214..90fd09c65f95 100644
--- a/drivers/acpi/sbs.c
+++ b/drivers/acpi/sbs.c
@@ -1,6 +1,8 @@
/*
- * acpi_sbs.c - ACPI Smart Battery System Driver ($Revision: 1.16 $)
+ * sbs.c - ACPI Smart Battery System Driver ($Revision: 2.0 $)
*
+ * Copyright (c) 2007 Alexey Starikovskiy <astarikovskiy@suse.de>
+ * Copyright (c) 2005-2007 Vladimir Lebedev <vladimir.p.lebedev@intel.com>
* Copyright (c) 2005 Rich Townsend <rhdt@bartol.udel.edu>
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -26,15 +28,22 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
+
+#ifdef CONFIG_ACPI_PROCFS
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <asm/uaccess.h>
+#endif
+
#include <linux/acpi.h>
#include <linux/timer.h>
#include <linux/jiffies.h>
#include <linux/delay.h>
-#define ACPI_SBS_COMPONENT 0x00080000
+#include <linux/power_supply.h>
+
+#include "sbshc.h"
+
#define ACPI_SBS_CLASS "sbs"
#define ACPI_AC_CLASS "ac_adapter"
#define ACPI_BATTERY_CLASS "battery"
@@ -44,836 +53,436 @@
#define ACPI_SBS_FILE_ALARM "alarm"
#define ACPI_BATTERY_DIR_NAME "BAT%i"
#define ACPI_AC_DIR_NAME "AC0"
-#define ACPI_SBC_SMBUS_ADDR 0x9
-#define ACPI_SBSM_SMBUS_ADDR 0xa
-#define ACPI_SB_SMBUS_ADDR 0xb
-#define ACPI_SBS_AC_NOTIFY_STATUS 0x80
-#define ACPI_SBS_BATTERY_NOTIFY_STATUS 0x80
-#define ACPI_SBS_BATTERY_NOTIFY_INFO 0x81
-#define _COMPONENT ACPI_SBS_COMPONENT
+enum acpi_sbs_device_addr {
+ ACPI_SBS_CHARGER = 0x9,
+ ACPI_SBS_MANAGER = 0xa,
+ ACPI_SBS_BATTERY = 0xb,
+};
-ACPI_MODULE_NAME("sbs");
+#define ACPI_SBS_NOTIFY_STATUS 0x80
+#define ACPI_SBS_NOTIFY_INFO 0x81
-MODULE_AUTHOR("Rich Townsend");
+MODULE_AUTHOR("Alexey Starikovskiy <astarikovskiy@suse.de>");
MODULE_DESCRIPTION("Smart Battery System ACPI interface driver");
MODULE_LICENSE("GPL");
-#define xmsleep(t) msleep(t)
-
-#define ACPI_EC_SMB_PRTCL 0x00 /* protocol, PEC */
-
-#define ACPI_EC_SMB_STS 0x01 /* status */
-#define ACPI_EC_SMB_ADDR 0x02 /* address */
-#define ACPI_EC_SMB_CMD 0x03 /* command */
-#define ACPI_EC_SMB_DATA 0x04 /* 32 data registers */
-#define ACPI_EC_SMB_BCNT 0x24 /* number of data bytes */
-
-#define ACPI_EC_SMB_STS_DONE 0x80
-#define ACPI_EC_SMB_STS_STATUS 0x1f
-
-#define ACPI_EC_SMB_PRTCL_WRITE 0x00
-#define ACPI_EC_SMB_PRTCL_READ 0x01
-#define ACPI_EC_SMB_PRTCL_WORD_DATA 0x08
-#define ACPI_EC_SMB_PRTCL_BLOCK_DATA 0x0a
-
-#define ACPI_EC_SMB_TRANSACTION_SLEEP 1
-#define ACPI_EC_SMB_ACCESS_SLEEP1 1
-#define ACPI_EC_SMB_ACCESS_SLEEP2 10
-
-#define DEF_CAPACITY_UNIT 3
-#define MAH_CAPACITY_UNIT 1
-#define MWH_CAPACITY_UNIT 2
-#define CAPACITY_UNIT DEF_CAPACITY_UNIT
-
-#define REQUEST_UPDATE_MODE 1
-#define QUEUE_UPDATE_MODE 2
-
-#define DATA_TYPE_COMMON 0
-#define DATA_TYPE_INFO 1
-#define DATA_TYPE_STATE 2
-#define DATA_TYPE_ALARM 3
-#define DATA_TYPE_AC_STATE 4
+static unsigned int cache_time = 1000;
+module_param(cache_time, uint, 0644);
+MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
extern struct proc_dir_entry *acpi_lock_ac_dir(void);
extern struct proc_dir_entry *acpi_lock_battery_dir(void);
extern void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir);
extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
-#define MAX_SBS_BAT 4
+#define MAX_SBS_BAT 4
#define ACPI_SBS_BLOCK_MAX 32
-#define ACPI_SBS_SMBUS_READ 1
-#define ACPI_SBS_SMBUS_WRITE 2
-
-#define ACPI_SBS_WORD_DATA 1
-#define ACPI_SBS_BLOCK_DATA 2
-
-#define UPDATE_DELAY 10
-
-/* 0 - every time, > 0 - by update_time */
-static unsigned int update_time = 120;
-
-static unsigned int capacity_mode = CAPACITY_UNIT;
-
-module_param(update_time, uint, 0644);
-module_param(capacity_mode, uint, 0444);
-
-static int acpi_sbs_add(struct acpi_device *device);
-static int acpi_sbs_remove(struct acpi_device *device, int type);
-static int acpi_sbs_resume(struct acpi_device *device);
-
static const struct acpi_device_id sbs_device_ids[] = {
- {"ACPI0001", 0},
- {"ACPI0005", 0},
+ {"ACPI0002", 0},
{"", 0},
};
MODULE_DEVICE_TABLE(acpi, sbs_device_ids);
-static struct acpi_driver acpi_sbs_driver = {
- .name = "sbs",
- .class = ACPI_SBS_CLASS,
- .ids = sbs_device_ids,
- .ops = {
- .add = acpi_sbs_add,
- .remove = acpi_sbs_remove,
- .resume = acpi_sbs_resume,
- },
-};
-
-struct acpi_ac {
- int ac_present;
-};
-
-struct acpi_battery_info {
- int capacity_mode;
- s16 full_charge_capacity;
- s16 design_capacity;
- s16 design_voltage;
- int vscale;
- int ipscale;
- s16 serial_number;
- char manufacturer_name[ACPI_SBS_BLOCK_MAX + 3];
- char device_name[ACPI_SBS_BLOCK_MAX + 3];
- char device_chemistry[ACPI_SBS_BLOCK_MAX + 3];
-};
-
-struct acpi_battery_state {
- s16 voltage;
- s16 amperage;
- s16 remaining_capacity;
- s16 battery_state;
-};
-
-struct acpi_battery_alarm {
- s16 remaining_capacity;
-};
-
struct acpi_battery {
- int alive;
- int id;
- int init_state;
- int battery_present;
+ struct power_supply bat;
struct acpi_sbs *sbs;
- struct acpi_battery_info info;
- struct acpi_battery_state state;
- struct acpi_battery_alarm alarm;
- struct proc_dir_entry *battery_entry;
+#ifdef CONFIG_ACPI_PROCFS
+ struct proc_dir_entry *proc_entry;
+#endif
+ unsigned long update_time;
+ char name[8];
+ char manufacturer_name[ACPI_SBS_BLOCK_MAX];
+ char device_name[ACPI_SBS_BLOCK_MAX];
+ char device_chemistry[ACPI_SBS_BLOCK_MAX];
+ u16 alarm_capacity;
+ u16 full_charge_capacity;
+ u16 design_capacity;
+ u16 design_voltage;
+ u16 serial_number;
+ u16 cycle_count;
+ u16 temp_now;
+ u16 voltage_now;
+ s16 current_now;
+ s16 current_avg;
+ u16 capacity_now;
+ u16 state_of_charge;
+ u16 state;
+ u16 mode;
+ u16 spec;
+ u8 id;
+ u8 present:1;
};
+#define to_acpi_battery(x) container_of(x, struct acpi_battery, bat);
+
struct acpi_sbs {
- int base;
+ struct power_supply charger;
struct acpi_device *device;
- struct mutex mutex;
- int sbsm_present;
- int sbsm_batteries_supported;
- struct proc_dir_entry *ac_entry;
- struct acpi_ac ac;
+ struct acpi_smb_hc *hc;
+ struct mutex lock;
+#ifdef CONFIG_ACPI_PROCFS
+ struct proc_dir_entry *charger_entry;
+#endif
struct acpi_battery battery[MAX_SBS_BAT];
- int zombie;
- struct timer_list update_timer;
- int run_cnt;
- int update_proc_flg;
+ u8 batteries_supported:4;
+ u8 manager_present:1;
+ u8 charger_present:1;
};
-static int acpi_sbs_update_run(struct acpi_sbs *sbs, int id, int data_type);
-static void acpi_sbs_update_time(void *data);
+#define to_acpi_sbs(x) container_of(x, struct acpi_sbs, charger)
-union sbs_rw_data {
- u16 word;
- u8 block[ACPI_SBS_BLOCK_MAX + 2];
-};
-
-static int acpi_ec_sbs_access(struct acpi_sbs *sbs, u16 addr,
- char read_write, u8 command, int size,
- union sbs_rw_data *data);
-
-/* --------------------------------------------------------------------------
- SMBus Communication
- -------------------------------------------------------------------------- */
-
-static int acpi_ec_sbs_read(struct acpi_sbs *sbs, u8 address, u8 * data)
+static inline int battery_scale(int log)
{
- u8 val;
- int err;
-
- err = ec_read(sbs->base + address, &val);
- if (!err) {
- *data = val;
- }
- xmsleep(ACPI_EC_SMB_TRANSACTION_SLEEP);
- return (err);
-}
-
-static int acpi_ec_sbs_write(struct acpi_sbs *sbs, u8 address, u8 data)
-{
- int err;
-
- err = ec_write(sbs->base + address, data);
- return (err);
-}
-
-static int
-acpi_ec_sbs_access(struct acpi_sbs *sbs, u16 addr,
- char read_write, u8 command, int size,
- union sbs_rw_data *data)
-{
- unsigned char protocol, len = 0, temp[2] = { 0, 0 };
- int i;
-
- if (read_write == ACPI_SBS_SMBUS_READ) {
- protocol = ACPI_EC_SMB_PRTCL_READ;
- } else {
- protocol = ACPI_EC_SMB_PRTCL_WRITE;
- }
-
- switch (size) {
-
- case ACPI_SBS_WORD_DATA:
- acpi_ec_sbs_write(sbs, ACPI_EC_SMB_CMD, command);
- if (read_write == ACPI_SBS_SMBUS_WRITE) {
- acpi_ec_sbs_write(sbs, ACPI_EC_SMB_DATA, data->word);
- acpi_ec_sbs_write(sbs, ACPI_EC_SMB_DATA + 1,
- data->word >> 8);
- }
- protocol |= ACPI_EC_SMB_PRTCL_WORD_DATA;
- break;
- case ACPI_SBS_BLOCK_DATA:
- acpi_ec_sbs_write(sbs, ACPI_EC_SMB_CMD, command);
- if (read_write == ACPI_SBS_SMBUS_WRITE) {
- len = min_t(u8, data->block[0], 32);
- acpi_ec_sbs_write(sbs, ACPI_EC_SMB_BCNT, len);
- for (i = 0; i < len; i++)
- acpi_ec_sbs_write(sbs, ACPI_EC_SMB_DATA + i,
- data->block[i + 1]);
- }
- protocol |= ACPI_EC_SMB_PRTCL_BLOCK_DATA;
- break;
- default:
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "unsupported transaction %d", size));
- return (-1);
- }
-
- acpi_ec_sbs_write(sbs, ACPI_EC_SMB_ADDR, addr << 1);
- acpi_ec_sbs_write(sbs, ACPI_EC_SMB_PRTCL, protocol);
-
- acpi_ec_sbs_read(sbs, ACPI_EC_SMB_STS, temp);
-
- if (~temp[0] & ACPI_EC_SMB_STS_DONE) {
- xmsleep(ACPI_EC_SMB_ACCESS_SLEEP1);
- acpi_ec_sbs_read(sbs, ACPI_EC_SMB_STS, temp);
- }
- if (~temp[0] & ACPI_EC_SMB_STS_DONE) {
- xmsleep(ACPI_EC_SMB_ACCESS_SLEEP2);
- acpi_ec_sbs_read(sbs, ACPI_EC_SMB_STS, temp);
- }
- if ((~temp[0] & ACPI_EC_SMB_STS_DONE)
- || (temp[0] & ACPI_EC_SMB_STS_STATUS)) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "transaction %d error", size));
- return (-1);
- }
-
- if (read_write == ACPI_SBS_SMBUS_WRITE) {
- return (0);
- }
-
- switch (size) {
-
- case ACPI_SBS_WORD_DATA:
- acpi_ec_sbs_read(sbs, ACPI_EC_SMB_DATA, temp);
- acpi_ec_sbs_read(sbs, ACPI_EC_SMB_DATA + 1, temp + 1);
- data->word = (temp[1] << 8) | temp[0];
- break;
-
- case ACPI_SBS_BLOCK_DATA:
- len = 0;
- acpi_ec_sbs_read(sbs, ACPI_EC_SMB_BCNT, &len);
- len = min_t(u8, len, 32);
- for (i = 0; i < len; i++)
- acpi_ec_sbs_read(sbs, ACPI_EC_SMB_DATA + i,
- data->block + i + 1);
- data->block[0] = len;
- break;
- default:
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "unsupported transaction %d", size));
- return (-1);
- }
-
- return (0);
+ int scale = 1;
+ while (log--)
+ scale *= 10;
+ return scale;
}
-static int
-acpi_sbs_read_word(struct acpi_sbs *sbs, int addr, int func, u16 * word)
+static inline int acpi_battery_vscale(struct acpi_battery *battery)
{
- union sbs_rw_data data;
- int result = 0;
-
- result = acpi_ec_sbs_access(sbs, addr,
- ACPI_SBS_SMBUS_READ, func,
- ACPI_SBS_WORD_DATA, &data);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_ec_sbs_access() failed"));
- } else {
- *word = data.word;
- }
-
- return result;
+ return battery_scale((battery->spec & 0x0f00) >> 8);
}
-static int
-acpi_sbs_read_str(struct acpi_sbs *sbs, int addr, int func, char *str)
+static inline int acpi_battery_ipscale(struct acpi_battery *battery)
{
- union sbs_rw_data data;
- int result = 0;
-
- result = acpi_ec_sbs_access(sbs, addr,
- ACPI_SBS_SMBUS_READ, func,
- ACPI_SBS_BLOCK_DATA, &data);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_ec_sbs_access() failed"));
- } else {
- strncpy(str, (const char *)data.block + 1, data.block[0]);
- str[data.block[0]] = 0;
- }
-
- return result;
+ return battery_scale((battery->spec & 0xf000) >> 12);
}
-static int
-acpi_sbs_write_word(struct acpi_sbs *sbs, int addr, int func, int word)
+static inline int acpi_battery_mode(struct acpi_battery *battery)
{
- union sbs_rw_data data;
- int result = 0;
-
- data.word = word;
-
- result = acpi_ec_sbs_access(sbs, addr,
- ACPI_SBS_SMBUS_WRITE, func,
- ACPI_SBS_WORD_DATA, &data);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_ec_sbs_access() failed"));
- }
-
- return result;
+ return (battery->mode & 0x8000);
}
-static int sbs_zombie(struct acpi_sbs *sbs)
+static inline int acpi_battery_scale(struct acpi_battery *battery)
{
- return (sbs->zombie);
+ return (acpi_battery_mode(battery) ? 10 : 1) *
+ acpi_battery_ipscale(battery);
}
-static int sbs_mutex_lock(struct acpi_sbs *sbs)
+static int sbs_get_ac_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
{
- if (sbs_zombie(sbs)) {
- return -ENODEV;
+ struct acpi_sbs *sbs = to_acpi_sbs(psy);
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = sbs->charger_present;
+ break;
+ default:
+ return -EINVAL;
}
- mutex_lock(&sbs->mutex);
return 0;
}
-static void sbs_mutex_unlock(struct acpi_sbs *sbs)
+static int acpi_battery_technology(struct acpi_battery *battery)
{
- mutex_unlock(&sbs->mutex);
+ if (!strcasecmp("NiCd", battery->device_chemistry))
+ return POWER_SUPPLY_TECHNOLOGY_NiCd;
+ if (!strcasecmp("NiMH", battery->device_chemistry))
+ return POWER_SUPPLY_TECHNOLOGY_NiMH;
+ if (!strcasecmp("LION", battery->device_chemistry))
+ return POWER_SUPPLY_TECHNOLOGY_LION;
+ if (!strcasecmp("LiP", battery->device_chemistry))
+ return POWER_SUPPLY_TECHNOLOGY_LIPO;
+ return POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
}
-/* --------------------------------------------------------------------------
- Smart Battery System Management
- -------------------------------------------------------------------------- */
-
-static int acpi_check_update_proc(struct acpi_sbs *sbs)
+static int acpi_sbs_battery_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
{
- acpi_status status = AE_OK;
+ struct acpi_battery *battery = to_acpi_battery(psy);
- if (update_time == 0) {
- sbs->update_proc_flg = 0;
- return 0;
- }
- if (sbs->update_proc_flg == 0) {
- status = acpi_os_execute(OSL_GPE_HANDLER,
- acpi_sbs_update_time, sbs);
- if (status != AE_OK) {
- ACPI_EXCEPTION((AE_INFO, status,
- "acpi_os_execute() failed"));
- return 1;
- }
- sbs->update_proc_flg = 1;
+ if ((!battery->present) && psp != POWER_SUPPLY_PROP_PRESENT)
+ return -ENODEV;
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ if (battery->current_now < 0)
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ else if (battery->current_now > 0)
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ else
+ val->intval = POWER_SUPPLY_STATUS_FULL;
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = battery->present;
+ break;
+ case POWER_SUPPLY_PROP_TECHNOLOGY:
+ val->intval = acpi_battery_technology(battery);
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+ val->intval = battery->design_voltage *
+ acpi_battery_vscale(battery) * 1000;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ val->intval = battery->voltage_now *
+ acpi_battery_vscale(battery) * 1000;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+ val->intval = abs(battery->current_now) *
+ acpi_battery_ipscale(battery) * 1000;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_AVG:
+ val->intval = abs(battery->current_avg) *
+ acpi_battery_ipscale(battery) * 1000;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
+ val->intval = battery->state_of_charge;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+ case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
+ val->intval = battery->design_capacity *
+ acpi_battery_scale(battery) * 1000;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL:
+ case POWER_SUPPLY_PROP_ENERGY_FULL:
+ val->intval = battery->full_charge_capacity *
+ acpi_battery_scale(battery) * 1000;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_NOW:
+ case POWER_SUPPLY_PROP_ENERGY_NOW:
+ val->intval = battery->capacity_now *
+ acpi_battery_scale(battery) * 1000;
+ break;
+ case POWER_SUPPLY_PROP_TEMP:
+ val->intval = battery->temp_now - 2730; // dK -> dC
+ break;
+ case POWER_SUPPLY_PROP_MODEL_NAME:
+ val->strval = battery->device_name;
+ break;
+ case POWER_SUPPLY_PROP_MANUFACTURER:
+ val->strval = battery->manufacturer_name;
+ break;
+ default:
+ return -EINVAL;
}
return 0;
}
-static int acpi_sbs_generate_event(struct acpi_device *device,
- int event, int state, char *bid, char *class)
-{
- char bid_saved[5];
- char class_saved[20];
- int result = 0;
-
- strcpy(bid_saved, acpi_device_bid(device));
- strcpy(class_saved, acpi_device_class(device));
-
- strcpy(acpi_device_bid(device), bid);
- strcpy(acpi_device_class(device), class);
-
- result = acpi_bus_generate_proc_event(device, event, state);
-
- strcpy(acpi_device_bid(device), bid_saved);
- strcpy(acpi_device_class(device), class_saved);
-
- acpi_bus_generate_netlink_event(class, bid, event, state);
- return result;
-}
-
-static int acpi_battery_get_present(struct acpi_battery *battery)
-{
- s16 state;
- int result = 0;
- int is_present = 0;
-
- result = acpi_sbs_read_word(battery->sbs,
- ACPI_SBSM_SMBUS_ADDR, 0x01, &state);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_read_word() failed"));
- }
- if (!result) {
- is_present = (state & 0x000f) & (1 << battery->id);
- }
- battery->battery_present = is_present;
-
- return result;
-}
+static enum power_supply_property sbs_ac_props[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+};
-static int acpi_battery_select(struct acpi_battery *battery)
-{
- struct acpi_sbs *sbs = battery->sbs;
- int result = 0;
- s16 state;
- int foo;
+static enum power_supply_property sbs_charge_battery_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+ POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CURRENT_AVG,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+ POWER_SUPPLY_PROP_CHARGE_FULL,
+ POWER_SUPPLY_PROP_CHARGE_NOW,
+ POWER_SUPPLY_PROP_TEMP,
+ POWER_SUPPLY_PROP_MODEL_NAME,
+ POWER_SUPPLY_PROP_MANUFACTURER,
+};
- if (sbs->sbsm_present) {
+static enum power_supply_property sbs_energy_battery_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+ POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CURRENT_AVG,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
+ POWER_SUPPLY_PROP_ENERGY_FULL,
+ POWER_SUPPLY_PROP_ENERGY_NOW,
+ POWER_SUPPLY_PROP_TEMP,
+ POWER_SUPPLY_PROP_MODEL_NAME,
+ POWER_SUPPLY_PROP_MANUFACTURER,
+};
- /* Take special care not to knobble other nibbles of
- * state (aka selector_state), since
- * it causes charging to halt on SBSELs */
+/* --------------------------------------------------------------------------
+ Smart Battery System Management
+ -------------------------------------------------------------------------- */
- result =
- acpi_sbs_read_word(sbs, ACPI_SBSM_SMBUS_ADDR, 0x01, &state);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_read_word() failed"));
- goto end;
- }
+struct acpi_battery_reader {
+ u8 command; /* command for battery */
+ u8 mode; /* word or block? */
+ size_t offset; /* offset inside struct acpi_sbs_battery */
+};
- foo = (state & 0x0fff) | (1 << (battery->id + 12));
- result =
- acpi_sbs_write_word(sbs, ACPI_SBSM_SMBUS_ADDR, 0x01, foo);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_write_word() failed"));
- goto end;
- }
- }
+static struct acpi_battery_reader info_readers[] = {
+ {0x01, SMBUS_READ_WORD, offsetof(struct acpi_battery, alarm_capacity)},
+ {0x03, SMBUS_READ_WORD, offsetof(struct acpi_battery, mode)},
+ {0x10, SMBUS_READ_WORD, offsetof(struct acpi_battery, full_charge_capacity)},
+ {0x17, SMBUS_READ_WORD, offsetof(struct acpi_battery, cycle_count)},
+ {0x18, SMBUS_READ_WORD, offsetof(struct acpi_battery, design_capacity)},
+ {0x19, SMBUS_READ_WORD, offsetof(struct acpi_battery, design_voltage)},
+ {0x1a, SMBUS_READ_WORD, offsetof(struct acpi_battery, spec)},
+ {0x1c, SMBUS_READ_WORD, offsetof(struct acpi_battery, serial_number)},
+ {0x20, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, manufacturer_name)},
+ {0x21, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, device_name)},
+ {0x22, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, device_chemistry)},
+};
- end:
- return result;
-}
+static struct acpi_battery_reader state_readers[] = {
+ {0x08, SMBUS_READ_WORD, offsetof(struct acpi_battery, temp_now)},
+ {0x09, SMBUS_READ_WORD, offsetof(struct acpi_battery, voltage_now)},
+ {0x0a, SMBUS_READ_WORD, offsetof(struct acpi_battery, current_now)},
+ {0x0b, SMBUS_READ_WORD, offsetof(struct acpi_battery, current_avg)},
+ {0x0f, SMBUS_READ_WORD, offsetof(struct acpi_battery, capacity_now)},
+ {0x0e, SMBUS_READ_WORD, offsetof(struct acpi_battery, state_of_charge)},
+ {0x16, SMBUS_READ_WORD, offsetof(struct acpi_battery, state)},
+};
-static int acpi_sbsm_get_info(struct acpi_sbs *sbs)
+static int acpi_manager_get_info(struct acpi_sbs *sbs)
{
int result = 0;
- s16 battery_system_info;
-
- result = acpi_sbs_read_word(sbs, ACPI_SBSM_SMBUS_ADDR, 0x04,
- &battery_system_info);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_read_word() failed"));
- goto end;
- }
- sbs->sbsm_present = 1;
- sbs->sbsm_batteries_supported = battery_system_info & 0x000f;
-
- end:
+ u16 battery_system_info;
+ result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_MANAGER,
+ 0x04, (u8 *)&battery_system_info);
+ if (!result)
+ sbs->batteries_supported = battery_system_info & 0x000f;
return result;
}
static int acpi_battery_get_info(struct acpi_battery *battery)
{
- struct acpi_sbs *sbs = battery->sbs;
- int result = 0;
- s16 battery_mode;
- s16 specification_info;
-
- result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x03,
- &battery_mode);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_read_word() failed"));
- goto end;
- }
- battery->info.capacity_mode = (battery_mode & 0x8000) >> 15;
-
- result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x10,
- &battery->info.full_charge_capacity);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_read_word() failed"));
- goto end;
- }
-
- result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x18,
- &battery->info.design_capacity);
-
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_read_word() failed"));
- goto end;
- }
-
- result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x19,
- &battery->info.design_voltage);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_read_word() failed"));
- goto end;
+ int i, result = 0;
+
+ for (i = 0; i < ARRAY_SIZE(info_readers); ++i) {
+ result = acpi_smbus_read(battery->sbs->hc,
+ info_readers[i].mode,
+ ACPI_SBS_BATTERY,
+ info_readers[i].command,
+ (u8 *) battery +
+ info_readers[i].offset);
+ if (result)
+ break;
}
-
- result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x1a,
- &specification_info);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_read_word() failed"));
- goto end;
- }
-
- switch ((specification_info & 0x0f00) >> 8) {
- case 1:
- battery->info.vscale = 10;
- break;
- case 2:
- battery->info.vscale = 100;
- break;
- case 3:
- battery->info.vscale = 1000;
- break;
- default:
- battery->info.vscale = 1;
- }
-
- switch ((specification_info & 0xf000) >> 12) {
- case 1:
- battery->info.ipscale = 10;
- break;
- case 2:
- battery->info.ipscale = 100;
- break;
- case 3:
- battery->info.ipscale = 1000;
- break;
- default:
- battery->info.ipscale = 1;
- }
-
- result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x1c,
- &battery->info.serial_number);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_read_word() failed"));
- goto end;
- }
-
- result = acpi_sbs_read_str(sbs, ACPI_SB_SMBUS_ADDR, 0x20,
- battery->info.manufacturer_name);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_read_str() failed"));
- goto end;
- }
-
- result = acpi_sbs_read_str(sbs, ACPI_SB_SMBUS_ADDR, 0x21,
- battery->info.device_name);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_read_str() failed"));
- goto end;
- }
-
- result = acpi_sbs_read_str(sbs, ACPI_SB_SMBUS_ADDR, 0x22,
- battery->info.device_chemistry);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_read_str() failed"));
- goto end;
- }
-
- end:
return result;
}
static int acpi_battery_get_state(struct acpi_battery *battery)
{
- struct acpi_sbs *sbs = battery->sbs;
- int result = 0;
+ int i, result = 0;
- result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x09,
- &battery->state.voltage);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_read_word() failed"));
- goto end;
- }
-
- result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x0a,
- &battery->state.amperage);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_read_word() failed"));
- goto end;
- }
-
- result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x0f,
- &battery->state.remaining_capacity);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_read_word() failed"));
- goto end;
- }
-
- result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x16,
- &battery->state.battery_state);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_read_word() failed"));
- goto end;
+ if (battery->update_time &&
+ time_before(jiffies, battery->update_time +
+ msecs_to_jiffies(cache_time)))
+ return 0;
+ for (i = 0; i < ARRAY_SIZE(state_readers); ++i) {
+ result = acpi_smbus_read(battery->sbs->hc,
+ state_readers[i].mode,
+ ACPI_SBS_BATTERY,
+ state_readers[i].command,
+ (u8 *)battery +
+ state_readers[i].offset);
+ if (result)
+ goto end;
}
-
end:
+ battery->update_time = jiffies;
return result;
}
static int acpi_battery_get_alarm(struct acpi_battery *battery)
{
- struct acpi_sbs *sbs = battery->sbs;
- int result = 0;
-
- result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x01,
- &battery->alarm.remaining_capacity);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_read_word() failed"));
- goto end;
- }
-
- end:
-
- return result;
+ return acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD,
+ ACPI_SBS_BATTERY, 0x01,
+ (u8 *)&battery->alarm_capacity);
}
-static int acpi_battery_set_alarm(struct acpi_battery *battery,
- unsigned long alarm)
+static int acpi_battery_set_alarm(struct acpi_battery *battery)
{
struct acpi_sbs *sbs = battery->sbs;
- int result = 0;
- s16 battery_mode;
- int foo;
+ u16 value, sel = 1 << (battery->id + 12);
- result = acpi_battery_select(battery);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_battery_select() failed"));
- goto end;
- }
+ int ret;
- /* If necessary, enable the alarm */
- if (alarm > 0) {
- result =
- acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x03,
- &battery_mode);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_read_word() failed"));
+ if (sbs->manager_present) {
+ ret = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_MANAGER,
+ 0x01, (u8 *)&value);
+ if (ret)
goto end;
- }
-
- result =
- acpi_sbs_write_word(sbs, ACPI_SB_SMBUS_ADDR, 0x01,
- battery_mode & 0xbfff);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_write_word() failed"));
+ if ((value & 0xf000) != sel) {
+ value &= 0x0fff;
+ value |= sel;
+ ret = acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD,
+ ACPI_SBS_MANAGER,
+ 0x01, (u8 *)&value, 2);
+ if (ret)
goto end;
}
}
-
- foo = alarm / (battery->info.capacity_mode ? 10 : 1);
- result = acpi_sbs_write_word(sbs, ACPI_SB_SMBUS_ADDR, 0x01, foo);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_write_word() failed"));
- goto end;
- }
-
+ ret = acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY,
+ 0x01, (u8 *)&battery->alarm_capacity, 2);
end:
-
- return result;
+ return ret;
}
-static int acpi_battery_set_mode(struct acpi_battery *battery)
+static int acpi_ac_get_present(struct acpi_sbs *sbs)
{
- struct acpi_sbs *sbs = battery->sbs;
- int result = 0;
- s16 battery_mode;
-
- if (capacity_mode == DEF_CAPACITY_UNIT) {
- goto end;
- }
-
- result = acpi_sbs_read_word(sbs,
- ACPI_SB_SMBUS_ADDR, 0x03, &battery_mode);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_read_word() failed"));
- goto end;
- }
-
- if (capacity_mode == MAH_CAPACITY_UNIT) {
- battery_mode &= 0x7fff;
- } else {
- battery_mode |= 0x8000;
- }
- result = acpi_sbs_write_word(sbs,
- ACPI_SB_SMBUS_ADDR, 0x03, battery_mode);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_write_word() failed"));
- goto end;
- }
-
- result = acpi_sbs_read_word(sbs,
- ACPI_SB_SMBUS_ADDR, 0x03, &battery_mode);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_read_word() failed"));
- goto end;
- }
+ int result;
+ u16 status;
- end:
+ result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_CHARGER,
+ 0x13, (u8 *) & status);
+ if (!result)
+ sbs->charger_present = (status >> 15) & 0x1;
return result;
}
-static int acpi_battery_init(struct acpi_battery *battery)
+static ssize_t acpi_battery_alarm_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
- int result = 0;
-
- result = acpi_battery_select(battery);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_battery_select() failed"));
- goto end;
- }
-
- result = acpi_battery_set_mode(battery);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_battery_set_mode() failed"));
- goto end;
- }
-
- result = acpi_battery_get_info(battery);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_battery_get_info() failed"));
- goto end;
- }
-
- result = acpi_battery_get_state(battery);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_battery_get_state() failed"));
- goto end;
- }
-
- result = acpi_battery_get_alarm(battery);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_battery_get_alarm() failed"));
- goto end;
- }
-
- end:
- return result;
+ struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
+ acpi_battery_get_alarm(battery);
+ return sprintf(buf, "%d\n", battery->alarm_capacity *
+ acpi_battery_scale(battery) * 1000);
}
-static int acpi_ac_get_present(struct acpi_sbs *sbs)
+static ssize_t acpi_battery_alarm_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
- int result = 0;
- s16 charger_status;
-
- result = acpi_sbs_read_word(sbs, ACPI_SBC_SMBUS_ADDR, 0x13,
- &charger_status);
-
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_read_word() failed"));
- goto end;
- }
-
- sbs->ac.ac_present = (charger_status & 0x8000) >> 15;
-
- end:
-
- return result;
+ unsigned long x;
+ struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
+ if (sscanf(buf, "%ld\n", &x) == 1)
+ battery->alarm_capacity = x /
+ (1000 * acpi_battery_scale(battery));
+ if (battery->present)
+ acpi_battery_set_alarm(battery);
+ return count;
}
+static struct device_attribute alarm_attr = {
+ .attr = {.name = "alarm", .mode = 0644, .owner = THIS_MODULE},
+ .show = acpi_battery_alarm_show,
+ .store = acpi_battery_alarm_store,
+};
+
/* --------------------------------------------------------------------------
FS Interface (/proc/acpi)
-------------------------------------------------------------------------- */
+#ifdef CONFIG_ACPI_PROCFS
/* Generic Routines */
-
static int
-acpi_sbs_generic_add_fs(struct proc_dir_entry **dir,
- struct proc_dir_entry *parent_dir,
- char *dir_name,
- struct file_operations *info_fops,
- struct file_operations *state_fops,
- struct file_operations *alarm_fops, void *data)
+acpi_sbs_add_fs(struct proc_dir_entry **dir,
+ struct proc_dir_entry *parent_dir,
+ char *dir_name,
+ struct file_operations *info_fops,
+ struct file_operations *state_fops,
+ struct file_operations *alarm_fops, void *data)
{
struct proc_dir_entry *entry = NULL;
if (!*dir) {
*dir = proc_mkdir(dir_name, parent_dir);
if (!*dir) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "proc_mkdir() failed"));
return -ENODEV;
}
(*dir)->owner = THIS_MODULE;
@@ -882,10 +491,7 @@ acpi_sbs_generic_add_fs(struct proc_dir_entry **dir,
/* 'info' [R] */
if (info_fops) {
entry = create_proc_entry(ACPI_SBS_FILE_INFO, S_IRUGO, *dir);
- if (!entry) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "create_proc_entry() failed"));
- } else {
+ if (entry) {
entry->proc_fops = info_fops;
entry->data = data;
entry->owner = THIS_MODULE;
@@ -895,10 +501,7 @@ acpi_sbs_generic_add_fs(struct proc_dir_entry **dir,
/* 'state' [R] */
if (state_fops) {
entry = create_proc_entry(ACPI_SBS_FILE_STATE, S_IRUGO, *dir);
- if (!entry) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "create_proc_entry() failed"));
- } else {
+ if (entry) {
entry->proc_fops = state_fops;
entry->data = data;
entry->owner = THIS_MODULE;
@@ -908,24 +511,19 @@ acpi_sbs_generic_add_fs(struct proc_dir_entry **dir,
/* 'alarm' [R/W] */
if (alarm_fops) {
entry = create_proc_entry(ACPI_SBS_FILE_ALARM, S_IRUGO, *dir);
- if (!entry) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "create_proc_entry() failed"));
- } else {
+ if (entry) {
entry->proc_fops = alarm_fops;
entry->data = data;
entry->owner = THIS_MODULE;
}
}
-
return 0;
}
static void
-acpi_sbs_generic_remove_fs(struct proc_dir_entry **dir,
+acpi_sbs_remove_fs(struct proc_dir_entry **dir,
struct proc_dir_entry *parent_dir)
{
-
if (*dir) {
remove_proc_entry(ACPI_SBS_FILE_INFO, *dir);
remove_proc_entry(ACPI_SBS_FILE_STATE, *dir);
@@ -933,82 +531,52 @@ acpi_sbs_generic_remove_fs(struct proc_dir_entry **dir,
remove_proc_entry((*dir)->name, parent_dir);
*dir = NULL;
}
-
}
/* Smart Battery Interface */
-
static struct proc_dir_entry *acpi_battery_dir = NULL;
+static inline char *acpi_battery_units(struct acpi_battery *battery)
+{
+ return acpi_battery_mode(battery) ? " mWh" : " mAh";
+}
+
+
static int acpi_battery_read_info(struct seq_file *seq, void *offset)
{
struct acpi_battery *battery = seq->private;
struct acpi_sbs *sbs = battery->sbs;
- int cscale;
int result = 0;
- if (sbs_mutex_lock(sbs)) {
- return -ENODEV;
- }
-
- result = acpi_check_update_proc(sbs);
- if (result)
- goto end;
-
- if (update_time == 0) {
- result = acpi_sbs_update_run(sbs, battery->id, DATA_TYPE_INFO);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_update_run() failed"));
- }
- }
+ mutex_lock(&sbs->lock);
- if (battery->battery_present) {
- seq_printf(seq, "present: yes\n");
- } else {
- seq_printf(seq, "present: no\n");
+ seq_printf(seq, "present: %s\n",
+ (battery->present) ? "yes" : "no");
+ if (!battery->present)
goto end;
- }
- if (battery->info.capacity_mode) {
- cscale = battery->info.vscale * battery->info.ipscale;
- } else {
- cscale = battery->info.ipscale;
- }
seq_printf(seq, "design capacity: %i%s\n",
- battery->info.design_capacity * cscale,
- battery->info.capacity_mode ? "0 mWh" : " mAh");
-
+ battery->design_capacity * acpi_battery_scale(battery),
+ acpi_battery_units(battery));
seq_printf(seq, "last full capacity: %i%s\n",
- battery->info.full_charge_capacity * cscale,
- battery->info.capacity_mode ? "0 mWh" : " mAh");
-
+ battery->full_charge_capacity * acpi_battery_scale(battery),
+ acpi_battery_units(battery));
seq_printf(seq, "battery technology: rechargeable\n");
-
seq_printf(seq, "design voltage: %i mV\n",
- battery->info.design_voltage * battery->info.vscale);
-
+ battery->design_voltage * acpi_battery_vscale(battery));
seq_printf(seq, "design capacity warning: unknown\n");
seq_printf(seq, "design capacity low: unknown\n");
seq_printf(seq, "capacity granularity 1: unknown\n");
seq_printf(seq, "capacity granularity 2: unknown\n");
-
- seq_printf(seq, "model number: %s\n",
- battery->info.device_name);
-
+ seq_printf(seq, "model number: %s\n", battery->device_name);
seq_printf(seq, "serial number: %i\n",
- battery->info.serial_number);
-
+ battery->serial_number);
seq_printf(seq, "battery type: %s\n",
- battery->info.device_chemistry);
-
+ battery->device_chemistry);
seq_printf(seq, "OEM info: %s\n",
- battery->info.manufacturer_name);
-
+ battery->manufacturer_name);
end:
-
- sbs_mutex_unlock(sbs);
-
+ mutex_unlock(&sbs->lock);
return result;
}
@@ -1022,73 +590,29 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset)
struct acpi_battery *battery = seq->private;
struct acpi_sbs *sbs = battery->sbs;
int result = 0;
- int cscale;
- int foo;
-
- if (sbs_mutex_lock(sbs)) {
- return -ENODEV;
- }
- result = acpi_check_update_proc(sbs);
- if (result)
+ mutex_lock(&sbs->lock);
+ seq_printf(seq, "present: %s\n",
+ (battery->present) ? "yes" : "no");
+ if (!battery->present)
goto end;
- if (update_time == 0) {
- result = acpi_sbs_update_run(sbs, battery->id, DATA_TYPE_STATE);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_update_run() failed"));
- }
- }
-
- if (battery->battery_present) {
- seq_printf(seq, "present: yes\n");
- } else {
- seq_printf(seq, "present: no\n");
- goto end;
- }
-
- if (battery->info.capacity_mode) {
- cscale = battery->info.vscale * battery->info.ipscale;
- } else {
- cscale = battery->info.ipscale;
- }
-
- if (battery->state.battery_state & 0x0010) {
- seq_printf(seq, "capacity state: critical\n");
- } else {
- seq_printf(seq, "capacity state: ok\n");
- }
-
- foo = (s16) battery->state.amperage * battery->info.ipscale;
- if (battery->info.capacity_mode) {
- foo = foo * battery->info.design_voltage / 1000;
- }
- if (battery->state.amperage < 0) {
- seq_printf(seq, "charging state: discharging\n");
- seq_printf(seq, "present rate: %d %s\n",
- -foo, battery->info.capacity_mode ? "mW" : "mA");
- } else if (battery->state.amperage > 0) {
- seq_printf(seq, "charging state: charging\n");
- seq_printf(seq, "present rate: %d %s\n",
- foo, battery->info.capacity_mode ? "mW" : "mA");
- } else {
- seq_printf(seq, "charging state: charged\n");
- seq_printf(seq, "present rate: 0 %s\n",
- battery->info.capacity_mode ? "mW" : "mA");
- }
-
+ acpi_battery_get_state(battery);
+ seq_printf(seq, "capacity state: %s\n",
+ (battery->state & 0x0010) ? "critical" : "ok");
+ seq_printf(seq, "charging state: %s\n",
+ (battery->current_now < 0) ? "discharging" :
+ ((battery->current_now > 0) ? "charging" : "charged"));
+ seq_printf(seq, "present rate: %d mA\n",
+ abs(battery->current_now) * acpi_battery_ipscale(battery));
seq_printf(seq, "remaining capacity: %i%s\n",
- battery->state.remaining_capacity * cscale,
- battery->info.capacity_mode ? "0 mWh" : " mAh");
-
+ battery->capacity_now * acpi_battery_scale(battery),
+ acpi_battery_units(battery));
seq_printf(seq, "present voltage: %i mV\n",
- battery->state.voltage * battery->info.vscale);
+ battery->voltage_now * acpi_battery_vscale(battery));
end:
-
- sbs_mutex_unlock(sbs);
-
+ mutex_unlock(&sbs->lock);
return result;
}
@@ -1102,48 +626,25 @@ static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
struct acpi_battery *battery = seq->private;
struct acpi_sbs *sbs = battery->sbs;
int result = 0;
- int cscale;
-
- if (sbs_mutex_lock(sbs)) {
- return -ENODEV;
- }
-
- result = acpi_check_update_proc(sbs);
- if (result)
- goto end;
- if (update_time == 0) {
- result = acpi_sbs_update_run(sbs, battery->id, DATA_TYPE_ALARM);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_update_run() failed"));
- }
- }
+ mutex_lock(&sbs->lock);
- if (!battery->battery_present) {
+ if (!battery->present) {
seq_printf(seq, "present: no\n");
goto end;
}
- if (battery->info.capacity_mode) {
- cscale = battery->info.vscale * battery->info.ipscale;
- } else {
- cscale = battery->info.ipscale;
- }
-
+ acpi_battery_get_alarm(battery);
seq_printf(seq, "alarm: ");
- if (battery->alarm.remaining_capacity) {
+ if (battery->alarm_capacity)
seq_printf(seq, "%i%s\n",
- battery->alarm.remaining_capacity * cscale,
- battery->info.capacity_mode ? "0 mWh" : " mAh");
- } else {
+ battery->alarm_capacity *
+ acpi_battery_scale(battery),
+ acpi_battery_units(battery));
+ else
seq_printf(seq, "disabled\n");
- }
-
end:
-
- sbs_mutex_unlock(sbs);
-
+ mutex_unlock(&sbs->lock);
return result;
}
@@ -1155,59 +656,29 @@ acpi_battery_write_alarm(struct file *file, const char __user * buffer,
struct acpi_battery *battery = seq->private;
struct acpi_sbs *sbs = battery->sbs;
char alarm_string[12] = { '\0' };
- int result, old_alarm, new_alarm;
-
- if (sbs_mutex_lock(sbs)) {
- return -ENODEV;
- }
-
- result = acpi_check_update_proc(sbs);
- if (result)
- goto end;
-
- if (!battery->battery_present) {
+ int result = 0;
+ mutex_lock(&sbs->lock);
+ if (!battery->present) {
result = -ENODEV;
goto end;
}
-
if (count > sizeof(alarm_string) - 1) {
result = -EINVAL;
goto end;
}
-
if (copy_from_user(alarm_string, buffer, count)) {
result = -EFAULT;
goto end;
}
-
alarm_string[count] = 0;
-
- old_alarm = battery->alarm.remaining_capacity;
- new_alarm = simple_strtoul(alarm_string, NULL, 0);
-
- result = acpi_battery_set_alarm(battery, new_alarm);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_battery_set_alarm() failed"));
- acpi_battery_set_alarm(battery, old_alarm);
- goto end;
- }
- result = acpi_battery_get_alarm(battery);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_battery_get_alarm() failed"));
- acpi_battery_set_alarm(battery, old_alarm);
- goto end;
- }
-
+ battery->alarm_capacity = simple_strtoul(alarm_string, NULL, 0) /
+ acpi_battery_scale(battery);
+ acpi_battery_set_alarm(battery);
end:
- sbs_mutex_unlock(sbs);
-
- if (result) {
+ mutex_unlock(&sbs->lock);
+ if (result)
return result;
- } else {
- return count;
- }
+ return count;
}
static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file)
@@ -1246,26 +717,15 @@ static struct proc_dir_entry *acpi_ac_dir = NULL;
static int acpi_ac_read_state(struct seq_file *seq, void *offset)
{
- struct acpi_sbs *sbs = seq->private;
- int result;
- if (sbs_mutex_lock(sbs)) {
- return -ENODEV;
- }
+ struct acpi_sbs *sbs = seq->private;
- if (update_time == 0) {
- result = acpi_sbs_update_run(sbs, -1, DATA_TYPE_AC_STATE);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_update_run() failed"));
- }
- }
+ mutex_lock(&sbs->lock);
seq_printf(seq, "state: %s\n",
- sbs->ac.ac_present ? "on-line" : "off-line");
-
- sbs_mutex_unlock(sbs);
+ sbs->charger_present ? "on-line" : "off-line");
+ mutex_unlock(&sbs->lock);
return 0;
}
@@ -1282,429 +742,203 @@ static struct file_operations acpi_ac_state_fops = {
.owner = THIS_MODULE,
};
+#endif
+
/* --------------------------------------------------------------------------
Driver Interface
-------------------------------------------------------------------------- */
+static int acpi_battery_read(struct acpi_battery *battery)
+{
+ int result = 0, saved_present = battery->present;
+ u16 state;
+
+ if (battery->sbs->manager_present) {
+ result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD,
+ ACPI_SBS_MANAGER, 0x01, (u8 *)&state);
+ if (!result)
+ battery->present = state & (1 << battery->id);
+ state &= 0x0fff;
+ state |= 1 << (battery->id + 12);
+ acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD,
+ ACPI_SBS_MANAGER, 0x01, (u8 *)&state, 2);
+ } else if (battery->id == 0)
+ battery->present = 1;
+ if (result || !battery->present)
+ return result;
-/* Smart Battery */
+ if (saved_present != battery->present) {
+ battery->update_time = 0;
+ result = acpi_battery_get_info(battery);
+ if (result)
+ return result;
+ }
+ result = acpi_battery_get_state(battery);
+ return result;
+}
+/* Smart Battery */
static int acpi_battery_add(struct acpi_sbs *sbs, int id)
{
- int is_present;
+ struct acpi_battery *battery = &sbs->battery[id];
int result;
- char dir_name[32];
- struct acpi_battery *battery;
-
- battery = &sbs->battery[id];
-
- battery->alive = 0;
- battery->init_state = 0;
battery->id = id;
battery->sbs = sbs;
+ result = acpi_battery_read(battery);
+ if (result)
+ return result;
- result = acpi_battery_select(battery);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_battery_select() failed"));
- goto end;
- }
-
- result = acpi_battery_get_present(battery);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_battery_get_present() failed"));
- goto end;
- }
-
- is_present = battery->battery_present;
-
- if (is_present) {
- result = acpi_battery_init(battery);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_battery_init() failed"));
- goto end;
- }
- battery->init_state = 1;
- }
-
- sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id);
-
- result = acpi_sbs_generic_add_fs(&battery->battery_entry,
- acpi_battery_dir,
- dir_name,
- &acpi_battery_info_fops,
- &acpi_battery_state_fops,
- &acpi_battery_alarm_fops, battery);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_generic_add_fs() failed"));
- goto end;
+ sprintf(battery->name, ACPI_BATTERY_DIR_NAME, id);
+#ifdef CONFIG_ACPI_PROCFS
+ acpi_sbs_add_fs(&battery->proc_entry, acpi_battery_dir,
+ battery->name, &acpi_battery_info_fops,
+ &acpi_battery_state_fops, &acpi_battery_alarm_fops,
+ battery);
+#endif
+ battery->bat.name = battery->name;
+ battery->bat.type = POWER_SUPPLY_TYPE_BATTERY;
+ if (!acpi_battery_mode(battery)) {
+ battery->bat.properties = sbs_charge_battery_props;
+ battery->bat.num_properties =
+ ARRAY_SIZE(sbs_charge_battery_props);
+ } else {
+ battery->bat.properties = sbs_energy_battery_props;
+ battery->bat.num_properties =
+ ARRAY_SIZE(sbs_energy_battery_props);
}
- battery->alive = 1;
-
+ battery->bat.get_property = acpi_sbs_battery_get_property;
+ result = power_supply_register(&sbs->device->dev, &battery->bat);
+ device_create_file(battery->bat.dev, &alarm_attr);
printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n",
- ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), dir_name,
- sbs->battery->battery_present ? "present" : "absent");
-
- end:
+ ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
+ battery->name, sbs->battery->present ? "present" : "absent");
return result;
}
static void acpi_battery_remove(struct acpi_sbs *sbs, int id)
{
-
- if (sbs->battery[id].battery_entry) {
- acpi_sbs_generic_remove_fs(&(sbs->battery[id].battery_entry),
- acpi_battery_dir);
- }
+ if (sbs->battery[id].bat.dev)
+ device_remove_file(sbs->battery[id].bat.dev, &alarm_attr);
+ power_supply_unregister(&sbs->battery[id].bat);
+#ifdef CONFIG_ACPI_PROCFS
+ if (sbs->battery[id].proc_entry) {
+ acpi_sbs_remove_fs(&(sbs->battery[id].proc_entry),
+ acpi_battery_dir);
+ }
+#endif
}
-static int acpi_ac_add(struct acpi_sbs *sbs)
+static int acpi_charger_add(struct acpi_sbs *sbs)
{
int result;
result = acpi_ac_get_present(sbs);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_ac_get_present() failed"));
+ if (result)
goto end;
- }
-
- result = acpi_sbs_generic_add_fs(&sbs->ac_entry,
- acpi_ac_dir,
- ACPI_AC_DIR_NAME,
- NULL, &acpi_ac_state_fops, NULL, sbs);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_generic_add_fs() failed"));
+#ifdef CONFIG_ACPI_PROCFS
+ result = acpi_sbs_add_fs(&sbs->charger_entry, acpi_ac_dir,
+ ACPI_AC_DIR_NAME, NULL,
+ &acpi_ac_state_fops, NULL, sbs);
+ if (result)
goto end;
- }
-
+#endif
+ sbs->charger.name = "sbs-charger";
+ sbs->charger.type = POWER_SUPPLY_TYPE_MAINS;
+ sbs->charger.properties = sbs_ac_props;
+ sbs->charger.num_properties = ARRAY_SIZE(sbs_ac_props);
+ sbs->charger.get_property = sbs_get_ac_property;
+ power_supply_register(&sbs->device->dev, &sbs->charger);
printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)\n",
ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
- ACPI_AC_DIR_NAME, sbs->ac.ac_present ? "on-line" : "off-line");
-
+ ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line");
end:
-
return result;
}
-static void acpi_ac_remove(struct acpi_sbs *sbs)
+static void acpi_charger_remove(struct acpi_sbs *sbs)
{
-
- if (sbs->ac_entry) {
- acpi_sbs_generic_remove_fs(&sbs->ac_entry, acpi_ac_dir);
- }
+ if (sbs->charger.dev)
+ power_supply_unregister(&sbs->charger);
+#ifdef CONFIG_ACPI_PROCFS
+ if (sbs->charger_entry)
+ acpi_sbs_remove_fs(&sbs->charger_entry, acpi_ac_dir);
+#endif
}
-static void acpi_sbs_update_time_run(unsigned long data)
+void acpi_sbs_callback(void *context)
{
- acpi_os_execute(OSL_GPE_HANDLER, acpi_sbs_update_time, (void *)data);
-}
-
-static int acpi_sbs_update_run(struct acpi_sbs *sbs, int id, int data_type)
-{
- struct acpi_battery *battery;
- int result = 0, cnt;
- int old_ac_present = -1;
- int old_battery_present = -1;
- int new_ac_present = -1;
- int new_battery_present = -1;
- int id_min = 0, id_max = MAX_SBS_BAT - 1;
- char dir_name[32];
- int do_battery_init = 0, do_ac_init = 0;
- int old_remaining_capacity = 0;
- int update_battery = 1;
- int up_tm = update_time;
-
- if (sbs_zombie(sbs)) {
- goto end;
- }
-
- if (id >= 0) {
- id_min = id_max = id;
- }
-
- if (data_type == DATA_TYPE_COMMON && up_tm > 0) {
- cnt = up_tm / (up_tm > UPDATE_DELAY ? UPDATE_DELAY : up_tm);
- if (sbs->run_cnt % cnt != 0) {
- update_battery = 0;
- }
- }
-
- sbs->run_cnt++;
-
- old_ac_present = sbs->ac.ac_present;
-
- result = acpi_ac_get_present(sbs);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_ac_get_present() failed"));
- }
-
- new_ac_present = sbs->ac.ac_present;
-
- do_ac_init = (old_ac_present != new_ac_present);
- if (sbs->run_cnt == 1 && data_type == DATA_TYPE_COMMON) {
- do_ac_init = 1;
- }
-
- if (do_ac_init) {
- result = acpi_sbs_generate_event(sbs->device,
- ACPI_SBS_AC_NOTIFY_STATUS,
- new_ac_present,
- ACPI_AC_DIR_NAME,
- ACPI_AC_CLASS);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_generate_event() failed"));
- }
- }
-
- if (data_type == DATA_TYPE_COMMON) {
- if (!do_ac_init && !update_battery) {
- goto end;
- }
- }
-
- if (data_type == DATA_TYPE_AC_STATE && !do_ac_init) {
- goto end;
- }
-
- for (id = id_min; id <= id_max; id++) {
- battery = &sbs->battery[id];
- if (battery->alive == 0) {
- continue;
- }
-
- old_remaining_capacity = battery->state.remaining_capacity;
-
- old_battery_present = battery->battery_present;
-
- result = acpi_battery_select(battery);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_battery_select() failed"));
- }
-
- result = acpi_battery_get_present(battery);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_battery_get_present() failed"));
- }
-
- new_battery_present = battery->battery_present;
-
- do_battery_init = ((old_battery_present != new_battery_present)
- && new_battery_present);
- if (!new_battery_present)
- goto event;
- if (do_ac_init || do_battery_init) {
- result = acpi_battery_init(battery);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_battery_init() "
- "failed"));
- }
- }
- if (sbs_zombie(sbs)) {
- goto end;
- }
-
- if ((data_type == DATA_TYPE_COMMON
- || data_type == DATA_TYPE_INFO)
- && new_battery_present) {
- result = acpi_battery_get_info(battery);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_battery_get_info() failed"));
- }
- }
- if (data_type == DATA_TYPE_INFO) {
- continue;
- }
- if (sbs_zombie(sbs)) {
- goto end;
- }
-
- if ((data_type == DATA_TYPE_COMMON
- || data_type == DATA_TYPE_STATE)
- && new_battery_present) {
- result = acpi_battery_get_state(battery);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_battery_get_state() failed"));
- }
- }
- if (data_type == DATA_TYPE_STATE) {
- goto event;
- }
- if (sbs_zombie(sbs)) {
- goto end;
- }
-
- if ((data_type == DATA_TYPE_COMMON
- || data_type == DATA_TYPE_ALARM)
- && new_battery_present) {
- result = acpi_battery_get_alarm(battery);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_battery_get_alarm() "
- "failed"));
- }
- }
- if (data_type == DATA_TYPE_ALARM) {
- continue;
- }
- if (sbs_zombie(sbs)) {
- goto end;
- }
-
- event:
-
- if (old_battery_present != new_battery_present || do_ac_init ||
- old_remaining_capacity !=
- battery->state.remaining_capacity) {
- sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id);
- result = acpi_sbs_generate_event(sbs->device,
- ACPI_SBS_BATTERY_NOTIFY_STATUS,
- new_battery_present,
- dir_name,
- ACPI_BATTERY_CLASS);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_generate_event() "
- "failed"));
- }
+ int id;
+ struct acpi_sbs *sbs = context;
+ struct acpi_battery *bat;
+ u8 saved_charger_state = sbs->charger_present;
+ u8 saved_battery_state;
+ acpi_ac_get_present(sbs);
+ if (sbs->charger_present != saved_charger_state) {
+#ifdef CONFIG_ACPI_PROC_EVENT
+ acpi_bus_generate_proc_event4(ACPI_AC_CLASS, ACPI_AC_DIR_NAME,
+ ACPI_SBS_NOTIFY_STATUS,
+ sbs->charger_present);
+#endif
+ kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE);
+ }
+ if (sbs->manager_present) {
+ for (id = 0; id < MAX_SBS_BAT; ++id) {
+ if (!(sbs->batteries_supported & (1 << id)))
+ continue;
+ bat = &sbs->battery[id];
+ saved_battery_state = bat->present;
+ acpi_battery_read(bat);
+ if (saved_battery_state == bat->present)
+ continue;
+#ifdef CONFIG_ACPI_PROC_EVENT
+ acpi_bus_generate_proc_event4(ACPI_BATTERY_CLASS,
+ bat->name,
+ ACPI_SBS_NOTIFY_STATUS,
+ bat->present);
+#endif
+ kobject_uevent(&bat->bat.dev->kobj, KOBJ_CHANGE);
}
}
-
- end:
-
- return result;
}
-static void acpi_sbs_update_time(void *data)
-{
- struct acpi_sbs *sbs = data;
- unsigned long delay = -1;
- int result;
- unsigned int up_tm = update_time;
-
- if (sbs_mutex_lock(sbs))
- return;
-
- result = acpi_sbs_update_run(sbs, -1, DATA_TYPE_COMMON);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_update_run() failed"));
- }
-
- if (sbs_zombie(sbs)) {
- goto end;
- }
-
- if (!up_tm) {
- if (timer_pending(&sbs->update_timer))
- del_timer(&sbs->update_timer);
- } else {
- delay = (up_tm > UPDATE_DELAY ? UPDATE_DELAY : up_tm);
- delay = jiffies + HZ * delay;
- if (timer_pending(&sbs->update_timer)) {
- mod_timer(&sbs->update_timer, delay);
- } else {
- sbs->update_timer.data = (unsigned long)data;
- sbs->update_timer.function = acpi_sbs_update_time_run;
- sbs->update_timer.expires = delay;
- add_timer(&sbs->update_timer);
- }
- }
-
- end:
-
- sbs_mutex_unlock(sbs);
-}
+static int acpi_sbs_remove(struct acpi_device *device, int type);
static int acpi_sbs_add(struct acpi_device *device)
{
- struct acpi_sbs *sbs = NULL;
- int result = 0, remove_result = 0;
+ struct acpi_sbs *sbs;
+ int result = 0;
int id;
- acpi_status status = AE_OK;
- unsigned long val;
-
- status =
- acpi_evaluate_integer(device->handle, "_EC", NULL, &val);
- if (ACPI_FAILURE(status)) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Error obtaining _EC"));
- return -EIO;
- }
sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL);
if (!sbs) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR, "kzalloc() failed"));
result = -ENOMEM;
goto end;
}
- mutex_init(&sbs->mutex);
-
- sbs_mutex_lock(sbs);
+ mutex_init(&sbs->lock);
- sbs->base = 0xff & (val >> 8);
+ sbs->hc = acpi_driver_data(device->parent);
sbs->device = device;
-
strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_SBS_CLASS);
acpi_driver_data(device) = sbs;
- result = acpi_ac_add(sbs);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_ac_add() failed"));
- goto end;
- }
-
- acpi_sbsm_get_info(sbs);
-
- if (!sbs->sbsm_present) {
- result = acpi_battery_add(sbs, 0);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_battery_add() failed"));
- goto end;
- }
- } else {
- for (id = 0; id < MAX_SBS_BAT; id++) {
- if ((sbs->sbsm_batteries_supported & (1 << id))) {
- result = acpi_battery_add(sbs, id);
- if (result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_battery_add() failed"));
- goto end;
- }
- }
- }
- }
-
- init_timer(&sbs->update_timer);
- result = acpi_check_update_proc(sbs);
+ result = acpi_charger_add(sbs);
if (result)
goto end;
+ result = acpi_manager_get_info(sbs);
+ if (!result) {
+ sbs->manager_present = 1;
+ for (id = 0; id < MAX_SBS_BAT; ++id)
+ if ((sbs->batteries_supported & (1 << id)))
+ acpi_battery_add(sbs, id);
+ } else
+ acpi_battery_add(sbs, 0);
+ acpi_smbus_register_callback(sbs->hc, acpi_sbs_callback, sbs);
end:
-
- sbs_mutex_unlock(sbs);
-
- if (result) {
- remove_result = acpi_sbs_remove(device, 0);
- if (remove_result) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_sbs_remove() failed"));
- }
- }
-
+ if (result)
+ acpi_sbs_remove(device, 0);
return result;
}
@@ -1713,39 +947,25 @@ static int acpi_sbs_remove(struct acpi_device *device, int type)
struct acpi_sbs *sbs;
int id;
- if (!device) {
+ if (!device)
return -EINVAL;
- }
-
sbs = acpi_driver_data(device);
- if (!sbs) {
+ if (!sbs)
return -EINVAL;
- }
-
- sbs_mutex_lock(sbs);
-
- sbs->zombie = 1;
- del_timer_sync(&sbs->update_timer);
- acpi_os_wait_events_complete(NULL);
- del_timer_sync(&sbs->update_timer);
-
- for (id = 0; id < MAX_SBS_BAT; id++) {
+ mutex_lock(&sbs->lock);
+ acpi_smbus_unregister_callback(sbs->hc);
+ for (id = 0; id < MAX_SBS_BAT; ++id)
acpi_battery_remove(sbs, id);
- }
-
- acpi_ac_remove(sbs);
-
- sbs_mutex_unlock(sbs);
-
- mutex_destroy(&sbs->mutex);
-
+ acpi_charger_remove(sbs);
+ mutex_unlock(&sbs->lock);
+ mutex_destroy(&sbs->lock);
kfree(sbs);
-
return 0;
}
static void acpi_sbs_rmdirs(void)
{
+#ifdef CONFIG_ACPI_PROCFS
if (acpi_ac_dir) {
acpi_unlock_ac_dir(acpi_ac_dir);
acpi_ac_dir = NULL;
@@ -1754,69 +974,58 @@ static void acpi_sbs_rmdirs(void)
acpi_unlock_battery_dir(acpi_battery_dir);
acpi_battery_dir = NULL;
}
+#endif
}
static int acpi_sbs_resume(struct acpi_device *device)
{
struct acpi_sbs *sbs;
-
if (!device)
return -EINVAL;
-
sbs = device->driver_data;
-
- sbs->run_cnt = 0;
-
+ acpi_sbs_callback(sbs);
return 0;
}
+static struct acpi_driver acpi_sbs_driver = {
+ .name = "sbs",
+ .class = ACPI_SBS_CLASS,
+ .ids = sbs_device_ids,
+ .ops = {
+ .add = acpi_sbs_add,
+ .remove = acpi_sbs_remove,
+ .resume = acpi_sbs_resume,
+ },
+};
+
static int __init acpi_sbs_init(void)
{
int result = 0;
if (acpi_disabled)
return -ENODEV;
-
- if (capacity_mode != DEF_CAPACITY_UNIT
- && capacity_mode != MAH_CAPACITY_UNIT
- && capacity_mode != MWH_CAPACITY_UNIT) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "invalid capacity_mode = %d", capacity_mode));
- return -EINVAL;
- }
-
+#ifdef CONFIG_ACPI_PROCFS
acpi_ac_dir = acpi_lock_ac_dir();
- if (!acpi_ac_dir) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_lock_ac_dir() failed"));
+ if (!acpi_ac_dir)
return -ENODEV;
- }
-
acpi_battery_dir = acpi_lock_battery_dir();
if (!acpi_battery_dir) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_lock_battery_dir() failed"));
acpi_sbs_rmdirs();
return -ENODEV;
}
-
+#endif
result = acpi_bus_register_driver(&acpi_sbs_driver);
if (result < 0) {
- ACPI_EXCEPTION((AE_INFO, AE_ERROR,
- "acpi_bus_register_driver() failed"));
acpi_sbs_rmdirs();
return -ENODEV;
}
-
return 0;
}
static void __exit acpi_sbs_exit(void)
{
acpi_bus_unregister_driver(&acpi_sbs_driver);
-
acpi_sbs_rmdirs();
-
return;
}
diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c
new file mode 100644
index 000000000000..046d7c3ed356
--- /dev/null
+++ b/drivers/acpi/sbshc.c
@@ -0,0 +1,309 @@
+/*
+ * SMBus driver for ACPI Embedded Controller (v0.1)
+ *
+ * Copyright (c) 2007 Alexey Starikovskiy
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2.
+ */
+
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+#include <acpi/actypes.h>
+#include <linux/wait.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include "sbshc.h"
+
+#define ACPI_SMB_HC_CLASS "smbus_host_controller"
+#define ACPI_SMB_HC_DEVICE_NAME "ACPI SMBus HC"
+
+struct acpi_smb_hc {
+ struct acpi_ec *ec;
+ struct mutex lock;
+ wait_queue_head_t wait;
+ u8 offset;
+ u8 query_bit;
+ smbus_alarm_callback callback;
+ void *context;
+};
+
+static int acpi_smbus_hc_add(struct acpi_device *device);
+static int acpi_smbus_hc_remove(struct acpi_device *device, int type);
+
+static const struct acpi_device_id sbs_device_ids[] = {
+ {"ACPI0001", 0},
+ {"ACPI0005", 0},
+ {"", 0},
+};
+
+MODULE_DEVICE_TABLE(acpi, sbs_device_ids);
+
+static struct acpi_driver acpi_smb_hc_driver = {
+ .name = "smbus_hc",
+ .class = ACPI_SMB_HC_CLASS,
+ .ids = sbs_device_ids,
+ .ops = {
+ .add = acpi_smbus_hc_add,
+ .remove = acpi_smbus_hc_remove,
+ },
+};
+
+union acpi_smb_status {
+ u8 raw;
+ struct {
+ u8 status:5;
+ u8 reserved:1;
+ u8 alarm:1;
+ u8 done:1;
+ } fields;
+};
+
+enum acpi_smb_status_codes {
+ SMBUS_OK = 0,
+ SMBUS_UNKNOWN_FAILURE = 0x07,
+ SMBUS_DEVICE_ADDRESS_NACK = 0x10,
+ SMBUS_DEVICE_ERROR = 0x11,
+ SMBUS_DEVICE_COMMAND_ACCESS_DENIED = 0x12,
+ SMBUS_UNKNOWN_ERROR = 0x13,
+ SMBUS_DEVICE_ACCESS_DENIED = 0x17,
+ SMBUS_TIMEOUT = 0x18,
+ SMBUS_HOST_UNSUPPORTED_PROTOCOL = 0x19,
+ SMBUS_BUSY = 0x1a,
+ SMBUS_PEC_ERROR = 0x1f,
+};
+
+enum acpi_smb_offset {
+ ACPI_SMB_PROTOCOL = 0, /* protocol, PEC */
+ ACPI_SMB_STATUS = 1, /* status */
+ ACPI_SMB_ADDRESS = 2, /* address */
+ ACPI_SMB_COMMAND = 3, /* command */
+ ACPI_SMB_DATA = 4, /* 32 data registers */
+ ACPI_SMB_BLOCK_COUNT = 0x24, /* number of data bytes */
+ ACPI_SMB_ALARM_ADDRESS = 0x25, /* alarm address */
+ ACPI_SMB_ALARM_DATA = 0x26, /* 2 bytes alarm data */
+};
+
+static inline int smb_hc_read(struct acpi_smb_hc *hc, u8 address, u8 *data)
+{
+ return ec_read(hc->offset + address, data);
+}
+
+static inline int smb_hc_write(struct acpi_smb_hc *hc, u8 address, u8 data)
+{
+ return ec_write(hc->offset + address, data);
+}
+
+static inline int smb_check_done(struct acpi_smb_hc *hc)
+{
+ union acpi_smb_status status = {.raw = 0};
+ smb_hc_read(hc, ACPI_SMB_STATUS, &status.raw);
+ return status.fields.done && (status.fields.status == SMBUS_OK);
+}
+
+static int wait_transaction_complete(struct acpi_smb_hc *hc, int timeout)
+{
+ if (wait_event_timeout(hc->wait, smb_check_done(hc),
+ msecs_to_jiffies(timeout)))
+ return 0;
+ else
+ return -ETIME;
+}
+
+int acpi_smbus_transaction(struct acpi_smb_hc *hc, u8 protocol, u8 address,
+ u8 command, u8 *data, u8 length)
+{
+ int ret = -EFAULT, i;
+ u8 temp, sz = 0;
+
+ mutex_lock(&hc->lock);
+ if (smb_hc_read(hc, ACPI_SMB_PROTOCOL, &temp))
+ goto end;
+ if (temp) {
+ ret = -EBUSY;
+ goto end;
+ }
+ smb_hc_write(hc, ACPI_SMB_COMMAND, command);
+ smb_hc_write(hc, ACPI_SMB_COMMAND, command);
+ if (!(protocol & 0x01)) {
+ smb_hc_write(hc, ACPI_SMB_BLOCK_COUNT, length);
+ for (i = 0; i < length; ++i)
+ smb_hc_write(hc, ACPI_SMB_DATA + i, data[i]);
+ }
+ smb_hc_write(hc, ACPI_SMB_ADDRESS, address << 1);
+ smb_hc_write(hc, ACPI_SMB_PROTOCOL, protocol);
+ /*
+ * Wait for completion. Save the status code, data size,
+ * and data into the return package (if required by the protocol).
+ */
+ ret = wait_transaction_complete(hc, 1000);
+ if (ret || !(protocol & 0x01))
+ goto end;
+ switch (protocol) {
+ case SMBUS_RECEIVE_BYTE:
+ case SMBUS_READ_BYTE:
+ sz = 1;
+ break;
+ case SMBUS_READ_WORD:
+ sz = 2;
+ break;
+ case SMBUS_READ_BLOCK:
+ if (smb_hc_read(hc, ACPI_SMB_BLOCK_COUNT, &sz)) {
+ ret = -EFAULT;
+ goto end;
+ }
+ sz &= 0x1f;
+ break;
+ }
+ for (i = 0; i < sz; ++i)
+ smb_hc_read(hc, ACPI_SMB_DATA + i, &data[i]);
+ end:
+ mutex_unlock(&hc->lock);
+ return ret;
+}
+
+int acpi_smbus_read(struct acpi_smb_hc *hc, u8 protocol, u8 address,
+ u8 command, u8 *data)
+{
+ return acpi_smbus_transaction(hc, protocol, address, command, data, 0);
+}
+
+EXPORT_SYMBOL_GPL(acpi_smbus_read);
+
+int acpi_smbus_write(struct acpi_smb_hc *hc, u8 protocol, u8 address,
+ u8 command, u8 *data, u8 length)
+{
+ return acpi_smbus_transaction(hc, protocol, address, command, data, length);
+}
+
+EXPORT_SYMBOL_GPL(acpi_smbus_write);
+
+int acpi_smbus_register_callback(struct acpi_smb_hc *hc,
+ smbus_alarm_callback callback, void *context)
+{
+ mutex_lock(&hc->lock);
+ hc->callback = callback;
+ hc->context = context;
+ mutex_unlock(&hc->lock);
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(acpi_smbus_register_callback);
+
+int acpi_smbus_unregister_callback(struct acpi_smb_hc *hc)
+{
+ mutex_lock(&hc->lock);
+ hc->callback = NULL;
+ hc->context = NULL;
+ mutex_unlock(&hc->lock);
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(acpi_smbus_unregister_callback);
+
+static void acpi_smbus_callback(void *context)
+{
+ struct acpi_smb_hc *hc = context;
+
+ if (hc->callback)
+ hc->callback(hc->context);
+}
+
+static int smbus_alarm(void *context)
+{
+ struct acpi_smb_hc *hc = context;
+ union acpi_smb_status status;
+ if (smb_hc_read(hc, ACPI_SMB_STATUS, &status.raw))
+ return 0;
+ /* Check if it is only a completion notify */
+ if (status.fields.done)
+ wake_up(&hc->wait);
+ if (!status.fields.alarm)
+ return 0;
+ mutex_lock(&hc->lock);
+ smb_hc_write(hc, ACPI_SMB_STATUS, status.raw);
+ if (hc->callback)
+ acpi_os_execute(OSL_GPE_HANDLER, acpi_smbus_callback, hc);
+ mutex_unlock(&hc->lock);
+ return 0;
+}
+
+typedef int (*acpi_ec_query_func) (void *data);
+
+extern int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
+ acpi_handle handle, acpi_ec_query_func func,
+ void *data);
+
+static int acpi_smbus_hc_add(struct acpi_device *device)
+{
+ int status;
+ unsigned long val;
+ struct acpi_smb_hc *hc;
+
+ if (!device)
+ return -EINVAL;
+
+ status = acpi_evaluate_integer(device->handle, "_EC", NULL, &val);
+ if (ACPI_FAILURE(status)) {
+ printk(KERN_ERR PREFIX "error obtaining _EC.\n");
+ return -EIO;
+ }
+
+ strcpy(acpi_device_name(device), ACPI_SMB_HC_DEVICE_NAME);
+ strcpy(acpi_device_class(device), ACPI_SMB_HC_CLASS);
+
+ hc = kzalloc(sizeof(struct acpi_smb_hc), GFP_KERNEL);
+ if (!hc)
+ return -ENOMEM;
+ mutex_init(&hc->lock);
+ init_waitqueue_head(&hc->wait);
+
+ hc->ec = acpi_driver_data(device->parent);
+ hc->offset = (val >> 8) & 0xff;
+ hc->query_bit = val & 0xff;
+ acpi_driver_data(device) = hc;
+
+ acpi_ec_add_query_handler(hc->ec, hc->query_bit, NULL, smbus_alarm, hc);
+ printk(KERN_INFO PREFIX "SBS HC: EC = 0x%p, offset = 0x%0x, query_bit = 0x%0x\n",
+ hc->ec, hc->offset, hc->query_bit);
+
+ return 0;
+}
+
+extern void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit);
+
+static int acpi_smbus_hc_remove(struct acpi_device *device, int type)
+{
+ struct acpi_smb_hc *hc;
+
+ if (!device)
+ return -EINVAL;
+
+ hc = acpi_driver_data(device);
+ acpi_ec_remove_query_handler(hc->ec, hc->query_bit);
+ kfree(hc);
+ return 0;
+}
+
+static int __init acpi_smb_hc_init(void)
+{
+ int result;
+
+ result = acpi_bus_register_driver(&acpi_smb_hc_driver);
+ if (result < 0)
+ return -ENODEV;
+ return 0;
+}
+
+static void __exit acpi_smb_hc_exit(void)
+{
+ acpi_bus_unregister_driver(&acpi_smb_hc_driver);
+}
+
+module_init(acpi_smb_hc_init);
+module_exit(acpi_smb_hc_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Alexey Starikovskiy");
+MODULE_DESCRIPTION("ACPI SMBus HC driver");
diff --git a/drivers/acpi/sbshc.h b/drivers/acpi/sbshc.h
new file mode 100644
index 000000000000..3bda3491a97b
--- /dev/null
+++ b/drivers/acpi/sbshc.h
@@ -0,0 +1,27 @@
+struct acpi_smb_hc;
+enum acpi_smb_protocol {
+ SMBUS_WRITE_QUICK = 2,
+ SMBUS_READ_QUICK = 3,
+ SMBUS_SEND_BYTE = 4,
+ SMBUS_RECEIVE_BYTE = 5,
+ SMBUS_WRITE_BYTE = 6,
+ SMBUS_READ_BYTE = 7,
+ SMBUS_WRITE_WORD = 8,
+ SMBUS_READ_WORD = 9,
+ SMBUS_WRITE_BLOCK = 0xa,
+ SMBUS_READ_BLOCK = 0xb,
+ SMBUS_PROCESS_CALL = 0xc,
+ SMBUS_BLOCK_PROCESS_CALL = 0xd,
+};
+
+static const u8 SMBUS_PEC = 0x80;
+
+typedef void (*smbus_alarm_callback)(void *context);
+
+extern int acpi_smbus_read(struct acpi_smb_hc *hc, u8 protocol, u8 address,
+ u8 command, u8 * data);
+extern int acpi_smbus_write(struct acpi_smb_hc *hc, u8 protocol, u8 slave_address,
+ u8 command, u8 * data, u8 length);
+extern int acpi_smbus_register_callback(struct acpi_smb_hc *hc,
+ smbus_alarm_callback callback, void *context);
+extern int acpi_smbus_unregister_callback(struct acpi_smb_hc *hc);
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
index 5055acf2163c..2c0b6630f8ba 100644
--- a/drivers/acpi/sleep/main.c
+++ b/drivers/acpi/sleep/main.c
@@ -44,13 +44,12 @@ int acpi_sleep_prepare(u32 acpi_state)
ACPI_FLUSH_CPU_CACHE();
acpi_enable_wakeup_device_prep(acpi_state);
#endif
- acpi_gpe_sleep_prepare(acpi_state);
acpi_enter_sleep_state_prep(acpi_state);
return 0;
}
#ifdef CONFIG_SUSPEND
-static struct pm_ops acpi_pm_ops;
+static struct platform_suspend_ops acpi_pm_ops;
extern void do_suspend_lowlevel(void);
@@ -85,13 +84,12 @@ static int acpi_pm_set_target(suspend_state_t pm_state)
/**
* acpi_pm_prepare - Do preliminary suspend work.
- * @pm_state: ignored
*
* If necessary, set the firmware waking vector and do arch-specific
* nastiness to get the wakeup code to the waking vector.
*/
-static int acpi_pm_prepare(suspend_state_t pm_state)
+static int acpi_pm_prepare(void)
{
int error = acpi_sleep_prepare(acpi_target_sleep_state);
@@ -160,18 +158,17 @@ static int acpi_pm_enter(suspend_state_t pm_state)
/**
* acpi_pm_finish - Finish up suspend sequence.
- * @pm_state: ignored
*
* This is called after we wake back up (or if entering the sleep state
* failed).
*/
-static int acpi_pm_finish(suspend_state_t pm_state)
+static void acpi_pm_finish(void)
{
u32 acpi_state = acpi_target_sleep_state;
- acpi_leave_sleep_state(acpi_state);
acpi_disable_wakeup_device(acpi_state);
+ acpi_leave_sleep_state(acpi_state);
/* reset firmware waking vector */
acpi_set_firmware_waking_vector((acpi_physical_address) 0);
@@ -184,7 +181,6 @@ static int acpi_pm_finish(suspend_state_t pm_state)
init_8259A(0);
}
#endif
- return 0;
}
static int acpi_pm_state_valid(suspend_state_t pm_state)
@@ -203,7 +199,7 @@ static int acpi_pm_state_valid(suspend_state_t pm_state)
}
}
-static struct pm_ops acpi_pm_ops = {
+static struct platform_suspend_ops acpi_pm_ops = {
.valid = acpi_pm_state_valid,
.set_target = acpi_pm_set_target,
.prepare = acpi_pm_prepare,
@@ -233,6 +229,12 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
#endif /* CONFIG_SUSPEND */
#ifdef CONFIG_HIBERNATION
+static int acpi_hibernation_start(void)
+{
+ acpi_target_sleep_state = ACPI_STATE_S4;
+ return 0;
+}
+
static int acpi_hibernation_prepare(void)
{
return acpi_sleep_prepare(ACPI_STATE_S4);
@@ -254,13 +256,29 @@ static int acpi_hibernation_enter(void)
return ACPI_SUCCESS(status) ? 0 : -EFAULT;
}
+static void acpi_hibernation_leave(void)
+{
+ /*
+ * If ACPI is not enabled by the BIOS and the boot kernel, we need to
+ * enable it here.
+ */
+ acpi_enable();
+}
+
static void acpi_hibernation_finish(void)
{
- acpi_leave_sleep_state(ACPI_STATE_S4);
+ /*
+ * If ACPI is not enabled by the BIOS and the boot kernel, we need to
+ * enable it here.
+ */
+ acpi_enable();
acpi_disable_wakeup_device(ACPI_STATE_S4);
+ acpi_leave_sleep_state(ACPI_STATE_S4);
/* reset firmware waking vector */
acpi_set_firmware_waking_vector((acpi_physical_address) 0);
+
+ acpi_target_sleep_state = ACPI_STATE_S0;
}
static int acpi_hibernation_pre_restore(void)
@@ -277,10 +295,13 @@ static void acpi_hibernation_restore_cleanup(void)
acpi_hw_enable_all_runtime_gpes();
}
-static struct hibernation_ops acpi_hibernation_ops = {
+static struct platform_hibernation_ops acpi_hibernation_ops = {
+ .start = acpi_hibernation_start,
+ .pre_snapshot = acpi_hibernation_prepare,
+ .finish = acpi_hibernation_finish,
.prepare = acpi_hibernation_prepare,
.enter = acpi_hibernation_enter,
- .finish = acpi_hibernation_finish,
+ .leave = acpi_hibernation_leave,
.pre_restore = acpi_hibernation_pre_restore,
.restore_cleanup = acpi_hibernation_restore_cleanup,
};
@@ -389,6 +410,7 @@ static void acpi_power_off(void)
/* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */
printk("%s called\n", __FUNCTION__);
local_irq_disable();
+ acpi_enable_wakeup_device(ACPI_STATE_S5);
acpi_enter_sleep_state(ACPI_STATE_S5);
}
@@ -417,7 +439,7 @@ int __init acpi_sleep_init(void)
}
}
- pm_set_ops(&acpi_pm_ops);
+ suspend_set_ops(&acpi_pm_ops);
#endif
#ifdef CONFIG_HIBERNATION
diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c
index 3839efd5eaea..1538355c266b 100644
--- a/drivers/acpi/sleep/proc.c
+++ b/drivers/acpi/sleep/proc.c
@@ -194,6 +194,23 @@ static int get_date_field(char **p, u32 * value)
return result;
}
+/* Read a possibly BCD register, always return binary */
+static u32 cmos_bcd_read(int offset, int rtc_control)
+{
+ u32 val = CMOS_READ(offset);
+ if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+ BCD_TO_BIN(val);
+ return val;
+}
+
+/* Write binary value into possibly BCD register */
+static void cmos_bcd_write(u32 val, int offset, int rtc_control)
+{
+ if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+ BIN_TO_BCD(val);
+ CMOS_WRITE(val, offset);
+}
+
static ssize_t
acpi_system_write_alarm(struct file *file,
const char __user * buffer, size_t count, loff_t * ppos)
@@ -258,35 +275,18 @@ acpi_system_write_alarm(struct file *file,
spin_lock_irq(&rtc_lock);
rtc_control = CMOS_READ(RTC_CONTROL);
- if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
- BIN_TO_BCD(yr);
- BIN_TO_BCD(mo);
- BIN_TO_BCD(day);
- BIN_TO_BCD(hr);
- BIN_TO_BCD(min);
- BIN_TO_BCD(sec);
- }
if (adjust) {
- yr += CMOS_READ(RTC_YEAR);
- mo += CMOS_READ(RTC_MONTH);
- day += CMOS_READ(RTC_DAY_OF_MONTH);
- hr += CMOS_READ(RTC_HOURS);
- min += CMOS_READ(RTC_MINUTES);
- sec += CMOS_READ(RTC_SECONDS);
+ yr += cmos_bcd_read(RTC_YEAR, rtc_control);
+ mo += cmos_bcd_read(RTC_MONTH, rtc_control);
+ day += cmos_bcd_read(RTC_DAY_OF_MONTH, rtc_control);
+ hr += cmos_bcd_read(RTC_HOURS, rtc_control);
+ min += cmos_bcd_read(RTC_MINUTES, rtc_control);
+ sec += cmos_bcd_read(RTC_SECONDS, rtc_control);
}
spin_unlock_irq(&rtc_lock);
- if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
- BCD_TO_BIN(yr);
- BCD_TO_BIN(mo);
- BCD_TO_BIN(day);
- BCD_TO_BIN(hr);
- BCD_TO_BIN(min);
- BCD_TO_BIN(sec);
- }
-
if (sec > 59) {
min++;
sec -= 60;
@@ -307,14 +307,6 @@ acpi_system_write_alarm(struct file *file,
yr++;
mo -= 12;
}
- if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
- BIN_TO_BCD(yr);
- BIN_TO_BCD(mo);
- BIN_TO_BCD(day);
- BIN_TO_BCD(hr);
- BIN_TO_BCD(min);
- BIN_TO_BCD(sec);
- }
spin_lock_irq(&rtc_lock);
/*
@@ -326,9 +318,9 @@ acpi_system_write_alarm(struct file *file,
CMOS_READ(RTC_INTR_FLAGS);
/* write the fields the rtc knows about */
- CMOS_WRITE(hr, RTC_HOURS_ALARM);
- CMOS_WRITE(min, RTC_MINUTES_ALARM);
- CMOS_WRITE(sec, RTC_SECONDS_ALARM);
+ cmos_bcd_write(hr, RTC_HOURS_ALARM, rtc_control);
+ cmos_bcd_write(min, RTC_MINUTES_ALARM, rtc_control);
+ cmos_bcd_write(sec, RTC_SECONDS_ALARM, rtc_control);
/*
* If the system supports an enhanced alarm it will have non-zero
@@ -336,11 +328,11 @@ acpi_system_write_alarm(struct file *file,
* to the RTC area of memory.
*/
if (acpi_gbl_FADT.day_alarm)
- CMOS_WRITE(day, acpi_gbl_FADT.day_alarm);
+ cmos_bcd_write(day, acpi_gbl_FADT.day_alarm, rtc_control);
if (acpi_gbl_FADT.month_alarm)
- CMOS_WRITE(mo, acpi_gbl_FADT.month_alarm);
+ cmos_bcd_write(mo, acpi_gbl_FADT.month_alarm, rtc_control);
if (acpi_gbl_FADT.century)
- CMOS_WRITE(yr / 100, acpi_gbl_FADT.century);
+ cmos_bcd_write(yr / 100, acpi_gbl_FADT.century, rtc_control);
/* enable the rtc alarm interrupt */
rtc_control |= RTC_AIE;
CMOS_WRITE(rtc_control, RTC_CONTROL);
diff --git a/drivers/acpi/sleep/sleep.h b/drivers/acpi/sleep/sleep.h
index ff1f8504f497..a2ea125ae2d0 100644
--- a/drivers/acpi/sleep/sleep.h
+++ b/drivers/acpi/sleep/sleep.h
@@ -5,6 +5,5 @@ extern int acpi_suspend (u32 state);
extern void acpi_enable_wakeup_device_prep(u8 sleep_state);
extern void acpi_enable_wakeup_device(u8 sleep_state);
extern void acpi_disable_wakeup_device(u8 sleep_state);
-extern void acpi_gpe_sleep_prepare(u32 sleep_state);
extern int acpi_sleep_prepare(u32 acpi_state);
diff --git a/drivers/acpi/sleep/wakeup.c b/drivers/acpi/sleep/wakeup.c
index 97c27ddb144d..ed8e41becf0c 100644
--- a/drivers/acpi/sleep/wakeup.c
+++ b/drivers/acpi/sleep/wakeup.c
@@ -64,36 +64,29 @@ void acpi_enable_wakeup_device(u8 sleep_state)
ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device");
spin_lock(&acpi_device_lock);
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
- struct acpi_device *dev = container_of(node,
- struct acpi_device,
- wakeup_list);
-
+ struct acpi_device *dev =
+ container_of(node, struct acpi_device, wakeup_list);
+ if (!dev->wakeup.flags.valid)
+ continue;
/* If users want to disable run-wake GPE,
* we only disable it for wake and leave it for runtime
*/
- if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) {
- spin_unlock(&acpi_device_lock);
- acpi_set_gpe_type(dev->wakeup.gpe_device,
- dev->wakeup.gpe_number,
- ACPI_GPE_TYPE_RUNTIME);
- /* Re-enable it, since set_gpe_type will disable it */
- acpi_enable_gpe(dev->wakeup.gpe_device,
- dev->wakeup.gpe_number, ACPI_ISR);
- spin_lock(&acpi_device_lock);
+ if (!dev->wakeup.state.enabled ||
+ sleep_state > (u32) dev->wakeup.sleep_state) {
+ if (dev->wakeup.flags.run_wake) {
+ spin_unlock(&acpi_device_lock);
+ /* set_gpe_type will disable GPE, leave it like that */
+ acpi_set_gpe_type(dev->wakeup.gpe_device,
+ dev->wakeup.gpe_number,
+ ACPI_GPE_TYPE_RUNTIME);
+ spin_lock(&acpi_device_lock);
+ }
continue;
}
-
- if (!dev->wakeup.flags.valid ||
- !dev->wakeup.state.enabled ||
- (sleep_state > (u32) dev->wakeup.sleep_state))
- continue;
-
spin_unlock(&acpi_device_lock);
- /* run-wake GPE has been enabled */
if (!dev->wakeup.flags.run_wake)
acpi_enable_gpe(dev->wakeup.gpe_device,
dev->wakeup.gpe_number, ACPI_ISR);
- dev->wakeup.state.active = 1;
spin_lock(&acpi_device_lock);
}
spin_unlock(&acpi_device_lock);
@@ -112,26 +105,25 @@ void acpi_disable_wakeup_device(u8 sleep_state)
spin_lock(&acpi_device_lock);
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
- struct acpi_device *dev = container_of(node,
- struct acpi_device,
- wakeup_list);
+ struct acpi_device *dev =
+ container_of(node, struct acpi_device, wakeup_list);
- if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) {
- spin_unlock(&acpi_device_lock);
- acpi_set_gpe_type(dev->wakeup.gpe_device,
- dev->wakeup.gpe_number,
- ACPI_GPE_TYPE_WAKE_RUN);
- /* Re-enable it, since set_gpe_type will disable it */
- acpi_enable_gpe(dev->wakeup.gpe_device,
- dev->wakeup.gpe_number, ACPI_NOT_ISR);
- spin_lock(&acpi_device_lock);
+ if (!dev->wakeup.flags.valid)
continue;
- }
-
- if (!dev->wakeup.flags.valid ||
- !dev->wakeup.state.active ||
- (sleep_state > (u32) dev->wakeup.sleep_state))
+ if (!dev->wakeup.state.enabled ||
+ sleep_state > (u32) dev->wakeup.sleep_state) {
+ if (dev->wakeup.flags.run_wake) {
+ spin_unlock(&acpi_device_lock);
+ acpi_set_gpe_type(dev->wakeup.gpe_device,
+ dev->wakeup.gpe_number,
+ ACPI_GPE_TYPE_WAKE_RUN);
+ /* Re-enable it, since set_gpe_type will disable it */
+ acpi_enable_gpe(dev->wakeup.gpe_device,
+ dev->wakeup.gpe_number, ACPI_NOT_ISR);
+ spin_lock(&acpi_device_lock);
+ }
continue;
+ }
spin_unlock(&acpi_device_lock);
acpi_disable_wakeup_device_power(dev);
@@ -142,7 +134,6 @@ void acpi_disable_wakeup_device(u8 sleep_state)
acpi_clear_gpe(dev->wakeup.gpe_device,
dev->wakeup.gpe_number, ACPI_NOT_ISR);
}
- dev->wakeup.state.active = 0;
spin_lock(&acpi_device_lock);
}
spin_unlock(&acpi_device_lock);
@@ -160,48 +151,20 @@ static int __init acpi_wakeup_device_init(void)
struct acpi_device *dev = container_of(node,
struct acpi_device,
wakeup_list);
-
/* In case user doesn't load button driver */
- if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) {
- spin_unlock(&acpi_device_lock);
- acpi_set_gpe_type(dev->wakeup.gpe_device,
- dev->wakeup.gpe_number,
- ACPI_GPE_TYPE_WAKE_RUN);
- acpi_enable_gpe(dev->wakeup.gpe_device,
- dev->wakeup.gpe_number, ACPI_NOT_ISR);
- dev->wakeup.state.enabled = 1;
- spin_lock(&acpi_device_lock);
- }
+ if (!dev->wakeup.flags.run_wake || dev->wakeup.state.enabled)
+ continue;
+ spin_unlock(&acpi_device_lock);
+ acpi_set_gpe_type(dev->wakeup.gpe_device,
+ dev->wakeup.gpe_number,
+ ACPI_GPE_TYPE_WAKE_RUN);
+ acpi_enable_gpe(dev->wakeup.gpe_device,
+ dev->wakeup.gpe_number, ACPI_NOT_ISR);
+ dev->wakeup.state.enabled = 1;
+ spin_lock(&acpi_device_lock);
}
spin_unlock(&acpi_device_lock);
-
return 0;
}
late_initcall(acpi_wakeup_device_init);
-
-/*
- * Disable all wakeup GPEs before entering requested sleep state.
- * @sleep_state: ACPI state
- * Since acpi_enter_sleep_state() will disable all
- * RUNTIME GPEs, we simply mark all GPES that
- * are not enabled for wakeup from requested state as RUNTIME.
- */
-void acpi_gpe_sleep_prepare(u32 sleep_state)
-{
- struct list_head *node, *next;
-
- list_for_each_safe(node, next, &acpi_wakeup_device_list) {
- struct acpi_device *dev = container_of(node,
- struct acpi_device,
- wakeup_list);
-
- /* The GPE can wakeup system from this state, don't touch it */
- if ((u32) dev->wakeup.sleep_state >= sleep_state)
- continue;
- /* acpi_set_gpe_type will automatically disable GPE */
- acpi_set_gpe_type(dev->wakeup.gpe_device,
- dev->wakeup.gpe_number,
- ACPI_GPE_TYPE_RUNTIME);
- }
-}
diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c
index 8cc9492ffbf2..5f1d85f2ffe4 100644
--- a/drivers/acpi/tables/tbutils.c
+++ b/drivers/acpi/tables/tbutils.c
@@ -400,7 +400,7 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags)
u32 table_count;
struct acpi_table_header *table;
acpi_physical_address address;
- acpi_physical_address rsdt_address;
+ acpi_physical_address uninitialized_var(rsdt_address);
u32 length;
u8 *table_entry;
acpi_status status;
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index ad898e10c1a9..5f79b4451212 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -195,6 +195,7 @@ struct acpi_thermal {
struct acpi_thermal_trips trips;
struct acpi_handle_list devices;
struct timer_list timer;
+ struct mutex lock;
};
static const struct file_operations acpi_thermal_state_fops = {
@@ -711,6 +712,7 @@ static void acpi_thermal_check(void *data)
int result = 0;
struct acpi_thermal *tz = data;
unsigned long sleep_time = 0;
+ unsigned long timeout_jiffies = 0;
int i = 0;
struct acpi_thermal_state state;
@@ -720,11 +722,15 @@ static void acpi_thermal_check(void *data)
return;
}
+ /* Check if someone else is already running */
+ if (!mutex_trylock(&tz->lock))
+ return;
+
state = tz->state;
result = acpi_thermal_get_temperature(tz);
if (result)
- return;
+ goto unlock;
memset(&tz->state, 0, sizeof(tz->state));
@@ -787,10 +793,13 @@ static void acpi_thermal_check(void *data)
* a thermal event occurs). Note that _TSP and _TZD values are
* given in 1/10th seconds (we must covert to milliseconds).
*/
- if (tz->state.passive)
+ if (tz->state.passive) {
sleep_time = tz->trips.passive.tsp * 100;
- else if (tz->polling_frequency > 0)
+ timeout_jiffies = jiffies + (HZ * sleep_time) / 1000;
+ } else if (tz->polling_frequency > 0) {
sleep_time = tz->polling_frequency * 100;
+ timeout_jiffies = round_jiffies(jiffies + (HZ * sleep_time) / 1000);
+ }
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s: temperature[%lu] sleep[%lu]\n",
tz->name, tz->temperature, sleep_time));
@@ -804,17 +813,16 @@ static void acpi_thermal_check(void *data)
del_timer(&(tz->timer));
} else {
if (timer_pending(&(tz->timer)))
- mod_timer(&(tz->timer),
- jiffies + (HZ * sleep_time) / 1000);
+ mod_timer(&(tz->timer), timeout_jiffies);
else {
tz->timer.data = (unsigned long)tz;
tz->timer.function = acpi_thermal_run;
- tz->timer.expires = jiffies + (HZ * sleep_time) / 1000;
+ tz->timer.expires = timeout_jiffies;
add_timer(&(tz->timer));
}
}
-
- return;
+ unlock:
+ mutex_unlock(&tz->lock);
}
/* --------------------------------------------------------------------------
@@ -1251,7 +1259,7 @@ static int acpi_thermal_add(struct acpi_device *device)
strcpy(acpi_device_name(device), ACPI_THERMAL_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_THERMAL_CLASS);
acpi_driver_data(device) = tz;
-
+ mutex_init(&tz->lock);
result = acpi_thermal_get_info(tz);
if (result)
goto end;
@@ -1321,7 +1329,7 @@ static int acpi_thermal_remove(struct acpi_device *device, int type)
}
acpi_thermal_remove_fs(device);
-
+ mutex_destroy(&tz->lock);
kfree(tz);
return 0;
}
diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c
index a736ef7bdee4..9e8c20c6a0b7 100644
--- a/drivers/acpi/toshiba_acpi.c
+++ b/drivers/acpi/toshiba_acpi.c
@@ -591,9 +591,12 @@ static int __init toshiba_acpi_init(void)
NULL,
&toshiba_backlight_data);
if (IS_ERR(toshiba_backlight_device)) {
+ int ret = PTR_ERR(toshiba_backlight_device);
+
printk(KERN_ERR "Could not register toshiba backlight device\n");
toshiba_backlight_device = NULL;
toshiba_acpi_exit();
+ return ret;
}
toshiba_backlight_device->props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index b8a2095cb5ee..bac956b30c57 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -409,14 +409,17 @@ acpi_video_device_lcd_query_levels(struct acpi_video_device *device,
static int
acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level)
{
- int status;
+ int status = AE_OK;
union acpi_object arg0 = { ACPI_TYPE_INTEGER };
struct acpi_object_list args = { 1, &arg0 };
arg0.integer.value = level;
- status = acpi_evaluate_object(device->dev->handle, "_BCM", &args, NULL);
+ if (device->cap._BCM)
+ status = acpi_evaluate_object(device->dev->handle, "_BCM",
+ &args, NULL);
+ device->brightness->curr = level;
return status;
}
@@ -424,11 +427,11 @@ static int
acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
unsigned long *level)
{
- int status;
-
- status = acpi_evaluate_integer(device->dev->handle, "_BQC", NULL, level);
-
- return status;
+ if (device->cap._BQC)
+ return acpi_evaluate_integer(device->dev->handle, "_BQC", NULL,
+ level);
+ *level = device->brightness->curr;
+ return AE_OK;
}
static int
@@ -1633,9 +1636,20 @@ static int
acpi_video_get_next_level(struct acpi_video_device *device,
u32 level_current, u32 event)
{
- int min, max, min_above, max_below, i, l;
+ int min, max, min_above, max_below, i, l, delta = 255;
max = max_below = 0;
min = min_above = 255;
+ /* Find closest level to level_current */
+ for (i = 0; i < device->brightness->count; i++) {
+ l = device->brightness->levels[i];
+ if (abs(l - level_current) < abs(delta)) {
+ delta = l - level_current;
+ if (!delta)
+ break;
+ }
+ }
+ /* Ajust level_current to closest available level */
+ level_current += delta;
for (i = 0; i < device->brightness->count; i++) {
l = device->brightness->levels[i];
if (l < min)
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 4672066167e3..ba63619ae5df 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -182,6 +182,15 @@ config PATA_ACPI
firmware in the BIOS. This driver can sometimes handle
otherwise unsupported hardware.
+config SATA_FSL
+ tristate "Freescale 3.0Gbps SATA support"
+ depends on PPC_MPC837x
+ help
+ This option enables support for Freescale 3.0Gbps SATA controller.
+ It can be found on MPC837x and MPC8315.
+
+ If unsure, say N.
+
config PATA_ALI
tristate "ALi PATA support (Experimental)"
depends on PCI && EXPERIMENTAL
@@ -272,6 +281,15 @@ config PATA_CS5535
If unsure, say N.
+config PATA_CS5536
+ tristate "CS5536 PATA support (Experimental)"
+ depends on PCI && X86 && !X86_64 && EXPERIMENTAL
+ help
+ This option enables support for the AMD CS5536
+ companion chip used with the Geode LX processor family.
+
+ If unsure, say N.
+
config PATA_CYPRESS
tristate "Cypress CY82C693 PATA support (Very Experimental)"
depends on PCI && EXPERIMENTAL
@@ -632,11 +650,4 @@ config PATA_BF54X
If unsure, say N.
-config PATA_BF54X_DMA
- bool "DMA mode"
- depends on PATA_BF54X
- default y
- help
- Enable DMA mode for Blackfin ATAPI controller.
-
endif # ATA
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index 2a63645003eb..b13feb2c5dae 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_SATA_ULI) += sata_uli.o
obj-$(CONFIG_SATA_MV) += sata_mv.o
obj-$(CONFIG_SATA_INIC162X) += sata_inic162x.o
obj-$(CONFIG_PDC_ADMA) += pdc_adma.o
+obj-$(CONFIG_SATA_FSL) += sata_fsl.o
obj-$(CONFIG_PATA_ALI) += pata_ali.o
obj-$(CONFIG_PATA_AMD) += pata_amd.o
@@ -28,6 +29,7 @@ obj-$(CONFIG_PATA_CMD64X) += pata_cmd64x.o
obj-$(CONFIG_PATA_CS5520) += pata_cs5520.o
obj-$(CONFIG_PATA_CS5530) += pata_cs5530.o
obj-$(CONFIG_PATA_CS5535) += pata_cs5535.o
+obj-$(CONFIG_PATA_CS5536) += pata_cs5536.o
obj-$(CONFIG_PATA_CYPRESS) += pata_cypress.o
obj-$(CONFIG_PATA_EFAR) += pata_efar.o
obj-$(CONFIG_PATA_HPT366) += pata_hpt366.o
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 10bc3f64c453..ed9b407e42d4 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -41,6 +41,7 @@
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
#include <linux/device.h>
+#include <linux/dmi.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_cmnd.h>
#include <linux/libata.h>
@@ -48,6 +49,9 @@
#define DRV_NAME "ahci"
#define DRV_VERSION "3.0"
+static int ahci_enable_alpm(struct ata_port *ap,
+ enum link_pm policy);
+static void ahci_disable_alpm(struct ata_port *ap);
enum {
AHCI_PCI_BAR = 5,
@@ -98,6 +102,7 @@ enum {
HOST_CAP_SSC = (1 << 14), /* Slumber capable */
HOST_CAP_PMP = (1 << 17), /* Port Multiplier support */
HOST_CAP_CLO = (1 << 24), /* Command List Override support */
+ HOST_CAP_ALPM = (1 << 26), /* Aggressive Link PM support */
HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */
HOST_CAP_SNTF = (1 << 29), /* SNotification register */
HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing */
@@ -154,6 +159,8 @@ enum {
PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS,
/* PORT_CMD bits */
+ PORT_CMD_ASP = (1 << 27), /* Aggressive Slumber/Partial */
+ PORT_CMD_ALPE = (1 << 26), /* Aggressive Link PM enable */
PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */
PORT_CMD_PMP = (1 << 17), /* PMP attached */
PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */
@@ -177,13 +184,14 @@ enum {
AHCI_HFLAG_MV_PATA = (1 << 4), /* PATA port */
AHCI_HFLAG_NO_MSI = (1 << 5), /* no PCI MSI */
AHCI_HFLAG_NO_PMP = (1 << 6), /* no PMP */
+ AHCI_HFLAG_NO_HOTPLUG = (1 << 7), /* ignore PxSERR.DIAG.N */
/* ap->flags bits */
- AHCI_FLAG_NO_HOTPLUG = (1 << 24), /* ignore PxSERR.DIAG.N */
AHCI_FLAG_COMMON = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
- ATA_FLAG_ACPI_SATA | ATA_FLAG_AN,
+ ATA_FLAG_ACPI_SATA | ATA_FLAG_AN |
+ ATA_FLAG_IPM,
AHCI_LFLAG_COMMON = ATA_LFLAG_SKIP_D2H_BSY,
};
@@ -227,7 +235,7 @@ struct ahci_port_priv {
static int ahci_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val);
static int ahci_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val);
-static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
+static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);
static void ahci_irq_clear(struct ata_port *ap);
static int ahci_port_start(struct ata_port *ap);
@@ -241,6 +249,7 @@ static void ahci_pmp_attach(struct ata_port *ap);
static void ahci_pmp_detach(struct ata_port *ap);
static void ahci_error_handler(struct ata_port *ap);
static void ahci_vt8251_error_handler(struct ata_port *ap);
+static void ahci_p5wdh_error_handler(struct ata_port *ap);
static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
static int ahci_port_resume(struct ata_port *ap);
static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl);
@@ -252,6 +261,11 @@ static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
static int ahci_pci_device_resume(struct pci_dev *pdev);
#endif
+static struct class_device_attribute *ahci_shost_attrs[] = {
+ &class_device_attr_link_power_management_policy,
+ NULL
+};
+
static struct scsi_host_template ahci_sht = {
.module = THIS_MODULE,
.name = DRV_NAME,
@@ -269,6 +283,7 @@ static struct scsi_host_template ahci_sht = {
.slave_configure = ata_scsi_slave_config,
.slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
+ .shost_attrs = ahci_shost_attrs,
};
static const struct ata_port_operations ahci_ops = {
@@ -300,6 +315,8 @@ static const struct ata_port_operations ahci_ops = {
.port_suspend = ahci_port_suspend,
.port_resume = ahci_port_resume,
#endif
+ .enable_pm = ahci_enable_alpm,
+ .disable_pm = ahci_disable_alpm,
.port_start = ahci_port_start,
.port_stop = ahci_port_stop,
@@ -339,6 +356,40 @@ static const struct ata_port_operations ahci_vt8251_ops = {
.port_stop = ahci_port_stop,
};
+static const struct ata_port_operations ahci_p5wdh_ops = {
+ .check_status = ahci_check_status,
+ .check_altstatus = ahci_check_status,
+ .dev_select = ata_noop_dev_select,
+
+ .tf_read = ahci_tf_read,
+
+ .qc_defer = sata_pmp_qc_defer_cmd_switch,
+ .qc_prep = ahci_qc_prep,
+ .qc_issue = ahci_qc_issue,
+
+ .irq_clear = ahci_irq_clear,
+
+ .scr_read = ahci_scr_read,
+ .scr_write = ahci_scr_write,
+
+ .freeze = ahci_freeze,
+ .thaw = ahci_thaw,
+
+ .error_handler = ahci_p5wdh_error_handler,
+ .post_internal_cmd = ahci_post_internal_cmd,
+
+ .pmp_attach = ahci_pmp_attach,
+ .pmp_detach = ahci_pmp_detach,
+
+#ifdef CONFIG_PM
+ .port_suspend = ahci_port_suspend,
+ .port_resume = ahci_port_resume,
+#endif
+
+ .port_start = ahci_port_start,
+ .port_stop = ahci_port_stop,
+};
+
#define AHCI_HFLAGS(flags) .private_data = (void *)(flags)
static const struct ata_port_info ahci_port_info[] = {
@@ -729,7 +780,7 @@ static int ahci_stop_engine(struct ata_port *ap)
/* wait for engine to stop. This could be as long as 500 msec */
tmp = ata_wait_register(port_mmio + PORT_CMD,
- PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
+ PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
if (tmp & PORT_CMD_LIST_ON)
return -EIO;
@@ -800,6 +851,130 @@ static void ahci_power_up(struct ata_port *ap)
writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD);
}
+static void ahci_disable_alpm(struct ata_port *ap)
+{
+ struct ahci_host_priv *hpriv = ap->host->private_data;
+ void __iomem *port_mmio = ahci_port_base(ap);
+ u32 cmd;
+ struct ahci_port_priv *pp = ap->private_data;
+
+ /* IPM bits should be disabled by libata-core */
+ /* get the existing command bits */
+ cmd = readl(port_mmio + PORT_CMD);
+
+ /* disable ALPM and ASP */
+ cmd &= ~PORT_CMD_ASP;
+ cmd &= ~PORT_CMD_ALPE;
+
+ /* force the interface back to active */
+ cmd |= PORT_CMD_ICC_ACTIVE;
+
+ /* write out new cmd value */
+ writel(cmd, port_mmio + PORT_CMD);
+ cmd = readl(port_mmio + PORT_CMD);
+
+ /* wait 10ms to be sure we've come out of any low power state */
+ msleep(10);
+
+ /* clear out any PhyRdy stuff from interrupt status */
+ writel(PORT_IRQ_PHYRDY, port_mmio + PORT_IRQ_STAT);
+
+ /* go ahead and clean out PhyRdy Change from Serror too */
+ ahci_scr_write(ap, SCR_ERROR, ((1 << 16) | (1 << 18)));
+
+ /*
+ * Clear flag to indicate that we should ignore all PhyRdy
+ * state changes
+ */
+ hpriv->flags &= ~AHCI_HFLAG_NO_HOTPLUG;
+
+ /*
+ * Enable interrupts on Phy Ready.
+ */
+ pp->intr_mask |= PORT_IRQ_PHYRDY;
+ writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
+
+ /*
+ * don't change the link pm policy - we can be called
+ * just to turn of link pm temporarily
+ */
+}
+
+static int ahci_enable_alpm(struct ata_port *ap,
+ enum link_pm policy)
+{
+ struct ahci_host_priv *hpriv = ap->host->private_data;
+ void __iomem *port_mmio = ahci_port_base(ap);
+ u32 cmd;
+ struct ahci_port_priv *pp = ap->private_data;
+ u32 asp;
+
+ /* Make sure the host is capable of link power management */
+ if (!(hpriv->cap & HOST_CAP_ALPM))
+ return -EINVAL;
+
+ switch (policy) {
+ case MAX_PERFORMANCE:
+ case NOT_AVAILABLE:
+ /*
+ * if we came here with NOT_AVAILABLE,
+ * it just means this is the first time we
+ * have tried to enable - default to max performance,
+ * and let the user go to lower power modes on request.
+ */
+ ahci_disable_alpm(ap);
+ return 0;
+ case MIN_POWER:
+ /* configure HBA to enter SLUMBER */
+ asp = PORT_CMD_ASP;
+ break;
+ case MEDIUM_POWER:
+ /* configure HBA to enter PARTIAL */
+ asp = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /*
+ * Disable interrupts on Phy Ready. This keeps us from
+ * getting woken up due to spurious phy ready interrupts
+ * TBD - Hot plug should be done via polling now, is
+ * that even supported?
+ */
+ pp->intr_mask &= ~PORT_IRQ_PHYRDY;
+ writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
+
+ /*
+ * Set a flag to indicate that we should ignore all PhyRdy
+ * state changes since these can happen now whenever we
+ * change link state
+ */
+ hpriv->flags |= AHCI_HFLAG_NO_HOTPLUG;
+
+ /* get the existing command bits */
+ cmd = readl(port_mmio + PORT_CMD);
+
+ /*
+ * Set ASP based on Policy
+ */
+ cmd |= asp;
+
+ /*
+ * Setting this bit will instruct the HBA to aggressively
+ * enter a lower power link state when it's appropriate and
+ * based on the value set above for ASP
+ */
+ cmd |= PORT_CMD_ALPE;
+
+ /* write out new cmd value */
+ writel(cmd, port_mmio + PORT_CMD);
+ cmd = readl(port_mmio + PORT_CMD);
+
+ /* IPM bits should be set by libata-core */
+ return 0;
+}
+
#ifdef CONFIG_PM
static void ahci_power_down(struct ata_port *ap)
{
@@ -862,8 +1037,10 @@ static int ahci_reset_controller(struct ata_host *host)
* AHCI-specific, such as HOST_RESET.
*/
tmp = readl(mmio + HOST_CTL);
- if (!(tmp & HOST_AHCI_EN))
- writel(tmp | HOST_AHCI_EN, mmio + HOST_CTL);
+ if (!(tmp & HOST_AHCI_EN)) {
+ tmp |= HOST_AHCI_EN;
+ writel(tmp, mmio + HOST_CTL);
+ }
/* global controller reset */
if ((tmp & HOST_RESET) == 0) {
@@ -1117,15 +1294,8 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
tf.ctl &= ~ATA_SRST;
ahci_exec_polled_cmd(ap, pmp, &tf, 0, 0, 0);
- /* spec mandates ">= 2ms" before checking status.
- * We wait 150ms, because that was the magic delay used for
- * ATAPI devices in Hale Landis's ATADRVR, for the period of time
- * between when the ATA command register is written, and then
- * status is checked. Because waiting for "a while" before
- * checking status is fine, post SRST, we perform this magic
- * delay here as well.
- */
- msleep(150);
+ /* wait a while before checking status */
+ ata_wait_after_reset(ap, deadline);
rc = ata_wait_ready(ap, deadline);
/* link occupied, -ENODEV too is an error */
@@ -1213,6 +1383,53 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
return rc ?: -EAGAIN;
}
+static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline)
+{
+ struct ata_port *ap = link->ap;
+ struct ahci_port_priv *pp = ap->private_data;
+ u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
+ struct ata_taskfile tf;
+ int rc;
+
+ ahci_stop_engine(ap);
+
+ /* clear D2H reception area to properly wait for D2H FIS */
+ ata_tf_init(link->device, &tf);
+ tf.command = 0x80;
+ ata_tf_to_fis(&tf, 0, 0, d2h_fis);
+
+ rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
+ deadline);
+
+ ahci_start_engine(ap);
+
+ if (rc || ata_link_offline(link))
+ return rc;
+
+ /* spec mandates ">= 2ms" before checking status */
+ msleep(150);
+
+ /* The pseudo configuration device on SIMG4726 attached to
+ * ASUS P5W-DH Deluxe doesn't send signature FIS after
+ * hardreset if no device is attached to the first downstream
+ * port && the pseudo device locks up on SRST w/ PMP==0. To
+ * work around this, wait for !BSY only briefly. If BSY isn't
+ * cleared, perform CLO and proceed to IDENTIFY (achieved by
+ * ATA_LFLAG_NO_SRST and ATA_LFLAG_ASSUME_ATA).
+ *
+ * Wait for two seconds. Devices attached to downstream port
+ * which can't process the following IDENTIFY after this will
+ * have to be reset again. For most cases, this should
+ * suffice while making probing snappish enough.
+ */
+ rc = ata_wait_ready(ap, jiffies + 2 * HZ);
+ if (rc)
+ ahci_kick_engine(ap, 0);
+
+ return 0;
+}
+
static void ahci_postreset(struct ata_link *link, unsigned int *class)
{
struct ata_port *ap = link->ap;
@@ -1426,6 +1643,17 @@ static void ahci_port_intr(struct ata_port *ap)
if (unlikely(resetting))
status &= ~PORT_IRQ_BAD_PMP;
+ /* If we are getting PhyRdy, this is
+ * just a power state change, we should
+ * clear out this, plus the PhyRdy/Comm
+ * Wake bits from Serror
+ */
+ if ((hpriv->flags & AHCI_HFLAG_NO_HOTPLUG) &&
+ (status & PORT_IRQ_PHYRDY)) {
+ status &= ~PORT_IRQ_PHYRDY;
+ ahci_scr_write(ap, SCR_ERROR, ((1 << 16) | (1 << 18)));
+ }
+
if (unlikely(status & PORT_IRQ_ERROR)) {
ahci_error_intr(ap, status);
return;
@@ -1479,7 +1707,7 @@ static void ahci_port_intr(struct ata_port *ap)
return;
}
- /* hmmm... a spurious interupt */
+ /* hmmm... a spurious interrupt */
/* if !NCQ, ignore. No modern ATA device has broken HSM
* implementation for non-NCQ commands.
@@ -1564,9 +1792,9 @@ static irqreturn_t ahci_interrupt(int irq, void *dev_instance)
if (!irq_stat)
return IRQ_NONE;
- spin_lock(&host->lock);
+ spin_lock(&host->lock);
- for (i = 0; i < host->n_ports; i++) {
+ for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap;
if (!(irq_stat & (1 << i)))
@@ -1670,6 +1898,19 @@ static void ahci_vt8251_error_handler(struct ata_port *ap)
ahci_postreset);
}
+static void ahci_p5wdh_error_handler(struct ata_port *ap)
+{
+ if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
+ /* restart engine */
+ ahci_stop_engine(ap);
+ ahci_start_engine(ap);
+ }
+
+ /* perform recovery */
+ ata_do_eh(ap, ata_std_prereset, ahci_softreset, ahci_p5wdh_hardreset,
+ ahci_postreset);
+}
+
static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
@@ -1829,9 +2070,9 @@ static int ahci_port_start(struct ata_port *ap)
pp->cmd_tbl_dma = mem_dma;
/*
- * Save off initial list of interrupts to be enabled.
- * This could be changed later
- */
+ * Save off initial list of interrupts to be enabled.
+ * This could be changed later
+ */
pp->intr_mask = DEF_PORT_IRQ;
ap->private_data = pp;
@@ -1918,12 +2159,12 @@ static void ahci_print_info(struct ata_host *host)
dev_printk(KERN_INFO, &pdev->dev,
"AHCI %02x%02x.%02x%02x "
"%u slots %u ports %s Gbps 0x%x impl %s mode\n"
- ,
+ ,
- (vers >> 24) & 0xff,
- (vers >> 16) & 0xff,
- (vers >> 8) & 0xff,
- vers & 0xff,
+ (vers >> 24) & 0xff,
+ (vers >> 16) & 0xff,
+ (vers >> 8) & 0xff,
+ vers & 0xff,
((cap >> 8) & 0x1f) + 1,
(cap & 0x1f) + 1,
@@ -1935,7 +2176,7 @@ static void ahci_print_info(struct ata_host *host)
"flags: "
"%s%s%s%s%s%s%s"
"%s%s%s%s%s%s%s\n"
- ,
+ ,
cap & (1 << 31) ? "64bit " : "",
cap & (1 << 30) ? "ncq " : "",
@@ -1955,6 +2196,51 @@ static void ahci_print_info(struct ata_host *host)
);
}
+/* On ASUS P5W DH Deluxe, the second port of PCI device 00:1f.2 is
+ * hardwired to on-board SIMG 4726. The chipset is ICH8 and doesn't
+ * support PMP and the 4726 either directly exports the device
+ * attached to the first downstream port or acts as a hardware storage
+ * controller and emulate a single ATA device (can be RAID 0/1 or some
+ * other configuration).
+ *
+ * When there's no device attached to the first downstream port of the
+ * 4726, "Config Disk" appears, which is a pseudo ATA device to
+ * configure the 4726. However, ATA emulation of the device is very
+ * lame. It doesn't send signature D2H Reg FIS after the initial
+ * hardreset, pukes on SRST w/ PMP==0 and has bunch of other issues.
+ *
+ * The following function works around the problem by always using
+ * hardreset on the port and not depending on receiving signature FIS
+ * afterward. If signature FIS isn't received soon, ATA class is
+ * assumed without follow-up softreset.
+ */
+static void ahci_p5wdh_workaround(struct ata_host *host)
+{
+ static struct dmi_system_id sysids[] = {
+ {
+ .ident = "P5W DH Deluxe",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR,
+ "ASUSTEK COMPUTER INC"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"),
+ },
+ },
+ { }
+ };
+ struct pci_dev *pdev = to_pci_dev(host->dev);
+
+ if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) &&
+ dmi_check_system(sysids)) {
+ struct ata_port *ap = host->ports[1];
+
+ dev_printk(KERN_INFO, &pdev->dev, "enabling ASUS P5W DH "
+ "Deluxe on-board SIMG4726 workaround\n");
+
+ ap->ops = &ahci_p5wdh_ops;
+ ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA;
+ }
+}
+
static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version;
@@ -2015,6 +2301,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
ata_port_pbar_desc(ap, AHCI_PCI_BAR,
0x100 + ap->port_no * 0x80, "port");
+ /* set initial link pm policy */
+ ap->pm_policy = NOT_AVAILABLE;
+
/* standard SATA port setup */
if (hpriv->port_map & (1 << i))
ap->ioaddr.cmd_addr = port_mmio;
@@ -2024,6 +2313,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
ap->ops = &ata_dummy_port_ops;
}
+ /* apply workaround for ASUS P5W DH Deluxe mainboard */
+ ahci_p5wdh_workaround(host);
+
/* initialize adapter */
rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64);
if (rc)
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 9ce4aa9c2f25..328ce8a08426 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -130,6 +130,7 @@ enum {
ich8_sata_ahci = 9,
piix_pata_mwdma = 10, /* PIIX3 MWDMA only */
tolapai_sata_ahci = 11,
+ ich9_2port_sata = 12,
/* constants for mapping table */
P0 = 0, /* port 0 */
@@ -156,12 +157,12 @@ struct piix_host_priv {
const int *map;
};
-static int piix_init_one (struct pci_dev *pdev,
- const struct pci_device_id *ent);
+static int piix_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent);
static void piix_pata_error_handler(struct ata_port *ap);
-static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev);
-static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev);
-static void ich_set_dmamode (struct ata_port *ap, struct ata_device *adev);
+static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev);
+static void piix_set_dmamode(struct ata_port *ap, struct ata_device *adev);
+static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev);
static int ich_pata_cable_detect(struct ata_port *ap);
#ifdef CONFIG_PM
static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
@@ -238,19 +239,19 @@ static const struct pci_device_id piix_pci_tbl[] = {
/* SATA Controller 1 IDE (ICH8) */
{ 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
/* SATA Controller 2 IDE (ICH8) */
- { 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
+ { 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata },
/* Mobile SATA Controller IDE (ICH8M) */
{ 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
/* SATA Controller IDE (ICH9) */
{ 0x8086, 0x2920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
/* SATA Controller IDE (ICH9) */
- { 0x8086, 0x2921, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
+ { 0x8086, 0x2921, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata },
/* SATA Controller IDE (ICH9) */
- { 0x8086, 0x2926, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
+ { 0x8086, 0x2926, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata },
/* SATA Controller IDE (ICH9M) */
- { 0x8086, 0x2928, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
+ { 0x8086, 0x2928, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata },
/* SATA Controller IDE (ICH9M) */
- { 0x8086, 0x292d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
+ { 0x8086, 0x292d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata },
/* SATA Controller IDE (ICH9M) */
{ 0x8086, 0x292e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
/* SATA Controller IDE (Tolapai) */
@@ -448,6 +449,18 @@ static const struct piix_map_db tolapai_map_db = {
},
};
+static const struct piix_map_db ich9_2port_map_db = {
+ .mask = 0x3,
+ .port_enable = 0x3,
+ .map = {
+ /* PM PS SM SS MAP */
+ { P0, NA, P1, NA }, /* 00b */
+ { RV, RV, RV, RV }, /* 01b */
+ { RV, RV, RV, RV }, /* 10b */
+ { RV, RV, RV, RV },
+ },
+};
+
static const struct piix_map_db *piix_map_db_table[] = {
[ich5_sata] = &ich5_map_db,
[ich6_sata] = &ich6_map_db,
@@ -455,6 +468,7 @@ static const struct piix_map_db *piix_map_db_table[] = {
[ich6m_sata_ahci] = &ich6m_map_db,
[ich8_sata_ahci] = &ich8_map_db,
[tolapai_sata_ahci] = &tolapai_map_db,
+ [ich9_2port_sata] = &ich9_2port_map_db,
};
static struct ata_port_info piix_port_info[] = {
@@ -570,6 +584,17 @@ static struct ata_port_info piix_port_info[] = {
.udma_mask = ATA_UDMA6,
.port_ops = &piix_sata_ops,
},
+
+ [ich9_2port_sata] =
+ {
+ .sht = &piix_sht,
+ .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
+ PIIX_FLAG_AHCI,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &piix_sata_ops,
+ },
};
static struct pci_bits piix_enable_bits[] = {
@@ -596,6 +621,7 @@ struct ich_laptop {
static const struct ich_laptop ich_laptop[] = {
/* devid, subvendor, subdev */
{ 0x27DF, 0x0005, 0x0280 }, /* ICH7 on Acer 5602WLMi */
+ { 0x27DF, 0x1025, 0x0102 }, /* ICH7 on Acer 5602aWLMi */
{ 0x27DF, 0x1025, 0x0110 }, /* ICH7 on Acer 3682WLMi */
{ 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */
{ 0x27DF, 0x103C, 0x30A1 }, /* ICH7 on HP Compaq nc2400 */
@@ -625,9 +651,9 @@ static int ich_pata_cable_detect(struct ata_port *ap)
while (lap->device) {
if (lap->device == pdev->device &&
lap->subvendor == pdev->subsystem_vendor &&
- lap->subdevice == pdev->subsystem_device) {
+ lap->subdevice == pdev->subsystem_device)
return ATA_CBL_PATA40_SHORT;
- }
+
lap++;
}
@@ -674,7 +700,7 @@ static void piix_pata_error_handler(struct ata_port *ap)
* None (inherited from caller).
*/
-static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev)
+static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev)
{
unsigned int pio = adev->pio_mode - XFER_PIO_0;
struct pci_dev *dev = to_pci_dev(ap->host->dev);
@@ -761,7 +787,7 @@ static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev)
* None (inherited from caller).
*/
-static void do_pata_set_dmamode (struct ata_port *ap, struct ata_device *adev, int isich)
+static void do_pata_set_dmamode(struct ata_port *ap, struct ata_device *adev, int isich)
{
struct pci_dev *dev = to_pci_dev(ap->host->dev);
u8 master_port = ap->port_no ? 0x42 : 0x40;
@@ -788,7 +814,7 @@ static void do_pata_set_dmamode (struct ata_port *ap, struct ata_device *adev, i
int u_clock, u_speed;
/*
- * UDMA is handled by a combination of clock switching and
+ * UDMA is handled by a combination of clock switching and
* selection of dividers
*
* Handy rule: Odd modes are UDMATIMx 01, even are 02
@@ -880,7 +906,7 @@ static void do_pata_set_dmamode (struct ata_port *ap, struct ata_device *adev, i
* None (inherited from caller).
*/
-static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+static void piix_set_dmamode(struct ata_port *ap, struct ata_device *adev)
{
do_pata_set_dmamode(ap, adev, 0);
}
@@ -896,7 +922,7 @@ static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev)
* None (inherited from caller).
*/
-static void ich_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev)
{
do_pata_set_dmamode(ap, adev, 1);
}
@@ -934,6 +960,13 @@ static int piix_broken_suspend(void)
},
},
{
+ .ident = "Satellite Pro U200",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE PRO U200"),
+ },
+ },
+ {
.ident = "Satellite U205",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
@@ -1081,8 +1114,7 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev)
u16 cfg;
int no_piix_dma = 0;
- while((pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, pdev)) != NULL)
- {
+ while ((pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, pdev)) != NULL) {
/* Look for 450NX PXB. Check for problem configurations
A PCI quirk checks bit 6 already */
pci_read_config_word(pdev, 0x41, &cfg);
@@ -1216,7 +1248,7 @@ static void piix_iocfg_bit18_quirk(struct pci_dev *pdev)
* Zero on success, or -ERRNO value.
*/
-static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+static int piix_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version;
struct device *dev = &pdev->dev;
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 3f7533589041..545ea865ceb5 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -26,7 +26,7 @@
#include <acpi/actypes.h>
#define NO_PORT_MULT 0xffff
-#define SATA_ADR(root,pmp) (((root) << 16) | (pmp))
+#define SATA_ADR(root, pmp) (((root) << 16) | (pmp))
#define REGS_PER_GTF 7
struct ata_acpi_gtf {
@@ -96,8 +96,8 @@ static void ata_acpi_associate_ide_port(struct ata_port *ap)
}
}
-static void ata_acpi_handle_hotplug (struct ata_port *ap, struct kobject *kobj,
- u32 event)
+static void ata_acpi_handle_hotplug(struct ata_port *ap, struct kobject *kobj,
+ u32 event)
{
char event_string[12];
char *envp[] = { event_string, NULL };
@@ -114,7 +114,7 @@ static void ata_acpi_handle_hotplug (struct ata_port *ap, struct kobject *kobj,
}
if (kobj) {
- sprintf(event_string, "BAY_EVENT=%d", event);
+ sprintf(event_string, "BAY_EVENT=%d", event);
kobject_uevent_env(kobj, KOBJ_CHANGE, envp);
}
}
@@ -127,14 +127,14 @@ static void ata_acpi_dev_notify(acpi_handle handle, u32 event, void *data)
if (dev->sdev)
kobj = &dev->sdev->sdev_gendev.kobj;
- ata_acpi_handle_hotplug (dev->link->ap, kobj, event);
+ ata_acpi_handle_hotplug(dev->link->ap, kobj, event);
}
static void ata_acpi_ap_notify(acpi_handle handle, u32 event, void *data)
{
struct ata_port *ap = data;
- ata_acpi_handle_hotplug (ap, &ap->dev->kobj, event);
+ ata_acpi_handle_hotplug(ap, &ap->dev->kobj, event);
}
/**
@@ -312,7 +312,7 @@ EXPORT_SYMBOL_GPL(ata_acpi_stm);
*
* RETURNS:
* Number of taskfiles on success, 0 if _GTF doesn't exist or doesn't
- * contain valid data. -errno on other errors.
+ * contain valid data.
*/
static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf,
void **ptr_to_free)
@@ -339,7 +339,6 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf,
ata_dev_printk(dev, KERN_WARNING,
"_GTF evaluation failed (AE 0x%x)\n",
status);
- rc = -EIO;
}
goto out_free;
}
@@ -359,7 +358,6 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf,
ata_dev_printk(dev, KERN_WARNING,
"_GTF unexpected object type 0x%x\n",
out_obj->type);
- rc = -EINVAL;
goto out_free;
}
@@ -367,7 +365,6 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf,
ata_dev_printk(dev, KERN_WARNING,
"unexpected _GTF length (%d)\n",
out_obj->buffer.length);
- rc = -EINVAL;
goto out_free;
}
@@ -398,11 +395,11 @@ int ata_acpi_cbl_80wire(struct ata_port *ap)
{
struct ata_acpi_gtm gtm;
int valid = 0;
-
+
/* No _GTM data, no information */
if (ata_acpi_gtm(ap, &gtm) < 0)
return 0;
-
+
/* Split timing, DMA enabled */
if ((gtm.flags & 0x11) == 0x11 && gtm.drive[0].dma < 55)
valid |= 1;
@@ -511,10 +508,7 @@ static int ata_acpi_exec_tfs(struct ata_device *dev)
int gtf_count, i, rc;
/* get taskfiles */
- rc = ata_dev_get_GTF(dev, &gtf, &ptr_to_free);
- if (rc < 0)
- return rc;
- gtf_count = rc;
+ gtf_count = ata_dev_get_GTF(dev, &gtf, &ptr_to_free);
/* execute them */
for (i = 0, rc = 0; i < gtf_count; i++) {
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index b05384a8c326..81898036dbca 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -49,11 +49,11 @@
#include <linux/workqueue.h>
#include <linux/jiffies.h>
#include <linux/scatterlist.h>
+#include <linux/io.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_host.h>
#include <linux/libata.h>
-#include <asm/io.h>
#include <asm/semaphore.h>
#include <asm/byteorder.h>
@@ -68,7 +68,8 @@ const unsigned long sata_deb_timing_long[] = { 100, 2000, 5000 };
static unsigned int ata_dev_init_params(struct ata_device *dev,
u16 heads, u16 sectors);
static unsigned int ata_dev_set_xfermode(struct ata_device *dev);
-static unsigned int ata_dev_set_AN(struct ata_device *dev, u8 enable);
+static unsigned int ata_dev_set_feature(struct ata_device *dev,
+ u8 enable, u8 feature);
static void ata_dev_xfermask(struct ata_device *dev);
static unsigned long ata_dev_blacklisted(const struct ata_device *dev);
@@ -93,7 +94,7 @@ int libata_fua = 0;
module_param_named(fua, libata_fua, int, 0444);
MODULE_PARM_DESC(fua, "FUA support (0=off, 1=on)");
-static int ata_ignore_hpa = 0;
+static int ata_ignore_hpa;
module_param_named(ignore_hpa, ata_ignore_hpa, int, 0644);
MODULE_PARM_DESC(ignore_hpa, "Ignore HPA limit (0=keep BIOS limits, 1=ignore limits, using full disk)");
@@ -619,6 +620,183 @@ void ata_dev_disable(struct ata_device *dev)
}
}
+static int ata_dev_set_dipm(struct ata_device *dev, enum link_pm policy)
+{
+ struct ata_link *link = dev->link;
+ struct ata_port *ap = link->ap;
+ u32 scontrol;
+ unsigned int err_mask;
+ int rc;
+
+ /*
+ * disallow DIPM for drivers which haven't set
+ * ATA_FLAG_IPM. This is because when DIPM is enabled,
+ * phy ready will be set in the interrupt status on
+ * state changes, which will cause some drivers to
+ * think there are errors - additionally drivers will
+ * need to disable hot plug.
+ */
+ if (!(ap->flags & ATA_FLAG_IPM) || !ata_dev_enabled(dev)) {
+ ap->pm_policy = NOT_AVAILABLE;
+ return -EINVAL;
+ }
+
+ /*
+ * For DIPM, we will only enable it for the
+ * min_power setting.
+ *
+ * Why? Because Disks are too stupid to know that
+ * If the host rejects a request to go to SLUMBER
+ * they should retry at PARTIAL, and instead it
+ * just would give up. So, for medium_power to
+ * work at all, we need to only allow HIPM.
+ */
+ rc = sata_scr_read(link, SCR_CONTROL, &scontrol);
+ if (rc)
+ return rc;
+
+ switch (policy) {
+ case MIN_POWER:
+ /* no restrictions on IPM transitions */
+ scontrol &= ~(0x3 << 8);
+ rc = sata_scr_write(link, SCR_CONTROL, scontrol);
+ if (rc)
+ return rc;
+
+ /* enable DIPM */
+ if (dev->flags & ATA_DFLAG_DIPM)
+ err_mask = ata_dev_set_feature(dev,
+ SETFEATURES_SATA_ENABLE, SATA_DIPM);
+ break;
+ case MEDIUM_POWER:
+ /* allow IPM to PARTIAL */
+ scontrol &= ~(0x1 << 8);
+ scontrol |= (0x2 << 8);
+ rc = sata_scr_write(link, SCR_CONTROL, scontrol);
+ if (rc)
+ return rc;
+
+ /*
+ * we don't have to disable DIPM since IPM flags
+ * disallow transitions to SLUMBER, which effectively
+ * disable DIPM if it does not support PARTIAL
+ */
+ break;
+ case NOT_AVAILABLE:
+ case MAX_PERFORMANCE:
+ /* disable all IPM transitions */
+ scontrol |= (0x3 << 8);
+ rc = sata_scr_write(link, SCR_CONTROL, scontrol);
+ if (rc)
+ return rc;
+
+ /*
+ * we don't have to disable DIPM since IPM flags
+ * disallow all transitions which effectively
+ * disable DIPM anyway.
+ */
+ break;
+ }
+
+ /* FIXME: handle SET FEATURES failure */
+ (void) err_mask;
+
+ return 0;
+}
+
+/**
+ * ata_dev_enable_pm - enable SATA interface power management
+ * @dev: device to enable power management
+ * @policy: the link power management policy
+ *
+ * Enable SATA Interface power management. This will enable
+ * Device Interface Power Management (DIPM) for min_power
+ * policy, and then call driver specific callbacks for
+ * enabling Host Initiated Power management.
+ *
+ * Locking: Caller.
+ * Returns: -EINVAL if IPM is not supported, 0 otherwise.
+ */
+void ata_dev_enable_pm(struct ata_device *dev, enum link_pm policy)
+{
+ int rc = 0;
+ struct ata_port *ap = dev->link->ap;
+
+ /* set HIPM first, then DIPM */
+ if (ap->ops->enable_pm)
+ rc = ap->ops->enable_pm(ap, policy);
+ if (rc)
+ goto enable_pm_out;
+ rc = ata_dev_set_dipm(dev, policy);
+
+enable_pm_out:
+ if (rc)
+ ap->pm_policy = MAX_PERFORMANCE;
+ else
+ ap->pm_policy = policy;
+ return /* rc */; /* hopefully we can use 'rc' eventually */
+}
+
+#ifdef CONFIG_PM
+/**
+ * ata_dev_disable_pm - disable SATA interface power management
+ * @dev: device to disable power management
+ *
+ * Disable SATA Interface power management. This will disable
+ * Device Interface Power Management (DIPM) without changing
+ * policy, call driver specific callbacks for disabling Host
+ * Initiated Power management.
+ *
+ * Locking: Caller.
+ * Returns: void
+ */
+static void ata_dev_disable_pm(struct ata_device *dev)
+{
+ struct ata_port *ap = dev->link->ap;
+
+ ata_dev_set_dipm(dev, MAX_PERFORMANCE);
+ if (ap->ops->disable_pm)
+ ap->ops->disable_pm(ap);
+}
+#endif /* CONFIG_PM */
+
+void ata_lpm_schedule(struct ata_port *ap, enum link_pm policy)
+{
+ ap->pm_policy = policy;
+ ap->link.eh_info.action |= ATA_EHI_LPM;
+ ap->link.eh_info.flags |= ATA_EHI_NO_AUTOPSY;
+ ata_port_schedule_eh(ap);
+}
+
+#ifdef CONFIG_PM
+static void ata_lpm_enable(struct ata_host *host)
+{
+ struct ata_link *link;
+ struct ata_port *ap;
+ struct ata_device *dev;
+ int i;
+
+ for (i = 0; i < host->n_ports; i++) {
+ ap = host->ports[i];
+ ata_port_for_each_link(link, ap) {
+ ata_link_for_each_dev(dev, link)
+ ata_dev_disable_pm(dev);
+ }
+ }
+}
+
+static void ata_lpm_disable(struct ata_host *host)
+{
+ int i;
+
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
+ ata_lpm_schedule(ap, ap->pm_policy);
+ }
+}
+#endif /* CONFIG_PM */
+
+
/**
* ata_devchk - PATA device presence detection
* @ap: ATA channel to examine
@@ -713,7 +891,7 @@ unsigned int ata_dev_classify(const struct ata_taskfile *tf)
}
if ((tf->lbam == 0x3c) && (tf->lbah == 0xc3)) {
- printk("ata: SEMB device ignored\n");
+ printk(KERN_INFO "ata: SEMB device ignored\n");
return ATA_DEV_SEMB_UNSUP; /* not yet */
}
@@ -939,7 +1117,7 @@ static int ata_read_native_max_address(struct ata_device *dev, u64 *max_sectors)
*max_sectors = ata_tf_to_lba48(&tf);
else
*max_sectors = ata_tf_to_lba(&tf);
- if (dev->horkage & ATA_HORKAGE_HPA_SIZE)
+ if (dev->horkage & ATA_HORKAGE_HPA_SIZE)
(*max_sectors)--;
return 0;
}
@@ -1151,7 +1329,7 @@ void ata_id_to_dma_mode(struct ata_device *dev, u8 unknown)
* LOCKING:
* caller.
*/
-void ata_noop_dev_select (struct ata_port *ap, unsigned int device)
+void ata_noop_dev_select(struct ata_port *ap, unsigned int device)
{
}
@@ -1171,7 +1349,7 @@ void ata_noop_dev_select (struct ata_port *ap, unsigned int device)
* caller.
*/
-void ata_std_dev_select (struct ata_port *ap, unsigned int device)
+void ata_std_dev_select(struct ata_port *ap, unsigned int device)
{
u8 tmp;
@@ -1292,7 +1470,7 @@ static unsigned int ata_id_xfermask(const u16 *id)
*/
u8 mode = (id[ATA_ID_OLD_PIO_MODES] >> 8) & 0xFF;
if (mode < 5) /* Valid PIO range */
- pio_mask = (2 << mode) - 1;
+ pio_mask = (2 << mode) - 1;
else
pio_mask = 1;
@@ -1392,7 +1570,7 @@ static void ata_qc_complete_internal(struct ata_queued_cmd *qc)
* @tf: Taskfile registers for the command and the result
* @cdb: CDB for packet command
* @dma_dir: Data tranfer direction of the command
- * @sg: sg list for the data buffer of the command
+ * @sgl: sg list for the data buffer of the command
* @n_elem: Number of sg entries
* @timeout: Timeout in msecs (0 for default)
*
@@ -1410,7 +1588,7 @@ static void ata_qc_complete_internal(struct ata_queued_cmd *qc)
*/
unsigned ata_exec_internal_sg(struct ata_device *dev,
struct ata_taskfile *tf, const u8 *cdb,
- int dma_dir, struct scatterlist *sg,
+ int dma_dir, struct scatterlist *sgl,
unsigned int n_elem, unsigned long timeout)
{
struct ata_link *link = dev->link;
@@ -1472,11 +1650,12 @@ unsigned ata_exec_internal_sg(struct ata_device *dev,
qc->dma_dir = dma_dir;
if (dma_dir != DMA_NONE) {
unsigned int i, buflen = 0;
+ struct scatterlist *sg;
- for (i = 0; i < n_elem; i++)
- buflen += sg[i].length;
+ for_each_sg(sgl, sg, n_elem, i)
+ buflen += sg->length;
- ata_sg_init(qc, sg, n_elem);
+ ata_sg_init(qc, sgl, n_elem);
qc->nbytes = buflen;
}
@@ -1692,7 +1871,7 @@ static u32 ata_pio_mask_no_iordy(const struct ata_device *adev)
* for pre-ATA4 drives.
*
* FIXME: ATA_CMD_ID_ATA is optional for early drives and right
- * now we abort if we hit that case.
+ * now we abort if we hit that case.
*
* LOCKING:
* Kernel thread context (may sleep)
@@ -1798,13 +1977,7 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
* SET_FEATURES spin-up subcommand before it will accept
* anything other than the original IDENTIFY command.
*/
- ata_tf_init(dev, &tf);
- tf.command = ATA_CMD_SET_FEATURES;
- tf.feature = SETFEATURES_SPINUP;
- tf.protocol = ATA_PROT_NODATA;
- tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
- err_mask = ata_exec_internal(dev, &tf, NULL,
- DMA_NONE, NULL, 0, 0);
+ err_mask = ata_dev_set_feature(dev, SETFEATURES_SPINUP, 0);
if (err_mask && id[2] != 0x738c) {
rc = -EIO;
reason = "SPINUP failed";
@@ -1978,9 +2151,8 @@ int ata_dev_configure(struct ata_device *dev)
"supports DRM functions and may "
"not be fully accessable.\n");
snprintf(revbuf, 7, "CFA");
- }
- else
- snprintf(revbuf, 7, "ATA-%d", ata_id_major_version(id));
+ } else
+ snprintf(revbuf, 7, "ATA-%d", ata_id_major_version(id));
dev->n_sectors = ata_id_n_sectors(id);
@@ -2075,7 +2247,8 @@ int ata_dev_configure(struct ata_device *dev)
unsigned int err_mask;
/* issue SET feature command to turn this on */
- err_mask = ata_dev_set_AN(dev, SETFEATURES_SATA_ENABLE);
+ err_mask = ata_dev_set_feature(dev,
+ SETFEATURES_SATA_ENABLE, SATA_AN);
if (err_mask)
ata_dev_printk(dev, KERN_ERR,
"failed to enable ATAPI AN "
@@ -2105,11 +2278,18 @@ int ata_dev_configure(struct ata_device *dev)
if (dev->flags & ATA_DFLAG_LBA48)
dev->max_sectors = ATA_MAX_SECTORS_LBA48;
+ if (!(dev->horkage & ATA_HORKAGE_IPM)) {
+ if (ata_id_has_hipm(dev->id))
+ dev->flags |= ATA_DFLAG_HIPM;
+ if (ata_id_has_dipm(dev->id))
+ dev->flags |= ATA_DFLAG_DIPM;
+ }
+
if (dev->horkage & ATA_HORKAGE_DIAGNOSTIC) {
/* Let the user know. We don't want to disallow opens for
rescue purposes, or in case the vendor is just a blithering
idiot */
- if (print_info) {
+ if (print_info) {
ata_dev_printk(dev, KERN_WARNING,
"Drive reports diagnostics failure. This may indicate a drive\n");
ata_dev_printk(dev, KERN_WARNING,
@@ -2126,10 +2306,21 @@ int ata_dev_configure(struct ata_device *dev)
dev->max_sectors = ATA_MAX_SECTORS;
}
+ if ((dev->class == ATA_DEV_ATAPI) &&
+ (atapi_command_packet_set(id) == TYPE_TAPE))
+ dev->max_sectors = ATA_MAX_SECTORS_TAPE;
+
if (dev->horkage & ATA_HORKAGE_MAX_SEC_128)
dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128,
dev->max_sectors);
+ if (ata_dev_blacklisted(dev) & ATA_HORKAGE_IPM) {
+ dev->horkage |= ATA_HORKAGE_IPM;
+
+ /* reset link pm_policy for this port to no pm */
+ ap->pm_policy = MAX_PERFORMANCE;
+ }
+
if (ap->ops->dev_config)
ap->ops->dev_config(dev);
@@ -2223,6 +2414,25 @@ int ata_bus_probe(struct ata_port *ap)
tries[dev->devno] = ATA_PROBE_MAX_TRIES;
retry:
+ ata_link_for_each_dev(dev, &ap->link) {
+ /* If we issue an SRST then an ATA drive (not ATAPI)
+ * may change configuration and be in PIO0 timing. If
+ * we do a hard reset (or are coming from power on)
+ * this is true for ATA or ATAPI. Until we've set a
+ * suitable controller mode we should not touch the
+ * bus as we may be talking too fast.
+ */
+ dev->pio_mode = XFER_PIO_0;
+
+ /* If the controller has a pio mode setup function
+ * then use it to set the chipset to rights. Don't
+ * touch the DMA setup as that will be dealt with when
+ * configuring devices.
+ */
+ if (ap->ops->set_piomode)
+ ap->ops->set_piomode(ap, dev);
+ }
+
/* reset and determine device classes */
ap->ops->phy_reset(ap);
@@ -2238,12 +2448,6 @@ int ata_bus_probe(struct ata_port *ap)
ata_port_probe(ap);
- /* after the reset the device state is PIO 0 and the controller
- state is undefined. Record the mode */
-
- ata_link_for_each_dev(dev, &ap->link)
- dev->pio_mode = XFER_PIO_0;
-
/* read IDENTIFY page and configure devices. We have to do the identify
specific sequence bass-ackwards so that PDIAG- is released by
the slave device */
@@ -2549,17 +2753,27 @@ int sata_down_spd_limit(struct ata_link *link)
static int __sata_set_spd_needed(struct ata_link *link, u32 *scontrol)
{
- u32 spd, limit;
+ struct ata_link *host_link = &link->ap->link;
+ u32 limit, target, spd;
- if (link->sata_spd_limit == UINT_MAX)
- limit = 0;
+ limit = link->sata_spd_limit;
+
+ /* Don't configure downstream link faster than upstream link.
+ * It doesn't speed up anything and some PMPs choke on such
+ * configuration.
+ */
+ if (!ata_is_host_link(link) && host_link->sata_spd)
+ limit &= (1 << host_link->sata_spd) - 1;
+
+ if (limit == UINT_MAX)
+ target = 0;
else
- limit = fls(link->sata_spd_limit);
+ target = fls(limit);
spd = (*scontrol >> 4) & 0xf;
- *scontrol = (*scontrol & ~0xf0) | ((limit & 0xf) << 4);
+ *scontrol = (*scontrol & ~0xf0) | ((target & 0xf) << 4);
- return spd != limit;
+ return spd != target;
}
/**
@@ -2582,7 +2796,7 @@ int sata_set_spd_needed(struct ata_link *link)
u32 scontrol;
if (sata_scr_read(link, SCR_CONTROL, &scontrol))
- return 0;
+ return 1;
return __sata_set_spd_needed(link, &scontrol);
}
@@ -2666,8 +2880,8 @@ static const struct ata_timing ata_timing[] = {
{ 0xFF }
};
-#define ENOUGH(v,unit) (((v)-1)/(unit)+1)
-#define EZ(v,unit) ((v)?ENOUGH(v,unit):0)
+#define ENOUGH(v, unit) (((v)-1)/(unit)+1)
+#define EZ(v, unit) ((v)?ENOUGH(v, unit):0)
static void ata_timing_quantize(const struct ata_timing *t, struct ata_timing *q, int T, int UT)
{
@@ -2694,7 +2908,7 @@ void ata_timing_merge(const struct ata_timing *a, const struct ata_timing *b,
if (what & ATA_TIMING_UDMA ) m->udma = max(a->udma, b->udma);
}
-static const struct ata_timing* ata_timing_find_mode(unsigned short speed)
+static const struct ata_timing *ata_timing_find_mode(unsigned short speed)
{
const struct ata_timing *t;
@@ -2726,10 +2940,10 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed,
if (adev->id[ATA_ID_FIELD_VALID] & 2) { /* EIDE drive */
memset(&p, 0, sizeof(p));
- if(speed >= XFER_PIO_0 && speed <= XFER_SW_DMA_0) {
+ if (speed >= XFER_PIO_0 && speed <= XFER_SW_DMA_0) {
if (speed <= XFER_PIO_2) p.cycle = p.cyc8b = adev->id[ATA_ID_EIDE_PIO];
else p.cycle = p.cyc8b = adev->id[ATA_ID_EIDE_PIO_IORDY];
- } else if(speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2) {
+ } else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2) {
p.cycle = adev->id[ATA_ID_EIDE_DMA_MIN];
}
ata_timing_merge(&p, t, t, ATA_TIMING_CYCLE | ATA_TIMING_CYC8B);
@@ -2875,14 +3089,24 @@ static int ata_dev_set_mode(struct ata_device *dev)
dev->flags |= ATA_DFLAG_PIO;
err_mask = ata_dev_set_xfermode(dev);
+
/* Old CFA may refuse this command, which is just fine */
if (dev->xfer_shift == ATA_SHIFT_PIO && ata_id_is_cfa(dev->id))
- err_mask &= ~AC_ERR_DEV;
+ err_mask &= ~AC_ERR_DEV;
+
/* Some very old devices and some bad newer ones fail any kind of
SET_XFERMODE request but support PIO0-2 timings and no IORDY */
if (dev->xfer_shift == ATA_SHIFT_PIO && !ata_id_has_iordy(dev->id) &&
dev->pio_mode <= XFER_PIO_2)
err_mask &= ~AC_ERR_DEV;
+
+ /* Early MWDMA devices do DMA but don't allow DMA mode setting.
+ Don't fail an MWDMA0 set IFF the device indicates it is in MWDMA0 */
+ if (dev->xfer_shift == ATA_SHIFT_MWDMA &&
+ dev->dma_mode == XFER_MW_DMA_0 &&
+ (dev->id[63] >> 8) & 1)
+ err_mask &= ~AC_ERR_DEV;
+
if (err_mask) {
ata_dev_printk(dev, KERN_ERR, "failed to set xfermode "
"(err_mask=0x%x)\n", err_mask);
@@ -3112,6 +3336,61 @@ int ata_busy_sleep(struct ata_port *ap,
}
/**
+ * ata_wait_after_reset - wait before checking status after reset
+ * @ap: port containing status register to be polled
+ * @deadline: deadline jiffies for the operation
+ *
+ * After reset, we need to pause a while before reading status.
+ * Also, certain combination of controller and device report 0xff
+ * for some duration (e.g. until SATA PHY is up and running)
+ * which is interpreted as empty port in ATA world. This
+ * function also waits for such devices to get out of 0xff
+ * status.
+ *
+ * LOCKING:
+ * Kernel thread context (may sleep).
+ */
+void ata_wait_after_reset(struct ata_port *ap, unsigned long deadline)
+{
+ unsigned long until = jiffies + ATA_TMOUT_FF_WAIT;
+
+ if (time_before(until, deadline))
+ deadline = until;
+
+ /* Spec mandates ">= 2ms" before checking status. We wait
+ * 150ms, because that was the magic delay used for ATAPI
+ * devices in Hale Landis's ATADRVR, for the period of time
+ * between when the ATA command register is written, and then
+ * status is checked. Because waiting for "a while" before
+ * checking status is fine, post SRST, we perform this magic
+ * delay here as well.
+ *
+ * Old drivers/ide uses the 2mS rule and then waits for ready.
+ */
+ msleep(150);
+
+ /* Wait for 0xff to clear. Some SATA devices take a long time
+ * to clear 0xff after reset. For example, HHD424020F7SV00
+ * iVDR needs >= 800ms while. Quantum GoVault needs even more
+ * than that.
+ *
+ * Note that some PATA controllers (pata_ali) explode if
+ * status register is read more than once when there's no
+ * device attached.
+ */
+ if (ap->flags & ATA_FLAG_SATA) {
+ while (1) {
+ u8 status = ata_chk_status(ap);
+
+ if (status != 0xff || time_after(jiffies, deadline))
+ return;
+
+ msleep(50);
+ }
+ }
+}
+
+/**
* ata_wait_ready - sleep until BSY clears, or timeout
* @ap: port containing status register to be polled
* @deadline: deadline jiffies for the operation
@@ -3217,8 +3496,6 @@ static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask,
unsigned long deadline)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
- struct ata_device *dev;
- int i = 0;
DPRINTK("ata%u: bus reset via SRST\n", ap->print_id);
@@ -3229,42 +3506,14 @@ static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask,
udelay(20); /* FIXME: flush */
iowrite8(ap->ctl, ioaddr->ctl_addr);
- /* If we issued an SRST then an ATA drive (not ATAPI)
- * may have changed configuration and be in PIO0 timing. If
- * we did a hard reset (or are coming from power on) this is
- * true for ATA or ATAPI. Until we've set a suitable controller
- * mode we should not touch the bus as we may be talking too fast.
- */
-
- ata_link_for_each_dev(dev, &ap->link)
- dev->pio_mode = XFER_PIO_0;
-
- /* If the controller has a pio mode setup function then use
- it to set the chipset to rights. Don't touch the DMA setup
- as that will be dealt with when revalidating */
- if (ap->ops->set_piomode) {
- ata_link_for_each_dev(dev, &ap->link)
- if (devmask & (1 << i++))
- ap->ops->set_piomode(ap, dev);
- }
-
- /* spec mandates ">= 2ms" before checking status.
- * We wait 150ms, because that was the magic delay used for
- * ATAPI devices in Hale Landis's ATADRVR, for the period of time
- * between when the ATA command register is written, and then
- * status is checked. Because waiting for "a while" before
- * checking status is fine, post SRST, we perform this magic
- * delay here as well.
- *
- * Old drivers/ide uses the 2mS rule and then waits for ready
- */
- msleep(150);
+ /* wait a while before checking status */
+ ata_wait_after_reset(ap, deadline);
/* Before we perform post reset processing we want to see if
* the bus shows 0xFF because the odd clown forgets the D7
* pulldown resistor.
*/
- if (ata_check_status(ap) == 0xFF)
+ if (ata_chk_status(ap) == 0xFF)
return -ENODEV;
return ata_bus_post_reset(ap, devmask, deadline);
@@ -3685,8 +3934,8 @@ int sata_std_hardreset(struct ata_link *link, unsigned int *class,
return 0;
}
- /* wait a while before checking status, see SRST for more info */
- msleep(150);
+ /* wait a while before checking status */
+ ata_wait_after_reset(ap, deadline);
/* If PMP is supported, we have to do follow-up SRST. Note
* that some PMPs don't send D2H Reg FIS after hardreset at
@@ -3942,11 +4191,8 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ "SAMSUNG CD-ROM SC", NULL, ATA_HORKAGE_NODMA },
{ "ATAPI CD-ROM DRIVE 40X MAXIMUM",NULL,ATA_HORKAGE_NODMA },
{ "_NEC DV5800A", NULL, ATA_HORKAGE_NODMA },
- { "SAMSUNG CD-ROM SN-124","N001", ATA_HORKAGE_NODMA },
+ { "SAMSUNG CD-ROM SN-124", "N001", ATA_HORKAGE_NODMA },
{ "Seagate STT20000A", NULL, ATA_HORKAGE_NODMA },
- { "IOMEGA ZIP 250 ATAPI", NULL, ATA_HORKAGE_NODMA }, /* temporary fix */
- { "IOMEGA ZIP 250 ATAPI Floppy",
- NULL, ATA_HORKAGE_NODMA },
/* Odd clown on sil3726/4726 PMPs */
{ "Config Disk", NULL, ATA_HORKAGE_NODMA |
ATA_HORKAGE_SKIP_PM },
@@ -3958,7 +4204,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
/* Devices where NCQ should be avoided */
/* NCQ is slow */
- { "WDC WD740ADFD-00", NULL, ATA_HORKAGE_NONCQ },
+ { "WDC WD740ADFD-00", NULL, ATA_HORKAGE_NONCQ },
/* http://thread.gmane.org/gmane.linux.ide/14907 */
{ "FUJITSU MHT2060BH", NULL, ATA_HORKAGE_NONCQ },
/* NCQ is broken */
@@ -3978,15 +4224,18 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ "HTS541612J9SA00", "SBDIC7JP", ATA_HORKAGE_NONCQ, },
{ "HDT722516DLA380", "V43OA96A", ATA_HORKAGE_NONCQ, },
{ "Hitachi HTS541616J9SA00", "SB4OC70P", ATA_HORKAGE_NONCQ, },
+ { "Hitachi HTS542525K9SA00", "BBFOC31P", ATA_HORKAGE_NONCQ, },
{ "WDC WD740ADFD-00NLR1", NULL, ATA_HORKAGE_NONCQ, },
{ "WDC WD3200AAJS-00RYA0", "12.01B01", ATA_HORKAGE_NONCQ, },
{ "FUJITSU MHV2080BH", "00840028", ATA_HORKAGE_NONCQ, },
{ "ST9120822AS", "3.CLF", ATA_HORKAGE_NONCQ, },
{ "ST9160821AS", "3.CLF", ATA_HORKAGE_NONCQ, },
{ "ST9160821AS", "3.ALD", ATA_HORKAGE_NONCQ, },
+ { "ST9160821AS", "3.CCD", ATA_HORKAGE_NONCQ, },
{ "ST3160812AS", "3.ADJ", ATA_HORKAGE_NONCQ, },
{ "ST980813AS", "3.ADB", ATA_HORKAGE_NONCQ, },
{ "SAMSUNG HD401LJ", "ZZ100-15", ATA_HORKAGE_NONCQ, },
+ { "Maxtor 7V300F0", "VA111900", ATA_HORKAGE_NONCQ, },
/* devices which puke on READ_NATIVE_MAX */
{ "HDS724040KLSA80", "KFAOA20N", ATA_HORKAGE_BROKEN_HPA, },
@@ -3998,11 +4247,15 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ "ST340823A", NULL, ATA_HORKAGE_HPA_SIZE, },
{ "ST320413A", NULL, ATA_HORKAGE_HPA_SIZE, },
+ /* Devices which get the IVB wrong */
+ { "QUANTUM FIREBALLlct10 05", "A03.0900", ATA_HORKAGE_IVB, },
+ { "TSSTcorp CDDVDW SH-S202J", "SB00", ATA_HORKAGE_IVB, },
+
/* End Marker */
{ }
};
-int strn_pattern_cmp(const char *patt, const char *name, int wildchar)
+static int strn_pattern_cmp(const char *patt, const char *name, int wildchar)
{
const char *p;
int len;
@@ -4013,8 +4266,14 @@ int strn_pattern_cmp(const char *patt, const char *name, int wildchar)
p = strchr(patt, wildchar);
if (p && ((*(p + 1)) == 0))
len = p - patt;
- else
+ else {
len = strlen(name);
+ if (!len) {
+ if (!*patt)
+ return 0;
+ return -1;
+ }
+ }
return strncmp(patt, name, len);
}
@@ -4053,6 +4312,21 @@ static int ata_dma_blacklisted(const struct ata_device *dev)
}
/**
+ * ata_is_40wire - check drive side detection
+ * @dev: device
+ *
+ * Perform drive side detection decoding, allowing for device vendors
+ * who can't follow the documentation.
+ */
+
+static int ata_is_40wire(struct ata_device *dev)
+{
+ if (dev->horkage & ATA_HORKAGE_IVB)
+ return ata_drive_40wire_relaxed(dev->id);
+ return ata_drive_40wire(dev->id);
+}
+
+/**
* ata_dev_xfermask - Compute supported xfermask of the given device
* @dev: Device to compute xfermask for
*
@@ -4098,7 +4372,7 @@ static void ata_dev_xfermask(struct ata_device *dev)
}
if ((host->flags & ATA_HOST_SIMPLEX) &&
- host->simplex_claimed && host->simplex_claimed != ap) {
+ host->simplex_claimed && host->simplex_claimed != ap) {
xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
ata_dev_printk(dev, KERN_WARNING, "simplex DMA is claimed by "
"other device, disabling DMA\n");
@@ -4120,11 +4394,11 @@ static void ata_dev_xfermask(struct ata_device *dev)
*/
if (xfer_mask & (0xF8 << ATA_SHIFT_UDMA))
/* UDMA/44 or higher would be available */
- if((ap->cbl == ATA_CBL_PATA40) ||
- (ata_drive_40wire(dev->id) &&
- (ap->cbl == ATA_CBL_PATA_UNK ||
- ap->cbl == ATA_CBL_PATA80))) {
- ata_dev_printk(dev, KERN_WARNING,
+ if ((ap->cbl == ATA_CBL_PATA40) ||
+ (ata_is_40wire(dev) &&
+ (ap->cbl == ATA_CBL_PATA_UNK ||
+ ap->cbl == ATA_CBL_PATA80))) {
+ ata_dev_printk(dev, KERN_WARNING,
"limited to UDMA/33 due to 40-wire cable\n");
xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA);
}
@@ -4170,15 +4444,14 @@ static unsigned int ata_dev_set_xfermode(struct ata_device *dev)
DPRINTK("EXIT, err_mask=%x\n", err_mask);
return err_mask;
}
-
/**
- * ata_dev_set_AN - Issue SET FEATURES - SATA FEATURES
+ * ata_dev_set_feature - Issue SET FEATURES - SATA FEATURES
* @dev: Device to which command will be sent
* @enable: Whether to enable or disable the feature
+ * @feature: The sector count represents the feature to set
*
* Issue SET FEATURES - SATA FEATURES command to device @dev
- * on port @ap with sector count set to indicate Asynchronous
- * Notification feature
+ * on port @ap with sector count
*
* LOCKING:
* PCI/etc. bus probe sem.
@@ -4186,7 +4459,8 @@ static unsigned int ata_dev_set_xfermode(struct ata_device *dev)
* RETURNS:
* 0 on success, AC_ERR_* mask otherwise.
*/
-static unsigned int ata_dev_set_AN(struct ata_device *dev, u8 enable)
+static unsigned int ata_dev_set_feature(struct ata_device *dev, u8 enable,
+ u8 feature)
{
struct ata_taskfile tf;
unsigned int err_mask;
@@ -4199,7 +4473,7 @@ static unsigned int ata_dev_set_AN(struct ata_device *dev, u8 enable)
tf.feature = enable;
tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
tf.protocol = ATA_PROT_NODATA;
- tf.nsect = SATA_AN;
+ tf.nsect = feature;
err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
@@ -4285,10 +4559,10 @@ void ata_sg_clean(struct ata_queued_cmd *qc)
if (qc->n_elem)
dma_unmap_sg(ap->dev, sg, qc->n_elem, dir);
/* restore last sg */
- sg[qc->orig_n_elem - 1].length += qc->pad_len;
+ sg_last(sg, qc->orig_n_elem)->length += qc->pad_len;
if (pad_buf) {
struct scatterlist *psg = &qc->pad_sgent;
- void *addr = kmap_atomic(psg->page, KM_IRQ0);
+ void *addr = kmap_atomic(sg_page(psg), KM_IRQ0);
memcpy(addr + psg->offset, pad_buf, qc->pad_len);
kunmap_atomic(addr, KM_IRQ0);
}
@@ -4387,7 +4661,7 @@ static void ata_fill_sg_dumb(struct ata_queued_cmd *qc)
u32 addr, offset;
u32 sg_len, len, blen;
- /* determine if physical DMA addr spans 64K boundary.
+ /* determine if physical DMA addr spans 64K boundary.
* Note h/w doesn't support 64-bit, so we unconditionally
* truncate dma_addr_t to u32.
*/
@@ -4540,6 +4814,7 @@ void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen)
qc->orig_n_elem = 1;
qc->buf_virt = buf;
qc->nbytes = buflen;
+ qc->cursg = qc->__sg;
sg_init_one(&qc->sgent, buf, buflen);
}
@@ -4565,6 +4840,7 @@ void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
qc->__sg = sg;
qc->n_elem = n_elem;
qc->orig_n_elem = n_elem;
+ qc->cursg = qc->__sg;
}
/**
@@ -4654,7 +4930,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
struct scatterlist *sg = qc->__sg;
- struct scatterlist *lsg = &sg[qc->n_elem - 1];
+ struct scatterlist *lsg = sg_last(qc->__sg, qc->n_elem);
int n_elem, pre_n_elem, dir, trim_sg = 0;
VPRINTK("ENTER, ata%u\n", ap->print_id);
@@ -4676,11 +4952,12 @@ static int ata_sg_setup(struct ata_queued_cmd *qc)
* data in this function or read data in ata_sg_clean.
*/
offset = lsg->offset + lsg->length - qc->pad_len;
- psg->page = nth_page(lsg->page, offset >> PAGE_SHIFT);
- psg->offset = offset_in_page(offset);
+ sg_init_table(psg, 1);
+ sg_set_page(psg, nth_page(sg_page(lsg), offset >> PAGE_SHIFT),
+ qc->pad_len, offset_in_page(offset));
if (qc->tf.flags & ATA_TFLAG_WRITE) {
- void *addr = kmap_atomic(psg->page, KM_IRQ0);
+ void *addr = kmap_atomic(sg_page(psg), KM_IRQ0);
memcpy(pad_buf, addr + psg->offset, qc->pad_len);
kunmap_atomic(addr, KM_IRQ0);
}
@@ -4818,7 +5095,6 @@ void ata_data_xfer_noirq(struct ata_device *adev, unsigned char *buf,
static void ata_pio_sector(struct ata_queued_cmd *qc)
{
int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
- struct scatterlist *sg = qc->__sg;
struct ata_port *ap = qc->ap;
struct page *page;
unsigned int offset;
@@ -4827,8 +5103,8 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
if (qc->curbytes == qc->nbytes - qc->sect_size)
ap->hsm_task_state = HSM_ST_LAST;
- page = sg[qc->cursg].page;
- offset = sg[qc->cursg].offset + qc->cursg_ofs;
+ page = sg_page(qc->cursg);
+ offset = qc->cursg->offset + qc->cursg_ofs;
/* get the current page and offset */
page = nth_page(page, (offset >> PAGE_SHIFT));
@@ -4856,8 +5132,8 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
qc->curbytes += qc->sect_size;
qc->cursg_ofs += qc->sect_size;
- if (qc->cursg_ofs == (&sg[qc->cursg])->length) {
- qc->cursg++;
+ if (qc->cursg_ofs == qc->cursg->length) {
+ qc->cursg = sg_next(qc->cursg);
qc->cursg_ofs = 0;
}
}
@@ -4943,16 +5219,18 @@ static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
{
int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
struct scatterlist *sg = qc->__sg;
+ struct scatterlist *lsg = sg_last(qc->__sg, qc->n_elem);
struct ata_port *ap = qc->ap;
struct page *page;
unsigned char *buf;
unsigned int offset, count;
+ int no_more_sg = 0;
if (qc->curbytes + bytes >= qc->nbytes)
ap->hsm_task_state = HSM_ST_LAST;
next_sg:
- if (unlikely(qc->cursg >= qc->n_elem)) {
+ if (unlikely(no_more_sg)) {
/*
* The end of qc->sg is reached and the device expects
* more data to transfer. In order not to overrun qc->sg
@@ -4969,15 +5247,15 @@ next_sg:
"%u bytes trailing data\n", bytes);
for (i = 0; i < words; i++)
- ap->ops->data_xfer(qc->dev, (unsigned char*)pad_buf, 2, do_write);
+ ap->ops->data_xfer(qc->dev, (unsigned char *)pad_buf, 2, do_write);
ap->hsm_task_state = HSM_ST_LAST;
return;
}
- sg = &qc->__sg[qc->cursg];
+ sg = qc->cursg;
- page = sg->page;
+ page = sg_page(sg);
offset = sg->offset + qc->cursg_ofs;
/* get the current page and offset */
@@ -5014,7 +5292,10 @@ next_sg:
qc->cursg_ofs += count;
if (qc->cursg_ofs == sg->length) {
- qc->cursg++;
+ if (qc->cursg == lsg)
+ no_more_sg = 1;
+
+ qc->cursg = sg_next(qc->cursg);
qc->cursg_ofs = 0;
}
@@ -5577,6 +5858,9 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
* taken care of.
*/
if (ap->ops->error_handler) {
+ struct ata_device *dev = qc->dev;
+ struct ata_eh_info *ehi = &dev->link->eh_info;
+
WARN_ON(ap->pflags & ATA_PFLAG_FROZEN);
if (unlikely(qc->err_mask))
@@ -5595,6 +5879,27 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
if (qc->flags & ATA_QCFLAG_RESULT_TF)
fill_result_tf(qc);
+ /* Some commands need post-processing after successful
+ * completion.
+ */
+ switch (qc->tf.command) {
+ case ATA_CMD_SET_FEATURES:
+ if (qc->tf.feature != SETFEATURES_WC_ON &&
+ qc->tf.feature != SETFEATURES_WC_OFF)
+ break;
+ /* fall through */
+ case ATA_CMD_INIT_DEV_PARAMS: /* CHS translation changed */
+ case ATA_CMD_SET_MULTI: /* multi_count changed */
+ /* revalidate device */
+ ehi->dev_action[dev->devno] |= ATA_EH_REVALIDATE;
+ ata_port_schedule_eh(ap);
+ break;
+
+ case ATA_CMD_SLEEP:
+ dev->flags |= ATA_DFLAG_SLEEPING;
+ break;
+ }
+
__ata_qc_complete(qc);
} else {
if (qc->flags & ATA_QCFLAG_EH_SCHEDULED)
@@ -5732,6 +6037,14 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
qc->flags &= ~ATA_QCFLAG_DMAMAP;
}
+ /* if device is sleeping, schedule softreset and abort the link */
+ if (unlikely(qc->dev->flags & ATA_DFLAG_SLEEPING)) {
+ link->eh_info.action |= ATA_EH_SOFTRESET;
+ ata_ehi_push_desc(&link->eh_info, "waking up from sleep");
+ ata_link_abort(link);
+ return;
+ }
+
ap->ops->qc_prep(qc);
qc->err_mask |= ap->ops->qc_issue(qc);
@@ -5894,8 +6207,8 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
* One if interrupt was handled, zero if not (shared irq).
*/
-inline unsigned int ata_host_intr (struct ata_port *ap,
- struct ata_queued_cmd *qc)
+inline unsigned int ata_host_intr(struct ata_port *ap,
+ struct ata_queued_cmd *qc)
{
struct ata_eh_info *ehi = &ap->link.eh_info;
u8 status, host_stat = 0;
@@ -5995,7 +6308,7 @@ idle_irq:
* IRQ_NONE or IRQ_HANDLED.
*/
-irqreturn_t ata_interrupt (int irq, void *dev_instance)
+irqreturn_t ata_interrupt(int irq, void *dev_instance)
{
struct ata_host *host = dev_instance;
unsigned int i;
@@ -6198,7 +6511,7 @@ int ata_flush_cache(struct ata_device *dev)
/* This is wrong. On a failed flush we get back the LBA of the lost
sector and we should (assuming it wasn't aborted as unknown) issue
- a further flush command to continue the writeback until it
+ a further flush command to continue the writeback until it
does not error */
err_mask = ata_do_simple_cmd(dev, cmd);
if (err_mask) {
@@ -6279,6 +6592,12 @@ int ata_host_suspend(struct ata_host *host, pm_message_t mesg)
{
int rc;
+ /*
+ * disable link pm on all ports before requesting
+ * any pm activity
+ */
+ ata_lpm_enable(host);
+
rc = ata_host_request_pm(host, mesg, 0, ATA_EHI_QUIET, 1);
if (rc == 0)
host->dev->power.power_state = mesg;
@@ -6301,6 +6620,9 @@ void ata_host_resume(struct ata_host *host)
ata_host_request_pm(host, PMSG_ON, ATA_EH_SOFTRESET,
ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, 0);
host->dev->power.power_state = PMSG_ON;
+
+ /* reenable link pm */
+ ata_lpm_disable(host);
}
#endif
@@ -6505,19 +6827,6 @@ static void ata_host_release(struct device *gendev, void *res)
if (!ap)
continue;
- if ((host->flags & ATA_HOST_STARTED) && ap->ops->port_stop)
- ap->ops->port_stop(ap);
- }
-
- if ((host->flags & ATA_HOST_STARTED) && host->ops->host_stop)
- host->ops->host_stop(host);
-
- for (i = 0; i < host->n_ports; i++) {
- struct ata_port *ap = host->ports[i];
-
- if (!ap)
- continue;
-
if (ap->scsi_host)
scsi_host_put(ap->scsi_host);
@@ -6644,6 +6953,24 @@ struct ata_host *ata_host_alloc_pinfo(struct device *dev,
return host;
}
+static void ata_host_stop(struct device *gendev, void *res)
+{
+ struct ata_host *host = dev_get_drvdata(gendev);
+ int i;
+
+ WARN_ON(!(host->flags & ATA_HOST_STARTED));
+
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
+
+ if (ap->ops->port_stop)
+ ap->ops->port_stop(ap);
+ }
+
+ if (host->ops->host_stop)
+ host->ops->host_stop(host);
+}
+
/**
* ata_host_start - start and freeze ports of an ATA host
* @host: ATA host to start ports for
@@ -6662,6 +6989,8 @@ struct ata_host *ata_host_alloc_pinfo(struct device *dev,
*/
int ata_host_start(struct ata_host *host)
{
+ int have_stop = 0;
+ void *start_dr = NULL;
int i, rc;
if (host->flags & ATA_HOST_STARTED)
@@ -6673,6 +7002,22 @@ int ata_host_start(struct ata_host *host)
if (!host->ops && !ata_port_is_dummy(ap))
host->ops = ap->ops;
+ if (ap->ops->port_stop)
+ have_stop = 1;
+ }
+
+ if (host->ops->host_stop)
+ have_stop = 1;
+
+ if (have_stop) {
+ start_dr = devres_alloc(ata_host_stop, 0, GFP_KERNEL);
+ if (!start_dr)
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
+
if (ap->ops->port_start) {
rc = ap->ops->port_start(ap);
if (rc) {
@@ -6685,6 +7030,8 @@ int ata_host_start(struct ata_host *host)
ata_eh_freeze_port(ap);
}
+ if (start_dr)
+ devres_add(host->dev, start_dr);
host->flags |= ATA_HOST_STARTED;
return 0;
@@ -6695,6 +7042,7 @@ int ata_host_start(struct ata_host *host)
if (ap->ops->port_stop)
ap->ops->port_stop(ap);
}
+ devres_free(start_dr);
return rc;
}
@@ -6843,6 +7191,7 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
struct ata_port *ap = host->ports[i];
ata_scsi_scan_host(ap, 1);
+ ata_lpm_schedule(ap, ap->pm_policy);
}
return 0;
@@ -6861,6 +7210,10 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
* request IRQ and register it. This helper takes necessasry
* arguments and performs the three steps in one go.
*
+ * An invalid IRQ skips the IRQ registration and expects the host to
+ * have set polling mode on the port. In this case, @irq_handler
+ * should be NULL.
+ *
* LOCKING:
* Inherited from calling layer (may sleep).
*
@@ -6877,6 +7230,12 @@ int ata_host_activate(struct ata_host *host, int irq,
if (rc)
return rc;
+ /* Special case for polling mode */
+ if (!irq) {
+ WARN_ON(irq_handler);
+ return ata_host_register(host, sht);
+ }
+
rc = devm_request_irq(host->dev, irq, irq_handler, irq_flags,
dev_driver_string(host->dev), host);
if (rc)
@@ -6904,7 +7263,7 @@ int ata_host_activate(struct ata_host *host, int irq,
* LOCKING:
* Kernel thread context (may sleep).
*/
-void ata_port_detach(struct ata_port *ap)
+static void ata_port_detach(struct ata_port *ap)
{
unsigned long flags;
struct ata_link *link;
@@ -7239,7 +7598,6 @@ const struct ata_port_info ata_dummy_port_info = {
* likely to change as new drivers are added and updated.
* Do not depend on ABI/API stability.
*/
-
EXPORT_SYMBOL_GPL(sata_deb_timing_normal);
EXPORT_SYMBOL_GPL(sata_deb_timing_hotplug);
EXPORT_SYMBOL_GPL(sata_deb_timing_long);
@@ -7309,6 +7667,7 @@ EXPORT_SYMBOL_GPL(ata_port_disable);
EXPORT_SYMBOL_GPL(ata_ratelimit);
EXPORT_SYMBOL_GPL(ata_wait_register);
EXPORT_SYMBOL_GPL(ata_busy_sleep);
+EXPORT_SYMBOL_GPL(ata_wait_after_reset);
EXPORT_SYMBOL_GPL(ata_wait_ready);
EXPORT_SYMBOL_GPL(ata_port_queue_task);
EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 2eaa39fc65d0..ed8813b222a0 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1197,7 +1197,7 @@ void ata_eh_done(struct ata_link *link, struct ata_device *dev,
* RETURNS:
* Descriptive string for @err_mask
*/
-static const char * ata_err_string(unsigned int err_mask)
+static const char *ata_err_string(unsigned int err_mask)
{
if (err_mask & AC_ERR_HOST_BUS)
return "host bus error";
@@ -1747,6 +1747,7 @@ static void ata_eh_link_autopsy(struct ata_link *link)
{
struct ata_port *ap = link->ap;
struct ata_eh_context *ehc = &link->eh_context;
+ struct ata_device *dev;
unsigned int all_err_mask = 0;
int tag, is_io = 0;
u32 serror;
@@ -1800,10 +1801,8 @@ static void ata_eh_link_autopsy(struct ata_link *link)
qc->err_mask &= ~AC_ERR_OTHER;
/* SENSE_VALID trumps dev/unknown error and revalidation */
- if (qc->flags & ATA_QCFLAG_SENSE_VALID) {
+ if (qc->flags & ATA_QCFLAG_SENSE_VALID)
qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER);
- ehc->i.action &= ~ATA_EH_REVALIDATE;
- }
/* accumulate error info */
ehc->i.dev = qc->dev;
@@ -1816,21 +1815,28 @@ static void ata_eh_link_autopsy(struct ata_link *link)
if (ap->pflags & ATA_PFLAG_FROZEN ||
all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT))
ehc->i.action |= ATA_EH_SOFTRESET;
- else if (all_err_mask)
+ else if ((is_io && all_err_mask) ||
+ (!is_io && (all_err_mask & ~AC_ERR_DEV)))
ehc->i.action |= ATA_EH_REVALIDATE;
- /* if we have offending qcs and the associated failed device */
+ /* If we have offending qcs and the associated failed device,
+ * perform per-dev EH action only on the offending device.
+ */
if (ehc->i.dev) {
- /* speed down */
- ehc->i.action |= ata_eh_speed_down(ehc->i.dev, is_io,
- all_err_mask);
-
- /* perform per-dev EH action only on the offending device */
ehc->i.dev_action[ehc->i.dev->devno] |=
ehc->i.action & ATA_EH_PERDEV_MASK;
ehc->i.action &= ~ATA_EH_PERDEV_MASK;
}
+ /* consider speeding down */
+ dev = ehc->i.dev;
+ if (!dev && ata_link_max_devices(link) == 1 &&
+ ata_dev_enabled(link->device))
+ dev = link->device;
+
+ if (dev)
+ ehc->i.action |= ata_eh_speed_down(dev, is_io, all_err_mask);
+
DPRINTK("EXIT\n");
}
@@ -1879,7 +1885,9 @@ static void ata_eh_link_report(struct ata_link *link)
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
- if (!(qc->flags & ATA_QCFLAG_FAILED) || qc->dev->link != link)
+ if (!(qc->flags & ATA_QCFLAG_FAILED) || qc->dev->link != link ||
+ ((qc->flags & ATA_QCFLAG_QUIET) &&
+ qc->err_mask == AC_ERR_DEV))
continue;
if (qc->flags & ATA_QCFLAG_SENSE_VALID && !qc->err_mask)
continue;
@@ -1934,7 +1942,7 @@ static void ata_eh_link_report(struct ata_link *link)
ehc->i.serror & SERR_LINK_SEQ_ERR ? "LinkSeq " : "",
ehc->i.serror & SERR_TRANS_ST_ERROR ? "TrStaTrns " : "",
ehc->i.serror & SERR_UNRECOG_FIS ? "UnrecFIS " : "",
- ehc->i.serror & SERR_DEV_XCHG ? "DevExch " : "" );
+ ehc->i.serror & SERR_DEV_XCHG ? "DevExch " : "");
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
static const char *dma_str[] = {
@@ -1969,17 +1977,17 @@ static void ata_eh_link_report(struct ata_link *link)
qc->err_mask & AC_ERR_NCQ ? " <F>" : "");
if (res->command & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ |
- ATA_ERR) ) {
+ ATA_ERR)) {
if (res->command & ATA_BUSY)
ata_dev_printk(qc->dev, KERN_ERR,
- "status: { Busy }\n" );
+ "status: { Busy }\n");
else
ata_dev_printk(qc->dev, KERN_ERR,
"status: { %s%s%s%s}\n",
res->command & ATA_DRDY ? "DRDY " : "",
res->command & ATA_DF ? "DF " : "",
res->command & ATA_DRQ ? "DRQ " : "",
- res->command & ATA_ERR ? "ERR " : "" );
+ res->command & ATA_ERR ? "ERR " : "");
}
if (cmd->command != ATA_CMD_PACKET &&
@@ -1990,7 +1998,7 @@ static void ata_eh_link_report(struct ata_link *link)
res->feature & ATA_ICRC ? "ICRC " : "",
res->feature & ATA_UNC ? "UNC " : "",
res->feature & ATA_IDNF ? "IDNF " : "",
- res->feature & ATA_ABORTED ? "ABRT " : "" );
+ res->feature & ATA_ABORTED ? "ABRT " : "");
}
}
@@ -2064,16 +2072,19 @@ int ata_eh_reset(struct ata_link *link, int classify,
ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
ata_reset_fn_t hardreset, ata_postreset_fn_t postreset)
{
+ const int max_tries = ARRAY_SIZE(ata_eh_reset_timeouts);
struct ata_port *ap = link->ap;
struct ata_eh_context *ehc = &link->eh_context;
unsigned int *classes = ehc->classes;
+ unsigned int lflags = link->flags;
int verbose = !(ehc->i.flags & ATA_EHI_QUIET);
int try = 0;
struct ata_device *dev;
- unsigned long deadline;
- unsigned int action;
+ unsigned long deadline, now;
+ unsigned int tmp_action;
ata_reset_fn_t reset;
unsigned long flags;
+ u32 sstatus;
int rc;
/* about to reset */
@@ -2083,17 +2094,36 @@ int ata_eh_reset(struct ata_link *link, int classify,
ata_eh_about_to_do(link, NULL, ehc->i.action & ATA_EH_RESET_MASK);
+ ata_link_for_each_dev(dev, link) {
+ /* If we issue an SRST then an ATA drive (not ATAPI)
+ * may change configuration and be in PIO0 timing. If
+ * we do a hard reset (or are coming from power on)
+ * this is true for ATA or ATAPI. Until we've set a
+ * suitable controller mode we should not touch the
+ * bus as we may be talking too fast.
+ */
+ dev->pio_mode = XFER_PIO_0;
+
+ /* If the controller has a pio mode setup function
+ * then use it to set the chipset to rights. Don't
+ * touch the DMA setup as that will be dealt with when
+ * configuring devices.
+ */
+ if (ap->ops->set_piomode)
+ ap->ops->set_piomode(ap, dev);
+ }
+
/* Determine which reset to use and record in ehc->i.action.
* prereset() may examine and modify it.
*/
- action = ehc->i.action;
- ehc->i.action &= ~ATA_EH_RESET_MASK;
- if (softreset && (!hardreset || (!(link->flags & ATA_LFLAG_NO_SRST) &&
+ if (softreset && (!hardreset || (!(lflags & ATA_LFLAG_NO_SRST) &&
!sata_set_spd_needed(link) &&
- !(action & ATA_EH_HARDRESET))))
- ehc->i.action |= ATA_EH_SOFTRESET;
+ !(ehc->i.action & ATA_EH_HARDRESET))))
+ tmp_action = ATA_EH_SOFTRESET;
else
- ehc->i.action |= ATA_EH_HARDRESET;
+ tmp_action = ATA_EH_HARDRESET;
+
+ ehc->i.action = (ehc->i.action & ~ATA_EH_RESET_MASK) | tmp_action;
if (prereset) {
rc = prereset(link, jiffies + ATA_EH_PRERESET_TIMEOUT);
@@ -2161,80 +2191,64 @@ int ata_eh_reset(struct ata_link *link, int classify,
"follow-up softreset required "
"but no softreset avaliable\n");
rc = -EINVAL;
- goto out;
+ goto fail;
}
ata_eh_about_to_do(link, NULL, ATA_EH_RESET_MASK);
rc = ata_do_reset(link, reset, classes, deadline);
-
- if (rc == 0 && classify && classes[0] == ATA_DEV_UNKNOWN &&
- !(link->flags & ATA_LFLAG_ASSUME_CLASS)) {
- ata_link_printk(link, KERN_ERR,
- "classification failed\n");
- rc = -EINVAL;
- goto out;
- }
}
- /* if we skipped follow-up srst, clear rc */
- if (rc == -EAGAIN)
- rc = 0;
-
- if (rc && rc != -ERESTART && try < ARRAY_SIZE(ata_eh_reset_timeouts)) {
- unsigned long now = jiffies;
-
- if (time_before(now, deadline)) {
- unsigned long delta = deadline - jiffies;
-
- ata_link_printk(link, KERN_WARNING, "reset failed "
- "(errno=%d), retrying in %u secs\n",
- rc, (jiffies_to_msecs(delta) + 999) / 1000);
+ /* -EAGAIN can happen if we skipped followup SRST */
+ if (rc && rc != -EAGAIN)
+ goto fail;
- while (delta)
- delta = schedule_timeout_uninterruptible(delta);
+ /* was classification successful? */
+ if (classify && classes[0] == ATA_DEV_UNKNOWN &&
+ !(lflags & ATA_LFLAG_ASSUME_CLASS)) {
+ if (try < max_tries) {
+ ata_link_printk(link, KERN_WARNING,
+ "classification failed\n");
+ rc = -EINVAL;
+ goto fail;
}
- if (rc == -EPIPE ||
- try == ARRAY_SIZE(ata_eh_reset_timeouts) - 1)
- sata_down_spd_limit(link);
- if (hardreset)
- reset = hardreset;
- goto retry;
+ ata_link_printk(link, KERN_WARNING,
+ "classfication failed, assuming ATA\n");
+ lflags |= ATA_LFLAG_ASSUME_ATA;
}
- if (rc == 0) {
- u32 sstatus;
+ ata_link_for_each_dev(dev, link) {
+ /* After the reset, the device state is PIO 0 and the
+ * controller state is undefined. Reset also wakes up
+ * drives from sleeping mode.
+ */
+ dev->pio_mode = XFER_PIO_0;
+ dev->flags &= ~ATA_DFLAG_SLEEPING;
- ata_link_for_each_dev(dev, link) {
- /* After the reset, the device state is PIO 0
- * and the controller state is undefined.
- * Record the mode.
- */
- dev->pio_mode = XFER_PIO_0;
+ if (ata_link_offline(link))
+ continue;
- if (ata_link_offline(link))
- continue;
+ /* apply class override and convert UNKNOWN to NONE */
+ if (lflags & ATA_LFLAG_ASSUME_ATA)
+ classes[dev->devno] = ATA_DEV_ATA;
+ else if (lflags & ATA_LFLAG_ASSUME_SEMB)
+ classes[dev->devno] = ATA_DEV_SEMB_UNSUP; /* not yet */
+ else if (classes[dev->devno] == ATA_DEV_UNKNOWN)
+ classes[dev->devno] = ATA_DEV_NONE;
+ }
- /* apply class override and convert UNKNOWN to NONE */
- if (link->flags & ATA_LFLAG_ASSUME_ATA)
- classes[dev->devno] = ATA_DEV_ATA;
- else if (link->flags & ATA_LFLAG_ASSUME_SEMB)
- classes[dev->devno] = ATA_DEV_SEMB_UNSUP; /* not yet */
- else if (classes[dev->devno] == ATA_DEV_UNKNOWN)
- classes[dev->devno] = ATA_DEV_NONE;
- }
+ /* record current link speed */
+ if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0)
+ link->sata_spd = (sstatus >> 4) & 0xf;
- /* record current link speed */
- if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0)
- link->sata_spd = (sstatus >> 4) & 0xf;
+ if (postreset)
+ postreset(link, classes);
- if (postreset)
- postreset(link, classes);
+ /* reset successful, schedule revalidation */
+ ata_eh_done(link, NULL, ehc->i.action & ATA_EH_RESET_MASK);
+ ehc->i.action |= ATA_EH_REVALIDATE;
- /* reset successful, schedule revalidation */
- ata_eh_done(link, NULL, ehc->i.action & ATA_EH_RESET_MASK);
- ehc->i.action |= ATA_EH_REVALIDATE;
- }
+ rc = 0;
out:
/* clear hotplug flag */
ehc->i.flags &= ~ATA_EHI_HOTPLUGGED;
@@ -2244,6 +2258,28 @@ int ata_eh_reset(struct ata_link *link, int classify,
spin_unlock_irqrestore(ap->lock, flags);
return rc;
+
+ fail:
+ if (rc == -ERESTART || try >= max_tries)
+ goto out;
+
+ now = jiffies;
+ if (time_before(now, deadline)) {
+ unsigned long delta = deadline - now;
+
+ ata_link_printk(link, KERN_WARNING, "reset failed "
+ "(errno=%d), retrying in %u secs\n",
+ rc, (jiffies_to_msecs(delta) + 999) / 1000);
+
+ while (delta)
+ delta = schedule_timeout_uninterruptible(delta);
+ }
+
+ if (rc == -EPIPE || try == max_tries - 1)
+ sata_down_spd_limit(link);
+ if (hardreset)
+ reset = hardreset;
+ goto retry;
}
static int ata_eh_revalidate_and_attach(struct ata_link *link,
@@ -2416,7 +2452,7 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err)
/* give it just one more chance */
ehc->tries[dev->devno] = min(ehc->tries[dev->devno], 1);
case -EIO:
- if (ehc->tries[dev->devno] == 1) {
+ if (ehc->tries[dev->devno] == 1 && dev->pio_mode > XFER_PIO_0) {
/* This is the last chance, better to slow
* down than lose it.
*/
@@ -2607,11 +2643,15 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
ehc->i.flags &= ~ATA_EHI_SETMODE;
}
+ if (ehc->i.action & ATA_EHI_LPM)
+ ata_link_for_each_dev(dev, link)
+ ata_dev_enable_pm(dev, ap->pm_policy);
+
/* this link is okay now */
ehc->i.flags = 0;
continue;
- dev_fail:
+dev_fail:
nr_failed_devs++;
if (ata_eh_handle_dev_fail(dev, rc))
nr_disabled_devs++;
@@ -2672,8 +2712,15 @@ void ata_eh_finish(struct ata_port *ap)
/* FIXME: Once EH migration is complete,
* generate sense data in this function,
* considering both err_mask and tf.
+ *
+ * There's no point in retrying invalid
+ * (detected by libata) and non-IO device
+ * errors (rejected by device). Finish them
+ * immediately.
*/
- if (qc->err_mask & AC_ERR_INVALID)
+ if ((qc->err_mask & AC_ERR_INVALID) ||
+ (!(qc->flags & ATA_QCFLAG_IO) &&
+ qc->err_mask == AC_ERR_DEV))
ata_eh_qc_complete(qc);
else
ata_eh_qc_retry(qc);
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index ea53e6a570b4..94144ed50a6b 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -45,7 +45,7 @@
#include <scsi/scsi_transport.h>
#include <linux/libata.h>
#include <linux/hdreg.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include "libata.h"
@@ -53,9 +53,9 @@
typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc);
-static struct ata_device * __ata_scsi_find_dev(struct ata_port *ap,
+static struct ata_device *__ata_scsi_find_dev(struct ata_port *ap,
const struct scsi_device *scsidev);
-static struct ata_device * ata_scsi_find_dev(struct ata_port *ap,
+static struct ata_device *ata_scsi_find_dev(struct ata_port *ap,
const struct scsi_device *scsidev);
static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
unsigned int id, unsigned int lun);
@@ -110,6 +110,74 @@ static struct scsi_transport_template ata_scsi_transport_template = {
};
+static const struct {
+ enum link_pm value;
+ const char *name;
+} link_pm_policy[] = {
+ { NOT_AVAILABLE, "max_performance" },
+ { MIN_POWER, "min_power" },
+ { MAX_PERFORMANCE, "max_performance" },
+ { MEDIUM_POWER, "medium_power" },
+};
+
+static const char *ata_scsi_lpm_get(enum link_pm policy)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(link_pm_policy); i++)
+ if (link_pm_policy[i].value == policy)
+ return link_pm_policy[i].name;
+
+ return NULL;
+}
+
+static ssize_t ata_scsi_lpm_put(struct class_device *class_dev,
+ const char *buf, size_t count)
+{
+ struct Scsi_Host *shost = class_to_shost(class_dev);
+ struct ata_port *ap = ata_shost_to_port(shost);
+ enum link_pm policy = 0;
+ int i;
+
+ /*
+ * we are skipping array location 0 on purpose - this
+ * is because a value of NOT_AVAILABLE is displayed
+ * to the user as max_performance, but when the user
+ * writes "max_performance", they actually want the
+ * value to match MAX_PERFORMANCE.
+ */
+ for (i = 1; i < ARRAY_SIZE(link_pm_policy); i++) {
+ const int len = strlen(link_pm_policy[i].name);
+ if (strncmp(link_pm_policy[i].name, buf, len) == 0 &&
+ buf[len] == '\n') {
+ policy = link_pm_policy[i].value;
+ break;
+ }
+ }
+ if (!policy)
+ return -EINVAL;
+
+ ata_lpm_schedule(ap, policy);
+ return count;
+}
+
+static ssize_t
+ata_scsi_lpm_show(struct class_device *class_dev, char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(class_dev);
+ struct ata_port *ap = ata_shost_to_port(shost);
+ const char *policy =
+ ata_scsi_lpm_get(ap->pm_policy);
+
+ if (!policy)
+ return -EINVAL;
+
+ return snprintf(buf, 23, "%s\n", policy);
+}
+CLASS_DEVICE_ATTR(link_power_management_policy, S_IRUGO | S_IWUSR,
+ ata_scsi_lpm_show, ata_scsi_lpm_put);
+EXPORT_SYMBOL_GPL(class_device_attr_link_power_management_policy);
+
static void ata_scsi_invalid_field(struct scsi_cmnd *cmd,
void (*done)(struct scsi_cmnd *))
{
@@ -228,7 +296,7 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
scsi_cmd[1] = (4 << 1); /* PIO Data-in */
scsi_cmd[2] = 0x0e; /* no off.line or cc, read from dev,
- block count in sector count field */
+ block count in sector count field */
data_dir = DMA_FROM_DEVICE;
} else {
scsi_cmd[1] = (3 << 1); /* Non-data */
@@ -252,7 +320,7 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
/* Good values for timeout and retries? Values below
from scsi_ioctl_send_command() for default case... */
cmd_result = scsi_execute(scsidev, scsi_cmd, data_dir, argbuf, argsize,
- sensebuf, (10*HZ), 5, 0);
+ sensebuf, (10*HZ), 5, 0);
if (driver_byte(cmd_result) == DRIVER_SENSE) {/* sense data available */
u8 *desc = sensebuf + 8;
@@ -263,18 +331,18 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
if (cmd_result & SAM_STAT_CHECK_CONDITION) {
struct scsi_sense_hdr sshdr;
scsi_normalize_sense(sensebuf, SCSI_SENSE_BUFFERSIZE,
- &sshdr);
- if (sshdr.sense_key==0 &&
- sshdr.asc==0 && sshdr.ascq==0)
+ &sshdr);
+ if (sshdr.sense_key == 0 &&
+ sshdr.asc == 0 && sshdr.ascq == 0)
cmd_result &= ~SAM_STAT_CHECK_CONDITION;
}
/* Send userspace a few ATA registers (same as drivers/ide) */
- if (sensebuf[0] == 0x72 && /* format is "descriptor" */
- desc[0] == 0x09 ) { /* code is "ATA Descriptor" */
- args[0] = desc[13]; /* status */
- args[1] = desc[3]; /* error */
- args[2] = desc[5]; /* sector count (0:7) */
+ if (sensebuf[0] == 0x72 && /* format is "descriptor" */
+ desc[0] == 0x09) { /* code is "ATA Descriptor" */
+ args[0] = desc[13]; /* status */
+ args[1] = desc[3]; /* error */
+ args[2] = desc[5]; /* sector count (0:7) */
if (copy_to_user(arg, args, sizeof(args)))
rc = -EFAULT;
}
@@ -350,8 +418,8 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)
struct scsi_sense_hdr sshdr;
scsi_normalize_sense(sensebuf, SCSI_SENSE_BUFFERSIZE,
&sshdr);
- if (sshdr.sense_key==0 &&
- sshdr.asc==0 && sshdr.ascq==0)
+ if (sshdr.sense_key == 0 &&
+ sshdr.asc == 0 && sshdr.ascq == 0)
cmd_result &= ~SAM_STAT_CHECK_CONDITION;
}
@@ -773,6 +841,9 @@ static void ata_scsi_dev_config(struct scsi_device *sdev,
blk_queue_max_hw_segments(q, q->max_hw_segments - 1);
}
+ if (dev->flags & ATA_DFLAG_AN)
+ set_bit(SDEV_EVT_MEDIA_CHANGE, sdev->supported_events);
+
if (dev->flags & ATA_DFLAG_NCQ) {
int depth;
@@ -801,8 +872,6 @@ int ata_scsi_slave_config(struct scsi_device *sdev)
ata_scsi_sdev_config(sdev);
- blk_queue_max_phys_segments(sdev->request_queue, LIBATA_MAX_PRD);
-
sdev->manage_start_stop = 1;
if (dev)
@@ -977,7 +1046,7 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
if ((qc->dev->flags & ATA_DFLAG_SPUNDOWN) &&
(system_state == SYSTEM_HALT ||
system_state == SYSTEM_POWER_OFF)) {
- static unsigned long warned = 0;
+ static unsigned long warned;
if (!test_and_set_bit(0, &warned)) {
ata_dev_printk(qc->dev, KERN_WARNING,
@@ -1042,6 +1111,9 @@ static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc)
else
tf->command = ATA_CMD_FLUSH;
+ /* flush is critical for IO integrity, consider it an IO command */
+ qc->flags |= ATA_QCFLAG_IO;
+
return 0;
}
@@ -1365,29 +1437,7 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
struct ata_port *ap = qc->ap;
struct scsi_cmnd *cmd = qc->scsicmd;
u8 *cdb = cmd->cmnd;
- int need_sense = (qc->err_mask != 0);
-
- /* We snoop the SET_FEATURES - Write Cache ON/OFF command, and
- * schedule EH_REVALIDATE operation to update the IDENTIFY DEVICE
- * cache
- */
- if (ap->ops->error_handler && !need_sense) {
- switch (qc->tf.command) {
- case ATA_CMD_SET_FEATURES:
- if ((qc->tf.feature == SETFEATURES_WC_ON) ||
- (qc->tf.feature == SETFEATURES_WC_OFF)) {
- ap->link.eh_info.action |= ATA_EH_REVALIDATE;
- ata_port_schedule_eh(ap);
- }
- break;
-
- case ATA_CMD_INIT_DEV_PARAMS: /* CHS translation changed */
- case ATA_CMD_SET_MULTI: /* multi_count changed */
- ap->link.eh_info.action |= ATA_EH_REVALIDATE;
- ata_port_schedule_eh(ap);
- break;
- }
- }
+ int need_sense = (qc->err_mask != 0);
/* For ATA pass thru (SAT) commands, generate a sense block if
* user mandated it or if there's an error. Note that if we
@@ -1397,7 +1447,7 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
* was no error, SK, ASC and ASCQ will all be zero.
*/
if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) &&
- ((cdb[2] & 0x20) || need_sense)) {
+ ((cdb[2] & 0x20) || need_sense)) {
ata_gen_passthru_sense(qc);
} else {
if (!need_sense) {
@@ -1501,7 +1551,7 @@ static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd,
return 0;
early_finish:
- ata_qc_free(qc);
+ ata_qc_free(qc);
qc->scsidone(cmd);
DPRINTK("EXIT - early finish (good or error)\n");
return 0;
@@ -1545,7 +1595,7 @@ static unsigned int ata_scsi_rbuf_get(struct scsi_cmnd *cmd, u8 **buf_out)
struct scatterlist *sg = scsi_sglist(cmd);
if (sg) {
- buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+ buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
buflen = sg->length;
} else {
buf = NULL;
@@ -1591,8 +1641,8 @@ static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, u8 *buf)
*/
void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
- unsigned int (*actor) (struct ata_scsi_args *args,
- u8 *rbuf, unsigned int buflen))
+ unsigned int (*actor) (struct ata_scsi_args *args,
+ u8 *rbuf, unsigned int buflen))
{
u8 *rbuf;
unsigned int buflen, rc;
@@ -2141,7 +2191,7 @@ saving_not_supp:
* None.
*/
unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
- unsigned int buflen)
+ unsigned int buflen)
{
u64 last_lba = args->dev->n_sectors - 1; /* LBA of the last block */
@@ -2465,7 +2515,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
return 0;
}
-static struct ata_device * ata_find_dev(struct ata_port *ap, int devno)
+static struct ata_device *ata_find_dev(struct ata_port *ap, int devno)
{
if (ap->nr_pmp_links == 0) {
if (likely(devno < ata_link_max_devices(&ap->link)))
@@ -2478,8 +2528,8 @@ static struct ata_device * ata_find_dev(struct ata_port *ap, int devno)
return NULL;
}
-static struct ata_device * __ata_scsi_find_dev(struct ata_port *ap,
- const struct scsi_device *scsidev)
+static struct ata_device *__ata_scsi_find_dev(struct ata_port *ap,
+ const struct scsi_device *scsidev)
{
int devno;
@@ -2565,27 +2615,27 @@ static u8
ata_scsi_map_proto(u8 byte1)
{
switch((byte1 & 0x1e) >> 1) {
- case 3: /* Non-data */
- return ATA_PROT_NODATA;
-
- case 6: /* DMA */
- case 10: /* UDMA Data-in */
- case 11: /* UDMA Data-Out */
- return ATA_PROT_DMA;
-
- case 4: /* PIO Data-in */
- case 5: /* PIO Data-out */
- return ATA_PROT_PIO;
-
- case 0: /* Hard Reset */
- case 1: /* SRST */
- case 8: /* Device Diagnostic */
- case 9: /* Device Reset */
- case 7: /* DMA Queued */
- case 12: /* FPDMA */
- case 15: /* Return Response Info */
- default: /* Reserved */
- break;
+ case 3: /* Non-data */
+ return ATA_PROT_NODATA;
+
+ case 6: /* DMA */
+ case 10: /* UDMA Data-in */
+ case 11: /* UDMA Data-Out */
+ return ATA_PROT_DMA;
+
+ case 4: /* PIO Data-in */
+ case 5: /* PIO Data-out */
+ return ATA_PROT_PIO;
+
+ case 0: /* Hard Reset */
+ case 1: /* SRST */
+ case 8: /* Device Diagnostic */
+ case 9: /* Device Reset */
+ case 7: /* DMA Queued */
+ case 12: /* FPDMA */
+ case 15: /* Return Response Info */
+ default: /* Reserved */
+ break;
}
return ATA_PROT_UNKNOWN;
@@ -2720,8 +2770,8 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
*/
qc->nbytes = scsi_bufflen(scmd);
- /* request result TF */
- qc->flags |= ATA_QCFLAG_RESULT_TF;
+ /* request result TF and be quiet about device error */
+ qc->flags |= ATA_QCFLAG_RESULT_TF | ATA_QCFLAG_QUIET;
return 0;
@@ -2920,94 +2970,94 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,
args.done = done;
switch(scsicmd[0]) {
- /* TODO: worth improving? */
- case FORMAT_UNIT:
+ /* TODO: worth improving? */
+ case FORMAT_UNIT:
+ ata_scsi_invalid_field(cmd, done);
+ break;
+
+ case INQUIRY:
+ if (scsicmd[1] & 2) /* is CmdDt set? */
ata_scsi_invalid_field(cmd, done);
+ else if ((scsicmd[1] & 1) == 0) /* is EVPD clear? */
+ ata_scsi_rbuf_fill(&args, ata_scsiop_inq_std);
+ else switch (scsicmd[2]) {
+ case 0x00:
+ ata_scsi_rbuf_fill(&args, ata_scsiop_inq_00);
break;
-
- case INQUIRY:
- if (scsicmd[1] & 2) /* is CmdDt set? */
- ata_scsi_invalid_field(cmd, done);
- else if ((scsicmd[1] & 1) == 0) /* is EVPD clear? */
- ata_scsi_rbuf_fill(&args, ata_scsiop_inq_std);
- else switch (scsicmd[2]) {
- case 0x00:
- ata_scsi_rbuf_fill(&args, ata_scsiop_inq_00);
- break;
- case 0x80:
- ata_scsi_rbuf_fill(&args, ata_scsiop_inq_80);
- break;
- case 0x83:
- ata_scsi_rbuf_fill(&args, ata_scsiop_inq_83);
- break;
- case 0x89:
- ata_scsi_rbuf_fill(&args, ata_scsiop_inq_89);
- break;
- default:
- ata_scsi_invalid_field(cmd, done);
- break;
- }
+ case 0x80:
+ ata_scsi_rbuf_fill(&args, ata_scsiop_inq_80);
break;
-
- case MODE_SENSE:
- case MODE_SENSE_10:
- ata_scsi_rbuf_fill(&args, ata_scsiop_mode_sense);
+ case 0x83:
+ ata_scsi_rbuf_fill(&args, ata_scsiop_inq_83);
break;
-
- case MODE_SELECT: /* unconditionally return */
- case MODE_SELECT_10: /* bad-field-in-cdb */
+ case 0x89:
+ ata_scsi_rbuf_fill(&args, ata_scsiop_inq_89);
+ break;
+ default:
ata_scsi_invalid_field(cmd, done);
break;
+ }
+ break;
- case READ_CAPACITY:
+ case MODE_SENSE:
+ case MODE_SENSE_10:
+ ata_scsi_rbuf_fill(&args, ata_scsiop_mode_sense);
+ break;
+
+ case MODE_SELECT: /* unconditionally return */
+ case MODE_SELECT_10: /* bad-field-in-cdb */
+ ata_scsi_invalid_field(cmd, done);
+ break;
+
+ case READ_CAPACITY:
+ ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap);
+ break;
+
+ case SERVICE_ACTION_IN:
+ if ((scsicmd[1] & 0x1f) == SAI_READ_CAPACITY_16)
ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap);
- break;
+ else
+ ata_scsi_invalid_field(cmd, done);
+ break;
- case SERVICE_ACTION_IN:
- if ((scsicmd[1] & 0x1f) == SAI_READ_CAPACITY_16)
- ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap);
- else
- ata_scsi_invalid_field(cmd, done);
- break;
+ case REPORT_LUNS:
+ ata_scsi_rbuf_fill(&args, ata_scsiop_report_luns);
+ break;
- case REPORT_LUNS:
- ata_scsi_rbuf_fill(&args, ata_scsiop_report_luns);
- break;
+ case REQUEST_SENSE:
+ ata_scsi_set_sense(cmd, 0, 0, 0);
+ cmd->result = (DRIVER_SENSE << 24);
+ done(cmd);
+ break;
- case REQUEST_SENSE:
- ata_scsi_set_sense(cmd, 0, 0, 0);
- cmd->result = (DRIVER_SENSE << 24);
- done(cmd);
- break;
+ /* if we reach this, then writeback caching is disabled,
+ * turning this into a no-op.
+ */
+ case SYNCHRONIZE_CACHE:
+ /* fall through */
+
+ /* no-op's, complete with success */
+ case REZERO_UNIT:
+ case SEEK_6:
+ case SEEK_10:
+ case TEST_UNIT_READY:
+ ata_scsi_rbuf_fill(&args, ata_scsiop_noop);
+ break;
- /* if we reach this, then writeback caching is disabled,
- * turning this into a no-op.
- */
- case SYNCHRONIZE_CACHE:
- /* fall through */
-
- /* no-op's, complete with success */
- case REZERO_UNIT:
- case SEEK_6:
- case SEEK_10:
- case TEST_UNIT_READY:
+ case SEND_DIAGNOSTIC:
+ tmp8 = scsicmd[1] & ~(1 << 3);
+ if ((tmp8 == 0x4) && (!scsicmd[3]) && (!scsicmd[4]))
ata_scsi_rbuf_fill(&args, ata_scsiop_noop);
- break;
-
- case SEND_DIAGNOSTIC:
- tmp8 = scsicmd[1] & ~(1 << 3);
- if ((tmp8 == 0x4) && (!scsicmd[3]) && (!scsicmd[4]))
- ata_scsi_rbuf_fill(&args, ata_scsiop_noop);
- else
- ata_scsi_invalid_field(cmd, done);
- break;
+ else
+ ata_scsi_invalid_field(cmd, done);
+ break;
- /* all other commands */
- default:
- ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, 0x20, 0x0);
- /* "Invalid command operation code" */
- done(cmd);
- break;
+ /* all other commands */
+ default:
+ ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, 0x20, 0x0);
+ /* "Invalid command operation code" */
+ done(cmd);
+ break;
}
}
@@ -3239,7 +3289,7 @@ static void ata_scsi_handle_link_detach(struct ata_link *link)
/**
* ata_scsi_media_change_notify - send media change event
- * @atadev: Pointer to the disk device with media change event
+ * @dev: Pointer to the disk device with media change event
*
* Tell the block layer to send a media change notification
* event.
@@ -3249,10 +3299,9 @@ static void ata_scsi_handle_link_detach(struct ata_link *link)
*/
void ata_scsi_media_change_notify(struct ata_device *dev)
{
-#ifdef OTHER_AN_PATCHES_HAVE_BEEN_APPLIED
if (dev->sdev)
- scsi_device_event_notify(dev->sdev, SDEV_MEDIA_CHANGE);
-#endif
+ sdev_evt_send_simple(dev->sdev, SDEV_EVT_MEDIA_CHANGE,
+ GFP_ATOMIC);
}
/**
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 026439e05afe..48acc09dab96 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -156,7 +156,7 @@ void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
- tf->command = ata_check_status(ap);
+ tf->command = ata_chk_status(ap);
tf->feature = ioread8(ioaddr->error_addr);
tf->nsect = ioread8(ioaddr->nsect_addr);
tf->lbal = ioread8(ioaddr->lbal_addr);
@@ -248,7 +248,7 @@ void ata_bmdma_setup(struct ata_queued_cmd *qc)
* LOCKING:
* spin_lock_irqsave(host lock)
*/
-void ata_bmdma_start (struct ata_queued_cmd *qc)
+void ata_bmdma_start(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
u8 dmactl;
@@ -856,7 +856,7 @@ err_out:
* @pdev: PCI device
*
* Some PCI ATA devices report simplex mode but in fact can be told to
- * enter non simplex mode. This implements the neccessary logic to
+ * enter non simplex mode. This implements the necessary logic to
* perform the task on such devices. Calling it on other devices will
* have -undefined- behaviour.
*/
@@ -882,7 +882,7 @@ unsigned long ata_pci_default_filter(struct ata_device *adev, unsigned long xfer
/* Filter out DMA modes if the device has been configured by
the BIOS as PIO only */
- if (adev->link->ap->ioaddr.bmdma_addr == 0)
+ if (adev->link->ap->ioaddr.bmdma_addr == NULL)
xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
return xfer_mask;
}
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 90df58a3edc9..0e6cf3a484dc 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -101,6 +101,8 @@ extern int sata_link_init_spd(struct ata_link *link);
extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg);
extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg);
extern struct ata_port *ata_port_alloc(struct ata_host *host);
+extern void ata_dev_enable_pm(struct ata_device *dev, enum link_pm policy);
+extern void ata_lpm_schedule(struct ata_port *ap, enum link_pm);
/* libata-acpi.c */
#ifdef CONFIG_ATA_ACPI
diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c
index 5d3920f6fd69..e4542ab9c7f8 100644
--- a/drivers/ata/pata_acpi.c
+++ b/drivers/ata/pata_acpi.c
@@ -181,7 +181,7 @@ static void pacpi_set_piomode(struct ata_port *ap, struct ata_device *adev)
int unit = adev->devno;
struct pata_acpi *acpi = ap->private_data;
- if(!(acpi->gtm.flags & 0x10))
+ if (!(acpi->gtm.flags & 0x10))
unit = 0;
/* Now stuff the nS values into the structure */
@@ -202,7 +202,7 @@ static void pacpi_set_dmamode(struct ata_port *ap, struct ata_device *adev)
int unit = adev->devno;
struct pata_acpi *acpi = ap->private_data;
- if(!(acpi->gtm.flags & 0x10))
+ if (!(acpi->gtm.flags & 0x10))
unit = 0;
/* Now stuff the nS values into the structure */
@@ -370,8 +370,10 @@ static struct pci_driver pacpi_pci_driver = {
.id_table = pacpi_pci_tbl,
.probe = pacpi_init_one,
.remove = ata_pci_remove_one,
+#ifdef CONFIG_PM
.suspend = ata_pci_device_suspend,
.resume = ata_pci_device_resume,
+#endif
};
static int __init pacpi_init(void)
diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c
index 747549e4563a..b5e38426b815 100644
--- a/drivers/ata/pata_bf54x.c
+++ b/drivers/ata/pata_bf54x.c
@@ -1092,14 +1092,15 @@ static unsigned int bfin_bus_softreset(struct ata_port *ap,
* Note: Original code is ata_std_softreset().
*/
-static int bfin_std_softreset(struct ata_port *ap, unsigned int *classes,
+static int bfin_std_softreset(struct ata_link *link, unsigned int *classes,
unsigned long deadline)
{
+ struct ata_port *ap = link->ap;
unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
unsigned int devmask = 0, err_mask;
u8 err;
- if (ata_port_offline(ap)) {
+ if (ata_link_offline(link)) {
classes[0] = ATA_DEV_NONE;
goto out;
}
@@ -1122,9 +1123,11 @@ static int bfin_std_softreset(struct ata_port *ap, unsigned int *classes,
}
/* determine by signature whether we have ATA or ATAPI devices */
- classes[0] = ata_dev_try_classify(ap, 0, &err);
+ classes[0] = ata_dev_try_classify(&ap->link.device[0],
+ devmask & (1 << 0), &err);
if (slave_possible && err != 0x81)
- classes[1] = ata_dev_try_classify(ap, 1, &err);
+ classes[1] = ata_dev_try_classify(&ap->link.device[1],
+ devmask & (1 << 1), &err);
out:
return 0;
@@ -1167,7 +1170,7 @@ static unsigned char bfin_bmdma_status(struct ata_port *ap)
static void bfin_data_xfer(struct ata_device *adev, unsigned char *buf,
unsigned int buflen, int write_data)
{
- struct ata_port *ap = adev->ap;
+ struct ata_port *ap = adev->link->ap;
unsigned int words = buflen >> 1;
unsigned short *buf16 = (u16 *) buf;
void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
@@ -1206,7 +1209,10 @@ static void bfin_irq_clear(struct ata_port *ap)
void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
pr_debug("in atapi irq clear\n");
- ATAPI_SET_INT_STATUS(base, 0x1FF);
+
+ ATAPI_SET_INT_STATUS(base, ATAPI_GET_INT_STATUS(base)|ATAPI_DEV_INT
+ | MULTI_DONE_INT | UDMAIN_DONE_INT | UDMAOUT_DONE_INT
+ | MULTI_TERM_INT | UDMAIN_TERM_INT | UDMAOUT_TERM_INT);
}
/**
@@ -1234,33 +1240,6 @@ static unsigned char bfin_irq_on(struct ata_port *ap)
}
/**
- * bfin_irq_ack - Acknowledge a device interrupt.
- * @ap: Port on which interrupts are enabled.
- *
- * Note: Original code is ata_irq_ack().
- */
-
-static unsigned char bfin_irq_ack(struct ata_port *ap, unsigned int chk_drq)
-{
- void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
- unsigned int bits = chk_drq ? ATA_BUSY | ATA_DRQ : ATA_BUSY;
- unsigned char status;
-
- pr_debug("in atapi irq ack\n");
- status = ata_busy_wait(ap, bits, 1000);
- if (status & bits)
- if (ata_msg_err(ap))
- dev_err(ap->dev, "abnormal status 0x%X\n", status);
-
- /* get controller status; clear intr, err bits */
- ATAPI_SET_INT_STATUS(base, ATAPI_GET_INT_STATUS(base)|ATAPI_DEV_INT
- | MULTI_DONE_INT | UDMAIN_DONE_INT | UDMAOUT_DONE_INT
- | MULTI_TERM_INT | UDMAIN_TERM_INT | UDMAOUT_TERM_INT);
-
- return bfin_bmdma_status(ap);
-}
-
-/**
* bfin_bmdma_freeze - Freeze DMA controller port
* @ap: port to freeze
*
@@ -1308,8 +1287,9 @@ void bfin_bmdma_thaw(struct ata_port *ap)
* Note: Original code is ata_std_postreset().
*/
-static void bfin_std_postreset(struct ata_port *ap, unsigned int *classes)
+static void bfin_std_postreset(struct ata_link *link, unsigned int *classes)
{
+ struct ata_port *ap = link->ap;
void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
/* re-enable interrupts */
@@ -1395,7 +1375,6 @@ static struct scsi_host_template bfin_sht = {
};
static const struct ata_port_operations bfin_pata_ops = {
- .port_disable = ata_port_disable,
.set_piomode = bfin_set_piomode,
.set_dmamode = bfin_set_dmamode,
@@ -1423,7 +1402,6 @@ static const struct ata_port_operations bfin_pata_ops = {
.irq_handler = ata_interrupt,
.irq_clear = bfin_irq_clear,
.irq_on = bfin_irq_on,
- .irq_ack = bfin_irq_ack,
.port_start = bfin_port_start,
.port_stop = bfin_port_stop,
@@ -1437,11 +1415,7 @@ static struct ata_port_info bfin_port_info[] = {
| ATA_FLAG_NO_LEGACY,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0,
-#ifdef CONFIG_PATA_BF54X_DMA
- .udma_mask = ATA_UDMA5,
-#else
.udma_mask = 0,
-#endif
.port_ops = &bfin_pata_ops,
},
};
@@ -1607,9 +1581,25 @@ static struct platform_driver bfin_atapi_driver = {
},
};
+#define ATAPI_MODE_SIZE 10
+static char bfin_atapi_mode[ATAPI_MODE_SIZE];
+
static int __init bfin_atapi_init(void)
{
pr_info("register bfin atapi driver\n");
+
+ switch(bfin_atapi_mode[0]) {
+ case 'p':
+ case 'P':
+ break;
+ case 'm':
+ case 'M':
+ bfin_port_info[0].mwdma_mask = ATA_MWDMA2;
+ break;
+ default:
+ bfin_port_info[0].udma_mask = ATA_UDMA5;
+ };
+
return platform_driver_register(&bfin_atapi_driver);
}
@@ -1620,6 +1610,13 @@ static void __exit bfin_atapi_exit(void)
module_init(bfin_atapi_init);
module_exit(bfin_atapi_exit);
+/*
+ * ATAPI mode:
+ * pio/PIO
+ * udma/UDMA (default)
+ * mwdma/MWDMA
+ */
+module_param_string(bfin_atapi_mode, bfin_atapi_mode, ATAPI_MODE_SIZE, 0);
MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
MODULE_DESCRIPTION("PATA driver for blackfin 54x ATAPI controller");
diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c
index 9e412c26b2a3..7acbbd9ee469 100644
--- a/drivers/ata/pata_cmd64x.c
+++ b/drivers/ata/pata_cmd64x.c
@@ -215,7 +215,7 @@ static void cmd64x_set_dmamode(struct ata_port *ap, struct ata_device *adev)
regU &= ~(0x05 << adev->devno);
if (adev->dma_mode >= XFER_UDMA_0) {
- /* Merge thge timing value */
+ /* Merge the timing value */
regU |= udma_data[adev->dma_mode - XFER_UDMA_0] << shift;
/* Merge the control bits */
regU |= 1 << adev->devno; /* UDMA on */
diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c
index 57e827e4109e..e1818fdd9159 100644
--- a/drivers/ata/pata_cs5530.c
+++ b/drivers/ata/pata_cs5530.c
@@ -138,7 +138,7 @@ static void cs5530_set_dmamode(struct ata_port *ap, struct ata_device *adev)
*
* Called when the libata layer is about to issue a command. We wrap
* this interface so that we can load the correct ATA timings if
- * neccessary. Specifically we have a problem that there is only
+ * necessary. Specifically we have a problem that there is only
* one MWDMA/UDMA bit.
*/
diff --git a/drivers/ata/pata_cs5535.c b/drivers/ata/pata_cs5535.c
index 3578593a882b..01324530d052 100644
--- a/drivers/ata/pata_cs5535.c
+++ b/drivers/ata/pata_cs5535.c
@@ -25,7 +25,7 @@
* Documentation:
* Available from AMD web site.
* TODO
- * Review errata to see if serializing is neccessary
+ * Review errata to see if serializing is necessary
*/
#include <linux/kernel.h>
diff --git a/drivers/ata/pata_cs5536.c b/drivers/ata/pata_cs5536.c
new file mode 100644
index 000000000000..d753e568588e
--- /dev/null
+++ b/drivers/ata/pata_cs5536.c
@@ -0,0 +1,344 @@
+/*
+ * pata_cs5536.c - CS5536 PATA for new ATA layer
+ * (C) 2007 Martin K. Petersen <mkp@mkp.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Documentation:
+ * Available from AMD web site.
+ *
+ * The IDE timing registers for the CS5536 live in the Geode Machine
+ * Specific Register file and not PCI config space. Most BIOSes
+ * virtualize the PCI registers so the chip looks like a standard IDE
+ * controller. Unfortunately not all implementations get this right.
+ * In particular some have problems with unaligned accesses to the
+ * virtualized PCI registers. This driver always does full dword
+ * writes to work around the issue. Also, in case of a bad BIOS this
+ * driver can be loaded with the "msr=1" parameter which forces using
+ * the Machine Specific Registers to configure the device.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/libata.h>
+#include <scsi/scsi_host.h>
+#include <asm/msr.h>
+
+#define DRV_NAME "pata_cs5536"
+#define DRV_VERSION "0.0.6"
+
+enum {
+ CFG = 0,
+ DTC = 1,
+ CAST = 2,
+ ETC = 3,
+
+ MSR_IDE_BASE = 0x51300000,
+ MSR_IDE_CFG = (MSR_IDE_BASE + 0x10),
+ MSR_IDE_DTC = (MSR_IDE_BASE + 0x12),
+ MSR_IDE_CAST = (MSR_IDE_BASE + 0x13),
+ MSR_IDE_ETC = (MSR_IDE_BASE + 0x14),
+
+ PCI_IDE_CFG = 0x40,
+ PCI_IDE_DTC = 0x48,
+ PCI_IDE_CAST = 0x4c,
+ PCI_IDE_ETC = 0x50,
+
+ IDE_CFG_CHANEN = 0x2,
+ IDE_CFG_CABLE = 0x10000,
+
+ IDE_D0_SHIFT = 24,
+ IDE_D1_SHIFT = 16,
+ IDE_DRV_MASK = 0xff,
+
+ IDE_CAST_D0_SHIFT = 6,
+ IDE_CAST_D1_SHIFT = 4,
+ IDE_CAST_DRV_MASK = 0x3,
+ IDE_CAST_CMD_MASK = 0xff,
+ IDE_CAST_CMD_SHIFT = 24,
+
+ IDE_ETC_NODMA = 0x03,
+};
+
+static int use_msr;
+
+static const u32 msr_reg[4] = {
+ MSR_IDE_CFG, MSR_IDE_DTC, MSR_IDE_CAST, MSR_IDE_ETC,
+};
+
+static const u8 pci_reg[4] = {
+ PCI_IDE_CFG, PCI_IDE_DTC, PCI_IDE_CAST, PCI_IDE_ETC,
+};
+
+static inline int cs5536_read(struct pci_dev *pdev, int reg, int *val)
+{
+ if (unlikely(use_msr)) {
+ u32 dummy;
+
+ rdmsr(msr_reg[reg], *val, dummy);
+ return 0;
+ }
+
+ return pci_read_config_dword(pdev, pci_reg[reg], val);
+}
+
+static inline int cs5536_write(struct pci_dev *pdev, int reg, int val)
+{
+ if (unlikely(use_msr)) {
+ wrmsr(msr_reg[reg], val, 0);
+ return 0;
+ }
+
+ return pci_write_config_dword(pdev, pci_reg[reg], val);
+}
+
+/**
+ * cs5536_cable_detect - detect cable type
+ * @ap: Port to detect on
+ * @deadline: deadline jiffies for the operation
+ *
+ * Perform cable detection for ATA66 capable cable. Return a libata
+ * cable type.
+ */
+
+static int cs5536_cable_detect(struct ata_port *ap)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ u32 cfg;
+
+ cs5536_read(pdev, CFG, &cfg);
+
+ if (cfg & (IDE_CFG_CABLE << ap->port_no))
+ return ATA_CBL_PATA80;
+ else
+ return ATA_CBL_PATA40;
+}
+
+/**
+ * cs5536_set_piomode - PIO setup
+ * @ap: ATA interface
+ * @adev: device on the interface
+ */
+
+static void cs5536_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ static const u8 drv_timings[5] = {
+ 0x98, 0x55, 0x32, 0x21, 0x20,
+ };
+
+ static const u8 addr_timings[5] = {
+ 0x2, 0x1, 0x0, 0x0, 0x0,
+ };
+
+ static const u8 cmd_timings[5] = {
+ 0x99, 0x92, 0x90, 0x22, 0x20,
+ };
+
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ struct ata_device *pair = ata_dev_pair(adev);
+ int mode = adev->pio_mode - XFER_PIO_0;
+ int cmdmode = mode;
+ int dshift = ap->port_no ? IDE_D1_SHIFT : IDE_D0_SHIFT;
+ int cshift = ap->port_no ? IDE_CAST_D1_SHIFT : IDE_CAST_D0_SHIFT;
+ u32 dtc, cast, etc;
+
+ if (pair)
+ cmdmode = min(mode, pair->pio_mode - XFER_PIO_0);
+
+ cs5536_read(pdev, DTC, &dtc);
+ cs5536_read(pdev, CAST, &cast);
+ cs5536_read(pdev, ETC, &etc);
+
+ dtc &= ~(IDE_DRV_MASK << dshift);
+ dtc |= drv_timings[mode] << dshift;
+
+ cast &= ~(IDE_CAST_DRV_MASK << cshift);
+ cast |= addr_timings[mode] << cshift;
+
+ cast &= ~(IDE_CAST_CMD_MASK << IDE_CAST_CMD_SHIFT);
+ cast |= cmd_timings[cmdmode] << IDE_CAST_CMD_SHIFT;
+
+ etc &= ~(IDE_DRV_MASK << dshift);
+ etc |= IDE_ETC_NODMA << dshift;
+
+ cs5536_write(pdev, DTC, dtc);
+ cs5536_write(pdev, CAST, cast);
+ cs5536_write(pdev, ETC, etc);
+}
+
+/**
+ * cs5536_set_dmamode - DMA timing setup
+ * @ap: ATA interface
+ * @adev: Device being configured
+ *
+ */
+
+static void cs5536_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+{
+ static const u8 udma_timings[6] = {
+ 0xc2, 0xc1, 0xc0, 0xc4, 0xc5, 0xc6,
+ };
+
+ static const u8 mwdma_timings[3] = {
+ 0x67, 0x21, 0x20,
+ };
+
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ u32 dtc, etc;
+ int mode = adev->dma_mode;
+ int dshift = ap->port_no ? IDE_D1_SHIFT : IDE_D0_SHIFT;
+
+ if (mode >= XFER_UDMA_0) {
+ cs5536_read(pdev, ETC, &etc);
+
+ etc &= ~(IDE_DRV_MASK << dshift);
+ etc |= udma_timings[mode - XFER_UDMA_0] << dshift;
+
+ cs5536_write(pdev, ETC, etc);
+ } else { /* MWDMA */
+ cs5536_read(pdev, DTC, &dtc);
+
+ dtc &= ~(IDE_DRV_MASK << dshift);
+ dtc |= mwdma_timings[mode - XFER_MW_DMA_0] << dshift;
+
+ cs5536_write(pdev, DTC, dtc);
+ }
+}
+
+static struct scsi_host_template cs5536_sht = {
+ .module = THIS_MODULE,
+ .name = DRV_NAME,
+ .ioctl = ata_scsi_ioctl,
+ .queuecommand = ata_scsi_queuecmd,
+ .can_queue = ATA_DEF_QUEUE,
+ .this_id = ATA_SHT_THIS_ID,
+ .sg_tablesize = LIBATA_MAX_PRD,
+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+ .emulated = ATA_SHT_EMULATED,
+ .use_clustering = ATA_SHT_USE_CLUSTERING,
+ .proc_name = DRV_NAME,
+ .dma_boundary = ATA_DMA_BOUNDARY,
+ .slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
+ .bios_param = ata_std_bios_param,
+};
+
+static struct ata_port_operations cs5536_port_ops = {
+ .set_piomode = cs5536_set_piomode,
+ .set_dmamode = cs5536_set_dmamode,
+ .mode_filter = ata_pci_default_filter,
+
+ .tf_load = ata_tf_load,
+ .tf_read = ata_tf_read,
+ .check_status = ata_check_status,
+ .exec_command = ata_exec_command,
+ .dev_select = ata_std_dev_select,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = ata_bmdma_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+ .cable_detect = cs5536_cable_detect,
+
+ .bmdma_setup = ata_bmdma_setup,
+ .bmdma_start = ata_bmdma_start,
+ .bmdma_stop = ata_bmdma_stop,
+ .bmdma_status = ata_bmdma_status,
+
+ .qc_prep = ata_qc_prep,
+ .qc_issue = ata_qc_issue_prot,
+
+ .data_xfer = ata_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+ .irq_on = ata_irq_on,
+
+ .port_start = ata_port_start,
+};
+
+/**
+ * cs5536_init_one
+ * @dev: PCI device
+ * @id: Entry in match table
+ *
+ */
+
+static int cs5536_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ static const struct ata_port_info info = {
+ .sht = &cs5536_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = ATA_UDMA5,
+ .port_ops = &cs5536_port_ops,
+ };
+
+ const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info };
+ u32 cfg;
+
+ if (use_msr)
+ printk(KERN_ERR DRV_NAME ": Using MSR regs instead of PCI\n");
+
+ cs5536_read(dev, CFG, &cfg);
+
+ if ((cfg & IDE_CFG_CHANEN) == 0) {
+ printk(KERN_ERR DRV_NAME ": disabled by BIOS\n");
+ return -ENODEV;
+ }
+
+ return ata_pci_init_one(dev, ppi);
+}
+
+static const struct pci_device_id cs5536[] = {
+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CS5536_IDE), },
+ { },
+};
+
+static struct pci_driver cs5536_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = cs5536,
+ .probe = cs5536_init_one,
+ .remove = ata_pci_remove_one,
+#ifdef CONFIG_PM
+ .suspend = ata_pci_device_suspend,
+ .resume = ata_pci_device_resume,
+#endif
+};
+
+static int __init cs5536_init(void)
+{
+ return pci_register_driver(&cs5536_pci_driver);
+}
+
+static void __exit cs5536_exit(void)
+{
+ pci_unregister_driver(&cs5536_pci_driver);
+}
+
+MODULE_AUTHOR("Martin K. Petersen");
+MODULE_DESCRIPTION("low-level driver for the CS5536 IDE controller");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, cs5536);
+MODULE_VERSION(DRV_VERSION);
+module_param_named(msr, use_msr, int, 0644);
+MODULE_PARM_DESC(msr, "Force using MSR to configure IDE function (Default: 0)");
+
+module_init(cs5536_init);
+module_exit(cs5536_exit);
diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c
index e61cb1fd57b2..3816b8605e0d 100644
--- a/drivers/ata/pata_hpt37x.c
+++ b/drivers/ata/pata_hpt37x.c
@@ -295,7 +295,7 @@ static unsigned long hpt370_filter(struct ata_device *adev, unsigned long mask)
static unsigned long hpt370a_filter(struct ata_device *adev, unsigned long mask)
{
- if (adev->class != ATA_DEV_ATA) {
+ if (adev->class == ATA_DEV_ATA) {
if (hpt_dma_blacklisted(adev, "UDMA100", bad_ata100_5))
mask &= ~ (0x1F << ATA_SHIFT_UDMA);
}
@@ -359,28 +359,25 @@ static int hpt374_pre_reset(struct ata_link *link, unsigned long deadline)
{ 0x50, 1, 0x04, 0x04 },
{ 0x54, 1, 0x04, 0x04 }
};
- u16 mcr3, mcr6;
+ u16 mcr3;
u8 ata66;
struct ata_port *ap = link->ap;
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ unsigned int mcrbase = 0x50 + 4 * ap->port_no;
if (!pci_test_config_bits(pdev, &hpt37x_enable_bits[ap->port_no]))
return -ENOENT;
/* Do the extra channel work */
- pci_read_config_word(pdev, 0x52, &mcr3);
- pci_read_config_word(pdev, 0x56, &mcr6);
+ pci_read_config_word(pdev, mcrbase + 2, &mcr3);
/* Set bit 15 of 0x52 to enable TCBLID as input
- Set bit 15 of 0x56 to enable FCBLID as input
*/
- pci_write_config_word(pdev, 0x52, mcr3 | 0x8000);
- pci_write_config_word(pdev, 0x56, mcr6 | 0x8000);
+ pci_write_config_word(pdev, mcrbase + 2, mcr3 | 0x8000);
pci_read_config_byte(pdev, 0x5A, &ata66);
/* Reset TCBLID/FCBLID to output */
pci_write_config_word(pdev, 0x52, mcr3);
- pci_write_config_word(pdev, 0x56, mcr6);
- if (ata66 & (1 << ap->port_no))
+ if (ata66 & (2 >> ap->port_no))
ap->cbl = ATA_CBL_PATA40;
else
ap->cbl = ATA_CBL_PATA80;
@@ -844,6 +841,25 @@ static int hpt37x_calibrate_dpll(struct pci_dev *dev)
/* Never went stable */
return 0;
}
+
+static u32 hpt374_read_freq(struct pci_dev *pdev)
+{
+ u32 freq;
+ unsigned long io_base = pci_resource_start(pdev, 4);
+ if (PCI_FUNC(pdev->devfn) & 1) {
+ struct pci_dev *pdev_0 = pci_get_slot(pdev->bus, pdev->devfn - 1);
+ /* Someone hot plugged the controller on us ? */
+ if (pdev_0 == NULL)
+ return 0;
+ io_base = pci_resource_start(pdev_0, 4);
+ freq = inl(io_base + 0x90);
+ pci_dev_put(pdev_0);
+ }
+ else
+ freq = inl(io_base + 0x90);
+ return freq;
+}
+
/**
* hpt37x_init_one - Initialise an HPT37X/302
* @dev: PCI device
@@ -902,7 +918,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x0f,
+ .udma_mask = ATA_UDMA5,
.port_ops = &hpt370_port_ops
};
/* HPT370A - UDMA100 */
@@ -911,7 +927,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x0f,
+ .udma_mask = ATA_UDMA5,
.port_ops = &hpt370a_port_ops
};
/* HPT371, 372 and friends - UDMA133 */
@@ -1047,9 +1063,16 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
outb(0x0e, iobase + 0x9c);
/* Some devices do not let this value be accessed via PCI space
- according to the old driver */
+ according to the old driver. In addition we must use the value
+ from FN 0 on the HPT374 */
+
+ if (chip_table == &hpt374) {
+ freq = hpt374_read_freq(dev);
+ if (freq == 0)
+ return -ENODEV;
+ } else
+ freq = inl(iobase + 0x90);
- freq = inl(iobase + 0x90);
if ((freq >> 12) != 0xABCDE) {
int i;
u8 sr;
diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c
index be30923566c5..842fe08a3c13 100644
--- a/drivers/ata/pata_icside.c
+++ b/drivers/ata/pata_icside.c
@@ -332,12 +332,13 @@ static void ata_dummy_noret(struct ata_port *port)
{
}
-static void pata_icside_postreset(struct ata_port *ap, unsigned int *classes)
+static void pata_icside_postreset(struct ata_link *link, unsigned int *classes)
{
+ struct ata_port *ap = link->ap;
struct pata_icside_state *state = ap->host->private_data;
if (classes[0] != ATA_DEV_NONE || classes[1] != ATA_DEV_NONE)
- return ata_std_postreset(ap, classes);
+ return ata_std_postreset(link, classes);
state->port[ap->port_no].disabled = 1;
@@ -395,29 +396,30 @@ static struct ata_port_operations pata_icside_port_ops = {
static void __devinit
pata_icside_setup_ioaddr(struct ata_port *ap, void __iomem *base,
- const struct portinfo *info)
+ struct pata_icside_info *info,
+ const struct portinfo *port)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
- void __iomem *cmd = base + info->dataoffset;
+ void __iomem *cmd = base + port->dataoffset;
ioaddr->cmd_addr = cmd;
- ioaddr->data_addr = cmd + (ATA_REG_DATA << info->stepping);
- ioaddr->error_addr = cmd + (ATA_REG_ERR << info->stepping);
- ioaddr->feature_addr = cmd + (ATA_REG_FEATURE << info->stepping);
- ioaddr->nsect_addr = cmd + (ATA_REG_NSECT << info->stepping);
- ioaddr->lbal_addr = cmd + (ATA_REG_LBAL << info->stepping);
- ioaddr->lbam_addr = cmd + (ATA_REG_LBAM << info->stepping);
- ioaddr->lbah_addr = cmd + (ATA_REG_LBAH << info->stepping);
- ioaddr->device_addr = cmd + (ATA_REG_DEVICE << info->stepping);
- ioaddr->status_addr = cmd + (ATA_REG_STATUS << info->stepping);
- ioaddr->command_addr = cmd + (ATA_REG_CMD << info->stepping);
-
- ioaddr->ctl_addr = base + info->ctrloffset;
+ ioaddr->data_addr = cmd + (ATA_REG_DATA << port->stepping);
+ ioaddr->error_addr = cmd + (ATA_REG_ERR << port->stepping);
+ ioaddr->feature_addr = cmd + (ATA_REG_FEATURE << port->stepping);
+ ioaddr->nsect_addr = cmd + (ATA_REG_NSECT << port->stepping);
+ ioaddr->lbal_addr = cmd + (ATA_REG_LBAL << port->stepping);
+ ioaddr->lbam_addr = cmd + (ATA_REG_LBAM << port->stepping);
+ ioaddr->lbah_addr = cmd + (ATA_REG_LBAH << port->stepping);
+ ioaddr->device_addr = cmd + (ATA_REG_DEVICE << port->stepping);
+ ioaddr->status_addr = cmd + (ATA_REG_STATUS << port->stepping);
+ ioaddr->command_addr = cmd + (ATA_REG_CMD << port->stepping);
+
+ ioaddr->ctl_addr = base + port->ctrloffset;
ioaddr->altstatus_addr = ioaddr->ctl_addr;
ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx",
- info->raw_base + info->dataoffset,
- info->raw_base + info->ctrloffset);
+ info->raw_base + port->dataoffset,
+ info->raw_base + port->ctrloffset);
if (info->raw_ioc_base)
ata_port_desc(ap, "iocbase 0x%lx", info->raw_ioc_base);
@@ -441,7 +443,7 @@ static int __devinit pata_icside_register_v5(struct pata_icside_info *info)
info->nr_ports = 1;
info->port[0] = &pata_icside_portinfo_v5;
- info->raw_base = ecard_resource_start(ec, ECARD_RES_MEMC);
+ info->raw_base = ecard_resource_start(info->ec, ECARD_RES_MEMC);
return 0;
}
@@ -522,7 +524,7 @@ static int __devinit pata_icside_add_ports(struct pata_icside_info *info)
ap->flags |= ATA_FLAG_SLAVE_POSS;
ap->ops = &pata_icside_port_ops;
- pata_icside_setup_ioaddr(ap, info->base, info->port[i]);
+ pata_icside_setup_ioaddr(ap, info->base, info, info->port[i]);
}
return ata_host_activate(host, ec->irq, ata_interrupt, 0,
diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c
index 988ef736b936..ca9aae09daed 100644
--- a/drivers/ata/pata_it821x.c
+++ b/drivers/ata/pata_it821x.c
@@ -105,7 +105,7 @@ struct it821x_dev
/*
* We allow users to force the card into non raid mode without
- * flashing the alternative BIOS. This is also neccessary right now
+ * flashing the alternative BIOS. This is also necessary right now
* for embedded platforms that cannot run a PC BIOS but are using this
* device.
*/
@@ -383,7 +383,7 @@ static void it821x_passthru_bmdma_stop(struct ata_queued_cmd *qc)
* @ap: ATA port
* @device: Device number (not pointer)
*
- * Device selection hook. If neccessary perform clock switching
+ * Device selection hook. If necessary perform clock switching
*/
static void it821x_passthru_dev_select(struct ata_port *ap,
diff --git a/drivers/ata/pata_mpiix.c b/drivers/ata/pata_mpiix.c
index d5483087a3fa..c0d9e0cf208c 100644
--- a/drivers/ata/pata_mpiix.c
+++ b/drivers/ata/pata_mpiix.c
@@ -129,7 +129,7 @@ static void mpiix_set_piomode(struct ata_port *ap, struct ata_device *adev)
*
* Called when the libata layer is about to issue a command. We wrap
* this interface so that we can load the correct ATA timings if
- * neccessary. Our logic also clears TIME0/TIME1 for the other device so
+ * necessary. Our logic also clears TIME0/TIME1 for the other device so
* that, even if we get this wrong, cycles to the other device will
* be made PIO0.
*/
diff --git a/drivers/ata/pata_ns87410.c b/drivers/ata/pata_ns87410.c
index 6e8e55745b7b..9fe66fd75017 100644
--- a/drivers/ata/pata_ns87410.c
+++ b/drivers/ata/pata_ns87410.c
@@ -124,7 +124,7 @@ static void ns87410_set_piomode(struct ata_port *ap, struct ata_device *adev)
*
* Called when the libata layer is about to issue a command. We wrap
* this interface so that we can load the correct ATA timings if
- * neccessary.
+ * necessary.
*/
static unsigned int ns87410_qc_issue_prot(struct ata_queued_cmd *qc)
diff --git a/drivers/ata/pata_ns87415.c b/drivers/ata/pata_ns87415.c
index bb97ef583f9b..d0e2e50823b1 100644
--- a/drivers/ata/pata_ns87415.c
+++ b/drivers/ata/pata_ns87415.c
@@ -17,7 +17,7 @@
* TODO:
* Test PARISC SuperIO
* Get someone to test on SPARC
- * Implement lazy pio/dma switching for better performance
+ * Implement lazy pio/dma switching for better performance
* 8bit shared timing.
* See if we need to kill the FIFO for ATAPI
*/
@@ -60,10 +60,10 @@ static void ns87415_set_mode(struct ata_port *ap, struct ata_device *adev, u8 mo
u16 clocking;
u8 iordy;
u8 status;
-
+
/* Timing register format is 17 - low nybble read timing with
the high nybble being 16 - x for recovery time in PCI clocks */
-
+
ata_timing_compute(adev, adev->pio_mode, &t, T, 0);
clocking = 17 - FIT(t.active, 2, 17);
@@ -71,7 +71,7 @@ static void ns87415_set_mode(struct ata_port *ap, struct ata_device *adev, u8 mo
/* Use the same timing for read and write bytes */
clocking |= (clocking << 8);
pci_write_config_word(dev, timing, clocking);
-
+
/* Set the IORDY enable versus DMA enable on or off properly */
pci_read_config_byte(dev, 0x42, &iordy);
iordy &= ~(1 << (4 + unit));
@@ -185,7 +185,7 @@ static void ns87415_bmdma_irq_clear(struct ata_port *ap)
if (!mmio)
return;
- iowrite8((ioread8(mmio + ATA_DMA_CMD) | ATA_DMA_INTR | ATA_DMA_ERR),
+ iowrite8((ioread8(mmio + ATA_DMA_CMD) | ATA_DMA_INTR | ATA_DMA_ERR),
mmio + ATA_DMA_CMD);
}
@@ -215,6 +215,8 @@ static int ns87415_check_atapi_dma(struct ata_queued_cmd *qc)
#include <asm/superio.h>
+#define SUPERIO_IDE_MAX_RETRIES 25
+
/**
* ns87560_read_buggy - workaround buggy Super I/O chip
* @port: Port to read
diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c
index 3cd5eb2b6c91..44da09ace52c 100644
--- a/drivers/ata/pata_oldpiix.c
+++ b/drivers/ata/pata_oldpiix.c
@@ -200,7 +200,7 @@ static void oldpiix_set_dmamode (struct ata_port *ap, struct ata_device *adev)
*
* Called when the libata layer is about to issue a command. We wrap
* this interface so that we can load the correct ATA timings if
- * neccessary. Our logic also clears TIME0/TIME1 for the other device so
+ * necessary. Our logic also clears TIME0/TIME1 for the other device so
* that, even if we get this wrong, cycles to the other device will
* be made PIO0.
*/
diff --git a/drivers/ata/pata_optidma.c b/drivers/ata/pata_optidma.c
index 6b07b5b48532..f9b485a487ae 100644
--- a/drivers/ata/pata_optidma.c
+++ b/drivers/ata/pata_optidma.c
@@ -449,7 +449,7 @@ static int optiplus_with_udma(struct pci_dev *pdev)
/* Find function 1 */
dev1 = pci_get_device(0x1045, 0xC701, NULL);
- if(dev1 == NULL)
+ if (dev1 == NULL)
return 0;
/* Rev must be >= 0x10 */
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
index 782ff4ada9d1..fd36099428a4 100644
--- a/drivers/ata/pata_pcmcia.c
+++ b/drivers/ata/pata_pcmcia.c
@@ -74,8 +74,7 @@ static int pcmcia_set_mode(struct ata_link *link, struct ata_device **r_failed_d
return ata_do_set_mode(link, r_failed_dev);
if (memcmp(master->id + ATA_ID_FW_REV, slave->id + ATA_ID_FW_REV,
- ATA_ID_FW_REV_LEN + ATA_ID_PROD_LEN) == 0)
- {
+ ATA_ID_FW_REV_LEN + ATA_ID_PROD_LEN) == 0) {
/* Suspicious match, but could be two cards from
the same vendor - check serial */
if (memcmp(master->id + ATA_ID_SERNO, slave->id + ATA_ID_SERNO,
@@ -248,7 +247,8 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
goto next_entry;
io_base = pdev->io.BasePort1;
ctl_base = pdev->io.BasePort1 + 0x0e;
- } else goto next_entry;
+ } else
+ goto next_entry;
/* If we've got this far, we're done */
break;
}
@@ -285,8 +285,8 @@ next_entry:
printk(KERN_WARNING DRV_NAME ": second channel not yet supported.\n");
/*
- * Having done the PCMCIA plumbing the ATA side is relatively
- * sane.
+ * Having done the PCMCIA plumbing the ATA side is relatively
+ * sane.
*/
ret = -ENOMEM;
host = ata_host_alloc(&pdev->dev, 1);
@@ -353,6 +353,7 @@ static void pcmcia_remove_one(struct pcmcia_device *pdev)
static struct pcmcia_device_id pcmcia_devices[] = {
PCMCIA_DEVICE_FUNC_ID(4),
+ PCMCIA_DEVICE_MANF_CARD(0x0000, 0x0000), /* Corsair */
PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000), /* Hitachi */
PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000), /* I-O Data CFA */
PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001), /* Mitsubishi CFA */
@@ -362,7 +363,7 @@ static struct pcmcia_device_id pcmcia_devices[] = {
PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000), /* Toshiba */
PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000), /* Samsung */
- PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000), /* Hitachi */
+ PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000), /* Hitachi */
PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001),
PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0100), /* Viking CFA */
PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200), /* Lexar, Viking CFA */
@@ -378,6 +379,7 @@ static struct pcmcia_device_id pcmcia_devices[] = {
PCMCIA_DEVICE_PROD_ID12("EXP ", "CD-ROM", 0x0a5c52fd, 0x66536591),
PCMCIA_DEVICE_PROD_ID12("EXP ", "PnPIDE", 0x0a5c52fd, 0x0c694728),
PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e),
+ PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420),
PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae),
PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178),
PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178),
diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c
index 3d3f1558cdee..2622577521a1 100644
--- a/drivers/ata/pata_pdc2027x.c
+++ b/drivers/ata/pata_pdc2027x.c
@@ -348,7 +348,7 @@ static unsigned long pdc2027x_mode_filter(struct ata_device *adev, unsigned long
ata_id_c_string(pair->id, model_num, ATA_ID_PROD,
ATA_ID_PROD_LEN + 1);
/* If the master is a maxtor in UDMA6 then the slave should not use UDMA 6 */
- if(strstr(model_num, "Maxtor") == 0 && pair->dma_mode == XFER_UDMA_6)
+ if (strstr(model_num, "Maxtor") == 0 && pair->dma_mode == XFER_UDMA_6)
mask &= ~ (1 << (6 + ATA_SHIFT_UDMA));
return ata_pci_default_filter(adev, mask);
diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c
index 65d951618c60..bc7c2d5d8d5e 100644
--- a/drivers/ata/pata_pdc202xx_old.c
+++ b/drivers/ata/pata_pdc202xx_old.c
@@ -351,9 +351,9 @@ static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id
struct pci_dev *bridge = dev->bus->self;
/* Don't grab anything behind a Promise I2O RAID */
if (bridge && bridge->vendor == PCI_VENDOR_ID_INTEL) {
- if( bridge->device == PCI_DEVICE_ID_INTEL_I960)
+ if (bridge->device == PCI_DEVICE_ID_INTEL_I960)
return -ENODEV;
- if( bridge->device == PCI_DEVICE_ID_INTEL_I960RM)
+ if (bridge->device == PCI_DEVICE_ID_INTEL_I960RM)
return -ENODEV;
}
}
diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c
index fc72a965643d..ac03a90a6168 100644
--- a/drivers/ata/pata_platform.c
+++ b/drivers/ata/pata_platform.c
@@ -1,7 +1,7 @@
/*
* Generic platform device PATA driver
*
- * Copyright (C) 2006 Paul Mundt
+ * Copyright (C) 2006 - 2007 Paul Mundt
*
* Based on pata_pcmcia:
*
@@ -22,7 +22,7 @@
#include <linux/pata_platform.h>
#define DRV_NAME "pata_platform"
-#define DRV_VERSION "1.1"
+#define DRV_VERSION "1.2"
static int pio_mask = 1;
@@ -120,15 +120,20 @@ static void pata_platform_setup_port(struct ata_ioports *ioaddr,
* Register a platform bus IDE interface. Such interfaces are PIO and we
* assume do not support IRQ sharing.
*
- * Platform devices are expected to contain 3 resources per port:
+ * Platform devices are expected to contain at least 2 resources per port:
*
* - I/O Base (IORESOURCE_IO or IORESOURCE_MEM)
* - CTL Base (IORESOURCE_IO or IORESOURCE_MEM)
+ *
+ * and optionally:
+ *
* - IRQ (IORESOURCE_IRQ)
*
* If the base resources are both mem types, the ioremap() is handled
* here. For IORESOURCE_IO, it's assumed that there's no remapping
* necessary.
+ *
+ * If no IRQ resource is present, PIO polling mode is used instead.
*/
static int __devinit pata_platform_probe(struct platform_device *pdev)
{
@@ -137,11 +142,12 @@ static int __devinit pata_platform_probe(struct platform_device *pdev)
struct ata_port *ap;
struct pata_platform_info *pp_info;
unsigned int mmio;
+ int irq;
/*
* Simple resource validation ..
*/
- if (unlikely(pdev->num_resources != 3)) {
+ if ((pdev->num_resources != 3) && (pdev->num_resources != 2)) {
dev_err(&pdev->dev, "invalid number of resources\n");
return -EINVAL;
}
@@ -173,6 +179,13 @@ static int __devinit pata_platform_probe(struct platform_device *pdev)
(ctl_res->flags == IORESOURCE_MEM));
/*
+ * And the IRQ
+ */
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ irq = 0; /* no irq */
+
+ /*
* Now that that's out of the way, wire up the port..
*/
host = ata_host_alloc(&pdev->dev, 1);
@@ -185,6 +198,14 @@ static int __devinit pata_platform_probe(struct platform_device *pdev)
ap->flags |= ATA_FLAG_SLAVE_POSS;
/*
+ * Use polling mode if there's no IRQ
+ */
+ if (!irq) {
+ ap->flags |= ATA_FLAG_PIO_POLLING;
+ ata_port_desc(ap, "no IRQ, using PIO polling");
+ }
+
+ /*
* Handle the MMIO case
*/
if (mmio) {
@@ -213,9 +234,9 @@ static int __devinit pata_platform_probe(struct platform_device *pdev)
(unsigned long long)ctl_res->start);
/* activate */
- return ata_host_activate(host, platform_get_irq(pdev, 0),
- ata_interrupt, pp_info ? pp_info->irq_flags
- : 0, &pata_platform_sht);
+ return ata_host_activate(host, irq, irq ? ata_interrupt : NULL,
+ pp_info ? pp_info->irq_flags : 0,
+ &pata_platform_sht);
}
/**
diff --git a/drivers/ata/pata_radisys.c b/drivers/ata/pata_radisys.c
index d5b76497f4a2..8109b08fc024 100644
--- a/drivers/ata/pata_radisys.c
+++ b/drivers/ata/pata_radisys.c
@@ -161,7 +161,7 @@ static void radisys_set_dmamode (struct ata_port *ap, struct ata_device *adev)
*
* Called when the libata layer is about to issue a command. We wrap
* this interface so that we can load the correct ATA timings if
- * neccessary. Our logic also clears TIME0/TIME1 for the other device so
+ * necessary. Our logic also clears TIME0/TIME1 for the other device so
* that, even if we get this wrong, cycles to the other device will
* be made PIO0.
*/
diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c
index 21ebc485ca4b..725a8586cd6e 100644
--- a/drivers/ata/pata_sc1200.c
+++ b/drivers/ata/pata_sc1200.c
@@ -156,7 +156,7 @@ static void sc1200_set_dmamode(struct ata_port *ap, struct ata_device *adev)
*
* Called when the libata layer is about to issue a command. We wrap
* this interface so that we can load the correct ATA timings if
- * neccessary. Specifically we have a problem that there is only
+ * necessary. Specifically we have a problem that there is only
* one MWDMA/UDMA bit.
*/
diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c
index 55576138faea..ea2ef9fc15be 100644
--- a/drivers/ata/pata_scc.c
+++ b/drivers/ata/pata_scc.c
@@ -570,17 +570,8 @@ static unsigned int scc_bus_softreset(struct ata_port *ap, unsigned int devmask,
udelay(20);
out_be32(ioaddr->ctl_addr, ap->ctl);
- /* spec mandates ">= 2ms" before checking status.
- * We wait 150ms, because that was the magic delay used for
- * ATAPI devices in Hale Landis's ATADRVR, for the period of time
- * between when the ATA command register is written, and then
- * status is checked. Because waiting for "a while" before
- * checking status is fine, post SRST, we perform this magic
- * delay here as well.
- *
- * Old drivers/ide uses the 2mS rule and then waits for ready
- */
- msleep(150);
+ /* wait a while before checking status */
+ ata_wait_after_reset(ap, deadline);
/* Before we perform post reset processing we want to see if
* the bus shows 0xFF because the odd clown forgets the D7
diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c
index df68806df4be..8bed88873720 100644
--- a/drivers/ata/pata_serverworks.c
+++ b/drivers/ata/pata_serverworks.c
@@ -274,28 +274,27 @@ static void serverworks_set_dmamode(struct ata_port *ap, struct ata_device *adev
{
static const u8 dma_mode[] = { 0x77, 0x21, 0x20 };
int offset = 1 + 2 * ap->port_no - adev->devno;
- int devbits = (2 * ap->port_no + adev->devno);
+ int devbits = 2 * ap->port_no + adev->devno;
u8 ultra;
u8 ultra_cfg;
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
pci_read_config_byte(pdev, 0x54, &ultra_cfg);
+ pci_read_config_byte(pdev, 0x56 + ap->port_no, &ultra);
+ ultra &= ~(0x0F << (adev->devno * 4));
if (adev->dma_mode >= XFER_UDMA_0) {
pci_write_config_byte(pdev, 0x44 + offset, 0x20);
- pci_read_config_byte(pdev, 0x56 + ap->port_no, &ultra);
- ultra &= ~(0x0F << (ap->port_no * 4));
ultra |= (adev->dma_mode - XFER_UDMA_0)
- << (ap->port_no * 4);
- pci_write_config_byte(pdev, 0x56 + ap->port_no, ultra);
-
+ << (adev->devno * 4);
ultra_cfg |= (1 << devbits);
} else {
pci_write_config_byte(pdev, 0x44 + offset,
dma_mode[adev->dma_mode - XFER_MW_DMA_0]);
ultra_cfg &= ~(1 << devbits);
}
+ pci_write_config_byte(pdev, 0x56 + ap->port_no, ultra);
pci_write_config_byte(pdev, 0x54, ultra_cfg);
}
diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c
index 2eb75cd74a96..5c1e9cb59ecb 100644
--- a/drivers/ata/pata_sil680.c
+++ b/drivers/ata/pata_sil680.c
@@ -16,7 +16,7 @@
*
* If you have strange problems with nVidia chipset systems please
* see the SI support documentation and update your system BIOS
- * if neccessary
+ * if necessary
*
* TODO
* If we know all our devices are LBA28 (or LBA28 sized) we could use
@@ -279,7 +279,7 @@ static struct ata_port_operations sil680_port_ops = {
* Returns the final clock settings.
*/
-static u8 sil680_init_chip(struct pci_dev *pdev)
+static u8 sil680_init_chip(struct pci_dev *pdev, int *try_mmio)
{
u32 class_rev = 0;
u8 tmpbyte = 0;
@@ -297,6 +297,8 @@ static u8 sil680_init_chip(struct pci_dev *pdev)
dev_dbg(&pdev->dev, "sil680: BA5_EN = %d clock = %02X\n",
tmpbyte & 1, tmpbyte & 0x30);
+ *try_mmio = (tmpbyte & 1) || pci_resource_start(pdev, 5);
+
switch(tmpbyte & 0x30) {
case 0x00:
/* 133 clock attempt to force it on */
@@ -361,25 +363,76 @@ static int __devinit sil680_init_one(struct pci_dev *pdev,
};
const struct ata_port_info *ppi[] = { &info, NULL };
static int printed_version;
+ struct ata_host *host;
+ void __iomem *mmio_base;
+ int rc, try_mmio;
if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
- switch(sil680_init_chip(pdev))
- {
+ switch (sil680_init_chip(pdev, &try_mmio)) {
case 0:
ppi[0] = &info_slow;
break;
case 0x30:
return -ENODEV;
}
+
+ if (!try_mmio)
+ goto use_ioports;
+
+ /* Try to acquire MMIO resources and fallback to PIO if
+ * that fails
+ */
+ rc = pcim_enable_device(pdev);
+ if (rc)
+ return rc;
+ rc = pcim_iomap_regions(pdev, 1 << SIL680_MMIO_BAR, DRV_NAME);
+ if (rc)
+ goto use_ioports;
+
+ /* Allocate host and set it up */
+ host = ata_host_alloc_pinfo(&pdev->dev, ppi, 2);
+ if (!host)
+ return -ENOMEM;
+ host->iomap = pcim_iomap_table(pdev);
+
+ /* Setup DMA masks */
+ rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
+ if (rc)
+ return rc;
+ rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
+ if (rc)
+ return rc;
+ pci_set_master(pdev);
+
+ /* Get MMIO base and initialize port addresses */
+ mmio_base = host->iomap[SIL680_MMIO_BAR];
+ host->ports[0]->ioaddr.bmdma_addr = mmio_base + 0x00;
+ host->ports[0]->ioaddr.cmd_addr = mmio_base + 0x80;
+ host->ports[0]->ioaddr.ctl_addr = mmio_base + 0x8a;
+ host->ports[0]->ioaddr.altstatus_addr = mmio_base + 0x8a;
+ ata_std_ports(&host->ports[0]->ioaddr);
+ host->ports[1]->ioaddr.bmdma_addr = mmio_base + 0x08;
+ host->ports[1]->ioaddr.cmd_addr = mmio_base + 0xc0;
+ host->ports[1]->ioaddr.ctl_addr = mmio_base + 0xca;
+ host->ports[1]->ioaddr.altstatus_addr = mmio_base + 0xca;
+ ata_std_ports(&host->ports[1]->ioaddr);
+
+ /* Register & activate */
+ return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED,
+ &sil680_sht);
+
+use_ioports:
return ata_pci_init_one(pdev, ppi);
}
#ifdef CONFIG_PM
static int sil680_reinit_one(struct pci_dev *pdev)
{
- sil680_init_chip(pdev);
+ int try_mmio;
+
+ sil680_init_chip(pdev, &try_mmio);
return ata_pci_device_resume(pdev);
}
#endif
diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c
index 5d41b6612d7f..a4175fbdd170 100644
--- a/drivers/ata/pata_via.c
+++ b/drivers/ata/pata_via.c
@@ -176,7 +176,7 @@ static int via_cable_detect(struct ata_port *ap) {
if ((config->flags & VIA_UDMA) < VIA_UDMA_66)
return ATA_CBL_PATA40;
/* UDMA 66 chips have only drive side logic */
- else if((config->flags & VIA_UDMA) < VIA_UDMA_100)
+ else if ((config->flags & VIA_UDMA) < VIA_UDMA_100)
return ATA_CBL_PATA_UNK;
/* UDMA 100 or later */
pci_read_config_dword(pdev, 0x50, &ata66);
@@ -420,7 +420,7 @@ static struct ata_port_operations via_port_ops_noirq = {
* @pdev: PCI device
* @flags: configuration flags
*
- * Set the FIFO properties for this device if neccessary. Used both on
+ * Set the FIFO properties for this device if necessary. Used both on
* set up and on and the resume path
*/
diff --git a/drivers/ata/pata_winbond.c b/drivers/ata/pata_winbond.c
index 549cbbe9fd07..311cdb3a5566 100644
--- a/drivers/ata/pata_winbond.c
+++ b/drivers/ata/pata_winbond.c
@@ -279,7 +279,7 @@ static __init int winbond_init(void)
if (request_region(port, 2, "pata_winbond")) {
ret = winbond_init_one(port);
- if(ret <= 0)
+ if (ret <= 0)
release_region(port, 2);
else ct+= ret;
}
diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c
index 8d1b03d5bcb1..bd4c2a3c88d7 100644
--- a/drivers/ata/pdc_adma.c
+++ b/drivers/ata/pdc_adma.c
@@ -47,10 +47,10 @@
#define DRV_VERSION "1.0"
/* macro to calculate base address for ATA regs */
-#define ADMA_ATA_REGS(base,port_no) ((base) + ((port_no) * 0x40))
+#define ADMA_ATA_REGS(base, port_no) ((base) + ((port_no) * 0x40))
/* macro to calculate base address for ADMA regs */
-#define ADMA_REGS(base,port_no) ((base) + 0x80 + ((port_no) * 0x20))
+#define ADMA_REGS(base, port_no) ((base) + 0x80 + ((port_no) * 0x20))
/* macro to obtain addresses from ata_port */
#define ADMA_PORT_REGS(ap) \
@@ -128,7 +128,7 @@ struct adma_port_priv {
adma_state_t state;
};
-static int adma_ata_init_one (struct pci_dev *pdev,
+static int adma_ata_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent);
static int adma_port_start(struct ata_port *ap);
static void adma_host_stop(struct ata_host *host);
@@ -318,7 +318,7 @@ static int adma_fill_sg(struct ata_queued_cmd *qc)
struct scatterlist *sg;
struct ata_port *ap = qc->ap;
struct adma_port_priv *pp = ap->private_data;
- u8 *buf = pp->pkt;
+ u8 *buf = pp->pkt, *last_buf = NULL;
int i = (2 + buf[3]) * 8;
u8 pFLAGS = pORD | ((qc->tf.flags & ATA_TFLAG_WRITE) ? pDIRO : 0);
@@ -334,20 +334,23 @@ static int adma_fill_sg(struct ata_queued_cmd *qc)
*(__le32 *)(buf + i) = cpu_to_le32(len);
i += 4;
- if (ata_sg_is_last(sg, qc))
- pFLAGS |= pEND;
+ last_buf = &buf[i];
buf[i++] = pFLAGS;
buf[i++] = qc->dev->dma_mode & 0xf;
buf[i++] = 0; /* pPKLW */
buf[i++] = 0; /* reserved */
- *(__le32 *)(buf + i)
- = (pFLAGS & pEND) ? 0 : cpu_to_le32(pp->pkt_dma + i + 4);
+ *(__le32 *)(buf + i) =
+ (pFLAGS & pEND) ? 0 : cpu_to_le32(pp->pkt_dma + i + 4);
i += 4;
VPRINTK("PRD[%u] = (0x%lX, 0x%X)\n", i/4,
(unsigned long)addr, len);
}
+
+ if (likely(last_buf))
+ *last_buf |= pEND;
+
return i;
}
@@ -614,7 +617,7 @@ static int adma_port_start(struct ata_port *ap)
return -ENOMEM;
/* paranoia? */
if ((pp->pkt_dma & 7) != 0) {
- printk("bad alignment for pp->pkt_dma: %08x\n",
+ printk(KERN_ERR "bad alignment for pp->pkt_dma: %08x\n",
(u32)pp->pkt_dma);
return -ENOMEM;
}
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c
new file mode 100644
index 000000000000..d015b4adcfe0
--- /dev/null
+++ b/drivers/ata/sata_fsl.c
@@ -0,0 +1,1395 @@
+/*
+ * drivers/ata/sata_fsl.c
+ *
+ * Freescale 3.0Gbps SATA device driver
+ *
+ * Author: Ashish Kalra <ashish.kalra@freescale.com>
+ * Li Yang <leoli@freescale.com>
+ *
+ * Copyright (c) 2006-2007 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_cmnd.h>
+#include <linux/libata.h>
+#include <asm/io.h>
+#include <linux/of_platform.h>
+
+/* Controller information */
+enum {
+ SATA_FSL_QUEUE_DEPTH = 16,
+ SATA_FSL_MAX_PRD = 63,
+ SATA_FSL_MAX_PRD_USABLE = SATA_FSL_MAX_PRD - 1,
+ SATA_FSL_MAX_PRD_DIRECT = 16, /* Direct PRDT entries */
+
+ SATA_FSL_HOST_FLAGS = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+ ATA_FLAG_NCQ),
+ SATA_FSL_HOST_LFLAGS = ATA_LFLAG_SKIP_D2H_BSY,
+
+ SATA_FSL_MAX_CMDS = SATA_FSL_QUEUE_DEPTH,
+ SATA_FSL_CMD_HDR_SIZE = 16, /* 4 DWORDS */
+ SATA_FSL_CMD_SLOT_SIZE = (SATA_FSL_MAX_CMDS * SATA_FSL_CMD_HDR_SIZE),
+
+ /*
+ * SATA-FSL host controller supports a max. of (15+1) direct PRDEs, and
+ * chained indirect PRDEs upto a max count of 63.
+ * We are allocating an array of 63 PRDEs contigiously, but PRDE#15 will
+ * be setup as an indirect descriptor, pointing to it's next
+ * (contigious) PRDE. Though chained indirect PRDE arrays are
+ * supported,it will be more efficient to use a direct PRDT and
+ * a single chain/link to indirect PRDE array/PRDT.
+ */
+
+ SATA_FSL_CMD_DESC_CFIS_SZ = 32,
+ SATA_FSL_CMD_DESC_SFIS_SZ = 32,
+ SATA_FSL_CMD_DESC_ACMD_SZ = 16,
+ SATA_FSL_CMD_DESC_RSRVD = 16,
+
+ SATA_FSL_CMD_DESC_SIZE = (SATA_FSL_CMD_DESC_CFIS_SZ +
+ SATA_FSL_CMD_DESC_SFIS_SZ +
+ SATA_FSL_CMD_DESC_ACMD_SZ +
+ SATA_FSL_CMD_DESC_RSRVD +
+ SATA_FSL_MAX_PRD * 16),
+
+ SATA_FSL_CMD_DESC_OFFSET_TO_PRDT =
+ (SATA_FSL_CMD_DESC_CFIS_SZ +
+ SATA_FSL_CMD_DESC_SFIS_SZ +
+ SATA_FSL_CMD_DESC_ACMD_SZ +
+ SATA_FSL_CMD_DESC_RSRVD),
+
+ SATA_FSL_CMD_DESC_AR_SZ = (SATA_FSL_CMD_DESC_SIZE * SATA_FSL_MAX_CMDS),
+ SATA_FSL_PORT_PRIV_DMA_SZ = (SATA_FSL_CMD_SLOT_SIZE +
+ SATA_FSL_CMD_DESC_AR_SZ),
+
+ /*
+ * MPC8315 has two SATA controllers, SATA1 & SATA2
+ * (one port per controller)
+ * MPC837x has 2/4 controllers, one port per controller
+ */
+
+ SATA_FSL_MAX_PORTS = 1,
+
+ SATA_FSL_IRQ_FLAG = IRQF_SHARED,
+};
+
+/*
+* Host Controller command register set - per port
+*/
+enum {
+ CQ = 0,
+ CA = 8,
+ CC = 0x10,
+ CE = 0x18,
+ DE = 0x20,
+ CHBA = 0x24,
+ HSTATUS = 0x28,
+ HCONTROL = 0x2C,
+ CQPMP = 0x30,
+ SIGNATURE = 0x34,
+ ICC = 0x38,
+
+ /*
+ * Host Status Register (HStatus) bitdefs
+ */
+ ONLINE = (1 << 31),
+ GOING_OFFLINE = (1 << 30),
+ BIST_ERR = (1 << 29),
+
+ FATAL_ERR_HC_MASTER_ERR = (1 << 18),
+ FATAL_ERR_PARITY_ERR_TX = (1 << 17),
+ FATAL_ERR_PARITY_ERR_RX = (1 << 16),
+ FATAL_ERR_DATA_UNDERRUN = (1 << 13),
+ FATAL_ERR_DATA_OVERRUN = (1 << 12),
+ FATAL_ERR_CRC_ERR_TX = (1 << 11),
+ FATAL_ERR_CRC_ERR_RX = (1 << 10),
+ FATAL_ERR_FIFO_OVRFL_TX = (1 << 9),
+ FATAL_ERR_FIFO_OVRFL_RX = (1 << 8),
+
+ FATAL_ERROR_DECODE = FATAL_ERR_HC_MASTER_ERR |
+ FATAL_ERR_PARITY_ERR_TX |
+ FATAL_ERR_PARITY_ERR_RX |
+ FATAL_ERR_DATA_UNDERRUN |
+ FATAL_ERR_DATA_OVERRUN |
+ FATAL_ERR_CRC_ERR_TX |
+ FATAL_ERR_CRC_ERR_RX |
+ FATAL_ERR_FIFO_OVRFL_TX | FATAL_ERR_FIFO_OVRFL_RX,
+
+ INT_ON_FATAL_ERR = (1 << 5),
+ INT_ON_PHYRDY_CHG = (1 << 4),
+
+ INT_ON_SIGNATURE_UPDATE = (1 << 3),
+ INT_ON_SNOTIFY_UPDATE = (1 << 2),
+ INT_ON_SINGL_DEVICE_ERR = (1 << 1),
+ INT_ON_CMD_COMPLETE = 1,
+
+ INT_ON_ERROR = INT_ON_FATAL_ERR |
+ INT_ON_PHYRDY_CHG | INT_ON_SINGL_DEVICE_ERR,
+
+ /*
+ * Host Control Register (HControl) bitdefs
+ */
+ HCONTROL_ONLINE_PHY_RST = (1 << 31),
+ HCONTROL_FORCE_OFFLINE = (1 << 30),
+ HCONTROL_PARITY_PROT_MOD = (1 << 14),
+ HCONTROL_DPATH_PARITY = (1 << 12),
+ HCONTROL_SNOOP_ENABLE = (1 << 10),
+ HCONTROL_PMP_ATTACHED = (1 << 9),
+ HCONTROL_COPYOUT_STATFIS = (1 << 8),
+ IE_ON_FATAL_ERR = (1 << 5),
+ IE_ON_PHYRDY_CHG = (1 << 4),
+ IE_ON_SIGNATURE_UPDATE = (1 << 3),
+ IE_ON_SNOTIFY_UPDATE = (1 << 2),
+ IE_ON_SINGL_DEVICE_ERR = (1 << 1),
+ IE_ON_CMD_COMPLETE = 1,
+
+ DEFAULT_PORT_IRQ_ENABLE_MASK = IE_ON_FATAL_ERR | IE_ON_PHYRDY_CHG |
+ IE_ON_SIGNATURE_UPDATE |
+ IE_ON_SINGL_DEVICE_ERR | IE_ON_CMD_COMPLETE,
+
+ EXT_INDIRECT_SEG_PRD_FLAG = (1 << 31),
+ DATA_SNOOP_ENABLE = (1 << 22),
+};
+
+/*
+ * SATA Superset Registers
+ */
+enum {
+ SSTATUS = 0,
+ SERROR = 4,
+ SCONTROL = 8,
+ SNOTIFY = 0xC,
+};
+
+/*
+ * Control Status Register Set
+ */
+enum {
+ TRANSCFG = 0,
+ TRANSSTATUS = 4,
+ LINKCFG = 8,
+ LINKCFG1 = 0xC,
+ LINKCFG2 = 0x10,
+ LINKSTATUS = 0x14,
+ LINKSTATUS1 = 0x18,
+ PHYCTRLCFG = 0x1C,
+ COMMANDSTAT = 0x20,
+};
+
+/* PHY (link-layer) configuration control */
+enum {
+ PHY_BIST_ENABLE = 0x01,
+};
+
+/*
+ * Command Header Table entry, i.e, command slot
+ * 4 Dwords per command slot, command header size == 64 Dwords.
+ */
+struct cmdhdr_tbl_entry {
+ u32 cda;
+ u32 prde_fis_len;
+ u32 ttl;
+ u32 desc_info;
+};
+
+/*
+ * Description information bitdefs
+ */
+enum {
+ VENDOR_SPECIFIC_BIST = (1 << 10),
+ CMD_DESC_SNOOP_ENABLE = (1 << 9),
+ FPDMA_QUEUED_CMD = (1 << 8),
+ SRST_CMD = (1 << 7),
+ BIST = (1 << 6),
+ ATAPI_CMD = (1 << 5),
+};
+
+/*
+ * Command Descriptor
+ */
+struct command_desc {
+ u8 cfis[8 * 4];
+ u8 sfis[8 * 4];
+ u8 acmd[4 * 4];
+ u8 fill[4 * 4];
+ u32 prdt[SATA_FSL_MAX_PRD_DIRECT * 4];
+ u32 prdt_indirect[(SATA_FSL_MAX_PRD - SATA_FSL_MAX_PRD_DIRECT) * 4];
+};
+
+/*
+ * Physical region table descriptor(PRD)
+ */
+
+struct prde {
+ u32 dba;
+ u8 fill[2 * 4];
+ u32 ddc_and_ext;
+};
+
+/*
+ * ata_port private data
+ * This is our per-port instance data.
+ */
+struct sata_fsl_port_priv {
+ struct cmdhdr_tbl_entry *cmdslot;
+ dma_addr_t cmdslot_paddr;
+ struct command_desc *cmdentry;
+ dma_addr_t cmdentry_paddr;
+
+ /*
+ * SATA FSL controller has a Status FIS which should contain the
+ * received D2H FIS & taskfile registers. This SFIS is present in
+ * the command descriptor, and to have a ready reference to it,
+ * we are caching it here, quite similar to what is done in H/W on
+ * AHCI compliant devices by copying taskfile fields to a 32-bit
+ * register.
+ */
+
+ struct ata_taskfile tf;
+};
+
+/*
+ * ata_port->host_set private data
+ */
+struct sata_fsl_host_priv {
+ void __iomem *hcr_base;
+ void __iomem *ssr_base;
+ void __iomem *csr_base;
+ int irq;
+};
+
+static inline unsigned int sata_fsl_tag(unsigned int tag,
+ void __iomem *hcr_base)
+{
+ /* We let libATA core do actual (queue) tag allocation */
+
+ /* all non NCQ/queued commands should have tag#0 */
+ if (ata_tag_internal(tag)) {
+ DPRINTK("mapping internal cmds to tag#0\n");
+ return 0;
+ }
+
+ if (unlikely(tag >= SATA_FSL_QUEUE_DEPTH)) {
+ DPRINTK("tag %d invalid : out of range\n", tag);
+ return 0;
+ }
+
+ if (unlikely((ioread32(hcr_base + CQ)) & (1 << tag))) {
+ DPRINTK("tag %d invalid : in use!!\n", tag);
+ return 0;
+ }
+
+ return tag;
+}
+
+static void sata_fsl_setup_cmd_hdr_entry(struct sata_fsl_port_priv *pp,
+ unsigned int tag, u32 desc_info,
+ u32 data_xfer_len, u8 num_prde,
+ u8 fis_len)
+{
+ dma_addr_t cmd_descriptor_address;
+
+ cmd_descriptor_address = pp->cmdentry_paddr +
+ tag * SATA_FSL_CMD_DESC_SIZE;
+
+ /* NOTE: both data_xfer_len & fis_len are Dword counts */
+
+ pp->cmdslot[tag].cda = cpu_to_le32(cmd_descriptor_address);
+ pp->cmdslot[tag].prde_fis_len =
+ cpu_to_le32((num_prde << 16) | (fis_len << 2));
+ pp->cmdslot[tag].ttl = cpu_to_le32(data_xfer_len & ~0x03);
+ pp->cmdslot[tag].desc_info = cpu_to_le32(desc_info | (tag & 0x1F));
+
+ VPRINTK("cda=0x%x, prde_fis_len=0x%x, ttl=0x%x, di=0x%x\n",
+ pp->cmdslot[tag].cda,
+ pp->cmdslot[tag].prde_fis_len,
+ pp->cmdslot[tag].ttl, pp->cmdslot[tag].desc_info);
+
+}
+
+static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc,
+ u32 *ttl, dma_addr_t cmd_desc_paddr)
+{
+ struct scatterlist *sg;
+ unsigned int num_prde = 0;
+ u32 ttl_dwords = 0;
+
+ /*
+ * NOTE : direct & indirect prdt's are contigiously allocated
+ */
+ struct prde *prd = (struct prde *)&((struct command_desc *)
+ cmd_desc)->prdt;
+
+ struct prde *prd_ptr_to_indirect_ext = NULL;
+ unsigned indirect_ext_segment_sz = 0;
+ dma_addr_t indirect_ext_segment_paddr;
+
+ VPRINTK("SATA FSL : cd = 0x%x, prd = 0x%x\n", cmd_desc, prd);
+
+ indirect_ext_segment_paddr = cmd_desc_paddr +
+ SATA_FSL_CMD_DESC_OFFSET_TO_PRDT + SATA_FSL_MAX_PRD_DIRECT * 16;
+
+ ata_for_each_sg(sg, qc) {
+ dma_addr_t sg_addr = sg_dma_address(sg);
+ u32 sg_len = sg_dma_len(sg);
+
+ VPRINTK("SATA FSL : fill_sg, sg_addr = 0x%x, sg_len = %d\n",
+ sg_addr, sg_len);
+
+ /* warn if each s/g element is not dword aligned */
+ if (sg_addr & 0x03)
+ ata_port_printk(qc->ap, KERN_ERR,
+ "s/g addr unaligned : 0x%x\n", sg_addr);
+ if (sg_len & 0x03)
+ ata_port_printk(qc->ap, KERN_ERR,
+ "s/g len unaligned : 0x%x\n", sg_len);
+
+ if ((num_prde == (SATA_FSL_MAX_PRD_DIRECT - 1)) &&
+ (qc->n_iter + 1 != qc->n_elem)) {
+ VPRINTK("setting indirect prde\n");
+ prd_ptr_to_indirect_ext = prd;
+ prd->dba = cpu_to_le32(indirect_ext_segment_paddr);
+ indirect_ext_segment_sz = 0;
+ ++prd;
+ ++num_prde;
+ }
+
+ ttl_dwords += sg_len;
+ prd->dba = cpu_to_le32(sg_addr);
+ prd->ddc_and_ext =
+ cpu_to_le32(DATA_SNOOP_ENABLE | (sg_len & ~0x03));
+
+ VPRINTK("sg_fill, ttl=%d, dba=0x%x, ddc=0x%x\n",
+ ttl_dwords, prd->dba, prd->ddc_and_ext);
+
+ ++num_prde;
+ ++prd;
+ if (prd_ptr_to_indirect_ext)
+ indirect_ext_segment_sz += sg_len;
+ }
+
+ if (prd_ptr_to_indirect_ext) {
+ /* set indirect extension flag along with indirect ext. size */
+ prd_ptr_to_indirect_ext->ddc_and_ext =
+ cpu_to_le32((EXT_INDIRECT_SEG_PRD_FLAG |
+ DATA_SNOOP_ENABLE |
+ (indirect_ext_segment_sz & ~0x03)));
+ }
+
+ *ttl = ttl_dwords;
+ return num_prde;
+}
+
+static void sata_fsl_qc_prep(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct sata_fsl_port_priv *pp = ap->private_data;
+ struct sata_fsl_host_priv *host_priv = ap->host->private_data;
+ void __iomem *hcr_base = host_priv->hcr_base;
+ unsigned int tag = sata_fsl_tag(qc->tag, hcr_base);
+ struct command_desc *cd;
+ u32 desc_info = CMD_DESC_SNOOP_ENABLE;
+ u32 num_prde = 0;
+ u32 ttl_dwords = 0;
+ dma_addr_t cd_paddr;
+
+ cd = (struct command_desc *)pp->cmdentry + tag;
+ cd_paddr = pp->cmdentry_paddr + tag * SATA_FSL_CMD_DESC_SIZE;
+
+ ata_tf_to_fis(&qc->tf, 0, 1, (u8 *) &cd->cfis);
+
+ VPRINTK("Dumping cfis : 0x%x, 0x%x, 0x%x\n",
+ cd->cfis[0], cd->cfis[1], cd->cfis[2]);
+
+ if (qc->tf.protocol == ATA_PROT_NCQ) {
+ VPRINTK("FPDMA xfer,Sctor cnt[0:7],[8:15] = %d,%d\n",
+ cd->cfis[3], cd->cfis[11]);
+ }
+
+ /* setup "ACMD - atapi command" in cmd. desc. if this is ATAPI cmd */
+ if (is_atapi_taskfile(&qc->tf)) {
+ desc_info |= ATAPI_CMD;
+ memset((void *)&cd->acmd, 0, 32);
+ memcpy((void *)&cd->acmd, qc->cdb, qc->dev->cdb_len);
+ }
+
+ if (qc->flags & ATA_QCFLAG_DMAMAP)
+ num_prde = sata_fsl_fill_sg(qc, (void *)cd,
+ &ttl_dwords, cd_paddr);
+
+ if (qc->tf.protocol == ATA_PROT_NCQ)
+ desc_info |= FPDMA_QUEUED_CMD;
+
+ sata_fsl_setup_cmd_hdr_entry(pp, tag, desc_info, ttl_dwords,
+ num_prde, 5);
+
+ VPRINTK("SATA FSL : xx_qc_prep, di = 0x%x, ttl = %d, num_prde = %d\n",
+ desc_info, ttl_dwords, num_prde);
+}
+
+static unsigned int sata_fsl_qc_issue(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct sata_fsl_host_priv *host_priv = ap->host->private_data;
+ void __iomem *hcr_base = host_priv->hcr_base;
+ unsigned int tag = sata_fsl_tag(qc->tag, hcr_base);
+
+ VPRINTK("xx_qc_issue called,CQ=0x%x,CA=0x%x,CE=0x%x,CC=0x%x\n",
+ ioread32(CQ + hcr_base),
+ ioread32(CA + hcr_base),
+ ioread32(CE + hcr_base), ioread32(CC + hcr_base));
+
+ /* Simply queue command to the controller/device */
+ iowrite32(1 << tag, CQ + hcr_base);
+
+ VPRINTK("xx_qc_issue called, tag=%d, CQ=0x%x, CA=0x%x\n",
+ tag, ioread32(CQ + hcr_base), ioread32(CA + hcr_base));
+
+ VPRINTK("CE=0x%x, DE=0x%x, CC=0x%x, CmdStat = 0x%x\n",
+ ioread32(CE + hcr_base),
+ ioread32(DE + hcr_base),
+ ioread32(CC + hcr_base), ioread32(COMMANDSTAT + csr_base));
+
+ return 0;
+}
+
+static int sata_fsl_scr_write(struct ata_port *ap, unsigned int sc_reg_in,
+ u32 val)
+{
+ struct sata_fsl_host_priv *host_priv = ap->host->private_data;
+ void __iomem *ssr_base = host_priv->ssr_base;
+ unsigned int sc_reg;
+
+ switch (sc_reg_in) {
+ case SCR_STATUS:
+ case SCR_ERROR:
+ case SCR_CONTROL:
+ case SCR_ACTIVE:
+ sc_reg = sc_reg_in;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ VPRINTK("xx_scr_write, reg_in = %d\n", sc_reg);
+
+ iowrite32(val, ssr_base + (sc_reg * 4));
+ return 0;
+}
+
+static int sata_fsl_scr_read(struct ata_port *ap, unsigned int sc_reg_in,
+ u32 *val)
+{
+ struct sata_fsl_host_priv *host_priv = ap->host->private_data;
+ void __iomem *ssr_base = host_priv->ssr_base;
+ unsigned int sc_reg;
+
+ switch (sc_reg_in) {
+ case SCR_STATUS:
+ case SCR_ERROR:
+ case SCR_CONTROL:
+ case SCR_ACTIVE:
+ sc_reg = sc_reg_in;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ VPRINTK("xx_scr_read, reg_in = %d\n", sc_reg);
+
+ *val = ioread32(ssr_base + (sc_reg * 4));
+ return 0;
+}
+
+static void sata_fsl_freeze(struct ata_port *ap)
+{
+ struct sata_fsl_host_priv *host_priv = ap->host->private_data;
+ void __iomem *hcr_base = host_priv->hcr_base;
+ u32 temp;
+
+ VPRINTK("xx_freeze, CQ=0x%x, CA=0x%x, CE=0x%x, DE=0x%x\n",
+ ioread32(CQ + hcr_base),
+ ioread32(CA + hcr_base),
+ ioread32(CE + hcr_base), ioread32(DE + hcr_base));
+ VPRINTK("CmdStat = 0x%x\n", ioread32(csr_base + COMMANDSTAT));
+
+ /* disable interrupts on the controller/port */
+ temp = ioread32(hcr_base + HCONTROL);
+ iowrite32((temp & ~0x3F), hcr_base + HCONTROL);
+
+ VPRINTK("in xx_freeze : HControl = 0x%x, HStatus = 0x%x\n",
+ ioread32(hcr_base + HCONTROL), ioread32(hcr_base + HSTATUS));
+}
+
+static void sata_fsl_thaw(struct ata_port *ap)
+{
+ struct sata_fsl_host_priv *host_priv = ap->host->private_data;
+ void __iomem *hcr_base = host_priv->hcr_base;
+ u32 temp;
+
+ /* ack. any pending IRQs for this controller/port */
+ temp = ioread32(hcr_base + HSTATUS);
+
+ VPRINTK("xx_thaw, pending IRQs = 0x%x\n", (temp & 0x3F));
+
+ if (temp & 0x3F)
+ iowrite32((temp & 0x3F), hcr_base + HSTATUS);
+
+ /* enable interrupts on the controller/port */
+ temp = ioread32(hcr_base + HCONTROL);
+ iowrite32((temp | DEFAULT_PORT_IRQ_ENABLE_MASK), hcr_base + HCONTROL);
+
+ VPRINTK("xx_thaw : HControl = 0x%x, HStatus = 0x%x\n",
+ ioread32(hcr_base + HCONTROL), ioread32(hcr_base + HSTATUS));
+}
+
+/*
+ * NOTE : 1st D2H FIS from device does not update sfis in command descriptor.
+ */
+static inline void sata_fsl_cache_taskfile_from_d2h_fis(struct ata_queued_cmd
+ *qc,
+ struct ata_port *ap)
+{
+ struct sata_fsl_port_priv *pp = ap->private_data;
+ struct sata_fsl_host_priv *host_priv = ap->host->private_data;
+ void __iomem *hcr_base = host_priv->hcr_base;
+ unsigned int tag = sata_fsl_tag(qc->tag, hcr_base);
+ struct command_desc *cd;
+
+ cd = pp->cmdentry + tag;
+
+ ata_tf_from_fis(cd->sfis, &pp->tf);
+}
+
+static u8 sata_fsl_check_status(struct ata_port *ap)
+{
+ struct sata_fsl_port_priv *pp = ap->private_data;
+
+ return pp->tf.command;
+}
+
+static void sata_fsl_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+{
+ struct sata_fsl_port_priv *pp = ap->private_data;
+
+ *tf = pp->tf;
+}
+
+static int sata_fsl_port_start(struct ata_port *ap)
+{
+ struct device *dev = ap->host->dev;
+ struct sata_fsl_port_priv *pp;
+ int retval;
+ void *mem;
+ dma_addr_t mem_dma;
+ struct sata_fsl_host_priv *host_priv = ap->host->private_data;
+ void __iomem *hcr_base = host_priv->hcr_base;
+ u32 temp;
+
+ pp = kzalloc(sizeof(*pp), GFP_KERNEL);
+ if (!pp)
+ return -ENOMEM;
+
+ /*
+ * allocate per command dma alignment pad buffer, which is used
+ * internally by libATA to ensure that all transfers ending on
+ * unaligned boundaries are padded, to align on Dword boundaries
+ */
+ retval = ata_pad_alloc(ap, dev);
+ if (retval) {
+ kfree(pp);
+ return retval;
+ }
+
+ mem = dma_alloc_coherent(dev, SATA_FSL_PORT_PRIV_DMA_SZ, &mem_dma,
+ GFP_KERNEL);
+ if (!mem) {
+ ata_pad_free(ap, dev);
+ kfree(pp);
+ return -ENOMEM;
+ }
+ memset(mem, 0, SATA_FSL_PORT_PRIV_DMA_SZ);
+
+ pp->cmdslot = mem;
+ pp->cmdslot_paddr = mem_dma;
+
+ mem += SATA_FSL_CMD_SLOT_SIZE;
+ mem_dma += SATA_FSL_CMD_SLOT_SIZE;
+
+ pp->cmdentry = mem;
+ pp->cmdentry_paddr = mem_dma;
+
+ ap->private_data = pp;
+
+ VPRINTK("CHBA = 0x%x, cmdentry_phys = 0x%x\n",
+ pp->cmdslot_paddr, pp->cmdentry_paddr);
+
+ /* Now, update the CHBA register in host controller cmd register set */
+ iowrite32(pp->cmdslot_paddr & 0xffffffff, hcr_base + CHBA);
+
+ /*
+ * Now, we can bring the controller on-line & also initiate
+ * the COMINIT sequence, we simply return here and the boot-probing
+ * & device discovery process is re-initiated by libATA using a
+ * Softreset EH (dummy) session. Hence, boot probing and device
+ * discovey will be part of sata_fsl_softreset() callback.
+ */
+
+ temp = ioread32(hcr_base + HCONTROL);
+ iowrite32((temp | HCONTROL_ONLINE_PHY_RST), hcr_base + HCONTROL);
+
+ VPRINTK("HStatus = 0x%x\n", ioread32(hcr_base + HSTATUS));
+ VPRINTK("HControl = 0x%x\n", ioread32(hcr_base + HCONTROL));
+ VPRINTK("CHBA = 0x%x\n", ioread32(hcr_base + CHBA));
+
+#ifdef CONFIG_MPC8315_DS
+ /*
+ * Workaround for 8315DS board 3gbps link-up issue,
+ * currently limit SATA port to GEN1 speed
+ */
+ sata_fsl_scr_read(ap, SCR_CONTROL, &temp);
+ temp &= ~(0xF << 4);
+ temp |= (0x1 << 4);
+ sata_fsl_scr_write(ap, SCR_CONTROL, temp);
+
+ sata_fsl_scr_read(ap, SCR_CONTROL, &temp);
+ dev_printk(KERN_WARNING, dev, "scr_control, speed limited to %x\n",
+ temp);
+#endif
+
+ return 0;
+}
+
+static void sata_fsl_port_stop(struct ata_port *ap)
+{
+ struct device *dev = ap->host->dev;
+ struct sata_fsl_port_priv *pp = ap->private_data;
+ struct sata_fsl_host_priv *host_priv = ap->host->private_data;
+ void __iomem *hcr_base = host_priv->hcr_base;
+ u32 temp;
+
+ /*
+ * Force host controller to go off-line, aborting current operations
+ */
+ temp = ioread32(hcr_base + HCONTROL);
+ temp &= ~HCONTROL_ONLINE_PHY_RST;
+ temp |= HCONTROL_FORCE_OFFLINE;
+ iowrite32(temp, hcr_base + HCONTROL);
+
+ /* Poll for controller to go offline - should happen immediately */
+ ata_wait_register(hcr_base + HSTATUS, ONLINE, ONLINE, 1, 1);
+
+ ap->private_data = NULL;
+ dma_free_coherent(dev, SATA_FSL_PORT_PRIV_DMA_SZ,
+ pp->cmdslot, pp->cmdslot_paddr);
+
+ ata_pad_free(ap, dev);
+ kfree(pp);
+}
+
+static unsigned int sata_fsl_dev_classify(struct ata_port *ap)
+{
+ struct sata_fsl_host_priv *host_priv = ap->host->private_data;
+ void __iomem *hcr_base = host_priv->hcr_base;
+ struct ata_taskfile tf;
+ u32 temp;
+
+ temp = ioread32(hcr_base + SIGNATURE);
+
+ VPRINTK("raw sig = 0x%x\n", temp);
+ VPRINTK("HStatus = 0x%x\n", ioread32(hcr_base + HSTATUS));
+ VPRINTK("HControl = 0x%x\n", ioread32(hcr_base + HCONTROL));
+
+ tf.lbah = (temp >> 24) & 0xff;
+ tf.lbam = (temp >> 16) & 0xff;
+ tf.lbal = (temp >> 8) & 0xff;
+ tf.nsect = temp & 0xff;
+
+ return ata_dev_classify(&tf);
+}
+
+static int sata_fsl_softreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline)
+{
+ struct ata_port *ap = link->ap;
+ struct sata_fsl_port_priv *pp = ap->private_data;
+ struct sata_fsl_host_priv *host_priv = ap->host->private_data;
+ void __iomem *hcr_base = host_priv->hcr_base;
+ u32 temp;
+ struct ata_taskfile tf;
+ u8 *cfis;
+ u32 Serror;
+ int i = 0;
+ unsigned long start_jiffies;
+
+ DPRINTK("in xx_softreset\n");
+
+try_offline_again:
+ /*
+ * Force host controller to go off-line, aborting current operations
+ */
+ temp = ioread32(hcr_base + HCONTROL);
+ temp &= ~HCONTROL_ONLINE_PHY_RST;
+ iowrite32(temp, hcr_base + HCONTROL);
+
+ /* Poll for controller to go offline */
+ temp = ata_wait_register(hcr_base + HSTATUS, ONLINE, ONLINE, 1, 500);
+
+ if (temp & ONLINE) {
+ ata_port_printk(ap, KERN_ERR,
+ "Softreset failed, not off-lined %d\n", i);
+
+ /*
+ * Try to offline controller atleast twice
+ */
+ i++;
+ if (i == 2)
+ goto err;
+ else
+ goto try_offline_again;
+ }
+
+ DPRINTK("softreset, controller off-lined\n");
+ VPRINTK("HStatus = 0x%x\n", ioread32(hcr_base + HSTATUS));
+ VPRINTK("HControl = 0x%x\n", ioread32(hcr_base + HCONTROL));
+
+ /*
+ * PHY reset should remain asserted for atleast 1ms
+ */
+ msleep(1);
+
+ /*
+ * Now, bring the host controller online again, this can take time
+ * as PHY reset and communication establishment, 1st D2H FIS and
+ * device signature update is done, on safe side assume 500ms
+ * NOTE : Host online status may be indicated immediately!!
+ */
+
+ temp = ioread32(hcr_base + HCONTROL);
+ temp |= (HCONTROL_ONLINE_PHY_RST | HCONTROL_SNOOP_ENABLE);
+ iowrite32(temp, hcr_base + HCONTROL);
+
+ temp = ata_wait_register(hcr_base + HSTATUS, ONLINE, 0, 1, 500);
+
+ if (!(temp & ONLINE)) {
+ ata_port_printk(ap, KERN_ERR,
+ "Softreset failed, not on-lined\n");
+ goto err;
+ }
+
+ DPRINTK("softreset, controller off-lined & on-lined\n");
+ VPRINTK("HStatus = 0x%x\n", ioread32(hcr_base + HSTATUS));
+ VPRINTK("HControl = 0x%x\n", ioread32(hcr_base + HCONTROL));
+
+ /*
+ * First, wait for the PHYRDY change to occur before waiting for
+ * the signature, and also verify if SStatus indicates device
+ * presence
+ */
+
+ temp = ata_wait_register(hcr_base + HSTATUS, 0xFF, 0, 1, 500);
+ if ((!(temp & 0x10)) || ata_link_offline(link)) {
+ ata_port_printk(ap, KERN_WARNING,
+ "No Device OR PHYRDY change,Hstatus = 0x%x\n",
+ ioread32(hcr_base + HSTATUS));
+ goto err;
+ }
+
+ /*
+ * Wait for the first D2H from device,i.e,signature update notification
+ */
+ start_jiffies = jiffies;
+ temp = ata_wait_register(hcr_base + HSTATUS, 0xFF, 0x10,
+ 500, jiffies_to_msecs(deadline - start_jiffies));
+
+ if ((temp & 0xFF) != 0x18) {
+ ata_port_printk(ap, KERN_WARNING, "No Signature Update\n");
+ goto err;
+ } else {
+ ata_port_printk(ap, KERN_INFO,
+ "Signature Update detected @ %d msecs\n",
+ jiffies_to_msecs(jiffies - start_jiffies));
+ }
+
+ /*
+ * Send a device reset (SRST) explicitly on command slot #0
+ * Check : will the command queue (reg) be cleared during offlining ??
+ * Also we will be online only if Phy commn. has been established
+ * and device presence has been detected, therefore if we have
+ * reached here, we can send a command to the target device
+ */
+
+ DPRINTK("Sending SRST/device reset\n");
+
+ ata_tf_init(link->device, &tf);
+ cfis = (u8 *) &pp->cmdentry->cfis;
+
+ /* device reset/SRST is a control register update FIS, uses tag0 */
+ sata_fsl_setup_cmd_hdr_entry(pp, 0,
+ SRST_CMD | CMD_DESC_SNOOP_ENABLE, 0, 0, 5);
+
+ tf.ctl |= ATA_SRST; /* setup SRST bit in taskfile control reg */
+ ata_tf_to_fis(&tf, 0, 0, cfis);
+
+ DPRINTK("Dumping cfis : 0x%x, 0x%x, 0x%x, 0x%x\n",
+ cfis[0], cfis[1], cfis[2], cfis[3]);
+
+ /*
+ * Queue SRST command to the controller/device, ensure that no
+ * other commands are active on the controller/device
+ */
+
+ DPRINTK("@Softreset, CQ = 0x%x, CA = 0x%x, CC = 0x%x\n",
+ ioread32(CQ + hcr_base),
+ ioread32(CA + hcr_base), ioread32(CC + hcr_base));
+
+ iowrite32(0xFFFF, CC + hcr_base);
+ iowrite32(1, CQ + hcr_base);
+
+ temp = ata_wait_register(CQ + hcr_base, 0x1, 0x1, 1, 5000);
+ if (temp & 0x1) {
+ ata_port_printk(ap, KERN_WARNING, "ATA_SRST issue failed\n");
+
+ DPRINTK("Softreset@5000,CQ=0x%x,CA=0x%x,CC=0x%x\n",
+ ioread32(CQ + hcr_base),
+ ioread32(CA + hcr_base), ioread32(CC + hcr_base));
+
+ sata_fsl_scr_read(ap, SCR_ERROR, &Serror);
+
+ DPRINTK("HStatus = 0x%x\n", ioread32(hcr_base + HSTATUS));
+ DPRINTK("HControl = 0x%x\n", ioread32(hcr_base + HCONTROL));
+ DPRINTK("Serror = 0x%x\n", Serror);
+ goto err;
+ }
+
+ msleep(1);
+
+ /*
+ * SATA device enters reset state after receving a Control register
+ * FIS with SRST bit asserted and it awaits another H2D Control reg.
+ * FIS with SRST bit cleared, then the device does internal diags &
+ * initialization, followed by indicating it's initialization status
+ * using ATA signature D2H register FIS to the host controller.
+ */
+
+ sata_fsl_setup_cmd_hdr_entry(pp, 0, CMD_DESC_SNOOP_ENABLE, 0, 0, 5);
+
+ tf.ctl &= ~ATA_SRST; /* 2nd H2D Ctl. register FIS */
+ ata_tf_to_fis(&tf, 0, 0, cfis);
+
+ iowrite32(1, CQ + hcr_base);
+ msleep(150); /* ?? */
+
+ /*
+ * The above command would have signalled an interrupt on command
+ * complete, which needs special handling, by clearing the Nth
+ * command bit of the CCreg
+ */
+ iowrite32(0x01, CC + hcr_base); /* We know it will be cmd#0 always */
+
+ DPRINTK("SATA FSL : Now checking device signature\n");
+
+ *class = ATA_DEV_NONE;
+
+ /* Verify if SStatus indicates device presence */
+ if (ata_link_online(link)) {
+ /*
+ * if we are here, device presence has been detected,
+ * 1st D2H FIS would have been received, but sfis in
+ * command desc. is not updated, but signature register
+ * would have been updated
+ */
+
+ *class = sata_fsl_dev_classify(ap);
+
+ DPRINTK("class = %d\n", *class);
+ VPRINTK("ccreg = 0x%x\n", ioread32(hcr_base + CC));
+ VPRINTK("cereg = 0x%x\n", ioread32(hcr_base + CE));
+ }
+
+ return 0;
+
+err:
+ return -EIO;
+}
+
+static void sata_fsl_error_handler(struct ata_port *ap)
+{
+
+ DPRINTK("in xx_error_handler\n");
+
+ /* perform recovery */
+ ata_do_eh(ap, ata_std_prereset, sata_fsl_softreset, sata_std_hardreset,
+ ata_std_postreset);
+}
+
+static void sata_fsl_post_internal_cmd(struct ata_queued_cmd *qc)
+{
+ if (qc->flags & ATA_QCFLAG_FAILED)
+ qc->err_mask |= AC_ERR_OTHER;
+
+ if (qc->err_mask) {
+ /* make DMA engine forget about the failed command */
+
+ }
+}
+
+static void sata_fsl_irq_clear(struct ata_port *ap)
+{
+ /* unused */
+}
+
+static void sata_fsl_error_intr(struct ata_port *ap)
+{
+ struct ata_link *link = &ap->link;
+ struct ata_eh_info *ehi = &link->eh_info;
+ struct sata_fsl_host_priv *host_priv = ap->host->private_data;
+ void __iomem *hcr_base = host_priv->hcr_base;
+ u32 hstatus, dereg, cereg = 0, SError = 0;
+ unsigned int err_mask = 0, action = 0;
+ struct ata_queued_cmd *qc;
+ int freeze = 0;
+
+ hstatus = ioread32(hcr_base + HSTATUS);
+ cereg = ioread32(hcr_base + CE);
+
+ ata_ehi_clear_desc(ehi);
+
+ /*
+ * Handle & Clear SError
+ */
+
+ sata_fsl_scr_read(ap, SCR_ERROR, &SError);
+ if (unlikely(SError & 0xFFFF0000)) {
+ sata_fsl_scr_write(ap, SCR_ERROR, SError);
+ err_mask |= AC_ERR_ATA_BUS;
+ }
+
+ DPRINTK("error_intr,hStat=0x%x,CE=0x%x,DE =0x%x,SErr=0x%x\n",
+ hstatus, cereg, ioread32(hcr_base + DE), SError);
+
+ /* handle single device errors */
+ if (cereg) {
+ /*
+ * clear the command error, also clears queue to the device
+ * in error, and we can (re)issue commands to this device.
+ * When a device is in error all commands queued into the
+ * host controller and at the device are considered aborted
+ * and the queue for that device is stopped. Now, after
+ * clearing the device error, we can issue commands to the
+ * device to interrogate it to find the source of the error.
+ */
+ dereg = ioread32(hcr_base + DE);
+ iowrite32(dereg, hcr_base + DE);
+ iowrite32(cereg, hcr_base + CE);
+
+ DPRINTK("single device error, CE=0x%x, DE=0x%x\n",
+ ioread32(hcr_base + CE), ioread32(hcr_base + DE));
+ /*
+ * We should consider this as non fatal error, and TF must
+ * be updated as done below.
+ */
+
+ err_mask |= AC_ERR_DEV;
+ }
+
+ /* handle fatal errors */
+ if (hstatus & FATAL_ERROR_DECODE) {
+ err_mask |= AC_ERR_ATA_BUS;
+ action |= ATA_EH_SOFTRESET;
+ /* how will fatal error interrupts be completed ?? */
+ freeze = 1;
+ }
+
+ /* Handle PHYRDY change notification */
+ if (hstatus & INT_ON_PHYRDY_CHG) {
+ DPRINTK("SATA FSL: PHYRDY change indication\n");
+
+ /* Setup a soft-reset EH action */
+ ata_ehi_hotplugged(ehi);
+ freeze = 1;
+ }
+
+ /* record error info */
+ qc = ata_qc_from_tag(ap, link->active_tag);
+
+ if (qc) {
+ sata_fsl_cache_taskfile_from_d2h_fis(qc, qc->ap);
+ qc->err_mask |= err_mask;
+ } else
+ ehi->err_mask |= err_mask;
+
+ ehi->action |= action;
+ ehi->serror |= SError;
+
+ /* freeze or abort */
+ if (freeze)
+ ata_port_freeze(ap);
+ else
+ ata_port_abort(ap);
+}
+
+static void sata_fsl_qc_complete(struct ata_queued_cmd *qc)
+{
+ if (qc->flags & ATA_QCFLAG_RESULT_TF) {
+ DPRINTK("xx_qc_complete called\n");
+ sata_fsl_cache_taskfile_from_d2h_fis(qc, qc->ap);
+ }
+}
+
+static void sata_fsl_host_intr(struct ata_port *ap)
+{
+ struct ata_link *link = &ap->link;
+ struct sata_fsl_host_priv *host_priv = ap->host->private_data;
+ void __iomem *hcr_base = host_priv->hcr_base;
+ u32 hstatus, qc_active = 0;
+ struct ata_queued_cmd *qc;
+ u32 SError;
+
+ hstatus = ioread32(hcr_base + HSTATUS);
+
+ sata_fsl_scr_read(ap, SCR_ERROR, &SError);
+
+ if (unlikely(SError & 0xFFFF0000)) {
+ DPRINTK("serror @host_intr : 0x%x\n", SError);
+ sata_fsl_error_intr(ap);
+
+ }
+
+ if (unlikely(hstatus & INT_ON_ERROR)) {
+ DPRINTK("error interrupt!!\n");
+ sata_fsl_error_intr(ap);
+ return;
+ }
+
+ if (link->sactive) { /* only true for NCQ commands */
+ int i;
+ /* Read command completed register */
+ qc_active = ioread32(hcr_base + CC);
+ /* clear CC bit, this will also complete the interrupt */
+ iowrite32(qc_active, hcr_base + CC);
+
+ DPRINTK("Status of all queues :\n");
+ DPRINTK("qc_active/CC = 0x%x, CA = 0x%x, CE=0x%x\n",
+ qc_active, ioread32(hcr_base + CA),
+ ioread32(hcr_base + CE));
+
+ for (i = 0; i < SATA_FSL_QUEUE_DEPTH; i++) {
+ if (qc_active & (1 << i)) {
+ qc = ata_qc_from_tag(ap, i);
+ if (qc) {
+ sata_fsl_qc_complete(qc);
+ ata_qc_complete(qc);
+ }
+ DPRINTK
+ ("completing ncq cmd,tag=%d,CC=0x%x,CA=0x%x\n",
+ i, ioread32(hcr_base + CC),
+ ioread32(hcr_base + CA));
+ }
+ }
+ return;
+
+ } else if (ap->qc_active) {
+ iowrite32(1, hcr_base + CC);
+ qc = ata_qc_from_tag(ap, link->active_tag);
+
+ DPRINTK("completing non-ncq cmd, tag=%d,CC=0x%x\n",
+ link->active_tag, ioread32(hcr_base + CC));
+
+ if (qc) {
+ sata_fsl_qc_complete(qc);
+ ata_qc_complete(qc);
+ }
+ } else {
+ /* Spurious Interrupt!! */
+ DPRINTK("spurious interrupt!!, CC = 0x%x\n",
+ ioread32(hcr_base + CC));
+ return;
+ }
+}
+
+static irqreturn_t sata_fsl_interrupt(int irq, void *dev_instance)
+{
+ struct ata_host *host = dev_instance;
+ struct sata_fsl_host_priv *host_priv = host->private_data;
+ void __iomem *hcr_base = host_priv->hcr_base;
+ u32 interrupt_enables;
+ unsigned handled = 0;
+ struct ata_port *ap;
+
+ /* ack. any pending IRQs for this controller/port */
+ interrupt_enables = ioread32(hcr_base + HSTATUS);
+ interrupt_enables &= 0x3F;
+
+ DPRINTK("interrupt status 0x%x\n", interrupt_enables);
+
+ if (!interrupt_enables)
+ return IRQ_NONE;
+
+ spin_lock(&host->lock);
+
+ /* Assuming one port per host controller */
+
+ ap = host->ports[0];
+ if (ap) {
+ sata_fsl_host_intr(ap);
+ } else {
+ dev_printk(KERN_WARNING, host->dev,
+ "interrupt on disabled port 0\n");
+ }
+
+ iowrite32(interrupt_enables, hcr_base + HSTATUS);
+ handled = 1;
+
+ spin_unlock(&host->lock);
+
+ return IRQ_RETVAL(handled);
+}
+
+/*
+ * Multiple ports are represented by multiple SATA controllers with
+ * one port per controller
+ */
+static int sata_fsl_init_controller(struct ata_host *host)
+{
+ struct sata_fsl_host_priv *host_priv = host->private_data;
+ void __iomem *hcr_base = host_priv->hcr_base;
+ u32 temp;
+
+ /*
+ * NOTE : We cannot bring the controller online before setting
+ * the CHBA, hence main controller initialization is done as
+ * part of the port_start() callback
+ */
+
+ /* ack. any pending IRQs for this controller/port */
+ temp = ioread32(hcr_base + HSTATUS);
+ if (temp & 0x3F)
+ iowrite32((temp & 0x3F), hcr_base + HSTATUS);
+
+ /* Keep interrupts disabled on the controller */
+ temp = ioread32(hcr_base + HCONTROL);
+ iowrite32((temp & ~0x3F), hcr_base + HCONTROL);
+
+ /* Disable interrupt coalescing control(icc), for the moment */
+ DPRINTK("icc = 0x%x\n", ioread32(hcr_base + ICC));
+ iowrite32(0x01000000, hcr_base + ICC);
+
+ /* clear error registers, SError is cleared by libATA */
+ iowrite32(0x00000FFFF, hcr_base + CE);
+ iowrite32(0x00000FFFF, hcr_base + DE);
+
+ /* initially assuming no Port multiplier, set CQPMP to 0 */
+ iowrite32(0x0, hcr_base + CQPMP);
+
+ /*
+ * host controller will be brought on-line, during xx_port_start()
+ * callback, that should also initiate the OOB, COMINIT sequence
+ */
+
+ DPRINTK("HStatus = 0x%x\n", ioread32(hcr_base + HSTATUS));
+ DPRINTK("HControl = 0x%x\n", ioread32(hcr_base + HCONTROL));
+
+ return 0;
+}
+
+/*
+ * scsi mid-layer and libata interface structures
+ */
+static struct scsi_host_template sata_fsl_sht = {
+ .module = THIS_MODULE,
+ .name = "sata_fsl",
+ .ioctl = ata_scsi_ioctl,
+ .queuecommand = ata_scsi_queuecmd,
+ .change_queue_depth = ata_scsi_change_queue_depth,
+ .can_queue = SATA_FSL_QUEUE_DEPTH,
+ .this_id = ATA_SHT_THIS_ID,
+ .sg_tablesize = SATA_FSL_MAX_PRD_USABLE,
+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+ .emulated = ATA_SHT_EMULATED,
+ .use_clustering = ATA_SHT_USE_CLUSTERING,
+ .proc_name = "sata_fsl",
+ .dma_boundary = ATA_DMA_BOUNDARY,
+ .slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
+ .bios_param = ata_std_bios_param,
+};
+
+static const struct ata_port_operations sata_fsl_ops = {
+ .check_status = sata_fsl_check_status,
+ .check_altstatus = sata_fsl_check_status,
+ .dev_select = ata_noop_dev_select,
+
+ .tf_read = sata_fsl_tf_read,
+
+ .qc_prep = sata_fsl_qc_prep,
+ .qc_issue = sata_fsl_qc_issue,
+ .irq_clear = sata_fsl_irq_clear,
+
+ .scr_read = sata_fsl_scr_read,
+ .scr_write = sata_fsl_scr_write,
+
+ .freeze = sata_fsl_freeze,
+ .thaw = sata_fsl_thaw,
+ .error_handler = sata_fsl_error_handler,
+ .post_internal_cmd = sata_fsl_post_internal_cmd,
+
+ .port_start = sata_fsl_port_start,
+ .port_stop = sata_fsl_port_stop,
+};
+
+static const struct ata_port_info sata_fsl_port_info[] = {
+ {
+ .flags = SATA_FSL_HOST_FLAGS,
+ .link_flags = SATA_FSL_HOST_LFLAGS,
+ .pio_mask = 0x1f, /* pio 0-4 */
+ .udma_mask = 0x7f, /* udma 0-6 */
+ .port_ops = &sata_fsl_ops,
+ },
+};
+
+static int sata_fsl_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
+{
+ int retval = 0;
+ void __iomem *hcr_base = NULL;
+ void __iomem *ssr_base = NULL;
+ void __iomem *csr_base = NULL;
+ struct sata_fsl_host_priv *host_priv = NULL;
+ struct resource *r;
+ int irq;
+ struct ata_host *host;
+
+ struct ata_port_info pi = sata_fsl_port_info[0];
+ const struct ata_port_info *ppi[] = { &pi, NULL };
+
+ dev_printk(KERN_INFO, &ofdev->dev,
+ "Sata FSL Platform/CSB Driver init\n");
+
+ r = kmalloc(sizeof(struct resource), GFP_KERNEL);
+
+ hcr_base = of_iomap(ofdev->node, 0);
+ if (!hcr_base)
+ goto error_exit_with_cleanup;
+
+ ssr_base = hcr_base + 0x100;
+ csr_base = hcr_base + 0x140;
+
+ DPRINTK("@reset i/o = 0x%x\n", ioread32(csr_base + TRANSCFG));
+ DPRINTK("sizeof(cmd_desc) = %d\n", sizeof(struct command_desc));
+ DPRINTK("sizeof(#define cmd_desc) = %d\n", SATA_FSL_CMD_DESC_SIZE);
+
+ host_priv = kzalloc(sizeof(struct sata_fsl_host_priv), GFP_KERNEL);
+ if (!host_priv)
+ goto error_exit_with_cleanup;
+
+ host_priv->hcr_base = hcr_base;
+ host_priv->ssr_base = ssr_base;
+ host_priv->csr_base = csr_base;
+
+ irq = irq_of_parse_and_map(ofdev->node, 0);
+ if (irq < 0) {
+ dev_printk(KERN_ERR, &ofdev->dev, "invalid irq from platform\n");
+ goto error_exit_with_cleanup;
+ }
+ host_priv->irq = irq;
+
+ /* allocate host structure */
+ host = ata_host_alloc_pinfo(&ofdev->dev, ppi, SATA_FSL_MAX_PORTS);
+
+ /* host->iomap is not used currently */
+ host->private_data = host_priv;
+
+ /* setup port(s) */
+
+ host->ports[0]->ioaddr.cmd_addr = host_priv->hcr_base;
+ host->ports[0]->ioaddr.scr_addr = host_priv->ssr_base;
+
+ /* initialize host controller */
+ sata_fsl_init_controller(host);
+
+ /*
+ * Now, register with libATA core, this will also initiate the
+ * device discovery process, invoking our port_start() handler &
+ * error_handler() to execute a dummy Softreset EH session
+ */
+ ata_host_activate(host, irq, sata_fsl_interrupt, SATA_FSL_IRQ_FLAG,
+ &sata_fsl_sht);
+
+ dev_set_drvdata(&ofdev->dev, host);
+
+ return 0;
+
+error_exit_with_cleanup:
+
+ if (hcr_base)
+ iounmap(hcr_base);
+ if (host_priv)
+ kfree(host_priv);
+
+ return retval;
+}
+
+static int sata_fsl_remove(struct of_device *ofdev)
+{
+ struct ata_host *host = dev_get_drvdata(&ofdev->dev);
+ struct sata_fsl_host_priv *host_priv = host->private_data;
+
+ ata_host_detach(host);
+
+ dev_set_drvdata(&ofdev->dev, NULL);
+
+ irq_dispose_mapping(host_priv->irq);
+ iounmap(host_priv->hcr_base);
+ kfree(host_priv);
+
+ return 0;
+}
+
+static struct of_device_id fsl_sata_match[] = {
+ {
+ .compatible = "fsl,mpc8315-sata",
+ },
+ {
+ .compatible = "fsl,mpc8379-sata",
+ },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, fsl_sata_match);
+
+static struct of_platform_driver fsl_sata_driver = {
+ .name = "fsl-sata",
+ .match_table = fsl_sata_match,
+ .probe = sata_fsl_probe,
+ .remove = sata_fsl_remove,
+};
+
+static int __init sata_fsl_init(void)
+{
+ of_register_platform_driver(&fsl_sata_driver);
+ return 0;
+}
+
+static void __exit sata_fsl_exit(void)
+{
+ of_unregister_platform_driver(&fsl_sata_driver);
+}
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ashish Kalra, Freescale Semiconductor");
+MODULE_DESCRIPTION("Freescale 3.0Gbps SATA controller low level driver");
+MODULE_VERSION("1.10");
+
+module_init(sata_fsl_init);
+module_exit(sata_fsl_exit);
diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c
index 08595f34b3e8..323c087e8cc1 100644
--- a/drivers/ata/sata_inic162x.c
+++ b/drivers/ata/sata_inic162x.c
@@ -143,7 +143,7 @@ static const int scr_map[] = {
[SCR_CONTROL] = 2,
};
-static void __iomem * inic_port_base(struct ata_port *ap)
+static void __iomem *inic_port_base(struct ata_port *ap)
{
return ap->host->iomap[MMIO_BAR] + ap->port_no * PORT_SIZE;
}
@@ -448,7 +448,7 @@ static int inic_hardreset(struct ata_link *link, unsigned int *class,
struct ata_taskfile tf;
/* wait a while before checking status */
- msleep(150);
+ ata_wait_after_reset(ap, deadline);
rc = ata_wait_ready(ap, deadline);
/* link occupied, -ENODEV too is an error */
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 4df8311968e9..a43f64d2775b 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -421,7 +421,6 @@ static void mv_error_handler(struct ata_port *ap);
static void mv_post_int_cmd(struct ata_queued_cmd *qc);
static void mv_eh_freeze(struct ata_port *ap);
static void mv_eh_thaw(struct ata_port *ap);
-static int mv_slave_config(struct scsi_device *sdev);
static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
static void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
@@ -459,7 +458,7 @@ static struct scsi_host_template mv5_sht = {
.use_clustering = 1,
.proc_name = DRV_NAME,
.dma_boundary = MV_DMA_BOUNDARY,
- .slave_configure = mv_slave_config,
+ .slave_configure = ata_scsi_slave_config,
.slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
@@ -477,7 +476,7 @@ static struct scsi_host_template mv6_sht = {
.use_clustering = 1,
.proc_name = DRV_NAME,
.dma_boundary = MV_DMA_BOUNDARY,
- .slave_configure = mv_slave_config,
+ .slave_configure = ata_scsi_slave_config,
.slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
@@ -756,17 +755,6 @@ static void mv_irq_clear(struct ata_port *ap)
{
}
-static int mv_slave_config(struct scsi_device *sdev)
-{
- int rc = ata_scsi_slave_config(sdev);
- if (rc)
- return rc;
-
- blk_queue_max_phys_segments(sdev->request_queue, MV_MAX_SG_CT / 2);
-
- return 0; /* scsi layer doesn't check return value, sigh */
-}
-
static void mv_set_edma_ptrs(void __iomem *port_mmio,
struct mv_host_priv *hpriv,
struct mv_port_priv *pp)
@@ -857,7 +845,7 @@ static int __mv_stop_dma(struct ata_port *ap)
pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
} else {
WARN_ON(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS));
- }
+ }
/* now properly wait for the eDMA to stop */
for (i = 1000; i > 0; i--) {
@@ -895,7 +883,7 @@ static void mv_dump_mem(void __iomem *start, unsigned bytes)
for (b = 0; b < bytes; ) {
DPRINTK("%p: ", start + b);
for (w = 0; b < bytes && w < 4; w++) {
- printk("%08x ",readl(start + b));
+ printk("%08x ", readl(start + b));
b += sizeof(u32);
}
printk("\n");
@@ -911,8 +899,8 @@ static void mv_dump_pci_cfg(struct pci_dev *pdev, unsigned bytes)
for (b = 0; b < bytes; ) {
DPRINTK("%02x: ", b);
for (w = 0; b < bytes && w < 4; w++) {
- (void) pci_read_config_dword(pdev,b,&dw);
- printk("%08x ",dw);
+ (void) pci_read_config_dword(pdev, b, &dw);
+ printk("%08x ", dw);
b += sizeof(u32);
}
printk("\n");
@@ -956,9 +944,9 @@ static void mv_dump_all_regs(void __iomem *mmio_base, int port,
}
for (p = start_port; p < start_port + num_ports; p++) {
port_base = mv_port_base(mmio_base, p);
- DPRINTK("EDMA regs (port %i):\n",p);
+ DPRINTK("EDMA regs (port %i):\n", p);
mv_dump_mem(port_base, 0x54);
- DPRINTK("SATA regs (port %i):\n",p);
+ DPRINTK("SATA regs (port %i):\n", p);
mv_dump_mem(port_base+0x300, 0x60);
}
#endif
@@ -1138,7 +1126,7 @@ static void mv_fill_sg(struct ata_queued_cmd *qc)
{
struct mv_port_priv *pp = qc->ap->private_data;
struct scatterlist *sg;
- struct mv_sg *mv_sg;
+ struct mv_sg *mv_sg, *last_sg = NULL;
mv_sg = pp->sg_tbl;
ata_for_each_sg(sg, qc) {
@@ -1159,16 +1147,16 @@ static void mv_fill_sg(struct ata_queued_cmd *qc)
sg_len -= len;
addr += len;
- if (!sg_len && ata_sg_is_last(sg, qc))
- mv_sg->flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL);
-
+ last_sg = mv_sg;
mv_sg++;
}
-
}
+
+ if (likely(last_sg))
+ last_sg->flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL);
}
-static inline void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last)
+static void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last)
{
u16 tmp = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS |
(last ? CRQB_CMD_LAST : 0);
@@ -1196,7 +1184,7 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
u16 flags = 0;
unsigned in_index;
- if (qc->tf.protocol != ATA_PROT_DMA)
+ if (qc->tf.protocol != ATA_PROT_DMA)
return;
/* Fill in command request block
@@ -1288,7 +1276,7 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc)
unsigned in_index;
u32 flags = 0;
- if (qc->tf.protocol != ATA_PROT_DMA)
+ if (qc->tf.protocol != ATA_PROT_DMA)
return;
/* Fill in Gen IIE command request block
@@ -1618,7 +1606,7 @@ static void mv_host_intr(struct ata_host *host, u32 relevant, unsigned int hc)
writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
VPRINTK("ENTER, hc%u relevant=0x%08x HC IRQ cause=0x%08x\n",
- hc,relevant,hc_irq_cause);
+ hc, relevant, hc_irq_cause);
for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) {
struct ata_port *ap = host->ports[port];
@@ -1995,9 +1983,8 @@ static int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
for (i = 0; i < 1000; i++) {
udelay(1);
t = readl(reg);
- if (PCI_MASTER_EMPTY & t) {
+ if (PCI_MASTER_EMPTY & t)
break;
- }
}
if (!(PCI_MASTER_EMPTY & t)) {
printk(KERN_ERR DRV_NAME ": PCI master won't flush\n");
@@ -2442,7 +2429,7 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
struct mv_host_priv *hpriv = host->private_data;
u32 hp_flags = hpriv->hp_flags;
- switch(board_idx) {
+ switch (board_idx) {
case chip_5080:
hpriv->ops = &mv5xxx_ops;
hp_flags |= MV_HP_GEN_I;
@@ -2523,7 +2510,8 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
break;
default:
- printk(KERN_ERR DRV_NAME ": BUG: invalid board index %u\n", board_idx);
+ dev_printk(KERN_ERR, &pdev->dev,
+ "BUG: invalid board index %u\n", board_idx);
return 1;
}
@@ -2680,7 +2668,7 @@ static void mv_print_info(struct ata_host *host)
*/
static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- static int printed_version = 0;
+ static int printed_version;
unsigned int board_idx = (unsigned int)ent->driver_data;
const struct ata_port_info *ppi[] = { &mv_port_info[board_idx], NULL };
struct ata_host *host;
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index 40557fe2ffdf..44f9e5d9e362 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -163,12 +163,41 @@ enum {
NV_ADMA_STAT_STOPPED = (1 << 10),
NV_ADMA_STAT_DONE = (1 << 12),
NV_ADMA_STAT_ERR = NV_ADMA_STAT_CPBERR |
- NV_ADMA_STAT_TIMEOUT,
+ NV_ADMA_STAT_TIMEOUT,
/* port flags */
NV_ADMA_PORT_REGISTER_MODE = (1 << 0),
NV_ADMA_ATAPI_SETUP_COMPLETE = (1 << 1),
+ /* MCP55 reg offset */
+ NV_CTL_MCP55 = 0x400,
+ NV_INT_STATUS_MCP55 = 0x440,
+ NV_INT_ENABLE_MCP55 = 0x444,
+ NV_NCQ_REG_MCP55 = 0x448,
+
+ /* MCP55 */
+ NV_INT_ALL_MCP55 = 0xffff,
+ NV_INT_PORT_SHIFT_MCP55 = 16, /* each port occupies 16 bits */
+ NV_INT_MASK_MCP55 = NV_INT_ALL_MCP55 & 0xfffd,
+
+ /* SWNCQ ENABLE BITS*/
+ NV_CTL_PRI_SWNCQ = 0x02,
+ NV_CTL_SEC_SWNCQ = 0x04,
+
+ /* SW NCQ status bits*/
+ NV_SWNCQ_IRQ_DEV = (1 << 0),
+ NV_SWNCQ_IRQ_PM = (1 << 1),
+ NV_SWNCQ_IRQ_ADDED = (1 << 2),
+ NV_SWNCQ_IRQ_REMOVED = (1 << 3),
+
+ NV_SWNCQ_IRQ_BACKOUT = (1 << 4),
+ NV_SWNCQ_IRQ_SDBFIS = (1 << 5),
+ NV_SWNCQ_IRQ_DHREGFIS = (1 << 6),
+ NV_SWNCQ_IRQ_DMASETUP = (1 << 7),
+
+ NV_SWNCQ_IRQ_HOTPLUG = NV_SWNCQ_IRQ_ADDED |
+ NV_SWNCQ_IRQ_REMOVED,
+
};
/* ADMA Physical Region Descriptor - one SG segment */
@@ -199,7 +228,7 @@ struct nv_adma_cpb {
u8 reserved1; /* 1 */
u8 ctl_flags; /* 2 */
/* len is length of taskfile in 64 bit words */
- u8 len; /* 3 */
+ u8 len; /* 3 */
u8 tag; /* 4 */
u8 next_cpb_idx; /* 5 */
__le16 reserved2; /* 6-7 */
@@ -215,9 +244,9 @@ struct nv_adma_port_priv {
dma_addr_t cpb_dma;
struct nv_adma_prd *aprd;
dma_addr_t aprd_dma;
- void __iomem * ctl_block;
- void __iomem * gen_block;
- void __iomem * notifier_clear_block;
+ void __iomem *ctl_block;
+ void __iomem *gen_block;
+ void __iomem *notifier_clear_block;
u8 flags;
int last_issue_ncq;
};
@@ -226,9 +255,45 @@ struct nv_host_priv {
unsigned long type;
};
-#define NV_ADMA_CHECK_INTR(GCTL, PORT) ((GCTL) & ( 1 << (19 + (12 * (PORT)))))
+struct defer_queue {
+ u32 defer_bits;
+ unsigned int head;
+ unsigned int tail;
+ unsigned int tag[ATA_MAX_QUEUE];
+};
+
+enum ncq_saw_flag_list {
+ ncq_saw_d2h = (1U << 0),
+ ncq_saw_dmas = (1U << 1),
+ ncq_saw_sdb = (1U << 2),
+ ncq_saw_backout = (1U << 3),
+};
+
+struct nv_swncq_port_priv {
+ struct ata_prd *prd; /* our SG list */
+ dma_addr_t prd_dma; /* and its DMA mapping */
+ void __iomem *sactive_block;
+ void __iomem *irq_block;
+ void __iomem *tag_block;
+ u32 qc_active;
+
+ unsigned int last_issue_tag;
+
+ /* fifo circular queue to store deferral command */
+ struct defer_queue defer_queue;
-static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
+ /* for NCQ interrupt analysis */
+ u32 dhfis_bits;
+ u32 dmafis_bits;
+ u32 sdbfis_bits;
+
+ unsigned int ncq_flags;
+};
+
+
+#define NV_ADMA_CHECK_INTR(GCTL, PORT) ((GCTL) & (1 << (19 + (12 * (PORT)))))
+
+static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
#ifdef CONFIG_PM
static int nv_pci_device_resume(struct pci_dev *pdev);
#endif
@@ -236,8 +301,8 @@ static void nv_ck804_host_stop(struct ata_host *host);
static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance);
static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance);
static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance);
-static int nv_scr_read (struct ata_port *ap, unsigned int sc_reg, u32 *val);
-static int nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
+static int nv_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val);
+static int nv_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val);
static void nv_nf2_freeze(struct ata_port *ap);
static void nv_nf2_thaw(struct ata_port *ap);
@@ -263,13 +328,29 @@ static void nv_adma_host_stop(struct ata_host *host);
static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc);
static void nv_adma_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
+static void nv_mcp55_thaw(struct ata_port *ap);
+static void nv_mcp55_freeze(struct ata_port *ap);
+static void nv_swncq_error_handler(struct ata_port *ap);
+static int nv_swncq_slave_config(struct scsi_device *sdev);
+static int nv_swncq_port_start(struct ata_port *ap);
+static void nv_swncq_qc_prep(struct ata_queued_cmd *qc);
+static void nv_swncq_fill_sg(struct ata_queued_cmd *qc);
+static unsigned int nv_swncq_qc_issue(struct ata_queued_cmd *qc);
+static void nv_swncq_irq_clear(struct ata_port *ap, u16 fis);
+static irqreturn_t nv_swncq_interrupt(int irq, void *dev_instance);
+#ifdef CONFIG_PM
+static int nv_swncq_port_suspend(struct ata_port *ap, pm_message_t mesg);
+static int nv_swncq_port_resume(struct ata_port *ap);
+#endif
+
enum nv_host_type
{
GENERIC,
NFORCE2,
NFORCE3 = NFORCE2, /* NF2 == NF3 as far as sata_nv is concerned */
CK804,
- ADMA
+ ADMA,
+ SWNCQ,
};
static const struct pci_device_id nv_pci_tbl[] = {
@@ -280,10 +361,10 @@ static const struct pci_device_id nv_pci_tbl[] = {
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2), CK804 },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA), CK804 },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2), CK804 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA), GENERIC },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2), GENERIC },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA), GENERIC },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2), GENERIC },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA), SWNCQ },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2), SWNCQ },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA), SWNCQ },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2), SWNCQ },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA), GENERIC },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2), GENERIC },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3), GENERIC },
@@ -339,6 +420,25 @@ static struct scsi_host_template nv_adma_sht = {
.bios_param = ata_std_bios_param,
};
+static struct scsi_host_template nv_swncq_sht = {
+ .module = THIS_MODULE,
+ .name = DRV_NAME,
+ .ioctl = ata_scsi_ioctl,
+ .queuecommand = ata_scsi_queuecmd,
+ .change_queue_depth = ata_scsi_change_queue_depth,
+ .can_queue = ATA_MAX_QUEUE,
+ .this_id = ATA_SHT_THIS_ID,
+ .sg_tablesize = LIBATA_MAX_PRD,
+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+ .emulated = ATA_SHT_EMULATED,
+ .use_clustering = ATA_SHT_USE_CLUSTERING,
+ .proc_name = DRV_NAME,
+ .dma_boundary = ATA_DMA_BOUNDARY,
+ .slave_configure = nv_swncq_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
+ .bios_param = ata_std_bios_param,
+};
+
static const struct ata_port_operations nv_generic_ops = {
.tf_load = ata_tf_load,
.tf_read = ata_tf_read,
@@ -444,6 +544,35 @@ static const struct ata_port_operations nv_adma_ops = {
.host_stop = nv_adma_host_stop,
};
+static const struct ata_port_operations nv_swncq_ops = {
+ .tf_load = ata_tf_load,
+ .tf_read = ata_tf_read,
+ .exec_command = ata_exec_command,
+ .check_status = ata_check_status,
+ .dev_select = ata_std_dev_select,
+ .bmdma_setup = ata_bmdma_setup,
+ .bmdma_start = ata_bmdma_start,
+ .bmdma_stop = ata_bmdma_stop,
+ .bmdma_status = ata_bmdma_status,
+ .qc_defer = ata_std_qc_defer,
+ .qc_prep = nv_swncq_qc_prep,
+ .qc_issue = nv_swncq_qc_issue,
+ .freeze = nv_mcp55_freeze,
+ .thaw = nv_mcp55_thaw,
+ .error_handler = nv_swncq_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+ .data_xfer = ata_data_xfer,
+ .irq_clear = ata_bmdma_irq_clear,
+ .irq_on = ata_irq_on,
+ .scr_read = nv_scr_read,
+ .scr_write = nv_scr_write,
+#ifdef CONFIG_PM
+ .port_suspend = nv_swncq_port_suspend,
+ .port_resume = nv_swncq_port_resume,
+#endif
+ .port_start = nv_swncq_port_start,
+};
+
static const struct ata_port_info nv_port_info[] = {
/* generic */
{
@@ -490,6 +619,18 @@ static const struct ata_port_info nv_port_info[] = {
.port_ops = &nv_adma_ops,
.irq_handler = nv_adma_interrupt,
},
+ /* SWNCQ */
+ {
+ .sht = &nv_swncq_sht,
+ .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_NCQ,
+ .link_flags = ATA_LFLAG_HRST_TO_RESUME,
+ .pio_mask = NV_PIO_MASK,
+ .mwdma_mask = NV_MWDMA_MASK,
+ .udma_mask = NV_UDMA_MASK,
+ .port_ops = &nv_swncq_ops,
+ .irq_handler = nv_swncq_interrupt,
+ },
};
MODULE_AUTHOR("NVIDIA");
@@ -499,6 +640,7 @@ MODULE_DEVICE_TABLE(pci, nv_pci_tbl);
MODULE_VERSION(DRV_VERSION);
static int adma_enabled = 1;
+static int swncq_enabled;
static void nv_adma_register_mode(struct ata_port *ap)
{
@@ -511,12 +653,12 @@ static void nv_adma_register_mode(struct ata_port *ap)
return;
status = readw(mmio + NV_ADMA_STAT);
- while(!(status & NV_ADMA_STAT_IDLE) && count < 20) {
+ while (!(status & NV_ADMA_STAT_IDLE) && count < 20) {
ndelay(50);
status = readw(mmio + NV_ADMA_STAT);
count++;
}
- if(count == 20)
+ if (count == 20)
ata_port_printk(ap, KERN_WARNING,
"timeout waiting for ADMA IDLE, stat=0x%hx\n",
status);
@@ -526,12 +668,12 @@ static void nv_adma_register_mode(struct ata_port *ap)
count = 0;
status = readw(mmio + NV_ADMA_STAT);
- while(!(status & NV_ADMA_STAT_LEGACY) && count < 20) {
+ while (!(status & NV_ADMA_STAT_LEGACY) && count < 20) {
ndelay(50);
status = readw(mmio + NV_ADMA_STAT);
count++;
}
- if(count == 20)
+ if (count == 20)
ata_port_printk(ap, KERN_WARNING,
"timeout waiting for ADMA LEGACY, stat=0x%hx\n",
status);
@@ -555,13 +697,13 @@ static void nv_adma_mode(struct ata_port *ap)
writew(tmp | NV_ADMA_CTL_GO, mmio + NV_ADMA_CTL);
status = readw(mmio + NV_ADMA_STAT);
- while(((status & NV_ADMA_STAT_LEGACY) ||
+ while (((status & NV_ADMA_STAT_LEGACY) ||
!(status & NV_ADMA_STAT_IDLE)) && count < 20) {
ndelay(50);
status = readw(mmio + NV_ADMA_STAT);
count++;
}
- if(count == 20)
+ if (count == 20)
ata_port_printk(ap, KERN_WARNING,
"timeout waiting for ADMA LEGACY clear and IDLE, stat=0x%hx\n",
status);
@@ -605,8 +747,7 @@ static int nv_adma_slave_config(struct scsi_device *sdev)
on the port. */
adma_enable = 0;
nv_adma_register_mode(ap);
- }
- else {
+ } else {
bounce_limit = *ap->dev->dma_mask;
segment_boundary = NV_ADMA_DMA_BOUNDARY;
sg_tablesize = NV_ADMA_SGTBL_TOTAL_LEN;
@@ -615,23 +756,22 @@ static int nv_adma_slave_config(struct scsi_device *sdev)
pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, &current_reg);
- if(ap->port_no == 1)
+ if (ap->port_no == 1)
config_mask = NV_MCP_SATA_CFG_20_PORT1_EN |
NV_MCP_SATA_CFG_20_PORT1_PWB_EN;
else
config_mask = NV_MCP_SATA_CFG_20_PORT0_EN |
NV_MCP_SATA_CFG_20_PORT0_PWB_EN;
- if(adma_enable) {
+ if (adma_enable) {
new_reg = current_reg | config_mask;
pp->flags &= ~NV_ADMA_ATAPI_SETUP_COMPLETE;
- }
- else {
+ } else {
new_reg = current_reg & ~config_mask;
pp->flags |= NV_ADMA_ATAPI_SETUP_COMPLETE;
}
- if(current_reg != new_reg)
+ if (current_reg != new_reg)
pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, new_reg);
blk_queue_bounce_limit(sdev->request_queue, bounce_limit);
@@ -665,7 +805,7 @@ static unsigned int nv_adma_tf_to_cpb(struct ata_taskfile *tf, __le16 *cpb)
{
unsigned int idx = 0;
- if(tf->flags & ATA_TFLAG_ISADDR) {
+ if (tf->flags & ATA_TFLAG_ISADDR) {
if (tf->flags & ATA_TFLAG_LBA48) {
cpb[idx++] = cpu_to_le16((ATA_REG_ERR << 8) | tf->hob_feature | WNB);
cpb[idx++] = cpu_to_le16((ATA_REG_NSECT << 8) | tf->hob_nsect);
@@ -682,12 +822,12 @@ static unsigned int nv_adma_tf_to_cpb(struct ata_taskfile *tf, __le16 *cpb)
cpb[idx++] = cpu_to_le16((ATA_REG_LBAH << 8) | tf->lbah);
}
- if(tf->flags & ATA_TFLAG_DEVICE)
+ if (tf->flags & ATA_TFLAG_DEVICE)
cpb[idx++] = cpu_to_le16((ATA_REG_DEVICE << 8) | tf->device);
cpb[idx++] = cpu_to_le16((ATA_REG_CMD << 8) | tf->command | CMDEND);
- while(idx < 12)
+ while (idx < 12)
cpb[idx++] = cpu_to_le16(IGN);
return idx;
@@ -708,7 +848,7 @@ static int nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err)
int freeze = 0;
ata_ehi_clear_desc(ehi);
- __ata_ehi_push_desc(ehi, "CPB resp_flags 0x%x: ", flags );
+ __ata_ehi_push_desc(ehi, "CPB resp_flags 0x%x: ", flags);
if (flags & NV_CPB_RESP_ATA_ERR) {
ata_ehi_push_desc(ehi, "ATA error");
ehi->err_mask |= AC_ERR_DEV;
@@ -737,15 +877,16 @@ static int nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err)
struct ata_queued_cmd *qc = ata_qc_from_tag(ap, cpb_num);
VPRINTK("CPB flags done, flags=0x%x\n", flags);
if (likely(qc)) {
- DPRINTK("Completing qc from tag %d\n",cpb_num);
+ DPRINTK("Completing qc from tag %d\n", cpb_num);
ata_qc_complete(qc);
} else {
struct ata_eh_info *ehi = &ap->link.eh_info;
/* Notifier bits set without a command may indicate the drive
is misbehaving. Raise host state machine violation on this
condition. */
- ata_port_printk(ap, KERN_ERR, "notifier for tag %d with no command?\n",
- cpb_num);
+ ata_port_printk(ap, KERN_ERR,
+ "notifier for tag %d with no cmd?\n",
+ cpb_num);
ehi->err_mask |= AC_ERR_HSM;
ehi->action |= ATA_EH_SOFTRESET;
ata_port_freeze(ap);
@@ -810,7 +951,7 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
if (pp->flags & NV_ADMA_PORT_REGISTER_MODE) {
u8 irq_stat = readb(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804)
>> (NV_INT_PORT_SHIFT * i);
- if(ata_tag_valid(ap->link.active_tag))
+ if (ata_tag_valid(ap->link.active_tag))
/** NV_INT_DEV indication seems unreliable at times
at least in ADMA mode. Force it on always when a
command is active, to prevent losing interrupts. */
@@ -824,7 +965,7 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
gen_ctl = readl(pp->gen_block + NV_ADMA_GEN_CTL);
- if( !NV_ADMA_CHECK_INTR(gen_ctl, ap->port_no) && !notifier &&
+ if (!NV_ADMA_CHECK_INTR(gen_ctl, ap->port_no) && !notifier &&
!notifier_error)
/* Nothing to do */
continue;
@@ -848,7 +989,7 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
struct ata_eh_info *ehi = &ap->link.eh_info;
ata_ehi_clear_desc(ehi);
- __ata_ehi_push_desc(ehi, "ADMA status 0x%08x: ", status );
+ __ata_ehi_push_desc(ehi, "ADMA status 0x%08x: ", status);
if (status & NV_ADMA_STAT_TIMEOUT) {
ehi->err_mask |= AC_ERR_SYSTEM;
ata_ehi_push_desc(ehi, "timeout");
@@ -872,7 +1013,7 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
u32 check_commands;
int pos, error = 0;
- if(ata_tag_valid(ap->link.active_tag))
+ if (ata_tag_valid(ap->link.active_tag))
check_commands = 1 << ap->link.active_tag;
else
check_commands = ap->link.sactive;
@@ -881,14 +1022,14 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
while ((pos = ffs(check_commands)) && !error) {
pos--;
error = nv_adma_check_cpb(ap, pos,
- notifier_error & (1 << pos) );
- check_commands &= ~(1 << pos );
+ notifier_error & (1 << pos));
+ check_commands &= ~(1 << pos);
}
}
}
}
- if(notifier_clears[0] || notifier_clears[1]) {
+ if (notifier_clears[0] || notifier_clears[1]) {
/* Note: Both notifier clear registers must be written
if either is set, even if one is zero, according to NVIDIA. */
struct nv_adma_port_priv *pp = host->ports[0]->private_data;
@@ -914,14 +1055,14 @@ static void nv_adma_freeze(struct ata_port *ap)
return;
/* clear any outstanding CK804 notifications */
- writeb( NV_INT_ALL << (ap->port_no * NV_INT_PORT_SHIFT),
+ writeb(NV_INT_ALL << (ap->port_no * NV_INT_PORT_SHIFT),
ap->host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804);
/* Disable interrupt */
tmp = readw(mmio + NV_ADMA_CTL);
- writew( tmp & ~(NV_ADMA_CTL_AIEN | NV_ADMA_CTL_HOTPLUG_IEN),
+ writew(tmp & ~(NV_ADMA_CTL_AIEN | NV_ADMA_CTL_HOTPLUG_IEN),
mmio + NV_ADMA_CTL);
- readw( mmio + NV_ADMA_CTL ); /* flush posted write */
+ readw(mmio + NV_ADMA_CTL); /* flush posted write */
}
static void nv_adma_thaw(struct ata_port *ap)
@@ -937,9 +1078,9 @@ static void nv_adma_thaw(struct ata_port *ap)
/* Enable interrupt */
tmp = readw(mmio + NV_ADMA_CTL);
- writew( tmp | (NV_ADMA_CTL_AIEN | NV_ADMA_CTL_HOTPLUG_IEN),
+ writew(tmp | (NV_ADMA_CTL_AIEN | NV_ADMA_CTL_HOTPLUG_IEN),
mmio + NV_ADMA_CTL);
- readw( mmio + NV_ADMA_CTL ); /* flush posted write */
+ readw(mmio + NV_ADMA_CTL); /* flush posted write */
}
static void nv_adma_irq_clear(struct ata_port *ap)
@@ -954,7 +1095,7 @@ static void nv_adma_irq_clear(struct ata_port *ap)
}
/* clear any outstanding CK804 notifications */
- writeb( NV_INT_ALL << (ap->port_no * NV_INT_PORT_SHIFT),
+ writeb(NV_INT_ALL << (ap->port_no * NV_INT_PORT_SHIFT),
ap->host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804);
/* clear ADMA status */
@@ -979,7 +1120,7 @@ static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc)
{
struct nv_adma_port_priv *pp = qc->ap->private_data;
- if(pp->flags & NV_ADMA_PORT_REGISTER_MODE)
+ if (pp->flags & NV_ADMA_PORT_REGISTER_MODE)
ata_bmdma_post_internal_cmd(qc);
}
@@ -1025,7 +1166,7 @@ static int nv_adma_port_start(struct ata_port *ap)
pp->cpb_dma = mem_dma;
writel(mem_dma & 0xFFFFFFFF, mmio + NV_ADMA_CPB_BASE_LOW);
- writel((mem_dma >> 16 ) >> 16, mmio + NV_ADMA_CPB_BASE_HIGH);
+ writel((mem_dma >> 16) >> 16, mmio + NV_ADMA_CPB_BASE_HIGH);
mem += NV_ADMA_MAX_CPBS * NV_ADMA_CPB_SZ;
mem_dma += NV_ADMA_MAX_CPBS * NV_ADMA_CPB_SZ;
@@ -1049,15 +1190,15 @@ static int nv_adma_port_start(struct ata_port *ap)
/* clear GO for register mode, enable interrupt */
tmp = readw(mmio + NV_ADMA_CTL);
- writew( (tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN |
- NV_ADMA_CTL_HOTPLUG_IEN, mmio + NV_ADMA_CTL);
+ writew((tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN |
+ NV_ADMA_CTL_HOTPLUG_IEN, mmio + NV_ADMA_CTL);
tmp = readw(mmio + NV_ADMA_CTL);
writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
- readw( mmio + NV_ADMA_CTL ); /* flush posted write */
+ readw(mmio + NV_ADMA_CTL); /* flush posted write */
udelay(1);
writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
- readw( mmio + NV_ADMA_CTL ); /* flush posted write */
+ readw(mmio + NV_ADMA_CTL); /* flush posted write */
return 0;
}
@@ -1097,7 +1238,7 @@ static int nv_adma_port_resume(struct ata_port *ap)
/* set CPB block location */
writel(pp->cpb_dma & 0xFFFFFFFF, mmio + NV_ADMA_CPB_BASE_LOW);
- writel((pp->cpb_dma >> 16 ) >> 16, mmio + NV_ADMA_CPB_BASE_HIGH);
+ writel((pp->cpb_dma >> 16) >> 16, mmio + NV_ADMA_CPB_BASE_HIGH);
/* clear any outstanding interrupt conditions */
writew(0xffff, mmio + NV_ADMA_STAT);
@@ -1110,15 +1251,15 @@ static int nv_adma_port_resume(struct ata_port *ap)
/* clear GO for register mode, enable interrupt */
tmp = readw(mmio + NV_ADMA_CTL);
- writew( (tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN |
- NV_ADMA_CTL_HOTPLUG_IEN, mmio + NV_ADMA_CTL);
+ writew((tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN |
+ NV_ADMA_CTL_HOTPLUG_IEN, mmio + NV_ADMA_CTL);
tmp = readw(mmio + NV_ADMA_CTL);
writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
- readw( mmio + NV_ADMA_CTL ); /* flush posted write */
+ readw(mmio + NV_ADMA_CTL); /* flush posted write */
udelay(1);
writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
- readw( mmio + NV_ADMA_CTL ); /* flush posted write */
+ readw(mmio + NV_ADMA_CTL); /* flush posted write */
return 0;
}
@@ -1202,7 +1343,8 @@ static void nv_adma_fill_sg(struct ata_queued_cmd *qc, struct nv_adma_cpb *cpb)
idx = 0;
ata_for_each_sg(sg, qc) {
- aprd = (idx < 5) ? &cpb->aprd[idx] : &pp->aprd[NV_ADMA_SGTBL_LEN * qc->tag + (idx-5)];
+ aprd = (idx < 5) ? &cpb->aprd[idx] :
+ &pp->aprd[NV_ADMA_SGTBL_LEN * qc->tag + (idx-5)];
nv_adma_fill_aprd(qc, sg, idx, aprd);
idx++;
}
@@ -1219,12 +1361,12 @@ static int nv_adma_use_reg_mode(struct ata_queued_cmd *qc)
/* ADMA engine can only be used for non-ATAPI DMA commands,
or interrupt-driven no-data commands, where a result taskfile
is not required. */
- if((pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) ||
+ if ((pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) ||
(qc->tf.flags & ATA_TFLAG_POLLING) ||
(qc->flags & ATA_QCFLAG_RESULT_TF))
return 1;
- if((qc->flags & ATA_QCFLAG_DMAMAP) ||
+ if ((qc->flags & ATA_QCFLAG_DMAMAP) ||
(qc->tf.protocol == ATA_PROT_NODATA))
return 0;
@@ -1261,14 +1403,14 @@ static void nv_adma_qc_prep(struct ata_queued_cmd *qc)
nv_adma_tf_to_cpb(&qc->tf, cpb->tf);
- if(qc->flags & ATA_QCFLAG_DMAMAP) {
+ if (qc->flags & ATA_QCFLAG_DMAMAP) {
nv_adma_fill_sg(qc, cpb);
ctl_flags |= NV_CPB_CTL_APRD_VALID;
} else
memset(&cpb->aprd[0], 0, sizeof(struct nv_adma_prd) * 5);
- /* Be paranoid and don't let the device see NV_CPB_CTL_CPB_VALID until we are
- finished filling in all of the contents */
+ /* Be paranoid and don't let the device see NV_CPB_CTL_CPB_VALID
+ until we are finished filling in all of the contents */
wmb();
cpb->ctl_flags = ctl_flags;
wmb();
@@ -1295,16 +1437,16 @@ static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc)
and (number of cpbs to append -1) in top 8 bits */
wmb();
- if(curr_ncq != pp->last_issue_ncq) {
- /* Seems to need some delay before switching between NCQ and non-NCQ
- commands, else we get command timeouts and such. */
+ if (curr_ncq != pp->last_issue_ncq) {
+ /* Seems to need some delay before switching between NCQ and
+ non-NCQ commands, else we get command timeouts and such. */
udelay(20);
pp->last_issue_ncq = curr_ncq;
}
writew(qc->tag, mmio + NV_ADMA_APPEND);
- DPRINTK("Issued tag %u\n",qc->tag);
+ DPRINTK("Issued tag %u\n", qc->tag);
return 0;
}
@@ -1452,6 +1594,34 @@ static void nv_ck804_thaw(struct ata_port *ap)
writeb(mask, mmio_base + NV_INT_ENABLE_CK804);
}
+static void nv_mcp55_freeze(struct ata_port *ap)
+{
+ void __iomem *mmio_base = ap->host->iomap[NV_MMIO_BAR];
+ int shift = ap->port_no * NV_INT_PORT_SHIFT_MCP55;
+ u32 mask;
+
+ writel(NV_INT_ALL_MCP55 << shift, mmio_base + NV_INT_STATUS_MCP55);
+
+ mask = readl(mmio_base + NV_INT_ENABLE_MCP55);
+ mask &= ~(NV_INT_ALL_MCP55 << shift);
+ writel(mask, mmio_base + NV_INT_ENABLE_MCP55);
+ ata_bmdma_freeze(ap);
+}
+
+static void nv_mcp55_thaw(struct ata_port *ap)
+{
+ void __iomem *mmio_base = ap->host->iomap[NV_MMIO_BAR];
+ int shift = ap->port_no * NV_INT_PORT_SHIFT_MCP55;
+ u32 mask;
+
+ writel(NV_INT_ALL_MCP55 << shift, mmio_base + NV_INT_STATUS_MCP55);
+
+ mask = readl(mmio_base + NV_INT_ENABLE_MCP55);
+ mask |= (NV_INT_MASK_MCP55 << shift);
+ writel(mask, mmio_base + NV_INT_ENABLE_MCP55);
+ ata_bmdma_thaw(ap);
+}
+
static int nv_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline)
{
@@ -1459,7 +1629,7 @@ static int nv_hardreset(struct ata_link *link, unsigned int *class,
/* SATA hardreset fails to retrieve proper device signature on
* some controllers. Don't classify on hardreset. For more
- * info, see http://bugme.osdl.org/show_bug.cgi?id=3352
+ * info, see http://bugzilla.kernel.org/show_bug.cgi?id=3352
*/
return sata_std_hardreset(link, &dummy, deadline);
}
@@ -1473,12 +1643,12 @@ static void nv_error_handler(struct ata_port *ap)
static void nv_adma_error_handler(struct ata_port *ap)
{
struct nv_adma_port_priv *pp = ap->private_data;
- if(!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) {
+ if (!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) {
void __iomem *mmio = pp->ctl_block;
int i;
u16 tmp;
- if(ata_tag_valid(ap->link.active_tag) || ap->link.sactive) {
+ if (ata_tag_valid(ap->link.active_tag) || ap->link.sactive) {
u32 notifier = readl(mmio + NV_ADMA_NOTIFIER);
u32 notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR);
u32 gen_ctl = readl(pp->gen_block + NV_ADMA_GEN_CTL);
@@ -1486,16 +1656,17 @@ static void nv_adma_error_handler(struct ata_port *ap)
u8 cpb_count = readb(mmio + NV_ADMA_CPB_COUNT);
u8 next_cpb_idx = readb(mmio + NV_ADMA_NEXT_CPB_IDX);
- ata_port_printk(ap, KERN_ERR, "EH in ADMA mode, notifier 0x%X "
+ ata_port_printk(ap, KERN_ERR,
+ "EH in ADMA mode, notifier 0x%X "
"notifier_error 0x%X gen_ctl 0x%X status 0x%X "
"next cpb count 0x%X next cpb idx 0x%x\n",
notifier, notifier_error, gen_ctl, status,
cpb_count, next_cpb_idx);
- for( i=0;i<NV_ADMA_MAX_CPBS;i++) {
+ for (i = 0; i < NV_ADMA_MAX_CPBS; i++) {
struct nv_adma_cpb *cpb = &pp->cpb[i];
- if( (ata_tag_valid(ap->link.active_tag) && i == ap->link.active_tag) ||
- ap->link.sactive & (1 << i) )
+ if ((ata_tag_valid(ap->link.active_tag) && i == ap->link.active_tag) ||
+ ap->link.sactive & (1 << i))
ata_port_printk(ap, KERN_ERR,
"CPB %d: ctl_flags 0x%x, resp_flags 0x%x\n",
i, cpb->ctl_flags, cpb->resp_flags);
@@ -1505,8 +1676,9 @@ static void nv_adma_error_handler(struct ata_port *ap)
/* Push us back into port register mode for error handling. */
nv_adma_register_mode(ap);
- /* Mark all of the CPBs as invalid to prevent them from being executed */
- for( i=0;i<NV_ADMA_MAX_CPBS;i++)
+ /* Mark all of the CPBs as invalid to prevent them from
+ being executed */
+ for (i = 0; i < NV_ADMA_MAX_CPBS; i++)
pp->cpb[i].ctl_flags &= ~NV_CPB_CTL_CPB_VALID;
/* clear CPB fetch count */
@@ -1515,19 +1687,676 @@ static void nv_adma_error_handler(struct ata_port *ap)
/* Reset channel */
tmp = readw(mmio + NV_ADMA_CTL);
writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
- readw( mmio + NV_ADMA_CTL ); /* flush posted write */
+ readw(mmio + NV_ADMA_CTL); /* flush posted write */
udelay(1);
writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
- readw( mmio + NV_ADMA_CTL ); /* flush posted write */
+ readw(mmio + NV_ADMA_CTL); /* flush posted write */
+ }
+
+ ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,
+ nv_hardreset, ata_std_postreset);
+}
+
+static void nv_swncq_qc_to_dq(struct ata_port *ap, struct ata_queued_cmd *qc)
+{
+ struct nv_swncq_port_priv *pp = ap->private_data;
+ struct defer_queue *dq = &pp->defer_queue;
+
+ /* queue is full */
+ WARN_ON(dq->tail - dq->head == ATA_MAX_QUEUE);
+ dq->defer_bits |= (1 << qc->tag);
+ dq->tag[dq->tail++ & (ATA_MAX_QUEUE - 1)] = qc->tag;
+}
+
+static struct ata_queued_cmd *nv_swncq_qc_from_dq(struct ata_port *ap)
+{
+ struct nv_swncq_port_priv *pp = ap->private_data;
+ struct defer_queue *dq = &pp->defer_queue;
+ unsigned int tag;
+
+ if (dq->head == dq->tail) /* null queue */
+ return NULL;
+
+ tag = dq->tag[dq->head & (ATA_MAX_QUEUE - 1)];
+ dq->tag[dq->head++ & (ATA_MAX_QUEUE - 1)] = ATA_TAG_POISON;
+ WARN_ON(!(dq->defer_bits & (1 << tag)));
+ dq->defer_bits &= ~(1 << tag);
+
+ return ata_qc_from_tag(ap, tag);
+}
+
+static void nv_swncq_fis_reinit(struct ata_port *ap)
+{
+ struct nv_swncq_port_priv *pp = ap->private_data;
+
+ pp->dhfis_bits = 0;
+ pp->dmafis_bits = 0;
+ pp->sdbfis_bits = 0;
+ pp->ncq_flags = 0;
+}
+
+static void nv_swncq_pp_reinit(struct ata_port *ap)
+{
+ struct nv_swncq_port_priv *pp = ap->private_data;
+ struct defer_queue *dq = &pp->defer_queue;
+
+ dq->head = 0;
+ dq->tail = 0;
+ dq->defer_bits = 0;
+ pp->qc_active = 0;
+ pp->last_issue_tag = ATA_TAG_POISON;
+ nv_swncq_fis_reinit(ap);
+}
+
+static void nv_swncq_irq_clear(struct ata_port *ap, u16 fis)
+{
+ struct nv_swncq_port_priv *pp = ap->private_data;
+
+ writew(fis, pp->irq_block);
+}
+
+static void __ata_bmdma_stop(struct ata_port *ap)
+{
+ struct ata_queued_cmd qc;
+
+ qc.ap = ap;
+ ata_bmdma_stop(&qc);
+}
+
+static void nv_swncq_ncq_stop(struct ata_port *ap)
+{
+ struct nv_swncq_port_priv *pp = ap->private_data;
+ unsigned int i;
+ u32 sactive;
+ u32 done_mask;
+
+ ata_port_printk(ap, KERN_ERR,
+ "EH in SWNCQ mode,QC:qc_active 0x%X sactive 0x%X\n",
+ ap->qc_active, ap->link.sactive);
+ ata_port_printk(ap, KERN_ERR,
+ "SWNCQ:qc_active 0x%X defer_bits 0x%X last_issue_tag 0x%x\n "
+ "dhfis 0x%X dmafis 0x%X sdbfis 0x%X\n",
+ pp->qc_active, pp->defer_queue.defer_bits, pp->last_issue_tag,
+ pp->dhfis_bits, pp->dmafis_bits, pp->sdbfis_bits);
+
+ ata_port_printk(ap, KERN_ERR, "ATA_REG 0x%X ERR_REG 0x%X\n",
+ ap->ops->check_status(ap),
+ ioread8(ap->ioaddr.error_addr));
+
+ sactive = readl(pp->sactive_block);
+ done_mask = pp->qc_active ^ sactive;
+
+ ata_port_printk(ap, KERN_ERR, "tag : dhfis dmafis sdbfis sacitve\n");
+ for (i = 0; i < ATA_MAX_QUEUE; i++) {
+ u8 err = 0;
+ if (pp->qc_active & (1 << i))
+ err = 0;
+ else if (done_mask & (1 << i))
+ err = 1;
+ else
+ continue;
+
+ ata_port_printk(ap, KERN_ERR,
+ "tag 0x%x: %01x %01x %01x %01x %s\n", i,
+ (pp->dhfis_bits >> i) & 0x1,
+ (pp->dmafis_bits >> i) & 0x1,
+ (pp->sdbfis_bits >> i) & 0x1,
+ (sactive >> i) & 0x1,
+ (err ? "error! tag doesn't exit" : " "));
+ }
+
+ nv_swncq_pp_reinit(ap);
+ ap->ops->irq_clear(ap);
+ __ata_bmdma_stop(ap);
+ nv_swncq_irq_clear(ap, 0xffff);
+}
+
+static void nv_swncq_error_handler(struct ata_port *ap)
+{
+ struct ata_eh_context *ehc = &ap->link.eh_context;
+
+ if (ap->link.sactive) {
+ nv_swncq_ncq_stop(ap);
+ ehc->i.action |= ATA_EH_HARDRESET;
}
ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,
nv_hardreset, ata_std_postreset);
}
-static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+#ifdef CONFIG_PM
+static int nv_swncq_port_suspend(struct ata_port *ap, pm_message_t mesg)
+{
+ void __iomem *mmio = ap->host->iomap[NV_MMIO_BAR];
+ u32 tmp;
+
+ /* clear irq */
+ writel(~0, mmio + NV_INT_STATUS_MCP55);
+
+ /* disable irq */
+ writel(0, mmio + NV_INT_ENABLE_MCP55);
+
+ /* disable swncq */
+ tmp = readl(mmio + NV_CTL_MCP55);
+ tmp &= ~(NV_CTL_PRI_SWNCQ | NV_CTL_SEC_SWNCQ);
+ writel(tmp, mmio + NV_CTL_MCP55);
+
+ return 0;
+}
+
+static int nv_swncq_port_resume(struct ata_port *ap)
{
- static int printed_version = 0;
+ void __iomem *mmio = ap->host->iomap[NV_MMIO_BAR];
+ u32 tmp;
+
+ /* clear irq */
+ writel(~0, mmio + NV_INT_STATUS_MCP55);
+
+ /* enable irq */
+ writel(0x00fd00fd, mmio + NV_INT_ENABLE_MCP55);
+
+ /* enable swncq */
+ tmp = readl(mmio + NV_CTL_MCP55);
+ writel(tmp | NV_CTL_PRI_SWNCQ | NV_CTL_SEC_SWNCQ, mmio + NV_CTL_MCP55);
+
+ return 0;
+}
+#endif
+
+static void nv_swncq_host_init(struct ata_host *host)
+{
+ u32 tmp;
+ void __iomem *mmio = host->iomap[NV_MMIO_BAR];
+ struct pci_dev *pdev = to_pci_dev(host->dev);
+ u8 regval;
+
+ /* disable ECO 398 */
+ pci_read_config_byte(pdev, 0x7f, &regval);
+ regval &= ~(1 << 7);
+ pci_write_config_byte(pdev, 0x7f, regval);
+
+ /* enable swncq */
+ tmp = readl(mmio + NV_CTL_MCP55);
+ VPRINTK("HOST_CTL:0x%X\n", tmp);
+ writel(tmp | NV_CTL_PRI_SWNCQ | NV_CTL_SEC_SWNCQ, mmio + NV_CTL_MCP55);
+
+ /* enable irq intr */
+ tmp = readl(mmio + NV_INT_ENABLE_MCP55);
+ VPRINTK("HOST_ENABLE:0x%X\n", tmp);
+ writel(tmp | 0x00fd00fd, mmio + NV_INT_ENABLE_MCP55);
+
+ /* clear port irq */
+ writel(~0x0, mmio + NV_INT_STATUS_MCP55);
+}
+
+static int nv_swncq_slave_config(struct scsi_device *sdev)
+{
+ struct ata_port *ap = ata_shost_to_port(sdev->host);
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ struct ata_device *dev;
+ int rc;
+ u8 rev;
+ u8 check_maxtor = 0;
+ unsigned char model_num[ATA_ID_PROD_LEN + 1];
+
+ rc = ata_scsi_slave_config(sdev);
+ if (sdev->id >= ATA_MAX_DEVICES || sdev->channel || sdev->lun)
+ /* Not a proper libata device, ignore */
+ return rc;
+
+ dev = &ap->link.device[sdev->id];
+ if (!(ap->flags & ATA_FLAG_NCQ) || dev->class == ATA_DEV_ATAPI)
+ return rc;
+
+ /* if MCP51 and Maxtor, then disable ncq */
+ if (pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA ||
+ pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2)
+ check_maxtor = 1;
+
+ /* if MCP55 and rev <= a2 and Maxtor, then disable ncq */
+ if (pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA ||
+ pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2) {
+ pci_read_config_byte(pdev, 0x8, &rev);
+ if (rev <= 0xa2)
+ check_maxtor = 1;
+ }
+
+ if (!check_maxtor)
+ return rc;
+
+ ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num));
+
+ if (strncmp(model_num, "Maxtor", 6) == 0) {
+ ata_scsi_change_queue_depth(sdev, 1);
+ ata_dev_printk(dev, KERN_NOTICE,
+ "Disabling SWNCQ mode (depth %x)\n", sdev->queue_depth);
+ }
+
+ return rc;
+}
+
+static int nv_swncq_port_start(struct ata_port *ap)
+{
+ struct device *dev = ap->host->dev;
+ void __iomem *mmio = ap->host->iomap[NV_MMIO_BAR];
+ struct nv_swncq_port_priv *pp;
+ int rc;
+
+ rc = ata_port_start(ap);
+ if (rc)
+ return rc;
+
+ pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
+ if (!pp)
+ return -ENOMEM;
+
+ pp->prd = dmam_alloc_coherent(dev, ATA_PRD_TBL_SZ * ATA_MAX_QUEUE,
+ &pp->prd_dma, GFP_KERNEL);
+ if (!pp->prd)
+ return -ENOMEM;
+ memset(pp->prd, 0, ATA_PRD_TBL_SZ * ATA_MAX_QUEUE);
+
+ ap->private_data = pp;
+ pp->sactive_block = ap->ioaddr.scr_addr + 4 * SCR_ACTIVE;
+ pp->irq_block = mmio + NV_INT_STATUS_MCP55 + ap->port_no * 2;
+ pp->tag_block = mmio + NV_NCQ_REG_MCP55 + ap->port_no * 2;
+
+ return 0;
+}
+
+static void nv_swncq_qc_prep(struct ata_queued_cmd *qc)
+{
+ if (qc->tf.protocol != ATA_PROT_NCQ) {
+ ata_qc_prep(qc);
+ return;
+ }
+
+ if (!(qc->flags & ATA_QCFLAG_DMAMAP))
+ return;
+
+ nv_swncq_fill_sg(qc);
+}
+
+static void nv_swncq_fill_sg(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct scatterlist *sg;
+ unsigned int idx;
+ struct nv_swncq_port_priv *pp = ap->private_data;
+ struct ata_prd *prd;
+
+ WARN_ON(qc->__sg == NULL);
+ WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
+
+ prd = pp->prd + ATA_MAX_PRD * qc->tag;
+
+ idx = 0;
+ ata_for_each_sg(sg, qc) {
+ u32 addr, offset;
+ u32 sg_len, len;
+
+ addr = (u32)sg_dma_address(sg);
+ sg_len = sg_dma_len(sg);
+
+ while (sg_len) {
+ offset = addr & 0xffff;
+ len = sg_len;
+ if ((offset + sg_len) > 0x10000)
+ len = 0x10000 - offset;
+
+ prd[idx].addr = cpu_to_le32(addr);
+ prd[idx].flags_len = cpu_to_le32(len & 0xffff);
+
+ idx++;
+ sg_len -= len;
+ addr += len;
+ }
+ }
+
+ if (idx)
+ prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
+}
+
+static unsigned int nv_swncq_issue_atacmd(struct ata_port *ap,
+ struct ata_queued_cmd *qc)
+{
+ struct nv_swncq_port_priv *pp = ap->private_data;
+
+ if (qc == NULL)
+ return 0;
+
+ DPRINTK("Enter\n");
+
+ writel((1 << qc->tag), pp->sactive_block);
+ pp->last_issue_tag = qc->tag;
+ pp->dhfis_bits &= ~(1 << qc->tag);
+ pp->dmafis_bits &= ~(1 << qc->tag);
+ pp->qc_active |= (0x1 << qc->tag);
+
+ ap->ops->tf_load(ap, &qc->tf); /* load tf registers */
+ ap->ops->exec_command(ap, &qc->tf);
+
+ DPRINTK("Issued tag %u\n", qc->tag);
+
+ return 0;
+}
+
+static unsigned int nv_swncq_qc_issue(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct nv_swncq_port_priv *pp = ap->private_data;
+
+ if (qc->tf.protocol != ATA_PROT_NCQ)
+ return ata_qc_issue_prot(qc);
+
+ DPRINTK("Enter\n");
+
+ if (!pp->qc_active)
+ nv_swncq_issue_atacmd(ap, qc);
+ else
+ nv_swncq_qc_to_dq(ap, qc); /* add qc to defer queue */
+
+ return 0;
+}
+
+static void nv_swncq_hotplug(struct ata_port *ap, u32 fis)
+{
+ u32 serror;
+ struct ata_eh_info *ehi = &ap->link.eh_info;
+
+ ata_ehi_clear_desc(ehi);
+
+ /* AHCI needs SError cleared; otherwise, it might lock up */
+ sata_scr_read(&ap->link, SCR_ERROR, &serror);
+ sata_scr_write(&ap->link, SCR_ERROR, serror);
+
+ /* analyze @irq_stat */
+ if (fis & NV_SWNCQ_IRQ_ADDED)
+ ata_ehi_push_desc(ehi, "hot plug");
+ else if (fis & NV_SWNCQ_IRQ_REMOVED)
+ ata_ehi_push_desc(ehi, "hot unplug");
+
+ ata_ehi_hotplugged(ehi);
+
+ /* okay, let's hand over to EH */
+ ehi->serror |= serror;
+
+ ata_port_freeze(ap);
+}
+
+static int nv_swncq_sdbfis(struct ata_port *ap)
+{
+ struct ata_queued_cmd *qc;
+ struct nv_swncq_port_priv *pp = ap->private_data;
+ struct ata_eh_info *ehi = &ap->link.eh_info;
+ u32 sactive;
+ int nr_done = 0;
+ u32 done_mask;
+ int i;
+ u8 host_stat;
+ u8 lack_dhfis = 0;
+
+ host_stat = ap->ops->bmdma_status(ap);
+ if (unlikely(host_stat & ATA_DMA_ERR)) {
+ /* error when transfering data to/from memory */
+ ata_ehi_clear_desc(ehi);
+ ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat);
+ ehi->err_mask |= AC_ERR_HOST_BUS;
+ ehi->action |= ATA_EH_SOFTRESET;
+ return -EINVAL;
+ }
+
+ ap->ops->irq_clear(ap);
+ __ata_bmdma_stop(ap);
+
+ sactive = readl(pp->sactive_block);
+ done_mask = pp->qc_active ^ sactive;
+
+ if (unlikely(done_mask & sactive)) {
+ ata_ehi_clear_desc(ehi);
+ ata_ehi_push_desc(ehi, "illegal SWNCQ:qc_active transition"
+ "(%08x->%08x)", pp->qc_active, sactive);
+ ehi->err_mask |= AC_ERR_HSM;
+ ehi->action |= ATA_EH_HARDRESET;
+ return -EINVAL;
+ }
+ for (i = 0; i < ATA_MAX_QUEUE; i++) {
+ if (!(done_mask & (1 << i)))
+ continue;
+
+ qc = ata_qc_from_tag(ap, i);
+ if (qc) {
+ ata_qc_complete(qc);
+ pp->qc_active &= ~(1 << i);
+ pp->dhfis_bits &= ~(1 << i);
+ pp->dmafis_bits &= ~(1 << i);
+ pp->sdbfis_bits |= (1 << i);
+ nr_done++;
+ }
+ }
+
+ if (!ap->qc_active) {
+ DPRINTK("over\n");
+ nv_swncq_pp_reinit(ap);
+ return nr_done;
+ }
+
+ if (pp->qc_active & pp->dhfis_bits)
+ return nr_done;
+
+ if ((pp->ncq_flags & ncq_saw_backout) ||
+ (pp->qc_active ^ pp->dhfis_bits))
+ /* if the controller cann't get a device to host register FIS,
+ * The driver needs to reissue the new command.
+ */
+ lack_dhfis = 1;
+
+ DPRINTK("id 0x%x QC: qc_active 0x%x,"
+ "SWNCQ:qc_active 0x%X defer_bits %X "
+ "dhfis 0x%X dmafis 0x%X last_issue_tag %x\n",
+ ap->print_id, ap->qc_active, pp->qc_active,
+ pp->defer_queue.defer_bits, pp->dhfis_bits,
+ pp->dmafis_bits, pp->last_issue_tag);
+
+ nv_swncq_fis_reinit(ap);
+
+ if (lack_dhfis) {
+ qc = ata_qc_from_tag(ap, pp->last_issue_tag);
+ nv_swncq_issue_atacmd(ap, qc);
+ return nr_done;
+ }
+
+ if (pp->defer_queue.defer_bits) {
+ /* send deferral queue command */
+ qc = nv_swncq_qc_from_dq(ap);
+ WARN_ON(qc == NULL);
+ nv_swncq_issue_atacmd(ap, qc);
+ }
+
+ return nr_done;
+}
+
+static inline u32 nv_swncq_tag(struct ata_port *ap)
+{
+ struct nv_swncq_port_priv *pp = ap->private_data;
+ u32 tag;
+
+ tag = readb(pp->tag_block) >> 2;
+ return (tag & 0x1f);
+}
+
+static int nv_swncq_dmafis(struct ata_port *ap)
+{
+ struct ata_queued_cmd *qc;
+ unsigned int rw;
+ u8 dmactl;
+ u32 tag;
+ struct nv_swncq_port_priv *pp = ap->private_data;
+
+ __ata_bmdma_stop(ap);
+ tag = nv_swncq_tag(ap);
+
+ DPRINTK("dma setup tag 0x%x\n", tag);
+ qc = ata_qc_from_tag(ap, tag);
+
+ if (unlikely(!qc))
+ return 0;
+
+ rw = qc->tf.flags & ATA_TFLAG_WRITE;
+
+ /* load PRD table addr. */
+ iowrite32(pp->prd_dma + ATA_PRD_TBL_SZ * qc->tag,
+ ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS);
+
+ /* specify data direction, triple-check start bit is clear */
+ dmactl = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+ dmactl &= ~ATA_DMA_WR;
+ if (!rw)
+ dmactl |= ATA_DMA_WR;
+
+ iowrite8(dmactl | ATA_DMA_START, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+
+ return 1;
+}
+
+static void nv_swncq_host_interrupt(struct ata_port *ap, u16 fis)
+{
+ struct nv_swncq_port_priv *pp = ap->private_data;
+ struct ata_queued_cmd *qc;
+ struct ata_eh_info *ehi = &ap->link.eh_info;
+ u32 serror;
+ u8 ata_stat;
+ int rc = 0;
+
+ ata_stat = ap->ops->check_status(ap);
+ nv_swncq_irq_clear(ap, fis);
+ if (!fis)
+ return;
+
+ if (ap->pflags & ATA_PFLAG_FROZEN)
+ return;
+
+ if (fis & NV_SWNCQ_IRQ_HOTPLUG) {
+ nv_swncq_hotplug(ap, fis);
+ return;
+ }
+
+ if (!pp->qc_active)
+ return;
+
+ if (ap->ops->scr_read(ap, SCR_ERROR, &serror))
+ return;
+ ap->ops->scr_write(ap, SCR_ERROR, serror);
+
+ if (ata_stat & ATA_ERR) {
+ ata_ehi_clear_desc(ehi);
+ ata_ehi_push_desc(ehi, "Ata error. fis:0x%X", fis);
+ ehi->err_mask |= AC_ERR_DEV;
+ ehi->serror |= serror;
+ ehi->action |= ATA_EH_SOFTRESET;
+ ata_port_freeze(ap);
+ return;
+ }
+
+ if (fis & NV_SWNCQ_IRQ_BACKOUT) {
+ /* If the IRQ is backout, driver must issue
+ * the new command again some time later.
+ */
+ pp->ncq_flags |= ncq_saw_backout;
+ }
+
+ if (fis & NV_SWNCQ_IRQ_SDBFIS) {
+ pp->ncq_flags |= ncq_saw_sdb;
+ DPRINTK("id 0x%x SWNCQ: qc_active 0x%X "
+ "dhfis 0x%X dmafis 0x%X sactive 0x%X\n",
+ ap->print_id, pp->qc_active, pp->dhfis_bits,
+ pp->dmafis_bits, readl(pp->sactive_block));
+ rc = nv_swncq_sdbfis(ap);
+ if (rc < 0)
+ goto irq_error;
+ }
+
+ if (fis & NV_SWNCQ_IRQ_DHREGFIS) {
+ /* The interrupt indicates the new command
+ * was transmitted correctly to the drive.
+ */
+ pp->dhfis_bits |= (0x1 << pp->last_issue_tag);
+ pp->ncq_flags |= ncq_saw_d2h;
+ if (pp->ncq_flags & (ncq_saw_sdb | ncq_saw_backout)) {
+ ata_ehi_push_desc(ehi, "illegal fis transaction");
+ ehi->err_mask |= AC_ERR_HSM;
+ ehi->action |= ATA_EH_HARDRESET;
+ goto irq_error;
+ }
+
+ if (!(fis & NV_SWNCQ_IRQ_DMASETUP) &&
+ !(pp->ncq_flags & ncq_saw_dmas)) {
+ ata_stat = ap->ops->check_status(ap);
+ if (ata_stat & ATA_BUSY)
+ goto irq_exit;
+
+ if (pp->defer_queue.defer_bits) {
+ DPRINTK("send next command\n");
+ qc = nv_swncq_qc_from_dq(ap);
+ nv_swncq_issue_atacmd(ap, qc);
+ }
+ }
+ }
+
+ if (fis & NV_SWNCQ_IRQ_DMASETUP) {
+ /* program the dma controller with appropriate PRD buffers
+ * and start the DMA transfer for requested command.
+ */
+ pp->dmafis_bits |= (0x1 << nv_swncq_tag(ap));
+ pp->ncq_flags |= ncq_saw_dmas;
+ rc = nv_swncq_dmafis(ap);
+ }
+
+irq_exit:
+ return;
+irq_error:
+ ata_ehi_push_desc(ehi, "fis:0x%x", fis);
+ ata_port_freeze(ap);
+ return;
+}
+
+static irqreturn_t nv_swncq_interrupt(int irq, void *dev_instance)
+{
+ struct ata_host *host = dev_instance;
+ unsigned int i;
+ unsigned int handled = 0;
+ unsigned long flags;
+ u32 irq_stat;
+
+ spin_lock_irqsave(&host->lock, flags);
+
+ irq_stat = readl(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_MCP55);
+
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
+
+ if (ap && !(ap->flags & ATA_FLAG_DISABLED)) {
+ if (ap->link.sactive) {
+ nv_swncq_host_interrupt(ap, (u16)irq_stat);
+ handled = 1;
+ } else {
+ if (irq_stat) /* reserve Hotplug */
+ nv_swncq_irq_clear(ap, 0xfff0);
+
+ handled += nv_host_intr(ap, (u8)irq_stat);
+ }
+ }
+ irq_stat >>= NV_INT_PORT_SHIFT_MCP55;
+ }
+
+ spin_unlock_irqrestore(&host->lock, flags);
+
+ return IRQ_RETVAL(handled);
+}
+
+static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ static int printed_version;
const struct ata_port_info *ppi[] = { NULL, NULL };
struct ata_host *host;
struct nv_host_priv *hpriv;
@@ -1539,7 +2368,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
// Make sure this is a SATA controller by counting the number of bars
// (NVIDIA SATA controllers will always have six bars). Otherwise,
// it's an IDE controller and we ignore it.
- for (bar=0; bar<6; bar++)
+ for (bar = 0; bar < 6; bar++)
if (pci_resource_start(pdev, bar) == 0)
return -ENODEV;
@@ -1551,11 +2380,19 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
return rc;
/* determine type and allocate host */
- if (type >= CK804 && adma_enabled) {
+ if (type == CK804 && adma_enabled) {
dev_printk(KERN_NOTICE, &pdev->dev, "Using ADMA mode\n");
type = ADMA;
}
+ if (type == SWNCQ) {
+ if (swncq_enabled)
+ dev_printk(KERN_NOTICE, &pdev->dev,
+ "Using SWNCQ mode\n");
+ else
+ type = GENERIC;
+ }
+
ppi[0] = &nv_port_info[type];
rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
if (rc)
@@ -1597,7 +2434,8 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
rc = nv_adma_host_init(host);
if (rc)
return rc;
- }
+ } else if (type == SWNCQ)
+ nv_swncq_host_init(host);
pci_set_master(pdev);
return ata_host_activate(host, pdev->irq, ppi[0]->irq_handler,
@@ -1612,37 +2450,37 @@ static int nv_pci_device_resume(struct pci_dev *pdev)
int rc;
rc = ata_pci_device_do_resume(pdev);
- if(rc)
+ if (rc)
return rc;
if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
- if(hpriv->type >= CK804) {
+ if (hpriv->type >= CK804) {
u8 regval;
pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, &regval);
regval |= NV_MCP_SATA_CFG_20_SATA_SPACE_EN;
pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval);
}
- if(hpriv->type == ADMA) {
+ if (hpriv->type == ADMA) {
u32 tmp32;
struct nv_adma_port_priv *pp;
/* enable/disable ADMA on the ports appropriately */
pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, &tmp32);
pp = host->ports[0]->private_data;
- if(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)
+ if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)
tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT0_EN |
- NV_MCP_SATA_CFG_20_PORT0_PWB_EN);
+ NV_MCP_SATA_CFG_20_PORT0_PWB_EN);
else
tmp32 |= (NV_MCP_SATA_CFG_20_PORT0_EN |
- NV_MCP_SATA_CFG_20_PORT0_PWB_EN);
+ NV_MCP_SATA_CFG_20_PORT0_PWB_EN);
pp = host->ports[1]->private_data;
- if(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)
+ if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)
tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT1_EN |
- NV_MCP_SATA_CFG_20_PORT1_PWB_EN);
+ NV_MCP_SATA_CFG_20_PORT1_PWB_EN);
else
tmp32 |= (NV_MCP_SATA_CFG_20_PORT1_EN |
- NV_MCP_SATA_CFG_20_PORT1_PWB_EN);
+ NV_MCP_SATA_CFG_20_PORT1_PWB_EN);
pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, tmp32);
}
@@ -1696,3 +2534,6 @@ module_init(nv_init);
module_exit(nv_exit);
module_param_named(adma, adma_enabled, bool, 0444);
MODULE_PARM_DESC(adma, "Enable use of ADMA (Default: true)");
+module_param_named(swncq, swncq_enabled, bool, 0444);
+MODULE_PARM_DESC(swncq, "Enable use of SWNCQ (Default: false)");
+
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c
index 903213153b5d..7914def54fa3 100644
--- a/drivers/ata/sata_promise.c
+++ b/drivers/ata/sata_promise.c
@@ -2,6 +2,7 @@
* sata_promise.c - Promise SATA
*
* Maintained by: Jeff Garzik <jgarzik@pobox.com>
+ * Mikael Pettersson <mikpe@it.uu.se>
* Please ALWAYS copy linux-ide@vger.kernel.org
* on emails.
*
@@ -45,11 +46,12 @@
#include "sata_promise.h"
#define DRV_NAME "sata_promise"
-#define DRV_VERSION "2.10"
+#define DRV_VERSION "2.11"
enum {
PDC_MAX_PORTS = 4,
PDC_MMIO_BAR = 3,
+ PDC_MAX_PRD = LIBATA_MAX_PRD - 1, /* -1 for ASIC PRD bug workaround */
/* register offsets */
PDC_FEATURE = 0x04, /* Feature/Error reg (per port) */
@@ -83,10 +85,12 @@ enum {
PDC_PCI_SYS_ERR = (1 << 22), /* PCI system error */
PDC1_PCI_PARITY_ERR = (1 << 23), /* PCI parity error (from SATA150 driver) */
PDC1_ERR_MASK = PDC1_PCI_PARITY_ERR,
- PDC2_ERR_MASK = PDC2_HTO_ERR | PDC2_ATA_HBA_ERR | PDC2_ATA_DMA_CNT_ERR,
- PDC_ERR_MASK = (PDC_PH_ERR | PDC_SH_ERR | PDC_DH_ERR | PDC_OVERRUN_ERR
- | PDC_UNDERRUN_ERR | PDC_DRIVE_ERR | PDC_PCI_SYS_ERR
- | PDC1_ERR_MASK | PDC2_ERR_MASK),
+ PDC2_ERR_MASK = PDC2_HTO_ERR | PDC2_ATA_HBA_ERR |
+ PDC2_ATA_DMA_CNT_ERR,
+ PDC_ERR_MASK = PDC_PH_ERR | PDC_SH_ERR | PDC_DH_ERR |
+ PDC_OVERRUN_ERR | PDC_UNDERRUN_ERR |
+ PDC_DRIVE_ERR | PDC_PCI_SYS_ERR |
+ PDC1_ERR_MASK | PDC2_ERR_MASK,
board_2037x = 0, /* FastTrak S150 TX2plus */
board_2037x_pata = 1, /* FastTrak S150 TX2plus PATA port */
@@ -155,7 +159,7 @@ static struct scsi_host_template pdc_ata_sht = {
.queuecommand = ata_scsi_queuecmd,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
- .sg_tablesize = LIBATA_MAX_PRD,
+ .sg_tablesize = PDC_MAX_PRD,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
.emulated = ATA_SHT_EMULATED,
.use_clustering = ATA_SHT_USE_CLUSTERING,
@@ -238,7 +242,7 @@ static const struct ata_port_operations pdc_pata_ops = {
};
static const struct ata_port_info pdc_port_info[] = {
- /* board_2037x */
+ [board_2037x] =
{
.flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA |
PDC_FLAG_SATA_PATA,
@@ -248,7 +252,7 @@ static const struct ata_port_info pdc_port_info[] = {
.port_ops = &pdc_old_sata_ops,
},
- /* board_2037x_pata */
+ [board_2037x_pata] =
{
.flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, /* pio0-4 */
@@ -257,7 +261,7 @@ static const struct ata_port_info pdc_port_info[] = {
.port_ops = &pdc_pata_ops,
},
- /* board_20319 */
+ [board_20319] =
{
.flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA |
PDC_FLAG_4_PORTS,
@@ -267,7 +271,7 @@ static const struct ata_port_info pdc_port_info[] = {
.port_ops = &pdc_old_sata_ops,
},
- /* board_20619 */
+ [board_20619] =
{
.flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS |
PDC_FLAG_4_PORTS,
@@ -277,7 +281,7 @@ static const struct ata_port_info pdc_port_info[] = {
.port_ops = &pdc_pata_ops,
},
- /* board_2057x */
+ [board_2057x] =
{
.flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA |
PDC_FLAG_GEN_II | PDC_FLAG_SATA_PATA,
@@ -287,7 +291,7 @@ static const struct ata_port_info pdc_port_info[] = {
.port_ops = &pdc_sata_ops,
},
- /* board_2057x_pata */
+ [board_2057x_pata] =
{
.flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS |
PDC_FLAG_GEN_II,
@@ -297,7 +301,7 @@ static const struct ata_port_info pdc_port_info[] = {
.port_ops = &pdc_pata_ops,
},
- /* board_40518 */
+ [board_40518] =
{
.flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA |
PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS,
@@ -521,6 +525,84 @@ static void pdc_atapi_pkt(struct ata_queued_cmd *qc)
memcpy(buf+31, cdb, cdb_len);
}
+/**
+ * pdc_fill_sg - Fill PCI IDE PRD table
+ * @qc: Metadata associated with taskfile to be transferred
+ *
+ * Fill PCI IDE PRD (scatter-gather) table with segments
+ * associated with the current disk command.
+ * Make sure hardware does not choke on it.
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host lock)
+ *
+ */
+static void pdc_fill_sg(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct scatterlist *sg;
+ unsigned int idx;
+ const u32 SG_COUNT_ASIC_BUG = 41*4;
+
+ if (!(qc->flags & ATA_QCFLAG_DMAMAP))
+ return;
+
+ WARN_ON(qc->__sg == NULL);
+ WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
+
+ idx = 0;
+ ata_for_each_sg(sg, qc) {
+ u32 addr, offset;
+ u32 sg_len, len;
+
+ /* determine if physical DMA addr spans 64K boundary.
+ * Note h/w doesn't support 64-bit, so we unconditionally
+ * truncate dma_addr_t to u32.
+ */
+ addr = (u32) sg_dma_address(sg);
+ sg_len = sg_dma_len(sg);
+
+ while (sg_len) {
+ offset = addr & 0xffff;
+ len = sg_len;
+ if ((offset + sg_len) > 0x10000)
+ len = 0x10000 - offset;
+
+ ap->prd[idx].addr = cpu_to_le32(addr);
+ ap->prd[idx].flags_len = cpu_to_le32(len & 0xffff);
+ VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len);
+
+ idx++;
+ sg_len -= len;
+ addr += len;
+ }
+ }
+
+ if (idx) {
+ u32 len = le32_to_cpu(ap->prd[idx - 1].flags_len);
+
+ if (len > SG_COUNT_ASIC_BUG) {
+ u32 addr;
+
+ VPRINTK("Splitting last PRD.\n");
+
+ addr = le32_to_cpu(ap->prd[idx - 1].addr);
+ ap->prd[idx - 1].flags_len = cpu_to_le32(len - SG_COUNT_ASIC_BUG);
+ VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx - 1, addr, SG_COUNT_ASIC_BUG);
+
+ addr = addr + len - SG_COUNT_ASIC_BUG;
+ len = SG_COUNT_ASIC_BUG;
+ ap->prd[idx].addr = cpu_to_le32(addr);
+ ap->prd[idx].flags_len = cpu_to_le32(len);
+ VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len);
+
+ idx++;
+ }
+
+ ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
+ }
+}
+
static void pdc_qc_prep(struct ata_queued_cmd *qc)
{
struct pdc_port_priv *pp = qc->ap->private_data;
@@ -530,7 +612,7 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc)
switch (qc->tf.protocol) {
case ATA_PROT_DMA:
- ata_qc_prep(qc);
+ pdc_fill_sg(qc);
/* fall through */
case ATA_PROT_NODATA:
@@ -546,11 +628,11 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc)
break;
case ATA_PROT_ATAPI:
- ata_qc_prep(qc);
+ pdc_fill_sg(qc);
break;
case ATA_PROT_ATAPI_DMA:
- ata_qc_prep(qc);
+ pdc_fill_sg(qc);
/*FALLTHROUGH*/
case ATA_PROT_ATAPI_NODATA:
pdc_atapi_pkt(qc);
@@ -695,19 +777,20 @@ static void pdc_irq_clear(struct ata_port *ap)
readl(mmio + PDC_INT_SEQMASK);
}
-static inline int pdc_is_sataii_tx4(unsigned long flags)
+static int pdc_is_sataii_tx4(unsigned long flags)
{
const unsigned long mask = PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS;
return (flags & mask) == mask;
}
-static inline unsigned int pdc_port_no_to_ata_no(unsigned int port_no, int is_sataii_tx4)
+static unsigned int pdc_port_no_to_ata_no(unsigned int port_no,
+ int is_sataii_tx4)
{
static const unsigned char sataii_tx4_port_remap[4] = { 3, 1, 0, 2};
return is_sataii_tx4 ? sataii_tx4_port_remap[port_no] : port_no;
}
-static irqreturn_t pdc_interrupt (int irq, void *dev_instance)
+static irqreturn_t pdc_interrupt(int irq, void *dev_instance)
{
struct ata_host *host = dev_instance;
struct ata_port *ap;
@@ -839,15 +922,16 @@ static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
{
- WARN_ON (tf->protocol == ATA_PROT_DMA ||
- tf->protocol == ATA_PROT_ATAPI_DMA);
+ WARN_ON(tf->protocol == ATA_PROT_DMA ||
+ tf->protocol == ATA_PROT_ATAPI_DMA);
ata_tf_load(ap, tf);
}
-static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
+static void pdc_exec_command_mmio(struct ata_port *ap,
+ const struct ata_taskfile *tf)
{
- WARN_ON (tf->protocol == ATA_PROT_DMA ||
- tf->protocol == ATA_PROT_ATAPI_DMA);
+ WARN_ON(tf->protocol == ATA_PROT_DMA ||
+ tf->protocol == ATA_PROT_ATAPI_DMA);
ata_exec_command(ap, tf);
}
@@ -870,8 +954,11 @@ static int pdc_check_atapi_dma(struct ata_queued_cmd *qc)
}
/* -45150 (FFFF4FA2) to -1 (FFFFFFFF) shall use PIO mode */
if (scsicmd[0] == WRITE_10) {
- unsigned int lba;
- lba = (scsicmd[2] << 24) | (scsicmd[3] << 16) | (scsicmd[4] << 8) | scsicmd[5];
+ unsigned int lba =
+ (scsicmd[2] << 24) |
+ (scsicmd[3] << 16) |
+ (scsicmd[4] << 8) |
+ scsicmd[5];
if (lba >= 0xFFFF4FA2)
pio = 1;
}
@@ -956,7 +1043,8 @@ static void pdc_host_init(struct ata_host *host)
writel(tmp, mmio + PDC_SLEW_CTL);
}
-static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+static int pdc_ata_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
static int printed_version;
const struct ata_port_info *pi = &pdc_port_info[ent->driver_data];
diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c
index c4c4cd29eebb..2f1de6ec044c 100644
--- a/drivers/ata/sata_qstor.c
+++ b/drivers/ata/sata_qstor.c
@@ -103,7 +103,7 @@ enum {
QS_DMA_BOUNDARY = ~0UL
};
-typedef enum { qs_state_idle, qs_state_pkt, qs_state_mmio } qs_state_t;
+typedef enum { qs_state_mmio, qs_state_pkt } qs_state_t;
struct qs_port_priv {
u8 *pkt;
@@ -113,17 +113,18 @@ struct qs_port_priv {
static int qs_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val);
static int qs_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val);
-static int qs_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
+static int qs_ata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
static int qs_port_start(struct ata_port *ap);
static void qs_host_stop(struct ata_host *host);
-static void qs_phy_reset(struct ata_port *ap);
static void qs_qc_prep(struct ata_queued_cmd *qc);
static unsigned int qs_qc_issue(struct ata_queued_cmd *qc);
static int qs_check_atapi_dma(struct ata_queued_cmd *qc);
static void qs_bmdma_stop(struct ata_queued_cmd *qc);
static u8 qs_bmdma_status(struct ata_port *ap);
static void qs_irq_clear(struct ata_port *ap);
-static void qs_eng_timeout(struct ata_port *ap);
+static void qs_freeze(struct ata_port *ap);
+static void qs_thaw(struct ata_port *ap);
+static void qs_error_handler(struct ata_port *ap);
static struct scsi_host_template qs_ata_sht = {
.module = THIS_MODULE,
@@ -135,7 +136,6 @@ static struct scsi_host_template qs_ata_sht = {
.sg_tablesize = QS_MAX_PRD,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
.emulated = ATA_SHT_EMULATED,
- //FIXME .use_clustering = ATA_SHT_USE_CLUSTERING,
.use_clustering = ENABLE_CLUSTERING,
.proc_name = DRV_NAME,
.dma_boundary = QS_DMA_BOUNDARY,
@@ -151,11 +151,12 @@ static const struct ata_port_operations qs_ata_ops = {
.check_atapi_dma = qs_check_atapi_dma,
.exec_command = ata_exec_command,
.dev_select = ata_std_dev_select,
- .phy_reset = qs_phy_reset,
.qc_prep = qs_qc_prep,
.qc_issue = qs_qc_issue,
.data_xfer = ata_data_xfer,
- .eng_timeout = qs_eng_timeout,
+ .freeze = qs_freeze,
+ .thaw = qs_thaw,
+ .error_handler = qs_error_handler,
.irq_clear = qs_irq_clear,
.irq_on = ata_irq_on,
.scr_read = qs_scr_read,
@@ -170,8 +171,6 @@ static const struct ata_port_info qs_port_info[] = {
/* board_2068_idx */
{
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
- ATA_FLAG_SATA_RESET |
- //FIXME ATA_FLAG_SRST |
ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING,
.pio_mask = 0x10, /* pio4 */
.udma_mask = ATA_UDMA6,
@@ -220,7 +219,9 @@ static void qs_irq_clear(struct ata_port *ap)
static inline void qs_enter_reg_mode(struct ata_port *ap)
{
u8 __iomem *chan = qs_mmio_base(ap->host) + (ap->port_no * 0x4000);
+ struct qs_port_priv *pp = ap->private_data;
+ pp->state = qs_state_mmio;
writeb(QS_CTR0_REG, chan + QS_CCT_CTR0);
readb(chan + QS_CCT_CTR0); /* flush */
}
@@ -234,23 +235,28 @@ static inline void qs_reset_channel_logic(struct ata_port *ap)
qs_enter_reg_mode(ap);
}
-static void qs_phy_reset(struct ata_port *ap)
+static void qs_freeze(struct ata_port *ap)
{
- struct qs_port_priv *pp = ap->private_data;
+ u8 __iomem *mmio_base = qs_mmio_base(ap->host);
- pp->state = qs_state_idle;
- qs_reset_channel_logic(ap);
- sata_phy_reset(ap);
+ writeb(0, mmio_base + QS_HCT_CTRL); /* disable host interrupts */
+ qs_enter_reg_mode(ap);
}
-static void qs_eng_timeout(struct ata_port *ap)
+static void qs_thaw(struct ata_port *ap)
{
- struct qs_port_priv *pp = ap->private_data;
+ u8 __iomem *mmio_base = qs_mmio_base(ap->host);
+
+ qs_enter_reg_mode(ap);
+ writeb(1, mmio_base + QS_HCT_CTRL); /* enable host interrupts */
+}
+
+static int qs_prereset(struct ata_link *link, unsigned long deadline)
+{
+ struct ata_port *ap = link->ap;
- if (pp->state != qs_state_idle) /* healthy paranoia */
- pp->state = qs_state_mmio;
qs_reset_channel_logic(ap);
- ata_eng_timeout(ap);
+ return ata_std_prereset(link, deadline);
}
static int qs_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
@@ -261,6 +267,13 @@ static int qs_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
return 0;
}
+static void qs_error_handler(struct ata_port *ap)
+{
+ qs_enter_reg_mode(ap);
+ ata_do_eh(ap, qs_prereset, ata_std_softreset, NULL,
+ ata_std_postreset);
+}
+
static int qs_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
{
if (sc_reg > SCR_CONTROL)
@@ -359,7 +372,6 @@ static unsigned int qs_qc_issue(struct ata_queued_cmd *qc)
switch (qc->tf.protocol) {
case ATA_PROT_DMA:
-
pp->state = qs_state_pkt;
qs_packet_start(qc);
return 0;
@@ -376,6 +388,26 @@ static unsigned int qs_qc_issue(struct ata_queued_cmd *qc)
return ata_qc_issue_prot(qc);
}
+static void qs_do_or_die(struct ata_queued_cmd *qc, u8 status)
+{
+ qc->err_mask |= ac_err_mask(status);
+
+ if (!qc->err_mask) {
+ ata_qc_complete(qc);
+ } else {
+ struct ata_port *ap = qc->ap;
+ struct ata_eh_info *ehi = &ap->link.eh_info;
+
+ ata_ehi_clear_desc(ehi);
+ ata_ehi_push_desc(ehi, "status 0x%02X", status);
+
+ if (qc->err_mask == AC_ERR_DEV)
+ ata_port_abort(ap);
+ else
+ ata_port_freeze(ap);
+ }
+}
+
static inline unsigned int qs_intr_pkt(struct ata_host *host)
{
unsigned int handled = 0;
@@ -407,10 +439,8 @@ static inline unsigned int qs_intr_pkt(struct ata_host *host)
switch (sHST) {
case 0: /* successful CPB */
case 3: /* device error */
- pp->state = qs_state_idle;
qs_enter_reg_mode(qc->ap);
- qc->err_mask |= ac_err_mask(sDST);
- ata_qc_complete(qc);
+ qs_do_or_die(qc, sDST);
break;
default:
break;
@@ -432,25 +462,27 @@ static inline unsigned int qs_intr_mmio(struct ata_host *host)
if (ap &&
!(ap->flags & ATA_FLAG_DISABLED)) {
struct ata_queued_cmd *qc;
- struct qs_port_priv *pp = ap->private_data;
- if (!pp || pp->state != qs_state_mmio)
- continue;
+ struct qs_port_priv *pp;
qc = ata_qc_from_tag(ap, ap->link.active_tag);
- if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
-
- /* check main status, clearing INTRQ */
- u8 status = ata_check_status(ap);
- if ((status & ATA_BUSY))
- continue;
- DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n",
- ap->print_id, qc->tf.protocol, status);
-
- /* complete taskfile transaction */
- pp->state = qs_state_idle;
- qc->err_mask |= ac_err_mask(status);
- ata_qc_complete(qc);
+ if (!qc || !(qc->flags & ATA_QCFLAG_ACTIVE)) {
+ /*
+ * The qstor hardware generates spurious
+ * interrupts from time to time when switching
+ * in and out of packet mode.
+ * There's no obvious way to know if we're
+ * here now due to that, so just ack the irq
+ * and pretend we knew it was ours.. (ugh).
+ * This does not affect packet mode.
+ */
+ ata_check_status(ap);
handled = 1;
+ continue;
}
+ pp = ap->private_data;
+ if (!pp || pp->state != qs_state_mmio)
+ continue;
+ if (!(qc->tf.flags & ATA_TFLAG_POLLING))
+ handled |= ata_host_intr(ap, qc);
}
}
return handled;
@@ -460,12 +492,13 @@ static irqreturn_t qs_intr(int irq, void *dev_instance)
{
struct ata_host *host = dev_instance;
unsigned int handled = 0;
+ unsigned long flags;
VPRINTK("ENTER\n");
- spin_lock(&host->lock);
+ spin_lock_irqsave(&host->lock, flags);
handled = qs_intr_pkt(host) | qs_intr_mmio(host);
- spin_unlock(&host->lock);
+ spin_unlock_irqrestore(&host->lock, flags);
VPRINTK("EXIT\n");
@@ -502,7 +535,6 @@ static int qs_port_start(struct ata_port *ap)
rc = ata_port_start(ap);
if (rc)
return rc;
- qs_enter_reg_mode(ap);
pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
if (!pp)
return -ENOMEM;
@@ -513,6 +545,7 @@ static int qs_port_start(struct ata_port *ap)
memset(pp->pkt, 0, QS_PKT_BYTES);
ap->private_data = pp;
+ qs_enter_reg_mode(ap);
addr = (u64)pp->pkt_dma;
writel((u32) addr, chan + QS_CCF_CPBA);
writel((u32)(addr >> 32), chan + QS_CCF_CPBA + 4);
diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c
index ea3a0ab7e027..4e6e381279cc 100644
--- a/drivers/ata/sata_sil.c
+++ b/drivers/ata/sata_sil.c
@@ -111,7 +111,7 @@ enum {
SIL_QUIRK_UDMA5MAX = (1 << 1),
};
-static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
+static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
#ifdef CONFIG_PM
static int sil_pci_device_resume(struct pci_dev *pdev);
#endif
@@ -138,7 +138,7 @@ static const struct pci_device_id sil_pci_tbl[] = {
/* TODO firmware versions should be added - eric */
static const struct sil_drivelist {
- const char * product;
+ const char *product;
unsigned int quirk;
} sil_blacklist [] = {
{ "ST320012AS", SIL_QUIRK_MOD15WRITE },
@@ -279,7 +279,7 @@ MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, sil_pci_tbl);
MODULE_VERSION(DRV_VERSION);
-static int slow_down = 0;
+static int slow_down;
module_param(slow_down, int, 0444);
MODULE_PARM_DESC(slow_down, "Sledgehammer used to work around random problems, by limiting commands to 15 sectors (0=off, 1=on)");
@@ -332,7 +332,8 @@ static int sil_set_mode(struct ata_link *link, struct ata_device **r_failed)
return 0;
}
-static inline void __iomem *sil_scr_addr(struct ata_port *ap, unsigned int sc_reg)
+static inline void __iomem *sil_scr_addr(struct ata_port *ap,
+ unsigned int sc_reg)
{
void __iomem *offset = ap->ioaddr.scr_addr;
@@ -643,7 +644,7 @@ static void sil_init_controller(struct ata_host *host)
}
}
-static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version;
int board_id = ent->driver_data;
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index b0619278454a..187dcb02c681 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -265,11 +265,11 @@ static struct sil24_cerr_info {
unsigned int err_mask, action;
const char *desc;
} sil24_cerr_db[] = {
- [0] = { AC_ERR_DEV, ATA_EH_REVALIDATE,
+ [0] = { AC_ERR_DEV, 0,
"device error" },
- [PORT_CERR_DEV] = { AC_ERR_DEV, ATA_EH_REVALIDATE,
+ [PORT_CERR_DEV] = { AC_ERR_DEV, 0,
"device error via D2H FIS" },
- [PORT_CERR_SDB] = { AC_ERR_DEV, ATA_EH_REVALIDATE,
+ [PORT_CERR_SDB] = { AC_ERR_DEV, 0,
"device error via SDB FIS" },
[PORT_CERR_DATA] = { AC_ERR_ATA_BUS, ATA_EH_SOFTRESET,
"error in data FIS" },
@@ -674,7 +674,7 @@ static int sil24_do_softreset(struct ata_link *link, unsigned int *class,
/* put the port into known state */
if (sil24_init_port(ap)) {
- reason ="port not ready";
+ reason = "port not ready";
goto err;
}
@@ -756,7 +756,8 @@ static int sil24_hardreset(struct ata_link *link, unsigned int *class,
writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT);
tmp = ata_wait_register(port + PORT_CTRL_STAT,
- PORT_CS_DEV_RST, PORT_CS_DEV_RST, 10, tout_msec);
+ PORT_CS_DEV_RST, PORT_CS_DEV_RST, 10,
+ tout_msec);
/* SStatus oscillates between zero and valid status after
* DEV_RST, debounce it.
@@ -796,16 +797,19 @@ static inline void sil24_fill_sg(struct ata_queued_cmd *qc,
struct sil24_sge *sge)
{
struct scatterlist *sg;
+ struct sil24_sge *last_sge = NULL;
ata_for_each_sg(sg, qc) {
sge->addr = cpu_to_le64(sg_dma_address(sg));
sge->cnt = cpu_to_le32(sg_dma_len(sg));
- if (ata_sg_is_last(sg, qc))
- sge->flags = cpu_to_le32(SGE_TRM);
- else
- sge->flags = 0;
+ sge->flags = 0;
+
+ last_sge = sge;
sge++;
}
+
+ if (likely(last_sge))
+ last_sge->flags = cpu_to_le32(SGE_TRM);
}
static int sil24_qc_defer(struct ata_queued_cmd *qc)
@@ -1267,7 +1271,7 @@ static void sil24_init_controller(struct ata_host *host)
PORT_CS_PORT_RST, 10, 100);
if (tmp & PORT_CS_PORT_RST)
dev_printk(KERN_ERR, host->dev,
- "failed to clear port RST\n");
+ "failed to clear port RST\n");
}
/* configure port */
@@ -1280,7 +1284,7 @@ static void sil24_init_controller(struct ata_host *host)
static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- static int printed_version = 0;
+ static int printed_version;
struct ata_port_info pi = sil24_port_info[ent->driver_data];
const struct ata_port_info *ppi[] = { &pi, NULL };
void __iomem * const *iomap;
diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c
index 8d98a9fb0a42..a01260a56432 100644
--- a/drivers/ata/sata_sis.c
+++ b/drivers/ata/sata_sis.c
@@ -63,17 +63,17 @@ enum {
GENCTL_IOMAPPED_SCR = (1 << 26), /* if set, SCRs are in IO space */
};
-static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
-static int sis_scr_read (struct ata_port *ap, unsigned int sc_reg, u32 *val);
-static int sis_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
+static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
+static int sis_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val);
+static int sis_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val);
static const struct pci_device_id sis_pci_tbl[] = {
- { PCI_VDEVICE(SI, 0x0180), sis_180 }, /* SiS 964/180 */
- { PCI_VDEVICE(SI, 0x0181), sis_180 }, /* SiS 964/180 */
- { PCI_VDEVICE(SI, 0x0182), sis_180 }, /* SiS 965/965L */
- { PCI_VDEVICE(SI, 0x0183), sis_180 }, /* SiS 965/965L */
- { PCI_VDEVICE(SI, 0x1182), sis_180 }, /* SiS 966/680 */
- { PCI_VDEVICE(SI, 0x1183), sis_180 }, /* SiS 966/966L/968/680 */
+ { PCI_VDEVICE(SI, 0x0180), sis_180 }, /* SiS 964/180 */
+ { PCI_VDEVICE(SI, 0x0181), sis_180 }, /* SiS 964/180 */
+ { PCI_VDEVICE(SI, 0x0182), sis_180 }, /* SiS 965/965L */
+ { PCI_VDEVICE(SI, 0x0183), sis_180 }, /* SiS 965/965L */
+ { PCI_VDEVICE(SI, 0x1182), sis_180 }, /* SiS 966/680 */
+ { PCI_VDEVICE(SI, 0x1183), sis_180 }, /* SiS 966/966L/968/680 */
{ } /* terminate list */
};
@@ -92,7 +92,7 @@ static struct scsi_host_template sis_sht = {
.queuecommand = ata_scsi_queuecmd,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
- .sg_tablesize = ATA_MAX_PRD,
+ .sg_tablesize = LIBATA_MAX_PRD,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
.emulated = ATA_SHT_EMULATED,
.use_clustering = ATA_SHT_USE_CLUSTERING,
@@ -149,28 +149,28 @@ static unsigned int get_scr_cfg_addr(struct ata_port *ap, unsigned int sc_reg)
if (ap->port_no) {
switch (pdev->device) {
- case 0x0180:
- case 0x0181:
- pci_read_config_byte(pdev, SIS_PMR, &pmr);
- if ((pmr & SIS_PMR_COMBINED) == 0)
- addr += SIS180_SATA1_OFS;
- break;
-
- case 0x0182:
- case 0x0183:
- case 0x1182:
- addr += SIS182_SATA1_OFS;
- break;
+ case 0x0180:
+ case 0x0181:
+ pci_read_config_byte(pdev, SIS_PMR, &pmr);
+ if ((pmr & SIS_PMR_COMBINED) == 0)
+ addr += SIS180_SATA1_OFS;
+ break;
+
+ case 0x0182:
+ case 0x0183:
+ case 0x1182:
+ addr += SIS182_SATA1_OFS;
+ break;
}
}
return addr;
}
-static u32 sis_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg)
+static u32 sis_scr_cfg_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
unsigned int cfg_addr = get_scr_cfg_addr(ap, sc_reg);
- u32 val, val2 = 0;
+ u32 val2 = 0;
u8 pmr;
if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */
@@ -178,16 +178,19 @@ static u32 sis_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg)
pci_read_config_byte(pdev, SIS_PMR, &pmr);
- pci_read_config_dword(pdev, cfg_addr, &val);
+ pci_read_config_dword(pdev, cfg_addr, val);
if ((pdev->device == 0x0182) || (pdev->device == 0x0183) ||
(pdev->device == 0x1182) || (pmr & SIS_PMR_COMBINED))
pci_read_config_dword(pdev, cfg_addr+0x10, &val2);
- return (val|val2) & 0xfffffffb; /* avoid problems with powerdowned ports */
+ *val |= val2;
+ *val &= 0xfffffffb; /* avoid problems with powerdowned ports */
+
+ return 0;
}
-static void sis_scr_cfg_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
+static void sis_scr_cfg_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
unsigned int cfg_addr = get_scr_cfg_addr(ap, sc_reg);
@@ -214,7 +217,7 @@ static int sis_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
return -EINVAL;
if (ap->flags & SIS_FLAG_CFGSCR)
- return sis_scr_cfg_read(ap, sc_reg);
+ return sis_scr_cfg_read(ap, sc_reg, val);
pci_read_config_byte(pdev, SIS_PMR, &pmr);
@@ -250,7 +253,7 @@ static int sis_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
return 0;
}
-static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version;
struct ata_port_info pi = sis_port_info;
@@ -306,29 +309,33 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
} else {
dev_printk(KERN_INFO, &pdev->dev,
"Detected SiS 180/181 chipset in combined mode\n");
- port2_start=0;
+ port2_start = 0;
pi.flags |= ATA_FLAG_SLAVE_POSS;
}
break;
case 0x0182:
case 0x0183:
- pci_read_config_dword ( pdev, 0x6C, &val);
+ pci_read_config_dword(pdev, 0x6C, &val);
if (val & (1L << 31)) {
- dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 182/965 chipset\n");
+ dev_printk(KERN_INFO, &pdev->dev,
+ "Detected SiS 182/965 chipset\n");
pi.flags |= ATA_FLAG_SLAVE_POSS;
} else {
- dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 182/965L chipset\n");
+ dev_printk(KERN_INFO, &pdev->dev,
+ "Detected SiS 182/965L chipset\n");
}
break;
case 0x1182:
- dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 1182/966/680 SATA controller\n");
+ dev_printk(KERN_INFO, &pdev->dev,
+ "Detected SiS 1182/966/680 SATA controller\n");
pi.flags |= ATA_FLAG_SLAVE_POSS;
break;
case 0x1183:
- dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 1183/966/966L/968/680 controller in PATA mode\n");
+ dev_printk(KERN_INFO, &pdev->dev,
+ "Detected SiS 1183/966/966L/968/680 controller in PATA mode\n");
ppi[0] = &sis_info133_for_sata;
ppi[1] = &sis_info133_for_sata;
break;
diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c
index 12d613c48c19..69f651e0bc98 100644
--- a/drivers/ata/sata_svw.c
+++ b/drivers/ata/sata_svw.c
@@ -182,7 +182,7 @@ static void k2_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
tf->hob_lbal = lbal >> 8;
tf->hob_lbam = lbam >> 8;
tf->hob_lbah = lbah >> 8;
- }
+ }
}
/**
@@ -193,7 +193,7 @@ static void k2_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
* spin_lock_irqsave(host lock)
*/
-static void k2_bmdma_setup_mmio (struct ata_queued_cmd *qc)
+static void k2_bmdma_setup_mmio(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
@@ -224,7 +224,7 @@ static void k2_bmdma_setup_mmio (struct ata_queued_cmd *qc)
* spin_lock_irqsave(host lock)
*/
-static void k2_bmdma_start_mmio (struct ata_queued_cmd *qc)
+static void k2_bmdma_start_mmio(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
void __iomem *mmio = ap->ioaddr.bmdma_addr;
@@ -255,7 +255,7 @@ static void k2_bmdma_start_mmio (struct ata_queued_cmd *qc)
static u8 k2_stat_check_status(struct ata_port *ap)
{
- return readl(ap->ioaddr.status_addr);
+ return readl(ap->ioaddr.status_addr);
}
#ifdef CONFIG_PPC_OF
@@ -395,7 +395,7 @@ static void k2_sata_setup_port(struct ata_ioports *port, void __iomem *base)
}
-static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+static int k2_sata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version;
const struct ata_port_info *ppi[] =
diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c
index 9f9f7b30654a..4d857185f33b 100644
--- a/drivers/ata/sata_sx4.c
+++ b/drivers/ata/sata_sx4.c
@@ -62,13 +62,13 @@
submit ATA packet to hardware
hardware executes ATA WRITE command, w/ data in DIMM
hardware raises interrupt
-
+
and each READ looks like this:
submit ATA packet to hardware
hardware executes ATA READ command, w/ data in DIMM
hardware raises interrupt
-
+
submit HDMA packet to hardware
hardware copies data from DIMM to system memory
hardware raises interrupt
@@ -212,9 +212,9 @@ struct pdc_host_priv {
};
-static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
+static int pdc_sata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
static void pdc_eng_timeout(struct ata_port *ap);
-static void pdc_20621_phy_reset (struct ata_port *ap);
+static void pdc_20621_phy_reset(struct ata_port *ap);
static int pdc_port_start(struct ata_port *ap);
static void pdc20621_qc_prep(struct ata_queued_cmd *qc);
static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
@@ -320,16 +320,16 @@ static int pdc_port_start(struct ata_port *ap)
return 0;
}
-static void pdc_20621_phy_reset (struct ata_port *ap)
+static void pdc_20621_phy_reset(struct ata_port *ap)
{
VPRINTK("ENTER\n");
- ap->cbl = ATA_CBL_SATA;
- ata_port_probe(ap);
- ata_bus_reset(ap);
+ ap->cbl = ATA_CBL_SATA;
+ ata_port_probe(ap);
+ ata_bus_reset(ap);
}
static inline void pdc20621_ata_sg(struct ata_taskfile *tf, u8 *buf,
- unsigned int portno,
+ unsigned int portno,
unsigned int total_len)
{
u32 addr;
@@ -351,7 +351,7 @@ static inline void pdc20621_ata_sg(struct ata_taskfile *tf, u8 *buf,
}
static inline void pdc20621_host_sg(struct ata_taskfile *tf, u8 *buf,
- unsigned int portno,
+ unsigned int portno,
unsigned int total_len)
{
u32 addr;
@@ -711,8 +711,8 @@ static unsigned int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc)
return ata_qc_issue_prot(qc);
}
-static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
- struct ata_queued_cmd *qc,
+static inline unsigned int pdc20621_host_intr(struct ata_port *ap,
+ struct ata_queued_cmd *qc,
unsigned int doing_hdma,
void __iomem *mmio)
{
@@ -803,7 +803,7 @@ static void pdc20621_irq_clear(struct ata_port *ap)
readl(mmio + PDC_20621_SEQMASK);
}
-static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance)
+static irqreturn_t pdc20621_interrupt(int irq, void *dev_instance)
{
struct ata_host *host = dev_instance;
struct ata_port *ap;
@@ -836,9 +836,9 @@ static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance)
return IRQ_NONE;
}
- spin_lock(&host->lock);
+ spin_lock(&host->lock);
- for (i = 1; i < 9; i++) {
+ for (i = 1; i < 9; i++) {
port_no = i - 1;
if (port_no > 3)
port_no -= 4;
@@ -859,7 +859,7 @@ static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance)
}
}
- spin_unlock(&host->lock);
+ spin_unlock(&host->lock);
VPRINTK("mask == 0x%x\n", mask);
@@ -906,16 +906,16 @@ static void pdc_eng_timeout(struct ata_port *ap)
static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
{
- WARN_ON (tf->protocol == ATA_PROT_DMA ||
- tf->protocol == ATA_PROT_NODATA);
+ WARN_ON(tf->protocol == ATA_PROT_DMA ||
+ tf->protocol == ATA_PROT_NODATA);
ata_tf_load(ap, tf);
}
static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
{
- WARN_ON (tf->protocol == ATA_PROT_DMA ||
- tf->protocol == ATA_PROT_NODATA);
+ WARN_ON(tf->protocol == ATA_PROT_DMA ||
+ tf->protocol == ATA_PROT_NODATA);
ata_exec_command(ap, tf);
}
@@ -953,7 +953,7 @@ static void pdc20621_get_from_dimm(struct ata_host *host, void *psource,
mmio += PDC_CHIP0_OFS;
page_mask = 0x00;
- window_size = 0x2000 * 4; /* 32K byte uchar size */
+ window_size = 0x2000 * 4; /* 32K byte uchar size */
idx = (u16) (offset / window_size);
writel(0x01, mmio + PDC_GENERAL_CTLR);
@@ -979,7 +979,7 @@ static void pdc20621_get_from_dimm(struct ata_host *host, void *psource,
window_size / 4);
psource += window_size;
size -= window_size;
- idx ++;
+ idx++;
}
if (size) {
@@ -1008,7 +1008,7 @@ static void pdc20621_put_to_dimm(struct ata_host *host, void *psource,
mmio += PDC_CHIP0_OFS;
page_mask = 0x00;
- window_size = 0x2000 * 4; /* 32K byte uchar size */
+ window_size = 0x2000 * 4; /* 32K byte uchar size */
idx = (u16) (offset / window_size);
writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
@@ -1031,7 +1031,7 @@ static void pdc20621_put_to_dimm(struct ata_host *host, void *psource,
readl(mmio + PDC_GENERAL_CTLR);
psource += window_size;
size -= window_size;
- idx ++;
+ idx++;
}
if (size) {
@@ -1050,7 +1050,7 @@ static unsigned int pdc20621_i2c_read(struct ata_host *host, u32 device,
void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
u32 i2creg = 0;
u32 status;
- u32 count =0;
+ u32 count = 0;
/* hard-code chip #0 */
mmio += PDC_CHIP0_OFS;
@@ -1082,21 +1082,21 @@ static unsigned int pdc20621_i2c_read(struct ata_host *host, u32 device,
static int pdc20621_detect_dimm(struct ata_host *host)
{
- u32 data=0 ;
+ u32 data = 0;
if (pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS,
PDC_DIMM_SPD_SYSTEM_FREQ, &data)) {
- if (data == 100)
+ if (data == 100)
return 100;
- } else
+ } else
return 0;
if (pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS, 9, &data)) {
- if(data <= 0x75)
+ if (data <= 0x75)
return 133;
- } else
+ } else
return 0;
- return 0;
+ return 0;
}
@@ -1104,8 +1104,8 @@ static int pdc20621_prog_dimm0(struct ata_host *host)
{
u32 spd0[50];
u32 data = 0;
- int size, i;
- u8 bdimmsize;
+ int size, i;
+ u8 bdimmsize;
void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
static const struct {
unsigned int reg;
@@ -1128,40 +1128,40 @@ static int pdc20621_prog_dimm0(struct ata_host *host)
/* hard-code chip #0 */
mmio += PDC_CHIP0_OFS;
- for(i=0; i<ARRAY_SIZE(pdc_i2c_read_data); i++)
+ for (i = 0; i < ARRAY_SIZE(pdc_i2c_read_data); i++)
pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS,
pdc_i2c_read_data[i].reg,
&spd0[pdc_i2c_read_data[i].ofs]);
- data |= (spd0[4] - 8) | ((spd0[21] != 0) << 3) | ((spd0[3]-11) << 4);
- data |= ((spd0[17] / 4) << 6) | ((spd0[5] / 2) << 7) |
+ data |= (spd0[4] - 8) | ((spd0[21] != 0) << 3) | ((spd0[3]-11) << 4);
+ data |= ((spd0[17] / 4) << 6) | ((spd0[5] / 2) << 7) |
((((spd0[27] + 9) / 10) - 1) << 8) ;
- data |= (((((spd0[29] > spd0[28])
+ data |= (((((spd0[29] > spd0[28])
? spd0[29] : spd0[28]) + 9) / 10) - 1) << 10;
- data |= ((spd0[30] - spd0[29] + 9) / 10 - 2) << 12;
+ data |= ((spd0[30] - spd0[29] + 9) / 10 - 2) << 12;
- if (spd0[18] & 0x08)
+ if (spd0[18] & 0x08)
data |= ((0x03) << 14);
- else if (spd0[18] & 0x04)
+ else if (spd0[18] & 0x04)
data |= ((0x02) << 14);
- else if (spd0[18] & 0x01)
+ else if (spd0[18] & 0x01)
data |= ((0x01) << 14);
- else
+ else
data |= (0 << 14);
- /*
+ /*
Calculate the size of bDIMMSize (power of 2) and
merge the DIMM size by program start/end address.
*/
- bdimmsize = spd0[4] + (spd0[5] / 2) + spd0[3] + (spd0[17] / 2) + 3;
- size = (1 << bdimmsize) >> 20; /* size = xxx(MB) */
- data |= (((size / 16) - 1) << 16);
- data |= (0 << 23);
+ bdimmsize = spd0[4] + (spd0[5] / 2) + spd0[3] + (spd0[17] / 2) + 3;
+ size = (1 << bdimmsize) >> 20; /* size = xxx(MB) */
+ data |= (((size / 16) - 1) << 16);
+ data |= (0 << 23);
data |= 8;
- writel(data, mmio + PDC_DIMM0_CONTROL);
+ writel(data, mmio + PDC_DIMM0_CONTROL);
readl(mmio + PDC_DIMM0_CONTROL);
- return size;
+ return size;
}
@@ -1172,9 +1172,9 @@ static unsigned int pdc20621_prog_dimm_global(struct ata_host *host)
void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
/* hard-code chip #0 */
- mmio += PDC_CHIP0_OFS;
+ mmio += PDC_CHIP0_OFS;
- /*
+ /*
Set To Default : DIMM Module Global Control Register (0x022259F1)
DIMM Arbitration Disable (bit 20)
DIMM Data/Control Output Driving Selection (bit12 - bit15)
@@ -1193,40 +1193,40 @@ static unsigned int pdc20621_prog_dimm_global(struct ata_host *host)
writel(data, mmio + PDC_SDRAM_CONTROL);
readl(mmio + PDC_SDRAM_CONTROL);
printk(KERN_ERR "Local DIMM ECC Enabled\n");
- }
+ }
- /* DIMM Initialization Select/Enable (bit 18/19) */
- data &= (~(1<<18));
- data |= (1<<19);
- writel(data, mmio + PDC_SDRAM_CONTROL);
+ /* DIMM Initialization Select/Enable (bit 18/19) */
+ data &= (~(1<<18));
+ data |= (1<<19);
+ writel(data, mmio + PDC_SDRAM_CONTROL);
- error = 1;
- for (i = 1; i <= 10; i++) { /* polling ~5 secs */
+ error = 1;
+ for (i = 1; i <= 10; i++) { /* polling ~5 secs */
data = readl(mmio + PDC_SDRAM_CONTROL);
if (!(data & (1<<19))) {
- error = 0;
- break;
+ error = 0;
+ break;
}
msleep(i*100);
- }
- return error;
+ }
+ return error;
}
static unsigned int pdc20621_dimm_init(struct ata_host *host)
{
int speed, size, length;
- u32 addr,spd0,pci_status;
- u32 tmp=0;
- u32 time_period=0;
- u32 tcount=0;
- u32 ticks=0;
- u32 clock=0;
- u32 fparam=0;
+ u32 addr, spd0, pci_status;
+ u32 tmp = 0;
+ u32 time_period = 0;
+ u32 tcount = 0;
+ u32 ticks = 0;
+ u32 clock = 0;
+ u32 fparam = 0;
void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
/* hard-code chip #0 */
- mmio += PDC_CHIP0_OFS;
+ mmio += PDC_CHIP0_OFS;
/* Initialize PLL based upon PCI Bus Frequency */
@@ -1254,7 +1254,7 @@ static unsigned int pdc20621_dimm_init(struct ata_host *host)
If SX4 is on PCI-X bus, after 3 seconds, the timer counter
register should be >= (0xffffffff - 3x10^8).
*/
- if(tcount >= PCI_X_TCOUNT) {
+ if (tcount >= PCI_X_TCOUNT) {
ticks = (time_period - tcount);
VPRINTK("Num counters 0x%x (%d)\n", ticks, ticks);
@@ -1285,41 +1285,43 @@ static unsigned int pdc20621_dimm_init(struct ata_host *host)
if (!(speed = pdc20621_detect_dimm(host))) {
printk(KERN_ERR "Detect Local DIMM Fail\n");
return 1; /* DIMM error */
- }
- VPRINTK("Local DIMM Speed = %d\n", speed);
+ }
+ VPRINTK("Local DIMM Speed = %d\n", speed);
- /* Programming DIMM0 Module Control Register (index_CID0:80h) */
+ /* Programming DIMM0 Module Control Register (index_CID0:80h) */
size = pdc20621_prog_dimm0(host);
- VPRINTK("Local DIMM Size = %dMB\n",size);
+ VPRINTK("Local DIMM Size = %dMB\n", size);
- /* Programming DIMM Module Global Control Register (index_CID0:88h) */
+ /* Programming DIMM Module Global Control Register (index_CID0:88h) */
if (pdc20621_prog_dimm_global(host)) {
printk(KERN_ERR "Programming DIMM Module Global Control Register Fail\n");
return 1;
- }
+ }
#ifdef ATA_VERBOSE_DEBUG
{
- u8 test_parttern1[40] = {0x55,0xAA,'P','r','o','m','i','s','e',' ',
- 'N','o','t',' ','Y','e','t',' ','D','e','f','i','n','e','d',' ',
- '1','.','1','0',
- '9','8','0','3','1','6','1','2',0,0};
+ u8 test_parttern1[40] =
+ {0x55,0xAA,'P','r','o','m','i','s','e',' ',
+ 'N','o','t',' ','Y','e','t',' ',
+ 'D','e','f','i','n','e','d',' ',
+ '1','.','1','0',
+ '9','8','0','3','1','6','1','2',0,0};
u8 test_parttern2[40] = {0};
- pdc20621_put_to_dimm(host, (void *) test_parttern2, 0x10040, 40);
- pdc20621_put_to_dimm(host, (void *) test_parttern2, 0x40, 40);
+ pdc20621_put_to_dimm(host, test_parttern2, 0x10040, 40);
+ pdc20621_put_to_dimm(host, test_parttern2, 0x40, 40);
- pdc20621_put_to_dimm(host, (void *) test_parttern1, 0x10040, 40);
- pdc20621_get_from_dimm(host, (void *) test_parttern2, 0x40, 40);
+ pdc20621_put_to_dimm(host, test_parttern1, 0x10040, 40);
+ pdc20621_get_from_dimm(host, test_parttern2, 0x40, 40);
printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
test_parttern2[1], &(test_parttern2[2]));
- pdc20621_get_from_dimm(host, (void *) test_parttern2, 0x10040,
+ pdc20621_get_from_dimm(host, test_parttern2, 0x10040,
40);
printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
test_parttern2[1], &(test_parttern2[2]));
- pdc20621_put_to_dimm(host, (void *) test_parttern1, 0x40, 40);
- pdc20621_get_from_dimm(host, (void *) test_parttern2, 0x40, 40);
+ pdc20621_put_to_dimm(host, test_parttern1, 0x40, 40);
+ pdc20621_get_from_dimm(host, test_parttern2, 0x40, 40);
printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
test_parttern2[1], &(test_parttern2[2]));
}
@@ -1375,7 +1377,8 @@ static void pdc_20621_init(struct ata_host *host)
readl(mmio + PDC_HDMA_CTLSTAT); /* flush */
}
-static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+static int pdc_sata_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
static int printed_version;
const struct ata_port_info *ppi[] =
diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c
index d394da085ae4..e710e71b7b92 100644
--- a/drivers/ata/sata_uli.c
+++ b/drivers/ata/sata_uli.c
@@ -56,9 +56,9 @@ struct uli_priv {
unsigned int scr_cfg_addr[uli_max_ports];
};
-static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
-static int uli_scr_read (struct ata_port *ap, unsigned int sc_reg, u32 *val);
-static int uli_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
+static int uli_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
+static int uli_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val);
+static int uli_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val);
static const struct pci_device_id uli_pci_tbl[] = {
{ PCI_VDEVICE(AL, 0x5289), uli_5289 },
@@ -143,7 +143,7 @@ static unsigned int get_scr_cfg_addr(struct ata_port *ap, unsigned int sc_reg)
return hpriv->scr_cfg_addr[ap->port_no] + (4 * sc_reg);
}
-static u32 uli_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg)
+static u32 uli_scr_cfg_read(struct ata_port *ap, unsigned int sc_reg)
{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
unsigned int cfg_addr = get_scr_cfg_addr(ap, sc_reg);
@@ -153,7 +153,7 @@ static u32 uli_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg)
return val;
}
-static void uli_scr_cfg_write (struct ata_port *ap, unsigned int scr, u32 val)
+static void uli_scr_cfg_write(struct ata_port *ap, unsigned int scr, u32 val)
{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
unsigned int cfg_addr = get_scr_cfg_addr(ap, scr);
@@ -161,7 +161,7 @@ static void uli_scr_cfg_write (struct ata_port *ap, unsigned int scr, u32 val)
pci_write_config_dword(pdev, cfg_addr, val);
}
-static int uli_scr_read (struct ata_port *ap, unsigned int sc_reg, u32 *val)
+static int uli_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
{
if (sc_reg > SCR_CONTROL)
return -EINVAL;
@@ -170,16 +170,16 @@ static int uli_scr_read (struct ata_port *ap, unsigned int sc_reg, u32 *val)
return 0;
}
-static int uli_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
+static int uli_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
{
- if (sc_reg > SCR_CONTROL) //SCR_CONTROL=2, SCR_ERROR=1, SCR_STATUS=0
+ if (sc_reg > SCR_CONTROL) //SCR_CONTROL=2, SCR_ERROR=1, SCR_STATUS=0
return -EINVAL;
uli_scr_cfg_write(ap, sc_reg, val);
return 0;
}
-static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+static int uli_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version;
const struct ata_port_info *ppi[] = { &uli_port_info, NULL };
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
index cc6ee0890f56..3ef072ff319d 100644
--- a/drivers/ata/sata_via.c
+++ b/drivers/ata/sata_via.c
@@ -3,7 +3,7 @@
*
* Maintained by: Jeff Garzik <jgarzik@pobox.com>
* Please ALWAYS copy linux-ide@vger.kernel.org
- on emails.
+ * on emails.
*
* Copyright 2003-2004 Red Hat, Inc. All rights reserved.
* Copyright 2003-2004 Jeff Garzik
@@ -69,7 +69,7 @@ enum {
SATA_EXT_PHY = (1 << 6), /* 0==use PATA, 1==ext phy */
};
-static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
+static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
static int svia_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val);
static int svia_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val);
static void svia_noop_freeze(struct ata_port *ap);
@@ -372,12 +372,12 @@ static const unsigned int vt6421_bar_sizes[] = {
16, 16, 16, 16, 32, 128
};
-static void __iomem * svia_scr_addr(void __iomem *addr, unsigned int port)
+static void __iomem *svia_scr_addr(void __iomem *addr, unsigned int port)
{
return addr + (port * 128);
}
-static void __iomem * vt6421_scr_addr(void __iomem *addr, unsigned int port)
+static void __iomem *vt6421_scr_addr(void __iomem *addr, unsigned int port)
{
return addr + (port * 64);
}
@@ -472,7 +472,7 @@ static void svia_configure(struct pci_dev *pdev)
if ((tmp8 & ALL_PORTS) != ALL_PORTS) {
dev_printk(KERN_DEBUG, &pdev->dev,
"enabling SATA channels (0x%x)\n",
- (int) tmp8);
+ (int) tmp8);
tmp8 |= ALL_PORTS;
pci_write_config_byte(pdev, SATA_CHAN_ENAB, tmp8);
}
@@ -482,7 +482,7 @@ static void svia_configure(struct pci_dev *pdev)
if ((tmp8 & ALL_PORTS) != ALL_PORTS) {
dev_printk(KERN_DEBUG, &pdev->dev,
"enabling SATA channel interrupts (0x%x)\n",
- (int) tmp8);
+ (int) tmp8);
tmp8 |= ALL_PORTS;
pci_write_config_byte(pdev, SATA_INT_GATE, tmp8);
}
@@ -492,13 +492,13 @@ static void svia_configure(struct pci_dev *pdev)
if ((tmp8 & NATIVE_MODE_ALL) != NATIVE_MODE_ALL) {
dev_printk(KERN_DEBUG, &pdev->dev,
"enabling SATA channel native mode (0x%x)\n",
- (int) tmp8);
+ (int) tmp8);
tmp8 |= NATIVE_MODE_ALL;
pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8);
}
}
-static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version;
unsigned int i;
@@ -525,8 +525,8 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
dev_printk(KERN_ERR, &pdev->dev,
"invalid PCI BAR %u (sz 0x%llx, val 0x%llx)\n",
i,
- (unsigned long long)pci_resource_start(pdev, i),
- (unsigned long long)pci_resource_len(pdev, i));
+ (unsigned long long)pci_resource_start(pdev, i),
+ (unsigned long long)pci_resource_len(pdev, i));
return -ENODEV;
}
diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c
index 0d9be1684873..95ae3ed24a9d 100644
--- a/drivers/ata/sata_vsc.c
+++ b/drivers/ata/sata_vsc.c
@@ -162,7 +162,8 @@ static void vsc_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
/*
* The only thing the ctl register is used for is SRST.
* That is not enabled or disabled via tf_load.
- * However, if ATA_NIEN is changed, then we need to change the interrupt register.
+ * However, if ATA_NIEN is changed, then we need to change
+ * the interrupt register.
*/
if ((tf->ctl & ATA_NIEN) != (ap->last_ctl & ATA_NIEN)) {
ap->last_ctl = tf->ctl;
@@ -219,7 +220,7 @@ static void vsc_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
tf->hob_lbal = lbal >> 8;
tf->hob_lbam = lbam >> 8;
tf->hob_lbah = lbah >> 8;
- }
+ }
}
static inline void vsc_error_intr(u8 port_status, struct ata_port *ap)
@@ -256,9 +257,10 @@ static void vsc_port_intr(u8 port_status, struct ata_port *ap)
/*
* vsc_sata_interrupt
*
- * Read the interrupt register and process for the devices that have them pending.
+ * Read the interrupt register and process for the devices that have
+ * them pending.
*/
-static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance)
+static irqreturn_t vsc_sata_interrupt(int irq, void *dev_instance)
{
struct ata_host *host = dev_instance;
unsigned int i;
@@ -287,7 +289,7 @@ static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance)
handled++;
} else
dev_printk(KERN_ERR, host->dev,
- ": interrupt from disabled port %d\n", i);
+ "interrupt from disabled port %d\n", i);
}
}
@@ -363,7 +365,8 @@ static void __devinit vsc_sata_setup_port(struct ata_ioports *port,
}
-static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+static int __devinit vsc_sata_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
static const struct ata_port_info pi = {
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
diff --git a/drivers/atm/Makefile b/drivers/atm/Makefile
index 1b16f8166b09..e4fa99658699 100644
--- a/drivers/atm/Makefile
+++ b/drivers/atm/Makefile
@@ -41,7 +41,7 @@ ifeq ($(CONFIG_ATM_FORE200E_PCA),y)
# guess the target endianess to choose the right PCA-200E firmware image
ifeq ($(CONFIG_ATM_FORE200E_PCA_DEFAULT_FW),y)
byteorder.h := include$(if $(patsubst $(srctree),,$(objtree)),2)/asm/byteorder.h
- CONFIG_ATM_FORE200E_PCA_FW := $(obj)/pca200e$(if $(shell $(CC) $(CPPFLAGS) -E -dM $(byteorder.h) | grep ' __LITTLE_ENDIAN '),.bin,_ecd.bin2)
+ CONFIG_ATM_FORE200E_PCA_FW := $(obj)/pca200e$(if $(shell $(CC) $(KBUILD_CPPFLAGS) -E -dM $(byteorder.h) | grep ' __LITTLE_ENDIAN '),.bin,_ecd.bin2)
endif
endif
diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c
index 94ebc9dc40fd..f8f7139c07c1 100644
--- a/drivers/atm/firestream.c
+++ b/drivers/atm/firestream.c
@@ -1596,7 +1596,7 @@ static irqreturn_t fs_irq (int irq, void *dev_id)
/* print the bits in the ISR register. */
if (fs_debug & FS_DEBUG_IRQ) {
- /* The FS_DEBUG things are unneccesary here. But this way it is
+ /* The FS_DEBUG things are unnecessary here. But this way it is
clear for grep that these are debug prints. */
fs_dprintk (FS_DEBUG_IRQ, "IRQ status:");
for (i=0;i<27;i++)
diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c
index f96446c358ba..9b2cf253f02f 100644
--- a/drivers/atm/horizon.c
+++ b/drivers/atm/horizon.c
@@ -1382,8 +1382,9 @@ static inline void rx_data_av_handler (hrz_dev * dev) {
/********** interrupt handler **********/
-static irqreturn_t interrupt_handler(int irq, void *dev_id) {
- hrz_dev * dev = (hrz_dev *) dev_id;
+static irqreturn_t interrupt_handler(int irq, void *dev_id)
+{
+ hrz_dev *dev = dev_id;
u32 int_source;
unsigned int irq_ok;
diff --git a/drivers/base/core.c b/drivers/base/core.c
index c1343414d285..3f4d6aa13990 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -1228,18 +1228,18 @@ int device_rename(struct device *dev, char *new_name)
sysfs_remove_link(&dev->parent->kobj, old_class_name);
}
}
-#endif
-
+#else
if (dev->class) {
sysfs_remove_link(&dev->class->subsys.kobj, old_device_name);
error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj,
dev->bus_id);
if (error) {
- /* Uh... how to unravel this if restoring can fail? */
dev_err(dev, "%s: sysfs_create_symlink failed (%d)\n",
__FUNCTION__, error);
}
}
+#endif
+
out:
put_device(dev);
diff --git a/drivers/base/dmapool.c b/drivers/base/dmapool.c
index 7647abfe1890..b5034dc72a05 100644
--- a/drivers/base/dmapool.c
+++ b/drivers/base/dmapool.c
@@ -2,7 +2,6 @@
#include <linux/device.h>
#include <linux/mm.h>
#include <asm/io.h> /* Needed for i386 to build */
-#include <asm/scatterlist.h> /* Needed for i386 to build */
#include <linux/dma-mapping.h>
#include <linux/dmapool.h>
#include <linux/slab.h>
@@ -302,7 +301,7 @@ restart:
if (mem_flags & __GFP_WAIT) {
DECLARE_WAITQUEUE (wait, current);
- current->state = TASK_INTERRUPTIBLE;
+ __set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue (&pool->waitq, &wait);
spin_unlock_irqrestore (&pool->lock, flags);
@@ -366,7 +365,7 @@ dma_pool_free (struct dma_pool *pool, void *vaddr, dma_addr_t dma)
unsigned long flags;
int map, block;
- if ((page = pool_find_page (pool, dma)) == 0) {
+ if ((page = pool_find_page(pool, dma)) == NULL) {
if (pool->dev)
dev_err(pool->dev, "dma_pool_free %s, %p/%lx (bad dma)\n",
pool->name, vaddr, (unsigned long) dma);
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 7a1390cd6aad..7868707c7eda 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -137,7 +137,7 @@ static ssize_t show_mem_state(struct sys_device *dev, char *buf)
return len;
}
-static inline int memory_notify(unsigned long val, void *v)
+int memory_notify(unsigned long val, void *v)
{
return blocking_notifier_call_chain(&memory_chain, val, v);
}
@@ -183,7 +183,6 @@ memory_block_action(struct memory_block *mem, unsigned long action)
break;
case MEM_OFFLINE:
mem->state = MEM_GOING_OFFLINE;
- memory_notify(MEM_GOING_OFFLINE, NULL);
start_paddr = page_to_pfn(first_page) << PAGE_SHIFT;
ret = remove_memory(start_paddr,
PAGES_PER_SECTION << PAGE_SHIFT);
@@ -191,7 +190,6 @@ memory_block_action(struct memory_block *mem, unsigned long action)
mem->state = old_state;
break;
}
- memory_notify(MEM_MAPPING_INVALID, NULL);
break;
default:
printk(KERN_WARNING "%s(%p, %ld) unknown action: %ld\n",
@@ -199,11 +197,6 @@ memory_block_action(struct memory_block *mem, unsigned long action)
WARN_ON(1);
ret = -EINVAL;
}
- /*
- * For now, only notify on successful memory operations
- */
- if (!ret)
- memory_notify(action, NULL);
return ret;
}
@@ -238,7 +231,7 @@ store_mem_state(struct sys_device *dev, const char *buf, size_t count)
mem = container_of(dev, struct memory_block, sysdev);
phys_section_nr = mem->phys_index;
- if (!valid_section_nr(phys_section_nr))
+ if (!present_section_nr(phys_section_nr))
goto out;
if (!strncmp(buf, "online", min((int)count, 6)))
@@ -418,7 +411,7 @@ int register_new_memory(struct mem_section *section)
int unregister_memory_section(struct mem_section *section)
{
- if (!valid_section(section))
+ if (!present_section(section))
return -EINVAL;
return remove_memory_block(0, section, 0);
@@ -443,7 +436,7 @@ int __init memory_dev_init(void)
* during boot and have been initialized
*/
for (i = 0; i < NR_MEM_SECTIONS; i++) {
- if (!valid_section_nr(i))
+ if (!present_section_nr(i))
continue;
err = add_memory_block(0, __nr_to_section(i), MEM_ONLINE, 0);
if (!ret)
diff --git a/drivers/base/node.c b/drivers/base/node.c
index cae346ef1b20..88eeed72b5d6 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -12,6 +12,7 @@
#include <linux/topology.h>
#include <linux/nodemask.h>
#include <linux/cpu.h>
+#include <linux/device.h>
static struct sysdev_class node_class = {
set_kset_name("node"),
@@ -232,8 +233,96 @@ void unregister_one_node(int nid)
unregister_node(&node_devices[nid]);
}
+/*
+ * node states attributes
+ */
+
+static ssize_t print_nodes_state(enum node_states state, char *buf)
+{
+ int n;
+
+ n = nodelist_scnprintf(buf, PAGE_SIZE, node_states[state]);
+ if (n > 0 && PAGE_SIZE > n + 1) {
+ *(buf + n++) = '\n';
+ *(buf + n++) = '\0';
+ }
+ return n;
+}
+
+static ssize_t print_nodes_possible(struct sysdev_class *class, char *buf)
+{
+ return print_nodes_state(N_POSSIBLE, buf);
+}
+
+static ssize_t print_nodes_online(struct sysdev_class *class, char *buf)
+{
+ return print_nodes_state(N_ONLINE, buf);
+}
+
+static ssize_t print_nodes_has_normal_memory(struct sysdev_class *class,
+ char *buf)
+{
+ return print_nodes_state(N_NORMAL_MEMORY, buf);
+}
+
+static ssize_t print_nodes_has_cpu(struct sysdev_class *class, char *buf)
+{
+ return print_nodes_state(N_CPU, buf);
+}
+
+static SYSDEV_CLASS_ATTR(possible, 0444, print_nodes_possible, NULL);
+static SYSDEV_CLASS_ATTR(online, 0444, print_nodes_online, NULL);
+static SYSDEV_CLASS_ATTR(has_normal_memory, 0444, print_nodes_has_normal_memory,
+ NULL);
+static SYSDEV_CLASS_ATTR(has_cpu, 0444, print_nodes_has_cpu, NULL);
+
+#ifdef CONFIG_HIGHMEM
+static ssize_t print_nodes_has_high_memory(struct sysdev_class *class,
+ char *buf)
+{
+ return print_nodes_state(N_HIGH_MEMORY, buf);
+}
+
+static SYSDEV_CLASS_ATTR(has_high_memory, 0444, print_nodes_has_high_memory,
+ NULL);
+#endif
+
+struct sysdev_class_attribute *node_state_attr[] = {
+ &attr_possible,
+ &attr_online,
+ &attr_has_normal_memory,
+#ifdef CONFIG_HIGHMEM
+ &attr_has_high_memory,
+#endif
+ &attr_has_cpu,
+};
+
+static int node_states_init(void)
+{
+ int i;
+ int err = 0;
+
+ for (i = 0; i < NR_NODE_STATES; i++) {
+ int ret;
+ ret = sysdev_class_create_file(&node_class, node_state_attr[i]);
+ if (!err)
+ err = ret;
+ }
+ return err;
+}
+
static int __init register_node_type(void)
{
- return sysdev_class_register(&node_class);
+ int ret;
+
+ ret = sysdev_class_register(&node_class);
+ if (!ret)
+ ret = node_states_init();
+
+ /*
+ * Note: we're not going to unregister the node class if we fail
+ * to register the node state class attribute files.
+ */
+ return ret;
}
postcore_initcall(register_node_type);
diff --git a/drivers/base/power/trace.c b/drivers/base/power/trace.c
index 2b0c601e422e..2b4b392dcbc1 100644
--- a/drivers/base/power/trace.c
+++ b/drivers/base/power/trace.c
@@ -114,7 +114,7 @@ static unsigned int read_magic_time(void)
get_rtc_time(&time);
printk("Time: %2d:%02d:%02d Date: %02d/%02d/%02d\n",
time.tm_hour, time.tm_min, time.tm_sec,
- time.tm_mon, time.tm_mday, time.tm_year);
+ time.tm_mon + 1, time.tm_mday, time.tm_year % 100);
val = time.tm_year; /* 100 years */
if (val > 100)
val -= 100;
diff --git a/drivers/base/topology.c b/drivers/base/topology.c
index 8d8cdfec6529..e1d3ad4db2f0 100644
--- a/drivers/base/topology.c
+++ b/drivers/base/topology.c
@@ -94,27 +94,18 @@ static struct attribute_group topology_attr_group = {
.name = "topology"
};
-static cpumask_t topology_dev_map = CPU_MASK_NONE;
-
/* Add/Remove cpu_topology interface for CPU device */
static int __cpuinit topology_add_dev(unsigned int cpu)
{
- int rc;
struct sys_device *sys_dev = get_cpu_sysdev(cpu);
- rc = sysfs_create_group(&sys_dev->kobj, &topology_attr_group);
- if (!rc)
- cpu_set(cpu, topology_dev_map);
- return rc;
+ return sysfs_create_group(&sys_dev->kobj, &topology_attr_group);
}
static void __cpuinit topology_remove_dev(unsigned int cpu)
{
struct sys_device *sys_dev = get_cpu_sysdev(cpu);
- if (!cpu_isset(cpu, topology_dev_map))
- return;
- cpu_clear(cpu, topology_dev_map);
sysfs_remove_group(&sys_dev->kobj, &topology_attr_group);
}
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 84d6aa500e26..9030c373ce67 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -44,6 +44,7 @@
#include <linux/init.h>
#include <linux/jiffies.h>
#include <linux/random.h>
+#include <linux/scatterlist.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include "DAC960.h"
@@ -345,6 +346,7 @@ static bool DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller)
Command->V1.ScatterGatherList =
(DAC960_V1_ScatterGatherSegment_T *)ScatterGatherCPU;
Command->V1.ScatterGatherListDMA = ScatterGatherDMA;
+ sg_init_table(Command->cmd_sglist, DAC960_V1_ScatterGatherLimit);
} else {
Command->cmd_sglist = Command->V2.ScatterList;
Command->V2.ScatterGatherList =
@@ -353,6 +355,7 @@ static bool DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller)
Command->V2.RequestSense =
(DAC960_SCSI_RequestSense_T *)RequestSenseCPU;
Command->V2.RequestSenseDMA = RequestSenseDMA;
+ sg_init_table(Command->cmd_sglist, DAC960_V2_ScatterGatherLimit);
}
}
return true;
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index ca4d7f0d09b7..4d0119ea9e35 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -204,23 +204,6 @@ config BLK_DEV_COW_COMMON
bool
default BLK_DEV_UBD
-config MMAPPER
- tristate "Example IO memory driver (BROKEN)"
- depends on UML && BROKEN
- ---help---
- The User-Mode Linux port can provide support for IO Memory
- emulation with this option. This allows a host file to be
- specified as an I/O region on the kernel command line. That file
- will be mapped into UML's kernel address space where a driver can
- locate it and do whatever it wants with the memory, including
- providing an interface to it for UML processes to use.
-
- For more information, see
- <http://user-mode-linux.sourceforge.net/iomem.html>.
-
- If you'd like to be able to provide a simulated IO port space for
- User-Mode Linux processes, say Y. If unsure, say N.
-
config BLK_DEV_LOOP
tristate "Loopback device support"
---help---
@@ -351,7 +334,7 @@ config BLK_DEV_RAM_COUNT
default "16"
depends on BLK_DEV_RAM
help
- The default value is 16 RAM disks. Change this if you know what
+ The default value is 16 RAM disks. Change this if you know what you
are doing. If you boot from a filesystem that needs to be extracted
in memory, you will need at least one RAM disk (e.g. root on cramfs).
@@ -361,7 +344,7 @@ config BLK_DEV_RAM_SIZE
default "4096"
help
The default value is 4096 kilobytes. Only change this if you know
- what are you doing.
+ what you are doing.
config BLK_DEV_RAM_BLOCKSIZE
int "Default RAM disk block size (bytes)"
@@ -442,4 +425,10 @@ config XEN_BLKDEV_FRONTEND
block device driver. It communicates with a back-end driver
in another domain which drives the actual block device.
+config VIRTIO_BLK
+ tristate "Virtio block driver (EXPERIMENTAL)"
+ depends on EXPERIMENTAL && VIRTIO
+ ---help---
+ This is the virtual block driver for lguest. Say Y or M.
+
endif # BLK_DEV
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index 014e72121b5a..7691505a2e12 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -25,10 +25,10 @@ obj-$(CONFIG_SUNVDC) += sunvdc.o
obj-$(CONFIG_BLK_DEV_UMEM) += umem.o
obj-$(CONFIG_BLK_DEV_NBD) += nbd.o
obj-$(CONFIG_BLK_DEV_CRYPTOLOOP) += cryptoloop.o
+obj-$(CONFIG_VIRTIO_BLK) += virtio_blk.o
obj-$(CONFIG_VIODASD) += viodasd.o
obj-$(CONFIG_BLK_DEV_SX8) += sx8.o
obj-$(CONFIG_BLK_DEV_UB) += ub.o
obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += xen-blkfront.o
-obj-$(CONFIG_LGUEST_BLOCK) += lguest_blk.o
diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h
index ba07f762c4cb..07f02f855ab5 100644
--- a/drivers/block/aoe/aoe.h
+++ b/drivers/block/aoe/aoe.h
@@ -48,15 +48,6 @@ struct aoe_hdr {
__be32 tag;
};
-#ifdef __KERNEL__
-#include <linux/skbuff.h>
-
-static inline struct aoe_hdr *aoe_hdr(const struct sk_buff *skb)
-{
- return (struct aoe_hdr *)skb_mac_header(skb);
-}
-#endif
-
struct aoe_atahdr {
unsigned char aflags;
unsigned char errfeat;
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
index 99672017ca56..4d59d5057734 100644
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -120,7 +120,7 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f)
/* initialize the headers & frame */
skb = f->skb;
- h = aoe_hdr(skb);
+ h = (struct aoe_hdr *) skb_mac_header(skb);
ah = (struct aoe_atahdr *) (h+1);
skb_put(skb, sizeof *h + sizeof *ah);
memset(h, 0, skb->len);
@@ -209,7 +209,7 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail)
skb->dev = ifp;
if (sl_tail == NULL)
sl_tail = skb;
- h = aoe_hdr(skb);
+ h = (struct aoe_hdr *) skb_mac_header(skb);
memset(h, 0, sizeof *h + sizeof *ch);
memset(h->dst, 0xff, sizeof h->dst);
@@ -304,7 +304,7 @@ rexmit(struct aoedev *d, struct frame *f)
aoechr_error(buf);
skb = f->skb;
- h = aoe_hdr(skb);
+ h = (struct aoe_hdr *) skb_mac_header(skb);
ah = (struct aoe_atahdr *) (h+1);
f->tag = n;
h->tag = cpu_to_be32(n);
@@ -533,7 +533,7 @@ aoecmd_ata_rsp(struct sk_buff *skb)
char ebuf[128];
u16 aoemajor;
- hin = aoe_hdr(skb);
+ hin = (struct aoe_hdr *) skb_mac_header(skb);
aoemajor = be16_to_cpu(get_unaligned(&hin->major));
d = aoedev_by_aoeaddr(aoemajor, hin->minor);
if (d == NULL) {
@@ -565,7 +565,7 @@ aoecmd_ata_rsp(struct sk_buff *skb)
calc_rttavg(d, tsince(f->tag));
ahin = (struct aoe_atahdr *) (hin+1);
- hout = aoe_hdr(f->skb);
+ hout = (struct aoe_hdr *) skb_mac_header(f->skb);
ahout = (struct aoe_atahdr *) (hout+1);
buf = f->buf;
@@ -699,7 +699,7 @@ aoecmd_ata_id(struct aoedev *d)
/* initialize the headers & frame */
skb = f->skb;
- h = aoe_hdr(skb);
+ h = (struct aoe_hdr *) skb_mac_header(skb);
ah = (struct aoe_atahdr *) (h+1);
skb_put(skb, sizeof *h + sizeof *ah);
memset(h, 0, skb->len);
@@ -730,7 +730,7 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
enum { MAXFRAMES = 16 };
u16 n;
- h = aoe_hdr(skb);
+ h = (struct aoe_hdr *) skb_mac_header(skb);
ch = (struct aoe_cfghdr *) (h+1);
/*
diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c
index 4dc0fb7da94b..4e6deb7f5c24 100644
--- a/drivers/block/aoe/aoenet.c
+++ b/drivers/block/aoe/aoenet.c
@@ -127,7 +127,7 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt,
goto exit;
skb_push(skb, ETH_HLEN); /* (1) */
- h = aoe_hdr(skb);
+ h = (struct aoe_hdr *) skb_mac_header(skb);
n = be32_to_cpu(get_unaligned(&h->tag));
if ((h->verfl & AOEFL_RSP) == 0 || (n & 1<<31))
goto exit;
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 55c3237fb1bc..7d704968765f 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1,20 +1,20 @@
/*
- * Disk Array driver for HP SA 5xxx and 6xxx Controllers
- * Copyright 2000, 2006 Hewlett-Packard Development Company, L.P.
+ * Disk Array driver for HP Smart Array controllers.
+ * (C) Copyright 2000, 2007 Hewlett-Packard Development Company, L.P.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT. See the GNU General Public License for more details.
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307, USA.
*
* Questions/Comments/Bugfixes to iss_storagedev@hp.com
*
@@ -1191,7 +1191,6 @@ static inline void complete_buffers(struct bio *bio, int status)
{
while (bio) {
struct bio *xbh = bio->bi_next;
- int nr_sectors = bio_sectors(bio);
bio->bi_next = NULL;
bio_endio(bio, status ? 0 : -EIO);
@@ -1583,38 +1582,36 @@ static int deregister_disk(struct gendisk *disk, drive_info_struct *drv,
* allows us to delete disk zero but keep the controller registered.
*/
if (h->gendisk[0] != disk) {
- if (disk) {
- struct request_queue *q = disk->queue;
- if (disk->flags & GENHD_FL_UP)
- del_gendisk(disk);
- if (q) {
- blk_cleanup_queue(q);
- /* Set drv->queue to NULL so that we do not try
- * to call blk_start_queue on this queue in the
- * interrupt handler
- */
- drv->queue = NULL;
- }
- /* If clear_all is set then we are deleting the logical
- * drive, not just refreshing its info. For drives
- * other than disk 0 we will call put_disk. We do not
- * do this for disk 0 as we need it to be able to
- * configure the controller.
+ struct request_queue *q = disk->queue;
+ if (disk->flags & GENHD_FL_UP)
+ del_gendisk(disk);
+ if (q) {
+ blk_cleanup_queue(q);
+ /* Set drv->queue to NULL so that we do not try
+ * to call blk_start_queue on this queue in the
+ * interrupt handler
+ */
+ drv->queue = NULL;
+ }
+ /* If clear_all is set then we are deleting the logical
+ * drive, not just refreshing its info. For drives
+ * other than disk 0 we will call put_disk. We do not
+ * do this for disk 0 as we need it to be able to
+ * configure the controller.
+ */
+ if (clear_all){
+ /* This isn't pretty, but we need to find the
+ * disk in our array and NULL our the pointer.
+ * This is so that we will call alloc_disk if
+ * this index is used again later.
*/
- if (clear_all){
- /* This isn't pretty, but we need to find the
- * disk in our array and NULL our the pointer.
- * This is so that we will call alloc_disk if
- * this index is used again later.
- */
- for (i=0; i < CISS_MAX_LUN; i++){
- if(h->gendisk[i] == disk){
- h->gendisk[i] = NULL;
- break;
- }
+ for (i=0; i < CISS_MAX_LUN; i++){
+ if(h->gendisk[i] == disk){
+ h->gendisk[i] = NULL;
+ break;
}
- put_disk(disk);
}
+ put_disk(disk);
}
} else {
set_capacity(disk, 0);
@@ -2366,30 +2363,55 @@ static inline void resend_cciss_cmd(ctlr_info_t *h, CommandList_struct *c)
start_io(h);
}
+static inline unsigned int make_status_bytes(unsigned int scsi_status_byte,
+ unsigned int msg_byte, unsigned int host_byte,
+ unsigned int driver_byte)
+{
+ /* inverse of macros in scsi.h */
+ return (scsi_status_byte & 0xff) |
+ ((msg_byte & 0xff) << 8) |
+ ((host_byte & 0xff) << 16) |
+ ((driver_byte & 0xff) << 24);
+}
+
static inline int evaluate_target_status(CommandList_struct *cmd)
{
unsigned char sense_key;
- int error_count = 1;
+ unsigned char status_byte, msg_byte, host_byte, driver_byte;
+ int error_value;
+
+ /* If we get in here, it means we got "target status", that is, scsi status */
+ status_byte = cmd->err_info->ScsiStatus;
+ driver_byte = DRIVER_OK;
+ msg_byte = cmd->err_info->CommandStatus; /* correct? seems too device specific */
+
+ if (blk_pc_request(cmd->rq))
+ host_byte = DID_PASSTHROUGH;
+ else
+ host_byte = DID_OK;
+
+ error_value = make_status_bytes(status_byte, msg_byte,
+ host_byte, driver_byte);
- if (cmd->err_info->ScsiStatus != 0x02) { /* not check condition? */
+ if (cmd->err_info->ScsiStatus != SAM_STAT_CHECK_CONDITION) {
if (!blk_pc_request(cmd->rq))
printk(KERN_WARNING "cciss: cmd %p "
"has SCSI Status 0x%x\n",
cmd, cmd->err_info->ScsiStatus);
- return error_count;
+ return error_value;
}
/* check the sense key */
sense_key = 0xf & cmd->err_info->SenseInfo[2];
/* no status or recovered error */
- if ((sense_key == 0x0) || (sense_key == 0x1))
- error_count = 0;
+ if (((sense_key == 0x0) || (sense_key == 0x1)) && !blk_pc_request(cmd->rq))
+ error_value = 0;
if (!blk_pc_request(cmd->rq)) { /* Not SG_IO or similar? */
- if (error_count != 0)
+ if (error_value != 0)
printk(KERN_WARNING "cciss: cmd %p has CHECK CONDITION"
" sense key = 0x%x\n", cmd, sense_key);
- return error_count;
+ return error_value;
}
/* SG_IO or similar, copy sense data back */
@@ -2401,7 +2423,7 @@ static inline int evaluate_target_status(CommandList_struct *cmd)
} else
cmd->rq->sense_len = 0;
- return error_count;
+ return error_value;
}
/* checks the status of the job and calls complete buffers to mark all
@@ -2417,7 +2439,7 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd,
rq->errors = 0;
if (timeout)
- rq->errors = 1;
+ rq->errors = make_status_bytes(0, 0, 0, DRIVER_TIMEOUT);
if (cmd->err_info->CommandStatus == 0) /* no error has occurred */
goto after_error_processing;
@@ -2443,32 +2465,44 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd,
case CMD_INVALID:
printk(KERN_WARNING "cciss: cmd %p is "
"reported invalid\n", cmd);
- rq->errors = 1;
+ rq->errors = make_status_bytes(SAM_STAT_GOOD,
+ cmd->err_info->CommandStatus, DRIVER_OK,
+ blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR);
break;
case CMD_PROTOCOL_ERR:
printk(KERN_WARNING "cciss: cmd %p has "
"protocol error \n", cmd);
- rq->errors = 1;
+ rq->errors = make_status_bytes(SAM_STAT_GOOD,
+ cmd->err_info->CommandStatus, DRIVER_OK,
+ blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR);
break;
case CMD_HARDWARE_ERR:
printk(KERN_WARNING "cciss: cmd %p had "
" hardware error\n", cmd);
- rq->errors = 1;
+ rq->errors = make_status_bytes(SAM_STAT_GOOD,
+ cmd->err_info->CommandStatus, DRIVER_OK,
+ blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR);
break;
case CMD_CONNECTION_LOST:
printk(KERN_WARNING "cciss: cmd %p had "
"connection lost\n", cmd);
- rq->errors = 1;
+ rq->errors = make_status_bytes(SAM_STAT_GOOD,
+ cmd->err_info->CommandStatus, DRIVER_OK,
+ blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR);
break;
case CMD_ABORTED:
printk(KERN_WARNING "cciss: cmd %p was "
"aborted\n", cmd);
- rq->errors = 1;
+ rq->errors = make_status_bytes(SAM_STAT_GOOD,
+ cmd->err_info->CommandStatus, DRIVER_OK,
+ blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ABORT);
break;
case CMD_ABORT_FAILED:
printk(KERN_WARNING "cciss: cmd %p reports "
"abort failed\n", cmd);
- rq->errors = 1;
+ rq->errors = make_status_bytes(SAM_STAT_GOOD,
+ cmd->err_info->CommandStatus, DRIVER_OK,
+ blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR);
break;
case CMD_UNSOLICITED_ABORT:
printk(KERN_WARNING "cciss%d: unsolicited "
@@ -2482,17 +2516,23 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd,
printk(KERN_WARNING
"cciss%d: %p retried too "
"many times\n", h->ctlr, cmd);
- rq->errors = 1;
+ rq->errors = make_status_bytes(SAM_STAT_GOOD,
+ cmd->err_info->CommandStatus, DRIVER_OK,
+ blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ABORT);
break;
case CMD_TIMEOUT:
printk(KERN_WARNING "cciss: cmd %p timedout\n", cmd);
- rq->errors = 1;
+ rq->errors = make_status_bytes(SAM_STAT_GOOD,
+ cmd->err_info->CommandStatus, DRIVER_OK,
+ blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR);
break;
default:
printk(KERN_WARNING "cciss: cmd %p returned "
"unknown status %x\n", cmd,
cmd->err_info->CommandStatus);
- rq->errors = 1;
+ rq->errors = make_status_bytes(SAM_STAT_GOOD,
+ cmd->err_info->CommandStatus, DRIVER_OK,
+ blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR);
}
after_error_processing:
@@ -2570,6 +2610,7 @@ static void do_cciss_request(struct request_queue *q)
(int)creq->nr_sectors);
#endif /* CCISS_DEBUG */
+ sg_init_table(tmp_sg, MAXSGENTRIES);
seg = blk_rq_map_sg(q, creq, tmp_sg);
/* get the DMA records for the setup */
@@ -2580,7 +2621,7 @@ static void do_cciss_request(struct request_queue *q)
for (i = 0; i < seg; i++) {
c->SG[i].Len = tmp_sg[i].length;
- temp64.val = (__u64) pci_map_page(h->pdev, tmp_sg[i].page,
+ temp64.val = (__u64) pci_map_page(h->pdev, sg_page(&tmp_sg[i]),
tmp_sg[i].offset,
tmp_sg[i].length, dir);
c->SG[i].Addr.lower = temp64.val32.lower;
@@ -3035,15 +3076,20 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
}
#endif
- /* Disabling DMA prefetch for the P600
- * An ASIC bug may result in a prefetch beyond
- * physical memory.
+ /* Disabling DMA prefetch and refetch for the P600.
+ * An ASIC bug may result in accesses to invalid memory addresses.
+ * We've disabled prefetch for some time now. Testing with XEN
+ * kernels revealed a bug in the refetch if dom0 resides on a P600.
*/
if(board_id == 0x3225103C) {
__u32 dma_prefetch;
+ __u32 dma_refetch;
dma_prefetch = readl(c->vaddr + I2O_DMA1_CFG);
dma_prefetch |= 0x8000;
writel(dma_prefetch, c->vaddr + I2O_DMA1_CFG);
+ pci_read_config_dword(pdev, PCI_COMMAND_PARITY, &dma_refetch);
+ dma_refetch |= 0x1;
+ pci_write_config_dword(pdev, PCI_COMMAND_PARITY, dma_refetch);
}
#ifdef CCISS_DEBUG
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index 4aca7ddfdddf..63ee6c076cb3 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -1,20 +1,20 @@
/*
- * Disk Array driver for Compaq SA53xx Controllers, SCSI Tape module
- * Copyright 2001 Compaq Computer Corporation
+ * Disk Array driver for HP Smart Array controllers, SCSI Tape module.
+ * (C) Copyright 2001, 2007 Hewlett-Packard Development Company, L.P.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT. See the GNU General Public License for more details.
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Foundation, Inc., 59 Temple Place, Suite 300, Boston, MA
+ * 02111-1307, USA.
*
* Questions/Comments/Bugfixes to iss_storagedev@hp.com
*
diff --git a/drivers/block/cciss_scsi.h b/drivers/block/cciss_scsi.h
index 5e7e06c07d6c..d9c2c586502f 100644
--- a/drivers/block/cciss_scsi.h
+++ b/drivers/block/cciss_scsi.h
@@ -1,20 +1,20 @@
/*
- * Disk Array driver for Compaq SA53xx Controllers, SCSI Tape module
- * Copyright 2001 Compaq Computer Corporation
+ * Disk Array driver for HP Smart Array controllers, SCSI Tape module.
+ * (C) Copyright 2001, 2007 Hewlett-Packard Development Company, L.P.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT. See the GNU General Public License for more details.
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Foundation, Inc., 59 Temple Place, Suite 300, Boston, MA
+ * 02111-1307, USA.
*
* Questions/Comments/Bugfixes to iss_storagedev@hp.com
*
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index 3853c9a38d6a..c8132d958795 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -37,6 +37,7 @@
#include <linux/spinlock.h>
#include <linux/blkdev.h>
#include <linux/genhd.h>
+#include <linux/scatterlist.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -918,6 +919,7 @@ queue_next:
DBGPX(
printk("sector=%d, nr_sectors=%d\n", creq->sector, creq->nr_sectors);
);
+ sg_init_table(tmp_sg, SG_MAX);
seg = blk_rq_map_sg(q, creq, tmp_sg);
/* Now do all the DMA Mappings */
@@ -929,7 +931,7 @@ DBGPX(
{
c->req.sg[i].size = tmp_sg[i].length;
c->req.sg[i].addr = (__u32) pci_map_page(h->pci_dev,
- tmp_sg[i].page,
+ sg_page(&tmp_sg[i]),
tmp_sg[i].offset,
tmp_sg[i].length, dir);
}
@@ -981,9 +983,8 @@ static void start_io(ctlr_info_t *h)
static inline void complete_buffers(struct bio *bio, int ok)
{
struct bio *xbh;
- while(bio) {
- int nr_sectors = bio_sectors(bio);
+ while (bio) {
xbh = bio->bi_next;
bio->bi_next = NULL;
diff --git a/drivers/block/cryptoloop.c b/drivers/block/cryptoloop.c
index 40535036e893..241167878edf 100644
--- a/drivers/block/cryptoloop.c
+++ b/drivers/block/cryptoloop.c
@@ -26,6 +26,7 @@
#include <linux/crypto.h>
#include <linux/blkdev.h>
#include <linux/loop.h>
+#include <linux/scatterlist.h>
#include <asm/semaphore.h>
#include <asm/uaccess.h>
@@ -119,14 +120,17 @@ cryptoloop_transfer(struct loop_device *lo, int cmd,
.tfm = tfm,
.flags = CRYPTO_TFM_REQ_MAY_SLEEP,
};
- struct scatterlist sg_out = { NULL, };
- struct scatterlist sg_in = { NULL, };
+ struct scatterlist sg_out;
+ struct scatterlist sg_in;
encdec_cbc_t encdecfunc;
struct page *in_page, *out_page;
unsigned in_offs, out_offs;
int err;
+ sg_init_table(&sg_out, 1);
+ sg_init_table(&sg_in, 1);
+
if (cmd == READ) {
in_page = raw_page;
in_offs = raw_off;
@@ -146,13 +150,8 @@ cryptoloop_transfer(struct loop_device *lo, int cmd,
u32 iv[4] = { 0, };
iv[0] = cpu_to_le32(IV & 0xffffffff);
- sg_in.page = in_page;
- sg_in.offset = in_offs;
- sg_in.length = sz;
-
- sg_out.page = out_page;
- sg_out.offset = out_offs;
- sg_out.length = sz;
+ sg_set_page(&sg_in, in_page, sz, in_offs);
+ sg_set_page(&sg_out, out_page, sz, out_offs);
desc.info = iv;
err = encdecfunc(&desc, &sg_out, &sg_in, sz);
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 80483aac4cc9..639ed14bb08d 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -5,6 +5,7 @@
* Copyright (C) 1993, 1994 Alain Knaff
* Copyright (C) 1998 Alan Cox
*/
+
/*
* 02.12.91 - Changed to static variables to indicate need for reset
* and recalibrate. This makes some things easier (output_byte reset
@@ -149,7 +150,7 @@
#define REALLY_SLOW_IO
#define DEBUGT 2
-#define DCL_DEBUG /* debug disk change line */
+#define DCL_DEBUG /* debug disk change line */
/* do print messages for unexpected interrupts */
static int print_unex = 1;
@@ -161,10 +162,8 @@ static int print_unex = 1;
#include <linux/workqueue.h>
#define FDPATCHES
#include <linux/fdreg.h>
-
#include <linux/fd.h>
#include <linux/hdreg.h>
-
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/mm.h>
@@ -274,8 +273,7 @@ static inline void fallback_on_nodma_alloc(char **addr, size_t l)
return; /* we have the memory */
if (can_use_virtual_dma != 2)
return; /* no fallback allowed */
- printk
- ("DMA memory shortage. Temporarily falling back on virtual DMA\n");
+ printk("DMA memory shortage. Temporarily falling back on virtual DMA\n");
*addr = (char *)nodma_mem_alloc(l);
#else
return;
@@ -291,8 +289,8 @@ static int initialising = 1;
#define TOMINOR(x) ((x & 3) | ((x & 4) << 5))
#define UNIT(x) ((x) & 0x03) /* drive on fdc */
#define FDC(x) (((x) & 0x04) >> 2) /* fdc of drive */
+ /* reverse mapping from unit and fdc to drive */
#define REVDRIVE(fdc, unit) ((unit) + ((fdc) << 2))
- /* reverse mapping from unit and fdc to drive */
#define DP (&drive_params[current_drive])
#define DRS (&drive_state[current_drive])
#define DRWE (&write_errors[current_drive])
@@ -356,7 +354,6 @@ static int inr; /* size of reply buffer, when called from interrupt */
#define R_HEAD (reply_buffer[4])
#define R_SECTOR (reply_buffer[5])
#define R_SIZECODE (reply_buffer[6])
-
#define SEL_DLY (2*HZ/100)
/*
@@ -472,8 +469,8 @@ static struct floppy_struct floppy_type[32] = {
{ 6400,40,2,80,0,0x25,0x5B,0xCF,0x00,"E3200" }, /* 26 3.20MB 3.5" */
{ 7040,44,2,80,0,0x25,0x5B,0xCF,0x00,"E3520" }, /* 27 3.52MB 3.5" */
{ 7680,48,2,80,0,0x25,0x63,0xCF,0x00,"E3840" }, /* 28 3.84MB 3.5" */
-
{ 3680,23,2,80,0,0x1C,0x10,0xCF,0x00,"H1840" }, /* 29 1.84MB 3.5" */
+
{ 1600,10,2,80,0,0x25,0x02,0xDF,0x2E,"D800" }, /* 30 800KB 3.5" */
{ 3200,20,2,80,0,0x1C,0x00,0xCF,0x2C,"H1600" }, /* 31 1.6MB 3.5" */
};
@@ -539,12 +536,12 @@ static char *floppy_track_buffer;
static int max_buffer_sectors;
static int *errors;
-typedef void (*done_f) (int);
+typedef void (*done_f)(int);
static struct cont_t {
- void (*interrupt) (void); /* this is called after the interrupt of the
+ void (*interrupt)(void); /* this is called after the interrupt of the
* main command */
- void (*redo) (void); /* this is called to retry the operation */
- void (*error) (void); /* this is called to tally an error */
+ void (*redo)(void); /* this is called to retry the operation */
+ void (*error)(void); /* this is called to tally an error */
done_f done; /* this is called to say if the operation has
* succeeded/failed */
} *cont;
@@ -694,7 +691,6 @@ static void reschedule_timeout(int drive, const char *message, int marg)
}
#define INFBOUND(a,b) (a)=max_t(int, a, b)
-
#define SUPBOUND(a,b) (a)=min_t(int, a, b)
/*
@@ -733,6 +729,7 @@ static void reschedule_timeout(int drive, const char *message, int marg)
static int disk_change(int drive)
{
int fdc = FDC(drive);
+
#ifdef FLOPPY_SANITY_CHECK
if (time_before(jiffies, UDRS->select_date + UDP->select_delay))
DPRINT("WARNING disk change called early\n");
@@ -771,7 +768,6 @@ static int disk_change(int drive)
floppy_sizes[TOMINOR(drive)] = MAX_DISK_SIZE << 1;
}
- /*USETF(FD_DISK_NEWCHANGE); */
return 1;
} else {
UDRS->last_checked = jiffies;
@@ -787,7 +783,10 @@ static inline int is_selected(int dor, int unit)
static int set_dor(int fdc, char mask, char data)
{
- register unsigned char drive, unit, newdor, olddor;
+ unsigned char unit;
+ unsigned char drive;
+ unsigned char newdor;
+ unsigned char olddor;
if (FDCS->address == -1)
return -1;
@@ -892,7 +891,6 @@ static int _lock_fdc(int drive, int interruptible, int line)
set_current_state(TASK_RUNNING);
remove_wait_queue(&fdc_wait, &wait);
-
flush_scheduled_work();
}
command_status = FD_COMMAND_NONE;
@@ -942,7 +940,7 @@ static void motor_off_callback(unsigned long nr)
static void floppy_off(unsigned int drive)
{
unsigned long volatile delta;
- register int fdc = FDC(drive);
+ int fdc = FDC(drive);
if (!(FDCS->dor & (0x10 << UNIT(drive))))
return;
@@ -968,7 +966,9 @@ static void floppy_off(unsigned int drive)
*/
static void scandrives(void)
{
- int i, drive, saved_drive;
+ int i;
+ int drive;
+ int saved_drive;
if (DP->select_delay)
return;
@@ -1146,7 +1146,9 @@ static void show_floppy(void);
/* waits until the fdc becomes ready */
static int wait_til_ready(void)
{
- int counter, status;
+ int status;
+ int counter;
+
if (FDCS->reset)
return -1;
for (counter = 0; counter < 10000; counter++) {
@@ -1193,7 +1195,8 @@ static int output_byte(char byte)
/* gets the response from the fdc */
static int result(void)
{
- int i, status = 0;
+ int i;
+ int status = 0;
for (i = 0; i < MAX_REPLIES; i++) {
if ((status = wait_til_ready()) < 0)
@@ -1226,6 +1229,7 @@ static int result(void)
static int need_more_output(void)
{
int status;
+
if ((status = wait_til_ready()) < 0)
return -1;
if ((status & (STATUS_READY | STATUS_DIR | STATUS_DMA)) == STATUS_READY)
@@ -1309,8 +1313,11 @@ static int fdc_configure(void)
*/
static void fdc_specify(void)
{
- unsigned char spec1, spec2;
- unsigned long srt, hlt, hut;
+ unsigned char spec1;
+ unsigned char spec2;
+ unsigned long srt;
+ unsigned long hlt;
+ unsigned long hut;
unsigned long dtr = NOMINAL_DTR;
unsigned long scale_dtr = NOMINAL_DTR;
int hlt_max_code = 0x7f;
@@ -1319,7 +1326,6 @@ static void fdc_specify(void)
if (FDCS->need_configure && FDCS->version >= FDC_82072A) {
fdc_configure();
FDCS->need_configure = 0;
- /*DPRINT("FIFO enabled\n"); */
}
switch (raw_cmd->rate & 0x03) {
@@ -1472,7 +1478,6 @@ static int interpret_errors(void)
tell_sector();
}
printk("\n");
-
}
if (ST2 & ST2_WC || ST2 & ST2_BC)
/* wrong cylinder => recal */
@@ -1498,7 +1503,10 @@ static int interpret_errors(void)
*/
static void setup_rw_floppy(void)
{
- int i, r, flags, dflags;
+ int i;
+ int r;
+ int flags;
+ int dflags;
unsigned long ready_date;
timeout_fn function;
@@ -1728,9 +1736,9 @@ static void print_result(char *message, int inr)
/* interrupt handler. Note that this can be called externally on the Sparc */
irqreturn_t floppy_interrupt(int irq, void *dev_id)
{
- void (*handler) (void) = do_floppy;
int do_print;
unsigned long f;
+ void (*handler)(void) = do_floppy;
lasthandler = handler;
interruptjiffies = jiffies;
@@ -1912,12 +1920,11 @@ static void floppy_shutdown(unsigned long data)
is_alive("floppy shutdown");
}
-/*typedef void (*timeout_fn)(unsigned long);*/
-
/* start motor, check media-changed condition and write protection */
-static int start_motor(void (*function) (void))
+static int start_motor(void (*function)(void))
{
- int mask, data;
+ int mask;
+ int data;
mask = 0xfc;
data = UNIT(current_drive);
@@ -2020,17 +2027,17 @@ static struct cont_t wakeup_cont = {
.interrupt = empty,
.redo = do_wakeup,
.error = empty,
- .done = (done_f) empty
+ .done = (done_f)empty
};
static struct cont_t intr_cont = {
.interrupt = empty,
.redo = process_fd_request,
.error = empty,
- .done = (done_f) empty
+ .done = (done_f)empty
};
-static int wait_til_done(void (*handler) (void), int interruptible)
+static int wait_til_done(void (*handler)(void), int interruptible)
{
int ret;
@@ -2049,7 +2056,6 @@ static int wait_til_done(void (*handler) (void), int interruptible)
break;
is_alive("wait_til_done");
-
schedule();
}
@@ -2141,6 +2147,7 @@ static void bad_flp_intr(void)
static void set_floppy(int drive)
{
int type = ITYPE(UDRS->fd_device);
+
if (type)
_floppy = floppy_type + type;
else
@@ -2169,11 +2176,14 @@ static void format_interrupt(void)
#define CT(x) ((x) | 0xc0)
static void setup_format_params(int track)
{
+ int n;
+ int il;
+ int count;
+ int head_shift;
+ int track_shift;
struct fparm {
unsigned char track, head, sect, size;
} *here = (struct fparm *)floppy_track_buffer;
- int il, n;
- int count, head_shift, track_shift;
raw_cmd = &default_raw_cmd;
raw_cmd->track = track;
@@ -2344,7 +2354,10 @@ static void request_done(int uptodate)
/* Interrupt handler evaluating the result of the r/w operation */
static void rw_interrupt(void)
{
- int nr_sectors, ssize, eoc, heads;
+ int eoc;
+ int ssize;
+ int heads;
+ int nr_sectors;
if (R_HEAD >= 2) {
/* some Toshiba floppy controllers occasionnally seem to
@@ -2476,7 +2489,8 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2)
{
int remaining; /* number of transferred 512-byte sectors */
struct bio_vec *bv;
- char *buffer, *dma_buffer;
+ char *buffer;
+ char *dma_buffer;
int size;
struct req_iterator iter;
@@ -2556,19 +2570,6 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2)
#endif
}
-#if 0
-static inline int check_dma_crossing(char *start,
- unsigned long length, char *message)
-{
- if (CROSS_64KB(start, length)) {
- printk("DMA xfer crosses 64KB boundary in %s %p-%p\n",
- message, start, start + length);
- return 1;
- } else
- return 0;
-}
-#endif
-
/* work around a bug in pseudo DMA
* (on some FDCs) pseudo DMA does not stop when the CPU stops
* sending data. Hence we need a different way to signal the
@@ -2578,7 +2579,8 @@ static inline int check_dma_crossing(char *start,
*/
static void virtualdmabug_workaround(void)
{
- int hard_sectors, end_sector;
+ int hard_sectors;
+ int end_sector;
if (CT(COMMAND) == FD_WRITE) {
COMMAND &= ~0x80; /* switch off multiple track mode */
@@ -2610,7 +2612,10 @@ static void virtualdmabug_workaround(void)
static int make_raw_rw_request(void)
{
int aligned_sector_t;
- int max_sector, max_size, tracksize, ssize;
+ int max_sector;
+ int max_size;
+ int tracksize;
+ int ssize;
if (max_buffer_sectors == 0) {
printk("VFS: Block I/O scheduled on unopened device\n");
@@ -2762,9 +2767,7 @@ static int make_raw_rw_request(void)
*/
if (!direct ||
(indirect * 2 > direct * 3 &&
- *errors < DP->max_errors.read_track &&
- /*!TESTF(FD_NEED_TWADDLE) && */
- ((!probing
+ *errors < DP->max_errors.read_track && ((!probing
|| (DP->read_track & (1 << DRS->probed_format)))))) {
max_size = current_req->nr_sectors;
} else {
@@ -2777,10 +2780,6 @@ static int make_raw_rw_request(void)
indirect, direct, fsector_t);
return 0;
}
-/* check_dma_crossing(raw_cmd->kernel_data,
- raw_cmd->length,
- "end of make_raw_request [1]");*/
-
virtualdmabug_workaround();
return 2;
}
@@ -2830,8 +2829,6 @@ static int make_raw_rw_request(void)
raw_cmd->length = ((raw_cmd->length - 1) | (ssize - 1)) + 1;
raw_cmd->length <<= 9;
#ifdef FLOPPY_SANITY_CHECK
- /*check_dma_crossing(raw_cmd->kernel_data, raw_cmd->length,
- "end of make_raw_request"); */
if ((raw_cmd->length < current_count_sectors << 9) ||
(raw_cmd->kernel_data != current_req->buffer &&
CT(COMMAND) == FD_WRITE &&
@@ -3011,6 +3008,7 @@ static struct cont_t poll_cont = {
static int poll_drive(int interruptible, int flag)
{
int ret;
+
/* no auto-sense, just clear dcl */
raw_cmd = &default_raw_cmd;
raw_cmd->flags = flag;
@@ -3173,7 +3171,8 @@ static inline int raw_cmd_copyout(int cmd, char __user *param,
static void raw_cmd_free(struct floppy_raw_cmd **ptr)
{
- struct floppy_raw_cmd *next, *this;
+ struct floppy_raw_cmd *next;
+ struct floppy_raw_cmd *this;
this = *ptr;
*ptr = NULL;
@@ -3245,8 +3244,10 @@ static inline int raw_cmd_copyin(int cmd, char __user *param,
static int raw_cmd_ioctl(int cmd, void __user *param)
{
- int drive, ret, ret2;
struct floppy_raw_cmd *my_raw_cmd;
+ int drive;
+ int ret2;
+ int ret;
if (FDCS->rawcmd <= 1)
FDCS->rawcmd = 1;
@@ -3453,7 +3454,8 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
#define IN(c,x,tag) case c: *(x) = inparam. tag ; return 0
int drive = (long)inode->i_bdev->bd_disk->private_data;
- int i, type = ITYPE(UDRS->fd_device);
+ int type = ITYPE(UDRS->fd_device);
+ int i;
int ret;
int size;
union inparam {
@@ -3619,8 +3621,7 @@ static void __init config_types(void)
if (!UDP->cmos && FLOPPY1_TYPE)
UDP->cmos = FLOPPY1_TYPE;
- /* XXX */
- /* additional physical CMOS drive detection should go here */
+ /* FIXME: additional physical CMOS drive detection should go here */
for (drive = 0; drive < N_DRIVE; drive++) {
unsigned int type = UDP->cmos;
@@ -3903,13 +3904,13 @@ static int floppy_revalidate(struct gendisk *disk)
}
static struct block_device_operations floppy_fops = {
- .owner = THIS_MODULE,
- .open = floppy_open,
- .release = floppy_release,
- .ioctl = fd_ioctl,
- .getgeo = fd_getgeo,
- .media_changed = check_floppy_change,
- .revalidate_disk = floppy_revalidate,
+ .owner = THIS_MODULE,
+ .open = floppy_open,
+ .release = floppy_release,
+ .ioctl = fd_ioctl,
+ .getgeo = fd_getgeo,
+ .media_changed = check_floppy_change,
+ .revalidate_disk = floppy_revalidate,
};
/*
@@ -4388,11 +4389,15 @@ static int floppy_grab_irq_and_dma(void)
if (fd_request_dma()) {
DPRINT("Unable to grab DMA%d for the floppy driver\n",
FLOPPY_DMA);
- fd_free_irq();
- spin_lock_irqsave(&floppy_usage_lock, flags);
- usage_count--;
- spin_unlock_irqrestore(&floppy_usage_lock, flags);
- return -1;
+ if (can_use_virtual_dma & 2)
+ use_virtual_dma = can_use_virtual_dma = 1;
+ if (!(can_use_virtual_dma & 1)) {
+ fd_free_irq();
+ spin_lock_irqsave(&floppy_usage_lock, flags);
+ usage_count--;
+ spin_unlock_irqrestore(&floppy_usage_lock, flags);
+ return -1;
+ }
}
for (fdc = 0; fdc < N_FDC; fdc++) {
@@ -4424,8 +4429,8 @@ static int floppy_grab_irq_and_dma(void)
if (FDCS->address != -1)
fd_outb(FDCS->dor, FD_DOR);
/*
- * The driver will try and free resources and relies on us
- * to know if they were allocated or not.
+ * The driver will try and free resources and relies on us
+ * to know if they were allocated or not.
*/
fdc = 0;
irqdma_allocated = 1;
diff --git a/drivers/block/lguest_blk.c b/drivers/block/lguest_blk.c
deleted file mode 100644
index fa8e42341b87..000000000000
--- a/drivers/block/lguest_blk.c
+++ /dev/null
@@ -1,421 +0,0 @@
-/*D:400
- * The Guest block driver
- *
- * This is a simple block driver, which appears as /dev/lgba, lgbb, lgbc etc.
- * The mechanism is simple: we place the information about the request in the
- * device page, then use SEND_DMA (containing the data for a write, or an empty
- * "ping" DMA for a read).
- :*/
-/* Copyright 2006 Rusty Russell <rusty@rustcorp.com.au> IBM Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-//#define DEBUG
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/blkdev.h>
-#include <linux/interrupt.h>
-#include <linux/lguest_bus.h>
-
-static char next_block_index = 'a';
-
-/*D:420 Here is the structure which holds all the information we need about
- * each Guest block device.
- *
- * I'm sure at this stage, you're wondering "hey, where was the adventure I was
- * promised?" and thinking "Rusty sucks, I shall say nasty things about him on
- * my blog". I think Real adventures have boring bits, too, and you're in the
- * middle of one. But it gets better. Just not quite yet. */
-struct blockdev
-{
- /* The block queue infrastructure wants a spinlock: it is held while it
- * calls our block request function. We grab it in our interrupt
- * handler so the responses don't mess with new requests. */
- spinlock_t lock;
-
- /* The disk structure registered with kernel. */
- struct gendisk *disk;
-
- /* The major device number for this disk, and the interrupt. We only
- * really keep them here for completeness; we'd need them if we
- * supported device unplugging. */
- int major;
- int irq;
-
- /* The physical address of this device's memory page */
- unsigned long phys_addr;
- /* The mapped memory page for convenient acces. */
- struct lguest_block_page *lb_page;
-
- /* We only have a single request outstanding at a time: this is it. */
- struct lguest_dma dma;
- struct request *req;
-};
-
-/*D:495 We originally used end_request() throughout the driver, but it turns
- * out that end_request() is deprecated, and doesn't actually end the request
- * (which seems like a good reason to deprecate it!). It simply ends the first
- * bio. So if we had 3 bios in a "struct request" we would do all 3,
- * end_request(), do 2, end_request(), do 1 and end_request(): twice as much
- * work as we needed to do.
- *
- * This reinforced to me that I do not understand the block layer.
- *
- * Nonetheless, Jens Axboe gave me this nice helper to end all chunks of a
- * request. This improved disk speed by 130%. */
-static void end_entire_request(struct request *req, int uptodate)
-{
- if (end_that_request_first(req, uptodate, req->hard_nr_sectors))
- BUG();
- add_disk_randomness(req->rq_disk);
- blkdev_dequeue_request(req);
- end_that_request_last(req, uptodate);
-}
-
-/* I'm told there are only two stories in the world worth telling: love and
- * hate. So there used to be a love scene here like this:
- *
- * Launcher: We could make beautiful I/O together, you and I.
- * Guest: My, that's a big disk!
- *
- * Unfortunately, it was just too raunchy for our otherwise-gentle tale. */
-
-/*D:490 This is the interrupt handler, called when a block read or write has
- * been completed for us. */
-static irqreturn_t lgb_irq(int irq, void *_bd)
-{
- /* We handed our "struct blockdev" as the argument to request_irq(), so
- * it is passed through to us here. This tells us which device we're
- * dealing with in case we have more than one. */
- struct blockdev *bd = _bd;
- unsigned long flags;
-
- /* We weren't doing anything? Strange, but could happen if we shared
- * interrupts (we don't!). */
- if (!bd->req) {
- pr_debug("No work!\n");
- return IRQ_NONE;
- }
-
- /* Not done yet? That's equally strange. */
- if (!bd->lb_page->result) {
- pr_debug("No result!\n");
- return IRQ_NONE;
- }
-
- /* We have to grab the lock before ending the request. */
- spin_lock_irqsave(&bd->lock, flags);
- /* "result" is 1 for success, 2 for failure: end_entire_request() wants
- * to know whether this succeeded or not. */
- end_entire_request(bd->req, bd->lb_page->result == 1);
- /* Clear out request, it's done. */
- bd->req = NULL;
- /* Reset incoming DMA for next time. */
- bd->dma.used_len = 0;
- /* Ready for more reads or writes */
- blk_start_queue(bd->disk->queue);
- spin_unlock_irqrestore(&bd->lock, flags);
-
- /* The interrupt was for us, we dealt with it. */
- return IRQ_HANDLED;
-}
-
-/*D:480 The block layer's "struct request" contains a number of "struct bio"s,
- * each of which contains "struct bio_vec"s, each of which contains a page, an
- * offset and a length.
- *
- * Fortunately there are iterators to help us walk through the "struct
- * request". Even more fortunately, there were plenty of places to steal the
- * code from. We pack the "struct request" into our "struct lguest_dma" and
- * return the total length. */
-static unsigned int req_to_dma(struct request *req, struct lguest_dma *dma)
-{
- unsigned int i = 0, len = 0;
- struct req_iterator iter;
- struct bio_vec *bvec;
-
- rq_for_each_segment(bvec, req, iter) {
- /* We told the block layer not to give us too many. */
- BUG_ON(i == LGUEST_MAX_DMA_SECTIONS);
- /* If we had a zero-length segment, it would look like
- * the end of the data referred to by the "struct
- * lguest_dma", so make sure that doesn't happen. */
- BUG_ON(!bvec->bv_len);
- /* Convert page & offset to a physical address */
- dma->addr[i] = page_to_phys(bvec->bv_page)
- + bvec->bv_offset;
- dma->len[i] = bvec->bv_len;
- len += bvec->bv_len;
- i++;
- }
- /* If the array isn't full, we mark the end with a 0 length */
- if (i < LGUEST_MAX_DMA_SECTIONS)
- dma->len[i] = 0;
- return len;
-}
-
-/* This creates an empty DMA, useful for prodding the Host without sending data
- * (ie. when we want to do a read) */
-static void empty_dma(struct lguest_dma *dma)
-{
- dma->len[0] = 0;
-}
-
-/*D:470 Setting up a request is fairly easy: */
-static void setup_req(struct blockdev *bd,
- int type, struct request *req, struct lguest_dma *dma)
-{
- /* The type is 1 (write) or 0 (read). */
- bd->lb_page->type = type;
- /* The sector on disk where the read or write starts. */
- bd->lb_page->sector = req->sector;
- /* The result is initialized to 0 (unfinished). */
- bd->lb_page->result = 0;
- /* The current request (so we can end it in the interrupt handler). */
- bd->req = req;
- /* The number of bytes: returned as a side-effect of req_to_dma(),
- * which packs the block layer's "struct request" into our "struct
- * lguest_dma" */
- bd->lb_page->bytes = req_to_dma(req, dma);
-}
-
-/*D:450 Write is pretty straightforward: we pack the request into a "struct
- * lguest_dma", then use SEND_DMA to send the request. */
-static void do_write(struct blockdev *bd, struct request *req)
-{
- struct lguest_dma send;
-
- pr_debug("lgb: WRITE sector %li\n", (long)req->sector);
- setup_req(bd, 1, req, &send);
-
- lguest_send_dma(bd->phys_addr, &send);
-}
-
-/* Read is similar to write, except we pack the request into our receive
- * "struct lguest_dma" and send through an empty DMA just to tell the Host that
- * there's a request pending. */
-static void do_read(struct blockdev *bd, struct request *req)
-{
- struct lguest_dma ping;
-
- pr_debug("lgb: READ sector %li\n", (long)req->sector);
- setup_req(bd, 0, req, &bd->dma);
-
- empty_dma(&ping);
- lguest_send_dma(bd->phys_addr, &ping);
-}
-
-/*D:440 This where requests come in: we get handed the request queue and are
- * expected to pull a "struct request" off it until we've finished them or
- * we're waiting for a reply: */
-static void do_lgb_request(struct request_queue *q)
-{
- struct blockdev *bd;
- struct request *req;
-
-again:
- /* This sometimes returns NULL even on the very first time around. I
- * wonder if it's something to do with letting elves handle the request
- * queue... */
- req = elv_next_request(q);
- if (!req)
- return;
-
- /* We attached the struct blockdev to the disk: get it back */
- bd = req->rq_disk->private_data;
- /* Sometimes we get repeated requests after blk_stop_queue(), but we
- * can only handle one at a time. */
- if (bd->req)
- return;
-
- /* We only do reads and writes: no tricky business! */
- if (!blk_fs_request(req)) {
- pr_debug("Got non-command 0x%08x\n", req->cmd_type);
- req->errors++;
- end_entire_request(req, 0);
- goto again;
- }
-
- if (rq_data_dir(req) == WRITE)
- do_write(bd, req);
- else
- do_read(bd, req);
-
- /* We've put out the request, so stop any more coming in until we get
- * an interrupt, which takes us to lgb_irq() to re-enable the queue. */
- blk_stop_queue(q);
-}
-
-/*D:430 This is the "struct block_device_operations" we attach to the disk at
- * the end of lguestblk_probe(). It doesn't seem to want much. */
-static struct block_device_operations lguestblk_fops = {
- .owner = THIS_MODULE,
-};
-
-/*D:425 Setting up a disk device seems to involve a lot of code. I'm not sure
- * quite why. I do know that the IDE code sent two or three of the maintainers
- * insane, perhaps this is the fringe of the same disease?
- *
- * As in the console code, the probe function gets handed the generic
- * lguest_device from lguest_bus.c: */
-static int lguestblk_probe(struct lguest_device *lgdev)
-{
- struct blockdev *bd;
- int err;
- int irqflags = IRQF_SHARED;
-
- /* First we allocate our own "struct blockdev" and initialize the easy
- * fields. */
- bd = kmalloc(sizeof(*bd), GFP_KERNEL);
- if (!bd)
- return -ENOMEM;
-
- spin_lock_init(&bd->lock);
- bd->irq = lgdev_irq(lgdev);
- bd->req = NULL;
- bd->dma.used_len = 0;
- bd->dma.len[0] = 0;
- /* The descriptor in the lguest_devices array provided by the Host
- * gives the Guest the physical page number of the device's page. */
- bd->phys_addr = (lguest_devices[lgdev->index].pfn << PAGE_SHIFT);
-
- /* We use lguest_map() to get a pointer to the device page */
- bd->lb_page = lguest_map(bd->phys_addr, 1);
- if (!bd->lb_page) {
- err = -ENOMEM;
- goto out_free_bd;
- }
-
- /* We need a major device number: 0 means "assign one dynamically". */
- bd->major = register_blkdev(0, "lguestblk");
- if (bd->major < 0) {
- err = bd->major;
- goto out_unmap;
- }
-
- /* This allocates a "struct gendisk" where we pack all the information
- * about the disk which the rest of Linux sees. The argument is the
- * number of minor devices desired: we need one minor for the main
- * disk, and one for each partition. Of course, we can't possibly know
- * how many partitions are on the disk (add_disk does that).
- */
- bd->disk = alloc_disk(16);
- if (!bd->disk) {
- err = -ENOMEM;
- goto out_unregister_blkdev;
- }
-
- /* Every disk needs a queue for requests to come in: we set up the
- * queue with a callback function (the core of our driver) and the lock
- * to use. */
- bd->disk->queue = blk_init_queue(do_lgb_request, &bd->lock);
- if (!bd->disk->queue) {
- err = -ENOMEM;
- goto out_put_disk;
- }
-
- /* We can only handle a certain number of pointers in our SEND_DMA
- * call, so we set that with blk_queue_max_hw_segments(). This is not
- * to be confused with blk_queue_max_phys_segments() of course! I
- * know, who could possibly confuse the two?
- *
- * Well, it's simple to tell them apart: this one seems to work and the
- * other one didn't. */
- blk_queue_max_hw_segments(bd->disk->queue, LGUEST_MAX_DMA_SECTIONS);
-
- /* Due to technical limitations of our Host (and simple coding) we
- * can't have a single buffer which crosses a page boundary. Tell it
- * here. This means that our maximum request size is 16
- * (LGUEST_MAX_DMA_SECTIONS) pages. */
- blk_queue_segment_boundary(bd->disk->queue, PAGE_SIZE-1);
-
- /* We name our disk: this becomes the device name when udev does its
- * magic thing and creates the device node, such as /dev/lgba.
- * next_block_index is a global which starts at 'a'. Unfortunately
- * this simple increment logic means that the 27th disk will be called
- * "/dev/lgb{". In that case, I recommend having at least 29 disks, so
- * your /dev directory will be balanced. */
- sprintf(bd->disk->disk_name, "lgb%c", next_block_index++);
-
- /* We look to the device descriptor again to see if this device's
- * interrupts are expected to be random. If they are, we tell the irq
- * subsystem. At the moment this bit is always set. */
- if (lguest_devices[lgdev->index].features & LGUEST_DEVICE_F_RANDOMNESS)
- irqflags |= IRQF_SAMPLE_RANDOM;
-
- /* Now we have the name and irqflags, we can request the interrupt; we
- * give it the "struct blockdev" we have set up to pass to lgb_irq()
- * when there is an interrupt. */
- err = request_irq(bd->irq, lgb_irq, irqflags, bd->disk->disk_name, bd);
- if (err)
- goto out_cleanup_queue;
-
- /* We bind our one-entry DMA pool to the key for this block device so
- * the Host can reply to our requests. The key is equal to the
- * physical address of the device's page, which is conveniently
- * unique. */
- err = lguest_bind_dma(bd->phys_addr, &bd->dma, 1, bd->irq);
- if (err)
- goto out_free_irq;
-
- /* We finish our disk initialization and add the disk to the system. */
- bd->disk->major = bd->major;
- bd->disk->first_minor = 0;
- bd->disk->private_data = bd;
- bd->disk->fops = &lguestblk_fops;
- /* This is initialized to the disk size by the Launcher. */
- set_capacity(bd->disk, bd->lb_page->num_sectors);
- add_disk(bd->disk);
-
- printk(KERN_INFO "%s: device %i at major %d\n",
- bd->disk->disk_name, lgdev->index, bd->major);
-
- /* We don't need to keep the "struct blockdev" around, but if we ever
- * implemented device removal, we'd need this. */
- lgdev->private = bd;
- return 0;
-
-out_free_irq:
- free_irq(bd->irq, bd);
-out_cleanup_queue:
- blk_cleanup_queue(bd->disk->queue);
-out_put_disk:
- put_disk(bd->disk);
-out_unregister_blkdev:
- unregister_blkdev(bd->major, "lguestblk");
-out_unmap:
- lguest_unmap(bd->lb_page);
-out_free_bd:
- kfree(bd);
- return err;
-}
-
-/*D:410 The boilerplate code for registering the lguest block driver is just
- * like the console: */
-static struct lguest_driver lguestblk_drv = {
- .name = "lguestblk",
- .owner = THIS_MODULE,
- .device_type = LGUEST_DEVICE_T_BLOCK,
- .probe = lguestblk_probe,
-};
-
-static __init int lguestblk_init(void)
-{
- return register_lguest_driver(&lguestblk_drv);
-}
-module_init(lguestblk_init);
-
-MODULE_DESCRIPTION("Lguest block driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index b9233a06934c..56e23042728a 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -29,7 +29,7 @@
*
* Maximum number of loop devices when compiled-in now selectable by passing
* max_loop=<1-255> to the kernel on boot.
- * Erik I. Bolsø, <eriki@himolde.no>, Oct 31, 1999
+ * Erik I. Bolsø, <eriki@himolde.no>, Oct 31, 1999
*
* Completely rewrite request handling to be make_request_fn style and
* non blocking, pushing work to a helper thread. Lots of fixes from
@@ -204,14 +204,13 @@ lo_do_transfer(struct loop_device *lo, int cmd,
* do_lo_send_aops - helper for writing data to a loop device
*
* This is the fast version for backing filesystems which implement the address
- * space operations prepare_write and commit_write.
+ * space operations write_begin and write_end.
*/
static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec,
- int bsize, loff_t pos, struct page *page)
+ int bsize, loff_t pos, struct page *unused)
{
struct file *file = lo->lo_backing_file; /* kudos to NFsckingS */
struct address_space *mapping = file->f_mapping;
- const struct address_space_operations *aops = mapping->a_ops;
pgoff_t index;
unsigned offset, bv_offs;
int len, ret;
@@ -223,63 +222,45 @@ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec,
len = bvec->bv_len;
while (len > 0) {
sector_t IV;
- unsigned size;
+ unsigned size, copied;
int transfer_result;
+ struct page *page;
+ void *fsdata;
IV = ((sector_t)index << (PAGE_CACHE_SHIFT - 9))+(offset >> 9);
size = PAGE_CACHE_SIZE - offset;
if (size > len)
size = len;
- page = grab_cache_page(mapping, index);
- if (unlikely(!page))
+
+ ret = pagecache_write_begin(file, mapping, pos, size, 0,
+ &page, &fsdata);
+ if (ret)
goto fail;
- ret = aops->prepare_write(file, page, offset,
- offset + size);
- if (unlikely(ret)) {
- if (ret == AOP_TRUNCATED_PAGE) {
- page_cache_release(page);
- continue;
- }
- goto unlock;
- }
+
transfer_result = lo_do_transfer(lo, WRITE, page, offset,
bvec->bv_page, bv_offs, size, IV);
- if (unlikely(transfer_result)) {
- /*
- * The transfer failed, but we still write the data to
- * keep prepare/commit calls balanced.
- */
- printk(KERN_ERR "loop: transfer error block %llu\n",
- (unsigned long long)index);
- zero_user_page(page, offset, size, KM_USER0);
- }
- flush_dcache_page(page);
- ret = aops->commit_write(file, page, offset,
- offset + size);
- if (unlikely(ret)) {
- if (ret == AOP_TRUNCATED_PAGE) {
- page_cache_release(page);
- continue;
- }
- goto unlock;
- }
+ copied = size;
if (unlikely(transfer_result))
- goto unlock;
- bv_offs += size;
- len -= size;
+ copied = 0;
+
+ ret = pagecache_write_end(file, mapping, pos, size, copied,
+ page, fsdata);
+ if (ret < 0 || ret != copied)
+ goto fail;
+
+ if (unlikely(transfer_result))
+ goto fail;
+
+ bv_offs += copied;
+ len -= copied;
offset = 0;
index++;
- pos += size;
- unlock_page(page);
- page_cache_release(page);
+ pos += copied;
}
ret = 0;
out:
mutex_unlock(&mapping->host->i_mutex);
return ret;
-unlock:
- unlock_page(page);
- page_cache_release(page);
fail:
ret = -1;
goto out;
@@ -313,7 +294,7 @@ static int __do_lo_send_write(struct file *file,
* do_lo_send_direct_write - helper for writing data to a loop device
*
* This is the fast, non-transforming version for backing filesystems which do
- * not implement the address space operations prepare_write and commit_write.
+ * not implement the address space operations write_begin and write_end.
* It uses the write file operation which should be present on all writeable
* filesystems.
*/
@@ -332,7 +313,7 @@ static int do_lo_send_direct_write(struct loop_device *lo,
* do_lo_send_write - helper for writing data to a loop device
*
* This is the slow, transforming version for filesystems which do not
- * implement the address space operations prepare_write and commit_write. It
+ * implement the address space operations write_begin and write_end. It
* uses the write file operation which should be present on all writeable
* filesystems.
*
@@ -780,7 +761,7 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file,
*/
if (!file->f_op->splice_read)
goto out_putf;
- if (aops->prepare_write && aops->commit_write)
+ if (aops->prepare_write || aops->write_begin)
lo_flags |= LO_FLAGS_USE_AOPS;
if (!(lo_flags & LO_FLAGS_USE_AOPS) && !file->f_op->write)
lo_flags |= LO_FLAGS_READ_ONLY;
@@ -1304,7 +1285,6 @@ static long lo_compat_ioctl(struct file *file, unsigned int cmd, unsigned long a
struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
int err;
- lock_kernel();
switch(cmd) {
case LOOP_SET_STATUS:
mutex_lock(&lo->lo_ctl_mutex);
@@ -1330,7 +1310,6 @@ static long lo_compat_ioctl(struct file *file, unsigned int cmd, unsigned long a
err = -ENOIOCTLCMD;
break;
}
- unlock_kernel();
return err;
}
#endif
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index be5ec3a9b1fc..b4c0888aedc3 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -28,6 +28,7 @@
#include <linux/err.h>
#include <linux/kernel.h>
#include <net/sock.h>
+#include <linux/net.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -113,12 +114,42 @@ static void nbd_end_request(struct request *req)
spin_unlock_irqrestore(q->queue_lock, flags);
}
+static void sock_shutdown(struct nbd_device *lo, int lock)
+{
+ /* Forcibly shutdown the socket causing all listeners
+ * to error
+ *
+ * FIXME: This code is duplicated from sys_shutdown, but
+ * there should be a more generic interface rather than
+ * calling socket ops directly here */
+ if (lock)
+ mutex_lock(&lo->tx_lock);
+ if (lo->sock) {
+ printk(KERN_WARNING "%s: shutting down socket\n",
+ lo->disk->disk_name);
+ kernel_sock_shutdown(lo->sock, SHUT_RDWR);
+ lo->sock = NULL;
+ }
+ if (lock)
+ mutex_unlock(&lo->tx_lock);
+}
+
+static void nbd_xmit_timeout(unsigned long arg)
+{
+ struct task_struct *task = (struct task_struct *)arg;
+
+ printk(KERN_WARNING "nbd: killing hung xmit (%s, pid: %d)\n",
+ task->comm, task->pid);
+ force_sig(SIGKILL, task);
+}
+
/*
* Send or receive packet.
*/
-static int sock_xmit(struct socket *sock, int send, void *buf, int size,
+static int sock_xmit(struct nbd_device *lo, int send, void *buf, int size,
int msg_flags)
{
+ struct socket *sock = lo->sock;
int result;
struct msghdr msg;
struct kvec iov;
@@ -139,17 +170,29 @@ static int sock_xmit(struct socket *sock, int send, void *buf, int size,
msg.msg_controllen = 0;
msg.msg_flags = msg_flags | MSG_NOSIGNAL;
- if (send)
+ if (send) {
+ struct timer_list ti;
+
+ if (lo->xmit_timeout) {
+ init_timer(&ti);
+ ti.function = nbd_xmit_timeout;
+ ti.data = (unsigned long)current;
+ ti.expires = jiffies + lo->xmit_timeout;
+ add_timer(&ti);
+ }
result = kernel_sendmsg(sock, &msg, &iov, 1, size);
- else
+ if (lo->xmit_timeout)
+ del_timer_sync(&ti);
+ } else
result = kernel_recvmsg(sock, &msg, &iov, 1, size, 0);
if (signal_pending(current)) {
siginfo_t info;
printk(KERN_WARNING "nbd (pid %d: %s) got signal %d\n",
- current->pid, current->comm,
+ task_pid_nr(current), current->comm,
dequeue_signal_lock(current, &current->blocked, &info));
result = -EINTR;
+ sock_shutdown(lo, !send);
break;
}
@@ -167,23 +210,22 @@ static int sock_xmit(struct socket *sock, int send, void *buf, int size,
return result;
}
-static inline int sock_send_bvec(struct socket *sock, struct bio_vec *bvec,
+static inline int sock_send_bvec(struct nbd_device *lo, struct bio_vec *bvec,
int flags)
{
int result;
void *kaddr = kmap(bvec->bv_page);
- result = sock_xmit(sock, 1, kaddr + bvec->bv_offset, bvec->bv_len,
- flags);
+ result = sock_xmit(lo, 1, kaddr + bvec->bv_offset, bvec->bv_len, flags);
kunmap(bvec->bv_page);
return result;
}
+/* always call with the tx_lock held */
static int nbd_send_req(struct nbd_device *lo, struct request *req)
{
int result, flags;
struct nbd_request request;
unsigned long size = req->nr_sectors << 9;
- struct socket *sock = lo->sock;
request.magic = htonl(NBD_REQUEST_MAGIC);
request.type = htonl(nbd_cmd(req));
@@ -196,8 +238,8 @@ static int nbd_send_req(struct nbd_device *lo, struct request *req)
nbdcmd_to_ascii(nbd_cmd(req)),
(unsigned long long)req->sector << 9,
req->nr_sectors << 9);
- result = sock_xmit(sock, 1, &request, sizeof(request),
- (nbd_cmd(req) == NBD_CMD_WRITE)? MSG_MORE: 0);
+ result = sock_xmit(lo, 1, &request, sizeof(request),
+ (nbd_cmd(req) == NBD_CMD_WRITE) ? MSG_MORE : 0);
if (result <= 0) {
printk(KERN_ERR "%s: Send control failed (result %d)\n",
lo->disk->disk_name, result);
@@ -217,7 +259,7 @@ static int nbd_send_req(struct nbd_device *lo, struct request *req)
flags = MSG_MORE;
dprintk(DBG_TX, "%s: request %p: sending %d bytes data\n",
lo->disk->disk_name, req, bvec->bv_len);
- result = sock_send_bvec(sock, bvec, flags);
+ result = sock_send_bvec(lo, bvec, flags);
if (result <= 0) {
printk(KERN_ERR "%s: Send data failed (result %d)\n",
lo->disk->disk_name, result);
@@ -231,22 +273,18 @@ error_out:
return 1;
}
-static struct request *nbd_find_request(struct nbd_device *lo, char *handle)
+static struct request *nbd_find_request(struct nbd_device *lo,
+ struct request *xreq)
{
- struct request *req;
- struct list_head *tmp;
- struct request *xreq;
+ struct request *req, *tmp;
int err;
- memcpy(&xreq, handle, sizeof(xreq));
-
err = wait_event_interruptible(lo->active_wq, lo->active_req != xreq);
if (unlikely(err))
goto out;
spin_lock(&lo->queue_lock);
- list_for_each(tmp, &lo->queue_head) {
- req = list_entry(tmp, struct request, queuelist);
+ list_for_each_entry_safe(req, tmp, &lo->queue_head, queuelist) {
if (req != xreq)
continue;
list_del_init(&req->queuelist);
@@ -261,11 +299,11 @@ out:
return ERR_PTR(err);
}
-static inline int sock_recv_bvec(struct socket *sock, struct bio_vec *bvec)
+static inline int sock_recv_bvec(struct nbd_device *lo, struct bio_vec *bvec)
{
int result;
void *kaddr = kmap(bvec->bv_page);
- result = sock_xmit(sock, 0, kaddr + bvec->bv_offset, bvec->bv_len,
+ result = sock_xmit(lo, 0, kaddr + bvec->bv_offset, bvec->bv_len,
MSG_WAITALL);
kunmap(bvec->bv_page);
return result;
@@ -277,10 +315,9 @@ static struct request *nbd_read_stat(struct nbd_device *lo)
int result;
struct nbd_reply reply;
struct request *req;
- struct socket *sock = lo->sock;
reply.magic = 0;
- result = sock_xmit(sock, 0, &reply, sizeof(reply), MSG_WAITALL);
+ result = sock_xmit(lo, 0, &reply, sizeof(reply), MSG_WAITALL);
if (result <= 0) {
printk(KERN_ERR "%s: Receive control failed (result %d)\n",
lo->disk->disk_name, result);
@@ -295,7 +332,7 @@ static struct request *nbd_read_stat(struct nbd_device *lo)
goto harderror;
}
- req = nbd_find_request(lo, reply.handle);
+ req = nbd_find_request(lo, *(struct request **)reply.handle);
if (unlikely(IS_ERR(req))) {
result = PTR_ERR(req);
if (result != -ENOENT)
@@ -321,7 +358,7 @@ static struct request *nbd_read_stat(struct nbd_device *lo)
struct bio_vec *bvec;
rq_for_each_segment(bvec, req, iter) {
- result = sock_recv_bvec(sock, bvec);
+ result = sock_recv_bvec(lo, bvec);
if (result <= 0) {
printk(KERN_ERR "%s: Receive data failed (result %d)\n",
lo->disk->disk_name, result);
@@ -396,6 +433,7 @@ static void nbd_clear_que(struct nbd_device *lo)
}
}
+
/*
* We always wait for result of write, for now. It would be nice to make it optional
* in future
@@ -471,7 +509,6 @@ error_out:
nbd_end_request(req);
spin_lock(q->queue_lock);
}
- return;
}
static int nbd_ioctl(struct inode *inode, struct file *file,
@@ -504,7 +541,9 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
sreq.nr_sectors = 0;
if (!lo->sock)
return -EINVAL;
+ mutex_lock(&lo->tx_lock);
nbd_send_req(lo, &sreq);
+ mutex_unlock(&lo->tx_lock);
return 0;
case NBD_CLEAR_SOCK:
@@ -548,6 +587,9 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
set_blocksize(inode->i_bdev, lo->blksize);
set_capacity(lo->disk, lo->bytesize >> 9);
return 0;
+ case NBD_SET_TIMEOUT:
+ lo->xmit_timeout = arg * HZ;
+ return 0;
case NBD_SET_SIZE_BLOCKS:
lo->bytesize = ((u64) arg) * lo->blksize;
inode->i_bdev->bd_inode->i_size = lo->bytesize;
@@ -560,28 +602,16 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
error = nbd_do_it(lo);
if (error)
return error;
- /* on return tidy up in case we have a signal */
- /* Forcibly shutdown the socket causing all listeners
- * to error
- *
- * FIXME: This code is duplicated from sys_shutdown, but
- * there should be a more generic interface rather than
- * calling socket ops directly here */
- mutex_lock(&lo->tx_lock);
- if (lo->sock) {
- printk(KERN_WARNING "%s: shutting down socket\n",
- lo->disk->disk_name);
- lo->sock->ops->shutdown(lo->sock,
- SEND_SHUTDOWN|RCV_SHUTDOWN);
- lo->sock = NULL;
- }
- mutex_unlock(&lo->tx_lock);
+ sock_shutdown(lo, 1);
file = lo->file;
lo->file = NULL;
nbd_clear_que(lo);
printk(KERN_WARNING "%s: queue cleared\n", lo->disk->disk_name);
if (file)
fput(file);
+ lo->bytesize = 0;
+ inode->i_bdev->bd_inode->i_size = 0;
+ set_capacity(lo->disk, 0);
return lo->harderror;
case NBD_CLEAR_QUE:
/*
@@ -659,14 +689,14 @@ static int __init nbd_init(void)
mutex_init(&nbd_dev[i].tx_lock);
init_waitqueue_head(&nbd_dev[i].active_wq);
nbd_dev[i].blksize = 1024;
- nbd_dev[i].bytesize = 0x7ffffc00ULL << 10; /* 2TB */
+ nbd_dev[i].bytesize = 0;
disk->major = NBD_MAJOR;
disk->first_minor = i;
disk->fops = &nbd_fops;
disk->private_data = &nbd_dev[i];
disk->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO;
sprintf(disk->disk_name, "nbd%d", i);
- set_capacity(disk, 0x7ffffc00ULL << 1); /* 2 TB */
+ set_capacity(disk, 0);
add_disk(disk);
}
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index ceffa6034e20..e7fe6ca97dd8 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -488,13 +488,11 @@ static int pf_atapi(struct pf_unit *pf, char *cmd, int dlen, char *buf, char *fu
return r;
}
-#define DBMSG(msg) ((verbose>1)?(msg):NULL)
-
static void pf_lock(struct pf_unit *pf, int func)
{
char lo_cmd[12] = { ATAPI_LOCK, pf->lun << 5, 0, 0, func, 0, 0, 0, 0, 0, 0, 0 };
- pf_atapi(pf, lo_cmd, 0, pf_scratch, func ? "unlock" : "lock");
+ pf_atapi(pf, lo_cmd, 0, pf_scratch, func ? "lock" : "unlock");
}
static void pf_eject(struct pf_unit *pf)
@@ -555,7 +553,7 @@ static void pf_mode_sense(struct pf_unit *pf)
{ ATAPI_MODE_SENSE, pf->lun << 5, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0 };
char buf[8];
- pf_atapi(pf, ms_cmd, 8, buf, DBMSG("mode sense"));
+ pf_atapi(pf, ms_cmd, 8, buf, "mode sense");
pf->media_status = PF_RW;
if (buf[3] & 0x80)
pf->media_status = PF_RO;
@@ -591,7 +589,7 @@ static void pf_get_capacity(struct pf_unit *pf)
char buf[8];
int bs;
- if (pf_atapi(pf, rc_cmd, 8, buf, DBMSG("get capacity"))) {
+ if (pf_atapi(pf, rc_cmd, 8, buf, "get capacity")) {
pf->media_status = PF_NM;
return;
}
@@ -804,13 +802,18 @@ static int pf_next_buf(void)
pf_buf += 512;
pf_block++;
if (!pf_run)
- return 0;
- if (!pf_count)
return 1;
- spin_lock_irqsave(&pf_spin_lock, saved_flags);
- pf_end_request(1);
- spin_unlock_irqrestore(&pf_spin_lock, saved_flags);
- return 1;
+ if (!pf_count) {
+ spin_lock_irqsave(&pf_spin_lock, saved_flags);
+ pf_end_request(1);
+ pf_req = elv_next_request(pf_queue);
+ spin_unlock_irqrestore(&pf_spin_lock, saved_flags);
+ if (!pf_req)
+ return 1;
+ pf_count = pf_req->current_nr_sectors;
+ pf_buf = pf_req->buffer;
+ }
+ return 0;
}
static inline void next_request(int success)
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index 9f4e67ee1eb0..b91accf12656 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -664,7 +664,7 @@ static int pt_open(struct inode *inode, struct file *file)
goto out;
err = -EROFS;
- if ((!tape->flags & PT_WRITE_OK) && (file->f_mode & 2))
+ if ((!(tape->flags & PT_WRITE_OK)) && (file->f_mode & 2))
goto out;
if (!(iminor(inode) & 128))
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 540bf3676985..a5ee21319d37 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -358,10 +358,19 @@ static ssize_t class_pktcdvd_store_add(struct class *c, const char *buf,
size_t count)
{
unsigned int major, minor;
+
if (sscanf(buf, "%u:%u", &major, &minor) == 2) {
+ /* pkt_setup_dev() expects caller to hold reference to self */
+ if (!try_module_get(THIS_MODULE))
+ return -ENODEV;
+
pkt_setup_dev(MKDEV(major, minor), NULL);
+
+ module_put(THIS_MODULE);
+
return count;
}
+
return -EINVAL;
}
@@ -1133,16 +1142,21 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
* Schedule reads for missing parts of the packet.
*/
for (f = 0; f < pkt->frames; f++) {
+ struct bio_vec *vec;
+
int p, offset;
if (written[f])
continue;
bio = pkt->r_bios[f];
+ vec = bio->bi_io_vec;
bio_init(bio);
bio->bi_max_vecs = 1;
bio->bi_sector = pkt->sector + f * (CD_FRAMESIZE >> 9);
bio->bi_bdev = pd->bdev;
bio->bi_end_io = pkt_end_io_read;
bio->bi_private = pkt;
+ bio->bi_io_vec = vec;
+ bio->bi_destructor = pkt_bio_destructor;
p = (f * CD_FRAMESIZE) / PAGE_SIZE;
offset = (f * CD_FRAMESIZE) % PAGE_SIZE;
@@ -1439,6 +1453,8 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
pkt->w_bio->bi_bdev = pd->bdev;
pkt->w_bio->bi_end_io = pkt_end_io_packet_write;
pkt->w_bio->bi_private = pkt;
+ pkt->w_bio->bi_io_vec = bvec;
+ pkt->w_bio->bi_destructor = pkt_bio_destructor;
for (f = 0; f < pkt->frames; f++)
if (!bio_add_page(pkt->w_bio, bvec[f].bv_page, CD_FRAMESIZE, bvec[f].bv_offset))
BUG();
diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c
index 06d0552cf49c..e354bfc070e1 100644
--- a/drivers/block/ps3disk.c
+++ b/drivers/block/ps3disk.c
@@ -414,26 +414,6 @@ static void ps3disk_prepare_flush(struct request_queue *q, struct request *req)
req->cmd_type = REQ_TYPE_FLUSH;
}
-static int ps3disk_issue_flush(struct request_queue *q, struct gendisk *gendisk,
- sector_t *sector)
-{
- struct ps3_storage_device *dev = q->queuedata;
- struct request *req;
- int res;
-
- dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__);
-
- req = blk_get_request(q, WRITE, __GFP_WAIT);
- ps3disk_prepare_flush(q, req);
- res = blk_execute_rq(q, gendisk, req, 0);
- if (res)
- dev_err(&dev->sbd.core, "%s:%u: flush request failed %d\n",
- __func__, __LINE__, res);
- blk_put_request(req);
- return res;
-}
-
-
static unsigned long ps3disk_mask;
static DEFINE_MUTEX(ps3disk_mask_mutex);
@@ -506,7 +486,6 @@ static int __devinit ps3disk_probe(struct ps3_system_bus_device *_dev)
blk_queue_dma_alignment(queue, dev->blk_size-1);
blk_queue_hardsect_size(queue, dev->blk_size);
- blk_queue_issue_flush_fn(queue, ps3disk_issue_flush);
blk_queue_ordered(queue, QUEUE_ORDERED_DRAIN_FLUSH,
ps3disk_prepare_flush);
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index 701ea77f62e9..82f4eecc8699 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -189,6 +189,18 @@ static int ramdisk_set_page_dirty(struct page *page)
return 0;
}
+/*
+ * releasepage is called by pagevec_strip/try_to_release_page if
+ * buffers_heads_over_limit is true. Without a releasepage function
+ * try_to_free_buffers is called instead. That can unset the dirty
+ * bit of our ram disk pages, which will be eventually freed, even
+ * if the page is still in use.
+ */
+static int ramdisk_releasepage(struct page *page, gfp_t dummy)
+{
+ return 0;
+}
+
static const struct address_space_operations ramdisk_aops = {
.readpage = ramdisk_readpage,
.prepare_write = ramdisk_prepare_write,
@@ -196,6 +208,7 @@ static const struct address_space_operations ramdisk_aops = {
.writepage = ramdisk_writepage,
.set_page_dirty = ramdisk_set_page_dirty,
.writepages = ramdisk_writepages,
+ .releasepage = ramdisk_releasepage,
};
static int rd_blkdev_pagecache_IO(int rw, struct bio_vec *vec, sector_t sector,
@@ -365,7 +378,7 @@ static int rd_open(struct inode *inode, struct file *filp)
/*
* Deep badness. rd_blkdev_pagecache_IO() needs to allocate
* pagecache pages within a request_fn. We cannot recur back
- * into the filesytem which is mounted atop the ramdisk, because
+ * into the filesystem which is mounted atop the ramdisk, because
* that would deadlock on fs locks. And we really don't want
* to reenter rd_blkdev_pagecache_IO when we're already within
* that function.
@@ -411,6 +424,9 @@ static void __exit rd_cleanup(void)
blk_cleanup_queue(rd_queue[i]);
}
unregister_blkdev(RAMDISK_MAJOR, "ramdisk");
+
+ bdi_destroy(&rd_file_backing_dev_info);
+ bdi_destroy(&rd_backing_dev_info);
}
/*
@@ -419,7 +435,19 @@ static void __exit rd_cleanup(void)
static int __init rd_init(void)
{
int i;
- int err = -ENOMEM;
+ int err;
+
+ err = bdi_init(&rd_backing_dev_info);
+ if (err)
+ goto out2;
+
+ err = bdi_init(&rd_file_backing_dev_info);
+ if (err) {
+ bdi_destroy(&rd_backing_dev_info);
+ goto out2;
+ }
+
+ err = -ENOMEM;
if (rd_blocksize > PAGE_SIZE || rd_blocksize < 512 ||
(rd_blocksize & (rd_blocksize-1))) {
@@ -473,6 +501,9 @@ out:
put_disk(rd_disks[i]);
blk_cleanup_queue(rd_queue[i]);
}
+ bdi_destroy(&rd_backing_dev_info);
+ bdi_destroy(&rd_file_backing_dev_info);
+out2:
return err;
}
@@ -486,17 +517,12 @@ static int __init ramdisk_size(char *str)
rd_size = simple_strtol(str,NULL,0);
return 1;
}
-static int __init ramdisk_size2(char *str) /* kludge */
-{
- return ramdisk_size(str);
-}
static int __init ramdisk_blocksize(char *str)
{
rd_blocksize = simple_strtol(str,NULL,0);
return 1;
}
-__setup("ramdisk=", ramdisk_size);
-__setup("ramdisk_size=", ramdisk_size2);
+__setup("ramdisk_size=", ramdisk_size);
__setup("ramdisk_blocksize=", ramdisk_blocksize);
#endif
diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c
index 317a790c153b..fac4c6cd04f7 100644
--- a/drivers/block/sunvdc.c
+++ b/drivers/block/sunvdc.c
@@ -15,6 +15,7 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/list.h>
+#include <linux/scatterlist.h>
#include <asm/vio.h>
#include <asm/ldc.h>
@@ -388,6 +389,7 @@ static int __send_request(struct request *req)
op = VD_OP_BWRITE;
}
+ sg_init_table(sg, port->ring_cookies);
nsg = blk_rq_map_sg(req->q, req, sg);
len = 0;
diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c
index 402209fec59a..52dc5e131718 100644
--- a/drivers/block/sx8.c
+++ b/drivers/block/sx8.c
@@ -27,6 +27,7 @@
#include <linux/hdreg.h>
#include <linux/dma-mapping.h>
#include <linux/completion.h>
+#include <linux/scatterlist.h>
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -522,6 +523,7 @@ static struct carm_request *carm_get_request(struct carm_host *host)
host->n_msgs++;
assert(host->n_msgs <= CARM_MAX_REQ);
+ sg_init_table(crq->sg, CARM_MAX_REQ_SG);
return crq;
}
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index c57dd2b3a0c8..08e909dc7944 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -25,6 +25,7 @@
#include <linux/usb_usual.h>
#include <linux/blkdev.h>
#include <linux/timer.h>
+#include <linux/scatterlist.h>
#include <scsi/scsi.h>
#define DRV_NAME "ub"
@@ -656,6 +657,7 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq)
if ((cmd = ub_get_cmd(lun)) == NULL)
return -1;
memset(cmd, 0, sizeof(struct ub_scsi_cmd));
+ sg_init_table(cmd->sgv, UB_MAX_REQ_SG);
blkdev_dequeue_request(rq);
@@ -1309,9 +1311,8 @@ static void ub_data_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
else
pipe = sc->send_bulk_pipe;
sc->last_pipe = pipe;
- usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe,
- page_address(sg->page) + sg->offset, sg->length,
- ub_urb_complete, sc);
+ usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe, sg_virt(sg),
+ sg->length, ub_urb_complete, sc);
sc->work_urb.actual_length = 0;
sc->work_urb.error_count = 0;
sc->work_urb.status = 0;
@@ -1427,9 +1428,9 @@ static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
scmd->state = UB_CMDST_INIT;
scmd->nsg = 1;
sg = &scmd->sgv[0];
- sg->page = virt_to_page(sc->top_sense);
- sg->offset = (unsigned long)sc->top_sense & (PAGE_SIZE-1);
- sg->length = UB_SENSE_SIZE;
+ sg_init_table(sg, UB_MAX_REQ_SG);
+ sg_set_page(sg, virt_to_page(sc->top_sense), UB_SENSE_SIZE,
+ (unsigned long)sc->top_sense & (PAGE_SIZE-1));
scmd->len = UB_SENSE_SIZE;
scmd->lun = cmd->lun;
scmd->done = ub_top_sense_done;
@@ -1863,9 +1864,8 @@ static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun,
cmd->state = UB_CMDST_INIT;
cmd->nsg = 1;
sg = &cmd->sgv[0];
- sg->page = virt_to_page(p);
- sg->offset = (unsigned long)p & (PAGE_SIZE-1);
- sg->length = 8;
+ sg_init_table(sg, UB_MAX_REQ_SG);
+ sg_set_page(sg, virt_to_page(p), 8, (unsigned long)p & (PAGE_SIZE-1));
cmd->len = 8;
cmd->lun = lun;
cmd->done = ub_probe_done;
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c
index e824b672e05a..ab5d404faa11 100644
--- a/drivers/block/viodasd.c
+++ b/drivers/block/viodasd.c
@@ -41,6 +41,7 @@
#include <linux/dma-mapping.h>
#include <linux/completion.h>
#include <linux/device.h>
+#include <linux/scatterlist.h>
#include <asm/uaccess.h>
#include <asm/vio.h>
@@ -270,6 +271,7 @@ static int send_request(struct request *req)
d = req->rq_disk->private_data;
/* Now build the scatter-gather list */
+ sg_init_table(sg, VIOMAXBLOCKDMA);
nsg = blk_rq_map_sg(req->q, req, sg);
nsg = dma_map_sg(d->dev, sg, nsg, direction);
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
new file mode 100644
index 000000000000..3cf7129d83e6
--- /dev/null
+++ b/drivers/block/virtio_blk.c
@@ -0,0 +1,310 @@
+//#define DEBUG
+#include <linux/spinlock.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/virtio.h>
+#include <linux/virtio_blk.h>
+#include <linux/scatterlist.h>
+
+#define VIRTIO_MAX_SG (3+MAX_PHYS_SEGMENTS)
+
+static unsigned char virtblk_index = 'a';
+struct virtio_blk
+{
+ spinlock_t lock;
+
+ struct virtio_device *vdev;
+ struct virtqueue *vq;
+
+ /* The disk structure for the kernel. */
+ struct gendisk *disk;
+
+ /* Request tracking. */
+ struct list_head reqs;
+
+ mempool_t *pool;
+
+ /* Scatterlist: can be too big for stack. */
+ struct scatterlist sg[VIRTIO_MAX_SG];
+};
+
+struct virtblk_req
+{
+ struct list_head list;
+ struct request *req;
+ struct virtio_blk_outhdr out_hdr;
+ struct virtio_blk_inhdr in_hdr;
+};
+
+static bool blk_done(struct virtqueue *vq)
+{
+ struct virtio_blk *vblk = vq->vdev->priv;
+ struct virtblk_req *vbr;
+ unsigned int len;
+ unsigned long flags;
+
+ spin_lock_irqsave(&vblk->lock, flags);
+ while ((vbr = vblk->vq->vq_ops->get_buf(vblk->vq, &len)) != NULL) {
+ int uptodate;
+ switch (vbr->in_hdr.status) {
+ case VIRTIO_BLK_S_OK:
+ uptodate = 1;
+ break;
+ case VIRTIO_BLK_S_UNSUPP:
+ uptodate = -ENOTTY;
+ break;
+ default:
+ uptodate = 0;
+ break;
+ }
+
+ end_dequeued_request(vbr->req, uptodate);
+ list_del(&vbr->list);
+ mempool_free(vbr, vblk->pool);
+ }
+ /* In case queue is stopped waiting for more buffers. */
+ blk_start_queue(vblk->disk->queue);
+ spin_unlock_irqrestore(&vblk->lock, flags);
+ return true;
+}
+
+static bool do_req(struct request_queue *q, struct virtio_blk *vblk,
+ struct request *req)
+{
+ unsigned long num, out, in;
+ struct virtblk_req *vbr;
+
+ vbr = mempool_alloc(vblk->pool, GFP_ATOMIC);
+ if (!vbr)
+ /* When another request finishes we'll try again. */
+ return false;
+
+ vbr->req = req;
+ if (blk_fs_request(vbr->req)) {
+ vbr->out_hdr.type = 0;
+ vbr->out_hdr.sector = vbr->req->sector;
+ vbr->out_hdr.ioprio = vbr->req->ioprio;
+ } else if (blk_pc_request(vbr->req)) {
+ vbr->out_hdr.type = VIRTIO_BLK_T_SCSI_CMD;
+ vbr->out_hdr.sector = 0;
+ vbr->out_hdr.ioprio = vbr->req->ioprio;
+ } else {
+ /* We don't put anything else in the queue. */
+ BUG();
+ }
+
+ if (blk_barrier_rq(vbr->req))
+ vbr->out_hdr.type |= VIRTIO_BLK_T_BARRIER;
+
+ /* This init could be done at vblk creation time */
+ sg_init_table(vblk->sg, VIRTIO_MAX_SG);
+ sg_set_buf(&vblk->sg[0], &vbr->out_hdr, sizeof(vbr->out_hdr));
+ num = blk_rq_map_sg(q, vbr->req, vblk->sg+1);
+ sg_set_buf(&vblk->sg[num+1], &vbr->in_hdr, sizeof(vbr->in_hdr));
+
+ if (rq_data_dir(vbr->req) == WRITE) {
+ vbr->out_hdr.type |= VIRTIO_BLK_T_OUT;
+ out = 1 + num;
+ in = 1;
+ } else {
+ vbr->out_hdr.type |= VIRTIO_BLK_T_IN;
+ out = 1;
+ in = 1 + num;
+ }
+
+ if (vblk->vq->vq_ops->add_buf(vblk->vq, vblk->sg, out, in, vbr)) {
+ mempool_free(vbr, vblk->pool);
+ return false;
+ }
+
+ list_add_tail(&vbr->list, &vblk->reqs);
+ return true;
+}
+
+static void do_virtblk_request(struct request_queue *q)
+{
+ struct virtio_blk *vblk = NULL;
+ struct request *req;
+ unsigned int issued = 0;
+
+ while ((req = elv_next_request(q)) != NULL) {
+ vblk = req->rq_disk->private_data;
+ BUG_ON(req->nr_phys_segments > ARRAY_SIZE(vblk->sg));
+
+ /* If this request fails, stop queue and wait for something to
+ finish to restart it. */
+ if (!do_req(q, vblk, req)) {
+ blk_stop_queue(q);
+ break;
+ }
+ blkdev_dequeue_request(req);
+ issued++;
+ }
+
+ if (issued)
+ vblk->vq->vq_ops->kick(vblk->vq);
+}
+
+static int virtblk_ioctl(struct inode *inode, struct file *filp,
+ unsigned cmd, unsigned long data)
+{
+ return scsi_cmd_ioctl(filp, inode->i_bdev->bd_disk->queue,
+ inode->i_bdev->bd_disk, cmd,
+ (void __user *)data);
+}
+
+static struct block_device_operations virtblk_fops = {
+ .ioctl = virtblk_ioctl,
+ .owner = THIS_MODULE,
+};
+
+static int virtblk_probe(struct virtio_device *vdev)
+{
+ struct virtio_blk *vblk;
+ int err, major;
+ void *token;
+ unsigned int len;
+ u64 cap;
+ u32 v;
+
+ vdev->priv = vblk = kmalloc(sizeof(*vblk), GFP_KERNEL);
+ if (!vblk) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ INIT_LIST_HEAD(&vblk->reqs);
+ spin_lock_init(&vblk->lock);
+ vblk->vdev = vdev;
+
+ /* We expect one virtqueue, for output. */
+ vblk->vq = vdev->config->find_vq(vdev, blk_done);
+ if (IS_ERR(vblk->vq)) {
+ err = PTR_ERR(vblk->vq);
+ goto out_free_vblk;
+ }
+
+ vblk->pool = mempool_create_kmalloc_pool(1,sizeof(struct virtblk_req));
+ if (!vblk->pool) {
+ err = -ENOMEM;
+ goto out_free_vq;
+ }
+
+ major = register_blkdev(0, "virtblk");
+ if (major < 0) {
+ err = major;
+ goto out_mempool;
+ }
+
+ /* FIXME: How many partitions? How long is a piece of string? */
+ vblk->disk = alloc_disk(1 << 4);
+ if (!vblk->disk) {
+ err = -ENOMEM;
+ goto out_unregister_blkdev;
+ }
+
+ vblk->disk->queue = blk_init_queue(do_virtblk_request, &vblk->lock);
+ if (!vblk->disk->queue) {
+ err = -ENOMEM;
+ goto out_put_disk;
+ }
+
+ sprintf(vblk->disk->disk_name, "vd%c", virtblk_index++);
+ vblk->disk->major = major;
+ vblk->disk->first_minor = 0;
+ vblk->disk->private_data = vblk;
+ vblk->disk->fops = &virtblk_fops;
+
+ /* If barriers are supported, tell block layer that queue is ordered */
+ token = vdev->config->find(vdev, VIRTIO_CONFIG_BLK_F, &len);
+ if (virtio_use_bit(vdev, token, len, VIRTIO_BLK_F_BARRIER))
+ blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL);
+
+ err = virtio_config_val(vdev, VIRTIO_CONFIG_BLK_F_CAPACITY, &cap);
+ if (err) {
+ dev_err(&vdev->dev, "Bad/missing capacity in config\n");
+ goto out_put_disk;
+ }
+
+ /* If capacity is too big, truncate with warning. */
+ if ((sector_t)cap != cap) {
+ dev_warn(&vdev->dev, "Capacity %llu too large: truncating\n",
+ (unsigned long long)cap);
+ cap = (sector_t)-1;
+ }
+ set_capacity(vblk->disk, cap);
+
+ err = virtio_config_val(vdev, VIRTIO_CONFIG_BLK_F_SIZE_MAX, &v);
+ if (!err)
+ blk_queue_max_segment_size(vblk->disk->queue, v);
+ else if (err != -ENOENT) {
+ dev_err(&vdev->dev, "Bad SIZE_MAX in config\n");
+ goto out_put_disk;
+ }
+
+ err = virtio_config_val(vdev, VIRTIO_CONFIG_BLK_F_SEG_MAX, &v);
+ if (!err)
+ blk_queue_max_hw_segments(vblk->disk->queue, v);
+ else if (err != -ENOENT) {
+ dev_err(&vdev->dev, "Bad SEG_MAX in config\n");
+ goto out_put_disk;
+ }
+
+ add_disk(vblk->disk);
+ return 0;
+
+out_put_disk:
+ put_disk(vblk->disk);
+out_unregister_blkdev:
+ unregister_blkdev(major, "virtblk");
+out_mempool:
+ mempool_destroy(vblk->pool);
+out_free_vq:
+ vdev->config->del_vq(vblk->vq);
+out_free_vblk:
+ kfree(vblk);
+out:
+ return err;
+}
+
+static void virtblk_remove(struct virtio_device *vdev)
+{
+ struct virtio_blk *vblk = vdev->priv;
+ int major = vblk->disk->major;
+
+ BUG_ON(!list_empty(&vblk->reqs));
+ blk_cleanup_queue(vblk->disk->queue);
+ put_disk(vblk->disk);
+ unregister_blkdev(major, "virtblk");
+ mempool_destroy(vblk->pool);
+ kfree(vblk);
+}
+
+static struct virtio_device_id id_table[] = {
+ { VIRTIO_ID_BLOCK, VIRTIO_DEV_ANY_ID },
+ { 0 },
+};
+
+static struct virtio_driver virtio_blk = {
+ .driver.name = KBUILD_MODNAME,
+ .driver.owner = THIS_MODULE,
+ .id_table = id_table,
+ .probe = virtblk_probe,
+ .remove = __devexit_p(virtblk_remove),
+};
+
+static int __init init(void)
+{
+ return register_virtio_driver(&virtio_blk);
+}
+
+static void __exit fini(void)
+{
+ unregister_virtio_driver(&virtio_blk);
+}
+module_init(init);
+module_exit(fini);
+
+MODULE_DEVICE_TABLE(virtio, id_table);
+MODULE_DESCRIPTION("Virtio block driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c
index 9e7652dcde6c..82effce97c51 100644
--- a/drivers/block/xsysace.c
+++ b/drivers/block/xsysace.c
@@ -390,8 +390,8 @@ static inline void ace_dump_mem(void *base, int len)
static void ace_dump_regs(struct ace_device *ace)
{
dev_info(ace->dev, " ctrl: %.8x seccnt/cmd: %.4x ver:%.4x\n"
- " status:%.8x mpu_lba:%.8x busmode:%4x\n"
- " error: %.8x cfg_lba:%.8x fatstat:%.4x\n",
+ KERN_INFO " status:%.8x mpu_lba:%.8x busmode:%4x\n"
+ KERN_INFO " error: %.8x cfg_lba:%.8x fatstat:%.4x\n",
ace_in32(ace, ACE_CTRL),
ace_in(ace, ACE_SECCNTCMD),
ace_in(ace, ACE_VERSION),
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index b9fbe6e7f9ae..075598e1c502 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -22,6 +22,30 @@ config BT_HCIUSB_SCO
Say Y here to compile support for SCO over HCI USB.
+config BT_HCIBTUSB
+ tristate "HCI USB driver (alternate version)"
+ depends on USB && EXPERIMENTAL && BT_HCIUSB=n
+ help
+ Bluetooth HCI USB driver.
+ This driver is required if you want to use Bluetooth devices with
+ USB interface.
+
+ This driver is still experimental and has no SCO support.
+
+ Say Y here to compile support for Bluetooth USB devices into the
+ kernel or say M to compile it as module (btusb).
+
+config BT_HCIBTSDIO
+ tristate "HCI SDIO driver"
+ depends on MMC
+ help
+ Bluetooth HCI SDIO driver.
+ This driver is required if you want to use Bluetooth device with
+ SDIO interface.
+
+ Say Y here to compile support for Bluetooth SDIO devices into the
+ kernel or say M to compile it as module (btsdio).
+
config BT_HCIUART
tristate "HCI UART driver"
help
@@ -55,6 +79,17 @@ config BT_HCIUART_BCSP
Say Y here to compile support for HCI BCSP protocol.
+config BT_HCIUART_LL
+ bool "HCILL protocol support"
+ depends on BT_HCIUART
+ help
+ HCILL (HCI Low Level) is a serial protocol for communication
+ between Bluetooth device and host. This protocol is required for
+ serial Bluetooth devices that are based on Texas Instruments'
+ BRF chips.
+
+ Say Y here to compile support for HCILL protocol.
+
config BT_HCIBCM203X
tristate "HCI BCM203x USB driver"
depends on USB
diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile
index 08c10e178e02..77444afbf107 100644
--- a/drivers/bluetooth/Makefile
+++ b/drivers/bluetooth/Makefile
@@ -13,7 +13,11 @@ obj-$(CONFIG_BT_HCIBT3C) += bt3c_cs.o
obj-$(CONFIG_BT_HCIBLUECARD) += bluecard_cs.o
obj-$(CONFIG_BT_HCIBTUART) += btuart_cs.o
+obj-$(CONFIG_BT_HCIBTUSB) += btusb.o
+obj-$(CONFIG_BT_HCIBTSDIO) += btsdio.o
+
hci_uart-y := hci_ldisc.o
hci_uart-$(CONFIG_BT_HCIUART_H4) += hci_h4.o
hci_uart-$(CONFIG_BT_HCIUART_BCSP) += hci_bcsp.o
+hci_uart-$(CONFIG_BT_HCIUART_LL) += hci_ll.o
hci_uart-objs := $(hci_uart-y)
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c
index 851de4d5b7de..bcf57927b7a8 100644
--- a/drivers/bluetooth/bluecard_cs.c
+++ b/drivers/bluetooth/bluecard_cs.c
@@ -503,10 +503,7 @@ static irqreturn_t bluecard_interrupt(int irq, void *dev_inst)
unsigned int iobase;
unsigned char reg;
- if (!info || !info->hdev) {
- BT_ERR("Call of irq %d for unknown device", irq);
- return IRQ_NONE;
- }
+ BUG_ON(!info->hdev);
if (!test_bit(CARD_READY, &(info->hw_state)))
return IRQ_HANDLED;
diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c
index e8ebd5d3de86..1375b5345a0a 100644
--- a/drivers/bluetooth/bpa10x.c
+++ b/drivers/bluetooth/bpa10x.c
@@ -2,7 +2,7 @@
*
* Digianswer Bluetooth USB driver
*
- * Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.org>
+ * Copyright (C) 2004-2007 Marcel Holtmann <marcel@holtmann.org>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -21,13 +21,14 @@
*
*/
-#include <linux/module.h>
-
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/types.h>
+#include <linux/sched.h>
#include <linux/errno.h>
+#include <linux/skbuff.h>
#include <linux/usb.h>
@@ -39,7 +40,7 @@
#define BT_DBG(D...)
#endif
-#define VERSION "0.8"
+#define VERSION "0.9"
static int ignore = 0;
@@ -52,393 +53,285 @@ static struct usb_device_id bpa10x_table[] = {
MODULE_DEVICE_TABLE(usb, bpa10x_table);
-#define BPA10X_CMD_EP 0x00
-#define BPA10X_EVT_EP 0x81
-#define BPA10X_TX_EP 0x02
-#define BPA10X_RX_EP 0x82
-
-#define BPA10X_CMD_BUF_SIZE 252
-#define BPA10X_EVT_BUF_SIZE 16
-#define BPA10X_TX_BUF_SIZE 384
-#define BPA10X_RX_BUF_SIZE 384
-
struct bpa10x_data {
- struct hci_dev *hdev;
- struct usb_device *udev;
+ struct hci_dev *hdev;
+ struct usb_device *udev;
- rwlock_t lock;
+ struct usb_anchor tx_anchor;
+ struct usb_anchor rx_anchor;
- struct sk_buff_head cmd_queue;
- struct urb *cmd_urb;
- struct urb *evt_urb;
- struct sk_buff *evt_skb;
- unsigned int evt_len;
-
- struct sk_buff_head tx_queue;
- struct urb *tx_urb;
- struct urb *rx_urb;
+ struct sk_buff *rx_skb[2];
};
-#define HCI_VENDOR_HDR_SIZE 5
+#define HCI_VENDOR_HDR_SIZE 5
struct hci_vendor_hdr {
- __u8 type;
- __le16 snum;
- __le16 dlen;
+ __u8 type;
+ __le16 snum;
+ __le16 dlen;
} __attribute__ ((packed));
-static void bpa10x_recv_bulk(struct bpa10x_data *data, unsigned char *buf, int count)
+static int bpa10x_recv(struct hci_dev *hdev, int queue, void *buf, int count)
{
- struct hci_acl_hdr *ah;
- struct hci_sco_hdr *sh;
- struct hci_vendor_hdr *vh;
- struct sk_buff *skb;
- int len;
+ struct bpa10x_data *data = hdev->driver_data;
+
+ BT_DBG("%s queue %d buffer %p count %d", hdev->name,
+ queue, buf, count);
+
+ if (queue < 0 || queue > 1)
+ return -EILSEQ;
+
+ hdev->stat.byte_rx += count;
while (count) {
- switch (*buf++) {
- case HCI_ACLDATA_PKT:
- ah = (struct hci_acl_hdr *) buf;
- len = HCI_ACL_HDR_SIZE + __le16_to_cpu(ah->dlen);
- skb = bt_skb_alloc(len, GFP_ATOMIC);
- if (skb) {
- memcpy(skb_put(skb, len), buf, len);
- skb->dev = (void *) data->hdev;
- bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
- hci_recv_frame(skb);
- }
- break;
+ struct sk_buff *skb = data->rx_skb[queue];
+ struct { __u8 type; int expect; } *scb;
+ int type, len = 0;
- case HCI_SCODATA_PKT:
- sh = (struct hci_sco_hdr *) buf;
- len = HCI_SCO_HDR_SIZE + sh->dlen;
- skb = bt_skb_alloc(len, GFP_ATOMIC);
- if (skb) {
- memcpy(skb_put(skb, len), buf, len);
- skb->dev = (void *) data->hdev;
- bt_cb(skb)->pkt_type = HCI_SCODATA_PKT;
- hci_recv_frame(skb);
+ if (!skb) {
+ /* Start of the frame */
+
+ type = *((__u8 *) buf);
+ count--; buf++;
+
+ switch (type) {
+ case HCI_EVENT_PKT:
+ if (count >= HCI_EVENT_HDR_SIZE) {
+ struct hci_event_hdr *h = buf;
+ len = HCI_EVENT_HDR_SIZE + h->plen;
+ } else
+ return -EILSEQ;
+ break;
+
+ case HCI_ACLDATA_PKT:
+ if (count >= HCI_ACL_HDR_SIZE) {
+ struct hci_acl_hdr *h = buf;
+ len = HCI_ACL_HDR_SIZE +
+ __le16_to_cpu(h->dlen);
+ } else
+ return -EILSEQ;
+ break;
+
+ case HCI_SCODATA_PKT:
+ if (count >= HCI_SCO_HDR_SIZE) {
+ struct hci_sco_hdr *h = buf;
+ len = HCI_SCO_HDR_SIZE + h->dlen;
+ } else
+ return -EILSEQ;
+ break;
+
+ case HCI_VENDOR_PKT:
+ if (count >= HCI_VENDOR_HDR_SIZE) {
+ struct hci_vendor_hdr *h = buf;
+ len = HCI_VENDOR_HDR_SIZE +
+ __le16_to_cpu(h->dlen);
+ } else
+ return -EILSEQ;
+ break;
}
- break;
- case HCI_VENDOR_PKT:
- vh = (struct hci_vendor_hdr *) buf;
- len = HCI_VENDOR_HDR_SIZE + __le16_to_cpu(vh->dlen);
skb = bt_skb_alloc(len, GFP_ATOMIC);
- if (skb) {
- memcpy(skb_put(skb, len), buf, len);
- skb->dev = (void *) data->hdev;
- bt_cb(skb)->pkt_type = HCI_VENDOR_PKT;
- hci_recv_frame(skb);
+ if (!skb) {
+ BT_ERR("%s no memory for packet", hdev->name);
+ return -ENOMEM;
}
- break;
-
- default:
- len = count - 1;
- break;
- }
- buf += len;
- count -= (len + 1);
- }
-}
-
-static int bpa10x_recv_event(struct bpa10x_data *data, unsigned char *buf, int size)
-{
- BT_DBG("data %p buf %p size %d", data, buf, size);
+ skb->dev = (void *) hdev;
- if (data->evt_skb) {
- struct sk_buff *skb = data->evt_skb;
+ data->rx_skb[queue] = skb;
- memcpy(skb_put(skb, size), buf, size);
+ scb = (void *) skb->cb;
+ scb->type = type;
+ scb->expect = len;
+ } else {
+ /* Continuation */
- if (skb->len == data->evt_len) {
- data->evt_skb = NULL;
- data->evt_len = 0;
- hci_recv_frame(skb);
- }
- } else {
- struct sk_buff *skb;
- struct hci_event_hdr *hdr;
- unsigned char pkt_type;
- int pkt_len = 0;
-
- if (size < HCI_EVENT_HDR_SIZE + 1) {
- BT_ERR("%s event packet block with size %d is too short",
- data->hdev->name, size);
- return -EILSEQ;
+ scb = (void *) skb->cb;
+ len = scb->expect;
}
- pkt_type = *buf++;
- size--;
-
- if (pkt_type != HCI_EVENT_PKT) {
- BT_ERR("%s unexpected event packet start byte 0x%02x",
- data->hdev->name, pkt_type);
- return -EPROTO;
- }
+ len = min(len, count);
- hdr = (struct hci_event_hdr *) buf;
- pkt_len = HCI_EVENT_HDR_SIZE + hdr->plen;
+ memcpy(skb_put(skb, len), buf, len);
- skb = bt_skb_alloc(pkt_len, GFP_ATOMIC);
- if (!skb) {
- BT_ERR("%s no memory for new event packet",
- data->hdev->name);
- return -ENOMEM;
- }
+ scb->expect -= len;
- skb->dev = (void *) data->hdev;
- bt_cb(skb)->pkt_type = pkt_type;
+ if (scb->expect == 0) {
+ /* Complete frame */
- memcpy(skb_put(skb, size), buf, size);
+ data->rx_skb[queue] = NULL;
- if (pkt_len == size) {
+ bt_cb(skb)->pkt_type = scb->type;
hci_recv_frame(skb);
- } else {
- data->evt_skb = skb;
- data->evt_len = pkt_len;
}
+
+ count -= len; buf += len;
}
return 0;
}
-static void bpa10x_wakeup(struct bpa10x_data *data)
+static void bpa10x_tx_complete(struct urb *urb)
{
- struct urb *urb;
- struct sk_buff *skb;
- int err;
+ struct sk_buff *skb = urb->context;
+ struct hci_dev *hdev = (struct hci_dev *) skb->dev;
- BT_DBG("data %p", data);
+ BT_DBG("%s urb %p status %d count %d", hdev->name,
+ urb, urb->status, urb->actual_length);
- urb = data->cmd_urb;
- if (urb->status == -EINPROGRESS)
- skb = NULL;
+ if (!test_bit(HCI_RUNNING, &hdev->flags))
+ goto done;
+
+ if (!urb->status)
+ hdev->stat.byte_tx += urb->transfer_buffer_length;
else
- skb = skb_dequeue(&data->cmd_queue);
+ hdev->stat.err_tx++;
- if (skb) {
- struct usb_ctrlrequest *cr;
+done:
+ kfree(urb->setup_packet);
- if (skb->len > BPA10X_CMD_BUF_SIZE) {
- BT_ERR("%s command packet with size %d is too big",
- data->hdev->name, skb->len);
- kfree_skb(skb);
- return;
- }
+ kfree_skb(skb);
+}
+
+static void bpa10x_rx_complete(struct urb *urb)
+{
+ struct hci_dev *hdev = urb->context;
+ struct bpa10x_data *data = hdev->driver_data;
+ int err;
- cr = (struct usb_ctrlrequest *) urb->setup_packet;
- cr->wLength = __cpu_to_le16(skb->len);
+ BT_DBG("%s urb %p status %d count %d", hdev->name,
+ urb, urb->status, urb->actual_length);
- skb_copy_from_linear_data(skb, urb->transfer_buffer, skb->len);
- urb->transfer_buffer_length = skb->len;
+ if (!test_bit(HCI_RUNNING, &hdev->flags))
+ return;
- err = usb_submit_urb(urb, GFP_ATOMIC);
- if (err < 0 && err != -ENODEV) {
- BT_ERR("%s submit failed for command urb %p with error %d",
- data->hdev->name, urb, err);
- skb_queue_head(&data->cmd_queue, skb);
- } else
- kfree_skb(skb);
+ if (urb->status == 0) {
+ if (bpa10x_recv(hdev, usb_pipebulk(urb->pipe),
+ urb->transfer_buffer,
+ urb->actual_length) < 0) {
+ BT_ERR("%s corrupted event packet", hdev->name);
+ hdev->stat.err_rx++;
+ }
}
- urb = data->tx_urb;
- if (urb->status == -EINPROGRESS)
- skb = NULL;
- else
- skb = skb_dequeue(&data->tx_queue);
-
- if (skb) {
- skb_copy_from_linear_data(skb, urb->transfer_buffer, skb->len);
- urb->transfer_buffer_length = skb->len;
-
- err = usb_submit_urb(urb, GFP_ATOMIC);
- if (err < 0 && err != -ENODEV) {
- BT_ERR("%s submit failed for command urb %p with error %d",
- data->hdev->name, urb, err);
- skb_queue_head(&data->tx_queue, skb);
- } else
- kfree_skb(skb);
+ usb_anchor_urb(urb, &data->rx_anchor);
+
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err < 0) {
+ BT_ERR("%s urb %p failed to resubmit (%d)",
+ hdev->name, urb, -err);
+ usb_unanchor_urb(urb);
}
}
-static void bpa10x_complete(struct urb *urb)
+static inline int bpa10x_submit_intr_urb(struct hci_dev *hdev)
{
- struct bpa10x_data *data = urb->context;
- unsigned char *buf = urb->transfer_buffer;
- int err, count = urb->actual_length;
+ struct bpa10x_data *data = hdev->driver_data;
+ struct urb *urb;
+ unsigned char *buf;
+ unsigned int pipe;
+ int err, size = 16;
- BT_DBG("data %p urb %p buf %p count %d", data, urb, buf, count);
+ BT_DBG("%s", hdev->name);
- read_lock(&data->lock);
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!urb)
+ return -ENOMEM;
- if (!test_bit(HCI_RUNNING, &data->hdev->flags))
- goto unlock;
+ buf = kmalloc(size, GFP_KERNEL);
+ if (!buf) {
+ usb_free_urb(urb);
+ return -ENOMEM;
+ }
- if (urb->status < 0 || !count)
- goto resubmit;
+ pipe = usb_rcvintpipe(data->udev, 0x81);
- if (usb_pipein(urb->pipe)) {
- data->hdev->stat.byte_rx += count;
+ usb_fill_int_urb(urb, data->udev, pipe, buf, size,
+ bpa10x_rx_complete, hdev, 1);
- if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)
- bpa10x_recv_event(data, buf, count);
+ urb->transfer_flags |= URB_FREE_BUFFER;
- if (usb_pipetype(urb->pipe) == PIPE_BULK)
- bpa10x_recv_bulk(data, buf, count);
- } else {
- data->hdev->stat.byte_tx += count;
+ usb_anchor_urb(urb, &data->rx_anchor);
- bpa10x_wakeup(data);
+ err = usb_submit_urb(urb, GFP_KERNEL);
+ if (err < 0) {
+ BT_ERR("%s urb %p submission failed (%d)",
+ hdev->name, urb, -err);
+ usb_unanchor_urb(urb);
+ kfree(buf);
}
-resubmit:
- if (usb_pipein(urb->pipe)) {
- err = usb_submit_urb(urb, GFP_ATOMIC);
- if (err < 0 && err != -ENODEV) {
- BT_ERR("%s urb %p type %d resubmit status %d",
- data->hdev->name, urb, usb_pipetype(urb->pipe), err);
- }
- }
+ usb_free_urb(urb);
-unlock:
- read_unlock(&data->lock);
+ return err;
}
-static inline struct urb *bpa10x_alloc_urb(struct usb_device *udev, unsigned int pipe,
- size_t size, gfp_t flags, void *data)
+static inline int bpa10x_submit_bulk_urb(struct hci_dev *hdev)
{
+ struct bpa10x_data *data = hdev->driver_data;
struct urb *urb;
- struct usb_ctrlrequest *cr;
unsigned char *buf;
+ unsigned int pipe;
+ int err, size = 64;
- BT_DBG("udev %p data %p", udev, data);
+ BT_DBG("%s", hdev->name);
- urb = usb_alloc_urb(0, flags);
+ urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb)
- return NULL;
+ return -ENOMEM;
- buf = kmalloc(size, flags);
+ buf = kmalloc(size, GFP_KERNEL);
if (!buf) {
usb_free_urb(urb);
- return NULL;
+ return -ENOMEM;
}
- switch (usb_pipetype(pipe)) {
- case PIPE_CONTROL:
- cr = kmalloc(sizeof(*cr), flags);
- if (!cr) {
- kfree(buf);
- usb_free_urb(urb);
- return NULL;
- }
+ pipe = usb_rcvbulkpipe(data->udev, 0x82);
- cr->bRequestType = USB_TYPE_VENDOR;
- cr->bRequest = 0;
- cr->wIndex = 0;
- cr->wValue = 0;
- cr->wLength = __cpu_to_le16(0);
+ usb_fill_bulk_urb(urb, data->udev, pipe,
+ buf, size, bpa10x_rx_complete, hdev);
- usb_fill_control_urb(urb, udev, pipe, (void *) cr, buf, 0, bpa10x_complete, data);
- break;
+ urb->transfer_flags |= URB_FREE_BUFFER;
- case PIPE_INTERRUPT:
- usb_fill_int_urb(urb, udev, pipe, buf, size, bpa10x_complete, data, 1);
- break;
+ usb_anchor_urb(urb, &data->rx_anchor);
- case PIPE_BULK:
- usb_fill_bulk_urb(urb, udev, pipe, buf, size, bpa10x_complete, data);
- break;
-
- default:
+ err = usb_submit_urb(urb, GFP_KERNEL);
+ if (err < 0) {
+ BT_ERR("%s urb %p submission failed (%d)",
+ hdev->name, urb, -err);
+ usb_unanchor_urb(urb);
kfree(buf);
- usb_free_urb(urb);
- return NULL;
}
- return urb;
-}
-
-static inline void bpa10x_free_urb(struct urb *urb)
-{
- BT_DBG("urb %p", urb);
-
- if (!urb)
- return;
-
- kfree(urb->setup_packet);
- kfree(urb->transfer_buffer);
-
usb_free_urb(urb);
+
+ return err;
}
static int bpa10x_open(struct hci_dev *hdev)
{
struct bpa10x_data *data = hdev->driver_data;
- struct usb_device *udev = data->udev;
- unsigned long flags;
int err;
- BT_DBG("hdev %p data %p", hdev, data);
+ BT_DBG("%s", hdev->name);
if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
return 0;
- data->cmd_urb = bpa10x_alloc_urb(udev, usb_sndctrlpipe(udev, BPA10X_CMD_EP),
- BPA10X_CMD_BUF_SIZE, GFP_KERNEL, data);
- if (!data->cmd_urb) {
- err = -ENOMEM;
- goto done;
- }
-
- data->evt_urb = bpa10x_alloc_urb(udev, usb_rcvintpipe(udev, BPA10X_EVT_EP),
- BPA10X_EVT_BUF_SIZE, GFP_KERNEL, data);
- if (!data->evt_urb) {
- bpa10x_free_urb(data->cmd_urb);
- err = -ENOMEM;
- goto done;
- }
-
- data->rx_urb = bpa10x_alloc_urb(udev, usb_rcvbulkpipe(udev, BPA10X_RX_EP),
- BPA10X_RX_BUF_SIZE, GFP_KERNEL, data);
- if (!data->rx_urb) {
- bpa10x_free_urb(data->evt_urb);
- bpa10x_free_urb(data->cmd_urb);
- err = -ENOMEM;
- goto done;
- }
-
- data->tx_urb = bpa10x_alloc_urb(udev, usb_sndbulkpipe(udev, BPA10X_TX_EP),
- BPA10X_TX_BUF_SIZE, GFP_KERNEL, data);
- if (!data->rx_urb) {
- bpa10x_free_urb(data->rx_urb);
- bpa10x_free_urb(data->evt_urb);
- bpa10x_free_urb(data->cmd_urb);
- err = -ENOMEM;
- goto done;
- }
+ err = bpa10x_submit_intr_urb(hdev);
+ if (err < 0)
+ goto error;
- write_lock_irqsave(&data->lock, flags);
+ err = bpa10x_submit_bulk_urb(hdev);
+ if (err < 0)
+ goto error;
- err = usb_submit_urb(data->evt_urb, GFP_ATOMIC);
- if (err < 0) {
- BT_ERR("%s submit failed for event urb %p with error %d",
- data->hdev->name, data->evt_urb, err);
- } else {
- err = usb_submit_urb(data->rx_urb, GFP_ATOMIC);
- if (err < 0) {
- BT_ERR("%s submit failed for rx urb %p with error %d",
- data->hdev->name, data->evt_urb, err);
- usb_kill_urb(data->evt_urb);
- }
- }
+ return 0;
- write_unlock_irqrestore(&data->lock, flags);
+error:
+ usb_kill_anchored_urbs(&data->rx_anchor);
-done:
- if (err < 0)
- clear_bit(HCI_RUNNING, &hdev->flags);
+ clear_bit(HCI_RUNNING, &hdev->flags);
return err;
}
@@ -446,27 +339,13 @@ done:
static int bpa10x_close(struct hci_dev *hdev)
{
struct bpa10x_data *data = hdev->driver_data;
- unsigned long flags;
- BT_DBG("hdev %p data %p", hdev, data);
+ BT_DBG("%s", hdev->name);
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
return 0;
- write_lock_irqsave(&data->lock, flags);
-
- skb_queue_purge(&data->cmd_queue);
- usb_kill_urb(data->cmd_urb);
- usb_kill_urb(data->evt_urb);
- usb_kill_urb(data->rx_urb);
- usb_kill_urb(data->tx_urb);
-
- write_unlock_irqrestore(&data->lock, flags);
-
- bpa10x_free_urb(data->cmd_urb);
- bpa10x_free_urb(data->evt_urb);
- bpa10x_free_urb(data->rx_urb);
- bpa10x_free_urb(data->tx_urb);
+ usb_kill_anchored_urbs(&data->rx_anchor);
return 0;
}
@@ -475,9 +354,9 @@ static int bpa10x_flush(struct hci_dev *hdev)
{
struct bpa10x_data *data = hdev->driver_data;
- BT_DBG("hdev %p data %p", hdev, data);
+ BT_DBG("%s", hdev->name);
- skb_queue_purge(&data->cmd_queue);
+ usb_kill_anchored_urbs(&data->tx_anchor);
return 0;
}
@@ -485,45 +364,78 @@ static int bpa10x_flush(struct hci_dev *hdev)
static int bpa10x_send_frame(struct sk_buff *skb)
{
struct hci_dev *hdev = (struct hci_dev *) skb->dev;
- struct bpa10x_data *data;
-
- BT_DBG("hdev %p skb %p type %d len %d", hdev, skb, bt_cb(skb)->pkt_type, skb->len);
+ struct bpa10x_data *data = hdev->driver_data;
+ struct usb_ctrlrequest *dr;
+ struct urb *urb;
+ unsigned int pipe;
+ int err;
- if (!hdev) {
- BT_ERR("Frame for unknown HCI device");
- return -ENODEV;
- }
+ BT_DBG("%s", hdev->name);
if (!test_bit(HCI_RUNNING, &hdev->flags))
return -EBUSY;
- data = hdev->driver_data;
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb)
+ return -ENOMEM;
/* Prepend skb with frame type */
- memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
+ *skb_push(skb, 1) = bt_cb(skb)->pkt_type;
switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT:
+ dr = kmalloc(sizeof(*dr), GFP_ATOMIC);
+ if (!dr) {
+ usb_free_urb(urb);
+ return -ENOMEM;
+ }
+
+ dr->bRequestType = USB_TYPE_VENDOR;
+ dr->bRequest = 0;
+ dr->wIndex = 0;
+ dr->wValue = 0;
+ dr->wLength = __cpu_to_le16(skb->len);
+
+ pipe = usb_sndctrlpipe(data->udev, 0x00);
+
+ usb_fill_control_urb(urb, data->udev, pipe, (void *) dr,
+ skb->data, skb->len, bpa10x_tx_complete, skb);
+
hdev->stat.cmd_tx++;
- skb_queue_tail(&data->cmd_queue, skb);
break;
case HCI_ACLDATA_PKT:
+ pipe = usb_sndbulkpipe(data->udev, 0x02);
+
+ usb_fill_bulk_urb(urb, data->udev, pipe,
+ skb->data, skb->len, bpa10x_tx_complete, skb);
+
hdev->stat.acl_tx++;
- skb_queue_tail(&data->tx_queue, skb);
break;
case HCI_SCODATA_PKT:
+ pipe = usb_sndbulkpipe(data->udev, 0x02);
+
+ usb_fill_bulk_urb(urb, data->udev, pipe,
+ skb->data, skb->len, bpa10x_tx_complete, skb);
+
hdev->stat.sco_tx++;
- skb_queue_tail(&data->tx_queue, skb);
break;
- };
- read_lock(&data->lock);
+ default:
+ return -EILSEQ;
+ }
+
+ usb_anchor_urb(urb, &data->tx_anchor);
- bpa10x_wakeup(data);
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err < 0) {
+ BT_ERR("%s urb %p submission failed", hdev->name, urb);
+ kfree(urb->setup_packet);
+ usb_unanchor_urb(urb);
+ }
- read_unlock(&data->lock);
+ usb_free_urb(urb);
return 0;
}
@@ -532,16 +444,17 @@ static void bpa10x_destruct(struct hci_dev *hdev)
{
struct bpa10x_data *data = hdev->driver_data;
- BT_DBG("hdev %p data %p", hdev, data);
+ BT_DBG("%s", hdev->name);
+ kfree(data->rx_skb[0]);
+ kfree(data->rx_skb[1]);
kfree(data);
}
static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
- struct usb_device *udev = interface_to_usbdev(intf);
- struct hci_dev *hdev;
struct bpa10x_data *data;
+ struct hci_dev *hdev;
int err;
BT_DBG("intf %p id %p", intf, id);
@@ -549,48 +462,43 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
if (ignore)
return -ENODEV;
- if (intf->cur_altsetting->desc.bInterfaceNumber > 0)
+ if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
return -ENODEV;
data = kzalloc(sizeof(*data), GFP_KERNEL);
- if (!data) {
- BT_ERR("Can't allocate data structure");
+ if (!data)
return -ENOMEM;
- }
-
- data->udev = udev;
- rwlock_init(&data->lock);
+ data->udev = interface_to_usbdev(intf);
- skb_queue_head_init(&data->cmd_queue);
- skb_queue_head_init(&data->tx_queue);
+ init_usb_anchor(&data->tx_anchor);
+ init_usb_anchor(&data->rx_anchor);
hdev = hci_alloc_dev();
if (!hdev) {
- BT_ERR("Can't allocate HCI device");
kfree(data);
return -ENOMEM;
}
- data->hdev = hdev;
-
hdev->type = HCI_USB;
hdev->driver_data = data;
+
+ data->hdev = hdev;
+
SET_HCIDEV_DEV(hdev, &intf->dev);
- hdev->open = bpa10x_open;
- hdev->close = bpa10x_close;
- hdev->flush = bpa10x_flush;
- hdev->send = bpa10x_send_frame;
- hdev->destruct = bpa10x_destruct;
+ hdev->open = bpa10x_open;
+ hdev->close = bpa10x_close;
+ hdev->flush = bpa10x_flush;
+ hdev->send = bpa10x_send_frame;
+ hdev->destruct = bpa10x_destruct;
hdev->owner = THIS_MODULE;
err = hci_register_dev(hdev);
if (err < 0) {
- BT_ERR("Can't register HCI device");
- kfree(data);
hci_free_dev(hdev);
+ kfree(data);
return err;
}
@@ -602,19 +510,17 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
static void bpa10x_disconnect(struct usb_interface *intf)
{
struct bpa10x_data *data = usb_get_intfdata(intf);
- struct hci_dev *hdev = data->hdev;
BT_DBG("intf %p", intf);
- if (!hdev)
+ if (!data)
return;
usb_set_intfdata(intf, NULL);
- if (hci_unregister_dev(hdev) < 0)
- BT_ERR("Can't unregister HCI device %s", hdev->name);
+ hci_unregister_dev(data->hdev);
- hci_free_dev(hdev);
+ hci_free_dev(data->hdev);
}
static struct usb_driver bpa10x_driver = {
@@ -626,15 +532,9 @@ static struct usb_driver bpa10x_driver = {
static int __init bpa10x_init(void)
{
- int err;
-
BT_INFO("Digianswer Bluetooth USB driver ver %s", VERSION);
- err = usb_register(&bpa10x_driver);
- if (err < 0)
- BT_ERR("Failed to register USB driver");
-
- return err;
+ return usb_register(&bpa10x_driver);
}
static void __exit bpa10x_exit(void)
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index 39516074636b..a18f9b8c9e12 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -344,10 +344,7 @@ static irqreturn_t bt3c_interrupt(int irq, void *dev_inst)
unsigned int iobase;
int iir;
- if (!info || !info->hdev) {
- BT_ERR("Call of irq %d for unknown device", irq);
- return IRQ_NONE;
- }
+ BUG_ON(!info->hdev);
iobase = info->p_dev->io.BasePort1;
diff --git a/drivers/bluetooth/btsdio.c b/drivers/bluetooth/btsdio.c
new file mode 100644
index 000000000000..b786f6187902
--- /dev/null
+++ b/drivers/bluetooth/btsdio.c
@@ -0,0 +1,406 @@
+/*
+ *
+ * Generic Bluetooth SDIO driver
+ *
+ * Copyright (C) 2007 Cambridge Silicon Radio Ltd.
+ * Copyright (C) 2007 Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/skbuff.h>
+
+#include <linux/mmc/sdio_ids.h>
+#include <linux/mmc/sdio_func.h>
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+
+#ifndef CONFIG_BT_HCIBTSDIO_DEBUG
+#undef BT_DBG
+#define BT_DBG(D...)
+#endif
+
+#define VERSION "0.1"
+
+static const struct sdio_device_id btsdio_table[] = {
+ /* Generic Bluetooth Type-A SDIO device */
+ { SDIO_DEVICE_CLASS(SDIO_CLASS_BT_A) },
+
+ /* Generic Bluetooth Type-B SDIO device */
+ { SDIO_DEVICE_CLASS(SDIO_CLASS_BT_B) },
+
+ { } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(sdio, btsdio_table);
+
+struct btsdio_data {
+ struct hci_dev *hdev;
+ struct sdio_func *func;
+
+ struct work_struct work;
+
+ struct sk_buff_head txq;
+};
+
+#define REG_RDAT 0x00 /* Receiver Data */
+#define REG_TDAT 0x00 /* Transmitter Data */
+#define REG_PC_RRT 0x10 /* Read Packet Control */
+#define REG_PC_WRT 0x11 /* Write Packet Control */
+#define REG_RTC_STAT 0x12 /* Retry Control Status */
+#define REG_RTC_SET 0x12 /* Retry Control Set */
+#define REG_INTRD 0x13 /* Interrupt Indication */
+#define REG_CL_INTRD 0x13 /* Interrupt Clear */
+#define REG_EN_INTRD 0x14 /* Interrupt Enable */
+#define REG_MD_STAT 0x20 /* Bluetooth Mode Status */
+
+static int btsdio_tx_packet(struct btsdio_data *data, struct sk_buff *skb)
+{
+ int err;
+
+ BT_DBG("%s", data->hdev->name);
+
+ /* Prepend Type-A header */
+ skb_push(skb, 4);
+ skb->data[0] = (skb->len & 0x0000ff);
+ skb->data[1] = (skb->len & 0x00ff00) >> 8;
+ skb->data[2] = (skb->len & 0xff0000) >> 16;
+ skb->data[3] = bt_cb(skb)->pkt_type;
+
+ err = sdio_writesb(data->func, REG_TDAT, skb->data, skb->len);
+ if (err < 0) {
+ sdio_writeb(data->func, 0x01, REG_PC_WRT, NULL);
+ return err;
+ }
+
+ data->hdev->stat.byte_tx += skb->len;
+
+ kfree_skb(skb);
+
+ return 0;
+}
+
+static void btsdio_work(struct work_struct *work)
+{
+ struct btsdio_data *data = container_of(work, struct btsdio_data, work);
+ struct sk_buff *skb;
+ int err;
+
+ BT_DBG("%s", data->hdev->name);
+
+ sdio_claim_host(data->func);
+
+ while ((skb = skb_dequeue(&data->txq))) {
+ err = btsdio_tx_packet(data, skb);
+ if (err < 0) {
+ data->hdev->stat.err_tx++;
+ skb_queue_head(&data->txq, skb);
+ break;
+ }
+ }
+
+ sdio_release_host(data->func);
+}
+
+static int btsdio_rx_packet(struct btsdio_data *data)
+{
+ u8 hdr[4] __attribute__ ((aligned(4)));
+ struct sk_buff *skb;
+ int err, len;
+
+ BT_DBG("%s", data->hdev->name);
+
+ err = sdio_readsb(data->func, hdr, REG_RDAT, 4);
+ if (err < 0)
+ return err;
+
+ len = hdr[0] | (hdr[1] << 8) | (hdr[2] << 16);
+ if (len < 4 || len > 65543)
+ return -EILSEQ;
+
+ skb = bt_skb_alloc(len - 4, GFP_KERNEL);
+ if (!skb) {
+ /* Out of memory. Prepare a read retry and just
+ * return with the expectation that the next time
+ * we're called we'll have more memory. */
+ return -ENOMEM;
+ }
+
+ skb_put(skb, len - 4);
+
+ err = sdio_readsb(data->func, skb->data, REG_RDAT, len - 4);
+ if (err < 0) {
+ kfree(skb);
+ return err;
+ }
+
+ data->hdev->stat.byte_rx += len;
+
+ skb->dev = (void *) data->hdev;
+ bt_cb(skb)->pkt_type = hdr[3];
+
+ err = hci_recv_frame(skb);
+ if (err < 0) {
+ kfree(skb);
+ return err;
+ }
+
+ sdio_writeb(data->func, 0x00, REG_PC_RRT, NULL);
+
+ return 0;
+}
+
+static void btsdio_interrupt(struct sdio_func *func)
+{
+ struct btsdio_data *data = sdio_get_drvdata(func);
+ int intrd;
+
+ BT_DBG("%s", data->hdev->name);
+
+ intrd = sdio_readb(func, REG_INTRD, NULL);
+ if (intrd & 0x01) {
+ sdio_writeb(func, 0x01, REG_CL_INTRD, NULL);
+
+ if (btsdio_rx_packet(data) < 0) {
+ data->hdev->stat.err_rx++;
+ sdio_writeb(data->func, 0x01, REG_PC_RRT, NULL);
+ }
+ }
+}
+
+static int btsdio_open(struct hci_dev *hdev)
+{
+ struct btsdio_data *data = hdev->driver_data;
+ int err;
+
+ BT_DBG("%s", hdev->name);
+
+ if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
+ return 0;
+
+ sdio_claim_host(data->func);
+
+ err = sdio_enable_func(data->func);
+ if (err < 0) {
+ clear_bit(HCI_RUNNING, &hdev->flags);
+ goto release;
+ }
+
+ err = sdio_claim_irq(data->func, btsdio_interrupt);
+ if (err < 0) {
+ sdio_disable_func(data->func);
+ clear_bit(HCI_RUNNING, &hdev->flags);
+ goto release;
+ }
+
+ if (data->func->class == SDIO_CLASS_BT_B)
+ sdio_writeb(data->func, 0x00, REG_MD_STAT, NULL);
+
+ sdio_writeb(data->func, 0x01, REG_EN_INTRD, NULL);
+
+release:
+ sdio_release_host(data->func);
+
+ return err;
+}
+
+static int btsdio_close(struct hci_dev *hdev)
+{
+ struct btsdio_data *data = hdev->driver_data;
+
+ BT_DBG("%s", hdev->name);
+
+ if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
+ return 0;
+
+ sdio_claim_host(data->func);
+
+ sdio_writeb(data->func, 0x00, REG_EN_INTRD, NULL);
+
+ sdio_release_irq(data->func);
+ sdio_disable_func(data->func);
+
+ sdio_release_host(data->func);
+
+ return 0;
+}
+
+static int btsdio_flush(struct hci_dev *hdev)
+{
+ struct btsdio_data *data = hdev->driver_data;
+
+ BT_DBG("%s", hdev->name);
+
+ skb_queue_purge(&data->txq);
+
+ return 0;
+}
+
+static int btsdio_send_frame(struct sk_buff *skb)
+{
+ struct hci_dev *hdev = (struct hci_dev *) skb->dev;
+ struct btsdio_data *data = hdev->driver_data;
+
+ BT_DBG("%s", hdev->name);
+
+ if (!test_bit(HCI_RUNNING, &hdev->flags))
+ return -EBUSY;
+
+ switch (bt_cb(skb)->pkt_type) {
+ case HCI_COMMAND_PKT:
+ hdev->stat.cmd_tx++;
+ break;
+
+ case HCI_ACLDATA_PKT:
+ hdev->stat.acl_tx++;
+ break;
+
+ case HCI_SCODATA_PKT:
+ hdev->stat.sco_tx++;
+ break;
+
+ default:
+ return -EILSEQ;
+ }
+
+ skb_queue_tail(&data->txq, skb);
+
+ schedule_work(&data->work);
+
+ return 0;
+}
+
+static void btsdio_destruct(struct hci_dev *hdev)
+{
+ struct btsdio_data *data = hdev->driver_data;
+
+ BT_DBG("%s", hdev->name);
+
+ kfree(data);
+}
+
+static int btsdio_probe(struct sdio_func *func,
+ const struct sdio_device_id *id)
+{
+ struct btsdio_data *data;
+ struct hci_dev *hdev;
+ struct sdio_func_tuple *tuple = func->tuples;
+ int err;
+
+ BT_DBG("func %p id %p class 0x%04x", func, id, func->class);
+
+ while (tuple) {
+ BT_DBG("code 0x%x size %d", tuple->code, tuple->size);
+ tuple = tuple->next;
+ }
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->func = func;
+
+ INIT_WORK(&data->work, btsdio_work);
+
+ skb_queue_head_init(&data->txq);
+
+ hdev = hci_alloc_dev();
+ if (!hdev) {
+ kfree(data);
+ return -ENOMEM;
+ }
+
+ hdev->type = HCI_SDIO;
+ hdev->driver_data = data;
+
+ data->hdev = hdev;
+
+ SET_HCIDEV_DEV(hdev, &func->dev);
+
+ hdev->open = btsdio_open;
+ hdev->close = btsdio_close;
+ hdev->flush = btsdio_flush;
+ hdev->send = btsdio_send_frame;
+ hdev->destruct = btsdio_destruct;
+
+ hdev->owner = THIS_MODULE;
+
+ err = hci_register_dev(hdev);
+ if (err < 0) {
+ hci_free_dev(hdev);
+ kfree(data);
+ return err;
+ }
+
+ sdio_set_drvdata(func, data);
+
+ return 0;
+}
+
+static void btsdio_remove(struct sdio_func *func)
+{
+ struct btsdio_data *data = sdio_get_drvdata(func);
+ struct hci_dev *hdev;
+
+ BT_DBG("func %p", func);
+
+ if (!data)
+ return;
+
+ hdev = data->hdev;
+
+ sdio_set_drvdata(func, NULL);
+
+ hci_unregister_dev(hdev);
+
+ hci_free_dev(hdev);
+}
+
+static struct sdio_driver btsdio_driver = {
+ .name = "btsdio",
+ .probe = btsdio_probe,
+ .remove = btsdio_remove,
+ .id_table = btsdio_table,
+};
+
+static int __init btsdio_init(void)
+{
+ BT_INFO("Generic Bluetooth SDIO driver ver %s", VERSION);
+
+ return sdio_register_driver(&btsdio_driver);
+}
+
+static void __exit btsdio_exit(void)
+{
+ sdio_unregister_driver(&btsdio_driver);
+}
+
+module_init(btsdio_init);
+module_exit(btsdio_exit);
+
+MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
+MODULE_DESCRIPTION("Generic Bluetooth SDIO driver ver " VERSION);
+MODULE_VERSION(VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c
index d7d2ea0d86a1..08f48d577aba 100644
--- a/drivers/bluetooth/btuart_cs.c
+++ b/drivers/bluetooth/btuart_cs.c
@@ -294,10 +294,7 @@ static irqreturn_t btuart_interrupt(int irq, void *dev_inst)
int boguscount = 0;
int iir, lsr;
- if (!info || !info->hdev) {
- BT_ERR("Call of irq %d for unknown device", irq);
- return IRQ_NONE;
- }
+ BUG_ON(!info->hdev);
iobase = info->p_dev->io.BasePort1;
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
new file mode 100644
index 000000000000..12e108914f19
--- /dev/null
+++ b/drivers/bluetooth/btusb.c
@@ -0,0 +1,564 @@
+/*
+ *
+ * Generic Bluetooth USB driver
+ *
+ * Copyright (C) 2005-2007 Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/skbuff.h>
+
+#include <linux/usb.h>
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+
+//#define CONFIG_BT_HCIBTUSB_DEBUG
+#ifndef CONFIG_BT_HCIBTUSB_DEBUG
+#undef BT_DBG
+#define BT_DBG(D...)
+#endif
+
+#define VERSION "0.1"
+
+static struct usb_device_id btusb_table[] = {
+ /* Generic Bluetooth USB device */
+ { USB_DEVICE_INFO(0xe0, 0x01, 0x01) },
+
+ { } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, btusb_table);
+
+static struct usb_device_id blacklist_table[] = {
+ { } /* Terminating entry */
+};
+
+#define BTUSB_INTR_RUNNING 0
+#define BTUSB_BULK_RUNNING 1
+
+struct btusb_data {
+ struct hci_dev *hdev;
+ struct usb_device *udev;
+
+ spinlock_t lock;
+
+ unsigned long flags;
+
+ struct work_struct work;
+
+ struct usb_anchor tx_anchor;
+ struct usb_anchor intr_anchor;
+ struct usb_anchor bulk_anchor;
+
+ struct usb_endpoint_descriptor *intr_ep;
+ struct usb_endpoint_descriptor *bulk_tx_ep;
+ struct usb_endpoint_descriptor *bulk_rx_ep;
+};
+
+static void btusb_intr_complete(struct urb *urb)
+{
+ struct hci_dev *hdev = urb->context;
+ struct btusb_data *data = hdev->driver_data;
+ int err;
+
+ BT_DBG("%s urb %p status %d count %d", hdev->name,
+ urb, urb->status, urb->actual_length);
+
+ if (!test_bit(HCI_RUNNING, &hdev->flags))
+ return;
+
+ if (urb->status == 0) {
+ if (hci_recv_fragment(hdev, HCI_EVENT_PKT,
+ urb->transfer_buffer,
+ urb->actual_length) < 0) {
+ BT_ERR("%s corrupted event packet", hdev->name);
+ hdev->stat.err_rx++;
+ }
+ }
+
+ if (!test_bit(BTUSB_INTR_RUNNING, &data->flags))
+ return;
+
+ usb_anchor_urb(urb, &data->intr_anchor);
+
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err < 0) {
+ BT_ERR("%s urb %p failed to resubmit (%d)",
+ hdev->name, urb, -err);
+ usb_unanchor_urb(urb);
+ }
+}
+
+static inline int btusb_submit_intr_urb(struct hci_dev *hdev)
+{
+ struct btusb_data *data = hdev->driver_data;
+ struct urb *urb;
+ unsigned char *buf;
+ unsigned int pipe;
+ int err, size;
+
+ BT_DBG("%s", hdev->name);
+
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb)
+ return -ENOMEM;
+
+ size = le16_to_cpu(data->intr_ep->wMaxPacketSize);
+
+ buf = kmalloc(size, GFP_ATOMIC);
+ if (!buf) {
+ usb_free_urb(urb);
+ return -ENOMEM;
+ }
+
+ pipe = usb_rcvintpipe(data->udev, data->intr_ep->bEndpointAddress);
+
+ usb_fill_int_urb(urb, data->udev, pipe, buf, size,
+ btusb_intr_complete, hdev,
+ data->intr_ep->bInterval);
+
+ urb->transfer_flags |= URB_FREE_BUFFER;
+
+ usb_anchor_urb(urb, &data->intr_anchor);
+
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err < 0) {
+ BT_ERR("%s urb %p submission failed (%d)",
+ hdev->name, urb, -err);
+ usb_unanchor_urb(urb);
+ kfree(buf);
+ }
+
+ usb_free_urb(urb);
+
+ return err;
+}
+
+static void btusb_bulk_complete(struct urb *urb)
+{
+ struct hci_dev *hdev = urb->context;
+ struct btusb_data *data = hdev->driver_data;
+ int err;
+
+ BT_DBG("%s urb %p status %d count %d", hdev->name,
+ urb, urb->status, urb->actual_length);
+
+ if (!test_bit(HCI_RUNNING, &hdev->flags))
+ return;
+
+ if (urb->status == 0) {
+ if (hci_recv_fragment(hdev, HCI_ACLDATA_PKT,
+ urb->transfer_buffer,
+ urb->actual_length) < 0) {
+ BT_ERR("%s corrupted ACL packet", hdev->name);
+ hdev->stat.err_rx++;
+ }
+ }
+
+ if (!test_bit(BTUSB_BULK_RUNNING, &data->flags))
+ return;
+
+ usb_anchor_urb(urb, &data->bulk_anchor);
+
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err < 0) {
+ BT_ERR("%s urb %p failed to resubmit (%d)",
+ hdev->name, urb, -err);
+ usb_unanchor_urb(urb);
+ }
+}
+
+static inline int btusb_submit_bulk_urb(struct hci_dev *hdev)
+{
+ struct btusb_data *data = hdev->driver_data;
+ struct urb *urb;
+ unsigned char *buf;
+ unsigned int pipe;
+ int err, size;
+
+ BT_DBG("%s", hdev->name);
+
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!urb)
+ return -ENOMEM;
+
+ size = le16_to_cpu(data->bulk_rx_ep->wMaxPacketSize);
+
+ buf = kmalloc(size, GFP_KERNEL);
+ if (!buf) {
+ usb_free_urb(urb);
+ return -ENOMEM;
+ }
+
+ pipe = usb_rcvbulkpipe(data->udev, data->bulk_rx_ep->bEndpointAddress);
+
+ usb_fill_bulk_urb(urb, data->udev, pipe,
+ buf, size, btusb_bulk_complete, hdev);
+
+ urb->transfer_flags |= URB_FREE_BUFFER;
+
+ usb_anchor_urb(urb, &data->bulk_anchor);
+
+ err = usb_submit_urb(urb, GFP_KERNEL);
+ if (err < 0) {
+ BT_ERR("%s urb %p submission failed (%d)",
+ hdev->name, urb, -err);
+ usb_unanchor_urb(urb);
+ kfree(buf);
+ }
+
+ usb_free_urb(urb);
+
+ return err;
+}
+
+static void btusb_tx_complete(struct urb *urb)
+{
+ struct sk_buff *skb = urb->context;
+ struct hci_dev *hdev = (struct hci_dev *) skb->dev;
+
+ BT_DBG("%s urb %p status %d count %d", hdev->name,
+ urb, urb->status, urb->actual_length);
+
+ if (!test_bit(HCI_RUNNING, &hdev->flags))
+ goto done;
+
+ if (!urb->status)
+ hdev->stat.byte_tx += urb->transfer_buffer_length;
+ else
+ hdev->stat.err_tx++;
+
+done:
+ kfree(urb->setup_packet);
+
+ kfree_skb(skb);
+}
+
+static int btusb_open(struct hci_dev *hdev)
+{
+ struct btusb_data *data = hdev->driver_data;
+ int err;
+
+ BT_DBG("%s", hdev->name);
+
+ if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
+ return 0;
+
+ if (test_and_set_bit(BTUSB_INTR_RUNNING, &data->flags))
+ return 0;
+
+ err = btusb_submit_intr_urb(hdev);
+ if (err < 0) {
+ clear_bit(BTUSB_INTR_RUNNING, &hdev->flags);
+ clear_bit(HCI_RUNNING, &hdev->flags);
+ }
+
+ return err;
+}
+
+static int btusb_close(struct hci_dev *hdev)
+{
+ struct btusb_data *data = hdev->driver_data;
+
+ BT_DBG("%s", hdev->name);
+
+ if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
+ return 0;
+
+ clear_bit(BTUSB_BULK_RUNNING, &data->flags);
+ usb_kill_anchored_urbs(&data->bulk_anchor);
+
+ clear_bit(BTUSB_INTR_RUNNING, &data->flags);
+ usb_kill_anchored_urbs(&data->intr_anchor);
+
+ return 0;
+}
+
+static int btusb_flush(struct hci_dev *hdev)
+{
+ struct btusb_data *data = hdev->driver_data;
+
+ BT_DBG("%s", hdev->name);
+
+ usb_kill_anchored_urbs(&data->tx_anchor);
+
+ return 0;
+}
+
+static int btusb_send_frame(struct sk_buff *skb)
+{
+ struct hci_dev *hdev = (struct hci_dev *) skb->dev;
+ struct btusb_data *data = hdev->driver_data;
+ struct usb_ctrlrequest *dr;
+ struct urb *urb;
+ unsigned int pipe;
+ int err;
+
+ BT_DBG("%s", hdev->name);
+
+ if (!test_bit(HCI_RUNNING, &hdev->flags))
+ return -EBUSY;
+
+ switch (bt_cb(skb)->pkt_type) {
+ case HCI_COMMAND_PKT:
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb)
+ return -ENOMEM;
+
+ dr = kmalloc(sizeof(*dr), GFP_ATOMIC);
+ if (!dr) {
+ usb_free_urb(urb);
+ return -ENOMEM;
+ }
+
+ dr->bRequestType = USB_TYPE_CLASS;
+ dr->bRequest = 0;
+ dr->wIndex = 0;
+ dr->wValue = 0;
+ dr->wLength = __cpu_to_le16(skb->len);
+
+ pipe = usb_sndctrlpipe(data->udev, 0x00);
+
+ usb_fill_control_urb(urb, data->udev, pipe, (void *) dr,
+ skb->data, skb->len, btusb_tx_complete, skb);
+
+ hdev->stat.cmd_tx++;
+ break;
+
+ case HCI_ACLDATA_PKT:
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb)
+ return -ENOMEM;
+
+ pipe = usb_sndbulkpipe(data->udev,
+ data->bulk_tx_ep->bEndpointAddress);
+
+ usb_fill_bulk_urb(urb, data->udev, pipe,
+ skb->data, skb->len, btusb_tx_complete, skb);
+
+ hdev->stat.acl_tx++;
+ break;
+
+ case HCI_SCODATA_PKT:
+ hdev->stat.sco_tx++;
+ kfree_skb(skb);
+ return 0;
+
+ default:
+ return -EILSEQ;
+ }
+
+ usb_anchor_urb(urb, &data->tx_anchor);
+
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err < 0) {
+ BT_ERR("%s urb %p submission failed", hdev->name, urb);
+ kfree(urb->setup_packet);
+ usb_unanchor_urb(urb);
+ }
+
+ usb_free_urb(urb);
+
+ return err;
+}
+
+static void btusb_destruct(struct hci_dev *hdev)
+{
+ struct btusb_data *data = hdev->driver_data;
+
+ BT_DBG("%s", hdev->name);
+
+ kfree(data);
+}
+
+static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
+{
+ struct btusb_data *data = hdev->driver_data;
+
+ BT_DBG("%s evt %d", hdev->name, evt);
+
+ if (evt == HCI_NOTIFY_CONN_ADD || evt == HCI_NOTIFY_CONN_DEL)
+ schedule_work(&data->work);
+}
+
+static void btusb_work(struct work_struct *work)
+{
+ struct btusb_data *data = container_of(work, struct btusb_data, work);
+ struct hci_dev *hdev = data->hdev;
+
+ if (hdev->conn_hash.acl_num == 0) {
+ clear_bit(BTUSB_BULK_RUNNING, &data->flags);
+ usb_kill_anchored_urbs(&data->bulk_anchor);
+ return;
+ }
+
+ if (!test_and_set_bit(BTUSB_BULK_RUNNING, &data->flags)) {
+ if (btusb_submit_bulk_urb(hdev) < 0)
+ clear_bit(BTUSB_BULK_RUNNING, &data->flags);
+ else
+ btusb_submit_bulk_urb(hdev);
+ }
+}
+
+static int btusb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usb_endpoint_descriptor *ep_desc;
+ struct btusb_data *data;
+ struct hci_dev *hdev;
+ int i, err;
+
+ BT_DBG("intf %p id %p", intf, id);
+
+ if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
+ return -ENODEV;
+
+ if (!id->driver_info) {
+ const struct usb_device_id *match;
+ match = usb_match_id(intf, blacklist_table);
+ if (match)
+ id = match;
+ }
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
+ ep_desc = &intf->cur_altsetting->endpoint[i].desc;
+
+ if (!data->intr_ep && usb_endpoint_is_int_in(ep_desc)) {
+ data->intr_ep = ep_desc;
+ continue;
+ }
+
+ if (!data->bulk_tx_ep && usb_endpoint_is_bulk_out(ep_desc)) {
+ data->bulk_tx_ep = ep_desc;
+ continue;
+ }
+
+ if (!data->bulk_rx_ep && usb_endpoint_is_bulk_in(ep_desc)) {
+ data->bulk_rx_ep = ep_desc;
+ continue;
+ }
+ }
+
+ if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep) {
+ kfree(data);
+ return -ENODEV;
+ }
+
+ data->udev = interface_to_usbdev(intf);
+
+ spin_lock_init(&data->lock);
+
+ INIT_WORK(&data->work, btusb_work);
+
+ init_usb_anchor(&data->tx_anchor);
+ init_usb_anchor(&data->intr_anchor);
+ init_usb_anchor(&data->bulk_anchor);
+
+ hdev = hci_alloc_dev();
+ if (!hdev) {
+ kfree(data);
+ return -ENOMEM;
+ }
+
+ hdev->type = HCI_USB;
+ hdev->driver_data = data;
+
+ data->hdev = hdev;
+
+ SET_HCIDEV_DEV(hdev, &intf->dev);
+
+ hdev->open = btusb_open;
+ hdev->close = btusb_close;
+ hdev->flush = btusb_flush;
+ hdev->send = btusb_send_frame;
+ hdev->destruct = btusb_destruct;
+ hdev->notify = btusb_notify;
+
+ hdev->owner = THIS_MODULE;
+
+ set_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks);
+
+ err = hci_register_dev(hdev);
+ if (err < 0) {
+ hci_free_dev(hdev);
+ kfree(data);
+ return err;
+ }
+
+ usb_set_intfdata(intf, data);
+
+ return 0;
+}
+
+static void btusb_disconnect(struct usb_interface *intf)
+{
+ struct btusb_data *data = usb_get_intfdata(intf);
+ struct hci_dev *hdev;
+
+ BT_DBG("intf %p", intf);
+
+ if (!data)
+ return;
+
+ hdev = data->hdev;
+
+ usb_set_intfdata(intf, NULL);
+
+ hci_unregister_dev(hdev);
+
+ hci_free_dev(hdev);
+}
+
+static struct usb_driver btusb_driver = {
+ .name = "btusb",
+ .probe = btusb_probe,
+ .disconnect = btusb_disconnect,
+ .id_table = btusb_table,
+};
+
+static int __init btusb_init(void)
+{
+ BT_INFO("Generic Bluetooth USB driver ver %s", VERSION);
+
+ return usb_register(&btusb_driver);
+}
+
+static void __exit btusb_exit(void)
+{
+ usb_deregister(&btusb_driver);
+}
+
+module_init(btusb_init);
+module_exit(btusb_exit);
+
+MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
+MODULE_DESCRIPTION("Generic Bluetooth USB driver ver " VERSION);
+MODULE_VERSION(VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
index 7f9c54b9964a..dae45cdf02b2 100644
--- a/drivers/bluetooth/dtl1_cs.c
+++ b/drivers/bluetooth/dtl1_cs.c
@@ -298,10 +298,7 @@ static irqreturn_t dtl1_interrupt(int irq, void *dev_inst)
int boguscount = 0;
int iir, lsr;
- if (!info || !info->hdev) {
- BT_ERR("Call of irq %d for unknown device", irq);
- return IRQ_NONE;
- }
+ BUG_ON(!info->hdev);
iobase = info->p_dev->io.BasePort1;
diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c
index d66064ccb31c..696f7528f022 100644
--- a/drivers/bluetooth/hci_bcsp.c
+++ b/drivers/bluetooth/hci_bcsp.c
@@ -237,7 +237,8 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data,
if (hciextn && chan == 5) {
struct hci_command_hdr *hdr = (struct hci_command_hdr *) data;
- if (hci_opcode_ogf(__le16_to_cpu(hdr->opcode)) == OGF_VENDOR_CMD) {
+ /* Vendor specific commands */
+ if (hci_opcode_ogf(__le16_to_cpu(hdr->opcode)) == 0x3f) {
u8 desc = *(data + HCI_COMMAND_HDR_SIZE);
if ((desc & 0xf0) == 0xc0) {
data += HCI_COMMAND_HDR_SIZE + 1;
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 6055b9c0ac0f..e68821d074b0 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -549,7 +549,10 @@ static int __init hci_uart_init(void)
#ifdef CONFIG_BT_HCIUART_BCSP
bcsp_init();
#endif
-
+#ifdef CONFIG_BT_HCIUART_LL
+ ll_init();
+#endif
+
return 0;
}
@@ -563,6 +566,9 @@ static void __exit hci_uart_exit(void)
#ifdef CONFIG_BT_HCIUART_BCSP
bcsp_deinit();
#endif
+#ifdef CONFIG_BT_HCIUART_LL
+ ll_deinit();
+#endif
/* Release tty registration of line discipline */
if ((err = tty_unregister_ldisc(N_HCI)))
diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c
new file mode 100644
index 000000000000..8c3e62a17b4a
--- /dev/null
+++ b/drivers/bluetooth/hci_ll.c
@@ -0,0 +1,531 @@
+/*
+ * Texas Instruments' Bluetooth HCILL UART protocol
+ *
+ * HCILL (HCI Low Level) is a Texas Instruments' power management
+ * protocol extension to H4.
+ *
+ * Copyright (C) 2007 Texas Instruments, Inc.
+ *
+ * Written by Ohad Ben-Cohen <ohad@bencohen.org>
+ *
+ * Acknowledgements:
+ * This file is based on hci_h4.c, which was written
+ * by Maxim Krasnyansky and Marcel Holtmann.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/poll.h>
+
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/signal.h>
+#include <linux/ioctl.h>
+#include <linux/skbuff.h>
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+
+#include "hci_uart.h"
+
+/* HCILL commands */
+#define HCILL_GO_TO_SLEEP_IND 0x30
+#define HCILL_GO_TO_SLEEP_ACK 0x31
+#define HCILL_WAKE_UP_IND 0x32
+#define HCILL_WAKE_UP_ACK 0x33
+
+/* HCILL receiver States */
+#define HCILL_W4_PACKET_TYPE 0
+#define HCILL_W4_EVENT_HDR 1
+#define HCILL_W4_ACL_HDR 2
+#define HCILL_W4_SCO_HDR 3
+#define HCILL_W4_DATA 4
+
+/* HCILL states */
+enum hcill_states_e {
+ HCILL_ASLEEP,
+ HCILL_ASLEEP_TO_AWAKE,
+ HCILL_AWAKE,
+ HCILL_AWAKE_TO_ASLEEP
+};
+
+struct hcill_cmd {
+ u8 cmd;
+} __attribute__((packed));
+
+struct ll_struct {
+ unsigned long rx_state;
+ unsigned long rx_count;
+ struct sk_buff *rx_skb;
+ struct sk_buff_head txq;
+ spinlock_t hcill_lock; /* HCILL state lock */
+ unsigned long hcill_state; /* HCILL power state */
+ struct sk_buff_head tx_wait_q; /* HCILL wait queue */
+};
+
+/*
+ * Builds and sends an HCILL command packet.
+ * These are very simple packets with only 1 cmd byte
+ */
+static int send_hcill_cmd(u8 cmd, struct hci_uart *hu)
+{
+ int err = 0;
+ struct sk_buff *skb = NULL;
+ struct ll_struct *ll = hu->priv;
+ struct hcill_cmd *hcill_packet;
+
+ BT_DBG("hu %p cmd 0x%x", hu, cmd);
+
+ /* allocate packet */
+ skb = bt_skb_alloc(1, GFP_ATOMIC);
+ if (!skb) {
+ BT_ERR("cannot allocate memory for HCILL packet");
+ err = -ENOMEM;
+ goto out;
+ }
+
+ /* prepare packet */
+ hcill_packet = (struct hcill_cmd *) skb_put(skb, 1);
+ hcill_packet->cmd = cmd;
+ skb->dev = (void *) hu->hdev;
+
+ /* send packet */
+ skb_queue_tail(&ll->txq, skb);
+out:
+ return err;
+}
+
+/* Initialize protocol */
+static int ll_open(struct hci_uart *hu)
+{
+ struct ll_struct *ll;
+
+ BT_DBG("hu %p", hu);
+
+ ll = kzalloc(sizeof(*ll), GFP_ATOMIC);
+ if (!ll)
+ return -ENOMEM;
+
+ skb_queue_head_init(&ll->txq);
+ skb_queue_head_init(&ll->tx_wait_q);
+ spin_lock_init(&ll->hcill_lock);
+
+ ll->hcill_state = HCILL_AWAKE;
+
+ hu->priv = ll;
+
+ return 0;
+}
+
+/* Flush protocol data */
+static int ll_flush(struct hci_uart *hu)
+{
+ struct ll_struct *ll = hu->priv;
+
+ BT_DBG("hu %p", hu);
+
+ skb_queue_purge(&ll->tx_wait_q);
+ skb_queue_purge(&ll->txq);
+
+ return 0;
+}
+
+/* Close protocol */
+static int ll_close(struct hci_uart *hu)
+{
+ struct ll_struct *ll = hu->priv;
+
+ BT_DBG("hu %p", hu);
+
+ skb_queue_purge(&ll->tx_wait_q);
+ skb_queue_purge(&ll->txq);
+
+ if (ll->rx_skb)
+ kfree_skb(ll->rx_skb);
+
+ hu->priv = NULL;
+
+ kfree(ll);
+
+ return 0;
+}
+
+/*
+ * internal function, which does common work of the device wake up process:
+ * 1. places all pending packets (waiting in tx_wait_q list) in txq list.
+ * 2. changes internal state to HCILL_AWAKE.
+ * Note: assumes that hcill_lock spinlock is taken,
+ * shouldn't be called otherwise!
+ */
+static void __ll_do_awake(struct ll_struct *ll)
+{
+ struct sk_buff *skb = NULL;
+
+ while ((skb = skb_dequeue(&ll->tx_wait_q)))
+ skb_queue_tail(&ll->txq, skb);
+
+ ll->hcill_state = HCILL_AWAKE;
+}
+
+/*
+ * Called upon a wake-up-indication from the device
+ */
+static void ll_device_want_to_wakeup(struct hci_uart *hu)
+{
+ unsigned long flags;
+ struct ll_struct *ll = hu->priv;
+
+ BT_DBG("hu %p", hu);
+
+ /* lock hcill state */
+ spin_lock_irqsave(&ll->hcill_lock, flags);
+
+ switch (ll->hcill_state) {
+ case HCILL_ASLEEP:
+ /* acknowledge device wake up */
+ if (send_hcill_cmd(HCILL_WAKE_UP_ACK, hu) < 0) {
+ BT_ERR("cannot acknowledge device wake up");
+ goto out;
+ }
+ break;
+ case HCILL_ASLEEP_TO_AWAKE:
+ /*
+ * this state means that a wake-up-indication
+ * is already on its way to the device,
+ * and will serve as the required wake-up-ack
+ */
+ BT_DBG("dual wake-up-indication");
+ break;
+ default:
+ /* any other state are illegal */
+ BT_ERR("received HCILL_WAKE_UP_IND in state %ld", ll->hcill_state);
+ break;
+ }
+
+ /* send pending packets and change state to HCILL_AWAKE */
+ __ll_do_awake(ll);
+
+out:
+ spin_unlock_irqrestore(&ll->hcill_lock, flags);
+
+ /* actually send the packets */
+ hci_uart_tx_wakeup(hu);
+}
+
+/*
+ * Called upon a sleep-indication from the device
+ */
+static void ll_device_want_to_sleep(struct hci_uart *hu)
+{
+ unsigned long flags;
+ struct ll_struct *ll = hu->priv;
+
+ BT_DBG("hu %p", hu);
+
+ /* lock hcill state */
+ spin_lock_irqsave(&ll->hcill_lock, flags);
+
+ /* sanity check */
+ if (ll->hcill_state != HCILL_AWAKE)
+ BT_ERR("ERR: HCILL_GO_TO_SLEEP_IND in state %ld", ll->hcill_state);
+
+ /* acknowledge device sleep */
+ if (send_hcill_cmd(HCILL_GO_TO_SLEEP_ACK, hu) < 0) {
+ BT_ERR("cannot acknowledge device sleep");
+ goto out;
+ }
+
+ /* update state */
+ ll->hcill_state = HCILL_ASLEEP;
+
+out:
+ spin_unlock_irqrestore(&ll->hcill_lock, flags);
+
+ /* actually send the sleep ack packet */
+ hci_uart_tx_wakeup(hu);
+}
+
+/*
+ * Called upon wake-up-acknowledgement from the device
+ */
+static void ll_device_woke_up(struct hci_uart *hu)
+{
+ unsigned long flags;
+ struct ll_struct *ll = hu->priv;
+
+ BT_DBG("hu %p", hu);
+
+ /* lock hcill state */
+ spin_lock_irqsave(&ll->hcill_lock, flags);
+
+ /* sanity check */
+ if (ll->hcill_state != HCILL_ASLEEP_TO_AWAKE)
+ BT_ERR("received HCILL_WAKE_UP_ACK in state %ld", ll->hcill_state);
+
+ /* send pending packets and change state to HCILL_AWAKE */
+ __ll_do_awake(ll);
+
+ spin_unlock_irqrestore(&ll->hcill_lock, flags);
+
+ /* actually send the packets */
+ hci_uart_tx_wakeup(hu);
+}
+
+/* Enqueue frame for transmittion (padding, crc, etc) */
+/* may be called from two simultaneous tasklets */
+static int ll_enqueue(struct hci_uart *hu, struct sk_buff *skb)
+{
+ unsigned long flags = 0;
+ struct ll_struct *ll = hu->priv;
+
+ BT_DBG("hu %p skb %p", hu, skb);
+
+ /* Prepend skb with frame type */
+ memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
+
+ /* lock hcill state */
+ spin_lock_irqsave(&ll->hcill_lock, flags);
+
+ /* act according to current state */
+ switch (ll->hcill_state) {
+ case HCILL_AWAKE:
+ BT_DBG("device awake, sending normally");
+ skb_queue_tail(&ll->txq, skb);
+ break;
+ case HCILL_ASLEEP:
+ BT_DBG("device asleep, waking up and queueing packet");
+ /* save packet for later */
+ skb_queue_tail(&ll->tx_wait_q, skb);
+ /* awake device */
+ if (send_hcill_cmd(HCILL_WAKE_UP_IND, hu) < 0) {
+ BT_ERR("cannot wake up device");
+ break;
+ }
+ ll->hcill_state = HCILL_ASLEEP_TO_AWAKE;
+ break;
+ case HCILL_ASLEEP_TO_AWAKE:
+ BT_DBG("device waking up, queueing packet");
+ /* transient state; just keep packet for later */
+ skb_queue_tail(&ll->tx_wait_q, skb);
+ break;
+ default:
+ BT_ERR("illegal hcill state: %ld (losing packet)", ll->hcill_state);
+ kfree_skb(skb);
+ break;
+ }
+
+ spin_unlock_irqrestore(&ll->hcill_lock, flags);
+
+ return 0;
+}
+
+static inline int ll_check_data_len(struct ll_struct *ll, int len)
+{
+ register int room = skb_tailroom(ll->rx_skb);
+
+ BT_DBG("len %d room %d", len, room);
+
+ if (!len) {
+ hci_recv_frame(ll->rx_skb);
+ } else if (len > room) {
+ BT_ERR("Data length is too large");
+ kfree_skb(ll->rx_skb);
+ } else {
+ ll->rx_state = HCILL_W4_DATA;
+ ll->rx_count = len;
+ return len;
+ }
+
+ ll->rx_state = HCILL_W4_PACKET_TYPE;
+ ll->rx_skb = NULL;
+ ll->rx_count = 0;
+
+ return 0;
+}
+
+/* Recv data */
+static int ll_recv(struct hci_uart *hu, void *data, int count)
+{
+ struct ll_struct *ll = hu->priv;
+ register char *ptr;
+ struct hci_event_hdr *eh;
+ struct hci_acl_hdr *ah;
+ struct hci_sco_hdr *sh;
+ register int len, type, dlen;
+
+ BT_DBG("hu %p count %d rx_state %ld rx_count %ld", hu, count, ll->rx_state, ll->rx_count);
+
+ ptr = data;
+ while (count) {
+ if (ll->rx_count) {
+ len = min_t(unsigned int, ll->rx_count, count);
+ memcpy(skb_put(ll->rx_skb, len), ptr, len);
+ ll->rx_count -= len; count -= len; ptr += len;
+
+ if (ll->rx_count)
+ continue;
+
+ switch (ll->rx_state) {
+ case HCILL_W4_DATA:
+ BT_DBG("Complete data");
+ hci_recv_frame(ll->rx_skb);
+
+ ll->rx_state = HCILL_W4_PACKET_TYPE;
+ ll->rx_skb = NULL;
+ continue;
+
+ case HCILL_W4_EVENT_HDR:
+ eh = (struct hci_event_hdr *) ll->rx_skb->data;
+
+ BT_DBG("Event header: evt 0x%2.2x plen %d", eh->evt, eh->plen);
+
+ ll_check_data_len(ll, eh->plen);
+ continue;
+
+ case HCILL_W4_ACL_HDR:
+ ah = (struct hci_acl_hdr *) ll->rx_skb->data;
+ dlen = __le16_to_cpu(ah->dlen);
+
+ BT_DBG("ACL header: dlen %d", dlen);
+
+ ll_check_data_len(ll, dlen);
+ continue;
+
+ case HCILL_W4_SCO_HDR:
+ sh = (struct hci_sco_hdr *) ll->rx_skb->data;
+
+ BT_DBG("SCO header: dlen %d", sh->dlen);
+
+ ll_check_data_len(ll, sh->dlen);
+ continue;
+ }
+ }
+
+ /* HCILL_W4_PACKET_TYPE */
+ switch (*ptr) {
+ case HCI_EVENT_PKT:
+ BT_DBG("Event packet");
+ ll->rx_state = HCILL_W4_EVENT_HDR;
+ ll->rx_count = HCI_EVENT_HDR_SIZE;
+ type = HCI_EVENT_PKT;
+ break;
+
+ case HCI_ACLDATA_PKT:
+ BT_DBG("ACL packet");
+ ll->rx_state = HCILL_W4_ACL_HDR;
+ ll->rx_count = HCI_ACL_HDR_SIZE;
+ type = HCI_ACLDATA_PKT;
+ break;
+
+ case HCI_SCODATA_PKT:
+ BT_DBG("SCO packet");
+ ll->rx_state = HCILL_W4_SCO_HDR;
+ ll->rx_count = HCI_SCO_HDR_SIZE;
+ type = HCI_SCODATA_PKT;
+ break;
+
+ /* HCILL signals */
+ case HCILL_GO_TO_SLEEP_IND:
+ BT_DBG("HCILL_GO_TO_SLEEP_IND packet");
+ ll_device_want_to_sleep(hu);
+ ptr++; count--;
+ continue;
+
+ case HCILL_GO_TO_SLEEP_ACK:
+ /* shouldn't happen */
+ BT_ERR("received HCILL_GO_TO_SLEEP_ACK (in state %ld)", ll->hcill_state);
+ ptr++; count--;
+ continue;
+
+ case HCILL_WAKE_UP_IND:
+ BT_DBG("HCILL_WAKE_UP_IND packet");
+ ll_device_want_to_wakeup(hu);
+ ptr++; count--;
+ continue;
+
+ case HCILL_WAKE_UP_ACK:
+ BT_DBG("HCILL_WAKE_UP_ACK packet");
+ ll_device_woke_up(hu);
+ ptr++; count--;
+ continue;
+
+ default:
+ BT_ERR("Unknown HCI packet type %2.2x", (__u8)*ptr);
+ hu->hdev->stat.err_rx++;
+ ptr++; count--;
+ continue;
+ };
+
+ ptr++; count--;
+
+ /* Allocate packet */
+ ll->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
+ if (!ll->rx_skb) {
+ BT_ERR("Can't allocate mem for new packet");
+ ll->rx_state = HCILL_W4_PACKET_TYPE;
+ ll->rx_count = 0;
+ return 0;
+ }
+
+ ll->rx_skb->dev = (void *) hu->hdev;
+ bt_cb(ll->rx_skb)->pkt_type = type;
+ }
+
+ return count;
+}
+
+static struct sk_buff *ll_dequeue(struct hci_uart *hu)
+{
+ struct ll_struct *ll = hu->priv;
+ return skb_dequeue(&ll->txq);
+}
+
+static struct hci_uart_proto llp = {
+ .id = HCI_UART_LL,
+ .open = ll_open,
+ .close = ll_close,
+ .recv = ll_recv,
+ .enqueue = ll_enqueue,
+ .dequeue = ll_dequeue,
+ .flush = ll_flush,
+};
+
+int ll_init(void)
+{
+ int err = hci_uart_register_proto(&llp);
+
+ if (!err)
+ BT_INFO("HCILL protocol initialized");
+ else
+ BT_ERR("HCILL protocol registration failed");
+
+ return err;
+}
+
+int ll_deinit(void)
+{
+ return hci_uart_unregister_proto(&llp);
+}
diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h
index 1097ce72393f..50113db06b9f 100644
--- a/drivers/bluetooth/hci_uart.h
+++ b/drivers/bluetooth/hci_uart.h
@@ -33,12 +33,13 @@
#define HCIUARTGETDEVICE _IOR('U', 202, int)
/* UART protocols */
-#define HCI_UART_MAX_PROTO 4
+#define HCI_UART_MAX_PROTO 5
#define HCI_UART_H4 0
#define HCI_UART_BCSP 1
#define HCI_UART_3WIRE 2
#define HCI_UART_H4DS 3
+#define HCI_UART_LL 4
struct hci_uart;
@@ -85,3 +86,8 @@ int h4_deinit(void);
int bcsp_init(void);
int bcsp_deinit(void);
#endif
+
+#ifdef CONFIG_BT_HCIUART_LL
+int ll_init(void);
+int ll_deinit(void);
+#endif
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 79245714f0a7..af0561053167 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -1107,7 +1107,7 @@ int open_for_data(struct cdrom_device_info * cdi)
is the default case! */
cdinfo(CD_OPEN, "bummer. wrong media type.\n");
cdinfo(CD_WARNING, "pid %d must open device O_NONBLOCK!\n",
- (unsigned int)current->pid);
+ (unsigned int)task_pid_nr(current));
ret=-EMEDIUMTYPE;
goto clean_up_and_return;
}
@@ -3458,47 +3458,19 @@ static void cdrom_update_settings(void)
static int cdrom_sysctl_handler(ctl_table *ctl, int write, struct file * filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
- int *valp = ctl->data;
- int val = *valp;
int ret;
ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
- if (write && *valp != val) {
+ if (write) {
/* we only care for 1 or 0. */
- if (*valp)
- *valp = 1;
- else
- *valp = 0;
+ autoclose = !!cdrom_sysctl_settings.autoclose;
+ autoeject = !!cdrom_sysctl_settings.autoeject;
+ debug = !!cdrom_sysctl_settings.debug;
+ lockdoor = !!cdrom_sysctl_settings.lock;
+ check_media_type = !!cdrom_sysctl_settings.check;
- switch (ctl->ctl_name) {
- case DEV_CDROM_AUTOCLOSE: {
- if (valp == &cdrom_sysctl_settings.autoclose)
- autoclose = cdrom_sysctl_settings.autoclose;
- break;
- }
- case DEV_CDROM_AUTOEJECT: {
- if (valp == &cdrom_sysctl_settings.autoeject)
- autoeject = cdrom_sysctl_settings.autoeject;
- break;
- }
- case DEV_CDROM_DEBUG: {
- if (valp == &cdrom_sysctl_settings.debug)
- debug = cdrom_sysctl_settings.debug;
- break;
- }
- case DEV_CDROM_LOCK: {
- if (valp == &cdrom_sysctl_settings.lock)
- lockdoor = cdrom_sysctl_settings.lock;
- break;
- }
- case DEV_CDROM_CHECK_MEDIA: {
- if (valp == &cdrom_sysctl_settings.check)
- check_media_type = cdrom_sysctl_settings.check;
- break;
- }
- }
/* update the option flags according to the changes. we
don't have per device options through sysctl yet,
but we will have and then this will disappear. */
@@ -3511,7 +3483,6 @@ static int cdrom_sysctl_handler(ctl_table *ctl, int write, struct file * filp,
/* Place files in /proc/sys/dev/cdrom */
static ctl_table cdrom_table[] = {
{
- .ctl_name = DEV_CDROM_INFO,
.procname = "info",
.data = &cdrom_sysctl_settings.info,
.maxlen = CDROM_STR_SIZE,
@@ -3519,7 +3490,6 @@ static ctl_table cdrom_table[] = {
.proc_handler = &cdrom_sysctl_info,
},
{
- .ctl_name = DEV_CDROM_AUTOCLOSE,
.procname = "autoclose",
.data = &cdrom_sysctl_settings.autoclose,
.maxlen = sizeof(int),
@@ -3527,7 +3497,6 @@ static ctl_table cdrom_table[] = {
.proc_handler = &cdrom_sysctl_handler,
},
{
- .ctl_name = DEV_CDROM_AUTOEJECT,
.procname = "autoeject",
.data = &cdrom_sysctl_settings.autoeject,
.maxlen = sizeof(int),
@@ -3535,7 +3504,6 @@ static ctl_table cdrom_table[] = {
.proc_handler = &cdrom_sysctl_handler,
},
{
- .ctl_name = DEV_CDROM_DEBUG,
.procname = "debug",
.data = &cdrom_sysctl_settings.debug,
.maxlen = sizeof(int),
@@ -3543,7 +3511,6 @@ static ctl_table cdrom_table[] = {
.proc_handler = &cdrom_sysctl_handler,
},
{
- .ctl_name = DEV_CDROM_LOCK,
.procname = "lock",
.data = &cdrom_sysctl_settings.lock,
.maxlen = sizeof(int),
@@ -3551,7 +3518,6 @@ static ctl_table cdrom_table[] = {
.proc_handler = &cdrom_sysctl_handler,
},
{
- .ctl_name = DEV_CDROM_CHECK_MEDIA,
.procname = "check_media",
.data = &cdrom_sysctl_settings.check,
.maxlen = sizeof(int),
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
index 880b5dce3a62..d8bb44b98a6a 100644
--- a/drivers/cdrom/viocd.c
+++ b/drivers/cdrom/viocd.c
@@ -41,9 +41,9 @@
#include <linux/completion.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <linux/scatterlist.h>
#include <asm/vio.h>
-#include <asm/scatterlist.h>
#include <asm/iseries/hv_types.h>
#include <asm/iseries/hv_lp_event.h>
#include <asm/iseries/vio.h>
@@ -258,6 +258,7 @@ static int send_request(struct request *req)
cmd = viomajorsubtype_cdio | viocdwrite;
}
+ sg_init_table(&sg, 1);
if (blk_rq_map_sg(req->q, req, &sg) == 0) {
printk(VIOCD_KERN_WARNING
"error setting up scatter/gather list\n");
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index b391776e5bf3..bf18d757b876 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -568,8 +568,8 @@ config TIPAR
config HVC_DRIVER
bool
help
- Users of pSeries machines that want to utilize the hvc console front-end
- module for their backend console driver should select this option.
+ Generic "hypervisor virtual console" infrastructure for various
+ hypervisors (pSeries, iSeries, Xen, lguest).
It will automatically be selected if one of the back-end console drivers
is selected.
@@ -613,6 +613,10 @@ config HVC_XEN
help
Xen virtual console device driver
+config VIRTIO_CONSOLE
+ bool
+ select HVC_DRIVER
+
config HVCS
tristate "IBM Hypervisor Virtual Console Server support"
depends on PPC_PSERIES
@@ -632,8 +636,6 @@ config HVCS
source "drivers/char/ipmi/Kconfig"
-source "drivers/char/watchdog/Kconfig"
-
config DS1620
tristate "NetWinder thermometer support"
depends on ARCH_NETWINDER
@@ -896,10 +898,6 @@ config GPIO_TB0219
depends on TANBAC_TB022X
select GPIO_VR41XX
-source "drivers/char/agp/Kconfig"
-
-source "drivers/char/drm/Kconfig"
-
source "drivers/char/pcmcia/Kconfig"
config MWAVE
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index c78ff26647ee..07304d50e0cb 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -42,7 +42,6 @@ obj-$(CONFIG_SYNCLINK_GT) += synclink_gt.o
obj-$(CONFIG_N_HDLC) += n_hdlc.o
obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o
obj-$(CONFIG_SX) += sx.o generic_serial.o
-obj-$(CONFIG_LGUEST_GUEST) += hvc_lguest.o
obj-$(CONFIG_RIO) += rio/ generic_serial.o
obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi.o
obj-$(CONFIG_HVC_ISERIES) += hvc_iseries.o
@@ -50,6 +49,7 @@ obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o
obj-$(CONFIG_HVC_BEAT) += hvc_beat.o
obj-$(CONFIG_HVC_DRIVER) += hvc_console.o
obj-$(CONFIG_HVC_XEN) += hvc_xen.o
+obj-$(CONFIG_VIRTIO_CONSOLE) += virtio_console.o
obj-$(CONFIG_RAW_DRIVER) += raw.o
obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o
obj-$(CONFIG_MSPEC) += mspec.o
diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig
index 713533d8a86e..ccb1fa89de29 100644
--- a/drivers/char/agp/Kconfig
+++ b/drivers/char/agp/Kconfig
@@ -1,4 +1,4 @@
-config AGP
+menuconfig AGP
tristate "/dev/agpgart (AGP Support)"
depends on ALPHA || IA64 || PARISC || PPC || X86
depends on PCI
@@ -56,9 +56,9 @@ config AGP_AMD
X on AMD Irongate, 761, and 762 chipsets.
config AGP_AMD64
- tristate "AMD Opteron/Athlon64 on-CPU GART support" if !IOMMU
+ tristate "AMD Opteron/Athlon64 on-CPU GART support" if !GART_IOMMU
depends on AGP && X86
- default y if IOMMU
+ default y if GART_IOMMU
help
This option gives you AGP support for the GLX component of
X using the on-CPU northbridge of the AMD Athlon64/Opteron CPUs.
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index d95662e96326..d8200ac8f8cb 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -787,7 +787,7 @@ static void __exit agp_amd64_cleanup(void)
/* On AMD64 the PCI driver needs to initialize this driver early
for the IOMMU, so it has to be called via a backdoor. */
-#ifndef CONFIG_IOMMU
+#ifndef CONFIG_GART_IOMMU
module_init(agp_amd64_init);
module_exit(agp_amd64_cleanup);
#endif
diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c
index d78cd09186aa..cac0009cebc1 100644
--- a/drivers/char/agp/efficeon-agp.c
+++ b/drivers/char/agp/efficeon-agp.c
@@ -221,7 +221,7 @@ static int efficeon_create_gatt_table(struct agp_bridge_data *bridge)
SetPageReserved(virt_to_page((char *)page));
for (offset = 0; offset < PAGE_SIZE; offset += clflush_chunk)
- asm volatile("clflush %0" : : "m" (*(char *)(page+offset)));
+ clflush((char *)page+offset);
efficeon_private.l1_table[index] = page;
@@ -268,15 +268,16 @@ static int efficeon_insert_memory(struct agp_memory * mem, off_t pg_start, int t
*page = insert;
/* clflush is slow, so don't clflush until we have to */
- if ( last_page &&
- ((unsigned long)page^(unsigned long)last_page) & clflush_mask )
- asm volatile("clflush %0" : : "m" (*last_page));
+ if (last_page &&
+ (((unsigned long)page^(unsigned long)last_page) &
+ clflush_mask))
+ clflush(last_page);
last_page = page;
}
if ( last_page )
- asm volatile("clflush %0" : : "m" (*last_page));
+ clflush(last_page);
agp_bridge->driver->tlb_flush(mem);
return 0;
diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c
index 313a133a1172..cbb0444467ba 100644
--- a/drivers/char/agp/hp-agp.c
+++ b/drivers/char/agp/hp-agp.c
@@ -14,15 +14,12 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/agp_backend.h>
+#include <linux/log2.h>
#include <asm/acpi-ext.h>
#include "agp.h"
-#ifndef log2
-#define log2(x) ffz(~(x))
-#endif
-
#define HP_ZX1_IOC_OFFSET 0x1000 /* ACPI reports SBA, we want IOC */
/* HP ZX1 IOC registers */
@@ -257,7 +254,7 @@ hp_zx1_configure (void)
readl(hp->ioc_regs+HP_ZX1_IMASK);
writel(hp->iova_base|1, hp->ioc_regs+HP_ZX1_IBASE);
readl(hp->ioc_regs+HP_ZX1_IBASE);
- writel(hp->iova_base|log2(HP_ZX1_IOVA_SIZE), hp->ioc_regs+HP_ZX1_PCOM);
+ writel(hp->iova_base|ilog2(HP_ZX1_IOVA_SIZE), hp->ioc_regs+HP_ZX1_PCOM);
readl(hp->ioc_regs+HP_ZX1_PCOM);
}
@@ -285,7 +282,7 @@ hp_zx1_tlbflush (struct agp_memory *mem)
{
struct _hp_private *hp = &hp_private;
- writeq(hp->gart_base | log2(hp->gart_size), hp->ioc_regs+HP_ZX1_PCOM);
+ writeq(hp->gart_base | ilog2(hp->gart_size), hp->ioc_regs+HP_ZX1_PCOM);
readq(hp->ioc_regs+HP_ZX1_PCOM);
}
diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c
index 70117df4d067..e72a83e2bad5 100644
--- a/drivers/char/agp/i460-agp.c
+++ b/drivers/char/agp/i460-agp.c
@@ -13,6 +13,7 @@
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/agp_backend.h>
+#include <linux/log2.h>
#include "agp.h"
@@ -59,8 +60,6 @@
*/
#define WR_FLUSH_GATT(index) RD_GATT(index)
-#define log2(x) ffz(~(x))
-
static struct {
void *gatt; /* ioremap'd GATT area */
@@ -148,7 +147,7 @@ static int i460_fetch_size (void)
* values[i].size.
*/
values[i].num_entries = (values[i].size << 8) >> (I460_IO_PAGE_SHIFT - 12);
- values[i].page_order = log2((sizeof(u32)*values[i].num_entries) >> PAGE_SHIFT);
+ values[i].page_order = ilog2((sizeof(u32)*values[i].num_entries) >> PAGE_SHIFT);
}
for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
diff --git a/drivers/char/agp/parisc-agp.c b/drivers/char/agp/parisc-agp.c
index f4562cc22343..2939e3570f9d 100644
--- a/drivers/char/agp/parisc-agp.c
+++ b/drivers/char/agp/parisc-agp.c
@@ -18,6 +18,7 @@
#include <linux/init.h>
#include <linux/klist.h>
#include <linux/agp_backend.h>
+#include <linux/log2.h>
#include <asm-parisc/parisc-device.h>
#include <asm-parisc/ropes.h>
@@ -27,10 +28,6 @@
#define DRVNAME "quicksilver"
#define DRVPFX DRVNAME ": "
-#ifndef log2
-#define log2(x) ffz(~(x))
-#endif
-
#define AGP8X_MODE_BIT 3
#define AGP8X_MODE (1 << AGP8X_MODE_BIT)
@@ -92,7 +89,7 @@ parisc_agp_tlbflush(struct agp_memory *mem)
{
struct _parisc_agp_info *info = &parisc_agp_info;
- writeq(info->gart_base | log2(info->gart_size), info->ioc_regs+IOC_PCOM);
+ writeq(info->gart_base | ilog2(info->gart_size), info->ioc_regs+IOC_PCOM);
readq(info->ioc_regs+IOC_PCOM); /* flush */
}
diff --git a/drivers/char/apm-emulation.c b/drivers/char/apm-emulation.c
index ec116df919d9..c99e43b837f5 100644
--- a/drivers/char/apm-emulation.c
+++ b/drivers/char/apm-emulation.c
@@ -18,7 +18,7 @@
#include <linux/apm_bios.h>
#include <linux/capability.h>
#include <linux/sched.h>
-#include <linux/pm.h>
+#include <linux/suspend.h>
#include <linux/apm-emulation.h>
#include <linux/freezer.h>
#include <linux/device.h>
diff --git a/drivers/char/consolemap.c b/drivers/char/consolemap.c
index 4b3916f54909..6b104e45a322 100644
--- a/drivers/char/consolemap.c
+++ b/drivers/char/consolemap.c
@@ -494,12 +494,11 @@ int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
if (p && p->readonly) return -EIO;
if (!p || --p->refcount) {
- q = kmalloc(sizeof(*p), GFP_KERNEL);
+ q = kzalloc(sizeof(*p), GFP_KERNEL);
if (!q) {
if (p) p->refcount++;
return -ENOMEM;
}
- memset(q, 0, sizeof(*q));
q->refcount=1;
*vc->vc_uni_pagedir_loc = (unsigned long)q;
} else {
@@ -670,19 +669,29 @@ void con_protect_unimap(struct vc_data *vc, int rdonly)
p->readonly = rdonly;
}
+/*
+ * Always use USER_MAP. These functions are used by the keyboard,
+ * which shouldn't be affected by G0/G1 switching, etc.
+ * If the user map still contains default values, i.e. the
+ * direct-to-font mapping, then assume user is using Latin1.
+ */
/* may be called during an interrupt */
u32 conv_8bit_to_uni(unsigned char c)
{
- /*
- * Always use USER_MAP. This function is used by the keyboard,
- * which shouldn't be affected by G0/G1 switching, etc.
- * If the user map still contains default values, i.e. the
- * direct-to-font mapping, then assume user is using Latin1.
- */
unsigned short uni = translations[USER_MAP][c];
return uni == (0xf000 | c) ? c : uni;
}
+int conv_uni_to_8bit(u32 uni)
+{
+ int c;
+ for (c = 0; c < 0x100; c++)
+ if (translations[USER_MAP][c] == uni ||
+ (translations[USER_MAP][c] == (c | 0xf000) && uni == c))
+ return c;
+ return -1;
+}
+
int
conv_uni_to_pc(struct vc_data *conp, long ucs)
{
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index 9e0adfe27c12..e4f579c3e245 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -359,7 +359,7 @@
*
* Revision 1.36.3.8 1996/06/07 16:29:00 bentson
* starting minor number at zero; added missing verify_area
- * as noted by Heiko Eissfeldt <heiko@colossus.escape.de>
+ * as noted by Heiko Eißfeldt <heiko@colossus.escape.de>
*
* Revision 1.36.3.7 1996/04/19 21:06:18 bentson
* remove unneeded boot message & fix CLOCAL hardware flow
@@ -662,7 +662,7 @@
static void cy_throttle(struct tty_struct *tty);
static void cy_send_xchar(struct tty_struct *tty, char ch);
-#define IS_CYC_Z(card) ((card).num_chips == -1)
+#define IS_CYC_Z(card) ((card).num_chips == (unsigned int)-1)
#define Z_FPGA_CHECK(card) \
((readl(&((struct RUNTIME_9060 __iomem *) \
@@ -727,8 +727,6 @@ static struct tty_driver *cy_serial_driver;
driver to probe addresses at a different address, add it to
this table. If the driver is probing some other board and
causing problems, remove the offending address from this table.
- The cy_setup function extracts additional addresses from the
- boot options line. The form is "cyclades=address,address..."
*/
static unsigned int cy_isa_addresses[] = {
@@ -897,71 +895,6 @@ static inline int serial_paranoia_check(struct cyclades_port *info,
return 0;
} /* serial_paranoia_check */
-/*
- * This routine is used by the interrupt handler to schedule
- * processing in the software interrupt portion of the driver
- * (also known as the "bottom half"). This can be called any
- * number of times for any channel without harm.
- */
-static inline void cy_sched_event(struct cyclades_port *info, int event)
-{
- info->event |= 1 << event; /* remember what kind of event and who */
- schedule_work(&info->tqueue);
-} /* cy_sched_event */
-
-/*
- * This routine is used to handle the "bottom half" processing for the
- * serial driver, known also the "software interrupt" processing.
- * This processing is done at the kernel interrupt level, after the
- * cy#/_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This
- * is where time-consuming activities which can not be done in the
- * interrupt driver proper are done; the interrupt driver schedules
- * them using cy_sched_event(), and they get done here.
- *
- * This is done through one level of indirection--the task queue.
- * When a hardware interrupt service routine wants service by the
- * driver's bottom half, it enqueues the appropriate tq_struct (one
- * per port) to the keventd work queue and sets a request flag
- * that the work queue be processed.
- *
- * Although this may seem unwieldy, it gives the system a way to
- * pass an argument (in this case the pointer to the cyclades_port
- * structure) to the bottom half of the driver. Previous kernels
- * had to poll every port to see if that port needed servicing.
- */
-static void
-do_softint(struct work_struct *work)
-{
- struct cyclades_port *info =
- container_of(work, struct cyclades_port, tqueue);
- struct tty_struct *tty;
-
- tty = info->tty;
- if (!tty)
- return;
-
- if (test_and_clear_bit(Cy_EVENT_HANGUP, &info->event)) {
- tty_hangup(info->tty);
- wake_up_interruptible(&info->open_wait);
- info->flags &= ~ASYNC_NORMAL_ACTIVE;
- }
- if (test_and_clear_bit(Cy_EVENT_OPEN_WAKEUP, &info->event))
- wake_up_interruptible(&info->open_wait);
-#ifdef CONFIG_CYZ_INTR
- if (test_and_clear_bit(Cy_EVENT_Z_RX_FULL, &info->event) &&
- !timer_pending(&cyz_rx_full_timer[info->line]))
- mod_timer(&cyz_rx_full_timer[info->line], jiffies + 1);
-#endif
- if (test_and_clear_bit(Cy_EVENT_DELTA_WAKEUP, &info->event))
- wake_up_interruptible(&info->delta_msr_wait);
- tty_wakeup(tty);
-#ifdef Z_WAKE
- if (test_and_clear_bit(Cy_EVENT_SHUTDOWN_WAKEUP, &info->event))
- complete(&info->shutdown_wait);
-#endif
-} /* do_softint */
-
-
/***********************************************************/
/********* Start of block of Cyclom-Y specific code ********/
@@ -1045,382 +978,332 @@ static unsigned detect_isa_irq(void __iomem * address)
}
#endif /* CONFIG_ISA */
-static void cyy_intr_chip(struct cyclades_card *cinfo, int chip,
- void __iomem * base_addr, int status, int index)
+static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
+ void __iomem *base_addr)
{
struct cyclades_port *info;
struct tty_struct *tty;
- int char_count;
- int j, len, mdm_change, mdm_status, outch;
- int save_xir, channel, save_car;
- char data;
+ int len, index = cinfo->bus_index;
+ u8 save_xir, channel, save_car, data, char_count;
- if (status & CySRReceive) { /* reception interrupt */
#ifdef CY_DEBUG_INTERRUPTS
- printk(KERN_DEBUG "cyy_interrupt: rcvd intr, chip %d\n", chip);
+ printk(KERN_DEBUG "cyy_interrupt: rcvd intr, chip %d\n", chip);
#endif
- /* determine the channel & change to that context */
- spin_lock(&cinfo->card_lock);
- save_xir = (u_char) readb(base_addr + (CyRIR << index));
- channel = (u_short) (save_xir & CyIRChannel);
- info = &cinfo->ports[channel + chip * 4];
- save_car = readb(base_addr + (CyCAR << index));
- cy_writeb(base_addr + (CyCAR << index), save_xir);
-
- /* if there is nowhere to put the data, discard it */
- if (info->tty == NULL) {
- j = (readb(base_addr + (CyRIVR << index)) &
- CyIVRMask);
- if (j == CyIVRRxEx) { /* exception */
+ /* determine the channel & change to that context */
+ save_xir = readb(base_addr + (CyRIR << index));
+ channel = save_xir & CyIRChannel;
+ info = &cinfo->ports[channel + chip * 4];
+ save_car = readb(base_addr + (CyCAR << index));
+ cy_writeb(base_addr + (CyCAR << index), save_xir);
+
+ /* if there is nowhere to put the data, discard it */
+ if (info->tty == NULL) {
+ if ((readb(base_addr + (CyRIVR << index)) & CyIVRMask) ==
+ CyIVRRxEx) { /* exception */
+ data = readb(base_addr + (CyRDSR << index));
+ } else { /* normal character reception */
+ char_count = readb(base_addr + (CyRDCR << index));
+ while (char_count--)
data = readb(base_addr + (CyRDSR << index));
- } else { /* normal character reception */
- char_count = readb(base_addr +
- (CyRDCR << index));
- while (char_count--) {
- data = readb(base_addr +
- (CyRDSR << index));
- }
- }
- } else { /* there is an open port for this data */
- tty = info->tty;
- j = (readb(base_addr + (CyRIVR << index)) &
- CyIVRMask);
- if (j == CyIVRRxEx) { /* exception */
- data = readb(base_addr + (CyRDSR << index));
-
- /* For statistics only */
- if (data & CyBREAK)
- info->icount.brk++;
- else if (data & CyFRAME)
- info->icount.frame++;
- else if (data & CyPARITY)
- info->icount.parity++;
- else if (data & CyOVERRUN)
- info->icount.overrun++;
-
- if (data & info->ignore_status_mask) {
+ }
+ goto end;
+ }
+ /* there is an open port for this data */
+ tty = info->tty;
+ if ((readb(base_addr + (CyRIVR << index)) & CyIVRMask) ==
+ CyIVRRxEx) { /* exception */
+ data = readb(base_addr + (CyRDSR << index));
+
+ /* For statistics only */
+ if (data & CyBREAK)
+ info->icount.brk++;
+ else if (data & CyFRAME)
+ info->icount.frame++;
+ else if (data & CyPARITY)
+ info->icount.parity++;
+ else if (data & CyOVERRUN)
+ info->icount.overrun++;
+
+ if (data & info->ignore_status_mask) {
+ info->icount.rx++;
+ return;
+ }
+ if (tty_buffer_request_room(tty, 1)) {
+ if (data & info->read_status_mask) {
+ if (data & CyBREAK) {
+ tty_insert_flip_char(tty,
+ readb(base_addr + (CyRDSR <<
+ index)), TTY_BREAK);
+ info->icount.rx++;
+ if (info->flags & ASYNC_SAK)
+ do_SAK(tty);
+ } else if (data & CyFRAME) {
+ tty_insert_flip_char( tty,
+ readb(base_addr + (CyRDSR <<
+ index)), TTY_FRAME);
+ info->icount.rx++;
+ info->idle_stats.frame_errs++;
+ } else if (data & CyPARITY) {
+ /* Pieces of seven... */
+ tty_insert_flip_char(tty,
+ readb(base_addr + (CyRDSR <<
+ index)), TTY_PARITY);
+ info->icount.rx++;
+ info->idle_stats.parity_errs++;
+ } else if (data & CyOVERRUN) {
+ tty_insert_flip_char(tty, 0,
+ TTY_OVERRUN);
+ info->icount.rx++;
+ /* If the flip buffer itself is
+ overflowing, we still lose
+ the next incoming character.
+ */
+ tty_insert_flip_char(tty,
+ readb(base_addr + (CyRDSR <<
+ index)), TTY_FRAME);
info->icount.rx++;
- spin_unlock(&cinfo->card_lock);
- return;
- }
- if (tty_buffer_request_room(tty, 1)) {
- if (data & info->read_status_mask) {
- if (data & CyBREAK) {
- tty_insert_flip_char(
- tty,
- readb(
- base_addr +
- (CyRDSR <<
- index)),
- TTY_BREAK);
- info->icount.rx++;
- if (info->flags &
- ASYNC_SAK) {
- do_SAK(tty);
- }
- } else if (data & CyFRAME) {
- tty_insert_flip_char(
- tty,
- readb(
- base_addr +
- (CyRDSR <<
- index)),
- TTY_FRAME);
- info->icount.rx++;
- info->idle_stats.
- frame_errs++;
- } else if (data & CyPARITY) {
- /* Pieces of seven... */
- tty_insert_flip_char(
- tty,
- readb(
- base_addr +
- (CyRDSR <<
- index)),
- TTY_PARITY);
- info->icount.rx++;
- info->idle_stats.
- parity_errs++;
- } else if (data & CyOVERRUN) {
- tty_insert_flip_char(
- tty, 0,
- TTY_OVERRUN);
- info->icount.rx++;
- /* If the flip buffer itself is
- overflowing, we still lose
- the next incoming character.
- */
- tty_insert_flip_char(
- tty,
- readb(
- base_addr +
- (CyRDSR <<
- index)),
- TTY_FRAME);
- info->icount.rx++;
- info->idle_stats.
- overruns++;
- /* These two conditions may imply */
- /* a normal read should be done. */
- /* }else if(data & CyTIMEOUT){ */
- /* }else if(data & CySPECHAR){ */
- } else {
- tty_insert_flip_char(
- tty, 0,
- TTY_NORMAL);
- info->icount.rx++;
- }
- } else {
- tty_insert_flip_char(tty, 0,
- TTY_NORMAL);
- info->icount.rx++;
- }
- } else {
- /* there was a software buffer
- overrun and nothing could be
- done about it!!! */
- info->icount.buf_overrun++;
info->idle_stats.overruns++;
+ /* These two conditions may imply */
+ /* a normal read should be done. */
+ /* } else if(data & CyTIMEOUT) { */
+ /* } else if(data & CySPECHAR) { */
+ } else {
+ tty_insert_flip_char(tty, 0,
+ TTY_NORMAL);
+ info->icount.rx++;
}
- } else { /* normal character reception */
- /* load # chars available from the chip */
- char_count = readb(base_addr +
- (CyRDCR << index));
+ } else {
+ tty_insert_flip_char(tty, 0, TTY_NORMAL);
+ info->icount.rx++;
+ }
+ } else {
+ /* there was a software buffer overrun and nothing
+ * could be done about it!!! */
+ info->icount.buf_overrun++;
+ info->idle_stats.overruns++;
+ }
+ } else { /* normal character reception */
+ /* load # chars available from the chip */
+ char_count = readb(base_addr + (CyRDCR << index));
#ifdef CY_ENABLE_MONITORING
- ++info->mon.int_count;
- info->mon.char_count += char_count;
- if (char_count > info->mon.char_max)
- info->mon.char_max = char_count;
- info->mon.char_last = char_count;
+ ++info->mon.int_count;
+ info->mon.char_count += char_count;
+ if (char_count > info->mon.char_max)
+ info->mon.char_max = char_count;
+ info->mon.char_last = char_count;
#endif
- len = tty_buffer_request_room(tty, char_count);
- while (len--) {
- data = readb(base_addr +
- (CyRDSR << index));
- tty_insert_flip_char(tty, data,
- TTY_NORMAL);
- info->idle_stats.recv_bytes++;
- info->icount.rx++;
+ len = tty_buffer_request_room(tty, char_count);
+ while (len--) {
+ data = readb(base_addr + (CyRDSR << index));
+ tty_insert_flip_char(tty, data, TTY_NORMAL);
+ info->idle_stats.recv_bytes++;
+ info->icount.rx++;
#ifdef CY_16Y_HACK
- udelay(10L);
+ udelay(10L);
#endif
- }
- info->idle_stats.recv_idle = jiffies;
- }
- tty_schedule_flip(tty);
}
- /* end of service */
- cy_writeb(base_addr + (CyRIR << index), (save_xir & 0x3f));
- cy_writeb(base_addr + (CyCAR << index), (save_car));
- spin_unlock(&cinfo->card_lock);
+ info->idle_stats.recv_idle = jiffies;
}
+ tty_schedule_flip(tty);
+end:
+ /* end of service */
+ cy_writeb(base_addr + (CyRIR << index), save_xir & 0x3f);
+ cy_writeb(base_addr + (CyCAR << index), save_car);
+}
+
+static void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip,
+ void __iomem *base_addr)
+{
+ struct cyclades_port *info;
+ int char_count, index = cinfo->bus_index;
+ u8 save_xir, channel, save_car, outch;
- if (status & CySRTransmit) { /* transmission interrupt */
- /* Since we only get here when the transmit buffer
- is empty, we know we can always stuff a dozen
- characters. */
+ /* Since we only get here when the transmit buffer
+ is empty, we know we can always stuff a dozen
+ characters. */
#ifdef CY_DEBUG_INTERRUPTS
- printk(KERN_DEBUG "cyy_interrupt: xmit intr, chip %d\n", chip);
+ printk(KERN_DEBUG "cyy_interrupt: xmit intr, chip %d\n", chip);
#endif
- /* determine the channel & change to that context */
- spin_lock(&cinfo->card_lock);
- save_xir = (u_char) readb(base_addr + (CyTIR << index));
- channel = (u_short) (save_xir & CyIRChannel);
- save_car = readb(base_addr + (CyCAR << index));
- cy_writeb(base_addr + (CyCAR << index), save_xir);
+ /* determine the channel & change to that context */
+ save_xir = readb(base_addr + (CyTIR << index));
+ channel = save_xir & CyIRChannel;
+ save_car = readb(base_addr + (CyCAR << index));
+ cy_writeb(base_addr + (CyCAR << index), save_xir);
- /* validate the port# (as configured and open) */
- if (channel + chip * 4 >= cinfo->nports) {
- cy_writeb(base_addr + (CySRER << index),
- readb(base_addr + (CySRER << index)) &
- ~CyTxRdy);
- goto txend;
- }
- info = &cinfo->ports[channel + chip * 4];
- if (info->tty == NULL) {
- cy_writeb(base_addr + (CySRER << index),
- readb(base_addr + (CySRER << index)) &
- ~CyTxRdy);
- goto txdone;
- }
+ /* validate the port# (as configured and open) */
+ if (channel + chip * 4 >= cinfo->nports) {
+ cy_writeb(base_addr + (CySRER << index),
+ readb(base_addr + (CySRER << index)) & ~CyTxRdy);
+ goto end;
+ }
+ info = &cinfo->ports[channel + chip * 4];
+ if (info->tty == NULL) {
+ cy_writeb(base_addr + (CySRER << index),
+ readb(base_addr + (CySRER << index)) & ~CyTxRdy);
+ goto end;
+ }
- /* load the on-chip space for outbound data */
- char_count = info->xmit_fifo_size;
+ /* load the on-chip space for outbound data */
+ char_count = info->xmit_fifo_size;
- if (info->x_char) { /* send special char */
- outch = info->x_char;
- cy_writeb(base_addr + (CyTDR << index), outch);
- char_count--;
- info->icount.tx++;
- info->x_char = 0;
- }
+ if (info->x_char) { /* send special char */
+ outch = info->x_char;
+ cy_writeb(base_addr + (CyTDR << index), outch);
+ char_count--;
+ info->icount.tx++;
+ info->x_char = 0;
+ }
- if (info->breakon || info->breakoff) {
- if (info->breakon) {
- cy_writeb(base_addr + (CyTDR << index), 0);
- cy_writeb(base_addr + (CyTDR << index), 0x81);
- info->breakon = 0;
- char_count -= 2;
- }
- if (info->breakoff) {
- cy_writeb(base_addr + (CyTDR << index), 0);
- cy_writeb(base_addr + (CyTDR << index), 0x83);
- info->breakoff = 0;
- char_count -= 2;
- }
+ if (info->breakon || info->breakoff) {
+ if (info->breakon) {
+ cy_writeb(base_addr + (CyTDR << index), 0);
+ cy_writeb(base_addr + (CyTDR << index), 0x81);
+ info->breakon = 0;
+ char_count -= 2;
+ }
+ if (info->breakoff) {
+ cy_writeb(base_addr + (CyTDR << index), 0);
+ cy_writeb(base_addr + (CyTDR << index), 0x83);
+ info->breakoff = 0;
+ char_count -= 2;
}
+ }
- while (char_count-- > 0) {
- if (!info->xmit_cnt) {
- if (readb(base_addr + (CySRER << index)) &
- CyTxMpty) {
- cy_writeb(base_addr + (CySRER << index),
- readb(base_addr +
- (CySRER << index)) &
+ while (char_count-- > 0) {
+ if (!info->xmit_cnt) {
+ if (readb(base_addr + (CySRER << index)) & CyTxMpty) {
+ cy_writeb(base_addr + (CySRER << index),
+ readb(base_addr + (CySRER << index)) &
~CyTxMpty);
- } else {
- cy_writeb(base_addr + (CySRER << index),
- (readb(base_addr +
- (CySRER << index)) &
+ } else {
+ cy_writeb(base_addr + (CySRER << index),
+ (readb(base_addr + (CySRER << index)) &
~CyTxRdy) | CyTxMpty);
- }
- goto txdone;
}
- if (info->xmit_buf == NULL) {
- cy_writeb(base_addr + (CySRER << index),
- readb(base_addr + (CySRER << index)) &
+ goto done;
+ }
+ if (info->xmit_buf == NULL) {
+ cy_writeb(base_addr + (CySRER << index),
+ readb(base_addr + (CySRER << index)) &
~CyTxRdy);
- goto txdone;
- }
- if (info->tty->stopped || info->tty->hw_stopped) {
- cy_writeb(base_addr + (CySRER << index),
- readb(base_addr + (CySRER << index)) &
+ goto done;
+ }
+ if (info->tty->stopped || info->tty->hw_stopped) {
+ cy_writeb(base_addr + (CySRER << index),
+ readb(base_addr + (CySRER << index)) &
~CyTxRdy);
- goto txdone;
- }
- /* Because the Embedded Transmit Commands have
- been enabled, we must check to see if the
- escape character, NULL, is being sent. If it
- is, we must ensure that there is room for it
- to be doubled in the output stream. Therefore
- we no longer advance the pointer when the
- character is fetched, but rather wait until
- after the check for a NULL output character.
- This is necessary because there may not be
- room for the two chars needed to send a NULL.)
- */
- outch = info->xmit_buf[info->xmit_tail];
- if (outch) {
+ goto done;
+ }
+ /* Because the Embedded Transmit Commands have been enabled,
+ * we must check to see if the escape character, NULL, is being
+ * sent. If it is, we must ensure that there is room for it to
+ * be doubled in the output stream. Therefore we no longer
+ * advance the pointer when the character is fetched, but
+ * rather wait until after the check for a NULL output
+ * character. This is necessary because there may not be room
+ * for the two chars needed to send a NULL.)
+ */
+ outch = info->xmit_buf[info->xmit_tail];
+ if (outch) {
+ info->xmit_cnt--;
+ info->xmit_tail = (info->xmit_tail + 1) &
+ (SERIAL_XMIT_SIZE - 1);
+ cy_writeb(base_addr + (CyTDR << index), outch);
+ info->icount.tx++;
+ } else {
+ if (char_count > 1) {
info->xmit_cnt--;
info->xmit_tail = (info->xmit_tail + 1) &
- (SERIAL_XMIT_SIZE - 1);
+ (SERIAL_XMIT_SIZE - 1);
cy_writeb(base_addr + (CyTDR << index), outch);
+ cy_writeb(base_addr + (CyTDR << index), 0);
info->icount.tx++;
- } else {
- if (char_count > 1) {
- info->xmit_cnt--;
- info->xmit_tail = (info->xmit_tail + 1)&
- (SERIAL_XMIT_SIZE - 1);
- cy_writeb(base_addr + (CyTDR << index),
- outch);
- cy_writeb(base_addr + (CyTDR << index),
- 0);
- info->icount.tx++;
- char_count--;
- }
+ char_count--;
}
}
-
-txdone:
- if (info->xmit_cnt < WAKEUP_CHARS) {
- cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
- }
-txend:
- /* end of service */
- cy_writeb(base_addr + (CyTIR << index), (save_xir & 0x3f));
- cy_writeb(base_addr + (CyCAR << index), (save_car));
- spin_unlock(&cinfo->card_lock);
}
- if (status & CySRModem) { /* modem interrupt */
+done:
+ tty_wakeup(info->tty);
+end:
+ /* end of service */
+ cy_writeb(base_addr + (CyTIR << index), save_xir & 0x3f);
+ cy_writeb(base_addr + (CyCAR << index), save_car);
+}
- /* determine the channel & change to that context */
- spin_lock(&cinfo->card_lock);
- save_xir = (u_char) readb(base_addr + (CyMIR << index));
- channel = (u_short) (save_xir & CyIRChannel);
- info = &cinfo->ports[channel + chip * 4];
- save_car = readb(base_addr + (CyCAR << index));
- cy_writeb(base_addr + (CyCAR << index), save_xir);
+static void cyy_chip_modem(struct cyclades_card *cinfo, int chip,
+ void __iomem *base_addr)
+{
+ struct cyclades_port *info;
+ int index = cinfo->bus_index;
+ u8 save_xir, channel, save_car, mdm_change, mdm_status;
- mdm_change = readb(base_addr + (CyMISR << index));
- mdm_status = readb(base_addr + (CyMSVR1 << index));
+ /* determine the channel & change to that context */
+ save_xir = readb(base_addr + (CyMIR << index));
+ channel = save_xir & CyIRChannel;
+ info = &cinfo->ports[channel + chip * 4];
+ save_car = readb(base_addr + (CyCAR << index));
+ cy_writeb(base_addr + (CyCAR << index), save_xir);
- if (info->tty) {
- if (mdm_change & CyANY_DELTA) {
- /* For statistics only */
- if (mdm_change & CyDCD)
- info->icount.dcd++;
- if (mdm_change & CyCTS)
- info->icount.cts++;
- if (mdm_change & CyDSR)
- info->icount.dsr++;
- if (mdm_change & CyRI)
- info->icount.rng++;
-
- cy_sched_event(info, Cy_EVENT_DELTA_WAKEUP);
- }
+ mdm_change = readb(base_addr + (CyMISR << index));
+ mdm_status = readb(base_addr + (CyMSVR1 << index));
- if ((mdm_change & CyDCD) &&
- (info->flags & ASYNC_CHECK_CD)) {
- if (mdm_status & CyDCD) {
- cy_sched_event(info,
- Cy_EVENT_OPEN_WAKEUP);
- } else {
- cy_sched_event(info, Cy_EVENT_HANGUP);
- }
- }
- if ((mdm_change & CyCTS) &&
- (info->flags & ASYNC_CTS_FLOW)) {
- if (info->tty->hw_stopped) {
- if (mdm_status & CyCTS) {
- /* cy_start isn't used
- because... !!! */
- info->tty->hw_stopped = 0;
- cy_writeb(base_addr +
- (CySRER << index),
- readb(base_addr +
- (CySRER <<
- index))|
- CyTxRdy);
- cy_sched_event(info,
- Cy_EVENT_WRITE_WAKEUP);
- }
- } else {
- if (!(mdm_status & CyCTS)) {
- /* cy_stop isn't used
- because ... !!! */
- info->tty->hw_stopped = 1;
- cy_writeb(base_addr +
- (CySRER << index),
- readb(base_addr +
- (CySRER <<
- index)) &
- ~CyTxRdy);
- }
- }
+ if (!info->tty)
+ goto end;
+
+ if (mdm_change & CyANY_DELTA) {
+ /* For statistics only */
+ if (mdm_change & CyDCD)
+ info->icount.dcd++;
+ if (mdm_change & CyCTS)
+ info->icount.cts++;
+ if (mdm_change & CyDSR)
+ info->icount.dsr++;
+ if (mdm_change & CyRI)
+ info->icount.rng++;
+
+ wake_up_interruptible(&info->delta_msr_wait);
+ }
+
+ if ((mdm_change & CyDCD) && (info->flags & ASYNC_CHECK_CD)) {
+ if (!(mdm_status & CyDCD)) {
+ tty_hangup(info->tty);
+ info->flags &= ~ASYNC_NORMAL_ACTIVE;
+ }
+ wake_up_interruptible(&info->open_wait);
+ }
+ if ((mdm_change & CyCTS) && (info->flags & ASYNC_CTS_FLOW)) {
+ if (info->tty->hw_stopped) {
+ if (mdm_status & CyCTS) {
+ /* cy_start isn't used
+ because... !!! */
+ info->tty->hw_stopped = 0;
+ cy_writeb(base_addr + (CySRER << index),
+ readb(base_addr + (CySRER << index)) |
+ CyTxRdy);
+ tty_wakeup(info->tty);
}
-/* if (mdm_change & CyDSR) {
+ } else {
+ if (!(mdm_status & CyCTS)) {
+ /* cy_stop isn't used
+ because ... !!! */
+ info->tty->hw_stopped = 1;
+ cy_writeb(base_addr + (CySRER << index),
+ readb(base_addr + (CySRER << index)) &
+ ~CyTxRdy);
}
- if (mdm_change & CyRI) {
- }*/
}
- /* end of service */
- cy_writeb(base_addr + (CyMIR << index), (save_xir & 0x3f));
- cy_writeb(base_addr + (CyCAR << index), save_car);
- spin_unlock(&cinfo->card_lock);
}
+/* if (mdm_change & CyDSR) {
+ }
+ if (mdm_change & CyRI) {
+ }*/
+end:
+ /* end of service */
+ cy_writeb(base_addr + (CyMIR << index), save_xir & 0x3f);
+ cy_writeb(base_addr + (CyCAR << index), save_car);
}
/* The real interrupt service routine is called
@@ -1432,10 +1315,8 @@ static irqreturn_t cyy_interrupt(int irq, void *dev_id)
int status;
struct cyclades_card *cinfo = dev_id;
void __iomem *base_addr, *card_base_addr;
- int chip;
+ unsigned int chip, too_many, had_work;
int index;
- int too_many;
- int had_work;
if (unlikely(cinfo == NULL)) {
#ifdef CY_DEBUG_INTERRUPTS
@@ -1470,11 +1351,16 @@ static irqreturn_t cyy_interrupt(int irq, void *dev_id)
chips to be checked in a round-robin fashion (after
draining each of a bunch (1000) of characters).
*/
- if (1000 < too_many++) {
+ if (1000 < too_many++)
break;
- }
- cyy_intr_chip(cinfo, chip, base_addr, status,
- index);
+ spin_lock(&cinfo->card_lock);
+ if (status & CySRReceive) /* rx intr */
+ cyy_chip_rx(cinfo, chip, base_addr);
+ if (status & CySRTransmit) /* tx intr */
+ cyy_chip_tx(cinfo, chip, base_addr);
+ if (status & CySRModem) /* modem intr */
+ cyy_chip_modem(cinfo, chip, base_addr);
+ spin_unlock(&cinfo->card_lock);
}
}
} while (had_work);
@@ -1529,7 +1415,7 @@ cyz_issue_cmd(struct cyclades_card *cinfo,
struct ZFW_CTRL __iomem *zfw_ctrl;
struct BOARD_CTRL __iomem *board_ctrl;
__u32 __iomem *pci_doorbell;
- int index;
+ unsigned int index;
firm_id = cinfo->base_addr + ID_ADDRESS;
if (!ISZLOADED(*cinfo)) {
@@ -1554,13 +1440,12 @@ cyz_issue_cmd(struct cyclades_card *cinfo,
return 0;
} /* cyz_issue_cmd */
-static void
-cyz_handle_rx(struct cyclades_port *info, struct CH_CTRL __iomem *ch_ctrl,
+static void cyz_handle_rx(struct cyclades_port *info,
struct BUF_CTRL __iomem *buf_ctrl)
{
struct cyclades_card *cinfo = info->card;
struct tty_struct *tty = info->tty;
- int char_count;
+ unsigned int char_count;
int len;
#ifdef BLOCKMOVE
unsigned char *buf;
@@ -1633,9 +1518,11 @@ cyz_handle_rx(struct cyclades_port *info, struct CH_CTRL __iomem *ch_ctrl,
char_count = rx_put - rx_get;
else
char_count = rx_put - rx_get + rx_bufsize;
- if (char_count >= (int)readl(&buf_ctrl->rx_threshold)) {
- cy_sched_event(info, Cy_EVENT_Z_RX_FULL);
- }
+ if (char_count >= readl(&buf_ctrl->rx_threshold) &&
+ !timer_pending(&cyz_rx_full_timer[
+ info->line]))
+ mod_timer(&cyz_rx_full_timer[info->line],
+ jiffies + 1);
#endif
info->idle_stats.recv_idle = jiffies;
tty_schedule_flip(tty);
@@ -1645,14 +1532,13 @@ cyz_handle_rx(struct cyclades_port *info, struct CH_CTRL __iomem *ch_ctrl,
}
}
-static void
-cyz_handle_tx(struct cyclades_port *info, struct CH_CTRL __iomem *ch_ctrl,
+static void cyz_handle_tx(struct cyclades_port *info,
struct BUF_CTRL __iomem *buf_ctrl)
{
struct cyclades_card *cinfo = info->card;
struct tty_struct *tty = info->tty;
- char data;
- int char_count;
+ u8 data;
+ unsigned int char_count;
#ifdef BLOCKMOVE
int small_count;
#endif
@@ -1716,10 +1602,8 @@ cyz_handle_tx(struct cyclades_port *info, struct CH_CTRL __iomem *ch_ctrl,
info->icount.tx++;
}
#endif
+ tty_wakeup(tty);
ztxdone:
- if (info->xmit_cnt < WAKEUP_CHARS) {
- cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
- }
/* Update tx_put */
cy_writel(&buf_ctrl->tx_put, tx_put);
}
@@ -1781,10 +1665,11 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
if ((fw_ver > 241 ? ((u_long) param) :
readl(&ch_ctrl->rs_status)) &
C_RS_DCD) {
- cy_sched_event(info,
- Cy_EVENT_OPEN_WAKEUP);
+ wake_up_interruptible(&info->open_wait);
} else {
- cy_sched_event(info, Cy_EVENT_HANGUP);
+ tty_hangup(info->tty);
+ wake_up_interruptible(&info->open_wait);
+ info->flags &= ~ASYNC_NORMAL_ACTIVE;
}
}
break;
@@ -1802,7 +1687,7 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
break;
#ifdef Z_WAKE
case C_CM_IOCTLW:
- cy_sched_event(info, Cy_EVENT_SHUTDOWN_WAKEUP);
+ complete(&info->shutdown_wait);
break;
#endif
#ifdef CONFIG_CYZ_INTR
@@ -1814,7 +1699,7 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
printk(KERN_DEBUG "cyz_interrupt: rcvd intr, card %d, "
"port %ld\n", info->card, channel);
#endif
- cyz_handle_rx(info, ch_ctrl, buf_ctrl);
+ cyz_handle_rx(info, buf_ctrl);
break;
case C_CM_TXBEMPTY:
case C_CM_TXLOWWM:
@@ -1824,7 +1709,7 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
printk(KERN_DEBUG "cyz_interrupt: xmit intr, card %d, "
"port %ld\n", info->card, channel);
#endif
- cyz_handle_tx(info, ch_ctrl, buf_ctrl);
+ cyz_handle_tx(info, buf_ctrl);
break;
#endif /* CONFIG_CYZ_INTR */
case C_CM_FATAL:
@@ -1834,7 +1719,7 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
break;
}
if (delta_count)
- cy_sched_event(info, Cy_EVENT_DELTA_WAKEUP);
+ wake_up_interruptible(&info->delta_msr_wait);
if (special_count)
tty_schedule_flip(tty);
}
@@ -1893,10 +1778,9 @@ static void cyz_poll(unsigned long arg)
struct FIRM_ID __iomem *firm_id;
struct ZFW_CTRL __iomem *zfw_ctrl;
struct BOARD_CTRL __iomem *board_ctrl;
- struct CH_CTRL __iomem *ch_ctrl;
struct BUF_CTRL __iomem *buf_ctrl;
unsigned long expires = jiffies + HZ;
- int card, port;
+ unsigned int port, card;
for (card = 0; card < NR_CARDS; card++) {
cinfo = &cy_card[card];
@@ -1923,12 +1807,11 @@ static void cyz_poll(unsigned long arg)
for (port = 0; port < cinfo->nports; port++) {
info = &cinfo->ports[port];
tty = info->tty;
- ch_ctrl = &(zfw_ctrl->ch_ctrl[port]);
buf_ctrl = &(zfw_ctrl->buf_ctrl[port]);
if (!info->throttle)
- cyz_handle_rx(info, ch_ctrl, buf_ctrl);
- cyz_handle_tx(info, ch_ctrl, buf_ctrl);
+ cyz_handle_rx(info, buf_ctrl);
+ cyz_handle_tx(info, buf_ctrl);
}
/* poll every 'cyz_polling_cycle' period */
expires = jiffies + cyz_polling_cycle;
@@ -2491,11 +2374,11 @@ block_til_ready(struct tty_struct *tty, struct file *filp,
static int cy_open(struct tty_struct *tty, struct file *filp)
{
struct cyclades_port *info;
- unsigned int i;
- int retval, line;
+ unsigned int i, line;
+ int retval;
line = tty->index;
- if ((line < 0) || (NR_PORTS <= line)) {
+ if ((tty->index < 0) || (NR_PORTS <= line)) {
return -ENODEV;
}
for (i = 0; i < NR_CARDS; i++)
@@ -2812,7 +2695,6 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
spin_lock_irqsave(&card->card_lock, flags);
tty->closing = 0;
- info->event = 0;
info->tty = NULL;
if (info->blocked_open) {
spin_unlock_irqrestore(&card->card_lock, flags);
@@ -4444,7 +4326,6 @@ static void cy_hangup(struct tty_struct *tty)
cy_flush_buffer(tty);
shutdown(info);
- info->event = 0;
info->count = 0;
#ifdef CY_DEBUG_COUNT
printk(KERN_DEBUG "cyc:cy_hangup (%d): setting count to 0\n",
@@ -4467,9 +4348,9 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo)
{
struct cyclades_port *info;
u32 uninitialized_var(mailbox);
- unsigned int nports;
+ unsigned int nports, port;
unsigned short chip_number;
- int uninitialized_var(index), port;
+ int uninitialized_var(index);
spin_lock_init(&cinfo->card_lock);
@@ -4502,7 +4383,6 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo)
info->closing_wait = CLOSING_WAIT_DELAY;
info->close_delay = 5 * HZ / 10;
- INIT_WORK(&info->tqueue, do_softint);
init_waitqueue_head(&info->open_wait);
init_waitqueue_head(&info->close_wait);
init_completion(&info->shutdown_wait);
@@ -5236,7 +5116,7 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
}
}
#endif /* CONFIG_CYZ_INTR */
- cy_card[card_no].num_chips = -1;
+ cy_card[card_no].num_chips = (unsigned int)-1;
}
/* set cy_card */
@@ -5480,13 +5360,13 @@ static int __init cy_init(void)
#ifdef CONFIG_PCI
/* look for pci boards */
retval = pci_register_driver(&cy_pci_driver);
- if (retval && !nboards)
- goto err_unr;
+ if (retval && !nboards) {
+ tty_unregister_driver(cy_serial_driver);
+ goto err_frtty;
+ }
#endif
return 0;
-err_unr:
- tty_unregister_driver(cy_serial_driver);
err_frtty:
put_tty_driver(cy_serial_driver);
err:
@@ -5496,7 +5376,7 @@ err:
static void __exit cy_cleanup_module(void)
{
struct cyclades_card *card;
- int i, e1;
+ unsigned int i, e1;
#ifndef CONFIG_CYZ_INTR
del_timer_sync(&cyz_timerlist);
@@ -5524,8 +5404,7 @@ static void __exit cy_cleanup_module(void)
#endif /* CONFIG_CYZ_INTR */
)
free_irq(card->irq, card);
- for (e1 = card->first_line;
- e1 < card->first_line +
+ for (e1 = card->first_line; e1 < card->first_line +
card->nports; e1++)
tty_unregister_device(cy_serial_driver, e1);
kfree(card->ports);
diff --git a/drivers/char/defkeymap.c_shipped b/drivers/char/defkeymap.c_shipped
index 453a2f1ffa15..0aa419a61767 100644
--- a/drivers/char/defkeymap.c_shipped
+++ b/drivers/char/defkeymap.c_shipped
@@ -222,7 +222,7 @@ char *func_table[MAX_NR_FUNC] = {
NULL,
};
-struct kbdiacr accent_table[MAX_DIACR] = {
+struct kbdiacruc accent_table[MAX_DIACR] = {
{'`', 'A', '\300'}, {'`', 'a', '\340'},
{'\'', 'A', '\301'}, {'\'', 'a', '\341'},
{'^', 'A', '\302'}, {'^', 'a', '\342'},
diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig
index 0b7ffa5191c6..ba3058dd39a7 100644
--- a/drivers/char/drm/Kconfig
+++ b/drivers/char/drm/Kconfig
@@ -4,7 +4,7 @@
# This driver provides support for the
# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
#
-config DRM
+menuconfig DRM
tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)"
depends on (AGP || AGP=n) && PCI && !EMULATED_CMPXCHG
help
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index 9dd0760dd87a..dde02a15fa59 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -559,8 +559,6 @@ struct drm_mm {
* a family of cards. There will one drm_device for each card present
* in this family
*/
-struct drm_device;
-
struct drm_driver {
int (*load) (struct drm_device *, unsigned long flags);
int (*firstopen) (struct drm_device *);
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c
index 856774fbe025..d24a6c2c2c24 100644
--- a/drivers/char/drm/drm_bufs.c
+++ b/drivers/char/drm/drm_bufs.c
@@ -1456,7 +1456,7 @@ int drm_freebufs(struct drm_device *dev, void *data,
buf = dma->buflist[idx];
if (buf->file_priv != file_priv) {
DRM_ERROR("Process %d freeing buffer not owned\n",
- current->pid);
+ task_pid_nr(current));
return -EINVAL;
}
drm_free_buffer(dev, buf);
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
index 72668b15e5ce..44a46268b02b 100644
--- a/drivers/char/drm/drm_drv.c
+++ b/drivers/char/drm/drm_drv.c
@@ -463,7 +463,7 @@ int drm_ioctl(struct inode *inode, struct file *filp,
++file_priv->ioctl_count;
DRM_DEBUG("pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n",
- current->pid, cmd, nr,
+ task_pid_nr(current), cmd, nr,
(long)old_encode_dev(file_priv->head->device),
file_priv->authenticated);
diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c
index f383fc37190c..3992f73299cc 100644
--- a/drivers/char/drm/drm_fops.c
+++ b/drivers/char/drm/drm_fops.c
@@ -234,7 +234,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
if (!drm_cpu_valid())
return -EINVAL;
- DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor);
+ DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor);
priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES);
if (!priv)
@@ -244,7 +244,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
filp->private_data = priv;
priv->filp = filp;
priv->uid = current->euid;
- priv->pid = current->pid;
+ priv->pid = task_pid_nr(current);
priv->minor = minor;
priv->head = drm_heads[minor];
priv->ioctl_count = 0;
@@ -339,7 +339,8 @@ int drm_release(struct inode *inode, struct file *filp)
*/
DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
- current->pid, (long)old_encode_dev(file_priv->head->device),
+ task_pid_nr(current),
+ (long)old_encode_dev(file_priv->head->device),
dev->open_count);
if (dev->driver->reclaim_buffers_locked && dev->lock.hw_lock) {
diff --git a/drivers/char/drm/drm_hashtab.c b/drivers/char/drm/drm_hashtab.c
index 3ad319070704..4b8e7db5a232 100644
--- a/drivers/char/drm/drm_hashtab.c
+++ b/drivers/char/drm/drm_hashtab.c
@@ -29,7 +29,7 @@
* Simple open hash tab implementation.
*
* Authors:
- * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
*/
#include "drmP.h"
diff --git a/drivers/char/drm/drm_hashtab.h b/drivers/char/drm/drm_hashtab.h
index 0f1376774168..573e333ac457 100644
--- a/drivers/char/drm/drm_hashtab.h
+++ b/drivers/char/drm/drm_hashtab.h
@@ -29,7 +29,7 @@
* Simple open hash tab implementation.
*
* Authors:
- * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
*/
#ifndef DRM_HASHTAB_H
diff --git a/drivers/char/drm/drm_ioctl.c b/drivers/char/drm/drm_ioctl.c
index d9be14624526..3cbebf868e68 100644
--- a/drivers/char/drm/drm_ioctl.c
+++ b/drivers/char/drm/drm_ioctl.c
@@ -272,7 +272,7 @@ int drm_getstats(struct drm_device *dev, void *data,
struct drm_stats *stats = data;
int i;
- memset(stats, 0, sizeof(stats));
+ memset(stats, 0, sizeof(*stats));
mutex_lock(&dev->struct_mutex);
diff --git a/drivers/char/drm/drm_lock.c b/drivers/char/drm/drm_lock.c
index c6b73e744d67..bea2a7d5b2b2 100644
--- a/drivers/char/drm/drm_lock.c
+++ b/drivers/char/drm/drm_lock.c
@@ -58,12 +58,12 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
if (lock->context == DRM_KERNEL_CONTEXT) {
DRM_ERROR("Process %d using kernel context %d\n",
- current->pid, lock->context);
+ task_pid_nr(current), lock->context);
return -EINVAL;
}
DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
- lock->context, current->pid,
+ lock->context, task_pid_nr(current),
dev->lock.hw_lock->lock, lock->flags);
if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE))
@@ -153,7 +153,7 @@ int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv)
if (lock->context == DRM_KERNEL_CONTEXT) {
DRM_ERROR("Process %d using kernel context %d\n",
- current->pid, lock->context);
+ task_pid_nr(current), lock->context);
return -EINVAL;
}
diff --git a/drivers/char/drm/drm_mm.c b/drivers/char/drm/drm_mm.c
index 3e6bc14f7441..86f4eb61a6a4 100644
--- a/drivers/char/drm/drm_mm.c
+++ b/drivers/char/drm/drm_mm.c
@@ -38,7 +38,7 @@
* Aligned allocations can also see improvement.
*
* Authors:
- * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
*/
#include "drmP.h"
diff --git a/drivers/char/drm/drm_os_linux.h b/drivers/char/drm/drm_os_linux.h
index 114e54e0f61b..daa69c9d8977 100644
--- a/drivers/char/drm/drm_os_linux.h
+++ b/drivers/char/drm/drm_os_linux.h
@@ -7,7 +7,7 @@
#include <linux/delay.h>
/** Current process ID */
-#define DRM_CURRENTPID current->pid
+#define DRM_CURRENTPID task_pid_nr(current)
#define DRM_SUSER(p) capable(CAP_SYS_ADMIN)
#define DRM_UDELAY(d) udelay(d)
/** Read a byte from a MMIO region */
@@ -62,14 +62,6 @@ static __inline__ int mtrr_del(int reg, unsigned long base, unsigned long size)
#endif
-/** For data going into the kernel through the ioctl argument */
-#define DRM_COPY_FROM_USER_IOCTL(arg1, arg2, arg3) \
- if ( copy_from_user(&arg1, arg2, arg3) ) \
- return -EFAULT
-/** For data going from the kernel through the ioctl argument */
-#define DRM_COPY_TO_USER_IOCTL(arg1, arg2, arg3) \
- if ( copy_to_user(arg1, &arg2, arg3) ) \
- return -EFAULT
/** Other copying of data to kernel space */
#define DRM_COPY_FROM_USER(arg1, arg2, arg3) \
copy_from_user(arg1, arg2, arg3)
diff --git a/drivers/char/drm/drm_pci.c b/drivers/char/drm/drm_pci.c
index e292bb0eaca2..b55d5bc6ea61 100644
--- a/drivers/char/drm/drm_pci.c
+++ b/drivers/char/drm/drm_pci.c
@@ -8,12 +8,12 @@
* \todo Implement the remaining ioctl's for the PCI pools.
* \todo The wrappers here are so thin that they would be better off inlined..
*
- * \author Jose Fonseca <jrfonseca@tungstengraphics.com>
+ * \author José Fonseca <jrfonseca@tungstengraphics.com>
* \author Leif Delgass <ldelgass@retinalburn.net>
*/
/*
- * Copyright 2003 Jos�Fonseca.
+ * Copyright 2003 José Fonseca.
* Copyright 2003 Leif Delgass.
* All Rights Reserved.
*
diff --git a/drivers/char/drm/drm_sarea.h b/drivers/char/drm/drm_sarea.h
index f5466966081e..e040f47f369f 100644
--- a/drivers/char/drm/drm_sarea.h
+++ b/drivers/char/drm/drm_sarea.h
@@ -2,7 +2,7 @@
* \file drm_sarea.h
* \brief SAREA definitions
*
- * \author Michel Dänzer <michel@daenzer.net>
+ * \author Michel Dänzer <michel@daenzer.net>
*/
/*
diff --git a/drivers/char/drm/drm_sman.c b/drivers/char/drm/drm_sman.c
index 8421a93946d8..926f146390ce 100644
--- a/drivers/char/drm/drm_sman.c
+++ b/drivers/char/drm/drm_sman.c
@@ -33,7 +33,7 @@
* struct or a context identifier.
*
* Authors:
- * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
*/
#include "drm_sman.h"
diff --git a/drivers/char/drm/drm_sman.h b/drivers/char/drm/drm_sman.h
index 39a39fefeef1..08ecf83ad5d4 100644
--- a/drivers/char/drm/drm_sman.h
+++ b/drivers/char/drm/drm_sman.h
@@ -33,7 +33,7 @@
* struct or a context identifier.
*
* Authors:
- * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
*/
#ifndef DRM_SMAN_H
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
index 8e841bdee6dc..eb381a7c5bee 100644
--- a/drivers/char/drm/i810_dma.c
+++ b/drivers/char/drm/i810_dma.c
@@ -1024,7 +1024,7 @@ static int i810_getbuf(struct drm_device *dev, void *data,
retcode = i810_dma_get_buffer(dev, d, file_priv);
DRM_DEBUG("i810_dma: %d returning %d, granted = %d\n",
- current->pid, retcode, d->granted);
+ task_pid_nr(current), retcode, d->granted);
sarea_priv->last_dispatch = (int)hw_status[5];
diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c
index 43a1f78712d6..69a363edb0d2 100644
--- a/drivers/char/drm/i830_dma.c
+++ b/drivers/char/drm/i830_dma.c
@@ -1409,7 +1409,7 @@ static int i830_getbuf(struct drm_device *dev, void *data,
retcode = i830_dma_get_buffer(dev, d, file_priv);
DRM_DEBUG("i830_dma: %d returning %d, granted = %d\n",
- current->pid, retcode, d->granted);
+ task_pid_nr(current), retcode, d->granted);
sarea_priv->last_dispatch = (int)hw_status[5];
diff --git a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h
index 250d2aa46581..5041bd8dbed8 100644
--- a/drivers/char/drm/r128_drv.h
+++ b/drivers/char/drm/r128_drv.h
@@ -29,7 +29,7 @@
* Rickard E. (Rik) Faith <faith@valinux.com>
* Kevin E. Martin <martin@valinux.com>
* Gareth Hughes <gareth@valinux.com>
- * Michel D�zer <daenzerm@student.ethz.ch>
+ * Michel Dänzer <daenzerm@student.ethz.ch>
*/
#ifndef __R128_DRV_H__
diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c
index 335423c5c186..24fca8ec1379 100644
--- a/drivers/char/drm/radeon_cp.c
+++ b/drivers/char/drm/radeon_cp.c
@@ -1679,7 +1679,7 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init)
dev_priv->gart_info.bus_addr =
dev_priv->pcigart_offset + dev_priv->fb_location;
dev_priv->gart_info.mapping.offset =
- dev_priv->gart_info.bus_addr;
+ dev_priv->pcigart_offset + dev_priv->fb_aper_offset;
dev_priv->gart_info.mapping.size =
dev_priv->gart_info.table_size;
@@ -2275,7 +2275,8 @@ int radeon_driver_firstopen(struct drm_device *dev)
if (ret != 0)
return ret;
- ret = drm_addmap(dev, drm_get_resource_start(dev, 0),
+ dev_priv->fb_aper_offset = drm_get_resource_start(dev, 0);
+ ret = drm_addmap(dev, dev_priv->fb_aper_offset,
drm_get_resource_len(dev, 0), _DRM_FRAME_BUFFER,
_DRM_WRITE_COMBINING, &map);
if (ret != 0)
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
index e4077bc212b3..bfbb60a9298c 100644
--- a/drivers/char/drm/radeon_drv.h
+++ b/drivers/char/drm/radeon_drv.h
@@ -293,6 +293,7 @@ typedef struct drm_radeon_private {
/* starting from here on, data is preserved accross an open */
uint32_t flags; /* see radeon_chip_flags */
+ unsigned long fb_aper_offset;
} drm_radeon_private_t;
typedef struct drm_radeon_buf_priv {
diff --git a/drivers/char/drm/radeon_irq.c b/drivers/char/drm/radeon_irq.c
index f89e57665b64..84f5bc36252b 100644
--- a/drivers/char/drm/radeon_irq.c
+++ b/drivers/char/drm/radeon_irq.c
@@ -27,7 +27,7 @@
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
- * Michel D�zer <michel@daenzer.net>
+ * Michel Dänzer <michel@daenzer.net>
*/
#include "drmP.h"
@@ -144,8 +144,8 @@ static int radeon_wait_irq(struct drm_device * dev, int swi_nr)
return ret;
}
-int radeon_driver_vblank_do_wait(struct drm_device * dev, unsigned int *sequence,
- int crtc)
+static int radeon_driver_vblank_do_wait(struct drm_device * dev,
+ unsigned int *sequence, int crtc)
{
drm_radeon_private_t *dev_priv =
(drm_radeon_private_t *) dev->dev_private;
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
index 69c9f2febf43..f824f2f5fdc2 100644
--- a/drivers/char/drm/radeon_state.c
+++ b/drivers/char/drm/radeon_state.c
@@ -3005,7 +3005,7 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil
/*
* This ioctl() doesn't work on 64-bit platforms because hw_lock is a
* pointer which can't fit into an int-sized variable. According to
- * Michel Dänzer, the ioctl() is only used on embedded platforms, so
+ * Michel Dänzer, the ioctl() is only used on embedded platforms, so
* not supporting it shouldn't be a problem. If the same functionality
* is needed on 64-bit platforms, a new ioctl() would have to be added,
* so backwards-compatibility for the embedded platforms can be
diff --git a/drivers/char/drm/savage_bci.c b/drivers/char/drm/savage_bci.c
index 59484d56b333..d465b2f9c1cd 100644
--- a/drivers/char/drm/savage_bci.c
+++ b/drivers/char/drm/savage_bci.c
@@ -968,9 +968,6 @@ static int savage_bci_event_wait(struct drm_device *dev, void *data, struct drm_
DRM_DEBUG("\n");
- DRM_COPY_FROM_USER_IOCTL(event, (drm_savage_event_wait_t __user *) data,
- sizeof(event));
-
UPDATE_EVENT_COUNTER();
if (dev_priv->status_ptr)
hw_e = dev_priv->status_ptr[1] & 0xffff;
diff --git a/drivers/char/drm/sis_mm.c b/drivers/char/drm/sis_mm.c
index 8c66838ff515..a6b7ccdaf73d 100644
--- a/drivers/char/drm/sis_mm.c
+++ b/drivers/char/drm/sis_mm.c
@@ -28,7 +28,7 @@
/*
* Authors:
- * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
*/
#include "drmP.h"
@@ -134,6 +134,7 @@ static int sis_drm_alloc(struct drm_device *dev, struct drm_file *file_priv,
dev_priv->agp_initialized)) {
DRM_ERROR
("Attempt to allocate from uninitialized memory manager.\n");
+ mutex_unlock(&dev->struct_mutex);
return -EINVAL;
}
diff --git a/drivers/char/drm/via_mm.c b/drivers/char/drm/via_mm.c
index 9afc1684348d..3ffbf8649833 100644
--- a/drivers/char/drm/via_mm.c
+++ b/drivers/char/drm/via_mm.c
@@ -22,7 +22,7 @@
* DEALINGS IN THE SOFTWARE.
*/
/*
- * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
*/
#include "drmP.h"
diff --git a/drivers/char/drm/via_verifier.h b/drivers/char/drm/via_verifier.h
index 28b50296a7bd..d6f8214b69f5 100644
--- a/drivers/char/drm/via_verifier.h
+++ b/drivers/char/drm/via_verifier.h
@@ -20,7 +20,7 @@
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
- * Author: Thomas Hellström 2004.
+ * Author: Thomas Hellström 2004.
*/
#ifndef _VIA_VERIFIER_H_
diff --git a/drivers/char/ec3104_keyb.c b/drivers/char/ec3104_keyb.c
deleted file mode 100644
index 020011495d91..000000000000
--- a/drivers/char/ec3104_keyb.c
+++ /dev/null
@@ -1,457 +0,0 @@
-/*
- * linux/drivers/char/ec3104_keyb.c
- *
- * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
- *
- * based on linux/drivers/char/pc_keyb.c, which had the following comments:
- *
- * Separation of the PC low-level part by Geert Uytterhoeven, May 1997
- * See keyboard.c for the whole history.
- *
- * Major cleanup by Martin Mares, May 1997
- *
- * Combined the keyboard and PS/2 mouse handling into one file,
- * because they share the same hardware.
- * Johan Myreen <jem@iki.fi> 1998-10-08.
- *
- * Code fixes to handle mouse ACKs properly.
- * C. Scott Ananian <cananian@alumni.princeton.edu> 1999-01-29.
- */
-/* EC3104 note:
- * This code was written without any documentation about the EC3104 chip. While
- * I hope I got most of the basic functionality right, the register names I use
- * are most likely completely different from those in the chip documentation.
- *
- * If you have any further information about the EC3104, please tell me
- * (prumpf@tux.org).
- */
-
-
-#include <linux/spinlock.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/mm.h>
-#include <linux/signal.h>
-#include <linux/init.h>
-#include <linux/kbd_ll.h>
-#include <linux/delay.h>
-#include <linux/random.h>
-#include <linux/poll.h>
-#include <linux/miscdevice.h>
-#include <linux/slab.h>
-#include <linux/kbd_kern.h>
-#include <linux/bitops.h>
-
-#include <asm/keyboard.h>
-#include <asm/uaccess.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-#include <asm/ec3104.h>
-
-#include <asm/io.h>
-
-/* Some configuration switches are present in the include file... */
-
-#include <linux/pc_keyb.h>
-
-#define MSR_CTS 0x10
-#define MCR_RTS 0x02
-#define LSR_DR 0x01
-#define LSR_BOTH_EMPTY 0x60
-
-static struct e5_struct {
- u8 packet[8];
- int pos;
- int length;
-
- u8 cached_mcr;
- u8 last_msr;
-} ec3104_keyb;
-
-/* Simple translation table for the SysRq keys */
-
-
-#ifdef CONFIG_MAGIC_SYSRQ
-unsigned char ec3104_kbd_sysrq_xlate[128] =
- "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
- "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
- "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
- "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
- "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
- "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
- "\r\000/"; /* 0x60 - 0x6f */
-#endif
-
-static void kbd_write_command_w(int data);
-static void kbd_write_output_w(int data);
-#ifdef CONFIG_PSMOUSE
-static void aux_write_ack(int val);
-static void __aux_write_ack(int val);
-#endif
-
-static DEFINE_SPINLOCK(kbd_controller_lock);
-static unsigned char handle_kbd_event(void);
-
-/* used only by send_data - set by keyboard_interrupt */
-static volatile unsigned char reply_expected;
-static volatile unsigned char acknowledge;
-static volatile unsigned char resend;
-
-
-int ec3104_kbd_setkeycode(unsigned int scancode, unsigned int keycode)
-{
- return 0;
-}
-
-int ec3104_kbd_getkeycode(unsigned int scancode)
-{
- return 0;
-}
-
-
-/* yes, it probably would be faster to use an array. I don't care. */
-
-static inline unsigned char ec3104_scan2key(unsigned char scancode)
-{
- switch (scancode) {
- case 1: /* '`' */
- return 41;
-
- case 2 ... 27:
- return scancode;
-
- case 28: /* '\\' */
- return 43;
-
- case 29 ... 39:
- return scancode + 1;
-
- case 40: /* '\r' */
- return 28;
-
- case 41 ... 50:
- return scancode + 3;
-
- case 51: /* ' ' */
- return 57;
-
- case 52: /* escape */
- return 1;
-
- case 54: /* insert/delete (labelled delete) */
- /* this should arguably be 110, but I'd like to have ctrl-alt-del
- * working with a standard keymap */
- return 111;
-
- case 55: /* left */
- return 105;
- case 56: /* home */
- return 102;
- case 57: /* end */
- return 107;
- case 58: /* up */
- return 103;
- case 59: /* down */
- return 108;
- case 60: /* pgup */
- return 104;
- case 61: /* pgdown */
- return 109;
- case 62: /* right */
- return 106;
-
- case 79 ... 88: /* f1 - f10 */
- return scancode - 20;
-
- case 89 ... 90: /* f11 - f12 */
- return scancode - 2;
-
- case 91: /* left shift */
- return 42;
-
- case 92: /* right shift */
- return 54;
-
- case 93: /* left alt */
- return 56;
- case 94: /* right alt */
- return 100;
- case 95: /* left ctrl */
- return 29;
- case 96: /* right ctrl */
- return 97;
-
- case 97: /* caps lock */
- return 58;
- case 102: /* left windows */
- return 125;
- case 103: /* right windows */
- return 126;
-
- case 106: /* Fn */
- /* this is wrong. */
- return 84;
-
- default:
- return 0;
- }
-}
-
-int ec3104_kbd_translate(unsigned char scancode, unsigned char *keycode,
- char raw_mode)
-{
- scancode &= 0x7f;
-
- *keycode = ec3104_scan2key(scancode);
-
- return 1;
-}
-
-char ec3104_kbd_unexpected_up(unsigned char keycode)
-{
- return 0200;
-}
-
-static inline void handle_keyboard_event(unsigned char scancode)
-{
-#ifdef CONFIG_VT
- handle_scancode(scancode, !(scancode & 0x80));
-#endif
- tasklet_schedule(&keyboard_tasklet);
-}
-
-void ec3104_kbd_leds(unsigned char leds)
-{
-}
-
-static u8 e5_checksum(u8 *packet, int count)
-{
- int i;
- u8 sum = 0;
-
- for (i=0; i<count; i++)
- sum ^= packet[i];
-
- if (sum & 0x80)
- sum ^= 0xc0;
-
- return sum;
-}
-
-static void e5_wait_for_cts(struct e5_struct *k)
-{
- u8 msr;
-
- do {
- msr = ctrl_inb(EC3104_SER4_MSR);
- } while (!(msr & MSR_CTS));
-}
-
-
-static void e5_send_byte(u8 byte, struct e5_struct *k)
-{
- u8 status;
-
- do {
- status = ctrl_inb(EC3104_SER4_LSR);
- } while ((status & LSR_BOTH_EMPTY) != LSR_BOTH_EMPTY);
-
- printk("<%02x>", byte);
-
- ctrl_outb(byte, EC3104_SER4_DATA);
-
- do {
- status = ctrl_inb(EC3104_SER4_LSR);
- } while ((status & LSR_BOTH_EMPTY) != LSR_BOTH_EMPTY);
-
-}
-
-static int e5_send_packet(u8 *packet, int count, struct e5_struct *k)
-{
- int i;
-
- disable_irq(EC3104_IRQ_SER4);
-
- if (k->cached_mcr & MCR_RTS) {
- printk("e5_send_packet: too slow\n");
- enable_irq(EC3104_IRQ_SER4);
- return -EAGAIN;
- }
-
- k->cached_mcr |= MCR_RTS;
- ctrl_outb(k->cached_mcr, EC3104_SER4_MCR);
-
- e5_wait_for_cts(k);
-
- printk("p: ");
-
- for(i=0; i<count; i++)
- e5_send_byte(packet[i], k);
-
- e5_send_byte(e5_checksum(packet, count), k);
-
- printk("\n");
-
- udelay(1500);
-
- k->cached_mcr &= ~MCR_RTS;
- ctrl_outb(k->cached_mcr, EC3104_SER4_MCR);
-
- set_current_state(TASK_UNINTERRUPTIBLE);
-
-
-
- enable_irq(EC3104_IRQ_SER4);
-
-
-
- return 0;
-}
-
-/*
- * E5 packets we know about:
- * E5->host 0x80 0x05 <checksum> - resend packet
- * host->E5 0x83 0x43 <contrast> - set LCD contrast
- * host->E5 0x85 0x41 0x02 <brightness> 0x02 - set LCD backlight
- * E5->host 0x87 <ps2 packet> 0x00 <checksum> - external PS2
- * E5->host 0x88 <scancode> <checksum> - key press
- */
-
-static void e5_receive(struct e5_struct *k)
-{
- k->packet[k->pos++] = ctrl_inb(EC3104_SER4_DATA);
-
- if (k->pos == 1) {
- switch(k->packet[0]) {
- case 0x80:
- k->length = 3;
- break;
-
- case 0x87: /* PS2 ext */
- k->length = 6;
- break;
-
- case 0x88: /* keyboard */
- k->length = 3;
- break;
-
- default:
- k->length = 1;
- printk(KERN_WARNING "unknown E5 packet %02x\n",
- k->packet[0]);
- }
- }
-
- if (k->pos == k->length) {
- int i;
-
- if (e5_checksum(k->packet, k->length) != 0)
- printk(KERN_WARNING "E5: wrong checksum\n");
-
-#if 0
- printk("E5 packet [");
- for(i=0; i<k->length; i++) {
- printk("%02x ", k->packet[i]);
- }
-
- printk("(%02x)]\n", e5_checksum(k->packet, k->length-1));
-#endif
-
- switch(k->packet[0]) {
- case 0x80:
- case 0x88:
- handle_keyboard_event(k->packet[1]);
- break;
- }
-
- k->pos = k->length = 0;
- }
-}
-
-static void ec3104_keyb_interrupt(int irq, void *data)
-{
- struct e5_struct *k = &ec3104_keyb;
- u8 msr, lsr;
-
- msr = ctrl_inb(EC3104_SER4_MSR);
-
- if ((msr & MSR_CTS) && !(k->last_msr & MSR_CTS)) {
- if (k->cached_mcr & MCR_RTS)
- printk("confused: RTS already high\n");
- /* CTS went high. Send RTS. */
- k->cached_mcr |= MCR_RTS;
-
- ctrl_outb(k->cached_mcr, EC3104_SER4_MCR);
- } else if ((!(msr & MSR_CTS)) && (k->last_msr & MSR_CTS)) {
- /* CTS went low. */
- if (!(k->cached_mcr & MCR_RTS))
- printk("confused: RTS already low\n");
-
- k->cached_mcr &= ~MCR_RTS;
-
- ctrl_outb(k->cached_mcr, EC3104_SER4_MCR);
- }
-
- k->last_msr = msr;
-
- lsr = ctrl_inb(EC3104_SER4_LSR);
-
- if (lsr & LSR_DR)
- e5_receive(k);
-}
-
-static void ec3104_keyb_clear_state(void)
-{
- struct e5_struct *k = &ec3104_keyb;
- u8 msr, lsr;
-
- /* we want CTS to be low */
- k->last_msr = 0;
-
- for (;;) {
- msleep(100);
-
- msr = ctrl_inb(EC3104_SER4_MSR);
-
- lsr = ctrl_inb(EC3104_SER4_LSR);
-
- if (lsr & LSR_DR) {
- e5_receive(k);
- continue;
- }
-
- if ((msr & MSR_CTS) && !(k->last_msr & MSR_CTS)) {
- if (k->cached_mcr & MCR_RTS)
- printk("confused: RTS already high\n");
- /* CTS went high. Send RTS. */
- k->cached_mcr |= MCR_RTS;
-
- ctrl_outb(k->cached_mcr, EC3104_SER4_MCR);
- } else if ((!(msr & MSR_CTS)) && (k->last_msr & MSR_CTS)) {
- /* CTS went low. */
- if (!(k->cached_mcr & MCR_RTS))
- printk("confused: RTS already low\n");
-
- k->cached_mcr &= ~MCR_RTS;
-
- ctrl_outb(k->cached_mcr, EC3104_SER4_MCR);
- } else
- break;
-
- k->last_msr = msr;
-
- continue;
- }
-}
-
-void __init ec3104_kbd_init_hw(void)
-{
- ec3104_keyb.last_msr = ctrl_inb(EC3104_SER4_MSR);
- ec3104_keyb.cached_mcr = ctrl_inb(EC3104_SER4_MCR);
-
- ec3104_keyb_clear_state();
-
- /* Ok, finally allocate the IRQ, and off we go.. */
- request_irq(EC3104_IRQ_SER4, ec3104_keyb_interrupt, 0, "keyboard", NULL);
-}
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
index c6c56fb8ba50..ffcecde9e2a5 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -1,34 +1,30 @@
/*
-
-
Copyright (C) 1996 Digi International.
-
+
For technical support please email digiLinux@dgii.com or
call Digi tech support at (612) 912-3456
** This driver is no longer supported by Digi **
- Much of this design and code came from epca.c which was
- copyright (C) 1994, 1995 Troy De Jongh, and subsquently
- modified by David Nugent, Christoph Lameter, Mike McLagan.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
---------------------------------------------------------------------------- */
-/* See README.epca for change history --DAT*/
+ Much of this design and code came from epca.c which was
+ copyright (C) 1994, 1995 Troy De Jongh, and subsquently
+ modified by David Nugent, Christoph Lameter, Mike McLagan.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+/* See README.epca for change history --DAT*/
#include <linux/module.h>
#include <linux/kernel.h>
@@ -54,13 +50,10 @@
#include "epca.h"
#include "epcaconfig.h"
-/* ---------------------- Begin defines ------------------------ */
-
#define VERSION "1.3.0.1-LK2.6"
/* This major needs to be submitted to Linux to join the majors list */
-
-#define DIGIINFOMAJOR 35 /* For Digi specific ioctl */
+#define DIGIINFOMAJOR 35 /* For Digi specific ioctl */
#define MAXCARDS 7
@@ -68,60 +61,48 @@
#define PFX "epca: "
-/* ----------------- Begin global definitions ------------------- */
-
static int nbdevs, num_cards, liloconfig;
static int digi_poller_inhibited = 1 ;
static int setup_error_code;
static int invalid_lilo_config;
-/* The ISA boards do window flipping into the same spaces so its only sane
- with a single lock. It's still pretty efficient */
-
+/*
+ * The ISA boards do window flipping into the same spaces so its only sane with
+ * a single lock. It's still pretty efficient.
+ */
static DEFINE_SPINLOCK(epca_lock);
-/* -----------------------------------------------------------------------
- MAXBOARDS is typically 12, but ISA and EISA cards are restricted to
- 7 below.
---------------------------------------------------------------------------*/
+/* MAXBOARDS is typically 12, but ISA and EISA cards are restricted to 7 below. */
static struct board_info boards[MAXBOARDS];
-
-/* ------------- Begin structures used for driver registeration ---------- */
-
static struct tty_driver *pc_driver;
static struct tty_driver *pc_info;
/* ------------------ Begin Digi specific structures -------------------- */
-/* ------------------------------------------------------------------------
- digi_channels represents an array of structures that keep track of
- each channel of the Digi product. Information such as transmit and
- receive pointers, termio data, and signal definitions (DTR, CTS, etc ...)
- are stored here. This structure is NOT used to overlay the cards
- physical channel structure.
--------------------------------------------------------------------------- */
-
+/*
+ * digi_channels represents an array of structures that keep track of each
+ * channel of the Digi product. Information such as transmit and receive
+ * pointers, termio data, and signal definitions (DTR, CTS, etc ...) are stored
+ * here. This structure is NOT used to overlay the cards physical channel
+ * structure.
+ */
static struct channel digi_channels[MAX_ALLOC];
-/* ------------------------------------------------------------------------
- card_ptr is an array used to hold the address of the
- first channel structure of each card. This array will hold
- the addresses of various channels located in digi_channels.
--------------------------------------------------------------------------- */
+/*
+ * card_ptr is an array used to hold the address of the first channel structure
+ * of each card. This array will hold the addresses of various channels located
+ * in digi_channels.
+ */
static struct channel *card_ptr[MAXCARDS];
static struct timer_list epca_timer;
-/* ---------------------- Begin function prototypes --------------------- */
-
-/* ----------------------------------------------------------------------
- Begin generic memory functions. These functions will be alias
- (point at) more specific functions dependent on the board being
- configured.
------------------------------------------------------------------------ */
-
+/*
+ * Begin generic memory functions. These functions will be alias (point at)
+ * more specific functions dependent on the board being configured.
+ */
static void memwinon(struct board_info *b, unsigned int win);
static void memwinoff(struct board_info *b, unsigned int win);
static void globalwinon(struct channel *ch);
@@ -170,8 +151,6 @@ static void dummy_memoff(struct channel *ch);
static void dummy_assertgwinon(struct channel *ch);
static void dummy_assertmemoff(struct channel *ch);
-/* ------------------- Begin declare functions ----------------------- */
-
static struct channel *verifyChannel(struct tty_struct *);
static void pc_sched_event(struct channel *, int);
static void epca_error(int, char *);
@@ -213,62 +192,55 @@ static int pc_write(struct tty_struct *, const unsigned char *, int);
static int pc_init(void);
static int init_PCI(void);
-
-/* ------------------------------------------------------------------
- Table of functions for each board to handle memory. Mantaining
- parallelism is a *very* good idea here. The idea is for the
- runtime code to blindly call these functions, not knowing/caring
- about the underlying hardware. This stuff should contain no
- conditionals; if more functionality is needed a different entry
- should be established. These calls are the interface calls and
- are the only functions that should be accessed. Anyone caught
- making direct calls deserves what they get.
--------------------------------------------------------------------- */
-
+/*
+ * Table of functions for each board to handle memory. Mantaining parallelism
+ * is a *very* good idea here. The idea is for the runtime code to blindly call
+ * these functions, not knowing/caring about the underlying hardware. This
+ * stuff should contain no conditionals; if more functionality is needed a
+ * different entry should be established. These calls are the interface calls
+ * and are the only functions that should be accessed. Anyone caught making
+ * direct calls deserves what they get.
+ */
static void memwinon(struct board_info *b, unsigned int win)
{
- (b->memwinon)(b, win);
+ b->memwinon(b, win);
}
static void memwinoff(struct board_info *b, unsigned int win)
{
- (b->memwinoff)(b, win);
+ b->memwinoff(b, win);
}
static void globalwinon(struct channel *ch)
{
- (ch->board->globalwinon)(ch);
+ ch->board->globalwinon(ch);
}
static void rxwinon(struct channel *ch)
{
- (ch->board->rxwinon)(ch);
+ ch->board->rxwinon(ch);
}
static void txwinon(struct channel *ch)
{
- (ch->board->txwinon)(ch);
+ ch->board->txwinon(ch);
}
static void memoff(struct channel *ch)
{
- (ch->board->memoff)(ch);
+ ch->board->memoff(ch);
}
static void assertgwinon(struct channel *ch)
{
- (ch->board->assertgwinon)(ch);
+ ch->board->assertgwinon(ch);
}
static void assertmemoff(struct channel *ch)
{
- (ch->board->assertmemoff)(ch);
+ ch->board->assertmemoff(ch);
}
-/* ---------------------------------------------------------
- PCXEM windowing is the same as that used in the PCXR
- and CX series cards.
------------------------------------------------------------- */
-
+/* PCXEM windowing is the same as that used in the PCXR and CX series cards. */
static void pcxem_memwinon(struct board_info *b, unsigned int win)
{
outb_p(FEPWIN|win, b->port + 1);
@@ -300,32 +272,30 @@ static void pcxem_memoff(struct channel *ch)
}
/* ----------------- Begin pcxe memory window stuff ------------------ */
-
static void pcxe_memwinon(struct board_info *b, unsigned int win)
{
- outb_p(FEPWIN | win, b->port + 1);
+ outb_p(FEPWIN | win, b->port + 1);
}
static void pcxe_memwinoff(struct board_info *b, unsigned int win)
{
- outb_p(inb(b->port) & ~FEPMEM,
- b->port + 1);
+ outb_p(inb(b->port) & ~FEPMEM, b->port + 1);
outb_p(0, b->port + 1);
}
static void pcxe_globalwinon(struct channel *ch)
{
- outb_p( FEPWIN, (int)ch->board->port + 1);
+ outb_p(FEPWIN, (int)ch->board->port + 1);
}
static void pcxe_rxwinon(struct channel *ch)
{
- outb_p(ch->rxwin, (int)ch->board->port + 1);
+ outb_p(ch->rxwin, (int)ch->board->port + 1);
}
static void pcxe_txwinon(struct channel *ch)
{
- outb_p(ch->txwin, (int)ch->board->port + 1);
+ outb_p(ch->txwin, (int)ch->board->port + 1);
}
static void pcxe_memoff(struct channel *ch)
@@ -335,10 +305,9 @@ static void pcxe_memoff(struct channel *ch)
}
/* ------------- Begin pc64xe and pcxi memory window stuff -------------- */
-
static void pcxi_memwinon(struct board_info *b, unsigned int win)
{
- outb_p(inb(b->port) | FEPMEM, b->port);
+ outb_p(inb(b->port) | FEPMEM, b->port);
}
static void pcxi_memwinoff(struct board_info *b, unsigned int win)
@@ -353,12 +322,12 @@ static void pcxi_globalwinon(struct channel *ch)
static void pcxi_rxwinon(struct channel *ch)
{
- outb_p(FEPMEM, ch->board->port);
+ outb_p(FEPMEM, ch->board->port);
}
static void pcxi_txwinon(struct channel *ch)
{
- outb_p(FEPMEM, ch->board->port);
+ outb_p(FEPMEM, ch->board->port);
}
static void pcxi_memoff(struct channel *ch)
@@ -376,16 +345,13 @@ static void pcxi_assertmemoff(struct channel *ch)
epcaassert(!(inb(ch->board->port) & FEPMEM), "Memory on");
}
-
-/* ----------------------------------------------------------------------
- Not all of the cards need specific memory windowing routines. Some
- cards (Such as PCI) needs no windowing routines at all. We provide
- these do nothing routines so that the same code base can be used.
- The driver will ALWAYS call a windowing routine if it thinks it needs
- to; regardless of the card. However, dependent on the card the routine
- may or may not do anything.
----------------------------------------------------------------------------*/
-
+/*
+ * Not all of the cards need specific memory windowing routines. Some cards
+ * (Such as PCI) needs no windowing routines at all. We provide these do
+ * nothing routines so that the same code base can be used. The driver will
+ * ALWAYS call a windowing routine if it thinks it needs to; regardless of the
+ * card. However, dependent on the card the routine may or may not do anything.
+ */
static void dummy_memwinon(struct board_info *b, unsigned int win)
{
}
@@ -418,15 +384,14 @@ static void dummy_assertmemoff(struct channel *ch)
{
}
-/* ----------------- Begin verifyChannel function ----------------------- */
static struct channel *verifyChannel(struct tty_struct *tty)
-{ /* Begin verifyChannel */
- /* --------------------------------------------------------------------
- This routine basically provides a sanity check. It insures that
- the channel returned is within the proper range of addresses as
- well as properly initialized. If some bogus info gets passed in
- through tty->driver_data this should catch it.
- --------------------------------------------------------------------- */
+{
+ /*
+ * This routine basically provides a sanity check. It insures that the
+ * channel returned is within the proper range of addresses as well as
+ * properly initialized. If some bogus info gets passed in
+ * through tty->driver_data this should catch it.
+ */
if (tty) {
struct channel *ch = (struct channel *)tty->driver_data;
if ((ch >= &digi_channels[0]) && (ch < &digi_channels[nbdevs])) {
@@ -435,62 +400,55 @@ static struct channel *verifyChannel(struct tty_struct *tty)
}
}
return NULL;
-
-} /* End verifyChannel */
-
-/* ------------------ Begin pc_sched_event ------------------------- */
+}
static void pc_sched_event(struct channel *ch, int event)
{
- /* ----------------------------------------------------------------------
- We call this to schedule interrupt processing on some event. The
- kernel sees our request and calls the related routine in OUR driver.
- -------------------------------------------------------------------------*/
+ /*
+ * We call this to schedule interrupt processing on some event. The
+ * kernel sees our request and calls the related routine in OUR driver.
+ */
ch->event |= 1 << event;
schedule_work(&ch->tqueue);
-} /* End pc_sched_event */
-
-/* ------------------ Begin epca_error ------------------------- */
+}
static void epca_error(int line, char *msg)
{
printk(KERN_ERR "epca_error (Digi): line = %d %s\n",line,msg);
}
-/* ------------------ Begin pc_close ------------------------- */
-static void pc_close(struct tty_struct * tty, struct file * filp)
+static void pc_close(struct tty_struct *tty, struct file *filp)
{
struct channel *ch;
unsigned long flags;
- /* ---------------------------------------------------------
- verifyChannel returns the channel from the tty struct
- if it is valid. This serves as a sanity check.
- ------------------------------------------------------------- */
- if ((ch = verifyChannel(tty)) != NULL) { /* Begin if ch != NULL */
+ /*
+ * verifyChannel returns the channel from the tty struct if it is
+ * valid. This serves as a sanity check.
+ */
+ if ((ch = verifyChannel(tty)) != NULL) {
spin_lock_irqsave(&epca_lock, flags);
if (tty_hung_up_p(filp)) {
spin_unlock_irqrestore(&epca_lock, flags);
return;
}
- /* Check to see if the channel is open more than once */
if (ch->count-- > 1) {
/* Begin channel is open more than once */
- /* -------------------------------------------------------------
- Return without doing anything. Someone might still be using
- the channel.
- ---------------------------------------------------------------- */
+ /*
+ * Return without doing anything. Someone might still
+ * be using the channel.
+ */
spin_unlock_irqrestore(&epca_lock, flags);
return;
- } /* End channel is open more than once */
+ }
/* Port open only once go ahead with shutdown & reset */
BUG_ON(ch->count < 0);
- /* ---------------------------------------------------------------
- Let the rest of the driver know the channel is being closed.
- This becomes important if an open is attempted before close
- is finished.
- ------------------------------------------------------------------ */
+ /*
+ * Let the rest of the driver know the channel is being closed.
+ * This becomes important if an open is attempted before close
+ * is finished.
+ */
ch->asyncflags |= ASYNC_CLOSING;
tty->closing = 1;
@@ -498,7 +456,7 @@ static void pc_close(struct tty_struct * tty, struct file * filp)
if (ch->asyncflags & ASYNC_INITIALIZED) {
/* Setup an event to indicate when the transmit buffer empties */
- setup_empty_event(tty, ch);
+ setup_empty_event(tty, ch);
tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */
}
if (tty->driver->flush_buffer)
@@ -513,27 +471,24 @@ static void pc_close(struct tty_struct * tty, struct file * filp)
ch->tty = NULL;
spin_unlock_irqrestore(&epca_lock, flags);
- if (ch->blocked_open) { /* Begin if blocked_open */
- if (ch->close_delay)
+ if (ch->blocked_open) {
+ if (ch->close_delay)
msleep_interruptible(jiffies_to_msecs(ch->close_delay));
wake_up_interruptible(&ch->open_wait);
- } /* End if blocked_open */
- ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED |
+ }
+ ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED |
ASYNC_CLOSING);
wake_up_interruptible(&ch->close_wait);
- } /* End if ch != NULL */
-} /* End pc_close */
-
-/* ------------------ Begin shutdown ------------------------- */
+ }
+}
static void shutdown(struct channel *ch)
-{ /* Begin shutdown */
-
+{
unsigned long flags;
struct tty_struct *tty;
struct board_chan __iomem *bc;
- if (!(ch->asyncflags & ASYNC_INITIALIZED))
+ if (!(ch->asyncflags & ASYNC_INITIALIZED))
return;
spin_lock_irqsave(&epca_lock, flags);
@@ -541,50 +496,40 @@ static void shutdown(struct channel *ch)
globalwinon(ch);
bc = ch->brdchan;
- /* ------------------------------------------------------------------
- In order for an event to be generated on the receipt of data the
- idata flag must be set. Since we are shutting down, this is not
- necessary clear this flag.
- --------------------------------------------------------------------- */
-
+ /*
+ * In order for an event to be generated on the receipt of data the
+ * idata flag must be set. Since we are shutting down, this is not
+ * necessary clear this flag.
+ */
if (bc)
writeb(0, &bc->idata);
tty = ch->tty;
- /* ----------------------------------------------------------------
- If we're a modem control device and HUPCL is on, drop RTS & DTR.
- ------------------------------------------------------------------ */
-
+ /* If we're a modem control device and HUPCL is on, drop RTS & DTR. */
if (tty->termios->c_cflag & HUPCL) {
ch->omodem &= ~(ch->m_rts | ch->m_dtr);
fepcmd(ch, SETMODEM, 0, ch->m_dtr | ch->m_rts, 10, 1);
}
memoff(ch);
- /* ------------------------------------------------------------------
- The channel has officialy been closed. The next time it is opened
- it will have to reinitialized. Set a flag to indicate this.
- ---------------------------------------------------------------------- */
-
+ /*
+ * The channel has officialy been closed. The next time it is opened it
+ * will have to reinitialized. Set a flag to indicate this.
+ */
/* Prevent future Digi programmed interrupts from coming active */
-
ch->asyncflags &= ~ASYNC_INITIALIZED;
spin_unlock_irqrestore(&epca_lock, flags);
-
-} /* End shutdown */
-
-/* ------------------ Begin pc_hangup ------------------------- */
+}
static void pc_hangup(struct tty_struct *tty)
-{ /* Begin pc_hangup */
+{
struct channel *ch;
-
- /* ---------------------------------------------------------
- verifyChannel returns the channel from the tty struct
- if it is valid. This serves as a sanity check.
- ------------------------------------------------------------- */
- if ((ch = verifyChannel(tty)) != NULL) { /* Begin if ch != NULL */
+ /*
+ * verifyChannel returns the channel from the tty struct if it is
+ * valid. This serves as a sanity check.
+ */
+ if ((ch = verifyChannel(tty)) != NULL) {
unsigned long flags;
if (tty->driver->flush_buffer)
@@ -599,15 +544,12 @@ static void pc_hangup(struct tty_struct *tty)
ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED);
spin_unlock_irqrestore(&epca_lock, flags);
wake_up_interruptible(&ch->open_wait);
- } /* End if ch != NULL */
-
-} /* End pc_hangup */
-
-/* ------------------ Begin pc_write ------------------------- */
+ }
+}
-static int pc_write(struct tty_struct * tty,
+static int pc_write(struct tty_struct *tty,
const unsigned char *buf, int bytesAvailable)
-{ /* Begin pc_write */
+{
unsigned int head, tail;
int dataLen;
int size;
@@ -617,25 +559,23 @@ static int pc_write(struct tty_struct * tty,
int remain;
struct board_chan __iomem *bc;
- /* ----------------------------------------------------------------
- pc_write is primarily called directly by the kernel routine
- tty_write (Though it can also be called by put_char) found in
- tty_io.c. pc_write is passed a line discipline buffer where
- the data to be written out is stored. The line discipline
- implementation itself is done at the kernel level and is not
- brought into the driver.
- ------------------------------------------------------------------- */
-
- /* ---------------------------------------------------------
- verifyChannel returns the channel from the tty struct
- if it is valid. This serves as a sanity check.
- ------------------------------------------------------------- */
+ /*
+ * pc_write is primarily called directly by the kernel routine
+ * tty_write (Though it can also be called by put_char) found in
+ * tty_io.c. pc_write is passed a line discipline buffer where the data
+ * to be written out is stored. The line discipline implementation
+ * itself is done at the kernel level and is not brought into the
+ * driver.
+ */
+ /*
+ * verifyChannel returns the channel from the tty struct if it is
+ * valid. This serves as a sanity check.
+ */
if ((ch = verifyChannel(tty)) == NULL)
return 0;
/* Make a pointer to the channel data structure found on the board. */
-
bc = ch->brdchan;
size = ch->txbufsize;
amountCopied = 0;
@@ -650,37 +590,36 @@ static int pc_write(struct tty_struct * tty,
tail = readw(&bc->tout);
tail &= (size - 1);
- /* If head >= tail, head has not wrapped around. */
- if (head >= tail) { /* Begin head has not wrapped */
- /* ---------------------------------------------------------------
- remain (much like dataLen above) represents the total amount of
- space available on the card for data. Here dataLen represents
- the space existing between the head pointer and the end of
- buffer. This is important because a memcpy cannot be told to
- automatically wrap around when it hits the buffer end.
- ------------------------------------------------------------------ */
+ if (head >= tail) {
+ /* head has not wrapped */
+ /*
+ * remain (much like dataLen above) represents the total amount
+ * of space available on the card for data. Here dataLen
+ * represents the space existing between the head pointer and
+ * the end of buffer. This is important because a memcpy cannot
+ * be told to automatically wrap around when it hits the buffer
+ * end.
+ */
dataLen = size - head;
remain = size - (head - tail) - 1;
- } else { /* Begin head has wrapped around */
-
+ } else {
+ /* head has wrapped around */
remain = tail - head - 1;
dataLen = remain;
-
- } /* End head has wrapped around */
- /* -------------------------------------------------------------------
- Check the space on the card. If we have more data than
- space; reduce the amount of data to fit the space.
- ---------------------------------------------------------------------- */
+ }
+ /*
+ * Check the space on the card. If we have more data than space; reduce
+ * the amount of data to fit the space.
+ */
bytesAvailable = min(remain, bytesAvailable);
txwinon(ch);
- while (bytesAvailable > 0)
- { /* Begin while there is data to copy onto card */
-
- /* -----------------------------------------------------------------
- If head is not wrapped, the below will make sure the first
- data copy fills to the end of card buffer.
- ------------------------------------------------------------------- */
+ while (bytesAvailable > 0) {
+ /* there is data to copy onto card */
+ /*
+ * If head is not wrapped, the below will make sure the first
+ * data copy fills to the end of card buffer.
+ */
dataLen = min(bytesAvailable, dataLen);
memcpy_toio(ch->txptr + head, buf, dataLen);
buf += dataLen;
@@ -692,7 +631,7 @@ static int pc_write(struct tty_struct * tty,
head = 0;
dataLen = tail;
}
- } /* End while there is data to copy onto card */
+ }
ch->statusflags |= TXBUSY;
globalwinon(ch);
writew(head, &bc->tin);
@@ -703,22 +642,16 @@ static int pc_write(struct tty_struct * tty,
}
memoff(ch);
spin_unlock_irqrestore(&epca_lock, flags);
- return(amountCopied);
-
-} /* End pc_write */
-
-/* ------------------ Begin pc_put_char ------------------------- */
+ return amountCopied;
+}
static void pc_put_char(struct tty_struct *tty, unsigned char c)
-{ /* Begin pc_put_char */
+{
pc_write(tty, &c, 1);
-} /* End pc_put_char */
-
-/* ------------------ Begin pc_write_room ------------------------- */
+}
static int pc_write_room(struct tty_struct *tty)
-{ /* Begin pc_write_room */
-
+{
int remain;
struct channel *ch;
unsigned long flags;
@@ -727,11 +660,10 @@ static int pc_write_room(struct tty_struct *tty)
remain = 0;
- /* ---------------------------------------------------------
- verifyChannel returns the channel from the tty struct
- if it is valid. This serves as a sanity check.
- ------------------------------------------------------------- */
-
+ /*
+ * verifyChannel returns the channel from the tty struct if it is
+ * valid. This serves as a sanity check.
+ */
if ((ch = verifyChannel(tty)) != NULL) {
spin_lock_irqsave(&epca_lock, flags);
globalwinon(ch);
@@ -757,14 +689,10 @@ static int pc_write_room(struct tty_struct *tty)
}
/* Return how much room is left on card */
return remain;
-
-} /* End pc_write_room */
-
-/* ------------------ Begin pc_chars_in_buffer ---------------------- */
+}
static int pc_chars_in_buffer(struct tty_struct *tty)
-{ /* Begin pc_chars_in_buffer */
-
+{
int chars;
unsigned int ctail, head, tail;
int remain;
@@ -772,13 +700,12 @@ static int pc_chars_in_buffer(struct tty_struct *tty)
struct channel *ch;
struct board_chan __iomem *bc;
- /* ---------------------------------------------------------
- verifyChannel returns the channel from the tty struct
- if it is valid. This serves as a sanity check.
- ------------------------------------------------------------- */
-
+ /*
+ * verifyChannel returns the channel from the tty struct if it is
+ * valid. This serves as a sanity check.
+ */
if ((ch = verifyChannel(tty)) == NULL)
- return(0);
+ return 0;
spin_lock_irqsave(&epca_lock, flags);
globalwinon(ch);
@@ -793,45 +720,40 @@ static int pc_chars_in_buffer(struct tty_struct *tty)
else { /* Begin if some space on the card has been used */
head = readw(&bc->tin) & (ch->txbufsize - 1);
tail &= (ch->txbufsize - 1);
- /* --------------------------------------------------------------
- The logic here is basically opposite of the above pc_write_room
- here we are finding the amount of bytes in the buffer filled.
- Not the amount of bytes empty.
- ------------------------------------------------------------------- */
+ /*
+ * The logic here is basically opposite of the above
+ * pc_write_room here we are finding the amount of bytes in the
+ * buffer filled. Not the amount of bytes empty.
+ */
if ((remain = tail - head - 1) < 0 )
remain += ch->txbufsize;
chars = (int)(ch->txbufsize - remain);
- /* -------------------------------------------------------------
- Make it possible to wakeup anything waiting for output
- in tty_ioctl.c, etc.
-
- If not already set. Setup an event to indicate when the
- transmit buffer empties
- ----------------------------------------------------------------- */
+ /*
+ * Make it possible to wakeup anything waiting for output in
+ * tty_ioctl.c, etc.
+ *
+ * If not already set. Setup an event to indicate when the
+ * transmit buffer empties.
+ */
if (!(ch->statusflags & EMPTYWAIT))
setup_empty_event(tty,ch);
-
} /* End if some space on the card has been used */
memoff(ch);
spin_unlock_irqrestore(&epca_lock, flags);
/* Return number of characters residing on card. */
- return(chars);
-
-} /* End pc_chars_in_buffer */
-
-/* ------------------ Begin pc_flush_buffer ---------------------- */
+ return chars;
+}
static void pc_flush_buffer(struct tty_struct *tty)
-{ /* Begin pc_flush_buffer */
-
+{
unsigned int tail;
unsigned long flags;
struct channel *ch;
struct board_chan __iomem *bc;
- /* ---------------------------------------------------------
- verifyChannel returns the channel from the tty struct
- if it is valid. This serves as a sanity check.
- ------------------------------------------------------------- */
+ /*
+ * verifyChannel returns the channel from the tty struct if it is
+ * valid. This serves as a sanity check.
+ */
if ((ch = verifyChannel(tty)) == NULL)
return;
@@ -844,51 +766,47 @@ static void pc_flush_buffer(struct tty_struct *tty)
memoff(ch);
spin_unlock_irqrestore(&epca_lock, flags);
tty_wakeup(tty);
-} /* End pc_flush_buffer */
-
-/* ------------------ Begin pc_flush_chars ---------------------- */
+}
static void pc_flush_chars(struct tty_struct *tty)
-{ /* Begin pc_flush_chars */
- struct channel * ch;
- /* ---------------------------------------------------------
- verifyChannel returns the channel from the tty struct
- if it is valid. This serves as a sanity check.
- ------------------------------------------------------------- */
+{
+ struct channel *ch;
+ /*
+ * verifyChannel returns the channel from the tty struct if it is
+ * valid. This serves as a sanity check.
+ */
if ((ch = verifyChannel(tty)) != NULL) {
unsigned long flags;
spin_lock_irqsave(&epca_lock, flags);
- /* ----------------------------------------------------------------
- If not already set and the transmitter is busy setup an event
- to indicate when the transmit empties.
- ------------------------------------------------------------------- */
+ /*
+ * If not already set and the transmitter is busy setup an
+ * event to indicate when the transmit empties.
+ */
if ((ch->statusflags & TXBUSY) && !(ch->statusflags & EMPTYWAIT))
setup_empty_event(tty,ch);
spin_unlock_irqrestore(&epca_lock, flags);
}
-} /* End pc_flush_chars */
-
-/* ------------------ Begin block_til_ready ---------------------- */
+}
-static int block_til_ready(struct tty_struct *tty,
+static int block_til_ready(struct tty_struct *tty,
struct file *filp, struct channel *ch)
-{ /* Begin block_til_ready */
+{
DECLARE_WAITQUEUE(wait,current);
- int retval, do_clocal = 0;
+ int retval, do_clocal = 0;
unsigned long flags;
if (tty_hung_up_p(filp)) {
if (ch->asyncflags & ASYNC_HUP_NOTIFY)
retval = -EAGAIN;
else
- retval = -ERESTARTSYS;
- return(retval);
+ retval = -ERESTARTSYS;
+ return retval;
}
- /* -----------------------------------------------------------------
- If the device is in the middle of being closed, then block
- until it's done, and then try again.
- -------------------------------------------------------------------- */
+ /*
+ * If the device is in the middle of being closed, then block until
+ * it's done, and then try again.
+ */
if (ch->asyncflags & ASYNC_CLOSING) {
interruptible_sleep_on(&ch->close_wait);
@@ -899,17 +817,17 @@ static int block_til_ready(struct tty_struct *tty,
}
if (filp->f_flags & O_NONBLOCK) {
- /* -----------------------------------------------------------------
- If non-blocking mode is set, then make the check up front
- and then exit.
- -------------------------------------------------------------------- */
+ /*
+ * If non-blocking mode is set, then make the check up front
+ * and then exit.
+ */
ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
return 0;
}
if (tty->termios->c_cflag & CLOCAL)
do_clocal = 1;
/* Block waiting for the carrier detect and the line to become free */
-
+
retval = 0;
add_wait_queue(&ch->open_wait, &wait);
@@ -918,19 +836,18 @@ static int block_til_ready(struct tty_struct *tty,
if (!tty_hung_up_p(filp))
ch->count--;
ch->blocked_open++;
- while(1)
- { /* Begin forever while */
+ while (1) {
set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
- !(ch->asyncflags & ASYNC_INITIALIZED))
+ !(ch->asyncflags & ASYNC_INITIALIZED))
{
if (ch->asyncflags & ASYNC_HUP_NOTIFY)
retval = -EAGAIN;
else
- retval = -ERESTARTSYS;
+ retval = -ERESTARTSYS;
break;
}
- if (!(ch->asyncflags & ASYNC_CLOSING) &&
+ if (!(ch->asyncflags & ASYNC_CLOSING) &&
(do_clocal || (ch->imodem & ch->dcd)))
break;
if (signal_pending(current)) {
@@ -938,16 +855,15 @@ static int block_til_ready(struct tty_struct *tty,
break;
}
spin_unlock_irqrestore(&epca_lock, flags);
- /* ---------------------------------------------------------------
- Allow someone else to be scheduled. We will occasionally go
- through this loop until one of the above conditions change.
- The below schedule call will allow other processes to enter and
- prevent this loop from hogging the cpu.
- ------------------------------------------------------------------ */
+ /*
+ * Allow someone else to be scheduled. We will occasionally go
+ * through this loop until one of the above conditions change.
+ * The below schedule call will allow other processes to enter
+ * and prevent this loop from hogging the cpu.
+ */
schedule();
spin_lock_irqsave(&epca_lock, flags);
-
- } /* End forever while */
+ }
__set_current_state(TASK_RUNNING);
remove_wait_queue(&ch->open_wait, &wait);
@@ -962,13 +878,10 @@ static int block_til_ready(struct tty_struct *tty,
ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
return 0;
-} /* End block_til_ready */
-
-/* ------------------ Begin pc_open ---------------------- */
+}
static int pc_open(struct tty_struct *tty, struct file * filp)
-{ /* Begin pc_open */
-
+{
struct channel *ch;
unsigned long flags;
int line, retval, boardnum;
@@ -984,12 +897,11 @@ static int pc_open(struct tty_struct *tty, struct file * filp)
/* Check status of board configured in system. */
- /* -----------------------------------------------------------------
- I check to see if the epca_setup routine detected an user error.
- It might be better to put this in pc_init, but for the moment it
- goes here.
- ---------------------------------------------------------------------- */
-
+ /*
+ * I check to see if the epca_setup routine detected an user error. It
+ * might be better to put this in pc_init, but for the moment it goes
+ * here.
+ */
if (invalid_lilo_config) {
if (setup_error_code & INVALID_BOARD_TYPE)
printk(KERN_ERR "epca: pc_open: Invalid board type specified in kernel options.\n");
@@ -1010,49 +922,48 @@ static int pc_open(struct tty_struct *tty, struct file * filp)
tty->driver_data = NULL; /* Mark this device as 'down' */
return(-ENODEV);
}
-
+
if ((bc = ch->brdchan) == 0) {
tty->driver_data = NULL;
return -ENODEV;
}
spin_lock_irqsave(&epca_lock, flags);
- /* ------------------------------------------------------------------
- Every time a channel is opened, increment a counter. This is
- necessary because we do not wish to flush and shutdown the channel
- until the last app holding the channel open, closes it.
- --------------------------------------------------------------------- */
+ /*
+ * Every time a channel is opened, increment a counter. This is
+ * necessary because we do not wish to flush and shutdown the channel
+ * until the last app holding the channel open, closes it.
+ */
ch->count++;
- /* ----------------------------------------------------------------
- Set a kernel structures pointer to our local channel
- structure. This way we can get to it when passed only
- a tty struct.
- ------------------------------------------------------------------ */
+ /*
+ * Set a kernel structures pointer to our local channel structure. This
+ * way we can get to it when passed only a tty struct.
+ */
tty->driver_data = ch;
- /* ----------------------------------------------------------------
- If this is the first time the channel has been opened, initialize
- the tty->termios struct otherwise let pc_close handle it.
- -------------------------------------------------------------------- */
+ /*
+ * If this is the first time the channel has been opened, initialize
+ * the tty->termios struct otherwise let pc_close handle it.
+ */
globalwinon(ch);
ch->statusflags = 0;
/* Save boards current modem status */
ch->imodem = readb(&bc->mstat);
- /* ----------------------------------------------------------------
- Set receive head and tail ptrs to each other. This indicates
- no data available to read.
- ----------------------------------------------------------------- */
+ /*
+ * Set receive head and tail ptrs to each other. This indicates no data
+ * available to read.
+ */
head = readw(&bc->rin);
writew(head, &bc->rout);
/* Set the channels associated tty structure */
ch->tty = tty;
- /* -----------------------------------------------------------------
- The below routine generally sets up parity, baud, flow control
- issues, etc.... It effect both control flags and input flags.
- -------------------------------------------------------------------- */
+ /*
+ * The below routine generally sets up parity, baud, flow control
+ * issues, etc.... It effect both control flags and input flags.
+ */
epcaparam(tty,ch);
ch->asyncflags |= ASYNC_INITIALIZED;
memoff(ch);
@@ -1061,10 +972,10 @@ static int pc_open(struct tty_struct *tty, struct file * filp)
retval = block_til_ready(tty, filp, ch);
if (retval)
return retval;
- /* -------------------------------------------------------------
- Set this again in case a hangup set it to zero while this
- open() was waiting for the line...
- --------------------------------------------------------------- */
+ /*
+ * Set this again in case a hangup set it to zero while this open() was
+ * waiting for the line...
+ */
spin_lock_irqsave(&epca_lock, flags);
ch->tty = tty;
globalwinon(ch);
@@ -1073,13 +984,12 @@ static int pc_open(struct tty_struct *tty, struct file * filp)
memoff(ch);
spin_unlock_irqrestore(&epca_lock, flags);
return 0;
-} /* End pc_open */
+}
static int __init epca_module_init(void)
-{ /* Begin init_module */
+{
return pc_init();
}
-
module_init(epca_module_init);
static struct pci_driver epca_driver;
@@ -1092,8 +1002,7 @@ static void __exit epca_module_exit(void)
del_timer_sync(&epca_timer);
- if ((tty_unregister_driver(pc_driver)) ||
- (tty_unregister_driver(pc_info)))
+ if (tty_unregister_driver(pc_driver) || tty_unregister_driver(pc_info))
{
printk(KERN_WARNING "epca: cleanup_module failed to un-register tty driver\n");
return;
@@ -1101,23 +1010,20 @@ static void __exit epca_module_exit(void)
put_tty_driver(pc_driver);
put_tty_driver(pc_info);
- for (crd = 0; crd < num_cards; crd++) { /* Begin for each card */
+ for (crd = 0; crd < num_cards; crd++) {
bd = &boards[crd];
- if (!bd)
- { /* Begin sanity check */
+ if (!bd) { /* sanity check */
printk(KERN_ERR "<Error> - Digi : cleanup_module failed\n");
return;
- } /* End sanity check */
+ }
ch = card_ptr[crd];
- for (count = 0; count < bd->numports; count++, ch++)
- { /* Begin for each port */
+ for (count = 0; count < bd->numports; count++, ch++) {
if (ch && ch->tty)
tty_hangup(ch->tty);
- } /* End for each port */
- } /* End for each card */
- pci_unregister_driver (&epca_driver);
+ }
+ }
+ pci_unregister_driver(&epca_driver);
}
-
module_exit(epca_module_exit);
static const struct tty_operations pc_ops = {
@@ -1148,10 +1054,8 @@ static struct tty_operations info_ops = {
.ioctl = info_ioctl,
};
-/* ------------------ Begin pc_init ---------------------- */
-
static int __init pc_init(void)
-{ /* Begin pc_init */
+{
int crd;
struct board_info *bd;
unsigned char board_id = 0;
@@ -1169,63 +1073,57 @@ static int __init pc_init(void)
if (!pc_info)
goto out2;
- /* -----------------------------------------------------------------------
- If epca_setup has not been ran by LILO set num_cards to defaults; copy
- board structure defined by digiConfig into drivers board structure.
- Note : If LILO has ran epca_setup then epca_setup will handle defining
- num_cards as well as copying the data into the board structure.
- -------------------------------------------------------------------------- */
- if (!liloconfig) { /* Begin driver has been configured via. epcaconfig */
-
+ /*
+ * If epca_setup has not been ran by LILO set num_cards to defaults;
+ * copy board structure defined by digiConfig into drivers board
+ * structure. Note : If LILO has ran epca_setup then epca_setup will
+ * handle defining num_cards as well as copying the data into the board
+ * structure.
+ */
+ if (!liloconfig) {
+ /* driver has been configured via. epcaconfig */
nbdevs = NBDEVS;
num_cards = NUMCARDS;
- memcpy((void *)&boards, (void *)&static_boards,
- (sizeof(struct board_info) * NUMCARDS));
- } /* End driver has been configured via. epcaconfig */
-
- /* -----------------------------------------------------------------
- Note : If lilo was used to configure the driver and the
- ignore epcaconfig option was choosen (digiepca=2) then
- nbdevs and num_cards will equal 0 at this point. This is
- okay; PCI cards will still be picked up if detected.
- --------------------------------------------------------------------- */
-
- /* -----------------------------------------------------------
- Set up interrupt, we will worry about memory allocation in
- post_fep_init.
- --------------------------------------------------------------- */
+ memcpy(&boards, &static_boards,
+ sizeof(struct board_info) * NUMCARDS);
+ }
+ /*
+ * Note : If lilo was used to configure the driver and the ignore
+ * epcaconfig option was choosen (digiepca=2) then nbdevs and num_cards
+ * will equal 0 at this point. This is okay; PCI cards will still be
+ * picked up if detected.
+ */
+ /*
+ * Set up interrupt, we will worry about memory allocation in
+ * post_fep_init.
+ */
printk(KERN_INFO "DIGI epca driver version %s loaded.\n",VERSION);
- /* ------------------------------------------------------------------
- NOTE : This code assumes that the number of ports found in
- the boards array is correct. This could be wrong if
- the card in question is PCI (And therefore has no ports
- entry in the boards structure.) The rest of the
- information will be valid for PCI because the beginning
- of pc_init scans for PCI and determines i/o and base
- memory addresses. I am not sure if it is possible to
- read the number of ports supported by the card prior to
- it being booted (Since that is the state it is in when
- pc_init is run). Because it is not possible to query the
- number of supported ports until after the card has booted;
- we are required to calculate the card_ptrs as the card is
- is initialized (Inside post_fep_init). The negative thing
- about this approach is that digiDload's call to GET_INFO
- will have a bad port value. (Since this is called prior
- to post_fep_init.)
-
- --------------------------------------------------------------------- */
-
+ /*
+ * NOTE : This code assumes that the number of ports found in the
+ * boards array is correct. This could be wrong if the card in question
+ * is PCI (And therefore has no ports entry in the boards structure.)
+ * The rest of the information will be valid for PCI because the
+ * beginning of pc_init scans for PCI and determines i/o and base
+ * memory addresses. I am not sure if it is possible to read the number
+ * of ports supported by the card prior to it being booted (Since that
+ * is the state it is in when pc_init is run). Because it is not
+ * possible to query the number of supported ports until after the card
+ * has booted; we are required to calculate the card_ptrs as the card
+ * is initialized (Inside post_fep_init). The negative thing about this
+ * approach is that digiDload's call to GET_INFO will have a bad port
+ * value. (Since this is called prior to post_fep_init.)
+ */
pci_boards_found = 0;
- if(num_cards < MAXBOARDS)
+ if (num_cards < MAXBOARDS)
pci_boards_found += init_PCI();
num_cards += pci_boards_found;
pc_driver->owner = THIS_MODULE;
- pc_driver->name = "ttyD";
- pc_driver->major = DIGI_MAJOR;
+ pc_driver->name = "ttyD";
+ pc_driver->major = DIGI_MAJOR;
pc_driver->minor_start = 0;
pc_driver->type = TTY_DRIVER_TYPE_SERIAL;
pc_driver->subtype = SERIAL_TYPE_NORMAL;
@@ -1256,120 +1154,108 @@ static int __init pc_init(void)
tty_set_operations(pc_info, &info_ops);
- for (crd = 0; crd < num_cards; crd++)
- { /* Begin for each card */
-
- /* ------------------------------------------------------------------
- This is where the appropriate memory handlers for the hardware is
- set. Everything at runtime blindly jumps through these vectors.
- ---------------------------------------------------------------------- */
+ for (crd = 0; crd < num_cards; crd++) {
+ /*
+ * This is where the appropriate memory handlers for the
+ * hardware is set. Everything at runtime blindly jumps through
+ * these vectors.
+ */
/* defined in epcaconfig.h */
bd = &boards[crd];
- switch (bd->type)
- { /* Begin switch on bd->type {board type} */
- case PCXEM:
- case EISAXEM:
- bd->memwinon = pcxem_memwinon ;
- bd->memwinoff = pcxem_memwinoff ;
- bd->globalwinon = pcxem_globalwinon ;
- bd->txwinon = pcxem_txwinon ;
- bd->rxwinon = pcxem_rxwinon ;
- bd->memoff = pcxem_memoff ;
- bd->assertgwinon = dummy_assertgwinon;
- bd->assertmemoff = dummy_assertmemoff;
- break;
-
- case PCIXEM:
- case PCIXRJ:
- case PCIXR:
- bd->memwinon = dummy_memwinon;
- bd->memwinoff = dummy_memwinoff;
- bd->globalwinon = dummy_globalwinon;
- bd->txwinon = dummy_txwinon;
- bd->rxwinon = dummy_rxwinon;
- bd->memoff = dummy_memoff;
- bd->assertgwinon = dummy_assertgwinon;
- bd->assertmemoff = dummy_assertmemoff;
- break;
-
- case PCXE:
- case PCXEVE:
-
- bd->memwinon = pcxe_memwinon;
- bd->memwinoff = pcxe_memwinoff;
- bd->globalwinon = pcxe_globalwinon;
- bd->txwinon = pcxe_txwinon;
- bd->rxwinon = pcxe_rxwinon;
- bd->memoff = pcxe_memoff;
- bd->assertgwinon = dummy_assertgwinon;
- bd->assertmemoff = dummy_assertmemoff;
- break;
-
- case PCXI:
- case PC64XE:
-
- bd->memwinon = pcxi_memwinon;
- bd->memwinoff = pcxi_memwinoff;
- bd->globalwinon = pcxi_globalwinon;
- bd->txwinon = pcxi_txwinon;
- bd->rxwinon = pcxi_rxwinon;
- bd->memoff = pcxi_memoff;
- bd->assertgwinon = pcxi_assertgwinon;
- bd->assertmemoff = pcxi_assertmemoff;
- break;
-
- default:
- break;
-
- } /* End switch on bd->type */
-
- /* ---------------------------------------------------------------
- Some cards need a memory segment to be defined for use in
- transmit and receive windowing operations. These boards
- are listed in the below switch. In the case of the XI the
- amount of memory on the board is variable so the memory_seg
- is also variable. This code determines what they segment
- should be.
- ----------------------------------------------------------------- */
-
- switch (bd->type)
- { /* Begin switch on bd->type {board type} */
-
- case PCXE:
- case PCXEVE:
- case PC64XE:
- bd->memory_seg = 0xf000;
+ switch (bd->type) {
+ case PCXEM:
+ case EISAXEM:
+ bd->memwinon = pcxem_memwinon;
+ bd->memwinoff = pcxem_memwinoff;
+ bd->globalwinon = pcxem_globalwinon;
+ bd->txwinon = pcxem_txwinon;
+ bd->rxwinon = pcxem_rxwinon;
+ bd->memoff = pcxem_memoff;
+ bd->assertgwinon = dummy_assertgwinon;
+ bd->assertmemoff = dummy_assertmemoff;
break;
- case PCXI:
- board_id = inb((int)bd->port);
- if ((board_id & 0x1) == 0x1)
- { /* Begin it's an XI card */
-
- /* Is it a 64K board */
- if ((board_id & 0x30) == 0)
- bd->memory_seg = 0xf000;
-
- /* Is it a 128K board */
- if ((board_id & 0x30) == 0x10)
- bd->memory_seg = 0xe000;
+ case PCIXEM:
+ case PCIXRJ:
+ case PCIXR:
+ bd->memwinon = dummy_memwinon;
+ bd->memwinoff = dummy_memwinoff;
+ bd->globalwinon = dummy_globalwinon;
+ bd->txwinon = dummy_txwinon;
+ bd->rxwinon = dummy_rxwinon;
+ bd->memoff = dummy_memoff;
+ bd->assertgwinon = dummy_assertgwinon;
+ bd->assertmemoff = dummy_assertmemoff;
+ break;
- /* Is is a 256K board */
- if ((board_id & 0x30) == 0x20)
- bd->memory_seg = 0xc000;
+ case PCXE:
+ case PCXEVE:
+ bd->memwinon = pcxe_memwinon;
+ bd->memwinoff = pcxe_memwinoff;
+ bd->globalwinon = pcxe_globalwinon;
+ bd->txwinon = pcxe_txwinon;
+ bd->rxwinon = pcxe_rxwinon;
+ bd->memoff = pcxe_memoff;
+ bd->assertgwinon = dummy_assertgwinon;
+ bd->assertmemoff = dummy_assertmemoff;
+ break;
- /* Is it a 512K board */
- if ((board_id & 0x30) == 0x30)
- bd->memory_seg = 0x8000;
+ case PCXI:
+ case PC64XE:
+ bd->memwinon = pcxi_memwinon;
+ bd->memwinoff = pcxi_memwinoff;
+ bd->globalwinon = pcxi_globalwinon;
+ bd->txwinon = pcxi_txwinon;
+ bd->rxwinon = pcxi_rxwinon;
+ bd->memoff = pcxi_memoff;
+ bd->assertgwinon = pcxi_assertgwinon;
+ bd->assertmemoff = pcxi_assertmemoff;
+ break;
- } else printk(KERN_ERR "epca: Board at 0x%x doesn't appear to be an XI\n",(int)bd->port);
+ default:
break;
+ }
- } /* End switch on bd->type */
+ /*
+ * Some cards need a memory segment to be defined for use in
+ * transmit and receive windowing operations. These boards are
+ * listed in the below switch. In the case of the XI the amount
+ * of memory on the board is variable so the memory_seg is also
+ * variable. This code determines what they segment should be.
+ */
+ switch (bd->type) {
+ case PCXE:
+ case PCXEVE:
+ case PC64XE:
+ bd->memory_seg = 0xf000;
+ break;
- } /* End for each card */
+ case PCXI:
+ board_id = inb((int)bd->port);
+ if ((board_id & 0x1) == 0x1) {
+ /* it's an XI card */
+ /* Is it a 64K board */
+ if ((board_id & 0x30) == 0)
+ bd->memory_seg = 0xf000;
+
+ /* Is it a 128K board */
+ if ((board_id & 0x30) == 0x10)
+ bd->memory_seg = 0xe000;
+
+ /* Is is a 256K board */
+ if ((board_id & 0x30) == 0x20)
+ bd->memory_seg = 0xc000;
+
+ /* Is it a 512K board */
+ if ((board_id & 0x30) == 0x30)
+ bd->memory_seg = 0x8000;
+ } else
+ printk(KERN_ERR "epca: Board at 0x%x doesn't appear to be an XI\n",(int)bd->port);
+ break;
+ }
+ }
err = tty_register_driver(pc_driver);
if (err) {
@@ -1383,10 +1269,7 @@ static int __init pc_init(void)
goto out4;
}
- /* -------------------------------------------------------------------
- Start up the poller to check for events on all enabled boards
- ---------------------------------------------------------------------- */
-
+ /* Start up the poller to check for events on all enabled boards */
init_timer(&epca_timer);
epca_timer.function = epcapoll;
mod_timer(&epca_timer, jiffies + HZ/25);
@@ -1400,51 +1283,47 @@ out2:
put_tty_driver(pc_driver);
out1:
return err;
-
-} /* End pc_init */
-
-/* ------------------ Begin post_fep_init ---------------------- */
+}
static void post_fep_init(unsigned int crd)
-{ /* Begin post_fep_init */
-
+{
int i;
void __iomem *memaddr;
struct global_data __iomem *gd;
struct board_info *bd;
struct board_chan __iomem *bc;
- struct channel *ch;
- int shrinkmem = 0, lowwater ;
-
- /* -------------------------------------------------------------
- This call is made by the user via. the ioctl call DIGI_INIT.
- It is responsible for setting up all the card specific stuff.
- ---------------------------------------------------------------- */
- bd = &boards[crd];
+ struct channel *ch;
+ int shrinkmem = 0, lowwater;
- /* -----------------------------------------------------------------
- If this is a PCI board, get the port info. Remember PCI cards
- do not have entries into the epcaconfig.h file, so we can't get
- the number of ports from it. Unfortunetly, this means that anyone
- doing a DIGI_GETINFO before the board has booted will get an invalid
- number of ports returned (It should return 0). Calls to DIGI_GETINFO
- after DIGI_INIT has been called will return the proper values.
- ------------------------------------------------------------------- */
+ /*
+ * This call is made by the user via. the ioctl call DIGI_INIT. It is
+ * responsible for setting up all the card specific stuff.
+ */
+ bd = &boards[crd];
+ /*
+ * If this is a PCI board, get the port info. Remember PCI cards do not
+ * have entries into the epcaconfig.h file, so we can't get the number
+ * of ports from it. Unfortunetly, this means that anyone doing a
+ * DIGI_GETINFO before the board has booted will get an invalid number
+ * of ports returned (It should return 0). Calls to DIGI_GETINFO after
+ * DIGI_INIT has been called will return the proper values.
+ */
if (bd->type >= PCIXEM) { /* Begin get PCI number of ports */
- /* --------------------------------------------------------------------
- Below we use XEMPORTS as a memory offset regardless of which PCI
- card it is. This is because all of the supported PCI cards have
- the same memory offset for the channel data. This will have to be
- changed if we ever develop a PCI/XE card. NOTE : The FEP manual
- states that the port offset is 0xC22 as opposed to 0xC02. This is
- only true for PC/XE, and PC/XI cards; not for the XEM, or CX series.
- On the PCI cards the number of ports is determined by reading a
- ID PROM located in the box attached to the card. The card can then
- determine the index the id to determine the number of ports available.
- (FYI - The id should be located at 0x1ac (And may use up to 4 bytes
- if the box in question is a XEM or CX)).
- ------------------------------------------------------------------------ */
+ /*
+ * Below we use XEMPORTS as a memory offset regardless of which
+ * PCI card it is. This is because all of the supported PCI
+ * cards have the same memory offset for the channel data. This
+ * will have to be changed if we ever develop a PCI/XE card.
+ * NOTE : The FEP manual states that the port offset is 0xC22
+ * as opposed to 0xC02. This is only true for PC/XE, and PC/XI
+ * cards; not for the XEM, or CX series. On the PCI cards the
+ * number of ports is determined by reading a ID PROM located
+ * in the box attached to the card. The card can then determine
+ * the index the id to determine the number of ports available.
+ * (FYI - The id should be located at 0x1ac (And may use up to
+ * 4 bytes if the box in question is a XEM or CX)).
+ */
/* PCI cards are already remapped at this point ISA are not */
bd->numports = readw(bd->re_map_membase + XEMPORTS);
epcaassert(bd->numports <= 64,"PCI returned a invalid number of ports");
@@ -1465,95 +1344,87 @@ static void post_fep_init(unsigned int crd)
memaddr = bd->re_map_membase;
- /* -----------------------------------------------------------------
- The below assignment will set bc to point at the BEGINING of
- the cards channel structures. For 1 card there will be between
- 8 and 64 of these structures.
- -------------------------------------------------------------------- */
-
+ /*
+ * The below assignment will set bc to point at the BEGINING of the
+ * cards channel structures. For 1 card there will be between 8 and 64
+ * of these structures.
+ */
bc = memaddr + CHANSTRUCT;
- /* -------------------------------------------------------------------
- The below assignment will set gd to point at the BEGINING of
- global memory address 0xc00. The first data in that global
- memory actually starts at address 0xc1a. The command in
- pointer begins at 0xd10.
- ---------------------------------------------------------------------- */
-
+ /*
+ * The below assignment will set gd to point at the BEGINING of global
+ * memory address 0xc00. The first data in that global memory actually
+ * starts at address 0xc1a. The command in pointer begins at 0xd10.
+ */
gd = memaddr + GLOBAL;
- /* --------------------------------------------------------------------
- XEPORTS (address 0xc22) points at the number of channels the
- card supports. (For 64XE, XI, XEM, and XR use 0xc02)
- ----------------------------------------------------------------------- */
-
+ /*
+ * XEPORTS (address 0xc22) points at the number of channels the card
+ * supports. (For 64XE, XI, XEM, and XR use 0xc02)
+ */
if ((bd->type == PCXEVE || bd->type == PCXE) && (readw(memaddr + XEPORTS) < 3))
shrinkmem = 1;
if (bd->type < PCIXEM)
if (!request_region((int)bd->port, 4, board_desc[bd->type]))
- return;
+ return;
memwinon(bd, 0);
- /* --------------------------------------------------------------------
- Remember ch is the main drivers channels structure, while bc is
- the cards channel structure.
- ------------------------------------------------------------------------ */
-
- /* For every port on the card do ..... */
-
- for (i = 0; i < bd->numports; i++, ch++, bc++) { /* Begin for each port */
+ /*
+ * Remember ch is the main drivers channels structure, while bc is the
+ * cards channel structure.
+ */
+ for (i = 0; i < bd->numports; i++, ch++, bc++) {
unsigned long flags;
u16 tseg, rseg;
- ch->brdchan = bc;
- ch->mailbox = gd;
+ ch->brdchan = bc;
+ ch->mailbox = gd;
INIT_WORK(&ch->tqueue, do_softint);
- ch->board = &boards[crd];
+ ch->board = &boards[crd];
spin_lock_irqsave(&epca_lock, flags);
switch (bd->type) {
- /* ----------------------------------------------------------------
- Since some of the boards use different bitmaps for their
- control signals we cannot hard code these values and retain
- portability. We virtualize this data here.
- ------------------------------------------------------------------- */
- case EISAXEM:
- case PCXEM:
- case PCIXEM:
- case PCIXRJ:
- case PCIXR:
- ch->m_rts = 0x02 ;
- ch->m_dcd = 0x80 ;
- ch->m_dsr = 0x20 ;
- ch->m_cts = 0x10 ;
- ch->m_ri = 0x40 ;
- ch->m_dtr = 0x01 ;
- break;
-
- case PCXE:
- case PCXEVE:
- case PCXI:
- case PC64XE:
- ch->m_rts = 0x02 ;
- ch->m_dcd = 0x08 ;
- ch->m_dsr = 0x10 ;
- ch->m_cts = 0x20 ;
- ch->m_ri = 0x40 ;
- ch->m_dtr = 0x80 ;
- break;
-
- } /* End switch bd->type */
+ /*
+ * Since some of the boards use different bitmaps for
+ * their control signals we cannot hard code these
+ * values and retain portability. We virtualize this
+ * data here.
+ */
+ case EISAXEM:
+ case PCXEM:
+ case PCIXEM:
+ case PCIXRJ:
+ case PCIXR:
+ ch->m_rts = 0x02;
+ ch->m_dcd = 0x80;
+ ch->m_dsr = 0x20;
+ ch->m_cts = 0x10;
+ ch->m_ri = 0x40;
+ ch->m_dtr = 0x01;
+ break;
+
+ case PCXE:
+ case PCXEVE:
+ case PCXI:
+ case PC64XE:
+ ch->m_rts = 0x02;
+ ch->m_dcd = 0x08;
+ ch->m_dsr = 0x10;
+ ch->m_cts = 0x20;
+ ch->m_ri = 0x40;
+ ch->m_dtr = 0x80;
+ break;
+ }
if (boards[crd].altpin) {
ch->dsr = ch->m_dcd;
ch->dcd = ch->m_dsr;
ch->digiext.digi_flags |= DIGI_ALTPIN;
- }
- else {
+ } else {
ch->dcd = ch->m_dcd;
ch->dsr = ch->m_dsr;
}
-
+
ch->boardnum = crd;
ch->channelnum = i;
ch->magic = EPCA_MAGIC;
@@ -1568,71 +1439,67 @@ static void post_fep_init(unsigned int crd)
rseg = readw(&bc->rseg);
switch (bd->type) {
+ case PCIXEM:
+ case PCIXRJ:
+ case PCIXR:
+ /* Cover all the 2MEG cards */
+ ch->txptr = memaddr + ((tseg << 4) & 0x1fffff);
+ ch->rxptr = memaddr + ((rseg << 4) & 0x1fffff);
+ ch->txwin = FEPWIN | (tseg >> 11);
+ ch->rxwin = FEPWIN | (rseg >> 11);
+ break;
- case PCIXEM:
- case PCIXRJ:
- case PCIXR:
- /* Cover all the 2MEG cards */
- ch->txptr = memaddr + ((tseg << 4) & 0x1fffff);
- ch->rxptr = memaddr + ((rseg << 4) & 0x1fffff);
- ch->txwin = FEPWIN | (tseg >> 11);
- ch->rxwin = FEPWIN | (rseg >> 11);
- break;
-
- case PCXEM:
- case EISAXEM:
- /* Cover all the 32K windowed cards */
- /* Mask equal to window size - 1 */
- ch->txptr = memaddr + ((tseg << 4) & 0x7fff);
- ch->rxptr = memaddr + ((rseg << 4) & 0x7fff);
- ch->txwin = FEPWIN | (tseg >> 11);
- ch->rxwin = FEPWIN | (rseg >> 11);
- break;
-
- case PCXEVE:
- case PCXE:
- ch->txptr = memaddr + (((tseg - bd->memory_seg) << 4) & 0x1fff);
- ch->txwin = FEPWIN | ((tseg - bd->memory_seg) >> 9);
- ch->rxptr = memaddr + (((rseg - bd->memory_seg) << 4) & 0x1fff);
- ch->rxwin = FEPWIN | ((rseg - bd->memory_seg) >>9 );
- break;
-
- case PCXI:
- case PC64XE:
- ch->txptr = memaddr + ((tseg - bd->memory_seg) << 4);
- ch->rxptr = memaddr + ((rseg - bd->memory_seg) << 4);
- ch->txwin = ch->rxwin = 0;
- break;
-
- } /* End switch bd->type */
+ case PCXEM:
+ case EISAXEM:
+ /* Cover all the 32K windowed cards */
+ /* Mask equal to window size - 1 */
+ ch->txptr = memaddr + ((tseg << 4) & 0x7fff);
+ ch->rxptr = memaddr + ((rseg << 4) & 0x7fff);
+ ch->txwin = FEPWIN | (tseg >> 11);
+ ch->rxwin = FEPWIN | (rseg >> 11);
+ break;
+
+ case PCXEVE:
+ case PCXE:
+ ch->txptr = memaddr + (((tseg - bd->memory_seg) << 4) & 0x1fff);
+ ch->txwin = FEPWIN | ((tseg - bd->memory_seg) >> 9);
+ ch->rxptr = memaddr + (((rseg - bd->memory_seg) << 4) & 0x1fff);
+ ch->rxwin = FEPWIN | ((rseg - bd->memory_seg) >>9 );
+ break;
+
+ case PCXI:
+ case PC64XE:
+ ch->txptr = memaddr + ((tseg - bd->memory_seg) << 4);
+ ch->rxptr = memaddr + ((rseg - bd->memory_seg) << 4);
+ ch->txwin = ch->rxwin = 0;
+ break;
+ }
ch->txbufhead = 0;
ch->txbufsize = readw(&bc->tmax) + 1;
-
+
ch->rxbufhead = 0;
ch->rxbufsize = readw(&bc->rmax) + 1;
-
+
lowwater = ch->txbufsize >= 2000 ? 1024 : (ch->txbufsize / 2);
/* Set transmitter low water mark */
fepcmd(ch, STXLWATER, lowwater, 0, 10, 0);
/* Set receiver low water mark */
-
fepcmd(ch, SRXLWATER, (ch->rxbufsize / 4), 0, 10, 0);
/* Set receiver high water mark */
-
fepcmd(ch, SRXHWATER, (3 * ch->rxbufsize / 4), 0, 10, 0);
writew(100, &bc->edelay);
writeb(1, &bc->idata);
-
+
ch->startc = readb(&bc->startc);
ch->stopc = readb(&bc->stopc);
ch->startca = readb(&bc->startca);
ch->stopca = readb(&bc->stopca);
-
+
ch->fepcflag = 0;
ch->fepiflag = 0;
ch->fepoflag = 0;
@@ -1640,7 +1507,7 @@ static void post_fep_init(unsigned int crd)
ch->fepstopc = 0;
ch->fepstartca = 0;
ch->fepstopca = 0;
-
+
ch->close_delay = 50;
ch->count = 0;
ch->blocked_open = 0;
@@ -1648,80 +1515,66 @@ static void post_fep_init(unsigned int crd)
init_waitqueue_head(&ch->close_wait);
spin_unlock_irqrestore(&epca_lock, flags);
- } /* End for each port */
+ }
- printk(KERN_INFO
- "Digi PC/Xx Driver V%s: %s I/O = 0x%lx Mem = 0x%lx Ports = %d\n",
+ printk(KERN_INFO
+ "Digi PC/Xx Driver V%s: %s I/O = 0x%lx Mem = 0x%lx Ports = %d\n",
VERSION, board_desc[bd->type], (long)bd->port, (long)bd->membase, bd->numports);
memwinoff(bd, 0);
-
-} /* End post_fep_init */
-
-/* --------------------- Begin epcapoll ------------------------ */
+}
static void epcapoll(unsigned long ignored)
-{ /* Begin epcapoll */
-
+{
unsigned long flags;
int crd;
volatile unsigned int head, tail;
struct channel *ch;
struct board_info *bd;
- /* -------------------------------------------------------------------
- This routine is called upon every timer interrupt. Even though
- the Digi series cards are capable of generating interrupts this
- method of non-looping polling is more efficient. This routine
- checks for card generated events (Such as receive data, are transmit
- buffer empty) and acts on those events.
- ----------------------------------------------------------------------- */
-
- for (crd = 0; crd < num_cards; crd++)
- { /* Begin for each card */
-
+ /*
+ * This routine is called upon every timer interrupt. Even though the
+ * Digi series cards are capable of generating interrupts this method
+ * of non-looping polling is more efficient. This routine checks for
+ * card generated events (Such as receive data, are transmit buffer
+ * empty) and acts on those events.
+ */
+ for (crd = 0; crd < num_cards; crd++) {
bd = &boards[crd];
ch = card_ptr[crd];
if ((bd->status == DISABLED) || digi_poller_inhibited)
- continue; /* Begin loop next interation */
-
- /* -----------------------------------------------------------
- assertmemoff is not needed here; indeed it is an empty subroutine.
- It is being kept because future boards may need this as well as
- some legacy boards.
- ---------------------------------------------------------------- */
+ continue;
+ /*
+ * assertmemoff is not needed here; indeed it is an empty
+ * subroutine. It is being kept because future boards may need
+ * this as well as some legacy boards.
+ */
spin_lock_irqsave(&epca_lock, flags);
assertmemoff(ch);
globalwinon(ch);
- /* ---------------------------------------------------------------
- In this case head and tail actually refer to the event queue not
- the transmit or receive queue.
- ------------------------------------------------------------------- */
-
+ /*
+ * In this case head and tail actually refer to the event queue
+ * not the transmit or receive queue.
+ */
head = readw(&ch->mailbox->ein);
tail = readw(&ch->mailbox->eout);
-
- /* If head isn't equal to tail we have an event */
+ /* If head isn't equal to tail we have an event */
if (head != tail)
doevent(crd);
memoff(ch);
spin_unlock_irqrestore(&epca_lock, flags);
-
} /* End for each card */
mod_timer(&epca_timer, jiffies + (HZ / 25));
-} /* End epcapoll */
-
-/* --------------------- Begin doevent ------------------------ */
+}
static void doevent(int crd)
-{ /* Begin doevent */
-
+{
void __iomem *eventbuf;
struct channel *ch, *chan0;
static struct tty_struct *tty;
@@ -1731,28 +1584,28 @@ static void doevent(int crd)
int event, channel;
int mstat, lstat;
- /* -------------------------------------------------------------------
- This subroutine is called by epcapoll when an event is detected
- in the event queue. This routine responds to those events.
- --------------------------------------------------------------------- */
+ /*
+ * This subroutine is called by epcapoll when an event is detected
+ * in the event queue. This routine responds to those events.
+ */
bd = &boards[crd];
chan0 = card_ptr[crd];
epcaassert(chan0 <= &digi_channels[nbdevs - 1], "ch out of range");
assertgwinon(chan0);
- while ((tail = readw(&chan0->mailbox->eout)) != (head = readw(&chan0->mailbox->ein)))
- { /* Begin while something in event queue */
+ while ((tail = readw(&chan0->mailbox->eout)) != (head = readw(&chan0->mailbox->ein))) { /* Begin while something in event queue */
assertgwinon(chan0);
eventbuf = bd->re_map_membase + tail + ISTART;
/* Get the channel the event occurred on */
channel = readb(eventbuf);
/* Get the actual event code that occurred */
event = readb(eventbuf + 1);
- /* ----------------------------------------------------------------
- The two assignments below get the current modem status (mstat)
- and the previous modem status (lstat). These are useful becuase
- an event could signal a change in modem signals itself.
- ------------------------------------------------------------------- */
+ /*
+ * The two assignments below get the current modem status
+ * (mstat) and the previous modem status (lstat). These are
+ * useful becuase an event could signal a change in modem
+ * signals itself.
+ */
mstat = readb(eventbuf + 2);
lstat = readb(eventbuf + 3);
@@ -1772,37 +1625,36 @@ static void doevent(int crd)
assertgwinon(ch);
} /* End DATA_IND */
/* else *//* Fix for DCD transition missed bug */
- if (event & MODEMCHG_IND) { /* Begin MODEMCHG_IND */
+ if (event & MODEMCHG_IND) {
/* A modem signal change has been indicated */
ch->imodem = mstat;
- if (ch->asyncflags & ASYNC_CHECK_CD) {
+ if (ch->asyncflags & ASYNC_CHECK_CD) {
if (mstat & ch->dcd) /* We are now receiving dcd */
wake_up_interruptible(&ch->open_wait);
else
pc_sched_event(ch, EPCA_EVENT_HANGUP); /* No dcd; hangup */
}
- } /* End MODEMCHG_IND */
+ }
tty = ch->tty;
- if (tty) { /* Begin if valid tty */
- if (event & BREAK_IND) { /* Begin if BREAK_IND */
+ if (tty) {
+ if (event & BREAK_IND) {
/* A break has been indicated */
tty_insert_flip_char(tty, 0, TTY_BREAK);
- tty_schedule_flip(tty);
- } else if (event & LOWTX_IND) { /* Begin LOWTX_IND */
- if (ch->statusflags & LOWWAIT)
- { /* Begin if LOWWAIT */
+ tty_schedule_flip(tty);
+ } else if (event & LOWTX_IND) {
+ if (ch->statusflags & LOWWAIT) {
ch->statusflags &= ~LOWWAIT;
tty_wakeup(tty);
- } /* End if LOWWAIT */
- } else if (event & EMPTYTX_IND) { /* Begin EMPTYTX_IND */
+ }
+ } else if (event & EMPTYTX_IND) {
/* This event is generated by setup_empty_event */
ch->statusflags &= ~TXBUSY;
- if (ch->statusflags & EMPTYWAIT) { /* Begin if EMPTYWAIT */
+ if (ch->statusflags & EMPTYWAIT) {
ch->statusflags &= ~EMPTYWAIT;
tty_wakeup(tty);
- } /* End if EMPTYWAIT */
- } /* End EMPTYTX_IND */
- } /* End if valid tty */
+ }
+ }
+ }
next:
globalwinon(ch);
BUG_ON(!bc);
@@ -1810,13 +1662,11 @@ static void doevent(int crd)
writew((tail + 4) & (IMAX - ISTART - 4), &chan0->mailbox->eout);
globalwinon(chan0);
} /* End while something in event queue */
-} /* End doevent */
-
-/* --------------------- Begin fepcmd ------------------------ */
+}
static void fepcmd(struct channel *ch, int cmd, int word_or_byte,
int byte2, int ncmds, int bytecmd)
-{ /* Begin fepcmd */
+{
unchar __iomem *memaddr;
unsigned int head, cmdTail, cmdStart, cmdMax;
long count;
@@ -1831,11 +1681,11 @@ static void fepcmd(struct channel *ch, int cmd, int word_or_byte,
head = readw(&ch->mailbox->cin);
/* cmdStart is a base address */
cmdStart = readw(&ch->mailbox->cstart);
- /* ------------------------------------------------------------------
- We do the addition below because we do not want a max pointer
- relative to cmdStart. We want a max pointer that points at the
- physical end of the command queue.
- -------------------------------------------------------------------- */
+ /*
+ * We do the addition below because we do not want a max pointer
+ * relative to cmdStart. We want a max pointer that points at the
+ * physical end of the command queue.
+ */
cmdMax = (cmdStart + 4 + readw(&ch->mailbox->cmax));
memaddr = ch->board->re_map_membase;
@@ -1860,7 +1710,7 @@ static void fepcmd(struct channel *ch, int cmd, int word_or_byte,
writew(head, &ch->mailbox->cin);
count = FEPTIMEOUT;
- for (;;) { /* Begin forever loop */
+ for (;;) {
count--;
if (count == 0) {
printk(KERN_ERR "<Error> - Fep not responding in fepcmd()\n");
@@ -1869,26 +1719,23 @@ static void fepcmd(struct channel *ch, int cmd, int word_or_byte,
head = readw(&ch->mailbox->cin);
cmdTail = readw(&ch->mailbox->cout);
n = (head - cmdTail) & (cmdMax - cmdStart - 4);
- /* ----------------------------------------------------------
- Basically this will break when the FEP acknowledges the
- command by incrementing cmdTail (Making it equal to head).
- ------------------------------------------------------------- */
+ /*
+ * Basically this will break when the FEP acknowledges the
+ * command by incrementing cmdTail (Making it equal to head).
+ */
if (n <= ncmds * (sizeof(short) * 4))
- break; /* Well nearly forever :-) */
- } /* End forever loop */
-} /* End fepcmd */
-
-/* ---------------------------------------------------------------------
- Digi products use fields in their channels structures that are very
- similar to the c_cflag and c_iflag fields typically found in UNIX
- termios structures. The below three routines allow mappings
- between these hardware "flags" and their respective Linux flags.
-------------------------------------------------------------------------- */
-
-/* --------------------- Begin termios2digi_h -------------------- */
+ break;
+ }
+}
+/*
+ * Digi products use fields in their channels structures that are very similar
+ * to the c_cflag and c_iflag fields typically found in UNIX termios
+ * structures. The below three routines allow mappings between these hardware
+ * "flags" and their respective Linux flags.
+ */
static unsigned termios2digi_h(struct channel *ch, unsigned cflag)
-{ /* Begin termios2digi_h */
+{
unsigned res = 0;
if (cflag & CRTSCTS) {
@@ -1918,86 +1765,73 @@ static unsigned termios2digi_h(struct channel *ch, unsigned cflag)
ch->digiext.digi_flags |= CTSPACE;
return res;
+}
-} /* End termios2digi_h */
-
-/* --------------------- Begin termios2digi_i -------------------- */
static unsigned termios2digi_i(struct channel *ch, unsigned iflag)
-{ /* Begin termios2digi_i */
-
- unsigned res = iflag & (IGNBRK | BRKINT | IGNPAR | PARMRK |
+{
+ unsigned res = iflag & (IGNBRK | BRKINT | IGNPAR | PARMRK |
INPCK | ISTRIP|IXON|IXANY|IXOFF);
if (ch->digiext.digi_flags & DIGI_AIXON)
res |= IAIXON;
return res;
-
-} /* End termios2digi_i */
-
-/* --------------------- Begin termios2digi_c -------------------- */
+}
static unsigned termios2digi_c(struct channel *ch, unsigned cflag)
-{ /* Begin termios2digi_c */
-
+{
unsigned res = 0;
- if (cflag & CBAUDEX) { /* Begin detected CBAUDEX */
+ if (cflag & CBAUDEX) {
ch->digiext.digi_flags |= DIGI_FAST;
- /* -------------------------------------------------------------
- HUPCL bit is used by FEP to indicate fast baud
- table is to be used.
- ----------------------------------------------------------------- */
+ /*
+ * HUPCL bit is used by FEP to indicate fast baud table is to
+ * be used.
+ */
res |= FEP_HUPCL;
- } /* End detected CBAUDEX */
- else ch->digiext.digi_flags &= ~DIGI_FAST;
- /* -------------------------------------------------------------------
- CBAUD has bit position 0x1000 set these days to indicate Linux
- baud rate remap. Digi hardware can't handle the bit assignment.
- (We use a different bit assignment for high speed.). Clear this
- bit out.
- ---------------------------------------------------------------------- */
+ } else
+ ch->digiext.digi_flags &= ~DIGI_FAST;
+ /*
+ * CBAUD has bit position 0x1000 set these days to indicate Linux
+ * baud rate remap. Digi hardware can't handle the bit assignment.
+ * (We use a different bit assignment for high speed.). Clear this
+ * bit out.
+ */
res |= cflag & ((CBAUD ^ CBAUDEX) | PARODD | PARENB | CSTOPB | CSIZE);
- /* -------------------------------------------------------------
- This gets a little confusing. The Digi cards have their own
- representation of c_cflags controling baud rate. For the most
- part this is identical to the Linux implementation. However;
- Digi supports one rate (76800) that Linux doesn't. This means
- that the c_cflag entry that would normally mean 76800 for Digi
- actually means 115200 under Linux. Without the below mapping,
- a stty 115200 would only drive the board at 76800. Since
- the rate 230400 is also found after 76800, the same problem afflicts
- us when we choose a rate of 230400. Without the below modificiation
- stty 230400 would actually give us 115200.
-
- There are two additional differences. The Linux value for CLOCAL
- (0x800; 0004000) has no meaning to the Digi hardware. Also in
- later releases of Linux; the CBAUD define has CBAUDEX (0x1000;
- 0010000) ored into it (CBAUD = 0x100f as opposed to 0xf). CBAUDEX
- should be checked for a screened out prior to termios2digi_c
- returning. Since CLOCAL isn't used by the board this can be
- ignored as long as the returned value is used only by Digi hardware.
- ----------------------------------------------------------------- */
+ /*
+ * This gets a little confusing. The Digi cards have their own
+ * representation of c_cflags controling baud rate. For the most part
+ * this is identical to the Linux implementation. However; Digi
+ * supports one rate (76800) that Linux doesn't. This means that the
+ * c_cflag entry that would normally mean 76800 for Digi actually means
+ * 115200 under Linux. Without the below mapping, a stty 115200 would
+ * only drive the board at 76800. Since the rate 230400 is also found
+ * after 76800, the same problem afflicts us when we choose a rate of
+ * 230400. Without the below modificiation stty 230400 would actually
+ * give us 115200.
+ *
+ * There are two additional differences. The Linux value for CLOCAL
+ * (0x800; 0004000) has no meaning to the Digi hardware. Also in later
+ * releases of Linux; the CBAUD define has CBAUDEX (0x1000; 0010000)
+ * ored into it (CBAUD = 0x100f as opposed to 0xf). CBAUDEX should be
+ * checked for a screened out prior to termios2digi_c returning. Since
+ * CLOCAL isn't used by the board this can be ignored as long as the
+ * returned value is used only by Digi hardware.
+ */
if (cflag & CBAUDEX) {
- /* -------------------------------------------------------------
- The below code is trying to guarantee that only baud rates
- 115200 and 230400 are remapped. We use exclusive or because
- the various baud rates share common bit positions and therefore
- can't be tested for easily.
- ----------------------------------------------------------------- */
-
-
- if ((!((cflag & 0x7) ^ (B115200 & ~CBAUDEX))) ||
+ /*
+ * The below code is trying to guarantee that only baud rates
+ * 115200 and 230400 are remapped. We use exclusive or because
+ * the various baud rates share common bit positions and
+ * therefore can't be tested for easily.
+ */
+ if ((!((cflag & 0x7) ^ (B115200 & ~CBAUDEX))) ||
(!((cflag & 0x7) ^ (B230400 & ~CBAUDEX))))
res += 1;
}
return res;
-
-} /* End termios2digi_c */
-
-/* --------------------- Begin epcaparam ----------------------- */
+}
/* Caller must hold the locks */
static void epcaparam(struct tty_struct *tty, struct channel *ch)
-{ /* Begin epcaparam */
-
+{
unsigned int cmdHead;
struct ktermios *ts;
struct board_chan __iomem *bc;
@@ -2013,28 +1847,29 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch)
writew(cmdHead, &bc->rout);
cmdHead = readw(&bc->tin);
/* Changing baud in mid-stream transmission can be wonderful */
- /* ---------------------------------------------------------------
- Flush current transmit buffer by setting cmdTail pointer (tout)
- to cmdHead pointer (tin). Hopefully the transmit buffer is empty.
- ----------------------------------------------------------------- */
+ /*
+ * Flush current transmit buffer by setting cmdTail pointer
+ * (tout) to cmdHead pointer (tin). Hopefully the transmit
+ * buffer is empty.
+ */
fepcmd(ch, STOUT, (unsigned) cmdHead, 0, 0, 0);
mval = 0;
- } else { /* Begin CBAUD not detected */
- /* -------------------------------------------------------------------
- c_cflags have changed but that change had nothing to do with BAUD.
- Propagate the change to the card.
- ---------------------------------------------------------------------- */
+ } else { /* Begin CBAUD not detected */
+ /*
+ * c_cflags have changed but that change had nothing to do with
+ * BAUD. Propagate the change to the card.
+ */
cflag = termios2digi_c(ch, ts->c_cflag);
if (cflag != ch->fepcflag) {
ch->fepcflag = cflag;
/* Set baud rate, char size, stop bits, parity */
fepcmd(ch, SETCTRLFLAGS, (unsigned) cflag, 0, 0, 0);
}
- /* ----------------------------------------------------------------
- If the user has not forced CLOCAL and if the device is not a
- CALLOUT device (Which is always CLOCAL) we set flags such that
- the driver will wait on carrier detect.
- ------------------------------------------------------------------- */
+ /*
+ * If the user has not forced CLOCAL and if the device is not a
+ * CALLOUT device (Which is always CLOCAL) we set flags such
+ * that the driver will wait on carrier detect.
+ */
if (ts->c_cflag & CLOCAL)
ch->asyncflags &= ~ASYNC_CHECK_CD;
else
@@ -2045,19 +1880,19 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch)
/* Check input mode flags */
if (iflag != ch->fepiflag) {
ch->fepiflag = iflag;
- /* ---------------------------------------------------------------
- Command sets channels iflag structure on the board. Such things
- as input soft flow control, handling of parity errors, and
- break handling are all set here.
- ------------------------------------------------------------------- */
+ /*
+ * Command sets channels iflag structure on the board. Such
+ * things as input soft flow control, handling of parity
+ * errors, and break handling are all set here.
+ */
/* break handling, parity handling, input stripping, flow control chars */
fepcmd(ch, SETIFLAGS, (unsigned int) ch->fepiflag, 0, 0, 0);
}
- /* ---------------------------------------------------------------
- Set the board mint value for this channel. This will cause hardware
- events to be generated each time the DCD signal (Described in mint)
- changes.
- ------------------------------------------------------------------- */
+ /*
+ * Set the board mint value for this channel. This will cause hardware
+ * events to be generated each time the DCD signal (Described in mint)
+ * changes.
+ */
writeb(ch->dcd, &bc->mint);
if ((ts->c_cflag & CLOCAL) || (ch->digiext.digi_flags & DIGI_FORCEDCD))
if (ch->digiext.digi_flags & DIGI_FORCEDCD)
@@ -2066,23 +1901,23 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch)
hflow = termios2digi_h(ch, ts->c_cflag);
if (hflow != ch->hflow) {
ch->hflow = hflow;
- /* --------------------------------------------------------------
- Hard flow control has been selected but the board is not
- using it. Activate hard flow control now.
- ----------------------------------------------------------------- */
+ /*
+ * Hard flow control has been selected but the board is not
+ * using it. Activate hard flow control now.
+ */
fepcmd(ch, SETHFLOW, hflow, 0xff, 0, 1);
}
mval ^= ch->modemfake & (mval ^ ch->modem);
if (ch->omodem ^ mval) {
ch->omodem = mval;
- /* --------------------------------------------------------------
- The below command sets the DTR and RTS mstat structure. If
- hard flow control is NOT active these changes will drive the
- output of the actual DTR and RTS lines. If hard flow control
- is active, the changes will be saved in the mstat structure and
- only asserted when hard flow control is turned off.
- ----------------------------------------------------------------- */
+ /*
+ * The below command sets the DTR and RTS mstat structure. If
+ * hard flow control is NOT active these changes will drive the
+ * output of the actual DTR and RTS lines. If hard flow control
+ * is active, the changes will be saved in the mstat structure
+ * and only asserted when hard flow control is turned off.
+ */
/* First reset DTR & RTS; then set them */
fepcmd(ch, SETMODEM, 0, ((ch->m_dtr)|(ch->m_rts)), 0, 1);
@@ -2091,28 +1926,26 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch)
if (ch->startc != ch->fepstartc || ch->stopc != ch->fepstopc) {
ch->fepstartc = ch->startc;
ch->fepstopc = ch->stopc;
- /* ------------------------------------------------------------
- The XON / XOFF characters have changed; propagate these
- changes to the card.
- --------------------------------------------------------------- */
+ /*
+ * The XON / XOFF characters have changed; propagate these
+ * changes to the card.
+ */
fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1);
}
if (ch->startca != ch->fepstartca || ch->stopca != ch->fepstopca) {
ch->fepstartca = ch->startca;
ch->fepstopca = ch->stopca;
- /* ---------------------------------------------------------------
- Similar to the above, this time the auxilarly XON / XOFF
- characters have changed; propagate these changes to the card.
- ------------------------------------------------------------------ */
+ /*
+ * Similar to the above, this time the auxilarly XON / XOFF
+ * characters have changed; propagate these changes to the card.
+ */
fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1);
}
-} /* End epcaparam */
+}
-/* --------------------- Begin receive_data ----------------------- */
/* Caller holds lock */
static void receive_data(struct channel *ch)
-{ /* Begin receive_data */
-
+{
unchar *rptr;
struct ktermios *ts = NULL;
struct tty_struct *tty;
@@ -2121,11 +1954,10 @@ static void receive_data(struct channel *ch)
unsigned int tail, head;
unsigned int wrapmask;
- /* ---------------------------------------------------------------
- This routine is called by doint when a receive data event
- has taken place.
- ------------------------------------------------------------------- */
-
+ /*
+ * This routine is called by doint when a receive data event has taken
+ * place.
+ */
globalwinon(ch);
if (ch->statusflags & RXSTOPPED)
return;
@@ -2136,10 +1968,10 @@ static void receive_data(struct channel *ch)
BUG_ON(!bc);
wrapmask = ch->rxbufsize - 1;
- /* ---------------------------------------------------------------------
- Get the head and tail pointers to the receiver queue. Wrap the
- head pointer if it has reached the end of the buffer.
- ------------------------------------------------------------------------ */
+ /*
+ * Get the head and tail pointers to the receiver queue. Wrap the head
+ * pointer if it has reached the end of the buffer.
+ */
head = readw(&bc->rin);
head &= wrapmask;
tail = readw(&bc->rout) & wrapmask;
@@ -2148,10 +1980,7 @@ static void receive_data(struct channel *ch)
if (bytesAvailable == 0)
return;
- /* ------------------------------------------------------------------
- If CREAD bit is off or device not open, set TX tail to head
- --------------------------------------------------------------------- */
-
+ /* If CREAD bit is off or device not open, set TX tail to head */
if (!tty || !ts || !(ts->c_cflag & CREAD)) {
writew(head, &bc->rout);
return;
@@ -2168,22 +1997,20 @@ static void receive_data(struct channel *ch)
rxwinon(ch);
while (bytesAvailable > 0) { /* Begin while there is data on the card */
wrapgap = (head >= tail) ? head - tail : ch->rxbufsize - tail;
- /* ---------------------------------------------------------------
- Even if head has wrapped around only report the amount of
- data to be equal to the size - tail. Remember memcpy can't
- automaticly wrap around the receive buffer.
- ----------------------------------------------------------------- */
+ /*
+ * Even if head has wrapped around only report the amount of
+ * data to be equal to the size - tail. Remember memcpy can't
+ * automaticly wrap around the receive buffer.
+ */
dataToRead = (wrapgap < bytesAvailable) ? wrapgap : bytesAvailable;
- /* --------------------------------------------------------------
- Make sure we don't overflow the buffer
- ----------------------------------------------------------------- */
+ /* Make sure we don't overflow the buffer */
dataToRead = tty_prepare_flip_string(tty, &rptr, dataToRead);
if (dataToRead == 0)
break;
- /* ---------------------------------------------------------------
- Move data read from our card into the line disciplines buffer
- for translation if necessary.
- ------------------------------------------------------------------ */
+ /*
+ * Move data read from our card into the line disciplines
+ * buffer for translation if necessary.
+ */
memcpy_fromio(rptr, ch->rxptr + tail, dataToRead);
tail = (tail + dataToRead) & wrapmask;
bytesAvailable -= dataToRead;
@@ -2191,28 +2018,26 @@ static void receive_data(struct channel *ch)
globalwinon(ch);
writew(tail, &bc->rout);
/* Must be called with global data */
- tty_schedule_flip(ch->tty);
- return;
-} /* End receive_data */
+ tty_schedule_flip(ch->tty);
+}
-static int info_ioctl(struct tty_struct *tty, struct file * file,
+static int info_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
- switch (cmd)
- { /* Begin switch cmd */
- case DIGI_GETINFO:
- { /* Begin case DIGI_GETINFO */
- struct digi_info di ;
+ switch (cmd) {
+ case DIGI_GETINFO:
+ {
+ struct digi_info di;
int brd;
- if(get_user(brd, (unsigned int __user *)arg))
+ if (get_user(brd, (unsigned int __user *)arg))
return -EFAULT;
if (brd < 0 || brd >= num_cards || num_cards == 0)
return -ENODEV;
memset(&di, 0, sizeof(di));
- di.board = brd ;
+ di.board = brd;
di.status = boards[brd].status;
di.type = boards[brd].type ;
di.numports = boards[brd].numports ;
@@ -2220,45 +2045,44 @@ static int info_ioctl(struct tty_struct *tty, struct file * file,
di.port = (unsigned char *)boards[brd].port ;
di.membase = (unsigned char *)boards[brd].membase ;
- if (copy_to_user((void __user *)arg, &di, sizeof (di)))
+ if (copy_to_user((void __user *)arg, &di, sizeof(di)))
return -EFAULT;
break;
- } /* End case DIGI_GETINFO */
-
- case DIGI_POLLER:
- { /* Begin case DIGI_POLLER */
+ }
- int brd = arg & 0xff000000 >> 16 ;
- unsigned char state = arg & 0xff ;
+ case DIGI_POLLER:
+ {
+ int brd = arg & 0xff000000 >> 16;
+ unsigned char state = arg & 0xff;
if (brd < 0 || brd >= num_cards) {
printk(KERN_ERR "epca: DIGI POLLER : brd not valid!\n");
- return (-ENODEV);
+ return -ENODEV;
}
- digi_poller_inhibited = state ;
- break ;
- } /* End case DIGI_POLLER */
-
- case DIGI_INIT:
- { /* Begin case DIGI_INIT */
- /* ------------------------------------------------------------
- This call is made by the apps to complete the initilization
- of the board(s). This routine is responsible for setting
- the card to its initial state and setting the drivers control
- fields to the sutianle settings for the card in question.
- ---------------------------------------------------------------- */
- int crd ;
- for (crd = 0; crd < num_cards; crd++)
- post_fep_init (crd);
- break ;
- } /* End case DIGI_INIT */
- default:
- return -ENOTTY;
- } /* End switch cmd */
- return (0) ;
+ digi_poller_inhibited = state;
+ break;
+ }
+
+ case DIGI_INIT:
+ {
+ /*
+ * This call is made by the apps to complete the
+ * initilization of the board(s). This routine is
+ * responsible for setting the card to its initial
+ * state and setting the drivers control fields to the
+ * sutianle settings for the card in question.
+ */
+ int crd;
+ for (crd = 0; crd < num_cards; crd++)
+ post_fep_init(crd);
+ break;
+ }
+ default:
+ return -ENOTTY;
+ }
+ return 0;
}
-/* --------------------- Begin pc_ioctl ----------------------- */
static int pc_tiocmget(struct tty_struct *tty, struct file *file)
{
@@ -2304,9 +2128,9 @@ static int pc_tiocmset(struct tty_struct *tty, struct file *file,
spin_lock_irqsave(&epca_lock, flags);
/*
- * I think this modemfake stuff is broken. It doesn't
- * correctly reflect the behaviour desired by the TIOCM*
- * ioctls. Therefore this is probably broken.
+ * I think this modemfake stuff is broken. It doesn't correctly reflect
+ * the behaviour desired by the TIOCM* ioctls. Therefore this is
+ * probably broken.
*/
if (set & TIOCM_RTS) {
ch->modemfake |= ch->m_rts;
@@ -2325,10 +2149,10 @@ static int pc_tiocmset(struct tty_struct *tty, struct file *file,
ch->modem &= ~ch->m_dtr;
}
globalwinon(ch);
- /* --------------------------------------------------------------
- The below routine generally sets up parity, baud, flow control
- issues, etc.... It effect both control flags and input flags.
- ------------------------------------------------------------------ */
+ /*
+ * The below routine generally sets up parity, baud, flow control
+ * issues, etc.... It effect both control flags and input flags.
+ */
epcaparam(tty,ch);
memoff(ch);
spin_unlock_irqrestore(&epca_lock, flags);
@@ -2337,8 +2161,7 @@ static int pc_tiocmset(struct tty_struct *tty, struct file *file,
static int pc_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
-{ /* Begin pc_ioctl */
-
+{
digiflow_t dflow;
int retval;
unsigned long flags;
@@ -2347,49 +2170,47 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
struct board_chan __iomem *bc;
struct channel *ch = (struct channel *) tty->driver_data;
void __user *argp = (void __user *)arg;
-
+
if (ch)
bc = ch->brdchan;
- else
+ else
return -EINVAL;
- /* -------------------------------------------------------------------
- For POSIX compliance we need to add more ioctls. See tty_ioctl.c
- in /usr/src/linux/drivers/char for a good example. In particular
- think about adding TCSETAF, TCSETAW, TCSETA, TCSETSF, TCSETSW, TCSETS.
- ---------------------------------------------------------------------- */
-
- switch (cmd)
- { /* Begin switch cmd */
- case TCSBRK: /* SVID version: non-zero arg --> no break */
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- /* Setup an event to indicate when the transmit buffer empties */
- spin_lock_irqsave(&epca_lock, flags);
- setup_empty_event(tty,ch);
- spin_unlock_irqrestore(&epca_lock, flags);
- tty_wait_until_sent(tty, 0);
- if (!arg)
- digi_send_break(ch, HZ/4); /* 1/4 second */
- return 0;
- case TCSBRKP: /* support for POSIX tcsendbreak() */
- retval = tty_check_change(tty);
- if (retval)
- return retval;
+ /*
+ * For POSIX compliance we need to add more ioctls. See tty_ioctl.c in
+ * /usr/src/linux/drivers/char for a good example. In particular think
+ * about adding TCSETAF, TCSETAW, TCSETA, TCSETSF, TCSETSW, TCSETS.
+ */
+ switch (cmd) {
+ case TCSBRK: /* SVID version: non-zero arg --> no break */
+ retval = tty_check_change(tty);
+ if (retval)
+ return retval;
+ /* Setup an event to indicate when the transmit buffer empties */
+ spin_lock_irqsave(&epca_lock, flags);
+ setup_empty_event(tty,ch);
+ spin_unlock_irqrestore(&epca_lock, flags);
+ tty_wait_until_sent(tty, 0);
+ if (!arg)
+ digi_send_break(ch, HZ / 4); /* 1/4 second */
+ return 0;
+ case TCSBRKP: /* support for POSIX tcsendbreak() */
+ retval = tty_check_change(tty);
+ if (retval)
+ return retval;
- /* Setup an event to indicate when the transmit buffer empties */
- spin_lock_irqsave(&epca_lock, flags);
- setup_empty_event(tty,ch);
- spin_unlock_irqrestore(&epca_lock, flags);
- tty_wait_until_sent(tty, 0);
- digi_send_break(ch, arg ? arg*(HZ/10) : HZ/4);
- return 0;
- case TIOCGSOFTCAR:
- if (put_user(C_CLOCAL(tty)?1:0, (unsigned long __user *)arg))
- return -EFAULT;
- return 0;
- case TIOCSSOFTCAR:
+ /* Setup an event to indicate when the transmit buffer empties */
+ spin_lock_irqsave(&epca_lock, flags);
+ setup_empty_event(tty,ch);
+ spin_unlock_irqrestore(&epca_lock, flags);
+ tty_wait_until_sent(tty, 0);
+ digi_send_break(ch, arg ? arg*(HZ/10) : HZ/4);
+ return 0;
+ case TIOCGSOFTCAR:
+ if (put_user(C_CLOCAL(tty)?1:0, (unsigned long __user *)arg))
+ return -EFAULT;
+ return 0;
+ case TIOCSSOFTCAR:
{
unsigned int value;
@@ -2400,144 +2221,141 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
(value ? CLOCAL : 0));
return 0;
}
- case TIOCMODG:
- mflag = pc_tiocmget(tty, file);
- if (put_user(mflag, (unsigned long __user *)argp))
- return -EFAULT;
- break;
- case TIOCMODS:
- if (get_user(mstat, (unsigned __user *)argp))
- return -EFAULT;
- return pc_tiocmset(tty, file, mstat, ~mstat);
- case TIOCSDTR:
- spin_lock_irqsave(&epca_lock, flags);
- ch->omodem |= ch->m_dtr;
- globalwinon(ch);
- fepcmd(ch, SETMODEM, ch->m_dtr, 0, 10, 1);
- memoff(ch);
- spin_unlock_irqrestore(&epca_lock, flags);
- break;
+ case TIOCMODG:
+ mflag = pc_tiocmget(tty, file);
+ if (put_user(mflag, (unsigned long __user *)argp))
+ return -EFAULT;
+ break;
+ case TIOCMODS:
+ if (get_user(mstat, (unsigned __user *)argp))
+ return -EFAULT;
+ return pc_tiocmset(tty, file, mstat, ~mstat);
+ case TIOCSDTR:
+ spin_lock_irqsave(&epca_lock, flags);
+ ch->omodem |= ch->m_dtr;
+ globalwinon(ch);
+ fepcmd(ch, SETMODEM, ch->m_dtr, 0, 10, 1);
+ memoff(ch);
+ spin_unlock_irqrestore(&epca_lock, flags);
+ break;
- case TIOCCDTR:
+ case TIOCCDTR:
+ spin_lock_irqsave(&epca_lock, flags);
+ ch->omodem &= ~ch->m_dtr;
+ globalwinon(ch);
+ fepcmd(ch, SETMODEM, 0, ch->m_dtr, 10, 1);
+ memoff(ch);
+ spin_unlock_irqrestore(&epca_lock, flags);
+ break;
+ case DIGI_GETA:
+ if (copy_to_user(argp, &ch->digiext, sizeof(digi_t)))
+ return -EFAULT;
+ break;
+ case DIGI_SETAW:
+ case DIGI_SETAF:
+ if (cmd == DIGI_SETAW) {
+ /* Setup an event to indicate when the transmit buffer empties */
spin_lock_irqsave(&epca_lock, flags);
- ch->omodem &= ~ch->m_dtr;
- globalwinon(ch);
- fepcmd(ch, SETMODEM, 0, ch->m_dtr, 10, 1);
- memoff(ch);
+ setup_empty_event(tty,ch);
spin_unlock_irqrestore(&epca_lock, flags);
- break;
- case DIGI_GETA:
- if (copy_to_user(argp, &ch->digiext, sizeof(digi_t)))
- return -EFAULT;
- break;
- case DIGI_SETAW:
- case DIGI_SETAF:
- if (cmd == DIGI_SETAW) {
- /* Setup an event to indicate when the transmit buffer empties */
- spin_lock_irqsave(&epca_lock, flags);
- setup_empty_event(tty,ch);
- spin_unlock_irqrestore(&epca_lock, flags);
- tty_wait_until_sent(tty, 0);
- } else {
- /* ldisc lock already held in ioctl */
- if (tty->ldisc.flush_buffer)
- tty->ldisc.flush_buffer(tty);
- }
- /* Fall Thru */
- case DIGI_SETA:
- if (copy_from_user(&ch->digiext, argp, sizeof(digi_t)))
- return -EFAULT;
-
- if (ch->digiext.digi_flags & DIGI_ALTPIN) {
- ch->dcd = ch->m_dsr;
- ch->dsr = ch->m_dcd;
- } else {
- ch->dcd = ch->m_dcd;
- ch->dsr = ch->m_dsr;
+ tty_wait_until_sent(tty, 0);
+ } else {
+ /* ldisc lock already held in ioctl */
+ if (tty->ldisc.flush_buffer)
+ tty->ldisc.flush_buffer(tty);
+ }
+ /* Fall Thru */
+ case DIGI_SETA:
+ if (copy_from_user(&ch->digiext, argp, sizeof(digi_t)))
+ return -EFAULT;
+
+ if (ch->digiext.digi_flags & DIGI_ALTPIN) {
+ ch->dcd = ch->m_dsr;
+ ch->dsr = ch->m_dcd;
+ } else {
+ ch->dcd = ch->m_dcd;
+ ch->dsr = ch->m_dsr;
}
-
- spin_lock_irqsave(&epca_lock, flags);
- globalwinon(ch);
- /* -----------------------------------------------------------------
- The below routine generally sets up parity, baud, flow control
- issues, etc.... It effect both control flags and input flags.
- ------------------------------------------------------------------- */
+ spin_lock_irqsave(&epca_lock, flags);
+ globalwinon(ch);
- epcaparam(tty,ch);
- memoff(ch);
- spin_unlock_irqrestore(&epca_lock, flags);
- break;
+ /*
+ * The below routine generally sets up parity, baud, flow
+ * control issues, etc.... It effect both control flags and
+ * input flags.
+ */
+ epcaparam(tty,ch);
+ memoff(ch);
+ spin_unlock_irqrestore(&epca_lock, flags);
+ break;
+
+ case DIGI_GETFLOW:
+ case DIGI_GETAFLOW:
+ spin_lock_irqsave(&epca_lock, flags);
+ globalwinon(ch);
+ if (cmd == DIGI_GETFLOW) {
+ dflow.startc = readb(&bc->startc);
+ dflow.stopc = readb(&bc->stopc);
+ } else {
+ dflow.startc = readb(&bc->startca);
+ dflow.stopc = readb(&bc->stopca);
+ }
+ memoff(ch);
+ spin_unlock_irqrestore(&epca_lock, flags);
+
+ if (copy_to_user(argp, &dflow, sizeof(dflow)))
+ return -EFAULT;
+ break;
+
+ case DIGI_SETAFLOW:
+ case DIGI_SETFLOW:
+ if (cmd == DIGI_SETFLOW) {
+ startc = ch->startc;
+ stopc = ch->stopc;
+ } else {
+ startc = ch->startca;
+ stopc = ch->stopca;
+ }
+
+ if (copy_from_user(&dflow, argp, sizeof(dflow)))
+ return -EFAULT;
- case DIGI_GETFLOW:
- case DIGI_GETAFLOW:
+ if (dflow.startc != startc || dflow.stopc != stopc) { /* Begin if setflow toggled */
spin_lock_irqsave(&epca_lock, flags);
globalwinon(ch);
- if (cmd == DIGI_GETFLOW) {
- dflow.startc = readb(&bc->startc);
- dflow.stopc = readb(&bc->stopc);
- } else {
- dflow.startc = readb(&bc->startca);
- dflow.stopc = readb(&bc->stopca);
- }
- memoff(ch);
- spin_unlock_irqrestore(&epca_lock, flags);
- if (copy_to_user(argp, &dflow, sizeof(dflow)))
- return -EFAULT;
- break;
-
- case DIGI_SETAFLOW:
- case DIGI_SETFLOW:
if (cmd == DIGI_SETFLOW) {
- startc = ch->startc;
- stopc = ch->stopc;
+ ch->fepstartc = ch->startc = dflow.startc;
+ ch->fepstopc = ch->stopc = dflow.stopc;
+ fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1);
} else {
- startc = ch->startca;
- stopc = ch->stopca;
+ ch->fepstartca = ch->startca = dflow.startc;
+ ch->fepstopca = ch->stopca = dflow.stopc;
+ fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1);
}
- if (copy_from_user(&dflow, argp, sizeof(dflow)))
- return -EFAULT;
+ if (ch->statusflags & TXSTOPPED)
+ pc_start(tty);
- if (dflow.startc != startc || dflow.stopc != stopc) { /* Begin if setflow toggled */
- spin_lock_irqsave(&epca_lock, flags);
- globalwinon(ch);
-
- if (cmd == DIGI_SETFLOW) {
- ch->fepstartc = ch->startc = dflow.startc;
- ch->fepstopc = ch->stopc = dflow.stopc;
- fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1);
- } else {
- ch->fepstartca = ch->startca = dflow.startc;
- ch->fepstopca = ch->stopca = dflow.stopc;
- fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1);
- }
-
- if (ch->statusflags & TXSTOPPED)
- pc_start(tty);
-
- memoff(ch);
- spin_unlock_irqrestore(&epca_lock, flags);
- } /* End if setflow toggled */
- break;
- default:
- return -ENOIOCTLCMD;
- } /* End switch cmd */
+ memoff(ch);
+ spin_unlock_irqrestore(&epca_lock, flags);
+ } /* End if setflow toggled */
+ break;
+ default:
+ return -ENOIOCTLCMD;
+ }
return 0;
-} /* End pc_ioctl */
-
-/* --------------------- Begin pc_set_termios ----------------------- */
+}
static void pc_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{ /* Begin pc_set_termios */
-
+{
struct channel *ch;
unsigned long flags;
- /* ---------------------------------------------------------
- verifyChannel returns the channel from the tty struct
- if it is valid. This serves as a sanity check.
- ------------------------------------------------------------- */
+ /*
+ * verifyChannel returns the channel from the tty struct if it is
+ * valid. This serves as a sanity check.
+ */
if ((ch = verifyChannel(tty)) != NULL) { /* Begin if channel valid */
spin_lock_irqsave(&epca_lock, flags);
globalwinon(ch);
@@ -2554,47 +2372,40 @@ static void pc_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
wake_up_interruptible(&ch->open_wait);
} /* End if channel valid */
-
-} /* End pc_set_termios */
-
-/* --------------------- Begin do_softint ----------------------- */
+}
static void do_softint(struct work_struct *work)
-{ /* Begin do_softint */
+{
struct channel *ch = container_of(work, struct channel, tqueue);
/* Called in response to a modem change event */
- if (ch && ch->magic == EPCA_MAGIC) { /* Begin EPCA_MAGIC */
+ if (ch && ch->magic == EPCA_MAGIC) {
struct tty_struct *tty = ch->tty;
if (tty && tty->driver_data) {
- if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) { /* Begin if clear_bit */
+ if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) {
tty_hangup(tty); /* FIXME: module removal race here - AKPM */
wake_up_interruptible(&ch->open_wait);
ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE;
- } /* End if clear_bit */
+ }
}
- } /* End EPCA_MAGIC */
-} /* End do_softint */
-
-/* ------------------------------------------------------------
- pc_stop and pc_start provide software flow control to the
- routine and the pc_ioctl routine.
----------------------------------------------------------------- */
-
-/* --------------------- Begin pc_stop ----------------------- */
+ }
+}
+/*
+ * pc_stop and pc_start provide software flow control to the routine and the
+ * pc_ioctl routine.
+ */
static void pc_stop(struct tty_struct *tty)
-{ /* Begin pc_stop */
-
+{
struct channel *ch;
unsigned long flags;
- /* ---------------------------------------------------------
- verifyChannel returns the channel from the tty struct
- if it is valid. This serves as a sanity check.
- ------------------------------------------------------------- */
- if ((ch = verifyChannel(tty)) != NULL) { /* Begin if valid channel */
+ /*
+ * verifyChannel returns the channel from the tty struct if it is
+ * valid. This serves as a sanity check.
+ */
+ if ((ch = verifyChannel(tty)) != NULL) {
spin_lock_irqsave(&epca_lock, flags);
- if ((ch->statusflags & TXSTOPPED) == 0) { /* Begin if transmit stop requested */
+ if ((ch->statusflags & TXSTOPPED) == 0) { /* Begin if transmit stop requested */
globalwinon(ch);
/* STOP transmitting now !! */
fepcmd(ch, PAUSETX, 0, 0, 0, 0);
@@ -2602,19 +2413,17 @@ static void pc_stop(struct tty_struct *tty)
memoff(ch);
} /* End if transmit stop requested */
spin_unlock_irqrestore(&epca_lock, flags);
- } /* End if valid channel */
-} /* End pc_stop */
-
-/* --------------------- Begin pc_start ----------------------- */
+ }
+}
static void pc_start(struct tty_struct *tty)
-{ /* Begin pc_start */
+{
struct channel *ch;
- /* ---------------------------------------------------------
- verifyChannel returns the channel from the tty struct
- if it is valid. This serves as a sanity check.
- ------------------------------------------------------------- */
- if ((ch = verifyChannel(tty)) != NULL) { /* Begin if channel valid */
+ /*
+ * verifyChannel returns the channel from the tty struct if it is
+ * valid. This serves as a sanity check.
+ */
+ if ((ch = verifyChannel(tty)) != NULL) {
unsigned long flags;
spin_lock_irqsave(&epca_lock, flags);
/* Just in case output was resumed because of a change in Digi-flow */
@@ -2630,28 +2439,25 @@ static void pc_start(struct tty_struct *tty)
memoff(ch);
} /* End transmit resume requested */
spin_unlock_irqrestore(&epca_lock, flags);
- } /* End if channel valid */
-} /* End pc_start */
-
-/* ------------------------------------------------------------------
- The below routines pc_throttle and pc_unthrottle are used
- to slow (And resume) the receipt of data into the kernels
- receive buffers. The exact occurrence of this depends on the
- size of the kernels receive buffer and what the 'watermarks'
- are set to for that buffer. See the n_ttys.c file for more
- details.
-______________________________________________________________________ */
-/* --------------------- Begin throttle ----------------------- */
-
-static void pc_throttle(struct tty_struct * tty)
-{ /* Begin pc_throttle */
+ }
+}
+
+/*
+ * The below routines pc_throttle and pc_unthrottle are used to slow (And
+ * resume) the receipt of data into the kernels receive buffers. The exact
+ * occurrence of this depends on the size of the kernels receive buffer and
+ * what the 'watermarks' are set to for that buffer. See the n_ttys.c file for
+ * more details.
+ */
+static void pc_throttle(struct tty_struct *tty)
+{
struct channel *ch;
unsigned long flags;
- /* ---------------------------------------------------------
- verifyChannel returns the channel from the tty struct
- if it is valid. This serves as a sanity check.
- ------------------------------------------------------------- */
- if ((ch = verifyChannel(tty)) != NULL) { /* Begin if channel valid */
+ /*
+ * verifyChannel returns the channel from the tty struct if it is
+ * valid. This serves as a sanity check.
+ */
+ if ((ch = verifyChannel(tty)) != NULL) {
spin_lock_irqsave(&epca_lock, flags);
if ((ch->statusflags & RXSTOPPED) == 0) {
globalwinon(ch);
@@ -2660,20 +2466,18 @@ static void pc_throttle(struct tty_struct * tty)
memoff(ch);
}
spin_unlock_irqrestore(&epca_lock, flags);
- } /* End if channel valid */
-} /* End pc_throttle */
-
-/* --------------------- Begin unthrottle ----------------------- */
+ }
+}
static void pc_unthrottle(struct tty_struct *tty)
-{ /* Begin pc_unthrottle */
+{
struct channel *ch;
unsigned long flags;
- /* ---------------------------------------------------------
- verifyChannel returns the channel from the tty struct
- if it is valid. This serves as a sanity check.
- ------------------------------------------------------------- */
- if ((ch = verifyChannel(tty)) != NULL) { /* Begin if channel valid */
+ /*
+ * verifyChannel returns the channel from the tty struct if it is
+ * valid. This serves as a sanity check.
+ */
+ if ((ch = verifyChannel(tty)) != NULL) {
/* Just in case output was resumed because of a change in Digi-flow */
spin_lock_irqsave(&epca_lock, flags);
if (ch->statusflags & RXSTOPPED) {
@@ -2683,151 +2487,143 @@ static void pc_unthrottle(struct tty_struct *tty)
memoff(ch);
}
spin_unlock_irqrestore(&epca_lock, flags);
- } /* End if channel valid */
-} /* End pc_unthrottle */
-
-/* --------------------- Begin digi_send_break ----------------------- */
+ }
+}
void digi_send_break(struct channel *ch, int msec)
-{ /* Begin digi_send_break */
+{
unsigned long flags;
spin_lock_irqsave(&epca_lock, flags);
globalwinon(ch);
- /* --------------------------------------------------------------------
- Maybe I should send an infinite break here, schedule() for
- msec amount of time, and then stop the break. This way,
- the user can't screw up the FEP by causing digi_send_break()
- to be called (i.e. via an ioctl()) more than once in msec amount
- of time. Try this for now...
- ------------------------------------------------------------------------ */
+ /*
+ * Maybe I should send an infinite break here, schedule() for msec
+ * amount of time, and then stop the break. This way, the user can't
+ * screw up the FEP by causing digi_send_break() to be called (i.e. via
+ * an ioctl()) more than once in msec amount of time.
+ * Try this for now...
+ */
fepcmd(ch, SENDBREAK, msec, 0, 10, 0);
memoff(ch);
spin_unlock_irqrestore(&epca_lock, flags);
-} /* End digi_send_break */
-
-/* --------------------- Begin setup_empty_event ----------------------- */
+}
/* Caller MUST hold the lock */
-
static void setup_empty_event(struct tty_struct *tty, struct channel *ch)
-{ /* Begin setup_empty_event */
-
+{
struct board_chan __iomem *bc = ch->brdchan;
globalwinon(ch);
ch->statusflags |= EMPTYWAIT;
- /* ------------------------------------------------------------------
- When set the iempty flag request a event to be generated when the
- transmit buffer is empty (If there is no BREAK in progress).
- --------------------------------------------------------------------- */
+ /*
+ * When set the iempty flag request a event to be generated when the
+ * transmit buffer is empty (If there is no BREAK in progress).
+ */
writeb(1, &bc->iempty);
memoff(ch);
-} /* End setup_empty_event */
+}
-/* ---------------------- Begin epca_setup -------------------------- */
void epca_setup(char *str, int *ints)
-{ /* Begin epca_setup */
+{
struct board_info board;
int index, loop, last;
char *temp, *t2;
unsigned len;
- /* ----------------------------------------------------------------------
- If this routine looks a little strange it is because it is only called
- if a LILO append command is given to boot the kernel with parameters.
- In this way, we can provide the user a method of changing his board
- configuration without rebuilding the kernel.
- ----------------------------------------------------------------------- */
- if (!liloconfig)
- liloconfig = 1;
+ /*
+ * If this routine looks a little strange it is because it is only
+ * called if a LILO append command is given to boot the kernel with
+ * parameters. In this way, we can provide the user a method of
+ * changing his board configuration without rebuilding the kernel.
+ */
+ if (!liloconfig)
+ liloconfig = 1;
memset(&board, 0, sizeof(board));
/* Assume the data is int first, later we can change it */
/* I think that array position 0 of ints holds the number of args */
for (last = 0, index = 1; index <= ints[0]; index++)
- switch(index)
- { /* Begin parse switch */
- case 1:
- board.status = ints[index];
- /* ---------------------------------------------------------
- We check for 2 (As opposed to 1; because 2 is a flag
- instructing the driver to ignore epcaconfig.) For this
- reason we check for 2.
- ------------------------------------------------------------ */
- if (board.status == 2) { /* Begin ignore epcaconfig as well as lilo cmd line */
- nbdevs = 0;
- num_cards = 0;
- return;
- } /* End ignore epcaconfig as well as lilo cmd line */
-
- if (board.status > 2) {
- printk(KERN_ERR "epca_setup: Invalid board status 0x%x\n", board.status);
- invalid_lilo_config = 1;
- setup_error_code |= INVALID_BOARD_STATUS;
- return;
- }
- last = index;
- break;
- case 2:
- board.type = ints[index];
- if (board.type >= PCIXEM) {
- printk(KERN_ERR "epca_setup: Invalid board type 0x%x\n", board.type);
- invalid_lilo_config = 1;
- setup_error_code |= INVALID_BOARD_TYPE;
- return;
- }
- last = index;
- break;
- case 3:
- board.altpin = ints[index];
- if (board.altpin > 1) {
- printk(KERN_ERR "epca_setup: Invalid board altpin 0x%x\n", board.altpin);
- invalid_lilo_config = 1;
- setup_error_code |= INVALID_ALTPIN;
- return;
- }
- last = index;
- break;
-
- case 4:
- board.numports = ints[index];
- if (board.numports < 2 || board.numports > 256) {
- printk(KERN_ERR "epca_setup: Invalid board numports 0x%x\n", board.numports);
- invalid_lilo_config = 1;
- setup_error_code |= INVALID_NUM_PORTS;
- return;
- }
- nbdevs += board.numports;
- last = index;
- break;
-
- case 5:
- board.port = ints[index];
- if (ints[index] <= 0) {
- printk(KERN_ERR "epca_setup: Invalid io port 0x%x\n", (unsigned int)board.port);
- invalid_lilo_config = 1;
- setup_error_code |= INVALID_PORT_BASE;
- return;
- }
- last = index;
- break;
-
- case 6:
- board.membase = ints[index];
- if (ints[index] <= 0) {
- printk(KERN_ERR "epca_setup: Invalid memory base 0x%x\n",(unsigned int)board.membase);
- invalid_lilo_config = 1;
- setup_error_code |= INVALID_MEM_BASE;
- return;
- }
- last = index;
- break;
+ switch (index) { /* Begin parse switch */
+ case 1:
+ board.status = ints[index];
+ /*
+ * We check for 2 (As opposed to 1; because 2 is a flag
+ * instructing the driver to ignore epcaconfig.) For
+ * this reason we check for 2.
+ */
+ if (board.status == 2) { /* Begin ignore epcaconfig as well as lilo cmd line */
+ nbdevs = 0;
+ num_cards = 0;
+ return;
+ } /* End ignore epcaconfig as well as lilo cmd line */
+
+ if (board.status > 2) {
+ printk(KERN_ERR "epca_setup: Invalid board status 0x%x\n", board.status);
+ invalid_lilo_config = 1;
+ setup_error_code |= INVALID_BOARD_STATUS;
+ return;
+ }
+ last = index;
+ break;
+ case 2:
+ board.type = ints[index];
+ if (board.type >= PCIXEM) {
+ printk(KERN_ERR "epca_setup: Invalid board type 0x%x\n", board.type);
+ invalid_lilo_config = 1;
+ setup_error_code |= INVALID_BOARD_TYPE;
+ return;
+ }
+ last = index;
+ break;
+ case 3:
+ board.altpin = ints[index];
+ if (board.altpin > 1) {
+ printk(KERN_ERR "epca_setup: Invalid board altpin 0x%x\n", board.altpin);
+ invalid_lilo_config = 1;
+ setup_error_code |= INVALID_ALTPIN;
+ return;
+ }
+ last = index;
+ break;
+
+ case 4:
+ board.numports = ints[index];
+ if (board.numports < 2 || board.numports > 256) {
+ printk(KERN_ERR "epca_setup: Invalid board numports 0x%x\n", board.numports);
+ invalid_lilo_config = 1;
+ setup_error_code |= INVALID_NUM_PORTS;
+ return;
+ }
+ nbdevs += board.numports;
+ last = index;
+ break;
- default:
- printk(KERN_ERR "<Error> - epca_setup: Too many integer parms\n");
+ case 5:
+ board.port = ints[index];
+ if (ints[index] <= 0) {
+ printk(KERN_ERR "epca_setup: Invalid io port 0x%x\n", (unsigned int)board.port);
+ invalid_lilo_config = 1;
+ setup_error_code |= INVALID_PORT_BASE;
return;
+ }
+ last = index;
+ break;
+
+ case 6:
+ board.membase = ints[index];
+ if (ints[index] <= 0) {
+ printk(KERN_ERR "epca_setup: Invalid memory base 0x%x\n",(unsigned int)board.membase);
+ invalid_lilo_config = 1;
+ setup_error_code |= INVALID_MEM_BASE;
+ return;
+ }
+ last = index;
+ break;
+
+ default:
+ printk(KERN_ERR "<Error> - epca_setup: Too many integer parms\n");
+ return;
} /* End parse switch */
@@ -2844,120 +2640,121 @@ void epca_setup(char *str, int *ints)
/* Set index to the number of args + 1 */
index = last + 1;
- switch(index)
- {
- case 1:
- len = strlen(str);
- if (strncmp("Disable", str, len) == 0)
- board.status = 0;
- else if (strncmp("Enable", str, len) == 0)
- board.status = 1;
- else {
- printk(KERN_ERR "epca_setup: Invalid status %s\n", str);
- invalid_lilo_config = 1;
- setup_error_code |= INVALID_BOARD_STATUS;
- return;
- }
- last = index;
- break;
-
- case 2:
- for(loop = 0; loop < EPCA_NUM_TYPES; loop++)
- if (strcmp(board_desc[loop], str) == 0)
- break;
- /* ---------------------------------------------------------------
- If the index incremented above refers to a legitamate board
- type set it here.
- ------------------------------------------------------------------*/
- if (index < EPCA_NUM_TYPES)
- board.type = loop;
- else {
- printk(KERN_ERR "epca_setup: Invalid board type: %s\n", str);
- invalid_lilo_config = 1;
- setup_error_code |= INVALID_BOARD_TYPE;
- return;
- }
- last = index;
- break;
-
- case 3:
- len = strlen(str);
- if (strncmp("Disable", str, len) == 0)
- board.altpin = 0;
- else if (strncmp("Enable", str, len) == 0)
- board.altpin = 1;
- else {
- printk(KERN_ERR "epca_setup: Invalid altpin %s\n", str);
- invalid_lilo_config = 1;
- setup_error_code |= INVALID_ALTPIN;
- return;
- }
- last = index;
- break;
-
- case 4:
- t2 = str;
- while (isdigit(*t2))
- t2++;
-
- if (*t2) {
- printk(KERN_ERR "epca_setup: Invalid port count %s\n", str);
- invalid_lilo_config = 1;
- setup_error_code |= INVALID_NUM_PORTS;
- return;
- }
+ switch (index) {
+ case 1:
+ len = strlen(str);
+ if (strncmp("Disable", str, len) == 0)
+ board.status = 0;
+ else if (strncmp("Enable", str, len) == 0)
+ board.status = 1;
+ else {
+ printk(KERN_ERR "epca_setup: Invalid status %s\n", str);
+ invalid_lilo_config = 1;
+ setup_error_code |= INVALID_BOARD_STATUS;
+ return;
+ }
+ last = index;
+ break;
- /* ------------------------------------------------------------
- There is not a man page for simple_strtoul but the code can be
- found in vsprintf.c. The first argument is the string to
- translate (To an unsigned long obviously), the second argument
- can be the address of any character variable or a NULL. If a
- variable is given, the end pointer of the string will be stored
- in that variable; if a NULL is given the end pointer will
- not be returned. The last argument is the base to use. If
- a 0 is indicated, the routine will attempt to determine the
- proper base by looking at the values prefix (A '0' for octal,
- a 'x' for hex, etc ... If a value is given it will use that
- value as the base.
- ---------------------------------------------------------------- */
- board.numports = simple_strtoul(str, NULL, 0);
- nbdevs += board.numports;
- last = index;
- break;
-
- case 5:
- t2 = str;
- while (isxdigit(*t2))
- t2++;
-
- if (*t2) {
- printk(KERN_ERR "epca_setup: Invalid i/o address %s\n", str);
- invalid_lilo_config = 1;
- setup_error_code |= INVALID_PORT_BASE;
- return;
- }
+ case 2:
+ for (loop = 0; loop < EPCA_NUM_TYPES; loop++)
+ if (strcmp(board_desc[loop], str) == 0)
+ break;
+ /*
+ * If the index incremented above refers to a
+ * legitamate board type set it here.
+ */
+ if (index < EPCA_NUM_TYPES)
+ board.type = loop;
+ else {
+ printk(KERN_ERR "epca_setup: Invalid board type: %s\n", str);
+ invalid_lilo_config = 1;
+ setup_error_code |= INVALID_BOARD_TYPE;
+ return;
+ }
+ last = index;
+ break;
- board.port = simple_strtoul(str, NULL, 16);
- last = index;
- break;
+ case 3:
+ len = strlen(str);
+ if (strncmp("Disable", str, len) == 0)
+ board.altpin = 0;
+ else if (strncmp("Enable", str, len) == 0)
+ board.altpin = 1;
+ else {
+ printk(KERN_ERR "epca_setup: Invalid altpin %s\n", str);
+ invalid_lilo_config = 1;
+ setup_error_code |= INVALID_ALTPIN;
+ return;
+ }
+ last = index;
+ break;
- case 6:
- t2 = str;
- while (isxdigit(*t2))
- t2++;
+ case 4:
+ t2 = str;
+ while (isdigit(*t2))
+ t2++;
- if (*t2) {
- printk(KERN_ERR "epca_setup: Invalid memory base %s\n",str);
- invalid_lilo_config = 1;
- setup_error_code |= INVALID_MEM_BASE;
- return;
- }
- board.membase = simple_strtoul(str, NULL, 16);
- last = index;
- break;
- default:
- printk(KERN_ERR "epca: Too many string parms\n");
+ if (*t2) {
+ printk(KERN_ERR "epca_setup: Invalid port count %s\n", str);
+ invalid_lilo_config = 1;
+ setup_error_code |= INVALID_NUM_PORTS;
+ return;
+ }
+
+ /*
+ * There is not a man page for simple_strtoul but the
+ * code can be found in vsprintf.c. The first argument
+ * is the string to translate (To an unsigned long
+ * obviously), the second argument can be the address
+ * of any character variable or a NULL. If a variable
+ * is given, the end pointer of the string will be
+ * stored in that variable; if a NULL is given the end
+ * pointer will not be returned. The last argument is
+ * the base to use. If a 0 is indicated, the routine
+ * will attempt to determine the proper base by looking
+ * at the values prefix (A '0' for octal, a 'x' for
+ * hex, etc ... If a value is given it will use that
+ * value as the base.
+ */
+ board.numports = simple_strtoul(str, NULL, 0);
+ nbdevs += board.numports;
+ last = index;
+ break;
+
+ case 5:
+ t2 = str;
+ while (isxdigit(*t2))
+ t2++;
+
+ if (*t2) {
+ printk(KERN_ERR "epca_setup: Invalid i/o address %s\n", str);
+ invalid_lilo_config = 1;
+ setup_error_code |= INVALID_PORT_BASE;
+ return;
+ }
+
+ board.port = simple_strtoul(str, NULL, 16);
+ last = index;
+ break;
+
+ case 6:
+ t2 = str;
+ while (isxdigit(*t2))
+ t2++;
+
+ if (*t2) {
+ printk(KERN_ERR "epca_setup: Invalid memory base %s\n",str);
+ invalid_lilo_config = 1;
+ setup_error_code |= INVALID_MEM_BASE;
return;
+ }
+ board.membase = simple_strtoul(str, NULL, 16);
+ last = index;
+ break;
+ default:
+ printk(KERN_ERR "epca: Too many string parms\n");
+ return;
}
str = temp;
} /* End while there is a string arg */
@@ -2966,19 +2763,16 @@ void epca_setup(char *str, int *ints)
printk(KERN_ERR "epca: Insufficient parms specified\n");
return;
}
-
+
/* I should REALLY validate the stuff here */
/* Copies our local copy of board into boards */
memcpy((void *)&boards[num_cards],(void *)&board, sizeof(board));
/* Does this get called once per lilo arg are what ? */
- printk(KERN_INFO "PC/Xx: Added board %i, %s %i ports at 0x%4.4X base 0x%6.6X\n",
- num_cards, board_desc[board.type],
+ printk(KERN_INFO "PC/Xx: Added board %i, %s %i ports at 0x%4.4X base 0x%6.6X\n",
+ num_cards, board_desc[board.type],
board.numports, (int)board.port, (unsigned int) board.membase);
num_cards++;
-} /* End epca_setup */
-
-
-/* ------------------------ Begin init_PCI --------------------------- */
+}
enum epic_board_types {
brd_xr = 0,
@@ -2987,7 +2781,6 @@ enum epic_board_types {
brd_xrj,
};
-
/* indexed directly by epic_board_types enum */
static struct {
unsigned char board_type;
@@ -2999,7 +2792,7 @@ static struct {
{ PCIXRJ, 2, },
};
-static int __devinit epca_init_one (struct pci_dev *pdev,
+static int __devinit epca_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
static int board_num = -1;
@@ -3013,7 +2806,7 @@ static int __devinit epca_init_one (struct pci_dev *pdev,
board_idx = board_num + num_cards;
if (board_idx >= MAXBOARDS)
goto err_out;
-
+
addr = pci_resource_start (pdev, epca_info_tbl[info_idx].bar_idx);
if (!addr) {
printk (KERN_ERR PFX "PCI region #%d not available (size 0)\n",
@@ -3053,15 +2846,15 @@ static int __devinit epca_init_one (struct pci_dev *pdev,
goto err_out_free_memregion;
}
- /* --------------------------------------------------------------
- I don't know what the below does, but the hardware guys say
- its required on everything except PLX (In this case XRJ).
- ---------------------------------------------------------------- */
+ /*
+ * I don't know what the below does, but the hardware guys say its
+ * required on everything except PLX (In this case XRJ).
+ */
if (info_idx != brd_xrj) {
- pci_write_config_byte(pdev, 0x40, 0);
+ pci_write_config_byte(pdev, 0x40, 0);
pci_write_config_byte(pdev, 0x46, 0);
}
-
+
return 0;
err_out_free_memregion:
@@ -3086,7 +2879,7 @@ static struct pci_device_id epca_pci_tbl[] = {
MODULE_DEVICE_TABLE(pci, epca_pci_tbl);
int __init init_PCI (void)
-{ /* Begin init_PCI */
+{
memset (&epca_driver, 0, sizeof (epca_driver));
epca_driver.name = "epca";
epca_driver.id_table = epca_pci_tbl;
diff --git a/drivers/char/esp.c b/drivers/char/esp.c
index 2e7ae42a5503..28607763ae64 100644
--- a/drivers/char/esp.c
+++ b/drivers/char/esp.c
@@ -19,7 +19,7 @@
*
* rs_set_termios fixed to look also for changes of the input
* flags INPCK, BRKINT, PARMRK, IGNPAR and IGNBRK.
- * Bernd Anh�pl 05/17/96.
+ * Bernd Anhäupl 05/17/96.
*
* --- End of notices from serial.c ---
*
@@ -58,10 +58,10 @@
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/bitops.h>
#include <asm/system.h>
#include <asm/io.h>
-#include <asm/bitops.h>
#include <asm/dma.h>
#include <linux/slab.h>
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index 83c1151ec7a2..8252f8668538 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -69,6 +69,8 @@ static struct task_struct *hvc_task;
/* Picks up late kicks after list walk but before schedule() */
static int hvc_kicked;
+static int hvc_init(void);
+
#ifdef CONFIG_MAGIC_SYSRQ
static int sysrq_pressed;
#endif
@@ -754,6 +756,13 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
struct hvc_struct *hp;
int i;
+ /* We wait until a driver actually comes along */
+ if (!hvc_driver) {
+ int err = hvc_init();
+ if (err)
+ return ERR_PTR(err);
+ }
+
hp = kmalloc(ALIGN(sizeof(*hp), sizeof(long)) + outbuf_size,
GFP_KERNEL);
if (!hp)
@@ -829,16 +838,18 @@ int __devexit hvc_remove(struct hvc_struct *hp)
return 0;
}
-/* Driver initialization. Follow console initialization. This is where the TTY
- * interfaces start to become available. */
-static int __init hvc_init(void)
+/* Driver initialization: called as soon as someone uses hvc_alloc(). */
+static int hvc_init(void)
{
struct tty_driver *drv;
+ int err;
/* We need more than hvc_count adapters due to hotplug additions. */
drv = alloc_tty_driver(HVC_ALLOC_TTY_ADAPTERS);
- if (!drv)
- return -ENOMEM;
+ if (!drv) {
+ err = -ENOMEM;
+ goto out;
+ }
drv->owner = THIS_MODULE;
drv->driver_name = "hvc";
@@ -854,30 +865,43 @@ static int __init hvc_init(void)
* added later. */
hvc_task = kthread_run(khvcd, NULL, "khvcd");
if (IS_ERR(hvc_task)) {
- panic("Couldn't create kthread for console.\n");
- put_tty_driver(drv);
- return -EIO;
+ printk(KERN_ERR "Couldn't create kthread for console.\n");
+ err = PTR_ERR(hvc_task);
+ goto put_tty;
}
- if (tty_register_driver(drv))
- panic("Couldn't register hvc console driver\n");
+ err = tty_register_driver(drv);
+ if (err) {
+ printk(KERN_ERR "Couldn't register hvc console driver\n");
+ goto stop_thread;
+ }
+ /* FIXME: This mb() seems completely random. Remove it. */
mb();
hvc_driver = drv;
return 0;
+
+put_tty:
+ put_tty_driver(hvc_driver);
+stop_thread:
+ kthread_stop(hvc_task);
+ hvc_task = NULL;
+out:
+ return err;
}
-module_init(hvc_init);
/* This isn't particularly necessary due to this being a console driver
* but it is nice to be thorough.
*/
static void __exit hvc_exit(void)
{
- kthread_stop(hvc_task);
+ if (hvc_driver) {
+ kthread_stop(hvc_task);
- tty_unregister_driver(hvc_driver);
- /* return tty_struct instances allocated in hvc_init(). */
- put_tty_driver(hvc_driver);
- unregister_console(&hvc_con_driver);
+ tty_unregister_driver(hvc_driver);
+ /* return tty_struct instances allocated in hvc_init(). */
+ put_tty_driver(hvc_driver);
+ unregister_console(&hvc_con_driver);
+ }
}
module_exit(hvc_exit);
diff --git a/drivers/char/hvc_lguest.c b/drivers/char/hvc_lguest.c
deleted file mode 100644
index 3d6bd0baa56d..000000000000
--- a/drivers/char/hvc_lguest.c
+++ /dev/null
@@ -1,177 +0,0 @@
-/*D:300
- * The Guest console driver
- *
- * This is a trivial console driver: we use lguest's DMA mechanism to send
- * bytes out, and register a DMA buffer to receive bytes in. It is assumed to
- * be present and available from the very beginning of boot.
- *
- * Writing console drivers is one of the few remaining Dark Arts in Linux.
- * Fortunately for us, the path of virtual consoles has been well-trodden by
- * the PowerPC folks, who wrote "hvc_console.c" to generically support any
- * virtual console. We use that infrastructure which only requires us to write
- * the basic put_chars and get_chars functions and call the right register
- * functions.
- :*/
-
-/*M:002 The console can be flooded: while the Guest is processing input the
- * Host can send more. Buffering in the Host could alleviate this, but it is a
- * difficult problem in general. :*/
-/* Copyright (C) 2006 Rusty Russell, IBM Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/lguest_bus.h>
-#include <asm/paravirt.h>
-#include "hvc_console.h"
-
-/*D:340 This is our single console input buffer, with associated "struct
- * lguest_dma" referring to it. Note the 0-terminated length array, and the
- * use of physical address for the buffer itself. */
-static char inbuf[256];
-static struct lguest_dma cons_input = { .used_len = 0,
- .addr[0] = __pa(inbuf),
- .len[0] = sizeof(inbuf),
- .len[1] = 0 };
-
-/*D:310 The put_chars() callback is pretty straightforward.
- *
- * First we put the pointer and length in a "struct lguest_dma": we only have
- * one pointer, so we set the second length to 0. Then we use SEND_DMA to send
- * the data to (Host) buffers attached to the console key. Usually a device's
- * key is a physical address within the device's memory, but because the
- * console device doesn't have any associated physical memory, we use the
- * LGUEST_CONSOLE_DMA_KEY constant (aka 0). */
-static int put_chars(u32 vtermno, const char *buf, int count)
-{
- struct lguest_dma dma;
-
- /* FIXME: DMA buffers in a "struct lguest_dma" are not allowed
- * to go over page boundaries. This never seems to happen,
- * but if it did we'd need to fix this code. */
- dma.len[0] = count;
- dma.len[1] = 0;
- dma.addr[0] = __pa(buf);
-
- lguest_send_dma(LGUEST_CONSOLE_DMA_KEY, &dma);
- /* We're expected to return the amount of data we wrote: all of it. */
- return count;
-}
-
-/*D:350 get_chars() is the callback from the hvc_console infrastructure when
- * an interrupt is received.
- *
- * Firstly we see if our buffer has been filled: if not, we return. The rest
- * of the code deals with the fact that the hvc_console() infrastructure only
- * asks us for 16 bytes at a time. We keep a "cons_offset" variable for
- * partially-read buffers. */
-static int get_chars(u32 vtermno, char *buf, int count)
-{
- static int cons_offset;
-
- /* Nothing left to see here... */
- if (!cons_input.used_len)
- return 0;
-
- /* You want more than we have to give? Well, try wanting less! */
- if (cons_input.used_len - cons_offset < count)
- count = cons_input.used_len - cons_offset;
-
- /* Copy across to their buffer and increment offset. */
- memcpy(buf, inbuf + cons_offset, count);
- cons_offset += count;
-
- /* Finished? Zero offset, and reset cons_input so Host will use it
- * again. */
- if (cons_offset == cons_input.used_len) {
- cons_offset = 0;
- cons_input.used_len = 0;
- }
- return count;
-}
-/*:*/
-
-static struct hv_ops lguest_cons = {
- .get_chars = get_chars,
- .put_chars = put_chars,
-};
-
-/*D:320 Console drivers are initialized very early so boot messages can go
- * out. At this stage, the console is output-only. Our driver checks we're a
- * Guest, and if so hands hvc_instantiate() the console number (0), priority
- * (0), and the struct hv_ops containing the put_chars() function. */
-static int __init cons_init(void)
-{
- if (strcmp(paravirt_ops.name, "lguest") != 0)
- return 0;
-
- return hvc_instantiate(0, 0, &lguest_cons);
-}
-console_initcall(cons_init);
-
-/*D:370 To set up and manage our virtual console, we call hvc_alloc() and
- * stash the result in the private pointer of the "struct lguest_device".
- * Since we never remove the console device we never need this pointer again,
- * but using ->private is considered good form, and you never know who's going
- * to copy your driver.
- *
- * Once the console is set up, we bind our input buffer ready for input. */
-static int lguestcons_probe(struct lguest_device *lgdev)
-{
- int err;
-
- /* The first argument of hvc_alloc() is the virtual console number, so
- * we use zero. The second argument is the interrupt number.
- *
- * The third argument is a "struct hv_ops" containing the put_chars()
- * and get_chars() pointers. The final argument is the output buffer
- * size: we use 256 and expect the Host to have room for us to send
- * that much. */
- lgdev->private = hvc_alloc(0, lgdev_irq(lgdev), &lguest_cons, 256);
- if (IS_ERR(lgdev->private))
- return PTR_ERR(lgdev->private);
-
- /* We bind a single DMA buffer at key LGUEST_CONSOLE_DMA_KEY.
- * "cons_input" is that statically-initialized global DMA buffer we saw
- * above, and we also give the interrupt we want. */
- err = lguest_bind_dma(LGUEST_CONSOLE_DMA_KEY, &cons_input, 1,
- lgdev_irq(lgdev));
- if (err)
- printk("lguest console: failed to bind buffer.\n");
- return err;
-}
-/* Note the use of lgdev_irq() for the interrupt number. We tell hvc_alloc()
- * to expect input when this interrupt is triggered, and then tell
- * lguest_bind_dma() that is the interrupt to send us when input comes in. */
-
-/*D:360 From now on the console driver follows standard Guest driver form:
- * register_lguest_driver() registers the device type and probe function, and
- * the probe function sets up the device.
- *
- * The standard "struct lguest_driver": */
-static struct lguest_driver lguestcons_drv = {
- .name = "lguestcons",
- .owner = THIS_MODULE,
- .device_type = LGUEST_DEVICE_T_CONSOLE,
- .probe = lguestcons_probe,
-};
-
-/* The standard init function */
-static int __init hvc_lguest_init(void)
-{
- return register_lguest_driver(&lguestcons_drv);
-}
-module_init(hvc_lguest_init);
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
index e13dd1892bfd..3f35a1c562b1 100644
--- a/drivers/char/hw_random/omap-rng.c
+++ b/drivers/char/hw_random/omap-rng.c
@@ -10,7 +10,7 @@
* Mostly based on original driver:
*
* Copyright (C) 2005 Nokia Corporation
- * Author: Juha Yrj��<juha.yrjola@nokia.com>
+ * Author: Juha Yrjölä <juha.yrjola@nokia.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c
index cd406416effd..30e564516422 100644
--- a/drivers/char/i8k.c
+++ b/drivers/char/i8k.c
@@ -371,14 +371,14 @@ static int i8k_proc_show(struct seq_file *seq, void *offset)
int fn_key, cpu_temp, ac_power;
int left_fan, right_fan, left_speed, right_speed;
- cpu_temp = i8k_get_temp(0); /* 11100 µs */
- left_fan = i8k_get_fan_status(I8K_FAN_LEFT); /* 580 µs */
- right_fan = i8k_get_fan_status(I8K_FAN_RIGHT); /* 580 µs */
- left_speed = i8k_get_fan_speed(I8K_FAN_LEFT); /* 580 µs */
- right_speed = i8k_get_fan_speed(I8K_FAN_RIGHT); /* 580 µs */
- fn_key = i8k_get_fn_status(); /* 750 µs */
+ cpu_temp = i8k_get_temp(0); /* 11100 µs */
+ left_fan = i8k_get_fan_status(I8K_FAN_LEFT); /* 580 µs */
+ right_fan = i8k_get_fan_status(I8K_FAN_RIGHT); /* 580 µs */
+ left_speed = i8k_get_fan_speed(I8K_FAN_LEFT); /* 580 µs */
+ right_speed = i8k_get_fan_speed(I8K_FAN_RIGHT); /* 580 µs */
+ fn_key = i8k_get_fn_status(); /* 750 µs */
if (power_status)
- ac_power = i8k_get_power_status(); /* 14700 µs */
+ ac_power = i8k_get_power_status(); /* 14700 µs */
else
ac_power = -1;
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c
index bd94d5f9e62b..e04e66cf2c68 100644
--- a/drivers/char/ip2/ip2main.c
+++ b/drivers/char/ip2/ip2main.c
@@ -619,11 +619,7 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
ip2config.irq[i] = pci_dev_i->irq;
} else { // ann error
ip2config.addr[i] = 0;
- if (status == PCIBIOS_DEVICE_NOT_FOUND) {
- printk( KERN_ERR "IP2: PCI board %d not found\n", i );
- } else {
- printk( KERN_ERR "IP2: PCI error 0x%x \n", status );
- }
+ printk(KERN_ERR "IP2: PCI board %d not found\n", i);
}
}
#else
@@ -646,10 +642,9 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
if ( ip2config.addr[i] ) {
- pB = kmalloc( sizeof(i2eBordStr), GFP_KERNEL);
- if ( pB != NULL ) {
+ pB = kzalloc(sizeof(i2eBordStr), GFP_KERNEL);
+ if (pB) {
i2BoardPtrTable[i] = pB;
- memset( pB, 0, sizeof(i2eBordStr) );
iiSetAddress( pB, ip2config.addr[i], ii2DelayTimer );
iiReset( pB );
} else {
@@ -757,7 +752,7 @@ retry:
continue;
rc = request_irq( ip2config.irq[i], ip2_interrupt,
IP2_SA_FLAGS | (ip2config.type[i] == PCI ? IRQF_SHARED : 0),
- pcName, (void *)&pcName);
+ pcName, i2BoardPtrTable[i]);
if (rc) {
printk(KERN_ERR "IP2: an request_irq failed: error %d\n",rc);
ip2config.irq[i] = CIR_POLL;
@@ -1171,12 +1166,37 @@ ip2_interrupt_bh(struct work_struct *work)
/* */
/* */
/******************************************************************************/
-static irqreturn_t
-ip2_interrupt(int irq, void *dev_id)
+static void
+ip2_irq_work(i2eBordStrPtr pB)
+{
+#ifdef USE_IQI
+ if (NO_MAIL_HERE != ( pB->i2eStartMail = iiGetMail(pB))) {
+// Disable his interrupt (will be enabled when serviced)
+// This is mostly to protect from reentrancy.
+ iiDisableMailIrq(pB);
+
+// Park the board on the immediate queue for processing.
+ schedule_work(&pB->tqueue_interrupt);
+
+// Make sure the immediate queue is flagged to fire.
+ }
+#else
+
+// We are using immediate servicing here. This sucks and can
+// cause all sorts of havoc with ppp and others. The failsafe
+// check on iiSendPendingMail could also throw a hairball.
+
+ i2ServiceBoard( pB );
+
+#endif /* USE_IQI */
+}
+
+static void
+ip2_polled_interrupt(void)
{
int i;
i2eBordStrPtr pB;
- int handled = 0;
+ const int irq = 0;
ip2trace (ITRC_NO_PORT, ITRC_INTR, 99, 1, irq );
@@ -1188,32 +1208,28 @@ ip2_interrupt(int irq, void *dev_id)
// IRQ = 0 for polled boards, we won't poll "IRQ" boards
if ( pB && (pB->i2eUsingIrq == irq) ) {
- handled = 1;
-#ifdef USE_IQI
+ ip2_irq_work(pB);
+ }
+ }
- if (NO_MAIL_HERE != ( pB->i2eStartMail = iiGetMail(pB))) {
-// Disable his interrupt (will be enabled when serviced)
-// This is mostly to protect from reentrancy.
- iiDisableMailIrq(pB);
+ ++irq_counter;
-// Park the board on the immediate queue for processing.
- schedule_work(&pB->tqueue_interrupt);
+ ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 );
+}
-// Make sure the immediate queue is flagged to fire.
- }
-#else
-// We are using immediate servicing here. This sucks and can
-// cause all sorts of havoc with ppp and others. The failsafe
-// check on iiSendPendingMail could also throw a hairball.
- i2ServiceBoard( pB );
-#endif /* USE_IQI */
- }
- }
+static irqreturn_t
+ip2_interrupt(int irq, void *dev_id)
+{
+ i2eBordStrPtr pB = dev_id;
+
+ ip2trace (ITRC_NO_PORT, ITRC_INTR, 99, 1, pB->i2eUsingIrq );
+
+ ip2_irq_work(pB);
++irq_counter;
ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 );
- return IRQ_RETVAL(handled);
+ return IRQ_HANDLED;
}
/******************************************************************************/
@@ -1236,7 +1252,7 @@ ip2_poll(unsigned long arg)
// Just polled boards, IRQ = 0 will hit all non-interrupt boards.
// It will NOT poll boards handled by hard interrupts.
// The issue of queued BH interrups is handled in ip2_interrupt().
- ip2_interrupt(0, NULL);
+ ip2_polled_interrupt();
PollTimer.expires = POLL_TIMEOUT;
add_timer( &PollTimer );
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 6a01dd9e43f8..5dc1265ce1d5 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -221,10 +221,8 @@ struct ipmi_smi
void *send_info;
#ifdef CONFIG_PROC_FS
- /* A list of proc entries for this interface. This does not
- need a lock, only one thread creates it and only one thread
- destroys it. */
- spinlock_t proc_entry_lock;
+ /* A list of proc entries for this interface. */
+ struct mutex proc_entry_lock;
struct ipmi_proc_entry *proc_entries;
#endif
@@ -1891,11 +1889,11 @@ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,
file->write_proc = write_proc;
file->owner = owner;
- spin_lock(&smi->proc_entry_lock);
+ mutex_lock(&smi->proc_entry_lock);
/* Stick it on the list. */
entry->next = smi->proc_entries;
smi->proc_entries = entry;
- spin_unlock(&smi->proc_entry_lock);
+ mutex_unlock(&smi->proc_entry_lock);
}
#endif /* CONFIG_PROC_FS */
@@ -1939,7 +1937,7 @@ static void remove_proc_entries(ipmi_smi_t smi)
#ifdef CONFIG_PROC_FS
struct ipmi_proc_entry *entry;
- spin_lock(&smi->proc_entry_lock);
+ mutex_lock(&smi->proc_entry_lock);
while (smi->proc_entries) {
entry = smi->proc_entries;
smi->proc_entries = entry->next;
@@ -1948,7 +1946,7 @@ static void remove_proc_entries(ipmi_smi_t smi)
kfree(entry->name);
kfree(entry);
}
- spin_unlock(&smi->proc_entry_lock);
+ mutex_unlock(&smi->proc_entry_lock);
remove_proc_entry(smi->proc_dir_name, proc_ipmi_root);
#endif /* CONFIG_PROC_FS */
}
@@ -2614,6 +2612,14 @@ channel_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg)
return;
}
+void ipmi_poll_interface(ipmi_user_t user)
+{
+ ipmi_smi_t intf = user->intf;
+
+ if (intf->handlers->poll)
+ intf->handlers->poll(intf->send_info);
+}
+
int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
void *send_info,
struct ipmi_device_id *device_id,
@@ -2671,7 +2677,7 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
}
intf->curr_seq = 0;
#ifdef CONFIG_PROC_FS
- spin_lock_init(&intf->proc_entry_lock);
+ mutex_init(&intf->proc_entry_lock);
#endif
spin_lock_init(&intf->waiting_msgs_lock);
INIT_LIST_HEAD(&intf->waiting_msgs);
@@ -4136,7 +4142,7 @@ static __exit void cleanup_ipmi(void)
del_timer_sync(&ipmi_timer);
#ifdef CONFIG_PROC_FS
- remove_proc_entry(proc_ipmi_root->name, &proc_root);
+ remove_proc_entry(proc_ipmi_root->name, NULL);
#endif /* CONFIG_PROC_FS */
driver_unregister(&ipmidriver);
@@ -4166,6 +4172,7 @@ EXPORT_SYMBOL(ipmi_destroy_user);
EXPORT_SYMBOL(ipmi_get_version);
EXPORT_SYMBOL(ipmi_request_settime);
EXPORT_SYMBOL(ipmi_request_supply_msgs);
+EXPORT_SYMBOL(ipmi_poll_interface);
EXPORT_SYMBOL(ipmi_register_smi);
EXPORT_SYMBOL(ipmi_unregister_smi);
EXPORT_SYMBOL(ipmi_register_for_cmd);
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index c1222e98525d..4f560d0bb808 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -675,7 +675,8 @@ static void handle_transaction_done(struct smi_info *smi_info)
}
/* Called on timeouts and events. Timeouts should pass the elapsed
- time, interrupts should pass in zero. */
+ time, interrupts should pass in zero. Must be called with
+ si_lock held and interrupts disabled. */
static enum si_sm_result smi_event_handler(struct smi_info *smi_info,
int time)
{
@@ -892,13 +893,16 @@ static int ipmi_thread(void *data)
static void poll(void *send_info)
{
struct smi_info *smi_info = send_info;
+ unsigned long flags;
/*
* Make sure there is some delay in the poll loop so we can
* drive time forward and timeout things.
*/
udelay(10);
+ spin_lock_irqsave(&smi_info->si_lock, flags);
smi_event_handler(smi_info, 10);
+ spin_unlock_irqrestore(&smi_info->si_lock, flags);
}
static void request_events(void *send_info)
@@ -1006,6 +1010,10 @@ static int smi_start_processing(void *send_info,
new_smi->intf = intf;
+ /* Try to claim any interrupts. */
+ if (new_smi->irq_setup)
+ new_smi->irq_setup(new_smi);
+
/* Set up the timer that drives the interface. */
setup_timer(&new_smi->si_timer, smi_timeout, (long)new_smi);
new_smi->last_timeout_jiffies = jiffies;
@@ -2372,20 +2380,9 @@ static int try_get_dev_id(struct smi_info *smi_info)
/* Otherwise, we got some data. */
resp_len = smi_info->handlers->get_result(smi_info->si_sm,
resp, IPMI_MAX_MSG_LENGTH);
- if (resp_len < 14) {
- /* That's odd, it should be longer. */
- rv = -EINVAL;
- goto out;
- }
- if ((resp[1] != IPMI_GET_DEVICE_ID_CMD) || (resp[2] != 0)) {
- /* That's odd, it shouldn't be able to fail. */
- rv = -EINVAL;
- goto out;
- }
-
- /* Record info from the get device id, in case we need it. */
- ipmi_demangle_device_id(resp+3, resp_len-3, &smi_info->device_id);
+ /* Check and record info from the get device id, in case we need it. */
+ rv = ipmi_demangle_device_id(resp, resp_len, &smi_info->device_id);
out:
kfree(resp);
@@ -2765,10 +2762,6 @@ static int try_smi_init(struct smi_info *new_smi)
setup_oem_data_handler(new_smi);
setup_xaction_handlers(new_smi);
- /* Try to claim any interrupts. */
- if (new_smi->irq_setup)
- new_smi->irq_setup(new_smi);
-
INIT_LIST_HEAD(&(new_smi->xmit_msgs));
INIT_LIST_HEAD(&(new_smi->hp_xmit_msgs));
new_smi->curr_msg = NULL;
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
index 41f78e2c158f..e686fc925168 100644
--- a/drivers/char/ipmi/ipmi_watchdog.c
+++ b/drivers/char/ipmi/ipmi_watchdog.c
@@ -50,10 +50,19 @@
#include <linux/poll.h>
#include <linux/string.h>
#include <linux/ctype.h>
+#include <linux/delay.h>
#include <asm/atomic.h>
-#ifdef CONFIG_X86_LOCAL_APIC
-#include <asm/apic.h>
+#ifdef CONFIG_X86
+/* This is ugly, but I've determined that x86 is the only architecture
+ that can reasonably support the IPMI NMI watchdog timeout at this
+ time. If another architecture adds this capability somehow, it
+ will have to be a somewhat different mechanism and I have no idea
+ how it will work. So in the unlikely event that another
+ architecture supports this, we can figure out a good generic
+ mechanism for it at that time. */
+#include <asm/kdebug.h>
+#define HAVE_DIE_NMI
#endif
#define PFX "IPMI Watchdog: "
@@ -166,8 +175,6 @@ static char expect_close;
static int ifnum_to_use = -1;
-static DECLARE_RWSEM(register_sem);
-
/* Parameters to ipmi_set_timeout */
#define IPMI_SET_TIMEOUT_NO_HB 0
#define IPMI_SET_TIMEOUT_HB_IF_NECESSARY 1
@@ -193,11 +200,9 @@ static int set_param_int(const char *val, struct kernel_param *kp)
if (endp == val)
return -EINVAL;
- down_read(&register_sem);
*((int *)kp->arg) = l;
if (watchdog_user)
rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
- up_read(&register_sem);
return rv;
}
@@ -226,17 +231,15 @@ static int set_param_str(const char *val, struct kernel_param *kp)
s = strstrip(valcp);
- down_read(&register_sem);
rv = fn(s, NULL);
if (rv)
- goto out_unlock;
+ goto out;
check_parms();
if (watchdog_user)
rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
- out_unlock:
- up_read(&register_sem);
+ out:
return rv;
}
@@ -319,9 +322,12 @@ static unsigned char ipmi_version_minor;
/* If a pretimeout occurs, this is used to allow only one panic to happen. */
static atomic_t preop_panic_excl = ATOMIC_INIT(-1);
-static int ipmi_heartbeat(void);
-static void panic_halt_ipmi_heartbeat(void);
+#ifdef HAVE_DIE_NMI
+static int testing_nmi;
+static int nmi_handler_registered;
+#endif
+static int ipmi_heartbeat(void);
/* We use a mutex to make sure that only one thing can send a set
timeout at one time, because we only have one copy of the data.
@@ -360,6 +366,9 @@ static int i_ipmi_set_timeout(struct ipmi_smi_msg *smi_msg,
int hbnow = 0;
+ /* These can be cleared as we are setting the timeout. */
+ pretimeout_since_last_heartbeat = 0;
+
data[0] = 0;
WDOG_SET_TIMER_USE(data[0], WDOG_TIMER_USE_SMS_OS);
@@ -434,31 +443,75 @@ static int ipmi_set_timeout(int do_heartbeat)
wait_for_completion(&set_timeout_wait);
+ mutex_unlock(&set_timeout_lock);
+
if ((do_heartbeat == IPMI_SET_TIMEOUT_FORCE_HB)
|| ((send_heartbeat_now)
&& (do_heartbeat == IPMI_SET_TIMEOUT_HB_IF_NECESSARY)))
- {
rv = ipmi_heartbeat();
- }
- mutex_unlock(&set_timeout_lock);
out:
return rv;
}
-static void dummy_smi_free(struct ipmi_smi_msg *msg)
+static atomic_t panic_done_count = ATOMIC_INIT(0);
+
+static void panic_smi_free(struct ipmi_smi_msg *msg)
{
+ atomic_dec(&panic_done_count);
}
-static void dummy_recv_free(struct ipmi_recv_msg *msg)
+static void panic_recv_free(struct ipmi_recv_msg *msg)
{
+ atomic_dec(&panic_done_count);
+}
+
+static struct ipmi_smi_msg panic_halt_heartbeat_smi_msg =
+{
+ .done = panic_smi_free
+};
+static struct ipmi_recv_msg panic_halt_heartbeat_recv_msg =
+{
+ .done = panic_recv_free
+};
+
+static void panic_halt_ipmi_heartbeat(void)
+{
+ struct kernel_ipmi_msg msg;
+ struct ipmi_system_interface_addr addr;
+ int rv;
+
+ /* Don't reset the timer if we have the timer turned off, that
+ re-enables the watchdog. */
+ if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)
+ return;
+
+ addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+ addr.channel = IPMI_BMC_CHANNEL;
+ addr.lun = 0;
+
+ msg.netfn = 0x06;
+ msg.cmd = IPMI_WDOG_RESET_TIMER;
+ msg.data = NULL;
+ msg.data_len = 0;
+ rv = ipmi_request_supply_msgs(watchdog_user,
+ (struct ipmi_addr *) &addr,
+ 0,
+ &msg,
+ NULL,
+ &panic_halt_heartbeat_smi_msg,
+ &panic_halt_heartbeat_recv_msg,
+ 1);
+ if (!rv)
+ atomic_add(2, &panic_done_count);
}
+
static struct ipmi_smi_msg panic_halt_smi_msg =
{
- .done = dummy_smi_free
+ .done = panic_smi_free
};
static struct ipmi_recv_msg panic_halt_recv_msg =
{
- .done = dummy_recv_free
+ .done = panic_recv_free
};
/* Special call, doesn't claim any locks. This is only to be called
@@ -470,13 +523,21 @@ static void panic_halt_ipmi_set_timeout(void)
int send_heartbeat_now;
int rv;
+ /* Wait for the messages to be free. */
+ while (atomic_read(&panic_done_count) != 0)
+ ipmi_poll_interface(watchdog_user);
rv = i_ipmi_set_timeout(&panic_halt_smi_msg,
&panic_halt_recv_msg,
&send_heartbeat_now);
if (!rv) {
+ atomic_add(2, &panic_done_count);
if (send_heartbeat_now)
panic_halt_ipmi_heartbeat();
- }
+ } else
+ printk(KERN_WARNING PFX
+ "Unable to extend the watchdog timeout.");
+ while (atomic_read(&panic_done_count) != 0)
+ ipmi_poll_interface(watchdog_user);
}
/* We use a semaphore to make sure that only one thing can send a
@@ -505,24 +566,14 @@ static struct ipmi_recv_msg heartbeat_recv_msg =
.done = heartbeat_free_recv
};
-static struct ipmi_smi_msg panic_halt_heartbeat_smi_msg =
-{
- .done = dummy_smi_free
-};
-static struct ipmi_recv_msg panic_halt_heartbeat_recv_msg =
-{
- .done = dummy_recv_free
-};
-
static int ipmi_heartbeat(void)
{
struct kernel_ipmi_msg msg;
int rv;
struct ipmi_system_interface_addr addr;
- if (ipmi_ignore_heartbeat) {
+ if (ipmi_ignore_heartbeat)
return 0;
- }
if (ipmi_start_timer_on_heartbeat) {
ipmi_start_timer_on_heartbeat = 0;
@@ -533,7 +584,6 @@ static int ipmi_heartbeat(void)
We don't want to set the action, though, we want to
leave that alone (thus it can't be combined with the
above operation. */
- pretimeout_since_last_heartbeat = 0;
return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
}
@@ -586,35 +636,6 @@ static int ipmi_heartbeat(void)
return rv;
}
-static void panic_halt_ipmi_heartbeat(void)
-{
- struct kernel_ipmi_msg msg;
- struct ipmi_system_interface_addr addr;
-
-
- /* Don't reset the timer if we have the timer turned off, that
- re-enables the watchdog. */
- if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)
- return;
-
- addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
- addr.channel = IPMI_BMC_CHANNEL;
- addr.lun = 0;
-
- msg.netfn = 0x06;
- msg.cmd = IPMI_WDOG_RESET_TIMER;
- msg.data = NULL;
- msg.data_len = 0;
- ipmi_request_supply_msgs(watchdog_user,
- (struct ipmi_addr *) &addr,
- 0,
- &msg,
- NULL,
- &panic_halt_heartbeat_smi_msg,
- &panic_halt_heartbeat_recv_msg,
- 1);
-}
-
static struct watchdog_info ident =
{
.options = 0, /* WDIOF_SETTIMEOUT, */
@@ -895,7 +916,6 @@ static void ipmi_register_watchdog(int ipmi_intf)
{
int rv = -EBUSY;
- down_write(&register_sem);
if (watchdog_user)
goto out;
@@ -921,15 +941,56 @@ static void ipmi_register_watchdog(int ipmi_intf)
printk(KERN_CRIT PFX "Unable to register misc device\n");
}
- out:
- up_write(&register_sem);
+#ifdef HAVE_DIE_NMI
+ if (nmi_handler_registered) {
+ int old_pretimeout = pretimeout;
+ int old_timeout = timeout;
+ int old_preop_val = preop_val;
+
+ /* Set the pretimeout to go off in a second and give
+ ourselves plenty of time to stop the timer. */
+ ipmi_watchdog_state = WDOG_TIMEOUT_RESET;
+ preop_val = WDOG_PREOP_NONE; /* Make sure nothing happens */
+ pretimeout = 99;
+ timeout = 100;
+
+ testing_nmi = 1;
+
+ rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB);
+ if (rv) {
+ printk(KERN_WARNING PFX "Error starting timer to"
+ " test NMI: 0x%x. The NMI pretimeout will"
+ " likely not work\n", rv);
+ rv = 0;
+ goto out_restore;
+ }
+
+ msleep(1500);
+ if (testing_nmi != 2) {
+ printk(KERN_WARNING PFX "IPMI NMI didn't seem to"
+ " occur. The NMI pretimeout will"
+ " likely not work\n");
+ }
+ out_restore:
+ testing_nmi = 0;
+ preop_val = old_preop_val;
+ pretimeout = old_pretimeout;
+ timeout = old_timeout;
+ }
+#endif
+
+ out:
if ((start_now) && (rv == 0)) {
/* Run from startup, so start the timer now. */
start_now = 0; /* Disable this function after first startup. */
ipmi_watchdog_state = action_val;
ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB);
printk(KERN_INFO PFX "Starting now!\n");
+ } else {
+ /* Stop the timer now. */
+ ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
+ ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB);
}
}
@@ -937,8 +998,6 @@ static void ipmi_unregister_watchdog(int ipmi_intf)
{
int rv;
- down_write(&register_sem);
-
if (!watchdog_user)
goto out;
@@ -963,20 +1022,44 @@ static void ipmi_unregister_watchdog(int ipmi_intf)
watchdog_user = NULL;
out:
- up_write(&register_sem);
+ return;
}
-#ifdef HAVE_NMI_HANDLER
+#ifdef HAVE_DIE_NMI
static int
-ipmi_nmi(void *dev_id, int cpu, int handled)
+ipmi_nmi(struct notifier_block *self, unsigned long val, void *data)
{
+ struct die_args *args = data;
+
+ if (val != DIE_NMI)
+ return NOTIFY_OK;
+
+ /* Hack, if it's a memory or I/O error, ignore it. */
+ if (args->err & 0xc0)
+ return NOTIFY_OK;
+
+ /*
+ * If we get here, it's an NMI that's not a memory or I/O
+ * error. We can't truly tell if it's from IPMI or not
+ * without sending a message, and sending a message is almost
+ * impossible because of locking.
+ */
+
+ if (testing_nmi) {
+ testing_nmi = 2;
+ return NOTIFY_STOP;
+ }
+
/* If we are not expecting a timeout, ignore it. */
if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)
- return NOTIFY_DONE;
+ return NOTIFY_OK;
+
+ if (preaction_val != WDOG_PRETIMEOUT_NMI)
+ return NOTIFY_OK;
/* If no one else handled the NMI, we assume it was the IPMI
watchdog. */
- if ((!handled) && (preop_val == WDOG_PREOP_PANIC)) {
+ if (preop_val == WDOG_PREOP_PANIC) {
/* On some machines, the heartbeat will give
an error and not work unless we re-enable
the timer. So do so. */
@@ -985,18 +1068,12 @@ ipmi_nmi(void *dev_id, int cpu, int handled)
panic(PFX "pre-timeout");
}
- return NOTIFY_DONE;
+ return NOTIFY_STOP;
}
-static struct nmi_handler ipmi_nmi_handler =
-{
- .link = LIST_HEAD_INIT(ipmi_nmi_handler.link),
- .dev_name = "ipmi_watchdog",
- .dev_id = NULL,
- .handler = ipmi_nmi,
- .priority = 0, /* Call us last. */
+static struct notifier_block ipmi_nmi_handler = {
+ .notifier_call = ipmi_nmi
};
-int nmi_handler_registered;
#endif
static int wdog_reboot_handler(struct notifier_block *this,
@@ -1009,7 +1086,7 @@ static int wdog_reboot_handler(struct notifier_block *this,
/* Make sure we only do this once. */
reboot_event_handled = 1;
- if (code == SYS_DOWN || code == SYS_HALT) {
+ if (code == SYS_POWER_OFF || code == SYS_HALT) {
/* Disable the WDT if we are shutting down. */
ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
panic_halt_ipmi_set_timeout();
@@ -1113,7 +1190,7 @@ static int preaction_op(const char *inval, char *outval)
preaction_val = WDOG_PRETIMEOUT_NONE;
else if (strcmp(inval, "pre_smi") == 0)
preaction_val = WDOG_PRETIMEOUT_SMI;
-#ifdef HAVE_NMI_HANDLER
+#ifdef HAVE_DIE_NMI
else if (strcmp(inval, "pre_nmi") == 0)
preaction_val = WDOG_PRETIMEOUT_NMI;
#endif
@@ -1147,7 +1224,7 @@ static int preop_op(const char *inval, char *outval)
static void check_parms(void)
{
-#ifdef HAVE_NMI_HANDLER
+#ifdef HAVE_DIE_NMI
int do_nmi = 0;
int rv;
@@ -1160,20 +1237,9 @@ static void check_parms(void)
preop_op("preop_none", NULL);
do_nmi = 0;
}
-#ifdef CONFIG_X86_LOCAL_APIC
- if (nmi_watchdog == NMI_IO_APIC) {
- printk(KERN_WARNING PFX "nmi_watchdog is set to IO APIC"
- " mode (value is %d), that is incompatible"
- " with using NMI in the IPMI watchdog."
- " Disabling IPMI nmi pretimeout.\n",
- nmi_watchdog);
- preaction_val = WDOG_PRETIMEOUT_NONE;
- do_nmi = 0;
- }
-#endif
}
if (do_nmi && !nmi_handler_registered) {
- rv = request_nmi(&ipmi_nmi_handler);
+ rv = register_die_notifier(&ipmi_nmi_handler);
if (rv) {
printk(KERN_WARNING PFX
"Can't register nmi handler\n");
@@ -1181,7 +1247,7 @@ static void check_parms(void)
} else
nmi_handler_registered = 1;
} else if (!do_nmi && nmi_handler_registered) {
- release_nmi(&ipmi_nmi_handler);
+ unregister_die_notifier(&ipmi_nmi_handler);
nmi_handler_registered = 0;
}
#endif
@@ -1217,9 +1283,9 @@ static int __init ipmi_wdog_init(void)
rv = ipmi_smi_watcher_register(&smi_watcher);
if (rv) {
-#ifdef HAVE_NMI_HANDLER
- if (preaction_val == WDOG_PRETIMEOUT_NMI)
- release_nmi(&ipmi_nmi_handler);
+#ifdef HAVE_DIE_NMI
+ if (nmi_handler_registered)
+ unregister_die_notifier(&ipmi_nmi_handler);
#endif
atomic_notifier_chain_unregister(&panic_notifier_list,
&wdog_panic_notifier);
@@ -1238,9 +1304,9 @@ static void __exit ipmi_wdog_exit(void)
ipmi_smi_watcher_unregister(&smi_watcher);
ipmi_unregister_watchdog(watchdog_ifnum);
-#ifdef HAVE_NMI_HANDLER
+#ifdef HAVE_DIE_NMI
if (nmi_handler_registered)
- release_nmi(&ipmi_nmi_handler);
+ unregister_die_notifier(&ipmi_nmi_handler);
#endif
atomic_notifier_chain_unregister(&panic_notifier_list,
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index 77a7a4a06620..85d596a3c18c 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -1529,7 +1529,7 @@ static int __devinit reset_card(struct pci_dev *pdev,
portcount = inw(base + 0x2);
if (!inw(base + 0xe) & 0x1 || (portcount != 0 && portcount != 4 &&
portcount != 8 && portcount != 16)) {
- dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure.",
+ dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure.\n",
card + 1);
retval = -EIO;
goto end;
@@ -1622,7 +1622,9 @@ static int __devinit load_firmware(struct pci_dev *pdev,
if ((status = inw(base + 0x4)) != 0) {
dev_warn(&pdev->dev, "Card%d rejected load header:\n"
- "Address:0x%x\nCount:0x%x\nStatus:0x%x\n",
+ KERN_WARNING "Address:0x%x\n"
+ KERN_WARNING "Count:0x%x\n"
+ KERN_WARNING "Status:0x%x\n",
index + 1, frame->addr, frame->count, status);
goto errrelfw;
}
@@ -1666,7 +1668,9 @@ static int __devinit load_firmware(struct pci_dev *pdev,
if ((status = inw(base + 0x4)) != 0) {
dev_warn(&pdev->dev, "Card%d rejected verify header:\n"
- "Address:0x%x\nCount:0x%x\nStatus: 0x%x\n",
+ KERN_WARNING "Address:0x%x\n"
+ KERN_WARNING "Count:0x%x\n"
+ KERN_WARNING "Status: 0x%x\n",
index + 1, frame->addr, frame->count, status);
goto errrelfw;
}
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index d95f316afb5a..fc54d234507a 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -38,9 +38,11 @@
#include <linux/kbd_kern.h>
#include <linux/kbd_diacr.h>
#include <linux/vt_kern.h>
+#include <linux/consolemap.h>
#include <linux/sysrq.h>
#include <linux/input.h>
#include <linux/reboot.h>
+#include <linux/notifier.h>
extern void ctrl_alt_del(void);
@@ -80,7 +82,8 @@ void compute_shiftstate(void);
typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value,
char up_flag);
static k_handler_fn K_HANDLERS;
-static k_handler_fn *k_handler[16] = { K_HANDLERS };
+k_handler_fn *k_handler[16] = { K_HANDLERS };
+EXPORT_SYMBOL_GPL(k_handler);
#define FN_HANDLERS\
fn_null, fn_enter, fn_show_ptregs, fn_show_mem,\
@@ -126,7 +129,7 @@ int shift_state = 0;
*/
static struct input_handler kbd_handler;
-static unsigned long key_down[NBITS(KEY_MAX)]; /* keyboard key bitmap */
+static unsigned long key_down[BITS_TO_LONGS(KEY_CNT)]; /* keyboard key bitmap */
static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */
static int dead_key_next;
static int npadch = -1; /* -1 or number assembled on pad */
@@ -159,6 +162,23 @@ static int sysrq_alt_use;
static int sysrq_alt;
/*
+ * Notifier list for console keyboard events
+ */
+static ATOMIC_NOTIFIER_HEAD(keyboard_notifier_list);
+
+int register_keyboard_notifier(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_register(&keyboard_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(register_keyboard_notifier);
+
+int unregister_keyboard_notifier(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_unregister(&keyboard_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(unregister_keyboard_notifier);
+
+/*
* Translation of scancodes to keycodes. We set them on only the first
* keyboard in the list that accepts the scancode and keycode.
* Explanation for not choosing the first attached keyboard anymore:
@@ -403,9 +423,12 @@ static unsigned int handle_diacr(struct vc_data *vc, unsigned int ch)
return d;
if (kbd->kbdmode == VC_UNICODE)
- to_utf8(vc, conv_8bit_to_uni(d));
- else if (d < 0x100)
- put_queue(vc, d);
+ to_utf8(vc, d);
+ else {
+ int c = conv_uni_to_8bit(d);
+ if (c != -1)
+ put_queue(vc, c);
+ }
return ch;
}
@@ -417,9 +440,12 @@ static void fn_enter(struct vc_data *vc)
{
if (diacr) {
if (kbd->kbdmode == VC_UNICODE)
- to_utf8(vc, conv_8bit_to_uni(diacr));
- else if (diacr < 0x100)
- put_queue(vc, diacr);
+ to_utf8(vc, diacr);
+ else {
+ int c = conv_uni_to_8bit(diacr);
+ if (c != -1)
+ put_queue(vc, c);
+ }
diacr = 0;
}
put_queue(vc, 13);
@@ -627,9 +653,12 @@ static void k_unicode(struct vc_data *vc, unsigned int value, char up_flag)
return;
}
if (kbd->kbdmode == VC_UNICODE)
- to_utf8(vc, conv_8bit_to_uni(value));
- else if (value < 0x100)
- put_queue(vc, value);
+ to_utf8(vc, value);
+ else {
+ int c = conv_uni_to_8bit(value);
+ if (c != -1)
+ put_queue(vc, c);
+ }
}
/*
@@ -646,7 +675,12 @@ static void k_deadunicode(struct vc_data *vc, unsigned int value, char up_flag)
static void k_self(struct vc_data *vc, unsigned char value, char up_flag)
{
- k_unicode(vc, value, up_flag);
+ unsigned int uni;
+ if (kbd->kbdmode == VC_UNICODE)
+ uni = value;
+ else
+ uni = conv_8bit_to_uni(value);
+ k_unicode(vc, uni, up_flag);
}
static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag)
@@ -1115,6 +1149,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
unsigned char type, raw_mode;
struct tty_struct *tty;
int shift_final;
+ struct keyboard_notifier_param param = { .vc = vc, .value = keycode, .down = down };
tty = vc->vc_tty;
@@ -1202,10 +1237,11 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
return;
}
- shift_final = (shift_state | kbd->slockstate) ^ kbd->lockstate;
+ param.shift = shift_final = (shift_state | kbd->slockstate) ^ kbd->lockstate;
key_map = key_maps[shift_final];
- if (!key_map) {
+ if (atomic_notifier_call_chain(&keyboard_notifier_list, KBD_KEYCODE, &param) == NOTIFY_STOP || !key_map) {
+ atomic_notifier_call_chain(&keyboard_notifier_list, KBD_UNBOUND_KEYCODE, &param);
compute_shiftstate();
kbd->slockstate = 0;
return;
@@ -1222,6 +1258,9 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
type = KTYP(keysym);
if (type < 0xf0) {
+ param.value = keysym;
+ if (atomic_notifier_call_chain(&keyboard_notifier_list, KBD_UNICODE, &param) == NOTIFY_STOP)
+ return;
if (down && !raw_mode)
to_utf8(vc, keysym);
return;
@@ -1229,9 +1268,6 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
type -= 0xf0;
- if (raw_mode && type != KT_SPEC && type != KT_SHIFT)
- return;
-
if (type == KT_LETTER) {
type = KT_LATIN;
if (vc_kbd_led(kbd, VC_CAPSLOCK)) {
@@ -1240,9 +1276,18 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
keysym = key_map[keycode];
}
}
+ param.value = keysym;
+
+ if (atomic_notifier_call_chain(&keyboard_notifier_list, KBD_KEYSYM, &param) == NOTIFY_STOP)
+ return;
+
+ if (raw_mode && type != KT_SPEC && type != KT_SHIFT)
+ return;
(*k_handler[type])(vc, keysym & 0xff, !down);
+ atomic_notifier_call_chain(&keyboard_notifier_list, KBD_POST_KEYSYM, &param);
+
if (type != KT_SLOCK)
kbd->slockstate = 0;
}
@@ -1332,12 +1377,12 @@ static void kbd_start(struct input_handle *handle)
static const struct input_device_id kbd_ids[] = {
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
- .evbit = { BIT(EV_KEY) },
+ .evbit = { BIT_MASK(EV_KEY) },
},
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
- .evbit = { BIT(EV_SND) },
+ .evbit = { BIT_MASK(EV_SND) },
},
{ }, /* Terminating entry */
@@ -1366,7 +1411,7 @@ int __init kbd_init(void)
kbd_table[i].lockstate = KBD_DEFLOCK;
kbd_table[i].slockstate = 0;
kbd_table[i].modeflags = KBD_DEFMODE;
- kbd_table[i].kbdmode = VC_XLATE;
+ kbd_table[i].kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE;
}
error = input_register_handler(&kbd_handler);
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index c59e2a0996cc..81674d7c56c7 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -144,7 +144,7 @@ static unsigned int lp_count = 0;
static struct class *lp_class;
#ifdef CONFIG_LP_CONSOLE
-static struct parport *console_registered; // initially NULL
+static struct parport *console_registered;
#endif /* CONFIG_LP_CONSOLE */
#undef LP_DEBUG
@@ -749,8 +749,8 @@ static struct console lpcons = {
/* --- initialisation code ------------------------------------- */
static int parport_nr[LP_NO] = { [0 ... LP_NO-1] = LP_PARPORT_UNSPEC };
-static char *parport[LP_NO] = { NULL, };
-static int reset = 0;
+static char *parport[LP_NO];
+static int reset;
module_param_array(parport, charp, NULL, 0);
module_param(reset, bool, 0);
@@ -758,10 +758,10 @@ module_param(reset, bool, 0);
#ifndef MODULE
static int __init lp_setup (char *str)
{
- static int parport_ptr; // initially zero
+ static int parport_ptr;
int x;
- if (get_option (&str, &x)) {
+ if (get_option(&str, &x)) {
if (x == 0) {
/* disable driver on "lp=" or "lp=0" */
parport_nr[0] = LP_PARPORT_OFF;
@@ -807,7 +807,7 @@ static int lp_register(int nr, struct parport *port)
#ifdef CONFIG_LP_CONSOLE
if (!nr) {
if (port->modes & PARPORT_MODE_SAFEININT) {
- register_console (&lpcons);
+ register_console(&lpcons);
console_registered = port;
printk (KERN_INFO "lp%d: console ready\n", CONSOLE_LP);
} else
@@ -823,8 +823,7 @@ static void lp_attach (struct parport *port)
{
unsigned int i;
- switch (parport_nr[0])
- {
+ switch (parport_nr[0]) {
case LP_PARPORT_UNSPEC:
case LP_PARPORT_AUTO:
if (parport_nr[0] == LP_PARPORT_AUTO &&
@@ -855,7 +854,7 @@ static void lp_detach (struct parport *port)
/* Write this some day. */
#ifdef CONFIG_LP_CONSOLE
if (console_registered == port) {
- unregister_console (&lpcons);
+ unregister_console(&lpcons);
console_registered = NULL;
}
#endif /* CONFIG_LP_CONSOLE */
diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c
index 7ee5d9444926..3c5802ae1716 100644
--- a/drivers/char/mbcs.c
+++ b/drivers/char/mbcs.c
@@ -22,7 +22,6 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/mm.h>
-#include <linux/fs.h>
#include <linux/uio.h>
#include <asm/io.h>
#include <asm/uaccess.h>
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index bbee97ff355f..20070b7c573d 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -41,7 +41,7 @@
*/
static inline int uncached_access(struct file *file, unsigned long addr)
{
-#if defined(__i386__)
+#if defined(__i386__) && !defined(__arch_um__)
/*
* On the PPro and successors, the MTRRs are used to set
* memory types for physical addresses outside main memory,
@@ -57,7 +57,7 @@ static inline int uncached_access(struct file *file, unsigned long addr)
test_bit(X86_FEATURE_CYRIX_ARR, boot_cpu_data.x86_capability) ||
test_bit(X86_FEATURE_CENTAUR_MCR, boot_cpu_data.x86_capability) )
&& addr >= __pa(high_memory);
-#elif defined(__x86_64__)
+#elif defined(__x86_64__) && !defined(__arch_um__)
/*
* This is broken because it can generate memory type aliases,
* which can cause cache corruptions
@@ -625,65 +625,10 @@ static ssize_t splice_write_null(struct pipe_inode_info *pipe,struct file *out,
return splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_null);
}
-#ifdef CONFIG_MMU
-/*
- * For fun, we are using the MMU for this.
- */
-static inline size_t read_zero_pagealigned(char __user * buf, size_t size)
-{
- struct mm_struct *mm;
- struct vm_area_struct * vma;
- unsigned long addr=(unsigned long)buf;
-
- mm = current->mm;
- /* Oops, this was forgotten before. -ben */
- down_read(&mm->mmap_sem);
-
- /* For private mappings, just map in zero pages. */
- for (vma = find_vma(mm, addr); vma; vma = vma->vm_next) {
- unsigned long count;
-
- if (vma->vm_start > addr || (vma->vm_flags & VM_WRITE) == 0)
- goto out_up;
- if (vma->vm_flags & (VM_SHARED | VM_HUGETLB))
- break;
- count = vma->vm_end - addr;
- if (count > size)
- count = size;
-
- zap_page_range(vma, addr, count, NULL);
- if (zeromap_page_range(vma, addr, count, PAGE_COPY))
- break;
-
- size -= count;
- buf += count;
- addr += count;
- if (size == 0)
- goto out_up;
- }
-
- up_read(&mm->mmap_sem);
-
- /* The shared case is hard. Let's do the conventional zeroing. */
- do {
- unsigned long unwritten = clear_user(buf, PAGE_SIZE);
- if (unwritten)
- return size + unwritten - PAGE_SIZE;
- cond_resched();
- buf += PAGE_SIZE;
- size -= PAGE_SIZE;
- } while (size);
-
- return size;
-out_up:
- up_read(&mm->mmap_sem);
- return size;
-}
-
static ssize_t read_zero(struct file * file, char __user * buf,
size_t count, loff_t *ppos)
{
- unsigned long left, unwritten, written = 0;
+ size_t written;
if (!count)
return 0;
@@ -691,69 +636,33 @@ static ssize_t read_zero(struct file * file, char __user * buf,
if (!access_ok(VERIFY_WRITE, buf, count))
return -EFAULT;
- left = count;
-
- /* do we want to be clever? Arbitrary cut-off */
- if (count >= PAGE_SIZE*4) {
- unsigned long partial;
+ written = 0;
+ while (count) {
+ unsigned long unwritten;
+ size_t chunk = count;
- /* How much left of the page? */
- partial = (PAGE_SIZE-1) & -(unsigned long) buf;
- unwritten = clear_user(buf, partial);
- written = partial - unwritten;
- if (unwritten)
- goto out;
- left -= partial;
- buf += partial;
- unwritten = read_zero_pagealigned(buf, left & PAGE_MASK);
- written += (left & PAGE_MASK) - unwritten;
+ if (chunk > PAGE_SIZE)
+ chunk = PAGE_SIZE; /* Just for latency reasons */
+ unwritten = clear_user(buf, chunk);
+ written += chunk - unwritten;
if (unwritten)
- goto out;
- buf += left & PAGE_MASK;
- left &= ~PAGE_MASK;
- }
- unwritten = clear_user(buf, left);
- written += left - unwritten;
-out:
- return written ? written : -EFAULT;
-}
-
-static int mmap_zero(struct file * file, struct vm_area_struct * vma)
-{
- int err;
-
- if (vma->vm_flags & VM_SHARED)
- return shmem_zero_setup(vma);
- err = zeromap_page_range(vma, vma->vm_start,
- vma->vm_end - vma->vm_start, vma->vm_page_prot);
- BUG_ON(err == -EEXIST);
- return err;
-}
-#else /* CONFIG_MMU */
-static ssize_t read_zero(struct file * file, char * buf,
- size_t count, loff_t *ppos)
-{
- size_t todo = count;
-
- while (todo) {
- size_t chunk = todo;
-
- if (chunk > 4096)
- chunk = 4096; /* Just for latency reasons */
- if (clear_user(buf, chunk))
- return -EFAULT;
+ break;
buf += chunk;
- todo -= chunk;
+ count -= chunk;
cond_resched();
}
- return count;
+ return written ? written : -EFAULT;
}
static int mmap_zero(struct file * file, struct vm_area_struct * vma)
{
+#ifndef CONFIG_MMU
return -ENOSYS;
+#endif
+ if (vma->vm_flags & VM_SHARED)
+ return shmem_zero_setup(vma);
+ return 0;
}
-#endif /* CONFIG_MMU */
static ssize_t write_full(struct file * file, const char __user * buf,
size_t count, loff_t *ppos)
@@ -984,6 +893,11 @@ static struct class *mem_class;
static int __init chr_dev_init(void)
{
int i;
+ int err;
+
+ err = bdi_init(&zero_bdi);
+ if (err)
+ return err;
if (register_chrdev(MEM_MAJOR,"mem",&memory_fops))
printk("unable to get major %d for memory devs\n", MEM_MAJOR);
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index ed76f0a127fd..2fc255a21486 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -41,6 +41,7 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/bitops.h>
+#include <linux/completion.h>
#include <asm/system.h>
#include <asm/io.h>
@@ -142,7 +143,7 @@ struct moxa_port {
struct tty_struct *tty;
int cflag;
wait_queue_head_t open_wait;
- wait_queue_head_t close_wait;
+ struct completion close_wait;
struct timer_list emptyTimer;
@@ -166,7 +167,6 @@ struct moxa_port {
#define WAKEUP_CHARS 256
-static int verbose = 0;
static int ttymajor = MOXAMAJOR;
/* Variables for insmod */
#ifdef MODULE
@@ -184,7 +184,6 @@ module_param_array(baseaddr, int, NULL, 0);
module_param_array(numports, int, NULL, 0);
#endif
module_param(ttymajor, int, 0);
-module_param(verbose, bool, 0644);
/*
* static functions:
@@ -208,13 +207,13 @@ static int moxa_tiocmget(struct tty_struct *tty, struct file *file);
static int moxa_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear);
static void moxa_poll(unsigned long);
-static void set_tty_param(struct tty_struct *);
-static int block_till_ready(struct tty_struct *, struct file *,
+static void moxa_set_tty_param(struct tty_struct *);
+static int moxa_block_till_ready(struct tty_struct *, struct file *,
struct moxa_port *);
-static void setup_empty_event(struct tty_struct *);
-static void check_xmit_empty(unsigned long);
-static void shut_down(struct moxa_port *);
-static void receive_data(struct moxa_port *);
+static void moxa_setup_empty_event(struct tty_struct *);
+static void moxa_check_xmit_empty(unsigned long);
+static void moxa_shut_down(struct moxa_port *);
+static void moxa_receive_data(struct moxa_port *);
/*
* moxa board interface functions:
*/
@@ -283,8 +282,10 @@ static int __devinit moxa_pci_probe(struct pci_dev *pdev,
int retval;
retval = pci_enable_device(pdev);
- if (retval)
+ if (retval) {
+ dev_err(&pdev->dev, "can't enable pci device\n");
goto err;
+ }
for (i = 0; i < MAX_BOARDS; i++)
if (moxa_boards[i].basemem == NULL)
@@ -292,16 +293,17 @@ static int __devinit moxa_pci_probe(struct pci_dev *pdev,
retval = -ENODEV;
if (i >= MAX_BOARDS) {
- if (verbose)
- printk("More than %d MOXA Intellio family boards "
+ dev_warn(&pdev->dev, "more than %u MOXA Intellio family boards "
"found. Board is ignored.\n", MAX_BOARDS);
goto err;
}
board = &moxa_boards[i];
board->basemem = pci_iomap(pdev, 2, 0x4000);
- if (board->basemem == NULL)
+ if (board->basemem == NULL) {
+ dev_err(&pdev->dev, "can't remap io space 2\n");
goto err;
+ }
board->boardType = board_type;
switch (board_type) {
@@ -347,7 +349,8 @@ static int __init moxa_init(void)
int i, numBoards, retval = 0;
struct moxa_port *ch;
- printk(KERN_INFO "MOXA Intellio family driver version %s\n", MOXA_VERSION);
+ printk(KERN_INFO "MOXA Intellio family driver version %s\n",
+ MOXA_VERSION);
moxaDriver = alloc_tty_driver(MAX_PORTS + 1);
if (!moxaDriver)
return -ENOMEM;
@@ -372,13 +375,13 @@ static int __init moxa_init(void)
ch->closing_wait = 30 * HZ;
ch->cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
init_waitqueue_head(&ch->open_wait);
- init_waitqueue_head(&ch->close_wait);
+ init_completion(&ch->close_wait);
- setup_timer(&ch->emptyTimer, check_xmit_empty,
+ setup_timer(&ch->emptyTimer, moxa_check_xmit_empty,
(unsigned long)ch);
}
- printk("Tty devices major number = %d\n", ttymajor);
+ pr_debug("Moxa tty devices major number = %d\n", ttymajor);
if (tty_register_driver(moxaDriver)) {
printk(KERN_ERR "Couldn't install MOXA Smartio family driver !\n");
@@ -400,11 +403,10 @@ static int __init moxa_init(void)
moxa_boards[numBoards].numPorts = moxa_isa_boards[i].numPorts;
moxa_boards[numBoards].busType = MOXA_BUS_TYPE_ISA;
moxa_boards[numBoards].baseAddr = moxa_isa_boards[i].baseAddr;
- if (verbose)
- printk("Board %2d: %s board(baseAddr=%lx)\n",
- numBoards + 1,
- moxa_brdname[moxa_boards[numBoards].boardType - 1],
- moxa_boards[numBoards].baseAddr);
+ pr_debug("Moxa board %2d: %s board(baseAddr=%lx)\n",
+ numBoards + 1,
+ moxa_brdname[moxa_boards[numBoards].boardType-1],
+ moxa_boards[numBoards].baseAddr);
numBoards++;
}
}
@@ -413,14 +415,13 @@ static int __init moxa_init(void)
for (i = 0; i < MAX_BOARDS; i++) {
if ((type[i] == MOXA_BOARD_C218_ISA) ||
(type[i] == MOXA_BOARD_C320_ISA)) {
- if (verbose)
- printk("Board %2d: %s board(baseAddr=%lx)\n",
- numBoards + 1,
- moxa_brdname[type[i] - 1],
- (unsigned long) baseaddr[i]);
+ pr_debug("Moxa board %2d: %s board(baseAddr=%lx)\n",
+ numBoards + 1, moxa_brdname[type[i] - 1],
+ (unsigned long)baseaddr[i]);
if (numBoards >= MAX_BOARDS) {
- if (verbose)
- printk("More than %d MOXA Intellio family boards found. Board is ignored.", MAX_BOARDS);
+ printk(KERN_WARNING "More than %d MOXA "
+ "Intellio family boards found. Board "
+ "is ignored.\n", MAX_BOARDS);
continue;
}
moxa_boards[numBoards].boardType = type[i];
@@ -456,16 +457,14 @@ static void __exit moxa_exit(void)
{
int i;
- if (verbose)
- printk("Unloading module moxa ...\n");
-
del_timer_sync(&moxaTimer);
for (i = 0; i < MAX_PORTS; i++)
del_timer_sync(&moxa_ports[i].emptyTimer);
if (tty_unregister_driver(moxaDriver))
- printk("Couldn't unregister MOXA Intellio family serial driver\n");
+ printk(KERN_ERR "Couldn't unregister MOXA Intellio family "
+ "serial driver\n");
put_tty_driver(moxaDriver);
#ifdef CONFIG_PCI
@@ -475,9 +474,6 @@ static void __exit moxa_exit(void)
for (i = 0; i < MAX_BOARDS; i++)
if (moxa_boards[i].basemem)
iounmap(moxa_boards[i].basemem);
-
- if (verbose)
- printk("Done\n");
}
module_init(moxa_init);
@@ -504,12 +500,12 @@ static int moxa_open(struct tty_struct *tty, struct file *filp)
ch->tty = tty;
if (!(ch->asyncflags & ASYNC_INITIALIZED)) {
ch->statusflags = 0;
- set_tty_param(tty);
+ moxa_set_tty_param(tty);
MoxaPortLineCtrl(ch->port, 1, 1);
MoxaPortEnable(ch->port);
ch->asyncflags |= ASYNC_INITIALIZED;
}
- retval = block_till_ready(tty, filp, ch);
+ retval = moxa_block_till_ready(tty, filp, ch);
moxa_unthrottle(tty);
@@ -532,9 +528,7 @@ static void moxa_close(struct tty_struct *tty, struct file *filp)
return;
}
if (!MoxaPortIsValid(port)) {
-#ifdef SERIAL_DEBUG_CLOSE
- printk("Invalid portno in moxa_close\n");
-#endif
+ pr_debug("Invalid portno in moxa_close\n");
tty->driver_data = NULL;
return;
}
@@ -547,13 +541,13 @@ static void moxa_close(struct tty_struct *tty, struct file *filp)
ch = (struct moxa_port *) tty->driver_data;
if ((tty->count == 1) && (ch->count != 1)) {
- printk("moxa_close: bad serial port count; tty->count is 1, "
- "ch->count is %d\n", ch->count);
+ printk(KERN_WARNING "moxa_close: bad serial port count; "
+ "tty->count is 1, ch->count is %d\n", ch->count);
ch->count = 1;
}
if (--ch->count < 0) {
- printk("moxa_close: bad serial port count, device=%s\n",
- tty->name);
+ printk(KERN_WARNING "moxa_close: bad serial port count, "
+ "device=%s\n", tty->name);
ch->count = 0;
}
if (ch->count) {
@@ -563,11 +557,11 @@ static void moxa_close(struct tty_struct *tty, struct file *filp)
ch->cflag = tty->termios->c_cflag;
if (ch->asyncflags & ASYNC_INITIALIZED) {
- setup_empty_event(tty);
+ moxa_setup_empty_event(tty);
tty_wait_until_sent(tty, 30 * HZ); /* 30 seconds timeout */
del_timer_sync(&moxa_ports[ch->port].emptyTimer);
}
- shut_down(ch);
+ moxa_shut_down(ch);
MoxaPortFlushData(port, 2);
if (tty->driver->flush_buffer)
@@ -584,7 +578,7 @@ static void moxa_close(struct tty_struct *tty, struct file *filp)
wake_up_interruptible(&ch->open_wait);
}
ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
- wake_up_interruptible(&ch->close_wait);
+ complete_all(&ch->close_wait);
}
static int moxa_write(struct tty_struct *tty,
@@ -653,7 +647,7 @@ static int moxa_chars_in_buffer(struct tty_struct *tty)
* in tty_ioctl.c, etc.
*/
if (!(ch->statusflags & EMPTYWAIT))
- setup_empty_event(tty);
+ moxa_setup_empty_event(tty);
}
return (chars);
}
@@ -751,7 +745,7 @@ static int moxa_ioctl(struct tty_struct *tty, struct file *file,
retval = tty_check_change(tty);
if (retval)
return (retval);
- setup_empty_event(tty);
+ moxa_setup_empty_event(tty);
tty_wait_until_sent(tty, 0);
if (!arg)
MoxaPortSendBreak(ch->port, 0);
@@ -760,7 +754,7 @@ static int moxa_ioctl(struct tty_struct *tty, struct file *file,
retval = tty_check_change(tty);
if (retval)
return (retval);
- setup_empty_event(tty);
+ moxa_setup_empty_event(tty);
tty_wait_until_sent(tty, 0);
MoxaPortSendBreak(ch->port, arg);
return (0);
@@ -809,7 +803,7 @@ static void moxa_set_termios(struct tty_struct *tty,
if (ch == NULL)
return;
- set_tty_param(tty);
+ moxa_set_tty_param(tty);
if (!(old_termios->c_cflag & CLOCAL) &&
(tty->termios->c_cflag & CLOCAL))
wake_up_interruptible(&ch->open_wait);
@@ -845,7 +839,7 @@ static void moxa_hangup(struct tty_struct *tty)
struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
moxa_flush_buffer(tty);
- shut_down(ch);
+ moxa_shut_down(ch);
ch->event = 0;
ch->count = 0;
ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE;
@@ -875,7 +869,7 @@ static void moxa_poll(unsigned long ignored)
continue;
if (!(ch->statusflags & THROTTLE) &&
(MoxaPortRxQueue(ch->port) > 0))
- receive_data(ch);
+ moxa_receive_data(ch);
if ((tp = ch->tty) == 0)
continue;
if (ch->statusflags & LOWWAIT) {
@@ -909,7 +903,7 @@ static void moxa_poll(unsigned long ignored)
/******************************************************************************/
-static void set_tty_param(struct tty_struct *tty)
+static void moxa_set_tty_param(struct tty_struct *tty)
{
register struct ktermios *ts;
struct moxa_port *ch;
@@ -934,7 +928,7 @@ static void set_tty_param(struct tty_struct *tty)
MoxaPortSetTermio(ch->port, ts, tty_get_baud_rate(tty));
}
-static int block_till_ready(struct tty_struct *tty, struct file *filp,
+static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp,
struct moxa_port *ch)
{
DECLARE_WAITQUEUE(wait,current);
@@ -948,7 +942,7 @@ static int block_till_ready(struct tty_struct *tty, struct file *filp,
*/
if (tty_hung_up_p(filp) || (ch->asyncflags & ASYNC_CLOSING)) {
if (ch->asyncflags & ASYNC_CLOSING)
- interruptible_sleep_on(&ch->close_wait);
+ wait_for_completion_interruptible(&ch->close_wait);
#ifdef SERIAL_DO_RESTART
if (ch->asyncflags & ASYNC_HUP_NOTIFY)
return (-EAGAIN);
@@ -971,10 +965,8 @@ static int block_till_ready(struct tty_struct *tty, struct file *filp,
*/
retval = 0;
add_wait_queue(&ch->open_wait, &wait);
-#ifdef SERIAL_DEBUG_OPEN
- printk("block_til_ready before block: ttys%d, count = %d\n",
- ch->line, ch->count);
-#endif
+ pr_debug("block_til_ready before block: ttys%d, count = %d\n",
+ ch->port, ch->count);
spin_lock_irqsave(&moxa_lock, flags);
if (!tty_hung_up_p(filp))
ch->count--;
@@ -1013,10 +1005,8 @@ static int block_till_ready(struct tty_struct *tty, struct file *filp,
ch->count++;
ch->blocked_open--;
spin_unlock_irqrestore(&moxa_lock, flags);
-#ifdef SERIAL_DEBUG_OPEN
- printk("block_til_ready after blocking: ttys%d, count = %d\n",
- ch->line, ch->count);
-#endif
+ pr_debug("block_til_ready after blocking: ttys%d, count = %d\n",
+ ch->port, ch->count);
if (retval)
return (retval);
/* FIXME: review to see if we need to use set_bit on these */
@@ -1024,7 +1014,7 @@ static int block_till_ready(struct tty_struct *tty, struct file *filp,
return 0;
}
-static void setup_empty_event(struct tty_struct *tty)
+static void moxa_setup_empty_event(struct tty_struct *tty)
{
struct moxa_port *ch = tty->driver_data;
unsigned long flags;
@@ -1035,24 +1025,24 @@ static void setup_empty_event(struct tty_struct *tty)
spin_unlock_irqrestore(&moxa_lock, flags);
}
-static void check_xmit_empty(unsigned long data)
+static void moxa_check_xmit_empty(unsigned long data)
{
struct moxa_port *ch;
ch = (struct moxa_port *) data;
- del_timer_sync(&moxa_ports[ch->port].emptyTimer);
if (ch->tty && (ch->statusflags & EMPTYWAIT)) {
if (MoxaPortTxQueue(ch->port) == 0) {
ch->statusflags &= ~EMPTYWAIT;
tty_wakeup(ch->tty);
return;
}
- mod_timer(&moxa_ports[ch->port].emptyTimer, jiffies + HZ);
+ mod_timer(&moxa_ports[ch->port].emptyTimer,
+ round_jiffies(jiffies + HZ));
} else
ch->statusflags &= ~EMPTYWAIT;
}
-static void shut_down(struct moxa_port *ch)
+static void moxa_shut_down(struct moxa_port *ch)
{
struct tty_struct *tp;
@@ -1072,7 +1062,7 @@ static void shut_down(struct moxa_port *ch)
ch->asyncflags &= ~ASYNC_INITIALIZED;
}
-static void receive_data(struct moxa_port *ch)
+static void moxa_receive_data(struct moxa_port *ch)
{
struct tty_struct *tp;
struct ktermios *ts;
@@ -1406,8 +1396,8 @@ static struct mon_str moxaLog;
static int moxaFuncTout = HZ / 2;
static void moxafunc(void __iomem *, int, ushort);
-static void wait_finish(void __iomem *);
-static void low_water_check(void __iomem *);
+static void moxa_wait_finish(void __iomem *);
+static void moxa_low_water_check(void __iomem *);
static int moxaloadbios(int, unsigned char __user *, int);
static int moxafindcard(int);
static int moxaload320b(int, unsigned char __user *, int);
@@ -1473,7 +1463,7 @@ void MoxaPortFlushData(int port, int mode)
moxafunc(ofsAddr, FC_FlushQueue, mode);
if (mode != 1) {
moxa_ports[port].lowChkFlag = 0;
- low_water_check(ofsAddr);
+ moxa_low_water_check(ofsAddr);
}
}
@@ -1654,7 +1644,7 @@ int MoxaDriverPoll(void)
if (moxa_ports[p].lowChkFlag) {
moxa_ports[p].lowChkFlag = 0;
ofsAddr = moxa_ports[p].tableAddr;
- low_water_check(ofsAddr);
+ moxa_low_water_check(ofsAddr);
}
}
}
@@ -2081,7 +2071,7 @@ int MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud)
writeb(termio->c_cc[VSTART], ofsAddr + FuncArg);
writeb(termio->c_cc[VSTOP], ofsAddr + FuncArg1);
writeb(FC_SetXonXoff, ofsAddr + FuncCode);
- wait_finish(ofsAddr);
+ moxa_wait_finish(ofsAddr);
}
return (0);
@@ -2480,10 +2470,10 @@ static void moxafunc(void __iomem *ofsAddr, int cmd, ushort arg)
writew(arg, ofsAddr + FuncArg);
writew(cmd, ofsAddr + FuncCode);
- wait_finish(ofsAddr);
+ moxa_wait_finish(ofsAddr);
}
-static void wait_finish(void __iomem *ofsAddr)
+static void moxa_wait_finish(void __iomem *ofsAddr)
{
unsigned long i, j;
@@ -2496,7 +2486,7 @@ static void wait_finish(void __iomem *ofsAddr)
}
}
-static void low_water_check(void __iomem *ofsAddr)
+static void moxa_low_water_check(void __iomem *ofsAddr)
{
int len;
ushort rptr, wptr, mask;
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c
index 04ac155d3a07..82f2e27dca7d 100644
--- a/drivers/char/mspec.c
+++ b/drivers/char/mspec.c
@@ -362,7 +362,7 @@ mspec_init(void)
is_sn2 = 1;
if (is_shub2()) {
ret = -ENOMEM;
- for_each_online_node(nid) {
+ for_each_node_state(nid, N_ONLINE) {
int actual_nid;
int nasid;
unsigned long phys;
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 2aee3fef0416..fd0abef7ee08 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -56,11 +56,11 @@
#include <linux/mm.h>
#include <linux/delay.h>
#include <linux/pci.h>
+#include <linux/bitops.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/irq.h>
-#include <asm/bitops.h>
#include <asm/uaccess.h>
#include "mxser.h"
@@ -383,7 +383,6 @@ static int mxser_init(void);
/* static void mxser_poll(unsigned long); */
static int mxser_get_ISA_conf(int, struct mxser_hwconf *);
-static int mxser_get_PCI_conf(int, int, int, struct mxser_hwconf *);
static void mxser_do_softint(struct work_struct *);
static int mxser_open(struct tty_struct *, struct file *);
static void mxser_close(struct tty_struct *, struct file *);
@@ -422,7 +421,7 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout);
static void mxser_startrx(struct tty_struct *tty);
static void mxser_stoprx(struct tty_struct *tty);
-
+#ifdef CONFIG_PCI
static int CheckIsMoxaMust(int io)
{
u8 oldmcr, hwid;
@@ -445,6 +444,7 @@ static int CheckIsMoxaMust(int io)
}
return MOXA_OTHER_UART;
}
+#endif
/* above is modified by Victor Yu. 08-15-2002 */
@@ -1938,14 +1938,6 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id)
inb(info->base + UART_MSR);
continue;
}
- /* above add by Victor Yu. 09-13-2002 */
- /*
- if (info->tty->flip.count < TTY_FLIPBUF_SIZE / 4) {
- info->IER |= MOXA_MUST_RECV_ISR;
- outb(info->IER, info->base + UART_IER);
- }
- */
-
/* mask by Victor Yu. 09-13-2002
if ( !info->tty ||
@@ -2599,19 +2591,8 @@ static int mxser_change_speed(struct mxser_struct *info, struct ktermios *old_te
info->IER |= UART_IER_MSI;
if ((info->type == PORT_16550A) || (info->IsMoxaMustChipFlag)) {
info->MCR |= UART_MCR_AFE;
- /* status = mxser_get_msr(info->base, 0, info->port); */
-/*
- save_flags(flags);
- cli();
- status = inb(baseaddr + UART_MSR);
- restore_flags(flags);
-*/
- /* mxser_check_modem_status(info, status); */
} else {
- /* status = mxser_get_msr(info->base, 0, info->port); */
- /* MX_LOCK(&info->slock); */
status = inb(info->base + UART_MSR);
- /* MX_UNLOCK(&info->slock); */
if (info->tty->hw_stopped) {
if (status & UART_MSR_CTS) {
info->tty->hw_stopped = 0;
diff --git a/drivers/char/mxser.h b/drivers/char/mxser.h
index 9fe28497eae9..1f4aa45ec004 100644
--- a/drivers/char/mxser.h
+++ b/drivers/char/mxser.h
@@ -30,8 +30,7 @@
#define TTY_THRESHOLD_THROTTLE 128
-#define LO_WATER (TTY_FLIPBUF_SIZE)
-#define HI_WATER (TTY_FLIPBUF_SIZE*2*3/4)
+#define HI_WATER 768
// added by James. 03-11-2004.
#define MOXA_SDS_GETICOUNTER (MOXA + 68)
diff --git a/drivers/char/mxser_new.c b/drivers/char/mxser_new.c
index 6a563932ba19..081c84c7b548 100644
--- a/drivers/char/mxser_new.c
+++ b/drivers/char/mxser_new.c
@@ -2,7 +2,7 @@
* mxser.c -- MOXA Smartio/Industio family multiport serial driver.
*
* Copyright (C) 1999-2006 Moxa Technologies (support@moxa.com.tw).
- * Copyright (C) 2006 Jiri Slaby <jirislaby@gmail.com>
+ * Copyright (C) 2006-2007 Jiri Slaby <jirislaby@gmail.com>
*
* This code is loosely based on the 1.8 moxa driver which is based on
* Linux serial driver, written by Linus Torvalds, Theodore T'so and
@@ -39,16 +39,16 @@
#include <linux/mm.h>
#include <linux/delay.h>
#include <linux/pci.h>
+#include <linux/bitops.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/irq.h>
-#include <asm/bitops.h>
#include <asm/uaccess.h>
#include "mxser_new.h"
-#define MXSER_VERSION "2.0.1" /* 1.9.15 */
+#define MXSER_VERSION "2.0.2" /* 1.10 */
#define MXSERMAJOR 174
#define MXSERCUMAJOR 175
@@ -72,6 +72,12 @@
#define UART_MCR_AFE 0x20
#define UART_LSR_SPECIAL 0x1E
+#define PCI_DEVICE_ID_CB108 0x1080
+#define PCI_DEVICE_ID_CB114 0x1142
+#define PCI_DEVICE_ID_CB134I 0x1341
+#define PCI_DEVICE_ID_CP138U 0x1380
+#define PCI_DEVICE_ID_POS104UL 0x1044
+
#define C168_ASIC_ID 1
#define C104_ASIC_ID 2
@@ -107,71 +113,63 @@ struct mxser_cardinfo {
};
static const struct mxser_cardinfo mxser_cards[] = {
- { 8, "C168 series", }, /* C168-ISA */
- { 4, "C104 series", }, /* C104-ISA */
- { 4, "CI-104J series", }, /* CI104J */
- { 8, "C168H/PCI series", }, /* C168-PCI */
- { 4, "C104H/PCI series", }, /* C104-PCI */
- { 4, "C102 series", MXSER_HAS2 }, /* C102-ISA */
- { 4, "CI-132 series", MXSER_HAS2 }, /* CI132 */
- { 4, "CI-134 series", }, /* CI134 */
- { 2, "CP-132 series", }, /* CP132 */
- { 4, "CP-114 series", }, /* CP114 */
- { 4, "CT-114 series", }, /* CT114 */
- { 2, "CP-102 series", MXSER_HIGHBAUD }, /* CP102 */
- { 4, "CP-104U series", }, /* CP104U */
- { 8, "CP-168U series", }, /* CP168U */
- { 2, "CP-132U series", }, /* CP132U */
- { 4, "CP-134U series", }, /* CP134U */
- { 4, "CP-104JU series", }, /* CP104JU */
+/* 0*/ { 8, "C168 series", },
+ { 4, "C104 series", },
+ { 4, "CI-104J series", },
+ { 8, "C168H/PCI series", },
+ { 4, "C104H/PCI series", },
+/* 5*/ { 4, "C102 series", MXSER_HAS2 }, /* C102-ISA */
+ { 4, "CI-132 series", MXSER_HAS2 },
+ { 4, "CI-134 series", },
+ { 2, "CP-132 series", },
+ { 4, "CP-114 series", },
+/*10*/ { 4, "CT-114 series", },
+ { 2, "CP-102 series", MXSER_HIGHBAUD },
+ { 4, "CP-104U series", },
+ { 8, "CP-168U series", },
+ { 2, "CP-132U series", },
+/*15*/ { 4, "CP-134U series", },
+ { 4, "CP-104JU series", },
{ 8, "Moxa UC7000 Serial", }, /* RC7000 */
- { 8, "CP-118U series", }, /* CP118U */
- { 2, "CP-102UL series", }, /* CP102UL */
- { 2, "CP-102U series", }, /* CP102U */
- { 8, "CP-118EL series", }, /* CP118EL */
- { 8, "CP-168EL series", }, /* CP168EL */
- { 4, "CP-104EL series", } /* CP104EL */
+ { 8, "CP-118U series", },
+ { 2, "CP-102UL series", },
+/*20*/ { 2, "CP-102U series", },
+ { 8, "CP-118EL series", },
+ { 8, "CP-168EL series", },
+ { 4, "CP-104EL series", },
+ { 8, "CB-108 series", },
+/*25*/ { 4, "CB-114 series", },
+ { 4, "CB-134I series", },
+ { 8, "CP-138U series", },
+ { 4, "POS-104UL series", }
};
/* driver_data correspond to the lines in the structure above
see also ISA probe function before you change something */
static struct pci_device_id mxser_pcibrds[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C168),
- .driver_data = 3 },
- { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C104),
- .driver_data = 4 },
- { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP132),
- .driver_data = 8 },
- { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP114),
- .driver_data = 9 },
- { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CT114),
- .driver_data = 10 },
- { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102),
- .driver_data = 11 },
- { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP104U),
- .driver_data = 12 },
- { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP168U),
- .driver_data = 13 },
- { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP132U),
- .driver_data = 14 },
- { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP134U),
- .driver_data = 15 },
- { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP104JU),
- .driver_data = 16 },
- { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_RC7000),
- .driver_data = 17 },
- { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP118U),
- .driver_data = 18 },
- { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102UL),
- .driver_data = 19 },
- { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102U),
- .driver_data = 20 },
- { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP118EL),
- .driver_data = 21 },
- { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP168EL),
- .driver_data = 22 },
- { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP104EL),
- .driver_data = 23 },
+ { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_C168), .driver_data = 3 },
+ { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_C104), .driver_data = 4 },
+ { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP132), .driver_data = 8 },
+ { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP114), .driver_data = 9 },
+ { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CT114), .driver_data = 10 },
+ { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102), .driver_data = 11 },
+ { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104U), .driver_data = 12 },
+ { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP168U), .driver_data = 13 },
+ { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP132U), .driver_data = 14 },
+ { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP134U), .driver_data = 15 },
+ { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104JU),.driver_data = 16 },
+ { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_RC7000), .driver_data = 17 },
+ { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP118U), .driver_data = 18 },
+ { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102UL),.driver_data = 19 },
+ { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102U), .driver_data = 20 },
+ { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP118EL),.driver_data = 21 },
+ { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP168EL),.driver_data = 22 },
+ { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104EL),.driver_data = 23 },
+ { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB108), .driver_data = 24 },
+ { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB114), .driver_data = 25 },
+ { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB134I), .driver_data = 26 },
+ { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP138U), .driver_data = 27 },
+ { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_POS104UL), .driver_data = 28 },
{ }
};
MODULE_DEVICE_TABLE(pci, mxser_pcibrds);
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c
index e8332f305d72..82bcfb9c839a 100644
--- a/drivers/char/n_hdlc.c
+++ b/drivers/char/n_hdlc.c
@@ -229,7 +229,7 @@ static void n_hdlc_release(struct n_hdlc *n_hdlc)
wake_up_interruptible (&tty->read_wait);
wake_up_interruptible (&tty->write_wait);
- if (tty != NULL && tty->disc_data == n_hdlc)
+ if (tty->disc_data == n_hdlc)
tty->disc_data = NULL; /* Break the tty->n_hdlc link */
/* Release transmit and receive buffers */
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index 038056911934..596c7173997b 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -437,7 +437,7 @@ static inline void finish_erasing(struct tty_struct *tty)
* @c: character input
* @tty: terminal device
*
- * Perform erase and neccessary output when an erase character is
+ * Perform erase and necessary output when an erase character is
* present in the stream from the driver layer. Handles the complexities
* of UTF-8 multibyte symbols.
*/
@@ -657,7 +657,7 @@ static inline void n_tty_receive_overrun(struct tty_struct *tty)
* @c: character
*
* Process a parity error and queue the right data to indicate
- * the error case if neccessary. Locking as per n_tty_receive_buf.
+ * the error case if necessary. Locking as per n_tty_receive_buf.
*/
static inline void n_tty_receive_parity_error(struct tty_struct *tty,
unsigned char c)
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
index cc5d77797def..02518da6a386 100644
--- a/drivers/char/pcmcia/cm4000_cs.c
+++ b/drivers/char/pcmcia/cm4000_cs.c
@@ -47,7 +47,7 @@
/* #define ATR_CSUM */
#ifdef PCMCIA_DEBUG
-#define reader_to_dev(x) (&handle_to_dev(x->p_dev->handle))
+#define reader_to_dev(x) (&handle_to_dev(x->p_dev))
static int pc_debug = PCMCIA_DEBUG;
module_param(pc_debug, int, 0600);
#define DEBUGP(n, rdr, x, args...) do { \
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c
index a0b9c8728d56..5f291bf739a6 100644
--- a/drivers/char/pcmcia/cm4040_cs.c
+++ b/drivers/char/pcmcia/cm4040_cs.c
@@ -41,7 +41,7 @@
#ifdef PCMCIA_DEBUG
-#define reader_to_dev(x) (&handle_to_dev(x->p_dev->handle))
+#define reader_to_dev(x) (&handle_to_dev(x->p_dev))
static int pc_debug = PCMCIA_DEBUG;
module_param(pc_debug, int, 0600);
#define DEBUGP(n, rdr, x, args...) do { \
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 2b889317461e..8caff0ca80ff 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -123,7 +123,7 @@ typedef struct
#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
struct _input_signal_events {
- int ri_up;
+ int ri_up;
int ri_down;
int dsr_up;
int dsr_down;
@@ -137,7 +137,7 @@ struct _input_signal_events {
/*
* Device instance data structure
*/
-
+
typedef struct _mgslpc_info {
void *if_ptr; /* General purpose pointer (used by SPPP) */
int magic;
@@ -146,15 +146,15 @@ typedef struct _mgslpc_info {
int line;
unsigned short close_delay;
unsigned short closing_wait; /* time to wait before closing */
-
+
struct mgsl_icount icount;
-
+
struct tty_struct *tty;
int timeout;
int x_char; /* xon/xoff character */
int blocked_open; /* # of blocked opens */
unsigned char read_status_mask;
- unsigned char ignore_status_mask;
+ unsigned char ignore_status_mask;
unsigned char *tx_buf;
int tx_put;
@@ -170,10 +170,10 @@ typedef struct _mgslpc_info {
int rx_buf_size; /* size in bytes of single rx buffer */
int rx_buf_count; /* total number of rx buffers */
int rx_frame_count; /* number of full rx buffers */
-
+
wait_queue_head_t open_wait;
wait_queue_head_t close_wait;
-
+
wait_queue_head_t status_event_wait_q;
wait_queue_head_t event_wait_q;
struct timer_list tx_timer; /* HDLC transmit timeout timer */
@@ -192,7 +192,7 @@ typedef struct _mgslpc_info {
int bh_running;
int bh_requested;
-
+
int dcd_chkcount; /* check counts to prevent */
int cts_chkcount; /* too many IRQs if a signal */
int dsr_chkcount; /* is floating */
@@ -212,7 +212,7 @@ typedef struct _mgslpc_info {
unsigned int io_base; /* base I/O address of adapter */
unsigned int irq_level;
-
+
MGSL_PARAMS params; /* communications parameters */
unsigned char serial_signals; /* current serial signal states */
@@ -249,7 +249,7 @@ typedef struct _mgslpc_info {
*/
#define TXBUFSIZE 4096
-
+
#define CHA 0x00 /* channel A offset */
#define CHB 0x40 /* channel B offset */
@@ -298,9 +298,9 @@ typedef struct _mgslpc_info {
#define PIM 0x3d
#define PCR 0x3e
#define CCR4 0x3f
-
+
// IMR/ISR
-
+
#define IRQ_BREAK_ON BIT15 // rx break detected
#define IRQ_DATAOVERRUN BIT14 // receive data overflow
#define IRQ_ALLSENT BIT13 // all sent
@@ -315,13 +315,13 @@ typedef struct _mgslpc_info {
#define IRQ_DCD BIT2 // carrier detect status change
#define IRQ_OVERRUN BIT1 // receive frame overflow
#define IRQ_RXFIFO BIT0 // receive pool full
-
+
// STAR
-
+
#define XFW BIT6 // transmit FIFO write enable
#define CEC BIT2 // command executing
#define CTS BIT1 // CTS state
-
+
#define PVR_DTR BIT0
#define PVR_DSR BIT1
#define PVR_RI BIT2
@@ -329,25 +329,25 @@ typedef struct _mgslpc_info {
#define PVR_RS232 0x20 /* 0010b */
#define PVR_V35 0xe0 /* 1110b */
#define PVR_RS422 0x40 /* 0100b */
-
-/* Register access functions */
-
+
+/* Register access functions */
+
#define write_reg(info, reg, val) outb((val),(info)->io_base + (reg))
#define read_reg(info, reg) inb((info)->io_base + (reg))
-#define read_reg16(info, reg) inw((info)->io_base + (reg))
+#define read_reg16(info, reg) inw((info)->io_base + (reg))
#define write_reg16(info, reg, val) outw((val), (info)->io_base + (reg))
-
+
#define set_reg_bits(info, reg, mask) \
write_reg(info, (reg), \
- (unsigned char) (read_reg(info, (reg)) | (mask)))
+ (unsigned char) (read_reg(info, (reg)) | (mask)))
#define clear_reg_bits(info, reg, mask) \
write_reg(info, (reg), \
- (unsigned char) (read_reg(info, (reg)) & ~(mask)))
+ (unsigned char) (read_reg(info, (reg)) & ~(mask)))
/*
* interrupt enable/disable routines
- */
-static void irq_disable(MGSLPC_INFO *info, unsigned char channel, unsigned short mask)
+ */
+static void irq_disable(MGSLPC_INFO *info, unsigned char channel, unsigned short mask)
{
if (channel == CHA) {
info->imra_value |= mask;
@@ -357,7 +357,7 @@ static void irq_disable(MGSLPC_INFO *info, unsigned char channel, unsigned short
write_reg16(info, CHB + IMR, info->imrb_value);
}
}
-static void irq_enable(MGSLPC_INFO *info, unsigned char channel, unsigned short mask)
+static void irq_enable(MGSLPC_INFO *info, unsigned char channel, unsigned short mask)
{
if (channel == CHA) {
info->imra_value &= ~mask;
@@ -558,7 +558,7 @@ static int mgslpc_probe(struct pcmcia_device *link)
spin_lock_init(&info->lock);
spin_lock_init(&info->netlock);
memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS));
- info->idle_mode = HDLC_TXIDLE_FLAGS;
+ info->idle_mode = HDLC_TXIDLE_FLAGS;
info->imra_value = 0xffff;
info->imrb_value = 0xffff;
info->pim_value = 0xff;
@@ -600,7 +600,7 @@ static int mgslpc_config(struct pcmcia_device *link)
u_char buf[64];
cistpl_cftable_entry_t dflt = { 0 };
cistpl_cftable_entry_t *cfg;
-
+
if (debug_level >= DEBUG_LEVEL_INFO)
printk("mgslpc_config(0x%p)\n", link);
@@ -624,7 +624,7 @@ static int mgslpc_config(struct pcmcia_device *link)
link->conf.ConfigIndex = cfg->index;
link->conf.Attributes |= CONF_ENABLE_IRQ;
-
+
/* IO window settings */
link->io.NumPorts1 = 0;
if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
@@ -644,7 +644,7 @@ static int mgslpc_config(struct pcmcia_device *link)
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.ConfigIndex = 8;
link->conf.Present = PRESENT_OPTION;
-
+
link->irq.Attributes |= IRQ_HANDLE_PRESENT;
link->irq.Handler = mgslpc_isr;
link->irq.Instance = info;
@@ -753,10 +753,10 @@ static inline int mgslpc_paranoia_check(MGSLPC_INFO *info,
#define CMD_TXEOM BIT1 // transmit end message
#define CMD_TXRESET BIT0 // transmit reset
-static BOOLEAN wait_command_complete(MGSLPC_INFO *info, unsigned char channel)
+static BOOLEAN wait_command_complete(MGSLPC_INFO *info, unsigned char channel)
{
int i = 0;
- /* wait for command completion */
+ /* wait for command completion */
while (read_reg(info, (unsigned char)(channel+STAR)) & BIT2) {
udelay(1);
if (i++ == 1000)
@@ -765,7 +765,7 @@ static BOOLEAN wait_command_complete(MGSLPC_INFO *info, unsigned char channel)
return TRUE;
}
-static void issue_command(MGSLPC_INFO *info, unsigned char channel, unsigned char cmd)
+static void issue_command(MGSLPC_INFO *info, unsigned char channel, unsigned char cmd)
{
wait_command_complete(info, channel);
write_reg(info, (unsigned char) (channel + CMDR), cmd);
@@ -775,12 +775,12 @@ static void tx_pause(struct tty_struct *tty)
{
MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;
unsigned long flags;
-
+
if (mgslpc_paranoia_check(info, tty->name, "tx_pause"))
return;
if (debug_level >= DEBUG_LEVEL_INFO)
- printk("tx_pause(%s)\n",info->device_name);
-
+ printk("tx_pause(%s)\n",info->device_name);
+
spin_lock_irqsave(&info->lock,flags);
if (info->tx_enabled)
tx_stop(info);
@@ -791,12 +791,12 @@ static void tx_release(struct tty_struct *tty)
{
MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;
unsigned long flags;
-
+
if (mgslpc_paranoia_check(info, tty->name, "tx_release"))
return;
if (debug_level >= DEBUG_LEVEL_INFO)
- printk("tx_release(%s)\n",info->device_name);
-
+ printk("tx_release(%s)\n",info->device_name);
+
spin_lock_irqsave(&info->lock,flags);
if (!info->tx_enabled)
tx_start(info);
@@ -810,7 +810,7 @@ static int bh_action(MGSLPC_INFO *info)
{
unsigned long flags;
int rc = 0;
-
+
spin_lock_irqsave(&info->lock,flags);
if (info->pending_bh & BH_RECEIVE) {
@@ -829,9 +829,9 @@ static int bh_action(MGSLPC_INFO *info)
info->bh_running = 0;
info->bh_requested = 0;
}
-
+
spin_unlock_irqrestore(&info->lock,flags);
-
+
return rc;
}
@@ -842,22 +842,22 @@ static void bh_handler(struct work_struct *work)
if (!info)
return;
-
+
if (debug_level >= DEBUG_LEVEL_BH)
printk( "%s(%d):bh_handler(%s) entry\n",
__FILE__,__LINE__,info->device_name);
-
+
info->bh_running = 1;
while((action = bh_action(info)) != 0) {
-
+
/* Process work item */
if ( debug_level >= DEBUG_LEVEL_BH )
printk( "%s(%d):bh_handler() work item action=%d\n",
__FILE__,__LINE__,action);
switch (action) {
-
+
case BH_RECEIVE:
while(rx_get_frame(info));
break;
@@ -897,7 +897,7 @@ static void bh_status(MGSLPC_INFO *info)
info->cts_chkcount = 0;
}
-/* eom: non-zero = end of frame */
+/* eom: non-zero = end of frame */
static void rx_ready_hdlc(MGSLPC_INFO *info, int eom)
{
unsigned char data[2];
@@ -906,7 +906,7 @@ static void rx_ready_hdlc(MGSLPC_INFO *info, int eom)
if (debug_level >= DEBUG_LEVEL_ISR)
printk("%s(%d):rx_ready_hdlc(eom=%d)\n",__FILE__,__LINE__,eom);
-
+
if (!info->rx_enabled)
return;
@@ -920,12 +920,12 @@ static void rx_ready_hdlc(MGSLPC_INFO *info, int eom)
}
if (eom) {
- /* end of frame, get FIFO count from RBCL register */
+ /* end of frame, get FIFO count from RBCL register */
if (!(fifo_count = (unsigned char)(read_reg(info, CHA+RBCL) & 0x1f)))
fifo_count = 32;
} else
fifo_count = 32;
-
+
do {
if (fifo_count == 1) {
read_count = 1;
@@ -969,7 +969,7 @@ static void rx_ready_async(MGSLPC_INFO *info, int tcd)
struct mgsl_icount *icount = &info->icount;
if (tcd) {
- /* early termination, get FIFO count from RBCL register */
+ /* early termination, get FIFO count from RBCL register */
fifo_count = (unsigned char)(read_reg(info, CHA+RBCL) & 0x1f);
/* Zero fifo count could mean 0 or 32 bytes available.
@@ -981,7 +981,7 @@ static void rx_ready_async(MGSLPC_INFO *info, int tcd)
fifo_count = 32;
tty_buffer_request_room(tty, fifo_count);
- /* Flush received async data to receive data buffer. */
+ /* Flush received async data to receive data buffer. */
while (fifo_count) {
data = read_reg(info, CHA + RXFIFO);
status = read_reg(info, CHA + RXFIFO);
@@ -995,7 +995,7 @@ static void rx_ready_async(MGSLPC_INFO *info, int tcd)
// BIT6:framing error
if (status & (BIT7 + BIT6)) {
- if (status & BIT7)
+ if (status & BIT7)
icount->parity++;
else
icount->frame++;
@@ -1003,7 +1003,7 @@ static void rx_ready_async(MGSLPC_INFO *info, int tcd)
/* discard char if tty control flags say so */
if (status & info->ignore_status_mask)
continue;
-
+
status &= info->read_status_mask;
if (status & BIT7)
@@ -1022,7 +1022,7 @@ static void rx_ready_async(MGSLPC_INFO *info, int tcd)
__FILE__,__LINE__,icount->rx,icount->brk,
icount->parity,icount->frame,icount->overrun);
}
-
+
if (work)
tty_flip_buffer_push(tty);
}
@@ -1032,7 +1032,7 @@ static void tx_done(MGSLPC_INFO *info)
{
if (!info->tx_active)
return;
-
+
info->tx_active = 0;
info->tx_aborting = 0;
@@ -1040,8 +1040,8 @@ static void tx_done(MGSLPC_INFO *info)
return;
info->tx_count = info->tx_put = info->tx_get = 0;
- del_timer(&info->tx_timer);
-
+ del_timer(&info->tx_timer);
+
if (info->drop_rts_on_tx_done) {
get_signals(info);
if (info->serial_signals & SerialSignal_RTS) {
@@ -1054,7 +1054,7 @@ static void tx_done(MGSLPC_INFO *info)
#if SYNCLINK_GENERIC_HDLC
if (info->netcount)
hdlcdev_tx_done(info);
- else
+ else
#endif
{
if (info->tty->stopped || info->tty->hw_stopped) {
@@ -1090,7 +1090,7 @@ static void tx_ready(MGSLPC_INFO *info)
while (info->tx_count && fifo_count) {
c = min(2, min_t(int, fifo_count, min(info->tx_count, TXBUFSIZE - info->tx_get)));
-
+
if (c == 1) {
write_reg(info, CHA + TXFIFO, *(info->tx_buf + info->tx_get));
} else {
@@ -1220,9 +1220,9 @@ static void ri_change(MGSLPC_INFO *info)
}
/* Interrupt service routine entry point.
- *
+ *
* Arguments:
- *
+ *
* irq interrupt number that caused interrupt
* dev_id device ID supplied during interrupt registration
*/
@@ -1233,18 +1233,18 @@ static irqreturn_t mgslpc_isr(int irq, void *dev_id)
unsigned char gis, pis;
int count=0;
- if (debug_level >= DEBUG_LEVEL_ISR)
+ if (debug_level >= DEBUG_LEVEL_ISR)
printk("mgslpc_isr(%d) entry.\n", irq);
if (!info)
return IRQ_NONE;
-
+
if (!(info->p_dev->_locked))
return IRQ_HANDLED;
spin_lock(&info->lock);
while ((gis = read_reg(info, CHA + GIS))) {
- if (debug_level >= DEBUG_LEVEL_ISR)
+ if (debug_level >= DEBUG_LEVEL_ISR)
printk("mgslpc_isr %s gis=%04X\n", info->device_name,gis);
if ((gis & 0x70) || count > 1000) {
@@ -1268,7 +1268,7 @@ static irqreturn_t mgslpc_isr(int irq, void *dev_id)
irq_disable(info, CHA, IRQ_TIMER);
}
- /* receive IRQs */
+ /* receive IRQs */
if (isr & IRQ_EXITHUNT) {
info->icount.exithunt++;
wake_up_interruptible(&info->event_wait_q);
@@ -1283,12 +1283,12 @@ static irqreturn_t mgslpc_isr(int irq, void *dev_id)
}
if (isr & (IRQ_RXEOM + IRQ_RXFIFO)) {
if (info->params.mode == MGSL_MODE_HDLC)
- rx_ready_hdlc(info, isr & IRQ_RXEOM);
+ rx_ready_hdlc(info, isr & IRQ_RXEOM);
else
rx_ready_async(info, isr & IRQ_RXEOM);
}
- /* transmit IRQs */
+ /* transmit IRQs */
if (isr & IRQ_UNDERRUN) {
if (info->tx_aborting)
info->icount.txabort++;
@@ -1311,13 +1311,13 @@ static irqreturn_t mgslpc_isr(int irq, void *dev_id)
ri_change(info);
}
}
-
- /* Request bottom half processing if there's something
+
+ /* Request bottom half processing if there's something
* for it to do and the bh is not already running
*/
if (info->pending_bh && !info->bh_running && !info->bh_requested) {
- if ( debug_level >= DEBUG_LEVEL_ISR )
+ if ( debug_level >= DEBUG_LEVEL_ISR )
printk("%s(%d):%s queueing bh task.\n",
__FILE__,__LINE__,info->device_name);
schedule_work(&info->task);
@@ -1325,8 +1325,8 @@ static irqreturn_t mgslpc_isr(int irq, void *dev_id)
}
spin_unlock(&info->lock);
-
- if (debug_level >= DEBUG_LEVEL_ISR)
+
+ if (debug_level >= DEBUG_LEVEL_ISR)
printk("%s(%d):mgslpc_isr(%d)exit.\n",
__FILE__,__LINE__,irq);
@@ -1338,13 +1338,13 @@ static irqreturn_t mgslpc_isr(int irq, void *dev_id)
static int startup(MGSLPC_INFO * info)
{
int retval = 0;
-
+
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):startup(%s)\n",__FILE__,__LINE__,info->device_name);
-
+
if (info->flags & ASYNC_INITIALIZED)
return 0;
-
+
if (!info->tx_buf) {
/* allocate a page of memory for a transmit buffer */
info->tx_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);
@@ -1356,18 +1356,18 @@ static int startup(MGSLPC_INFO * info)
}
info->pending_bh = 0;
-
+
memset(&info->icount, 0, sizeof(info->icount));
setup_timer(&info->tx_timer, tx_timeout, (unsigned long)info);
/* Allocate and claim adapter resources */
retval = claim_resources(info);
-
+
/* perform existance check and diagnostics */
if ( !retval )
retval = adapter_test(info);
-
+
if ( retval ) {
if (capable(CAP_SYS_ADMIN) && info->tty)
set_bit(TTY_IO_ERROR, &info->tty->flags);
@@ -1377,12 +1377,12 @@ static int startup(MGSLPC_INFO * info)
/* program hardware for current parameters */
mgslpc_change_params(info);
-
+
if (info->tty)
clear_bit(TTY_IO_ERROR, &info->tty->flags);
info->flags |= ASYNC_INITIALIZED;
-
+
return 0;
}
@@ -1391,7 +1391,7 @@ static int startup(MGSLPC_INFO * info)
static void shutdown(MGSLPC_INFO * info)
{
unsigned long flags;
-
+
if (!(info->flags & ASYNC_INITIALIZED))
return;
@@ -1418,16 +1418,16 @@ static void shutdown(MGSLPC_INFO * info)
/* TODO:disable interrupts instead of reset to preserve signal states */
reset_device(info);
-
+
if (!info->tty || info->tty->termios->c_cflag & HUPCL) {
info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS);
set_signals(info);
}
-
+
spin_unlock_irqrestore(&info->lock,flags);
- release_resources(info);
-
+ release_resources(info);
+
if (info->tty)
set_bit(TTY_IO_ERROR, &info->tty->flags);
@@ -1439,18 +1439,18 @@ static void mgslpc_program_hw(MGSLPC_INFO *info)
unsigned long flags;
spin_lock_irqsave(&info->lock,flags);
-
+
rx_stop(info);
tx_stop(info);
info->tx_count = info->tx_put = info->tx_get = 0;
-
+
if (info->params.mode == MGSL_MODE_HDLC || info->netcount)
hdlc_mode(info);
else
async_mode(info);
-
+
set_signals(info);
-
+
info->dcd_chkcount = 0;
info->cts_chkcount = 0;
info->ri_chkcount = 0;
@@ -1459,10 +1459,10 @@ static void mgslpc_program_hw(MGSLPC_INFO *info)
irq_enable(info, CHB, IRQ_DCD | IRQ_CTS);
port_irq_enable(info, (unsigned char) PVR_DSR | PVR_RI);
get_signals(info);
-
+
if (info->netcount || info->tty->termios->c_cflag & CREAD)
rx_start(info);
-
+
spin_unlock_irqrestore(&info->lock,flags);
}
@@ -1475,11 +1475,11 @@ static void mgslpc_change_params(MGSLPC_INFO *info)
if (!info->tty || !info->tty->termios)
return;
-
+
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgslpc_change_params(%s)\n",
__FILE__,__LINE__, info->device_name );
-
+
cflag = info->tty->termios->c_cflag;
/* if B0 rate (hangup) specified then negate DTR and RTS */
@@ -1488,9 +1488,9 @@ static void mgslpc_change_params(MGSLPC_INFO *info)
info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
else
info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
-
+
/* byte size and parity */
-
+
switch (cflag & CSIZE) {
case CS5: info->params.data_bits = 5; break;
case CS6: info->params.data_bits = 6; break;
@@ -1498,7 +1498,7 @@ static void mgslpc_change_params(MGSLPC_INFO *info)
case CS8: info->params.data_bits = 8; break;
default: info->params.data_bits = 7; break;
}
-
+
if (cflag & CSTOPB)
info->params.stop_bits = 2;
else
@@ -1519,7 +1519,7 @@ static void mgslpc_change_params(MGSLPC_INFO *info)
/* calculate number of jiffies to transmit a full
* FIFO (32 bytes) at specified data rate
*/
- bits_per_char = info->params.data_bits +
+ bits_per_char = info->params.data_bits +
info->params.stop_bits + 1;
/* if port data rate is set to 460800 or less then
@@ -1529,9 +1529,9 @@ static void mgslpc_change_params(MGSLPC_INFO *info)
if (info->params.data_rate <= 460800) {
info->params.data_rate = tty_get_baud_rate(info->tty);
}
-
+
if ( info->params.data_rate ) {
- info->timeout = (32*HZ*bits_per_char) /
+ info->timeout = (32*HZ*bits_per_char) /
info->params.data_rate;
}
info->timeout += HZ/50; /* Add .02 seconds of slop */
@@ -1540,14 +1540,14 @@ static void mgslpc_change_params(MGSLPC_INFO *info)
info->flags |= ASYNC_CTS_FLOW;
else
info->flags &= ~ASYNC_CTS_FLOW;
-
+
if (cflag & CLOCAL)
info->flags &= ~ASYNC_CHECK_CD;
else
info->flags |= ASYNC_CHECK_CD;
/* process tty input control flags */
-
+
info->read_status_mask = 0;
if (I_INPCK(info->tty))
info->read_status_mask |= BIT7 | BIT6;
@@ -1576,7 +1576,7 @@ static void mgslpc_put_char(struct tty_struct *tty, unsigned char ch)
return;
spin_lock_irqsave(&info->lock,flags);
-
+
if (info->params.mode == MGSL_MODE_ASYNC || !info->tx_active) {
if (info->tx_count < TXBUFSIZE - 1) {
info->tx_buf[info->tx_put++] = ch;
@@ -1584,7 +1584,7 @@ static void mgslpc_put_char(struct tty_struct *tty, unsigned char ch)
info->tx_count++;
}
}
-
+
spin_unlock_irqrestore(&info->lock,flags);
}
@@ -1595,11 +1595,11 @@ static void mgslpc_flush_chars(struct tty_struct *tty)
{
MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;
unsigned long flags;
-
+
if (debug_level >= DEBUG_LEVEL_INFO)
printk( "%s(%d):mgslpc_flush_chars() entry on %s tx_count=%d\n",
__FILE__,__LINE__,info->device_name,info->tx_count);
-
+
if (mgslpc_paranoia_check(info, tty->name, "mgslpc_flush_chars"))
return;
@@ -1618,13 +1618,13 @@ static void mgslpc_flush_chars(struct tty_struct *tty)
}
/* Send a block of data
- *
+ *
* Arguments:
- *
+ *
* tty pointer to tty information structure
* buf pointer to buffer containing send data
* count size of send data in bytes
- *
+ *
* Returns: number of characters written
*/
static int mgslpc_write(struct tty_struct * tty,
@@ -1633,11 +1633,11 @@ static int mgslpc_write(struct tty_struct * tty,
int c, ret = 0;
MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;
unsigned long flags;
-
+
if (debug_level >= DEBUG_LEVEL_INFO)
printk( "%s(%d):mgslpc_write(%s) count=%d\n",
__FILE__,__LINE__,info->device_name,count);
-
+
if (mgslpc_paranoia_check(info, tty->name, "mgslpc_write") ||
!info->tx_buf)
goto cleanup;
@@ -1659,7 +1659,7 @@ static int mgslpc_write(struct tty_struct * tty,
TXBUFSIZE - info->tx_put));
if (c <= 0)
break;
-
+
memcpy(info->tx_buf + info->tx_put, buf, c);
spin_lock_irqsave(&info->lock,flags);
@@ -1678,7 +1678,7 @@ start:
tx_start(info);
spin_unlock_irqrestore(&info->lock,flags);
}
-cleanup:
+cleanup:
if (debug_level >= DEBUG_LEVEL_INFO)
printk( "%s(%d):mgslpc_write(%s) returning=%d\n",
__FILE__,__LINE__,info->device_name,ret);
@@ -1691,7 +1691,7 @@ static int mgslpc_write_room(struct tty_struct *tty)
{
MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;
int ret;
-
+
if (mgslpc_paranoia_check(info, tty->name, "mgslpc_write_room"))
return 0;
@@ -1706,7 +1706,7 @@ static int mgslpc_write_room(struct tty_struct *tty)
if (ret < 0)
ret = 0;
}
-
+
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgslpc_write_room(%s)=%d\n",
__FILE__,__LINE__, info->device_name, ret);
@@ -1719,14 +1719,14 @@ static int mgslpc_chars_in_buffer(struct tty_struct *tty)
{
MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;
int rc;
-
+
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgslpc_chars_in_buffer(%s)\n",
__FILE__,__LINE__, info->device_name );
-
+
if (mgslpc_paranoia_check(info, tty->name, "mgslpc_chars_in_buffer"))
return 0;
-
+
if (info->params.mode == MGSL_MODE_HDLC)
rc = info->tx_active ? info->max_frame_size : 0;
else
@@ -1735,7 +1735,7 @@ static int mgslpc_chars_in_buffer(struct tty_struct *tty)
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgslpc_chars_in_buffer(%s)=%d\n",
__FILE__,__LINE__, info->device_name, rc);
-
+
return rc;
}
@@ -1745,17 +1745,17 @@ static void mgslpc_flush_buffer(struct tty_struct *tty)
{
MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;
unsigned long flags;
-
+
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgslpc_flush_buffer(%s) entry\n",
__FILE__,__LINE__, info->device_name );
-
+
if (mgslpc_paranoia_check(info, tty->name, "mgslpc_flush_buffer"))
return;
-
- spin_lock_irqsave(&info->lock,flags);
+
+ spin_lock_irqsave(&info->lock,flags);
info->tx_count = info->tx_put = info->tx_get = 0;
- del_timer(&info->tx_timer);
+ del_timer(&info->tx_timer);
spin_unlock_irqrestore(&info->lock,flags);
wake_up_interruptible(&tty->write_wait);
@@ -1772,7 +1772,7 @@ static void mgslpc_send_xchar(struct tty_struct *tty, char ch)
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgslpc_send_xchar(%s,%d)\n",
__FILE__,__LINE__, info->device_name, ch );
-
+
if (mgslpc_paranoia_check(info, tty->name, "mgslpc_send_xchar"))
return;
@@ -1791,17 +1791,17 @@ static void mgslpc_throttle(struct tty_struct * tty)
{
MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;
unsigned long flags;
-
+
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgslpc_throttle(%s) entry\n",
__FILE__,__LINE__, info->device_name );
if (mgslpc_paranoia_check(info, tty->name, "mgslpc_throttle"))
return;
-
+
if (I_IXOFF(tty))
mgslpc_send_xchar(tty, STOP_CHAR(tty));
-
+
if (tty->termios->c_cflag & CRTSCTS) {
spin_lock_irqsave(&info->lock,flags);
info->serial_signals &= ~SerialSignal_RTS;
@@ -1816,21 +1816,21 @@ static void mgslpc_unthrottle(struct tty_struct * tty)
{
MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;
unsigned long flags;
-
+
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgslpc_unthrottle(%s) entry\n",
__FILE__,__LINE__, info->device_name );
if (mgslpc_paranoia_check(info, tty->name, "mgslpc_unthrottle"))
return;
-
+
if (I_IXOFF(tty)) {
if (info->x_char)
info->x_char = 0;
else
mgslpc_send_xchar(tty, START_CHAR(tty));
}
-
+
if (tty->termios->c_cflag & CRTSCTS) {
spin_lock_irqsave(&info->lock,flags);
info->serial_signals |= SerialSignal_RTS;
@@ -1870,9 +1870,9 @@ static int get_params(MGSLPC_INFO * info, MGSL_PARAMS __user *user_params)
}
/* set the serial parameters
- *
+ *
* Arguments:
- *
+ *
* info pointer to device instance data
* new_params user buffer containing new serial params
*
@@ -1883,7 +1883,7 @@ static int set_params(MGSLPC_INFO * info, MGSL_PARAMS __user *new_params)
unsigned long flags;
MGSL_PARAMS tmp_params;
int err;
-
+
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):set_params %s\n", __FILE__,__LINE__,
info->device_name );
@@ -1894,13 +1894,13 @@ static int set_params(MGSLPC_INFO * info, MGSL_PARAMS __user *new_params)
__FILE__,__LINE__,info->device_name);
return -EFAULT;
}
-
+
spin_lock_irqsave(&info->lock,flags);
memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS));
spin_unlock_irqrestore(&info->lock,flags);
-
+
mgslpc_change_params(info);
-
+
return 0;
}
@@ -1963,10 +1963,10 @@ static int set_interface(MGSLPC_INFO * info, int if_mode)
static int set_txenable(MGSLPC_INFO * info, int enable)
{
unsigned long flags;
-
+
if (debug_level >= DEBUG_LEVEL_INFO)
printk("set_txenable(%s,%d)\n", info->device_name, enable);
-
+
spin_lock_irqsave(&info->lock,flags);
if (enable) {
if (!info->tx_enabled)
@@ -1982,10 +1982,10 @@ static int set_txenable(MGSLPC_INFO * info, int enable)
static int tx_abort(MGSLPC_INFO * info)
{
unsigned long flags;
-
+
if (debug_level >= DEBUG_LEVEL_INFO)
printk("tx_abort(%s)\n", info->device_name);
-
+
spin_lock_irqsave(&info->lock,flags);
if (info->tx_active && info->tx_count &&
info->params.mode == MGSL_MODE_HDLC) {
@@ -2002,10 +2002,10 @@ static int tx_abort(MGSLPC_INFO * info)
static int set_rxenable(MGSLPC_INFO * info, int enable)
{
unsigned long flags;
-
+
if (debug_level >= DEBUG_LEVEL_INFO)
printk("set_rxenable(%s,%d)\n", info->device_name, enable);
-
+
spin_lock_irqsave(&info->lock,flags);
if (enable) {
if (!info->rx_enabled)
@@ -2019,7 +2019,7 @@ static int set_rxenable(MGSLPC_INFO * info, int enable)
}
/* wait for specified event to occur
- *
+ *
* Arguments: info pointer to device instance data
* mask pointer to bitmask of events to wait for
* Return Value: 0 if successful and bit mask updated with
@@ -2040,7 +2040,7 @@ static int wait_events(MGSLPC_INFO * info, int __user *mask_ptr)
COPY_FROM_USER(rc,&mask, mask_ptr, sizeof(int));
if (rc)
return -EFAULT;
-
+
if (debug_level >= DEBUG_LEVEL_INFO)
printk("wait_events(%s,%d)\n", info->device_name, mask);
@@ -2062,24 +2062,24 @@ static int wait_events(MGSLPC_INFO * info, int __user *mask_ptr)
/* save current irq counts */
cprev = info->icount;
oldsigs = info->input_signal_events;
-
+
if ((info->params.mode == MGSL_MODE_HDLC) &&
(mask & MgslEvent_ExitHuntMode))
irq_enable(info, CHA, IRQ_EXITHUNT);
-
+
set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&info->event_wait_q, &wait);
-
+
spin_unlock_irqrestore(&info->lock,flags);
-
-
+
+
for(;;) {
schedule();
if (signal_pending(current)) {
rc = -ERESTARTSYS;
break;
}
-
+
/* get current irq counts */
spin_lock_irqsave(&info->lock,flags);
cnow = info->icount;
@@ -2115,11 +2115,11 @@ static int wait_events(MGSLPC_INFO * info, int __user *mask_ptr)
(cnow.rxidle != cprev.rxidle ? MgslEvent_IdleReceived:0) );
if (events)
break;
-
+
cprev = cnow;
oldsigs = newsigs;
}
-
+
remove_wait_queue(&info->event_wait_q, &wait);
set_current_state(TASK_RUNNING);
@@ -2247,42 +2247,42 @@ static void mgslpc_break(struct tty_struct *tty, int break_state)
{
MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
unsigned long flags;
-
+
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgslpc_break(%s,%d)\n",
__FILE__,__LINE__, info->device_name, break_state);
-
+
if (mgslpc_paranoia_check(info, tty->name, "mgslpc_break"))
return;
spin_lock_irqsave(&info->lock,flags);
if (break_state == -1)
set_reg_bits(info, CHA+DAFO, BIT6);
- else
+ else
clear_reg_bits(info, CHA+DAFO, BIT6);
spin_unlock_irqrestore(&info->lock,flags);
}
/* Service an IOCTL request
- *
+ *
* Arguments:
- *
+ *
* tty pointer to tty instance data
* file pointer to associated file object for device
* cmd IOCTL command code
* arg command argument/context
- *
+ *
* Return Value: 0 if success, otherwise error code
*/
static int mgslpc_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
{
MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
-
+
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgslpc_ioctl %s cmd=%08X\n", __FILE__,__LINE__,
info->device_name, cmd );
-
+
if (mgslpc_paranoia_check(info, tty->name, "mgslpc_ioctl"))
return -ENODEV;
@@ -2302,7 +2302,7 @@ static int ioctl_common(MGSLPC_INFO *info, unsigned int cmd, unsigned long arg)
struct serial_icounter_struct __user *p_cuser; /* user space */
void __user *argp = (void __user *)arg;
unsigned long flags;
-
+
switch (cmd) {
case MGSL_IOCGPARAMS:
return get_params(info, argp);
@@ -2363,9 +2363,9 @@ static int ioctl_common(MGSLPC_INFO *info, unsigned int cmd, unsigned long arg)
}
/* Set new termios settings
- *
+ *
* Arguments:
- *
+ *
* tty pointer to tty structure
* termios pointer to buffer to hold returned old termios
*/
@@ -2373,14 +2373,14 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term
{
MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;
unsigned long flags;
-
+
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgslpc_set_termios %s\n", __FILE__,__LINE__,
tty->driver->name );
-
+
/* just return if nothing has changed */
if ((tty->termios->c_cflag == old_termios->c_cflag)
- && (RELEVANT_IFLAG(tty->termios->c_iflag)
+ && (RELEVANT_IFLAG(tty->termios->c_iflag)
== RELEVANT_IFLAG(old_termios->c_iflag)))
return;
@@ -2394,12 +2394,12 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term
set_signals(info);
spin_unlock_irqrestore(&info->lock,flags);
}
-
+
/* Handle transition away from B0 status */
if (!(old_termios->c_cflag & CBAUD) &&
tty->termios->c_cflag & CBAUD) {
info->serial_signals |= SerialSignal_DTR;
- if (!(tty->termios->c_cflag & CRTSCTS) ||
+ if (!(tty->termios->c_cflag & CRTSCTS) ||
!test_bit(TTY_THROTTLED, &tty->flags)) {
info->serial_signals |= SerialSignal_RTS;
}
@@ -2407,7 +2407,7 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term
set_signals(info);
spin_unlock_irqrestore(&info->lock,flags);
}
-
+
/* Handle turning off CRTSCTS */
if (old_termios->c_cflag & CRTSCTS &&
!(tty->termios->c_cflag & CRTSCTS)) {
@@ -2422,17 +2422,17 @@ static void mgslpc_close(struct tty_struct *tty, struct file * filp)
if (mgslpc_paranoia_check(info, tty->name, "mgslpc_close"))
return;
-
+
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgslpc_close(%s) entry, count=%d\n",
__FILE__,__LINE__, info->device_name, info->count);
-
+
if (!info->count)
return;
if (tty_hung_up_p(filp))
goto cleanup;
-
+
if ((tty->count == 1) && (info->count != 1)) {
/*
* tty->count is 1 and the tty structure will be freed.
@@ -2443,30 +2443,30 @@ static void mgslpc_close(struct tty_struct *tty, struct file * filp)
"info->count is %d\n", info->count);
info->count = 1;
}
-
+
info->count--;
-
+
/* if at least one open remaining, leave hardware active */
if (info->count)
goto cleanup;
-
+
info->flags |= ASYNC_CLOSING;
-
- /* set tty->closing to notify line discipline to
+
+ /* set tty->closing to notify line discipline to
* only process XON/XOFF characters. Only the N_TTY
* discipline appears to use this (ppp does not).
*/
tty->closing = 1;
-
+
/* wait for transmit data to clear all layers */
-
+
if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) {
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgslpc_close(%s) calling tty_wait_until_sent\n",
__FILE__,__LINE__, info->device_name );
tty_wait_until_sent(tty, info->closing_wait);
}
-
+
if (info->flags & ASYNC_INITIALIZED)
mgslpc_wait_until_sent(tty, info->timeout);
@@ -2474,24 +2474,24 @@ static void mgslpc_close(struct tty_struct *tty, struct file * filp)
tty->driver->flush_buffer(tty);
ldisc_flush_buffer(tty);
-
+
shutdown(info);
-
+
tty->closing = 0;
info->tty = NULL;
-
+
if (info->blocked_open) {
if (info->close_delay) {
msleep_interruptible(jiffies_to_msecs(info->close_delay));
}
wake_up_interruptible(&info->open_wait);
}
-
+
info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
-
+
wake_up_interruptible(&info->close_wait);
-
-cleanup:
+
+cleanup:
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgslpc_close(%s) exit, count=%d\n", __FILE__,__LINE__,
tty->driver->name, info->count);
@@ -2510,31 +2510,31 @@ static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout)
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgslpc_wait_until_sent(%s) entry\n",
__FILE__,__LINE__, info->device_name );
-
+
if (mgslpc_paranoia_check(info, tty->name, "mgslpc_wait_until_sent"))
return;
if (!(info->flags & ASYNC_INITIALIZED))
goto exit;
-
+
orig_jiffies = jiffies;
-
+
/* Set check interval to 1/5 of estimated time to
* send a character, and make it at least 1. The check
* interval should also be less than the timeout.
* Note: use tight timings here to satisfy the NIST-PCTS.
- */
-
+ */
+
if ( info->params.data_rate ) {
char_time = info->timeout/(32 * 5);
if (!char_time)
char_time++;
} else
char_time = 1;
-
+
if (timeout)
char_time = min_t(unsigned long, char_time, timeout);
-
+
if (info->params.mode == MGSL_MODE_HDLC) {
while (info->tx_active) {
msleep_interruptible(jiffies_to_msecs(char_time));
@@ -2553,7 +2553,7 @@ static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout)
break;
}
}
-
+
exit:
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgslpc_wait_until_sent(%s) exit\n",
@@ -2566,18 +2566,18 @@ exit:
static void mgslpc_hangup(struct tty_struct *tty)
{
MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
-
+
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgslpc_hangup(%s)\n",
__FILE__,__LINE__, info->device_name );
-
+
if (mgslpc_paranoia_check(info, tty->name, "mgslpc_hangup"))
return;
mgslpc_flush_buffer(tty);
shutdown(info);
-
- info->count = 0;
+
+ info->count = 0;
info->flags &= ~ASYNC_NORMAL_ACTIVE;
info->tty = NULL;
@@ -2594,7 +2594,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
int retval;
int do_clocal = 0, extra_count = 0;
unsigned long flags;
-
+
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):block_til_ready on %s\n",
__FILE__,__LINE__, tty->driver->name );
@@ -2615,10 +2615,10 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
* mgslpc_close() knows when to free things. We restore it upon
* exit, either normal or abnormal.
*/
-
+
retval = 0;
add_wait_queue(&info->open_wait, &wait);
-
+
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):block_til_ready before block on %s count=%d\n",
__FILE__,__LINE__, tty->driver->name, info->count );
@@ -2630,7 +2630,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
}
spin_unlock_irqrestore(&info->lock, flags);
info->blocked_open++;
-
+
while (1) {
if ((tty->termios->c_cflag & CBAUD)) {
spin_lock_irqsave(&info->lock,flags);
@@ -2638,50 +2638,50 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
set_signals(info);
spin_unlock_irqrestore(&info->lock,flags);
}
-
+
set_current_state(TASK_INTERRUPTIBLE);
-
+
if (tty_hung_up_p(filp) || !(info->flags & ASYNC_INITIALIZED)){
retval = (info->flags & ASYNC_HUP_NOTIFY) ?
-EAGAIN : -ERESTARTSYS;
break;
}
-
+
spin_lock_irqsave(&info->lock,flags);
get_signals(info);
spin_unlock_irqrestore(&info->lock,flags);
-
+
if (!(info->flags & ASYNC_CLOSING) &&
(do_clocal || (info->serial_signals & SerialSignal_DCD)) ) {
break;
}
-
+
if (signal_pending(current)) {
retval = -ERESTARTSYS;
break;
}
-
+
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):block_til_ready blocking on %s count=%d\n",
__FILE__,__LINE__, tty->driver->name, info->count );
-
+
schedule();
}
-
+
set_current_state(TASK_RUNNING);
remove_wait_queue(&info->open_wait, &wait);
-
+
if (extra_count)
info->count++;
info->blocked_open--;
-
+
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):block_til_ready after blocking on %s count=%d\n",
__FILE__,__LINE__, tty->driver->name, info->count );
-
+
if (!retval)
info->flags |= ASYNC_NORMAL_ACTIVE;
-
+
return retval;
}
@@ -2691,7 +2691,7 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp)
int retval, line;
unsigned long flags;
- /* verify range of specified line number */
+ /* verify range of specified line number */
line = tty->index;
if ((line < 0) || (line >= mgslpc_device_count)) {
printk("%s(%d):mgslpc_open with invalid line #%d.\n",
@@ -2705,10 +2705,10 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp)
info = info->next_device;
if (mgslpc_paranoia_check(info, tty->name, "mgslpc_open"))
return -ENODEV;
-
+
tty->driver_data = info;
info->tty = tty;
-
+
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgslpc_open(%s), old ref count = %d\n",
__FILE__,__LINE__,tty->driver->name, info->count);
@@ -2721,7 +2721,7 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp)
-EAGAIN : -ERESTARTSYS);
goto cleanup;
}
-
+
info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
spin_lock_irqsave(&info->netlock, flags);
@@ -2752,15 +2752,15 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp)
printk("%s(%d):mgslpc_open(%s) success\n",
__FILE__,__LINE__, info->device_name);
retval = 0;
-
-cleanup:
+
+cleanup:
if (retval) {
if (tty->count == 1)
info->tty = NULL; /* tty layer will release tty struct */
if(info->count)
info->count--;
}
-
+
return retval;
}
@@ -2781,7 +2781,7 @@ static inline int line_info(char *buf, MGSLPC_INFO *info)
spin_lock_irqsave(&info->lock,flags);
get_signals(info);
spin_unlock_irqrestore(&info->lock,flags);
-
+
stat_buf[0] = 0;
stat_buf[1] = 0;
if (info->serial_signals & SerialSignal_RTS)
@@ -2805,7 +2805,7 @@ static inline int line_info(char *buf, MGSLPC_INFO *info)
if (info->icount.txabort)
ret += sprintf(buf+ret, " txabort:%d", info->icount.txabort);
if (info->icount.rxshort)
- ret += sprintf(buf+ret, " rxshort:%d", info->icount.rxshort);
+ ret += sprintf(buf+ret, " rxshort:%d", info->icount.rxshort);
if (info->icount.rxlong)
ret += sprintf(buf+ret, " rxlong:%d", info->icount.rxlong);
if (info->icount.rxover)
@@ -2820,18 +2820,18 @@ static inline int line_info(char *buf, MGSLPC_INFO *info)
if (info->icount.parity)
ret += sprintf(buf+ret, " pe:%d", info->icount.parity);
if (info->icount.brk)
- ret += sprintf(buf+ret, " brk:%d", info->icount.brk);
+ ret += sprintf(buf+ret, " brk:%d", info->icount.brk);
if (info->icount.overrun)
ret += sprintf(buf+ret, " oe:%d", info->icount.overrun);
}
-
+
/* Append serial signal status to end */
ret += sprintf(buf+ret, " %s\n", stat_buf+1);
-
+
ret += sprintf(buf+ret, "txactive=%d bh_req=%d bh_run=%d pending_bh=%x\n",
info->tx_active,info->bh_requested,info->bh_running,
info->pending_bh);
-
+
return ret;
}
@@ -2843,9 +2843,9 @@ static int mgslpc_read_proc(char *page, char **start, off_t off, int count,
int len = 0, l;
off_t begin = 0;
MGSLPC_INFO *info;
-
+
len += sprintf(page, "synclink driver:%s\n", driver_version);
-
+
info = mgslpc_device_list;
while( info ) {
l = line_info(page + len, info);
@@ -2902,7 +2902,7 @@ static int claim_resources(MGSLPC_INFO *info)
printk( "Cant allocate rx buffer %s\n", info->device_name);
release_resources(info);
return -ENODEV;
- }
+ }
return 0;
}
@@ -2915,7 +2915,7 @@ static void release_resources(MGSLPC_INFO *info)
/* Add the specified device instance data structure to the
* global linked list of devices and increment the device count.
- *
+ *
* Arguments: info pointer to device instance data
*/
static void mgslpc_add_device(MGSLPC_INFO *info)
@@ -2923,7 +2923,7 @@ static void mgslpc_add_device(MGSLPC_INFO *info)
info->next_device = NULL;
info->line = mgslpc_device_count;
sprintf(info->device_name,"ttySLP%d",info->line);
-
+
if (info->line < MAX_DEVICE_COUNT) {
if (maxframe[info->line])
info->max_frame_size = maxframe[info->line];
@@ -2931,21 +2931,21 @@ static void mgslpc_add_device(MGSLPC_INFO *info)
}
mgslpc_device_count++;
-
+
if (!mgslpc_device_list)
mgslpc_device_list = info;
- else {
+ else {
MGSLPC_INFO *current_dev = mgslpc_device_list;
while( current_dev->next_device )
current_dev = current_dev->next_device;
current_dev->next_device = info;
}
-
+
if (info->max_frame_size < 4096)
info->max_frame_size = 4096;
else if (info->max_frame_size > 65535)
info->max_frame_size = 65535;
-
+
printk( "SyncLink PC Card %s:IO=%04X IRQ=%d\n",
info->device_name, info->io_base, info->irq_level);
@@ -3060,7 +3060,7 @@ static int __init synclink_cs_init(void)
}
/* Initialize the tty_driver structure */
-
+
serial_driver->owner = THIS_MODULE;
serial_driver->driver_name = "synclink_cs";
serial_driver->name = "ttySLP";
@@ -3081,11 +3081,11 @@ static int __init synclink_cs_init(void)
serial_driver = NULL;
goto error;
}
-
+
printk("%s %s, tty major#%d\n",
driver_name, driver_version,
serial_driver->major);
-
+
return 0;
error:
@@ -3093,7 +3093,7 @@ error:
return rc;
}
-static void __exit synclink_cs_exit(void)
+static void __exit synclink_cs_exit(void)
{
synclink_cs_cleanup();
}
@@ -3106,8 +3106,8 @@ static void mgslpc_set_rate(MGSLPC_INFO *info, unsigned char channel, unsigned i
unsigned int M, N;
unsigned char val;
- /* note:standard BRG mode is broken in V3.2 chip
- * so enhanced mode is always used
+ /* note:standard BRG mode is broken in V3.2 chip
+ * so enhanced mode is always used
*/
if (rate) {
@@ -3126,7 +3126,7 @@ static void mgslpc_set_rate(MGSLPC_INFO *info, unsigned char channel, unsigned i
* divisor = (N+1)*2^M
*
* Note: M *must* not be zero (causes asymetric duty cycle)
- */
+ */
write_reg(info, (unsigned char) (channel + BGR),
(unsigned char) ((M << 6) + N));
val = read_reg(info, (unsigned char) (channel + CCR2)) & 0x3f;
@@ -3140,7 +3140,7 @@ static void mgslpc_set_rate(MGSLPC_INFO *info, unsigned char channel, unsigned i
static void enable_auxclk(MGSLPC_INFO *info)
{
unsigned char val;
-
+
/* MODE
*
* 07..06 MDS[1..0] 10 = transparent HDLC mode
@@ -3152,14 +3152,14 @@ static void enable_auxclk(MGSLPC_INFO *info)
* 00 TLP Test Loop, 0 = no loop
*
* 1000 0010
- */
+ */
val = 0x82;
-
- /* channel B RTS is used to enable AUXCLK driver on SP505 */
+
+ /* channel B RTS is used to enable AUXCLK driver on SP505 */
if (info->params.mode == MGSL_MODE_HDLC && info->params.clock_speed)
val |= BIT2;
write_reg(info, CHB + MODE, val);
-
+
/* CCR0
*
* 07 PU Power Up, 1=active, 0=power down
@@ -3169,9 +3169,9 @@ static void enable_auxclk(MGSLPC_INFO *info)
* 01..00 SM[1..0] Serial Mode, 00=HDLC
*
* 11000000
- */
+ */
write_reg(info, CHB + CCR0, 0xc0);
-
+
/* CCR1
*
* 07 SFLG Shared Flag, 0 = disable shared flags
@@ -3182,9 +3182,9 @@ static void enable_auxclk(MGSLPC_INFO *info)
* 02..00 CM[2..0] Clock Mode
*
* 0001 0111
- */
+ */
write_reg(info, CHB + CCR1, 0x17);
-
+
/* CCR2 (Channel B)
*
* 07..06 BGR[9..8] Baud rate bits 9..8
@@ -3196,12 +3196,12 @@ static void enable_auxclk(MGSLPC_INFO *info)
* 00 DIV, data inversion 0=disabled, 1=enabled
*
* 0011 1000
- */
+ */
if (info->params.mode == MGSL_MODE_HDLC && info->params.clock_speed)
write_reg(info, CHB + CCR2, 0x38);
else
write_reg(info, CHB + CCR2, 0x30);
-
+
/* CCR4
*
* 07 MCK4 Master Clock Divide by 4, 1=enabled
@@ -3212,37 +3212,37 @@ static void enable_auxclk(MGSLPC_INFO *info)
* 01..00 RFT[1..0] RxFIFO Threshold 00=32 bytes
*
* 0101 0000
- */
+ */
write_reg(info, CHB + CCR4, 0x50);
-
+
/* if auxclk not enabled, set internal BRG so
* CTS transitions can be detected (requires TxC)
- */
+ */
if (info->params.mode == MGSL_MODE_HDLC && info->params.clock_speed)
mgslpc_set_rate(info, CHB, info->params.clock_speed);
else
mgslpc_set_rate(info, CHB, 921600);
}
-static void loopback_enable(MGSLPC_INFO *info)
+static void loopback_enable(MGSLPC_INFO *info)
{
unsigned char val;
-
- /* CCR1:02..00 CM[2..0] Clock Mode = 111 (clock mode 7) */
+
+ /* CCR1:02..00 CM[2..0] Clock Mode = 111 (clock mode 7) */
val = read_reg(info, CHA + CCR1) | (BIT2 + BIT1 + BIT0);
write_reg(info, CHA + CCR1, val);
-
- /* CCR2:04 SSEL Clock source select, 1=submode b */
+
+ /* CCR2:04 SSEL Clock source select, 1=submode b */
val = read_reg(info, CHA + CCR2) | (BIT4 + BIT5);
write_reg(info, CHA + CCR2, val);
-
- /* set LinkSpeed if available, otherwise default to 2Mbps */
+
+ /* set LinkSpeed if available, otherwise default to 2Mbps */
if (info->params.clock_speed)
mgslpc_set_rate(info, CHA, info->params.clock_speed);
else
mgslpc_set_rate(info, CHA, 1843200);
-
- /* MODE:00 TLP Test Loop, 1=loopback enabled */
+
+ /* MODE:00 TLP Test Loop, 1=loopback enabled */
val = read_reg(info, CHA + MODE) | BIT0;
write_reg(info, CHA + MODE, val);
}
@@ -3252,36 +3252,36 @@ static void hdlc_mode(MGSLPC_INFO *info)
unsigned char val;
unsigned char clkmode, clksubmode;
- /* disable all interrupts */
+ /* disable all interrupts */
irq_disable(info, CHA, 0xffff);
irq_disable(info, CHB, 0xffff);
port_irq_disable(info, 0xff);
-
- /* assume clock mode 0a, rcv=RxC xmt=TxC */
+
+ /* assume clock mode 0a, rcv=RxC xmt=TxC */
clkmode = clksubmode = 0;
if (info->params.flags & HDLC_FLAG_RXC_DPLL
&& info->params.flags & HDLC_FLAG_TXC_DPLL) {
- /* clock mode 7a, rcv = DPLL, xmt = DPLL */
+ /* clock mode 7a, rcv = DPLL, xmt = DPLL */
clkmode = 7;
} else if (info->params.flags & HDLC_FLAG_RXC_BRG
&& info->params.flags & HDLC_FLAG_TXC_BRG) {
- /* clock mode 7b, rcv = BRG, xmt = BRG */
+ /* clock mode 7b, rcv = BRG, xmt = BRG */
clkmode = 7;
clksubmode = 1;
} else if (info->params.flags & HDLC_FLAG_RXC_DPLL) {
if (info->params.flags & HDLC_FLAG_TXC_BRG) {
- /* clock mode 6b, rcv = DPLL, xmt = BRG/16 */
+ /* clock mode 6b, rcv = DPLL, xmt = BRG/16 */
clkmode = 6;
clksubmode = 1;
} else {
- /* clock mode 6a, rcv = DPLL, xmt = TxC */
+ /* clock mode 6a, rcv = DPLL, xmt = TxC */
clkmode = 6;
}
} else if (info->params.flags & HDLC_FLAG_TXC_BRG) {
- /* clock mode 0b, rcv = RxC, xmt = BRG */
+ /* clock mode 0b, rcv = RxC, xmt = BRG */
clksubmode = 1;
}
-
+
/* MODE
*
* 07..06 MDS[1..0] 10 = transparent HDLC mode
@@ -3293,16 +3293,16 @@ static void hdlc_mode(MGSLPC_INFO *info)
* 00 TLP Test Loop, 0 = no loop
*
* 1000 0010
- */
+ */
val = 0x82;
if (info->params.loopback)
val |= BIT0;
-
- /* preserve RTS state */
+
+ /* preserve RTS state */
if (info->serial_signals & SerialSignal_RTS)
val |= BIT2;
write_reg(info, CHA + MODE, val);
-
+
/* CCR0
*
* 07 PU Power Up, 1=active, 0=power down
@@ -3312,7 +3312,7 @@ static void hdlc_mode(MGSLPC_INFO *info)
* 01..00 SM[1..0] Serial Mode, 00=HDLC
*
* 11000000
- */
+ */
val = 0xc0;
switch (info->params.encoding)
{
@@ -3330,7 +3330,7 @@ static void hdlc_mode(MGSLPC_INFO *info)
break; // Manchester
}
write_reg(info, CHA + CCR0, val);
-
+
/* CCR1
*
* 07 SFLG Shared Flag, 0 = disable shared flags
@@ -3341,10 +3341,10 @@ static void hdlc_mode(MGSLPC_INFO *info)
* 02..00 CM[2..0] Clock Mode
*
* 0001 0000
- */
+ */
val = 0x10 + clkmode;
write_reg(info, CHA + CCR1, val);
-
+
/* CCR2
*
* 07..06 BGR[9..8] Baud rate bits 9..8
@@ -3356,7 +3356,7 @@ static void hdlc_mode(MGSLPC_INFO *info)
* 00 DIV, data inversion 0=disabled, 1=enabled
*
* 0000 0000
- */
+ */
val = 0x00;
if (clkmode == 2 || clkmode == 3 || clkmode == 6
|| clkmode == 7 || (clkmode == 0 && clksubmode == 1))
@@ -3368,7 +3368,7 @@ static void hdlc_mode(MGSLPC_INFO *info)
if (info->params.encoding == HDLC_ENCODING_NRZB)
val |= BIT0;
write_reg(info, CHA + CCR2, val);
-
+
/* CCR3
*
* 07..06 PRE[1..0] Preamble count 00=1, 01=2, 10=4, 11=8
@@ -3380,7 +3380,7 @@ static void hdlc_mode(MGSLPC_INFO *info)
* 00 PSD DPLL Phase Shift Disable
*
* 0000 0000
- */
+ */
val = 0x00;
if (info->params.crc_type == HDLC_CRC_NONE)
val |= BIT2 + BIT1;
@@ -3399,8 +3399,8 @@ static void hdlc_mode(MGSLPC_INFO *info)
break;
}
write_reg(info, CHA + CCR3, val);
-
- /* PRE - Preamble pattern */
+
+ /* PRE - Preamble pattern */
val = 0;
switch (info->params.preamble)
{
@@ -3410,7 +3410,7 @@ static void hdlc_mode(MGSLPC_INFO *info)
case HDLC_PREAMBLE_PATTERN_ONES: val = 0xff; break;
}
write_reg(info, CHA + PRE, val);
-
+
/* CCR4
*
* 07 MCK4 Master Clock Divide by 4, 1=enabled
@@ -3421,21 +3421,21 @@ static void hdlc_mode(MGSLPC_INFO *info)
* 01..00 RFT[1..0] RxFIFO Threshold 00=32 bytes
*
* 0101 0000
- */
+ */
val = 0x50;
write_reg(info, CHA + CCR4, val);
if (info->params.flags & HDLC_FLAG_RXC_DPLL)
mgslpc_set_rate(info, CHA, info->params.clock_speed * 16);
else
mgslpc_set_rate(info, CHA, info->params.clock_speed);
-
+
/* RLCR Receive length check register
*
* 7 1=enable receive length check
* 6..0 Max frame length = (RL + 1) * 32
- */
+ */
write_reg(info, CHA + RLCR, 0);
-
+
/* XBCH Transmit Byte Count High
*
* 07 DMA mode, 0 = interrupt driven
@@ -3445,7 +3445,7 @@ static void hdlc_mode(MGSLPC_INFO *info)
* 03..00 XBC[10..8] Transmit byte count bits 10..8
*
* 0000 0000
- */
+ */
val = 0x00;
if (info->params.flags & HDLC_FLAG_AUTO_DCD)
val |= BIT5;
@@ -3456,7 +3456,7 @@ static void hdlc_mode(MGSLPC_INFO *info)
if (info->params.flags & HDLC_FLAG_AUTO_CTS)
{
irq_enable(info, CHB, IRQ_CTS);
- /* PVR[3] 1=AUTO CTS active */
+ /* PVR[3] 1=AUTO CTS active */
set_reg_bits(info, CHA + PVR, BIT3);
} else
clear_reg_bits(info, CHA + PVR, BIT3);
@@ -3467,7 +3467,7 @@ static void hdlc_mode(MGSLPC_INFO *info)
issue_command(info, CHA, CMD_TXRESET + CMD_RXRESET);
wait_command_complete(info, CHA);
read_reg16(info, CHA + ISR); /* clear pending IRQs */
-
+
/* Master clock mode enabled above to allow reset commands
* to complete even if no data clocks are present.
*
@@ -3477,7 +3477,7 @@ static void hdlc_mode(MGSLPC_INFO *info)
*
* Leave master clock mode enabled for IRQ test because the
* timer IRQ used by the test can only happen in master clock mode.
- */
+ */
if (!info->testing_irq)
clear_reg_bits(info, CHA + CCR0, BIT6);
@@ -3492,8 +3492,8 @@ static void rx_stop(MGSLPC_INFO *info)
if (debug_level >= DEBUG_LEVEL_ISR)
printk("%s(%d):rx_stop(%s)\n",
__FILE__,__LINE__, info->device_name );
-
- /* MODE:03 RAC Receiver Active, 0=inactive */
+
+ /* MODE:03 RAC Receiver Active, 0=inactive */
clear_reg_bits(info, CHA + MODE, BIT3);
info->rx_enabled = 0;
@@ -3510,7 +3510,7 @@ static void rx_start(MGSLPC_INFO *info)
info->rx_enabled = 0;
info->rx_overflow = 0;
- /* MODE:03 RAC Receiver Active, 1=active */
+ /* MODE:03 RAC Receiver Active, 1=active */
set_reg_bits(info, CHA + MODE, BIT3);
info->rx_enabled = 1;
@@ -3521,7 +3521,7 @@ static void tx_start(MGSLPC_INFO *info)
if (debug_level >= DEBUG_LEVEL_ISR)
printk("%s(%d):tx_start(%s)\n",
__FILE__,__LINE__, info->device_name );
-
+
if (info->tx_count) {
/* If auto RTS enabled and RTS is inactive, then assert */
/* RTS and set a flag indicating that the driver should */
@@ -3559,8 +3559,8 @@ static void tx_stop(MGSLPC_INFO *info)
if (debug_level >= DEBUG_LEVEL_ISR)
printk("%s(%d):tx_stop(%s)\n",
__FILE__,__LINE__, info->device_name );
-
- del_timer(&info->tx_timer);
+
+ del_timer(&info->tx_timer);
info->tx_enabled = 0;
info->tx_active = 0;
@@ -3570,17 +3570,17 @@ static void tx_stop(MGSLPC_INFO *info)
*/
static void reset_device(MGSLPC_INFO *info)
{
- /* power up both channels (set BIT7) */
+ /* power up both channels (set BIT7) */
write_reg(info, CHA + CCR0, 0x80);
write_reg(info, CHB + CCR0, 0x80);
write_reg(info, CHA + MODE, 0);
write_reg(info, CHB + MODE, 0);
-
- /* disable all interrupts */
+
+ /* disable all interrupts */
irq_disable(info, CHA, 0xffff);
irq_disable(info, CHB, 0xffff);
port_irq_disable(info, 0xff);
-
+
/* PCR Port Configuration Register
*
* 07..04 DEC[3..0] Serial I/F select outputs
@@ -3590,9 +3590,9 @@ static void reset_device(MGSLPC_INFO *info)
* 00 DTR output 0=active
*
* 0000 0110
- */
+ */
write_reg(info, PCR, 0x06);
-
+
/* PVR Port Value Register
*
* 07..04 DEC[3..0] Serial I/F select (0000=disabled)
@@ -3604,7 +3604,7 @@ static void reset_device(MGSLPC_INFO *info)
* 0000 0001
*/
// write_reg(info, PVR, PVR_DTR);
-
+
/* IPC Interrupt Port Configuration
*
* 07 VIS 1=Masked interrupts visible
@@ -3614,7 +3614,7 @@ static void reset_device(MGSLPC_INFO *info)
* 01..00 IC[1..0] Interrupt Config, 01=push-pull output, active low
*
* 0000 0101
- */
+ */
write_reg(info, IPC, 0x05);
}
@@ -3622,11 +3622,11 @@ static void async_mode(MGSLPC_INFO *info)
{
unsigned char val;
- /* disable all interrupts */
+ /* disable all interrupts */
irq_disable(info, CHA, 0xffff);
irq_disable(info, CHB, 0xffff);
port_irq_disable(info, 0xff);
-
+
/* MODE
*
* 07 Reserved, 0
@@ -3639,16 +3639,16 @@ static void async_mode(MGSLPC_INFO *info)
* 00 TLP Test Loop, 0 = no loop
*
* 0000 0110
- */
+ */
val = 0x06;
if (info->params.loopback)
val |= BIT0;
-
- /* preserve RTS state */
+
+ /* preserve RTS state */
if (!(info->serial_signals & SerialSignal_RTS))
val |= BIT6;
write_reg(info, CHA + MODE, val);
-
+
/* CCR0
*
* 07 PU Power Up, 1=active, 0=power down
@@ -3658,9 +3658,9 @@ static void async_mode(MGSLPC_INFO *info)
* 01..00 SM[1..0] Serial Mode, 11=Async
*
* 1000 0011
- */
+ */
write_reg(info, CHA + CCR0, 0x83);
-
+
/* CCR1
*
* 07..05 Reserved, 0
@@ -3669,9 +3669,9 @@ static void async_mode(MGSLPC_INFO *info)
* 02..00 CM[2..0] Clock Mode, 111=BRG
*
* 0001 1111
- */
+ */
write_reg(info, CHA + CCR1, 0x1f);
-
+
/* CCR2 (channel A)
*
* 07..06 BGR[9..8] Baud rate bits 9..8
@@ -3683,18 +3683,18 @@ static void async_mode(MGSLPC_INFO *info)
* 00 DIV, data inversion 0=disabled, 1=enabled
*
* 0001 0000
- */
+ */
write_reg(info, CHA + CCR2, 0x10);
-
+
/* CCR3
*
* 07..01 Reserved, 0
* 00 PSD DPLL Phase Shift Disable
*
* 0000 0000
- */
+ */
write_reg(info, CHA + CCR3, 0);
-
+
/* CCR4
*
* 07 MCK4 Master Clock Divide by 4, 1=enabled
@@ -3704,10 +3704,10 @@ static void async_mode(MGSLPC_INFO *info)
* 03..00 Reserved, must be 0
*
* 0101 0000
- */
+ */
write_reg(info, CHA + CCR4, 0x50);
mgslpc_set_rate(info, CHA, info->params.data_rate * 16);
-
+
/* DAFO Data Format
*
* 07 Reserved, 0
@@ -3717,7 +3717,7 @@ static void async_mode(MGSLPC_INFO *info)
* 02 PAREN Parity Enable
* 01..00 CHL[1..0] Character Length (00=8, 01=7)
*
- */
+ */
val = 0x00;
if (info->params.data_bits != 8)
val |= BIT0; /* 7 bits */
@@ -3732,7 +3732,7 @@ static void async_mode(MGSLPC_INFO *info)
val |= BIT4;
}
write_reg(info, CHA + DAFO, val);
-
+
/* RFC Rx FIFO Control
*
* 07 Reserved, 0
@@ -3744,15 +3744,15 @@ static void async_mode(MGSLPC_INFO *info)
* 00 TCDE Terminate Char Detect Enable, 0=disabled
*
* 0101 1100
- */
+ */
write_reg(info, CHA + RFC, 0x5c);
-
+
/* RLCR Receive length check register
*
* Max frame length = (RL + 1) * 32
- */
+ */
write_reg(info, CHA + RLCR, 0);
-
+
/* XBCH Transmit Byte Count High
*
* 07 DMA mode, 0 = interrupt driven
@@ -3762,20 +3762,20 @@ static void async_mode(MGSLPC_INFO *info)
* 03..00 XBC[10..8] Transmit byte count bits 10..8
*
* 0000 0000
- */
+ */
val = 0x00;
if (info->params.flags & HDLC_FLAG_AUTO_DCD)
val |= BIT5;
write_reg(info, CHA + XBCH, val);
if (info->params.flags & HDLC_FLAG_AUTO_CTS)
irq_enable(info, CHA, IRQ_CTS);
-
- /* MODE:03 RAC Receiver Active, 1=active */
+
+ /* MODE:03 RAC Receiver Active, 1=active */
set_reg_bits(info, CHA + MODE, BIT3);
enable_auxclk(info);
if (info->params.flags & HDLC_FLAG_AUTO_CTS) {
irq_enable(info, CHB, IRQ_CTS);
- /* PVR[3] 1=AUTO CTS active */
+ /* PVR[3] 1=AUTO CTS active */
set_reg_bits(info, CHA + PVR, BIT3);
} else
clear_reg_bits(info, CHA + PVR, BIT3);
@@ -3791,7 +3791,7 @@ static void async_mode(MGSLPC_INFO *info)
*/
static void tx_set_idle(MGSLPC_INFO *info)
{
- /* Note: ESCC2 only supports flags and one idle modes */
+ /* Note: ESCC2 only supports flags and one idle modes */
if (info->idle_mode == HDLC_TXIDLE_FLAGS)
set_reg_bits(info, CHA + CCR1, BIT3);
else
@@ -3803,8 +3803,8 @@ static void tx_set_idle(MGSLPC_INFO *info)
static void get_signals(MGSLPC_INFO *info)
{
unsigned char status = 0;
-
- /* preserve DTR and RTS */
+
+ /* preserve DTR and RTS */
info->serial_signals &= SerialSignal_DTR + SerialSignal_RTS;
if (read_reg(info, CHB + VSTR) & BIT7)
@@ -3873,7 +3873,7 @@ static int rx_get_frame(MGSLPC_INFO *info)
unsigned long flags;
struct tty_struct *tty = info->tty;
int return_frame = 0;
-
+
if (info->rx_frame_count == 0)
return 0;
@@ -3913,10 +3913,10 @@ static int rx_get_frame(MGSLPC_INFO *info)
if (debug_level >= DEBUG_LEVEL_BH)
printk("%s(%d):rx_get_frame(%s) status=%04X size=%d\n",
__FILE__,__LINE__,info->device_name,status,framesize);
-
+
if (debug_level >= DEBUG_LEVEL_DATA)
- trace_block(info, buf->data, framesize, 0);
-
+ trace_block(info, buf->data, framesize, 0);
+
if (framesize) {
if ((info->params.crc_type & HDLC_CRC_RETURN_EX &&
framesize+1 > info->max_frame_size) ||
@@ -3953,7 +3953,7 @@ static int rx_get_frame(MGSLPC_INFO *info)
static BOOLEAN register_test(MGSLPC_INFO *info)
{
- static unsigned char patterns[] =
+ static unsigned char patterns[] =
{ 0x00, 0xff, 0xaa, 0x55, 0x69, 0x96, 0x0f };
static unsigned int count = ARRAY_SIZE(patterns);
unsigned int i;
@@ -4002,13 +4002,13 @@ static BOOLEAN irq_test(MGSLPC_INFO *info)
while(end_time-- && !info->irq_occurred) {
msleep_interruptible(10);
}
-
+
info->testing_irq = FALSE;
spin_lock_irqsave(&info->lock,flags);
reset_device(info);
spin_unlock_irqrestore(&info->lock,flags);
-
+
return info->irq_occurred ? TRUE : FALSE;
}
@@ -4042,13 +4042,13 @@ static void trace_block(MGSLPC_INFO *info,const char* data, int count, int xmit)
printk("%s tx data:\n",info->device_name);
else
printk("%s rx data:\n",info->device_name);
-
+
while(count) {
if (count > 16)
linecount = 16;
else
linecount = count;
-
+
for(i=0;i<linecount;i++)
printk("%02X ",(unsigned char)data[i]);
for(;i<17;i++)
@@ -4060,7 +4060,7 @@ static void trace_block(MGSLPC_INFO *info,const char* data, int count, int xmit)
printk(".");
}
printk("\n");
-
+
data += linecount;
count -= linecount;
}
@@ -4073,7 +4073,7 @@ static void tx_timeout(unsigned long context)
{
MGSLPC_INFO *info = (MGSLPC_INFO*)context;
unsigned long flags;
-
+
if ( debug_level >= DEBUG_LEVEL_INFO )
printk( "%s(%d):tx_timeout(%s)\n",
__FILE__,__LINE__,info->device_name);
@@ -4086,7 +4086,7 @@ static void tx_timeout(unsigned long context)
info->tx_count = info->tx_put = info->tx_get = 0;
spin_unlock_irqrestore(&info->lock,flags);
-
+
#if SYNCLINK_GENERIC_HDLC
if (info->netcount)
hdlcdev_tx_done(info);
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index 84ac64fc48a1..3aab837d9480 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -66,7 +66,6 @@
#include <linux/poll.h>
#include <linux/major.h>
#include <linux/ppdev.h>
-#include <linux/device.h>
#include <asm/uaccess.h>
#define PP_VERSION "ppdev: user-space parallel port driver"
@@ -268,9 +267,9 @@ static ssize_t pp_write (struct file * file, const char __user * buf,
return bytes_written;
}
-static void pp_irq (int irq, void * private)
+static void pp_irq (void *private)
{
- struct pp_struct * pp = (struct pp_struct *) private;
+ struct pp_struct *pp = private;
if (pp->irqresponse) {
parport_write_control (pp->pdev->port, pp->irqctl);
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index 73de77105fea..706ff34728f1 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -318,7 +318,7 @@ int pty_limit = NR_UNIX98_PTY_DEFAULT;
static int pty_limit_min = 0;
static int pty_limit_max = NR_UNIX98_PTY_MAX;
-ctl_table pty_table[] = {
+static struct ctl_table pty_table[] = {
{
.ctl_name = PTY_MAX,
.procname = "max",
@@ -340,6 +340,27 @@ ctl_table pty_table[] = {
}
};
+static struct ctl_table pty_kern_table[] = {
+ {
+ .ctl_name = KERN_PTY,
+ .procname = "pty",
+ .mode = 0555,
+ .child = pty_table,
+ },
+ {}
+};
+
+static struct ctl_table pty_root_table[] = {
+ {
+ .ctl_name = CTL_KERN,
+ .procname = "kernel",
+ .mode = 0555,
+ .child = pty_kern_table,
+ },
+ {}
+};
+
+
static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
@@ -404,6 +425,7 @@ static void __init unix98_pty_init(void)
panic("Couldn't register Unix98 pts driver");
pty_table[1].data = &ptm_driver->refcount;
+ register_sysctl_table(pty_root_table);
}
#else
static inline void unix98_pty_init(void) { }
diff --git a/drivers/char/random.c b/drivers/char/random.c
index af274e5a25ee..5fee05661823 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -649,7 +649,7 @@ EXPORT_SYMBOL_GPL(add_input_randomness);
void add_interrupt_randomness(int irq)
{
- if (irq >= NR_IRQS || irq_timer_state[irq] == 0)
+ if (irq >= NR_IRQS || irq_timer_state[irq] == NULL)
return;
DEBUG_ENT("irq event %d\n", irq);
@@ -1494,7 +1494,7 @@ __u32 secure_tcpv6_sequence_number(__be32 *saddr, __be32 *daddr,
seq = twothirdsMD4Transform((const __u32 *)daddr, hash) & HASH_MASK;
seq += keyptr->count;
- seq += ktime_get_real().tv64;
+ seq += ktime_to_ns(ktime_get_real());
return seq;
}
@@ -1556,7 +1556,7 @@ __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
* overlaps less than one time per MSL (2 minutes).
* Choosing a clock of 64 ns period is OK. (period of 274 s)
*/
- seq += ktime_get_real().tv64 >> 6;
+ seq += ktime_to_ns(ktime_get_real()) >> 6;
#if 0
printk("init_seq(%lx, %lx, %d, %d) = %d\n",
saddr, daddr, sport, dport, seq);
@@ -1616,7 +1616,7 @@ u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
seq = half_md4_transform(hash, keyptr->secret);
seq |= ((u64)keyptr->count) << (32 - HASH_BITS);
- seq += ktime_get_real().tv64;
+ seq += ktime_to_ns(ktime_get_real());
seq &= (1ull << 48) - 1;
#if 0
printk("dccp init_seq(%lx, %lx, %d, %d) = %d\n",
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c
index b37e626f4faa..102ece4c4e0e 100644
--- a/drivers/char/riscom8.c
+++ b/drivers/char/riscom8.c
@@ -79,7 +79,6 @@
#define RS_EVENT_WRITE_WAKEUP 0
-static struct riscom_board * IRQ_to_board[16];
static struct tty_driver *riscom_driver;
static struct riscom_board rc_board[RC_NBOARD] = {
@@ -537,16 +536,14 @@ static inline void rc_check_modem(struct riscom_board const * bp)
}
/* The main interrupt processing routine */
-static irqreturn_t rc_interrupt(int irq, void * dev_id)
+static irqreturn_t rc_interrupt(int dummy, void * dev_id)
{
unsigned char status;
unsigned char ack;
- struct riscom_board *bp;
+ struct riscom_board *bp = dev_id;
unsigned long loop = 0;
int handled = 0;
- bp = IRQ_to_board[irq];
-
if (!(bp->flags & RC_BOARD_ACTIVE))
return IRQ_NONE;
@@ -603,7 +600,7 @@ static irqreturn_t rc_interrupt(int irq, void * dev_id)
*/
/* Called with disabled interrupts */
-static inline int rc_setup_board(struct riscom_board * bp)
+static int rc_setup_board(struct riscom_board * bp)
{
int error;
@@ -611,7 +608,7 @@ static inline int rc_setup_board(struct riscom_board * bp)
return 0;
error = request_irq(bp->irq, rc_interrupt, IRQF_DISABLED,
- "RISCom/8", NULL);
+ "RISCom/8", bp);
if (error)
return error;
@@ -619,14 +616,13 @@ static inline int rc_setup_board(struct riscom_board * bp)
bp->DTR = ~0;
rc_out(bp, RC_DTR, bp->DTR); /* Drop DTR on all ports */
- IRQ_to_board[bp->irq] = bp;
bp->flags |= RC_BOARD_ACTIVE;
return 0;
}
/* Called with disabled interrupts */
-static inline void rc_shutdown_board(struct riscom_board *bp)
+static void rc_shutdown_board(struct riscom_board *bp)
{
if (!(bp->flags & RC_BOARD_ACTIVE))
return;
@@ -634,7 +630,6 @@ static inline void rc_shutdown_board(struct riscom_board *bp)
bp->flags &= ~RC_BOARD_ACTIVE;
free_irq(bp->irq, NULL);
- IRQ_to_board[bp->irq] = NULL;
bp->DTR = ~0;
rc_out(bp, RC_DTR, bp->DTR); /* Drop DTR on all ports */
@@ -1594,7 +1589,6 @@ static inline int rc_init_drivers(void)
if (!riscom_driver)
return -ENOMEM;
- memset(IRQ_to_board, 0, sizeof(IRQ_to_board));
riscom_driver->owner = THIS_MODULE;
riscom_driver->name = "ttyL";
riscom_driver->major = RISCOM8_NORMAL_MAJOR;
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index 56cbba7b6ec0..d83419c3857e 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -84,6 +84,7 @@
#include <linux/mutex.h>
#include <linux/ioport.h>
#include <linux/delay.h>
+#include <linux/completion.h>
#include <linux/wait.h>
#include <linux/pci.h>
#include <asm/uaccess.h>
@@ -548,8 +549,8 @@ static void rp_handle_port(struct r_port *info)
static void rp_do_poll(unsigned long dummy)
{
CONTROLLER_t *ctlp;
- int ctrl, aiop, ch, line, i;
- unsigned int xmitmask;
+ int ctrl, aiop, ch, line;
+ unsigned int xmitmask, i;
unsigned int CtlMask;
unsigned char AiopMask;
Word_t bit;
@@ -562,7 +563,7 @@ static void rp_do_poll(unsigned long dummy)
/* Get a ptr to the board's control struct */
ctlp = sCtlNumToCtlPtr(ctrl);
- /* Get the interupt status from the board */
+ /* Get the interrupt status from the board */
#ifdef CONFIG_PCI
if (ctlp->BusType == isPCI)
CtlMask = sPCIGetControllerIntStatus(ctlp);
@@ -650,7 +651,7 @@ static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev)
info->closing_wait = 3000;
info->close_delay = 50;
init_waitqueue_head(&info->open_wait);
- init_waitqueue_head(&info->close_wait);
+ init_completion(&info->close_wait);
info->flags &= ~ROCKET_MODE_MASK;
switch (pc104[board][line]) {
case 422:
@@ -699,8 +700,8 @@ static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev)
spin_lock_init(&info->slock);
mutex_init(&info->write_mtx);
rp_table[line] = info;
- if (pci_dev)
- tty_register_device(rocket_driver, line, &pci_dev->dev);
+ tty_register_device(rocket_driver, line, pci_dev ? &pci_dev->dev :
+ NULL);
}
/*
@@ -878,7 +879,8 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
if (tty_hung_up_p(filp))
return ((info->flags & ROCKET_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
if (info->flags & ROCKET_CLOSING) {
- interruptible_sleep_on(&info->close_wait);
+ if (wait_for_completion_interruptible(&info->close_wait))
+ return -ERESTARTSYS;
return ((info->flags & ROCKET_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
}
@@ -983,8 +985,10 @@ static int rp_open(struct tty_struct *tty, struct file *filp)
return -ENOMEM;
if (info->flags & ROCKET_CLOSING) {
- interruptible_sleep_on(&info->close_wait);
+ retval = wait_for_completion_interruptible(&info->close_wait);
free_page(page);
+ if (retval)
+ return retval;
return ((info->flags & ROCKET_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
}
@@ -1176,7 +1180,7 @@ static void rp_close(struct tty_struct *tty, struct file *filp)
}
info->flags &= ~(ROCKET_INITIALIZED | ROCKET_CLOSING | ROCKET_NORMAL_ACTIVE);
tty->closing = 0;
- wake_up_interruptible(&info->close_wait);
+ complete_all(&info->close_wait);
atomic_dec(&rp_num_ports_open);
#ifdef ROCKET_DEBUG_OPEN
@@ -1869,8 +1873,6 @@ static __init int register_PCI(int i, struct pci_dev *dev)
int fast_clock = 0;
int altChanRingIndicator = 0;
int ports_per_aiop = 8;
- int ret;
- unsigned int class_rev;
WordIO_t ConfigIO = 0;
ByteIO_t UPCIRingInd = 0;
@@ -1878,12 +1880,6 @@ static __init int register_PCI(int i, struct pci_dev *dev)
return 0;
rcktpt_io_addr[i] = pci_resource_start(dev, 0);
- ret = pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
-
- if (ret) {
- printk(KERN_INFO " Error during register_PCI(), unable to read config dword \n");
- return 0;
- }
rcktpt_type[i] = ROCKET_TYPE_NORMAL;
rocketModel[i].loadrm2 = 0;
@@ -2037,8 +2033,9 @@ static __init int register_PCI(int i, struct pci_dev *dev)
ports_per_aiop = 6;
str = "6-port";
- /* If class_rev is 1, the rocketmodem flash must be loaded. If it is 2 it is a "socketed" version. */
- if ((class_rev & 0xFF) == 1) {
+ /* If revision is 1, the rocketmodem flash must be loaded.
+ * If it is 2 it is a "socketed" version. */
+ if (dev->revision == 1) {
rcktpt_type[i] = ROCKET_TYPE_MODEMII;
rocketModel[i].loadrm2 = 1;
} else {
@@ -2053,7 +2050,7 @@ static __init int register_PCI(int i, struct pci_dev *dev)
max_num_aiops = 1;
ports_per_aiop = 4;
str = "4-port";
- if ((class_rev & 0xFF) == 1) {
+ if (dev->revision == 1) {
rcktpt_type[i] = ROCKET_TYPE_MODEMII;
rocketModel[i].loadrm2 = 1;
} else {
@@ -2362,26 +2359,14 @@ static const struct tty_operations rocket_ops = {
*/
static int __init rp_init(void)
{
- int retval, pci_boards_found, isa_boards_found, i;
+ int ret = -ENOMEM, pci_boards_found, isa_boards_found, i;
printk(KERN_INFO "RocketPort device driver module, version %s, %s\n",
ROCKET_VERSION, ROCKET_DATE);
rocket_driver = alloc_tty_driver(MAX_RP_PORTS);
if (!rocket_driver)
- return -ENOMEM;
-
- /*
- * Initialize the array of pointers to our own internal state
- * structures.
- */
- memset(rp_table, 0, sizeof (rp_table));
- memset(xmit_flags, 0, sizeof (xmit_flags));
-
- for (i = 0; i < MAX_RP_PORTS; i++)
- lineNumbers[i] = 0;
- nextLineNumber = 0;
- memset(rocketModel, 0, sizeof (rocketModel));
+ goto err;
/*
* If board 1 is non-zero, there is at least one ISA configured. If controller is
@@ -2396,8 +2381,11 @@ static int __init rp_init(void)
/* If an ISA card is configured, reserve the 4 byte IO space for the Mudbac controller */
if (controller && (!request_region(controller, 4, "Comtrol RocketPort"))) {
- printk(KERN_INFO "Unable to reserve IO region for first configured ISA RocketPort controller 0x%lx. Driver exiting \n", controller);
- return -EBUSY;
+ printk(KERN_ERR "Unable to reserve IO region for first "
+ "configured ISA RocketPort controller 0x%lx. "
+ "Driver exiting\n", controller);
+ ret = -EBUSY;
+ goto err_tty;
}
/* Store ISA variable retrieved from command line or .conf file. */
@@ -2434,15 +2422,14 @@ static int __init rp_init(void)
rocket_driver->init_termios.c_ispeed = 9600;
rocket_driver->init_termios.c_ospeed = 9600;
#ifdef ROCKET_SOFT_FLOW
- rocket_driver->flags |= TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+ rocket_driver->flags |= TTY_DRIVER_REAL_RAW;
#endif
tty_set_operations(rocket_driver, &rocket_ops);
- retval = tty_register_driver(rocket_driver);
- if (retval < 0) {
- printk(KERN_INFO "Couldn't install tty RocketPort driver (error %d)\n", -retval);
- put_tty_driver(rocket_driver);
- return -1;
+ ret = tty_register_driver(rocket_driver);
+ if (ret < 0) {
+ printk(KERN_ERR "Couldn't install tty RocketPort driver\n");
+ goto err_tty;
}
#ifdef ROCKET_DEBUG_OPEN
@@ -2469,14 +2456,18 @@ static int __init rp_init(void)
max_board = pci_boards_found + isa_boards_found;
if (max_board == 0) {
- printk(KERN_INFO "No rocketport ports found; unloading driver.\n");
- del_timer_sync(&rocket_timer);
- tty_unregister_driver(rocket_driver);
- put_tty_driver(rocket_driver);
- return -ENXIO;
+ printk(KERN_ERR "No rocketport ports found; unloading driver\n");
+ ret = -ENXIO;
+ goto err_ttyu;
}
return 0;
+err_ttyu:
+ tty_unregister_driver(rocket_driver);
+err_tty:
+ put_tty_driver(rocket_driver);
+err:
+ return ret;
}
@@ -2491,10 +2482,14 @@ static void rp_cleanup_module(void)
if (retval)
printk(KERN_INFO "Error %d while trying to unregister "
"rocketport driver\n", -retval);
- put_tty_driver(rocket_driver);
for (i = 0; i < MAX_RP_PORTS; i++)
- kfree(rp_table[i]);
+ if (rp_table[i]) {
+ tty_unregister_device(rocket_driver, i);
+ kfree(rp_table[i]);
+ }
+
+ put_tty_driver(rocket_driver);
for (i = 0; i < NUM_BOARDS; i++) {
if (rcktpt_io_addr[i] <= 0 || is_PCI[i])
diff --git a/drivers/char/rocket_int.h b/drivers/char/rocket_int.h
index b4c53dfa7951..55b8f2d71a96 100644
--- a/drivers/char/rocket_int.h
+++ b/drivers/char/rocket_int.h
@@ -1163,13 +1163,8 @@ struct r_port {
int read_status_mask;
int cps;
-#ifdef DECLARE_WAITQUEUE
wait_queue_head_t open_wait;
- wait_queue_head_t close_wait;
-#else
- struct wait_queue *open_wait;
- struct wait_queue *close_wait;
-#endif
+ struct completion close_wait;
spinlock_t slock;
struct mutex write_mtx;
};
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index ec6b65ec69ea..0c66b802736a 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -918,6 +918,31 @@ static const struct file_operations rtc_proc_fops = {
};
#endif
+static resource_size_t rtc_size;
+
+static struct resource * __init rtc_request_region(resource_size_t size)
+{
+ struct resource *r;
+
+ if (RTC_IOMAPPED)
+ r = request_region(RTC_PORT(0), size, "rtc");
+ else
+ r = request_mem_region(RTC_PORT(0), size, "rtc");
+
+ if (r)
+ rtc_size = size;
+
+ return r;
+}
+
+static void rtc_release_region(void)
+{
+ if (RTC_IOMAPPED)
+ release_region(RTC_PORT(0), rtc_size);
+ else
+ release_mem_region(RTC_PORT(0), rtc_size);
+}
+
static int __init rtc_init(void)
{
#ifdef CONFIG_PROC_FS
@@ -968,10 +993,17 @@ found:
}
no_irq:
#else
- if (RTC_IOMAPPED)
- r = request_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc");
- else
- r = request_mem_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc");
+ r = rtc_request_region(RTC_IO_EXTENT);
+
+ /*
+ * If we've already requested a smaller range (for example, because
+ * PNPBIOS or ACPI told us how the device is configured), the request
+ * above might fail because it's too big.
+ *
+ * If so, request just the range we actually use.
+ */
+ if (!r)
+ r = rtc_request_region(RTC_IO_EXTENT_USED);
if (!r) {
#ifdef RTC_IRQ
rtc_has_irq = 0;
@@ -992,10 +1024,7 @@ no_irq:
/* Yeah right, seeing as irq 8 doesn't even hit the bus. */
rtc_has_irq = 0;
printk(KERN_ERR "rtc: IRQ %d is not free.\n", RTC_IRQ);
- if (RTC_IOMAPPED)
- release_region(RTC_PORT(0), RTC_IO_EXTENT);
- else
- release_mem_region(RTC_PORT(0), RTC_IO_EXTENT);
+ rtc_release_region();
return -EIO;
}
hpet_rtc_timer_init();
@@ -1009,7 +1038,7 @@ no_irq:
free_irq(RTC_IRQ, NULL);
rtc_has_irq = 0;
#endif
- release_region(RTC_PORT(0), RTC_IO_EXTENT);
+ rtc_release_region();
return -ENODEV;
}
@@ -1091,10 +1120,7 @@ static void __exit rtc_exit (void)
if (rtc_has_irq)
free_irq (rtc_irq, &rtc_port);
#else
- if (RTC_IOMAPPED)
- release_region(RTC_PORT(0), RTC_IO_EXTENT);
- else
- release_mem_region(RTC_PORT(0), RTC_IO_EXTENT);
+ rtc_release_region();
#ifdef RTC_IRQ
if (rtc_has_irq)
free_irq (RTC_IRQ, NULL);
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index 859858561ab6..877e53dcb996 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -7,7 +7,7 @@
*
* Copyright (C) 2005 Narayanan R S <nars@kadamba.org>
*
- * Copyright (C) 2001-2002 Alcôve <www.alcove.com>
+ * Copyright (C) 2001-2002 Alcôve <www.alcove.com>
*
* Copyright (C) 2001 Michael Ashley <m.ashley@unsw.edu.au>
*
@@ -1178,9 +1178,9 @@ static int __devinit sonypi_create_input_devices(void)
jog_dev->id.bustype = BUS_ISA;
jog_dev->id.vendor = PCI_VENDOR_ID_SONY;
- jog_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- jog_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_MIDDLE);
- jog_dev->relbit[0] = BIT(REL_WHEEL);
+ jog_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+ jog_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_MIDDLE);
+ jog_dev->relbit[0] = BIT_MASK(REL_WHEEL);
sonypi_device.input_key_dev = key_dev = input_allocate_device();
if (!key_dev) {
@@ -1193,7 +1193,7 @@ static int __devinit sonypi_create_input_devices(void)
key_dev->id.vendor = PCI_VENDOR_ID_SONY;
/* Initialize the Input Drivers: special keys */
- key_dev->evbit[0] = BIT(EV_KEY);
+ key_dev->evbit[0] = BIT_MASK(EV_KEY);
for (i = 0; sonypi_inputkeys[i].sonypiev; i++)
if (sonypi_inputkeys[i].inputev)
set_bit(sonypi_inputkeys[i].inputev, key_dev->keybit);
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index 85a23283dff5..a6e1c9ba1217 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -1467,7 +1467,7 @@ static int sx_open(struct tty_struct *tty, struct file *filp)
line = tty->index;
sx_dprintk(SX_DEBUG_OPEN, "%d: opening line %d. tty=%p ctty=%p, "
- "np=%d)\n", current->pid, line, tty,
+ "np=%d)\n", task_pid_nr(current), line, tty,
current->signal->tty, sx_nports);
if ((line < 0) || (line >= SX_NPORTS) || (line >= sx_nports))
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index fdc256b380b8..905d1f51a7bf 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -81,13 +81,9 @@
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/delay.h>
-
#include <linux/netdevice.h>
-
#include <linux/vmalloc.h>
#include <linux/init.h>
-
-#include <linux/delay.h>
#include <linux/ioctl.h>
#include <asm/system.h>
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index 39cc318011ea..de60e1ea4fb3 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -36,6 +36,7 @@
#include <linux/kexec.h>
#include <linux/irq.h>
#include <linux/hrtimer.h>
+#include <linux/oom.h>
#include <asm/ptrace.h>
#include <asm/irq_regs.h>
@@ -107,12 +108,12 @@ static void sysrq_handle_unraw(int key, struct tty_struct *tty)
struct kbd_struct *kbd = &kbd_table[fg_console];
if (kbd)
- kbd->kbdmode = VC_XLATE;
+ kbd->kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE;
}
static struct sysrq_key_op sysrq_unraw_op = {
.handler = sysrq_handle_unraw,
.help_msg = "unRaw",
- .action_msg = "Keyboard mode set to XLATE",
+ .action_msg = "Keyboard mode set to system default",
.enable_mask = SYSRQ_ENABLE_KEYBOARD,
};
#else
@@ -250,7 +251,7 @@ static void send_sig_all(int sig)
struct task_struct *p;
for_each_process(p) {
- if (p->mm && !is_init(p))
+ if (p->mm && !is_global_init(p))
/* Not swapper, init nor kernel thread */
force_sig(sig, p);
}
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index 23fa18a6654c..fd771a4d6d18 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -381,7 +381,7 @@ static struct tpm_vendor_specific tpm_tis = {
static irqreturn_t tis_int_probe(int irq, void *dev_id)
{
- struct tpm_chip *chip = (struct tpm_chip *) dev_id;
+ struct tpm_chip *chip = dev_id;
u32 interrupt;
interrupt = ioread32(chip->vendor.iobase +
@@ -401,7 +401,7 @@ static irqreturn_t tis_int_probe(int irq, void *dev_id)
static irqreturn_t tis_int_handler(int irq, void *dev_id)
{
- struct tpm_chip *chip = (struct tpm_chip *) dev_id;
+ struct tpm_chip *chip = dev_id;
u32 interrupt;
int i;
@@ -435,17 +435,12 @@ module_param(interrupts, bool, 0444);
MODULE_PARM_DESC(interrupts, "Enable interrupts");
static int tpm_tis_init(struct device *dev, resource_size_t start,
- resource_size_t len)
+ resource_size_t len, unsigned int irq)
{
u32 vendor, intfcaps, intmask;
int rc, i;
struct tpm_chip *chip;
- if (!start)
- start = TIS_MEM_BASE;
- if (!len)
- len = TIS_MEM_LEN;
-
if (!(chip = tpm_register_hardware(dev, &tpm_tis)))
return -ENODEV;
@@ -512,7 +507,9 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
iowrite32(intmask,
chip->vendor.iobase +
TPM_INT_ENABLE(chip->vendor.locality));
- if (interrupts) {
+ if (interrupts)
+ chip->vendor.irq = irq;
+ if (interrupts && !chip->vendor.irq) {
chip->vendor.irq =
ioread8(chip->vendor.iobase +
TPM_INT_VECTOR(chip->vendor.locality));
@@ -597,10 +594,17 @@ static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
const struct pnp_device_id *pnp_id)
{
resource_size_t start, len;
+ unsigned int irq = 0;
+
start = pnp_mem_start(pnp_dev, 0);
len = pnp_mem_len(pnp_dev, 0);
- return tpm_tis_init(&pnp_dev->dev, start, len);
+ if (pnp_irq_valid(pnp_dev, 0))
+ irq = pnp_irq(pnp_dev, 0);
+ else
+ interrupts = 0;
+
+ return tpm_tis_init(&pnp_dev->dev, start, len, irq);
}
static int tpm_tis_pnp_suspend(struct pnp_dev *dev, pm_message_t msg)
@@ -660,7 +664,7 @@ static int __init init_tis(void)
return rc;
if (IS_ERR(pdev=platform_device_register_simple("tpm_tis", -1, NULL, 0)))
return PTR_ERR(pdev);
- if((rc=tpm_tis_init(&pdev->dev, 0, 0)) != 0) {
+ if((rc=tpm_tis_init(&pdev->dev, TIS_MEM_BASE, TIS_MEM_LEN, 0)) != 0) {
platform_device_unregister(pdev);
driver_unregister(&tis_drv);
}
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 9c867cf6de64..f36fecd3fd26 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -103,6 +103,7 @@
#include <linux/selection.h>
#include <linux/kmod.h>
+#include <linux/nsproxy.h>
#undef TTY_DEBUG_HANGUP
@@ -942,7 +943,7 @@ EXPORT_SYMBOL_GPL(tty_ldisc_deref);
* @tty: terminal to activate ldisc on
*
* Set the TTY_LDISC flag when the line discipline can be called
- * again. Do neccessary wakeups for existing sleepers.
+ * again. Do necessary wakeups for existing sleepers.
*
* Note: nobody should set this bit except via this function. Clearing
* directly is allowed.
@@ -1503,7 +1504,7 @@ EXPORT_SYMBOL(tty_hangup);
*
* The user has asked via system call for the terminal to be hung up.
* We do this synchronously so that when the syscall returns the process
- * is complete. That guarantee is neccessary for security reasons.
+ * is complete. That guarantee is necessary for security reasons.
*/
void tty_vhangup(struct tty_struct * tty)
@@ -1690,7 +1691,7 @@ EXPORT_SYMBOL(stop_tty);
* @tty: tty to start
*
* Start a tty that has been stopped if at all possible. Perform
- * any neccessary wakeups and propagate the TIOCPKT status. If this
+ * any necessary wakeups and propagate the TIOCPKT status. If this
* is the tty was previous stopped and is being started then the
* driver start method is invoked and the line discipline woken.
*
@@ -2876,7 +2877,7 @@ static int tty_fasync(int fd, struct file * filp, int on)
* @tty: tty to fake input into
* @p: pointer to character
*
- * Fake input to a tty device. Does the neccessary locking and
+ * Fake input to a tty device. Does the necessary locking and
* input management.
*
* FIXME: does not honour flow control ??
@@ -3107,7 +3108,7 @@ static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
*/
if (tty == real_tty && current->signal->tty != real_tty)
return -ENOTTY;
- return put_user(pid_nr(real_tty->pgrp), p);
+ return put_user(pid_vnr(real_tty->pgrp), p);
}
/**
@@ -3141,7 +3142,7 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
if (pgrp_nr < 0)
return -EINVAL;
rcu_read_lock();
- pgrp = find_pid(pgrp_nr);
+ pgrp = find_vpid(pgrp_nr);
retval = -ESRCH;
if (!pgrp)
goto out_unlock;
@@ -3178,7 +3179,7 @@ static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t _
return -ENOTTY;
if (!real_tty->session)
return -ENOTTY;
- return put_user(pid_nr(real_tty->session), p);
+ return put_user(pid_vnr(real_tty->session), p);
}
/**
@@ -3528,8 +3529,8 @@ void __do_SAK(struct tty_struct *tty)
/* Kill the entire session */
do_each_pid_task(session, PIDTYPE_SID, p) {
printk(KERN_NOTICE "SAK: killed process %d"
- " (%s): process_session(p)==tty->session\n",
- p->pid, p->comm);
+ " (%s): task_session_nr(p)==tty->session\n",
+ task_pid_nr(p), p->comm);
send_sig(SIGKILL, p, 1);
} while_each_pid_task(session, PIDTYPE_SID, p);
/* Now kill any processes that happen to have the
@@ -3538,8 +3539,8 @@ void __do_SAK(struct tty_struct *tty)
do_each_thread(g, p) {
if (p->signal->tty == tty) {
printk(KERN_NOTICE "SAK: killed process %d"
- " (%s): process_session(p)==tty->session\n",
- p->pid, p->comm);
+ " (%s): task_session_nr(p)==tty->session\n",
+ task_pid_nr(p), p->comm);
send_sig(SIGKILL, p, 1);
continue;
}
@@ -3559,7 +3560,7 @@ void __do_SAK(struct tty_struct *tty)
filp->private_data == tty) {
printk(KERN_NOTICE "SAK: killed process %d"
" (%s): fd#%d opened to the tty\n",
- p->pid, p->comm, i);
+ task_pid_nr(p), p->comm, i);
force_sig(SIGKILL, p);
break;
}
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index 3ee73cf64bd2..1bdd2bf4f37d 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -206,8 +206,6 @@ speed_t tty_termios_input_baud_rate(struct ktermios *termios)
EXPORT_SYMBOL(tty_termios_input_baud_rate);
-#ifdef BOTHER
-
/**
* tty_termios_encode_baud_rate
* @termios: ktermios structure holding user requested state
@@ -225,18 +223,26 @@ EXPORT_SYMBOL(tty_termios_input_baud_rate);
*
* Locking: Caller should hold termios lock. This is already held
* when calling this function from the driver termios handler.
+ *
+ * The ifdefs deal with platforms whose owners have yet to update them
+ * and will all go away once this is done.
*/
-void tty_termios_encode_baud_rate(struct ktermios *termios, speed_t ibaud, speed_t obaud)
+void tty_termios_encode_baud_rate(struct ktermios *termios,
+ speed_t ibaud, speed_t obaud)
{
int i = 0;
int ifound = -1, ofound = -1;
int iclose = ibaud/50, oclose = obaud/50;
int ibinput = 0;
+ if (obaud == 0) /* CD dropped */
+ ibaud = 0; /* Clear ibaud to be sure */
+
termios->c_ispeed = ibaud;
termios->c_ospeed = obaud;
+#ifdef BOTHER
/* If the user asked for a precise weird speed give a precise weird
answer. If they asked for a Bfoo speed they many have problems
digesting non-exact replies so fuzz a bit */
@@ -247,32 +253,64 @@ void tty_termios_encode_baud_rate(struct ktermios *termios, speed_t ibaud, speed
iclose = 0;
if ((termios->c_cflag >> IBSHIFT) & CBAUD)
ibinput = 1; /* An input speed was specified */
-
+#endif
termios->c_cflag &= ~CBAUD;
+ /*
+ * Our goal is to find a close match to the standard baud rate
+ * returned. Walk the baud rate table and if we get a very close
+ * match then report back the speed as a POSIX Bxxxx value by
+ * preference
+ */
+
do {
- if (obaud - oclose >= baud_table[i] && obaud + oclose <= baud_table[i]) {
+ if (obaud - oclose <= baud_table[i] &&
+ obaud + oclose >= baud_table[i]) {
termios->c_cflag |= baud_bits[i];
ofound = i;
}
- if (ibaud - iclose >= baud_table[i] && ibaud + iclose <= baud_table[i]) {
- /* For the case input == output don't set IBAUD bits if the user didn't do so */
- if (ofound != i || ibinput)
+ if (ibaud - iclose <= baud_table[i] &&
+ ibaud + iclose >= baud_table[i]) {
+ /* For the case input == output don't set IBAUD bits
+ if the user didn't do so */
+ if (ofound == i && !ibinput)
+ ifound = i;
+#ifdef IBSHIFT
+ else {
+ ifound = i;
termios->c_cflag |= (baud_bits[i] << IBSHIFT);
- ifound = i;
+ }
+#endif
}
} while (++i < n_baud_table);
+
+ /*
+ * If we found no match then use BOTHER if provided or warn
+ * the user their platform maintainer needs to wake up if not.
+ */
+#ifdef BOTHER
if (ofound == -1)
termios->c_cflag |= BOTHER;
/* Set exact input bits only if the input and output differ or the
user already did */
if (ifound == -1 && (ibaud != obaud || ibinput))
termios->c_cflag |= (BOTHER << IBSHIFT);
+#else
+ if (ifound == -1 || ofound == -1) {
+ static int warned;
+ if (!warned++)
+ printk(KERN_WARNING "tty: Unable to return correct "
+ "speed data as your architecture needs updating.\n");
+ }
+#endif
}
-
EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
-#endif
+void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud)
+{
+ tty_termios_encode_baud_rate(tty->termios, ibaud, obaud);
+}
+EXPORT_SYMBOL_GPL(tty_encode_baud_rate);
/**
* tty_get_baud_rate - get tty bit rates
@@ -304,6 +342,29 @@ speed_t tty_get_baud_rate(struct tty_struct *tty)
EXPORT_SYMBOL(tty_get_baud_rate);
/**
+ * tty_termios_copy_hw - copy hardware settings
+ * @new: New termios
+ * @old: Old termios
+ *
+ * Propogate the hardware specific terminal setting bits from
+ * the old termios structure to the new one. This is used in cases
+ * where the hardware does not support reconfiguration or as a helper
+ * in some cases where only minimal reconfiguration is supported
+ */
+
+void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old)
+{
+ /* The bits a dumb device handles in software. Smart devices need
+ to always provide a set_termios method */
+ new->c_cflag &= HUPCL | CREAD | CLOCAL;
+ new->c_cflag |= old->c_cflag & ~(HUPCL | CREAD | CLOCAL);
+ new->c_ispeed = old->c_ispeed;
+ new->c_ospeed = old->c_ospeed;
+}
+
+EXPORT_SYMBOL(tty_termios_copy_hw);
+
+/**
* change_termios - update termios values
* @tty: tty to update
* @new_termios: desired new value
@@ -340,13 +401,12 @@ static void change_termios(struct tty_struct * tty, struct ktermios * new_termio
tty->erasing = 0;
}
-
+ /* This bit should be in the ldisc code */
if (canon_change && !L_ICANON(tty) && tty->read_cnt)
/* Get characters left over from canonical mode. */
wake_up_interruptible(&tty->read_wait);
/* See if packet mode change of state. */
-
if (tty->link && tty->link->packet) {
int old_flow = ((old_termios.c_iflag & IXON) &&
(old_termios.c_cc[VSTOP] == '\023') &&
@@ -366,6 +426,8 @@ static void change_termios(struct tty_struct * tty, struct ktermios * new_termio
if (tty->driver->set_termios)
(*tty->driver->set_termios)(tty, &old_termios);
+ else
+ tty_termios_copy_hw(tty->termios, &old_termios);
ld = tty_ldisc_ref(tty);
if (ld != NULL) {
@@ -382,7 +444,7 @@ static void change_termios(struct tty_struct * tty, struct ktermios * new_termio
* @arg: user data
* @opt: option information
*
- * Helper function to prepare termios data and run neccessary other
+ * Helper function to prepare termios data and run necessary other
* functions before using change_termios to do the actual changes.
*
* Locking:
@@ -440,6 +502,11 @@ static int set_termios(struct tty_struct * tty, void __user *arg, int opt)
}
change_termios(tty, &tmp_termios);
+
+ /* FIXME: Arguably if tmp_termios == tty->termios AND the
+ actual requested termios was not tmp_termios then we may
+ want to return an error as no user requested change has
+ succeeded */
return 0;
}
@@ -663,13 +730,23 @@ static int send_prio_char(struct tty_struct *tty, char ch)
return 0;
}
-int n_tty_ioctl(struct tty_struct * tty, struct file * file,
- unsigned int cmd, unsigned long arg)
+/**
+ * tty_mode_ioctl - mode related ioctls
+ * @tty: tty for the ioctl
+ * @file: file pointer for the tty
+ * @cmd: command
+ * @arg: ioctl argument
+ *
+ * Perform non line discipline specific mode control ioctls. This
+ * is designed to be called by line disciplines to ensure they provide
+ * consistent mode setting.
+ */
+
+int tty_mode_ioctl(struct tty_struct * tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
{
struct tty_struct * real_tty;
void __user *p = (void __user *)arg;
- int retval;
- struct tty_ldisc *ld;
if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
tty->driver->subtype == PTY_TYPE_MASTER)
@@ -732,6 +809,93 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO);
case TCSETA:
return set_termios(real_tty, p, TERMIOS_TERMIO);
+#ifndef TCGETS2
+ case TIOCGLCKTRMIOS:
+ if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
+ return -EFAULT;
+ return 0;
+
+ case TIOCSLCKTRMIOS:
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (user_termios_to_kernel_termios(real_tty->termios_locked, (struct termios __user *) arg))
+ return -EFAULT;
+ return 0;
+#else
+ case TIOCGLCKTRMIOS:
+ if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked))
+ return -EFAULT;
+ return 0;
+
+ case TIOCSLCKTRMIOS:
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (user_termios_to_kernel_termios_1(real_tty->termios_locked, (struct termios __user *) arg))
+ return -EFAULT;
+ return 0;
+#endif
+ case TIOCGSOFTCAR:
+ return put_user(C_CLOCAL(tty) ? 1 : 0, (int __user *)arg);
+ case TIOCSSOFTCAR:
+ if (get_user(arg, (unsigned int __user *) arg))
+ return -EFAULT;
+ mutex_lock(&tty->termios_mutex);
+ tty->termios->c_cflag =
+ ((tty->termios->c_cflag & ~CLOCAL) |
+ (arg ? CLOCAL : 0));
+ mutex_unlock(&tty->termios_mutex);
+ return 0;
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+EXPORT_SYMBOL_GPL(tty_mode_ioctl);
+
+int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
+{
+ struct tty_ldisc *ld;
+ int retval = tty_check_change(tty);
+ if (retval)
+ return retval;
+
+ ld = tty_ldisc_ref(tty);
+ switch (arg) {
+ case TCIFLUSH:
+ if (ld && ld->flush_buffer)
+ ld->flush_buffer(tty);
+ break;
+ case TCIOFLUSH:
+ if (ld && ld->flush_buffer)
+ ld->flush_buffer(tty);
+ /* fall through */
+ case TCOFLUSH:
+ if (tty->driver->flush_buffer)
+ tty->driver->flush_buffer(tty);
+ break;
+ default:
+ tty_ldisc_deref(ld);
+ return -EINVAL;
+ }
+ tty_ldisc_deref(ld);
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(tty_perform_flush);
+
+int n_tty_ioctl(struct tty_struct * tty, struct file * file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct tty_struct * real_tty;
+ int retval;
+
+ if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
+ tty->driver->subtype == PTY_TYPE_MASTER)
+ real_tty = tty->link;
+ else
+ real_tty = tty;
+
+ switch (cmd) {
case TCXONC:
retval = tty_check_change(tty);
if (retval)
@@ -762,30 +926,7 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
}
return 0;
case TCFLSH:
- retval = tty_check_change(tty);
- if (retval)
- return retval;
-
- ld = tty_ldisc_ref(tty);
- switch (arg) {
- case TCIFLUSH:
- if (ld && ld->flush_buffer)
- ld->flush_buffer(tty);
- break;
- case TCIOFLUSH:
- if (ld && ld->flush_buffer)
- ld->flush_buffer(tty);
- /* fall through */
- case TCOFLUSH:
- if (tty->driver->flush_buffer)
- tty->driver->flush_buffer(tty);
- break;
- default:
- tty_ldisc_deref(ld);
- return -EINVAL;
- }
- tty_ldisc_deref(ld);
- return 0;
+ return tty_perform_flush(tty, arg);
case TIOCOUTQ:
return put_user(tty->driver->chars_in_buffer ?
tty->driver->chars_in_buffer(tty) : 0,
@@ -795,32 +936,6 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
if (L_ICANON(tty))
retval = inq_canon(tty);
return put_user(retval, (unsigned int __user *) arg);
-#ifndef TCGETS2
- case TIOCGLCKTRMIOS:
- if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
- return -EFAULT;
- return 0;
-
- case TIOCSLCKTRMIOS:
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
- if (user_termios_to_kernel_termios(real_tty->termios_locked, (struct termios __user *) arg))
- return -EFAULT;
- return 0;
-#else
- case TIOCGLCKTRMIOS:
- if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked))
- return -EFAULT;
- return 0;
-
- case TIOCSLCKTRMIOS:
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
- if (user_termios_to_kernel_termios_1(real_tty->termios_locked, (struct termios __user *) arg))
- return -EFAULT;
- return 0;
-#endif
-
case TIOCPKT:
{
int pktmode;
@@ -839,19 +954,9 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
tty->packet = 0;
return 0;
}
- case TIOCGSOFTCAR:
- return put_user(C_CLOCAL(tty) ? 1 : 0, (int __user *)arg);
- case TIOCSSOFTCAR:
- if (get_user(arg, (unsigned int __user *) arg))
- return -EFAULT;
- mutex_lock(&tty->termios_mutex);
- tty->termios->c_cflag =
- ((tty->termios->c_cflag & ~CLOCAL) |
- (arg ? CLOCAL : 0));
- mutex_unlock(&tty->termios_mutex);
- return 0;
default:
- return -ENOIOCTLCMD;
+ /* Try the mode commands */
+ return tty_mode_ioctl(tty, file, cmd, arg);
}
}
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
new file mode 100644
index 000000000000..e34da5c97196
--- /dev/null
+++ b/drivers/char/virtio_console.c
@@ -0,0 +1,225 @@
+/*D:300
+ * The Guest console driver
+ *
+ * Writing console drivers is one of the few remaining Dark Arts in Linux.
+ * Fortunately for us, the path of virtual consoles has been well-trodden by
+ * the PowerPC folks, who wrote "hvc_console.c" to generically support any
+ * virtual console. We use that infrastructure which only requires us to write
+ * the basic put_chars and get_chars functions and call the right register
+ * functions.
+ :*/
+
+/*M:002 The console can be flooded: while the Guest is processing input the
+ * Host can send more. Buffering in the Host could alleviate this, but it is a
+ * difficult problem in general. :*/
+/* Copyright (C) 2006, 2007 Rusty Russell, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/virtio.h>
+#include <linux/virtio_console.h>
+#include "hvc_console.h"
+
+/*D:340 These represent our input and output console queues, and the virtio
+ * operations for them. */
+static struct virtqueue *in_vq, *out_vq;
+static struct virtio_device *vdev;
+
+/* This is our input buffer, and how much data is left in it. */
+static unsigned int in_len;
+static char *in, *inbuf;
+
+/* The operations for our console. */
+static struct hv_ops virtio_cons;
+
+/*D:310 The put_chars() callback is pretty straightforward.
+ *
+ * We turn the characters into a scatter-gather list, add it to the output
+ * queue and then kick the Host. Then we sit here waiting for it to finish:
+ * inefficient in theory, but in practice implementations will do it
+ * immediately (lguest's Launcher does). */
+static int put_chars(u32 vtermno, const char *buf, int count)
+{
+ struct scatterlist sg[1];
+ unsigned int len;
+
+ /* This is a convenient routine to initialize a single-elem sg list */
+ sg_init_one(sg, buf, count);
+
+ /* add_buf wants a token to identify this buffer: we hand it any
+ * non-NULL pointer, since there's only ever one buffer. */
+ if (out_vq->vq_ops->add_buf(out_vq, sg, 1, 0, (void *)1) == 0) {
+ /* Tell Host to go! */
+ out_vq->vq_ops->kick(out_vq);
+ /* Chill out until it's done with the buffer. */
+ while (!out_vq->vq_ops->get_buf(out_vq, &len))
+ cpu_relax();
+ }
+
+ /* We're expected to return the amount of data we wrote: all of it. */
+ return count;
+}
+
+/* Create a scatter-gather list representing our input buffer and put it in the
+ * queue. */
+static void add_inbuf(void)
+{
+ struct scatterlist sg[1];
+ sg_init_one(sg, inbuf, PAGE_SIZE);
+
+ /* We should always be able to add one buffer to an empty queue. */
+ if (in_vq->vq_ops->add_buf(in_vq, sg, 0, 1, inbuf) != 0)
+ BUG();
+ in_vq->vq_ops->kick(in_vq);
+}
+
+/*D:350 get_chars() is the callback from the hvc_console infrastructure when
+ * an interrupt is received.
+ *
+ * Most of the code deals with the fact that the hvc_console() infrastructure
+ * only asks us for 16 bytes at a time. We keep in_offset and in_used fields
+ * for partially-filled buffers. */
+static int get_chars(u32 vtermno, char *buf, int count)
+{
+ /* If we don't have an input queue yet, we can't get input. */
+ BUG_ON(!in_vq);
+
+ /* No buffer? Try to get one. */
+ if (!in_len) {
+ in = in_vq->vq_ops->get_buf(in_vq, &in_len);
+ if (!in)
+ return 0;
+ }
+
+ /* You want more than we have to give? Well, try wanting less! */
+ if (in_len < count)
+ count = in_len;
+
+ /* Copy across to their buffer and increment offset. */
+ memcpy(buf, in, count);
+ in += count;
+ in_len -= count;
+
+ /* Finished? Re-register buffer so Host will use it again. */
+ if (in_len == 0)
+ add_inbuf();
+
+ return count;
+}
+/*:*/
+
+/*D:320 Console drivers are initialized very early so boot messages can go out,
+ * so we do things slightly differently from the generic virtio initialization
+ * of the net and block drivers.
+ *
+ * At this stage, the console is output-only. It's too early to set up a
+ * virtqueue, so we let the drivers do some boutique early-output thing. */
+int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int))
+{
+ virtio_cons.put_chars = put_chars;
+ return hvc_instantiate(0, 0, &virtio_cons);
+}
+
+/*D:370 Once we're further in boot, we get probed like any other virtio device.
+ * At this stage we set up the output virtqueue.
+ *
+ * To set up and manage our virtual console, we call hvc_alloc(). Since we
+ * never remove the console device we never need this pointer again.
+ *
+ * Finally we put our input buffer in the input queue, ready to receive. */
+static int __devinit virtcons_probe(struct virtio_device *dev)
+{
+ int err;
+ struct hvc_struct *hvc;
+
+ vdev = dev;
+
+ /* This is the scratch page we use to receive console input */
+ inbuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!inbuf) {
+ err = -ENOMEM;
+ goto fail;
+ }
+
+ /* Find the input queue. */
+ /* FIXME: This is why we want to wean off hvc: we do nothing
+ * when input comes in. */
+ in_vq = vdev->config->find_vq(vdev, NULL);
+ if (IS_ERR(in_vq)) {
+ err = PTR_ERR(in_vq);
+ goto free;
+ }
+
+ out_vq = vdev->config->find_vq(vdev, NULL);
+ if (IS_ERR(out_vq)) {
+ err = PTR_ERR(out_vq);
+ goto free_in_vq;
+ }
+
+ /* Start using the new console output. */
+ virtio_cons.get_chars = get_chars;
+ virtio_cons.put_chars = put_chars;
+
+ /* The first argument of hvc_alloc() is the virtual console number, so
+ * we use zero. The second argument is the interrupt number; we
+ * currently leave this as zero: it would be better not to use the
+ * hvc mechanism and fix this (FIXME!).
+ *
+ * The third argument is a "struct hv_ops" containing the put_chars()
+ * and get_chars() pointers. The final argument is the output buffer
+ * size: we can do any size, so we put PAGE_SIZE here. */
+ hvc = hvc_alloc(0, 0, &virtio_cons, PAGE_SIZE);
+ if (IS_ERR(hvc)) {
+ err = PTR_ERR(hvc);
+ goto free_out_vq;
+ }
+
+ /* Register the input buffer the first time. */
+ add_inbuf();
+ return 0;
+
+free_out_vq:
+ vdev->config->del_vq(out_vq);
+free_in_vq:
+ vdev->config->del_vq(in_vq);
+free:
+ kfree(inbuf);
+fail:
+ return err;
+}
+
+static struct virtio_device_id id_table[] = {
+ { VIRTIO_ID_CONSOLE, VIRTIO_DEV_ANY_ID },
+ { 0 },
+};
+
+static struct virtio_driver virtio_console = {
+ .driver.name = KBUILD_MODNAME,
+ .driver.owner = THIS_MODULE,
+ .id_table = id_table,
+ .probe = virtcons_probe,
+};
+
+static int __init init(void)
+{
+ return register_virtio_driver(&virtio_console);
+}
+module_init(init);
+
+MODULE_DEVICE_TABLE(virtio, id_table);
+MODULE_DESCRIPTION("Virtio console driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index edb7002a3216..7a5badfb7d84 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -99,6 +99,7 @@
#include <linux/pm.h>
#include <linux/font.h>
#include <linux/bitops.h>
+#include <linux/notifier.h>
#include <asm/io.h>
#include <asm/system.h>
@@ -158,7 +159,7 @@ static void blank_screen_t(unsigned long dummy);
static void set_palette(struct vc_data *vc);
static int printable; /* Is console ready for printing? */
-static int default_utf8;
+int default_utf8 = true;
module_param(default_utf8, int, S_IRUGO | S_IWUSR);
/*
@@ -223,6 +224,35 @@ enum {
};
/*
+ * Notifier list for console events.
+ */
+static ATOMIC_NOTIFIER_HEAD(vt_notifier_list);
+
+int register_vt_notifier(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_register(&vt_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(register_vt_notifier);
+
+int unregister_vt_notifier(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_unregister(&vt_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(unregister_vt_notifier);
+
+static void notify_write(struct vc_data *vc, unsigned int unicode)
+{
+ struct vt_notifier_param param = { .vc = vc, unicode = unicode };
+ atomic_notifier_call_chain(&vt_notifier_list, VT_WRITE, &param);
+}
+
+static void notify_update(struct vc_data *vc)
+{
+ struct vt_notifier_param param = { .vc = vc };
+ atomic_notifier_call_chain(&vt_notifier_list, VT_UPDATE, &param);
+}
+
+/*
* Low-Level Functions
*/
@@ -718,6 +748,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */
return -ENXIO;
if (!vc_cons[currcons].d) {
struct vc_data *vc;
+ struct vt_notifier_param param;
/* prevent users from taking too much memory */
if (currcons >= MAX_NR_USER_CONSOLES && !capable(CAP_SYS_RESOURCE))
@@ -729,7 +760,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */
/* although the numbers above are not valid since long ago, the
point is still up-to-date and the comment still has its value
even if only as a historical artifact. --mj, July 1998 */
- vc = kzalloc(sizeof(struct vc_data), GFP_KERNEL);
+ param.vc = vc = kzalloc(sizeof(struct vc_data), GFP_KERNEL);
if (!vc)
return -ENOMEM;
vc_cons[currcons].d = vc;
@@ -746,17 +777,20 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */
}
vc->vc_kmalloced = 1;
vc_init(vc, vc->vc_rows, vc->vc_cols, 1);
+ atomic_notifier_call_chain(&vt_notifier_list, VT_ALLOCATE, &param);
}
return 0;
}
-static inline int resize_screen(struct vc_data *vc, int width, int height)
+static inline int resize_screen(struct vc_data *vc, int width, int height,
+ int user)
{
/* Resizes the resolution of the display adapater */
int err = 0;
if (vc->vc_mode != KD_GRAPHICS && vc->vc_sw->con_resize)
- err = vc->vc_sw->con_resize(vc, width, height);
+ err = vc->vc_sw->con_resize(vc, width, height, user);
+
return err;
}
@@ -772,7 +806,7 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0;
unsigned int old_cols, old_rows, old_row_size, old_screen_size;
unsigned int new_cols, new_rows, new_row_size, new_screen_size;
- unsigned int end;
+ unsigned int end, user;
unsigned short *newscreen;
WARN_CONSOLE_UNLOCKED();
@@ -780,6 +814,9 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
if (!vc)
return -ENXIO;
+ user = vc->vc_resize_user;
+ vc->vc_resize_user = 0;
+
if (cols > VC_RESIZE_MAXCOL || lines > VC_RESIZE_MAXROW)
return -EINVAL;
@@ -800,7 +837,7 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
old_row_size = vc->vc_size_row;
old_screen_size = vc->vc_screenbuf_size;
- err = resize_screen(vc, new_cols, new_rows);
+ err = resize_screen(vc, new_cols, new_rows, user);
if (err) {
kfree(newscreen);
return err;
@@ -902,6 +939,8 @@ void vc_deallocate(unsigned int currcons)
if (vc_cons_allocated(currcons)) {
struct vc_data *vc = vc_cons[currcons].d;
+ struct vt_notifier_param param = { .vc = vc };
+ atomic_notifier_call_chain(&vt_notifier_list, VT_DEALLOCATE, &param);
vc->vc_sw->con_deinit(vc);
put_pid(vc->vt_pid);
module_put(vc->vc_sw->owner);
@@ -1014,6 +1053,7 @@ static void lf(struct vc_data *vc)
vc->vc_pos += vc->vc_size_row;
}
vc->vc_need_wrap = 0;
+ notify_write(vc, '\n');
}
static void ri(struct vc_data *vc)
@@ -1034,6 +1074,7 @@ static inline void cr(struct vc_data *vc)
{
vc->vc_pos -= vc->vc_x << 1;
vc->vc_need_wrap = vc->vc_x = 0;
+ notify_write(vc, '\r');
}
static inline void bs(struct vc_data *vc)
@@ -1042,6 +1083,7 @@ static inline void bs(struct vc_data *vc)
vc->vc_pos -= 2;
vc->vc_x--;
vc->vc_need_wrap = 0;
+ notify_write(vc, '\b');
}
}
@@ -1588,6 +1630,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
break;
}
vc->vc_pos += (vc->vc_x << 1);
+ notify_write(vc, '\t');
return;
case 10: case 11: case 12:
lf(vc);
@@ -2247,6 +2290,7 @@ rescan_last_byte:
tc = conv_uni_to_pc(vc, ' '); /* A space is printed in the second column */
if (tc < 0) tc = ' ';
}
+ notify_write(vc, c);
if (inverse) {
FLUSH
@@ -2269,6 +2313,7 @@ rescan_last_byte:
release_console_sem();
out:
+ notify_update(vc);
return n;
#undef FLUSH
}
@@ -2312,6 +2357,7 @@ static void console_callback(struct work_struct *ignored)
do_blank_screen(0);
blank_timer_expired = 0;
}
+ notify_update(vc_cons[fg_console].d);
release_console_sem();
}
@@ -2413,6 +2459,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
continue;
}
scr_writew((vc->vc_attr << 8) + c, (unsigned short *)vc->vc_pos);
+ notify_write(vc, c);
cnt++;
if (myx == vc->vc_cols - 1) {
vc->vc_need_wrap = 1;
@@ -2431,6 +2478,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
}
}
set_cursor(vc);
+ notify_update(vc);
quit:
clear_bit(0, &printing);
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index 7a61a2a9aafe..e6f89e8b9258 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -23,6 +23,7 @@
#include <linux/major.h>
#include <linux/fs.h>
#include <linux/console.h>
+#include <linux/consolemap.h>
#include <linux/signal.h>
#include <linux/timex.h>
@@ -582,10 +583,27 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
case KDGKBDIACR:
{
struct kbdiacrs __user *a = up;
+ struct kbdiacr diacr;
+ int i;
if (put_user(accent_table_size, &a->kb_cnt))
return -EFAULT;
- if (copy_to_user(a->kbdiacr, accent_table, accent_table_size*sizeof(struct kbdiacr)))
+ for (i = 0; i < accent_table_size; i++) {
+ diacr.diacr = conv_uni_to_8bit(accent_table[i].diacr);
+ diacr.base = conv_uni_to_8bit(accent_table[i].base);
+ diacr.result = conv_uni_to_8bit(accent_table[i].result);
+ if (copy_to_user(a->kbdiacr + i, &diacr, sizeof(struct kbdiacr)))
+ return -EFAULT;
+ }
+ return 0;
+ }
+ case KDGKBDIACRUC:
+ {
+ struct kbdiacrsuc __user *a = up;
+
+ if (put_user(accent_table_size, &a->kb_cnt))
+ return -EFAULT;
+ if (copy_to_user(a->kbdiacruc, accent_table, accent_table_size*sizeof(struct kbdiacruc)))
return -EFAULT;
return 0;
}
@@ -593,6 +611,30 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
case KDSKBDIACR:
{
struct kbdiacrs __user *a = up;
+ struct kbdiacr diacr;
+ unsigned int ct;
+ int i;
+
+ if (!perm)
+ return -EPERM;
+ if (get_user(ct,&a->kb_cnt))
+ return -EFAULT;
+ if (ct >= MAX_DIACR)
+ return -EINVAL;
+ accent_table_size = ct;
+ for (i = 0; i < ct; i++) {
+ if (copy_from_user(&diacr, a->kbdiacr + i, sizeof(struct kbdiacr)))
+ return -EFAULT;
+ accent_table[i].diacr = conv_8bit_to_uni(diacr.diacr);
+ accent_table[i].base = conv_8bit_to_uni(diacr.base);
+ accent_table[i].result = conv_8bit_to_uni(diacr.result);
+ }
+ return 0;
+ }
+
+ case KDSKBDIACRUC:
+ {
+ struct kbdiacrsuc __user *a = up;
unsigned int ct;
if (!perm)
@@ -602,7 +644,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
if (ct >= MAX_DIACR)
return -EINVAL;
accent_table_size = ct;
- if (copy_from_user(accent_table, a->kbdiacr, ct*sizeof(struct kbdiacr)))
+ if (copy_from_user(accent_table, a->kbdiacruc, ct*sizeof(struct kbdiacruc)))
return -EFAULT;
return 0;
}
@@ -847,14 +889,24 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
case VT_RESIZE:
{
struct vt_sizes __user *vtsizes = up;
+ struct vc_data *vc;
+
ushort ll,cc;
if (!perm)
return -EPERM;
if (get_user(ll, &vtsizes->v_rows) ||
get_user(cc, &vtsizes->v_cols))
return -EFAULT;
- for (i = 0; i < MAX_NR_CONSOLES; i++)
- vc_lock_resize(vc_cons[i].d, cc, ll);
+
+ for (i = 0; i < MAX_NR_CONSOLES; i++) {
+ vc = vc_cons[i].d;
+
+ if (vc) {
+ vc->vc_resize_user = 1;
+ vc_lock_resize(vc_cons[i].d, cc, ll);
+ }
+ }
+
return 0;
}
@@ -900,6 +952,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
vc_cons[i].d->vc_scan_lines = vlin;
if (clin)
vc_cons[i].d->vc_font.height = clin;
+ vc_cons[i].d->vc_resize_user = 1;
vc_resize(vc_cons[i].d, cc, ll);
release_console_sem();
}
@@ -1072,7 +1125,7 @@ int vt_waitactive(int vt)
void reset_vc(struct vc_data *vc)
{
vc->vc_mode = KD_TEXT;
- kbd_table[vc->vc_num].kbdmode = VC_XLATE;
+ kbd_table[vc->vc_num].kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE;
vc->vt_mode.mode = VT_AUTO;
vc->vt_mode.waitv = 0;
vc->vt_mode.relsig = 0;
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
index 0e328d387af4..6883fcb79ad3 100644
--- a/drivers/connector/connector.c
+++ b/drivers/connector/connector.c
@@ -218,7 +218,7 @@ static void cn_rx_skb(struct sk_buff *__skb)
skb->len < nlh->nlmsg_len ||
nlh->nlmsg_len > CONNECTOR_MAX_MSG_SIZE) {
kfree_skb(skb);
- goto out;
+ return;
}
len = NLMSG_ALIGN(nlh->nlmsg_len);
@@ -229,9 +229,6 @@ static void cn_rx_skb(struct sk_buff *__skb)
if (err < 0)
kfree_skb(skb);
}
-
-out:
- kfree_skb(__skb);
}
/*
diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig
new file mode 100644
index 000000000000..3bed4127d4ad
--- /dev/null
+++ b/drivers/cpuidle/Kconfig
@@ -0,0 +1,20 @@
+
+config CPU_IDLE
+ bool "CPU idle PM support"
+ help
+ CPU idle is a generic framework for supporting software-controlled
+ idle processor power management. It includes modular cross-platform
+ governors that can be swapped during runtime.
+
+ If you're using a mobile platform that supports CPU idle PM (e.g.
+ an ACPI-capable notebook), you should say Y here.
+
+config CPU_IDLE_GOV_LADDER
+ bool
+ depends on CPU_IDLE
+ default y
+
+config CPU_IDLE_GOV_MENU
+ bool
+ depends on CPU_IDLE && NO_HZ
+ default y
diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile
new file mode 100644
index 000000000000..5634f88379df
--- /dev/null
+++ b/drivers/cpuidle/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for cpuidle.
+#
+
+obj-y += cpuidle.o driver.o governor.o sysfs.o governors/
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
new file mode 100644
index 000000000000..d2fabe7863a9
--- /dev/null
+++ b/drivers/cpuidle/cpuidle.c
@@ -0,0 +1,294 @@
+/*
+ * cpuidle.c - core cpuidle infrastructure
+ *
+ * (C) 2006-2007 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+ * Shaohua Li <shaohua.li@intel.com>
+ * Adam Belay <abelay@novell.com>
+ *
+ * This code is licenced under the GPL.
+ */
+
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/notifier.h>
+#include <linux/latency.h>
+#include <linux/cpu.h>
+#include <linux/cpuidle.h>
+
+#include "cpuidle.h"
+
+DEFINE_PER_CPU(struct cpuidle_device *, cpuidle_devices);
+
+DEFINE_MUTEX(cpuidle_lock);
+LIST_HEAD(cpuidle_detected_devices);
+static void (*pm_idle_old)(void);
+
+static int enabled_devices;
+
+/**
+ * cpuidle_idle_call - the main idle loop
+ *
+ * NOTE: no locks or semaphores should be used here
+ */
+static void cpuidle_idle_call(void)
+{
+ struct cpuidle_device *dev = __get_cpu_var(cpuidle_devices);
+ struct cpuidle_state *target_state;
+ int next_state;
+
+ /* check if the device is ready */
+ if (!dev || !dev->enabled) {
+ if (pm_idle_old)
+ pm_idle_old();
+ else
+ local_irq_enable();
+ return;
+ }
+
+ /* ask the governor for the next state */
+ next_state = cpuidle_curr_governor->select(dev);
+ if (need_resched())
+ return;
+ target_state = &dev->states[next_state];
+
+ /* enter the state and update stats */
+ dev->last_residency = target_state->enter(dev, target_state);
+ dev->last_state = target_state;
+ target_state->time += dev->last_residency;
+ target_state->usage++;
+
+ /* give the governor an opportunity to reflect on the outcome */
+ if (cpuidle_curr_governor->reflect)
+ cpuidle_curr_governor->reflect(dev);
+}
+
+/**
+ * cpuidle_install_idle_handler - installs the cpuidle idle loop handler
+ */
+void cpuidle_install_idle_handler(void)
+{
+ if (enabled_devices && (pm_idle != cpuidle_idle_call)) {
+ /* Make sure all changes finished before we switch to new idle */
+ smp_wmb();
+ pm_idle = cpuidle_idle_call;
+ }
+}
+
+/**
+ * cpuidle_uninstall_idle_handler - uninstalls the cpuidle idle loop handler
+ */
+void cpuidle_uninstall_idle_handler(void)
+{
+ if (enabled_devices && (pm_idle != pm_idle_old)) {
+ pm_idle = pm_idle_old;
+ cpu_idle_wait();
+ }
+}
+
+/**
+ * cpuidle_pause_and_lock - temporarily disables CPUIDLE
+ */
+void cpuidle_pause_and_lock(void)
+{
+ mutex_lock(&cpuidle_lock);
+ cpuidle_uninstall_idle_handler();
+}
+
+EXPORT_SYMBOL_GPL(cpuidle_pause_and_lock);
+
+/**
+ * cpuidle_resume_and_unlock - resumes CPUIDLE operation
+ */
+void cpuidle_resume_and_unlock(void)
+{
+ cpuidle_install_idle_handler();
+ mutex_unlock(&cpuidle_lock);
+}
+
+EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock);
+
+/**
+ * cpuidle_enable_device - enables idle PM for a CPU
+ * @dev: the CPU
+ *
+ * This function must be called between cpuidle_pause_and_lock and
+ * cpuidle_resume_and_unlock when used externally.
+ */
+int cpuidle_enable_device(struct cpuidle_device *dev)
+{
+ int ret, i;
+
+ if (dev->enabled)
+ return 0;
+ if (!cpuidle_curr_driver || !cpuidle_curr_governor)
+ return -EIO;
+ if (!dev->state_count)
+ return -EINVAL;
+
+ if ((ret = cpuidle_add_state_sysfs(dev)))
+ return ret;
+
+ if (cpuidle_curr_governor->enable &&
+ (ret = cpuidle_curr_governor->enable(dev)))
+ goto fail_sysfs;
+
+ for (i = 0; i < dev->state_count; i++) {
+ dev->states[i].usage = 0;
+ dev->states[i].time = 0;
+ }
+ dev->last_residency = 0;
+ dev->last_state = NULL;
+
+ smp_wmb();
+
+ dev->enabled = 1;
+
+ enabled_devices++;
+ return 0;
+
+fail_sysfs:
+ cpuidle_remove_state_sysfs(dev);
+
+ return ret;
+}
+
+EXPORT_SYMBOL_GPL(cpuidle_enable_device);
+
+/**
+ * cpuidle_disable_device - disables idle PM for a CPU
+ * @dev: the CPU
+ *
+ * This function must be called between cpuidle_pause_and_lock and
+ * cpuidle_resume_and_unlock when used externally.
+ */
+void cpuidle_disable_device(struct cpuidle_device *dev)
+{
+ if (!dev->enabled)
+ return;
+ if (!cpuidle_curr_driver || !cpuidle_curr_governor)
+ return;
+
+ dev->enabled = 0;
+
+ if (cpuidle_curr_governor->disable)
+ cpuidle_curr_governor->disable(dev);
+
+ cpuidle_remove_state_sysfs(dev);
+ enabled_devices--;
+}
+
+EXPORT_SYMBOL_GPL(cpuidle_disable_device);
+
+/**
+ * cpuidle_register_device - registers a CPU's idle PM feature
+ * @dev: the cpu
+ */
+int cpuidle_register_device(struct cpuidle_device *dev)
+{
+ int ret;
+ struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu);
+
+ if (!sys_dev)
+ return -EINVAL;
+ if (!try_module_get(cpuidle_curr_driver->owner))
+ return -EINVAL;
+
+ init_completion(&dev->kobj_unregister);
+
+ mutex_lock(&cpuidle_lock);
+
+ per_cpu(cpuidle_devices, dev->cpu) = dev;
+ list_add(&dev->device_list, &cpuidle_detected_devices);
+ if ((ret = cpuidle_add_sysfs(sys_dev))) {
+ mutex_unlock(&cpuidle_lock);
+ module_put(cpuidle_curr_driver->owner);
+ return ret;
+ }
+
+ cpuidle_enable_device(dev);
+ cpuidle_install_idle_handler();
+
+ mutex_unlock(&cpuidle_lock);
+
+ return 0;
+
+}
+
+EXPORT_SYMBOL_GPL(cpuidle_register_device);
+
+/**
+ * cpuidle_unregister_device - unregisters a CPU's idle PM feature
+ * @dev: the cpu
+ */
+void cpuidle_unregister_device(struct cpuidle_device *dev)
+{
+ struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu);
+
+ cpuidle_pause_and_lock();
+
+ cpuidle_disable_device(dev);
+
+ cpuidle_remove_sysfs(sys_dev);
+ list_del(&dev->device_list);
+ wait_for_completion(&dev->kobj_unregister);
+ per_cpu(cpuidle_devices, dev->cpu) = NULL;
+
+ cpuidle_resume_and_unlock();
+
+ module_put(cpuidle_curr_driver->owner);
+}
+
+EXPORT_SYMBOL_GPL(cpuidle_unregister_device);
+
+#ifdef CONFIG_SMP
+
+static void smp_callback(void *v)
+{
+ /* we already woke the CPU up, nothing more to do */
+}
+
+/*
+ * This function gets called when a part of the kernel has a new latency
+ * requirement. This means we need to get all processors out of their C-state,
+ * and then recalculate a new suitable C-state. Just do a cross-cpu IPI; that
+ * wakes them all right up.
+ */
+static int cpuidle_latency_notify(struct notifier_block *b,
+ unsigned long l, void *v)
+{
+ smp_call_function(smp_callback, NULL, 0, 1);
+ return NOTIFY_OK;
+}
+
+static struct notifier_block cpuidle_latency_notifier = {
+ .notifier_call = cpuidle_latency_notify,
+};
+
+#define latency_notifier_init(x) do { register_latency_notifier(x); } while (0)
+
+#else /* CONFIG_SMP */
+
+#define latency_notifier_init(x) do { } while (0)
+
+#endif /* CONFIG_SMP */
+
+/**
+ * cpuidle_init - core initializer
+ */
+static int __init cpuidle_init(void)
+{
+ int ret;
+
+ pm_idle_old = pm_idle;
+
+ ret = cpuidle_add_class_sysfs(&cpu_sysdev_class);
+ if (ret)
+ return ret;
+
+ latency_notifier_init(&cpuidle_latency_notifier);
+
+ return 0;
+}
+
+core_initcall(cpuidle_init);
diff --git a/drivers/cpuidle/cpuidle.h b/drivers/cpuidle/cpuidle.h
new file mode 100644
index 000000000000..9476ba33ee2c
--- /dev/null
+++ b/drivers/cpuidle/cpuidle.h
@@ -0,0 +1,33 @@
+/*
+ * cpuidle.h - The internal header file
+ */
+
+#ifndef __DRIVER_CPUIDLE_H
+#define __DRIVER_CPUIDLE_H
+
+#include <linux/sysdev.h>
+
+/* For internal use only */
+extern struct cpuidle_governor *cpuidle_curr_governor;
+extern struct cpuidle_driver *cpuidle_curr_driver;
+extern struct list_head cpuidle_governors;
+extern struct list_head cpuidle_detected_devices;
+extern struct mutex cpuidle_lock;
+extern spinlock_t cpuidle_driver_lock;
+
+/* idle loop */
+extern void cpuidle_install_idle_handler(void);
+extern void cpuidle_uninstall_idle_handler(void);
+
+/* governors */
+extern int cpuidle_switch_governor(struct cpuidle_governor *gov);
+
+/* sysfs */
+extern int cpuidle_add_class_sysfs(struct sysdev_class *cls);
+extern void cpuidle_remove_class_sysfs(struct sysdev_class *cls);
+extern int cpuidle_add_state_sysfs(struct cpuidle_device *device);
+extern void cpuidle_remove_state_sysfs(struct cpuidle_device *device);
+extern int cpuidle_add_sysfs(struct sys_device *sysdev);
+extern void cpuidle_remove_sysfs(struct sys_device *sysdev);
+
+#endif /* __DRIVER_CPUIDLE_H */
diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c
new file mode 100644
index 000000000000..2257004fe33d
--- /dev/null
+++ b/drivers/cpuidle/driver.c
@@ -0,0 +1,56 @@
+/*
+ * driver.c - driver support
+ *
+ * (C) 2006-2007 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+ * Shaohua Li <shaohua.li@intel.com>
+ * Adam Belay <abelay@novell.com>
+ *
+ * This code is licenced under the GPL.
+ */
+
+#include <linux/mutex.h>
+#include <linux/module.h>
+#include <linux/cpuidle.h>
+
+#include "cpuidle.h"
+
+struct cpuidle_driver *cpuidle_curr_driver;
+DEFINE_SPINLOCK(cpuidle_driver_lock);
+
+/**
+ * cpuidle_register_driver - registers a driver
+ * @drv: the driver
+ */
+int cpuidle_register_driver(struct cpuidle_driver *drv)
+{
+ if (!drv)
+ return -EINVAL;
+
+ spin_lock(&cpuidle_driver_lock);
+ if (cpuidle_curr_driver) {
+ spin_unlock(&cpuidle_driver_lock);
+ return -EBUSY;
+ }
+ cpuidle_curr_driver = drv;
+ spin_unlock(&cpuidle_driver_lock);
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(cpuidle_register_driver);
+
+/**
+ * cpuidle_unregister_driver - unregisters a driver
+ * @drv: the driver
+ */
+void cpuidle_unregister_driver(struct cpuidle_driver *drv)
+{
+ if (!drv)
+ return;
+
+ spin_lock(&cpuidle_driver_lock);
+ cpuidle_curr_driver = NULL;
+ spin_unlock(&cpuidle_driver_lock);
+}
+
+EXPORT_SYMBOL_GPL(cpuidle_unregister_driver);
diff --git a/drivers/cpuidle/governor.c b/drivers/cpuidle/governor.c
new file mode 100644
index 000000000000..70b59642a708
--- /dev/null
+++ b/drivers/cpuidle/governor.c
@@ -0,0 +1,138 @@
+/*
+ * governor.c - governor support
+ *
+ * (C) 2006-2007 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+ * Shaohua Li <shaohua.li@intel.com>
+ * Adam Belay <abelay@novell.com>
+ *
+ * This code is licenced under the GPL.
+ */
+
+#include <linux/mutex.h>
+#include <linux/module.h>
+#include <linux/cpuidle.h>
+
+#include "cpuidle.h"
+
+LIST_HEAD(cpuidle_governors);
+struct cpuidle_governor *cpuidle_curr_governor;
+
+/**
+ * __cpuidle_find_governor - finds a governor of the specified name
+ * @str: the name
+ *
+ * Must be called with cpuidle_lock aquired.
+ */
+static struct cpuidle_governor * __cpuidle_find_governor(const char *str)
+{
+ struct cpuidle_governor *gov;
+
+ list_for_each_entry(gov, &cpuidle_governors, governor_list)
+ if (!strnicmp(str, gov->name, CPUIDLE_NAME_LEN))
+ return gov;
+
+ return NULL;
+}
+
+/**
+ * cpuidle_switch_governor - changes the governor
+ * @gov: the new target governor
+ *
+ * NOTE: "gov" can be NULL to specify disabled
+ * Must be called with cpuidle_lock aquired.
+ */
+int cpuidle_switch_governor(struct cpuidle_governor *gov)
+{
+ struct cpuidle_device *dev;
+
+ if (gov == cpuidle_curr_governor)
+ return 0;
+
+ cpuidle_uninstall_idle_handler();
+
+ if (cpuidle_curr_governor) {
+ list_for_each_entry(dev, &cpuidle_detected_devices, device_list)
+ cpuidle_disable_device(dev);
+ module_put(cpuidle_curr_governor->owner);
+ }
+
+ cpuidle_curr_governor = gov;
+
+ if (gov) {
+ if (!try_module_get(cpuidle_curr_governor->owner))
+ return -EINVAL;
+ list_for_each_entry(dev, &cpuidle_detected_devices, device_list)
+ cpuidle_enable_device(dev);
+ cpuidle_install_idle_handler();
+ printk(KERN_INFO "cpuidle: using governor %s\n", gov->name);
+ }
+
+ return 0;
+}
+
+/**
+ * cpuidle_register_governor - registers a governor
+ * @gov: the governor
+ */
+int cpuidle_register_governor(struct cpuidle_governor *gov)
+{
+ int ret = -EEXIST;
+
+ if (!gov || !gov->select)
+ return -EINVAL;
+
+ mutex_lock(&cpuidle_lock);
+ if (__cpuidle_find_governor(gov->name) == NULL) {
+ ret = 0;
+ list_add_tail(&gov->governor_list, &cpuidle_governors);
+ if (!cpuidle_curr_governor ||
+ cpuidle_curr_governor->rating < gov->rating)
+ cpuidle_switch_governor(gov);
+ }
+ mutex_unlock(&cpuidle_lock);
+
+ return ret;
+}
+
+/**
+ * cpuidle_replace_governor - find a replacement governor
+ * @exclude_rating: the rating that will be skipped while looking for
+ * new governor.
+ */
+static struct cpuidle_governor *cpuidle_replace_governor(int exclude_rating)
+{
+ struct cpuidle_governor *gov;
+ struct cpuidle_governor *ret_gov = NULL;
+ unsigned int max_rating = 0;
+
+ list_for_each_entry(gov, &cpuidle_governors, governor_list) {
+ if (gov->rating == exclude_rating)
+ continue;
+ if (gov->rating > max_rating) {
+ max_rating = gov->rating;
+ ret_gov = gov;
+ }
+ }
+
+ return ret_gov;
+}
+
+/**
+ * cpuidle_unregister_governor - unregisters a governor
+ * @gov: the governor
+ */
+void cpuidle_unregister_governor(struct cpuidle_governor *gov)
+{
+ if (!gov)
+ return;
+
+ mutex_lock(&cpuidle_lock);
+ if (gov == cpuidle_curr_governor) {
+ struct cpuidle_governor *new_gov;
+ new_gov = cpuidle_replace_governor(gov->rating);
+ cpuidle_switch_governor(new_gov);
+ }
+ list_del(&gov->governor_list);
+ mutex_unlock(&cpuidle_lock);
+}
+
diff --git a/drivers/cpuidle/governors/Makefile b/drivers/cpuidle/governors/Makefile
new file mode 100644
index 000000000000..1b512722689f
--- /dev/null
+++ b/drivers/cpuidle/governors/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for cpuidle governors.
+#
+
+obj-$(CONFIG_CPU_IDLE_GOV_LADDER) += ladder.o
+obj-$(CONFIG_CPU_IDLE_GOV_MENU) += menu.o
diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c
new file mode 100644
index 000000000000..eb666ecae7c9
--- /dev/null
+++ b/drivers/cpuidle/governors/ladder.c
@@ -0,0 +1,166 @@
+/*
+ * ladder.c - the residency ladder algorithm
+ *
+ * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
+ * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
+ * Copyright (C) 2004, 2005 Dominik Brodowski <linux@brodo.de>
+ *
+ * (C) 2006-2007 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+ * Shaohua Li <shaohua.li@intel.com>
+ * Adam Belay <abelay@novell.com>
+ *
+ * This code is licenced under the GPL.
+ */
+
+#include <linux/kernel.h>
+#include <linux/cpuidle.h>
+#include <linux/latency.h>
+#include <linux/moduleparam.h>
+#include <linux/jiffies.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#define PROMOTION_COUNT 4
+#define DEMOTION_COUNT 1
+
+struct ladder_device_state {
+ struct {
+ u32 promotion_count;
+ u32 demotion_count;
+ u32 promotion_time;
+ u32 demotion_time;
+ } threshold;
+ struct {
+ int promotion_count;
+ int demotion_count;
+ } stats;
+};
+
+struct ladder_device {
+ struct ladder_device_state states[CPUIDLE_STATE_MAX];
+ int last_state_idx;
+};
+
+static DEFINE_PER_CPU(struct ladder_device, ladder_devices);
+
+/**
+ * ladder_do_selection - prepares private data for a state change
+ * @ldev: the ladder device
+ * @old_idx: the current state index
+ * @new_idx: the new target state index
+ */
+static inline void ladder_do_selection(struct ladder_device *ldev,
+ int old_idx, int new_idx)
+{
+ ldev->states[old_idx].stats.promotion_count = 0;
+ ldev->states[old_idx].stats.demotion_count = 0;
+ ldev->last_state_idx = new_idx;
+}
+
+/**
+ * ladder_select_state - selects the next state to enter
+ * @dev: the CPU
+ */
+static int ladder_select_state(struct cpuidle_device *dev)
+{
+ struct ladder_device *ldev = &__get_cpu_var(ladder_devices);
+ struct ladder_device_state *last_state;
+ int last_residency, last_idx = ldev->last_state_idx;
+
+ if (unlikely(!ldev))
+ return 0;
+
+ last_state = &ldev->states[last_idx];
+
+ if (dev->states[last_idx].flags & CPUIDLE_FLAG_TIME_VALID)
+ last_residency = cpuidle_get_last_residency(dev) - dev->states[last_idx].exit_latency;
+ else
+ last_residency = last_state->threshold.promotion_time + 1;
+
+ /* consider promotion */
+ if (last_idx < dev->state_count - 1 &&
+ last_residency > last_state->threshold.promotion_time &&
+ dev->states[last_idx + 1].exit_latency <= system_latency_constraint()) {
+ last_state->stats.promotion_count++;
+ last_state->stats.demotion_count = 0;
+ if (last_state->stats.promotion_count >= last_state->threshold.promotion_count) {
+ ladder_do_selection(ldev, last_idx, last_idx + 1);
+ return last_idx + 1;
+ }
+ }
+
+ /* consider demotion */
+ if (last_idx > 0 &&
+ last_residency < last_state->threshold.demotion_time) {
+ last_state->stats.demotion_count++;
+ last_state->stats.promotion_count = 0;
+ if (last_state->stats.demotion_count >= last_state->threshold.demotion_count) {
+ ladder_do_selection(ldev, last_idx, last_idx - 1);
+ return last_idx - 1;
+ }
+ }
+
+ /* otherwise remain at the current state */
+ return last_idx;
+}
+
+/**
+ * ladder_enable_device - setup for the governor
+ * @dev: the CPU
+ */
+static int ladder_enable_device(struct cpuidle_device *dev)
+{
+ int i;
+ struct ladder_device *ldev = &per_cpu(ladder_devices, dev->cpu);
+ struct ladder_device_state *lstate;
+ struct cpuidle_state *state;
+
+ ldev->last_state_idx = 0;
+
+ for (i = 0; i < dev->state_count; i++) {
+ state = &dev->states[i];
+ lstate = &ldev->states[i];
+
+ lstate->stats.promotion_count = 0;
+ lstate->stats.demotion_count = 0;
+
+ lstate->threshold.promotion_count = PROMOTION_COUNT;
+ lstate->threshold.demotion_count = DEMOTION_COUNT;
+
+ if (i < dev->state_count - 1)
+ lstate->threshold.promotion_time = state->exit_latency;
+ if (i > 0)
+ lstate->threshold.demotion_time = state->exit_latency;
+ }
+
+ return 0;
+}
+
+static struct cpuidle_governor ladder_governor = {
+ .name = "ladder",
+ .rating = 10,
+ .enable = ladder_enable_device,
+ .select = ladder_select_state,
+ .owner = THIS_MODULE,
+};
+
+/**
+ * init_ladder - initializes the governor
+ */
+static int __init init_ladder(void)
+{
+ return cpuidle_register_governor(&ladder_governor);
+}
+
+/**
+ * exit_ladder - exits the governor
+ */
+static void __exit exit_ladder(void)
+{
+ cpuidle_unregister_governor(&ladder_governor);
+}
+
+MODULE_LICENSE("GPL");
+module_init(init_ladder);
+module_exit(exit_ladder);
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
new file mode 100644
index 000000000000..299d45c3bdd2
--- /dev/null
+++ b/drivers/cpuidle/governors/menu.c
@@ -0,0 +1,137 @@
+/*
+ * menu.c - the menu idle governor
+ *
+ * Copyright (C) 2006-2007 Adam Belay <abelay@novell.com>
+ *
+ * This code is licenced under the GPL.
+ */
+
+#include <linux/kernel.h>
+#include <linux/cpuidle.h>
+#include <linux/latency.h>
+#include <linux/time.h>
+#include <linux/ktime.h>
+#include <linux/hrtimer.h>
+#include <linux/tick.h>
+
+#define BREAK_FUZZ 4 /* 4 us */
+
+struct menu_device {
+ int last_state_idx;
+
+ unsigned int expected_us;
+ unsigned int predicted_us;
+ unsigned int last_measured_us;
+ unsigned int elapsed_us;
+};
+
+static DEFINE_PER_CPU(struct menu_device, menu_devices);
+
+/**
+ * menu_select - selects the next idle state to enter
+ * @dev: the CPU
+ */
+static int menu_select(struct cpuidle_device *dev)
+{
+ struct menu_device *data = &__get_cpu_var(menu_devices);
+ int i;
+
+ /* determine the expected residency time */
+ data->expected_us =
+ (u32) ktime_to_ns(tick_nohz_get_sleep_length()) / 1000;
+
+ /* find the deepest idle state that satisfies our constraints */
+ for (i = 1; i < dev->state_count; i++) {
+ struct cpuidle_state *s = &dev->states[i];
+
+ if (s->target_residency > data->expected_us)
+ break;
+ if (s->target_residency > data->predicted_us)
+ break;
+ if (s->exit_latency > system_latency_constraint())
+ break;
+ }
+
+ data->last_state_idx = i - 1;
+ return i - 1;
+}
+
+/**
+ * menu_reflect - attempts to guess what happened after entry
+ * @dev: the CPU
+ *
+ * NOTE: it's important to be fast here because this operation will add to
+ * the overall exit latency.
+ */
+static void menu_reflect(struct cpuidle_device *dev)
+{
+ struct menu_device *data = &__get_cpu_var(menu_devices);
+ int last_idx = data->last_state_idx;
+ unsigned int measured_us =
+ cpuidle_get_last_residency(dev) + data->elapsed_us;
+ struct cpuidle_state *target = &dev->states[last_idx];
+
+ /*
+ * Ugh, this idle state doesn't support residency measurements, so we
+ * are basically lost in the dark. As a compromise, assume we slept
+ * for one full standard timer tick. However, be aware that this
+ * could potentially result in a suboptimal state transition.
+ */
+ if (!(target->flags & CPUIDLE_FLAG_TIME_VALID))
+ measured_us = USEC_PER_SEC / HZ;
+
+ /* Predict time remaining until next break event */
+ if (measured_us + BREAK_FUZZ < data->expected_us - target->exit_latency) {
+ data->predicted_us = max(measured_us, data->last_measured_us);
+ data->last_measured_us = measured_us;
+ data->elapsed_us = 0;
+ } else {
+ if (data->elapsed_us < data->elapsed_us + measured_us)
+ data->elapsed_us = measured_us;
+ else
+ data->elapsed_us = -1;
+ data->predicted_us = max(measured_us, data->last_measured_us);
+ }
+}
+
+/**
+ * menu_enable_device - scans a CPU's states and does setup
+ * @dev: the CPU
+ */
+static int menu_enable_device(struct cpuidle_device *dev)
+{
+ struct menu_device *data = &per_cpu(menu_devices, dev->cpu);
+
+ memset(data, 0, sizeof(struct menu_device));
+
+ return 0;
+}
+
+static struct cpuidle_governor menu_governor = {
+ .name = "menu",
+ .rating = 20,
+ .enable = menu_enable_device,
+ .select = menu_select,
+ .reflect = menu_reflect,
+ .owner = THIS_MODULE,
+};
+
+/**
+ * init_menu - initializes the governor
+ */
+static int __init init_menu(void)
+{
+ return cpuidle_register_governor(&menu_governor);
+}
+
+/**
+ * exit_menu - exits the governor
+ */
+static void __exit exit_menu(void)
+{
+ cpuidle_unregister_governor(&menu_governor);
+}
+
+MODULE_LICENSE("GPL");
+module_init(init_menu);
+module_exit(exit_menu);
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c
new file mode 100644
index 000000000000..0f3515e77d4b
--- /dev/null
+++ b/drivers/cpuidle/sysfs.c
@@ -0,0 +1,361 @@
+/*
+ * sysfs.c - sysfs support
+ *
+ * (C) 2006-2007 Shaohua Li <shaohua.li@intel.com>
+ *
+ * This code is licenced under the GPL.
+ */
+
+#include <linux/kernel.h>
+#include <linux/cpuidle.h>
+#include <linux/sysfs.h>
+#include <linux/cpu.h>
+
+#include "cpuidle.h"
+
+static unsigned int sysfs_switch;
+static int __init cpuidle_sysfs_setup(char *unused)
+{
+ sysfs_switch = 1;
+ return 1;
+}
+__setup("cpuidle_sysfs_switch", cpuidle_sysfs_setup);
+
+static ssize_t show_available_governors(struct sys_device *dev, char *buf)
+{
+ ssize_t i = 0;
+ struct cpuidle_governor *tmp;
+
+ mutex_lock(&cpuidle_lock);
+ list_for_each_entry(tmp, &cpuidle_governors, governor_list) {
+ if (i >= (ssize_t) ((PAGE_SIZE/sizeof(char)) - CPUIDLE_NAME_LEN - 2))
+ goto out;
+ i += scnprintf(&buf[i], CPUIDLE_NAME_LEN, "%s ", tmp->name);
+ }
+
+out:
+ i+= sprintf(&buf[i], "\n");
+ mutex_unlock(&cpuidle_lock);
+ return i;
+}
+
+static ssize_t show_current_driver(struct sys_device *dev, char *buf)
+{
+ ssize_t ret;
+
+ spin_lock(&cpuidle_driver_lock);
+ if (cpuidle_curr_driver)
+ ret = sprintf(buf, "%s\n", cpuidle_curr_driver->name);
+ else
+ ret = sprintf(buf, "none\n");
+ spin_unlock(&cpuidle_driver_lock);
+
+ return ret;
+}
+
+static ssize_t show_current_governor(struct sys_device *dev, char *buf)
+{
+ ssize_t ret;
+
+ mutex_lock(&cpuidle_lock);
+ if (cpuidle_curr_governor)
+ ret = sprintf(buf, "%s\n", cpuidle_curr_governor->name);
+ else
+ ret = sprintf(buf, "none\n");
+ mutex_unlock(&cpuidle_lock);
+
+ return ret;
+}
+
+static ssize_t store_current_governor(struct sys_device *dev,
+ const char *buf, size_t count)
+{
+ char gov_name[CPUIDLE_NAME_LEN];
+ int ret = -EINVAL;
+ size_t len = count;
+ struct cpuidle_governor *gov;
+
+ if (!len || len >= sizeof(gov_name))
+ return -EINVAL;
+
+ memcpy(gov_name, buf, len);
+ gov_name[len] = '\0';
+ if (gov_name[len - 1] == '\n')
+ gov_name[--len] = '\0';
+
+ mutex_lock(&cpuidle_lock);
+
+ list_for_each_entry(gov, &cpuidle_governors, governor_list) {
+ if (strlen(gov->name) == len && !strcmp(gov->name, gov_name)) {
+ ret = cpuidle_switch_governor(gov);
+ break;
+ }
+ }
+
+ mutex_unlock(&cpuidle_lock);
+
+ if (ret)
+ return ret;
+ else
+ return count;
+}
+
+static SYSDEV_ATTR(current_driver, 0444, show_current_driver, NULL);
+static SYSDEV_ATTR(current_governor_ro, 0444, show_current_governor, NULL);
+
+static struct attribute *cpuclass_default_attrs[] = {
+ &attr_current_driver.attr,
+ &attr_current_governor_ro.attr,
+ NULL
+};
+
+static SYSDEV_ATTR(available_governors, 0444, show_available_governors, NULL);
+static SYSDEV_ATTR(current_governor, 0644, show_current_governor,
+ store_current_governor);
+
+static struct attribute *cpuclass_switch_attrs[] = {
+ &attr_available_governors.attr,
+ &attr_current_driver.attr,
+ &attr_current_governor.attr,
+ NULL
+};
+
+static struct attribute_group cpuclass_attr_group = {
+ .attrs = cpuclass_default_attrs,
+ .name = "cpuidle",
+};
+
+/**
+ * cpuidle_add_class_sysfs - add CPU global sysfs attributes
+ */
+int cpuidle_add_class_sysfs(struct sysdev_class *cls)
+{
+ if (sysfs_switch)
+ cpuclass_attr_group.attrs = cpuclass_switch_attrs;
+
+ return sysfs_create_group(&cls->kset.kobj, &cpuclass_attr_group);
+}
+
+/**
+ * cpuidle_remove_class_sysfs - remove CPU global sysfs attributes
+ */
+void cpuidle_remove_class_sysfs(struct sysdev_class *cls)
+{
+ sysfs_remove_group(&cls->kset.kobj, &cpuclass_attr_group);
+}
+
+struct cpuidle_attr {
+ struct attribute attr;
+ ssize_t (*show)(struct cpuidle_device *, char *);
+ ssize_t (*store)(struct cpuidle_device *, const char *, size_t count);
+};
+
+#define define_one_ro(_name, show) \
+ static struct cpuidle_attr attr_##_name = __ATTR(_name, 0444, show, NULL)
+#define define_one_rw(_name, show, store) \
+ static struct cpuidle_attr attr_##_name = __ATTR(_name, 0644, show, store)
+
+#define kobj_to_cpuidledev(k) container_of(k, struct cpuidle_device, kobj)
+#define attr_to_cpuidleattr(a) container_of(a, struct cpuidle_attr, attr)
+static ssize_t cpuidle_show(struct kobject * kobj, struct attribute * attr ,char * buf)
+{
+ int ret = -EIO;
+ struct cpuidle_device *dev = kobj_to_cpuidledev(kobj);
+ struct cpuidle_attr * cattr = attr_to_cpuidleattr(attr);
+
+ if (cattr->show) {
+ mutex_lock(&cpuidle_lock);
+ ret = cattr->show(dev, buf);
+ mutex_unlock(&cpuidle_lock);
+ }
+ return ret;
+}
+
+static ssize_t cpuidle_store(struct kobject * kobj, struct attribute * attr,
+ const char * buf, size_t count)
+{
+ int ret = -EIO;
+ struct cpuidle_device *dev = kobj_to_cpuidledev(kobj);
+ struct cpuidle_attr * cattr = attr_to_cpuidleattr(attr);
+
+ if (cattr->store) {
+ mutex_lock(&cpuidle_lock);
+ ret = cattr->store(dev, buf, count);
+ mutex_unlock(&cpuidle_lock);
+ }
+ return ret;
+}
+
+static struct sysfs_ops cpuidle_sysfs_ops = {
+ .show = cpuidle_show,
+ .store = cpuidle_store,
+};
+
+static void cpuidle_sysfs_release(struct kobject *kobj)
+{
+ struct cpuidle_device *dev = kobj_to_cpuidledev(kobj);
+
+ complete(&dev->kobj_unregister);
+}
+
+static struct kobj_type ktype_cpuidle = {
+ .sysfs_ops = &cpuidle_sysfs_ops,
+ .release = cpuidle_sysfs_release,
+};
+
+struct cpuidle_state_attr {
+ struct attribute attr;
+ ssize_t (*show)(struct cpuidle_state *, char *);
+ ssize_t (*store)(struct cpuidle_state *, const char *, size_t);
+};
+
+#define define_one_state_ro(_name, show) \
+static struct cpuidle_state_attr attr_##_name = __ATTR(_name, 0444, show, NULL)
+
+#define define_show_state_function(_name) \
+static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \
+{ \
+ return sprintf(buf, "%u\n", state->_name);\
+}
+
+static ssize_t show_state_name(struct cpuidle_state *state, char *buf)
+{
+ return sprintf(buf, "%s\n", state->name);
+}
+
+define_show_state_function(exit_latency)
+define_show_state_function(power_usage)
+define_show_state_function(usage)
+define_show_state_function(time)
+define_one_state_ro(name, show_state_name);
+define_one_state_ro(latency, show_state_exit_latency);
+define_one_state_ro(power, show_state_power_usage);
+define_one_state_ro(usage, show_state_usage);
+define_one_state_ro(time, show_state_time);
+
+static struct attribute *cpuidle_state_default_attrs[] = {
+ &attr_name.attr,
+ &attr_latency.attr,
+ &attr_power.attr,
+ &attr_usage.attr,
+ &attr_time.attr,
+ NULL
+};
+
+#define kobj_to_state_obj(k) container_of(k, struct cpuidle_state_kobj, kobj)
+#define kobj_to_state(k) (kobj_to_state_obj(k)->state)
+#define attr_to_stateattr(a) container_of(a, struct cpuidle_state_attr, attr)
+static ssize_t cpuidle_state_show(struct kobject * kobj,
+ struct attribute * attr ,char * buf)
+{
+ int ret = -EIO;
+ struct cpuidle_state *state = kobj_to_state(kobj);
+ struct cpuidle_state_attr * cattr = attr_to_stateattr(attr);
+
+ if (cattr->show)
+ ret = cattr->show(state, buf);
+
+ return ret;
+}
+
+static struct sysfs_ops cpuidle_state_sysfs_ops = {
+ .show = cpuidle_state_show,
+};
+
+static void cpuidle_state_sysfs_release(struct kobject *kobj)
+{
+ struct cpuidle_state_kobj *state_obj = kobj_to_state_obj(kobj);
+
+ complete(&state_obj->kobj_unregister);
+}
+
+static struct kobj_type ktype_state_cpuidle = {
+ .sysfs_ops = &cpuidle_state_sysfs_ops,
+ .default_attrs = cpuidle_state_default_attrs,
+ .release = cpuidle_state_sysfs_release,
+};
+
+static void inline cpuidle_free_state_kobj(struct cpuidle_device *device, int i)
+{
+ kobject_unregister(&device->kobjs[i]->kobj);
+ wait_for_completion(&device->kobjs[i]->kobj_unregister);
+ kfree(device->kobjs[i]);
+ device->kobjs[i] = NULL;
+}
+
+/**
+ * cpuidle_add_driver_sysfs - adds driver-specific sysfs attributes
+ * @device: the target device
+ */
+int cpuidle_add_state_sysfs(struct cpuidle_device *device)
+{
+ int i, ret = -ENOMEM;
+ struct cpuidle_state_kobj *kobj;
+
+ /* state statistics */
+ for (i = 0; i < device->state_count; i++) {
+ kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL);
+ if (!kobj)
+ goto error_state;
+ kobj->state = &device->states[i];
+ init_completion(&kobj->kobj_unregister);
+
+ kobj->kobj.parent = &device->kobj;
+ kobj->kobj.ktype = &ktype_state_cpuidle;
+ kobject_set_name(&kobj->kobj, "state%d", i);
+ ret = kobject_register(&kobj->kobj);
+ if (ret) {
+ kfree(kobj);
+ goto error_state;
+ }
+ device->kobjs[i] = kobj;
+ }
+
+ return 0;
+
+error_state:
+ for (i = i - 1; i >= 0; i--)
+ cpuidle_free_state_kobj(device, i);
+ return ret;
+}
+
+/**
+ * cpuidle_remove_driver_sysfs - removes driver-specific sysfs attributes
+ * @device: the target device
+ */
+void cpuidle_remove_state_sysfs(struct cpuidle_device *device)
+{
+ int i;
+
+ for (i = 0; i < device->state_count; i++)
+ cpuidle_free_state_kobj(device, i);
+}
+
+/**
+ * cpuidle_add_sysfs - creates a sysfs instance for the target device
+ * @sysdev: the target device
+ */
+int cpuidle_add_sysfs(struct sys_device *sysdev)
+{
+ int cpu = sysdev->id;
+ struct cpuidle_device *dev;
+
+ dev = per_cpu(cpuidle_devices, cpu);
+ dev->kobj.parent = &sysdev->kobj;
+ dev->kobj.ktype = &ktype_cpuidle;
+ kobject_set_name(&dev->kobj, "%s", "cpuidle");
+ return kobject_register(&dev->kobj);
+}
+
+/**
+ * cpuidle_remove_sysfs - deletes a sysfs instance on the target device
+ * @sysdev: the target device
+ */
+void cpuidle_remove_sysfs(struct sys_device *sysdev)
+{
+ int cpu = sysdev->id;
+ struct cpuidle_device *dev;
+
+ dev = per_cpu(cpuidle_devices, cpu);
+ kobject_unregister(&dev->kobj);
+}
diff --git a/drivers/crypto/geode-aes.c b/drivers/crypto/geode-aes.c
index f9a34abbf4fa..711e246e1ef0 100644
--- a/drivers/crypto/geode-aes.c
+++ b/drivers/crypto/geode-aes.c
@@ -110,8 +110,7 @@ geode_aes_crypt(struct geode_aes_op *op)
* we don't need to worry
*/
- if (op->src == op->dst)
- flags |= (AES_CTRL_DCA | AES_CTRL_SCA);
+ flags |= (AES_CTRL_DCA | AES_CTRL_SCA);
if (op->dir == AES_DIR_ENCRYPT)
flags |= AES_CTRL_ENCRYPT;
diff --git a/drivers/crypto/padlock-sha.c b/drivers/crypto/padlock-sha.c
index 4e8de162fc12..c666b4e0933e 100644
--- a/drivers/crypto/padlock-sha.c
+++ b/drivers/crypto/padlock-sha.c
@@ -55,7 +55,7 @@ static void padlock_sha_bypass(struct crypto_tfm *tfm)
if (ctx(tfm)->data && ctx(tfm)->used) {
struct scatterlist sg;
- sg_set_buf(&sg, ctx(tfm)->data, ctx(tfm)->used);
+ sg_init_one(&sg, ctx(tfm)->data, ctx(tfm)->used);
crypto_hash_update(&ctx(tfm)->fallback, &sg, sg.length);
}
@@ -79,7 +79,7 @@ static void padlock_sha_update(struct crypto_tfm *tfm,
if (unlikely(ctx(tfm)->bypass)) {
struct scatterlist sg;
- sg_set_buf(&sg, (uint8_t *)data, length);
+ sg_init_one(&sg, (uint8_t *)data, length);
crypto_hash_update(&ctx(tfm)->fallback, &sg, length);
return;
}
diff --git a/drivers/dca/Kconfig b/drivers/dca/Kconfig
new file mode 100644
index 000000000000..94f0364a0efb
--- /dev/null
+++ b/drivers/dca/Kconfig
@@ -0,0 +1,7 @@
+#
+# DCA server configuration
+#
+
+config DCA
+ tristate
+
diff --git a/drivers/dca/Makefile b/drivers/dca/Makefile
new file mode 100644
index 000000000000..b2db56bb9dde
--- /dev/null
+++ b/drivers/dca/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_DCA) += dca.o
+dca-objs := dca-core.o dca-sysfs.o
diff --git a/drivers/dca/dca-core.c b/drivers/dca/dca-core.c
new file mode 100644
index 000000000000..bf5b92f86df7
--- /dev/null
+++ b/drivers/dca/dca-core.c
@@ -0,0 +1,200 @@
+/*
+ * Copyright(c) 2007 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ */
+
+/*
+ * This driver supports an interface for DCA clients and providers to meet.
+ */
+
+#include <linux/kernel.h>
+#include <linux/notifier.h>
+#include <linux/device.h>
+#include <linux/dca.h>
+
+MODULE_LICENSE("GPL");
+
+/* For now we're assuming a single, global, DCA provider for the system. */
+
+static DEFINE_SPINLOCK(dca_lock);
+
+static struct dca_provider *global_dca = NULL;
+
+/**
+ * dca_add_requester - add a dca client to the list
+ * @dev - the device that wants dca service
+ */
+int dca_add_requester(struct device *dev)
+{
+ int err, slot;
+
+ if (!global_dca)
+ return -ENODEV;
+
+ spin_lock(&dca_lock);
+ slot = global_dca->ops->add_requester(global_dca, dev);
+ spin_unlock(&dca_lock);
+ if (slot < 0)
+ return slot;
+
+ err = dca_sysfs_add_req(global_dca, dev, slot);
+ if (err) {
+ spin_lock(&dca_lock);
+ global_dca->ops->remove_requester(global_dca, dev);
+ spin_unlock(&dca_lock);
+ return err;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(dca_add_requester);
+
+/**
+ * dca_remove_requester - remove a dca client from the list
+ * @dev - the device that wants dca service
+ */
+int dca_remove_requester(struct device *dev)
+{
+ int slot;
+ if (!global_dca)
+ return -ENODEV;
+
+ spin_lock(&dca_lock);
+ slot = global_dca->ops->remove_requester(global_dca, dev);
+ spin_unlock(&dca_lock);
+ if (slot < 0)
+ return slot;
+
+ dca_sysfs_remove_req(global_dca, slot);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(dca_remove_requester);
+
+/**
+ * dca_get_tag - return the dca tag for the given cpu
+ * @cpu - the cpuid as returned by get_cpu()
+ */
+u8 dca_get_tag(int cpu)
+{
+ if (!global_dca)
+ return -ENODEV;
+ return global_dca->ops->get_tag(global_dca, cpu);
+}
+EXPORT_SYMBOL_GPL(dca_get_tag);
+
+/**
+ * alloc_dca_provider - get data struct for describing a dca provider
+ * @ops - pointer to struct of dca operation function pointers
+ * @priv_size - size of extra mem to be added for provider's needs
+ */
+struct dca_provider *alloc_dca_provider(struct dca_ops *ops, int priv_size)
+{
+ struct dca_provider *dca;
+ int alloc_size;
+
+ alloc_size = (sizeof(*dca) + priv_size);
+ dca = kzalloc(alloc_size, GFP_KERNEL);
+ if (!dca)
+ return NULL;
+ dca->ops = ops;
+
+ return dca;
+}
+EXPORT_SYMBOL_GPL(alloc_dca_provider);
+
+/**
+ * free_dca_provider - release the dca provider data struct
+ * @ops - pointer to struct of dca operation function pointers
+ * @priv_size - size of extra mem to be added for provider's needs
+ */
+void free_dca_provider(struct dca_provider *dca)
+{
+ kfree(dca);
+}
+EXPORT_SYMBOL_GPL(free_dca_provider);
+
+static BLOCKING_NOTIFIER_HEAD(dca_provider_chain);
+
+/**
+ * register_dca_provider - register a dca provider
+ * @dca - struct created by alloc_dca_provider()
+ * @dev - device providing dca services
+ */
+int register_dca_provider(struct dca_provider *dca, struct device *dev)
+{
+ int err;
+
+ if (global_dca)
+ return -EEXIST;
+ err = dca_sysfs_add_provider(dca, dev);
+ if (err)
+ return err;
+ global_dca = dca;
+ blocking_notifier_call_chain(&dca_provider_chain,
+ DCA_PROVIDER_ADD, NULL);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(register_dca_provider);
+
+/**
+ * unregister_dca_provider - remove a dca provider
+ * @dca - struct created by alloc_dca_provider()
+ */
+void unregister_dca_provider(struct dca_provider *dca)
+{
+ if (!global_dca)
+ return;
+ blocking_notifier_call_chain(&dca_provider_chain,
+ DCA_PROVIDER_REMOVE, NULL);
+ global_dca = NULL;
+ dca_sysfs_remove_provider(dca);
+}
+EXPORT_SYMBOL_GPL(unregister_dca_provider);
+
+/**
+ * dca_register_notify - register a client's notifier callback
+ */
+void dca_register_notify(struct notifier_block *nb)
+{
+ blocking_notifier_chain_register(&dca_provider_chain, nb);
+}
+EXPORT_SYMBOL_GPL(dca_register_notify);
+
+/**
+ * dca_unregister_notify - remove a client's notifier callback
+ */
+void dca_unregister_notify(struct notifier_block *nb)
+{
+ blocking_notifier_chain_unregister(&dca_provider_chain, nb);
+}
+EXPORT_SYMBOL_GPL(dca_unregister_notify);
+
+static int __init dca_init(void)
+{
+ return dca_sysfs_init();
+}
+
+static void __exit dca_exit(void)
+{
+ dca_sysfs_exit();
+}
+
+module_init(dca_init);
+module_exit(dca_exit);
+
diff --git a/drivers/dca/dca-sysfs.c b/drivers/dca/dca-sysfs.c
new file mode 100644
index 000000000000..24a263b6844c
--- /dev/null
+++ b/drivers/dca/dca-sysfs.c
@@ -0,0 +1,88 @@
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/device.h>
+#include <linux/idr.h>
+#include <linux/kdev_t.h>
+#include <linux/err.h>
+#include <linux/dca.h>
+
+static struct class *dca_class;
+static struct idr dca_idr;
+static spinlock_t dca_idr_lock;
+
+int dca_sysfs_add_req(struct dca_provider *dca, struct device *dev, int slot)
+{
+ struct class_device *cd;
+
+ cd = class_device_create(dca_class, dca->cd, MKDEV(0, slot + 1),
+ dev, "requester%d", slot);
+ if (IS_ERR(cd))
+ return PTR_ERR(cd);
+ return 0;
+}
+
+void dca_sysfs_remove_req(struct dca_provider *dca, int slot)
+{
+ class_device_destroy(dca_class, MKDEV(0, slot + 1));
+}
+
+int dca_sysfs_add_provider(struct dca_provider *dca, struct device *dev)
+{
+ struct class_device *cd;
+ int err = 0;
+
+idr_try_again:
+ if (!idr_pre_get(&dca_idr, GFP_KERNEL))
+ return -ENOMEM;
+ spin_lock(&dca_idr_lock);
+ err = idr_get_new(&dca_idr, dca, &dca->id);
+ spin_unlock(&dca_idr_lock);
+ switch (err) {
+ case 0:
+ break;
+ case -EAGAIN:
+ goto idr_try_again;
+ default:
+ return err;
+ }
+
+ cd = class_device_create(dca_class, NULL, MKDEV(0, 0),
+ dev, "dca%d", dca->id);
+ if (IS_ERR(cd)) {
+ spin_lock(&dca_idr_lock);
+ idr_remove(&dca_idr, dca->id);
+ spin_unlock(&dca_idr_lock);
+ return PTR_ERR(cd);
+ }
+ dca->cd = cd;
+ return 0;
+}
+
+void dca_sysfs_remove_provider(struct dca_provider *dca)
+{
+ class_device_unregister(dca->cd);
+ dca->cd = NULL;
+ spin_lock(&dca_idr_lock);
+ idr_remove(&dca_idr, dca->id);
+ spin_unlock(&dca_idr_lock);
+}
+
+int __init dca_sysfs_init(void)
+{
+ idr_init(&dca_idr);
+ spin_lock_init(&dca_idr_lock);
+
+ dca_class = class_create(THIS_MODULE, "dca");
+ if (IS_ERR(dca_class)) {
+ idr_destroy(&dca_idr);
+ return PTR_ERR(dca_class);
+ }
+ return 0;
+}
+
+void __exit dca_sysfs_exit(void)
+{
+ class_destroy(dca_class);
+ idr_destroy(&dca_idr);
+}
+
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 8f670dae53bb..6a7d25fc2470 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -2,42 +2,51 @@
# DMA engine configuration
#
-menu "DMA Engine support"
- depends on HAS_DMA
+menuconfig DMADEVICES
+ bool "DMA Offload Engine support"
+ depends on (PCI && X86) || ARCH_IOP32X || ARCH_IOP33X || ARCH_IOP13XX
+ help
+ Intel(R) offload engines enable offloading memory copies in the
+ network stack and RAID operations in the MD driver.
+
+if DMADEVICES
+
+comment "DMA Devices"
+
+config INTEL_IOATDMA
+ tristate "Intel I/OAT DMA support"
+ depends on PCI && X86
+ select DMA_ENGINE
+ select DCA
+ help
+ Enable support for the Intel(R) I/OAT DMA engine present
+ in recent Intel Xeon chipsets.
+
+ Say Y here if you have such a chipset.
+
+ If unsure, say N.
+
+config INTEL_IOP_ADMA
+ tristate "Intel IOP ADMA support"
+ depends on ARCH_IOP32X || ARCH_IOP33X || ARCH_IOP13XX
+ select ASYNC_CORE
+ select DMA_ENGINE
+ help
+ Enable support for the Intel(R) IOP Series RAID engines.
config DMA_ENGINE
- bool "Support for DMA engines"
- ---help---
- DMA engines offload bulk memory operations from the CPU to dedicated
- hardware, allowing the operations to happen asynchronously.
+ bool
comment "DMA Clients"
+ depends on DMA_ENGINE
config NET_DMA
bool "Network: TCP receive copy offload"
depends on DMA_ENGINE && NET
- default y
- ---help---
+ help
This enables the use of DMA engines in the network stack to
offload receive copy-to-user operations, freeing CPU cycles.
Since this is the main user of the DMA engine, it should be enabled;
say Y here.
-comment "DMA Devices"
-
-config INTEL_IOATDMA
- tristate "Intel I/OAT DMA support"
- depends on DMA_ENGINE && PCI
- default m
- ---help---
- Enable support for the Intel(R) I/OAT DMA engine.
-
-config INTEL_IOP_ADMA
- tristate "Intel IOP ADMA support"
- depends on DMA_ENGINE && (ARCH_IOP32X || ARCH_IOP33X || ARCH_IOP13XX)
- select ASYNC_CORE
- default m
- ---help---
- Enable support for the Intel(R) IOP Series RAID engines.
-
-endmenu
+endif
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index b3839b687ae0..b152cd84e123 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -1,4 +1,5 @@
obj-$(CONFIG_DMA_ENGINE) += dmaengine.o
obj-$(CONFIG_NET_DMA) += iovlock.o
obj-$(CONFIG_INTEL_IOATDMA) += ioatdma.o
+ioatdma-objs := ioat.o ioat_dma.o ioat_dca.o
obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 82489923af09..d59b2f417306 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -182,10 +182,9 @@ static void dma_client_chan_alloc(struct dma_client *client)
/* we are done once this client rejects
* an available resource
*/
- if (ack == DMA_ACK) {
+ if (ack == DMA_ACK)
dma_chan_get(chan);
- kref_get(&device->refcount);
- } else if (ack == DMA_NAK)
+ else if (ack == DMA_NAK)
return;
}
}
@@ -272,11 +271,8 @@ static void dma_clients_notify_removed(struct dma_chan *chan)
/* client was holding resources for this channel so
* free it
*/
- if (ack == DMA_ACK) {
+ if (ack == DMA_ACK)
dma_chan_put(chan);
- kref_put(&chan->device->refcount,
- dma_async_device_cleanup);
- }
}
mutex_unlock(&dma_list_mutex);
@@ -316,11 +312,8 @@ void dma_async_client_unregister(struct dma_client *client)
ack = client->event_callback(client, chan,
DMA_RESOURCE_REMOVED);
- if (ack == DMA_ACK) {
+ if (ack == DMA_ACK)
dma_chan_put(chan);
- kref_put(&chan->device->refcount,
- dma_async_device_cleanup);
- }
}
list_del(&client->global_node);
@@ -397,6 +390,8 @@ int dma_async_device_register(struct dma_device *device)
goto err_out;
}
+ /* One for the channel, one of the class device */
+ kref_get(&device->refcount);
kref_get(&device->refcount);
kref_init(&chan->refcount);
chan->slow_ref = 0;
diff --git a/drivers/dma/ioat.c b/drivers/dma/ioat.c
new file mode 100644
index 000000000000..16e0fd8facfb
--- /dev/null
+++ b/drivers/dma/ioat.c
@@ -0,0 +1,211 @@
+/*
+ * Intel I/OAT DMA Linux driver
+ * Copyright(c) 2007 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ */
+
+/*
+ * This driver supports an Intel I/OAT DMA engine, which does asynchronous
+ * copy operations.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/dca.h>
+#include "ioatdma.h"
+#include "ioatdma_registers.h"
+#include "ioatdma_hw.h"
+
+MODULE_VERSION(IOAT_DMA_VERSION);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Intel Corporation");
+
+static struct pci_device_id ioat_pci_tbl[] = {
+ /* I/OAT v1 platforms */
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_CNB) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SCNB) },
+ { PCI_DEVICE(PCI_VENDOR_ID_UNISYS, PCI_DEVICE_ID_UNISYS_DMA_DIRECTOR) },
+
+ /* I/OAT v2 platforms */
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB) },
+ { 0, }
+};
+
+struct ioat_device {
+ struct pci_dev *pdev;
+ void __iomem *iobase;
+ struct ioatdma_device *dma;
+ struct dca_provider *dca;
+};
+
+static int __devinit ioat_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id);
+static void __devexit ioat_remove(struct pci_dev *pdev);
+
+static int ioat_dca_enabled = 1;
+module_param(ioat_dca_enabled, int, 0644);
+MODULE_PARM_DESC(ioat_dca_enabled, "control support of dca service (default: 1)");
+
+static int ioat_setup_functionality(struct pci_dev *pdev, void __iomem *iobase)
+{
+ struct ioat_device *device = pci_get_drvdata(pdev);
+ u8 version;
+ int err = 0;
+
+ version = readb(iobase + IOAT_VER_OFFSET);
+ switch (version) {
+ case IOAT_VER_1_2:
+ device->dma = ioat_dma_probe(pdev, iobase);
+ if (device->dma && ioat_dca_enabled)
+ device->dca = ioat_dca_init(pdev, iobase);
+ break;
+ case IOAT_VER_2_0:
+ device->dma = ioat_dma_probe(pdev, iobase);
+ if (device->dma && ioat_dca_enabled)
+ device->dca = ioat2_dca_init(pdev, iobase);
+ break;
+ default:
+ err = -ENODEV;
+ break;
+ }
+ if (!device->dma)
+ err = -ENODEV;
+ return err;
+}
+
+static void ioat_shutdown_functionality(struct pci_dev *pdev)
+{
+ struct ioat_device *device = pci_get_drvdata(pdev);
+
+ dev_err(&pdev->dev, "Removing dma and dca services\n");
+ if (device->dca) {
+ unregister_dca_provider(device->dca);
+ free_dca_provider(device->dca);
+ device->dca = NULL;
+ }
+
+ if (device->dma) {
+ ioat_dma_remove(device->dma);
+ device->dma = NULL;
+ }
+}
+
+static struct pci_driver ioat_pci_driver = {
+ .name = "ioatdma",
+ .id_table = ioat_pci_tbl,
+ .probe = ioat_probe,
+ .shutdown = ioat_shutdown_functionality,
+ .remove = __devexit_p(ioat_remove),
+};
+
+static int __devinit ioat_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ void __iomem *iobase;
+ struct ioat_device *device;
+ unsigned long mmio_start, mmio_len;
+ int err;
+
+ err = pci_enable_device(pdev);
+ if (err)
+ goto err_enable_device;
+
+ err = pci_request_regions(pdev, ioat_pci_driver.name);
+ if (err)
+ goto err_request_regions;
+
+ err = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
+ if (err)
+ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (err)
+ goto err_set_dma_mask;
+
+ err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+ if (err)
+ err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+ if (err)
+ goto err_set_dma_mask;
+
+ mmio_start = pci_resource_start(pdev, 0);
+ mmio_len = pci_resource_len(pdev, 0);
+ iobase = ioremap(mmio_start, mmio_len);
+ if (!iobase) {
+ err = -ENOMEM;
+ goto err_ioremap;
+ }
+
+ device = kzalloc(sizeof(*device), GFP_KERNEL);
+ if (!device) {
+ err = -ENOMEM;
+ goto err_kzalloc;
+ }
+ device->pdev = pdev;
+ pci_set_drvdata(pdev, device);
+ device->iobase = iobase;
+
+ pci_set_master(pdev);
+
+ err = ioat_setup_functionality(pdev, iobase);
+ if (err)
+ goto err_version;
+
+ return 0;
+
+err_version:
+ kfree(device);
+err_kzalloc:
+ iounmap(iobase);
+err_ioremap:
+err_set_dma_mask:
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+err_request_regions:
+err_enable_device:
+ return err;
+}
+
+/*
+ * It is unsafe to remove this module: if removed while a requested
+ * dma is outstanding, esp. from tcp, it is possible to hang while
+ * waiting for something that will never finish. However, if you're
+ * feeling lucky, this usually works just fine.
+ */
+static void __devexit ioat_remove(struct pci_dev *pdev)
+{
+ struct ioat_device *device = pci_get_drvdata(pdev);
+
+ ioat_shutdown_functionality(pdev);
+
+ kfree(device);
+}
+
+static int __init ioat_init_module(void)
+{
+ return pci_register_driver(&ioat_pci_driver);
+}
+module_init(ioat_init_module);
+
+static void __exit ioat_exit_module(void)
+{
+ pci_unregister_driver(&ioat_pci_driver);
+}
+module_exit(ioat_exit_module);
diff --git a/drivers/dma/ioat_dca.c b/drivers/dma/ioat_dca.c
new file mode 100644
index 000000000000..0fa8a98051a8
--- /dev/null
+++ b/drivers/dma/ioat_dca.c
@@ -0,0 +1,427 @@
+/*
+ * Intel I/OAT DMA Linux driver
+ * Copyright(c) 2007 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/dca.h>
+
+/* either a kernel change is needed, or we need something like this in kernel */
+#ifndef CONFIG_SMP
+#include <asm/smp.h>
+#undef cpu_physical_id
+#define cpu_physical_id(cpu) (cpuid_ebx(1) >> 24)
+#endif
+
+#include "ioatdma.h"
+#include "ioatdma_registers.h"
+
+/*
+ * Bit 16 of a tag map entry is the "valid" bit, if it is set then bits 0:15
+ * contain the bit number of the APIC ID to map into the DCA tag. If the valid
+ * bit is not set, then the value must be 0 or 1 and defines the bit in the tag.
+ */
+#define DCA_TAG_MAP_VALID 0x80
+
+/*
+ * "Legacy" DCA systems do not implement the DCA register set in the
+ * I/OAT device. Software needs direct support for their tag mappings.
+ */
+
+#define APICID_BIT(x) (DCA_TAG_MAP_VALID | (x))
+#define IOAT_TAG_MAP_LEN 8
+
+static u8 ioat_tag_map_BNB[IOAT_TAG_MAP_LEN] = {
+ 1, APICID_BIT(1), APICID_BIT(2), APICID_BIT(2), };
+static u8 ioat_tag_map_SCNB[IOAT_TAG_MAP_LEN] = {
+ 1, APICID_BIT(1), APICID_BIT(2), APICID_BIT(2), };
+static u8 ioat_tag_map_CNB[IOAT_TAG_MAP_LEN] = {
+ 1, APICID_BIT(1), APICID_BIT(3), APICID_BIT(4), APICID_BIT(2), };
+static u8 ioat_tag_map_UNISYS[IOAT_TAG_MAP_LEN] = { 0 };
+
+/* pack PCI B/D/F into a u16 */
+static inline u16 dcaid_from_pcidev(struct pci_dev *pci)
+{
+ return (pci->bus->number << 8) | pci->devfn;
+}
+
+static int dca_enabled_in_bios(struct pci_dev *pdev)
+{
+ /* CPUID level 9 returns DCA configuration */
+ /* Bit 0 indicates DCA enabled by the BIOS */
+ unsigned long cpuid_level_9;
+ int res;
+
+ cpuid_level_9 = cpuid_eax(9);
+ res = test_bit(0, &cpuid_level_9);
+ if (!res)
+ dev_err(&pdev->dev, "DCA is disabled in BIOS\n");
+
+ return res;
+}
+
+static int system_has_dca_enabled(struct pci_dev *pdev)
+{
+ if (boot_cpu_has(X86_FEATURE_DCA))
+ return dca_enabled_in_bios(pdev);
+
+ dev_err(&pdev->dev, "boot cpu doesn't have X86_FEATURE_DCA\n");
+ return 0;
+}
+
+struct ioat_dca_slot {
+ struct pci_dev *pdev; /* requester device */
+ u16 rid; /* requester id, as used by IOAT */
+};
+
+#define IOAT_DCA_MAX_REQ 6
+
+struct ioat_dca_priv {
+ void __iomem *iobase;
+ void *dca_base;
+ int max_requesters;
+ int requester_count;
+ u8 tag_map[IOAT_TAG_MAP_LEN];
+ struct ioat_dca_slot req_slots[0];
+};
+
+/* 5000 series chipset DCA Port Requester ID Table Entry Format
+ * [15:8] PCI-Express Bus Number
+ * [7:3] PCI-Express Device Number
+ * [2:0] PCI-Express Function Number
+ *
+ * 5000 series chipset DCA control register format
+ * [7:1] Reserved (0)
+ * [0] Ignore Function Number
+ */
+
+static int ioat_dca_add_requester(struct dca_provider *dca, struct device *dev)
+{
+ struct ioat_dca_priv *ioatdca = dca_priv(dca);
+ struct pci_dev *pdev;
+ int i;
+ u16 id;
+
+ /* This implementation only supports PCI-Express */
+ if (dev->bus != &pci_bus_type)
+ return -ENODEV;
+ pdev = to_pci_dev(dev);
+ id = dcaid_from_pcidev(pdev);
+
+ if (ioatdca->requester_count == ioatdca->max_requesters)
+ return -ENODEV;
+
+ for (i = 0; i < ioatdca->max_requesters; i++) {
+ if (ioatdca->req_slots[i].pdev == NULL) {
+ /* found an empty slot */
+ ioatdca->requester_count++;
+ ioatdca->req_slots[i].pdev = pdev;
+ ioatdca->req_slots[i].rid = id;
+ writew(id, ioatdca->dca_base + (i * 4));
+ /* make sure the ignore function bit is off */
+ writeb(0, ioatdca->dca_base + (i * 4) + 2);
+ return i;
+ }
+ }
+ /* Error, ioatdma->requester_count is out of whack */
+ return -EFAULT;
+}
+
+static int ioat_dca_remove_requester(struct dca_provider *dca,
+ struct device *dev)
+{
+ struct ioat_dca_priv *ioatdca = dca_priv(dca);
+ struct pci_dev *pdev;
+ int i;
+
+ /* This implementation only supports PCI-Express */
+ if (dev->bus != &pci_bus_type)
+ return -ENODEV;
+ pdev = to_pci_dev(dev);
+
+ for (i = 0; i < ioatdca->max_requesters; i++) {
+ if (ioatdca->req_slots[i].pdev == pdev) {
+ writew(0, ioatdca->dca_base + (i * 4));
+ ioatdca->req_slots[i].pdev = NULL;
+ ioatdca->req_slots[i].rid = 0;
+ ioatdca->requester_count--;
+ return i;
+ }
+ }
+ return -ENODEV;
+}
+
+static u8 ioat_dca_get_tag(struct dca_provider *dca, int cpu)
+{
+ struct ioat_dca_priv *ioatdca = dca_priv(dca);
+ int i, apic_id, bit, value;
+ u8 entry, tag;
+
+ tag = 0;
+ apic_id = cpu_physical_id(cpu);
+
+ for (i = 0; i < IOAT_TAG_MAP_LEN; i++) {
+ entry = ioatdca->tag_map[i];
+ if (entry & DCA_TAG_MAP_VALID) {
+ bit = entry & ~DCA_TAG_MAP_VALID;
+ value = (apic_id & (1 << bit)) ? 1 : 0;
+ } else {
+ value = entry ? 1 : 0;
+ }
+ tag |= (value << i);
+ }
+ return tag;
+}
+
+static struct dca_ops ioat_dca_ops = {
+ .add_requester = ioat_dca_add_requester,
+ .remove_requester = ioat_dca_remove_requester,
+ .get_tag = ioat_dca_get_tag,
+};
+
+
+struct dca_provider *ioat_dca_init(struct pci_dev *pdev, void __iomem *iobase)
+{
+ struct dca_provider *dca;
+ struct ioat_dca_priv *ioatdca;
+ u8 *tag_map = NULL;
+ int i;
+ int err;
+
+ if (!system_has_dca_enabled(pdev))
+ return NULL;
+
+ /* I/OAT v1 systems must have a known tag_map to support DCA */
+ switch (pdev->vendor) {
+ case PCI_VENDOR_ID_INTEL:
+ switch (pdev->device) {
+ case PCI_DEVICE_ID_INTEL_IOAT:
+ tag_map = ioat_tag_map_BNB;
+ break;
+ case PCI_DEVICE_ID_INTEL_IOAT_CNB:
+ tag_map = ioat_tag_map_CNB;
+ break;
+ case PCI_DEVICE_ID_INTEL_IOAT_SCNB:
+ tag_map = ioat_tag_map_SCNB;
+ break;
+ }
+ break;
+ case PCI_VENDOR_ID_UNISYS:
+ switch (pdev->device) {
+ case PCI_DEVICE_ID_UNISYS_DMA_DIRECTOR:
+ tag_map = ioat_tag_map_UNISYS;
+ break;
+ }
+ break;
+ }
+ if (tag_map == NULL)
+ return NULL;
+
+ dca = alloc_dca_provider(&ioat_dca_ops,
+ sizeof(*ioatdca) +
+ (sizeof(struct ioat_dca_slot) * IOAT_DCA_MAX_REQ));
+ if (!dca)
+ return NULL;
+
+ ioatdca = dca_priv(dca);
+ ioatdca->max_requesters = IOAT_DCA_MAX_REQ;
+
+ ioatdca->dca_base = iobase + 0x54;
+
+ /* copy over the APIC ID to DCA tag mapping */
+ for (i = 0; i < IOAT_TAG_MAP_LEN; i++)
+ ioatdca->tag_map[i] = tag_map[i];
+
+ err = register_dca_provider(dca, &pdev->dev);
+ if (err) {
+ free_dca_provider(dca);
+ return NULL;
+ }
+
+ return dca;
+}
+
+
+static int ioat2_dca_add_requester(struct dca_provider *dca, struct device *dev)
+{
+ struct ioat_dca_priv *ioatdca = dca_priv(dca);
+ struct pci_dev *pdev;
+ int i;
+ u16 id;
+ u16 global_req_table;
+
+ /* This implementation only supports PCI-Express */
+ if (dev->bus != &pci_bus_type)
+ return -ENODEV;
+ pdev = to_pci_dev(dev);
+ id = dcaid_from_pcidev(pdev);
+
+ if (ioatdca->requester_count == ioatdca->max_requesters)
+ return -ENODEV;
+
+ for (i = 0; i < ioatdca->max_requesters; i++) {
+ if (ioatdca->req_slots[i].pdev == NULL) {
+ /* found an empty slot */
+ ioatdca->requester_count++;
+ ioatdca->req_slots[i].pdev = pdev;
+ ioatdca->req_slots[i].rid = id;
+ global_req_table =
+ readw(ioatdca->dca_base + IOAT_DCA_GREQID_OFFSET);
+ writel(id | IOAT_DCA_GREQID_VALID,
+ ioatdca->iobase + global_req_table + (i * 4));
+ return i;
+ }
+ }
+ /* Error, ioatdma->requester_count is out of whack */
+ return -EFAULT;
+}
+
+static int ioat2_dca_remove_requester(struct dca_provider *dca,
+ struct device *dev)
+{
+ struct ioat_dca_priv *ioatdca = dca_priv(dca);
+ struct pci_dev *pdev;
+ int i;
+ u16 global_req_table;
+
+ /* This implementation only supports PCI-Express */
+ if (dev->bus != &pci_bus_type)
+ return -ENODEV;
+ pdev = to_pci_dev(dev);
+
+ for (i = 0; i < ioatdca->max_requesters; i++) {
+ if (ioatdca->req_slots[i].pdev == pdev) {
+ global_req_table =
+ readw(ioatdca->dca_base + IOAT_DCA_GREQID_OFFSET);
+ writel(0, ioatdca->iobase + global_req_table + (i * 4));
+ ioatdca->req_slots[i].pdev = NULL;
+ ioatdca->req_slots[i].rid = 0;
+ ioatdca->requester_count--;
+ return i;
+ }
+ }
+ return -ENODEV;
+}
+
+static u8 ioat2_dca_get_tag(struct dca_provider *dca, int cpu)
+{
+ u8 tag;
+
+ tag = ioat_dca_get_tag(dca, cpu);
+ tag = (~tag) & 0x1F;
+ return tag;
+}
+
+static struct dca_ops ioat2_dca_ops = {
+ .add_requester = ioat2_dca_add_requester,
+ .remove_requester = ioat2_dca_remove_requester,
+ .get_tag = ioat2_dca_get_tag,
+};
+
+static int ioat2_dca_count_dca_slots(void *iobase, u16 dca_offset)
+{
+ int slots = 0;
+ u32 req;
+ u16 global_req_table;
+
+ global_req_table = readw(iobase + dca_offset + IOAT_DCA_GREQID_OFFSET);
+ if (global_req_table == 0)
+ return 0;
+ do {
+ req = readl(iobase + global_req_table + (slots * sizeof(u32)));
+ slots++;
+ } while ((req & IOAT_DCA_GREQID_LASTID) == 0);
+
+ return slots;
+}
+
+struct dca_provider *ioat2_dca_init(struct pci_dev *pdev, void __iomem *iobase)
+{
+ struct dca_provider *dca;
+ struct ioat_dca_priv *ioatdca;
+ int slots;
+ int i;
+ int err;
+ u32 tag_map;
+ u16 dca_offset;
+ u16 csi_fsb_control;
+ u16 pcie_control;
+ u8 bit;
+
+ if (!system_has_dca_enabled(pdev))
+ return NULL;
+
+ dca_offset = readw(iobase + IOAT_DCAOFFSET_OFFSET);
+ if (dca_offset == 0)
+ return NULL;
+
+ slots = ioat2_dca_count_dca_slots(iobase, dca_offset);
+ if (slots == 0)
+ return NULL;
+
+ dca = alloc_dca_provider(&ioat2_dca_ops,
+ sizeof(*ioatdca)
+ + (sizeof(struct ioat_dca_slot) * slots));
+ if (!dca)
+ return NULL;
+
+ ioatdca = dca_priv(dca);
+ ioatdca->iobase = iobase;
+ ioatdca->dca_base = iobase + dca_offset;
+ ioatdca->max_requesters = slots;
+
+ /* some bios might not know to turn these on */
+ csi_fsb_control = readw(ioatdca->dca_base + IOAT_FSB_CAP_ENABLE_OFFSET);
+ if ((csi_fsb_control & IOAT_FSB_CAP_ENABLE_PREFETCH) == 0) {
+ csi_fsb_control |= IOAT_FSB_CAP_ENABLE_PREFETCH;
+ writew(csi_fsb_control,
+ ioatdca->dca_base + IOAT_FSB_CAP_ENABLE_OFFSET);
+ }
+ pcie_control = readw(ioatdca->dca_base + IOAT_PCI_CAP_ENABLE_OFFSET);
+ if ((pcie_control & IOAT_PCI_CAP_ENABLE_MEMWR) == 0) {
+ pcie_control |= IOAT_PCI_CAP_ENABLE_MEMWR;
+ writew(pcie_control,
+ ioatdca->dca_base + IOAT_PCI_CAP_ENABLE_OFFSET);
+ }
+
+
+ /* TODO version, compatibility and configuration checks */
+
+ /* copy out the APIC to DCA tag map */
+ tag_map = readl(ioatdca->dca_base + IOAT_APICID_TAG_MAP_OFFSET);
+ for (i = 0; i < 5; i++) {
+ bit = (tag_map >> (4 * i)) & 0x0f;
+ if (bit < 8)
+ ioatdca->tag_map[i] = bit | DCA_TAG_MAP_VALID;
+ else
+ ioatdca->tag_map[i] = 0;
+ }
+
+ err = register_dca_provider(dca, &pdev->dev);
+ if (err) {
+ free_dca_provider(dca);
+ return NULL;
+ }
+
+ return dca;
+}
diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c
new file mode 100644
index 000000000000..c1c2dcc6fc2e
--- /dev/null
+++ b/drivers/dma/ioat_dma.c
@@ -0,0 +1,1383 @@
+/*
+ * Intel I/OAT DMA Linux driver
+ * Copyright(c) 2004 - 2007 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ */
+
+/*
+ * This driver supports an Intel I/OAT DMA engine, which does asynchronous
+ * copy operations.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/dmaengine.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include "ioatdma.h"
+#include "ioatdma_registers.h"
+#include "ioatdma_hw.h"
+
+#define to_ioat_chan(chan) container_of(chan, struct ioat_dma_chan, common)
+#define to_ioatdma_device(dev) container_of(dev, struct ioatdma_device, common)
+#define to_ioat_desc(lh) container_of(lh, struct ioat_desc_sw, node)
+#define tx_to_ioat_desc(tx) container_of(tx, struct ioat_desc_sw, async_tx)
+
+static int ioat_pending_level = 4;
+module_param(ioat_pending_level, int, 0644);
+MODULE_PARM_DESC(ioat_pending_level,
+ "high-water mark for pushing ioat descriptors (default: 4)");
+
+/* internal functions */
+static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan);
+static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan);
+
+static struct ioat_desc_sw *
+ioat1_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan);
+static struct ioat_desc_sw *
+ioat2_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan);
+
+static inline struct ioat_dma_chan *ioat_lookup_chan_by_index(
+ struct ioatdma_device *device,
+ int index)
+{
+ return device->idx[index];
+}
+
+/**
+ * ioat_dma_do_interrupt - handler used for single vector interrupt mode
+ * @irq: interrupt id
+ * @data: interrupt data
+ */
+static irqreturn_t ioat_dma_do_interrupt(int irq, void *data)
+{
+ struct ioatdma_device *instance = data;
+ struct ioat_dma_chan *ioat_chan;
+ unsigned long attnstatus;
+ int bit;
+ u8 intrctrl;
+
+ intrctrl = readb(instance->reg_base + IOAT_INTRCTRL_OFFSET);
+
+ if (!(intrctrl & IOAT_INTRCTRL_MASTER_INT_EN))
+ return IRQ_NONE;
+
+ if (!(intrctrl & IOAT_INTRCTRL_INT_STATUS)) {
+ writeb(intrctrl, instance->reg_base + IOAT_INTRCTRL_OFFSET);
+ return IRQ_NONE;
+ }
+
+ attnstatus = readl(instance->reg_base + IOAT_ATTNSTATUS_OFFSET);
+ for_each_bit(bit, &attnstatus, BITS_PER_LONG) {
+ ioat_chan = ioat_lookup_chan_by_index(instance, bit);
+ tasklet_schedule(&ioat_chan->cleanup_task);
+ }
+
+ writeb(intrctrl, instance->reg_base + IOAT_INTRCTRL_OFFSET);
+ return IRQ_HANDLED;
+}
+
+/**
+ * ioat_dma_do_interrupt_msix - handler used for vector-per-channel interrupt mode
+ * @irq: interrupt id
+ * @data: interrupt data
+ */
+static irqreturn_t ioat_dma_do_interrupt_msix(int irq, void *data)
+{
+ struct ioat_dma_chan *ioat_chan = data;
+
+ tasklet_schedule(&ioat_chan->cleanup_task);
+
+ return IRQ_HANDLED;
+}
+
+static void ioat_dma_cleanup_tasklet(unsigned long data);
+
+/**
+ * ioat_dma_enumerate_channels - find and initialize the device's channels
+ * @device: the device to be enumerated
+ */
+static int ioat_dma_enumerate_channels(struct ioatdma_device *device)
+{
+ u8 xfercap_scale;
+ u32 xfercap;
+ int i;
+ struct ioat_dma_chan *ioat_chan;
+
+ device->common.chancnt = readb(device->reg_base + IOAT_CHANCNT_OFFSET);
+ xfercap_scale = readb(device->reg_base + IOAT_XFERCAP_OFFSET);
+ xfercap = (xfercap_scale == 0 ? -1 : (1UL << xfercap_scale));
+
+ for (i = 0; i < device->common.chancnt; i++) {
+ ioat_chan = kzalloc(sizeof(*ioat_chan), GFP_KERNEL);
+ if (!ioat_chan) {
+ device->common.chancnt = i;
+ break;
+ }
+
+ ioat_chan->device = device;
+ ioat_chan->reg_base = device->reg_base + (0x80 * (i + 1));
+ ioat_chan->xfercap = xfercap;
+ ioat_chan->desccount = 0;
+ if (ioat_chan->device->version != IOAT_VER_1_2) {
+ writel(IOAT_DCACTRL_CMPL_WRITE_ENABLE
+ | IOAT_DMA_DCA_ANY_CPU,
+ ioat_chan->reg_base + IOAT_DCACTRL_OFFSET);
+ }
+ spin_lock_init(&ioat_chan->cleanup_lock);
+ spin_lock_init(&ioat_chan->desc_lock);
+ INIT_LIST_HEAD(&ioat_chan->free_desc);
+ INIT_LIST_HEAD(&ioat_chan->used_desc);
+ /* This should be made common somewhere in dmaengine.c */
+ ioat_chan->common.device = &device->common;
+ list_add_tail(&ioat_chan->common.device_node,
+ &device->common.channels);
+ device->idx[i] = ioat_chan;
+ tasklet_init(&ioat_chan->cleanup_task,
+ ioat_dma_cleanup_tasklet,
+ (unsigned long) ioat_chan);
+ tasklet_disable(&ioat_chan->cleanup_task);
+ }
+ return device->common.chancnt;
+}
+
+static void ioat_set_src(dma_addr_t addr,
+ struct dma_async_tx_descriptor *tx,
+ int index)
+{
+ tx_to_ioat_desc(tx)->src = addr;
+}
+
+static void ioat_set_dest(dma_addr_t addr,
+ struct dma_async_tx_descriptor *tx,
+ int index)
+{
+ tx_to_ioat_desc(tx)->dst = addr;
+}
+
+static inline void __ioat1_dma_memcpy_issue_pending(
+ struct ioat_dma_chan *ioat_chan);
+static inline void __ioat2_dma_memcpy_issue_pending(
+ struct ioat_dma_chan *ioat_chan);
+
+static dma_cookie_t ioat1_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+ struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan);
+ struct ioat_desc_sw *first = tx_to_ioat_desc(tx);
+ struct ioat_desc_sw *prev, *new;
+ struct ioat_dma_descriptor *hw;
+ dma_cookie_t cookie;
+ LIST_HEAD(new_chain);
+ u32 copy;
+ size_t len;
+ dma_addr_t src, dst;
+ int orig_ack;
+ unsigned int desc_count = 0;
+
+ /* src and dest and len are stored in the initial descriptor */
+ len = first->len;
+ src = first->src;
+ dst = first->dst;
+ orig_ack = first->async_tx.ack;
+ new = first;
+
+ spin_lock_bh(&ioat_chan->desc_lock);
+ prev = to_ioat_desc(ioat_chan->used_desc.prev);
+ prefetch(prev->hw);
+ do {
+ copy = min((u32) len, ioat_chan->xfercap);
+
+ new->async_tx.ack = 1;
+
+ hw = new->hw;
+ hw->size = copy;
+ hw->ctl = 0;
+ hw->src_addr = src;
+ hw->dst_addr = dst;
+ hw->next = 0;
+
+ /* chain together the physical address list for the HW */
+ wmb();
+ prev->hw->next = (u64) new->async_tx.phys;
+
+ len -= copy;
+ dst += copy;
+ src += copy;
+
+ list_add_tail(&new->node, &new_chain);
+ desc_count++;
+ prev = new;
+ } while (len && (new = ioat1_dma_get_next_descriptor(ioat_chan)));
+
+ hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS;
+ if (new->async_tx.callback) {
+ hw->ctl |= IOAT_DMA_DESCRIPTOR_CTL_INT_GN;
+ if (first != new) {
+ /* move callback into to last desc */
+ new->async_tx.callback = first->async_tx.callback;
+ new->async_tx.callback_param
+ = first->async_tx.callback_param;
+ first->async_tx.callback = NULL;
+ first->async_tx.callback_param = NULL;
+ }
+ }
+
+ new->tx_cnt = desc_count;
+ new->async_tx.ack = orig_ack; /* client is in control of this ack */
+
+ /* store the original values for use in later cleanup */
+ if (new != first) {
+ new->src = first->src;
+ new->dst = first->dst;
+ new->len = first->len;
+ }
+
+ /* cookie incr and addition to used_list must be atomic */
+ cookie = ioat_chan->common.cookie;
+ cookie++;
+ if (cookie < 0)
+ cookie = 1;
+ ioat_chan->common.cookie = new->async_tx.cookie = cookie;
+
+ /* write address into NextDescriptor field of last desc in chain */
+ to_ioat_desc(ioat_chan->used_desc.prev)->hw->next =
+ first->async_tx.phys;
+ __list_splice(&new_chain, ioat_chan->used_desc.prev);
+
+ ioat_chan->dmacount += desc_count;
+ ioat_chan->pending += desc_count;
+ if (ioat_chan->pending >= ioat_pending_level)
+ __ioat1_dma_memcpy_issue_pending(ioat_chan);
+ spin_unlock_bh(&ioat_chan->desc_lock);
+
+ return cookie;
+}
+
+static dma_cookie_t ioat2_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+ struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan);
+ struct ioat_desc_sw *first = tx_to_ioat_desc(tx);
+ struct ioat_desc_sw *new;
+ struct ioat_dma_descriptor *hw;
+ dma_cookie_t cookie;
+ u32 copy;
+ size_t len;
+ dma_addr_t src, dst;
+ int orig_ack;
+ unsigned int desc_count = 0;
+
+ /* src and dest and len are stored in the initial descriptor */
+ len = first->len;
+ src = first->src;
+ dst = first->dst;
+ orig_ack = first->async_tx.ack;
+ new = first;
+
+ /* ioat_chan->desc_lock is still in force in version 2 path */
+
+ do {
+ copy = min((u32) len, ioat_chan->xfercap);
+
+ new->async_tx.ack = 1;
+
+ hw = new->hw;
+ hw->size = copy;
+ hw->ctl = 0;
+ hw->src_addr = src;
+ hw->dst_addr = dst;
+
+ len -= copy;
+ dst += copy;
+ src += copy;
+ desc_count++;
+ } while (len && (new = ioat2_dma_get_next_descriptor(ioat_chan)));
+
+ hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS;
+ if (new->async_tx.callback) {
+ hw->ctl |= IOAT_DMA_DESCRIPTOR_CTL_INT_GN;
+ if (first != new) {
+ /* move callback into to last desc */
+ new->async_tx.callback = first->async_tx.callback;
+ new->async_tx.callback_param
+ = first->async_tx.callback_param;
+ first->async_tx.callback = NULL;
+ first->async_tx.callback_param = NULL;
+ }
+ }
+
+ new->tx_cnt = desc_count;
+ new->async_tx.ack = orig_ack; /* client is in control of this ack */
+
+ /* store the original values for use in later cleanup */
+ if (new != first) {
+ new->src = first->src;
+ new->dst = first->dst;
+ new->len = first->len;
+ }
+
+ /* cookie incr and addition to used_list must be atomic */
+ cookie = ioat_chan->common.cookie;
+ cookie++;
+ if (cookie < 0)
+ cookie = 1;
+ ioat_chan->common.cookie = new->async_tx.cookie = cookie;
+
+ ioat_chan->dmacount += desc_count;
+ ioat_chan->pending += desc_count;
+ if (ioat_chan->pending >= ioat_pending_level)
+ __ioat2_dma_memcpy_issue_pending(ioat_chan);
+ spin_unlock_bh(&ioat_chan->desc_lock);
+
+ return cookie;
+}
+
+/**
+ * ioat_dma_alloc_descriptor - allocate and return a sw and hw descriptor pair
+ * @ioat_chan: the channel supplying the memory pool for the descriptors
+ * @flags: allocation flags
+ */
+static struct ioat_desc_sw *ioat_dma_alloc_descriptor(
+ struct ioat_dma_chan *ioat_chan,
+ gfp_t flags)
+{
+ struct ioat_dma_descriptor *desc;
+ struct ioat_desc_sw *desc_sw;
+ struct ioatdma_device *ioatdma_device;
+ dma_addr_t phys;
+
+ ioatdma_device = to_ioatdma_device(ioat_chan->common.device);
+ desc = pci_pool_alloc(ioatdma_device->dma_pool, flags, &phys);
+ if (unlikely(!desc))
+ return NULL;
+
+ desc_sw = kzalloc(sizeof(*desc_sw), flags);
+ if (unlikely(!desc_sw)) {
+ pci_pool_free(ioatdma_device->dma_pool, desc, phys);
+ return NULL;
+ }
+
+ memset(desc, 0, sizeof(*desc));
+ dma_async_tx_descriptor_init(&desc_sw->async_tx, &ioat_chan->common);
+ desc_sw->async_tx.tx_set_src = ioat_set_src;
+ desc_sw->async_tx.tx_set_dest = ioat_set_dest;
+ switch (ioat_chan->device->version) {
+ case IOAT_VER_1_2:
+ desc_sw->async_tx.tx_submit = ioat1_tx_submit;
+ break;
+ case IOAT_VER_2_0:
+ desc_sw->async_tx.tx_submit = ioat2_tx_submit;
+ break;
+ }
+ INIT_LIST_HEAD(&desc_sw->async_tx.tx_list);
+
+ desc_sw->hw = desc;
+ desc_sw->async_tx.phys = phys;
+
+ return desc_sw;
+}
+
+static int ioat_initial_desc_count = 256;
+module_param(ioat_initial_desc_count, int, 0644);
+MODULE_PARM_DESC(ioat_initial_desc_count,
+ "initial descriptors per channel (default: 256)");
+
+/**
+ * ioat2_dma_massage_chan_desc - link the descriptors into a circle
+ * @ioat_chan: the channel to be massaged
+ */
+static void ioat2_dma_massage_chan_desc(struct ioat_dma_chan *ioat_chan)
+{
+ struct ioat_desc_sw *desc, *_desc;
+
+ /* setup used_desc */
+ ioat_chan->used_desc.next = ioat_chan->free_desc.next;
+ ioat_chan->used_desc.prev = NULL;
+
+ /* pull free_desc out of the circle so that every node is a hw
+ * descriptor, but leave it pointing to the list
+ */
+ ioat_chan->free_desc.prev->next = ioat_chan->free_desc.next;
+ ioat_chan->free_desc.next->prev = ioat_chan->free_desc.prev;
+
+ /* circle link the hw descriptors */
+ desc = to_ioat_desc(ioat_chan->free_desc.next);
+ desc->hw->next = to_ioat_desc(desc->node.next)->async_tx.phys;
+ list_for_each_entry_safe(desc, _desc, ioat_chan->free_desc.next, node) {
+ desc->hw->next = to_ioat_desc(desc->node.next)->async_tx.phys;
+ }
+}
+
+/**
+ * ioat_dma_alloc_chan_resources - returns the number of allocated descriptors
+ * @chan: the channel to be filled out
+ */
+static int ioat_dma_alloc_chan_resources(struct dma_chan *chan)
+{
+ struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+ struct ioat_desc_sw *desc = NULL;
+ u16 chanctrl;
+ u32 chanerr;
+ int i;
+ LIST_HEAD(tmp_list);
+
+ /* have we already been set up? */
+ if (!list_empty(&ioat_chan->free_desc))
+ return ioat_chan->desccount;
+
+ /* Setup register to interrupt and write completion status on error */
+ chanctrl = IOAT_CHANCTRL_ERR_INT_EN |
+ IOAT_CHANCTRL_ANY_ERR_ABORT_EN |
+ IOAT_CHANCTRL_ERR_COMPLETION_EN;
+ writew(chanctrl, ioat_chan->reg_base + IOAT_CHANCTRL_OFFSET);
+
+ chanerr = readl(ioat_chan->reg_base + IOAT_CHANERR_OFFSET);
+ if (chanerr) {
+ dev_err(&ioat_chan->device->pdev->dev,
+ "CHANERR = %x, clearing\n", chanerr);
+ writel(chanerr, ioat_chan->reg_base + IOAT_CHANERR_OFFSET);
+ }
+
+ /* Allocate descriptors */
+ for (i = 0; i < ioat_initial_desc_count; i++) {
+ desc = ioat_dma_alloc_descriptor(ioat_chan, GFP_KERNEL);
+ if (!desc) {
+ dev_err(&ioat_chan->device->pdev->dev,
+ "Only %d initial descriptors\n", i);
+ break;
+ }
+ list_add_tail(&desc->node, &tmp_list);
+ }
+ spin_lock_bh(&ioat_chan->desc_lock);
+ ioat_chan->desccount = i;
+ list_splice(&tmp_list, &ioat_chan->free_desc);
+ if (ioat_chan->device->version != IOAT_VER_1_2)
+ ioat2_dma_massage_chan_desc(ioat_chan);
+ spin_unlock_bh(&ioat_chan->desc_lock);
+
+ /* allocate a completion writeback area */
+ /* doing 2 32bit writes to mmio since 1 64b write doesn't work */
+ ioat_chan->completion_virt =
+ pci_pool_alloc(ioat_chan->device->completion_pool,
+ GFP_KERNEL,
+ &ioat_chan->completion_addr);
+ memset(ioat_chan->completion_virt, 0,
+ sizeof(*ioat_chan->completion_virt));
+ writel(((u64) ioat_chan->completion_addr) & 0x00000000FFFFFFFF,
+ ioat_chan->reg_base + IOAT_CHANCMP_OFFSET_LOW);
+ writel(((u64) ioat_chan->completion_addr) >> 32,
+ ioat_chan->reg_base + IOAT_CHANCMP_OFFSET_HIGH);
+
+ tasklet_enable(&ioat_chan->cleanup_task);
+ ioat_dma_start_null_desc(ioat_chan); /* give chain to dma device */
+ return ioat_chan->desccount;
+}
+
+/**
+ * ioat_dma_free_chan_resources - release all the descriptors
+ * @chan: the channel to be cleaned
+ */
+static void ioat_dma_free_chan_resources(struct dma_chan *chan)
+{
+ struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+ struct ioatdma_device *ioatdma_device = to_ioatdma_device(chan->device);
+ struct ioat_desc_sw *desc, *_desc;
+ int in_use_descs = 0;
+
+ tasklet_disable(&ioat_chan->cleanup_task);
+ ioat_dma_memcpy_cleanup(ioat_chan);
+
+ /* Delay 100ms after reset to allow internal DMA logic to quiesce
+ * before removing DMA descriptor resources.
+ */
+ writeb(IOAT_CHANCMD_RESET,
+ ioat_chan->reg_base
+ + IOAT_CHANCMD_OFFSET(ioat_chan->device->version));
+ mdelay(100);
+
+ spin_lock_bh(&ioat_chan->desc_lock);
+ switch (ioat_chan->device->version) {
+ case IOAT_VER_1_2:
+ list_for_each_entry_safe(desc, _desc,
+ &ioat_chan->used_desc, node) {
+ in_use_descs++;
+ list_del(&desc->node);
+ pci_pool_free(ioatdma_device->dma_pool, desc->hw,
+ desc->async_tx.phys);
+ kfree(desc);
+ }
+ list_for_each_entry_safe(desc, _desc,
+ &ioat_chan->free_desc, node) {
+ list_del(&desc->node);
+ pci_pool_free(ioatdma_device->dma_pool, desc->hw,
+ desc->async_tx.phys);
+ kfree(desc);
+ }
+ break;
+ case IOAT_VER_2_0:
+ list_for_each_entry_safe(desc, _desc,
+ ioat_chan->free_desc.next, node) {
+ list_del(&desc->node);
+ pci_pool_free(ioatdma_device->dma_pool, desc->hw,
+ desc->async_tx.phys);
+ kfree(desc);
+ }
+ desc = to_ioat_desc(ioat_chan->free_desc.next);
+ pci_pool_free(ioatdma_device->dma_pool, desc->hw,
+ desc->async_tx.phys);
+ kfree(desc);
+ INIT_LIST_HEAD(&ioat_chan->free_desc);
+ INIT_LIST_HEAD(&ioat_chan->used_desc);
+ break;
+ }
+ spin_unlock_bh(&ioat_chan->desc_lock);
+
+ pci_pool_free(ioatdma_device->completion_pool,
+ ioat_chan->completion_virt,
+ ioat_chan->completion_addr);
+
+ /* one is ok since we left it on there on purpose */
+ if (in_use_descs > 1)
+ dev_err(&ioat_chan->device->pdev->dev,
+ "Freeing %d in use descriptors!\n",
+ in_use_descs - 1);
+
+ ioat_chan->last_completion = ioat_chan->completion_addr = 0;
+ ioat_chan->pending = 0;
+ ioat_chan->dmacount = 0;
+}
+
+/**
+ * ioat_dma_get_next_descriptor - return the next available descriptor
+ * @ioat_chan: IOAT DMA channel handle
+ *
+ * Gets the next descriptor from the chain, and must be called with the
+ * channel's desc_lock held. Allocates more descriptors if the channel
+ * has run out.
+ */
+static struct ioat_desc_sw *
+ioat1_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan)
+{
+ struct ioat_desc_sw *new = NULL;
+
+ if (!list_empty(&ioat_chan->free_desc)) {
+ new = to_ioat_desc(ioat_chan->free_desc.next);
+ list_del(&new->node);
+ } else {
+ /* try to get another desc */
+ new = ioat_dma_alloc_descriptor(ioat_chan, GFP_ATOMIC);
+ /* will this ever happen? */
+ /* TODO add upper limit on these */
+ BUG_ON(!new);
+ }
+
+ prefetch(new->hw);
+ return new;
+}
+
+static struct ioat_desc_sw *
+ioat2_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan)
+{
+ struct ioat_desc_sw *new = NULL;
+
+ /*
+ * used.prev points to where to start processing
+ * used.next points to next free descriptor
+ * if used.prev == NULL, there are none waiting to be processed
+ * if used.next == used.prev.prev, there is only one free descriptor,
+ * and we need to use it to as a noop descriptor before
+ * linking in a new set of descriptors, since the device
+ * has probably already read the pointer to it
+ */
+ if (ioat_chan->used_desc.prev &&
+ ioat_chan->used_desc.next == ioat_chan->used_desc.prev->prev) {
+
+ struct ioat_desc_sw *desc = NULL;
+ struct ioat_desc_sw *noop_desc = NULL;
+ int i;
+
+ /* set up the noop descriptor */
+ noop_desc = to_ioat_desc(ioat_chan->used_desc.next);
+ noop_desc->hw->size = 0;
+ noop_desc->hw->ctl = IOAT_DMA_DESCRIPTOR_NUL;
+ noop_desc->hw->src_addr = 0;
+ noop_desc->hw->dst_addr = 0;
+
+ ioat_chan->used_desc.next = ioat_chan->used_desc.next->next;
+ ioat_chan->pending++;
+ ioat_chan->dmacount++;
+
+ /* get a few more descriptors */
+ for (i = 16; i; i--) {
+ desc = ioat_dma_alloc_descriptor(ioat_chan, GFP_ATOMIC);
+ BUG_ON(!desc);
+ list_add_tail(&desc->node, ioat_chan->used_desc.next);
+
+ desc->hw->next
+ = to_ioat_desc(desc->node.next)->async_tx.phys;
+ to_ioat_desc(desc->node.prev)->hw->next
+ = desc->async_tx.phys;
+ ioat_chan->desccount++;
+ }
+
+ ioat_chan->used_desc.next = noop_desc->node.next;
+ }
+ new = to_ioat_desc(ioat_chan->used_desc.next);
+ prefetch(new);
+ ioat_chan->used_desc.next = new->node.next;
+
+ if (ioat_chan->used_desc.prev == NULL)
+ ioat_chan->used_desc.prev = &new->node;
+
+ prefetch(new->hw);
+ return new;
+}
+
+static struct ioat_desc_sw *ioat_dma_get_next_descriptor(
+ struct ioat_dma_chan *ioat_chan)
+{
+ if (!ioat_chan)
+ return NULL;
+
+ switch (ioat_chan->device->version) {
+ case IOAT_VER_1_2:
+ return ioat1_dma_get_next_descriptor(ioat_chan);
+ break;
+ case IOAT_VER_2_0:
+ return ioat2_dma_get_next_descriptor(ioat_chan);
+ break;
+ }
+ return NULL;
+}
+
+static struct dma_async_tx_descriptor *ioat1_dma_prep_memcpy(
+ struct dma_chan *chan,
+ size_t len,
+ int int_en)
+{
+ struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+ struct ioat_desc_sw *new;
+
+ spin_lock_bh(&ioat_chan->desc_lock);
+ new = ioat_dma_get_next_descriptor(ioat_chan);
+ new->len = len;
+ spin_unlock_bh(&ioat_chan->desc_lock);
+
+ return new ? &new->async_tx : NULL;
+}
+
+static struct dma_async_tx_descriptor *ioat2_dma_prep_memcpy(
+ struct dma_chan *chan,
+ size_t len,
+ int int_en)
+{
+ struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+ struct ioat_desc_sw *new;
+
+ spin_lock_bh(&ioat_chan->desc_lock);
+ new = ioat2_dma_get_next_descriptor(ioat_chan);
+ new->len = len;
+
+ /* leave ioat_chan->desc_lock set in version 2 path */
+ return new ? &new->async_tx : NULL;
+}
+
+
+/**
+ * ioat_dma_memcpy_issue_pending - push potentially unrecognized appended
+ * descriptors to hw
+ * @chan: DMA channel handle
+ */
+static inline void __ioat1_dma_memcpy_issue_pending(
+ struct ioat_dma_chan *ioat_chan)
+{
+ ioat_chan->pending = 0;
+ writeb(IOAT_CHANCMD_APPEND, ioat_chan->reg_base + IOAT1_CHANCMD_OFFSET);
+}
+
+static void ioat1_dma_memcpy_issue_pending(struct dma_chan *chan)
+{
+ struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+
+ if (ioat_chan->pending != 0) {
+ spin_lock_bh(&ioat_chan->desc_lock);
+ __ioat1_dma_memcpy_issue_pending(ioat_chan);
+ spin_unlock_bh(&ioat_chan->desc_lock);
+ }
+}
+
+static inline void __ioat2_dma_memcpy_issue_pending(
+ struct ioat_dma_chan *ioat_chan)
+{
+ ioat_chan->pending = 0;
+ writew(ioat_chan->dmacount,
+ ioat_chan->reg_base + IOAT_CHAN_DMACOUNT_OFFSET);
+}
+
+static void ioat2_dma_memcpy_issue_pending(struct dma_chan *chan)
+{
+ struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+
+ if (ioat_chan->pending != 0) {
+ spin_lock_bh(&ioat_chan->desc_lock);
+ __ioat2_dma_memcpy_issue_pending(ioat_chan);
+ spin_unlock_bh(&ioat_chan->desc_lock);
+ }
+}
+
+static void ioat_dma_cleanup_tasklet(unsigned long data)
+{
+ struct ioat_dma_chan *chan = (void *)data;
+ ioat_dma_memcpy_cleanup(chan);
+ writew(IOAT_CHANCTRL_INT_DISABLE,
+ chan->reg_base + IOAT_CHANCTRL_OFFSET);
+}
+
+/**
+ * ioat_dma_memcpy_cleanup - cleanup up finished descriptors
+ * @chan: ioat channel to be cleaned up
+ */
+static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan)
+{
+ unsigned long phys_complete;
+ struct ioat_desc_sw *desc, *_desc;
+ dma_cookie_t cookie = 0;
+ unsigned long desc_phys;
+ struct ioat_desc_sw *latest_desc;
+
+ prefetch(ioat_chan->completion_virt);
+
+ if (!spin_trylock_bh(&ioat_chan->cleanup_lock))
+ return;
+
+ /* The completion writeback can happen at any time,
+ so reads by the driver need to be atomic operations
+ The descriptor physical addresses are limited to 32-bits
+ when the CPU can only do a 32-bit mov */
+
+#if (BITS_PER_LONG == 64)
+ phys_complete =
+ ioat_chan->completion_virt->full
+ & IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR;
+#else
+ phys_complete =
+ ioat_chan->completion_virt->low & IOAT_LOW_COMPLETION_MASK;
+#endif
+
+ if ((ioat_chan->completion_virt->full
+ & IOAT_CHANSTS_DMA_TRANSFER_STATUS) ==
+ IOAT_CHANSTS_DMA_TRANSFER_STATUS_HALTED) {
+ dev_err(&ioat_chan->device->pdev->dev,
+ "Channel halted, chanerr = %x\n",
+ readl(ioat_chan->reg_base + IOAT_CHANERR_OFFSET));
+
+ /* TODO do something to salvage the situation */
+ }
+
+ if (phys_complete == ioat_chan->last_completion) {
+ spin_unlock_bh(&ioat_chan->cleanup_lock);
+ return;
+ }
+
+ cookie = 0;
+ spin_lock_bh(&ioat_chan->desc_lock);
+ switch (ioat_chan->device->version) {
+ case IOAT_VER_1_2:
+ list_for_each_entry_safe(desc, _desc,
+ &ioat_chan->used_desc, node) {
+
+ /*
+ * Incoming DMA requests may use multiple descriptors,
+ * due to exceeding xfercap, perhaps. If so, only the
+ * last one will have a cookie, and require unmapping.
+ */
+ if (desc->async_tx.cookie) {
+ cookie = desc->async_tx.cookie;
+
+ /*
+ * yes we are unmapping both _page and _single
+ * alloc'd regions with unmap_page. Is this
+ * *really* that bad?
+ */
+ pci_unmap_page(ioat_chan->device->pdev,
+ pci_unmap_addr(desc, dst),
+ pci_unmap_len(desc, len),
+ PCI_DMA_FROMDEVICE);
+ pci_unmap_page(ioat_chan->device->pdev,
+ pci_unmap_addr(desc, src),
+ pci_unmap_len(desc, len),
+ PCI_DMA_TODEVICE);
+
+ if (desc->async_tx.callback) {
+ desc->async_tx.callback(desc->async_tx.callback_param);
+ desc->async_tx.callback = NULL;
+ }
+ }
+
+ if (desc->async_tx.phys != phys_complete) {
+ /*
+ * a completed entry, but not the last, so clean
+ * up if the client is done with the descriptor
+ */
+ if (desc->async_tx.ack) {
+ list_del(&desc->node);
+ list_add_tail(&desc->node,
+ &ioat_chan->free_desc);
+ } else
+ desc->async_tx.cookie = 0;
+ } else {
+ /*
+ * last used desc. Do not remove, so we can
+ * append from it, but don't look at it next
+ * time, either
+ */
+ desc->async_tx.cookie = 0;
+
+ /* TODO check status bits? */
+ break;
+ }
+ }
+ break;
+ case IOAT_VER_2_0:
+ /* has some other thread has already cleaned up? */
+ if (ioat_chan->used_desc.prev == NULL)
+ break;
+
+ /* work backwards to find latest finished desc */
+ desc = to_ioat_desc(ioat_chan->used_desc.next);
+ latest_desc = NULL;
+ do {
+ desc = to_ioat_desc(desc->node.prev);
+ desc_phys = (unsigned long)desc->async_tx.phys
+ & IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR;
+ if (desc_phys == phys_complete) {
+ latest_desc = desc;
+ break;
+ }
+ } while (&desc->node != ioat_chan->used_desc.prev);
+
+ if (latest_desc != NULL) {
+
+ /* work forwards to clear finished descriptors */
+ for (desc = to_ioat_desc(ioat_chan->used_desc.prev);
+ &desc->node != latest_desc->node.next &&
+ &desc->node != ioat_chan->used_desc.next;
+ desc = to_ioat_desc(desc->node.next)) {
+ if (desc->async_tx.cookie) {
+ cookie = desc->async_tx.cookie;
+ desc->async_tx.cookie = 0;
+
+ pci_unmap_page(ioat_chan->device->pdev,
+ pci_unmap_addr(desc, dst),
+ pci_unmap_len(desc, len),
+ PCI_DMA_FROMDEVICE);
+ pci_unmap_page(ioat_chan->device->pdev,
+ pci_unmap_addr(desc, src),
+ pci_unmap_len(desc, len),
+ PCI_DMA_TODEVICE);
+
+ if (desc->async_tx.callback) {
+ desc->async_tx.callback(desc->async_tx.callback_param);
+ desc->async_tx.callback = NULL;
+ }
+ }
+ }
+
+ /* move used.prev up beyond those that are finished */
+ if (&desc->node == ioat_chan->used_desc.next)
+ ioat_chan->used_desc.prev = NULL;
+ else
+ ioat_chan->used_desc.prev = &desc->node;
+ }
+ break;
+ }
+
+ spin_unlock_bh(&ioat_chan->desc_lock);
+
+ ioat_chan->last_completion = phys_complete;
+ if (cookie != 0)
+ ioat_chan->completed_cookie = cookie;
+
+ spin_unlock_bh(&ioat_chan->cleanup_lock);
+}
+
+static void ioat_dma_dependency_added(struct dma_chan *chan)
+{
+ struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+ spin_lock_bh(&ioat_chan->desc_lock);
+ if (ioat_chan->pending == 0) {
+ spin_unlock_bh(&ioat_chan->desc_lock);
+ ioat_dma_memcpy_cleanup(ioat_chan);
+ } else
+ spin_unlock_bh(&ioat_chan->desc_lock);
+}
+
+/**
+ * ioat_dma_is_complete - poll the status of a IOAT DMA transaction
+ * @chan: IOAT DMA channel handle
+ * @cookie: DMA transaction identifier
+ * @done: if not %NULL, updated with last completed transaction
+ * @used: if not %NULL, updated with last used transaction
+ */
+static enum dma_status ioat_dma_is_complete(struct dma_chan *chan,
+ dma_cookie_t cookie,
+ dma_cookie_t *done,
+ dma_cookie_t *used)
+{
+ struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+ dma_cookie_t last_used;
+ dma_cookie_t last_complete;
+ enum dma_status ret;
+
+ last_used = chan->cookie;
+ last_complete = ioat_chan->completed_cookie;
+
+ if (done)
+ *done = last_complete;
+ if (used)
+ *used = last_used;
+
+ ret = dma_async_is_complete(cookie, last_complete, last_used);
+ if (ret == DMA_SUCCESS)
+ return ret;
+
+ ioat_dma_memcpy_cleanup(ioat_chan);
+
+ last_used = chan->cookie;
+ last_complete = ioat_chan->completed_cookie;
+
+ if (done)
+ *done = last_complete;
+ if (used)
+ *used = last_used;
+
+ return dma_async_is_complete(cookie, last_complete, last_used);
+}
+
+static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan)
+{
+ struct ioat_desc_sw *desc;
+
+ spin_lock_bh(&ioat_chan->desc_lock);
+
+ desc = ioat_dma_get_next_descriptor(ioat_chan);
+ desc->hw->ctl = IOAT_DMA_DESCRIPTOR_NUL
+ | IOAT_DMA_DESCRIPTOR_CTL_INT_GN
+ | IOAT_DMA_DESCRIPTOR_CTL_CP_STS;
+ desc->hw->size = 0;
+ desc->hw->src_addr = 0;
+ desc->hw->dst_addr = 0;
+ desc->async_tx.ack = 1;
+ switch (ioat_chan->device->version) {
+ case IOAT_VER_1_2:
+ desc->hw->next = 0;
+ list_add_tail(&desc->node, &ioat_chan->used_desc);
+
+ writel(((u64) desc->async_tx.phys) & 0x00000000FFFFFFFF,
+ ioat_chan->reg_base + IOAT1_CHAINADDR_OFFSET_LOW);
+ writel(((u64) desc->async_tx.phys) >> 32,
+ ioat_chan->reg_base + IOAT1_CHAINADDR_OFFSET_HIGH);
+
+ writeb(IOAT_CHANCMD_START, ioat_chan->reg_base
+ + IOAT_CHANCMD_OFFSET(ioat_chan->device->version));
+ break;
+ case IOAT_VER_2_0:
+ writel(((u64) desc->async_tx.phys) & 0x00000000FFFFFFFF,
+ ioat_chan->reg_base + IOAT2_CHAINADDR_OFFSET_LOW);
+ writel(((u64) desc->async_tx.phys) >> 32,
+ ioat_chan->reg_base + IOAT2_CHAINADDR_OFFSET_HIGH);
+
+ ioat_chan->dmacount++;
+ __ioat2_dma_memcpy_issue_pending(ioat_chan);
+ break;
+ }
+ spin_unlock_bh(&ioat_chan->desc_lock);
+}
+
+/*
+ * Perform a IOAT transaction to verify the HW works.
+ */
+#define IOAT_TEST_SIZE 2000
+
+static void ioat_dma_test_callback(void *dma_async_param)
+{
+ printk(KERN_ERR "ioatdma: ioat_dma_test_callback(%p)\n",
+ dma_async_param);
+}
+
+/**
+ * ioat_dma_self_test - Perform a IOAT transaction to verify the HW works.
+ * @device: device to be tested
+ */
+static int ioat_dma_self_test(struct ioatdma_device *device)
+{
+ int i;
+ u8 *src;
+ u8 *dest;
+ struct dma_chan *dma_chan;
+ struct dma_async_tx_descriptor *tx = NULL;
+ dma_addr_t addr;
+ dma_cookie_t cookie;
+ int err = 0;
+
+ src = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, GFP_KERNEL);
+ if (!src)
+ return -ENOMEM;
+ dest = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, GFP_KERNEL);
+ if (!dest) {
+ kfree(src);
+ return -ENOMEM;
+ }
+
+ /* Fill in src buffer */
+ for (i = 0; i < IOAT_TEST_SIZE; i++)
+ src[i] = (u8)i;
+
+ /* Start copy, using first DMA channel */
+ dma_chan = container_of(device->common.channels.next,
+ struct dma_chan,
+ device_node);
+ if (device->common.device_alloc_chan_resources(dma_chan) < 1) {
+ dev_err(&device->pdev->dev,
+ "selftest cannot allocate chan resource\n");
+ err = -ENODEV;
+ goto out;
+ }
+
+ tx = device->common.device_prep_dma_memcpy(dma_chan, IOAT_TEST_SIZE, 0);
+ if (!tx) {
+ dev_err(&device->pdev->dev,
+ "Self-test prep failed, disabling\n");
+ err = -ENODEV;
+ goto free_resources;
+ }
+
+ async_tx_ack(tx);
+ addr = dma_map_single(dma_chan->device->dev, src, IOAT_TEST_SIZE,
+ DMA_TO_DEVICE);
+ tx->tx_set_src(addr, tx, 0);
+ addr = dma_map_single(dma_chan->device->dev, dest, IOAT_TEST_SIZE,
+ DMA_FROM_DEVICE);
+ tx->tx_set_dest(addr, tx, 0);
+ tx->callback = ioat_dma_test_callback;
+ tx->callback_param = (void *)0x8086;
+ cookie = tx->tx_submit(tx);
+ if (cookie < 0) {
+ dev_err(&device->pdev->dev,
+ "Self-test setup failed, disabling\n");
+ err = -ENODEV;
+ goto free_resources;
+ }
+ device->common.device_issue_pending(dma_chan);
+ msleep(1);
+
+ if (device->common.device_is_tx_complete(dma_chan, cookie, NULL, NULL)
+ != DMA_SUCCESS) {
+ dev_err(&device->pdev->dev,
+ "Self-test copy timed out, disabling\n");
+ err = -ENODEV;
+ goto free_resources;
+ }
+ if (memcmp(src, dest, IOAT_TEST_SIZE)) {
+ dev_err(&device->pdev->dev,
+ "Self-test copy failed compare, disabling\n");
+ err = -ENODEV;
+ goto free_resources;
+ }
+
+free_resources:
+ device->common.device_free_chan_resources(dma_chan);
+out:
+ kfree(src);
+ kfree(dest);
+ return err;
+}
+
+static char ioat_interrupt_style[32] = "msix";
+module_param_string(ioat_interrupt_style, ioat_interrupt_style,
+ sizeof(ioat_interrupt_style), 0644);
+MODULE_PARM_DESC(ioat_interrupt_style,
+ "set ioat interrupt style: msix (default), "
+ "msix-single-vector, msi, intx)");
+
+/**
+ * ioat_dma_setup_interrupts - setup interrupt handler
+ * @device: ioat device
+ */
+static int ioat_dma_setup_interrupts(struct ioatdma_device *device)
+{
+ struct ioat_dma_chan *ioat_chan;
+ int err, i, j, msixcnt;
+ u8 intrctrl = 0;
+
+ if (!strcmp(ioat_interrupt_style, "msix"))
+ goto msix;
+ if (!strcmp(ioat_interrupt_style, "msix-single-vector"))
+ goto msix_single_vector;
+ if (!strcmp(ioat_interrupt_style, "msi"))
+ goto msi;
+ if (!strcmp(ioat_interrupt_style, "intx"))
+ goto intx;
+ dev_err(&device->pdev->dev, "invalid ioat_interrupt_style %s\n",
+ ioat_interrupt_style);
+ goto err_no_irq;
+
+msix:
+ /* The number of MSI-X vectors should equal the number of channels */
+ msixcnt = device->common.chancnt;
+ for (i = 0; i < msixcnt; i++)
+ device->msix_entries[i].entry = i;
+
+ err = pci_enable_msix(device->pdev, device->msix_entries, msixcnt);
+ if (err < 0)
+ goto msi;
+ if (err > 0)
+ goto msix_single_vector;
+
+ for (i = 0; i < msixcnt; i++) {
+ ioat_chan = ioat_lookup_chan_by_index(device, i);
+ err = request_irq(device->msix_entries[i].vector,
+ ioat_dma_do_interrupt_msix,
+ 0, "ioat-msix", ioat_chan);
+ if (err) {
+ for (j = 0; j < i; j++) {
+ ioat_chan =
+ ioat_lookup_chan_by_index(device, j);
+ free_irq(device->msix_entries[j].vector,
+ ioat_chan);
+ }
+ goto msix_single_vector;
+ }
+ }
+ intrctrl |= IOAT_INTRCTRL_MSIX_VECTOR_CONTROL;
+ device->irq_mode = msix_multi_vector;
+ goto done;
+
+msix_single_vector:
+ device->msix_entries[0].entry = 0;
+ err = pci_enable_msix(device->pdev, device->msix_entries, 1);
+ if (err)
+ goto msi;
+
+ err = request_irq(device->msix_entries[0].vector, ioat_dma_do_interrupt,
+ 0, "ioat-msix", device);
+ if (err) {
+ pci_disable_msix(device->pdev);
+ goto msi;
+ }
+ device->irq_mode = msix_single_vector;
+ goto done;
+
+msi:
+ err = pci_enable_msi(device->pdev);
+ if (err)
+ goto intx;
+
+ err = request_irq(device->pdev->irq, ioat_dma_do_interrupt,
+ 0, "ioat-msi", device);
+ if (err) {
+ pci_disable_msi(device->pdev);
+ goto intx;
+ }
+ /*
+ * CB 1.2 devices need a bit set in configuration space to enable MSI
+ */
+ if (device->version == IOAT_VER_1_2) {
+ u32 dmactrl;
+ pci_read_config_dword(device->pdev,
+ IOAT_PCI_DMACTRL_OFFSET, &dmactrl);
+ dmactrl |= IOAT_PCI_DMACTRL_MSI_EN;
+ pci_write_config_dword(device->pdev,
+ IOAT_PCI_DMACTRL_OFFSET, dmactrl);
+ }
+ device->irq_mode = msi;
+ goto done;
+
+intx:
+ err = request_irq(device->pdev->irq, ioat_dma_do_interrupt,
+ IRQF_SHARED, "ioat-intx", device);
+ if (err)
+ goto err_no_irq;
+ device->irq_mode = intx;
+
+done:
+ intrctrl |= IOAT_INTRCTRL_MASTER_INT_EN;
+ writeb(intrctrl, device->reg_base + IOAT_INTRCTRL_OFFSET);
+ return 0;
+
+err_no_irq:
+ /* Disable all interrupt generation */
+ writeb(0, device->reg_base + IOAT_INTRCTRL_OFFSET);
+ dev_err(&device->pdev->dev, "no usable interrupts\n");
+ device->irq_mode = none;
+ return -1;
+}
+
+/**
+ * ioat_dma_remove_interrupts - remove whatever interrupts were set
+ * @device: ioat device
+ */
+static void ioat_dma_remove_interrupts(struct ioatdma_device *device)
+{
+ struct ioat_dma_chan *ioat_chan;
+ int i;
+
+ /* Disable all interrupt generation */
+ writeb(0, device->reg_base + IOAT_INTRCTRL_OFFSET);
+
+ switch (device->irq_mode) {
+ case msix_multi_vector:
+ for (i = 0; i < device->common.chancnt; i++) {
+ ioat_chan = ioat_lookup_chan_by_index(device, i);
+ free_irq(device->msix_entries[i].vector, ioat_chan);
+ }
+ pci_disable_msix(device->pdev);
+ break;
+ case msix_single_vector:
+ free_irq(device->msix_entries[0].vector, device);
+ pci_disable_msix(device->pdev);
+ break;
+ case msi:
+ free_irq(device->pdev->irq, device);
+ pci_disable_msi(device->pdev);
+ break;
+ case intx:
+ free_irq(device->pdev->irq, device);
+ break;
+ case none:
+ dev_warn(&device->pdev->dev,
+ "call to %s without interrupts setup\n", __func__);
+ }
+ device->irq_mode = none;
+}
+
+struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev,
+ void __iomem *iobase)
+{
+ int err;
+ struct ioatdma_device *device;
+
+ device = kzalloc(sizeof(*device), GFP_KERNEL);
+ if (!device) {
+ err = -ENOMEM;
+ goto err_kzalloc;
+ }
+ device->pdev = pdev;
+ device->reg_base = iobase;
+ device->version = readb(device->reg_base + IOAT_VER_OFFSET);
+
+ /* DMA coherent memory pool for DMA descriptor allocations */
+ device->dma_pool = pci_pool_create("dma_desc_pool", pdev,
+ sizeof(struct ioat_dma_descriptor),
+ 64, 0);
+ if (!device->dma_pool) {
+ err = -ENOMEM;
+ goto err_dma_pool;
+ }
+
+ device->completion_pool = pci_pool_create("completion_pool", pdev,
+ sizeof(u64), SMP_CACHE_BYTES,
+ SMP_CACHE_BYTES);
+ if (!device->completion_pool) {
+ err = -ENOMEM;
+ goto err_completion_pool;
+ }
+
+ INIT_LIST_HEAD(&device->common.channels);
+ ioat_dma_enumerate_channels(device);
+
+ device->common.device_alloc_chan_resources =
+ ioat_dma_alloc_chan_resources;
+ device->common.device_free_chan_resources =
+ ioat_dma_free_chan_resources;
+ device->common.dev = &pdev->dev;
+
+ dma_cap_set(DMA_MEMCPY, device->common.cap_mask);
+ device->common.device_is_tx_complete = ioat_dma_is_complete;
+ device->common.device_dependency_added = ioat_dma_dependency_added;
+ switch (device->version) {
+ case IOAT_VER_1_2:
+ device->common.device_prep_dma_memcpy = ioat1_dma_prep_memcpy;
+ device->common.device_issue_pending =
+ ioat1_dma_memcpy_issue_pending;
+ break;
+ case IOAT_VER_2_0:
+ device->common.device_prep_dma_memcpy = ioat2_dma_prep_memcpy;
+ device->common.device_issue_pending =
+ ioat2_dma_memcpy_issue_pending;
+ break;
+ }
+
+ dev_err(&device->pdev->dev,
+ "Intel(R) I/OAT DMA Engine found,"
+ " %d channels, device version 0x%02x, driver version %s\n",
+ device->common.chancnt, device->version, IOAT_DMA_VERSION);
+
+ err = ioat_dma_setup_interrupts(device);
+ if (err)
+ goto err_setup_interrupts;
+
+ err = ioat_dma_self_test(device);
+ if (err)
+ goto err_self_test;
+
+ dma_async_device_register(&device->common);
+
+ return device;
+
+err_self_test:
+ ioat_dma_remove_interrupts(device);
+err_setup_interrupts:
+ pci_pool_destroy(device->completion_pool);
+err_completion_pool:
+ pci_pool_destroy(device->dma_pool);
+err_dma_pool:
+ kfree(device);
+err_kzalloc:
+ dev_err(&device->pdev->dev,
+ "Intel(R) I/OAT DMA Engine initialization failed\n");
+ return NULL;
+}
+
+void ioat_dma_remove(struct ioatdma_device *device)
+{
+ struct dma_chan *chan, *_chan;
+ struct ioat_dma_chan *ioat_chan;
+
+ ioat_dma_remove_interrupts(device);
+
+ dma_async_device_unregister(&device->common);
+
+ pci_pool_destroy(device->dma_pool);
+ pci_pool_destroy(device->completion_pool);
+
+ iounmap(device->reg_base);
+ pci_release_regions(device->pdev);
+ pci_disable_device(device->pdev);
+
+ list_for_each_entry_safe(chan, _chan,
+ &device->common.channels, device_node) {
+ ioat_chan = to_ioat_chan(chan);
+ list_del(&chan->device_node);
+ kfree(ioat_chan);
+ }
+ kfree(device);
+}
+
diff --git a/drivers/dma/ioatdma.c b/drivers/dma/ioatdma.c
deleted file mode 100644
index 41b18c5a3141..000000000000
--- a/drivers/dma/ioatdma.c
+++ /dev/null
@@ -1,817 +0,0 @@
-/*
- * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called COPYING.
- */
-
-/*
- * This driver supports an Intel I/OAT DMA engine, which does asynchronous
- * copy operations.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/dmaengine.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include "ioatdma.h"
-#include "ioatdma_registers.h"
-#include "ioatdma_hw.h"
-
-#define to_ioat_chan(chan) container_of(chan, struct ioat_dma_chan, common)
-#define to_ioat_device(dev) container_of(dev, struct ioat_device, common)
-#define to_ioat_desc(lh) container_of(lh, struct ioat_desc_sw, node)
-#define tx_to_ioat_desc(tx) container_of(tx, struct ioat_desc_sw, async_tx)
-
-/* internal functions */
-static int __devinit ioat_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
-static void ioat_shutdown(struct pci_dev *pdev);
-static void __devexit ioat_remove(struct pci_dev *pdev);
-
-static int enumerate_dma_channels(struct ioat_device *device)
-{
- u8 xfercap_scale;
- u32 xfercap;
- int i;
- struct ioat_dma_chan *ioat_chan;
-
- device->common.chancnt = readb(device->reg_base + IOAT_CHANCNT_OFFSET);
- xfercap_scale = readb(device->reg_base + IOAT_XFERCAP_OFFSET);
- xfercap = (xfercap_scale == 0 ? -1 : (1UL << xfercap_scale));
-
- for (i = 0; i < device->common.chancnt; i++) {
- ioat_chan = kzalloc(sizeof(*ioat_chan), GFP_KERNEL);
- if (!ioat_chan) {
- device->common.chancnt = i;
- break;
- }
-
- ioat_chan->device = device;
- ioat_chan->reg_base = device->reg_base + (0x80 * (i + 1));
- ioat_chan->xfercap = xfercap;
- spin_lock_init(&ioat_chan->cleanup_lock);
- spin_lock_init(&ioat_chan->desc_lock);
- INIT_LIST_HEAD(&ioat_chan->free_desc);
- INIT_LIST_HEAD(&ioat_chan->used_desc);
- /* This should be made common somewhere in dmaengine.c */
- ioat_chan->common.device = &device->common;
- list_add_tail(&ioat_chan->common.device_node,
- &device->common.channels);
- }
- return device->common.chancnt;
-}
-
-static void
-ioat_set_src(dma_addr_t addr, struct dma_async_tx_descriptor *tx, int index)
-{
- struct ioat_desc_sw *iter, *desc = tx_to_ioat_desc(tx);
- struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan);
-
- pci_unmap_addr_set(desc, src, addr);
-
- list_for_each_entry(iter, &desc->async_tx.tx_list, node) {
- iter->hw->src_addr = addr;
- addr += ioat_chan->xfercap;
- }
-
-}
-
-static void
-ioat_set_dest(dma_addr_t addr, struct dma_async_tx_descriptor *tx, int index)
-{
- struct ioat_desc_sw *iter, *desc = tx_to_ioat_desc(tx);
- struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan);
-
- pci_unmap_addr_set(desc, dst, addr);
-
- list_for_each_entry(iter, &desc->async_tx.tx_list, node) {
- iter->hw->dst_addr = addr;
- addr += ioat_chan->xfercap;
- }
-}
-
-static dma_cookie_t
-ioat_tx_submit(struct dma_async_tx_descriptor *tx)
-{
- struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan);
- struct ioat_desc_sw *desc = tx_to_ioat_desc(tx);
- int append = 0;
- dma_cookie_t cookie;
- struct ioat_desc_sw *group_start;
-
- group_start = list_entry(desc->async_tx.tx_list.next,
- struct ioat_desc_sw, node);
- spin_lock_bh(&ioat_chan->desc_lock);
- /* cookie incr and addition to used_list must be atomic */
- cookie = ioat_chan->common.cookie;
- cookie++;
- if (cookie < 0)
- cookie = 1;
- ioat_chan->common.cookie = desc->async_tx.cookie = cookie;
-
- /* write address into NextDescriptor field of last desc in chain */
- to_ioat_desc(ioat_chan->used_desc.prev)->hw->next =
- group_start->async_tx.phys;
- list_splice_init(&desc->async_tx.tx_list, ioat_chan->used_desc.prev);
-
- ioat_chan->pending += desc->tx_cnt;
- if (ioat_chan->pending >= 4) {
- append = 1;
- ioat_chan->pending = 0;
- }
- spin_unlock_bh(&ioat_chan->desc_lock);
-
- if (append)
- writeb(IOAT_CHANCMD_APPEND,
- ioat_chan->reg_base + IOAT_CHANCMD_OFFSET);
-
- return cookie;
-}
-
-static struct ioat_desc_sw *ioat_dma_alloc_descriptor(
- struct ioat_dma_chan *ioat_chan,
- gfp_t flags)
-{
- struct ioat_dma_descriptor *desc;
- struct ioat_desc_sw *desc_sw;
- struct ioat_device *ioat_device;
- dma_addr_t phys;
-
- ioat_device = to_ioat_device(ioat_chan->common.device);
- desc = pci_pool_alloc(ioat_device->dma_pool, flags, &phys);
- if (unlikely(!desc))
- return NULL;
-
- desc_sw = kzalloc(sizeof(*desc_sw), flags);
- if (unlikely(!desc_sw)) {
- pci_pool_free(ioat_device->dma_pool, desc, phys);
- return NULL;
- }
-
- memset(desc, 0, sizeof(*desc));
- dma_async_tx_descriptor_init(&desc_sw->async_tx, &ioat_chan->common);
- desc_sw->async_tx.tx_set_src = ioat_set_src;
- desc_sw->async_tx.tx_set_dest = ioat_set_dest;
- desc_sw->async_tx.tx_submit = ioat_tx_submit;
- INIT_LIST_HEAD(&desc_sw->async_tx.tx_list);
- desc_sw->hw = desc;
- desc_sw->async_tx.phys = phys;
-
- return desc_sw;
-}
-
-#define INITIAL_IOAT_DESC_COUNT 128
-
-static void ioat_start_null_desc(struct ioat_dma_chan *ioat_chan);
-
-/* returns the actual number of allocated descriptors */
-static int ioat_dma_alloc_chan_resources(struct dma_chan *chan)
-{
- struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
- struct ioat_desc_sw *desc = NULL;
- u16 chanctrl;
- u32 chanerr;
- int i;
- LIST_HEAD(tmp_list);
-
- /* have we already been set up? */
- if (!list_empty(&ioat_chan->free_desc))
- return INITIAL_IOAT_DESC_COUNT;
-
- /* Setup register to interrupt and write completion status on error */
- chanctrl = IOAT_CHANCTRL_ERR_INT_EN |
- IOAT_CHANCTRL_ANY_ERR_ABORT_EN |
- IOAT_CHANCTRL_ERR_COMPLETION_EN;
- writew(chanctrl, ioat_chan->reg_base + IOAT_CHANCTRL_OFFSET);
-
- chanerr = readl(ioat_chan->reg_base + IOAT_CHANERR_OFFSET);
- if (chanerr) {
- printk("IOAT: CHANERR = %x, clearing\n", chanerr);
- writel(chanerr, ioat_chan->reg_base + IOAT_CHANERR_OFFSET);
- }
-
- /* Allocate descriptors */
- for (i = 0; i < INITIAL_IOAT_DESC_COUNT; i++) {
- desc = ioat_dma_alloc_descriptor(ioat_chan, GFP_KERNEL);
- if (!desc) {
- printk(KERN_ERR "IOAT: Only %d initial descriptors\n", i);
- break;
- }
- list_add_tail(&desc->node, &tmp_list);
- }
- spin_lock_bh(&ioat_chan->desc_lock);
- list_splice(&tmp_list, &ioat_chan->free_desc);
- spin_unlock_bh(&ioat_chan->desc_lock);
-
- /* allocate a completion writeback area */
- /* doing 2 32bit writes to mmio since 1 64b write doesn't work */
- ioat_chan->completion_virt =
- pci_pool_alloc(ioat_chan->device->completion_pool,
- GFP_KERNEL,
- &ioat_chan->completion_addr);
- memset(ioat_chan->completion_virt, 0,
- sizeof(*ioat_chan->completion_virt));
- writel(((u64) ioat_chan->completion_addr) & 0x00000000FFFFFFFF,
- ioat_chan->reg_base + IOAT_CHANCMP_OFFSET_LOW);
- writel(((u64) ioat_chan->completion_addr) >> 32,
- ioat_chan->reg_base + IOAT_CHANCMP_OFFSET_HIGH);
-
- ioat_start_null_desc(ioat_chan);
- return i;
-}
-
-static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan);
-
-static void ioat_dma_free_chan_resources(struct dma_chan *chan)
-{
- struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
- struct ioat_device *ioat_device = to_ioat_device(chan->device);
- struct ioat_desc_sw *desc, *_desc;
- u16 chanctrl;
- int in_use_descs = 0;
-
- ioat_dma_memcpy_cleanup(ioat_chan);
-
- writeb(IOAT_CHANCMD_RESET, ioat_chan->reg_base + IOAT_CHANCMD_OFFSET);
-
- spin_lock_bh(&ioat_chan->desc_lock);
- list_for_each_entry_safe(desc, _desc, &ioat_chan->used_desc, node) {
- in_use_descs++;
- list_del(&desc->node);
- pci_pool_free(ioat_device->dma_pool, desc->hw,
- desc->async_tx.phys);
- kfree(desc);
- }
- list_for_each_entry_safe(desc, _desc, &ioat_chan->free_desc, node) {
- list_del(&desc->node);
- pci_pool_free(ioat_device->dma_pool, desc->hw,
- desc->async_tx.phys);
- kfree(desc);
- }
- spin_unlock_bh(&ioat_chan->desc_lock);
-
- pci_pool_free(ioat_device->completion_pool,
- ioat_chan->completion_virt,
- ioat_chan->completion_addr);
-
- /* one is ok since we left it on there on purpose */
- if (in_use_descs > 1)
- printk(KERN_ERR "IOAT: Freeing %d in use descriptors!\n",
- in_use_descs - 1);
-
- ioat_chan->last_completion = ioat_chan->completion_addr = 0;
-}
-
-static struct dma_async_tx_descriptor *
-ioat_dma_prep_memcpy(struct dma_chan *chan, size_t len, int int_en)
-{
- struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
- struct ioat_desc_sw *first, *prev, *new;
- LIST_HEAD(new_chain);
- u32 copy;
- size_t orig_len;
- int desc_count = 0;
-
- if (!len)
- return NULL;
-
- orig_len = len;
-
- first = NULL;
- prev = NULL;
-
- spin_lock_bh(&ioat_chan->desc_lock);
- while (len) {
- if (!list_empty(&ioat_chan->free_desc)) {
- new = to_ioat_desc(ioat_chan->free_desc.next);
- list_del(&new->node);
- } else {
- /* try to get another desc */
- new = ioat_dma_alloc_descriptor(ioat_chan, GFP_ATOMIC);
- /* will this ever happen? */
- /* TODO add upper limit on these */
- BUG_ON(!new);
- }
-
- copy = min((u32) len, ioat_chan->xfercap);
-
- new->hw->size = copy;
- new->hw->ctl = 0;
- new->async_tx.cookie = 0;
- new->async_tx.ack = 1;
-
- /* chain together the physical address list for the HW */
- if (!first)
- first = new;
- else
- prev->hw->next = (u64) new->async_tx.phys;
-
- prev = new;
- len -= copy;
- list_add_tail(&new->node, &new_chain);
- desc_count++;
- }
-
- list_splice(&new_chain, &new->async_tx.tx_list);
-
- new->hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS;
- new->hw->next = 0;
- new->tx_cnt = desc_count;
- new->async_tx.ack = 0; /* client is in control of this ack */
- new->async_tx.cookie = -EBUSY;
-
- pci_unmap_len_set(new, len, orig_len);
- spin_unlock_bh(&ioat_chan->desc_lock);
-
- return new ? &new->async_tx : NULL;
-}
-
-
-/**
- * ioat_dma_memcpy_issue_pending - push potentially unrecognized appended descriptors to hw
- * @chan: DMA channel handle
- */
-
-static void ioat_dma_memcpy_issue_pending(struct dma_chan *chan)
-{
- struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
-
- if (ioat_chan->pending != 0) {
- ioat_chan->pending = 0;
- writeb(IOAT_CHANCMD_APPEND,
- ioat_chan->reg_base + IOAT_CHANCMD_OFFSET);
- }
-}
-
-static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *chan)
-{
- unsigned long phys_complete;
- struct ioat_desc_sw *desc, *_desc;
- dma_cookie_t cookie = 0;
-
- prefetch(chan->completion_virt);
-
- if (!spin_trylock(&chan->cleanup_lock))
- return;
-
- /* The completion writeback can happen at any time,
- so reads by the driver need to be atomic operations
- The descriptor physical addresses are limited to 32-bits
- when the CPU can only do a 32-bit mov */
-
-#if (BITS_PER_LONG == 64)
- phys_complete =
- chan->completion_virt->full & IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR;
-#else
- phys_complete = chan->completion_virt->low & IOAT_LOW_COMPLETION_MASK;
-#endif
-
- if ((chan->completion_virt->full & IOAT_CHANSTS_DMA_TRANSFER_STATUS) ==
- IOAT_CHANSTS_DMA_TRANSFER_STATUS_HALTED) {
- printk("IOAT: Channel halted, chanerr = %x\n",
- readl(chan->reg_base + IOAT_CHANERR_OFFSET));
-
- /* TODO do something to salvage the situation */
- }
-
- if (phys_complete == chan->last_completion) {
- spin_unlock(&chan->cleanup_lock);
- return;
- }
-
- spin_lock_bh(&chan->desc_lock);
- list_for_each_entry_safe(desc, _desc, &chan->used_desc, node) {
-
- /*
- * Incoming DMA requests may use multiple descriptors, due to
- * exceeding xfercap, perhaps. If so, only the last one will
- * have a cookie, and require unmapping.
- */
- if (desc->async_tx.cookie) {
- cookie = desc->async_tx.cookie;
-
- /* yes we are unmapping both _page and _single alloc'd
- regions with unmap_page. Is this *really* that bad?
- */
- pci_unmap_page(chan->device->pdev,
- pci_unmap_addr(desc, dst),
- pci_unmap_len(desc, len),
- PCI_DMA_FROMDEVICE);
- pci_unmap_page(chan->device->pdev,
- pci_unmap_addr(desc, src),
- pci_unmap_len(desc, len),
- PCI_DMA_TODEVICE);
- }
-
- if (desc->async_tx.phys != phys_complete) {
- /* a completed entry, but not the last, so cleanup
- * if the client is done with the descriptor
- */
- if (desc->async_tx.ack) {
- list_del(&desc->node);
- list_add_tail(&desc->node, &chan->free_desc);
- } else
- desc->async_tx.cookie = 0;
- } else {
- /* last used desc. Do not remove, so we can append from
- it, but don't look at it next time, either */
- desc->async_tx.cookie = 0;
-
- /* TODO check status bits? */
- break;
- }
- }
-
- spin_unlock_bh(&chan->desc_lock);
-
- chan->last_completion = phys_complete;
- if (cookie != 0)
- chan->completed_cookie = cookie;
-
- spin_unlock(&chan->cleanup_lock);
-}
-
-static void ioat_dma_dependency_added(struct dma_chan *chan)
-{
- struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
- spin_lock_bh(&ioat_chan->desc_lock);
- if (ioat_chan->pending == 0) {
- spin_unlock_bh(&ioat_chan->desc_lock);
- ioat_dma_memcpy_cleanup(ioat_chan);
- } else
- spin_unlock_bh(&ioat_chan->desc_lock);
-}
-
-/**
- * ioat_dma_is_complete - poll the status of a IOAT DMA transaction
- * @chan: IOAT DMA channel handle
- * @cookie: DMA transaction identifier
- * @done: if not %NULL, updated with last completed transaction
- * @used: if not %NULL, updated with last used transaction
- */
-
-static enum dma_status ioat_dma_is_complete(struct dma_chan *chan,
- dma_cookie_t cookie,
- dma_cookie_t *done,
- dma_cookie_t *used)
-{
- struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
- dma_cookie_t last_used;
- dma_cookie_t last_complete;
- enum dma_status ret;
-
- last_used = chan->cookie;
- last_complete = ioat_chan->completed_cookie;
-
- if (done)
- *done= last_complete;
- if (used)
- *used = last_used;
-
- ret = dma_async_is_complete(cookie, last_complete, last_used);
- if (ret == DMA_SUCCESS)
- return ret;
-
- ioat_dma_memcpy_cleanup(ioat_chan);
-
- last_used = chan->cookie;
- last_complete = ioat_chan->completed_cookie;
-
- if (done)
- *done= last_complete;
- if (used)
- *used = last_used;
-
- return dma_async_is_complete(cookie, last_complete, last_used);
-}
-
-/* PCI API */
-
-static struct pci_device_id ioat_pci_tbl[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT) },
- { PCI_DEVICE(PCI_VENDOR_ID_UNISYS,
- PCI_DEVICE_ID_UNISYS_DMA_DIRECTOR) },
- { 0, }
-};
-
-static struct pci_driver ioat_pci_driver = {
- .name = "ioatdma",
- .id_table = ioat_pci_tbl,
- .probe = ioat_probe,
- .shutdown = ioat_shutdown,
- .remove = __devexit_p(ioat_remove),
-};
-
-static irqreturn_t ioat_do_interrupt(int irq, void *data)
-{
- struct ioat_device *instance = data;
- unsigned long attnstatus;
- u8 intrctrl;
-
- intrctrl = readb(instance->reg_base + IOAT_INTRCTRL_OFFSET);
-
- if (!(intrctrl & IOAT_INTRCTRL_MASTER_INT_EN))
- return IRQ_NONE;
-
- if (!(intrctrl & IOAT_INTRCTRL_INT_STATUS)) {
- writeb(intrctrl, instance->reg_base + IOAT_INTRCTRL_OFFSET);
- return IRQ_NONE;
- }
-
- attnstatus = readl(instance->reg_base + IOAT_ATTNSTATUS_OFFSET);
-
- printk(KERN_ERR "ioatdma error: interrupt! status %lx\n", attnstatus);
-
- writeb(intrctrl, instance->reg_base + IOAT_INTRCTRL_OFFSET);
- return IRQ_HANDLED;
-}
-
-static void ioat_start_null_desc(struct ioat_dma_chan *ioat_chan)
-{
- struct ioat_desc_sw *desc;
-
- spin_lock_bh(&ioat_chan->desc_lock);
-
- if (!list_empty(&ioat_chan->free_desc)) {
- desc = to_ioat_desc(ioat_chan->free_desc.next);
- list_del(&desc->node);
- } else {
- /* try to get another desc */
- spin_unlock_bh(&ioat_chan->desc_lock);
- desc = ioat_dma_alloc_descriptor(ioat_chan, GFP_KERNEL);
- spin_lock_bh(&ioat_chan->desc_lock);
- /* will this ever happen? */
- BUG_ON(!desc);
- }
-
- desc->hw->ctl = IOAT_DMA_DESCRIPTOR_NUL;
- desc->hw->next = 0;
- desc->async_tx.ack = 1;
-
- list_add_tail(&desc->node, &ioat_chan->used_desc);
- spin_unlock_bh(&ioat_chan->desc_lock);
-
- writel(((u64) desc->async_tx.phys) & 0x00000000FFFFFFFF,
- ioat_chan->reg_base + IOAT_CHAINADDR_OFFSET_LOW);
- writel(((u64) desc->async_tx.phys) >> 32,
- ioat_chan->reg_base + IOAT_CHAINADDR_OFFSET_HIGH);
-
- writeb(IOAT_CHANCMD_START, ioat_chan->reg_base + IOAT_CHANCMD_OFFSET);
-}
-
-/*
- * Perform a IOAT transaction to verify the HW works.
- */
-#define IOAT_TEST_SIZE 2000
-
-static int ioat_self_test(struct ioat_device *device)
-{
- int i;
- u8 *src;
- u8 *dest;
- struct dma_chan *dma_chan;
- struct dma_async_tx_descriptor *tx;
- dma_addr_t addr;
- dma_cookie_t cookie;
- int err = 0;
-
- src = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, GFP_KERNEL);
- if (!src)
- return -ENOMEM;
- dest = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, GFP_KERNEL);
- if (!dest) {
- kfree(src);
- return -ENOMEM;
- }
-
- /* Fill in src buffer */
- for (i = 0; i < IOAT_TEST_SIZE; i++)
- src[i] = (u8)i;
-
- /* Start copy, using first DMA channel */
- dma_chan = container_of(device->common.channels.next,
- struct dma_chan,
- device_node);
- if (ioat_dma_alloc_chan_resources(dma_chan) < 1) {
- err = -ENODEV;
- goto out;
- }
-
- tx = ioat_dma_prep_memcpy(dma_chan, IOAT_TEST_SIZE, 0);
- async_tx_ack(tx);
- addr = dma_map_single(dma_chan->device->dev, src, IOAT_TEST_SIZE,
- DMA_TO_DEVICE);
- ioat_set_src(addr, tx, 0);
- addr = dma_map_single(dma_chan->device->dev, dest, IOAT_TEST_SIZE,
- DMA_FROM_DEVICE);
- ioat_set_dest(addr, tx, 0);
- cookie = ioat_tx_submit(tx);
- ioat_dma_memcpy_issue_pending(dma_chan);
- msleep(1);
-
- if (ioat_dma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {
- printk(KERN_ERR "ioatdma: Self-test copy timed out, disabling\n");
- err = -ENODEV;
- goto free_resources;
- }
- if (memcmp(src, dest, IOAT_TEST_SIZE)) {
- printk(KERN_ERR "ioatdma: Self-test copy failed compare, disabling\n");
- err = -ENODEV;
- goto free_resources;
- }
-
-free_resources:
- ioat_dma_free_chan_resources(dma_chan);
-out:
- kfree(src);
- kfree(dest);
- return err;
-}
-
-static int __devinit ioat_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
-{
- int err;
- unsigned long mmio_start, mmio_len;
- void __iomem *reg_base;
- struct ioat_device *device;
-
- err = pci_enable_device(pdev);
- if (err)
- goto err_enable_device;
-
- err = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
- if (err)
- err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
- if (err)
- goto err_set_dma_mask;
-
- err = pci_request_regions(pdev, ioat_pci_driver.name);
- if (err)
- goto err_request_regions;
-
- mmio_start = pci_resource_start(pdev, 0);
- mmio_len = pci_resource_len(pdev, 0);
-
- reg_base = ioremap(mmio_start, mmio_len);
- if (!reg_base) {
- err = -ENOMEM;
- goto err_ioremap;
- }
-
- device = kzalloc(sizeof(*device), GFP_KERNEL);
- if (!device) {
- err = -ENOMEM;
- goto err_kzalloc;
- }
-
- /* DMA coherent memory pool for DMA descriptor allocations */
- device->dma_pool = pci_pool_create("dma_desc_pool", pdev,
- sizeof(struct ioat_dma_descriptor), 64, 0);
- if (!device->dma_pool) {
- err = -ENOMEM;
- goto err_dma_pool;
- }
-
- device->completion_pool = pci_pool_create("completion_pool", pdev, sizeof(u64), SMP_CACHE_BYTES, SMP_CACHE_BYTES);
- if (!device->completion_pool) {
- err = -ENOMEM;
- goto err_completion_pool;
- }
-
- device->pdev = pdev;
- pci_set_drvdata(pdev, device);
-#ifdef CONFIG_PCI_MSI
- if (pci_enable_msi(pdev) == 0) {
- device->msi = 1;
- } else {
- device->msi = 0;
- }
-#endif
- err = request_irq(pdev->irq, &ioat_do_interrupt, IRQF_SHARED, "ioat",
- device);
- if (err)
- goto err_irq;
-
- device->reg_base = reg_base;
-
- writeb(IOAT_INTRCTRL_MASTER_INT_EN, device->reg_base + IOAT_INTRCTRL_OFFSET);
- pci_set_master(pdev);
-
- INIT_LIST_HEAD(&device->common.channels);
- enumerate_dma_channels(device);
-
- dma_cap_set(DMA_MEMCPY, device->common.cap_mask);
- device->common.device_alloc_chan_resources = ioat_dma_alloc_chan_resources;
- device->common.device_free_chan_resources = ioat_dma_free_chan_resources;
- device->common.device_prep_dma_memcpy = ioat_dma_prep_memcpy;
- device->common.device_is_tx_complete = ioat_dma_is_complete;
- device->common.device_issue_pending = ioat_dma_memcpy_issue_pending;
- device->common.device_dependency_added = ioat_dma_dependency_added;
- device->common.dev = &pdev->dev;
- printk(KERN_INFO "Intel(R) I/OAT DMA Engine found, %d channels\n",
- device->common.chancnt);
-
- err = ioat_self_test(device);
- if (err)
- goto err_self_test;
-
- dma_async_device_register(&device->common);
-
- return 0;
-
-err_self_test:
-err_irq:
- pci_pool_destroy(device->completion_pool);
-err_completion_pool:
- pci_pool_destroy(device->dma_pool);
-err_dma_pool:
- kfree(device);
-err_kzalloc:
- iounmap(reg_base);
-err_ioremap:
- pci_release_regions(pdev);
-err_request_regions:
-err_set_dma_mask:
- pci_disable_device(pdev);
-err_enable_device:
-
- printk(KERN_ERR "Intel(R) I/OAT DMA Engine initialization failed\n");
-
- return err;
-}
-
-static void ioat_shutdown(struct pci_dev *pdev)
-{
- struct ioat_device *device;
- device = pci_get_drvdata(pdev);
-
- dma_async_device_unregister(&device->common);
-}
-
-static void __devexit ioat_remove(struct pci_dev *pdev)
-{
- struct ioat_device *device;
- struct dma_chan *chan, *_chan;
- struct ioat_dma_chan *ioat_chan;
-
- device = pci_get_drvdata(pdev);
- dma_async_device_unregister(&device->common);
-
- free_irq(device->pdev->irq, device);
-#ifdef CONFIG_PCI_MSI
- if (device->msi)
- pci_disable_msi(device->pdev);
-#endif
- pci_pool_destroy(device->dma_pool);
- pci_pool_destroy(device->completion_pool);
- iounmap(device->reg_base);
- pci_release_regions(pdev);
- pci_disable_device(pdev);
- list_for_each_entry_safe(chan, _chan, &device->common.channels, device_node) {
- ioat_chan = to_ioat_chan(chan);
- list_del(&chan->device_node);
- kfree(ioat_chan);
- }
- kfree(device);
-}
-
-/* MODULE API */
-MODULE_VERSION("1.9");
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Intel Corporation");
-
-static int __init ioat_init_module(void)
-{
- /* it's currently unsafe to unload this module */
- /* if forced, worst case is that rmmod hangs */
- __unsafe(THIS_MODULE);
-
- return pci_register_driver(&ioat_pci_driver);
-}
-
-module_init(ioat_init_module);
-
-static void __exit ioat_exit_module(void)
-{
- pci_unregister_driver(&ioat_pci_driver);
-}
-
-module_exit(ioat_exit_module);
diff --git a/drivers/dma/ioatdma.h b/drivers/dma/ioatdma.h
index bf4dad70e0f5..b668234ef654 100644
--- a/drivers/dma/ioatdma.h
+++ b/drivers/dma/ioatdma.h
@@ -1,5 +1,5 @@
/*
- * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved.
+ * Copyright(c) 2004 - 2007 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -28,46 +28,47 @@
#include <linux/cache.h>
#include <linux/pci_ids.h>
+#define IOAT_DMA_VERSION "2.04"
+
+enum ioat_interrupt {
+ none = 0,
+ msix_multi_vector = 1,
+ msix_single_vector = 2,
+ msi = 3,
+ intx = 4,
+};
+
#define IOAT_LOW_COMPLETION_MASK 0xffffffc0
+#define IOAT_DMA_DCA_ANY_CPU ~0
+
/**
- * struct ioat_device - internal representation of a IOAT device
+ * struct ioatdma_device - internal representation of a IOAT device
* @pdev: PCI-Express device
* @reg_base: MMIO register space base address
* @dma_pool: for allocating DMA descriptors
* @common: embedded struct dma_device
- * @msi: Message Signaled Interrupt number
+ * @version: version of ioatdma device
+ * @irq_mode: which style irq to use
+ * @msix_entries: irq handlers
+ * @idx: per channel data
*/
-struct ioat_device {
+struct ioatdma_device {
struct pci_dev *pdev;
void __iomem *reg_base;
struct pci_pool *dma_pool;
struct pci_pool *completion_pool;
-
struct dma_device common;
- u8 msi;
+ u8 version;
+ enum ioat_interrupt irq_mode;
+ struct msix_entry msix_entries[4];
+ struct ioat_dma_chan *idx[4];
};
/**
* struct ioat_dma_chan - internal representation of a DMA channel
- * @device:
- * @reg_base:
- * @sw_in_use:
- * @completion:
- * @completion_low:
- * @completion_high:
- * @completed_cookie: last cookie seen completed on cleanup
- * @cookie: value of last cookie given to client
- * @last_completion:
- * @xfercap:
- * @desc_lock:
- * @free_desc:
- * @used_desc:
- * @resource:
- * @device_node:
*/
-
struct ioat_dma_chan {
void __iomem *reg_base;
@@ -83,8 +84,10 @@ struct ioat_dma_chan {
struct list_head used_desc;
int pending;
+ int dmacount;
+ int desccount;
- struct ioat_device *device;
+ struct ioatdma_device *device;
struct dma_chan common;
dma_addr_t completion_addr;
@@ -95,6 +98,7 @@ struct ioat_dma_chan {
u32 high;
};
} *completion_virt;
+ struct tasklet_struct cleanup_task;
};
/* wrapper around hardware descriptor format + additional software fields */
@@ -111,10 +115,23 @@ struct ioat_desc_sw {
struct ioat_dma_descriptor *hw;
struct list_head node;
int tx_cnt;
- DECLARE_PCI_UNMAP_LEN(len)
- DECLARE_PCI_UNMAP_ADDR(src)
- DECLARE_PCI_UNMAP_ADDR(dst)
+ size_t len;
+ dma_addr_t src;
+ dma_addr_t dst;
struct dma_async_tx_descriptor async_tx;
};
+#if defined(CONFIG_INTEL_IOATDMA) || defined(CONFIG_INTEL_IOATDMA_MODULE)
+struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev,
+ void __iomem *iobase);
+void ioat_dma_remove(struct ioatdma_device *device);
+struct dca_provider *ioat_dca_init(struct pci_dev *pdev, void __iomem *iobase);
+struct dca_provider *ioat2_dca_init(struct pci_dev *pdev, void __iomem *iobase);
+#else
+#define ioat_dma_probe(pdev, iobase) NULL
+#define ioat_dma_remove(device) do { } while (0)
+#define ioat_dca_init(pdev, iobase) NULL
+#define ioat2_dca_init(pdev, iobase) NULL
+#endif
+
#endif /* IOATDMA_H */
diff --git a/drivers/dma/ioatdma_hw.h b/drivers/dma/ioatdma_hw.h
index 4d7a12880be3..dd470fa91d86 100644
--- a/drivers/dma/ioatdma_hw.h
+++ b/drivers/dma/ioatdma_hw.h
@@ -1,5 +1,5 @@
/*
- * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved.
+ * Copyright(c) 2004 - 2007 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -22,12 +22,19 @@
#define _IOAT_HW_H_
/* PCI Configuration Space Values */
-#define IOAT_PCI_VID 0x8086
-#define IOAT_PCI_DID 0x1A38
-#define IOAT_PCI_RID 0x00
-#define IOAT_PCI_SVID 0x8086
-#define IOAT_PCI_SID 0x8086
-#define IOAT_VER 0x12 /* Version 1.2 */
+#define IOAT_PCI_VID 0x8086
+
+/* CB device ID's */
+#define IOAT_PCI_DID_5000 0x1A38
+#define IOAT_PCI_DID_CNB 0x360B
+#define IOAT_PCI_DID_SCNB 0x65FF
+#define IOAT_PCI_DID_SNB 0x402F
+
+#define IOAT_PCI_RID 0x00
+#define IOAT_PCI_SVID 0x8086
+#define IOAT_PCI_SID 0x8086
+#define IOAT_VER_1_2 0x12 /* Version 1.2 */
+#define IOAT_VER_2_0 0x20 /* Version 2.0 */
struct ioat_dma_descriptor {
uint32_t size;
@@ -47,6 +54,16 @@ struct ioat_dma_descriptor {
#define IOAT_DMA_DESCRIPTOR_CTL_CP_STS 0x00000008
#define IOAT_DMA_DESCRIPTOR_CTL_FRAME 0x00000010
#define IOAT_DMA_DESCRIPTOR_NUL 0x00000020
-#define IOAT_DMA_DESCRIPTOR_OPCODE 0xFF000000
+#define IOAT_DMA_DESCRIPTOR_CTL_SP_BRK 0x00000040
+#define IOAT_DMA_DESCRIPTOR_CTL_DP_BRK 0x00000080
+#define IOAT_DMA_DESCRIPTOR_CTL_BNDL 0x00000100
+#define IOAT_DMA_DESCRIPTOR_CTL_DCA 0x00000200
+#define IOAT_DMA_DESCRIPTOR_CTL_BUFHINT 0x00000400
+
+#define IOAT_DMA_DESCRIPTOR_CTL_OPCODE_CONTEXT 0xFF000000
+#define IOAT_DMA_DESCRIPTOR_CTL_OPCODE_DMA 0x00000000
+
+#define IOAT_DMA_DESCRIPTOR_CTL_CONTEXT_DCA 0x00000001
+#define IOAT_DMA_DESCRIPTOR_CTL_OPCODE_MASK 0xFF000000
#endif
diff --git a/drivers/dma/ioatdma_registers.h b/drivers/dma/ioatdma_registers.h
index a30c7349075a..9832d7ebd931 100644
--- a/drivers/dma/ioatdma_registers.h
+++ b/drivers/dma/ioatdma_registers.h
@@ -1,5 +1,5 @@
/*
- * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved.
+ * Copyright(c) 2004 - 2007 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -21,6 +21,9 @@
#ifndef _IOAT_REGISTERS_H_
#define _IOAT_REGISTERS_H_
+#define IOAT_PCI_DMACTRL_OFFSET 0x48
+#define IOAT_PCI_DMACTRL_DMA_EN 0x00000001
+#define IOAT_PCI_DMACTRL_MSI_EN 0x00000002
/* MMIO Device Registers */
#define IOAT_CHANCNT_OFFSET 0x00 /* 8-bit */
@@ -39,25 +42,25 @@
#define IOAT_INTRCTRL_MASTER_INT_EN 0x01 /* Master Interrupt Enable */
#define IOAT_INTRCTRL_INT_STATUS 0x02 /* ATTNSTATUS -or- Channel Int */
#define IOAT_INTRCTRL_INT 0x04 /* INT_STATUS -and- MASTER_INT_EN */
+#define IOAT_INTRCTRL_MSIX_VECTOR_CONTROL 0x08 /* Enable all MSI-X vectors */
#define IOAT_ATTNSTATUS_OFFSET 0x04 /* Each bit is a channel */
#define IOAT_VER_OFFSET 0x08 /* 8-bit */
#define IOAT_VER_MAJOR_MASK 0xF0
#define IOAT_VER_MINOR_MASK 0x0F
-#define GET_IOAT_VER_MAJOR(x) ((x) & IOAT_VER_MAJOR_MASK)
+#define GET_IOAT_VER_MAJOR(x) (((x) & IOAT_VER_MAJOR_MASK) >> 4)
#define GET_IOAT_VER_MINOR(x) ((x) & IOAT_VER_MINOR_MASK)
#define IOAT_PERPORTOFFSET_OFFSET 0x0A /* 16-bit */
#define IOAT_INTRDELAY_OFFSET 0x0C /* 16-bit */
#define IOAT_INTRDELAY_INT_DELAY_MASK 0x3FFF /* Interrupt Delay Time */
-#define IOAT_INTRDELAY_COALESE_SUPPORT 0x8000 /* Interrupt Coalesing Supported */
+#define IOAT_INTRDELAY_COALESE_SUPPORT 0x8000 /* Interrupt Coalescing Supported */
#define IOAT_DEVICE_STATUS_OFFSET 0x0E /* 16-bit */
#define IOAT_DEVICE_STATUS_DEGRADED_MODE 0x0001
-
#define IOAT_CHANNEL_MMIO_SIZE 0x80 /* Each Channel MMIO space is this size */
/* DMA Channel Registers */
@@ -70,25 +73,101 @@
#define IOAT_CHANCTRL_ERR_COMPLETION_EN 0x0004
#define IOAT_CHANCTRL_INT_DISABLE 0x0001
-#define IOAT_DMA_COMP_OFFSET 0x02 /* 16-bit DMA channel compatability */
-#define IOAT_DMA_COMP_V1 0x0001 /* Compatability with DMA version 1 */
-
-#define IOAT_CHANSTS_OFFSET 0x04 /* 64-bit Channel Status Register */
-#define IOAT_CHANSTS_OFFSET_LOW 0x04
-#define IOAT_CHANSTS_OFFSET_HIGH 0x08
-#define IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR 0xFFFFFFFFFFFFFFC0UL
+#define IOAT_DMA_COMP_OFFSET 0x02 /* 16-bit DMA channel compatibility */
+#define IOAT_DMA_COMP_V1 0x0001 /* Compatibility with DMA version 1 */
+#define IOAT_DMA_COMP_V2 0x0002 /* Compatibility with DMA version 2 */
+
+
+#define IOAT1_CHANSTS_OFFSET 0x04 /* 64-bit Channel Status Register */
+#define IOAT2_CHANSTS_OFFSET 0x08 /* 64-bit Channel Status Register */
+#define IOAT_CHANSTS_OFFSET(ver) ((ver) < IOAT_VER_2_0 \
+ ? IOAT1_CHANSTS_OFFSET : IOAT2_CHANSTS_OFFSET)
+#define IOAT1_CHANSTS_OFFSET_LOW 0x04
+#define IOAT2_CHANSTS_OFFSET_LOW 0x08
+#define IOAT_CHANSTS_OFFSET_LOW(ver) ((ver) < IOAT_VER_2_0 \
+ ? IOAT1_CHANSTS_OFFSET_LOW : IOAT2_CHANSTS_OFFSET_LOW)
+#define IOAT1_CHANSTS_OFFSET_HIGH 0x08
+#define IOAT2_CHANSTS_OFFSET_HIGH 0x0C
+#define IOAT_CHANSTS_OFFSET_HIGH(ver) ((ver) < IOAT_VER_2_0 \
+ ? IOAT1_CHANSTS_OFFSET_HIGH : IOAT2_CHANSTS_OFFSET_HIGH)
+#define IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR ~0x3F
#define IOAT_CHANSTS_SOFT_ERR 0x0000000000000010
+#define IOAT_CHANSTS_UNAFFILIATED_ERR 0x0000000000000008
#define IOAT_CHANSTS_DMA_TRANSFER_STATUS 0x0000000000000007
#define IOAT_CHANSTS_DMA_TRANSFER_STATUS_ACTIVE 0x0
#define IOAT_CHANSTS_DMA_TRANSFER_STATUS_DONE 0x1
#define IOAT_CHANSTS_DMA_TRANSFER_STATUS_SUSPENDED 0x2
#define IOAT_CHANSTS_DMA_TRANSFER_STATUS_HALTED 0x3
-#define IOAT_CHAINADDR_OFFSET 0x0C /* 64-bit Descriptor Chain Address Register */
-#define IOAT_CHAINADDR_OFFSET_LOW 0x0C
-#define IOAT_CHAINADDR_OFFSET_HIGH 0x10
-#define IOAT_CHANCMD_OFFSET 0x14 /* 8-bit DMA Channel Command Register */
+
+#define IOAT_CHAN_DMACOUNT_OFFSET 0x06 /* 16-bit DMA Count register */
+
+#define IOAT_DCACTRL_OFFSET 0x30 /* 32 bit Direct Cache Access Control Register */
+#define IOAT_DCACTRL_CMPL_WRITE_ENABLE 0x10000
+#define IOAT_DCACTRL_TARGET_CPU_MASK 0xFFFF /* APIC ID */
+
+/* CB DCA Memory Space Registers */
+#define IOAT_DCAOFFSET_OFFSET 0x14
+/* CB_BAR + IOAT_DCAOFFSET value */
+#define IOAT_DCA_VER_OFFSET 0x00
+#define IOAT_DCA_VER_MAJOR_MASK 0xF0
+#define IOAT_DCA_VER_MINOR_MASK 0x0F
+
+#define IOAT_DCA_COMP_OFFSET 0x02
+#define IOAT_DCA_COMP_V1 0x1
+
+#define IOAT_FSB_CAPABILITY_OFFSET 0x04
+#define IOAT_FSB_CAPABILITY_PREFETCH 0x1
+
+#define IOAT_PCI_CAPABILITY_OFFSET 0x06
+#define IOAT_PCI_CAPABILITY_MEMWR 0x1
+
+#define IOAT_FSB_CAP_ENABLE_OFFSET 0x08
+#define IOAT_FSB_CAP_ENABLE_PREFETCH 0x1
+
+#define IOAT_PCI_CAP_ENABLE_OFFSET 0x0A
+#define IOAT_PCI_CAP_ENABLE_MEMWR 0x1
+
+#define IOAT_APICID_TAG_MAP_OFFSET 0x0C
+#define IOAT_APICID_TAG_MAP_TAG0 0x0000000F
+#define IOAT_APICID_TAG_MAP_TAG0_SHIFT 0
+#define IOAT_APICID_TAG_MAP_TAG1 0x000000F0
+#define IOAT_APICID_TAG_MAP_TAG1_SHIFT 4
+#define IOAT_APICID_TAG_MAP_TAG2 0x00000F00
+#define IOAT_APICID_TAG_MAP_TAG2_SHIFT 8
+#define IOAT_APICID_TAG_MAP_TAG3 0x0000F000
+#define IOAT_APICID_TAG_MAP_TAG3_SHIFT 12
+#define IOAT_APICID_TAG_MAP_TAG4 0x000F0000
+#define IOAT_APICID_TAG_MAP_TAG4_SHIFT 16
+#define IOAT_APICID_TAG_CB2_VALID 0x8080808080
+
+#define IOAT_DCA_GREQID_OFFSET 0x10
+#define IOAT_DCA_GREQID_SIZE 0x04
+#define IOAT_DCA_GREQID_MASK 0xFFFF
+#define IOAT_DCA_GREQID_IGNOREFUN 0x10000000
+#define IOAT_DCA_GREQID_VALID 0x20000000
+#define IOAT_DCA_GREQID_LASTID 0x80000000
+
+
+
+#define IOAT1_CHAINADDR_OFFSET 0x0C /* 64-bit Descriptor Chain Address Register */
+#define IOAT2_CHAINADDR_OFFSET 0x10 /* 64-bit Descriptor Chain Address Register */
+#define IOAT_CHAINADDR_OFFSET(ver) ((ver) < IOAT_VER_2_0 \
+ ? IOAT1_CHAINADDR_OFFSET : IOAT2_CHAINADDR_OFFSET)
+#define IOAT1_CHAINADDR_OFFSET_LOW 0x0C
+#define IOAT2_CHAINADDR_OFFSET_LOW 0x10
+#define IOAT_CHAINADDR_OFFSET_LOW(ver) ((ver) < IOAT_VER_2_0 \
+ ? IOAT1_CHAINADDR_OFFSET_LOW : IOAT2_CHAINADDR_OFFSET_LOW)
+#define IOAT1_CHAINADDR_OFFSET_HIGH 0x10
+#define IOAT2_CHAINADDR_OFFSET_HIGH 0x14
+#define IOAT_CHAINADDR_OFFSET_HIGH(ver) ((ver) < IOAT_VER_2_0 \
+ ? IOAT1_CHAINADDR_OFFSET_HIGH : IOAT2_CHAINADDR_OFFSET_HIGH)
+
+#define IOAT1_CHANCMD_OFFSET 0x14 /* 8-bit DMA Channel Command Register */
+#define IOAT2_CHANCMD_OFFSET 0x04 /* 8-bit DMA Channel Command Register */
+#define IOAT_CHANCMD_OFFSET(ver) ((ver) < IOAT_VER_2_0 \
+ ? IOAT1_CHANCMD_OFFSET : IOAT2_CHANCMD_OFFSET)
#define IOAT_CHANCMD_RESET 0x20
#define IOAT_CHANCMD_RESUME 0x10
#define IOAT_CHANCMD_ABORT 0x08
@@ -120,6 +199,7 @@
#define IOAT_CHANERR_COMPLETION_ADDR_ERR 0x1000
#define IOAT_CHANERR_INT_CONFIGURATION_ERR 0x2000
#define IOAT_CHANERR_SOFT_ERR 0x4000
+#define IOAT_CHANERR_UNAFFILIATED_ERR 0x8000
#define IOAT_CHANERR_MASK_OFFSET 0x2C /* 32-bit Channel Error Register */
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
index 5a1d426744d6..e5c62b75f36f 100644
--- a/drivers/dma/iop-adma.c
+++ b/drivers/dma/iop-adma.c
@@ -1446,21 +1446,20 @@ static struct platform_driver iop_adma_driver = {
static int __init iop_adma_init (void)
{
- /* it's currently unsafe to unload this module */
- /* if forced, worst case is that rmmod hangs */
- __unsafe(THIS_MODULE);
-
return platform_driver_register(&iop_adma_driver);
}
+/* it's currently unsafe to unload this module */
+#if 0
static void __exit iop_adma_exit (void)
{
platform_driver_unregister(&iop_adma_driver);
return;
}
+module_exit(iop_adma_exit);
+#endif
module_init(iop_adma_init);
-module_exit(iop_adma_exit);
MODULE_AUTHOR("Intel Corporation");
MODULE_DESCRIPTION("IOP ADMA Engine Driver");
diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h
index e80af67664cc..2d23e304f5ec 100644
--- a/drivers/edac/edac_core.h
+++ b/drivers/edac/edac_core.h
@@ -94,8 +94,6 @@ extern int edac_debug_level;
#endif /* !CONFIG_EDAC_DEBUG */
-#define BIT(x) (1 << (x))
-
#define PCI_VEND_DEV(vend, dev) PCI_VENDOR_ID_ ## vend, \
PCI_DEVICE_ID_ ## vend ## _ ## dev
diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c
index 96f7e63e3996..a1f24c42d5ff 100644
--- a/drivers/edac/i5000_edac.c
+++ b/drivers/edac/i5000_edac.c
@@ -1462,7 +1462,7 @@ MODULE_DEVICE_TABLE(pci, i5000_pci_tbl);
*
*/
static struct pci_driver i5000_driver = {
- .name = __stringify(KBUILD_BASENAME),
+ .name = KBUILD_BASENAME,
.probe = i5000_init_one,
.remove = __devexit_p(i5000_remove_one),
.id_table = i5000_pci_tbl,
diff --git a/drivers/edac/pasemi_edac.c b/drivers/edac/pasemi_edac.c
index e66cdd42a392..9007d0677220 100644
--- a/drivers/edac/pasemi_edac.c
+++ b/drivers/edac/pasemi_edac.c
@@ -270,6 +270,7 @@ static void __devexit pasemi_edac_remove(struct pci_dev *pdev)
static const struct pci_device_id pasemi_edac_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_PASEMI, 0xa00a) },
+ { }
};
MODULE_DEVICE_TABLE(pci, pasemi_edac_pci_tbl);
diff --git a/drivers/fc4/Kconfig b/drivers/fc4/Kconfig
deleted file mode 100644
index 345dbe6f10df..000000000000
--- a/drivers/fc4/Kconfig
+++ /dev/null
@@ -1,81 +0,0 @@
-#
-# FC4 device configuration
-#
-
-menu "Fibre Channel support"
-
-config FC4
- tristate "Fibre Channel and FC4 SCSI support"
- ---help---
- Fibre Channel is a high speed serial protocol mainly used to
- connect large storage devices to the computer; it is compatible with
- and intended to replace SCSI.
-
- This is an experimental support for storage arrays connected to your
- computer using optical fibre cables and the "X3.269-199X Fibre
- Channel Protocol for SCSI" specification. If you want to use this,
- you need to say Y here and to "SCSI support" as well as to the
- drivers for the storage array itself and for the interface adapter
- such as SOC or SOC+. This subsystem could even serve for IP
- networking, with some code extensions.
-
- If unsure, say N.
-
-comment "FC4 drivers"
- depends on FC4
-
-config FC4_SOC
- tristate "Sun SOC/Sbus"
- depends on FC4!=n && SPARC
- help
- Serial Optical Channel is an interface card with one or two Fibre
- Optic ports, each of which can be connected to a disk array. Note
- that if you have older firmware in the card, you'll need the
- microcode from the Solaris driver to make it work.
-
- To compile this support as a module, choose M here: the module will
- be called soc.
-
-config FC4_SOCAL
- tristate "Sun SOC+ (aka SOCAL)"
- depends on FC4!=n && SPARC
- ---help---
- Serial Optical Channel Plus is an interface card with up to two
- Fibre Optic ports. This card supports FC Arbitrated Loop (usually
- A5000 or internal FC disks in E[3-6]000 machines through the
- Interface Board). You'll probably need the microcode from the
- Solaris driver to make it work.
-
- To compile this support as a module, choose M here: the module will
- be called socal.
-
-comment "FC4 targets"
- depends on FC4
-
-config SCSI_PLUTO
- tristate "SparcSTORAGE Array 100 and 200 series"
- depends on FC4!=n && SCSI
- help
- If you never bought a disk array made by Sun, go with N.
-
- To compile this support as a module, choose M here: the module will
- be called pluto.
-
-config SCSI_FCAL
- tristate "Sun Enterprise Network Array (A5000 and EX500)" if SPARC
- depends on FC4!=n && SCSI
- help
- This driver drives FC-AL disks connected through a Fibre Channel
- card using the drivers/fc4 layer (currently only SOCAL). The most
- common is either A5000 array or internal disks in E[3-6]000
- machines.
-
- To compile this support as a module, choose M here: the module will
- be called fcal.
-
-config SCSI_FCAL
- prompt "Generic FC-AL disk driver"
- depends on FC4!=n && SCSI && !SPARC
-
-endmenu
-
diff --git a/drivers/fc4/Makefile b/drivers/fc4/Makefile
deleted file mode 100644
index 0db3fbb553e9..000000000000
--- a/drivers/fc4/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# Makefile for the Linux Fibre Channel device drivers.
-#
-
-fc4-objs := fc.o fc_syms.o
-
-obj-$(CONFIG_FC4) += fc4.o
-obj-$(CONFIG_FC4_SOC) += soc.o
-obj-$(CONFIG_FC4_SOCAL) += socal.o
diff --git a/drivers/fc4/fc-al.h b/drivers/fc4/fc-al.h
deleted file mode 100644
index 62d3ca436d72..000000000000
--- a/drivers/fc4/fc-al.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* fc-al.h: Definitions for Fibre Channel Arbitrated Loop topology.
- *
- * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- *
- * Sources:
- * Fibre Channel Arbitrated Loop (FC-AL), ANSI, Rev. 4.5, 1995
- */
-
-#ifndef __FC_AL_H
-#define __FC_AL_H
-
-/* Loop initialization payloads */
-#define FC_AL_LISM 0x11010000 /* Select Master, 12B payload */
-#define FC_AL_LIFA 0x11020000 /* Fabric Assign AL_PA bitmap, 20B payload */
-#define FC_AL_LIPA 0x11030000 /* Previously Acquired AL_PA bitmap, 20B payload */
-#define FC_AL_LIHA 0x11040000 /* Hard Assigned AL_PA bitmap, 20B payload */
-#define FC_AL_LISA 0x11050000 /* Soft Assigned AL_PA bitmap, 20B payload */
-#define FC_AL_LIRP 0x11060000 /* Report AL_PA position map, 132B payload */
-#define FC_AL_LILP 0x11070000 /* Loop AL_PA position map, 132B payload */
-
-typedef struct {
- u32 magic;
- u8 len;
- u8 alpa[127];
-} fc_al_posmap;
-
-#endif /* !(__FC_H) */
diff --git a/drivers/fc4/fc.c b/drivers/fc4/fc.c
deleted file mode 100644
index 82de9e1adb1e..000000000000
--- a/drivers/fc4/fc.c
+++ /dev/null
@@ -1,1146 +0,0 @@
-/* fc.c: Generic Fibre Channel and FC4 SCSI driver.
- *
- * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1997,1998 Jirka Hanika (geo@ff.cuni.cz)
- *
- * There are two kinds of Fibre Channel adapters used in Linux. Either
- * the adapter is "smart" and does all FC bookkeeping by itself and
- * just presents a standard SCSI interface to the operating system
- * (that's e.g. the case with Qlogic FC cards), or leaves most of the FC
- * bookkeeping to the OS (e.g. soc, socal). Drivers for the former adapters
- * will look like normal SCSI drivers (with the exception of max_id will be
- * usually 127), the latter on the other side allows SCSI, IP over FC and other
- * protocols. This driver tree is for the latter adapters.
- *
- * This file should support both Point-to-Point and Arbitrated Loop topologies.
- *
- * Sources:
- * Fibre Channel Physical & Signaling Interface (FC-PH), dpANS, 1994
- * dpANS Fibre Channel Protocol for SCSI (X3.269-199X), Rev. 012, 1995
- * Fibre Channel Arbitrated Loop (FC-AL), Rev. 4.5, 1995
- * Fibre Channel Private Loop SCSI Direct Attach (FC-PLDA), Rev. 2.1, 1997
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/jiffies.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/init.h>
-
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-#include <asm/semaphore.h>
-#include "fcp_impl.h"
-#include <scsi/scsi_host.h>
-
-/* #define FCDEBUG */
-
-#define fc_printk printk ("%s: ", fc->name); printk
-
-#ifdef FCDEBUG
-#define FCD(x) fc_printk x;
-#define FCND(x) printk ("FC: "); printk x;
-#else
-#define FCD(x)
-#define FCND(x)
-#endif
-
-#ifdef __sparc__
-#define dma_alloc_consistent(d,s,p) sbus_alloc_consistent(d,s,p)
-#define dma_free_consistent(d,s,v,h) sbus_free_consistent(d,s,v,h)
-#define dma_map_single(d,v,s,dir) sbus_map_single(d,v,s,dir)
-#define dma_unmap_single(d,h,s,dir) sbus_unmap_single(d,h,s,dir)
-#define dma_map_sg(d,s,n,dir) sbus_map_sg(d,s,n,dir)
-#define dma_unmap_sg(d,s,n,dir) sbus_unmap_sg(d,s,n,dir)
-#else
-#define dma_alloc_consistent(d,s,p) pci_alloc_consistent(d,s,p)
-#define dma_free_consistent(d,s,v,h) pci_free_consistent(d,s,v,h)
-#define dma_map_single(d,v,s,dir) pci_map_single(d,v,s,dir)
-#define dma_unmap_single(d,h,s,dir) pci_unmap_single(d,h,s,dir)
-#define dma_map_sg(d,s,n,dir) pci_map_sg(d,s,n,dir)
-#define dma_unmap_sg(d,s,n,dir) pci_unmap_sg(d,s,n,dir)
-#endif
-
-#define FCP_CMND(SCpnt) ((fcp_cmnd *)&(SCpnt->SCp))
-#define FC_SCMND(SCpnt) ((fc_channel *)(SCpnt->device->host->hostdata[0]))
-#define SC_FCMND(fcmnd) ((struct scsi_cmnd *)((long)fcmnd - (long)&(((struct scsi_cmnd *)0)->SCp)))
-
-static int fcp_scsi_queue_it(fc_channel *, struct scsi_cmnd *, fcp_cmnd *, int);
-void fcp_queue_empty(fc_channel *);
-
-static void fcp_scsi_insert_queue (fc_channel *fc, fcp_cmnd *fcmd)
-{
- if (!fc->scsi_que) {
- fc->scsi_que = fcmd;
- fcmd->next = fcmd;
- fcmd->prev = fcmd;
- } else {
- fc->scsi_que->prev->next = fcmd;
- fcmd->prev = fc->scsi_que->prev;
- fc->scsi_que->prev = fcmd;
- fcmd->next = fc->scsi_que;
- }
-}
-
-static void fcp_scsi_remove_queue (fc_channel *fc, fcp_cmnd *fcmd)
-{
- if (fcmd == fcmd->next) {
- fc->scsi_que = NULL;
- return;
- }
- if (fcmd == fc->scsi_que)
- fc->scsi_que = fcmd->next;
- fcmd->prev->next = fcmd->next;
- fcmd->next->prev = fcmd->prev;
-}
-
-fc_channel *fc_channels = NULL;
-
-#define LSMAGIC 620829043
-typedef struct {
- /* Must be first */
- struct semaphore sem;
- int magic;
- int count;
- logi *logi;
- fcp_cmnd *fcmds;
- atomic_t todo;
- struct timer_list timer;
- unsigned char grace[0];
-} ls;
-
-#define LSOMAGIC 654907799
-typedef struct {
- /* Must be first */
- struct semaphore sem;
- int magic;
- int count;
- fcp_cmnd *fcmds;
- atomic_t todo;
- struct timer_list timer;
-} lso;
-
-#define LSEMAGIC 84482456
-typedef struct {
- /* Must be first */
- struct semaphore sem;
- int magic;
- int status;
- struct timer_list timer;
-} lse;
-
-static void fcp_login_timeout(unsigned long data)
-{
- ls *l = (ls *)data;
- FCND(("Login timeout\n"))
- up(&l->sem);
-}
-
-static void fcp_login_done(fc_channel *fc, int i, int status)
-{
- fcp_cmnd *fcmd;
- logi *plogi;
- fc_hdr *fch;
- ls *l = (ls *)fc->ls;
-
- FCD(("Login done %d %d\n", i, status))
- if (i < l->count) {
- if (fc->state == FC_STATE_FPORT_OK) {
- FCD(("Additional FPORT_OK received with status %d\n", status))
- return;
- }
- switch (status) {
- case FC_STATUS_OK: /* Oh, we found a fabric */
- case FC_STATUS_P_RJT: /* Oh, we haven't found any */
- fc->state = FC_STATE_FPORT_OK;
- fcmd = l->fcmds + i;
- plogi = l->logi + 3 * i;
- dma_unmap_single (fc->dev, fcmd->cmd, 3 * sizeof(logi),
- DMA_BIDIRECTIONAL);
- plogi->code = LS_PLOGI;
- memcpy (&plogi->nport_wwn, &fc->wwn_nport, sizeof(fc_wwn));
- memcpy (&plogi->node_wwn, &fc->wwn_node, sizeof(fc_wwn));
- memcpy (&plogi->common, fc->common_svc, sizeof(common_svc_parm));
- memcpy (&plogi->class1, fc->class_svcs, 3*sizeof(svc_parm));
- fch = &fcmd->fch;
- fcmd->token += l->count;
- FILL_FCHDR_RCTL_DID(fch, R_CTL_ELS_REQ, fc->did);
- FILL_FCHDR_SID(fch, fc->sid);
-#ifdef FCDEBUG
- {
- int i;
- unsigned *x = (unsigned *)plogi;
- printk ("logi: ");
- for (i = 0; i < 21; i++)
- printk ("%08x ", x[i]);
- printk ("\n");
- }
-#endif
- fcmd->cmd = dma_map_single (fc->dev, plogi, 3 * sizeof(logi),
- DMA_BIDIRECTIONAL);
- fcmd->rsp = fcmd->cmd + 2 * sizeof(logi);
- if (fc->hw_enque (fc, fcmd))
- printk ("FC: Cannot enque PLOGI packet on %s\n", fc->name);
- break;
- case FC_STATUS_ERR_OFFLINE:
- fc->state = FC_STATE_MAYBEOFFLINE;
- FCD (("FC is offline %d\n", l->grace[i]))
- break;
- default:
- printk ("FLOGI failed for %s with status %d\n", fc->name, status);
- /* Do some sort of error recovery here */
- break;
- }
- } else {
- i -= l->count;
- if (fc->state != FC_STATE_FPORT_OK) {
- FCD(("Unexpected N-PORT rsp received"))
- return;
- }
- switch (status) {
- case FC_STATUS_OK:
- plogi = l->logi + 3 * i;
- dma_unmap_single (fc->dev, l->fcmds[i].cmd, 3 * sizeof(logi),
- DMA_BIDIRECTIONAL);
- if (!fc->wwn_dest.lo && !fc->wwn_dest.hi) {
- memcpy (&fc->wwn_dest, &plogi[1].node_wwn, sizeof(fc_wwn));
- FCD(("Dest WWN %08x%08x\n", *(u32 *)&fc->wwn_dest, fc->wwn_dest.lo))
- } else if (fc->wwn_dest.lo != plogi[1].node_wwn.lo ||
- fc->wwn_dest.hi != plogi[1].node_wwn.hi) {
- printk ("%s: mismatch in wwns. Got %08x%08x, expected %08x%08x\n",
- fc->name,
- *(u32 *)&plogi[1].node_wwn, plogi[1].node_wwn.lo,
- *(u32 *)&fc->wwn_dest, fc->wwn_dest.lo);
- }
- fc->state = FC_STATE_ONLINE;
- printk ("%s: ONLINE\n", fc->name);
- if (atomic_dec_and_test (&l->todo))
- up(&l->sem);
- break;
- case FC_STATUS_ERR_OFFLINE:
- fc->state = FC_STATE_OFFLINE;
- dma_unmap_single (fc->dev, l->fcmds[i].cmd, 3 * sizeof(logi),
- DMA_BIDIRECTIONAL);
- printk ("%s: FC is offline\n", fc->name);
- if (atomic_dec_and_test (&l->todo))
- up(&l->sem);
- break;
- default:
- printk ("PLOGI failed for %s with status %d\n", fc->name, status);
- /* Do some sort of error recovery here */
- break;
- }
- }
-}
-
-static void fcp_report_map_done(fc_channel *fc, int i, int status)
-{
- fcp_cmnd *fcmd;
- fc_hdr *fch;
- unsigned char j;
- ls *l = (ls *)fc->ls;
- fc_al_posmap *p;
-
- FCD(("Report map done %d %d\n", i, status))
- switch (status) {
- case FC_STATUS_OK: /* Ok, let's have a fun on a loop */
- dma_unmap_single (fc->dev, l->fcmds[i].cmd, 3 * sizeof(logi),
- DMA_BIDIRECTIONAL);
- p = (fc_al_posmap *)(l->logi + 3 * i);
-#ifdef FCDEBUG
- {
- u32 *u = (u32 *)p;
- FCD(("%08x\n", u[0]))
- u ++;
- FCD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7]))
- }
-#endif
- if ((p->magic & 0xffff0000) != FC_AL_LILP || !p->len) {
- printk ("FC: Bad magic from REPORT_AL_MAP on %s - %08x\n", fc->name, p->magic);
- fc->state = FC_STATE_OFFLINE;
- } else {
- fc->posmap = kzalloc(sizeof(fcp_posmap)+p->len, GFP_KERNEL);
- if (!fc->posmap) {
- printk("FC: Not enough memory, offlining channel\n");
- fc->state = FC_STATE_OFFLINE;
- } else {
- int k;
- /* FIXME: This is where SOCAL transfers our AL-PA.
- Keep it here till we found out what other cards do... */
- fc->sid = (p->magic & 0xff);
- for (i = 0; i < p->len; i++)
- if (p->alpa[i] == fc->sid)
- break;
- k = p->len;
- if (i == p->len)
- i = 0;
- else {
- p->len--;
- i++;
- }
- fc->posmap->len = p->len;
- for (j = 0; j < p->len; j++) {
- if (i == k) i = 0;
- fc->posmap->list[j] = p->alpa[i++];
- }
- fc->state = FC_STATE_ONLINE;
- }
- }
- printk ("%s: ONLINE\n", fc->name);
- if (atomic_dec_and_test (&l->todo))
- up(&l->sem);
- break;
- case FC_STATUS_POINTTOPOINT: /* We're Point-to-Point, no AL... */
- FCD(("SID %d DID %d\n", fc->sid, fc->did))
- fcmd = l->fcmds + i;
- dma_unmap_single(fc->dev, fcmd->cmd, 3 * sizeof(logi),
- DMA_BIDIRECTIONAL);
- fch = &fcmd->fch;
- memset(l->logi + 3 * i, 0, 3 * sizeof(logi));
- FILL_FCHDR_RCTL_DID(fch, R_CTL_ELS_REQ, FS_FABRIC_F_PORT);
- FILL_FCHDR_SID(fch, 0);
- FILL_FCHDR_TYPE_FCTL(fch, TYPE_EXTENDED_LS, F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE);
- FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0);
- FILL_FCHDR_OXRX(fch, 0xffff, 0xffff);
- fch->param = 0;
- l->logi [3 * i].code = LS_FLOGI;
- fcmd->cmd = dma_map_single (fc->dev, l->logi + 3 * i, 3 * sizeof(logi),
- DMA_BIDIRECTIONAL);
- fcmd->rsp = fcmd->cmd + sizeof(logi);
- fcmd->cmdlen = sizeof(logi);
- fcmd->rsplen = sizeof(logi);
- fcmd->data = (dma_addr_t)NULL;
- fcmd->class = FC_CLASS_SIMPLE;
- fcmd->proto = TYPE_EXTENDED_LS;
- if (fc->hw_enque (fc, fcmd))
- printk ("FC: Cannot enque FLOGI packet on %s\n", fc->name);
- break;
- case FC_STATUS_ERR_OFFLINE:
- fc->state = FC_STATE_MAYBEOFFLINE;
- FCD (("FC is offline %d\n", l->grace[i]))
- break;
- default:
- printk ("FLOGI failed for %s with status %d\n", fc->name, status);
- /* Do some sort of error recovery here */
- break;
- }
-}
-
-void fcp_register(fc_channel *fc, u8 type, int unregister)
-{
- int size, i;
- int slots = (fc->can_queue * 3) >> 1;
-
- FCND(("Going to %sregister\n", unregister ? "un" : ""))
-
- if (type == TYPE_SCSI_FCP) {
- if (!unregister) {
- fc->scsi_cmd_pool = (fcp_cmd *)
- dma_alloc_consistent (fc->dev,
- slots * (sizeof (fcp_cmd) + fc->rsp_size),
- &fc->dma_scsi_cmd);
- fc->scsi_rsp_pool = (char *)(fc->scsi_cmd_pool + slots);
- fc->dma_scsi_rsp = fc->dma_scsi_cmd + slots * sizeof (fcp_cmd);
- fc->scsi_bitmap_end = (slots + 63) & ~63;
- size = fc->scsi_bitmap_end / 8;
- fc->scsi_bitmap = kzalloc (size, GFP_KERNEL);
- set_bit (0, fc->scsi_bitmap);
- for (i = fc->can_queue; i < fc->scsi_bitmap_end; i++)
- set_bit (i, fc->scsi_bitmap);
- fc->scsi_free = fc->can_queue;
- fc->cmd_slots = kzalloc(slots * sizeof(fcp_cmnd*), GFP_KERNEL);
- fc->abort_count = 0;
- } else {
- fc->scsi_name[0] = 0;
- kfree (fc->scsi_bitmap);
- kfree (fc->cmd_slots);
- FCND(("Unregistering\n"));
-#if 0
- if (fc->rst_pkt) {
- if (fc->rst_pkt->eh_state == SCSI_STATE_UNUSED)
- kfree(fc->rst_pkt);
- else {
- /* Can't happen. Some memory would be lost. */
- printk("FC: Reset in progress. Now?!");
- }
- }
-#endif
- FCND(("Unregistered\n"));
- }
- } else
- printk ("FC: %segistering unknown type %02x\n", unregister ? "Unr" : "R", type);
-}
-
-static void fcp_scsi_done(struct scsi_cmnd *SCpnt);
-
-static inline void fcp_scsi_receive(fc_channel *fc, int token, int status, fc_hdr *fch)
-{
- fcp_cmnd *fcmd;
- fcp_rsp *rsp;
- int host_status;
- struct scsi_cmnd *SCpnt;
- int sense_len;
- int rsp_status;
-
- fcmd = fc->cmd_slots[token];
- if (!fcmd) return;
- rsp = (fcp_rsp *) (fc->scsi_rsp_pool + fc->rsp_size * token);
- SCpnt = SC_FCMND(fcmd);
-
- if (SCpnt->done != fcp_scsi_done)
- return;
-
- rsp_status = rsp->fcp_status;
- FCD(("rsp_status %08x status %08x\n", rsp_status, status))
- switch (status) {
- case FC_STATUS_OK:
- host_status=DID_OK;
-
- if (rsp_status & FCP_STATUS_RESID) {
-#ifdef FCDEBUG
- FCD(("Resid %d\n", rsp->fcp_resid))
- {
- fcp_cmd *cmd = fc->scsi_cmd_pool + token;
- int i;
-
- printk ("Command ");
- for (i = 0; i < sizeof(fcp_cmd); i+=4)
- printk ("%08x ", *(u32 *)(((char *)cmd)+i));
- printk ("\nResponse ");
- for (i = 0; i < fc->rsp_size; i+=4)
- printk ("%08x ", *(u32 *)(((char *)rsp)+i));
- printk ("\n");
- }
-#endif
- }
-
- if (rsp_status & FCP_STATUS_SENSE_LEN) {
- sense_len = rsp->fcp_sense_len;
- if (sense_len > sizeof(SCpnt->sense_buffer)) sense_len = sizeof(SCpnt->sense_buffer);
- memcpy(SCpnt->sense_buffer, ((char *)(rsp+1)), sense_len);
- }
-
- if (fcmd->data)
- dma_unmap_sg(fc->dev, scsi_sglist(SCpnt),
- scsi_sg_count(SCpnt),
- SCpnt->sc_data_direction);
- break;
- default:
- host_status=DID_ERROR; /* FIXME */
- FCD(("Wrong FC status %d for token %d\n", status, token))
- break;
- }
-
- if (status_byte(rsp_status) == QUEUE_FULL) {
- printk ("%s: (%d,%d) Received rsp_status 0x%x\n", fc->name, SCpnt->device->channel, SCpnt->device->id, rsp_status);
- }
-
- SCpnt->result = (host_status << 16) | (rsp_status & 0xff);
-#ifdef FCDEBUG
- if (host_status || SCpnt->result || rsp_status) printk("FC: host_status %d, packet status %d\n",
- host_status, SCpnt->result);
-#endif
- SCpnt->done = fcmd->done;
- fcmd->done=NULL;
- clear_bit(token, fc->scsi_bitmap);
- fc->scsi_free++;
- FCD(("Calling scsi_done with %08x\n", SCpnt->result))
- SCpnt->scsi_done(SCpnt);
-}
-
-void fcp_receive_solicited(fc_channel *fc, int proto, int token, int status, fc_hdr *fch)
-{
- int magic;
- FCD(("receive_solicited %d %d %d\n", proto, token, status))
- switch (proto) {
- case TYPE_SCSI_FCP:
- fcp_scsi_receive(fc, token, status, fch); break;
- case TYPE_EXTENDED_LS:
- case PROTO_REPORT_AL_MAP:
- magic = 0;
- if (fc->ls)
- magic = ((ls *)(fc->ls))->magic;
- if (magic == LSMAGIC) {
- ls *l = (ls *)fc->ls;
- int i = (token >= l->count) ? token - l->count : token;
-
- /* Let's be sure */
- if ((unsigned)i < l->count && l->fcmds[i].fc == fc) {
- if (proto == TYPE_EXTENDED_LS)
- fcp_login_done(fc, token, status);
- else
- fcp_report_map_done(fc, token, status);
- break;
- }
- }
- FCD(("fc %p fc->ls %p fc->cmd_slots %p\n", fc, fc->ls, fc->cmd_slots))
- if (proto == TYPE_EXTENDED_LS && !fc->ls && fc->cmd_slots) {
- fcp_cmnd *fcmd;
-
- fcmd = fc->cmd_slots[token];
- if (fcmd && fcmd->ls && ((ls *)(fcmd->ls))->magic == LSEMAGIC) {
- lse *l = (lse *)fcmd->ls;
-
- l->status = status;
- up (&l->sem);
- }
- }
- break;
- case PROTO_OFFLINE:
- if (fc->ls && ((lso *)(fc->ls))->magic == LSOMAGIC) {
- lso *l = (lso *)fc->ls;
-
- if ((unsigned)token < l->count && l->fcmds[token].fc == fc) {
- /* Wow, OFFLINE response arrived :) */
- FCD(("OFFLINE Response arrived\n"))
- fc->state = FC_STATE_OFFLINE;
- if (atomic_dec_and_test (&l->todo))
- up(&l->sem);
- }
- }
- break;
-
- default:
- break;
- }
-}
-
-void fcp_state_change(fc_channel *fc, int state)
-{
- FCD(("state_change %d %d\n", state, fc->state))
- if (state == FC_STATE_ONLINE && fc->state == FC_STATE_MAYBEOFFLINE)
- fc->state = FC_STATE_UNINITED;
- else if (state == FC_STATE_ONLINE)
- printk (KERN_WARNING "%s: state change to ONLINE\n", fc->name);
- else
- printk (KERN_ERR "%s: state change to OFFLINE\n", fc->name);
-}
-
-int fcp_initialize(fc_channel *fcchain, int count)
-{
- fc_channel *fc;
- fcp_cmnd *fcmd;
- int i, retry, ret;
- ls *l;
-
- FCND(("fcp_inititialize %08lx\n", (long)fcp_init))
- FCND(("fc_channels %08lx\n", (long)fc_channels))
- FCND((" SID %d DID %d\n", fcchain->sid, fcchain->did))
- l = kzalloc(sizeof (ls) + count, GFP_KERNEL);
- if (!l) {
- printk ("FC: Cannot allocate memory for initialization\n");
- return -ENOMEM;
- }
- l->magic = LSMAGIC;
- l->count = count;
- FCND(("FCP Init for %d channels\n", count))
- init_MUTEX_LOCKED(&l->sem);
- init_timer(&l->timer);
- l->timer.function = fcp_login_timeout;
- l->timer.data = (unsigned long)l;
- atomic_set (&l->todo, count);
- l->logi = kzalloc (count * 3 * sizeof(logi), GFP_KERNEL);
- l->fcmds = kzalloc (count * sizeof(fcp_cmnd), GFP_KERNEL);
- if (!l->logi || !l->fcmds) {
- kfree (l->logi);
- kfree (l->fcmds);
- kfree (l);
- printk ("FC: Cannot allocate DMA memory for initialization\n");
- return -ENOMEM;
- }
- for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) {
- fc->state = FC_STATE_UNINITED;
- fc->rst_pkt = NULL; /* kmalloc when first used */
- }
- /* First try if we are in a AL topology */
- FCND(("Initializing REPORT_MAP packets\n"))
- for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) {
- fcmd = l->fcmds + i;
- fc->login = fcmd;
- fc->ls = (void *)l;
- /* Assumes sizeof(fc_al_posmap) < 3 * sizeof(logi), which is true */
- fcmd->cmd = dma_map_single (fc->dev, l->logi + 3 * i, 3 * sizeof(logi),
- DMA_BIDIRECTIONAL);
- fcmd->proto = PROTO_REPORT_AL_MAP;
- fcmd->token = i;
- fcmd->fc = fc;
- }
- for (retry = 0; retry < 8; retry++) {
- int nqueued = 0;
- FCND(("Sending REPORT_MAP/FLOGI/PLOGI packets\n"))
- for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) {
- if (fc->state == FC_STATE_ONLINE || fc->state == FC_STATE_OFFLINE)
- continue;
- disable_irq(fc->irq);
- if (fc->state == FC_STATE_MAYBEOFFLINE) {
- if (!l->grace[i]) {
- l->grace[i]++;
- FCD(("Grace\n"))
- } else {
- fc->state = FC_STATE_OFFLINE;
- enable_irq(fc->irq);
- dma_unmap_single (fc->dev, l->fcmds[i].cmd, 3 * sizeof(logi), DMA_BIDIRECTIONAL);
- if (atomic_dec_and_test (&l->todo))
- goto all_done;
- }
- }
- ret = fc->hw_enque (fc, fc->login);
- enable_irq(fc->irq);
- if (!ret) {
- nqueued++;
- continue;
- }
- if (ret == -ENOSYS && fc->login->proto == PROTO_REPORT_AL_MAP) {
- /* Oh yes, this card handles Point-to-Point only, so let's try that. */
- fc_hdr *fch;
-
- FCD(("SID %d DID %d\n", fc->sid, fc->did))
- fcmd = l->fcmds + i;
- dma_unmap_single(fc->dev, fcmd->cmd, 3 * sizeof(logi), DMA_BIDIRECTIONAL);
- fch = &fcmd->fch;
- FILL_FCHDR_RCTL_DID(fch, R_CTL_ELS_REQ, FS_FABRIC_F_PORT);
- FILL_FCHDR_SID(fch, 0);
- FILL_FCHDR_TYPE_FCTL(fch, TYPE_EXTENDED_LS, F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE);
- FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0);
- FILL_FCHDR_OXRX(fch, 0xffff, 0xffff);
- fch->param = 0;
- l->logi [3 * i].code = LS_FLOGI;
- fcmd->cmd = dma_map_single (fc->dev, l->logi + 3 * i, 3 * sizeof(logi), DMA_BIDIRECTIONAL);
- fcmd->rsp = fcmd->cmd + sizeof(logi);
- fcmd->cmdlen = sizeof(logi);
- fcmd->rsplen = sizeof(logi);
- fcmd->data = (dma_addr_t)NULL;
- fcmd->class = FC_CLASS_SIMPLE;
- fcmd->proto = TYPE_EXTENDED_LS;
- } else
- printk ("FC: Cannot enque FLOGI/REPORT_MAP packet on %s\n", fc->name);
- }
-
- if (nqueued) {
- l->timer.expires = jiffies + 5 * HZ;
- add_timer(&l->timer);
-
- down(&l->sem);
- if (!atomic_read(&l->todo)) {
- FCND(("All channels answered in time\n"))
- break; /* All fc channels have answered us */
- }
- }
- }
-all_done:
- for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) {
- fc->ls = NULL;
- switch (fc->state) {
- case FC_STATE_ONLINE: break;
- case FC_STATE_OFFLINE: break;
- default: dma_unmap_single (fc->dev, l->fcmds[i].cmd, 3 * sizeof(logi), DMA_BIDIRECTIONAL);
- break;
- }
- }
- del_timer(&l->timer);
- kfree (l->logi);
- kfree (l->fcmds);
- kfree (l);
- return 0;
-}
-
-int fcp_forceoffline(fc_channel *fcchain, int count)
-{
- fc_channel *fc;
- fcp_cmnd *fcmd;
- int i, ret;
- lso l;
-
- memset (&l, 0, sizeof(lso));
- l.count = count;
- l.magic = LSOMAGIC;
- FCND(("FCP Force Offline for %d channels\n", count))
- init_MUTEX_LOCKED(&l.sem);
- init_timer(&l.timer);
- l.timer.function = fcp_login_timeout;
- l.timer.data = (unsigned long)&l;
- atomic_set (&l.todo, count);
- l.fcmds = kzalloc (count * sizeof(fcp_cmnd), GFP_KERNEL);
- if (!l.fcmds) {
- printk ("FC: Cannot allocate memory for forcing offline\n");
- return -ENOMEM;
- }
- FCND(("Initializing OFFLINE packets\n"))
- for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) {
- fc->state = FC_STATE_UNINITED;
- fcmd = l.fcmds + i;
- fc->login = fcmd;
- fc->ls = (void *)&l;
- fcmd->did = fc->did;
- fcmd->class = FC_CLASS_OFFLINE;
- fcmd->proto = PROTO_OFFLINE;
- fcmd->token = i;
- fcmd->fc = fc;
- disable_irq(fc->irq);
- ret = fc->hw_enque (fc, fc->login);
- enable_irq(fc->irq);
- if (ret) printk ("FC: Cannot enque OFFLINE packet on %s\n", fc->name);
- }
-
- l.timer.expires = jiffies + 5 * HZ;
- add_timer(&l.timer);
- down(&l.sem);
- del_timer(&l.timer);
-
- for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++)
- fc->ls = NULL;
- kfree (l.fcmds);
- return 0;
-}
-
-int fcp_init(fc_channel *fcchain)
-{
- fc_channel *fc;
- int count=0;
- int ret;
-
- for (fc = fcchain; fc; fc = fc->next) {
- fc->fcp_register = fcp_register;
- count++;
- }
-
- ret = fcp_initialize (fcchain, count);
- if (ret)
- return ret;
-
- if (!fc_channels)
- fc_channels = fcchain;
- else {
- for (fc = fc_channels; fc->next; fc = fc->next);
- fc->next = fcchain;
- }
- return ret;
-}
-
-void fcp_release(fc_channel *fcchain, int count) /* count must > 0 */
-{
- fc_channel *fc;
- fc_channel *fcx;
-
- for (fc = fcchain; --count && fc->next; fc = fc->next);
- if (count) {
- printk("FC: nothing to release\n");
- return;
- }
-
- if (fc_channels == fcchain)
- fc_channels = fc->next;
- else {
- for (fcx = fc_channels; fcx->next != fcchain; fcx = fcx->next);
- fcx->next = fc->next;
- }
- fc->next = NULL;
-
- /*
- * We've just grabbed fcchain out of the fc_channel list
- * and zero-terminated it, while destroying the count.
- *
- * Freeing the fc's is the low level driver's responsibility.
- */
-}
-
-
-static void fcp_scsi_done(struct scsi_cmnd *SCpnt)
-{
- if (FCP_CMND(SCpnt)->done)
- FCP_CMND(SCpnt)->done(SCpnt);
-}
-
-static int fcp_scsi_queue_it(fc_channel *fc, struct scsi_cmnd *SCpnt,
- fcp_cmnd *fcmd, int prepare)
-{
- long i;
- fcp_cmd *cmd;
- u32 fcp_cntl;
- if (prepare) {
- i = find_first_zero_bit (fc->scsi_bitmap, fc->scsi_bitmap_end);
- set_bit (i, fc->scsi_bitmap);
- fcmd->token = i;
- cmd = fc->scsi_cmd_pool + i;
-
- if (fc->encode_addr (SCpnt, cmd->fcp_addr, fc, fcmd)) {
- /* Invalid channel/id/lun and couldn't map it into fcp_addr */
- clear_bit (i, fc->scsi_bitmap);
- SCpnt->result = (DID_BAD_TARGET << 16);
- SCpnt->scsi_done(SCpnt);
- return 0;
- }
- fc->scsi_free--;
- fc->cmd_slots[fcmd->token] = fcmd;
-
- if (SCpnt->device->tagged_supported) {
- if (jiffies - fc->ages[SCpnt->device->channel * fc->targets + SCpnt->device->id] > (5 * 60 * HZ)) {
- fc->ages[SCpnt->device->channel * fc->targets + SCpnt->device->id] = jiffies;
- fcp_cntl = FCP_CNTL_QTYPE_ORDERED;
- } else
- fcp_cntl = FCP_CNTL_QTYPE_SIMPLE;
- } else
- fcp_cntl = FCP_CNTL_QTYPE_UNTAGGED;
-
- if (!scsi_bufflen(SCpnt)) {
- cmd->fcp_cntl = fcp_cntl;
- fcmd->data = (dma_addr_t)NULL;
- } else {
- struct scatterlist *sg;
- int nents;
-
- switch (SCpnt->cmnd[0]) {
- case WRITE_6:
- case WRITE_10:
- case WRITE_12:
- cmd->fcp_cntl = (FCP_CNTL_WRITE | fcp_cntl); break;
- default:
- cmd->fcp_cntl = (FCP_CNTL_READ | fcp_cntl); break;
- }
-
- sg = scsi_sglist(SCpnt);
- nents = dma_map_sg(fc->dev, sg, scsi_sg_count(SCpnt),
- SCpnt->sc_data_direction);
- fcmd->data = sg_dma_address(sg);
- cmd->fcp_data_len = sg_dma_len(sg);
- }
- memcpy (cmd->fcp_cdb, SCpnt->cmnd, SCpnt->cmd_len);
- memset (cmd->fcp_cdb+SCpnt->cmd_len, 0, sizeof(cmd->fcp_cdb)-SCpnt->cmd_len);
- FCD(("XXX: %04x.%04x.%04x.%04x - %08x%08x%08x\n", cmd->fcp_addr[0], cmd->fcp_addr[1], cmd->fcp_addr[2], cmd->fcp_addr[3], *(u32 *)SCpnt->cmnd, *(u32 *)(SCpnt->cmnd+4), *(u32 *)(SCpnt->cmnd+8)))
- }
- FCD(("Trying to enque %p\n", fcmd))
- if (!fc->scsi_que) {
- if (!fc->hw_enque (fc, fcmd)) {
- FCD(("hw_enque succeeded for %p\n", fcmd))
- return 0;
- }
- }
- FCD(("Putting into que1 %p\n", fcmd))
- fcp_scsi_insert_queue (fc, fcmd);
- return 0;
-}
-
-int fcp_scsi_queuecommand(struct scsi_cmnd *SCpnt,
- void (* done)(struct scsi_cmnd *))
-{
- fcp_cmnd *fcmd = FCP_CMND(SCpnt);
- fc_channel *fc = FC_SCMND(SCpnt);
-
- FCD(("Entering SCSI queuecommand %p\n", fcmd))
- if (SCpnt->done != fcp_scsi_done) {
- fcmd->done = SCpnt->done;
- SCpnt->done = fcp_scsi_done;
- SCpnt->scsi_done = done;
- fcmd->proto = TYPE_SCSI_FCP;
- if (!fc->scsi_free) {
- FCD(("FC: !scsi_free, putting cmd on ML queue\n"))
-#if (FCP_SCSI_USE_NEW_EH_CODE == 0)
- printk("fcp_scsi_queue_command: queue full, losing cmd, bad\n");
-#endif
- return 1;
- }
- return fcp_scsi_queue_it(fc, SCpnt, fcmd, 1);
- }
- return fcp_scsi_queue_it(fc, SCpnt, fcmd, 0);
-}
-
-void fcp_queue_empty(fc_channel *fc)
-{
- fcp_cmnd *fcmd;
-
- FCD(("Queue empty\n"))
- while ((fcmd = fc->scsi_que)) {
- /* The hw told us we can try again queue some packet */
- if (fc->hw_enque (fc, fcmd))
- break;
- fcp_scsi_remove_queue (fc, fcmd);
- }
-}
-
-int fcp_scsi_abort(struct scsi_cmnd *SCpnt)
-{
- /* Internal bookkeeping only. Lose 1 cmd_slots slot. */
- fcp_cmnd *fcmd = FCP_CMND(SCpnt);
- fc_channel *fc = FC_SCMND(SCpnt);
-
- /*
- * We react to abort requests by simply forgetting
- * about the command and pretending everything's sweet.
- * This may or may not be silly. We can't, however,
- * immediately reuse the command's cmd_slots slot,
- * as its result may arrive later and we cannot
- * check whether it is the aborted one, can't we?
- *
- * Therefore, after the first few aborts are done,
- * we tell the scsi error handler to do something clever.
- * It will eventually call host reset, refreshing
- * cmd_slots for us.
- *
- * There is a theoretical chance that we sometimes allow
- * more than can_queue packets to the jungle this way,
- * but the worst outcome possible is a series of
- * more aborts and eventually the dev_reset catharsis.
- */
-
- if (++fc->abort_count < (fc->can_queue >> 1)) {
- SCpnt->result = DID_ABORT;
- fcmd->done(SCpnt);
- printk("FC: soft abort\n");
- return SUCCESS;
- } else {
- printk("FC: hard abort refused\n");
- return FAILED;
- }
-}
-
-#if 0
-void fcp_scsi_reset_done(struct scsi_cmnd *SCpnt)
-{
- fc_channel *fc = FC_SCMND(SCpnt);
-
- fc->rst_pkt->eh_state = SCSI_STATE_FINISHED;
- up(fc->rst_pkt->device->host->eh_action);
-}
-#endif
-
-#define FCP_RESET_TIMEOUT (2*HZ)
-
-int fcp_scsi_dev_reset(struct scsi_cmnd *SCpnt)
-{
-#if 0 /* broken junk, but if davem wants to compile this driver, let him.. */
- unsigned long flags;
- fcp_cmd *cmd;
- fcp_cmnd *fcmd;
- fc_channel *fc = FC_SCMND(SCpnt);
- DECLARE_MUTEX_LOCKED(sem);
-
- if (!fc->rst_pkt) {
- fc->rst_pkt = kmalloc(sizeof(SCpnt), GFP_KERNEL);
- if (!fc->rst_pkt) return FAILED;
-
- fcmd = FCP_CMND(fc->rst_pkt);
-
-
- fcmd->token = 0;
- cmd = fc->scsi_cmd_pool + 0;
- FCD(("Preparing rst packet\n"))
- fc->encode_addr (SCpnt, cmd->fcp_addr, fc, fcmd);
- fc->rst_pkt->device = SCpnt->device;
- fc->rst_pkt->cmd_len = 0;
-
- fc->cmd_slots[0] = fcmd;
-
- cmd->fcp_cntl = FCP_CNTL_QTYPE_ORDERED | FCP_CNTL_RESET;
- fcmd->data = (dma_addr_t)NULL;
- fcmd->proto = TYPE_SCSI_FCP;
-
- memcpy (cmd->fcp_cdb, SCpnt->cmnd, SCpnt->cmd_len);
- memset (cmd->fcp_cdb+SCpnt->cmd_len, 0, sizeof(cmd->fcp_cdb)-SCpnt->cmd_len);
- FCD(("XXX: %04x.%04x.%04x.%04x - %08x%08x%08x\n", cmd->fcp_addr[0], cmd->fcp_addr[1], cmd->fcp_addr[2], cmd->fcp_addr[3], *(u32 *)SCpnt->cmnd, *(u32 *)(SCpnt->cmnd+4), *(u32 *)(SCpnt->cmnd+8)))
- } else {
- fcmd = FCP_CMND(fc->rst_pkt);
- if (fc->rst_pkt->eh_state == SCSI_STATE_QUEUED)
- return FAILED; /* or SUCCESS. Only these */
- }
- fc->rst_pkt->done = NULL;
-
-
- fc->rst_pkt->eh_state = SCSI_STATE_QUEUED;
- init_timer(&fc->rst_pkt->eh_timeout);
- fc->rst_pkt->eh_timeout.data = (unsigned long) fc->rst_pkt;
- fc->rst_pkt->eh_timeout.expires = jiffies + FCP_RESET_TIMEOUT;
- fc->rst_pkt->eh_timeout.function = (void (*)(unsigned long))fcp_scsi_reset_done;
-
- add_timer(&fc->rst_pkt->eh_timeout);
-
- /*
- * Set up the semaphore so we wait for the command to complete.
- */
-
- fc->rst_pkt->device->host->eh_action = &sem;
-
- fc->rst_pkt->done = fcp_scsi_reset_done;
-
- spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
- fcp_scsi_queue_it(fc, fc->rst_pkt, fcmd, 0);
- spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
-
- down(&sem);
-
- fc->rst_pkt->device->host->eh_action = NULL;
- del_timer(&fc->rst_pkt->eh_timeout);
-
- /*
- * See if timeout. If so, tell the host to forget about it.
- * In other words, we don't want a callback any more.
- */
- if (fc->rst_pkt->eh_state == SCSI_STATE_TIMEOUT ) {
- fc->rst_pkt->eh_state = SCSI_STATE_UNUSED;
- return FAILED;
- }
- fc->rst_pkt->eh_state = SCSI_STATE_UNUSED;
-#endif
- return SUCCESS;
-}
-
-static int __fcp_scsi_host_reset(struct scsi_cmnd *SCpnt)
-{
- fc_channel *fc = FC_SCMND(SCpnt);
- fcp_cmnd *fcmd = FCP_CMND(SCpnt);
- int i;
-
- printk ("FC: host reset\n");
-
- for (i=0; i < fc->can_queue; i++) {
- if (fc->cmd_slots[i] && SCpnt->result != DID_ABORT) {
- SCpnt->result = DID_RESET;
- fcmd->done(SCpnt);
- fc->cmd_slots[i] = NULL;
- }
- }
- fc->reset(fc);
- fc->abort_count = 0;
- if (fcp_initialize(fc, 1)) return SUCCESS;
- else return FAILED;
-}
-
-int fcp_scsi_host_reset(struct scsi_cmnd *SCpnt)
-{
- unsigned long flags;
- int rc;
-
- spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
- rc = __fcp_scsi_host_reset(SCpnt);
- spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
-
- return rc;
-}
-
-static int fcp_els_queue_it(fc_channel *fc, fcp_cmnd *fcmd)
-{
- long i;
-
- i = find_first_zero_bit (fc->scsi_bitmap, fc->scsi_bitmap_end);
- set_bit (i, fc->scsi_bitmap);
- fcmd->token = i;
- fc->scsi_free--;
- fc->cmd_slots[fcmd->token] = fcmd;
- return fcp_scsi_queue_it(fc, NULL, fcmd, 0);
-}
-
-static int fc_do_els(fc_channel *fc, unsigned int alpa, void *data, int len)
-{
- fcp_cmnd _fcmd, *fcmd;
- fc_hdr *fch;
- lse l;
- int i;
-
- fcmd = &_fcmd;
- memset(fcmd, 0, sizeof(fcp_cmnd));
- FCD(("PLOGI SID %d DID %d\n", fc->sid, alpa))
- fch = &fcmd->fch;
- FILL_FCHDR_RCTL_DID(fch, R_CTL_ELS_REQ, alpa);
- FILL_FCHDR_SID(fch, fc->sid);
- FILL_FCHDR_TYPE_FCTL(fch, TYPE_EXTENDED_LS, F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE);
- FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0);
- FILL_FCHDR_OXRX(fch, 0xffff, 0xffff);
- fch->param = 0;
- fcmd->cmd = dma_map_single (fc->dev, data, 2 * len, DMA_BIDIRECTIONAL);
- fcmd->rsp = fcmd->cmd + len;
- fcmd->cmdlen = len;
- fcmd->rsplen = len;
- fcmd->data = (dma_addr_t)NULL;
- fcmd->fc = fc;
- fcmd->class = FC_CLASS_SIMPLE;
- fcmd->proto = TYPE_EXTENDED_LS;
-
- memset (&l, 0, sizeof(lse));
- l.magic = LSEMAGIC;
- init_MUTEX_LOCKED(&l.sem);
- l.timer.function = fcp_login_timeout;
- l.timer.data = (unsigned long)&l;
- l.status = FC_STATUS_TIMED_OUT;
- fcmd->ls = (void *)&l;
-
- disable_irq(fc->irq);
- fcp_els_queue_it(fc, fcmd);
- enable_irq(fc->irq);
-
- for (i = 0;;) {
- l.timer.expires = jiffies + 5 * HZ;
- add_timer(&l.timer);
- down(&l.sem);
- del_timer(&l.timer);
- if (l.status != FC_STATUS_TIMED_OUT) break;
- if (++i == 3) break;
- disable_irq(fc->irq);
- fcp_scsi_queue_it(fc, NULL, fcmd, 0);
- enable_irq(fc->irq);
- }
-
- clear_bit(fcmd->token, fc->scsi_bitmap);
- fc->scsi_free++;
- dma_unmap_single (fc->dev, fcmd->cmd, 2 * len, DMA_BIDIRECTIONAL);
- return l.status;
-}
-
-int fc_do_plogi(fc_channel *fc, unsigned char alpa, fc_wwn *node, fc_wwn *nport)
-{
- logi *l;
- int status;
-
- l = kzalloc(2 * sizeof(logi), GFP_KERNEL);
- if (!l) return -ENOMEM;
- l->code = LS_PLOGI;
- memcpy (&l->nport_wwn, &fc->wwn_nport, sizeof(fc_wwn));
- memcpy (&l->node_wwn, &fc->wwn_node, sizeof(fc_wwn));
- memcpy (&l->common, fc->common_svc, sizeof(common_svc_parm));
- memcpy (&l->class1, fc->class_svcs, 3*sizeof(svc_parm));
- status = fc_do_els(fc, alpa, l, sizeof(logi));
- if (status == FC_STATUS_OK) {
- if (l[1].code == LS_ACC) {
-#ifdef FCDEBUG
- u32 *u = (u32 *)&l[1].nport_wwn;
- FCD(("AL-PA %02x: Port WWN %08x%08x Node WWN %08x%08x\n", alpa,
- u[0], u[1], u[2], u[3]))
-#endif
- memcpy(nport, &l[1].nport_wwn, sizeof(fc_wwn));
- memcpy(node, &l[1].node_wwn, sizeof(fc_wwn));
- } else
- status = FC_STATUS_BAD_RSP;
- }
- kfree(l);
- return status;
-}
-
-typedef struct {
- unsigned int code;
- unsigned params[4];
-} prli;
-
-int fc_do_prli(fc_channel *fc, unsigned char alpa)
-{
- prli *p;
- int status;
-
- p = kzalloc(2 * sizeof(prli), GFP_KERNEL);
- if (!p) return -ENOMEM;
- p->code = LS_PRLI;
- p->params[0] = 0x08002000;
- p->params[3] = 0x00000022;
- status = fc_do_els(fc, alpa, p, sizeof(prli));
- if (status == FC_STATUS_OK && p[1].code != LS_PRLI_ACC && p[1].code != LS_ACC)
- status = FC_STATUS_BAD_RSP;
- kfree(p);
- return status;
-}
-
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/fc4/fc.h b/drivers/fc4/fc.h
deleted file mode 100644
index 13f89d4c8cb9..000000000000
--- a/drivers/fc4/fc.h
+++ /dev/null
@@ -1,230 +0,0 @@
-/* fc.h: Definitions for Fibre Channel Physical and Signaling Interface.
- *
- * Copyright (C) 1996-1997,1999 Jakub Jelinek (jj@ultra.linux.cz)
- *
- * Sources:
- * Fibre Channel Physical & Signaling Interface (FC-PH), dpANS, 1994
- * dpANS Fibre Channel Protocol for SCSI (X3.269-199X), Rev. 012, 1995
- */
-
-#ifndef __FC_H
-#define __FC_H
-
-/* World Wide Name */
-#define NAAID_IEEE 1
-#define NAAID_IEEE_EXT 2
-#define NAAID_LOCAL 3
-#define NAAID_IP 4
-#define NAAID_IEEE_REG 5
-#define NAAID_IEEE_REG_EXT 6
-#define NAAID_CCITT 12
-#define NAAID_CCITT_GRP 14
-
-/* This is NAAID_IEEE_EXT scheme */
-typedef struct {
- u32 naaid:4;
- u32 nportid:12;
- u32 hi:16;
- u32 lo;
-} fc_wwn;
-
-/* Frame header for FC-PH frames */
-
-/* r_ctl field */
-#define R_CTL_DEVICE_DATA 0x00 /* FC4 Device_Data frame */
-#define R_CTL_EXTENDED_SVC 0x20 /* Extended Link_Data frame */
-#define R_CTL_FC4_SVC 0x30 /* FC4 Link_Data frame */
-#define R_CTL_VIDEO 0x40 /* Video_Data frame */
-#define R_CTL_BASIC_SVC 0x80 /* Basic Link_Data frame */
-#define R_CTL_LINK_CTL 0xc0 /* Link_Control frame */
-/* FC4 Device_Data frames */
-#define R_CTL_UNCATEGORIZED 0x00
-#define R_CTL_SOLICITED_DATA 0x01
-#define R_CTL_UNSOL_CONTROL 0x02
-#define R_CTL_SOLICITED_CONTROL 0x03
-#define R_CTL_UNSOL_DATA 0x04
-#define R_CTL_XFER_RDY 0x05
-#define R_CTL_COMMAND 0x06
-#define R_CTL_STATUS 0x07
-/* Basic Link_Data frames */
-#define R_CTL_LS_NOP 0x80
-#define R_CTL_LS_ABTS 0x81
-#define R_CTL_LS_RMC 0x82
-#define R_CTL_LS_BA_ACC 0x84
-#define R_CTL_LS_BA_RJT 0x85
-/* Extended Link_Data frames */
-#define R_CTL_ELS_REQ 0x22
-#define R_CTL_ELS_RSP 0x23
-/* Link_Control frames */
-#define R_CTL_ACK_1 0xc0
-#define R_CTL_ACK_N 0xc1
-#define R_CTL_P_RJT 0xc2
-#define R_CTL_F_RJT 0xc3
-#define R_CTL_P_BSY 0xc4
-#define R_CTL_F_BSY_DF 0xc5
-#define R_CTL_F_BSY_LC 0xc6
-#define R_CTL_LCR 0xc7
-
-/* type field */
-#define TYPE_BASIC_LS 0x00
-#define TYPE_EXTENDED_LS 0x01
-#define TYPE_IS8802 0x04
-#define TYPE_IS8802_SNAP 0x05
-#define TYPE_SCSI_FCP 0x08
-#define TYPE_SCSI_GPP 0x09
-#define TYPE_HIPP_FP 0x0a
-#define TYPE_IPI3_MASTER 0x11
-#define TYPE_IPI3_SLAVE 0x12
-#define TYPE_IPI3_PEER 0x13
-
-/* f_ctl field */
-#define F_CTL_FILL_BYTES 0x000003
-#define F_CTL_XCHG_REASSEMBLE 0x000004
-#define F_CTL_RO_PRESENT 0x000008
-#define F_CTL_ABORT_SEQ 0x000030
-#define F_CTL_CONTINUE_SEQ 0x0000c0
-#define F_CTL_INVALIDATE_XID 0x004000
-#define F_CTL_XID_REASSIGNED 0x008000
-#define F_CTL_SEQ_INITIATIVE 0x010000
-#define F_CTL_CHAINED_SEQ 0x020000
-#define F_CTL_END_CONNECT 0x040000
-#define F_CTL_END_SEQ 0x080000
-#define F_CTL_LAST_SEQ 0x100000
-#define F_CTL_FIRST_SEQ 0x200000
-#define F_CTL_SEQ_CONTEXT 0x400000
-#define F_CTL_XCHG_CONTEXT 0x800000
-
-typedef struct {
- u32 r_ctl:8, did:24;
- u32 xxx1:8, sid:24;
- u32 type:8, f_ctl:24;
- u32 seq_id:8, df_ctl:8, seq_cnt:16;
- u16 ox_id, rx_id;
- u32 param;
-} fc_hdr;
-/* The following are ugly macros to make setup of this structure faster */
-#define FILL_FCHDR_RCTL_DID(fch, r_ctl, did) *(u32 *)(fch) = ((r_ctl) << 24) | (did);
-#define FILL_FCHDR_SID(fch, sid) *((u32 *)(fch)+1) = (sid);
-#define FILL_FCHDR_TYPE_FCTL(fch, type, f_ctl) *((u32 *)(fch)+2) = ((type) << 24) | (f_ctl);
-#define FILL_FCHDR_SEQ_DF_SEQ(fch, seq_id, df_ctl, seq_cnt) *((u32 *)(fch)+3) = ((seq_id) << 24) | ((df_ctl) << 16) | (seq_cnt);
-#define FILL_FCHDR_OXRX(fch, ox_id, rx_id) *((u32 *)(fch)+4) = ((ox_id) << 16) | (rx_id);
-
-/* Well known addresses */
-#define FS_GENERAL_MULTICAST 0xfffff7
-#define FS_WELL_KNOWN_MULTICAST 0xfffff8
-#define FS_HUNT_GROUP 0xfffff9
-#define FS_MANAGEMENT_SERVER 0xfffffa
-#define FS_TIME_SERVER 0xfffffb
-#define FS_NAME_SERVER 0xfffffc
-#define FS_FABRIC_CONTROLLER 0xfffffd
-#define FS_FABRIC_F_PORT 0xfffffe
-#define FS_BROADCAST 0xffffff
-
-/* Reject frames */
-/* The param field should be cast to this structure */
-typedef struct {
- u8 action;
- u8 reason;
- u8 xxx;
- u8 vendor_unique;
-} rjt_param;
-
-/* Reject action codes */
-#define RJT_RETRY 0x01
-#define RJT_NONRETRY 0x02
-
-/* Reject reason codes */
-#define RJT_INVALID_DID 0x01
-#define RJT_INVALID_SID 0x02
-#define RJT_NPORT_NOT_AVAIL_TEMP 0x03
-#define RJT_NPORT_NOT_AVAIL_PERM 0x04
-#define RJT_CLASS_NOT_SUPPORTED 0x05
-#define RJT_DELIMITER_ERROR 0x06
-#define RJT_TYPE_NOT_SUPPORTED 0x07
-#define RJT_INVALID_LINK_CONTROL 0x08
-#define RJT_INVALID_R_CTL 0x09
-#define RJT_INVALID_F_CTL 0x0a
-#define RJT_INVALID_OX_ID 0x0b
-#define RJT_INVALID_RX_ID 0x0c
-#define RJT_INVALID_SEQ_ID 0x0d
-#define RJT_INVALID_DF_CTL 0x0e
-#define RJT_INVALID_SEQ_CNT 0x0f
-#define RJT_INVALID_PARAMETER 0x10
-#define RJT_EXCHANGE_ERROR 0x11
-#define RJT_PROTOCOL_ERROR 0x12
-#define RJT_INCORRECT_LENGTH 0x13
-#define RJT_UNEXPECTED_ACK 0x14
-#define RJT_UNEXPECTED_LINK_RESP 0x15
-#define RJT_LOGIN_REQUIRED 0x16
-#define RJT_EXCESSIVE_SEQUENCES 0x17
-#define RJT_CANT_ESTABLISH_EXCHANGE 0x18
-#define RJT_SECURITY_NOT_SUPPORTED 0x19
-#define RJT_FABRIC_NA 0x1a
-#define RJT_VENDOR_UNIQUE 0xff
-
-
-#define SP_F_PORT_LOGIN 0x10
-
-/* Extended SVC commands */
-#define LS_RJT 0x01000000
-#define LS_ACC 0x02000000
-#define LS_PRLI_ACC 0x02100014
-#define LS_PLOGI 0x03000000
-#define LS_FLOGI 0x04000000
-#define LS_LOGO 0x05000000
-#define LS_ABTX 0x06000000
-#define LS_RCS 0x07000000
-#define LS_RES 0x08000000
-#define LS_RSS 0x09000000
-#define LS_RSI 0x0a000000
-#define LS_ESTS 0x0b000000
-#define LS_ESTC 0x0c000000
-#define LS_ADVC 0x0d000000
-#define LS_RTV 0x0e000000
-#define LS_RLS 0x0f000000
-#define LS_ECHO 0x10000000
-#define LS_TEST 0x11000000
-#define LS_RRQ 0x12000000
-#define LS_IDENT 0x20000000
-#define LS_PRLI 0x20100014
-#define LS_DISPLAY 0x21000000
-#define LS_PRLO 0x21100014
-#define LS_PDISC 0x50000000
-#define LS_ADISC 0x52000000
-
-typedef struct {
- u8 fcph_hi, fcph_lo;
- u16 buf2buf_credit;
- u8 common_features;
- u8 xxx1;
- u16 buf2buf_size;
- u8 xxx2;
- u8 total_concurrent;
- u16 off_by_info;
- u32 e_d_tov;
-} common_svc_parm;
-
-typedef struct {
- u16 serv_opts;
- u16 initiator_ctl;
- u16 rcpt_ctl;
- u16 recv_size;
- u8 xxx1;
- u8 concurrent_seqs;
- u16 end2end_credit;
- u16 open_seqs_per_xchg;
- u16 xxx2;
-} svc_parm;
-
-/* Login */
-typedef struct {
- u32 code;
- common_svc_parm common;
- fc_wwn nport_wwn;
- fc_wwn node_wwn;
- svc_parm class1;
- svc_parm class2;
- svc_parm class3;
-} logi;
-
-#endif /* !(__FC_H) */
diff --git a/drivers/fc4/fc_syms.c b/drivers/fc4/fc_syms.c
deleted file mode 100644
index bd3918ddf7ac..000000000000
--- a/drivers/fc4/fc_syms.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * We should not even be trying to compile this if we are not doing
- * a module.
- */
-#include <linux/module.h>
-
-#ifdef CONFIG_MODULES
-
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-
-#include "fcp_impl.h"
-
-EXPORT_SYMBOL(fcp_init);
-EXPORT_SYMBOL(fcp_release);
-EXPORT_SYMBOL(fcp_queue_empty);
-EXPORT_SYMBOL(fcp_receive_solicited);
-EXPORT_SYMBOL(fc_channels);
-EXPORT_SYMBOL(fcp_state_change);
-EXPORT_SYMBOL(fc_do_plogi);
-EXPORT_SYMBOL(fc_do_prli);
-
-/* SCSI stuff */
-EXPORT_SYMBOL(fcp_scsi_queuecommand);
-EXPORT_SYMBOL(fcp_scsi_abort);
-EXPORT_SYMBOL(fcp_scsi_dev_reset);
-EXPORT_SYMBOL(fcp_scsi_host_reset);
-
-#endif /* CONFIG_MODULES */
diff --git a/drivers/fc4/fcp.h b/drivers/fc4/fcp.h
deleted file mode 100644
index 6aa34a7a4c11..000000000000
--- a/drivers/fc4/fcp.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/* fcp.h: Definitions for Fibre Channel Protocol.
- *
- * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- *
- */
-
-#ifndef __FCP_H
-#define __FCP_H
-
-/* FCP addressing is hierarchical with up to 4 layers, MS first.
- Exact meaning of the addresses is up to the vendor */
-
-/* fcp_cntl field */
-#define FCP_CNTL_WRITE 0x00000001 /* Initiator write */
-#define FCP_CNTL_READ 0x00000002 /* Initiator read */
-#define FCP_CNTL_ABORT_TSK 0x00000200 /* Abort task set */
-#define FCP_CNTL_CLR_TASK 0x00000400 /* Clear task set */
-#define FCP_CNTL_RESET 0x00002000 /* Reset */
-#define FCP_CNTL_CLR_ACA 0x00004000 /* Clear ACA */
-#define FCP_CNTL_KILL_TASK 0x00008000 /* Terminate task */
-#define FCP_CNTL_QTYPE_MASK 0x00070000 /* Tagged queueing type */
-#define FCP_CNTL_QTYPE_SIMPLE 0x00000000
-#define FCP_CNTL_QTYPE_HEAD_OF_Q 0x00010000
-#define FCP_CNTL_QTYPE_ORDERED 0x00020000
-#define FCP_CNTL_QTYPE_ACA_Q_TAG 0x00040000
-#define FCP_CNTL_QTYPE_UNTAGGED 0x00050000
-
-typedef struct {
- u16 fcp_addr[4];
- u32 fcp_cntl;
- u8 fcp_cdb[16];
- u32 fcp_data_len;
-} fcp_cmd;
-
-/* fcp_status field */
-#define FCP_STATUS_MASK 0x000000ff /* scsi status of command */
-#define FCP_STATUS_RSP_LEN 0x00000100 /* response_len != 0 */
-#define FCP_STATUS_SENSE_LEN 0x00000200 /* sense_len != 0 */
-#define FCP_STATUS_RESID 0x00000400 /* resid != 0 */
-
-typedef struct {
- u32 xxx[2];
- u32 fcp_status;
- u32 fcp_resid;
- u32 fcp_sense_len;
- u32 fcp_response_len;
- /* u8 fcp_sense[fcp_sense_len]; */
- /* u8 fcp_response[fcp_response_len]; */
-} fcp_rsp;
-
-/* fcp errors */
-
-/* rsp_info_type field */
-#define FCP_RSP_SCSI_BUS_ERR 0x01
-#define FCP_RSP_SCSI_PORT_ERR 0x02
-#define FCP_RSP_CARD_ERR 0x03
-
-/* isp_status field */
-#define FCP_RSP_CMD_COMPLETE 0x0000
-#define FCP_RSP_CMD_INCOMPLETE 0x0001
-#define FCP_RSP_CMD_DMA_ERR 0x0002
-#define FCP_RSP_CMD_TRAN_ERR 0x0003
-#define FCP_RSP_CMD_RESET 0x0004
-#define FCP_RSP_CMD_ABORTED 0x0005
-#define FCP_RSP_CMD_TIMEOUT 0x0006
-#define FCP_RSP_CMD_OVERRUN 0x0007
-
-/* isp_state_flags field */
-#define FCP_RSP_ST_GOT_BUS 0x0100
-#define FCP_RSP_ST_GOT_TARGET 0x0200
-#define FCP_RSP_ST_SENT_CMD 0x0400
-#define FCP_RSP_ST_XFRD_DATA 0x0800
-#define FCP_RSP_ST_GOT_STATUS 0x1000
-#define FCP_RSP_ST_GOT_SENSE 0x2000
-
-/* isp_stat_flags field */
-#define FCP_RSP_STAT_DISC 0x0001
-#define FCP_RSP_STAT_SYNC 0x0002
-#define FCP_RSP_STAT_PERR 0x0004
-#define FCP_RSP_STAT_BUS_RESET 0x0008
-#define FCP_RSP_STAT_DEV_RESET 0x0010
-#define FCP_RSP_STAT_ABORTED 0x0020
-#define FCP_RSP_STAT_TIMEOUT 0x0040
-#define FCP_RSP_STAT_NEGOTIATE 0x0080
-
-typedef struct {
- u8 rsp_info_type;
- u8 xxx;
- u16 isp_status;
- u16 isp_state_flags;
- u16 isp_stat_flags;
-} fcp_scsi_err;
-
-#endif /* !(__FCP_H) */
diff --git a/drivers/fc4/fcp_impl.h b/drivers/fc4/fcp_impl.h
deleted file mode 100644
index 506338a461ba..000000000000
--- a/drivers/fc4/fcp_impl.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/* fcp_impl.h: Generic SCSI on top of FC4 - our interface defines.
- *
- * Copyright (C) 1997-1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1998 Jirka Hanika (geo@ff.cuni.cz)
- */
-
-#ifndef _FCP_SCSI_H
-#define _FCP_SCSI_H
-
-#include <linux/types.h>
-#include "../scsi/scsi.h"
-
-#include "fc.h"
-#include "fcp.h"
-#include "fc-al.h"
-
-#include <asm/io.h>
-#ifdef __sparc__
-#include <asm/sbus.h>
-#endif
-
-/* 0 or 1 */
-#define FCP_SCSI_USE_NEW_EH_CODE 0
-
-#define FC_CLASS_OUTBOUND 0x01
-#define FC_CLASS_INBOUND 0x02
-#define FC_CLASS_SIMPLE 0x03
-#define FC_CLASS_IO_WRITE 0x04
-#define FC_CLASS_IO_READ 0x05
-#define FC_CLASS_UNSOLICITED 0x06
-#define FC_CLASS_OFFLINE 0x08
-
-#define PROTO_OFFLINE 0x02
-#define PROTO_REPORT_AL_MAP 0x03
-#define PROTO_FORCE_LIP 0x06
-
-struct _fc_channel;
-
-typedef struct fcp_cmnd {
- struct fcp_cmnd *next;
- struct fcp_cmnd *prev;
- void (*done)(struct scsi_cmnd *);
- unsigned short proto;
- unsigned short token;
- unsigned int did;
- /* FCP SCSI stuff */
- dma_addr_t data;
- /* From now on this cannot be touched for proto == TYPE_SCSI_FCP */
- fc_hdr fch;
- dma_addr_t cmd;
- dma_addr_t rsp;
- int cmdlen;
- int rsplen;
- int class;
- int datalen;
- /* This is just used as a verification during login */
- struct _fc_channel *fc;
- void *ls;
-} fcp_cmnd;
-
-typedef struct {
- unsigned int len;
- unsigned char list[0];
-} fcp_posmap;
-
-typedef struct _fc_channel {
- struct _fc_channel *next;
- int irq;
- int state;
- int sid;
- int did;
- char name[16];
- void (*fcp_register)(struct _fc_channel *, u8, int);
- void (*reset)(struct _fc_channel *);
- int (*hw_enque)(struct _fc_channel *, fcp_cmnd *);
- fc_wwn wwn_node;
- fc_wwn wwn_nport;
- fc_wwn wwn_dest;
- common_svc_parm *common_svc;
- svc_parm *class_svcs;
-#ifdef __sparc__
- struct sbus_dev *dev;
-#else
- struct pci_dev *dev;
-#endif
- struct module *module;
- /* FCP SCSI stuff */
- short can_queue;
- short abort_count;
- int rsp_size;
- fcp_cmd *scsi_cmd_pool;
- char *scsi_rsp_pool;
- dma_addr_t dma_scsi_cmd, dma_scsi_rsp;
- unsigned long *scsi_bitmap;
- long scsi_bitmap_end;
- int scsi_free;
- int (*encode_addr)(struct scsi_cmnd *, u16 *, struct _fc_channel *, fcp_cmnd *);
- fcp_cmnd *scsi_que;
- char scsi_name[4];
- fcp_cmnd **cmd_slots;
- int channels;
- int targets;
- long *ages;
- struct scsi_cmnd *rst_pkt;
- fcp_posmap *posmap;
- /* LOGIN stuff */
- fcp_cmnd *login;
- void *ls;
-} fc_channel;
-
-extern fc_channel *fc_channels;
-
-#define FC_STATE_UNINITED 0
-#define FC_STATE_ONLINE 1
-#define FC_STATE_OFFLINE 2
-#define FC_STATE_RESETING 3
-#define FC_STATE_FPORT_OK 4
-#define FC_STATE_MAYBEOFFLINE 5
-
-#define FC_STATUS_OK 0
-#define FC_STATUS_P_RJT 2
-#define FC_STATUS_F_RJT 3
-#define FC_STATUS_P_BSY 4
-#define FC_STATUS_F_BSY 5
-#define FC_STATUS_ERR_OFFLINE 0x11
-#define FC_STATUS_TIMEOUT 0x12
-#define FC_STATUS_ERR_OVERRUN 0x13
-#define FC_STATUS_POINTTOPOINT 0x15
-#define FC_STATUS_AL 0x16
-#define FC_STATUS_UNKNOWN_CQ_TYPE 0x20
-#define FC_STATUS_BAD_SEG_CNT 0x21
-#define FC_STATUS_MAX_XCHG_EXCEEDED 0x22
-#define FC_STATUS_BAD_XID 0x23
-#define FC_STATUS_XCHG_BUSY 0x24
-#define FC_STATUS_BAD_POOL_ID 0x25
-#define FC_STATUS_INSUFFICIENT_CQES 0x26
-#define FC_STATUS_ALLOC_FAIL 0x27
-#define FC_STATUS_BAD_SID 0x28
-#define FC_STATUS_NO_SEQ_INIT 0x29
-#define FC_STATUS_TIMED_OUT -1
-#define FC_STATUS_BAD_RSP -2
-
-void fcp_queue_empty(fc_channel *);
-int fcp_init(fc_channel *);
-void fcp_release(fc_channel *fc_chain, int count);
-void fcp_receive_solicited(fc_channel *, int, int, int, fc_hdr *);
-void fcp_state_change(fc_channel *, int);
-int fc_do_plogi(fc_channel *, unsigned char, fc_wwn *, fc_wwn *);
-int fc_do_prli(fc_channel *, unsigned char);
-
-#define for_each_fc_channel(fc) \
- for (fc = fc_channels; fc; fc = fc->next)
-
-#define for_each_online_fc_channel(fc) \
- for_each_fc_channel(fc) \
- if (fc->state == FC_STATE_ONLINE)
-
-int fcp_scsi_queuecommand(struct scsi_cmnd *,
- void (* done) (struct scsi_cmnd *));
-int fcp_scsi_abort(struct scsi_cmnd *);
-int fcp_scsi_dev_reset(struct scsi_cmnd *);
-int fcp_scsi_host_reset(struct scsi_cmnd *);
-
-#endif /* !(_FCP_SCSI_H) */
diff --git a/drivers/fc4/soc.c b/drivers/fc4/soc.c
deleted file mode 100644
index d517734462e6..000000000000
--- a/drivers/fc4/soc.c
+++ /dev/null
@@ -1,764 +0,0 @@
-/* soc.c: Sparc SUNW,soc (Serial Optical Channel) Fibre Channel Sbus adapter support.
- *
- * Copyright (C) 1996,1997,1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1997,1998 Jirka Hanika (geo@ff.cuni.cz)
- *
- * Sources:
- * Fibre Channel Physical & Signaling Interface (FC-PH), dpANS, 1994
- * dpANS Fibre Channel Protocol for SCSI (X3.269-199X), Rev. 012, 1995
- *
- * Supported hardware:
- * Tested on SOC sbus card bought with SS1000 in Linux running on SS5 and Ultra1.
- * For SOC sbus cards, you have to make sure your FCode is 1.52 or later.
- * If you have older FCode, you should try to upgrade or get SOC microcode from Sun
- * (the microcode is present in Solaris soc driver as well). In that case you need
- * to #define HAVE_SOC_UCODE and format the microcode into soc_asm.c. For the exact
- * format mail me and I will tell you. I cannot offer you the actual microcode though,
- * unless Sun confirms they don't mind.
- */
-
-static char *version =
- "soc.c:v1.3 9/Feb/99 Jakub Jelinek (jj@ultra.linux.cz), Jirka Hanika (geo@ff.cuni.cz)\n";
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/bitops.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <linux/errno.h>
-#include <asm/byteorder.h>
-
-#include <asm/openprom.h>
-#include <asm/oplib.h>
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-
-/* #define SOCDEBUG */
-/* #define HAVE_SOC_UCODE */
-
-#include "fcp_impl.h"
-#include "soc.h"
-#ifdef HAVE_SOC_UCODE
-#include "soc_asm.h"
-#endif
-
-#define soc_printk printk ("soc%d: ", s->soc_no); printk
-
-#ifdef SOCDEBUG
-#define SOD(x) soc_printk x;
-#else
-#define SOD(x)
-#endif
-
-#define for_each_soc(s) for (s = socs; s; s = s->next)
-struct soc *socs = NULL;
-
-static inline void soc_disable(struct soc *s)
-{
- sbus_writel(0, s->regs + IMASK);
- sbus_writel(SOC_CMD_SOFT_RESET, s->regs + CMD);
-}
-
-static inline void soc_enable(struct soc *s)
-{
- SOD(("enable %08x\n", s->cfg))
- sbus_writel(0, s->regs + SAE);
- sbus_writel(s->cfg, s->regs + CFG);
- sbus_writel(SOC_CMD_RSP_QALL, s->regs + CMD);
- SOC_SETIMASK(s, SOC_IMASK_RSP_QALL | SOC_IMASK_SAE);
- SOD(("imask %08lx %08lx\n", s->imask, sbus_readl(s->regs + IMAK)));
-}
-
-static void soc_reset(fc_channel *fc)
-{
- soc_port *port = (soc_port *)fc;
- struct soc *s = port->s;
-
- /* FIXME */
- soc_disable(s);
- s->req[0].seqno = 1;
- s->req[1].seqno = 1;
- s->rsp[0].seqno = 1;
- s->rsp[1].seqno = 1;
- s->req[0].in = 0;
- s->req[1].in = 0;
- s->rsp[0].in = 0;
- s->rsp[1].in = 0;
- s->req[0].out = 0;
- s->req[1].out = 0;
- s->rsp[0].out = 0;
- s->rsp[1].out = 0;
-
- /* FIXME */
- soc_enable(s);
-}
-
-static inline void soc_solicited (struct soc *s)
-{
- fc_hdr fchdr;
- soc_rsp __iomem *hwrsp;
- soc_cq_rsp *sw_cq;
- int token;
- int status;
- fc_channel *fc;
-
- sw_cq = &s->rsp[SOC_SOLICITED_RSP_Q];
-
- if (sw_cq->pool == NULL)
- sw_cq->pool = (soc_req __iomem *)
- (s->xram + xram_get_32low ((xram_p)&sw_cq->hw_cq->address));
- sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in);
- SOD (("soc_solicited, %d pkts arrived\n", (sw_cq->in-sw_cq->out) & sw_cq->last))
- for (;;) {
- hwrsp = (soc_rsp __iomem *)sw_cq->pool + sw_cq->out;
- token = xram_get_32low ((xram_p)&hwrsp->shdr.token);
- status = xram_get_32low ((xram_p)&hwrsp->status);
- fc = (fc_channel *)(&s->port[(token >> 11) & 1]);
-
- if (status == SOC_OK) {
- fcp_receive_solicited(fc, token >> 12,
- token & ((1 << 11) - 1),
- FC_STATUS_OK, NULL);
- } else {
- xram_copy_from(&fchdr, (xram_p)&hwrsp->fchdr, sizeof(fchdr));
- /* We have intentionally defined FC_STATUS_* constants
- * to match SOC_* constants, otherwise we'd have to
- * translate status.
- */
- fcp_receive_solicited(fc, token >> 12,
- token & ((1 << 11) - 1),
- status, &fchdr);
- }
-
- if (++sw_cq->out > sw_cq->last) {
- sw_cq->seqno++;
- sw_cq->out = 0;
- }
-
- if (sw_cq->out == sw_cq->in) {
- sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in);
- if (sw_cq->out == sw_cq->in) {
- /* Tell the hardware about it */
- sbus_writel((sw_cq->out << 24) |
- (SOC_CMD_RSP_QALL &
- ~(SOC_CMD_RSP_Q0 << SOC_SOLICITED_RSP_Q)),
- s->regs + CMD);
-
- /* Read it, so that we're sure it has been updated */
- sbus_readl(s->regs + CMD);
- sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in);
- if (sw_cq->out == sw_cq->in)
- break;
- }
- }
- }
-}
-
-static inline void soc_request (struct soc *s, u32 cmd)
-{
- SOC_SETIMASK(s, s->imask & ~(cmd & SOC_CMD_REQ_QALL));
- SOD(("imask %08lx %08lx\n", s->imask, sbus_readl(s->regs + IMASK)));
-
- SOD(("Queues available %08x OUT %X %X\n", cmd,
- xram_get_8((xram_p)&s->req[0].hw_cq->out),
- xram_get_8((xram_p)&s->req[0].hw_cq->out)))
- if (s->port[s->curr_port].fc.state != FC_STATE_OFFLINE) {
- fcp_queue_empty ((fc_channel *)&(s->port[s->curr_port]));
- if (((s->req[1].in + 1) & s->req[1].last) != (s->req[1].out))
- fcp_queue_empty ((fc_channel *)&(s->port[1 - s->curr_port]));
- } else {
- fcp_queue_empty ((fc_channel *)&(s->port[1 - s->curr_port]));
- }
- if (s->port[1 - s->curr_port].fc.state != FC_STATE_OFFLINE)
- s->curr_port ^= 1;
-}
-
-static inline void soc_unsolicited (struct soc *s)
-{
- soc_rsp __iomem *hwrsp, *hwrspc;
- soc_cq_rsp *sw_cq;
- int count;
- int status;
- int flags;
- fc_channel *fc;
-
- sw_cq = &s->rsp[SOC_UNSOLICITED_RSP_Q];
- if (sw_cq->pool == NULL)
- sw_cq->pool = (soc_req __iomem *)
- (s->xram + (xram_get_32low ((xram_p)&sw_cq->hw_cq->address)));
-
- sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in);
- SOD (("soc_unsolicited, %d packets arrived\n", (sw_cq->in - sw_cq->out) & sw_cq->last))
- while (sw_cq->in != sw_cq->out) {
- /* ...real work per entry here... */
- hwrsp = (soc_rsp __iomem *)sw_cq->pool + sw_cq->out;
-
- hwrspc = NULL;
- flags = xram_get_16 ((xram_p)&hwrsp->shdr.flags);
- count = xram_get_8 ((xram_p)&hwrsp->count);
- fc = (fc_channel *)&s->port[flags & SOC_PORT_B];
- SOD(("FC %08lx fcp_state_change %08lx\n",
- (long)fc, (long)fc->fcp_state_change))
-
- if (count != 1) {
- /* Ugh, continuation entries */
- u8 in;
-
- if (count != 2) {
- printk("%s: Too many continuations entries %d\n",
- fc->name, count);
- goto update_out;
- }
-
- in = sw_cq->in;
- if (in < sw_cq->out) in += sw_cq->last + 1;
- if (in < sw_cq->out + 2) {
- /* Ask the hardware if they haven't arrived yet. */
- sbus_writel((sw_cq->out << 24) |
- (SOC_CMD_RSP_QALL &
- ~(SOC_CMD_RSP_Q0 << SOC_UNSOLICITED_RSP_Q)),
- s->regs + CMD);
-
- /* Read it, so that we're sure it has been updated */
- sbus_readl(s->regs + CMD);
- sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in);
- in = sw_cq->in;
- if (in < sw_cq->out)
- in += sw_cq->last + 1;
- if (in < sw_cq->out + 2) /* Nothing came, let us wait */
- return;
- }
- if (sw_cq->out == sw_cq->last)
- hwrspc = (soc_rsp __iomem *)sw_cq->pool;
- else
- hwrspc = hwrsp + 1;
- }
-
- switch (flags & ~SOC_PORT_B) {
- case SOC_STATUS:
- status = xram_get_32low ((xram_p)&hwrsp->status);
- switch (status) {
- case SOC_ONLINE:
- SOD(("State change to ONLINE\n"));
- fcp_state_change(fc, FC_STATE_ONLINE);
- break;
- case SOC_OFFLINE:
- SOD(("State change to OFFLINE\n"));
- fcp_state_change(fc, FC_STATE_OFFLINE);
- break;
- default:
- printk ("%s: Unknown STATUS no %d\n",
- fc->name, status);
- break;
- }
- break;
- case (SOC_UNSOLICITED|SOC_FC_HDR):
- {
- int r_ctl = xram_get_8 ((xram_p)&hwrsp->fchdr);
- unsigned len;
- char buf[64];
-
- if ((r_ctl & 0xf0) == R_CTL_EXTENDED_SVC) {
- len = xram_get_32 ((xram_p)&hwrsp->shdr.bytecnt);
- if (len < 4 || !hwrspc) {
- printk ("%s: Invalid R_CTL %02x "
- "continuation entries\n",
- fc->name, r_ctl);
- } else {
- if (len > 60)
- len = 60;
- xram_copy_from (buf, (xram_p)hwrspc,
- (len + 3) & ~3);
- if (*(u32 *)buf == LS_DISPLAY) {
- int i;
-
- for (i = 4; i < len; i++)
- if (buf[i] == '\n')
- buf[i] = ' ';
- buf[len] = 0;
- printk ("%s message: %s\n",
- fc->name, buf + 4);
- } else {
- printk ("%s: Unknown LS_CMD "
- "%02x\n", fc->name,
- buf[0]);
- }
- }
- } else {
- printk ("%s: Unsolicited R_CTL %02x "
- "not handled\n", fc->name, r_ctl);
- }
- }
- break;
- default:
- printk ("%s: Unexpected flags %08x\n", fc->name, flags);
- break;
- };
-update_out:
- if (++sw_cq->out > sw_cq->last) {
- sw_cq->seqno++;
- sw_cq->out = 0;
- }
-
- if (hwrspc) {
- if (++sw_cq->out > sw_cq->last) {
- sw_cq->seqno++;
- sw_cq->out = 0;
- }
- }
-
- if (sw_cq->out == sw_cq->in) {
- sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in);
- if (sw_cq->out == sw_cq->in) {
- /* Tell the hardware about it */
- sbus_writel((sw_cq->out << 24) |
- (SOC_CMD_RSP_QALL &
- ~(SOC_CMD_RSP_Q0 << SOC_UNSOLICITED_RSP_Q)),
- s->regs + CMD);
-
- /* Read it, so that we're sure it has been updated */
- sbus_readl(s->regs + CMD);
- sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in);
- }
- }
- }
-}
-
-static irqreturn_t soc_intr(int irq, void *dev_id)
-{
- u32 cmd;
- unsigned long flags;
- register struct soc *s = (struct soc *)dev_id;
-
- spin_lock_irqsave(&s->lock, flags);
- cmd = sbus_readl(s->regs + CMD);
- for (; (cmd = SOC_INTR (s, cmd)); cmd = sbus_readl(s->regs + CMD)) {
- if (cmd & SOC_CMD_RSP_Q1) soc_unsolicited (s);
- if (cmd & SOC_CMD_RSP_Q0) soc_solicited (s);
- if (cmd & SOC_CMD_REQ_QALL) soc_request (s, cmd);
- }
- spin_unlock_irqrestore(&s->lock, flags);
-
- return IRQ_HANDLED;
-}
-
-#define TOKEN(proto, port, token) (((proto)<<12)|(token)|(port))
-
-static int soc_hw_enque (fc_channel *fc, fcp_cmnd *fcmd)
-{
- soc_port *port = (soc_port *)fc;
- struct soc *s = port->s;
- int qno;
- soc_cq_req *sw_cq;
- int cq_next_in;
- soc_req *request;
- fc_hdr *fch;
- int i;
-
- if (fcmd->proto == TYPE_SCSI_FCP)
- qno = 1;
- else
- qno = 0;
- SOD(("Putting a FCP packet type %d into hw queue %d\n", fcmd->proto, qno))
- if (s->imask & (SOC_IMASK_REQ_Q0 << qno)) {
- SOD(("EIO %08x\n", s->imask))
- return -EIO;
- }
- sw_cq = s->req + qno;
- cq_next_in = (sw_cq->in + 1) & sw_cq->last;
-
- if (cq_next_in == sw_cq->out &&
- cq_next_in == (sw_cq->out = xram_get_8((xram_p)&sw_cq->hw_cq->out))) {
- SOD(("%d IN %d OUT %d LAST %d\n", qno, sw_cq->in, sw_cq->out, sw_cq->last))
- SOC_SETIMASK(s, s->imask | (SOC_IMASK_REQ_Q0 << qno));
- SOD(("imask %08lx %08lx\n", s->imask, sbus_readl(s->regs + IMASK)));
- /* If queue is full, just say NO */
- return -EBUSY;
- }
-
- request = sw_cq->pool + sw_cq->in;
- fch = &request->fchdr;
-
- switch (fcmd->proto) {
- case TYPE_SCSI_FCP:
- request->shdr.token = TOKEN(TYPE_SCSI_FCP, port->mask, fcmd->token);
- request->data[0].base = fc->dma_scsi_cmd + fcmd->token * sizeof(fcp_cmd);
- request->data[0].count = sizeof(fcp_cmd);
- request->data[1].base = fc->dma_scsi_rsp + fcmd->token * fc->rsp_size;
- request->data[1].count = fc->rsp_size;
- if (fcmd->data) {
- request->shdr.segcnt = 3;
- i = fc->scsi_cmd_pool[fcmd->token].fcp_data_len;
- request->shdr.bytecnt = i;
- request->data[2].base = fcmd->data;
- request->data[2].count = i;
- request->type =
- (fc->scsi_cmd_pool[fcmd->token].fcp_cntl & FCP_CNTL_WRITE) ?
- SOC_CQTYPE_IO_WRITE : SOC_CQTYPE_IO_READ;
- } else {
- request->shdr.segcnt = 2;
- request->shdr.bytecnt = 0;
- request->data[2].base = 0;
- request->data[2].count = 0;
- request->type = SOC_CQTYPE_SIMPLE;
- }
- FILL_FCHDR_RCTL_DID(fch, R_CTL_COMMAND, fc->did);
- FILL_FCHDR_SID(fch, fc->sid);
- FILL_FCHDR_TYPE_FCTL(fch, TYPE_SCSI_FCP,
- F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE);
- FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0);
- FILL_FCHDR_OXRX(fch, 0xffff, 0xffff);
- fch->param = 0;
- request->shdr.flags = port->flags;
- request->shdr.class = 2;
- break;
-
- case PROTO_OFFLINE:
- memset (request, 0, sizeof(*request));
- request->shdr.token = TOKEN(PROTO_OFFLINE, port->mask, fcmd->token);
- request->type = SOC_CQTYPE_OFFLINE;
- FILL_FCHDR_RCTL_DID(fch, R_CTL_COMMAND, fc->did);
- FILL_FCHDR_SID(fch, fc->sid);
- FILL_FCHDR_TYPE_FCTL(fch, TYPE_SCSI_FCP,
- F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE);
- FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0);
- FILL_FCHDR_OXRX(fch, 0xffff, 0xffff);
- request->shdr.flags = port->flags;
- break;
-
- case PROTO_REPORT_AL_MAP:
- /* SOC only supports Point-to-Point topology, no FC-AL, sorry... */
- return -ENOSYS;
-
- default:
- request->shdr.token = TOKEN(fcmd->proto, port->mask, fcmd->token);
- request->shdr.class = 2;
- request->shdr.flags = port->flags;
- memcpy (fch, &fcmd->fch, sizeof(fc_hdr));
- request->data[0].count = fcmd->cmdlen;
- request->data[1].count = fcmd->rsplen;
- request->type = fcmd->class;
- switch (fcmd->class) {
- case FC_CLASS_OUTBOUND:
- request->data[0].base = fcmd->cmd;
- request->data[0].count = fcmd->cmdlen;
- request->type = SOC_CQTYPE_OUTBOUND;
- request->shdr.bytecnt = fcmd->cmdlen;
- request->shdr.segcnt = 1;
- break;
- case FC_CLASS_INBOUND:
- request->data[0].base = fcmd->rsp;
- request->data[0].count = fcmd->rsplen;
- request->type = SOC_CQTYPE_INBOUND;
- request->shdr.bytecnt = 0;
- request->shdr.segcnt = 1;
- break;
- case FC_CLASS_SIMPLE:
- request->data[0].base = fcmd->cmd;
- request->data[1].base = fcmd->rsp;
- request->data[0].count = fcmd->cmdlen;
- request->data[1].count = fcmd->rsplen;
- request->type = SOC_CQTYPE_SIMPLE;
- request->shdr.bytecnt = fcmd->cmdlen;
- request->shdr.segcnt = 2;
- break;
- case FC_CLASS_IO_READ:
- case FC_CLASS_IO_WRITE:
- request->data[0].base = fcmd->cmd;
- request->data[1].base = fcmd->rsp;
- request->data[0].count = fcmd->cmdlen;
- request->data[1].count = fcmd->rsplen;
- request->type =
- (fcmd->class == FC_CLASS_IO_READ) ?
- SOC_CQTYPE_IO_READ : SOC_CQTYPE_IO_WRITE;
- if (fcmd->data) {
- request->data[2].base = fcmd->data;
- request->data[2].count = fcmd->datalen;
- request->shdr.bytecnt = fcmd->datalen;
- request->shdr.segcnt = 3;
- } else {
- request->shdr.bytecnt = 0;
- request->shdr.segcnt = 2;
- }
- break;
- };
- break;
- };
-
- request->count = 1;
- request->flags = 0;
- request->seqno = sw_cq->seqno;
-
- /* And now tell the SOC about it */
-
- if (++sw_cq->in > sw_cq->last) {
- sw_cq->in = 0;
- sw_cq->seqno++;
- }
-
- SOD(("Putting %08x into cmd\n",
- SOC_CMD_RSP_QALL | (sw_cq->in << 24) | (SOC_CMD_REQ_Q0 << qno)))
-
- sbus_writel(SOC_CMD_RSP_QALL | (sw_cq->in << 24) | (SOC_CMD_REQ_Q0 << qno),
- s->regs + CMD);
-
- /* Read so that command is completed. */
- sbus_readl(s->regs + CMD);
-
- return 0;
-}
-
-static inline void soc_download_fw(struct soc *s)
-{
-#ifdef HAVE_SOC_UCODE
- xram_copy_to (s->xram, soc_ucode, sizeof(soc_ucode));
- xram_bzero (s->xram + sizeof(soc_ucode), 32768 - sizeof(soc_ucode));
-#endif
-}
-
-/* Check for what the best SBUS burst we can use happens
- * to be on this machine.
- */
-static inline void soc_init_bursts(struct soc *s, struct sbus_dev *sdev)
-{
- int bsizes, bsizes_more;
-
- bsizes = (prom_getintdefault(sdev->prom_node,"burst-sizes",0xff) & 0xff);
- bsizes_more = (prom_getintdefault(sdev->bus->prom_node, "burst-sizes", 0xff) & 0xff);
- bsizes &= bsizes_more;
- if ((bsizes & 0x7f) == 0x7f)
- s->cfg = SOC_CFG_BURST_64;
- else if ((bsizes & 0x3f) == 0x3f)
- s->cfg = SOC_CFG_BURST_32;
- else if ((bsizes & 0x1f) == 0x1f)
- s->cfg = SOC_CFG_BURST_16;
- else
- s->cfg = SOC_CFG_BURST_4;
-}
-
-static inline void soc_init(struct sbus_dev *sdev, int no)
-{
- unsigned char tmp[60];
- int propl;
- struct soc *s;
- static int version_printed = 0;
- soc_hw_cq cq[8];
- int size, i;
- int irq;
-
- s = kzalloc (sizeof (struct soc), GFP_KERNEL);
- if (s == NULL)
- return;
- spin_lock_init(&s->lock);
- s->soc_no = no;
-
- SOD(("socs %08lx soc_intr %08lx soc_hw_enque %08x\n",
- (long)socs, (long)soc_intr, (long)soc_hw_enque))
- if (version_printed++ == 0)
- printk (version);
-
- s->port[0].fc.module = THIS_MODULE;
- s->port[1].fc.module = THIS_MODULE;
-
- s->next = socs;
- socs = s;
- s->port[0].fc.dev = sdev;
- s->port[1].fc.dev = sdev;
- s->port[0].s = s;
- s->port[1].s = s;
-
- s->port[0].fc.next = &s->port[1].fc;
-
- /* World Wide Name of SOC */
- propl = prom_getproperty (sdev->prom_node, "soc-wwn", tmp, sizeof(tmp));
- if (propl != sizeof (fc_wwn)) {
- s->wwn.naaid = NAAID_IEEE;
- s->wwn.lo = 0x12345678;
- } else
- memcpy (&s->wwn, tmp, sizeof (fc_wwn));
-
- propl = prom_getproperty (sdev->prom_node, "port-wwns", tmp, sizeof(tmp));
- if (propl != 2 * sizeof (fc_wwn)) {
- s->port[0].fc.wwn_nport.naaid = NAAID_IEEE_EXT;
- s->port[0].fc.wwn_nport.hi = s->wwn.hi;
- s->port[0].fc.wwn_nport.lo = s->wwn.lo;
- s->port[1].fc.wwn_nport.naaid = NAAID_IEEE_EXT;
- s->port[1].fc.wwn_nport.nportid = 1;
- s->port[1].fc.wwn_nport.hi = s->wwn.hi;
- s->port[1].fc.wwn_nport.lo = s->wwn.lo;
- } else {
- memcpy (&s->port[0].fc.wwn_nport, tmp, sizeof (fc_wwn));
- memcpy (&s->port[1].fc.wwn_nport, tmp + sizeof (fc_wwn), sizeof (fc_wwn));
- }
- memcpy (&s->port[0].fc.wwn_node, &s->wwn, sizeof (fc_wwn));
- memcpy (&s->port[1].fc.wwn_node, &s->wwn, sizeof (fc_wwn));
- SOD(("Got wwns %08x%08x ports %08x%08x and %08x%08x\n",
- *(u32 *)&s->port[0].fc.wwn_nport, s->port[0].fc.wwn_nport.lo,
- *(u32 *)&s->port[0].fc.wwn_nport, s->port[0].fc.wwn_nport.lo,
- *(u32 *)&s->port[1].fc.wwn_nport, s->port[1].fc.wwn_nport.lo))
-
- s->port[0].fc.sid = 1;
- s->port[1].fc.sid = 17;
- s->port[0].fc.did = 2;
- s->port[1].fc.did = 18;
-
- s->port[0].fc.reset = soc_reset;
- s->port[1].fc.reset = soc_reset;
-
- if (sdev->num_registers == 1) {
- /* Probably SunFire onboard SOC */
- s->xram = sbus_ioremap(&sdev->resource[0], 0,
- 0x10000UL, "soc xram");
- s->regs = sbus_ioremap(&sdev->resource[0], 0x10000UL,
- 0x10UL, "soc regs");
- } else {
- /* Probably SOC sbus card */
- s->xram = sbus_ioremap(&sdev->resource[1], 0,
- sdev->reg_addrs[1].reg_size, "soc xram");
- s->regs = sbus_ioremap(&sdev->resource[2], 0,
- sdev->reg_addrs[2].reg_size, "soc regs");
- }
-
- soc_init_bursts(s, sdev);
-
- SOD(("Disabling SOC\n"))
-
- soc_disable (s);
-
- irq = sdev->irqs[0];
-
- if (request_irq (irq, soc_intr, IRQF_SHARED, "SOC", (void *)s)) {
- soc_printk ("Cannot order irq %d to go\n", irq);
- socs = s->next;
- return;
- }
-
- SOD(("SOC uses IRQ %d\n", irq))
-
- s->port[0].fc.irq = irq;
- s->port[1].fc.irq = irq;
-
- sprintf (s->port[0].fc.name, "soc%d port A", no);
- sprintf (s->port[1].fc.name, "soc%d port B", no);
- s->port[0].flags = SOC_FC_HDR | SOC_PORT_A;
- s->port[1].flags = SOC_FC_HDR | SOC_PORT_B;
- s->port[1].mask = (1 << 11);
-
- s->port[0].fc.hw_enque = soc_hw_enque;
- s->port[1].fc.hw_enque = soc_hw_enque;
-
- soc_download_fw (s);
-
- SOD(("Downloaded firmware\n"))
-
- /* Now setup xram circular queues */
- memset (cq, 0, sizeof(cq));
-
- size = (SOC_CQ_REQ0_SIZE + SOC_CQ_REQ1_SIZE) * sizeof(soc_req);
- s->req_cpu = sbus_alloc_consistent(sdev, size, &s->req_dvma);
- s->req[0].pool = s->req_cpu;
- cq[0].address = s->req_dvma;
- s->req[1].pool = s->req[0].pool + SOC_CQ_REQ0_SIZE;
-
- s->req[0].hw_cq = (soc_hw_cq __iomem *)(s->xram + SOC_CQ_REQ_OFFSET);
- s->req[1].hw_cq = (soc_hw_cq __iomem *)(s->xram + SOC_CQ_REQ_OFFSET + sizeof(soc_hw_cq));
- s->rsp[0].hw_cq = (soc_hw_cq __iomem *)(s->xram + SOC_CQ_RSP_OFFSET);
- s->rsp[1].hw_cq = (soc_hw_cq __iomem *)(s->xram + SOC_CQ_RSP_OFFSET + sizeof(soc_hw_cq));
-
- cq[1].address = cq[0].address + (SOC_CQ_REQ0_SIZE * sizeof(soc_req));
- cq[4].address = 1;
- cq[5].address = 1;
- cq[0].last = SOC_CQ_REQ0_SIZE - 1;
- cq[1].last = SOC_CQ_REQ1_SIZE - 1;
- cq[4].last = SOC_CQ_RSP0_SIZE - 1;
- cq[5].last = SOC_CQ_RSP1_SIZE - 1;
- for (i = 0; i < 8; i++)
- cq[i].seqno = 1;
-
- s->req[0].last = SOC_CQ_REQ0_SIZE - 1;
- s->req[1].last = SOC_CQ_REQ1_SIZE - 1;
- s->rsp[0].last = SOC_CQ_RSP0_SIZE - 1;
- s->rsp[1].last = SOC_CQ_RSP1_SIZE - 1;
-
- s->req[0].seqno = 1;
- s->req[1].seqno = 1;
- s->rsp[0].seqno = 1;
- s->rsp[1].seqno = 1;
-
- xram_copy_to (s->xram + SOC_CQ_REQ_OFFSET, cq, sizeof(cq));
-
- /* Make our sw copy of SOC service parameters */
- xram_copy_from (s->serv_params, s->xram + 0x140, sizeof (s->serv_params));
-
- s->port[0].fc.common_svc = (common_svc_parm *)s->serv_params;
- s->port[0].fc.class_svcs = (svc_parm *)(s->serv_params + 0x20);
- s->port[1].fc.common_svc = (common_svc_parm *)&s->serv_params;
- s->port[1].fc.class_svcs = (svc_parm *)(s->serv_params + 0x20);
-
- soc_enable (s);
-
- SOD(("Enabled SOC\n"))
-}
-
-static int __init soc_probe(void)
-{
- struct sbus_bus *sbus;
- struct sbus_dev *sdev = NULL;
- struct soc *s;
- int cards = 0;
-
- for_each_sbus(sbus) {
- for_each_sbusdev(sdev, sbus) {
- if(!strcmp(sdev->prom_name, "SUNW,soc")) {
- soc_init(sdev, cards);
- cards++;
- }
- }
- }
- if (!cards) return -EIO;
-
- for_each_soc(s)
- if (s->next)
- s->port[1].fc.next = &s->next->port[0].fc;
- fcp_init (&socs->port[0].fc);
- return 0;
-}
-
-static void __exit soc_cleanup(void)
-{
- struct soc *s;
- int irq;
- struct sbus_dev *sdev;
-
- for_each_soc(s) {
- irq = s->port[0].fc.irq;
- free_irq (irq, s);
-
- fcp_release(&(s->port[0].fc), 2);
-
- sdev = s->port[0].fc.dev;
- if (sdev->num_registers == 1) {
- sbus_iounmap(s->xram, 0x10000UL);
- sbus_iounmap(s->regs, 0x10UL);
- } else {
- sbus_iounmap(s->xram, sdev->reg_addrs[1].reg_size);
- sbus_iounmap(s->regs, sdev->reg_addrs[2].reg_size);
- }
- sbus_free_consistent(sdev,
- (SOC_CQ_REQ0_SIZE+SOC_CQ_REQ1_SIZE)*sizeof(soc_req),
- s->req_cpu, s->req_dvma);
- }
-}
-
-module_init(soc_probe);
-module_exit(soc_cleanup);
-MODULE_LICENSE("GPL");
diff --git a/drivers/fc4/soc.h b/drivers/fc4/soc.h
deleted file mode 100644
index d38cf5b28eed..000000000000
--- a/drivers/fc4/soc.h
+++ /dev/null
@@ -1,301 +0,0 @@
-/* soc.h: Definitions for Sparc SUNW,soc Fibre Channel Sbus driver.
- *
- * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- */
-
-#ifndef __SOC_H
-#define __SOC_H
-
-#include "fc.h"
-#include "fcp.h"
-#include "fcp_impl.h"
-
-/* Hardware register offsets and constants first {{{ */
-#define CFG 0x00UL /* Config Register */
-#define SAE 0x04UL /* Slave Access Error Register */
-#define CMD 0x08UL /* Command and Status Register */
-#define IMASK 0x0cUL /* Interrupt Mask Register */
-
-/* Config Register */
-#define SOC_CFG_EXT_RAM_BANK_MASK 0x07000000
-#define SOC_CFG_EEPROM_BANK_MASK 0x00030000
-#define SOC_CFG_BURST64_MASK 0x00000700
-#define SOC_CFG_SBUS_PARITY_TEST 0x00000020
-#define SOC_CFG_SBUS_PARITY_CHECK 0x00000010
-#define SOC_CFG_SBUS_ENHANCED 0x00000008
-#define SOC_CFG_BURST_MASK 0x00000007
-/* Bursts */
-#define SOC_CFG_BURST_4 0x00000000
-#define SOC_CFG_BURST_16 0x00000004
-#define SOC_CFG_BURST_32 0x00000005
-#define SOC_CFG_BURST_64 0x00000006
-
-/* Slave Access Error Register */
-#define SOC_SAE_ALIGNMENT 0x00000004
-#define SOC_SAE_UNSUPPORTED 0x00000002
-#define SOC_SAE_PARITY 0x00000001
-
-/* Command & Status Register */
-#define SOC_CMD_RSP_QALL 0x000f0000
-#define SOC_CMD_RSP_Q0 0x00010000
-#define SOC_CMD_RSP_Q1 0x00020000
-#define SOC_CMD_RSP_Q2 0x00040000
-#define SOC_CMD_RSP_Q3 0x00080000
-#define SOC_CMD_REQ_QALL 0x00000f00
-#define SOC_CMD_REQ_Q0 0x00000100
-#define SOC_CMD_REQ_Q1 0x00000200
-#define SOC_CMD_REQ_Q2 0x00000400
-#define SOC_CMD_REQ_Q3 0x00000800
-#define SOC_CMD_SAE 0x00000080
-#define SOC_CMD_INTR_PENDING 0x00000008
-#define SOC_CMD_NON_QUEUED 0x00000004
-#define SOC_CMD_IDLE 0x00000002
-#define SOC_CMD_SOFT_RESET 0x00000001
-
-/* Interrupt Mask Register */
-#define SOC_IMASK_RSP_QALL 0x000f0000
-#define SOC_IMASK_RSP_Q0 0x00010000
-#define SOC_IMASK_RSP_Q1 0x00020000
-#define SOC_IMASK_RSP_Q2 0x00040000
-#define SOC_IMASK_RSP_Q3 0x00080000
-#define SOC_IMASK_REQ_QALL 0x00000f00
-#define SOC_IMASK_REQ_Q0 0x00000100
-#define SOC_IMASK_REQ_Q1 0x00000200
-#define SOC_IMASK_REQ_Q2 0x00000400
-#define SOC_IMASK_REQ_Q3 0x00000800
-#define SOC_IMASK_SAE 0x00000080
-#define SOC_IMASK_NON_QUEUED 0x00000004
-
-#define SOC_INTR(s, cmd) \
- (((cmd & SOC_CMD_RSP_QALL) | ((~cmd) & SOC_CMD_REQ_QALL)) \
- & s->imask)
-
-#define SOC_SETIMASK(s, i) \
-do { (s)->imask = (i); \
- sbus_writel((i), (s)->regs + IMASK); \
-} while(0)
-
-/* XRAM
- *
- * This is a 64KB register area. It accepts only halfword access.
- * That's why here are the following inline functions...
- */
-
-typedef void __iomem *xram_p;
-
-/* Get 32bit number from XRAM */
-static inline u32 xram_get_32(xram_p x)
-{
- return ((sbus_readw(x + 0x00UL) << 16) |
- (sbus_readw(x + 0x02UL)));
-}
-
-/* Like the above, but when we don't care about the high 16 bits */
-static inline u32 xram_get_32low(xram_p x)
-{
- return (u32) sbus_readw(x + 0x02UL);
-}
-
-static inline u16 xram_get_16(xram_p x)
-{
- return sbus_readw(x);
-}
-
-static inline u8 xram_get_8(xram_p x)
-{
- if ((unsigned long)x & 0x1UL) {
- x = x - 1;
- return (u8) sbus_readw(x);
- } else {
- return (u8) (sbus_readw(x) >> 8);
- }
-}
-
-static inline void xram_copy_from(void *p, xram_p x, int len)
-{
- for (len >>= 2; len > 0; len--, x += sizeof(u32)) {
- u32 val, *p32 = p;
-
- val = ((sbus_readw(x + 0x00UL) << 16) |
- (sbus_readw(x + 0x02UL)));
- *p32++ = val;
- p = p32;
- }
-}
-
-static inline void xram_copy_to(xram_p x, void *p, int len)
-{
- for (len >>= 2; len > 0; len--, x += sizeof(u32)) {
- u32 tmp, *p32 = p;
-
- tmp = *p32++;
- p = p32;
- sbus_writew(tmp >> 16, x + 0x00UL);
- sbus_writew(tmp, x + 0x02UL);
- }
-}
-
-static inline void xram_bzero(xram_p x, int len)
-{
- for (len >>= 1; len > 0; len--, x += sizeof(u16))
- sbus_writew(0, x);
-}
-
-/* Circular Queue */
-
-#define SOC_CQ_REQ_OFFSET (0x100 * sizeof(u16))
-#define SOC_CQ_RSP_OFFSET (0x110 * sizeof(u16))
-
-typedef struct {
- u32 address;
- u8 in;
- u8 out;
- u8 last;
- u8 seqno;
-} soc_hw_cq;
-
-#define SOC_PORT_A 0x0000 /* From/To Port A */
-#define SOC_PORT_B 0x0001 /* From/To Port A */
-#define SOC_FC_HDR 0x0002 /* Contains FC Header */
-#define SOC_NORSP 0x0004 /* Don't generate response nor interrupt */
-#define SOC_NOINT 0x0008 /* Generate response but not interrupt */
-#define SOC_XFERRDY 0x0010 /* Generate XFERRDY */
-#define SOC_IGNOREPARAM 0x0020 /* Ignore PARAM field in the FC header */
-#define SOC_COMPLETE 0x0040 /* Command completed */
-#define SOC_UNSOLICITED 0x0080 /* For request this is the packet to establish unsolicited pools, */
- /* for rsp this is unsolicited packet */
-#define SOC_STATUS 0x0100 /* State change (on/off line) */
-
-typedef struct {
- u32 token;
- u16 flags;
- u8 class;
- u8 segcnt;
- u32 bytecnt;
-} soc_hdr;
-
-typedef struct {
- u32 base;
- u32 count;
-} soc_data;
-
-#define SOC_CQTYPE_OUTBOUND 0x01
-#define SOC_CQTYPE_INBOUND 0x02
-#define SOC_CQTYPE_SIMPLE 0x03
-#define SOC_CQTYPE_IO_WRITE 0x04
-#define SOC_CQTYPE_IO_READ 0x05
-#define SOC_CQTYPE_UNSOLICITED 0x06
-#define SOC_CQTYPE_DIAG 0x07
-#define SOC_CQTYPE_OFFLINE 0x08
-#define SOC_CQTYPE_RESPONSE 0x10
-#define SOC_CQTYPE_INLINE 0x20
-
-#define SOC_CQFLAGS_CONT 0x01
-#define SOC_CQFLAGS_FULL 0x02
-#define SOC_CQFLAGS_BADHDR 0x04
-#define SOC_CQFLAGS_BADPKT 0x08
-
-typedef struct {
- soc_hdr shdr;
- soc_data data[3];
- fc_hdr fchdr;
- u8 count;
- u8 type;
- u8 flags;
- u8 seqno;
-} soc_req;
-
-#define SOC_OK 0
-#define SOC_P_RJT 2
-#define SOC_F_RJT 3
-#define SOC_P_BSY 4
-#define SOC_F_BSY 5
-#define SOC_ONLINE 0x10
-#define SOC_OFFLINE 0x11
-#define SOC_TIMEOUT 0x12
-#define SOC_OVERRUN 0x13
-#define SOC_UNKOWN_CQ_TYPE 0x20
-#define SOC_BAD_SEG_CNT 0x21
-#define SOC_MAX_XCHG_EXCEEDED 0x22
-#define SOC_BAD_XID 0x23
-#define SOC_XCHG_BUSY 0x24
-#define SOC_BAD_POOL_ID 0x25
-#define SOC_INSUFFICIENT_CQES 0x26
-#define SOC_ALLOC_FAIL 0x27
-#define SOC_BAD_SID 0x28
-#define SOC_NO_SEG_INIT 0x29
-
-typedef struct {
- soc_hdr shdr;
- u32 status;
- soc_data data;
- u8 xxx1[12];
- fc_hdr fchdr;
- u8 count;
- u8 type;
- u8 flags;
- u8 seqno;
-} soc_rsp;
-
-/* }}} */
-
-/* Now our software structures and constants we use to drive the beast {{{ */
-
-#define SOC_CQ_REQ0_SIZE 4
-#define SOC_CQ_REQ1_SIZE 64
-#define SOC_CQ_RSP0_SIZE 8
-#define SOC_CQ_RSP1_SIZE 4
-
-#define SOC_SOLICITED_RSP_Q 0
-#define SOC_UNSOLICITED_RSP_Q 1
-
-struct soc;
-
-typedef struct {
- /* This must come first */
- fc_channel fc;
- struct soc *s;
- u16 flags;
- u16 mask;
-} soc_port;
-
-typedef struct {
- soc_hw_cq __iomem *hw_cq; /* Related XRAM cq */
- soc_req __iomem *pool;
- u8 in;
- u8 out;
- u8 last;
- u8 seqno;
-} soc_cq_rsp;
-
-typedef struct {
- soc_hw_cq __iomem *hw_cq; /* Related XRAM cq */
- soc_req *pool;
- u8 in;
- u8 out;
- u8 last;
- u8 seqno;
-} soc_cq_req;
-
-struct soc {
- spinlock_t lock;
- soc_port port[2]; /* Every SOC has one or two FC ports */
- soc_cq_req req[2]; /* Request CQs */
- soc_cq_rsp rsp[2]; /* Response CQs */
- int soc_no;
- void __iomem *regs;
- xram_p xram;
- fc_wwn wwn;
- u32 imask; /* Our copy of regs->imask */
- u32 cfg; /* Our copy of regs->cfg */
- char serv_params[80];
- struct soc *next;
- int curr_port; /* Which port will have priority to fcp_queue_empty */
-
- soc_req *req_cpu;
- u32 req_dvma;
-};
-
-/* }}} */
-
-#endif /* !(__SOC_H) */
diff --git a/drivers/fc4/socal.c b/drivers/fc4/socal.c
deleted file mode 100644
index c903ebfab526..000000000000
--- a/drivers/fc4/socal.c
+++ /dev/null
@@ -1,904 +0,0 @@
-/* socal.c: Sparc SUNW,socal (SOC+) Fibre Channel Sbus adapter support.
- *
- * Copyright (C) 1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
- *
- * Sources:
- * Fibre Channel Physical & Signaling Interface (FC-PH), dpANS, 1994
- * dpANS Fibre Channel Protocol for SCSI (X3.269-199X), Rev. 012, 1995
- * SOC+ Programming Guide 0.1
- * Fibre Channel Arbitrated Loop (FC-AL), dpANS rev. 4.5, 1995
- *
- * Supported hardware:
- * On-board SOC+ adapters of Ultra Enterprise servers and sun4d.
- */
-
-static char *version =
- "socal.c: SOC+ driver v1.1 9/Feb/99 Jakub Jelinek (jj@ultra.linux.cz)\n";
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/bitops.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <linux/errno.h>
-#include <asm/byteorder.h>
-
-#include <asm/openprom.h>
-#include <asm/oplib.h>
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-
-/* #define SOCALDEBUG */
-/* #define HAVE_SOCAL_UCODE */
-/* #define USE_64BIT_MODE */
-
-#include "fcp_impl.h"
-#include "socal.h"
-#ifdef HAVE_SOCAL_UCODE
-#include "socal_asm.h"
-#endif
-
-#define socal_printk printk ("socal%d: ", s->socal_no); printk
-
-#ifdef SOCALDEBUG
-#define SOD(x) socal_printk x;
-#else
-#define SOD(x)
-#endif
-
-#define for_each_socal(s) for (s = socals; s; s = s->next)
-struct socal *socals = NULL;
-
-static void socal_copy_from_xram(void *d, void __iomem *xram, long size)
-{
- u32 *dp = (u32 *) d;
- while (size) {
- *dp++ = sbus_readl(xram);
- xram += sizeof(u32);
- size -= sizeof(u32);
- }
-}
-
-static void socal_copy_to_xram(void __iomem *xram, void *s, long size)
-{
- u32 *sp = (u32 *) s;
- while (size) {
- u32 val = *sp++;
- sbus_writel(val, xram);
- xram += sizeof(u32);
- size -= sizeof(u32);
- }
-}
-
-#ifdef HAVE_SOCAL_UCODE
-static void socal_bzero(unsigned long xram, int size)
-{
- while (size) {
- sbus_writel(0, xram);
- xram += sizeof(u32);
- size -= sizeof(u32);
- }
-}
-#endif
-
-static inline void socal_disable(struct socal *s)
-{
- sbus_writel(0, s->regs + IMASK);
- sbus_writel(SOCAL_CMD_SOFT_RESET, s->regs + CMD);
-}
-
-static inline void socal_enable(struct socal *s)
-{
- SOD(("enable %08x\n", s->cfg))
- sbus_writel(0, s->regs + SAE);
- sbus_writel(s->cfg, s->regs + CFG);
- sbus_writel(SOCAL_CMD_RSP_QALL, s->regs + CMD);
- SOCAL_SETIMASK(s, SOCAL_IMASK_RSP_QALL | SOCAL_IMASK_SAE);
- SOD(("imask %08x %08x\n", s->imask, sbus_readl(s->regs + IMASK)));
-}
-
-static void socal_reset(fc_channel *fc)
-{
- socal_port *port = (socal_port *)fc;
- struct socal *s = port->s;
-
- /* FIXME */
- socal_disable(s);
- s->req[0].seqno = 1;
- s->req[1].seqno = 1;
- s->rsp[0].seqno = 1;
- s->rsp[1].seqno = 1;
- s->req[0].in = 0;
- s->req[1].in = 0;
- s->rsp[0].in = 0;
- s->rsp[1].in = 0;
- s->req[0].out = 0;
- s->req[1].out = 0;
- s->rsp[0].out = 0;
- s->rsp[1].out = 0;
-
- /* FIXME */
- socal_enable(s);
-}
-
-static inline void socal_solicited(struct socal *s, unsigned long qno)
-{
- socal_rsp *hwrsp;
- socal_cq *sw_cq;
- int token;
- int status;
- fc_channel *fc;
-
- sw_cq = &s->rsp[qno];
-
- /* Finally an improvement against old SOC :) */
- sw_cq->in = sbus_readb(s->regs + RESP + qno);
- SOD (("socal_solicited, %d packets arrived\n",
- (sw_cq->in - sw_cq->out) & sw_cq->last))
- for (;;) {
- hwrsp = (socal_rsp *)sw_cq->pool + sw_cq->out;
- SOD(("hwrsp %p out %d\n", hwrsp, sw_cq->out))
-
-#if defined(SOCALDEBUG) && 0
- {
- u32 *u = (u32 *)hwrsp;
- SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n",
- u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7]))
- u += 8;
- SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n",
- u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7]))
- u = (u32 *)s->xram;
- while (u < ((u32 *)s->regs)) {
- if (sbus_readl(&u[0]) == 0x00003000 ||
- sbus_readl(&u[0]) == 0x00003801) {
- SOD(("Found at %04lx\n",
- (unsigned long)u - (unsigned long)s->xram))
- SOD((" %08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n",
- sbus_readl(&u[0]), sbus_readl(&u[1]),
- sbus_readl(&u[2]), sbus_readl(&u[3]),
- sbus_readl(&u[4]), sbus_readl(&u[5]),
- sbus_readl(&u[6]), sbus_readl(&u[7])))
- u += 8;
- SOD((" %08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n",
- sbus_readl(&u[0]), sbus_readl(&u[1]),
- sbus_readl(&u[2]), sbus_readl(&u[3]),
- sbus_readl(&u[4]), sbus_readl(&u[5]),
- sbus_readl(&u[6]), sbus_readl(&u[7])))
- u -= 8;
- }
- u++;
- }
- }
-#endif
-
- token = hwrsp->shdr.token;
- status = hwrsp->status;
- fc = (fc_channel *)(&s->port[(token >> 11) & 1]);
-
- SOD(("Solicited token %08x status %08x\n", token, status))
- if (status == SOCAL_OK) {
- fcp_receive_solicited(fc, token >> 12,
- token & ((1 << 11) - 1),
- FC_STATUS_OK, NULL);
- } else {
- /* We have intentionally defined FC_STATUS_* constants
- * to match SOCAL_* constants, otherwise we'd have to
- * translate status.
- */
- fcp_receive_solicited(fc, token >> 12,
- token & ((1 << 11) - 1), status, &hwrsp->fchdr);
- }
-
- if (++sw_cq->out > sw_cq->last) {
- sw_cq->seqno++;
- sw_cq->out = 0;
- }
-
- if (sw_cq->out == sw_cq->in) {
- sw_cq->in = sbus_readb(s->regs + RESP + qno);
- if (sw_cq->out == sw_cq->in) {
- /* Tell the hardware about it */
- sbus_writel((sw_cq->out << 24) |
- (SOCAL_CMD_RSP_QALL &
- ~(SOCAL_CMD_RSP_Q0 << qno)),
- s->regs + CMD);
-
- /* Read it, so that we're sure it has been updated */
- sbus_readl(s->regs + CMD);
- sw_cq->in = sbus_readb(s->regs + RESP + qno);
- if (sw_cq->out == sw_cq->in)
- break;
- }
- }
- }
-}
-
-static inline void socal_request (struct socal *s, u32 cmd)
-{
- SOCAL_SETIMASK(s, s->imask & ~(cmd & SOCAL_CMD_REQ_QALL));
- SOD(("imask %08x %08x\n", s->imask, sbus_readl(s->regs + IMASK)));
-
- SOD(("Queues available %08x OUT %X\n", cmd, s->regs->reqpr[0]))
- if (s->port[s->curr_port].fc.state != FC_STATE_OFFLINE) {
- fcp_queue_empty ((fc_channel *)&(s->port[s->curr_port]));
- if (((s->req[1].in + 1) & s->req[1].last) != (s->req[1].out))
- fcp_queue_empty ((fc_channel *)&(s->port[1 - s->curr_port]));
- } else {
- fcp_queue_empty ((fc_channel *)&(s->port[1 - s->curr_port]));
- }
- if (s->port[1 - s->curr_port].fc.state != FC_STATE_OFFLINE)
- s->curr_port ^= 1;
-}
-
-static inline void socal_unsolicited (struct socal *s, unsigned long qno)
-{
- socal_rsp *hwrsp, *hwrspc;
- socal_cq *sw_cq;
- int count;
- int status;
- int flags;
- fc_channel *fc;
-
- sw_cq = &s->rsp[qno];
-
- sw_cq->in = sbus_readb(s->regs + RESP + qno);
- SOD (("socal_unsolicited, %d packets arrived, in %d\n",
- (sw_cq->in - sw_cq->out) & sw_cq->last, sw_cq->in))
- while (sw_cq->in != sw_cq->out) {
- /* ...real work per entry here... */
- hwrsp = (socal_rsp *)sw_cq->pool + sw_cq->out;
- SOD(("hwrsp %p out %d\n", hwrsp, sw_cq->out))
-
-#if defined(SOCALDEBUG) && 0
- {
- u32 *u = (u32 *)hwrsp;
- SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n",
- u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7]))
- u += 8;
- SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n",
- u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7]))
- }
-#endif
-
- hwrspc = NULL;
- flags = hwrsp->shdr.flags;
- count = hwrsp->count;
- fc = (fc_channel *)&s->port[flags & SOCAL_PORT_B];
- SOD(("FC %08lx\n", (long)fc))
-
- if (count != 1) {
- /* Ugh, continuation entries */
- u8 in;
-
- if (count != 2) {
- printk("%s: Too many continuations entries %d\n",
- fc->name, count);
- goto update_out;
- }
-
- in = sw_cq->in;
- if (in < sw_cq->out)
- in += sw_cq->last + 1;
- if (in < sw_cq->out + 2) {
- /* Ask the hardware if they haven't arrived yet. */
- sbus_writel((sw_cq->out << 24) |
- (SOCAL_CMD_RSP_QALL &
- ~(SOCAL_CMD_RSP_Q0 << qno)),
- s->regs + CMD);
-
- /* Read it, so that we're sure it has been updated */
- sbus_readl(s->regs + CMD);
- sw_cq->in = sbus_readb(s->regs + RESP + qno);
- in = sw_cq->in;
- if (in < sw_cq->out)
- in += sw_cq->last + 1;
- if (in < sw_cq->out + 2) /* Nothing came, let us wait */
- return;
- }
- if (sw_cq->out == sw_cq->last)
- hwrspc = (socal_rsp *)sw_cq->pool;
- else
- hwrspc = hwrsp + 1;
- }
-
- switch (flags & ~SOCAL_PORT_B) {
- case SOCAL_STATUS:
- status = hwrsp->status;
- switch (status) {
- case SOCAL_ONLINE:
- SOD(("State change to ONLINE\n"));
- fcp_state_change(fc, FC_STATE_ONLINE);
- break;
- case SOCAL_ONLINE_LOOP:
- SOD(("State change to ONLINE_LOOP\n"));
- fcp_state_change(fc, FC_STATE_ONLINE);
- break;
- case SOCAL_OFFLINE:
- SOD(("State change to OFFLINE\n"));
- fcp_state_change(fc, FC_STATE_OFFLINE);
- break;
- default:
- printk ("%s: Unknown STATUS no %d\n",
- fc->name, status);
- break;
- };
-
- break;
- case (SOCAL_UNSOLICITED|SOCAL_FC_HDR):
- {
- int r_ctl = *((u8 *)&hwrsp->fchdr);
- unsigned len;
-
- if ((r_ctl & 0xf0) == R_CTL_EXTENDED_SVC) {
- len = hwrsp->shdr.bytecnt;
- if (len < 4 || !hwrspc) {
- printk ("%s: Invalid R_CTL %02x "
- "continuation entries\n",
- fc->name, r_ctl);
- } else {
- if (len > 60)
- len = 60;
- if (*(u32 *)hwrspc == LS_DISPLAY) {
- int i;
-
- for (i = 4; i < len; i++)
- if (((u8 *)hwrspc)[i] == '\n')
- ((u8 *)hwrspc)[i] = ' ';
- ((u8 *)hwrspc)[len] = 0;
- printk ("%s message: %s\n",
- fc->name, ((u8 *)hwrspc) + 4);
- } else {
- printk ("%s: Unknown LS_CMD "
- "%08x\n", fc->name,
- *(u32 *)hwrspc);
- }
- }
- } else {
- printk ("%s: Unsolicited R_CTL %02x "
- "not handled\n", fc->name, r_ctl);
- }
- }
- break;
- default:
- printk ("%s: Unexpected flags %08x\n", fc->name, flags);
- break;
- };
-update_out:
- if (++sw_cq->out > sw_cq->last) {
- sw_cq->seqno++;
- sw_cq->out = 0;
- }
-
- if (hwrspc) {
- if (++sw_cq->out > sw_cq->last) {
- sw_cq->seqno++;
- sw_cq->out = 0;
- }
- }
-
- if (sw_cq->out == sw_cq->in) {
- sw_cq->in = sbus_readb(s->regs + RESP + qno);
- if (sw_cq->out == sw_cq->in) {
- /* Tell the hardware about it */
- sbus_writel((sw_cq->out << 24) |
- (SOCAL_CMD_RSP_QALL &
- ~(SOCAL_CMD_RSP_Q0 << qno)),
- s->regs + CMD);
-
- /* Read it, so that we're sure it has been updated */
- sbus_readl(s->regs + CMD);
- sw_cq->in = sbus_readb(s->regs + RESP + qno);
- }
- }
- }
-}
-
-static irqreturn_t socal_intr(int irq, void *dev_id)
-{
- u32 cmd;
- unsigned long flags;
- register struct socal *s = (struct socal *)dev_id;
-
- spin_lock_irqsave(&s->lock, flags);
- cmd = sbus_readl(s->regs + CMD);
- for (; (cmd = SOCAL_INTR (s, cmd)); cmd = sbus_readl(s->regs + CMD)) {
-#ifdef SOCALDEBUG
- static int cnt = 0;
- if (cnt++ < 50)
- printk("soc_intr %08x\n", cmd);
-#endif
- if (cmd & SOCAL_CMD_RSP_Q2)
- socal_unsolicited (s, SOCAL_UNSOLICITED_RSP_Q);
- if (cmd & SOCAL_CMD_RSP_Q1)
- socal_unsolicited (s, SOCAL_SOLICITED_BAD_RSP_Q);
- if (cmd & SOCAL_CMD_RSP_Q0)
- socal_solicited (s, SOCAL_SOLICITED_RSP_Q);
- if (cmd & SOCAL_CMD_REQ_QALL)
- socal_request (s, cmd);
- }
- spin_unlock_irqrestore(&s->lock, flags);
-
- return IRQ_HANDLED;
-}
-
-#define TOKEN(proto, port, token) (((proto)<<12)|(token)|(port))
-
-static int socal_hw_enque (fc_channel *fc, fcp_cmnd *fcmd)
-{
- socal_port *port = (socal_port *)fc;
- struct socal *s = port->s;
- unsigned long qno;
- socal_cq *sw_cq;
- int cq_next_in;
- socal_req *request;
- fc_hdr *fch;
- int i;
-
- if (fcmd->proto == TYPE_SCSI_FCP)
- qno = 1;
- else
- qno = 0;
- SOD(("Putting a FCP packet type %d into hw queue %d\n", fcmd->proto, qno))
- if (s->imask & (SOCAL_IMASK_REQ_Q0 << qno)) {
- SOD(("EIO %08x\n", s->imask))
- return -EIO;
- }
- sw_cq = s->req + qno;
- cq_next_in = (sw_cq->in + 1) & sw_cq->last;
-
- if (cq_next_in == sw_cq->out &&
- cq_next_in == (sw_cq->out = sbus_readb(s->regs + REQP + qno))) {
- SOD(("%d IN %d OUT %d LAST %d\n",
- qno, sw_cq->in,
- sw_cq->out, sw_cq->last))
- SOCAL_SETIMASK(s, s->imask | (SOCAL_IMASK_REQ_Q0 << qno));
- SOD(("imask %08x %08x\n", s->imask, sbus_readl(s->regs + IMASK)));
-
- /* If queue is full, just say NO. */
- return -EBUSY;
- }
-
- request = sw_cq->pool + sw_cq->in;
- fch = &request->fchdr;
-
- switch (fcmd->proto) {
- case TYPE_SCSI_FCP:
- request->shdr.token = TOKEN(TYPE_SCSI_FCP, port->mask, fcmd->token);
- request->data[0].base = fc->dma_scsi_cmd + fcmd->token * sizeof(fcp_cmd);
- request->data[0].count = sizeof(fcp_cmd);
- request->data[1].base = fc->dma_scsi_rsp + fcmd->token * fc->rsp_size;
- request->data[1].count = fc->rsp_size;
- if (fcmd->data) {
- request->shdr.segcnt = 3;
- i = fc->scsi_cmd_pool[fcmd->token].fcp_data_len;
- request->shdr.bytecnt = i;
- request->data[2].base = fcmd->data;
- request->data[2].count = i;
- request->type = (fc->scsi_cmd_pool[fcmd->token].fcp_cntl & FCP_CNTL_WRITE) ?
- SOCAL_CQTYPE_IO_WRITE : SOCAL_CQTYPE_IO_READ;
- } else {
- request->shdr.segcnt = 2;
- request->shdr.bytecnt = 0;
- request->data[2].base = 0;
- request->data[2].count = 0;
- request->type = SOCAL_CQTYPE_SIMPLE;
- }
- FILL_FCHDR_RCTL_DID(fch, R_CTL_COMMAND, fcmd->did);
- FILL_FCHDR_SID(fch, fc->sid);
- FILL_FCHDR_TYPE_FCTL(fch, TYPE_SCSI_FCP, F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE);
- FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0);
- FILL_FCHDR_OXRX(fch, 0xffff, 0xffff);
- fch->param = 0;
- request->shdr.flags = port->flags;
- request->shdr.class = fc->posmap ? 3 : 2;
- break;
-
- case PROTO_OFFLINE:
- memset (request, 0, sizeof(*request));
- request->shdr.token = TOKEN(PROTO_OFFLINE, port->mask, fcmd->token);
- request->type = SOCAL_CQTYPE_OFFLINE;
- FILL_FCHDR_RCTL_DID(fch, R_CTL_COMMAND, fcmd->did);
- FILL_FCHDR_SID(fch, fc->sid);
- FILL_FCHDR_TYPE_FCTL(fch, TYPE_SCSI_FCP, F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE);
- FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0);
- FILL_FCHDR_OXRX(fch, 0xffff, 0xffff);
- request->shdr.flags = port->flags;
- break;
-
- case PROTO_REPORT_AL_MAP:
- memset (request, 0, sizeof(*request));
- request->shdr.token = TOKEN(PROTO_REPORT_AL_MAP, port->mask, fcmd->token);
- request->type = SOCAL_CQTYPE_REPORT_MAP;
- request->shdr.flags = port->flags;
- request->shdr.segcnt = 1;
- request->shdr.bytecnt = sizeof(fc_al_posmap);
- request->data[0].base = fcmd->cmd;
- request->data[0].count = sizeof(fc_al_posmap);
- break;
-
- default:
- request->shdr.token = TOKEN(fcmd->proto, port->mask, fcmd->token);
- request->shdr.class = fc->posmap ? 3 : 2;
- request->shdr.flags = port->flags;
- memcpy (fch, &fcmd->fch, sizeof(fc_hdr));
- request->data[0].count = fcmd->cmdlen;
- request->data[1].count = fcmd->rsplen;
- request->type = fcmd->class;
- switch (fcmd->class) {
- case FC_CLASS_OUTBOUND:
- request->data[0].base = fcmd->cmd;
- request->data[0].count = fcmd->cmdlen;
- request->type = SOCAL_CQTYPE_OUTBOUND;
- request->shdr.bytecnt = fcmd->cmdlen;
- request->shdr.segcnt = 1;
- break;
- case FC_CLASS_INBOUND:
- request->data[0].base = fcmd->rsp;
- request->data[0].count = fcmd->rsplen;
- request->type = SOCAL_CQTYPE_INBOUND;
- request->shdr.bytecnt = 0;
- request->shdr.segcnt = 1;
- break;
- case FC_CLASS_SIMPLE:
- request->data[0].base = fcmd->cmd;
- request->data[1].base = fcmd->rsp;
- request->data[0].count = fcmd->cmdlen;
- request->data[1].count = fcmd->rsplen;
- request->type = SOCAL_CQTYPE_SIMPLE;
- request->shdr.bytecnt = fcmd->cmdlen;
- request->shdr.segcnt = 2;
- break;
- case FC_CLASS_IO_READ:
- case FC_CLASS_IO_WRITE:
- request->data[0].base = fcmd->cmd;
- request->data[1].base = fcmd->rsp;
- request->data[0].count = fcmd->cmdlen;
- request->data[1].count = fcmd->rsplen;
- request->type = (fcmd->class == FC_CLASS_IO_READ) ? SOCAL_CQTYPE_IO_READ : SOCAL_CQTYPE_IO_WRITE;
- if (fcmd->data) {
- request->data[2].base = fcmd->data;
- request->data[2].count = fcmd->datalen;
- request->shdr.bytecnt = fcmd->datalen;
- request->shdr.segcnt = 3;
- } else {
- request->shdr.bytecnt = 0;
- request->shdr.segcnt = 2;
- }
- break;
- }
- break;
- }
-
- request->count = 1;
- request->flags = 0;
- request->seqno = sw_cq->seqno;
-
- SOD(("queueing token %08x\n", request->shdr.token))
-
- /* And now tell the SOCAL about it */
-
- if (++sw_cq->in > sw_cq->last) {
- sw_cq->in = 0;
- sw_cq->seqno++;
- }
-
- SOD(("Putting %08x into cmd\n", SOCAL_CMD_RSP_QALL | (sw_cq->in << 24) | (SOCAL_CMD_REQ_Q0 << qno)))
-
- sbus_writel(SOCAL_CMD_RSP_QALL | (sw_cq->in << 24) | (SOCAL_CMD_REQ_Q0 << qno),
- s->regs + CMD);
-
- /* Read so that command is completed */
- sbus_readl(s->regs + CMD);
-
- return 0;
-}
-
-static inline void socal_download_fw(struct socal *s)
-{
-#ifdef HAVE_SOCAL_UCODE
- SOD(("Loading %ld bytes from %p to %p\n", sizeof(socal_ucode), socal_ucode, s->xram))
- socal_copy_to_xram(s->xram, socal_ucode, sizeof(socal_ucode));
- SOD(("Clearing the rest of memory\n"))
- socal_bzero (s->xram + sizeof(socal_ucode), 65536 - sizeof(socal_ucode));
- SOD(("Done\n"))
-#endif
-}
-
-/* Check for what the best SBUS burst we can use happens
- * to be on this machine.
- */
-static inline void socal_init_bursts(struct socal *s, struct sbus_dev *sdev)
-{
- int bsizes, bsizes_more;
- u32 cfg;
-
- bsizes = (prom_getintdefault(sdev->prom_node,"burst-sizes",0xff) & 0xff);
- bsizes_more = (prom_getintdefault(sdev->bus->prom_node, "burst-sizes", 0xff) & 0xff);
- bsizes &= bsizes_more;
-#ifdef USE_64BIT_MODE
-#ifdef __sparc_v9__
- mmu_set_sbus64(sdev, bsizes >> 16);
-#endif
-#endif
- if ((bsizes & 0x7f) == 0x7f)
- cfg = SOCAL_CFG_BURST_64;
- else if ((bsizes & 0x3f) == 0x3f)
- cfg = SOCAL_CFG_BURST_32;
- else if ((bsizes & 0x1f) == 0x1f)
- cfg = SOCAL_CFG_BURST_16;
- else
- cfg = SOCAL_CFG_BURST_4;
-#ifdef USE_64BIT_MODE
-#ifdef __sparc_v9__
- /* What is BURST_128? -jj */
- if ((bsizes & 0x780000) == 0x780000)
- cfg |= (SOCAL_CFG_BURST_64 << 8) | SOCAL_CFG_SBUS_ENHANCED;
- else if ((bsizes & 0x380000) == 0x380000)
- cfg |= (SOCAL_CFG_BURST_32 << 8) | SOCAL_CFG_SBUS_ENHANCED;
- else if ((bsizes & 0x180000) == 0x180000)
- cfg |= (SOCAL_CFG_BURST_16 << 8) | SOCAL_CFG_SBUS_ENHANCED;
- else
- cfg |= (SOCAL_CFG_BURST_8 << 8) | SOCAL_CFG_SBUS_ENHANCED;
-#endif
-#endif
- s->cfg = cfg;
-}
-
-static inline void socal_init(struct sbus_dev *sdev, int no)
-{
- unsigned char tmp[60];
- int propl;
- struct socal *s;
- static unsigned version_printed = 0;
- socal_hw_cq cq[8];
- int size, i;
- int irq, node;
-
- s = kzalloc (sizeof (struct socal), GFP_KERNEL);
- if (!s) return;
- spin_lock_init(&s->lock);
- s->socal_no = no;
-
- SOD(("socals %08lx socal_intr %08lx socal_hw_enque %08lx\n",
- (long)socals, (long)socal_intr, (long)socal_hw_enque))
- if (version_printed++ == 0)
- printk (version);
-
- s->port[0].fc.module = THIS_MODULE;
- s->port[1].fc.module = THIS_MODULE;
-
- s->next = socals;
- socals = s;
- s->port[0].fc.dev = sdev;
- s->port[1].fc.dev = sdev;
- s->port[0].s = s;
- s->port[1].s = s;
-
- s->port[0].fc.next = &s->port[1].fc;
-
- /* World Wide Name of SOCAL */
- propl = prom_getproperty (sdev->prom_node, "wwn", tmp, sizeof(tmp));
- if (propl != sizeof (fc_wwn)) {
- s->wwn.naaid = NAAID_IEEE_REG;
- s->wwn.nportid = 0x123;
- s->wwn.hi = 0x1234;
- s->wwn.lo = 0x12345678;
- } else
- memcpy (&s->wwn, tmp, sizeof (fc_wwn));
-
- memcpy (&s->port[0].fc.wwn_nport, &s->wwn, sizeof (fc_wwn));
- s->port[0].fc.wwn_nport.lo++;
- memcpy (&s->port[1].fc.wwn_nport, &s->wwn, sizeof (fc_wwn));
- s->port[1].fc.wwn_nport.lo+=2;
-
- node = prom_getchild (sdev->prom_node);
- while (node && (node = prom_searchsiblings (node, "sf"))) {
- int port;
-
- port = prom_getintdefault(node, "port#", -1);
- switch (port) {
- case 0:
- case 1:
- if (prom_getproplen(node, "port-wwn") == sizeof (fc_wwn))
- prom_getproperty (node, "port-wwn",
- (char *)&s->port[port].fc.wwn_nport,
- sizeof (fc_wwn));
- break;
- default:
- break;
- };
-
- node = prom_getsibling(node);
- }
-
- memcpy (&s->port[0].fc.wwn_node, &s->wwn, sizeof (fc_wwn));
- memcpy (&s->port[1].fc.wwn_node, &s->wwn, sizeof (fc_wwn));
- SOD(("Got wwns %08x%08x ports %08x%08x and %08x%08x\n",
- *(u32 *)&s->port[0].fc.wwn_node, s->port[0].fc.wwn_node.lo,
- *(u32 *)&s->port[0].fc.wwn_nport, s->port[0].fc.wwn_nport.lo,
- *(u32 *)&s->port[1].fc.wwn_nport, s->port[1].fc.wwn_nport.lo))
-
- s->port[0].fc.sid = 1;
- s->port[1].fc.sid = 17;
- s->port[0].fc.did = 2;
- s->port[1].fc.did = 18;
-
- s->port[0].fc.reset = socal_reset;
- s->port[1].fc.reset = socal_reset;
-
- if (sdev->num_registers == 1) {
- s->eeprom = sbus_ioremap(&sdev->resource[0], 0,
- sdev->reg_addrs[0].reg_size, "socal xram");
- if (sdev->reg_addrs[0].reg_size > 0x20000)
- s->xram = s->eeprom + 0x10000UL;
- else
- s->xram = s->eeprom;
- s->regs = (s->xram + 0x10000UL);
- } else {
- /* E.g. starfire presents 3 registers for SOCAL */
- s->xram = sbus_ioremap(&sdev->resource[1], 0,
- sdev->reg_addrs[1].reg_size, "socal xram");
- s->regs = sbus_ioremap(&sdev->resource[2], 0,
- sdev->reg_addrs[2].reg_size, "socal regs");
- }
-
- socal_init_bursts(s, sdev);
-
- SOD(("Disabling SOCAL\n"))
-
- socal_disable (s);
-
- irq = sdev->irqs[0];
-
- if (request_irq (irq, socal_intr, IRQF_SHARED, "SOCAL", (void *)s)) {
- socal_printk ("Cannot order irq %d to go\n", irq);
- socals = s->next;
- return;
- }
-
- SOD(("SOCAL uses IRQ %d\n", irq))
-
- s->port[0].fc.irq = irq;
- s->port[1].fc.irq = irq;
-
- sprintf (s->port[0].fc.name, "socal%d port A", no);
- sprintf (s->port[1].fc.name, "socal%d port B", no);
- s->port[0].flags = SOCAL_FC_HDR | SOCAL_PORT_A;
- s->port[1].flags = SOCAL_FC_HDR | SOCAL_PORT_B;
- s->port[1].mask = (1 << 11);
-
- s->port[0].fc.hw_enque = socal_hw_enque;
- s->port[1].fc.hw_enque = socal_hw_enque;
-
- socal_download_fw (s);
-
- SOD(("Downloaded firmware\n"))
-
- /* Now setup xram circular queues */
- memset (cq, 0, sizeof(cq));
-
- size = (SOCAL_CQ_REQ0_SIZE + SOCAL_CQ_REQ1_SIZE +
- SOCAL_CQ_RSP0_SIZE + SOCAL_CQ_RSP1_SIZE +
- SOCAL_CQ_RSP2_SIZE) * sizeof(socal_req);
- s->req_cpu = sbus_alloc_consistent(sdev, size, &s->req_dvma);
- s->req[0].pool = s->req_cpu;
- cq[0].address = s->req_dvma;
- s->req[1].pool = s->req[0].pool + SOCAL_CQ_REQ0_SIZE;
- s->rsp[0].pool = s->req[1].pool + SOCAL_CQ_REQ1_SIZE;
- s->rsp[1].pool = s->rsp[0].pool + SOCAL_CQ_RSP0_SIZE;
- s->rsp[2].pool = s->rsp[1].pool + SOCAL_CQ_RSP1_SIZE;
-
- s->req[0].hw_cq = (socal_hw_cq __iomem *)(s->xram + SOCAL_CQ_REQ_OFFSET);
- s->req[1].hw_cq = (socal_hw_cq __iomem *)(s->xram + SOCAL_CQ_REQ_OFFSET + sizeof(socal_hw_cq));
- s->rsp[0].hw_cq = (socal_hw_cq __iomem *)(s->xram + SOCAL_CQ_RSP_OFFSET);
- s->rsp[1].hw_cq = (socal_hw_cq __iomem *)(s->xram + SOCAL_CQ_RSP_OFFSET + sizeof(socal_hw_cq));
- s->rsp[2].hw_cq = (socal_hw_cq __iomem *)(s->xram + SOCAL_CQ_RSP_OFFSET + 2 * sizeof(socal_hw_cq));
-
- cq[1].address = cq[0].address + (SOCAL_CQ_REQ0_SIZE * sizeof(socal_req));
- cq[4].address = cq[1].address + (SOCAL_CQ_REQ1_SIZE * sizeof(socal_req));
- cq[5].address = cq[4].address + (SOCAL_CQ_RSP0_SIZE * sizeof(socal_req));
- cq[6].address = cq[5].address + (SOCAL_CQ_RSP1_SIZE * sizeof(socal_req));
-
- cq[0].last = SOCAL_CQ_REQ0_SIZE - 1;
- cq[1].last = SOCAL_CQ_REQ1_SIZE - 1;
- cq[4].last = SOCAL_CQ_RSP0_SIZE - 1;
- cq[5].last = SOCAL_CQ_RSP1_SIZE - 1;
- cq[6].last = SOCAL_CQ_RSP2_SIZE - 1;
- for (i = 0; i < 8; i++)
- cq[i].seqno = 1;
-
- s->req[0].last = SOCAL_CQ_REQ0_SIZE - 1;
- s->req[1].last = SOCAL_CQ_REQ1_SIZE - 1;
- s->rsp[0].last = SOCAL_CQ_RSP0_SIZE - 1;
- s->rsp[1].last = SOCAL_CQ_RSP1_SIZE - 1;
- s->rsp[2].last = SOCAL_CQ_RSP2_SIZE - 1;
-
- s->req[0].seqno = 1;
- s->req[1].seqno = 1;
- s->rsp[0].seqno = 1;
- s->rsp[1].seqno = 1;
- s->rsp[2].seqno = 1;
-
- socal_copy_to_xram(s->xram + SOCAL_CQ_REQ_OFFSET, cq, sizeof(cq));
-
- SOD(("Setting up params\n"))
-
- /* Make our sw copy of SOCAL service parameters */
- socal_copy_from_xram(s->serv_params, s->xram + 0x280, sizeof (s->serv_params));
-
- s->port[0].fc.common_svc = (common_svc_parm *)s->serv_params;
- s->port[0].fc.class_svcs = (svc_parm *)(s->serv_params + 0x20);
- s->port[1].fc.common_svc = (common_svc_parm *)&s->serv_params;
- s->port[1].fc.class_svcs = (svc_parm *)(s->serv_params + 0x20);
-
- socal_enable (s);
-
- SOD(("Enabled SOCAL\n"))
-}
-
-static int __init socal_probe(void)
-{
- struct sbus_bus *sbus;
- struct sbus_dev *sdev = NULL;
- struct socal *s;
- int cards = 0;
-
- for_each_sbus(sbus) {
- for_each_sbusdev(sdev, sbus) {
- if(!strcmp(sdev->prom_name, "SUNW,socal")) {
- socal_init(sdev, cards);
- cards++;
- }
- }
- }
- if (!cards)
- return -EIO;
-
- for_each_socal(s)
- if (s->next)
- s->port[1].fc.next = &s->next->port[0].fc;
-
- fcp_init (&socals->port[0].fc);
- return 0;
-}
-
-static void __exit socal_cleanup(void)
-{
- struct socal *s;
- int irq;
- struct sbus_dev *sdev;
-
- for_each_socal(s) {
- irq = s->port[0].fc.irq;
- free_irq (irq, s);
-
- fcp_release(&(s->port[0].fc), 2);
-
- sdev = s->port[0].fc.dev;
- if (sdev->num_registers == 1) {
- sbus_iounmap(s->eeprom, sdev->reg_addrs[0].reg_size);
- } else {
- sbus_iounmap(s->xram, sdev->reg_addrs[1].reg_size);
- sbus_iounmap(s->regs, sdev->reg_addrs[2].reg_size);
- }
- sbus_free_consistent(sdev,
- (SOCAL_CQ_REQ0_SIZE + SOCAL_CQ_REQ1_SIZE +
- SOCAL_CQ_RSP0_SIZE + SOCAL_CQ_RSP1_SIZE +
- SOCAL_CQ_RSP2_SIZE) * sizeof(socal_req),
- s->req_cpu, s->req_dvma);
- }
-}
-
-module_init(socal_probe);
-module_exit(socal_cleanup);
-MODULE_LICENSE("GPL");
diff --git a/drivers/fc4/socal.h b/drivers/fc4/socal.h
deleted file mode 100644
index 774edf68e4d2..000000000000
--- a/drivers/fc4/socal.h
+++ /dev/null
@@ -1,314 +0,0 @@
-/* socal.h: Definitions for Sparc SUNW,socal (SOC+) Fibre Channel Sbus driver.
- *
- * Copyright (C) 1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
- */
-
-#ifndef __SOCAL_H
-#define __SOCAL_H
-
-#include "fc.h"
-#include "fcp.h"
-#include "fcp_impl.h"
-
-/* Hardware register offsets and constants first {{{ */
-#define CFG 0x00UL
-#define SAE 0x04UL
-#define CMD 0x08UL
-#define IMASK 0x0cUL
-#define REQP 0x10UL
-#define RESP 0x14UL
-
-/* Config Register */
-#define SOCAL_CFG_EXT_RAM_BANK_MASK 0x07000000
-#define SOCAL_CFG_EEPROM_BANK_MASK 0x00030000
-#define SOCAL_CFG_BURST64_MASK 0x00000700
-#define SOCAL_CFG_SBUS_PARITY_TEST 0x00000020
-#define SOCAL_CFG_SBUS_PARITY_CHECK 0x00000010
-#define SOCAL_CFG_SBUS_ENHANCED 0x00000008
-#define SOCAL_CFG_BURST_MASK 0x00000007
-/* Bursts */
-#define SOCAL_CFG_BURST_4 0x00000000
-#define SOCAL_CFG_BURST_8 0x00000003
-#define SOCAL_CFG_BURST_16 0x00000004
-#define SOCAL_CFG_BURST_32 0x00000005
-#define SOCAL_CFG_BURST_64 0x00000006
-#define SOCAL_CFG_BURST_128 0x00000007
-
-/* Slave Access Error Register */
-#define SOCAL_SAE_ALIGNMENT 0x00000004
-#define SOCAL_SAE_UNSUPPORTED 0x00000002
-#define SOCAL_SAE_PARITY 0x00000001
-
-/* Command & Status Register */
-#define SOCAL_CMD_RSP_QALL 0x000f0000
-#define SOCAL_CMD_RSP_Q0 0x00010000
-#define SOCAL_CMD_RSP_Q1 0x00020000
-#define SOCAL_CMD_RSP_Q2 0x00040000
-#define SOCAL_CMD_RSP_Q3 0x00080000
-#define SOCAL_CMD_REQ_QALL 0x00000f00
-#define SOCAL_CMD_REQ_Q0 0x00000100
-#define SOCAL_CMD_REQ_Q1 0x00000200
-#define SOCAL_CMD_REQ_Q2 0x00000400
-#define SOCAL_CMD_REQ_Q3 0x00000800
-#define SOCAL_CMD_SAE 0x00000080
-#define SOCAL_CMD_INTR_PENDING 0x00000008
-#define SOCAL_CMD_NON_QUEUED 0x00000004
-#define SOCAL_CMD_IDLE 0x00000002
-#define SOCAL_CMD_SOFT_RESET 0x00000001
-
-/* Interrupt Mask Register */
-#define SOCAL_IMASK_RSP_QALL 0x000f0000
-#define SOCAL_IMASK_RSP_Q0 0x00010000
-#define SOCAL_IMASK_RSP_Q1 0x00020000
-#define SOCAL_IMASK_RSP_Q2 0x00040000
-#define SOCAL_IMASK_RSP_Q3 0x00080000
-#define SOCAL_IMASK_REQ_QALL 0x00000f00
-#define SOCAL_IMASK_REQ_Q0 0x00000100
-#define SOCAL_IMASK_REQ_Q1 0x00000200
-#define SOCAL_IMASK_REQ_Q2 0x00000400
-#define SOCAL_IMASK_REQ_Q3 0x00000800
-#define SOCAL_IMASK_SAE 0x00000080
-#define SOCAL_IMASK_NON_QUEUED 0x00000004
-
-#define SOCAL_INTR(s, cmd) \
- (((cmd & SOCAL_CMD_RSP_QALL) | ((~cmd) & SOCAL_CMD_REQ_QALL)) \
- & s->imask)
-
-#define SOCAL_SETIMASK(s, i) \
-do { (s)->imask = (i); \
- sbus_writel((i), (s)->regs + IMASK); \
-} while (0)
-
-#define SOCAL_MAX_EXCHANGES 1024
-
-/* XRAM
- *
- * This is a 64KB register area.
- * From the documentation, it seems like it is finally able to cope
- * at least with 1,2,4 byte accesses for read and 2,4 byte accesses for write.
- */
-
-/* Circular Queue */
-
-#define SOCAL_CQ_REQ_OFFSET 0x200
-#define SOCAL_CQ_RSP_OFFSET 0x220
-
-typedef struct {
- u32 address;
- u8 in;
- u8 out;
- u8 last;
- u8 seqno;
-} socal_hw_cq;
-
-#define SOCAL_PORT_A 0x0000 /* From/To Port A */
-#define SOCAL_PORT_B 0x0001 /* From/To Port A */
-#define SOCAL_FC_HDR 0x0002 /* Contains FC Header */
-#define SOCAL_NORSP 0x0004 /* Don't generate response nor interrupt */
-#define SOCAL_NOINT 0x0008 /* Generate response but not interrupt */
-#define SOCAL_XFERRDY 0x0010 /* Generate XFERRDY */
-#define SOCAL_IGNOREPARAM 0x0020 /* Ignore PARAM field in the FC header */
-#define SOCAL_COMPLETE 0x0040 /* Command completed */
-#define SOCAL_UNSOLICITED 0x0080 /* For request this is the packet to establish unsolicited pools, */
- /* for rsp this is unsolicited packet */
-#define SOCAL_STATUS 0x0100 /* State change (on/off line) */
-#define SOCAL_RSP_HDR 0x0200 /* Return frame header in any case */
-
-typedef struct {
- u32 token;
- u16 flags;
- u8 class;
- u8 segcnt;
- u32 bytecnt;
-} socal_hdr;
-
-typedef struct {
- u32 base;
- u32 count;
-} socal_data;
-
-#define SOCAL_CQTYPE_NOP 0x00
-#define SOCAL_CQTYPE_OUTBOUND 0x01
-#define SOCAL_CQTYPE_INBOUND 0x02
-#define SOCAL_CQTYPE_SIMPLE 0x03
-#define SOCAL_CQTYPE_IO_WRITE 0x04
-#define SOCAL_CQTYPE_IO_READ 0x05
-#define SOCAL_CQTYPE_UNSOLICITED 0x06
-#define SOCAL_CQTYPE_BYPASS_DEV 0x06
-#define SOCAL_CQTYPE_DIAG 0x07
-#define SOCAL_CQTYPE_OFFLINE 0x08
-#define SOCAL_CQTYPE_ADD_POOL 0x09
-#define SOCAL_CQTYPE_DELETE_POOL 0x0a
-#define SOCAL_CQTYPE_ADD_BUFFER 0x0b
-#define SOCAL_CQTYPE_ADD_POOL_BUFFER 0x0c
-#define SOCAL_CQTYPE_REQUEST_ABORT 0x0d
-#define SOCAL_CQTYPE_REQUEST_LIP 0x0e
-#define SOCAL_CQTYPE_REPORT_MAP 0x0f
-#define SOCAL_CQTYPE_RESPONSE 0x10
-#define SOCAL_CQTYPE_INLINE 0x20
-
-#define SOCAL_CQFLAGS_CONT 0x01
-#define SOCAL_CQFLAGS_FULL 0x02
-#define SOCAL_CQFLAGS_BADHDR 0x04
-#define SOCAL_CQFLAGS_BADPKT 0x08
-
-typedef struct {
- socal_hdr shdr;
- socal_data data[3];
- fc_hdr fchdr;
- u8 count;
- u8 type;
- u8 flags;
- u8 seqno;
-} socal_req;
-
-#define SOCAL_OK 0
-#define SOCAL_P_RJT 2
-#define SOCAL_F_RJT 3
-#define SOCAL_P_BSY 4
-#define SOCAL_F_BSY 5
-#define SOCAL_ONLINE 0x10
-#define SOCAL_OFFLINE 0x11
-#define SOCAL_TIMEOUT 0x12
-#define SOCAL_OVERRUN 0x13
-#define SOCAL_ONLINE_LOOP 0x14
-#define SOCAL_OLD_PORT 0x15
-#define SOCAL_AL_PORT 0x16
-#define SOCAL_UNKOWN_CQ_TYPE 0x20
-#define SOCAL_BAD_SEG_CNT 0x21
-#define SOCAL_MAX_XCHG_EXCEEDED 0x22
-#define SOCAL_BAD_XID 0x23
-#define SOCAL_XCHG_BUSY 0x24
-#define SOCAL_BAD_POOL_ID 0x25
-#define SOCAL_INSUFFICIENT_CQES 0x26
-#define SOCAL_ALLOC_FAIL 0x27
-#define SOCAL_BAD_SID 0x28
-#define SOCAL_NO_SEG_INIT 0x29
-#define SOCAL_BAD_DID 0x2a
-#define SOCAL_ABORTED 0x30
-#define SOCAL_ABORT_FAILED 0x31
-
-typedef struct {
- socal_hdr shdr;
- u32 status;
- socal_data data;
- u8 xxx1[10];
- u16 ncmds;
- fc_hdr fchdr;
- u8 count;
- u8 type;
- u8 flags;
- u8 seqno;
-} socal_rsp;
-
-typedef struct {
- socal_hdr shdr;
- u8 xxx1[48];
- u8 count;
- u8 type;
- u8 flags;
- u8 seqno;
-} socal_cmdonly;
-
-#define SOCAL_DIAG_NOP 0x00
-#define SOCAL_DIAG_INT_LOOP 0x01
-#define SOCAL_DIAG_EXT_LOOP 0x02
-#define SOCAL_DIAG_REM_LOOP 0x03
-#define SOCAL_DIAG_XRAM_TEST 0x04
-#define SOCAL_DIAG_SOC_TEST 0x05
-#define SOCAL_DIAG_HCB_TEST 0x06
-#define SOCAL_DIAG_SOCLB_TEST 0x07
-#define SOCAL_DIAG_SRDSLB_TEST 0x08
-#define SOCAL_DIAG_EXTOE_TEST 0x09
-
-typedef struct {
- socal_hdr shdr;
- u32 cmd;
- u8 xxx1[44];
- u8 count;
- u8 type;
- u8 flags;
- u8 seqno;
-} socal_diag_req;
-
-#define SOCAL_POOL_MASK_RCTL 0x800000
-#define SOCAL_POOL_MASK_DID 0x700000
-#define SOCAL_POOL_MASK_SID 0x070000
-#define SOCAL_POOL_MASK_TYPE 0x008000
-#define SOCAL_POOL_MASK_F_CTL 0x007000
-#define SOCAL_POOL_MASK_SEQ_ID 0x000800
-#define SOCAL_POOL_MASK_D_CTL 0x000400
-#define SOCAL_POOL_MASK_SEQ_CNT 0x000300
-#define SOCAL_POOL_MASK_OX_ID 0x0000f0
-#define SOCAL_POOL_MASK_PARAM 0x00000f
-
-typedef struct {
- socal_hdr shdr;
- u32 pool_id;
- u32 header_mask;
- u32 buf_size;
- u32 entries;
- u8 xxx1[8];
- fc_hdr fchdr;
- u8 count;
- u8 type;
- u8 flags;
- u8 seqno;
-} socal_pool_req;
-
-/* }}} */
-
-/* Now our software structures and constants we use to drive the beast {{{ */
-
-#define SOCAL_CQ_REQ0_SIZE 4
-#define SOCAL_CQ_REQ1_SIZE 256
-#define SOCAL_CQ_RSP0_SIZE 8
-#define SOCAL_CQ_RSP1_SIZE 4
-#define SOCAL_CQ_RSP2_SIZE 4
-
-#define SOCAL_SOLICITED_RSP_Q 0
-#define SOCAL_SOLICITED_BAD_RSP_Q 1
-#define SOCAL_UNSOLICITED_RSP_Q 2
-
-struct socal;
-
-typedef struct {
- /* This must come first */
- fc_channel fc;
- struct socal *s;
- u16 flags;
- u16 mask;
-} socal_port;
-
-typedef struct {
- socal_hw_cq __iomem *hw_cq; /* Related XRAM cq */
- socal_req *pool;
- u8 in;
- u8 out;
- u8 last;
- u8 seqno;
-} socal_cq;
-
-struct socal {
- spinlock_t lock;
- socal_port port[2]; /* Every SOCAL has one or two FC ports */
- socal_cq req[4]; /* Request CQs */
- socal_cq rsp[4]; /* Response CQs */
- int socal_no;
- void __iomem *regs;
- void __iomem *xram;
- void __iomem *eeprom;
- fc_wwn wwn;
- u32 imask; /* Our copy of regs->imask */
- u32 cfg; /* Our copy of regs->cfg */
- char serv_params[80];
- struct socal *next;
- int curr_port; /* Which port will have priority to fcp_queue_empty */
-
- socal_req * req_cpu;
- u32 req_dvma;
-};
-
-/* }}} */
-
-#endif /* !(__SOCAL_H) */
diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c
index 06471302200f..60f1a8924a95 100644
--- a/drivers/firewire/fw-cdev.c
+++ b/drivers/firewire/fw-cdev.c
@@ -25,11 +25,14 @@
#include <linux/device.h>
#include <linux/vmalloc.h>
#include <linux/poll.h>
+#include <linux/preempt.h>
+#include <linux/time.h>
#include <linux/delay.h>
#include <linux/mm.h>
#include <linux/idr.h>
#include <linux/compat.h>
#include <linux/firewire-cdev.h>
+#include <asm/system.h>
#include <asm/uaccess.h>
#include "fw-transaction.h"
#include "fw-topology.h"
@@ -140,11 +143,10 @@ static void queue_event(struct client *client, struct event *event,
event->v[1].size = size1;
spin_lock_irqsave(&client->lock, flags);
-
list_add_tail(&event->link, &client->event_list);
- wake_up_interruptible(&client->wait);
-
spin_unlock_irqrestore(&client->lock, flags);
+
+ wake_up_interruptible(&client->wait);
}
static int
@@ -621,20 +623,19 @@ iso_callback(struct fw_iso_context *context, u32 cycle,
size_t header_length, void *header, void *data)
{
struct client *client = data;
- struct iso_interrupt *interrupt;
+ struct iso_interrupt *irq;
- interrupt = kzalloc(sizeof(*interrupt) + header_length, GFP_ATOMIC);
- if (interrupt == NULL)
+ irq = kzalloc(sizeof(*irq) + header_length, GFP_ATOMIC);
+ if (irq == NULL)
return;
- interrupt->interrupt.type = FW_CDEV_EVENT_ISO_INTERRUPT;
- interrupt->interrupt.closure = client->iso_closure;
- interrupt->interrupt.cycle = cycle;
- interrupt->interrupt.header_length = header_length;
- memcpy(interrupt->interrupt.header, header, header_length);
- queue_event(client, &interrupt->event,
- &interrupt->interrupt,
- sizeof(interrupt->interrupt) + header_length, NULL, 0);
+ irq->interrupt.type = FW_CDEV_EVENT_ISO_INTERRUPT;
+ irq->interrupt.closure = client->iso_closure;
+ irq->interrupt.cycle = cycle;
+ irq->interrupt.header_length = header_length;
+ memcpy(irq->interrupt.header, header, header_length);
+ queue_event(client, &irq->event, &irq->interrupt,
+ sizeof(irq->interrupt) + header_length, NULL, 0);
}
static int ioctl_create_iso_context(struct client *client, void *buffer)
@@ -812,6 +813,28 @@ static int ioctl_stop_iso(struct client *client, void *buffer)
return fw_iso_context_stop(client->iso_context);
}
+static int ioctl_get_cycle_timer(struct client *client, void *buffer)
+{
+ struct fw_cdev_get_cycle_timer *request = buffer;
+ struct fw_card *card = client->device->card;
+ unsigned long long bus_time;
+ struct timeval tv;
+ unsigned long flags;
+
+ preempt_disable();
+ local_irq_save(flags);
+
+ bus_time = card->driver->get_bus_time(card);
+ do_gettimeofday(&tv);
+
+ local_irq_restore(flags);
+ preempt_enable();
+
+ request->local_time = tv.tv_sec * 1000000ULL + tv.tv_usec;
+ request->cycle_timer = bus_time & 0xffffffff;
+ return 0;
+}
+
static int (* const ioctl_handlers[])(struct client *client, void *buffer) = {
ioctl_get_info,
ioctl_send_request,
@@ -825,6 +848,7 @@ static int (* const ioctl_handlers[])(struct client *client, void *buffer) = {
ioctl_queue_iso,
ioctl_start_iso,
ioctl_stop_iso,
+ ioctl_get_cycle_timer,
};
static int
diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h
index d13e6a69707f..894d4a92a18e 100644
--- a/drivers/firewire/fw-device.h
+++ b/drivers/firewire/fw-device.h
@@ -102,11 +102,6 @@ fw_unit(struct device *dev)
#define CSR_INSTANCE 0x18
#define CSR_DIRECTORY_ID 0x20
-#define SBP2_COMMAND_SET_SPECIFIER 0x38
-#define SBP2_COMMAND_SET 0x39
-#define SBP2_COMMAND_SET_REVISION 0x3b
-#define SBP2_FIRMWARE_REVISION 0x3c
-
struct fw_csr_iterator {
u32 *p;
u32 *end;
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
index e14c1ca7813e..c9b9081831da 100644
--- a/drivers/firewire/fw-ohci.c
+++ b/drivers/firewire/fw-ohci.c
@@ -18,21 +18,23 @@
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
+#include <linux/compiler.h>
#include <linux/delay.h>
-#include <linux/poll.h>
#include <linux/dma-mapping.h>
+#include <linux/gfp.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
-#include <asm/uaccess.h>
-#include <asm/semaphore.h>
+#include <asm/page.h>
+#include <asm/system.h>
-#include "fw-transaction.h"
#include "fw-ohci.h"
+#include "fw-transaction.h"
#define DESCRIPTOR_OUTPUT_MORE 0
#define DESCRIPTOR_OUTPUT_LAST (1 << 12)
@@ -604,7 +606,7 @@ static int
at_context_queue_packet(struct context *ctx, struct fw_packet *packet)
{
struct fw_ohci *ohci = ctx->ohci;
- dma_addr_t d_bus, payload_bus;
+ dma_addr_t d_bus, uninitialized_var(payload_bus);
struct driver_data *driver_data;
struct descriptor *d, *last;
__le32 *header;
@@ -678,6 +680,9 @@ at_context_queue_packet(struct context *ctx, struct fw_packet *packet)
/* FIXME: Document how the locking works. */
if (ohci->generation != packet->generation) {
+ if (packet->payload_length > 0)
+ dma_unmap_single(ohci->card.device, payload_bus,
+ packet->payload_length, DMA_TO_DEVICE);
packet->ack = RCODE_GENERATION;
return -1;
}
@@ -912,10 +917,15 @@ static void bus_reset_tasklet(unsigned long data)
reg = reg_read(ohci, OHCI1394_NodeID);
if (!(reg & OHCI1394_NodeID_idValid)) {
- fw_error("node ID not valid, new bus reset in progress\n");
+ fw_notify("node ID not valid, new bus reset in progress\n");
+ return;
+ }
+ if ((reg & OHCI1394_NodeID_nodeNumber) == 63) {
+ fw_notify("malconfigured bus\n");
return;
}
- ohci->node_id = reg & 0xffff;
+ ohci->node_id = reg & (OHCI1394_NodeID_busNumber |
+ OHCI1394_NodeID_nodeNumber);
/*
* The count in the SelfIDCount register is the number of
@@ -926,12 +936,14 @@ static void bus_reset_tasklet(unsigned long data)
self_id_count = (reg_read(ohci, OHCI1394_SelfIDCount) >> 3) & 0x3ff;
generation = (le32_to_cpu(ohci->self_id_cpu[0]) >> 16) & 0xff;
+ rmb();
for (i = 1, j = 0; j < self_id_count; i += 2, j++) {
if (ohci->self_id_cpu[i] != ~ohci->self_id_cpu[i + 1])
fw_error("inconsistent self IDs\n");
ohci->self_id_buffer[j] = le32_to_cpu(ohci->self_id_cpu[i]);
}
+ rmb();
/*
* Check the consistency of the self IDs we just read. The
@@ -972,8 +984,10 @@ static void bus_reset_tasklet(unsigned long data)
*/
if (ohci->next_config_rom != NULL) {
- free_rom = ohci->config_rom;
- free_rom_bus = ohci->config_rom_bus;
+ if (ohci->next_config_rom != ohci->config_rom) {
+ free_rom = ohci->config_rom;
+ free_rom_bus = ohci->config_rom_bus;
+ }
ohci->config_rom = ohci->next_config_rom;
ohci->config_rom_bus = ohci->next_config_rom_bus;
ohci->next_config_rom = NULL;
@@ -1046,6 +1060,9 @@ static irqreturn_t irq_handler(int irq, void *data)
iso_event &= ~(1 << i);
}
+ if (unlikely(event & OHCI1394_postedWriteErr))
+ fw_error("PCI posted write error\n");
+
if (event & OHCI1394_cycle64Seconds) {
cycle_time = reg_read(ohci, OHCI1394_IsochronousCycleTimer);
if ((cycle_time & 0x80000000) == 0)
@@ -1119,8 +1136,8 @@ static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length)
OHCI1394_RQPkt | OHCI1394_RSPkt |
OHCI1394_reqTxComplete | OHCI1394_respTxComplete |
OHCI1394_isochRx | OHCI1394_isochTx |
- OHCI1394_masterIntEnable |
- OHCI1394_cycle64Seconds);
+ OHCI1394_postedWriteErr | OHCI1394_cycle64Seconds |
+ OHCI1394_masterIntEnable);
/* Activate link_on bit and contender bit in our self ID packets.*/
if (ohci_update_phy_reg(card, 4, 0,
@@ -1146,19 +1163,30 @@ static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length)
* the right values in the bus reset tasklet.
*/
- ohci->next_config_rom =
- dma_alloc_coherent(ohci->card.device, CONFIG_ROM_SIZE,
- &ohci->next_config_rom_bus, GFP_KERNEL);
- if (ohci->next_config_rom == NULL)
- return -ENOMEM;
+ if (config_rom) {
+ ohci->next_config_rom =
+ dma_alloc_coherent(ohci->card.device, CONFIG_ROM_SIZE,
+ &ohci->next_config_rom_bus,
+ GFP_KERNEL);
+ if (ohci->next_config_rom == NULL)
+ return -ENOMEM;
- memset(ohci->next_config_rom, 0, CONFIG_ROM_SIZE);
- fw_memcpy_to_be32(ohci->next_config_rom, config_rom, length * 4);
+ memset(ohci->next_config_rom, 0, CONFIG_ROM_SIZE);
+ fw_memcpy_to_be32(ohci->next_config_rom, config_rom, length * 4);
+ } else {
+ /*
+ * In the suspend case, config_rom is NULL, which
+ * means that we just reuse the old config rom.
+ */
+ ohci->next_config_rom = ohci->config_rom;
+ ohci->next_config_rom_bus = ohci->config_rom_bus;
+ }
- ohci->next_header = config_rom[0];
+ ohci->next_header = be32_to_cpu(ohci->next_config_rom[0]);
ohci->next_config_rom[0] = 0;
reg_write(ohci, OHCI1394_ConfigROMhdr, 0);
- reg_write(ohci, OHCI1394_BusOptions, config_rom[2]);
+ reg_write(ohci, OHCI1394_BusOptions,
+ be32_to_cpu(ohci->next_config_rom[2]));
reg_write(ohci, OHCI1394_ConfigROMmap, ohci->next_config_rom_bus);
reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000);
@@ -1444,7 +1472,7 @@ ohci_allocate_iso_context(struct fw_card *card, int type, size_t header_size)
/* FIXME: We need a fallback for pre 1.1 OHCI. */
if (callback == handle_ir_dualbuffer_packet &&
ohci->version < OHCI_VERSION_1_1)
- return ERR_PTR(-EINVAL);
+ return ERR_PTR(-ENOSYS);
spin_lock_irqsave(&ohci->lock, flags);
index = ffs(*mask) - 1;
@@ -1763,7 +1791,7 @@ ohci_queue_iso(struct fw_iso_context *base,
buffer, payload);
else
/* FIXME: Implement fallback for OHCI 1.0 controllers. */
- return -EINVAL;
+ return -ENOSYS;
}
static const struct fw_card_driver ohci_driver = {
@@ -1883,7 +1911,12 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
ohci->version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff;
fw_notify("Added fw-ohci device %s, OHCI version %x.%x\n",
dev->dev.bus_id, ohci->version >> 16, ohci->version & 0xff);
-
+ if (ohci->version < OHCI_VERSION_1_1) {
+ fw_notify(" Isochronous I/O is not yet implemented for "
+ "OHCI 1.0 chips.\n");
+ fw_notify(" Cameras, audio devices etc. won't work on "
+ "this controller with this driver version.\n");
+ }
return 0;
fail_self_id:
@@ -1964,7 +1997,7 @@ static int pci_resume(struct pci_dev *pdev)
return err;
}
- return ohci_enable(&ohci->card, ohci->config_rom, CONFIG_ROM_SIZE);
+ return ohci_enable(&ohci->card, NULL, 0);
}
#endif
diff --git a/drivers/firewire/fw-ohci.h b/drivers/firewire/fw-ohci.h
index fa15706397d7..dec4f04e6b24 100644
--- a/drivers/firewire/fw-ohci.h
+++ b/drivers/firewire/fw-ohci.h
@@ -59,6 +59,8 @@
#define OHCI1394_LinkControl_cycleSource (1 << 22)
#define OHCI1394_NodeID 0x0E8
#define OHCI1394_NodeID_idValid 0x80000000
+#define OHCI1394_NodeID_nodeNumber 0x0000003f
+#define OHCI1394_NodeID_busNumber 0x0000ffc0
#define OHCI1394_PhyControl 0x0EC
#define OHCI1394_PhyControl_Read(addr) (((addr) << 8) | 0x00008000)
#define OHCI1394_PhyControl_ReadDone 0x80000000
diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
index 238730f75db1..624ff3e082f6 100644
--- a/drivers/firewire/fw-sbp2.c
+++ b/drivers/firewire/fw-sbp2.c
@@ -37,11 +37,12 @@
#include <linux/dma-mapping.h>
#include <linux/blkdev.h>
#include <linux/string.h>
+#include <linux/stringify.h>
#include <linux/timer.h>
+#include <linux/workqueue.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_dbg.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
@@ -61,36 +62,94 @@ module_param_named(exclusive_login, sbp2_param_exclusive_login, bool, 0644);
MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device "
"(default = Y, use N for concurrent initiators)");
+/*
+ * Flags for firmware oddities
+ *
+ * - 128kB max transfer
+ * Limit transfer size. Necessary for some old bridges.
+ *
+ * - 36 byte inquiry
+ * When scsi_mod probes the device, let the inquiry command look like that
+ * from MS Windows.
+ *
+ * - skip mode page 8
+ * Suppress sending of mode_sense for mode page 8 if the device pretends to
+ * support the SCSI Primary Block commands instead of Reduced Block Commands.
+ *
+ * - fix capacity
+ * Tell sd_mod to correct the last sector number reported by read_capacity.
+ * Avoids access beyond actual disk limits on devices with an off-by-one bug.
+ * Don't use this with devices which don't have this bug.
+ *
+ * - override internal blacklist
+ * Instead of adding to the built-in blacklist, use only the workarounds
+ * specified in the module load parameter.
+ * Useful if a blacklist entry interfered with a non-broken device.
+ */
+#define SBP2_WORKAROUND_128K_MAX_TRANS 0x1
+#define SBP2_WORKAROUND_INQUIRY_36 0x2
+#define SBP2_WORKAROUND_MODE_SENSE_8 0x4
+#define SBP2_WORKAROUND_FIX_CAPACITY 0x8
+#define SBP2_WORKAROUND_OVERRIDE 0x100
+
+static int sbp2_param_workarounds;
+module_param_named(workarounds, sbp2_param_workarounds, int, 0644);
+MODULE_PARM_DESC(workarounds, "Work around device bugs (default = 0"
+ ", 128kB max transfer = " __stringify(SBP2_WORKAROUND_128K_MAX_TRANS)
+ ", 36 byte inquiry = " __stringify(SBP2_WORKAROUND_INQUIRY_36)
+ ", skip mode page 8 = " __stringify(SBP2_WORKAROUND_MODE_SENSE_8)
+ ", fix capacity = " __stringify(SBP2_WORKAROUND_FIX_CAPACITY)
+ ", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE)
+ ", or a combination)");
+
/* I don't know why the SCSI stack doesn't define something like this... */
typedef void (*scsi_done_fn_t)(struct scsi_cmnd *);
static const char sbp2_driver_name[] = "sbp2";
-struct sbp2_device {
- struct kref kref;
- struct fw_unit *unit;
+/*
+ * We create one struct sbp2_logical_unit per SBP-2 Logical Unit Number Entry
+ * and one struct scsi_device per sbp2_logical_unit.
+ */
+struct sbp2_logical_unit {
+ struct sbp2_target *tgt;
+ struct list_head link;
+ struct scsi_device *sdev;
struct fw_address_handler address_handler;
struct list_head orb_list;
- u64 management_agent_address;
+
u64 command_block_agent_address;
- u32 workarounds;
+ u16 lun;
int login_id;
/*
- * We cache these addresses and only update them once we've
- * logged in or reconnected to the sbp2 device. That way, any
- * IO to the device will automatically fail and get retried if
- * it happens in a window where the device is not ready to
- * handle it (e.g. after a bus reset but before we reconnect).
+ * The generation is updated once we've logged in or reconnected
+ * to the logical unit. Thus, I/O to the device will automatically
+ * fail and get retried if it happens in a window where the device
+ * is not ready, e.g. after a bus reset but before we reconnect.
*/
- int node_id;
- int address_high;
int generation;
-
int retries;
struct delayed_work work;
};
+/*
+ * We create one struct sbp2_target per IEEE 1212 Unit Directory
+ * and one struct Scsi_Host per sbp2_target.
+ */
+struct sbp2_target {
+ struct kref kref;
+ struct fw_unit *unit;
+
+ u64 management_agent_address;
+ int directory_id;
+ int node_id;
+ int address_high;
+
+ unsigned workarounds;
+ struct list_head lu_list;
+};
+
#define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000
#define SBP2_MAX_SECTORS 255 /* Max sectors supported */
#define SBP2_ORB_TIMEOUT 2000 /* Timeout in ms */
@@ -101,17 +160,9 @@ struct sbp2_device {
#define SBP2_DIRECTION_FROM_MEDIA 0x1
/* Unit directory keys */
-#define SBP2_COMMAND_SET_SPECIFIER 0x38
-#define SBP2_COMMAND_SET 0x39
-#define SBP2_COMMAND_SET_REVISION 0x3b
-#define SBP2_FIRMWARE_REVISION 0x3c
-
-/* Flags for detected oddities and brokeness */
-#define SBP2_WORKAROUND_128K_MAX_TRANS 0x1
-#define SBP2_WORKAROUND_INQUIRY_36 0x2
-#define SBP2_WORKAROUND_MODE_SENSE_8 0x4
-#define SBP2_WORKAROUND_FIX_CAPACITY 0x8
-#define SBP2_WORKAROUND_OVERRIDE 0x100
+#define SBP2_CSR_FIRMWARE_REVISION 0x3c
+#define SBP2_CSR_LOGICAL_UNIT_NUMBER 0x14
+#define SBP2_CSR_LOGICAL_UNIT_DIRECTORY 0xd4
/* Management orb opcodes */
#define SBP2_LOGIN_REQUEST 0x0
@@ -219,7 +270,7 @@ struct sbp2_command_orb {
} request;
struct scsi_cmnd *cmd;
scsi_done_fn_t done;
- struct fw_unit *unit;
+ struct sbp2_logical_unit *lu;
struct sbp2_pointer page_table[SG_ALL] __attribute__((aligned(8)));
dma_addr_t page_table_bus;
@@ -295,7 +346,7 @@ sbp2_status_write(struct fw_card *card, struct fw_request *request,
unsigned long long offset,
void *payload, size_t length, void *callback_data)
{
- struct sbp2_device *sd = callback_data;
+ struct sbp2_logical_unit *lu = callback_data;
struct sbp2_orb *orb;
struct sbp2_status status;
size_t header_size;
@@ -319,7 +370,7 @@ sbp2_status_write(struct fw_card *card, struct fw_request *request,
/* Lookup the orb corresponding to this status write. */
spin_lock_irqsave(&card->lock, flags);
- list_for_each_entry(orb, &sd->orb_list, link) {
+ list_for_each_entry(orb, &lu->orb_list, link) {
if (STATUS_GET_ORB_HIGH(status) == 0 &&
STATUS_GET_ORB_LOW(status) == orb->request_bus) {
orb->rcode = RCODE_COMPLETE;
@@ -329,7 +380,7 @@ sbp2_status_write(struct fw_card *card, struct fw_request *request,
}
spin_unlock_irqrestore(&card->lock, flags);
- if (&orb->link != &sd->orb_list)
+ if (&orb->link != &lu->orb_list)
orb->callback(orb, &status);
else
fw_error("status write for unknown orb\n");
@@ -361,20 +412,20 @@ complete_transaction(struct fw_card *card, int rcode,
orb->rcode = rcode;
if (orb->rcode != RCODE_COMPLETE) {
list_del(&orb->link);
+ spin_unlock_irqrestore(&card->lock, flags);
orb->callback(orb, NULL);
+ } else {
+ spin_unlock_irqrestore(&card->lock, flags);
}
- spin_unlock_irqrestore(&card->lock, flags);
-
kref_put(&orb->kref, free_orb);
}
static void
-sbp2_send_orb(struct sbp2_orb *orb, struct fw_unit *unit,
+sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu,
int node_id, int generation, u64 offset)
{
- struct fw_device *device = fw_device(unit->device.parent);
- struct sbp2_device *sd = unit->device.driver_data;
+ struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
unsigned long flags;
orb->pointer.high = 0;
@@ -382,7 +433,7 @@ sbp2_send_orb(struct sbp2_orb *orb, struct fw_unit *unit,
fw_memcpy_to_be32(&orb->pointer, &orb->pointer, sizeof(orb->pointer));
spin_lock_irqsave(&device->card->lock, flags);
- list_add_tail(&orb->link, &sd->orb_list);
+ list_add_tail(&orb->link, &lu->orb_list);
spin_unlock_irqrestore(&device->card->lock, flags);
/* Take a ref for the orb list and for the transaction callback. */
@@ -395,10 +446,9 @@ sbp2_send_orb(struct sbp2_orb *orb, struct fw_unit *unit,
complete_transaction, orb);
}
-static int sbp2_cancel_orbs(struct fw_unit *unit)
+static int sbp2_cancel_orbs(struct sbp2_logical_unit *lu)
{
- struct fw_device *device = fw_device(unit->device.parent);
- struct sbp2_device *sd = unit->device.driver_data;
+ struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
struct sbp2_orb *orb, *next;
struct list_head list;
unsigned long flags;
@@ -406,7 +456,7 @@ static int sbp2_cancel_orbs(struct fw_unit *unit)
INIT_LIST_HEAD(&list);
spin_lock_irqsave(&device->card->lock, flags);
- list_splice_init(&sd->orb_list, &list);
+ list_splice_init(&lu->orb_list, &list);
spin_unlock_irqrestore(&device->card->lock, flags);
list_for_each_entry_safe(orb, next, &list, link) {
@@ -433,11 +483,11 @@ complete_management_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
}
static int
-sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation,
- int function, int lun, void *response)
+sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id,
+ int generation, int function, int lun_or_login_id,
+ void *response)
{
- struct fw_device *device = fw_device(unit->device.parent);
- struct sbp2_device *sd = unit->device.driver_data;
+ struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
struct sbp2_management_orb *orb;
int retval = -ENOMEM;
@@ -458,12 +508,12 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation,
orb->request.misc =
MANAGEMENT_ORB_NOTIFY |
MANAGEMENT_ORB_FUNCTION(function) |
- MANAGEMENT_ORB_LUN(lun);
+ MANAGEMENT_ORB_LUN(lun_or_login_id);
orb->request.length =
MANAGEMENT_ORB_RESPONSE_LENGTH(sizeof(orb->response));
- orb->request.status_fifo.high = sd->address_handler.offset >> 32;
- orb->request.status_fifo.low = sd->address_handler.offset;
+ orb->request.status_fifo.high = lu->address_handler.offset >> 32;
+ orb->request.status_fifo.low = lu->address_handler.offset;
if (function == SBP2_LOGIN_REQUEST) {
orb->request.misc |=
@@ -482,14 +532,14 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation,
if (dma_mapping_error(orb->base.request_bus))
goto fail_mapping_request;
- sbp2_send_orb(&orb->base, unit,
- node_id, generation, sd->management_agent_address);
+ sbp2_send_orb(&orb->base, lu, node_id, generation,
+ lu->tgt->management_agent_address);
wait_for_completion_timeout(&orb->done,
msecs_to_jiffies(SBP2_ORB_TIMEOUT));
retval = -EIO;
- if (sbp2_cancel_orbs(unit) == 0) {
+ if (sbp2_cancel_orbs(lu) == 0) {
fw_error("orb reply timed out, rcode=0x%02x\n",
orb->base.rcode);
goto out;
@@ -534,10 +584,9 @@ complete_agent_reset_write(struct fw_card *card, int rcode,
kfree(t);
}
-static int sbp2_agent_reset(struct fw_unit *unit)
+static int sbp2_agent_reset(struct sbp2_logical_unit *lu)
{
- struct fw_device *device = fw_device(unit->device.parent);
- struct sbp2_device *sd = unit->device.driver_data;
+ struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
struct fw_transaction *t;
static u32 zero;
@@ -546,181 +595,273 @@ static int sbp2_agent_reset(struct fw_unit *unit)
return -ENOMEM;
fw_send_request(device->card, t, TCODE_WRITE_QUADLET_REQUEST,
- sd->node_id, sd->generation, device->max_speed,
- sd->command_block_agent_address + SBP2_AGENT_RESET,
+ lu->tgt->node_id, lu->generation, device->max_speed,
+ lu->command_block_agent_address + SBP2_AGENT_RESET,
&zero, sizeof(zero), complete_agent_reset_write, t);
return 0;
}
-static void sbp2_reconnect(struct work_struct *work);
-static struct scsi_host_template scsi_driver_template;
-
-static void release_sbp2_device(struct kref *kref)
+static void sbp2_release_target(struct kref *kref)
{
- struct sbp2_device *sd = container_of(kref, struct sbp2_device, kref);
- struct Scsi_Host *host =
- container_of((void *)sd, struct Scsi_Host, hostdata[0]);
-
- scsi_remove_host(host);
- sbp2_send_management_orb(sd->unit, sd->node_id, sd->generation,
- SBP2_LOGOUT_REQUEST, sd->login_id, NULL);
- fw_core_remove_address_handler(&sd->address_handler);
- fw_notify("removed sbp2 unit %s\n", sd->unit->device.bus_id);
- put_device(&sd->unit->device);
- scsi_host_put(host);
+ struct sbp2_target *tgt = container_of(kref, struct sbp2_target, kref);
+ struct sbp2_logical_unit *lu, *next;
+ struct Scsi_Host *shost =
+ container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
+
+ list_for_each_entry_safe(lu, next, &tgt->lu_list, link) {
+ if (lu->sdev)
+ scsi_remove_device(lu->sdev);
+
+ sbp2_send_management_orb(lu, tgt->node_id, lu->generation,
+ SBP2_LOGOUT_REQUEST, lu->login_id, NULL);
+ fw_core_remove_address_handler(&lu->address_handler);
+ list_del(&lu->link);
+ kfree(lu);
+ }
+ scsi_remove_host(shost);
+ fw_notify("released %s\n", tgt->unit->device.bus_id);
+
+ put_device(&tgt->unit->device);
+ scsi_host_put(shost);
}
+static struct workqueue_struct *sbp2_wq;
+
+static void sbp2_reconnect(struct work_struct *work);
+
static void sbp2_login(struct work_struct *work)
{
- struct sbp2_device *sd =
- container_of(work, struct sbp2_device, work.work);
- struct Scsi_Host *host =
- container_of((void *)sd, struct Scsi_Host, hostdata[0]);
- struct fw_unit *unit = sd->unit;
+ struct sbp2_logical_unit *lu =
+ container_of(work, struct sbp2_logical_unit, work.work);
+ struct Scsi_Host *shost =
+ container_of((void *)lu->tgt, struct Scsi_Host, hostdata[0]);
+ struct scsi_device *sdev;
+ struct scsi_lun eight_bytes_lun;
+ struct fw_unit *unit = lu->tgt->unit;
struct fw_device *device = fw_device(unit->device.parent);
struct sbp2_login_response response;
- int generation, node_id, local_node_id, lun, retval;
-
- /* FIXME: Make this work for multi-lun devices. */
- lun = 0;
+ int generation, node_id, local_node_id;
generation = device->card->generation;
node_id = device->node->node_id;
local_node_id = device->card->local_node->node_id;
- if (sbp2_send_management_orb(unit, node_id, generation,
- SBP2_LOGIN_REQUEST, lun, &response) < 0) {
- if (sd->retries++ < 5) {
- schedule_delayed_work(&sd->work, DIV_ROUND_UP(HZ, 5));
+ if (sbp2_send_management_orb(lu, node_id, generation,
+ SBP2_LOGIN_REQUEST, lu->lun, &response) < 0) {
+ if (lu->retries++ < 5) {
+ if (queue_delayed_work(sbp2_wq, &lu->work,
+ DIV_ROUND_UP(HZ, 5)))
+ kref_get(&lu->tgt->kref);
} else {
- fw_error("failed to login to %s\n",
- unit->device.bus_id);
- kref_put(&sd->kref, release_sbp2_device);
+ fw_error("failed to login to %s LUN %04x\n",
+ unit->device.bus_id, lu->lun);
}
+ kref_put(&lu->tgt->kref, sbp2_release_target);
return;
}
- sd->generation = generation;
- sd->node_id = node_id;
- sd->address_high = local_node_id << 16;
+ lu->generation = generation;
+ lu->tgt->node_id = node_id;
+ lu->tgt->address_high = local_node_id << 16;
/* Get command block agent offset and login id. */
- sd->command_block_agent_address =
+ lu->command_block_agent_address =
((u64) (response.command_block_agent.high & 0xffff) << 32) |
response.command_block_agent.low;
- sd->login_id = LOGIN_RESPONSE_GET_LOGIN_ID(response);
+ lu->login_id = LOGIN_RESPONSE_GET_LOGIN_ID(response);
- fw_notify("logged in to sbp2 unit %s (%d retries)\n",
- unit->device.bus_id, sd->retries);
- fw_notify(" - management_agent_address: 0x%012llx\n",
- (unsigned long long) sd->management_agent_address);
- fw_notify(" - command_block_agent_address: 0x%012llx\n",
- (unsigned long long) sd->command_block_agent_address);
- fw_notify(" - status write address: 0x%012llx\n",
- (unsigned long long) sd->address_handler.offset);
+ fw_notify("logged in to %s LUN %04x (%d retries)\n",
+ unit->device.bus_id, lu->lun, lu->retries);
#if 0
/* FIXME: The linux1394 sbp2 does this last step. */
sbp2_set_busy_timeout(scsi_id);
#endif
- PREPARE_DELAYED_WORK(&sd->work, sbp2_reconnect);
- sbp2_agent_reset(unit);
+ PREPARE_DELAYED_WORK(&lu->work, sbp2_reconnect);
+ sbp2_agent_reset(lu);
+
+ memset(&eight_bytes_lun, 0, sizeof(eight_bytes_lun));
+ eight_bytes_lun.scsi_lun[0] = (lu->lun >> 8) & 0xff;
+ eight_bytes_lun.scsi_lun[1] = lu->lun & 0xff;
- /* FIXME: Loop over luns here. */
- lun = 0;
- retval = scsi_add_device(host, 0, 0, lun);
- if (retval < 0) {
- sbp2_send_management_orb(unit, sd->node_id, sd->generation,
- SBP2_LOGOUT_REQUEST, sd->login_id,
- NULL);
+ sdev = __scsi_add_device(shost, 0, 0,
+ scsilun_to_int(&eight_bytes_lun), lu);
+ if (IS_ERR(sdev)) {
+ sbp2_send_management_orb(lu, node_id, generation,
+ SBP2_LOGOUT_REQUEST, lu->login_id, NULL);
/*
* Set this back to sbp2_login so we fall back and
* retry login on bus reset.
*/
- PREPARE_DELAYED_WORK(&sd->work, sbp2_login);
+ PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
+ } else {
+ lu->sdev = sdev;
+ scsi_device_put(sdev);
}
- kref_put(&sd->kref, release_sbp2_device);
+ kref_put(&lu->tgt->kref, sbp2_release_target);
}
-static int sbp2_probe(struct device *dev)
+static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry)
{
- struct fw_unit *unit = fw_unit(dev);
- struct fw_device *device = fw_device(unit->device.parent);
- struct sbp2_device *sd;
- struct fw_csr_iterator ci;
- struct Scsi_Host *host;
- int i, key, value, err;
- u32 model, firmware_revision;
+ struct sbp2_logical_unit *lu;
- err = -ENOMEM;
- host = scsi_host_alloc(&scsi_driver_template, sizeof(*sd));
- if (host == NULL)
- goto fail;
+ lu = kmalloc(sizeof(*lu), GFP_KERNEL);
+ if (!lu)
+ return -ENOMEM;
- sd = (struct sbp2_device *) host->hostdata;
- unit->device.driver_data = sd;
- sd->unit = unit;
- INIT_LIST_HEAD(&sd->orb_list);
- kref_init(&sd->kref);
+ lu->address_handler.length = 0x100;
+ lu->address_handler.address_callback = sbp2_status_write;
+ lu->address_handler.callback_data = lu;
- sd->address_handler.length = 0x100;
- sd->address_handler.address_callback = sbp2_status_write;
- sd->address_handler.callback_data = sd;
+ if (fw_core_add_address_handler(&lu->address_handler,
+ &fw_high_memory_region) < 0) {
+ kfree(lu);
+ return -ENOMEM;
+ }
- err = fw_core_add_address_handler(&sd->address_handler,
- &fw_high_memory_region);
- if (err < 0)
- goto fail_host;
+ lu->tgt = tgt;
+ lu->sdev = NULL;
+ lu->lun = lun_entry & 0xffff;
+ lu->retries = 0;
+ INIT_LIST_HEAD(&lu->orb_list);
+ INIT_DELAYED_WORK(&lu->work, sbp2_login);
- err = fw_device_enable_phys_dma(device);
- if (err < 0)
- goto fail_address_handler;
+ list_add_tail(&lu->link, &tgt->lu_list);
+ return 0;
+}
- err = scsi_add_host(host, &unit->device);
- if (err < 0)
- goto fail_address_handler;
+static int sbp2_scan_logical_unit_dir(struct sbp2_target *tgt, u32 *directory)
+{
+ struct fw_csr_iterator ci;
+ int key, value;
- /*
- * Scan unit directory to get management agent address,
- * firmware revison and model. Initialize firmware_revision
- * and model to values that wont match anything in our table.
- */
- firmware_revision = 0xff000000;
- model = 0xff000000;
- fw_csr_iterator_init(&ci, unit->directory);
+ fw_csr_iterator_init(&ci, directory);
+ while (fw_csr_iterator_next(&ci, &key, &value))
+ if (key == SBP2_CSR_LOGICAL_UNIT_NUMBER &&
+ sbp2_add_logical_unit(tgt, value) < 0)
+ return -ENOMEM;
+ return 0;
+}
+
+static int sbp2_scan_unit_dir(struct sbp2_target *tgt, u32 *directory,
+ u32 *model, u32 *firmware_revision)
+{
+ struct fw_csr_iterator ci;
+ int key, value;
+
+ fw_csr_iterator_init(&ci, directory);
while (fw_csr_iterator_next(&ci, &key, &value)) {
switch (key) {
+
case CSR_DEPENDENT_INFO | CSR_OFFSET:
- sd->management_agent_address =
- 0xfffff0000000ULL + 4 * value;
+ tgt->management_agent_address =
+ CSR_REGISTER_BASE + 4 * value;
break;
- case SBP2_FIRMWARE_REVISION:
- firmware_revision = value;
+
+ case CSR_DIRECTORY_ID:
+ tgt->directory_id = value;
break;
+
case CSR_MODEL:
- model = value;
+ *model = value;
+ break;
+
+ case SBP2_CSR_FIRMWARE_REVISION:
+ *firmware_revision = value;
+ break;
+
+ case SBP2_CSR_LOGICAL_UNIT_NUMBER:
+ if (sbp2_add_logical_unit(tgt, value) < 0)
+ return -ENOMEM;
+ break;
+
+ case SBP2_CSR_LOGICAL_UNIT_DIRECTORY:
+ if (sbp2_scan_logical_unit_dir(tgt, ci.p + value) < 0)
+ return -ENOMEM;
break;
}
}
+ return 0;
+}
+
+static void sbp2_init_workarounds(struct sbp2_target *tgt, u32 model,
+ u32 firmware_revision)
+{
+ int i;
+ unsigned w = sbp2_param_workarounds;
+
+ if (w)
+ fw_notify("Please notify linux1394-devel@lists.sourceforge.net "
+ "if you need the workarounds parameter for %s\n",
+ tgt->unit->device.bus_id);
+
+ if (w & SBP2_WORKAROUND_OVERRIDE)
+ goto out;
for (i = 0; i < ARRAY_SIZE(sbp2_workarounds_table); i++) {
+
if (sbp2_workarounds_table[i].firmware_revision !=
(firmware_revision & 0xffffff00))
continue;
+
if (sbp2_workarounds_table[i].model != model &&
sbp2_workarounds_table[i].model != ~0)
continue;
- sd->workarounds |= sbp2_workarounds_table[i].workarounds;
+
+ w |= sbp2_workarounds_table[i].workarounds;
break;
}
-
- if (sd->workarounds)
- fw_notify("Workarounds for node %s: 0x%x "
+ out:
+ if (w)
+ fw_notify("Workarounds for %s: 0x%x "
"(firmware_revision 0x%06x, model_id 0x%06x)\n",
- unit->device.bus_id,
- sd->workarounds, firmware_revision, model);
+ tgt->unit->device.bus_id,
+ w, firmware_revision, model);
+ tgt->workarounds = w;
+}
+
+static struct scsi_host_template scsi_driver_template;
+
+static int sbp2_probe(struct device *dev)
+{
+ struct fw_unit *unit = fw_unit(dev);
+ struct fw_device *device = fw_device(unit->device.parent);
+ struct sbp2_target *tgt;
+ struct sbp2_logical_unit *lu;
+ struct Scsi_Host *shost;
+ u32 model, firmware_revision;
+
+ shost = scsi_host_alloc(&scsi_driver_template, sizeof(*tgt));
+ if (shost == NULL)
+ return -ENOMEM;
+
+ tgt = (struct sbp2_target *)shost->hostdata;
+ unit->device.driver_data = tgt;
+ tgt->unit = unit;
+ kref_init(&tgt->kref);
+ INIT_LIST_HEAD(&tgt->lu_list);
+
+ if (fw_device_enable_phys_dma(device) < 0)
+ goto fail_shost_put;
+
+ if (scsi_add_host(shost, &unit->device) < 0)
+ goto fail_shost_put;
+
+ /* Initialize to values that won't match anything in our table. */
+ firmware_revision = 0xff000000;
+ model = 0xff000000;
+
+ /* implicit directory ID */
+ tgt->directory_id = ((unit->directory - device->config_rom) * 4
+ + CSR_CONFIG_ROM) & 0xffffff;
+
+ if (sbp2_scan_unit_dir(tgt, unit->directory, &model,
+ &firmware_revision) < 0)
+ goto fail_tgt_put;
+
+ sbp2_init_workarounds(tgt, model, firmware_revision);
get_device(&unit->device);
@@ -729,35 +870,34 @@ static int sbp2_probe(struct device *dev)
* reschedule retries. Always get the ref before scheduling
* work.
*/
- INIT_DELAYED_WORK(&sd->work, sbp2_login);
- if (schedule_delayed_work(&sd->work, 0))
- kref_get(&sd->kref);
-
+ list_for_each_entry(lu, &tgt->lu_list, link)
+ if (queue_delayed_work(sbp2_wq, &lu->work, 0))
+ kref_get(&tgt->kref);
return 0;
- fail_address_handler:
- fw_core_remove_address_handler(&sd->address_handler);
- fail_host:
- scsi_host_put(host);
- fail:
- return err;
+ fail_tgt_put:
+ kref_put(&tgt->kref, sbp2_release_target);
+ return -ENOMEM;
+
+ fail_shost_put:
+ scsi_host_put(shost);
+ return -ENOMEM;
}
static int sbp2_remove(struct device *dev)
{
struct fw_unit *unit = fw_unit(dev);
- struct sbp2_device *sd = unit->device.driver_data;
-
- kref_put(&sd->kref, release_sbp2_device);
+ struct sbp2_target *tgt = unit->device.driver_data;
+ kref_put(&tgt->kref, sbp2_release_target);
return 0;
}
static void sbp2_reconnect(struct work_struct *work)
{
- struct sbp2_device *sd =
- container_of(work, struct sbp2_device, work.work);
- struct fw_unit *unit = sd->unit;
+ struct sbp2_logical_unit *lu =
+ container_of(work, struct sbp2_logical_unit, work.work);
+ struct fw_unit *unit = lu->tgt->unit;
struct fw_device *device = fw_device(unit->device.parent);
int generation, node_id, local_node_id;
@@ -765,40 +905,51 @@ static void sbp2_reconnect(struct work_struct *work)
node_id = device->node->node_id;
local_node_id = device->card->local_node->node_id;
- if (sbp2_send_management_orb(unit, node_id, generation,
+ if (sbp2_send_management_orb(lu, node_id, generation,
SBP2_RECONNECT_REQUEST,
- sd->login_id, NULL) < 0) {
- if (sd->retries++ >= 5) {
+ lu->login_id, NULL) < 0) {
+ if (lu->retries++ >= 5) {
fw_error("failed to reconnect to %s\n",
unit->device.bus_id);
/* Fall back and try to log in again. */
- sd->retries = 0;
- PREPARE_DELAYED_WORK(&sd->work, sbp2_login);
+ lu->retries = 0;
+ PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
}
- schedule_delayed_work(&sd->work, DIV_ROUND_UP(HZ, 5));
+ if (queue_delayed_work(sbp2_wq, &lu->work, DIV_ROUND_UP(HZ, 5)))
+ kref_get(&lu->tgt->kref);
+ kref_put(&lu->tgt->kref, sbp2_release_target);
return;
}
- sd->generation = generation;
- sd->node_id = node_id;
- sd->address_high = local_node_id << 16;
+ lu->generation = generation;
+ lu->tgt->node_id = node_id;
+ lu->tgt->address_high = local_node_id << 16;
- fw_notify("reconnected to unit %s (%d retries)\n",
- unit->device.bus_id, sd->retries);
- sbp2_agent_reset(unit);
- sbp2_cancel_orbs(unit);
- kref_put(&sd->kref, release_sbp2_device);
+ fw_notify("reconnected to %s LUN %04x (%d retries)\n",
+ unit->device.bus_id, lu->lun, lu->retries);
+
+ sbp2_agent_reset(lu);
+ sbp2_cancel_orbs(lu);
+
+ kref_put(&lu->tgt->kref, sbp2_release_target);
}
static void sbp2_update(struct fw_unit *unit)
{
- struct fw_device *device = fw_device(unit->device.parent);
- struct sbp2_device *sd = unit->device.driver_data;
+ struct sbp2_target *tgt = unit->device.driver_data;
+ struct sbp2_logical_unit *lu;
- sd->retries = 0;
- fw_device_enable_phys_dma(device);
- if (schedule_delayed_work(&sd->work, 0))
- kref_get(&sd->kref);
+ fw_device_enable_phys_dma(fw_device(unit->device.parent));
+
+ /*
+ * Fw-core serializes sbp2_update() against sbp2_remove().
+ * Iteration over tgt->lu_list is therefore safe here.
+ */
+ list_for_each_entry(lu, &tgt->lu_list, link) {
+ lu->retries = 0;
+ if (queue_delayed_work(sbp2_wq, &lu->work, 0))
+ kref_get(&tgt->kref);
+ }
}
#define SBP2_UNIT_SPEC_ID_ENTRY 0x0000609e
@@ -868,13 +1019,12 @@ complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
{
struct sbp2_command_orb *orb =
container_of(base_orb, struct sbp2_command_orb, base);
- struct fw_unit *unit = orb->unit;
- struct fw_device *device = fw_device(unit->device.parent);
+ struct fw_device *device = fw_device(orb->lu->tgt->unit->device.parent);
int result;
if (status != NULL) {
if (STATUS_GET_DEAD(*status))
- sbp2_agent_reset(unit);
+ sbp2_agent_reset(orb->lu);
switch (STATUS_GET_RESPONSE(*status)) {
case SBP2_STATUS_REQUEST_COMPLETE:
@@ -918,12 +1068,10 @@ complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
orb->done(orb->cmd);
}
-static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb)
+static int
+sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device,
+ struct sbp2_logical_unit *lu)
{
- struct sbp2_device *sd =
- (struct sbp2_device *)orb->cmd->device->host->hostdata;
- struct fw_unit *unit = sd->unit;
- struct fw_device *device = fw_device(unit->device.parent);
struct scatterlist *sg;
int sg_len, l, i, j, count;
dma_addr_t sg_addr;
@@ -942,10 +1090,9 @@ static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb)
* tables.
*/
if (count == 1 && sg_dma_len(sg) < SBP2_MAX_SG_ELEMENT_LENGTH) {
- orb->request.data_descriptor.high = sd->address_high;
+ orb->request.data_descriptor.high = lu->tgt->address_high;
orb->request.data_descriptor.low = sg_dma_address(sg);
- orb->request.misc |=
- COMMAND_ORB_DATA_SIZE(sg_dma_len(sg));
+ orb->request.misc |= COMMAND_ORB_DATA_SIZE(sg_dma_len(sg));
return 0;
}
@@ -989,7 +1136,7 @@ static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb)
* initiator (i.e. us), but data_descriptor can refer to data
* on other nodes so we need to put our ID in descriptor.high.
*/
- orb->request.data_descriptor.high = sd->address_high;
+ orb->request.data_descriptor.high = lu->tgt->address_high;
orb->request.data_descriptor.low = orb->page_table_bus;
orb->request.misc |=
COMMAND_ORB_PAGE_TABLE_PRESENT |
@@ -1008,12 +1155,11 @@ static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb)
static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
{
- struct sbp2_device *sd =
- (struct sbp2_device *)cmd->device->host->hostdata;
- struct fw_unit *unit = sd->unit;
- struct fw_device *device = fw_device(unit->device.parent);
+ struct sbp2_logical_unit *lu = cmd->device->hostdata;
+ struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
struct sbp2_command_orb *orb;
unsigned max_payload;
+ int retval = SCSI_MLQUEUE_HOST_BUSY;
/*
* Bidirectional commands are not yet implemented, and unknown
@@ -1029,14 +1175,14 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
orb = kzalloc(sizeof(*orb), GFP_ATOMIC);
if (orb == NULL) {
fw_notify("failed to alloc orb\n");
- goto fail_alloc;
+ return SCSI_MLQUEUE_HOST_BUSY;
}
/* Initialize rcode to something not RCODE_COMPLETE. */
orb->base.rcode = -1;
kref_init(&orb->base.kref);
- orb->unit = unit;
+ orb->lu = lu;
orb->done = done;
orb->cmd = cmd;
@@ -1062,8 +1208,8 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
orb->request.misc |=
COMMAND_ORB_DIRECTION(SBP2_DIRECTION_TO_MEDIA);
- if (scsi_sg_count(cmd) && sbp2_command_orb_map_scatterlist(orb) < 0)
- goto fail_mapping;
+ if (scsi_sg_count(cmd) && sbp2_map_scatterlist(orb, device, lu) < 0)
+ goto out;
fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request));
@@ -1076,49 +1222,47 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
dma_map_single(device->card->device, &orb->request,
sizeof(orb->request), DMA_TO_DEVICE);
if (dma_mapping_error(orb->base.request_bus))
- goto fail_mapping;
-
- sbp2_send_orb(&orb->base, unit, sd->node_id, sd->generation,
- sd->command_block_agent_address + SBP2_ORB_POINTER);
-
- kref_put(&orb->base.kref, free_orb);
- return 0;
+ goto out;
- fail_mapping:
+ sbp2_send_orb(&orb->base, lu, lu->tgt->node_id, lu->generation,
+ lu->command_block_agent_address + SBP2_ORB_POINTER);
+ retval = 0;
+ out:
kref_put(&orb->base.kref, free_orb);
- fail_alloc:
- return SCSI_MLQUEUE_HOST_BUSY;
+ return retval;
}
static int sbp2_scsi_slave_alloc(struct scsi_device *sdev)
{
- struct sbp2_device *sd = (struct sbp2_device *)sdev->host->hostdata;
+ struct sbp2_logical_unit *lu = sdev->hostdata;
sdev->allow_restart = 1;
- if (sd->workarounds & SBP2_WORKAROUND_INQUIRY_36)
+ if (lu->tgt->workarounds & SBP2_WORKAROUND_INQUIRY_36)
sdev->inquiry_len = 36;
+
return 0;
}
static int sbp2_scsi_slave_configure(struct scsi_device *sdev)
{
- struct sbp2_device *sd = (struct sbp2_device *)sdev->host->hostdata;
- struct fw_unit *unit = sd->unit;
+ struct sbp2_logical_unit *lu = sdev->hostdata;
sdev->use_10_for_rw = 1;
if (sdev->type == TYPE_ROM)
sdev->use_10_for_ms = 1;
+
if (sdev->type == TYPE_DISK &&
- sd->workarounds & SBP2_WORKAROUND_MODE_SENSE_8)
+ lu->tgt->workarounds & SBP2_WORKAROUND_MODE_SENSE_8)
sdev->skip_ms_page_8 = 1;
- if (sd->workarounds & SBP2_WORKAROUND_FIX_CAPACITY) {
- fw_notify("setting fix_capacity for %s\n", unit->device.bus_id);
+
+ if (lu->tgt->workarounds & SBP2_WORKAROUND_FIX_CAPACITY)
sdev->fix_capacity = 1;
- }
- if (sd->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS)
+
+ if (lu->tgt->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS)
blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512);
+
return 0;
}
@@ -1128,13 +1272,11 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev)
*/
static int sbp2_scsi_abort(struct scsi_cmnd *cmd)
{
- struct sbp2_device *sd =
- (struct sbp2_device *)cmd->device->host->hostdata;
- struct fw_unit *unit = sd->unit;
+ struct sbp2_logical_unit *lu = cmd->device->hostdata;
fw_notify("sbp2_scsi_abort\n");
- sbp2_agent_reset(unit);
- sbp2_cancel_orbs(unit);
+ sbp2_agent_reset(lu);
+ sbp2_cancel_orbs(lu);
return SUCCESS;
}
@@ -1151,37 +1293,18 @@ sbp2_sysfs_ieee1394_id_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct scsi_device *sdev = to_scsi_device(dev);
- struct sbp2_device *sd;
- struct fw_unit *unit;
+ struct sbp2_logical_unit *lu;
struct fw_device *device;
- u32 directory_id;
- struct fw_csr_iterator ci;
- int key, value, lun;
if (!sdev)
return 0;
- sd = (struct sbp2_device *)sdev->host->hostdata;
- unit = sd->unit;
- device = fw_device(unit->device.parent);
-
- /* implicit directory ID */
- directory_id = ((unit->directory - device->config_rom) * 4
- + CSR_CONFIG_ROM) & 0xffffff;
-
- /* explicit directory ID, overrides implicit ID if present */
- fw_csr_iterator_init(&ci, unit->directory);
- while (fw_csr_iterator_next(&ci, &key, &value))
- if (key == CSR_DIRECTORY_ID) {
- directory_id = value;
- break;
- }
- /* FIXME: Make this work for multi-lun devices. */
- lun = 0;
+ lu = sdev->hostdata;
+ device = fw_device(lu->tgt->unit->device.parent);
return sprintf(buf, "%08x%08x:%06x:%04x\n",
device->config_rom[3], device->config_rom[4],
- directory_id, lun);
+ lu->tgt->directory_id, lu->lun);
}
static DEVICE_ATTR(ieee1394_id, S_IRUGO, sbp2_sysfs_ieee1394_id_show, NULL);
@@ -1219,12 +1342,17 @@ MODULE_ALIAS("sbp2");
static int __init sbp2_init(void)
{
+ sbp2_wq = create_singlethread_workqueue(KBUILD_MODNAME);
+ if (!sbp2_wq)
+ return -ENOMEM;
+
return driver_register(&sbp2_driver.driver);
}
static void __exit sbp2_cleanup(void)
{
driver_unregister(&sbp2_driver.driver);
+ destroy_workqueue(sbp2_wq);
}
module_init(sbp2_init);
diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c
index 39e5cd12aa52..0fc9b000e99d 100644
--- a/drivers/firewire/fw-topology.c
+++ b/drivers/firewire/fw-topology.c
@@ -152,6 +152,10 @@ static void update_hop_count(struct fw_node *node)
node->max_hops = max(max_child_hops, depths[0] + depths[1] + 2);
}
+static inline struct fw_node *fw_node(struct list_head *l)
+{
+ return list_entry(l, struct fw_node, link);
+}
/**
* build_tree - Build the tree representation of the topology
@@ -162,7 +166,7 @@ static void update_hop_count(struct fw_node *node)
* This function builds the tree representation of the topology given
* by the self IDs from the latest bus reset. During the construction
* of the tree, the function checks that the self IDs are valid and
- * internally consistent. On succcess this funtions returns the
+ * internally consistent. On succcess this function returns the
* fw_node corresponding to the local card otherwise NULL.
*/
static struct fw_node *build_tree(struct fw_card *card,
@@ -211,6 +215,10 @@ static struct fw_node *build_tree(struct fw_card *card,
*/
for (i = 0, h = &stack; i < child_port_count; i++)
h = h->prev;
+ /*
+ * When the stack is empty, this yields an invalid value,
+ * but that pointer will never be dereferenced.
+ */
child = fw_node(h);
node = fw_node_create(q, port_count, card->color);
diff --git a/drivers/firewire/fw-topology.h b/drivers/firewire/fw-topology.h
index 1b56b4ac7fb2..cedc1ec906e9 100644
--- a/drivers/firewire/fw-topology.h
+++ b/drivers/firewire/fw-topology.h
@@ -51,12 +51,6 @@ struct fw_node {
};
static inline struct fw_node *
-fw_node(struct list_head *l)
-{
- return list_entry(l, struct fw_node, link);
-}
-
-static inline struct fw_node *
fw_node_get(struct fw_node *node)
{
atomic_inc(&node->ref_count);
diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c
index 3e1cb12e43cd..c00d4a9b39e5 100644
--- a/drivers/firewire/fw-transaction.c
+++ b/drivers/firewire/fw-transaction.c
@@ -228,7 +228,7 @@ fw_fill_request(struct fw_packet *packet, int tcode, int tlabel,
*
* @param card the card from which to send the request
* @param tcode the tcode for this transaction. Do not use
- * TCODE_LOCK_REQUEST directly, insted use TCODE_LOCK_MASK_SWAP
+ * TCODE_LOCK_REQUEST directly, instead use TCODE_LOCK_MASK_SWAP
* etc. to specify tcode and ext_tcode.
* @param node_id the destination node ID (bus ID and PHY ID concatenated)
* @param generation the generation for which node_id is valid
@@ -410,7 +410,12 @@ EXPORT_SYMBOL(fw_unit_space_region);
* controller. When a request is received that falls within the
* specified address range, the specified callback is invoked. The
* parameters passed to the callback give the details of the
- * particular request
+ * particular request.
+ *
+ * Return value: 0 on success, non-zero otherwise.
+ * The start offset of the handler's address region is determined by
+ * fw_core_add_address_handler() and is returned in handler->offset.
+ * The offset is quadlet-aligned.
*/
int
fw_core_add_address_handler(struct fw_address_handler *handler,
@@ -422,14 +427,15 @@ fw_core_add_address_handler(struct fw_address_handler *handler,
spin_lock_irqsave(&address_handler_lock, flags);
- handler->offset = region->start;
+ handler->offset = roundup(region->start, 4);
while (handler->offset + handler->length <= region->end) {
other =
lookup_overlapping_address_handler(&address_handler_list,
handler->offset,
handler->length);
if (other != NULL) {
- handler->offset += other->length;
+ handler->offset =
+ roundup(other->offset + other->length, 4);
} else {
list_add_tail(&handler->link, &address_handler_list);
ret = 0;
diff --git a/drivers/firmware/dcdbas.h b/drivers/firmware/dcdbas.h
index dcdba0f1b32c..87bc3417de27 100644
--- a/drivers/firmware/dcdbas.h
+++ b/drivers/firmware/dcdbas.h
@@ -17,7 +17,6 @@
#define _DCDBAS_H_
#include <linux/device.h>
-#include <linux/input.h>
#include <linux/sysfs.h>
#include <linux/types.h>
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index dd332f28e08c..0b27da7d7497 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -297,7 +297,7 @@ static struct hid_usage *hidinput_find_key(struct hid_device *hid,
static int hidinput_getkeycode(struct input_dev *dev, int scancode,
int *keycode)
{
- struct hid_device *hid = dev->private;
+ struct hid_device *hid = input_get_drvdata(dev);
struct hid_usage *usage;
usage = hidinput_find_key(hid, scancode, 0);
@@ -311,7 +311,7 @@ static int hidinput_getkeycode(struct input_dev *dev, int scancode,
static int hidinput_setkeycode(struct input_dev *dev, int scancode,
int keycode)
{
- struct hid_device *hid = dev->private;
+ struct hid_device *hid = input_get_drvdata(dev);
struct hid_usage *usage;
int old_keycode;
@@ -1152,7 +1152,7 @@ int hidinput_connect(struct hid_device *hid)
kfree(hidinput);
input_free_device(input_dev);
err_hid("Out of memory during hid input probe");
- return -1;
+ goto out_unwind;
}
input_set_drvdata(input_dev, hid);
@@ -1186,15 +1186,25 @@ int hidinput_connect(struct hid_device *hid)
* UGCI) cram a lot of unrelated inputs into the
* same interface. */
hidinput->report = report;
- input_register_device(hidinput->input);
+ if (input_register_device(hidinput->input))
+ goto out_cleanup;
hidinput = NULL;
}
}
- if (hidinput)
- input_register_device(hidinput->input);
+ if (hidinput && input_register_device(hidinput->input))
+ goto out_cleanup;
return 0;
+
+out_cleanup:
+ input_free_device(hidinput->input);
+ kfree(hidinput);
+out_unwind:
+ /* unwind the ones we already registered */
+ hidinput_disconnect(hid);
+
+ return -1;
}
EXPORT_SYMBOL_GPL(hidinput_connect);
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index a702e2f6da7d..1ca6f4635eeb 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -113,13 +113,13 @@ static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t
if (count > HID_MIN_BUFFER_SIZE) {
printk(KERN_WARNING "hidraw: pid %d passed too large report\n",
- current->pid);
+ task_pid_nr(current));
return -EINVAL;
}
if (count < 2) {
printk(KERN_WARNING "hidraw: pid %d passed too short report\n",
- current->pid);
+ task_pid_nr(current));
return -EINVAL;
}
diff --git a/drivers/hid/usbhid/hid-ff.c b/drivers/hid/usbhid/hid-ff.c
index 22329feb3b5a..4c210e16b1b4 100644
--- a/drivers/hid/usbhid/hid-ff.c
+++ b/drivers/hid/usbhid/hid-ff.c
@@ -1,6 +1,4 @@
/*
- * $Id: hid-ff.c,v 1.2 2002/04/18 22:02:47 jdeneux Exp $
- *
* Force feedback support for hid devices.
* Not all hid devices use the same protocol. For example, some use PID,
* other use their own proprietary procotol.
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 41a59a80e7ed..a2552856476b 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -129,6 +129,11 @@
#define USB_DEVICE_ID_0_8_8_IF_KIT 0x0053
#define USB_DEVICE_ID_PHIDGET_MOTORCONTROL 0x0058
+#define USB_VENDOR_ID_GOTOP 0x08f2
+#define USB_DEVICE_ID_SUPER_Q2 0x007f
+#define USB_DEVICE_ID_GOGOPEN 0x00ce
+#define USB_DEVICE_ID_PENPOWER 0x00f4
+
#define USB_VENDOR_ID_GRIFFIN 0x077d
#define USB_DEVICE_ID_POWERMATE 0x0410
#define USB_DEVICE_ID_SOUNDKNOB 0x04AA
@@ -415,6 +420,9 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_7_IF_KIT, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_8_IF_KIT, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_PHIDGET_MOTORCONTROL, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_SUPER_Q2, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_GOGOPEN, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_PENPOWER, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_90, HID_QUIRK_IGNORE },
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index 9837adcb17e9..5fc4019956ba 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -743,7 +743,7 @@ inval:
static long hiddev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct inode *inode = file->f_path.dentry->d_inode;
- return hiddev_ioctl(inode, file, cmd, compat_ptr(arg));
+ return hiddev_ioctl(inode, file, cmd, (unsigned long)compat_ptr(arg));
}
#endif
diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c
index b76b02f7b52d..775a1ef28a29 100644
--- a/drivers/hid/usbhid/usbkbd.c
+++ b/drivers/hid/usbhid/usbkbd.c
@@ -274,8 +274,11 @@ static int usb_kbd_probe(struct usb_interface *iface,
input_set_drvdata(input_dev, kbd);
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
- input_dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL) | BIT(LED_COMPOSE) | BIT(LED_KANA);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_LED) |
+ BIT_MASK(EV_REP);
+ input_dev->ledbit[0] = BIT_MASK(LED_NUML) | BIT_MASK(LED_CAPSL) |
+ BIT_MASK(LED_SCROLLL) | BIT_MASK(LED_COMPOSE) |
+ BIT_MASK(LED_KANA);
for (i = 0; i < 255; i++)
set_bit(usb_kbd_keycode[i], input_dev->keybit);
diff --git a/drivers/hid/usbhid/usbmouse.c b/drivers/hid/usbhid/usbmouse.c
index 5345c73bcf62..f8ad6910d3d9 100644
--- a/drivers/hid/usbhid/usbmouse.c
+++ b/drivers/hid/usbhid/usbmouse.c
@@ -173,11 +173,13 @@ static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_i
usb_to_input_id(dev, &input_dev->id);
input_dev->dev.parent = &intf->dev;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
- input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
- input_dev->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA);
- input_dev->relbit[0] |= BIT(REL_WHEEL);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+ input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
+ BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);
+ input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
+ input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_SIDE) |
+ BIT_MASK(BTN_EXTRA);
+ input_dev->relbit[0] |= BIT_MASK(REL_WHEEL);
input_set_drvdata(input_dev, mouse);
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index e47f88170806..a0445bea9f75 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -158,6 +158,7 @@ config SENSORS_K8TEMP
config SENSORS_AMS
tristate "Apple Motion Sensor driver"
depends on PPC_PMAC && !PPC64 && INPUT && ((ADB_PMU && I2C = y) || (ADB_PMU && !I2C) || I2C) && EXPERIMENTAL
+ select INPUT_POLLDEV
help
Support for the motion sensor included in PowerBooks. Includes
implementations for PMU and I2C.
@@ -215,6 +216,16 @@ config SENSORS_DS1621
This driver can also be built as a module. If so, the module
will be called ds1621.
+config SENSORS_I5K_AMB
+ tristate "FB-DIMM AMB temperature sensor on Intel 5000 series chipsets"
+ depends on PCI && EXPERIMENTAL
+ help
+ If you say yes here you get support for FB-DIMM AMB temperature
+ monitoring chips on systems with the Intel 5000 series chipset.
+
+ This driver can also be built as a module. If so, the module
+ will be called i5k_amb.
+
config SENSORS_F71805F
tristate "Fintek F71805F/FG, F71806F/FG and F71872F/FG"
depends on EXPERIMENTAL
@@ -701,6 +712,7 @@ config SENSORS_W83627EHF
config SENSORS_HDAPS
tristate "IBM Hard Drive Active Protection System (hdaps)"
depends on INPUT && X86
+ select INPUT_POLLDEV
default n
help
This driver provides support for the IBM Hard Drive Active Protection
@@ -722,6 +734,7 @@ config SENSORS_APPLESMC
depends on INPUT && X86
select NEW_LEDS
select LEDS_CLASS
+ select INPUT_POLLDEV
default n
help
This driver provides support for the Apple System Management
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 6da3eef94306..55595f6e1aa6 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o
obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o
obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o
obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o
+obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o
obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o
obj-$(CONFIG_SENSORS_IT87) += it87.o
obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o
diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c
index cb2331bfd9d5..d9f04ce90327 100644
--- a/drivers/hwmon/abituguru3.c
+++ b/drivers/hwmon/abituguru3.c
@@ -503,7 +503,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "AUX3 FAN", 36, 2, 60, 1, 0 },
{ NULL, 0, 0, 0, 0, 0 } }
},
- { 0x001A, "unknown", {
+ { 0x001A, "Abit IP35 Pro", {
{ "CPU Core", 0, 0, 10, 1, 0 },
{ "DDR2", 1, 0, 20, 1, 0 },
{ "DDR2 VTT", 2, 0, 10, 1, 0 },
@@ -530,6 +530,60 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "AUX3 Fan", 36, 2, 60, 1, 0 },
{ NULL, 0, 0, 0, 0, 0 } }
},
+ { 0x001B, "unknown", {
+ { "CPU Core", 0, 0, 10, 1, 0 },
+ { "DDR3", 1, 0, 20, 1, 0 },
+ { "DDR3 VTT", 2, 0, 10, 1, 0 },
+ { "CPU VTT", 3, 0, 10, 1, 0 },
+ { "MCH 1.25V", 4, 0, 10, 1, 0 },
+ { "ICHIO 1.5V", 5, 0, 10, 1, 0 },
+ { "ICH 1.05V", 6, 0, 10, 1, 0 },
+ { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
+ { "ATX +12V (8-pin)", 8, 0, 60, 1, 0 },
+ { "ATX +5V", 9, 0, 30, 1, 0 },
+ { "+3.3V", 10, 0, 20, 1, 0 },
+ { "5VSB", 11, 0, 30, 1, 0 },
+ { "CPU", 24, 1, 1, 1, 0 },
+ { "System", 25, 1, 1, 1, 0 },
+ { "PWM Phase1", 26, 1, 1, 1, 0 },
+ { "PWM Phase2", 27, 1, 1, 1, 0 },
+ { "PWM Phase3", 28, 1, 1, 1, 0 },
+ { "PWM Phase4", 29, 1, 1, 1, 0 },
+ { "PWM Phase5", 30, 1, 1, 1, 0 },
+ { "CPU Fan", 32, 2, 60, 1, 0 },
+ { "SYS Fan", 34, 2, 60, 1, 0 },
+ { "AUX1 Fan", 33, 2, 60, 1, 0 },
+ { "AUX2 Fan", 35, 2, 60, 1, 0 },
+ { "AUX3 Fan", 36, 2, 60, 1, 0 },
+ { NULL, 0, 0, 0, 0, 0 } }
+ },
+ { 0x001C, "unknown", {
+ { "CPU Core", 0, 0, 10, 1, 0 },
+ { "DDR2", 1, 0, 20, 1, 0 },
+ { "DDR2 VTT", 2, 0, 10, 1, 0 },
+ { "CPU VTT", 3, 0, 10, 1, 0 },
+ { "MCH 1.25V", 4, 0, 10, 1, 0 },
+ { "ICHIO 1.5V", 5, 0, 10, 1, 0 },
+ { "ICH 1.05V", 6, 0, 10, 1, 0 },
+ { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
+ { "ATX +12V (8-pin)", 8, 0, 60, 1, 0 },
+ { "ATX +5V", 9, 0, 30, 1, 0 },
+ { "+3.3V", 10, 0, 20, 1, 0 },
+ { "5VSB", 11, 0, 30, 1, 0 },
+ { "CPU", 24, 1, 1, 1, 0 },
+ { "System", 25, 1, 1, 1, 0 },
+ { "PWM Phase1", 26, 1, 1, 1, 0 },
+ { "PWM Phase2", 27, 1, 1, 1, 0 },
+ { "PWM Phase3", 28, 1, 1, 1, 0 },
+ { "PWM Phase4", 29, 1, 1, 1, 0 },
+ { "PWM Phase5", 30, 1, 1, 1, 0 },
+ { "CPU Fan", 32, 2, 60, 1, 0 },
+ { "SYS Fan", 34, 2, 60, 1, 0 },
+ { "AUX1 Fan", 33, 2, 60, 1, 0 },
+ { "AUX2 Fan", 35, 2, 60, 1, 0 },
+ { "AUX3 Fan", 36, 2, 60, 1, 0 },
+ { NULL, 0, 0, 0, 0, 0 } }
+ },
{ 0x0000, NULL, { { NULL, 0, 0, 0, 0, 0 } } }
};
diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c
index aa875ca50d9b..3e63c1486770 100644
--- a/drivers/hwmon/adm1026.c
+++ b/drivers/hwmon/adm1026.c
@@ -1651,7 +1651,7 @@ static int adm1026_detect(struct i2c_adapter *adapter, int address,
break;
default :
dev_err(&adapter->dev, ": Internal error, invalid "
- "kind (%d)!", kind);
+ "kind (%d)!\n", kind);
err = -EFAULT;
goto exitfree;
}
diff --git a/drivers/hwmon/ams/ams-input.c b/drivers/hwmon/ams/ams-input.c
index ca7095d96ad0..7b81e0c2c2d9 100644
--- a/drivers/hwmon/ams/ams-input.c
+++ b/drivers/hwmon/ams/ams-input.c
@@ -27,47 +27,32 @@ static unsigned int invert;
module_param(invert, bool, 0644);
MODULE_PARM_DESC(invert, "Invert input data on X and Y axis");
-static int ams_input_kthread(void *data)
+static void ams_idev_poll(struct input_polled_dev *dev)
{
+ struct input_dev *idev = dev->input;
s8 x, y, z;
- while (!kthread_should_stop()) {
- mutex_lock(&ams_info.lock);
-
- ams_sensors(&x, &y, &z);
-
- x -= ams_info.xcalib;
- y -= ams_info.ycalib;
- z -= ams_info.zcalib;
-
- input_report_abs(ams_info.idev, ABS_X, invert ? -x : x);
- input_report_abs(ams_info.idev, ABS_Y, invert ? -y : y);
- input_report_abs(ams_info.idev, ABS_Z, z);
+ mutex_lock(&ams_info.lock);
- input_sync(ams_info.idev);
+ ams_sensors(&x, &y, &z);
- mutex_unlock(&ams_info.lock);
+ x -= ams_info.xcalib;
+ y -= ams_info.ycalib;
+ z -= ams_info.zcalib;
- msleep(25);
- }
+ input_report_abs(idev, ABS_X, invert ? -x : x);
+ input_report_abs(idev, ABS_Y, invert ? -y : y);
+ input_report_abs(idev, ABS_Z, z);
- return 0;
-}
+ input_sync(idev);
-static int ams_input_open(struct input_dev *dev)
-{
- ams_info.kthread = kthread_run(ams_input_kthread, NULL, "kams");
- return IS_ERR(ams_info.kthread) ? PTR_ERR(ams_info.kthread) : 0;
-}
-
-static void ams_input_close(struct input_dev *dev)
-{
- kthread_stop(ams_info.kthread);
+ mutex_unlock(&ams_info.lock);
}
/* Call with ams_info.lock held! */
static void ams_input_enable(void)
{
+ struct input_dev *input;
s8 x, y, z;
if (ams_info.idev)
@@ -78,27 +63,29 @@ static void ams_input_enable(void)
ams_info.ycalib = y;
ams_info.zcalib = z;
- ams_info.idev = input_allocate_device();
+ ams_info.idev = input_allocate_polled_device();
if (!ams_info.idev)
return;
- ams_info.idev->name = "Apple Motion Sensor";
- ams_info.idev->id.bustype = ams_info.bustype;
- ams_info.idev->id.vendor = 0;
- ams_info.idev->open = ams_input_open;
- ams_info.idev->close = ams_input_close;
- ams_info.idev->dev.parent = &ams_info.of_dev->dev;
+ ams_info.idev->poll = ams_idev_poll;
+ ams_info.idev->poll_interval = 25;
+
+ input = ams_info.idev->input;
+ input->name = "Apple Motion Sensor";
+ input->id.bustype = ams_info.bustype;
+ input->id.vendor = 0;
+ input->dev.parent = &ams_info.of_dev->dev;
- input_set_abs_params(ams_info.idev, ABS_X, -50, 50, 3, 0);
- input_set_abs_params(ams_info.idev, ABS_Y, -50, 50, 3, 0);
- input_set_abs_params(ams_info.idev, ABS_Z, -50, 50, 3, 0);
+ input_set_abs_params(input, ABS_X, -50, 50, 3, 0);
+ input_set_abs_params(input, ABS_Y, -50, 50, 3, 0);
+ input_set_abs_params(input, ABS_Z, -50, 50, 3, 0);
- set_bit(EV_ABS, ams_info.idev->evbit);
- set_bit(EV_KEY, ams_info.idev->evbit);
- set_bit(BTN_TOUCH, ams_info.idev->keybit);
+ set_bit(EV_ABS, input->evbit);
+ set_bit(EV_KEY, input->evbit);
+ set_bit(BTN_TOUCH, input->keybit);
- if (input_register_device(ams_info.idev)) {
- input_free_device(ams_info.idev);
+ if (input_register_polled_device(ams_info.idev)) {
+ input_free_polled_device(ams_info.idev);
ams_info.idev = NULL;
return;
}
@@ -108,7 +95,8 @@ static void ams_input_enable(void)
static void ams_input_disable(void)
{
if (ams_info.idev) {
- input_unregister_device(ams_info.idev);
+ input_unregister_polled_device(ams_info.idev);
+ input_free_polled_device(ams_info.idev);
ams_info.idev = NULL;
}
}
diff --git a/drivers/hwmon/ams/ams.h b/drivers/hwmon/ams/ams.h
index 240730e6bcde..a6221e5dd984 100644
--- a/drivers/hwmon/ams/ams.h
+++ b/drivers/hwmon/ams/ams.h
@@ -1,5 +1,5 @@
#include <linux/i2c.h>
-#include <linux/input.h>
+#include <linux/input-polldev.h>
#include <linux/kthread.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
@@ -52,8 +52,7 @@ struct ams {
#endif
/* Joystick emulation */
- struct task_struct *kthread;
- struct input_dev *idev;
+ struct input_polled_dev *idev;
__u16 bustype;
/* calibrated null values */
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index f37fd7ebf65a..86c66c345f8b 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -28,7 +28,7 @@
#include <linux/delay.h>
#include <linux/platform_device.h>
-#include <linux/input.h>
+#include <linux/input-polldev.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/timer.h>
@@ -59,9 +59,9 @@
#define LIGHT_SENSOR_LEFT_KEY "ALV0" /* r-o {alv (6 bytes) */
#define LIGHT_SENSOR_RIGHT_KEY "ALV1" /* r-o {alv (6 bytes) */
-#define BACKLIGHT_KEY "LKSB" /* w-o {lkb (2 bytes) */
+#define BACKLIGHT_KEY "LKSB" /* w-o {lkb (2 bytes) */
-#define CLAMSHELL_KEY "MSLD" /* r-o ui8 (unused) */
+#define CLAMSHELL_KEY "MSLD" /* r-o ui8 (unused) */
#define MOTION_SENSOR_X_KEY "MO_X" /* r-o sp78 (2 bytes) */
#define MOTION_SENSOR_Y_KEY "MO_Y" /* r-o sp78 (2 bytes) */
@@ -80,7 +80,7 @@
/*
* Temperature sensors keys (sp78 - 2 bytes).
*/
-static const char* temperature_sensors_sets[][13] = {
+static const char* temperature_sensors_sets[][36] = {
/* Set 0: Macbook Pro */
{ "TA0P", "TB0T", "TC0D", "TC0P", "TG0H", "TG0P", "TG0T", "Th0H",
"Th1H", "Tm0P", "Ts0P", "Ts1P", NULL },
@@ -88,7 +88,13 @@ static const char* temperature_sensors_sets[][13] = {
{ "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TN1P", "Th0H", "Th0S",
"Th1H", "Ts0P", NULL },
/* Set 2: Macmini set */
- { "TC0D", "TC0P", NULL }
+ { "TC0D", "TC0P", NULL },
+/* Set 3: Mac Pro (2 x Quad-Core) */
+ { "TA0P", "TCAG", "TCAH", "TCBG", "TCBH", "TC0C", "TC0D", "TC0P",
+ "TC1C", "TC1D", "TC2C", "TC2D", "TC3C", "TC3D", "THTG", "TH0P",
+ "TH1P", "TH2P", "TH3P", "TMAP", "TMAS", "TMBS", "TM0P", "TM0S",
+ "TM1P", "TM1S", "TM2P", "TM2S", "TM3S", "TM8P", "TM8S", "TM9P",
+ "TM9S", "TN0H", "TS0C", NULL },
};
/* List of keys used to read/write fan speeds */
@@ -103,7 +109,7 @@ static const char* fan_speed_keys[] = {
#define INIT_TIMEOUT_MSECS 5000 /* wait up to 5s for device init ... */
#define INIT_WAIT_MSECS 50 /* ... in 50ms increments */
-#define APPLESMC_POLL_PERIOD (HZ/20) /* poll for input every 1/20s */
+#define APPLESMC_POLL_INTERVAL 50 /* msecs */
#define APPLESMC_INPUT_FUZZ 4 /* input event threshold */
#define APPLESMC_INPUT_FLAT 4
@@ -125,9 +131,8 @@ static const int debug;
static struct platform_device *pdev;
static s16 rest_x;
static s16 rest_y;
-static struct timer_list applesmc_timer;
-static struct input_dev *applesmc_idev;
static struct device *hwmon_dev;
+static struct input_polled_dev *applesmc_idev;
/* Indicates whether this computer has an accelerometer. */
static unsigned int applesmc_accelerometer;
@@ -138,7 +143,7 @@ static unsigned int applesmc_light;
/* Indicates which temperature sensors set to use. */
static unsigned int applesmc_temperature_set;
-static struct mutex applesmc_lock;
+static DEFINE_MUTEX(applesmc_lock);
/*
* Last index written to key_at_index sysfs file, and value to use for all other
@@ -455,27 +460,12 @@ static void applesmc_calibrate(void)
rest_x = -rest_x;
}
-static int applesmc_idev_open(struct input_dev *dev)
-{
- add_timer(&applesmc_timer);
-
- return 0;
-}
-
-static void applesmc_idev_close(struct input_dev *dev)
-{
- del_timer_sync(&applesmc_timer);
-}
-
-static void applesmc_idev_poll(unsigned long unused)
+static void applesmc_idev_poll(struct input_polled_dev *dev)
{
+ struct input_dev *idev = dev->input;
s16 x, y;
- /* Cannot sleep. Try nonblockingly. If we fail, try again later. */
- if (!mutex_trylock(&applesmc_lock)) {
- mod_timer(&applesmc_timer, jiffies + APPLESMC_POLL_PERIOD);
- return;
- }
+ mutex_lock(&applesmc_lock);
if (applesmc_read_motion_sensor(SENSOR_X, &x))
goto out;
@@ -483,13 +473,11 @@ static void applesmc_idev_poll(unsigned long unused)
goto out;
x = -x;
- input_report_abs(applesmc_idev, ABS_X, x - rest_x);
- input_report_abs(applesmc_idev, ABS_Y, y - rest_y);
- input_sync(applesmc_idev);
+ input_report_abs(idev, ABS_X, x - rest_x);
+ input_report_abs(idev, ABS_Y, y - rest_y);
+ input_sync(idev);
out:
- mod_timer(&applesmc_timer, jiffies + APPLESMC_POLL_PERIOD);
-
mutex_unlock(&applesmc_lock);
}
@@ -821,8 +809,7 @@ static ssize_t applesmc_key_at_index_read_show(struct device *dev,
if (!ret) {
return info[0];
- }
- else {
+ } else {
return ret;
}
}
@@ -1009,14 +996,18 @@ static struct attribute *fan##offset##_attributes[] = { \
/*
* Create the needed functions for each fan using the macro defined above
- * (2 fans are supported)
+ * (4 fans are supported)
*/
sysfs_fan_speeds_offset(1);
sysfs_fan_speeds_offset(2);
+sysfs_fan_speeds_offset(3);
+sysfs_fan_speeds_offset(4);
static const struct attribute_group fan_attribute_groups[] = {
{ .attrs = fan1_attributes },
- { .attrs = fan2_attributes }
+ { .attrs = fan2_attributes },
+ { .attrs = fan3_attributes },
+ { .attrs = fan4_attributes },
};
/*
@@ -1046,6 +1037,52 @@ static SENSOR_DEVICE_ATTR(temp11_input, S_IRUGO,
applesmc_show_temperature, NULL, 10);
static SENSOR_DEVICE_ATTR(temp12_input, S_IRUGO,
applesmc_show_temperature, NULL, 11);
+static SENSOR_DEVICE_ATTR(temp13_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 12);
+static SENSOR_DEVICE_ATTR(temp14_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 13);
+static SENSOR_DEVICE_ATTR(temp15_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 14);
+static SENSOR_DEVICE_ATTR(temp16_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 15);
+static SENSOR_DEVICE_ATTR(temp17_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 16);
+static SENSOR_DEVICE_ATTR(temp18_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 17);
+static SENSOR_DEVICE_ATTR(temp19_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 18);
+static SENSOR_DEVICE_ATTR(temp20_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 19);
+static SENSOR_DEVICE_ATTR(temp21_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 20);
+static SENSOR_DEVICE_ATTR(temp22_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 21);
+static SENSOR_DEVICE_ATTR(temp23_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 22);
+static SENSOR_DEVICE_ATTR(temp24_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 23);
+static SENSOR_DEVICE_ATTR(temp25_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 24);
+static SENSOR_DEVICE_ATTR(temp26_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 25);
+static SENSOR_DEVICE_ATTR(temp27_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 26);
+static SENSOR_DEVICE_ATTR(temp28_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 27);
+static SENSOR_DEVICE_ATTR(temp29_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 28);
+static SENSOR_DEVICE_ATTR(temp30_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 29);
+static SENSOR_DEVICE_ATTR(temp31_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 30);
+static SENSOR_DEVICE_ATTR(temp32_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 31);
+static SENSOR_DEVICE_ATTR(temp33_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 32);
+static SENSOR_DEVICE_ATTR(temp34_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 33);
+static SENSOR_DEVICE_ATTR(temp35_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 34);
static struct attribute *temperature_attributes[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
@@ -1060,6 +1097,29 @@ static struct attribute *temperature_attributes[] = {
&sensor_dev_attr_temp10_input.dev_attr.attr,
&sensor_dev_attr_temp11_input.dev_attr.attr,
&sensor_dev_attr_temp12_input.dev_attr.attr,
+ &sensor_dev_attr_temp13_input.dev_attr.attr,
+ &sensor_dev_attr_temp14_input.dev_attr.attr,
+ &sensor_dev_attr_temp15_input.dev_attr.attr,
+ &sensor_dev_attr_temp16_input.dev_attr.attr,
+ &sensor_dev_attr_temp17_input.dev_attr.attr,
+ &sensor_dev_attr_temp18_input.dev_attr.attr,
+ &sensor_dev_attr_temp19_input.dev_attr.attr,
+ &sensor_dev_attr_temp20_input.dev_attr.attr,
+ &sensor_dev_attr_temp21_input.dev_attr.attr,
+ &sensor_dev_attr_temp22_input.dev_attr.attr,
+ &sensor_dev_attr_temp23_input.dev_attr.attr,
+ &sensor_dev_attr_temp24_input.dev_attr.attr,
+ &sensor_dev_attr_temp25_input.dev_attr.attr,
+ &sensor_dev_attr_temp26_input.dev_attr.attr,
+ &sensor_dev_attr_temp27_input.dev_attr.attr,
+ &sensor_dev_attr_temp28_input.dev_attr.attr,
+ &sensor_dev_attr_temp29_input.dev_attr.attr,
+ &sensor_dev_attr_temp30_input.dev_attr.attr,
+ &sensor_dev_attr_temp31_input.dev_attr.attr,
+ &sensor_dev_attr_temp32_input.dev_attr.attr,
+ &sensor_dev_attr_temp33_input.dev_attr.attr,
+ &sensor_dev_attr_temp34_input.dev_attr.attr,
+ &sensor_dev_attr_temp35_input.dev_attr.attr,
NULL
};
@@ -1093,6 +1153,7 @@ static int applesmc_dmi_match(const struct dmi_system_id *id)
/* Create accelerometer ressources */
static int applesmc_create_accelerometer(void)
{
+ struct input_dev *idev;
int ret;
ret = sysfs_create_group(&pdev->dev.kobj,
@@ -1100,40 +1161,37 @@ static int applesmc_create_accelerometer(void)
if (ret)
goto out;
- applesmc_idev = input_allocate_device();
+ applesmc_idev = input_allocate_polled_device();
if (!applesmc_idev) {
ret = -ENOMEM;
goto out_sysfs;
}
+ applesmc_idev->poll = applesmc_idev_poll;
+ applesmc_idev->poll_interval = APPLESMC_POLL_INTERVAL;
+
/* initial calibrate for the input device */
applesmc_calibrate();
- /* initialize the input class */
- applesmc_idev->name = "applesmc";
- applesmc_idev->id.bustype = BUS_HOST;
- applesmc_idev->dev.parent = &pdev->dev;
- applesmc_idev->evbit[0] = BIT(EV_ABS);
- applesmc_idev->open = applesmc_idev_open;
- applesmc_idev->close = applesmc_idev_close;
- input_set_abs_params(applesmc_idev, ABS_X,
+ /* initialize the input device */
+ idev = applesmc_idev->input;
+ idev->name = "applesmc";
+ idev->id.bustype = BUS_HOST;
+ idev->dev.parent = &pdev->dev;
+ idev->evbit[0] = BIT_MASK(EV_ABS);
+ input_set_abs_params(idev, ABS_X,
-256, 256, APPLESMC_INPUT_FUZZ, APPLESMC_INPUT_FLAT);
- input_set_abs_params(applesmc_idev, ABS_Y,
+ input_set_abs_params(idev, ABS_Y,
-256, 256, APPLESMC_INPUT_FUZZ, APPLESMC_INPUT_FLAT);
- ret = input_register_device(applesmc_idev);
+ ret = input_register_polled_device(applesmc_idev);
if (ret)
goto out_idev;
- /* start up our timer for the input device */
- init_timer(&applesmc_timer);
- applesmc_timer.function = applesmc_idev_poll;
- applesmc_timer.expires = jiffies + APPLESMC_POLL_PERIOD;
-
return 0;
out_idev:
- input_free_device(applesmc_idev);
+ input_free_polled_device(applesmc_idev);
out_sysfs:
sysfs_remove_group(&pdev->dev.kobj, &accelerometer_attributes_group);
@@ -1146,8 +1204,8 @@ out:
/* Release all ressources used by the accelerometer */
static void applesmc_release_accelerometer(void)
{
- del_timer_sync(&applesmc_timer);
- input_unregister_device(applesmc_idev);
+ input_unregister_polled_device(applesmc_idev);
+ input_free_polled_device(applesmc_idev);
sysfs_remove_group(&pdev->dev.kobj, &accelerometer_attributes_group);
}
@@ -1158,6 +1216,8 @@ static __initdata struct dmi_match_data applesmc_dmi_data[] = {
{ .accelerometer = 1, .light = 0, .temperature_set = 1 },
/* MacMini: temperature set 2 */
{ .accelerometer = 0, .light = 0, .temperature_set = 2 },
+/* MacPro: temperature set 3 */
+ { .accelerometer = 0, .light = 0, .temperature_set = 3 },
};
/* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1".
@@ -1175,6 +1235,10 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = {
DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
DMI_MATCH(DMI_PRODUCT_NAME,"Macmini") },
(void*)&applesmc_dmi_data[2]},
+ { applesmc_dmi_match, "Apple MacPro2", {
+ DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
+ DMI_MATCH(DMI_PRODUCT_NAME,"MacPro2") },
+ (void*)&applesmc_dmi_data[3]},
{ .ident = NULL }
};
@@ -1184,8 +1248,6 @@ static int __init applesmc_init(void)
int count;
int i;
- mutex_init(&applesmc_lock);
-
if (!dmi_check_system(applesmc_whitelist)) {
printk(KERN_WARNING "applesmc: supported laptop not found!\n");
ret = -ENODEV;
@@ -1227,9 +1289,19 @@ static int __init applesmc_init(void)
switch (count) {
default:
- printk(KERN_WARNING "applesmc: More than 2 fans found,"
- " but at most 2 fans are supported"
+ printk(KERN_WARNING "applesmc: More than 4 fans found,"
+ " but at most 4 fans are supported"
" by the driver.\n");
+ case 4:
+ ret = sysfs_create_group(&pdev->dev.kobj,
+ &fan_attribute_groups[3]);
+ if (ret)
+ goto out_key_enumeration;
+ case 3:
+ ret = sysfs_create_group(&pdev->dev.kobj,
+ &fan_attribute_groups[2]);
+ if (ret)
+ goto out_key_enumeration;
case 2:
ret = sysfs_create_group(&pdev->dev.kobj,
&fan_attribute_groups[1]);
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index 6f66551d9e51..5c82ec7f8bbd 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -150,7 +150,7 @@ static struct coretemp_data *coretemp_update_device(struct device *dev)
static int __devinit coretemp_probe(struct platform_device *pdev)
{
struct coretemp_data *data;
- struct cpuinfo_x86 *c = &(cpu_data)[pdev->id];
+ struct cpuinfo_x86 *c = &cpu_data(pdev->id);
int err;
u32 eax, edx;
@@ -359,7 +359,7 @@ static int __init coretemp_init(void)
struct pdev_entry *p, *n;
/* quick check if we run Intel */
- if (cpu_data[0].x86_vendor != X86_VENDOR_INTEL)
+ if (cpu_data(0).x86_vendor != X86_VENDOR_INTEL)
goto exit;
err = platform_driver_register(&coretemp_driver);
@@ -367,7 +367,7 @@ static int __init coretemp_init(void)
goto exit;
for_each_online_cpu(i) {
- struct cpuinfo_x86 *c = &(cpu_data)[i];
+ struct cpuinfo_x86 *c = &cpu_data(i);
/* check if family 6, models e, f, 16 */
if ((c->cpuid_level < 0) || (c->x86 != 0x6) ||
diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c
index 13a041326a04..6892f76fc18a 100644
--- a/drivers/hwmon/f75375s.c
+++ b/drivers/hwmon/f75375s.c
@@ -34,6 +34,7 @@
#include <linux/i2c.h>
#include <linux/err.h>
#include <linux/mutex.h>
+#include <linux/f75375s.h>
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x2d, 0x2e, I2C_CLIENT_END };
@@ -86,7 +87,7 @@ I2C_CLIENT_INSMOD_2(f75373, f75375);
struct f75375_data {
unsigned short addr;
- struct i2c_client client;
+ struct i2c_client *client;
struct device *hwmon_dev;
const char *name;
@@ -116,15 +117,25 @@ struct f75375_data {
static int f75375_attach_adapter(struct i2c_adapter *adapter);
static int f75375_detect(struct i2c_adapter *adapter, int address, int kind);
static int f75375_detach_client(struct i2c_client *client);
+static int f75375_probe(struct i2c_client *client);
+static int f75375_remove(struct i2c_client *client);
-static struct i2c_driver f75375_driver = {
+static struct i2c_driver f75375_legacy_driver = {
.driver = {
- .name = "f75375",
+ .name = "f75375_legacy",
},
.attach_adapter = f75375_attach_adapter,
.detach_client = f75375_detach_client,
};
+static struct i2c_driver f75375_driver = {
+ .driver = {
+ .name = "f75375",
+ },
+ .probe = f75375_probe,
+ .remove = f75375_remove,
+};
+
static inline int f75375_read8(struct i2c_client *client, u8 reg)
{
return i2c_smbus_read_byte_data(client, reg);
@@ -276,19 +287,14 @@ static ssize_t show_pwm_enable(struct device *dev, struct device_attribute
return sprintf(buf, "%d\n", data->pwm_enable[nr]);
}
-static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static int set_pwm_enable_direct(struct i2c_client *client, int nr, int val)
{
- int nr = to_sensor_dev_attr(attr)->index;
- struct i2c_client *client = to_i2c_client(dev);
struct f75375_data *data = i2c_get_clientdata(client);
- int val = simple_strtoul(buf, NULL, 10);
u8 fanmode;
if (val < 0 || val > 4)
return -EINVAL;
- mutex_lock(&data->update_lock);
fanmode = f75375_read8(client, F75375_REG_FAN_TIMER);
fanmode = ~(3 << FAN_CTRL_MODE(nr));
@@ -310,8 +316,22 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr,
}
f75375_write8(client, F75375_REG_FAN_TIMER, fanmode);
data->pwm_enable[nr] = val;
+ return 0;
+}
+
+static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int nr = to_sensor_dev_attr(attr)->index;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct f75375_data *data = i2c_get_clientdata(client);
+ int val = simple_strtoul(buf, NULL, 10);
+ int err = 0;
+
+ mutex_lock(&data->update_lock);
+ err = set_pwm_enable_direct(client, nr, val);
mutex_unlock(&data->update_lock);
- return count;
+ return err ? err : count;
}
static ssize_t set_pwm_mode(struct device *dev, struct device_attribute *attr,
@@ -323,7 +343,7 @@ static ssize_t set_pwm_mode(struct device *dev, struct device_attribute *attr,
int val = simple_strtoul(buf, NULL, 10);
u8 conf = 0;
- if (val != 0 || val != 1 || data->kind == f75373)
+ if (!(val == 0 || val == 1))
return -EINVAL;
mutex_lock(&data->update_lock);
@@ -529,13 +549,13 @@ static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO|S_IWUSR,
show_pwm, set_pwm, 0);
static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO|S_IWUSR,
show_pwm_enable, set_pwm_enable, 0);
-static SENSOR_DEVICE_ATTR(pwm1_mode, S_IRUGO|S_IWUSR,
+static SENSOR_DEVICE_ATTR(pwm1_mode, S_IRUGO,
show_pwm_mode, set_pwm_mode, 0);
static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR,
show_pwm, set_pwm, 1);
static SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO|S_IWUSR,
show_pwm_enable, set_pwm_enable, 1);
-static SENSOR_DEVICE_ATTR(pwm2_mode, S_IRUGO|S_IWUSR,
+static SENSOR_DEVICE_ATTR(pwm2_mode, S_IRUGO,
show_pwm_mode, set_pwm_mode, 1);
static struct attribute *f75375_attributes[] = {
@@ -580,12 +600,9 @@ static const struct attribute_group f75375_group = {
static int f75375_detach_client(struct i2c_client *client)
{
- struct f75375_data *data = i2c_get_clientdata(client);
int err;
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &f75375_group);
-
+ f75375_remove(client);
err = i2c_detach_client(client);
if (err) {
dev_err(&client->dev,
@@ -593,7 +610,91 @@ static int f75375_detach_client(struct i2c_client *client)
"client not detached.\n");
return err;
}
+ kfree(client);
+ return 0;
+}
+
+static void f75375_init(struct i2c_client *client, struct f75375_data *data,
+ struct f75375s_platform_data *f75375s_pdata)
+{
+ int nr;
+ set_pwm_enable_direct(client, 0, f75375s_pdata->pwm_enable[0]);
+ set_pwm_enable_direct(client, 1, f75375s_pdata->pwm_enable[1]);
+ for (nr = 0; nr < 2; nr++) {
+ data->pwm[nr] = SENSORS_LIMIT(f75375s_pdata->pwm[nr], 0, 255);
+ f75375_write8(client, F75375_REG_FAN_PWM_DUTY(nr),
+ data->pwm[nr]);
+ }
+
+}
+
+static int f75375_probe(struct i2c_client *client)
+{
+ struct f75375_data *data = i2c_get_clientdata(client);
+ struct f75375s_platform_data *f75375s_pdata = client->dev.platform_data;
+ int err;
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_BYTE_DATA))
+ return -EIO;
+ if (!(data = kzalloc(sizeof(struct f75375_data), GFP_KERNEL)))
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, data);
+ data->client = client;
+ mutex_init(&data->update_lock);
+
+ if (strcmp(client->name, "f75375") == 0)
+ data->kind = f75375;
+ else if (strcmp(client->name, "f75373") == 0)
+ data->kind = f75373;
+ else {
+ dev_err(&client->dev, "Unsupported device: %s\n", client->name);
+ return -ENODEV;
+ }
+
+ if ((err = sysfs_create_group(&client->dev.kobj, &f75375_group)))
+ goto exit_free;
+
+ if (data->kind == f75375) {
+ err = sysfs_chmod_file(&client->dev.kobj,
+ &sensor_dev_attr_pwm1_mode.dev_attr.attr,
+ S_IRUGO | S_IWUSR);
+ if (err)
+ goto exit_remove;
+ err = sysfs_chmod_file(&client->dev.kobj,
+ &sensor_dev_attr_pwm2_mode.dev_attr.attr,
+ S_IRUGO | S_IWUSR);
+ if (err)
+ goto exit_remove;
+ }
+
+ data->hwmon_dev = hwmon_device_register(&client->dev);
+ if (IS_ERR(data->hwmon_dev)) {
+ err = PTR_ERR(data->hwmon_dev);
+ goto exit_remove;
+ }
+
+ if (f75375s_pdata != NULL)
+ f75375_init(client, data, f75375s_pdata);
+
+ return 0;
+
+exit_remove:
+ sysfs_remove_group(&client->dev.kobj, &f75375_group);
+exit_free:
kfree(data);
+ i2c_set_clientdata(client, NULL);
+ return err;
+}
+
+static int f75375_remove(struct i2c_client *client)
+{
+ struct f75375_data *data = i2c_get_clientdata(client);
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&client->dev.kobj, &f75375_group);
+ kfree(data);
+ i2c_set_clientdata(client, NULL);
return 0;
}
@@ -608,20 +709,17 @@ static int f75375_attach_adapter(struct i2c_adapter *adapter)
static int f75375_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *client;
- struct f75375_data *data;
u8 version = 0;
int err = 0;
const char *name = "";
- if (!(data = kzalloc(sizeof(struct f75375_data), GFP_KERNEL))) {
+ if (!(client = kzalloc(sizeof(*client), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- client = &data->client;
- i2c_set_clientdata(client, data);
client->addr = address;
client->adapter = adapter;
- client->driver = &f75375_driver;
+ client->driver = &f75375_legacy_driver;
if (kind < 0) {
u16 vendid = f75375_read16(client, F75375_REG_VENDOR);
@@ -644,42 +742,42 @@ static int f75375_detect(struct i2c_adapter *adapter, int address, int kind)
} else if (kind == f75373) {
name = "f75373";
}
-
dev_info(&adapter->dev, "found %s version: %02X\n", name, version);
strlcpy(client->name, name, I2C_NAME_SIZE);
- data->kind = kind;
- mutex_init(&data->update_lock);
+
if ((err = i2c_attach_client(client)))
goto exit_free;
- if ((err = sysfs_create_group(&client->dev.kobj, &f75375_group)))
+ if ((err = f75375_probe(client)) < 0)
goto exit_detach;
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove;
- }
-
return 0;
-exit_remove:
- sysfs_remove_group(&client->dev.kobj, &f75375_group);
exit_detach:
i2c_detach_client(client);
exit_free:
- kfree(data);
+ kfree(client);
exit:
return err;
}
static int __init sensors_f75375_init(void)
{
- return i2c_add_driver(&f75375_driver);
+ int status;
+ status = i2c_add_driver(&f75375_driver);
+ if (status)
+ return status;
+
+ status = i2c_add_driver(&f75375_legacy_driver);
+ if (status)
+ i2c_del_driver(&f75375_driver);
+
+ return status;
}
static void __exit sensors_f75375_exit(void)
{
+ i2c_del_driver(&f75375_legacy_driver);
i2c_del_driver(&f75375_driver);
}
diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c
index a3b56c816e11..2d39d8fc2389 100644
--- a/drivers/hwmon/gl520sm.c
+++ b/drivers/hwmon/gl520sm.c
@@ -2,7 +2,7 @@
gl520sm.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>,
- Kyösti Mälkki <kmalkki@cc.hut.fi>
+ Kyösti Mälkki <kmalkki@cc.hut.fi>
Copyright (c) 2005 Maarten Deprez <maartendeprez@users.sourceforge.net>
This program is free software; you can redistribute it and/or modify
@@ -805,7 +805,7 @@ static void __exit sensors_gl520sm_exit(void)
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
- "Kyösti Mälkki <kmalkki@cc.hut.fi>, "
+ "Kyösti Mälkki <kmalkki@cc.hut.fi>, "
"Maarten Deprez <maartendeprez@users.sourceforge.net>");
MODULE_DESCRIPTION("GL520SM driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c
index a7c6d407572b..bab5fd2e4dfd 100644
--- a/drivers/hwmon/hdaps.c
+++ b/drivers/hwmon/hdaps.c
@@ -28,7 +28,7 @@
#include <linux/delay.h>
#include <linux/platform_device.h>
-#include <linux/input.h>
+#include <linux/input-polldev.h>
#include <linux/kernel.h>
#include <linux/mutex.h>
#include <linux/module.h>
@@ -61,13 +61,12 @@
#define INIT_TIMEOUT_MSECS 4000 /* wait up to 4s for device init ... */
#define INIT_WAIT_MSECS 200 /* ... in 200ms increments */
-#define HDAPS_POLL_PERIOD (HZ/20) /* poll for input every 1/20s */
+#define HDAPS_POLL_INTERVAL 50 /* poll for input every 1/20s (50 ms)*/
#define HDAPS_INPUT_FUZZ 4 /* input event threshold */
#define HDAPS_INPUT_FLAT 4
-static struct timer_list hdaps_timer;
static struct platform_device *pdev;
-static struct input_dev *hdaps_idev;
+static struct input_polled_dev *hdaps_idev;
static unsigned int hdaps_invert;
static u8 km_activity;
static int rest_x;
@@ -323,24 +322,19 @@ static void hdaps_calibrate(void)
__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &rest_x, &rest_y);
}
-static void hdaps_mousedev_poll(unsigned long unused)
+static void hdaps_mousedev_poll(struct input_polled_dev *dev)
{
+ struct input_dev *input_dev = dev->input;
int x, y;
- /* Cannot sleep. Try nonblockingly. If we fail, try again later. */
- if (mutex_trylock(&hdaps_mtx)) {
- mod_timer(&hdaps_timer,jiffies + HDAPS_POLL_PERIOD);
- return;
- }
+ mutex_lock(&hdaps_mtx);
if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y))
goto out;
- input_report_abs(hdaps_idev, ABS_X, x - rest_x);
- input_report_abs(hdaps_idev, ABS_Y, y - rest_y);
- input_sync(hdaps_idev);
-
- mod_timer(&hdaps_timer, jiffies + HDAPS_POLL_PERIOD);
+ input_report_abs(input_dev, ABS_X, x - rest_x);
+ input_report_abs(input_dev, ABS_Y, y - rest_y);
+ input_sync(input_dev);
out:
mutex_unlock(&hdaps_mtx);
@@ -536,6 +530,7 @@ static struct dmi_system_id __initdata hdaps_whitelist[] = {
static int __init hdaps_init(void)
{
+ struct input_dev *idev;
int ret;
if (!dmi_check_system(hdaps_whitelist)) {
@@ -563,39 +558,37 @@ static int __init hdaps_init(void)
if (ret)
goto out_device;
- hdaps_idev = input_allocate_device();
+ hdaps_idev = input_allocate_polled_device();
if (!hdaps_idev) {
ret = -ENOMEM;
goto out_group;
}
+ hdaps_idev->poll = hdaps_mousedev_poll;
+ hdaps_idev->poll_interval = HDAPS_POLL_INTERVAL;
+
/* initial calibrate for the input device */
hdaps_calibrate();
/* initialize the input class */
- hdaps_idev->name = "hdaps";
- hdaps_idev->dev.parent = &pdev->dev;
- hdaps_idev->evbit[0] = BIT(EV_ABS);
- input_set_abs_params(hdaps_idev, ABS_X,
+ idev = hdaps_idev->input;
+ idev->name = "hdaps";
+ idev->dev.parent = &pdev->dev;
+ idev->evbit[0] = BIT_MASK(EV_ABS);
+ input_set_abs_params(idev, ABS_X,
-256, 256, HDAPS_INPUT_FUZZ, HDAPS_INPUT_FLAT);
- input_set_abs_params(hdaps_idev, ABS_Y,
+ input_set_abs_params(idev, ABS_Y,
-256, 256, HDAPS_INPUT_FUZZ, HDAPS_INPUT_FLAT);
- ret = input_register_device(hdaps_idev);
+ ret = input_register_polled_device(hdaps_idev);
if (ret)
goto out_idev;
- /* start up our timer for the input device */
- init_timer(&hdaps_timer);
- hdaps_timer.function = hdaps_mousedev_poll;
- hdaps_timer.expires = jiffies + HDAPS_POLL_PERIOD;
- add_timer(&hdaps_timer);
-
printk(KERN_INFO "hdaps: driver successfully loaded.\n");
return 0;
out_idev:
- input_free_device(hdaps_idev);
+ input_free_polled_device(hdaps_idev);
out_group:
sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group);
out_device:
@@ -611,8 +604,8 @@ out:
static void __exit hdaps_exit(void)
{
- del_timer_sync(&hdaps_timer);
- input_unregister_device(hdaps_idev);
+ input_unregister_polled_device(hdaps_idev);
+ input_free_polled_device(hdaps_idev);
sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group);
platform_device_unregister(pdev);
platform_driver_unregister(&hdaps_driver);
diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c
index f17e771e42f8..3330667280b9 100644
--- a/drivers/hwmon/hwmon-vid.c
+++ b/drivers/hwmon/hwmon-vid.c
@@ -200,7 +200,7 @@ static u8 find_vrm(u8 eff_family, u8 eff_model, u8 eff_stepping, u8 vendor)
u8 vid_which_vrm(void)
{
- struct cpuinfo_x86 *c = cpu_data;
+ struct cpuinfo_x86 *c = &cpu_data(0);
u32 eax;
u8 eff_family, eff_model, eff_stepping, vrm_ret;
diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c
new file mode 100644
index 000000000000..6ac5c6f53585
--- /dev/null
+++ b/drivers/hwmon/i5k_amb.c
@@ -0,0 +1,552 @@
+/*
+ * A hwmon driver for the Intel 5000 series chipset FB-DIMM AMB
+ * temperature sensors
+ * Copyright (C) 2007 IBM
+ *
+ * Author: Darrick J. Wong <djwong@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/jiffies.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/log2.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+
+#define DRVNAME "i5k_amb"
+
+#define I5K_REG_AMB_BASE_ADDR 0x48
+#define I5K_REG_AMB_LEN_ADDR 0x50
+#define I5K_REG_CHAN0_PRESENCE_ADDR 0x64
+#define I5K_REG_CHAN1_PRESENCE_ADDR 0x66
+
+#define AMB_REG_TEMP_MIN_ADDR 0x80
+#define AMB_REG_TEMP_MID_ADDR 0x81
+#define AMB_REG_TEMP_MAX_ADDR 0x82
+#define AMB_REG_TEMP_STATUS_ADDR 0x84
+#define AMB_REG_TEMP_ADDR 0x85
+
+#define AMB_CONFIG_SIZE 2048
+#define AMB_FUNC_3_OFFSET 768
+
+static unsigned long amb_reg_temp_status(unsigned int amb)
+{
+ return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_STATUS_ADDR +
+ AMB_CONFIG_SIZE * amb;
+}
+
+static unsigned long amb_reg_temp_min(unsigned int amb)
+{
+ return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_MIN_ADDR +
+ AMB_CONFIG_SIZE * amb;
+}
+
+static unsigned long amb_reg_temp_mid(unsigned int amb)
+{
+ return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_MID_ADDR +
+ AMB_CONFIG_SIZE * amb;
+}
+
+static unsigned long amb_reg_temp_max(unsigned int amb)
+{
+ return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_MAX_ADDR +
+ AMB_CONFIG_SIZE * amb;
+}
+
+static unsigned long amb_reg_temp(unsigned int amb)
+{
+ return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_ADDR +
+ AMB_CONFIG_SIZE * amb;
+}
+
+#define MAX_MEM_CHANNELS 4
+#define MAX_AMBS_PER_CHANNEL 16
+#define MAX_AMBS (MAX_MEM_CHANNELS * \
+ MAX_AMBS_PER_CHANNEL)
+/*
+ * Ugly hack: For some reason the highest bit is set if there
+ * are _any_ DIMMs in the channel. Attempting to read from
+ * this "high-order" AMB results in a memory bus error, so
+ * for now we'll just ignore that top bit, even though that
+ * might prevent us from seeing the 16th DIMM in the channel.
+ */
+#define REAL_MAX_AMBS_PER_CHANNEL 15
+#define KNOBS_PER_AMB 5
+
+static unsigned long amb_num_from_reg(unsigned int byte_num, unsigned int bit)
+{
+ return byte_num * MAX_AMBS_PER_CHANNEL + bit;
+}
+
+#define AMB_SYSFS_NAME_LEN 16
+struct i5k_device_attribute {
+ struct sensor_device_attribute s_attr;
+ char name[AMB_SYSFS_NAME_LEN];
+};
+
+struct i5k_amb_data {
+ struct device *hwmon_dev;
+
+ unsigned long amb_base;
+ unsigned long amb_len;
+ u16 amb_present[MAX_MEM_CHANNELS];
+ void __iomem *amb_mmio;
+ struct i5k_device_attribute *attrs;
+ unsigned int num_attrs;
+};
+
+static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ return sprintf(buf, "%s\n", DRVNAME);
+}
+
+
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
+static struct platform_device *amb_pdev;
+
+static u8 amb_read_byte(struct i5k_amb_data *data, unsigned long offset)
+{
+ return ioread8(data->amb_mmio + offset);
+}
+
+static void amb_write_byte(struct i5k_amb_data *data, unsigned long offset,
+ u8 val)
+{
+ iowrite8(val, data->amb_mmio + offset);
+}
+
+static ssize_t show_amb_alarm(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i5k_amb_data *data = dev_get_drvdata(dev);
+
+ if (!(amb_read_byte(data, amb_reg_temp_status(attr->index)) & 0x20) &&
+ (amb_read_byte(data, amb_reg_temp_status(attr->index)) & 0x8))
+ return sprintf(buf, "1\n");
+ else
+ return sprintf(buf, "0\n");
+}
+
+static ssize_t store_amb_min(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i5k_amb_data *data = dev_get_drvdata(dev);
+ unsigned long temp = simple_strtoul(buf, NULL, 10) / 500;
+
+ if (temp > 255)
+ temp = 255;
+
+ amb_write_byte(data, amb_reg_temp_min(attr->index), temp);
+ return count;
+}
+
+static ssize_t store_amb_mid(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i5k_amb_data *data = dev_get_drvdata(dev);
+ unsigned long temp = simple_strtoul(buf, NULL, 10) / 500;
+
+ if (temp > 255)
+ temp = 255;
+
+ amb_write_byte(data, amb_reg_temp_mid(attr->index), temp);
+ return count;
+}
+
+static ssize_t store_amb_max(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i5k_amb_data *data = dev_get_drvdata(dev);
+ unsigned long temp = simple_strtoul(buf, NULL, 10) / 500;
+
+ if (temp > 255)
+ temp = 255;
+
+ amb_write_byte(data, amb_reg_temp_max(attr->index), temp);
+ return count;
+}
+
+static ssize_t show_amb_min(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i5k_amb_data *data = dev_get_drvdata(dev);
+ return sprintf(buf, "%d\n",
+ 500 * amb_read_byte(data, amb_reg_temp_min(attr->index)));
+}
+
+static ssize_t show_amb_mid(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i5k_amb_data *data = dev_get_drvdata(dev);
+ return sprintf(buf, "%d\n",
+ 500 * amb_read_byte(data, amb_reg_temp_mid(attr->index)));
+}
+
+static ssize_t show_amb_max(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i5k_amb_data *data = dev_get_drvdata(dev);
+ return sprintf(buf, "%d\n",
+ 500 * amb_read_byte(data, amb_reg_temp_max(attr->index)));
+}
+
+static ssize_t show_amb_temp(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i5k_amb_data *data = dev_get_drvdata(dev);
+ return sprintf(buf, "%d\n",
+ 500 * amb_read_byte(data, amb_reg_temp(attr->index)));
+}
+
+static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)
+{
+ int i, j, k, d = 0;
+ u16 c;
+ int res = 0;
+ int num_ambs = 0;
+ struct i5k_amb_data *data = platform_get_drvdata(pdev);
+
+ /* Count the number of AMBs found */
+ /* ignore the high-order bit, see "Ugly hack" comment above */
+ for (i = 0; i < MAX_MEM_CHANNELS; i++)
+ num_ambs += hweight16(data->amb_present[i] & 0x7fff);
+
+ /* Set up sysfs stuff */
+ data->attrs = kzalloc(sizeof(*data->attrs) * num_ambs * KNOBS_PER_AMB,
+ GFP_KERNEL);
+ if (!data->attrs)
+ return -ENOMEM;
+ data->num_attrs = 0;
+
+ for (i = 0; i < MAX_MEM_CHANNELS; i++) {
+ c = data->amb_present[i];
+ for (j = 0; j < REAL_MAX_AMBS_PER_CHANNEL; j++, c >>= 1) {
+ struct i5k_device_attribute *iattr;
+
+ k = amb_num_from_reg(i, j);
+ if (!(c & 0x1))
+ continue;
+ d++;
+
+ /* Temperature sysfs knob */
+ iattr = data->attrs + data->num_attrs;
+ snprintf(iattr->name, AMB_SYSFS_NAME_LEN,
+ "temp%d_input", d);
+ iattr->s_attr.dev_attr.attr.name = iattr->name;
+ iattr->s_attr.dev_attr.attr.mode = S_IRUGO;
+ iattr->s_attr.dev_attr.show = show_amb_temp;
+ iattr->s_attr.index = k;
+ res = device_create_file(&pdev->dev,
+ &iattr->s_attr.dev_attr);
+ if (res)
+ goto exit_remove;
+ data->num_attrs++;
+
+ /* Temperature min sysfs knob */
+ iattr = data->attrs + data->num_attrs;
+ snprintf(iattr->name, AMB_SYSFS_NAME_LEN,
+ "temp%d_min", d);
+ iattr->s_attr.dev_attr.attr.name = iattr->name;
+ iattr->s_attr.dev_attr.attr.mode = S_IWUSR | S_IRUGO;
+ iattr->s_attr.dev_attr.show = show_amb_min;
+ iattr->s_attr.dev_attr.store = store_amb_min;
+ iattr->s_attr.index = k;
+ res = device_create_file(&pdev->dev,
+ &iattr->s_attr.dev_attr);
+ if (res)
+ goto exit_remove;
+ data->num_attrs++;
+
+ /* Temperature mid sysfs knob */
+ iattr = data->attrs + data->num_attrs;
+ snprintf(iattr->name, AMB_SYSFS_NAME_LEN,
+ "temp%d_mid", d);
+ iattr->s_attr.dev_attr.attr.name = iattr->name;
+ iattr->s_attr.dev_attr.attr.mode = S_IWUSR | S_IRUGO;
+ iattr->s_attr.dev_attr.show = show_amb_mid;
+ iattr->s_attr.dev_attr.store = store_amb_mid;
+ iattr->s_attr.index = k;
+ res = device_create_file(&pdev->dev,
+ &iattr->s_attr.dev_attr);
+ if (res)
+ goto exit_remove;
+ data->num_attrs++;
+
+ /* Temperature max sysfs knob */
+ iattr = data->attrs + data->num_attrs;
+ snprintf(iattr->name, AMB_SYSFS_NAME_LEN,
+ "temp%d_max", d);
+ iattr->s_attr.dev_attr.attr.name = iattr->name;
+ iattr->s_attr.dev_attr.attr.mode = S_IWUSR | S_IRUGO;
+ iattr->s_attr.dev_attr.show = show_amb_max;
+ iattr->s_attr.dev_attr.store = store_amb_max;
+ iattr->s_attr.index = k;
+ res = device_create_file(&pdev->dev,
+ &iattr->s_attr.dev_attr);
+ if (res)
+ goto exit_remove;
+ data->num_attrs++;
+
+ /* Temperature alarm sysfs knob */
+ iattr = data->attrs + data->num_attrs;
+ snprintf(iattr->name, AMB_SYSFS_NAME_LEN,
+ "temp%d_alarm", d);
+ iattr->s_attr.dev_attr.attr.name = iattr->name;
+ iattr->s_attr.dev_attr.attr.mode = S_IRUGO;
+ iattr->s_attr.dev_attr.show = show_amb_alarm;
+ iattr->s_attr.index = k;
+ res = device_create_file(&pdev->dev,
+ &iattr->s_attr.dev_attr);
+ if (res)
+ goto exit_remove;
+ data->num_attrs++;
+ }
+ }
+
+ res = device_create_file(&pdev->dev, &dev_attr_name);
+ if (res)
+ goto exit_remove;
+
+ data->hwmon_dev = hwmon_device_register(&pdev->dev);
+ if (IS_ERR(data->hwmon_dev)) {
+ res = PTR_ERR(data->hwmon_dev);
+ goto exit_remove;
+ }
+
+ return res;
+
+exit_remove:
+ device_remove_file(&pdev->dev, &dev_attr_name);
+ for (i = 0; i < data->num_attrs; i++)
+ device_remove_file(&pdev->dev, &data->attrs[i].s_attr.dev_attr);
+ kfree(data->attrs);
+
+ return res;
+}
+
+static int __devinit i5k_amb_add(void)
+{
+ int res = -ENODEV;
+
+ /* only ever going to be one of these */
+ amb_pdev = platform_device_alloc(DRVNAME, 0);
+ if (!amb_pdev)
+ return -ENOMEM;
+
+ res = platform_device_add(amb_pdev);
+ if (res)
+ goto err;
+ return 0;
+
+err:
+ platform_device_put(amb_pdev);
+ return res;
+}
+
+static int __devinit i5k_find_amb_registers(struct i5k_amb_data *data)
+{
+ struct pci_dev *pcidev;
+ u32 val32;
+ int res = -ENODEV;
+
+ /* Find AMB register memory space */
+ pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_5000_ERR,
+ NULL);
+ if (!pcidev)
+ return -ENODEV;
+
+ if (pci_read_config_dword(pcidev, I5K_REG_AMB_BASE_ADDR, &val32))
+ goto out;
+ data->amb_base = val32;
+
+ if (pci_read_config_dword(pcidev, I5K_REG_AMB_LEN_ADDR, &val32))
+ goto out;
+ data->amb_len = val32;
+
+ /* Is it big enough? */
+ if (data->amb_len < AMB_CONFIG_SIZE * MAX_AMBS) {
+ dev_err(&pcidev->dev, "AMB region too small!\n");
+ goto out;
+ }
+
+ res = 0;
+out:
+ pci_dev_put(pcidev);
+ return res;
+}
+
+static int __devinit i5k_channel_probe(u16 *amb_present, unsigned long dev_id)
+{
+ struct pci_dev *pcidev;
+ u16 val16;
+ int res = -ENODEV;
+
+ /* Copy the DIMM presence map for these two channels */
+ pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, dev_id, NULL);
+ if (!pcidev)
+ return -ENODEV;
+
+ if (pci_read_config_word(pcidev, I5K_REG_CHAN0_PRESENCE_ADDR, &val16))
+ goto out;
+ amb_present[0] = val16;
+
+ if (pci_read_config_word(pcidev, I5K_REG_CHAN1_PRESENCE_ADDR, &val16))
+ goto out;
+ amb_present[1] = val16;
+
+ res = 0;
+
+out:
+ pci_dev_put(pcidev);
+ return res;
+}
+
+static int __devinit i5k_amb_probe(struct platform_device *pdev)
+{
+ struct i5k_amb_data *data;
+ struct resource *reso;
+ int res = -ENODEV;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ /* Figure out where the AMB registers live */
+ res = i5k_find_amb_registers(data);
+ if (res)
+ goto err;
+
+ /* Copy the DIMM presence map for the first two channels */
+ res = i5k_channel_probe(&data->amb_present[0],
+ PCI_DEVICE_ID_INTEL_5000_FBD0);
+ if (res)
+ goto err;
+
+ /* Copy the DIMM presence map for the optional second two channels */
+ i5k_channel_probe(&data->amb_present[2],
+ PCI_DEVICE_ID_INTEL_5000_FBD1);
+
+ /* Set up resource regions */
+ reso = request_mem_region(data->amb_base, data->amb_len, DRVNAME);
+ if (!reso) {
+ res = -EBUSY;
+ goto err;
+ }
+
+ data->amb_mmio = ioremap_nocache(data->amb_base, data->amb_len);
+ if (!data->amb_mmio) {
+ res = -EBUSY;
+ goto err_map_failed;
+ }
+
+ platform_set_drvdata(pdev, data);
+
+ res = i5k_amb_hwmon_init(pdev);
+ if (res)
+ goto err_init_failed;
+
+ return res;
+
+err_init_failed:
+ iounmap(data->amb_mmio);
+ platform_set_drvdata(pdev, NULL);
+err_map_failed:
+ release_mem_region(data->amb_base, data->amb_len);
+err:
+ kfree(data);
+ return res;
+}
+
+static int __devexit i5k_amb_remove(struct platform_device *pdev)
+{
+ int i;
+ struct i5k_amb_data *data = platform_get_drvdata(pdev);
+
+ hwmon_device_unregister(data->hwmon_dev);
+ device_remove_file(&pdev->dev, &dev_attr_name);
+ for (i = 0; i < data->num_attrs; i++)
+ device_remove_file(&pdev->dev, &data->attrs[i].s_attr.dev_attr);
+ kfree(data->attrs);
+ iounmap(data->amb_mmio);
+ release_mem_region(data->amb_base, data->amb_len);
+ platform_set_drvdata(pdev, NULL);
+ kfree(data);
+ return 0;
+}
+
+static struct platform_driver i5k_amb_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRVNAME,
+ },
+ .probe = i5k_amb_probe,
+ .remove = __devexit_p(i5k_amb_remove),
+};
+
+static int __init i5k_amb_init(void)
+{
+ int res;
+
+ res = platform_driver_register(&i5k_amb_driver);
+ if (res)
+ return res;
+
+ res = i5k_amb_add();
+ if (res)
+ platform_driver_unregister(&i5k_amb_driver);
+
+ return res;
+}
+
+static void __exit i5k_amb_exit(void)
+{
+ platform_device_unregister(amb_pdev);
+ platform_driver_unregister(&i5k_amb_driver);
+}
+
+MODULE_AUTHOR("Darrick J. Wong <djwong@us.ibm.com>");
+MODULE_DESCRIPTION("Intel 5000 chipset FB-DIMM AMB temperature sensor");
+MODULE_LICENSE("GPL");
+
+module_init(i5k_amb_init);
+module_exit(i5k_amb_exit);
diff --git a/drivers/hwmon/ibmpex.c b/drivers/hwmon/ibmpex.c
index c462824ffccf..9c9cdb0685e4 100644
--- a/drivers/hwmon/ibmpex.c
+++ b/drivers/hwmon/ibmpex.c
@@ -140,10 +140,10 @@ static int ibmpex_send_message(struct ibmpex_bmc_data *data)
return 0;
out1:
- printk(KERN_ERR "%s: request_settime=%x\n", __FUNCTION__, err);
+ dev_err(data->bmc_device, "request_settime=%x\n", err);
return err;
out:
- printk(KERN_ERR "%s: validate_addr=%x\n", __FUNCTION__, err);
+ dev_err(data->bmc_device, "validate_addr=%x\n", err);
return err;
}
@@ -161,14 +161,14 @@ static int ibmpex_ver_check(struct ibmpex_bmc_data *data)
data->sensor_major = data->rx_msg_data[0];
data->sensor_minor = data->rx_msg_data[1];
- printk(KERN_INFO DRVNAME ": Found BMC with sensor interface "
- "v%d.%d %d-%02d-%02d on interface %d\n",
- data->sensor_major,
- data->sensor_minor,
- extract_value(data->rx_msg_data, 2),
- data->rx_msg_data[4],
- data->rx_msg_data[5],
- data->interface);
+ dev_info(data->bmc_device, "Found BMC with sensor interface "
+ "v%d.%d %d-%02d-%02d on interface %d\n",
+ data->sensor_major,
+ data->sensor_minor,
+ extract_value(data->rx_msg_data, 2),
+ data->rx_msg_data[4],
+ data->rx_msg_data[5],
+ data->interface);
return 0;
}
@@ -212,8 +212,8 @@ static int ibmpex_query_sensor_data(struct ibmpex_bmc_data *data, int sensor)
wait_for_completion(&data->read_complete);
if (data->rx_result || data->rx_msg_len < 26) {
- printk(KERN_ERR "Error reading sensor %d, please check.\n",
- sensor);
+ dev_err(data->bmc_device, "Error reading sensor %d.\n",
+ sensor);
return -ENOENT;
}
@@ -456,8 +456,7 @@ static void ibmpex_register_bmc(int iface, struct device *dev)
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data) {
- printk(KERN_ERR DRVNAME ": Insufficient memory for BMC "
- "interface %d.\n", data->interface);
+ dev_err(dev, "Insufficient memory for BMC interface.\n");
return;
}
@@ -471,9 +470,8 @@ static void ibmpex_register_bmc(int iface, struct device *dev)
err = ipmi_create_user(data->interface, &driver_data.ipmi_hndlrs,
data, &data->user);
if (err < 0) {
- printk(KERN_ERR DRVNAME ": Error, unable to register user with "
- "ipmi interface %d\n",
- data->interface);
+ dev_err(dev, "Unable to register user with IPMI "
+ "interface %d\n", data->interface);
goto out;
}
@@ -495,9 +493,9 @@ static void ibmpex_register_bmc(int iface, struct device *dev)
data->hwmon_dev = hwmon_device_register(data->bmc_device);
if (IS_ERR(data->hwmon_dev)) {
- printk(KERN_ERR DRVNAME ": Error, unable to register hwmon "
- "class device for interface %d\n",
- data->interface);
+ dev_err(data->bmc_device, "Unable to register hwmon "
+ "device for IPMI interface %d\n",
+ data->interface);
goto out_user;
}
@@ -508,7 +506,7 @@ static void ibmpex_register_bmc(int iface, struct device *dev)
/* Now go find all the sensors */
err = ibmpex_find_sensors(data);
if (err) {
- printk(KERN_ERR "Error %d allocating memory\n", err);
+ dev_err(data->bmc_device, "Error %d finding sensors\n", err);
goto out_register;
}
@@ -561,10 +559,10 @@ static void ibmpex_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data)
struct ibmpex_bmc_data *data = (struct ibmpex_bmc_data *)user_msg_data;
if (msg->msgid != data->tx_msgid) {
- printk(KERN_ERR "Received msgid (%02x) and transmitted "
- "msgid (%02x) mismatch!\n",
- (int)msg->msgid,
- (int)data->tx_msgid);
+ dev_err(data->bmc_device, "Mismatch between received msgid "
+ "(%02x) and transmitted msgid (%02x)!\n",
+ (int)msg->msgid,
+ (int)data->tx_msgid);
ipmi_free_recv_msg(msg);
return;
}
diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c
index f207434730de..650b07d5b902 100644
--- a/drivers/hwmon/lm63.c
+++ b/drivers/hwmon/lm63.c
@@ -533,7 +533,7 @@ static void lm63_init_client(struct i2c_client *client)
/* Start converting if needed */
if (data->config & 0x40) { /* standby */
- dev_dbg(&client->dev, "Switching to operational mode");
+ dev_dbg(&client->dev, "Switching to operational mode\n");
data->config &= 0xA7;
i2c_smbus_write_byte_data(client, LM63_REG_CONFIG1,
data->config);
diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c
index dd366889ce9b..d435f003292d 100644
--- a/drivers/hwmon/lm70.c
+++ b/drivers/hwmon/lm70.c
@@ -31,14 +31,15 @@
#include <linux/err.h>
#include <linux/sysfs.h>
#include <linux/hwmon.h>
+#include <linux/mutex.h>
#include <linux/spi/spi.h>
-#include <asm/semaphore.h>
+
#define DRVNAME "lm70"
struct lm70 {
struct device *hwmon_dev;
- struct semaphore sem;
+ struct mutex lock;
};
/* sysfs hook function */
@@ -51,7 +52,7 @@ static ssize_t lm70_sense_temp(struct device *dev,
s16 raw=0;
struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev);
- if (down_interruptible(&p_lm70->sem))
+ if (mutex_lock_interruptible(&p_lm70->lock))
return -ERESTARTSYS;
/*
@@ -83,7 +84,7 @@ static ssize_t lm70_sense_temp(struct device *dev,
val = ((int)raw/32) * 250;
status = sprintf(buf, "%d\n", val); /* millidegrees Celsius */
out:
- up(&p_lm70->sem);
+ mutex_unlock(&p_lm70->lock);
return status;
}
@@ -112,7 +113,7 @@ static int __devinit lm70_probe(struct spi_device *spi)
if (!p_lm70)
return -ENOMEM;
- init_MUTEX(&p_lm70->sem);
+ mutex_init(&p_lm70->lock);
/* sysfs hook */
p_lm70->hwmon_dev = hwmon_device_register(&spi->dev);
diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c
index 860b71ccbb86..a276806f3d53 100644
--- a/drivers/hwmon/sis5595.c
+++ b/drivers/hwmon/sis5595.c
@@ -3,7 +3,7 @@
for hardware monitoring
Copyright (C) 1998 - 2001 Frodo Looijaard <frodol@dds.nl>,
- Kyösti Mälkki <kmalkki@cc.hut.fi>, and
+ Kyösti Mälkki <kmalkki@cc.hut.fi>, and
Mark D. Studebaker <mdsxyz123@yahoo.com>
Ported to Linux 2.6 by Aurelien Jarno <aurelien@aurel32.net> with
the help of Jean Delvare <khali@linux-fr.org>
@@ -435,6 +435,22 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, ch
}
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
+static ssize_t show_alarm(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ struct sis5595_data *data = sis5595_update_device(dev);
+ int nr = to_sensor_dev_attr(da)->index;
+ return sprintf(buf, "%u\n", (data->alarms >> nr) & 1);
+}
+static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 15);
+static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6);
+static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7);
+static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 15);
+
static ssize_t show_name(struct device *dev, struct device_attribute *attr,
char *buf)
{
@@ -447,22 +463,28 @@ static struct attribute *sis5595_attributes[] = {
&sensor_dev_attr_in0_input.dev_attr.attr,
&sensor_dev_attr_in0_min.dev_attr.attr,
&sensor_dev_attr_in0_max.dev_attr.attr,
+ &sensor_dev_attr_in0_alarm.dev_attr.attr,
&sensor_dev_attr_in1_input.dev_attr.attr,
&sensor_dev_attr_in1_min.dev_attr.attr,
&sensor_dev_attr_in1_max.dev_attr.attr,
+ &sensor_dev_attr_in1_alarm.dev_attr.attr,
&sensor_dev_attr_in2_input.dev_attr.attr,
&sensor_dev_attr_in2_min.dev_attr.attr,
&sensor_dev_attr_in2_max.dev_attr.attr,
+ &sensor_dev_attr_in2_alarm.dev_attr.attr,
&sensor_dev_attr_in3_input.dev_attr.attr,
&sensor_dev_attr_in3_min.dev_attr.attr,
&sensor_dev_attr_in3_max.dev_attr.attr,
+ &sensor_dev_attr_in3_alarm.dev_attr.attr,
&sensor_dev_attr_fan1_input.dev_attr.attr,
&sensor_dev_attr_fan1_min.dev_attr.attr,
&sensor_dev_attr_fan1_div.dev_attr.attr,
+ &sensor_dev_attr_fan1_alarm.dev_attr.attr,
&sensor_dev_attr_fan2_input.dev_attr.attr,
&sensor_dev_attr_fan2_min.dev_attr.attr,
&sensor_dev_attr_fan2_div.dev_attr.attr,
+ &sensor_dev_attr_fan2_alarm.dev_attr.attr,
&dev_attr_alarms.attr,
&dev_attr_name.attr,
@@ -473,19 +495,28 @@ static const struct attribute_group sis5595_group = {
.attrs = sis5595_attributes,
};
-static struct attribute *sis5595_attributes_opt[] = {
+static struct attribute *sis5595_attributes_in4[] = {
&sensor_dev_attr_in4_input.dev_attr.attr,
&sensor_dev_attr_in4_min.dev_attr.attr,
&sensor_dev_attr_in4_max.dev_attr.attr,
+ &sensor_dev_attr_in4_alarm.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group sis5595_group_in4 = {
+ .attrs = sis5595_attributes_in4,
+};
+static struct attribute *sis5595_attributes_temp1[] = {
&dev_attr_temp1_input.attr,
&dev_attr_temp1_max.attr,
&dev_attr_temp1_max_hyst.attr,
+ &sensor_dev_attr_temp1_alarm.dev_attr.attr,
NULL
};
-static const struct attribute_group sis5595_group_opt = {
- .attrs = sis5595_attributes_opt,
+static const struct attribute_group sis5595_group_temp1 = {
+ .attrs = sis5595_attributes_temp1,
};
/* This is called when the module is loaded */
@@ -540,20 +571,12 @@ static int __devinit sis5595_probe(struct platform_device *pdev)
if ((err = sysfs_create_group(&pdev->dev.kobj, &sis5595_group)))
goto exit_free;
if (data->maxins == 4) {
- if ((err = device_create_file(&pdev->dev,
- &sensor_dev_attr_in4_input.dev_attr))
- || (err = device_create_file(&pdev->dev,
- &sensor_dev_attr_in4_min.dev_attr))
- || (err = device_create_file(&pdev->dev,
- &sensor_dev_attr_in4_max.dev_attr)))
+ if ((err = sysfs_create_group(&pdev->dev.kobj,
+ &sis5595_group_in4)))
goto exit_remove_files;
} else {
- if ((err = device_create_file(&pdev->dev,
- &dev_attr_temp1_input))
- || (err = device_create_file(&pdev->dev,
- &dev_attr_temp1_max))
- || (err = device_create_file(&pdev->dev,
- &dev_attr_temp1_max_hyst)))
+ if ((err = sysfs_create_group(&pdev->dev.kobj,
+ &sis5595_group_temp1)))
goto exit_remove_files;
}
@@ -567,7 +590,8 @@ static int __devinit sis5595_probe(struct platform_device *pdev)
exit_remove_files:
sysfs_remove_group(&pdev->dev.kobj, &sis5595_group);
- sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_opt);
+ sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_in4);
+ sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_temp1);
exit_free:
kfree(data);
exit_release:
@@ -582,7 +606,8 @@ static int __devexit sis5595_remove(struct platform_device *pdev)
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&pdev->dev.kobj, &sis5595_group);
- sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_opt);
+ sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_in4);
+ sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_temp1);
release_region(data->addr, SIS5595_EXTENT);
platform_set_drvdata(pdev, NULL);
diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c
index 8f63dada6019..2635bba1e3fc 100644
--- a/drivers/hwmon/via686a.c
+++ b/drivers/hwmon/via686a.c
@@ -3,7 +3,7 @@
for hardware monitoring
Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>,
- Kyösti Mälkki <kmalkki@cc.hut.fi>,
+ Kyösti Mälkki <kmalkki@cc.hut.fi>,
Mark Studebaker <mdsxyz123@yahoo.com>,
and Bob Dougherty <bobd@stanford.edu>
(Some conversion-factor data were contributed by Jonathan Teh Soon Yew
@@ -866,7 +866,7 @@ static void __exit sm_via686a_exit(void)
}
}
-MODULE_AUTHOR("Kyösti Mälkki <kmalkki@cc.hut.fi>, "
+MODULE_AUTHOR("Kyösti Mälkki <kmalkki@cc.hut.fi>, "
"Mark Studebaker <mdsxyz123@yahoo.com> "
"and Bob Dougherty <bobd@stanford.edu>");
MODULE_DESCRIPTION("VIA 686A Sensor device");
diff --git a/drivers/hwmon/vt1211.c b/drivers/hwmon/vt1211.c
index e69416465e6d..7dfcc8dd316d 100644
--- a/drivers/hwmon/vt1211.c
+++ b/drivers/hwmon/vt1211.c
@@ -795,7 +795,7 @@ static ssize_t set_pwm_auto_point_pwm(struct device *dev,
if ((val < 0) || (val > 255)) {
dev_err(dev, "pwm value %ld is out of range. "
- "Choose a value between 0 and 255." , val);
+ "Choose a value between 0 and 255.\n" , val);
return -EINVAL;
}
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index 20ae425a1980..879d0a6544cc 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -170,20 +170,16 @@ superio_exit(void)
#define W83781D_REG_IN(nr) ((nr < 7) ? (0x20 + (nr)) : \
(0x550 + (nr) - 7))
-#define W83781D_REG_FAN_MIN(nr) (0x3a + (nr))
-#define W83781D_REG_FAN(nr) (0x27 + (nr))
-
-#define W83781D_REG_TEMP2_CONFIG 0x152
-#define W83781D_REG_TEMP3_CONFIG 0x252
-#define W83781D_REG_TEMP(nr) ((nr == 3) ? (0x0250) : \
- ((nr == 2) ? (0x0150) : \
- (0x27)))
-#define W83781D_REG_TEMP_HYST(nr) ((nr == 3) ? (0x253) : \
- ((nr == 2) ? (0x153) : \
- (0x3A)))
-#define W83781D_REG_TEMP_OVER(nr) ((nr == 3) ? (0x255) : \
- ((nr == 2) ? (0x155) : \
- (0x39)))
+/* nr:0-2 for fans:1-3 */
+#define W83627HF_REG_FAN_MIN(nr) (0x3b + (nr))
+#define W83627HF_REG_FAN(nr) (0x28 + (nr))
+
+#define W83627HF_REG_TEMP2_CONFIG 0x152
+#define W83627HF_REG_TEMP3_CONFIG 0x252
+/* these are zero-based, unlike config constants above */
+static const u16 w83627hf_reg_temp[] = { 0x27, 0x150, 0x250 };
+static const u16 w83627hf_reg_temp_hyst[] = { 0x3A, 0x153, 0x253 };
+static const u16 w83627hf_reg_temp_over[] = { 0x39, 0x155, 0x255 };
#define W83781D_REG_BANK 0x4E
@@ -360,12 +356,9 @@ struct w83627hf_data {
u8 in_min[9]; /* Register value */
u8 fan[3]; /* Register value */
u8 fan_min[3]; /* Register value */
- u8 temp;
- u8 temp_max; /* Register value */
- u8 temp_max_hyst; /* Register value */
- u16 temp_add[2]; /* Register value */
- u16 temp_max_add[2]; /* Register value */
- u16 temp_max_hyst_add[2]; /* Register value */
+ u16 temp[3]; /* Register value */
+ u16 temp_max[3]; /* Register value */
+ u16 temp_max_hyst[3]; /* Register value */
u8 fan_div[3]; /* Register encoding, shifted right */
u8 vid; /* Register encoding, combined */
u32 alarms; /* Register encoding, combined */
@@ -590,7 +583,7 @@ store_fan_min(struct device *dev, struct device_attribute *devattr,
mutex_lock(&data->update_lock);
data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
- w83627hf_write_value(data, W83781D_REG_FAN_MIN(nr+1),
+ w83627hf_write_value(data, W83627HF_REG_FAN_MIN(nr),
data->fan_min[nr]);
mutex_unlock(&data->update_lock);
@@ -611,12 +604,10 @@ show_temp(struct device *dev, struct device_attribute *devattr, char *buf)
{
int nr = to_sensor_dev_attr(devattr)->index;
struct w83627hf_data *data = w83627hf_update_device(dev);
- if (nr >= 2) { /* TEMP2 and TEMP3 */
- return sprintf(buf, "%ld\n",
- (long)LM75_TEMP_FROM_REG(data->temp_add[nr-2]));
- } else { /* TEMP1 */
- return sprintf(buf, "%ld\n", (long)TEMP_FROM_REG(data->temp));
- }
+
+ u16 tmp = data->temp[nr];
+ return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp)
+ : (long) TEMP_FROM_REG(tmp));
}
static ssize_t
@@ -625,13 +616,10 @@ show_temp_max(struct device *dev, struct device_attribute *devattr,
{
int nr = to_sensor_dev_attr(devattr)->index;
struct w83627hf_data *data = w83627hf_update_device(dev);
- if (nr >= 2) { /* TEMP2 and TEMP3 */
- return sprintf(buf, "%ld\n",
- (long)LM75_TEMP_FROM_REG(data->temp_max_add[nr-2]));
- } else { /* TEMP1 */
- return sprintf(buf, "%ld\n",
- (long)TEMP_FROM_REG(data->temp_max));
- }
+
+ u16 tmp = data->temp_max[nr];
+ return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp)
+ : (long) TEMP_FROM_REG(tmp));
}
static ssize_t
@@ -640,13 +628,10 @@ show_temp_max_hyst(struct device *dev, struct device_attribute *devattr,
{
int nr = to_sensor_dev_attr(devattr)->index;
struct w83627hf_data *data = w83627hf_update_device(dev);
- if (nr >= 2) { /* TEMP2 and TEMP3 */
- return sprintf(buf, "%ld\n",
- (long)LM75_TEMP_FROM_REG(data->temp_max_hyst_add[nr-2]));
- } else { /* TEMP1 */
- return sprintf(buf, "%ld\n",
- (long)TEMP_FROM_REG(data->temp_max_hyst));
- }
+
+ u16 tmp = data->temp_max_hyst[nr];
+ return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp)
+ : (long) TEMP_FROM_REG(tmp));
}
static ssize_t
@@ -656,18 +641,11 @@ store_temp_max(struct device *dev, struct device_attribute *devattr,
int nr = to_sensor_dev_attr(devattr)->index;
struct w83627hf_data *data = dev_get_drvdata(dev);
long val = simple_strtol(buf, NULL, 10);
+ u16 tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val);
mutex_lock(&data->update_lock);
-
- if (nr >= 2) { /* TEMP2 and TEMP3 */
- data->temp_max_add[nr-2] = LM75_TEMP_TO_REG(val);
- w83627hf_write_value(data, W83781D_REG_TEMP_OVER(nr),
- data->temp_max_add[nr-2]);
- } else { /* TEMP1 */
- data->temp_max = TEMP_TO_REG(val);
- w83627hf_write_value(data, W83781D_REG_TEMP_OVER(nr),
- data->temp_max);
- }
+ data->temp_max[nr] = tmp;
+ w83627hf_write_value(data, w83627hf_reg_temp_over[nr], tmp);
mutex_unlock(&data->update_lock);
return count;
}
@@ -679,29 +657,22 @@ store_temp_max_hyst(struct device *dev, struct device_attribute *devattr,
int nr = to_sensor_dev_attr(devattr)->index;
struct w83627hf_data *data = dev_get_drvdata(dev);
long val = simple_strtol(buf, NULL, 10);
+ u16 tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val);
mutex_lock(&data->update_lock);
-
- if (nr >= 2) { /* TEMP2 and TEMP3 */
- data->temp_max_hyst_add[nr-2] = LM75_TEMP_TO_REG(val);
- w83627hf_write_value(data, W83781D_REG_TEMP_HYST(nr),
- data->temp_max_hyst_add[nr-2]);
- } else { /* TEMP1 */
- data->temp_max_hyst = TEMP_TO_REG(val);
- w83627hf_write_value(data, W83781D_REG_TEMP_HYST(nr),
- data->temp_max_hyst);
- }
+ data->temp_max_hyst[nr] = tmp;
+ w83627hf_write_value(data, w83627hf_reg_temp_hyst[nr], tmp);
mutex_unlock(&data->update_lock);
return count;
}
#define sysfs_temp_decl(offset) \
static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
- show_temp, NULL, offset); \
+ show_temp, NULL, offset - 1); \
static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO|S_IWUSR, \
- show_temp_max, store_temp_max, offset); \
+ show_temp_max, store_temp_max, offset - 1); \
static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO|S_IWUSR, \
- show_temp_max_hyst, store_temp_max_hyst, offset);
+ show_temp_max_hyst, store_temp_max_hyst, offset - 1);
sysfs_temp_decl(1);
sysfs_temp_decl(2);
@@ -844,7 +815,7 @@ store_fan_div(struct device *dev, struct device_attribute *devattr,
/* Restore fan_min */
data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
- w83627hf_write_value(data, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]);
+ w83627hf_write_value(data, W83627HF_REG_FAN_MIN(nr), data->fan_min[nr]);
mutex_unlock(&data->update_lock);
return count;
@@ -1170,7 +1141,7 @@ static int __devinit w83627hf_probe(struct platform_device *pdev)
struct w83627hf_sio_data *sio_data = dev->platform_data;
struct w83627hf_data *data;
struct resource *res;
- int err;
+ int err, i;
static const char *names[] = {
"w83627hf",
@@ -1204,9 +1175,9 @@ static int __devinit w83627hf_probe(struct platform_device *pdev)
w83627hf_init_device(pdev);
/* A few vars need to be filled upon startup */
- data->fan_min[0] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(1));
- data->fan_min[1] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(2));
- data->fan_min[2] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(3));
+ for (i = 0; i <= 2; i++)
+ data->fan_min[i] = w83627hf_read_value(
+ data, W83627HF_REG_FAN_MIN(i));
w83627hf_update_fan_div(data);
/* Register common device attributes */
@@ -1514,23 +1485,23 @@ static void __devinit w83627hf_init_device(struct platform_device *pdev)
if(init) {
/* Enable temp2 */
- tmp = w83627hf_read_value(data, W83781D_REG_TEMP2_CONFIG);
+ tmp = w83627hf_read_value(data, W83627HF_REG_TEMP2_CONFIG);
if (tmp & 0x01) {
dev_warn(&pdev->dev, "Enabling temp2, readings "
"might not make sense\n");
- w83627hf_write_value(data, W83781D_REG_TEMP2_CONFIG,
+ w83627hf_write_value(data, W83627HF_REG_TEMP2_CONFIG,
tmp & 0xfe);
}
/* Enable temp3 */
if (type != w83697hf) {
tmp = w83627hf_read_value(data,
- W83781D_REG_TEMP3_CONFIG);
+ W83627HF_REG_TEMP3_CONFIG);
if (tmp & 0x01) {
dev_warn(&pdev->dev, "Enabling temp3, "
"readings might not make sense\n");
w83627hf_write_value(data,
- W83781D_REG_TEMP3_CONFIG, tmp & 0xfe);
+ W83627HF_REG_TEMP3_CONFIG, tmp & 0xfe);
}
}
}
@@ -1563,7 +1534,7 @@ static void w83627hf_update_fan_div(struct w83627hf_data *data)
static struct w83627hf_data *w83627hf_update_device(struct device *dev)
{
struct w83627hf_data *data = dev_get_drvdata(dev);
- int i;
+ int i, num_temps = (data->type == w83697hf) ? 2 : 3;
mutex_lock(&data->update_lock);
@@ -1584,12 +1555,12 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev)
w83627hf_read_value(data,
W83781D_REG_IN_MAX(i));
}
- for (i = 1; i <= 3; i++) {
- data->fan[i - 1] =
- w83627hf_read_value(data, W83781D_REG_FAN(i));
- data->fan_min[i - 1] =
+ for (i = 0; i <= 2; i++) {
+ data->fan[i] =
+ w83627hf_read_value(data, W83627HF_REG_FAN(i));
+ data->fan_min[i] =
w83627hf_read_value(data,
- W83781D_REG_FAN_MIN(i));
+ W83627HF_REG_FAN_MIN(i));
}
for (i = 0; i <= 2; i++) {
u8 tmp = w83627hf_read_value(data,
@@ -1616,25 +1587,13 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev)
break;
}
}
-
- data->temp = w83627hf_read_value(data, W83781D_REG_TEMP(1));
- data->temp_max =
- w83627hf_read_value(data, W83781D_REG_TEMP_OVER(1));
- data->temp_max_hyst =
- w83627hf_read_value(data, W83781D_REG_TEMP_HYST(1));
- data->temp_add[0] =
- w83627hf_read_value(data, W83781D_REG_TEMP(2));
- data->temp_max_add[0] =
- w83627hf_read_value(data, W83781D_REG_TEMP_OVER(2));
- data->temp_max_hyst_add[0] =
- w83627hf_read_value(data, W83781D_REG_TEMP_HYST(2));
- if (data->type != w83697hf) {
- data->temp_add[1] =
- w83627hf_read_value(data, W83781D_REG_TEMP(3));
- data->temp_max_add[1] =
- w83627hf_read_value(data, W83781D_REG_TEMP_OVER(3));
- data->temp_max_hyst_add[1] =
- w83627hf_read_value(data, W83781D_REG_TEMP_HYST(3));
+ for (i = 0; i < num_temps; i++) {
+ data->temp[i] = w83627hf_read_value(
+ data, w83627hf_reg_temp[i]);
+ data->temp_max[i] = w83627hf_read_value(
+ data, w83627hf_reg_temp_over[i]);
+ data->temp_max_hyst[i] = w83627hf_read_value(
+ data, w83627hf_reg_temp_hyst[i]);
}
w83627hf_update_fan_div(data);
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index a6a1edfe7614..e0fa7520400d 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -1122,12 +1122,13 @@ w83781d_create_files(struct device *dev, int kind, int is_isa)
&sensor_dev_attr_temp3_beep.dev_attr)))
return err;
- if (kind != w83781d)
+ if (kind != w83781d) {
err = sysfs_chmod_file(&dev->kobj,
&sensor_dev_attr_temp3_alarm.dev_attr.attr,
S_IRUGO | S_IWUSR);
if (err)
return err;
+ }
}
if (kind != w83781d && kind != as99127f) {
diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c
index b6f2ebf9f9cf..a9c01a6f0057 100644
--- a/drivers/hwmon/w83791d.c
+++ b/drivers/hwmon/w83791d.c
@@ -1096,7 +1096,7 @@ static int w83791d_detect(struct i2c_adapter *adapter, int address, int kind)
if (kind == w83791d) {
client_name = "w83791d";
} else {
- dev_err(dev, "w83791d: Internal error: unknown kind (%d)?!?",
+ dev_err(dev, "w83791d: Internal error: unknown kind (%d)?!?\n",
kind);
goto error1;
}
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c
index f836198b705c..007449d3e16e 100644
--- a/drivers/hwmon/w83792d.c
+++ b/drivers/hwmon/w83792d.c
@@ -1385,8 +1385,8 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
if (kind == w83792d) {
client_name = "w83792d";
} else {
- dev_err(dev, "w83792d: Internal error: unknown"
- " kind (%d)?!?", kind);
+ dev_err(dev, "w83792d: Internal error: unknown kind (%d)?!?\n",
+ kind);
goto ERROR1;
}
diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c
index 7f0a0a62cf60..a37cb6b8593c 100644
--- a/drivers/i2c/algos/i2c-algo-bit.c
+++ b/drivers/i2c/algos/i2c-algo-bit.c
@@ -18,7 +18,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* ------------------------------------------------------------------------- */
-/* With some changes from Frodo Looijaard <frodol@dds.nl>, Kyösti Mälkki
+/* With some changes from Frodo Looijaard <frodol@dds.nl>, Kyösti Mälkki
<kmalkki@cc.hut.fi> and Jean Delvare <khali@linux-fr.org> */
#include <linux/kernel.h>
diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c
index 36fdf971f080..2a16211f12e5 100644
--- a/drivers/i2c/algos/i2c-algo-pca.c
+++ b/drivers/i2c/algos/i2c-algo-pca.c
@@ -350,7 +350,7 @@ static int pca_init(struct i2c_algo_pca_data *adap)
pca_outw(adap, I2C_PCA_ADR, own << 1);
pca_set_con(adap, I2C_PCA_CON_ENSIO | clock);
- udelay(500); /* 500 µs for oscilator to stabilise */
+ udelay(500); /* 500 µs for oscilator to stabilise */
return 0;
}
diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c
index ecb2c2d7d540..ab2e6f3498b4 100644
--- a/drivers/i2c/algos/i2c-algo-pcf.c
+++ b/drivers/i2c/algos/i2c-algo-pcf.c
@@ -19,7 +19,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* ------------------------------------------------------------------------- */
-/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
+/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
Frodo Looijaard <frodol@dds.nl> ,and also from Martin Bailey
<mbailey@littlefeet-inc.com> */
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index de95c75efb41..c466c6cfc2e5 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -278,7 +278,7 @@ config I2C_IXP2000
depends on ARCH_IXP2000
select I2C_ALGOBIT
help
- Say Y here if you have an Intel IXP2000(2400, 2800, 2850) based
+ Say Y here if you have an Intel IXP2000 (2400, 2800, 2850) based
system and are using GPIO lines for an I2C bus.
This support is also available as a module. If so, the module
@@ -293,8 +293,8 @@ config I2C_POWERMAC
default y
help
This exposes the various PowerMac i2c interfaces to the linux i2c
- layer and to userland. It is used by various drivers on the powemac
- platform, thus should generally be enabled.
+ layer and to userland. It is used by various drivers on the PowerMac
+ platform, and should generally be enabled.
This support is also available as a module. If so, the module
will be called i2c-powermac.
@@ -438,12 +438,12 @@ config I2C_SIMTEC
tristate "Simtec Generic I2C interface"
select I2C_ALGOBIT
help
- If you say yes to this option, support will be inclyded for
+ If you say yes to this option, support will be included for
the Simtec Generic I2C interface. This driver is for the
simple I2C bus used on newer Simtec products for general
I2C, such as DDC on the Simtec BBD2016A.
- This driver can also be build as a module. If so, the module
+ This driver can also be built as a module. If so, the module
will be called i2c-simtec.
config SCx200_I2C
diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c
index 804f0a551c05..b7a9977b025f 100644
--- a/drivers/i2c/busses/i2c-elektor.c
+++ b/drivers/i2c/busses/i2c-elektor.c
@@ -19,7 +19,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* ------------------------------------------------------------------------- */
-/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
+/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
Frodo Looijaard <frodol@dds.nl> */
/* Partialy rewriten by Oleg I. Vdovikin for mmapped support of
diff --git a/drivers/i2c/busses/i2c-hydra.c b/drivers/i2c/busses/i2c-hydra.c
index 9832f773651d..f9972f9651e4 100644
--- a/drivers/i2c/busses/i2c-hydra.c
+++ b/drivers/i2c/busses/i2c-hydra.c
@@ -7,7 +7,7 @@
Copyright (c) 1999-2004 Geert Uytterhoeven <geert@linux-m68k.org>
Based on i2c Support for Via Technologies 82C586B South Bridge
- Copyright (c) 1998, 1999 Kyösti Mälkki <kmalkki@cc.hut.fi>
+ Copyright (c) 1998, 1999 Kyösti Mälkki <kmalkki@cc.hut.fi>
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
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index e08bacadd6bc..9b43ff7270d0 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -18,7 +18,7 @@
* Copyright 1995-97 Simon G. Vogl
* 1998-99 Hans Berglund
*
- * With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi>
+ * With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi>
* and even Frodo Looijaard <frodol@dds.nl>
*
* This program is free software; you can redistribute it and/or modify it
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index e471e3bfdc1e..89a30028ddb6 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -8,7 +8,7 @@
* Tony Lindgren <tony@atomide.com> and Imre Deak <imre.deak@nokia.com>
* Copyright (C) 2005 Nokia Corporation
*
- * Cleaned up by Juha Yrjölä <juha.yrjola@nokia.com>
+ * Cleaned up by Juha Yrjölä <juha.yrjola@nokia.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/drivers/i2c/busses/i2c-parport-light.c b/drivers/i2c/busses/i2c-parport-light.c
index 49a95e2887bc..c6faf9bdad18 100644
--- a/drivers/i2c/busses/i2c-parport-light.c
+++ b/drivers/i2c/busses/i2c-parport-light.c
@@ -7,7 +7,7 @@
Copyright (C) 1995-2000 Simon G. Vogl
With some changes from:
Frodo Looijaard <frodol@dds.nl>
- Kyösti Mälkki <kmalkki@cc.hut.fi>
+ Kyösti Mälkki <kmalkki@cc.hut.fi>
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
diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c
index 039a07fde908..59ba2086d2f9 100644
--- a/drivers/i2c/busses/i2c-parport.c
+++ b/drivers/i2c/busses/i2c-parport.c
@@ -7,7 +7,7 @@
Copyright (C) 1995-2000 Simon G. Vogl
With some changes from:
Frodo Looijaard <frodol@dds.nl>
- Kyösti Mälkki <kmalkki@cc.hut.fi>
+ Kyösti Mälkki <kmalkki@cc.hut.fi>
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
diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c
index 58e32714afb5..ca18e0be4901 100644
--- a/drivers/i2c/busses/i2c-pasemi.c
+++ b/drivers/i2c/busses/i2c-pasemi.c
@@ -51,6 +51,7 @@ struct pasemi_smbus {
#define MRXFIFO_DATA_M 0x000000ff
#define SMSTA_XEN 0x08000000
+#define SMSTA_MTN 0x00200000
#define CTL_MRR 0x00000400
#define CTL_MTR 0x00000200
@@ -98,6 +99,10 @@ static unsigned int pasemi_smb_waitready(struct pasemi_smbus *smbus)
status = reg_read(smbus, REG_SMSTA);
}
+ /* Got NACK? */
+ if (status & SMSTA_MTN)
+ return -ENXIO;
+
if (timeout < 0) {
dev_warn(&smbus->dev->dev, "Timeout, status 0x%08x\n", status);
reg_write(smbus, REG_SMSTA, status);
@@ -364,7 +369,7 @@ static int __devinit pasemi_smb_probe(struct pci_dev *dev,
smbus->adapter.algo = &smbus_algorithm;
smbus->adapter.algo_data = smbus;
- /* set up the driverfs linkage to our parent device */
+ /* set up the sysfs linkage to our parent device */
smbus->adapter.dev.parent = &dev->dev;
reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR |
diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c
index 17cecf1ea797..be99c02ecac5 100644
--- a/drivers/i2c/busses/i2c-pmcmsp.c
+++ b/drivers/i2c/busses/i2c-pmcmsp.c
@@ -591,18 +591,18 @@ static int pmcmsptwi_master_xfer(struct i2c_adapter *adap,
if (msg->flags & I2C_M_TEN)
pmcmsptwi_set_twi_config(&oldcfg, data);
- dev_dbg(&adap->dev, "I2C %s of %d bytes ",
- (msg->flags & I2C_M_RD) ? "read" : "write", msg->len);
+ dev_dbg(&adap->dev, "I2C %s of %d bytes %s\n",
+ (msg->flags & I2C_M_RD) ? "read" : "write", msg->len,
+ (ret == MSP_TWI_XFER_OK) ? "succeeded" : "failed");
+
if (ret != MSP_TWI_XFER_OK) {
/*
* TODO: We could potentially loop and retry in the case
* of MSP_TWI_XFER_TIMEOUT.
*/
- dev_dbg(&adap->dev, "failed\n");
return -1;
}
- dev_dbg(&adap->dev, "succeeded\n");
return 0;
}
diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c
index 17376feb1acc..f8d0dff0de7e 100644
--- a/drivers/i2c/busses/i2c-pnx.c
+++ b/drivers/i2c/busses/i2c-pnx.c
@@ -575,7 +575,7 @@ static int __devinit i2c_pnx_probe(struct platform_device *pdev)
else {
freq_mhz = PNX_DEFAULT_FREQ;
dev_info(&pdev->dev, "Setting bus frequency to default value: "
- "%d MHz", freq_mhz);
+ "%d MHz\n", freq_mhz);
}
i2c_pnx->adapter->algo = &pnx_algorithm;
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index bb5466b27b59..6426a61f8d4d 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -31,6 +31,8 @@
#include <linux/interrupt.h>
#include <linux/i2c-pxa.h>
#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
#include <asm/hardware.h>
#include <asm/irq.h>
@@ -48,6 +50,7 @@ struct pxa_i2c {
unsigned int slave_addr;
struct i2c_adapter adap;
+ struct clk *clk;
#ifdef CONFIG_I2C_PXA_SLAVE
struct i2c_slave_client *slave;
#endif
@@ -82,7 +85,7 @@ struct bits {
const char *set;
const char *unset;
};
-#define BIT(m, s, u) { .mask = m, .set = s, .unset = u }
+#define PXA_BIT(m, s, u) { .mask = m, .set = s, .unset = u }
static inline void
decode_bits(const char *prefix, const struct bits *bits, int num, u32 val)
@@ -97,17 +100,17 @@ decode_bits(const char *prefix, const struct bits *bits, int num, u32 val)
}
static const struct bits isr_bits[] = {
- BIT(ISR_RWM, "RX", "TX"),
- BIT(ISR_ACKNAK, "NAK", "ACK"),
- BIT(ISR_UB, "Bsy", "Rdy"),
- BIT(ISR_IBB, "BusBsy", "BusRdy"),
- BIT(ISR_SSD, "SlaveStop", NULL),
- BIT(ISR_ALD, "ALD", NULL),
- BIT(ISR_ITE, "TxEmpty", NULL),
- BIT(ISR_IRF, "RxFull", NULL),
- BIT(ISR_GCAD, "GenCall", NULL),
- BIT(ISR_SAD, "SlaveAddr", NULL),
- BIT(ISR_BED, "BusErr", NULL),
+ PXA_BIT(ISR_RWM, "RX", "TX"),
+ PXA_BIT(ISR_ACKNAK, "NAK", "ACK"),
+ PXA_BIT(ISR_UB, "Bsy", "Rdy"),
+ PXA_BIT(ISR_IBB, "BusBsy", "BusRdy"),
+ PXA_BIT(ISR_SSD, "SlaveStop", NULL),
+ PXA_BIT(ISR_ALD, "ALD", NULL),
+ PXA_BIT(ISR_ITE, "TxEmpty", NULL),
+ PXA_BIT(ISR_IRF, "RxFull", NULL),
+ PXA_BIT(ISR_GCAD, "GenCall", NULL),
+ PXA_BIT(ISR_SAD, "SlaveAddr", NULL),
+ PXA_BIT(ISR_BED, "BusErr", NULL),
};
static void decode_ISR(unsigned int val)
@@ -117,21 +120,21 @@ static void decode_ISR(unsigned int val)
}
static const struct bits icr_bits[] = {
- BIT(ICR_START, "START", NULL),
- BIT(ICR_STOP, "STOP", NULL),
- BIT(ICR_ACKNAK, "ACKNAK", NULL),
- BIT(ICR_TB, "TB", NULL),
- BIT(ICR_MA, "MA", NULL),
- BIT(ICR_SCLE, "SCLE", "scle"),
- BIT(ICR_IUE, "IUE", "iue"),
- BIT(ICR_GCD, "GCD", NULL),
- BIT(ICR_ITEIE, "ITEIE", NULL),
- BIT(ICR_IRFIE, "IRFIE", NULL),
- BIT(ICR_BEIE, "BEIE", NULL),
- BIT(ICR_SSDIE, "SSDIE", NULL),
- BIT(ICR_ALDIE, "ALDIE", NULL),
- BIT(ICR_SADIE, "SADIE", NULL),
- BIT(ICR_UR, "UR", "ur"),
+ PXA_BIT(ICR_START, "START", NULL),
+ PXA_BIT(ICR_STOP, "STOP", NULL),
+ PXA_BIT(ICR_ACKNAK, "ACKNAK", NULL),
+ PXA_BIT(ICR_TB, "TB", NULL),
+ PXA_BIT(ICR_MA, "MA", NULL),
+ PXA_BIT(ICR_SCLE, "SCLE", "scle"),
+ PXA_BIT(ICR_IUE, "IUE", "iue"),
+ PXA_BIT(ICR_GCD, "GCD", NULL),
+ PXA_BIT(ICR_ITEIE, "ITEIE", NULL),
+ PXA_BIT(ICR_IRFIE, "IRFIE", NULL),
+ PXA_BIT(ICR_BEIE, "BEIE", NULL),
+ PXA_BIT(ICR_SSDIE, "SSDIE", NULL),
+ PXA_BIT(ICR_ALDIE, "ALDIE", NULL),
+ PXA_BIT(ICR_SADIE, "SADIE", NULL),
+ PXA_BIT(ICR_UR, "UR", "ur"),
};
static void decode_ICR(unsigned int val)
@@ -869,6 +872,12 @@ static int i2c_pxa_probe(struct platform_device *dev)
sprintf(i2c->adap.name, "pxa_i2c-i2c.%u", dev->id);
+ i2c->clk = clk_get(&dev->dev, "I2CCLK");
+ if (IS_ERR(i2c->clk)) {
+ ret = PTR_ERR(i2c->clk);
+ goto eclk;
+ }
+
i2c->reg_base = ioremap(res->start, res_len(res));
if (!i2c->reg_base) {
ret = -EIO;
@@ -889,22 +898,19 @@ static int i2c_pxa_probe(struct platform_device *dev)
}
#endif
+ clk_enable(i2c->clk);
+#ifdef CONFIG_PXA27x
switch (dev->id) {
case 0:
-#ifdef CONFIG_PXA27x
pxa_gpio_mode(GPIO117_I2CSCL_MD);
pxa_gpio_mode(GPIO118_I2CSDA_MD);
-#endif
- pxa_set_cken(CKEN_I2C, 1);
break;
-#ifdef CONFIG_PXA27x
case 1:
local_irq_disable();
PCFR |= PCFR_PI2CEN;
local_irq_enable();
- pxa_set_cken(CKEN_PWRI2C, 1);
-#endif
}
+#endif
ret = request_irq(irq, i2c_pxa_handler, IRQF_DISABLED,
i2c->adap.name, i2c);
@@ -948,19 +954,18 @@ static int i2c_pxa_probe(struct platform_device *dev)
eadapt:
free_irq(irq, i2c);
ereqirq:
- switch (dev->id) {
- case 0:
- pxa_set_cken(CKEN_I2C, 0);
- break;
+ clk_disable(i2c->clk);
+
#ifdef CONFIG_PXA27x
- case 1:
- pxa_set_cken(CKEN_PWRI2C, 0);
+ if (dev->id == 1) {
local_irq_disable();
PCFR &= ~PCFR_PI2CEN;
local_irq_enable();
-#endif
}
+#endif
eremap:
+ clk_put(i2c->clk);
+eclk:
kfree(i2c);
emalloc:
release_mem_region(res->start, res_len(res));
@@ -975,18 +980,18 @@ static int i2c_pxa_remove(struct platform_device *dev)
i2c_del_adapter(&i2c->adap);
free_irq(i2c->irq, i2c);
- switch (dev->id) {
- case 0:
- pxa_set_cken(CKEN_I2C, 0);
- break;
+
+ clk_disable(i2c->clk);
+ clk_put(i2c->clk);
+
#ifdef CONFIG_PXA27x
- case 1:
- pxa_set_cken(CKEN_PWRI2C, 0);
+ if (dev->id == 1) {
local_irq_disable();
PCFR &= ~PCFR_PI2CEN;
local_irq_enable();
-#endif
}
+#endif
+
release_mem_region(i2c->iobase, i2c->iosize);
kfree(i2c);
diff --git a/drivers/i2c/busses/i2c-via.c b/drivers/i2c/busses/i2c-via.c
index 81520868797b..61716f6b14dc 100644
--- a/drivers/i2c/busses/i2c-via.c
+++ b/drivers/i2c/busses/i2c-via.c
@@ -4,7 +4,7 @@
i2c Support for Via Technologies 82C586B South Bridge
- Copyright (c) 1998, 1999 Kyösti Mälkki <kmalkki@cc.hut.fi>
+ Copyright (c) 1998, 1999 Kyösti Mälkki <kmalkki@cc.hut.fi>
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
@@ -176,7 +176,7 @@ static void __exit i2c_vt586b_exit(void)
}
-MODULE_AUTHOR("Kyösti Mälkki <kmalkki@cc.hut.fi>");
+MODULE_AUTHOR("Kyösti Mälkki <kmalkki@cc.hut.fi>");
MODULE_DESCRIPTION("i2c for Via vt82c586b southbridge");
MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
index edc275002f80..c9ce77f13c0e 100644
--- a/drivers/i2c/busses/i2c-viapro.c
+++ b/drivers/i2c/busses/i2c-viapro.c
@@ -2,7 +2,7 @@
i2c-viapro.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>,
- Philip Edelbrock <phil@netroedge.com>, Kyösti Mälkki <kmalkki@cc.hut.fi>,
+ Philip Edelbrock <phil@netroedge.com>, Kyösti Mälkki <kmalkki@cc.hut.fi>,
Mark D. Studebaker <mdsxyz123@yahoo.com>
Copyright (C) 2005 - 2007 Jean Delvare <khali@linux-fr.org>
diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
index d3da1fb05b9b..1a7eeebac506 100644
--- a/drivers/i2c/chips/eeprom.c
+++ b/drivers/i2c/chips/eeprom.c
@@ -128,13 +128,20 @@ static ssize_t eeprom_read(struct kobject *kobj, struct bin_attribute *bin_attr,
for (slice = off >> 5; slice <= (off + count - 1) >> 5; slice++)
eeprom_update_client(client, slice);
- /* Hide Vaio security settings to regular users (16 first bytes) */
- if (data->nature == VAIO && off < 16 && !capable(CAP_SYS_ADMIN)) {
- size_t in_row1 = 16 - off;
- in_row1 = min(in_row1, count);
- memset(buf, 0, in_row1);
- if (count - in_row1 > 0)
- memcpy(buf + in_row1, &data->data[16], count - in_row1);
+ /* Hide Vaio private settings to regular users:
+ - BIOS passwords: bytes 0x00 to 0x0f
+ - UUID: bytes 0x10 to 0x1f
+ - Serial number: 0xc0 to 0xdf */
+ if (data->nature == VAIO && !capable(CAP_SYS_ADMIN)) {
+ int i;
+
+ for (i = 0; i < count; i++) {
+ if ((off + i <= 0x1f) ||
+ (off + i >= 0xc0 && off + i <= 0xdf))
+ buf[i] = 0;
+ else
+ buf[i] = data->data[off + i];
+ }
} else {
memcpy(buf, &data->data[off], count);
}
@@ -197,14 +204,18 @@ static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
goto exit_kfree;
/* Detect the Vaio nature of EEPROMs.
- We use the "PCG-" prefix as the signature. */
+ We use the "PCG-" or "VGN-" prefix as the signature. */
if (address == 0x57) {
- if (i2c_smbus_read_byte_data(new_client, 0x80) == 'P'
- && i2c_smbus_read_byte(new_client) == 'C'
- && i2c_smbus_read_byte(new_client) == 'G'
- && i2c_smbus_read_byte(new_client) == '-') {
+ char name[4];
+
+ name[0] = i2c_smbus_read_byte_data(new_client, 0x80);
+ name[1] = i2c_smbus_read_byte(new_client);
+ name[2] = i2c_smbus_read_byte(new_client);
+ name[3] = i2c_smbus_read_byte(new_client);
+
+ if (!memcmp(name, "PCG-", 4) || !memcmp(name, "VGN-", 4)) {
dev_info(&new_client->dev, "Vaio EEPROM detected, "
- "enabling password protection\n");
+ "enabling privacy protection\n");
data->nature = VAIO;
}
}
diff --git a/drivers/i2c/chips/menelaus.c b/drivers/i2c/chips/menelaus.c
index d9c92c5e0077..2dea0123a958 100644
--- a/drivers/i2c/chips/menelaus.c
+++ b/drivers/i2c/chips/menelaus.c
@@ -49,8 +49,6 @@
#define DRIVER_NAME "menelaus"
-#define pr_err(fmt, arg...) printk(KERN_ERR DRIVER_NAME ": ", ## arg);
-
#define MENELAUS_I2C_ADDRESS 0x72
#define MENELAUS_REV 0x01
@@ -155,7 +153,7 @@ static int menelaus_write_reg(int reg, u8 value)
int val = i2c_smbus_write_byte_data(the_menelaus->client, reg, value);
if (val < 0) {
- pr_err("write error");
+ pr_err(DRIVER_NAME ": write error");
return val;
}
@@ -167,7 +165,7 @@ static int menelaus_read_reg(int reg)
int val = i2c_smbus_read_byte_data(the_menelaus->client, reg);
if (val < 0)
- pr_err("read error");
+ pr_err(DRIVER_NAME ": read error");
return val;
}
@@ -1177,7 +1175,7 @@ static int menelaus_probe(struct i2c_client *client)
/* If a true probe check the device */
rev = menelaus_read_reg(MENELAUS_REV);
if (rev < 0) {
- pr_err("device not found");
+ pr_err(DRIVER_NAME ": device not found");
err = -ENODEV;
goto fail1;
}
@@ -1197,7 +1195,7 @@ static int menelaus_probe(struct i2c_client *client)
err = request_irq(client->irq, menelaus_irq, IRQF_DISABLED,
DRIVER_NAME, menelaus);
if (err) {
- dev_dbg(&client->dev, "can't get IRQ %d, err %d",
+ dev_dbg(&client->dev, "can't get IRQ %d, err %d\n",
client->irq, err);
goto fail1;
}
@@ -1258,7 +1256,7 @@ static int __init menelaus_init(void)
res = i2c_add_driver(&menelaus_i2c_driver);
if (res < 0) {
- pr_err("driver registration failed\n");
+ pr_err(DRIVER_NAME ": driver registration failed\n");
return res;
}
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index e73d58c43f38..b5e13e405e72 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -17,7 +17,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* ------------------------------------------------------------------------- */
-/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi>.
+/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi>.
All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl>
SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com> and
Jean Delvare <khali@linux-fr.org> */
@@ -673,7 +673,7 @@ static int __i2c_check_addr(struct i2c_adapter *adapter, unsigned int addr)
return 0;
}
-int i2c_check_addr(struct i2c_adapter *adapter, int addr)
+static int i2c_check_addr(struct i2c_adapter *adapter, int addr)
{
int rval;
@@ -683,7 +683,6 @@ int i2c_check_addr(struct i2c_adapter *adapter, int addr)
return rval;
}
-EXPORT_SYMBOL(i2c_check_addr);
int i2c_attach_client(struct i2c_client *client)
{
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 5a15e50748de..c21ae20ae362 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -38,6 +38,15 @@
static struct i2c_driver i2cdev_driver;
+/*
+ * An i2c_dev represents an i2c_adapter ... an I2C or SMBus master, not a
+ * slave (i2c_client) with which messages will be exchanged. It's coupled
+ * with a character special file which is accessed by user mode drivers.
+ *
+ * The list of i2c_dev structures is parallel to the i2c_adapter lists
+ * maintained by the driver model, and is updated using notifications
+ * delivered to the i2cdev_driver.
+ */
struct i2c_dev {
struct list_head list;
struct i2c_adapter *adap;
@@ -103,6 +112,25 @@ static ssize_t show_adapter_name(struct device *dev,
}
static DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL);
+/* ------------------------------------------------------------------------- */
+
+/*
+ * After opening an instance of this character special file, a file
+ * descriptor starts out associated only with an i2c_adapter (and bus).
+ *
+ * Using the I2C_RDWR ioctl(), you can then *immediately* issue i2c_msg
+ * traffic to any devices on the bus used by that adapter. That's because
+ * the i2c_msg vectors embed all the addressing information they need, and
+ * are submitted directly to an i2c_adapter. However, SMBus-only adapters
+ * don't support that interface.
+ *
+ * To use read()/write() system calls on that file descriptor, or to use
+ * SMBus interfaces (and work with SMBus-only hosts!), you must first issue
+ * an I2C_SLAVE (or I2C_SLAVE_FORCE) ioctl. That configures an anonymous
+ * (never registered) i2c_client so it holds the addressing information
+ * needed by those system calls and by this SMBus interface.
+ */
+
static ssize_t i2cdev_read (struct file *file, char __user *buf, size_t count,
loff_t *offset)
{
@@ -154,6 +182,29 @@ static ssize_t i2cdev_write (struct file *file, const char __user *buf, size_t c
return ret;
}
+/* This address checking function differs from the one in i2c-core
+ in that it considers an address with a registered device, but no
+ bounded driver, as NOT busy. */
+static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr)
+{
+ struct list_head *item;
+ struct i2c_client *client;
+ int res = 0;
+
+ mutex_lock(&adapter->clist_lock);
+ list_for_each(item, &adapter->clients) {
+ client = list_entry(item, struct i2c_client, list);
+ if (client->addr == addr) {
+ if (client->driver)
+ res = -EBUSY;
+ break;
+ }
+ }
+ mutex_unlock(&adapter->clist_lock);
+
+ return res;
+}
+
static int i2cdev_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
@@ -172,11 +223,22 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file,
switch ( cmd ) {
case I2C_SLAVE:
case I2C_SLAVE_FORCE:
+ /* NOTE: devices set up to work with "new style" drivers
+ * can't use I2C_SLAVE, even when the device node is not
+ * bound to a driver. Only I2C_SLAVE_FORCE will work.
+ *
+ * Setting the PEC flag here won't affect kernel drivers,
+ * which will be using the i2c_client node registered with
+ * the driver model core. Likewise, when that client has
+ * the PEC flag already set, the i2c-dev driver won't see
+ * (or use) this setting.
+ */
if ((arg > 0x3ff) ||
(((client->flags & I2C_M_TEN) == 0) && arg > 0x7f))
return -EINVAL;
- if ((cmd == I2C_SLAVE) && i2c_check_addr(client->adapter,arg))
+ if (cmd == I2C_SLAVE && i2cdev_check_addr(client->adapter, arg))
return -EBUSY;
+ /* REVISIT: address could become busy later */
client->addr = arg;
return 0;
case I2C_TENBIT:
@@ -386,6 +448,13 @@ static int i2cdev_open(struct inode *inode, struct file *file)
if (!adap)
return -ENODEV;
+ /* This creates an anonymous i2c_client, which may later be
+ * pointed to some address using I2C_SLAVE or I2C_SLAVE_FORCE.
+ *
+ * This client is ** NEVER REGISTERED ** with the driver model
+ * or I2C core code!! It just holds private copies of addressing
+ * information and maybe a PEC flag.
+ */
client = kzalloc(sizeof(*client), GFP_KERNEL);
if (!client) {
i2c_put_adapter(adap);
@@ -394,7 +463,6 @@ static int i2cdev_open(struct inode *inode, struct file *file)
snprintf(client->name, I2C_NAME_SIZE, "i2c-dev %d", adap->nr);
client->driver = &i2cdev_driver;
- /* registered with adapter, passed as client to user */
client->adapter = adap;
file->private_data = client;
@@ -422,6 +490,14 @@ static const struct file_operations i2cdev_fops = {
.release = i2cdev_release,
};
+/* ------------------------------------------------------------------------- */
+
+/*
+ * The legacy "i2cdev_driver" is used primarily to get notifications when
+ * I2C adapters are added or removed, so that each one gets an i2c_dev
+ * and is thus made available to userspace driver code.
+ */
+
static struct class *i2c_dev_class;
static int i2cdev_attach_adapter(struct i2c_adapter *adap)
@@ -486,6 +562,12 @@ static struct i2c_driver i2cdev_driver = {
.detach_client = i2cdev_detach_client,
};
+/* ------------------------------------------------------------------------- */
+
+/*
+ * module load/unload record keeping
+ */
+
static int __init i2c_dev_init(void)
{
int res;
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 8982c0932438..e445fe6e4ba9 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -152,9 +152,22 @@ config BLK_DEV_IDEDISK
If unsure, say Y.
config IDEDISK_MULTI_MODE
- bool "Use multi-mode by default"
- help
- If you get this error, try to say Y here:
+ bool "Use multiple sector mode for Programmed Input/Output by default"
+ help
+ This setting is irrelevant for most IDE disks, with direct memory
+ access, to which multiple sector mode does not apply. Multiple sector
+ mode is a feature of most modern IDE hard drives, permitting the
+ transfer of multiple sectors per Programmed Input/Output interrupt,
+ rather than the usual one sector per interrupt. When this feature is
+ enabled, it can reduce operating system overhead for disk Programmed
+ Input/Output. On some systems, it also can increase the data
+ throughput of Programmed Input/Output. Some drives, however, seemed
+ to run slower with multiple sector mode enabled. Some drives claimed
+ to support multiple sector mode, but lost data at some settings.
+ Under rare circumstances, such failures could result in massive
+ filesystem corruption.
+
+ If you get the following error, try to say Y here:
hda: set_multmode: status=0x51 { DriveReady SeekComplete Error }
hda: set_multmode: error=0x04 { DriveStatusError }
@@ -190,10 +203,6 @@ config BLK_DEV_IDECD
CD-ROM drive, you can say N to all other CD-ROM options, but be sure
to say Y or M to "ISO 9660 CD-ROM file system support".
- Note that older versions of LILO (LInux LOader) cannot properly deal
- with IDE/ATAPI CD-ROMs, so install LILO 16 or higher, available from
- <http://lilo.go.dyndns.org/>.
-
To compile this driver as a module, choose M here: the
module will be called ide-cd.
@@ -380,9 +389,10 @@ config IDEPCI_SHARE_IRQ
config IDEPCI_PCIBUS_ORDER
def_bool BLK_DEV_IDE=y && BLK_DEV_IDEPCI
+# TODO: split it on per host driver config options (or module parameters)
config BLK_DEV_OFFBOARD
bool "Boot off-board chipsets first support"
- depends on BLK_DEV_IDEPCI
+ depends on BLK_DEV_IDEPCI && (BLK_DEV_AEC62XX || BLK_DEV_GENERIC || BLK_DEV_HPT34X || BLK_DEV_HPT366 || BLK_DEV_PDC202XX_NEW || BLK_DEV_PDC202XX_OLD || BLK_DEV_TC86C001)
help
Normally, IDE controllers built into the motherboard (on-board
controllers) are assigned to ide0 and ide1 while those on add-in PCI
@@ -435,24 +445,6 @@ config BLK_DEV_IDEDMA_PCI
bool
select BLK_DEV_IDEPCI
-config BLK_DEV_IDEDMA_FORCED
- bool "Force enable legacy 2.0.X HOSTS to use DMA"
- depends on BLK_DEV_IDEDMA_PCI
- help
- This is an old piece of lost code from Linux 2.0 Kernels.
-
- Generally say N here.
-
-# TODO: remove it
-config IDEDMA_ONLYDISK
- bool "Enable DMA only for disks "
- depends on BLK_DEV_IDEDMA_PCI
- help
- This is used if you know your ATAPI Devices are going to fail DMA
- Transfers.
-
- Generally say N here.
-
config BLK_DEV_AEC62XX
tristate "AEC62XX chipset support"
select BLK_DEV_IDEDMA_PCI
@@ -1074,6 +1066,9 @@ endif
config BLK_DEV_IDEDMA
def_bool BLK_DEV_IDEDMA_PCI || BLK_DEV_IDEDMA_PMAC || BLK_DEV_IDEDMA_ICS || BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+config IDE_ARCH_OBSOLETE_INIT
+ def_bool ALPHA || (ARM && !ARCH_L7200) || BLACKFIN || X86 || IA64 || M32R || MIPS || PARISC || PPC || (SUPERH64 && BLK_DEV_IDEPCI) || SPARC
+
endif
config BLK_DEV_HD_ONLY
diff --git a/drivers/ide/arm/bast-ide.c b/drivers/ide/arm/bast-ide.c
index f7449d04114a..48db6167bb90 100644
--- a/drivers/ide/arm/bast-ide.c
+++ b/drivers/ide/arm/bast-ide.c
@@ -45,7 +45,7 @@ bastide_register(unsigned int base, unsigned int aux, int irq,
hw.io_ports[IDE_CONTROL_OFFSET] = aux + (6 * 0x20);
hw.irq = irq;
- ide_register_hw(&hw, 0, hwif);
+ ide_register_hw(&hw, NULL, 0, hwif);
return 0;
}
diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c
index bd1f5b670378..93f71fcfc04d 100644
--- a/drivers/ide/arm/icside.c
+++ b/drivers/ide/arm/icside.c
@@ -309,14 +309,6 @@ static int icside_dma_on(ide_drive_t *drive)
return 0;
}
-static int icside_dma_check(ide_drive_t *drive)
-{
- if (ide_tune_dma(drive))
- return 0;
-
- return -1;
-}
-
static int icside_dma_end(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
@@ -324,27 +316,29 @@ static int icside_dma_end(ide_drive_t *drive)
drive->waiting_for_dma = 0;
- disable_dma(hwif->hw.dma);
+ disable_dma(ECARD_DEV(state->dev)->dma);
/* Teardown mappings after DMA has completed. */
dma_unmap_sg(state->dev, hwif->sg_table, hwif->sg_nents,
hwif->sg_dma_direction);
- return get_dma_residue(hwif->hw.dma) != 0;
+ return get_dma_residue(ECARD_DEV(state->dev)->dma) != 0;
}
static void icside_dma_start(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
+ struct icside_state *state = hwif->hwif_data;
/* We can not enable DMA on both channels simultaneously. */
- BUG_ON(dma_channel_active(hwif->hw.dma));
- enable_dma(hwif->hw.dma);
+ BUG_ON(dma_channel_active(ECARD_DEV(state->dev)->dma));
+ enable_dma(ECARD_DEV(state->dev)->dma);
}
static int icside_dma_setup(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
+ struct icside_state *state = hwif->hwif_data;
struct request *rq = hwif->hwgroup->rq;
unsigned int dma_mode;
@@ -356,7 +350,7 @@ static int icside_dma_setup(ide_drive_t *drive)
/*
* We can not enable DMA on both channels.
*/
- BUG_ON(dma_channel_active(hwif->hw.dma));
+ BUG_ON(dma_channel_active(ECARD_DEV(state->dev)->dma));
icside_build_sglist(drive, rq);
@@ -373,14 +367,14 @@ static int icside_dma_setup(ide_drive_t *drive)
/*
* Select the correct timing for this drive.
*/
- set_dma_speed(hwif->hw.dma, drive->drive_data);
+ set_dma_speed(ECARD_DEV(state->dev)->dma, drive->drive_data);
/*
* Tell the DMA engine about the SG table and
* data direction.
*/
- set_dma_sg(hwif->hw.dma, hwif->sg_table, hwif->sg_nents);
- set_dma_mode(hwif->hw.dma, dma_mode);
+ set_dma_sg(ECARD_DEV(state->dev)->dma, hwif->sg_table, hwif->sg_nents);
+ set_dma_mode(ECARD_DEV(state->dev)->dma, dma_mode);
drive->waiting_for_dma = 1;
@@ -423,18 +417,13 @@ static void icside_dma_lost_irq(ide_drive_t *drive)
static void icside_dma_init(ide_hwif_t *hwif)
{
- printk(" %s: SG-DMA", hwif->name);
-
- hwif->atapi_dma = 1;
hwif->mwdma_mask = 7; /* MW0..2 */
hwif->swdma_mask = 7; /* SW0..2 */
hwif->dmatable_cpu = NULL;
hwif->dmatable_dma = 0;
hwif->set_dma_mode = icside_set_dma_mode;
- hwif->autodma = 1;
- hwif->ide_dma_check = icside_dma_check;
hwif->dma_host_off = icside_dma_host_off;
hwif->dma_off_quietly = icside_dma_off_quietly;
hwif->dma_host_on = icside_dma_host_on;
@@ -446,50 +435,21 @@ static void icside_dma_init(ide_hwif_t *hwif)
hwif->ide_dma_test_irq = icside_dma_test_irq;
hwif->dma_timeout = icside_dma_timeout;
hwif->dma_lost_irq = icside_dma_lost_irq;
-
- hwif->drives[0].autodma = hwif->autodma;
- hwif->drives[1].autodma = hwif->autodma;
-
- printk(" capable%s\n", hwif->autodma ? ", auto-enable" : "");
}
#else
#define icside_dma_init(hwif) (0)
#endif
-static ide_hwif_t *icside_find_hwif(unsigned long dataport)
-{
- ide_hwif_t *hwif;
- int index;
-
- for (index = 0; index < MAX_HWIFS; ++index) {
- hwif = &ide_hwifs[index];
- if (hwif->io_ports[IDE_DATA_OFFSET] == dataport)
- goto found;
- }
-
- for (index = 0; index < MAX_HWIFS; ++index) {
- hwif = &ide_hwifs[index];
- if (!hwif->io_ports[IDE_DATA_OFFSET])
- goto found;
- }
-
- hwif = NULL;
-found:
- return hwif;
-}
-
static ide_hwif_t *
icside_setup(void __iomem *base, struct cardinfo *info, struct expansion_card *ec)
{
unsigned long port = (unsigned long)base + info->dataoffset;
ide_hwif_t *hwif;
- hwif = icside_find_hwif(port);
+ hwif = ide_find_port(port);
if (hwif) {
int i;
- memset(&hwif->hw, 0, sizeof(hw_regs_t));
-
/*
* Ensure we're using MMIO
*/
@@ -497,13 +457,10 @@ icside_setup(void __iomem *base, struct cardinfo *info, struct expansion_card *e
hwif->mmio = 1;
for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
- hwif->hw.io_ports[i] = port;
hwif->io_ports[i] = port;
port += 1 << info->stepping;
}
- hwif->hw.io_ports[IDE_CONTROL_OFFSET] = (unsigned long)base + info->ctrloffset;
hwif->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)base + info->ctrloffset;
- hwif->hw.irq = ec->irq;
hwif->irq = ec->irq;
hwif->noprobe = 0;
hwif->chipset = ide_acorn;
@@ -518,6 +475,7 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec)
{
ide_hwif_t *hwif;
void __iomem *base;
+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0);
if (!base)
@@ -541,9 +499,9 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec)
state->hwif[0] = hwif;
- probe_hwif_init(hwif);
+ idx[0] = hwif->index;
- ide_proc_register_port(hwif);
+ ide_device_add(idx);
return 0;
}
@@ -555,6 +513,7 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
void __iomem *ioc_base, *easi_base;
unsigned int sel = 0;
int ret;
+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
ioc_base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
if (!ioc_base) {
@@ -610,7 +569,6 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
hwif->serialized = 1;
hwif->config_data = (unsigned long)ioc_base;
hwif->select_data = sel;
- hwif->hw.dma = ec->dma;
mate->maskproc = icside_maskproc;
mate->channel = 1;
@@ -619,18 +577,16 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
mate->serialized = 1;
mate->config_data = (unsigned long)ioc_base;
mate->select_data = sel | 1;
- mate->hw.dma = ec->dma;
if (ec->dma != NO_DMA && !request_dma(ec->dma, hwif->name)) {
icside_dma_init(hwif);
icside_dma_init(mate);
}
- probe_hwif_init(hwif);
- probe_hwif_init(mate);
+ idx[0] = hwif->index;
+ idx[1] = mate->index;
- ide_proc_register_port(hwif);
- ide_proc_register_port(mate);
+ ide_device_add(idx);
return 0;
diff --git a/drivers/ide/arm/ide_arm.c b/drivers/ide/arm/ide_arm.c
index bce2bec81413..8957cbadf5c2 100644
--- a/drivers/ide/arm/ide_arm.c
+++ b/drivers/ide/arm/ide_arm.c
@@ -31,5 +31,5 @@ void __init ide_arm_init(void)
memset(&hw, 0, sizeof(hw));
ide_std_init_ports(&hw, IDE_ARM_IO, IDE_ARM_IO + 0x206);
hw.irq = IDE_ARM_IRQ;
- ide_register_hw(&hw, 1, NULL);
+ ide_register_hw(&hw, NULL, 1, NULL);
}
diff --git a/drivers/ide/arm/rapide.c b/drivers/ide/arm/rapide.c
index 83811af11610..0775a3afef48 100644
--- a/drivers/ide/arm/rapide.c
+++ b/drivers/ide/arm/rapide.c
@@ -13,42 +13,25 @@
#include <asm/ecard.h>
-/*
- * Something like this really should be in generic code, but isn't.
- */
static ide_hwif_t *
rapide_locate_hwif(void __iomem *base, void __iomem *ctrl, unsigned int sz, int irq)
{
unsigned long port = (unsigned long)base;
- ide_hwif_t *hwif;
- int index, i;
-
- for (index = 0; index < MAX_HWIFS; ++index) {
- hwif = ide_hwifs + index;
- if (hwif->io_ports[IDE_DATA_OFFSET] == port)
- goto found;
- }
-
- for (index = 0; index < MAX_HWIFS; ++index) {
- hwif = ide_hwifs + index;
- if (hwif->io_ports[IDE_DATA_OFFSET] == 0)
- goto found;
- }
+ ide_hwif_t *hwif = ide_find_port(port);
+ int i;
- return NULL;
+ if (hwif == NULL)
+ goto out;
- found:
for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
- hwif->hw.io_ports[i] = port;
hwif->io_ports[i] = port;
port += sz;
}
- hwif->hw.io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl;
hwif->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl;
- hwif->hw.irq = hwif->irq = irq;
+ hwif->irq = irq;
hwif->mmio = 1;
default_hwif_mmiops(hwif);
-
+out:
return hwif;
}
@@ -58,6 +41,7 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
ide_hwif_t *hwif;
void __iomem *base;
int ret;
+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
ret = ecard_request_resources(ec);
if (ret)
@@ -74,8 +58,11 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
hwif->hwif_data = base;
hwif->gendev.parent = &ec->dev;
hwif->noprobe = 0;
- probe_hwif_init(hwif);
- ide_proc_register_port(hwif);
+
+ idx[0] = hwif->index;
+
+ ide_device_add(idx);
+
ecard_set_drvdata(ec, hwif);
goto out;
}
diff --git a/drivers/ide/cris/ide-cris.c b/drivers/ide/cris/ide-cris.c
index 2b4d2a0ae5c2..7f5bc2ee6c7e 100644
--- a/drivers/ide/cris/ide-cris.c
+++ b/drivers/ide/cris/ide-cris.c
@@ -664,7 +664,6 @@ cris_ide_inb(unsigned long reg)
return (unsigned char)cris_ide_inw(reg);
}
-static int cris_dma_check (ide_drive_t *drive);
static int cris_dma_end (ide_drive_t *drive);
static int cris_dma_setup (ide_drive_t *drive);
static void cris_dma_exec_cmd (ide_drive_t *drive, u8 command);
@@ -749,8 +748,7 @@ static void cris_set_dma_mode(ide_drive_t *drive, const u8 speed)
hold = ATA_DMA2_HOLD;
break;
default:
- BUG();
- break;
+ return;
}
if (speed >= XFER_UDMA_0)
@@ -783,7 +781,7 @@ init_e100_ide (void)
ide_offsets,
0, 0, cris_ide_ack_intr,
ide_default_irq(0));
- ide_register_hw(&hw, 1, &hwif);
+ ide_register_hw(&hw, NULL, 1, &hwif);
hwif->mmio = 1;
hwif->chipset = ide_etrax100;
hwif->set_pio_mode = &cris_set_pio_mode;
@@ -792,7 +790,6 @@ init_e100_ide (void)
hwif->ata_output_data = &cris_ide_output_data;
hwif->atapi_input_bytes = &cris_atapi_input_bytes;
hwif->atapi_output_bytes = &cris_atapi_output_bytes;
- hwif->ide_dma_check = &cris_dma_check;
hwif->ide_dma_end = &cris_dma_end;
hwif->dma_setup = &cris_dma_setup;
hwif->dma_exec_cmd = &cris_dma_exec_cmd;
@@ -807,12 +804,12 @@ init_e100_ide (void)
hwif->dma_host_on = &cris_dma_on;
hwif->dma_off_quietly = &cris_dma_off;
hwif->cbl = ATA_CBL_PATA40;
+ hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
hwif->pio_mask = ATA_PIO4,
+ hwif->drives[0].autotune = 1;
+ hwif->drives[1].autotune = 1;
hwif->ultra_mask = cris_ultra_mask;
hwif->mwdma_mask = 0x07; /* Multiword DMA 0-2 */
- hwif->autodma = 1;
- hwif->drives[0].autodma = 1;
- hwif->drives[1].autodma = 1;
}
/* Reset pulse */
@@ -937,10 +934,11 @@ static int cris_ide_build_dmatable (ide_drive_t *drive)
* than two possibly non-adjacent physical 4kB pages.
*/
/* group sequential buffers into one large buffer */
- addr = page_to_phys(sg->page) + sg->offset;
+ addr = sg_phys(sg);
size = sg_dma_len(sg);
- while (sg++, --i) {
- if ((addr + size) != page_to_phys(sg->page) + sg->offset)
+ while (--i) {
+ sg = sg_next(sg);
+ if ((addr + size) != sg_phys(sg))
break;
size += sg_dma_len(sg);
}
@@ -1017,14 +1015,6 @@ static ide_startstop_t cris_dma_intr (ide_drive_t *drive)
* the caller should revert to PIO for the current request.
*/
-static int cris_dma_check(ide_drive_t *drive)
-{
- if (ide_tune_dma(drive))
- return 0;
-
- return -1;
-}
-
static int cris_dma_end(ide_drive_t *drive)
{
drive->waiting_for_dma = 0;
diff --git a/drivers/ide/h8300/ide-h8300.c b/drivers/ide/h8300/ide-h8300.c
index 6d26ad7360d5..4a49b5c59acb 100644
--- a/drivers/ide/h8300/ide-h8300.c
+++ b/drivers/ide/h8300/ide-h8300.c
@@ -68,7 +68,6 @@ static inline void hw_setup(hw_regs_t *hw)
hw->io_ports[i] = CONFIG_H8300_IDE_BASE + H8300_IDE_GAP*i;
hw->io_ports[IDE_CONTROL_OFFSET] = CONFIG_H8300_IDE_ALT;
hw->irq = EXT_IRQ0 + CONFIG_H8300_IDE_IRQ;
- hw->dma = NO_DMA;
hw->chipset = ide_generic;
}
@@ -101,7 +100,7 @@ void __init h8300_ide_init(void)
hw_setup(&hw);
/* register if */
- idx = ide_register_hw(&hw, 1, &hwif);
+ idx = ide_register_hw(&hw, NULL, 1, &hwif);
if (idx == -1) {
printk(KERN_ERR "ide-h8300: IDE I/F register failed\n");
return;
diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c
index 1d5f6823101c..89df48fdc69d 100644
--- a/drivers/ide/ide-acpi.c
+++ b/drivers/ide/ide-acpi.c
@@ -350,7 +350,7 @@ static int taskfile_load_raw(ide_drive_t *drive,
memset(&args, 0, sizeof(ide_task_t));
args.command_type = IDE_DRIVE_TASK_NO_DATA;
- args.data_phase = TASKFILE_IN;
+ args.data_phase = TASKFILE_NO_DATA;
args.handler = &task_no_data_intr;
/* convert gtf to IDE Taskfile */
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index ca843522f91d..57a5f63d6ae3 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -120,7 +120,7 @@
* Reformat to match kernel tabbing style.
* Add CDROM_GET_UPC ioctl.
* 3.10 Apr 10, 1996 -- Fix compilation error with STANDARD_ATAPI.
- * 3.11 Apr 29, 1996 -- Patch from Heiko Eissfeldt <heiko@colossus.escape.de>
+ * 3.11 Apr 29, 1996 -- Patch from Heiko Eißfeldt <heiko@colossus.escape.de>
* to remove redundant verify_area calls.
* 3.12 May 7, 1996 -- Rudimentary changer support. Based on patches
* from Gerhard Zuber <zuber@berlin.snafu.de>.
@@ -256,7 +256,7 @@
* - Minimize the TOC reading - only do it when we
* know a media change has occurred.
* - Moved all the CDROMREADx ioctls to the Uniform layer.
- * - Heiko Eissfeldt <heiko@colossus.escape.de> supplied
+ * - Heiko Eißfeldt <heiko@colossus.escape.de> supplied
* some fixes for CDI.
* - CD-ROM leaving door locked fix from Andries
* Brouwer <Andries.Brouwer@cwi.nl>
@@ -2341,7 +2341,7 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
If we get an error for the regular case, we assume
a CDI without additional audio tracks. In this case
the readable TOC is empty (CDI tracks are not included)
- and only holds the Leadout entry. Heiko Eißfeldt */
+ and only holds the Leadout entry. Heiko Eißfeldt */
ntracks = 0;
stat = cdrom_read_tocentry(drive, CDROM_LEADOUT, 1, 0,
(char *)&toc->hdr,
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 4754769eda97..00123d99527a 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -169,7 +169,7 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
nsectors.all = (u16) rq->nr_sectors;
- if (hwif->no_lba48_dma && lba48 && dma) {
+ if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && lba48 && dma) {
if (block + rq->nr_sectors > 1ULL << 28)
dma = 0;
else
@@ -593,28 +593,12 @@ static int smart_enable(ide_drive_t *drive)
return ide_raw_taskfile(drive, &args, NULL);
}
-static int get_smart_values(ide_drive_t *drive, u8 *buf)
+static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd)
{
ide_task_t args;
memset(&args, 0, sizeof(ide_task_t));
- args.tfRegister[IDE_FEATURE_OFFSET] = SMART_READ_VALUES;
- args.tfRegister[IDE_NSECTOR_OFFSET] = 0x01;
- args.tfRegister[IDE_LCYL_OFFSET] = SMART_LCYL_PASS;
- args.tfRegister[IDE_HCYL_OFFSET] = SMART_HCYL_PASS;
- args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SMART;
- args.command_type = IDE_DRIVE_TASK_IN;
- args.data_phase = TASKFILE_IN;
- args.handler = &task_in_intr;
- (void) smart_enable(drive);
- return ide_raw_taskfile(drive, &args, buf);
-}
-
-static int get_smart_thresholds(ide_drive_t *drive, u8 *buf)
-{
- ide_task_t args;
- memset(&args, 0, sizeof(ide_task_t));
- args.tfRegister[IDE_FEATURE_OFFSET] = SMART_READ_THRESHOLDS;
+ args.tfRegister[IDE_FEATURE_OFFSET] = sub_cmd;
args.tfRegister[IDE_NSECTOR_OFFSET] = 0x01;
args.tfRegister[IDE_LCYL_OFFSET] = SMART_LCYL_PASS;
args.tfRegister[IDE_HCYL_OFFSET] = SMART_HCYL_PASS;
@@ -656,7 +640,7 @@ static int proc_idedisk_read_smart_thresholds
ide_drive_t *drive = (ide_drive_t *)data;
int len = 0, i = 0;
- if (!get_smart_thresholds(drive, page)) {
+ if (get_smart_data(drive, page, SMART_READ_THRESHOLDS) == 0) {
unsigned short *val = (unsigned short *) page;
char *out = ((char *)val) + (SECTOR_WORDS * 4);
page = out;
@@ -675,7 +659,7 @@ static int proc_idedisk_read_smart_values
ide_drive_t *drive = (ide_drive_t *)data;
int len = 0, i = 0;
- if (!get_smart_values(drive, page)) {
+ if (get_smart_data(drive, page, SMART_READ_VALUES) == 0) {
unsigned short *val = (unsigned short *) page;
char *out = ((char *)val) + (SECTOR_WORDS * 4);
page = out;
@@ -716,32 +700,6 @@ static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
rq->buffer = rq->cmd;
}
-static int idedisk_issue_flush(struct request_queue *q, struct gendisk *disk,
- sector_t *error_sector)
-{
- ide_drive_t *drive = q->queuedata;
- struct request *rq;
- int ret;
-
- if (!drive->wcache)
- return 0;
-
- rq = blk_get_request(q, WRITE, __GFP_WAIT);
-
- idedisk_prepare_flush(q, rq);
-
- ret = blk_execute_rq(q, disk, rq, 0);
-
- /*
- * if we failed and caller wants error offset, get it
- */
- if (ret && error_sector)
- *error_sector = ide_get_error_location(drive, rq->cmd);
-
- blk_put_request(rq);
- return ret;
-}
-
/*
* This is tightly woven into the driver->do_special can not touch.
* DON'T do it again until a total personality rewrite is committed.
@@ -781,7 +739,6 @@ static void update_ordered(ide_drive_t *drive)
struct hd_driveid *id = drive->id;
unsigned ordered = QUEUE_ORDERED_NONE;
prepare_flush_fn *prep_fn = NULL;
- issue_flush_fn *issue_fn = NULL;
if (drive->wcache) {
unsigned long long capacity;
@@ -805,13 +762,11 @@ static void update_ordered(ide_drive_t *drive)
if (barrier) {
ordered = QUEUE_ORDERED_DRAIN_FLUSH;
prep_fn = idedisk_prepare_flush;
- issue_fn = idedisk_issue_flush;
}
} else
ordered = QUEUE_ORDERED_DRAIN;
blk_queue_ordered(drive->queue, ordered, prep_fn);
- blk_queue_issue_flush_fn(drive->queue, issue_fn);
}
static int write_cache(ide_drive_t *drive, int arg)
@@ -885,7 +840,7 @@ static int set_lba_addressing(ide_drive_t *drive, int arg)
drive->addressing = 0;
- if (HWIF(drive)->no_lba48)
+ if (drive->hwif->host_flags & IDE_HFLAG_NO_LBA48)
return 0;
if (!idedisk_supports_lba48(drive->id))
@@ -918,6 +873,7 @@ static inline void idedisk_add_settings(ide_drive_t *drive) { ; }
static void idedisk_setup (ide_drive_t *drive)
{
+ ide_hwif_t *hwif = drive->hwif;
struct hd_driveid *id = drive->id;
unsigned long long capacity;
@@ -938,7 +894,6 @@ static void idedisk_setup (ide_drive_t *drive)
(void)set_lba_addressing(drive, 1);
if (drive->addressing == 1) {
- ide_hwif_t *hwif = HWIF(drive);
int max_s = 2048;
if (max_s > hwif->rqsize)
@@ -961,7 +916,7 @@ static void idedisk_setup (ide_drive_t *drive)
drive->capacity64 = 1ULL << 28;
}
- if (drive->hwif->no_lba48_dma && drive->addressing) {
+ if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && drive->addressing) {
if (drive->capacity64 > 1ULL << 28) {
printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode will"
" be used for accessing sectors > %u\n",
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index b453211ee0fc..e3add70b9cd8 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -280,7 +280,7 @@ int ide_build_dmatable (ide_drive_t *drive, struct request *rq)
}
}
- sg++;
+ sg = sg_next(sg);
i--;
}
@@ -338,35 +338,32 @@ static int config_drive_for_dma (ide_drive_t *drive)
ide_hwif_t *hwif = drive->hwif;
struct hd_driveid *id = drive->id;
- /* consult the list of known "bad" drives */
- if (__ide_dma_bad_drive(drive))
- return -1;
+ if (drive->media != ide_disk) {
+ if (hwif->host_flags & IDE_HFLAG_NO_ATAPI_DMA)
+ return 0;
+ }
- if (drive->media != ide_disk && hwif->atapi_dma == 0)
- return -1;
+ /*
+ * Enable DMA on any drive that has
+ * UltraDMA (mode 0/1/2/3/4/5/6) enabled
+ */
+ if ((id->field_valid & 4) && ((id->dma_ultra >> 8) & 0x7f))
+ return 1;
- if ((id->capability & 1) && drive->autodma) {
- /*
- * Enable DMA on any drive that has
- * UltraDMA (mode 0/1/2/3/4/5/6) enabled
- */
- if ((id->field_valid & 4) && ((id->dma_ultra >> 8) & 0x7f))
- return 0;
- /*
- * Enable DMA on any drive that has mode2 DMA
- * (multi or single) enabled
- */
- if (id->field_valid & 2) /* regular DMA */
- if ((id->dma_mword & 0x404) == 0x404 ||
- (id->dma_1word & 0x404) == 0x404)
- return 0;
+ /*
+ * Enable DMA on any drive that has mode2 DMA
+ * (multi or single) enabled
+ */
+ if (id->field_valid & 2) /* regular DMA */
+ if ((id->dma_mword & 0x404) == 0x404 ||
+ (id->dma_1word & 0x404) == 0x404)
+ return 1;
- /* Consult the list of known "good" drives */
- if (ide_dma_good_drive(drive))
- return 0;
- }
+ /* Consult the list of known "good" drives */
+ if (ide_dma_good_drive(drive))
+ return 1;
- return -1;
+ return 0;
}
/**
@@ -627,6 +624,8 @@ static int __ide_dma_test_irq(ide_drive_t *drive)
drive->name, __FUNCTION__);
return 0;
}
+#else
+static inline int config_drive_for_dma(ide_drive_t *drive) { return 0; }
#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
int __ide_dma_bad_drive (ide_drive_t *drive)
@@ -729,8 +728,10 @@ u8 ide_find_dma_mode(ide_drive_t *drive, u8 req_mode)
int x, i;
u8 mode = 0;
- if (drive->media != ide_disk && hwif->atapi_dma == 0)
- return 0;
+ if (drive->media != ide_disk) {
+ if (hwif->host_flags & IDE_HFLAG_NO_ATAPI_DMA)
+ return 0;
+ }
for (i = 0; i < ARRAY_SIZE(xfer_mode_bases); i++) {
if (req_mode < xfer_mode_bases[i])
@@ -751,24 +752,28 @@ u8 ide_find_dma_mode(ide_drive_t *drive, u8 req_mode)
mode = XFER_MW_DMA_1;
}
- printk(KERN_DEBUG "%s: selected mode 0x%x\n", drive->name, mode);
+ printk(KERN_DEBUG "%s: %s mode selected\n", drive->name,
+ mode ? ide_xfer_verbose(mode) : "no DMA");
return min(mode, req_mode);
}
EXPORT_SYMBOL_GPL(ide_find_dma_mode);
-int ide_tune_dma(ide_drive_t *drive)
+static int ide_tune_dma(ide_drive_t *drive)
{
u8 speed;
- if ((drive->id->capability & 1) == 0 || drive->autodma == 0)
+ if (noautodma || drive->nodma || (drive->id->capability & 1) == 0)
return 0;
/* consult the list of known "bad" drives */
if (__ide_dma_bad_drive(drive))
return 0;
+ if (drive->hwif->host_flags & IDE_HFLAG_TRUST_BIOS_FOR_DMA)
+ return config_drive_for_dma(drive);
+
speed = ide_max_dma_mode(drive);
if (!speed)
@@ -783,7 +788,22 @@ int ide_tune_dma(ide_drive_t *drive)
return 1;
}
-EXPORT_SYMBOL_GPL(ide_tune_dma);
+static int ide_dma_check(ide_drive_t *drive)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ int vdma = (hwif->host_flags & IDE_HFLAG_VDMA)? 1 : 0;
+
+ if (!vdma && ide_tune_dma(drive))
+ return 0;
+
+ /* TODO: always do PIO fallback */
+ if (hwif->host_flags & IDE_HFLAG_TRUST_BIOS_FOR_DMA)
+ return -1;
+
+ ide_set_max_pio(drive);
+
+ return vdma ? 0 : -1;
+}
void ide_dma_verbose(ide_drive_t *drive)
{
@@ -842,7 +862,7 @@ int ide_set_dma(ide_drive_t *drive)
ide_hwif_t *hwif = drive->hwif;
int rc;
- rc = hwif->ide_dma_check(drive);
+ rc = ide_dma_check(drive);
switch(rc) {
case -1: /* DMA needs to be disabled */
@@ -882,10 +902,7 @@ void ide_dma_timeout (ide_drive_t *drive)
EXPORT_SYMBOL(ide_dma_timeout);
-/*
- * Needed for allowing full modular support of ide-driver
- */
-static int ide_release_dma_engine(ide_hwif_t *hwif)
+static void ide_release_dma_engine(ide_hwif_t *hwif)
{
if (hwif->dmatable_cpu) {
pci_free_consistent(hwif->pci_dev,
@@ -894,7 +911,6 @@ static int ide_release_dma_engine(ide_hwif_t *hwif)
hwif->dmatable_dma);
hwif->dmatable_cpu = NULL;
}
- return 1;
}
static int ide_release_iomio_dma(ide_hwif_t *hwif)
@@ -937,12 +953,6 @@ static int ide_mapped_mmio_dma(ide_hwif_t *hwif, unsigned long base, unsigned in
{
printk(KERN_INFO " %s: MMIO-DMA ", hwif->name);
- hwif->dma_base = base;
-
- if(hwif->mate)
- hwif->dma_master = (hwif->channel) ? hwif->mate->dma_base : base;
- else
- hwif->dma_master = base;
return 0;
}
@@ -956,8 +966,6 @@ static int ide_iomio_dma(ide_hwif_t *hwif, unsigned long base, unsigned int port
return 1;
}
- hwif->dma_base = base;
-
if (hwif->cds->extra) {
hwif->extra_base = base + (hwif->channel ? 8 : 16);
@@ -972,10 +980,6 @@ static int ide_iomio_dma(ide_hwif_t *hwif, unsigned long base, unsigned int port
}
}
- if(hwif->mate)
- hwif->dma_master = (hwif->channel) ? hwif->mate->dma_base:base;
- else
- hwif->dma_master = base;
return 0;
}
@@ -987,12 +991,9 @@ static int ide_dma_iobase(ide_hwif_t *hwif, unsigned long base, unsigned int por
return ide_iomio_dma(hwif, base, ports);
}
-/*
- * This can be called for a dynamically installed interface. Don't __init it
- */
-void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_ports)
+void ide_setup_dma(ide_hwif_t *hwif, unsigned long base, unsigned num_ports)
{
- if (ide_dma_iobase(hwif, dma_base, num_ports))
+ if (ide_dma_iobase(hwif, base, num_ports))
return;
if (ide_allocate_dma_engine(hwif)) {
@@ -1000,6 +1001,13 @@ void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_p
return;
}
+ hwif->dma_base = base;
+
+ if (hwif->mate)
+ hwif->dma_master = hwif->channel ? hwif->mate->dma_base : base;
+ else
+ hwif->dma_master = base;
+
if (!(hwif->dma_command))
hwif->dma_command = hwif->dma_base;
if (!(hwif->dma_vendor1))
@@ -1019,8 +1027,6 @@ void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_p
hwif->ide_dma_on = &__ide_dma_on;
if (!hwif->dma_host_on)
hwif->dma_host_on = &ide_dma_host_on;
- if (!hwif->ide_dma_check)
- hwif->ide_dma_check = &config_drive_for_dma;
if (!hwif->dma_setup)
hwif->dma_setup = &ide_dma_setup;
if (!hwif->dma_exec_cmd)
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 4cece930114c..db22d1ff4e55 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -47,15 +47,15 @@
#include <linux/device.h>
#include <linux/kmod.h>
#include <linux/scatterlist.h>
+#include <linux/bitops.h>
#include <asm/byteorder.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <asm/io.h>
-#include <asm/bitops.h>
static int __ide_end_request(ide_drive_t *drive, struct request *rq,
- int uptodate, unsigned int nr_bytes)
+ int uptodate, unsigned int nr_bytes, int dequeue)
{
int ret = 1;
@@ -80,9 +80,11 @@ static int __ide_end_request(ide_drive_t *drive, struct request *rq,
if (!end_that_request_chunk(rq, uptodate, nr_bytes)) {
add_disk_randomness(rq->rq_disk);
- if (!list_empty(&rq->queuelist))
- blkdev_dequeue_request(rq);
- HWGROUP(drive)->rq = NULL;
+ if (dequeue) {
+ if (!list_empty(&rq->queuelist))
+ blkdev_dequeue_request(rq);
+ HWGROUP(drive)->rq = NULL;
+ }
end_that_request_last(rq, uptodate);
ret = 0;
}
@@ -122,7 +124,7 @@ int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors)
nr_bytes = rq->hard_cur_sectors << 9;
}
- ret = __ide_end_request(drive, rq, uptodate, nr_bytes);
+ ret = __ide_end_request(drive, rq, uptodate, nr_bytes, 1);
spin_unlock_irqrestore(&ide_lock, flags);
return ret;
@@ -219,11 +221,11 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
case ide_pm_restore_dma: /* Resume step 3 (restore DMA) */
/*
- * Right now, all we do is call hwif->ide_dma_check(drive),
+ * Right now, all we do is call ide_set_dma(drive),
* we could be smarter and check for current xfer_speed
* in struct drive etc...
*/
- if (drive->hwif->ide_dma_check == NULL)
+ if (drive->hwif->ide_dma_on == NULL)
break;
drive->hwif->dma_off_quietly(drive);
/*
@@ -255,39 +257,13 @@ int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq,
int uptodate, int nr_sectors)
{
unsigned long flags;
- int ret = 1;
+ int ret;
spin_lock_irqsave(&ide_lock, flags);
-
BUG_ON(!blk_rq_started(rq));
-
- /*
- * if failfast is set on a request, override number of sectors and
- * complete the whole request right now
- */
- if (blk_noretry_request(rq) && end_io_error(uptodate))
- nr_sectors = rq->hard_nr_sectors;
-
- if (!blk_fs_request(rq) && end_io_error(uptodate) && !rq->errors)
- rq->errors = -EIO;
-
- /*
- * decide whether to reenable DMA -- 3 is a random magic for now,
- * if we DMA timeout more than 3 times, just stay in PIO
- */
- if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) {
- drive->state = 0;
- HWGROUP(drive)->hwif->ide_dma_on(drive);
- }
-
- if (!end_that_request_first(rq, uptodate, nr_sectors)) {
- add_disk_randomness(rq->rq_disk);
- if (blk_rq_tagged(rq))
- blk_queue_end_tag(drive->queue, rq);
- end_that_request_last(rq, uptodate);
- ret = 0;
- }
+ ret = __ide_end_request(drive, rq, uptodate, nr_sectors << 9, 0);
spin_unlock_irqrestore(&ide_lock, flags);
+
return ret;
}
EXPORT_SYMBOL_GPL(ide_end_dequeued_request);
@@ -322,41 +298,6 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq)
spin_unlock_irqrestore(&ide_lock, flags);
}
-/*
- * FIXME: probably move this somewhere else, name is bad too :)
- */
-u64 ide_get_error_location(ide_drive_t *drive, char *args)
-{
- u32 high, low;
- u8 hcyl, lcyl, sect;
- u64 sector;
-
- high = 0;
- hcyl = args[5];
- lcyl = args[4];
- sect = args[3];
-
- if (ide_id_has_flush_cache_ext(drive->id)) {
- low = (hcyl << 16) | (lcyl << 8) | sect;
- HWIF(drive)->OUTB(drive->ctl|0x80, IDE_CONTROL_REG);
- high = ide_read_24(drive);
- } else {
- u8 cur = HWIF(drive)->INB(IDE_SELECT_REG);
- if (cur & 0x40) {
- high = cur & 0xf;
- low = (hcyl << 16) | (lcyl << 8) | sect;
- } else {
- low = hcyl * drive->head * drive->sect;
- low += lcyl * drive->sect;
- low += sect - 1;
- }
- }
-
- sector = ((u64) high << 24) | low;
- return sector;
-}
-EXPORT_SYMBOL(ide_get_error_location);
-
/**
* ide_end_drive_cmd - end an explicit drive command
* @drive: command
@@ -399,6 +340,8 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
if (args) {
args[0] = stat;
args[1] = err;
+ /* be sure we're looking at the low order bits */
+ hwif->OUTB(drive->ctl & ~0x80, IDE_CONTROL_REG);
args[2] = hwif->INB(IDE_NSECTOR_REG);
args[3] = hwif->INB(IDE_SECTOR_REG);
args[4] = hwif->INB(IDE_LCYL_REG);
@@ -519,7 +462,8 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8
}
}
- if ((stat & DRQ_STAT) && rq_data_dir(rq) == READ && hwif->err_stops_fifo == 0)
+ if ((stat & DRQ_STAT) && rq_data_dir(rq) == READ &&
+ (hwif->host_flags & IDE_HFLAG_ERROR_STOPS_FIFO) == 0)
try_to_flush_leftover_data(drive);
if (rq->errors >= ERROR_MAX || blk_noretry_request(rq)) {
@@ -712,7 +656,8 @@ static ide_startstop_t drive_cmd_intr (ide_drive_t *drive)
int retries = 10;
local_irq_enable_in_hardirq();
- if ((stat & DRQ_STAT) && args && args[3]) {
+ if (rq->cmd_type == REQ_TYPE_ATA_CMD &&
+ (stat & DRQ_STAT) && args && args[3]) {
u8 io_32bit = drive->io_32bit;
drive->io_32bit = 0;
hwif->ata_input_data(drive, &args[4], args[3] * SECTOR_WORDS);
@@ -834,7 +779,20 @@ static ide_startstop_t do_special (ide_drive_t *drive)
s->b.set_tune = 0;
if (set_pio_mode_abuse(drive->hwif, req_pio)) {
- if (hwif->set_pio_mode)
+
+ if (hwif->set_pio_mode == NULL)
+ return ide_stopped;
+
+ /*
+ * take ide_lock for drive->[no_]unmask/[no_]io_32bit
+ */
+ if (req_pio == 8 || req_pio == 9) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&ide_lock, flags);
+ hwif->set_pio_mode(drive, req_pio);
+ spin_unlock_irqrestore(&ide_lock, flags);
+ } else
hwif->set_pio_mode(drive, req_pio);
} else {
int keep_dma = drive->using_dma;
@@ -881,7 +839,8 @@ void ide_init_sg_cmd(ide_drive_t *drive, struct request *rq)
ide_hwif_t *hwif = drive->hwif;
hwif->nsect = hwif->nleft = rq->nr_sectors;
- hwif->cursg = hwif->cursg_ofs = 0;
+ hwif->cursg_ofs = 0;
+ hwif->cursg = NULL;
}
EXPORT_SYMBOL_GPL(ide_init_sg_cmd);
@@ -926,7 +885,6 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
return do_rw_taskfile(drive, args);
} else if (rq->cmd_type == REQ_TYPE_ATA_TASK) {
u8 *args = rq->buffer;
- u8 sel;
if (!args)
goto done;
@@ -944,10 +902,7 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
hwif->OUTB(args[3], IDE_SECTOR_REG);
hwif->OUTB(args[4], IDE_LCYL_REG);
hwif->OUTB(args[5], IDE_HCYL_REG);
- sel = (args[6] & ~0x10);
- if (drive->select.b.unit)
- sel |= 0x10;
- hwif->OUTB(sel, IDE_SELECT_REG);
+ hwif->OUTB((args[6] & 0xEF)|drive->select.all, IDE_SELECT_REG);
ide_cmd(drive, args[0], args[2], &drive_cmd_intr);
return ide_started;
} else if (rq->cmd_type == REQ_TYPE_ATA_CMD) {
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index aa738833bed5..e17a9ee120ea 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -403,8 +403,12 @@ void ide_fix_driveid (struct hd_driveid *id)
#endif
}
-/* FIXME: exported for use by the USB storage (isd200.c) code only */
-EXPORT_SYMBOL(ide_fix_driveid);
+/*
+ * ide_fixstring() cleans up and (optionally) byte-swaps a text string,
+ * removing leading/trailing blanks and compressing internal blanks.
+ * It is primarily used to tidy up the model name/number fields as
+ * returned by the WIN_[P]IDENTIFY commands.
+ */
void ide_fixstring (u8 *s, const int bytecount, const int byteswap)
{
@@ -582,9 +586,12 @@ EXPORT_SYMBOL_GPL(ide_in_drive_list);
/*
* Early UDMA66 devices don't set bit14 to 1, only bit13 is valid.
* We list them here and depend on the device side cable detection for them.
+ *
+ * Some optical devices with the buggy firmwares have the same problem.
*/
static const struct drive_list_entry ivb_list[] = {
{ "QUANTUM FIREBALLlct10 05" , "A03.0900" },
+ { "TSSTcorp CDDVDW SH-S202J" , "SB00" },
{ NULL , NULL }
};
@@ -693,35 +700,16 @@ static u8 ide_auto_reduce_xfer (ide_drive_t *drive)
}
#endif /* CONFIG_BLK_DEV_IDEDMA */
-/*
- * Update the
- */
-int ide_driveid_update (ide_drive_t *drive)
+int ide_driveid_update(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct hd_driveid *id;
-#if 0
- id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC);
- if (!id)
- return 0;
-
- taskfile_lib_get_identify(drive, (char *)&id);
+ unsigned long timeout, flags;
- ide_fix_driveid(id);
- if (id) {
- drive->id->dma_ultra = id->dma_ultra;
- drive->id->dma_mword = id->dma_mword;
- drive->id->dma_1word = id->dma_1word;
- /* anything more ? */
- kfree(id);
- }
- return 1;
-#else
/*
* Re-read drive->id for possible DMA mode
* change (copied from ide-probe.c)
*/
- unsigned long timeout, flags;
SELECT_MASK(drive, 1);
if (IDE_CONTROL_REG)
@@ -763,7 +751,6 @@ int ide_driveid_update (ide_drive_t *drive)
}
return 1;
-#endif
}
int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
@@ -776,7 +763,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
// msleep(50);
#ifdef CONFIG_BLK_DEV_IDEDMA
- if (hwif->ide_dma_check) /* check if host supports DMA */
+ if (hwif->ide_dma_on) /* check if host supports DMA */
hwif->dma_host_off(drive);
#endif
@@ -830,7 +817,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
#ifdef CONFIG_BLK_DEV_IDEDMA
if (speed >= XFER_SW_DMA_0)
hwif->dma_host_on(drive);
- else if (hwif->ide_dma_check) /* check if host supports DMA */
+ else if (hwif->ide_dma_on) /* check if host supports DMA */
hwif->dma_off_quietly(drive);
#endif
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
index 0e2562f0f74e..1609b8604f56 100644
--- a/drivers/ide/ide-lib.c
+++ b/drivers/ide/ide-lib.c
@@ -96,21 +96,6 @@ static u8 ide_rate_filter(ide_drive_t *drive, u8 speed)
return min(speed, mode);
}
-int ide_use_fast_pio(ide_drive_t *drive)
-{
- struct hd_driveid *id = drive->id;
-
- if ((id->capability & 1) && drive->autodma)
- return 1;
-
- if ((id->capability & 8) || (id->field_valid & 2))
- return 1;
-
- return 0;
-}
-
-EXPORT_SYMBOL_GPL(ide_use_fast_pio);
-
/*
* Standard (generic) timings for PIO modes, from ATA2 specification.
* These timings are for access to the IDE data port register *only*.
@@ -529,6 +514,7 @@ static u8 ide_dump_ata_status(ide_drive_t *drive, const char *msg, u8 stat)
if (drive->addressing == 1) {
__u64 sectors = 0;
u32 low = 0, high = 0;
+ hwif->OUTB(drive->ctl&~0x80, IDE_CONTROL_REG);
low = ide_read_24(drive);
hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG);
high = ide_read_24(drive);
diff --git a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c
index 2b8009c50e91..e245521af7b5 100644
--- a/drivers/ide/ide-pnp.c
+++ b/drivers/ide/ide-pnp.c
@@ -40,9 +40,8 @@ static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id
ide_std_init_ports(&hw, pnp_port_start(dev, 0),
pnp_port_start(dev, 1));
hw.irq = pnp_irq(dev, 0);
- hw.dma = NO_DMA;
- index = ide_register_hw(&hw, 1, &hwif);
+ index = ide_register_hw(&hw, NULL, 1, &hwif);
if (index != -1) {
printk(KERN_INFO "ide%d: generic PnP IDE interface\n", index);
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index d1011712601c..56fb0b843429 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -47,6 +47,7 @@
#include <linux/spinlock.h>
#include <linux/kmod.h>
#include <linux/pci.h>
+#include <linux/scatterlist.h>
#include <asm/byteorder.h>
#include <asm/irq.h>
@@ -171,11 +172,12 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
ide_fixstring(id->fw_rev, sizeof(id->fw_rev), bswap);
ide_fixstring(id->serial_no, sizeof(id->serial_no), bswap);
+ /* we depend on this a lot! */
+ id->model[sizeof(id->model)-1] = '\0';
+
if (strstr(id->model, "E X A B Y T E N E S T"))
goto err_misc;
- /* we depend on this a lot! */
- id->model[sizeof(id->model)-1] = '\0';
printk("%s: %s, ", drive->name, id->model);
drive->present = 1;
drive->dead = 0;
@@ -717,7 +719,7 @@ EXPORT_SYMBOL_GPL(ide_undecoded_slave);
* This routine only knows how to look for drive units 0 and 1
* on an interface, so any setting of MAX_DRIVES > 2 won't work here.
*/
-static void probe_hwif(ide_hwif_t *hwif, void (*fixup)(ide_hwif_t *hwif))
+static void probe_hwif(ide_hwif_t *hwif)
{
unsigned long flags;
unsigned int irqd;
@@ -819,8 +821,8 @@ static void probe_hwif(ide_hwif_t *hwif, void (*fixup)(ide_hwif_t *hwif))
return;
}
- if (fixup)
- fixup(hwif);
+ if (hwif->fixup)
+ hwif->fixup(hwif);
for (unit = 0; unit < MAX_DRIVES; ++unit) {
ide_drive_t *drive = &hwif->drives[unit];
@@ -835,16 +837,7 @@ static void probe_hwif(ide_hwif_t *hwif, void (*fixup)(ide_hwif_t *hwif))
drive->nice1 = 1;
- /*
- * MAJOR HACK BARF :-/
- *
- * FIXME: chipsets own this cruft!
- */
- /*
- * Move here to prevent module loading clashing.
- */
- // drive->autodma = hwif->autodma;
- if (hwif->ide_dma_check) {
+ if (hwif->ide_dma_on) {
/*
* Force DMAing for the beginning of the check.
* Some chipsets appear to do interesting
@@ -852,10 +845,7 @@ static void probe_hwif(ide_hwif_t *hwif, void (*fixup)(ide_hwif_t *hwif))
* PARANOIA!!!
*/
hwif->dma_off_quietly(drive);
-#ifdef CONFIG_IDEDMA_ONLYDISK
- if (drive->media == ide_disk)
-#endif
- ide_set_dma(drive);
+ ide_set_dma(drive);
}
}
}
@@ -871,10 +861,11 @@ static void probe_hwif(ide_hwif_t *hwif, void (*fixup)(ide_hwif_t *hwif))
}
static int hwif_init(ide_hwif_t *hwif);
+static void hwif_register_devices(ide_hwif_t *hwif);
-int probe_hwif_init_with_fixup(ide_hwif_t *hwif, void (*fixup)(ide_hwif_t *hwif))
+static int probe_hwif_init(ide_hwif_t *hwif)
{
- probe_hwif(hwif, fixup);
+ probe_hwif(hwif);
if (!hwif_init(hwif)) {
printk(KERN_INFO "%s: failed to initialize IDE interface\n",
@@ -882,34 +873,12 @@ int probe_hwif_init_with_fixup(ide_hwif_t *hwif, void (*fixup)(ide_hwif_t *hwif)
return -1;
}
- if (hwif->present) {
- u16 unit = 0;
- int ret;
+ if (hwif->present)
+ hwif_register_devices(hwif);
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- ide_drive_t *drive = &hwif->drives[unit];
- /* For now don't attach absent drives, we may
- want them on default or a new "empty" class
- for hotplug reprobing ? */
- if (drive->present) {
- ret = device_register(&drive->gendev);
- if (ret < 0)
- printk(KERN_WARNING "IDE: %s: "
- "device_register error: %d\n",
- __FUNCTION__, ret);
- }
- }
- }
return 0;
}
-int probe_hwif_init(ide_hwif_t *hwif)
-{
- return probe_hwif_init_with_fixup(hwif, NULL);
-}
-
-EXPORT_SYMBOL(probe_hwif_init);
-
#if MAX_HWIFS > 1
/*
* save_match() is used to simplify logic in init_irq() below.
@@ -963,7 +932,8 @@ static int ide_init_queue(ide_drive_t *drive)
blk_queue_segment_boundary(q, 0xffff);
if (!hwif->rqsize) {
- if (hwif->no_lba48 || hwif->no_lba48_dma)
+ if ((hwif->host_flags & IDE_HFLAG_NO_LBA48) ||
+ (hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA))
hwif->rqsize = 256;
else
hwif->rqsize = 65536;
@@ -1355,6 +1325,8 @@ static int hwif_init(ide_hwif_t *hwif)
printk(KERN_ERR "%s: unable to allocate SG table.\n", hwif->name);
goto out;
}
+
+ sg_init_table(hwif->sg_table, hwif->sg_max_nents);
if (init_irq(hwif) == 0)
goto done;
@@ -1390,6 +1362,24 @@ out:
return 0;
}
+static void hwif_register_devices(ide_hwif_t *hwif)
+{
+ unsigned int i;
+
+ for (i = 0; i < MAX_DRIVES; i++) {
+ ide_drive_t *drive = &hwif->drives[i];
+
+ if (drive->present) {
+ int ret = device_register(&drive->gendev);
+
+ if (ret < 0)
+ printk(KERN_WARNING "IDE: %s: "
+ "device_register error: %d\n",
+ __FUNCTION__, ret);
+ }
+ }
+}
+
int ideprobe_init (void)
{
unsigned int index;
@@ -1401,27 +1391,18 @@ int ideprobe_init (void)
for (index = 0; index < MAX_HWIFS; ++index)
if (probe[index])
- probe_hwif(&ide_hwifs[index], NULL);
+ probe_hwif(&ide_hwifs[index]);
for (index = 0; index < MAX_HWIFS; ++index)
if (probe[index])
hwif_init(&ide_hwifs[index]);
for (index = 0; index < MAX_HWIFS; ++index) {
if (probe[index]) {
ide_hwif_t *hwif = &ide_hwifs[index];
- int unit;
if (!hwif->present)
continue;
if (hwif->chipset == ide_unknown || hwif->chipset == ide_forced)
hwif->chipset = ide_generic;
- for (unit = 0; unit < MAX_DRIVES; ++unit)
- if (hwif->drives[unit].present) {
- int ret = device_register(
- &hwif->drives[unit].gendev);
- if (ret < 0)
- printk(KERN_WARNING "IDE: %s: "
- "device_register error: %d\n",
- __FUNCTION__, ret);
- }
+ hwif_register_devices(hwif);
}
}
for (index = 0; index < MAX_HWIFS; ++index)
@@ -1431,3 +1412,22 @@ int ideprobe_init (void)
}
EXPORT_SYMBOL_GPL(ideprobe_init);
+
+int ide_device_add(u8 idx[4])
+{
+ int i, rc = 0;
+
+ for (i = 0; i < 4; i++) {
+ if (idx[i] != 0xff)
+ rc |= probe_hwif_init(&ide_hwifs[idx[i]]);
+ }
+
+ for (i = 0; i < 4; i++) {
+ if (idx[i] != 0xff)
+ ide_proc_register_port(&ide_hwifs[idx[i]]);
+ }
+
+ return rc;
+}
+
+EXPORT_SYMBOL_GPL(ide_device_add);
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index fc1d8ae6a803..a4007d30da52 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -804,8 +804,6 @@ void ide_proc_register_port(ide_hwif_t *hwif)
create_proc_ide_drives(hwif);
}
-EXPORT_SYMBOL_GPL(ide_proc_register_port);
-
#ifdef CONFIG_BLK_DEV_IDEPCI
void ide_pci_create_host_proc(const char *name, get_info_t *get_info)
{
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index 1fa57947bca0..7b9181b5469d 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -565,7 +565,7 @@ typedef struct os_dat_s {
* The following parameter is used to select the point in the internal
* tape fifo in which we will start to refill the buffer. Decreasing
* the following parameter will improve the system's latency and
- * interactive response, while using a high value might improve sytem
+ * interactive response, while using a high value might improve system
* throughput.
*/
#define IDETAPE_FIFO_THRESHOLD 2
@@ -621,7 +621,6 @@ typedef struct os_dat_s {
*/
#define USE_IOTRACE 0
#if USE_IOTRACE
-#include <linux/io_trace.h>
#define IO_IDETAPE_FIFO 500
#endif
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index aa06dafb74ac..2b60f1b0437e 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -8,23 +8,6 @@
* Copyright (C) 2003-2004 Bartlomiej Zolnierkiewicz
*
* The big the bad and the ugly.
- *
- * Problems to be fixed because of BH interface or the lack therefore.
- *
- * Fill me in stupid !!!
- *
- * HOST:
- * General refers to the Controller and Driver "pair".
- * DATA HANDLER:
- * Under the context of Linux it generally refers to an interrupt handler.
- * However, it correctly describes the 'HOST'
- * DATA BLOCK:
- * The amount of data needed to be transfered as predefined in the
- * setup of the device.
- * STORAGE ATOMIC:
- * The 'DATA BLOCK' associated to the 'DATA HANDLER', and can be as
- * small as a single sector or as large as the entire command block
- * request.
*/
#include <linux/module.h>
@@ -45,6 +28,7 @@
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/bitops.h>
+#include <linux/scatterlist.h>
#include <asm/byteorder.h>
#include <asm/irq.h>
@@ -263,6 +247,7 @@ static void ide_pio_sector(ide_drive_t *drive, unsigned int write)
{
ide_hwif_t *hwif = drive->hwif;
struct scatterlist *sg = hwif->sg_table;
+ struct scatterlist *cursg = hwif->cursg;
struct page *page;
#ifdef CONFIG_HIGHMEM
unsigned long flags;
@@ -270,8 +255,14 @@ static void ide_pio_sector(ide_drive_t *drive, unsigned int write)
unsigned int offset;
u8 *buf;
- page = sg[hwif->cursg].page;
- offset = sg[hwif->cursg].offset + hwif->cursg_ofs * SECTOR_SIZE;
+ cursg = hwif->cursg;
+ if (!cursg) {
+ cursg = sg;
+ hwif->cursg = sg;
+ }
+
+ page = sg_page(cursg);
+ offset = cursg->offset + hwif->cursg_ofs * SECTOR_SIZE;
/* get the current page and offset */
page = nth_page(page, (offset >> PAGE_SHIFT));
@@ -285,8 +276,8 @@ static void ide_pio_sector(ide_drive_t *drive, unsigned int write)
hwif->nleft--;
hwif->cursg_ofs++;
- if ((hwif->cursg_ofs * SECTOR_SIZE) == sg[hwif->cursg].length) {
- hwif->cursg++;
+ if ((hwif->cursg_ofs * SECTOR_SIZE) == cursg->length) {
+ hwif->cursg = sg_next(hwif->cursg);
hwif->cursg_ofs = 0;
}
@@ -367,6 +358,8 @@ static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq,
static void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat)
{
+ HWIF(drive)->cursg = NULL;
+
if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
ide_task_t *task = rq->special;
@@ -478,6 +471,7 @@ static int ide_diag_taskfile(ide_drive_t *drive, ide_task_t *args, unsigned long
struct request rq;
memset(&rq, 0, sizeof(rq));
+ rq.ref_count = 1;
rq.cmd_type = REQ_TYPE_ATA_TASKFILE;
rq.buffer = buf;
@@ -518,6 +512,7 @@ int ide_raw_taskfile (ide_drive_t *drive, ide_task_t *args, u8 *buf)
EXPORT_SYMBOL(ide_raw_taskfile);
+#ifdef CONFIG_IDE_TASK_IOCTL
int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
{
ide_task_request_t *req_task;
@@ -667,6 +662,7 @@ abort:
return err;
}
+#endif
int ide_wait_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, u8 feature, u8 sectors, u8 *buf)
{
@@ -685,9 +681,6 @@ int ide_wait_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, u8 feature, u8 sectors,
return ide_do_drive_cmd(drive, &rq, ide_wait);
}
-/*
- * FIXME : this needs to map into at taskfile. <andre@linux-ide.org>
- */
int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
{
int err = 0;
@@ -751,9 +744,6 @@ static int ide_wait_cmd_task(ide_drive_t *drive, u8 *buf)
return ide_do_drive_cmd(drive, &rq, ide_wait);
}
-/*
- * FIXME : this needs to map into at taskfile. <andre@linux-ide.org>
- */
int ide_task_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
{
void __user *p = (void __user *)arg;
@@ -850,9 +840,14 @@ ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task)
case TASKFILE_OUT_DMA:
case TASKFILE_IN_DMAQ:
case TASKFILE_IN_DMA:
- hwif->dma_setup(drive);
- hwif->dma_exec_cmd(drive, taskfile->command);
- hwif->dma_start(drive);
+ if (!drive->using_dma)
+ break;
+
+ if (!hwif->dma_setup(drive)) {
+ hwif->dma_exec_cmd(drive, taskfile->command);
+ hwif->dma_start(drive);
+ return ide_started;
+ }
break;
default:
@@ -866,7 +861,8 @@ ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task)
return task->prehandler(drive, task->rq);
}
ide_execute_command(drive, taskfile->command, task->handler, WAIT_WORSTCASE, NULL);
+ return ide_started;
}
- return ide_started;
+ return ide_stopped;
}
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 5c0e4078b5cb..674a65c1a130 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -100,8 +100,6 @@ static int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */
int noautodma = 0;
-EXPORT_SYMBOL(noautodma);
-
#ifdef CONFIG_BLK_DEV_IDEACPI
int ide_noacpi = 0;
int ide_noacpitfs = 1;
@@ -136,8 +134,6 @@ static void init_hwif_data(ide_hwif_t *hwif, unsigned int index)
hwif->bus_state = BUSSTATE_ON;
- hwif->atapi_dma = 0; /* disable all atapi dma */
-
init_completion(&hwif->gendev_rel_comp);
default_hwif_iops(hwif);
@@ -172,7 +168,6 @@ static void init_hwif_default(ide_hwif_t *hwif, unsigned int index)
ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, &hwif->irq);
- memcpy(&hwif->hw, &hw, sizeof(hw));
memcpy(hwif->io_ports, hw.io_ports, sizeof(hw.io_ports));
hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
@@ -218,7 +213,7 @@ static void __init init_ide_data (void)
init_hwif_data(hwif, index);
init_hwif_default(hwif, index);
#if !defined(CONFIG_PPC32) || !defined(CONFIG_PCI)
- hwif->irq = hwif->hw.irq =
+ hwif->irq =
ide_init_default_irq(hwif->io_ports[IDE_DATA_OFFSET]);
#endif
}
@@ -269,6 +264,30 @@ static int ide_system_bus_speed(void)
return system_bus_speed;
}
+ide_hwif_t * ide_find_port(unsigned long base)
+{
+ ide_hwif_t *hwif;
+ int i;
+
+ for (i = 0; i < MAX_HWIFS; i++) {
+ hwif = &ide_hwifs[i];
+ if (hwif->io_ports[IDE_DATA_OFFSET] == base)
+ goto found;
+ }
+
+ for (i = 0; i < MAX_HWIFS; i++) {
+ hwif = &ide_hwifs[i];
+ if (hwif->io_ports[IDE_DATA_OFFSET] == 0)
+ goto found;
+ }
+
+ hwif = NULL;
+found:
+ return hwif;
+}
+
+EXPORT_SYMBOL_GPL(ide_find_port);
+
static struct resource* hwif_request_region(ide_hwif_t *hwif,
unsigned long addr, int num)
{
@@ -381,7 +400,6 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
hwif->pio_mask = tmp_hwif->pio_mask;
- hwif->atapi_dma = tmp_hwif->atapi_dma;
hwif->ultra_mask = tmp_hwif->ultra_mask;
hwif->mwdma_mask = tmp_hwif->mwdma_mask;
hwif->swdma_mask = tmp_hwif->swdma_mask;
@@ -396,6 +414,8 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
hwif->cds = tmp_hwif->cds;
#endif
+ hwif->fixup = tmp_hwif->fixup;
+
hwif->set_pio_mode = tmp_hwif->set_pio_mode;
hwif->set_dma_mode = tmp_hwif->set_dma_mode;
hwif->mdma_filter = tmp_hwif->mdma_filter;
@@ -418,7 +438,6 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
hwif->dma_exec_cmd = tmp_hwif->dma_exec_cmd;
hwif->dma_start = tmp_hwif->dma_start;
hwif->ide_dma_end = tmp_hwif->ide_dma_end;
- hwif->ide_dma_check = tmp_hwif->ide_dma_check;
hwif->ide_dma_on = tmp_hwif->ide_dma_on;
hwif->dma_off_quietly = tmp_hwif->dma_off_quietly;
hwif->ide_dma_test_irq = tmp_hwif->ide_dma_test_irq;
@@ -443,7 +462,6 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
hwif->mmio = tmp_hwif->mmio;
hwif->rqsize = tmp_hwif->rqsize;
- hwif->no_lba48 = tmp_hwif->no_lba48;
#ifndef CONFIG_BLK_DEV_IDECS
hwif->irq = tmp_hwif->irq;
@@ -461,7 +479,6 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
hwif->select_data = tmp_hwif->select_data;
hwif->extra_base = tmp_hwif->extra_base;
hwif->extra_ports = tmp_hwif->extra_ports;
- hwif->autodma = tmp_hwif->autodma;
hwif->hwif_data = tmp_hwif->hwif_data;
}
@@ -660,7 +677,6 @@ void ide_setup_ports ( hw_regs_t *hw,
}
}
hw->irq = irq;
- hw->dma = NO_DMA;
hw->ack_intr = ack_intr;
/*
* hw->iops = iops;
@@ -668,11 +684,11 @@ void ide_setup_ports ( hw_regs_t *hw,
}
/**
- * ide_register_hw_with_fixup - register IDE interface
+ * ide_register_hw - register IDE interface
* @hw: hardware registers
+ * @fixup: fixup function
* @initializing: set while initializing built-in drivers
* @hwifp: pointer to returned hwif
- * @fixup: fixup function
*
* Register an IDE interface, specifying exactly the registers etc.
* Set init=1 iff calling before probes have taken place.
@@ -680,9 +696,8 @@ void ide_setup_ports ( hw_regs_t *hw,
* Returns -1 on error.
*/
-int ide_register_hw_with_fixup(hw_regs_t *hw, int initializing,
- ide_hwif_t **hwifp,
- void(*fixup)(ide_hwif_t *hwif))
+int ide_register_hw(hw_regs_t *hw, void (*fixup)(ide_hwif_t *),
+ int initializing, ide_hwif_t **hwifp)
{
int index, retry = 1;
ide_hwif_t *hwif;
@@ -690,7 +705,7 @@ int ide_register_hw_with_fixup(hw_regs_t *hw, int initializing,
do {
for (index = 0; index < MAX_HWIFS; ++index) {
hwif = &ide_hwifs[index];
- if (hwif->hw.io_ports[IDE_DATA_OFFSET] == hw->io_ports[IDE_DATA_OFFSET])
+ if (hwif->io_ports[IDE_DATA_OFFSET] == hw->io_ports[IDE_DATA_OFFSET])
goto found;
}
for (index = 0; index < MAX_HWIFS; ++index) {
@@ -698,7 +713,7 @@ int ide_register_hw_with_fixup(hw_regs_t *hw, int initializing,
if (hwif->hold)
continue;
if ((!hwif->present && !hwif->mate && !initializing) ||
- (!hwif->hw.io_ports[IDE_DATA_OFFSET] && initializing))
+ (!hwif->io_ports[IDE_DATA_OFFSET] && initializing))
goto found;
}
for (index = 0; index < MAX_HWIFS; index++)
@@ -714,16 +729,18 @@ found:
}
if (hwif->present)
return -1;
- memcpy(&hwif->hw, hw, sizeof(*hw));
- memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->hw.io_ports));
+ memcpy(hwif->io_ports, hw->io_ports, sizeof(hwif->io_ports));
hwif->irq = hw->irq;
hwif->noprobe = 0;
+ hwif->fixup = fixup;
hwif->chipset = hw->chipset;
hwif->gendev.parent = hw->dev;
+ hwif->ack_intr = hw->ack_intr;
+
+ if (initializing == 0) {
+ u8 idx[4] = { index, 0xff, 0xff, 0xff };
- if (!initializing) {
- probe_hwif_init_with_fixup(hwif, fixup);
- ide_proc_register_port(hwif);
+ ide_device_add(idx);
}
if (hwifp)
@@ -732,13 +749,6 @@ found:
return (initializing || hwif->present) ? index : -1;
}
-EXPORT_SYMBOL(ide_register_hw_with_fixup);
-
-int ide_register_hw(hw_regs_t *hw, int initializing, ide_hwif_t **hwifp)
-{
- return ide_register_hw_with_fixup(hw, initializing, hwifp, NULL);
-}
-
EXPORT_SYMBOL(ide_register_hw);
/*
@@ -823,7 +833,7 @@ int set_using_dma(ide_drive_t *drive, int arg)
if (!drive->id || !(drive->id->capability & 1))
goto out;
- if (hwif->ide_dma_check == NULL)
+ if (hwif->ide_dma_on == NULL)
goto out;
err = -EBUSY;
@@ -1054,7 +1064,7 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
ide_init_hwif_ports(&hw, (unsigned long) args[0],
(unsigned long) args[1], NULL);
hw.irq = args[2];
- if (ide_register_hw(&hw, 0, NULL) == -1)
+ if (ide_register_hw(&hw, NULL, 0, NULL) == -1)
return -EIO;
return 0;
}
@@ -1276,7 +1286,7 @@ static int __init ide_setup(char *s)
if (!strcmp(s, "ide=nodma")) {
printk(" : Prevented DMA\n");
noautodma = 1;
- return 1;
+ goto obsolete_option;
}
#ifdef CONFIG_IDEPCI_PCIBUS_ORDER
@@ -1310,7 +1320,7 @@ static int __init ide_setup(char *s)
*/
if (s[0] == 'h' && s[1] == 'd' && s[2] >= 'a' && s[2] <= max_drive) {
const char *hd_words[] = {
- "none", "noprobe", "nowerr", "cdrom", "minus5",
+ "none", "noprobe", "nowerr", "cdrom", "nodma",
"autotune", "noautotune", "minus8", "swapdata", "bswap",
"noflush", "remap", "remap63", "scsi", NULL };
unit = s[2] - 'a';
@@ -1338,6 +1348,9 @@ static int __init ide_setup(char *s)
drive->ready_stat = 0;
hwif->noprobe = 0;
goto done;
+ case -5: /* nodma */
+ drive->nodma = 1;
+ goto done;
case -6: /* "autotune" */
drive->autotune = IDE_TUNE_AUTO;
goto obsolete_option;
@@ -1399,9 +1412,12 @@ static int __init ide_setup(char *s)
*/
static const char *ide_words[] = {
"noprobe", "serialize", "minus3", "minus4",
- "reset", "dma", "ata66", "minus8", "minus9",
+ "reset", "minus6", "ata66", "minus8", "minus9",
"minus10", "four", "qd65xx", "ht6560b", "cmd640_vlb",
"dtc2278", "umc8672", "ali14xx", NULL };
+
+ hw_regs_t hwregs;
+
hw = s[3] - '0';
hwif = &ide_hwifs[hw];
i = match_parm(&s[4], ide_words, vals, 3);
@@ -1478,6 +1494,7 @@ static int __init ide_setup(char *s)
case -10: /* minus10 */
case -9: /* minus9 */
case -8: /* minus8 */
+ case -6:
case -4:
case -3:
goto bad_option;
@@ -1492,9 +1509,6 @@ static int __init ide_setup(char *s)
#else
goto bad_hwif;
#endif
- case -6: /* dma */
- hwif->autodma = 1;
- goto obsolete_option;
case -5: /* "reset" */
hwif->reset = 1;
goto obsolete_option;
@@ -1513,9 +1527,9 @@ static int __init ide_setup(char *s)
case 2: /* base,ctl */
vals[2] = 0; /* default irq = probe for it */
case 3: /* base,ctl,irq */
- hwif->hw.irq = vals[2];
- ide_init_hwif_ports(&hwif->hw, (unsigned long) vals[0], (unsigned long) vals[1], &hwif->irq);
- memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
+ memset(&hwregs, 0, sizeof(hwregs));
+ ide_init_hwif_ports(&hwregs, vals[0], vals[1], &hwif->irq);
+ memcpy(hwif->io_ports, hwregs.io_ports, sizeof(hwif->io_ports));
hwif->irq = vals[2];
hwif->noprobe = 0;
hwif->chipset = ide_forced;
diff --git a/drivers/ide/legacy/ali14xx.c b/drivers/ide/legacy/ali14xx.c
index 2f0ef9b44033..10311ecc674a 100644
--- a/drivers/ide/legacy/ali14xx.c
+++ b/drivers/ide/legacy/ali14xx.c
@@ -102,6 +102,8 @@ static void outReg (u8 data, u8 reg)
outb_p(data, dataPort);
}
+static DEFINE_SPINLOCK(ali14xx_lock);
+
/*
* Set PIO mode for the specified drive.
* This function computes timing parameters
@@ -129,14 +131,14 @@ static void ali14xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
/* stuff timing parameters into controller registers */
driveNum = (HWIF(drive)->index << 1) + drive->select.b.unit;
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&ali14xx_lock, flags);
outb_p(regOn, basePort);
outReg(param1, regTab[driveNum].reg1);
outReg(param2, regTab[driveNum].reg2);
outReg(param3, regTab[driveNum].reg3);
outReg(param4, regTab[driveNum].reg4);
outb_p(regOff, basePort);
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&ali14xx_lock, flags);
}
/*
@@ -193,6 +195,7 @@ static int __init initRegisters (void) {
static int __init ali14xx_probe(void)
{
ide_hwif_t *hwif, *mate;
+ static u8 idx[4] = { 0, 1, 0xff, 0xff };
printk(KERN_DEBUG "ali14xx: base=0x%03x, regOn=0x%02x.\n",
basePort, regOn);
@@ -217,11 +220,7 @@ static int __init ali14xx_probe(void)
mate->mate = hwif;
mate->channel = 1;
- probe_hwif_init(hwif);
- probe_hwif_init(mate);
-
- ide_proc_register_port(hwif);
- ide_proc_register_port(mate);
+ ide_device_add(idx);
return 0;
}
diff --git a/drivers/ide/legacy/buddha.c b/drivers/ide/legacy/buddha.c
index 101aee1711c4..4a0be251a05f 100644
--- a/drivers/ide/legacy/buddha.c
+++ b/drivers/ide/legacy/buddha.c
@@ -212,8 +212,8 @@ fail_base2:
// xsurf_iops,
IRQ_AMIGA_PORTS);
}
-
- index = ide_register_hw(&hw, 1, &hwif);
+
+ index = ide_register_hw(&hw, NULL, 1, &hwif);
if (index != -1) {
hwif->mmio = 1;
printk("ide%d: ", index);
diff --git a/drivers/ide/legacy/dtc2278.c b/drivers/ide/legacy/dtc2278.c
index f16521254867..24a845d45bd2 100644
--- a/drivers/ide/legacy/dtc2278.c
+++ b/drivers/ide/legacy/dtc2278.c
@@ -67,20 +67,24 @@ static void sub22 (char b, char c)
}
}
+static DEFINE_SPINLOCK(dtc2278_lock);
+
static void dtc2278_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
unsigned long flags;
if (pio >= 3) {
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&dtc2278_lock, flags);
/*
* This enables PIO mode4 (3?) on the first interface
*/
sub22(1,0xc3);
sub22(0,0xa0);
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&dtc2278_lock, flags);
} else {
/* we don't know how to set it back again.. */
+ /* Actually we do - there is a data sheet available for the
+ Winbond but does anyone actually care */
}
/*
@@ -94,6 +98,7 @@ static int __init dtc2278_probe(void)
{
unsigned long flags;
ide_hwif_t *hwif, *mate;
+ static u8 idx[4] = { 0, 1, 0xff, 0xff };
hwif = &ide_hwifs[0];
mate = &ide_hwifs[1];
@@ -129,16 +134,13 @@ static int __init dtc2278_probe(void)
mate->serialized = 1;
mate->chipset = ide_dtc2278;
+ mate->pio_mask = ATA_PIO4;
mate->drives[0].no_unmask = 1;
mate->drives[1].no_unmask = 1;
mate->mate = hwif;
mate->channel = 1;
- probe_hwif_init(hwif);
- probe_hwif_init(mate);
-
- ide_proc_register_port(hwif);
- ide_proc_register_port(mate);
+ ide_device_add(idx);
return 0;
}
diff --git a/drivers/ide/legacy/falconide.c b/drivers/ide/legacy/falconide.c
index f0829b83e970..7d7936f1b900 100644
--- a/drivers/ide/legacy/falconide.c
+++ b/drivers/ide/legacy/falconide.c
@@ -72,7 +72,7 @@ void __init falconide_init(void)
0, 0, NULL,
// falconide_iops,
IRQ_MFP_IDE);
- index = ide_register_hw(&hw, 1, NULL);
+ index = ide_register_hw(&hw, NULL, 1, NULL);
if (index != -1)
printk("ide%d: Falcon IDE interface\n", index);
diff --git a/drivers/ide/legacy/gayle.c b/drivers/ide/legacy/gayle.c
index 0830a021bbb6..53331ee1e957 100644
--- a/drivers/ide/legacy/gayle.c
+++ b/drivers/ide/legacy/gayle.c
@@ -165,7 +165,7 @@ found:
// &gayle_iops,
IRQ_AMIGA_PORTS);
- index = ide_register_hw(&hw, 1, &hwif);
+ index = ide_register_hw(&hw, NULL, 1, &hwif);
if (index != -1) {
hwif->mmio = 1;
switch (i) {
diff --git a/drivers/ide/legacy/ht6560b.c b/drivers/ide/legacy/ht6560b.c
index 2e5a9cc5c0f7..a4245d13f11b 100644
--- a/drivers/ide/legacy/ht6560b.c
+++ b/drivers/ide/legacy/ht6560b.c
@@ -247,6 +247,8 @@ static u8 ht_pio2timings(ide_drive_t *drive, const u8 pio)
}
}
+static DEFINE_SPINLOCK(ht6560b_lock);
+
/*
* Enable/Disable so called prefetch mode
*/
@@ -254,9 +256,9 @@ static void ht_set_prefetch(ide_drive_t *drive, u8 state)
{
unsigned long flags;
int t = HT_PREFETCH_MODE << 8;
-
- spin_lock_irqsave(&ide_lock, flags);
-
+
+ spin_lock_irqsave(&ht6560b_lock, flags);
+
/*
* Prefetch mode and unmask irq seems to conflict
*/
@@ -268,9 +270,9 @@ static void ht_set_prefetch(ide_drive_t *drive, u8 state)
drive->drive_data &= ~t; /* disable prefetch mode */
drive->no_unmask = 0;
}
-
- spin_unlock_irqrestore(&ide_lock, flags);
-
+
+ spin_unlock_irqrestore(&ht6560b_lock, flags);
+
#ifdef DEBUG
printk("ht6560b: drive %s prefetch mode %sabled\n", drive->name, (state ? "en" : "dis"));
#endif
@@ -287,16 +289,14 @@ static void ht6560b_set_pio_mode(ide_drive_t *drive, const u8 pio)
ht_set_prefetch(drive, pio & 1);
return;
}
-
+
timing = ht_pio2timings(drive, pio);
-
- spin_lock_irqsave(&ide_lock, flags);
-
+
+ spin_lock_irqsave(&ht6560b_lock, flags);
drive->drive_data &= 0xff00;
drive->drive_data |= timing;
-
- spin_unlock_irqrestore(&ide_lock, flags);
-
+ spin_unlock_irqrestore(&ht6560b_lock, flags);
+
#ifdef DEBUG
printk("ht6560b: drive %s tuned to pio mode %#x timing=%#x\n", drive->name, pio, timing);
#endif
@@ -311,6 +311,7 @@ MODULE_PARM_DESC(probe, "probe for HT6560B chipset");
int __init ht6560b_init(void)
{
ide_hwif_t *hwif, *mate;
+ static u8 idx[4] = { 0, 1, 0xff, 0xff };
int t;
if (probe_ht6560b == 0)
@@ -359,11 +360,7 @@ int __init ht6560b_init(void)
mate->drives[0].drive_data = t;
mate->drives[1].drive_data = t;
- probe_hwif_init(hwif);
- probe_hwif_init(mate);
-
- ide_proc_register_port(hwif);
- ide_proc_register_port(mate);
+ ide_device_add(idx);
return 0;
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
index 4cdb519f9832..03715c058664 100644
--- a/drivers/ide/legacy/ide-cs.c
+++ b/drivers/ide/legacy/ide-cs.c
@@ -28,7 +28,7 @@
and other provisions required by the GPL. If you do not delete
the provisions above, a recipient may use your version of this
file under either the MPL or the GPL.
-
+
======================================================================*/
#include <linux/module.h>
@@ -153,7 +153,7 @@ static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq
hw.irq = irq;
hw.chipset = ide_pci;
hw.dev = &handle->dev;
- return ide_register_hw_with_fixup(&hw, 0, NULL, ide_undecoded_slave);
+ return ide_register_hw(&hw, &ide_undecoded_slave, 0, NULL);
}
/*======================================================================
@@ -327,13 +327,13 @@ failed:
After a card is removed, ide_release() will unregister the net
device, and release the PCMCIA configuration. If the device is
still open, this will be postponed until it is closed.
-
+
======================================================================*/
void ide_release(struct pcmcia_device *link)
{
ide_info_t *info = link->priv;
-
+
DEBUG(0, "ide_release(0x%p)\n", link);
if (info->ndev) {
@@ -353,11 +353,12 @@ void ide_release(struct pcmcia_device *link)
stuff to run after an event is received. A CARD_REMOVAL event
also sets some flags to discourage the ide drivers from
talking to the ports.
-
+
======================================================================*/
static struct pcmcia_device_id ide_ids[] = {
PCMCIA_DEVICE_FUNC_ID(4),
+ PCMCIA_DEVICE_MANF_CARD(0x0000, 0x0000), /* Corsair */
PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000), /* Hitachi */
PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000), /* I-O Data CFA */
PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001), /* Mitsubishi CFA */
@@ -366,7 +367,7 @@ static struct pcmcia_device_id ide_ids[] = {
PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000), /* Toshiba */
PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000), /* Samsung */
- PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000), /* Hitachi */
+ PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000), /* Hitachi */
PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001),
PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0100), /* Viking CFA */
PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200), /* Lexar, Viking CFA */
@@ -384,6 +385,7 @@ static struct pcmcia_device_id ide_ids[] = {
PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e),
PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae),
PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178),
+ PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420),
PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178),
PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753),
PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF8GB", 0x2e6d1829, 0xacbe682e),
diff --git a/drivers/ide/legacy/ide_platform.c b/drivers/ide/legacy/ide_platform.c
index b992b2b91fe2..7bb79f53dac8 100644
--- a/drivers/ide/legacy/ide_platform.c
+++ b/drivers/ide/legacy/ide_platform.c
@@ -33,39 +33,24 @@ static ide_hwif_t *__devinit plat_ide_locate_hwif(void __iomem *base,
int mmio)
{
unsigned long port = (unsigned long)base;
- ide_hwif_t *hwif;
- int index, i;
-
- for (index = 0; index < MAX_HWIFS; ++index) {
- hwif = ide_hwifs + index;
- if (hwif->io_ports[IDE_DATA_OFFSET] == port)
- goto found;
- }
-
- for (index = 0; index < MAX_HWIFS; ++index) {
- hwif = ide_hwifs + index;
- if (hwif->io_ports[IDE_DATA_OFFSET] == 0)
- goto found;
- }
+ ide_hwif_t *hwif = ide_find_port(port);
+ int i;
- return NULL;
-
-found:
+ if (hwif == NULL)
+ goto out;
- hwif->hw.io_ports[IDE_DATA_OFFSET] = port;
+ hwif->io_ports[IDE_DATA_OFFSET] = port;
port += (1 << pdata->ioport_shift);
for (i = IDE_ERROR_OFFSET; i <= IDE_STATUS_OFFSET;
i++, port += (1 << pdata->ioport_shift))
- hwif->hw.io_ports[i] = port;
+ hwif->io_ports[i] = port;
- hwif->hw.io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl;
+ hwif->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl;
- memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->hw.io_ports));
- hwif->hw.irq = hwif->irq = irq;
+ hwif->irq = irq;
- hwif->hw.dma = NO_DMA;
- hwif->chipset = hwif->hw.chipset = ide_generic;
+ hwif->chipset = ide_generic;
if (mmio) {
hwif->mmio = 1;
@@ -73,8 +58,8 @@ found:
}
hwif_prop.hwif = hwif;
- hwif_prop.index = index;
-
+ hwif_prop.index = hwif->index;
+out:
return hwif;
}
@@ -83,6 +68,7 @@ static int __devinit plat_ide_probe(struct platform_device *pdev)
struct resource *res_base, *res_alt, *res_irq;
ide_hwif_t *hwif;
struct pata_platform_info *pdata;
+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
int ret = 0;
int mmio = 0;
@@ -130,10 +116,11 @@ static int __devinit plat_ide_probe(struct platform_device *pdev)
hwif->gendev.parent = &pdev->dev;
hwif->noprobe = 0;
- probe_hwif_init(hwif);
+ idx[0] = hwif->index;
+
+ ide_device_add(idx);
platform_set_drvdata(pdev, hwif);
- ide_proc_register_port(hwif);
return 0;
diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c
index b557c45a5a9d..e87cd2f16430 100644
--- a/drivers/ide/legacy/macide.c
+++ b/drivers/ide/legacy/macide.c
@@ -93,21 +93,21 @@ void macide_init(void)
0, 0, macide_ack_intr,
// quadra_ide_iops,
IRQ_NUBUS_F);
- index = ide_register_hw(&hw, 1, &hwif);
+ index = ide_register_hw(&hw, NULL, 1, &hwif);
break;
case MAC_IDE_PB:
ide_setup_ports(&hw, IDE_BASE, macide_offsets,
0, 0, macide_ack_intr,
// macide_pb_iops,
IRQ_NUBUS_C);
- index = ide_register_hw(&hw, 1, &hwif);
+ index = ide_register_hw(&hw, NULL, 1, &hwif);
break;
case MAC_IDE_BABOON:
ide_setup_ports(&hw, BABOON_BASE, macide_offsets,
0, 0, NULL,
// macide_baboon_iops,
IRQ_BABOON_1);
- index = ide_register_hw(&hw, 1, &hwif);
+ index = ide_register_hw(&hw, NULL, 1, &hwif);
if (index == -1) break;
if (macintosh_config->ident == MAC_MODEL_PB190) {
diff --git a/drivers/ide/legacy/q40ide.c b/drivers/ide/legacy/q40ide.c
index e628a983ce33..a73db1bd482d 100644
--- a/drivers/ide/legacy/q40ide.c
+++ b/drivers/ide/legacy/q40ide.c
@@ -89,9 +89,8 @@ void q40_ide_setup_ports ( hw_regs_t *hw,
else
hw->io_ports[i] = Q40_ISA_IO_B(base + offsets[i]);
}
-
+
hw->irq = irq;
- hw->dma = NO_DMA;
hw->ack_intr = ack_intr;
/*
* hw->iops = iops;
@@ -102,7 +101,7 @@ void q40_ide_setup_ports ( hw_regs_t *hw,
/*
* the static array is needed to have the name reported in /proc/ioports,
- * hwif->name unfortunately isn´t available yet
+ * hwif->name unfortunately isn't available yet
*/
static const char *q40_ide_names[Q40IDE_NUM_HWIFS]={
"ide0", "ide1"
@@ -142,7 +141,7 @@ void q40ide_init(void)
0, NULL,
// m68kide_iops,
q40ide_default_irq(pcide_bases[i]));
- index = ide_register_hw(&hw, 1, &hwif);
+ index = ide_register_hw(&hw, NULL, 1, &hwif);
// **FIXME**
if (index != -1)
hwif->mmio = 1;
diff --git a/drivers/ide/legacy/qd65xx.c b/drivers/ide/legacy/qd65xx.c
index 0c81d2d0b941..912e73853faa 100644
--- a/drivers/ide/legacy/qd65xx.c
+++ b/drivers/ide/legacy/qd65xx.c
@@ -89,26 +89,6 @@
static int timings[4]={-1,-1,-1,-1}; /* stores current timing for each timer */
-static void qd_write_reg (u8 content, unsigned long reg)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&ide_lock, flags);
- outb(content,reg);
- spin_unlock_irqrestore(&ide_lock, flags);
-}
-
-static u8 __init qd_read_reg (unsigned long reg)
-{
- unsigned long flags;
- u8 read;
-
- spin_lock_irqsave(&ide_lock, flags);
- read = inb(reg);
- spin_unlock_irqrestore(&ide_lock, flags);
- return read;
-}
-
/*
* qd_select:
*
@@ -121,7 +101,7 @@ static void qd_select (ide_drive_t *drive)
(QD_TIMREG(drive) & 0x02);
if (timings[index] != QD_TIMING(drive))
- qd_write_reg(timings[index] = QD_TIMING(drive), QD_TIMREG(drive));
+ outb(timings[index] = QD_TIMING(drive), QD_TIMREG(drive));
}
/*
@@ -284,7 +264,7 @@ static void qd6580_set_pio_mode(ide_drive_t *drive, const u8 pio)
}
if (!HWIF(drive)->channel && drive->media != ide_disk) {
- qd_write_reg(0x5f, QD_CONTROL_PORT);
+ outb(0x5f, QD_CONTROL_PORT);
printk(KERN_WARNING "%s: ATAPI: disabled read-ahead FIFO "
"and post-write buffer on %s.\n",
drive->name, HWIF(drive)->name);
@@ -301,16 +281,15 @@ static void qd6580_set_pio_mode(ide_drive_t *drive, const u8 pio)
static int __init qd_testreg(int port)
{
- u8 savereg;
- u8 readreg;
unsigned long flags;
+ u8 savereg, readreg;
- spin_lock_irqsave(&ide_lock, flags);
+ local_irq_save(flags);
savereg = inb_p(port);
outb_p(QD_TESTVAL, port); /* safe value */
readreg = inb_p(port);
outb(savereg, port);
- spin_unlock_irqrestore(&ide_lock, flags);
+ local_irq_restore(flags);
if (savereg == QD_TESTVAL) {
printk(KERN_ERR "Outch ! the probe for qd65xx isn't reliable !\n");
@@ -364,13 +343,13 @@ static void __exit qd_unsetup(ide_hwif_t *hwif)
if (set_pio_mode == (void *)qd6500_set_pio_mode) {
// will do it for both
- qd_write_reg(QD6500_DEF_DATA, QD_TIMREG(&hwif->drives[0]));
+ outb(QD6500_DEF_DATA, QD_TIMREG(&hwif->drives[0]));
} else if (set_pio_mode == (void *)qd6580_set_pio_mode) {
if (QD_CONTROL(hwif) & QD_CONTR_SEC_DISABLED) {
- qd_write_reg(QD6580_DEF_DATA, QD_TIMREG(&hwif->drives[0]));
- qd_write_reg(QD6580_DEF_DATA2, QD_TIMREG(&hwif->drives[1]));
+ outb(QD6580_DEF_DATA, QD_TIMREG(&hwif->drives[0]));
+ outb(QD6580_DEF_DATA2, QD_TIMREG(&hwif->drives[1]));
} else {
- qd_write_reg(hwif->channel ? QD6580_DEF_DATA2 : QD6580_DEF_DATA, QD_TIMREG(&hwif->drives[0]));
+ outb(hwif->channel ? QD6580_DEF_DATA2 : QD6580_DEF_DATA, QD_TIMREG(&hwif->drives[0]));
}
} else {
printk(KERN_WARNING "Unknown qd65xx tuning fonction !\n");
@@ -389,10 +368,11 @@ static void __exit qd_unsetup(ide_hwif_t *hwif)
static int __init qd_probe(int base)
{
ide_hwif_t *hwif;
+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
u8 config;
u8 unit;
- config = qd_read_reg(QD_CONFIG_PORT);
+ config = inb(QD_CONFIG_PORT);
if (! ((config & QD_CONFIG_BASEPORT) >> 1 == (base == 0xb0)) )
return 1;
@@ -419,9 +399,9 @@ static int __init qd_probe(int base)
hwif->set_pio_mode = &qd6500_set_pio_mode;
- probe_hwif_init(hwif);
+ idx[0] = unit;
- ide_proc_register_port(hwif);
+ ide_device_add(idx);
return 1;
}
@@ -436,7 +416,7 @@ static int __init qd_probe(int base)
/* qd6580 found */
- control = qd_read_reg(QD_CONTROL_PORT);
+ control = inb(QD_CONTROL_PORT);
printk(KERN_NOTICE "qd6580 at %#x\n", base);
printk(KERN_DEBUG "qd6580: config=%#x, control=%#x, ID3=%u\n",
@@ -453,11 +433,11 @@ static int __init qd_probe(int base)
hwif->set_pio_mode = &qd6580_set_pio_mode;
- probe_hwif_init(hwif);
+ idx[0] = unit;
- qd_write_reg(QD_DEF_CONTR,QD_CONTROL_PORT);
+ ide_device_add(idx);
- ide_proc_register_port(hwif);
+ outb(QD_DEF_CONTR, QD_CONTROL_PORT);
return 1;
} else {
@@ -474,19 +454,17 @@ static int __init qd_probe(int base)
hwif->set_pio_mode = &qd6580_set_pio_mode;
- probe_hwif_init(hwif);
-
qd_setup(mate, base, config | (control << 8),
QD6580_DEF_DATA2, QD6580_DEF_DATA2);
mate->set_pio_mode = &qd6580_set_pio_mode;
- probe_hwif_init(mate);
+ idx[0] = 0;
+ idx[1] = 1;
- qd_write_reg(QD_DEF_CONTR,QD_CONTROL_PORT);
+ ide_device_add(idx);
- ide_proc_register_port(hwif);
- ide_proc_register_port(mate);
+ outb(QD_DEF_CONTR, QD_CONTROL_PORT);
return 0; /* no other qd65xx possible */
}
diff --git a/drivers/ide/legacy/umc8672.c b/drivers/ide/legacy/umc8672.c
index 1151c92dd531..79577b916874 100644
--- a/drivers/ide/legacy/umc8672.c
+++ b/drivers/ide/legacy/umc8672.c
@@ -124,8 +124,9 @@ static void umc_set_pio_mode(ide_drive_t *drive, const u8 pio)
static int __init umc8672_probe(void)
{
- unsigned long flags;
ide_hwif_t *hwif, *mate;
+ unsigned long flags;
+ static u8 idx[4] = { 0, 1, 0xff, 0xff };
if (!request_region(0x108, 2, "umc8672")) {
printk(KERN_ERR "umc8672: ports 0x108-0x109 already in use.\n");
@@ -158,11 +159,7 @@ static int __init umc8672_probe(void)
mate->mate = hwif;
mate->channel = 1;
- probe_hwif_init(hwif);
- probe_hwif_init(mate);
-
- ide_proc_register_port(hwif);
- ide_proc_register_port(mate);
+ ide_device_add(idx);
return 0;
}
diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c
index aebde49365d1..a4ce3ba15d61 100644
--- a/drivers/ide/mips/au1xxx-ide.c
+++ b/drivers/ide/mips/au1xxx-ide.c
@@ -276,8 +276,7 @@ static int auide_build_dmatable(ide_drive_t *drive)
if (iswrite) {
if(!put_source_flags(ahwif->tx_chan,
- (void*)(page_address(sg->page)
- + sg->offset),
+ (void*) sg_virt(sg),
tc, flags)) {
printk(KERN_ERR "%s failed %d\n",
__FUNCTION__, __LINE__);
@@ -285,8 +284,7 @@ static int auide_build_dmatable(ide_drive_t *drive)
} else
{
if(!put_dest_flags(ahwif->rx_chan,
- (void*)(page_address(sg->page)
- + sg->offset),
+ (void*) sg_virt(sg),
tc, flags)) {
printk(KERN_ERR "%s failed %d\n",
__FUNCTION__, __LINE__);
@@ -296,7 +294,7 @@ static int auide_build_dmatable(ide_drive_t *drive)
cur_addr += tc;
cur_len -= tc;
}
- sg++;
+ sg = sg_next(sg);
i--;
}
@@ -351,11 +349,18 @@ static int auide_dma_setup(ide_drive_t *drive)
return 0;
}
-static int auide_dma_check(ide_drive_t *drive)
+static u8 auide_mdma_filter(ide_drive_t *drive)
{
- u8 speed = ide_max_dma_mode(drive);
+ /*
+ * FIXME: ->white_list and ->black_list are based on completely bogus
+ * ->ide_dma_check implementation which didn't set neither the host
+ * controller timings nor the device for the desired transfer mode.
+ *
+ * They should be either removed or 0x00 MWDMA mask should be
+ * returned for devices on the ->black_list.
+ */
- if( dbdma_init_done == 0 ){
+ if (dbdma_init_done == 0) {
auide_hwif.white_list = ide_in_drive_list(drive->id,
dma_white_list);
auide_hwif.black_list = ide_in_drive_list(drive->id,
@@ -366,22 +371,11 @@ static int auide_dma_check(ide_drive_t *drive)
}
/* Is the drive in our DMA black list? */
-
- if ( auide_hwif.black_list ) {
- drive->using_dma = 0;
-
- /* Borrowed the warning message from ide-dma.c */
-
+ if (auide_hwif.black_list)
printk(KERN_WARNING "%s: Disabling DMA for %s (blacklisted)\n",
- drive->name, drive->id->model);
- }
- else
- drive->using_dma = 1;
+ drive->name, drive->id->model);
- if (drive->autodma && (speed & XFER_MODE) != XFER_PIO)
- return 0;
-
- return -1;
+ return drive->hwif->mwdma_mask;
}
static int auide_dma_test_irq(ide_drive_t *drive)
@@ -605,8 +599,9 @@ static int au_ide_probe(struct device *dev)
_auide_hwif *ahwif = &auide_hwif;
ide_hwif_t *hwif;
struct resource *res;
- hw_regs_t *hw;
int ret = 0;
+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ hw_regs_t hw;
#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA)
char *mode = "MWDMA2";
@@ -648,12 +643,12 @@ static int au_ide_probe(struct device *dev)
/* FIXME: This might possibly break PCMCIA IDE devices */
hwif = &ide_hwifs[pdev->id];
- hw = &hwif->hw;
- hwif->irq = hw->irq = ahwif->irq;
+ hwif->irq = ahwif->irq;
hwif->chipset = ide_au1xxx;
- auide_setup_ports(hw, ahwif);
- memcpy(hwif->io_ports, hw->io_ports, sizeof(hwif->io_ports));
+ memset(&hw, 0, sizeof(hw));
+ auide_setup_ports(&hw, ahwif);
+ memcpy(hwif->io_ports, hw.io_ports, sizeof(hwif->io_ports));
hwif->ultra_mask = 0x0; /* Disable Ultra DMA */
#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
@@ -692,7 +687,8 @@ static int au_ide_probe(struct device *dev)
hwif->dma_off_quietly = &auide_dma_off_quietly;
hwif->dma_timeout = &auide_dma_timeout;
- hwif->ide_dma_check = &auide_dma_check;
+ hwif->mdma_filter = &auide_mdma_filter;
+
hwif->dma_exec_cmd = &auide_dma_exec_cmd;
hwif->dma_start = &auide_dma_start;
hwif->ide_dma_end = &auide_dma_end;
@@ -702,23 +698,17 @@ static int au_ide_probe(struct device *dev)
hwif->dma_host_on = &auide_dma_host_on;
hwif->dma_lost_irq = &auide_dma_lost_irq;
hwif->ide_dma_on = &auide_dma_on;
-
- hwif->autodma = 1;
- hwif->drives[0].autodma = hwif->autodma;
- hwif->drives[1].autodma = hwif->autodma;
- hwif->atapi_dma = 1;
-
#else /* !CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA */
- hwif->autodma = 0;
hwif->channel = 0;
hwif->hold = 1;
hwif->select_data = 0; /* no chipset-specific code */
hwif->config_data = 0; /* no chipset-specific code */
- hwif->drives[0].autodma = 0;
hwif->drives[0].autotune = 1; /* 1=autotune, 2=noautotune, 0=default */
+ hwif->drives[1].autotune = 1;
#endif
- hwif->drives[0].no_io_32bit = 1;
+ hwif->drives[0].no_io_32bit = 1;
+ hwif->drives[1].no_io_32bit = 1;
auide_hwif.hwif = hwif;
hwif->hwif_data = &auide_hwif;
@@ -728,9 +718,9 @@ static int au_ide_probe(struct device *dev)
dbdma_init_done = 1;
#endif
- probe_hwif_init(hwif);
+ idx[0] = hwif->index;
- ide_proc_register_port(hwif);
+ ide_device_add(idx);
dev_set_drvdata(dev, hwif);
diff --git a/drivers/ide/mips/swarm.c b/drivers/ide/mips/swarm.c
index c2e29571b007..521edd41b572 100644
--- a/drivers/ide/mips/swarm.c
+++ b/drivers/ide/mips/swarm.c
@@ -71,6 +71,7 @@ static int __devinit swarm_ide_probe(struct device *dev)
u8 __iomem *base;
phys_t offset, size;
int i;
+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
if (!SIBYTE_HAVE_IDE)
return -ENODEV;
@@ -119,18 +120,15 @@ static int __devinit swarm_ide_probe(struct device *dev)
hwif->noprobe = 0;
for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
- hwif->hw.io_ports[i] =
+ hwif->io_ports[i] =
(unsigned long)(base + ((0x1f0 + i) << 5));
- hwif->hw.io_ports[IDE_CONTROL_OFFSET] =
+ hwif->io_ports[IDE_CONTROL_OFFSET] =
(unsigned long)(base + (0x3f6 << 5));
- hwif->hw.irq = K_INT_GB_IDE;
+ hwif->irq = K_INT_GB_IDE;
- memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
- hwif->irq = hwif->hw.irq;
+ idx[0] = hwif->index;
- probe_hwif_init(hwif);
-
- ide_proc_register_port(hwif);
+ ide_device_add(idx);
dev_set_drvdata(dev, hwif);
diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
index d6cb2d5143c8..19ec421f7b9f 100644
--- a/drivers/ide/pci/aec62xx.c
+++ b/drivers/ide/pci/aec62xx.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/aec62xx.c Version 0.24 May 24, 2007
+ * linux/drivers/ide/pci/aec62xx.c Version 0.27 Sep 16, 2007
*
* Copyright (C) 1999-2002 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2007 MontaVista Software, Inc. <source@mvista.com>
@@ -141,30 +141,6 @@ static void aec_set_pio_mode(ide_drive_t *drive, const u8 pio)
drive->hwif->set_dma_mode(drive, pio + XFER_PIO_0);
}
-static int aec62xx_config_drive_xfer_rate (ide_drive_t *drive)
-{
- if (ide_tune_dma(drive))
- return 0;
-
- if (ide_use_fast_pio(drive))
- ide_set_max_pio(drive);
-
- return -1;
-}
-
-static void aec62xx_dma_lost_irq (ide_drive_t *drive)
-{
- switch (HWIF(drive)->pci_dev->device) {
- case PCI_DEVICE_ID_ARTOP_ATP860:
- case PCI_DEVICE_ID_ARTOP_ATP860R:
- case PCI_DEVICE_ID_ARTOP_ATP865:
- case PCI_DEVICE_ID_ARTOP_ATP865R:
- printk(" AEC62XX time out ");
- default:
- break;
- }
-}
-
static unsigned int __devinit init_chipset_aec62xx(struct pci_dev *dev, const char *name)
{
int bus_speed = system_bus_clock();
@@ -195,114 +171,76 @@ static unsigned int __devinit init_chipset_aec62xx(struct pci_dev *dev, const ch
static void __devinit init_hwif_aec62xx(ide_hwif_t *hwif)
{
struct pci_dev *dev = hwif->pci_dev;
- u8 reg54 = 0, mask = hwif->channel ? 0xf0 : 0x0f;
- unsigned long flags;
hwif->set_pio_mode = &aec_set_pio_mode;
- if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) {
- if(hwif->mate)
- hwif->mate->serialized = hwif->serialized = 1;
+ if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF)
hwif->set_dma_mode = &aec6210_set_mode;
- } else
+ else
hwif->set_dma_mode = &aec6260_set_mode;
- if (!hwif->dma_base) {
- hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
+ if (hwif->dma_base == 0)
return;
- }
- hwif->ultra_mask = hwif->cds->udma_mask;
- hwif->mwdma_mask = 0x07;
-
- hwif->ide_dma_check = &aec62xx_config_drive_xfer_rate;
- hwif->dma_lost_irq = &aec62xx_dma_lost_irq;
+ if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF)
+ return;
- if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) {
- spin_lock_irqsave(&ide_lock, flags);
- pci_read_config_byte (dev, 0x54, &reg54);
- pci_write_config_byte(dev, 0x54, (reg54 & ~mask));
- spin_unlock_irqrestore(&ide_lock, flags);
- } else if (hwif->cbl != ATA_CBL_PATA40_SHORT) {
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT) {
u8 ata66 = 0, mask = hwif->channel ? 0x02 : 0x01;
pci_read_config_byte(hwif->pci_dev, 0x49, &ata66);
hwif->cbl = (ata66 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
}
-
- if (!noautodma)
- hwif->autodma = 1;
- hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma;
-}
-
-static int __devinit init_setup_aec62xx(struct pci_dev *dev, ide_pci_device_t *d)
-{
- return ide_setup_pci_device(dev, d);
-}
-
-static int __devinit init_setup_aec6x80(struct pci_dev *dev, ide_pci_device_t *d)
-{
- unsigned long dma_base = pci_resource_start(dev, 4);
-
- if (inb(dma_base + 2) & 0x10) {
- d->name = (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R) ?
- "AEC6880R" : "AEC6880";
- d->udma_mask = 0x7f; /* udma0-6 */
- }
-
- return ide_setup_pci_device(dev, d);
}
-static ide_pci_device_t aec62xx_chipsets[] __devinitdata = {
+static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
{ /* 0 */
.name = "AEC6210",
- .init_setup = init_setup_aec62xx,
.init_chipset = init_chipset_aec62xx,
.init_hwif = init_hwif_aec62xx,
- .autodma = AUTODMA,
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
- .bootable = OFF_BOARD,
+ .host_flags = IDE_HFLAG_SERIALIZE |
+ IDE_HFLAG_NO_ATAPI_DMA |
+ IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
- .udma_mask = 0x07, /* udma0-2 */
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA2,
},{ /* 1 */
.name = "AEC6260",
- .init_setup = init_setup_aec62xx,
.init_chipset = init_chipset_aec62xx,
.init_hwif = init_hwif_aec62xx,
- .autodma = NOAUTODMA,
- .bootable = OFF_BOARD,
+ .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_NO_AUTODMA |
+ IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
- .udma_mask = 0x1f, /* udma0-4 */
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA4,
},{ /* 2 */
.name = "AEC6260R",
- .init_setup = init_setup_aec62xx,
.init_chipset = init_chipset_aec62xx,
.init_hwif = init_hwif_aec62xx,
- .autodma = AUTODMA,
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
- .bootable = NEVER_BOARD,
+ .host_flags = IDE_HFLAG_NO_ATAPI_DMA,
.pio_mask = ATA_PIO4,
- .udma_mask = 0x1f, /* udma0-4 */
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA4,
},{ /* 3 */
.name = "AEC6280",
- .init_setup = init_setup_aec6x80,
.init_chipset = init_chipset_aec62xx,
.init_hwif = init_hwif_aec62xx,
- .autodma = AUTODMA,
- .bootable = OFF_BOARD,
+ .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
- .udma_mask = 0x3f, /* udma0-5 */
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA5,
},{ /* 4 */
.name = "AEC6280R",
- .init_setup = init_setup_aec6x80,
.init_chipset = init_chipset_aec62xx,
.init_hwif = init_hwif_aec62xx,
- .autodma = AUTODMA,
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
- .bootable = OFF_BOARD,
+ .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
- .udma_mask = 0x3f, /* udma0-5 */
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA5,
}
};
@@ -315,22 +253,34 @@ static ide_pci_device_t aec62xx_chipsets[] __devinitdata = {
* finds a device matching our IDE device tables.
*
* NOTE: since we're going to modify the 'name' field for AEC-6[26]80[R]
- * chips, pass a local copy of 'struct pci_device_id' down the call chain.
+ * chips, pass a local copy of 'struct ide_port_info' down the call chain.
*/
-
+
static int __devinit aec62xx_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- ide_pci_device_t d = aec62xx_chipsets[id->driver_data];
+ struct ide_port_info d;
+ u8 idx = id->driver_data;
+
+ d = aec62xx_chipsets[idx];
+
+ if (idx == 3 || idx == 4) {
+ unsigned long dma_base = pci_resource_start(dev, 4);
+
+ if (inb(dma_base + 2) & 0x10) {
+ d.name = (idx == 4) ? "AEC6880R" : "AEC6880";
+ d.udma_mask = ATA_UDMA6;
+ }
+ }
- return d.init_setup(dev, &d);
+ return ide_setup_pci_device(dev, &d);
}
-static struct pci_device_id aec62xx_pci_tbl[] = {
- { PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
- { PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860R, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 },
- { PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP865, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 },
- { PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP865R, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
+static const struct pci_device_id aec62xx_pci_tbl[] = {
+ { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF), 0 },
+ { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP860), 1 },
+ { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP860R), 2 },
+ { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP865), 3 },
+ { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP865R), 4 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, aec62xx_pci_tbl);
diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
index 0b83443bf250..a607dd31a64c 100644
--- a/drivers/ide/pci/alim15x3.c
+++ b/drivers/ide/pci/alim15x3.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/alim15x3.c Version 0.26 Jul 14 2007
+ * linux/drivers/ide/pci/alim15x3.c Version 0.29 Sep 16 2007
*
* Copyright (C) 1998-2000 Michel Aubry, Maintainer
* Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer
@@ -437,26 +437,6 @@ static void ali_set_dma_mode(ide_drive_t *drive, const u8 speed)
}
/**
- * ali15x3_config_drive_for_dma - configure for DMA
- * @drive: drive to configure
- *
- * Configure a drive for DMA operation. If DMA is not possible we
- * drop the drive into PIO mode instead.
- */
-
-static int ali15x3_config_drive_for_dma(ide_drive_t *drive)
-{
- drive->init_speed = 0;
-
- if (ide_tune_dma(drive))
- return 0;
-
- ide_set_max_pio(drive);
-
- return -1;
-}
-
-/**
* ali15x3_dma_setup - begin a DMA phase
* @drive: target device
*
@@ -512,6 +492,13 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c
* clear bit 7
*/
pci_write_config_byte(dev, 0x4b, tmpbyte & 0x7F);
+ /*
+ * check m1533, 0x5e, bit 1~4 == 1001 => & 00011110 = 00010010
+ */
+ if (m5229_revision >= 0x20 && isa_dev) {
+ pci_read_config_byte(isa_dev, 0x5e, &tmpbyte);
+ chip_is_1543c_e = ((tmpbyte & 0x1e) == 0x12) ? 1: 0;
+ }
goto out;
}
@@ -557,7 +544,30 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c
pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x02);
}
}
+
out:
+ /*
+ * CD_ROM DMA on (m5229, 0x53, bit0)
+ * Enable this bit even if we want to use PIO.
+ * PIO FIFO off (m5229, 0x53, bit1)
+ * The hardware will use 0x54h and 0x55h to control PIO FIFO.
+ * (Not on later devices it seems)
+ *
+ * 0x53 changes meaning on later revs - we must no touch
+ * bit 1 on them. Need to check if 0x20 is the right break.
+ */
+ if (m5229_revision >= 0x20) {
+ pci_read_config_byte(dev, 0x53, &tmpbyte);
+
+ if (m5229_revision <= 0x20)
+ tmpbyte = (tmpbyte & (~0x02)) | 0x01;
+ else if (m5229_revision == 0xc7 || m5229_revision == 0xc8)
+ tmpbyte |= 0x03;
+ else
+ tmpbyte |= 0x01;
+
+ pci_write_config_byte(dev, 0x53, tmpbyte);
+ }
pci_dev_put(north);
pci_dev_put(isa_dev);
local_irq_restore(flags);
@@ -636,36 +646,8 @@ static u8 __devinit ata66_ali15x3(ide_hwif_t *hwif)
if ((tmpbyte & (1 << hwif->channel)) == 0)
cbl = ATA_CBL_PATA80;
}
- } else {
- /*
- * check m1533, 0x5e, bit 1~4 == 1001 => & 00011110 = 00010010
- */
- pci_read_config_byte(isa_dev, 0x5e, &tmpbyte);
- chip_is_1543c_e = ((tmpbyte & 0x1e) == 0x12) ? 1: 0;
}
- /*
- * CD_ROM DMA on (m5229, 0x53, bit0)
- * Enable this bit even if we want to use PIO
- * PIO FIFO off (m5229, 0x53, bit1)
- * The hardware will use 0x54h and 0x55h to control PIO FIFO
- * (Not on later devices it seems)
- *
- * 0x53 changes meaning on later revs - we must no touch
- * bit 1 on them. Need to check if 0x20 is the right break
- */
-
- pci_read_config_byte(dev, 0x53, &tmpbyte);
-
- if(m5229_revision <= 0x20)
- tmpbyte = (tmpbyte & (~0x02)) | 0x01;
- else if (m5229_revision == 0xc7 || m5229_revision == 0xc8)
- tmpbyte |= 0x03;
- else
- tmpbyte |= 0x01;
-
- pci_write_config_byte(dev, 0x53, tmpbyte);
-
local_irq_restore(flags);
return cbl;
@@ -680,52 +662,17 @@ static u8 __devinit ata66_ali15x3(ide_hwif_t *hwif)
static void __devinit init_hwif_common_ali15x3 (ide_hwif_t *hwif)
{
- hwif->autodma = 0;
hwif->set_pio_mode = &ali_set_pio_mode;
hwif->set_dma_mode = &ali_set_dma_mode;
hwif->udma_filter = &ali_udma_filter;
- /* don't use LBA48 DMA on ALi devices before rev 0xC5 */
- hwif->no_lba48_dma = (m5229_revision <= 0xC4) ? 1 : 0;
-
- if (!hwif->dma_base) {
- hwif->drives[0].autotune = 1;
- hwif->drives[1].autotune = 1;
+ if (hwif->dma_base == 0)
return;
- }
-
- /*
- * check in ->init_dma guarantees m5229_revision >= 0x20 here
- */
-
- if (m5229_revision > 0x20)
- hwif->atapi_dma = 1;
-
- if (m5229_revision <= 0x20)
- hwif->ultra_mask = 0x00; /* no udma */
- else if (m5229_revision < 0xC2)
- hwif->ultra_mask = 0x07; /* udma0-2 */
- else if (m5229_revision == 0xC2 || m5229_revision == 0xC3)
- hwif->ultra_mask = 0x1f; /* udma0-4 */
- else if (m5229_revision == 0xC4)
- hwif->ultra_mask = 0x3f; /* udma0-5 */
- else
- hwif->ultra_mask = 0x7f; /* udma0-6 */
- hwif->mwdma_mask = 0x07;
- hwif->swdma_mask = 0x07;
-
- hwif->ide_dma_check = &ali15x3_config_drive_for_dma;
hwif->dma_setup = &ali15x3_dma_setup;
if (hwif->cbl != ATA_CBL_PATA40_SHORT)
hwif->cbl = ata66_ali15x3(hwif);
-
- if (!noautodma)
- hwif->autodma = 1;
-
- hwif->drives[0].autodma = hwif->autodma;
- hwif->drives[1].autodma = hwif->autodma;
}
/**
@@ -799,14 +746,15 @@ static void __devinit init_dma_ali15x3 (ide_hwif_t *hwif, unsigned long dmabase)
ide_setup_dma(hwif, dmabase, 8);
}
-static ide_pci_device_t ali15x3_chipset __devinitdata = {
+static const struct ide_port_info ali15x3_chipset __devinitdata = {
.name = "ALI15X3",
.init_chipset = init_chipset_ali15x3,
.init_hwif = init_hwif_ali15x3,
.init_dma = init_dma_ali15x3,
- .autodma = AUTODMA,
- .bootable = ON_BOARD,
+ .host_flags = IDE_HFLAG_BOOTABLE,
.pio_mask = ATA_PIO5,
+ .swdma_mask = ATA_SWDMA2,
+ .mwdma_mask = ATA_MWDMA2,
};
/**
@@ -824,21 +772,40 @@ static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_dev
{ },
};
- ide_pci_device_t *d = &ali15x3_chipset;
+ struct ide_port_info d = ali15x3_chipset;
+ u8 rev = dev->revision;
if (pci_dev_present(ati_rs100))
printk(KERN_WARNING "alim15x3: ATI Radeon IGP Northbridge is not yet fully tested.\n");
+ /* don't use LBA48 DMA on ALi devices before rev 0xC5 */
+ if (rev <= 0xC4)
+ d.host_flags |= IDE_HFLAG_NO_LBA48_DMA;
+
+ if (rev >= 0x20) {
+ if (rev == 0x20)
+ d.host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
+
+ if (rev < 0xC2)
+ d.udma_mask = ATA_UDMA2;
+ else if (rev == 0xC2 || rev == 0xC3)
+ d.udma_mask = ATA_UDMA4;
+ else if (rev == 0xC4)
+ d.udma_mask = ATA_UDMA5;
+ else
+ d.udma_mask = ATA_UDMA6;
+ }
+
#if defined(CONFIG_SPARC64)
- d->init_hwif = init_hwif_common_ali15x3;
+ d.init_hwif = init_hwif_common_ali15x3;
#endif /* CONFIG_SPARC64 */
- return ide_setup_pci_device(dev, d);
+ return ide_setup_pci_device(dev, &d);
}
-static struct pci_device_id alim15x3_pci_tbl[] = {
- { PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5228, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+static const struct pci_device_id alim15x3_pci_tbl[] = {
+ { PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5229), 0 },
+ { PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5228), 0 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, alim15x3_pci_tbl);
diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
index 6ff4089a2379..8d4125ec252c 100644
--- a/drivers/ide/pci/amd74xx.c
+++ b/drivers/ide/pci/amd74xx.c
@@ -1,5 +1,5 @@
/*
- * Version 2.23
+ * Version 2.24
*
* AMD 755/756/766/8111 and nVidia nForce/2/2s/3/3s/CK804/MCP04
* IDE driver for Linux.
@@ -28,9 +28,6 @@
#include "ide-timing.h"
-#define DISPLAY_AMD_TIMINGS
-
-#define AMD_IDE_ENABLE (0x00 + amd_config->base)
#define AMD_IDE_CONFIG (0x01 + amd_config->base)
#define AMD_CABLE_DETECT (0x02 + amd_config->base)
#define AMD_DRIVE_TIMING (0x08 + amd_config->base)
@@ -80,7 +77,7 @@ static struct amd_ide_chip {
};
static struct amd_ide_chip *amd_config;
-static ide_pci_device_t *amd_chipset;
+static const struct ide_port_info *amd_chipset;
static unsigned int amd_80w;
static unsigned int amd_clock;
@@ -88,118 +85,6 @@ static char *amd_dma[] = { "16", "25", "33", "44", "66", "100", "133" };
static unsigned char amd_cyc2udma[] = { 6, 6, 5, 4, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 7 };
/*
- * AMD /proc entry.
- */
-
-#ifdef CONFIG_IDE_PROC_FS
-
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 amd74xx_proc;
-
-static unsigned char amd_udma2cyc[] = { 4, 6, 8, 10, 3, 2, 1, 15 };
-static unsigned long amd_base;
-static struct pci_dev *bmide_dev;
-extern int (*amd74xx_display_info)(char *, char **, off_t, int); /* ide-proc.c */
-
-#define amd_print(format, arg...) p += sprintf(p, format "\n" , ## arg)
-#define amd_print_drive(name, format, arg...)\
- p += sprintf(p, name); for (i = 0; i < 4; i++) p += sprintf(p, format, ## arg); p += sprintf(p, "\n");
-
-static int amd74xx_get_info(char *buffer, char **addr, off_t offset, int count)
-{
- int speed[4], cycle[4], setup[4], active[4], recover[4], den[4],
- uen[4], udma[4], active8b[4], recover8b[4];
- struct pci_dev *dev = bmide_dev;
- unsigned int v, u, i;
- unsigned short c, w;
- unsigned char t;
- int len;
- char *p = buffer;
-
- amd_print("----------AMD BusMastering IDE Configuration----------------");
-
- amd_print("Driver Version: 2.13");
- amd_print("South Bridge: %s", pci_name(bmide_dev));
-
- amd_print("Revision: IDE %#x", dev->revision);
- amd_print("Highest DMA rate: UDMA%s", amd_dma[fls(amd_config->udma_mask) - 1]);
-
- amd_print("BM-DMA base: %#lx", amd_base);
- amd_print("PCI clock: %d.%dMHz", amd_clock / 1000, amd_clock / 100 % 10);
-
- amd_print("-----------------------Primary IDE-------Secondary IDE------");
-
- pci_read_config_byte(dev, AMD_IDE_CONFIG, &t);
- amd_print("Prefetch Buffer: %10s%20s", (t & 0x80) ? "yes" : "no", (t & 0x20) ? "yes" : "no");
- amd_print("Post Write Buffer: %10s%20s", (t & 0x40) ? "yes" : "no", (t & 0x10) ? "yes" : "no");
-
- pci_read_config_byte(dev, AMD_IDE_ENABLE, &t);
- amd_print("Enabled: %10s%20s", (t & 0x02) ? "yes" : "no", (t & 0x01) ? "yes" : "no");
-
- c = inb(amd_base + 0x02) | (inb(amd_base + 0x0a) << 8);
- amd_print("Simplex only: %10s%20s", (c & 0x80) ? "yes" : "no", (c & 0x8000) ? "yes" : "no");
-
- amd_print("Cable Type: %10s%20s", (amd_80w & 1) ? "80w" : "40w", (amd_80w & 2) ? "80w" : "40w");
-
- if (!amd_clock)
- return p - buffer;
-
- amd_print("-------------------drive0----drive1----drive2----drive3-----");
-
- pci_read_config_byte(dev, AMD_ADDRESS_SETUP, &t);
- pci_read_config_dword(dev, AMD_DRIVE_TIMING, &v);
- pci_read_config_word(dev, AMD_8BIT_TIMING, &w);
- pci_read_config_dword(dev, AMD_UDMA_TIMING, &u);
-
- for (i = 0; i < 4; i++) {
- setup[i] = ((t >> ((3 - i) << 1)) & 0x3) + 1;
- recover8b[i] = ((w >> ((1 - (i >> 1)) << 3)) & 0xf) + 1;
- active8b[i] = ((w >> (((1 - (i >> 1)) << 3) + 4)) & 0xf) + 1;
- active[i] = ((v >> (((3 - i) << 3) + 4)) & 0xf) + 1;
- recover[i] = ((v >> ((3 - i) << 3)) & 0xf) + 1;
-
- udma[i] = amd_udma2cyc[((u >> ((3 - i) << 3)) & 0x7)];
- uen[i] = ((u >> ((3 - i) << 3)) & 0x40) ? 1 : 0;
- den[i] = (c & ((i & 1) ? 0x40 : 0x20) << ((i & 2) << 2));
-
- if (den[i] && uen[i] && udma[i] == 1) {
- speed[i] = amd_clock * 3;
- cycle[i] = 666666 / amd_clock;
- continue;
- }
-
- if (den[i] && uen[i] && udma[i] == 15) {
- speed[i] = amd_clock * 4;
- cycle[i] = 500000 / amd_clock;
- continue;
- }
-
- speed[i] = 4 * amd_clock / ((den[i] && uen[i]) ? udma[i] : (active[i] + recover[i]) * 2);
- cycle[i] = 1000000 * ((den[i] && uen[i]) ? udma[i] : (active[i] + recover[i]) * 2) / amd_clock / 2;
- }
-
- amd_print_drive("Transfer Mode: ", "%10s", den[i] ? (uen[i] ? "UDMA" : "DMA") : "PIO");
-
- amd_print_drive("Address Setup: ", "%8dns", 1000000 * setup[i] / amd_clock);
- amd_print_drive("Cmd Active: ", "%8dns", 1000000 * active8b[i] / amd_clock);
- amd_print_drive("Cmd Recovery: ", "%8dns", 1000000 * recover8b[i] / amd_clock);
- amd_print_drive("Data Active: ", "%8dns", 1000000 * active[i] / amd_clock);
- amd_print_drive("Data Recovery: ", "%8dns", 1000000 * recover[i] / amd_clock);
- amd_print_drive("Cycle Time: ", "%8dns", cycle[i]);
- amd_print_drive("Transfer Rate: ", "%4d.%dMB/s", speed[i] / 1000, speed[i] / 100 % 10);
-
- /* hoping p - buffer is less than 4K... */
- len = (p - buffer) - offset;
- *addr = buffer + offset;
-
- return len > count ? count : len;
-}
-
-#endif
-
-/*
* amd_set_speed() writes timing values to the chipset registers
*/
@@ -264,16 +149,6 @@ static void amd_set_pio_mode(ide_drive_t *drive, const u8 pio)
amd_set_drive(drive, XFER_PIO_0 + pio);
}
-static int amd74xx_ide_dma_check(ide_drive_t *drive)
-{
- if (ide_tune_dma(drive))
- return 0;
-
- ide_set_max_pio(drive);
-
- return -1;
-}
-
/*
* The initialization callback. Here we determine the IDE chip type
* and initialize its drive independent registers.
@@ -358,55 +233,27 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const ch
* Print the boot message.
*/
- pci_read_config_byte(dev, PCI_REVISION_ID, &t);
printk(KERN_INFO "%s: %s (rev %02x) UDMA%s controller\n",
amd_chipset->name, pci_name(dev), dev->revision,
amd_dma[fls(amd_config->udma_mask) - 1]);
-/*
- * Register /proc/ide/amd74xx entry
- */
-
-#if defined(DISPLAY_AMD_TIMINGS) && defined(CONFIG_IDE_PROC_FS)
- if (!amd74xx_proc) {
- amd_base = pci_resource_start(dev, 4);
- bmide_dev = dev;
- ide_pci_create_host_proc("amd74xx", amd74xx_get_info);
- amd74xx_proc = 1;
- }
-#endif /* DISPLAY_AMD_TIMINGS && CONFIG_IDE_PROC_FS */
-
return dev->irq;
}
static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
{
- int i;
-
if (hwif->irq == 0) /* 0 is bogus but will do for now */
hwif->irq = pci_get_legacy_ide_irq(hwif->pci_dev, hwif->channel);
- hwif->autodma = 0;
-
hwif->set_pio_mode = &amd_set_pio_mode;
hwif->set_dma_mode = &amd_set_drive;
- for (i = 0; i < 2; i++) {
- hwif->drives[i].io_32bit = 1;
- hwif->drives[i].unmask = 1;
- hwif->drives[i].autotune = 1;
- hwif->drives[i].dn = hwif->channel * 2 + i;
- }
-
if (!hwif->dma_base)
return;
- hwif->atapi_dma = 1;
-
hwif->ultra_mask = amd_config->udma_mask;
- hwif->mwdma_mask = 0x07;
- if ((amd_config->flags & AMD_BAD_SWDMA) == 0)
- hwif->swdma_mask = 0x07;
+ if (amd_config->flags & AMD_BAD_SWDMA)
+ hwif->swdma_mask = 0x00;
if (hwif->cbl != ATA_CBL_PATA40_SHORT) {
if ((amd_80w >> hwif->channel) & 1)
@@ -414,26 +261,26 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
else
hwif->cbl = ATA_CBL_PATA40;
}
-
- hwif->ide_dma_check = &amd74xx_ide_dma_check;
- if (!noautodma)
- hwif->autodma = 1;
- hwif->drives[0].autodma = hwif->autodma;
- hwif->drives[1].autodma = hwif->autodma;
}
+#define IDE_HFLAGS_AMD \
+ (IDE_HFLAG_PIO_NO_BLACKLIST | \
+ IDE_HFLAG_PIO_NO_DOWNGRADE | \
+ IDE_HFLAG_POST_SET_MODE | \
+ IDE_HFLAG_IO_32BIT | \
+ IDE_HFLAG_UNMASK_IRQS | \
+ IDE_HFLAG_BOOTABLE)
+
#define DECLARE_AMD_DEV(name_str) \
{ \
.name = name_str, \
.init_chipset = init_chipset_amd74xx, \
.init_hwif = init_hwif_amd74xx, \
- .autodma = AUTODMA, \
.enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, \
- .bootable = ON_BOARD, \
- .host_flags = IDE_HFLAG_PIO_NO_BLACKLIST \
- | IDE_HFLAG_PIO_NO_DOWNGRADE \
- | IDE_HFLAG_POST_SET_MODE, \
+ .host_flags = IDE_HFLAGS_AMD, \
.pio_mask = ATA_PIO5, \
+ .swdma_mask = ATA_SWDMA2, \
+ .mwdma_mask = ATA_MWDMA2, \
}
#define DECLARE_NV_DEV(name_str) \
@@ -441,16 +288,14 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
.name = name_str, \
.init_chipset = init_chipset_amd74xx, \
.init_hwif = init_hwif_amd74xx, \
- .autodma = AUTODMA, \
.enablebits = {{0x50,0x02,0x02}, {0x50,0x01,0x01}}, \
- .bootable = ON_BOARD, \
- .host_flags = IDE_HFLAG_PIO_NO_BLACKLIST \
- | IDE_HFLAG_PIO_NO_DOWNGRADE \
- | IDE_HFLAG_POST_SET_MODE, \
+ .host_flags = IDE_HFLAGS_AMD, \
.pio_mask = ATA_PIO5, \
+ .swdma_mask = ATA_SWDMA2, \
+ .mwdma_mask = ATA_MWDMA2, \
}
-static ide_pci_device_t amd74xx_chipsets[] __devinitdata = {
+static const struct ide_port_info amd74xx_chipsets[] __devinitdata = {
/* 0 */ DECLARE_AMD_DEV("AMD7401"),
/* 1 */ DECLARE_AMD_DEV("AMD7409"),
/* 2 */ DECLARE_AMD_DEV("AMD7411"),
@@ -489,34 +334,34 @@ static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_
return ide_setup_pci_device(dev, amd_chipset);
}
-static struct pci_device_id amd74xx_pci_tbl[] = {
- { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_COBRA_7401, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7409, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
- { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7411, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 },
- { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_OPUS_7441, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 },
- { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 },
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6 },
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7 },
+static const struct pci_device_id amd74xx_pci_tbl[] = {
+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_COBRA_7401), 0 },
+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_VIPER_7409), 1 },
+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_VIPER_7411), 2 },
+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_OPUS_7441), 3 },
+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_8111_IDE), 4 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_IDE), 5 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE), 6 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE), 7 },
#ifdef CONFIG_BLK_DEV_IDE_SATA
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA), 8 },
#endif
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9 },
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE), 9 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE), 10 },
#ifdef CONFIG_BLK_DEV_IDE_SATA
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11 },
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA), 11 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2), 12 },
#endif
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13 },
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14 },
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15 },
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16 },
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17 },
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18 },
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 19 },
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 20 },
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 21 },
- { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 22 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE), 13 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE), 14 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE), 15 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE), 16 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE), 17 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE), 18 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE), 19 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE), 20 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE), 21 },
+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CS5536_IDE), 22 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl);
diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c
index 0eb97f021d39..ef8e0164ef7a 100644
--- a/drivers/ide/pci/atiixp.c
+++ b/drivers/ide/pci/atiixp.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/atiixp.c Version 0.02 Jun 16 2007
+ * linux/drivers/ide/pci/atiixp.c Version 0.03 Aug 3 2007
*
* Copyright (C) 2003 ATI Inc. <hyu@ati.com>
* Copyright (C) 2004,2007 Bartlomiej Zolnierkiewicz
@@ -47,43 +47,6 @@ static int save_mdma_mode[4];
static DEFINE_SPINLOCK(atiixp_lock);
-/**
- * atiixp_dma_2_pio - return the PIO mode matching DMA
- * @xfer_rate: transfer speed
- *
- * Returns the nearest equivalent PIO timing for the PIO or DMA
- * mode requested by the controller.
- */
-
-static u8 atiixp_dma_2_pio(u8 xfer_rate) {
- switch(xfer_rate) {
- case XFER_UDMA_6:
- case XFER_UDMA_5:
- case XFER_UDMA_4:
- case XFER_UDMA_3:
- case XFER_UDMA_2:
- case XFER_UDMA_1:
- case XFER_UDMA_0:
- case XFER_MW_DMA_2:
- case XFER_PIO_4:
- return 4;
- case XFER_MW_DMA_1:
- case XFER_PIO_3:
- return 3;
- case XFER_SW_DMA_2:
- case XFER_PIO_2:
- return 2;
- case XFER_MW_DMA_0:
- case XFER_SW_DMA_1:
- case XFER_SW_DMA_0:
- case XFER_PIO_1:
- case XFER_PIO_0:
- case XFER_PIO_SLOW:
- default:
- return 0;
- }
-}
-
static void atiixp_dma_host_on(ide_drive_t *drive)
{
struct pci_dev *dev = drive->hwif->pci_dev;
@@ -169,7 +132,9 @@ static void atiixp_set_dma_mode(ide_drive_t *drive, const u8 speed)
int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8;
u32 tmp32;
u16 tmp16;
- u8 pio;
+
+ if (speed < XFER_MW_DMA_0)
+ return;
spin_lock_irqsave(&atiixp_lock, flags);
@@ -191,34 +156,6 @@ static void atiixp_set_dma_mode(ide_drive_t *drive, const u8 speed)
}
spin_unlock_irqrestore(&atiixp_lock, flags);
-
- if (speed >= XFER_SW_DMA_0)
- pio = atiixp_dma_2_pio(speed);
- else
- pio = speed - XFER_PIO_0;
-
- atiixp_set_pio_mode(drive, pio);
-}
-
-/**
- * atiixp_dma_check - set up an IDE device
- * @drive: IDE drive to configure
- *
- * Set up the ATIIXP interface for the best available speed on this
- * interface, preferring DMA to PIO.
- */
-
-static int atiixp_dma_check(ide_drive_t *drive)
-{
- drive->init_speed = 0;
-
- if (ide_tune_dma(drive))
- return 0;
-
- if (ide_use_fast_pio(drive))
- ide_set_max_pio(drive);
-
- return -1;
}
/**
@@ -235,23 +172,12 @@ static void __devinit init_hwif_atiixp(ide_hwif_t *hwif)
u8 ch = hwif->channel;
struct pci_dev *pdev = hwif->pci_dev;
- if (!hwif->irq)
- hwif->irq = ch ? 15 : 14;
-
- hwif->autodma = 0;
hwif->set_pio_mode = &atiixp_set_pio_mode;
hwif->set_dma_mode = &atiixp_set_dma_mode;
- hwif->drives[0].autotune = 1;
- hwif->drives[1].autotune = 1;
if (!hwif->dma_base)
return;
- hwif->atapi_dma = 1;
- hwif->ultra_mask = 0x3f;
- hwif->mwdma_mask = 0x06;
- hwif->swdma_mask = 0x04;
-
pci_read_config_byte(pdev, ATIIXP_IDE_UDMA_MODE + ch, &udma_mode);
if ((udma_mode & 0x07) >= 0x04 || (udma_mode & 0x70) >= 0x40)
@@ -261,31 +187,26 @@ static void __devinit init_hwif_atiixp(ide_hwif_t *hwif)
hwif->dma_host_on = &atiixp_dma_host_on;
hwif->dma_host_off = &atiixp_dma_host_off;
- hwif->ide_dma_check = &atiixp_dma_check;
- if (!noautodma)
- hwif->autodma = 1;
-
- hwif->drives[1].autodma = hwif->autodma;
- hwif->drives[0].autodma = hwif->autodma;
}
-
-static ide_pci_device_t atiixp_pci_info[] __devinitdata = {
+static const struct ide_port_info atiixp_pci_info[] __devinitdata = {
{ /* 0 */
.name = "ATIIXP",
.init_hwif = init_hwif_atiixp,
- .autodma = AUTODMA,
.enablebits = {{0x48,0x01,0x00}, {0x48,0x08,0x00}},
- .bootable = ON_BOARD,
+ .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE,
.pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA5,
},{ /* 1 */
.name = "SB600_PATA",
.init_hwif = init_hwif_atiixp,
- .autodma = AUTODMA,
.enablebits = {{0x48,0x01,0x00}, {0x00,0x00,0x00}},
- .bootable = ON_BOARD,
- .host_flags = IDE_HFLAG_SINGLE,
+ .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_LEGACY_IRQS |
+ IDE_HFLAG_BOOTABLE,
.pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA5,
},
};
@@ -303,12 +224,12 @@ static int __devinit atiixp_init_one(struct pci_dev *dev, const struct pci_devic
return ide_setup_pci_device(dev, &atiixp_pci_info[id->driver_data]);
}
-static struct pci_device_id atiixp_pci_tbl[] = {
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP200_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP700_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+static const struct pci_device_id atiixp_pci_tbl[] = {
+ { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP200_IDE), 0 },
+ { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP300_IDE), 0 },
+ { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP400_IDE), 0 },
+ { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP600_IDE), 1 },
+ { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP700_IDE), 0 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl);
diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c
index f369645e4d16..4aa48104e0c1 100644
--- a/drivers/ide/pci/cmd640.c
+++ b/drivers/ide/pci/cmd640.c
@@ -185,6 +185,8 @@ static u8 recovery_counts[4] = {16, 16, 16, 16}; /* Recovery count (encoded) */
#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
+static DEFINE_SPINLOCK(cmd640_lock);
+
/*
* These are initialized to point at the devices we control
*/
@@ -258,12 +260,12 @@ static u8 get_cmd640_reg_vlb (u16 reg)
static u8 get_cmd640_reg(u16 reg)
{
- u8 b;
unsigned long flags;
+ u8 b;
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&cmd640_lock, flags);
b = __get_cmd640_reg(reg);
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&cmd640_lock, flags);
return b;
}
@@ -271,9 +273,9 @@ static void put_cmd640_reg(u16 reg, u8 val)
{
unsigned long flags;
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&cmd640_lock, flags);
__put_cmd640_reg(reg,val);
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&cmd640_lock, flags);
}
static int __init match_pci_cmd640_device (void)
@@ -351,7 +353,7 @@ static int __init secondary_port_responding (void)
{
unsigned long flags;
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&cmd640_lock, flags);
outb_p(0x0a, 0x170 + IDE_SELECT_OFFSET); /* select drive0 */
udelay(100);
@@ -359,11 +361,11 @@ static int __init secondary_port_responding (void)
outb_p(0x1a, 0x170 + IDE_SELECT_OFFSET); /* select drive1 */
udelay(100);
if ((inb_p(0x170 + IDE_SELECT_OFFSET) & 0x1f) != 0x1a) {
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&cmd640_lock, flags);
return 0; /* nothing responded */
}
}
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&cmd640_lock, flags);
return 1; /* success */
}
@@ -440,11 +442,11 @@ static void __init setup_device_ptrs (void)
static void set_prefetch_mode (unsigned int index, int mode)
{
ide_drive_t *drive = cmd_drives[index];
+ unsigned long flags;
int reg = prefetch_regs[index];
u8 b;
- unsigned long flags;
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&cmd640_lock, flags);
b = __get_cmd640_reg(reg);
if (mode) { /* want prefetch on? */
#if CMD640_PREFETCH_MASKS
@@ -460,7 +462,7 @@ static void set_prefetch_mode (unsigned int index, int mode)
b |= prefetch_masks[index]; /* disable prefetch */
}
__put_cmd640_reg(reg, b);
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&cmd640_lock, flags);
}
/*
@@ -561,7 +563,7 @@ static void program_drive_counts (unsigned int index)
/*
* Now that everything is ready, program the new timings
*/
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&cmd640_lock, flags);
/*
* Program the address_setup clocks into ARTTIM reg,
* and then the active/recovery counts into the DRWTIM reg
@@ -570,7 +572,7 @@ static void program_drive_counts (unsigned int index)
setup_count |= __get_cmd640_reg(arttim_regs[index]) & 0x3f;
__put_cmd640_reg(arttim_regs[index], setup_count);
__put_cmd640_reg(drwtim_regs[index], pack_nibbles(active_count, recovery_count));
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&cmd640_lock, flags);
}
/*
@@ -670,20 +672,20 @@ static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio)
static int pci_conf1(void)
{
- u32 tmp;
unsigned long flags;
+ u32 tmp;
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&cmd640_lock, flags);
outb(0x01, 0xCFB);
tmp = inl(0xCF8);
outl(0x80000000, 0xCF8);
if (inl(0xCF8) == 0x80000000) {
outl(tmp, 0xCF8);
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&cmd640_lock, flags);
return 1;
}
outl(tmp, 0xCF8);
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&cmd640_lock, flags);
return 0;
}
@@ -691,15 +693,15 @@ static int pci_conf2(void)
{
unsigned long flags;
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&cmd640_lock, flags);
outb(0x00, 0xCFB);
outb(0x00, 0xCF8);
outb(0x00, 0xCFA);
if (inb(0xCF8) == 0x00 && inb(0xCF8) == 0x00) {
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&cmd640_lock, flags);
return 1;
}
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&cmd640_lock, flags);
return 0;
}
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
index d50f15e34b80..51fca441c294 100644
--- a/drivers/ide/pci/cmd64x.c
+++ b/drivers/ide/pci/cmd64x.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/cmd64x.c Version 1.50 May 10, 2007
+ * linux/drivers/ide/pci/cmd64x.c Version 1.51 Nov 8, 2007
*
* cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines.
* Due to massive hardware bugs, UltraDMA is only supported
@@ -330,17 +330,6 @@ static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed)
(void) pci_write_config_byte(dev, pciU, regU);
}
-static int cmd64x_config_drive_for_dma (ide_drive_t *drive)
-{
- if (ide_tune_dma(drive))
- return 0;
-
- if (ide_use_fast_pio(drive))
- ide_set_max_pio(drive);
-
- return -1;
-}
-
static int cmd648_ide_dma_end (ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
@@ -350,7 +339,8 @@ static int cmd648_ide_dma_end (ide_drive_t *drive)
u8 mrdmode = inb(hwif->dma_master + 0x01);
/* clear the interrupt bit */
- outb(mrdmode | irq_mask, hwif->dma_master + 0x01);
+ outb((mrdmode & ~(MRDMODE_INTR_CH0 | MRDMODE_INTR_CH1)) | irq_mask,
+ hwif->dma_master + 0x01);
return err;
}
@@ -450,11 +440,8 @@ static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev, const cha
u8 mrdmode = 0;
if (dev->device == PCI_DEVICE_ID_CMD_646) {
- u8 rev = 0;
- pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
-
- switch (rev) {
+ switch (dev->revision) {
case 0x07:
case 0x05:
printk("%s: UltraDMA capable\n", name);
@@ -516,22 +503,13 @@ static u8 __devinit ata66_cmd64x(ide_hwif_t *hwif)
static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
{
struct pci_dev *dev = hwif->pci_dev;
- u8 rev = 0;
-
- pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
hwif->set_pio_mode = &cmd64x_set_pio_mode;
hwif->set_dma_mode = &cmd64x_set_dma_mode;
- hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
-
if (!hwif->dma_base)
return;
- hwif->atapi_dma = 1;
- hwif->mwdma_mask = 0x07;
- hwif->ultra_mask = hwif->cds->udma_mask;
-
/*
* UltraDMA only supported on PCI646U and PCI646U2, which
* correspond to revisions 0x03, 0x05 and 0x07 respectively.
@@ -544,11 +522,9 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
*
* So we only do UltraDMA on revision 0x05 and 0x07 chipsets.
*/
- if (dev->device == PCI_DEVICE_ID_CMD_646 && rev < 5)
+ if (dev->device == PCI_DEVICE_ID_CMD_646 && dev->revision < 5)
hwif->ultra_mask = 0x00;
- hwif->ide_dma_check = &cmd64x_config_drive_for_dma;
-
if (hwif->cbl != ATA_CBL_PATA40_SHORT)
hwif->cbl = ata66_cmd64x(hwif);
@@ -560,11 +536,10 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
hwif->ide_dma_test_irq = &cmd648_ide_dma_test_irq;
break;
case PCI_DEVICE_ID_CMD_646:
- hwif->chipset = ide_cmd646;
- if (rev == 0x01) {
+ if (dev->revision == 0x01) {
hwif->ide_dma_end = &cmd646_1_ide_dma_end;
break;
- } else if (rev >= 0x03)
+ } else if (dev->revision >= 0x03)
goto alt_irq_bits;
/* fall thru */
default:
@@ -572,93 +547,71 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
hwif->ide_dma_test_irq = &cmd64x_ide_dma_test_irq;
break;
}
-
- if (!noautodma)
- hwif->autodma = 1;
- hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma;
}
-static int __devinit init_setup_cmd64x(struct pci_dev *dev, ide_pci_device_t *d)
-{
- return ide_setup_pci_device(dev, d);
-}
-
-static int __devinit init_setup_cmd646(struct pci_dev *dev, ide_pci_device_t *d)
-{
- /*
- * The original PCI0646 didn't have the primary channel enable bit,
- * it appeared starting with PCI0646U (i.e. revision ID 3).
- */
- if (dev->revision < 3)
- d->enablebits[0].reg = 0;
-
- return ide_setup_pci_device(dev, d);
-}
-
-static ide_pci_device_t cmd64x_chipsets[] __devinitdata = {
+static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
{ /* 0 */
.name = "CMD643",
- .init_setup = init_setup_cmd64x,
.init_chipset = init_chipset_cmd64x,
.init_hwif = init_hwif_cmd64x,
- .autodma = AUTODMA,
.enablebits = {{0x00,0x00,0x00}, {0x51,0x08,0x08}},
- .bootable = ON_BOARD,
- .host_flags = IDE_HFLAG_ABUSE_PREFETCH,
+ .host_flags = IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE,
.pio_mask = ATA_PIO5,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = 0x00, /* no udma */
},{ /* 1 */
.name = "CMD646",
- .init_setup = init_setup_cmd646,
.init_chipset = init_chipset_cmd64x,
.init_hwif = init_hwif_cmd64x,
- .autodma = AUTODMA,
.enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
- .bootable = ON_BOARD,
- .host_flags = IDE_HFLAG_ABUSE_PREFETCH,
+ .host_flags = IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE,
.pio_mask = ATA_PIO5,
- .udma_mask = 0x07, /* udma0-2 */
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA2,
},{ /* 2 */
.name = "CMD648",
- .init_setup = init_setup_cmd64x,
.init_chipset = init_chipset_cmd64x,
.init_hwif = init_hwif_cmd64x,
- .autodma = AUTODMA,
.enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
- .bootable = ON_BOARD,
- .host_flags = IDE_HFLAG_ABUSE_PREFETCH,
+ .chipset = ide_cmd646,
+ .host_flags = IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE,
.pio_mask = ATA_PIO5,
- .udma_mask = 0x1f, /* udma0-4 */
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA4,
},{ /* 3 */
.name = "CMD649",
- .init_setup = init_setup_cmd64x,
.init_chipset = init_chipset_cmd64x,
.init_hwif = init_hwif_cmd64x,
- .autodma = AUTODMA,
.enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
- .bootable = ON_BOARD,
- .host_flags = IDE_HFLAG_ABUSE_PREFETCH,
+ .host_flags = IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE,
.pio_mask = ATA_PIO5,
- .udma_mask = 0x3f, /* udma0-5 */
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA5,
}
};
-/*
- * We may have to modify enablebits for PCI0646, so we'd better pass
- * a local copy of the ide_pci_device_t structure down the call chain...
- */
static int __devinit cmd64x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- ide_pci_device_t d = cmd64x_chipsets[id->driver_data];
+ struct ide_port_info d;
+ u8 idx = id->driver_data;
+
+ d = cmd64x_chipsets[idx];
+
+ /*
+ * The original PCI0646 didn't have the primary channel enable bit,
+ * it appeared starting with PCI0646U (i.e. revision ID 3).
+ */
+ if (idx == 1 && dev->revision < 3)
+ d.enablebits[0].reg = 0;
- return d.init_setup(dev, &d);
+ return ide_setup_pci_device(dev, &d);
}
-static struct pci_device_id cmd64x_pci_tbl[] = {
- { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_643, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
- { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_648, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
- { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
+static const struct pci_device_id cmd64x_pci_tbl[] = {
+ { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_643), 0 },
+ { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_646), 1 },
+ { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_648), 2 },
+ { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_649), 3 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, cmd64x_pci_tbl);
diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c
index fbce90048aec..0466462fd21b 100644
--- a/drivers/ide/pci/cs5520.c
+++ b/drivers/ide/pci/cs5520.c
@@ -105,27 +105,6 @@ static void cs5520_set_dma_mode(ide_drive_t *drive, const u8 speed)
cs5520_set_pio_mode(drive, 0);
}
-static int cs5520_config_drive_xfer_rate(ide_drive_t *drive)
-{
- /* Tune the drive for PIO modes up to PIO 4 */
- ide_set_max_pio(drive);
-
- /* Then tell the core to use DMA operations */
- return 0;
-}
-
-/*
- * We provide a callback for our nonstandard DMA location
- */
-
-static void __devinit cs5520_init_setup_dma(struct pci_dev *dev, ide_pci_device_t *d, ide_hwif_t *hwif)
-{
- unsigned long bmide = pci_resource_start(dev, 2); /* Not the usual 4 */
- if(hwif->mate && hwif->mate->dma_base) /* Second channel at primary + 8 */
- bmide += 8;
- ide_setup_dma(hwif, bmide, 8);
-}
-
/*
* We wrap the DMA activate to set the vdma flag. This is needed
* so that the IDE DMA layer issues PIO not DMA commands over the
@@ -134,6 +113,7 @@ static void __devinit cs5520_init_setup_dma(struct pci_dev *dev, ide_pci_device_
static int cs5520_dma_on(ide_drive_t *drive)
{
+ /* ATAPI is harder so leave it for now */
drive->vdma = 1;
return 0;
}
@@ -143,39 +123,25 @@ static void __devinit init_hwif_cs5520(ide_hwif_t *hwif)
hwif->set_pio_mode = &cs5520_set_pio_mode;
hwif->set_dma_mode = &cs5520_set_dma_mode;
- if (hwif->dma_base == 0) {
- hwif->drives[1].autotune = hwif->drives[0].autotune = 1;
+ if (hwif->dma_base == 0)
return;
- }
- hwif->ide_dma_check = &cs5520_config_drive_xfer_rate;
hwif->ide_dma_on = &cs5520_dma_on;
-
- /* ATAPI is harder so leave it for now */
- hwif->atapi_dma = 0;
- hwif->ultra_mask = 0;
- hwif->swdma_mask = 0;
- hwif->mwdma_mask = 0;
-
- if (!noautodma)
- hwif->autodma = 1;
-
- hwif->drives[0].autodma = hwif->autodma;
- hwif->drives[1].autodma = hwif->autodma;
}
#define DECLARE_CS_DEV(name_str) \
{ \
.name = name_str, \
- .init_setup_dma = cs5520_init_setup_dma, \
.init_hwif = init_hwif_cs5520, \
- .autodma = AUTODMA, \
- .bootable = ON_BOARD, \
- .host_flags = IDE_HFLAG_ISA_PORTS, \
+ .host_flags = IDE_HFLAG_ISA_PORTS | \
+ IDE_HFLAG_CS5520 | \
+ IDE_HFLAG_VDMA | \
+ IDE_HFLAG_NO_ATAPI_DMA | \
+ IDE_HFLAG_BOOTABLE, \
.pio_mask = ATA_PIO4, \
}
-static ide_pci_device_t cyrix_chipsets[] __devinitdata = {
+static const struct ide_port_info cyrix_chipsets[] __devinitdata = {
/* 0 */ DECLARE_CS_DEV("Cyrix 5510"),
/* 1 */ DECLARE_CS_DEV("Cyrix 5520")
};
@@ -188,9 +154,8 @@ static ide_pci_device_t cyrix_chipsets[] __devinitdata = {
static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- ide_hwif_t *hwif = NULL, *mate = NULL;
- ata_index_t index;
- ide_pci_device_t *d = &cyrix_chipsets[id->driver_data];
+ const struct ide_port_info *d = &cyrix_chipsets[id->driver_data];
+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
ide_setup_pci_noise(dev, d);
@@ -206,36 +171,21 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic
return -ENODEV;
}
- index.all = 0xf0f0;
-
/*
* Now the chipset is configured we can let the core
* do all the device setup for us
*/
- ide_pci_setup_ports(dev, d, 14, &index);
-
- if ((index.b.low & 0xf0) != 0xf0)
- hwif = &ide_hwifs[index.b.low];
- if ((index.b.high & 0xf0) != 0xf0)
- mate = &ide_hwifs[index.b.high];
-
- if (hwif)
- probe_hwif_init(hwif);
- if (mate)
- probe_hwif_init(mate);
+ ide_pci_setup_ports(dev, d, 14, &idx[0]);
- if (hwif)
- ide_proc_register_port(hwif);
- if (mate)
- ide_proc_register_port(mate);
+ ide_device_add(idx);
return 0;
}
-static struct pci_device_id cs5520_pci_tbl[] = {
- { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
+static const struct pci_device_id cs5520_pci_tbl[] = {
+ { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5510), 0 },
+ { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5520), 1 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, cs5520_pci_tbl);
diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c
index e4121577cef0..547690395eee 100644
--- a/drivers/ide/pci/cs5530.c
+++ b/drivers/ide/pci/cs5530.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/cs5530.c Version 0.74 Jul 28 2007
+ * linux/drivers/ide/pci/cs5530.c Version 0.77 Sep 24 2007
*
* Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2000 Mark Lord <mlord@pobox.com>
@@ -104,22 +104,6 @@ out:
return mask;
}
-/**
- * cs5530_config_dma - set DMA/UDMA mode
- * @drive: drive to tune
- *
- * cs5530_config_dma() handles setting of DMA/UDMA mode
- * for both the chipset and drive.
- */
-
-static int cs5530_config_dma(ide_drive_t *drive)
-{
- if (ide_tune_dma(drive))
- return 0;
-
- return 1;
-}
-
static void cs5530_set_dma_mode(ide_drive_t *drive, const u8 mode)
{
unsigned long basereg;
@@ -133,8 +117,7 @@ static void cs5530_set_dma_mode(ide_drive_t *drive, const u8 mode)
case XFER_MW_DMA_1: timings = 0x00012121; break;
case XFER_MW_DMA_2: timings = 0x00002020; break;
default:
- BUG();
- break;
+ return;
}
basereg = CS5530_BASEREG(drive->hwif);
reg = inl(basereg + 4); /* get drive0 config register */
@@ -162,7 +145,6 @@ static void cs5530_set_dma_mode(ide_drive_t *drive, const u8 mode)
static unsigned int __devinit init_chipset_cs5530 (struct pci_dev *dev, const char *name)
{
struct pci_dev *master_0 = NULL, *cs5530_0 = NULL;
- unsigned long flags;
if (pci_resource_start(dev, 4) == 0)
return -EFAULT;
@@ -187,9 +169,6 @@ static unsigned int __devinit init_chipset_cs5530 (struct pci_dev *dev, const ch
goto out;
}
- spin_lock_irqsave(&ide_lock, flags);
- /* all CPUs (there should only be one CPU with this chipset) */
-
/*
* Enable BusMaster and MemoryWriteAndInvalidate for the cs5530:
* --> OR 0x14 into 16-bit PCI COMMAND reg of function 0 of the cs5530
@@ -240,8 +219,6 @@ static unsigned int __devinit init_chipset_cs5530 (struct pci_dev *dev, const ch
pci_write_config_byte(master_0, 0x42, 0x00);
pci_write_config_byte(master_0, 0x43, 0xc1);
- spin_unlock_irqrestore(&ide_lock, flags);
-
out:
pci_dev_put(master_0);
pci_dev_put(cs5530_0);
@@ -260,54 +237,33 @@ static void __devinit init_hwif_cs5530 (ide_hwif_t *hwif)
{
unsigned long basereg;
u32 d0_timings;
- hwif->autodma = 0;
-
- if (hwif->mate)
- hwif->serialized = hwif->mate->serialized = 1;
hwif->set_pio_mode = &cs5530_set_pio_mode;
hwif->set_dma_mode = &cs5530_set_dma_mode;
basereg = CS5530_BASEREG(hwif);
d0_timings = inl(basereg + 0);
- if (CS5530_BAD_PIO(d0_timings)) {
- /* PIO timings not initialized? */
+ if (CS5530_BAD_PIO(d0_timings))
outl(cs5530_pio_timings[(d0_timings >> 31) & 1][0], basereg + 0);
- if (!hwif->drives[0].autotune)
- hwif->drives[0].autotune = 1;
- /* needs autotuning later */
- }
- if (CS5530_BAD_PIO(inl(basereg + 8))) {
- /* PIO timings not initialized? */
+ if (CS5530_BAD_PIO(inl(basereg + 8)))
outl(cs5530_pio_timings[(d0_timings >> 31) & 1][0], basereg + 8);
- if (!hwif->drives[1].autotune)
- hwif->drives[1].autotune = 1;
- /* needs autotuning later */
- }
if (hwif->dma_base == 0)
return;
- hwif->atapi_dma = 1;
- hwif->ultra_mask = 0x07;
- hwif->mwdma_mask = 0x07;
-
hwif->udma_filter = cs5530_udma_filter;
- hwif->ide_dma_check = &cs5530_config_dma;
- if (!noautodma)
- hwif->autodma = 1;
- hwif->drives[0].autodma = hwif->autodma;
- hwif->drives[1].autodma = hwif->autodma;
}
-static ide_pci_device_t cs5530_chipset __devinitdata = {
+static const struct ide_port_info cs5530_chipset __devinitdata = {
.name = "CS5530",
.init_chipset = init_chipset_cs5530,
.init_hwif = init_hwif_cs5530,
- .autodma = AUTODMA,
- .bootable = ON_BOARD,
+ .host_flags = IDE_HFLAG_SERIALIZE |
+ IDE_HFLAG_POST_SET_MODE |
+ IDE_HFLAG_BOOTABLE,
.pio_mask = ATA_PIO4,
- .host_flags = IDE_HFLAG_POST_SET_MODE,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA2,
};
static int __devinit cs5530_init_one(struct pci_dev *dev, const struct pci_device_id *id)
@@ -315,8 +271,8 @@ static int __devinit cs5530_init_one(struct pci_dev *dev, const struct pci_devic
return ide_setup_pci_device(dev, &cs5530_chipset);
}
-static struct pci_device_id cs5530_pci_tbl[] = {
- { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+static const struct pci_device_id cs5530_pci_tbl[] = {
+ { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE), 0 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, cs5530_pci_tbl);
diff --git a/drivers/ide/pci/cs5535.c b/drivers/ide/pci/cs5535.c
index 257865778f92..9094916e3780 100644
--- a/drivers/ide/pci/cs5535.c
+++ b/drivers/ide/pci/cs5535.c
@@ -84,7 +84,7 @@ static void cs5535_set_speed(ide_drive_t *drive, const u8 speed)
/* Set the PIO timings */
if ((speed & XFER_MODE) == XFER_PIO) {
- ide_drive_t *pair = &drive->hwif->drives[drive->dn ^ 1];
+ ide_drive_t *pair = ide_get_paired_drive(drive);
u8 cmd, pioa;
cmd = pioa = speed - XFER_PIO_0;
@@ -157,19 +157,6 @@ static void cs5535_set_pio_mode(ide_drive_t *drive, const u8 pio)
cs5535_set_speed(drive, XFER_PIO_0 + pio);
}
-static int cs5535_dma_check(ide_drive_t *drive)
-{
- drive->init_speed = 0;
-
- if (ide_tune_dma(drive))
- return 0;
-
- if (ide_use_fast_pio(drive))
- ide_set_max_pio(drive);
-
- return -1;
-}
-
static u8 __devinit cs5535_cable_detect(struct pci_dev *dev)
{
u8 bit;
@@ -190,37 +177,23 @@ static u8 __devinit cs5535_cable_detect(struct pci_dev *dev)
*/
static void __devinit init_hwif_cs5535(ide_hwif_t *hwif)
{
- hwif->autodma = 0;
-
hwif->set_pio_mode = &cs5535_set_pio_mode;
hwif->set_dma_mode = &cs5535_set_dma_mode;
- hwif->drives[1].autotune = hwif->drives[0].autotune = 1;
-
if (hwif->dma_base == 0)
return;
- hwif->ide_dma_check = &cs5535_dma_check;
-
- hwif->atapi_dma = 1;
- hwif->ultra_mask = 0x1F;
- hwif->mwdma_mask = 0x07;
-
hwif->cbl = cs5535_cable_detect(hwif->pci_dev);
-
- if (!noautodma)
- hwif->autodma = 1;
-
- hwif->drives[1].autodma = hwif->drives[0].autodma = hwif->autodma;
}
-static ide_pci_device_t cs5535_chipset __devinitdata = {
+static const struct ide_port_info cs5535_chipset __devinitdata = {
.name = "CS5535",
.init_hwif = init_hwif_cs5535,
- .autodma = AUTODMA,
- .bootable = ON_BOARD,
- .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_POST_SET_MODE,
+ .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_POST_SET_MODE |
+ IDE_HFLAG_BOOTABLE,
.pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA4,
};
static int __devinit cs5535_init_one(struct pci_dev *dev,
@@ -229,10 +202,8 @@ static int __devinit cs5535_init_one(struct pci_dev *dev,
return ide_setup_pci_device(dev, &cs5535_chipset);
}
-static struct pci_device_id cs5535_pci_tbl[] =
-{
- { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_IDE, PCI_ANY_ID,
- PCI_ANY_ID, 0, 0, 0},
+static const struct pci_device_id cs5535_pci_tbl[] = {
+ { PCI_VDEVICE(NS, PCI_DEVICE_ID_NS_CS5535_IDE), 0 },
{ 0, },
};
diff --git a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c
index dc278025d318..1cd4e9cb0521 100644
--- a/drivers/ide/pci/cy82c693.c
+++ b/drivers/ide/pci/cy82c693.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/cy82c693.c Version 0.40 Sep. 10, 2002
+ * linux/drivers/ide/pci/cy82c693.c Version 0.42 Oct 23, 2007
*
* Copyright (C) 1998-2000 Andreas S. Krebs (akrebs@altavista.net), Maintainer
* Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org>, Integrator
@@ -428,32 +428,18 @@ static unsigned int __devinit init_chipset_cy82c693(struct pci_dev *dev, const c
*/
static void __devinit init_hwif_cy82c693(ide_hwif_t *hwif)
{
- hwif->autodma = 0;
-
- hwif->chipset = ide_cy82c693;
hwif->set_pio_mode = &cy82c693_set_pio_mode;
- if (!hwif->dma_base) {
- hwif->drives[0].autotune = 1;
- hwif->drives[1].autotune = 1;
+ if (hwif->dma_base == 0)
return;
- }
-
- hwif->atapi_dma = 1;
- hwif->mwdma_mask = 0x04;
- hwif->swdma_mask = 0x04;
hwif->ide_dma_on = &cy82c693_ide_dma_on;
- if (!noautodma)
- hwif->autodma = 1;
- hwif->drives[0].autodma = hwif->autodma;
- hwif->drives[1].autodma = hwif->autodma;
}
-static __devinitdata ide_hwif_t *primary;
-
static void __devinit init_iops_cy82c693(ide_hwif_t *hwif)
{
+ static ide_hwif_t *primary;
+
if (PCI_FUNC(hwif->pci_dev->devfn) == 1)
primary = hwif;
else {
@@ -462,15 +448,17 @@ static void __devinit init_iops_cy82c693(ide_hwif_t *hwif)
}
}
-static ide_pci_device_t cy82c693_chipset __devinitdata = {
+static const struct ide_port_info cy82c693_chipset __devinitdata = {
.name = "CY82C693",
.init_chipset = init_chipset_cy82c693,
.init_iops = init_iops_cy82c693,
.init_hwif = init_hwif_cy82c693,
- .autodma = AUTODMA,
- .bootable = ON_BOARD,
- .host_flags = IDE_HFLAG_SINGLE,
+ .chipset = ide_cy82c693,
+ .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_TRUST_BIOS_FOR_DMA |
+ IDE_HFLAG_BOOTABLE,
.pio_mask = ATA_PIO4,
+ .swdma_mask = ATA_SWDMA2_ONLY,
+ .mwdma_mask = ATA_MWDMA2_ONLY,
};
static int __devinit cy82c693_init_one(struct pci_dev *dev, const struct pci_device_id *id)
@@ -489,8 +477,8 @@ static int __devinit cy82c693_init_one(struct pci_dev *dev, const struct pci_dev
return ret;
}
-static struct pci_device_id cy82c693_pci_tbl[] = {
- { PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+static const struct pci_device_id cy82c693_pci_tbl[] = {
+ { PCI_VDEVICE(CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693), 0 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, cy82c693_pci_tbl);
diff --git a/drivers/ide/pci/delkin_cb.c b/drivers/ide/pci/delkin_cb.c
index 46f4a888c037..83829081640a 100644
--- a/drivers/ide/pci/delkin_cb.c
+++ b/drivers/ide/pci/delkin_cb.c
@@ -80,7 +80,7 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id)
hw.irq = dev->irq;
hw.chipset = ide_pci; /* this enables IRQ sharing */
- rc = ide_register_hw_with_fixup(&hw, 0, &hwif, ide_undecoded_slave);
+ rc = ide_register_hw(&hw, &ide_undecoded_slave, 0, &hwif);
if (rc < 0) {
printk(KERN_ERR "delkin_cb: ide_register_hw failed (%d)\n", rc);
pci_disable_device(dev);
diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c
index 48caa468b762..06885697ed7b 100644
--- a/drivers/ide/pci/generic.c
+++ b/drivers/ide/pci/generic.c
@@ -49,125 +49,66 @@ static int __init ide_generic_all_on(char *unused)
printk(KERN_INFO "IDE generic will claim all unknown PCI IDE storage controllers.\n");
return 1;
}
-__setup("all-generic-ide", ide_generic_all_on);
+const __setup("all-generic-ide", ide_generic_all_on);
#endif
module_param_named(all_generic_ide, ide_generic_all, bool, 0444);
MODULE_PARM_DESC(all_generic_ide, "IDE generic will claim all unknown PCI IDE storage controllers.");
-static void __devinit init_hwif_generic (ide_hwif_t *hwif)
-{
- switch(hwif->pci_dev->device) {
- case PCI_DEVICE_ID_UMC_UM8673F:
- case PCI_DEVICE_ID_UMC_UM8886A:
- case PCI_DEVICE_ID_UMC_UM8886BF:
- hwif->irq = hwif->channel ? 15 : 14;
- break;
- default:
- break;
+#define IDE_HFLAGS_UMC (IDE_HFLAG_NO_DMA | IDE_HFLAG_FORCE_LEGACY_IRQS)
+
+#define DECLARE_GENERIC_PCI_DEV(name_str, extra_flags) \
+ { \
+ .name = name_str, \
+ .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA | \
+ extra_flags | \
+ IDE_HFLAG_BOOTABLE, \
+ .swdma_mask = ATA_SWDMA2, \
+ .mwdma_mask = ATA_MWDMA2, \
+ .udma_mask = ATA_UDMA6, \
}
- if (!(hwif->dma_base))
- return;
-
- hwif->atapi_dma = 1;
- hwif->ultra_mask = 0x7f;
- hwif->mwdma_mask = 0x07;
- hwif->swdma_mask = 0x07;
-
- if (!noautodma)
- hwif->autodma = 1;
- hwif->drives[0].autodma = hwif->autodma;
- hwif->drives[1].autodma = hwif->autodma;
-}
-
-#if 0
- /* Logic to add back later on */
-
- if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
- ide_pci_device_t *unknown = unknown_chipset;
- init_setup_unknown(dev, unknown);
- return 1;
- }
- return 0;
-#endif
+static const struct ide_port_info generic_chipsets[] __devinitdata = {
+ /* 0 */ DECLARE_GENERIC_PCI_DEV("Unknown", 0),
-static ide_pci_device_t generic_chipsets[] __devinitdata = {
- { /* 0 */
- .name = "Unknown",
- .init_hwif = init_hwif_generic,
- .autodma = AUTODMA,
- .bootable = ON_BOARD,
- },{ /* 1 */
+ { /* 1 */
.name = "NS87410",
- .init_hwif = init_hwif_generic,
- .autodma = AUTODMA,
.enablebits = {{0x43,0x08,0x08}, {0x47,0x08,0x08}},
- .bootable = ON_BOARD,
- },{ /* 2 */
- .name = "SAMURAI",
- .init_hwif = init_hwif_generic,
- .autodma = AUTODMA,
- .bootable = ON_BOARD,
- },{ /* 3 */
- .name = "HT6565",
- .init_hwif = init_hwif_generic,
- .autodma = AUTODMA,
- .bootable = ON_BOARD,
- },{ /* 4 */
- .name = "UM8673F",
- .init_hwif = init_hwif_generic,
- .autodma = NODMA,
- .bootable = ON_BOARD,
- },{ /* 5 */
- .name = "UM8886A",
- .init_hwif = init_hwif_generic,
- .autodma = NODMA,
- .bootable = ON_BOARD,
- },{ /* 6 */
- .name = "UM8886BF",
- .init_hwif = init_hwif_generic,
- .autodma = NODMA,
- .bootable = ON_BOARD,
- },{ /* 7 */
- .name = "HINT_IDE",
- .init_hwif = init_hwif_generic,
- .autodma = AUTODMA,
- .bootable = ON_BOARD,
- },{ /* 8 */
- .name = "VIA_IDE",
- .init_hwif = init_hwif_generic,
- .autodma = NOAUTODMA,
- .bootable = ON_BOARD,
- },{ /* 9 */
- .name = "OPTI621V",
- .init_hwif = init_hwif_generic,
- .autodma = NOAUTODMA,
- .bootable = ON_BOARD,
- },{ /* 10 */
+ .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA |
+ IDE_HFLAG_BOOTABLE,
+ .swdma_mask = ATA_SWDMA2,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA6,
+ },
+
+ /* 2 */ DECLARE_GENERIC_PCI_DEV("SAMURAI", 0),
+ /* 3 */ DECLARE_GENERIC_PCI_DEV("HT6565", 0),
+ /* 4 */ DECLARE_GENERIC_PCI_DEV("UM8673F", IDE_HFLAGS_UMC),
+ /* 5 */ DECLARE_GENERIC_PCI_DEV("UM8886A", IDE_HFLAGS_UMC),
+ /* 6 */ DECLARE_GENERIC_PCI_DEV("UM8886BF", IDE_HFLAGS_UMC),
+ /* 7 */ DECLARE_GENERIC_PCI_DEV("HINT_IDE", 0),
+ /* 8 */ DECLARE_GENERIC_PCI_DEV("VIA_IDE", IDE_HFLAG_NO_AUTODMA),
+ /* 9 */ DECLARE_GENERIC_PCI_DEV("OPTI621V", IDE_HFLAG_NO_AUTODMA),
+
+ { /* 10 */
.name = "VIA8237SATA",
- .init_hwif = init_hwif_generic,
- .autodma = AUTODMA,
- .bootable = OFF_BOARD,
- },{ /* 11 */
- .name = "Piccolo0102",
- .init_hwif = init_hwif_generic,
- .autodma = NOAUTODMA,
- .bootable = ON_BOARD,
- },{ /* 12 */
- .name = "Piccolo0103",
- .init_hwif = init_hwif_generic,
- .autodma = NOAUTODMA,
- .bootable = ON_BOARD,
- },{ /* 13 */
- .name = "Piccolo0105",
- .init_hwif = init_hwif_generic,
- .autodma = NOAUTODMA,
- .bootable = ON_BOARD,
- },{ /* 14 */
+ .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA |
+ IDE_HFLAG_OFF_BOARD,
+ .swdma_mask = ATA_SWDMA2,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA6,
+ },
+
+ /* 11 */ DECLARE_GENERIC_PCI_DEV("Piccolo0102", IDE_HFLAG_NO_AUTODMA),
+ /* 12 */ DECLARE_GENERIC_PCI_DEV("Piccolo0103", IDE_HFLAG_NO_AUTODMA),
+ /* 13 */ DECLARE_GENERIC_PCI_DEV("Piccolo0105", IDE_HFLAG_NO_AUTODMA),
+
+ { /* 14 */
.name = "Revolution",
- .init_hwif = init_hwif_generic,
- .autodma = AUTODMA,
- .bootable = OFF_BOARD,
+ .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA |
+ IDE_HFLAG_OFF_BOARD,
+ .swdma_mask = ATA_SWDMA2,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA6,
}
};
@@ -182,7 +123,7 @@ static ide_pci_device_t generic_chipsets[] __devinitdata = {
static int __devinit generic_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- ide_pci_device_t *d = &generic_chipsets[id->driver_data];
+ const struct ide_port_info *d = &generic_chipsets[id->driver_data];
int ret = -ENODEV;
/* Don't use the generic entry unless instructed to do so */
@@ -226,25 +167,28 @@ out:
return ret;
}
-static struct pci_device_id generic_pci_tbl[] = {
- { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
- { PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_SAMURAI_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
- { PCI_VENDOR_ID_HOLTEK, PCI_DEVICE_ID_HOLTEK_6565, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
- { PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8673F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
- { PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5},
- { PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6},
- { PCI_VENDOR_ID_HINT, PCI_DEVICE_ID_HINT_VXPROII_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7},
- { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8},
- { PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C558, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9},
+static const struct pci_device_id generic_pci_tbl[] = {
+ { PCI_VDEVICE(NS, PCI_DEVICE_ID_NS_87410), 1 },
+ { PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_SAMURAI_IDE), 2 },
+ { PCI_VDEVICE(HOLTEK, PCI_DEVICE_ID_HOLTEK_6565), 3 },
+ { PCI_VDEVICE(UMC, PCI_DEVICE_ID_UMC_UM8673F), 4 },
+ { PCI_VDEVICE(UMC, PCI_DEVICE_ID_UMC_UM8886A), 5 },
+ { PCI_VDEVICE(UMC, PCI_DEVICE_ID_UMC_UM8886BF), 6 },
+ { PCI_VDEVICE(HINT, PCI_DEVICE_ID_HINT_VXPROII_IDE), 7 },
+ { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C561), 8 },
+ { PCI_VDEVICE(OPTI, PCI_DEVICE_ID_OPTI_82C558), 9 },
#ifdef CONFIG_BLK_DEV_IDE_SATA
- { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10},
+ { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8237_SATA), 10 },
#endif
- { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11},
- { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12},
- { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13},
- { PCI_VENDOR_ID_NETCELL,PCI_DEVICE_ID_REVOLUTION, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14},
- /* Must come last. If you add entries adjust this table appropriately and the init_one code */
- { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 0},
+ { PCI_VDEVICE(TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO), 11 },
+ { PCI_VDEVICE(TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), 12 },
+ { PCI_VDEVICE(TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO_2), 13 },
+ { PCI_VDEVICE(NETCELL, PCI_DEVICE_ID_REVOLUTION), 14 },
+ /*
+ * Must come last. If you add entries adjust
+ * this table and generic_chipsets[] appropriately.
+ */
+ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 0 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, generic_pci_tbl);
diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c
index 218852aaf22a..ae6307fae4f9 100644
--- a/drivers/ide/pci/hpt34x.c
+++ b/drivers/ide/pci/hpt34x.c
@@ -80,19 +80,6 @@ static void hpt34x_set_pio_mode(ide_drive_t *drive, const u8 pio)
hpt34x_set_mode(drive, XFER_PIO_0 + pio);
}
-static int hpt34x_config_drive_xfer_rate (ide_drive_t *drive)
-{
- drive->init_speed = 0;
-
- if (ide_tune_dma(drive))
- return -1;
-
- if (ide_use_fast_pio(drive))
- ide_set_max_pio(drive);
-
- return -1;
-}
-
/*
* If the BIOS does not set the IO base addaress to XX00, 343 will fail.
*/
@@ -138,60 +125,51 @@ static unsigned int __devinit init_chipset_hpt34x(struct pci_dev *dev, const cha
static void __devinit init_hwif_hpt34x(ide_hwif_t *hwif)
{
- u16 pcicmd = 0;
-
- hwif->autodma = 0;
-
hwif->set_pio_mode = &hpt34x_set_pio_mode;
hwif->set_dma_mode = &hpt34x_set_mode;
+}
- hwif->drives[0].autotune = 1;
- hwif->drives[1].autotune = 1;
-
- pci_read_config_word(hwif->pci_dev, PCI_COMMAND, &pcicmd);
-
- if (!hwif->dma_base)
- return;
-
+static const struct ide_port_info hpt34x_chipsets[] __devinitdata = {
+ { /* 0 */
+ .name = "HPT343",
+ .init_chipset = init_chipset_hpt34x,
+ .init_hwif = init_hwif_hpt34x,
+ .extra = 16,
+ .host_flags = IDE_HFLAG_NO_ATAPI_DMA |
+ IDE_HFLAG_NO_AUTODMA,
+ .pio_mask = ATA_PIO5,
+ },
+ { /* 1 */
+ .name = "HPT345",
+ .init_chipset = init_chipset_hpt34x,
+ .init_hwif = init_hwif_hpt34x,
+ .extra = 16,
+ .host_flags = IDE_HFLAG_NO_ATAPI_DMA |
+ IDE_HFLAG_NO_AUTODMA |
+ IDE_HFLAG_OFF_BOARD,
+ .pio_mask = ATA_PIO5,
#ifdef CONFIG_HPT34X_AUTODMA
- hwif->ultra_mask = 0x07;
- hwif->mwdma_mask = 0x07;
- hwif->swdma_mask = 0x07;
+ .swdma_mask = ATA_SWDMA2,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA2,
#endif
-
- hwif->ide_dma_check = &hpt34x_config_drive_xfer_rate;
- if (!noautodma)
- hwif->autodma = (pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0;
- hwif->drives[0].autodma = hwif->autodma;
- hwif->drives[1].autodma = hwif->autodma;
-}
-
-static ide_pci_device_t hpt34x_chipset __devinitdata = {
- .name = "HPT34X",
- .init_chipset = init_chipset_hpt34x,
- .init_hwif = init_hwif_hpt34x,
- .autodma = NOAUTODMA,
- .bootable = NEVER_BOARD,
- .extra = 16,
- .pio_mask = ATA_PIO5,
+ }
};
static int __devinit hpt34x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- ide_pci_device_t *d = &hpt34x_chipset;
- static char *chipset_names[] = {"HPT343", "HPT345"};
+ const struct ide_port_info *d;
u16 pcicmd = 0;
pci_read_config_word(dev, PCI_COMMAND, &pcicmd);
- d->name = chipset_names[(pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0];
- d->bootable = (pcicmd & PCI_COMMAND_MEMORY) ? OFF_BOARD : NEVER_BOARD;
+ d = &hpt34x_chipsets[(pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0];
return ide_setup_pci_device(dev, d);
}
-static struct pci_device_id hpt34x_pci_tbl[] = {
- { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT343, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+static const struct pci_device_id hpt34x_pci_tbl[] = {
+ { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT343), 0 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, hpt34x_pci_tbl);
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
index 8812a9bb032f..5682895d36d9 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/pci/hpt366.c
@@ -1,9 +1,10 @@
/*
- * linux/drivers/ide/pci/hpt366.c Version 1.13 Sep 29, 2007
+ * linux/drivers/ide/pci/hpt366.c Version 1.21 Oct 23, 2007
*
* Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org>
* Portions Copyright (C) 2001 Sun Microsystems, Inc.
* Portions Copyright (C) 2003 Red Hat Inc
+ * Portions Copyright (C) 2007 Bartlomiej Zolnierkiewicz
* Portions Copyright (C) 2005-2007 MontaVista Software, Inc.
*
* Thanks to HighPoint Technologies for their assistance, and hardware.
@@ -393,8 +394,9 @@ enum ata_clock {
*/
struct hpt_info {
+ char *chip_name; /* Chip name */
u8 chip_type; /* Chip type */
- u8 max_ultra; /* Max. UltraDMA mode allowed */
+ u8 udma_mask; /* Allowed UltraDMA modes mask. */
u8 dpll_clk; /* DPLL clock in MHz */
u8 pci_clk; /* PCI clock in MHz */
u32 **settings; /* Chipset settings table */
@@ -431,79 +433,90 @@ static u32 *hpt37x_settings[NUM_ATA_CLOCKS] = {
sixty_six_base_hpt37x
};
-static struct hpt_info hpt36x __devinitdata = {
+static const struct hpt_info hpt36x __devinitdata = {
+ .chip_name = "HPT36x",
.chip_type = HPT36x,
- .max_ultra = HPT366_ALLOW_ATA66_3 ? (HPT366_ALLOW_ATA66_4 ? 4 : 3) : 2,
+ .udma_mask = HPT366_ALLOW_ATA66_3 ? (HPT366_ALLOW_ATA66_4 ? ATA_UDMA4 : ATA_UDMA3) : ATA_UDMA2,
.dpll_clk = 0, /* no DPLL */
.settings = hpt36x_settings
};
-static struct hpt_info hpt370 __devinitdata = {
+static const struct hpt_info hpt370 __devinitdata = {
+ .chip_name = "HPT370",
.chip_type = HPT370,
- .max_ultra = HPT370_ALLOW_ATA100_5 ? 5 : 4,
+ .udma_mask = HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4,
.dpll_clk = 48,
.settings = hpt37x_settings
};
-static struct hpt_info hpt370a __devinitdata = {
+static const struct hpt_info hpt370a __devinitdata = {
+ .chip_name = "HPT370A",
.chip_type = HPT370A,
- .max_ultra = HPT370_ALLOW_ATA100_5 ? 5 : 4,
+ .udma_mask = HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4,
.dpll_clk = 48,
.settings = hpt37x_settings
};
-static struct hpt_info hpt374 __devinitdata = {
+static const struct hpt_info hpt374 __devinitdata = {
+ .chip_name = "HPT374",
.chip_type = HPT374,
- .max_ultra = 5,
+ .udma_mask = ATA_UDMA5,
.dpll_clk = 48,
.settings = hpt37x_settings
};
-static struct hpt_info hpt372 __devinitdata = {
+static const struct hpt_info hpt372 __devinitdata = {
+ .chip_name = "HPT372",
.chip_type = HPT372,
- .max_ultra = HPT372_ALLOW_ATA133_6 ? 6 : 5,
+ .udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
.dpll_clk = 55,
.settings = hpt37x_settings
};
-static struct hpt_info hpt372a __devinitdata = {
+static const struct hpt_info hpt372a __devinitdata = {
+ .chip_name = "HPT372A",
.chip_type = HPT372A,
- .max_ultra = HPT372_ALLOW_ATA133_6 ? 6 : 5,
+ .udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
.dpll_clk = 66,
.settings = hpt37x_settings
};
-static struct hpt_info hpt302 __devinitdata = {
+static const struct hpt_info hpt302 __devinitdata = {
+ .chip_name = "HPT302",
.chip_type = HPT302,
- .max_ultra = HPT372_ALLOW_ATA133_6 ? 6 : 5,
+ .udma_mask = HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
.dpll_clk = 66,
.settings = hpt37x_settings
};
-static struct hpt_info hpt371 __devinitdata = {
+static const struct hpt_info hpt371 __devinitdata = {
+ .chip_name = "HPT371",
.chip_type = HPT371,
- .max_ultra = HPT371_ALLOW_ATA133_6 ? 6 : 5,
+ .udma_mask = HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
.dpll_clk = 66,
.settings = hpt37x_settings
};
-static struct hpt_info hpt372n __devinitdata = {
+static const struct hpt_info hpt372n __devinitdata = {
+ .chip_name = "HPT372N",
.chip_type = HPT372N,
- .max_ultra = HPT372_ALLOW_ATA133_6 ? 6 : 5,
+ .udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
.dpll_clk = 77,
.settings = hpt37x_settings
};
-static struct hpt_info hpt302n __devinitdata = {
+static const struct hpt_info hpt302n __devinitdata = {
+ .chip_name = "HPT302N",
.chip_type = HPT302N,
- .max_ultra = HPT302_ALLOW_ATA133_6 ? 6 : 5,
+ .udma_mask = HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
.dpll_clk = 77,
.settings = hpt37x_settings
};
-static struct hpt_info hpt371n __devinitdata = {
+static const struct hpt_info hpt371n __devinitdata = {
+ .chip_name = "HPT371N",
.chip_type = HPT371N,
- .max_ultra = HPT371_ALLOW_ATA133_6 ? 6 : 5,
+ .udma_mask = HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
.dpll_clk = 77,
.settings = hpt37x_settings
};
@@ -676,12 +689,11 @@ static int hpt3xx_quirkproc(ide_drive_t *drive)
static void hpt3xx_intrproc(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
-
if (drive->quirk_list)
return;
+
/* drives in the quirk_list may not like intr setups/cleanups */
- hwif->OUTB(drive->ctl | 2, IDE_CONTROL_REG);
+ outb(drive->ctl | 2, IDE_CONTROL_REG);
}
static void hpt3xx_maskproc(ide_drive_t *drive, int mask)
@@ -709,21 +721,8 @@ static void hpt3xx_maskproc(ide_drive_t *drive, int mask)
enable_irq (hwif->irq);
}
} else
- hwif->OUTB(mask ? (drive->ctl | 2) : (drive->ctl & ~2),
- IDE_CONTROL_REG);
-}
-
-static int hpt366_config_drive_xfer_rate(ide_drive_t *drive)
-{
- drive->init_speed = 0;
-
- if (ide_tune_dma(drive))
- return 0;
-
- if (ide_use_fast_pio(drive))
- ide_set_max_pio(drive);
-
- return -1;
+ outb(mask ? (drive->ctl | 2) : (drive->ctl & ~2),
+ IDE_CONTROL_REG);
}
/*
@@ -763,9 +762,9 @@ static void hpt370_irq_timeout(ide_drive_t *drive)
printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo & 0x1ff);
/* get DMA command mode */
- dma_cmd = hwif->INB(hwif->dma_command);
+ dma_cmd = inb(hwif->dma_command);
/* stop DMA */
- hwif->OUTB(dma_cmd & ~0x1, hwif->dma_command);
+ outb(dma_cmd & ~0x1, hwif->dma_command);
hpt370_clear_engine(drive);
}
@@ -780,12 +779,12 @@ static void hpt370_ide_dma_start(ide_drive_t *drive)
static int hpt370_ide_dma_end(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
- u8 dma_stat = hwif->INB(hwif->dma_status);
+ u8 dma_stat = inb(hwif->dma_status);
if (dma_stat & 0x01) {
/* wait a little */
udelay(20);
- dma_stat = hwif->INB(hwif->dma_status);
+ dma_stat = inb(hwif->dma_status);
if (dma_stat & 0x01)
hpt370_irq_timeout(drive);
}
@@ -846,34 +845,32 @@ static int hpt374_ide_dma_end(ide_drive_t *drive)
static void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode)
{
- u8 scr2 = hwif->INB(hwif->dma_master + 0x7b);
+ u8 scr2 = inb(hwif->dma_master + 0x7b);
if ((scr2 & 0x7f) == mode)
return;
/* Tristate the bus */
- hwif->OUTB(0x80, hwif->dma_master + 0x73);
- hwif->OUTB(0x80, hwif->dma_master + 0x77);
+ outb(0x80, hwif->dma_master + 0x73);
+ outb(0x80, hwif->dma_master + 0x77);
/* Switch clock and reset channels */
- hwif->OUTB(mode, hwif->dma_master + 0x7b);
- hwif->OUTB(0xc0, hwif->dma_master + 0x79);
+ outb(mode, hwif->dma_master + 0x7b);
+ outb(0xc0, hwif->dma_master + 0x79);
/*
* Reset the state machines.
* NOTE: avoid accidentally enabling the disabled channels.
*/
- hwif->OUTB(hwif->INB(hwif->dma_master + 0x70) | 0x32,
- hwif->dma_master + 0x70);
- hwif->OUTB(hwif->INB(hwif->dma_master + 0x74) | 0x32,
- hwif->dma_master + 0x74);
+ outb(inb(hwif->dma_master + 0x70) | 0x32, hwif->dma_master + 0x70);
+ outb(inb(hwif->dma_master + 0x74) | 0x32, hwif->dma_master + 0x74);
/* Complete reset */
- hwif->OUTB(0x00, hwif->dma_master + 0x79);
+ outb(0x00, hwif->dma_master + 0x79);
/* Reconnect channels to bus */
- hwif->OUTB(0x00, hwif->dma_master + 0x73);
- hwif->OUTB(0x00, hwif->dma_master + 0x77);
+ outb(0x00, hwif->dma_master + 0x73);
+ outb(0x00, hwif->dma_master + 0x77);
}
/**
@@ -1152,7 +1149,7 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
* Select 66 MHz DPLL clock only if UltraATA/133 mode is
* supported/enabled, use 50 MHz DPLL clock otherwise...
*/
- if (info->max_ultra == 6) {
+ if (info->udma_mask == ATA_UDMA6) {
dpll_clk = 66;
clock = ATA_CLOCK_66MHZ;
} else if (dpll_clk) { /* HPT36x chips don't have DPLL */
@@ -1304,13 +1301,8 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
if (new_mcr != old_mcr)
pci_write_config_byte(dev, hwif->select_data + 1, new_mcr);
- if (!hwif->dma_base) {
- hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
+ if (hwif->dma_base == 0)
return;
- }
-
- hwif->ultra_mask = hwif->cds->udma_mask;
- hwif->mwdma_mask = 0x07;
/*
* The HPT37x uses the CBLID pins as outputs for MA15/MA16
@@ -1349,8 +1341,6 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
if (hwif->cbl != ATA_CBL_PATA40_SHORT)
hwif->cbl = (scr1 & ata66) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
- hwif->ide_dma_check = &hpt366_config_drive_xfer_rate;
-
if (chip_type >= HPT374) {
hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq;
hwif->ide_dma_end = &hpt374_ide_dma_end;
@@ -1360,10 +1350,6 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
hwif->dma_timeout = &hpt370_dma_timeout;
} else
hwif->dma_lost_irq = &hpt366_dma_lost_irq;
-
- if (!noautodma)
- hwif->autodma = 1;
- hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma;
}
static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase)
@@ -1373,7 +1359,7 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase)
u8 dma_new = 0, dma_old = 0;
unsigned long flags;
- dma_old = hwif->INB(dmabase + 2);
+ dma_old = inb(dmabase + 2);
local_irq_save(flags);
@@ -1384,60 +1370,26 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase)
if (masterdma & 0x30) dma_new |= 0x20;
if ( slavedma & 0x30) dma_new |= 0x40;
if (dma_new != dma_old)
- hwif->OUTB(dma_new, dmabase + 2);
+ outb(dma_new, dmabase + 2);
local_irq_restore(flags);
ide_setup_dma(hwif, dmabase, 8);
}
-static int __devinit init_setup_hpt374(struct pci_dev *dev, ide_pci_device_t *d)
+static void __devinit hpt374_init(struct pci_dev *dev, struct pci_dev *dev2)
{
- struct pci_dev *dev2;
-
- if (PCI_FUNC(dev->devfn) & 1)
- return -ENODEV;
-
- pci_set_drvdata(dev, &hpt374);
-
- if ((dev2 = pci_get_slot(dev->bus, dev->devfn + 1)) != NULL) {
- int ret;
-
- pci_set_drvdata(dev2, &hpt374);
-
- if (dev2->irq != dev->irq) {
- /* FIXME: we need a core pci_set_interrupt() */
- dev2->irq = dev->irq;
- printk(KERN_WARNING "%s: PCI config space interrupt "
- "fixed.\n", d->name);
- }
- ret = ide_setup_pci_devices(dev, dev2, d);
- if (ret < 0)
- pci_dev_put(dev2);
- return ret;
+ if (dev2->irq != dev->irq) {
+ /* FIXME: we need a core pci_set_interrupt() */
+ dev2->irq = dev->irq;
+ printk(KERN_INFO "HPT374: PCI config space interrupt fixed\n");
}
- return ide_setup_pci_device(dev, d);
-}
-
-static int __devinit init_setup_hpt372n(struct pci_dev *dev, ide_pci_device_t *d)
-{
- pci_set_drvdata(dev, &hpt372n);
-
- return ide_setup_pci_device(dev, d);
}
-static int __devinit init_setup_hpt371(struct pci_dev *dev, ide_pci_device_t *d)
+static void __devinit hpt371_init(struct pci_dev *dev)
{
- struct hpt_info *info;
u8 mcr1 = 0;
- if (dev->revision > 1) {
- d->name = "HPT371N";
-
- info = &hpt371n;
- } else
- info = &hpt371;
-
/*
* HPT371 chips physically have only one channel, the secondary one,
* but the primary channel registers do exist! Go figure...
@@ -1447,194 +1399,102 @@ static int __devinit init_setup_hpt371(struct pci_dev *dev, ide_pci_device_t *d)
pci_read_config_byte(dev, 0x50, &mcr1);
if (mcr1 & 0x04)
pci_write_config_byte(dev, 0x50, mcr1 & ~0x04);
-
- pci_set_drvdata(dev, info);
-
- return ide_setup_pci_device(dev, d);
}
-static int __devinit init_setup_hpt372a(struct pci_dev *dev, ide_pci_device_t *d)
+static int __devinit hpt36x_init(struct pci_dev *dev, struct pci_dev *dev2)
{
- struct hpt_info *info;
-
- if (dev->revision > 1) {
- d->name = "HPT372N";
-
- info = &hpt372n;
- } else
- info = &hpt372a;
- pci_set_drvdata(dev, info);
+ u8 mcr1 = 0, pin1 = 0, pin2 = 0;
- return ide_setup_pci_device(dev, d);
-}
-
-static int __devinit init_setup_hpt302(struct pci_dev *dev, ide_pci_device_t *d)
-{
- struct hpt_info *info;
+ /*
+ * Now we'll have to force both channels enabled if
+ * at least one of them has been enabled by BIOS...
+ */
+ pci_read_config_byte(dev, 0x50, &mcr1);
+ if (mcr1 & 0x30)
+ pci_write_config_byte(dev, 0x50, mcr1 | 0x30);
- if (dev->revision > 1) {
- d->name = "HPT302N";
+ pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1);
+ pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2);
- info = &hpt302n;
- } else
- info = &hpt302;
- pci_set_drvdata(dev, info);
+ if (pin1 != pin2 && dev->irq == dev2->irq) {
+ printk(KERN_INFO "HPT36x: onboard version of chipset, "
+ "pin1=%d pin2=%d\n", pin1, pin2);
+ return 1;
+ }
- return ide_setup_pci_device(dev, d);
+ return 0;
}
-static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d)
-{
- struct pci_dev *dev2;
- u8 rev = dev->revision;
- static char *chipset_names[] = { "HPT366", "HPT366", "HPT368",
- "HPT370", "HPT370A", "HPT372",
- "HPT372N" };
- static struct hpt_info *info[] = { &hpt36x, &hpt36x, &hpt36x,
- &hpt370, &hpt370a, &hpt372,
- &hpt372n };
-
- if (PCI_FUNC(dev->devfn) & 1)
- return -ENODEV;
-
- switch (rev) {
- case 0:
- case 1:
- case 2:
+static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
+ { /* 0 */
+ .name = "HPT36x",
+ .init_chipset = init_chipset_hpt366,
+ .init_hwif = init_hwif_hpt366,
+ .init_dma = init_dma_hpt366,
/*
* HPT36x chips have one channel per function and have
* both channel enable bits located differently and visible
* to both functions -- really stupid design decision... :-(
* Bit 4 is for the primary channel, bit 5 for the secondary.
*/
- d->host_flags |= IDE_HFLAG_SINGLE;
- d->enablebits[0].mask = d->enablebits[0].val = 0x10;
-
- d->udma_mask = HPT366_ALLOW_ATA66_3 ? (HPT366_ALLOW_ATA66_4 ?
- ATA_UDMA4 : ATA_UDMA3) : ATA_UDMA2;
- break;
- case 3:
- case 4:
- d->udma_mask = HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4;
- break;
- default:
- rev = 6;
- /* fall thru */
- case 5:
- case 6:
- d->udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5;
- break;
- }
-
- d->name = chipset_names[rev];
-
- pci_set_drvdata(dev, info[rev]);
-
- if (rev > 2)
- goto init_single;
-
- if ((dev2 = pci_get_slot(dev->bus, dev->devfn + 1)) != NULL) {
- u8 mcr1 = 0, pin1 = 0, pin2 = 0;
- int ret;
-
- pci_set_drvdata(dev2, info[rev]);
-
- /*
- * Now we'll have to force both channels enabled if
- * at least one of them has been enabled by BIOS...
- */
- pci_read_config_byte(dev, 0x50, &mcr1);
- if (mcr1 & 0x30)
- pci_write_config_byte(dev, 0x50, mcr1 | 0x30);
-
- pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1);
- pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2);
- if (pin1 != pin2 && dev->irq == dev2->irq) {
- d->bootable = ON_BOARD;
- printk("%s: onboard version of chipset, pin1=%d pin2=%d\n",
- d->name, pin1, pin2);
- }
- ret = ide_setup_pci_devices(dev, dev2, d);
- if (ret < 0)
- pci_dev_put(dev2);
- return ret;
- }
-init_single:
- return ide_setup_pci_device(dev, d);
-}
-
-static ide_pci_device_t hpt366_chipsets[] __devinitdata = {
- { /* 0 */
- .name = "HPT366",
- .init_setup = init_setup_hpt366,
- .init_chipset = init_chipset_hpt366,
- .init_hwif = init_hwif_hpt366,
- .init_dma = init_dma_hpt366,
- .autodma = AUTODMA,
- .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
- .bootable = OFF_BOARD,
+ .enablebits = {{0x50,0x10,0x10}, {0x54,0x04,0x04}},
.extra = 240,
+ .host_flags = IDE_HFLAG_SINGLE |
+ IDE_HFLAG_NO_ATAPI_DMA |
+ IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
},{ /* 1 */
.name = "HPT372A",
- .init_setup = init_setup_hpt372a,
.init_chipset = init_chipset_hpt366,
.init_hwif = init_hwif_hpt366,
.init_dma = init_dma_hpt366,
- .autodma = AUTODMA,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
- .udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
- .bootable = OFF_BOARD,
.extra = 240,
+ .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
},{ /* 2 */
.name = "HPT302",
- .init_setup = init_setup_hpt302,
.init_chipset = init_chipset_hpt366,
.init_hwif = init_hwif_hpt366,
.init_dma = init_dma_hpt366,
- .autodma = AUTODMA,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
- .udma_mask = HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
- .bootable = OFF_BOARD,
.extra = 240,
+ .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
},{ /* 3 */
.name = "HPT371",
- .init_setup = init_setup_hpt371,
.init_chipset = init_chipset_hpt366,
.init_hwif = init_hwif_hpt366,
.init_dma = init_dma_hpt366,
- .autodma = AUTODMA,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
- .udma_mask = HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
- .bootable = OFF_BOARD,
.extra = 240,
+ .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
},{ /* 4 */
.name = "HPT374",
- .init_setup = init_setup_hpt374,
.init_chipset = init_chipset_hpt366,
.init_hwif = init_hwif_hpt366,
.init_dma = init_dma_hpt366,
- .autodma = AUTODMA,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
.udma_mask = ATA_UDMA5,
- .bootable = OFF_BOARD,
.extra = 240,
+ .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
},{ /* 5 */
.name = "HPT372N",
- .init_setup = init_setup_hpt372n,
.init_chipset = init_chipset_hpt366,
.init_hwif = init_hwif_hpt366,
.init_dma = init_dma_hpt366,
- .autodma = AUTODMA,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
- .udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
- .bootable = OFF_BOARD,
.extra = 240,
+ .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
}
};
@@ -1645,25 +1505,86 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = {
*
* Called when the PCI registration layer (or the IDE initialization)
* finds a device matching our IDE device tables.
- *
- * NOTE: since we'll have to modify some fields of the ide_pci_device_t
- * structure depending on the chip's revision, we'd better pass a local
- * copy down the call chain...
*/
static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- ide_pci_device_t d = hpt366_chipsets[id->driver_data];
+ const struct hpt_info *info = NULL;
+ struct pci_dev *dev2 = NULL;
+ struct ide_port_info d;
+ u8 idx = id->driver_data;
+ u8 rev = dev->revision;
+
+ if ((idx == 0 || idx == 4) && (PCI_FUNC(dev->devfn) & 1))
+ return -ENODEV;
+
+ switch (idx) {
+ case 0:
+ if (rev < 3)
+ info = &hpt36x;
+ else {
+ static const struct hpt_info *hpt37x_info[] =
+ { &hpt370, &hpt370a, &hpt372, &hpt372n };
+
+ info = hpt37x_info[min_t(u8, rev, 6) - 3];
+ idx++;
+ }
+ break;
+ case 1:
+ info = (rev > 1) ? &hpt372n : &hpt372a;
+ break;
+ case 2:
+ info = (rev > 1) ? &hpt302n : &hpt302;
+ break;
+ case 3:
+ hpt371_init(dev);
+ info = (rev > 1) ? &hpt371n : &hpt371;
+ break;
+ case 4:
+ info = &hpt374;
+ break;
+ case 5:
+ info = &hpt372n;
+ break;
+ }
+
+ d = hpt366_chipsets[idx];
+
+ d.name = info->chip_name;
+ d.udma_mask = info->udma_mask;
+
+ pci_set_drvdata(dev, (void *)info);
+
+ if (info == &hpt36x || info == &hpt374)
+ dev2 = pci_get_slot(dev->bus, dev->devfn + 1);
+
+ if (dev2) {
+ int ret;
+
+ pci_set_drvdata(dev2, (void *)info);
+
+ if (info == &hpt374)
+ hpt374_init(dev, dev2);
+ else {
+ if (hpt36x_init(dev, dev2))
+ d.host_flags |= IDE_HFLAG_BOOTABLE;
+ }
+
+ ret = ide_setup_pci_devices(dev, dev2, &d);
+ if (ret < 0)
+ pci_dev_put(dev2);
+ return ret;
+ }
- return d.init_setup(dev, &d);
+ return ide_setup_pci_device(dev, &d);
}
-static struct pci_device_id hpt366_pci_tbl[] = {
- { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT366, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT372, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
- { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT302, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
- { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
- { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT374, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
- { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT372N, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5},
+static const struct pci_device_id hpt366_pci_tbl[] = {
+ { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT366), 0 },
+ { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT372), 1 },
+ { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT302), 2 },
+ { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT371), 3 },
+ { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT374), 4 },
+ { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT372N), 5 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, hpt366_pci_tbl);
diff --git a/drivers/ide/pci/it8213.c b/drivers/ide/pci/it8213.c
index ecf4ce078dce..90b52ed37bfc 100644
--- a/drivers/ide/pci/it8213.c
+++ b/drivers/ide/pci/it8213.c
@@ -18,37 +18,6 @@
#include <asm/io.h>
/**
- * it8213_dma_2_pio - return the PIO mode matching DMA
- * @xfer_rate: transfer speed
- *
- * Returns the nearest equivalent PIO timing for the DMA
- * mode requested by the controller.
- */
-
-static u8 it8213_dma_2_pio (u8 xfer_rate) {
- switch(xfer_rate) {
- case XFER_UDMA_6:
- case XFER_UDMA_5:
- case XFER_UDMA_4:
- case XFER_UDMA_3:
- case XFER_UDMA_2:
- case XFER_UDMA_1:
- case XFER_UDMA_0:
- case XFER_MW_DMA_2:
- return 4;
- case XFER_MW_DMA_1:
- return 3;
- case XFER_SW_DMA_2:
- return 2;
- case XFER_MW_DMA_0:
- case XFER_SW_DMA_1:
- case XFER_SW_DMA_0:
- default:
- return 0;
- }
-}
-
-/**
* it8213_set_pio_mode - set host controller for PIO mode
* @drive: drive
* @pio: PIO mode number
@@ -166,6 +135,9 @@ static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed)
} else
pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
} else {
+ const u8 mwdma_to_pio[] = { 0, 3, 4 };
+ u8 pio;
+
if (reg48 & u_flag)
pci_write_config_byte(dev, 0x48, reg48 & ~u_flag);
if (reg4a & a_speed)
@@ -174,38 +146,21 @@ static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed)
pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
if (reg55 & w_flag)
pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
- }
- it8213_set_pio_mode(drive, it8213_dma_2_pio(speed));
-}
-
-/**
- * it8213_configure_drive_for_dma - set up for DMA transfers
- * @drive: drive we are going to set up
- *
- * Set up the drive for DMA, tune the controller and drive as
- * required. If the drive isn't suitable for DMA or we hit
- * other problems then we will drop down to PIO and set up
- * PIO appropriately
- */
-
-static int it8213_config_drive_for_dma (ide_drive_t *drive)
-{
- if (ide_tune_dma(drive))
- return 0;
-
- ide_set_max_pio(drive);
+ if (speed >= XFER_MW_DMA_0)
+ pio = mwdma_to_pio[speed - XFER_MW_DMA_0];
+ else
+ pio = 2; /* only SWDMA2 is allowed */
- return -1;
+ it8213_set_pio_mode(drive, pio);
+ }
}
/**
* init_hwif_it8213 - set up hwif structs
* @hwif: interface to set up
*
- * We do the basic set up of the interface structure. The IT8212
- * requires several custom handlers so we override the default
- * ide DMA handlers appropriately
+ * We do the basic set up of the interface structure.
*/
static void __devinit init_hwif_it8213(ide_hwif_t *hwif)
@@ -215,35 +170,13 @@ static void __devinit init_hwif_it8213(ide_hwif_t *hwif)
hwif->set_dma_mode = &it8213_set_dma_mode;
hwif->set_pio_mode = &it8213_set_pio_mode;
- hwif->autodma = 0;
-
- hwif->drives[0].autotune = 1;
- hwif->drives[1].autotune = 1;
-
if (!hwif->dma_base)
return;
- hwif->atapi_dma = 1;
- hwif->ultra_mask = 0x7f;
- hwif->mwdma_mask = 0x06;
- hwif->swdma_mask = 0x04;
-
pci_read_config_byte(hwif->pci_dev, 0x42, &reg42h);
- hwif->ide_dma_check = &it8213_config_drive_for_dma;
-
if (hwif->cbl != ATA_CBL_PATA40_SHORT)
hwif->cbl = (reg42h & 0x02) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
-
- /*
- * The BIOS often doesn't set up DMA on this controller
- * so we always do it.
- */
- if (!noautodma)
- hwif->autodma = 1;
-
- hwif->drives[0].autodma = hwif->autodma;
- hwif->drives[1].autodma = hwif->autodma;
}
@@ -251,14 +184,16 @@ static void __devinit init_hwif_it8213(ide_hwif_t *hwif)
{ \
.name = name_str, \
.init_hwif = init_hwif_it8213, \
- .autodma = AUTODMA, \
.enablebits = {{0x41,0x80,0x80}}, \
- .bootable = ON_BOARD, \
- .host_flags = IDE_HFLAG_SINGLE, \
+ .host_flags = IDE_HFLAG_SINGLE | \
+ IDE_HFLAG_BOOTABLE, \
.pio_mask = ATA_PIO4, \
+ .swdma_mask = ATA_SWDMA2_ONLY, \
+ .mwdma_mask = ATA_MWDMA12_ONLY, \
+ .udma_mask = ATA_UDMA6, \
}
-static ide_pci_device_t it8213_chipsets[] __devinitdata = {
+static const struct ide_port_info it8213_chipsets[] __devinitdata = {
/* 0 */ DECLARE_ITE_DEV("IT8213"),
};
@@ -279,9 +214,8 @@ static int __devinit it8213_init_one(struct pci_dev *dev, const struct pci_devic
return 0;
}
-
-static struct pci_device_id it8213_pci_tbl[] = {
- { PCI_VENDOR_ID_ITE, 0x8213, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+static const struct pci_device_id it8213_pci_tbl[] = {
+ { PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8213), 0 },
{ 0, },
};
diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c
index 1b69d82478c6..99b7d763b6c7 100644
--- a/drivers/ide/pci/it821x.c
+++ b/drivers/ide/pci/it821x.c
@@ -95,7 +95,7 @@ struct it821x_dev
/*
* We allow users to force the card into non raid mode without
- * flashing the alternative BIOS. This is also neccessary right now
+ * flashing the alternative BIOS. This is also necessary right now
* for embedded platforms that cannot run a PC BIOS but are using this
* device.
*/
@@ -416,26 +416,6 @@ static void it821x_set_dma_mode(ide_drive_t *drive, const u8 speed)
}
/**
- * it821x_configure_drive_for_dma - set up for DMA transfers
- * @drive: drive we are going to set up
- *
- * Set up the drive for DMA, tune the controller and drive as
- * required. If the drive isn't suitable for DMA or we hit
- * other problems then we will drop down to PIO and set up
- * PIO appropriately
- */
-
-static int it821x_config_drive_for_dma (ide_drive_t *drive)
-{
- if (ide_tune_dma(drive))
- return 0;
-
- ide_set_max_pio(drive);
-
- return -1;
-}
-
-/**
* ata66_it821x - check for 80 pin cable
* @hwif: interface to check
*
@@ -557,18 +537,17 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
struct it821x_dev *idev = kzalloc(sizeof(struct it821x_dev), GFP_KERNEL);
u8 conf;
- if(idev == NULL) {
+ if (idev == NULL) {
printk(KERN_ERR "it821x: out of memory, falling back to legacy behaviour.\n");
- goto fallback;
+ return;
}
- ide_set_hwifdata(hwif, idev);
- hwif->atapi_dma = 1;
+ ide_set_hwifdata(hwif, idev);
pci_read_config_byte(hwif->pci_dev, 0x50, &conf);
- if(conf & 1) {
+ if (conf & 1) {
idev->smart = 1;
- hwif->atapi_dma = 0;
+ hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
/* Long I/O's although allowed in LBA48 space cause the
onboard firmware to enter the twighlight zone */
hwif->rqsize = 256;
@@ -585,14 +564,14 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
/*
* Not in the docs but according to the reference driver
- * this is neccessary.
+ * this is necessary.
*/
pci_read_config_byte(hwif->pci_dev, 0x08, &conf);
- if(conf == 0x10) {
+ if (conf == 0x10) {
idev->timing10 = 1;
- hwif->atapi_dma = 0;
- if(!idev->smart)
+ hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
+ if (idev->smart == 0)
printk(KERN_WARNING "it821x: Revision 0x10, workarounds activated.\n");
}
@@ -606,32 +585,14 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
} else
hwif->host_flags |= IDE_HFLAG_NO_SET_MODE;
- hwif->drives[0].autotune = 1;
- hwif->drives[1].autotune = 1;
-
- if (!hwif->dma_base)
- goto fallback;
-
- hwif->ultra_mask = 0x7f;
- hwif->mwdma_mask = 0x07;
+ if (hwif->dma_base == 0)
+ return;
- hwif->ide_dma_check = &it821x_config_drive_for_dma;
+ hwif->ultra_mask = ATA_UDMA6;
+ hwif->mwdma_mask = ATA_MWDMA2;
if (hwif->cbl != ATA_CBL_PATA40_SHORT)
hwif->cbl = ata66_it821x(hwif);
-
- /*
- * The BIOS often doesn't set up DMA on this controller
- * so we always do it.
- */
-
- hwif->autodma = 1;
- hwif->drives[0].autodma = hwif->autodma;
- hwif->drives[1].autodma = hwif->autodma;
- return;
-fallback:
- hwif->autodma = 0;
- return;
}
static void __devinit it8212_disable_raid(struct pci_dev *dev)
@@ -672,13 +633,12 @@ static unsigned int __devinit init_chipset_it821x(struct pci_dev *dev, const cha
.name = name_str, \
.init_chipset = init_chipset_it821x, \
.init_hwif = init_hwif_it821x, \
- .autodma = AUTODMA, \
- .bootable = ON_BOARD, \
.fixup = it821x_fixups, \
+ .host_flags = IDE_HFLAG_BOOTABLE, \
.pio_mask = ATA_PIO4, \
}
-static ide_pci_device_t it821x_chipsets[] __devinitdata = {
+static const struct ide_port_info it821x_chipsets[] __devinitdata = {
/* 0 */ DECLARE_ITE_DEV("IT8212"),
};
@@ -693,13 +653,12 @@ static ide_pci_device_t it821x_chipsets[] __devinitdata = {
static int __devinit it821x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- ide_setup_pci_device(dev, &it821x_chipsets[id->driver_data]);
- return 0;
+ return ide_setup_pci_device(dev, &it821x_chipsets[id->driver_data]);
}
-static struct pci_device_id it821x_pci_tbl[] = {
- { PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- { PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8212, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+static const struct pci_device_id it821x_pci_tbl[] = {
+ { PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8211), 0 },
+ { PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8212), 0 },
{ 0, },
};
diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c
index 582b4cae2b53..0083eaf89c77 100644
--- a/drivers/ide/pci/jmicron.c
+++ b/drivers/ide/pci/jmicron.c
@@ -100,24 +100,6 @@ static void jmicron_set_dma_mode(ide_drive_t *drive, const u8 mode)
}
/**
- * jmicron_configure_drive_for_dma - set up for DMA transfers
- * @drive: drive we are going to set up
- *
- * As the JMicron snoops for timings all we actually need to do is
- * make sure we don't set an invalid mode.
- */
-
-static int jmicron_config_drive_for_dma (ide_drive_t *drive)
-{
- if (ide_tune_dma(drive))
- return 0;
-
- ide_set_max_pio(drive);
-
- return -1;
-}
-
-/**
* init_hwif_jmicron - set up hwif structs
* @hwif: interface to set up
*
@@ -129,37 +111,21 @@ static void __devinit init_hwif_jmicron(ide_hwif_t *hwif)
hwif->set_pio_mode = &jmicron_set_pio_mode;
hwif->set_dma_mode = &jmicron_set_dma_mode;
- hwif->drives[0].autotune = 1;
- hwif->drives[1].autotune = 1;
-
- if (!hwif->dma_base)
- goto fallback;
-
- hwif->atapi_dma = 1;
- hwif->ultra_mask = 0x7f;
- hwif->mwdma_mask = 0x07;
-
- hwif->ide_dma_check = &jmicron_config_drive_for_dma;
+ if (hwif->dma_base == 0)
+ return;
if (hwif->cbl != ATA_CBL_PATA40_SHORT)
hwif->cbl = ata66_jmicron(hwif);
-
- hwif->autodma = 1;
- hwif->drives[0].autodma = hwif->autodma;
- hwif->drives[1].autodma = hwif->autodma;
- return;
-fallback:
- hwif->autodma = 0;
- return;
}
-static ide_pci_device_t jmicron_chipset __devinitdata = {
+static const struct ide_port_info jmicron_chipset __devinitdata = {
.name = "JMB",
.init_hwif = init_hwif_jmicron,
- .autodma = AUTODMA,
- .bootable = ON_BOARD,
+ .host_flags = IDE_HFLAG_BOOTABLE,
.enablebits = { { 0x40, 0x01, 0x01 }, { 0x40, 0x10, 0x10 } },
.pio_mask = ATA_PIO5,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA6,
};
/**
@@ -173,8 +139,7 @@ static ide_pci_device_t jmicron_chipset __devinitdata = {
static int __devinit jmicron_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- ide_setup_pci_device(dev, &jmicron_chipset);
- return 0;
+ return ide_setup_pci_device(dev, &jmicron_chipset);
}
/* All JMB PATA controllers have and will continue to have the same
diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c
index 465c935fdf25..d4df4642dbb5 100644
--- a/drivers/ide/pci/ns87415.c
+++ b/drivers/ide/pci/ns87415.c
@@ -197,7 +197,6 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
u8 stat;
#endif
- hwif->autodma = 0;
hwif->selectproc = &ns87415_selectproc;
/*
@@ -259,21 +258,17 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
outb(0x60, hwif->dma_status);
hwif->dma_setup = &ns87415_ide_dma_setup;
hwif->ide_dma_end = &ns87415_ide_dma_end;
-
- if (!noautodma)
- hwif->autodma = 1;
- hwif->drives[0].autodma = hwif->autodma;
- hwif->drives[1].autodma = hwif->autodma;
}
-static ide_pci_device_t ns87415_chipset __devinitdata = {
+static const struct ide_port_info ns87415_chipset __devinitdata = {
.name = "NS87415",
#ifdef CONFIG_SUPERIO
.init_iops = init_iops_ns87415,
#endif
.init_hwif = init_hwif_ns87415,
- .autodma = AUTODMA,
- .bootable = ON_BOARD,
+ .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA |
+ IDE_HFLAG_NO_ATAPI_DMA |
+ IDE_HFLAG_BOOTABLE,
};
static int __devinit ns87415_init_one(struct pci_dev *dev, const struct pci_device_id *id)
@@ -281,8 +276,8 @@ static int __devinit ns87415_init_one(struct pci_dev *dev, const struct pci_devi
return ide_setup_pci_device(dev, &ns87415_chipset);
}
-static struct pci_device_id ns87415_pci_tbl[] = {
- { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+static const struct pci_device_id ns87415_pci_tbl[] = {
+ { PCI_VDEVICE(NS, PCI_DEVICE_ID_NS_87415), 0 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, ns87415_pci_tbl);
diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c
index 9fa06393469a..8953d9c3926f 100644
--- a/drivers/ide/pci/opti621.c
+++ b/drivers/ide/pci/opti621.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/opti621.c Version 0.7 Sept 10, 2002
+ * linux/drivers/ide/pci/opti621.c Version 0.9 Sep 24, 2007
*
* Copyright (C) 1996-1998 Linus Torvalds & authors (see below)
*/
@@ -57,9 +57,6 @@
* There is a 25/33MHz switch in configuration
* register, but driver is written for use at any frequency which get
* (use idebus=xx to select PCI bus speed).
- * Use hda=autotune and hdb=autotune for automatical tune of the PIO modes.
- * If you get strange results, do not use this and set PIO manually
- * by hdparm.
*
* Version 0.1, Nov 8, 1996
* by Jaromir Koutek, for 2.1.8.
@@ -136,6 +133,8 @@ static int reg_base;
#define PIO_NOT_EXIST 254
#define PIO_DONT_KNOW 255
+static DEFINE_SPINLOCK(opti621_lock);
+
/* there are stored pio numbers from other calls of opti621_set_pio_mode */
static void compute_pios(ide_drive_t *drive, const u8 pio)
/* Store values into drive->drive_data
@@ -281,7 +280,7 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
second.recovery_time, drdy);
#endif
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&opti621_lock, flags);
reg_base = hwif->io_ports[IDE_DATA_OFFSET];
@@ -320,7 +319,7 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
/* and read prefetch for both drives */
write_reg(misc, MISC_REG);
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&opti621_lock, flags);
}
/*
@@ -328,40 +327,31 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
*/
static void __devinit init_hwif_opti621 (ide_hwif_t *hwif)
{
- hwif->autodma = 0;
hwif->drives[0].drive_data = PIO_DONT_KNOW;
hwif->drives[1].drive_data = PIO_DONT_KNOW;
hwif->set_pio_mode = &opti621_set_pio_mode;
-
- if (!(hwif->dma_base))
- return;
-
- hwif->atapi_dma = 1;
- hwif->mwdma_mask = 0x07;
- hwif->swdma_mask = 0x07;
-
- if (!noautodma)
- hwif->autodma = 1;
- hwif->drives[0].autodma = hwif->autodma;
- hwif->drives[1].autodma = hwif->autodma;
}
-static ide_pci_device_t opti621_chipsets[] __devinitdata = {
+static const struct ide_port_info opti621_chipsets[] __devinitdata = {
{ /* 0 */
.name = "OPTI621",
.init_hwif = init_hwif_opti621,
- .autodma = AUTODMA,
.enablebits = {{0x45,0x80,0x00}, {0x40,0x08,0x00}},
- .bootable = ON_BOARD,
+ .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA |
+ IDE_HFLAG_BOOTABLE,
.pio_mask = ATA_PIO3,
+ .swdma_mask = ATA_SWDMA2,
+ .mwdma_mask = ATA_MWDMA2,
},{ /* 1 */
.name = "OPTI621X",
.init_hwif = init_hwif_opti621,
- .autodma = AUTODMA,
.enablebits = {{0x45,0x80,0x00}, {0x40,0x08,0x00}},
- .bootable = ON_BOARD,
+ .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA |
+ IDE_HFLAG_BOOTABLE,
.pio_mask = ATA_PIO3,
+ .swdma_mask = ATA_SWDMA2,
+ .mwdma_mask = ATA_MWDMA2,
}
};
@@ -370,9 +360,9 @@ static int __devinit opti621_init_one(struct pci_dev *dev, const struct pci_devi
return ide_setup_pci_device(dev, &opti621_chipsets[id->driver_data]);
}
-static struct pci_device_id opti621_pci_tbl[] = {
- { PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C621, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- { PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
+static const struct pci_device_id opti621_pci_tbl[] = {
+ { PCI_VDEVICE(OPTI, PCI_DEVICE_ID_OPTI_82C621), 0 },
+ { PCI_VDEVICE(OPTI, PCI_DEVICE_ID_OPTI_82C825), 1 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, opti621_pci_tbl);
diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
index ad0bdcb0c02b..4234efeba606 100644
--- a/drivers/ide/pci/pdc202xx_new.c
+++ b/drivers/ide/pci/pdc202xx_new.c
@@ -223,19 +223,6 @@ static u8 pdcnew_cable_detect(ide_hwif_t *hwif)
return ATA_CBL_PATA80;
}
-static int pdcnew_config_drive_xfer_rate(ide_drive_t *drive)
-{
- drive->init_speed = 0;
-
- if (ide_tune_dma(drive))
- return 0;
-
- if (ide_use_fast_pio(drive))
- ide_set_max_pio(drive);
-
- return -1;
-}
-
static int pdcnew_quirkproc(ide_drive_t *drive)
{
const char **list, *model = drive->id->model;
@@ -345,16 +332,12 @@ static long __devinit detect_pll_input_clock(unsigned long dma_base)
static void __devinit apple_kiwi_init(struct pci_dev *pdev)
{
struct device_node *np = pci_device_to_OF_node(pdev);
- unsigned int class_rev = 0;
u8 conf;
if (np == NULL || !of_device_is_compatible(np, "kiwi-root"))
return;
- pci_read_config_dword(pdev, PCI_CLASS_REVISION, &class_rev);
- class_rev &= 0xff;
-
- if (class_rev >= 0x03) {
+ if (pdev->revision >= 0x03) {
/* Setup chip magic config stuff (from darwin) */
pci_read_config_byte (pdev, 0x40, &conf);
pci_write_config_byte(pdev, 0x40, (conf | 0x01));
@@ -482,46 +465,82 @@ static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const cha
static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif)
{
- hwif->autodma = 0;
-
hwif->set_pio_mode = &pdcnew_set_pio_mode;
hwif->set_dma_mode = &pdcnew_set_mode;
hwif->quirkproc = &pdcnew_quirkproc;
hwif->resetproc = &pdcnew_reset;
- hwif->err_stops_fifo = 1;
-
- hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
-
if (hwif->dma_base == 0)
return;
- hwif->atapi_dma = 1;
-
- hwif->ultra_mask = hwif->cds->udma_mask;
- hwif->mwdma_mask = 0x07;
-
- hwif->ide_dma_check = &pdcnew_config_drive_xfer_rate;
-
if (hwif->cbl != ATA_CBL_PATA40_SHORT)
hwif->cbl = pdcnew_cable_detect(hwif);
-
- if (!noautodma)
- hwif->autodma = 1;
- hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma;
}
-static int __devinit init_setup_pdcnew(struct pci_dev *dev, ide_pci_device_t *d)
+static struct pci_dev * __devinit pdc20270_get_dev2(struct pci_dev *dev)
{
- return ide_setup_pci_device(dev, d);
+ struct pci_dev *dev2;
+
+ dev2 = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn) + 2,
+ PCI_FUNC(dev->devfn)));
+ if (dev2 &&
+ dev2->vendor == dev->vendor &&
+ dev2->device == dev->device) {
+
+ if (dev2->irq != dev->irq) {
+ dev2->irq = dev->irq;
+ printk(KERN_INFO "PDC20270: PCI config space "
+ "interrupt fixed\n");
+ }
+
+ return dev2;
+ }
+
+ return NULL;
}
-static int __devinit init_setup_pdc20270(struct pci_dev *dev, ide_pci_device_t *d)
+#define DECLARE_PDCNEW_DEV(name_str, udma) \
+ { \
+ .name = name_str, \
+ .init_chipset = init_chipset_pdcnew, \
+ .init_hwif = init_hwif_pdc202new, \
+ .host_flags = IDE_HFLAG_POST_SET_MODE | \
+ IDE_HFLAG_ERROR_STOPS_FIFO | \
+ IDE_HFLAG_OFF_BOARD, \
+ .pio_mask = ATA_PIO4, \
+ .mwdma_mask = ATA_MWDMA2, \
+ .udma_mask = udma, \
+ }
+
+static const struct ide_port_info pdcnew_chipsets[] __devinitdata = {
+ /* 0 */ DECLARE_PDCNEW_DEV("PDC20268", ATA_UDMA5),
+ /* 1 */ DECLARE_PDCNEW_DEV("PDC20269", ATA_UDMA6),
+ /* 2 */ DECLARE_PDCNEW_DEV("PDC20270", ATA_UDMA5),
+ /* 3 */ DECLARE_PDCNEW_DEV("PDC20271", ATA_UDMA6),
+ /* 4 */ DECLARE_PDCNEW_DEV("PDC20275", ATA_UDMA6),
+ /* 5 */ DECLARE_PDCNEW_DEV("PDC20276", ATA_UDMA6),
+ /* 6 */ DECLARE_PDCNEW_DEV("PDC20277", ATA_UDMA6),
+};
+
+/**
+ * pdc202new_init_one - called when a pdc202xx is found
+ * @dev: the pdc202new device
+ * @id: the matching pci id
+ *
+ * Called when the PCI registration layer (or the IDE initialization)
+ * finds a device matching our IDE device tables.
+ */
+
+static int __devinit pdc202new_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
+ const struct ide_port_info *d;
struct pci_dev *bridge = dev->bus->self;
+ u8 idx = id->driver_data;
+
+ d = &pdcnew_chipsets[idx];
- if (bridge != NULL &&
+ if (idx == 2 && bridge &&
bridge->vendor == PCI_VENDOR_ID_DEC &&
bridge->device == PCI_DEVICE_ID_DEC_21150) {
struct pci_dev *dev2;
@@ -529,143 +548,36 @@ static int __devinit init_setup_pdc20270(struct pci_dev *dev, ide_pci_device_t *
if (PCI_SLOT(dev->devfn) & 2)
return -ENODEV;
- dev2 = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn) + 2,
- PCI_FUNC(dev->devfn)));
- if (dev2 != NULL &&
- dev2->vendor == dev->vendor &&
- dev2->device == dev->device) {
- int ret;
+ dev2 = pdc20270_get_dev2(dev);
- if (dev2->irq != dev->irq) {
- dev2->irq = dev->irq;
-
- printk(KERN_WARNING "%s: PCI config space "
- "interrupt fixed.\n", d->name);
- }
-
- ret = ide_setup_pci_devices(dev, dev2, d);
+ if (dev2) {
+ int ret = ide_setup_pci_devices(dev, dev2, d);
if (ret < 0)
pci_dev_put(dev2);
return ret;
}
}
- return ide_setup_pci_device(dev, d);
-}
-static int __devinit init_setup_pdc20276(struct pci_dev *dev, ide_pci_device_t *d)
-{
- struct pci_dev *bridge = dev->bus->self;
-
- if (bridge != NULL &&
+ if (idx == 5 && bridge &&
bridge->vendor == PCI_VENDOR_ID_INTEL &&
- (bridge->device == PCI_DEVICE_ID_INTEL_I960 ||
- bridge->device == PCI_DEVICE_ID_INTEL_I960RM)) {
-
- printk(KERN_INFO "%s: attached to I2O RAID controller, "
- "skipping.\n", d->name);
+ (bridge->device == PCI_DEVICE_ID_INTEL_I960 ||
+ bridge->device == PCI_DEVICE_ID_INTEL_I960RM)) {
+ printk(KERN_INFO "PDC20276: attached to I2O RAID controller, "
+ "skipping\n");
return -ENODEV;
}
- return ide_setup_pci_device(dev, d);
-}
-
-static ide_pci_device_t pdcnew_chipsets[] __devinitdata = {
- { /* 0 */
- .name = "PDC20268",
- .init_setup = init_setup_pdcnew,
- .init_chipset = init_chipset_pdcnew,
- .init_hwif = init_hwif_pdc202new,
- .autodma = AUTODMA,
- .bootable = OFF_BOARD,
- .pio_mask = ATA_PIO4,
- .udma_mask = 0x3f, /* udma0-5 */
- .host_flags = IDE_HFLAG_POST_SET_MODE,
- },{ /* 1 */
- .name = "PDC20269",
- .init_setup = init_setup_pdcnew,
- .init_chipset = init_chipset_pdcnew,
- .init_hwif = init_hwif_pdc202new,
- .autodma = AUTODMA,
- .bootable = OFF_BOARD,
- .pio_mask = ATA_PIO4,
- .udma_mask = 0x7f, /* udma0-6*/
- .host_flags = IDE_HFLAG_POST_SET_MODE,
- },{ /* 2 */
- .name = "PDC20270",
- .init_setup = init_setup_pdc20270,
- .init_chipset = init_chipset_pdcnew,
- .init_hwif = init_hwif_pdc202new,
- .autodma = AUTODMA,
- .bootable = OFF_BOARD,
- .pio_mask = ATA_PIO4,
- .udma_mask = 0x3f, /* udma0-5 */
- .host_flags = IDE_HFLAG_POST_SET_MODE,
- },{ /* 3 */
- .name = "PDC20271",
- .init_setup = init_setup_pdcnew,
- .init_chipset = init_chipset_pdcnew,
- .init_hwif = init_hwif_pdc202new,
- .autodma = AUTODMA,
- .bootable = OFF_BOARD,
- .pio_mask = ATA_PIO4,
- .udma_mask = 0x7f, /* udma0-6*/
- .host_flags = IDE_HFLAG_POST_SET_MODE,
- },{ /* 4 */
- .name = "PDC20275",
- .init_setup = init_setup_pdcnew,
- .init_chipset = init_chipset_pdcnew,
- .init_hwif = init_hwif_pdc202new,
- .autodma = AUTODMA,
- .bootable = OFF_BOARD,
- .pio_mask = ATA_PIO4,
- .udma_mask = 0x7f, /* udma0-6*/
- .host_flags = IDE_HFLAG_POST_SET_MODE,
- },{ /* 5 */
- .name = "PDC20276",
- .init_setup = init_setup_pdc20276,
- .init_chipset = init_chipset_pdcnew,
- .init_hwif = init_hwif_pdc202new,
- .autodma = AUTODMA,
- .bootable = OFF_BOARD,
- .pio_mask = ATA_PIO4,
- .udma_mask = 0x7f, /* udma0-6*/
- .host_flags = IDE_HFLAG_POST_SET_MODE,
- },{ /* 6 */
- .name = "PDC20277",
- .init_setup = init_setup_pdcnew,
- .init_chipset = init_chipset_pdcnew,
- .init_hwif = init_hwif_pdc202new,
- .autodma = AUTODMA,
- .bootable = OFF_BOARD,
- .pio_mask = ATA_PIO4,
- .udma_mask = 0x7f, /* udma0-6*/
- .host_flags = IDE_HFLAG_POST_SET_MODE,
- }
-};
-/**
- * pdc202new_init_one - called when a pdc202xx is found
- * @dev: the pdc202new device
- * @id: the matching pci id
- *
- * Called when the PCI registration layer (or the IDE initialization)
- * finds a device matching our IDE device tables.
- */
-
-static int __devinit pdc202new_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-{
- ide_pci_device_t *d = &pdcnew_chipsets[id->driver_data];
-
- return d->init_setup(dev, d);
+ return ide_setup_pci_device(dev, d);
}
-static struct pci_device_id pdc202new_pci_tbl[] = {
- { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20269, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
- { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20270, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
- { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20271, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
- { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20275, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
- { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20276, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5},
- { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20277, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6},
+static const struct pci_device_id pdc202new_pci_tbl[] = {
+ { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20268), 0 },
+ { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20269), 1 },
+ { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20270), 2 },
+ { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20271), 3 },
+ { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20275), 4 },
+ { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20276), 5 },
+ { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20277), 6 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, pdc202new_pci_tbl);
diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
index 8c3e8cf36ec9..e09742e2ba59 100644
--- a/drivers/ide/pci/pdc202xx_old.c
+++ b/drivers/ide/pci/pdc202xx_old.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/pdc202xx_old.c Version 0.51 Jul 27, 2007
+ * linux/drivers/ide/pci/pdc202xx_old.c Version 0.52 Aug 27, 2007
*
* Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2006-2007 MontaVista Software, Inc.
@@ -97,9 +97,6 @@ static void pdc202xx_set_mode(ide_drive_t *drive, const u8 speed)
case XFER_MW_DMA_2: TB = 0x60; TC = 0x03; break;
case XFER_MW_DMA_1: TB = 0x60; TC = 0x04; break;
case XFER_MW_DMA_0: TB = 0xE0; TC = 0x0F; break;
- case XFER_SW_DMA_2: TB = 0x60; TC = 0x05; break;
- case XFER_SW_DMA_1: TB = 0x80; TC = 0x06; break;
- case XFER_SW_DMA_0: TB = 0xC0; TC = 0x0B; break;
case XFER_PIO_4: TA = 0x01; TB = 0x04; break;
case XFER_PIO_3: TA = 0x02; TB = 0x06; break;
case XFER_PIO_2: TA = 0x03; TB = 0x08; break;
@@ -179,19 +176,6 @@ static void pdc_old_disable_66MHz_clock(ide_hwif_t *hwif)
outb(clock & ~(hwif->channel ? 0x08 : 0x02), clock_reg);
}
-static int pdc202xx_config_drive_xfer_rate (ide_drive_t *drive)
-{
- drive->init_speed = 0;
-
- if (ide_tune_dma(drive))
- return 0;
-
- if (ide_use_fast_pio(drive))
- ide_set_max_pio(drive);
-
- return -1;
-}
-
static int pdc202xx_quirkproc (ide_drive_t *drive)
{
const char **list, *model = drive->id->model;
@@ -318,15 +302,6 @@ static unsigned int __devinit init_chipset_pdc202xx(struct pci_dev *dev,
static void __devinit init_hwif_pdc202xx(ide_hwif_t *hwif)
{
- struct pci_dev *dev = hwif->pci_dev;
-
- /* PDC20265 has problems with large LBA48 requests */
- if ((dev->device == PCI_DEVICE_ID_PROMISE_20267) ||
- (dev->device == PCI_DEVICE_ID_PROMISE_20265))
- hwif->rqsize = 256;
-
- hwif->autodma = 0;
-
hwif->set_pio_mode = &pdc202xx_set_pio_mode;
hwif->set_dma_mode = &pdc202xx_set_mode;
@@ -335,19 +310,9 @@ static void __devinit init_hwif_pdc202xx(ide_hwif_t *hwif)
if (hwif->pci_dev->device != PCI_DEVICE_ID_PROMISE_20246)
hwif->resetproc = &pdc202xx_reset;
- hwif->err_stops_fifo = 1;
-
- hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
-
if (hwif->dma_base == 0)
return;
- hwif->ultra_mask = hwif->cds->udma_mask;
- hwif->mwdma_mask = 0x07;
- hwif->swdma_mask = 0x07;
- hwif->atapi_dma = 1;
-
- hwif->ide_dma_check = &pdc202xx_config_drive_xfer_rate;
hwif->dma_lost_irq = &pdc202xx_dma_lost_irq;
hwif->dma_timeout = &pdc202xx_dma_timeout;
@@ -359,10 +324,6 @@ static void __devinit init_hwif_pdc202xx(ide_hwif_t *hwif)
hwif->ide_dma_end = &pdc202xx_old_ide_dma_end;
}
hwif->ide_dma_test_irq = &pdc202xx_old_ide_dma_test_irq;
-
- if (!noautodma)
- hwif->autodma = 1;
- hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma;
}
static void __devinit init_dma_pdc202xx(ide_hwif_t *hwif, unsigned long dmabase)
@@ -397,8 +358,8 @@ static void __devinit init_dma_pdc202xx(ide_hwif_t *hwif, unsigned long dmabase)
ide_setup_dma(hwif, dmabase, 8);
}
-static int __devinit init_setup_pdc202ata4(struct pci_dev *dev,
- ide_pci_device_t *d)
+static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev,
+ const char *name)
{
if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) {
u8 irq = 0, irq2 = 0;
@@ -408,90 +369,45 @@ static int __devinit init_setup_pdc202ata4(struct pci_dev *dev,
if (irq != irq2) {
pci_write_config_byte(dev,
(PCI_INTERRUPT_LINE)|0x80, irq); /* 0xbc */
- printk(KERN_INFO "%s: pci-config space interrupt "
- "mirror fixed.\n", d->name);
+ printk(KERN_INFO "%s: PCI config space interrupt "
+ "mirror fixed\n", name);
}
}
- return ide_setup_pci_device(dev, d);
}
-static int __devinit init_setup_pdc20265(struct pci_dev *dev,
- ide_pci_device_t *d)
-{
- if ((dev->bus->self) &&
- (dev->bus->self->vendor == PCI_VENDOR_ID_INTEL) &&
- ((dev->bus->self->device == PCI_DEVICE_ID_INTEL_I960) ||
- (dev->bus->self->device == PCI_DEVICE_ID_INTEL_I960RM))) {
- printk(KERN_INFO "ide: Skipping Promise PDC20265 "
- "attached to I2O RAID controller.\n");
- return -ENODEV;
+#define DECLARE_PDC2026X_DEV(name_str, udma, extra_flags) \
+ { \
+ .name = name_str, \
+ .init_chipset = init_chipset_pdc202xx, \
+ .init_hwif = init_hwif_pdc202xx, \
+ .init_dma = init_dma_pdc202xx, \
+ .extra = 48, \
+ .host_flags = IDE_HFLAG_ERROR_STOPS_FIFO | \
+ extra_flags | \
+ IDE_HFLAG_OFF_BOARD, \
+ .pio_mask = ATA_PIO4, \
+ .mwdma_mask = ATA_MWDMA2, \
+ .udma_mask = udma, \
}
- return ide_setup_pci_device(dev, d);
-}
-static int __devinit init_setup_pdc202xx(struct pci_dev *dev,
- ide_pci_device_t *d)
-{
- return ide_setup_pci_device(dev, d);
-}
-
-static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = {
+static const struct ide_port_info pdc202xx_chipsets[] __devinitdata = {
{ /* 0 */
.name = "PDC20246",
- .init_setup = init_setup_pdc202ata4,
.init_chipset = init_chipset_pdc202xx,
.init_hwif = init_hwif_pdc202xx,
.init_dma = init_dma_pdc202xx,
- .autodma = AUTODMA,
- .bootable = OFF_BOARD,
.extra = 16,
+ .host_flags = IDE_HFLAG_ERROR_STOPS_FIFO |
+ IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
- .udma_mask = 0x07, /* udma0-2 */
- },{ /* 1 */
- .name = "PDC20262",
- .init_setup = init_setup_pdc202ata4,
- .init_chipset = init_chipset_pdc202xx,
- .init_hwif = init_hwif_pdc202xx,
- .init_dma = init_dma_pdc202xx,
- .autodma = AUTODMA,
- .bootable = OFF_BOARD,
- .extra = 48,
- .pio_mask = ATA_PIO4,
- .udma_mask = 0x1f, /* udma0-4 */
- },{ /* 2 */
- .name = "PDC20263",
- .init_setup = init_setup_pdc202ata4,
- .init_chipset = init_chipset_pdc202xx,
- .init_hwif = init_hwif_pdc202xx,
- .init_dma = init_dma_pdc202xx,
- .autodma = AUTODMA,
- .bootable = OFF_BOARD,
- .extra = 48,
- .pio_mask = ATA_PIO4,
- .udma_mask = 0x1f, /* udma0-4 */
- },{ /* 3 */
- .name = "PDC20265",
- .init_setup = init_setup_pdc20265,
- .init_chipset = init_chipset_pdc202xx,
- .init_hwif = init_hwif_pdc202xx,
- .init_dma = init_dma_pdc202xx,
- .autodma = AUTODMA,
- .bootable = OFF_BOARD,
- .extra = 48,
- .pio_mask = ATA_PIO4,
- .udma_mask = 0x3f, /* udma0-5 */
- },{ /* 4 */
- .name = "PDC20267",
- .init_setup = init_setup_pdc202xx,
- .init_chipset = init_chipset_pdc202xx,
- .init_hwif = init_hwif_pdc202xx,
- .init_dma = init_dma_pdc202xx,
- .autodma = AUTODMA,
- .bootable = OFF_BOARD,
- .extra = 48,
- .pio_mask = ATA_PIO4,
- .udma_mask = 0x3f, /* udma0-5 */
- }
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA2,
+ },
+
+ /* 1 */ DECLARE_PDC2026X_DEV("PDC20262", ATA_UDMA4, 0),
+ /* 2 */ DECLARE_PDC2026X_DEV("PDC20263", ATA_UDMA4, 0),
+ /* 3 */ DECLARE_PDC2026X_DEV("PDC20265", ATA_UDMA5, IDE_HFLAG_RQSIZE_256),
+ /* 4 */ DECLARE_PDC2026X_DEV("PDC20267", ATA_UDMA5, IDE_HFLAG_RQSIZE_256),
};
/**
@@ -505,17 +421,36 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = {
static int __devinit pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- ide_pci_device_t *d = &pdc202xx_chipsets[id->driver_data];
+ const struct ide_port_info *d;
+ u8 idx = id->driver_data;
+
+ d = &pdc202xx_chipsets[idx];
+
+ if (idx < 3)
+ pdc202ata4_fixup_irq(dev, d->name);
- return d->init_setup(dev, d);
+ if (idx == 3) {
+ struct pci_dev *bridge = dev->bus->self;
+
+ if (bridge &&
+ bridge->vendor == PCI_VENDOR_ID_INTEL &&
+ (bridge->device == PCI_DEVICE_ID_INTEL_I960 ||
+ bridge->device == PCI_DEVICE_ID_INTEL_I960RM)) {
+ printk(KERN_INFO "ide: Skipping Promise PDC20265 "
+ "attached to I2O RAID controller\n");
+ return -ENODEV;
+ }
+ }
+
+ return ide_setup_pci_device(dev, d);
}
-static struct pci_device_id pdc202xx_pci_tbl[] = {
- { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20246, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20262, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
- { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20263, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
- { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20265, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
- { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20267, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
+static const struct pci_device_id pdc202xx_pci_tbl[] = {
+ { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20246), 0 },
+ { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20262), 1 },
+ { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20263), 2 },
+ { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20265), 3 },
+ { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20267), 4 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, pdc202xx_pci_tbl);
diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
index 38c91ba6497b..63625a0be712 100644
--- a/drivers/ide/pci/piix.c
+++ b/drivers/ide/pci/piix.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/piix.c Version 0.52 Jul 14, 2007
+ * linux/drivers/ide/pci/piix.c Version 0.54 Sep 5, 2007
*
* Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
* Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
@@ -106,37 +106,6 @@
static int no_piix_dma;
/**
- * piix_dma_2_pio - return the PIO mode matching DMA
- * @xfer_rate: transfer speed
- *
- * Returns the nearest equivalent PIO timing for the DMA
- * mode requested by the controller.
- */
-
-static u8 piix_dma_2_pio (u8 xfer_rate) {
- switch(xfer_rate) {
- case XFER_UDMA_6:
- case XFER_UDMA_5:
- case XFER_UDMA_4:
- case XFER_UDMA_3:
- case XFER_UDMA_2:
- case XFER_UDMA_1:
- case XFER_UDMA_0:
- case XFER_MW_DMA_2:
- return 4;
- case XFER_MW_DMA_1:
- return 3;
- case XFER_SW_DMA_2:
- return 2;
- case XFER_MW_DMA_0:
- case XFER_SW_DMA_1:
- case XFER_SW_DMA_0:
- default:
- return 0;
- }
-}
-
-/**
* piix_set_pio_mode - set host controller for PIO mode
* @drive: drive
* @pio: PIO mode number
@@ -263,6 +232,9 @@ static void piix_set_dma_mode(ide_drive_t *drive, const u8 speed)
} else
pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
} else {
+ const u8 mwdma_to_pio[] = { 0, 3, 4 };
+ u8 pio;
+
if (reg48 & u_flag)
pci_write_config_byte(dev, 0x48, reg48 & ~u_flag);
if (reg4a & a_speed)
@@ -271,80 +243,31 @@ static void piix_set_dma_mode(ide_drive_t *drive, const u8 speed)
pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
if (reg55 & w_flag)
pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
- }
- piix_set_pio_mode(drive, piix_dma_2_pio(speed));
-}
-
-/**
- * piix_config_drive_xfer_rate - set up an IDE device
- * @drive: IDE drive to configure
- *
- * Set up the PIIX interface for the best available speed on this
- * interface, preferring DMA to PIO.
- */
-
-static int piix_config_drive_xfer_rate (ide_drive_t *drive)
-{
- drive->init_speed = 0;
+ if (speed >= XFER_MW_DMA_0)
+ pio = mwdma_to_pio[speed - XFER_MW_DMA_0];
+ else
+ pio = 2; /* only SWDMA2 is allowed */
- if (ide_tune_dma(drive))
- return 0;
-
- if (ide_use_fast_pio(drive))
- ide_set_max_pio(drive);
-
- return -1;
-}
-
-/**
- * piix_is_ichx - check if ICHx
- * @dev: PCI device to check
- *
- * returns 1 if ICHx, 0 otherwise.
- */
-static int piix_is_ichx(struct pci_dev *dev)
-{
- switch (dev->device) {
- case PCI_DEVICE_ID_INTEL_82801EB_1:
- case PCI_DEVICE_ID_INTEL_82801AA_1:
- case PCI_DEVICE_ID_INTEL_82801AB_1:
- case PCI_DEVICE_ID_INTEL_82801BA_8:
- case PCI_DEVICE_ID_INTEL_82801BA_9:
- case PCI_DEVICE_ID_INTEL_82801CA_10:
- case PCI_DEVICE_ID_INTEL_82801CA_11:
- case PCI_DEVICE_ID_INTEL_82801DB_1:
- case PCI_DEVICE_ID_INTEL_82801DB_10:
- case PCI_DEVICE_ID_INTEL_82801DB_11:
- case PCI_DEVICE_ID_INTEL_82801EB_11:
- case PCI_DEVICE_ID_INTEL_82801E_11:
- case PCI_DEVICE_ID_INTEL_ESB_2:
- case PCI_DEVICE_ID_INTEL_ICH6_19:
- case PCI_DEVICE_ID_INTEL_ICH7_21:
- case PCI_DEVICE_ID_INTEL_ESB2_18:
- case PCI_DEVICE_ID_INTEL_ICH8_6:
- return 1;
+ piix_set_pio_mode(drive, pio);
}
-
- return 0;
}
/**
- * init_chipset_piix - set up the PIIX chipset
+ * init_chipset_ich - set up the ICH chipset
* @dev: PCI device to set up
* @name: Name of the device
*
- * Initialize the PCI device as required. For the PIIX this turns
- * out to be nice and simple
+ * Initialize the PCI device as required. For the ICH this turns
+ * out to be nice and simple.
*/
-static unsigned int __devinit init_chipset_piix (struct pci_dev *dev, const char *name)
+static unsigned int __devinit init_chipset_ich(struct pci_dev *dev, const char *name)
{
- if (piix_is_ichx(dev)) {
- unsigned int extra = 0;
- pci_read_config_dword(dev, 0x54, &extra);
- pci_write_config_dword(dev, 0x54, extra|0x400);
- }
+ u32 extra = 0;
+
+ pci_read_config_dword(dev, 0x54, &extra);
+ pci_write_config_dword(dev, 0x54, extra | 0x400);
return 0;
}
@@ -362,9 +285,9 @@ static void piix_dma_clear_irq(ide_drive_t *drive)
u8 dma_stat;
/* clear the INTR & ERROR bits */
- dma_stat = hwif->INB(hwif->dma_status);
+ dma_stat = inb(hwif->dma_status);
/* Should we force the bit as well ? */
- hwif->OUTB(dma_stat, hwif->dma_status);
+ outb(dma_stat, hwif->dma_status);
}
struct ich_laptop {
@@ -379,6 +302,7 @@ struct ich_laptop {
static const struct ich_laptop ich_laptop[] = {
/* devid, subvendor, subdev */
+ { 0x27DF, 0x1025, 0x0102 }, /* ICH7 on Acer 5602aWLMi */
{ 0x27DF, 0x0005, 0x0280 }, /* ICH7 on Acer 5602WLMi */
{ 0x27DF, 0x1025, 0x0110 }, /* ICH7 on Acer 3682WLMi */
{ 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */
@@ -418,37 +342,12 @@ static u8 __devinit piix_cable_detect(ide_hwif_t *hwif)
static void __devinit init_hwif_piix(ide_hwif_t *hwif)
{
-#ifndef CONFIG_IA64
- if (!hwif->irq)
- hwif->irq = hwif->channel ? 15 : 14;
-#endif /* CONFIG_IA64 */
-
- if (hwif->pci_dev->device == PCI_DEVICE_ID_INTEL_82371MX) {
- /* This is a painful system best to let it self tune for now */
- return;
- }
-
- hwif->autodma = 0;
-
hwif->set_pio_mode = &piix_set_pio_mode;
hwif->set_dma_mode = &piix_set_dma_mode;
- hwif->drives[0].autotune = 1;
- hwif->drives[1].autotune = 1;
-
if (!hwif->dma_base)
return;
- /* ICHx need to clear the bmdma status for all interrupts */
- if (piix_is_ichx(hwif->pci_dev))
- hwif->ide_dma_clear_irq = &piix_dma_clear_irq;
-
- hwif->atapi_dma = 1;
-
- hwif->ultra_mask = hwif->cds->udma_mask;
- hwif->mwdma_mask = 0x06;
- hwif->swdma_mask = 0x04;
-
if (hwif->ultra_mask & 0x78) {
if (hwif->cbl != ATA_CBL_PATA40_SHORT)
hwif->cbl = piix_cable_detect(hwif);
@@ -456,30 +355,51 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif)
if (no_piix_dma)
hwif->ultra_mask = hwif->mwdma_mask = hwif->swdma_mask = 0;
+}
- hwif->ide_dma_check = &piix_config_drive_xfer_rate;
- if (!noautodma)
- hwif->autodma = 1;
+static void __devinit init_hwif_ich(ide_hwif_t *hwif)
+{
+ init_hwif_piix(hwif);
- hwif->drives[1].autodma = hwif->autodma;
- hwif->drives[0].autodma = hwif->autodma;
+ /* ICHx need to clear the BMDMA status for all interrupts */
+ if (hwif->dma_base)
+ hwif->ide_dma_clear_irq = &piix_dma_clear_irq;
}
+#ifndef CONFIG_IA64
+ #define IDE_HFLAGS_PIIX (IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE)
+#else
+ #define IDE_HFLAGS_PIIX IDE_HFLAG_BOOTABLE
+#endif
+
#define DECLARE_PIIX_DEV(name_str, udma) \
{ \
.name = name_str, \
- .init_chipset = init_chipset_piix, \
.init_hwif = init_hwif_piix, \
- .autodma = AUTODMA, \
.enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \
- .bootable = ON_BOARD, \
+ .host_flags = IDE_HFLAGS_PIIX, \
.pio_mask = ATA_PIO4, \
+ .swdma_mask = ATA_SWDMA2_ONLY, \
+ .mwdma_mask = ATA_MWDMA12_ONLY, \
.udma_mask = udma, \
}
-static ide_pci_device_t piix_pci_info[] __devinitdata = {
- /* 0 */ DECLARE_PIIX_DEV("PIIXa", 0x00), /* no udma */
- /* 1 */ DECLARE_PIIX_DEV("PIIXb", 0x00), /* no udma */
+#define DECLARE_ICH_DEV(name_str, udma) \
+ { \
+ .name = name_str, \
+ .init_chipset = init_chipset_ich, \
+ .init_hwif = init_hwif_ich, \
+ .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \
+ .host_flags = IDE_HFLAGS_PIIX, \
+ .pio_mask = ATA_PIO4, \
+ .swdma_mask = ATA_SWDMA2_ONLY, \
+ .mwdma_mask = ATA_MWDMA12_ONLY, \
+ .udma_mask = udma, \
+ }
+
+static const struct ide_port_info piix_pci_info[] __devinitdata = {
+ /* 0 */ DECLARE_PIIX_DEV("PIIXa", 0x00), /* no udma */
+ /* 1 */ DECLARE_PIIX_DEV("PIIXb", 0x00), /* no udma */
/* 2 */
{ /*
@@ -488,36 +408,35 @@ static ide_pci_device_t piix_pci_info[] __devinitdata = {
* of the bit 14 of the IDETIM register at offset 0x6c
*/
.name = "MPIIX",
- .init_hwif = init_hwif_piix,
- .autodma = NODMA,
.enablebits = {{0x6d,0xc0,0x80}, {0x6d,0xc0,0xc0}},
- .bootable = ON_BOARD,
- .host_flags = IDE_HFLAG_ISA_PORTS,
+ .host_flags = IDE_HFLAG_ISA_PORTS | IDE_HFLAG_NO_DMA |
+ IDE_HFLAGS_PIIX,
.pio_mask = ATA_PIO4,
+ /* This is a painful system best to let it self tune for now */
},
- /* 3 */ DECLARE_PIIX_DEV("PIIX3", 0x00), /* no udma */
- /* 4 */ DECLARE_PIIX_DEV("PIIX4", 0x07), /* udma0-2 */
- /* 5 */ DECLARE_PIIX_DEV("ICH0", 0x07), /* udma0-2 */
- /* 6 */ DECLARE_PIIX_DEV("PIIX4", 0x07), /* udma0-2 */
- /* 7 */ DECLARE_PIIX_DEV("ICH", 0x1f), /* udma0-4 */
- /* 8 */ DECLARE_PIIX_DEV("PIIX4", 0x1f), /* udma0-4 */
- /* 9 */ DECLARE_PIIX_DEV("PIIX4", 0x07), /* udma0-2 */
- /* 10 */ DECLARE_PIIX_DEV("ICH2", 0x3f), /* udma0-5 */
- /* 11 */ DECLARE_PIIX_DEV("ICH2M", 0x3f), /* udma0-5 */
- /* 12 */ DECLARE_PIIX_DEV("ICH3M", 0x3f), /* udma0-5 */
- /* 13 */ DECLARE_PIIX_DEV("ICH3", 0x3f), /* udma0-5 */
- /* 14 */ DECLARE_PIIX_DEV("ICH4", 0x3f), /* udma0-5 */
- /* 15 */ DECLARE_PIIX_DEV("ICH5", 0x3f), /* udma0-5 */
- /* 16 */ DECLARE_PIIX_DEV("C-ICH", 0x3f), /* udma0-5 */
- /* 17 */ DECLARE_PIIX_DEV("ICH4", 0x3f), /* udma0-5 */
- /* 18 */ DECLARE_PIIX_DEV("ICH5-SATA", 0x3f), /* udma0-5 */
- /* 19 */ DECLARE_PIIX_DEV("ICH5", 0x3f), /* udma0-5 */
- /* 20 */ DECLARE_PIIX_DEV("ICH6", 0x3f), /* udma0-5 */
- /* 21 */ DECLARE_PIIX_DEV("ICH7", 0x3f), /* udma0-5 */
- /* 22 */ DECLARE_PIIX_DEV("ICH4", 0x3f), /* udma0-5 */
- /* 23 */ DECLARE_PIIX_DEV("ESB2", 0x3f), /* udma0-5 */
- /* 24 */ DECLARE_PIIX_DEV("ICH8M", 0x3f), /* udma0-5 */
+ /* 3 */ DECLARE_PIIX_DEV("PIIX3", 0x00), /* no udma */
+ /* 4 */ DECLARE_PIIX_DEV("PIIX4", ATA_UDMA2),
+ /* 5 */ DECLARE_ICH_DEV("ICH0", ATA_UDMA2),
+ /* 6 */ DECLARE_PIIX_DEV("PIIX4", ATA_UDMA2),
+ /* 7 */ DECLARE_ICH_DEV("ICH", ATA_UDMA4),
+ /* 8 */ DECLARE_PIIX_DEV("PIIX4", ATA_UDMA4),
+ /* 9 */ DECLARE_PIIX_DEV("PIIX4", ATA_UDMA2),
+ /* 10 */ DECLARE_ICH_DEV("ICH2", ATA_UDMA5),
+ /* 11 */ DECLARE_ICH_DEV("ICH2M", ATA_UDMA5),
+ /* 12 */ DECLARE_ICH_DEV("ICH3M", ATA_UDMA5),
+ /* 13 */ DECLARE_ICH_DEV("ICH3", ATA_UDMA5),
+ /* 14 */ DECLARE_ICH_DEV("ICH4", ATA_UDMA5),
+ /* 15 */ DECLARE_ICH_DEV("ICH5", ATA_UDMA5),
+ /* 16 */ DECLARE_ICH_DEV("C-ICH", ATA_UDMA5),
+ /* 17 */ DECLARE_ICH_DEV("ICH4", ATA_UDMA5),
+ /* 18 */ DECLARE_ICH_DEV("ICH5-SATA", ATA_UDMA5),
+ /* 19 */ DECLARE_ICH_DEV("ICH5", ATA_UDMA5),
+ /* 20 */ DECLARE_ICH_DEV("ICH6", ATA_UDMA5),
+ /* 21 */ DECLARE_ICH_DEV("ICH7", ATA_UDMA5),
+ /* 22 */ DECLARE_ICH_DEV("ICH4", ATA_UDMA5),
+ /* 23 */ DECLARE_ICH_DEV("ESB2", ATA_UDMA5),
+ /* 24 */ DECLARE_ICH_DEV("ICH8M", ATA_UDMA5),
};
/**
@@ -531,9 +450,7 @@ static ide_pci_device_t piix_pci_info[] __devinitdata = {
static int __devinit piix_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- ide_pci_device_t *d = &piix_pci_info[id->driver_data];
-
- return ide_setup_pci_device(dev, d);
+ return ide_setup_pci_device(dev, &piix_pci_info[id->driver_data]);
}
/**
@@ -565,34 +482,34 @@ static void __devinit piix_check_450nx(void)
printk(KERN_WARNING "piix: A BIOS update may resolve this.\n");
}
-static struct pci_device_id piix_pci_tbl[] = {
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371MX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5},
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6},
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7},
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82372FB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8},
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9},
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10},
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11},
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12},
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_11,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13},
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_11,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14},
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_11,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15},
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_11, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16},
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_10,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17},
+static const struct pci_device_id piix_pci_tbl[] = {
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371FB_0), 0 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371FB_1), 1 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371MX), 2 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371SB_1), 3 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371AB), 4 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801AB_1), 5 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82443MX_1), 6 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801AA_1), 7 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82372FB_1), 8 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82451NX), 9 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801BA_9), 10 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801BA_8), 11 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801CA_10), 12 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801CA_11), 13 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_11), 14 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801EB_11), 15 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801E_11), 16 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_10), 17 },
#ifdef CONFIG_BLK_DEV_IDE_SATA
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18},
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801EB_1), 18 },
#endif
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 19},
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_19, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 20},
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 21},
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 22},
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_18, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 23},
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 24},
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB_2), 19 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH6_19), 20 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH7_21), 21 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_1), 22 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB2_18), 23 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH8_6), 24 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, piix_pci_tbl);
diff --git a/drivers/ide/pci/rz1000.c b/drivers/ide/pci/rz1000.c
index 10e1ae7a4a02..6b10ae260fa2 100644
--- a/drivers/ide/pci/rz1000.c
+++ b/drivers/ide/pci/rz1000.c
@@ -35,13 +35,13 @@ static void __devinit init_hwif_rz1000 (ide_hwif_t *hwif)
u16 reg;
struct pci_dev *dev = hwif->pci_dev;
- hwif->chipset = ide_rz1000;
if (!pci_read_config_word (dev, 0x40, &reg) &&
!pci_write_config_word(dev, 0x40, reg & 0xdfff)) {
printk(KERN_INFO "%s: disabled chipset read-ahead "
"(buggy RZ1000/RZ1001)\n", hwif->name);
} else {
- hwif->serialized = 1;
+ if (hwif->mate)
+ hwif->mate->serialized = hwif->serialized = 1;
hwif->drives[0].no_unmask = 1;
hwif->drives[1].no_unmask = 1;
printk(KERN_INFO "%s: serialized, disabled unmasking "
@@ -49,11 +49,11 @@ static void __devinit init_hwif_rz1000 (ide_hwif_t *hwif)
}
}
-static ide_pci_device_t rz1000_chipset __devinitdata = {
+static const struct ide_port_info rz1000_chipset __devinitdata = {
.name = "RZ100x",
.init_hwif = init_hwif_rz1000,
- .autodma = NODMA,
- .bootable = ON_BOARD,
+ .chipset = ide_rz1000,
+ .host_flags = IDE_HFLAG_NO_DMA | IDE_HFLAG_BOOTABLE,
};
static int __devinit rz1000_init_one(struct pci_dev *dev, const struct pci_device_id *id)
@@ -61,9 +61,9 @@ static int __devinit rz1000_init_one(struct pci_dev *dev, const struct pci_devic
return ide_setup_pci_device(dev, &rz1000_chipset);
}
-static struct pci_device_id rz1000_pci_tbl[] = {
- { PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- { PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+static const struct pci_device_id rz1000_pci_tbl[] = {
+ { PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000), 0 },
+ { PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001), 0 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, rz1000_pci_tbl);
diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c
index ee0e3f554d9a..707d5ff66b03 100644
--- a/drivers/ide/pci/sc1200.c
+++ b/drivers/ide/pci/sc1200.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/sc1200.c Version 0.95 Jun 16 2007
+ * linux/drivers/ide/pci/sc1200.c Version 0.97 Aug 3 2007
*
* Copyright (C) 2000-2002 Mark Lord <mlord@pobox.com>
* Copyright (C) 2007 Bartlomiej Zolnierkiewicz
@@ -186,8 +186,7 @@ static void sc1200_set_dma_mode(ide_drive_t *drive, const u8 mode)
}
break;
default:
- BUG();
- break;
+ return;
}
if (unit == 0) { /* are we configuring drive0? */
@@ -199,19 +198,6 @@ static void sc1200_set_dma_mode(ide_drive_t *drive, const u8 mode)
}
}
-/*
- * sc1200_config_dma() handles selection/setting of DMA/UDMA modes
- * for both the chipset and drive.
- */
-static int sc1200_config_dma (ide_drive_t *drive)
-{
- if (ide_tune_dma(drive))
- return 0;
-
- return 1;
-}
-
-
/* Replacement for the standard ide_dma_end action in
* dma_proc.
*
@@ -337,17 +323,18 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state)
pci_disable_device(dev);
pci_set_power_state(dev, pci_choose_state(dev, state));
- dev->current_state = state.event;
return 0;
}
static int sc1200_resume (struct pci_dev *dev)
{
ide_hwif_t *hwif = NULL;
+ int i;
+
+ i = pci_enable_device(dev);
+ if (i)
+ return i;
- pci_set_power_state(dev, PCI_D0); // bring chip back from sleep state
- dev->current_state = PM_EVENT_ON;
- pci_enable_device(dev);
//
// loop over all interfaces that are part of this pci device:
//
@@ -375,10 +362,6 @@ static int sc1200_resume (struct pci_dev *dev)
*/
static void __devinit init_hwif_sc1200 (ide_hwif_t *hwif)
{
- if (hwif->mate)
- hwif->serialized = hwif->mate->serialized = 1;
- hwif->autodma = 0;
-
hwif->set_pio_mode = &sc1200_set_pio_mode;
hwif->set_dma_mode = &sc1200_set_dma_mode;
@@ -386,27 +369,19 @@ static void __devinit init_hwif_sc1200 (ide_hwif_t *hwif)
return;
hwif->udma_filter = sc1200_udma_filter;
- hwif->ide_dma_check = &sc1200_config_dma;
hwif->ide_dma_end = &sc1200_ide_dma_end;
-
- if (!noautodma)
- hwif->autodma = 1;
-
- hwif->atapi_dma = 1;
- hwif->ultra_mask = 0x07;
- hwif->mwdma_mask = 0x07;
-
- hwif->drives[0].autodma = hwif->autodma;
- hwif->drives[1].autodma = hwif->autodma;
}
-static ide_pci_device_t sc1200_chipset __devinitdata = {
+static const struct ide_port_info sc1200_chipset __devinitdata = {
.name = "SC1200",
.init_hwif = init_hwif_sc1200,
- .autodma = AUTODMA,
- .bootable = ON_BOARD,
- .host_flags = IDE_HFLAG_ABUSE_DMA_MODES | IDE_HFLAG_POST_SET_MODE,
+ .host_flags = IDE_HFLAG_SERIALIZE |
+ IDE_HFLAG_POST_SET_MODE |
+ IDE_HFLAG_ABUSE_DMA_MODES |
+ IDE_HFLAG_BOOTABLE,
.pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA2,
};
static int __devinit sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id)
@@ -414,8 +389,8 @@ static int __devinit sc1200_init_one(struct pci_dev *dev, const struct pci_devic
return ide_setup_pci_device(dev, &sc1200_chipset);
}
-static struct pci_device_id sc1200_pci_tbl[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_IDE), 0},
+static const struct pci_device_id sc1200_pci_tbl[] = {
+ { PCI_VDEVICE(NS, PCI_DEVICE_ID_NS_SCx200_IDE), 0},
{ 0, },
};
MODULE_DEVICE_TABLE(pci, sc1200_pci_tbl);
diff --git a/drivers/ide/pci/scc_pata.c b/drivers/ide/pci/scc_pata.c
index 67f06dd11b34..ebb7132b9b84 100644
--- a/drivers/ide/pci/scc_pata.c
+++ b/drivers/ide/pci/scc_pata.c
@@ -284,28 +284,6 @@ static void scc_set_dma_mode(ide_drive_t *drive, const u8 speed)
}
/**
- * scc_configure_drive_for_dma - set up for DMA transfers
- * @drive: drive we are going to set up
- *
- * Set up the drive for DMA, tune the controller and drive as
- * required.
- * If the drive isn't suitable for DMA or we hit other problems
- * then we will drop down to PIO and set up PIO appropriately.
- * (return -1)
- */
-
-static int scc_config_drive_for_dma(ide_drive_t *drive)
-{
- if (ide_tune_dma(drive))
- return 0;
-
- if (ide_use_fast_pio(drive))
- ide_set_max_pio(drive);
-
- return -1;
-}
-
-/**
* scc_ide_dma_setup - begin a DMA phase
* @drive: target device
*
@@ -494,7 +472,7 @@ static u8 scc_udma_filter(ide_drive_t *drive)
if ((drive->media != ide_disk) && (mask & 0xE0)) {
printk(KERN_INFO "%s: limit %s to UDMA4\n",
SCC_PATA_NAME, drive->name);
- mask = 0x1F;
+ mask = ATA_UDMA4;
}
return mask;
@@ -560,12 +538,13 @@ static int setup_mmio_scc (struct pci_dev *dev, const char *name)
/**
* init_setup_scc - set up an SCC PATA Controller
* @dev: PCI device
- * @d: IDE PCI device
+ * @d: IDE port info
*
* Perform the initial set up for this device.
*/
-static int __devinit init_setup_scc(struct pci_dev *dev, ide_pci_device_t *d)
+static int __devinit init_setup_scc(struct pci_dev *dev,
+ const struct ide_port_info *d)
{
unsigned long ctl_base;
unsigned long dma_base;
@@ -702,45 +681,29 @@ static void __devinit init_hwif_scc(ide_hwif_t *hwif)
hwif->ide_dma_end = scc_ide_dma_end;
hwif->set_pio_mode = scc_set_pio_mode;
hwif->set_dma_mode = scc_set_dma_mode;
- hwif->ide_dma_check = scc_config_drive_for_dma;
hwif->ide_dma_test_irq = scc_dma_test_irq;
hwif->udma_filter = scc_udma_filter;
- hwif->drives[0].autotune = IDE_TUNE_AUTO;
- hwif->drives[1].autotune = IDE_TUNE_AUTO;
-
- if (in_be32((void __iomem *)(hwif->config_data + 0xff0)) & CCKCTRL_ATACLKOEN) {
- hwif->ultra_mask = 0x7f; /* 133MHz */
- } else {
- hwif->ultra_mask = 0x3f; /* 100MHz */
- }
- hwif->mwdma_mask = 0x00;
- hwif->swdma_mask = 0x00;
- hwif->atapi_dma = 1;
+ if (in_be32((void __iomem *)(hwif->config_data + 0xff0)) & CCKCTRL_ATACLKOEN)
+ hwif->ultra_mask = ATA_UDMA6; /* 133MHz */
+ else
+ hwif->ultra_mask = ATA_UDMA5; /* 100MHz */
/* we support 80c cable only. */
hwif->cbl = ATA_CBL_PATA80;
-
- hwif->autodma = 0;
- if (!noautodma)
- hwif->autodma = 1;
- hwif->drives[0].autodma = hwif->autodma;
- hwif->drives[1].autodma = hwif->autodma;
}
#define DECLARE_SCC_DEV(name_str) \
{ \
.name = name_str, \
- .init_setup = init_setup_scc, \
.init_iops = init_iops_scc, \
.init_hwif = init_hwif_scc, \
- .autodma = AUTODMA, \
- .bootable = ON_BOARD, \
- .host_flags = IDE_HFLAG_SINGLE, \
+ .host_flags = IDE_HFLAG_SINGLE | \
+ IDE_HFLAG_BOOTABLE, \
.pio_mask = ATA_PIO4, \
}
-static ide_pci_device_t scc_chipsets[] __devinitdata = {
+static const struct ide_port_info scc_chipsets[] __devinitdata = {
/* 0 */ DECLARE_SCC_DEV("sccIDE"),
};
@@ -755,8 +718,7 @@ static ide_pci_device_t scc_chipsets[] __devinitdata = {
static int __devinit scc_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- ide_pci_device_t *d = &scc_chipsets[id->driver_data];
- return d->init_setup(dev, d);
+ return init_setup_scc(dev, &scc_chipsets[id->driver_data]);
}
/**
@@ -793,8 +755,8 @@ static void __devexit scc_remove(struct pci_dev *dev)
memset(ports, 0, sizeof(*ports));
}
-static struct pci_device_id scc_pci_tbl[] = {
- { PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_SCC_ATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+static const struct pci_device_id scc_pci_tbl[] = {
+ { PCI_VDEVICE(TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_SCC_ATA), 0 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, scc_pci_tbl);
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
index 49ec0ac64a4b..a7280311357b 100644
--- a/drivers/ide/pci/serverworks.c
+++ b/drivers/ide/pci/serverworks.c
@@ -97,6 +97,7 @@ static u8 svwks_udma_filter(ide_drive_t *drive)
mode = 2;
switch(mode) {
+ case 3: mask = 0x3f; break;
case 2: mask = 0x1f; break;
case 1: mask = 0x07; break;
default: mask = 0x00; break;
@@ -157,13 +158,6 @@ static void svwks_set_dma_mode(ide_drive_t *drive, const u8 speed)
u8 ultra_enable = 0, ultra_timing = 0, dma_timing = 0;
- /* If we are about to put a disk into UDMA mode we screwed up.
- Our code assumes we never _ever_ do this on an OSB4 */
-
- if(dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4 &&
- drive->media == ide_disk && speed >= XFER_UDMA_0)
- BUG();
-
pci_read_config_byte(dev, (0x56|hwif->channel), &ultra_timing);
pci_read_config_byte(dev, 0x54, &ultra_enable);
@@ -195,19 +189,6 @@ static void svwks_set_dma_mode(ide_drive_t *drive, const u8 speed)
pci_write_config_byte(dev, 0x54, ultra_enable);
}
-static int svwks_config_drive_xfer_rate (ide_drive_t *drive)
-{
- drive->init_speed = 0;
-
- if (ide_tune_dma(drive))
- return 0;
-
- if (ide_use_fast_pio(drive))
- ide_set_max_pio(drive);
-
- return -1;
-}
-
static unsigned int __devinit init_chipset_svwks (struct pci_dev *dev, const char *name)
{
unsigned int reg;
@@ -372,105 +353,62 @@ static u8 __devinit ata66_svwks(ide_hwif_t *hwif)
static void __devinit init_hwif_svwks (ide_hwif_t *hwif)
{
- if (!hwif->irq)
- hwif->irq = hwif->channel ? 15 : 14;
-
hwif->set_pio_mode = &svwks_set_pio_mode;
hwif->set_dma_mode = &svwks_set_dma_mode;
hwif->udma_filter = &svwks_udma_filter;
- hwif->atapi_dma = 1;
-
- if (hwif->pci_dev->device != PCI_DEVICE_ID_SERVERWORKS_OSB4IDE)
- hwif->ultra_mask = 0x3f;
-
- hwif->mwdma_mask = 0x07;
-
- hwif->autodma = 0;
-
- hwif->drives[0].autotune = 1;
- hwif->drives[1].autotune = 1;
-
if (!hwif->dma_base)
return;
- hwif->ide_dma_check = &svwks_config_drive_xfer_rate;
if (hwif->pci_dev->device != PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
if (hwif->cbl != ATA_CBL_PATA40_SHORT)
hwif->cbl = ata66_svwks(hwif);
}
- if (!noautodma)
- hwif->autodma = 1;
-
- hwif->drives[0].autodma = hwif->drives[1].autodma = 1;
-}
-
-static int __devinit init_setup_svwks (struct pci_dev *dev, ide_pci_device_t *d)
-{
- return ide_setup_pci_device(dev, d);
-}
-
-static int __devinit init_setup_csb6 (struct pci_dev *dev, ide_pci_device_t *d)
-{
- if (!(PCI_FUNC(dev->devfn) & 1)) {
- d->bootable = NEVER_BOARD;
- if (dev->resource[0].start == 0x01f1)
- d->bootable = ON_BOARD;
- }
-
- if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE ||
- dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2) &&
- (!(PCI_FUNC(dev->devfn) & 1)))
- d->host_flags |= IDE_HFLAG_SINGLE;
- else
- d->host_flags &= ~IDE_HFLAG_SINGLE;
-
- return ide_setup_pci_device(dev, d);
}
-static ide_pci_device_t serverworks_chipsets[] __devinitdata = {
+static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
{ /* 0 */
.name = "SvrWks OSB4",
- .init_setup = init_setup_svwks,
.init_chipset = init_chipset_svwks,
.init_hwif = init_hwif_svwks,
- .autodma = AUTODMA,
- .bootable = ON_BOARD,
+ .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE,
.pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = 0x00, /* UDMA is problematic on OSB4 */
},{ /* 1 */
.name = "SvrWks CSB5",
- .init_setup = init_setup_svwks,
.init_chipset = init_chipset_svwks,
.init_hwif = init_hwif_svwks,
- .autodma = AUTODMA,
- .bootable = ON_BOARD,
+ .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE,
.pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA5,
},{ /* 2 */
.name = "SvrWks CSB6",
- .init_setup = init_setup_csb6,
.init_chipset = init_chipset_svwks,
.init_hwif = init_hwif_svwks,
- .autodma = AUTODMA,
- .bootable = ON_BOARD,
+ .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE,
.pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA5,
},{ /* 3 */
.name = "SvrWks CSB6",
- .init_setup = init_setup_csb6,
.init_chipset = init_chipset_svwks,
.init_hwif = init_hwif_svwks,
- .autodma = AUTODMA,
- .bootable = ON_BOARD,
- .host_flags = IDE_HFLAG_SINGLE,
+ .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_SINGLE |
+ IDE_HFLAG_BOOTABLE,
.pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA5,
},{ /* 4 */
.name = "SvrWks HT1000",
- .init_setup = init_setup_svwks,
.init_chipset = init_chipset_svwks,
.init_hwif = init_hwif_svwks,
- .autodma = AUTODMA,
- .bootable = ON_BOARD,
- .host_flags = IDE_HFLAG_SINGLE,
+ .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_SINGLE |
+ IDE_HFLAG_BOOTABLE,
.pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA5,
}
};
@@ -485,17 +423,29 @@ static ide_pci_device_t serverworks_chipsets[] __devinitdata = {
static int __devinit svwks_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- ide_pci_device_t *d = &serverworks_chipsets[id->driver_data];
+ struct ide_port_info d;
+ u8 idx = id->driver_data;
+
+ d = serverworks_chipsets[idx];
+
+ if (idx == 2 || idx == 3) {
+ if ((PCI_FUNC(dev->devfn) & 1) == 0) {
+ if (pci_resource_start(dev, 0) != 0x01f1)
+ d.host_flags &= ~IDE_HFLAG_BOOTABLE;
+ d.host_flags |= IDE_HFLAG_SINGLE;
+ } else
+ d.host_flags &= ~IDE_HFLAG_SINGLE;
+ }
- return d->init_setup(dev, d);
+ return ide_setup_pci_device(dev, &d);
}
-static struct pci_device_id svwks_pci_tbl[] = {
- { PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- { PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
- { PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
- { PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
- { PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
+static const struct pci_device_id svwks_pci_tbl[] = {
+ { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE), 0 },
+ { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE), 1 },
+ { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE), 2 },
+ { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2), 3 },
+ { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000IDE), 4 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, svwks_pci_tbl);
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index 85ffaaa39b1b..de820aa58cd0 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -29,6 +29,7 @@
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/blkdev.h>
+#include <linux/scatterlist.h>
#include <linux/ioc4.h>
#include <asm/io.h>
@@ -295,20 +296,6 @@ static void sgiioc4_set_dma_mode(ide_drive_t *drive, const u8 speed)
{
}
-static int sgiioc4_ide_dma_check(ide_drive_t *drive)
-{
- if (ide_tune_dma(drive))
- return 0;
-
- /*
- * ->set_pio_mode is not implemented currently
- * so this is just for the completness
- */
- ide_set_max_pio(drive);
-
- return -1;
-}
-
/* returns 1 if dma irq issued, 0 otherwise */
static int
sgiioc4_ide_dma_test_irq(ide_drive_t * drive)
@@ -537,7 +524,7 @@ sgiioc4_build_dma_table(ide_drive_t * drive, struct request *rq, int ddir)
}
}
- sg++;
+ sg = sg_next(sg);
i--;
}
@@ -605,13 +592,11 @@ ide_init_sgiioc4(ide_hwif_t * hwif)
if (hwif->dma_base == 0)
return;
- hwif->atapi_dma = 1;
- hwif->mwdma_mask = 0x04;
+ hwif->mwdma_mask = ATA_MWDMA2_ONLY;
hwif->dma_setup = &sgiioc4_ide_dma_setup;
hwif->dma_start = &sgiioc4_ide_dma_start;
hwif->ide_dma_end = &sgiioc4_ide_dma_end;
- hwif->ide_dma_check = &sgiioc4_ide_dma_check;
hwif->ide_dma_on = &sgiioc4_ide_dma_on;
hwif->dma_off_quietly = &sgiioc4_dma_off_quietly;
hwif->ide_dma_test_irq = &sgiioc4_ide_dma_test_irq;
@@ -629,6 +614,7 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
void __iomem *virt_base;
ide_hwif_t *hwif;
int h;
+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
/*
* Find an empty HWIF; if none available, return -ENOMEM.
@@ -669,10 +655,12 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
}
if (hwif->io_ports[IDE_DATA_OFFSET] != cmd_base) {
+ hw_regs_t hw;
+
/* Initialize the IO registers */
- sgiioc4_init_hwif_ports(&hwif->hw, cmd_base, ctl, irqport);
- memcpy(hwif->io_ports, hwif->hw.io_ports,
- sizeof (hwif->io_ports));
+ memset(&hw, 0, sizeof(hw));
+ sgiioc4_init_hwif_ports(&hw, cmd_base, ctl, irqport);
+ memcpy(hwif->io_ports, hw.io_ports, sizeof(hwif->io_ports));
hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
}
@@ -688,22 +676,16 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
/* Initializing chipset IRQ Registers */
writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4));
- hwif->autodma = 0;
-
- if (dma_base && ide_dma_sgiioc4(hwif, dma_base) == 0) {
- hwif->autodma = 1;
- hwif->drives[1].autodma = hwif->drives[0].autodma = 1;
- } else
+ if (dma_base == 0 || ide_dma_sgiioc4(hwif, dma_base))
printk(KERN_INFO "%s: %s Bus-Master DMA disabled\n",
hwif->name, DRV_NAME);
ide_init_sgiioc4(hwif);
- if (probe_hwif_init(hwif))
- return -EIO;
+ idx[0] = hwif->index;
- /* Create /proc/ide entries */
- ide_proc_register_port(hwif);
+ if (ide_device_add(idx))
+ return -EIO;
return 0;
}
@@ -711,14 +693,12 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
static unsigned int __devinit
pci_init_sgiioc4(struct pci_dev *dev)
{
- unsigned int class_rev;
int ret;
- pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
- class_rev &= 0xff;
printk(KERN_INFO "%s: IDE controller at PCI slot %s, revision %d\n",
- DRV_NAME, pci_name(dev), class_rev);
- if (class_rev < IOC4_SUPPORTED_FIRMWARE_REV) {
+ DRV_NAME, pci_name(dev), dev->revision);
+
+ if (dev->revision < IOC4_SUPPORTED_FIRMWARE_REV) {
printk(KERN_ERR "Skipping %s IDE controller in slot %s: "
"firmware is obsolete - please upgrade to "
"revision46 or higher\n",
diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
index ce7784996d12..6d99441c605b 100644
--- a/drivers/ide/pci/siimage.c
+++ b/drivers/ide/pci/siimage.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/siimage.c Version 1.16 Jul 13 2007
+ * linux/drivers/ide/pci/siimage.c Version 1.18 Oct 18 2007
*
* Copyright (C) 2001-2002 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2003 Red Hat <alan@redhat.com>
@@ -26,7 +26,7 @@
*
* If you have strange problems with nVidia chipset systems please
* see the SI support documentation and update your system BIOS
- * if neccessary
+ * if necessary
*
* The Dell DRAC4 has some interesting features including effectively hot
* unplugging/replugging the virtual CD interface when the DRAC is reset.
@@ -57,8 +57,8 @@
static int pdev_is_sata(struct pci_dev *pdev)
{
- switch(pdev->device)
- {
+#ifdef CONFIG_BLK_DEV_IDE_SATA
+ switch(pdev->device) {
case PCI_DEVICE_ID_SII_3112:
case PCI_DEVICE_ID_SII_1210SA:
return 1;
@@ -66,9 +66,10 @@ static int pdev_is_sata(struct pci_dev *pdev)
return 0;
}
BUG();
+#endif
return 0;
}
-
+
/**
* is_sata - check if hwif is SATA
* @hwif: interface to check
@@ -136,7 +137,7 @@ static inline unsigned long siimage_seldev(ide_drive_t *drive, int r)
* SI3112 SATA controller life is a bit simpler.
*/
-static u8 sil_udma_filter(ide_drive_t *drive)
+static u8 sil_pata_udma_filter(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
unsigned long base = (unsigned long) hwif->hwif_data;
@@ -147,23 +148,23 @@ static u8 sil_udma_filter(ide_drive_t *drive)
else
pci_read_config_byte(hwif->pci_dev, 0x8A, &scsc);
- if (is_sata(hwif)) {
- mask = strstr(drive->id->model, "Maxtor") ? 0x3f : 0x7f;
- goto out;
- }
-
if ((scsc & 0x30) == 0x10) /* 133 */
- mask = 0x7f;
+ mask = ATA_UDMA6;
else if ((scsc & 0x30) == 0x20) /* 2xPCI */
- mask = 0x7f;
+ mask = ATA_UDMA6;
else if ((scsc & 0x30) == 0x00) /* 100 */
- mask = 0x3f;
+ mask = ATA_UDMA5;
else /* Disabled ? */
BUG();
-out:
+
return mask;
}
+static u8 sil_sata_udma_filter(ide_drive_t *drive)
+{
+ return strstr(drive->id->model, "Maxtor") ? ATA_UDMA5 : ATA_UDMA6;
+}
+
/**
* sil_set_pio_mode - set host controller for PIO mode
* @drive: drive
@@ -180,7 +181,7 @@ static void sil_set_pio_mode(ide_drive_t *drive, u8 pio)
const u16 data_speed[] = { 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1 };
ide_hwif_t *hwif = HWIF(drive);
- ide_drive_t *pair = &hwif->drives[drive->dn ^ 1];
+ ide_drive_t *pair = ide_get_paired_drive(drive);
u32 speedt = 0;
u16 speedp = 0;
unsigned long addr = siimage_seldev(drive, 0x04);
@@ -311,27 +312,6 @@ static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed)
}
}
-/**
- * siimage_configure_drive_for_dma - set up for DMA transfers
- * @drive: drive we are going to set up
- *
- * Set up the drive for DMA, tune the controller and drive as
- * required. If the drive isn't suitable for DMA or we hit
- * other problems then we will drop down to PIO and set up
- * PIO appropriately
- */
-
-static int siimage_config_drive_for_dma (ide_drive_t *drive)
-{
- if (ide_tune_dma(drive))
- return 0;
-
- if (ide_use_fast_pio(drive))
- ide_set_max_pio(drive);
-
- return -1;
-}
-
/* returns 1 if dma irq issued, 0 otherwise */
static int siimage_io_ide_dma_test_irq (ide_drive_t *drive)
{
@@ -361,10 +341,11 @@ static int siimage_io_ide_dma_test_irq (ide_drive_t *drive)
static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
- unsigned long base = (unsigned long)hwif->hwif_data;
unsigned long addr = siimage_selreg(hwif, 0x1);
if (SATA_ERROR_REG) {
+ unsigned long base = (unsigned long)hwif->hwif_data;
+
u32 ext_stat = readl((void __iomem *)(base + 0x10));
u8 watchdog = 0;
if (ext_stat & ((hwif->channel) ? 0x40 : 0x10)) {
@@ -397,7 +378,7 @@ static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive)
}
/**
- * siimage_busproc - bus isolation ioctl
+ * sil_sata_busproc - bus isolation IOCTL
* @drive: drive to isolate/restore
* @state: bus state to set
*
@@ -405,8 +386,8 @@ static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive)
* SATA controller the work required is quite limited, we
* just have to clean up the statistics
*/
-
-static int siimage_busproc (ide_drive_t * drive, int state)
+
+static int sil_sata_busproc(ide_drive_t * drive, int state)
{
ide_hwif_t *hwif = HWIF(drive);
u32 stat_config = 0;
@@ -438,14 +419,14 @@ static int siimage_busproc (ide_drive_t * drive, int state)
}
/**
- * siimage_reset_poll - wait for sata reset
+ * sil_sata_reset_poll - wait for SATA reset
* @drive: drive we are resetting
*
* Poll the SATA phy and see whether it has come back from the dead
* yet.
*/
-
-static int siimage_reset_poll (ide_drive_t *drive)
+
+static int sil_sata_reset_poll(ide_drive_t *drive)
{
if (SATA_STATUS_REG) {
ide_hwif_t *hwif = HWIF(drive);
@@ -457,27 +438,22 @@ static int siimage_reset_poll (ide_drive_t *drive)
HWGROUP(drive)->polling = 0;
return ide_started;
}
- return 0;
- } else {
- return 0;
}
+
+ return 0;
}
/**
- * siimage_pre_reset - reset hook
+ * sil_sata_pre_reset - reset hook
* @drive: IDE device being reset
*
* For the SATA devices we need to handle recalibration/geometry
* differently
*/
-
-static void siimage_pre_reset (ide_drive_t *drive)
-{
- if (drive->media != ide_disk)
- return;
- if (is_sata(HWIF(drive)))
- {
+static void sil_sata_pre_reset(ide_drive_t *drive)
+{
+ if (drive->media == ide_disk) {
drive->special.b.set_geometry = 0;
drive->special.b.recalibrate = 0;
}
@@ -523,7 +499,6 @@ static void siimage_reset (ide_drive_t *drive)
drive->failures++;
}
}
-
}
/**
@@ -661,13 +636,9 @@ static unsigned int setup_mmio_siimage (struct pci_dev *dev, const char *name)
static unsigned int __devinit init_chipset_siimage(struct pci_dev *dev, const char *name)
{
- u32 class_rev = 0;
- u8 tmpbyte = 0;
- u8 BA5_EN = 0;
+ u8 rev = dev->revision, tmpbyte = 0, BA5_EN = 0;
- pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
- class_rev &= 0xff;
- pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (class_rev) ? 1 : 255);
+ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, rev ? 1 : 255);
pci_read_config_byte(dev, 0x8A, &BA5_EN);
if ((BA5_EN & 0x01) || (pci_resource_start(dev, 5))) {
@@ -783,16 +754,11 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
hwif->sata_misc[SATA_IEN_OFFSET] = base + 0x148;
}
- hw.irq = hwif->pci_dev->irq;
+ memcpy(hwif->io_ports, hw.io_ports, sizeof(hwif->io_ports));
- memcpy(&hwif->hw, &hw, sizeof(hw));
- memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->hw.io_ports));
+ hwif->irq = dev->irq;
- hwif->irq = hw.irq;
-
- base = (unsigned long) addr;
-
- hwif->dma_base = base + (ch ? 0x08 : 0x00);
+ hwif->dma_base = (unsigned long)addr + (ch ? 0x08 : 0x00);
hwif->mmio = 1;
}
@@ -846,19 +812,14 @@ static void __devinit siimage_fixup(ide_hwif_t *hwif)
static void __devinit init_iops_siimage(ide_hwif_t *hwif)
{
- struct pci_dev *dev = hwif->pci_dev;
- u32 class_rev = 0;
-
- pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
- class_rev &= 0xff;
-
hwif->hwif_data = NULL;
/* Pessimal until we finish probing */
hwif->rqsize = 15;
- if (pci_get_drvdata(dev) == NULL)
+ if (pci_get_drvdata(hwif->pci_dev) == NULL)
return;
+
init_mmio_iops_siimage(hwif);
}
@@ -894,38 +855,32 @@ static u8 __devinit ata66_siimage(ide_hwif_t *hwif)
static void __devinit init_hwif_siimage(ide_hwif_t *hwif)
{
- hwif->autodma = 0;
-
+ u8 sata = is_sata(hwif);
+
hwif->resetproc = &siimage_reset;
hwif->set_pio_mode = &sil_set_pio_mode;
hwif->set_dma_mode = &sil_set_dma_mode;
- hwif->reset_poll = &siimage_reset_poll;
- hwif->pre_reset = &siimage_pre_reset;
- hwif->udma_filter = &sil_udma_filter;
- if(is_sata(hwif)) {
+ if (sata) {
static int first = 1;
- hwif->busproc = &siimage_busproc;
+ hwif->busproc = &sil_sata_busproc;
+ hwif->reset_poll = &sil_sata_reset_poll;
+ hwif->pre_reset = &sil_sata_pre_reset;
+ hwif->udma_filter = &sil_sata_udma_filter;
if (first) {
printk(KERN_INFO "siimage: For full SATA support you should use the libata sata_sil module.\n");
first = 0;
}
- }
-
- hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
+ } else
+ hwif->udma_filter = &sil_pata_udma_filter;
if (hwif->dma_base == 0)
return;
- hwif->ultra_mask = 0x7f;
- hwif->mwdma_mask = 0x07;
-
- if (!is_sata(hwif))
- hwif->atapi_dma = 1;
-
- hwif->ide_dma_check = &siimage_config_drive_for_dma;
+ if (sata)
+ hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
if (hwif->cbl != ATA_CBL_PATA40_SHORT)
hwif->cbl = ata66_siimage(hwif);
@@ -935,15 +890,6 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif)
} else {
hwif->ide_dma_test_irq = & siimage_io_ide_dma_test_irq;
}
-
- /*
- * The BIOS often doesn't set up DMA on this controller
- * so we always do it.
- */
-
- hwif->autodma = 1;
- hwif->drives[0].autodma = hwif->autodma;
- hwif->drives[1].autodma = hwif->autodma;
}
#define DECLARE_SII_DEV(name_str) \
@@ -953,12 +899,13 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif)
.init_iops = init_iops_siimage, \
.init_hwif = init_hwif_siimage, \
.fixup = siimage_fixup, \
- .autodma = AUTODMA, \
- .bootable = ON_BOARD, \
+ .host_flags = IDE_HFLAG_BOOTABLE, \
.pio_mask = ATA_PIO4, \
+ .mwdma_mask = ATA_MWDMA2, \
+ .udma_mask = ATA_UDMA6, \
}
-static ide_pci_device_t siimage_chipsets[] __devinitdata = {
+static const struct ide_port_info siimage_chipsets[] __devinitdata = {
/* 0 */ DECLARE_SII_DEV("SiI680"),
/* 1 */ DECLARE_SII_DEV("SiI3112 Serial ATA"),
/* 2 */ DECLARE_SII_DEV("Adaptec AAR-1210SA")
@@ -978,11 +925,11 @@ static int __devinit siimage_init_one(struct pci_dev *dev, const struct pci_devi
return ide_setup_pci_device(dev, &siimage_chipsets[id->driver_data]);
}
-static struct pci_device_id siimage_pci_tbl[] = {
- { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+static const struct pci_device_id siimage_pci_tbl[] = {
+ { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_680), 0 },
#ifdef CONFIG_BLK_DEV_IDE_SATA
- { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
- { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_1210SA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
+ { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_3112), 1 },
+ { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_1210SA), 2 },
#endif
{ 0, },
};
diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
index b375ee53d66d..f6e2ab3dd166 100644
--- a/drivers/ide/pci/sis5513.c
+++ b/drivers/ide/pci/sis5513.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/sis5513.c Version 0.27 Jul 14, 2007
+ * linux/drivers/ide/pci/sis5513.c Version 0.31 Aug 9, 2007
*
* Copyright (C) 1999-2000 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2002 Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer
@@ -65,8 +65,6 @@
#include "ide-timing.h"
-#define DISPLAY_SIS_TIMINGS
-
/* registers layout and init values are chipset family dependant */
#define ATA_16 0x01
@@ -193,362 +191,124 @@ static char* chipset_capability[] = {
"ATA 133 (1st gen)", "ATA 133 (2nd gen)"
};
-#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_IDE_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 sis_proc = 0;
-
-static struct pci_dev *bmide_dev;
-
-static char* cable_type[] = {
- "80 pins",
- "40 pins"
-};
+/*
+ * Configuration functions
+ */
-static char* recovery_time[] ={
- "12 PCICLK", "1 PCICLK",
- "2 PCICLK", "3 PCICLK",
- "4 PCICLK", "5 PCICLCK",
- "6 PCICLK", "7 PCICLCK",
- "8 PCICLK", "9 PCICLCK",
- "10 PCICLK", "11 PCICLK",
- "13 PCICLK", "14 PCICLK",
- "15 PCICLK", "15 PCICLK"
-};
+static u8 sis_ata133_get_base(ide_drive_t *drive)
+{
+ struct pci_dev *dev = drive->hwif->pci_dev;
+ u32 reg54 = 0;
-static char* active_time[] = {
- "8 PCICLK", "1 PCICLCK",
- "2 PCICLK", "3 PCICLK",
- "4 PCICLK", "5 PCICLK",
- "6 PCICLK", "12 PCICLK"
-};
+ pci_read_config_dword(dev, 0x54, &reg54);
-static char* cycle_time[] = {
- "Reserved", "2 CLK",
- "3 CLK", "4 CLK",
- "5 CLK", "6 CLK",
- "7 CLK", "8 CLK",
- "9 CLK", "10 CLK",
- "11 CLK", "12 CLK",
- "13 CLK", "14 CLK",
- "15 CLK", "16 CLK"
-};
+ return ((reg54 & 0x40000000) ? 0x70 : 0x40) + drive->dn * 4;
+}
-/* Generic add master or slave info function */
-static char* get_drives_info (char *buffer, u8 pos)
+static void sis_ata16_program_timings(ide_drive_t *drive, const u8 mode)
{
- u8 reg00, reg01, reg10, reg11; /* timing registers */
- u32 regdw0, regdw1;
- char* p = buffer;
-
-/* Postwrite/Prefetch */
- if (chipset_family < ATA_133) {
- pci_read_config_byte(bmide_dev, 0x4b, &reg00);
- p += sprintf(p, "Drive %d: Postwrite %s \t \t Postwrite %s\n",
- pos, (reg00 & (0x10 << pos)) ? "Enabled" : "Disabled",
- (reg00 & (0x40 << pos)) ? "Enabled" : "Disabled");
- p += sprintf(p, " Prefetch %s \t \t Prefetch %s\n",
- (reg00 & (0x01 << pos)) ? "Enabled" : "Disabled",
- (reg00 & (0x04 << pos)) ? "Enabled" : "Disabled");
- pci_read_config_byte(bmide_dev, 0x40+2*pos, &reg00);
- pci_read_config_byte(bmide_dev, 0x41+2*pos, &reg01);
- pci_read_config_byte(bmide_dev, 0x44+2*pos, &reg10);
- pci_read_config_byte(bmide_dev, 0x45+2*pos, &reg11);
- } else {
- u32 reg54h;
- u8 drive_pci = 0x40;
- pci_read_config_dword(bmide_dev, 0x54, &reg54h);
- if (reg54h & 0x40000000) {
- // Configuration space remapped to 0x70
- drive_pci = 0x70;
- }
- pci_read_config_dword(bmide_dev, (unsigned long)drive_pci+4*pos, &regdw0);
- pci_read_config_dword(bmide_dev, (unsigned long)drive_pci+4*pos+8, &regdw1);
+ struct pci_dev *dev = drive->hwif->pci_dev;
+ u16 t1 = 0;
+ u8 drive_pci = 0x40 + drive->dn * 2;
- p += sprintf(p, "Drive %d:\n", pos);
- }
+ const u16 pio_timings[] = { 0x000, 0x607, 0x404, 0x303, 0x301 };
+ const u16 mwdma_timings[] = { 0x008, 0x302, 0x301 };
+ pci_read_config_word(dev, drive_pci, &t1);
-/* UDMA */
- if (chipset_family >= ATA_133) {
- p += sprintf(p, " UDMA %s \t \t \t UDMA %s\n",
- (regdw0 & 0x04) ? "Enabled" : "Disabled",
- (regdw1 & 0x04) ? "Enabled" : "Disabled");
- p += sprintf(p, " UDMA Cycle Time %s \t UDMA Cycle Time %s\n",
- cycle_time[(regdw0 & 0xF0) >> 4],
- cycle_time[(regdw1 & 0xF0) >> 4]);
- } else if (chipset_family >= ATA_33) {
- p += sprintf(p, " UDMA %s \t \t \t UDMA %s\n",
- (reg01 & 0x80) ? "Enabled" : "Disabled",
- (reg11 & 0x80) ? "Enabled" : "Disabled");
-
- p += sprintf(p, " UDMA Cycle Time ");
- switch(chipset_family) {
- case ATA_33: p += sprintf(p, cycle_time[(reg01 & 0x60) >> 5]); break;
- case ATA_66:
- case ATA_100a: p += sprintf(p, cycle_time[(reg01 & 0x70) >> 4]); break;
- case ATA_100:
- case ATA_133a: p += sprintf(p, cycle_time[reg01 & 0x0F]); break;
- default: p += sprintf(p, "?"); break;
- }
- p += sprintf(p, " \t UDMA Cycle Time ");
- switch(chipset_family) {
- case ATA_33: p += sprintf(p, cycle_time[(reg11 & 0x60) >> 5]); break;
- case ATA_66:
- case ATA_100a: p += sprintf(p, cycle_time[(reg11 & 0x70) >> 4]); break;
- case ATA_100:
- case ATA_133a: p += sprintf(p, cycle_time[reg11 & 0x0F]); break;
- default: p += sprintf(p, "?"); break;
- }
- p += sprintf(p, "\n");
- }
+ /* clear active/recovery timings */
+ t1 &= ~0x070f;
+ if (mode >= XFER_MW_DMA_0) {
+ if (chipset_family > ATA_16)
+ t1 &= ~0x8000; /* disable UDMA */
+ t1 |= mwdma_timings[mode - XFER_MW_DMA_0];
+ } else
+ t1 |= pio_timings[mode - XFER_PIO_0];
+ pci_write_config_word(dev, drive_pci, t1);
+}
- if (chipset_family < ATA_133) { /* else case TODO */
+static void sis_ata100_program_timings(ide_drive_t *drive, const u8 mode)
+{
+ struct pci_dev *dev = drive->hwif->pci_dev;
+ u8 t1, drive_pci = 0x40 + drive->dn * 2;
-/* Data Active */
- p += sprintf(p, " Data Active Time ");
- switch(chipset_family) {
- case ATA_16: /* confirmed */
- case ATA_33:
- case ATA_66:
- case ATA_100a: p += sprintf(p, active_time[reg01 & 0x07]); break;
- case ATA_100:
- case ATA_133a: p += sprintf(p, active_time[(reg00 & 0x70) >> 4]); break;
- default: p += sprintf(p, "?"); break;
- }
- p += sprintf(p, " \t Data Active Time ");
- switch(chipset_family) {
- case ATA_16:
- case ATA_33:
- case ATA_66:
- case ATA_100a: p += sprintf(p, active_time[reg11 & 0x07]); break;
- case ATA_100:
- case ATA_133a: p += sprintf(p, active_time[(reg10 & 0x70) >> 4]); break;
- default: p += sprintf(p, "?"); break;
- }
- p += sprintf(p, "\n");
+ /* timing bits: 7:4 active 3:0 recovery */
+ const u8 pio_timings[] = { 0x00, 0x67, 0x44, 0x33, 0x31 };
+ const u8 mwdma_timings[] = { 0x08, 0x32, 0x31 };
-/* Data Recovery */
- /* warning: may need (reg&0x07) for pre ATA66 chips */
- p += sprintf(p, " Data Recovery Time %s \t Data Recovery Time %s\n",
- recovery_time[reg00 & 0x0f], recovery_time[reg10 & 0x0f]);
- }
+ if (mode >= XFER_MW_DMA_0) {
+ u8 t2 = 0;
- return p;
-}
+ pci_read_config_byte(dev, drive_pci, &t2);
+ t2 &= ~0x80; /* disable UDMA */
+ pci_write_config_byte(dev, drive_pci, t2);
-static char* get_masters_info(char* buffer)
-{
- return get_drives_info(buffer, 0);
+ t1 = mwdma_timings[mode - XFER_MW_DMA_0];
+ } else
+ t1 = pio_timings[mode - XFER_PIO_0];
+
+ pci_write_config_byte(dev, drive_pci + 1, t1);
}
-static char* get_slaves_info(char* buffer)
+static void sis_ata133_program_timings(ide_drive_t *drive, const u8 mode)
{
- return get_drives_info(buffer, 1);
+ struct pci_dev *dev = drive->hwif->pci_dev;
+ u32 t1 = 0;
+ u8 drive_pci = sis_ata133_get_base(drive), clk, idx;
+
+ pci_read_config_dword(dev, drive_pci, &t1);
+
+ t1 &= 0xc0c00fff;
+ clk = (t1 & 0x08) ? ATA_133 : ATA_100;
+ if (mode >= XFER_MW_DMA_0) {
+ t1 &= ~0x04; /* disable UDMA */
+ idx = mode - XFER_MW_DMA_0 + 5;
+ } else
+ idx = mode - XFER_PIO_0;
+ t1 |= ini_time_value[clk][idx] << 12;
+ t1 |= act_time_value[clk][idx] << 16;
+ t1 |= rco_time_value[clk][idx] << 24;
+
+ pci_write_config_dword(dev, drive_pci, t1);
}
-/* Main get_info, called on /proc/ide/sis reads */
-static int sis_get_info (char *buffer, char **addr, off_t offset, int count)
+static void sis_program_timings(ide_drive_t *drive, const u8 mode)
{
- char *p = buffer;
- int len;
- u8 reg;
- u16 reg2, reg3;
-
- p += sprintf(p, "\nSiS 5513 ");
- switch(chipset_family) {
- case ATA_16: p += sprintf(p, "DMA 16"); break;
- case ATA_33: p += sprintf(p, "Ultra 33"); break;
- case ATA_66: p += sprintf(p, "Ultra 66"); break;
- case ATA_100a:
- case ATA_100: p += sprintf(p, "Ultra 100"); break;
- case ATA_133a:
- case ATA_133: p += sprintf(p, "Ultra 133"); break;
- default: p+= sprintf(p, "Unknown???"); break;
- }
- p += sprintf(p, " chipset\n");
- p += sprintf(p, "--------------- Primary Channel "
- "---------------- Secondary Channel "
- "-------------\n");
-
-/* Status */
- pci_read_config_byte(bmide_dev, 0x4a, &reg);
- if (chipset_family == ATA_133) {
- pci_read_config_word(bmide_dev, 0x50, &reg2);
- pci_read_config_word(bmide_dev, 0x52, &reg3);
- }
- p += sprintf(p, "Channel Status: ");
- if (chipset_family < ATA_66) {
- p += sprintf(p, "%s \t \t \t \t %s\n",
- (reg & 0x04) ? "On" : "Off",
- (reg & 0x02) ? "On" : "Off");
- } else if (chipset_family < ATA_133) {
- p += sprintf(p, "%s \t \t \t \t %s \n",
- (reg & 0x02) ? "On" : "Off",
- (reg & 0x04) ? "On" : "Off");
- } else { /* ATA_133 */
- p += sprintf(p, "%s \t \t \t \t %s \n",
- (reg2 & 0x02) ? "On" : "Off",
- (reg3 & 0x02) ? "On" : "Off");
- }
-
-/* Operation Mode */
- pci_read_config_byte(bmide_dev, 0x09, &reg);
- p += sprintf(p, "Operation Mode: %s \t \t \t %s \n",
- (reg & 0x01) ? "Native" : "Compatible",
- (reg & 0x04) ? "Native" : "Compatible");
-
-/* 80-pin cable ? */
- if (chipset_family >= ATA_133) {
- p += sprintf(p, "Cable Type: %s \t \t \t %s\n",
- (reg2 & 0x01) ? cable_type[1] : cable_type[0],
- (reg3 & 0x01) ? cable_type[1] : cable_type[0]);
- } else if (chipset_family > ATA_33) {
- pci_read_config_byte(bmide_dev, 0x48, &reg);
- p += sprintf(p, "Cable Type: %s \t \t \t %s\n",
- (reg & 0x10) ? cable_type[1] : cable_type[0],
- (reg & 0x20) ? cable_type[1] : cable_type[0]);
- }
-
-/* Prefetch Count */
- if (chipset_family < ATA_133) {
- pci_read_config_word(bmide_dev, 0x4c, &reg2);
- pci_read_config_word(bmide_dev, 0x4e, &reg3);
- p += sprintf(p, "Prefetch Count: %d \t \t \t \t %d\n",
- reg2, reg3);
- }
-
- p = get_masters_info(p);
- p = get_slaves_info(p);
-
- len = (p - buffer) - offset;
- *addr = buffer + offset;
-
- return len > count ? count : len;
+ if (chipset_family < ATA_100) /* ATA_16/33/66/100a */
+ sis_ata16_program_timings(drive, mode);
+ else if (chipset_family < ATA_133) /* ATA_100/133a */
+ sis_ata100_program_timings(drive, mode);
+ else /* ATA_133 */
+ sis_ata133_program_timings(drive, mode);
}
-#endif /* defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_IDE_PROC_FS) */
-/*
- * Configuration functions
- */
-/* Enables per-drive prefetch and postwrite */
static void config_drive_art_rwp (ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev;
-
u8 reg4bh = 0;
- u8 rw_prefetch = (0x11 << drive->dn);
+ u8 rw_prefetch = 0;
- if (drive->media != ide_disk)
- return;
pci_read_config_byte(dev, 0x4b, &reg4bh);
- if ((reg4bh & rw_prefetch) != rw_prefetch)
+ if (drive->media == ide_disk)
+ rw_prefetch = 0x11 << drive->dn;
+
+ if ((reg4bh & (0x11 << drive->dn)) != rw_prefetch)
pci_write_config_byte(dev, 0x4b, reg4bh|rw_prefetch);
}
-/* Set per-drive active and recovery time */
static void sis_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
- ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
-
- u8 drive_pci, test1, test2;
-
config_drive_art_rwp(drive);
-
- /* In pre ATA_133 case, drives sit at 0x40 + 4*drive->dn */
- drive_pci = 0x40;
- /* In SiS962 case drives sit at (0x40 or 0x70) + 8*drive->dn) */
- if (chipset_family >= ATA_133) {
- u32 reg54h;
- pci_read_config_dword(dev, 0x54, &reg54h);
- if (reg54h & 0x40000000) drive_pci = 0x70;
- drive_pci += ((drive->dn)*0x4);
- } else {
- drive_pci += ((drive->dn)*0x2);
- }
-
- /* register layout changed with newer ATA100 chips */
- if (chipset_family < ATA_100) {
- pci_read_config_byte(dev, drive_pci, &test1);
- pci_read_config_byte(dev, drive_pci+1, &test2);
-
- /* Clear active and recovery timings */
- test1 &= ~0x0F;
- test2 &= ~0x07;
-
- switch(pio) {
- case 4: test1 |= 0x01; test2 |= 0x03; break;
- case 3: test1 |= 0x03; test2 |= 0x03; break;
- case 2: test1 |= 0x04; test2 |= 0x04; break;
- case 1: test1 |= 0x07; test2 |= 0x06; break;
- case 0: /* PIO0: register setting == X000 */
- default: break;
- }
- pci_write_config_byte(dev, drive_pci, test1);
- pci_write_config_byte(dev, drive_pci+1, test2);
- } else if (chipset_family < ATA_133) {
- switch(pio) { /* active recovery
- v v */
- case 4: test1 = 0x30|0x01; break;
- case 3: test1 = 0x30|0x03; break;
- case 2: test1 = 0x40|0x04; break;
- case 1: test1 = 0x60|0x07; break;
- case 0: test1 = 0x00; break;
- default: break;
- }
- pci_write_config_byte(dev, drive_pci, test1);
- } else { /* ATA_133 */
- u32 test3;
- pci_read_config_dword(dev, drive_pci, &test3);
- test3 &= 0xc0c00fff;
- if (test3 & 0x08) {
- test3 |= ini_time_value[ATA_133][pio] << 12;
- test3 |= act_time_value[ATA_133][pio] << 16;
- test3 |= rco_time_value[ATA_133][pio] << 24;
- } else {
- test3 |= ini_time_value[ATA_100][pio] << 12;
- test3 |= act_time_value[ATA_100][pio] << 16;
- test3 |= rco_time_value[ATA_100][pio] << 24;
- }
- pci_write_config_dword(dev, drive_pci, test3);
- }
+ sis_program_timings(drive, XFER_PIO_0 + pio);
}
static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed)
{
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev;
- u32 regdw;
- u8 drive_pci, reg;
-
- /* See sis_set_pio_mode() for drive PCI config registers */
- drive_pci = 0x40;
- if (chipset_family >= ATA_133) {
- u32 reg54h;
- pci_read_config_dword(dev, 0x54, &reg54h);
- if (reg54h & 0x40000000) drive_pci = 0x70;
- drive_pci += ((drive->dn)*0x4);
- pci_read_config_dword(dev, (unsigned long)drive_pci, &regdw);
- /* Disable UDMA bit for non UDMA modes on UDMA chips */
- if (speed < XFER_UDMA_0) {
- regdw &= 0xfffffffb;
- pci_write_config_dword(dev, (unsigned long)drive_pci, regdw);
- }
-
- } else {
- drive_pci += ((drive->dn)*0x2);
- pci_read_config_byte(dev, drive_pci+1, &reg);
- /* Disable UDMA bit for non UDMA modes on UDMA chips */
- if ((speed < XFER_UDMA_0) && (chipset_family > ATA_16)) {
- reg &= 0x7F;
- pci_write_config_byte(dev, drive_pci+1, reg);
- }
- }
/* Config chip for mode */
switch(speed) {
@@ -560,6 +320,10 @@ static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed)
case XFER_UDMA_1:
case XFER_UDMA_0:
if (chipset_family >= ATA_133) {
+ u32 regdw = 0;
+ u8 drive_pci = sis_ata133_get_base(drive);
+
+ pci_read_config_dword(dev, drive_pci, &regdw);
regdw |= 0x04;
regdw &= 0xfffff00f;
/* check if ATA133 enable */
@@ -572,6 +336,9 @@ static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed)
}
pci_write_config_dword(dev, (unsigned long)drive_pci, regdw);
} else {
+ u8 drive_pci = 0x40 + drive->dn * 2, reg = 0;
+
+ pci_read_config_byte(dev, drive_pci+1, &reg);
/* Force the UDMA bit on if we want to use UDMA */
reg |= 0x80;
/* clean reg cycle time bits */
@@ -586,42 +353,19 @@ static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed)
case XFER_MW_DMA_2:
case XFER_MW_DMA_1:
case XFER_MW_DMA_0:
- case XFER_SW_DMA_2:
- case XFER_SW_DMA_1:
- case XFER_SW_DMA_0:
+ sis_program_timings(drive, speed);
break;
default:
- BUG();
break;
}
}
-static int sis5513_config_xfer_rate(ide_drive_t *drive)
-{
- /*
- * TODO: always set PIO mode and remove this
- */
- ide_set_max_pio(drive);
-
- drive->init_speed = 0;
-
- if (ide_tune_dma(drive))
- return 0;
-
- if (ide_use_fast_pio(drive))
- ide_set_max_pio(drive);
-
- return -1;
-}
-
static u8 sis5513_ata133_udma_filter(ide_drive_t *drive)
{
struct pci_dev *dev = drive->hwif->pci_dev;
- int drive_pci;
- u32 reg54 = 0, regdw = 0;
+ u32 regdw = 0;
+ u8 drive_pci = sis_ata133_get_base(drive);
- pci_read_config_dword(dev, 0x54, &reg54);
- drive_pci = ((reg54 & 0x40000000) ? 0x70 : 0x40) + drive->dn * 4;
pci_read_config_dword(dev, drive_pci, &regdw);
/* if ATA133 disable, we should not set speed above UDMA5 */
@@ -767,14 +511,6 @@ static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const c
}
break;
}
-
-#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_IDE_PROC_FS)
- if (!sis_proc) {
- sis_proc = 1;
- bmide_dev = dev;
- ide_pci_create_host_proc("sis", sis_get_info);
- }
-#endif
}
return 0;
@@ -827,53 +563,30 @@ static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif)
{
u8 udma_rates[] = { 0x00, 0x00, 0x07, 0x1f, 0x3f, 0x3f, 0x7f, 0x7f };
- hwif->autodma = 0;
-
- if (!hwif->irq)
- hwif->irq = hwif->channel ? 15 : 14;
-
hwif->set_pio_mode = &sis_set_pio_mode;
hwif->set_dma_mode = &sis_set_dma_mode;
if (chipset_family >= ATA_133)
hwif->udma_filter = sis5513_ata133_udma_filter;
- if (!(hwif->dma_base)) {
- hwif->drives[0].autotune = 1;
- hwif->drives[1].autotune = 1;
+ if (hwif->dma_base == 0)
return;
- }
-
- hwif->atapi_dma = 1;
hwif->ultra_mask = udma_rates[chipset_family];
- hwif->mwdma_mask = 0x07;
- hwif->swdma_mask = 0x07;
-
- if (!chipset_family)
- return;
if (hwif->cbl != ATA_CBL_PATA40_SHORT)
hwif->cbl = ata66_sis5513(hwif);
-
- if (chipset_family > ATA_16) {
- hwif->ide_dma_check = &sis5513_config_xfer_rate;
- if (!noautodma)
- hwif->autodma = 1;
- }
- hwif->drives[0].autodma = hwif->autodma;
- hwif->drives[1].autodma = hwif->autodma;
- return;
}
-static ide_pci_device_t sis5513_chipset __devinitdata = {
+static const struct ide_port_info sis5513_chipset __devinitdata = {
.name = "SIS5513",
.init_chipset = init_chipset_sis5513,
.init_hwif = init_hwif_sis5513,
- .autodma = NOAUTODMA,
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
- .bootable = ON_BOARD,
+ .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_NO_AUTODMA |
+ IDE_HFLAG_BOOTABLE,
.pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
};
static int __devinit sis5513_init_one(struct pci_dev *dev, const struct pci_device_id *id)
@@ -881,10 +594,10 @@ static int __devinit sis5513_init_one(struct pci_dev *dev, const struct pci_devi
return ide_setup_pci_device(dev, &sis5513_chipset);
}
-static struct pci_device_id sis5513_pci_tbl[] = {
- { PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- { PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5518, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- { PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_1180, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+static const struct pci_device_id sis5513_pci_tbl[] = {
+ { PCI_VDEVICE(SI, PCI_DEVICE_ID_SI_5513), 0 },
+ { PCI_VDEVICE(SI, PCI_DEVICE_ID_SI_5518), 0 },
+ { PCI_VDEVICE(SI, PCI_DEVICE_ID_SI_1180), 0 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, sis5513_pci_tbl);
diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c
index 2ef26e3f7be4..147d783f7529 100644
--- a/drivers/ide/pci/sl82c105.c
+++ b/drivers/ide/pci/sl82c105.c
@@ -145,19 +145,6 @@ static void sl82c105_set_dma_mode(ide_drive_t *drive, const u8 speed)
}
/*
- * Check to see if the drive and chipset are capable of DMA mode.
- */
-static int sl82c105_ide_dma_check(ide_drive_t *drive)
-{
- DBG(("sl82c105_ide_dma_check(drive:%s)\n", drive->name));
-
- if (ide_tune_dma(drive))
- return 0;
-
- return -1;
-}
-
-/*
* The SL82C105 holds off all IDE interrupts while in DMA mode until
* all DMA activity is completed. Sometimes this causes problems (eg,
* when the drive wants to report an error condition).
@@ -374,19 +361,6 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
hwif->selectproc = &sl82c105_selectproc;
hwif->resetproc = &sl82c105_resetproc;
- /*
- * We support 32-bit I/O on this interface, and
- * it doesn't have problems with interrupts.
- */
- hwif->drives[0].io_32bit = hwif->drives[1].io_32bit = 1;
- hwif->drives[0].unmask = hwif->drives[1].unmask = 1;
-
- /*
- * We always autotune PIO, this is done before DMA is checked,
- * so there's no risk of accidentally disabling DMA
- */
- hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
-
if (!hwif->dma_base)
return;
@@ -401,31 +375,27 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
return;
}
- hwif->atapi_dma = 1;
- hwif->mwdma_mask = 0x07;
+ hwif->mwdma_mask = ATA_MWDMA2;
- hwif->ide_dma_check = &sl82c105_ide_dma_check;
hwif->ide_dma_on = &sl82c105_ide_dma_on;
hwif->dma_off_quietly = &sl82c105_dma_off_quietly;
hwif->dma_lost_irq = &sl82c105_dma_lost_irq;
hwif->dma_start = &sl82c105_dma_start;
hwif->dma_timeout = &sl82c105_dma_timeout;
- if (!noautodma)
- hwif->autodma = 1;
- hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma;
-
if (hwif->mate)
hwif->serialized = hwif->mate->serialized = 1;
}
-static ide_pci_device_t sl82c105_chipset __devinitdata = {
+static const struct ide_port_info sl82c105_chipset __devinitdata = {
.name = "W82C105",
.init_chipset = init_chipset_sl82c105,
.init_hwif = init_hwif_sl82c105,
- .autodma = NOAUTODMA,
.enablebits = {{0x40,0x01,0x01}, {0x40,0x10,0x10}},
- .bootable = ON_BOARD,
+ .host_flags = IDE_HFLAG_IO_32BIT |
+ IDE_HFLAG_UNMASK_IRQS |
+ IDE_HFLAG_NO_AUTODMA |
+ IDE_HFLAG_BOOTABLE,
.pio_mask = ATA_PIO5,
};
@@ -434,8 +404,8 @@ static int __devinit sl82c105_init_one(struct pci_dev *dev, const struct pci_dev
return ide_setup_pci_device(dev, &sl82c105_chipset);
}
-static struct pci_device_id sl82c105_pci_tbl[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105), 0},
+static const struct pci_device_id sl82c105_pci_tbl[] = {
+ { PCI_VDEVICE(WINBOND, PCI_DEVICE_ID_WINBOND_82C105), 0 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, sl82c105_pci_tbl);
diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c
index ebac87f7200a..eb4445b229ed 100644
--- a/drivers/ide/pci/slc90e66.c
+++ b/drivers/ide/pci/slc90e66.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/slc90e66.c Version 0.16 Jul 14, 2007
+ * linux/drivers/ide/pci/slc90e66.c Version 0.19 Sep 24, 2007
*
* Copyright (C) 2000-2002 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2006-2007 MontaVista Software, Inc. <source@mvista.com>
@@ -21,26 +21,7 @@
#include <asm/io.h>
-static u8 slc90e66_dma_2_pio (u8 xfer_rate) {
- switch(xfer_rate) {
- case XFER_UDMA_4:
- case XFER_UDMA_3:
- case XFER_UDMA_2:
- case XFER_UDMA_1:
- case XFER_UDMA_0:
- case XFER_MW_DMA_2:
- return 4;
- case XFER_MW_DMA_1:
- return 3;
- case XFER_SW_DMA_2:
- return 2;
- case XFER_MW_DMA_0:
- case XFER_SW_DMA_1:
- case XFER_SW_DMA_0:
- default:
- return 0;
- }
-}
+static DEFINE_SPINLOCK(slc90e66_lock);
static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
@@ -61,7 +42,7 @@ static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio)
{ 2, 1 },
{ 2, 3 }, };
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&slc90e66_lock, flags);
pci_read_config_word(dev, master_port, &master_data);
if (pio > 1)
@@ -92,7 +73,7 @@ static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio)
pci_write_config_word(dev, master_port, master_data);
if (is_slave)
pci_write_config_byte(dev, slave_port, slave_data);
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&slc90e66_lock, flags);
}
static void slc90e66_set_dma_mode(ide_drive_t *drive, const u8 speed)
@@ -132,26 +113,21 @@ static void slc90e66_set_dma_mode(ide_drive_t *drive, const u8 speed)
pci_write_config_word(dev, 0x4a, reg4a|u_speed);
}
} else {
+ const u8 mwdma_to_pio[] = { 0, 3, 4 };
+ u8 pio;
+
if (reg48 & u_flag)
pci_write_config_word(dev, 0x48, reg48 & ~u_flag);
if (reg4a & a_speed)
pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
- }
-
- slc90e66_set_pio_mode(drive, slc90e66_dma_2_pio(speed));
-}
-
-static int slc90e66_config_drive_xfer_rate (ide_drive_t *drive)
-{
- drive->init_speed = 0;
-
- if (ide_tune_dma(drive))
- return 0;
- if (ide_use_fast_pio(drive))
- ide_set_max_pio(drive);
+ if (speed >= XFER_MW_DMA_0)
+ pio = mwdma_to_pio[speed - XFER_MW_DMA_0];
+ else
+ pio = 2; /* only SWDMA2 is allowed */
- return -1;
+ slc90e66_set_pio_mode(drive, pio);
+ }
}
static void __devinit init_hwif_slc90e66 (ide_hwif_t *hwif)
@@ -159,46 +135,28 @@ static void __devinit init_hwif_slc90e66 (ide_hwif_t *hwif)
u8 reg47 = 0;
u8 mask = hwif->channel ? 0x01 : 0x02; /* bit0:Primary */
- hwif->autodma = 0;
-
- if (!hwif->irq)
- hwif->irq = hwif->channel ? 15 : 14;
-
hwif->set_pio_mode = &slc90e66_set_pio_mode;
hwif->set_dma_mode = &slc90e66_set_dma_mode;
pci_read_config_byte(hwif->pci_dev, 0x47, &reg47);
- if (!hwif->dma_base) {
- hwif->drives[0].autotune = 1;
- hwif->drives[1].autotune = 1;
+ if (hwif->dma_base == 0)
return;
- }
-
- hwif->atapi_dma = 1;
- hwif->ultra_mask = 0x1f;
- hwif->mwdma_mask = 0x06;
- hwif->swdma_mask = 0x04;
if (hwif->cbl != ATA_CBL_PATA40_SHORT)
/* bit[0(1)]: 0:80, 1:40 */
hwif->cbl = (reg47 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
-
- hwif->ide_dma_check = &slc90e66_config_drive_xfer_rate;
-
- if (!noautodma)
- hwif->autodma = 1;
- hwif->drives[0].autodma = hwif->autodma;
- hwif->drives[1].autodma = hwif->autodma;
}
-static ide_pci_device_t slc90e66_chipset __devinitdata = {
+static const struct ide_port_info slc90e66_chipset __devinitdata = {
.name = "SLC90E66",
.init_hwif = init_hwif_slc90e66,
- .autodma = AUTODMA,
.enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
- .bootable = ON_BOARD,
+ .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE,
.pio_mask = ATA_PIO4,
+ .swdma_mask = ATA_SWDMA2_ONLY,
+ .mwdma_mask = ATA_MWDMA12_ONLY,
+ .udma_mask = ATA_UDMA4,
};
static int __devinit slc90e66_init_one(struct pci_dev *dev, const struct pci_device_id *id)
@@ -206,8 +164,8 @@ static int __devinit slc90e66_init_one(struct pci_dev *dev, const struct pci_dev
return ide_setup_pci_device(dev, &slc90e66_chipset);
}
-static struct pci_device_id slc90e66_pci_tbl[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1), 0},
+static const struct pci_device_id slc90e66_pci_tbl[] = {
+ { PCI_VDEVICE(EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1), 0 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, slc90e66_pci_tbl);
diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c
index 840415d68d38..a66ebd14664e 100644
--- a/drivers/ide/pci/tc86c001.c
+++ b/drivers/ide/pci/tc86c001.c
@@ -1,5 +1,5 @@
/*
- * drivers/ide/pci/tc86c001.c Version 1.00 Dec 12, 2006
+ * drivers/ide/pci/tc86c001.c Version 1.01 Sep 5, 2007
*
* Copyright (C) 2002 Toshiba Corporation
* Copyright (C) 2005-2006 MontaVista Software, Inc. <source@mvista.com>
@@ -17,7 +17,7 @@ static void tc86c001_set_mode(ide_drive_t *drive, const u8 speed)
{
ide_hwif_t *hwif = HWIF(drive);
unsigned long scr_port = hwif->config_data + (drive->dn ? 0x02 : 0x00);
- u16 mode, scr = hwif->INW(scr_port);
+ u16 mode, scr = inw(scr_port);
switch (speed) {
case XFER_UDMA_4: mode = 0x00c0; break;
@@ -65,7 +65,7 @@ static int tc86c001_timer_expiry(ide_drive_t *drive)
ide_hwif_t *hwif = HWIF(drive);
ide_expiry_t *expiry = ide_get_hwifdata(hwif);
ide_hwgroup_t *hwgroup = HWGROUP(drive);
- u8 dma_stat = hwif->INB(hwif->dma_status);
+ u8 dma_stat = inb(hwif->dma_status);
/* Restore a higher level driver's expiry handler first. */
hwgroup->expiry = expiry;
@@ -73,7 +73,7 @@ static int tc86c001_timer_expiry(ide_drive_t *drive)
if ((dma_stat & 5) == 1) { /* DMA active and no interrupt */
unsigned long sc_base = hwif->config_data;
unsigned long twcr_port = sc_base + (drive->dn ? 0x06 : 0x04);
- u8 dma_cmd = hwif->INB(hwif->dma_command);
+ u8 dma_cmd = inb(hwif->dma_command);
printk(KERN_WARNING "%s: DMA interrupt possibly stuck, "
"attempting recovery...\n", drive->name);
@@ -135,7 +135,7 @@ static int tc86c001_busproc(ide_drive_t *drive, int state)
u16 scr1;
/* System Control 1 Register bit 11 (ATA Hard Reset) read */
- scr1 = hwif->INW(sc_base + 0x00);
+ scr1 = inw(sc_base + 0x00);
switch (state) {
case BUSSTATE_ON:
@@ -162,21 +162,10 @@ static int tc86c001_busproc(ide_drive_t *drive, int state)
return 0;
}
-static int tc86c001_config_drive_xfer_rate(ide_drive_t *drive)
-{
- if (ide_tune_dma(drive))
- return 0;
-
- if (ide_use_fast_pio(drive))
- ide_set_max_pio(drive);
-
- return -1;
-}
-
static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
{
unsigned long sc_base = pci_resource_start(hwif->pci_dev, 5);
- u16 scr1 = hwif->INW(sc_base + 0x00);;
+ u16 scr1 = inw(sc_base + 0x00);
/* System Control 1 Register bit 15 (Soft Reset) set */
outw(scr1 | 0x8000, sc_base + 0x00);
@@ -195,8 +184,6 @@ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
hwif->busproc = &tc86c001_busproc;
- hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
-
if (!hwif->dma_base)
return;
@@ -209,11 +196,6 @@ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
/* Sector Count Register limit */
hwif->rqsize = 0xffff;
- hwif->atapi_dma = 1;
- hwif->ultra_mask = 0x1f;
- hwif->mwdma_mask = 0x07;
-
- hwif->ide_dma_check = &tc86c001_config_drive_xfer_rate;
hwif->dma_start = &tc86c001_dma_start;
if (hwif->cbl != ATA_CBL_PATA40_SHORT) {
@@ -221,13 +203,9 @@ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
* System Control 1 Register bit 13 (PDIAGN):
* 0=80-pin cable, 1=40-pin cable
*/
- scr1 = hwif->INW(sc_base + 0x00);
+ scr1 = inw(sc_base + 0x00);
hwif->cbl = (scr1 & 0x2000) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
}
-
- if (!noautodma)
- hwif->autodma = 1;
- hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma;
}
static unsigned int __devinit init_chipset_tc86c001(struct pci_dev *dev,
@@ -240,14 +218,14 @@ static unsigned int __devinit init_chipset_tc86c001(struct pci_dev *dev,
return err;
}
-static ide_pci_device_t tc86c001_chipset __devinitdata = {
+static const struct ide_port_info tc86c001_chipset __devinitdata = {
.name = "TC86C001",
.init_chipset = init_chipset_tc86c001,
.init_hwif = init_hwif_tc86c001,
- .autodma = AUTODMA,
- .bootable = OFF_BOARD,
- .host_flags = IDE_HFLAG_SINGLE,
+ .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA4,
};
static int __devinit tc86c001_init_one(struct pci_dev *dev,
@@ -256,9 +234,8 @@ static int __devinit tc86c001_init_one(struct pci_dev *dev,
return ide_setup_pci_device(dev, &tc86c001_chipset);
}
-static struct pci_device_id tc86c001_pci_tbl[] = {
- { PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+static const struct pci_device_id tc86c001_pci_tbl[] = {
+ { PCI_VDEVICE(TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE), 0 },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, tc86c001_pci_tbl);
diff --git a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c
index 54e411d4e56c..a227c41d23a3 100644
--- a/drivers/ide/pci/triflex.c
+++ b/drivers/ide/pci/triflex.c
@@ -96,42 +96,20 @@ static void triflex_set_pio_mode(ide_drive_t *drive, const u8 pio)
triflex_set_mode(drive, XFER_PIO_0 + pio);
}
-static int triflex_config_drive_xfer_rate(ide_drive_t *drive)
-{
- if (ide_tune_dma(drive))
- return 0;
-
- ide_set_max_pio(drive);
-
- return -1;
-}
-
static void __devinit init_hwif_triflex(ide_hwif_t *hwif)
{
hwif->set_pio_mode = &triflex_set_pio_mode;
hwif->set_dma_mode = &triflex_set_mode;
-
- if (hwif->dma_base == 0)
- return;
-
- hwif->atapi_dma = 1;
- hwif->mwdma_mask = 0x07;
- hwif->swdma_mask = 0x07;
- hwif->ide_dma_check = &triflex_config_drive_xfer_rate;
-
- if (!noautodma)
- hwif->autodma = 1;
- hwif->drives[0].autodma = hwif->autodma;
- hwif->drives[1].autodma = hwif->autodma;
}
-static ide_pci_device_t triflex_device __devinitdata = {
+static const struct ide_port_info triflex_device __devinitdata = {
.name = "TRIFLEX",
.init_hwif = init_hwif_triflex,
- .autodma = AUTODMA,
.enablebits = {{0x80, 0x01, 0x01}, {0x80, 0x02, 0x02}},
- .bootable = ON_BOARD,
+ .host_flags = IDE_HFLAG_BOOTABLE,
.pio_mask = ATA_PIO4,
+ .swdma_mask = ATA_SWDMA2,
+ .mwdma_mask = ATA_MWDMA2,
};
static int __devinit triflex_init_one(struct pci_dev *dev,
@@ -140,9 +118,8 @@ static int __devinit triflex_init_one(struct pci_dev *dev,
return ide_setup_pci_device(dev, &triflex_device);
}
-static struct pci_device_id triflex_pci_tbl[] = {
- { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_TRIFLEX_IDE,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+static const struct pci_device_id triflex_pci_tbl[] = {
+ { PCI_VDEVICE(COMPAQ, PCI_DEVICE_ID_COMPAQ_TRIFLEX_IDE), 0 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, triflex_pci_tbl);
diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c
index dc4f4e298e00..5011ba22e36c 100644
--- a/drivers/ide/pci/trm290.c
+++ b/drivers/ide/pci/trm290.c
@@ -250,8 +250,6 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif)
u8 reg = 0;
struct pci_dev *dev = hwif->pci_dev;
- hwif->no_lba48 = 1;
- hwif->chipset = ide_trm290;
cfgbase = pci_resource_start(dev, 4);
if ((dev->class & 5) && cfgbase) {
hwif->config_data = cfgbase;
@@ -292,9 +290,6 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif)
hwif->ide_dma_test_irq = &trm290_ide_dma_test_irq;
hwif->selectproc = &trm290_selectproc;
- hwif->autodma = 0; /* play it safe for now */
- hwif->drives[0].autodma = hwif->autodma;
- hwif->drives[1].autodma = hwif->autodma;
#if 1
{
/*
@@ -324,11 +319,17 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif)
#endif
}
-static ide_pci_device_t trm290_chipset __devinitdata = {
+static const struct ide_port_info trm290_chipset __devinitdata = {
.name = "TRM290",
.init_hwif = init_hwif_trm290,
- .autodma = NOAUTODMA,
- .bootable = ON_BOARD,
+ .chipset = ide_trm290,
+ .host_flags = IDE_HFLAG_NO_ATAPI_DMA |
+#if 0 /* play it safe for now */
+ IDE_HFLAG_TRUST_BIOS_FOR_DMA |
+#endif
+ IDE_HFLAG_NO_AUTODMA |
+ IDE_HFLAG_BOOTABLE |
+ IDE_HFLAG_NO_LBA48,
};
static int __devinit trm290_init_one(struct pci_dev *dev, const struct pci_device_id *id)
@@ -336,8 +337,8 @@ static int __devinit trm290_init_one(struct pci_dev *dev, const struct pci_devic
return ide_setup_pci_device(dev, &trm290_chipset);
}
-static struct pci_device_id trm290_pci_tbl[] = {
- { PCI_VENDOR_ID_TEKRAM, PCI_DEVICE_ID_TEKRAM_DC290, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+static const struct pci_device_id trm290_pci_tbl[] = {
+ { PCI_VDEVICE(TEKRAM, PCI_DEVICE_ID_TEKRAM_DC290), 0 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, trm290_pci_tbl);
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
index 479e49661032..a0d3c16b68ec 100644
--- a/drivers/ide/pci/via82cxxx.c
+++ b/drivers/ide/pci/via82cxxx.c
@@ -1,6 +1,6 @@
/*
*
- * Version 3.49
+ * Version 3.50
*
* VIA IDE driver for Linux. Supported southbridges:
*
@@ -197,24 +197,6 @@ static void via_set_pio_mode(ide_drive_t *drive, const u8 pio)
via_set_drive(drive, XFER_PIO_0 + pio);
}
-/**
- * via82cxxx_ide_dma_check - set up for DMA if possible
- * @drive: IDE drive to set up
- *
- * Set up the drive for the highest supported speed considering the
- * driver, controller and cable
- */
-
-static int via82cxxx_ide_dma_check (ide_drive_t *drive)
-{
- if (ide_tune_dma(drive))
- return 0;
-
- ide_set_max_pio(drive);
-
- return -1;
-}
-
static struct via_isa_bridge *via_config_find(struct pci_dev **isa)
{
struct via_isa_bridge *via_config;
@@ -440,76 +422,40 @@ static u8 __devinit via82cxxx_cable_detect(ide_hwif_t *hwif)
static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif)
{
- struct via82cxxx_dev *vdev = pci_get_drvdata(hwif->pci_dev);
- int i;
-
- hwif->autodma = 0;
-
hwif->set_pio_mode = &via_set_pio_mode;
hwif->set_dma_mode = &via_set_drive;
-#ifdef CONFIG_PPC_CHRP
- if(machine_is(chrp) && _chrp_type == _CHRP_Pegasos) {
- hwif->irq = hwif->channel ? 15 : 14;
- }
-#endif
-
- for (i = 0; i < 2; i++) {
- hwif->drives[i].io_32bit = 1;
- hwif->drives[i].unmask = (vdev->via_config->flags & VIA_NO_UNMASK) ? 0 : 1;
- hwif->drives[i].autotune = 1;
- hwif->drives[i].dn = hwif->channel * 2 + i;
- }
-
if (!hwif->dma_base)
return;
- hwif->atapi_dma = 1;
-
- hwif->ultra_mask = vdev->via_config->udma_mask;
- hwif->mwdma_mask = 0x07;
- hwif->swdma_mask = 0x07;
-
if (hwif->cbl != ATA_CBL_PATA40_SHORT)
hwif->cbl = via82cxxx_cable_detect(hwif);
-
- hwif->ide_dma_check = &via82cxxx_ide_dma_check;
- if (!noautodma)
- hwif->autodma = 1;
- hwif->drives[0].autodma = hwif->autodma;
- hwif->drives[1].autodma = hwif->autodma;
}
-static ide_pci_device_t via82cxxx_chipsets[] __devinitdata = {
- { /* 0 */
- .name = "VP_IDE",
- .init_chipset = init_chipset_via82cxxx,
- .init_hwif = init_hwif_via82cxxx,
- .autodma = NOAUTODMA,
- .enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}},
- .bootable = ON_BOARD,
- .host_flags = IDE_HFLAG_PIO_NO_BLACKLIST
- | IDE_HFLAG_PIO_NO_DOWNGRADE
- | IDE_HFLAG_POST_SET_MODE,
- .pio_mask = ATA_PIO5,
- },{ /* 1 */
- .name = "VP_IDE",
- .init_chipset = init_chipset_via82cxxx,
- .init_hwif = init_hwif_via82cxxx,
- .autodma = AUTODMA,
- .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
- .bootable = ON_BOARD,
- .host_flags = IDE_HFLAG_PIO_NO_BLACKLIST
- | IDE_HFLAG_PIO_NO_DOWNGRADE
- | IDE_HFLAG_POST_SET_MODE,
- .pio_mask = ATA_PIO5,
- }
+static const struct ide_port_info via82cxxx_chipset __devinitdata = {
+ .name = "VP_IDE",
+ .init_chipset = init_chipset_via82cxxx,
+ .init_hwif = init_hwif_via82cxxx,
+ .enablebits = { { 0x40, 0x02, 0x02 }, { 0x40, 0x01, 0x01 } },
+ .host_flags = IDE_HFLAG_PIO_NO_BLACKLIST |
+ IDE_HFLAG_PIO_NO_DOWNGRADE |
+ IDE_HFLAG_POST_SET_MODE |
+ IDE_HFLAG_IO_32BIT |
+ IDE_HFLAG_BOOTABLE,
+ .pio_mask = ATA_PIO5,
+ .swdma_mask = ATA_SWDMA2,
+ .mwdma_mask = ATA_MWDMA2,
};
static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
struct pci_dev *isa = NULL;
struct via_isa_bridge *via_config;
+ u8 idx = id->driver_data;
+ struct ide_port_info d;
+
+ d = via82cxxx_chipset;
+
/*
* Find the ISA bridge and check we know what it is.
*/
@@ -519,14 +465,30 @@ static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_i
printk(KERN_WARNING "VP_IDE: Unknown VIA SouthBridge, disabling DMA.\n");
return -ENODEV;
}
- return ide_setup_pci_device(dev, &via82cxxx_chipsets[id->driver_data]);
+
+ if (idx == 0)
+ d.host_flags |= IDE_HFLAG_NO_AUTODMA;
+ else
+ d.enablebits[1].reg = d.enablebits[0].reg = 0;
+
+ if ((via_config->flags & VIA_NO_UNMASK) == 0)
+ d.host_flags |= IDE_HFLAG_UNMASK_IRQS;
+
+#ifdef CONFIG_PPC_CHRP
+ if (machine_is(chrp) && _chrp_type == _CHRP_Pegasos)
+ d.host_flags |= IDE_HFLAG_FORCE_LEGACY_IRQS;
+#endif
+
+ d.udma_mask = via_config->udma_mask;
+
+ return ide_setup_pci_device(dev, &d);
}
-static struct pci_device_id via_pci_tbl[] = {
- { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_6410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
- { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_SATA_EIDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
+static const struct pci_device_id via_pci_tbl[] = {
+ { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C576_1), 0 },
+ { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C586_1), 0 },
+ { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_6410), 1 },
+ { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_SATA_EIDE), 1 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, via_pci_tbl);
diff --git a/drivers/ide/ppc/mpc8xx.c b/drivers/ide/ppc/mpc8xx.c
index df2e92034f5d..5f0da35ab5ad 100644
--- a/drivers/ide/ppc/mpc8xx.c
+++ b/drivers/ide/ppc/mpc8xx.c
@@ -316,8 +316,8 @@ m8xx_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port,
ide_hwifs[data_port].pio_mask = ATA_PIO4;
ide_hwifs[data_port].set_pio_mode = m8xx_ide_set_pio_mode;
+ ide_hwifs[data_port].ack_intr = (ide_ack_intr_t *)ide_interrupt_ack;
- hw->ack_intr = (ide_ack_intr_t *) ide_interrupt_ack;
/* Enable Harddisk Interrupt,
* and make it edge sensitive
*/
@@ -402,8 +402,8 @@ void m8xx_ide_init_hwif_ports (hw_regs_t *hw,
ide_hwifs[data_port].pio_mask = ATA_PIO4;
ide_hwifs[data_port].set_pio_mode = m8xx_ide_set_pio_mode;
+ ide_hwifs[data_port].ack_intr = (ide_ack_intr_t *)ide_interrupt_ack;
- hw->ack_intr = (ide_ack_intr_t *) ide_interrupt_ack;
/* Enable Harddisk Interrupt,
* and make it edge sensitive
*/
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
index 7d8873839e21..5afdfef7264c 100644
--- a/drivers/ide/ppc/pmac.c
+++ b/drivers/ide/ppc/pmac.c
@@ -1039,6 +1039,8 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
{
struct device_node *np = pmif->node;
const int *bidp;
+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ hw_regs_t hw;
pmif->cable_80 = 0;
pmif->broken_dma = pmif->broken_dma_warn = 0;
@@ -1124,8 +1126,9 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
/* Tell common code _not_ to mess with resources */
hwif->mmio = 1;
hwif->hwif_data = pmif;
- pmac_ide_init_hwif_ports(&hwif->hw, pmif->regbase, 0, &hwif->irq);
- memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
+ memset(&hw, 0, sizeof(hw));
+ pmac_ide_init_hwif_ports(&hw, pmif->regbase, 0, &hwif->irq);
+ memcpy(hwif->io_ports, hw.io_ports, sizeof(hwif->io_ports));
hwif->chipset = ide_pmac;
hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET] || pmif->mediabay;
hwif->hold = pmif->mediabay;
@@ -1135,6 +1138,7 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
hwif->drives[0].autotune = IDE_TUNE_AUTO;
hwif->drives[1].autotune = IDE_TUNE_AUTO;
hwif->host_flags = IDE_HFLAG_SET_PIO_MODE_KEEP_DMA |
+ IDE_HFLAG_PIO_NO_DOWNGRADE |
IDE_HFLAG_POST_SET_MODE;
hwif->pio_mask = ATA_PIO4;
hwif->set_pio_mode = pmac_ide_set_pio_mode;
@@ -1163,10 +1167,9 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
pmac_ide_setup_dma(pmif, hwif);
#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
- /* We probe the hwif now */
- probe_hwif_init(hwif);
+ idx[0] = hwif->index;
- ide_proc_register_port(hwif);
+ ide_device_add(idx);
return 0;
}
@@ -1421,17 +1424,12 @@ static struct macio_driver pmac_ide_macio_driver =
.resume = pmac_ide_macio_resume,
};
-static struct pci_device_id pmac_ide_pci_match[] = {
- { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_ATA,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID_ATA100,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_K2_ATA100,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_SH_ATA,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID2_ATA,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+static const struct pci_device_id pmac_ide_pci_match[] = {
+ { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_UNI_N_ATA), 0 },
+ { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_IPID_ATA100), 0 },
+ { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_K2_ATA100), 0 },
+ { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_SH_ATA), 0 },
+ { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_IPID2_ATA), 0 },
{},
};
@@ -1539,7 +1537,7 @@ pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq)
cur_len -= tc;
++table;
}
- sg++;
+ sg = sg_next(sg);
i--;
}
@@ -1579,19 +1577,6 @@ pmac_ide_destroy_dmatable (ide_drive_t *drive)
}
/*
- * Check what is the best DMA timing setting for the drive and
- * call appropriate functions to apply it.
- */
-static int
-pmac_ide_dma_check(ide_drive_t *drive)
-{
- if (ide_tune_dma(drive))
- return 0;
-
- return -1;
-}
-
-/*
* Prepare a DMA transfer. We build the DMA table, adjust the timings for
* a read on KeyLargo ATA/66 and mark us as waiting for DMA completion
*/
@@ -1788,7 +1773,6 @@ pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
hwif->dma_off_quietly = &ide_dma_off_quietly;
hwif->ide_dma_on = &__ide_dma_on;
- hwif->ide_dma_check = &pmac_ide_dma_check;
hwif->dma_setup = &pmac_ide_dma_setup;
hwif->dma_exec_cmd = &pmac_ide_dma_exec_cmd;
hwif->dma_start = &pmac_ide_dma_start;
@@ -1799,7 +1783,6 @@ pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
hwif->dma_timeout = &ide_dma_timeout;
hwif->dma_lost_irq = &pmac_ide_dma_lost_irq;
- hwif->atapi_dma = 1;
switch(pmif->kind) {
case controller_sh_ata6:
hwif->ultra_mask = pmif->cable_80 ? 0x7f : 0x07;
@@ -1823,9 +1806,6 @@ pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
hwif->swdma_mask = 0x00;
break;
}
-
- hwif->autodma = 1;
- hwif->drives[1].autodma = hwif->drives[0].autodma = hwif->autodma;
}
#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
index 1129f8c30840..25fd09053220 100644
--- a/drivers/ide/setup-pci.c
+++ b/drivers/ide/setup-pci.c
@@ -7,11 +7,6 @@
* May be copied or modified under the terms of the GNU General Public License
*/
-/*
- * This module provides support for automatic detection and
- * configuration of all PCI IDE interfaces present in a system.
- */
-
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
@@ -145,74 +140,36 @@ static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *name)
}
#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
-
-#ifdef CONFIG_BLK_DEV_IDEDMA_FORCED
-/*
- * Long lost data from 2.0.34 that is now in 2.0.39
- *
- * This was used in ./drivers/block/triton.c to do DMA Base address setup
- * when PnP failed. Oh the things we forget. I believe this was part
- * of SFF-8038i that has been withdrawn from public access... :-((
- */
-#define DEFAULT_BMIBA 0xe800 /* in case BIOS did not init it */
-#define DEFAULT_BMCRBA 0xcc00 /* VIA's default value */
-#define DEFAULT_BMALIBA 0xd400 /* ALI's default value */
-#endif /* CONFIG_BLK_DEV_IDEDMA_FORCED */
-
/**
* ide_get_or_set_dma_base - setup BMIBA
- * @hwif: Interface
+ * @d: IDE port info
+ * @hwif: IDE interface
*
- * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space:
- * If need be we set up the DMA base. Where a device has a partner that
- * is already in DMA mode we check and enforce IDE simplex rules.
+ * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space.
+ * Where a device has a partner that is already in DMA mode we check
+ * and enforce IDE simplex rules.
*/
-static unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif)
+static unsigned long ide_get_or_set_dma_base(const struct ide_port_info *d, ide_hwif_t *hwif)
{
unsigned long dma_base = 0;
struct pci_dev *dev = hwif->pci_dev;
-#ifdef CONFIG_BLK_DEV_IDEDMA_FORCED
- int second_chance = 0;
-
-second_chance_to_dma:
-#endif /* CONFIG_BLK_DEV_IDEDMA_FORCED */
-
if (hwif->mmio)
return hwif->dma_base;
if (hwif->mate && hwif->mate->dma_base) {
dma_base = hwif->mate->dma_base - (hwif->channel ? 0 : 8);
} else {
- dma_base = pci_resource_start(dev, 4);
- if (!dma_base) {
- printk(KERN_ERR "%s: dma_base is invalid\n",
- hwif->cds->name);
- }
- }
+ u8 baridx = (d->host_flags & IDE_HFLAG_CS5520) ? 2 : 4;
-#ifdef CONFIG_BLK_DEV_IDEDMA_FORCED
- /* FIXME - should use pci_assign_resource surely */
- if ((!dma_base) && (!second_chance)) {
- unsigned long set_bmiba = 0;
- second_chance++;
- switch(dev->vendor) {
- case PCI_VENDOR_ID_AL:
- set_bmiba = DEFAULT_BMALIBA; break;
- case PCI_VENDOR_ID_VIA:
- set_bmiba = DEFAULT_BMCRBA; break;
- case PCI_VENDOR_ID_INTEL:
- set_bmiba = DEFAULT_BMIBA; break;
- default:
- return dma_base;
- }
- pci_write_config_dword(dev, 0x20, set_bmiba|1);
- goto second_chance_to_dma;
+ dma_base = pci_resource_start(dev, baridx);
+
+ if (dma_base == 0)
+ printk(KERN_ERR "%s: DMA base is invalid\n", d->name);
}
-#endif /* CONFIG_BLK_DEV_IDEDMA_FORCED */
- if (dma_base) {
+ if ((d->host_flags & IDE_HFLAG_CS5520) == 0 && dma_base) {
u8 simplex_stat = 0;
dma_base += hwif->channel ? 8 : 0;
@@ -223,13 +180,13 @@ second_chance_to_dma:
case PCI_DEVICE_ID_CMD_643:
case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE:
case PCI_DEVICE_ID_REVOLUTION:
- simplex_stat = hwif->INB(dma_base + 2);
- hwif->OUTB((simplex_stat&0x60),(dma_base + 2));
- simplex_stat = hwif->INB(dma_base + 2);
+ simplex_stat = inb(dma_base + 2);
+ outb(simplex_stat & 0x60, dma_base + 2);
+ simplex_stat = inb(dma_base + 2);
if (simplex_stat & 0x80) {
printk(KERN_INFO "%s: simplex device: "
- "DMA forced\n",
- hwif->cds->name);
+ "DMA forced\n",
+ d->name);
}
break;
default:
@@ -252,8 +209,8 @@ second_chance_to_dma:
*/
if (hwif->mate && hwif->mate->dma_base) {
printk(KERN_INFO "%s: simplex device: "
- "DMA disabled\n",
- hwif->cds->name);
+ "DMA disabled\n",
+ d->name);
dma_base = 0;
}
}
@@ -263,10 +220,11 @@ second_chance_to_dma:
}
#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
-void ide_setup_pci_noise (struct pci_dev *dev, ide_pci_device_t *d)
+void ide_setup_pci_noise(struct pci_dev *dev, const struct ide_port_info *d)
{
- printk(KERN_INFO "%s: IDE controller at PCI slot %s\n",
- d->name, pci_name(dev));
+ printk(KERN_INFO "%s: IDE controller (0x%04x:0x%04x rev 0x%02x) at "
+ " PCI slot %s\n", d->name, dev->vendor, dev->device,
+ dev->revision, pci_name(dev));
}
EXPORT_SYMBOL_GPL(ide_setup_pci_noise);
@@ -275,15 +233,15 @@ EXPORT_SYMBOL_GPL(ide_setup_pci_noise);
/**
* ide_pci_enable - do PCI enables
* @dev: PCI device
- * @d: IDE pci device data
+ * @d: IDE port info
*
* Enable the IDE PCI device. We attempt to enable the device in full
* but if that fails then we only need BAR4 so we will enable that.
*
* Returns zero on success or an error code
*/
-
-static int ide_pci_enable(struct pci_dev *dev, ide_pci_device_t *d)
+
+static int ide_pci_enable(struct pci_dev *dev, const struct ide_port_info *d)
{
int ret;
@@ -298,9 +256,9 @@ static int ide_pci_enable(struct pci_dev *dev, ide_pci_device_t *d)
}
/*
- * assume all devices can do 32-bit dma for now. we can add a
- * dma mask field to the ide_pci_device_t if we need it (or let
- * lower level driver set the dma mask)
+ * assume all devices can do 32-bit DMA for now, we can add
+ * a DMA mask field to the struct ide_port_info if we need it
+ * (or let lower level driver set the DMA mask)
*/
ret = pci_set_dma_mask(dev, DMA_32BIT_MASK);
if (ret < 0) {
@@ -322,13 +280,13 @@ out:
/**
* ide_pci_configure - configure an unconfigured device
* @dev: PCI device
- * @d: IDE pci device data
+ * @d: IDE port info
*
* Enable and configure the PCI device we have been passed.
* Returns zero on success or an error code.
*/
-
-static int ide_pci_configure(struct pci_dev *dev, ide_pci_device_t *d)
+
+static int ide_pci_configure(struct pci_dev *dev, const struct ide_port_info *d)
{
u16 pcicmd = 0;
/*
@@ -356,15 +314,15 @@ static int ide_pci_configure(struct pci_dev *dev, ide_pci_device_t *d)
/**
* ide_pci_check_iomem - check a register is I/O
- * @dev: pci device
- * @d: ide_pci_device
- * @bar: bar number
+ * @dev: PCI device
+ * @d: IDE port info
+ * @bar: BAR number
*
* Checks if a BAR is configured and points to MMIO space. If so
* print an error and return an error code. Otherwise return 0
*/
-
-static int ide_pci_check_iomem(struct pci_dev *dev, ide_pci_device_t *d, int bar)
+
+static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info *d, int bar)
{
ulong flags = pci_resource_flags(dev, bar);
@@ -386,7 +344,7 @@ static int ide_pci_check_iomem(struct pci_dev *dev, ide_pci_device_t *d, int bar
/**
* ide_hwif_configure - configure an IDE interface
* @dev: PCI device holding interface
- * @d: IDE pci data
+ * @d: IDE port info
* @mate: Paired interface if any
*
* Perform the initial set up for the hardware interface structure. This
@@ -395,11 +353,12 @@ static int ide_pci_check_iomem(struct pci_dev *dev, ide_pci_device_t *d, int bar
*
* Returns the new hardware interface structure, or NULL on a failure
*/
-
-static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev, ide_pci_device_t *d, ide_hwif_t *mate, int port, int irq)
+
+static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev, const struct ide_port_info *d, ide_hwif_t *mate, int port, int irq)
{
unsigned long ctl = 0, base = 0;
ide_hwif_t *hwif;
+ u8 bootable = (d->host_flags & IDE_HFLAG_BOOTABLE) ? 1 : 0;
if ((d->host_flags & IDE_HFLAG_ISA_PORTS) == 0) {
/* Possibly we should fail if these checks report true */
@@ -420,23 +379,24 @@ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev, ide_pci_device_t *d,
ctl = port ? 0x374 : 0x3f4;
base = port ? 0x170 : 0x1f0;
}
- if ((hwif = ide_match_hwif(base, d->bootable, d->name)) == NULL)
+ if ((hwif = ide_match_hwif(base, bootable, d->name)) == NULL)
return NULL; /* no room in ide_hwifs[] */
if (hwif->io_ports[IDE_DATA_OFFSET] != base ||
hwif->io_ports[IDE_CONTROL_OFFSET] != (ctl | 2)) {
- memset(&hwif->hw, 0, sizeof(hwif->hw));
-#ifndef IDE_ARCH_OBSOLETE_INIT
- ide_std_init_ports(&hwif->hw, base, (ctl | 2));
- hwif->hw.io_ports[IDE_IRQ_OFFSET] = 0;
+ hw_regs_t hw;
+
+ memset(&hw, 0, sizeof(hw));
+#ifndef CONFIG_IDE_ARCH_OBSOLETE_INIT
+ ide_std_init_ports(&hw, base, ctl | 2);
#else
- ide_init_hwif_ports(&hwif->hw, base, (ctl | 2), NULL);
+ ide_init_hwif_ports(&hw, base, ctl | 2, NULL);
#endif
- memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
+ memcpy(hwif->io_ports, hw.io_ports, sizeof(hwif->io_ports));
hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
}
- hwif->chipset = ide_pci;
+ hwif->chipset = d->chipset ? d->chipset : ide_pci;
hwif->pci_dev = dev;
- hwif->cds = (struct ide_pci_device_s *) d;
+ hwif->cds = d;
hwif->channel = port;
if (!hwif->irq)
@@ -451,35 +411,30 @@ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev, ide_pci_device_t *d,
/**
* ide_hwif_setup_dma - configure DMA interface
* @dev: PCI device
- * @d: IDE pci data
- * @hwif: Hardware interface we are configuring
+ * @d: IDE port info
+ * @hwif: IDE interface
*
* Set up the DMA base for the interface. Enable the master bits as
* necessary and attempt to bring the device DMA into a ready to use
* state
*/
-
-#ifndef CONFIG_BLK_DEV_IDEDMA_PCI
-static void ide_hwif_setup_dma(struct pci_dev *dev, ide_pci_device_t *d, ide_hwif_t *hwif)
-{
-}
-#else
-static void ide_hwif_setup_dma(struct pci_dev *dev, ide_pci_device_t *d, ide_hwif_t *hwif)
+
+static void ide_hwif_setup_dma(struct pci_dev *dev, const struct ide_port_info *d, ide_hwif_t *hwif)
{
+#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
u16 pcicmd;
+
pci_read_config_word(dev, PCI_COMMAND, &pcicmd);
- if ((d->autodma == AUTODMA) ||
+ if ((d->host_flags & IDE_HFLAG_NO_AUTODMA) == 0 ||
((dev->class >> 8) == PCI_CLASS_STORAGE_IDE &&
(dev->class & 0x80))) {
- unsigned long dma_base = ide_get_or_set_dma_base(hwif);
+ unsigned long dma_base = ide_get_or_set_dma_base(d, hwif);
if (dma_base && !(pcicmd & PCI_COMMAND_MASTER)) {
/*
* Set up BM-DMA capability
* (PnP BIOS should have done this)
*/
- /* default DMA off if we had to configure it here */
- hwif->autodma = 0;
pci_set_master(dev);
if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd) || !(pcicmd & PCI_COMMAND_MASTER)) {
printk(KERN_ERR "%s: %s error updating PCICMD\n",
@@ -498,13 +453,13 @@ static void ide_hwif_setup_dma(struct pci_dev *dev, ide_pci_device_t *d, ide_hwi
"(BIOS)\n", hwif->name, d->name);
}
}
-}
#endif /* CONFIG_BLK_DEV_IDEDMA_PCI*/
+}
/**
* ide_setup_pci_controller - set up IDE PCI
* @dev: PCI device
- * @d: IDE PCI data
+ * @d: IDE port info
* @noisy: verbose flag
* @config: returned as 1 if we configured the hardware
*
@@ -512,11 +467,10 @@ static void ide_hwif_setup_dma(struct pci_dev *dev, ide_pci_device_t *d, ide_hwi
* up the PCI side of the device, checks that the device is enabled
* and enables it if need be
*/
-
-static int ide_setup_pci_controller(struct pci_dev *dev, ide_pci_device_t *d, int noisy, int *config)
+
+static int ide_setup_pci_controller(struct pci_dev *dev, const struct ide_port_info *d, int noisy, int *config)
{
int ret;
- u32 class_rev;
u16 pcicmd;
if (noisy)
@@ -539,10 +493,6 @@ static int ide_setup_pci_controller(struct pci_dev *dev, ide_pci_device_t *d, in
printk(KERN_INFO "%s: device enabled (Linux)\n", d->name);
}
- pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
- class_rev &= 0xff;
- if (noisy)
- printk(KERN_INFO "%s: chipset revision %d\n", d->name, class_rev);
out:
return ret;
}
@@ -550,9 +500,9 @@ out:
/**
* ide_pci_setup_ports - configure ports/devices on PCI IDE
* @dev: PCI device
- * @d: IDE pci device info
+ * @d: IDE port info
* @pciirq: IRQ line
- * @index: ata index to update
+ * @idx: ATA index table to update
*
* Scan the interfaces attached to this device and do any
* necessary per port setup. Attach the devices and ask the
@@ -562,26 +512,25 @@ out:
* but is also used directly as a helper function by some controllers
* where the chipset setup is not the default PCI IDE one.
*/
-
-void ide_pci_setup_ports(struct pci_dev *dev, ide_pci_device_t *d, int pciirq, ata_index_t *index)
+
+void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, int pciirq, u8 *idx)
{
int channels = (d->host_flags & IDE_HFLAG_SINGLE) ? 1 : 2, port;
- int at_least_one_hwif_enabled = 0;
ide_hwif_t *hwif, *mate = NULL;
u8 tmp;
- index->all = 0xf0f0;
-
/*
* Set up the IDE ports
*/
-
+
for (port = 0; port < channels; ++port) {
- ide_pci_enablebit_t *e = &(d->enablebits[port]);
-
+ const ide_pci_enablebit_t *e = &(d->enablebits[port]);
+
if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) ||
- (tmp & e->mask) != e->val))
+ (tmp & e->mask) != e->val)) {
+ printk(KERN_INFO "%s: IDE port disabled\n", d->name);
continue; /* port not enabled */
+ }
if ((hwif = ide_hwif_configure(dev, d, mate, port, pciirq)) == NULL)
continue;
@@ -589,27 +538,49 @@ void ide_pci_setup_ports(struct pci_dev *dev, ide_pci_device_t *d, int pciirq, a
/* setup proper ancestral information */
hwif->gendev.parent = &dev->dev;
- if (hwif->channel) {
- index->b.high = hwif->index;
- } else {
- index->b.low = hwif->index;
- }
+ *(idx + port) = hwif->index;
if (d->init_iops)
d->init_iops(hwif);
- if (d->autodma == NODMA)
- goto bypass_legacy_dma;
-
- if(d->init_setup_dma)
- d->init_setup_dma(dev, d, hwif);
- else
+ if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0)
ide_hwif_setup_dma(dev, d, hwif);
-bypass_legacy_dma:
+
+ if ((!hwif->irq && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) ||
+ (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS))
+ hwif->irq = port ? 15 : 14;
+
+ hwif->fixup = d->fixup;
+
hwif->host_flags = d->host_flags;
hwif->pio_mask = d->pio_mask;
+ if ((d->host_flags & IDE_HFLAG_SERIALIZE) && hwif->mate)
+ hwif->mate->serialized = hwif->serialized = 1;
+
+ if (d->host_flags & IDE_HFLAG_IO_32BIT) {
+ hwif->drives[0].io_32bit = 1;
+ hwif->drives[1].io_32bit = 1;
+ }
+
+ if (d->host_flags & IDE_HFLAG_UNMASK_IRQS) {
+ hwif->drives[0].unmask = 1;
+ hwif->drives[1].unmask = 1;
+ }
+
+ if (hwif->dma_base) {
+ hwif->swdma_mask = d->swdma_mask;
+ hwif->mwdma_mask = d->mwdma_mask;
+ hwif->ultra_mask = d->udma_mask;
+ }
+
+ hwif->drives[0].autotune = 1;
+ hwif->drives[1].autotune = 1;
+
+ if (d->host_flags & IDE_HFLAG_RQSIZE_256)
+ hwif->rqsize = 256;
+
if (d->init_hwif)
/* Call chipset-specific routine
* for each enabled hwif
@@ -617,10 +588,7 @@ bypass_legacy_dma:
d->init_hwif(hwif);
mate = hwif;
- at_least_one_hwif_enabled = 1;
}
- if (!at_least_one_hwif_enabled)
- printk(KERN_INFO "%s: neither IDE port enabled (BIOS)\n", d->name);
}
EXPORT_SYMBOL_GPL(ide_pci_setup_ports);
@@ -632,13 +600,13 @@ EXPORT_SYMBOL_GPL(ide_pci_setup_ports);
*
* One thing that is not standardized is the location of the
* primary/secondary interface "enable/disable" bits. For chipsets that
- * we "know" about, this information is in the ide_pci_device_t struct;
+ * we "know" about, this information is in the struct ide_port_info;
* for all other chipsets, we just assume both interfaces are enabled.
*/
-static int do_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d,
- ata_index_t *index, u8 noisy)
+static int do_ide_setup_pci_device(struct pci_dev *dev,
+ const struct ide_port_info *d,
+ u8 *idx, u8 noisy)
{
- static ata_index_t ata_index = { .b = { .low = 0xff, .high = 0xff } };
int tried_config = 0;
int pciirq, ret;
@@ -688,51 +656,35 @@ static int do_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d,
/* FIXME: silent failure can happen */
- *index = ata_index;
- ide_pci_setup_ports(dev, d, pciirq, index);
+ ide_pci_setup_ports(dev, d, pciirq, idx);
out:
return ret;
}
-int ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d)
+int ide_setup_pci_device(struct pci_dev *dev, const struct ide_port_info *d)
{
- ide_hwif_t *hwif = NULL, *mate = NULL;
- ata_index_t index_list;
+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
int ret;
- ret = do_ide_setup_pci_device(dev, d, &index_list, 1);
- if (ret < 0)
- goto out;
-
- if ((index_list.b.low & 0xf0) != 0xf0)
- hwif = &ide_hwifs[index_list.b.low];
- if ((index_list.b.high & 0xf0) != 0xf0)
- mate = &ide_hwifs[index_list.b.high];
+ ret = do_ide_setup_pci_device(dev, d, &idx[0], 1);
- if (hwif)
- probe_hwif_init_with_fixup(hwif, d->fixup);
- if (mate)
- probe_hwif_init_with_fixup(mate, d->fixup);
+ if (ret >= 0)
+ ide_device_add(idx);
- if (hwif)
- ide_proc_register_port(hwif);
- if (mate)
- ide_proc_register_port(mate);
-out:
return ret;
}
EXPORT_SYMBOL_GPL(ide_setup_pci_device);
int ide_setup_pci_devices(struct pci_dev *dev1, struct pci_dev *dev2,
- ide_pci_device_t *d)
+ const struct ide_port_info *d)
{
struct pci_dev *pdev[] = { dev1, dev2 };
- ata_index_t index_list[2];
int ret, i;
+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
for (i = 0; i < 2; i++) {
- ret = do_ide_setup_pci_device(pdev[i], d, index_list + i, !i);
+ ret = do_ide_setup_pci_device(pdev[i], d, &idx[i*2], !i);
/*
* FIXME: Mom, mom, they stole me the helper function to undo
* do_ide_setup_pci_device() on the first device!
@@ -741,25 +693,7 @@ int ide_setup_pci_devices(struct pci_dev *dev1, struct pci_dev *dev2,
goto out;
}
- for (i = 0; i < 2; i++) {
- u8 idx[2] = { index_list[i].b.low, index_list[i].b.high };
- int j;
-
- for (j = 0; j < 2; j++) {
- if ((idx[j] & 0xf0) != 0xf0)
- probe_hwif_init(ide_hwifs + idx[j]);
- }
- }
-
- for (i = 0; i < 2; i++) {
- u8 idx[2] = { index_list[i].b.low, index_list[i].b.high };
- int j;
-
- for (j = 0; j < 2; j++) {
- if ((idx[j] & 0xf0) != 0xf0)
- ide_proc_register_port(ide_hwifs + idx[j]);
- }
- }
+ ide_device_add(idx);
out:
return ret;
}
@@ -784,9 +718,6 @@ static LIST_HEAD(ide_pci_drivers);
* hands the controllers off to the core PCI code to do the rest of
* the work.
*
- * The driver_data of the driver table must point to an ide_pci_device_t
- * describing the interface.
- *
* Returns are the same as for pci_register_driver
*/
diff --git a/drivers/ieee1394/csr1212.c b/drivers/ieee1394/csr1212.c
index d08166bda1c5..e8122def164d 100644
--- a/drivers/ieee1394/csr1212.c
+++ b/drivers/ieee1394/csr1212.c
@@ -218,12 +218,10 @@ static struct csr1212_keyval *csr1212_new_keyval(u8 type, u8 key)
if (!kv)
return NULL;
+ atomic_set(&kv->refcnt, 1);
kv->key.type = type;
kv->key.id = key;
-
kv->associate = NULL;
- kv->refcnt = 1;
-
kv->next = NULL;
kv->prev = NULL;
kv->offset = 0;
@@ -326,12 +324,13 @@ void csr1212_associate_keyval(struct csr1212_keyval *kv,
if (kv->associate)
csr1212_release_keyval(kv->associate);
- associate->refcnt++;
+ csr1212_keep_keyval(associate);
kv->associate = associate;
}
-int csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir,
- struct csr1212_keyval *kv)
+static int __csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir,
+ struct csr1212_keyval *kv,
+ bool keep_keyval)
{
struct csr1212_dentry *dentry;
@@ -341,10 +340,10 @@ int csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir,
if (!dentry)
return -ENOMEM;
+ if (keep_keyval)
+ csr1212_keep_keyval(kv);
dentry->kv = kv;
- kv->refcnt++;
-
dentry->next = NULL;
dentry->prev = dir->value.directory.dentries_tail;
@@ -358,6 +357,12 @@ int csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir,
return CSR1212_SUCCESS;
}
+int csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir,
+ struct csr1212_keyval *kv)
+{
+ return __csr1212_attach_keyval_to_directory(dir, kv, true);
+}
+
#define CSR1212_DESCRIPTOR_LEAF_DATA(kv) \
(&((kv)->value.leaf.data[1]))
@@ -483,15 +488,18 @@ void csr1212_detach_keyval_from_directory(struct csr1212_keyval *dir,
/* This function is used to free the memory taken by a keyval. If the given
* keyval is a directory type, then any keyvals contained in that directory
- * will be destroyed as well if their respective refcnts are 0. By means of
+ * will be destroyed as well if noone holds a reference on them. By means of
* list manipulation, this routine will descend a directory structure in a
* non-recursive manner. */
-static void csr1212_destroy_keyval(struct csr1212_keyval *kv)
+void csr1212_release_keyval(struct csr1212_keyval *kv)
{
struct csr1212_keyval *k, *a;
struct csr1212_dentry dentry;
struct csr1212_dentry *head, *tail;
+ if (!atomic_dec_and_test(&kv->refcnt))
+ return;
+
dentry.kv = kv;
dentry.next = NULL;
dentry.prev = NULL;
@@ -503,9 +511,8 @@ static void csr1212_destroy_keyval(struct csr1212_keyval *kv)
k = head->kv;
while (k) {
- k->refcnt--;
-
- if (k->refcnt > 0)
+ /* must not dec_and_test kv->refcnt again */
+ if (k != kv && !atomic_dec_and_test(&k->refcnt))
break;
a = k->associate;
@@ -536,14 +543,6 @@ static void csr1212_destroy_keyval(struct csr1212_keyval *kv)
}
}
-void csr1212_release_keyval(struct csr1212_keyval *kv)
-{
- if (kv->refcnt > 1)
- kv->refcnt--;
- else
- csr1212_destroy_keyval(kv);
-}
-
void csr1212_destroy_csr(struct csr1212_csr *csr)
{
struct csr1212_csr_rom_cache *c, *oc;
@@ -1126,6 +1125,7 @@ csr1212_parse_dir_entry(struct csr1212_keyval *dir, u32 ki, u32 kv_pos)
int ret = CSR1212_SUCCESS;
struct csr1212_keyval *k = NULL;
u32 offset;
+ bool keep_keyval = true;
switch (CSR1212_KV_KEY_TYPE(ki)) {
case CSR1212_KV_TYPE_IMMEDIATE:
@@ -1135,8 +1135,8 @@ csr1212_parse_dir_entry(struct csr1212_keyval *dir, u32 ki, u32 kv_pos)
ret = -ENOMEM;
goto out;
}
-
- k->refcnt = 0; /* Don't keep local reference when parsing. */
+ /* Don't keep local reference when parsing. */
+ keep_keyval = false;
break;
case CSR1212_KV_TYPE_CSR_OFFSET:
@@ -1146,7 +1146,8 @@ csr1212_parse_dir_entry(struct csr1212_keyval *dir, u32 ki, u32 kv_pos)
ret = -ENOMEM;
goto out;
}
- k->refcnt = 0; /* Don't keep local reference when parsing. */
+ /* Don't keep local reference when parsing. */
+ keep_keyval = false;
break;
default:
@@ -1174,8 +1175,10 @@ csr1212_parse_dir_entry(struct csr1212_keyval *dir, u32 ki, u32 kv_pos)
ret = -ENOMEM;
goto out;
}
- k->refcnt = 0; /* Don't keep local reference when parsing. */
- k->valid = 0; /* Contents not read yet so it's not valid. */
+ /* Don't keep local reference when parsing. */
+ keep_keyval = false;
+ /* Contents not read yet so it's not valid. */
+ k->valid = 0;
k->offset = offset;
k->prev = dir;
@@ -1183,7 +1186,7 @@ csr1212_parse_dir_entry(struct csr1212_keyval *dir, u32 ki, u32 kv_pos)
dir->next->prev = k;
dir->next = k;
}
- ret = csr1212_attach_keyval_to_directory(dir, k);
+ ret = __csr1212_attach_keyval_to_directory(dir, k, keep_keyval);
out:
if (ret != CSR1212_SUCCESS && k != NULL)
free_keyval(k);
diff --git a/drivers/ieee1394/csr1212.h b/drivers/ieee1394/csr1212.h
index df909ce66304..043039fc63ec 100644
--- a/drivers/ieee1394/csr1212.h
+++ b/drivers/ieee1394/csr1212.h
@@ -32,6 +32,7 @@
#include <linux/types.h>
#include <linux/slab.h>
+#include <asm/atomic.h>
#define CSR1212_MALLOC(size) kmalloc((size), GFP_KERNEL)
#define CSR1212_FREE(ptr) kfree(ptr)
@@ -149,7 +150,7 @@ struct csr1212_keyval {
struct csr1212_directory directory;
} value;
struct csr1212_keyval *associate;
- int refcnt;
+ atomic_t refcnt;
/* used in generating and/or parsing CSR image */
struct csr1212_keyval *next, *prev; /* flat list of CSR elements */
@@ -350,7 +351,8 @@ csr1212_get_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv);
* need for code to retain a keyval that has been parsed. */
static inline void csr1212_keep_keyval(struct csr1212_keyval *kv)
{
- kv->refcnt++;
+ atomic_inc(&kv->refcnt);
+ smp_mb__after_atomic_inc();
}
diff --git a/drivers/ieee1394/dma.c b/drivers/ieee1394/dma.c
index 45d605581922..7c4eb39b7024 100644
--- a/drivers/ieee1394/dma.c
+++ b/drivers/ieee1394/dma.c
@@ -12,7 +12,7 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
-#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
#include "dma.h"
@@ -103,16 +103,15 @@ int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes,
goto err;
}
- /* just to be safe - this will become unnecessary once sglist->address goes away */
- memset(dma->sglist, 0, dma->n_pages * sizeof(*dma->sglist));
+ sg_init_table(dma->sglist, dma->n_pages);
/* fill scatter/gather list with pages */
for (i = 0; i < dma->n_pages; i++) {
unsigned long va =
(unsigned long)dma->kvirt + (i << PAGE_SHIFT);
- dma->sglist[i].page = vmalloc_to_page((void *)va);
- dma->sglist[i].length = PAGE_SIZE;
+ sg_set_page(&dma->sglist[i], vmalloc_to_page((void *)va),
+ PAGE_SIZE, 0);
}
/* map sglist to the IOMMU */
diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
index dc9dce22f6a8..b166b3575fa6 100644
--- a/drivers/ieee1394/eth1394.c
+++ b/drivers/ieee1394/eth1394.c
@@ -1153,8 +1153,6 @@ static int ether1394_data_handler(struct net_device *dev, int srcid, int destid,
pdg->sz++;
lh = find_partial_datagram(pdgl, dgl);
} else {
- struct partial_datagram *pd;
-
pd = list_entry(lh, struct partial_datagram, list);
if (fragment_overlap(&pd->frag_info, fg_off, fg_len)) {
@@ -1222,23 +1220,19 @@ static int ether1394_data_handler(struct net_device *dev, int srcid, int destid,
priv->stats.rx_errors++;
priv->stats.rx_dropped++;
dev_kfree_skb_any(skb);
- goto bad_proto;
- }
-
- if (netif_rx(skb) == NET_RX_DROP) {
+ } else if (netif_rx(skb) == NET_RX_DROP) {
priv->stats.rx_errors++;
priv->stats.rx_dropped++;
- goto bad_proto;
+ } else {
+ priv->stats.rx_packets++;
+ priv->stats.rx_bytes += skb->len;
}
- /* Statistics */
- priv->stats.rx_packets++;
- priv->stats.rx_bytes += skb->len;
+ spin_unlock_irqrestore(&priv->lock, flags);
bad_proto:
if (netif_queue_stopped(dev))
netif_wake_queue(dev);
- spin_unlock_irqrestore(&priv->lock, flags);
dev->last_rx = jiffies;
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
index 98fd985a32ff..36c747b277d0 100644
--- a/drivers/ieee1394/ieee1394_core.c
+++ b/drivers/ieee1394/ieee1394_core.c
@@ -488,7 +488,7 @@ void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot)
highlevel_host_reset(host);
}
-static spinlock_t pending_packets_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(pending_packets_lock);
/**
* hpsb_packet_sent - notify core of sending a packet
diff --git a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c
index c39c70a8aa9f..677989320951 100644
--- a/drivers/ieee1394/ieee1394_transactions.c
+++ b/drivers/ieee1394/ieee1394_transactions.c
@@ -235,7 +235,6 @@ int hpsb_packet_success(struct hpsb_packet *packet)
packet->node_id);
return -EAGAIN;
}
- BUG();
case ACK_BUSY_X:
case ACK_BUSY_A:
@@ -282,7 +281,6 @@ int hpsb_packet_success(struct hpsb_packet *packet)
packet->ack_code, packet->node_id, packet->tcode);
return -EAGAIN;
}
- BUG();
}
struct hpsb_packet *hpsb_make_readpacket(struct hpsb_host *host, nodeid_t node,
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index 1939fee616ec..90dc75be3418 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -1014,13 +1014,13 @@ static struct unit_directory *nodemgr_process_unit_directory
CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) == 0) {
switch (last_key_id) {
case CSR1212_KV_ID_VENDOR:
- ud->vendor_name_kv = kv;
csr1212_keep_keyval(kv);
+ ud->vendor_name_kv = kv;
break;
case CSR1212_KV_ID_MODEL:
- ud->model_name_kv = kv;
csr1212_keep_keyval(kv);
+ ud->model_name_kv = kv;
break;
}
@@ -1112,7 +1112,7 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent
{
unsigned int ud_id = 0;
struct csr1212_dentry *dentry;
- struct csr1212_keyval *kv;
+ struct csr1212_keyval *kv, *vendor_name_kv = NULL;
u8 last_key_id = 0;
ne->needs_probe = 0;
@@ -1139,8 +1139,8 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent
CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH(kv) == 0 &&
CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET(kv) == 0 &&
CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) == 0) {
- ne->vendor_name_kv = kv;
csr1212_keep_keyval(kv);
+ vendor_name_kv = kv;
}
}
break;
@@ -1149,10 +1149,13 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent
}
if (ne->vendor_name_kv) {
- int error = device_create_file(&ne->device,
- &dev_attr_ne_vendor_name_kv);
-
- if (error && error != -EEXIST)
+ kv = ne->vendor_name_kv;
+ ne->vendor_name_kv = vendor_name_kv;
+ csr1212_release_keyval(kv);
+ } else if (vendor_name_kv) {
+ ne->vendor_name_kv = vendor_name_kv;
+ if (device_create_file(&ne->device,
+ &dev_attr_ne_vendor_name_kv) != 0)
HPSB_ERR("Failed to add sysfs attribute");
}
}
@@ -1712,7 +1715,8 @@ static int nodemgr_host_thread(void *__hi)
* to make sure things settle down. */
g = get_hpsb_generation(host);
for (i = 0; i < 4 ; i++) {
- if (msleep_interruptible(63) || kthread_should_stop())
+ msleep_interruptible(63);
+ if (kthread_should_stop())
goto exit;
/* Now get the generation in which the node ID's we collect
diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
index d1a5bcdb5e0b..8af01ab30cc9 100644
--- a/drivers/ieee1394/pcilynx.c
+++ b/drivers/ieee1394/pcilynx.c
@@ -121,16 +121,6 @@ static int bit_getsda(void *data)
return reg_read((struct ti_lynx *) data, SERIAL_EEPROM_CONTROL) & 0x00000010;
}
-static int bit_reg(struct i2c_client *client)
-{
- return 0;
-}
-
-static int bit_unreg(struct i2c_client *client)
-{
- return 0;
-}
-
static struct i2c_algo_bit_data bit_data = {
.setsda = bit_setsda,
.setscl = bit_setscl,
@@ -140,14 +130,6 @@ static struct i2c_algo_bit_data bit_data = {
.timeout = 100,
};
-static struct i2c_adapter bit_ops = {
- .id = 0xAA, //FIXME: probably we should get an id in i2c-id.h
- .client_register = bit_reg,
- .client_unregister = bit_unreg,
- .name = "PCILynx I2C",
-};
-
-
/*
* PCL handling functions.
@@ -765,7 +747,6 @@ static int lynx_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
} else {
struct ti_pcl pcl;
u32 ack;
- struct hpsb_packet *packet;
PRINT(KERN_INFO, lynx->id, "cancelling async packet, that was already in PCL");
@@ -1436,9 +1417,11 @@ static int __devinit add_card(struct pci_dev *dev,
struct i2c_algo_bit_data i2c_adapter_data;
error = -ENOMEM;
- i2c_ad = kmemdup(&bit_ops, sizeof(*i2c_ad), GFP_KERNEL);
+ i2c_ad = kzalloc(sizeof(*i2c_ad), GFP_KERNEL);
if (!i2c_ad) FAIL("failed to allocate I2C adapter memory");
+ i2c_ad->id = I2C_HW_B_PCILYNX;
+ strlcpy(i2c_ad->name, "PCILynx I2C", sizeof(i2c_ad->name));
i2c_adapter_data = bit_data;
i2c_ad->algo_data = &i2c_adapter_data;
i2c_adapter_data.data = lynx;
@@ -1465,13 +1448,11 @@ static int __devinit add_card(struct pci_dev *dev,
{ 0x50, I2C_M_RD, 20, (unsigned char*) lynx->bus_info_block }
};
- /* we use i2c_transfer, because i2c_smbus_read_block_data does not work properly and we
- do it more efficiently in one transaction rather then using several reads */
+ /* we use i2c_transfer because we have no i2c_client
+ at hand */
if (i2c_transfer(i2c_ad, msg, 2) < 0) {
PRINT(KERN_ERR, lynx->id, "unable to read bus info block from i2c");
} else {
- int i;
-
PRINT(KERN_INFO, lynx->id, "got bus info block from serial eeprom");
/* FIXME: probably we shoud rewrite the max_rec, max_ROM(1394a),
* generation(1394a) and link_spd(1394a) field and recalculate
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index a81ba8fca0db..b83d254bc86e 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -71,11 +71,11 @@
#include <linux/types.h>
#include <linux/wait.h>
#include <linux/workqueue.h>
+#include <linux/scatterlist.h>
#include <asm/byteorder.h>
#include <asm/errno.h>
#include <asm/param.h>
-#include <asm/scatterlist.h>
#include <asm/system.h>
#include <asm/types.h>
@@ -242,6 +242,8 @@ static int sbp2_max_speed_and_size(struct sbp2_lu *);
static const u8 sbp2_speedto_max_payload[] = { 0x7, 0x8, 0x9, 0xA, 0xB, 0xC };
+static DEFINE_RWLOCK(sbp2_hi_logical_units_lock);
+
static struct hpsb_highlevel sbp2_highlevel = {
.name = SBP2_DEVICE_NAME,
.host_reset = sbp2_host_reset,
@@ -732,6 +734,7 @@ static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *ud)
struct sbp2_fwhost_info *hi;
struct Scsi_Host *shost = NULL;
struct sbp2_lu *lu = NULL;
+ unsigned long flags;
lu = kzalloc(sizeof(*lu), GFP_KERNEL);
if (!lu) {
@@ -784,7 +787,9 @@ static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *ud)
lu->hi = hi;
+ write_lock_irqsave(&sbp2_hi_logical_units_lock, flags);
list_add_tail(&lu->lu_list, &hi->logical_units);
+ write_unlock_irqrestore(&sbp2_hi_logical_units_lock, flags);
/* Register the status FIFO address range. We could use the same FIFO
* for targets at different nodes. However we need different FIFOs per
@@ -828,16 +833,20 @@ static void sbp2_host_reset(struct hpsb_host *host)
{
struct sbp2_fwhost_info *hi;
struct sbp2_lu *lu;
+ unsigned long flags;
hi = hpsb_get_hostinfo(&sbp2_highlevel, host);
if (!hi)
return;
+
+ read_lock_irqsave(&sbp2_hi_logical_units_lock, flags);
list_for_each_entry(lu, &hi->logical_units, lu_list)
if (likely(atomic_read(&lu->state) !=
SBP2LU_STATE_IN_SHUTDOWN)) {
atomic_set(&lu->state, SBP2LU_STATE_IN_RESET);
scsi_block_requests(lu->shost);
}
+ read_unlock_irqrestore(&sbp2_hi_logical_units_lock, flags);
}
static int sbp2_start_device(struct sbp2_lu *lu)
@@ -919,6 +928,7 @@ alloc_fail:
static void sbp2_remove_device(struct sbp2_lu *lu)
{
struct sbp2_fwhost_info *hi;
+ unsigned long flags;
if (!lu)
return;
@@ -933,7 +943,9 @@ static void sbp2_remove_device(struct sbp2_lu *lu)
flush_scheduled_work();
sbp2util_remove_command_orb_pool(lu, hi->host);
+ write_lock_irqsave(&sbp2_hi_logical_units_lock, flags);
list_del(&lu->lu_list);
+ write_unlock_irqrestore(&sbp2_hi_logical_units_lock, flags);
if (lu->login_response)
dma_free_coherent(hi->host->device.parent,
@@ -1454,7 +1466,7 @@ static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
cmd->dma_size = sgpnt[0].length;
cmd->dma_type = CMD_DMA_PAGE;
cmd->cmd_dma = dma_map_page(hi->host->device.parent,
- sgpnt[0].page, sgpnt[0].offset,
+ sg_page(&sgpnt[0]), sgpnt[0].offset,
cmd->dma_size, cmd->dma_dir);
orb->data_descriptor_lo = cmd->cmd_dma;
@@ -1707,6 +1719,7 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid,
}
/* Find the unit which wrote the status. */
+ read_lock_irqsave(&sbp2_hi_logical_units_lock, flags);
list_for_each_entry(lu_tmp, &hi->logical_units, lu_list) {
if (lu_tmp->ne->nodeid == nodeid &&
lu_tmp->status_fifo_addr == addr) {
@@ -1714,6 +1727,8 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid,
break;
}
}
+ read_unlock_irqrestore(&sbp2_hi_logical_units_lock, flags);
+
if (unlikely(!lu)) {
SBP2_ERR("lu is NULL - device is gone?");
return RCODE_ADDRESS_ERROR;
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 93644f82592c..0751697ef984 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -114,13 +114,16 @@ struct rdma_id_private {
struct rdma_bind_list *bind_list;
struct hlist_node node;
- struct list_head list;
- struct list_head listen_list;
+ struct list_head list; /* listen_any_list or cma_device.list */
+ struct list_head listen_list; /* per device listens */
struct cma_device *cma_dev;
struct list_head mc_list;
+ int internal_id;
enum cma_state state;
spinlock_t lock;
+ struct mutex qp_mutex;
+
struct completion comp;
atomic_t refcount;
wait_queue_head_t wait_remove;
@@ -389,6 +392,7 @@ struct rdma_cm_id *rdma_create_id(rdma_cm_event_handler event_handler,
id_priv->id.event_handler = event_handler;
id_priv->id.ps = ps;
spin_lock_init(&id_priv->lock);
+ mutex_init(&id_priv->qp_mutex);
init_completion(&id_priv->comp);
atomic_set(&id_priv->refcount, 1);
init_waitqueue_head(&id_priv->wait_remove);
@@ -474,61 +478,86 @@ EXPORT_SYMBOL(rdma_create_qp);
void rdma_destroy_qp(struct rdma_cm_id *id)
{
- ib_destroy_qp(id->qp);
+ struct rdma_id_private *id_priv;
+
+ id_priv = container_of(id, struct rdma_id_private, id);
+ mutex_lock(&id_priv->qp_mutex);
+ ib_destroy_qp(id_priv->id.qp);
+ id_priv->id.qp = NULL;
+ mutex_unlock(&id_priv->qp_mutex);
}
EXPORT_SYMBOL(rdma_destroy_qp);
-static int cma_modify_qp_rtr(struct rdma_cm_id *id)
+static int cma_modify_qp_rtr(struct rdma_id_private *id_priv)
{
struct ib_qp_attr qp_attr;
int qp_attr_mask, ret;
- if (!id->qp)
- return 0;
+ mutex_lock(&id_priv->qp_mutex);
+ if (!id_priv->id.qp) {
+ ret = 0;
+ goto out;
+ }
/* Need to update QP attributes from default values. */
qp_attr.qp_state = IB_QPS_INIT;
- ret = rdma_init_qp_attr(id, &qp_attr, &qp_attr_mask);
+ ret = rdma_init_qp_attr(&id_priv->id, &qp_attr, &qp_attr_mask);
if (ret)
- return ret;
+ goto out;
- ret = ib_modify_qp(id->qp, &qp_attr, qp_attr_mask);
+ ret = ib_modify_qp(id_priv->id.qp, &qp_attr, qp_attr_mask);
if (ret)
- return ret;
+ goto out;
qp_attr.qp_state = IB_QPS_RTR;
- ret = rdma_init_qp_attr(id, &qp_attr, &qp_attr_mask);
+ ret = rdma_init_qp_attr(&id_priv->id, &qp_attr, &qp_attr_mask);
if (ret)
- return ret;
+ goto out;
- return ib_modify_qp(id->qp, &qp_attr, qp_attr_mask);
+ ret = ib_modify_qp(id_priv->id.qp, &qp_attr, qp_attr_mask);
+out:
+ mutex_unlock(&id_priv->qp_mutex);
+ return ret;
}
-static int cma_modify_qp_rts(struct rdma_cm_id *id)
+static int cma_modify_qp_rts(struct rdma_id_private *id_priv)
{
struct ib_qp_attr qp_attr;
int qp_attr_mask, ret;
- if (!id->qp)
- return 0;
+ mutex_lock(&id_priv->qp_mutex);
+ if (!id_priv->id.qp) {
+ ret = 0;
+ goto out;
+ }
qp_attr.qp_state = IB_QPS_RTS;
- ret = rdma_init_qp_attr(id, &qp_attr, &qp_attr_mask);
+ ret = rdma_init_qp_attr(&id_priv->id, &qp_attr, &qp_attr_mask);
if (ret)
- return ret;
+ goto out;
- return ib_modify_qp(id->qp, &qp_attr, qp_attr_mask);
+ ret = ib_modify_qp(id_priv->id.qp, &qp_attr, qp_attr_mask);
+out:
+ mutex_unlock(&id_priv->qp_mutex);
+ return ret;
}
-static int cma_modify_qp_err(struct rdma_cm_id *id)
+static int cma_modify_qp_err(struct rdma_id_private *id_priv)
{
struct ib_qp_attr qp_attr;
+ int ret;
- if (!id->qp)
- return 0;
+ mutex_lock(&id_priv->qp_mutex);
+ if (!id_priv->id.qp) {
+ ret = 0;
+ goto out;
+ }
qp_attr.qp_state = IB_QPS_ERR;
- return ib_modify_qp(id->qp, &qp_attr, IB_QP_STATE);
+ ret = ib_modify_qp(id_priv->id.qp, &qp_attr, IB_QP_STATE);
+out:
+ mutex_unlock(&id_priv->qp_mutex);
+ return ret;
}
static int cma_ib_init_qp_attr(struct rdma_id_private *id_priv,
@@ -717,50 +746,27 @@ static void cma_cancel_route(struct rdma_id_private *id_priv)
}
}
-static inline int cma_internal_listen(struct rdma_id_private *id_priv)
-{
- return (id_priv->state == CMA_LISTEN) && id_priv->cma_dev &&
- cma_any_addr(&id_priv->id.route.addr.src_addr);
-}
-
-static void cma_destroy_listen(struct rdma_id_private *id_priv)
-{
- cma_exch(id_priv, CMA_DESTROYING);
-
- if (id_priv->cma_dev) {
- switch (rdma_node_get_transport(id_priv->id.device->node_type)) {
- case RDMA_TRANSPORT_IB:
- if (id_priv->cm_id.ib && !IS_ERR(id_priv->cm_id.ib))
- ib_destroy_cm_id(id_priv->cm_id.ib);
- break;
- case RDMA_TRANSPORT_IWARP:
- if (id_priv->cm_id.iw && !IS_ERR(id_priv->cm_id.iw))
- iw_destroy_cm_id(id_priv->cm_id.iw);
- break;
- default:
- break;
- }
- cma_detach_from_dev(id_priv);
- }
- list_del(&id_priv->listen_list);
-
- cma_deref_id(id_priv);
- wait_for_completion(&id_priv->comp);
-
- kfree(id_priv);
-}
-
static void cma_cancel_listens(struct rdma_id_private *id_priv)
{
struct rdma_id_private *dev_id_priv;
+ /*
+ * Remove from listen_any_list to prevent added devices from spawning
+ * additional listen requests.
+ */
mutex_lock(&lock);
list_del(&id_priv->list);
while (!list_empty(&id_priv->listen_list)) {
dev_id_priv = list_entry(id_priv->listen_list.next,
struct rdma_id_private, listen_list);
- cma_destroy_listen(dev_id_priv);
+ /* sync with device removal to avoid duplicate destruction */
+ list_del_init(&dev_id_priv->list);
+ list_del(&dev_id_priv->listen_list);
+ mutex_unlock(&lock);
+
+ rdma_destroy_id(&dev_id_priv->id);
+ mutex_lock(&lock);
}
mutex_unlock(&lock);
}
@@ -848,6 +854,9 @@ void rdma_destroy_id(struct rdma_cm_id *id)
cma_deref_id(id_priv);
wait_for_completion(&id_priv->comp);
+ if (id_priv->internal_id)
+ cma_deref_id(id_priv->id.context);
+
kfree(id_priv->id.route.path_rec);
kfree(id_priv);
}
@@ -857,11 +866,11 @@ static int cma_rep_recv(struct rdma_id_private *id_priv)
{
int ret;
- ret = cma_modify_qp_rtr(&id_priv->id);
+ ret = cma_modify_qp_rtr(id_priv);
if (ret)
goto reject;
- ret = cma_modify_qp_rts(&id_priv->id);
+ ret = cma_modify_qp_rts(id_priv);
if (ret)
goto reject;
@@ -871,7 +880,7 @@ static int cma_rep_recv(struct rdma_id_private *id_priv)
return 0;
reject:
- cma_modify_qp_err(&id_priv->id);
+ cma_modify_qp_err(id_priv);
ib_send_cm_rej(id_priv->cm_id.ib, IB_CM_REJ_CONSUMER_DEFINED,
NULL, 0, NULL, 0);
return ret;
@@ -947,7 +956,7 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
/* ignore event */
goto out;
case IB_CM_REJ_RECEIVED:
- cma_modify_qp_err(&id_priv->id);
+ cma_modify_qp_err(id_priv);
event.status = ib_event->param.rej_rcvd.reason;
event.event = RDMA_CM_EVENT_REJECTED;
event.param.conn.private_data = ib_event->private_data;
@@ -1404,14 +1413,13 @@ static void cma_listen_on_dev(struct rdma_id_private *id_priv,
cma_attach_to_dev(dev_id_priv, cma_dev);
list_add_tail(&dev_id_priv->listen_list, &id_priv->listen_list);
+ atomic_inc(&id_priv->refcount);
+ dev_id_priv->internal_id = 1;
ret = rdma_listen(id, id_priv->backlog);
if (ret)
- goto err;
-
- return;
-err:
- cma_destroy_listen(dev_id_priv);
+ printk(KERN_WARNING "RDMA CMA: cma_listen_on_dev, error %d, "
+ "listening on device %s", ret, cma_dev->device->name);
}
static void cma_listen_on_all(struct rdma_id_private *id_priv)
@@ -2264,7 +2272,7 @@ static int cma_connect_iw(struct rdma_id_private *id_priv,
sin = (struct sockaddr_in*) &id_priv->id.route.addr.dst_addr;
cm_id->remote_addr = *sin;
- ret = cma_modify_qp_rtr(&id_priv->id);
+ ret = cma_modify_qp_rtr(id_priv);
if (ret)
goto out;
@@ -2331,7 +2339,7 @@ static int cma_accept_ib(struct rdma_id_private *id_priv,
int qp_attr_mask, ret;
if (id_priv->id.qp) {
- ret = cma_modify_qp_rtr(&id_priv->id);
+ ret = cma_modify_qp_rtr(id_priv);
if (ret)
goto out;
@@ -2370,7 +2378,7 @@ static int cma_accept_iw(struct rdma_id_private *id_priv,
struct iw_cm_conn_param iw_param;
int ret;
- ret = cma_modify_qp_rtr(&id_priv->id);
+ ret = cma_modify_qp_rtr(id_priv);
if (ret)
return ret;
@@ -2442,7 +2450,7 @@ int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
return 0;
reject:
- cma_modify_qp_err(id);
+ cma_modify_qp_err(id_priv);
rdma_reject(id, NULL, 0);
return ret;
}
@@ -2512,7 +2520,7 @@ int rdma_disconnect(struct rdma_cm_id *id)
switch (rdma_node_get_transport(id->device->node_type)) {
case RDMA_TRANSPORT_IB:
- ret = cma_modify_qp_err(id);
+ ret = cma_modify_qp_err(id_priv);
if (ret)
goto out;
/* Initiate or respond to a disconnect. */
@@ -2543,9 +2551,11 @@ static int cma_ib_mc_handler(int status, struct ib_sa_multicast *multicast)
cma_disable_remove(id_priv, CMA_ADDR_RESOLVED))
return 0;
+ mutex_lock(&id_priv->qp_mutex);
if (!status && id_priv->id.qp)
status = ib_attach_mcast(id_priv->id.qp, &multicast->rec.mgid,
multicast->rec.mlid);
+ mutex_unlock(&id_priv->qp_mutex);
memset(&event, 0, sizeof event);
event.status = status;
@@ -2757,16 +2767,12 @@ static void cma_process_remove(struct cma_device *cma_dev)
id_priv = list_entry(cma_dev->id_list.next,
struct rdma_id_private, list);
- if (cma_internal_listen(id_priv)) {
- cma_destroy_listen(id_priv);
- continue;
- }
-
+ list_del(&id_priv->listen_list);
list_del_init(&id_priv->list);
atomic_inc(&id_priv->refcount);
mutex_unlock(&lock);
- ret = cma_remove_id_dev(id_priv);
+ ret = id_priv->internal_id ? 1 : cma_remove_id_dev(id_priv);
cma_deref_id(id_priv);
if (ret)
rdma_destroy_id(&id_priv->id);
@@ -2797,11 +2803,12 @@ static void cma_remove_one(struct ib_device *device)
static int cma_init(void)
{
- int ret, low, high;
+ int ret, low, high, remaining;
get_random_bytes(&next_port, sizeof next_port);
inet_get_local_port_range(&low, &high);
- next_port = ((unsigned int) next_port % (high - low)) + low;
+ remaining = (high - low) + 1;
+ next_port = ((unsigned int) next_port % remaining) + low;
cma_wq = create_singlethread_workqueue("rdma_cm");
if (!cma_wq)
diff --git a/drivers/infiniband/core/fmr_pool.c b/drivers/infiniband/core/fmr_pool.c
index d7f64525469b..e8d5f6b64998 100644
--- a/drivers/infiniband/core/fmr_pool.c
+++ b/drivers/infiniband/core/fmr_pool.c
@@ -291,10 +291,10 @@ struct ib_fmr_pool *ib_create_fmr_pool(struct ib_pd *pd,
atomic_set(&pool->flush_ser, 0);
init_waitqueue_head(&pool->force_wait);
- pool->thread = kthread_create(ib_fmr_cleanup_thread,
- pool,
- "ib_fmr(%s)",
- device->name);
+ pool->thread = kthread_run(ib_fmr_cleanup_thread,
+ pool,
+ "ib_fmr(%s)",
+ device->name);
if (IS_ERR(pool->thread)) {
printk(KERN_WARNING PFX "couldn't start cleanup thread\n");
ret = PTR_ERR(pool->thread);
diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index 2f54e29dc7a6..4e3128ff73c1 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -55,9 +55,11 @@ static void __ib_umem_release(struct ib_device *dev, struct ib_umem *umem, int d
ib_dma_unmap_sg(dev, chunk->page_list,
chunk->nents, DMA_BIDIRECTIONAL);
for (i = 0; i < chunk->nents; ++i) {
+ struct page *page = sg_page(&chunk->page_list[i]);
+
if (umem->writable && dirty)
- set_page_dirty_lock(chunk->page_list[i].page);
- put_page(chunk->page_list[i].page);
+ set_page_dirty_lock(page);
+ put_page(page);
}
kfree(chunk);
@@ -164,13 +166,12 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
}
chunk->nents = min_t(int, ret, IB_UMEM_MAX_PAGE_CHUNK);
+ sg_init_table(chunk->page_list, chunk->nents);
for (i = 0; i < chunk->nents; ++i) {
if (vma_list &&
!is_vm_hugetlb_page(vma_list[i + off]))
umem->hugetlb = 0;
- chunk->page_list[i].page = page_list[i + off];
- chunk->page_list[i].offset = 0;
- chunk->page_list[i].length = PAGE_SIZE;
+ sg_set_page(&chunk->page_list[i], page_list[i + off], PAGE_SIZE, 0);
}
chunk->nmap = ib_dma_map_sg(context->device,
@@ -179,7 +180,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
DMA_BIDIRECTIONAL);
if (chunk->nmap <= 0) {
for (i = 0; i < chunk->nents; ++i)
- put_page(chunk->page_list[i].page);
+ put_page(sg_page(&chunk->page_list[i]));
kfree(chunk);
ret = -ENOMEM;
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 01d70084aebe..495c803fb11d 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -147,8 +147,12 @@ static struct ib_uobject *__idr_get_uobj(struct idr *idr, int id,
spin_lock(&ib_uverbs_idr_lock);
uobj = idr_find(idr, id);
- if (uobj)
- kref_get(&uobj->ref);
+ if (uobj) {
+ if (uobj->context == context)
+ kref_get(&uobj->ref);
+ else
+ uobj = NULL;
+ }
spin_unlock(&ib_uverbs_idr_lock);
return uobj;
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c
index f0c777589374..b5436ca92e68 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
@@ -1000,6 +1000,7 @@ static int iwch_query_device(struct ib_device *ibdev,
props->max_sge = dev->attr.max_sge_per_wr;
props->max_sge_rd = 1;
props->max_qp_rd_atom = dev->attr.max_rdma_reads_per_qp;
+ props->max_qp_init_rd_atom = dev->attr.max_rdma_reads_per_qp;
props->max_cq = dev->attr.max_cqs;
props->max_cqe = dev->attr.max_cqes_per_cq;
props->max_mr = dev->attr.max_mem_regs;
diff --git a/drivers/infiniband/hw/ehca/ehca_av.c b/drivers/infiniband/hw/ehca/ehca_av.c
index 97d108634c58..453eb995c1d4 100644
--- a/drivers/infiniband/hw/ehca/ehca_av.c
+++ b/drivers/infiniband/hw/ehca/ehca_av.c
@@ -50,6 +50,38 @@
static struct kmem_cache *av_cache;
+int ehca_calc_ipd(struct ehca_shca *shca, int port,
+ enum ib_rate path_rate, u32 *ipd)
+{
+ int path = ib_rate_to_mult(path_rate);
+ int link, ret;
+ struct ib_port_attr pa;
+
+ if (path_rate == IB_RATE_PORT_CURRENT) {
+ *ipd = 0;
+ return 0;
+ }
+
+ if (unlikely(path < 0)) {
+ ehca_err(&shca->ib_device, "Invalid static rate! path_rate=%x",
+ path_rate);
+ return -EINVAL;
+ }
+
+ ret = ehca_query_port(&shca->ib_device, port, &pa);
+ if (unlikely(ret < 0)) {
+ ehca_err(&shca->ib_device, "Failed to query port ret=%i", ret);
+ return ret;
+ }
+
+ link = ib_width_enum_to_int(pa.active_width) * pa.active_speed;
+
+ /* IPD = round((link / path) - 1) */
+ *ipd = ((link + (path >> 1)) / path) - 1;
+
+ return 0;
+}
+
struct ib_ah *ehca_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
{
int ret;
@@ -69,15 +101,13 @@ struct ib_ah *ehca_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
av->av.slid_path_bits = ah_attr->src_path_bits;
if (ehca_static_rate < 0) {
- int ah_mult = ib_rate_to_mult(ah_attr->static_rate);
- int ehca_mult =
- ib_rate_to_mult(shca->sport[ah_attr->port_num].rate );
-
- if (ah_mult >= ehca_mult)
- av->av.ipd = 0;
- else
- av->av.ipd = (ah_mult > 0) ?
- ((ehca_mult - 1) / ah_mult) : 0;
+ u32 ipd;
+ if (ehca_calc_ipd(shca, ah_attr->port_num,
+ ah_attr->static_rate, &ipd)) {
+ ret = -EINVAL;
+ goto create_ah_exit1;
+ }
+ av->av.ipd = ipd;
} else
av->av.ipd = ehca_static_rate;
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
index 0f7a55d35ea7..87f12d4312a7 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -95,7 +95,6 @@ struct ehca_sma_attr {
struct ehca_sport {
struct ib_cq *ibcq_aqp1;
struct ib_qp *ibqp_aqp1;
- enum ib_rate rate;
enum ib_port_state port_state;
struct ehca_sma_attr saved_attr;
};
@@ -107,7 +106,7 @@ struct ehca_sport {
struct ehca_shca {
struct ib_device ib_device;
- struct ibmebus_dev *ibmebus_dev;
+ struct of_device *ofdev;
u8 num_ports;
int hw_level;
struct list_head shca_list;
@@ -323,7 +322,6 @@ extern int ehca_static_rate;
extern int ehca_port_act_time;
extern int ehca_use_hp_mr;
extern int ehca_scaling_code;
-extern int ehca_mr_largepage;
struct ipzu_queue_resp {
u32 qe_size; /* queue entry size */
diff --git a/drivers/infiniband/hw/ehca/ehca_eq.c b/drivers/infiniband/hw/ehca/ehca_eq.c
index 1d41faa7a337..b4ac617a70e6 100644
--- a/drivers/infiniband/hw/ehca/ehca_eq.c
+++ b/drivers/infiniband/hw/ehca/ehca_eq.c
@@ -123,7 +123,7 @@ int ehca_create_eq(struct ehca_shca *shca,
/* register interrupt handlers and initialize work queues */
if (type == EHCA_EQ) {
- ret = ibmebus_request_irq(NULL, eq->ist, ehca_interrupt_eq,
+ ret = ibmebus_request_irq(eq->ist, ehca_interrupt_eq,
IRQF_DISABLED, "ehca_eq",
(void *)shca);
if (ret < 0)
@@ -131,7 +131,7 @@ int ehca_create_eq(struct ehca_shca *shca,
tasklet_init(&eq->interrupt_task, ehca_tasklet_eq, (long)shca);
} else if (type == EHCA_NEQ) {
- ret = ibmebus_request_irq(NULL, eq->ist, ehca_interrupt_neq,
+ ret = ibmebus_request_irq(eq->ist, ehca_interrupt_neq,
IRQF_DISABLED, "ehca_neq",
(void *)shca);
if (ret < 0)
@@ -171,7 +171,7 @@ int ehca_destroy_eq(struct ehca_shca *shca, struct ehca_eq *eq)
u64 h_ret;
spin_lock_irqsave(&eq->spinlock, flags);
- ibmebus_free_irq(NULL, eq->ist, (void *)shca);
+ ibmebus_free_irq(eq->ist, (void *)shca);
h_ret = hipz_h_destroy_eq(shca->ipz_hca_handle, eq);
diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c b/drivers/infiniband/hw/ehca/ehca_hca.c
index 4aa3ffa6a19f..5bd7b591987e 100644
--- a/drivers/infiniband/hw/ehca/ehca_hca.c
+++ b/drivers/infiniband/hw/ehca/ehca_hca.c
@@ -77,6 +77,7 @@ int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props)
}
memset(props, 0, sizeof(struct ib_device_attr));
+ props->page_size_cap = shca->hca_cap_mr_pgsize;
props->fw_ver = rblock->hw_ver;
props->max_mr_size = rblock->max_mr_size;
props->vendor_id = rblock->vendor_id >> 8;
@@ -150,7 +151,6 @@ int ehca_query_port(struct ib_device *ibdev,
}
memset(props, 0, sizeof(struct ib_port_attr));
- props->state = rblock->state;
switch (rblock->max_mtu) {
case 0x1:
@@ -187,11 +187,20 @@ int ehca_query_port(struct ib_device *ibdev,
props->subnet_timeout = rblock->subnet_timeout;
props->init_type_reply = rblock->init_type_reply;
- props->active_width = IB_WIDTH_12X;
- props->active_speed = 0x1;
-
- /* at the moment (logical) link state is always LINK_UP */
- props->phys_state = 0x5;
+ if (rblock->state && rblock->phys_width) {
+ props->phys_state = rblock->phys_pstate;
+ props->state = rblock->phys_state;
+ props->active_width = rblock->phys_width;
+ props->active_speed = rblock->phys_speed;
+ } else {
+ /* old firmware releases don't report physical
+ * port info, so use default values
+ */
+ props->phys_state = 5;
+ props->state = rblock->state;
+ props->active_width = IB_WIDTH_12X;
+ props->active_speed = 0x1;
+ }
query_port1:
ehca_free_fw_ctrlblock(rblock);
diff --git a/drivers/infiniband/hw/ehca/ehca_iverbs.h b/drivers/infiniband/hw/ehca/ehca_iverbs.h
index dce503bb7d6b..5485799cdc8d 100644
--- a/drivers/infiniband/hw/ehca/ehca_iverbs.h
+++ b/drivers/infiniband/hw/ehca/ehca_iverbs.h
@@ -189,6 +189,9 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma);
void ehca_poll_eqs(unsigned long data);
+int ehca_calc_ipd(struct ehca_shca *shca, int port,
+ enum ib_rate path_rate, u32 *ipd);
+
#ifdef CONFIG_PPC_64K_PAGES
void *ehca_alloc_fw_ctrlblock(gfp_t flags);
void ehca_free_fw_ctrlblock(void *ptr);
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
index 403467f66fe6..90d4334179bf 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -65,7 +65,7 @@ int ehca_port_act_time = 30;
int ehca_poll_all_eqs = 1;
int ehca_static_rate = -1;
int ehca_scaling_code = 0;
-int ehca_mr_largepage = 0;
+int ehca_mr_largepage = 1;
module_param_named(open_aqp1, ehca_open_aqp1, int, S_IRUGO);
module_param_named(debug_level, ehca_debug_level, int, S_IRUGO);
@@ -260,13 +260,20 @@ static struct cap_descr {
{ HCA_CAP_MINI_QP, "HCA_CAP_MINI_QP" },
};
-int ehca_sense_attributes(struct ehca_shca *shca)
+static int ehca_sense_attributes(struct ehca_shca *shca)
{
int i, ret = 0;
u64 h_ret;
struct hipz_query_hca *rblock;
struct hipz_query_port *port;
+ static const u32 pgsize_map[] = {
+ HCA_CAP_MR_PGSIZE_4K, 0x1000,
+ HCA_CAP_MR_PGSIZE_64K, 0x10000,
+ HCA_CAP_MR_PGSIZE_1M, 0x100000,
+ HCA_CAP_MR_PGSIZE_16M, 0x1000000,
+ };
+
rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
if (!rblock) {
ehca_gen_err("Cannot allocate rblock memory.");
@@ -320,17 +327,21 @@ int ehca_sense_attributes(struct ehca_shca *shca)
shca->hw_level = ehca_hw_level;
ehca_gen_dbg(" ... hardware level=%x", shca->hw_level);
- shca->sport[0].rate = IB_RATE_30_GBPS;
- shca->sport[1].rate = IB_RATE_30_GBPS;
-
shca->hca_cap = rblock->hca_cap_indicators;
ehca_gen_dbg(" ... HCA capabilities:");
for (i = 0; i < ARRAY_SIZE(hca_cap_descr); i++)
if (EHCA_BMASK_GET(hca_cap_descr[i].mask, shca->hca_cap))
ehca_gen_dbg(" %s", hca_cap_descr[i].descr);
- shca->hca_cap_mr_pgsize = rblock->memory_page_size_supported;
+ /* translate supported MR page sizes; always support 4K */
+ shca->hca_cap_mr_pgsize = EHCA_PAGESIZE;
+ if (ehca_mr_largepage) { /* support extra sizes only if enabled */
+ for (i = 0; i < ARRAY_SIZE(pgsize_map); i += 2)
+ if (rblock->memory_page_size_supported & pgsize_map[i])
+ shca->hca_cap_mr_pgsize |= pgsize_map[i + 1];
+ }
+ /* query max MTU from first port -- it's the same for all ports */
port = (struct hipz_query_port *)rblock;
h_ret = hipz_h_query_port(shca->ipz_hca_handle, 1, port);
if (h_ret != H_SUCCESS) {
@@ -404,7 +415,7 @@ int ehca_init_device(struct ehca_shca *shca)
shca->ib_device.node_type = RDMA_NODE_IB_CA;
shca->ib_device.phys_port_cnt = shca->num_ports;
shca->ib_device.num_comp_vectors = 1;
- shca->ib_device.dma_device = &shca->ibmebus_dev->ofdev.dev;
+ shca->ib_device.dma_device = &shca->ofdev->dev;
shca->ib_device.query_device = ehca_query_device;
shca->ib_device.query_port = ehca_query_port;
shca->ib_device.query_gid = ehca_query_gid;
@@ -579,12 +590,12 @@ static ssize_t ehca_show_##name(struct device *dev, \
\
rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL); \
if (!rblock) { \
- dev_err(dev, "Can't allocate rblock memory."); \
+ dev_err(dev, "Can't allocate rblock memory.\n"); \
return 0; \
} \
\
if (hipz_h_query_hca(shca->ipz_hca_handle, rblock) != H_SUCCESS) { \
- dev_err(dev, "Can't query device properties"); \
+ dev_err(dev, "Can't query device properties\n"); \
ehca_free_fw_ctrlblock(rblock); \
return 0; \
} \
@@ -658,7 +669,7 @@ static struct attribute_group ehca_dev_attr_grp = {
.attrs = ehca_dev_attrs
};
-static int __devinit ehca_probe(struct ibmebus_dev *dev,
+static int __devinit ehca_probe(struct of_device *dev,
const struct of_device_id *id)
{
struct ehca_shca *shca;
@@ -666,16 +677,16 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev,
struct ib_pd *ibpd;
int ret;
- handle = of_get_property(dev->ofdev.node, "ibm,hca-handle", NULL);
+ handle = of_get_property(dev->node, "ibm,hca-handle", NULL);
if (!handle) {
ehca_gen_err("Cannot get eHCA handle for adapter: %s.",
- dev->ofdev.node->full_name);
+ dev->node->full_name);
return -ENODEV;
}
if (!(*handle)) {
ehca_gen_err("Wrong eHCA handle for adapter: %s.",
- dev->ofdev.node->full_name);
+ dev->node->full_name);
return -ENODEV;
}
@@ -686,9 +697,9 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev,
}
mutex_init(&shca->modify_mutex);
- shca->ibmebus_dev = dev;
+ shca->ofdev = dev;
shca->ipz_hca_handle.handle = *handle;
- dev->ofdev.dev.driver_data = shca;
+ dev->dev.driver_data = shca;
ret = ehca_sense_attributes(shca);
if (ret < 0) {
@@ -764,7 +775,7 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev,
}
}
- ret = sysfs_create_group(&dev->ofdev.dev.kobj, &ehca_dev_attr_grp);
+ ret = sysfs_create_group(&dev->dev.kobj, &ehca_dev_attr_grp);
if (ret) /* only complain; we can live without attributes */
ehca_err(&shca->ib_device,
"Cannot create device attributes ret=%d", ret);
@@ -814,12 +825,12 @@ probe1:
return -EINVAL;
}
-static int __devexit ehca_remove(struct ibmebus_dev *dev)
+static int __devexit ehca_remove(struct of_device *dev)
{
- struct ehca_shca *shca = dev->ofdev.dev.driver_data;
+ struct ehca_shca *shca = dev->dev.driver_data;
int ret;
- sysfs_remove_group(&dev->ofdev.dev.kobj, &ehca_dev_attr_grp);
+ sysfs_remove_group(&dev->dev.kobj, &ehca_dev_attr_grp);
if (ehca_open_aqp1 == 1) {
int i;
@@ -870,11 +881,11 @@ static struct of_device_id ehca_device_table[] =
{},
};
-static struct ibmebus_driver ehca_driver = {
- .name = "ehca",
- .id_table = ehca_device_table,
- .probe = ehca_probe,
- .remove = ehca_remove,
+static struct of_platform_driver ehca_driver = {
+ .name = "ehca",
+ .match_table = ehca_device_table,
+ .probe = ehca_probe,
+ .remove = ehca_remove,
};
void ehca_poll_eqs(unsigned long data)
diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c b/drivers/infiniband/hw/ehca/ehca_mrmw.c
index da88738265ed..e239bbf54da1 100644
--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
@@ -72,24 +72,14 @@ enum ehca_mr_pgsize {
static u32 ehca_encode_hwpage_size(u32 pgsize)
{
- u32 idx = 0;
- pgsize >>= 12;
- /*
- * map mr page size into hw code:
- * 0, 1, 2, 3 for 4K, 64K, 1M, 64M
- */
- while (!(pgsize & 1)) {
- idx++;
- pgsize >>= 4;
- }
- return idx;
+ int log = ilog2(pgsize);
+ WARN_ON(log < 12 || log > 24 || log & 3);
+ return (log - 12) / 4;
}
static u64 ehca_get_max_hwpage_size(struct ehca_shca *shca)
{
- if (shca->hca_cap_mr_pgsize & HCA_CAP_MR_PGSIZE_16M)
- return EHCA_MR_PGSIZE16M;
- return EHCA_MR_PGSIZE4K;
+ return 1UL << ilog2(shca->hca_cap_mr_pgsize);
}
static struct ehca_mr *ehca_mr_new(void)
@@ -259,7 +249,7 @@ struct ib_mr *ehca_reg_phys_mr(struct ib_pd *pd,
pginfo.u.phy.num_phys_buf = num_phys_buf;
pginfo.u.phy.phys_buf_array = phys_buf_array;
pginfo.next_hwpage =
- ((u64)iova_start & ~(hw_pgsize - 1)) / hw_pgsize;
+ ((u64)iova_start & ~PAGE_MASK) / hw_pgsize;
ret = ehca_reg_mr(shca, e_mr, iova_start, size, mr_access_flags,
e_pd, &pginfo, &e_mr->ib.ib_mr.lkey,
@@ -296,7 +286,7 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
container_of(pd->device, struct ehca_shca, ib_device);
struct ehca_pd *e_pd = container_of(pd, struct ehca_pd, ib_pd);
struct ehca_mr_pginfo pginfo;
- int ret;
+ int ret, page_shift;
u32 num_kpages;
u32 num_hwpages;
u64 hwpage_size;
@@ -351,19 +341,20 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
/* determine number of MR pages */
num_kpages = NUM_CHUNKS((virt % PAGE_SIZE) + length, PAGE_SIZE);
/* select proper hw_pgsize */
- if (ehca_mr_largepage &&
- (shca->hca_cap_mr_pgsize & HCA_CAP_MR_PGSIZE_16M)) {
- int page_shift = PAGE_SHIFT;
- if (e_mr->umem->hugetlb) {
- /* determine page_shift, clamp between 4K and 16M */
- page_shift = (fls64(length - 1) + 3) & ~3;
- page_shift = min(max(page_shift, EHCA_MR_PGSHIFT4K),
- EHCA_MR_PGSHIFT16M);
- }
- hwpage_size = 1UL << page_shift;
- } else
- hwpage_size = EHCA_MR_PGSIZE4K; /* ehca1 only supports 4k */
- ehca_dbg(pd->device, "hwpage_size=%lx", hwpage_size);
+ page_shift = PAGE_SHIFT;
+ if (e_mr->umem->hugetlb) {
+ /* determine page_shift, clamp between 4K and 16M */
+ page_shift = (fls64(length - 1) + 3) & ~3;
+ page_shift = min(max(page_shift, EHCA_MR_PGSHIFT4K),
+ EHCA_MR_PGSHIFT16M);
+ }
+ hwpage_size = 1UL << page_shift;
+
+ /* now that we have the desired page size, shift until it's
+ * supported, too. 4K is always supported, so this terminates.
+ */
+ while (!(hwpage_size & shca->hca_cap_mr_pgsize))
+ hwpage_size >>= 4;
reg_user_mr_fallback:
num_hwpages = NUM_CHUNKS((virt % hwpage_size) + length, hwpage_size);
@@ -547,7 +538,7 @@ int ehca_rereg_phys_mr(struct ib_mr *mr,
pginfo.u.phy.num_phys_buf = num_phys_buf;
pginfo.u.phy.phys_buf_array = phys_buf_array;
pginfo.next_hwpage =
- ((u64)iova_start & ~(hw_pgsize - 1)) / hw_pgsize;
+ ((u64)iova_start & ~PAGE_MASK) / hw_pgsize;
}
if (mr_rereg_mask & IB_MR_REREG_ACCESS)
new_acl = mr_access_flags;
@@ -809,8 +800,9 @@ struct ib_fmr *ehca_alloc_fmr(struct ib_pd *pd,
ib_fmr = ERR_PTR(-EINVAL);
goto alloc_fmr_exit0;
}
- hw_pgsize = ehca_get_max_hwpage_size(shca);
- if ((1 << fmr_attr->page_shift) != hw_pgsize) {
+
+ hw_pgsize = 1 << fmr_attr->page_shift;
+ if (!(hw_pgsize & shca->hca_cap_mr_pgsize)) {
ehca_err(pd->device, "unsupported fmr_attr->page_shift=%x",
fmr_attr->page_shift);
ib_fmr = ERR_PTR(-EINVAL);
@@ -826,6 +818,7 @@ struct ib_fmr *ehca_alloc_fmr(struct ib_pd *pd,
/* register MR on HCA */
memset(&pginfo, 0, sizeof(pginfo));
+ pginfo.hwpage_size = hw_pgsize;
/*
* pginfo.num_hwpages==0, ie register_rpages() will not be called
* but deferred to map_phys_fmr()
@@ -1776,7 +1769,7 @@ static int ehca_set_pagebuf_user1(struct ehca_mr_pginfo *pginfo,
list_for_each_entry_continue(
chunk, (&(pginfo->u.usr.region->chunk_list)), list) {
for (i = pginfo->u.usr.next_nmap; i < chunk->nmap; ) {
- pgaddr = page_to_pfn(chunk->page_list[i].page)
+ pgaddr = page_to_pfn(sg_page(&chunk->page_list[i]))
<< PAGE_SHIFT ;
*kpage = phys_to_abs(pgaddr +
(pginfo->next_hwpage *
@@ -1832,7 +1825,7 @@ static int ehca_check_kpages_per_ate(struct scatterlist *page_list,
{
int t;
for (t = start_idx; t <= end_idx; t++) {
- u64 pgaddr = page_to_pfn(page_list[t].page) << PAGE_SHIFT;
+ u64 pgaddr = page_to_pfn(sg_page(&page_list[t])) << PAGE_SHIFT;
ehca_gen_dbg("chunk_page=%lx value=%016lx", pgaddr,
*(u64 *)abs_to_virt(phys_to_abs(pgaddr)));
if (pgaddr - PAGE_SIZE != *prev_pgaddr) {
@@ -1867,7 +1860,7 @@ static int ehca_set_pagebuf_user2(struct ehca_mr_pginfo *pginfo,
chunk, (&(pginfo->u.usr.region->chunk_list)), list) {
for (i = pginfo->u.usr.next_nmap; i < chunk->nmap; ) {
if (nr_kpages == kpages_per_hwpage) {
- pgaddr = ( page_to_pfn(chunk->page_list[i].page)
+ pgaddr = ( page_to_pfn(sg_page(&chunk->page_list[i]))
<< PAGE_SHIFT );
*kpage = phys_to_abs(pgaddr);
if ( !(*kpage) ) {
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
index e2bd62be11e7..2e3e6547cb78 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -451,7 +451,6 @@ static struct ehca_qp *internal_create_qp(
has_srq = 1;
parms.ext_type = EQPT_SRQBASE;
parms.srq_qpn = my_srq->real_qp_num;
- parms.srq_token = my_srq->token;
}
if (is_llqp && has_srq) {
@@ -583,6 +582,9 @@ static struct ehca_qp *internal_create_qp(
goto create_qp_exit1;
}
+ if (has_srq)
+ parms.srq_token = my_qp->token;
+
parms.servicetype = ibqptype2servicetype(qp_type);
if (parms.servicetype < 0) {
ret = -EINVAL;
@@ -1194,10 +1196,6 @@ static int internal_modify_qp(struct ib_qp *ibqp,
update_mask |= EHCA_BMASK_SET(MQPCB_MASK_QKEY, 1);
}
if (attr_mask & IB_QP_AV) {
- int ah_mult = ib_rate_to_mult(attr->ah_attr.static_rate);
- int ehca_mult = ib_rate_to_mult(shca->sport[my_qp->
- init_attr.port_num].rate);
-
mqpcb->dlid = attr->ah_attr.dlid;
update_mask |= EHCA_BMASK_SET(MQPCB_MASK_DLID, 1);
mqpcb->source_path_bits = attr->ah_attr.src_path_bits;
@@ -1205,11 +1203,12 @@ static int internal_modify_qp(struct ib_qp *ibqp,
mqpcb->service_level = attr->ah_attr.sl;
update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SERVICE_LEVEL, 1);
- if (ah_mult < ehca_mult)
- mqpcb->max_static_rate = (ah_mult > 0) ?
- ((ehca_mult - 1) / ah_mult) : 0;
- else
- mqpcb->max_static_rate = 0;
+ if (ehca_calc_ipd(shca, my_qp->init_attr.port_num,
+ attr->ah_attr.static_rate,
+ &mqpcb->max_static_rate)) {
+ ret = -EINVAL;
+ goto modify_qp_exit2;
+ }
update_mask |= EHCA_BMASK_SET(MQPCB_MASK_MAX_STATIC_RATE, 1);
/*
@@ -1278,10 +1277,6 @@ static int internal_modify_qp(struct ib_qp *ibqp,
(MQPCB_MASK_RDMA_ATOMIC_OUTST_DEST_QP, 1);
}
if (attr_mask & IB_QP_ALT_PATH) {
- int ah_mult = ib_rate_to_mult(attr->alt_ah_attr.static_rate);
- int ehca_mult = ib_rate_to_mult(
- shca->sport[my_qp->init_attr.port_num].rate);
-
if (attr->alt_port_num < 1
|| attr->alt_port_num > shca->num_ports) {
ret = -EINVAL;
@@ -1307,10 +1302,12 @@ static int internal_modify_qp(struct ib_qp *ibqp,
mqpcb->source_path_bits_al = attr->alt_ah_attr.src_path_bits;
mqpcb->service_level_al = attr->alt_ah_attr.sl;
- if (ah_mult > 0 && ah_mult < ehca_mult)
- mqpcb->max_static_rate_al = (ehca_mult - 1) / ah_mult;
- else
- mqpcb->max_static_rate_al = 0;
+ if (ehca_calc_ipd(shca, my_qp->init_attr.port_num,
+ attr->alt_ah_attr.static_rate,
+ &mqpcb->max_static_rate_al)) {
+ ret = -EINVAL;
+ goto modify_qp_exit2;
+ }
/* OpenIB doesn't support alternate retry counts - copy them */
mqpcb->retry_count_al = mqpcb->retry_count;
diff --git a/drivers/infiniband/hw/ehca/hipz_hw.h b/drivers/infiniband/hw/ehca/hipz_hw.h
index d9739e554515..485b8400359e 100644
--- a/drivers/infiniband/hw/ehca/hipz_hw.h
+++ b/drivers/infiniband/hw/ehca/hipz_hw.h
@@ -402,7 +402,11 @@ struct hipz_query_port {
u64 max_msg_sz;
u32 max_mtu;
u32 vl_cap;
- u8 reserved2[1900];
+ u32 phys_pstate;
+ u32 phys_state;
+ u32 phys_speed;
+ u32 phys_width;
+ u8 reserved2[1884];
u64 guid_entries[255];
} __attribute__ ((packed));
diff --git a/drivers/infiniband/hw/ipath/ipath_cq.c b/drivers/infiniband/hw/ipath/ipath_cq.c
index 645ed71fd797..08d8ae148cd0 100644
--- a/drivers/infiniband/hw/ipath/ipath_cq.c
+++ b/drivers/infiniband/hw/ipath/ipath_cq.c
@@ -404,7 +404,7 @@ int ipath_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata)
ret = ib_copy_to_udata(udata, &offset, sizeof(offset));
if (ret)
- goto bail;
+ goto bail_free;
}
spin_lock_irq(&cq->lock);
@@ -424,10 +424,8 @@ int ipath_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata)
else
n = head - tail;
if (unlikely((u32)cqe < n)) {
- spin_unlock_irq(&cq->lock);
- vfree(wc);
ret = -EOVERFLOW;
- goto bail;
+ goto bail_unlock;
}
for (n = 0; tail != head; n++) {
if (cq->ip)
@@ -459,7 +457,12 @@ int ipath_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata)
}
ret = 0;
+ goto bail;
+bail_unlock:
+ spin_unlock_irq(&cq->lock);
+bail_free:
+ vfree(wc);
bail:
return ret;
}
diff --git a/drivers/infiniband/hw/ipath/ipath_dma.c b/drivers/infiniband/hw/ipath/ipath_dma.c
index f87f003e3ef8..e90a0ea538a0 100644
--- a/drivers/infiniband/hw/ipath/ipath_dma.c
+++ b/drivers/infiniband/hw/ipath/ipath_dma.c
@@ -30,6 +30,7 @@
* SOFTWARE.
*/
+#include <linux/scatterlist.h>
#include <rdma/ib_verbs.h>
#include "ipath_verbs.h"
@@ -96,17 +97,18 @@ static void ipath_dma_unmap_page(struct ib_device *dev,
BUG_ON(!valid_dma_direction(direction));
}
-static int ipath_map_sg(struct ib_device *dev, struct scatterlist *sg, int nents,
- enum dma_data_direction direction)
+static int ipath_map_sg(struct ib_device *dev, struct scatterlist *sgl,
+ int nents, enum dma_data_direction direction)
{
+ struct scatterlist *sg;
u64 addr;
int i;
int ret = nents;
BUG_ON(!valid_dma_direction(direction));
- for (i = 0; i < nents; i++) {
- addr = (u64) page_address(sg[i].page);
+ for_each_sg(sgl, sg, nents, i) {
+ addr = (u64) page_address(sg_page(sg));
/* TODO: handle highmem pages */
if (!addr) {
ret = 0;
@@ -125,7 +127,7 @@ static void ipath_unmap_sg(struct ib_device *dev,
static u64 ipath_sg_dma_address(struct ib_device *dev, struct scatterlist *sg)
{
- u64 addr = (u64) page_address(sg->page);
+ u64 addr = (u64) page_address(sg_page(sg));
if (addr)
addr += sg->offset;
diff --git a/drivers/infiniband/hw/ipath/ipath_eeprom.c b/drivers/infiniband/hw/ipath/ipath_eeprom.c
index bcfa3ccb555f..e7c25dbbcdc9 100644
--- a/drivers/infiniband/hw/ipath/ipath_eeprom.c
+++ b/drivers/infiniband/hw/ipath/ipath_eeprom.c
@@ -538,7 +538,15 @@ static u8 flash_csum(struct ipath_flash *ifp, int adjust)
u8 *ip = (u8 *) ifp;
u8 csum = 0, len;
- for (len = 0; len < ifp->if_length; len++)
+ /*
+ * Limit length checksummed to max length of actual data.
+ * Checksum of erased eeprom will still be bad, but we avoid
+ * reading past the end of the buffer we were passed.
+ */
+ len = ifp->if_length;
+ if (len > sizeof(struct ipath_flash))
+ len = sizeof(struct ipath_flash);
+ while (len--)
csum += *ip++;
csum -= ifp->if_csum;
csum = ~csum;
diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c
index 6a5dd5cd773d..c61f9da2964a 100644
--- a/drivers/infiniband/hw/ipath/ipath_intr.c
+++ b/drivers/infiniband/hw/ipath/ipath_intr.c
@@ -453,7 +453,7 @@ skip_ibchange:
}
static void handle_supp_msgs(struct ipath_devdata *dd,
- unsigned supp_msgs, char msg[512])
+ unsigned supp_msgs, char *msg, int msgsz)
{
/*
* Print the message unless it's ibc status change only, which
@@ -461,9 +461,9 @@ static void handle_supp_msgs(struct ipath_devdata *dd,
*/
if (dd->ipath_lasterror & ~INFINIPATH_E_IBSTATUSCHANGED) {
int iserr;
- iserr = ipath_decode_err(msg, sizeof msg,
- dd->ipath_lasterror &
- ~INFINIPATH_E_IBSTATUSCHANGED);
+ iserr = ipath_decode_err(msg, msgsz,
+ dd->ipath_lasterror &
+ ~INFINIPATH_E_IBSTATUSCHANGED);
if (dd->ipath_lasterror &
~(INFINIPATH_E_RRCVEGRFULL |
INFINIPATH_E_RRCVHDRFULL | INFINIPATH_E_PKTERRS))
@@ -492,8 +492,8 @@ static void handle_supp_msgs(struct ipath_devdata *dd,
}
static unsigned handle_frequent_errors(struct ipath_devdata *dd,
- ipath_err_t errs, char msg[512],
- int *noprint)
+ ipath_err_t errs, char *msg,
+ int msgsz, int *noprint)
{
unsigned long nc;
static unsigned long nextmsg_time;
@@ -512,7 +512,7 @@ static unsigned handle_frequent_errors(struct ipath_devdata *dd,
nextmsg_time = nc + HZ * 3;
}
else if (supp_msgs) {
- handle_supp_msgs(dd, supp_msgs, msg);
+ handle_supp_msgs(dd, supp_msgs, msg, msgsz);
supp_msgs = 0;
nmsgs = 0;
}
@@ -525,14 +525,14 @@ static unsigned handle_frequent_errors(struct ipath_devdata *dd,
static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
{
- char msg[512];
+ char msg[128];
u64 ignore_this_time = 0;
int i, iserr = 0;
int chkerrpkts = 0, noprint = 0;
unsigned supp_msgs;
int log_idx;
- supp_msgs = handle_frequent_errors(dd, errs, msg, &noprint);
+ supp_msgs = handle_frequent_errors(dd, errs, msg, sizeof msg, &noprint);
/* don't report errors that are masked */
errs &= ~dd->ipath_maskederrs;
diff --git a/drivers/infiniband/hw/ipath/ipath_mr.c b/drivers/infiniband/hw/ipath/ipath_mr.c
index e442470a2375..db4ba92f79fc 100644
--- a/drivers/infiniband/hw/ipath/ipath_mr.c
+++ b/drivers/infiniband/hw/ipath/ipath_mr.c
@@ -225,7 +225,7 @@ struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
for (i = 0; i < chunk->nents; i++) {
void *vaddr;
- vaddr = page_address(chunk->page_list[i].page);
+ vaddr = page_address(sg_page(&chunk->page_list[i]));
if (!vaddr) {
ret = ERR_PTR(-EINVAL);
goto bail;
diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c
index 5c29b2bfea17..120a61b03bc4 100644
--- a/drivers/infiniband/hw/ipath/ipath_rc.c
+++ b/drivers/infiniband/hw/ipath/ipath_rc.c
@@ -959,8 +959,9 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode,
/* If this is a partial ACK, reset the retransmit timer. */
if (qp->s_last != qp->s_tail) {
spin_lock(&dev->pending_lock);
- list_add_tail(&qp->timerwait,
- &dev->pending[dev->pending_index]);
+ if (list_empty(&qp->timerwait))
+ list_add_tail(&qp->timerwait,
+ &dev->pending[dev->pending_index]);
spin_unlock(&dev->pending_lock);
/*
* If we get a partial ACK for a resent operation,
diff --git a/drivers/infiniband/hw/ipath/ipath_ruc.c b/drivers/infiniband/hw/ipath/ipath_ruc.c
index 4b6b7ee8e5c1..54c61a972de2 100644
--- a/drivers/infiniband/hw/ipath/ipath_ruc.c
+++ b/drivers/infiniband/hw/ipath/ipath_ruc.c
@@ -630,11 +630,8 @@ bail:;
void ipath_send_complete(struct ipath_qp *qp, struct ipath_swqe *wqe,
enum ib_wc_status status)
{
- u32 last = qp->s_last;
-
- if (++last == qp->s_size)
- last = 0;
- qp->s_last = last;
+ unsigned long flags;
+ u32 last;
/* See ch. 11.2.4.1 and 10.7.3.1 */
if (!(qp->s_flags & IPATH_S_SIGNAL_REQ_WR) ||
@@ -658,4 +655,11 @@ void ipath_send_complete(struct ipath_qp *qp, struct ipath_swqe *wqe,
wc.port_num = 0;
ipath_cq_enter(to_icq(qp->ibqp.send_cq), &wc, 0);
}
+
+ spin_lock_irqsave(&qp->s_lock, flags);
+ last = qp->s_last;
+ if (++last >= qp->s_size)
+ last = 0;
+ qp->s_last = last;
+ spin_unlock_irqrestore(&qp->s_lock, flags);
}
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 31a480e5b0d0..8cba9c532e64 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -63,6 +63,10 @@ struct mlx4_ib_sqp {
u8 header_buf[MLX4_IB_UD_HEADER_SIZE];
};
+enum {
+ MLX4_IB_MIN_SQ_STRIDE = 6
+};
+
static const __be32 mlx4_ib_opcode[] = {
[IB_WR_SEND] = __constant_cpu_to_be32(MLX4_OPCODE_SEND),
[IB_WR_SEND_WITH_IMM] = __constant_cpu_to_be32(MLX4_OPCODE_SEND_IMM),
@@ -285,9 +289,17 @@ static int set_kernel_sq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
return 0;
}
-static int set_user_sq_size(struct mlx4_ib_qp *qp,
+static int set_user_sq_size(struct mlx4_ib_dev *dev,
+ struct mlx4_ib_qp *qp,
struct mlx4_ib_create_qp *ucmd)
{
+ /* Sanity check SQ size before proceeding */
+ if ((1 << ucmd->log_sq_bb_count) > dev->dev->caps.max_wqes ||
+ ucmd->log_sq_stride >
+ ilog2(roundup_pow_of_two(dev->dev->caps.max_sq_desc_sz)) ||
+ ucmd->log_sq_stride < MLX4_IB_MIN_SQ_STRIDE)
+ return -EINVAL;
+
qp->sq.wqe_cnt = 1 << ucmd->log_sq_bb_count;
qp->sq.wqe_shift = ucmd->log_sq_stride;
@@ -330,7 +342,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
qp->sq_no_prefetch = ucmd.sq_no_prefetch;
- err = set_user_sq_size(qp, &ucmd);
+ err = set_user_sq_size(dev, qp, &ucmd);
if (err)
goto err;
@@ -1270,7 +1282,7 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
int size;
int i;
- spin_lock_irqsave(&qp->rq.lock, flags);
+ spin_lock_irqsave(&qp->sq.lock, flags);
ind = qp->sq.head;
@@ -1436,7 +1448,7 @@ out:
(qp->sq.wqe_cnt - 1));
}
- spin_unlock_irqrestore(&qp->rq.lock, flags);
+ spin_unlock_irqrestore(&qp->sq.lock, flags);
return err;
}
diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c
index be6e1e03bdab..6bd9f1393349 100644
--- a/drivers/infiniband/hw/mthca/mthca_cq.c
+++ b/drivers/infiniband/hw/mthca/mthca_cq.c
@@ -204,16 +204,11 @@ static void dump_cqe(struct mthca_dev *dev, void *cqe_ptr)
static inline void update_cons_index(struct mthca_dev *dev, struct mthca_cq *cq,
int incr)
{
- __be32 doorbell[2];
-
if (mthca_is_memfree(dev)) {
*cq->set_ci_db = cpu_to_be32(cq->cons_index);
wmb();
} else {
- doorbell[0] = cpu_to_be32(MTHCA_TAVOR_CQ_DB_INC_CI | cq->cqn);
- doorbell[1] = cpu_to_be32(incr - 1);
-
- mthca_write64(doorbell,
+ mthca_write64(MTHCA_TAVOR_CQ_DB_INC_CI | cq->cqn, incr - 1,
dev->kar + MTHCA_CQ_DOORBELL,
MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
/*
@@ -731,17 +726,12 @@ repoll:
int mthca_tavor_arm_cq(struct ib_cq *cq, enum ib_cq_notify_flags flags)
{
- __be32 doorbell[2];
+ u32 dbhi = ((flags & IB_CQ_SOLICITED_MASK) == IB_CQ_SOLICITED ?
+ MTHCA_TAVOR_CQ_DB_REQ_NOT_SOL :
+ MTHCA_TAVOR_CQ_DB_REQ_NOT) |
+ to_mcq(cq)->cqn;
- doorbell[0] = cpu_to_be32(((flags & IB_CQ_SOLICITED_MASK) ==
- IB_CQ_SOLICITED ?
- MTHCA_TAVOR_CQ_DB_REQ_NOT_SOL :
- MTHCA_TAVOR_CQ_DB_REQ_NOT) |
- to_mcq(cq)->cqn);
- doorbell[1] = (__force __be32) 0xffffffff;
-
- mthca_write64(doorbell,
- to_mdev(cq->device)->kar + MTHCA_CQ_DOORBELL,
+ mthca_write64(dbhi, 0xffffffff, to_mdev(cq->device)->kar + MTHCA_CQ_DOORBELL,
MTHCA_GET_DOORBELL_LOCK(&to_mdev(cq->device)->doorbell_lock));
return 0;
@@ -750,19 +740,16 @@ int mthca_tavor_arm_cq(struct ib_cq *cq, enum ib_cq_notify_flags flags)
int mthca_arbel_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags)
{
struct mthca_cq *cq = to_mcq(ibcq);
- __be32 doorbell[2];
- u32 sn;
- __be32 ci;
-
- sn = cq->arm_sn & 3;
- ci = cpu_to_be32(cq->cons_index);
+ __be32 db_rec[2];
+ u32 dbhi;
+ u32 sn = cq->arm_sn & 3;
- doorbell[0] = ci;
- doorbell[1] = cpu_to_be32((cq->cqn << 8) | (2 << 5) | (sn << 3) |
- ((flags & IB_CQ_SOLICITED_MASK) ==
- IB_CQ_SOLICITED ? 1 : 2));
+ db_rec[0] = cpu_to_be32(cq->cons_index);
+ db_rec[1] = cpu_to_be32((cq->cqn << 8) | (2 << 5) | (sn << 3) |
+ ((flags & IB_CQ_SOLICITED_MASK) ==
+ IB_CQ_SOLICITED ? 1 : 2));
- mthca_write_db_rec(doorbell, cq->arm_db);
+ mthca_write_db_rec(db_rec, cq->arm_db);
/*
* Make sure that the doorbell record in host memory is
@@ -770,14 +757,12 @@ int mthca_arbel_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags)
*/
wmb();
- doorbell[0] = cpu_to_be32((sn << 28) |
- ((flags & IB_CQ_SOLICITED_MASK) == IB_CQ_SOLICITED ?
- MTHCA_ARBEL_CQ_DB_REQ_NOT_SOL :
- MTHCA_ARBEL_CQ_DB_REQ_NOT) |
- cq->cqn);
- doorbell[1] = ci;
+ dbhi = (sn << 28) |
+ ((flags & IB_CQ_SOLICITED_MASK) == IB_CQ_SOLICITED ?
+ MTHCA_ARBEL_CQ_DB_REQ_NOT_SOL :
+ MTHCA_ARBEL_CQ_DB_REQ_NOT) | cq->cqn;
- mthca_write64(doorbell,
+ mthca_write64(dbhi, cq->cons_index,
to_mdev(ibcq->device)->kar + MTHCA_CQ_DOORBELL,
MTHCA_GET_DOORBELL_LOCK(&to_mdev(ibcq->device)->doorbell_lock));
diff --git a/drivers/infiniband/hw/mthca/mthca_doorbell.h b/drivers/infiniband/hw/mthca/mthca_doorbell.h
index dd9a44d170c9..b374dc395be1 100644
--- a/drivers/infiniband/hw/mthca/mthca_doorbell.h
+++ b/drivers/infiniband/hw/mthca/mthca_doorbell.h
@@ -58,10 +58,10 @@ static inline void mthca_write64_raw(__be64 val, void __iomem *dest)
__raw_writeq((__force u64) val, dest);
}
-static inline void mthca_write64(__be32 val[2], void __iomem *dest,
+static inline void mthca_write64(u32 hi, u32 lo, void __iomem *dest,
spinlock_t *doorbell_lock)
{
- __raw_writeq(*(u64 *) val, dest);
+ __raw_writeq((__force u64) cpu_to_be64((u64) hi << 32 | lo), dest);
}
static inline void mthca_write_db_rec(__be32 val[2], __be32 *db)
@@ -87,14 +87,17 @@ static inline void mthca_write64_raw(__be64 val, void __iomem *dest)
__raw_writel(((__force u32 *) &val)[1], dest + 4);
}
-static inline void mthca_write64(__be32 val[2], void __iomem *dest,
+static inline void mthca_write64(u32 hi, u32 lo, void __iomem *dest,
spinlock_t *doorbell_lock)
{
unsigned long flags;
+ hi = (__force u32) cpu_to_be32(hi);
+ lo = (__force u32) cpu_to_be32(lo);
+
spin_lock_irqsave(doorbell_lock, flags);
- __raw_writel((__force u32) val[0], dest);
- __raw_writel((__force u32) val[1], dest + 4);
+ __raw_writel(hi, dest);
+ __raw_writel(lo, dest + 4);
spin_unlock_irqrestore(doorbell_lock, flags);
}
diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c
index 8592b26dc4e1..b29de51b7f35 100644
--- a/drivers/infiniband/hw/mthca/mthca_eq.c
+++ b/drivers/infiniband/hw/mthca/mthca_eq.c
@@ -173,11 +173,6 @@ static inline u64 async_mask(struct mthca_dev *dev)
static inline void tavor_set_eq_ci(struct mthca_dev *dev, struct mthca_eq *eq, u32 ci)
{
- __be32 doorbell[2];
-
- doorbell[0] = cpu_to_be32(MTHCA_EQ_DB_SET_CI | eq->eqn);
- doorbell[1] = cpu_to_be32(ci & (eq->nent - 1));
-
/*
* This barrier makes sure that all updates to ownership bits
* done by set_eqe_hw() hit memory before the consumer index
@@ -187,7 +182,7 @@ static inline void tavor_set_eq_ci(struct mthca_dev *dev, struct mthca_eq *eq, u
* having set_eqe_hw() overwrite the owner field.
*/
wmb();
- mthca_write64(doorbell,
+ mthca_write64(MTHCA_EQ_DB_SET_CI | eq->eqn, ci & (eq->nent - 1),
dev->kar + MTHCA_EQ_DOORBELL,
MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
}
@@ -212,12 +207,7 @@ static inline void set_eq_ci(struct mthca_dev *dev, struct mthca_eq *eq, u32 ci)
static inline void tavor_eq_req_not(struct mthca_dev *dev, int eqn)
{
- __be32 doorbell[2];
-
- doorbell[0] = cpu_to_be32(MTHCA_EQ_DB_REQ_NOT | eqn);
- doorbell[1] = 0;
-
- mthca_write64(doorbell,
+ mthca_write64(MTHCA_EQ_DB_REQ_NOT | eqn, 0,
dev->kar + MTHCA_EQ_DOORBELL,
MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
}
@@ -230,12 +220,7 @@ static inline void arbel_eq_req_not(struct mthca_dev *dev, u32 eqn_mask)
static inline void disarm_cq(struct mthca_dev *dev, int eqn, int cqn)
{
if (!mthca_is_memfree(dev)) {
- __be32 doorbell[2];
-
- doorbell[0] = cpu_to_be32(MTHCA_EQ_DB_DISARM_CQ | eqn);
- doorbell[1] = cpu_to_be32(cqn);
-
- mthca_write64(doorbell,
+ mthca_write64(MTHCA_EQ_DB_DISARM_CQ | eqn, cqn,
dev->kar + MTHCA_EQ_DOORBELL,
MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
}
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c
index e61f3e626980..1f4d27d7c16d 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.c
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.c
@@ -71,7 +71,7 @@ static void mthca_free_icm_pages(struct mthca_dev *dev, struct mthca_icm_chunk *
PCI_DMA_BIDIRECTIONAL);
for (i = 0; i < chunk->npages; ++i)
- __free_pages(chunk->mem[i].page,
+ __free_pages(sg_page(&chunk->mem[i]),
get_order(chunk->mem[i].length));
}
@@ -81,7 +81,7 @@ static void mthca_free_icm_coherent(struct mthca_dev *dev, struct mthca_icm_chun
for (i = 0; i < chunk->npages; ++i) {
dma_free_coherent(&dev->pdev->dev, chunk->mem[i].length,
- lowmem_page_address(chunk->mem[i].page),
+ lowmem_page_address(sg_page(&chunk->mem[i])),
sg_dma_address(&chunk->mem[i]));
}
}
@@ -107,12 +107,13 @@ void mthca_free_icm(struct mthca_dev *dev, struct mthca_icm *icm, int coherent)
static int mthca_alloc_icm_pages(struct scatterlist *mem, int order, gfp_t gfp_mask)
{
- mem->page = alloc_pages(gfp_mask, order);
- if (!mem->page)
+ struct page *page;
+
+ page = alloc_pages(gfp_mask, order);
+ if (!page)
return -ENOMEM;
- mem->length = PAGE_SIZE << order;
- mem->offset = 0;
+ sg_set_page(mem, page, PAGE_SIZE << order, 0);
return 0;
}
@@ -157,6 +158,7 @@ struct mthca_icm *mthca_alloc_icm(struct mthca_dev *dev, int npages,
if (!chunk)
goto fail;
+ sg_init_table(chunk->mem, MTHCA_ICM_CHUNK_LEN);
chunk->npages = 0;
chunk->nsg = 0;
list_add_tail(&chunk->list, &icm->chunk_list);
@@ -304,7 +306,7 @@ void *mthca_table_find(struct mthca_icm_table *table, int obj, dma_addr_t *dma_h
* so if we found the page, dma_handle has already
* been assigned to. */
if (chunk->mem[i].length > offset) {
- page = chunk->mem[i].page;
+ page = sg_page(&chunk->mem[i]);
goto out;
}
offset -= chunk->mem[i].length;
@@ -445,6 +447,7 @@ static u64 mthca_uarc_virt(struct mthca_dev *dev, struct mthca_uar *uar, int pag
int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar,
struct mthca_user_db_table *db_tab, int index, u64 uaddr)
{
+ struct page *pages[1];
int ret = 0;
u8 status;
int i;
@@ -472,16 +475,16 @@ int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar,
}
ret = get_user_pages(current, current->mm, uaddr & PAGE_MASK, 1, 1, 0,
- &db_tab->page[i].mem.page, NULL);
+ pages, NULL);
if (ret < 0)
goto out;
- db_tab->page[i].mem.length = MTHCA_ICM_PAGE_SIZE;
- db_tab->page[i].mem.offset = uaddr & ~PAGE_MASK;
+ sg_set_page(&db_tab->page[i].mem, pages[0], MTHCA_ICM_PAGE_SIZE,
+ uaddr & ~PAGE_MASK);
ret = pci_map_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE);
if (ret < 0) {
- put_page(db_tab->page[i].mem.page);
+ put_page(pages[0]);
goto out;
}
@@ -491,7 +494,7 @@ int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar,
ret = -EINVAL;
if (ret) {
pci_unmap_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE);
- put_page(db_tab->page[i].mem.page);
+ put_page(sg_page(&db_tab->page[i].mem));
goto out;
}
@@ -557,7 +560,7 @@ void mthca_cleanup_user_db_tab(struct mthca_dev *dev, struct mthca_uar *uar,
if (db_tab->page[i].uvirt) {
mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, uar, i), 1, &status);
pci_unmap_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE);
- put_page(db_tab->page[i].mem.page);
+ put_page(sg_page(&db_tab->page[i].mem));
}
}
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index df01b2026a64..0e5461c65731 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -1799,15 +1799,11 @@ int mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
out:
if (likely(nreq)) {
- __be32 doorbell[2];
-
- doorbell[0] = cpu_to_be32(((qp->sq.next_ind << qp->sq.wqe_shift) +
- qp->send_wqe_offset) | f0 | op0);
- doorbell[1] = cpu_to_be32((qp->qpn << 8) | size0);
-
wmb();
- mthca_write64(doorbell,
+ mthca_write64(((qp->sq.next_ind << qp->sq.wqe_shift) +
+ qp->send_wqe_offset) | f0 | op0,
+ (qp->qpn << 8) | size0,
dev->kar + MTHCA_SEND_DOORBELL,
MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
/*
@@ -1829,7 +1825,6 @@ int mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
{
struct mthca_dev *dev = to_mdev(ibqp->device);
struct mthca_qp *qp = to_mqp(ibqp);
- __be32 doorbell[2];
unsigned long flags;
int err = 0;
int nreq;
@@ -1907,13 +1902,10 @@ int mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
if (unlikely(nreq == MTHCA_TAVOR_MAX_WQES_PER_RECV_DB)) {
nreq = 0;
- doorbell[0] = cpu_to_be32((qp->rq.next_ind << qp->rq.wqe_shift) | size0);
- doorbell[1] = cpu_to_be32(qp->qpn << 8);
-
wmb();
- mthca_write64(doorbell,
- dev->kar + MTHCA_RECEIVE_DOORBELL,
+ mthca_write64((qp->rq.next_ind << qp->rq.wqe_shift) | size0,
+ qp->qpn << 8, dev->kar + MTHCA_RECEIVE_DOORBELL,
MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
qp->rq.next_ind = ind;
@@ -1923,13 +1915,10 @@ int mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
out:
if (likely(nreq)) {
- doorbell[0] = cpu_to_be32((qp->rq.next_ind << qp->rq.wqe_shift) | size0);
- doorbell[1] = cpu_to_be32((qp->qpn << 8) | nreq);
-
wmb();
- mthca_write64(doorbell,
- dev->kar + MTHCA_RECEIVE_DOORBELL,
+ mthca_write64((qp->rq.next_ind << qp->rq.wqe_shift) | size0,
+ qp->qpn << 8 | nreq, dev->kar + MTHCA_RECEIVE_DOORBELL,
MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
}
@@ -1951,7 +1940,7 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
{
struct mthca_dev *dev = to_mdev(ibqp->device);
struct mthca_qp *qp = to_mqp(ibqp);
- __be32 doorbell[2];
+ u32 dbhi;
void *wqe;
void *prev_wqe;
unsigned long flags;
@@ -1981,10 +1970,8 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
if (unlikely(nreq == MTHCA_ARBEL_MAX_WQES_PER_SEND_DB)) {
nreq = 0;
- doorbell[0] = cpu_to_be32((MTHCA_ARBEL_MAX_WQES_PER_SEND_DB << 24) |
- ((qp->sq.head & 0xffff) << 8) |
- f0 | op0);
- doorbell[1] = cpu_to_be32((qp->qpn << 8) | size0);
+ dbhi = (MTHCA_ARBEL_MAX_WQES_PER_SEND_DB << 24) |
+ ((qp->sq.head & 0xffff) << 8) | f0 | op0;
qp->sq.head += MTHCA_ARBEL_MAX_WQES_PER_SEND_DB;
@@ -2000,7 +1987,8 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
* write MMIO send doorbell.
*/
wmb();
- mthca_write64(doorbell,
+
+ mthca_write64(dbhi, (qp->qpn << 8) | size0,
dev->kar + MTHCA_SEND_DOORBELL,
MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
}
@@ -2154,10 +2142,7 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
out:
if (likely(nreq)) {
- doorbell[0] = cpu_to_be32((nreq << 24) |
- ((qp->sq.head & 0xffff) << 8) |
- f0 | op0);
- doorbell[1] = cpu_to_be32((qp->qpn << 8) | size0);
+ dbhi = (nreq << 24) | ((qp->sq.head & 0xffff) << 8) | f0 | op0;
qp->sq.head += nreq;
@@ -2173,8 +2158,8 @@ out:
* write MMIO send doorbell.
*/
wmb();
- mthca_write64(doorbell,
- dev->kar + MTHCA_SEND_DOORBELL,
+
+ mthca_write64(dbhi, (qp->qpn << 8) | size0, dev->kar + MTHCA_SEND_DOORBELL,
MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
}
diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c
index 3f58c11a62b7..553d681f6813 100644
--- a/drivers/infiniband/hw/mthca/mthca_srq.c
+++ b/drivers/infiniband/hw/mthca/mthca_srq.c
@@ -491,7 +491,6 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
{
struct mthca_dev *dev = to_mdev(ibsrq->device);
struct mthca_srq *srq = to_msrq(ibsrq);
- __be32 doorbell[2];
unsigned long flags;
int err = 0;
int first_ind;
@@ -563,16 +562,13 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
if (unlikely(nreq == MTHCA_TAVOR_MAX_WQES_PER_RECV_DB)) {
nreq = 0;
- doorbell[0] = cpu_to_be32(first_ind << srq->wqe_shift);
- doorbell[1] = cpu_to_be32(srq->srqn << 8);
-
/*
* Make sure that descriptors are written
* before doorbell is rung.
*/
wmb();
- mthca_write64(doorbell,
+ mthca_write64(first_ind << srq->wqe_shift, srq->srqn << 8,
dev->kar + MTHCA_RECEIVE_DOORBELL,
MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
@@ -581,16 +577,13 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
}
if (likely(nreq)) {
- doorbell[0] = cpu_to_be32(first_ind << srq->wqe_shift);
- doorbell[1] = cpu_to_be32((srq->srqn << 8) | nreq);
-
/*
* Make sure that descriptors are written before
* doorbell is rung.
*/
wmb();
- mthca_write64(doorbell,
+ mthca_write64(first_ind << srq->wqe_shift, (srq->srqn << 8) | nreq,
dev->kar + MTHCA_RECEIVE_DOORBELL,
MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 6545fa798b12..eb7edab0e836 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -84,9 +84,8 @@ enum {
IPOIB_MCAST_RUN = 6,
IPOIB_STOP_REAPER = 7,
IPOIB_MCAST_STARTED = 8,
- IPOIB_FLAG_NETIF_STOPPED = 9,
- IPOIB_FLAG_ADMIN_CM = 10,
- IPOIB_FLAG_UMCAST = 11,
+ IPOIB_FLAG_ADMIN_CM = 9,
+ IPOIB_FLAG_UMCAST = 10,
IPOIB_MAX_BACKOFF_SECONDS = 16,
@@ -98,9 +97,9 @@ enum {
#define IPOIB_OP_RECV (1ul << 31)
#ifdef CONFIG_INFINIBAND_IPOIB_CM
-#define IPOIB_CM_OP_SRQ (1ul << 30)
+#define IPOIB_OP_CM (1ul << 30)
#else
-#define IPOIB_CM_OP_SRQ (0)
+#define IPOIB_OP_CM (0)
#endif
/* structs */
@@ -197,7 +196,6 @@ struct ipoib_cm_rx {
struct ipoib_cm_tx {
struct ib_cm_id *id;
- struct ib_cq *cq;
struct ib_qp *qp;
struct list_head list;
struct net_device *dev;
@@ -294,6 +292,7 @@ struct ipoib_dev_priv {
unsigned tx_tail;
struct ib_sge tx_sge;
struct ib_send_wr tx_wr;
+ unsigned tx_outstanding;
struct ib_wc ibwc[IPOIB_NUM_WC];
@@ -349,6 +348,7 @@ struct ipoib_neigh {
struct sk_buff_head queue;
struct neighbour *neighbour;
+ struct net_device *dev;
struct list_head list;
};
@@ -365,7 +365,8 @@ static inline struct ipoib_neigh **to_ipoib_neigh(struct neighbour *neigh)
INFINIBAND_ALEN, sizeof(void *));
}
-struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neigh);
+struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neigh,
+ struct net_device *dev);
void ipoib_neigh_free(struct net_device *dev, struct ipoib_neigh *neigh);
extern struct workqueue_struct *ipoib_workqueue;
@@ -502,6 +503,7 @@ void ipoib_cm_destroy_tx(struct ipoib_cm_tx *tx);
void ipoib_cm_skb_too_long(struct net_device* dev, struct sk_buff *skb,
unsigned int mtu);
void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc);
+void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ib_wc *wc);
#else
struct ipoib_cm_tx;
@@ -590,6 +592,9 @@ static inline void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *w
{
}
+static inline void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
+{
+}
#endif
#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index 0a0dcb8fdfd1..059cf92b60a5 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -60,7 +60,7 @@ static struct ib_qp_attr ipoib_cm_err_attr = {
.qp_state = IB_QPS_ERR
};
-#define IPOIB_CM_RX_DRAIN_WRID 0x7fffffff
+#define IPOIB_CM_RX_DRAIN_WRID 0xffffffff
static struct ib_send_wr ipoib_cm_rx_drain_wr = {
.wr_id = IPOIB_CM_RX_DRAIN_WRID,
@@ -87,7 +87,7 @@ static int ipoib_cm_post_receive(struct net_device *dev, int id)
struct ib_recv_wr *bad_wr;
int i, ret;
- priv->cm.rx_wr.wr_id = id | IPOIB_CM_OP_SRQ;
+ priv->cm.rx_wr.wr_id = id | IPOIB_OP_CM | IPOIB_OP_RECV;
for (i = 0; i < IPOIB_CM_RX_SG; ++i)
priv->cm.rx_sge[i].addr = priv->cm.srq_ring[id].mapping[i];
@@ -401,7 +401,7 @@ static void skb_put_frags(struct sk_buff *skb, unsigned int hdr_space,
void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
- unsigned int wr_id = wc->wr_id & ~IPOIB_CM_OP_SRQ;
+ unsigned int wr_id = wc->wr_id & ~(IPOIB_OP_CM | IPOIB_OP_RECV);
struct sk_buff *skb, *newskb;
struct ipoib_cm_rx *p;
unsigned long flags;
@@ -412,7 +412,7 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
wr_id, wc->status);
if (unlikely(wr_id >= ipoib_recvq_size)) {
- if (wr_id == (IPOIB_CM_RX_DRAIN_WRID & ~IPOIB_CM_OP_SRQ)) {
+ if (wr_id == (IPOIB_CM_RX_DRAIN_WRID & ~(IPOIB_OP_CM | IPOIB_OP_RECV))) {
spin_lock_irqsave(&priv->lock, flags);
list_splice_init(&priv->cm.rx_drain_list, &priv->cm.rx_reap_list);
ipoib_cm_start_rx_drain(priv);
@@ -434,7 +434,7 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
goto repost;
}
- if (!likely(wr_id & IPOIB_CM_RX_UPDATE_MASK)) {
+ if (unlikely(!(wr_id & IPOIB_CM_RX_UPDATE_MASK))) {
p = wc->qp->qp_context;
if (p && time_after_eq(jiffies, p->jiffies + IPOIB_CM_RX_UPDATE_TIME)) {
spin_lock_irqsave(&priv->lock, flags);
@@ -498,7 +498,7 @@ static inline int post_send(struct ipoib_dev_priv *priv,
priv->tx_sge.addr = addr;
priv->tx_sge.length = len;
- priv->tx_wr.wr_id = wr_id;
+ priv->tx_wr.wr_id = wr_id | IPOIB_OP_CM;
return ib_post_send(tx->qp, &priv->tx_wr, &bad_wr);
}
@@ -549,20 +549,19 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_
dev->trans_start = jiffies;
++tx->tx_head;
- if (tx->tx_head - tx->tx_tail == ipoib_sendq_size) {
+ if (++priv->tx_outstanding == ipoib_sendq_size) {
ipoib_dbg(priv, "TX ring 0x%x full, stopping kernel net queue\n",
tx->qp->qp_num);
netif_stop_queue(dev);
- set_bit(IPOIB_FLAG_NETIF_STOPPED, &tx->flags);
}
}
}
-static void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ipoib_cm_tx *tx,
- struct ib_wc *wc)
+void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
- unsigned int wr_id = wc->wr_id;
+ struct ipoib_cm_tx *tx = wc->qp->qp_context;
+ unsigned int wr_id = wc->wr_id & ~IPOIB_OP_CM;
struct ipoib_tx_buf *tx_req;
unsigned long flags;
@@ -587,11 +586,10 @@ static void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ipoib_cm_tx *tx
spin_lock_irqsave(&priv->tx_lock, flags);
++tx->tx_tail;
- if (unlikely(test_bit(IPOIB_FLAG_NETIF_STOPPED, &tx->flags)) &&
- tx->tx_head - tx->tx_tail <= ipoib_sendq_size >> 1) {
- clear_bit(IPOIB_FLAG_NETIF_STOPPED, &tx->flags);
+ if (unlikely(--priv->tx_outstanding == ipoib_sendq_size >> 1) &&
+ netif_queue_stopped(dev) &&
+ test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags))
netif_wake_queue(dev);
- }
if (wc->status != IB_WC_SUCCESS &&
wc->status != IB_WC_WR_FLUSH_ERR) {
@@ -614,11 +612,6 @@ static void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ipoib_cm_tx *tx
tx->neigh = NULL;
}
- /* queue would be re-started anyway when TX is destroyed,
- * but it makes sense to do it ASAP here. */
- if (test_and_clear_bit(IPOIB_FLAG_NETIF_STOPPED, &tx->flags))
- netif_wake_queue(dev);
-
if (test_and_clear_bit(IPOIB_FLAG_INITIALIZED, &tx->flags)) {
list_move(&tx->list, &priv->cm.reap_list);
queue_work(ipoib_workqueue, &priv->cm.reap_task);
@@ -632,19 +625,6 @@ static void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ipoib_cm_tx *tx
spin_unlock_irqrestore(&priv->tx_lock, flags);
}
-static void ipoib_cm_tx_completion(struct ib_cq *cq, void *tx_ptr)
-{
- struct ipoib_cm_tx *tx = tx_ptr;
- int n, i;
-
- ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);
- do {
- n = ib_poll_cq(cq, IPOIB_NUM_WC, tx->ibwc);
- for (i = 0; i < n; ++i)
- ipoib_cm_handle_tx_wc(tx->dev, tx, tx->ibwc + i);
- } while (n == IPOIB_NUM_WC);
-}
-
int ipoib_cm_dev_open(struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
@@ -807,17 +787,18 @@ static int ipoib_cm_rep_handler(struct ib_cm_id *cm_id, struct ib_cm_event *even
return 0;
}
-static struct ib_qp *ipoib_cm_create_tx_qp(struct net_device *dev, struct ib_cq *cq)
+static struct ib_qp *ipoib_cm_create_tx_qp(struct net_device *dev, struct ipoib_cm_tx *tx)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ib_qp_init_attr attr = {
- .send_cq = cq,
+ .send_cq = priv->cq,
.recv_cq = priv->cq,
.srq = priv->cm.srq,
.cap.max_send_wr = ipoib_sendq_size,
.cap.max_send_sge = 1,
.sq_sig_type = IB_SIGNAL_ALL_WR,
.qp_type = IB_QPT_RC,
+ .qp_context = tx
};
return ib_create_qp(priv->pd, &attr);
@@ -899,21 +880,7 @@ static int ipoib_cm_tx_init(struct ipoib_cm_tx *p, u32 qpn,
goto err_tx;
}
- p->cq = ib_create_cq(priv->ca, ipoib_cm_tx_completion, NULL, p,
- ipoib_sendq_size + 1, 0);
- if (IS_ERR(p->cq)) {
- ret = PTR_ERR(p->cq);
- ipoib_warn(priv, "failed to allocate tx cq: %d\n", ret);
- goto err_cq;
- }
-
- ret = ib_req_notify_cq(p->cq, IB_CQ_NEXT_COMP);
- if (ret) {
- ipoib_warn(priv, "failed to request completion notification: %d\n", ret);
- goto err_req_notify;
- }
-
- p->qp = ipoib_cm_create_tx_qp(p->dev, p->cq);
+ p->qp = ipoib_cm_create_tx_qp(p->dev, p);
if (IS_ERR(p->qp)) {
ret = PTR_ERR(p->qp);
ipoib_warn(priv, "failed to allocate tx qp: %d\n", ret);
@@ -950,12 +917,8 @@ err_modify:
err_id:
p->id = NULL;
ib_destroy_qp(p->qp);
-err_req_notify:
err_qp:
p->qp = NULL;
- ib_destroy_cq(p->cq);
-err_cq:
- p->cq = NULL;
err_tx:
return ret;
}
@@ -964,6 +927,8 @@ static void ipoib_cm_tx_destroy(struct ipoib_cm_tx *p)
{
struct ipoib_dev_priv *priv = netdev_priv(p->dev);
struct ipoib_tx_buf *tx_req;
+ unsigned long flags;
+ unsigned long begin;
ipoib_dbg(priv, "Destroy active connection 0x%x head 0x%x tail 0x%x\n",
p->qp ? p->qp->qp_num : 0, p->tx_head, p->tx_tail);
@@ -971,27 +936,40 @@ static void ipoib_cm_tx_destroy(struct ipoib_cm_tx *p)
if (p->id)
ib_destroy_cm_id(p->id);
- if (p->qp)
- ib_destroy_qp(p->qp);
-
- if (p->cq)
- ib_destroy_cq(p->cq);
-
- if (test_bit(IPOIB_FLAG_NETIF_STOPPED, &p->flags))
- netif_wake_queue(p->dev);
-
if (p->tx_ring) {
+ /* Wait for all sends to complete */
+ begin = jiffies;
while ((int) p->tx_tail - (int) p->tx_head < 0) {
- tx_req = &p->tx_ring[p->tx_tail & (ipoib_sendq_size - 1)];
- ib_dma_unmap_single(priv->ca, tx_req->mapping, tx_req->skb->len,
- DMA_TO_DEVICE);
- dev_kfree_skb_any(tx_req->skb);
- ++p->tx_tail;
+ if (time_after(jiffies, begin + 5 * HZ)) {
+ ipoib_warn(priv, "timing out; %d sends not completed\n",
+ p->tx_head - p->tx_tail);
+ goto timeout;
+ }
+
+ msleep(1);
}
+ }
- kfree(p->tx_ring);
+timeout:
+
+ while ((int) p->tx_tail - (int) p->tx_head < 0) {
+ tx_req = &p->tx_ring[p->tx_tail & (ipoib_sendq_size - 1)];
+ ib_dma_unmap_single(priv->ca, tx_req->mapping, tx_req->skb->len,
+ DMA_TO_DEVICE);
+ dev_kfree_skb_any(tx_req->skb);
+ ++p->tx_tail;
+ spin_lock_irqsave(&priv->tx_lock, flags);
+ if (unlikely(--priv->tx_outstanding == ipoib_sendq_size >> 1) &&
+ netif_queue_stopped(p->dev) &&
+ test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags))
+ netif_wake_queue(p->dev);
+ spin_unlock_irqrestore(&priv->tx_lock, flags);
}
+ if (p->qp)
+ ib_destroy_qp(p->qp);
+
+ kfree(p->tx_ring);
kfree(p);
}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 1a77e79f6b43..5063dd509ad2 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -267,11 +267,10 @@ static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
spin_lock_irqsave(&priv->tx_lock, flags);
++priv->tx_tail;
- if (unlikely(test_bit(IPOIB_FLAG_NETIF_STOPPED, &priv->flags)) &&
- priv->tx_head - priv->tx_tail <= ipoib_sendq_size >> 1) {
- clear_bit(IPOIB_FLAG_NETIF_STOPPED, &priv->flags);
+ if (unlikely(--priv->tx_outstanding == ipoib_sendq_size >> 1) &&
+ netif_queue_stopped(dev) &&
+ test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags))
netif_wake_queue(dev);
- }
spin_unlock_irqrestore(&priv->tx_lock, flags);
if (wc->status != IB_WC_SUCCESS &&
@@ -301,14 +300,18 @@ poll_more:
for (i = 0; i < n; i++) {
struct ib_wc *wc = priv->ibwc + i;
- if (wc->wr_id & IPOIB_CM_OP_SRQ) {
- ++done;
- ipoib_cm_handle_rx_wc(dev, wc);
- } else if (wc->wr_id & IPOIB_OP_RECV) {
+ if (wc->wr_id & IPOIB_OP_RECV) {
++done;
- ipoib_ib_handle_rx_wc(dev, wc);
- } else
- ipoib_ib_handle_tx_wc(dev, wc);
+ if (wc->wr_id & IPOIB_OP_CM)
+ ipoib_cm_handle_rx_wc(dev, wc);
+ else
+ ipoib_ib_handle_rx_wc(dev, wc);
+ } else {
+ if (wc->wr_id & IPOIB_OP_CM)
+ ipoib_cm_handle_tx_wc(dev, wc);
+ else
+ ipoib_ib_handle_tx_wc(dev, wc);
+ }
}
if (n != t)
@@ -401,10 +404,9 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
address->last_send = priv->tx_head;
++priv->tx_head;
- if (priv->tx_head - priv->tx_tail == ipoib_sendq_size) {
+ if (++priv->tx_outstanding == ipoib_sendq_size) {
ipoib_dbg(priv, "TX ring full, stopping kernel net queue\n");
netif_stop_queue(dev);
- set_bit(IPOIB_FLAG_NETIF_STOPPED, &priv->flags);
}
}
}
@@ -436,7 +438,8 @@ void ipoib_reap_ah(struct work_struct *work)
__ipoib_reap_ah(dev);
if (!test_bit(IPOIB_STOP_REAPER, &priv->flags))
- queue_delayed_work(ipoib_workqueue, &priv->ah_reap_task, HZ);
+ queue_delayed_work(ipoib_workqueue, &priv->ah_reap_task,
+ round_jiffies_relative(HZ));
}
int ipoib_ib_dev_open(struct net_device *dev)
@@ -472,7 +475,8 @@ int ipoib_ib_dev_open(struct net_device *dev)
}
clear_bit(IPOIB_STOP_REAPER, &priv->flags);
- queue_delayed_work(ipoib_workqueue, &priv->ah_reap_task, HZ);
+ queue_delayed_work(ipoib_workqueue, &priv->ah_reap_task,
+ round_jiffies_relative(HZ));
set_bit(IPOIB_FLAG_INITIALIZED, &priv->flags);
@@ -561,12 +565,17 @@ void ipoib_drain_cq(struct net_device *dev)
if (priv->ibwc[i].status == IB_WC_SUCCESS)
priv->ibwc[i].status = IB_WC_WR_FLUSH_ERR;
- if (priv->ibwc[i].wr_id & IPOIB_CM_OP_SRQ)
- ipoib_cm_handle_rx_wc(dev, priv->ibwc + i);
- else if (priv->ibwc[i].wr_id & IPOIB_OP_RECV)
- ipoib_ib_handle_rx_wc(dev, priv->ibwc + i);
- else
- ipoib_ib_handle_tx_wc(dev, priv->ibwc + i);
+ if (priv->ibwc[i].wr_id & IPOIB_OP_RECV) {
+ if (priv->ibwc[i].wr_id & IPOIB_OP_CM)
+ ipoib_cm_handle_rx_wc(dev, priv->ibwc + i);
+ else
+ ipoib_ib_handle_rx_wc(dev, priv->ibwc + i);
+ } else {
+ if (priv->ibwc[i].wr_id & IPOIB_OP_CM)
+ ipoib_cm_handle_tx_wc(dev, priv->ibwc + i);
+ else
+ ipoib_ib_handle_tx_wc(dev, priv->ibwc + i);
+ }
}
} while (n == IPOIB_NUM_WC);
}
@@ -612,6 +621,7 @@ int ipoib_ib_dev_stop(struct net_device *dev, int flush)
DMA_TO_DEVICE);
dev_kfree_skb_any(tx_req->skb);
++priv->tx_tail;
+ --priv->tx_outstanding;
}
for (i = 0; i < ipoib_recvq_size; ++i) {
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index e072f3c32ce6..a03a65ebcf0c 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -148,8 +148,6 @@ static int ipoib_stop(struct net_device *dev)
netif_stop_queue(dev);
- clear_bit(IPOIB_FLAG_NETIF_STOPPED, &priv->flags);
-
/*
* Now flush workqueue to make sure a scheduled task doesn't
* bring our internal state back up.
@@ -517,7 +515,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
struct ipoib_path *path;
struct ipoib_neigh *neigh;
- neigh = ipoib_neigh_alloc(skb->dst->neighbour);
+ neigh = ipoib_neigh_alloc(skb->dst->neighbour, skb->dev);
if (!neigh) {
++dev->stats.tx_dropped;
dev_kfree_skb_any(skb);
@@ -692,9 +690,10 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
goto out;
}
} else if (neigh->ah) {
- if (unlikely(memcmp(&neigh->dgid.raw,
+ if (unlikely((memcmp(&neigh->dgid.raw,
skb->dst->neighbour->ha + 4,
- sizeof(union ib_gid)))) {
+ sizeof(union ib_gid))) ||
+ (neigh->dev != dev))) {
spin_lock(&priv->lock);
/*
* It's safe to call ipoib_put_ah() inside
@@ -817,6 +816,13 @@ static void ipoib_neigh_cleanup(struct neighbour *n)
unsigned long flags;
struct ipoib_ah *ah = NULL;
+ neigh = *to_ipoib_neigh(n);
+ if (neigh) {
+ priv = netdev_priv(neigh->dev);
+ ipoib_dbg(priv, "neigh_destructor for bonding device: %s\n",
+ n->dev->name);
+ } else
+ return;
ipoib_dbg(priv,
"neigh_cleanup for %06x " IPOIB_GID_FMT "\n",
IPOIB_QPN(n->ha),
@@ -824,13 +830,10 @@ static void ipoib_neigh_cleanup(struct neighbour *n)
spin_lock_irqsave(&priv->lock, flags);
- neigh = *to_ipoib_neigh(n);
- if (neigh) {
- if (neigh->ah)
- ah = neigh->ah;
- list_del(&neigh->list);
- ipoib_neigh_free(n->dev, neigh);
- }
+ if (neigh->ah)
+ ah = neigh->ah;
+ list_del(&neigh->list);
+ ipoib_neigh_free(n->dev, neigh);
spin_unlock_irqrestore(&priv->lock, flags);
@@ -838,7 +841,8 @@ static void ipoib_neigh_cleanup(struct neighbour *n)
ipoib_put_ah(ah);
}
-struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neighbour)
+struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neighbour,
+ struct net_device *dev)
{
struct ipoib_neigh *neigh;
@@ -847,6 +851,7 @@ struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neighbour)
return NULL;
neigh->neighbour = neighbour;
+ neigh->dev = dev;
*to_ipoib_neigh(neighbour) = neigh;
skb_queue_head_init(&neigh->queue);
ipoib_cm_set(neigh, NULL);
@@ -895,7 +900,7 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port)
goto out_rx_ring_cleanup;
}
- /* priv->tx_head & tx_tail are already 0 */
+ /* priv->tx_head, tx_tail & tx_outstanding are already 0 */
if (ipoib_ib_dev_init(dev, ca, port))
goto out_tx_ring_cleanup;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index 827820ec66d1..9bcfc7ad6aa6 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -705,7 +705,8 @@ out:
if (skb->dst &&
skb->dst->neighbour &&
!*to_ipoib_neigh(skb->dst->neighbour)) {
- struct ipoib_neigh *neigh = ipoib_neigh_alloc(skb->dst->neighbour);
+ struct ipoib_neigh *neigh = ipoib_neigh_alloc(skb->dst->neighbour,
+ skb->dev);
if (neigh) {
kref_get(&mcast->ah->ref);
diff --git a/drivers/infiniband/ulp/iser/iser_memory.c b/drivers/infiniband/ulp/iser/iser_memory.c
index e05690e3592f..d68798061795 100644
--- a/drivers/infiniband/ulp/iser/iser_memory.c
+++ b/drivers/infiniband/ulp/iser/iser_memory.c
@@ -124,17 +124,19 @@ static int iser_start_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask,
if (cmd_dir == ISER_DIR_OUT) {
/* copy the unaligned sg the buffer which is used for RDMA */
- struct scatterlist *sg = (struct scatterlist *)data->buf;
+ struct scatterlist *sgl = (struct scatterlist *)data->buf;
+ struct scatterlist *sg;
int i;
char *p, *from;
- for (p = mem, i = 0; i < data->size; i++) {
- from = kmap_atomic(sg[i].page, KM_USER0);
+ p = mem;
+ for_each_sg(sgl, sg, data->size, i) {
+ from = kmap_atomic(sg_page(sg), KM_USER0);
memcpy(p,
- from + sg[i].offset,
- sg[i].length);
+ from + sg->offset,
+ sg->length);
kunmap_atomic(from, KM_USER0);
- p += sg[i].length;
+ p += sg->length;
}
}
@@ -176,7 +178,7 @@ void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask,
if (cmd_dir == ISER_DIR_IN) {
char *mem;
- struct scatterlist *sg;
+ struct scatterlist *sgl, *sg;
unsigned char *p, *to;
unsigned int sg_size;
int i;
@@ -184,16 +186,17 @@ void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask,
/* copy back read RDMA to unaligned sg */
mem = mem_copy->copy_buf;
- sg = (struct scatterlist *)iser_ctask->data[ISER_DIR_IN].buf;
+ sgl = (struct scatterlist *)iser_ctask->data[ISER_DIR_IN].buf;
sg_size = iser_ctask->data[ISER_DIR_IN].size;
- for (p = mem, i = 0; i < sg_size; i++){
- to = kmap_atomic(sg[i].page, KM_SOFTIRQ0);
- memcpy(to + sg[i].offset,
+ p = mem;
+ for_each_sg(sgl, sg, sg_size, i) {
+ to = kmap_atomic(sg_page(sg), KM_SOFTIRQ0);
+ memcpy(to + sg->offset,
p,
- sg[i].length);
+ sg->length);
kunmap_atomic(to, KM_SOFTIRQ0);
- p += sg[i].length;
+ p += sg->length;
}
}
@@ -224,7 +227,8 @@ static int iser_sg_to_page_vec(struct iser_data_buf *data,
struct iser_page_vec *page_vec,
struct ib_device *ibdev)
{
- struct scatterlist *sg = (struct scatterlist *)data->buf;
+ struct scatterlist *sgl = (struct scatterlist *)data->buf;
+ struct scatterlist *sg;
u64 first_addr, last_addr, page;
int end_aligned;
unsigned int cur_page = 0;
@@ -232,24 +236,25 @@ static int iser_sg_to_page_vec(struct iser_data_buf *data,
int i;
/* compute the offset of first element */
- page_vec->offset = (u64) sg[0].offset & ~MASK_4K;
+ page_vec->offset = (u64) sgl[0].offset & ~MASK_4K;
- for (i = 0; i < data->dma_nents; i++) {
- unsigned int dma_len = ib_sg_dma_len(ibdev, &sg[i]);
+ for_each_sg(sgl, sg, data->dma_nents, i) {
+ unsigned int dma_len = ib_sg_dma_len(ibdev, sg);
total_sz += dma_len;
- first_addr = ib_sg_dma_address(ibdev, &sg[i]);
+ first_addr = ib_sg_dma_address(ibdev, sg);
last_addr = first_addr + dma_len;
end_aligned = !(last_addr & ~MASK_4K);
/* continue to collect page fragments till aligned or SG ends */
while (!end_aligned && (i + 1 < data->dma_nents)) {
+ sg = sg_next(sg);
i++;
- dma_len = ib_sg_dma_len(ibdev, &sg[i]);
+ dma_len = ib_sg_dma_len(ibdev, sg);
total_sz += dma_len;
- last_addr = ib_sg_dma_address(ibdev, &sg[i]) + dma_len;
+ last_addr = ib_sg_dma_address(ibdev, sg) + dma_len;
end_aligned = !(last_addr & ~MASK_4K);
}
@@ -284,25 +289,26 @@ static int iser_sg_to_page_vec(struct iser_data_buf *data,
static unsigned int iser_data_buf_aligned_len(struct iser_data_buf *data,
struct ib_device *ibdev)
{
- struct scatterlist *sg;
+ struct scatterlist *sgl, *sg;
u64 end_addr, next_addr;
int i, cnt;
unsigned int ret_len = 0;
- sg = (struct scatterlist *)data->buf;
+ sgl = (struct scatterlist *)data->buf;
- for (cnt = 0, i = 0; i < data->dma_nents; i++, cnt++) {
+ cnt = 0;
+ for_each_sg(sgl, sg, data->dma_nents, i) {
/* iser_dbg("Checking sg iobuf [%d]: phys=0x%08lX "
"offset: %ld sz: %ld\n", i,
- (unsigned long)page_to_phys(sg[i].page),
- (unsigned long)sg[i].offset,
- (unsigned long)sg[i].length); */
- end_addr = ib_sg_dma_address(ibdev, &sg[i]) +
- ib_sg_dma_len(ibdev, &sg[i]);
+ (unsigned long)sg_phys(sg),
+ (unsigned long)sg->offset,
+ (unsigned long)sg->length); */
+ end_addr = ib_sg_dma_address(ibdev, sg) +
+ ib_sg_dma_len(ibdev, sg);
/* iser_dbg("Checking sg iobuf end address "
"0x%08lX\n", end_addr); */
if (i + 1 < data->dma_nents) {
- next_addr = ib_sg_dma_address(ibdev, &sg[i+1]);
+ next_addr = ib_sg_dma_address(ibdev, sg_next(sg));
/* are i, i+1 fragments of the same page? */
if (end_addr == next_addr)
continue;
@@ -322,15 +328,16 @@ static unsigned int iser_data_buf_aligned_len(struct iser_data_buf *data,
static void iser_data_buf_dump(struct iser_data_buf *data,
struct ib_device *ibdev)
{
- struct scatterlist *sg = (struct scatterlist *)data->buf;
+ struct scatterlist *sgl = (struct scatterlist *)data->buf;
+ struct scatterlist *sg;
int i;
- for (i = 0; i < data->dma_nents; i++)
+ for_each_sg(sgl, sg, data->dma_nents, i)
iser_err("sg[%d] dma_addr:0x%lX page:0x%p "
"off:0x%x sz:0x%x dma_len:0x%x\n",
- i, (unsigned long)ib_sg_dma_address(ibdev, &sg[i]),
- sg[i].page, sg[i].offset,
- sg[i].length, ib_sg_dma_len(ibdev, &sg[i]));
+ i, (unsigned long)ib_sg_dma_address(ibdev, sg),
+ sg_page(sg), sg->offset,
+ sg->length, ib_sg_dma_len(ibdev, sg));
}
static void iser_dump_page_vec(struct iser_page_vec *page_vec)
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
index 2d87357e2b2b..63512d906f02 100644
--- a/drivers/input/Kconfig
+++ b/drivers/input/Kconfig
@@ -114,28 +114,6 @@ config INPUT_JOYDEV
To compile this driver as a module, choose M here: the
module will be called joydev.
-config INPUT_TSDEV
- tristate "Touchscreen interface"
- ---help---
- Say Y here if you have an application that only can understand the
- Compaq touchscreen protocol for absolute pointer data. This is
- useful namely for embedded configurations.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called tsdev.
-
-config INPUT_TSDEV_SCREEN_X
- int "Horizontal screen resolution"
- depends on INPUT_TSDEV
- default "240"
-
-config INPUT_TSDEV_SCREEN_Y
- int "Vertical screen resolution"
- depends on INPUT_TSDEV
- default "320"
-
config INPUT_EVDEV
tristate "Event interface"
help
diff --git a/drivers/input/Makefile b/drivers/input/Makefile
index 15eb752697b3..99af903bd3ce 100644
--- a/drivers/input/Makefile
+++ b/drivers/input/Makefile
@@ -13,7 +13,6 @@ obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o
obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o
obj-$(CONFIG_INPUT_JOYDEV) += joydev.o
obj-$(CONFIG_INPUT_EVDEV) += evdev.o
-obj-$(CONFIG_INPUT_TSDEV) += tsdev.o
obj-$(CONFIG_INPUT_EVBUG) += evbug.o
obj-$(CONFIG_INPUT_KEYBOARD) += keyboard/
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index f1c3d6cebd58..e5b4e9bfbdc5 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -30,6 +30,8 @@ struct evdev {
wait_queue_head_t wait;
struct evdev_client *grab;
struct list_head client_list;
+ spinlock_t client_lock; /* protects client_list */
+ struct mutex mutex;
struct device dev;
};
@@ -37,39 +39,54 @@ struct evdev_client {
struct input_event buffer[EVDEV_BUFFER_SIZE];
int head;
int tail;
+ spinlock_t buffer_lock; /* protects access to buffer, head and tail */
struct fasync_struct *fasync;
struct evdev *evdev;
struct list_head node;
};
static struct evdev *evdev_table[EVDEV_MINORS];
+static DEFINE_MUTEX(evdev_table_mutex);
-static void evdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
+static void evdev_pass_event(struct evdev_client *client,
+ struct input_event *event)
+{
+ /*
+ * Interrupts are disabled, just acquire the lock
+ */
+ spin_lock(&client->buffer_lock);
+ client->buffer[client->head++] = *event;
+ client->head &= EVDEV_BUFFER_SIZE - 1;
+ spin_unlock(&client->buffer_lock);
+
+ kill_fasync(&client->fasync, SIGIO, POLL_IN);
+}
+
+/*
+ * Pass incoming event to all connected clients.
+ */
+static void evdev_event(struct input_handle *handle,
+ unsigned int type, unsigned int code, int value)
{
struct evdev *evdev = handle->private;
struct evdev_client *client;
+ struct input_event event;
- if (evdev->grab) {
- client = evdev->grab;
+ do_gettimeofday(&event.time);
+ event.type = type;
+ event.code = code;
+ event.value = value;
- do_gettimeofday(&client->buffer[client->head].time);
- client->buffer[client->head].type = type;
- client->buffer[client->head].code = code;
- client->buffer[client->head].value = value;
- client->head = (client->head + 1) & (EVDEV_BUFFER_SIZE - 1);
+ rcu_read_lock();
- kill_fasync(&client->fasync, SIGIO, POLL_IN);
- } else
- list_for_each_entry(client, &evdev->client_list, node) {
+ client = rcu_dereference(evdev->grab);
+ if (client)
+ evdev_pass_event(client, &event);
+ else
+ list_for_each_entry_rcu(client, &evdev->client_list, node)
+ evdev_pass_event(client, &event);
- do_gettimeofday(&client->buffer[client->head].time);
- client->buffer[client->head].type = type;
- client->buffer[client->head].code = code;
- client->buffer[client->head].value = value;
- client->head = (client->head + 1) & (EVDEV_BUFFER_SIZE - 1);
-
- kill_fasync(&client->fasync, SIGIO, POLL_IN);
- }
+ rcu_read_unlock();
wake_up_interruptible(&evdev->wait);
}
@@ -88,38 +105,140 @@ static int evdev_flush(struct file *file, fl_owner_t id)
{
struct evdev_client *client = file->private_data;
struct evdev *evdev = client->evdev;
+ int retval;
+
+ retval = mutex_lock_interruptible(&evdev->mutex);
+ if (retval)
+ return retval;
if (!evdev->exist)
- return -ENODEV;
+ retval = -ENODEV;
+ else
+ retval = input_flush_device(&evdev->handle, file);
- return input_flush_device(&evdev->handle, file);
+ mutex_unlock(&evdev->mutex);
+ return retval;
}
static void evdev_free(struct device *dev)
{
struct evdev *evdev = container_of(dev, struct evdev, dev);
- evdev_table[evdev->minor] = NULL;
kfree(evdev);
}
+/*
+ * Grabs an event device (along with underlying input device).
+ * This function is called with evdev->mutex taken.
+ */
+static int evdev_grab(struct evdev *evdev, struct evdev_client *client)
+{
+ int error;
+
+ if (evdev->grab)
+ return -EBUSY;
+
+ error = input_grab_device(&evdev->handle);
+ if (error)
+ return error;
+
+ rcu_assign_pointer(evdev->grab, client);
+ synchronize_rcu();
+
+ return 0;
+}
+
+static int evdev_ungrab(struct evdev *evdev, struct evdev_client *client)
+{
+ if (evdev->grab != client)
+ return -EINVAL;
+
+ rcu_assign_pointer(evdev->grab, NULL);
+ synchronize_rcu();
+ input_release_device(&evdev->handle);
+
+ return 0;
+}
+
+static void evdev_attach_client(struct evdev *evdev,
+ struct evdev_client *client)
+{
+ spin_lock(&evdev->client_lock);
+ list_add_tail_rcu(&client->node, &evdev->client_list);
+ spin_unlock(&evdev->client_lock);
+ synchronize_rcu();
+}
+
+static void evdev_detach_client(struct evdev *evdev,
+ struct evdev_client *client)
+{
+ spin_lock(&evdev->client_lock);
+ list_del_rcu(&client->node);
+ spin_unlock(&evdev->client_lock);
+ synchronize_rcu();
+}
+
+static int evdev_open_device(struct evdev *evdev)
+{
+ int retval;
+
+ retval = mutex_lock_interruptible(&evdev->mutex);
+ if (retval)
+ return retval;
+
+ if (!evdev->exist)
+ retval = -ENODEV;
+ else if (!evdev->open++) {
+ retval = input_open_device(&evdev->handle);
+ if (retval)
+ evdev->open--;
+ }
+
+ mutex_unlock(&evdev->mutex);
+ return retval;
+}
+
+static void evdev_close_device(struct evdev *evdev)
+{
+ mutex_lock(&evdev->mutex);
+
+ if (evdev->exist && !--evdev->open)
+ input_close_device(&evdev->handle);
+
+ mutex_unlock(&evdev->mutex);
+}
+
+/*
+ * Wake up users waiting for IO so they can disconnect from
+ * dead device.
+ */
+static void evdev_hangup(struct evdev *evdev)
+{
+ struct evdev_client *client;
+
+ spin_lock(&evdev->client_lock);
+ list_for_each_entry(client, &evdev->client_list, node)
+ kill_fasync(&client->fasync, SIGIO, POLL_HUP);
+ spin_unlock(&evdev->client_lock);
+
+ wake_up_interruptible(&evdev->wait);
+}
+
static int evdev_release(struct inode *inode, struct file *file)
{
struct evdev_client *client = file->private_data;
struct evdev *evdev = client->evdev;
- if (evdev->grab == client) {
- input_release_device(&evdev->handle);
- evdev->grab = NULL;
- }
+ mutex_lock(&evdev->mutex);
+ if (evdev->grab == client)
+ evdev_ungrab(evdev, client);
+ mutex_unlock(&evdev->mutex);
evdev_fasync(-1, file, 0);
- list_del(&client->node);
+ evdev_detach_client(evdev, client);
kfree(client);
- if (!--evdev->open && evdev->exist)
- input_close_device(&evdev->handle);
-
+ evdev_close_device(evdev);
put_device(&evdev->dev);
return 0;
@@ -127,41 +246,44 @@ static int evdev_release(struct inode *inode, struct file *file)
static int evdev_open(struct inode *inode, struct file *file)
{
- struct evdev_client *client;
struct evdev *evdev;
+ struct evdev_client *client;
int i = iminor(inode) - EVDEV_MINOR_BASE;
int error;
if (i >= EVDEV_MINORS)
return -ENODEV;
+ error = mutex_lock_interruptible(&evdev_table_mutex);
+ if (error)
+ return error;
evdev = evdev_table[i];
+ if (evdev)
+ get_device(&evdev->dev);
+ mutex_unlock(&evdev_table_mutex);
- if (!evdev || !evdev->exist)
+ if (!evdev)
return -ENODEV;
- get_device(&evdev->dev);
-
client = kzalloc(sizeof(struct evdev_client), GFP_KERNEL);
if (!client) {
error = -ENOMEM;
goto err_put_evdev;
}
+ spin_lock_init(&client->buffer_lock);
client->evdev = evdev;
- list_add_tail(&client->node, &evdev->client_list);
+ evdev_attach_client(evdev, client);
- if (!evdev->open++ && evdev->exist) {
- error = input_open_device(&evdev->handle);
- if (error)
- goto err_free_client;
- }
+ error = evdev_open_device(evdev);
+ if (error)
+ goto err_free_client;
file->private_data = client;
return 0;
err_free_client:
- list_del(&client->node);
+ evdev_detach_client(evdev, client);
kfree(client);
err_put_evdev:
put_device(&evdev->dev);
@@ -197,12 +319,14 @@ static inline size_t evdev_event_size(void)
sizeof(struct input_event_compat) : sizeof(struct input_event);
}
-static int evdev_event_from_user(const char __user *buffer, struct input_event *event)
+static int evdev_event_from_user(const char __user *buffer,
+ struct input_event *event)
{
if (COMPAT_TEST) {
struct input_event_compat compat_event;
- if (copy_from_user(&compat_event, buffer, sizeof(struct input_event_compat)))
+ if (copy_from_user(&compat_event, buffer,
+ sizeof(struct input_event_compat)))
return -EFAULT;
event->time.tv_sec = compat_event.time.tv_sec;
@@ -219,7 +343,8 @@ static int evdev_event_from_user(const char __user *buffer, struct input_event *
return 0;
}
-static int evdev_event_to_user(char __user *buffer, const struct input_event *event)
+static int evdev_event_to_user(char __user *buffer,
+ const struct input_event *event)
{
if (COMPAT_TEST) {
struct input_event_compat compat_event;
@@ -230,7 +355,8 @@ static int evdev_event_to_user(char __user *buffer, const struct input_event *ev
compat_event.code = event->code;
compat_event.value = event->value;
- if (copy_to_user(buffer, &compat_event, sizeof(struct input_event_compat)))
+ if (copy_to_user(buffer, &compat_event,
+ sizeof(struct input_event_compat)))
return -EFAULT;
} else {
@@ -248,7 +374,8 @@ static inline size_t evdev_event_size(void)
return sizeof(struct input_event);
}
-static int evdev_event_from_user(const char __user *buffer, struct input_event *event)
+static int evdev_event_from_user(const char __user *buffer,
+ struct input_event *event)
{
if (copy_from_user(event, buffer, sizeof(struct input_event)))
return -EFAULT;
@@ -256,7 +383,8 @@ static int evdev_event_from_user(const char __user *buffer, struct input_event *
return 0;
}
-static int evdev_event_to_user(char __user *buffer, const struct input_event *event)
+static int evdev_event_to_user(char __user *buffer,
+ const struct input_event *event)
{
if (copy_to_user(buffer, event, sizeof(struct input_event)))
return -EFAULT;
@@ -266,37 +394,71 @@ static int evdev_event_to_user(char __user *buffer, const struct input_event *ev
#endif /* CONFIG_COMPAT */
-static ssize_t evdev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
+static ssize_t evdev_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *ppos)
{
struct evdev_client *client = file->private_data;
struct evdev *evdev = client->evdev;
struct input_event event;
- int retval = 0;
+ int retval;
- if (!evdev->exist)
- return -ENODEV;
+ retval = mutex_lock_interruptible(&evdev->mutex);
+ if (retval)
+ return retval;
+
+ if (!evdev->exist) {
+ retval = -ENODEV;
+ goto out;
+ }
while (retval < count) {
- if (evdev_event_from_user(buffer + retval, &event))
- return -EFAULT;
- input_inject_event(&evdev->handle, event.type, event.code, event.value);
+ if (evdev_event_from_user(buffer + retval, &event)) {
+ retval = -EFAULT;
+ goto out;
+ }
+
+ input_inject_event(&evdev->handle,
+ event.type, event.code, event.value);
retval += evdev_event_size();
}
+ out:
+ mutex_unlock(&evdev->mutex);
return retval;
}
-static ssize_t evdev_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
+static int evdev_fetch_next_event(struct evdev_client *client,
+ struct input_event *event)
+{
+ int have_event;
+
+ spin_lock_irq(&client->buffer_lock);
+
+ have_event = client->head != client->tail;
+ if (have_event) {
+ *event = client->buffer[client->tail++];
+ client->tail &= EVDEV_BUFFER_SIZE - 1;
+ }
+
+ spin_unlock_irq(&client->buffer_lock);
+
+ return have_event;
+}
+
+static ssize_t evdev_read(struct file *file, char __user *buffer,
+ size_t count, loff_t *ppos)
{
struct evdev_client *client = file->private_data;
struct evdev *evdev = client->evdev;
+ struct input_event event;
int retval;
if (count < evdev_event_size())
return -EINVAL;
- if (client->head == client->tail && evdev->exist && (file->f_flags & O_NONBLOCK))
+ if (client->head == client->tail && evdev->exist &&
+ (file->f_flags & O_NONBLOCK))
return -EAGAIN;
retval = wait_event_interruptible(evdev->wait,
@@ -307,14 +469,12 @@ static ssize_t evdev_read(struct file *file, char __user *buffer, size_t count,
if (!evdev->exist)
return -ENODEV;
- while (client->head != client->tail && retval + evdev_event_size() <= count) {
-
- struct input_event *event = (struct input_event *) client->buffer + client->tail;
+ while (retval + evdev_event_size() <= count &&
+ evdev_fetch_next_event(client, &event)) {
- if (evdev_event_to_user(buffer + retval, event))
+ if (evdev_event_to_user(buffer + retval, &event))
return -EFAULT;
- client->tail = (client->tail + 1) & (EVDEV_BUFFER_SIZE - 1);
retval += evdev_event_size();
}
@@ -335,7 +495,7 @@ static unsigned int evdev_poll(struct file *file, poll_table *wait)
#ifdef CONFIG_COMPAT
#define BITS_PER_LONG_COMPAT (sizeof(compat_long_t) * 8)
-#define NBITS_COMPAT(x) ((((x) - 1) / BITS_PER_LONG_COMPAT) + 1)
+#define BITS_TO_LONGS_COMPAT(x) ((((x) - 1) / BITS_PER_LONG_COMPAT) + 1)
#ifdef __BIG_ENDIAN
static int bits_to_user(unsigned long *bits, unsigned int maxbit,
@@ -344,7 +504,7 @@ static int bits_to_user(unsigned long *bits, unsigned int maxbit,
int len, i;
if (compat) {
- len = NBITS_COMPAT(maxbit) * sizeof(compat_long_t);
+ len = BITS_TO_LONGS_COMPAT(maxbit) * sizeof(compat_long_t);
if (len > maxlen)
len = maxlen;
@@ -355,7 +515,7 @@ static int bits_to_user(unsigned long *bits, unsigned int maxbit,
sizeof(compat_long_t)))
return -EFAULT;
} else {
- len = NBITS(maxbit) * sizeof(long);
+ len = BITS_TO_LONGS(maxbit) * sizeof(long);
if (len > maxlen)
len = maxlen;
@@ -370,8 +530,8 @@ static int bits_to_user(unsigned long *bits, unsigned int maxbit,
unsigned int maxlen, void __user *p, int compat)
{
int len = compat ?
- NBITS_COMPAT(maxbit) * sizeof(compat_long_t) :
- NBITS(maxbit) * sizeof(long);
+ BITS_TO_LONGS_COMPAT(maxbit) * sizeof(compat_long_t) :
+ BITS_TO_LONGS(maxbit) * sizeof(long);
if (len > maxlen)
len = maxlen;
@@ -385,7 +545,7 @@ static int bits_to_user(unsigned long *bits, unsigned int maxbit,
static int bits_to_user(unsigned long *bits, unsigned int maxbit,
unsigned int maxlen, void __user *p, int compat)
{
- int len = NBITS(maxbit) * sizeof(long);
+ int len = BITS_TO_LONGS(maxbit) * sizeof(long);
if (len > maxlen)
len = maxlen;
@@ -409,8 +569,8 @@ static int str_to_user(const char *str, unsigned int maxlen, void __user *p)
return copy_to_user(p, str, len) ? -EFAULT : len;
}
-static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
- void __user *p, int compat_mode)
+static long evdev_do_ioctl(struct file *file, unsigned int cmd,
+ void __user *p, int compat_mode)
{
struct evdev_client *client = file->private_data;
struct evdev *evdev = client->evdev;
@@ -421,215 +581,289 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
int i, t, u, v;
int error;
- if (!evdev->exist)
- return -ENODEV;
-
switch (cmd) {
- case EVIOCGVERSION:
- return put_user(EV_VERSION, ip);
+ case EVIOCGVERSION:
+ return put_user(EV_VERSION, ip);
- case EVIOCGID:
- if (copy_to_user(p, &dev->id, sizeof(struct input_id)))
- return -EFAULT;
- return 0;
+ case EVIOCGID:
+ if (copy_to_user(p, &dev->id, sizeof(struct input_id)))
+ return -EFAULT;
+ return 0;
- case EVIOCGREP:
- if (!test_bit(EV_REP, dev->evbit))
- return -ENOSYS;
- if (put_user(dev->rep[REP_DELAY], ip))
- return -EFAULT;
- if (put_user(dev->rep[REP_PERIOD], ip + 1))
- return -EFAULT;
- return 0;
+ case EVIOCGREP:
+ if (!test_bit(EV_REP, dev->evbit))
+ return -ENOSYS;
+ if (put_user(dev->rep[REP_DELAY], ip))
+ return -EFAULT;
+ if (put_user(dev->rep[REP_PERIOD], ip + 1))
+ return -EFAULT;
+ return 0;
- case EVIOCSREP:
- if (!test_bit(EV_REP, dev->evbit))
- return -ENOSYS;
- if (get_user(u, ip))
- return -EFAULT;
- if (get_user(v, ip + 1))
- return -EFAULT;
+ case EVIOCSREP:
+ if (!test_bit(EV_REP, dev->evbit))
+ return -ENOSYS;
+ if (get_user(u, ip))
+ return -EFAULT;
+ if (get_user(v, ip + 1))
+ return -EFAULT;
- input_inject_event(&evdev->handle, EV_REP, REP_DELAY, u);
- input_inject_event(&evdev->handle, EV_REP, REP_PERIOD, v);
+ input_inject_event(&evdev->handle, EV_REP, REP_DELAY, u);
+ input_inject_event(&evdev->handle, EV_REP, REP_PERIOD, v);
- return 0;
+ return 0;
- case EVIOCGKEYCODE:
- if (get_user(t, ip))
- return -EFAULT;
+ case EVIOCGKEYCODE:
+ if (get_user(t, ip))
+ return -EFAULT;
- error = dev->getkeycode(dev, t, &v);
- if (error)
- return error;
+ error = dev->getkeycode(dev, t, &v);
+ if (error)
+ return error;
- if (put_user(v, ip + 1))
- return -EFAULT;
+ if (put_user(v, ip + 1))
+ return -EFAULT;
- return 0;
+ return 0;
- case EVIOCSKEYCODE:
- if (get_user(t, ip) || get_user(v, ip + 1))
- return -EFAULT;
+ case EVIOCSKEYCODE:
+ if (get_user(t, ip) || get_user(v, ip + 1))
+ return -EFAULT;
- return dev->setkeycode(dev, t, v);
+ return dev->setkeycode(dev, t, v);
- case EVIOCSFF:
- if (copy_from_user(&effect, p, sizeof(effect)))
- return -EFAULT;
+ case EVIOCSFF:
+ if (copy_from_user(&effect, p, sizeof(effect)))
+ return -EFAULT;
- error = input_ff_upload(dev, &effect, file);
+ error = input_ff_upload(dev, &effect, file);
- if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
- return -EFAULT;
+ if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
+ return -EFAULT;
- return error;
+ return error;
- case EVIOCRMFF:
- return input_ff_erase(dev, (int)(unsigned long) p, file);
+ case EVIOCRMFF:
+ return input_ff_erase(dev, (int)(unsigned long) p, file);
- case EVIOCGEFFECTS:
- i = test_bit(EV_FF, dev->evbit) ? dev->ff->max_effects : 0;
- if (put_user(i, ip))
- return -EFAULT;
- return 0;
-
- case EVIOCGRAB:
- if (p) {
- if (evdev->grab)
- return -EBUSY;
- if (input_grab_device(&evdev->handle))
- return -EBUSY;
- evdev->grab = client;
- return 0;
- } else {
- if (evdev->grab != client)
- return -EINVAL;
- input_release_device(&evdev->handle);
- evdev->grab = NULL;
- return 0;
- }
+ case EVIOCGEFFECTS:
+ i = test_bit(EV_FF, dev->evbit) ?
+ dev->ff->max_effects : 0;
+ if (put_user(i, ip))
+ return -EFAULT;
+ return 0;
+
+ case EVIOCGRAB:
+ if (p)
+ return evdev_grab(evdev, client);
+ else
+ return evdev_ungrab(evdev, client);
- default:
+ default:
- if (_IOC_TYPE(cmd) != 'E')
- return -EINVAL;
+ if (_IOC_TYPE(cmd) != 'E')
+ return -EINVAL;
- if (_IOC_DIR(cmd) == _IOC_READ) {
+ if (_IOC_DIR(cmd) == _IOC_READ) {
- if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) {
+ if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0))) {
- unsigned long *bits;
- int len;
+ unsigned long *bits;
+ int len;
- switch (_IOC_NR(cmd) & EV_MAX) {
- case 0: bits = dev->evbit; len = EV_MAX; break;
- case EV_KEY: bits = dev->keybit; len = KEY_MAX; break;
- case EV_REL: bits = dev->relbit; len = REL_MAX; break;
- case EV_ABS: bits = dev->absbit; len = ABS_MAX; break;
- case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break;
- case EV_LED: bits = dev->ledbit; len = LED_MAX; break;
- case EV_SND: bits = dev->sndbit; len = SND_MAX; break;
- case EV_FF: bits = dev->ffbit; len = FF_MAX; break;
- case EV_SW: bits = dev->swbit; len = SW_MAX; break;
- default: return -EINVAL;
- }
- return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode);
- }
+ switch (_IOC_NR(cmd) & EV_MAX) {
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0)))
- return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd),
- p, compat_mode);
+ case 0: bits = dev->evbit; len = EV_MAX; break;
+ case EV_KEY: bits = dev->keybit; len = KEY_MAX; break;
+ case EV_REL: bits = dev->relbit; len = REL_MAX; break;
+ case EV_ABS: bits = dev->absbit; len = ABS_MAX; break;
+ case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break;
+ case EV_LED: bits = dev->ledbit; len = LED_MAX; break;
+ case EV_SND: bits = dev->sndbit; len = SND_MAX; break;
+ case EV_FF: bits = dev->ffbit; len = FF_MAX; break;
+ case EV_SW: bits = dev->swbit; len = SW_MAX; break;
+ default: return -EINVAL;
+ }
+ return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode);
+ }
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0)))
- return bits_to_user(dev->led, LED_MAX, _IOC_SIZE(cmd),
- p, compat_mode);
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0)))
+ return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd),
+ p, compat_mode);
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0)))
- return bits_to_user(dev->snd, SND_MAX, _IOC_SIZE(cmd),
- p, compat_mode);
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0)))
+ return bits_to_user(dev->led, LED_MAX, _IOC_SIZE(cmd),
+ p, compat_mode);
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0)))
- return bits_to_user(dev->sw, SW_MAX, _IOC_SIZE(cmd),
- p, compat_mode);
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0)))
+ return bits_to_user(dev->snd, SND_MAX, _IOC_SIZE(cmd),
+ p, compat_mode);
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0)))
- return str_to_user(dev->name, _IOC_SIZE(cmd), p);
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0)))
+ return bits_to_user(dev->sw, SW_MAX, _IOC_SIZE(cmd),
+ p, compat_mode);
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0)))
- return str_to_user(dev->phys, _IOC_SIZE(cmd), p);
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0)))
+ return str_to_user(dev->name, _IOC_SIZE(cmd), p);
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0)))
- return str_to_user(dev->uniq, _IOC_SIZE(cmd), p);
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0)))
+ return str_to_user(dev->phys, _IOC_SIZE(cmd), p);
- if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0)))
+ return str_to_user(dev->uniq, _IOC_SIZE(cmd), p);
- t = _IOC_NR(cmd) & ABS_MAX;
+ if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
- abs.value = dev->abs[t];
- abs.minimum = dev->absmin[t];
- abs.maximum = dev->absmax[t];
- abs.fuzz = dev->absfuzz[t];
- abs.flat = dev->absflat[t];
+ t = _IOC_NR(cmd) & ABS_MAX;
- if (copy_to_user(p, &abs, sizeof(struct input_absinfo)))
- return -EFAULT;
+ abs.value = dev->abs[t];
+ abs.minimum = dev->absmin[t];
+ abs.maximum = dev->absmax[t];
+ abs.fuzz = dev->absfuzz[t];
+ abs.flat = dev->absflat[t];
- return 0;
- }
+ if (copy_to_user(p, &abs, sizeof(struct input_absinfo)))
+ return -EFAULT;
+ return 0;
}
- if (_IOC_DIR(cmd) == _IOC_WRITE) {
+ }
+
+ if (_IOC_DIR(cmd) == _IOC_WRITE) {
- if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) {
+ if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) {
- t = _IOC_NR(cmd) & ABS_MAX;
+ t = _IOC_NR(cmd) & ABS_MAX;
- if (copy_from_user(&abs, p, sizeof(struct input_absinfo)))
- return -EFAULT;
+ if (copy_from_user(&abs, p,
+ sizeof(struct input_absinfo)))
+ return -EFAULT;
- dev->abs[t] = abs.value;
- dev->absmin[t] = abs.minimum;
- dev->absmax[t] = abs.maximum;
- dev->absfuzz[t] = abs.fuzz;
- dev->absflat[t] = abs.flat;
+ /*
+ * Take event lock to ensure that we are not
+ * changing device parameters in the middle
+ * of event.
+ */
+ spin_lock_irq(&dev->event_lock);
- return 0;
- }
+ dev->abs[t] = abs.value;
+ dev->absmin[t] = abs.minimum;
+ dev->absmax[t] = abs.maximum;
+ dev->absfuzz[t] = abs.fuzz;
+ dev->absflat[t] = abs.flat;
+
+ spin_unlock_irq(&dev->event_lock);
+
+ return 0;
}
+ }
}
return -EINVAL;
}
+static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
+ void __user *p, int compat_mode)
+{
+ struct evdev_client *client = file->private_data;
+ struct evdev *evdev = client->evdev;
+ int retval;
+
+ retval = mutex_lock_interruptible(&evdev->mutex);
+ if (retval)
+ return retval;
+
+ if (!evdev->exist) {
+ retval = -ENODEV;
+ goto out;
+ }
+
+ retval = evdev_do_ioctl(file, cmd, p, compat_mode);
+
+ out:
+ mutex_unlock(&evdev->mutex);
+ return retval;
+}
+
static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
return evdev_ioctl_handler(file, cmd, (void __user *)arg, 0);
}
#ifdef CONFIG_COMPAT
-static long evdev_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
+static long evdev_ioctl_compat(struct file *file,
+ unsigned int cmd, unsigned long arg)
{
return evdev_ioctl_handler(file, cmd, compat_ptr(arg), 1);
}
#endif
static const struct file_operations evdev_fops = {
- .owner = THIS_MODULE,
- .read = evdev_read,
- .write = evdev_write,
- .poll = evdev_poll,
- .open = evdev_open,
- .release = evdev_release,
- .unlocked_ioctl = evdev_ioctl,
+ .owner = THIS_MODULE,
+ .read = evdev_read,
+ .write = evdev_write,
+ .poll = evdev_poll,
+ .open = evdev_open,
+ .release = evdev_release,
+ .unlocked_ioctl = evdev_ioctl,
#ifdef CONFIG_COMPAT
- .compat_ioctl = evdev_ioctl_compat,
+ .compat_ioctl = evdev_ioctl_compat,
#endif
- .fasync = evdev_fasync,
- .flush = evdev_flush
+ .fasync = evdev_fasync,
+ .flush = evdev_flush
};
+static int evdev_install_chrdev(struct evdev *evdev)
+{
+ /*
+ * No need to do any locking here as calls to connect and
+ * disconnect are serialized by the input core
+ */
+ evdev_table[evdev->minor] = evdev;
+ return 0;
+}
+
+static void evdev_remove_chrdev(struct evdev *evdev)
+{
+ /*
+ * Lock evdev table to prevent race with evdev_open()
+ */
+ mutex_lock(&evdev_table_mutex);
+ evdev_table[evdev->minor] = NULL;
+ mutex_unlock(&evdev_table_mutex);
+}
+
+/*
+ * Mark device non-existent. This disables writes, ioctls and
+ * prevents new users from opening the device. Already posted
+ * blocking reads will stay, however new ones will fail.
+ */
+static void evdev_mark_dead(struct evdev *evdev)
+{
+ mutex_lock(&evdev->mutex);
+ evdev->exist = 0;
+ mutex_unlock(&evdev->mutex);
+}
+
+static void evdev_cleanup(struct evdev *evdev)
+{
+ struct input_handle *handle = &evdev->handle;
+
+ evdev_mark_dead(evdev);
+ evdev_hangup(evdev);
+ evdev_remove_chrdev(evdev);
+
+ /* evdev is marked dead so no one else accesses evdev->open */
+ if (evdev->open) {
+ input_flush_device(handle, NULL);
+ input_close_device(handle);
+ }
+}
+
+/*
+ * Create new evdev device. Note that input core serializes calls
+ * to connect and disconnect so we don't need to lock evdev_table here.
+ */
static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
const struct input_device_id *id)
{
@@ -637,7 +871,10 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
int minor;
int error;
- for (minor = 0; minor < EVDEV_MINORS && evdev_table[minor]; minor++);
+ for (minor = 0; minor < EVDEV_MINORS; minor++)
+ if (!evdev_table[minor])
+ break;
+
if (minor == EVDEV_MINORS) {
printk(KERN_ERR "evdev: no more free evdev devices\n");
return -ENFILE;
@@ -648,38 +885,44 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
return -ENOMEM;
INIT_LIST_HEAD(&evdev->client_list);
+ spin_lock_init(&evdev->client_lock);
+ mutex_init(&evdev->mutex);
init_waitqueue_head(&evdev->wait);
+ snprintf(evdev->name, sizeof(evdev->name), "event%d", minor);
evdev->exist = 1;
evdev->minor = minor;
+
evdev->handle.dev = dev;
evdev->handle.name = evdev->name;
evdev->handle.handler = handler;
evdev->handle.private = evdev;
- snprintf(evdev->name, sizeof(evdev->name), "event%d", minor);
- snprintf(evdev->dev.bus_id, sizeof(evdev->dev.bus_id),
- "event%d", minor);
+ strlcpy(evdev->dev.bus_id, evdev->name, sizeof(evdev->dev.bus_id));
+ evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor);
evdev->dev.class = &input_class;
evdev->dev.parent = &dev->dev;
- evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor);
evdev->dev.release = evdev_free;
device_initialize(&evdev->dev);
- evdev_table[minor] = evdev;
-
- error = device_add(&evdev->dev);
+ error = input_register_handle(&evdev->handle);
if (error)
goto err_free_evdev;
- error = input_register_handle(&evdev->handle);
+ error = evdev_install_chrdev(evdev);
+ if (error)
+ goto err_unregister_handle;
+
+ error = device_add(&evdev->dev);
if (error)
- goto err_delete_evdev;
+ goto err_cleanup_evdev;
return 0;
- err_delete_evdev:
- device_del(&evdev->dev);
+ err_cleanup_evdev:
+ evdev_cleanup(evdev);
+ err_unregister_handle:
+ input_unregister_handle(&evdev->handle);
err_free_evdev:
put_device(&evdev->dev);
return error;
@@ -688,21 +931,10 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
static void evdev_disconnect(struct input_handle *handle)
{
struct evdev *evdev = handle->private;
- struct evdev_client *client;
- input_unregister_handle(handle);
device_del(&evdev->dev);
-
- evdev->exist = 0;
-
- if (evdev->open) {
- input_flush_device(handle, NULL);
- input_close_device(handle);
- list_for_each_entry(client, &evdev->client_list, node)
- kill_fasync(&client->fasync, SIGIO, POLL_HUP);
- wake_up_interruptible(&evdev->wait);
- }
-
+ evdev_cleanup(evdev);
+ input_unregister_handle(handle);
put_device(&evdev->dev);
}
@@ -714,13 +946,13 @@ static const struct input_device_id evdev_ids[] = {
MODULE_DEVICE_TABLE(input, evdev_ids);
static struct input_handler evdev_handler = {
- .event = evdev_event,
- .connect = evdev_connect,
- .disconnect = evdev_disconnect,
- .fops = &evdev_fops,
- .minor = EVDEV_MINOR_BASE,
- .name = "evdev",
- .id_table = evdev_ids,
+ .event = evdev_event,
+ .connect = evdev_connect,
+ .disconnect = evdev_disconnect,
+ .fops = &evdev_fops,
+ .minor = EVDEV_MINOR_BASE,
+ .name = "evdev",
+ .id_table = evdev_ids,
};
static int __init evdev_init(void)
diff --git a/drivers/input/fixp-arith.h b/drivers/input/fixp-arith.h
index ed3d2da0c485..3089d7382325 100644
--- a/drivers/input/fixp-arith.h
+++ b/drivers/input/fixp-arith.h
@@ -24,7 +24,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Should you need to contact me, the author, you can do so by
- * e-mail - mail your message to <deneux@ifrance.com>
+ * e-mail - mail your message to <johann.deneux@gmail.com>
*/
#include <linux/types.h>
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index 20896d5e5f0e..bfc6061f1554 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -136,7 +136,8 @@ static int gameport_measure_speed(struct gameport *gameport)
}
gameport_close(gameport);
- return (cpu_data[raw_smp_processor_id()].loops_per_jiffy * (unsigned long)HZ / (1000 / 50)) / (tx < 1 ? 1 : tx);
+ return (cpu_data(raw_smp_processor_id()).loops_per_jiffy *
+ (unsigned long)HZ / (1000 / 50)) / (tx < 1 ? 1 : tx);
#else
@@ -448,9 +449,8 @@ static int gameport_thread(void *nothing)
set_freezable();
do {
gameport_handle_event();
- wait_event_interruptible(gameport_wait,
+ wait_event_freezable(gameport_wait,
kthread_should_stop() || !list_empty(&gameport_event_list));
- try_to_freeze();
} while (!kthread_should_stop());
printk(KERN_DEBUG "gameport: kgameportd exiting\n");
diff --git a/drivers/input/input-polldev.c b/drivers/input/input-polldev.c
index b773d4c756a6..92b359894e81 100644
--- a/drivers/input/input-polldev.c
+++ b/drivers/input/input-polldev.c
@@ -70,6 +70,7 @@ static int input_open_polled_device(struct input_dev *input)
{
struct input_polled_dev *dev = input->private;
int error;
+ unsigned long ticks;
error = input_polldev_start_workqueue();
if (error)
@@ -78,8 +79,10 @@ static int input_open_polled_device(struct input_dev *input)
if (dev->flush)
dev->flush(dev);
- queue_delayed_work(polldev_wq, &dev->work,
- msecs_to_jiffies(dev->poll_interval));
+ ticks = msecs_to_jiffies(dev->poll_interval);
+ if (ticks >= HZ)
+ ticks = round_jiffies(ticks);
+ queue_delayed_work(polldev_wq, &dev->work, ticks);
return 0;
}
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 5dc361c954e2..307c7b5c2b33 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -17,10 +17,10 @@
#include <linux/major.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
-#include <linux/interrupt.h>
#include <linux/poll.h>
#include <linux/device.h>
#include <linux/mutex.h>
+#include <linux/rcupdate.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_DESCRIPTION("Input core");
@@ -31,167 +31,245 @@ MODULE_LICENSE("GPL");
static LIST_HEAD(input_dev_list);
static LIST_HEAD(input_handler_list);
+/*
+ * input_mutex protects access to both input_dev_list and input_handler_list.
+ * This also causes input_[un]register_device and input_[un]register_handler
+ * be mutually exclusive which simplifies locking in drivers implementing
+ * input handlers.
+ */
+static DEFINE_MUTEX(input_mutex);
+
static struct input_handler *input_table[8];
-/**
- * input_event() - report new input event
- * @dev: device that generated the event
- * @type: type of the event
- * @code: event code
- * @value: value of the event
- *
- * This function should be used by drivers implementing various input devices
- * See also input_inject_event()
- */
-void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+static inline int is_event_supported(unsigned int code,
+ unsigned long *bm, unsigned int max)
{
- struct input_handle *handle;
+ return code <= max && test_bit(code, bm);
+}
- if (type > EV_MAX || !test_bit(type, dev->evbit))
- return;
+static int input_defuzz_abs_event(int value, int old_val, int fuzz)
+{
+ if (fuzz) {
+ if (value > old_val - fuzz / 2 && value < old_val + fuzz / 2)
+ return old_val;
- add_input_randomness(type, code, value);
+ if (value > old_val - fuzz && value < old_val + fuzz)
+ return (old_val * 3 + value) / 4;
- switch (type) {
-
- case EV_SYN:
- switch (code) {
- case SYN_CONFIG:
- if (dev->event)
- dev->event(dev, type, code, value);
- break;
-
- case SYN_REPORT:
- if (dev->sync)
- return;
- dev->sync = 1;
- break;
- }
- break;
+ if (value > old_val - fuzz * 2 && value < old_val + fuzz * 2)
+ return (old_val + value) / 2;
+ }
- case EV_KEY:
+ return value;
+}
- if (code > KEY_MAX || !test_bit(code, dev->keybit) || !!test_bit(code, dev->key) == value)
- return;
+/*
+ * Pass event through all open handles. This function is called with
+ * dev->event_lock held and interrupts disabled.
+ */
+static void input_pass_event(struct input_dev *dev,
+ unsigned int type, unsigned int code, int value)
+{
+ struct input_handle *handle;
- if (value == 2)
- break;
+ rcu_read_lock();
- change_bit(code, dev->key);
+ handle = rcu_dereference(dev->grab);
+ if (handle)
+ handle->handler->event(handle, type, code, value);
+ else
+ list_for_each_entry_rcu(handle, &dev->h_list, d_node)
+ if (handle->open)
+ handle->handler->event(handle,
+ type, code, value);
+ rcu_read_unlock();
+}
- if (test_bit(EV_REP, dev->evbit) && dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] && dev->timer.data && value) {
- dev->repeat_key = code;
- mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]));
- }
+/*
+ * Generate software autorepeat event. Note that we take
+ * dev->event_lock here to avoid racing with input_event
+ * which may cause keys get "stuck".
+ */
+static void input_repeat_key(unsigned long data)
+{
+ struct input_dev *dev = (void *) data;
+ unsigned long flags;
- break;
+ spin_lock_irqsave(&dev->event_lock, flags);
- case EV_SW:
+ if (test_bit(dev->repeat_key, dev->key) &&
+ is_event_supported(dev->repeat_key, dev->keybit, KEY_MAX)) {
- if (code > SW_MAX || !test_bit(code, dev->swbit) || !!test_bit(code, dev->sw) == value)
- return;
+ input_pass_event(dev, EV_KEY, dev->repeat_key, 2);
- change_bit(code, dev->sw);
+ if (dev->sync) {
+ /*
+ * Only send SYN_REPORT if we are not in a middle
+ * of driver parsing a new hardware packet.
+ * Otherwise assume that the driver will send
+ * SYN_REPORT once it's done.
+ */
+ input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
+ }
- break;
+ if (dev->rep[REP_PERIOD])
+ mod_timer(&dev->timer, jiffies +
+ msecs_to_jiffies(dev->rep[REP_PERIOD]));
+ }
- case EV_ABS:
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+}
- if (code > ABS_MAX || !test_bit(code, dev->absbit))
- return;
+static void input_start_autorepeat(struct input_dev *dev, int code)
+{
+ if (test_bit(EV_REP, dev->evbit) &&
+ dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] &&
+ dev->timer.data) {
+ dev->repeat_key = code;
+ mod_timer(&dev->timer,
+ jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]));
+ }
+}
- if (dev->absfuzz[code]) {
- if ((value > dev->abs[code] - (dev->absfuzz[code] >> 1)) &&
- (value < dev->abs[code] + (dev->absfuzz[code] >> 1)))
- return;
+#define INPUT_IGNORE_EVENT 0
+#define INPUT_PASS_TO_HANDLERS 1
+#define INPUT_PASS_TO_DEVICE 2
+#define INPUT_PASS_TO_ALL (INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE)
- if ((value > dev->abs[code] - dev->absfuzz[code]) &&
- (value < dev->abs[code] + dev->absfuzz[code]))
- value = (dev->abs[code] * 3 + value) >> 2;
+static void input_handle_event(struct input_dev *dev,
+ unsigned int type, unsigned int code, int value)
+{
+ int disposition = INPUT_IGNORE_EVENT;
- if ((value > dev->abs[code] - (dev->absfuzz[code] << 1)) &&
- (value < dev->abs[code] + (dev->absfuzz[code] << 1)))
- value = (dev->abs[code] + value) >> 1;
- }
+ switch (type) {
- if (dev->abs[code] == value)
- return;
+ case EV_SYN:
+ switch (code) {
+ case SYN_CONFIG:
+ disposition = INPUT_PASS_TO_ALL;
+ break;
- dev->abs[code] = value;
+ case SYN_REPORT:
+ if (!dev->sync) {
+ dev->sync = 1;
+ disposition = INPUT_PASS_TO_HANDLERS;
+ }
break;
+ }
+ break;
- case EV_REL:
+ case EV_KEY:
+ if (is_event_supported(code, dev->keybit, KEY_MAX) &&
+ !!test_bit(code, dev->key) != value) {
- if (code > REL_MAX || !test_bit(code, dev->relbit) || (value == 0))
- return;
+ if (value != 2) {
+ __change_bit(code, dev->key);
+ if (value)
+ input_start_autorepeat(dev, code);
+ }
- break;
+ disposition = INPUT_PASS_TO_HANDLERS;
+ }
+ break;
- case EV_MSC:
+ case EV_SW:
+ if (is_event_supported(code, dev->swbit, SW_MAX) &&
+ !!test_bit(code, dev->sw) != value) {
- if (code > MSC_MAX || !test_bit(code, dev->mscbit))
- return;
+ __change_bit(code, dev->sw);
+ disposition = INPUT_PASS_TO_HANDLERS;
+ }
+ break;
- if (dev->event)
- dev->event(dev, type, code, value);
+ case EV_ABS:
+ if (is_event_supported(code, dev->absbit, ABS_MAX)) {
- break;
+ value = input_defuzz_abs_event(value,
+ dev->abs[code], dev->absfuzz[code]);
+
+ if (dev->abs[code] != value) {
+ dev->abs[code] = value;
+ disposition = INPUT_PASS_TO_HANDLERS;
+ }
+ }
+ break;
- case EV_LED:
+ case EV_REL:
+ if (is_event_supported(code, dev->relbit, REL_MAX) && value)
+ disposition = INPUT_PASS_TO_HANDLERS;
- if (code > LED_MAX || !test_bit(code, dev->ledbit) || !!test_bit(code, dev->led) == value)
- return;
+ break;
- change_bit(code, dev->led);
+ case EV_MSC:
+ if (is_event_supported(code, dev->mscbit, MSC_MAX))
+ disposition = INPUT_PASS_TO_ALL;
- if (dev->event)
- dev->event(dev, type, code, value);
+ break;
- break;
+ case EV_LED:
+ if (is_event_supported(code, dev->ledbit, LED_MAX) &&
+ !!test_bit(code, dev->led) != value) {
- case EV_SND:
+ __change_bit(code, dev->led);
+ disposition = INPUT_PASS_TO_ALL;
+ }
+ break;
- if (code > SND_MAX || !test_bit(code, dev->sndbit))
- return;
+ case EV_SND:
+ if (is_event_supported(code, dev->sndbit, SND_MAX)) {
if (!!test_bit(code, dev->snd) != !!value)
- change_bit(code, dev->snd);
+ __change_bit(code, dev->snd);
+ disposition = INPUT_PASS_TO_ALL;
+ }
+ break;
- if (dev->event)
- dev->event(dev, type, code, value);
+ case EV_REP:
+ if (code <= REP_MAX && value >= 0 && dev->rep[code] != value) {
+ dev->rep[code] = value;
+ disposition = INPUT_PASS_TO_ALL;
+ }
+ break;
- break;
+ case EV_FF:
+ if (value >= 0)
+ disposition = INPUT_PASS_TO_ALL;
+ break;
+ }
- case EV_REP:
+ if (type != EV_SYN)
+ dev->sync = 0;
- if (code > REP_MAX || value < 0 || dev->rep[code] == value)
- return;
+ if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event)
+ dev->event(dev, type, code, value);
- dev->rep[code] = value;
- if (dev->event)
- dev->event(dev, type, code, value);
+ if (disposition & INPUT_PASS_TO_HANDLERS)
+ input_pass_event(dev, type, code, value);
+}
- break;
+/**
+ * input_event() - report new input event
+ * @dev: device that generated the event
+ * @type: type of the event
+ * @code: event code
+ * @value: value of the event
+ *
+ * This function should be used by drivers implementing various input
+ * devices. See also input_inject_event().
+ */
- case EV_FF:
+void input_event(struct input_dev *dev,
+ unsigned int type, unsigned int code, int value)
+{
+ unsigned long flags;
- if (value < 0)
- return;
+ if (is_event_supported(type, dev->evbit, EV_MAX)) {
- if (dev->event)
- dev->event(dev, type, code, value);
- break;
+ spin_lock_irqsave(&dev->event_lock, flags);
+ add_input_randomness(type, code, value);
+ input_handle_event(dev, type, code, value);
+ spin_unlock_irqrestore(&dev->event_lock, flags);
}
-
- if (type != EV_SYN)
- dev->sync = 0;
-
- if (dev->grab)
- dev->grab->handler->event(dev->grab, type, code, value);
- else
- list_for_each_entry(handle, &dev->h_list, d_node)
- if (handle->open)
- handle->handler->event(handle, type, code, value);
}
EXPORT_SYMBOL(input_event);
@@ -202,102 +280,228 @@ EXPORT_SYMBOL(input_event);
* @code: event code
* @value: value of the event
*
- * Similar to input_event() but will ignore event if device is "grabbed" and handle
- * injecting event is not the one that owns the device.
+ * Similar to input_event() but will ignore event if device is
+ * "grabbed" and handle injecting event is not the one that owns
+ * the device.
*/
-void input_inject_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
-{
- if (!handle->dev->grab || handle->dev->grab == handle)
- input_event(handle->dev, type, code, value);
-}
-EXPORT_SYMBOL(input_inject_event);
-
-static void input_repeat_key(unsigned long data)
+void input_inject_event(struct input_handle *handle,
+ unsigned int type, unsigned int code, int value)
{
- struct input_dev *dev = (void *) data;
+ struct input_dev *dev = handle->dev;
+ struct input_handle *grab;
+ unsigned long flags;
- if (!test_bit(dev->repeat_key, dev->key))
- return;
+ if (is_event_supported(type, dev->evbit, EV_MAX)) {
+ spin_lock_irqsave(&dev->event_lock, flags);
- input_event(dev, EV_KEY, dev->repeat_key, 2);
- input_sync(dev);
+ rcu_read_lock();
+ grab = rcu_dereference(dev->grab);
+ if (!grab || grab == handle)
+ input_handle_event(dev, type, code, value);
+ rcu_read_unlock();
- if (dev->rep[REP_PERIOD])
- mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep[REP_PERIOD]));
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+ }
}
+EXPORT_SYMBOL(input_inject_event);
+/**
+ * input_grab_device - grabs device for exclusive use
+ * @handle: input handle that wants to own the device
+ *
+ * When a device is grabbed by an input handle all events generated by
+ * the device are delivered only to this handle. Also events injected
+ * by other input handles are ignored while device is grabbed.
+ */
int input_grab_device(struct input_handle *handle)
{
- if (handle->dev->grab)
- return -EBUSY;
+ struct input_dev *dev = handle->dev;
+ int retval;
- handle->dev->grab = handle;
- return 0;
+ retval = mutex_lock_interruptible(&dev->mutex);
+ if (retval)
+ return retval;
+
+ if (dev->grab) {
+ retval = -EBUSY;
+ goto out;
+ }
+
+ rcu_assign_pointer(dev->grab, handle);
+ synchronize_rcu();
+
+ out:
+ mutex_unlock(&dev->mutex);
+ return retval;
}
EXPORT_SYMBOL(input_grab_device);
-void input_release_device(struct input_handle *handle)
+static void __input_release_device(struct input_handle *handle)
{
struct input_dev *dev = handle->dev;
if (dev->grab == handle) {
- dev->grab = NULL;
+ rcu_assign_pointer(dev->grab, NULL);
+ /* Make sure input_pass_event() notices that grab is gone */
+ synchronize_rcu();
list_for_each_entry(handle, &dev->h_list, d_node)
- if (handle->handler->start)
+ if (handle->open && handle->handler->start)
handle->handler->start(handle);
}
}
+
+/**
+ * input_release_device - release previously grabbed device
+ * @handle: input handle that owns the device
+ *
+ * Releases previously grabbed device so that other input handles can
+ * start receiving input events. Upon release all handlers attached
+ * to the device have their start() method called so they have a change
+ * to synchronize device state with the rest of the system.
+ */
+void input_release_device(struct input_handle *handle)
+{
+ struct input_dev *dev = handle->dev;
+
+ mutex_lock(&dev->mutex);
+ __input_release_device(handle);
+ mutex_unlock(&dev->mutex);
+}
EXPORT_SYMBOL(input_release_device);
+/**
+ * input_open_device - open input device
+ * @handle: handle through which device is being accessed
+ *
+ * This function should be called by input handlers when they
+ * want to start receive events from given input device.
+ */
int input_open_device(struct input_handle *handle)
{
struct input_dev *dev = handle->dev;
- int err;
+ int retval;
- err = mutex_lock_interruptible(&dev->mutex);
- if (err)
- return err;
+ retval = mutex_lock_interruptible(&dev->mutex);
+ if (retval)
+ return retval;
+
+ if (dev->going_away) {
+ retval = -ENODEV;
+ goto out;
+ }
handle->open++;
if (!dev->users++ && dev->open)
- err = dev->open(dev);
-
- if (err)
- handle->open--;
+ retval = dev->open(dev);
+
+ if (retval) {
+ dev->users--;
+ if (!--handle->open) {
+ /*
+ * Make sure we are not delivering any more events
+ * through this handle
+ */
+ synchronize_rcu();
+ }
+ }
+ out:
mutex_unlock(&dev->mutex);
-
- return err;
+ return retval;
}
EXPORT_SYMBOL(input_open_device);
-int input_flush_device(struct input_handle* handle, struct file* file)
+int input_flush_device(struct input_handle *handle, struct file *file)
{
- if (handle->dev->flush)
- return handle->dev->flush(handle->dev, file);
+ struct input_dev *dev = handle->dev;
+ int retval;
- return 0;
+ retval = mutex_lock_interruptible(&dev->mutex);
+ if (retval)
+ return retval;
+
+ if (dev->flush)
+ retval = dev->flush(dev, file);
+
+ mutex_unlock(&dev->mutex);
+ return retval;
}
EXPORT_SYMBOL(input_flush_device);
+/**
+ * input_close_device - close input device
+ * @handle: handle through which device is being accessed
+ *
+ * This function should be called by input handlers when they
+ * want to stop receive events from given input device.
+ */
void input_close_device(struct input_handle *handle)
{
struct input_dev *dev = handle->dev;
- input_release_device(handle);
-
mutex_lock(&dev->mutex);
+ __input_release_device(handle);
+
if (!--dev->users && dev->close)
dev->close(dev);
- handle->open--;
+
+ if (!--handle->open) {
+ /*
+ * synchronize_rcu() makes sure that input_pass_event()
+ * completed and that no more input events are delivered
+ * through this handle
+ */
+ synchronize_rcu();
+ }
mutex_unlock(&dev->mutex);
}
EXPORT_SYMBOL(input_close_device);
+/*
+ * Prepare device for unregistering
+ */
+static void input_disconnect_device(struct input_dev *dev)
+{
+ struct input_handle *handle;
+ int code;
+
+ /*
+ * Mark device as going away. Note that we take dev->mutex here
+ * not to protect access to dev->going_away but rather to ensure
+ * that there are no threads in the middle of input_open_device()
+ */
+ mutex_lock(&dev->mutex);
+ dev->going_away = 1;
+ mutex_unlock(&dev->mutex);
+
+ spin_lock_irq(&dev->event_lock);
+
+ /*
+ * Simulate keyup events for all pressed keys so that handlers
+ * are not left with "stuck" keys. The driver may continue
+ * generate events even after we done here but they will not
+ * reach any handlers.
+ */
+ if (is_event_supported(EV_KEY, dev->evbit, EV_MAX)) {
+ for (code = 0; code <= KEY_MAX; code++) {
+ if (is_event_supported(code, dev->keybit, KEY_MAX) &&
+ test_bit(code, dev->key)) {
+ input_pass_event(dev, EV_KEY, code, 0);
+ }
+ }
+ input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
+ }
+
+ list_for_each_entry(handle, &dev->h_list, d_node)
+ handle->open = 0;
+
+ spin_unlock_irq(&dev->event_lock);
+}
+
static int input_fetch_keycode(struct input_dev *dev, int scancode)
{
switch (dev->keycodesize) {
@@ -380,10 +584,10 @@ static int input_default_setkeycode(struct input_dev *dev,
#define MATCH_BIT(bit, max) \
- for (i = 0; i < NBITS(max); i++) \
+ for (i = 0; i < BITS_TO_LONGS(max); i++) \
if ((id->bit[i] & dev->bit[i]) != id->bit[i]) \
break; \
- if (i != NBITS(max)) \
+ if (i != BITS_TO_LONGS(max)) \
continue;
static const struct input_device_id *input_match_device(const struct input_device_id *id,
@@ -473,7 +677,8 @@ static unsigned int input_proc_devices_poll(struct file *file, poll_table *wait)
static void *input_devices_seq_start(struct seq_file *seq, loff_t *pos)
{
- /* acquire lock here ... Yes, we do need locking, I knowi, I know... */
+ if (mutex_lock_interruptible(&input_mutex))
+ return NULL;
return seq_list_start(&input_dev_list, *pos);
}
@@ -485,7 +690,7 @@ static void *input_devices_seq_next(struct seq_file *seq, void *v, loff_t *pos)
static void input_devices_seq_stop(struct seq_file *seq, void *v)
{
- /* release lock here */
+ mutex_unlock(&input_mutex);
}
static void input_seq_print_bitmap(struct seq_file *seq, const char *name,
@@ -493,7 +698,7 @@ static void input_seq_print_bitmap(struct seq_file *seq, const char *name,
{
int i;
- for (i = NBITS(max) - 1; i > 0; i--)
+ for (i = BITS_TO_LONGS(max) - 1; i > 0; i--)
if (bitmap[i])
break;
@@ -569,7 +774,9 @@ static const struct file_operations input_devices_fileops = {
static void *input_handlers_seq_start(struct seq_file *seq, loff_t *pos)
{
- /* acquire lock here ... Yes, we do need locking, I knowi, I know... */
+ if (mutex_lock_interruptible(&input_mutex))
+ return NULL;
+
seq->private = (void *)(unsigned long)*pos;
return seq_list_start(&input_handler_list, *pos);
}
@@ -582,7 +789,7 @@ static void *input_handlers_seq_next(struct seq_file *seq, void *v, loff_t *pos)
static void input_handlers_seq_stop(struct seq_file *seq, void *v)
{
- /* release lock here */
+ mutex_unlock(&input_mutex);
}
static int input_handlers_seq_show(struct seq_file *seq, void *v)
@@ -685,7 +892,7 @@ static int input_print_modalias_bits(char *buf, int size,
len += snprintf(buf, max(size, 0), "%c", name);
for (i = min_bit; i < max_bit; i++)
- if (bm[LONG(i)] & BIT(i))
+ if (bm[BIT_WORD(i)] & BIT_MASK(i))
len += snprintf(buf + len, max(size - len, 0), "%X,", i);
return len;
}
@@ -784,7 +991,7 @@ static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap,
int i;
int len = 0;
- for (i = NBITS(max) - 1; i > 0; i--)
+ for (i = BITS_TO_LONGS(max) - 1; i > 0; i--)
if (bitmap[i])
break;
@@ -983,6 +1190,7 @@ struct input_dev *input_allocate_device(void)
dev->dev.class = &input_class;
device_initialize(&dev->dev);
mutex_init(&dev->mutex);
+ spin_lock_init(&dev->event_lock);
INIT_LIST_HEAD(&dev->h_list);
INIT_LIST_HEAD(&dev->node);
@@ -1000,7 +1208,7 @@ EXPORT_SYMBOL(input_allocate_device);
* This function should only be used if input_register_device()
* was not called yet or if it failed. Once device was registered
* use input_unregister_device() and memory will be freed once last
- * refrence to the device is dropped.
+ * reference to the device is dropped.
*
* Device should be allocated by input_allocate_device().
*
@@ -1070,6 +1278,18 @@ void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int
}
EXPORT_SYMBOL(input_set_capability);
+/**
+ * input_register_device - register device with input core
+ * @dev: device to be registered
+ *
+ * This function registers device with input core. The device must be
+ * allocated with input_allocate_device() and all it's capabilities
+ * set up before registering.
+ * If function fails the device must be freed with input_free_device().
+ * Once device has been successfully registered it can be unregistered
+ * with input_unregister_device(); input_free_device() should not be
+ * called in this case.
+ */
int input_register_device(struct input_dev *dev)
{
static atomic_t input_no = ATOMIC_INIT(0);
@@ -1077,7 +1297,7 @@ int input_register_device(struct input_dev *dev)
const char *path;
int error;
- set_bit(EV_SYN, dev->evbit);
+ __set_bit(EV_SYN, dev->evbit);
/*
* If delay and period are pre-set by the driver, then autorepeating
@@ -1098,8 +1318,6 @@ int input_register_device(struct input_dev *dev)
if (!dev->setkeycode)
dev->setkeycode = input_default_setkeycode;
- list_add_tail(&dev->node, &input_dev_list);
-
snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id),
"input%ld", (unsigned long) atomic_inc_return(&input_no) - 1);
@@ -1115,49 +1333,79 @@ int input_register_device(struct input_dev *dev)
dev->name ? dev->name : "Unspecified device", path ? path : "N/A");
kfree(path);
+ error = mutex_lock_interruptible(&input_mutex);
+ if (error) {
+ device_del(&dev->dev);
+ return error;
+ }
+
+ list_add_tail(&dev->node, &input_dev_list);
+
list_for_each_entry(handler, &input_handler_list, node)
input_attach_handler(dev, handler);
input_wakeup_procfs_readers();
+ mutex_unlock(&input_mutex);
+
return 0;
}
EXPORT_SYMBOL(input_register_device);
+/**
+ * input_unregister_device - unregister previously registered device
+ * @dev: device to be unregistered
+ *
+ * This function unregisters an input device. Once device is unregistered
+ * the caller should not try to access it as it may get freed at any moment.
+ */
void input_unregister_device(struct input_dev *dev)
{
struct input_handle *handle, *next;
- int code;
- for (code = 0; code <= KEY_MAX; code++)
- if (test_bit(code, dev->key))
- input_report_key(dev, code, 0);
- input_sync(dev);
+ input_disconnect_device(dev);
- del_timer_sync(&dev->timer);
+ mutex_lock(&input_mutex);
list_for_each_entry_safe(handle, next, &dev->h_list, d_node)
handle->handler->disconnect(handle);
WARN_ON(!list_empty(&dev->h_list));
+ del_timer_sync(&dev->timer);
list_del_init(&dev->node);
- device_unregister(&dev->dev);
-
input_wakeup_procfs_readers();
+
+ mutex_unlock(&input_mutex);
+
+ device_unregister(&dev->dev);
}
EXPORT_SYMBOL(input_unregister_device);
+/**
+ * input_register_handler - register a new input handler
+ * @handler: handler to be registered
+ *
+ * This function registers a new input handler (interface) for input
+ * devices in the system and attaches it to all input devices that
+ * are compatible with the handler.
+ */
int input_register_handler(struct input_handler *handler)
{
struct input_dev *dev;
+ int retval;
+
+ retval = mutex_lock_interruptible(&input_mutex);
+ if (retval)
+ return retval;
INIT_LIST_HEAD(&handler->h_list);
if (handler->fops != NULL) {
- if (input_table[handler->minor >> 5])
- return -EBUSY;
-
+ if (input_table[handler->minor >> 5]) {
+ retval = -EBUSY;
+ goto out;
+ }
input_table[handler->minor >> 5] = handler;
}
@@ -1167,14 +1415,26 @@ int input_register_handler(struct input_handler *handler)
input_attach_handler(dev, handler);
input_wakeup_procfs_readers();
- return 0;
+
+ out:
+ mutex_unlock(&input_mutex);
+ return retval;
}
EXPORT_SYMBOL(input_register_handler);
+/**
+ * input_unregister_handler - unregisters an input handler
+ * @handler: handler to be unregistered
+ *
+ * This function disconnects a handler from its input devices and
+ * removes it from lists of known handlers.
+ */
void input_unregister_handler(struct input_handler *handler)
{
struct input_handle *handle, *next;
+ mutex_lock(&input_mutex);
+
list_for_each_entry_safe(handle, next, &handler->h_list, h_node)
handler->disconnect(handle);
WARN_ON(!list_empty(&handler->h_list));
@@ -1185,14 +1445,45 @@ void input_unregister_handler(struct input_handler *handler)
input_table[handler->minor >> 5] = NULL;
input_wakeup_procfs_readers();
+
+ mutex_unlock(&input_mutex);
}
EXPORT_SYMBOL(input_unregister_handler);
+/**
+ * input_register_handle - register a new input handle
+ * @handle: handle to register
+ *
+ * This function puts a new input handle onto device's
+ * and handler's lists so that events can flow through
+ * it once it is opened using input_open_device().
+ *
+ * This function is supposed to be called from handler's
+ * connect() method.
+ */
int input_register_handle(struct input_handle *handle)
{
struct input_handler *handler = handle->handler;
+ struct input_dev *dev = handle->dev;
+ int error;
+
+ /*
+ * We take dev->mutex here to prevent race with
+ * input_release_device().
+ */
+ error = mutex_lock_interruptible(&dev->mutex);
+ if (error)
+ return error;
+ list_add_tail_rcu(&handle->d_node, &dev->h_list);
+ mutex_unlock(&dev->mutex);
+ synchronize_rcu();
- list_add_tail(&handle->d_node, &handle->dev->h_list);
+ /*
+ * Since we are supposed to be called from ->connect()
+ * which is mutually exclusive with ->disconnect()
+ * we can't be racing with input_unregister_handle()
+ * and so separate lock is not needed here.
+ */
list_add_tail(&handle->h_node, &handler->h_list);
if (handler->start)
@@ -1202,10 +1493,29 @@ int input_register_handle(struct input_handle *handle)
}
EXPORT_SYMBOL(input_register_handle);
+/**
+ * input_unregister_handle - unregister an input handle
+ * @handle: handle to unregister
+ *
+ * This function removes input handle from device's
+ * and handler's lists.
+ *
+ * This function is supposed to be called from handler's
+ * disconnect() method.
+ */
void input_unregister_handle(struct input_handle *handle)
{
+ struct input_dev *dev = handle->dev;
+
list_del_init(&handle->h_node);
- list_del_init(&handle->d_node);
+
+ /*
+ * Take dev->mutex to prevent race with input_release_device().
+ */
+ mutex_lock(&dev->mutex);
+ list_del_rcu(&handle->d_node);
+ mutex_unlock(&dev->mutex);
+ synchronize_rcu();
}
EXPORT_SYMBOL(input_unregister_handle);
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index a9a0180bfd46..22b2789ef58a 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -43,6 +43,8 @@ struct joydev {
struct input_handle handle;
wait_queue_head_t wait;
struct list_head client_list;
+ spinlock_t client_lock; /* protects client_list */
+ struct mutex mutex;
struct device dev;
struct js_corr corr[ABS_MAX + 1];
@@ -61,31 +63,61 @@ struct joydev_client {
int head;
int tail;
int startup;
+ spinlock_t buffer_lock; /* protects access to buffer, head and tail */
struct fasync_struct *fasync;
struct joydev *joydev;
struct list_head node;
};
static struct joydev *joydev_table[JOYDEV_MINORS];
+static DEFINE_MUTEX(joydev_table_mutex);
static int joydev_correct(int value, struct js_corr *corr)
{
switch (corr->type) {
- case JS_CORR_NONE:
- break;
- case JS_CORR_BROKEN:
- value = value > corr->coef[0] ? (value < corr->coef[1] ? 0 :
- ((corr->coef[3] * (value - corr->coef[1])) >> 14)) :
- ((corr->coef[2] * (value - corr->coef[0])) >> 14);
- break;
- default:
- return 0;
+
+ case JS_CORR_NONE:
+ break;
+
+ case JS_CORR_BROKEN:
+ value = value > corr->coef[0] ? (value < corr->coef[1] ? 0 :
+ ((corr->coef[3] * (value - corr->coef[1])) >> 14)) :
+ ((corr->coef[2] * (value - corr->coef[0])) >> 14);
+ break;
+
+ default:
+ return 0;
}
return value < -32767 ? -32767 : (value > 32767 ? 32767 : value);
}
-static void joydev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
+static void joydev_pass_event(struct joydev_client *client,
+ struct js_event *event)
+{
+ struct joydev *joydev = client->joydev;
+
+ /*
+ * IRQs already disabled, just acquire the lock
+ */
+ spin_lock(&client->buffer_lock);
+
+ client->buffer[client->head] = *event;
+
+ if (client->startup == joydev->nabs + joydev->nkey) {
+ client->head++;
+ client->head &= JOYDEV_BUFFER_SIZE - 1;
+ if (client->tail == client->head)
+ client->startup = 0;
+ }
+
+ spin_unlock(&client->buffer_lock);
+
+ kill_fasync(&client->fasync, SIGIO, POLL_IN);
+}
+
+static void joydev_event(struct input_handle *handle,
+ unsigned int type, unsigned int code, int value)
{
struct joydev *joydev = handle->private;
struct joydev_client *client;
@@ -93,39 +125,34 @@ static void joydev_event(struct input_handle *handle, unsigned int type, unsigne
switch (type) {
- case EV_KEY:
- if (code < BTN_MISC || value == 2)
- return;
- event.type = JS_EVENT_BUTTON;
- event.number = joydev->keymap[code - BTN_MISC];
- event.value = value;
- break;
-
- case EV_ABS:
- event.type = JS_EVENT_AXIS;
- event.number = joydev->absmap[code];
- event.value = joydev_correct(value, joydev->corr + event.number);
- if (event.value == joydev->abs[event.number])
- return;
- joydev->abs[event.number] = event.value;
- break;
+ case EV_KEY:
+ if (code < BTN_MISC || value == 2)
+ return;
+ event.type = JS_EVENT_BUTTON;
+ event.number = joydev->keymap[code - BTN_MISC];
+ event.value = value;
+ break;
- default:
+ case EV_ABS:
+ event.type = JS_EVENT_AXIS;
+ event.number = joydev->absmap[code];
+ event.value = joydev_correct(value,
+ &joydev->corr[event.number]);
+ if (event.value == joydev->abs[event.number])
return;
+ joydev->abs[event.number] = event.value;
+ break;
+
+ default:
+ return;
}
event.time = jiffies_to_msecs(jiffies);
- list_for_each_entry(client, &joydev->client_list, node) {
-
- memcpy(client->buffer + client->head, &event, sizeof(struct js_event));
-
- if (client->startup == joydev->nabs + joydev->nkey)
- if (client->tail == (client->head = (client->head + 1) & (JOYDEV_BUFFER_SIZE - 1)))
- client->startup = 0;
-
- kill_fasync(&client->fasync, SIGIO, POLL_IN);
- }
+ rcu_read_lock();
+ list_for_each_entry_rcu(client, &joydev->client_list, node)
+ joydev_pass_event(client, &event);
+ rcu_read_unlock();
wake_up_interruptible(&joydev->wait);
}
@@ -144,23 +171,83 @@ static void joydev_free(struct device *dev)
{
struct joydev *joydev = container_of(dev, struct joydev, dev);
- joydev_table[joydev->minor] = NULL;
kfree(joydev);
}
+static void joydev_attach_client(struct joydev *joydev,
+ struct joydev_client *client)
+{
+ spin_lock(&joydev->client_lock);
+ list_add_tail_rcu(&client->node, &joydev->client_list);
+ spin_unlock(&joydev->client_lock);
+ synchronize_rcu();
+}
+
+static void joydev_detach_client(struct joydev *joydev,
+ struct joydev_client *client)
+{
+ spin_lock(&joydev->client_lock);
+ list_del_rcu(&client->node);
+ spin_unlock(&joydev->client_lock);
+ synchronize_rcu();
+}
+
+static int joydev_open_device(struct joydev *joydev)
+{
+ int retval;
+
+ retval = mutex_lock_interruptible(&joydev->mutex);
+ if (retval)
+ return retval;
+
+ if (!joydev->exist)
+ retval = -ENODEV;
+ else if (!joydev->open++) {
+ retval = input_open_device(&joydev->handle);
+ if (retval)
+ joydev->open--;
+ }
+
+ mutex_unlock(&joydev->mutex);
+ return retval;
+}
+
+static void joydev_close_device(struct joydev *joydev)
+{
+ mutex_lock(&joydev->mutex);
+
+ if (joydev->exist && !--joydev->open)
+ input_close_device(&joydev->handle);
+
+ mutex_unlock(&joydev->mutex);
+}
+
+/*
+ * Wake up users waiting for IO so they can disconnect from
+ * dead device.
+ */
+static void joydev_hangup(struct joydev *joydev)
+{
+ struct joydev_client *client;
+
+ spin_lock(&joydev->client_lock);
+ list_for_each_entry(client, &joydev->client_list, node)
+ kill_fasync(&client->fasync, SIGIO, POLL_HUP);
+ spin_unlock(&joydev->client_lock);
+
+ wake_up_interruptible(&joydev->wait);
+}
+
static int joydev_release(struct inode *inode, struct file *file)
{
struct joydev_client *client = file->private_data;
struct joydev *joydev = client->joydev;
joydev_fasync(-1, file, 0);
-
- list_del(&client->node);
+ joydev_detach_client(joydev, client);
kfree(client);
- if (!--joydev->open && joydev->exist)
- input_close_device(&joydev->handle);
-
+ joydev_close_device(joydev);
put_device(&joydev->dev);
return 0;
@@ -176,11 +263,16 @@ static int joydev_open(struct inode *inode, struct file *file)
if (i >= JOYDEV_MINORS)
return -ENODEV;
+ error = mutex_lock_interruptible(&joydev_table_mutex);
+ if (error)
+ return error;
joydev = joydev_table[i];
- if (!joydev || !joydev->exist)
- return -ENODEV;
+ if (joydev)
+ get_device(&joydev->dev);
+ mutex_unlock(&joydev_table_mutex);
- get_device(&joydev->dev);
+ if (!joydev)
+ return -ENODEV;
client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL);
if (!client) {
@@ -188,37 +280,129 @@ static int joydev_open(struct inode *inode, struct file *file)
goto err_put_joydev;
}
+ spin_lock_init(&client->buffer_lock);
client->joydev = joydev;
- list_add_tail(&client->node, &joydev->client_list);
+ joydev_attach_client(joydev, client);
- if (!joydev->open++ && joydev->exist) {
- error = input_open_device(&joydev->handle);
- if (error)
- goto err_free_client;
- }
+ error = joydev_open_device(joydev);
+ if (error)
+ goto err_free_client;
file->private_data = client;
return 0;
err_free_client:
- list_del(&client->node);
+ joydev_detach_client(joydev, client);
kfree(client);
err_put_joydev:
put_device(&joydev->dev);
return error;
}
-static ssize_t joydev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
+static int joydev_generate_startup_event(struct joydev_client *client,
+ struct input_dev *input,
+ struct js_event *event)
{
- return -EINVAL;
+ struct joydev *joydev = client->joydev;
+ int have_event;
+
+ spin_lock_irq(&client->buffer_lock);
+
+ have_event = client->startup < joydev->nabs + joydev->nkey;
+
+ if (have_event) {
+
+ event->time = jiffies_to_msecs(jiffies);
+ if (client->startup < joydev->nkey) {
+ event->type = JS_EVENT_BUTTON | JS_EVENT_INIT;
+ event->number = client->startup;
+ event->value = !!test_bit(joydev->keypam[event->number],
+ input->key);
+ } else {
+ event->type = JS_EVENT_AXIS | JS_EVENT_INIT;
+ event->number = client->startup - joydev->nkey;
+ event->value = joydev->abs[event->number];
+ }
+ client->startup++;
+ }
+
+ spin_unlock_irq(&client->buffer_lock);
+
+ return have_event;
+}
+
+static int joydev_fetch_next_event(struct joydev_client *client,
+ struct js_event *event)
+{
+ int have_event;
+
+ spin_lock_irq(&client->buffer_lock);
+
+ have_event = client->head != client->tail;
+ if (have_event) {
+ *event = client->buffer[client->tail++];
+ client->tail &= JOYDEV_BUFFER_SIZE - 1;
+ }
+
+ spin_unlock_irq(&client->buffer_lock);
+
+ return have_event;
+}
+
+/*
+ * Old joystick interface
+ */
+static ssize_t joydev_0x_read(struct joydev_client *client,
+ struct input_dev *input,
+ char __user *buf)
+{
+ struct joydev *joydev = client->joydev;
+ struct JS_DATA_TYPE data;
+ int i;
+
+ spin_lock_irq(&input->event_lock);
+
+ /*
+ * Get device state
+ */
+ for (data.buttons = i = 0; i < 32 && i < joydev->nkey; i++)
+ data.buttons |=
+ test_bit(joydev->keypam[i], input->key) ? (1 << i) : 0;
+ data.x = (joydev->abs[0] / 256 + 128) >> joydev->glue.JS_CORR.x;
+ data.y = (joydev->abs[1] / 256 + 128) >> joydev->glue.JS_CORR.y;
+
+ /*
+ * Reset reader's event queue
+ */
+ spin_lock(&client->buffer_lock);
+ client->startup = 0;
+ client->tail = client->head;
+ spin_unlock(&client->buffer_lock);
+
+ spin_unlock_irq(&input->event_lock);
+
+ if (copy_to_user(buf, &data, sizeof(struct JS_DATA_TYPE)))
+ return -EFAULT;
+
+ return sizeof(struct JS_DATA_TYPE);
+}
+
+static inline int joydev_data_pending(struct joydev_client *client)
+{
+ struct joydev *joydev = client->joydev;
+
+ return client->startup < joydev->nabs + joydev->nkey ||
+ client->head != client->tail;
}
-static ssize_t joydev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+static ssize_t joydev_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
{
struct joydev_client *client = file->private_data;
struct joydev *joydev = client->joydev;
struct input_dev *input = joydev->handle.dev;
- int retval = 0;
+ struct js_event event;
+ int retval;
if (!joydev->exist)
return -ENODEV;
@@ -226,68 +410,35 @@ static ssize_t joydev_read(struct file *file, char __user *buf, size_t count, lo
if (count < sizeof(struct js_event))
return -EINVAL;
- if (count == sizeof(struct JS_DATA_TYPE)) {
-
- struct JS_DATA_TYPE data;
- int i;
-
- for (data.buttons = i = 0; i < 32 && i < joydev->nkey; i++)
- data.buttons |= test_bit(joydev->keypam[i], input->key) ? (1 << i) : 0;
- data.x = (joydev->abs[0] / 256 + 128) >> joydev->glue.JS_CORR.x;
- data.y = (joydev->abs[1] / 256 + 128) >> joydev->glue.JS_CORR.y;
-
- if (copy_to_user(buf, &data, sizeof(struct JS_DATA_TYPE)))
- return -EFAULT;
-
- client->startup = 0;
- client->tail = client->head;
+ if (count == sizeof(struct JS_DATA_TYPE))
+ return joydev_0x_read(client, input, buf);
- return sizeof(struct JS_DATA_TYPE);
- }
-
- if (client->startup == joydev->nabs + joydev->nkey &&
- client->head == client->tail && (file->f_flags & O_NONBLOCK))
+ if (!joydev_data_pending(client) && (file->f_flags & O_NONBLOCK))
return -EAGAIN;
retval = wait_event_interruptible(joydev->wait,
- !joydev->exist ||
- client->startup < joydev->nabs + joydev->nkey ||
- client->head != client->tail);
+ !joydev->exist || joydev_data_pending(client));
if (retval)
return retval;
if (!joydev->exist)
return -ENODEV;
- while (client->startup < joydev->nabs + joydev->nkey && retval + sizeof(struct js_event) <= count) {
-
- struct js_event event;
-
- event.time = jiffies_to_msecs(jiffies);
-
- if (client->startup < joydev->nkey) {
- event.type = JS_EVENT_BUTTON | JS_EVENT_INIT;
- event.number = client->startup;
- event.value = !!test_bit(joydev->keypam[event.number], input->key);
- } else {
- event.type = JS_EVENT_AXIS | JS_EVENT_INIT;
- event.number = client->startup - joydev->nkey;
- event.value = joydev->abs[event.number];
- }
+ while (retval + sizeof(struct js_event) <= count &&
+ joydev_generate_startup_event(client, input, &event)) {
if (copy_to_user(buf + retval, &event, sizeof(struct js_event)))
return -EFAULT;
- client->startup++;
retval += sizeof(struct js_event);
}
- while (client->head != client->tail && retval + sizeof(struct js_event) <= count) {
+ while (retval + sizeof(struct js_event) <= count &&
+ joydev_fetch_next_event(client, &event)) {
- if (copy_to_user(buf + retval, client->buffer + client->tail, sizeof(struct js_event)))
+ if (copy_to_user(buf + retval, &event, sizeof(struct js_event)))
return -EFAULT;
- client->tail = (client->tail + 1) & (JOYDEV_BUFFER_SIZE - 1);
retval += sizeof(struct js_event);
}
@@ -301,126 +452,144 @@ static unsigned int joydev_poll(struct file *file, poll_table *wait)
struct joydev *joydev = client->joydev;
poll_wait(file, &joydev->wait, wait);
- return ((client->head != client->tail || client->startup < joydev->nabs + joydev->nkey) ?
- (POLLIN | POLLRDNORM) : 0) | (joydev->exist ? 0 : (POLLHUP | POLLERR));
+ return (joydev_data_pending(client) ? (POLLIN | POLLRDNORM) : 0) |
+ (joydev->exist ? 0 : (POLLHUP | POLLERR));
}
-static int joydev_ioctl_common(struct joydev *joydev, unsigned int cmd, void __user *argp)
+static int joydev_ioctl_common(struct joydev *joydev,
+ unsigned int cmd, void __user *argp)
{
struct input_dev *dev = joydev->handle.dev;
int i, j;
switch (cmd) {
- case JS_SET_CAL:
- return copy_from_user(&joydev->glue.JS_CORR, argp,
+ case JS_SET_CAL:
+ return copy_from_user(&joydev->glue.JS_CORR, argp,
sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0;
- case JS_GET_CAL:
- return copy_to_user(argp, &joydev->glue.JS_CORR,
+ case JS_GET_CAL:
+ return copy_to_user(argp, &joydev->glue.JS_CORR,
sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0;
- case JS_SET_TIMEOUT:
- return get_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp);
+ case JS_SET_TIMEOUT:
+ return get_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp);
- case JS_GET_TIMEOUT:
- return put_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp);
+ case JS_GET_TIMEOUT:
+ return put_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp);
- case JSIOCGVERSION:
- return put_user(JS_VERSION, (__u32 __user *) argp);
+ case JSIOCGVERSION:
+ return put_user(JS_VERSION, (__u32 __user *) argp);
- case JSIOCGAXES:
- return put_user(joydev->nabs, (__u8 __user *) argp);
+ case JSIOCGAXES:
+ return put_user(joydev->nabs, (__u8 __user *) argp);
- case JSIOCGBUTTONS:
- return put_user(joydev->nkey, (__u8 __user *) argp);
+ case JSIOCGBUTTONS:
+ return put_user(joydev->nkey, (__u8 __user *) argp);
- case JSIOCSCORR:
- if (copy_from_user(joydev->corr, argp,
- sizeof(joydev->corr[0]) * joydev->nabs))
- return -EFAULT;
- for (i = 0; i < joydev->nabs; i++) {
- j = joydev->abspam[i];
- joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i);
- }
- return 0;
+ case JSIOCSCORR:
+ if (copy_from_user(joydev->corr, argp,
+ sizeof(joydev->corr[0]) * joydev->nabs))
+ return -EFAULT;
- case JSIOCGCORR:
- return copy_to_user(argp, joydev->corr,
- sizeof(joydev->corr[0]) * joydev->nabs) ? -EFAULT : 0;
+ for (i = 0; i < joydev->nabs; i++) {
+ j = joydev->abspam[i];
+ joydev->abs[i] = joydev_correct(dev->abs[j],
+ &joydev->corr[i]);
+ }
+ return 0;
- case JSIOCSAXMAP:
- if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * (ABS_MAX + 1)))
- return -EFAULT;
- for (i = 0; i < joydev->nabs; i++) {
- if (joydev->abspam[i] > ABS_MAX)
- return -EINVAL;
- joydev->absmap[joydev->abspam[i]] = i;
- }
- return 0;
-
- case JSIOCGAXMAP:
- return copy_to_user(argp, joydev->abspam,
- sizeof(__u8) * (ABS_MAX + 1)) ? -EFAULT : 0;
-
- case JSIOCSBTNMAP:
- if (copy_from_user(joydev->keypam, argp, sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)))
+ case JSIOCGCORR:
+ return copy_to_user(argp, joydev->corr,
+ sizeof(joydev->corr[0]) * joydev->nabs) ? -EFAULT : 0;
+
+ case JSIOCSAXMAP:
+ if (copy_from_user(joydev->abspam, argp,
+ sizeof(__u8) * (ABS_MAX + 1)))
+ return -EFAULT;
+
+ for (i = 0; i < joydev->nabs; i++) {
+ if (joydev->abspam[i] > ABS_MAX)
+ return -EINVAL;
+ joydev->absmap[joydev->abspam[i]] = i;
+ }
+ return 0;
+
+ case JSIOCGAXMAP:
+ return copy_to_user(argp, joydev->abspam,
+ sizeof(__u8) * (ABS_MAX + 1)) ? -EFAULT : 0;
+
+ case JSIOCSBTNMAP:
+ if (copy_from_user(joydev->keypam, argp,
+ sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)))
+ return -EFAULT;
+
+ for (i = 0; i < joydev->nkey; i++) {
+ if (joydev->keypam[i] > KEY_MAX ||
+ joydev->keypam[i] < BTN_MISC)
+ return -EINVAL;
+ joydev->keymap[joydev->keypam[i] - BTN_MISC] = i;
+ }
+
+ return 0;
+
+ case JSIOCGBTNMAP:
+ return copy_to_user(argp, joydev->keypam,
+ sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)) ? -EFAULT : 0;
+
+ default:
+ if ((cmd & ~IOCSIZE_MASK) == JSIOCGNAME(0)) {
+ int len;
+ if (!dev->name)
+ return 0;
+ len = strlen(dev->name) + 1;
+ if (len > _IOC_SIZE(cmd))
+ len = _IOC_SIZE(cmd);
+ if (copy_to_user(argp, dev->name, len))
return -EFAULT;
- for (i = 0; i < joydev->nkey; i++) {
- if (joydev->keypam[i] > KEY_MAX || joydev->keypam[i] < BTN_MISC)
- return -EINVAL;
- joydev->keymap[joydev->keypam[i] - BTN_MISC] = i;
- }
- return 0;
-
- case JSIOCGBTNMAP:
- return copy_to_user(argp, joydev->keypam,
- sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)) ? -EFAULT : 0;
-
- default:
- if ((cmd & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) == JSIOCGNAME(0)) {
- int len;
- if (!dev->name)
- return 0;
- len = strlen(dev->name) + 1;
- if (len > _IOC_SIZE(cmd))
- len = _IOC_SIZE(cmd);
- if (copy_to_user(argp, dev->name, len))
- return -EFAULT;
- return len;
- }
+ return len;
+ }
}
return -EINVAL;
}
#ifdef CONFIG_COMPAT
-static long joydev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+static long joydev_compat_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
{
struct joydev_client *client = file->private_data;
struct joydev *joydev = client->joydev;
void __user *argp = (void __user *)arg;
s32 tmp32;
struct JS_DATA_SAVE_TYPE_32 ds32;
- int err;
+ int retval;
- if (!joydev->exist)
- return -ENODEV;
+ retval = mutex_lock_interruptible(&joydev->mutex);
+ if (retval)
+ return retval;
+
+ if (!joydev->exist) {
+ retval = -ENODEV;
+ goto out;
+ }
+
+ switch (cmd) {
- switch(cmd) {
case JS_SET_TIMELIMIT:
- err = get_user(tmp32, (s32 __user *) arg);
- if (err == 0)
+ retval = get_user(tmp32, (s32 __user *) arg);
+ if (retval == 0)
joydev->glue.JS_TIMELIMIT = tmp32;
break;
+
case JS_GET_TIMELIMIT:
tmp32 = joydev->glue.JS_TIMELIMIT;
- err = put_user(tmp32, (s32 __user *) arg);
+ retval = put_user(tmp32, (s32 __user *) arg);
break;
case JS_SET_ALL:
- err = copy_from_user(&ds32, argp,
- sizeof(ds32)) ? -EFAULT : 0;
- if (err == 0) {
+ retval = copy_from_user(&ds32, argp,
+ sizeof(ds32)) ? -EFAULT : 0;
+ if (retval == 0) {
joydev->glue.JS_TIMEOUT = ds32.JS_TIMEOUT;
joydev->glue.BUSY = ds32.BUSY;
joydev->glue.JS_EXPIRETIME = ds32.JS_EXPIRETIME;
@@ -438,55 +607,119 @@ static long joydev_compat_ioctl(struct file *file, unsigned int cmd, unsigned lo
ds32.JS_SAVE = joydev->glue.JS_SAVE;
ds32.JS_CORR = joydev->glue.JS_CORR;
- err = copy_to_user(argp, &ds32, sizeof(ds32)) ? -EFAULT : 0;
+ retval = copy_to_user(argp, &ds32, sizeof(ds32)) ? -EFAULT : 0;
break;
default:
- err = joydev_ioctl_common(joydev, cmd, argp);
+ retval = joydev_ioctl_common(joydev, cmd, argp);
+ break;
}
- return err;
+
+ out:
+ mutex_unlock(&joydev->mutex);
+ return retval;
}
#endif /* CONFIG_COMPAT */
-static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static long joydev_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
{
struct joydev_client *client = file->private_data;
struct joydev *joydev = client->joydev;
void __user *argp = (void __user *)arg;
+ int retval;
- if (!joydev->exist)
- return -ENODEV;
+ retval = mutex_lock_interruptible(&joydev->mutex);
+ if (retval)
+ return retval;
+
+ if (!joydev->exist) {
+ retval = -ENODEV;
+ goto out;
+ }
+
+ switch (cmd) {
+
+ case JS_SET_TIMELIMIT:
+ retval = get_user(joydev->glue.JS_TIMELIMIT,
+ (long __user *) arg);
+ break;
+
+ case JS_GET_TIMELIMIT:
+ retval = put_user(joydev->glue.JS_TIMELIMIT,
+ (long __user *) arg);
+ break;
+
+ case JS_SET_ALL:
+ retval = copy_from_user(&joydev->glue, argp,
+ sizeof(joydev->glue)) ? -EFAULT: 0;
+ break;
+
+ case JS_GET_ALL:
+ retval = copy_to_user(argp, &joydev->glue,
+ sizeof(joydev->glue)) ? -EFAULT : 0;
+ break;
- switch(cmd) {
- case JS_SET_TIMELIMIT:
- return get_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg);
- case JS_GET_TIMELIMIT:
- return put_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg);
- case JS_SET_ALL:
- return copy_from_user(&joydev->glue, argp,
- sizeof(joydev->glue)) ? -EFAULT : 0;
- case JS_GET_ALL:
- return copy_to_user(argp, &joydev->glue,
- sizeof(joydev->glue)) ? -EFAULT : 0;
- default:
- return joydev_ioctl_common(joydev, cmd, argp);
+ default:
+ retval = joydev_ioctl_common(joydev, cmd, argp);
+ break;
}
+ out:
+ mutex_unlock(&joydev->mutex);
+ return retval;
}
static const struct file_operations joydev_fops = {
- .owner = THIS_MODULE,
- .read = joydev_read,
- .write = joydev_write,
- .poll = joydev_poll,
- .open = joydev_open,
- .release = joydev_release,
- .ioctl = joydev_ioctl,
+ .owner = THIS_MODULE,
+ .read = joydev_read,
+ .poll = joydev_poll,
+ .open = joydev_open,
+ .release = joydev_release,
+ .unlocked_ioctl = joydev_ioctl,
#ifdef CONFIG_COMPAT
- .compat_ioctl = joydev_compat_ioctl,
+ .compat_ioctl = joydev_compat_ioctl,
#endif
- .fasync = joydev_fasync,
+ .fasync = joydev_fasync,
};
+static int joydev_install_chrdev(struct joydev *joydev)
+{
+ joydev_table[joydev->minor] = joydev;
+ return 0;
+}
+
+static void joydev_remove_chrdev(struct joydev *joydev)
+{
+ mutex_lock(&joydev_table_mutex);
+ joydev_table[joydev->minor] = NULL;
+ mutex_unlock(&joydev_table_mutex);
+}
+
+/*
+ * Mark device non-existant. This disables writes, ioctls and
+ * prevents new users from opening the device. Already posted
+ * blocking reads will stay, however new ones will fail.
+ */
+static void joydev_mark_dead(struct joydev *joydev)
+{
+ mutex_lock(&joydev->mutex);
+ joydev->exist = 0;
+ mutex_unlock(&joydev->mutex);
+}
+
+static void joydev_cleanup(struct joydev *joydev)
+{
+ struct input_handle *handle = &joydev->handle;
+
+ joydev_mark_dead(joydev);
+ joydev_hangup(joydev);
+ joydev_remove_chrdev(joydev);
+
+ /* joydev is marked dead so noone else accesses joydev->open */
+ if (joydev->open)
+ input_close_device(handle);
+}
+
static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
const struct input_device_id *id)
{
@@ -494,7 +727,10 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
int i, j, t, minor;
int error;
- for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++);
+ for (minor = 0; minor < JOYDEV_MINORS; minor++)
+ if (!joydev_table[minor])
+ break;
+
if (minor == JOYDEV_MINORS) {
printk(KERN_ERR "joydev: no more free joydev devices\n");
return -ENFILE;
@@ -505,15 +741,19 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
return -ENOMEM;
INIT_LIST_HEAD(&joydev->client_list);
+ spin_lock_init(&joydev->client_lock);
+ mutex_init(&joydev->mutex);
init_waitqueue_head(&joydev->wait);
+ snprintf(joydev->name, sizeof(joydev->name), "js%d", minor);
+ joydev->exist = 1;
joydev->minor = minor;
+
joydev->exist = 1;
joydev->handle.dev = dev;
joydev->handle.name = joydev->name;
joydev->handle.handler = handler;
joydev->handle.private = joydev;
- snprintf(joydev->name, sizeof(joydev->name), "js%d", minor);
for (i = 0; i < ABS_MAX + 1; i++)
if (test_bit(i, dev->absbit)) {
@@ -545,88 +785,89 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
}
joydev->corr[i].type = JS_CORR_BROKEN;
joydev->corr[i].prec = dev->absfuzz[j];
- joydev->corr[i].coef[0] = (dev->absmax[j] + dev->absmin[j]) / 2 - dev->absflat[j];
- joydev->corr[i].coef[1] = (dev->absmax[j] + dev->absmin[j]) / 2 + dev->absflat[j];
- if (!(t = ((dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j])))
- continue;
- joydev->corr[i].coef[2] = (1 << 29) / t;
- joydev->corr[i].coef[3] = (1 << 29) / t;
-
- joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i);
+ joydev->corr[i].coef[0] =
+ (dev->absmax[j] + dev->absmin[j]) / 2 - dev->absflat[j];
+ joydev->corr[i].coef[1] =
+ (dev->absmax[j] + dev->absmin[j]) / 2 + dev->absflat[j];
+
+ t = (dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j];
+ if (t) {
+ joydev->corr[i].coef[2] = (1 << 29) / t;
+ joydev->corr[i].coef[3] = (1 << 29) / t;
+
+ joydev->abs[i] = joydev_correct(dev->abs[j],
+ joydev->corr + i);
+ }
}
- snprintf(joydev->dev.bus_id, sizeof(joydev->dev.bus_id),
- "js%d", minor);
+ strlcpy(joydev->dev.bus_id, joydev->name, sizeof(joydev->dev.bus_id));
+ joydev->dev.devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor);
joydev->dev.class = &input_class;
joydev->dev.parent = &dev->dev;
- joydev->dev.devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor);
joydev->dev.release = joydev_free;
device_initialize(&joydev->dev);
- joydev_table[minor] = joydev;
-
- error = device_add(&joydev->dev);
+ error = input_register_handle(&joydev->handle);
if (error)
goto err_free_joydev;
- error = input_register_handle(&joydev->handle);
+ error = joydev_install_chrdev(joydev);
if (error)
- goto err_delete_joydev;
+ goto err_unregister_handle;
+
+ error = device_add(&joydev->dev);
+ if (error)
+ goto err_cleanup_joydev;
return 0;
- err_delete_joydev:
- device_del(&joydev->dev);
+ err_cleanup_joydev:
+ joydev_cleanup(joydev);
+ err_unregister_handle:
+ input_unregister_handle(&joydev->handle);
err_free_joydev:
put_device(&joydev->dev);
return error;
}
-
static void joydev_disconnect(struct input_handle *handle)
{
struct joydev *joydev = handle->private;
- struct joydev_client *client;
- input_unregister_handle(handle);
device_del(&joydev->dev);
-
- joydev->exist = 0;
-
- if (joydev->open) {
- input_close_device(handle);
- list_for_each_entry(client, &joydev->client_list, node)
- kill_fasync(&client->fasync, SIGIO, POLL_HUP);
- wake_up_interruptible(&joydev->wait);
- }
-
+ joydev_cleanup(joydev);
+ input_unregister_handle(handle);
put_device(&joydev->dev);
}
static const struct input_device_id joydev_blacklist[] = {
{
- .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT,
- .evbit = { BIT(EV_KEY) },
- .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) },
+ .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
+ INPUT_DEVICE_ID_MATCH_KEYBIT,
+ .evbit = { BIT_MASK(EV_KEY) },
+ .keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) },
}, /* Avoid itouchpads, touchscreens and tablets */
{ } /* Terminating entry */
};
static const struct input_device_id joydev_ids[] = {
{
- .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
- .evbit = { BIT(EV_ABS) },
- .absbit = { BIT(ABS_X) },
+ .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
+ INPUT_DEVICE_ID_MATCH_ABSBIT,
+ .evbit = { BIT_MASK(EV_ABS) },
+ .absbit = { BIT_MASK(ABS_X) },
},
{
- .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
- .evbit = { BIT(EV_ABS) },
- .absbit = { BIT(ABS_WHEEL) },
+ .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
+ INPUT_DEVICE_ID_MATCH_ABSBIT,
+ .evbit = { BIT_MASK(EV_ABS) },
+ .absbit = { BIT_MASK(ABS_WHEEL) },
},
{
- .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
- .evbit = { BIT(EV_ABS) },
- .absbit = { BIT(ABS_THROTTLE) },
+ .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
+ INPUT_DEVICE_ID_MATCH_ABSBIT,
+ .evbit = { BIT_MASK(EV_ABS) },
+ .absbit = { BIT_MASK(ABS_THROTTLE) },
},
{ } /* Terminating entry */
};
@@ -634,14 +875,14 @@ static const struct input_device_id joydev_ids[] = {
MODULE_DEVICE_TABLE(input, joydev_ids);
static struct input_handler joydev_handler = {
- .event = joydev_event,
- .connect = joydev_connect,
- .disconnect = joydev_disconnect,
- .fops = &joydev_fops,
- .minor = JOYDEV_MINOR_BASE,
- .name = "joydev",
- .id_table = joydev_ids,
- .blacklist = joydev_blacklist,
+ .event = joydev_event,
+ .connect = joydev_connect,
+ .disconnect = joydev_disconnect,
+ .fops = &joydev_fops,
+ .minor = JOYDEV_MINOR_BASE,
+ .name = "joydev",
+ .id_table = joydev_ids,
+ .blacklist = joydev_blacklist,
};
static int __init joydev_init(void)
diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c
index ff701ab10d74..52ba16f487c7 100644
--- a/drivers/input/joystick/a3d.c
+++ b/drivers/input/joystick/a3d.c
@@ -326,14 +326,19 @@ static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv)
a3d->length = 33;
- input_dev->evbit[0] |= BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL);
- input_dev->relbit[0] |= BIT(REL_X) | BIT(REL_Y);
- input_dev->absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_THROTTLE) | BIT(ABS_RUDDER)
- | BIT(ABS_HAT0X) | BIT(ABS_HAT0Y) | BIT(ABS_HAT1X) | BIT(ABS_HAT1Y);
- input_dev->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE)
- | BIT(BTN_SIDE) | BIT(BTN_EXTRA);
- input_dev->keybit[LONG(BTN_JOYSTICK)] |= BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP)
- | BIT(BTN_PINKIE);
+ input_dev->evbit[0] |= BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY) |
+ BIT_MASK(EV_REL);
+ input_dev->relbit[0] |= BIT_MASK(REL_X) | BIT_MASK(REL_Y);
+ input_dev->absbit[0] |= BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) |
+ BIT_MASK(ABS_THROTTLE) | BIT_MASK(ABS_RUDDER) |
+ BIT_MASK(ABS_HAT0X) | BIT_MASK(ABS_HAT0Y) |
+ BIT_MASK(ABS_HAT1X) | BIT_MASK(ABS_HAT1Y);
+ input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_RIGHT) |
+ BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) |
+ BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA);
+ input_dev->keybit[BIT_WORD(BTN_JOYSTICK)] |=
+ BIT_MASK(BTN_TRIGGER) | BIT_MASK(BTN_THUMB) |
+ BIT_MASK(BTN_TOP) | BIT_MASK(BTN_PINKIE);
a3d_read(a3d, data);
@@ -348,9 +353,10 @@ static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv)
} else {
a3d->length = 29;
- input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_REL);
- input_dev->relbit[0] |= BIT(REL_X) | BIT(REL_Y);
- input_dev->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE);
+ input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+ input_dev->relbit[0] |= BIT_MASK(REL_X) | BIT_MASK(REL_Y);
+ input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_RIGHT) |
+ BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE);
a3d_read(a3d, data);
diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c
index 28140c4a110d..d1ca8a14950f 100644
--- a/drivers/input/joystick/adi.c
+++ b/drivers/input/joystick/adi.c
@@ -431,7 +431,7 @@ static int adi_init_input(struct adi *adi, struct adi_port *port, int half)
input_dev->open = adi_open;
input_dev->close = adi_close;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad != -1)) * 2; i++)
set_bit(adi->abs[i], input_dev->absbit);
diff --git a/drivers/input/joystick/amijoy.c b/drivers/input/joystick/amijoy.c
index b0f5541ec3e6..5cf9f3610e67 100644
--- a/drivers/input/joystick/amijoy.c
+++ b/drivers/input/joystick/amijoy.c
@@ -137,9 +137,10 @@ static int __init amijoy_init(void)
amijoy_dev[i]->open = amijoy_open;
amijoy_dev[i]->close = amijoy_close;
- amijoy_dev[i]->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- amijoy_dev[i]->absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
- amijoy_dev[i]->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+ amijoy_dev[i]->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ amijoy_dev[i]->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y);
+ amijoy_dev[i]->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) |
+ BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
for (j = 0; j < 2; j++) {
amijoy_dev[i]->absmin[ABS_X + j] = -1;
amijoy_dev[i]->absmax[ABS_X + j] = 1;
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c
index bdd157c1ebf8..15739880afc6 100644
--- a/drivers/input/joystick/analog.c
+++ b/drivers/input/joystick/analog.c
@@ -456,7 +456,7 @@ static int analog_init_device(struct analog_port *port, struct analog *analog, i
input_dev->open = analog_open;
input_dev->close = analog_close;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
for (i = j = 0; i < 4; i++)
if (analog->mask & (1 << i)) {
diff --git a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c
index d3352a849b85..55646a6d89f5 100644
--- a/drivers/input/joystick/cobra.c
+++ b/drivers/input/joystick/cobra.c
@@ -218,7 +218,7 @@ static int cobra_connect(struct gameport *gameport, struct gameport_driver *drv)
input_dev->open = cobra_open;
input_dev->close = cobra_close;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
input_set_abs_params(input_dev, ABS_X, -1, 1, 0, 0);
input_set_abs_params(input_dev, ABS_Y, -1, 1, 0, 0);
for (j = 0; cobra_btn[j]; j++)
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c
index b069ee18e353..a6ca9d5e252f 100644
--- a/drivers/input/joystick/db9.c
+++ b/drivers/input/joystick/db9.c
@@ -4,7 +4,7 @@
* Copyright (c) 1999-2001 Vojtech Pavlik
*
* Based on the work of:
- * Andree Borrmann Mats Sjövall
+ * Andree Borrmann Mats Sjövall
*/
/*
@@ -631,7 +631,7 @@ static struct db9 __init *db9_probe(int parport, int mode)
input_dev->open = db9_open;
input_dev->close = db9_close;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
for (j = 0; j < db9_mode->n_buttons; j++)
set_bit(db9_mode->buttons[j], input_dev->keybit);
for (j = 0; j < db9_mode->n_axis; j++) {
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c
index 1a452e0e5f25..df2a9d02ca6c 100644
--- a/drivers/input/joystick/gamecon.c
+++ b/drivers/input/joystick/gamecon.c
@@ -653,12 +653,12 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type)
input_dev->close = gc_close;
if (pad_type != GC_SNESMOUSE) {
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
for (i = 0; i < 2; i++)
input_set_abs_params(input_dev, ABS_X + i, -1, 1, 0, 0);
} else
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
gc->pads[0] |= gc_status_bit[idx];
gc->pads[pad_type] |= gc_status_bit[idx];
diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c
index d514aebf7554..1f6302c0eb3f 100644
--- a/drivers/input/joystick/gf2k.c
+++ b/drivers/input/joystick/gf2k.c
@@ -315,7 +315,7 @@ static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv)
input_dev->open = gf2k_open;
input_dev->close = gf2k_close;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
for (i = 0; i < gf2k_axes[gf2k->id]; i++)
set_bit(gf2k_abs[i], input_dev->absbit);
diff --git a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c
index 73eb5ab6f140..fd3853ab1aad 100644
--- a/drivers/input/joystick/grip.c
+++ b/drivers/input/joystick/grip.c
@@ -370,7 +370,7 @@ static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
input_dev->open = grip_open;
input_dev->close = grip_close;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
for (j = 0; (t = grip_abs[grip->mode[i]][j]) >= 0; j++) {
diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c
index 4ed3a3eadf19..c57e21d68c00 100644
--- a/drivers/input/joystick/grip_mp.c
+++ b/drivers/input/joystick/grip_mp.c
@@ -606,7 +606,7 @@ static int register_slot(int slot, struct grip_mp *grip)
input_dev->open = grip_open;
input_dev->close = grip_close;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
for (j = 0; (t = grip_abs[port->mode][j]) >= 0; j++)
input_set_abs_params(input_dev, t, -1, 1, 0, 0);
diff --git a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c
index d4e8073caf27..aa6bfb3fb8cd 100644
--- a/drivers/input/joystick/guillemot.c
+++ b/drivers/input/joystick/guillemot.c
@@ -238,7 +238,7 @@ static int guillemot_connect(struct gameport *gameport, struct gameport_driver *
input_dev->open = guillemot_open;
input_dev->close = guillemot_close;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
for (i = 0; (t = guillemot->type->abs[i]) >= 0; i++)
input_set_abs_params(input_dev, t, 0, 255, 0, 0);
diff --git a/drivers/input/joystick/iforce/Makefile b/drivers/input/joystick/iforce/Makefile
index 17ae42bf9ffd..74daff49ab6e 100644
--- a/drivers/input/joystick/iforce/Makefile
+++ b/drivers/input/joystick/iforce/Makefile
@@ -1,7 +1,7 @@
#
# Makefile for the I-Force driver
#
-# By Johann Deneux <deneux@ifrance.com>
+# By Johann Deneux <johann.deneux@gmail.com>
#
# Goal definition
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c
index 682244b1c042..6f826b37d9aa 100644
--- a/drivers/input/joystick/iforce/iforce-main.c
+++ b/drivers/input/joystick/iforce/iforce-main.c
@@ -389,7 +389,8 @@ int iforce_init_device(struct iforce *iforce)
* Set input device bitfields and ranges.
*/
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_FF_STATUS);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) |
+ BIT_MASK(EV_FF_STATUS);
for (i = 0; iforce->type->btn[i] >= 0; i++)
set_bit(iforce->type->btn[i], input_dev->keybit);
diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h
index 40a853ac21c7..a964a7cfd210 100644
--- a/drivers/input/joystick/iforce/iforce.h
+++ b/drivers/input/joystick/iforce/iforce.h
@@ -62,13 +62,13 @@
#define FF_CORE_IS_PLAYED 3 /* Effect is currently being played */
#define FF_CORE_SHOULD_PLAY 4 /* User wants the effect to be played */
#define FF_CORE_UPDATE 5 /* Effect is being updated */
-#define FF_MODCORE_MAX 5
+#define FF_MODCORE_CNT 6
struct iforce_core_effect {
/* Information about where modifiers are stored in the device's memory */
struct resource mod1_chunk;
struct resource mod2_chunk;
- unsigned long flags[NBITS(FF_MODCORE_MAX)];
+ unsigned long flags[BITS_TO_LONGS(FF_MODCORE_CNT)];
};
#define FF_CMD_EFFECT 0x010e
diff --git a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c
index 1aec1e9d7c59..bc8ea95dfd0e 100644
--- a/drivers/input/joystick/interact.c
+++ b/drivers/input/joystick/interact.c
@@ -269,7 +269,7 @@ static int interact_connect(struct gameport *gameport, struct gameport_driver *d
input_dev->open = interact_open;
input_dev->close = interact_close;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
for (i = 0; (t = interact_type[interact->type].abs[i]) >= 0; i++) {
set_bit(t, input_dev->absbit);
diff --git a/drivers/input/joystick/magellan.c b/drivers/input/joystick/magellan.c
index b35604ee43ae..54e676948ebb 100644
--- a/drivers/input/joystick/magellan.c
+++ b/drivers/input/joystick/magellan.c
@@ -170,7 +170,7 @@ static int magellan_connect(struct serio *serio, struct serio_driver *drv)
input_dev->id.version = 0x0100;
input_dev->dev.parent = &serio->dev;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
for (i = 0; i < 9; i++)
set_bit(magellan_buttons[i], input_dev->keybit);
diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c
index 2adf73f63c94..7b4865fdee54 100644
--- a/drivers/input/joystick/sidewinder.c
+++ b/drivers/input/joystick/sidewinder.c
@@ -758,7 +758,7 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv)
input_dev->open = sw_open;
input_dev->close = sw_close;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
for (j = 0; (bits = sw_bit[sw->type][j]); j++) {
code = sw_abs[sw->type][j];
diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c
index abb7c4cf54ad..d4087fd49656 100644
--- a/drivers/input/joystick/spaceball.c
+++ b/drivers/input/joystick/spaceball.c
@@ -228,18 +228,23 @@ static int spaceball_connect(struct serio *serio, struct serio_driver *drv)
input_dev->id.version = 0x0100;
input_dev->dev.parent = &serio->dev;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
switch (id) {
case SPACEBALL_4000FLX:
case SPACEBALL_4000FLX_L:
- input_dev->keybit[LONG(BTN_0)] |= BIT(BTN_9);
- input_dev->keybit[LONG(BTN_A)] |= BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C) | BIT(BTN_MODE);
+ input_dev->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_9);
+ input_dev->keybit[BIT_WORD(BTN_A)] |= BIT_MASK(BTN_A) |
+ BIT_MASK(BTN_B) | BIT_MASK(BTN_C) |
+ BIT_MASK(BTN_MODE);
default:
- input_dev->keybit[LONG(BTN_0)] |= BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4)
- | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7) | BIT(BTN_8);
+ input_dev->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_2) |
+ BIT_MASK(BTN_3) | BIT_MASK(BTN_4) |
+ BIT_MASK(BTN_5) | BIT_MASK(BTN_6) |
+ BIT_MASK(BTN_7) | BIT_MASK(BTN_8);
case SPACEBALL_3003C:
- input_dev->keybit[LONG(BTN_0)] |= BIT(BTN_1) | BIT(BTN_8);
+ input_dev->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_1) |
+ BIT_MASK(BTN_8);
}
for (i = 0; i < 3; i++) {
diff --git a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c
index c4937f1e837c..f7ce4004f4ba 100644
--- a/drivers/input/joystick/spaceorb.c
+++ b/drivers/input/joystick/spaceorb.c
@@ -185,7 +185,7 @@ static int spaceorb_connect(struct serio *serio, struct serio_driver *drv)
input_dev->id.version = 0x0100;
input_dev->dev.parent = &serio->dev;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
for (i = 0; i < 6; i++)
set_bit(spaceorb_buttons[i], input_dev->keybit);
diff --git a/drivers/input/joystick/stinger.c b/drivers/input/joystick/stinger.c
index 8581ee991d4e..baa10b2f7ba1 100644
--- a/drivers/input/joystick/stinger.c
+++ b/drivers/input/joystick/stinger.c
@@ -156,10 +156,11 @@ static int stinger_connect(struct serio *serio, struct serio_driver *drv)
input_dev->id.version = 0x0100;
input_dev->dev.parent = &serio->dev;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- input_dev->keybit[LONG(BTN_A)] = BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C) | BIT(BTN_X) |
- BIT(BTN_Y) | BIT(BTN_Z) | BIT(BTN_TL) | BIT(BTN_TR) |
- BIT(BTN_START) | BIT(BTN_SELECT);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ input_dev->keybit[BIT_WORD(BTN_A)] = BIT_MASK(BTN_A) | BIT_MASK(BTN_B) |
+ BIT_MASK(BTN_C) | BIT_MASK(BTN_X) | BIT_MASK(BTN_Y) |
+ BIT_MASK(BTN_Z) | BIT_MASK(BTN_TL) | BIT_MASK(BTN_TR) |
+ BIT_MASK(BTN_START) | BIT_MASK(BTN_SELECT);
input_set_abs_params(input_dev, ABS_X, -64, 64, 0, 4);
input_set_abs_params(input_dev, ABS_Y, -64, 64, 0, 4);
diff --git a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c
index 3b36ee04f726..0feeb8acb532 100644
--- a/drivers/input/joystick/tmdc.c
+++ b/drivers/input/joystick/tmdc.c
@@ -333,7 +333,7 @@ static int tmdc_setup_port(struct tmdc *tmdc, int idx, unsigned char *data)
input_dev->open = tmdc_open;
input_dev->close = tmdc_close;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
for (i = 0; i < port->absc && i < TMDC_ABS; i++)
if (port->abs[i] >= 0)
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c
index 8381c6f14373..bbebd4e2ad7f 100644
--- a/drivers/input/joystick/turbografx.c
+++ b/drivers/input/joystick/turbografx.c
@@ -229,7 +229,7 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
input_dev->open = tgfx_open;
input_dev->close = tgfx_close;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
input_set_abs_params(input_dev, ABS_X, -1, 1, 0, 0);
input_set_abs_params(input_dev, ABS_Y, -1, 1, 0, 0);
diff --git a/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c
index c91504ec38eb..1085c841fec4 100644
--- a/drivers/input/joystick/twidjoy.c
+++ b/drivers/input/joystick/twidjoy.c
@@ -207,7 +207,7 @@ static int twidjoy_connect(struct serio *serio, struct serio_driver *drv)
input_dev->id.version = 0x0100;
input_dev->dev.parent = &serio->dev;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
input_set_abs_params(input_dev, ABS_X, -50, 50, 4, 4);
input_set_abs_params(input_dev, ABS_Y, -50, 50, 4, 4);
diff --git a/drivers/input/joystick/warrior.c b/drivers/input/joystick/warrior.c
index 4e85f72eefd7..e928b6e3724a 100644
--- a/drivers/input/joystick/warrior.c
+++ b/drivers/input/joystick/warrior.c
@@ -162,9 +162,11 @@ static int warrior_connect(struct serio *serio, struct serio_driver *drv)
input_dev->id.version = 0x0100;
input_dev->dev.parent = &serio->dev;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
- input_dev->keybit[LONG(BTN_TRIGGER)] = BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP) | BIT(BTN_TOP2);
- input_dev->relbit[0] = BIT(REL_DIAL);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL) |
+ BIT_MASK(EV_ABS);
+ input_dev->keybit[BIT_WORD(BTN_TRIGGER)] = BIT_MASK(BTN_TRIGGER) |
+ BIT_MASK(BTN_THUMB) | BIT_MASK(BTN_TOP) | BIT_MASK(BTN_TOP2);
+ input_dev->relbit[0] = BIT_MASK(REL_DIAL);
input_set_abs_params(input_dev, ABS_X, -64, 64, 0, 8);
input_set_abs_params(input_dev, ABS_Y, -64, 64, 0, 8);
input_set_abs_params(input_dev, ABS_THROTTLE, -112, 112, 0, 0);
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 28080395899c..6e9d75bd2b15 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -120,6 +120,7 @@ static const struct xpad_device {
{ 0x0738, 0x4536, "Mad Catz MicroCON", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x0738, 0x4540, "Mad Catz Beat Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
{ 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0738, 0x4716, "Mad Catz Wired Xbox 360 Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
{ 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
{ 0x0c12, 0x8802, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x0c12, 0x8810, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
@@ -129,6 +130,7 @@ static const struct xpad_device {
{ 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x0e6f, 0x0005, "Eclipse wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x0e6f, 0x0006, "Edge wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0e6f, 0x0006, "Pelican 'TSZ' Wired Xbox 360 Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
{ 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x0f30, 0x0202, "Joytech Advanced Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x0f30, 0x8888, "BigBen XBMiniPad Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
@@ -223,12 +225,16 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d
struct input_dev *dev = xpad->dev;
/* left stick */
- input_report_abs(dev, ABS_X, (__s16) (((__s16)data[13] << 8) | data[12]));
- input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[15] << 8) | data[14]));
+ input_report_abs(dev, ABS_X,
+ (__s16) le16_to_cpup((__le16 *)(data + 12)));
+ input_report_abs(dev, ABS_Y,
+ (__s16) le16_to_cpup((__le16 *)(data + 14)));
/* right stick */
- input_report_abs(dev, ABS_RX, (__s16) (((__s16)data[17] << 8) | data[16]));
- input_report_abs(dev, ABS_RY, (__s16) (((__s16)data[19] << 8) | data[18]));
+ input_report_abs(dev, ABS_RX,
+ (__s16) le16_to_cpup((__le16 *)(data + 16)));
+ input_report_abs(dev, ABS_RY,
+ (__s16) le16_to_cpup((__le16 *)(data + 18)));
/* triggers left/right */
input_report_abs(dev, ABS_Z, data[10]);
@@ -236,8 +242,10 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d
/* digital pad */
if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) {
- input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04));
- input_report_abs(dev, ABS_HAT0Y, !!(data[2] & 0x02) - !!(data[2] & 0x01));
+ input_report_abs(dev, ABS_HAT0X,
+ !!(data[2] & 0x08) - !!(data[2] & 0x04));
+ input_report_abs(dev, ABS_HAT0Y,
+ !!(data[2] & 0x02) - !!(data[2] & 0x01));
} else /* xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS */ {
input_report_key(dev, BTN_LEFT, data[2] & 0x04);
input_report_key(dev, BTN_RIGHT, data[2] & 0x08);
@@ -274,14 +282,17 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d
* http://www.free60.org/wiki/Gamepad
*/
-static void xpad360_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data)
+static void xpad360_process_packet(struct usb_xpad *xpad,
+ u16 cmd, unsigned char *data)
{
struct input_dev *dev = xpad->dev;
/* digital pad */
if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) {
- input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04));
- input_report_abs(dev, ABS_HAT0Y, !!(data[2] & 0x02) - !!(data[2] & 0x01));
+ input_report_abs(dev, ABS_HAT0X,
+ !!(data[2] & 0x08) - !!(data[2] & 0x04));
+ input_report_abs(dev, ABS_HAT0Y,
+ !!(data[2] & 0x02) - !!(data[2] & 0x01));
} else if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS) {
/* dpad as buttons (right, left, down, up) */
input_report_key(dev, BTN_LEFT, data[2] & 0x04);
@@ -308,12 +319,16 @@ static void xpad360_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char
input_report_key(dev, BTN_MODE, data[3] & 0x04);
/* left stick */
- input_report_abs(dev, ABS_X, (__s16) (((__s16)data[7] << 8) | (__s16)data[6]));
- input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[9] << 8) | (__s16)data[8]));
+ input_report_abs(dev, ABS_X,
+ (__s16) le16_to_cpup((__le16 *)(data + 6)));
+ input_report_abs(dev, ABS_Y,
+ (__s16) le16_to_cpup((__le16 *)(data + 8)));
/* right stick */
- input_report_abs(dev, ABS_RX, (__s16) (((__s16)data[11] << 8) | (__s16)data[10]));
- input_report_abs(dev, ABS_RY, (__s16) (((__s16)data[13] << 8) | (__s16)data[12]));
+ input_report_abs(dev, ABS_RX,
+ (__s16) le16_to_cpup((__le16 *)(data + 10)));
+ input_report_abs(dev, ABS_RY,
+ (__s16) le16_to_cpup((__le16 *)(data + 12)));
/* triggers left/right */
input_report_abs(dev, ABS_Z, data[4]);
@@ -335,10 +350,12 @@ static void xpad_irq_in(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+ dbg("%s - urb shutting down with status: %d",
+ __FUNCTION__, urb->status);
return;
default:
- dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+ dbg("%s - nonzero urb status received: %d",
+ __FUNCTION__, urb->status);
goto exit;
}
@@ -367,10 +384,12 @@ static void xpad_irq_out(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+ dbg("%s - urb shutting down with status: %d",
+ __FUNCTION__, urb->status);
return;
default:
- dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+ dbg("%s - nonzero urb status received: %d",
+ __FUNCTION__, urb->status);
goto exit;
}
@@ -378,7 +397,7 @@ exit:
retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
err("%s - usb_submit_urb failed with result %d",
- __FUNCTION__, retval);
+ __FUNCTION__, retval);
}
static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
@@ -595,7 +614,7 @@ static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs)
static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
- struct usb_device *udev = interface_to_usbdev (intf);
+ struct usb_device *udev = interface_to_usbdev(intf);
struct usb_xpad *xpad;
struct input_dev *input_dev;
struct usb_endpoint_descriptor *ep_irq_in;
@@ -641,7 +660,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
input_dev->open = xpad_open;
input_dev->close = xpad_close;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
/* set up buttons */
for (i = 0; xpad_btn[i] >= 0; i++)
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index c97d5eb0075d..2316a018fae6 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -208,6 +208,27 @@ config KEYBOARD_HIL
This driver implements support for HIL-keyboards attached
to your machine, so normally you should say Y here.
+config KEYBOARD_HP6XX
+ tristate "HP Jornada 6XX Keyboard support"
+ depends on SH_HP6XX
+ select INPUT_POLLDEV
+ help
+ This adds support for the onboard keyboard found on
+ HP Jornada 620/660/680/690.
+
+ To compile this driver as a module, choose M here: the
+ module will be called jornada680_kbd.
+
+config KEYBOARD_HP7XX
+ tristate "HP Jornada 7XX Keyboard Driver"
+ depends on SA1100_JORNADA720_SSP && SA1100_SSP
+ help
+ Say Y here to add support for the HP Jornada 7xx (710/720/728)
+ onboard keyboard.
+
+ To compile this driver as a module, choose M here: the
+ module will be called jornada720_kbd.
+
config KEYBOARD_OMAP
tristate "TI OMAP keypad support"
depends on (ARCH_OMAP1 || ARCH_OMAP2)
@@ -253,4 +274,23 @@ config KEYBOARD_GPIO
To compile this driver as a module, choose M here: the
module will be called gpio-keys.
+config KEYBOARD_MAPLE
+ tristate "Maple bus keyboard"
+ depends on SH_DREAMCAST && MAPLE
+ help
+ Say Y here if you have a Dreamcast console running Linux and have
+ a keyboard attached to its Maple bus.
+
+ To compile this driver as a module, choose M here: the
+ module will be called maple_keyb.
+
+config KEYBOARD_BFIN
+ tristate "Blackfin BF54x keypad support"
+ depends on BF54x
+ help
+ Say Y here if you want to use the BF54x keypad.
+
+ To compile this driver as a module, choose M here: the
+ module will be called bf54x-keys.
+
endif
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 28d211b87b14..e97455fdcc83 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -21,4 +21,7 @@ obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o
obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keyboard.o
obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o
obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o
-
+obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o
+obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o
+obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o
+obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o
diff --git a/drivers/input/keyboard/aaed2000_kbd.c b/drivers/input/keyboard/aaed2000_kbd.c
index 63d6ead6b877..72abc196ce66 100644
--- a/drivers/input/keyboard/aaed2000_kbd.c
+++ b/drivers/input/keyboard/aaed2000_kbd.c
@@ -125,7 +125,7 @@ static int __devinit aaedkbd_probe(struct platform_device *pdev)
input_dev->id.version = 0x0100;
input_dev->dev.parent = &pdev->dev;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
input_dev->keycode = aaedkbd->keycode;
input_dev->keycodesize = sizeof(unsigned char);
input_dev->keycodemax = ARRAY_SIZE(aaedkbd_keycode);
diff --git a/drivers/input/keyboard/amikbd.c b/drivers/input/keyboard/amikbd.c
index c67e84ec2d6a..81bf7562aca0 100644
--- a/drivers/input/keyboard/amikbd.c
+++ b/drivers/input/keyboard/amikbd.c
@@ -209,7 +209,7 @@ static int __init amikbd_init(void)
amikbd_dev->id.product = 0x0001;
amikbd_dev->id.version = 0x0100;
- amikbd_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ amikbd_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
for (i = 0; i < 0x78; i++)
set_bit(i, amikbd_dev->keybit);
diff --git a/drivers/input/keyboard/atakbd.c b/drivers/input/keyboard/atakbd.c
index a1800151b6ce..4e92100c56a8 100644
--- a/drivers/input/keyboard/atakbd.c
+++ b/drivers/input/keyboard/atakbd.c
@@ -237,7 +237,7 @@ static int __init atakbd_init(void)
atakbd_dev->id.product = 0x0001;
atakbd_dev->id.version = 0x0100;
- atakbd_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ atakbd_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
atakbd_dev->keycode = atakbd_keycode;
atakbd_dev->keycodesize = sizeof(unsigned char);
atakbd_dev->keycodemax = ARRAY_SIZE(atakbd_keycode);
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index 41fc3d03b6eb..b39c5b31e620 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -900,27 +900,32 @@ static void atkbd_set_device_attrs(struct atkbd *atkbd)
input_set_drvdata(input_dev, atkbd);
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_MSC);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) |
+ BIT_MASK(EV_MSC);
if (atkbd->write) {
- input_dev->evbit[0] |= BIT(EV_LED);
- input_dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
+ input_dev->evbit[0] |= BIT_MASK(EV_LED);
+ input_dev->ledbit[0] = BIT_MASK(LED_NUML) |
+ BIT_MASK(LED_CAPSL) | BIT_MASK(LED_SCROLLL);
}
if (atkbd->extra)
- input_dev->ledbit[0] |= BIT(LED_COMPOSE) | BIT(LED_SUSPEND) |
- BIT(LED_SLEEP) | BIT(LED_MUTE) | BIT(LED_MISC);
+ input_dev->ledbit[0] |= BIT_MASK(LED_COMPOSE) |
+ BIT_MASK(LED_SUSPEND) | BIT_MASK(LED_SLEEP) |
+ BIT_MASK(LED_MUTE) | BIT_MASK(LED_MISC);
if (!atkbd->softrepeat) {
input_dev->rep[REP_DELAY] = 250;
input_dev->rep[REP_PERIOD] = 33;
}
- input_dev->mscbit[0] = atkbd->softraw ? BIT(MSC_SCAN) : BIT(MSC_RAW) | BIT(MSC_SCAN);
+ input_dev->mscbit[0] = atkbd->softraw ? BIT_MASK(MSC_SCAN) :
+ BIT_MASK(MSC_RAW) | BIT_MASK(MSC_SCAN);
if (atkbd->scroll) {
- input_dev->evbit[0] |= BIT(EV_REL);
- input_dev->relbit[0] = BIT(REL_WHEEL) | BIT(REL_HWHEEL);
+ input_dev->evbit[0] |= BIT_MASK(EV_REL);
+ input_dev->relbit[0] = BIT_MASK(REL_WHEEL) |
+ BIT_MASK(REL_HWHEEL);
set_bit(BTN_MIDDLE, input_dev->keybit);
}
diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c
new file mode 100644
index 000000000000..e5f4da928340
--- /dev/null
+++ b/drivers/input/keyboard/bf54x-keys.c
@@ -0,0 +1,381 @@
+/*
+ * File: drivers/input/keyboard/bf54x-keys.c
+ * Based on:
+ * Author: Michael Hennerich <hennerich@blackfin.uclinux.org>
+ *
+ * Created:
+ * Description: keypad driver for Analog Devices Blackfin BF54x Processors
+ *
+ *
+ * Modified:
+ * Copyright 2007 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/sched.h>
+#include <linux/pm.h>
+#include <linux/sysctl.h>
+#include <linux/proc_fs.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/irq.h>
+
+#include <asm/portmux.h>
+#include <asm/mach/bf54x_keys.h>
+
+#define DRV_NAME "bf54x-keys"
+#define TIME_SCALE 100 /* 100 ns */
+#define MAX_MULT (0xFF * TIME_SCALE)
+#define MAX_RC 8 /* Max Row/Col */
+
+static const u16 per_rows[] = {
+ P_KEY_ROW7,
+ P_KEY_ROW6,
+ P_KEY_ROW5,
+ P_KEY_ROW4,
+ P_KEY_ROW3,
+ P_KEY_ROW2,
+ P_KEY_ROW1,
+ P_KEY_ROW0,
+ 0
+};
+
+static const u16 per_cols[] = {
+ P_KEY_COL7,
+ P_KEY_COL6,
+ P_KEY_COL5,
+ P_KEY_COL4,
+ P_KEY_COL3,
+ P_KEY_COL2,
+ P_KEY_COL1,
+ P_KEY_COL0,
+ 0
+};
+
+struct bf54x_kpad {
+ struct input_dev *input;
+ int irq;
+ unsigned short lastkey;
+ unsigned short *keycode;
+ struct timer_list timer;
+ unsigned int keyup_test_jiffies;
+};
+
+static inline int bfin_kpad_find_key(struct bf54x_kpad *bf54x_kpad,
+ struct input_dev *input, u16 keyident)
+{
+ u16 i;
+
+ for (i = 0; i < input->keycodemax; i++)
+ if (bf54x_kpad->keycode[i + input->keycodemax] == keyident)
+ return bf54x_kpad->keycode[i];
+ return -1;
+}
+
+static inline void bfin_keycodecpy(unsigned short *keycode,
+ const unsigned int *pdata_kc,
+ unsigned short keymapsize)
+{
+ unsigned int i;
+
+ for (i = 0; i < keymapsize; i++) {
+ keycode[i] = pdata_kc[i] & 0xffff;
+ keycode[i + keymapsize] = pdata_kc[i] >> 16;
+ }
+}
+
+static inline u16 bfin_kpad_get_prescale(u32 timescale)
+{
+ u32 sclk = get_sclk();
+
+ return ((((sclk / 1000) * timescale) / 1024) - 1);
+}
+
+static inline u16 bfin_kpad_get_keypressed(struct bf54x_kpad *bf54x_kpad)
+{
+ return (bfin_read_KPAD_STAT() & KPAD_PRESSED);
+}
+
+static inline void bfin_kpad_clear_irq(void)
+{
+ bfin_write_KPAD_STAT(0xFFFF);
+ bfin_write_KPAD_ROWCOL(0xFFFF);
+}
+
+static void bfin_kpad_timer(unsigned long data)
+{
+ struct platform_device *pdev = (struct platform_device *) data;
+ struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev);
+
+ if (bfin_kpad_get_keypressed(bf54x_kpad)) {
+ /* Try again later */
+ mod_timer(&bf54x_kpad->timer,
+ jiffies + bf54x_kpad->keyup_test_jiffies);
+ return;
+ }
+
+ input_report_key(bf54x_kpad->input, bf54x_kpad->lastkey, 0);
+ input_sync(bf54x_kpad->input);
+
+ /* Clear IRQ Status */
+
+ bfin_kpad_clear_irq();
+ enable_irq(bf54x_kpad->irq);
+}
+
+static irqreturn_t bfin_kpad_isr(int irq, void *dev_id)
+{
+ struct platform_device *pdev = dev_id;
+ struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev);
+ struct input_dev *input = bf54x_kpad->input;
+ int key;
+ u16 rowcol = bfin_read_KPAD_ROWCOL();
+
+ key = bfin_kpad_find_key(bf54x_kpad, input, rowcol);
+
+ input_report_key(input, key, 1);
+ input_sync(input);
+
+ if (bfin_kpad_get_keypressed(bf54x_kpad)) {
+ disable_irq(bf54x_kpad->irq);
+ bf54x_kpad->lastkey = key;
+ mod_timer(&bf54x_kpad->timer,
+ jiffies + bf54x_kpad->keyup_test_jiffies);
+ } else {
+ input_report_key(input, key, 0);
+ input_sync(input);
+
+ bfin_kpad_clear_irq();
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int __devinit bfin_kpad_probe(struct platform_device *pdev)
+{
+ struct bf54x_kpad *bf54x_kpad;
+ struct bfin_kpad_platform_data *pdata = pdev->dev.platform_data;
+ struct input_dev *input;
+ int i, error;
+
+ if (!pdata->rows || !pdata->cols || !pdata->keymap) {
+ printk(KERN_ERR DRV_NAME
+ ": No rows, cols or keymap from pdata\n");
+ return -EINVAL;
+ }
+
+ if (!pdata->keymapsize ||
+ pdata->keymapsize > (pdata->rows * pdata->cols)) {
+ printk(KERN_ERR DRV_NAME ": Invalid keymapsize\n");
+ return -EINVAL;
+ }
+
+ bf54x_kpad = kzalloc(sizeof(struct bf54x_kpad), GFP_KERNEL);
+ if (!bf54x_kpad)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, bf54x_kpad);
+
+ /* Allocate memory for keymap followed by private LUT */
+ bf54x_kpad->keycode = kmalloc(pdata->keymapsize *
+ sizeof(unsigned short) * 2, GFP_KERNEL);
+ if (!bf54x_kpad->keycode) {
+ error = -ENOMEM;
+ goto out;
+ }
+
+ if (!pdata->debounce_time || !pdata->debounce_time > MAX_MULT ||
+ !pdata->coldrive_time || !pdata->coldrive_time > MAX_MULT) {
+ printk(KERN_ERR DRV_NAME
+ ": Invalid Debounce/Columdrive Time from pdata\n");
+ bfin_write_KPAD_MSEL(0xFF0); /* Default MSEL */
+ } else {
+ bfin_write_KPAD_MSEL(
+ ((pdata->debounce_time / TIME_SCALE)
+ & DBON_SCALE) |
+ (((pdata->coldrive_time / TIME_SCALE) << 8)
+ & COLDRV_SCALE));
+
+ }
+
+ if (!pdata->keyup_test_interval)
+ bf54x_kpad->keyup_test_jiffies = msecs_to_jiffies(50);
+ else
+ bf54x_kpad->keyup_test_jiffies =
+ msecs_to_jiffies(pdata->keyup_test_interval);
+
+ if (peripheral_request_list((u16 *)&per_rows[MAX_RC - pdata->rows],
+ DRV_NAME)) {
+ printk(KERN_ERR DRV_NAME
+ ": Requesting Peripherals failed\n");
+ error = -EFAULT;
+ goto out0;
+ }
+
+ if (peripheral_request_list((u16 *)&per_cols[MAX_RC - pdata->cols],
+ DRV_NAME)) {
+ printk(KERN_ERR DRV_NAME
+ ": Requesting Peripherals failed\n");
+ error = -EFAULT;
+ goto out1;
+ }
+
+ bf54x_kpad->irq = platform_get_irq(pdev, 0);
+ if (bf54x_kpad->irq < 0) {
+ error = -ENODEV;
+ goto out2;
+ }
+
+ error = request_irq(bf54x_kpad->irq, bfin_kpad_isr,
+ IRQF_SAMPLE_RANDOM, DRV_NAME, pdev);
+ if (error) {
+ printk(KERN_ERR DRV_NAME
+ ": unable to claim irq %d; error %d\n",
+ bf54x_kpad->irq, error);
+ goto out2;
+ }
+
+ input = input_allocate_device();
+ if (!input) {
+ error = -ENOMEM;
+ goto out3;
+ }
+
+ bf54x_kpad->input = input;
+
+ input->name = pdev->name;
+ input->phys = "bf54x-keys/input0";
+ input->dev.parent = &pdev->dev;
+
+ input_set_drvdata(input, bf54x_kpad);
+
+ input->id.bustype = BUS_HOST;
+ input->id.vendor = 0x0001;
+ input->id.product = 0x0001;
+ input->id.version = 0x0100;
+
+ input->keycodesize = sizeof(unsigned short);
+ input->keycodemax = pdata->keymapsize;
+ input->keycode = bf54x_kpad->keycode;
+
+ bfin_keycodecpy(bf54x_kpad->keycode, pdata->keymap, pdata->keymapsize);
+
+ /* setup input device */
+ __set_bit(EV_KEY, input->evbit);
+
+ if (pdata->repeat)
+ __set_bit(EV_REP, input->evbit);
+
+ for (i = 0; i < input->keycodemax; i++)
+ __set_bit(bf54x_kpad->keycode[i] & KEY_MAX, input->keybit);
+ __clear_bit(KEY_RESERVED, input->keybit);
+
+ error = input_register_device(input);
+ if (error) {
+ printk(KERN_ERR DRV_NAME
+ ": Unable to register input device (%d)\n", error);
+ goto out4;
+ }
+
+ /* Init Keypad Key Up/Release test timer */
+
+ setup_timer(&bf54x_kpad->timer, bfin_kpad_timer, (unsigned long) pdev);
+
+ bfin_write_KPAD_PRESCALE(bfin_kpad_get_prescale(TIME_SCALE));
+
+ bfin_write_KPAD_CTL((((pdata->cols - 1) << 13) & KPAD_COLEN) |
+ (((pdata->rows - 1) << 10) & KPAD_ROWEN) |
+ (2 & KPAD_IRQMODE));
+
+ bfin_write_KPAD_CTL(bfin_read_KPAD_CTL() | KPAD_EN);
+
+ printk(KERN_ERR DRV_NAME
+ ": Blackfin BF54x Keypad registered IRQ %d\n", bf54x_kpad->irq);
+
+ return 0;
+
+out4:
+ input_free_device(input);
+out3:
+ free_irq(bf54x_kpad->irq, pdev);
+out2:
+ peripheral_free_list((u16 *)&per_cols[MAX_RC - pdata->cols]);
+out1:
+ peripheral_free_list((u16 *)&per_rows[MAX_RC - pdata->rows]);
+out0:
+ kfree(bf54x_kpad->keycode);
+out:
+ kfree(bf54x_kpad);
+ platform_set_drvdata(pdev, NULL);
+
+ return error;
+}
+
+static int __devexit bfin_kpad_remove(struct platform_device *pdev)
+{
+ struct bfin_kpad_platform_data *pdata = pdev->dev.platform_data;
+ struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev);
+
+ del_timer_sync(&bf54x_kpad->timer);
+ free_irq(bf54x_kpad->irq, pdev);
+
+ input_unregister_device(bf54x_kpad->input);
+
+ peripheral_free_list((u16 *)&per_rows[MAX_RC - pdata->rows]);
+ peripheral_free_list((u16 *)&per_cols[MAX_RC - pdata->cols]);
+
+ kfree(bf54x_kpad->keycode);
+ kfree(bf54x_kpad);
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+struct platform_driver bfin_kpad_device_driver = {
+ .probe = bfin_kpad_probe,
+ .remove = __devexit_p(bfin_kpad_remove),
+ .driver = {
+ .name = DRV_NAME,
+ }
+};
+
+static int __init bfin_kpad_init(void)
+{
+ return platform_driver_register(&bfin_kpad_device_driver);
+}
+
+static void __exit bfin_kpad_exit(void)
+{
+ platform_driver_unregister(&bfin_kpad_device_driver);
+}
+
+module_init(bfin_kpad_init);
+module_exit(bfin_kpad_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("Keypad driver for BF54x Processors");
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c
index 6578bfff644b..790fed368aae 100644
--- a/drivers/input/keyboard/corgikbd.c
+++ b/drivers/input/keyboard/corgikbd.c
@@ -325,7 +325,8 @@ static int __init corgikbd_probe(struct platform_device *pdev)
input_dev->id.version = 0x0100;
input_dev->dev.parent = &pdev->dev;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) |
+ BIT_MASK(EV_PWR) | BIT_MASK(EV_SW);
input_dev->keycode = corgikbd->keycode;
input_dev->keycodesize = sizeof(unsigned char);
input_dev->keycodemax = ARRAY_SIZE(corgikbd_keycode);
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index f0b22b8b2769..3eddf52a0bba 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -54,6 +54,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
struct input_dev *input;
int i, error;
+ int wakeup = 0;
input = input_allocate_device();
if (!input)
@@ -61,7 +62,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, input);
- input->evbit[0] = BIT(EV_KEY);
+ input->evbit[0] = BIT_MASK(EV_KEY);
input->name = pdev->name;
input->phys = "gpio-keys/input0";
@@ -77,31 +78,51 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
int irq = gpio_to_irq(button->gpio);
unsigned int type = button->type ?: EV_KEY;
- set_irq_type(irq, IRQ_TYPE_EDGE_BOTH);
- error = request_irq(irq, gpio_keys_isr, IRQF_SAMPLE_RANDOM,
- button->desc ? button->desc : "gpio_keys",
- pdev);
+ if (irq < 0) {
+ error = irq;
+ printk(KERN_ERR
+ "gpio-keys: "
+ "Unable to get irq number for GPIO %d,"
+ "error %d\n",
+ button->gpio, error);
+ goto fail;
+ }
+
+ error = request_irq(irq, gpio_keys_isr,
+ IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING,
+ button->desc ? button->desc : "gpio_keys",
+ pdev);
if (error) {
- printk(KERN_ERR "gpio-keys: unable to claim irq %d; error %d\n",
+ printk(KERN_ERR
+ "gpio-keys: Unable to claim irq %d; error %d\n",
irq, error);
goto fail;
}
+ if (button->wakeup)
+ wakeup = 1;
+
input_set_capability(input, type, button->code);
}
error = input_register_device(input);
if (error) {
- printk(KERN_ERR "Unable to register gpio-keys input device\n");
+ printk(KERN_ERR
+ "gpio-keys: Unable to register input device, "
+ "error: %d\n", error);
goto fail;
}
+ device_init_wakeup(&pdev->dev, wakeup);
+
return 0;
fail:
- for (i = i - 1; i >= 0; i--)
+ while (--i >= 0)
free_irq(gpio_to_irq(pdata->buttons[i].gpio), pdev);
+ platform_set_drvdata(pdev, NULL);
input_free_device(input);
return error;
@@ -113,6 +134,8 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev)
struct input_dev *input = platform_get_drvdata(pdev);
int i;
+ device_init_wakeup(&pdev->dev, 0);
+
for (i = 0; i < pdata->nbuttons; i++) {
int irq = gpio_to_irq(pdata->buttons[i].gpio);
free_irq(irq, pdev);
@@ -123,9 +146,53 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev)
return 0;
}
+
+#ifdef CONFIG_PM
+static int gpio_keys_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
+ int i;
+
+ if (device_may_wakeup(&pdev->dev)) {
+ for (i = 0; i < pdata->nbuttons; i++) {
+ struct gpio_keys_button *button = &pdata->buttons[i];
+ if (button->wakeup) {
+ int irq = gpio_to_irq(button->gpio);
+ enable_irq_wake(irq);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int gpio_keys_resume(struct platform_device *pdev)
+{
+ struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
+ int i;
+
+ if (device_may_wakeup(&pdev->dev)) {
+ for (i = 0; i < pdata->nbuttons; i++) {
+ struct gpio_keys_button *button = &pdata->buttons[i];
+ if (button->wakeup) {
+ int irq = gpio_to_irq(button->gpio);
+ disable_irq_wake(irq);
+ }
+ }
+ }
+
+ return 0;
+}
+#else
+#define gpio_keys_suspend NULL
+#define gpio_keys_resume NULL
+#endif
+
struct platform_driver gpio_keys_device_driver = {
.probe = gpio_keys_probe,
.remove = __devexit_p(gpio_keys_remove),
+ .suspend = gpio_keys_suspend,
+ .resume = gpio_keys_resume,
.driver = {
.name = "gpio-keys",
}
diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c
index cdd254f2e6c7..adbf29f0169d 100644
--- a/drivers/input/keyboard/hil_kbd.c
+++ b/drivers/input/keyboard/hil_kbd.c
@@ -323,8 +323,9 @@ static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv)
goto bail2;
}
- kbd->dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
- kbd->dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
+ kbd->dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
+ kbd->dev->ledbit[0] = BIT_MASK(LED_NUML) | BIT_MASK(LED_CAPSL) |
+ BIT_MASK(LED_SCROLLL);
kbd->dev->keycodemax = HIL_KEYCODES_SET1_TBLSIZE;
kbd->dev->keycodesize = sizeof(hil_kbd_set1[0]);
kbd->dev->keycode = hil_kbd_set1;
diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c
index 499b6974457f..50d80ecf0b80 100644
--- a/drivers/input/keyboard/hilkbd.c
+++ b/drivers/input/keyboard/hilkbd.c
@@ -266,8 +266,9 @@ hil_keyb_init(void)
if (hphilkeyb_keycode[i] != KEY_RESERVED)
set_bit(hphilkeyb_keycode[i], hil_dev.dev->keybit);
- hil_dev.dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
- hil_dev.dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
+ hil_dev.dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
+ hil_dev.dev->ledbit[0] = BIT_MASK(LED_NUML) | BIT_MASK(LED_CAPSL) |
+ BIT_MASK(LED_SCROLLL);
hil_dev.dev->keycodemax = HIL_KEYCODES_SET1_TBLSIZE;
hil_dev.dev->keycodesize= sizeof(hphilkeyb_keycode[0]);
hil_dev.dev->keycode = hphilkeyb_keycode;
diff --git a/drivers/input/keyboard/jornada680_kbd.c b/drivers/input/keyboard/jornada680_kbd.c
new file mode 100644
index 000000000000..bec1cf483723
--- /dev/null
+++ b/drivers/input/keyboard/jornada680_kbd.c
@@ -0,0 +1,277 @@
+/*
+ * drivers/input/keyboard/jornada680_kbd.c
+ *
+ * HP Jornada 620/660/680/690 scan keyboard platform driver
+ * Copyright (C) 2007 Kristoffer Ericson <Kristoffer.Ericson@gmail.com>
+ *
+ * Based on hp680_keyb.c
+ * Copyright (C) 2006 Paul Mundt
+ * Copyright (C) 2005 Andriy Skulysh
+ * Split from drivers/input/keyboard/hp600_keyb.c
+ * Copyright (C) 2000 Yaegashi Takeshi (hp6xx kbd scan routine and translation table)
+ * Copyright (C) 2000 Niibe Yutaka (HP620 Keyb translation table)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/input.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/input-polldev.h>
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+
+#include <asm/delay.h>
+#include <asm/io.h>
+
+#define PCCR 0xa4000104
+#define PDCR 0xa4000106
+#define PECR 0xa4000108
+#define PFCR 0xa400010a
+#define PCDR 0xa4000124
+#define PDDR 0xa4000126
+#define PEDR 0xa4000128
+#define PFDR 0xa400012a
+#define PGDR 0xa400012c
+#define PHDR 0xa400012e
+#define PJDR 0xa4000130
+#define PKDR 0xa4000132
+#define PLDR 0xa4000134
+
+static const unsigned short jornada_scancodes[] = {
+/* PTD1 */ KEY_CAPSLOCK, KEY_MACRO, KEY_LEFTCTRL, 0, KEY_ESC, 0, 0, 0, /* 1 -> 8 */
+ KEY_F1, KEY_F2, KEY_F3, KEY_F8, KEY_F7, KEY_F2, KEY_F4, KEY_F5, /* 9 -> 16 */
+/* PTD5 */ KEY_SLASH, KEY_APOSTROPHE, KEY_ENTER, 0, KEY_Z, 0, 0, 0, /* 17 -> 24 */
+ KEY_X, KEY_C, KEY_V, KEY_DOT, KEY_COMMA, KEY_M, KEY_B, KEY_N, /* 25 -> 32 */
+/* PTD7 */ KEY_KP2, KEY_KP6, 0, 0, 0, 0, 0, 0, /* 33 -> 40 */
+ 0, 0, 0, KEY_KP4, 0, 0, KEY_LEFTALT, KEY_HANJA, /* 41 -> 48 */
+/* PTE0 */ 0, 0, 0, 0, KEY_FINANCE, 0, 0, 0, /* 49 -> 56 */
+ KEY_LEFTCTRL, 0, KEY_SPACE, KEY_KPDOT, KEY_VOLUMEUP, 249, 0, 0, /* 57 -> 64 */
+/* PTE1 */ KEY_SEMICOLON, KEY_RIGHTBRACE, KEY_BACKSLASH, 0, KEY_A, 0, 0, 0,/* 65 -> 72 */
+ KEY_S, KEY_D, KEY_F, KEY_L, KEY_K, KEY_J, KEY_G, KEY_H, /* 73 -> 80 */
+/* PTE3 */ KEY_KP8, KEY_LEFTMETA, KEY_RIGHTSHIFT, 0, KEY_TAB, 0, 0,0, /* 81 -> 88 */
+ 0, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0, /* 89 -> 96 */
+/* PTE6 */ KEY_P, KEY_LEFTBRACE, KEY_BACKSPACE, 0, KEY_Q, 0, 0, 0, /* 97 -> 104 */
+ KEY_W, KEY_E, KEY_R, KEY_O, KEY_I, KEY_U, KEY_T, KEY_R, /* 105 -> 112 */
+/* PTE7 */ KEY_0, KEY_MINUS, KEY_EQUAL, 0, KEY_1, 0, 0, 0, /* 113 -> 120 */
+ KEY_2, KEY_3, KEY_4, KEY_9, KEY_8, KEY_7, KEY_5, KEY_6, /* 121 -> 128 */
+/* **** */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0
+};
+
+#define JORNADA_SCAN_SIZE 18
+
+struct jornadakbd {
+ struct input_polled_dev *poll_dev;
+ unsigned short keymap[ARRAY_SIZE(jornada_scancodes)];
+ unsigned char length;
+ unsigned char old_scan[JORNADA_SCAN_SIZE];
+ unsigned char new_scan[JORNADA_SCAN_SIZE];
+};
+
+static void jornada_parse_kbd(struct jornadakbd *jornadakbd)
+{
+ struct input_dev *input_dev = jornadakbd->poll_dev->input;
+ unsigned short *keymap = jornadakbd->keymap;
+ unsigned int sync_me = 0;
+ unsigned int i, j;
+
+ for (i = 0; i < JORNADA_SCAN_SIZE; i++) {
+ unsigned char new = jornadakbd->new_scan[i];
+ unsigned char old = jornadakbd->old_scan[i];
+ unsigned int xor = new ^ old;
+
+ if (xor == 0)
+ continue;
+
+ for (j = 0; j < 8; j++) {
+ unsigned int bit = 1 << j;
+ if (xor & bit) {
+ unsigned int scancode = (i << 3) + j;
+ input_event(input_dev,
+ EV_MSC, MSC_SCAN, scancode);
+ input_report_key(input_dev,
+ keymap[scancode],
+ !(new & bit));
+ sync_me = 1;
+ }
+ }
+ }
+
+ if (sync_me)
+ input_sync(input_dev);
+}
+
+static void jornada_scan_keyb(unsigned char *s)
+{
+ int i;
+ unsigned short ec_static, dc_static; /* = UINT16_t */
+ unsigned char matrix_switch[] = {
+ 0xfd, 0xff, /* PTD1 PD(1) */
+ 0xdf, 0xff, /* PTD5 PD(5) */
+ 0x7f, 0xff, /* PTD7 PD(7) */
+ 0xff, 0xfe, /* PTE0 PE(0) */
+ 0xff, 0xfd, /* PTE1 PE(1) */
+ 0xff, 0xf7, /* PTE3 PE(3) */
+ 0xff, 0xbf, /* PTE6 PE(6) */
+ 0xff, 0x7f, /* PTE7 PE(7) */
+ }, *t = matrix_switch;
+ /* PD(x) :
+ 1. 0xcc0c & (1~(1 << (2*(x)+1)))))
+ 2. (0xf0cf & 0xfffff) */
+ /* PE(x) :
+ 1. 0xcc0c & 0xffff
+ 2. 0xf0cf & (1~(1 << (2*(x)+1))))) */
+ unsigned short matrix_PDE[] = {
+ 0xcc04, 0xf0cf, /* PD(1) */
+ 0xc40c, 0xf0cf, /* PD(5) */
+ 0x4c0c, 0xf0cf, /* PD(7) */
+ 0xcc0c, 0xf0cd, /* PE(0) */
+ 0xcc0c, 0xf0c7, /* PE(1) */
+ 0xcc0c, 0xf04f, /* PE(3) */
+ 0xcc0c, 0xd0cf, /* PE(6) */
+ 0xcc0c, 0x70cf, /* PE(7) */
+ }, *y = matrix_PDE;
+
+ /* Save these control reg bits */
+ dc_static = (ctrl_inw(PDCR) & (~0xcc0c));
+ ec_static = (ctrl_inw(PECR) & (~0xf0cf));
+
+ for (i = 0; i < 8; i++) {
+ /* disable output for all but the one we want to scan */
+ ctrl_outw((dc_static | *y++), PDCR);
+ ctrl_outw((ec_static | *y++), PECR);
+ udelay(5);
+
+ /* Get scanline row */
+ ctrl_outb(*t++, PDDR);
+ ctrl_outb(*t++, PEDR);
+ udelay(50);
+
+ /* Read data */
+ *s++ = ctrl_inb(PCDR);
+ *s++ = ctrl_inb(PFDR);
+ }
+ /* Scan no lines */
+ ctrl_outb(0xff, PDDR);
+ ctrl_outb(0xff, PEDR);
+
+ /* Enable all scanlines */
+ ctrl_outw((dc_static | (0x5555 & 0xcc0c)),PDCR);
+ ctrl_outw((ec_static | (0x5555 & 0xf0cf)),PECR);
+
+ /* Ignore extra keys and events */
+ *s++ = ctrl_inb(PGDR);
+ *s++ = ctrl_inb(PHDR);
+}
+
+static void jornadakbd680_poll(struct input_polled_dev *dev)
+{
+ struct jornadakbd *jornadakbd = dev->private;
+
+ jornada_scan_keyb(jornadakbd->new_scan);
+ jornada_parse_kbd(jornadakbd);
+ memcpy(jornadakbd->old_scan, jornadakbd->new_scan, JORNADA_SCAN_SIZE);
+}
+
+static int __devinit jornada680kbd_probe(struct platform_device *pdev)
+{
+ struct jornadakbd *jornadakbd;
+ struct input_polled_dev *poll_dev;
+ struct input_dev *input_dev;
+ int i, error;
+
+ jornadakbd = kzalloc(sizeof(struct jornadakbd), GFP_KERNEL);
+ if (!jornadakbd)
+ return -ENOMEM;
+
+ poll_dev = input_allocate_polled_device();
+ if (!poll_dev) {
+ error = -ENOMEM;
+ goto failed;
+ }
+
+ platform_set_drvdata(pdev, jornadakbd);
+
+ jornadakbd->poll_dev = poll_dev;
+
+ memcpy(jornadakbd->keymap, jornada_scancodes,
+ sizeof(jornadakbd->keymap));
+
+ poll_dev->private = jornadakbd;
+ poll_dev->poll = jornadakbd680_poll;
+ poll_dev->poll_interval = 50; /* msec */
+
+ input_dev = poll_dev->input;
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ input_dev->name = "HP Jornada 680 keyboard";
+ input_dev->phys = "jornadakbd/input0";
+ input_dev->keycode = jornadakbd->keymap;
+ input_dev->keycodesize = sizeof(unsigned short);
+ input_dev->keycodemax = ARRAY_SIZE(jornada_scancodes);
+ input_dev->dev.parent = &pdev->dev;
+ input_dev->id.bustype = BUS_HOST;
+
+ for (i = 0; i < 128; i++)
+ if (jornadakbd->keymap[i])
+ __set_bit(jornadakbd->keymap[i], input_dev->keybit);
+ __clear_bit(KEY_RESERVED, input_dev->keybit);
+
+ input_set_capability(input_dev, EV_MSC, MSC_SCAN);
+
+ error = input_register_polled_device(jornadakbd->poll_dev);
+ if (error)
+ goto failed;
+
+ return 0;
+
+ failed:
+ printk(KERN_ERR "Jornadakbd: failed to register driver, error: %d\n",
+ error);
+ platform_set_drvdata(pdev, NULL);
+ input_free_polled_device(poll_dev);
+ kfree(jornadakbd);
+ return error;
+
+}
+
+static int __devexit jornada680kbd_remove(struct platform_device *pdev)
+{
+ struct jornadakbd *jornadakbd = platform_get_drvdata(pdev);
+
+ platform_set_drvdata(pdev, NULL);
+ input_unregister_polled_device(jornadakbd->poll_dev);
+ input_free_polled_device(jornadakbd->poll_dev);
+ kfree(jornadakbd);
+
+ return 0;
+}
+
+static struct platform_driver jornada680kbd_driver = {
+ .driver = {
+ .name = "jornada680_kbd",
+ },
+ .probe = jornada680kbd_probe,
+ .remove = __devexit_p(jornada680kbd_remove),
+};
+
+static int __init jornada680kbd_init(void)
+{
+ return platform_driver_register(&jornada680kbd_driver);
+}
+
+static void __exit jornada680kbd_exit(void)
+{
+ platform_driver_unregister(&jornada680kbd_driver);
+}
+
+module_init(jornada680kbd_init);
+module_exit(jornada680kbd_exit);
+
+MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>");
+MODULE_DESCRIPTION("HP Jornada 620/660/680/690 Keyboard Driver");
+MODULE_LICENSE("GPLv2");
diff --git a/drivers/input/keyboard/jornada720_kbd.c b/drivers/input/keyboard/jornada720_kbd.c
new file mode 100644
index 000000000000..e6696b3c9416
--- /dev/null
+++ b/drivers/input/keyboard/jornada720_kbd.c
@@ -0,0 +1,185 @@
+/*
+ * drivers/input/keyboard/jornada720_kbd.c
+ *
+ * HP Jornada 720 keyboard platform driver
+ *
+ * Copyright (C) 2006/2007 Kristoffer Ericson <Kristoffer.Ericson@Gmail.com>
+ *
+ * Copyright (C) 2006 jornada 720 kbd driver by
+ Filip Zyzniewsk <Filip.Zyzniewski@tefnet.plX
+ * based on (C) 2004 jornada 720 kbd driver by
+ Alex Lange <chicken@handhelds.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/arch/jornada720.h>
+#include <asm/hardware.h>
+
+MODULE_AUTHOR("Kristoffer Ericson <Kristoffer.Ericson@gmail.com>");
+MODULE_DESCRIPTION("HP Jornada 710/720/728 keyboard driver");
+MODULE_LICENSE("GPLv2");
+
+static unsigned short jornada_std_keymap[128] = { /* ROW */
+ 0, KEY_ESC, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, /* #1 */
+ KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_MUTE, /* -> */
+ 0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, /* #2 */
+ KEY_0, KEY_MINUS, KEY_EQUAL,0, 0, 0, /* -> */
+ 0, KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_U, KEY_I, KEY_O, /* #3 */
+ KEY_P, KEY_BACKSLASH, KEY_BACKSPACE, 0, 0, 0, /* -> */
+ 0, KEY_A, KEY_S, KEY_D, KEY_F, KEY_G, KEY_H, KEY_J, KEY_K, KEY_L, /* #4 */
+ KEY_SEMICOLON, KEY_LEFTBRACE, KEY_RIGHTBRACE, 0, 0, 0, /* -> */
+ 0, KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B, KEY_N, KEY_M, KEY_COMMA, /* #5 */
+ KEY_DOT, KEY_KPMINUS, KEY_APOSTROPHE, KEY_ENTER, 0, 0,0, /* -> */
+ 0, KEY_TAB, 0, KEY_LEFTSHIFT, 0, KEY_APOSTROPHE, 0, 0, 0, 0, /* #6 */
+ KEY_UP, 0, KEY_RIGHTSHIFT, 0, 0, 0,0, 0, 0, 0, 0, KEY_LEFTALT, KEY_GRAVE, /* -> */
+ 0, 0, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0,0, KEY_KPASTERISK, /* -> */
+ KEY_LEFTCTRL, 0, KEY_SPACE, 0, 0, 0, KEY_SLASH, KEY_DELETE, 0, 0, /* -> */
+ 0, 0, 0, KEY_POWER, /* -> */
+};
+
+struct jornadakbd {
+ unsigned short keymap[ARRAY_SIZE(jornada_std_keymap)];
+ struct input_dev *input;
+};
+
+static irqreturn_t jornada720_kbd_interrupt(int irq, void *dev_id)
+{
+ struct platform_device *pdev = dev_id;
+ struct jornadakbd *jornadakbd = platform_get_drvdata(pdev);
+ struct input_dev *input = jornadakbd->input;
+ u8 count, kbd_data, scan_code;
+
+ /* startup ssp with spinlock */
+ jornada_ssp_start();
+
+ if (jornada_ssp_inout(GETSCANKEYCODE) != TXDUMMY) {
+ printk(KERN_DEBUG
+ "jornada720_kbd: "
+ "GetKeycode command failed with ETIMEDOUT, "
+ "flushed bus\n");
+ } else {
+ /* How many keycodes are waiting for us? */
+ count = jornada_ssp_byte(TXDUMMY);
+
+ /* Lets drag them out one at a time */
+ while (count--) {
+ /* Exchange TxDummy for location (keymap[kbddata]) */
+ kbd_data = jornada_ssp_byte(TXDUMMY);
+ scan_code = kbd_data & 0x7f;
+
+ input_event(input, EV_MSC, MSC_SCAN, scan_code);
+ input_report_key(input, jornadakbd->keymap[scan_code],
+ !(kbd_data & 0x80));
+ input_sync(input);
+ }
+ }
+
+ /* release spinlock and turn off ssp */
+ jornada_ssp_end();
+
+ return IRQ_HANDLED;
+};
+
+static int __devinit jornada720_kbd_probe(struct platform_device *pdev)
+{
+ struct jornadakbd *jornadakbd;
+ struct input_dev *input_dev;
+ int i, err;
+
+ jornadakbd = kzalloc(sizeof(struct jornadakbd), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!jornadakbd || !input_dev) {
+ err = -ENOMEM;
+ goto fail1;
+ }
+
+ platform_set_drvdata(pdev, jornadakbd);
+
+ memcpy(jornadakbd->keymap, jornada_std_keymap,
+ sizeof(jornada_std_keymap));
+ jornadakbd->input = input_dev;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ input_dev->name = "HP Jornada 720 keyboard";
+ input_dev->phys = "jornadakbd/input0";
+ input_dev->keycode = jornadakbd->keymap;
+ input_dev->keycodesize = sizeof(unsigned short);
+ input_dev->keycodemax = ARRAY_SIZE(jornada_std_keymap);
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->dev.parent = &pdev->dev;
+
+ for (i = 0; i < ARRAY_SIZE(jornadakbd->keymap); i++)
+ __set_bit(jornadakbd->keymap[i], input_dev->keybit);
+ __clear_bit(KEY_RESERVED, input_dev->keybit);
+
+ input_set_capability(input_dev, EV_MSC, MSC_SCAN);
+
+ err = request_irq(IRQ_GPIO0,
+ jornada720_kbd_interrupt,
+ IRQF_DISABLED | IRQF_TRIGGER_FALLING,
+ "jornadakbd", pdev);
+ if (err) {
+ printk(KERN_INFO "jornadakbd720_kbd: Unable to grab IRQ\n");
+ goto fail1;
+ }
+
+ err = input_register_device(jornadakbd->input);
+ if (err)
+ goto fail2;
+
+ return 0;
+
+ fail2: /* IRQ, DEVICE, MEMORY */
+ free_irq(IRQ_GPIO0, pdev);
+ fail1: /* DEVICE, MEMORY */
+ platform_set_drvdata(pdev, NULL);
+ input_free_device(input_dev);
+ kfree(jornadakbd);
+ return err;
+};
+
+static int __devexit jornada720_kbd_remove(struct platform_device *pdev)
+{
+ struct jornadakbd *jornadakbd = platform_get_drvdata(pdev);
+
+ free_irq(IRQ_GPIO0, pdev);
+ platform_set_drvdata(pdev, NULL);
+ input_unregister_device(jornadakbd->input);
+ kfree(jornadakbd);
+
+ return 0;
+}
+
+static struct platform_driver jornada720_kbd_driver = {
+ .driver = {
+ .name = "jornada720_kbd",
+ },
+ .probe = jornada720_kbd_probe,
+ .remove = __devexit_p(jornada720_kbd_remove),
+};
+
+static int __init jornada720_kbd_init(void)
+{
+ return platform_driver_register(&jornada720_kbd_driver);
+}
+
+static void __exit jornada720_kbd_exit(void)
+{
+ platform_driver_unregister(&jornada720_kbd_driver);
+}
+
+module_init(jornada720_kbd_init);
+module_exit(jornada720_kbd_exit);
diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c
index 7a41b271f222..5a0ca18d6755 100644
--- a/drivers/input/keyboard/locomokbd.c
+++ b/drivers/input/keyboard/locomokbd.c
@@ -233,7 +233,7 @@ static int locomokbd_probe(struct locomo_dev *dev)
input_dev->id.version = 0x0100;
input_dev->dev.parent = &dev->dev;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
input_dev->keycode = locomokbd->keycode;
input_dev->keycodesize = sizeof(unsigned char);
input_dev->keycodemax = ARRAY_SIZE(locomokbd_keycode);
diff --git a/drivers/input/keyboard/maple_keyb.c b/drivers/input/keyboard/maple_keyb.c
new file mode 100644
index 000000000000..2b404284c28a
--- /dev/null
+++ b/drivers/input/keyboard/maple_keyb.c
@@ -0,0 +1,252 @@
+/*
+ * SEGA Dreamcast keyboard driver
+ * Based on drivers/usb/usbkbd.c
+ * Copyright YAEGASHI Takeshi, 2001
+ * Porting to 2.6 Copyright Adrian McMenamin, 2007
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/maple.h>
+#include <asm/mach/maple.h>
+
+/* Very simple mutex to ensure proper cleanup */
+static DEFINE_MUTEX(maple_keyb_mutex);
+
+#define NR_SCANCODES 256
+
+MODULE_AUTHOR("YAEGASHI Takeshi, Adrian McMenamin");
+MODULE_DESCRIPTION("SEGA Dreamcast keyboard driver");
+MODULE_LICENSE("GPL");
+
+struct dc_kbd {
+ struct input_dev *dev;
+ unsigned short keycode[NR_SCANCODES];
+ unsigned char new[8];
+ unsigned char old[8];
+};
+
+static const unsigned short dc_kbd_keycode[NR_SCANCODES] = {
+ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_A, KEY_B, KEY_C, KEY_D,
+ KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, KEY_J, KEY_K, KEY_L,
+ KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T,
+ KEY_U, KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z, KEY_1, KEY_2,
+ KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, KEY_0,
+ KEY_ENTER, KEY_ESC, KEY_BACKSPACE, KEY_TAB, KEY_SPACE, KEY_MINUS, KEY_EQUAL, KEY_LEFTBRACE,
+ KEY_RIGHTBRACE, KEY_BACKSLASH, KEY_BACKSLASH, KEY_SEMICOLON, KEY_APOSTROPHE, KEY_GRAVE, KEY_COMMA,
+ KEY_DOT, KEY_SLASH, KEY_CAPSLOCK, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6,
+ KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12, KEY_SYSRQ,
+ KEY_SCROLLLOCK, KEY_PAUSE, KEY_INSERT, KEY_HOME, KEY_PAGEUP, KEY_DELETE,
+ KEY_END, KEY_PAGEDOWN, KEY_RIGHT, KEY_LEFT, KEY_DOWN, KEY_UP,
+ KEY_NUMLOCK, KEY_KPSLASH, KEY_KPASTERISK, KEY_KPMINUS, KEY_KPPLUS, KEY_KPENTER, KEY_KP1, KEY_KP2,
+ KEY_KP3, KEY_KP4, KEY_KP5, KEY_KP6, KEY_KP7, KEY_KP8, KEY_KP9, KEY_KP0, KEY_KPDOT,
+ KEY_102ND, KEY_COMPOSE, KEY_POWER, KEY_KPEQUAL, KEY_F13, KEY_F14, KEY_F15,
+ KEY_F16, KEY_F17, KEY_F18, KEY_F19, KEY_F20,
+ KEY_F21, KEY_F22, KEY_F23, KEY_F24, KEY_OPEN, KEY_HELP, KEY_PROPS, KEY_FRONT,
+ KEY_STOP, KEY_AGAIN, KEY_UNDO, KEY_CUT, KEY_COPY, KEY_PASTE, KEY_FIND, KEY_MUTE,
+ KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_KPCOMMA, KEY_RESERVED, KEY_RO, KEY_KATAKANAHIRAGANA , KEY_YEN,
+ KEY_HENKAN, KEY_MUHENKAN, KEY_KPJPCOMMA, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
+ KEY_HANGEUL, KEY_HANJA, KEY_KATAKANA, KEY_HIRAGANA, KEY_ZENKAKUHANKAKU, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
+ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
+ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
+ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
+ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
+ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
+ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
+ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
+ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
+ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
+ KEY_LEFTCTRL, KEY_LEFTSHIFT, KEY_LEFTALT, KEY_LEFTMETA, KEY_RIGHTCTRL, KEY_RIGHTSHIFT, KEY_RIGHTALT, KEY_RIGHTMETA,
+ KEY_PLAYPAUSE, KEY_STOPCD, KEY_PREVIOUSSONG, KEY_NEXTSONG, KEY_EJECTCD, KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_MUTE,
+ KEY_WWW, KEY_BACK, KEY_FORWARD, KEY_STOP, KEY_FIND, KEY_SCROLLUP, KEY_SCROLLDOWN, KEY_EDIT, KEY_SLEEP,
+ KEY_SCREENLOCK, KEY_REFRESH, KEY_CALC, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED
+};
+
+static void dc_scan_kbd(struct dc_kbd *kbd)
+{
+ struct input_dev *dev = kbd->dev;
+ void *ptr;
+ int code, keycode;
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ code = i + 224;
+ keycode = kbd->keycode[code];
+ input_event(dev, EV_MSC, MSC_SCAN, code);
+ input_report_key(dev, keycode, (kbd->new[0] >> i) & 1);
+ }
+
+ for (i = 2; i < 8; i++) {
+ ptr = memchr(kbd->new + 2, kbd->old[i], 6);
+ code = kbd->old[i];
+ if (code > 3 && ptr == NULL) {
+ keycode = kbd->keycode[code];
+ if (keycode) {
+ input_event(dev, EV_MSC, MSC_SCAN, code);
+ input_report_key(dev, keycode, 0);
+ } else
+ printk(KERN_DEBUG "maple_keyb: "
+ "Unknown key (scancode %#x) released.",
+ code);
+ }
+ ptr = memchr(kbd->old + 2, kbd->new[i], 6);
+ code = kbd->new[i];
+ if (code > 3 && ptr) {
+ keycode = kbd->keycode[code];
+ if (keycode) {
+ input_event(dev, EV_MSC, MSC_SCAN, code);
+ input_report_key(dev, keycode, 1);
+ } else
+ printk(KERN_DEBUG "maple_keyb: "
+ "Unknown key (scancode %#x) pressed.",
+ code);
+ }
+ }
+ input_sync(dev);
+ memcpy(kbd->old, kbd->new, 8);
+}
+
+static void dc_kbd_callback(struct mapleq *mq)
+{
+ struct maple_device *mapledev = mq->dev;
+ struct dc_kbd *kbd = mapledev->private_data;
+ unsigned long *buf = mq->recvbuf;
+
+ /*
+ * We should always be getting the lock because the only
+ * time it may be locked if driver is in cleanup phase.
+ */
+ if (likely(mutex_trylock(&maple_keyb_mutex))) {
+
+ if (buf[1] == mapledev->function) {
+ memcpy(kbd->new, buf + 2, 8);
+ dc_scan_kbd(kbd);
+ }
+
+ mutex_unlock(&maple_keyb_mutex);
+ }
+}
+
+static int dc_kbd_connect(struct maple_device *mdev)
+{
+ int i, error;
+ struct dc_kbd *kbd;
+ struct input_dev *dev;
+
+ if (!(mdev->function & MAPLE_FUNC_KEYBOARD))
+ return -EINVAL;
+
+ kbd = kzalloc(sizeof(struct dc_kbd), GFP_KERNEL);
+ dev = input_allocate_device();
+ if (!kbd || !dev) {
+ error = -ENOMEM;
+ goto fail;
+ }
+
+ mdev->private_data = kbd;
+
+ kbd->dev = dev;
+ memcpy(kbd->keycode, dc_kbd_keycode, sizeof(kbd->keycode));
+
+ dev->name = mdev->product_name;
+ dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ dev->keycode = kbd->keycode;
+ dev->keycodesize = sizeof (unsigned short);
+ dev->keycodemax = ARRAY_SIZE(kbd->keycode);
+ dev->id.bustype = BUS_HOST;
+ dev->dev.parent = &mdev->dev;
+
+ for (i = 0; i < NR_SCANCODES; i++)
+ __set_bit(dc_kbd_keycode[i], dev->keybit);
+ __clear_bit(KEY_RESERVED, dev->keybit);
+
+ input_set_capability(dev, EV_MSC, MSC_SCAN);
+ input_set_drvdata(dev, kbd);
+
+ error = input_register_device(dev);
+ if (error)
+ goto fail;
+
+ /* Maple polling is locked to VBLANK - which may be just 50/s */
+ maple_getcond_callback(mdev, dc_kbd_callback, HZ/50, MAPLE_FUNC_KEYBOARD);
+ return 0;
+
+ fail:
+ input_free_device(dev);
+ kfree(kbd);
+ mdev->private_data = NULL;
+ return error;
+}
+
+static void dc_kbd_disconnect(struct maple_device *mdev)
+{
+ struct dc_kbd *kbd;
+
+ mutex_lock(&maple_keyb_mutex);
+
+ kbd = mdev->private_data;
+ mdev->private_data = NULL;
+ input_unregister_device(kbd->dev);
+ kfree(kbd);
+
+ mutex_unlock(&maple_keyb_mutex);
+}
+
+/* allow the keyboard to be used */
+static int probe_maple_kbd(struct device *dev)
+{
+ struct maple_device *mdev = to_maple_dev(dev);
+ struct maple_driver *mdrv = to_maple_driver(dev->driver);
+ int error;
+
+ error = dc_kbd_connect(mdev);
+ if (error)
+ return error;
+
+ mdev->driver = mdrv;
+ mdev->registered = 1;
+
+ return 0;
+}
+
+static struct maple_driver dc_kbd_driver = {
+ .function = MAPLE_FUNC_KEYBOARD,
+ .connect = dc_kbd_connect,
+ .disconnect = dc_kbd_disconnect,
+ .drv = {
+ .name = "Dreamcast_keyboard",
+ .probe = probe_maple_kbd,
+ },
+};
+
+static int __init dc_kbd_init(void)
+{
+ return maple_driver_register(&dc_kbd_driver.drv);
+}
+
+static void __exit dc_kbd_exit(void)
+{
+ driver_unregister(&dc_kbd_driver.drv);
+}
+
+module_init(dc_kbd_init);
+module_exit(dc_kbd_exit);
diff --git a/drivers/input/keyboard/newtonkbd.c b/drivers/input/keyboard/newtonkbd.c
index b97a41e3ee56..48d1cab0aa1c 100644
--- a/drivers/input/keyboard/newtonkbd.c
+++ b/drivers/input/keyboard/newtonkbd.c
@@ -106,7 +106,7 @@ static int nkbd_connect(struct serio *serio, struct serio_driver *drv)
input_dev->id.version = 0x0100;
input_dev->dev.parent = &serio->dev;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
input_dev->keycode = nkbd->keycode;
input_dev->keycodesize = sizeof(unsigned char);
input_dev->keycodemax = ARRAY_SIZE(nkbd_keycode);
diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c
index 3a228634f101..babc913d5492 100644
--- a/drivers/input/keyboard/omap-keypad.c
+++ b/drivers/input/keyboard/omap-keypad.c
@@ -4,7 +4,7 @@
* OMAP Keypad Driver
*
* Copyright (C) 2003 Nokia Corporation
- * Written by Timo Teräs <ext-timo.teras@nokia.com>
+ * Written by Timo Teräs <ext-timo.teras@nokia.com>
*
* Added support for H2 & H3 Keypad
* Copyright (C) 2004 Texas Instruments
@@ -233,7 +233,7 @@ static void omap_kp_tasklet(unsigned long data)
omap_writew(0, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
kp_cur_group = -1;
}
- }
+ }
}
static ssize_t omap_kp_enable_show(struct device *dev,
@@ -318,7 +318,7 @@ static int __init omap_kp_probe(struct platform_device *pdev)
keymap = pdata->keymap;
if (pdata->rep)
- set_bit(EV_REP, input_dev->evbit);
+ __set_bit(EV_REP, input_dev->evbit);
if (pdata->delay)
omap_kp->delay = pdata->delay;
@@ -365,9 +365,9 @@ static int __init omap_kp_probe(struct platform_device *pdev)
goto err2;
/* setup input device */
- set_bit(EV_KEY, input_dev->evbit);
+ __set_bit(EV_KEY, input_dev->evbit);
for (i = 0; keymap[i] != 0; i++)
- set_bit(keymap[i] & KEY_MAX, input_dev->keybit);
+ __set_bit(keymap[i] & KEY_MAX, input_dev->keybit);
input_dev->name = "omap-keypad";
input_dev->phys = "omap-keypad/input0";
input_dev->dev.parent = &pdev->dev;
@@ -377,10 +377,6 @@ static int __init omap_kp_probe(struct platform_device *pdev)
input_dev->id.product = 0x0001;
input_dev->id.version = 0x0100;
- input_dev->keycode = keymap;
- input_dev->keycodesize = sizeof(unsigned int);
- input_dev->keycodemax = pdata->keymapsize;
-
ret = input_register_device(omap_kp->input);
if (ret < 0) {
printk(KERN_ERR "Unable to register omap-keypad input device\n");
@@ -403,15 +399,15 @@ static int __init omap_kp_probe(struct platform_device *pdev)
} else {
for (irq_idx = 0; irq_idx < omap_kp->rows; irq_idx++) {
if (request_irq(OMAP_GPIO_IRQ(row_gpios[irq_idx]),
- omap_kp_interrupt,
+ omap_kp_interrupt,
IRQF_TRIGGER_FALLING,
- "omap-keypad", omap_kp) < 0)
+ "omap-keypad", omap_kp) < 0)
goto err5;
}
}
return 0;
err5:
- for (i = irq_idx-1; i >=0; i--)
+ for (i = irq_idx - 1; i >=0; i--)
free_irq(row_gpios[i], 0);
err4:
input_unregister_device(omap_kp->input);
@@ -440,9 +436,9 @@ static int omap_kp_remove(struct platform_device *pdev)
if (cpu_is_omap24xx()) {
int i;
for (i = 0; i < omap_kp->cols; i++)
- omap_free_gpio(col_gpios[i]);
+ omap_free_gpio(col_gpios[i]);
for (i = 0; i < omap_kp->rows; i++) {
- omap_free_gpio(row_gpios[i]);
+ omap_free_gpio(row_gpios[i]);
free_irq(OMAP_GPIO_IRQ(row_gpios[i]), 0);
}
} else {
@@ -485,6 +481,6 @@ static void __exit omap_kp_exit(void)
module_init(omap_kp_init);
module_exit(omap_kp_exit);
-MODULE_AUTHOR("Timo Teräs");
+MODULE_AUTHOR("Timo Teräs");
MODULE_DESCRIPTION("OMAP Keypad Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/input/keyboard/pxa27x_keyboard.c b/drivers/input/keyboard/pxa27x_keyboard.c
index ebe5eacf2990..bdd64ee4c5c8 100644
--- a/drivers/input/keyboard/pxa27x_keyboard.c
+++ b/drivers/input/keyboard/pxa27x_keyboard.c
@@ -23,6 +23,8 @@
#include <linux/input.h>
#include <linux/device.h>
#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/err.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -40,6 +42,8 @@
col/2 == 2 ? KPASMKP2 : KPASMKP3)
#define KPASMKPx_MKC(row, col) (1 << (row + 16 * (col % 2)))
+static struct clk *pxakbd_clk;
+
static irqreturn_t pxakbd_irq_handler(int irq, void *dev_id)
{
struct platform_device *pdev = dev_id;
@@ -104,7 +108,7 @@ static int pxakbd_open(struct input_dev *dev)
KPREC = 0x7F;
/* Enable unit clock */
- pxa_set_cken(CKEN_KEYPAD, 1);
+ clk_enable(pxakbd_clk);
return 0;
}
@@ -112,7 +116,7 @@ static int pxakbd_open(struct input_dev *dev)
static void pxakbd_close(struct input_dev *dev)
{
/* Disable clock unit */
- pxa_set_cken(CKEN_KEYPAD, 0);
+ clk_disable(pxakbd_clk);
}
#ifdef CONFIG_PM
@@ -140,7 +144,8 @@ static int pxakbd_resume(struct platform_device *pdev)
KPREC = pdata->reg_kprec;
/* Enable unit clock */
- pxa_set_cken(CKEN_KEYPAD, 1);
+ clk_disable(pxakbd_clk);
+ clk_enable(pxakbd_clk);
}
mutex_unlock(&input_dev->mutex);
@@ -158,11 +163,18 @@ static int __devinit pxakbd_probe(struct platform_device *pdev)
struct input_dev *input_dev;
int i, row, col, error;
+ pxakbd_clk = clk_get(&pdev->dev, "KBDCLK");
+ if (IS_ERR(pxakbd_clk)) {
+ error = PTR_ERR(pxakbd_clk);
+ goto err_clk;
+ }
+
/* Create and register the input driver. */
input_dev = input_allocate_device();
if (!input_dev) {
printk(KERN_ERR "Cannot request keypad device\n");
- return -ENOMEM;
+ error = -ENOMEM;
+ goto err_alloc;
}
input_dev->name = DRIVER_NAME;
@@ -171,8 +183,9 @@ static int __devinit pxakbd_probe(struct platform_device *pdev)
input_dev->close = pxakbd_close;
input_dev->dev.parent = &pdev->dev;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_REL);
- input_dev->relbit[LONG(REL_WHEEL)] = BIT(REL_WHEEL);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) |
+ BIT_MASK(EV_REL);
+ input_dev->relbit[BIT_WORD(REL_WHEEL)] = BIT_MASK(REL_WHEEL);
for (row = 0; row < pdata->nr_rows; row++) {
for (col = 0; col < pdata->nr_cols; col++) {
int code = pdata->keycodes[row][col];
@@ -185,7 +198,6 @@ static int __devinit pxakbd_probe(struct platform_device *pdev)
DRIVER_NAME, pdev);
if (error) {
printk(KERN_ERR "Cannot request keypad IRQ\n");
- pxa_set_cken(CKEN_KEYPAD, 0);
goto err_free_dev;
}
@@ -217,6 +229,9 @@ static int __devinit pxakbd_probe(struct platform_device *pdev)
free_irq(IRQ_KEYPAD, pdev);
err_free_dev:
input_free_device(input_dev);
+ err_alloc:
+ clk_put(pxakbd_clk);
+ err_clk:
return error;
}
@@ -226,6 +241,7 @@ static int __devexit pxakbd_remove(struct platform_device *pdev)
input_unregister_device(input_dev);
free_irq(IRQ_KEYPAD, pdev);
+ clk_put(pxakbd_clk);
platform_set_drvdata(pdev, NULL);
return 0;
diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c
index 41b80385476c..410d78a774d0 100644
--- a/drivers/input/keyboard/spitzkbd.c
+++ b/drivers/input/keyboard/spitzkbd.c
@@ -381,7 +381,8 @@ static int __init spitzkbd_probe(struct platform_device *dev)
input_dev->id.product = 0x0001;
input_dev->id.version = 0x0100;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) |
+ BIT_MASK(EV_PWR) | BIT_MASK(EV_SW);
input_dev->keycode = spitzkbd->keycode;
input_dev->keycodesize = sizeof(unsigned char);
input_dev->keycodemax = ARRAY_SIZE(spitzkbd_keycode);
diff --git a/drivers/input/keyboard/stowaway.c b/drivers/input/keyboard/stowaway.c
index b44b0684d543..7437219370b1 100644
--- a/drivers/input/keyboard/stowaway.c
+++ b/drivers/input/keyboard/stowaway.c
@@ -110,7 +110,7 @@ static int skbd_connect(struct serio *serio, struct serio_driver *drv)
input_dev->id.version = 0x0100;
input_dev->dev.parent = &serio->dev;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
input_dev->keycode = skbd->keycode;
input_dev->keycodesize = sizeof(unsigned char);
input_dev->keycodemax = ARRAY_SIZE(skbd_keycode);
diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c
index 1d4e39624cfe..be0f5d19d023 100644
--- a/drivers/input/keyboard/sunkbd.c
+++ b/drivers/input/keyboard/sunkbd.c
@@ -277,9 +277,11 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv)
input_dev->event = sunkbd_event;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_SND) | BIT(EV_REP);
- input_dev->ledbit[0] = BIT(LED_CAPSL) | BIT(LED_COMPOSE) | BIT(LED_SCROLLL) | BIT(LED_NUML);
- input_dev->sndbit[0] = BIT(SND_CLICK) | BIT(SND_BELL);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_LED) |
+ BIT_MASK(EV_SND) | BIT_MASK(EV_REP);
+ input_dev->ledbit[0] = BIT_MASK(LED_CAPSL) | BIT_MASK(LED_COMPOSE) |
+ BIT_MASK(LED_SCROLLL) | BIT_MASK(LED_NUML);
+ input_dev->sndbit[0] = BIT_MASK(SND_CLICK) | BIT_MASK(SND_BELL);
input_dev->keycode = sunkbd->keycode;
input_dev->keycodesize = sizeof(unsigned char);
diff --git a/drivers/input/keyboard/xtkbd.c b/drivers/input/keyboard/xtkbd.c
index f3a56eb58ed1..152a2c070508 100644
--- a/drivers/input/keyboard/xtkbd.c
+++ b/drivers/input/keyboard/xtkbd.c
@@ -110,7 +110,7 @@ static int xtkbd_connect(struct serio *serio, struct serio_driver *drv)
input_dev->id.version = 0x0100;
input_dev->dev.parent = &serio->dev;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
input_dev->keycode = xtkbd->keycode;
input_dev->keycodesize = sizeof(unsigned char);
input_dev->keycodemax = ARRAY_SIZE(xtkbd_keycode);
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index d602b8fa7d46..8f5c7b90187d 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -70,9 +70,9 @@ config INPUT_WISTRON_BTNS
select LEDS_CLASS
select CHECK_SIGNATURE
help
- Say Y here for support of Winstron laptop button interface, used on
+ Say Y here for support of Wistron laptop button interfaces, used on
laptops of various brands, including Acer and Fujitsu-Siemens. If
- available, mail and wifi leds will be controlable via /sys/class/leds.
+ available, mail and wifi LEDs will be controllable via /sys/class/leds.
To compile this driver as a module, choose M here: the module will
be called wistron_btns.
@@ -152,7 +152,7 @@ config INPUT_POWERMATE
config INPUT_YEALINK
tristate "Yealink usb-p1k voip phone"
- depends EXPERIMENTAL
+ depends on EXPERIMENTAL
depends on USB_ARCH_HAS_HCD
select USB
help
diff --git a/drivers/input/misc/ati_remote.c b/drivers/input/misc/ati_remote.c
index 471aab206443..3a7937481ad8 100644
--- a/drivers/input/misc/ati_remote.c
+++ b/drivers/input/misc/ati_remote.c
@@ -662,10 +662,10 @@ static void ati_remote_input_init(struct ati_remote *ati_remote)
struct input_dev *idev = ati_remote->idev;
int i;
- idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- idev->keybit[LONG(BTN_MOUSE)] = ( BIT(BTN_LEFT) | BIT(BTN_RIGHT) |
- BIT(BTN_SIDE) | BIT(BTN_EXTRA) );
- idev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+ idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+ idev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
+ BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA);
+ idev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++)
if (ati_remote_tbl[i].type == EV_KEY)
set_bit(ati_remote_tbl[i].code, idev->keybit);
diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c
index 1031543e5c3f..f2709b82485c 100644
--- a/drivers/input/misc/ati_remote2.c
+++ b/drivers/input/misc/ati_remote2.c
@@ -346,9 +346,10 @@ static int ati_remote2_input_init(struct ati_remote2 *ar2)
ar2->idev = idev;
input_set_drvdata(idev, ar2);
- idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_REL);
- idev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT);
- idev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+ idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | BIT_MASK(EV_REL);
+ idev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
+ BIT_MASK(BTN_RIGHT);
+ idev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
for (i = 0; ati_remote2_key_table[i].key_code != KEY_RESERVED; i++)
set_bit(ati_remote2_key_table[i].key_code, idev->keybit);
diff --git a/drivers/input/misc/atlas_btns.c b/drivers/input/misc/atlas_btns.c
index e43e92fd9e23..4e3ad657ed80 100644
--- a/drivers/input/misc/atlas_btns.c
+++ b/drivers/input/misc/atlas_btns.c
@@ -81,7 +81,7 @@ static int atlas_acpi_button_add(struct acpi_device *device)
input_dev->name = "Atlas ACPI button driver";
input_dev->phys = "ASIM0000/atlas/input0";
input_dev->id.bustype = BUS_HOST;
- input_dev->evbit[LONG(EV_KEY)] = BIT(EV_KEY);
+ input_dev->evbit[BIT_WORD(EV_KEY)] = BIT_MASK(EV_KEY);
set_bit(KEY_F1, input_dev->keybit);
set_bit(KEY_F2, input_dev->keybit);
diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c
index 064b07936019..1aef97ed5e84 100644
--- a/drivers/input/misc/cobalt_btns.c
+++ b/drivers/input/misc/cobalt_btns.c
@@ -104,7 +104,7 @@ static int __devinit cobalt_buttons_probe(struct platform_device *pdev)
input->id.bustype = BUS_HOST;
input->cdev.dev = &pdev->dev;
- input->evbit[0] = BIT(EV_KEY);
+ input->evbit[0] = BIT_MASK(EV_KEY);
for (i = 0; i < ARRAY_SIZE(buttons_map); i++) {
set_bit(buttons_map[i].keycode, input->keybit);
buttons_map[i].count = 0;
diff --git a/drivers/input/misc/ixp4xx-beeper.c b/drivers/input/misc/ixp4xx-beeper.c
index e759944041ab..d2ade7443b7d 100644
--- a/drivers/input/misc/ixp4xx-beeper.c
+++ b/drivers/input/misc/ixp4xx-beeper.c
@@ -109,8 +109,8 @@ static int __devinit ixp4xx_spkr_probe(struct platform_device *dev)
input_dev->id.version = 0x0100;
input_dev->dev.parent = &dev->dev;
- input_dev->evbit[0] = BIT(EV_SND);
- input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
+ input_dev->evbit[0] = BIT_MASK(EV_SND);
+ input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);
input_dev->event = ixp4xx_spkr_event;
err = request_irq(IRQ_IXP4XX_TIMER2, &ixp4xx_spkr_interrupt,
diff --git a/drivers/input/misc/keyspan_remote.c b/drivers/input/misc/keyspan_remote.c
index 1bffc9fa98c2..fd74347047dd 100644
--- a/drivers/input/misc/keyspan_remote.c
+++ b/drivers/input/misc/keyspan_remote.c
@@ -497,7 +497,7 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic
usb_to_input_id(udev, &input_dev->id);
input_dev->dev.parent = &interface->dev;
- input_dev->evbit[0] = BIT(EV_KEY); /* We will only report KEY events. */
+ input_dev->evbit[0] = BIT_MASK(EV_KEY); /* We will only report KEY events. */
for (i = 0; i < ARRAY_SIZE(keyspan_key_table); i++)
if (keyspan_key_table[i] != KEY_RESERVED)
set_bit(keyspan_key_table[i], input_dev->keybit);
diff --git a/drivers/input/misc/m68kspkr.c b/drivers/input/misc/m68kspkr.c
index e9f26e766b4d..0c64d9bb718e 100644
--- a/drivers/input/misc/m68kspkr.c
+++ b/drivers/input/misc/m68kspkr.c
@@ -65,8 +65,8 @@ static int __devinit m68kspkr_probe(struct platform_device *dev)
input_dev->id.version = 0x0100;
input_dev->dev.parent = &dev->dev;
- input_dev->evbit[0] = BIT(EV_SND);
- input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
+ input_dev->evbit[0] = BIT_MASK(EV_SND);
+ input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);
input_dev->event = m68kspkr_event;
err = input_register_device(input_dev);
diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c
index c19f77fbaf2a..43aaa5cebd12 100644
--- a/drivers/input/misc/pcspkr.c
+++ b/drivers/input/misc/pcspkr.c
@@ -24,7 +24,7 @@ MODULE_DESCRIPTION("PC Speaker beeper driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:pcspkr");
-#ifdef CONFIG_X86
+#if defined(CONFIG_MIPS) || defined(CONFIG_X86)
/* Use the global PIT lock ! */
#include <asm/i8253.h>
#else
@@ -86,8 +86,8 @@ static int __devinit pcspkr_probe(struct platform_device *dev)
pcspkr_dev->id.version = 0x0100;
pcspkr_dev->dev.parent = &dev->dev;
- pcspkr_dev->evbit[0] = BIT(EV_SND);
- pcspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
+ pcspkr_dev->evbit[0] = BIT_MASK(EV_SND);
+ pcspkr_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);
pcspkr_dev->event = pcspkr_event;
err = input_register_device(pcspkr_dev);
diff --git a/drivers/input/misc/powermate.c b/drivers/input/misc/powermate.c
index 448a470d28f2..7a7b8c7b9633 100644
--- a/drivers/input/misc/powermate.c
+++ b/drivers/input/misc/powermate.c
@@ -363,10 +363,11 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
input_dev->event = powermate_input_event;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_MSC);
- input_dev->keybit[LONG(BTN_0)] = BIT(BTN_0);
- input_dev->relbit[LONG(REL_DIAL)] = BIT(REL_DIAL);
- input_dev->mscbit[LONG(MSC_PULSELED)] = BIT(MSC_PULSELED);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL) |
+ BIT_MASK(EV_MSC);
+ input_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0);
+ input_dev->relbit[BIT_WORD(REL_DIAL)] = BIT_MASK(REL_DIAL);
+ input_dev->mscbit[BIT_WORD(MSC_PULSELED)] = BIT_MASK(MSC_PULSELED);
/* get a handle to the interrupt data pipe */
pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c
index e36ec1d92be8..a3637d870880 100644
--- a/drivers/input/misc/sparcspkr.c
+++ b/drivers/input/misc/sparcspkr.c
@@ -115,8 +115,8 @@ static int __devinit sparcspkr_probe(struct device *dev)
input_dev->id.version = 0x0100;
input_dev->dev.parent = dev;
- input_dev->evbit[0] = BIT(EV_SND);
- input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
+ input_dev->evbit[0] = BIT_MASK(EV_SND);
+ input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);
input_dev->event = state->event;
diff --git a/drivers/input/misc/yealink.c b/drivers/input/misc/yealink.c
index ab15880fd566..46279ef2b649 100644
--- a/drivers/input/misc/yealink.c
+++ b/drivers/input/misc/yealink.c
@@ -945,7 +945,7 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
/* input_dev->event = input_ev; TODO */
/* register available key events */
- input_dev->evbit[0] = BIT(EV_KEY);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY);
for (i = 0; i < 256; i++) {
int k = map_p1k_to_key(i);
if (k >= 0) {
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 2c5f11a4f6b4..2b5ed119c9a9 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -48,11 +48,13 @@ static const struct alps_model_info alps_model_data[] = {
{ { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */
{ { 0x63, 0x02, 0x64 }, 0xf8, 0xf8, 0 },
{ { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS }, /* Dell Latitude D800 */
+ { { 0x73, 0x00, 0x0a }, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */
{ { 0x73, 0x02, 0x0a }, 0xf8, 0xf8, 0 },
{ { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */
{ { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */
{ { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT },
{ { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */
+ { { 0x73, 0x02, 0x50 }, 0xcf, 0xff, ALPS_FW_BK_1 } /* Dell Vostro 1400 */
};
/*
@@ -453,24 +455,25 @@ int alps_init(struct psmouse *psmouse)
if (alps_hw_init(psmouse, &version))
goto init_fail;
- dev1->evbit[LONG(EV_KEY)] |= BIT(EV_KEY);
- dev1->keybit[LONG(BTN_TOUCH)] |= BIT(BTN_TOUCH);
- dev1->keybit[LONG(BTN_TOOL_FINGER)] |= BIT(BTN_TOOL_FINGER);
- dev1->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+ dev1->evbit[BIT_WORD(EV_KEY)] |= BIT_MASK(EV_KEY);
+ dev1->keybit[BIT_WORD(BTN_TOUCH)] |= BIT_MASK(BTN_TOUCH);
+ dev1->keybit[BIT_WORD(BTN_TOOL_FINGER)] |= BIT_MASK(BTN_TOOL_FINGER);
+ dev1->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_LEFT) |
+ BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
- dev1->evbit[LONG(EV_ABS)] |= BIT(EV_ABS);
+ dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS);
input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0);
input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0);
input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0);
if (priv->i->flags & ALPS_WHEEL) {
- dev1->evbit[LONG(EV_REL)] |= BIT(EV_REL);
- dev1->relbit[LONG(REL_WHEEL)] |= BIT(REL_WHEEL);
+ dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL);
+ dev1->relbit[BIT_WORD(REL_WHEEL)] |= BIT_MASK(REL_WHEEL);
}
if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
- dev1->keybit[LONG(BTN_FORWARD)] |= BIT(BTN_FORWARD);
- dev1->keybit[LONG(BTN_BACK)] |= BIT(BTN_BACK);
+ dev1->keybit[BIT_WORD(BTN_FORWARD)] |= BIT_MASK(BTN_FORWARD);
+ dev1->keybit[BIT_WORD(BTN_BACK)] |= BIT_MASK(BTN_BACK);
}
snprintf(priv->phys, sizeof(priv->phys), "%s/input1", psmouse->ps2dev.serio->phys);
@@ -481,9 +484,10 @@ int alps_init(struct psmouse *psmouse)
dev2->id.product = PSMOUSE_ALPS;
dev2->id.version = 0x0000;
- dev2->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- dev2->relbit[LONG(REL_X)] |= BIT(REL_X) | BIT(REL_Y);
- dev2->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+ dev2->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+ dev2->relbit[BIT_WORD(REL_X)] |= BIT_MASK(REL_X) | BIT_MASK(REL_Y);
+ dev2->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_LEFT) |
+ BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
if (input_register_device(priv->dev2))
goto init_fail;
diff --git a/drivers/input/mouse/amimouse.c b/drivers/input/mouse/amimouse.c
index 239a0e16d91a..a185ac78a42c 100644
--- a/drivers/input/mouse/amimouse.c
+++ b/drivers/input/mouse/amimouse.c
@@ -111,9 +111,10 @@ static int __init amimouse_init(void)
amimouse_dev->id.product = 0x0002;
amimouse_dev->id.version = 0x0100;
- amimouse_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- amimouse_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
- amimouse_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+ amimouse_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+ amimouse_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
+ amimouse_dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) |
+ BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
amimouse_dev->open = amimouse_open;
amimouse_dev->close = amimouse_close;
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c
index a1804bfdbb8c..b4423a471f02 100644
--- a/drivers/input/mouse/appletouch.c
+++ b/drivers/input/mouse/appletouch.c
@@ -129,12 +129,12 @@ MODULE_DEVICE_TABLE (usb, atp_table);
*/
#define ATP_THRESHOLD 5
-/* MacBook Pro (Geyser 3 & 4) initialization constants */
-#define ATP_GEYSER3_MODE_READ_REQUEST_ID 1
-#define ATP_GEYSER3_MODE_WRITE_REQUEST_ID 9
-#define ATP_GEYSER3_MODE_REQUEST_VALUE 0x300
-#define ATP_GEYSER3_MODE_REQUEST_INDEX 0
-#define ATP_GEYSER3_MODE_VENDOR_VALUE 0x04
+/* Geyser initialization constants */
+#define ATP_GEYSER_MODE_READ_REQUEST_ID 1
+#define ATP_GEYSER_MODE_WRITE_REQUEST_ID 9
+#define ATP_GEYSER_MODE_REQUEST_VALUE 0x300
+#define ATP_GEYSER_MODE_REQUEST_INDEX 0
+#define ATP_GEYSER_MODE_VENDOR_VALUE 0x04
/* Structure to hold all of our device specific stuff */
struct atp {
@@ -142,9 +142,11 @@ struct atp {
struct usb_device * udev; /* usb device */
struct urb * urb; /* usb request block */
signed char * data; /* transferred data */
- int open; /* non-zero if opened */
- struct input_dev *input; /* input dev */
- int valid; /* are the sensors valid ? */
+ struct input_dev * input; /* input dev */
+ unsigned char open; /* non-zero if opened */
+ unsigned char valid; /* are the sensors valid ? */
+ unsigned char size_detect_done;
+ unsigned char overflowwarn; /* overflow warning printed? */
int x_old; /* last reported x/y, */
int y_old; /* used for smoothing */
/* current value of the sensors */
@@ -153,7 +155,6 @@ struct atp {
signed char xy_old[ATP_XSENSORS + ATP_YSENSORS];
/* accumulated sensors */
int xy_acc[ATP_XSENSORS + ATP_YSENSORS];
- int overflowwarn; /* overflow warning printed? */
int datalen; /* size of an USB urb transfer */
int idlecount; /* number of empty packets */
struct work_struct work;
@@ -170,7 +171,7 @@ struct atp {
#define dprintk(format, a...) \
do { \
- if (debug) printk(format, ##a); \
+ if (debug) printk(KERN_DEBUG format, ##a); \
} while (0)
MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold, Michael Hanselmann");
@@ -188,6 +189,15 @@ static int debug = 1;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Activate debugging output");
+static inline int atp_is_fountain(struct atp *dev)
+{
+ u16 productId = le16_to_cpu(dev->udev->descriptor.idProduct);
+
+ return productId == FOUNTAIN_ANSI_PRODUCT_ID ||
+ productId == FOUNTAIN_ISO_PRODUCT_ID ||
+ productId == FOUNTAIN_TP_ONLY_PRODUCT_ID;
+}
+
/* Checks if the device a Geyser 2 (ANSI, ISO, JIS) */
static inline int atp_is_geyser_2(struct atp *dev)
{
@@ -211,52 +221,63 @@ static inline int atp_is_geyser_3(struct atp *dev)
}
/*
- * By default Geyser 3 device sends standard USB HID mouse
+ * By default newer Geyser devices send standard USB HID mouse
* packets (Report ID 2). This code changes device mode, so it
* sends raw sensor reports (Report ID 5).
*/
-static int atp_geyser3_init(struct usb_device *udev)
+static int atp_geyser_init(struct usb_device *udev)
{
char data[8];
int size;
size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
- ATP_GEYSER3_MODE_READ_REQUEST_ID,
+ ATP_GEYSER_MODE_READ_REQUEST_ID,
USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
- ATP_GEYSER3_MODE_REQUEST_VALUE,
- ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000);
+ ATP_GEYSER_MODE_REQUEST_VALUE,
+ ATP_GEYSER_MODE_REQUEST_INDEX, &data, 8, 5000);
if (size != 8) {
err("Could not do mode read request from device"
- " (Geyser 3 mode)");
+ " (Geyser Raw mode)");
return -EIO;
}
/* Apply the mode switch */
- data[0] = ATP_GEYSER3_MODE_VENDOR_VALUE;
+ data[0] = ATP_GEYSER_MODE_VENDOR_VALUE;
size = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
- ATP_GEYSER3_MODE_WRITE_REQUEST_ID,
+ ATP_GEYSER_MODE_WRITE_REQUEST_ID,
USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
- ATP_GEYSER3_MODE_REQUEST_VALUE,
- ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000);
+ ATP_GEYSER_MODE_REQUEST_VALUE,
+ ATP_GEYSER_MODE_REQUEST_INDEX, &data, 8, 5000);
if (size != 8) {
err("Could not do mode write request to device"
- " (Geyser 3 mode)");
+ " (Geyser Raw mode)");
return -EIO;
}
return 0;
}
-/* Reinitialise the device if it's a geyser 3 */
+/*
+ * Reinitialise the device. This usually stops stream of empty packets
+ * coming from it.
+ */
static void atp_reinit(struct work_struct *work)
{
struct atp *dev = container_of(work, struct atp, work);
struct usb_device *udev = dev->udev;
+ int retval;
dev->idlecount = 0;
- atp_geyser3_init(udev);
+
+ atp_geyser_init(udev);
+
+ retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
+ if (retval) {
+ err("%s - usb_submit_urb failed with result %d",
+ __FUNCTION__, retval);
+ }
}
static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
@@ -337,7 +358,7 @@ static void atp_complete(struct urb* urb)
break;
case -EOVERFLOW:
if(!dev->overflowwarn) {
- printk("appletouch: OVERFLOW with data "
+ printk(KERN_WARNING "appletouch: OVERFLOW with data "
"length %d, actual length is %d\n",
dev->datalen, dev->urb->actual_length);
dev->overflowwarn = 1;
@@ -426,15 +447,17 @@ static void atp_complete(struct urb* urb)
dev->x_old = dev->y_old = -1;
memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
- if (atp_is_geyser_3(dev)) /* No 17" Macbooks (yet) */
+ if (dev->size_detect_done ||
+ atp_is_geyser_3(dev)) /* No 17" Macbooks (yet) */
goto exit;
/* 17" Powerbooks have extra X sensors */
- for (i = (atp_is_geyser_2(dev)?15:16); i < ATP_XSENSORS; i++) {
- if (!dev->xy_cur[i]) continue;
+ for (i = (atp_is_geyser_2(dev) ? 15 : 16); i < ATP_XSENSORS; i++) {
+ if (!dev->xy_cur[i])
+ continue;
- printk("appletouch: 17\" model detected.\n");
- if(atp_is_geyser_2(dev))
+ printk(KERN_INFO "appletouch: 17\" model detected.\n");
+ if (atp_is_geyser_2(dev))
input_set_abs_params(dev->input, ABS_X, 0,
(20 - 1) *
ATP_XFACT - 1,
@@ -444,10 +467,10 @@ static void atp_complete(struct urb* urb)
(ATP_XSENSORS - 1) *
ATP_XFACT - 1,
ATP_FUZZ, 0);
-
break;
}
+ dev->size_detect_done = 1;
goto exit;
}
@@ -479,7 +502,7 @@ static void atp_complete(struct urb* urb)
dev->y_old = y;
if (debug > 1)
- printk("appletouch: X: %3d Y: %3d "
+ printk(KERN_DEBUG "appletouch: X: %3d Y: %3d "
"Xz: %3d Yz: %3d\n",
x, y, x_z, y_z);
@@ -502,23 +525,31 @@ static void atp_complete(struct urb* urb)
/* reset the accumulator on release */
memset(dev->xy_acc, 0, sizeof(dev->xy_acc));
+ }
+
+ input_report_key(dev->input, BTN_LEFT, key);
+ input_sync(dev->input);
- /* Geyser 3 will continue to send packets continually after
- the first touch unless reinitialised. Do so if it's been
- idle for a while in order to avoid waking the kernel up
- several hundred times a second */
- if (!key && atp_is_geyser_3(dev)) {
+ /*
+ * Many Geysers will continue to send packets continually after
+ * the first touch unless reinitialised. Do so if it's been
+ * idle for a while in order to avoid waking the kernel up
+ * several hundred times a second. Re-initialization does not
+ * work on Fountain touchpads.
+ */
+ if (!atp_is_fountain(dev)) {
+ if (!x && !y && !key) {
dev->idlecount++;
if (dev->idlecount == 10) {
dev->valid = 0;
schedule_work(&dev->work);
+ /* Don't resubmit urb here, wait for reinit */
+ return;
}
- }
+ } else
+ dev->idlecount = 0;
}
- input_report_key(dev->input, BTN_LEFT, key);
- input_sync(dev->input);
-
exit:
retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
if (retval) {
@@ -591,12 +622,12 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
else
dev->datalen = 81;
- if (atp_is_geyser_3(dev)) {
+ if (!atp_is_fountain(dev)) {
/* switch to raw sensor mode */
- if (atp_geyser3_init(udev))
+ if (atp_geyser_init(udev))
goto err_free_devs;
- printk("appletouch Geyser 3 inited.\n");
+ printk(KERN_INFO "appletouch: Geyser mode initialized.\n");
}
dev->urb = usb_alloc_urb(0, GFP_KERNEL);
diff --git a/drivers/input/mouse/atarimouse.c b/drivers/input/mouse/atarimouse.c
index c8c7244b48a1..98a3561d4b05 100644
--- a/drivers/input/mouse/atarimouse.c
+++ b/drivers/input/mouse/atarimouse.c
@@ -137,9 +137,10 @@ static int __init atamouse_init(void)
atamouse_dev->id.product = 0x0002;
atamouse_dev->id.version = 0x0100;
- atamouse_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- atamouse_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
- atamouse_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+ atamouse_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+ atamouse_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
+ atamouse_dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) |
+ BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
atamouse_dev->open = atamouse_open;
atamouse_dev->close = atamouse_close;
diff --git a/drivers/input/mouse/hil_ptr.c b/drivers/input/mouse/hil_ptr.c
index 449bf4dcbbcc..27f88fbb7136 100644
--- a/drivers/input/mouse/hil_ptr.c
+++ b/drivers/input/mouse/hil_ptr.c
@@ -298,12 +298,12 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
idd = ptr->idd + 1;
txt = "unknown";
if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) {
- ptr->dev->evbit[0] = BIT(EV_REL);
+ ptr->dev->evbit[0] = BIT_MASK(EV_REL);
txt = "relative";
}
if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_ABS) {
- ptr->dev->evbit[0] = BIT(EV_ABS);
+ ptr->dev->evbit[0] = BIT_MASK(EV_ABS);
txt = "absolute";
}
if (!ptr->dev->evbit[0])
@@ -311,7 +311,7 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
ptr->nbtn = HIL_IDD_NUM_BUTTONS(idd);
if (ptr->nbtn)
- ptr->dev->evbit[0] |= BIT(EV_KEY);
+ ptr->dev->evbit[0] |= BIT_MASK(EV_KEY);
naxsets = HIL_IDD_NUM_AXSETS(*idd);
ptr->naxes = HIL_IDD_NUM_AXES_PER_SET(*idd);
diff --git a/drivers/input/mouse/inport.c b/drivers/input/mouse/inport.c
index 79b624fe8994..26ec09529b51 100644
--- a/drivers/input/mouse/inport.c
+++ b/drivers/input/mouse/inport.c
@@ -144,7 +144,7 @@ static int __init inport_init(void)
b = inb(INPORT_SIGNATURE_PORT);
c = inb(INPORT_SIGNATURE_PORT);
if (a == b || a != c) {
- printk(KERN_ERR "inport.c: Didn't find InPort mouse at %#x\n", INPORT_BASE);
+ printk(KERN_INFO "inport.c: Didn't find InPort mouse at %#x\n", INPORT_BASE);
err = -ENODEV;
goto err_release_region;
}
@@ -163,9 +163,10 @@ static int __init inport_init(void)
inport_dev->id.product = 0x0001;
inport_dev->id.version = 0x0100;
- inport_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- inport_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
- inport_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+ inport_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+ inport_dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) |
+ BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
+ inport_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
inport_dev->open = inport_open;
inport_dev->close = inport_close;
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c
index 608674d0be8b..9ec57d80186e 100644
--- a/drivers/input/mouse/lifebook.c
+++ b/drivers/input/mouse/lifebook.c
@@ -97,6 +97,14 @@ static const struct dmi_system_id lifebook_dmi_table[] = {
.callback = lifebook_set_6byte_proto,
},
{
+ .ident = "CF-72",
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "CF-72"),
+ },
+ .callback = lifebook_set_serio_phys,
+ .driver_data = "isa0060/serio3",
+ },
+ {
.ident = "Lifebook B142",
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B142"),
@@ -262,9 +270,10 @@ static int lifebook_create_relative_device(struct psmouse *psmouse)
dev2->id.version = 0x0000;
dev2->dev.parent = &psmouse->ps2dev.serio->dev;
- dev2->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- dev2->relbit[LONG(REL_X)] = BIT(REL_X) | BIT(REL_Y);
- dev2->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT);
+ dev2->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+ dev2->relbit[BIT_WORD(REL_X)] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
+ dev2->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) |
+ BIT_MASK(BTN_RIGHT);
error = input_register_device(priv->dev2);
if (error)
@@ -282,14 +291,14 @@ static int lifebook_create_relative_device(struct psmouse *psmouse)
int lifebook_init(struct psmouse *psmouse)
{
struct input_dev *dev1 = psmouse->dev;
- int max_coord = lifebook_use_6byte_proto ? 1024 : 4096;
+ int max_coord = lifebook_use_6byte_proto ? 4096 : 1024;
if (lifebook_absolute_mode(psmouse))
return -1;
- dev1->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
+ dev1->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY);
dev1->relbit[0] = 0;
- dev1->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ dev1->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
input_set_abs_params(dev1, ABS_X, 0, max_coord, 0, 0);
input_set_abs_params(dev1, ABS_Y, 0, max_coord, 0, 0);
diff --git a/drivers/input/mouse/logibm.c b/drivers/input/mouse/logibm.c
index 26c3b2e2ca94..37e7c75b43bd 100644
--- a/drivers/input/mouse/logibm.c
+++ b/drivers/input/mouse/logibm.c
@@ -134,7 +134,7 @@ static int __init logibm_init(void)
udelay(100);
if (inb(LOGIBM_SIGNATURE_PORT) != LOGIBM_SIGNATURE_BYTE) {
- printk(KERN_ERR "logibm.c: Didn't find Logitech busmouse at %#x\n", LOGIBM_BASE);
+ printk(KERN_INFO "logibm.c: Didn't find Logitech busmouse at %#x\n", LOGIBM_BASE);
err = -ENODEV;
goto err_release_region;
}
@@ -156,9 +156,10 @@ static int __init logibm_init(void)
logibm_dev->id.product = 0x0001;
logibm_dev->id.version = 0x0100;
- logibm_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- logibm_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
- logibm_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+ logibm_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+ logibm_dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) |
+ BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
+ logibm_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
logibm_dev->open = logibm_open;
logibm_dev->close = logibm_close;
diff --git a/drivers/input/mouse/pc110pad.c b/drivers/input/mouse/pc110pad.c
index 05d992e514f0..8991ab0b4fe3 100644
--- a/drivers/input/mouse/pc110pad.c
+++ b/drivers/input/mouse/pc110pad.c
@@ -144,9 +144,9 @@ static int __init pc110pad_init(void)
pc110pad_dev->id.product = 0x0001;
pc110pad_dev->id.version = 0x0100;
- pc110pad_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- pc110pad_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
- pc110pad_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ pc110pad_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ pc110pad_dev->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y);
+ pc110pad_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
pc110pad_dev->absmax[ABS_X] = 0x1ff;
pc110pad_dev->absmax[ABS_Y] = 0x0ff;
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index b9f0fb2530e2..21a9c0b69a1f 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -648,9 +648,10 @@ static int psmouse_extensions(struct psmouse *psmouse,
/*
* Reset to defaults in case the device got confused by extended
- * protocol probes. Note that we do full reset becuase some mice
- * put themselves to sleep when see PSMOUSE_RESET_DIS.
+ * protocol probes. Note that we follow up with full reset because
+ * some mice put themselves to sleep when they see PSMOUSE_RESET_DIS.
*/
+ ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS);
psmouse_reset(psmouse);
if (max_proto >= PSMOUSE_IMEX && im_explorer_detect(psmouse, set_properties) == 0)
@@ -905,7 +906,7 @@ static void psmouse_activate(struct psmouse *psmouse)
/*
* psmouse_deactivate() puts the mouse into poll mode so that we don't get motion
- * reports from it unless we explicitely request it.
+ * reports from it unless we explicitly request it.
*/
static void psmouse_deactivate(struct psmouse *psmouse)
@@ -1114,9 +1115,10 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, const struct psmouse
input_dev->dev.parent = &psmouse->ps2dev.serio->dev;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
- input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+ input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
+ BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
+ input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
psmouse->set_rate = psmouse_set_rate;
psmouse->set_resolution = psmouse_set_resolution;
diff --git a/drivers/input/mouse/rpcmouse.c b/drivers/input/mouse/rpcmouse.c
index 355efd0423e7..18a48636ba4a 100644
--- a/drivers/input/mouse/rpcmouse.c
+++ b/drivers/input/mouse/rpcmouse.c
@@ -78,9 +78,10 @@ static int __init rpcmouse_init(void)
rpcmouse_dev->id.product = 0x0001;
rpcmouse_dev->id.version = 0x0100;
- rpcmouse_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- rpcmouse_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
- rpcmouse_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+ rpcmouse_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+ rpcmouse_dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) |
+ BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
+ rpcmouse_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
rpcmouse_lastx = (short) iomd_readl(IOMD_MOUSEX);
rpcmouse_lasty = (short) iomd_readl(IOMD_MOUSEY);
diff --git a/drivers/input/mouse/sermouse.c b/drivers/input/mouse/sermouse.c
index 77b8ee2b9651..ed917bfd086a 100644
--- a/drivers/input/mouse/sermouse.c
+++ b/drivers/input/mouse/sermouse.c
@@ -268,9 +268,10 @@ static int sermouse_connect(struct serio *serio, struct serio_driver *drv)
input_dev->id.version = 0x0100;
input_dev->dev.parent = &serio->dev;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT);
- input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+ input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
+ BIT_MASK(BTN_RIGHT);
+ input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
if (c & 0x01) set_bit(BTN_MIDDLE, input_dev->keybit);
if (c & 0x02) set_bit(BTN_SIDE, input_dev->keybit);
diff --git a/drivers/input/mouse/touchkit_ps2.c b/drivers/input/mouse/touchkit_ps2.c
index 7b977fd23571..3fadb2accac0 100644
--- a/drivers/input/mouse/touchkit_ps2.c
+++ b/drivers/input/mouse/touchkit_ps2.c
@@ -85,7 +85,7 @@ int touchkit_ps2_detect(struct psmouse *psmouse, int set_properties)
return -ENODEV;
if (set_properties) {
- dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
set_bit(BTN_TOUCH, dev->keybit);
input_set_abs_params(dev, ABS_X, 0, TOUCHKIT_MAX_XC, 0, 0);
input_set_abs_params(dev, ABS_Y, 0, TOUCHKIT_MAX_YC, 0, 0);
diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c
index 4a321576f345..404eedd5ffa2 100644
--- a/drivers/input/mouse/vsxxxaa.c
+++ b/drivers/input/mouse/vsxxxaa.c
@@ -330,7 +330,7 @@ vsxxxaa_handle_POR_packet (struct vsxxxaa *mouse)
/*
* Check for Power-On-Reset packets. These are sent out
- * after plugging the mouse in, or when explicitely
+ * after plugging the mouse in, or when explicitly
* requested by sending 'T'.
*
* [0]: 1 0 1 0 R3 R2 R1 R0
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index 9173916b8be5..78c3ea75da2a 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -61,9 +61,11 @@ struct mousedev {
int open;
int minor;
char name[16];
+ struct input_handle handle;
wait_queue_head_t wait;
struct list_head client_list;
- struct input_handle handle;
+ spinlock_t client_lock; /* protects client_list */
+ struct mutex mutex;
struct device dev;
struct list_head mixdev_node;
@@ -113,108 +115,137 @@ static unsigned char mousedev_imex_seq[] = { 0xf3, 200, 0xf3, 200, 0xf3, 80 };
static struct input_handler mousedev_handler;
static struct mousedev *mousedev_table[MOUSEDEV_MINORS];
+static DEFINE_MUTEX(mousedev_table_mutex);
static struct mousedev *mousedev_mix;
static LIST_HEAD(mousedev_mix_list);
+static void mixdev_open_devices(void);
+static void mixdev_close_devices(void);
+
#define fx(i) (mousedev->old_x[(mousedev->pkt_count - (i)) & 03])
#define fy(i) (mousedev->old_y[(mousedev->pkt_count - (i)) & 03])
-static void mousedev_touchpad_event(struct input_dev *dev, struct mousedev *mousedev, unsigned int code, int value)
+static void mousedev_touchpad_event(struct input_dev *dev,
+ struct mousedev *mousedev,
+ unsigned int code, int value)
{
int size, tmp;
enum { FRACTION_DENOM = 128 };
switch (code) {
- case ABS_X:
- fx(0) = value;
- if (mousedev->touch && mousedev->pkt_count >= 2) {
- size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
- if (size == 0)
- size = 256 * 2;
- tmp = ((value - fx(2)) * (256 * FRACTION_DENOM)) / size;
- tmp += mousedev->frac_dx;
- mousedev->packet.dx = tmp / FRACTION_DENOM;
- mousedev->frac_dx = tmp - mousedev->packet.dx * FRACTION_DENOM;
- }
- break;
- case ABS_Y:
- fy(0) = value;
- if (mousedev->touch && mousedev->pkt_count >= 2) {
- /* use X size to keep the same scale */
- size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
- if (size == 0)
- size = 256 * 2;
- tmp = -((value - fy(2)) * (256 * FRACTION_DENOM)) / size;
- tmp += mousedev->frac_dy;
- mousedev->packet.dy = tmp / FRACTION_DENOM;
- mousedev->frac_dy = tmp - mousedev->packet.dy * FRACTION_DENOM;
- }
- break;
+ case ABS_X:
+ fx(0) = value;
+ if (mousedev->touch && mousedev->pkt_count >= 2) {
+ size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
+ if (size == 0)
+ size = 256 * 2;
+ tmp = ((value - fx(2)) * 256 * FRACTION_DENOM) / size;
+ tmp += mousedev->frac_dx;
+ mousedev->packet.dx = tmp / FRACTION_DENOM;
+ mousedev->frac_dx =
+ tmp - mousedev->packet.dx * FRACTION_DENOM;
+ }
+ break;
+
+ case ABS_Y:
+ fy(0) = value;
+ if (mousedev->touch && mousedev->pkt_count >= 2) {
+ /* use X size to keep the same scale */
+ size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
+ if (size == 0)
+ size = 256 * 2;
+ tmp = -((value - fy(2)) * 256 * FRACTION_DENOM) / size;
+ tmp += mousedev->frac_dy;
+ mousedev->packet.dy = tmp / FRACTION_DENOM;
+ mousedev->frac_dy = tmp -
+ mousedev->packet.dy * FRACTION_DENOM;
+ }
+ break;
}
}
-static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev, unsigned int code, int value)
+static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev,
+ unsigned int code, int value)
{
int size;
switch (code) {
- case ABS_X:
- size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
- if (size == 0)
- size = xres ? : 1;
- if (value > dev->absmax[ABS_X])
- value = dev->absmax[ABS_X];
- if (value < dev->absmin[ABS_X])
- value = dev->absmin[ABS_X];
- mousedev->packet.x = ((value - dev->absmin[ABS_X]) * xres) / size;
- mousedev->packet.abs_event = 1;
- break;
- case ABS_Y:
- size = dev->absmax[ABS_Y] - dev->absmin[ABS_Y];
- if (size == 0)
- size = yres ? : 1;
- if (value > dev->absmax[ABS_Y])
- value = dev->absmax[ABS_Y];
- if (value < dev->absmin[ABS_Y])
- value = dev->absmin[ABS_Y];
- mousedev->packet.y = yres - ((value - dev->absmin[ABS_Y]) * yres) / size;
- mousedev->packet.abs_event = 1;
- break;
+ case ABS_X:
+ size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
+ if (size == 0)
+ size = xres ? : 1;
+ if (value > dev->absmax[ABS_X])
+ value = dev->absmax[ABS_X];
+ if (value < dev->absmin[ABS_X])
+ value = dev->absmin[ABS_X];
+ mousedev->packet.x =
+ ((value - dev->absmin[ABS_X]) * xres) / size;
+ mousedev->packet.abs_event = 1;
+ break;
+
+ case ABS_Y:
+ size = dev->absmax[ABS_Y] - dev->absmin[ABS_Y];
+ if (size == 0)
+ size = yres ? : 1;
+ if (value > dev->absmax[ABS_Y])
+ value = dev->absmax[ABS_Y];
+ if (value < dev->absmin[ABS_Y])
+ value = dev->absmin[ABS_Y];
+ mousedev->packet.y = yres -
+ ((value - dev->absmin[ABS_Y]) * yres) / size;
+ mousedev->packet.abs_event = 1;
+ break;
}
}
-static void mousedev_rel_event(struct mousedev *mousedev, unsigned int code, int value)
+static void mousedev_rel_event(struct mousedev *mousedev,
+ unsigned int code, int value)
{
switch (code) {
- case REL_X: mousedev->packet.dx += value; break;
- case REL_Y: mousedev->packet.dy -= value; break;
- case REL_WHEEL: mousedev->packet.dz -= value; break;
+ case REL_X:
+ mousedev->packet.dx += value;
+ break;
+
+ case REL_Y:
+ mousedev->packet.dy -= value;
+ break;
+
+ case REL_WHEEL:
+ mousedev->packet.dz -= value;
+ break;
}
}
-static void mousedev_key_event(struct mousedev *mousedev, unsigned int code, int value)
+static void mousedev_key_event(struct mousedev *mousedev,
+ unsigned int code, int value)
{
int index;
switch (code) {
- case BTN_TOUCH:
- case BTN_0:
- case BTN_LEFT: index = 0; break;
- case BTN_STYLUS:
- case BTN_1:
- case BTN_RIGHT: index = 1; break;
- case BTN_2:
- case BTN_FORWARD:
- case BTN_STYLUS2:
- case BTN_MIDDLE: index = 2; break;
- case BTN_3:
- case BTN_BACK:
- case BTN_SIDE: index = 3; break;
- case BTN_4:
- case BTN_EXTRA: index = 4; break;
- default: return;
+
+ case BTN_TOUCH:
+ case BTN_0:
+ case BTN_LEFT: index = 0; break;
+
+ case BTN_STYLUS:
+ case BTN_1:
+ case BTN_RIGHT: index = 1; break;
+
+ case BTN_2:
+ case BTN_FORWARD:
+ case BTN_STYLUS2:
+ case BTN_MIDDLE: index = 2; break;
+
+ case BTN_3:
+ case BTN_BACK:
+ case BTN_SIDE: index = 3; break;
+
+ case BTN_4:
+ case BTN_EXTRA: index = 4; break;
+
+ default: return;
}
if (value) {
@@ -226,19 +257,23 @@ static void mousedev_key_event(struct mousedev *mousedev, unsigned int code, int
}
}
-static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_hw_data *packet)
+static void mousedev_notify_readers(struct mousedev *mousedev,
+ struct mousedev_hw_data *packet)
{
struct mousedev_client *client;
struct mousedev_motion *p;
- unsigned long flags;
+ unsigned int new_head;
int wake_readers = 0;
- list_for_each_entry(client, &mousedev->client_list, node) {
- spin_lock_irqsave(&client->packet_lock, flags);
+ rcu_read_lock();
+ list_for_each_entry_rcu(client, &mousedev->client_list, node) {
+
+ /* Just acquire the lock, interrupts already disabled */
+ spin_lock(&client->packet_lock);
p = &client->packets[client->head];
if (client->ready && p->buttons != mousedev->packet.buttons) {
- unsigned int new_head = (client->head + 1) % PACKET_QUEUE_LEN;
+ new_head = (client->head + 1) % PACKET_QUEUE_LEN;
if (new_head != client->tail) {
p = &client->packets[client->head = new_head];
memset(p, 0, sizeof(struct mousedev_motion));
@@ -253,25 +288,29 @@ static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_h
}
client->pos_x += packet->dx;
- client->pos_x = client->pos_x < 0 ? 0 : (client->pos_x >= xres ? xres : client->pos_x);
+ client->pos_x = client->pos_x < 0 ?
+ 0 : (client->pos_x >= xres ? xres : client->pos_x);
client->pos_y += packet->dy;
- client->pos_y = client->pos_y < 0 ? 0 : (client->pos_y >= yres ? yres : client->pos_y);
+ client->pos_y = client->pos_y < 0 ?
+ 0 : (client->pos_y >= yres ? yres : client->pos_y);
p->dx += packet->dx;
p->dy += packet->dy;
p->dz += packet->dz;
p->buttons = mousedev->packet.buttons;
- if (p->dx || p->dy || p->dz || p->buttons != client->last_buttons)
+ if (p->dx || p->dy || p->dz ||
+ p->buttons != client->last_buttons)
client->ready = 1;
- spin_unlock_irqrestore(&client->packet_lock, flags);
+ spin_unlock(&client->packet_lock);
if (client->ready) {
kill_fasync(&client->fasync, SIGIO, POLL_IN);
wake_readers = 1;
}
}
+ rcu_read_unlock();
if (wake_readers)
wake_up_interruptible(&mousedev->wait);
@@ -281,7 +320,8 @@ static void mousedev_touchpad_touch(struct mousedev *mousedev, int value)
{
if (!value) {
if (mousedev->touch &&
- time_before(jiffies, mousedev->touch + msecs_to_jiffies(tap_time))) {
+ time_before(jiffies,
+ mousedev->touch + msecs_to_jiffies(tap_time))) {
/*
* Toggle left button to emulate tap.
* We rely on the fact that mousedev_mix always has 0
@@ -290,7 +330,8 @@ static void mousedev_touchpad_touch(struct mousedev *mousedev, int value)
set_bit(0, &mousedev->packet.buttons);
set_bit(0, &mousedev_mix->packet.buttons);
mousedev_notify_readers(mousedev, &mousedev_mix->packet);
- mousedev_notify_readers(mousedev_mix, &mousedev_mix->packet);
+ mousedev_notify_readers(mousedev_mix,
+ &mousedev_mix->packet);
clear_bit(0, &mousedev->packet.buttons);
clear_bit(0, &mousedev_mix->packet.buttons);
}
@@ -302,54 +343,61 @@ static void mousedev_touchpad_touch(struct mousedev *mousedev, int value)
mousedev->touch = jiffies;
}
-static void mousedev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
+static void mousedev_event(struct input_handle *handle,
+ unsigned int type, unsigned int code, int value)
{
struct mousedev *mousedev = handle->private;
switch (type) {
- case EV_ABS:
- /* Ignore joysticks */
- if (test_bit(BTN_TRIGGER, handle->dev->keybit))
- return;
- if (test_bit(BTN_TOOL_FINGER, handle->dev->keybit))
- mousedev_touchpad_event(handle->dev, mousedev, code, value);
- else
- mousedev_abs_event(handle->dev, mousedev, code, value);
+ case EV_ABS:
+ /* Ignore joysticks */
+ if (test_bit(BTN_TRIGGER, handle->dev->keybit))
+ return;
- break;
+ if (test_bit(BTN_TOOL_FINGER, handle->dev->keybit))
+ mousedev_touchpad_event(handle->dev,
+ mousedev, code, value);
+ else
+ mousedev_abs_event(handle->dev, mousedev, code, value);
- case EV_REL:
- mousedev_rel_event(mousedev, code, value);
- break;
+ break;
- case EV_KEY:
- if (value != 2) {
- if (code == BTN_TOUCH && test_bit(BTN_TOOL_FINGER, handle->dev->keybit))
- mousedev_touchpad_touch(mousedev, value);
- else
- mousedev_key_event(mousedev, code, value);
- }
- break;
+ case EV_REL:
+ mousedev_rel_event(mousedev, code, value);
+ break;
- case EV_SYN:
- if (code == SYN_REPORT) {
- if (mousedev->touch) {
- mousedev->pkt_count++;
- /* Input system eats duplicate events, but we need all of them
- * to do correct averaging so apply present one forward
- */
- fx(0) = fx(1);
- fy(0) = fy(1);
- }
-
- mousedev_notify_readers(mousedev, &mousedev->packet);
- mousedev_notify_readers(mousedev_mix, &mousedev->packet);
-
- mousedev->packet.dx = mousedev->packet.dy = mousedev->packet.dz = 0;
- mousedev->packet.abs_event = 0;
+ case EV_KEY:
+ if (value != 2) {
+ if (code == BTN_TOUCH &&
+ test_bit(BTN_TOOL_FINGER, handle->dev->keybit))
+ mousedev_touchpad_touch(mousedev, value);
+ else
+ mousedev_key_event(mousedev, code, value);
+ }
+ break;
+
+ case EV_SYN:
+ if (code == SYN_REPORT) {
+ if (mousedev->touch) {
+ mousedev->pkt_count++;
+ /*
+ * Input system eats duplicate events,
+ * but we need all of them to do correct
+ * averaging so apply present one forward
+ */
+ fx(0) = fx(1);
+ fy(0) = fy(1);
}
- break;
+
+ mousedev_notify_readers(mousedev, &mousedev->packet);
+ mousedev_notify_readers(mousedev_mix, &mousedev->packet);
+
+ mousedev->packet.dx = mousedev->packet.dy =
+ mousedev->packet.dz = 0;
+ mousedev->packet.abs_event = 0;
+ }
+ break;
}
}
@@ -367,41 +415,48 @@ static void mousedev_free(struct device *dev)
{
struct mousedev *mousedev = container_of(dev, struct mousedev, dev);
- mousedev_table[mousedev->minor] = NULL;
kfree(mousedev);
}
-static int mixdev_add_device(struct mousedev *mousedev)
+static int mousedev_open_device(struct mousedev *mousedev)
{
- int error;
+ int retval;
- if (mousedev_mix->open) {
- error = input_open_device(&mousedev->handle);
- if (error)
- return error;
+ retval = mutex_lock_interruptible(&mousedev->mutex);
+ if (retval)
+ return retval;
- mousedev->open++;
- mousedev->mixdev_open = 1;
+ if (mousedev->minor == MOUSEDEV_MIX)
+ mixdev_open_devices();
+ else if (!mousedev->exist)
+ retval = -ENODEV;
+ else if (!mousedev->open++) {
+ retval = input_open_device(&mousedev->handle);
+ if (retval)
+ mousedev->open--;
}
- get_device(&mousedev->dev);
- list_add_tail(&mousedev->mixdev_node, &mousedev_mix_list);
-
- return 0;
+ mutex_unlock(&mousedev->mutex);
+ return retval;
}
-static void mixdev_remove_device(struct mousedev *mousedev)
+static void mousedev_close_device(struct mousedev *mousedev)
{
- if (mousedev->mixdev_open) {
- mousedev->mixdev_open = 0;
- if (!--mousedev->open && mousedev->exist)
- input_close_device(&mousedev->handle);
- }
+ mutex_lock(&mousedev->mutex);
- list_del_init(&mousedev->mixdev_node);
- put_device(&mousedev->dev);
+ if (mousedev->minor == MOUSEDEV_MIX)
+ mixdev_close_devices();
+ else if (mousedev->exist && !--mousedev->open)
+ input_close_device(&mousedev->handle);
+
+ mutex_unlock(&mousedev->mutex);
}
+/*
+ * Open all available devices so they can all be multiplexed in one.
+ * stream. Note that this function is called with mousedev_mix->mutex
+ * held.
+ */
static void mixdev_open_devices(void)
{
struct mousedev *mousedev;
@@ -411,16 +466,19 @@ static void mixdev_open_devices(void)
list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
if (!mousedev->mixdev_open) {
- if (!mousedev->open && mousedev->exist)
- if (input_open_device(&mousedev->handle))
- continue;
+ if (mousedev_open_device(mousedev))
+ continue;
- mousedev->open++;
mousedev->mixdev_open = 1;
}
}
}
+/*
+ * Close all devices that were opened as part of multiplexed
+ * device. Note that this function is called with mousedev_mix->mutex
+ * held.
+ */
static void mixdev_close_devices(void)
{
struct mousedev *mousedev;
@@ -431,33 +489,45 @@ static void mixdev_close_devices(void)
list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
if (mousedev->mixdev_open) {
mousedev->mixdev_open = 0;
- if (!--mousedev->open && mousedev->exist)
- input_close_device(&mousedev->handle);
+ mousedev_close_device(mousedev);
}
}
}
+
+static void mousedev_attach_client(struct mousedev *mousedev,
+ struct mousedev_client *client)
+{
+ spin_lock(&mousedev->client_lock);
+ list_add_tail_rcu(&client->node, &mousedev->client_list);
+ spin_unlock(&mousedev->client_lock);
+ synchronize_rcu();
+}
+
+static void mousedev_detach_client(struct mousedev *mousedev,
+ struct mousedev_client *client)
+{
+ spin_lock(&mousedev->client_lock);
+ list_del_rcu(&client->node);
+ spin_unlock(&mousedev->client_lock);
+ synchronize_rcu();
+}
+
static int mousedev_release(struct inode *inode, struct file *file)
{
struct mousedev_client *client = file->private_data;
struct mousedev *mousedev = client->mousedev;
mousedev_fasync(-1, file, 0);
-
- list_del(&client->node);
+ mousedev_detach_client(mousedev, client);
kfree(client);
- if (mousedev->minor == MOUSEDEV_MIX)
- mixdev_close_devices();
- else if (!--mousedev->open && mousedev->exist)
- input_close_device(&mousedev->handle);
-
+ mousedev_close_device(mousedev);
put_device(&mousedev->dev);
return 0;
}
-
static int mousedev_open(struct inode *inode, struct file *file)
{
struct mousedev_client *client;
@@ -475,12 +545,17 @@ static int mousedev_open(struct inode *inode, struct file *file)
if (i >= MOUSEDEV_MINORS)
return -ENODEV;
+ error = mutex_lock_interruptible(&mousedev_table_mutex);
+ if (error)
+ return error;
mousedev = mousedev_table[i];
+ if (mousedev)
+ get_device(&mousedev->dev);
+ mutex_unlock(&mousedev_table_mutex);
+
if (!mousedev)
return -ENODEV;
- get_device(&mousedev->dev);
-
client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL);
if (!client) {
error = -ENOMEM;
@@ -491,21 +566,17 @@ static int mousedev_open(struct inode *inode, struct file *file)
client->pos_x = xres / 2;
client->pos_y = yres / 2;
client->mousedev = mousedev;
- list_add_tail(&client->node, &mousedev->client_list);
+ mousedev_attach_client(mousedev, client);
- if (mousedev->minor == MOUSEDEV_MIX)
- mixdev_open_devices();
- else if (!mousedev->open++ && mousedev->exist) {
- error = input_open_device(&mousedev->handle);
- if (error)
- goto err_free_client;
- }
+ error = mousedev_open_device(mousedev);
+ if (error)
+ goto err_free_client;
file->private_data = client;
return 0;
err_free_client:
- list_del(&client->node);
+ mousedev_detach_client(mousedev, client);
kfree(client);
err_put_mousedev:
put_device(&mousedev->dev);
@@ -517,41 +588,41 @@ static inline int mousedev_limit_delta(int delta, int limit)
return delta > limit ? limit : (delta < -limit ? -limit : delta);
}
-static void mousedev_packet(struct mousedev_client *client, signed char *ps2_data)
+static void mousedev_packet(struct mousedev_client *client,
+ signed char *ps2_data)
{
- struct mousedev_motion *p;
- unsigned long flags;
-
- spin_lock_irqsave(&client->packet_lock, flags);
- p = &client->packets[client->tail];
+ struct mousedev_motion *p = &client->packets[client->tail];
- ps2_data[0] = 0x08 | ((p->dx < 0) << 4) | ((p->dy < 0) << 5) | (p->buttons & 0x07);
+ ps2_data[0] = 0x08 |
+ ((p->dx < 0) << 4) | ((p->dy < 0) << 5) | (p->buttons & 0x07);
ps2_data[1] = mousedev_limit_delta(p->dx, 127);
ps2_data[2] = mousedev_limit_delta(p->dy, 127);
p->dx -= ps2_data[1];
p->dy -= ps2_data[2];
switch (client->mode) {
- case MOUSEDEV_EMUL_EXPS:
- ps2_data[3] = mousedev_limit_delta(p->dz, 7);
- p->dz -= ps2_data[3];
- ps2_data[3] = (ps2_data[3] & 0x0f) | ((p->buttons & 0x18) << 1);
- client->bufsiz = 4;
- break;
-
- case MOUSEDEV_EMUL_IMPS:
- ps2_data[0] |= ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1);
- ps2_data[3] = mousedev_limit_delta(p->dz, 127);
- p->dz -= ps2_data[3];
- client->bufsiz = 4;
- break;
-
- case MOUSEDEV_EMUL_PS2:
- default:
- ps2_data[0] |= ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1);
- p->dz = 0;
- client->bufsiz = 3;
- break;
+ case MOUSEDEV_EMUL_EXPS:
+ ps2_data[3] = mousedev_limit_delta(p->dz, 7);
+ p->dz -= ps2_data[3];
+ ps2_data[3] = (ps2_data[3] & 0x0f) | ((p->buttons & 0x18) << 1);
+ client->bufsiz = 4;
+ break;
+
+ case MOUSEDEV_EMUL_IMPS:
+ ps2_data[0] |=
+ ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1);
+ ps2_data[3] = mousedev_limit_delta(p->dz, 127);
+ p->dz -= ps2_data[3];
+ client->bufsiz = 4;
+ break;
+
+ case MOUSEDEV_EMUL_PS2:
+ default:
+ ps2_data[0] |=
+ ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1);
+ p->dz = 0;
+ client->bufsiz = 3;
+ break;
}
if (!p->dx && !p->dy && !p->dz) {
@@ -561,12 +632,56 @@ static void mousedev_packet(struct mousedev_client *client, signed char *ps2_dat
} else
client->tail = (client->tail + 1) % PACKET_QUEUE_LEN;
}
-
- spin_unlock_irqrestore(&client->packet_lock, flags);
}
+static void mousedev_generate_response(struct mousedev_client *client,
+ int command)
+{
+ client->ps2[0] = 0xfa; /* ACK */
+
+ switch (command) {
-static ssize_t mousedev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
+ case 0xeb: /* Poll */
+ mousedev_packet(client, &client->ps2[1]);
+ client->bufsiz++; /* account for leading ACK */
+ break;
+
+ case 0xf2: /* Get ID */
+ switch (client->mode) {
+ case MOUSEDEV_EMUL_PS2:
+ client->ps2[1] = 0;
+ break;
+ case MOUSEDEV_EMUL_IMPS:
+ client->ps2[1] = 3;
+ break;
+ case MOUSEDEV_EMUL_EXPS:
+ client->ps2[1] = 4;
+ break;
+ }
+ client->bufsiz = 2;
+ break;
+
+ case 0xe9: /* Get info */
+ client->ps2[1] = 0x60; client->ps2[2] = 3; client->ps2[3] = 200;
+ client->bufsiz = 4;
+ break;
+
+ case 0xff: /* Reset */
+ client->impsseq = client->imexseq = 0;
+ client->mode = MOUSEDEV_EMUL_PS2;
+ client->ps2[1] = 0xaa; client->ps2[2] = 0x00;
+ client->bufsiz = 3;
+ break;
+
+ default:
+ client->bufsiz = 1;
+ break;
+ }
+ client->buffer = client->bufsiz;
+}
+
+static ssize_t mousedev_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *ppos)
{
struct mousedev_client *client = file->private_data;
unsigned char c;
@@ -577,6 +692,8 @@ static ssize_t mousedev_write(struct file *file, const char __user *buffer, size
if (get_user(c, buffer + i))
return -EFAULT;
+ spin_lock_irq(&client->packet_lock);
+
if (c == mousedev_imex_seq[client->imexseq]) {
if (++client->imexseq == MOUSEDEV_SEQ_LEN) {
client->imexseq = 0;
@@ -593,68 +710,39 @@ static ssize_t mousedev_write(struct file *file, const char __user *buffer, size
} else
client->impsseq = 0;
- client->ps2[0] = 0xfa;
-
- switch (c) {
-
- case 0xeb: /* Poll */
- mousedev_packet(client, &client->ps2[1]);
- client->bufsiz++; /* account for leading ACK */
- break;
-
- case 0xf2: /* Get ID */
- switch (client->mode) {
- case MOUSEDEV_EMUL_PS2: client->ps2[1] = 0; break;
- case MOUSEDEV_EMUL_IMPS: client->ps2[1] = 3; break;
- case MOUSEDEV_EMUL_EXPS: client->ps2[1] = 4; break;
- }
- client->bufsiz = 2;
- break;
-
- case 0xe9: /* Get info */
- client->ps2[1] = 0x60; client->ps2[2] = 3; client->ps2[3] = 200;
- client->bufsiz = 4;
- break;
-
- case 0xff: /* Reset */
- client->impsseq = client->imexseq = 0;
- client->mode = MOUSEDEV_EMUL_PS2;
- client->ps2[1] = 0xaa; client->ps2[2] = 0x00;
- client->bufsiz = 3;
- break;
-
- default:
- client->bufsiz = 1;
- break;
- }
+ mousedev_generate_response(client, c);
- client->buffer = client->bufsiz;
+ spin_unlock_irq(&client->packet_lock);
}
kill_fasync(&client->fasync, SIGIO, POLL_IN);
-
wake_up_interruptible(&client->mousedev->wait);
return count;
}
-static ssize_t mousedev_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
+static ssize_t mousedev_read(struct file *file, char __user *buffer,
+ size_t count, loff_t *ppos)
{
struct mousedev_client *client = file->private_data;
+ struct mousedev *mousedev = client->mousedev;
+ signed char data[sizeof(client->ps2)];
int retval = 0;
- if (!client->ready && !client->buffer && (file->f_flags & O_NONBLOCK))
+ if (!client->ready && !client->buffer && mousedev->exist &&
+ (file->f_flags & O_NONBLOCK))
return -EAGAIN;
- retval = wait_event_interruptible(client->mousedev->wait,
- !client->mousedev->exist || client->ready || client->buffer);
-
+ retval = wait_event_interruptible(mousedev->wait,
+ !mousedev->exist || client->ready || client->buffer);
if (retval)
return retval;
- if (!client->mousedev->exist)
+ if (!mousedev->exist)
return -ENODEV;
+ spin_lock_irq(&client->packet_lock);
+
if (!client->buffer && client->ready) {
mousedev_packet(client, client->ps2);
client->buffer = client->bufsiz;
@@ -663,9 +751,12 @@ static ssize_t mousedev_read(struct file *file, char __user *buffer, size_t coun
if (count > client->buffer)
count = client->buffer;
+ memcpy(data, client->ps2 + client->bufsiz - client->buffer, count);
client->buffer -= count;
- if (copy_to_user(buffer, client->ps2 + client->bufsiz - client->buffer - count, count))
+ spin_unlock_irq(&client->packet_lock);
+
+ if (copy_to_user(buffer, data, count))
return -EFAULT;
return count;
@@ -692,6 +783,60 @@ static const struct file_operations mousedev_fops = {
.fasync = mousedev_fasync,
};
+static int mousedev_install_chrdev(struct mousedev *mousedev)
+{
+ mousedev_table[mousedev->minor] = mousedev;
+ return 0;
+}
+
+static void mousedev_remove_chrdev(struct mousedev *mousedev)
+{
+ mutex_lock(&mousedev_table_mutex);
+ mousedev_table[mousedev->minor] = NULL;
+ mutex_unlock(&mousedev_table_mutex);
+}
+
+/*
+ * Mark device non-existent. This disables writes, ioctls and
+ * prevents new users from opening the device. Already posted
+ * blocking reads will stay, however new ones will fail.
+ */
+static void mousedev_mark_dead(struct mousedev *mousedev)
+{
+ mutex_lock(&mousedev->mutex);
+ mousedev->exist = 0;
+ mutex_unlock(&mousedev->mutex);
+}
+
+/*
+ * Wake up users waiting for IO so they can disconnect from
+ * dead device.
+ */
+static void mousedev_hangup(struct mousedev *mousedev)
+{
+ struct mousedev_client *client;
+
+ spin_lock(&mousedev->client_lock);
+ list_for_each_entry(client, &mousedev->client_list, node)
+ kill_fasync(&client->fasync, SIGIO, POLL_HUP);
+ spin_unlock(&mousedev->client_lock);
+
+ wake_up_interruptible(&mousedev->wait);
+}
+
+static void mousedev_cleanup(struct mousedev *mousedev)
+{
+ struct input_handle *handle = &mousedev->handle;
+
+ mousedev_mark_dead(mousedev);
+ mousedev_hangup(mousedev);
+ mousedev_remove_chrdev(mousedev);
+
+ /* mousedev is marked dead so no one else accesses mousedev->open */
+ if (mousedev->open)
+ input_close_device(handle);
+}
+
static struct mousedev *mousedev_create(struct input_dev *dev,
struct input_handler *handler,
int minor)
@@ -707,6 +852,10 @@ static struct mousedev *mousedev_create(struct input_dev *dev,
INIT_LIST_HEAD(&mousedev->client_list);
INIT_LIST_HEAD(&mousedev->mixdev_node);
+ spin_lock_init(&mousedev->client_lock);
+ mutex_init(&mousedev->mutex);
+ lockdep_set_subclass(&mousedev->mutex,
+ minor == MOUSEDEV_MIX ? MOUSEDEV_MIX : 0);
init_waitqueue_head(&mousedev->wait);
if (minor == MOUSEDEV_MIX)
@@ -731,14 +880,27 @@ static struct mousedev *mousedev_create(struct input_dev *dev,
mousedev->dev.release = mousedev_free;
device_initialize(&mousedev->dev);
- mousedev_table[minor] = mousedev;
+ if (minor != MOUSEDEV_MIX) {
+ error = input_register_handle(&mousedev->handle);
+ if (error)
+ goto err_free_mousedev;
+ }
+
+ error = mousedev_install_chrdev(mousedev);
+ if (error)
+ goto err_unregister_handle;
error = device_add(&mousedev->dev);
if (error)
- goto err_free_mousedev;
+ goto err_cleanup_mousedev;
return mousedev;
+ err_cleanup_mousedev:
+ mousedev_cleanup(mousedev);
+ err_unregister_handle:
+ if (minor != MOUSEDEV_MIX)
+ input_unregister_handle(&mousedev->handle);
err_free_mousedev:
put_device(&mousedev->dev);
err_out:
@@ -747,29 +909,64 @@ static struct mousedev *mousedev_create(struct input_dev *dev,
static void mousedev_destroy(struct mousedev *mousedev)
{
- struct mousedev_client *client;
-
device_del(&mousedev->dev);
- mousedev->exist = 0;
+ mousedev_cleanup(mousedev);
+ if (mousedev->minor != MOUSEDEV_MIX)
+ input_unregister_handle(&mousedev->handle);
+ put_device(&mousedev->dev);
+}
- if (mousedev->open) {
- input_close_device(&mousedev->handle);
- list_for_each_entry(client, &mousedev->client_list, node)
- kill_fasync(&client->fasync, SIGIO, POLL_HUP);
- wake_up_interruptible(&mousedev->wait);
+static int mixdev_add_device(struct mousedev *mousedev)
+{
+ int retval;
+
+ retval = mutex_lock_interruptible(&mousedev_mix->mutex);
+ if (retval)
+ return retval;
+
+ if (mousedev_mix->open) {
+ retval = mousedev_open_device(mousedev);
+ if (retval)
+ goto out;
+
+ mousedev->mixdev_open = 1;
}
+ get_device(&mousedev->dev);
+ list_add_tail(&mousedev->mixdev_node, &mousedev_mix_list);
+
+ out:
+ mutex_unlock(&mousedev_mix->mutex);
+ return retval;
+}
+
+static void mixdev_remove_device(struct mousedev *mousedev)
+{
+ mutex_lock(&mousedev_mix->mutex);
+
+ if (mousedev->mixdev_open) {
+ mousedev->mixdev_open = 0;
+ mousedev_close_device(mousedev);
+ }
+
+ list_del_init(&mousedev->mixdev_node);
+ mutex_unlock(&mousedev_mix->mutex);
+
put_device(&mousedev->dev);
}
-static int mousedev_connect(struct input_handler *handler, struct input_dev *dev,
+static int mousedev_connect(struct input_handler *handler,
+ struct input_dev *dev,
const struct input_device_id *id)
{
struct mousedev *mousedev;
int minor;
int error;
- for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++);
+ for (minor = 0; minor < MOUSEDEV_MINORS; minor++)
+ if (!mousedev_table[minor])
+ break;
+
if (minor == MOUSEDEV_MINORS) {
printk(KERN_ERR "mousedev: no more free mousedev devices\n");
return -ENFILE;
@@ -779,21 +976,13 @@ static int mousedev_connect(struct input_handler *handler, struct input_dev *dev
if (IS_ERR(mousedev))
return PTR_ERR(mousedev);
- error = input_register_handle(&mousedev->handle);
- if (error)
- goto err_delete_mousedev;
-
error = mixdev_add_device(mousedev);
- if (error)
- goto err_unregister_handle;
+ if (error) {
+ mousedev_destroy(mousedev);
+ return error;
+ }
return 0;
-
- err_unregister_handle:
- input_unregister_handle(&mousedev->handle);
- err_delete_mousedev:
- device_unregister(&mousedev->dev);
- return error;
}
static void mousedev_disconnect(struct input_handle *handle)
@@ -801,33 +990,44 @@ static void mousedev_disconnect(struct input_handle *handle)
struct mousedev *mousedev = handle->private;
mixdev_remove_device(mousedev);
- input_unregister_handle(handle);
mousedev_destroy(mousedev);
}
static const struct input_device_id mousedev_ids[] = {
{
- .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_RELBIT,
- .evbit = { BIT(EV_KEY) | BIT(EV_REL) },
- .keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) },
- .relbit = { BIT(REL_X) | BIT(REL_Y) },
- }, /* A mouse like device, at least one button, two relative axes */
+ .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
+ INPUT_DEVICE_ID_MATCH_KEYBIT |
+ INPUT_DEVICE_ID_MATCH_RELBIT,
+ .evbit = { BIT_MASK(EV_KEY) | BIT_MASK(EV_REL) },
+ .keybit = { [BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) },
+ .relbit = { BIT_MASK(REL_X) | BIT_MASK(REL_Y) },
+ }, /* A mouse like device, at least one button,
+ two relative axes */
{
- .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_RELBIT,
- .evbit = { BIT(EV_KEY) | BIT(EV_REL) },
- .relbit = { BIT(REL_WHEEL) },
+ .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
+ INPUT_DEVICE_ID_MATCH_RELBIT,
+ .evbit = { BIT_MASK(EV_KEY) | BIT_MASK(EV_REL) },
+ .relbit = { BIT_MASK(REL_WHEEL) },
}, /* A separate scrollwheel */
{
- .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
- .evbit = { BIT(EV_KEY) | BIT(EV_ABS) },
- .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) },
- .absbit = { BIT(ABS_X) | BIT(ABS_Y) },
- }, /* A tablet like device, at least touch detection, two absolute axes */
+ .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
+ INPUT_DEVICE_ID_MATCH_KEYBIT |
+ INPUT_DEVICE_ID_MATCH_ABSBIT,
+ .evbit = { BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) },
+ .keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) },
+ .absbit = { BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) },
+ }, /* A tablet like device, at least touch detection,
+ two absolute axes */
{
- .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
- .evbit = { BIT(EV_KEY) | BIT(EV_ABS) },
- .keybit = { [LONG(BTN_TOOL_FINGER)] = BIT(BTN_TOOL_FINGER) },
- .absbit = { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_TOOL_WIDTH) },
+ .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
+ INPUT_DEVICE_ID_MATCH_KEYBIT |
+ INPUT_DEVICE_ID_MATCH_ABSBIT,
+ .evbit = { BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) },
+ .keybit = { [BIT_WORD(BTN_TOOL_FINGER)] =
+ BIT_MASK(BTN_TOOL_FINGER) },
+ .absbit = { BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) |
+ BIT_MASK(ABS_PRESSURE) |
+ BIT_MASK(ABS_TOOL_WIDTH) },
}, /* A touchpad */
{ }, /* Terminating entry */
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c
index 6af199805ffc..02b3ad8c0826 100644
--- a/drivers/input/serio/hp_sdc.c
+++ b/drivers/input/serio/hp_sdc.c
@@ -944,11 +944,7 @@ static int __init hp_sdc_init_hppa(struct parisc_device *d)
#endif /* __hppa__ */
-#if !defined(__mc68000__) /* Link error on m68k! */
-static void __exit hp_sdc_exit(void)
-#else
static void hp_sdc_exit(void)
-#endif
{
write_lock_irq(&hp_sdc.lock);
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index c2eea2767e10..1a0cea3c5294 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -20,6 +20,7 @@
#include <linux/err.h>
#include <linux/rcupdate.h>
#include <linux/platform_device.h>
+#include <linux/i8042.h>
#include <asm/io.h>
@@ -208,7 +209,7 @@ static int __i8042_command(unsigned char *param, int command)
return 0;
}
-static int i8042_command(unsigned char *param, int command)
+int i8042_command(unsigned char *param, int command)
{
unsigned long flags;
int retval;
@@ -219,6 +220,7 @@ static int i8042_command(unsigned char *param, int command)
return retval;
}
+EXPORT_SYMBOL(i8042_command);
/*
* i8042_kbd_write() sends a byte out through the keyboard interface.
@@ -385,6 +387,8 @@ static int i8042_enable_kbd_port(void)
i8042_ctr |= I8042_CTR_KBDINT;
if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
+ i8042_ctr &= ~I8042_CTR_KBDINT;
+ i8042_ctr |= I8042_CTR_KBDDIS;
printk(KERN_ERR "i8042.c: Failed to enable KBD port.\n");
return -EIO;
}
@@ -402,6 +406,8 @@ static int i8042_enable_aux_port(void)
i8042_ctr |= I8042_CTR_AUXINT;
if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
+ i8042_ctr &= ~I8042_CTR_AUXINT;
+ i8042_ctr |= I8042_CTR_AUXDIS;
printk(KERN_ERR "i8042.c: Failed to enable AUX port.\n");
return -EIO;
}
diff --git a/drivers/input/serio/i8042.h b/drivers/input/serio/i8042.h
index b3eb7a72d961..dd22d91f8b39 100644
--- a/drivers/input/serio/i8042.h
+++ b/drivers/input/serio/i8042.h
@@ -61,28 +61,6 @@
#define I8042_CTR_XLATE 0x40
/*
- * Commands.
- */
-
-#define I8042_CMD_CTL_RCTR 0x0120
-#define I8042_CMD_CTL_WCTR 0x1060
-#define I8042_CMD_CTL_TEST 0x01aa
-
-#define I8042_CMD_KBD_DISABLE 0x00ad
-#define I8042_CMD_KBD_ENABLE 0x00ae
-#define I8042_CMD_KBD_TEST 0x01ab
-#define I8042_CMD_KBD_LOOP 0x11d2
-
-#define I8042_CMD_AUX_DISABLE 0x00a7
-#define I8042_CMD_AUX_ENABLE 0x00a8
-#define I8042_CMD_AUX_TEST 0x01a9
-#define I8042_CMD_AUX_SEND 0x10d4
-#define I8042_CMD_AUX_LOOP 0x11d3
-
-#define I8042_CMD_MUX_PFX 0x0090
-#define I8042_CMD_MUX_SEND 0x1090
-
-/*
* Return codes.
*/
diff --git a/drivers/input/serio/parkbd.c b/drivers/input/serio/parkbd.c
index 688610e86a3e..b089977e0ef9 100644
--- a/drivers/input/serio/parkbd.c
+++ b/drivers/input/serio/parkbd.c
@@ -102,7 +102,7 @@ static int parkbd_write(struct serio *port, unsigned char c)
return 0;
}
-static void parkbd_interrupt(int irq, void *dev_id)
+static void parkbd_interrupt(void *dev_id)
{
if (parkbd_writing) {
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index b3bc15acd3f5..7f5293828fbf 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -387,9 +387,8 @@ static int serio_thread(void *nothing)
set_freezable();
do {
serio_handle_event();
- wait_event_interruptible(serio_wait,
+ wait_event_freezable(serio_wait,
kthread_should_stop() || !list_empty(&serio_event_list));
- try_to_freeze();
} while (!kthread_should_stop());
printk(KERN_DEBUG "serio: kseriod exiting\n");
diff --git a/drivers/input/tablet/acecad.c b/drivers/input/tablet/acecad.c
index dd2310458c46..b973d0ef6d16 100644
--- a/drivers/input/tablet/acecad.c
+++ b/drivers/input/tablet/acecad.c
@@ -192,10 +192,14 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
input_dev->open = usb_acecad_open;
input_dev->close = usb_acecad_close;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
- input_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
- input_dev->keybit[LONG(BTN_DIGI)] = BIT(BTN_TOOL_PEN) |BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ input_dev->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) |
+ BIT_MASK(ABS_PRESSURE);
+ input_dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) |
+ BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);
+ input_dev->keybit[BIT_WORD(BTN_DIGI)] = BIT_MASK(BTN_TOOL_PEN) |
+ BIT_MASK(BTN_TOUCH) | BIT_MASK(BTN_STYLUS) |
+ BIT_MASK(BTN_STYLUS2);
switch (id->driver_info) {
case 0:
diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c
index b2ca10f2fe0e..d2c6da264722 100644
--- a/drivers/input/tablet/gtco.c
+++ b/drivers/input/tablet/gtco.c
@@ -573,10 +573,12 @@ static void gtco_setup_caps(struct input_dev *inputdev)
struct gtco *device = input_get_drvdata(inputdev);
/* Which events */
- inputdev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_MSC);
+ inputdev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) |
+ BIT_MASK(EV_MSC);
/* Misc event menu block */
- inputdev->mscbit[0] = BIT(MSC_SCAN)|BIT(MSC_SERIAL)|BIT(MSC_RAW) ;
+ inputdev->mscbit[0] = BIT_MASK(MSC_SCAN) | BIT_MASK(MSC_SERIAL) |
+ BIT_MASK(MSC_RAW);
/* Absolute values based on HID report info */
input_set_abs_params(inputdev, ABS_X, device->min_X, device->max_X,
diff --git a/drivers/input/tablet/kbtab.c b/drivers/input/tablet/kbtab.c
index 91e6d00d4a43..1182fc133167 100644
--- a/drivers/input/tablet/kbtab.c
+++ b/drivers/input/tablet/kbtab.c
@@ -153,10 +153,13 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i
input_dev->open = kbtab_open;
input_dev->close = kbtab_close;
- input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_MSC);
- input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
- input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH);
- input_dev->mscbit[0] |= BIT(MSC_SERIAL);
+ input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) |
+ BIT_MASK(EV_MSC);
+ input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_LEFT) |
+ BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);
+ input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_PEN) |
+ BIT_MASK(BTN_TOUCH);
+ input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL);
input_set_abs_params(input_dev, ABS_X, 0, 0x2000, 4, 0);
input_set_abs_params(input_dev, ABS_Y, 0, 0x1750, 4, 0);
input_set_abs_params(input_dev, ABS_PRESSURE, 0, 0xff, 0, 0);
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 064e123c9b76..d64b1ea136b3 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -140,48 +140,58 @@ static void wacom_close(struct input_dev *dev)
void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
- input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_1) | BIT(BTN_5);
+ input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_1) |
+ BIT_MASK(BTN_5);
input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
}
void input_dev_g4(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
- input_dev->evbit[0] |= BIT(EV_MSC);
- input_dev->mscbit[0] |= BIT(MSC_SERIAL);
- input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER);
- input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_4);
+ input_dev->evbit[0] |= BIT_MASK(EV_MSC);
+ input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL);
+ input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_FINGER);
+ input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_0) |
+ BIT_MASK(BTN_4);
}
void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
- input_dev->evbit[0] |= BIT(EV_REL);
- input_dev->relbit[0] |= BIT(REL_WHEEL);
- input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
- input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2);
+ input_dev->evbit[0] |= BIT_MASK(EV_REL);
+ input_dev->relbit[0] |= BIT_MASK(REL_WHEEL);
+ input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_LEFT) |
+ BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);
+ input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) |
+ BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_STYLUS2);
input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->features->distance_max, 0, 0);
}
void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
- input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER);
- input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3);
+ input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_FINGER);
+ input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_0) |
+ BIT_MASK(BTN_1) | BIT_MASK(BTN_2) | BIT_MASK(BTN_3);
input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
}
void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
- input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7);
+ input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_4) |
+ BIT_MASK(BTN_5) | BIT_MASK(BTN_6) | BIT_MASK(BTN_7);
input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
}
void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
- input_dev->evbit[0] |= BIT(EV_MSC) | BIT(EV_REL);
- input_dev->mscbit[0] |= BIT(MSC_SERIAL);
- input_dev->relbit[0] |= BIT(REL_WHEEL);
- input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | BIT(BTN_SIDE) | BIT(BTN_EXTRA);
- input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_TOOL_BRUSH)
- | BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS) | BIT(BTN_STYLUS2);
+ input_dev->evbit[0] |= BIT_MASK(EV_MSC) | BIT_MASK(EV_REL);
+ input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL);
+ input_dev->relbit[0] |= BIT_MASK(REL_WHEEL);
+ input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_LEFT) |
+ BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE) |
+ BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA);
+ input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) |
+ BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_TOOL_BRUSH) |
+ BIT_MASK(BTN_TOOL_PENCIL) | BIT_MASK(BTN_TOOL_AIRBRUSH) |
+ BIT_MASK(BTN_TOOL_LENS) | BIT_MASK(BTN_STYLUS2);
input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->features->distance_max, 0, 0);
input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0);
input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0);
@@ -192,12 +202,13 @@ void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
- input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER);
+ input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_STYLUS2) |
+ BIT_MASK(BTN_TOOL_RUBBER);
}
void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
- input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER);
+ input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER);
}
static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id)
@@ -243,12 +254,13 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
input_dev->open = wacom_open;
input_dev->close = wacom_close;
- input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS);
- input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH) | BIT(BTN_STYLUS);
+ input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_PEN) |
+ BIT_MASK(BTN_TOUCH) | BIT_MASK(BTN_STYLUS);
input_set_abs_params(input_dev, ABS_X, 0, wacom_wac->features->x_max, 4, 0);
input_set_abs_params(input_dev, ABS_Y, 0, wacom_wac->features->y_max, 4, 0);
input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom_wac->features->pressure_max, 0, 0);
- input_dev->absbit[LONG(ABS_MISC)] |= BIT(ABS_MISC);
+ input_dev->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC);
wacom_init_input_dev(input_dev, wacom_wac);
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index f929fcdbae2e..fa8442b6241c 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -126,6 +126,16 @@ config TOUCHSCREEN_HP600
To compile this driver as a module, choose M here: the
module will be called hp680_ts_input.
+config TOUCHSCREEN_HP7XX
+ tristate "HP Jornada 710/720/728 touchscreen"
+ depends on SA1100_JORNADA720_SSP
+ help
+ Say Y here if you have a HP Jornada 710/720/728 and want
+ to support the built-in touchscreen.
+
+ To compile this driver as a module, choose M here: the
+ module will be called jornada720_ts.
+
config TOUCHSCREEN_PENMOUNT
tristate "Penmount serial touchscreen"
select SERIO
@@ -191,6 +201,8 @@ config TOUCHSCREEN_USB_COMPOSITE
- Gunze AHL61
- DMC TSC-10/25
- IRTOUCHSYSTEMS/UNITOP
+ - IdealTEK URTC1000
+ - GoTop Super_Q2/GogoPen/PenPower tablets
Have a look at <http://linux.chapter7.ch/touchkit/> for
a usage description and the required user-space stuff.
@@ -238,4 +250,19 @@ config TOUCHSCREEN_USB_IRTOUCH
bool "IRTOUCHSYSTEMS/UNITOP device support" if EMBEDDED
depends on TOUCHSCREEN_USB_COMPOSITE
+config TOUCHSCREEN_USB_IDEALTEK
+ default y
+ bool "IdealTEK URTC1000 device support" if EMBEDDED
+ depends on TOUCHSCREEN_USB_COMPOSITE
+
+config TOUCHSCREEN_USB_GENERAL_TOUCH
+ default y
+ bool "GeneralTouch Touchscreen device support" if EMBEDDED
+ depends on TOUCHSCREEN_USB_COMPOSITE
+
+config TOUCHSCREEN_USB_GOTOP
+ default y
+ bool "GoTop Super_Q2/GogoPen/PenPower tablet device support" if EMBEDDED
+ depends on TOUCHSCREEN_USB_COMPOSITE
+
endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 5de8933c4993..35d4097df35a 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o
obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o
obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o
+obj-$(CONFIG_TOUCHSCREEN_HP7XX) += jornada720_ts.o
obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE) += usbtouchscreen.o
obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 51ae4fb7d123..f59aecf5ec15 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -917,8 +917,8 @@ static int __devinit ads7846_probe(struct spi_device *spi)
input_dev->phys = ts->phys;
input_dev->dev.parent = &spi->dev;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
input_set_abs_params(input_dev, ABS_X,
pdata->x_min ? : 0,
pdata->x_max ? : MAX_12BIT,
diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c
index e6a31d118786..b1b2e07bf080 100644
--- a/drivers/input/touchscreen/corgi_ts.c
+++ b/drivers/input/touchscreen/corgi_ts.c
@@ -302,8 +302,8 @@ static int __init corgits_probe(struct platform_device *pdev)
input_dev->id.version = 0x0100;
input_dev->dev.parent = &pdev->dev;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
input_set_abs_params(input_dev, ABS_X, X_AXIS_MIN, X_AXIS_MAX, 0, 0);
input_set_abs_params(input_dev, ABS_Y, Y_AXIS_MIN, Y_AXIS_MAX, 0, 0);
input_set_abs_params(input_dev, ABS_PRESSURE, PRESSURE_MIN, PRESSURE_MAX, 0, 0);
diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c
index 557d781719f1..d20689cdbd5d 100644
--- a/drivers/input/touchscreen/elo.c
+++ b/drivers/input/touchscreen/elo.c
@@ -320,8 +320,8 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv)
input_dev->id.version = 0x0100;
input_dev->dev.parent = &serio->dev;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
serio_set_drvdata(serio, elo);
err = serio_open(serio, drv);
diff --git a/drivers/input/touchscreen/fujitsu_ts.c b/drivers/input/touchscreen/fujitsu_ts.c
index daf7a4afc935..80b21800355f 100644
--- a/drivers/input/touchscreen/fujitsu_ts.c
+++ b/drivers/input/touchscreen/fujitsu_ts.c
@@ -122,8 +122,8 @@ static int fujitsu_connect(struct serio *serio, struct serio_driver *drv)
input_dev->id.vendor = SERIO_FUJITSU;
input_dev->id.product = 0;
input_dev->id.version = 0x0100;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
input_set_abs_params(input_dev, ABS_X, 0, 4096, 0, 0);
input_set_abs_params(input_dev, ABS_Y, 0, 4096, 0, 0);
diff --git a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c
index 39d602600d7c..a48a15868c4a 100644
--- a/drivers/input/touchscreen/gunze.c
+++ b/drivers/input/touchscreen/gunze.c
@@ -137,8 +137,8 @@ static int gunze_connect(struct serio *serio, struct serio_driver *drv)
input_dev->id.product = 0x0051;
input_dev->id.version = 0x0100;
input_dev->dev.parent = &serio->dev;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
input_set_abs_params(input_dev, ABS_X, 24, 1000, 0, 0);
input_set_abs_params(input_dev, ABS_Y, 24, 1000, 0, 0);
diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c
index 09ed7803cb8f..2ae6c6016a86 100644
--- a/drivers/input/touchscreen/h3600_ts_input.c
+++ b/drivers/input/touchscreen/h3600_ts_input.c
@@ -373,8 +373,9 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv)
input_dev->event = h3600ts_event;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_LED) | BIT(EV_PWR);
- input_dev->ledbit[0] = BIT(LED_SLEEP);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) |
+ BIT_MASK(EV_LED) | BIT_MASK(EV_PWR);
+ input_dev->ledbit[0] = BIT_MASK(LED_SLEEP);
input_set_abs_params(input_dev, ABS_X, 60, 985, 0, 0);
input_set_abs_params(input_dev, ABS_Y, 35, 1024, 0, 0);
diff --git a/drivers/input/touchscreen/hp680_ts_input.c b/drivers/input/touchscreen/hp680_ts_input.c
index 1a15475aedfc..c38d4e0f95c6 100644
--- a/drivers/input/touchscreen/hp680_ts_input.c
+++ b/drivers/input/touchscreen/hp680_ts_input.c
@@ -81,8 +81,8 @@ static int __init hp680_ts_init(void)
if (!hp680_ts_dev)
return -ENOMEM;
- hp680_ts_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
- hp680_ts_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ hp680_ts_dev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY);
+ hp680_ts_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
input_set_abs_params(hp680_ts_dev, ABS_X,
HP680_TS_ABS_X_MIN, HP680_TS_ABS_X_MAX, 0, 0);
diff --git a/drivers/input/touchscreen/jornada720_ts.c b/drivers/input/touchscreen/jornada720_ts.c
new file mode 100644
index 000000000000..42a1c9a1940e
--- /dev/null
+++ b/drivers/input/touchscreen/jornada720_ts.c
@@ -0,0 +1,182 @@
+/*
+ * drivers/input/touchscreen/jornada720_ts.c
+ *
+ * Copyright (C) 2007 Kristoffer Ericson <Kristoffer.Ericson@gmail.com>
+ *
+ * Copyright (C) 2006 Filip Zyzniewski <filip.zyzniewski@tefnet.pl>
+ * based on HP Jornada 56x touchscreen driver by Alex Lange <chicken@handhelds.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * HP Jornada 710/720/729 Touchscreen Driver
+ */
+
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/jornada720.h>
+
+MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>");
+MODULE_DESCRIPTION("HP Jornada 710/720/728 touchscreen driver");
+MODULE_LICENSE("GPLv2");
+
+struct jornada_ts {
+ struct input_dev *dev;
+ int x_data[4]; /* X sample values */
+ int y_data[4]; /* Y sample values */
+};
+
+static void jornada720_ts_collect_data(struct jornada_ts *jornada_ts)
+{
+
+ /* 3 low word X samples */
+ jornada_ts->x_data[0] = jornada_ssp_byte(TXDUMMY);
+ jornada_ts->x_data[1] = jornada_ssp_byte(TXDUMMY);
+ jornada_ts->x_data[2] = jornada_ssp_byte(TXDUMMY);
+
+ /* 3 low word Y samples */
+ jornada_ts->y_data[0] = jornada_ssp_byte(TXDUMMY);
+ jornada_ts->y_data[1] = jornada_ssp_byte(TXDUMMY);
+ jornada_ts->y_data[2] = jornada_ssp_byte(TXDUMMY);
+
+ /* combined x samples bits */
+ jornada_ts->x_data[3] = jornada_ssp_byte(TXDUMMY);
+
+ /* combined y samples bits */
+ jornada_ts->y_data[3] = jornada_ssp_byte(TXDUMMY);
+}
+
+static int jornada720_ts_average(int coords[4])
+{
+ int coord, high_bits = coords[3];
+
+ coord = coords[0] | ((high_bits & 0x03) << 8);
+ coord += coords[1] | ((high_bits & 0x0c) << 6);
+ coord += coords[2] | ((high_bits & 0x30) << 4);
+
+ return coord / 3;
+}
+
+static irqreturn_t jornada720_ts_interrupt(int irq, void *dev_id)
+{
+ struct platform_device *pdev = dev_id;
+ struct jornada_ts *jornada_ts = platform_get_drvdata(pdev);
+ struct input_dev *input = jornada_ts->dev;
+ int x, y;
+
+ /* If GPIO_GPIO9 is set to high then report pen up */
+ if (GPLR & GPIO_GPIO(9)) {
+ input_report_key(input, BTN_TOUCH, 0);
+ input_sync(input);
+ } else {
+ jornada_ssp_start();
+
+ /* proper reply to request is always TXDUMMY */
+ if (jornada_ssp_inout(GETTOUCHSAMPLES) == TXDUMMY) {
+ jornada720_ts_collect_data(jornada_ts);
+
+ x = jornada720_ts_average(jornada_ts->x_data);
+ y = jornada720_ts_average(jornada_ts->y_data);
+
+ input_report_key(input, BTN_TOUCH, 1);
+ input_report_abs(input, ABS_X, x);
+ input_report_abs(input, ABS_Y, y);
+ input_sync(input);
+ }
+
+ jornada_ssp_end();
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int __devinit jornada720_ts_probe(struct platform_device *pdev)
+{
+ struct jornada_ts *jornada_ts;
+ struct input_dev *input_dev;
+ int error;
+
+ jornada_ts = kzalloc(sizeof(struct jornada_ts), GFP_KERNEL);
+ input_dev = input_allocate_device();
+
+ if (!jornada_ts || !input_dev) {
+ error = -ENOMEM;
+ goto fail1;
+ }
+
+ platform_set_drvdata(pdev, jornada_ts);
+
+ jornada_ts->dev = input_dev;
+
+ input_dev->name = "HP Jornada 7xx Touchscreen";
+ input_dev->phys = "jornadats/input0";
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->dev.parent = &pdev->dev;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_set_abs_params(input_dev, ABS_X, 270, 3900, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, 180, 3700, 0, 0);
+
+ error = request_irq(IRQ_GPIO9,
+ jornada720_ts_interrupt,
+ IRQF_DISABLED | IRQF_TRIGGER_RISING,
+ "HP7XX Touchscreen driver", pdev);
+ if (error) {
+ printk(KERN_INFO "HP7XX TS : Unable to acquire irq!\n");
+ goto fail1;
+ }
+
+ error = input_register_device(jornada_ts->dev);
+ if (error)
+ goto fail2;
+
+ return 0;
+
+ fail2:
+ free_irq(IRQ_GPIO9, pdev);
+ fail1:
+ platform_set_drvdata(pdev, NULL);
+ input_free_device(input_dev);
+ kfree(jornada_ts);
+ return error;
+}
+
+static int __devexit jornada720_ts_remove(struct platform_device *pdev)
+{
+ struct jornada_ts *jornada_ts = platform_get_drvdata(pdev);
+
+ free_irq(IRQ_GPIO9, pdev);
+ platform_set_drvdata(pdev, NULL);
+ input_unregister_device(jornada_ts->dev);
+ kfree(jornada_ts);
+
+ return 0;
+}
+
+static struct platform_driver jornada720_ts_driver = {
+ .probe = jornada720_ts_probe,
+ .remove = __devexit_p(jornada720_ts_remove),
+ .driver = {
+ .name = "jornada_ts",
+ },
+};
+
+static int __init jornada720_ts_init(void)
+{
+ return platform_driver_register(&jornada720_ts_driver);
+}
+
+static void __exit jornada720_ts_exit(void)
+{
+ platform_driver_unregister(&jornada720_ts_driver);
+}
+
+module_init(jornada720_ts_init);
+module_exit(jornada720_ts_exit);
diff --git a/drivers/input/touchscreen/mk712.c b/drivers/input/touchscreen/mk712.c
index 44140feeffc5..80a658868706 100644
--- a/drivers/input/touchscreen/mk712.c
+++ b/drivers/input/touchscreen/mk712.c
@@ -186,8 +186,8 @@ static int __init mk712_init(void)
mk712_dev->open = mk712_open;
mk712_dev->close = mk712_close;
- mk712_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- mk712_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ mk712_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ mk712_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
input_set_abs_params(mk712_dev, ABS_X, 0, 0xfff, 88, 0);
input_set_abs_params(mk712_dev, ABS_Y, 0, 0xfff, 88, 0);
diff --git a/drivers/input/touchscreen/mtouch.c b/drivers/input/touchscreen/mtouch.c
index 4ec3b1f940c8..9077228418b7 100644
--- a/drivers/input/touchscreen/mtouch.c
+++ b/drivers/input/touchscreen/mtouch.c
@@ -151,8 +151,8 @@ static int mtouch_connect(struct serio *serio, struct serio_driver *drv)
input_dev->id.product = 0;
input_dev->id.version = 0x0100;
input_dev->dev.parent = &serio->dev;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
input_set_abs_params(mtouch->dev, ABS_X, MTOUCH_MIN_XC, MTOUCH_MAX_XC, 0, 0);
input_set_abs_params(mtouch->dev, ABS_Y, MTOUCH_MIN_YC, MTOUCH_MAX_YC, 0, 0);
diff --git a/drivers/input/touchscreen/penmount.c b/drivers/input/touchscreen/penmount.c
index f2c0d3c7149c..c7f9cebebbb6 100644
--- a/drivers/input/touchscreen/penmount.c
+++ b/drivers/input/touchscreen/penmount.c
@@ -113,8 +113,8 @@ static int pm_connect(struct serio *serio, struct serio_driver *drv)
input_dev->id.version = 0x0100;
input_dev->dev.parent = &serio->dev;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
input_set_abs_params(pm->dev, ABS_X, 0, 0x3ff, 0, 0);
input_set_abs_params(pm->dev, ABS_Y, 0, 0x3ff, 0, 0);
diff --git a/drivers/input/touchscreen/touchright.c b/drivers/input/touchscreen/touchright.c
index 3def7bb1df44..3a5c142c2a78 100644
--- a/drivers/input/touchscreen/touchright.c
+++ b/drivers/input/touchscreen/touchright.c
@@ -125,8 +125,8 @@ static int tr_connect(struct serio *serio, struct serio_driver *drv)
input_dev->id.product = 0;
input_dev->id.version = 0x0100;
input_dev->dev.parent = &serio->dev;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
input_set_abs_params(tr->dev, ABS_X, TR_MIN_XC, TR_MAX_XC, 0, 0);
input_set_abs_params(tr->dev, ABS_Y, TR_MIN_YC, TR_MAX_YC, 0, 0);
diff --git a/drivers/input/touchscreen/touchwin.c b/drivers/input/touchscreen/touchwin.c
index ac4bdcf18666..763a656a59f8 100644
--- a/drivers/input/touchscreen/touchwin.c
+++ b/drivers/input/touchscreen/touchwin.c
@@ -132,8 +132,8 @@ static int tw_connect(struct serio *serio, struct serio_driver *drv)
input_dev->id.product = 0;
input_dev->id.version = 0x0100;
input_dev->dev.parent = &serio->dev;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
input_set_abs_params(tw->dev, ABS_X, TW_MIN_XC, TW_MAX_XC, 0, 0);
input_set_abs_params(tw->dev, ABS_Y, TW_MIN_YC, TW_MAX_YC, 0, 0);
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c
index 36f944019158..7549939b9535 100644
--- a/drivers/input/touchscreen/ucb1400_ts.c
+++ b/drivers/input/touchscreen/ucb1400_ts.c
@@ -130,8 +130,7 @@ static unsigned int ucb1400_adc_read(struct ucb1400 *ucb, u16 adc_channel)
if (val & UCB_ADC_DAT_VALID)
break;
/* yield to other processes */
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
}
return UCB_ADC_DAT_VALUE(val);
@@ -334,10 +333,9 @@ static int ucb1400_ts_thread(void *_ucb)
timeout = msecs_to_jiffies(10);
}
- wait_event_interruptible_timeout(ucb->ts_wait,
+ wait_event_freezable_timeout(ucb->ts_wait,
ucb->irq_pending || ucb->ts_restart || kthread_should_stop(),
timeout);
- try_to_freeze();
}
/* Send the "pen off" if we are stopping with the pen still active */
@@ -519,7 +517,7 @@ static int ucb1400_ts_probe(struct device *dev)
idev->id.product = id;
idev->open = ucb1400_ts_open;
idev->close = ucb1400_ts_close;
- idev->evbit[0] = BIT(EV_ABS);
+ idev->evbit[0] = BIT_MASK(EV_ABS);
ucb1400_adc_enable(ucb);
x_res = ucb1400_ts_read_xres(ucb);
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c
index 741f6c6f1e50..19055e7381f8 100644
--- a/drivers/input/touchscreen/usbtouchscreen.c
+++ b/drivers/input/touchscreen/usbtouchscreen.c
@@ -10,8 +10,10 @@
* - Gunze AHL61
* - DMC TSC-10/25
* - IRTOUCHSYSTEMS/UNITOP
+ * - IdealTEK URTC1000
+ * - GoTop Super_Q2/GogoPen/PenPower tablets
*
- * Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch>
+ * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch>
* Copyright (C) by Todd E. Johnson (mtouchusb.c)
*
* This program is free software; you can redistribute it and/or
@@ -92,7 +94,7 @@ struct usbtouch_usb {
};
-#if defined(CONFIG_TOUCHSCREEN_USB_EGALAX) || defined(CONFIG_TOUCHSCREEN_USB_ETURBO)
+#if defined(CONFIG_TOUCHSCREEN_USB_EGALAX) || defined(CONFIG_TOUCHSCREEN_USB_ETURBO) || defined(CONFIG_TOUCHSCREEN_USB_IDEALTEK)
#define MULTI_PACKET
#endif
@@ -112,6 +114,9 @@ enum {
DEVTYPE_GUNZE,
DEVTYPE_DMC_TSC10,
DEVTYPE_IRTOUCH,
+ DEVTYPE_IDEALTEK,
+ DEVTYPE_GENERAL_TOUCH,
+ DEVTYPE_GOTOP,
};
static struct usb_device_id usbtouch_devices[] = {
@@ -157,6 +162,20 @@ static struct usb_device_id usbtouch_devices[] = {
{USB_DEVICE(0x6615, 0x0001), .driver_info = DEVTYPE_IRTOUCH},
#endif
+#ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK
+ {USB_DEVICE(0x1391, 0x1000), .driver_info = DEVTYPE_IDEALTEK},
+#endif
+
+#ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH
+ {USB_DEVICE(0x0dfc, 0x0001), .driver_info = DEVTYPE_GENERAL_TOUCH},
+#endif
+
+#ifdef CONFIG_TOUCHSCREEN_USB_GOTOP
+ {USB_DEVICE(0x08f2, 0x007f), .driver_info = DEVTYPE_GOTOP},
+ {USB_DEVICE(0x08f2, 0x00ce), .driver_info = DEVTYPE_GOTOP},
+ {USB_DEVICE(0x08f2, 0x00f4), .driver_info = DEVTYPE_GOTOP},
+#endif
+
{}
};
@@ -396,7 +415,8 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch)
TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT);
if (ret < 0)
return ret;
- if (buf[0] != 0x06 || buf[1] != 0x00)
+ if ((buf[0] != 0x06 || buf[1] != 0x00) &&
+ (buf[0] != 0x15 || buf[1] != 0x01))
return -ENODEV;
/* start sending data */
@@ -438,6 +458,71 @@ static int irtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
/*****************************************************************************
+ * IdealTEK URTC1000 Part
+ */
+#ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK
+static int idealtek_get_pkt_len(unsigned char *buf, int len)
+{
+ if (buf[0] & 0x80)
+ return 5;
+ if (buf[0] == 0x01)
+ return len;
+ return 0;
+}
+
+static int idealtek_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
+{
+ switch (pkt[0] & 0x98) {
+ case 0x88:
+ /* touch data in IdealTEK mode */
+ dev->x = (pkt[1] << 5) | (pkt[2] >> 2);
+ dev->y = (pkt[3] << 5) | (pkt[4] >> 2);
+ dev->touch = (pkt[0] & 0x40) ? 1 : 0;
+ return 1;
+
+ case 0x98:
+ /* touch data in MT emulation mode */
+ dev->x = (pkt[2] << 5) | (pkt[1] >> 2);
+ dev->y = (pkt[4] << 5) | (pkt[3] >> 2);
+ dev->touch = (pkt[0] & 0x40) ? 1 : 0;
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+#endif
+
+/*****************************************************************************
+ * General Touch Part
+ */
+#ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH
+static int general_touch_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
+{
+ dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1] ;
+ dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3] ;
+ dev->press = pkt[5] & 0xff;
+ dev->touch = pkt[0] & 0x01;
+
+ return 1;
+}
+#endif
+
+/*****************************************************************************
+ * GoTop Part
+ */
+#ifdef CONFIG_TOUCHSCREEN_USB_GOTOP
+static int gotop_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
+{
+ dev->x = ((pkt[1] & 0x38) << 4) | pkt[2];
+ dev->y = ((pkt[1] & 0x07) << 7) | pkt[3];
+ dev->touch = pkt[0] & 0x01;
+ return 1;
+}
+#endif
+
+
+/*****************************************************************************
* the different device descriptors
*/
static struct usbtouch_device_info usbtouch_dev_info[] = {
@@ -537,6 +622,42 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
.read_data = irtouch_read_data,
},
#endif
+
+#ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK
+ [DEVTYPE_IDEALTEK] = {
+ .min_xc = 0x0,
+ .max_xc = 0x0fff,
+ .min_yc = 0x0,
+ .max_yc = 0x0fff,
+ .rept_size = 8,
+ .flags = USBTOUCH_FLG_BUFFER,
+ .process_pkt = usbtouch_process_multi,
+ .get_pkt_len = idealtek_get_pkt_len,
+ .read_data = idealtek_read_data,
+ },
+#endif
+
+#ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH
+ [DEVTYPE_GENERAL_TOUCH] = {
+ .min_xc = 0x0,
+ .max_xc = 0x0500,
+ .min_yc = 0x0,
+ .max_yc = 0x0500,
+ .rept_size = 7,
+ .read_data = general_touch_read_data,
+ },
+#endif
+
+#ifdef CONFIG_TOUCHSCREEN_USB_GOTOP
+ [DEVTYPE_GOTOP] = {
+ .min_xc = 0x0,
+ .max_xc = 0x03ff,
+ .min_yc = 0x0,
+ .max_yc = 0x03ff,
+ .rept_size = 4,
+ .read_data = gotop_read_data,
+ },
+#endif
};
@@ -779,8 +900,8 @@ static int usbtouch_probe(struct usb_interface *intf,
input_dev->open = usbtouch_open;
input_dev->close = usbtouch_close;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
input_set_abs_params(input_dev, ABS_X, type->min_xc, type->max_xc, 0, 0);
input_set_abs_params(input_dev, ABS_Y, type->min_yc, type->max_yc, 0, 0);
if (type->max_press)
diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c
deleted file mode 100644
index d2f882e98e5e..000000000000
--- a/drivers/input/tsdev.c
+++ /dev/null
@@ -1,533 +0,0 @@
-/*
- * $Id: tsdev.c,v 1.15 2002/04/10 16:50:19 jsimmons Exp $
- *
- * Copyright (c) 2001 "Crazy" james Simmons
- *
- * Compaq touchscreen protocol driver. The protocol emulated by this driver
- * is obsolete; for new programs use the tslib library which can read directly
- * from evdev and perform dejittering, variance filtering and calibration -
- * all in user space, not at kernel level. The meaning of this driver is
- * to allow usage of newer input drivers with old applications that use the
- * old /dev/h3600_ts and /dev/h3600_tsraw devices.
- *
- * 09-Apr-2004: Andrew Zabolotny <zap@homelink.ru>
- * Fixed to actually work, not just output random numbers.
- * Added support for both h3600_ts and h3600_tsraw protocol
- * emulation.
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <jsimmons@infradead.org>.
- */
-
-#define TSDEV_MINOR_BASE 128
-#define TSDEV_MINORS 32
-/* First 16 devices are h3600_ts compatible; second 16 are h3600_tsraw */
-#define TSDEV_MINOR_MASK 15
-#define TSDEV_BUFFER_SIZE 64
-
-#include <linux/slab.h>
-#include <linux/poll.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/input.h>
-#include <linux/major.h>
-#include <linux/random.h>
-#include <linux/time.h>
-#include <linux/device.h>
-
-#ifndef CONFIG_INPUT_TSDEV_SCREEN_X
-#define CONFIG_INPUT_TSDEV_SCREEN_X 240
-#endif
-#ifndef CONFIG_INPUT_TSDEV_SCREEN_Y
-#define CONFIG_INPUT_TSDEV_SCREEN_Y 320
-#endif
-
-/* This driver emulates both protocols of the old h3600_ts and h3600_tsraw
- * devices. The first one must output X/Y data in 'cooked' format, e.g.
- * filtered, dejittered and calibrated. Second device just outputs raw
- * data received from the hardware.
- *
- * This driver doesn't support filtering and dejittering; it supports only
- * calibration. Filtering and dejittering must be done in the low-level
- * driver, if needed, because it may gain additional benefits from knowing
- * the low-level details, the nature of noise and so on.
- *
- * The driver precomputes a calibration matrix given the initial xres and
- * yres values (quite innacurate for most touchscreens) that will result
- * in a more or less expected range of output values. The driver supports
- * the TS_SET_CAL ioctl, which will replace the calibration matrix with a
- * new one, supposedly generated from the values taken from the raw device.
- */
-
-MODULE_AUTHOR("James Simmons <jsimmons@transvirtual.com>");
-MODULE_DESCRIPTION("Input driver to touchscreen converter");
-MODULE_LICENSE("GPL");
-
-static int xres = CONFIG_INPUT_TSDEV_SCREEN_X;
-module_param(xres, uint, 0);
-MODULE_PARM_DESC(xres, "Horizontal screen resolution (can be negative for X-mirror)");
-
-static int yres = CONFIG_INPUT_TSDEV_SCREEN_Y;
-module_param(yres, uint, 0);
-MODULE_PARM_DESC(yres, "Vertical screen resolution (can be negative for Y-mirror)");
-
-/* From Compaq's Touch Screen Specification version 0.2 (draft) */
-struct ts_event {
- short pressure;
- short x;
- short y;
- short millisecs;
-};
-
-struct ts_calibration {
- int xscale;
- int xtrans;
- int yscale;
- int ytrans;
- int xyswap;
-};
-
-struct tsdev {
- int exist;
- int open;
- int minor;
- char name[8];
- struct input_handle handle;
- wait_queue_head_t wait;
- struct list_head client_list;
- struct device dev;
-
- int x, y, pressure;
- struct ts_calibration cal;
-};
-
-struct tsdev_client {
- struct fasync_struct *fasync;
- struct list_head node;
- struct tsdev *tsdev;
- int head, tail;
- struct ts_event event[TSDEV_BUFFER_SIZE];
- int raw;
-};
-
-/* The following ioctl codes are defined ONLY for backward compatibility.
- * Don't use tsdev for new developement; use the tslib library instead.
- * Touchscreen calibration is a fully userspace task.
- */
-/* Use 'f' as magic number */
-#define IOC_H3600_TS_MAGIC 'f'
-#define TS_GET_CAL _IOR(IOC_H3600_TS_MAGIC, 10, struct ts_calibration)
-#define TS_SET_CAL _IOW(IOC_H3600_TS_MAGIC, 11, struct ts_calibration)
-
-static struct tsdev *tsdev_table[TSDEV_MINORS/2];
-
-static int tsdev_fasync(int fd, struct file *file, int on)
-{
- struct tsdev_client *client = file->private_data;
- int retval;
-
- retval = fasync_helper(fd, file, on, &client->fasync);
- return retval < 0 ? retval : 0;
-}
-
-static int tsdev_open(struct inode *inode, struct file *file)
-{
- int i = iminor(inode) - TSDEV_MINOR_BASE;
- struct tsdev_client *client;
- struct tsdev *tsdev;
- int error;
-
- printk(KERN_WARNING "tsdev (compaq touchscreen emulation) is scheduled "
- "for removal.\nSee Documentation/feature-removal-schedule.txt "
- "for details.\n");
-
- if (i >= TSDEV_MINORS)
- return -ENODEV;
-
- tsdev = tsdev_table[i & TSDEV_MINOR_MASK];
- if (!tsdev || !tsdev->exist)
- return -ENODEV;
-
- get_device(&tsdev->dev);
-
- client = kzalloc(sizeof(struct tsdev_client), GFP_KERNEL);
- if (!client) {
- error = -ENOMEM;
- goto err_put_tsdev;
- }
-
- client->tsdev = tsdev;
- client->raw = (i >= TSDEV_MINORS / 2) ? 1 : 0;
- list_add_tail(&client->node, &tsdev->client_list);
-
- if (!tsdev->open++ && tsdev->exist) {
- error = input_open_device(&tsdev->handle);
- if (error)
- goto err_free_client;
- }
-
- file->private_data = client;
- return 0;
-
- err_free_client:
- list_del(&client->node);
- kfree(client);
- err_put_tsdev:
- put_device(&tsdev->dev);
- return error;
-}
-
-static void tsdev_free(struct device *dev)
-{
- struct tsdev *tsdev = container_of(dev, struct tsdev, dev);
-
- tsdev_table[tsdev->minor] = NULL;
- kfree(tsdev);
-}
-
-static int tsdev_release(struct inode *inode, struct file *file)
-{
- struct tsdev_client *client = file->private_data;
- struct tsdev *tsdev = client->tsdev;
-
- tsdev_fasync(-1, file, 0);
-
- list_del(&client->node);
- kfree(client);
-
- if (!--tsdev->open && tsdev->exist)
- input_close_device(&tsdev->handle);
-
- put_device(&tsdev->dev);
-
- return 0;
-}
-
-static ssize_t tsdev_read(struct file *file, char __user *buffer, size_t count,
- loff_t *ppos)
-{
- struct tsdev_client *client = file->private_data;
- struct tsdev *tsdev = client->tsdev;
- int retval = 0;
-
- if (client->head == client->tail && tsdev->exist && (file->f_flags & O_NONBLOCK))
- return -EAGAIN;
-
- retval = wait_event_interruptible(tsdev->wait,
- client->head != client->tail || !tsdev->exist);
- if (retval)
- return retval;
-
- if (!tsdev->exist)
- return -ENODEV;
-
- while (client->head != client->tail &&
- retval + sizeof (struct ts_event) <= count) {
- if (copy_to_user (buffer + retval, client->event + client->tail,
- sizeof (struct ts_event)))
- return -EFAULT;
- client->tail = (client->tail + 1) & (TSDEV_BUFFER_SIZE - 1);
- retval += sizeof (struct ts_event);
- }
-
- return retval;
-}
-
-/* No kernel lock - fine */
-static unsigned int tsdev_poll(struct file *file, poll_table *wait)
-{
- struct tsdev_client *client = file->private_data;
- struct tsdev *tsdev = client->tsdev;
-
- poll_wait(file, &tsdev->wait, wait);
- return ((client->head == client->tail) ? 0 : (POLLIN | POLLRDNORM)) |
- (tsdev->exist ? 0 : (POLLHUP | POLLERR));
-}
-
-static int tsdev_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- struct tsdev_client *client = file->private_data;
- struct tsdev *tsdev = client->tsdev;
- int retval = 0;
-
- switch (cmd) {
- case TS_GET_CAL:
- if (copy_to_user((void __user *)arg, &tsdev->cal,
- sizeof (struct ts_calibration)))
- retval = -EFAULT;
- break;
-
- case TS_SET_CAL:
- if (copy_from_user(&tsdev->cal, (void __user *)arg,
- sizeof (struct ts_calibration)))
- retval = -EFAULT;
- break;
-
- default:
- retval = -EINVAL;
- break;
- }
-
- return retval;
-}
-
-static const struct file_operations tsdev_fops = {
- .owner = THIS_MODULE,
- .open = tsdev_open,
- .release = tsdev_release,
- .read = tsdev_read,
- .poll = tsdev_poll,
- .fasync = tsdev_fasync,
- .ioctl = tsdev_ioctl,
-};
-
-static void tsdev_event(struct input_handle *handle, unsigned int type,
- unsigned int code, int value)
-{
- struct tsdev *tsdev = handle->private;
- struct tsdev_client *client;
- struct timeval time;
-
- switch (type) {
- case EV_ABS:
- switch (code) {
- case ABS_X:
- tsdev->x = value;
- break;
-
- case ABS_Y:
- tsdev->y = value;
- break;
-
- case ABS_PRESSURE:
- if (value > handle->dev->absmax[ABS_PRESSURE])
- value = handle->dev->absmax[ABS_PRESSURE];
- value -= handle->dev->absmin[ABS_PRESSURE];
- if (value < 0)
- value = 0;
- tsdev->pressure = value;
- break;
- }
- break;
-
- case EV_REL:
- switch (code) {
- case REL_X:
- tsdev->x += value;
- if (tsdev->x < 0)
- tsdev->x = 0;
- else if (tsdev->x > xres)
- tsdev->x = xres;
- break;
-
- case REL_Y:
- tsdev->y += value;
- if (tsdev->y < 0)
- tsdev->y = 0;
- else if (tsdev->y > yres)
- tsdev->y = yres;
- break;
- }
- break;
-
- case EV_KEY:
- if (code == BTN_TOUCH || code == BTN_MOUSE) {
- switch (value) {
- case 0:
- tsdev->pressure = 0;
- break;
-
- case 1:
- if (!tsdev->pressure)
- tsdev->pressure = 1;
- break;
- }
- }
- break;
- }
-
- if (type != EV_SYN || code != SYN_REPORT)
- return;
-
- list_for_each_entry(client, &tsdev->client_list, node) {
- int x, y, tmp;
-
- do_gettimeofday(&time);
- client->event[client->head].millisecs = time.tv_usec / 1000;
- client->event[client->head].pressure = tsdev->pressure;
-
- x = tsdev->x;
- y = tsdev->y;
-
- /* Calibration */
- if (!client->raw) {
- x = ((x * tsdev->cal.xscale) >> 8) + tsdev->cal.xtrans;
- y = ((y * tsdev->cal.yscale) >> 8) + tsdev->cal.ytrans;
- if (tsdev->cal.xyswap) {
- tmp = x; x = y; y = tmp;
- }
- }
-
- client->event[client->head].x = x;
- client->event[client->head].y = y;
- client->head = (client->head + 1) & (TSDEV_BUFFER_SIZE - 1);
- kill_fasync(&client->fasync, SIGIO, POLL_IN);
- }
- wake_up_interruptible(&tsdev->wait);
-}
-
-static int tsdev_connect(struct input_handler *handler, struct input_dev *dev,
- const struct input_device_id *id)
-{
- struct tsdev *tsdev;
- int minor, delta;
- int error;
-
- for (minor = 0; minor < TSDEV_MINORS / 2 && tsdev_table[minor]; minor++);
- if (minor >= TSDEV_MINORS / 2) {
- printk(KERN_ERR
- "tsdev: You have way too many touchscreens\n");
- return -ENFILE;
- }
-
- tsdev = kzalloc(sizeof(struct tsdev), GFP_KERNEL);
- if (!tsdev)
- return -ENOMEM;
-
- INIT_LIST_HEAD(&tsdev->client_list);
- init_waitqueue_head(&tsdev->wait);
-
- tsdev->exist = 1;
- tsdev->minor = minor;
- tsdev->handle.dev = dev;
- tsdev->handle.name = tsdev->name;
- tsdev->handle.handler = handler;
- tsdev->handle.private = tsdev;
- snprintf(tsdev->name, sizeof(tsdev->name), "ts%d", minor);
-
- /* Precompute the rough calibration matrix */
- delta = dev->absmax [ABS_X] - dev->absmin [ABS_X] + 1;
- if (delta == 0)
- delta = 1;
- tsdev->cal.xscale = (xres << 8) / delta;
- tsdev->cal.xtrans = - ((dev->absmin [ABS_X] * tsdev->cal.xscale) >> 8);
-
- delta = dev->absmax [ABS_Y] - dev->absmin [ABS_Y] + 1;
- if (delta == 0)
- delta = 1;
- tsdev->cal.yscale = (yres << 8) / delta;
- tsdev->cal.ytrans = - ((dev->absmin [ABS_Y] * tsdev->cal.yscale) >> 8);
-
- snprintf(tsdev->dev.bus_id, sizeof(tsdev->dev.bus_id),
- "ts%d", minor);
- tsdev->dev.class = &input_class;
- tsdev->dev.parent = &dev->dev;
- tsdev->dev.devt = MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor);
- tsdev->dev.release = tsdev_free;
- device_initialize(&tsdev->dev);
-
- tsdev_table[minor] = tsdev;
-
- error = device_add(&tsdev->dev);
- if (error)
- goto err_free_tsdev;
-
- error = input_register_handle(&tsdev->handle);
- if (error)
- goto err_delete_tsdev;
-
- return 0;
-
- err_delete_tsdev:
- device_del(&tsdev->dev);
- err_free_tsdev:
- put_device(&tsdev->dev);
- return error;
-}
-
-static void tsdev_disconnect(struct input_handle *handle)
-{
- struct tsdev *tsdev = handle->private;
- struct tsdev_client *client;
-
- input_unregister_handle(handle);
- device_del(&tsdev->dev);
-
- tsdev->exist = 0;
-
- if (tsdev->open) {
- input_close_device(handle);
- list_for_each_entry(client, &tsdev->client_list, node)
- kill_fasync(&client->fasync, SIGIO, POLL_HUP);
- wake_up_interruptible(&tsdev->wait);
- }
-
- put_device(&tsdev->dev);
-}
-
-static const struct input_device_id tsdev_ids[] = {
- {
- .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_RELBIT,
- .evbit = { BIT(EV_KEY) | BIT(EV_REL) },
- .keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) },
- .relbit = { BIT(REL_X) | BIT(REL_Y) },
- }, /* A mouse like device, at least one button, two relative axes */
-
- {
- .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
- .evbit = { BIT(EV_KEY) | BIT(EV_ABS) },
- .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) },
- .absbit = { BIT(ABS_X) | BIT(ABS_Y) },
- }, /* A tablet like device, at least touch detection, two absolute axes */
-
- {
- .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
- .evbit = { BIT(EV_ABS) },
- .absbit = { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) },
- }, /* A tablet like device with several gradations of pressure */
-
- {} /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(input, tsdev_ids);
-
-static struct input_handler tsdev_handler = {
- .event = tsdev_event,
- .connect = tsdev_connect,
- .disconnect = tsdev_disconnect,
- .fops = &tsdev_fops,
- .minor = TSDEV_MINOR_BASE,
- .name = "tsdev",
- .id_table = tsdev_ids,
-};
-
-static int __init tsdev_init(void)
-{
- return input_register_handler(&tsdev_handler);
-}
-
-static void __exit tsdev_exit(void)
-{
- input_unregister_handler(&tsdev_handler);
-}
-
-module_init(tsdev_init);
-module_exit(tsdev_exit);
diff --git a/drivers/isdn/act2000/act2000_isa.c b/drivers/isdn/act2000/act2000_isa.c
index 09ea50dd3459..1bd8960ead33 100644
--- a/drivers/isdn/act2000/act2000_isa.c
+++ b/drivers/isdn/act2000/act2000_isa.c
@@ -61,7 +61,7 @@ act2000_isa_detect(unsigned short portbase)
}
static irqreturn_t
-act2000_isa_interrupt(int irq, void *dev_id)
+act2000_isa_interrupt(int dummy, void *dev_id)
{
act2000_card *card = dev_id;
u_char istatus;
@@ -80,7 +80,7 @@ act2000_isa_interrupt(int irq, void *dev_id)
printk(KERN_WARNING "act2000: errIRQ\n");
}
if (istatus)
- printk(KERN_DEBUG "act2000: ?IRQ %d %02x\n", irq, istatus);
+ printk(KERN_DEBUG "act2000: ?IRQ %d %02x\n", card->irq, istatus);
return IRQ_HANDLED;
}
@@ -126,11 +126,13 @@ act2000_isa_enable_irq(act2000_card * card)
/*
* Install interrupt handler, enable irq on card.
- * If irq is -1, choose next free irq, else irq is given explicitely.
+ * If irq is -1, choose next free irq, else irq is given explicitly.
*/
int
act2000_isa_config_irq(act2000_card * card, short irq)
{
+ int old_irq;
+
if (card->flags & ACT2000_FLAGS_IVALID) {
free_irq(card->irq, card);
}
@@ -139,8 +141,10 @@ act2000_isa_config_irq(act2000_card * card, short irq)
if (!irq)
return 0;
- if (!request_irq(irq, &act2000_isa_interrupt, 0, card->regname, card)) {
- card->irq = irq;
+ old_irq = card->irq;
+ card->irq = irq;
+ if (request_irq(irq, &act2000_isa_interrupt, 0, card->regname, card)) {
+ card->irq = old_irq;
card->flags |= ACT2000_FLAGS_IVALID;
printk(KERN_WARNING
"act2000: Could not request irq %d\n",irq);
diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c
index 23b6f7bc16b7..48c1775ef5b3 100644
--- a/drivers/isdn/capi/capidrv.c
+++ b/drivers/isdn/capi/capidrv.c
@@ -506,9 +506,14 @@ static void send_message(capidrv_contr * card, _cmsg * cmsg)
{
struct sk_buff *skb;
size_t len;
+
capi_cmsg2message(cmsg, cmsg->buf);
len = CAPIMSG_LEN(cmsg->buf);
skb = alloc_skb(len, GFP_ATOMIC);
+ if (!skb) {
+ printk(KERN_ERR "capidrv::send_message: can't allocate mem\n");
+ return;
+ }
memcpy(skb_put(skb, len), cmsg->buf, len);
if (capi20_put_message(&global.ap, skb) != CAPI_NOERROR)
kfree_skb(skb);
@@ -1838,6 +1843,7 @@ static int if_sendbuf(int id, int channel, int doack, struct sk_buff *skb)
int msglen;
u16 errcode;
u16 datahandle;
+ u32 data;
if (!card) {
printk(KERN_ERR "capidrv: if_sendbuf called with invalid driverId %d!\n",
@@ -1855,9 +1861,26 @@ static int if_sendbuf(int id, int channel, int doack, struct sk_buff *skb)
return 0;
}
datahandle = nccip->datahandle;
+
+ /*
+ * Here we copy pointer skb->data into the 32-bit 'Data' field.
+ * The 'Data' field is not used in practice in linux kernel
+ * (neither in 32 or 64 bit), but should have some value,
+ * since a CAPI message trace will display it.
+ *
+ * The correct value in the 32 bit case is the address of the
+ * data, in 64 bit it makes no sense, we use 0 there.
+ */
+
+#ifdef CONFIG_64BIT
+ data = 0;
+#else
+ data = (unsigned long) skb->data;
+#endif
+
capi_fill_DATA_B3_REQ(&sendcmsg, global.ap.applid, card->msgid++,
nccip->ncci, /* adr */
- (u32) skb->data, /* Data */
+ data, /* Data */
skb->len, /* DataLength */
datahandle, /* DataHandle */
0 /* Flags */
@@ -2118,7 +2141,10 @@ static int capidrv_delcontr(u16 contr)
printk(KERN_ERR "capidrv: delcontr: no contr %u\n", contr);
return -1;
}
- #warning FIXME: maybe a race condition the card should be removed here from global list /kkeil
+
+ /* FIXME: maybe a race condition the card should be removed
+ * here from global list /kkeil
+ */
spin_unlock_irqrestore(&global_lock, flags);
del_timer(&card->listentimer);
diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c
index 9f73bc2727c2..f55531869313 100644
--- a/drivers/isdn/capi/kcapi.c
+++ b/drivers/isdn/capi/kcapi.c
@@ -821,6 +821,8 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data)
return -EFAULT;
}
card = get_capi_ctr_by_nr(ldef.contr);
+ if (!card)
+ return -EINVAL;
card = capi_ctr_get(card);
if (!card)
return -ESRCH;
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c
index 00e31609a238..af7648274b38 100644
--- a/drivers/isdn/gigaset/bas-gigaset.c
+++ b/drivers/isdn/gigaset/bas-gigaset.c
@@ -1936,14 +1936,7 @@ static int gigaset_write_room(struct cardstate *cs)
*/
static int gigaset_chars_in_buffer(struct cardstate *cs)
{
- unsigned long flags;
- unsigned bytes;
-
- spin_lock_irqsave(&cs->cmdlock, flags);
- bytes = cs->cmdbytes;
- spin_unlock_irqrestore(&cs->cmdlock, flags);
-
- return bytes;
+ return cs->cmdbytes;
}
/* gigaset_brkchars
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c
index 6df336bdd571..acd417197d03 100644
--- a/drivers/isdn/gigaset/common.c
+++ b/drivers/isdn/gigaset/common.c
@@ -534,7 +534,8 @@ int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src,
n = RBUFSIZE - tail;
if (!n) {
dev_err(inbuf->cs->dev,
- "buffer overflow (%u bytes lost)", bytesleft);
+ "buffer overflow (%u bytes lost)\n",
+ bytesleft);
break;
}
if (n > bytesleft)
diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c
index 1654fa413575..9e089f06a942 100644
--- a/drivers/isdn/gigaset/i4l.c
+++ b/drivers/isdn/gigaset/i4l.c
@@ -109,13 +109,9 @@ EXPORT_SYMBOL_GPL(gigaset_skb_sent);
static int command_from_LL(isdn_ctrl *cntrl)
{
struct cardstate *cs = gigaset_get_cs_by_id(cntrl->driver);
- //isdn_ctrl response;
- //unsigned long flags;
struct bc_state *bcs;
int retval = 0;
struct setup_parm *sp;
- unsigned param;
- unsigned long flags;
gigaset_debugdrivers();
@@ -162,12 +158,8 @@ static int command_from_LL(isdn_ctrl *cntrl)
}
*sp = cntrl->parm.setup;
- spin_lock_irqsave(&cs->lock, flags);
- param = bcs->at_state.seq_index;
- spin_unlock_irqrestore(&cs->lock, flags);
-
- if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, sp, param,
- NULL)) {
+ if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, sp,
+ bcs->at_state.seq_index, NULL)) {
//FIXME what should we do?
kfree(sp);
gigaset_free_channel(bcs);
diff --git a/drivers/isdn/gigaset/proc.c b/drivers/isdn/gigaset/proc.c
index e767afa55abf..da6f3acf9fd0 100644
--- a/drivers/isdn/gigaset/proc.c
+++ b/drivers/isdn/gigaset/proc.c
@@ -19,15 +19,9 @@
static ssize_t show_cidmode(struct device *dev,
struct device_attribute *attr, char *buf)
{
- int ret;
- unsigned long flags;
struct cardstate *cs = dev_get_drvdata(dev);
- spin_lock_irqsave(&cs->lock, flags);
- ret = sprintf(buf, "%u\n", cs->cidmode);
- spin_unlock_irqrestore(&cs->lock, flags);
-
- return ret;
+ return sprintf(buf, "%u\n", cs->cidmode);
}
static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr,
diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c
index a1263019df5e..ca4bee173cfb 100644
--- a/drivers/isdn/gigaset/usb-gigaset.c
+++ b/drivers/isdn/gigaset/usb-gigaset.c
@@ -310,7 +310,6 @@ static void gigaset_modem_fill(unsigned long data)
struct cardstate *cs = (struct cardstate *) data;
struct bc_state *bcs = &cs->bcs[0]; /* only one channel */
struct cmdbuf_t *cb;
- unsigned long flags;
int again;
gig_dbg(DEBUG_OUTPUT, "modem_fill");
@@ -323,9 +322,7 @@ static void gigaset_modem_fill(unsigned long data)
do {
again = 0;
if (!bcs->tx_skb) { /* no skb is being sent */
- spin_lock_irqsave(&cs->cmdlock, flags);
cb = cs->cmdbuf;
- spin_unlock_irqrestore(&cs->cmdlock, flags);
if (cb) { /* commands to send? */
gig_dbg(DEBUG_OUTPUT, "modem_fill: cb");
if (send_cb(cs, cb) < 0) {
@@ -546,13 +543,9 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
static int gigaset_write_room(struct cardstate *cs)
{
- unsigned long flags;
unsigned bytes;
- spin_lock_irqsave(&cs->cmdlock, flags);
bytes = cs->cmdbytes;
- spin_unlock_irqrestore(&cs->cmdlock, flags);
-
return bytes < IF_WRITEBUF ? IF_WRITEBUF - bytes : 0;
}
diff --git a/drivers/isdn/hardware/avm/b1.c b/drivers/isdn/hardware/avm/b1.c
index 7a69a18d07e2..4484a6417235 100644
--- a/drivers/isdn/hardware/avm/b1.c
+++ b/drivers/isdn/hardware/avm/b1.c
@@ -321,12 +321,15 @@ void b1_reset_ctr(struct capi_ctr *ctrl)
avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
avmcard *card = cinfo->card;
unsigned int port = card->port;
+ unsigned long flags;
b1_reset(port);
b1_reset(port);
memset(cinfo->version, 0, sizeof(cinfo->version));
+ spin_lock_irqsave(&card->lock, flags);
capilib_release(&cinfo->ncci_head);
+ spin_unlock_irqrestore(&card->lock, flags);
capi_ctr_reseted(ctrl);
}
@@ -361,9 +364,8 @@ void b1_release_appl(struct capi_ctr *ctrl, u16 appl)
unsigned int port = card->port;
unsigned long flags;
- capilib_release_appl(&cinfo->ncci_head, appl);
-
spin_lock_irqsave(&card->lock, flags);
+ capilib_release_appl(&cinfo->ncci_head, appl);
b1_put_byte(port, SEND_RELEASE);
b1_put_word(port, appl);
spin_unlock_irqrestore(&card->lock, flags);
@@ -380,27 +382,27 @@ u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data);
u16 dlen, retval;
+ spin_lock_irqsave(&card->lock, flags);
if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
retval = capilib_data_b3_req(&cinfo->ncci_head,
CAPIMSG_APPID(skb->data),
CAPIMSG_NCCI(skb->data),
CAPIMSG_MSGID(skb->data));
- if (retval != CAPI_NOERROR)
+ if (retval != CAPI_NOERROR) {
+ spin_unlock_irqrestore(&card->lock, flags);
return retval;
+ }
dlen = CAPIMSG_DATALEN(skb->data);
- spin_lock_irqsave(&card->lock, flags);
b1_put_byte(port, SEND_DATA_B3_REQ);
b1_put_slice(port, skb->data, len);
b1_put_slice(port, skb->data + len, dlen);
- spin_unlock_irqrestore(&card->lock, flags);
} else {
- spin_lock_irqsave(&card->lock, flags);
b1_put_byte(port, SEND_MESSAGE);
b1_put_slice(port, skb->data, len);
- spin_unlock_irqrestore(&card->lock, flags);
}
+ spin_unlock_irqrestore(&card->lock, flags);
dev_kfree_skb_any(skb);
return CAPI_NOERROR;
@@ -534,17 +536,17 @@ irqreturn_t b1_interrupt(int interrupt, void *devptr)
ApplId = (unsigned) b1_get_word(card->port);
MsgLen = b1_get_slice(card->port, card->msgbuf);
- spin_unlock_irqrestore(&card->lock, flags);
if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) {
printk(KERN_ERR "%s: incoming packet dropped\n",
card->name);
+ spin_unlock_irqrestore(&card->lock, flags);
} else {
memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_CONF)
capilib_data_b3_conf(&cinfo->ncci_head, ApplId,
CAPIMSG_NCCI(skb->data),
CAPIMSG_MSGID(skb->data));
-
+ spin_unlock_irqrestore(&card->lock, flags);
capi_ctr_handle_message(ctrl, ApplId, skb);
}
break;
@@ -554,21 +556,17 @@ irqreturn_t b1_interrupt(int interrupt, void *devptr)
ApplId = b1_get_word(card->port);
NCCI = b1_get_word(card->port);
WindowSize = b1_get_word(card->port);
- spin_unlock_irqrestore(&card->lock, flags);
-
capilib_new_ncci(&cinfo->ncci_head, ApplId, NCCI, WindowSize);
-
+ spin_unlock_irqrestore(&card->lock, flags);
break;
case RECEIVE_FREE_NCCI:
ApplId = b1_get_word(card->port);
NCCI = b1_get_word(card->port);
- spin_unlock_irqrestore(&card->lock, flags);
-
if (NCCI != 0xffffffff)
capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI);
-
+ spin_unlock_irqrestore(&card->lock, flags);
break;
case RECEIVE_START:
diff --git a/drivers/isdn/hardware/avm/b1dma.c b/drivers/isdn/hardware/avm/b1dma.c
index 428872b653e9..669f6f67449c 100644
--- a/drivers/isdn/hardware/avm/b1dma.c
+++ b/drivers/isdn/hardware/avm/b1dma.c
@@ -486,11 +486,13 @@ static void b1dma_handle_rx(avmcard *card)
card->name);
} else {
memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
- if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_CONF)
+ if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_CONF) {
+ spin_lock(&card->lock);
capilib_data_b3_conf(&cinfo->ncci_head, ApplId,
- CAPIMSG_NCCI(skb->data),
- CAPIMSG_MSGID(skb->data));
-
+ CAPIMSG_NCCI(skb->data),
+ CAPIMSG_MSGID(skb->data));
+ spin_unlock(&card->lock);
+ }
capi_ctr_handle_message(ctrl, ApplId, skb);
}
break;
@@ -500,9 +502,9 @@ static void b1dma_handle_rx(avmcard *card)
ApplId = _get_word(&p);
NCCI = _get_word(&p);
WindowSize = _get_word(&p);
-
+ spin_lock(&card->lock);
capilib_new_ncci(&cinfo->ncci_head, ApplId, NCCI, WindowSize);
-
+ spin_unlock(&card->lock);
break;
case RECEIVE_FREE_NCCI:
@@ -510,9 +512,11 @@ static void b1dma_handle_rx(avmcard *card)
ApplId = _get_word(&p);
NCCI = _get_word(&p);
- if (NCCI != 0xffffffff)
+ if (NCCI != 0xffffffff) {
+ spin_lock(&card->lock);
capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI);
-
+ spin_unlock(&card->lock);
+ }
break;
case RECEIVE_START:
@@ -751,10 +755,10 @@ void b1dma_reset_ctr(struct capi_ctr *ctrl)
spin_lock_irqsave(&card->lock, flags);
b1dma_reset(card);
- spin_unlock_irqrestore(&card->lock, flags);
memset(cinfo->version, 0, sizeof(cinfo->version));
capilib_release(&cinfo->ncci_head);
+ spin_unlock_irqrestore(&card->lock, flags);
capi_ctr_reseted(ctrl);
}
@@ -803,8 +807,11 @@ void b1dma_release_appl(struct capi_ctr *ctrl, u16 appl)
avmcard *card = cinfo->card;
struct sk_buff *skb;
void *p;
+ unsigned long flags;
+ spin_lock_irqsave(&card->lock, flags);
capilib_release_appl(&cinfo->ncci_head, appl);
+ spin_unlock_irqrestore(&card->lock, flags);
skb = alloc_skb(7, GFP_ATOMIC);
if (!skb) {
@@ -832,10 +839,13 @@ u16 b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
u16 retval = CAPI_NOERROR;
if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) {
+ unsigned long flags;
+ spin_lock_irqsave(&card->lock, flags);
retval = capilib_data_b3_req(&cinfo->ncci_head,
CAPIMSG_APPID(skb->data),
CAPIMSG_NCCI(skb->data),
CAPIMSG_MSGID(skb->data));
+ spin_unlock_irqrestore(&card->lock, flags);
}
if (retval == CAPI_NOERROR)
b1dma_queue_tx(card, skb);
diff --git a/drivers/isdn/hardware/avm/c4.c b/drivers/isdn/hardware/avm/c4.c
index d58f927e766a..4bbbbe688077 100644
--- a/drivers/isdn/hardware/avm/c4.c
+++ b/drivers/isdn/hardware/avm/c4.c
@@ -678,7 +678,9 @@ static irqreturn_t c4_handle_interrupt(avmcard *card)
for (i=0; i < card->nr_controllers; i++) {
avmctrl_info *cinfo = &card->ctrlinfo[i];
memset(cinfo->version, 0, sizeof(cinfo->version));
+ spin_lock_irqsave(&card->lock, flags);
capilib_release(&cinfo->ncci_head);
+ spin_unlock_irqrestore(&card->lock, flags);
capi_ctr_reseted(&cinfo->capi_ctrl);
}
card->nlogcontr = 0;
@@ -727,6 +729,7 @@ static void c4_send_init(avmcard *card)
{
struct sk_buff *skb;
void *p;
+ unsigned long flags;
skb = alloc_skb(15, GFP_ATOMIC);
if (!skb) {
@@ -744,12 +747,15 @@ static void c4_send_init(avmcard *card)
skb_put(skb, (u8 *)p - (u8 *)skb->data);
skb_queue_tail(&card->dma->send_queue, skb);
+ spin_lock_irqsave(&card->lock, flags);
c4_dispatch_tx(card);
+ spin_unlock_irqrestore(&card->lock, flags);
}
static int queue_sendconfigword(avmcard *card, u32 val)
{
struct sk_buff *skb;
+ unsigned long flags;
void *p;
skb = alloc_skb(3+4, GFP_ATOMIC);
@@ -766,7 +772,9 @@ static int queue_sendconfigword(avmcard *card, u32 val)
skb_put(skb, (u8 *)p - (u8 *)skb->data);
skb_queue_tail(&card->dma->send_queue, skb);
+ spin_lock_irqsave(&card->lock, flags);
c4_dispatch_tx(card);
+ spin_unlock_irqrestore(&card->lock, flags);
return 0;
}
@@ -986,7 +994,9 @@ static void c4_release_appl(struct capi_ctr *ctrl, u16 appl)
struct sk_buff *skb;
void *p;
+ spin_lock_irqsave(&card->lock, flags);
capilib_release_appl(&cinfo->ncci_head, appl);
+ spin_unlock_irqrestore(&card->lock, flags);
if (ctrl->cnr == card->cardnr) {
skb = alloc_skb(7, GFP_ATOMIC);
@@ -1019,7 +1029,8 @@ static u16 c4_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
u16 retval = CAPI_NOERROR;
unsigned long flags;
- if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) {
+ spin_lock_irqsave(&card->lock, flags);
+ if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) {
retval = capilib_data_b3_req(&cinfo->ncci_head,
CAPIMSG_APPID(skb->data),
CAPIMSG_NCCI(skb->data),
@@ -1027,10 +1038,9 @@ static u16 c4_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
}
if (retval == CAPI_NOERROR) {
skb_queue_tail(&card->dma->send_queue, skb);
- spin_lock_irqsave(&card->lock, flags);
c4_dispatch_tx(card);
- spin_unlock_irqrestore(&card->lock, flags);
}
+ spin_unlock_irqrestore(&card->lock, flags);
return retval;
}
diff --git a/drivers/isdn/hardware/avm/t1isa.c b/drivers/isdn/hardware/avm/t1isa.c
index c925020fe9b7..6130724e46e7 100644
--- a/drivers/isdn/hardware/avm/t1isa.c
+++ b/drivers/isdn/hardware/avm/t1isa.c
@@ -180,8 +180,8 @@ static irqreturn_t t1isa_interrupt(int interrupt, void *devptr)
ApplId = (unsigned) b1_get_word(card->port);
MsgLen = t1_get_slice(card->port, card->msgbuf);
- spin_unlock_irqrestore(&card->lock, flags);
if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) {
+ spin_unlock_irqrestore(&card->lock, flags);
printk(KERN_ERR "%s: incoming packet dropped\n",
card->name);
} else {
@@ -190,7 +190,7 @@ static irqreturn_t t1isa_interrupt(int interrupt, void *devptr)
capilib_data_b3_conf(&cinfo->ncci_head, ApplId,
CAPIMSG_NCCI(skb->data),
CAPIMSG_MSGID(skb->data));
-
+ spin_unlock_irqrestore(&card->lock, flags);
capi_ctr_handle_message(ctrl, ApplId, skb);
}
break;
@@ -200,21 +200,17 @@ static irqreturn_t t1isa_interrupt(int interrupt, void *devptr)
ApplId = b1_get_word(card->port);
NCCI = b1_get_word(card->port);
WindowSize = b1_get_word(card->port);
- spin_unlock_irqrestore(&card->lock, flags);
-
capilib_new_ncci(&cinfo->ncci_head, ApplId, NCCI, WindowSize);
-
+ spin_unlock_irqrestore(&card->lock, flags);
break;
case RECEIVE_FREE_NCCI:
ApplId = b1_get_word(card->port);
NCCI = b1_get_word(card->port);
- spin_unlock_irqrestore(&card->lock, flags);
-
if (NCCI != 0xffffffff)
capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI);
-
+ spin_unlock_irqrestore(&card->lock, flags);
break;
case RECEIVE_START:
@@ -333,13 +329,16 @@ static void t1isa_reset_ctr(struct capi_ctr *ctrl)
avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
avmcard *card = cinfo->card;
unsigned int port = card->port;
+ unsigned long flags;
t1_disable_irq(port);
b1_reset(port);
b1_reset(port);
memset(cinfo->version, 0, sizeof(cinfo->version));
+ spin_lock_irqsave(&card->lock, flags);
capilib_release(&cinfo->ncci_head);
+ spin_unlock_irqrestore(&card->lock, flags);
capi_ctr_reseted(ctrl);
}
@@ -466,29 +465,26 @@ static u16 t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data);
u16 dlen, retval;
+ spin_lock_irqsave(&card->lock, flags);
if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
retval = capilib_data_b3_req(&cinfo->ncci_head,
CAPIMSG_APPID(skb->data),
CAPIMSG_NCCI(skb->data),
CAPIMSG_MSGID(skb->data));
- if (retval != CAPI_NOERROR)
+ if (retval != CAPI_NOERROR) {
+ spin_unlock_irqrestore(&card->lock, flags);
return retval;
-
+ }
dlen = CAPIMSG_DATALEN(skb->data);
- spin_lock_irqsave(&card->lock, flags);
b1_put_byte(port, SEND_DATA_B3_REQ);
t1_put_slice(port, skb->data, len);
t1_put_slice(port, skb->data + len, dlen);
- spin_unlock_irqrestore(&card->lock, flags);
} else {
-
- spin_lock_irqsave(&card->lock, flags);
b1_put_byte(port, SEND_MESSAGE);
t1_put_slice(port, skb->data, len);
- spin_unlock_irqrestore(&card->lock, flags);
}
-
+ spin_unlock_irqrestore(&card->lock, flags);
dev_kfree_skb_any(skb);
return CAPI_NOERROR;
}
diff --git a/drivers/isdn/hardware/eicon/capifunc.c b/drivers/isdn/hardware/eicon/capifunc.c
index 82edc1c1db7a..4d425c644d41 100644
--- a/drivers/isdn/hardware/eicon/capifunc.c
+++ b/drivers/isdn/hardware/eicon/capifunc.c
@@ -321,7 +321,7 @@ void sendf(APPL * appl, word command, dword Id, word Number, byte * format, ...)
DBG_BLK((((char *)(long)GET_DWORD(&msg.info.data_b3_ind.Data)) + i,
((dlength - i) < 256) ? (dlength - i) : 256))
if (!(myDriverDebugHandle.dbgMask & DL_PRV0))
- break; /* not more if not explicitely requested */
+ break; /* not more if not explicitly requested */
}
}
break;
@@ -965,7 +965,7 @@ static u16 diva_send_message(struct capi_ctr *ctrl,
((GET_WORD(&msg->info.data_b3_req.Data_Length) - j) <
256) ? (GET_WORD(&msg->info.data_b3_req.Data_Length) - j) : 256))
if (!(myDriverDebugHandle.dbgMask & DL_PRV0))
- break; /* not more if not explicitely requested */
+ break; /* not more if not explicitly requested */
}
}
#endif
diff --git a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig
index a3b945ac3256..7832d8ba8e44 100644
--- a/drivers/isdn/hisax/Kconfig
+++ b/drivers/isdn/hisax/Kconfig
@@ -109,7 +109,7 @@ config HISAX_16_3
config HISAX_TELESPCI
bool "Teles PCI"
- depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV))
+ depends on PCI && PCI_LEGACY && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV))
help
This enables HiSax support for the Teles PCI.
See <file:Documentation/isdn/README.HiSax> on how to configure it.
@@ -237,7 +237,7 @@ config HISAX_MIC
config HISAX_NETJET
bool "NETjet card"
- depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV))
+ depends on PCI && PCI_LEGACY && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV))
help
This enables HiSax support for the NetJet from Traverse
Technologies.
@@ -248,7 +248,7 @@ config HISAX_NETJET
config HISAX_NETJET_U
bool "NETspider U card"
- depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV))
+ depends on PCI && PCI_LEGACY && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV))
help
This enables HiSax support for the Netspider U interface ISDN card
from Traverse Technologies.
@@ -287,7 +287,7 @@ config HISAX_HSTSAPHIR
config HISAX_BKM_A4T
bool "Telekom A4T card"
- depends on PCI
+ depends on PCI && PCI_LEGACY
help
This enables HiSax support for the Telekom A4T card.
@@ -297,7 +297,7 @@ config HISAX_BKM_A4T
config HISAX_SCT_QUADRO
bool "Scitel Quadro card"
- depends on PCI
+ depends on PCI && PCI_LEGACY
help
This enables HiSax support for the Scitel Quadro card.
@@ -316,7 +316,7 @@ config HISAX_GAZEL
config HISAX_HFC_PCI
bool "HFC PCI-Bus cards"
- depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV))
+ depends on PCI && PCI_LEGACY && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV))
help
This enables HiSax support for the HFC-S PCI 2BDS0 based cards.
@@ -325,7 +325,7 @@ config HISAX_HFC_PCI
config HISAX_W6692
bool "Winbond W6692 based cards"
- depends on PCI
+ depends on PCI && PCI_LEGACY
help
This enables HiSax support for Winbond W6692 based PCI ISDN cards.
@@ -341,7 +341,7 @@ config HISAX_HFC_SX
config HISAX_ENTERNOW_PCI
bool "Formula-n enter:now PCI card"
- depends on HISAX_NETJET && PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV))
+ depends on HISAX_NETJET && PCI && PCI_LEGACY && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV))
help
This enables HiSax support for the Formula-n enter:now PCI
ISDN card.
@@ -411,7 +411,7 @@ config HISAX_HFC4S8S
config HISAX_FRITZ_PCIPNP
tristate "AVM Fritz!Card PCI/PCIv2/PnP support (EXPERIMENTAL)"
- depends on PCI && EXPERIMENTAL
+ depends on PCI && PCI_LEGACY && EXPERIMENTAL
help
This enables the driver for the AVM Fritz!Card PCI,
Fritz!Card PCI v2 and Fritz!Card PnP.
diff --git a/drivers/isdn/hisax/amd7930_fn.c b/drivers/isdn/hisax/amd7930_fn.c
index 3b19caeba258..c0d7036404a5 100644
--- a/drivers/isdn/hisax/amd7930_fn.c
+++ b/drivers/isdn/hisax/amd7930_fn.c
@@ -767,7 +767,7 @@ Amd7930_init(struct IsdnCardState *cs)
/* read */
if (*ptr++ >= 0x100) {
if (cmd < 8)
- /* setzt Register zurück */
+ /* reset register */
rByteAMD(cs, cmd);
else {
wByteAMD(cs, 0x00, cmd);
diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c
index f8b79783c8b3..035d158779df 100644
--- a/drivers/isdn/hisax/avm_pci.c
+++ b/drivers/isdn/hisax/avm_pci.c
@@ -830,7 +830,7 @@ static int __devinit avm_pnp_setup(struct IsdnCardState *cs)
#endif /* __ISAPNP__ */
-#ifndef CONFIG_PCI
+#ifndef CONFIG_PCI_LEGACY
static int __devinit avm_pci_setup(struct IsdnCardState *cs)
{
@@ -872,7 +872,7 @@ static int __devinit avm_pci_setup(struct IsdnCardState *cs)
return (1);
}
-#endif /* CONFIG_PCI */
+#endif /* CONFIG_PCI_LEGACY */
int __devinit
setup_avm_pcipnp(struct IsdnCard *card)
diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c
index 826745078746..2d670856d141 100644
--- a/drivers/isdn/hisax/diva.c
+++ b/drivers/isdn/hisax/diva.c
@@ -1148,7 +1148,7 @@ static int __devinit setup_diva_isapnp(struct IsdnCard *card)
#endif /* ISAPNP */
-#ifdef CONFIG_PCI
+#ifdef CONFIG_PCI_LEGACY
static struct pci_dev *dev_diva __devinitdata = NULL;
static struct pci_dev *dev_diva_u __devinitdata = NULL;
static struct pci_dev *dev_diva201 __devinitdata = NULL;
@@ -1229,14 +1229,14 @@ static int __devinit setup_diva_pci(struct IsdnCard *card)
return (1); /* card found */
}
-#else /* if !CONFIG_PCI */
+#else /* if !CONFIG_PCI_LEGACY */
static int __devinit setup_diva_pci(struct IsdnCard *card)
{
return (-1); /* card not found; continue search */
}
-#endif /* CONFIG_PCI */
+#endif /* CONFIG_PCI_LEGACY */
int __devinit
setup_diva(struct IsdnCard *card)
diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c
index 948a9b290fd1..d272d8ce6537 100644
--- a/drivers/isdn/hisax/elsa.c
+++ b/drivers/isdn/hisax/elsa.c
@@ -883,7 +883,7 @@ setup_elsa_isa(struct IsdnCard *card)
val += 'A' - 3;
if (val == 'B' || val == 'C')
val ^= 1;
- if ((cs->subtyp == ELSA_PCFPRO) && (val = 'G'))
+ if ((cs->subtyp == ELSA_PCFPRO) && (val == 'G'))
val = 'C';
printk(KERN_INFO
"Elsa: %s found at %#lx Rev.:%c IRQ %d\n",
@@ -1025,7 +1025,7 @@ setup_elsa_pcmcia(struct IsdnCard *card)
cs->irq);
}
-#ifdef CONFIG_PCI
+#ifdef CONFIG_PCI_LEGACY
static struct pci_dev *dev_qs1000 __devinitdata = NULL;
static struct pci_dev *dev_qs3000 __devinitdata = NULL;
@@ -1093,7 +1093,7 @@ setup_elsa_pci(struct IsdnCard *card)
{
return (1);
}
-#endif /* CONFIG_PCI */
+#endif /* CONFIG_PCI_LEGACY */
static int __devinit
setup_elsa_common(struct IsdnCard *card)
diff --git a/drivers/isdn/hisax/enternow_pci.c b/drivers/isdn/hisax/enternow_pci.c
index b73027ff50e8..39f421ed8de8 100644
--- a/drivers/isdn/hisax/enternow_pci.c
+++ b/drivers/isdn/hisax/enternow_pci.c
@@ -75,16 +75,16 @@
static const char *enternow_pci_rev = "$Revision: 1.1.4.5 $";
-/* für PowerISDN PCI */
+/* for PowerISDN PCI */
#define TJ_AMD_IRQ 0x20
#define TJ_LED1 0x40
#define TJ_LED2 0x80
-/* Das Fenster zum AMD...
- * Ab Adresse hw.njet.base + TJ_AMD_PORT werden vom AMD jeweils 8 Bit in
- * den TigerJet i/o-Raum gemappt
- * -> 0x01 des AMD bei hw.njet.base + 0C4 */
+/* The window to [the] AMD [chip]...
+ * From address hw.njet.base + TJ_AMD_PORT onwards, the AMD
+ * maps [consecutive/multiple] 8 bits into the TigerJet I/O space
+ * -> 0x01 of the AMD at hw.njet.base + 0C4 */
#define TJ_AMD_PORT 0xC0
@@ -96,11 +96,11 @@ static const char *enternow_pci_rev = "$Revision: 1.1.4.5 $";
static unsigned char
ReadByteAmd7930(struct IsdnCardState *cs, unsigned char offset)
{
- /* direktes Register */
+ /* direct register */
if(offset < 8)
return (inb(cs->hw.njet.isac + 4*offset));
- /* indirektes Register */
+ /* indirect register */
else {
outb(offset, cs->hw.njet.isac + 4*AMD_CR);
return(inb(cs->hw.njet.isac + 4*AMD_DR));
@@ -111,11 +111,11 @@ ReadByteAmd7930(struct IsdnCardState *cs, unsigned char offset)
static void
WriteByteAmd7930(struct IsdnCardState *cs, unsigned char offset, unsigned char value)
{
- /* direktes Register */
+ /* direct register */
if(offset < 8)
outb(value, cs->hw.njet.isac + 4*offset);
- /* indirektes Register */
+ /* indirect register */
else {
outb(offset, cs->hw.njet.isac + 4*AMD_CR);
outb(value, cs->hw.njet.isac + 4*AMD_DR);
diff --git a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c
index 3efa719b6d29..f66620ad8e7c 100644
--- a/drivers/isdn/hisax/gazel.c
+++ b/drivers/isdn/hisax/gazel.c
@@ -532,6 +532,7 @@ setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs)
return (0);
}
+#ifdef CONFIG_PCI_LEGACY
static struct pci_dev *dev_tel __devinitdata = NULL;
static int __devinit
@@ -620,6 +621,7 @@ setup_gazelpci(struct IsdnCardState *cs)
return (0);
}
+#endif /* CONFIG_PCI_LEGACY */
int __devinit
setup_gazel(struct IsdnCard *card)
@@ -639,7 +641,7 @@ setup_gazel(struct IsdnCard *card)
return (0);
} else {
-#ifdef CONFIG_PCI
+#ifdef CONFIG_PCI_LEGACY
if (setup_gazelpci(cs))
return (0);
#else
diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
index 077080aca799..fba8b624ffcf 100644
--- a/drivers/isdn/hisax/hfc_pci.c
+++ b/drivers/isdn/hisax/hfc_pci.c
@@ -1,6 +1,6 @@
/* $Id: hfc_pci.c,v 1.48.2.4 2004/02/11 13:21:33 keil Exp $
*
- * low level driver for CCD´s hfc-pci based cards
+ * low level driver for CCD's hfc-pci based cards
*
* Author Werner Cornelius
* based on existing driver for CCD hfc ISA cards
diff --git a/drivers/isdn/hisax/isdnhdlc.c b/drivers/isdn/hisax/isdnhdlc.c
index 268dced6c34a..c69a77a80062 100644
--- a/drivers/isdn/hisax/isdnhdlc.c
+++ b/drivers/isdn/hisax/isdnhdlc.c
@@ -1,7 +1,7 @@
/*
* isdnhdlc.c -- General purpose ISDN HDLC decoder.
*
- *Copyright (C) 2002 Wolfgang Mües <wolfgang@iksw-muees.de>
+ *Copyright (C) 2002 Wolfgang Mües <wolfgang@iksw-muees.de>
* 2001 Frode Isaksen <fisaksen@bewan.com>
* 2001 Kai Germaschewski <kai.germaschewski@gmx.de>
*
@@ -27,7 +27,7 @@
/*-------------------------------------------------------------------*/
-MODULE_AUTHOR("Wolfgang Mües <wolfgang@iksw-muees.de>, "
+MODULE_AUTHOR("Wolfgang Mües <wolfgang@iksw-muees.de>, "
"Frode Isaksen <fisaksen@bewan.com>, "
"Kai Germaschewski <kai.germaschewski@gmx.de>");
MODULE_DESCRIPTION("General purpose ISDN HDLC decoder");
diff --git a/drivers/isdn/hisax/isdnhdlc.h b/drivers/isdn/hisax/isdnhdlc.h
index 45167d2f8fb0..cf0a95a24015 100644
--- a/drivers/isdn/hisax/isdnhdlc.h
+++ b/drivers/isdn/hisax/isdnhdlc.h
@@ -5,7 +5,7 @@
* Neccessary because some ISDN devices don't have HDLC
* controllers. Also included: a bit reversal table.
*
- *Copyright (C) 2002 Wolfgang Mües <wolfgang@iksw-muees.de>
+ *Copyright (C) 2002 Wolfgang Mües <wolfgang@iksw-muees.de>
* 2001 Frode Isaksen <fisaksen@bewan.com>
* 2001 Kai Germaschewski <kai.germaschewski@gmx.de>
*
diff --git a/drivers/isdn/hisax/jade.c b/drivers/isdn/hisax/jade.c
index 43d61d1bc5b6..70840a710acf 100644
--- a/drivers/isdn/hisax/jade.c
+++ b/drivers/isdn/hisax/jade.c
@@ -304,7 +304,7 @@ initjade(struct IsdnCardState *cs)
cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR, 0x00);
/* Setup host access to hdlc controller */
jade_write_indirect(cs, jade_HDLCCNTRACCESS, (jadeINDIRECT_HAH1|jadeINDIRECT_HAH2));
- /* Unmask HDLC int (don´t forget DSP int later on)*/
+ /* Unmask HDLC int (don't forget DSP int later on)*/
cs->BC_Write_Reg(cs, -1,jade_INT, (jadeINT_HDLC1|jadeINT_HDLC2));
/* once again TRANSPARENT */
diff --git a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c
index e5918c6fe73d..bd9921128aa8 100644
--- a/drivers/isdn/hisax/niccy.c
+++ b/drivers/isdn/hisax/niccy.c
@@ -223,7 +223,6 @@ static int niccy_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return 0;
}
-static struct pci_dev *niccy_dev __devinitdata = NULL;
#ifdef __ISAPNP__
static struct pnp_card *pnp_c __devinitdata = NULL;
#endif
@@ -299,7 +298,9 @@ int __devinit setup_niccy(struct IsdnCard *card)
return 0;
}
} else {
-#ifdef CONFIG_PCI
+#ifdef CONFIG_PCI_LEGACY
+ static struct pci_dev *niccy_dev __devinitdata;
+
u_int pci_ioaddr;
cs->subtyp = 0;
if ((niccy_dev = pci_find_device(PCI_VENDOR_ID_SATSAGEM,
@@ -356,7 +357,7 @@ int __devinit setup_niccy(struct IsdnCard *card)
printk(KERN_WARNING "Niccy: io0 0 and NO_PCI_BIOS\n");
printk(KERN_WARNING "Niccy: unable to config NICCY PCI\n");
return 0;
-#endif /* CONFIG_PCI */
+#endif /* CONFIG_PCI_LEGACY */
}
printk(KERN_INFO "HiSax: %s %s config irq:%d data:0x%X ale:0x%X\n",
CardType[cs->typ], (cs->subtyp == 1) ? "PnP" : "PCI",
diff --git a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c
index 03dfc32166a0..95425f3d2220 100644
--- a/drivers/isdn/hisax/sedlbauer.c
+++ b/drivers/isdn/hisax/sedlbauer.c
@@ -600,7 +600,7 @@ setup_sedlbauer_isapnp(struct IsdnCard *card, int *bytecnt)
}
#endif /* __ISAPNP__ */
-#ifdef CONFIG_PCI
+#ifdef CONFIG_PCI_LEGACY
static struct pci_dev *dev_sedl __devinitdata = NULL;
static int __devinit
@@ -675,7 +675,7 @@ setup_sedlbauer_pci(struct IsdnCard *card)
return (1);
}
-#endif /* CONFIG_PCI */
+#endif /* CONFIG_PCI_LEGACY */
int __devinit
setup_sedlbauer(struct IsdnCard *card)
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
index 4910bca52640..c6df2925ebd0 100644
--- a/drivers/isdn/i4l/isdn_common.c
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -1365,7 +1365,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
} else {
s = NULL;
}
- ret = down_interruptible(&dev->sem);
+ ret = mutex_lock_interruptible(&dev->mtx);
if( ret ) return ret;
if ((s = isdn_net_new(s, NULL))) {
if (copy_to_user(argp, s, strlen(s) + 1)){
@@ -1375,7 +1375,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
}
} else
ret = -ENODEV;
- up(&dev->sem);
+ mutex_unlock(&dev->mtx);
return ret;
case IIOCNETASL:
/* Add a slave to a network-interface */
@@ -1384,7 +1384,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
return -EFAULT;
} else
return -EINVAL;
- ret = down_interruptible(&dev->sem);
+ ret = mutex_lock_interruptible(&dev->mtx);
if( ret ) return ret;
if ((s = isdn_net_newslave(bname))) {
if (copy_to_user(argp, s, strlen(s) + 1)){
@@ -1394,17 +1394,17 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
}
} else
ret = -ENODEV;
- up(&dev->sem);
+ mutex_unlock(&dev->mtx);
return ret;
case IIOCNETDIF:
/* Delete a network-interface */
if (arg) {
if (copy_from_user(name, argp, sizeof(name)))
return -EFAULT;
- ret = down_interruptible(&dev->sem);
+ ret = mutex_lock_interruptible(&dev->mtx);
if( ret ) return ret;
ret = isdn_net_rm(name);
- up(&dev->sem);
+ mutex_unlock(&dev->mtx);
return ret;
} else
return -EINVAL;
@@ -1433,10 +1433,10 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
if (arg) {
if (copy_from_user(&phone, argp, sizeof(phone)))
return -EFAULT;
- ret = down_interruptible(&dev->sem);
+ ret = mutex_lock_interruptible(&dev->mtx);
if( ret ) return ret;
ret = isdn_net_addphone(&phone);
- up(&dev->sem);
+ mutex_unlock(&dev->mtx);
return ret;
} else
return -EINVAL;
@@ -1445,10 +1445,10 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
if (arg) {
if (copy_from_user(&phone, argp, sizeof(phone)))
return -EFAULT;
- ret = down_interruptible(&dev->sem);
+ ret = mutex_lock_interruptible(&dev->mtx);
if( ret ) return ret;
ret = isdn_net_getphones(&phone, argp);
- up(&dev->sem);
+ mutex_unlock(&dev->mtx);
return ret;
} else
return -EINVAL;
@@ -1457,10 +1457,10 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
if (arg) {
if (copy_from_user(&phone, argp, sizeof(phone)))
return -EFAULT;
- ret = down_interruptible(&dev->sem);
+ ret = mutex_lock_interruptible(&dev->mtx);
if( ret ) return ret;
ret = isdn_net_delphone(&phone);
- up(&dev->sem);
+ mutex_unlock(&dev->mtx);
return ret;
} else
return -EINVAL;
@@ -2304,7 +2304,7 @@ static int __init isdn_init(void)
#ifdef MODULE
dev->owner = THIS_MODULE;
#endif
- init_MUTEX(&dev->sem);
+ mutex_init(&dev->mtx);
init_waitqueue_head(&dev->info_waitq);
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
dev->drvmap[i] = -1;
diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c
index 7c9cb7e19f2e..b39d1f5b378e 100644
--- a/drivers/isdn/i4l/isdn_net.c
+++ b/drivers/isdn/i4l/isdn_net.c
@@ -328,7 +328,7 @@ isdn_net_autohup(void)
l->cps = (l->transcount * HZ) / (jiffies - last_jiffies);
l->transcount = 0;
if (dev->net_verbose > 3)
- printk(KERN_DEBUG "%s: %d bogocps\n", l->name, l->cps);
+ printk(KERN_DEBUG "%s: %d bogocps\n", p->dev->name, l->cps);
if ((l->flags & ISDN_NET_CONNECTED) && (!l->dialstate)) {
anymore = 1;
l->huptimer++;
@@ -350,12 +350,12 @@ isdn_net_autohup(void)
if (l->hupflags & ISDN_CHARGEHUP) {
if (l->hupflags & ISDN_WAITCHARGE) {
printk(KERN_DEBUG "isdn_net: Hupflags of %s are %X\n",
- l->name, l->hupflags);
+ p->dev->name, l->hupflags);
isdn_net_hangup(p->dev);
} else if (time_after(jiffies, l->chargetime + l->chargeint)) {
printk(KERN_DEBUG
"isdn_net: %s: chtime = %lu, chint = %d\n",
- l->name, l->chargetime, l->chargeint);
+ p->dev->name, l->chargetime, l->chargeint);
isdn_net_hangup(p->dev);
}
} else
@@ -442,8 +442,8 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c)
#endif
isdn_net_lp_disconnected(lp);
isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
- printk(KERN_INFO "%s: remote hangup\n", lp->name);
- printk(KERN_INFO "%s: Chargesum is %d\n", lp->name,
+ printk(KERN_INFO "%s: remote hangup\n", p->dev->name);
+ printk(KERN_INFO "%s: Chargesum is %d\n", p->dev->name,
lp->charge);
isdn_net_unbind_channel(lp);
return 1;
@@ -487,7 +487,7 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c)
isdn_net_add_to_bundle(nd, lp);
}
}
- printk(KERN_INFO "isdn_net: %s connected\n", lp->name);
+ printk(KERN_INFO "isdn_net: %s connected\n", p->dev->name);
/* If first Chargeinfo comes before B-Channel connect,
* we correct the timestamp here.
*/
@@ -534,7 +534,7 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c)
lp->hupflags |= ISDN_HAVECHARGE;
lp->chargetime = jiffies;
printk(KERN_DEBUG "isdn_net: Got CINF chargetime of %s now %lu\n",
- lp->name, lp->chargetime);
+ p->dev->name, lp->chargetime);
return 1;
}
}
@@ -565,7 +565,7 @@ isdn_net_dial(void)
#ifdef ISDN_DEBUG_NET_DIAL
if (lp->dialstate)
- printk(KERN_DEBUG "%s: dialstate=%d\n", lp->name, lp->dialstate);
+ printk(KERN_DEBUG "%s: dialstate=%d\n", p->dev->name, lp->dialstate);
#endif
switch (lp->dialstate) {
case 0:
@@ -578,7 +578,7 @@ isdn_net_dial(void)
lp->dial = lp->phone[1];
if (!lp->dial) {
printk(KERN_WARNING "%s: phone number deleted?\n",
- lp->name);
+ p->dev->name);
isdn_net_hangup(p->dev);
break;
}
@@ -632,13 +632,13 @@ isdn_net_dial(void)
cmd.arg = lp->isdn_channel;
if (!lp->dial) {
printk(KERN_WARNING "%s: phone number deleted?\n",
- lp->name);
+ p->dev->name);
isdn_net_hangup(p->dev);
break;
}
if (!strncmp(lp->dial->num, "LEASED", strlen("LEASED"))) {
lp->dialstate = 4;
- printk(KERN_INFO "%s: Open leased line ...\n", lp->name);
+ printk(KERN_INFO "%s: Open leased line ...\n", p->dev->name);
} else {
if(lp->dialtimeout > 0)
if (time_after(jiffies, lp->dialstarted + lp->dialtimeout)) {
@@ -688,7 +688,7 @@ isdn_net_dial(void)
dev->usage[i] |= ISDN_USAGE_OUTGOING;
isdn_info_update();
}
- printk(KERN_INFO "%s: dialing %d %s... %s\n", lp->name,
+ printk(KERN_INFO "%s: dialing %d %s... %s\n", p->dev->name,
lp->dialretry, cmd.parm.setup.phone,
(cmd.parm.setup.si1 == 1) ? "DOV" : "");
lp->dtimer = 0;
@@ -797,7 +797,7 @@ isdn_net_dial(void)
*/
if (lp->dtimer++ > lp->cbdelay)
{
- printk(KERN_INFO "%s: hangup waiting for callback ...\n", lp->name);
+ printk(KERN_INFO "%s: hangup waiting for callback ...\n", p->dev->name);
lp->dtimer = 0;
lp->dialstate = 4;
cmd.driver = lp->isdn_device;
@@ -810,7 +810,7 @@ isdn_net_dial(void)
break;
default:
printk(KERN_WARNING "isdn_net: Illegal dialstate %d for device %s\n",
- lp->dialstate, lp->name);
+ lp->dialstate, p->dev->name);
}
p = (isdn_net_dev *) p->next;
}
@@ -836,11 +836,11 @@ isdn_net_hangup(struct net_device *d)
if (slp->flags & ISDN_NET_CONNECTED) {
printk(KERN_INFO
"isdn_net: hang up slave %s before %s\n",
- slp->name, lp->name);
+ lp->slave->name, d->name);
isdn_net_hangup(lp->slave);
}
}
- printk(KERN_INFO "isdn_net: local hangup %s\n", lp->name);
+ printk(KERN_INFO "isdn_net: local hangup %s\n", d->name);
#ifdef CONFIG_ISDN_PPP
if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
isdn_ppp_free(lp);
@@ -858,7 +858,7 @@ isdn_net_hangup(struct net_device *d)
cmd.command = ISDN_CMD_HANGUP;
cmd.arg = lp->isdn_channel;
isdn_command(&cmd);
- printk(KERN_INFO "%s: Chargesum is %d\n", lp->name, lp->charge);
+ printk(KERN_INFO "%s: Chargesum is %d\n", d->name, lp->charge);
isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
}
isdn_net_unbind_channel(lp);
@@ -885,7 +885,7 @@ isdn_net_log_skb(struct sk_buff * skb, isdn_net_local * lp)
/* fall back to old isdn_net_log_packet method() */
char * buf = skb->data;
- printk(KERN_DEBUG "isdn_net: protocol %04x is buggy, dev %s\n", skb->protocol, lp->name);
+ printk(KERN_DEBUG "isdn_net: protocol %04x is buggy, dev %s\n", skb->protocol, lp->netdev->dev->name);
p = buf;
proto = ETH_P_IP;
switch (lp->p_encap) {
@@ -1023,7 +1023,7 @@ void isdn_net_writebuf_skb(isdn_net_local *lp, struct sk_buff *skb)
ret = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 1, skb);
if (ret != len) {
/* we should never get here */
- printk(KERN_WARNING "%s: HL driver queue full\n", lp->name);
+ printk(KERN_WARNING "%s: HL driver queue full\n", lp->netdev->dev->name);
goto error;
}
@@ -1461,7 +1461,7 @@ isdn_ciscohdlck_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
mod_timer(&lp->cisco_timer, expires);
printk(KERN_INFO "%s: Keepalive period set "
"to %d seconds.\n",
- lp->name, lp->cisco_keepalive_period);
+ dev->name, lp->cisco_keepalive_period);
}
break;
@@ -1512,7 +1512,7 @@ isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data)
lp->cisco_line_state = 0;
printk (KERN_WARNING
"UPDOWN: Line protocol on Interface %s,"
- " changed state to down\n", lp->name);
+ " changed state to down\n", lp->netdev->dev->name);
/* should stop routing higher-level data accross */
} else if ((!lp->cisco_line_state) &&
(myseq_diff >= 0) && (myseq_diff <= 2)) {
@@ -1520,14 +1520,14 @@ isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data)
lp->cisco_line_state = 1;
printk (KERN_WARNING
"UPDOWN: Line protocol on Interface %s,"
- " changed state to up\n", lp->name);
+ " changed state to up\n", lp->netdev->dev->name);
/* restart routing higher-level data accross */
}
if (lp->cisco_debserint)
printk (KERN_DEBUG "%s: HDLC "
"myseq %lu, mineseen %lu%c, yourseen %lu, %s\n",
- lp->name, last_cisco_myseq, lp->cisco_mineseen,
+ lp->netdev->dev->name, last_cisco_myseq, lp->cisco_mineseen,
((last_cisco_myseq == lp->cisco_mineseen) ? '*' : 040),
lp->cisco_yourseq,
((lp->cisco_line_state) ? "line up" : "line down"));
@@ -1682,7 +1682,7 @@ isdn_net_ciscohdlck_slarp_in(isdn_net_local *lp, struct sk_buff *skb)
"remote ip: %d.%d.%d.%d, "
"local ip: %d.%d.%d.%d "
"mask: %d.%d.%d.%d\n",
- lp->name,
+ lp->netdev->dev->name,
HIPQUAD(addr),
HIPQUAD(local),
HIPQUAD(mask));
@@ -1690,7 +1690,7 @@ isdn_net_ciscohdlck_slarp_in(isdn_net_local *lp, struct sk_buff *skb)
slarp_reply_out:
printk(KERN_INFO "%s: got invalid slarp "
"reply (%d.%d.%d.%d/%d.%d.%d.%d) "
- "- ignored\n", lp->name,
+ "- ignored\n", lp->netdev->dev->name,
HIPQUAD(addr), HIPQUAD(mask));
break;
case CISCO_SLARP_KEEPALIVE:
@@ -1701,7 +1701,8 @@ isdn_net_ciscohdlck_slarp_in(isdn_net_local *lp, struct sk_buff *skb)
lp->cisco_last_slarp_in) {
printk(KERN_DEBUG "%s: Keepalive period mismatch - "
"is %d but should be %d.\n",
- lp->name, period, lp->cisco_keepalive_period);
+ lp->netdev->dev->name, period,
+ lp->cisco_keepalive_period);
}
lp->cisco_last_slarp_in = jiffies;
p += get_u32(p, &my_seq);
@@ -1732,12 +1733,12 @@ isdn_net_ciscohdlck_receive(isdn_net_local *lp, struct sk_buff *skb)
if (addr != CISCO_ADDR_UNICAST && addr != CISCO_ADDR_BROADCAST) {
printk(KERN_WARNING "%s: Unknown Cisco addr 0x%02x\n",
- lp->name, addr);
+ lp->netdev->dev->name, addr);
goto out_free;
}
if (ctrl != CISCO_CTRL) {
printk(KERN_WARNING "%s: Unknown Cisco ctrl 0x%02x\n",
- lp->name, ctrl);
+ lp->netdev->dev->name, ctrl);
goto out_free;
}
@@ -1748,7 +1749,8 @@ isdn_net_ciscohdlck_receive(isdn_net_local *lp, struct sk_buff *skb)
case CISCO_TYPE_CDP:
if (lp->cisco_debserint)
printk(KERN_DEBUG "%s: Received CDP packet. use "
- "\"no cdp enable\" on cisco.\n", lp->name);
+ "\"no cdp enable\" on cisco.\n",
+ lp->netdev->dev->name);
goto out_free;
default:
/* no special cisco protocol */
@@ -1843,7 +1845,7 @@ isdn_net_receive(struct net_device *ndev, struct sk_buff *skb)
};
#endif /* CONFIG_ISDN_X25 */
printk(KERN_WARNING "%s: unknown encapsulation, dropping\n",
- lp->name);
+ lp->netdev->dev->name);
kfree_skb(skb);
return;
}
@@ -2174,7 +2176,7 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
wret = matchret;
#ifdef ISDN_DEBUG_NET_ICALL
printk(KERN_DEBUG "n_fi: if='%s', l.msn=%s, l.flags=%d, l.dstate=%d\n",
- lp->name, lp->msn, lp->flags, lp->dialstate);
+ p->dev->name, lp->msn, lp->flags, lp->dialstate);
#endif
if ((!matchret) && /* EAZ is matching */
(((!(lp->flags & ISDN_NET_CONNECTED)) && /* but not connected */
@@ -2277,7 +2279,7 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
* */
if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) {
printk(KERN_INFO "incoming call, interface %s `stopped' -> rejected\n",
- lp->name);
+ p->dev->name);
return 3;
}
/*
@@ -2286,7 +2288,7 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
*/
if (!isdn_net_device_started(p)) {
printk(KERN_INFO "%s: incoming call, interface down -> rejected\n",
- lp->name);
+ p->dev->name);
return 3;
}
/* Interface is up, now see if it's a slave. If so, see if
@@ -2294,8 +2296,8 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
*/
if (lp->master) {
isdn_net_local *mlp = (isdn_net_local *) lp->master->priv;
- printk(KERN_DEBUG "ICALLslv: %s\n", lp->name);
- printk(KERN_DEBUG "master=%s\n", mlp->name);
+ printk(KERN_DEBUG "ICALLslv: %s\n", p->dev->name);
+ printk(KERN_DEBUG "master=%s\n", lp->master->name);
if (mlp->flags & ISDN_NET_CONNECTED) {
printk(KERN_DEBUG "master online\n");
/* Master is online, find parent-slave (master if first slave) */
@@ -2322,11 +2324,11 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
* */
if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) {
printk(KERN_INFO "incoming call for callback, interface %s `off' -> rejected\n",
- lp->name);
+ p->dev->name);
return 3;
}
printk(KERN_DEBUG "%s: call from %s -> %s, start callback\n",
- lp->name, nr, eaz);
+ p->dev->name, nr, eaz);
if (lp->phone[1]) {
/* Grab a free ISDN-Channel */
spin_lock_irqsave(&dev->lock, flags);
@@ -2340,7 +2342,8 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
lp->msn)
) < 0) {
- printk(KERN_WARNING "isdn_net_find_icall: No channel for %s\n", lp->name);
+ printk(KERN_WARNING "isdn_net_find_icall: No channel for %s\n",
+ p->dev->name);
spin_unlock_irqrestore(&dev->lock, flags);
return 0;
}
@@ -2361,11 +2364,12 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
/* Initiate dialing by returning 2 or 4 */
return (lp->flags & ISDN_NET_CBHUP) ? 2 : 4;
} else
- printk(KERN_WARNING "isdn_net: %s: No phone number\n", lp->name);
+ printk(KERN_WARNING "isdn_net: %s: No phone number\n",
+ p->dev->name);
return 0;
} else {
- printk(KERN_DEBUG "%s: call from %s -> %s accepted\n", lp->name, nr,
- eaz);
+ printk(KERN_DEBUG "%s: call from %s -> %s accepted\n",
+ p->dev->name, nr, eaz);
/* if this interface is dialing, it does it probably on a different
device, so free this device */
if ((lp->dialstate == 4) || (lp->dialstate == 12)) {
@@ -2424,7 +2428,7 @@ isdn_net_findif(char *name)
isdn_net_dev *p = dev->netdev;
while (p) {
- if (!strcmp(p->local->name, name))
+ if (!strcmp(p->dev->name, name))
return p;
p = (isdn_net_dev *) p->next;
}
@@ -2453,7 +2457,8 @@ isdn_net_force_dial_lp(isdn_net_local * lp)
lp->pre_device,
lp->pre_channel,
lp->msn)) < 0) {
- printk(KERN_WARNING "isdn_net_force_dial: No channel for %s\n", lp->name);
+ printk(KERN_WARNING "isdn_net_force_dial: No channel for %s\n",
+ lp->netdev->dev->name);
spin_unlock_irqrestore(&dev->lock, flags);
return -EAGAIN;
}
@@ -2556,7 +2561,7 @@ isdn_net_new(char *name, struct net_device *master)
return NULL;
}
if (name == NULL)
- name = " ";
+ return NULL;
if (!(netdev = kzalloc(sizeof(isdn_net_dev), GFP_KERNEL))) {
printk(KERN_WARNING "isdn_net: Could not allocate net-device\n");
return NULL;
@@ -2568,7 +2573,6 @@ isdn_net_new(char *name, struct net_device *master)
return NULL;
}
netdev->local = netdev->dev->priv;
- strcpy(netdev->local->name, netdev->dev->name);
netdev->dev->init = isdn_net_init;
if (master) {
/* Device shall be a slave */
@@ -2673,7 +2677,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
#endif
if (isdn_net_device_started(p)) {
printk(KERN_WARNING "%s: cannot change encap when if is up\n",
- lp->name);
+ p->dev->name);
return -EBUSY;
}
#ifdef CONFIG_ISDN_X25
@@ -2698,7 +2702,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
case ISDN_NET_ENCAP_SYNCPPP:
#ifndef CONFIG_ISDN_PPP
printk(KERN_WARNING "%s: SyncPPP support not configured\n",
- lp->name);
+ p->dev->name);
return -EINVAL;
#else
p->dev->type = ARPHRD_PPP; /* change ARP type */
@@ -2709,7 +2713,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
case ISDN_NET_ENCAP_X25IFACE:
#ifndef CONFIG_ISDN_X25
printk(KERN_WARNING "%s: isdn-x25 support not configured\n",
- p->local->name);
+ p->dev->name);
return -EINVAL;
#else
p->dev->type = ARPHRD_X25; /* change ARP type */
@@ -2725,7 +2729,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
break;
printk(KERN_WARNING
"%s: encapsulation protocol %d not supported\n",
- p->local->name, cfg->p_encap);
+ p->dev->name, cfg->p_encap);
return -EINVAL;
}
if (strlen(cfg->drvid)) {
@@ -2902,13 +2906,18 @@ isdn_net_getcfg(isdn_net_ioctl_cfg * cfg)
cfg->pppbind = lp->pppbind;
cfg->dialtimeout = lp->dialtimeout >= 0 ? lp->dialtimeout / HZ : -1;
cfg->dialwait = lp->dialwait / HZ;
- if (lp->slave)
- strcpy(cfg->slave, ((isdn_net_local *) lp->slave->priv)->name);
- else
+ if (lp->slave) {
+ if (strlen(lp->slave->name) > 8)
+ strcpy(cfg->slave, "too-long");
+ else
+ strcpy(cfg->slave, lp->slave->name);
+ } else
cfg->slave[0] = '\0';
- if (lp->master)
- strcpy(cfg->master, ((isdn_net_local *) lp->master->priv)->name);
- else
+ if (lp->master) {
+ if (strlen(lp->master->name) > 8)
+ strcpy(cfg->master, "too-long");
+ strcpy(cfg->master, lp->master->name);
+ } else
cfg->master[0] = '\0';
return 0;
}
@@ -2978,7 +2987,8 @@ isdn_net_getpeer(isdn_net_ioctl_phone *phone, isdn_net_ioctl_phone __user *peer)
isdn_net_dev *p = isdn_net_findif(phone->name);
int ch, dv, idx;
- if (!p) return -ENODEV;
+ if (!p)
+ return -ENODEV;
/*
* Theoretical race: while this executes, the remote number might
* become invalid (hang up) or change (new connection), resulting
@@ -2987,14 +2997,18 @@ isdn_net_getpeer(isdn_net_ioctl_phone *phone, isdn_net_ioctl_phone __user *peer)
*/
ch = p->local->isdn_channel;
dv = p->local->isdn_device;
- if(ch<0 && dv<0) return -ENOTCONN;
+ if(ch < 0 && dv < 0)
+ return -ENOTCONN;
idx = isdn_dc2minor(dv, ch);
- if (idx<0) return -ENODEV;
+ if (idx <0 )
+ return -ENODEV;
/* for pre-bound channels, we need this extra check */
- if ( strncmp(dev->num[idx],"???",3) == 0 ) return -ENOTCONN;
- strncpy(phone->phone,dev->num[idx],ISDN_MSNLEN);
- phone->outgoing=USG_OUTGOING(dev->usage[idx]);
- if ( copy_to_user(peer,phone,sizeof(*peer)) ) return -EFAULT;
+ if (strncmp(dev->num[idx], "???", 3) == 0)
+ return -ENOTCONN;
+ strncpy(phone->phone, dev->num[idx], ISDN_MSNLEN);
+ phone->outgoing = USG_OUTGOING(dev->usage[idx]);
+ if (copy_to_user(peer, phone, sizeof(*peer)))
+ return -EFAULT;
return 0;
}
/*
@@ -3113,18 +3127,18 @@ isdn_net_realrm(isdn_net_dev * p, isdn_net_dev * q)
dev->netdev = p->next;
if (p->local->slave) {
/* If this interface has a slave, remove it also */
- char *slavename = ((isdn_net_local *) (p->local->slave->priv))->name;
+ char *slavename = p->local->slave->name;
isdn_net_dev *n = dev->netdev;
q = NULL;
while (n) {
- if (!strcmp(n->local->name, slavename)) {
+ if (!strcmp(n->dev->name, slavename)) {
spin_unlock_irqrestore(&dev->lock, flags);
isdn_net_realrm(n, q);
spin_lock_irqsave(&dev->lock, flags);
break;
}
q = n;
- n = (isdn_net_dev *) n->next;
+ n = (isdn_net_dev *)n->next;
}
}
spin_unlock_irqrestore(&dev->lock, flags);
@@ -3152,7 +3166,7 @@ isdn_net_rm(char *name)
p = dev->netdev;
q = NULL;
while (p) {
- if (!strcmp(p->local->name, name)) {
+ if (!strcmp(p->dev->name, name)) {
spin_unlock_irqrestore(&dev->lock, flags);
return (isdn_net_realrm(p, q));
}
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
index 0e5e59f84344..9f5fe372f83d 100644
--- a/drivers/isdn/i4l/isdn_ppp.c
+++ b/drivers/isdn/i4l/isdn_ppp.c
@@ -190,9 +190,11 @@ isdn_ppp_bind(isdn_net_local * lp)
retval = -1;
goto out;
}
- unit = isdn_ppp_if_get_unit(lp->name); /* get unit number from interface name .. ugly! */
+ /* get unit number from interface name .. ugly! */
+ unit = isdn_ppp_if_get_unit(lp->netdev->dev->name);
if (unit < 0) {
- printk(KERN_ERR "isdn_ppp_bind: illegal interface name %s.\n", lp->name);
+ printk(KERN_ERR "isdn_ppp_bind: illegal interface name %s.\n",
+ lp->netdev->dev->name);
retval = -1;
goto out;
}
@@ -507,7 +509,8 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
case PPPIOCGIFNAME:
if(!lp)
return -EINVAL;
- if ((r = set_arg(argp, lp->name, strlen(lp->name))))
+ if ((r = set_arg(argp, lp->netdev->dev->name,
+ strlen(lp->netdev->dev->name))))
return r;
break;
case PPPIOCGMPFLAGS: /* get configuration flags */
diff --git a/drivers/isdn/pcbit/capi.c b/drivers/isdn/pcbit/capi.c
index 7b55e151f1b0..ac5a91ccde81 100644
--- a/drivers/isdn/pcbit/capi.c
+++ b/drivers/isdn/pcbit/capi.c
@@ -15,9 +15,9 @@
/*
* Documentation:
- * - "Common ISDN API - Perfil Português - Versão 2.1",
+ * - "Common ISDN API - Perfil Português - Versão 2.1",
* Telecom Portugal, Fev 1992.
- * - "Common ISDN API - Especificação de protocolos para
+ * - "Common ISDN API - Especificação de protocolos para
* acesso aos canais B", Inesc, Jan 1994.
*/
diff --git a/drivers/isdn/sc/card.h b/drivers/isdn/sc/card.h
index 5992f63c383e..0120bcf88311 100644
--- a/drivers/isdn/sc/card.h
+++ b/drivers/isdn/sc/card.h
@@ -109,7 +109,7 @@ void memcpy_fromshmem(int card, void *dest, const void *src, size_t n);
int get_card_from_id(int driver);
int indicate_status(int card, int event, ulong Channel, char *Data);
irqreturn_t interrupt_handler(int interrupt, void *cardptr);
-int sndpkt(int devId, int channel, struct sk_buff *data);
+int sndpkt(int devId, int channel, int ack, struct sk_buff *data);
void rcvpkt(int card, RspMessage *rcvmsg);
int command(isdn_ctrl *cmd);
int reset(int card);
diff --git a/drivers/isdn/sc/debug.h b/drivers/isdn/sc/debug.h
deleted file mode 100644
index e9db96ede4b2..000000000000
--- a/drivers/isdn/sc/debug.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* $Id: debug.h,v 1.2.8.1 2001/09/23 22:24:59 kai Exp $
- *
- * Copyright (C) 1996 SpellCaster Telecommunications Inc.
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- * For more information, please contact gpl-info@spellcast.com or write:
- *
- * SpellCaster Telecommunications Inc.
- * 5621 Finch Avenue East, Unit #3
- * Scarborough, Ontario Canada
- * M1B 2T9
- * +1 (416) 297-8565
- * +1 (416) 297-6433 Facsimile
- */
-
-#define REQUEST_IRQ(a,b,c,d,e) request_irq(a,b,c,d,e)
-#define FREE_IRQ(a,b) free_irq(a,b)
diff --git a/drivers/isdn/sc/includes.h b/drivers/isdn/sc/includes.h
index 5286e0c810a9..4766e5b77378 100644
--- a/drivers/isdn/sc/includes.h
+++ b/drivers/isdn/sc/includes.h
@@ -14,4 +14,3 @@
#include <linux/timer.h>
#include <linux/wait.h>
#include <linux/isdnif.h>
-#include "debug.h"
diff --git a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c
index 0bf76344a0d5..dd0acd06750b 100644
--- a/drivers/isdn/sc/init.c
+++ b/drivers/isdn/sc/init.c
@@ -334,7 +334,8 @@ static int __init sc_init(void)
*/
sc_adapter[cinst]->interrupt = irq[b];
if (request_irq(sc_adapter[cinst]->interrupt, interrupt_handler,
- IRQF_DISABLED, interface->id, NULL))
+ IRQF_DISABLED, interface->id,
+ (void *)(unsigned long) cinst))
{
kfree(sc_adapter[cinst]->channel);
indicate_status(cinst, ISDN_STAT_UNLOAD, 0, NULL); /* Fix me */
@@ -404,7 +405,7 @@ static void __exit sc_exit(void)
/*
* Release the IRQ
*/
- FREE_IRQ(sc_adapter[i]->interrupt, NULL);
+ free_irq(sc_adapter[i]->interrupt, NULL);
/*
* Reset for a clean start
diff --git a/drivers/isdn/sc/interrupt.c b/drivers/isdn/sc/interrupt.c
index bef7963cdd02..485be8b1e1b3 100644
--- a/drivers/isdn/sc/interrupt.c
+++ b/drivers/isdn/sc/interrupt.c
@@ -21,28 +21,15 @@
#include "card.h"
#include <linux/interrupt.h>
-static int get_card_from_irq(int irq)
-{
- int i;
-
- for(i = 0 ; i < cinst ; i++) {
- if(sc_adapter[i]->interrupt == irq)
- return i;
- }
- return -1;
-}
-
/*
*
*/
-irqreturn_t interrupt_handler(int interrupt, void *cardptr)
+irqreturn_t interrupt_handler(int dummy, void *card_inst)
{
RspMessage rcvmsg;
int channel;
- int card;
-
- card = get_card_from_irq(interrupt);
+ int card = (int)(unsigned long) card_inst;
if(!IS_VALID_CARD(card)) {
pr_debug("Invalid param: %d is not a valid card id\n", card);
diff --git a/drivers/isdn/sc/packet.c b/drivers/isdn/sc/packet.c
index 92016a2608e9..5ff6ae868440 100644
--- a/drivers/isdn/sc/packet.c
+++ b/drivers/isdn/sc/packet.c
@@ -20,7 +20,7 @@
#include "message.h"
#include "card.h"
-int sndpkt(int devId, int channel, struct sk_buff *data)
+int sndpkt(int devId, int channel, int ack, struct sk_buff *data)
{
LLData ReqLnkWrite;
int status;
diff --git a/drivers/isdn/sc/shmem.c b/drivers/isdn/sc/shmem.c
index 034d41a61ae1..712220cef139 100644
--- a/drivers/isdn/sc/shmem.c
+++ b/drivers/isdn/sc/shmem.c
@@ -28,15 +28,15 @@ void memcpy_toshmem(int card, void *dest, const void *src, size_t n)
{
unsigned long flags;
unsigned char ch;
+ unsigned long dest_rem = ((unsigned long) dest) % 0x4000;
- if(!IS_VALID_CARD(card)) {
+ if (!IS_VALID_CARD(card)) {
pr_debug("Invalid param: %d is not a valid card id\n", card);
return;
}
- if(n > SRAM_PAGESIZE) {
+ if (n > SRAM_PAGESIZE)
return;
- }
/*
* determine the page to load from the address
@@ -50,8 +50,7 @@ void memcpy_toshmem(int card, void *dest, const void *src, size_t n)
outb(((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80,
sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
- memcpy_toio(sc_adapter[card]->rambase +
- ((unsigned long) dest % 0x4000), src, n);
+ memcpy_toio((void __iomem *)(sc_adapter[card]->rambase + dest_rem), src, n);
spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
pr_debug("%s: set page to %#x\n",sc_adapter[card]->devicename,
((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80);
diff --git a/drivers/kvm/Kconfig b/drivers/kvm/Kconfig
index 8749fa4ffcee..656920636cb2 100644
--- a/drivers/kvm/Kconfig
+++ b/drivers/kvm/Kconfig
@@ -47,4 +47,8 @@ config KVM_AMD
Provides support for KVM on AMD processors equipped with the AMD-V
(SVM) extensions.
+# OK, it's a little counter-intuitive to do this, but it puts it neatly under
+# the virtualization menu.
+source drivers/lguest/Kconfig
+
endif # VIRTUALIZATION
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index af2d288c881d..07ae280e8fe5 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -198,21 +198,15 @@ static void vcpu_put(struct kvm_vcpu *vcpu)
static void ack_flush(void *_completed)
{
- atomic_t *completed = _completed;
-
- atomic_inc(completed);
}
void kvm_flush_remote_tlbs(struct kvm *kvm)
{
- int i, cpu, needed;
+ int i, cpu;
cpumask_t cpus;
struct kvm_vcpu *vcpu;
- atomic_t completed;
- atomic_set(&completed, 0);
cpus_clear(cpus);
- needed = 0;
for (i = 0; i < KVM_MAX_VCPUS; ++i) {
vcpu = kvm->vcpus[i];
if (!vcpu)
@@ -221,23 +215,9 @@ void kvm_flush_remote_tlbs(struct kvm *kvm)
continue;
cpu = vcpu->cpu;
if (cpu != -1 && cpu != raw_smp_processor_id())
- if (!cpu_isset(cpu, cpus)) {
- cpu_set(cpu, cpus);
- ++needed;
- }
- }
-
- /*
- * We really want smp_call_function_mask() here. But that's not
- * available, so ipi all cpus in parallel and wait for them
- * to complete.
- */
- for (cpu = first_cpu(cpus); cpu != NR_CPUS; cpu = next_cpu(cpu, cpus))
- smp_call_function_single(cpu, ack_flush, &completed, 1, 0);
- while (atomic_read(&completed) != needed) {
- cpu_relax();
- barrier();
+ cpu_set(cpu, cpus);
}
+ smp_call_function_mask(cpus, ack_flush, NULL, 1);
}
int kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm *kvm, unsigned id)
@@ -2054,12 +2034,21 @@ again:
kvm_x86_ops->run(vcpu, kvm_run);
- kvm_guest_exit();
vcpu->guest_mode = 0;
local_irq_enable();
++vcpu->stat.exits;
+ /*
+ * We must have an instruction between local_irq_enable() and
+ * kvm_guest_exit(), so the timer interrupt isn't delayed by
+ * the interrupt shadow. The stat.exits increment will do nicely.
+ * But we need to prevent reordering, hence this barrier():
+ */
+ barrier();
+
+ kvm_guest_exit();
+
preempt_enable();
/*
diff --git a/drivers/kvm/lapic.c b/drivers/kvm/lapic.c
index a190587cf6a5..238fcad3cece 100644
--- a/drivers/kvm/lapic.c
+++ b/drivers/kvm/lapic.c
@@ -494,12 +494,19 @@ static void apic_send_ipi(struct kvm_lapic *apic)
static u32 apic_get_tmcct(struct kvm_lapic *apic)
{
- u32 counter_passed;
- ktime_t passed, now = apic->timer.dev.base->get_time();
- u32 tmcct = apic_get_reg(apic, APIC_TMICT);
+ u64 counter_passed;
+ ktime_t passed, now;
+ 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)
+ return 0;
+
if (unlikely(ktime_to_ns(now) <=
ktime_to_ns(apic->timer.last_update))) {
/* Wrap around */
@@ -514,15 +521,24 @@ static u32 apic_get_tmcct(struct kvm_lapic *apic)
counter_passed = div64_64(ktime_to_ns(passed),
(APIC_BUS_CYCLE_NS * apic->timer.divide_count));
- tmcct -= counter_passed;
- if (tmcct <= 0) {
- if (unlikely(!apic_lvtt_period(apic)))
+ if (counter_passed > tmcct) {
+ if (unlikely(!apic_lvtt_period(apic))) {
+ /* one-shot timers stick at 0 until reset */
tmcct = 0;
- else
- do {
- tmcct += apic_get_reg(apic, APIC_TMICT);
- } while (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;
}
return tmcct;
@@ -853,7 +869,7 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu)
apic_set_reg(apic, APIC_ISR + 0x10 * i, 0);
apic_set_reg(apic, APIC_TMR + 0x10 * i, 0);
}
- apic->timer.divide_count = 0;
+ update_divide_count(apic);
atomic_set(&apic->timer.pending, 0);
if (vcpu->vcpu_id == 0)
vcpu->apic_base |= MSR_IA32_APICBASE_BSP;
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c
index 6d84d30f5ed0..feb5ac986c5d 100644
--- a/drivers/kvm/mmu.c
+++ b/drivers/kvm/mmu.c
@@ -1049,6 +1049,7 @@ int kvm_mmu_reset_context(struct kvm_vcpu *vcpu)
destroy_kvm_mmu(vcpu);
return init_kvm_mmu(vcpu);
}
+EXPORT_SYMBOL_GPL(kvm_mmu_reset_context);
int kvm_mmu_load(struct kvm_vcpu *vcpu)
{
@@ -1088,7 +1089,7 @@ static void mmu_pte_write_zap_pte(struct kvm_vcpu *vcpu,
mmu_page_remove_parent_pte(child, spte);
}
}
- *spte = 0;
+ set_shadow_pte(spte, 0);
kvm_flush_remote_tlbs(vcpu->kvm);
}
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c
index 729f1cd93606..7a6eead63a6b 100644
--- a/drivers/kvm/svm.c
+++ b/drivers/kvm/svm.c
@@ -494,6 +494,7 @@ static void init_vmcb(struct vmcb *vmcb)
*/
/* (1ULL << INTERCEPT_SELECTIVE_CR0) | */
(1ULL << INTERCEPT_CPUID) |
+ (1ULL << INTERCEPT_INVD) |
(1ULL << INTERCEPT_HLT) |
(1ULL << INTERCEPT_INVLPGA) |
(1ULL << INTERCEPT_IOIO_PROT) |
@@ -507,6 +508,7 @@ static void init_vmcb(struct vmcb *vmcb)
(1ULL << INTERCEPT_STGI) |
(1ULL << INTERCEPT_CLGI) |
(1ULL << INTERCEPT_SKINIT) |
+ (1ULL << INTERCEPT_WBINVD) |
(1ULL << INTERCEPT_MONITOR) |
(1ULL << INTERCEPT_MWAIT);
@@ -561,6 +563,12 @@ static void svm_vcpu_reset(struct kvm_vcpu *vcpu)
struct vcpu_svm *svm = to_svm(vcpu);
init_vmcb(svm->vmcb);
+
+ if (vcpu->vcpu_id != 0) {
+ svm->vmcb->save.rip = 0;
+ svm->vmcb->save.cs.base = svm->vcpu.sipi_vector << 12;
+ svm->vmcb->save.cs.selector = svm->vcpu.sipi_vector << 8;
+ }
}
static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)
@@ -1241,6 +1249,7 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm,
[SVM_EXIT_VINTR] = interrupt_window_interception,
/* [SVM_EXIT_CR0_SEL_WRITE] = emulate_on_interception, */
[SVM_EXIT_CPUID] = cpuid_interception,
+ [SVM_EXIT_INVD] = emulate_on_interception,
[SVM_EXIT_HLT] = halt_interception,
[SVM_EXIT_INVLPG] = emulate_on_interception,
[SVM_EXIT_INVLPGA] = invalid_op_interception,
@@ -1255,6 +1264,7 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm,
[SVM_EXIT_STGI] = invalid_op_interception,
[SVM_EXIT_CLGI] = invalid_op_interception,
[SVM_EXIT_SKINIT] = invalid_op_interception,
+ [SVM_EXIT_WBINVD] = emulate_on_interception,
[SVM_EXIT_MONITOR] = invalid_op_interception,
[SVM_EXIT_MWAIT] = invalid_op_interception,
};
@@ -1579,10 +1589,6 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
#endif
: "cc", "memory" );
- local_irq_disable();
-
- stgi();
-
if ((svm->vmcb->save.dr7 & 0xff))
load_db_regs(svm->host_db_regs);
@@ -1599,6 +1605,10 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
reload_tss(vcpu);
+ local_irq_disable();
+
+ stgi();
+
svm->next_rip = 0;
}
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index 4f115a8e45ef..bb56ae3f89b6 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -523,6 +523,8 @@ static unsigned long vmx_get_rflags(struct kvm_vcpu *vcpu)
static void vmx_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)
{
+ if (vcpu->rmode.active)
+ rflags |= IOPL_MASK | X86_EFLAGS_VM;
vmcs_writel(GUEST_RFLAGS, rflags);
}
@@ -1128,6 +1130,7 @@ static void enter_rmode(struct kvm_vcpu *vcpu)
fix_rmode_seg(VCPU_SREG_GS, &vcpu->rmode.gs);
fix_rmode_seg(VCPU_SREG_FS, &vcpu->rmode.fs);
+ kvm_mmu_reset_context(vcpu);
init_rmode_tss(vcpu->kvm);
}
@@ -1760,10 +1763,8 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
set_bit(irq / BITS_PER_LONG, &vcpu->irq_summary);
}
- if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200) { /* nmi */
- asm ("int $2");
- return 1;
- }
+ if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200) /* nmi */
+ return 1; /* already handled by vmx_vcpu_run() */
if (is_no_device(intr_info)) {
vmx_fpu_activate(vcpu);
@@ -2196,6 +2197,7 @@ static void vmx_intr_assist(struct kvm_vcpu *vcpu)
static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
+ u32 intr_info;
/*
* Loading guest fpu may have cleared host cr0.ts
@@ -2322,6 +2324,12 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
asm ("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS));
vmx->launched = 1;
+
+ intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
+
+ /* We need to handle NMIs before interrupts are enabled */
+ if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200) /* nmi */
+ asm("int $2");
}
static void vmx_inject_page_fault(struct kvm_vcpu *vcpu,
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
index 9737c3b2f48c..33b181451557 100644
--- a/drivers/kvm/x86_emulate.c
+++ b/drivers/kvm/x86_emulate.c
@@ -167,7 +167,7 @@ static u8 opcode_table[256] = {
static u16 twobyte_table[256] = {
/* 0x00 - 0x0F */
0, SrcMem | ModRM | DstReg, 0, 0, 0, 0, ImplicitOps, 0,
- 0, ImplicitOps, 0, 0, 0, ImplicitOps | ModRM, 0, 0,
+ ImplicitOps, ImplicitOps, 0, 0, 0, ImplicitOps | ModRM, 0, 0,
/* 0x10 - 0x1F */
0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0,
/* 0x20 - 0x2F */
@@ -212,7 +212,8 @@ static u16 twobyte_table[256] = {
0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov,
DstReg | SrcMem16 | ModRM | Mov,
/* 0xC0 - 0xCF */
- 0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, DstMem | SrcReg | ModRM | Mov, 0, 0, 0, ImplicitOps | ModRM,
+ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xD0 - 0xDF */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xE0 - 0xEF */
@@ -596,11 +597,10 @@ x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
case 0xf0: /* LOCK */
lock_prefix = 1;
break;
+ case 0xf2: /* REPNE/REPNZ */
case 0xf3: /* REP/REPE/REPZ */
rep_prefix = 1;
break;
- case 0xf2: /* REPNE/REPNZ */
- break;
default:
goto done_prefixes;
}
@@ -825,6 +825,14 @@ done_prefixes:
if (twobyte && b == 0x01 && modrm_reg == 7)
break;
srcmem_common:
+ /*
+ * For instructions with a ModR/M byte, switch to register
+ * access if Mod = 3.
+ */
+ if ((d & ModRM) && modrm_mod == 3) {
+ src.type = OP_REG;
+ break;
+ }
src.type = OP_MEM;
src.ptr = (unsigned long *)cr2;
src.val = 0;
@@ -893,6 +901,14 @@ done_prefixes:
dst.ptr = (unsigned long *)cr2;
dst.bytes = (d & ByteOp) ? 1 : op_bytes;
dst.val = 0;
+ /*
+ * For instructions with a ModR/M byte, switch to register
+ * access if Mod = 3.
+ */
+ if ((d & ModRM) && modrm_mod == 3) {
+ dst.type = OP_REG;
+ break;
+ }
if (d & BitOp) {
unsigned long mask = ~(dst.bytes * 8 - 1);
@@ -964,17 +980,6 @@ done_prefixes:
goto cannot_emulate;
dst.val = (s32) src.val;
break;
- case 0x6a: /* push imm8 */
- src.val = 0L;
- src.val = insn_fetch(s8, 1, _eip);
-push:
- dst.type = OP_MEM;
- dst.bytes = op_bytes;
- dst.val = src.val;
- register_address_increment(_regs[VCPU_REGS_RSP], -op_bytes);
- dst.ptr = (void *) register_address(ctxt->ss_base,
- _regs[VCPU_REGS_RSP]);
- break;
case 0x80 ... 0x83: /* Grp1 */
switch (modrm_reg) {
case 0:
@@ -1083,31 +1088,6 @@ push:
case 0xd2 ... 0xd3: /* Grp2 */
src.val = _regs[VCPU_REGS_RCX];
goto grp2;
- case 0xe8: /* call (near) */ {
- long int rel;
- switch (op_bytes) {
- case 2:
- rel = insn_fetch(s16, 2, _eip);
- break;
- case 4:
- rel = insn_fetch(s32, 4, _eip);
- break;
- case 8:
- rel = insn_fetch(s64, 8, _eip);
- break;
- default:
- DPRINTF("Call: Invalid op_bytes\n");
- goto cannot_emulate;
- }
- src.val = (unsigned long) _eip;
- JMP_REL(rel);
- goto push;
- }
- case 0xe9: /* jmp rel */
- case 0xeb: /* jmp rel short */
- JMP_REL(src.val);
- no_wb = 1; /* Disable writeback. */
- break;
case 0xf6 ... 0xf7: /* Grp3 */
switch (modrm_reg) {
case 0 ... 1: /* test */
@@ -1252,6 +1232,17 @@ special_insn:
register_address_increment(_regs[VCPU_REGS_RSP], op_bytes);
no_wb = 1; /* Disable writeback. */
break;
+ case 0x6a: /* push imm8 */
+ src.val = 0L;
+ src.val = insn_fetch(s8, 1, _eip);
+ push:
+ dst.type = OP_MEM;
+ dst.bytes = op_bytes;
+ dst.val = src.val;
+ register_address_increment(_regs[VCPU_REGS_RSP], -op_bytes);
+ dst.ptr = (void *) register_address(ctxt->ss_base,
+ _regs[VCPU_REGS_RSP]);
+ break;
case 0x6c: /* insb */
case 0x6d: /* insw/insd */
if (kvm_emulate_pio_string(ctxt->vcpu, NULL,
@@ -1350,6 +1341,32 @@ special_insn:
case 0xae ... 0xaf: /* scas */
DPRINTF("Urk! I don't handle SCAS.\n");
goto cannot_emulate;
+ case 0xe8: /* call (near) */ {
+ long int rel;
+ switch (op_bytes) {
+ case 2:
+ rel = insn_fetch(s16, 2, _eip);
+ break;
+ case 4:
+ rel = insn_fetch(s32, 4, _eip);
+ break;
+ case 8:
+ rel = insn_fetch(s64, 8, _eip);
+ break;
+ default:
+ DPRINTF("Call: Invalid op_bytes\n");
+ goto cannot_emulate;
+ }
+ src.val = (unsigned long) _eip;
+ JMP_REL(rel);
+ goto push;
+ }
+ case 0xe9: /* jmp rel */
+ case 0xeb: /* jmp rel short */
+ JMP_REL(src.val);
+ no_wb = 1; /* Disable writeback. */
+ break;
+
}
goto writeback;
@@ -1501,6 +1518,10 @@ twobyte_insn:
dst.bytes = op_bytes;
dst.val = (d & ByteOp) ? (s8) src.val : (s16) src.val;
break;
+ case 0xc3: /* movnti */
+ dst.bytes = op_bytes;
+ dst.val = (op_bytes == 4) ? (u32) src.val : (u64) src.val;
+ break;
}
goto writeback;
@@ -1511,6 +1532,8 @@ twobyte_special_insn:
case 0x06:
emulate_clts(ctxt->vcpu);
break;
+ case 0x08: /* invd */
+ break;
case 0x09: /* wbinvd */
break;
case 0x0d: /* GrpP (prefetch) */
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 3cb23210b912..ec568fa1c6cc 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -83,7 +83,7 @@ config LEDS_WRAP
config LEDS_H1940
tristate "LED Support for iPAQ H1940 device"
- depends LEDS_CLASS && ARCH_H1940
+ depends on LEDS_CLASS && ARCH_H1940
help
This option enables support for the LEDs on the h1940.
@@ -108,6 +108,12 @@ config LEDS_GPIO
outputs. To be useful the particular board must have LEDs
and they must be connected to the GPIO lines.
+config LEDS_CM_X270
+ tristate "LED Support for the CM-X270 LEDs"
+ depends on LEDS_CLASS && MACH_ARMCORE
+ help
+ This option enables support for the CM-X270 LEDs.
+
comment "LED Triggers"
config LEDS_TRIGGERS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index d2ca1abbc3d2..a60de1b46c2c 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_LEDS_H1940) += leds-h1940.o
obj-$(CONFIG_LEDS_COBALT_QUBE) += leds-cobalt-qube.o
obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o
obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
+obj-$(CONFIG_LEDS_CM_X270) += leds-cm-x270.o
# LED Triggers
obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
diff --git a/drivers/leds/leds-cm-x270.c b/drivers/leds/leds-cm-x270.c
new file mode 100644
index 000000000000..9aebef02a974
--- /dev/null
+++ b/drivers/leds/leds-cm-x270.c
@@ -0,0 +1,122 @@
+/*
+ * drivers/leds/leds-cm-x270.c
+ *
+ * Copyright 2007 CompuLab Ltd.
+ * Author: Mike Rapoport <mike@compulab.co.il>
+ *
+ * Based on leds-corgi.c
+ * Author: Richard Purdie <rpurdie@openedhand.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+
+#include <asm/arch/hardware.h>
+#include <asm/arch/pxa-regs.h>
+
+#define GPIO_RED_LED (93)
+#define GPIO_GREEN_LED (94)
+
+static void cmx270_red_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ if (value)
+ GPCR(GPIO_RED_LED) = GPIO_bit(GPIO_RED_LED);
+ else
+ GPSR(GPIO_RED_LED) = GPIO_bit(GPIO_RED_LED);
+}
+
+static void cmx270_green_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ if (value)
+ GPCR(GPIO_GREEN_LED) = GPIO_bit(GPIO_GREEN_LED);
+ else
+ GPSR(GPIO_GREEN_LED) = GPIO_bit(GPIO_GREEN_LED);
+}
+
+static struct led_classdev cmx270_red_led = {
+ .name = "cm-x270:red",
+ .default_trigger = "nand-disk",
+ .brightness_set = cmx270_red_set,
+};
+
+static struct led_classdev cmx270_green_led = {
+ .name = "cm-x270:green",
+ .default_trigger = "heartbeat",
+ .brightness_set = cmx270_green_set,
+};
+
+#ifdef CONFIG_PM
+static int cmx270led_suspend(struct platform_device *dev, pm_message_t state)
+{
+ led_classdev_suspend(&cmx270_red_led);
+ led_classdev_suspend(&cmx270_green_led);
+ return 0;
+}
+
+static int cmx270led_resume(struct platform_device *dev)
+{
+ led_classdev_resume(&cmx270_red_led);
+ led_classdev_resume(&cmx270_green_led);
+ return 0;
+}
+#endif
+
+static int cmx270led_probe(struct platform_device *pdev)
+{
+ int ret;
+
+ ret = led_classdev_register(&pdev->dev, &cmx270_red_led);
+ if (ret < 0)
+ return ret;
+
+ ret = led_classdev_register(&pdev->dev, &cmx270_green_led);
+ if (ret < 0)
+ led_classdev_unregister(&cmx270_red_led);
+
+ return ret;
+}
+
+static int cmx270led_remove(struct platform_device *pdev)
+{
+ led_classdev_unregister(&cmx270_red_led);
+ led_classdev_unregister(&cmx270_green_led);
+ return 0;
+}
+
+static struct platform_driver cmx270led_driver = {
+ .probe = cmx270led_probe,
+ .remove = cmx270led_remove,
+#ifdef CONFIG_PM
+ .suspend = cmx270led_suspend,
+ .resume = cmx270led_resume,
+#endif
+ .driver = {
+ .name = "cm-x270-led",
+ },
+};
+
+static int __init cmx270led_init(void)
+{
+ return platform_driver_register(&cmx270led_driver);
+}
+
+static void __exit cmx270led_exit(void)
+{
+ platform_driver_unregister(&cmx270led_driver);
+}
+
+module_init(cmx270led_init);
+module_exit(cmx270led_exit);
+
+MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
+MODULE_DESCRIPTION("CM-x270 LED driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index 47d90db280ce..99bc50059d35 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -60,7 +60,7 @@ static void gpio_led_set(struct led_classdev *led_cdev,
gpio_set_value(led_dat->gpio, level);
}
-static int __init gpio_led_probe(struct platform_device *pdev)
+static int gpio_led_probe(struct platform_device *pdev)
{
struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
struct gpio_led *cur_led;
@@ -93,13 +93,13 @@ static int __init gpio_led_probe(struct platform_device *pdev)
gpio_direction_output(led_dat->gpio, led_dat->active_low);
+ INIT_WORK(&led_dat->work, gpio_led_work);
+
ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
if (ret < 0) {
gpio_free(led_dat->gpio);
goto err;
}
-
- INIT_WORK(&led_dat->work, gpio_led_work);
}
platform_set_drvdata(pdev, leds_data);
@@ -110,17 +110,17 @@ err:
if (i > 0) {
for (i = i - 1; i >= 0; i--) {
led_classdev_unregister(&leds_data[i].cdev);
+ cancel_work_sync(&leds_data[i].work);
gpio_free(leds_data[i].gpio);
}
}
- flush_scheduled_work();
kfree(leds_data);
return ret;
}
-static int __exit gpio_led_remove(struct platform_device *pdev)
+static int __devexit gpio_led_remove(struct platform_device *pdev)
{
int i;
struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
@@ -130,9 +130,10 @@ static int __exit gpio_led_remove(struct platform_device *pdev)
for (i = 0; i < pdata->num_leds; i++) {
led_classdev_unregister(&leds_data[i].cdev);
+ cancel_work_sync(&leds_data[i].work);
gpio_free(leds_data[i].gpio);
}
-
+
kfree(leds_data);
return 0;
@@ -144,7 +145,7 @@ static int gpio_led_suspend(struct platform_device *pdev, pm_message_t state)
struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
struct gpio_led_data *leds_data;
int i;
-
+
leds_data = platform_get_drvdata(pdev);
for (i = 0; i < pdata->num_leds; i++)
@@ -172,7 +173,8 @@ static int gpio_led_resume(struct platform_device *pdev)
#endif
static struct platform_driver gpio_led_driver = {
- .remove = __exit_p(gpio_led_remove),
+ .probe = gpio_led_probe,
+ .remove = __devexit_p(gpio_led_remove),
.suspend = gpio_led_suspend,
.resume = gpio_led_resume,
.driver = {
@@ -183,7 +185,7 @@ static struct platform_driver gpio_led_driver = {
static int __init gpio_led_init(void)
{
- return platform_driver_probe(&gpio_led_driver, gpio_led_probe);
+ return platform_driver_register(&gpio_led_driver);
}
static void __exit gpio_led_exit(void)
diff --git a/drivers/leds/leds-s3c24xx.c b/drivers/leds/leds-s3c24xx.c
index 50914439d861..0fd640751294 100644
--- a/drivers/leds/leds-s3c24xx.c
+++ b/drivers/leds/leds-s3c24xx.c
@@ -43,7 +43,7 @@ static void s3c24xx_led_set(struct led_classdev *led_cdev,
struct s3c24xx_gpio_led *led = to_gpio(led_cdev);
struct s3c24xx_led_platdata *pd = led->pdata;
- /* there will be a sort delay between setting the output and
+ /* there will be a short delay between setting the output and
* going from output to input when using tristate. */
s3c2410_gpio_setpin(pd->gpio, (value ? 1 : 0) ^
diff --git a/drivers/lguest/Kconfig b/drivers/lguest/Kconfig
index 41e2250613a1..7eb9ecff8f4a 100644
--- a/drivers/lguest/Kconfig
+++ b/drivers/lguest/Kconfig
@@ -1,7 +1,6 @@
config LGUEST
tristate "Linux hypervisor example code"
- depends on X86 && PARAVIRT && EXPERIMENTAL && !X86_PAE && FUTEX
- select LGUEST_GUEST
+ depends on X86_32 && EXPERIMENTAL && !X86_PAE && FUTEX && !(X86_VISWS || X86_VOYAGER)
select HVC_DRIVER
---help---
This is a very simple module which allows you to run
@@ -18,13 +17,3 @@ config LGUEST_GUEST
The guest needs code built-in, even if the host has lguest
support as a module. The drivers are tiny, so we build them
in too.
-
-config LGUEST_NET
- tristate
- default y
- depends on LGUEST_GUEST && NET
-
-config LGUEST_BLOCK
- tristate
- default y
- depends on LGUEST_GUEST && BLOCK
diff --git a/drivers/lguest/Makefile b/drivers/lguest/Makefile
index e5047471c334..5e8272d296d8 100644
--- a/drivers/lguest/Makefile
+++ b/drivers/lguest/Makefile
@@ -1,10 +1,12 @@
-# Guest requires the paravirt_ops replacement and the bus driver.
-obj-$(CONFIG_LGUEST_GUEST) += lguest.o lguest_asm.o lguest_bus.o
+# Guest requires the device configuration and probing code.
+obj-$(CONFIG_LGUEST_GUEST) += lguest_device.o
# Host requires the other files, which can be a module.
obj-$(CONFIG_LGUEST) += lg.o
-lg-y := core.o hypercalls.o page_tables.o interrupts_and_traps.o \
- segments.o io.o lguest_user.o switcher.o
+lg-y = core.o hypercalls.o page_tables.o interrupts_and_traps.o \
+ segments.o lguest_user.o
+
+lg-$(CONFIG_X86_32) += x86/switcher_32.o x86/core.o
Preparation Preparation!: PREFIX=P
Guest: PREFIX=G
diff --git a/drivers/lguest/core.c b/drivers/lguest/core.c
index 4a315f08a567..cb4c67025d52 100644
--- a/drivers/lguest/core.c
+++ b/drivers/lguest/core.c
@@ -11,58 +11,20 @@
#include <linux/vmalloc.h>
#include <linux/cpu.h>
#include <linux/freezer.h>
+#include <linux/highmem.h>
#include <asm/paravirt.h>
-#include <asm/desc.h>
#include <asm/pgtable.h>
#include <asm/uaccess.h>
#include <asm/poll.h>
-#include <asm/highmem.h>
#include <asm/asm-offsets.h>
-#include <asm/i387.h>
#include "lg.h"
-/* Found in switcher.S */
-extern char start_switcher_text[], end_switcher_text[], switch_to_guest[];
-extern unsigned long default_idt_entries[];
-
-/* Every guest maps the core switcher code. */
-#define SHARED_SWITCHER_PAGES \
- DIV_ROUND_UP(end_switcher_text - start_switcher_text, PAGE_SIZE)
-/* Pages for switcher itself, then two pages per cpu */
-#define TOTAL_SWITCHER_PAGES (SHARED_SWITCHER_PAGES + 2 * NR_CPUS)
-
-/* We map at -4M for ease of mapping into the guest (one PTE page). */
-#define SWITCHER_ADDR 0xFFC00000
static struct vm_struct *switcher_vma;
static struct page **switcher_page;
-static int cpu_had_pge;
-static struct {
- unsigned long offset;
- unsigned short segment;
-} lguest_entry;
-
/* This One Big lock protects all inter-guest data structures. */
DEFINE_MUTEX(lguest_lock);
-static DEFINE_PER_CPU(struct lguest *, last_guest);
-
-/* FIXME: Make dynamic. */
-#define MAX_LGUEST_GUESTS 16
-struct lguest lguests[MAX_LGUEST_GUESTS];
-
-/* Offset from where switcher.S was compiled to where we've copied it */
-static unsigned long switcher_offset(void)
-{
- return SWITCHER_ADDR - (unsigned long)start_switcher_text;
-}
-
-/* This cpu's struct lguest_pages. */
-static struct lguest_pages *lguest_pages(unsigned int cpu)
-{
- return &(((struct lguest_pages *)
- (SWITCHER_ADDR + SHARED_SWITCHER_PAGES*PAGE_SIZE))[cpu]);
-}
/*H:010 We need to set up the Switcher at a high virtual address. Remember the
* Switcher is a few hundred bytes of assembler code which actually changes the
@@ -73,9 +35,7 @@ static struct lguest_pages *lguest_pages(unsigned int cpu)
* Host since it will be running as the switchover occurs.
*
* Trying to map memory at a particular address is an unusual thing to do, so
- * it's not a simple one-liner. We also set up the per-cpu parts of the
- * Switcher here.
- */
+ * it's not a simple one-liner. */
static __init int map_switcher(void)
{
int i, err;
@@ -132,90 +92,11 @@ static __init int map_switcher(void)
goto free_vma;
}
- /* Now the switcher is mapped at the right address, we can't fail!
- * Copy in the compiled-in Switcher code (from switcher.S). */
+ /* Now the Switcher is mapped at the right address, we can't fail!
+ * Copy in the compiled-in Switcher code (from <arch>_switcher.S). */
memcpy(switcher_vma->addr, start_switcher_text,
end_switcher_text - start_switcher_text);
- /* Most of the switcher.S doesn't care that it's been moved; on Intel,
- * jumps are relative, and it doesn't access any references to external
- * code or data.
- *
- * The only exception is the interrupt handlers in switcher.S: their
- * addresses are placed in a table (default_idt_entries), so we need to
- * update the table with the new addresses. switcher_offset() is a
- * convenience function which returns the distance between the builtin
- * switcher code and the high-mapped copy we just made. */
- for (i = 0; i < IDT_ENTRIES; i++)
- default_idt_entries[i] += switcher_offset();
-
- /*
- * Set up the Switcher's per-cpu areas.
- *
- * Each CPU gets two pages of its own within the high-mapped region
- * (aka. "struct lguest_pages"). Much of this can be initialized now,
- * but some depends on what Guest we are running (which is set up in
- * copy_in_guest_info()).
- */
- for_each_possible_cpu(i) {
- /* lguest_pages() returns this CPU's two pages. */
- struct lguest_pages *pages = lguest_pages(i);
- /* This is a convenience pointer to make the code fit one
- * statement to a line. */
- struct lguest_ro_state *state = &pages->state;
-
- /* The Global Descriptor Table: the Host has a different one
- * for each CPU. We keep a descriptor for the GDT which says
- * where it is and how big it is (the size is actually the last
- * byte, not the size, hence the "-1"). */
- state->host_gdt_desc.size = GDT_SIZE-1;
- state->host_gdt_desc.address = (long)get_cpu_gdt_table(i);
-
- /* All CPUs on the Host use the same Interrupt Descriptor
- * Table, so we just use store_idt(), which gets this CPU's IDT
- * descriptor. */
- store_idt(&state->host_idt_desc);
-
- /* The descriptors for the Guest's GDT and IDT can be filled
- * out now, too. We copy the GDT & IDT into ->guest_gdt and
- * ->guest_idt before actually running the Guest. */
- state->guest_idt_desc.size = sizeof(state->guest_idt)-1;
- state->guest_idt_desc.address = (long)&state->guest_idt;
- state->guest_gdt_desc.size = sizeof(state->guest_gdt)-1;
- state->guest_gdt_desc.address = (long)&state->guest_gdt;
-
- /* We know where we want the stack to be when the Guest enters
- * the switcher: in pages->regs. The stack grows upwards, so
- * we start it at the end of that structure. */
- state->guest_tss.esp0 = (long)(&pages->regs + 1);
- /* And this is the GDT entry to use for the stack: we keep a
- * couple of special LGUEST entries. */
- state->guest_tss.ss0 = LGUEST_DS;
-
- /* x86 can have a finegrained bitmap which indicates what I/O
- * ports the process can use. We set it to the end of our
- * structure, meaning "none". */
- state->guest_tss.io_bitmap_base = sizeof(state->guest_tss);
-
- /* Some GDT entries are the same across all Guests, so we can
- * set them up now. */
- setup_default_gdt_entries(state);
- /* Most IDT entries are the same for all Guests, too.*/
- setup_default_idt_entries(state, default_idt_entries);
-
- /* The Host needs to be able to use the LGUEST segments on this
- * CPU, too, so put them in the Host GDT. */
- get_cpu_gdt_table(i)[GDT_ENTRY_LGUEST_CS] = FULL_EXEC_SEGMENT;
- get_cpu_gdt_table(i)[GDT_ENTRY_LGUEST_DS] = FULL_SEGMENT;
- }
-
- /* In the Switcher, we want the %cs segment register to use the
- * LGUEST_CS GDT entry: we've put that in the Host and Guest GDTs, so
- * it will be undisturbed when we switch. To change %cs and jump we
- * need this structure to feed to Intel's "lcall" instruction. */
- lguest_entry.offset = (long)switch_to_guest + switcher_offset();
- lguest_entry.segment = LGUEST_CS;
-
printk(KERN_INFO "lguest: mapped switcher at %p\n",
switcher_vma->addr);
/* And we succeeded... */
@@ -247,86 +128,15 @@ static void unmap_switcher(void)
__free_pages(switcher_page[i], 0);
}
-/*H:130 Our Guest is usually so well behaved; it never tries to do things it
- * isn't allowed to. Unfortunately, "struct paravirt_ops" isn't quite
- * complete, because it doesn't contain replacements for the Intel I/O
- * instructions. As a result, the Guest sometimes fumbles across one during
- * the boot process as it probes for various things which are usually attached
- * to a PC.
- *
- * When the Guest uses one of these instructions, we get trap #13 (General
- * Protection Fault) and come here. We see if it's one of those troublesome
- * instructions and skip over it. We return true if we did. */
-static int emulate_insn(struct lguest *lg)
-{
- u8 insn;
- unsigned int insnlen = 0, in = 0, shift = 0;
- /* The eip contains the *virtual* address of the Guest's instruction:
- * guest_pa just subtracts the Guest's page_offset. */
- unsigned long physaddr = guest_pa(lg, lg->regs->eip);
-
- /* The guest_pa() function only works for Guest kernel addresses, but
- * that's all we're trying to do anyway. */
- if (lg->regs->eip < lg->page_offset)
- return 0;
-
- /* Decoding x86 instructions is icky. */
- lgread(lg, &insn, physaddr, 1);
-
- /* 0x66 is an "operand prefix". It means it's using the upper 16 bits
- of the eax register. */
- if (insn == 0x66) {
- shift = 16;
- /* The instruction is 1 byte so far, read the next byte. */
- insnlen = 1;
- lgread(lg, &insn, physaddr + insnlen, 1);
- }
-
- /* We can ignore the lower bit for the moment and decode the 4 opcodes
- * we need to emulate. */
- switch (insn & 0xFE) {
- case 0xE4: /* in <next byte>,%al */
- insnlen += 2;
- in = 1;
- break;
- case 0xEC: /* in (%dx),%al */
- insnlen += 1;
- in = 1;
- break;
- case 0xE6: /* out %al,<next byte> */
- insnlen += 2;
- break;
- case 0xEE: /* out %al,(%dx) */
- insnlen += 1;
- break;
- default:
- /* OK, we don't know what this is, can't emulate. */
- return 0;
- }
-
- /* If it was an "IN" instruction, they expect the result to be read
- * into %eax, so we change %eax. We always return all-ones, which
- * traditionally means "there's nothing there". */
- if (in) {
- /* Lower bit tells is whether it's a 16 or 32 bit access */
- if (insn & 0x1)
- lg->regs->eax = 0xFFFFFFFF;
- else
- lg->regs->eax |= (0xFFFF << shift);
- }
- /* Finally, we've "done" the instruction, so move past it. */
- lg->regs->eip += insnlen;
- /* Success! */
- return 1;
-}
-/*:*/
-
-/*L:305
+/*H:032
* Dealing With Guest Memory.
*
+ * Before we go too much further into the Host, we need to grok the routines
+ * we use to deal with Guest memory.
+ *
* When the Guest gives us (what it thinks is) a physical address, we can use
- * the normal copy_from_user() & copy_to_user() on that address: remember,
- * Guest physical == Launcher virtual.
+ * the normal copy_from_user() & copy_to_user() on the corresponding place in
+ * the memory region allocated by the Launcher.
*
* But we can't trust the Guest: it might be trying to access the Launcher
* code. We have to check that the range is below the pfn_limit the Launcher
@@ -338,148 +148,27 @@ int lguest_address_ok(const struct lguest *lg,
return (addr+len) / PAGE_SIZE < lg->pfn_limit && (addr+len >= addr);
}
-/* This is a convenient routine to get a 32-bit value from the Guest (a very
- * common operation). Here we can see how useful the kill_lguest() routine we
- * met in the Launcher can be: we return a random value (0) instead of needing
- * to return an error. */
-u32 lgread_u32(struct lguest *lg, unsigned long addr)
-{
- u32 val = 0;
-
- /* Don't let them access lguest binary. */
- if (!lguest_address_ok(lg, addr, sizeof(val))
- || get_user(val, (u32 __user *)addr) != 0)
- kill_guest(lg, "bad read address %#lx", addr);
- return val;
-}
-
-/* Same thing for writing a value. */
-void lgwrite_u32(struct lguest *lg, unsigned long addr, u32 val)
-{
- if (!lguest_address_ok(lg, addr, sizeof(val))
- || put_user(val, (u32 __user *)addr) != 0)
- kill_guest(lg, "bad write address %#lx", addr);
-}
-
-/* This routine is more generic, and copies a range of Guest bytes into a
- * buffer. If the copy_from_user() fails, we fill the buffer with zeroes, so
- * the caller doesn't end up using uninitialized kernel memory. */
-void lgread(struct lguest *lg, void *b, unsigned long addr, unsigned bytes)
+/* This routine copies memory from the Guest. Here we can see how useful the
+ * kill_lguest() routine we met in the Launcher can be: we return a random
+ * value (all zeroes) instead of needing to return an error. */
+void __lgread(struct lguest *lg, void *b, unsigned long addr, unsigned bytes)
{
if (!lguest_address_ok(lg, addr, bytes)
- || copy_from_user(b, (void __user *)addr, bytes) != 0) {
+ || copy_from_user(b, lg->mem_base + addr, bytes) != 0) {
/* copy_from_user should do this, but as we rely on it... */
memset(b, 0, bytes);
kill_guest(lg, "bad read address %#lx len %u", addr, bytes);
}
}
-/* Similarly, our generic routine to copy into a range of Guest bytes. */
-void lgwrite(struct lguest *lg, unsigned long addr, const void *b,
- unsigned bytes)
+/* This is the write (copy into guest) version. */
+void __lgwrite(struct lguest *lg, unsigned long addr, const void *b,
+ unsigned bytes)
{
if (!lguest_address_ok(lg, addr, bytes)
- || copy_to_user((void __user *)addr, b, bytes) != 0)
+ || copy_to_user(lg->mem_base + addr, b, bytes) != 0)
kill_guest(lg, "bad write address %#lx len %u", addr, bytes);
}
-/* (end of memory access helper routines) :*/
-
-static void set_ts(void)
-{
- u32 cr0;
-
- cr0 = read_cr0();
- if (!(cr0 & 8))
- write_cr0(cr0|8);
-}
-
-/*S:010
- * We are getting close to the Switcher.
- *
- * Remember that each CPU has two pages which are visible to the Guest when it
- * runs on that CPU. This has to contain the state for that Guest: we copy the
- * state in just before we run the Guest.
- *
- * Each Guest has "changed" flags which indicate what has changed in the Guest
- * since it last ran. We saw this set in interrupts_and_traps.c and
- * segments.c.
- */
-static void copy_in_guest_info(struct lguest *lg, struct lguest_pages *pages)
-{
- /* Copying all this data can be quite expensive. We usually run the
- * same Guest we ran last time (and that Guest hasn't run anywhere else
- * meanwhile). If that's not the case, we pretend everything in the
- * Guest has changed. */
- if (__get_cpu_var(last_guest) != lg || lg->last_pages != pages) {
- __get_cpu_var(last_guest) = lg;
- lg->last_pages = pages;
- lg->changed = CHANGED_ALL;
- }
-
- /* These copies are pretty cheap, so we do them unconditionally: */
- /* Save the current Host top-level page directory. */
- pages->state.host_cr3 = __pa(current->mm->pgd);
- /* Set up the Guest's page tables to see this CPU's pages (and no
- * other CPU's pages). */
- map_switcher_in_guest(lg, pages);
- /* Set up the two "TSS" members which tell the CPU what stack to use
- * for traps which do directly into the Guest (ie. traps at privilege
- * level 1). */
- pages->state.guest_tss.esp1 = lg->esp1;
- pages->state.guest_tss.ss1 = lg->ss1;
-
- /* Copy direct-to-Guest trap entries. */
- if (lg->changed & CHANGED_IDT)
- copy_traps(lg, pages->state.guest_idt, default_idt_entries);
-
- /* Copy all GDT entries which the Guest can change. */
- if (lg->changed & CHANGED_GDT)
- copy_gdt(lg, pages->state.guest_gdt);
- /* If only the TLS entries have changed, copy them. */
- else if (lg->changed & CHANGED_GDT_TLS)
- copy_gdt_tls(lg, pages->state.guest_gdt);
-
- /* Mark the Guest as unchanged for next time. */
- lg->changed = 0;
-}
-
-/* Finally: the code to actually call into the Switcher to run the Guest. */
-static void run_guest_once(struct lguest *lg, struct lguest_pages *pages)
-{
- /* This is a dummy value we need for GCC's sake. */
- unsigned int clobber;
-
- /* Copy the guest-specific information into this CPU's "struct
- * lguest_pages". */
- copy_in_guest_info(lg, pages);
-
- /* Set the trap number to 256 (impossible value). If we fault while
- * switching to the Guest (bad segment registers or bug), this will
- * cause us to abort the Guest. */
- lg->regs->trapnum = 256;
-
- /* Now: we push the "eflags" register on the stack, then do an "lcall".
- * This is how we change from using the kernel code segment to using
- * the dedicated lguest code segment, as well as jumping into the
- * Switcher.
- *
- * The lcall also pushes the old code segment (KERNEL_CS) onto the
- * stack, then the address of this call. This stack layout happens to
- * exactly match the stack of an interrupt... */
- asm volatile("pushf; lcall *lguest_entry"
- /* This is how we tell GCC that %eax ("a") and %ebx ("b")
- * are changed by this routine. The "=" means output. */
- : "=a"(clobber), "=b"(clobber)
- /* %eax contains the pages pointer. ("0" refers to the
- * 0-th argument above, ie "a"). %ebx contains the
- * physical address of the Guest's top-level page
- * directory. */
- : "0"(pages), "1"(__pa(lg->pgdirs[lg->pgdidx].pgdir))
- /* We tell gcc that all these registers could change,
- * which means we don't have to save and restore them in
- * the Switcher. */
- : "memory", "%edx", "%ecx", "%edi", "%esi");
-}
/*:*/
/*H:030 Let's jump straight to the the main loop which runs the Guest.
@@ -489,22 +178,16 @@ int run_guest(struct lguest *lg, unsigned long __user *user)
{
/* We stop running once the Guest is dead. */
while (!lg->dead) {
- /* We need to initialize this, otherwise gcc complains. It's
- * not (yet) clever enough to see that it's initialized when we
- * need it. */
- unsigned int cr2 = 0; /* Damn gcc */
-
- /* First we run any hypercalls the Guest wants done: either in
- * the hypercall ring in "struct lguest_data", or directly by
- * using int 31 (LGUEST_TRAP_ENTRY). */
- do_hypercalls(lg);
- /* It's possible the Guest did a SEND_DMA hypercall to the
+ /* First we run any hypercalls the Guest wants done. */
+ if (lg->hcall)
+ do_hypercalls(lg);
+
+ /* It's possible the Guest did a NOTIFY hypercall to the
* Launcher, in which case we return from the read() now. */
- if (lg->dma_is_pending) {
- if (put_user(lg->pending_dma, user) ||
- put_user(lg->pending_key, user+1))
+ if (lg->pending_notify) {
+ if (put_user(lg->pending_notify, user))
return -EFAULT;
- return sizeof(unsigned long)*2;
+ return sizeof(lg->pending_notify);
}
/* Check for signals */
@@ -542,144 +225,20 @@ int run_guest(struct lguest *lg, unsigned long __user *user)
* the "Do Not Disturb" sign: */
local_irq_disable();
- /* Remember the awfully-named TS bit? If the Guest has asked
- * to set it we set it now, so we can trap and pass that trap
- * to the Guest if it uses the FPU. */
- if (lg->ts)
- set_ts();
-
- /* SYSENTER is an optimized way of doing system calls. We
- * can't allow it because it always jumps to privilege level 0.
- * A normal Guest won't try it because we don't advertise it in
- * CPUID, but a malicious Guest (or malicious Guest userspace
- * program) could, so we tell the CPU to disable it before
- * running the Guest. */
- if (boot_cpu_has(X86_FEATURE_SEP))
- wrmsr(MSR_IA32_SYSENTER_CS, 0, 0);
-
- /* Now we actually run the Guest. It will pop back out when
- * something interesting happens, and we can examine its
- * registers to see what it was doing. */
- run_guest_once(lg, lguest_pages(raw_smp_processor_id()));
-
- /* The "regs" pointer contains two extra entries which are not
- * really registers: a trap number which says what interrupt or
- * trap made the switcher code come back, and an error code
- * which some traps set. */
-
- /* If the Guest page faulted, then the cr2 register will tell
- * us the bad virtual address. We have to grab this now,
- * because once we re-enable interrupts an interrupt could
- * fault and thus overwrite cr2, or we could even move off to a
- * different CPU. */
- if (lg->regs->trapnum == 14)
- cr2 = read_cr2();
- /* Similarly, if we took a trap because the Guest used the FPU,
- * we have to restore the FPU it expects to see. */
- else if (lg->regs->trapnum == 7)
- math_state_restore();
-
- /* Restore SYSENTER if it's supposed to be on. */
- if (boot_cpu_has(X86_FEATURE_SEP))
- wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0);
+ /* Actually run the Guest until something happens. */
+ lguest_arch_run_guest(lg);
/* Now we're ready to be interrupted or moved to other CPUs */
local_irq_enable();
- /* OK, so what happened? */
- switch (lg->regs->trapnum) {
- case 13: /* We've intercepted a GPF. */
- /* Check if this was one of those annoying IN or OUT
- * instructions which we need to emulate. If so, we
- * just go back into the Guest after we've done it. */
- if (lg->regs->errcode == 0) {
- if (emulate_insn(lg))
- continue;
- }
- break;
- case 14: /* We've intercepted a page fault. */
- /* The Guest accessed a virtual address that wasn't
- * mapped. This happens a lot: we don't actually set
- * up most of the page tables for the Guest at all when
- * we start: as it runs it asks for more and more, and
- * we set them up as required. In this case, we don't
- * even tell the Guest that the fault happened.
- *
- * The errcode tells whether this was a read or a
- * write, and whether kernel or userspace code. */
- if (demand_page(lg, cr2, lg->regs->errcode))
- continue;
-
- /* OK, it's really not there (or not OK): the Guest
- * needs to know. We write out the cr2 value so it
- * knows where the fault occurred.
- *
- * Note that if the Guest were really messed up, this
- * could happen before it's done the INITIALIZE
- * hypercall, so lg->lguest_data will be NULL, so
- * &lg->lguest_data->cr2 will be address 8. Writing
- * into that address won't hurt the Host at all,
- * though. */
- if (put_user(cr2, &lg->lguest_data->cr2))
- kill_guest(lg, "Writing cr2");
- break;
- case 7: /* We've intercepted a Device Not Available fault. */
- /* If the Guest doesn't want to know, we already
- * restored the Floating Point Unit, so we just
- * continue without telling it. */
- if (!lg->ts)
- continue;
- break;
- case 32 ... 255:
- /* These values mean a real interrupt occurred, in
- * which case the Host handler has already been run.
- * We just do a friendly check if another process
- * should now be run, then fall through to loop
- * around: */
- cond_resched();
- case LGUEST_TRAP_ENTRY: /* Handled at top of loop */
- continue;
- }
-
- /* If we get here, it's a trap the Guest wants to know
- * about. */
- if (deliver_trap(lg, lg->regs->trapnum))
- continue;
-
- /* If the Guest doesn't have a handler (either it hasn't
- * registered any yet, or it's one of the faults we don't let
- * it handle), it dies with a cryptic error message. */
- kill_guest(lg, "unhandled trap %li at %#lx (%#lx)",
- lg->regs->trapnum, lg->regs->eip,
- lg->regs->trapnum == 14 ? cr2 : lg->regs->errcode);
+ /* Now we deal with whatever happened to the Guest. */
+ lguest_arch_handle_trap(lg);
}
+
/* The Guest is dead => "No such file or directory" */
return -ENOENT;
}
-/* Now we can look at each of the routines this calls, in increasing order of
- * complexity: do_hypercalls(), emulate_insn(), maybe_do_interrupt(),
- * deliver_trap() and demand_page(). After all those, we'll be ready to
- * examine the Switcher, and our philosophical understanding of the Host/Guest
- * duality will be complete. :*/
-
-int find_free_guest(void)
-{
- unsigned int i;
- for (i = 0; i < MAX_LGUEST_GUESTS; i++)
- if (!lguests[i].tsk)
- return i;
- return -1;
-}
-
-static void adjust_pge(void *on)
-{
- if (on)
- write_cr4(read_cr4() | X86_CR4_PGE);
- else
- write_cr4(read_cr4() & ~X86_CR4_PGE);
-}
-
/*H:000
* Welcome to the Host!
*
@@ -694,79 +253,57 @@ static int __init init(void)
/* Lguest can't run under Xen, VMI or itself. It does Tricky Stuff. */
if (paravirt_enabled()) {
- printk("lguest is afraid of %s\n", paravirt_ops.name);
+ printk("lguest is afraid of %s\n", pv_info.name);
return -EPERM;
}
/* First we put the Switcher up in very high virtual memory. */
err = map_switcher();
if (err)
- return err;
+ goto out;
/* Now we set up the pagetable implementation for the Guests. */
err = init_pagetables(switcher_page, SHARED_SWITCHER_PAGES);
- if (err) {
- unmap_switcher();
- return err;
- }
+ if (err)
+ goto unmap;
- /* The I/O subsystem needs some things initialized. */
- lguest_io_init();
+ /* We might need to reserve an interrupt vector. */
+ err = init_interrupts();
+ if (err)
+ goto free_pgtables;
/* /dev/lguest needs to be registered. */
err = lguest_device_init();
- if (err) {
- free_pagetables();
- unmap_switcher();
- return err;
- }
+ if (err)
+ goto free_interrupts;
- /* Finally, we need to turn off "Page Global Enable". PGE is an
- * optimization where page table entries are specially marked to show
- * they never change. The Host kernel marks all the kernel pages this
- * way because it's always present, even when userspace is running.
- *
- * Lguest breaks this: unbeknownst to the rest of the Host kernel, we
- * switch to the Guest kernel. If you don't disable this on all CPUs,
- * you'll get really weird bugs that you'll chase for two days.
- *
- * I used to turn PGE off every time we switched to the Guest and back
- * on when we return, but that slowed the Switcher down noticibly. */
-
- /* We don't need the complexity of CPUs coming and going while we're
- * doing this. */
- lock_cpu_hotplug();
- if (cpu_has_pge) { /* We have a broader idea of "global". */
- /* Remember that this was originally set (for cleanup). */
- cpu_had_pge = 1;
- /* adjust_pge is a helper function which sets or unsets the PGE
- * bit on its CPU, depending on the argument (0 == unset). */
- on_each_cpu(adjust_pge, (void *)0, 0, 1);
- /* Turn off the feature in the global feature set. */
- clear_bit(X86_FEATURE_PGE, boot_cpu_data.x86_capability);
- }
- unlock_cpu_hotplug();
+ /* Finally we do some architecture-specific setup. */
+ lguest_arch_host_init();
/* All good! */
return 0;
+
+free_interrupts:
+ free_interrupts();
+free_pgtables:
+ free_pagetables();
+unmap:
+ unmap_switcher();
+out:
+ return err;
}
/* Cleaning up is just the same code, backwards. With a little French. */
static void __exit fini(void)
{
lguest_device_remove();
+ free_interrupts();
free_pagetables();
unmap_switcher();
- /* If we had PGE before we started, turn it back on now. */
- lock_cpu_hotplug();
- if (cpu_had_pge) {
- set_bit(X86_FEATURE_PGE, boot_cpu_data.x86_capability);
- /* adjust_pge's argument "1" means set PGE. */
- on_each_cpu(adjust_pge, (void *)1, 0, 1);
- }
- unlock_cpu_hotplug();
+ lguest_arch_host_fini();
}
+/*:*/
/* The Host side of lguest can be a module. This is a nice way for people to
* play with it. */
diff --git a/drivers/lguest/hypercalls.c b/drivers/lguest/hypercalls.c
index db6caace3b9c..b478affe8f91 100644
--- a/drivers/lguest/hypercalls.c
+++ b/drivers/lguest/hypercalls.c
@@ -25,17 +25,13 @@
#include <linux/mm.h>
#include <asm/page.h>
#include <asm/pgtable.h>
-#include <irq_vectors.h>
#include "lg.h"
-/*H:120 This is the core hypercall routine: where the Guest gets what it
- * wants. Or gets killed. Or, in the case of LHCALL_CRASH, both.
- *
- * Remember from the Guest: %eax == which call to make, and the arguments are
- * packed into %edx, %ebx and %ecx if needed. */
-static void do_hcall(struct lguest *lg, struct lguest_regs *regs)
+/*H:120 This is the core hypercall routine: where the Guest gets what it wants.
+ * Or gets killed. Or, in the case of LHCALL_CRASH, both. */
+static void do_hcall(struct lguest *lg, struct hcall_args *args)
{
- switch (regs->eax) {
+ switch (args->arg0) {
case LHCALL_FLUSH_ASYNC:
/* This call does nothing, except by breaking out of the Guest
* it makes us process all the asynchronous hypercalls. */
@@ -51,7 +47,7 @@ static void do_hcall(struct lguest *lg, struct lguest_regs *regs)
char msg[128];
/* If the lgread fails, it will call kill_guest() itself; the
* kill_guest() with the message will be ignored. */
- lgread(lg, msg, regs->edx, sizeof(msg));
+ __lgread(lg, msg, args->arg1, sizeof(msg));
msg[sizeof(msg)-1] = '\0';
kill_guest(lg, "CRASH: %s", msg);
break;
@@ -59,67 +55,50 @@ static void do_hcall(struct lguest *lg, struct lguest_regs *regs)
case LHCALL_FLUSH_TLB:
/* FLUSH_TLB comes in two flavors, depending on the
* argument: */
- if (regs->edx)
+ if (args->arg1)
guest_pagetable_clear_all(lg);
else
guest_pagetable_flush_user(lg);
break;
- case LHCALL_BIND_DMA:
- /* BIND_DMA really wants four arguments, but it's the only call
- * which does. So the Guest packs the number of buffers and
- * the interrupt number into the final argument, and we decode
- * it here. This can legitimately fail, since we currently
- * place a limit on the number of DMA pools a Guest can have.
- * So we return true or false from this call. */
- regs->eax = bind_dma(lg, regs->edx, regs->ebx,
- regs->ecx >> 8, regs->ecx & 0xFF);
- break;
/* All these calls simply pass the arguments through to the right
* routines. */
- case LHCALL_SEND_DMA:
- send_dma(lg, regs->edx, regs->ebx);
- break;
- case LHCALL_LOAD_GDT:
- load_guest_gdt(lg, regs->edx, regs->ebx);
- break;
- case LHCALL_LOAD_IDT_ENTRY:
- load_guest_idt_entry(lg, regs->edx, regs->ebx, regs->ecx);
- break;
case LHCALL_NEW_PGTABLE:
- guest_new_pagetable(lg, regs->edx);
+ guest_new_pagetable(lg, args->arg1);
break;
case LHCALL_SET_STACK:
- guest_set_stack(lg, regs->edx, regs->ebx, regs->ecx);
+ guest_set_stack(lg, args->arg1, args->arg2, args->arg3);
break;
case LHCALL_SET_PTE:
- guest_set_pte(lg, regs->edx, regs->ebx, mkgpte(regs->ecx));
+ guest_set_pte(lg, args->arg1, args->arg2, __pte(args->arg3));
break;
case LHCALL_SET_PMD:
- guest_set_pmd(lg, regs->edx, regs->ebx);
- break;
- case LHCALL_LOAD_TLS:
- guest_load_tls(lg, regs->edx);
+ guest_set_pmd(lg, args->arg1, args->arg2);
break;
case LHCALL_SET_CLOCKEVENT:
- guest_set_clockevent(lg, regs->edx);
+ guest_set_clockevent(lg, args->arg1);
break;
-
case LHCALL_TS:
/* This sets the TS flag, as we saw used in run_guest(). */
- lg->ts = regs->edx;
+ lg->ts = args->arg1;
break;
case LHCALL_HALT:
/* Similarly, this sets the halted flag for run_guest(). */
lg->halted = 1;
break;
+ case LHCALL_NOTIFY:
+ lg->pending_notify = args->arg1;
+ break;
default:
- kill_guest(lg, "Bad hypercall %li\n", regs->eax);
+ /* It should be an architecture-specific hypercall. */
+ if (lguest_arch_do_hcall(lg, args))
+ kill_guest(lg, "Bad hypercall %li\n", args->arg0);
}
}
+/*:*/
-/* Asynchronous hypercalls are easy: we just look in the array in the Guest's
- * "struct lguest_data" and see if there are any new ones marked "ready".
+/*H:124 Asynchronous hypercalls are easy: we just look in the array in the
+ * Guest's "struct lguest_data" to see if any new ones are marked "ready".
*
* We are careful to do these in order: obviously we respect the order the
* Guest put them in the ring, but we also promise the Guest that they will
@@ -134,10 +113,9 @@ static void do_async_hcalls(struct lguest *lg)
if (copy_from_user(&st, &lg->lguest_data->hcall_status, sizeof(st)))
return;
-
/* We process "struct lguest_data"s hcalls[] ring once. */
for (i = 0; i < ARRAY_SIZE(st); i++) {
- struct lguest_regs regs;
+ struct hcall_args args;
/* We remember where we were up to from last time. This makes
* sure that the hypercalls are done in the order the Guest
* places them in the ring. */
@@ -152,18 +130,16 @@ static void do_async_hcalls(struct lguest *lg)
if (++lg->next_hcall == LHCALL_RING_SIZE)
lg->next_hcall = 0;
- /* We copy the hypercall arguments into a fake register
- * structure. This makes life simple for do_hcall(). */
- if (get_user(regs.eax, &lg->lguest_data->hcalls[n].eax)
- || get_user(regs.edx, &lg->lguest_data->hcalls[n].edx)
- || get_user(regs.ecx, &lg->lguest_data->hcalls[n].ecx)
- || get_user(regs.ebx, &lg->lguest_data->hcalls[n].ebx)) {
+ /* Copy the hypercall arguments into a local copy of
+ * the hcall_args struct. */
+ if (copy_from_user(&args, &lg->lguest_data->hcalls[n],
+ sizeof(struct hcall_args))) {
kill_guest(lg, "Fetching async hypercalls");
break;
}
/* Do the hypercall, same as a normal one. */
- do_hcall(lg, &regs);
+ do_hcall(lg, &args);
/* Mark the hypercall done. */
if (put_user(0xFF, &lg->lguest_data->hcall_status[n])) {
@@ -171,9 +147,9 @@ static void do_async_hcalls(struct lguest *lg)
break;
}
- /* Stop doing hypercalls if we've just done a DMA to the
- * Launcher: it needs to service this first. */
- if (lg->dma_is_pending)
+ /* Stop doing hypercalls if they want to notify the Launcher:
+ * it needs to service this first. */
+ if (lg->pending_notify)
break;
}
}
@@ -182,76 +158,35 @@ static void do_async_hcalls(struct lguest *lg)
* Guest makes a hypercall, we end up here to set things up: */
static void initialize(struct lguest *lg)
{
- u32 tsc_speed;
-
/* You can't do anything until you're initialized. The Guest knows the
* rules, so we're unforgiving here. */
- if (lg->regs->eax != LHCALL_LGUEST_INIT) {
- kill_guest(lg, "hypercall %li before LGUEST_INIT",
- lg->regs->eax);
+ if (lg->hcall->arg0 != LHCALL_LGUEST_INIT) {
+ kill_guest(lg, "hypercall %li before INIT", lg->hcall->arg0);
return;
}
- /* We insist that the Time Stamp Counter exist and doesn't change with
- * cpu frequency. Some devious chip manufacturers decided that TSC
- * changes could be handled in software. I decided that time going
- * backwards might be good for benchmarks, but it's bad for users.
- *
- * We also insist that the TSC be stable: the kernel detects unreliable
- * TSCs for its own purposes, and we use that here. */
- if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC) && !check_tsc_unstable())
- tsc_speed = tsc_khz;
- else
- tsc_speed = 0;
-
- /* The pointer to the Guest's "struct lguest_data" is the only
- * argument. */
- lg->lguest_data = (struct lguest_data __user *)lg->regs->edx;
- /* If we check the address they gave is OK now, we can simply
- * copy_to_user/from_user from now on rather than using lgread/lgwrite.
- * I put this in to show that I'm not immune to writing stupid
- * optimizations. */
- if (!lguest_address_ok(lg, lg->regs->edx, sizeof(*lg->lguest_data))) {
+ if (lguest_arch_init_hypercalls(lg))
kill_guest(lg, "bad guest page %p", lg->lguest_data);
- return;
- }
+
/* The Guest tells us where we're not to deliver interrupts by putting
* the range of addresses into "struct lguest_data". */
if (get_user(lg->noirq_start, &lg->lguest_data->noirq_start)
- || get_user(lg->noirq_end, &lg->lguest_data->noirq_end)
- /* We tell the Guest that it can't use the top 4MB of virtual
- * addresses used by the Switcher. */
- || put_user(4U*1024*1024, &lg->lguest_data->reserve_mem)
- || put_user(tsc_speed, &lg->lguest_data->tsc_khz)
- /* We also give the Guest a unique id, as used in lguest_net.c. */
- || put_user(lg->guestid, &lg->lguest_data->guestid))
+ || get_user(lg->noirq_end, &lg->lguest_data->noirq_end))
kill_guest(lg, "bad guest page %p", lg->lguest_data);
- /* We write the current time into the Guest's data page once now. */
+ /* We write the current time into the Guest's data page once so it can
+ * set its clock. */
write_timestamp(lg);
+ /* page_tables.c will also do some setup. */
+ page_table_guest_data_init(lg);
+
/* This is the one case where the above accesses might have been the
* first write to a Guest page. This may have caused a copy-on-write
- * fault, but the Guest might be referring to the old (read-only)
- * page. */
+ * fault, but the old page might be (read-only) in the Guest
+ * pagetable. */
guest_pagetable_clear_all(lg);
}
-/* Now we've examined the hypercall code; our Guest can make requests. There
- * is one other way we can do things for the Guest, as we see in
- * emulate_insn(). */
-
-/*H:110 Tricky point: we mark the hypercall as "done" once we've done it.
- * Normally we don't need to do this: the Guest will run again and update the
- * trap number before we come back around the run_guest() loop to
- * do_hypercalls().
- *
- * However, if we are signalled or the Guest sends DMA to the Launcher, that
- * loop will exit without running the Guest. When it comes back it would try
- * to re-run the hypercall. */
-static void clear_hcall(struct lguest *lg)
-{
- lg->regs->trapnum = 255;
-}
/*H:100
* Hypercalls
@@ -261,16 +196,12 @@ static void clear_hcall(struct lguest *lg)
*/
void do_hypercalls(struct lguest *lg)
{
- /* Not initialized yet? */
+ /* Not initialized yet? This hypercall must do it. */
if (unlikely(!lg->lguest_data)) {
- /* Did the Guest make a hypercall? We might have come back for
- * some other reason (an interrupt, a different trap). */
- if (lg->regs->trapnum == LGUEST_TRAP_ENTRY) {
- /* Set up the "struct lguest_data" */
- initialize(lg);
- /* The hypercall is done. */
- clear_hcall(lg);
- }
+ /* Set up the "struct lguest_data" */
+ initialize(lg);
+ /* Hcall is done. */
+ lg->hcall = NULL;
return;
}
@@ -280,12 +211,21 @@ void do_hypercalls(struct lguest *lg)
do_async_hcalls(lg);
/* If we stopped reading the hypercall ring because the Guest did a
- * SEND_DMA to the Launcher, we want to return now. Otherwise if the
- * Guest asked us to do a hypercall, we do it. */
- if (!lg->dma_is_pending && lg->regs->trapnum == LGUEST_TRAP_ENTRY) {
- do_hcall(lg, lg->regs);
- /* The hypercall is done. */
- clear_hcall(lg);
+ * NOTIFY to the Launcher, we want to return now. Otherwise we do
+ * the hypercall. */
+ if (!lg->pending_notify) {
+ do_hcall(lg, lg->hcall);
+ /* Tricky point: we reset the hcall pointer to mark the
+ * hypercall as "done". We use the hcall pointer rather than
+ * the trap number to indicate a hypercall is pending.
+ * Normally it doesn't matter: the Guest will run again and
+ * update the trap number before we come back here.
+ *
+ * However, if we are signalled or the Guest sends I/O to the
+ * Launcher, the run_guest() loop will exit without running the
+ * Guest. When it comes back it would try to re-run the
+ * hypercall. */
+ lg->hcall = NULL;
}
}
@@ -295,6 +235,6 @@ void write_timestamp(struct lguest *lg)
{
struct timespec now;
ktime_get_real_ts(&now);
- if (put_user(now, &lg->lguest_data->time))
+ if (copy_to_user(&lg->lguest_data->time, &now, sizeof(struct timespec)))
kill_guest(lg, "Writing timestamp");
}
diff --git a/drivers/lguest/interrupts_and_traps.c b/drivers/lguest/interrupts_and_traps.c
index 39731232d827..2b66f79c208b 100644
--- a/drivers/lguest/interrupts_and_traps.c
+++ b/drivers/lguest/interrupts_and_traps.c
@@ -12,8 +12,14 @@
* them first, so we also have a way of "reflecting" them into the Guest as if
* they had been delivered to it directly. :*/
#include <linux/uaccess.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
#include "lg.h"
+/* Allow Guests to use a non-128 (ie. non-Linux) syscall trap. */
+static unsigned int syscall_vector = SYSCALL_VECTOR;
+module_param(syscall_vector, uint, 0444);
+
/* The address of the interrupt handler is split into two bits: */
static unsigned long idt_address(u32 lo, u32 hi)
{
@@ -39,7 +45,7 @@ static void push_guest_stack(struct lguest *lg, unsigned long *gstack, u32 val)
{
/* Stack grows upwards: move stack then write value. */
*gstack -= 4;
- lgwrite_u32(lg, *gstack, val);
+ lgwrite(lg, *gstack, u32, val);
}
/*H:210 The set_guest_interrupt() routine actually delivers the interrupt or
@@ -56,8 +62,9 @@ static void push_guest_stack(struct lguest *lg, unsigned long *gstack, u32 val)
* it). */
static void set_guest_interrupt(struct lguest *lg, u32 lo, u32 hi, int has_err)
{
- unsigned long gstack;
+ unsigned long gstack, origstack;
u32 eflags, ss, irq_enable;
+ unsigned long virtstack;
/* There are two cases for interrupts: one where the Guest is already
* in the kernel, and a more complex one where the Guest is in
@@ -65,8 +72,10 @@ static void set_guest_interrupt(struct lguest *lg, u32 lo, u32 hi, int has_err)
if ((lg->regs->ss&0x3) != GUEST_PL) {
/* The Guest told us their kernel stack with the SET_STACK
* hypercall: both the virtual address and the segment */
- gstack = guest_pa(lg, lg->esp1);
+ virtstack = lg->esp1;
ss = lg->ss1;
+
+ origstack = gstack = guest_pa(lg, virtstack);
/* We push the old stack segment and pointer onto the new
* stack: when the Guest does an "iret" back from the interrupt
* handler the CPU will notice they're dropping privilege
@@ -75,14 +84,16 @@ static void set_guest_interrupt(struct lguest *lg, u32 lo, u32 hi, int has_err)
push_guest_stack(lg, &gstack, lg->regs->esp);
} else {
/* We're staying on the same Guest (kernel) stack. */
- gstack = guest_pa(lg, lg->regs->esp);
+ virtstack = lg->regs->esp;
ss = lg->regs->ss;
+
+ origstack = gstack = guest_pa(lg, virtstack);
}
/* Remember that we never let the Guest actually disable interrupts, so
* the "Interrupt Flag" bit is always set. We copy that bit from the
- * Guest's "irq_enabled" field into the eflags word: the Guest copies
- * it back in "lguest_iret". */
+ * Guest's "irq_enabled" field into the eflags word: we saw the Guest
+ * copy it back in "lguest_iret". */
eflags = lg->regs->eflags;
if (get_user(irq_enable, &lg->lguest_data->irq_enabled) == 0
&& !(irq_enable & X86_EFLAGS_IF))
@@ -102,7 +113,7 @@ static void set_guest_interrupt(struct lguest *lg, u32 lo, u32 hi, int has_err)
/* Now we've pushed all the old state, we change the stack, the code
* segment and the address to execute. */
lg->regs->ss = ss;
- lg->regs->esp = gstack + lg->page_offset;
+ lg->regs->esp = virtstack + (gstack - origstack);
lg->regs->cs = (__KERNEL_CS|GUEST_PL);
lg->regs->eip = idt_address(lo, hi);
@@ -113,7 +124,7 @@ static void set_guest_interrupt(struct lguest *lg, u32 lo, u32 hi, int has_err)
kill_guest(lg, "Disabling interrupts");
}
-/*H:200
+/*H:205
* Virtual Interrupts.
*
* maybe_do_interrupt() gets called before every entry to the Guest, to see if
@@ -165,7 +176,7 @@ void maybe_do_interrupt(struct lguest *lg)
/* Look at the IDT entry the Guest gave us for this interrupt. The
* first 32 (FIRST_EXTERNAL_VECTOR) entries are for traps, so we skip
* over them. */
- idt = &lg->idt[FIRST_EXTERNAL_VECTOR+irq];
+ idt = &lg->arch.idt[FIRST_EXTERNAL_VECTOR+irq];
/* If they don't have a handler (yet?), we just ignore it */
if (idt_present(idt->a, idt->b)) {
/* OK, mark it no longer pending and deliver it. */
@@ -183,6 +194,47 @@ void maybe_do_interrupt(struct lguest *lg)
* timer interrupt. */
write_timestamp(lg);
}
+/*:*/
+
+/* Linux uses trap 128 for system calls. Plan9 uses 64, and Ron Minnich sent
+ * me a patch, so we support that too. It'd be a big step for lguest if half
+ * the Plan 9 user base were to start using it.
+ *
+ * Actually now I think of it, it's possible that Ron *is* half the Plan 9
+ * userbase. Oh well. */
+static bool could_be_syscall(unsigned int num)
+{
+ /* Normal Linux SYSCALL_VECTOR or reserved vector? */
+ return num == SYSCALL_VECTOR || num == syscall_vector;
+}
+
+/* The syscall vector it wants must be unused by Host. */
+bool check_syscall_vector(struct lguest *lg)
+{
+ u32 vector;
+
+ if (get_user(vector, &lg->lguest_data->syscall_vec))
+ return false;
+
+ return could_be_syscall(vector);
+}
+
+int init_interrupts(void)
+{
+ /* If they want some strange system call vector, reserve it now */
+ if (syscall_vector != SYSCALL_VECTOR
+ && test_and_set_bit(syscall_vector, used_vectors)) {
+ printk("lg: couldn't reserve syscall %u\n", syscall_vector);
+ return -EBUSY;
+ }
+ return 0;
+}
+
+void free_interrupts(void)
+{
+ if (syscall_vector != SYSCALL_VECTOR)
+ clear_bit(syscall_vector, used_vectors);
+}
/*H:220 Now we've got the routines to deliver interrupts, delivering traps
* like page fault is easy. The only trick is that Intel decided that some
@@ -197,49 +249,43 @@ int deliver_trap(struct lguest *lg, unsigned int num)
{
/* Trap numbers are always 8 bit, but we set an impossible trap number
* for traps inside the Switcher, so check that here. */
- if (num >= ARRAY_SIZE(lg->idt))
+ if (num >= ARRAY_SIZE(lg->arch.idt))
return 0;
/* Early on the Guest hasn't set the IDT entries (or maybe it put a
* bogus one in): if we fail here, the Guest will be killed. */
- if (!idt_present(lg->idt[num].a, lg->idt[num].b))
+ if (!idt_present(lg->arch.idt[num].a, lg->arch.idt[num].b))
return 0;
- set_guest_interrupt(lg, lg->idt[num].a, lg->idt[num].b, has_err(num));
+ set_guest_interrupt(lg, lg->arch.idt[num].a, lg->arch.idt[num].b,
+ has_err(num));
return 1;
}
/*H:250 Here's the hard part: returning to the Host every time a trap happens
* and then calling deliver_trap() and re-entering the Guest is slow.
- * Particularly because Guest userspace system calls are traps (trap 128).
+ * Particularly because Guest userspace system calls are traps (usually trap
+ * 128).
*
* So we'd like to set up the IDT to tell the CPU to deliver traps directly
* into the Guest. This is possible, but the complexities cause the size of
* this file to double! However, 150 lines of code is worth writing for taking
* system calls down from 1750ns to 270ns. Plus, if lguest didn't do it, all
- * the other hypervisors would tease it.
+ * the other hypervisors would beat it up at lunchtime.
*
- * This routine determines if a trap can be delivered directly. */
-static int direct_trap(const struct lguest *lg,
- const struct desc_struct *trap,
- unsigned int num)
+ * This routine indicates if a particular trap number could be delivered
+ * directly. */
+static int direct_trap(unsigned int num)
{
/* Hardware interrupts don't go to the Guest at all (except system
* call). */
- if (num >= FIRST_EXTERNAL_VECTOR && num != SYSCALL_VECTOR)
+ if (num >= FIRST_EXTERNAL_VECTOR && !could_be_syscall(num))
return 0;
/* The Host needs to see page faults (for shadow paging and to save the
* fault address), general protection faults (in/out emulation) and
* device not available (TS handling), and of course, the hypercall
* trap. */
- if (num == 14 || num == 13 || num == 7 || num == LGUEST_TRAP_ENTRY)
- return 0;
-
- /* Only trap gates (type 15) can go direct to the Guest. Interrupt
- * gates (type 14) disable interrupts as they are entered, which we
- * never let the Guest do. Not present entries (type 0x0) also can't
- * go direct, of course 8) */
- return idt_type(trap->a, trap->b) == 0xF;
+ return num != 14 && num != 13 && num != 7 && num != LGUEST_TRAP_ENTRY;
}
/*:*/
@@ -287,7 +333,7 @@ void pin_stack_pages(struct lguest *lg)
* change stacks on each context switch. */
void guest_set_stack(struct lguest *lg, u32 seg, u32 esp, unsigned int pages)
{
- /* You are not allowd have a stack segment with privilege level 0: bad
+ /* You are not allowed have a stack segment with privilege level 0: bad
* Guest! */
if ((seg & 0x3) != GUEST_PL)
kill_guest(lg, "bad stack segment %i", seg);
@@ -306,7 +352,7 @@ void guest_set_stack(struct lguest *lg, u32 seg, u32 esp, unsigned int pages)
* part of the Host: page table handling. */
/*H:235 This is the routine which actually checks the Guest's IDT entry and
- * transfers it into our entry in "struct lguest": */
+ * transfers it into the entry in "struct lguest": */
static void set_trap(struct lguest *lg, struct desc_struct *trap,
unsigned int num, u32 lo, u32 hi)
{
@@ -348,15 +394,11 @@ void load_guest_idt_entry(struct lguest *lg, unsigned int num, u32 lo, u32 hi)
* to copy this again. */
lg->changed |= CHANGED_IDT;
- /* The IDT which we keep in "struct lguest" only contains 32 entries
- * for the traps and LGUEST_IRQS (32) entries for interrupts. We
- * ignore attempts to set handlers for higher interrupt numbers, except
- * for the system call "interrupt" at 128: we have a special IDT entry
- * for that. */
- if (num < ARRAY_SIZE(lg->idt))
- set_trap(lg, &lg->idt[num], num, lo, hi);
- else if (num == SYSCALL_VECTOR)
- set_trap(lg, &lg->syscall_idt, num, lo, hi);
+ /* Check that the Guest doesn't try to step outside the bounds. */
+ if (num >= ARRAY_SIZE(lg->arch.idt))
+ kill_guest(lg, "Setting idt entry %u", num);
+ else
+ set_trap(lg, &lg->arch.idt[num], num, lo, hi);
}
/* The default entry for each interrupt points into the Switcher routines which
@@ -399,22 +441,35 @@ void copy_traps(const struct lguest *lg, struct desc_struct *idt,
/* We can simply copy the direct traps, otherwise we use the default
* ones in the Switcher: they will return to the Host. */
- for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++) {
- if (direct_trap(lg, &lg->idt[i], i))
- idt[i] = lg->idt[i];
+ for (i = 0; i < ARRAY_SIZE(lg->arch.idt); i++) {
+ /* If no Guest can ever override this trap, leave it alone. */
+ if (!direct_trap(i))
+ continue;
+
+ /* Only trap gates (type 15) can go direct to the Guest.
+ * Interrupt gates (type 14) disable interrupts as they are
+ * entered, which we never let the Guest do. Not present
+ * entries (type 0x0) also can't go direct, of course. */
+ if (idt_type(lg->arch.idt[i].a, lg->arch.idt[i].b) == 0xF)
+ idt[i] = lg->arch.idt[i];
else
+ /* Reset it to the default. */
default_idt_entry(&idt[i], i, def[i]);
}
-
- /* Don't forget the system call trap! The IDT entries for other
- * interupts never change, so no need to copy them. */
- i = SYSCALL_VECTOR;
- if (direct_trap(lg, &lg->syscall_idt, i))
- idt[i] = lg->syscall_idt;
- else
- default_idt_entry(&idt[i], i, def[i]);
}
+/*H:200
+ * The Guest Clock.
+ *
+ * There are two sources of virtual interrupts. We saw one in lguest_user.c:
+ * the Launcher sending interrupts for virtual devices. The other is the Guest
+ * timer interrupt.
+ *
+ * The Guest uses the LHCALL_SET_CLOCKEVENT hypercall to tell us how long to
+ * the next timer interrupt (in nanoseconds). We use the high-resolution timer
+ * infrastructure to set a callback at that time.
+ *
+ * 0 means "turn off the clock". */
void guest_set_clockevent(struct lguest *lg, unsigned long delta)
{
ktime_t expires;
@@ -425,20 +480,27 @@ void guest_set_clockevent(struct lguest *lg, unsigned long delta)
return;
}
+ /* We use wallclock time here, so the Guest might not be running for
+ * all the time between now and the timer interrupt it asked for. This
+ * is almost always the right thing to do. */
expires = ktime_add_ns(ktime_get_real(), delta);
hrtimer_start(&lg->hrt, expires, HRTIMER_MODE_ABS);
}
+/* This is the function called when the Guest's timer expires. */
static enum hrtimer_restart clockdev_fn(struct hrtimer *timer)
{
struct lguest *lg = container_of(timer, struct lguest, hrt);
+ /* Remember the first interrupt is the timer interrupt. */
set_bit(0, lg->irqs_pending);
+ /* If the Guest is actually stopped, we need to wake it up. */
if (lg->halted)
wake_up_process(lg->tsk);
return HRTIMER_NORESTART;
}
+/* This sets up the timer for this Guest. */
void init_clockdev(struct lguest *lg)
{
hrtimer_init(&lg->hrt, CLOCK_REALTIME, HRTIMER_MODE_ABS);
diff --git a/drivers/lguest/io.c b/drivers/lguest/io.c
deleted file mode 100644
index ea68613b43f6..000000000000
--- a/drivers/lguest/io.c
+++ /dev/null
@@ -1,626 +0,0 @@
-/*P:300 The I/O mechanism in lguest is simple yet flexible, allowing the Guest
- * to talk to the Launcher or directly to another Guest. It uses familiar
- * concepts of DMA and interrupts, plus some neat code stolen from
- * futexes... :*/
-
-/* Copyright (C) 2006 Rusty Russell IBM Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-#include <linux/types.h>
-#include <linux/futex.h>
-#include <linux/jhash.h>
-#include <linux/mm.h>
-#include <linux/highmem.h>
-#include <linux/uaccess.h>
-#include "lg.h"
-
-/*L:300
- * I/O
- *
- * Getting data in and out of the Guest is quite an art. There are numerous
- * ways to do it, and they all suck differently. We try to keep things fairly
- * close to "real" hardware so our Guest's drivers don't look like an alien
- * visitation in the middle of the Linux code, and yet make sure that Guests
- * can talk directly to other Guests, not just the Launcher.
- *
- * To do this, the Guest gives us a key when it binds or sends DMA buffers.
- * The key corresponds to a "physical" address inside the Guest (ie. a virtual
- * address inside the Launcher process). We don't, however, use this key
- * directly.
- *
- * We want Guests which share memory to be able to DMA to each other: two
- * Launchers can mmap memory the same file, then the Guests can communicate.
- * Fortunately, the futex code provides us with a way to get a "union
- * futex_key" corresponding to the memory lying at a virtual address: if the
- * two processes share memory, the "union futex_key" for that memory will match
- * even if the memory is mapped at different addresses in each. So we always
- * convert the keys to "union futex_key"s to compare them.
- *
- * Before we dive into this though, we need to look at another set of helper
- * routines used throughout the Host kernel code to access Guest memory.
- :*/
-static struct list_head dma_hash[61];
-
-/* An unfortunate side effect of the Linux double-linked list implementation is
- * that there's no good way to statically initialize an array of linked
- * lists. */
-void lguest_io_init(void)
-{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(dma_hash); i++)
- INIT_LIST_HEAD(&dma_hash[i]);
-}
-
-/* FIXME: allow multi-page lengths. */
-static int check_dma_list(struct lguest *lg, const struct lguest_dma *dma)
-{
- unsigned int i;
-
- for (i = 0; i < LGUEST_MAX_DMA_SECTIONS; i++) {
- if (!dma->len[i])
- return 1;
- if (!lguest_address_ok(lg, dma->addr[i], dma->len[i]))
- goto kill;
- if (dma->len[i] > PAGE_SIZE)
- goto kill;
- /* We could do over a page, but is it worth it? */
- if ((dma->addr[i] % PAGE_SIZE) + dma->len[i] > PAGE_SIZE)
- goto kill;
- }
- return 1;
-
-kill:
- kill_guest(lg, "bad DMA entry: %u@%#lx", dma->len[i], dma->addr[i]);
- return 0;
-}
-
-/*L:330 This is our hash function, using the wonderful Jenkins hash.
- *
- * The futex key is a union with three parts: an unsigned long word, a pointer,
- * and an int "offset". We could use jhash_2words() which takes three u32s.
- * (Ok, the hash functions are great: the naming sucks though).
- *
- * It's nice to be portable to 64-bit platforms, so we use the more generic
- * jhash2(), which takes an array of u32, the number of u32s, and an initial
- * u32 to roll in. This is uglier, but breaks down to almost the same code on
- * 32-bit platforms like this one.
- *
- * We want a position in the array, so we modulo ARRAY_SIZE(dma_hash) (ie. 61).
- */
-static unsigned int hash(const union futex_key *key)
-{
- return jhash2((u32*)&key->both.word,
- (sizeof(key->both.word)+sizeof(key->both.ptr))/4,
- key->both.offset)
- % ARRAY_SIZE(dma_hash);
-}
-
-/* This is a convenience routine to compare two keys. It's a much bemoaned C
- * weakness that it doesn't allow '==' on structures or unions, so we have to
- * open-code it like this. */
-static inline int key_eq(const union futex_key *a, const union futex_key *b)
-{
- return (a->both.word == b->both.word
- && a->both.ptr == b->both.ptr
- && a->both.offset == b->both.offset);
-}
-
-/*L:360 OK, when we need to actually free up a Guest's DMA array we do several
- * things, so we have a convenient function to do it.
- *
- * The caller must hold a read lock on dmainfo owner's current->mm->mmap_sem
- * for the drop_futex_key_refs(). */
-static void unlink_dma(struct lguest_dma_info *dmainfo)
-{
- /* You locked this too, right? */
- BUG_ON(!mutex_is_locked(&lguest_lock));
- /* This is how we know that the entry is free. */
- dmainfo->interrupt = 0;
- /* Remove it from the hash table. */
- list_del(&dmainfo->list);
- /* Drop the references we were holding (to the inode or mm). */
- drop_futex_key_refs(&dmainfo->key);
-}
-
-/*L:350 This is the routine which we call when the Guest asks to unregister a
- * DMA array attached to a given key. Returns true if the array was found. */
-static int unbind_dma(struct lguest *lg,
- const union futex_key *key,
- unsigned long dmas)
-{
- int i, ret = 0;
-
- /* We don't bother with the hash table, just look through all this
- * Guest's DMA arrays. */
- for (i = 0; i < LGUEST_MAX_DMA; i++) {
- /* In theory it could have more than one array on the same key,
- * or one array on multiple keys, so we check both */
- if (key_eq(key, &lg->dma[i].key) && dmas == lg->dma[i].dmas) {
- unlink_dma(&lg->dma[i]);
- ret = 1;
- break;
- }
- }
- return ret;
-}
-
-/*L:340 BIND_DMA: this is the hypercall which sets up an array of "struct
- * lguest_dma" for receiving I/O.
- *
- * The Guest wants to bind an array of "struct lguest_dma"s to a particular key
- * to receive input. This only happens when the Guest is setting up a new
- * device, so it doesn't have to be very fast.
- *
- * It returns 1 on a successful registration (it can fail if we hit the limit
- * of registrations for this Guest).
- */
-int bind_dma(struct lguest *lg,
- unsigned long ukey, unsigned long dmas, u16 numdmas, u8 interrupt)
-{
- unsigned int i;
- int ret = 0;
- union futex_key key;
- /* Futex code needs the mmap_sem. */
- struct rw_semaphore *fshared = &current->mm->mmap_sem;
-
- /* Invalid interrupt? (We could kill the guest here). */
- if (interrupt >= LGUEST_IRQS)
- return 0;
-
- /* We need to grab the Big Lguest Lock, because other Guests may be
- * trying to look through this Guest's DMAs to send something while
- * we're doing this. */
- mutex_lock(&lguest_lock);
- down_read(fshared);
- if (get_futex_key((u32 __user *)ukey, fshared, &key) != 0) {
- kill_guest(lg, "bad dma key %#lx", ukey);
- goto unlock;
- }
-
- /* We want to keep this key valid once we drop mmap_sem, so we have to
- * hold a reference. */
- get_futex_key_refs(&key);
-
- /* If the Guest specified an interrupt of 0, that means they want to
- * unregister this array of "struct lguest_dma"s. */
- if (interrupt == 0)
- ret = unbind_dma(lg, &key, dmas);
- else {
- /* Look through this Guest's dma array for an unused entry. */
- for (i = 0; i < LGUEST_MAX_DMA; i++) {
- /* If the interrupt is non-zero, the entry is already
- * used. */
- if (lg->dma[i].interrupt)
- continue;
-
- /* OK, a free one! Fill on our details. */
- lg->dma[i].dmas = dmas;
- lg->dma[i].num_dmas = numdmas;
- lg->dma[i].next_dma = 0;
- lg->dma[i].key = key;
- lg->dma[i].guestid = lg->guestid;
- lg->dma[i].interrupt = interrupt;
-
- /* Now we add it to the hash table: the position
- * depends on the futex key that we got. */
- list_add(&lg->dma[i].list, &dma_hash[hash(&key)]);
- /* Success! */
- ret = 1;
- goto unlock;
- }
- }
- /* If we didn't find a slot to put the key in, drop the reference
- * again. */
- drop_futex_key_refs(&key);
-unlock:
- /* Unlock and out. */
- up_read(fshared);
- mutex_unlock(&lguest_lock);
- return ret;
-}
-
-/*L:385 Note that our routines to access a different Guest's memory are called
- * lgread_other() and lgwrite_other(): these names emphasize that they are only
- * used when the Guest is *not* the current Guest.
- *
- * The interface for copying from another process's memory is called
- * access_process_vm(), with a final argument of 0 for a read, and 1 for a
- * write.
- *
- * We need lgread_other() to read the destination Guest's "struct lguest_dma"
- * array. */
-static int lgread_other(struct lguest *lg,
- void *buf, u32 addr, unsigned bytes)
-{
- if (!lguest_address_ok(lg, addr, bytes)
- || access_process_vm(lg->tsk, addr, buf, bytes, 0) != bytes) {
- memset(buf, 0, bytes);
- kill_guest(lg, "bad address in registered DMA struct");
- return 0;
- }
- return 1;
-}
-
-/* "lgwrite()" to another Guest: used to update the destination "used_len" once
- * we've transferred data into the buffer. */
-static int lgwrite_other(struct lguest *lg, u32 addr,
- const void *buf, unsigned bytes)
-{
- if (!lguest_address_ok(lg, addr, bytes)
- || (access_process_vm(lg->tsk, addr, (void *)buf, bytes, 1)
- != bytes)) {
- kill_guest(lg, "bad address writing to registered DMA");
- return 0;
- }
- return 1;
-}
-
-/*L:400 This is the generic engine which copies from a source "struct
- * lguest_dma" from this Guest into another Guest's "struct lguest_dma". The
- * destination Guest's pages have already been mapped, as contained in the
- * pages array.
- *
- * If you're wondering if there's a nice "copy from one process to another"
- * routine, so was I. But Linux isn't really set up to copy between two
- * unrelated processes, so we have to write it ourselves.
- */
-static u32 copy_data(struct lguest *srclg,
- const struct lguest_dma *src,
- const struct lguest_dma *dst,
- struct page *pages[])
-{
- unsigned int totlen, si, di, srcoff, dstoff;
- void *maddr = NULL;
-
- /* We return the total length transferred. */
- totlen = 0;
-
- /* We keep indexes into the source and destination "struct lguest_dma",
- * and an offset within each region. */
- si = di = 0;
- srcoff = dstoff = 0;
-
- /* We loop until the source or destination is exhausted. */
- while (si < LGUEST_MAX_DMA_SECTIONS && src->len[si]
- && di < LGUEST_MAX_DMA_SECTIONS && dst->len[di]) {
- /* We can only transfer the rest of the src buffer, or as much
- * as will fit into the destination buffer. */
- u32 len = min(src->len[si] - srcoff, dst->len[di] - dstoff);
-
- /* For systems using "highmem" we need to use kmap() to access
- * the page we want. We often use the same page over and over,
- * so rather than kmap() it on every loop, we set the maddr
- * pointer to NULL when we need to move to the next
- * destination page. */
- if (!maddr)
- maddr = kmap(pages[di]);
-
- /* Copy directly from (this Guest's) source address to the
- * destination Guest's kmap()ed buffer. Note that maddr points
- * to the start of the page: we need to add the offset of the
- * destination address and offset within the buffer. */
-
- /* FIXME: This is not completely portable. I looked at
- * copy_to_user_page(), and some arch's seem to need special
- * flushes. x86 is fine. */
- if (copy_from_user(maddr + (dst->addr[di] + dstoff)%PAGE_SIZE,
- (void __user *)src->addr[si], len) != 0) {
- /* If a copy failed, it's the source's fault. */
- kill_guest(srclg, "bad address in sending DMA");
- totlen = 0;
- break;
- }
-
- /* Increment the total and src & dst offsets */
- totlen += len;
- srcoff += len;
- dstoff += len;
-
- /* Presumably we reached the end of the src or dest buffers: */
- if (srcoff == src->len[si]) {
- /* Move to the next buffer at offset 0 */
- si++;
- srcoff = 0;
- }
- if (dstoff == dst->len[di]) {
- /* We need to unmap that destination page and reset
- * maddr ready for the next one. */
- kunmap(pages[di]);
- maddr = NULL;
- di++;
- dstoff = 0;
- }
- }
-
- /* If we still had a page mapped at the end, unmap now. */
- if (maddr)
- kunmap(pages[di]);
-
- return totlen;
-}
-
-/*L:390 This is how we transfer a "struct lguest_dma" from the source Guest
- * (the current Guest which called SEND_DMA) to another Guest. */
-static u32 do_dma(struct lguest *srclg, const struct lguest_dma *src,
- struct lguest *dstlg, const struct lguest_dma *dst)
-{
- int i;
- u32 ret;
- struct page *pages[LGUEST_MAX_DMA_SECTIONS];
-
- /* We check that both source and destination "struct lguest_dma"s are
- * within the bounds of the source and destination Guests */
- if (!check_dma_list(dstlg, dst) || !check_dma_list(srclg, src))
- return 0;
-
- /* We need to map the pages which correspond to each parts of
- * destination buffer. */
- for (i = 0; i < LGUEST_MAX_DMA_SECTIONS; i++) {
- if (dst->len[i] == 0)
- break;
- /* get_user_pages() is a complicated function, especially since
- * we only want a single page. But it works, and returns the
- * number of pages. Note that we're holding the destination's
- * mmap_sem, as get_user_pages() requires. */
- if (get_user_pages(dstlg->tsk, dstlg->mm,
- dst->addr[i], 1, 1, 1, pages+i, NULL)
- != 1) {
- /* This means the destination gave us a bogus buffer */
- kill_guest(dstlg, "Error mapping DMA pages");
- ret = 0;
- goto drop_pages;
- }
- }
-
- /* Now copy the data until we run out of src or dst. */
- ret = copy_data(srclg, src, dst, pages);
-
-drop_pages:
- while (--i >= 0)
- put_page(pages[i]);
- return ret;
-}
-
-/*L:380 Transferring data from one Guest to another is not as simple as I'd
- * like. We've found the "struct lguest_dma_info" bound to the same address as
- * the send, we need to copy into it.
- *
- * This function returns true if the destination array was empty. */
-static int dma_transfer(struct lguest *srclg,
- unsigned long udma,
- struct lguest_dma_info *dst)
-{
- struct lguest_dma dst_dma, src_dma;
- struct lguest *dstlg;
- u32 i, dma = 0;
-
- /* From the "struct lguest_dma_info" we found in the hash, grab the
- * Guest. */
- dstlg = &lguests[dst->guestid];
- /* Read in the source "struct lguest_dma" handed to SEND_DMA. */
- lgread(srclg, &src_dma, udma, sizeof(src_dma));
-
- /* We need the destination's mmap_sem, and we already hold the source's
- * mmap_sem for the futex key lookup. Normally this would suggest that
- * we could deadlock if the destination Guest was trying to send to
- * this source Guest at the same time, which is another reason that all
- * I/O is done under the big lguest_lock. */
- down_read(&dstlg->mm->mmap_sem);
-
- /* Look through the destination DMA array for an available buffer. */
- for (i = 0; i < dst->num_dmas; i++) {
- /* We keep a "next_dma" pointer which often helps us avoid
- * looking at lots of previously-filled entries. */
- dma = (dst->next_dma + i) % dst->num_dmas;
- if (!lgread_other(dstlg, &dst_dma,
- dst->dmas + dma * sizeof(struct lguest_dma),
- sizeof(dst_dma))) {
- goto fail;
- }
- if (!dst_dma.used_len)
- break;
- }
-
- /* If we found a buffer, we do the actual data copy. */
- if (i != dst->num_dmas) {
- unsigned long used_lenp;
- unsigned int ret;
-
- ret = do_dma(srclg, &src_dma, dstlg, &dst_dma);
- /* Put used length in the source "struct lguest_dma"'s used_len
- * field. It's a little tricky to figure out where that is,
- * though. */
- lgwrite_u32(srclg,
- udma+offsetof(struct lguest_dma, used_len), ret);
- /* Tranferring 0 bytes is OK if the source buffer was empty. */
- if (ret == 0 && src_dma.len[0] != 0)
- goto fail;
-
- /* The destination Guest might be running on a different CPU:
- * we have to make sure that it will see the "used_len" field
- * change to non-zero *after* it sees the data we copied into
- * the buffer. Hence a write memory barrier. */
- wmb();
- /* Figuring out where the destination's used_len field for this
- * "struct lguest_dma" in the array is also a little ugly. */
- used_lenp = dst->dmas
- + dma * sizeof(struct lguest_dma)
- + offsetof(struct lguest_dma, used_len);
- lgwrite_other(dstlg, used_lenp, &ret, sizeof(ret));
- /* Move the cursor for next time. */
- dst->next_dma++;
- }
- up_read(&dstlg->mm->mmap_sem);
-
- /* We trigger the destination interrupt, even if the destination was
- * empty and we didn't transfer anything: this gives them a chance to
- * wake up and refill. */
- set_bit(dst->interrupt, dstlg->irqs_pending);
- /* Wake up the destination process. */
- wake_up_process(dstlg->tsk);
- /* If we passed the last "struct lguest_dma", the receive had no
- * buffers left. */
- return i == dst->num_dmas;
-
-fail:
- up_read(&dstlg->mm->mmap_sem);
- return 0;
-}
-
-/*L:370 This is the counter-side to the BIND_DMA hypercall; the SEND_DMA
- * hypercall. We find out who's listening, and send to them. */
-void send_dma(struct lguest *lg, unsigned long ukey, unsigned long udma)
-{
- union futex_key key;
- int empty = 0;
- struct rw_semaphore *fshared = &current->mm->mmap_sem;
-
-again:
- mutex_lock(&lguest_lock);
- down_read(fshared);
- /* Get the futex key for the key the Guest gave us */
- if (get_futex_key((u32 __user *)ukey, fshared, &key) != 0) {
- kill_guest(lg, "bad sending DMA key");
- goto unlock;
- }
- /* Since the key must be a multiple of 4, the futex key uses the lower
- * bit of the "offset" field (which would always be 0) to indicate a
- * mapping which is shared with other processes (ie. Guests). */
- if (key.shared.offset & 1) {
- struct lguest_dma_info *i;
- /* Look through the hash for other Guests. */
- list_for_each_entry(i, &dma_hash[hash(&key)], list) {
- /* Don't send to ourselves. */
- if (i->guestid == lg->guestid)
- continue;
- if (!key_eq(&key, &i->key))
- continue;
-
- /* If dma_transfer() tells us the destination has no
- * available buffers, we increment "empty". */
- empty += dma_transfer(lg, udma, i);
- break;
- }
- /* If the destination is empty, we release our locks and
- * give the destination Guest a brief chance to restock. */
- if (empty == 1) {
- /* Give any recipients one chance to restock. */
- up_read(&current->mm->mmap_sem);
- mutex_unlock(&lguest_lock);
- /* Next time, we won't try again. */
- empty++;
- goto again;
- }
- } else {
- /* Private mapping: Guest is sending to its Launcher. We set
- * the "dma_is_pending" flag so that the main loop will exit
- * and the Launcher's read() from /dev/lguest will return. */
- lg->dma_is_pending = 1;
- lg->pending_dma = udma;
- lg->pending_key = ukey;
- }
-unlock:
- up_read(fshared);
- mutex_unlock(&lguest_lock);
-}
-/*:*/
-
-void release_all_dma(struct lguest *lg)
-{
- unsigned int i;
-
- BUG_ON(!mutex_is_locked(&lguest_lock));
-
- down_read(&lg->mm->mmap_sem);
- for (i = 0; i < LGUEST_MAX_DMA; i++) {
- if (lg->dma[i].interrupt)
- unlink_dma(&lg->dma[i]);
- }
- up_read(&lg->mm->mmap_sem);
-}
-
-/*M:007 We only return a single DMA buffer to the Launcher, but it would be
- * more efficient to return a pointer to the entire array of DMA buffers, which
- * it can cache and choose one whenever it wants.
- *
- * Currently the Launcher uses a write to /dev/lguest, and the return value is
- * the address of the DMA structure with the interrupt number placed in
- * dma->used_len. If we wanted to return the entire array, we need to return
- * the address, array size and interrupt number: this seems to require an
- * ioctl(). :*/
-
-/*L:320 This routine looks for a DMA buffer registered by the Guest on the
- * given key (using the BIND_DMA hypercall). */
-unsigned long get_dma_buffer(struct lguest *lg,
- unsigned long ukey, unsigned long *interrupt)
-{
- unsigned long ret = 0;
- union futex_key key;
- struct lguest_dma_info *i;
- struct rw_semaphore *fshared = &current->mm->mmap_sem;
-
- /* Take the Big Lguest Lock to stop other Guests sending this Guest DMA
- * at the same time. */
- mutex_lock(&lguest_lock);
- /* To match between Guests sharing the same underlying memory we steal
- * code from the futex infrastructure. This requires that we hold the
- * "mmap_sem" for our process (the Launcher), and pass it to the futex
- * code. */
- down_read(fshared);
-
- /* This can fail if it's not a valid address, or if the address is not
- * divisible by 4 (the futex code needs that, we don't really). */
- if (get_futex_key((u32 __user *)ukey, fshared, &key) != 0) {
- kill_guest(lg, "bad registered DMA buffer");
- goto unlock;
- }
- /* Search the hash table for matching entries (the Launcher can only
- * send to its own Guest for the moment, so the entry must be for this
- * Guest) */
- list_for_each_entry(i, &dma_hash[hash(&key)], list) {
- if (key_eq(&key, &i->key) && i->guestid == lg->guestid) {
- unsigned int j;
- /* Look through the registered DMA array for an
- * available buffer. */
- for (j = 0; j < i->num_dmas; j++) {
- struct lguest_dma dma;
-
- ret = i->dmas + j * sizeof(struct lguest_dma);
- lgread(lg, &dma, ret, sizeof(dma));
- if (dma.used_len == 0)
- break;
- }
- /* Store the interrupt the Guest wants when the buffer
- * is used. */
- *interrupt = i->interrupt;
- break;
- }
- }
-unlock:
- up_read(fshared);
- mutex_unlock(&lguest_lock);
- return ret;
-}
-/*:*/
-
-/*L:410 This really has completed the Launcher. Not only have we now finished
- * the longest chapter in our journey, but this also means we are over halfway
- * through!
- *
- * Enough prevaricating around the bush: it is time for us to dive into the
- * core of the Host, in "make Host".
- */
diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h
index 64f0abed317c..86924891b5eb 100644
--- a/drivers/lguest/lg.h
+++ b/drivers/lguest/lg.h
@@ -1,119 +1,25 @@
#ifndef _LGUEST_H
#define _LGUEST_H
-#include <asm/desc.h>
-
-#define GDT_ENTRY_LGUEST_CS 10
-#define GDT_ENTRY_LGUEST_DS 11
-#define LGUEST_CS (GDT_ENTRY_LGUEST_CS * 8)
-#define LGUEST_DS (GDT_ENTRY_LGUEST_DS * 8)
-
#ifndef __ASSEMBLY__
#include <linux/types.h>
#include <linux/init.h>
#include <linux/stringify.h>
-#include <linux/binfmts.h>
-#include <linux/futex.h>
#include <linux/lguest.h>
#include <linux/lguest_launcher.h>
#include <linux/wait.h>
#include <linux/err.h>
#include <asm/semaphore.h>
-#include "irq_vectors.h"
-#define GUEST_PL 1
-
-struct lguest_regs
-{
- /* Manually saved part. */
- unsigned long ebx, ecx, edx;
- unsigned long esi, edi, ebp;
- unsigned long gs;
- unsigned long eax;
- unsigned long fs, ds, es;
- unsigned long trapnum, errcode;
- /* Trap pushed part */
- unsigned long eip;
- unsigned long cs;
- unsigned long eflags;
- unsigned long esp;
- unsigned long ss;
-};
+#include <asm/lguest.h>
void free_pagetables(void);
int init_pagetables(struct page **switcher_page, unsigned int pages);
-/* Full 4G segment descriptors, suitable for CS and DS. */
-#define FULL_EXEC_SEGMENT ((struct desc_struct){0x0000ffff, 0x00cf9b00})
-#define FULL_SEGMENT ((struct desc_struct){0x0000ffff, 0x00cf9300})
-
-struct lguest_dma_info
-{
- struct list_head list;
- union futex_key key;
- unsigned long dmas;
- u16 next_dma;
- u16 num_dmas;
- u16 guestid;
- u8 interrupt; /* 0 when not registered */
-};
-
-/*H:310 The page-table code owes a great debt of gratitude to Andi Kleen. He
- * reviewed the original code which used "u32" for all page table entries, and
- * insisted that it would be far clearer with explicit typing. I thought it
- * was overkill, but he was right: it is much clearer than it was before.
- *
- * We have separate types for the Guest's ptes & pgds and the shadow ptes &
- * pgds. There's already a Linux type for these (pte_t and pgd_t) but they
- * change depending on kernel config options (PAE). */
-
-/* Each entry is identical: lower 12 bits of flags and upper 20 bits for the
- * "page frame number" (0 == first physical page, etc). They are different
- * types so the compiler will warn us if we mix them improperly. */
-typedef union {
- struct { unsigned flags:12, pfn:20; };
- struct { unsigned long val; } raw;
-} spgd_t;
-typedef union {
- struct { unsigned flags:12, pfn:20; };
- struct { unsigned long val; } raw;
-} spte_t;
-typedef union {
- struct { unsigned flags:12, pfn:20; };
- struct { unsigned long val; } raw;
-} gpgd_t;
-typedef union {
- struct { unsigned flags:12, pfn:20; };
- struct { unsigned long val; } raw;
-} gpte_t;
-
-/* We have two convenient macros to convert a "raw" value as handed to us by
- * the Guest into the correct Guest PGD or PTE type. */
-#define mkgpte(_val) ((gpte_t){.raw.val = _val})
-#define mkgpgd(_val) ((gpgd_t){.raw.val = _val})
-/*:*/
-
struct pgdir
{
- unsigned long cr3;
- spgd_t *pgdir;
-};
-
-/* This is a guest-specific page (mapped ro) into the guest. */
-struct lguest_ro_state
-{
- /* Host information we need to restore when we switch back. */
- u32 host_cr3;
- struct Xgt_desc_struct host_idt_desc;
- struct Xgt_desc_struct host_gdt_desc;
- u32 host_sp;
-
- /* Fields which are used when guest is running. */
- struct Xgt_desc_struct guest_idt_desc;
- struct Xgt_desc_struct guest_gdt_desc;
- struct i386_hw_tss guest_tss;
- struct desc_struct guest_idt[IDT_ENTRIES];
- struct desc_struct guest_gdt[GDT_ENTRIES];
+ unsigned long gpgdir;
+ pgd_t *pgdir;
};
/* We have two pages shared with guests, per cpu. */
@@ -141,9 +47,11 @@ struct lguest
struct lguest_data __user *lguest_data;
struct task_struct *tsk;
struct mm_struct *mm; /* == tsk->mm, but that becomes NULL on exit */
- u16 guestid;
u32 pfn_limit;
- u32 page_offset;
+ /* This provides the offset to the base of guest-physical
+ * memory in the Launcher. */
+ void __user *mem_base;
+ unsigned long kernel_address;
u32 cr2;
int halted;
int ts;
@@ -151,6 +59,9 @@ struct lguest
u32 esp1;
u8 ss1;
+ /* If a hypercall was asked for, this points to the arguments. */
+ struct hcall_args *hcall;
+
/* Do we need to stop what we're doing and return to userspace? */
int break_out;
wait_queue_head_t break_wq;
@@ -163,28 +74,16 @@ struct lguest
u32 pgdidx;
struct pgdir pgdirs[4];
- /* Cached wakeup: we hold a reference to this task. */
- struct task_struct *wake;
-
unsigned long noirq_start, noirq_end;
- int dma_is_pending;
- unsigned long pending_dma; /* struct lguest_dma */
- unsigned long pending_key; /* address they're sending to */
+ unsigned long pending_notify; /* pfn from LHCALL_NOTIFY */
unsigned int stack_pages;
u32 tsc_khz;
- struct lguest_dma_info dma[LGUEST_MAX_DMA];
-
/* Dead? */
const char *dead;
- /* The GDT entries copied into lguest_ro_state when running. */
- struct desc_struct gdt[GDT_ENTRIES];
-
- /* The IDT entries: some copied into lguest_ro_state when running. */
- struct desc_struct idt[FIRST_EXTERNAL_VECTOR+LGUEST_IRQS];
- struct desc_struct syscall_idt;
+ struct lguest_arch arch;
/* Virtual clock device */
struct hrtimer hrt;
@@ -193,19 +92,38 @@ struct lguest
DECLARE_BITMAP(irqs_pending, LGUEST_IRQS);
};
-extern struct lguest lguests[];
extern struct mutex lguest_lock;
/* core.c: */
-u32 lgread_u32(struct lguest *lg, unsigned long addr);
-void lgwrite_u32(struct lguest *lg, unsigned long addr, u32 val);
-void lgread(struct lguest *lg, void *buf, unsigned long addr, unsigned len);
-void lgwrite(struct lguest *lg, unsigned long, const void *buf, unsigned len);
-int find_free_guest(void);
int lguest_address_ok(const struct lguest *lg,
unsigned long addr, unsigned long len);
+void __lgread(struct lguest *, void *, unsigned long, unsigned);
+void __lgwrite(struct lguest *, unsigned long, const void *, unsigned);
+
+/*H:035 Using memory-copy operations like that is usually inconvient, so we
+ * have the following helper macros which read and write a specific type (often
+ * an unsigned long).
+ *
+ * This reads into a variable of the given type then returns that. */
+#define lgread(lg, addr, type) \
+ ({ type _v; __lgread((lg), &_v, (addr), sizeof(_v)); _v; })
+
+/* This checks that the variable is of the given type, then writes it out. */
+#define lgwrite(lg, addr, type, val) \
+ do { \
+ typecheck(type, val); \
+ __lgwrite((lg), (addr), &(val), sizeof(val)); \
+ } while(0)
+/* (end of memory access helper routines) :*/
+
int run_guest(struct lguest *lg, unsigned long __user *user);
+/* Helper macros to obtain the first 12 or the last 20 bits, this is only the
+ * first step in the migration to the kernel types. pte_pfn is already defined
+ * in the kernel. */
+#define pgd_flags(x) (pgd_val(x) & ~PAGE_MASK)
+#define pte_flags(x) (pte_val(x) & ~PAGE_MASK)
+#define pgd_pfn(x) (pgd_val(x) >> PAGE_SHIFT)
/* interrupts_and_traps.c: */
void maybe_do_interrupt(struct lguest *lg);
@@ -219,6 +137,9 @@ void copy_traps(const struct lguest *lg, struct desc_struct *idt,
const unsigned long *def);
void guest_set_clockevent(struct lguest *lg, unsigned long delta);
void init_clockdev(struct lguest *lg);
+bool check_syscall_vector(struct lguest *lg);
+int init_interrupts(void);
+void free_interrupts(void);
/* segments.c: */
void setup_default_gdt_entries(struct lguest_ro_state *state);
@@ -232,28 +153,33 @@ void copy_gdt_tls(const struct lguest *lg, struct desc_struct *gdt);
int init_guest_pagetable(struct lguest *lg, unsigned long pgtable);
void free_guest_pagetable(struct lguest *lg);
void guest_new_pagetable(struct lguest *lg, unsigned long pgtable);
-void guest_set_pmd(struct lguest *lg, unsigned long cr3, u32 i);
+void guest_set_pmd(struct lguest *lg, unsigned long gpgdir, u32 i);
void guest_pagetable_clear_all(struct lguest *lg);
void guest_pagetable_flush_user(struct lguest *lg);
-void guest_set_pte(struct lguest *lg, unsigned long cr3,
- unsigned long vaddr, gpte_t val);
+void guest_set_pte(struct lguest *lg, unsigned long gpgdir,
+ unsigned long vaddr, pte_t val);
void map_switcher_in_guest(struct lguest *lg, struct lguest_pages *pages);
int demand_page(struct lguest *info, unsigned long cr2, int errcode);
void pin_page(struct lguest *lg, unsigned long vaddr);
+unsigned long guest_pa(struct lguest *lg, unsigned long vaddr);
+void page_table_guest_data_init(struct lguest *lg);
+
+/* <arch>/core.c: */
+void lguest_arch_host_init(void);
+void lguest_arch_host_fini(void);
+void lguest_arch_run_guest(struct lguest *lg);
+void lguest_arch_handle_trap(struct lguest *lg);
+int lguest_arch_init_hypercalls(struct lguest *lg);
+int lguest_arch_do_hcall(struct lguest *lg, struct hcall_args *args);
+void lguest_arch_setup_regs(struct lguest *lg, unsigned long start);
+
+/* <arch>/switcher.S: */
+extern char start_switcher_text[], end_switcher_text[], switch_to_guest[];
/* lguest_user.c: */
int lguest_device_init(void);
void lguest_device_remove(void);
-/* io.c: */
-void lguest_io_init(void);
-int bind_dma(struct lguest *lg,
- unsigned long key, unsigned long udma, u16 numdmas, u8 interrupt);
-void send_dma(struct lguest *info, unsigned long key, unsigned long udma);
-void release_all_dma(struct lguest *lg);
-unsigned long get_dma_buffer(struct lguest *lg, unsigned long key,
- unsigned long *interrupt);
-
/* hypercalls.c: */
void do_hypercalls(struct lguest *lg);
void write_timestamp(struct lguest *lg);
@@ -262,7 +188,7 @@ void write_timestamp(struct lguest *lg);
* Let's step aside for the moment, to study one important routine that's used
* widely in the Host code.
*
- * There are many cases where the Guest does something invalid, like pass crap
+ * There are many cases where the Guest can do something invalid, like pass crap
* to a hypercall. Since only the Guest kernel can make hypercalls, it's quite
* acceptable to simply terminate the Guest and give the Launcher a nicely
* formatted reason. It's also simpler for the Guest itself, which doesn't
@@ -292,9 +218,5 @@ do { \
} while(0)
/* (End of aside) :*/
-static inline unsigned long guest_pa(struct lguest *lg, unsigned long vaddr)
-{
- return vaddr - lg->page_offset;
-}
#endif /* __ASSEMBLY__ */
#endif /* _LGUEST_H */
diff --git a/drivers/lguest/lguest_bus.c b/drivers/lguest/lguest_bus.c
deleted file mode 100644
index 9e7752cc8002..000000000000
--- a/drivers/lguest/lguest_bus.c
+++ /dev/null
@@ -1,218 +0,0 @@
-/*P:050 Lguest guests use a very simple bus for devices. It's a simple array
- * of device descriptors contained just above the top of normal memory. The
- * lguest bus is 80% tedious boilerplate code. :*/
-#include <linux/init.h>
-#include <linux/bootmem.h>
-#include <linux/lguest_bus.h>
-#include <asm/io.h>
-#include <asm/paravirt.h>
-
-static ssize_t type_show(struct device *_dev,
- struct device_attribute *attr, char *buf)
-{
- struct lguest_device *dev = container_of(_dev,struct lguest_device,dev);
- return sprintf(buf, "%hu", lguest_devices[dev->index].type);
-}
-static ssize_t features_show(struct device *_dev,
- struct device_attribute *attr, char *buf)
-{
- struct lguest_device *dev = container_of(_dev,struct lguest_device,dev);
- return sprintf(buf, "%hx", lguest_devices[dev->index].features);
-}
-static ssize_t pfn_show(struct device *_dev,
- struct device_attribute *attr, char *buf)
-{
- struct lguest_device *dev = container_of(_dev,struct lguest_device,dev);
- return sprintf(buf, "%u", lguest_devices[dev->index].pfn);
-}
-static ssize_t status_show(struct device *_dev,
- struct device_attribute *attr, char *buf)
-{
- struct lguest_device *dev = container_of(_dev,struct lguest_device,dev);
- return sprintf(buf, "%hx", lguest_devices[dev->index].status);
-}
-static ssize_t status_store(struct device *_dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct lguest_device *dev = container_of(_dev,struct lguest_device,dev);
- if (sscanf(buf, "%hi", &lguest_devices[dev->index].status) != 1)
- return -EINVAL;
- return count;
-}
-static struct device_attribute lguest_dev_attrs[] = {
- __ATTR_RO(type),
- __ATTR_RO(features),
- __ATTR_RO(pfn),
- __ATTR(status, 0644, status_show, status_store),
- __ATTR_NULL
-};
-
-/*D:130 The generic bus infrastructure requires a function which says whether a
- * device matches a driver. For us, it is simple: "struct lguest_driver"
- * contains a "device_type" field which indicates what type of device it can
- * handle, so we just cast the args and compare: */
-static int lguest_dev_match(struct device *_dev, struct device_driver *_drv)
-{
- struct lguest_device *dev = container_of(_dev,struct lguest_device,dev);
- struct lguest_driver *drv = container_of(_drv,struct lguest_driver,drv);
-
- return (drv->device_type == lguest_devices[dev->index].type);
-}
-/*:*/
-
-struct lguest_bus {
- struct bus_type bus;
- struct device dev;
-};
-
-static struct lguest_bus lguest_bus = {
- .bus = {
- .name = "lguest",
- .match = lguest_dev_match,
- .dev_attrs = lguest_dev_attrs,
- },
- .dev = {
- .parent = NULL,
- .bus_id = "lguest",
- }
-};
-
-/*D:140 This is the callback which occurs once the bus infrastructure matches
- * up a device and driver, ie. in response to add_lguest_device() calling
- * device_register(), or register_lguest_driver() calling driver_register().
- *
- * At the moment it's always the latter: the devices are added first, since
- * scan_devices() is called from a "core_initcall", and the drivers themselves
- * called later as a normal "initcall". But it would work the other way too.
- *
- * So now we have the happy couple, we add the status bit to indicate that we
- * found a driver. If the driver truly loves the device, it will return
- * happiness from its probe function (ok, perhaps this wasn't my greatest
- * analogy), and we set the final "driver ok" bit so the Host sees it's all
- * green. */
-static int lguest_dev_probe(struct device *_dev)
-{
- int ret;
- struct lguest_device*dev = container_of(_dev,struct lguest_device,dev);
- struct lguest_driver*drv = container_of(dev->dev.driver,
- struct lguest_driver, drv);
-
- lguest_devices[dev->index].status |= LGUEST_DEVICE_S_DRIVER;
- ret = drv->probe(dev);
- if (ret == 0)
- lguest_devices[dev->index].status |= LGUEST_DEVICE_S_DRIVER_OK;
- return ret;
-}
-
-/* The last part of the bus infrastructure is the function lguest drivers use
- * to register themselves. Firstly, we do nothing if there's no lguest bus
- * (ie. this is not a Guest), otherwise we fill in the embedded generic "struct
- * driver" fields and call the generic driver_register(). */
-int register_lguest_driver(struct lguest_driver *drv)
-{
- if (!lguest_devices)
- return 0;
-
- drv->drv.bus = &lguest_bus.bus;
- drv->drv.name = drv->name;
- drv->drv.owner = drv->owner;
- drv->drv.probe = lguest_dev_probe;
-
- return driver_register(&drv->drv);
-}
-
-/* At the moment we build all the drivers into the kernel because they're so
- * simple: 8144 bytes for all three of them as I type this. And as the console
- * really needs to be built in, it's actually only 3527 bytes for the network
- * and block drivers.
- *
- * If they get complex it will make sense for them to be modularized, so we
- * need to explicitly export the symbol.
- *
- * I don't think non-GPL modules make sense, so it's a GPL-only export.
- */
-EXPORT_SYMBOL_GPL(register_lguest_driver);
-
-/*D:120 This is the core of the lguest bus: actually adding a new device.
- * It's a separate function because it's neater that way, and because an
- * earlier version of the code supported hotplug and unplug. They were removed
- * early on because they were never used.
- *
- * As Andrew Tridgell says, "Untested code is buggy code".
- *
- * It's worth reading this carefully: we start with an index into the array of
- * "struct lguest_device_desc"s indicating the device which is new: */
-static void add_lguest_device(unsigned int index)
-{
- struct lguest_device *new;
-
- /* Each "struct lguest_device_desc" has a "status" field, which the
- * Guest updates as the device is probed. In the worst case, the Host
- * can look at these bits to tell what part of device setup failed,
- * even if the console isn't available. */
- lguest_devices[index].status |= LGUEST_DEVICE_S_ACKNOWLEDGE;
- new = kmalloc(sizeof(struct lguest_device), GFP_KERNEL);
- if (!new) {
- printk(KERN_EMERG "Cannot allocate lguest device %u\n", index);
- lguest_devices[index].status |= LGUEST_DEVICE_S_FAILED;
- return;
- }
-
- /* The "struct lguest_device" setup is pretty straight-forward example
- * code. */
- new->index = index;
- new->private = NULL;
- memset(&new->dev, 0, sizeof(new->dev));
- new->dev.parent = &lguest_bus.dev;
- new->dev.bus = &lguest_bus.bus;
- sprintf(new->dev.bus_id, "%u", index);
-
- /* device_register() causes the bus infrastructure to look for a
- * matching driver. */
- if (device_register(&new->dev) != 0) {
- printk(KERN_EMERG "Cannot register lguest device %u\n", index);
- lguest_devices[index].status |= LGUEST_DEVICE_S_FAILED;
- kfree(new);
- }
-}
-
-/*D:110 scan_devices() simply iterates through the device array. The type 0
- * is reserved to mean "no device", and anything else means we have found a
- * device: add it. */
-static void scan_devices(void)
-{
- unsigned int i;
-
- for (i = 0; i < LGUEST_MAX_DEVICES; i++)
- if (lguest_devices[i].type)
- add_lguest_device(i);
-}
-
-/*D:100 Fairly early in boot, lguest_bus_init() is called to set up the lguest
- * bus. We check that we are a Guest by checking paravirt_ops.name: there are
- * other ways of checking, but this seems most obvious to me.
- *
- * So we can access the array of "struct lguest_device_desc"s easily, we map
- * that memory and store the pointer in the global "lguest_devices". Then we
- * register the bus with the core. Doing two registrations seems clunky to me,
- * but it seems to be the correct sysfs incantation.
- *
- * Finally we call scan_devices() which adds all the devices found in the
- * "struct lguest_device_desc" array. */
-static int __init lguest_bus_init(void)
-{
- if (strcmp(paravirt_ops.name, "lguest") != 0)
- return 0;
-
- /* Devices are in a single page above top of "normal" mem */
- lguest_devices = lguest_map(max_pfn<<PAGE_SHIFT, 1);
-
- if (bus_register(&lguest_bus.bus) != 0
- || device_register(&lguest_bus.dev) != 0)
- panic("lguest bus registration failed");
-
- scan_devices();
- return 0;
-}
-/* Do this after core stuff, before devices. */
-postcore_initcall(lguest_bus_init);
diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c
new file mode 100644
index 000000000000..66f38722253a
--- /dev/null
+++ b/drivers/lguest/lguest_device.c
@@ -0,0 +1,377 @@
+/*P:050 Lguest guests use a very simple method to describe devices. It's a
+ * series of device descriptors contained just above the top of normal
+ * memory.
+ *
+ * We use the standard "virtio" device infrastructure, which provides us with a
+ * console, a network and a block driver. Each one expects some configuration
+ * information and a "virtqueue" mechanism to send and receive data. :*/
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/lguest_launcher.h>
+#include <linux/virtio.h>
+#include <linux/virtio_config.h>
+#include <linux/interrupt.h>
+#include <linux/virtio_ring.h>
+#include <linux/err.h>
+#include <asm/io.h>
+#include <asm/paravirt.h>
+#include <asm/lguest_hcall.h>
+
+/* The pointer to our (page) of device descriptions. */
+static void *lguest_devices;
+
+/* Unique numbering for lguest devices. */
+static unsigned int dev_index;
+
+/* For Guests, device memory can be used as normal memory, so we cast away the
+ * __iomem to quieten sparse. */
+static inline void *lguest_map(unsigned long phys_addr, unsigned long pages)
+{
+ return (__force void *)ioremap(phys_addr, PAGE_SIZE*pages);
+}
+
+static inline void lguest_unmap(void *addr)
+{
+ iounmap((__force void __iomem *)addr);
+}
+
+/*D:100 Each lguest device is just a virtio device plus a pointer to its entry
+ * in the lguest_devices page. */
+struct lguest_device {
+ struct virtio_device vdev;
+
+ /* The entry in the lguest_devices page for this device. */
+ struct lguest_device_desc *desc;
+};
+
+/* Since the virtio infrastructure hands us a pointer to the virtio_device all
+ * the time, it helps to have a curt macro to get a pointer to the struct
+ * lguest_device it's enclosed in. */
+#define to_lgdev(vdev) container_of(vdev, struct lguest_device, vdev)
+
+/*D:130
+ * Device configurations
+ *
+ * The configuration information for a device consists of a series of fields.
+ * We don't really care what they are: the Launcher set them up, and the driver
+ * will look at them during setup.
+ *
+ * For us these fields come immediately after that device's descriptor in the
+ * lguest_devices page.
+ *
+ * Each field starts with a "type" byte, a "length" byte, then that number of
+ * bytes of configuration information. The device descriptor tells us the
+ * total configuration length so we know when we've reached the last field. */
+
+/* type + length bytes */
+#define FHDR_LEN 2
+
+/* This finds the first field of a given type for a device's configuration. */
+static void *lg_find(struct virtio_device *vdev, u8 type, unsigned int *len)
+{
+ struct lguest_device_desc *desc = to_lgdev(vdev)->desc;
+ int i;
+
+ for (i = 0; i < desc->config_len; i += FHDR_LEN + desc->config[i+1]) {
+ if (desc->config[i] == type) {
+ /* Mark it used, so Host can know we looked at it, and
+ * also so we won't find the same one twice. */
+ desc->config[i] |= 0x80;
+ /* Remember, the second byte is the length. */
+ *len = desc->config[i+1];
+ /* We return a pointer to the field header. */
+ return desc->config + i;
+ }
+ }
+
+ /* Not found: return NULL for failure. */
+ return NULL;
+}
+
+/* Once they've found a field, getting a copy of it is easy. */
+static void lg_get(struct virtio_device *vdev, void *token,
+ void *buf, unsigned len)
+{
+ /* Check they didn't ask for more than the length of the field! */
+ BUG_ON(len > ((u8 *)token)[1]);
+ memcpy(buf, token + FHDR_LEN, len);
+}
+
+/* Setting the contents is also trivial. */
+static void lg_set(struct virtio_device *vdev, void *token,
+ const void *buf, unsigned len)
+{
+ BUG_ON(len > ((u8 *)token)[1]);
+ memcpy(token + FHDR_LEN, buf, len);
+}
+
+/* The operations to get and set the status word just access the status field
+ * of the device descriptor. */
+static u8 lg_get_status(struct virtio_device *vdev)
+{
+ return to_lgdev(vdev)->desc->status;
+}
+
+static void lg_set_status(struct virtio_device *vdev, u8 status)
+{
+ to_lgdev(vdev)->desc->status = status;
+}
+
+/*
+ * Virtqueues
+ *
+ * The other piece of infrastructure virtio needs is a "virtqueue": a way of
+ * the Guest device registering buffers for the other side to read from or
+ * write into (ie. send and receive buffers). Each device can have multiple
+ * virtqueues: for example the console driver uses one queue for sending and
+ * another for receiving.
+ *
+ * Fortunately for us, a very fast shared-memory-plus-descriptors virtqueue
+ * already exists in virtio_ring.c. We just need to connect it up.
+ *
+ * We start with the information we need to keep about each virtqueue.
+ */
+
+/*D:140 This is the information we remember about each virtqueue. */
+struct lguest_vq_info
+{
+ /* A copy of the information contained in the device config. */
+ struct lguest_vqconfig config;
+
+ /* The address where we mapped the virtio ring, so we can unmap it. */
+ void *pages;
+};
+
+/* When the virtio_ring code wants to prod the Host, it calls us here and we
+ * make a hypercall. We hand the page number of the virtqueue so the Host
+ * knows which virtqueue we're talking about. */
+static void lg_notify(struct virtqueue *vq)
+{
+ /* We store our virtqueue information in the "priv" pointer of the
+ * virtqueue structure. */
+ struct lguest_vq_info *lvq = vq->priv;
+
+ hcall(LHCALL_NOTIFY, lvq->config.pfn << PAGE_SHIFT, 0, 0);
+}
+
+/* This routine finds the first virtqueue described in the configuration of
+ * this device and sets it up.
+ *
+ * This is kind of an ugly duckling. It'd be nicer to have a standard
+ * representation of a virtqueue in the configuration space, but it seems that
+ * everyone wants to do it differently. The KVM coders want the Guest to
+ * allocate its own pages and tell the Host where they are, but for lguest it's
+ * simpler for the Host to simply tell us where the pages are.
+ *
+ * So we provide devices with a "find virtqueue and set it up" function. */
+static struct virtqueue *lg_find_vq(struct virtio_device *vdev,
+ bool (*callback)(struct virtqueue *vq))
+{
+ struct lguest_vq_info *lvq;
+ struct virtqueue *vq;
+ unsigned int len;
+ void *token;
+ int err;
+
+ /* Look for a field of the correct type to mark a virtqueue. Note that
+ * if this succeeds, then the type will be changed so it won't be found
+ * again, and future lg_find_vq() calls will find the next
+ * virtqueue (if any). */
+ token = vdev->config->find(vdev, VIRTIO_CONFIG_F_VIRTQUEUE, &len);
+ if (!token)
+ return ERR_PTR(-ENOENT);
+
+ lvq = kmalloc(sizeof(*lvq), GFP_KERNEL);
+ if (!lvq)
+ return ERR_PTR(-ENOMEM);
+
+ /* Note: we could use a configuration space inside here, just like we
+ * do for the device. This would allow expansion in future, because
+ * our configuration system is designed to be expansible. But this is
+ * way easier. */
+ if (len != sizeof(lvq->config)) {
+ dev_err(&vdev->dev, "Unexpected virtio config len %u\n", len);
+ err = -EIO;
+ goto free_lvq;
+ }
+ /* Make a copy of the "struct lguest_vqconfig" field. We need a copy
+ * because the config space might not be aligned correctly. */
+ vdev->config->get(vdev, token, &lvq->config, sizeof(lvq->config));
+
+ /* Figure out how many pages the ring will take, and map that memory */
+ lvq->pages = lguest_map((unsigned long)lvq->config.pfn << PAGE_SHIFT,
+ DIV_ROUND_UP(vring_size(lvq->config.num,
+ PAGE_SIZE),
+ PAGE_SIZE));
+ if (!lvq->pages) {
+ err = -ENOMEM;
+ goto free_lvq;
+ }
+
+ /* OK, tell virtio_ring.c to set up a virtqueue now we know its size
+ * and we've got a pointer to its pages. */
+ vq = vring_new_virtqueue(lvq->config.num, vdev, lvq->pages,
+ lg_notify, callback);
+ if (!vq) {
+ err = -ENOMEM;
+ goto unmap;
+ }
+
+ /* Tell the interrupt for this virtqueue to go to the virtio_ring
+ * interrupt handler. */
+ /* FIXME: We used to have a flag for the Host to tell us we could use
+ * the interrupt as a source of randomness: it'd be nice to have that
+ * back.. */
+ err = request_irq(lvq->config.irq, vring_interrupt, IRQF_SHARED,
+ vdev->dev.bus_id, vq);
+ if (err)
+ goto destroy_vring;
+
+ /* Last of all we hook up our 'struct lguest_vq_info" to the
+ * virtqueue's priv pointer. */
+ vq->priv = lvq;
+ return vq;
+
+destroy_vring:
+ vring_del_virtqueue(vq);
+unmap:
+ lguest_unmap(lvq->pages);
+free_lvq:
+ kfree(lvq);
+ return ERR_PTR(err);
+}
+/*:*/
+
+/* Cleaning up a virtqueue is easy */
+static void lg_del_vq(struct virtqueue *vq)
+{
+ struct lguest_vq_info *lvq = vq->priv;
+
+ /* Tell virtio_ring.c to free the virtqueue. */
+ vring_del_virtqueue(vq);
+ /* Unmap the pages containing the ring. */
+ lguest_unmap(lvq->pages);
+ /* Free our own queue information. */
+ kfree(lvq);
+}
+
+/* The ops structure which hooks everything together. */
+static struct virtio_config_ops lguest_config_ops = {
+ .find = lg_find,
+ .get = lg_get,
+ .set = lg_set,
+ .get_status = lg_get_status,
+ .set_status = lg_set_status,
+ .find_vq = lg_find_vq,
+ .del_vq = lg_del_vq,
+};
+
+/* The root device for the lguest virtio devices. This makes them appear as
+ * /sys/devices/lguest/0,1,2 not /sys/devices/0,1,2. */
+static struct device lguest_root = {
+ .parent = NULL,
+ .bus_id = "lguest",
+};
+
+/*D:120 This is the core of the lguest bus: actually adding a new device.
+ * It's a separate function because it's neater that way, and because an
+ * earlier version of the code supported hotplug and unplug. They were removed
+ * early on because they were never used.
+ *
+ * As Andrew Tridgell says, "Untested code is buggy code".
+ *
+ * It's worth reading this carefully: we start with a pointer to the new device
+ * descriptor in the "lguest_devices" page. */
+static void add_lguest_device(struct lguest_device_desc *d)
+{
+ struct lguest_device *ldev;
+
+ /* Start with zeroed memory; Linux's device layer seems to count on
+ * it. */
+ ldev = kzalloc(sizeof(*ldev), GFP_KERNEL);
+ if (!ldev) {
+ printk(KERN_EMERG "Cannot allocate lguest dev %u\n",
+ dev_index++);
+ return;
+ }
+
+ /* This devices' parent is the lguest/ dir. */
+ ldev->vdev.dev.parent = &lguest_root;
+ /* We have a unique device index thanks to the dev_index counter. */
+ ldev->vdev.index = dev_index++;
+ /* The device type comes straight from the descriptor. There's also a
+ * device vendor field in the virtio_device struct, which we leave as
+ * 0. */
+ ldev->vdev.id.device = d->type;
+ /* We have a simple set of routines for querying the device's
+ * configuration information and setting its status. */
+ ldev->vdev.config = &lguest_config_ops;
+ /* And we remember the device's descriptor for lguest_config_ops. */
+ ldev->desc = d;
+
+ /* register_virtio_device() sets up the generic fields for the struct
+ * virtio_device and calls device_register(). This makes the bus
+ * infrastructure look for a matching driver. */
+ if (register_virtio_device(&ldev->vdev) != 0) {
+ printk(KERN_ERR "Failed to register lguest device %u\n",
+ ldev->vdev.index);
+ kfree(ldev);
+ }
+}
+
+/*D:110 scan_devices() simply iterates through the device page. The type 0 is
+ * reserved to mean "end of devices". */
+static void scan_devices(void)
+{
+ unsigned int i;
+ struct lguest_device_desc *d;
+
+ /* We start at the page beginning, and skip over each entry. */
+ for (i = 0; i < PAGE_SIZE; i += sizeof(*d) + d->config_len) {
+ d = lguest_devices + i;
+
+ /* Once we hit a zero, stop. */
+ if (d->type == 0)
+ break;
+
+ add_lguest_device(d);
+ }
+}
+
+/*D:105 Fairly early in boot, lguest_devices_init() is called to set up the
+ * lguest device infrastructure. We check that we are a Guest by checking
+ * pv_info.name: there are other ways of checking, but this seems most
+ * obvious to me.
+ *
+ * So we can access the "struct lguest_device_desc"s easily, we map that memory
+ * and store the pointer in the global "lguest_devices". Then we register a
+ * root device from which all our devices will hang (this seems to be the
+ * correct sysfs incantation).
+ *
+ * Finally we call scan_devices() which adds all the devices found in the
+ * lguest_devices page. */
+static int __init lguest_devices_init(void)
+{
+ if (strcmp(pv_info.name, "lguest") != 0)
+ return 0;
+
+ if (device_register(&lguest_root) != 0)
+ panic("Could not register lguest root");
+
+ /* Devices are in a single page above top of "normal" mem */
+ lguest_devices = lguest_map(max_pfn<<PAGE_SHIFT, 1);
+
+ scan_devices();
+ return 0;
+}
+/* We do this after core stuff, but before the drivers. */
+postcore_initcall(lguest_devices_init);
+
+/*D:150 At this point in the journey we used to now wade through the lguest
+ * devices themselves: net, block and console. Since they're all now virtio
+ * devices rather than lguest-specific, I've decided to ignore them. Mostly,
+ * they're kind of boring. But this does mean you'll never experience the
+ * thrill of reading the forbidden love scene buried deep in the block driver.
+ *
+ * "make Launcher" beckons, where we answer questions like "Where do Guests
+ * come from?", and "What do you do when someone asks for optimization?". */
diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c
index 80d1b58c7698..3b92a61ba8d2 100644
--- a/drivers/lguest/lguest_user.c
+++ b/drivers/lguest/lguest_user.c
@@ -1,83 +1,29 @@
/*P:200 This contains all the /dev/lguest code, whereby the userspace launcher
* controls and communicates with the Guest. For example, the first write will
- * tell us the memory size, pagetable, entry point and kernel address offset.
- * A read will run the Guest until a signal is pending (-EINTR), or the Guest
- * does a DMA out to the Launcher. Writes are also used to get a DMA buffer
- * registered by the Guest and to send the Guest an interrupt. :*/
+ * tell us the Guest's memory layout, pagetable, entry point and kernel address
+ * offset. A read will run the Guest until something happens, such as a signal
+ * or the Guest doing a NOTIFY out to the Launcher. :*/
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include "lg.h"
-/*L:030 setup_regs() doesn't really belong in this file, but it gives us an
- * early glimpse deeper into the Host so it's worth having here.
- *
- * Most of the Guest's registers are left alone: we used get_zeroed_page() to
- * allocate the structure, so they will be 0. */
-static void setup_regs(struct lguest_regs *regs, unsigned long start)
-{
- /* There are four "segment" registers which the Guest needs to boot:
- * The "code segment" register (cs) refers to the kernel code segment
- * __KERNEL_CS, and the "data", "extra" and "stack" segment registers
- * refer to the kernel data segment __KERNEL_DS.
- *
- * The privilege level is packed into the lower bits. The Guest runs
- * at privilege level 1 (GUEST_PL).*/
- regs->ds = regs->es = regs->ss = __KERNEL_DS|GUEST_PL;
- regs->cs = __KERNEL_CS|GUEST_PL;
-
- /* The "eflags" register contains miscellaneous flags. Bit 1 (0x002)
- * is supposed to always be "1". Bit 9 (0x200) controls whether
- * interrupts are enabled. We always leave interrupts enabled while
- * running the Guest. */
- regs->eflags = 0x202;
-
- /* The "Extended Instruction Pointer" register says where the Guest is
- * running. */
- regs->eip = start;
-
- /* %esi points to our boot information, at physical address 0, so don't
- * touch it. */
-}
-
-/*L:310 To send DMA into the Guest, the Launcher needs to be able to ask for a
- * DMA buffer. This is done by writing LHREQ_GETDMA and the key to
- * /dev/lguest. */
-static long user_get_dma(struct lguest *lg, const u32 __user *input)
-{
- unsigned long key, udma, irq;
-
- /* Fetch the key they wrote to us. */
- if (get_user(key, input) != 0)
- return -EFAULT;
- /* Look for a free Guest DMA buffer bound to that key. */
- udma = get_dma_buffer(lg, key, &irq);
- if (!udma)
- return -ENOENT;
-
- /* We need to tell the Launcher what interrupt the Guest expects after
- * the buffer is filled. We stash it in udma->used_len. */
- lgwrite_u32(lg, udma + offsetof(struct lguest_dma, used_len), irq);
-
- /* The (guest-physical) address of the DMA buffer is returned from
- * the write(). */
- return udma;
-}
-
-/*L:315 To force the Guest to stop running and return to the Launcher, the
- * Waker sets writes LHREQ_BREAK and the value "1" to /dev/lguest. The
- * Launcher then writes LHREQ_BREAK and "0" to release the Waker. */
-static int break_guest_out(struct lguest *lg, const u32 __user *input)
+/*L:055 When something happens, the Waker process needs a way to stop the
+ * kernel running the Guest and return to the Launcher. So the Waker writes
+ * LHREQ_BREAK and the value "1" to /dev/lguest to do this. Once the Launcher
+ * has done whatever needs attention, it writes LHREQ_BREAK and "0" to release
+ * the Waker. */
+static int break_guest_out(struct lguest *lg, const unsigned long __user *input)
{
unsigned long on;
- /* Fetch whether they're turning break on or off.. */
+ /* Fetch whether they're turning break on or off. */
if (get_user(on, input) != 0)
return -EFAULT;
if (on) {
lg->break_out = 1;
- /* Pop it out (may be running on different CPU) */
+ /* Pop it out of the Guest (may be running on different CPU) */
wake_up_process(lg->tsk);
/* Wait for them to reset it */
return wait_event_interruptible(lg->break_wq, !lg->break_out);
@@ -90,9 +36,9 @@ static int break_guest_out(struct lguest *lg, const u32 __user *input)
/*L:050 Sending an interrupt is done by writing LHREQ_IRQ and an interrupt
* number to /dev/lguest. */
-static int user_send_irq(struct lguest *lg, const u32 __user *input)
+static int user_send_irq(struct lguest *lg, const unsigned long __user *input)
{
- u32 irq;
+ unsigned long irq;
if (get_user(irq, input) != 0)
return -EFAULT;
@@ -114,7 +60,7 @@ static ssize_t read(struct file *file, char __user *user, size_t size,loff_t*o)
if (!lg)
return -EINVAL;
- /* If you're not the task which owns the guest, go away. */
+ /* If you're not the task which owns the Guest, go away. */
if (current != lg->tsk)
return -EPERM;
@@ -133,43 +79,39 @@ static ssize_t read(struct file *file, char __user *user, size_t size,loff_t*o)
return len;
}
- /* If we returned from read() last time because the Guest sent DMA,
+ /* If we returned from read() last time because the Guest notified,
* clear the flag. */
- if (lg->dma_is_pending)
- lg->dma_is_pending = 0;
+ if (lg->pending_notify)
+ lg->pending_notify = 0;
/* Run the Guest until something interesting happens. */
return run_guest(lg, (unsigned long __user *)user);
}
-/*L:020 The initialization write supplies 4 32-bit values (in addition to the
- * 32-bit LHREQ_INITIALIZE value). These are:
+/*L:020 The initialization write supplies 4 pointer sized (32 or 64 bit)
+ * values (in addition to the LHREQ_INITIALIZE value). These are:
+ *
+ * base: The start of the Guest-physical memory inside the Launcher memory.
*
* pfnlimit: The highest (Guest-physical) page number the Guest should be
- * allowed to access. The Launcher has to live in Guest memory, so it sets
- * this to ensure the Guest can't reach it.
+ * allowed to access. The Guest memory lives inside the Launcher, so it sets
+ * this to ensure the Guest can only reach its own memory.
*
* pgdir: The (Guest-physical) address of the top of the initial Guest
* pagetables (which are set up by the Launcher).
*
* start: The first instruction to execute ("eip" in x86-speak).
- *
- * page_offset: The PAGE_OFFSET constant in the Guest kernel. We should
- * probably wean the code off this, but it's a very useful constant! Any
- * address above this is within the Guest kernel, and any kernel address can
- * quickly converted from physical to virtual by adding PAGE_OFFSET. It's
- * 0xC0000000 (3G) by default, but it's configurable at kernel build time.
*/
-static int initialize(struct file *file, const u32 __user *input)
+static int initialize(struct file *file, const unsigned long __user *input)
{
/* "struct lguest" contains everything we (the Host) know about a
* Guest. */
struct lguest *lg;
- int err, i;
- u32 args[4];
+ int err;
+ unsigned long args[4];
- /* We grab the Big Lguest lock, which protects the global array
- * "lguests" and multiple simultaneous initializations. */
+ /* We grab the Big Lguest lock, which protects against multiple
+ * simultaneous initializations. */
mutex_lock(&lguest_lock);
/* You can't initialize twice! Close the device and start again... */
if (file->private_data) {
@@ -182,20 +124,15 @@ static int initialize(struct file *file, const u32 __user *input)
goto unlock;
}
- /* Find an unused guest. */
- i = find_free_guest();
- if (i < 0) {
- err = -ENOSPC;
+ lg = kzalloc(sizeof(*lg), GFP_KERNEL);
+ if (!lg) {
+ err = -ENOMEM;
goto unlock;
}
- /* OK, we have an index into the "lguest" array: "lg" is a convenient
- * pointer. */
- lg = &lguests[i];
/* Populate the easy fields of our "struct lguest" */
- lg->guestid = i;
- lg->pfn_limit = args[0];
- lg->page_offset = args[3];
+ lg->mem_base = (void __user *)(long)args[0];
+ lg->pfn_limit = args[1];
/* We need a complete page for the Guest registers: they are accessible
* to the Guest and we can only grant it access to whole pages. */
@@ -210,17 +147,13 @@ static int initialize(struct file *file, const u32 __user *input)
/* Initialize the Guest's shadow page tables, using the toplevel
* address the Launcher gave us. This allocates memory, so can
* fail. */
- err = init_guest_pagetable(lg, args[1]);
+ err = init_guest_pagetable(lg, args[2]);
if (err)
goto free_regs;
/* Now we initialize the Guest's registers, handing it the start
* address. */
- setup_regs(lg->regs, args[2]);
-
- /* There are a couple of GDT entries the Guest expects when first
- * booting. */
- setup_guest_gdt(lg);
+ lguest_arch_setup_regs(lg, args[3]);
/* The timer for lguest's clock needs initialization. */
init_clockdev(lg);
@@ -251,27 +184,28 @@ static int initialize(struct file *file, const u32 __user *input)
free_regs:
free_page(lg->regs_page);
release_guest:
- memset(lg, 0, sizeof(*lg));
+ kfree(lg);
unlock:
mutex_unlock(&lguest_lock);
return err;
}
/*L:010 The first operation the Launcher does must be a write. All writes
- * start with a 32 bit number: for the first write this must be
+ * start with an unsigned long number: for the first write this must be
* LHREQ_INITIALIZE to set up the Guest. After that the Launcher can use
- * writes of other values to get DMA buffers and send interrupts. */
-static ssize_t write(struct file *file, const char __user *input,
+ * writes of other values to send interrupts. */
+static ssize_t write(struct file *file, const char __user *in,
size_t size, loff_t *off)
{
/* Once the guest is initialized, we hold the "struct lguest" in the
* file private data. */
struct lguest *lg = file->private_data;
- u32 req;
+ const unsigned long __user *input = (const unsigned long __user *)in;
+ unsigned long req;
if (get_user(req, input) != 0)
return -EFAULT;
- input += sizeof(req);
+ input++;
/* If you haven't initialized, you must do that first. */
if (req != LHREQ_INITIALIZE && !lg)
@@ -287,13 +221,11 @@ static ssize_t write(struct file *file, const char __user *input,
switch (req) {
case LHREQ_INITIALIZE:
- return initialize(file, (const u32 __user *)input);
- case LHREQ_GETDMA:
- return user_get_dma(lg, (const u32 __user *)input);
+ return initialize(file, input);
case LHREQ_IRQ:
- return user_send_irq(lg, (const u32 __user *)input);
+ return user_send_irq(lg, input);
case LHREQ_BREAK:
- return break_guest_out(lg, (const u32 __user *)input);
+ return break_guest_out(lg, input);
default:
return -EINVAL;
}
@@ -319,8 +251,6 @@ static int close(struct inode *inode, struct file *file)
mutex_lock(&lguest_lock);
/* Cancels the hrtimer set via LHCALL_SET_CLOCKEVENT. */
hrtimer_cancel(&lg->hrt);
- /* Free any DMA buffers the Guest had bound. */
- release_all_dma(lg);
/* Free up the shadow page tables for the Guest. */
free_guest_pagetable(lg);
/* Now all the memory cleanups are done, it's safe to release the
@@ -347,8 +277,7 @@ static int close(struct inode *inode, struct file *file)
* The Launcher is the Host userspace program which sets up, runs and services
* the Guest. In fact, many comments in the Drivers which refer to "the Host"
* doing things are inaccurate: the Launcher does all the device handling for
- * the Guest. The Guest can't tell what's done by the the Launcher and what by
- * the Host.
+ * the Guest, but the Guest can't know that.
*
* Just to confuse you: to the Host kernel, the Launcher *is* the Guest and we
* shall see more of that later.
diff --git a/drivers/lguest/page_tables.c b/drivers/lguest/page_tables.c
index b7a924ace684..fffabb327157 100644
--- a/drivers/lguest/page_tables.c
+++ b/drivers/lguest/page_tables.c
@@ -13,6 +13,7 @@
#include <linux/random.h>
#include <linux/percpu.h>
#include <asm/tlbflush.h>
+#include <asm/uaccess.h>
#include "lg.h"
/*M:008 We hold reference to pages, which prevents them from being swapped.
@@ -25,7 +26,8 @@
*
* We use two-level page tables for the Guest. If you're not entirely
* comfortable with virtual addresses, physical addresses and page tables then
- * I recommend you review lguest.c's "Page Table Handling" (with diagrams!).
+ * I recommend you review arch/x86/lguest/boot.c's "Page Table Handling" (with
+ * diagrams!).
*
* The Guest keeps page tables, but we maintain the actual ones here: these are
* called "shadow" page tables. Which is a very Guest-centric name: these are
@@ -35,53 +37,40 @@
*
* Anyway, this is the most complicated part of the Host code. There are seven
* parts to this:
- * (i) Setting up a page table entry for the Guest when it faults,
- * (ii) Setting up the page table entry for the Guest stack,
- * (iii) Setting up a page table entry when the Guest tells us it has changed,
+ * (i) Looking up a page table entry when the Guest faults,
+ * (ii) Making sure the Guest stack is mapped,
+ * (iii) Setting up a page table entry when the Guest tells us one has changed,
* (iv) Switching page tables,
- * (v) Flushing (thowing away) page tables,
+ * (v) Flushing (throwing away) page tables,
* (vi) Mapping the Switcher when the Guest is about to run,
* (vii) Setting up the page tables initially.
:*/
-/* Pages a 4k long, and each page table entry is 4 bytes long, giving us 1024
- * (or 2^10) entries per page. */
-#define PTES_PER_PAGE_SHIFT 10
-#define PTES_PER_PAGE (1 << PTES_PER_PAGE_SHIFT)
/* 1024 entries in a page table page maps 1024 pages: 4MB. The Switcher is
* conveniently placed at the top 4MB, so it uses a separate, complete PTE
* page. */
-#define SWITCHER_PGD_INDEX (PTES_PER_PAGE - 1)
+#define SWITCHER_PGD_INDEX (PTRS_PER_PGD - 1)
/* We actually need a separate PTE page for each CPU. Remember that after the
* Switcher code itself comes two pages for each CPU, and we don't want this
* CPU's guest to see the pages of any other CPU. */
-static DEFINE_PER_CPU(spte_t *, switcher_pte_pages);
+static DEFINE_PER_CPU(pte_t *, switcher_pte_pages);
#define switcher_pte_page(cpu) per_cpu(switcher_pte_pages, cpu)
-/*H:320 With our shadow and Guest types established, we need to deal with
- * them: the page table code is curly enough to need helper functions to keep
- * it clear and clean.
+/*H:320 The page table code is curly enough to need helper functions to keep it
+ * clear and clean.
*
- * The first helper takes a virtual address, and says which entry in the top
- * level page table deals with that address. Since each top level entry deals
- * with 4M, this effectively divides by 4M. */
-static unsigned vaddr_to_pgd_index(unsigned long vaddr)
-{
- return vaddr >> (PAGE_SHIFT + PTES_PER_PAGE_SHIFT);
-}
-
-/* There are two functions which return pointers to the shadow (aka "real")
+ * There are two functions which return pointers to the shadow (aka "real")
* page tables.
*
* spgd_addr() takes the virtual address and returns a pointer to the top-level
- * page directory entry for that address. Since we keep track of several page
- * tables, the "i" argument tells us which one we're interested in (it's
+ * page directory entry (PGD) for that address. Since we keep track of several
+ * page tables, the "i" argument tells us which one we're interested in (it's
* usually the current one). */
-static spgd_t *spgd_addr(struct lguest *lg, u32 i, unsigned long vaddr)
+static pgd_t *spgd_addr(struct lguest *lg, u32 i, unsigned long vaddr)
{
- unsigned int index = vaddr_to_pgd_index(vaddr);
+ unsigned int index = pgd_index(vaddr);
/* We kill any Guest trying to touch the Switcher addresses. */
if (index >= SWITCHER_PGD_INDEX) {
@@ -92,31 +81,31 @@ static spgd_t *spgd_addr(struct lguest *lg, u32 i, unsigned long vaddr)
return &lg->pgdirs[i].pgdir[index];
}
-/* This routine then takes the PGD entry given above, which contains the
- * address of the PTE page. It then returns a pointer to the PTE entry for the
- * given address. */
-static spte_t *spte_addr(struct lguest *lg, spgd_t spgd, unsigned long vaddr)
+/* This routine then takes the page directory entry returned above, which
+ * contains the address of the page table entry (PTE) page. It then returns a
+ * pointer to the PTE entry for the given address. */
+static pte_t *spte_addr(struct lguest *lg, pgd_t spgd, unsigned long vaddr)
{
- spte_t *page = __va(spgd.pfn << PAGE_SHIFT);
+ pte_t *page = __va(pgd_pfn(spgd) << PAGE_SHIFT);
/* You should never call this if the PGD entry wasn't valid */
- BUG_ON(!(spgd.flags & _PAGE_PRESENT));
- return &page[(vaddr >> PAGE_SHIFT) % PTES_PER_PAGE];
+ BUG_ON(!(pgd_flags(spgd) & _PAGE_PRESENT));
+ return &page[(vaddr >> PAGE_SHIFT) % PTRS_PER_PTE];
}
/* These two functions just like the above two, except they access the Guest
* page tables. Hence they return a Guest address. */
static unsigned long gpgd_addr(struct lguest *lg, unsigned long vaddr)
{
- unsigned int index = vaddr >> (PAGE_SHIFT + PTES_PER_PAGE_SHIFT);
- return lg->pgdirs[lg->pgdidx].cr3 + index * sizeof(gpgd_t);
+ unsigned int index = vaddr >> (PGDIR_SHIFT);
+ return lg->pgdirs[lg->pgdidx].gpgdir + index * sizeof(pgd_t);
}
static unsigned long gpte_addr(struct lguest *lg,
- gpgd_t gpgd, unsigned long vaddr)
+ pgd_t gpgd, unsigned long vaddr)
{
- unsigned long gpage = gpgd.pfn << PAGE_SHIFT;
- BUG_ON(!(gpgd.flags & _PAGE_PRESENT));
- return gpage + ((vaddr>>PAGE_SHIFT) % PTES_PER_PAGE) * sizeof(gpte_t);
+ unsigned long gpage = pgd_pfn(gpgd) << PAGE_SHIFT;
+ BUG_ON(!(pgd_flags(gpgd) & _PAGE_PRESENT));
+ return gpage + ((vaddr>>PAGE_SHIFT) % PTRS_PER_PTE) * sizeof(pte_t);
}
/*H:350 This routine takes a page number given by the Guest and converts it to
@@ -149,58 +138,60 @@ static unsigned long get_pfn(unsigned long virtpfn, int write)
* entry can be a little tricky. The flags are (almost) the same, but the
* Guest PTE contains a virtual page number: the CPU needs the real page
* number. */
-static spte_t gpte_to_spte(struct lguest *lg, gpte_t gpte, int write)
+static pte_t gpte_to_spte(struct lguest *lg, pte_t gpte, int write)
{
- spte_t spte;
- unsigned long pfn;
+ unsigned long pfn, base, flags;
/* The Guest sets the global flag, because it thinks that it is using
* PGE. We only told it to use PGE so it would tell us whether it was
* flushing a kernel mapping or a userspace mapping. We don't actually
* use the global bit, so throw it away. */
- spte.flags = (gpte.flags & ~_PAGE_GLOBAL);
+ flags = (pte_flags(gpte) & ~_PAGE_GLOBAL);
+
+ /* The Guest's pages are offset inside the Launcher. */
+ base = (unsigned long)lg->mem_base / PAGE_SIZE;
/* We need a temporary "unsigned long" variable to hold the answer from
* get_pfn(), because it returns 0xFFFFFFFF on failure, which wouldn't
* fit in spte.pfn. get_pfn() finds the real physical number of the
* page, given the virtual number. */
- pfn = get_pfn(gpte.pfn, write);
+ pfn = get_pfn(base + pte_pfn(gpte), write);
if (pfn == -1UL) {
- kill_guest(lg, "failed to get page %u", gpte.pfn);
+ kill_guest(lg, "failed to get page %lu", pte_pfn(gpte));
/* When we destroy the Guest, we'll go through the shadow page
* tables and release_pte() them. Make sure we don't think
* this one is valid! */
- spte.flags = 0;
+ flags = 0;
}
- /* Now we assign the page number, and our shadow PTE is complete. */
- spte.pfn = pfn;
- return spte;
+ /* Now we assemble our shadow PTE from the page number and flags. */
+ return pfn_pte(pfn, __pgprot(flags));
}
/*H:460 And to complete the chain, release_pte() looks like this: */
-static void release_pte(spte_t pte)
+static void release_pte(pte_t pte)
{
/* Remember that get_user_pages() took a reference to the page, in
* get_pfn()? We have to put it back now. */
- if (pte.flags & _PAGE_PRESENT)
- put_page(pfn_to_page(pte.pfn));
+ if (pte_flags(pte) & _PAGE_PRESENT)
+ put_page(pfn_to_page(pte_pfn(pte)));
}
/*:*/
-static void check_gpte(struct lguest *lg, gpte_t gpte)
+static void check_gpte(struct lguest *lg, pte_t gpte)
{
- if ((gpte.flags & (_PAGE_PWT|_PAGE_PSE)) || gpte.pfn >= lg->pfn_limit)
+ if ((pte_flags(gpte) & (_PAGE_PWT|_PAGE_PSE))
+ || pte_pfn(gpte) >= lg->pfn_limit)
kill_guest(lg, "bad page table entry");
}
-static void check_gpgd(struct lguest *lg, gpgd_t gpgd)
+static void check_gpgd(struct lguest *lg, pgd_t gpgd)
{
- if ((gpgd.flags & ~_PAGE_TABLE) || gpgd.pfn >= lg->pfn_limit)
+ if ((pgd_flags(gpgd) & ~_PAGE_TABLE) || pgd_pfn(gpgd) >= lg->pfn_limit)
kill_guest(lg, "bad page directory entry");
}
/*H:330
- * (i) Setting up a page table entry for the Guest when it faults
+ * (i) Looking up a page table entry when the Guest faults.
*
* We saw this call in run_guest(): when we see a page fault in the Guest, we
* come here. That's because we only set up the shadow page tables lazily as
@@ -208,24 +199,24 @@ static void check_gpgd(struct lguest *lg, gpgd_t gpgd)
* and return to the Guest without it knowing.
*
* If we fixed up the fault (ie. we mapped the address), this routine returns
- * true. */
+ * true. Otherwise, it was a real fault and we need to tell the Guest. */
int demand_page(struct lguest *lg, unsigned long vaddr, int errcode)
{
- gpgd_t gpgd;
- spgd_t *spgd;
+ pgd_t gpgd;
+ pgd_t *spgd;
unsigned long gpte_ptr;
- gpte_t gpte;
- spte_t *spte;
+ pte_t gpte;
+ pte_t *spte;
/* First step: get the top-level Guest page table entry. */
- gpgd = mkgpgd(lgread_u32(lg, gpgd_addr(lg, vaddr)));
+ gpgd = lgread(lg, gpgd_addr(lg, vaddr), pgd_t);
/* Toplevel not present? We can't map it in. */
- if (!(gpgd.flags & _PAGE_PRESENT))
+ if (!(pgd_flags(gpgd) & _PAGE_PRESENT))
return 0;
/* Now look at the matching shadow entry. */
spgd = spgd_addr(lg, lg->pgdidx, vaddr);
- if (!(spgd->flags & _PAGE_PRESENT)) {
+ if (!(pgd_flags(*spgd) & _PAGE_PRESENT)) {
/* No shadow entry: allocate a new shadow PTE page. */
unsigned long ptepage = get_zeroed_page(GFP_KERNEL);
/* This is not really the Guest's fault, but killing it is
@@ -238,34 +229,35 @@ int demand_page(struct lguest *lg, unsigned long vaddr, int errcode)
check_gpgd(lg, gpgd);
/* And we copy the flags to the shadow PGD entry. The page
* number in the shadow PGD is the page we just allocated. */
- spgd->raw.val = (__pa(ptepage) | gpgd.flags);
+ *spgd = __pgd(__pa(ptepage) | pgd_flags(gpgd));
}
/* OK, now we look at the lower level in the Guest page table: keep its
* address, because we might update it later. */
gpte_ptr = gpte_addr(lg, gpgd, vaddr);
- gpte = mkgpte(lgread_u32(lg, gpte_ptr));
+ gpte = lgread(lg, gpte_ptr, pte_t);
/* If this page isn't in the Guest page tables, we can't page it in. */
- if (!(gpte.flags & _PAGE_PRESENT))
+ if (!(pte_flags(gpte) & _PAGE_PRESENT))
return 0;
/* Check they're not trying to write to a page the Guest wants
* read-only (bit 2 of errcode == write). */
- if ((errcode & 2) && !(gpte.flags & _PAGE_RW))
+ if ((errcode & 2) && !(pte_flags(gpte) & _PAGE_RW))
return 0;
- /* User access to a kernel page? (bit 3 == user access) */
- if ((errcode & 4) && !(gpte.flags & _PAGE_USER))
+ /* User access to a kernel-only page? (bit 3 == user access) */
+ if ((errcode & 4) && !(pte_flags(gpte) & _PAGE_USER))
return 0;
/* Check that the Guest PTE flags are OK, and the page number is below
* the pfn_limit (ie. not mapping the Launcher binary). */
check_gpte(lg, gpte);
+
/* Add the _PAGE_ACCESSED and (for a write) _PAGE_DIRTY flag */
- gpte.flags |= _PAGE_ACCESSED;
+ gpte = pte_mkyoung(gpte);
if (errcode & 2)
- gpte.flags |= _PAGE_DIRTY;
+ gpte = pte_mkdirty(gpte);
/* Get the pointer to the shadow PTE entry we're going to set. */
spte = spte_addr(lg, *spgd, vaddr);
@@ -275,47 +267,50 @@ int demand_page(struct lguest *lg, unsigned long vaddr, int errcode)
/* If this is a write, we insist that the Guest page is writable (the
* final arg to gpte_to_spte()). */
- if (gpte.flags & _PAGE_DIRTY)
+ if (pte_dirty(gpte))
*spte = gpte_to_spte(lg, gpte, 1);
- else {
+ else
/* If this is a read, don't set the "writable" bit in the page
* table entry, even if the Guest says it's writable. That way
- * we come back here when a write does actually ocur, so we can
- * update the Guest's _PAGE_DIRTY flag. */
- gpte_t ro_gpte = gpte;
- ro_gpte.flags &= ~_PAGE_RW;
- *spte = gpte_to_spte(lg, ro_gpte, 0);
- }
+ * we will come back here when a write does actually occur, so
+ * we can update the Guest's _PAGE_DIRTY flag. */
+ *spte = gpte_to_spte(lg, pte_wrprotect(gpte), 0);
/* Finally, we write the Guest PTE entry back: we've set the
* _PAGE_ACCESSED and maybe the _PAGE_DIRTY flags. */
- lgwrite_u32(lg, gpte_ptr, gpte.raw.val);
+ lgwrite(lg, gpte_ptr, pte_t, gpte);
- /* We succeeded in mapping the page! */
+ /* The fault is fixed, the page table is populated, the mapping
+ * manipulated, the result returned and the code complete. A small
+ * delay and a trace of alliteration are the only indications the Guest
+ * has that a page fault occurred at all. */
return 1;
}
-/*H:360 (ii) Setting up the page table entry for the Guest stack.
+/*H:360
+ * (ii) Making sure the Guest stack is mapped.
*
- * Remember pin_stack_pages() which makes sure the stack is mapped? It could
- * simply call demand_page(), but as we've seen that logic is quite long, and
- * usually the stack pages are already mapped anyway, so it's not required.
+ * Remember that direct traps into the Guest need a mapped Guest kernel stack.
+ * pin_stack_pages() calls us here: we could simply call demand_page(), but as
+ * we've seen that logic is quite long, and usually the stack pages are already
+ * mapped, so it's overkill.
*
* This is a quick version which answers the question: is this virtual address
* mapped by the shadow page tables, and is it writable? */
static int page_writable(struct lguest *lg, unsigned long vaddr)
{
- spgd_t *spgd;
+ pgd_t *spgd;
unsigned long flags;
- /* Look at the top level entry: is it present? */
+ /* Look at the current top level entry: is it present? */
spgd = spgd_addr(lg, lg->pgdidx, vaddr);
- if (!(spgd->flags & _PAGE_PRESENT))
+ if (!(pgd_flags(*spgd) & _PAGE_PRESENT))
return 0;
/* Check the flags on the pte entry itself: it must be present and
* writable. */
- flags = spte_addr(lg, *spgd, vaddr)->flags;
+ flags = pte_flags(*(spte_addr(lg, *spgd, vaddr)));
+
return (flags & (_PAGE_PRESENT|_PAGE_RW)) == (_PAGE_PRESENT|_PAGE_RW);
}
@@ -329,39 +324,40 @@ void pin_page(struct lguest *lg, unsigned long vaddr)
}
/*H:450 If we chase down the release_pgd() code, it looks like this: */
-static void release_pgd(struct lguest *lg, spgd_t *spgd)
+static void release_pgd(struct lguest *lg, pgd_t *spgd)
{
/* If the entry's not present, there's nothing to release. */
- if (spgd->flags & _PAGE_PRESENT) {
+ if (pgd_flags(*spgd) & _PAGE_PRESENT) {
unsigned int i;
/* Converting the pfn to find the actual PTE page is easy: turn
* the page number into a physical address, then convert to a
* virtual address (easy for kernel pages like this one). */
- spte_t *ptepage = __va(spgd->pfn << PAGE_SHIFT);
+ pte_t *ptepage = __va(pgd_pfn(*spgd) << PAGE_SHIFT);
/* For each entry in the page, we might need to release it. */
- for (i = 0; i < PTES_PER_PAGE; i++)
+ for (i = 0; i < PTRS_PER_PTE; i++)
release_pte(ptepage[i]);
/* Now we can free the page of PTEs */
free_page((long)ptepage);
- /* And zero out the PGD entry we we never release it twice. */
- spgd->raw.val = 0;
+ /* And zero out the PGD entry so we never release it twice. */
+ *spgd = __pgd(0);
}
}
-/*H:440 (v) Flushing (thowing away) page tables,
- *
- * We saw flush_user_mappings() called when we re-used a top-level pgdir page.
- * It simply releases every PTE page from 0 up to the kernel address. */
+/*H:445 We saw flush_user_mappings() twice: once from the flush_user_mappings()
+ * hypercall and once in new_pgdir() when we re-used a top-level pgdir page.
+ * It simply releases every PTE page from 0 up to the Guest's kernel address. */
static void flush_user_mappings(struct lguest *lg, int idx)
{
unsigned int i;
/* Release every pgd entry up to the kernel's address. */
- for (i = 0; i < vaddr_to_pgd_index(lg->page_offset); i++)
+ for (i = 0; i < pgd_index(lg->kernel_address); i++)
release_pgd(lg, lg->pgdirs[idx].pgdir + i);
}
-/* The Guest also has a hypercall to do this manually: it's used when a large
- * number of mappings have been changed. */
+/*H:440 (v) Flushing (throwing away) page tables,
+ *
+ * The Guest has a hypercall to throw away the page tables: it's used when a
+ * large number of mappings have been changed. */
void guest_pagetable_flush_user(struct lguest *lg)
{
/* Drop the userspace part of the current page table. */
@@ -369,6 +365,25 @@ void guest_pagetable_flush_user(struct lguest *lg)
}
/*:*/
+/* We walk down the guest page tables to get a guest-physical address */
+unsigned long guest_pa(struct lguest *lg, unsigned long vaddr)
+{
+ pgd_t gpgd;
+ pte_t gpte;
+
+ /* First step: get the top-level Guest page table entry. */
+ gpgd = lgread(lg, gpgd_addr(lg, vaddr), pgd_t);
+ /* Toplevel not present? We can't map it in. */
+ if (!(pgd_flags(gpgd) & _PAGE_PRESENT))
+ kill_guest(lg, "Bad address %#lx", vaddr);
+
+ gpte = lgread(lg, gpte_addr(lg, gpgd, vaddr), pte_t);
+ if (!(pte_flags(gpte) & _PAGE_PRESENT))
+ kill_guest(lg, "Bad address %#lx", vaddr);
+
+ return pte_pfn(gpte) * PAGE_SIZE | (vaddr & ~PAGE_MASK);
+}
+
/* We keep several page tables. This is a simple routine to find the page
* table (if any) corresponding to this top-level address the Guest has given
* us. */
@@ -376,7 +391,7 @@ static unsigned int find_pgdir(struct lguest *lg, unsigned long pgtable)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(lg->pgdirs); i++)
- if (lg->pgdirs[i].cr3 == pgtable)
+ if (lg->pgdirs[i].gpgdir == pgtable)
break;
return i;
}
@@ -385,7 +400,7 @@ static unsigned int find_pgdir(struct lguest *lg, unsigned long pgtable)
* allocate a new one (and so the kernel parts are not there), we set
* blank_pgdir. */
static unsigned int new_pgdir(struct lguest *lg,
- unsigned long cr3,
+ unsigned long gpgdir,
int *blank_pgdir)
{
unsigned int next;
@@ -395,7 +410,7 @@ static unsigned int new_pgdir(struct lguest *lg,
next = random32() % ARRAY_SIZE(lg->pgdirs);
/* If it's never been allocated at all before, try now. */
if (!lg->pgdirs[next].pgdir) {
- lg->pgdirs[next].pgdir = (spgd_t *)get_zeroed_page(GFP_KERNEL);
+ lg->pgdirs[next].pgdir = (pgd_t *)get_zeroed_page(GFP_KERNEL);
/* If the allocation fails, just keep using the one we have */
if (!lg->pgdirs[next].pgdir)
next = lg->pgdidx;
@@ -405,7 +420,7 @@ static unsigned int new_pgdir(struct lguest *lg,
*blank_pgdir = 1;
}
/* Record which Guest toplevel this shadows. */
- lg->pgdirs[next].cr3 = cr3;
+ lg->pgdirs[next].gpgdir = gpgdir;
/* Release all the non-kernel mappings. */
flush_user_mappings(lg, next);
@@ -414,8 +429,9 @@ static unsigned int new_pgdir(struct lguest *lg,
/*H:430 (iv) Switching page tables
*
- * This is what happens when the Guest changes page tables (ie. changes the
- * top-level pgdir). This happens on almost every context switch. */
+ * Now we've seen all the page table setting and manipulation, let's see what
+ * what happens when the Guest changes page tables (ie. changes the top-level
+ * pgdir). This occurs on almost every context switch. */
void guest_new_pagetable(struct lguest *lg, unsigned long pgtable)
{
int newpgdir, repin = 0;
@@ -434,7 +450,8 @@ void guest_new_pagetable(struct lguest *lg, unsigned long pgtable)
}
/*H:470 Finally, a routine which throws away everything: all PGD entries in all
- * the shadow page tables. This is used when we destroy the Guest. */
+ * the shadow page tables, including the Guest's kernel mappings. This is used
+ * when we destroy the Guest. */
static void release_all_pagetables(struct lguest *lg)
{
unsigned int i, j;
@@ -449,13 +466,22 @@ static void release_all_pagetables(struct lguest *lg)
/* We also throw away everything when a Guest tells us it's changed a kernel
* mapping. Since kernel mappings are in every page table, it's easiest to
- * throw them all away. This is amazingly slow, but thankfully rare. */
+ * throw them all away. This traps the Guest in amber for a while as
+ * everything faults back in, but it's rare. */
void guest_pagetable_clear_all(struct lguest *lg)
{
release_all_pagetables(lg);
/* We need the Guest kernel stack mapped again. */
pin_stack_pages(lg);
}
+/*:*/
+/*M:009 Since we throw away all mappings when a kernel mapping changes, our
+ * performance sucks for guests using highmem. In fact, a guest with
+ * PAGE_OFFSET 0xc0000000 (the default) and more than about 700MB of RAM is
+ * usually slower than a Guest with less memory.
+ *
+ * This, of course, cannot be fixed. It would take some kind of... well, I
+ * don't know, but the term "puissant code-fu" comes to mind. :*/
/*H:420 This is the routine which actually sets the page table entry for then
* "idx"'th shadow page table.
@@ -472,26 +498,28 @@ void guest_pagetable_clear_all(struct lguest *lg)
* they set _PAGE_DIRTY then we can put a writable PTE entry in immediately.
*/
static void do_set_pte(struct lguest *lg, int idx,
- unsigned long vaddr, gpte_t gpte)
+ unsigned long vaddr, pte_t gpte)
{
- /* Look up the matching shadow page directot entry. */
- spgd_t *spgd = spgd_addr(lg, idx, vaddr);
+ /* Look up the matching shadow page directory entry. */
+ pgd_t *spgd = spgd_addr(lg, idx, vaddr);
/* If the top level isn't present, there's no entry to update. */
- if (spgd->flags & _PAGE_PRESENT) {
+ if (pgd_flags(*spgd) & _PAGE_PRESENT) {
/* Otherwise, we start by releasing the existing entry. */
- spte_t *spte = spte_addr(lg, *spgd, vaddr);
+ pte_t *spte = spte_addr(lg, *spgd, vaddr);
release_pte(*spte);
/* If they're setting this entry as dirty or accessed, we might
* as well put that entry they've given us in now. This shaves
* 10% off a copy-on-write micro-benchmark. */
- if (gpte.flags & (_PAGE_DIRTY | _PAGE_ACCESSED)) {
+ if (pte_flags(gpte) & (_PAGE_DIRTY | _PAGE_ACCESSED)) {
check_gpte(lg, gpte);
- *spte = gpte_to_spte(lg, gpte, gpte.flags&_PAGE_DIRTY);
+ *spte = gpte_to_spte(lg, gpte,
+ pte_flags(gpte) & _PAGE_DIRTY);
} else
- /* Otherwise we can demand_page() it in later. */
- spte->raw.val = 0;
+ /* Otherwise kill it and we can demand_page() it in
+ * later. */
+ *spte = __pte(0);
}
}
@@ -506,18 +534,18 @@ static void do_set_pte(struct lguest *lg, int idx,
* The benefit is that when we have to track a new page table, we can copy keep
* all the kernel mappings. This speeds up context switch immensely. */
void guest_set_pte(struct lguest *lg,
- unsigned long cr3, unsigned long vaddr, gpte_t gpte)
+ unsigned long gpgdir, unsigned long vaddr, pte_t gpte)
{
/* Kernel mappings must be changed on all top levels. Slow, but
* doesn't happen often. */
- if (vaddr >= lg->page_offset) {
+ if (vaddr >= lg->kernel_address) {
unsigned int i;
for (i = 0; i < ARRAY_SIZE(lg->pgdirs); i++)
if (lg->pgdirs[i].pgdir)
do_set_pte(lg, i, vaddr, gpte);
} else {
/* Is this page table one we have a shadow for? */
- int pgdir = find_pgdir(lg, cr3);
+ int pgdir = find_pgdir(lg, gpgdir);
if (pgdir != ARRAY_SIZE(lg->pgdirs))
/* If so, do the update. */
do_set_pte(lg, pgdir, vaddr, gpte);
@@ -525,7 +553,7 @@ void guest_set_pte(struct lguest *lg,
}
/*H:400
- * (iii) Setting up a page table entry when the Guest tells us it has changed.
+ * (iii) Setting up a page table entry when the Guest tells us one has changed.
*
* Just like we did in interrupts_and_traps.c, it makes sense for us to deal
* with the other side of page tables while we're here: what happens when the
@@ -538,7 +566,7 @@ void guest_set_pte(struct lguest *lg,
*
* So with that in mind here's our code to to update a (top-level) PGD entry:
*/
-void guest_set_pmd(struct lguest *lg, unsigned long cr3, u32 idx)
+void guest_set_pmd(struct lguest *lg, unsigned long gpgdir, u32 idx)
{
int pgdir;
@@ -548,7 +576,7 @@ void guest_set_pmd(struct lguest *lg, unsigned long cr3, u32 idx)
return;
/* If they're talking about a page table we have a shadow for... */
- pgdir = find_pgdir(lg, cr3);
+ pgdir = find_pgdir(lg, gpgdir);
if (pgdir < ARRAY_SIZE(lg->pgdirs))
/* ... throw it away. */
release_pgd(lg, lg->pgdirs[pgdir].pgdir + idx);
@@ -560,21 +588,34 @@ void guest_set_pmd(struct lguest *lg, unsigned long cr3, u32 idx)
* its first page table is. We set some things up here: */
int init_guest_pagetable(struct lguest *lg, unsigned long pgtable)
{
- /* In flush_user_mappings() we loop from 0 to
- * "vaddr_to_pgd_index(lg->page_offset)". This assumes it won't hit
- * the Switcher mappings, so check that now. */
- if (vaddr_to_pgd_index(lg->page_offset) >= SWITCHER_PGD_INDEX)
- return -EINVAL;
/* We start on the first shadow page table, and give it a blank PGD
* page. */
lg->pgdidx = 0;
- lg->pgdirs[lg->pgdidx].cr3 = pgtable;
- lg->pgdirs[lg->pgdidx].pgdir = (spgd_t*)get_zeroed_page(GFP_KERNEL);
+ lg->pgdirs[lg->pgdidx].gpgdir = pgtable;
+ lg->pgdirs[lg->pgdidx].pgdir = (pgd_t*)get_zeroed_page(GFP_KERNEL);
if (!lg->pgdirs[lg->pgdidx].pgdir)
return -ENOMEM;
return 0;
}
+/* When the Guest calls LHCALL_LGUEST_INIT we do more setup. */
+void page_table_guest_data_init(struct lguest *lg)
+{
+ /* We get the kernel address: above this is all kernel memory. */
+ if (get_user(lg->kernel_address, &lg->lguest_data->kernel_address)
+ /* We tell the Guest that it can't use the top 4MB of virtual
+ * addresses used by the Switcher. */
+ || put_user(4U*1024*1024, &lg->lguest_data->reserve_mem)
+ || put_user(lg->pgdirs[lg->pgdidx].gpgdir,&lg->lguest_data->pgdir))
+ kill_guest(lg, "bad guest page %p", lg->lguest_data);
+
+ /* In flush_user_mappings() we loop from 0 to
+ * "pgd_index(lg->kernel_address)". This assumes it won't hit the
+ * Switcher mappings, so check that now. */
+ if (pgd_index(lg->kernel_address) >= SWITCHER_PGD_INDEX)
+ kill_guest(lg, "bad kernel address %#lx", lg->kernel_address);
+}
+
/* When a Guest dies, our cleanup is fairly simple. */
void free_guest_pagetable(struct lguest *lg)
{
@@ -589,19 +630,20 @@ void free_guest_pagetable(struct lguest *lg)
/*H:480 (vi) Mapping the Switcher when the Guest is about to run.
*
- * The Switcher and the two pages for this CPU need to be available to the
+ * The Switcher and the two pages for this CPU need to be visible in the
* Guest (and not the pages for other CPUs). We have the appropriate PTE pages
- * for each CPU already set up, we just need to hook them in. */
+ * for each CPU already set up, we just need to hook them in now we know which
+ * Guest is about to run on this CPU. */
void map_switcher_in_guest(struct lguest *lg, struct lguest_pages *pages)
{
- spte_t *switcher_pte_page = __get_cpu_var(switcher_pte_pages);
- spgd_t switcher_pgd;
- spte_t regs_pte;
+ pte_t *switcher_pte_page = __get_cpu_var(switcher_pte_pages);
+ pgd_t switcher_pgd;
+ pte_t regs_pte;
/* Make the last PGD entry for this Guest point to the Switcher's PTE
* page for this CPU (with appropriate flags). */
- switcher_pgd.pfn = __pa(switcher_pte_page) >> PAGE_SHIFT;
- switcher_pgd.flags = _PAGE_KERNEL;
+ switcher_pgd = __pgd(__pa(switcher_pte_page) | _PAGE_KERNEL);
+
lg->pgdirs[lg->pgdidx].pgdir[SWITCHER_PGD_INDEX] = switcher_pgd;
/* We also change the Switcher PTE page. When we're running the Guest,
@@ -611,10 +653,8 @@ void map_switcher_in_guest(struct lguest *lg, struct lguest_pages *pages)
* CPU's "struct lguest_pages": if we make sure the Guest's register
* page is already mapped there, we don't have to copy them out
* again. */
- regs_pte.pfn = __pa(lg->regs_page) >> PAGE_SHIFT;
- regs_pte.flags = _PAGE_KERNEL;
- switcher_pte_page[(unsigned long)pages/PAGE_SIZE%PTES_PER_PAGE]
- = regs_pte;
+ regs_pte = pfn_pte (__pa(lg->regs_page) >> PAGE_SHIFT, __pgprot(_PAGE_KERNEL));
+ switcher_pte_page[(unsigned long)pages/PAGE_SIZE%PTRS_PER_PTE] = regs_pte;
}
/*:*/
@@ -635,26 +675,39 @@ static __init void populate_switcher_pte_page(unsigned int cpu,
unsigned int pages)
{
unsigned int i;
- spte_t *pte = switcher_pte_page(cpu);
+ pte_t *pte = switcher_pte_page(cpu);
/* The first entries are easy: they map the Switcher code. */
for (i = 0; i < pages; i++) {
- pte[i].pfn = page_to_pfn(switcher_page[i]);
- pte[i].flags = _PAGE_PRESENT|_PAGE_ACCESSED;
+ pte[i] = mk_pte(switcher_page[i],
+ __pgprot(_PAGE_PRESENT|_PAGE_ACCESSED));
}
/* The only other thing we map is this CPU's pair of pages. */
i = pages + cpu*2;
/* First page (Guest registers) is writable from the Guest */
- pte[i].pfn = page_to_pfn(switcher_page[i]);
- pte[i].flags = _PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_RW;
+ pte[i] = pfn_pte(page_to_pfn(switcher_page[i]),
+ __pgprot(_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_RW));
+
/* The second page contains the "struct lguest_ro_state", and is
* read-only. */
- pte[i+1].pfn = page_to_pfn(switcher_page[i+1]);
- pte[i+1].flags = _PAGE_PRESENT|_PAGE_ACCESSED;
+ pte[i+1] = pfn_pte(page_to_pfn(switcher_page[i+1]),
+ __pgprot(_PAGE_PRESENT|_PAGE_ACCESSED));
}
+/* We've made it through the page table code. Perhaps our tired brains are
+ * still processing the details, or perhaps we're simply glad it's over.
+ *
+ * If nothing else, note that all this complexity in juggling shadow page
+ * tables in sync with the Guest's page tables is for one reason: for most
+ * Guests this page table dance determines how bad performance will be. This
+ * is why Xen uses exotic direct Guest pagetable manipulation, and why both
+ * Intel and AMD have implemented shadow page table support directly into
+ * hardware.
+ *
+ * There is just one file remaining in the Host. */
+
/*H:510 At boot or module load time, init_pagetables() allocates and populates
* the Switcher PTE page for each CPU. */
__init int init_pagetables(struct page **switcher_page, unsigned int pages)
@@ -662,7 +715,7 @@ __init int init_pagetables(struct page **switcher_page, unsigned int pages)
unsigned int i;
for_each_possible_cpu(i) {
- switcher_pte_page(i) = (spte_t *)get_zeroed_page(GFP_KERNEL);
+ switcher_pte_page(i) = (pte_t *)get_zeroed_page(GFP_KERNEL);
if (!switcher_pte_page(i)) {
free_switcher_pte_pages();
return -ENOMEM;
diff --git a/drivers/lguest/segments.c b/drivers/lguest/segments.c
index 9b81119f46e9..9e189cbec7dd 100644
--- a/drivers/lguest/segments.c
+++ b/drivers/lguest/segments.c
@@ -12,8 +12,6 @@
#include "lg.h"
/*H:600
- * We've almost completed the Host; there's just one file to go!
- *
* Segments & The Global Descriptor Table
*
* (That title sounds like a bad Nerdcore group. Not to suggest that there are
@@ -55,7 +53,7 @@ static int ignored_gdt(unsigned int num)
|| num == GDT_ENTRY_DOUBLEFAULT_TSS);
}
-/*H:610 Once the GDT has been changed, we fix the new entries up a little. We
+/*H:630 Once the Guest gave us new GDT entries, we fix them up a little. We
* don't care if they're invalid: the worst that can happen is a General
* Protection Fault in the Switcher when it restores a Guest segment register
* which tries to use that entry. Then we kill the Guest for causing such a
@@ -73,63 +71,68 @@ static void fixup_gdt_table(struct lguest *lg, unsigned start, unsigned end)
/* Segment descriptors contain a privilege level: the Guest is
* sometimes careless and leaves this as 0, even though it's
* running at privilege level 1. If so, we fix it here. */
- if ((lg->gdt[i].b & 0x00006000) == 0)
- lg->gdt[i].b |= (GUEST_PL << 13);
+ if ((lg->arch.gdt[i].b & 0x00006000) == 0)
+ lg->arch.gdt[i].b |= (GUEST_PL << 13);
/* Each descriptor has an "accessed" bit. If we don't set it
* now, the CPU will try to set it when the Guest first loads
* that entry into a segment register. But the GDT isn't
* writable by the Guest, so bad things can happen. */
- lg->gdt[i].b |= 0x00000100;
+ lg->arch.gdt[i].b |= 0x00000100;
}
}
-/* This routine is called at boot or modprobe time for each CPU to set up the
- * "constant" GDT entries for Guests running on that CPU. */
+/*H:610 Like the IDT, we never simply use the GDT the Guest gives us. We keep
+ * a GDT for each CPU, and copy across the Guest's entries each time we want to
+ * run the Guest on that CPU.
+ *
+ * This routine is called at boot or modprobe time for each CPU to set up the
+ * constant GDT entries: the ones which are the same no matter what Guest we're
+ * running. */
void setup_default_gdt_entries(struct lguest_ro_state *state)
{
struct desc_struct *gdt = state->guest_gdt;
unsigned long tss = (unsigned long)&state->guest_tss;
- /* The hypervisor segments are full 0-4G segments, privilege level 0 */
+ /* The Switcher segments are full 0-4G segments, privilege level 0 */
gdt[GDT_ENTRY_LGUEST_CS] = FULL_EXEC_SEGMENT;
gdt[GDT_ENTRY_LGUEST_DS] = FULL_SEGMENT;
- /* The TSS segment refers to the TSS entry for this CPU, so we cannot
- * copy it from the Guest. Forgive the magic flags */
+ /* The TSS segment refers to the TSS entry for this particular CPU.
+ * Forgive the magic flags: the 0x8900 means the entry is Present, it's
+ * privilege level 0 Available 386 TSS system segment, and the 0x67
+ * means Saturn is eclipsed by Mercury in the twelfth house. */
gdt[GDT_ENTRY_TSS].a = 0x00000067 | (tss << 16);
gdt[GDT_ENTRY_TSS].b = 0x00008900 | (tss & 0xFF000000)
| ((tss >> 16) & 0x000000FF);
}
-/* This routine is called before the Guest is run for the first time. */
+/* This routine sets up the initial Guest GDT for booting. All entries start
+ * as 0 (unusable). */
void setup_guest_gdt(struct lguest *lg)
{
/* Start with full 0-4G segments... */
- lg->gdt[GDT_ENTRY_KERNEL_CS] = FULL_EXEC_SEGMENT;
- lg->gdt[GDT_ENTRY_KERNEL_DS] = FULL_SEGMENT;
+ lg->arch.gdt[GDT_ENTRY_KERNEL_CS] = FULL_EXEC_SEGMENT;
+ lg->arch.gdt[GDT_ENTRY_KERNEL_DS] = FULL_SEGMENT;
/* ...except the Guest is allowed to use them, so set the privilege
* level appropriately in the flags. */
- lg->gdt[GDT_ENTRY_KERNEL_CS].b |= (GUEST_PL << 13);
- lg->gdt[GDT_ENTRY_KERNEL_DS].b |= (GUEST_PL << 13);
+ lg->arch.gdt[GDT_ENTRY_KERNEL_CS].b |= (GUEST_PL << 13);
+ lg->arch.gdt[GDT_ENTRY_KERNEL_DS].b |= (GUEST_PL << 13);
}
-/* Like the IDT, we never simply use the GDT the Guest gives us. We set up the
- * GDTs for each CPU, then we copy across the entries each time we want to run
- * a different Guest on that CPU. */
-
-/* A partial GDT load, for the three "thead-local storage" entries. Otherwise
- * it's just like load_guest_gdt(). So much, in fact, it would probably be
- * neater to have a single hypercall to cover both. */
+/*H:650 An optimization of copy_gdt(), for just the three "thead-local storage"
+ * entries. */
void copy_gdt_tls(const struct lguest *lg, struct desc_struct *gdt)
{
unsigned int i;
for (i = GDT_ENTRY_TLS_MIN; i <= GDT_ENTRY_TLS_MAX; i++)
- gdt[i] = lg->gdt[i];
+ gdt[i] = lg->arch.gdt[i];
}
-/* This is the full version */
+/*H:640 When the Guest is run on a different CPU, or the GDT entries have
+ * changed, copy_gdt() is called to copy the Guest's GDT entries across to this
+ * CPU's GDT. */
void copy_gdt(const struct lguest *lg, struct desc_struct *gdt)
{
unsigned int i;
@@ -138,35 +141,42 @@ void copy_gdt(const struct lguest *lg, struct desc_struct *gdt)
* replaced. See ignored_gdt() above. */
for (i = 0; i < GDT_ENTRIES; i++)
if (!ignored_gdt(i))
- gdt[i] = lg->gdt[i];
+ gdt[i] = lg->arch.gdt[i];
}
-/* This is where the Guest asks us to load a new GDT (LHCALL_LOAD_GDT). */
+/*H:620 This is where the Guest asks us to load a new GDT (LHCALL_LOAD_GDT).
+ * We copy it from the Guest and tweak the entries. */
void load_guest_gdt(struct lguest *lg, unsigned long table, u32 num)
{
/* We assume the Guest has the same number of GDT entries as the
* Host, otherwise we'd have to dynamically allocate the Guest GDT. */
- if (num > ARRAY_SIZE(lg->gdt))
+ if (num > ARRAY_SIZE(lg->arch.gdt))
kill_guest(lg, "too many gdt entries %i", num);
/* We read the whole thing in, then fix it up. */
- lgread(lg, lg->gdt, table, num * sizeof(lg->gdt[0]));
- fixup_gdt_table(lg, 0, ARRAY_SIZE(lg->gdt));
+ __lgread(lg, lg->arch.gdt, table, num * sizeof(lg->arch.gdt[0]));
+ fixup_gdt_table(lg, 0, ARRAY_SIZE(lg->arch.gdt));
/* Mark that the GDT changed so the core knows it has to copy it again,
* even if the Guest is run on the same CPU. */
lg->changed |= CHANGED_GDT;
}
+/* This is the fast-track version for just changing the three TLS entries.
+ * Remember that this happens on every context switch, so it's worth
+ * optimizing. But wouldn't it be neater to have a single hypercall to cover
+ * both cases? */
void guest_load_tls(struct lguest *lg, unsigned long gtls)
{
- struct desc_struct *tls = &lg->gdt[GDT_ENTRY_TLS_MIN];
+ struct desc_struct *tls = &lg->arch.gdt[GDT_ENTRY_TLS_MIN];
- lgread(lg, tls, gtls, sizeof(*tls)*GDT_ENTRY_TLS_ENTRIES);
+ __lgread(lg, tls, gtls, sizeof(*tls)*GDT_ENTRY_TLS_ENTRIES);
fixup_gdt_table(lg, GDT_ENTRY_TLS_MIN, GDT_ENTRY_TLS_MAX+1);
+ /* Note that just the TLS entries have changed. */
lg->changed |= CHANGED_GDT_TLS;
}
+/*:*/
-/*
+/*H:660
* With this, we have finished the Host.
*
* Five of the seven parts of our task are complete. You have made it through
diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c
new file mode 100644
index 000000000000..482aec2a9631
--- /dev/null
+++ b/drivers/lguest/x86/core.c
@@ -0,0 +1,581 @@
+/*
+ * Copyright (C) 2006, Rusty Russell <rusty@rustcorp.com.au> IBM Corporation.
+ * Copyright (C) 2007, Jes Sorensen <jes@sgi.com> SGI.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/kernel.h>
+#include <linux/start_kernel.h>
+#include <linux/string.h>
+#include <linux/console.h>
+#include <linux/screen_info.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/cpu.h>
+#include <linux/lguest.h>
+#include <linux/lguest_launcher.h>
+#include <asm/paravirt.h>
+#include <asm/param.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/desc.h>
+#include <asm/setup.h>
+#include <asm/lguest.h>
+#include <asm/uaccess.h>
+#include <asm/i387.h>
+#include "../lg.h"
+
+static int cpu_had_pge;
+
+static struct {
+ unsigned long offset;
+ unsigned short segment;
+} lguest_entry;
+
+/* Offset from where switcher.S was compiled to where we've copied it */
+static unsigned long switcher_offset(void)
+{
+ return SWITCHER_ADDR - (unsigned long)start_switcher_text;
+}
+
+/* This cpu's struct lguest_pages. */
+static struct lguest_pages *lguest_pages(unsigned int cpu)
+{
+ return &(((struct lguest_pages *)
+ (SWITCHER_ADDR + SHARED_SWITCHER_PAGES*PAGE_SIZE))[cpu]);
+}
+
+static DEFINE_PER_CPU(struct lguest *, last_guest);
+
+/*S:010
+ * We approach the Switcher.
+ *
+ * Remember that each CPU has two pages which are visible to the Guest when it
+ * runs on that CPU. This has to contain the state for that Guest: we copy the
+ * state in just before we run the Guest.
+ *
+ * Each Guest has "changed" flags which indicate what has changed in the Guest
+ * since it last ran. We saw this set in interrupts_and_traps.c and
+ * segments.c.
+ */
+static void copy_in_guest_info(struct lguest *lg, struct lguest_pages *pages)
+{
+ /* Copying all this data can be quite expensive. We usually run the
+ * same Guest we ran last time (and that Guest hasn't run anywhere else
+ * meanwhile). If that's not the case, we pretend everything in the
+ * Guest has changed. */
+ if (__get_cpu_var(last_guest) != lg || lg->last_pages != pages) {
+ __get_cpu_var(last_guest) = lg;
+ lg->last_pages = pages;
+ lg->changed = CHANGED_ALL;
+ }
+
+ /* These copies are pretty cheap, so we do them unconditionally: */
+ /* Save the current Host top-level page directory. */
+ pages->state.host_cr3 = __pa(current->mm->pgd);
+ /* Set up the Guest's page tables to see this CPU's pages (and no
+ * other CPU's pages). */
+ map_switcher_in_guest(lg, pages);
+ /* Set up the two "TSS" members which tell the CPU what stack to use
+ * for traps which do directly into the Guest (ie. traps at privilege
+ * level 1). */
+ pages->state.guest_tss.esp1 = lg->esp1;
+ pages->state.guest_tss.ss1 = lg->ss1;
+
+ /* Copy direct-to-Guest trap entries. */
+ if (lg->changed & CHANGED_IDT)
+ copy_traps(lg, pages->state.guest_idt, default_idt_entries);
+
+ /* Copy all GDT entries which the Guest can change. */
+ if (lg->changed & CHANGED_GDT)
+ copy_gdt(lg, pages->state.guest_gdt);
+ /* If only the TLS entries have changed, copy them. */
+ else if (lg->changed & CHANGED_GDT_TLS)
+ copy_gdt_tls(lg, pages->state.guest_gdt);
+
+ /* Mark the Guest as unchanged for next time. */
+ lg->changed = 0;
+}
+
+/* Finally: the code to actually call into the Switcher to run the Guest. */
+static void run_guest_once(struct lguest *lg, struct lguest_pages *pages)
+{
+ /* This is a dummy value we need for GCC's sake. */
+ unsigned int clobber;
+
+ /* Copy the guest-specific information into this CPU's "struct
+ * lguest_pages". */
+ copy_in_guest_info(lg, pages);
+
+ /* Set the trap number to 256 (impossible value). If we fault while
+ * switching to the Guest (bad segment registers or bug), this will
+ * cause us to abort the Guest. */
+ lg->regs->trapnum = 256;
+
+ /* Now: we push the "eflags" register on the stack, then do an "lcall".
+ * This is how we change from using the kernel code segment to using
+ * the dedicated lguest code segment, as well as jumping into the
+ * Switcher.
+ *
+ * The lcall also pushes the old code segment (KERNEL_CS) onto the
+ * stack, then the address of this call. This stack layout happens to
+ * exactly match the stack layout created by an interrupt... */
+ asm volatile("pushf; lcall *lguest_entry"
+ /* This is how we tell GCC that %eax ("a") and %ebx ("b")
+ * are changed by this routine. The "=" means output. */
+ : "=a"(clobber), "=b"(clobber)
+ /* %eax contains the pages pointer. ("0" refers to the
+ * 0-th argument above, ie "a"). %ebx contains the
+ * physical address of the Guest's top-level page
+ * directory. */
+ : "0"(pages), "1"(__pa(lg->pgdirs[lg->pgdidx].pgdir))
+ /* We tell gcc that all these registers could change,
+ * which means we don't have to save and restore them in
+ * the Switcher. */
+ : "memory", "%edx", "%ecx", "%edi", "%esi");
+}
+/*:*/
+
+/*M:002 There are hooks in the scheduler which we can register to tell when we
+ * get kicked off the CPU (preempt_notifier_register()). This would allow us
+ * to lazily disable SYSENTER which would regain some performance, and should
+ * also simplify copy_in_guest_info(). Note that we'd still need to restore
+ * things when we exit to Launcher userspace, but that's fairly easy.
+ *
+ * The hooks were designed for KVM, but we can also put them to good use. :*/
+
+/*H:040 This is the i386-specific code to setup and run the Guest. Interrupts
+ * are disabled: we own the CPU. */
+void lguest_arch_run_guest(struct lguest *lg)
+{
+ /* Remember the awfully-named TS bit? If the Guest has asked to set it
+ * we set it now, so we can trap and pass that trap to the Guest if it
+ * uses the FPU. */
+ if (lg->ts)
+ lguest_set_ts();
+
+ /* SYSENTER is an optimized way of doing system calls. We can't allow
+ * it because it always jumps to privilege level 0. A normal Guest
+ * won't try it because we don't advertise it in CPUID, but a malicious
+ * Guest (or malicious Guest userspace program) could, so we tell the
+ * CPU to disable it before running the Guest. */
+ if (boot_cpu_has(X86_FEATURE_SEP))
+ wrmsr(MSR_IA32_SYSENTER_CS, 0, 0);
+
+ /* Now we actually run the Guest. It will return when something
+ * interesting happens, and we can examine its registers to see what it
+ * was doing. */
+ run_guest_once(lg, lguest_pages(raw_smp_processor_id()));
+
+ /* Note that the "regs" pointer contains two extra entries which are
+ * not really registers: a trap number which says what interrupt or
+ * trap made the switcher code come back, and an error code which some
+ * traps set. */
+
+ /* If the Guest page faulted, then the cr2 register will tell us the
+ * bad virtual address. We have to grab this now, because once we
+ * re-enable interrupts an interrupt could fault and thus overwrite
+ * cr2, or we could even move off to a different CPU. */
+ if (lg->regs->trapnum == 14)
+ lg->arch.last_pagefault = read_cr2();
+ /* Similarly, if we took a trap because the Guest used the FPU,
+ * we have to restore the FPU it expects to see. */
+ else if (lg->regs->trapnum == 7)
+ math_state_restore();
+
+ /* Restore SYSENTER if it's supposed to be on. */
+ if (boot_cpu_has(X86_FEATURE_SEP))
+ wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0);
+}
+
+/*H:130 Now we've examined the hypercall code; our Guest can make requests.
+ * Our Guest is usually so well behaved; it never tries to do things it isn't
+ * allowed to, and uses hypercalls instead. Unfortunately, Linux's paravirtual
+ * infrastructure isn't quite complete, because it doesn't contain replacements
+ * for the Intel I/O instructions. As a result, the Guest sometimes fumbles
+ * across one during the boot process as it probes for various things which are
+ * usually attached to a PC.
+ *
+ * When the Guest uses one of these instructions, we get a trap (General
+ * Protection Fault) and come here. We see if it's one of those troublesome
+ * instructions and skip over it. We return true if we did. */
+static int emulate_insn(struct lguest *lg)
+{
+ u8 insn;
+ unsigned int insnlen = 0, in = 0, shift = 0;
+ /* The eip contains the *virtual* address of the Guest's instruction:
+ * guest_pa just subtracts the Guest's page_offset. */
+ unsigned long physaddr = guest_pa(lg, lg->regs->eip);
+
+ /* This must be the Guest kernel trying to do something, not userspace!
+ * The bottom two bits of the CS segment register are the privilege
+ * level. */
+ if ((lg->regs->cs & 3) != GUEST_PL)
+ return 0;
+
+ /* Decoding x86 instructions is icky. */
+ insn = lgread(lg, physaddr, u8);
+
+ /* 0x66 is an "operand prefix". It means it's using the upper 16 bits
+ of the eax register. */
+ if (insn == 0x66) {
+ shift = 16;
+ /* The instruction is 1 byte so far, read the next byte. */
+ insnlen = 1;
+ insn = lgread(lg, physaddr + insnlen, u8);
+ }
+
+ /* We can ignore the lower bit for the moment and decode the 4 opcodes
+ * we need to emulate. */
+ switch (insn & 0xFE) {
+ case 0xE4: /* in <next byte>,%al */
+ insnlen += 2;
+ in = 1;
+ break;
+ case 0xEC: /* in (%dx),%al */
+ insnlen += 1;
+ in = 1;
+ break;
+ case 0xE6: /* out %al,<next byte> */
+ insnlen += 2;
+ break;
+ case 0xEE: /* out %al,(%dx) */
+ insnlen += 1;
+ break;
+ default:
+ /* OK, we don't know what this is, can't emulate. */
+ return 0;
+ }
+
+ /* If it was an "IN" instruction, they expect the result to be read
+ * into %eax, so we change %eax. We always return all-ones, which
+ * traditionally means "there's nothing there". */
+ if (in) {
+ /* Lower bit tells is whether it's a 16 or 32 bit access */
+ if (insn & 0x1)
+ lg->regs->eax = 0xFFFFFFFF;
+ else
+ lg->regs->eax |= (0xFFFF << shift);
+ }
+ /* Finally, we've "done" the instruction, so move past it. */
+ lg->regs->eip += insnlen;
+ /* Success! */
+ return 1;
+}
+
+/*H:050 Once we've re-enabled interrupts, we look at why the Guest exited. */
+void lguest_arch_handle_trap(struct lguest *lg)
+{
+ switch (lg->regs->trapnum) {
+ case 13: /* We've intercepted a General Protection Fault. */
+ /* Check if this was one of those annoying IN or OUT
+ * instructions which we need to emulate. If so, we just go
+ * back into the Guest after we've done it. */
+ if (lg->regs->errcode == 0) {
+ if (emulate_insn(lg))
+ return;
+ }
+ break;
+ case 14: /* We've intercepted a Page Fault. */
+ /* The Guest accessed a virtual address that wasn't mapped.
+ * This happens a lot: we don't actually set up most of the
+ * page tables for the Guest at all when we start: as it runs
+ * it asks for more and more, and we set them up as
+ * required. In this case, we don't even tell the Guest that
+ * the fault happened.
+ *
+ * The errcode tells whether this was a read or a write, and
+ * whether kernel or userspace code. */
+ if (demand_page(lg, lg->arch.last_pagefault, lg->regs->errcode))
+ return;
+
+ /* OK, it's really not there (or not OK): the Guest needs to
+ * know. We write out the cr2 value so it knows where the
+ * fault occurred.
+ *
+ * Note that if the Guest were really messed up, this could
+ * happen before it's done the LHCALL_LGUEST_INIT hypercall, so
+ * lg->lguest_data could be NULL */
+ if (lg->lguest_data &&
+ put_user(lg->arch.last_pagefault, &lg->lguest_data->cr2))
+ kill_guest(lg, "Writing cr2");
+ break;
+ case 7: /* We've intercepted a Device Not Available fault. */
+ /* If the Guest doesn't want to know, we already restored the
+ * Floating Point Unit, so we just continue without telling
+ * it. */
+ if (!lg->ts)
+ return;
+ break;
+ case 32 ... 255:
+ /* These values mean a real interrupt occurred, in which case
+ * the Host handler has already been run. We just do a
+ * friendly check if another process should now be run, then
+ * return to run the Guest again */
+ cond_resched();
+ return;
+ case LGUEST_TRAP_ENTRY:
+ /* Our 'struct hcall_args' maps directly over our regs: we set
+ * up the pointer now to indicate a hypercall is pending. */
+ lg->hcall = (struct hcall_args *)lg->regs;
+ return;
+ }
+
+ /* We didn't handle the trap, so it needs to go to the Guest. */
+ if (!deliver_trap(lg, lg->regs->trapnum))
+ /* If the Guest doesn't have a handler (either it hasn't
+ * registered any yet, or it's one of the faults we don't let
+ * it handle), it dies with a cryptic error message. */
+ kill_guest(lg, "unhandled trap %li at %#lx (%#lx)",
+ lg->regs->trapnum, lg->regs->eip,
+ lg->regs->trapnum == 14 ? lg->arch.last_pagefault
+ : lg->regs->errcode);
+}
+
+/* Now we can look at each of the routines this calls, in increasing order of
+ * complexity: do_hypercalls(), emulate_insn(), maybe_do_interrupt(),
+ * deliver_trap() and demand_page(). After all those, we'll be ready to
+ * examine the Switcher, and our philosophical understanding of the Host/Guest
+ * duality will be complete. :*/
+static void adjust_pge(void *on)
+{
+ if (on)
+ write_cr4(read_cr4() | X86_CR4_PGE);
+ else
+ write_cr4(read_cr4() & ~X86_CR4_PGE);
+}
+
+/*H:020 Now the Switcher is mapped and every thing else is ready, we need to do
+ * some more i386-specific initialization. */
+void __init lguest_arch_host_init(void)
+{
+ int i;
+
+ /* Most of the i386/switcher.S doesn't care that it's been moved; on
+ * Intel, jumps are relative, and it doesn't access any references to
+ * external code or data.
+ *
+ * The only exception is the interrupt handlers in switcher.S: their
+ * addresses are placed in a table (default_idt_entries), so we need to
+ * update the table with the new addresses. switcher_offset() is a
+ * convenience function which returns the distance between the builtin
+ * switcher code and the high-mapped copy we just made. */
+ for (i = 0; i < IDT_ENTRIES; i++)
+ default_idt_entries[i] += switcher_offset();
+
+ /*
+ * Set up the Switcher's per-cpu areas.
+ *
+ * Each CPU gets two pages of its own within the high-mapped region
+ * (aka. "struct lguest_pages"). Much of this can be initialized now,
+ * but some depends on what Guest we are running (which is set up in
+ * copy_in_guest_info()).
+ */
+ for_each_possible_cpu(i) {
+ /* lguest_pages() returns this CPU's two pages. */
+ struct lguest_pages *pages = lguest_pages(i);
+ /* This is a convenience pointer to make the code fit one
+ * statement to a line. */
+ struct lguest_ro_state *state = &pages->state;
+
+ /* The Global Descriptor Table: the Host has a different one
+ * for each CPU. We keep a descriptor for the GDT which says
+ * where it is and how big it is (the size is actually the last
+ * byte, not the size, hence the "-1"). */
+ state->host_gdt_desc.size = GDT_SIZE-1;
+ state->host_gdt_desc.address = (long)get_cpu_gdt_table(i);
+
+ /* All CPUs on the Host use the same Interrupt Descriptor
+ * Table, so we just use store_idt(), which gets this CPU's IDT
+ * descriptor. */
+ store_idt(&state->host_idt_desc);
+
+ /* The descriptors for the Guest's GDT and IDT can be filled
+ * out now, too. We copy the GDT & IDT into ->guest_gdt and
+ * ->guest_idt before actually running the Guest. */
+ state->guest_idt_desc.size = sizeof(state->guest_idt)-1;
+ state->guest_idt_desc.address = (long)&state->guest_idt;
+ state->guest_gdt_desc.size = sizeof(state->guest_gdt)-1;
+ state->guest_gdt_desc.address = (long)&state->guest_gdt;
+
+ /* We know where we want the stack to be when the Guest enters
+ * the switcher: in pages->regs. The stack grows upwards, so
+ * we start it at the end of that structure. */
+ state->guest_tss.esp0 = (long)(&pages->regs + 1);
+ /* And this is the GDT entry to use for the stack: we keep a
+ * couple of special LGUEST entries. */
+ state->guest_tss.ss0 = LGUEST_DS;
+
+ /* x86 can have a finegrained bitmap which indicates what I/O
+ * ports the process can use. We set it to the end of our
+ * structure, meaning "none". */
+ state->guest_tss.io_bitmap_base = sizeof(state->guest_tss);
+
+ /* Some GDT entries are the same across all Guests, so we can
+ * set them up now. */
+ setup_default_gdt_entries(state);
+ /* Most IDT entries are the same for all Guests, too.*/
+ setup_default_idt_entries(state, default_idt_entries);
+
+ /* The Host needs to be able to use the LGUEST segments on this
+ * CPU, too, so put them in the Host GDT. */
+ get_cpu_gdt_table(i)[GDT_ENTRY_LGUEST_CS] = FULL_EXEC_SEGMENT;
+ get_cpu_gdt_table(i)[GDT_ENTRY_LGUEST_DS] = FULL_SEGMENT;
+ }
+
+ /* In the Switcher, we want the %cs segment register to use the
+ * LGUEST_CS GDT entry: we've put that in the Host and Guest GDTs, so
+ * it will be undisturbed when we switch. To change %cs and jump we
+ * need this structure to feed to Intel's "lcall" instruction. */
+ lguest_entry.offset = (long)switch_to_guest + switcher_offset();
+ lguest_entry.segment = LGUEST_CS;
+
+ /* Finally, we need to turn off "Page Global Enable". PGE is an
+ * optimization where page table entries are specially marked to show
+ * they never change. The Host kernel marks all the kernel pages this
+ * way because it's always present, even when userspace is running.
+ *
+ * Lguest breaks this: unbeknownst to the rest of the Host kernel, we
+ * switch to the Guest kernel. If you don't disable this on all CPUs,
+ * you'll get really weird bugs that you'll chase for two days.
+ *
+ * I used to turn PGE off every time we switched to the Guest and back
+ * on when we return, but that slowed the Switcher down noticibly. */
+
+ /* We don't need the complexity of CPUs coming and going while we're
+ * doing this. */
+ lock_cpu_hotplug();
+ if (cpu_has_pge) { /* We have a broader idea of "global". */
+ /* Remember that this was originally set (for cleanup). */
+ cpu_had_pge = 1;
+ /* adjust_pge is a helper function which sets or unsets the PGE
+ * bit on its CPU, depending on the argument (0 == unset). */
+ on_each_cpu(adjust_pge, (void *)0, 0, 1);
+ /* Turn off the feature in the global feature set. */
+ clear_bit(X86_FEATURE_PGE, boot_cpu_data.x86_capability);
+ }
+ unlock_cpu_hotplug();
+};
+/*:*/
+
+void __exit lguest_arch_host_fini(void)
+{
+ /* If we had PGE before we started, turn it back on now. */
+ lock_cpu_hotplug();
+ if (cpu_had_pge) {
+ set_bit(X86_FEATURE_PGE, boot_cpu_data.x86_capability);
+ /* adjust_pge's argument "1" means set PGE. */
+ on_each_cpu(adjust_pge, (void *)1, 0, 1);
+ }
+ unlock_cpu_hotplug();
+}
+
+
+/*H:122 The i386-specific hypercalls simply farm out to the right functions. */
+int lguest_arch_do_hcall(struct lguest *lg, struct hcall_args *args)
+{
+ switch (args->arg0) {
+ case LHCALL_LOAD_GDT:
+ load_guest_gdt(lg, args->arg1, args->arg2);
+ break;
+ case LHCALL_LOAD_IDT_ENTRY:
+ load_guest_idt_entry(lg, args->arg1, args->arg2, args->arg3);
+ break;
+ case LHCALL_LOAD_TLS:
+ guest_load_tls(lg, args->arg1);
+ break;
+ default:
+ /* Bad Guest. Bad! */
+ return -EIO;
+ }
+ return 0;
+}
+
+/*H:126 i386-specific hypercall initialization: */
+int lguest_arch_init_hypercalls(struct lguest *lg)
+{
+ u32 tsc_speed;
+
+ /* The pointer to the Guest's "struct lguest_data" is the only
+ * argument. We check that address now. */
+ if (!lguest_address_ok(lg, lg->hcall->arg1, sizeof(*lg->lguest_data)))
+ return -EFAULT;
+
+ /* Having checked it, we simply set lg->lguest_data to point straight
+ * into the Launcher's memory at the right place and then use
+ * copy_to_user/from_user from now on, instead of lgread/write. I put
+ * this in to show that I'm not immune to writing stupid
+ * optimizations. */
+ lg->lguest_data = lg->mem_base + lg->hcall->arg1;
+
+ /* We insist that the Time Stamp Counter exist and doesn't change with
+ * cpu frequency. Some devious chip manufacturers decided that TSC
+ * changes could be handled in software. I decided that time going
+ * backwards might be good for benchmarks, but it's bad for users.
+ *
+ * We also insist that the TSC be stable: the kernel detects unreliable
+ * TSCs for its own purposes, and we use that here. */
+ if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC) && !check_tsc_unstable())
+ tsc_speed = tsc_khz;
+ else
+ tsc_speed = 0;
+ if (put_user(tsc_speed, &lg->lguest_data->tsc_khz))
+ return -EFAULT;
+
+ /* The interrupt code might not like the system call vector. */
+ if (!check_syscall_vector(lg))
+ kill_guest(lg, "bad syscall vector");
+
+ return 0;
+}
+
+/*L:030 lguest_arch_setup_regs()
+ *
+ * Most of the Guest's registers are left alone: we used get_zeroed_page() to
+ * allocate the structure, so they will be 0. */
+void lguest_arch_setup_regs(struct lguest *lg, unsigned long start)
+{
+ struct lguest_regs *regs = lg->regs;
+
+ /* There are four "segment" registers which the Guest needs to boot:
+ * The "code segment" register (cs) refers to the kernel code segment
+ * __KERNEL_CS, and the "data", "extra" and "stack" segment registers
+ * refer to the kernel data segment __KERNEL_DS.
+ *
+ * The privilege level is packed into the lower bits. The Guest runs
+ * at privilege level 1 (GUEST_PL).*/
+ regs->ds = regs->es = regs->ss = __KERNEL_DS|GUEST_PL;
+ regs->cs = __KERNEL_CS|GUEST_PL;
+
+ /* The "eflags" register contains miscellaneous flags. Bit 1 (0x002)
+ * is supposed to always be "1". Bit 9 (0x200) controls whether
+ * interrupts are enabled. We always leave interrupts enabled while
+ * running the Guest. */
+ regs->eflags = X86_EFLAGS_IF | 0x2;
+
+ /* The "Extended Instruction Pointer" register says where the Guest is
+ * running. */
+ regs->eip = start;
+
+ /* %esi points to our boot information, at physical address 0, so don't
+ * touch it. */
+
+ /* There are a couple of GDT entries the Guest expects when first
+ * booting. */
+ setup_guest_gdt(lg);
+}
diff --git a/drivers/lguest/switcher.S b/drivers/lguest/x86/switcher_32.S
index 7c9c230cc845..0af8baaa0d4a 100644
--- a/drivers/lguest/switcher.S
+++ b/drivers/lguest/x86/switcher_32.S
@@ -6,6 +6,37 @@
* are feeling invigorated and refreshed then the next, more challenging stage
* can be found in "make Guest". :*/
+/*M:012 Lguest is meant to be simple: my rule of thumb is that 1% more LOC must
+ * gain at least 1% more performance. Since neither LOC nor performance can be
+ * measured beforehand, it generally means implementing a feature then deciding
+ * if it's worth it. And once it's implemented, who can say no?
+ *
+ * This is why I haven't implemented this idea myself. I want to, but I
+ * haven't. You could, though.
+ *
+ * The main place where lguest performance sucks is Guest page faulting. When
+ * a Guest userspace process hits an unmapped page we switch back to the Host,
+ * walk the page tables, find it's not mapped, switch back to the Guest page
+ * fault handler, which calls a hypercall to set the page table entry, then
+ * finally returns to userspace. That's two round-trips.
+ *
+ * If we had a small walker in the Switcher, we could quickly check the Guest
+ * page table and if the page isn't mapped, immediately reflect the fault back
+ * into the Guest. This means the Switcher would have to know the top of the
+ * Guest page table and the page fault handler address.
+ *
+ * For simplicity, the Guest should only handle the case where the privilege
+ * level of the fault is 3 and probably only not present or write faults. It
+ * should also detect recursive faults, and hand the original fault to the
+ * Host (which is actually really easy).
+ *
+ * Two questions remain. Would the performance gain outweigh the complexity?
+ * And who would write the verse documenting it? :*/
+
+/*M:011 Lguest64 handles NMI. This gave me NMI envy (until I looked at their
+ * code). It's worth doing though, since it would let us use oprofile in the
+ * Host when a Guest is running. :*/
+
/*S:100
* Welcome to the Switcher itself!
*
@@ -48,7 +79,8 @@
#include <linux/linkage.h>
#include <asm/asm-offsets.h>
#include <asm/page.h>
-#include "lg.h"
+#include <asm/segment.h>
+#include <asm/lguest.h>
// We mark the start of the code to copy
// It's placed in .text tho it's never run here
@@ -87,7 +119,7 @@ ENTRY(switch_to_guest)
// All saved and there's now five steps before us:
// Stack, GDT, IDT, TSS
- // And last of all the page tables are flipped.
+ // Then last of all the page tables are flipped.
// Yet beware that our stack pointer must be
// Always valid lest an NMI hits
@@ -102,25 +134,25 @@ ENTRY(switch_to_guest)
lgdt LGUEST_PAGES_guest_gdt_desc(%eax)
// The Guest's IDT we did partially
- // Move to the "struct lguest_pages" as well.
+ // Copy to "struct lguest_pages" as well.
lidt LGUEST_PAGES_guest_idt_desc(%eax)
// The TSS entry which controls traps
// Must be loaded up with "ltr" now:
+ // The GDT entry that TSS uses
+ // Changes type when we load it: damn Intel!
// For after we switch over our page tables
- // It (as the rest) will be writable no more.
- // (The GDT entry TSS needs
- // Changes type when we load it: damn Intel!)
+ // That entry will be read-only: we'd crash.
movl $(GDT_ENTRY_TSS*8), %edx
ltr %dx
// Look back now, before we take this last step!
// The Host's TSS entry was also marked used;
- // Let's clear it again, ere we return.
+ // Let's clear it again for our return.
// The GDT descriptor of the Host
// Points to the table after two "size" bytes
movl (LGUEST_PAGES_host_gdt_desc+2)(%eax), %edx
- // Clear the type field of "used" (byte 5, bit 2)
+ // Clear "used" from type field (byte 5, bit 2)
andb $0xFD, (GDT_ENTRY_TSS*8 + 5)(%edx)
// Once our page table's switched, the Guest is live!
@@ -130,8 +162,9 @@ ENTRY(switch_to_guest)
// The page table change did one tricky thing:
// The Guest's register page has been mapped
- // Writable onto our %esp (stack) --
+ // Writable under our %esp (stack) --
// We can simply pop off all Guest regs.
+ popl %eax
popl %ebx
popl %ecx
popl %edx
@@ -139,7 +172,6 @@ ENTRY(switch_to_guest)
popl %edi
popl %ebp
popl %gs
- popl %eax
popl %fs
popl %ds
popl %es
@@ -151,23 +183,21 @@ ENTRY(switch_to_guest)
addl $8, %esp
// The last five stack slots hold return address
- // And everything needed to change privilege
- // Into the Guest privilege level of 1,
+ // And everything needed to switch privilege
+ // From Switcher's level 0 to Guest's 1,
// And the stack where the Guest had last left it.
// Interrupts are turned back on: we are Guest.
iret
-// There are two paths where we switch to the Host
+// We treat two paths to switch back to the Host
+// Yet both must save Guest state and restore Host
// So we put the routine in a macro.
-// We are on our way home, back to the Host
-// Interrupted out of the Guest, we come here.
#define SWITCH_TO_HOST \
/* We save the Guest state: all registers first \
* Laid out just as "struct lguest_regs" defines */ \
pushl %es; \
pushl %ds; \
pushl %fs; \
- pushl %eax; \
pushl %gs; \
pushl %ebp; \
pushl %edi; \
@@ -175,6 +205,7 @@ ENTRY(switch_to_guest)
pushl %edx; \
pushl %ecx; \
pushl %ebx; \
+ pushl %eax; \
/* Our stack and our code are using segments \
* Set in the TSS and IDT \
* Yet if we were to touch data we'd use \
@@ -193,7 +224,7 @@ ENTRY(switch_to_guest)
movl %esp, %eax; \
andl $(~(1 << PAGE_SHIFT - 1)), %eax; \
/* Save our trap number: the switch will obscure it \
- * (The Guest regs are not mapped here in the Host) \
+ * (In the Host the Guest regs are not mapped here) \
* %ebx holds it safe for deliver_to_host */ \
movl LGUEST_PAGES_regs_trapnum(%eax), %ebx; \
/* The Host GDT, IDT and stack! \
@@ -209,9 +240,9 @@ ENTRY(switch_to_guest)
/* Switch to Host's GDT, IDT. */ \
lgdt LGUEST_PAGES_host_gdt_desc(%eax); \
lidt LGUEST_PAGES_host_idt_desc(%eax); \
- /* Restore the Host's stack where it's saved regs lie */ \
+ /* Restore the Host's stack where its saved regs lie */ \
movl LGUEST_PAGES_host_sp(%eax), %esp; \
- /* Last the TSS: our Host is complete */ \
+ /* Last the TSS: our Host is returned */ \
movl $(GDT_ENTRY_TSS*8), %edx; \
ltr %dx; \
/* Restore now the regs saved right at the first. */ \
@@ -221,14 +252,15 @@ ENTRY(switch_to_guest)
popl %ds; \
popl %es
-// Here's where we come when the Guest has just trapped:
-// (Which trap we'll see has been pushed on the stack).
+// The first path is trod when the Guest has trapped:
+// (Which trap it was has been pushed on the stack).
// We need only switch back, and the Host will decode
// Why we came home, and what needs to be done.
return_to_host:
SWITCH_TO_HOST
iret
+// We are lead to the second path like so:
// An interrupt, with some cause external
// Has ajerked us rudely from the Guest's code
// Again we must return home to the Host
@@ -237,7 +269,7 @@ deliver_to_host:
// But now we must go home via that place
// Where that interrupt was supposed to go
// Had we not been ensconced, running the Guest.
- // Here we see the cleverness of our stack:
+ // Here we see the trickness of run_guest_once():
// The Host stack is formed like an interrupt
// With EIP, CS and EFLAGS layered.
// Interrupt handlers end with "iret"
@@ -262,7 +294,7 @@ deliver_to_host:
xorw %ax, %ax
orl %eax, %edx
// Now the address of the handler's in %edx
- // We call it now: its "iret" takes us home.
+ // We call it now: its "iret" drops us home.
jmp *%edx
// Every interrupt can come to us here
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig
index 56cd8998fe4b..77f50b63a970 100644
--- a/drivers/macintosh/Kconfig
+++ b/drivers/macintosh/Kconfig
@@ -172,6 +172,7 @@ config INPUT_ADBHID
config MAC_EMUMOUSEBTN
bool "Support for mouse button 2+3 emulation"
+ select INPUT
help
This provides generic support for emulating the 2nd and 3rd mouse
button with keypresses. If you say Y here, the emulation is still
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c
index 48d17bf6c927..883da72b5368 100644
--- a/drivers/macintosh/adbhid.c
+++ b/drivers/macintosh/adbhid.c
@@ -52,6 +52,11 @@
MODULE_AUTHOR("Franz Sirl <Franz.Sirl-kernel@lauterbach.com>");
+static int restore_capslock_events;
+module_param(restore_capslock_events, int, 0644);
+MODULE_PARM_DESC(restore_capslock_events,
+ "Produce keypress events for capslock on both keyup and keydown.");
+
#define KEYB_KEYREG 0 /* register # for key up/down data */
#define KEYB_LEDREG 2 /* register # for leds on ADB keyboard */
#define MOUSE_DATAREG 0 /* reg# for movement/button codes from mouse */
@@ -217,6 +222,8 @@ struct adbhid {
#define FLAG_FN_KEY_PRESSED 0x00000001
#define FLAG_POWER_FROM_FN 0x00000002
#define FLAG_EMU_FWDEL_DOWN 0x00000004
+#define FLAG_CAPSLOCK_TRANSLATE 0x00000008
+#define FLAG_CAPSLOCK_DOWN 0x00000010
static struct adbhid *adbhid[16];
@@ -272,19 +279,50 @@ adbhid_keyboard_input(unsigned char *data, int nb, int apoll)
}
static void
-adbhid_input_keycode(int id, int keycode, int repeat)
+adbhid_input_keycode(int id, int scancode, int repeat)
{
struct adbhid *ahid = adbhid[id];
- int up_flag, key;
-
- up_flag = (keycode & 0x80);
- keycode &= 0x7f;
+ int keycode, up_flag, key;
+
+ keycode = scancode & 0x7f;
+ up_flag = scancode & 0x80;
+
+ if (restore_capslock_events) {
+ if (keycode == ADB_KEY_CAPSLOCK && !up_flag) {
+ /* Key pressed, turning on the CapsLock LED.
+ * The next 0xff will be interpreted as a release. */
+ ahid->flags |= FLAG_CAPSLOCK_TRANSLATE
+ | FLAG_CAPSLOCK_DOWN;
+ } else if (scancode == 0xff) {
+ /* Scancode 0xff usually signifies that the capslock
+ * key was either pressed or released. */
+ if (ahid->flags & FLAG_CAPSLOCK_TRANSLATE) {
+ keycode = ADB_KEY_CAPSLOCK;
+ if (ahid->flags & FLAG_CAPSLOCK_DOWN) {
+ /* Key released */
+ up_flag = 1;
+ ahid->flags &= ~FLAG_CAPSLOCK_DOWN;
+ } else {
+ /* Key pressed */
+ up_flag = 0;
+ ahid->flags &= ~FLAG_CAPSLOCK_TRANSLATE;
+ }
+ } else {
+ printk(KERN_INFO "Spurious caps lock event "
+ "(scancode 0xff).");
+ }
+ }
+ }
switch (keycode) {
- case ADB_KEY_CAPSLOCK: /* Generate down/up events for CapsLock everytime. */
- input_report_key(ahid->input, KEY_CAPSLOCK, 1);
- input_report_key(ahid->input, KEY_CAPSLOCK, 0);
- input_sync(ahid->input);
+ case ADB_KEY_CAPSLOCK:
+ if (!restore_capslock_events) {
+ /* Generate down/up events for CapsLock everytime. */
+ input_report_key(ahid->input, KEY_CAPSLOCK, 1);
+ input_sync(ahid->input);
+ input_report_key(ahid->input, KEY_CAPSLOCK, 0);
+ input_sync(ahid->input);
+ }
return;
#ifdef CONFIG_PPC_PMAC
case ADB_KEY_POWER_OLD: /* Power key on PBook 3400 needs remapping */
@@ -296,7 +334,7 @@ adbhid_input_keycode(int id, int keycode, int repeat)
keycode = ADB_KEY_POWER;
}
break;
- case ADB_KEY_POWER:
+ case ADB_KEY_POWER:
/* Fn + Command will produce a bogus "power" keycode */
if (ahid->flags & FLAG_FN_KEY_PRESSED) {
keycode = ADB_KEY_CMD;
@@ -753,8 +791,10 @@ adbhid_input_register(int id, int default_id, int original_handler_id,
if (hid->keycode[i])
set_bit(hid->keycode[i], input_dev->keybit);
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
- input_dev->ledbit[0] = BIT(LED_SCROLLL) | BIT(LED_CAPSL) | BIT(LED_NUML);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_LED) |
+ BIT_MASK(EV_REP);
+ input_dev->ledbit[0] = BIT_MASK(LED_SCROLLL) |
+ BIT_MASK(LED_CAPSL) | BIT_MASK(LED_NUML);
input_dev->event = adbhid_kbd_event;
input_dev->keycodemax = KEY_FN;
input_dev->keycodesize = sizeof(hid->keycode[0]);
@@ -763,16 +803,18 @@ adbhid_input_register(int id, int default_id, int original_handler_id,
case ADB_MOUSE:
sprintf(hid->name, "ADB mouse");
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
- input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+ input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
+ BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
+ input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
break;
case ADB_MISC:
switch (original_handler_id) {
case 0x02: /* Adjustable keyboard button device */
sprintf(hid->name, "ADB adjustable keyboard buttons");
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) |
+ BIT_MASK(EV_REP);
set_bit(KEY_SOUND, input_dev->keybit);
set_bit(KEY_MUTE, input_dev->keybit);
set_bit(KEY_VOLUMEUP, input_dev->keybit);
@@ -780,7 +822,8 @@ adbhid_input_register(int id, int default_id, int original_handler_id,
break;
case 0x1f: /* Powerbook button device */
sprintf(hid->name, "ADB Powerbook buttons");
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) |
+ BIT_MASK(EV_REP);
set_bit(KEY_MUTE, input_dev->keybit);
set_bit(KEY_VOLUMEUP, input_dev->keybit);
set_bit(KEY_VOLUMEDOWN, input_dev->keybit);
diff --git a/drivers/macintosh/mac_hid.c b/drivers/macintosh/mac_hid.c
index 33dee3a773ed..89302309da92 100644
--- a/drivers/macintosh/mac_hid.c
+++ b/drivers/macintosh/mac_hid.c
@@ -117,9 +117,10 @@ static int emumousebtn_input_register(void)
emumousebtn->id.product = 0x0001;
emumousebtn->id.version = 0x0100;
- emumousebtn->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- emumousebtn->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
- emumousebtn->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+ emumousebtn->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+ emumousebtn->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
+ BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
+ emumousebtn->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
ret = input_register_device(emumousebtn);
if (ret)
diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c
index c803d2bba65d..48d647abea46 100644
--- a/drivers/macintosh/mediabay.c
+++ b/drivers/macintosh/mediabay.c
@@ -563,7 +563,7 @@ static void media_bay_step(int i)
ide_init_hwif_ports(&hw, (unsigned long) bay->cd_base, (unsigned long) 0, NULL);
hw.irq = bay->cd_irq;
hw.chipset = ide_pmac;
- bay->cd_index = ide_register_hw(&hw, 0, NULL);
+ bay->cd_index = ide_register_hw(&hw, NULL, 0, NULL);
pmu_resume();
}
if (bay->cd_index == -1) {
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index f7c509b7a8ea..dc741d3a4531 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -1521,7 +1521,7 @@ pmu_sr_intr(void)
req = current_req;
/*
* For PMU sleep and freq change requests, we lock the
- * PMU until it's explicitely unlocked. This avoids any
+ * PMU until it's explicitly unlocked. This avoids any
* spurrious event polling getting in
*/
current_req = req->next;
diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c
index 516d943227e2..075b4d99e354 100644
--- a/drivers/macintosh/windfarm_core.c
+++ b/drivers/macintosh/windfarm_core.c
@@ -94,7 +94,9 @@ static int wf_thread_func(void *data)
DBG("wf: thread started\n");
set_freezable();
- while(!kthread_should_stop()) {
+ while (!kthread_should_stop()) {
+ try_to_freeze();
+
if (time_after_eq(jiffies, next)) {
wf_notify(WF_EVENT_TICK, NULL);
if (wf_overtemp) {
@@ -116,12 +118,6 @@ static int wf_thread_func(void *data)
delay = next - jiffies;
if (delay <= HZ)
schedule_timeout_interruptible(delay);
-
- /* there should be no non-suspend signal, but oh well */
- if (signal_pending(current) && !try_to_freeze()) {
- printk(KERN_WARNING "windfarm: thread got sigl !\n");
- break;
- }
}
DBG("wf: thread stopped\n");
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig
index 34a8c60a254a..9b6fbf044fd8 100644
--- a/drivers/md/Kconfig
+++ b/drivers/md/Kconfig
@@ -267,6 +267,12 @@ config DM_MULTIPATH_RDAC
---help---
Multipath support for LSI/Engenio RDAC.
+config DM_MULTIPATH_HP
+ tristate "HP MSA multipath support (EXPERIMENTAL)"
+ depends on DM_MULTIPATH && BLK_DEV_DM && EXPERIMENTAL
+ ---help---
+ Multipath support for HP MSA (Active/Passive) series hardware.
+
config DM_DELAY
tristate "I/O delaying target (EXPERIMENTAL)"
depends on BLK_DEV_DM && EXPERIMENTAL
@@ -276,4 +282,10 @@ config DM_DELAY
If unsure, say N.
+config DM_UEVENT
+ bool "DM uevents (EXPERIMENTAL)"
+ depends on BLK_DEV_DM && EXPERIMENTAL
+ ---help---
+ Generate udev events for DM events.
+
endif # MD
diff --git a/drivers/md/Makefile b/drivers/md/Makefile
index c49366cdc05d..d9aa7edb8780 100644
--- a/drivers/md/Makefile
+++ b/drivers/md/Makefile
@@ -8,6 +8,7 @@ dm-multipath-objs := dm-hw-handler.o dm-path-selector.o dm-mpath.o
dm-snapshot-objs := dm-snap.o dm-exception-store.o
dm-mirror-objs := dm-log.o dm-raid1.o
dm-rdac-objs := dm-mpath-rdac.o
+dm-hp-sw-objs := dm-mpath-hp-sw.o
md-mod-objs := md.o bitmap.o
raid456-objs := raid5.o raid6algos.o raid6recov.o raid6tables.o \
raid6int1.o raid6int2.o raid6int4.o \
@@ -35,6 +36,7 @@ obj-$(CONFIG_DM_CRYPT) += dm-crypt.o
obj-$(CONFIG_DM_DELAY) += dm-delay.o
obj-$(CONFIG_DM_MULTIPATH) += dm-multipath.o dm-round-robin.o
obj-$(CONFIG_DM_MULTIPATH_EMC) += dm-emc.o
+obj-$(CONFIG_DM_MULTIPATH_HP) += dm-hp-sw.o
obj-$(CONFIG_DM_MULTIPATH_RDAC) += dm-rdac.o
obj-$(CONFIG_DM_SNAPSHOT) += dm-snapshot.o
obj-$(CONFIG_DM_MIRROR) += dm-mirror.o
@@ -48,6 +50,10 @@ ifeq ($(CONFIG_ALTIVEC),y)
altivec_flags := -maltivec -mabi=altivec
endif
+ifeq ($(CONFIG_DM_UEVENT),y)
+dm-mod-objs += dm-uevent.o
+endif
+
targets += raid6int1.c
$(obj)/raid6int1.c: UNROLL := 1
$(obj)/raid6int1.c: $(src)/raid6int.uc $(src)/unroll.pl FORCE
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 927cb34c4805..1b1ef3130e6e 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -274,7 +274,7 @@ static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait)
if (bitmap->offset < 0) {
/* DATA BITMAP METADATA */
if (bitmap->offset
- + page->index * (PAGE_SIZE/512)
+ + (long)(page->index * (PAGE_SIZE/512))
+ size/512 > 0)
/* bitmap runs in to metadata */
return -EINVAL;
@@ -1207,8 +1207,7 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect
prepare_to_wait(&bitmap->overflow_wait, &__wait,
TASK_UNINTERRUPTIBLE);
spin_unlock_irq(&bitmap->lock);
- bitmap->mddev->queue
- ->unplug_fn(bitmap->mddev->queue);
+ blk_unplug(bitmap->mddev->queue);
schedule();
finish_wait(&bitmap->overflow_wait, &__wait);
continue;
diff --git a/drivers/md/dm-bio-list.h b/drivers/md/dm-bio-list.h
index 3f7b827649e3..d4509be0fe67 100644
--- a/drivers/md/dm-bio-list.h
+++ b/drivers/md/dm-bio-list.h
@@ -21,11 +21,6 @@ static inline int bio_list_empty(const struct bio_list *bl)
return bl->head == NULL;
}
-#define BIO_LIST_INIT { .head = NULL, .tail = NULL }
-
-#define BIO_LIST(bl) \
- struct bio_list bl = BIO_LIST_INIT
-
static inline void bio_list_init(struct bio_list *bl)
{
bl->head = bl->tail = NULL;
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 8216a6f75be5..28c6ae095c56 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -36,7 +36,6 @@ struct dm_crypt_io {
struct work_struct work;
atomic_t pending;
int error;
- int post_process;
};
/*
@@ -57,7 +56,7 @@ struct crypt_config;
struct crypt_iv_operations {
int (*ctr)(struct crypt_config *cc, struct dm_target *ti,
- const char *opts);
+ const char *opts);
void (*dtr)(struct crypt_config *cc);
const char *(*status)(struct crypt_config *cc);
int (*generator)(struct crypt_config *cc, u8 *iv, sector_t sector);
@@ -80,6 +79,8 @@ struct crypt_config {
mempool_t *page_pool;
struct bio_set *bs;
+ struct workqueue_struct *io_queue;
+ struct workqueue_struct *crypt_queue;
/*
* crypto related data
*/
@@ -112,7 +113,7 @@ static void clone_init(struct dm_crypt_io *, struct bio *);
* Different IV generation algorithms:
*
* plain: the initial vector is the 32-bit little-endian version of the sector
- * number, padded with zeros if neccessary.
+ * number, padded with zeros if necessary.
*
* essiv: "encrypted sector|salt initial vector", the sector number is
* encrypted with the bulk cipher using a salt as key. The salt
@@ -137,7 +138,7 @@ static int crypt_iv_plain_gen(struct crypt_config *cc, u8 *iv, sector_t sector)
}
static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti,
- const char *opts)
+ const char *opts)
{
struct crypto_cipher *essiv_tfm;
struct crypto_hash *hash_tfm;
@@ -167,7 +168,7 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti,
return -ENOMEM;
}
- sg_set_buf(&sg, cc->key, cc->key_size);
+ sg_init_one(&sg, cc->key, cc->key_size);
desc.tfm = hash_tfm;
desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
err = crypto_hash_digest(&desc, &sg, cc->key_size, salt);
@@ -175,6 +176,7 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti,
if (err) {
ti->error = "Error calculating hash in ESSIV";
+ kfree(salt);
return err;
}
@@ -188,7 +190,7 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti,
if (crypto_cipher_blocksize(essiv_tfm) !=
crypto_blkcipher_ivsize(cc->tfm)) {
ti->error = "Block size of ESSIV cipher does "
- "not match IV size of block cipher";
+ "not match IV size of block cipher";
crypto_free_cipher(essiv_tfm);
kfree(salt);
return -EINVAL;
@@ -319,10 +321,10 @@ crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out,
return r;
}
-static void
-crypt_convert_init(struct crypt_config *cc, struct convert_context *ctx,
- struct bio *bio_out, struct bio *bio_in,
- sector_t sector, int write)
+static void crypt_convert_init(struct crypt_config *cc,
+ struct convert_context *ctx,
+ struct bio *bio_out, struct bio *bio_in,
+ sector_t sector, int write)
{
ctx->bio_in = bio_in;
ctx->bio_out = bio_out;
@@ -338,7 +340,7 @@ crypt_convert_init(struct crypt_config *cc, struct convert_context *ctx,
* Encrypt / decrypt data from one bio to another one (can be the same one)
*/
static int crypt_convert(struct crypt_config *cc,
- struct convert_context *ctx)
+ struct convert_context *ctx)
{
int r = 0;
@@ -346,16 +348,13 @@ static int crypt_convert(struct crypt_config *cc,
ctx->idx_out < ctx->bio_out->bi_vcnt) {
struct bio_vec *bv_in = bio_iovec_idx(ctx->bio_in, ctx->idx_in);
struct bio_vec *bv_out = bio_iovec_idx(ctx->bio_out, ctx->idx_out);
- struct scatterlist sg_in = {
- .page = bv_in->bv_page,
- .offset = bv_in->bv_offset + ctx->offset_in,
- .length = 1 << SECTOR_SHIFT
- };
- struct scatterlist sg_out = {
- .page = bv_out->bv_page,
- .offset = bv_out->bv_offset + ctx->offset_out,
- .length = 1 << SECTOR_SHIFT
- };
+ struct scatterlist sg_in, sg_out;
+
+ sg_init_table(&sg_in, 1);
+ sg_set_page(&sg_in, bv_in->bv_page, 1 << SECTOR_SHIFT, bv_in->bv_offset + ctx->offset_in);
+
+ sg_init_table(&sg_out, 1);
+ sg_set_page(&sg_out, bv_out->bv_page, 1 << SECTOR_SHIFT, bv_out->bv_offset + ctx->offset_out);
ctx->offset_in += sg_in.length;
if (ctx->offset_in >= bv_in->bv_len) {
@@ -370,7 +369,7 @@ static int crypt_convert(struct crypt_config *cc,
}
r = crypt_convert_scatterlist(cc, &sg_out, &sg_in, sg_in.length,
- ctx->write, ctx->sector);
+ ctx->write, ctx->sector);
if (r < 0)
break;
@@ -380,13 +379,13 @@ static int crypt_convert(struct crypt_config *cc,
return r;
}
- static void dm_crypt_bio_destructor(struct bio *bio)
- {
+static void dm_crypt_bio_destructor(struct bio *bio)
+{
struct dm_crypt_io *io = bio->bi_private;
struct crypt_config *cc = io->target->private;
bio_free(bio, cc->bs);
- }
+}
/*
* Generate a new unfragmented bio with the given size
@@ -441,33 +440,12 @@ static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned size)
return clone;
}
-static void crypt_free_buffer_pages(struct crypt_config *cc,
- struct bio *clone, unsigned int bytes)
+static void crypt_free_buffer_pages(struct crypt_config *cc, struct bio *clone)
{
- unsigned int i, start, end;
+ unsigned int i;
struct bio_vec *bv;
- /*
- * This is ugly, but Jens Axboe thinks that using bi_idx in the
- * endio function is too dangerous at the moment, so I calculate the
- * correct position using bi_vcnt and bi_size.
- * The bv_offset and bv_len fields might already be modified but we
- * know that we always allocated whole pages.
- * A fix to the bi_idx issue in the kernel is in the works, so
- * we will hopefully be able to revert to the cleaner solution soon.
- */
- i = clone->bi_vcnt - 1;
- bv = bio_iovec_idx(clone, i);
- end = (i << PAGE_SHIFT) + (bv->bv_offset + bv->bv_len) - clone->bi_size;
- start = end - bytes;
-
- start >>= PAGE_SHIFT;
- if (!clone->bi_size)
- end = clone->bi_vcnt;
- else
- end >>= PAGE_SHIFT;
-
- for (i = start; i < end; i++) {
+ for (i = 0; i < clone->bi_vcnt; i++) {
bv = bio_iovec_idx(clone, i);
BUG_ON(!bv->bv_page);
mempool_free(bv->bv_page, cc->page_pool);
@@ -479,7 +457,7 @@ static void crypt_free_buffer_pages(struct crypt_config *cc,
* One of the bios was finished. Check for completion of
* the whole request and correctly clean up the buffer.
*/
-static void dec_pending(struct dm_crypt_io *io, int error)
+static void crypt_dec_pending(struct dm_crypt_io *io, int error)
{
struct crypt_config *cc = (struct crypt_config *) io->target->private;
@@ -495,18 +473,36 @@ static void dec_pending(struct dm_crypt_io *io, int error)
}
/*
- * kcryptd:
+ * kcryptd/kcryptd_io:
*
* Needed because it would be very unwise to do decryption in an
* interrupt context.
+ *
+ * kcryptd performs the actual encryption or decryption.
+ *
+ * kcryptd_io performs the IO submission.
+ *
+ * They must be separated as otherwise the final stages could be
+ * starved by new requests which can block in the first stages due
+ * to memory allocation.
*/
-static struct workqueue_struct *_kcryptd_workqueue;
static void kcryptd_do_work(struct work_struct *work);
+static void kcryptd_do_crypt(struct work_struct *work);
static void kcryptd_queue_io(struct dm_crypt_io *io)
{
+ struct crypt_config *cc = io->target->private;
+
INIT_WORK(&io->work, kcryptd_do_work);
- queue_work(_kcryptd_workqueue, &io->work);
+ queue_work(cc->io_queue, &io->work);
+}
+
+static void kcryptd_queue_crypt(struct dm_crypt_io *io)
+{
+ struct crypt_config *cc = io->target->private;
+
+ INIT_WORK(&io->work, kcryptd_do_crypt);
+ queue_work(cc->crypt_queue, &io->work);
}
static void crypt_endio(struct bio *clone, int error)
@@ -519,7 +515,7 @@ static void crypt_endio(struct bio *clone, int error)
* free the processed pages
*/
if (!read_io) {
- crypt_free_buffer_pages(cc, clone, clone->bi_size);
+ crypt_free_buffer_pages(cc, clone);
goto out;
}
@@ -529,13 +525,12 @@ static void crypt_endio(struct bio *clone, int error)
}
bio_put(clone);
- io->post_process = 1;
- kcryptd_queue_io(io);
+ kcryptd_queue_crypt(io);
return;
out:
bio_put(clone);
- dec_pending(io, error);
+ crypt_dec_pending(io, error);
}
static void clone_init(struct dm_crypt_io *io, struct bio *clone)
@@ -565,7 +560,7 @@ static void process_read(struct dm_crypt_io *io)
*/
clone = bio_alloc_bioset(GFP_NOIO, bio_segments(base_bio), cc->bs);
if (unlikely(!clone)) {
- dec_pending(io, -ENOMEM);
+ crypt_dec_pending(io, -ENOMEM);
return;
}
@@ -600,7 +595,7 @@ static void process_write(struct dm_crypt_io *io)
while (remaining) {
clone = crypt_alloc_buffer(io, remaining);
if (unlikely(!clone)) {
- dec_pending(io, -ENOMEM);
+ crypt_dec_pending(io, -ENOMEM);
return;
}
@@ -608,9 +603,9 @@ static void process_write(struct dm_crypt_io *io)
ctx.idx_out = 0;
if (unlikely(crypt_convert(cc, &ctx) < 0)) {
- crypt_free_buffer_pages(cc, clone, clone->bi_size);
+ crypt_free_buffer_pages(cc, clone);
bio_put(clone);
- dec_pending(io, -EIO);
+ crypt_dec_pending(io, -EIO);
return;
}
@@ -645,17 +640,23 @@ static void process_read_endio(struct dm_crypt_io *io)
crypt_convert_init(cc, &ctx, io->base_bio, io->base_bio,
io->base_bio->bi_sector - io->target->begin, 0);
- dec_pending(io, crypt_convert(cc, &ctx));
+ crypt_dec_pending(io, crypt_convert(cc, &ctx));
}
static void kcryptd_do_work(struct work_struct *work)
{
struct dm_crypt_io *io = container_of(work, struct dm_crypt_io, work);
- if (io->post_process)
- process_read_endio(io);
- else if (bio_data_dir(io->base_bio) == READ)
+ if (bio_data_dir(io->base_bio) == READ)
process_read(io);
+}
+
+static void kcryptd_do_crypt(struct work_struct *work)
+{
+ struct dm_crypt_io *io = container_of(work, struct dm_crypt_io, work);
+
+ if (bio_data_dir(io->base_bio) == READ)
+ process_read_endio(io);
else
process_write(io);
}
@@ -711,7 +712,7 @@ static int crypt_set_key(struct crypt_config *cc, char *key)
cc->key_size = key_size; /* initial settings */
if ((!key_size && strcmp(key, "-")) ||
- (key_size && crypt_decode_key(cc->key, key, key_size) < 0))
+ (key_size && crypt_decode_key(cc->key, key, key_size) < 0))
return -EINVAL;
set_bit(DM_CRYPT_KEY_VALID, &cc->flags);
@@ -767,7 +768,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
if (crypt_set_key(cc, argv[1])) {
ti->error = "Error decoding key";
- goto bad1;
+ goto bad_cipher;
}
/* Compatiblity mode for old dm-crypt cipher strings */
@@ -778,19 +779,19 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
if (strcmp(chainmode, "ecb") && !ivmode) {
ti->error = "This chaining mode requires an IV mechanism";
- goto bad1;
+ goto bad_cipher;
}
- if (snprintf(cc->cipher, CRYPTO_MAX_ALG_NAME, "%s(%s)", chainmode,
- cipher) >= CRYPTO_MAX_ALG_NAME) {
+ if (snprintf(cc->cipher, CRYPTO_MAX_ALG_NAME, "%s(%s)",
+ chainmode, cipher) >= CRYPTO_MAX_ALG_NAME) {
ti->error = "Chain mode + cipher name is too long";
- goto bad1;
+ goto bad_cipher;
}
tfm = crypto_alloc_blkcipher(cc->cipher, 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(tfm)) {
ti->error = "Error allocating crypto tfm";
- goto bad1;
+ goto bad_cipher;
}
strcpy(cc->cipher, cipher);
@@ -814,18 +815,18 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
cc->iv_gen_ops = &crypt_iv_null_ops;
else {
ti->error = "Invalid IV mode";
- goto bad2;
+ goto bad_ivmode;
}
if (cc->iv_gen_ops && cc->iv_gen_ops->ctr &&
cc->iv_gen_ops->ctr(cc, ti, ivopts) < 0)
- goto bad2;
+ goto bad_ivmode;
cc->iv_size = crypto_blkcipher_ivsize(tfm);
if (cc->iv_size)
/* at least a 64 bit sector number should fit in our buffer */
cc->iv_size = max(cc->iv_size,
- (unsigned int)(sizeof(u64) / sizeof(u8)));
+ (unsigned int)(sizeof(u64) / sizeof(u8)));
else {
if (cc->iv_gen_ops) {
DMWARN("Selected cipher does not support IVs");
@@ -838,13 +839,13 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
cc->io_pool = mempool_create_slab_pool(MIN_IOS, _crypt_io_pool);
if (!cc->io_pool) {
ti->error = "Cannot allocate crypt io mempool";
- goto bad3;
+ goto bad_slab_pool;
}
cc->page_pool = mempool_create_page_pool(MIN_POOL_PAGES, 0);
if (!cc->page_pool) {
ti->error = "Cannot allocate page mempool";
- goto bad4;
+ goto bad_page_pool;
}
cc->bs = bioset_create(MIN_IOS, MIN_IOS);
@@ -855,25 +856,25 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
if (crypto_blkcipher_setkey(tfm, cc->key, key_size) < 0) {
ti->error = "Error setting key";
- goto bad5;
+ goto bad_device;
}
if (sscanf(argv[2], "%llu", &tmpll) != 1) {
ti->error = "Invalid iv_offset sector";
- goto bad5;
+ goto bad_device;
}
cc->iv_offset = tmpll;
if (sscanf(argv[4], "%llu", &tmpll) != 1) {
ti->error = "Invalid device sector";
- goto bad5;
+ goto bad_device;
}
cc->start = tmpll;
if (dm_get_device(ti, argv[3], cc->start, ti->len,
- dm_table_get_mode(ti->table), &cc->dev)) {
+ dm_table_get_mode(ti->table), &cc->dev)) {
ti->error = "Device lookup failed";
- goto bad5;
+ goto bad_device;
}
if (ivmode && cc->iv_gen_ops) {
@@ -882,27 +883,45 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
cc->iv_mode = kmalloc(strlen(ivmode) + 1, GFP_KERNEL);
if (!cc->iv_mode) {
ti->error = "Error kmallocing iv_mode string";
- goto bad5;
+ goto bad_ivmode_string;
}
strcpy(cc->iv_mode, ivmode);
} else
cc->iv_mode = NULL;
+ cc->io_queue = create_singlethread_workqueue("kcryptd_io");
+ if (!cc->io_queue) {
+ ti->error = "Couldn't create kcryptd io queue";
+ goto bad_io_queue;
+ }
+
+ cc->crypt_queue = create_singlethread_workqueue("kcryptd");
+ if (!cc->crypt_queue) {
+ ti->error = "Couldn't create kcryptd queue";
+ goto bad_crypt_queue;
+ }
+
ti->private = cc;
return 0;
-bad5:
+bad_crypt_queue:
+ destroy_workqueue(cc->io_queue);
+bad_io_queue:
+ kfree(cc->iv_mode);
+bad_ivmode_string:
+ dm_put_device(ti, cc->dev);
+bad_device:
bioset_free(cc->bs);
bad_bs:
mempool_destroy(cc->page_pool);
-bad4:
+bad_page_pool:
mempool_destroy(cc->io_pool);
-bad3:
+bad_slab_pool:
if (cc->iv_gen_ops && cc->iv_gen_ops->dtr)
cc->iv_gen_ops->dtr(cc);
-bad2:
+bad_ivmode:
crypto_free_blkcipher(tfm);
-bad1:
+bad_cipher:
/* Must zero key material before freeing */
memset(cc, 0, sizeof(*cc) + cc->key_size * sizeof(u8));
kfree(cc);
@@ -913,7 +932,8 @@ static void crypt_dtr(struct dm_target *ti)
{
struct crypt_config *cc = (struct crypt_config *) ti->private;
- flush_workqueue(_kcryptd_workqueue);
+ destroy_workqueue(cc->io_queue);
+ destroy_workqueue(cc->crypt_queue);
bioset_free(cc->bs);
mempool_destroy(cc->page_pool);
@@ -939,9 +959,13 @@ static int crypt_map(struct dm_target *ti, struct bio *bio,
io = mempool_alloc(cc->io_pool, GFP_NOIO);
io->target = ti;
io->base_bio = bio;
- io->error = io->post_process = 0;
+ io->error = 0;
atomic_set(&io->pending, 0);
- kcryptd_queue_io(io);
+
+ if (bio_data_dir(io->base_bio) == READ)
+ kcryptd_queue_io(io);
+ else
+ kcryptd_queue_crypt(io);
return DM_MAPIO_SUBMITTED;
}
@@ -1058,25 +1082,12 @@ static int __init dm_crypt_init(void)
if (!_crypt_io_pool)
return -ENOMEM;
- _kcryptd_workqueue = create_workqueue("kcryptd");
- if (!_kcryptd_workqueue) {
- r = -ENOMEM;
- DMERR("couldn't create kcryptd");
- goto bad1;
- }
-
r = dm_register_target(&crypt_target);
if (r < 0) {
DMERR("register failed %d", r);
- goto bad2;
+ kmem_cache_destroy(_crypt_io_pool);
}
- return 0;
-
-bad2:
- destroy_workqueue(_kcryptd_workqueue);
-bad1:
- kmem_cache_destroy(_crypt_io_pool);
return r;
}
@@ -1087,7 +1098,6 @@ static void __exit dm_crypt_exit(void)
if (r < 0)
DMERR("unregister failed %d", r);
- destroy_workqueue(_kcryptd_workqueue);
kmem_cache_destroy(_crypt_io_pool);
}
diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c
index 6928c136d3c5..bdd37f881c42 100644
--- a/drivers/md/dm-delay.c
+++ b/drivers/md/dm-delay.c
@@ -83,7 +83,7 @@ static struct bio *flush_delayed_bios(struct delay_c *dc, int flush_all)
struct dm_delay_info *delayed, *next;
unsigned long next_expires = 0;
int start_timer = 0;
- BIO_LIST(flush_bios);
+ struct bio_list flush_bios = { };
mutex_lock(&delayed_bios_lock);
list_for_each_entry_safe(delayed, next, &dc->delayed_bios, list) {
@@ -163,34 +163,32 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv)
goto bad;
}
- if (argc == 3) {
- dc->dev_write = NULL;
+ dc->dev_write = NULL;
+ if (argc == 3)
goto out;
- }
if (sscanf(argv[4], "%llu", &tmpll) != 1) {
ti->error = "Invalid write device sector";
- goto bad;
+ goto bad_dev_read;
}
dc->start_write = tmpll;
if (sscanf(argv[5], "%u", &dc->write_delay) != 1) {
ti->error = "Invalid write delay";
- goto bad;
+ goto bad_dev_read;
}
if (dm_get_device(ti, argv[3], dc->start_write, ti->len,
dm_table_get_mode(ti->table), &dc->dev_write)) {
ti->error = "Write device lookup failed";
- dm_put_device(ti, dc->dev_read);
- goto bad;
+ goto bad_dev_read;
}
out:
dc->delayed_pool = mempool_create_slab_pool(128, delayed_cache);
if (!dc->delayed_pool) {
DMERR("Couldn't create delayed bio pool.");
- goto bad;
+ goto bad_dev_write;
}
setup_timer(&dc->delay_timer, handle_delayed_timer, (unsigned long)dc);
@@ -203,6 +201,11 @@ out:
ti->private = dc;
return 0;
+bad_dev_write:
+ if (dc->dev_write)
+ dm_put_device(ti, dc->dev_write);
+bad_dev_read:
+ dm_put_device(ti, dc->dev_read);
bad:
kfree(dc);
return -EINVAL;
@@ -305,7 +308,7 @@ static int delay_status(struct dm_target *ti, status_type_t type,
(unsigned long long) dc->start_read,
dc->read_delay);
if (dc->dev_write)
- DMEMIT("%s %llu %u", dc->dev_write->name,
+ DMEMIT(" %s %llu %u", dc->dev_write->name,
(unsigned long long) dc->start_write,
dc->write_delay);
break;
diff --git a/drivers/md/dm-emc.c b/drivers/md/dm-emc.c
index 342517261ece..6b91b9ab1d41 100644
--- a/drivers/md/dm-emc.c
+++ b/drivers/md/dm-emc.c
@@ -81,7 +81,7 @@ static struct bio *get_failover_bio(struct dm_path *path, unsigned data_size)
}
if (bio_add_page(bio, page, data_size, 0) != data_size) {
- DMERR("get_failover_bio: alloc_page() failed.");
+ DMERR("get_failover_bio: bio_add_page() failed.");
__free_page(page);
bio_put(bio);
return NULL;
@@ -211,12 +211,10 @@ fail_path:
static struct emc_handler *alloc_emc_handler(void)
{
- struct emc_handler *h = kmalloc(sizeof(*h), GFP_KERNEL);
+ struct emc_handler *h = kzalloc(sizeof(*h), GFP_KERNEL);
- if (h) {
- memset(h, 0, sizeof(*h));
+ if (h)
spin_lock_init(&h->lock);
- }
return h;
}
diff --git a/drivers/md/dm-hw-handler.c b/drivers/md/dm-hw-handler.c
index baafaaba4d4b..2ee84d8aa0bf 100644
--- a/drivers/md/dm-hw-handler.c
+++ b/drivers/md/dm-hw-handler.c
@@ -91,12 +91,10 @@ void dm_put_hw_handler(struct hw_handler_type *hwht)
static struct hwh_internal *_alloc_hw_handler(struct hw_handler_type *hwht)
{
- struct hwh_internal *hwhi = kmalloc(sizeof(*hwhi), GFP_KERNEL);
+ struct hwh_internal *hwhi = kzalloc(sizeof(*hwhi), GFP_KERNEL);
- if (hwhi) {
- memset(hwhi, 0, sizeof(*hwhi));
+ if (hwhi)
hwhi->hwht = *hwht;
- }
return hwhi;
}
diff --git a/drivers/md/dm-hw-handler.h b/drivers/md/dm-hw-handler.h
index e0832e6fcf36..46809dcb121a 100644
--- a/drivers/md/dm-hw-handler.h
+++ b/drivers/md/dm-hw-handler.h
@@ -58,5 +58,6 @@ unsigned dm_scsi_err_handler(struct hw_handler *hwh, struct bio *bio);
#define MP_FAIL_PATH 1
#define MP_BYPASS_PG 2
#define MP_ERROR_IO 4 /* Don't retry this I/O */
+#define MP_RETRY 8
#endif
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index b441d82c338a..138200bf5e0b 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -700,7 +700,7 @@ static int dev_rename(struct dm_ioctl *param, size_t param_size)
int r;
char *new_name = (char *) param + param->data_start;
- if (new_name < (char *) (param + 1) ||
+ if (new_name < (char *) param->data ||
invalid_str(new_name, (void *) param + param_size)) {
DMWARN("Invalid new logical volume name supplied.");
return -EINVAL;
@@ -726,7 +726,7 @@ static int dev_set_geometry(struct dm_ioctl *param, size_t param_size)
if (!md)
return -ENXIO;
- if (geostr < (char *) (param + 1) ||
+ if (geostr < (char *) param->data ||
invalid_str(geostr, (void *) param + param_size)) {
DMWARN("Invalid geometry supplied.");
goto out;
@@ -1233,7 +1233,7 @@ static int target_message(struct dm_ioctl *param, size_t param_size)
if (r)
goto out;
- if (tmsg < (struct dm_target_msg *) (param + 1) ||
+ if (tmsg < (struct dm_target_msg *) param->data ||
invalid_str(tmsg->message, (void *) param + param_size)) {
DMWARN("Invalid target message parameters.");
r = -EINVAL;
@@ -1358,7 +1358,7 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl **param)
if (tmp.data_size < sizeof(tmp))
return -EINVAL;
- dmi = (struct dm_ioctl *) vmalloc(tmp.data_size);
+ dmi = vmalloc(tmp.data_size);
if (!dmi)
return -ENOMEM;
@@ -1515,3 +1515,35 @@ void dm_interface_exit(void)
dm_hash_exit();
}
+
+/**
+ * dm_copy_name_and_uuid - Copy mapped device name & uuid into supplied buffers
+ * @md: Pointer to mapped_device
+ * @name: Buffer (size DM_NAME_LEN) for name
+ * @uuid: Buffer (size DM_UUID_LEN) for uuid or empty string if uuid not defined
+ */
+int dm_copy_name_and_uuid(struct mapped_device *md, char *name, char *uuid)
+{
+ int r = 0;
+ struct hash_cell *hc;
+
+ if (!md)
+ return -ENXIO;
+
+ dm_get(md);
+ down_read(&_hash_lock);
+ hc = dm_get_mdptr(md);
+ if (!hc || hc->md != md) {
+ r = -ENXIO;
+ goto out;
+ }
+
+ strcpy(name, hc->name);
+ strcpy(uuid, hc->uuid ? : "");
+
+out:
+ up_read(&_hash_lock);
+ dm_put(md);
+
+ return r;
+}
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c
index a66428d860fe..072ee4353eab 100644
--- a/drivers/md/dm-log.c
+++ b/drivers/md/dm-log.c
@@ -696,7 +696,7 @@ static struct dirty_log_type _disk_type = {
.module = THIS_MODULE,
.ctr = disk_ctr,
.dtr = disk_dtr,
- .suspend = disk_flush,
+ .postsuspend = disk_flush,
.resume = disk_resume,
.get_region_size = core_get_region_size,
.is_clean = core_is_clean,
diff --git a/drivers/md/dm-log.h b/drivers/md/dm-log.h
index 86a301c8daf1..3fae87eb5963 100644
--- a/drivers/md/dm-log.h
+++ b/drivers/md/dm-log.h
@@ -32,7 +32,8 @@ struct dirty_log_type {
* There are times when we don't want the log to touch
* the disk.
*/
- int (*suspend)(struct dirty_log *log);
+ int (*presuspend)(struct dirty_log *log);
+ int (*postsuspend)(struct dirty_log *log);
int (*resume)(struct dirty_log *log);
/*
diff --git a/drivers/md/dm-mpath-hp-sw.c b/drivers/md/dm-mpath-hp-sw.c
new file mode 100644
index 000000000000..204bf42c9449
--- /dev/null
+++ b/drivers/md/dm-mpath-hp-sw.c
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2005 Mike Christie, All rights reserved.
+ * Copyright (C) 2007 Red Hat, Inc. All rights reserved.
+ * Authors: Mike Christie
+ * Dave Wysochanski
+ *
+ * This file is released under the GPL.
+ *
+ * This module implements the specific path activation code for
+ * HP StorageWorks and FSC FibreCat Asymmetric (Active/Passive)
+ * storage arrays.
+ * These storage arrays have controller-based failover, not
+ * LUN-based failover. However, LUN-based failover is the design
+ * of dm-multipath. Thus, this module is written for LUN-based failover.
+ */
+#include <linux/blkdev.h>
+#include <linux/list.h>
+#include <linux/types.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_dbg.h>
+
+#include "dm.h"
+#include "dm-hw-handler.h"
+
+#define DM_MSG_PREFIX "multipath hp-sw"
+#define DM_HP_HWH_NAME "hp-sw"
+#define DM_HP_HWH_VER "1.0.0"
+
+struct hp_sw_context {
+ unsigned char sense[SCSI_SENSE_BUFFERSIZE];
+};
+
+/*
+ * hp_sw_error_is_retryable - Is an HP-specific check condition retryable?
+ * @req: path activation request
+ *
+ * Examine error codes of request and determine whether the error is retryable.
+ * Some error codes are already retried by scsi-ml (see
+ * scsi_decide_disposition), but some HP specific codes are not.
+ * The intent of this routine is to supply the logic for the HP specific
+ * check conditions.
+ *
+ * Returns:
+ * 1 - command completed with retryable error
+ * 0 - command completed with non-retryable error
+ *
+ * Possible optimizations
+ * 1. More hardware-specific error codes
+ */
+static int hp_sw_error_is_retryable(struct request *req)
+{
+ /*
+ * NOT_READY is known to be retryable
+ * For now we just dump out the sense data and call it retryable
+ */
+ if (status_byte(req->errors) == CHECK_CONDITION)
+ __scsi_print_sense(DM_HP_HWH_NAME, req->sense, req->sense_len);
+
+ /*
+ * At this point we don't have complete information about all the error
+ * codes from this hardware, so we are just conservative and retry
+ * when in doubt.
+ */
+ return 1;
+}
+
+/*
+ * hp_sw_end_io - Completion handler for HP path activation.
+ * @req: path activation request
+ * @error: scsi-ml error
+ *
+ * Check sense data, free request structure, and notify dm that
+ * pg initialization has completed.
+ *
+ * Context: scsi-ml softirq
+ *
+ */
+static void hp_sw_end_io(struct request *req, int error)
+{
+ struct dm_path *path = req->end_io_data;
+ unsigned err_flags = 0;
+
+ if (!error) {
+ DMDEBUG("%s path activation command - success",
+ path->dev->name);
+ goto out;
+ }
+
+ if (hp_sw_error_is_retryable(req)) {
+ DMDEBUG("%s path activation command - retry",
+ path->dev->name);
+ err_flags = MP_RETRY;
+ goto out;
+ }
+
+ DMWARN("%s path activation fail - error=0x%x",
+ path->dev->name, error);
+ err_flags = MP_FAIL_PATH;
+
+out:
+ req->end_io_data = NULL;
+ __blk_put_request(req->q, req);
+ dm_pg_init_complete(path, err_flags);
+}
+
+/*
+ * hp_sw_get_request - Allocate an HP specific path activation request
+ * @path: path on which request will be sent (needed for request queue)
+ *
+ * The START command is used for path activation request.
+ * These arrays are controller-based failover, not LUN based.
+ * One START command issued to a single path will fail over all
+ * LUNs for the same controller.
+ *
+ * Possible optimizations
+ * 1. Make timeout configurable
+ * 2. Preallocate request
+ */
+static struct request *hp_sw_get_request(struct dm_path *path)
+{
+ struct request *req;
+ struct block_device *bdev = path->dev->bdev;
+ struct request_queue *q = bdev_get_queue(bdev);
+ struct hp_sw_context *h = path->hwhcontext;
+
+ req = blk_get_request(q, WRITE, GFP_NOIO);
+ if (!req)
+ goto out;
+
+ req->timeout = 60 * HZ;
+
+ req->errors = 0;
+ req->cmd_type = REQ_TYPE_BLOCK_PC;
+ req->cmd_flags |= REQ_FAILFAST | REQ_NOMERGE;
+ req->end_io_data = path;
+ req->sense = h->sense;
+ memset(req->sense, 0, SCSI_SENSE_BUFFERSIZE);
+
+ memset(&req->cmd, 0, BLK_MAX_CDB);
+ req->cmd[0] = START_STOP;
+ req->cmd[4] = 1;
+ req->cmd_len = COMMAND_SIZE(req->cmd[0]);
+
+out:
+ return req;
+}
+
+/*
+ * hp_sw_pg_init - HP path activation implementation.
+ * @hwh: hardware handler specific data
+ * @bypassed: unused; is the path group bypassed? (see dm-mpath.c)
+ * @path: path to send initialization command
+ *
+ * Send an HP-specific path activation command on 'path'.
+ * Do not try to optimize in any way, just send the activation command.
+ * More than one path activation command may be sent to the same controller.
+ * This seems to work fine for basic failover support.
+ *
+ * Possible optimizations
+ * 1. Detect an in-progress activation request and avoid submitting another one
+ * 2. Model the controller and only send a single activation request at a time
+ * 3. Determine the state of a path before sending an activation request
+ *
+ * Context: kmpathd (see process_queued_ios() in dm-mpath.c)
+ */
+static void hp_sw_pg_init(struct hw_handler *hwh, unsigned bypassed,
+ struct dm_path *path)
+{
+ struct request *req;
+ struct hp_sw_context *h;
+
+ path->hwhcontext = hwh->context;
+ h = hwh->context;
+
+ req = hp_sw_get_request(path);
+ if (!req) {
+ DMERR("%s path activation command - allocation fail",
+ path->dev->name);
+ goto retry;
+ }
+
+ DMDEBUG("%s path activation command - sent", path->dev->name);
+
+ blk_execute_rq_nowait(req->q, NULL, req, 1, hp_sw_end_io);
+ return;
+
+retry:
+ dm_pg_init_complete(path, MP_RETRY);
+}
+
+static int hp_sw_create(struct hw_handler *hwh, unsigned argc, char **argv)
+{
+ struct hp_sw_context *h;
+
+ h = kmalloc(sizeof(*h), GFP_KERNEL);
+ if (!h)
+ return -ENOMEM;
+
+ hwh->context = h;
+
+ return 0;
+}
+
+static void hp_sw_destroy(struct hw_handler *hwh)
+{
+ struct hp_sw_context *h = hwh->context;
+
+ kfree(h);
+}
+
+static struct hw_handler_type hp_sw_hwh = {
+ .name = DM_HP_HWH_NAME,
+ .module = THIS_MODULE,
+ .create = hp_sw_create,
+ .destroy = hp_sw_destroy,
+ .pg_init = hp_sw_pg_init,
+};
+
+static int __init hp_sw_init(void)
+{
+ int r;
+
+ r = dm_register_hw_handler(&hp_sw_hwh);
+ if (r < 0)
+ DMERR("register failed %d", r);
+ else
+ DMINFO("version " DM_HP_HWH_VER " loaded");
+
+ return r;
+}
+
+static void __exit hp_sw_exit(void)
+{
+ int r;
+
+ r = dm_unregister_hw_handler(&hp_sw_hwh);
+ if (r < 0)
+ DMERR("unregister failed %d", r);
+}
+
+module_init(hp_sw_init);
+module_exit(hp_sw_exit);
+
+MODULE_DESCRIPTION("DM Multipath HP StorageWorks / FSC FibreCat (A/P) support");
+MODULE_AUTHOR("Mike Christie, Dave Wysochanski <dm-devel@redhat.com>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DM_HP_HWH_VER);
diff --git a/drivers/md/dm-mpath-rdac.c b/drivers/md/dm-mpath-rdac.c
index 16b161345775..e04eb5c697fb 100644
--- a/drivers/md/dm-mpath-rdac.c
+++ b/drivers/md/dm-mpath-rdac.c
@@ -664,20 +664,21 @@ static struct hw_handler_type rdac_handler = {
static int __init rdac_init(void)
{
- int r = dm_register_hw_handler(&rdac_handler);
-
- if (r < 0) {
- DMERR("%s: register failed %d", RDAC_DM_HWH_NAME, r);
- return r;
- }
+ int r;
rdac_wkqd = create_singlethread_workqueue("rdac_wkqd");
if (!rdac_wkqd) {
DMERR("Failed to create workqueue rdac_wkqd.");
- dm_unregister_hw_handler(&rdac_handler);
return -ENOMEM;
}
+ r = dm_register_hw_handler(&rdac_handler);
+ if (r < 0) {
+ DMERR("%s: register failed %d", RDAC_DM_HWH_NAME, r);
+ destroy_workqueue(rdac_wkqd);
+ return r;
+ }
+
DMINFO("%s: version %s loaded", RDAC_DM_HWH_NAME, RDAC_DM_HWH_VER);
return 0;
}
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 31056abca89d..24b2b1e32fae 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -10,6 +10,7 @@
#include "dm-hw-handler.h"
#include "dm-bio-list.h"
#include "dm-bio-record.h"
+#include "dm-uevent.h"
#include <linux/ctype.h>
#include <linux/init.h>
@@ -75,6 +76,8 @@ struct multipath {
unsigned queue_io; /* Must we queue all I/O? */
unsigned queue_if_no_path; /* Queue I/O if last path fails? */
unsigned saved_queue_if_no_path;/* Saved state during suspension */
+ unsigned pg_init_retries; /* Number of times to retry pg_init */
+ unsigned pg_init_count; /* Number of times pg_init called */
struct work_struct process_queued_ios;
struct bio_list queued_ios;
@@ -225,6 +228,8 @@ static void __switch_pg(struct multipath *m, struct pgpath *pgpath)
m->pg_init_required = 0;
m->queue_io = 0;
}
+
+ m->pg_init_count = 0;
}
static int __choose_path_in_pg(struct multipath *m, struct priority_group *pg)
@@ -424,6 +429,7 @@ static void process_queued_ios(struct work_struct *work)
must_queue = 0;
if (m->pg_init_required && !m->pg_init_in_progress) {
+ m->pg_init_count++;
m->pg_init_required = 0;
m->pg_init_in_progress = 1;
init_required = 1;
@@ -689,9 +695,11 @@ static int parse_features(struct arg_set *as, struct multipath *m)
int r;
unsigned argc;
struct dm_target *ti = m->ti;
+ const char *param_name;
static struct param _params[] = {
- {0, 1, "invalid number of feature args"},
+ {0, 3, "invalid number of feature args"},
+ {1, 50, "pg_init_retries must be between 1 and 50"},
};
r = read_param(_params, shift(as), &argc, &ti->error);
@@ -701,12 +709,28 @@ static int parse_features(struct arg_set *as, struct multipath *m)
if (!argc)
return 0;
- if (!strnicmp(shift(as), MESG_STR("queue_if_no_path")))
- return queue_if_no_path(m, 1, 0);
- else {
+ do {
+ param_name = shift(as);
+ argc--;
+
+ if (!strnicmp(param_name, MESG_STR("queue_if_no_path"))) {
+ r = queue_if_no_path(m, 1, 0);
+ continue;
+ }
+
+ if (!strnicmp(param_name, MESG_STR("pg_init_retries")) &&
+ (argc >= 1)) {
+ r = read_param(_params + 1, shift(as),
+ &m->pg_init_retries, &ti->error);
+ argc--;
+ continue;
+ }
+
ti->error = "Unrecognised multipath feature request";
- return -EINVAL;
- }
+ r = -EINVAL;
+ } while (argc && !r);
+
+ return r;
}
static int multipath_ctr(struct dm_target *ti, unsigned int argc,
@@ -834,6 +858,9 @@ static int fail_path(struct pgpath *pgpath)
if (pgpath == m->current_pgpath)
m->current_pgpath = NULL;
+ dm_path_uevent(DM_UEVENT_PATH_FAILED, m->ti,
+ pgpath->path.dev->name, m->nr_valid_paths);
+
queue_work(kmultipathd, &m->trigger_event);
out:
@@ -873,6 +900,9 @@ static int reinstate_path(struct pgpath *pgpath)
if (!m->nr_valid_paths++ && m->queue_size)
queue_work(kmultipathd, &m->process_queued_ios);
+ dm_path_uevent(DM_UEVENT_PATH_REINSTATED, m->ti,
+ pgpath->path.dev->name, m->nr_valid_paths);
+
queue_work(kmultipathd, &m->trigger_event);
out:
@@ -976,6 +1006,26 @@ static int bypass_pg_num(struct multipath *m, const char *pgstr, int bypassed)
}
/*
+ * Should we retry pg_init immediately?
+ */
+static int pg_init_limit_reached(struct multipath *m, struct pgpath *pgpath)
+{
+ unsigned long flags;
+ int limit_reached = 0;
+
+ spin_lock_irqsave(&m->lock, flags);
+
+ if (m->pg_init_count <= m->pg_init_retries)
+ m->pg_init_required = 1;
+ else
+ limit_reached = 1;
+
+ spin_unlock_irqrestore(&m->lock, flags);
+
+ return limit_reached;
+}
+
+/*
* pg_init must call this when it has completed its initialisation
*/
void dm_pg_init_complete(struct dm_path *path, unsigned err_flags)
@@ -985,8 +1035,14 @@ void dm_pg_init_complete(struct dm_path *path, unsigned err_flags)
struct multipath *m = pg->m;
unsigned long flags;
- /* We insist on failing the path if the PG is already bypassed. */
- if (err_flags && pg->bypassed)
+ /*
+ * If requested, retry pg_init until maximum number of retries exceeded.
+ * If retry not requested and PG already bypassed, always fail the path.
+ */
+ if (err_flags & MP_RETRY) {
+ if (pg_init_limit_reached(m, pgpath))
+ err_flags |= MP_FAIL_PATH;
+ } else if (err_flags && pg->bypassed)
err_flags |= MP_FAIL_PATH;
if (err_flags & MP_FAIL_PATH)
@@ -996,7 +1052,7 @@ void dm_pg_init_complete(struct dm_path *path, unsigned err_flags)
bypass_pg(m, pg, 1);
spin_lock_irqsave(&m->lock, flags);
- if (err_flags) {
+ if (err_flags & ~MP_RETRY) {
m->current_pgpath = NULL;
m->current_pg = NULL;
} else if (!m->pg_init_required)
@@ -1148,11 +1204,15 @@ static int multipath_status(struct dm_target *ti, status_type_t type,
/* Features */
if (type == STATUSTYPE_INFO)
- DMEMIT("1 %u ", m->queue_size);
- else if (m->queue_if_no_path)
- DMEMIT("1 queue_if_no_path ");
- else
- DMEMIT("0 ");
+ DMEMIT("2 %u %u ", m->queue_size, m->pg_init_count);
+ else {
+ DMEMIT("%u ", m->queue_if_no_path +
+ (m->pg_init_retries > 0) * 2);
+ if (m->queue_if_no_path)
+ DMEMIT("queue_if_no_path ");
+ if (m->pg_init_retries)
+ DMEMIT("pg_init_retries %u ", m->pg_init_retries);
+ }
if (hwh->type && hwh->type->status)
sz += hwh->type->status(hwh, type, result + sz, maxlen - sz);
diff --git a/drivers/md/dm-path-selector.c b/drivers/md/dm-path-selector.c
index f10a0c89b3f4..ca1bb636a3e4 100644
--- a/drivers/md/dm-path-selector.c
+++ b/drivers/md/dm-path-selector.c
@@ -94,12 +94,10 @@ out:
static struct ps_internal *_alloc_path_selector(struct path_selector_type *pst)
{
- struct ps_internal *psi = kmalloc(sizeof(*psi), GFP_KERNEL);
+ struct ps_internal *psi = kzalloc(sizeof(*psi), GFP_KERNEL);
- if (psi) {
- memset(psi, 0, sizeof(*psi));
+ if (psi)
psi->pst = *pst;
- }
return psi;
}
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index d09ff15490a5..31123d4a6b9c 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -19,6 +19,7 @@
#include <linux/time.h>
#include <linux/vmalloc.h>
#include <linux/workqueue.h>
+#include <linux/log2.h>
#define DM_MSG_PREFIX "raid1"
#define DM_IO_PAGES 64
@@ -113,6 +114,7 @@ struct region {
* Mirror set structures.
*---------------------------------------------------------------*/
struct mirror {
+ struct mirror_set *ms;
atomic_t error_count;
struct dm_dev *dev;
sector_t offset;
@@ -974,6 +976,7 @@ static struct mirror_set *alloc_context(unsigned int nr_mirrors,
if (rh_init(&ms->rh, ms, dl, region_size, ms->nr_regions)) {
ti->error = "Error creating dirty region hash";
+ dm_io_client_destroy(ms->io_client);
kfree(ms);
return NULL;
}
@@ -994,7 +997,7 @@ static void free_context(struct mirror_set *ms, struct dm_target *ti,
static inline int _check_region_size(struct dm_target *ti, uint32_t size)
{
- return !(size % (PAGE_SIZE >> 9) || (size & (size - 1)) ||
+ return !(size % (PAGE_SIZE >> 9) || !is_power_of_2(size) ||
size > ti->len);
}
@@ -1015,6 +1018,7 @@ static int get_mirror(struct mirror_set *ms, struct dm_target *ti,
return -ENXIO;
}
+ ms->mirror[mirror].ms = ms;
ms->mirror[mirror].offset = offset;
return 0;
@@ -1163,16 +1167,14 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
ms->kmirrord_wq = create_singlethread_workqueue("kmirrord");
if (!ms->kmirrord_wq) {
DMERR("couldn't start kmirrord");
- free_context(ms, ti, m);
- return -ENOMEM;
+ r = -ENOMEM;
+ goto err_free_context;
}
INIT_WORK(&ms->kmirrord_work, do_mirror);
r = parse_features(ms, argc, argv, &args_used);
- if (r) {
- free_context(ms, ti, ms->nr_mirrors);
- return r;
- }
+ if (r)
+ goto err_destroy_wq;
argv += args_used;
argc -= args_used;
@@ -1188,19 +1190,22 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
if (argc) {
ti->error = "Too many mirror arguments";
- free_context(ms, ti, ms->nr_mirrors);
- return -EINVAL;
+ r = -EINVAL;
+ goto err_destroy_wq;
}
r = kcopyd_client_create(DM_IO_PAGES, &ms->kcopyd_client);
- if (r) {
- destroy_workqueue(ms->kmirrord_wq);
- free_context(ms, ti, ms->nr_mirrors);
- return r;
- }
+ if (r)
+ goto err_destroy_wq;
wake(ms);
return 0;
+
+err_destroy_wq:
+ destroy_workqueue(ms->kmirrord_wq);
+err_free_context:
+ free_context(ms, ti, ms->nr_mirrors);
+ return r;
}
static void mirror_dtr(struct dm_target *ti)
@@ -1302,7 +1307,7 @@ static void mirror_postsuspend(struct dm_target *ti)
wait_event(_kmirrord_recovery_stopped,
!atomic_read(&ms->rh.recovery_in_flight));
- if (log->type->suspend && log->type->suspend(log))
+ if (log->type->postsuspend && log->type->postsuspend(log))
/* FIXME: need better error handling */
DMWARN("log suspend failed");
}
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 98a633f3d6b0..cee16fadd9ee 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -17,6 +17,7 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
+#include <linux/log2.h>
#include "dm-snap.h"
#include "dm-bio-list.h"
@@ -415,7 +416,7 @@ static int set_chunk_size(struct dm_snapshot *s, const char *chunk_size_arg,
chunk_size = round_up(chunk_size, PAGE_SIZE >> 9);
/* Check chunk_size is a power of 2 */
- if (chunk_size & (chunk_size - 1)) {
+ if (!is_power_of_2(chunk_size)) {
*error = "Chunk size is not a power of 2";
return -EINVAL;
}
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index 51f5e0760012..969944a8aba2 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -11,6 +11,7 @@
#include <linux/blkdev.h>
#include <linux/bio.h>
#include <linux/slab.h>
+#include <linux/log2.h>
#define DM_MSG_PREFIX "striped"
@@ -99,7 +100,7 @@ static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv)
/*
* chunk_size is a power of two
*/
- if (!chunk_size || (chunk_size & (chunk_size - 1)) ||
+ if (!is_power_of_2(chunk_size) ||
(chunk_size < (PAGE_SIZE >> SECTOR_SHIFT))) {
ti->error = "Invalid chunk size";
return -EINVAL;
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 2bcde5798b5a..e298d8d11f24 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -102,6 +102,8 @@ static void combine_restrictions_low(struct io_restrictions *lhs,
lhs->seg_boundary_mask =
min_not_zero(lhs->seg_boundary_mask, rhs->seg_boundary_mask);
+ lhs->bounce_pfn = min_not_zero(lhs->bounce_pfn, rhs->bounce_pfn);
+
lhs->no_cluster |= rhs->no_cluster;
}
@@ -213,12 +215,11 @@ static int alloc_targets(struct dm_table *t, unsigned int num)
int dm_table_create(struct dm_table **result, int mode,
unsigned num_targets, struct mapped_device *md)
{
- struct dm_table *t = kmalloc(sizeof(*t), GFP_KERNEL);
+ struct dm_table *t = kzalloc(sizeof(*t), GFP_KERNEL);
if (!t)
return -ENOMEM;
- memset(t, 0, sizeof(*t));
INIT_LIST_HEAD(&t->devices);
atomic_set(&t->holders, 1);
@@ -567,6 +568,8 @@ void dm_set_device_limits(struct dm_target *ti, struct block_device *bdev)
min_not_zero(rs->seg_boundary_mask,
q->seg_boundary_mask);
+ rs->bounce_pfn = min_not_zero(rs->bounce_pfn, q->bounce_pfn);
+
rs->no_cluster |= !test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
}
EXPORT_SYMBOL_GPL(dm_set_device_limits);
@@ -708,6 +711,8 @@ static void check_for_valid_limits(struct io_restrictions *rs)
rs->max_segment_size = MAX_SEGMENT_SIZE;
if (!rs->seg_boundary_mask)
rs->seg_boundary_mask = -1;
+ if (!rs->bounce_pfn)
+ rs->bounce_pfn = -1;
}
int dm_table_add_target(struct dm_table *t, const char *type,
@@ -892,6 +897,7 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q)
q->hardsect_size = t->limits.hardsect_size;
q->max_segment_size = t->limits.max_segment_size;
q->seg_boundary_mask = t->limits.seg_boundary_mask;
+ q->bounce_pfn = t->limits.bounce_pfn;
if (t->limits.no_cluster)
q->queue_flags &= ~(1 << QUEUE_FLAG_CLUSTER);
else
@@ -994,38 +1000,10 @@ void dm_table_unplug_all(struct dm_table *t)
struct dm_dev *dd = list_entry(d, struct dm_dev, list);
struct request_queue *q = bdev_get_queue(dd->bdev);
- if (q->unplug_fn)
- q->unplug_fn(q);
+ blk_unplug(q);
}
}
-int dm_table_flush_all(struct dm_table *t)
-{
- struct list_head *d, *devices = dm_table_get_devices(t);
- int ret = 0;
- unsigned i;
-
- for (i = 0; i < t->num_targets; i++)
- if (t->targets[i].type->flush)
- t->targets[i].type->flush(&t->targets[i]);
-
- for (d = devices->next; d != devices; d = d->next) {
- struct dm_dev *dd = list_entry(d, struct dm_dev, list);
- struct request_queue *q = bdev_get_queue(dd->bdev);
- int err;
-
- if (!q->issue_flush_fn)
- err = -EOPNOTSUPP;
- else
- err = q->issue_flush_fn(q, dd->bdev->bd_disk, NULL);
-
- if (!ret)
- ret = err;
- }
-
- return ret;
-}
-
struct mapped_device *dm_table_get_md(struct dm_table *t)
{
dm_get(t->md);
@@ -1043,4 +1021,3 @@ EXPORT_SYMBOL(dm_table_get_md);
EXPORT_SYMBOL(dm_table_put);
EXPORT_SYMBOL(dm_table_get);
EXPORT_SYMBOL(dm_table_unplug_all);
-EXPORT_SYMBOL(dm_table_flush_all);
diff --git a/drivers/md/dm-target.c b/drivers/md/dm-target.c
index 477a041a41cf..835cf95b857f 100644
--- a/drivers/md/dm-target.c
+++ b/drivers/md/dm-target.c
@@ -88,12 +88,10 @@ void dm_put_target_type(struct target_type *t)
static struct tt_internal *alloc_target(struct target_type *t)
{
- struct tt_internal *ti = kmalloc(sizeof(*ti), GFP_KERNEL);
+ struct tt_internal *ti = kzalloc(sizeof(*ti), GFP_KERNEL);
- if (ti) {
- memset(ti, 0, sizeof(*ti));
+ if (ti)
ti->tt = *t;
- }
return ti;
}
diff --git a/drivers/md/dm-uevent.c b/drivers/md/dm-uevent.c
new file mode 100644
index 000000000000..50377e5dc2a3
--- /dev/null
+++ b/drivers/md/dm-uevent.c
@@ -0,0 +1,222 @@
+/*
+ * Device Mapper Uevent Support (dm-uevent)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright IBM Corporation, 2007
+ * Author: Mike Anderson <andmike@linux.vnet.ibm.com>
+ */
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/kobject.h>
+#include <linux/dm-ioctl.h>
+
+#include "dm.h"
+#include "dm-uevent.h"
+
+#define DM_MSG_PREFIX "uevent"
+
+static const struct {
+ enum dm_uevent_type type;
+ enum kobject_action action;
+ char *name;
+} _dm_uevent_type_names[] = {
+ {DM_UEVENT_PATH_FAILED, KOBJ_CHANGE, "PATH_FAILED"},
+ {DM_UEVENT_PATH_REINSTATED, KOBJ_CHANGE, "PATH_REINSTATED"},
+};
+
+static struct kmem_cache *_dm_event_cache;
+
+struct dm_uevent {
+ struct mapped_device *md;
+ enum kobject_action action;
+ struct kobj_uevent_env ku_env;
+ struct list_head elist;
+ char name[DM_NAME_LEN];
+ char uuid[DM_UUID_LEN];
+};
+
+static void dm_uevent_free(struct dm_uevent *event)
+{
+ kmem_cache_free(_dm_event_cache, event);
+}
+
+static struct dm_uevent *dm_uevent_alloc(struct mapped_device *md)
+{
+ struct dm_uevent *event;
+
+ event = kmem_cache_zalloc(_dm_event_cache, GFP_ATOMIC);
+ if (!event)
+ return NULL;
+
+ INIT_LIST_HEAD(&event->elist);
+ event->md = md;
+
+ return event;
+}
+
+static struct dm_uevent *dm_build_path_uevent(struct mapped_device *md,
+ struct dm_target *ti,
+ enum kobject_action action,
+ const char *dm_action,
+ const char *path,
+ unsigned nr_valid_paths)
+{
+ struct dm_uevent *event;
+
+ event = dm_uevent_alloc(md);
+ if (!event) {
+ DMERR("%s: dm_uevent_alloc() failed", __FUNCTION__);
+ goto err_nomem;
+ }
+
+ event->action = action;
+
+ if (add_uevent_var(&event->ku_env, "DM_TARGET=%s", ti->type->name)) {
+ DMERR("%s: add_uevent_var() for DM_TARGET failed",
+ __FUNCTION__);
+ goto err_add;
+ }
+
+ if (add_uevent_var(&event->ku_env, "DM_ACTION=%s", dm_action)) {
+ DMERR("%s: add_uevent_var() for DM_ACTION failed",
+ __FUNCTION__);
+ goto err_add;
+ }
+
+ if (add_uevent_var(&event->ku_env, "DM_SEQNUM=%u",
+ dm_next_uevent_seq(md))) {
+ DMERR("%s: add_uevent_var() for DM_SEQNUM failed",
+ __FUNCTION__);
+ goto err_add;
+ }
+
+ if (add_uevent_var(&event->ku_env, "DM_PATH=%s", path)) {
+ DMERR("%s: add_uevent_var() for DM_PATH failed", __FUNCTION__);
+ goto err_add;
+ }
+
+ if (add_uevent_var(&event->ku_env, "DM_NR_VALID_PATHS=%d",
+ nr_valid_paths)) {
+ DMERR("%s: add_uevent_var() for DM_NR_VALID_PATHS failed",
+ __FUNCTION__);
+ goto err_add;
+ }
+
+ return event;
+
+err_add:
+ dm_uevent_free(event);
+err_nomem:
+ return ERR_PTR(-ENOMEM);
+}
+
+/**
+ * dm_send_uevents - send uevents for given list
+ *
+ * @events: list of events to send
+ * @kobj: kobject generating event
+ *
+ */
+void dm_send_uevents(struct list_head *events, struct kobject *kobj)
+{
+ int r;
+ struct dm_uevent *event, *next;
+
+ list_for_each_entry_safe(event, next, events, elist) {
+ list_del_init(&event->elist);
+
+ /*
+ * Need to call dm_copy_name_and_uuid from here for now.
+ * Context of previous var adds and locking used for
+ * hash_cell not compatable.
+ */
+ if (dm_copy_name_and_uuid(event->md, event->name,
+ event->uuid)) {
+ DMERR("%s: dm_copy_name_and_uuid() failed",
+ __FUNCTION__);
+ goto uevent_free;
+ }
+
+ if (add_uevent_var(&event->ku_env, "DM_NAME=%s", event->name)) {
+ DMERR("%s: add_uevent_var() for DM_NAME failed",
+ __FUNCTION__);
+ goto uevent_free;
+ }
+
+ if (add_uevent_var(&event->ku_env, "DM_UUID=%s", event->uuid)) {
+ DMERR("%s: add_uevent_var() for DM_UUID failed",
+ __FUNCTION__);
+ goto uevent_free;
+ }
+
+ r = kobject_uevent_env(kobj, event->action, event->ku_env.envp);
+ if (r)
+ DMERR("%s: kobject_uevent_env failed", __FUNCTION__);
+uevent_free:
+ dm_uevent_free(event);
+ }
+}
+EXPORT_SYMBOL_GPL(dm_send_uevents);
+
+/**
+ * dm_path_uevent - called to create a new path event and queue it
+ *
+ * @event_type: path event type enum
+ * @ti: pointer to a dm_target
+ * @path: string containing pathname
+ * @nr_valid_paths: number of valid paths remaining
+ *
+ */
+void dm_path_uevent(enum dm_uevent_type event_type, struct dm_target *ti,
+ const char *path, unsigned nr_valid_paths)
+{
+ struct mapped_device *md = dm_table_get_md(ti->table);
+ struct dm_uevent *event;
+
+ if (event_type >= ARRAY_SIZE(_dm_uevent_type_names)) {
+ DMERR("%s: Invalid event_type %d", __FUNCTION__, event_type);
+ goto out;
+ }
+
+ event = dm_build_path_uevent(md, ti,
+ _dm_uevent_type_names[event_type].action,
+ _dm_uevent_type_names[event_type].name,
+ path, nr_valid_paths);
+ if (IS_ERR(event))
+ goto out;
+
+ dm_uevent_add(md, &event->elist);
+
+out:
+ dm_put(md);
+}
+EXPORT_SYMBOL_GPL(dm_path_uevent);
+
+int dm_uevent_init(void)
+{
+ _dm_event_cache = KMEM_CACHE(dm_uevent, 0);
+ if (!_dm_event_cache)
+ return -ENOMEM;
+
+ DMINFO("version 1.0.3");
+
+ return 0;
+}
+
+void dm_uevent_exit(void)
+{
+ kmem_cache_destroy(_dm_event_cache);
+}
diff --git a/drivers/md/dm-uevent.h b/drivers/md/dm-uevent.h
new file mode 100644
index 000000000000..2eccc8bd671a
--- /dev/null
+++ b/drivers/md/dm-uevent.h
@@ -0,0 +1,59 @@
+/*
+ * Device Mapper Uevent Support
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright IBM Corporation, 2007
+ * Author: Mike Anderson <andmike@linux.vnet.ibm.com>
+ */
+#ifndef DM_UEVENT_H
+#define DM_UEVENT_H
+
+enum dm_uevent_type {
+ DM_UEVENT_PATH_FAILED,
+ DM_UEVENT_PATH_REINSTATED,
+};
+
+#ifdef CONFIG_DM_UEVENT
+
+extern int dm_uevent_init(void);
+extern void dm_uevent_exit(void);
+extern void dm_send_uevents(struct list_head *events, struct kobject *kobj);
+extern void dm_path_uevent(enum dm_uevent_type event_type,
+ struct dm_target *ti, const char *path,
+ unsigned nr_valid_paths);
+
+#else
+
+static inline int dm_uevent_init(void)
+{
+ return 0;
+}
+static inline void dm_uevent_exit(void)
+{
+}
+static inline void dm_send_uevents(struct list_head *events,
+ struct kobject *kobj)
+{
+}
+static inline void dm_path_uevent(enum dm_uevent_type event_type,
+ struct dm_target *ti, const char *path,
+ unsigned nr_valid_paths)
+{
+}
+
+#endif /* CONFIG_DM_UEVENT */
+
+#endif /* DM_UEVENT_H */
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 167765c47747..07cbbb8eb3e0 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -7,6 +7,7 @@
#include "dm.h"
#include "dm-bio-list.h"
+#include "dm-uevent.h"
#include <linux/init.h>
#include <linux/module.h>
@@ -112,6 +113,9 @@ struct mapped_device {
*/
atomic_t event_nr;
wait_queue_head_t eventq;
+ atomic_t uevent_seq;
+ struct list_head uevent_list;
+ spinlock_t uevent_lock; /* Protect access to uevent_list */
/*
* freeze/thaw support require holding onto a super block
@@ -143,11 +147,19 @@ static int __init local_init(void)
return -ENOMEM;
}
+ r = dm_uevent_init();
+ if (r) {
+ kmem_cache_destroy(_tio_cache);
+ kmem_cache_destroy(_io_cache);
+ return r;
+ }
+
_major = major;
r = register_blkdev(_major, _name);
if (r < 0) {
kmem_cache_destroy(_tio_cache);
kmem_cache_destroy(_io_cache);
+ dm_uevent_exit();
return r;
}
@@ -162,6 +174,7 @@ static void local_exit(void)
kmem_cache_destroy(_tio_cache);
kmem_cache_destroy(_io_cache);
unregister_blkdev(_major, _name);
+ dm_uevent_exit();
_major = 0;
@@ -751,15 +764,13 @@ static void __clone_and_map(struct clone_info *ci)
/*
* Split the bio into several clones.
*/
-static void __split_bio(struct mapped_device *md, struct bio *bio)
+static int __split_bio(struct mapped_device *md, struct bio *bio)
{
struct clone_info ci;
ci.map = dm_get_table(md);
- if (!ci.map) {
- bio_io_error(bio);
- return;
- }
+ if (unlikely(!ci.map))
+ return -EIO;
ci.md = md;
ci.bio = bio;
@@ -779,6 +790,8 @@ static void __split_bio(struct mapped_device *md, struct bio *bio)
/* drop the extra reference count */
dec_pending(ci.io, 0);
dm_table_put(ci.map);
+
+ return 0;
}
/*-----------------------------------------------------------------
* CRUD END
@@ -790,7 +803,7 @@ static void __split_bio(struct mapped_device *md, struct bio *bio)
*/
static int dm_request(struct request_queue *q, struct bio *bio)
{
- int r;
+ int r = -EIO;
int rw = bio_data_dir(bio);
struct mapped_device *md = q->queuedata;
@@ -815,18 +828,11 @@ static int dm_request(struct request_queue *q, struct bio *bio)
while (test_bit(DMF_BLOCK_IO, &md->flags)) {
up_read(&md->io_lock);
- if (bio_rw(bio) == READA) {
- bio_io_error(bio);
- return 0;
- }
+ if (bio_rw(bio) != READA)
+ r = queue_io(md, bio);
- r = queue_io(md, bio);
- if (r < 0) {
- bio_io_error(bio);
- return 0;
-
- } else if (r == 0)
- return 0; /* deferred successfully */
+ if (r <= 0)
+ goto out_req;
/*
* We're in a while loop, because someone could suspend
@@ -835,24 +841,14 @@ static int dm_request(struct request_queue *q, struct bio *bio)
down_read(&md->io_lock);
}
- __split_bio(md, bio);
+ r = __split_bio(md, bio);
up_read(&md->io_lock);
- return 0;
-}
-
-static int dm_flush_all(struct request_queue *q, struct gendisk *disk,
- sector_t *error_sector)
-{
- struct mapped_device *md = q->queuedata;
- struct dm_table *map = dm_get_table(md);
- int ret = -ENXIO;
- if (map) {
- ret = dm_table_flush_all(map);
- dm_table_put(map);
- }
+out_req:
+ if (r < 0)
+ bio_io_error(bio);
- return ret;
+ return 0;
}
static void dm_unplug_all(struct request_queue *q)
@@ -992,6 +988,9 @@ static struct mapped_device *alloc_dev(int minor)
atomic_set(&md->holders, 1);
atomic_set(&md->open_count, 0);
atomic_set(&md->event_nr, 0);
+ atomic_set(&md->uevent_seq, 0);
+ INIT_LIST_HEAD(&md->uevent_list);
+ spin_lock_init(&md->uevent_lock);
md->queue = blk_alloc_queue(GFP_KERNEL);
if (!md->queue)
@@ -1003,7 +1002,6 @@ static struct mapped_device *alloc_dev(int minor)
blk_queue_make_request(md->queue, dm_request);
blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY);
md->queue->unplug_fn = dm_unplug_all;
- md->queue->issue_flush_fn = dm_flush_all;
md->io_pool = mempool_create_slab_pool(MIN_IOS, _io_cache);
if (!md->io_pool)
@@ -1060,12 +1058,14 @@ static struct mapped_device *alloc_dev(int minor)
return NULL;
}
+static void unlock_fs(struct mapped_device *md);
+
static void free_dev(struct mapped_device *md)
{
int minor = md->disk->first_minor;
if (md->suspended_bdev) {
- thaw_bdev(md->suspended_bdev, NULL);
+ unlock_fs(md);
bdput(md->suspended_bdev);
}
mempool_destroy(md->tio_pool);
@@ -1089,8 +1089,16 @@ static void free_dev(struct mapped_device *md)
*/
static void event_callback(void *context)
{
+ unsigned long flags;
+ LIST_HEAD(uevents);
struct mapped_device *md = (struct mapped_device *) context;
+ spin_lock_irqsave(&md->uevent_lock, flags);
+ list_splice_init(&md->uevent_list, &uevents);
+ spin_unlock_irqrestore(&md->uevent_lock, flags);
+
+ dm_send_uevents(&uevents, &md->disk->kobj);
+
atomic_inc(&md->event_nr);
wake_up(&md->eventq);
}
@@ -1249,7 +1257,8 @@ static void __flush_deferred_io(struct mapped_device *md, struct bio *c)
while (c) {
n = c->bi_next;
c->bi_next = NULL;
- __split_bio(md, c);
+ if (__split_bio(md, c))
+ bio_io_error(c);
c = n;
}
}
@@ -1507,6 +1516,11 @@ out:
/*-----------------------------------------------------------------
* Event notification.
*---------------------------------------------------------------*/
+uint32_t dm_next_uevent_seq(struct mapped_device *md)
+{
+ return atomic_add_return(1, &md->uevent_seq);
+}
+
uint32_t dm_get_event_nr(struct mapped_device *md)
{
return atomic_read(&md->event_nr);
@@ -1518,6 +1532,15 @@ int dm_wait_event(struct mapped_device *md, int event_nr)
(event_nr != atomic_read(&md->event_nr)));
}
+void dm_uevent_add(struct mapped_device *md, struct list_head *elist)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&md->uevent_lock, flags);
+ list_add(elist, &md->uevent_list);
+ spin_unlock_irqrestore(&md->uevent_lock, flags);
+}
+
/*
* The gendisk is only valid as long as you have a reference
* count on 'md'.
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index 462ee652a890..4b3faa45277e 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -111,7 +111,6 @@ void dm_table_postsuspend_targets(struct dm_table *t);
int dm_table_resume_targets(struct dm_table *t);
int dm_table_any_congested(struct dm_table *t, int bdi_bits);
void dm_table_unplug_all(struct dm_table *t);
-int dm_table_flush_all(struct dm_table *t);
/*-----------------------------------------------------------------
* A registry of target types.
diff --git a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c
index 7e052378c47e..f3831f31223e 100644
--- a/drivers/md/kcopyd.c
+++ b/drivers/md/kcopyd.c
@@ -198,7 +198,7 @@ struct kcopyd_job {
* These fields are only used if the job has been split
* into more manageable parts.
*/
- struct semaphore lock;
+ struct mutex lock;
atomic_t sub_jobs;
sector_t progress;
};
@@ -456,7 +456,7 @@ static void segment_complete(int read_err,
sector_t count = 0;
struct kcopyd_job *job = (struct kcopyd_job *) context;
- down(&job->lock);
+ mutex_lock(&job->lock);
/* update the error */
if (read_err)
@@ -480,7 +480,7 @@ static void segment_complete(int read_err,
job->progress += count;
}
}
- up(&job->lock);
+ mutex_unlock(&job->lock);
if (count) {
int i;
@@ -562,7 +562,7 @@ int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from,
dispatch_job(job);
else {
- init_MUTEX(&job->lock);
+ mutex_init(&job->lock);
job->progress = 0;
split_job(job);
}
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index 550148770bb2..3dac1cfb8189 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -87,30 +87,10 @@ static void linear_unplug(struct request_queue *q)
for (i=0; i < mddev->raid_disks; i++) {
struct request_queue *r_queue = bdev_get_queue(conf->disks[i].rdev->bdev);
- if (r_queue->unplug_fn)
- r_queue->unplug_fn(r_queue);
+ blk_unplug(r_queue);
}
}
-static int linear_issue_flush(struct request_queue *q, struct gendisk *disk,
- sector_t *error_sector)
-{
- mddev_t *mddev = q->queuedata;
- linear_conf_t *conf = mddev_to_conf(mddev);
- int i, ret = 0;
-
- for (i=0; i < mddev->raid_disks && ret == 0; i++) {
- struct block_device *bdev = conf->disks[i].rdev->bdev;
- struct request_queue *r_queue = bdev_get_queue(bdev);
-
- if (!r_queue->issue_flush_fn)
- ret = -EOPNOTSUPP;
- else
- ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
- }
- return ret;
-}
-
static int linear_congested(void *data, int bits)
{
mddev_t *mddev = data;
@@ -279,7 +259,6 @@ static int linear_run (mddev_t *mddev)
blk_queue_merge_bvec(mddev->queue, linear_mergeable_bvec);
mddev->queue->unplug_fn = linear_unplug;
- mddev->queue->issue_flush_fn = linear_issue_flush;
mddev->queue->backing_dev_info.congested_fn = linear_congested;
mddev->queue->backing_dev_info.congested_data = mddev;
return 0;
diff --git a/drivers/md/md.c b/drivers/md/md.c
index acf1b81b47cb..cef9ebd5a046 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -2714,7 +2714,7 @@ action_show(mddev_t *mddev, char *page)
{
char *type = "idle";
if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
- test_bit(MD_RECOVERY_NEEDED, &mddev->recovery)) {
+ (!mddev->ro && test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))) {
if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
type = "reshape";
else if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
@@ -2833,6 +2833,12 @@ sync_max_store(mddev_t *mddev, const char *buf, size_t len)
static struct md_sysfs_entry md_sync_max =
__ATTR(sync_speed_max, S_IRUGO|S_IWUSR, sync_max_show, sync_max_store);
+static ssize_t
+degraded_show(mddev_t *mddev, char *page)
+{
+ return sprintf(page, "%d\n", mddev->degraded);
+}
+static struct md_sysfs_entry md_degraded = __ATTR_RO(degraded);
static ssize_t
sync_speed_show(mddev_t *mddev, char *page)
@@ -2976,6 +2982,7 @@ static struct attribute *md_redundancy_attrs[] = {
&md_suspend_lo.attr,
&md_suspend_hi.attr,
&md_bitmap.attr,
+ &md_degraded.attr,
NULL,
};
static struct attribute_group md_redundancy_group = {
@@ -3463,7 +3470,6 @@ static int do_md_stop(mddev_t * mddev, int mode)
mddev->pers->stop(mddev);
mddev->queue->merge_bvec_fn = NULL;
mddev->queue->unplug_fn = NULL;
- mddev->queue->issue_flush_fn = NULL;
mddev->queue->backing_dev_info.congested_fn = NULL;
if (mddev->pers->sync_request)
sysfs_remove_group(&mddev->kobj, &md_redundancy_group);
@@ -4711,7 +4717,7 @@ mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev,
void md_unregister_thread(mdk_thread_t *thread)
{
- dprintk("interrupting MD-thread pid %d\n", thread->tsk->pid);
+ dprintk("interrupting MD-thread pid %d\n", task_pid_nr(thread->tsk));
kthread_stop(thread->tsk);
kfree(thread);
@@ -5439,7 +5445,7 @@ void md_do_sync(mddev_t *mddev)
* about not overloading the IO subsystem. (things like an
* e2fsck being done on the RAID array should execute fast)
*/
- mddev->queue->unplug_fn(mddev->queue);
+ blk_unplug(mddev->queue);
cond_resched();
currspeed = ((unsigned long)(io_sectors-mddev->resync_mark_cnt))/2
@@ -5458,7 +5464,7 @@ void md_do_sync(mddev_t *mddev)
* this also signals 'finished resyncing' to md_stop
*/
out:
- mddev->queue->unplug_fn(mddev->queue);
+ blk_unplug(mddev->queue);
wait_event(mddev->recovery_wait, !atomic_read(&mddev->recovery_active));
@@ -5771,26 +5777,47 @@ static int __init md_init(void)
* Searches all registered partitions for autorun RAID arrays
* at boot time.
*/
-static dev_t detected_devices[128];
-static int dev_cnt;
+
+static LIST_HEAD(all_detected_devices);
+struct detected_devices_node {
+ struct list_head list;
+ dev_t dev;
+};
void md_autodetect_dev(dev_t dev)
{
- if (dev_cnt >= 0 && dev_cnt < 127)
- detected_devices[dev_cnt++] = dev;
+ struct detected_devices_node *node_detected_dev;
+
+ node_detected_dev = kzalloc(sizeof(*node_detected_dev), GFP_KERNEL);
+ if (node_detected_dev) {
+ node_detected_dev->dev = dev;
+ list_add_tail(&node_detected_dev->list, &all_detected_devices);
+ } else {
+ printk(KERN_CRIT "md: md_autodetect_dev: kzalloc failed"
+ ", skipping dev(%d,%d)\n", MAJOR(dev), MINOR(dev));
+ }
}
static void autostart_arrays(int part)
{
mdk_rdev_t *rdev;
- int i;
+ struct detected_devices_node *node_detected_dev;
+ dev_t dev;
+ int i_scanned, i_passed;
- printk(KERN_INFO "md: Autodetecting RAID arrays.\n");
+ i_scanned = 0;
+ i_passed = 0;
- for (i = 0; i < dev_cnt; i++) {
- dev_t dev = detected_devices[i];
+ printk(KERN_INFO "md: Autodetecting RAID arrays.\n");
+ while (!list_empty(&all_detected_devices) && i_scanned < INT_MAX) {
+ i_scanned++;
+ node_detected_dev = list_entry(all_detected_devices.next,
+ struct detected_devices_node, list);
+ list_del(&node_detected_dev->list);
+ dev = node_detected_dev->dev;
+ kfree(node_detected_dev);
rdev = md_import_device(dev,0, 90);
if (IS_ERR(rdev))
continue;
@@ -5800,8 +5827,11 @@ static void autostart_arrays(int part)
continue;
}
list_add(&rdev->same_set, &pending_raid_disks);
+ i_passed++;
}
- dev_cnt = 0;
+
+ printk(KERN_INFO "md: Scanned %d and added %d devices.\n",
+ i_scanned, i_passed);
autorun_devices(part);
}
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index f2a63f394ad9..eb631ebed686 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -125,8 +125,7 @@ static void unplug_slaves(mddev_t *mddev)
atomic_inc(&rdev->nr_pending);
rcu_read_unlock();
- if (r_queue->unplug_fn)
- r_queue->unplug_fn(r_queue);
+ blk_unplug(r_queue);
rdev_dec_pending(rdev, mddev);
rcu_read_lock();
@@ -194,35 +193,6 @@ static void multipath_status (struct seq_file *seq, mddev_t *mddev)
seq_printf (seq, "]");
}
-static int multipath_issue_flush(struct request_queue *q, struct gendisk *disk,
- sector_t *error_sector)
-{
- mddev_t *mddev = q->queuedata;
- multipath_conf_t *conf = mddev_to_conf(mddev);
- int i, ret = 0;
-
- rcu_read_lock();
- for (i=0; i<mddev->raid_disks && ret == 0; i++) {
- mdk_rdev_t *rdev = rcu_dereference(conf->multipaths[i].rdev);
- if (rdev && !test_bit(Faulty, &rdev->flags)) {
- struct block_device *bdev = rdev->bdev;
- struct request_queue *r_queue = bdev_get_queue(bdev);
-
- if (!r_queue->issue_flush_fn)
- ret = -EOPNOTSUPP;
- else {
- atomic_inc(&rdev->nr_pending);
- rcu_read_unlock();
- ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk,
- error_sector);
- rdev_dec_pending(rdev, mddev);
- rcu_read_lock();
- }
- }
- }
- rcu_read_unlock();
- return ret;
-}
static int multipath_congested(void *data, int bits)
{
mddev_t *mddev = data;
@@ -527,7 +497,6 @@ static int multipath_run (mddev_t *mddev)
mddev->array_size = mddev->size;
mddev->queue->unplug_fn = multipath_unplug;
- mddev->queue->issue_flush_fn = multipath_issue_flush;
mddev->queue->backing_dev_info.congested_fn = multipath_congested;
mddev->queue->backing_dev_info.congested_data = mddev;
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index ef0da2d84959..f8e591708d1f 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -35,31 +35,10 @@ static void raid0_unplug(struct request_queue *q)
for (i=0; i<mddev->raid_disks; i++) {
struct request_queue *r_queue = bdev_get_queue(devlist[i]->bdev);
- if (r_queue->unplug_fn)
- r_queue->unplug_fn(r_queue);
+ blk_unplug(r_queue);
}
}
-static int raid0_issue_flush(struct request_queue *q, struct gendisk *disk,
- sector_t *error_sector)
-{
- mddev_t *mddev = q->queuedata;
- raid0_conf_t *conf = mddev_to_conf(mddev);
- mdk_rdev_t **devlist = conf->strip_zone[0].dev;
- int i, ret = 0;
-
- for (i=0; i<mddev->raid_disks && ret == 0; i++) {
- struct block_device *bdev = devlist[i]->bdev;
- struct request_queue *r_queue = bdev_get_queue(bdev);
-
- if (!r_queue->issue_flush_fn)
- ret = -EOPNOTSUPP;
- else
- ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
- }
- return ret;
-}
-
static int raid0_congested(void *data, int bits)
{
mddev_t *mddev = data;
@@ -250,7 +229,6 @@ static int create_strip_zones (mddev_t *mddev)
mddev->queue->unplug_fn = raid0_unplug;
- mddev->queue->issue_flush_fn = raid0_issue_flush;
mddev->queue->backing_dev_info.congested_fn = raid0_congested;
mddev->queue->backing_dev_info.congested_data = mddev;
@@ -493,7 +471,7 @@ bad_map:
bio_io_error(bio);
return 0;
}
-
+
static void raid0_status (struct seq_file *seq, mddev_t *mddev)
{
#undef MD_DEBUG
@@ -501,18 +479,18 @@ static void raid0_status (struct seq_file *seq, mddev_t *mddev)
int j, k, h;
char b[BDEVNAME_SIZE];
raid0_conf_t *conf = mddev_to_conf(mddev);
-
+
h = 0;
for (j = 0; j < conf->nr_strip_zones; j++) {
seq_printf(seq, " z%d", j);
if (conf->hash_table[h] == conf->strip_zone+j)
- seq_printf("(h%d)", h++);
+ seq_printf(seq, "(h%d)", h++);
seq_printf(seq, "=[");
for (k = 0; k < conf->strip_zone[j].nb_dev; k++)
- seq_printf (seq, "%s/", bdevname(
+ seq_printf(seq, "%s/", bdevname(
conf->strip_zone[j].dev[k]->bdev,b));
- seq_printf (seq, "] zo=%d do=%d s=%d\n",
+ seq_printf(seq, "] zo=%d do=%d s=%d\n",
conf->strip_zone[j].zone_offset,
conf->strip_zone[j].dev_offset,
conf->strip_zone[j].size);
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 6d03bea6fa58..4a69c416e045 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -9,7 +9,7 @@
*
* Better read-balancing code written by Mika Kuoppala <miku@iki.fi>, 2000
*
- * Fixes to reconstruction by Jakob Østergaard" <jakob@ostenfeld.dk>
+ * Fixes to reconstruction by Jakob Østergaard" <jakob@ostenfeld.dk>
* Various fixes by Neil Brown <neilb@cse.unsw.edu.au>
*
* Changes by Peter T. Breuer <ptb@it.uc3m.es> 31/1/2003 to support
@@ -549,8 +549,7 @@ static void unplug_slaves(mddev_t *mddev)
atomic_inc(&rdev->nr_pending);
rcu_read_unlock();
- if (r_queue->unplug_fn)
- r_queue->unplug_fn(r_queue);
+ blk_unplug(r_queue);
rdev_dec_pending(rdev, mddev);
rcu_read_lock();
@@ -567,36 +566,6 @@ static void raid1_unplug(struct request_queue *q)
md_wakeup_thread(mddev->thread);
}
-static int raid1_issue_flush(struct request_queue *q, struct gendisk *disk,
- sector_t *error_sector)
-{
- mddev_t *mddev = q->queuedata;
- conf_t *conf = mddev_to_conf(mddev);
- int i, ret = 0;
-
- rcu_read_lock();
- for (i=0; i<mddev->raid_disks && ret == 0; i++) {
- mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
- if (rdev && !test_bit(Faulty, &rdev->flags)) {
- struct block_device *bdev = rdev->bdev;
- struct request_queue *r_queue = bdev_get_queue(bdev);
-
- if (!r_queue->issue_flush_fn)
- ret = -EOPNOTSUPP;
- else {
- atomic_inc(&rdev->nr_pending);
- rcu_read_unlock();
- ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk,
- error_sector);
- rdev_dec_pending(rdev, mddev);
- rcu_read_lock();
- }
- }
- }
- rcu_read_unlock();
- return ret;
-}
-
static int raid1_congested(void *data, int bits)
{
mddev_t *mddev = data;
@@ -1244,7 +1213,8 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
j = 0;
if (j >= 0)
mddev->resync_mismatches += r1_bio->sectors;
- if (j < 0 || test_bit(MD_RECOVERY_CHECK, &mddev->recovery)) {
+ if (j < 0 || (test_bit(MD_RECOVERY_CHECK, &mddev->recovery)
+ && test_bit(BIO_UPTODATE, &sbio->bi_flags))) {
sbio->bi_end_io = NULL;
rdev_dec_pending(conf->mirrors[i].rdev, mddev);
} else {
@@ -1997,7 +1967,6 @@ static int run(mddev_t *mddev)
mddev->array_size = mddev->size;
mddev->queue->unplug_fn = raid1_unplug;
- mddev->queue->issue_flush_fn = raid1_issue_flush;
mddev->queue->backing_dev_info.congested_fn = raid1_congested;
mddev->queue->backing_dev_info.congested_data = mddev;
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 25a96c42bdb0..5cdcc9386200 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -593,8 +593,7 @@ static void unplug_slaves(mddev_t *mddev)
atomic_inc(&rdev->nr_pending);
rcu_read_unlock();
- if (r_queue->unplug_fn)
- r_queue->unplug_fn(r_queue);
+ blk_unplug(r_queue);
rdev_dec_pending(rdev, mddev);
rcu_read_lock();
@@ -611,36 +610,6 @@ static void raid10_unplug(struct request_queue *q)
md_wakeup_thread(mddev->thread);
}
-static int raid10_issue_flush(struct request_queue *q, struct gendisk *disk,
- sector_t *error_sector)
-{
- mddev_t *mddev = q->queuedata;
- conf_t *conf = mddev_to_conf(mddev);
- int i, ret = 0;
-
- rcu_read_lock();
- for (i=0; i<mddev->raid_disks && ret == 0; i++) {
- mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
- if (rdev && !test_bit(Faulty, &rdev->flags)) {
- struct block_device *bdev = rdev->bdev;
- struct request_queue *r_queue = bdev_get_queue(bdev);
-
- if (!r_queue->issue_flush_fn)
- ret = -EOPNOTSUPP;
- else {
- atomic_inc(&rdev->nr_pending);
- rcu_read_unlock();
- ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk,
- error_sector);
- rdev_dec_pending(rdev, mddev);
- rcu_read_lock();
- }
- }
- }
- rcu_read_unlock();
- return ret;
-}
-
static int raid10_congested(void *data, int bits)
{
mddev_t *mddev = data;
@@ -2118,7 +2087,6 @@ static int run(mddev_t *mddev)
mddev->resync_max_sectors = size << conf->chunk_shift;
mddev->queue->unplug_fn = raid10_unplug;
- mddev->queue->issue_flush_fn = raid10_issue_flush;
mddev->queue->backing_dev_info.congested_fn = raid10_congested;
mddev->queue->backing_dev_info.congested_data = mddev;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index caaca9e178bc..a5aad8cad843 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -376,7 +376,12 @@ static unsigned long get_stripe_work(struct stripe_head *sh)
ack++;
sh->ops.count -= ack;
- BUG_ON(sh->ops.count < 0);
+ if (unlikely(sh->ops.count < 0)) {
+ printk(KERN_ERR "pending: %#lx ops.pending: %#lx ops.ack: %#lx "
+ "ops.complete: %#lx\n", pending, sh->ops.pending,
+ sh->ops.ack, sh->ops.complete);
+ BUG();
+ }
return pending;
}
@@ -550,8 +555,7 @@ static void ops_complete_biofill(void *stripe_head_ref)
}
}
}
- clear_bit(STRIPE_OP_BIOFILL, &sh->ops.ack);
- clear_bit(STRIPE_OP_BIOFILL, &sh->ops.pending);
+ set_bit(STRIPE_OP_BIOFILL, &sh->ops.complete);
return_io(return_bi);
@@ -684,7 +688,8 @@ ops_run_prexor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
}
static struct dma_async_tx_descriptor *
-ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
+ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx,
+ unsigned long pending)
{
int disks = sh->disks;
int pd_idx = sh->pd_idx, i;
@@ -692,7 +697,7 @@ ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
/* check if prexor is active which means only process blocks
* that are part of a read-modify-write (Wantprexor)
*/
- int prexor = test_bit(STRIPE_OP_PREXOR, &sh->ops.pending);
+ int prexor = test_bit(STRIPE_OP_PREXOR, &pending);
pr_debug("%s: stripe %llu\n", __FUNCTION__,
(unsigned long long)sh->sector);
@@ -769,7 +774,8 @@ static void ops_complete_write(void *stripe_head_ref)
}
static void
-ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
+ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx,
+ unsigned long pending)
{
/* kernel stack size limits the total number of disks */
int disks = sh->disks;
@@ -777,7 +783,7 @@ ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
int count = 0, pd_idx = sh->pd_idx, i;
struct page *xor_dest;
- int prexor = test_bit(STRIPE_OP_PREXOR, &sh->ops.pending);
+ int prexor = test_bit(STRIPE_OP_PREXOR, &pending);
unsigned long flags;
dma_async_tx_callback callback;
@@ -804,7 +810,7 @@ ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
}
/* check whether this postxor is part of a write */
- callback = test_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending) ?
+ callback = test_bit(STRIPE_OP_BIODRAIN, &pending) ?
ops_complete_write : ops_complete_postxor;
/* 1/ if we prexor'd then the dest is reused as a source
@@ -892,12 +898,12 @@ static void raid5_run_ops(struct stripe_head *sh, unsigned long pending)
tx = ops_run_prexor(sh, tx);
if (test_bit(STRIPE_OP_BIODRAIN, &pending)) {
- tx = ops_run_biodrain(sh, tx);
+ tx = ops_run_biodrain(sh, tx, pending);
overlap_clear++;
}
if (test_bit(STRIPE_OP_POSTXOR, &pending))
- ops_run_postxor(sh, tx);
+ ops_run_postxor(sh, tx, pending);
if (test_bit(STRIPE_OP_CHECK, &pending))
ops_run_check(sh);
@@ -2620,6 +2626,13 @@ static void handle_stripe5(struct stripe_head *sh)
s.expanded = test_bit(STRIPE_EXPAND_READY, &sh->state);
/* Now to look around and see what can be done */
+ /* clean-up completed biofill operations */
+ if (test_bit(STRIPE_OP_BIOFILL, &sh->ops.complete)) {
+ clear_bit(STRIPE_OP_BIOFILL, &sh->ops.pending);
+ clear_bit(STRIPE_OP_BIOFILL, &sh->ops.ack);
+ clear_bit(STRIPE_OP_BIOFILL, &sh->ops.complete);
+ }
+
rcu_read_lock();
for (i=disks; i--; ) {
mdk_rdev_t *rdev;
@@ -3175,8 +3188,7 @@ static void unplug_slaves(mddev_t *mddev)
atomic_inc(&rdev->nr_pending);
rcu_read_unlock();
- if (r_queue->unplug_fn)
- r_queue->unplug_fn(r_queue);
+ blk_unplug(r_queue);
rdev_dec_pending(rdev, mddev);
rcu_read_lock();
@@ -3204,36 +3216,6 @@ static void raid5_unplug_device(struct request_queue *q)
unplug_slaves(mddev);
}
-static int raid5_issue_flush(struct request_queue *q, struct gendisk *disk,
- sector_t *error_sector)
-{
- mddev_t *mddev = q->queuedata;
- raid5_conf_t *conf = mddev_to_conf(mddev);
- int i, ret = 0;
-
- rcu_read_lock();
- for (i=0; i<mddev->raid_disks && ret == 0; i++) {
- mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev);
- if (rdev && !test_bit(Faulty, &rdev->flags)) {
- struct block_device *bdev = rdev->bdev;
- struct request_queue *r_queue = bdev_get_queue(bdev);
-
- if (!r_queue->issue_flush_fn)
- ret = -EOPNOTSUPP;
- else {
- atomic_inc(&rdev->nr_pending);
- rcu_read_unlock();
- ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk,
- error_sector);
- rdev_dec_pending(rdev, mddev);
- rcu_read_lock();
- }
- }
- }
- rcu_read_unlock();
- return ret;
-}
-
static int raid5_congested(void *data, int bits)
{
mddev_t *mddev = data;
@@ -4263,7 +4245,6 @@ static int run(mddev_t *mddev)
mdname(mddev));
mddev->queue->unplug_fn = raid5_unplug_device;
- mddev->queue->issue_flush_fn = raid5_issue_flush;
mddev->queue->backing_dev_info.congested_data = mddev;
mddev->queue->backing_dev_info.congested_fn = raid5_congested;
diff --git a/drivers/md/raid6algos.c b/drivers/md/raid6algos.c
index 926576156578..77a6e4bf503d 100644
--- a/drivers/md/raid6algos.c
+++ b/drivers/md/raid6algos.c
@@ -52,7 +52,7 @@ const struct raid6_calls * const raid6_algos[] = {
&raid6_intx16,
&raid6_intx32,
#endif
-#if defined(__i386__)
+#if defined(__i386__) && !defined(__arch_um__)
&raid6_mmxx1,
&raid6_mmxx2,
&raid6_sse1x1,
@@ -60,7 +60,7 @@ const struct raid6_calls * const raid6_algos[] = {
&raid6_sse2x1,
&raid6_sse2x2,
#endif
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(__arch_um__)
&raid6_sse2x1,
&raid6_sse2x2,
&raid6_sse2x4,
diff --git a/drivers/md/raid6mmx.c b/drivers/md/raid6mmx.c
index 6181a5a3365a..d4e4a1bd70ad 100644
--- a/drivers/md/raid6mmx.c
+++ b/drivers/md/raid6mmx.c
@@ -16,7 +16,7 @@
* MMX implementation of RAID-6 syndrome functions
*/
-#if defined(__i386__)
+#if defined(__i386__) && !defined(__arch_um__)
#include "raid6.h"
#include "raid6x86.h"
diff --git a/drivers/md/raid6sse1.c b/drivers/md/raid6sse1.c
index f0a1ba8f40ba..0666237276ff 100644
--- a/drivers/md/raid6sse1.c
+++ b/drivers/md/raid6sse1.c
@@ -21,7 +21,7 @@
* worthwhile as a separate implementation.
*/
-#if defined(__i386__)
+#if defined(__i386__) && !defined(__arch_um__)
#include "raid6.h"
#include "raid6x86.h"
diff --git a/drivers/md/raid6sse2.c b/drivers/md/raid6sse2.c
index 0f019762a7c3..b034ad868039 100644
--- a/drivers/md/raid6sse2.c
+++ b/drivers/md/raid6sse2.c
@@ -17,7 +17,7 @@
*
*/
-#if defined(__i386__) || defined(__x86_64__)
+#if (defined(__i386__) || defined(__x86_64__)) && !defined(__arch_um__)
#include "raid6.h"
#include "raid6x86.h"
@@ -161,7 +161,7 @@ const struct raid6_calls raid6_sse2x2 = {
#endif
-#ifdef __x86_64__
+#if defined(__x86_64__) && !defined(__arch_um__)
/*
* Unrolled-by-4 SSE2 implementation
diff --git a/drivers/md/raid6x86.h b/drivers/md/raid6x86.h
index 9111950414ff..99fea7a70ca7 100644
--- a/drivers/md/raid6x86.h
+++ b/drivers/md/raid6x86.h
@@ -19,7 +19,7 @@
#ifndef LINUX_RAID_RAID6X86_H
#define LINUX_RAID_RAID6X86_H
-#if defined(__i386__) || defined(__x86_64__)
+#if (defined(__i386__) || defined(__x86_64__)) && !defined(__arch_um__)
#ifdef __KERNEL__ /* Real code */
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
index dd9bd4310c84..1604f0490404 100644
--- a/drivers/media/Kconfig
+++ b/drivers/media/Kconfig
@@ -151,6 +151,7 @@ config VIDEO_IR_I2C
config VIDEO_IR
tristate
+ depends on INPUT
select VIDEO_IR_I2C if I2C
config VIDEO_TVEEPROM
diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c
index aefcf28da1ca..185e8a860c1a 100644
--- a/drivers/media/common/ir-keymaps.c
+++ b/drivers/media/common/ir-keymaps.c
@@ -1074,41 +1074,41 @@ EXPORT_SYMBOL_GPL(ir_codes_manli);
/* Mike Baikov <mike@baikov.com> */
IR_KEYTAB_TYPE ir_codes_gotview7135[IR_KEYTAB_SIZE] = {
- [ 0x21 ] = KEY_POWER,
- [ 0x69 ] = KEY_TV,
- [ 0x33 ] = KEY_0,
- [ 0x51 ] = KEY_1,
- [ 0x31 ] = KEY_2,
- [ 0x71 ] = KEY_3,
- [ 0x3b ] = KEY_4,
- [ 0x58 ] = KEY_5,
- [ 0x41 ] = KEY_6,
- [ 0x48 ] = KEY_7,
- [ 0x30 ] = KEY_8,
- [ 0x53 ] = KEY_9,
- [ 0x73 ] = KEY_AGAIN, /* LOOP */
- [ 0x0a ] = KEY_AUDIO,
- [ 0x61 ] = KEY_PRINT, /* PREVIEW */
- [ 0x7a ] = KEY_VIDEO,
- [ 0x20 ] = KEY_CHANNELUP,
- [ 0x40 ] = KEY_CHANNELDOWN,
- [ 0x18 ] = KEY_VOLUMEDOWN,
- [ 0x50 ] = KEY_VOLUMEUP,
- [ 0x10 ] = KEY_MUTE,
- [ 0x4a ] = KEY_SEARCH,
- [ 0x7b ] = KEY_SHUFFLE, /* SNAPSHOT */
- [ 0x22 ] = KEY_RECORD,
- [ 0x62 ] = KEY_STOP,
- [ 0x78 ] = KEY_PLAY,
- [ 0x39 ] = KEY_REWIND,
- [ 0x59 ] = KEY_PAUSE,
- [ 0x19 ] = KEY_FORWARD,
- [ 0x09 ] = KEY_ZOOM,
-
- [ 0x52 ] = KEY_F21, /* LIVE TIMESHIFT */
- [ 0x1a ] = KEY_F22, /* MIN TIMESHIFT */
- [ 0x3a ] = KEY_F23, /* TIMESHIFT */
- [ 0x70 ] = KEY_F24, /* NORMAL TIMESHIFT */
+ [ 0x11 ] = KEY_POWER,
+ [ 0x35 ] = KEY_TV,
+ [ 0x1b ] = KEY_0,
+ [ 0x29 ] = KEY_1,
+ [ 0x19 ] = KEY_2,
+ [ 0x39 ] = KEY_3,
+ [ 0x1f ] = KEY_4,
+ [ 0x2c ] = KEY_5,
+ [ 0x21 ] = KEY_6,
+ [ 0x24 ] = KEY_7,
+ [ 0x18 ] = KEY_8,
+ [ 0x2b ] = KEY_9,
+ [ 0x3b ] = KEY_AGAIN, /* LOOP */
+ [ 0x06 ] = KEY_AUDIO,
+ [ 0x31 ] = KEY_PRINT, /* PREVIEW */
+ [ 0x3e ] = KEY_VIDEO,
+ [ 0x10 ] = KEY_CHANNELUP,
+ [ 0x20 ] = KEY_CHANNELDOWN,
+ [ 0x0c ] = KEY_VOLUMEDOWN,
+ [ 0x28 ] = KEY_VOLUMEUP,
+ [ 0x08 ] = KEY_MUTE,
+ [ 0x26 ] = KEY_SEARCH, /*SCAN*/
+ [ 0x3f ] = KEY_SHUFFLE, /* SNAPSHOT */
+ [ 0x12 ] = KEY_RECORD,
+ [ 0x32 ] = KEY_STOP,
+ [ 0x3c ] = KEY_PLAY,
+ [ 0x1d ] = KEY_REWIND,
+ [ 0x2d ] = KEY_PAUSE,
+ [ 0x0d ] = KEY_FORWARD,
+ [ 0x05 ] = KEY_ZOOM, /*FULL*/
+
+ [ 0x2a ] = KEY_F21, /* LIVE TIMESHIFT */
+ [ 0x0e ] = KEY_F22, /* MIN TIMESHIFT */
+ [ 0x1e ] = KEY_F23, /* TIMESHIFT */
+ [ 0x38 ] = KEY_F24, /* NORMAL TIMESHIFT */
};
EXPORT_SYMBOL_GPL(ir_codes_gotview7135);
diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c
index 365a22118a09..7d04a6fd1acb 100644
--- a/drivers/media/common/saa7146_core.c
+++ b/drivers/media/common/saa7146_core.c
@@ -59,43 +59,89 @@ void saa7146_setgpio(struct saa7146_dev *dev, int port, u32 data)
}
/* This DEBI code is based on the saa7146 Stradis driver by Nathan Laredo */
-int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop)
+static inline int saa7146_wait_for_debi_done_sleep(struct saa7146_dev *dev,
+ unsigned long us1, unsigned long us2)
{
- unsigned long start;
+ unsigned long timeout;
int err;
/* wait for registers to be programmed */
- start = jiffies;
+ timeout = jiffies + usecs_to_jiffies(us1);
while (1) {
- err = time_after(jiffies, start + HZ/20);
+ err = time_after(jiffies, timeout);
if (saa7146_read(dev, MC2) & 2)
break;
if (err) {
- DEB_S(("timed out while waiting for registers getting programmed\n"));
+ printk(KERN_ERR "%s: %s timed out while waiting for "
+ "registers getting programmed\n",
+ dev->name, __FUNCTION__);
return -ETIMEDOUT;
}
- if (nobusyloop)
- msleep(1);
+ msleep(1);
}
/* wait for transfer to complete */
- start = jiffies;
+ timeout = jiffies + usecs_to_jiffies(us2);
while (1) {
- err = time_after(jiffies, start + HZ/4);
+ err = time_after(jiffies, timeout);
if (!(saa7146_read(dev, PSR) & SPCI_DEBI_S))
break;
saa7146_read(dev, MC2);
if (err) {
- DEB_S(("timed out while waiting for transfer completion\n"));
+ DEB_S(("%s: %s timed out while waiting for transfer "
+ "completion\n", dev->name, __FUNCTION__));
return -ETIMEDOUT;
}
- if (nobusyloop)
- msleep(1);
+ msleep(1);
}
return 0;
}
+static inline int saa7146_wait_for_debi_done_busyloop(struct saa7146_dev *dev,
+ unsigned long us1, unsigned long us2)
+{
+ unsigned long loops;
+
+ /* wait for registers to be programmed */
+ loops = us1;
+ while (1) {
+ if (saa7146_read(dev, MC2) & 2)
+ break;
+ if (!loops--) {
+ printk(KERN_ERR "%s: %s timed out while waiting for "
+ "registers getting programmed\n",
+ dev->name, __FUNCTION__);
+ return -ETIMEDOUT;
+ }
+ udelay(1);
+ }
+
+ /* wait for transfer to complete */
+ loops = us2 / 5;
+ while (1) {
+ if (!(saa7146_read(dev, PSR) & SPCI_DEBI_S))
+ break;
+ saa7146_read(dev, MC2);
+ if (!loops--) {
+ DEB_S(("%s: %s timed out while waiting for transfer "
+ "completion\n", dev->name, __FUNCTION__));
+ return -ETIMEDOUT;
+ }
+ udelay(5);
+ }
+
+ return 0;
+}
+
+int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop)
+{
+ if (nobusyloop)
+ return saa7146_wait_for_debi_done_sleep(dev, 50000, 250000);
+ else
+ return saa7146_wait_for_debi_done_busyloop(dev, 50000, 250000);
+}
+
/****************************************************************************
* general helper functions
****************************************************************************/
@@ -112,13 +158,13 @@ static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages)
sglist = kcalloc(nr_pages, sizeof(struct scatterlist), GFP_KERNEL);
if (NULL == sglist)
return NULL;
+ sg_init_table(sglist, nr_pages);
for (i = 0; i < nr_pages; i++, virt += PAGE_SIZE) {
pg = vmalloc_to_page(virt);
if (NULL == pg)
goto err;
BUG_ON(PageHighMem(pg));
- sglist[i].page = pg;
- sglist[i].length = PAGE_SIZE;
+ sg_set_page(&sglist[i], pg, PAGE_SIZE, 0);
}
return sglist;
diff --git a/drivers/media/common/saa7146_hlp.c b/drivers/media/common/saa7146_hlp.c
index d2905720eb74..9c905399a233 100644
--- a/drivers/media/common/saa7146_hlp.c
+++ b/drivers/media/common/saa7146_hlp.c
@@ -312,7 +312,7 @@ static int sort_and_eliminate(u32* values, int* count)
return -EINVAL;
}
- /* bubble sort the first ´count´ items of the array ´values´ */
+ /* bubble sort the first @count items of the array @values */
for( top = *count; top > 0; top--) {
for( low = 0, high = 1; high < top; low++, high++) {
if( values[low] > values[high] ) {
diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c
index eca602d9b3de..85e36a1d6d78 100644
--- a/drivers/media/dvb/bt8xx/bt878.c
+++ b/drivers/media/dvb/bt8xx/bt878.c
@@ -280,7 +280,7 @@ static irqreturn_t bt878_irq(int irq, void *dev_id)
if (!(astat = (stat & mask)))
return IRQ_NONE; /* this interrupt is not for me */
/* dprintk("bt878(%d) debug: irq count %d, stat 0x%8.8x, mask 0x%8.8x\n",bt->nr,count,stat,mask); */
- btwrite(astat, BT878_AINT_STAT); /* try to clear interupt condition */
+ btwrite(astat, BT878_AINT_STAT); /* try to clear interrupt condition */
if (astat & (BT878_ASCERR | BT878_AOCERR)) {
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c
index 5a12b5679556..db08b0a8888a 100644
--- a/drivers/media/dvb/cinergyT2/cinergyT2.c
+++ b/drivers/media/dvb/cinergyT2/cinergyT2.c
@@ -1,5 +1,5 @@
/*
- * TerraTec Cinergy T²/qanu USB2 DVB-T adapter.
+ * TerraTec Cinergy T²/qanu USB2 DVB-T adapter.
*
* Copyright (C) 2004 Daniel Mack <daniel@qanu.de> and
* Holger Waechtler <holger@qanu.de>
@@ -345,7 +345,9 @@ static int cinergyt2_start_feed(struct dvb_demux_feed *dvbdmxfeed)
struct dvb_demux *demux = dvbdmxfeed->demux;
struct cinergyt2 *cinergyt2 = demux->priv;
- if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem))
+ if (cinergyt2->disconnect_pending)
+ return -EAGAIN;
+ if (mutex_lock_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
if (cinergyt2->streaming == 0)
@@ -361,7 +363,9 @@ static int cinergyt2_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
struct dvb_demux *demux = dvbdmxfeed->demux;
struct cinergyt2 *cinergyt2 = demux->priv;
- if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem))
+ if (cinergyt2->disconnect_pending)
+ return -EAGAIN;
+ if (mutex_lock_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
if (--cinergyt2->streaming == 0)
@@ -481,12 +485,16 @@ static int cinergyt2_open (struct inode *inode, struct file *file)
{
struct dvb_device *dvbdev = file->private_data;
struct cinergyt2 *cinergyt2 = dvbdev->priv;
- int err = -ERESTARTSYS;
+ int err = -EAGAIN;
- if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->wq_sem))
+ if (cinergyt2->disconnect_pending)
+ goto out;
+ err = mutex_lock_interruptible(&cinergyt2->wq_sem);
+ if (err)
goto out;
- if (mutex_lock_interruptible(&cinergyt2->sem))
+ err = mutex_lock_interruptible(&cinergyt2->sem);
+ if (err)
goto out_unlock1;
if ((err = dvb_generic_open(inode, file)))
@@ -550,7 +558,9 @@ static unsigned int cinergyt2_poll (struct file *file, struct poll_table_struct
struct cinergyt2 *cinergyt2 = dvbdev->priv;
unsigned int mask = 0;
- if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem))
+ if (cinergyt2->disconnect_pending)
+ return -EAGAIN;
+ if (mutex_lock_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
poll_wait(file, &cinergyt2->poll_wq, wait);
@@ -625,7 +635,9 @@ static int cinergyt2_ioctl (struct inode *inode, struct file *file,
if (copy_from_user(&p, (void __user*) arg, sizeof(p)))
return -EFAULT;
- if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem))
+ if (cinergyt2->disconnect_pending)
+ return -EAGAIN;
+ if (mutex_lock_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
param->cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS;
@@ -820,7 +832,7 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2)
input_dev->name = DRIVER_NAME " remote control";
input_dev->phys = cinergyt2->phys;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
for (i = 0; i < ARRAY_SIZE(rc_keys); i += 3)
set_bit(rc_keys[i + 2], input_dev->keybit);
input_dev->keycodesize = 0;
@@ -996,7 +1008,9 @@ static int cinergyt2_suspend (struct usb_interface *intf, pm_message_t state)
{
struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
- if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->wq_sem))
+ if (cinergyt2->disconnect_pending)
+ return -EAGAIN;
+ if (mutex_lock_interruptible(&cinergyt2->wq_sem))
return -ERESTARTSYS;
cinergyt2_suspend_rc(cinergyt2);
@@ -1017,16 +1031,18 @@ static int cinergyt2_resume (struct usb_interface *intf)
{
struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
struct dvbt_set_parameters_msg *param = &cinergyt2->param;
- int err = -ERESTARTSYS;
+ int err = -EAGAIN;
- if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->wq_sem))
+ if (cinergyt2->disconnect_pending)
+ goto out;
+ err = mutex_lock_interruptible(&cinergyt2->wq_sem);
+ if (err)
goto out;
- if (mutex_lock_interruptible(&cinergyt2->sem))
+ err = mutex_lock_interruptible(&cinergyt2->sem);
+ if (err)
goto out_unlock1;
- err = 0;
-
if (!cinergyt2->sleeping) {
cinergyt2_sleep(cinergyt2, 0);
cinergyt2_command(cinergyt2, (char *) param, sizeof(*param), NULL, 0);
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
index 084a508a03da..89437fdab8be 100644
--- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
+++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
@@ -972,7 +972,7 @@ static int dvb_ca_en50221_thread(void *data)
/* main loop */
while (!kthread_should_stop()) {
/* sleep for a bit */
- while (!ca->wakeup) {
+ if (!ca->wakeup) {
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(ca->delay);
if (kthread_should_stop())
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index b203640ef1c5..445f02665577 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -527,7 +527,8 @@ static int dvb_frontend_thread(void *data)
up(&fepriv->sem); /* is locked when we enter the thread... */
restart:
timeout = wait_event_interruptible_timeout(fepriv->wait_queue,
- dvb_frontend_should_wakeup(fe) || kthread_should_stop(),
+ dvb_frontend_should_wakeup(fe) || kthread_should_stop()
+ || freezing(current),
fepriv->delay);
if (kthread_should_stop() || dvb_frontend_is_exiting(fe)) {
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c
index e8c4a8694532..58452b52002c 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c
@@ -828,7 +828,7 @@ MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
#define DIB0700_DEFAULT_DEVICE_PROPERTIES \
.caps = DVB_USB_IS_AN_I2C_ADAPTER, \
.usb_ctrl = DEVICE_SPECIFIC, \
- .firmware = "dvb-usb-dib0700-03-pre1.fw", \
+ .firmware = "dvb-usb-dib0700-1.10.fw", \
.download_firmware = dib0700_download_firmware, \
.no_reconnect = 1, \
.size_of_priv = sizeof(struct dib0700_state), \
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
index 7b9f35bfb4f0..c0c2c22ddd83 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
@@ -106,7 +106,7 @@ int dvb_usb_remote_init(struct dvb_usb_device *d)
if (!input_dev)
return -ENOMEM;
- input_dev->evbit[0] = BIT(EV_KEY);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY);
input_dev->name = "IR-receiver inside an USB DVB receiver";
input_dev->phys = d->rc_phys;
usb_to_input_id(d->udev, &input_dev->id);
diff --git a/drivers/media/dvb/frontends/mt2131.c b/drivers/media/dvb/frontends/mt2131.c
index 4b93931de4e1..13cf16668171 100644
--- a/drivers/media/dvb/frontends/mt2131.c
+++ b/drivers/media/dvb/frontends/mt2131.c
@@ -116,7 +116,7 @@ static int mt2131_set_params(struct dvb_frontend *fe,
f_lo1 = (f_lo1 / 250) * 250;
f_lo2 = f_lo1 - freq - MT2131_IF2;
- priv->frequency = (f_lo1 - f_lo2 - MT2131_IF2) * 1000,
+ priv->frequency = (f_lo1 - f_lo2 - MT2131_IF2) * 1000;
/* Frequency LO1 = 16MHz * (DIV1 + NUM1/8192 ) */
num1 = f_lo1 * 64 / (MT2131_FREF / 128);
diff --git a/drivers/media/dvb/frontends/s5h1409.c b/drivers/media/dvb/frontends/s5h1409.c
index 30e8a705fad4..8dee7ec9456a 100644
--- a/drivers/media/dvb/frontends/s5h1409.c
+++ b/drivers/media/dvb/frontends/s5h1409.c
@@ -42,6 +42,9 @@ struct s5h1409_state {
fe_modulation_t current_modulation;
u32 current_frequency;
+
+ u32 is_qam_locked;
+ u32 qam_state;
};
static int debug = 0;
@@ -94,6 +97,7 @@ static struct init_tab {
{ 0xac, 0x1003, },
{ 0xad, 0x103f, },
{ 0xe2, 0x0100, },
+ { 0xe3, 0x0000, },
{ 0x28, 0x1010, },
{ 0xb1, 0x000e, },
};
@@ -335,6 +339,8 @@ static int s5h1409_softreset(struct dvb_frontend* fe)
s5h1409_writereg(state, 0xf5, 0);
s5h1409_writereg(state, 0xf5, 1);
+ state->is_qam_locked = 0;
+ state->qam_state = 0;
return 0;
}
@@ -349,6 +355,11 @@ static int s5h1409_set_if_freq(struct dvb_frontend* fe, int KHz)
s5h1409_writereg(state, 0x87, 0x01be);
s5h1409_writereg(state, 0x88, 0x0436);
s5h1409_writereg(state, 0x89, 0x054d);
+ } else
+ if (KHz == 4000) {
+ s5h1409_writereg(state, 0x87, 0x014b);
+ s5h1409_writereg(state, 0x88, 0x0cb5);
+ s5h1409_writereg(state, 0x89, 0x03e2);
} else {
printk("%s() Invalid arg = %d KHz\n", __FUNCTION__, KHz);
ret = -1;
@@ -361,7 +372,7 @@ static int s5h1409_set_spectralinversion(struct dvb_frontend* fe, int inverted)
{
struct s5h1409_state* state = fe->demodulator_priv;
- dprintk("%s()\n", __FUNCTION__);
+ dprintk("%s(%d)\n", __FUNCTION__, inverted);
if(inverted == 1)
return s5h1409_writereg(state, 0x1b, 0x1101); /* Inverted */
@@ -382,14 +393,10 @@ static int s5h1409_enable_modulation(struct dvb_frontend* fe,
s5h1409_writereg(state, 0xf4, 0);
break;
case QAM_64:
- dprintk("%s() QAM_64\n", __FUNCTION__);
- s5h1409_writereg(state, 0xf4, 1);
- s5h1409_writereg(state, 0x85, 0x100);
- break;
case QAM_256:
- dprintk("%s() QAM_256\n", __FUNCTION__);
+ dprintk("%s() QAM_AUTO (64/256)\n", __FUNCTION__);
s5h1409_writereg(state, 0xf4, 1);
- s5h1409_writereg(state, 0x85, 0x101);
+ s5h1409_writereg(state, 0x85, 0x110);
break;
default:
dprintk("%s() Invalid modulation\n", __FUNCTION__);
@@ -423,7 +430,7 @@ static int s5h1409_set_gpio(struct dvb_frontend* fe, int enable)
if (enable)
return s5h1409_writereg(state, 0xe3, 0x1100);
else
- return s5h1409_writereg(state, 0xe3, 0);
+ return s5h1409_writereg(state, 0xe3, 0x1000);
}
static int s5h1409_sleep(struct dvb_frontend* fe, int enable)
@@ -444,6 +451,66 @@ static int s5h1409_register_reset(struct dvb_frontend* fe)
return s5h1409_writereg(state, 0xfa, 0);
}
+static void s5h1409_set_qam_amhum_mode(struct dvb_frontend *fe)
+{
+ struct s5h1409_state *state = fe->demodulator_priv;
+ u16 reg;
+
+ if (state->is_qam_locked)
+ return;
+
+ /* QAM EQ lock check */
+ reg = s5h1409_readreg(state, 0xf0);
+
+ if ((reg >> 13) & 0x1) {
+
+ state->is_qam_locked = 1;
+ reg &= 0xff;
+
+ s5h1409_writereg(state, 0x96, 0x00c);
+ if ((reg < 0x38) || (reg > 0x68) ) {
+ s5h1409_writereg(state, 0x93, 0x3332);
+ s5h1409_writereg(state, 0x9e, 0x2c37);
+ } else {
+ s5h1409_writereg(state, 0x93, 0x3130);
+ s5h1409_writereg(state, 0x9e, 0x2836);
+ }
+
+ } else {
+ s5h1409_writereg(state, 0x96, 0x0008);
+ s5h1409_writereg(state, 0x93, 0x3332);
+ s5h1409_writereg(state, 0x9e, 0x2c37);
+ }
+}
+
+static void s5h1409_set_qam_interleave_mode(struct dvb_frontend *fe)
+{
+ struct s5h1409_state *state = fe->demodulator_priv;
+ u16 reg, reg1, reg2;
+
+ reg = s5h1409_readreg(state, 0xf1);
+
+ /* Master lock */
+ if ((reg >> 15) & 0x1) {
+ if (state->qam_state != 2) {
+ state->qam_state = 2;
+ reg1 = s5h1409_readreg(state, 0xb2);
+ reg2 = s5h1409_readreg(state, 0xad);
+
+ s5h1409_writereg(state, 0x96, 0x20);
+ s5h1409_writereg(state, 0xad,
+ ( ((reg1 & 0xf000) >> 4) | (reg2 & 0xf0ff)) );
+ s5h1409_writereg(state, 0xab, 0x1100);
+ }
+ } else {
+ if (state->qam_state != 1) {
+ state->qam_state = 1;
+ s5h1409_writereg(state, 0x96, 0x08);
+ s5h1409_writereg(state, 0xab, 0x1101);
+ }
+ }
+}
+
/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
static int s5h1409_set_frontend (struct dvb_frontend* fe,
struct dvb_frontend_parameters *p)
@@ -458,12 +525,21 @@ static int s5h1409_set_frontend (struct dvb_frontend* fe,
s5h1409_enable_modulation(fe, p->u.vsb.modulation);
+ /* Allow the demod to settle */
+ msleep(100);
+
if (fe->ops.tuner_ops.set_params) {
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1);
fe->ops.tuner_ops.set_params(fe, p);
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
}
+ /* Optimize the demod for QAM */
+ if (p->u.vsb.modulation != VSB_8) {
+ s5h1409_set_qam_amhum_mode(fe);
+ s5h1409_set_qam_interleave_mode(fe);
+ }
+
return 0;
}
@@ -495,8 +571,8 @@ static int s5h1409_init (struct dvb_frontend* fe)
s5h1409_set_gpio(fe, state->config->gpio);
s5h1409_softreset(fe);
- /* Note: Leaving the I2C gate open here. */
- s5h1409_i2c_gate_ctrl(fe, 1);
+ /* Note: Leaving the I2C gate closed. */
+ s5h1409_i2c_gate_ctrl(fe, 0);
return 0;
}
diff --git a/drivers/media/dvb/frontends/stv0297.c b/drivers/media/dvb/frontends/stv0297.c
index 17e5cb561cd8..7c23775f77db 100644
--- a/drivers/media/dvb/frontends/stv0297.c
+++ b/drivers/media/dvb/frontends/stv0297.c
@@ -358,11 +358,23 @@ static int stv0297_read_ber(struct dvb_frontend *fe, u32 * ber)
static int stv0297_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
{
struct stv0297_state *state = fe->demodulator_priv;
- u8 STRENGTH[2];
-
- stv0297_readregs(state, 0x41, STRENGTH, 2);
- *strength = (STRENGTH[1] & 0x03) << 8 | STRENGTH[0];
-
+ u8 STRENGTH[3];
+ u16 tmp;
+
+ stv0297_readregs(state, 0x41, STRENGTH, 3);
+ tmp = (STRENGTH[1] & 0x03) << 8 | STRENGTH[0];
+ if (STRENGTH[2] & 0x20) {
+ if (tmp < 0x200)
+ tmp = 0;
+ else
+ tmp = tmp - 0x200;
+ } else {
+ if (tmp > 0x1ff)
+ tmp = 0;
+ else
+ tmp = 0x1ff - tmp;
+ }
+ *strength = (tmp << 7) | (tmp >> 2);
return 0;
}
diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb/frontends/tda10021.c
index 4cd9e82c4669..45137d2ebfb9 100644
--- a/drivers/media/dvb/frontends/tda10021.c
+++ b/drivers/media/dvb/frontends/tda10021.c
@@ -301,6 +301,8 @@ static int tda10021_read_ber(struct dvb_frontend* fe, u32* ber)
u32 _ber = tda10021_readreg(state, 0x14) |
(tda10021_readreg(state, 0x15) << 8) |
((tda10021_readreg(state, 0x16) & 0x0f) << 16);
+ _tda10021_writereg(state, 0x10, (tda10021_readreg(state, 0x10) & ~0xc0)
+ | (tda10021_inittab[0x10] & 0xc0));
*ber = 10 * _ber;
return 0;
@@ -310,7 +312,11 @@ static int tda10021_read_signal_strength(struct dvb_frontend* fe, u16* strength)
{
struct tda10021_state* state = fe->demodulator_priv;
+ u8 config = tda10021_readreg(state, 0x02);
u8 gain = tda10021_readreg(state, 0x17);
+ if (config & 0x02)
+ /* the agc value is inverted */
+ gain = ~gain;
*strength = (gain << 8) | gain;
return 0;
diff --git a/drivers/media/dvb/frontends/ves1820.c b/drivers/media/dvb/frontends/ves1820.c
index 066b73b75698..60433b5011fd 100644
--- a/drivers/media/dvb/frontends/ves1820.c
+++ b/drivers/media/dvb/frontends/ves1820.c
@@ -47,7 +47,7 @@ struct ves1820_state {
static int verbose;
static u8 ves1820_inittab[] = {
- 0x69, 0x6A, 0x93, 0x12, 0x12, 0x46, 0x26, 0x1A,
+ 0x69, 0x6A, 0x93, 0x1A, 0x12, 0x46, 0x26, 0x1A,
0x43, 0x6A, 0xAA, 0xAA, 0x1E, 0x85, 0x43, 0x20,
0xE0, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig
index 6d53289b3276..54b91f26ca63 100644
--- a/drivers/media/dvb/ttpci/Kconfig
+++ b/drivers/media/dvb/ttpci/Kconfig
@@ -84,7 +84,7 @@ config DVB_BUDGET
config DVB_BUDGET_CI
tristate "Budget cards with onboard CI connector"
- depends on DVB_CORE && PCI && I2C && VIDEO_V4L1
+ depends on DVB_CORE && PCI && I2C && VIDEO_V4L1 && INPUT
select VIDEO_SAA7146
select DVB_STV0297 if !DVB_FE_CUSTOMISE
select DVB_STV0299 if !DVB_FE_CUSTOMISE
diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c
index 5d19c402dad1..a283e1de83fa 100644
--- a/drivers/media/dvb/ttpci/av7110_ir.c
+++ b/drivers/media/dvb/ttpci/av7110_ir.c
@@ -27,7 +27,7 @@
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/kernel.h>
-#include <asm/bitops.h>
+#include <linux/bitops.h>
#include "av7110.h"
#include "av7110_hw.h"
diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
index 288e79f2cb0f..7902ae1d9a18 100644
--- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
+++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
@@ -128,7 +128,7 @@ struct ttusb {
struct dvb_frontend* fe;
};
-/* ugly workaround ... don't know why it's neccessary to read */
+/* ugly workaround ... don't know why it's necessary to read */
/* all result codes. */
#define DEBUG 0
diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
index 5e691fd79904..1ec981d98b91 100644
--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
@@ -1198,7 +1198,7 @@ static int ttusb_init_rc( struct ttusb_dec *dec)
input_dev->name = "ttusb_dec remote control";
input_dev->phys = dec->rc_phys;
- input_dev->evbit[0] = BIT(EV_KEY);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY);
input_dev->keycodesize = sizeof(u16);
input_dev->keycodemax = 0x1a;
input_dev->keycode = rc_keys;
diff --git a/drivers/media/radio/miropcm20-radio.c b/drivers/media/radio/miropcm20-radio.c
index c7c9d1dc0690..3ae56fef8c92 100644
--- a/drivers/media/radio/miropcm20-radio.c
+++ b/drivers/media/radio/miropcm20-radio.c
@@ -229,7 +229,6 @@ static struct video_device pcm20_radio = {
.owner = THIS_MODULE,
.name = "Miro PCM 20 radio",
.type = VID_TYPE_TUNER,
- .hardware = VID_HARDWARE_RTRACK,
.fops = &pcm20_fops,
.priv = &pcm20_unit
};
diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c
index 0c963db03614..5e4b9ddb23c0 100644
--- a/drivers/media/radio/radio-gemtek.c
+++ b/drivers/media/radio/radio-gemtek.c
@@ -554,7 +554,6 @@ static struct video_device gemtek_radio = {
.owner = THIS_MODULE,
.name = "GemTek Radio card",
.type = VID_TYPE_TUNER,
- .hardware = VID_HARDWARE_GEMTEK,
.fops = &gemtek_fops,
.vidioc_querycap = vidioc_querycap,
.vidioc_g_tuner = vidioc_g_tuner,
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 2e571eb9313a..c9f14bfc8544 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -363,7 +363,7 @@ endmenu # encoder / decoder chips
config VIDEO_VIVI
tristate "Virtual Video Driver"
- depends on VIDEO_V4L2 && !SPARC32 && !SPARC64 && PCI
+ depends on VIDEO_V4L2 && !SPARC32 && !SPARC64
select VIDEOBUF_VMALLOC
default n
---help---
diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c
index 19e9929ffa0f..c94a4d0f2804 100644
--- a/drivers/media/video/arv.c
+++ b/drivers/media/video/arv.c
@@ -755,7 +755,6 @@ static struct video_device ar_template = {
.owner = THIS_MODULE,
.name = "Colour AR VGA",
.type = VID_TYPE_CAPTURE,
- .hardware = VID_HARDWARE_ARV,
.fops = &ar_fops,
.release = ar_release,
.minor = -1,
diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c
index dd6a7d68b07f..3abd9fa54d2c 100644
--- a/drivers/media/video/bt8xx/bttv-cards.c
+++ b/drivers/media/video/bt8xx/bttv-cards.c
@@ -1259,7 +1259,7 @@ struct tvcard bttv_tvcards[] = {
.has_radio = 1,
},
[BTTV_BOARD_LIFETEC_9415] = {
- /* Tim Röstermundt <rosterm@uni-muenster.de>
+ /* Tim Röstermundt <rosterm@uni-muenster.de>
in de.comp.os.unix.linux.hardware:
options bttv card=0 pll=1 radio=1 gpiomask=0x18e0
gpiomux =0x44c71f,0x44d71f,0,0x44d71f,0x44dfff
@@ -2824,7 +2824,7 @@ struct tvcard bttv_tvcards[] = {
},
/* ---- card 0x8b ---------------------------------- */
[BTTV_BOARD_PV_M4900] = {
- /* Sérgio Fortier <sergiofortier@yahoo.com.br> */
+ /* Sérgio Fortier <sergiofortier@yahoo.com.br> */
.name = "Prolink PixelView PlayTV MPEG2 PV-M4900",
.video_inputs = 3,
.audio_inputs = 1,
@@ -4709,18 +4709,18 @@ adtvk503_audio(struct bttv *btv, struct video_audio *v, int set)
*
* The board hardwire Y0 (xpoint) to MUX1 and MUXOUT to Yin.
* GPIO pins are wired as:
- * GPIO[0:3] - AX[0:3] (xpoint) - P1[0:3] (microcontroler)
- * GPIO[4:6] - AY[0:2] (xpoint) - P1[4:6] (microcontroler)
- * GPIO[7] - DATA (xpoint) - P1[7] (microcontroler)
- * GPIO[8] - - P3[5] (microcontroler)
- * GPIO[9] - RESET (xpoint) - P3[6] (microcontroler)
- * GPIO[10] - STROBE (xpoint) - P3[7] (microcontroler)
- * GPINTR - - P3[4] (microcontroler)
+ * GPIO[0:3] - AX[0:3] (xpoint) - P1[0:3] (microcontroller)
+ * GPIO[4:6] - AY[0:2] (xpoint) - P1[4:6] (microcontroller)
+ * GPIO[7] - DATA (xpoint) - P1[7] (microcontroller)
+ * GPIO[8] - - P3[5] (microcontroller)
+ * GPIO[9] - RESET (xpoint) - P3[6] (microcontroller)
+ * GPIO[10] - STROBE (xpoint) - P3[7] (microcontroller)
+ * GPINTR - - P3[4] (microcontroller)
*
- * The microcontroler is a 80C32 like. It should be possible to change xpoint
- * configuration either directly (as we are doing) or using the microcontroler
+ * The microcontroller is a 80C32 like. It should be possible to change xpoint
+ * configuration either directly (as we are doing) or using the microcontroller
* which is also wired to I2C interface. I have no further info on the
- * microcontroler features, one would need to disassembly the firmware.
+ * microcontroller features, one would need to disassembly the firmware.
* note: the vendor refused to give any information on this product, all
* that stuff was found using a multimeter! :)
*/
@@ -4788,7 +4788,7 @@ static void tibetCS16_init(struct bttv *btv)
* The analog switch is controlled by the "master", but the detection order
* of the four BT878A chips is in an order which I just don't understand.
* The "master" is actually the second controller to be detected. The
- * logic on the board uses logical numbers for the 4 controlers, but
+ * logic on the board uses logical numbers for the 4 controllers, but
* those numbers are different from the detection sequence. When working
* with the analog switch, we need to "map" from the detection sequence
* over to the board's logical controller number. This mapping sequence
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
index 7a332b3efe51..a88b56e6ca05 100644
--- a/drivers/media/video/bt8xx/bttv-driver.c
+++ b/drivers/media/video/bt8xx/bttv-driver.c
@@ -2881,10 +2881,6 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
if (NULL == fmt)
return -EINVAL;
mutex_lock(&fh->cap.lock);
- if (fmt->depth != pic->depth) {
- retval = -EINVAL;
- goto fh_unlock_and_return;
- }
if (fmt->flags & FORMAT_FLAGS_RAW) {
/* VIDIOCMCAPTURE uses gbufsize, not RAW_BPL *
RAW_LINES * 2. F1 is stored at offset 0, F2
@@ -3117,6 +3113,8 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
vm->width,vm->height,field);
if (0 != retval)
goto fh_unlock_and_return;
+ btv->init.width = vm->width;
+ btv->init.height = vm->height;
spin_lock_irqsave(&btv->s_lock,flags);
buffer_queue(&fh->cap,&buf->vb);
spin_unlock_irqrestore(&btv->s_lock,flags);
@@ -3877,7 +3875,6 @@ static struct video_device bttv_video_template =
.name = "UNSET",
.type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|
VID_TYPE_CLIPPING|VID_TYPE_SCALES,
- .hardware = VID_HARDWARE_BT848,
.fops = &bttv_fops,
.minor = -1,
};
@@ -3886,7 +3883,6 @@ static struct video_device bttv_vbi_template =
{
.name = "bt848/878 vbi",
.type = VID_TYPE_TUNER|VID_TYPE_TELETEXT,
- .hardware = VID_HARDWARE_BT848,
.fops = &bttv_fops,
.minor = -1,
};
@@ -4034,7 +4030,6 @@ static struct video_device radio_template =
{
.name = "bt848/878 radio",
.type = VID_TYPE_TUNER,
- .hardware = VID_HARDWARE_BT848,
.fops = &radio_fops,
.minor = -1,
};
diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h
index 0b92c35a8435..d4ac4c4b49b4 100644
--- a/drivers/media/video/bt8xx/bttvp.h
+++ b/drivers/media/video/bt8xx/bttvp.h
@@ -36,7 +36,7 @@
#include <linux/pci.h>
#include <linux/input.h>
#include <linux/mutex.h>
-#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
#include <asm/io.h>
#include <media/v4l2-common.h>
diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c
index 7f7e3d3398d0..58423525591f 100644
--- a/drivers/media/video/bw-qcam.c
+++ b/drivers/media/video/bw-qcam.c
@@ -899,7 +899,6 @@ static struct video_device qcam_template=
.owner = THIS_MODULE,
.name = "Connectix Quickcam",
.type = VID_TYPE_CAPTURE,
- .hardware = VID_HARDWARE_QCAM_BW,
.fops = &qcam_fops,
};
diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c
index f76c6a6c3766..cf1546b5a7f1 100644
--- a/drivers/media/video/c-qcam.c
+++ b/drivers/media/video/c-qcam.c
@@ -699,7 +699,6 @@ static struct video_device qcam_template=
.owner = THIS_MODULE,
.name = "Colour QuickCam",
.type = VID_TYPE_CAPTURE,
- .hardware = VID_HARDWARE_QCAM_C,
.fops = &qcam_fops,
};
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c
index b63cab336920..7ae499c9c54c 100644
--- a/drivers/media/video/cafe_ccic.c
+++ b/drivers/media/video/cafe_ccic.c
@@ -3,6 +3,9 @@
* multifunction chip. Currently works with the Omnivision OV7670
* sensor.
*
+ * The data sheet for this device can be found at:
+ * http://www.marvell.com/products/pcconn/88ALP01.jsp
+ *
* Copyright 2006 One Laptop Per Child Association, Inc.
* Copyright 2006-7 Jonathan Corbet <corbet@lwn.net>
*
@@ -2232,13 +2235,16 @@ static int cafe_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct cafe_camera *cam = cafe_find_by_pdev(pdev);
int ret;
+ enum cafe_state cstate;
ret = pci_save_state(pdev);
if (ret)
return ret;
+ cstate = cam->state; /* HACK - stop_dma sets to idle */
cafe_ctlr_stop_dma(cam);
cafe_ctlr_power_down(cam);
pci_disable_device(pdev);
+ cam->state = cstate;
return 0;
}
diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c
index a1d02e5ce0fd..7c630f5ee725 100644
--- a/drivers/media/video/cpia.c
+++ b/drivers/media/video/cpia.c
@@ -65,10 +65,6 @@ MODULE_PARM_DESC(colorspace_conv,
#define ABOUT "V4L-Driver for Vision CPiA based cameras"
-#ifndef VID_HARDWARE_CPIA
-#define VID_HARDWARE_CPIA 24 /* FIXME -> from linux/videodev.h */
-#endif
-
#define CPIA_MODULE_CPIA (0<<5)
#define CPIA_MODULE_SYSTEM (1<<5)
#define CPIA_MODULE_VP_CTRL (5<<5)
@@ -3804,7 +3800,6 @@ static struct video_device cpia_template = {
.owner = THIS_MODULE,
.name = "CPiA Camera",
.type = VID_TYPE_CAPTURE,
- .hardware = VID_HARDWARE_CPIA,
.fops = &cpia_fops,
};
diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c
index e3aaba1e0e0a..e378abec806d 100644
--- a/drivers/media/video/cpia2/cpia2_v4l.c
+++ b/drivers/media/video/cpia2/cpia2_v4l.c
@@ -86,10 +86,6 @@ MODULE_LICENSE("GPL");
#define ABOUT "V4L-Driver for Vision CPiA2 based cameras"
-#ifndef VID_HARDWARE_CPIA2
-#error "VID_HARDWARE_CPIA2 should have been defined in linux/videodev.h"
-#endif
-
struct control_menu_info {
int value;
char name[32];
@@ -1942,7 +1938,6 @@ static struct video_device cpia2_template = {
.type= VID_TYPE_CAPTURE,
.type2 = V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_STREAMING,
- .hardware= VID_HARDWARE_CPIA2,
.minor= -1,
.fops= &fops_template,
.release= video_device_release,
diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig
index 72004a07b2d5..d8b1ccb44913 100644
--- a/drivers/media/video/cx23885/Kconfig
+++ b/drivers/media/video/cx23885/Kconfig
@@ -1,6 +1,6 @@
config VIDEO_CX23885
tristate "Conexant cx23885 (2388x successor) support"
- depends on DVB_CORE && VIDEO_DEV && PCI && I2C
+ depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT
select I2C_ALGOBIT
select FW_LOADER
select VIDEO_BTCX
diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c
index af16505bd2e0..3cdd136477e5 100644
--- a/drivers/media/video/cx23885/cx23885-core.c
+++ b/drivers/media/video/cx23885/cx23885-core.c
@@ -793,7 +793,7 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
dev->pci->subsystem_device);
cx23885_devcount--;
- goto fail_free;
+ return -ENODEV;
}
/* PCIe stuff */
@@ -835,10 +835,6 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
}
return 0;
-
-fail_free:
- kfree(dev);
- return -ENODEV;
}
void cx23885_dev_unregister(struct cx23885_dev *dev)
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig
index eeb5224ca101..ceb31d4a2512 100644
--- a/drivers/media/video/cx88/Kconfig
+++ b/drivers/media/video/cx88/Kconfig
@@ -1,6 +1,6 @@
config VIDEO_CX88
tristate "Conexant 2388x (bt878 successor) support"
- depends on VIDEO_DEV && PCI && I2C
+ depends on VIDEO_DEV && PCI && I2C && INPUT
select I2C_ALGOBIT
select FW_LOADER
select VIDEO_BTCX
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c
index 90c36c5705c3..40ffd7a5579a 100644
--- a/drivers/media/video/cx88/cx88-alsa.c
+++ b/drivers/media/video/cx88/cx88-alsa.c
@@ -7,7 +7,7 @@
* (c) 2005,2006 Ricardo Cerqueira <v4l@cerqueira.org>
* (c) 2005 Mauro Carvalho Chehab <mchehab@infradead.org>
* Based on a dummy cx88 module by Gerd Knorr <kraxel@bytesex.org>
- * Based on dummy.c by Jaroslav Kysela <perex@suse.cz>
+ * Based on dummy.c by Jaroslav Kysela <perex@perex.cz>
*
* 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
@@ -39,6 +39,7 @@
#include <sound/pcm_params.h>
#include <sound/control.h>
#include <sound/initval.h>
+#include <sound/tlv.h>
#include "cx88.h"
#include "cx88-reg.h"
@@ -82,6 +83,7 @@ typedef struct cx88_audio_dev snd_cx88_card_t;
+
/****************************************************************************
Module global static vars
****************************************************************************/
@@ -545,8 +547,8 @@ static int __devinit snd_cx88_pcm(snd_cx88_card_t *chip, int device, char *name)
/****************************************************************************
CONTROL INTERFACE
****************************************************************************/
-static int snd_cx88_capture_volume_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *info)
+static int snd_cx88_volume_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *info)
{
info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
info->count = 2;
@@ -556,9 +558,8 @@ static int snd_cx88_capture_volume_info(struct snd_kcontrol *kcontrol,
return 0;
}
-/* OK - TODO: test it */
-static int snd_cx88_capture_volume_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *value)
+static int snd_cx88_volume_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *value)
{
snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
struct cx88_core *core=chip->core;
@@ -573,8 +574,8 @@ static int snd_cx88_capture_volume_get(struct snd_kcontrol *kcontrol,
}
/* OK - TODO: test it */
-static int snd_cx88_capture_volume_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *value)
+static int snd_cx88_volume_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *value)
{
snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
struct cx88_core *core=chip->core;
@@ -605,14 +606,67 @@ static int snd_cx88_capture_volume_put(struct snd_kcontrol *kcontrol,
return changed;
}
-static struct snd_kcontrol_new snd_cx88_capture_volume = {
+static const DECLARE_TLV_DB_SCALE(snd_cx88_db_scale, -6300, 100, 0);
+
+static struct snd_kcontrol_new snd_cx88_volume = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+ .name = "Playback Volume",
+ .info = snd_cx88_volume_info,
+ .get = snd_cx88_volume_get,
+ .put = snd_cx88_volume_put,
+ .tlv.p = snd_cx88_db_scale,
+};
+
+static int snd_cx88_switch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *value)
+{
+ snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
+ struct cx88_core *core = chip->core;
+ u32 bit = kcontrol->private_value;
+
+ value->value.integer.value[0] = !(cx_read(AUD_VOL_CTL) & bit);
+ return 0;
+}
+
+static int snd_cx88_switch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *value)
+{
+ snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
+ struct cx88_core *core = chip->core;
+ u32 bit = kcontrol->private_value;
+ int ret = 0;
+ u32 vol;
+
+ spin_lock_irq(&chip->reg_lock);
+ vol = cx_read(AUD_VOL_CTL);
+ if (value->value.integer.value[0] != !(vol & bit)) {
+ vol ^= bit;
+ cx_write(AUD_VOL_CTL, vol);
+ ret = 1;
+ }
+ spin_unlock_irq(&chip->reg_lock);
+ return ret;
+}
+
+static struct snd_kcontrol_new snd_cx88_dac_switch = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Capture Volume",
- .info = snd_cx88_capture_volume_info,
- .get = snd_cx88_capture_volume_get,
- .put = snd_cx88_capture_volume_put,
+ .name = "Playback Switch",
+ .info = snd_ctl_boolean_mono_info,
+ .get = snd_cx88_switch_get,
+ .put = snd_cx88_switch_put,
+ .private_value = (1<<8),
};
+static struct snd_kcontrol_new snd_cx88_source_switch = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Capture Switch",
+ .info = snd_ctl_boolean_mono_info,
+ .get = snd_cx88_switch_get,
+ .put = snd_cx88_switch_put,
+ .private_value = (1<<6),
+};
/****************************************************************************
Basic Flow for Sound Devices
@@ -762,7 +816,13 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci,
if (err < 0)
goto error;
- err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_capture_volume, chip));
+ err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_volume, chip));
+ if (err < 0)
+ goto error;
+ err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_dac_switch, chip));
+ if (err < 0)
+ goto error;
+ err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_source_switch, chip));
if (err < 0)
goto error;
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
index 6d6f5048d762..f33f0b47142c 100644
--- a/drivers/media/video/cx88/cx88-blackbird.c
+++ b/drivers/media/video/cx88/cx88-blackbird.c
@@ -527,44 +527,6 @@ static void blackbird_codec_settings(struct cx8802_dev *dev)
cx2341x_update(dev, blackbird_mbox_func, NULL, &dev->params);
}
-static struct v4l2_mpeg_compression default_mpeg_params = {
- .st_type = V4L2_MPEG_PS_2,
- .st_bitrate = {
- .mode = V4L2_BITRATE_CBR,
- .min = 0,
- .target = 0,
- .max = 0
- },
- .ts_pid_pmt = 16,
- .ts_pid_audio = 260,
- .ts_pid_video = 256,
- .ts_pid_pcr = 259,
- .ps_size = 0,
- .au_type = V4L2_MPEG_AU_2_II,
- .au_bitrate = {
- .mode = V4L2_BITRATE_CBR,
- .min = 224,
- .target = 224,
- .max = 224
- },
- .au_sample_rate = 48000,
- .au_pesid = 0,
- .vi_type = V4L2_MPEG_VI_2,
- .vi_aspect_ratio = V4L2_MPEG_ASPECT_4_3,
- .vi_bitrate = {
- .mode = V4L2_BITRATE_CBR,
- .min = 4000,
- .target = 4500,
- .max = 6000
- },
- .vi_frame_rate = 25,
- .vi_frames_per_gop = 12,
- .vi_bframes_count = 2,
- .vi_pesid = 0,
- .closed_gops = 1,
- .pulldown = 0
-};
-
static int blackbird_initialize_codec(struct cx8802_dev *dev)
{
struct cx88_core *core = dev->core;
@@ -852,23 +814,6 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
return videobuf_streamoff(&fh->mpegq);
}
-static int vidioc_g_mpegcomp (struct file *file, void *fh,
- struct v4l2_mpeg_compression *f)
-{
- printk(KERN_WARNING "VIDIOC_G_MPEGCOMP is obsolete. "
- "Replace with VIDIOC_G_EXT_CTRLS!");
- memcpy(f,&default_mpeg_params,sizeof(*f));
- return 0;
-}
-
-static int vidioc_s_mpegcomp (struct file *file, void *fh,
- struct v4l2_mpeg_compression *f)
-{
- printk(KERN_WARNING "VIDIOC_S_MPEGCOMP is obsolete. "
- "Replace with VIDIOC_S_EXT_CTRLS!");
- return 0;
-}
-
static int vidioc_g_ext_ctrls (struct file *file, void *priv,
struct v4l2_ext_controls *f)
{
@@ -1216,8 +1161,6 @@ static struct video_device cx8802_mpeg_template =
.vidioc_dqbuf = vidioc_dqbuf,
.vidioc_streamon = vidioc_streamon,
.vidioc_streamoff = vidioc_streamoff,
- .vidioc_g_mpegcomp = vidioc_g_mpegcomp,
- .vidioc_s_mpegcomp = vidioc_s_mpegcomp,
.vidioc_g_ext_ctrls = vidioc_g_ext_ctrls,
.vidioc_s_ext_ctrls = vidioc_s_ext_ctrls,
.vidioc_try_ext_ctrls = vidioc_try_ext_ctrls,
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index d16e5c6d21c0..fce19caf9d04 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -475,8 +475,9 @@ static int dvb_register(struct cx8802_dev *dev)
break;
case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
#if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE))
+ /* MT352 is on a secondary I2C bus made from some GPIO lines */
dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config,
- &((struct vp3054_i2c_state *)dev->card_priv)->adap);
+ &dev->vp3054->adap);
if (dev->dvb.frontend != NULL) {
dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
&dev->core->i2c_adap, DVB_PLL_FMD1216ME);
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c
index a652f294d23d..448c67380945 100644
--- a/drivers/media/video/cx88/cx88-mpeg.c
+++ b/drivers/media/video/cx88/cx88-mpeg.c
@@ -79,7 +79,8 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
{
struct cx88_core *core = dev->core;
- dprintk(1, "cx8802_start_dma w: %d, h: %d, f: %d\n", dev->width, dev->height, buf->vb.field);
+ dprintk(1, "cx8802_start_dma w: %d, h: %d, f: %d\n",
+ buf->vb.width, buf->vb.height, buf->vb.field);
/* setup fifo + format */
cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28],
@@ -177,7 +178,6 @@ static int cx8802_restart_queue(struct cx8802_dev *dev,
struct cx88_dmaqueue *q)
{
struct cx88_buffer *buf;
- struct list_head *item;
dprintk( 1, "cx8802_restart_queue\n" );
if (list_empty(&q->active))
@@ -223,10 +223,8 @@ static int cx8802_restart_queue(struct cx8802_dev *dev,
dprintk(2,"restart_queue [%p/%d]: restart dma\n",
buf, buf->vb.i);
cx8802_start_dma(dev, q, buf);
- list_for_each(item,&q->active) {
- buf = list_entry(item, struct cx88_buffer, vb.queue);
+ list_for_each_entry(buf, &q->active, vb.queue)
buf->count = q->count++;
- }
mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
return 0;
}
@@ -572,42 +570,29 @@ int cx8802_resume_common(struct pci_dev *pci_dev)
return 0;
}
+#if defined(CONFIG_VIDEO_CX88_BLACKBIRD) || \
+ defined(CONFIG_VIDEO_CX88_BLACKBIRD_MODULE)
struct cx8802_dev * cx8802_get_device(struct inode *inode)
{
int minor = iminor(inode);
- struct cx8802_dev *h = NULL;
- struct list_head *list;
+ struct cx8802_dev *dev;
- list_for_each(list,&cx8802_devlist) {
- h = list_entry(list, struct cx8802_dev, devlist);
- if (h->mpeg_dev && h->mpeg_dev->minor == minor)
- return h;
- }
+ list_for_each_entry(dev, &cx8802_devlist, devlist)
+ if (dev->mpeg_dev && dev->mpeg_dev->minor == minor)
+ return dev;
return NULL;
}
+EXPORT_SYMBOL(cx8802_get_device);
+#endif
struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype)
{
- struct cx8802_dev *h = NULL;
- struct cx8802_driver *d = NULL;
- struct list_head *list;
- struct list_head *list2;
-
- list_for_each(list,&cx8802_devlist) {
- h = list_entry(list, struct cx8802_dev, devlist);
- if (h != dev)
- continue;
-
- list_for_each(list2, &h->drvlist.devlist) {
- d = list_entry(list2, struct cx8802_driver, devlist);
+ struct cx8802_driver *d;
- /* only unregister the correct driver type */
- if (d->type_id == btype) {
- return d;
- }
- }
- }
+ list_for_each_entry(d, &dev->drvlist, drvlist)
+ if (d->type_id == btype)
+ return d;
return NULL;
}
@@ -671,10 +656,9 @@ static int cx8802_check_driver(struct cx8802_driver *drv)
int cx8802_register_driver(struct cx8802_driver *drv)
{
- struct cx8802_dev *h;
+ struct cx8802_dev *dev;
struct cx8802_driver *driver;
- struct list_head *list;
- int err = 0, i = 0;
+ int err, i = 0;
printk(KERN_INFO
"cx88/2: registering cx8802 driver, type: %s access: %s\n",
@@ -686,14 +670,12 @@ int cx8802_register_driver(struct cx8802_driver *drv)
return err;
}
- list_for_each(list,&cx8802_devlist) {
- h = list_entry(list, struct cx8802_dev, devlist);
-
+ list_for_each_entry(dev, &cx8802_devlist, devlist) {
printk(KERN_INFO
"%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n",
- h->core->name, h->pci->subsystem_vendor,
- h->pci->subsystem_device, h->core->board.name,
- h->core->boardnr);
+ dev->core->name, dev->pci->subsystem_vendor,
+ dev->pci->subsystem_device, dev->core->board.name,
+ dev->core->boardnr);
/* Bring up a new struct for each driver instance */
driver = kzalloc(sizeof(*drv),GFP_KERNEL);
@@ -701,7 +683,7 @@ int cx8802_register_driver(struct cx8802_driver *drv)
return -ENOMEM;
/* Snapshot of the driver registration data */
- drv->core = h->core;
+ drv->core = dev->core;
drv->suspend = cx8802_suspend_common;
drv->resume = cx8802_resume_common;
drv->request_acquire = cx8802_request_acquire;
@@ -712,49 +694,38 @@ int cx8802_register_driver(struct cx8802_driver *drv)
if (err == 0) {
i++;
mutex_lock(&drv->core->lock);
- list_add_tail(&driver->devlist,&h->drvlist.devlist);
+ list_add_tail(&driver->drvlist, &dev->drvlist);
mutex_unlock(&drv->core->lock);
} else {
printk(KERN_ERR
"%s/2: cx8802 probe failed, err = %d\n",
- h->core->name, err);
+ dev->core->name, err);
}
}
- if (i == 0)
- err = -ENODEV;
- else
- err = 0;
- return err;
+ return i ? 0 : -ENODEV;
}
int cx8802_unregister_driver(struct cx8802_driver *drv)
{
- struct cx8802_dev *h;
- struct cx8802_driver *d;
- struct list_head *list;
- struct list_head *list2, *q;
- int err = 0, i = 0;
+ struct cx8802_dev *dev;
+ struct cx8802_driver *d, *dtmp;
+ int err = 0;
printk(KERN_INFO
"cx88/2: unregistering cx8802 driver, type: %s access: %s\n",
drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird",
drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive");
- list_for_each(list,&cx8802_devlist) {
- i++;
- h = list_entry(list, struct cx8802_dev, devlist);
-
+ list_for_each_entry(dev, &cx8802_devlist, devlist) {
printk(KERN_INFO
"%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n",
- h->core->name, h->pci->subsystem_vendor,
- h->pci->subsystem_device, h->core->board.name,
- h->core->boardnr);
-
- list_for_each_safe(list2, q, &h->drvlist.devlist) {
- d = list_entry(list2, struct cx8802_driver, devlist);
+ dev->core->name, dev->pci->subsystem_vendor,
+ dev->pci->subsystem_device, dev->core->board.name,
+ dev->core->boardnr);
+ list_for_each_entry_safe(d, dtmp, &dev->drvlist, drvlist) {
/* only unregister the correct driver type */
if (d->type_id != drv->type_id)
continue;
@@ -762,12 +733,12 @@ int cx8802_unregister_driver(struct cx8802_driver *drv)
err = d->remove(d);
if (err == 0) {
mutex_lock(&drv->core->lock);
- list_del(list2);
+ list_del(&d->drvlist);
mutex_unlock(&drv->core->lock);
+ kfree(d);
} else
printk(KERN_ERR "%s/2: cx8802 driver remove "
- "failed (%d)\n", h->core->name, err);
-
+ "failed (%d)\n", dev->core->name, err);
}
}
@@ -805,7 +776,7 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev,
if (err != 0)
goto fail_free;
- INIT_LIST_HEAD(&dev->drvlist.devlist);
+ INIT_LIST_HEAD(&dev->drvlist);
list_add_tail(&dev->devlist,&cx8802_devlist);
/* Maintain a reference so cx88-video can query the 8802 device. */
@@ -825,23 +796,30 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev,
static void __devexit cx8802_remove(struct pci_dev *pci_dev)
{
struct cx8802_dev *dev;
- struct cx8802_driver *h;
- struct list_head *list;
dev = pci_get_drvdata(pci_dev);
dprintk( 1, "%s\n", __FUNCTION__);
- list_for_each(list,&dev->drvlist.devlist) {
- h = list_entry(list, struct cx8802_driver, devlist);
- dprintk( 1, " ->driver\n");
- if (h->remove == NULL) {
- printk(KERN_ERR "%s .. skipping driver, no probe function\n", __FUNCTION__);
- continue;
+ if (!list_empty(&dev->drvlist)) {
+ struct cx8802_driver *drv, *tmp;
+ int err;
+
+ printk(KERN_WARNING "%s/2: Trying to remove cx8802 driver "
+ "while cx8802 sub-drivers still loaded?!\n",
+ dev->core->name);
+
+ list_for_each_entry_safe(drv, tmp, &dev->drvlist, drvlist) {
+ err = drv->remove(drv);
+ if (err == 0) {
+ mutex_lock(&drv->core->lock);
+ list_del(&drv->drvlist);
+ mutex_unlock(&drv->core->lock);
+ } else
+ printk(KERN_ERR "%s/2: cx8802 driver remove "
+ "failed (%d)\n", dev->core->name, err);
+ kfree(drv);
}
- printk(KERN_INFO "%s .. Removing driver type %d\n", __FUNCTION__, h->type_id);
- cx8802_unregister_driver(h);
- list_del(&dev->drvlist.devlist);
}
/* Destroy any 8802 reference. */
@@ -901,7 +879,6 @@ EXPORT_SYMBOL(cx8802_fini_common);
EXPORT_SYMBOL(cx8802_register_driver);
EXPORT_SYMBOL(cx8802_unregister_driver);
-EXPORT_SYMBOL(cx8802_get_device);
EXPORT_SYMBOL(cx8802_get_driver);
/* ----------------------------------------------------------- */
/*
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index 231ae6c4dd22..5ee05f8f3fad 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -1675,7 +1675,6 @@ static struct video_device cx8800_radio_template =
{
.name = "cx8800-radio",
.type = VID_TYPE_TUNER,
- .hardware = 0,
.fops = &radio_fops,
.minor = -1,
.vidioc_querycap = radio_querycap,
diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.c b/drivers/media/video/cx88/cx88-vp3054-i2c.c
index 77c37889232b..6ce5af488471 100644
--- a/drivers/media/video/cx88/cx88-vp3054-i2c.c
+++ b/drivers/media/video/cx88/cx88-vp3054-i2c.c
@@ -41,7 +41,7 @@ static void vp3054_bit_setscl(void *data, int state)
{
struct cx8802_dev *dev = data;
struct cx88_core *core = dev->core;
- struct vp3054_i2c_state *vp3054_i2c = dev->card_priv;
+ struct vp3054_i2c_state *vp3054_i2c = dev->vp3054;
if (state) {
vp3054_i2c->state |= 0x0001; /* SCL high */
@@ -58,7 +58,7 @@ static void vp3054_bit_setsda(void *data, int state)
{
struct cx8802_dev *dev = data;
struct cx88_core *core = dev->core;
- struct vp3054_i2c_state *vp3054_i2c = dev->card_priv;
+ struct vp3054_i2c_state *vp3054_i2c = dev->vp3054;
if (state) {
vp3054_i2c->state |= 0x0002; /* SDA high */
@@ -113,10 +113,10 @@ int vp3054_i2c_probe(struct cx8802_dev *dev)
if (core->boardnr != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)
return 0;
- dev->card_priv = kzalloc(sizeof(*vp3054_i2c), GFP_KERNEL);
- if (dev->card_priv == NULL)
+ vp3054_i2c = kzalloc(sizeof(*vp3054_i2c), GFP_KERNEL);
+ if (vp3054_i2c == NULL)
return -ENOMEM;
- vp3054_i2c = dev->card_priv;
+ dev->vp3054 = vp3054_i2c;
memcpy(&vp3054_i2c->algo, &vp3054_i2c_algo_template,
sizeof(vp3054_i2c->algo));
@@ -139,8 +139,8 @@ int vp3054_i2c_probe(struct cx8802_dev *dev)
if (0 != rc) {
printk("%s: vp3054_i2c register FAILED\n", core->name);
- kfree(dev->card_priv);
- dev->card_priv = NULL;
+ kfree(dev->vp3054);
+ dev->vp3054 = NULL;
}
return rc;
@@ -148,7 +148,7 @@ int vp3054_i2c_probe(struct cx8802_dev *dev)
void vp3054_i2c_remove(struct cx8802_dev *dev)
{
- struct vp3054_i2c_state *vp3054_i2c = dev->card_priv;
+ struct vp3054_i2c_state *vp3054_i2c = dev->vp3054;
if (vp3054_i2c == NULL ||
dev->core->boardnr != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
index 42e0a9b8c550..eb296bdecb1e 100644
--- a/drivers/media/video/cx88/cx88.h
+++ b/drivers/media/video/cx88/cx88.h
@@ -412,7 +412,9 @@ struct cx8802_suspend_state {
struct cx8802_driver {
struct cx88_core *core;
- struct list_head devlist;
+
+ /* List of drivers attached to device */
+ struct list_head drvlist;
/* Type of driver and access required */
enum cx88_board_type type_id;
@@ -453,27 +455,33 @@ struct cx8802_dev {
/* for blackbird only */
struct list_head devlist;
+#if defined(CONFIG_VIDEO_CX88_BLACKBIRD) || \
+ defined(CONFIG_VIDEO_CX88_BLACKBIRD_MODULE)
struct video_device *mpeg_dev;
u32 mailbox;
int width;
int height;
+ /* mpeg params */
+ struct cx2341x_mpeg_params params;
+#endif
+
#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
/* for dvb only */
struct videobuf_dvb dvb;
+#endif
- void *card_priv;
+#if defined(CONFIG_VIDEO_CX88_VP3054) || \
+ defined(CONFIG_VIDEO_CX88_VP3054_MODULE)
+ /* For VP3045 secondary I2C bus support */
+ struct vp3054_i2c_state *vp3054;
#endif
/* for switching modulation types */
unsigned char ts_gen_cntrl;
- /* mpeg params */
- struct cx2341x_mpeg_params params;
-
/* List of attached drivers */
- struct cx8802_driver drvlist;
- struct work_struct request_module_wk;
-
+ struct list_head drvlist;
+ struct work_struct request_module_wk;
};
/* ----------------------------------------------------------- */
diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig
index 5b6a40371602..c1127802ad9c 100644
--- a/drivers/media/video/em28xx/Kconfig
+++ b/drivers/media/video/em28xx/Kconfig
@@ -1,6 +1,6 @@
config VIDEO_EM28XX
tristate "Empia EM2800/2820/2840 USB video capture support"
- depends on VIDEO_V4L1 && I2C
+ depends on VIDEO_V4L1 && I2C && INPUT
select VIDEO_TUNER
select VIDEO_TVEEPROM
select VIDEO_IR
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
index d3282ec62c5b..d56484f20467 100644
--- a/drivers/media/video/em28xx/em28xx-core.c
+++ b/drivers/media/video/em28xx/em28xx-core.c
@@ -648,7 +648,7 @@ void em28xx_uninit_isoc(struct em28xx *dev)
*/
int em28xx_init_isoc(struct em28xx *dev)
{
- /* change interface to 3 which allowes the biggest packet sizes */
+ /* change interface to 3 which allows the biggest packet sizes */
int i, errCode;
const int sb_size = EM28XX_NUM_PACKETS * dev->max_pkt_size;
@@ -673,6 +673,7 @@ int em28xx_init_isoc(struct em28xx *dev)
("unable to allocate %i bytes for transfer buffer %i\n",
sb_size, i);
em28xx_uninit_isoc(dev);
+ usb_free_urb(urb);
return -ENOMEM;
}
memset(dev->transfer_buffer[i], 0, sb_size);
diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c
index 997d067e32e0..e3a4aa7a9df4 100644
--- a/drivers/media/video/em28xx/em28xx-i2c.c
+++ b/drivers/media/video/em28xx/em28xx-i2c.c
@@ -416,8 +416,10 @@ static int attach_inform(struct i2c_client *client)
struct em28xx *dev = client->adapter->algo_data;
switch (client->addr << 1) {
- case 0x43:
- case 0x4b:
+ case 0x86:
+ case 0x84:
+ case 0x96:
+ case 0x94:
{
struct tuner_setup tun_setup;
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index b8d5327c438d..2529c298b862 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -32,6 +32,7 @@
#include <linux/usb.h>
#include <linux/i2c.h>
#include <linux/version.h>
+#include <linux/mm.h>
#include <linux/video_decoder.h>
#include <linux/mutex.h>
@@ -907,7 +908,7 @@ static int em28xx_set_fmt(struct em28xx *dev, unsigned int cmd, struct v4l2_form
/* stop io in case it is already in progress */
if (dev->stream == STREAM_ON) {
- em28xx_videodbg("VIDIOC_SET_FMT: interupting stream\n");
+ em28xx_videodbg("VIDIOC_SET_FMT: interrupting stream\n");
if ((ret = em28xx_stream_interrupt(dev)))
return ret;
}
@@ -1617,7 +1618,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
/* Fills VBI device info */
dev->vbi_dev->type = VFL_TYPE_VBI;
- dev->vbi_dev->hardware = 0;
dev->vbi_dev->fops = &em28xx_v4l_fops;
dev->vbi_dev->minor = -1;
dev->vbi_dev->dev = &dev->udev->dev;
@@ -1629,7 +1629,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
dev->vdev->type = VID_TYPE_CAPTURE;
if (dev->has_tuner)
dev->vdev->type |= VID_TYPE_TUNER;
- dev->vdev->hardware = 0;
dev->vdev->fops = &em28xx_v4l_fops;
dev->vdev->minor = -1;
dev->vdev->dev = &dev->udev->dev;
diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c
index d5fef4c01c87..d19d73b81ede 100644
--- a/drivers/media/video/et61x251/et61x251_core.c
+++ b/drivers/media/video/et61x251/et61x251_core.c
@@ -2585,7 +2585,6 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
strcpy(cam->v4ldev->name, "ET61X[12]51 PC Camera");
cam->v4ldev->owner = THIS_MODULE;
cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES;
- cam->v4ldev->hardware = 0;
cam->v4ldev->fops = &et61x251_fops;
cam->v4ldev->minor = video_nr[dev_nr];
cam->v4ldev->release = video_device_release;
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
index d98dd0d1e373..29779d8bf7fb 100644
--- a/drivers/media/video/ir-kbd-i2c.c
+++ b/drivers/media/video/ir-kbd-i2c.c
@@ -528,6 +528,7 @@ static int ir_probe(struct i2c_adapter *adap)
break;
case I2C_HW_B_CX2388x:
probe = probe_cx88;
+ break;
case I2C_HW_B_CX23885:
probe = probe_cx23885;
break;
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c
index fd7a932e1d33..6d2dd8764f81 100644
--- a/drivers/media/video/ivtv/ivtv-driver.c
+++ b/drivers/media/video/ivtv/ivtv-driver.c
@@ -1003,8 +1003,6 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
IVTV_DEBUG_INFO("base addr: 0x%08x\n", itv->base_addr);
- mutex_lock(&itv->serialize_lock);
-
/* PCI Device Setup */
if ((retval = ivtv_setup_pci(itv, dev, pci_id)) != 0) {
if (retval == -EIO)
@@ -1064,7 +1062,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
IVTV_DEBUG_INFO("activating i2c...\n");
if (init_ivtv_i2c(itv)) {
IVTV_ERR("Could not initialize i2c\n");
- goto free_irq;
+ goto free_io;
}
IVTV_DEBUG_INFO("Active card count: %d.\n", ivtv_cards_active);
@@ -1176,7 +1174,11 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
IVTV_ERR("Failed to register irq %d\n", retval);
goto free_streams;
}
- mutex_unlock(&itv->serialize_lock);
+ retval = ivtv_streams_register(itv);
+ if (retval) {
+ IVTV_ERR("Error %d registering devices\n", retval);
+ goto free_irq;
+ }
IVTV_INFO("Initialized card #%d: %s\n", itv->num, itv->card_name);
return 0;
@@ -1195,7 +1197,6 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE);
free_workqueue:
destroy_workqueue(itv->irq_work_queues);
- mutex_unlock(&itv->serialize_lock);
err:
if (retval == 0)
retval = -ENODEV;
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h
index 3bda1df63cb6..49ce14d14a54 100644
--- a/drivers/media/video/ivtv/ivtv-driver.h
+++ b/drivers/media/video/ivtv/ivtv-driver.h
@@ -51,6 +51,7 @@
#include <linux/unistd.h>
#include <linux/byteorder/swab.h>
#include <linux/pagemap.h>
+#include <linux/scatterlist.h>
#include <linux/workqueue.h>
#include <linux/mutex.h>
#include <asm/uaccess.h>
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c
index da50fa4a72a5..a200a8a95a2d 100644
--- a/drivers/media/video/ivtv/ivtv-fileops.c
+++ b/drivers/media/video/ivtv/ivtv-fileops.c
@@ -822,6 +822,11 @@ int ivtv_v4l2_close(struct inode *inode, struct file *filp)
crystal_freq.flags = 0;
ivtv_saa7115(itv, VIDIOC_INT_S_CRYSTAL_FREQ, &crystal_freq);
}
+ if (atomic_read(&itv->capturing) > 0) {
+ /* Undo video mute */
+ ivtv_vapi(itv, CX2341X_ENC_MUTE_VIDEO, 1,
+ itv->params.video_mute | (itv->params.video_mute_yuv << 8));
+ }
/* Done! Unmute and continue. */
ivtv_unmute(itv);
ivtv_release_stream(s);
@@ -892,6 +897,7 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp)
if (atomic_read(&itv->capturing) > 0) {
/* switching to radio while capture is
in progress is not polite */
+ ivtv_release_stream(s);
kfree(item);
return -EBUSY;
}
@@ -947,7 +953,7 @@ int ivtv_v4l2_open(struct inode *inode, struct file *filp)
if (itv == NULL) {
/* Couldn't find a device registered
on that minor, shouldn't happen! */
- IVTV_WARN("No ivtv device found on minor %d\n", minor);
+ printk(KERN_WARNING "No ivtv device found on minor %d\n", minor);
return -ENXIO;
}
diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c
index 285fca676a69..623eea2652ca 100644
--- a/drivers/media/video/ivtv/ivtv-i2c.c
+++ b/drivers/media/video/ivtv/ivtv-i2c.c
@@ -741,7 +741,7 @@ int __devinit init_ivtv_i2c(struct ivtv *itv)
return i2c_bit_add_bus(&itv->i2c_adap);
}
-void __devexit exit_ivtv_i2c(struct ivtv *itv)
+void exit_ivtv_i2c(struct ivtv *itv)
{
IVTV_DEBUG_I2C("i2c exit\n");
diff --git a/drivers/media/video/ivtv/ivtv-i2c.h b/drivers/media/video/ivtv/ivtv-i2c.h
index 677c3292855e..de6a07442298 100644
--- a/drivers/media/video/ivtv/ivtv-i2c.h
+++ b/drivers/media/video/ivtv/ivtv-i2c.h
@@ -36,6 +36,6 @@ void ivtv_call_i2c_clients(struct ivtv *itv, unsigned int cmd, void *arg);
/* init + register i2c algo-bit adapter */
int __devinit init_ivtv_i2c(struct ivtv *itv);
-void __devexit exit_ivtv_i2c(struct ivtv *itv);
+void exit_ivtv_i2c(struct ivtv *itv);
#endif
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c
index 206eee7542db..fd6826f472e3 100644
--- a/drivers/media/video/ivtv/ivtv-ioctl.c
+++ b/drivers/media/video/ivtv/ivtv-ioctl.c
@@ -555,6 +555,7 @@ static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype,
/* set window size */
if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ struct cx2341x_mpeg_params *p = &itv->params;
int w = fmt->fmt.pix.width;
int h = fmt->fmt.pix.height;
@@ -566,17 +567,19 @@ static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype,
fmt->fmt.pix.width = w;
fmt->fmt.pix.height = h;
- if (!set_fmt || (itv->params.width == w && itv->params.height == h))
+ if (!set_fmt || (p->width == w && p->height == h))
return 0;
if (atomic_read(&itv->capturing) > 0)
return -EBUSY;
- itv->params.width = w;
- itv->params.height = h;
+ p->width = w;
+ p->height = h;
if (w != 720 || h != (itv->is_50hz ? 576 : 480))
- itv->params.video_temporal_filter = 0;
+ p->video_temporal_filter = 0;
else
- itv->params.video_temporal_filter = 8;
+ p->video_temporal_filter = 8;
+ if (p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
+ fmt->fmt.pix.width /= 2;
itv->video_dec_func(itv, VIDIOC_S_FMT, fmt);
return ivtv_get_fmt(itv, streamtype, fmt);
}
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c
index fd135985e70f..aa03e61ef310 100644
--- a/drivers/media/video/ivtv/ivtv-streams.c
+++ b/drivers/media/video/ivtv/ivtv-streams.c
@@ -166,10 +166,9 @@ static void ivtv_stream_init(struct ivtv *itv, int type)
ivtv_queue_init(&s->q_io);
}
-static int ivtv_reg_dev(struct ivtv *itv, int type)
+static int ivtv_prep_dev(struct ivtv *itv, int type)
{
struct ivtv_stream *s = &itv->streams[type];
- int vfl_type = ivtv_stream_info[type].vfl_type;
int minor_offset = ivtv_stream_info[type].minor_offset;
int minor;
@@ -187,15 +186,12 @@ static int ivtv_reg_dev(struct ivtv *itv, int type)
if (type >= IVTV_DEC_STREAM_TYPE_MPG && !(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
return 0;
- if (minor_offset >= 0)
- /* card number + user defined offset + device offset */
- minor = itv->num + ivtv_first_minor + minor_offset;
- else
- minor = -1;
+ /* card number + user defined offset + device offset */
+ minor = itv->num + ivtv_first_minor + minor_offset;
/* User explicitly selected 0 buffers for these streams, so don't
create them. */
- if (minor >= 0 && ivtv_stream_info[type].dma != PCI_DMA_NONE &&
+ if (ivtv_stream_info[type].dma != PCI_DMA_NONE &&
itv->options.kilobytes[type] == 0) {
IVTV_INFO("Disabled %s device\n", ivtv_stream_info[type].name);
return 0;
@@ -223,21 +219,53 @@ static int ivtv_reg_dev(struct ivtv *itv, int type)
s->v4l2dev->fops = ivtv_stream_info[type].fops;
s->v4l2dev->release = video_device_release;
- if (minor >= 0) {
- /* Register device. First try the desired minor, then any free one. */
- if (video_register_device(s->v4l2dev, vfl_type, minor) &&
- video_register_device(s->v4l2dev, vfl_type, -1)) {
- IVTV_ERR("Couldn't register v4l2 device for %s minor %d\n",
- s->name, minor);
- video_device_release(s->v4l2dev);
- s->v4l2dev = NULL;
- return -ENOMEM;
- }
+ return 0;
+}
+
+/* Initialize v4l2 variables and prepare v4l2 devices */
+int ivtv_streams_setup(struct ivtv *itv)
+{
+ int type;
+
+ /* Setup V4L2 Devices */
+ for (type = 0; type < IVTV_MAX_STREAMS; type++) {
+ /* Prepare device */
+ if (ivtv_prep_dev(itv, type))
+ break;
+
+ if (itv->streams[type].v4l2dev == NULL)
+ continue;
+
+ /* Allocate Stream */
+ if (ivtv_stream_alloc(&itv->streams[type]))
+ break;
}
- else {
- /* Don't register a 'hidden' stream (OSD) */
- IVTV_INFO("Created framebuffer stream for %s\n", s->name);
+ if (type == IVTV_MAX_STREAMS)
return 0;
+
+ /* One or more streams could not be initialized. Clean 'em all up. */
+ ivtv_streams_cleanup(itv);
+ return -ENOMEM;
+}
+
+static int ivtv_reg_dev(struct ivtv *itv, int type)
+{
+ struct ivtv_stream *s = &itv->streams[type];
+ int vfl_type = ivtv_stream_info[type].vfl_type;
+ int minor;
+
+ if (s->v4l2dev == NULL)
+ return 0;
+
+ minor = s->v4l2dev->minor;
+ /* Register device. First try the desired minor, then any free one. */
+ if (video_register_device(s->v4l2dev, vfl_type, minor) &&
+ video_register_device(s->v4l2dev, vfl_type, -1)) {
+ IVTV_ERR("Couldn't register v4l2 device for %s minor %d\n",
+ s->name, minor);
+ video_device_release(s->v4l2dev);
+ s->v4l2dev = NULL;
+ return -ENOMEM;
}
switch (vfl_type) {
@@ -262,27 +290,18 @@ static int ivtv_reg_dev(struct ivtv *itv, int type)
return 0;
}
-/* Initialize v4l2 variables and register v4l2 devices */
-int ivtv_streams_setup(struct ivtv *itv)
+/* Register v4l2 devices */
+int ivtv_streams_register(struct ivtv *itv)
{
int type;
+ int err = 0;
- /* Setup V4L2 Devices */
- for (type = 0; type < IVTV_MAX_STREAMS; type++) {
- /* Register Device */
- if (ivtv_reg_dev(itv, type))
- break;
-
- if (itv->streams[type].v4l2dev == NULL)
- continue;
+ /* Register V4L2 devices */
+ for (type = 0; type < IVTV_MAX_STREAMS; type++)
+ err |= ivtv_reg_dev(itv, type);
- /* Allocate Stream */
- if (ivtv_stream_alloc(&itv->streams[type]))
- break;
- }
- if (type == IVTV_MAX_STREAMS) {
+ if (err == 0)
return 0;
- }
/* One or more streams could not be initialized. Clean 'em all up. */
ivtv_streams_cleanup(itv);
@@ -303,11 +322,8 @@ void ivtv_streams_cleanup(struct ivtv *itv)
continue;
ivtv_stream_free(&itv->streams[type]);
- /* Free Device */
- if (vdev->minor == -1) /* 'Hidden' never registered stream (OSD) */
- video_device_release(vdev);
- else /* All others, just unregister. */
- video_unregister_device(vdev);
+ /* Unregister device */
+ video_unregister_device(vdev);
}
}
@@ -425,6 +441,7 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
{
u32 data[CX2341X_MBOX_MAX_DATA];
struct ivtv *itv = s->itv;
+ struct cx2341x_mpeg_params *p = &itv->params;
int captype = 0, subtype = 0;
int enable_passthrough = 0;
@@ -445,7 +462,7 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
}
itv->mpg_data_received = itv->vbi_data_inserted = 0;
itv->dualwatch_jiffies = jiffies;
- itv->dualwatch_stereo_mode = itv->params.audio_properties & 0x0300;
+ itv->dualwatch_stereo_mode = p->audio_properties & 0x0300;
itv->search_pack_header = 0;
break;
@@ -477,9 +494,6 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
s->subtype = subtype;
s->buffers_stolen = 0;
- /* mute/unmute video */
- ivtv_vapi(itv, CX2341X_ENC_MUTE_VIDEO, 1, test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? 1 : 0);
-
/* Clear Streamoff flags in case left from last capture */
clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
@@ -536,7 +550,12 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
itv->pgm_info_offset, itv->pgm_info_num);
/* Setup API for Stream */
- cx2341x_update(itv, ivtv_api_func, NULL, &itv->params);
+ cx2341x_update(itv, ivtv_api_func, NULL, p);
+
+ /* mute if capturing radio */
+ if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags))
+ ivtv_vapi(itv, CX2341X_ENC_MUTE_VIDEO, 1,
+ 1 | (p->video_mute_yuv << 8));
}
/* Vsync Setup */
@@ -585,6 +604,7 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s)
{
u32 data[CX2341X_MBOX_MAX_DATA];
struct ivtv *itv = s->itv;
+ struct cx2341x_mpeg_params *p = &itv->params;
int datatype;
if (s->v4l2dev == NULL)
@@ -623,7 +643,7 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s)
break;
}
if (ivtv_vapi(itv, CX2341X_DEC_SET_DECODER_SOURCE, 4, datatype,
- itv->params.width, itv->params.height, itv->params.audio_properties)) {
+ p->width, p->height, p->audio_properties)) {
IVTV_DEBUG_WARN("Couldn't initialize decoder source\n");
}
return 0;
diff --git a/drivers/media/video/ivtv/ivtv-streams.h b/drivers/media/video/ivtv/ivtv-streams.h
index 8f5f5b1c7c89..3d76a415fbd8 100644
--- a/drivers/media/video/ivtv/ivtv-streams.h
+++ b/drivers/media/video/ivtv/ivtv-streams.h
@@ -22,6 +22,7 @@
#define IVTV_STREAMS_H
int ivtv_streams_setup(struct ivtv *itv);
+int ivtv_streams_register(struct ivtv *itv);
void ivtv_streams_cleanup(struct ivtv *itv);
/* Capture related */
diff --git a/drivers/media/video/ivtv/ivtv-udma.c b/drivers/media/video/ivtv/ivtv-udma.c
index c4626d1cdf41..460db03b0ba0 100644
--- a/drivers/media/video/ivtv/ivtv-udma.c
+++ b/drivers/media/video/ivtv/ivtv-udma.c
@@ -49,8 +49,6 @@ int ivtv_udma_fill_sg_list (struct ivtv_user_dma *dma, struct ivtv_dma_page_info
unsigned int len = (i == dma_page->page_count - 1) ?
dma_page->tail : PAGE_SIZE - offset;
- dma->SGlist[map_offset].length = len;
- dma->SGlist[map_offset].offset = offset;
if (PageHighMem(dma->map[map_offset])) {
void *src;
@@ -63,10 +61,10 @@ int ivtv_udma_fill_sg_list (struct ivtv_user_dma *dma, struct ivtv_dma_page_info
memcpy(page_address(dma->bouncemap[map_offset]) + offset, src, len);
kunmap_atomic(src, KM_BOUNCE_READ);
local_irq_restore(flags);
- dma->SGlist[map_offset].page = dma->bouncemap[map_offset];
+ sg_set_page(&dma->SGlist[map_offset], dma->bouncemap[map_offset], len, offset);
}
else {
- dma->SGlist[map_offset].page = dma->map[map_offset];
+ sg_set_page(&dma->SGlist[map_offset], dma->map[map_offset], len, offset);
}
offset = 0;
map_offset++;
diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c
index e2288f224ab6..9091c4837bbc 100644
--- a/drivers/media/video/ivtv/ivtv-yuv.c
+++ b/drivers/media/video/ivtv/ivtv-yuv.c
@@ -710,7 +710,7 @@ static u32 ivtv_yuv_window_setup (struct ivtv *itv, struct yuv_frame_info *windo
/* If there's nothing to safe to display, we may as well stop now */
if ((int)window->dst_w <= 2 || (int)window->dst_h <= 2 || (int)window->src_w <= 2 || (int)window->src_h <= 2) {
- return 0;
+ return IVTV_YUV_UPDATE_INVALID;
}
/* Ensure video remains inside OSD area */
@@ -791,7 +791,7 @@ static u32 ivtv_yuv_window_setup (struct ivtv *itv, struct yuv_frame_info *windo
/* Check again. If there's nothing to safe to display, stop now */
if ((int)window->dst_w <= 2 || (int)window->dst_h <= 2 || (int)window->src_w <= 2 || (int)window->src_h <= 2) {
- return 0;
+ return IVTV_YUV_UPDATE_INVALID;
}
/* Both x offset & width are linked, so they have to be done together */
@@ -840,110 +840,118 @@ void ivtv_yuv_work_handler (struct ivtv *itv)
if (!(yuv_update = ivtv_yuv_window_setup (itv, &window)))
return;
- /* Update horizontal settings */
- if (yuv_update & IVTV_YUV_UPDATE_HORIZONTAL)
- ivtv_yuv_handle_horizontal(itv, &window);
+ if (yuv_update & IVTV_YUV_UPDATE_INVALID) {
+ write_reg(0x01008080, 0x2898);
+ } else if (yuv_update) {
+ write_reg(0x00108080, 0x2898);
- if (yuv_update & IVTV_YUV_UPDATE_VERTICAL)
- ivtv_yuv_handle_vertical(itv, &window);
+ if (yuv_update & IVTV_YUV_UPDATE_HORIZONTAL)
+ ivtv_yuv_handle_horizontal(itv, &window);
+
+ if (yuv_update & IVTV_YUV_UPDATE_VERTICAL)
+ ivtv_yuv_handle_vertical(itv, &window);
+ }
memcpy(&itv->yuv_info.old_frame_info, &window, sizeof (itv->yuv_info.old_frame_info));
}
static void ivtv_yuv_init (struct ivtv *itv)
{
+ struct yuv_playback_info *yi = &itv->yuv_info;
+
IVTV_DEBUG_YUV("ivtv_yuv_init\n");
/* Take a snapshot of the current register settings */
- itv->yuv_info.reg_2834 = read_reg(0x02834);
- itv->yuv_info.reg_2838 = read_reg(0x02838);
- itv->yuv_info.reg_283c = read_reg(0x0283c);
- itv->yuv_info.reg_2840 = read_reg(0x02840);
- itv->yuv_info.reg_2844 = read_reg(0x02844);
- itv->yuv_info.reg_2848 = read_reg(0x02848);
- itv->yuv_info.reg_2854 = read_reg(0x02854);
- itv->yuv_info.reg_285c = read_reg(0x0285c);
- itv->yuv_info.reg_2864 = read_reg(0x02864);
- itv->yuv_info.reg_2870 = read_reg(0x02870);
- itv->yuv_info.reg_2874 = read_reg(0x02874);
- itv->yuv_info.reg_2898 = read_reg(0x02898);
- itv->yuv_info.reg_2890 = read_reg(0x02890);
-
- itv->yuv_info.reg_289c = read_reg(0x0289c);
- itv->yuv_info.reg_2918 = read_reg(0x02918);
- itv->yuv_info.reg_291c = read_reg(0x0291c);
- itv->yuv_info.reg_2920 = read_reg(0x02920);
- itv->yuv_info.reg_2924 = read_reg(0x02924);
- itv->yuv_info.reg_2928 = read_reg(0x02928);
- itv->yuv_info.reg_292c = read_reg(0x0292c);
- itv->yuv_info.reg_2930 = read_reg(0x02930);
- itv->yuv_info.reg_2934 = read_reg(0x02934);
- itv->yuv_info.reg_2938 = read_reg(0x02938);
- itv->yuv_info.reg_293c = read_reg(0x0293c);
- itv->yuv_info.reg_2940 = read_reg(0x02940);
- itv->yuv_info.reg_2944 = read_reg(0x02944);
- itv->yuv_info.reg_2948 = read_reg(0x02948);
- itv->yuv_info.reg_294c = read_reg(0x0294c);
- itv->yuv_info.reg_2950 = read_reg(0x02950);
- itv->yuv_info.reg_2954 = read_reg(0x02954);
- itv->yuv_info.reg_2958 = read_reg(0x02958);
- itv->yuv_info.reg_295c = read_reg(0x0295c);
- itv->yuv_info.reg_2960 = read_reg(0x02960);
- itv->yuv_info.reg_2964 = read_reg(0x02964);
- itv->yuv_info.reg_2968 = read_reg(0x02968);
- itv->yuv_info.reg_296c = read_reg(0x0296c);
- itv->yuv_info.reg_2970 = read_reg(0x02970);
-
- itv->yuv_info.v_filter_1 = -1;
- itv->yuv_info.v_filter_2 = -1;
- itv->yuv_info.h_filter = -1;
+ yi->reg_2834 = read_reg(0x02834);
+ yi->reg_2838 = read_reg(0x02838);
+ yi->reg_283c = read_reg(0x0283c);
+ yi->reg_2840 = read_reg(0x02840);
+ yi->reg_2844 = read_reg(0x02844);
+ yi->reg_2848 = read_reg(0x02848);
+ yi->reg_2854 = read_reg(0x02854);
+ yi->reg_285c = read_reg(0x0285c);
+ yi->reg_2864 = read_reg(0x02864);
+ yi->reg_2870 = read_reg(0x02870);
+ yi->reg_2874 = read_reg(0x02874);
+ yi->reg_2898 = read_reg(0x02898);
+ yi->reg_2890 = read_reg(0x02890);
+
+ yi->reg_289c = read_reg(0x0289c);
+ yi->reg_2918 = read_reg(0x02918);
+ yi->reg_291c = read_reg(0x0291c);
+ yi->reg_2920 = read_reg(0x02920);
+ yi->reg_2924 = read_reg(0x02924);
+ yi->reg_2928 = read_reg(0x02928);
+ yi->reg_292c = read_reg(0x0292c);
+ yi->reg_2930 = read_reg(0x02930);
+ yi->reg_2934 = read_reg(0x02934);
+ yi->reg_2938 = read_reg(0x02938);
+ yi->reg_293c = read_reg(0x0293c);
+ yi->reg_2940 = read_reg(0x02940);
+ yi->reg_2944 = read_reg(0x02944);
+ yi->reg_2948 = read_reg(0x02948);
+ yi->reg_294c = read_reg(0x0294c);
+ yi->reg_2950 = read_reg(0x02950);
+ yi->reg_2954 = read_reg(0x02954);
+ yi->reg_2958 = read_reg(0x02958);
+ yi->reg_295c = read_reg(0x0295c);
+ yi->reg_2960 = read_reg(0x02960);
+ yi->reg_2964 = read_reg(0x02964);
+ yi->reg_2968 = read_reg(0x02968);
+ yi->reg_296c = read_reg(0x0296c);
+ yi->reg_2970 = read_reg(0x02970);
+
+ yi->v_filter_1 = -1;
+ yi->v_filter_2 = -1;
+ yi->h_filter = -1;
/* Set some valid size info */
- itv->yuv_info.osd_x_offset = read_reg(0x02a04) & 0x00000FFF;
- itv->yuv_info.osd_y_offset = (read_reg(0x02a04) >> 16) & 0x00000FFF;
+ yi->osd_x_offset = read_reg(0x02a04) & 0x00000FFF;
+ yi->osd_y_offset = (read_reg(0x02a04) >> 16) & 0x00000FFF;
/* Bit 2 of reg 2878 indicates current decoder output format
0 : NTSC 1 : PAL */
if (read_reg(0x2878) & 4)
- itv->yuv_info.decode_height = 576;
+ yi->decode_height = 576;
else
- itv->yuv_info.decode_height = 480;
+ yi->decode_height = 480;
- /* If no visible size set, assume full size */
- if (!itv->yuv_info.osd_vis_w)
- itv->yuv_info.osd_vis_w = 720 - itv->yuv_info.osd_x_offset;
-
- if (!itv->yuv_info.osd_vis_h) {
- itv->yuv_info.osd_vis_h = itv->yuv_info.decode_height - itv->yuv_info.osd_y_offset;
+ if (!itv->osd_info) {
+ yi->osd_vis_w = 720 - yi->osd_x_offset;
+ yi->osd_vis_h = yi->decode_height - yi->osd_y_offset;
} else {
- /* If output video standard has changed, requested height may
- not be legal */
- if (itv->yuv_info.osd_vis_h + itv->yuv_info.osd_y_offset > itv->yuv_info.decode_height) {
- IVTV_DEBUG_WARN("Clipping yuv output - fb size (%d) exceeds video standard limit (%d)\n",
- itv->yuv_info.osd_vis_h + itv->yuv_info.osd_y_offset,
- itv->yuv_info.decode_height);
- itv->yuv_info.osd_vis_h = itv->yuv_info.decode_height - itv->yuv_info.osd_y_offset;
+ /* If no visible size set, assume full size */
+ if (!yi->osd_vis_w)
+ yi->osd_vis_w = 720 - yi->osd_x_offset;
+
+ if (!yi->osd_vis_h)
+ yi->osd_vis_h = yi->decode_height - yi->osd_y_offset;
+ else {
+ /* If output video standard has changed, requested height may
+ not be legal */
+ if (yi->osd_vis_h + yi->osd_y_offset > yi->decode_height) {
+ IVTV_DEBUG_WARN("Clipping yuv output - fb size (%d) exceeds video standard limit (%d)\n",
+ yi->osd_vis_h + yi->osd_y_offset,
+ yi->decode_height);
+ yi->osd_vis_h = yi->decode_height - yi->osd_y_offset;
+ }
}
}
/* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */
- itv->yuv_info.blanking_ptr = kzalloc(720*16,GFP_KERNEL);
- if (itv->yuv_info.blanking_ptr) {
- itv->yuv_info.blanking_dmaptr = pci_map_single(itv->dev, itv->yuv_info.blanking_ptr, 720*16, PCI_DMA_TODEVICE);
- }
+ yi->blanking_ptr = kzalloc(720*16, GFP_KERNEL);
+ if (yi->blanking_ptr)
+ yi->blanking_dmaptr = pci_map_single(itv->dev, yi->blanking_ptr, 720*16, PCI_DMA_TODEVICE);
else {
- itv->yuv_info.blanking_dmaptr = 0;
- IVTV_DEBUG_WARN ("Failed to allocate yuv blanking buffer\n");
+ yi->blanking_dmaptr = 0;
+ IVTV_DEBUG_WARN("Failed to allocate yuv blanking buffer\n");
}
- IVTV_DEBUG_WARN("Enable video output\n");
- write_reg_sync(0x00108080, 0x2898);
-
/* Enable YUV decoder output */
write_reg_sync(0x01, IVTV_REG_VDM);
set_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags);
- atomic_set(&itv->yuv_info.next_dma_frame,0);
+ atomic_set(&yi->next_dma_frame, 0);
}
int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
diff --git a/drivers/media/video/ivtv/ivtv-yuv.h b/drivers/media/video/ivtv/ivtv-yuv.h
index f7215eeca018..3b966f0a204a 100644
--- a/drivers/media/video/ivtv/ivtv-yuv.h
+++ b/drivers/media/video/ivtv/ivtv-yuv.h
@@ -34,6 +34,7 @@
#define IVTV_YUV_UPDATE_HORIZONTAL 0x01
#define IVTV_YUV_UPDATE_VERTICAL 0x02
+#define IVTV_YUV_UPDATE_INVALID 0x04
extern const u32 yuv_offset[4];
diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c
index 9684048fe56c..52ffd154a3d8 100644
--- a/drivers/media/video/ivtv/ivtvfb.c
+++ b/drivers/media/video/ivtv/ivtvfb.c
@@ -55,7 +55,6 @@
static int ivtvfb_card_id = -1;
static int ivtvfb_debug = 0;
static int osd_laced;
-static int osd_compat;
static int osd_depth;
static int osd_upper;
static int osd_left;
@@ -65,7 +64,6 @@ static int osd_xres;
module_param(ivtvfb_card_id, int, 0444);
module_param_named(debug,ivtvfb_debug, int, 0644);
module_param(osd_laced, bool, 0444);
-module_param(osd_compat, bool, 0444);
module_param(osd_depth, int, 0444);
module_param(osd_upper, int, 0444);
module_param(osd_left, int, 0444);
@@ -80,12 +78,6 @@ MODULE_PARM_DESC(debug,
"Debug level (bitmask). Default: errors only\n"
"\t\t\t(debug = 3 gives full debugging)");
-MODULE_PARM_DESC(osd_compat,
- "Compatibility mode - Display size is locked (use for old X drivers)\n"
- "\t\t\t0=off\n"
- "\t\t\t1=on\n"
- "\t\t\tdefault off");
-
/* Why upper, left, xres, yres, depth, laced ? To match terminology used
by fbset.
Why start at 1 for left & upper coordinate ? Because X doesn't allow 0 */
@@ -166,9 +158,6 @@ struct osd_info {
unsigned long fb_end_aligned_physaddr;
#endif
- /* Current osd mode */
- int osd_mode;
-
/* Store the buffer offset */
int set_osd_coords_x;
int set_osd_coords_y;
@@ -470,13 +459,11 @@ static int ivtvfb_set_var(struct ivtv *itv, struct fb_var_screeninfo *var)
IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
}
- /* Change osd mode if needed.
- Although rare, things can go wrong. The extra mode
- change seems to help... */
- if (osd_mode != -1 && osd_mode != oi->osd_mode) {
+ /* Set video mode. Although rare, the display can become scrambled even
+ if we don't change mode. Always 'bounce' to osd_mode via mode 0 */
+ if (osd_mode != -1) {
ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, 0);
ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, osd_mode);
- oi->osd_mode = osd_mode;
}
oi->bits_per_pixel = var->bits_per_pixel;
@@ -579,14 +566,6 @@ static int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv)
osd_height_limit = 480;
}
- /* Check the bits per pixel */
- if (osd_compat) {
- if (var->bits_per_pixel != 32) {
- IVTVFB_DEBUG_WARN("Invalid colour mode: %d\n", var->bits_per_pixel);
- return -EINVAL;
- }
- }
-
if (var->bits_per_pixel == 8 || var->bits_per_pixel == 32) {
var->transp.offset = 24;
var->transp.length = 8;
@@ -638,32 +617,20 @@ static int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv)
}
/* Check the resolution */
- if (osd_compat) {
- if (var->xres != oi->ivtvfb_defined.xres ||
- var->yres != oi->ivtvfb_defined.yres ||
- var->xres_virtual != oi->ivtvfb_defined.xres_virtual ||
- var->yres_virtual != oi->ivtvfb_defined.yres_virtual) {
- IVTVFB_DEBUG_WARN("Invalid resolution: %dx%d (virtual %dx%d)\n",
- var->xres, var->yres, var->xres_virtual, var->yres_virtual);
- return -EINVAL;
- }
+ if (var->xres > IVTV_OSD_MAX_WIDTH || var->yres > osd_height_limit) {
+ IVTVFB_DEBUG_WARN("Invalid resolution: %dx%d\n",
+ var->xres, var->yres);
+ return -EINVAL;
}
- else {
- if (var->xres > IVTV_OSD_MAX_WIDTH || var->yres > osd_height_limit) {
- IVTVFB_DEBUG_WARN("Invalid resolution: %dx%d\n",
- var->xres, var->yres);
- return -EINVAL;
- }
- /* Max horizontal size is 1023 @ 32bpp, 2046 & 16bpp, 4092 @ 8bpp */
- if (var->xres_virtual > 4095 / (var->bits_per_pixel / 8) ||
- var->xres_virtual * var->yres_virtual * (var->bits_per_pixel / 8) > oi->video_buffer_size ||
- var->xres_virtual < var->xres ||
- var->yres_virtual < var->yres) {
- IVTVFB_DEBUG_WARN("Invalid virtual resolution: %dx%d\n",
- var->xres_virtual, var->yres_virtual);
- return -EINVAL;
- }
+ /* Max horizontal size is 1023 @ 32bpp, 2046 & 16bpp, 4092 @ 8bpp */
+ if (var->xres_virtual > 4095 / (var->bits_per_pixel / 8) ||
+ var->xres_virtual * var->yres_virtual * (var->bits_per_pixel / 8) > oi->video_buffer_size ||
+ var->xres_virtual < var->xres ||
+ var->yres_virtual < var->yres) {
+ IVTVFB_DEBUG_WARN("Invalid virtual resolution: %dx%d\n",
+ var->xres_virtual, var->yres_virtual);
+ return -EINVAL;
}
/* Some extra checks if in 8 bit mode */
@@ -877,17 +844,15 @@ static int ivtvfb_init_vidmode(struct ivtv *itv)
/* Color mode */
- if (osd_compat) osd_depth = 32;
- if (osd_depth != 8 && osd_depth != 16 && osd_depth != 32) osd_depth = 8;
+ if (osd_depth != 8 && osd_depth != 16 && osd_depth != 32)
+ osd_depth = 8;
oi->bits_per_pixel = osd_depth;
oi->bytes_per_pixel = oi->bits_per_pixel / 8;
- /* Invalidate current osd mode to force a mode switch later */
- oi->osd_mode = -1;
-
/* Horizontal size & position */
- if (osd_xres > 720) osd_xres = 720;
+ if (osd_xres > 720)
+ osd_xres = 720;
/* Must be a multiple of 4 for 8bpp & 2 for 16bpp */
if (osd_depth == 8)
@@ -895,10 +860,7 @@ static int ivtvfb_init_vidmode(struct ivtv *itv)
else if (osd_depth == 16)
osd_xres &= ~1;
- if (osd_xres)
- start_window.width = osd_xres;
- else
- start_window.width = osd_compat ? 720: 640;
+ start_window.width = osd_xres ? osd_xres : 640;
/* Check horizontal start (osd_left). */
if (osd_left && osd_left + start_window.width > 721) {
@@ -921,10 +883,7 @@ static int ivtvfb_init_vidmode(struct ivtv *itv)
if (osd_yres > max_height)
osd_yres = max_height;
- if (osd_yres)
- start_window.height = osd_yres;
- else
- start_window.height = osd_compat ? max_height : (itv->is_50hz ? 480 : 400);
+ start_window.height = osd_yres ? osd_yres : itv->is_50hz ? 480 : 400;
/* Check vertical start (osd_upper). */
if (osd_upper + start_window.height > max_height + 1) {
@@ -1127,10 +1086,6 @@ static int ivtvfb_init_card(struct ivtv *itv)
/* Enable the osd */
ivtvfb_blank(FB_BLANK_UNBLANK, &itv->osd_info->ivtvfb_info);
- /* Note if we're running in compatibility mode */
- if (osd_compat)
- IVTVFB_INFO("Running in compatibility mode. Display resize & mode change disabled\n");
-
/* Allocate DMA */
ivtv_udma_alloc(itv);
return 0;
@@ -1177,9 +1132,12 @@ static void ivtvfb_cleanup(void)
for (i = 0; i < ivtv_cards_active; i++) {
itv = ivtv_cards[i];
if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) && itv->osd_info) {
+ if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) {
+ IVTVFB_WARN("Framebuffer %d is in use, cannot unload\n", i);
+ return;
+ }
IVTVFB_DEBUG_INFO("Unregister framebuffer %d\n", i);
ivtvfb_blank(FB_BLANK_POWERDOWN, &itv->osd_info->ivtvfb_info);
- unregister_framebuffer(&itv->osd_info->ivtvfb_info);
ivtvfb_release_buffers(itv);
itv->osd_video_pbase = 0;
}
diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c
index 7533fc203319..c31163290432 100644
--- a/drivers/media/video/meye.c
+++ b/drivers/media/video/meye.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2001-2004 Stelian Pop <stelian@popies.net>
*
- * Copyright (C) 2001-2002 Alcôve <www.alcove.com>
+ * Copyright (C) 2001-2002 Alcôve <www.alcove.com>
*
* Copyright (C) 2000 Andrew Tridgell <tridge@valinux.com>
*
@@ -1762,7 +1762,6 @@ static struct video_device meye_template = {
.owner = THIS_MODULE,
.name = "meye",
.type = VID_TYPE_CAPTURE,
- .hardware = VID_HARDWARE_MEYE,
.fops = &meye_fops,
.release = video_device_release,
.minor = -1,
diff --git a/drivers/media/video/meye.h b/drivers/media/video/meye.h
index 323d0074120d..d535748df445 100644
--- a/drivers/media/video/meye.h
+++ b/drivers/media/video/meye.h
@@ -3,7 +3,7 @@
*
* Copyright (C) 2001-2004 Stelian Pop <stelian@popies.net>
*
- * Copyright (C) 2001-2002 Alcôve <www.alcove.com>
+ * Copyright (C) 2001-2002 Alcôve <www.alcove.com>
*
* Copyright (C) 2000 Andrew Tridgell <tridge@valinux.com>
*
diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c
index b8d4ac0d938e..d55d5800efb4 100644
--- a/drivers/media/video/ov511.c
+++ b/drivers/media/video/ov511.c
@@ -4668,7 +4668,6 @@ static struct video_device vdev_template = {
.owner = THIS_MODULE,
.name = "OV511 USB Camera",
.type = VID_TYPE_CAPTURE,
- .hardware = VID_HARDWARE_OV511,
.fops = &ov511_fops,
.release = video_device_release,
.minor = -1,
diff --git a/drivers/media/video/planb.c b/drivers/media/video/planb.c
index 0ef73d9d5848..36047d4e70f6 100644
--- a/drivers/media/video/planb.c
+++ b/drivers/media/video/planb.c
@@ -91,7 +91,6 @@ static void planb_close(struct video_device *);
static int planb_ioctl(struct video_device *, unsigned int, void *);
static int planb_init_done(struct video_device *);
static int planb_mmap(struct video_device *, const char *, unsigned long);
-static void planb_irq(int, void *);
static void release_planb(void);
int init_planbs(struct video_init *);
@@ -1315,7 +1314,7 @@ cmd_tab_data_end:
return c1;
}
-static void planb_irq(int irq, void *dev_id)
+static irqreturn_t planb_irq(int irq, void *dev_id)
{
unsigned int stat, astat;
struct planb *pb = (struct planb *)dev_id;
@@ -1358,13 +1357,14 @@ static void planb_irq(int irq, void *dev_id)
pb->frame_stat[fr] = GBUFFER_DONE;
pb->grabbing--;
wake_up_interruptible(&pb->capq);
- return;
+ return IRQ_HANDLED;
}
/* incorrect interrupts? */
pb->intr_mask = PLANB_CLR_IRQ;
out_le32(&pb->planb_base->intr_stat, PLANB_CLR_IRQ);
printk(KERN_ERR "PlanB: IRQ lockup, cleared intrrupts"
" unconditionally\n");
+ return IRQ_HANDLED;
}
/*******************************
@@ -2013,7 +2013,6 @@ static struct video_device planb_template=
.owner = THIS_MODULE,
.name = PLANB_DEVICE_NAME,
.type = VID_TYPE_OVERLAY,
- .hardware = VID_HARDWARE_PLANB,
.open = planb_open,
.close = planb_close,
.read = planb_read,
@@ -2091,7 +2090,7 @@ static int init_planb(struct planb *pb)
/* clear interrupt mask */
pb->intr_mask = PLANB_CLR_IRQ;
- result = request_irq(pb->irq, planb_irq, 0, "PlanB", (void *)pb);
+ result = request_irq(pb->irq, planb_irq, 0, "PlanB", pb);
if (result < 0) {
if (result==-EINVAL)
printk(KERN_ERR "PlanB: Bad irq number (%d) "
diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c
index b5a67f0dd19f..6820c2aabd30 100644
--- a/drivers/media/video/pms.c
+++ b/drivers/media/video/pms.c
@@ -895,7 +895,6 @@ static struct video_device pms_template=
.owner = THIS_MODULE,
.name = "Mediavision PMS",
.type = VID_TYPE_CAPTURE,
- .hardware = VID_HARDWARE_PMS,
.fops = &pms_fops,
};
diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
index f569b00201dd..46f156fb108c 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
@@ -410,7 +410,7 @@ static int parse_mtoken(const char *ptr,unsigned int len,
int msk;
*valptr = 0;
for (idx = 0, msk = 1; valid_bits; idx++, msk <<= 1) {
- if (!msk & valid_bits) continue;
+ if (!(msk & valid_bits)) continue;
valid_bits &= ~msk;
if (!names[idx]) continue;
slen = strlen(names[idx]);
diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/drivers/media/video/pvrusb2/pvrusb2-encoder.c
index 20b614436d2c..205087a3e136 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-encoder.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-encoder.c
@@ -209,6 +209,11 @@ static int pvr2_encoder_cmd(void *ctxt,
LOCK_TAKE(hdw->ctl_lock); do {
+ if (!hdw->flag_encoder_ok) {
+ ret = -EIO;
+ break;
+ }
+
retry_flag = 0;
try_count++;
ret = 0;
@@ -273,6 +278,7 @@ static int pvr2_encoder_cmd(void *ctxt,
ret = -EBUSY;
}
if (ret) {
+ hdw->flag_encoder_ok = 0;
pvr2_trace(
PVR2_TRACE_ERROR_LEGS,
"Giving up on command."
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
index 985d9ae7f5ee..f873994b088c 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
@@ -225,11 +225,12 @@ struct pvr2_hdw {
unsigned int cmd_debug_write_len; //
unsigned int cmd_debug_read_len; //
- int flag_ok; // device in known good state
- int flag_disconnected; // flag_ok == 0 due to disconnect
- int flag_init_ok; // true if structure is fully initialized
- int flag_streaming_enabled; // true if streaming should be on
- int fw1_state; // current situation with fw1
+ int flag_ok; /* device in known good state */
+ int flag_disconnected; /* flag_ok == 0 due to disconnect */
+ int flag_init_ok; /* true if structure is fully initialized */
+ int flag_streaming_enabled; /* true if streaming should be on */
+ int fw1_state; /* current situation with fw1 */
+ int flag_encoder_ok; /* True if encoder is healthy */
int flag_decoder_is_tuned;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index 27b12b4b5c88..402c59488253 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -1248,6 +1248,8 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
time we configure the encoder, then we'll fully configure it. */
hdw->enc_cur_valid = 0;
+ hdw->flag_encoder_ok = 0;
+
/* First prepare firmware loading */
ret |= pvr2_write_register(hdw, 0x0048, 0xffffffff); /*interrupt mask*/
ret |= pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000088); /*gpio dir*/
@@ -1346,6 +1348,7 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
"firmware2 upload post-proc failure");
} else {
+ hdw->flag_encoder_ok = !0;
hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_FIRMWARE);
}
return ret;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-main.c b/drivers/media/video/pvrusb2/pvrusb2-main.c
index ca9e2789c8ca..11b3b2e84b90 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-main.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-main.c
@@ -136,14 +136,13 @@ static int __init pvr_init(void)
static void __exit pvr_exit(void)
{
-
pvr2_trace(PVR2_TRACE_INIT,"pvr_exit");
+ usb_deregister(&pvr_driver);
+
#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
pvr2_sysfs_class_destroy(class_ptr);
#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
-
- usb_deregister(&pvr_driver);
}
module_init(pvr_init);
diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
index 2ee3c3049e8f..3c57a7d8200b 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
@@ -905,13 +905,6 @@ struct pvr2_sysfs *pvr2_sysfs_create(struct pvr2_context *mp,
}
-static int pvr2_sysfs_hotplug(struct device *d,
- struct kobj_uevent_env *env)
-{
- /* Even though we don't do anything here, we still need this function
- because sysfs will still try to call it. */
- return 0;
-}
struct pvr2_sysfs_class *pvr2_sysfs_class_create(void)
{
@@ -922,7 +915,6 @@ struct pvr2_sysfs_class *pvr2_sysfs_class_create(void)
clp->class.name = "pvrusb2";
clp->class.class_release = pvr2_sysfs_class_release;
clp->class.dev_release = pvr2_sysfs_release;
- clp->class.dev_uevent = pvr2_sysfs_hotplug;
if (class_register(&clp->class)) {
pvr2_sysfs_trace(
"Registration failed for pvr2_sysfs_class id=%p",clp);
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
index 4563b3df8a0d..7a596ea7cfe6 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
@@ -1121,15 +1121,12 @@ static const struct file_operations vdev_fops = {
};
-#define VID_HARDWARE_PVRUSB2 38 /* FIXME : need a good value */
-
static struct video_device vdev_template = {
.owner = THIS_MODULE,
.type = VID_TYPE_CAPTURE | VID_TYPE_TUNER,
.type2 = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE
| V4L2_CAP_TUNER | V4L2_CAP_AUDIO
| V4L2_CAP_READWRITE),
- .hardware = VID_HARDWARE_PVRUSB2,
.fops = &vdev_fops,
};
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
index 950da2542148..7300ace8f44e 100644
--- a/drivers/media/video/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -166,7 +166,6 @@ static struct video_device pwc_template = {
.owner = THIS_MODULE,
.name = "Philips Webcam", /* Filled in later */
.type = VID_TYPE_CAPTURE,
- .hardware = VID_HARDWARE_PWC,
.release = video_device_release,
.fops = &pwc_fops,
.minor = -1,
diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c
index e20aa3612a7c..ad0232935df6 100644
--- a/drivers/media/video/saa5246a.c
+++ b/drivers/media/video/saa5246a.c
@@ -196,10 +196,10 @@ static int i2c_senddata(struct saa5246a_device *t, ...)
return i2c_sendbuf(t, buf[0], ct-1, buf+1);
}
-/* Get count number of bytes from I²C-device at address adr, store them in buf.
+/* Get count number of bytes from I²C-device at address adr, store them in buf.
* Start & stop handshaking is done by this routine, ack will be sent after the
* last byte to inhibit further sending of data. If uaccess is 'true', data is
- * written to user-space with put_user. Returns -1 if I²C-device didn't send
+ * written to user-space with put_user. Returns -1 if I²C-device didn't send
* acknowledge, 0 otherwise
*/
static int i2c_getdata(struct saa5246a_device *t, int count, u8 *buf)
diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c
index 17f1e2e9a66b..94bb59a32b17 100644
--- a/drivers/media/video/saa5249.c
+++ b/drivers/media/video/saa5249.c
@@ -291,10 +291,10 @@ static int i2c_senddata(struct saa5249_device *t, ...)
return i2c_sendbuf(t, buf[0], ct-1, buf+1);
}
-/* Get count number of bytes from I²C-device at address adr, store them in buf. Start & stop
+/* Get count number of bytes from I²C-device at address adr, store them in buf. Start & stop
* handshaking is done by this routine, ack will be sent after the last byte to inhibit further
* sending of data. If uaccess is 'true', data is written to user-space with put_user.
- * Returns -1 if I²C-device didn't send acknowledge, 0 otherwise
+ * Returns -1 if I²C-device didn't send acknowledge, 0 otherwise
*/
static int i2c_getdata(struct saa5249_device *t, int count, u8 *buf)
diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig
index d6d8d660196d..3aa8cb2b860a 100644
--- a/drivers/media/video/saa7134/Kconfig
+++ b/drivers/media/video/saa7134/Kconfig
@@ -1,6 +1,6 @@
config VIDEO_SAA7134
tristate "Philips SAA7134 support"
- depends on VIDEO_DEV && PCI && I2C
+ depends on VIDEO_DEV && PCI && I2C && INPUT
select VIDEOBUF_DMA_SG
select VIDEO_IR
select VIDEO_TUNER
diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c
index 57f1f5d409e0..002e70a33a4f 100644
--- a/drivers/media/video/saa7134/saa6752hs.c
+++ b/drivers/media/video/saa7134/saa6752hs.c
@@ -71,7 +71,6 @@ static const struct v4l2_format v4l2_format_table[] =
struct saa6752hs_state {
struct i2c_client client;
- struct v4l2_mpeg_compression old_params;
struct saa6752hs_mpeg_params params;
enum saa6752hs_videoformat video_format;
v4l2_std_id standard;
@@ -161,35 +160,6 @@ static struct saa6752hs_mpeg_params param_defaults =
.au_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_256K,
};
-static struct v4l2_mpeg_compression old_param_defaults =
-{
- .st_type = V4L2_MPEG_TS_2,
- .st_bitrate = {
- .mode = V4L2_BITRATE_CBR,
- .target = 7000,
- },
-
- .ts_pid_pmt = 16,
- .ts_pid_video = 260,
- .ts_pid_audio = 256,
- .ts_pid_pcr = 259,
-
- .vi_type = V4L2_MPEG_VI_2,
- .vi_aspect_ratio = V4L2_MPEG_ASPECT_4_3,
- .vi_bitrate = {
- .mode = V4L2_BITRATE_VBR,
- .target = 4000,
- .max = 6000,
- },
-
- .au_type = V4L2_MPEG_AU_2_II,
- .au_bitrate = {
- .mode = V4L2_BITRATE_CBR,
- .target = 256,
- },
-
-};
-
/* ---------------------------------------------------------------------- */
static int saa6752hs_chip_command(struct i2c_client* client,
@@ -362,74 +332,6 @@ static void saa6752hs_set_subsampling(struct i2c_client* client,
}
-static void saa6752hs_old_set_params(struct i2c_client* client,
- struct v4l2_mpeg_compression* params)
-{
- struct saa6752hs_state *h = i2c_get_clientdata(client);
-
- /* check PIDs */
- if (params->ts_pid_pmt <= MPEG_PID_MAX) {
- h->old_params.ts_pid_pmt = params->ts_pid_pmt;
- h->params.ts_pid_pmt = params->ts_pid_pmt;
- }
- if (params->ts_pid_pcr <= MPEG_PID_MAX) {
- h->old_params.ts_pid_pcr = params->ts_pid_pcr;
- h->params.ts_pid_pcr = params->ts_pid_pcr;
- }
- if (params->ts_pid_video <= MPEG_PID_MAX) {
- h->old_params.ts_pid_video = params->ts_pid_video;
- h->params.ts_pid_video = params->ts_pid_video;
- }
- if (params->ts_pid_audio <= MPEG_PID_MAX) {
- h->old_params.ts_pid_audio = params->ts_pid_audio;
- h->params.ts_pid_audio = params->ts_pid_audio;
- }
-
- /* check bitrate parameters */
- if ((params->vi_bitrate.mode == V4L2_BITRATE_CBR) ||
- (params->vi_bitrate.mode == V4L2_BITRATE_VBR)) {
- h->old_params.vi_bitrate.mode = params->vi_bitrate.mode;
- h->params.vi_bitrate_mode = (params->vi_bitrate.mode == V4L2_BITRATE_VBR) ?
- V4L2_MPEG_VIDEO_BITRATE_MODE_VBR : V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
- }
- if (params->vi_bitrate.mode != V4L2_BITRATE_NONE)
- h->old_params.st_bitrate.target = params->st_bitrate.target;
- if (params->vi_bitrate.mode != V4L2_BITRATE_NONE)
- h->old_params.vi_bitrate.target = params->vi_bitrate.target;
- if (params->vi_bitrate.mode == V4L2_BITRATE_VBR)
- h->old_params.vi_bitrate.max = params->vi_bitrate.max;
- if (params->au_bitrate.mode != V4L2_BITRATE_NONE)
- h->old_params.au_bitrate.target = params->au_bitrate.target;
-
- /* aspect ratio */
- if (params->vi_aspect_ratio == V4L2_MPEG_ASPECT_4_3 ||
- params->vi_aspect_ratio == V4L2_MPEG_ASPECT_16_9) {
- h->old_params.vi_aspect_ratio = params->vi_aspect_ratio;
- if (params->vi_aspect_ratio == V4L2_MPEG_ASPECT_4_3)
- h->params.vi_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3;
- else
- h->params.vi_aspect = V4L2_MPEG_VIDEO_ASPECT_16x9;
- }
-
- /* range checks */
- if (h->old_params.st_bitrate.target > MPEG_TOTAL_TARGET_BITRATE_MAX)
- h->old_params.st_bitrate.target = MPEG_TOTAL_TARGET_BITRATE_MAX;
- if (h->old_params.vi_bitrate.target > MPEG_VIDEO_TARGET_BITRATE_MAX)
- h->old_params.vi_bitrate.target = MPEG_VIDEO_TARGET_BITRATE_MAX;
- if (h->old_params.vi_bitrate.max > MPEG_VIDEO_MAX_BITRATE_MAX)
- h->old_params.vi_bitrate.max = MPEG_VIDEO_MAX_BITRATE_MAX;
- h->params.vi_bitrate = params->vi_bitrate.target;
- h->params.vi_bitrate_peak = params->vi_bitrate.max;
- if (h->old_params.au_bitrate.target <= 256) {
- h->old_params.au_bitrate.target = 256;
- h->params.au_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_256K;
- }
- else {
- h->old_params.au_bitrate.target = 384;
- h->params.au_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_384K;
- }
-}
-
static int handle_ctrl(struct saa6752hs_mpeg_params *params,
struct v4l2_ext_control *ctrl, unsigned int cmd)
{
@@ -697,7 +599,6 @@ static int saa6752hs_attach(struct i2c_adapter *adap, int addr, int kind)
return -ENOMEM;
h->client = client_template;
h->params = param_defaults;
- h->old_params = old_param_defaults;
h->client.adapter = adap;
h->client.addr = addr;
@@ -734,23 +635,11 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
struct saa6752hs_state *h = i2c_get_clientdata(client);
struct v4l2_ext_controls *ctrls = arg;
- struct v4l2_mpeg_compression *old_params = arg;
struct saa6752hs_mpeg_params params;
int err = 0;
int i;
switch (cmd) {
- case VIDIOC_S_MPEGCOMP:
- if (NULL == old_params) {
- /* apply settings and start encoder */
- saa6752hs_init(client);
- break;
- }
- saa6752hs_old_set_params(client, old_params);
- /* fall through */
- case VIDIOC_G_MPEGCOMP:
- *old_params = h->old_params;
- break;
case VIDIOC_S_EXT_CTRLS:
if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
return -EINVAL;
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c
index c6f7279669c1..b9c5cf7dc849 100644
--- a/drivers/media/video/saa7134/saa7134-alsa.c
+++ b/drivers/media/video/saa7134/saa7134-alsa.c
@@ -543,8 +543,10 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream,
V4L functions, and force ALSA to use that as the DMA area */
substream->runtime->dma_area = dev->dmasound.dma.vmalloc;
+ substream->runtime->dma_bytes = dev->dmasound.bufsize;
+ substream->runtime->dma_addr = 0;
- return 1;
+ return 0;
}
@@ -652,6 +654,17 @@ static int snd_card_saa7134_capture_open(struct snd_pcm_substream * substream)
}
/*
+ * page callback (needed for mmap)
+ */
+
+static struct page *snd_card_saa7134_page(struct snd_pcm_substream *substream,
+ unsigned long offset)
+{
+ void *pageptr = substream->runtime->dma_area + offset;
+ return vmalloc_to_page(pageptr);
+}
+
+/*
* ALSA capture callbacks definition
*/
@@ -664,6 +677,7 @@ static struct snd_pcm_ops snd_card_saa7134_capture_ops = {
.prepare = snd_card_saa7134_capture_prepare,
.trigger = snd_card_saa7134_capture_trigger,
.pointer = snd_card_saa7134_capture_pointer,
+ .page = snd_card_saa7134_page,
};
/*
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index a4c192fb4e41..4f3dad9ae6d6 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -2996,11 +2996,11 @@ struct saa7134_board saa7134_boards[] = {
},{
.name = name_comp1,
.vmux = 0,
- .amux = LINE2,
+ .amux = LINE1,
},{
.name = name_svideo,
.vmux = 8,
- .amux = LINE2,
+ .amux = LINE1,
}},
},
[SAA7134_BOARD_FLYDVBS_LR300] = {
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index 1a4a24471f20..a499eea379e6 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -429,7 +429,7 @@ int saa7134_set_dmabits(struct saa7134_dev *dev)
assert_spin_locked(&dev->slock);
- if (dev->inresume)
+ if (dev->insuspend)
return 0;
/* video capture -- dma 0 + video task A */
@@ -563,6 +563,9 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id)
unsigned long report,status;
int loop, handled = 0;
+ if (dev->insuspend)
+ goto out;
+
for (loop = 0; loop < 10; loop++) {
report = saa_readl(SAA7134_IRQ_REPORT);
status = saa_readl(SAA7134_IRQ_STATUS);
@@ -1163,6 +1166,7 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
kfree(dev);
}
+#ifdef CONFIG_PM
static int saa7134_suspend(struct pci_dev *pci_dev , pm_message_t state)
{
@@ -1176,6 +1180,19 @@ static int saa7134_suspend(struct pci_dev *pci_dev , pm_message_t state)
saa_writel(SAA7134_IRQ2, 0);
saa_writel(SAA7134_MAIN_CTRL, 0);
+ synchronize_irq(pci_dev->irq);
+ dev->insuspend = 1;
+
+ /* Disable timeout timers - if we have active buffers, we will
+ fill them on resume*/
+
+ del_timer(&dev->video_q.timeout);
+ del_timer(&dev->vbi_q.timeout);
+ del_timer(&dev->ts_q.timeout);
+
+ if (dev->remote)
+ saa7134_ir_stop(dev);
+
pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state));
pci_save_state(pci_dev);
@@ -1194,24 +1211,27 @@ static int saa7134_resume(struct pci_dev *pci_dev)
/* Do things that are done in saa7134_initdev ,
except of initializing memory structures.*/
- dev->inresume = 1;
saa7134_board_init1(dev);
+ /* saa7134_hwinit1 */
if (saa7134_boards[dev->board].video_out)
saa7134_videoport_init(dev);
-
if (card_has_mpeg(dev))
saa7134_ts_init_hw(dev);
-
+ if (dev->remote)
+ saa7134_ir_start(dev, dev->remote);
saa7134_hw_enable1(dev);
- saa7134_set_decoder(dev);
- saa7134_i2c_call_clients(dev, VIDIOC_S_STD, &dev->tvnorm->id);
+
+
saa7134_board_init2(dev);
- saa7134_hw_enable2(dev);
+ /*saa7134_hwinit2*/
+ saa7134_set_tvnorm_hw(dev);
saa7134_tvaudio_setmute(dev);
saa7134_tvaudio_setvolume(dev, dev->ctl_volume);
+ saa7134_tvaudio_do_scan(dev);
saa7134_enable_i2s(dev);
+ saa7134_hw_enable2(dev);
/*resume unfinished buffer(s)*/
spin_lock_irqsave(&dev->slock, flags);
@@ -1219,13 +1239,19 @@ static int saa7134_resume(struct pci_dev *pci_dev)
saa7134_buffer_requeue(dev, &dev->vbi_q);
saa7134_buffer_requeue(dev, &dev->ts_q);
+ /* FIXME: Disable DMA audio sound - temporary till proper support
+ is implemented*/
+
+ dev->dmasound.dma_running = 0;
+
/* start DMA now*/
- dev->inresume = 0;
+ dev->insuspend = 0;
saa7134_set_dmabits(dev);
spin_unlock_irqrestore(&dev->slock, flags);
return 0;
}
+#endif
/* ----------------------------------------------------------- */
@@ -1262,8 +1288,10 @@ static struct pci_driver saa7134_pci_driver = {
.id_table = saa7134_pci_tbl,
.probe = saa7134_initdev,
.remove = __devexit_p(saa7134_finidev),
+#ifdef CONFIG_PM
.suspend = saa7134_suspend,
.resume = saa7134_resume
+#endif
};
static int saa7134_init(void)
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c
index 34ca874dd7fe..75d0c5bf46d2 100644
--- a/drivers/media/video/saa7134/saa7134-empress.c
+++ b/drivers/media/video/saa7134/saa7134-empress.c
@@ -284,17 +284,6 @@ static int ts_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_S_CTRL:
return saa7134_common_ioctl(dev, cmd, arg);
- case VIDIOC_S_MPEGCOMP:
- printk(KERN_WARNING "VIDIOC_S_MPEGCOMP is obsolete. "
- "Replace with VIDIOC_S_EXT_CTRLS!");
- saa7134_i2c_call_clients(dev, VIDIOC_S_MPEGCOMP, arg);
- ts_init_encoder(dev);
- return 0;
- case VIDIOC_G_MPEGCOMP:
- printk(KERN_WARNING "VIDIOC_G_MPEGCOMP is obsolete. "
- "Replace with VIDIOC_G_EXT_CTRLS!");
- saa7134_i2c_call_clients(dev, VIDIOC_G_MPEGCOMP, arg);
- return 0;
case VIDIOC_S_EXT_CTRLS:
/* count == 0 is abused in saa6752hs.c, so that special
case is handled here explicitly. */
@@ -342,7 +331,6 @@ static struct video_device saa7134_empress_template =
.name = "saa7134-empress",
.type = 0 /* FIXME */,
.type2 = 0 /* FIXME */,
- .hardware = 0,
.fops = &ts_fops,
.minor = -1,
};
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
index 80d2644f765a..3abaa1b8ac9d 100644
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -44,6 +44,14 @@ module_param(ir_rc5_remote_gap, int, 0644);
static int ir_rc5_key_timeout = 115;
module_param(ir_rc5_key_timeout, int, 0644);
+static int repeat_delay = 500;
+module_param(repeat_delay, int, 0644);
+MODULE_PARM_DESC(repeat_delay, "delay before key repeat started");
+static int repeat_period = 33;
+module_param(repeat_period, int, 0644);
+MODULE_PARM_DESC(repeat_period, "repeat period between"
+ "keypresses when key is down");
+
#define dprintk(fmt, arg...) if (ir_debug) \
printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg)
#define i2cdprintk(fmt, arg...) if (ir_debug) \
@@ -59,6 +67,13 @@ static int build_key(struct saa7134_dev *dev)
struct card_ir *ir = dev->remote;
u32 gpio, data;
+ /* here comes the additional handshake steps for some cards */
+ switch (dev->board) {
+ case SAA7134_BOARD_GOTVIEW_7135:
+ saa_setb(SAA7134_GPIO_GPSTATUS1, 0x80);
+ saa_clearb(SAA7134_GPIO_GPSTATUS1, 0x80);
+ break;
+ }
/* rising SAA7134_GPIO_GPRESCAN reads the status */
saa_clearb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN);
saa_setb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN);
@@ -159,7 +174,7 @@ static void saa7134_input_timer(unsigned long data)
mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling));
}
-static void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir)
+void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir)
{
if (ir->polling) {
setup_timer(&ir->timer, saa7134_input_timer,
@@ -182,7 +197,7 @@ static void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir)
}
}
-static void saa7134_ir_stop(struct saa7134_dev *dev)
+void saa7134_ir_stop(struct saa7134_dev *dev)
{
if (dev->remote->polling)
del_timer_sync(&dev->remote->timer);
@@ -285,10 +300,10 @@ int saa7134_input_init1(struct saa7134_dev *dev)
break;
case SAA7134_BOARD_GOTVIEW_7135:
ir_codes = ir_codes_gotview7135;
- mask_keycode = 0x0003EC;
- mask_keyup = 0x008000;
+ mask_keycode = 0x0003CC;
mask_keydown = 0x000010;
- polling = 50; // ms
+ polling = 5; /* ms */
+ saa_setb(SAA7134_GPIO_GPMODE1, 0x80);
break;
case SAA7134_BOARD_VIDEOMATE_TV_PVR:
case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS:
@@ -386,6 +401,10 @@ int saa7134_input_init1(struct saa7134_dev *dev)
if (err)
goto err_out_stop;
+ /* the remote isn't as bouncy as a keyboard */
+ ir->dev->rep[REP_DELAY] = repeat_delay;
+ ir->dev->rep[REP_PERIOD] = repeat_period;
+
return 0;
err_out_stop:
diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c
index 1b9e39a5ea47..f8e304c76232 100644
--- a/drivers/media/video/saa7134/saa7134-tvaudio.c
+++ b/drivers/media/video/saa7134/saa7134-tvaudio.c
@@ -27,6 +27,7 @@
#include <linux/kthread.h>
#include <linux/slab.h>
#include <linux/delay.h>
+#include <linux/freezer.h>
#include <asm/div64.h>
#include "saa7134-reg.h"
@@ -231,7 +232,7 @@ static void mute_input_7134(struct saa7134_dev *dev)
}
if (dev->hw_mute == mute &&
- dev->hw_input == in && !dev->inresume) {
+ dev->hw_input == in && !dev->insuspend) {
dprintk("mute/input: nothing to do [mute=%d,input=%s]\n",
mute,in->name);
return;
@@ -502,13 +503,17 @@ static int tvaudio_thread(void *data)
unsigned int i, audio, nscan;
int max1,max2,carrier,rx,mode,lastmode,default_carrier;
- allow_signal(SIGTERM);
+
+ set_freezable();
+
for (;;) {
tvaudio_sleep(dev,-1);
- if (kthread_should_stop() || signal_pending(current))
+ if (kthread_should_stop())
goto done;
restart:
+ try_to_freeze();
+
dev->thread.scan1 = dev->thread.scan2;
dprintk("tvaudio thread scan start [%d]\n",dev->thread.scan1);
dev->tvaudio = NULL;
@@ -612,9 +617,12 @@ static int tvaudio_thread(void *data)
lastmode = 42;
for (;;) {
+
+ try_to_freeze();
+
if (tvaudio_sleep(dev,5000))
goto restart;
- if (kthread_should_stop() || signal_pending(current))
+ if (kthread_should_stop())
break;
if (UNSET == dev->thread.mode) {
rx = tvaudio_getstereo(dev,&tvaudio[i]);
@@ -630,6 +638,7 @@ static int tvaudio_thread(void *data)
}
done:
+ dev->thread.stopped = 1;
return 0;
}
@@ -777,7 +786,8 @@ static int tvaudio_thread_ddep(void *data)
struct saa7134_dev *dev = data;
u32 value, norms, clock;
- allow_signal(SIGTERM);
+
+ set_freezable();
clock = saa7134_boards[dev->board].audio_clock;
if (UNSET != audio_clock_override)
@@ -790,10 +800,13 @@ static int tvaudio_thread_ddep(void *data)
for (;;) {
tvaudio_sleep(dev,-1);
- if (kthread_should_stop() || signal_pending(current))
+ if (kthread_should_stop())
goto done;
restart:
+
+ try_to_freeze();
+
dev->thread.scan1 = dev->thread.scan2;
dprintk("tvaudio thread scan start [%d]\n",dev->thread.scan1);
@@ -870,6 +883,7 @@ static int tvaudio_thread_ddep(void *data)
}
done:
+ dev->thread.stopped = 1;
return 0;
}
@@ -997,7 +1011,7 @@ int saa7134_tvaudio_init2(struct saa7134_dev *dev)
int saa7134_tvaudio_fini(struct saa7134_dev *dev)
{
/* shutdown tvaudio thread */
- if (dev->thread.thread)
+ if (dev->thread.thread && !dev->thread.stopped)
kthread_stop(dev->thread.thread);
saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x07, 0x00); /* LINE1 */
@@ -1013,7 +1027,9 @@ int saa7134_tvaudio_do_scan(struct saa7134_dev *dev)
} else if (dev->thread.thread) {
dev->thread.mode = UNSET;
dev->thread.scan2++;
- wake_up_process(dev->thread.thread);
+
+ if (!dev->insuspend && !dev->thread.stopped)
+ wake_up_process(dev->thread.thread);
} else {
dev->automute = 0;
saa7134_tvaudio_setmute(dev);
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
index 471b92793c12..3b9ffb4b648a 100644
--- a/drivers/media/video/saa7134/saa7134-video.c
+++ b/drivers/media/video/saa7134/saa7134-video.c
@@ -560,15 +560,8 @@ void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm)
dev->crop_current = dev->crop_defrect;
- saa7134_set_decoder(dev);
+ saa7134_set_tvnorm_hw(dev);
- if (card_in(dev, dev->ctl_input).tv) {
- if ((card(dev).tuner_type == TUNER_PHILIPS_TDA8290)
- && ((card(dev).tuner_config == 1)
- || (card(dev).tuner_config == 2)))
- saa7134_set_gpio(dev, 22, 5);
- saa7134_i2c_call_clients(dev, VIDIOC_S_STD, &norm->id);
- }
}
static void video_mux(struct saa7134_dev *dev, int input)
@@ -579,7 +572,8 @@ static void video_mux(struct saa7134_dev *dev, int input)
saa7134_tvaudio_setinput(dev, &card_in(dev, input));
}
-void saa7134_set_decoder(struct saa7134_dev *dev)
+
+static void saa7134_set_decoder(struct saa7134_dev *dev)
{
int luma_control, sync_control, mux;
@@ -630,6 +624,19 @@ void saa7134_set_decoder(struct saa7134_dev *dev)
saa_writeb(SAA7134_RAW_DATA_OFFSET, 0x80);
}
+void saa7134_set_tvnorm_hw(struct saa7134_dev *dev)
+{
+ saa7134_set_decoder(dev);
+
+ if (card_in(dev, dev->ctl_input).tv) {
+ if ((card(dev).tuner_type == TUNER_PHILIPS_TDA8290)
+ && ((card(dev).tuner_config == 1)
+ || (card(dev).tuner_config == 2)))
+ saa7134_set_gpio(dev, 22, 5);
+ saa7134_i2c_call_clients(dev, VIDIOC_S_STD, &dev->tvnorm->id);
+ }
+}
+
static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale)
{
static const struct {
@@ -2352,7 +2359,6 @@ struct video_device saa7134_video_template =
.name = "saa7134-video",
.type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|
VID_TYPE_CLIPPING|VID_TYPE_SCALES,
- .hardware = 0,
.fops = &video_fops,
.minor = -1,
};
@@ -2361,7 +2367,6 @@ struct video_device saa7134_vbi_template =
{
.name = "saa7134-vbi",
.type = VID_TYPE_TUNER|VID_TYPE_TELETEXT,
- .hardware = 0,
.fops = &video_fops,
.minor = -1,
};
@@ -2370,7 +2375,6 @@ struct video_device saa7134_radio_template =
{
.name = "saa7134-radio",
.type = VID_TYPE_TUNER,
- .hardware = 0,
.fops = &radio_fops,
.minor = -1,
};
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index 28ec6804bd5d..66a390c321a7 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -333,6 +333,7 @@ struct saa7134_thread {
unsigned int scan1;
unsigned int scan2;
unsigned int mode;
+ unsigned int stopped;
};
/* buffer for one video/vbi/ts frame */
@@ -524,7 +525,7 @@ struct saa7134_dev {
unsigned int hw_mute;
int last_carrier;
int nosignal;
- unsigned int inresume;
+ unsigned int insuspend;
/* SAA7134_MPEG_* */
struct saa7134_ts ts;
@@ -632,7 +633,7 @@ extern struct video_device saa7134_radio_template;
void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm);
int saa7134_videoport_init(struct saa7134_dev *dev);
-void saa7134_set_decoder(struct saa7134_dev *dev);
+void saa7134_set_tvnorm_hw(struct saa7134_dev *dev);
int saa7134_common_ioctl(struct saa7134_dev *dev,
unsigned int cmd, void *arg);
@@ -706,6 +707,8 @@ int saa7134_input_init1(struct saa7134_dev *dev);
void saa7134_input_fini(struct saa7134_dev *dev);
void saa7134_input_irq(struct saa7134_dev *dev);
void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir);
+void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir);
+void saa7134_ir_stop(struct saa7134_dev *dev);
/*
diff --git a/drivers/media/video/se401.c b/drivers/media/video/se401.c
index 93fb04ed99a0..d5d7d6cf734a 100644
--- a/drivers/media/video/se401.c
+++ b/drivers/media/video/se401.c
@@ -1231,7 +1231,6 @@ static struct video_device se401_template = {
.owner = THIS_MODULE,
.name = "se401 USB camera",
.type = VID_TYPE_CAPTURE,
- .hardware = VID_HARDWARE_SE401,
.fops = &se401_fops,
};
diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c
index 6991e06f7651..511847912c48 100644
--- a/drivers/media/video/sn9c102/sn9c102_core.c
+++ b/drivers/media/video/sn9c102/sn9c102_core.c
@@ -3319,7 +3319,6 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
strcpy(cam->v4ldev->name, "SN9C1xx PC Camera");
cam->v4ldev->owner = THIS_MODULE;
cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES;
- cam->v4ldev->hardware = 0;
cam->v4ldev->fops = &sn9c102_fops;
cam->v4ldev->minor = video_nr[dev_nr];
cam->v4ldev->release = video_device_release;
diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c
index eb220461ac77..3fb85af5d1f2 100644
--- a/drivers/media/video/stradis.c
+++ b/drivers/media/video/stradis.c
@@ -1917,7 +1917,6 @@ static const struct file_operations saa_fops = {
static struct video_device saa_template = {
.name = "SAA7146A",
.type = VID_TYPE_CAPTURE | VID_TYPE_OVERLAY,
- .hardware = VID_HARDWARE_SAA7146,
.fops = &saa_fops,
.minor = -1,
};
diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c
index 9e009a7ab863..afc32aa56fde 100644
--- a/drivers/media/video/stv680.c
+++ b/drivers/media/video/stv680.c
@@ -1398,7 +1398,6 @@ static struct video_device stv680_template = {
.owner = THIS_MODULE,
.name = "STV0680 USB camera",
.type = VID_TYPE_CAPTURE,
- .hardware = VID_HARDWARE_SE401,
.fops = &stv680_fops,
.release = video_device_release,
.minor = -1,
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index 94843086cda9..9e99f3636d3d 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -30,7 +30,7 @@
/* standard i2c insmod options */
static unsigned short normal_i2c[] = {
-#ifdef CONFIG_TUNER_TEA5761
+#if defined(CONFIG_TUNER_TEA5761) || (defined(CONFIG_TUNER_TEA5761_MODULE) && defined(MODULE))
0x10,
#endif
0x42, 0x43, 0x4a, 0x4b, /* tda8290 */
@@ -113,7 +113,7 @@ static void fe_standby(struct tuner *t)
static int fe_has_signal(struct tuner *t)
{
struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
- u16 strength;
+ u16 strength = 0;
if (fe_tuner_ops->get_rf_strength)
fe_tuner_ops->get_rf_strength(&t->fe, &strength);
@@ -292,7 +292,6 @@ static void set_type(struct i2c_client *c, unsigned int type,
}
t->mode_mask = T_RADIO;
break;
-#ifdef CONFIG_TUNER_TEA5761
case TUNER_TEA5761:
if (tea5761_attach(&t->fe, t->i2c.adapter, t->i2c.addr) == NULL) {
t->type = TUNER_ABSENT;
@@ -301,7 +300,6 @@ static void set_type(struct i2c_client *c, unsigned int type,
}
t->mode_mask = T_RADIO;
break;
-#endif
case TUNER_PHILIPS_FMD1216ME_MK3:
buffer[0] = 0x0b;
buffer[1] = 0xdc;
@@ -594,7 +592,6 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
/* autodetection code based on the i2c addr */
if (!no_autodetect) {
switch (addr) {
-#ifdef CONFIG_TUNER_TEA5761
case 0x10:
if (tea5761_autodetection(t->i2c.adapter, t->i2c.addr) != EINVAL) {
t->type = TUNER_TEA5761;
@@ -606,7 +603,6 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
goto register_client;
}
break;
-#endif
case 0x42:
case 0x43:
case 0x4a:
diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c
index e2f1c972754b..25d0aef88ef5 100644
--- a/drivers/media/video/tvp5150.c
+++ b/drivers/media/video/tvp5150.c
@@ -799,10 +799,10 @@ static inline void tvp5150_reset(struct i2c_client *c)
tvp5150_write_inittab(c, tvp5150_init_enable);
/* Initialize image preferences */
- tvp5150_write(c, TVP5150_BRIGHT_CTL, decoder->bright >> 8);
- tvp5150_write(c, TVP5150_CONTRAST_CTL, decoder->contrast >> 8);
- tvp5150_write(c, TVP5150_SATURATION_CTL, decoder->contrast >> 8);
- tvp5150_write(c, TVP5150_HUE_CTL, (decoder->hue - 32768) >> 8);
+ tvp5150_write(c, TVP5150_BRIGHT_CTL, decoder->bright);
+ tvp5150_write(c, TVP5150_CONTRAST_CTL, decoder->contrast);
+ tvp5150_write(c, TVP5150_SATURATION_CTL, decoder->contrast);
+ tvp5150_write(c, TVP5150_HUE_CTL, decoder->hue);
tvp5150_set_std(c, decoder->norm);
};
@@ -1077,10 +1077,10 @@ static int tvp5150_detect_client(struct i2c_adapter *adapter,
core->norm = V4L2_STD_ALL; /* Default is autodetect */
core->route.input = TVP5150_COMPOSITE1;
core->enable = 1;
- core->bright = 32768;
- core->contrast = 32768;
- core->hue = 32768;
- core->sat = 32768;
+ core->bright = 128;
+ core->contrast = 128;
+ core->hue = 0;
+ core->sat = 128;
if (rv) {
kfree(c);
diff --git a/drivers/media/video/usbvideo/konicawc.c b/drivers/media/video/usbvideo/konicawc.c
index 491505d6fdee..3e93f8058770 100644
--- a/drivers/media/video/usbvideo/konicawc.c
+++ b/drivers/media/video/usbvideo/konicawc.c
@@ -238,8 +238,8 @@ static void konicawc_register_input(struct konicawc *cam, struct usb_device *dev
usb_to_input_id(dev, &input_dev->id);
input_dev->dev.parent = &dev->dev;
- input_dev->evbit[0] = BIT(EV_KEY);
- input_dev->keybit[LONG(BTN_0)] = BIT(BTN_0);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY);
+ input_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0);
input_dev->private = cam;
diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c
index dd1a6d6bbc9e..d847273eeba0 100644
--- a/drivers/media/video/usbvideo/quickcam_messenger.c
+++ b/drivers/media/video/usbvideo/quickcam_messenger.c
@@ -102,8 +102,8 @@ static void qcm_register_input(struct qcm *cam, struct usb_device *dev)
usb_to_input_id(dev, &input_dev->id);
input_dev->dev.parent = &dev->dev;
- input_dev->evbit[0] = BIT(EV_KEY);
- input_dev->keybit[LONG(BTN_0)] = BIT(BTN_0);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY);
+ input_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0);
input_dev->private = cam;
diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c
index 37ce36b9e587..fb434b5602a3 100644
--- a/drivers/media/video/usbvideo/usbvideo.c
+++ b/drivers/media/video/usbvideo/usbvideo.c
@@ -952,7 +952,6 @@ static const struct file_operations usbvideo_fops = {
static const struct video_device usbvideo_template = {
.owner = THIS_MODULE,
.type = VID_TYPE_CAPTURE,
- .hardware = VID_HARDWARE_CPIA,
.fops = &usbvideo_fops,
};
diff --git a/drivers/media/video/usbvideo/vicam.c b/drivers/media/video/usbvideo/vicam.c
index ff555129c82f..da1ba0211108 100644
--- a/drivers/media/video/usbvideo/vicam.c
+++ b/drivers/media/video/usbvideo/vicam.c
@@ -955,7 +955,7 @@ read_frame(struct vicam_camera *cam, int framenum)
request[7] = realShutter >> 8;
}
- // Per John Markus Bjørndalen, byte at index 8 causes problems if it isn't 0
+ // Per John Markus Bjørndalen, byte at index 8 causes problems if it isn't 0
request[8] = 0;
// bytes 9-15 do not seem to affect exposure or image quality
@@ -1074,7 +1074,6 @@ static struct video_device vicam_template = {
.owner = THIS_MODULE,
.name = "ViCam-based USB Camera",
.type = VID_TYPE_CAPTURE,
- .hardware = VID_HARDWARE_VICAM,
.fops = &vicam_fops,
.minor = -1,
};
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c
index e2f3c01cfa13..36e689fa16c0 100644
--- a/drivers/media/video/usbvision/usbvision-video.c
+++ b/drivers/media/video/usbvision/usbvision-video.c
@@ -1400,7 +1400,6 @@ static const struct file_operations usbvision_fops = {
static struct video_device usbvision_video_template = {
.owner = THIS_MODULE,
.type = VID_TYPE_TUNER | VID_TYPE_CAPTURE,
- .hardware = VID_HARDWARE_USBVISION,
.fops = &usbvision_fops,
.name = "usbvision-video",
.release = video_device_release,
@@ -1455,7 +1454,6 @@ static struct video_device usbvision_radio_template=
{
.owner = THIS_MODULE,
.type = VID_TYPE_TUNER,
- .hardware = VID_HARDWARE_USBVISION,
.fops = &usbvision_radio_fops,
.name = "usbvision-radio",
.release = video_device_release,
@@ -1492,7 +1490,6 @@ static struct video_device usbvision_vbi_template=
{
.owner = THIS_MODULE,
.type = VID_TYPE_TUNER,
- .hardware = VID_HARDWARE_USBVISION,
.fops = &usbvision_vbi_fops,
.release = video_device_release,
.name = "usbvision-vbi",
diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c
index 9eac65f34bff..dcf22a3b672a 100644
--- a/drivers/media/video/v4l1-compat.c
+++ b/drivers/media/video/v4l1-compat.c
@@ -144,7 +144,7 @@ const static unsigned int palette2pixelformat[] = {
[VIDEO_PALETTE_YUV422P] = V4L2_PIX_FMT_YUV422P,
};
-static unsigned int __attribute_pure__
+static unsigned int __pure
palette_to_pixelformat(unsigned int palette)
{
if (palette < ARRAY_SIZE(palette2pixelformat))
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index c3440b280d20..1141b4bf41ce 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -37,7 +37,7 @@
* Video4linux 1/2 integration by Justin Schoeman
* <justin@suntiger.ee.up.ac.za>
* 2.4 PROCFS support ported from 2.4 kernels by
- * Iñaki García Etxebarria <garetxe@euskalnet.net>
+ * Iñaki García Etxebarria <garetxe@euskalnet.net>
* Makefile fix by "W. Michael Petullo" <mike@flyn.org>
* 2.4 devfs support ported from 2.4 kernels by
* Dan Merillat <dan@merillat.org>
@@ -317,8 +317,6 @@ static const char *v4l2_ioctls[] = {
[_IOC_NR(VIDIOC_ENUM_FMT)] = "VIDIOC_ENUM_FMT",
[_IOC_NR(VIDIOC_G_FMT)] = "VIDIOC_G_FMT",
[_IOC_NR(VIDIOC_S_FMT)] = "VIDIOC_S_FMT",
- [_IOC_NR(VIDIOC_G_MPEGCOMP)] = "VIDIOC_G_MPEGCOMP",
- [_IOC_NR(VIDIOC_S_MPEGCOMP)] = "VIDIOC_S_MPEGCOMP",
[_IOC_NR(VIDIOC_REQBUFS)] = "VIDIOC_REQBUFS",
[_IOC_NR(VIDIOC_QUERYBUF)] = "VIDIOC_QUERYBUF",
[_IOC_NR(VIDIOC_G_FBUF)] = "VIDIOC_G_FBUF",
diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c
index 5599a36490fc..89a44f16f0ba 100644
--- a/drivers/media/video/videobuf-core.c
+++ b/drivers/media/video/videobuf-core.c
@@ -967,6 +967,7 @@ int videobuf_cgmbuf(struct videobuf_queue *q,
return 0;
}
+EXPORT_SYMBOL_GPL(videobuf_cgmbuf);
#endif
/* --------------------------------------------------------------------- */
@@ -985,7 +986,6 @@ EXPORT_SYMBOL_GPL(videobuf_reqbufs);
EXPORT_SYMBOL_GPL(videobuf_querybuf);
EXPORT_SYMBOL_GPL(videobuf_qbuf);
EXPORT_SYMBOL_GPL(videobuf_dqbuf);
-EXPORT_SYMBOL_GPL(videobuf_cgmbuf);
EXPORT_SYMBOL_GPL(videobuf_streamon);
EXPORT_SYMBOL_GPL(videobuf_streamoff);
diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c
index 3eb6123227b2..44ee408e145f 100644
--- a/drivers/media/video/videobuf-dma-sg.c
+++ b/drivers/media/video/videobuf-dma-sg.c
@@ -27,6 +27,7 @@
#include <linux/pci.h>
#include <linux/vmalloc.h>
#include <linux/pagemap.h>
+#include <linux/scatterlist.h>
#include <asm/page.h>
#include <asm/pgtable.h>
@@ -60,13 +61,13 @@ videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages)
sglist = kcalloc(nr_pages, sizeof(struct scatterlist), GFP_KERNEL);
if (NULL == sglist)
return NULL;
+ sg_init_table(sglist, nr_pages);
for (i = 0; i < nr_pages; i++, virt += PAGE_SIZE) {
pg = vmalloc_to_page(virt);
if (NULL == pg)
goto err;
BUG_ON(PageHighMem(pg));
- sglist[i].page = pg;
- sglist[i].length = PAGE_SIZE;
+ sg_set_page(&sglist[i], pg, PAGE_SIZE, 0);
}
return sglist;
@@ -86,22 +87,20 @@ videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset)
sglist = kcalloc(nr_pages, sizeof(*sglist), GFP_KERNEL);
if (NULL == sglist)
return NULL;
+ sg_init_table(sglist, nr_pages);
if (NULL == pages[0])
goto nopage;
if (PageHighMem(pages[0]))
/* DMA to highmem pages might not work */
goto highmem;
- sglist[0].page = pages[0];
- sglist[0].offset = offset;
- sglist[0].length = PAGE_SIZE - offset;
+ sg_set_page(&sglist[0], pages[0], PAGE_SIZE - offset, offset);
for (i = 1; i < nr_pages; i++) {
if (NULL == pages[i])
goto nopage;
if (PageHighMem(pages[i]))
goto highmem;
- sglist[i].page = pages[i];
- sglist[i].length = PAGE_SIZE;
+ sg_set_page(&sglist[i], pages[i], PAGE_SIZE, 0);
}
return sglist;
diff --git a/drivers/media/video/videocodec.c b/drivers/media/video/videocodec.c
index f2bbd7a4d562..87951ec8254f 100644
--- a/drivers/media/video/videocodec.c
+++ b/drivers/media/video/videocodec.c
@@ -86,8 +86,8 @@ videocodec_attach (struct videocodec_master *master)
}
dprintk(2,
- "videocodec_attach: '%s', type: %x, flags %lx, magic %lx\n",
- master->name, master->type, master->flags, master->magic);
+ "videocodec_attach: '%s', flags %lx, magic %lx\n",
+ master->name, master->flags, master->magic);
if (!h) {
dprintk(1,
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c
index 8d8e517b344f..9611c3990285 100644
--- a/drivers/media/video/videodev.c
+++ b/drivers/media/video/videodev.c
@@ -1313,48 +1313,6 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
ret=vfd->vidioc_cropcap(file, fh, p);
break;
}
- case VIDIOC_G_MPEGCOMP:
- {
- struct v4l2_mpeg_compression *p=arg;
-
- /*FIXME: Several fields not shown */
- if (!vfd->vidioc_g_mpegcomp)
- break;
- ret=vfd->vidioc_g_mpegcomp(file, fh, p);
- if (!ret)
- dbgarg (cmd, "ts_pid_pmt=%d, ts_pid_audio=%d,"
- " ts_pid_video=%d, ts_pid_pcr=%d, "
- "ps_size=%d, au_sample_rate=%d, "
- "au_pesid=%c, vi_frame_rate=%d, "
- "vi_frames_per_gop=%d, "
- "vi_bframes_count=%d, vi_pesid=%c\n",
- p->ts_pid_pmt,p->ts_pid_audio,
- p->ts_pid_video,p->ts_pid_pcr,
- p->ps_size, p->au_sample_rate,
- p->au_pesid, p->vi_frame_rate,
- p->vi_frames_per_gop,
- p->vi_bframes_count, p->vi_pesid);
- break;
- }
- case VIDIOC_S_MPEGCOMP:
- {
- struct v4l2_mpeg_compression *p=arg;
- /*FIXME: Several fields not shown */
- if (!vfd->vidioc_s_mpegcomp)
- break;
- dbgarg (cmd, "ts_pid_pmt=%d, ts_pid_audio=%d, "
- "ts_pid_video=%d, ts_pid_pcr=%d, ps_size=%d, "
- "au_sample_rate=%d, au_pesid=%c, "
- "vi_frame_rate=%d, vi_frames_per_gop=%d, "
- "vi_bframes_count=%d, vi_pesid=%c\n",
- p->ts_pid_pmt,p->ts_pid_audio, p->ts_pid_video,
- p->ts_pid_pcr, p->ps_size, p->au_sample_rate,
- p->au_pesid, p->vi_frame_rate,
- p->vi_frames_per_gop, p->vi_bframes_count,
- p->vi_pesid);
- ret=vfd->vidioc_s_mpegcomp(file, fh, p);
- break;
- }
case VIDIOC_G_JPEGCOMP:
{
struct v4l2_jpegcompression *p=arg;
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
index b532aa280a1b..ee73dc75131c 100644
--- a/drivers/media/video/vivi.c
+++ b/drivers/media/video/vivi.c
@@ -1119,7 +1119,6 @@ static const struct file_operations vivi_fops = {
static struct video_device vivi = {
.name = "vivi",
.type = VID_TYPE_CAPTURE,
- .hardware = 0,
.fops = &vivi_fops,
.minor = -1,
// .release = video_device_release,
diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c
index 47366408637c..08aaae07c7e0 100644
--- a/drivers/media/video/w9966.c
+++ b/drivers/media/video/w9966.c
@@ -196,7 +196,6 @@ static struct video_device w9966_template = {
.owner = THIS_MODULE,
.name = W9966_DRIVERNAME,
.type = VID_TYPE_CAPTURE | VID_TYPE_SCALES,
- .hardware = VID_HARDWARE_W9966,
.fops = &w9966_fops,
};
diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c
index 9e7f3e685d73..2ae1430f5f7d 100644
--- a/drivers/media/video/w9968cf.c
+++ b/drivers/media/video/w9968cf.c
@@ -3549,7 +3549,6 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
strcpy(cam->v4ldev->name, symbolic(camlist, mod_id));
cam->v4ldev->owner = THIS_MODULE;
cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES;
- cam->v4ldev->hardware = VID_HARDWARE_W9968CF;
cam->v4ldev->fops = &w9968cf_fops;
cam->v4ldev->minor = video_nr[dev_nr];
cam->v4ldev->release = video_device_release;
diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c
index 08a93c31c0a0..2c5665c82442 100644
--- a/drivers/media/video/zc0301/zc0301_core.c
+++ b/drivers/media/video/zc0301/zc0301_core.c
@@ -1985,7 +1985,6 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
strcpy(cam->v4ldev->name, "ZC0301[P] PC Camera");
cam->v4ldev->owner = THIS_MODULE;
cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES;
- cam->v4ldev->hardware = 0;
cam->v4ldev->fops = &zc0301_fops;
cam->v4ldev->minor = video_nr[dev_nr];
cam->v4ldev->release = video_device_release;
diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c
index 48da36a15fca..6e0ac4c5c379 100644
--- a/drivers/media/video/zoran_card.c
+++ b/drivers/media/video/zoran_card.c
@@ -1235,8 +1235,14 @@ zoran_setup_videocodec (struct zoran *zr,
return m;
}
- m->magic = 0L; /* magic not used */
- m->type = VID_HARDWARE_ZR36067;
+ /* magic and type are unused for master struct. Makes sense only at
+ codec structs.
+ In the past, .type were initialized to the old V4L1 .hardware
+ value, as VID_HARDWARE_ZR36067
+ */
+ m->magic = 0L;
+ m->type = 0;
+
m->flags = CODEC_FLAG_ENCODER | CODEC_FLAG_DECODER;
strncpy(m->name, ZR_DEVNAME(zr), sizeof(m->name));
m->data = zr;
diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c
index 1c14fa2bd411..dd3d7d2c8b0e 100644
--- a/drivers/media/video/zoran_driver.c
+++ b/drivers/media/video/zoran_driver.c
@@ -60,7 +60,6 @@
#include <linux/spinlock.h>
#define MAP_NR(x) virt_to_page(x)
-#define ZORAN_HARDWARE VID_HARDWARE_ZR36067
#define ZORAN_VID_TYPE ( \
VID_TYPE_CAPTURE | \
VID_TYPE_OVERLAY | \
@@ -1285,7 +1284,7 @@ zoran_open (struct inode *inode,
}
dprintk(1, KERN_INFO "%s: zoran_open(%s, pid=[%d]), users(-)=%d\n",
- ZR_DEVNAME(zr), current->comm, current->pid, zr->user);
+ ZR_DEVNAME(zr), current->comm, task_pid_nr(current), zr->user);
/* now, create the open()-specific file_ops struct */
fh = kzalloc(sizeof(struct zoran_fh), GFP_KERNEL);
@@ -1358,7 +1357,7 @@ zoran_close (struct inode *inode,
struct zoran *zr = fh->zr;
dprintk(1, KERN_INFO "%s: zoran_close(%s, pid=[%d]), users(+)=%d\n",
- ZR_DEVNAME(zr), current->comm, current->pid, zr->user);
+ ZR_DEVNAME(zr), current->comm, task_pid_nr(current), zr->user);
/* kernel locks (fs/device.c), so don't do that ourselves
* (prevents deadlocks) */
@@ -4659,7 +4658,6 @@ struct video_device zoran_template __devinitdata = {
#ifdef CONFIG_VIDEO_V4L2
.type2 = ZORAN_V4L2_VID_FLAGS,
#endif
- .hardware = ZORAN_HARDWARE,
.fops = &zoran_fops,
.release = &zoran_vdev_release,
.minor = -1
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index bdff950a54a1..626bb3c9af2b 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -293,7 +293,7 @@ nextSGEset:
for (ii=0; ii < (numSgeThisFrame-1); ii++) {
thisxfer = sg_dma_len(sg);
if (thisxfer == 0) {
- sg ++; /* Get next SG element from the OS */
+ sg = sg_next(sg); /* Get next SG element from the OS */
sg_done++;
continue;
}
@@ -301,7 +301,7 @@ nextSGEset:
v2 = sg_dma_address(sg);
mptscsih_add_sge(psge, sgflags | thisxfer, v2);
- sg++; /* Get next SG element from the OS */
+ sg = sg_next(sg); /* Get next SG element from the OS */
psge += (sizeof(u32) + sizeof(dma_addr_t));
sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
sg_done++;
@@ -322,7 +322,7 @@ nextSGEset:
v2 = sg_dma_address(sg);
mptscsih_add_sge(psge, sgflags | thisxfer, v2);
/*
- sg++;
+ sg = sg_next(sg);
psge += (sizeof(u32) + sizeof(dma_addr_t));
*/
sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
@@ -2605,14 +2605,10 @@ mptscsih_set_scsi_lookup(MPT_ADAPTER *ioc, int i, struct scsi_cmnd *scmd)
}
/**
- * SCPNT_TO_LOOKUP_IDX
- *
- * search's for a given scmd in the ScsiLookup[] array list
- *
+ * SCPNT_TO_LOOKUP_IDX - searches for a given scmd in the ScsiLookup[] array list
* @ioc: Pointer to MPT_ADAPTER structure
- * @scmd: scsi_cmnd pointer
- *
- **/
+ * @sc: scsi_cmnd pointer
+ */
static int
SCPNT_TO_LOOKUP_IDX(MPT_ADAPTER *ioc, struct scsi_cmnd *sc)
{
diff --git a/drivers/message/i2o/README b/drivers/message/i2o/README
index a81f851f7b5d..911fc3021e3b 100644
--- a/drivers/message/i2o/README
+++ b/drivers/message/i2o/README
@@ -30,13 +30,13 @@ Juha Sievanen, University of Helsinki Finland
Bug fixes
Core code extensions
-Auvo Häkkinen, University of Helsinki Finland
+Auvo Häkkinen, University of Helsinki Finland
LAN OSM code
/Proc interface to LAN class
Bug fixes
Core code extensions
-Taneli Vähäkangas, University of Helsinki Finland
+Taneli Vähäkangas, University of Helsinki Finland
Fixes to i2o_config
CREDITS
diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c
index 8c83ee3b0920..6cbcc21de518 100644
--- a/drivers/message/i2o/exec-osm.c
+++ b/drivers/message/i2o/exec-osm.c
@@ -15,8 +15,8 @@
*
* Fixes/additions:
* Philipp Rumpf
- * Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI>
- * Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI>
+ * Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI>
+ * Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI>
* Deepak Saxena <deepak@plexity.net>
* Boji T Kannanthanam <boji.t.kannanthanam@intel.com>
* Alan Cox <alan@redhat.com>:
@@ -41,8 +41,6 @@
struct i2o_driver i2o_exec_driver;
-static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind);
-
/* global wait list for POST WAIT */
static LIST_HEAD(i2o_exec_wait_list);
@@ -369,6 +367,53 @@ static int i2o_exec_remove(struct device *dev)
return 0;
};
+#ifdef CONFIG_I2O_LCT_NOTIFY_ON_CHANGES
+/**
+ * i2o_exec_lct_notify - Send a asynchronus LCT NOTIFY request
+ * @c: I2O controller to which the request should be send
+ * @change_ind: change indicator
+ *
+ * This function sends a LCT NOTIFY request to the I2O controller with
+ * the change indicator change_ind. If the change_ind == 0 the controller
+ * replies immediately after the request. If change_ind > 0 the reply is
+ * send after change indicator of the LCT is > change_ind.
+ */
+static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind)
+{
+ i2o_status_block *sb = c->status_block.virt;
+ struct device *dev;
+ struct i2o_message *msg;
+
+ mutex_lock(&c->lct_lock);
+
+ dev = &c->pdev->dev;
+
+ if (i2o_dma_realloc
+ (dev, &c->dlct, le32_to_cpu(sb->expected_lct_size), GFP_KERNEL))
+ return -ENOMEM;
+
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
+
+ msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6);
+ msg->u.head[1] = cpu_to_le32(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 |
+ ADAPTER_TID);
+ msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context);
+ msg->u.s.tcntxt = cpu_to_le32(0x00000000);
+ msg->body[0] = cpu_to_le32(0xffffffff);
+ msg->body[1] = cpu_to_le32(change_ind);
+ msg->body[2] = cpu_to_le32(0xd0000000 | c->dlct.len);
+ msg->body[3] = cpu_to_le32(c->dlct.phys);
+
+ i2o_msg_post(c, msg);
+
+ mutex_unlock(&c->lct_lock);
+
+ return 0;
+}
+#endif
+
/**
* i2o_exec_lct_modified - Called on LCT NOTIFY reply
* @_work: work struct for a specific controller
@@ -525,51 +570,6 @@ int i2o_exec_lct_get(struct i2o_controller *c)
return rc;
}
-/**
- * i2o_exec_lct_notify - Send a asynchronus LCT NOTIFY request
- * @c: I2O controller to which the request should be send
- * @change_ind: change indicator
- *
- * This function sends a LCT NOTIFY request to the I2O controller with
- * the change indicator change_ind. If the change_ind == 0 the controller
- * replies immediately after the request. If change_ind > 0 the reply is
- * send after change indicator of the LCT is > change_ind.
- */
-static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind)
-{
- i2o_status_block *sb = c->status_block.virt;
- struct device *dev;
- struct i2o_message *msg;
-
- mutex_lock(&c->lct_lock);
-
- dev = &c->pdev->dev;
-
- if (i2o_dma_realloc
- (dev, &c->dlct, le32_to_cpu(sb->expected_lct_size), GFP_KERNEL))
- return -ENOMEM;
-
- msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
- if (IS_ERR(msg))
- return PTR_ERR(msg);
-
- msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6);
- msg->u.head[1] = cpu_to_le32(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 |
- ADAPTER_TID);
- msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context);
- msg->u.s.tcntxt = cpu_to_le32(0x00000000);
- msg->body[0] = cpu_to_le32(0xffffffff);
- msg->body[1] = cpu_to_le32(change_ind);
- msg->body[2] = cpu_to_le32(0xd0000000 | c->dlct.len);
- msg->body[3] = cpu_to_le32(c->dlct.phys);
-
- i2o_msg_post(c, msg);
-
- mutex_unlock(&c->lct_lock);
-
- return 0;
-};
-
/* Exec OSM driver struct */
struct i2o_driver i2o_exec_driver = {
.name = OSM_NAME,
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
index 50b2c7334410..e4ad7a1c4fbd 100644
--- a/drivers/message/i2o/i2o_block.c
+++ b/drivers/message/i2o/i2o_block.c
@@ -149,29 +149,6 @@ static int i2o_block_device_flush(struct i2o_device *dev)
};
/**
- * i2o_block_issue_flush - device-flush interface for block-layer
- * @queue: the request queue of the device which should be flushed
- * @disk: gendisk
- * @error_sector: error offset
- *
- * Helper function to provide flush functionality to block-layer.
- *
- * Returns 0 on success or negative error code on failure.
- */
-
-static int i2o_block_issue_flush(struct request_queue * queue, struct gendisk *disk,
- sector_t * error_sector)
-{
- struct i2o_block_device *i2o_blk_dev = queue->queuedata;
- int rc = -ENODEV;
-
- if (likely(i2o_blk_dev))
- rc = i2o_block_device_flush(i2o_blk_dev->i2o_dev);
-
- return rc;
-}
-
-/**
* i2o_block_device_mount - Mount (load) the media of device dev
* @dev: I2O device which should receive the mount request
* @media_id: Media Identifier
@@ -307,6 +284,7 @@ static inline struct i2o_block_request *i2o_block_request_alloc(void)
return ERR_PTR(-ENOMEM);
INIT_LIST_HEAD(&ireq->queue);
+ sg_init_table(ireq->sg_table, I2O_MAX_PHYS_SEGMENTS);
return ireq;
};
@@ -1009,7 +987,6 @@ static struct i2o_block_device *i2o_block_device_alloc(void)
}
blk_queue_prep_rq(queue, i2o_block_prep_req_fn);
- blk_queue_issue_flush_fn(queue, i2o_block_issue_flush);
gd->major = I2O_MAJOR;
gd->queue = queue;
@@ -1100,8 +1077,8 @@ static int i2o_block_probe(struct device *dev)
blk_queue_max_sectors(queue, max_sectors);
blk_queue_max_hw_segments(queue, i2o_sg_tablesize(c, body_size));
- osm_debug("max sectors = %d\n", queue->max_phys_segments);
- osm_debug("phys segments = %d\n", queue->max_sectors);
+ osm_debug("max sectors = %d\n", queue->max_sectors);
+ osm_debug("phys segments = %d\n", queue->max_phys_segments);
osm_debug("max hw segments = %d\n", queue->max_hw_segments);
/*
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c
index 84e046e94f5f..c0fb77dc19bb 100644
--- a/drivers/message/i2o/i2o_config.c
+++ b/drivers/message/i2o/i2o_config.c
@@ -10,12 +10,12 @@
* Added basic ioctl() support
* Deepak Saxena (06/07/1999):
* Added software download ioctl (still testing)
- * Auvo Häkkinen (09/10/1999):
+ * Auvo Häkkinen (09/10/1999):
* Changes to i2o_cfg_reply(), ioctl_parms()
* Added ioct_validate()
- * Taneli Vähäkangas (09/30/1999):
+ * Taneli Vähäkangas (09/30/1999):
* Fixed ioctl_swdl()
- * Taneli Vähäkangas (10/04/1999):
+ * Taneli Vähäkangas (10/04/1999):
* Changed ioctl_swdl(), implemented ioctl_swul() and ioctl_swdel()
* Deepak Saxena (11/18/1999):
* Added event managmenet support
diff --git a/drivers/message/i2o/i2o_proc.c b/drivers/message/i2o/i2o_proc.c
index 06892ac2286e..6fdd072201f9 100644
--- a/drivers/message/i2o/i2o_proc.c
+++ b/drivers/message/i2o/i2o_proc.c
@@ -19,8 +19,8 @@
*
*
* Fixes/additions:
- * Juha Sievänen (Juha.Sievanen@cs.Helsinki.FI),
- * Auvo Häkkinen (Auvo.Hakkinen@cs.Helsinki.FI)
+ * Juha Sievänen (Juha.Sievanen@cs.Helsinki.FI),
+ * Auvo Häkkinen (Auvo.Hakkinen@cs.Helsinki.FI)
* University of Helsinki, Department of Computer Science
* LAN entries
* Markus Lidel <Markus.Lidel@shadowconnect.com>
diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c
index a1ec16a075c6..7814a06ae970 100644
--- a/drivers/message/i2o/iop.c
+++ b/drivers/message/i2o/iop.c
@@ -15,8 +15,8 @@
*
* Fixes/additions:
* Philipp Rumpf
- * Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI>
- * Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI>
+ * Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI>
+ * Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI>
* Deepak Saxena <deepak@plexity.net>
* Boji T Kannanthanam <boji.t.kannanthanam@intel.com>
* Alan Cox <alan@redhat.com>:
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c
index 3661e6e065d2..685a89547a51 100644
--- a/drivers/message/i2o/pci.c
+++ b/drivers/message/i2o/pci.c
@@ -15,8 +15,8 @@
*
* Fixes/additions:
* Philipp Rumpf
- * Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI>
- * Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI>
+ * Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI>
+ * Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI>
* Deepak Saxena <deepak@plexity.net>
* Boji T Kannanthanam <boji.t.kannanthanam@intel.com>
* Alan Cox <alan@redhat.com>:
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index a20a51efe118..25716193a534 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -10,8 +10,8 @@ config MFD_SM501
---help---
This is the core driver for the Silicon Motion SM501 multimedia
companion chip. This device is a multifunction device which may
- provide numerous interfaces including USB host controller USB gadget,
- Asyncronous Serial ports, Audio functions and a dual display video
+ provide numerous interfaces including USB host controller, USB gadget,
+ asynchronous serial ports, audio functions, and a dual display video
interface. The device may be connected by PCI or local bus with
varying functions enabled.
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 73e248fb2ff1..b5e67c0ff433 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -111,6 +111,21 @@ config ASUS_LAPTOP
If you have an ACPI-compatible ASUS laptop, say Y or M here.
+config FUJITSU_LAPTOP
+ tristate "Fujitsu Laptop Extras"
+ depends on X86
+ depends on ACPI
+ depends on BACKLIGHT_CLASS_DEVICE
+ ---help---
+ This is a driver for laptops built by Fujitsu:
+
+ * P2xxx/P5xxx/S6xxx/S7xxx series Lifebooks
+ * Possibly other Fujitsu laptop models
+
+ It adds support for LCD brightness control.
+
+ If you have a Fujitsu laptop, say Y or M here.
+
config MSI_LAPTOP
tristate "MSI Laptop Extras"
depends on X86
@@ -134,6 +149,7 @@ config SONY_LAPTOP
tristate "Sony Laptop Extras"
depends on X86 && ACPI
select BACKLIGHT_CLASS_DEVICE
+ depends on INPUT
---help---
This mini-driver drives the SNC and SPIC devices present in the ACPI
BIOS of the Sony Vaio laptops.
@@ -156,6 +172,7 @@ config THINKPAD_ACPI
select BACKLIGHT_CLASS_DEVICE
select HWMON
select NVRAM
+ depends on INPUT
---help---
This is a driver for the IBM and Lenovo ThinkPad laptops. It adds
support for Fn-Fx key combinations, Bluetooth control, video
@@ -163,7 +180,7 @@ config THINKPAD_ACPI
For more information about this driver see
<file:Documentation/thinkpad-acpi.txt> and <http://ibm-acpi.sf.net/> .
- This driver was formely known as ibm-acpi.
+ This driver was formerly known as ibm-acpi.
If you have an IBM or Lenovo ThinkPad laptop, say Y or M here.
@@ -197,10 +214,22 @@ config THINKPAD_ACPI_BAY
default y
---help---
Allows the thinkpad_acpi driver to handle removable bays. It will
- eletrically disable the device in the bay, and also generate
+ electrically disable the device in the bay, and also generate
notifications when the bay lever is ejected or inserted.
If you are not sure, say Y here.
+config ATMEL_SSC
+ tristate "Device driver for Atmel SSC peripheral"
+ depends on AVR32 || ARCH_AT91
+ ---help---
+ This option enables device driver support for Atmel Syncronized
+ Serial Communication peripheral (SSC).
+
+ The SSC peripheral supports a wide variety of serial frame based
+ communications, i.e. I2S, SPI, etc.
+
+ If unsure, say N.
+
endif # MISC_DEVICES
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index b5ce0e3dba86..87f2685d728f 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_IBM_ASM) += ibmasm/
obj-$(CONFIG_HDPU_FEATURES) += hdpuftrs/
obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o
obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o
+obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o
obj-$(CONFIG_LKDTM) += lkdtm.o
obj-$(CONFIG_TIFM_CORE) += tifm_core.o
obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o
@@ -14,4 +15,5 @@ obj-$(CONFIG_PHANTOM) += phantom.o
obj-$(CONFIG_SGI_IOC4) += ioc4.o
obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o
obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o
+obj-$(CONFIG_FUJITSU_LAPTOP) += fujitsu-laptop.o
obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o
diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c
new file mode 100644
index 000000000000..058ccac700d0
--- /dev/null
+++ b/drivers/misc/atmel-ssc.c
@@ -0,0 +1,174 @@
+/*
+ * Atmel SSC driver
+ *
+ * Copyright (C) 2007 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/list.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/atmel-ssc.h>
+
+/* Serialize access to ssc_list and user count */
+static DEFINE_SPINLOCK(user_lock);
+static LIST_HEAD(ssc_list);
+
+struct ssc_device *ssc_request(unsigned int ssc_num)
+{
+ int ssc_valid = 0;
+ struct ssc_device *ssc;
+
+ spin_lock(&user_lock);
+ list_for_each_entry(ssc, &ssc_list, list) {
+ if (ssc->pdev->id == ssc_num) {
+ ssc_valid = 1;
+ break;
+ }
+ }
+
+ if (!ssc_valid) {
+ spin_unlock(&user_lock);
+ dev_dbg(&ssc->pdev->dev, "could not find requested device\n");
+ return ERR_PTR(-ENODEV);
+ }
+
+ if (ssc->user) {
+ spin_unlock(&user_lock);
+ dev_dbg(&ssc->pdev->dev, "module busy\n");
+ return ERR_PTR(-EBUSY);
+ }
+ ssc->user++;
+ spin_unlock(&user_lock);
+
+ clk_enable(ssc->clk);
+
+ return ssc;
+}
+EXPORT_SYMBOL(ssc_request);
+
+void ssc_free(struct ssc_device *ssc)
+{
+ spin_lock(&user_lock);
+ if (ssc->user) {
+ ssc->user--;
+ clk_disable(ssc->clk);
+ } else {
+ dev_dbg(&ssc->pdev->dev, "device already free\n");
+ }
+ spin_unlock(&user_lock);
+}
+EXPORT_SYMBOL(ssc_free);
+
+static int __init ssc_probe(struct platform_device *pdev)
+{
+ int retval = 0;
+ struct resource *regs;
+ struct ssc_device *ssc;
+
+ ssc = kzalloc(sizeof(struct ssc_device), GFP_KERNEL);
+ if (!ssc) {
+ dev_dbg(&pdev->dev, "out of memory\n");
+ retval = -ENOMEM;
+ goto out;
+ }
+
+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!regs) {
+ dev_dbg(&pdev->dev, "no mmio resource defined\n");
+ retval = -ENXIO;
+ goto out_free;
+ }
+
+ ssc->clk = clk_get(&pdev->dev, "pclk");
+ if (IS_ERR(ssc->clk)) {
+ dev_dbg(&pdev->dev, "no pclk clock defined\n");
+ retval = -ENXIO;
+ goto out_free;
+ }
+
+ ssc->pdev = pdev;
+ ssc->regs = ioremap(regs->start, regs->end - regs->start + 1);
+ if (!ssc->regs) {
+ dev_dbg(&pdev->dev, "ioremap failed\n");
+ retval = -EINVAL;
+ goto out_clk;
+ }
+
+ /* disable all interrupts */
+ clk_enable(ssc->clk);
+ ssc_writel(ssc->regs, IDR, ~0UL);
+ ssc_readl(ssc->regs, SR);
+ clk_disable(ssc->clk);
+
+ ssc->irq = platform_get_irq(pdev, 0);
+ if (!ssc->irq) {
+ dev_dbg(&pdev->dev, "could not get irq\n");
+ retval = -ENXIO;
+ goto out_unmap;
+ }
+
+ spin_lock(&user_lock);
+ list_add_tail(&ssc->list, &ssc_list);
+ spin_unlock(&user_lock);
+
+ platform_set_drvdata(pdev, ssc);
+
+ dev_info(&pdev->dev, "Atmel SSC device at 0x%p (irq %d)\n",
+ ssc->regs, ssc->irq);
+
+ goto out;
+
+out_unmap:
+ iounmap(ssc->regs);
+out_clk:
+ clk_put(ssc->clk);
+out_free:
+ kfree(ssc);
+out:
+ return retval;
+}
+
+static int __devexit ssc_remove(struct platform_device *pdev)
+{
+ struct ssc_device *ssc = platform_get_drvdata(pdev);
+
+ spin_lock(&user_lock);
+ iounmap(ssc->regs);
+ clk_put(ssc->clk);
+ list_del(&ssc->list);
+ kfree(ssc);
+ spin_unlock(&user_lock);
+
+ return 0;
+}
+
+static struct platform_driver ssc_driver = {
+ .remove = __devexit_p(ssc_remove),
+ .driver = {
+ .name = "ssc",
+ },
+};
+
+static int __init ssc_init(void)
+{
+ return platform_driver_probe(&ssc_driver, ssc_probe);
+}
+module_init(ssc_init);
+
+static void __exit ssc_exit(void)
+{
+ platform_driver_unregister(&ssc_driver);
+}
+module_exit(ssc_exit);
+
+MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
+MODULE_DESCRIPTION("SSC driver for Atmel AVR32 and AT91");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/fujitsu-laptop.c b/drivers/misc/fujitsu-laptop.c
new file mode 100644
index 000000000000..c8d62c268b11
--- /dev/null
+++ b/drivers/misc/fujitsu-laptop.c
@@ -0,0 +1,355 @@
+/*-*-linux-c-*-*/
+
+/*
+ Copyright (C) 2007 Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
+ Based on earlier work:
+ Copyright (C) 2003 Shane Spencer <shane@bogomip.com>
+ Adrian Yee <brewt-fujitsu@brewt.org>
+
+ Templated from msi-laptop.c which is copyright by its respective authors.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+ */
+
+/*
+ * fujitsu-laptop.c - Fujitsu laptop support, providing access to additional
+ * features made available on a range of Fujitsu laptops including the
+ * P2xxx/P5xxx/S6xxx/S7xxx series.
+ *
+ * This driver exports a few files in /sys/devices/platform/fujitsu-laptop/;
+ * others may be added at a later date.
+ *
+ * lcd_level - Screen brightness: contains a single integer in the
+ * range 0..7. (rw)
+ *
+ * In addition to these platform device attributes the driver
+ * registers itself in the Linux backlight control subsystem and is
+ * available to userspace under /sys/class/backlight/fujitsu-laptop/.
+ *
+ * This driver has been tested on a Fujitsu Lifebook S7020. It should
+ * work on most P-series and S-series Lifebooks, but YMMV.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/acpi.h>
+#include <linux/dmi.h>
+#include <linux/backlight.h>
+#include <linux/platform_device.h>
+#include <linux/autoconf.h>
+
+#define FUJITSU_DRIVER_VERSION "0.3"
+
+#define FUJITSU_LCD_N_LEVELS 8
+
+#define ACPI_FUJITSU_CLASS "fujitsu"
+#define ACPI_FUJITSU_HID "FUJ02B1"
+#define ACPI_FUJITSU_DRIVER_NAME "Fujitsu laptop FUJ02B1 ACPI extras driver"
+#define ACPI_FUJITSU_DEVICE_NAME "Fujitsu FUJ02B1"
+
+struct fujitsu_t {
+ acpi_handle acpi_handle;
+ struct backlight_device *bl_device;
+ struct platform_device *pf_device;
+
+ unsigned long fuj02b1_state;
+ unsigned int brightness_changed;
+ unsigned int brightness_level;
+};
+
+static struct fujitsu_t *fujitsu;
+
+/* Hardware access */
+
+static int set_lcd_level(int level)
+{
+ acpi_status status = AE_OK;
+ union acpi_object arg0 = { ACPI_TYPE_INTEGER };
+ struct acpi_object_list arg_list = { 1, &arg0 };
+ acpi_handle handle = NULL;
+
+ if (level < 0 || level >= FUJITSU_LCD_N_LEVELS)
+ return -EINVAL;
+
+ if (!fujitsu)
+ return -EINVAL;
+
+ status = acpi_get_handle(fujitsu->acpi_handle, "SBLL", &handle);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "SBLL not present\n"));
+ return -ENODEV;
+ }
+
+ arg0.integer.value = level;
+
+ status = acpi_evaluate_object(handle, NULL, &arg_list, NULL);
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
+
+ return 0;
+}
+
+static int get_lcd_level(void)
+{
+ unsigned long state = 0;
+ acpi_status status = AE_OK;
+
+ // Get the Brightness
+ status =
+ acpi_evaluate_integer(fujitsu->acpi_handle, "GBLL", NULL, &state);
+ if (status < 0)
+ return status;
+
+ fujitsu->fuj02b1_state = state;
+ fujitsu->brightness_level = state & 0x0fffffff;
+
+ if (state & 0x80000000)
+ fujitsu->brightness_changed = 1;
+ else
+ fujitsu->brightness_changed = 0;
+
+ return fujitsu->brightness_level;
+}
+
+/* Backlight device stuff */
+
+static int bl_get_brightness(struct backlight_device *b)
+{
+ return get_lcd_level();
+}
+
+static int bl_update_status(struct backlight_device *b)
+{
+ return set_lcd_level(b->props.brightness);
+}
+
+static struct backlight_ops fujitsubl_ops = {
+ .get_brightness = bl_get_brightness,
+ .update_status = bl_update_status,
+};
+
+/* Platform device */
+
+static ssize_t show_lcd_level(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+
+ int ret;
+
+ ret = get_lcd_level();
+ if (ret < 0)
+ return ret;
+
+ return sprintf(buf, "%i\n", ret);
+}
+
+static ssize_t store_lcd_level(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+
+ int level, ret;
+
+ if (sscanf(buf, "%i", &level) != 1
+ || (level < 0 || level >= FUJITSU_LCD_N_LEVELS))
+ return -EINVAL;
+
+ ret = set_lcd_level(level);
+ if (ret < 0)
+ return ret;
+
+ return count;
+}
+
+static DEVICE_ATTR(lcd_level, 0644, show_lcd_level, store_lcd_level);
+
+static struct attribute *fujitsupf_attributes[] = {
+ &dev_attr_lcd_level.attr,
+ NULL
+};
+
+static struct attribute_group fujitsupf_attribute_group = {
+ .attrs = fujitsupf_attributes
+};
+
+static struct platform_driver fujitsupf_driver = {
+ .driver = {
+ .name = "fujitsu-laptop",
+ .owner = THIS_MODULE,
+ }
+};
+
+/* ACPI device */
+
+static int acpi_fujitsu_add(struct acpi_device *device)
+{
+ int result = 0;
+ int state = 0;
+
+ ACPI_FUNCTION_TRACE("acpi_fujitsu_add");
+
+ if (!device)
+ return -EINVAL;
+
+ fujitsu->acpi_handle = device->handle;
+ sprintf(acpi_device_name(device), "%s", ACPI_FUJITSU_DEVICE_NAME);
+ sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS);
+ acpi_driver_data(device) = fujitsu;
+
+ result = acpi_bus_get_power(fujitsu->acpi_handle, &state);
+ if (result) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error reading power state\n"));
+ goto end;
+ }
+
+ printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
+ acpi_device_name(device), acpi_device_bid(device),
+ !device->power.state ? "on" : "off");
+
+ end:
+
+ return result;
+}
+
+static int acpi_fujitsu_remove(struct acpi_device *device, int type)
+{
+ ACPI_FUNCTION_TRACE("acpi_fujitsu_remove");
+
+ if (!device || !acpi_driver_data(device))
+ return -EINVAL;
+ fujitsu->acpi_handle = 0;
+
+ return 0;
+}
+
+static const struct acpi_device_id fujitsu_device_ids[] = {
+ {ACPI_FUJITSU_HID, 0},
+ {"", 0},
+};
+
+static struct acpi_driver acpi_fujitsu_driver = {
+ .name = ACPI_FUJITSU_DRIVER_NAME,
+ .class = ACPI_FUJITSU_CLASS,
+ .ids = fujitsu_device_ids,
+ .ops = {
+ .add = acpi_fujitsu_add,
+ .remove = acpi_fujitsu_remove,
+ },
+};
+
+/* Initialization */
+
+static int __init fujitsu_init(void)
+{
+ int ret, result;
+
+ if (acpi_disabled)
+ return -ENODEV;
+
+ fujitsu = kmalloc(sizeof(struct fujitsu_t), GFP_KERNEL);
+ if (!fujitsu)
+ return -ENOMEM;
+ memset(fujitsu, 0, sizeof(struct fujitsu_t));
+
+ result = acpi_bus_register_driver(&acpi_fujitsu_driver);
+ if (result < 0) {
+ ret = -ENODEV;
+ goto fail_acpi;
+ }
+
+ /* Register backlight stuff */
+
+ fujitsu->bl_device =
+ backlight_device_register("fujitsu-laptop", NULL, NULL,
+ &fujitsubl_ops);
+ if (IS_ERR(fujitsu->bl_device))
+ return PTR_ERR(fujitsu->bl_device);
+
+ fujitsu->bl_device->props.max_brightness = FUJITSU_LCD_N_LEVELS - 1;
+ ret = platform_driver_register(&fujitsupf_driver);
+ if (ret)
+ goto fail_backlight;
+
+ /* Register platform stuff */
+
+ fujitsu->pf_device = platform_device_alloc("fujitsu-laptop", -1);
+ if (!fujitsu->pf_device) {
+ ret = -ENOMEM;
+ goto fail_platform_driver;
+ }
+
+ ret = platform_device_add(fujitsu->pf_device);
+ if (ret)
+ goto fail_platform_device1;
+
+ ret =
+ sysfs_create_group(&fujitsu->pf_device->dev.kobj,
+ &fujitsupf_attribute_group);
+ if (ret)
+ goto fail_platform_device2;
+
+ printk(KERN_INFO "fujitsu-laptop: driver " FUJITSU_DRIVER_VERSION
+ " successfully loaded.\n");
+
+ return 0;
+
+ fail_platform_device2:
+
+ platform_device_del(fujitsu->pf_device);
+
+ fail_platform_device1:
+
+ platform_device_put(fujitsu->pf_device);
+
+ fail_platform_driver:
+
+ platform_driver_unregister(&fujitsupf_driver);
+
+ fail_backlight:
+
+ backlight_device_unregister(fujitsu->bl_device);
+
+ fail_acpi:
+
+ kfree(fujitsu);
+
+ return ret;
+}
+
+static void __exit fujitsu_cleanup(void)
+{
+ sysfs_remove_group(&fujitsu->pf_device->dev.kobj,
+ &fujitsupf_attribute_group);
+ platform_device_unregister(fujitsu->pf_device);
+ platform_driver_unregister(&fujitsupf_driver);
+ backlight_device_unregister(fujitsu->bl_device);
+
+ acpi_bus_unregister_driver(&acpi_fujitsu_driver);
+
+ kfree(fujitsu);
+
+ printk(KERN_INFO "fujitsu-laptop: driver unloaded.\n");
+}
+
+module_init(fujitsu_init);
+module_exit(fujitsu_cleanup);
+
+MODULE_AUTHOR("Jonathan Woithe");
+MODULE_DESCRIPTION("Fujitsu laptop extras support");
+MODULE_VERSION(FUJITSU_DRIVER_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/ibmasm/remote.c b/drivers/misc/ibmasm/remote.c
index 0550ce075fc4..477bb43c899c 100644
--- a/drivers/misc/ibmasm/remote.c
+++ b/drivers/misc/ibmasm/remote.c
@@ -17,7 +17,7 @@
*
* Copyright (C) IBM Corporation, 2004
*
- * Authors: Max Asböck <amax@us.ibm.com>
+ * Authors: Max Asböck <amax@us.ibm.com>
* Vernon Mauery <vernux@us.ibm.com>
*
*/
@@ -226,9 +226,9 @@ int ibmasm_init_remote_input_dev(struct service_processor *sp)
mouse_dev->id.product = pdev->device;
mouse_dev->id.version = 1;
mouse_dev->dev.parent = sp->dev;
- mouse_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- mouse_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) |
- BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
+ mouse_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ mouse_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
+ BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);
set_bit(BTN_TOUCH, mouse_dev->keybit);
mouse_dev->name = "ibmasm RSA I remote mouse";
input_set_abs_params(mouse_dev, ABS_X, 0, MOUSE_X_MAX, 0, 0);
@@ -239,7 +239,7 @@ int ibmasm_init_remote_input_dev(struct service_processor *sp)
keybd_dev->id.product = pdev->device;
keybd_dev->id.version = 2;
keybd_dev->dev.parent = sp->dev;
- keybd_dev->evbit[0] = BIT(EV_KEY);
+ keybd_dev->evbit[0] = BIT_MASK(EV_KEY);
keybd_dev->name = "ibmasm RSA I remote keyboard";
for (i = 0; i < XLATE_SIZE; i++) {
diff --git a/drivers/misc/ioc4.c b/drivers/misc/ioc4.c
index 6a5a05d1f392..05172d2613d6 100644
--- a/drivers/misc/ioc4.c
+++ b/drivers/misc/ioc4.c
@@ -244,10 +244,11 @@ ioc4_variant(struct ioc4_driver_data *idd)
idd->idd_pdev->bus->number == pdev->bus->number &&
3 == PCI_SLOT(pdev->devfn))
found = 1;
- pci_dev_put(pdev);
} while (pdev && !found);
- if (NULL != pdev)
+ if (NULL != pdev) {
+ pci_dev_put(pdev);
return IOC4_VARIANT_IO9;
+ }
/* IO10: Look for a Vitesse VSC 7174 at the same bus and slot 3. */
pdev = NULL;
@@ -258,10 +259,11 @@ ioc4_variant(struct ioc4_driver_data *idd)
idd->idd_pdev->bus->number == pdev->bus->number &&
3 == PCI_SLOT(pdev->devfn))
found = 1;
- pci_dev_put(pdev);
} while (pdev && !found);
- if (NULL != pdev)
+ if (NULL != pdev) {
+ pci_dev_put(pdev);
return IOC4_VARIANT_IO10;
+ }
/* PCI-RT: No SCSI/SATA controller will be present */
return IOC4_VARIANT_PCI_RT;
diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c
index 5108b7c576df..cd221fd0fb94 100644
--- a/drivers/misc/phantom.c
+++ b/drivers/misc/phantom.c
@@ -9,6 +9,7 @@
* You need an userspace library to cooperate with this driver. It (and other
* info) may be obtained here:
* http://www.fi.muni.cz/~xslaby/phantom.html
+ * or alternatively, you might use OpenHaptics provided by Sensable.
*/
#include <linux/kernel.h>
@@ -24,13 +25,14 @@
#include <asm/atomic.h>
#include <asm/io.h>
-#define PHANTOM_VERSION "n0.9.5"
+#define PHANTOM_VERSION "n0.9.7"
#define PHANTOM_MAX_MINORS 8
#define PHN_IRQCTL 0x4c /* irq control in caddr space */
#define PHB_RUNNING 1
+#define PHB_NOT_OH 2
static struct class *phantom_class;
static int phantom_major;
@@ -47,7 +49,11 @@ struct phantom_device {
struct cdev cdev;
struct mutex open_lock;
- spinlock_t ioctl_lock;
+ spinlock_t regs_lock;
+
+ /* used in NOT_OH mode */
+ struct phm_regs oregs;
+ u32 ctl_reg;
};
static unsigned char phantom_devices[PHANTOM_MAX_MINORS];
@@ -82,6 +88,7 @@ static long phantom_ioctl(struct file *file, unsigned int cmd,
struct phm_regs rs;
struct phm_reg r;
void __user *argp = (void __user *)arg;
+ unsigned long flags;
unsigned int i;
if (_IOC_TYPE(cmd) != PH_IOC_MAGIC ||
@@ -96,32 +103,45 @@ static long phantom_ioctl(struct file *file, unsigned int cmd,
if (r.reg > 7)
return -EINVAL;
- spin_lock(&dev->ioctl_lock);
+ spin_lock_irqsave(&dev->regs_lock, flags);
if (r.reg == PHN_CONTROL && (r.value & PHN_CTL_IRQ) &&
phantom_status(dev, dev->status | PHB_RUNNING)){
- spin_unlock(&dev->ioctl_lock);
+ spin_unlock_irqrestore(&dev->regs_lock, flags);
return -ENODEV;
}
pr_debug("phantom: writing %x to %u\n", r.value, r.reg);
+
+ /* preserve amp bit (don't allow to change it when in NOT_OH) */
+ if (r.reg == PHN_CONTROL && (dev->status & PHB_NOT_OH)) {
+ r.value &= ~PHN_CTL_AMP;
+ r.value |= dev->ctl_reg & PHN_CTL_AMP;
+ dev->ctl_reg = r.value;
+ }
+
iowrite32(r.value, dev->iaddr + r.reg);
ioread32(dev->iaddr); /* PCI posting */
if (r.reg == PHN_CONTROL && !(r.value & PHN_CTL_IRQ))
phantom_status(dev, dev->status & ~PHB_RUNNING);
- spin_unlock(&dev->ioctl_lock);
+ spin_unlock_irqrestore(&dev->regs_lock, flags);
break;
case PHN_SET_REGS:
if (copy_from_user(&rs, argp, sizeof(rs)))
return -EFAULT;
pr_debug("phantom: SRS %u regs %x\n", rs.count, rs.mask);
- spin_lock(&dev->ioctl_lock);
- for (i = 0; i < min(rs.count, 8U); i++)
- if ((1 << i) & rs.mask)
- iowrite32(rs.values[i], dev->oaddr + i);
- ioread32(dev->iaddr); /* PCI posting */
- spin_unlock(&dev->ioctl_lock);
+ spin_lock_irqsave(&dev->regs_lock, flags);
+ if (dev->status & PHB_NOT_OH)
+ memcpy(&dev->oregs, &rs, sizeof(rs));
+ else {
+ u32 m = min(rs.count, 8U);
+ for (i = 0; i < m; i++)
+ if (rs.mask & BIT(i))
+ iowrite32(rs.values[i], dev->oaddr + i);
+ ioread32(dev->iaddr); /* PCI posting */
+ }
+ spin_unlock_irqrestore(&dev->regs_lock, flags);
break;
case PHN_GET_REG:
if (copy_from_user(&r, argp, sizeof(r)))
@@ -135,20 +155,35 @@ static long phantom_ioctl(struct file *file, unsigned int cmd,
if (copy_to_user(argp, &r, sizeof(r)))
return -EFAULT;
break;
- case PHN_GET_REGS:
+ case PHN_GET_REGS: {
+ u32 m;
+
if (copy_from_user(&rs, argp, sizeof(rs)))
return -EFAULT;
+ m = min(rs.count, 8U);
+
pr_debug("phantom: GRS %u regs %x\n", rs.count, rs.mask);
- spin_lock(&dev->ioctl_lock);
- for (i = 0; i < min(rs.count, 8U); i++)
- if ((1 << i) & rs.mask)
+ spin_lock_irqsave(&dev->regs_lock, flags);
+ for (i = 0; i < m; i++)
+ if (rs.mask & BIT(i))
rs.values[i] = ioread32(dev->iaddr + i);
- spin_unlock(&dev->ioctl_lock);
+ spin_unlock_irqrestore(&dev->regs_lock, flags);
if (copy_to_user(argp, &rs, sizeof(rs)))
return -EFAULT;
break;
+ } case PHN_NOT_OH:
+ spin_lock_irqsave(&dev->regs_lock, flags);
+ if (dev->status & PHB_RUNNING) {
+ printk(KERN_ERR "phantom: you need to set NOT_OH "
+ "before you start the device!\n");
+ spin_unlock_irqrestore(&dev->regs_lock, flags);
+ return -EINVAL;
+ }
+ dev->status |= PHB_NOT_OH;
+ spin_unlock_irqrestore(&dev->regs_lock, flags);
+ break;
default:
return -ENOTTY;
}
@@ -171,8 +206,11 @@ static int phantom_open(struct inode *inode, struct file *file)
return -EINVAL;
}
+ WARN_ON(dev->status & PHB_NOT_OH);
+
file->private_data = dev;
+ atomic_set(&dev->counter, 0);
dev->opened++;
mutex_unlock(&dev->open_lock);
@@ -187,6 +225,7 @@ static int phantom_release(struct inode *inode, struct file *file)
dev->opened = 0;
phantom_status(dev, dev->status & ~PHB_RUNNING);
+ dev->status &= ~PHB_NOT_OH;
mutex_unlock(&dev->open_lock);
@@ -220,12 +259,32 @@ static struct file_operations phantom_file_ops = {
static irqreturn_t phantom_isr(int irq, void *data)
{
struct phantom_device *dev = data;
+ unsigned int i;
+ u32 ctl;
- if (!(ioread32(dev->iaddr + PHN_CONTROL) & PHN_CTL_IRQ))
+ spin_lock(&dev->regs_lock);
+ ctl = ioread32(dev->iaddr + PHN_CONTROL);
+ if (!(ctl & PHN_CTL_IRQ)) {
+ spin_unlock(&dev->regs_lock);
return IRQ_NONE;
+ }
iowrite32(0, dev->iaddr);
iowrite32(0xc0, dev->iaddr);
+
+ if (dev->status & PHB_NOT_OH) {
+ struct phm_regs *r = &dev->oregs;
+ u32 m = min(r->count, 8U);
+
+ for (i = 0; i < m; i++)
+ if (r->mask & BIT(i))
+ iowrite32(r->values[i], dev->oaddr + i);
+
+ dev->ctl_reg ^= PHN_CTL_AMP;
+ iowrite32(dev->ctl_reg, dev->iaddr + PHN_CONTROL);
+ }
+ spin_unlock(&dev->regs_lock);
+
ioread32(dev->iaddr); /* PCI posting */
atomic_inc(&dev->counter);
@@ -297,7 +356,7 @@ static int __devinit phantom_probe(struct pci_dev *pdev,
}
mutex_init(&pht->open_lock);
- spin_lock_init(&pht->ioctl_lock);
+ spin_lock_init(&pht->regs_lock);
init_waitqueue_head(&pht->wait);
cdev_init(&pht->cdev, &phantom_file_ops);
pht->cdev.owner = THIS_MODULE;
@@ -378,6 +437,8 @@ static int phantom_suspend(struct pci_dev *pdev, pm_message_t state)
iowrite32(0, dev->caddr + PHN_IRQCTL);
ioread32(dev->caddr + PHN_IRQCTL); /* PCI posting */
+ synchronize_irq(pdev->irq);
+
return 0;
}
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c
index e73a71f04bb4..bb13858f60a1 100644
--- a/drivers/misc/sony-laptop.c
+++ b/drivers/misc/sony-laptop.c
@@ -14,7 +14,7 @@
*
* Copyright (C) 2005 Narayanan R S <nars@kadamba.org>
*
- * Copyright (C) 2001-2002 Alcôve <www.alcove.com>
+ * Copyright (C) 2001-2002 Alcôve <www.alcove.com>
*
* Copyright (C) 2001 Michael Ashley <m.ashley@unsw.edu.au>
*
@@ -277,7 +277,7 @@ static void do_sony_laptop_release_key(struct work_struct *work)
static DECLARE_WORK(sony_laptop_release_key_work,
do_sony_laptop_release_key);
-/* forward event to the input subsytem */
+/* forward event to the input subsystem */
static void sony_laptop_report_input_event(u8 event)
{
struct input_dev *jog_dev = sony_laptop_input.jog_dev;
@@ -411,9 +411,9 @@ static int sony_laptop_setup_input(void)
jog_dev->id.bustype = BUS_ISA;
jog_dev->id.vendor = PCI_VENDOR_ID_SONY;
- jog_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- jog_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_MIDDLE);
- jog_dev->relbit[0] = BIT(REL_WHEEL);
+ jog_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+ jog_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_MIDDLE);
+ jog_dev->relbit[0] = BIT_MASK(REL_WHEEL);
error = input_register_device(jog_dev);
if (error)
@@ -1173,7 +1173,8 @@ static struct acpi_driver sony_nc_driver = {
#define SONYPI_TYPE3_OFFSET 0x12
struct sony_pic_ioport {
- struct acpi_resource_io io;
+ struct acpi_resource_io io1;
+ struct acpi_resource_io io2;
struct list_head list;
};
@@ -1443,11 +1444,11 @@ static u8 sony_pic_call1(u8 dev)
{
u8 v1, v2;
- wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2,
+ wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
ITERATIONS_LONG);
- outb(dev, spic_dev.cur_ioport->io.minimum + 4);
- v1 = inb_p(spic_dev.cur_ioport->io.minimum + 4);
- v2 = inb_p(spic_dev.cur_ioport->io.minimum);
+ outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
+ v1 = inb_p(spic_dev.cur_ioport->io1.minimum + 4);
+ v2 = inb_p(spic_dev.cur_ioport->io1.minimum);
dprintk("sony_pic_call1: 0x%.4x\n", (v2 << 8) | v1);
return v2;
}
@@ -1456,13 +1457,13 @@ static u8 sony_pic_call2(u8 dev, u8 fn)
{
u8 v1;
- wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2,
+ wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
ITERATIONS_LONG);
- outb(dev, spic_dev.cur_ioport->io.minimum + 4);
- wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2,
+ outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
+ wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
ITERATIONS_LONG);
- outb(fn, spic_dev.cur_ioport->io.minimum);
- v1 = inb_p(spic_dev.cur_ioport->io.minimum);
+ outb(fn, spic_dev.cur_ioport->io1.minimum);
+ v1 = inb_p(spic_dev.cur_ioport->io1.minimum);
dprintk("sony_pic_call2: 0x%.4x\n", v1);
return v1;
}
@@ -1471,13 +1472,13 @@ static u8 sony_pic_call3(u8 dev, u8 fn, u8 v)
{
u8 v1;
- wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2, ITERATIONS_LONG);
- outb(dev, spic_dev.cur_ioport->io.minimum + 4);
- wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2, ITERATIONS_LONG);
- outb(fn, spic_dev.cur_ioport->io.minimum);
- wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2, ITERATIONS_LONG);
- outb(v, spic_dev.cur_ioport->io.minimum);
- v1 = inb_p(spic_dev.cur_ioport->io.minimum);
+ wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
+ outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
+ wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
+ outb(fn, spic_dev.cur_ioport->io1.minimum);
+ wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
+ outb(v, spic_dev.cur_ioport->io1.minimum);
+ v1 = inb_p(spic_dev.cur_ioport->io1.minimum);
dprintk("sony_pic_call3: 0x%.4x\n", v1);
return v1;
}
@@ -2074,7 +2075,18 @@ sony_pic_read_possible_resource(struct acpi_resource *resource, void *context)
switch (resource->type) {
case ACPI_RESOURCE_TYPE_START_DEPENDENT:
+ {
+ /* start IO enumeration */
+ struct sony_pic_ioport *ioport = kzalloc(sizeof(*ioport), GFP_KERNEL);
+ if (!ioport)
+ return AE_ERROR;
+
+ list_add(&ioport->list, &dev->ioports);
+ return AE_OK;
+ }
+
case ACPI_RESOURCE_TYPE_END_DEPENDENT:
+ /* end IO enumeration */
return AE_OK;
case ACPI_RESOURCE_TYPE_IRQ:
@@ -2101,7 +2113,7 @@ sony_pic_read_possible_resource(struct acpi_resource *resource, void *context)
if (!interrupt)
return AE_ERROR;
- list_add_tail(&interrupt->list, &dev->interrupts);
+ list_add(&interrupt->list, &dev->interrupts);
interrupt->irq.triggering = p->triggering;
interrupt->irq.polarity = p->polarity;
interrupt->irq.sharable = p->sharable;
@@ -2113,18 +2125,27 @@ sony_pic_read_possible_resource(struct acpi_resource *resource, void *context)
case ACPI_RESOURCE_TYPE_IO:
{
struct acpi_resource_io *io = &resource->data.io;
- struct sony_pic_ioport *ioport = NULL;
+ struct sony_pic_ioport *ioport =
+ list_first_entry(&dev->ioports, struct sony_pic_ioport, list);
if (!io) {
dprintk("Blank IO resource\n");
return AE_OK;
}
- ioport = kzalloc(sizeof(*ioport), GFP_KERNEL);
- if (!ioport)
+ if (!ioport->io1.minimum) {
+ memcpy(&ioport->io1, io, sizeof(*io));
+ dprintk("IO1 at 0x%.4x (0x%.2x)\n", ioport->io1.minimum,
+ ioport->io1.address_length);
+ }
+ else if (!ioport->io2.minimum) {
+ memcpy(&ioport->io2, io, sizeof(*io));
+ dprintk("IO2 at 0x%.4x (0x%.2x)\n", ioport->io2.minimum,
+ ioport->io2.address_length);
+ }
+ else {
+ printk(KERN_ERR DRV_PFX "Unknown SPIC Type, more than 2 IO Ports\n");
return AE_ERROR;
-
- list_add_tail(&ioport->list, &dev->ioports);
- memcpy(&ioport->io, io, sizeof(*io));
+ }
return AE_OK;
}
default:
@@ -2199,10 +2220,22 @@ static int sony_pic_enable(struct acpi_device *device,
{
acpi_status status;
int result = 0;
+ /* Type 1 resource layout is:
+ * IO
+ * IO
+ * IRQNoFlags
+ * End
+ *
+ * Type 2 and 3 resource layout is:
+ * IO
+ * IRQNoFlags
+ * End
+ */
struct {
- struct acpi_resource io_res;
- struct acpi_resource irq_res;
- struct acpi_resource end;
+ struct acpi_resource res1;
+ struct acpi_resource res2;
+ struct acpi_resource res3;
+ struct acpi_resource res4;
} *resource;
struct acpi_buffer buffer = { 0, NULL };
@@ -2217,21 +2250,49 @@ static int sony_pic_enable(struct acpi_device *device,
buffer.length = sizeof(*resource) + 1;
buffer.pointer = resource;
- /* setup io resource */
- resource->io_res.type = ACPI_RESOURCE_TYPE_IO;
- resource->io_res.length = sizeof(struct acpi_resource);
- memcpy(&resource->io_res.data.io, &ioport->io,
- sizeof(struct acpi_resource_io));
+ /* setup Type 1 resources */
+ if (spic_dev.model == SONYPI_DEVICE_TYPE1) {
- /* setup irq resource */
- resource->irq_res.type = ACPI_RESOURCE_TYPE_IRQ;
- resource->irq_res.length = sizeof(struct acpi_resource);
- memcpy(&resource->irq_res.data.irq, &irq->irq,
- sizeof(struct acpi_resource_irq));
- /* we requested a shared irq */
- resource->irq_res.data.irq.sharable = ACPI_SHARED;
+ /* setup io resources */
+ resource->res1.type = ACPI_RESOURCE_TYPE_IO;
+ resource->res1.length = sizeof(struct acpi_resource);
+ memcpy(&resource->res1.data.io, &ioport->io1,
+ sizeof(struct acpi_resource_io));
- resource->end.type = ACPI_RESOURCE_TYPE_END_TAG;
+ resource->res2.type = ACPI_RESOURCE_TYPE_IO;
+ resource->res2.length = sizeof(struct acpi_resource);
+ memcpy(&resource->res2.data.io, &ioport->io2,
+ sizeof(struct acpi_resource_io));
+
+ /* setup irq resource */
+ resource->res3.type = ACPI_RESOURCE_TYPE_IRQ;
+ resource->res3.length = sizeof(struct acpi_resource);
+ memcpy(&resource->res3.data.irq, &irq->irq,
+ sizeof(struct acpi_resource_irq));
+ /* we requested a shared irq */
+ resource->res3.data.irq.sharable = ACPI_SHARED;
+
+ resource->res4.type = ACPI_RESOURCE_TYPE_END_TAG;
+
+ }
+ /* setup Type 2/3 resources */
+ else {
+ /* setup io resource */
+ resource->res1.type = ACPI_RESOURCE_TYPE_IO;
+ resource->res1.length = sizeof(struct acpi_resource);
+ memcpy(&resource->res1.data.io, &ioport->io1,
+ sizeof(struct acpi_resource_io));
+
+ /* setup irq resource */
+ resource->res2.type = ACPI_RESOURCE_TYPE_IRQ;
+ resource->res2.length = sizeof(struct acpi_resource);
+ memcpy(&resource->res2.data.irq, &irq->irq,
+ sizeof(struct acpi_resource_irq));
+ /* we requested a shared irq */
+ resource->res2.data.irq.sharable = ACPI_SHARED;
+
+ resource->res3.type = ACPI_RESOURCE_TYPE_END_TAG;
+ }
/* Attempt to set the resource */
dprintk("Evaluating _SRS\n");
@@ -2239,7 +2300,7 @@ static int sony_pic_enable(struct acpi_device *device,
/* check for total failure */
if (ACPI_FAILURE(status)) {
- printk(KERN_ERR DRV_PFX "Error evaluating _SRS");
+ printk(KERN_ERR DRV_PFX "Error evaluating _SRS\n");
result = -ENODEV;
goto end;
}
@@ -2268,11 +2329,14 @@ static irqreturn_t sony_pic_irq(int irq, void *dev_id)
struct sony_pic_dev *dev = (struct sony_pic_dev *) dev_id;
- ev = inb_p(dev->cur_ioport->io.minimum);
- data_mask = inb_p(dev->cur_ioport->io.minimum + dev->evport_offset);
+ ev = inb_p(dev->cur_ioport->io1.minimum);
+ if (dev->cur_ioport->io2.minimum)
+ data_mask = inb_p(dev->cur_ioport->io2.minimum);
+ else
+ data_mask = inb_p(dev->cur_ioport->io1.minimum + dev->evport_offset);
dprintk("event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n",
- ev, data_mask, dev->cur_ioport->io.minimum, dev->evport_offset);
+ ev, data_mask, dev->cur_ioport->io1.minimum, dev->evport_offset);
if (ev == 0x00 || ev == 0xff)
return IRQ_HANDLED;
@@ -2323,8 +2387,11 @@ static int sony_pic_remove(struct acpi_device *device, int type)
}
free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev);
- release_region(spic_dev.cur_ioport->io.minimum,
- spic_dev.cur_ioport->io.address_length);
+ release_region(spic_dev.cur_ioport->io1.minimum,
+ spic_dev.cur_ioport->io1.address_length);
+ if (spic_dev.cur_ioport->io2.minimum)
+ release_region(spic_dev.cur_ioport->io2.minimum,
+ spic_dev.cur_ioport->io2.address_length);
sonypi_compat_exit();
@@ -2397,14 +2464,36 @@ static int sony_pic_add(struct acpi_device *device)
goto err_remove_input;
/* request io port */
- list_for_each_entry(io, &spic_dev.ioports, list) {
- if (request_region(io->io.minimum, io->io.address_length,
+ list_for_each_entry_reverse(io, &spic_dev.ioports, list) {
+ if (request_region(io->io1.minimum, io->io1.address_length,
"Sony Programable I/O Device")) {
- dprintk("I/O port: 0x%.4x (0x%.4x) + 0x%.2x\n",
- io->io.minimum, io->io.maximum,
- io->io.address_length);
- spic_dev.cur_ioport = io;
- break;
+ dprintk("I/O port1: 0x%.4x (0x%.4x) + 0x%.2x\n",
+ io->io1.minimum, io->io1.maximum,
+ io->io1.address_length);
+ /* Type 1 have 2 ioports */
+ if (io->io2.minimum) {
+ if (request_region(io->io2.minimum,
+ io->io2.address_length,
+ "Sony Programable I/O Device")) {
+ dprintk("I/O port2: 0x%.4x (0x%.4x) + 0x%.2x\n",
+ io->io2.minimum, io->io2.maximum,
+ io->io2.address_length);
+ spic_dev.cur_ioport = io;
+ break;
+ }
+ else {
+ dprintk("Unable to get I/O port2: "
+ "0x%.4x (0x%.4x) + 0x%.2x\n",
+ io->io2.minimum, io->io2.maximum,
+ io->io2.address_length);
+ release_region(io->io1.minimum,
+ io->io1.address_length);
+ }
+ }
+ else {
+ spic_dev.cur_ioport = io;
+ break;
+ }
}
}
if (!spic_dev.cur_ioport) {
@@ -2414,7 +2503,7 @@ static int sony_pic_add(struct acpi_device *device)
}
/* request IRQ */
- list_for_each_entry(irq, &spic_dev.interrupts, list) {
+ list_for_each_entry_reverse(irq, &spic_dev.interrupts, list) {
if (!request_irq(irq->irq.interrupts[0], sony_pic_irq,
IRQF_SHARED, "sony-laptop", &spic_dev)) {
dprintk("IRQ: %d - triggering: %d - "
@@ -2462,8 +2551,11 @@ err_free_irq:
free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev);
err_release_region:
- release_region(spic_dev.cur_ioport->io.minimum,
- spic_dev.cur_ioport->io.address_length);
+ release_region(spic_dev.cur_ioport->io1.minimum,
+ spic_dev.cur_ioport->io1.address_length);
+ if (spic_dev.cur_ioport->io2.minimum)
+ release_region(spic_dev.cur_ioport->io2.minimum,
+ spic_dev.cur_ioport->io2.address_length);
err_remove_compat:
sonypi_compat_exit();
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
index 216948dd71a5..e953276664a0 100644
--- a/drivers/misc/thinkpad_acpi.c
+++ b/drivers/misc/thinkpad_acpi.c
@@ -22,7 +22,7 @@
*/
#define IBM_VERSION "0.16"
-#define TPACPI_SYSFS_VERSION 0x010000
+#define TPACPI_SYSFS_VERSION 0x020000
/*
* Changelog:
@@ -117,6 +117,12 @@ IBM_BIOS_MODULE_ALIAS("K[U,X-Z]");
#define __unused __attribute__ ((unused))
+static enum {
+ TPACPI_LIFE_INIT = 0,
+ TPACPI_LIFE_RUNNING,
+ TPACPI_LIFE_EXITING,
+} tpacpi_lifecycle;
+
/****************************************************************************
****************************************************************************
*
@@ -342,6 +348,9 @@ static void dispatch_acpi_notify(acpi_handle handle, u32 event, void *data)
{
struct ibm_struct *ibm = data;
+ if (tpacpi_lifecycle != TPACPI_LIFE_RUNNING)
+ return;
+
if (!ibm || !ibm->acpi || !ibm->acpi->notify)
return;
@@ -517,8 +526,10 @@ static char *next_cmd(char **cmds)
****************************************************************************/
static struct platform_device *tpacpi_pdev;
+static struct platform_device *tpacpi_sensors_pdev;
static struct device *tpacpi_hwmon;
static struct input_dev *tpacpi_inputdev;
+static struct mutex tpacpi_inputdev_send_mutex;
static int tpacpi_resume_handler(struct platform_device *pdev)
@@ -543,6 +554,12 @@ static struct platform_driver tpacpi_pdriver = {
.resume = tpacpi_resume_handler,
};
+static struct platform_driver tpacpi_hwmon_pdriver = {
+ .driver = {
+ .name = IBM_HWMON_DRVR_NAME,
+ .owner = THIS_MODULE,
+ },
+};
/*************************************************************************
* thinkpad-acpi driver attributes
@@ -692,6 +709,8 @@ static int parse_strtoul(const char *buf,
{
char *endp;
+ while (*buf && isspace(*buf))
+ buf++;
*value = simple_strtoul(buf, &endp, 0);
while (*endp && isspace(*endp))
endp++;
@@ -945,15 +964,15 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
KEY_UNKNOWN, /* 0x0C: FN+BACKSPACE */
KEY_UNKNOWN, /* 0x0D: FN+INSERT */
KEY_UNKNOWN, /* 0x0E: FN+DELETE */
- KEY_RESERVED, /* 0x0F: FN+HOME (brightness up) */
+ KEY_BRIGHTNESSUP, /* 0x0F: FN+HOME (brightness up) */
/* Scan codes 0x10 to 0x1F: Extended ACPI HKEY hot keys */
- KEY_RESERVED, /* 0x10: FN+END (brightness down) */
+ KEY_BRIGHTNESSDOWN, /* 0x10: FN+END (brightness down) */
KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */
KEY_UNKNOWN, /* 0x12: FN+PGDOWN */
KEY_ZOOM, /* 0x13: FN+SPACE (zoom) */
- KEY_RESERVED, /* 0x14: VOLUME UP */
- KEY_RESERVED, /* 0x15: VOLUME DOWN */
- KEY_RESERVED, /* 0x16: MUTE */
+ KEY_VOLUMEUP, /* 0x14: VOLUME UP */
+ KEY_VOLUMEDOWN, /* 0x15: VOLUME DOWN */
+ KEY_MUTE, /* 0x16: MUTE */
KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */
/* (assignments unknown, please report if found) */
KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
@@ -974,9 +993,9 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */
KEY_UNKNOWN, /* 0x12: FN+PGDOWN */
KEY_ZOOM, /* 0x13: FN+SPACE (zoom) */
- KEY_RESERVED, /* 0x14: VOLUME UP */
- KEY_RESERVED, /* 0x15: VOLUME DOWN */
- KEY_RESERVED, /* 0x16: MUTE */
+ KEY_VOLUMEUP, /* 0x14: VOLUME UP */
+ KEY_VOLUMEDOWN, /* 0x15: VOLUME DOWN */
+ KEY_MUTE, /* 0x16: MUTE */
KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */
/* (assignments unknown, please report if found) */
KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
@@ -989,6 +1008,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
int res, i;
int status;
+ int hkeyv;
vdbg_printk(TPACPI_DBG_INIT, "initializing hotkey subdriver\n");
@@ -1014,18 +1034,35 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
return res;
/* mask not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
- A30, R30, R31, T20-22, X20-21, X22-24 */
- tp_features.hotkey_mask =
- acpi_evalf(hkey_handle, NULL, "DHKN", "qv");
+ A30, R30, R31, T20-22, X20-21, X22-24. Detected by checking
+ for HKEY interface version 0x100 */
+ if (acpi_evalf(hkey_handle, &hkeyv, "MHKV", "qd")) {
+ if ((hkeyv >> 8) != 1) {
+ printk(IBM_ERR "unknown version of the "
+ "HKEY interface: 0x%x\n", hkeyv);
+ printk(IBM_ERR "please report this to %s\n",
+ IBM_MAIL);
+ } else {
+ /*
+ * MHKV 0x100 in A31, R40, R40e,
+ * T4x, X31, and later
+ * */
+ tp_features.hotkey_mask = 1;
+ }
+ }
vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n",
str_supported(tp_features.hotkey_mask));
if (tp_features.hotkey_mask) {
- /* MHKA available in A31, R40, R40e, T4x, X31, and later */
if (!acpi_evalf(hkey_handle, &hotkey_all_mask,
- "MHKA", "qd"))
+ "MHKA", "qd")) {
+ printk(IBM_ERR
+ "missing MHKA handler, "
+ "please report this to %s\n",
+ IBM_MAIL);
hotkey_all_mask = 0x080cU; /* FN+F12, FN+F4, FN+F3 */
+ }
}
res = hotkey_get(&hotkey_orig_status, &hotkey_orig_mask);
@@ -1131,6 +1168,8 @@ static void tpacpi_input_send_key(unsigned int scancode,
unsigned int keycode)
{
if (keycode != KEY_RESERVED) {
+ mutex_lock(&tpacpi_inputdev_send_mutex);
+
input_report_key(tpacpi_inputdev, keycode, 1);
if (keycode == KEY_UNKNOWN)
input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN,
@@ -1142,6 +1181,8 @@ static void tpacpi_input_send_key(unsigned int scancode,
input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN,
scancode);
input_sync(tpacpi_inputdev);
+
+ mutex_unlock(&tpacpi_inputdev_send_mutex);
}
}
@@ -1149,18 +1190,47 @@ static void tpacpi_input_send_radiosw(void)
{
int wlsw;
- if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&wlsw))
+ mutex_lock(&tpacpi_inputdev_send_mutex);
+
+ if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&wlsw)) {
input_report_switch(tpacpi_inputdev,
SW_RADIO, !!wlsw);
+ input_sync(tpacpi_inputdev);
+ }
+
+ mutex_unlock(&tpacpi_inputdev_send_mutex);
}
static void hotkey_notify(struct ibm_struct *ibm, u32 event)
{
u32 hkey;
unsigned int keycode, scancode;
- int send_acpi_ev = 0;
+ int send_acpi_ev;
+ int ignore_acpi_ev;
+
+ if (event != 0x80) {
+ printk(IBM_ERR "unknown HKEY notification event %d\n", event);
+ /* forward it to userspace, maybe it knows how to handle it */
+ acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class,
+ ibm->acpi->device->dev.bus_id,
+ event, 0);
+ return;
+ }
+
+ while (1) {
+ if (!acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) {
+ printk(IBM_ERR "failed to retrieve HKEY event\n");
+ return;
+ }
+
+ if (hkey == 0) {
+ /* queue empty */
+ return;
+ }
+
+ send_acpi_ev = 0;
+ ignore_acpi_ev = 0;
- if (event == 0x80 && acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) {
switch (hkey >> 12) {
case 1:
/* 0x1000-0x1FFF: key presses */
@@ -1182,9 +1252,11 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
* eat up known LID events */
if (hkey != 0x5001 && hkey != 0x5002) {
printk(IBM_ERR
- "unknown LID-related hotkey event: 0x%04x\n",
- hkey);
+ "unknown LID-related HKEY event: 0x%04x\n",
+ hkey);
send_acpi_ev = 1;
+ } else {
+ ignore_acpi_ev = 1;
}
break;
case 7:
@@ -1202,21 +1274,18 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
printk(IBM_NOTICE "unhandled HKEY event 0x%04x\n", hkey);
send_acpi_ev = 1;
}
- } else {
- printk(IBM_ERR "unknown hotkey notification event %d\n", event);
- hkey = 0;
- send_acpi_ev = 1;
- }
- /* Legacy events */
- if (send_acpi_ev || hotkey_report_mode < 2)
- acpi_bus_generate_proc_event(ibm->acpi->device, event, hkey);
+ /* Legacy events */
+ if (!ignore_acpi_ev && (send_acpi_ev || hotkey_report_mode < 2)) {
+ acpi_bus_generate_proc_event(ibm->acpi->device, event, hkey);
+ }
- /* netlink events */
- if (send_acpi_ev) {
- acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class,
- ibm->acpi->device->dev.bus_id,
- event, hkey);
+ /* netlink events */
+ if (!ignore_acpi_ev && send_acpi_ev) {
+ acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class,
+ ibm->acpi->device->dev.bus_id,
+ event, hkey);
+ }
}
}
@@ -2812,7 +2881,7 @@ static int __init thermal_init(struct ibm_init_struct *iibm)
switch(thermal_read_mode) {
case TPACPI_THERMAL_TPEC_16:
- res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
+ res = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj,
&thermal_temp_input16_group);
if (res)
return res;
@@ -2820,7 +2889,7 @@ static int __init thermal_init(struct ibm_init_struct *iibm)
case TPACPI_THERMAL_TPEC_8:
case TPACPI_THERMAL_ACPI_TMP07:
case TPACPI_THERMAL_ACPI_UPDT:
- res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
+ res = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj,
&thermal_temp_input8_group);
if (res)
return res;
@@ -2837,13 +2906,13 @@ static void thermal_exit(void)
{
switch(thermal_read_mode) {
case TPACPI_THERMAL_TPEC_16:
- sysfs_remove_group(&tpacpi_pdev->dev.kobj,
+ sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj,
&thermal_temp_input16_group);
break;
case TPACPI_THERMAL_TPEC_8:
case TPACPI_THERMAL_ACPI_TMP07:
case TPACPI_THERMAL_ACPI_UPDT:
- sysfs_remove_group(&tpacpi_pdev->dev.kobj,
+ sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj,
&thermal_temp_input16_group);
break;
case TPACPI_THERMAL_NONE:
@@ -3626,7 +3695,7 @@ static struct device_attribute dev_attr_fan_fan1_input =
__ATTR(fan1_input, S_IRUGO,
fan_fan1_input_show, NULL);
-/* sysfs fan fan_watchdog (driver) ------------------------------------- */
+/* sysfs fan fan_watchdog (hwmon driver) ------------------------------- */
static ssize_t fan_fan_watchdog_show(struct device_driver *drv,
char *buf)
{
@@ -3768,10 +3837,10 @@ static int __init fan_init(struct ibm_init_struct *iibm)
if (fan_status_access_mode != TPACPI_FAN_NONE ||
fan_control_access_mode != TPACPI_FAN_WR_NONE) {
- rc = sysfs_create_group(&tpacpi_pdev->dev.kobj,
+ rc = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj,
&fan_attr_group);
if (!(rc < 0))
- rc = driver_create_file(&tpacpi_pdriver.driver,
+ rc = driver_create_file(&tpacpi_hwmon_pdriver.driver,
&driver_attr_fan_watchdog);
if (rc < 0)
return rc;
@@ -3854,8 +3923,8 @@ static void fan_exit(void)
vdbg_printk(TPACPI_DBG_EXIT, "cancelling any pending fan watchdog tasks\n");
/* FIXME: can we really do this unconditionally? */
- sysfs_remove_group(&tpacpi_pdev->dev.kobj, &fan_attr_group);
- driver_remove_file(&tpacpi_pdriver.driver, &driver_attr_fan_watchdog);
+ sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj, &fan_attr_group);
+ driver_remove_file(&tpacpi_hwmon_pdriver.driver, &driver_attr_fan_watchdog);
cancel_delayed_work(&fan_watchdog_task);
flush_scheduled_work();
@@ -3888,6 +3957,9 @@ static void fan_watchdog_fire(struct work_struct *ignored)
{
int rc;
+ if (tpacpi_lifecycle != TPACPI_LIFE_RUNNING)
+ return;
+
printk(IBM_NOTICE "fan watchdog: enabling fan\n");
rc = fan_set_enable();
if (rc < 0) {
@@ -3908,7 +3980,8 @@ static void fan_watchdog_reset(void)
if (fan_watchdog_active)
cancel_delayed_work(&fan_watchdog_task);
- if (fan_watchdog_maxinterval > 0) {
+ if (fan_watchdog_maxinterval > 0 &&
+ tpacpi_lifecycle != TPACPI_LIFE_EXITING) {
fan_watchdog_active = 1;
if (!schedule_delayed_work(&fan_watchdog_task,
msecs_to_jiffies(fan_watchdog_maxinterval
@@ -4302,6 +4375,19 @@ static struct ibm_struct fan_driver_data = {
****************************************************************************
****************************************************************************/
+/* sysfs name ---------------------------------------------------------- */
+static ssize_t thinkpad_acpi_pdev_name_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", IBM_NAME);
+}
+
+static struct device_attribute dev_attr_thinkpad_acpi_pdev_name =
+ __ATTR(name, S_IRUGO, thinkpad_acpi_pdev_name_show, NULL);
+
+/* --------------------------------------------------------------------- */
+
/* /proc support */
static struct proc_dir_entry *proc_dir;
@@ -4674,6 +4760,8 @@ static int __init thinkpad_acpi_module_init(void)
{
int ret, i;
+ tpacpi_lifecycle = TPACPI_LIFE_INIT;
+
/* Parameter checking */
if (hotkey_report_mode > 2)
return -EINVAL;
@@ -4702,19 +4790,31 @@ static int __init thinkpad_acpi_module_init(void)
ret = platform_driver_register(&tpacpi_pdriver);
if (ret) {
- printk(IBM_ERR "unable to register platform driver\n");
+ printk(IBM_ERR "unable to register main platform driver\n");
thinkpad_acpi_module_exit();
return ret;
}
tp_features.platform_drv_registered = 1;
+ ret = platform_driver_register(&tpacpi_hwmon_pdriver);
+ if (ret) {
+ printk(IBM_ERR "unable to register hwmon platform driver\n");
+ thinkpad_acpi_module_exit();
+ return ret;
+ }
+ tp_features.sensors_pdrv_registered = 1;
+
ret = tpacpi_create_driver_attributes(&tpacpi_pdriver.driver);
+ if (!ret) {
+ tp_features.platform_drv_attrs_registered = 1;
+ ret = tpacpi_create_driver_attributes(&tpacpi_hwmon_pdriver.driver);
+ }
if (ret) {
printk(IBM_ERR "unable to create sysfs driver attributes\n");
thinkpad_acpi_module_exit();
return ret;
}
- tp_features.platform_drv_attrs_registered = 1;
+ tp_features.sensors_pdrv_attrs_registered = 1;
/* Device initialization */
@@ -4727,7 +4827,26 @@ static int __init thinkpad_acpi_module_init(void)
thinkpad_acpi_module_exit();
return ret;
}
- tpacpi_hwmon = hwmon_device_register(&tpacpi_pdev->dev);
+ tpacpi_sensors_pdev = platform_device_register_simple(
+ IBM_HWMON_DRVR_NAME,
+ -1, NULL, 0);
+ if (IS_ERR(tpacpi_sensors_pdev)) {
+ ret = PTR_ERR(tpacpi_sensors_pdev);
+ tpacpi_sensors_pdev = NULL;
+ printk(IBM_ERR "unable to register hwmon platform device\n");
+ thinkpad_acpi_module_exit();
+ return ret;
+ }
+ ret = device_create_file(&tpacpi_sensors_pdev->dev,
+ &dev_attr_thinkpad_acpi_pdev_name);
+ if (ret) {
+ printk(IBM_ERR
+ "unable to create sysfs hwmon device attributes\n");
+ thinkpad_acpi_module_exit();
+ return ret;
+ }
+ tp_features.sensors_pdev_attrs_registered = 1;
+ tpacpi_hwmon = hwmon_device_register(&tpacpi_sensors_pdev->dev);
if (IS_ERR(tpacpi_hwmon)) {
ret = PTR_ERR(tpacpi_hwmon);
tpacpi_hwmon = NULL;
@@ -4735,6 +4854,7 @@ static int __init thinkpad_acpi_module_init(void)
thinkpad_acpi_module_exit();
return ret;
}
+ mutex_init(&tpacpi_inputdev_send_mutex);
tpacpi_inputdev = input_allocate_device();
if (!tpacpi_inputdev) {
printk(IBM_ERR "unable to allocate input device\n");
@@ -4769,6 +4889,7 @@ static int __init thinkpad_acpi_module_init(void)
tp_features.input_device_registered = 1;
}
+ tpacpi_lifecycle = TPACPI_LIFE_RUNNING;
return 0;
}
@@ -4776,6 +4897,8 @@ static void thinkpad_acpi_module_exit(void)
{
struct ibm_struct *ibm, *itmp;
+ tpacpi_lifecycle = TPACPI_LIFE_EXITING;
+
list_for_each_entry_safe_reverse(ibm, itmp,
&tpacpi_all_drivers,
all_drivers) {
@@ -4794,12 +4917,22 @@ static void thinkpad_acpi_module_exit(void)
if (tpacpi_hwmon)
hwmon_device_unregister(tpacpi_hwmon);
+ if (tp_features.sensors_pdev_attrs_registered)
+ device_remove_file(&tpacpi_sensors_pdev->dev,
+ &dev_attr_thinkpad_acpi_pdev_name);
+ if (tpacpi_sensors_pdev)
+ platform_device_unregister(tpacpi_sensors_pdev);
if (tpacpi_pdev)
platform_device_unregister(tpacpi_pdev);
+ if (tp_features.sensors_pdrv_attrs_registered)
+ tpacpi_remove_driver_attributes(&tpacpi_hwmon_pdriver.driver);
if (tp_features.platform_drv_attrs_registered)
tpacpi_remove_driver_attributes(&tpacpi_pdriver.driver);
+ if (tp_features.sensors_pdrv_registered)
+ platform_driver_unregister(&tpacpi_hwmon_pdriver);
+
if (tp_features.platform_drv_registered)
platform_driver_unregister(&tpacpi_pdriver);
diff --git a/drivers/misc/thinkpad_acpi.h b/drivers/misc/thinkpad_acpi.h
index acd5835ec889..3abcc8120634 100644
--- a/drivers/misc/thinkpad_acpi.h
+++ b/drivers/misc/thinkpad_acpi.h
@@ -58,13 +58,14 @@
#define IBM_NAME "thinkpad"
#define IBM_DESC "ThinkPad ACPI Extras"
-#define IBM_FILE "thinkpad_acpi"
+#define IBM_FILE IBM_NAME "_acpi"
#define IBM_URL "http://ibm-acpi.sf.net/"
#define IBM_MAIL "ibm-acpi-devel@lists.sourceforge.net"
#define IBM_PROC_DIR "ibm"
#define IBM_ACPI_EVENT_PREFIX "ibm"
#define IBM_DRVR_NAME IBM_FILE
+#define IBM_HWMON_DRVR_NAME IBM_NAME "_hwmon"
#define IBM_LOG IBM_FILE ": "
#define IBM_ERR KERN_ERR IBM_LOG
@@ -171,6 +172,7 @@ static int parse_strtoul(const char *buf, unsigned long max,
/* Device model */
static struct platform_device *tpacpi_pdev;
+static struct platform_device *tpacpi_sensors_pdev;
static struct device *tpacpi_hwmon;
static struct platform_driver tpacpi_pdriver;
static struct input_dev *tpacpi_inputdev;
@@ -233,22 +235,25 @@ struct ibm_init_struct {
static struct {
#ifdef CONFIG_THINKPAD_ACPI_BAY
- u16 bay_status:1;
- u16 bay_eject:1;
- u16 bay_status2:1;
- u16 bay_eject2:1;
+ u32 bay_status:1;
+ u32 bay_eject:1;
+ u32 bay_status2:1;
+ u32 bay_eject2:1;
#endif
- u16 bluetooth:1;
- u16 hotkey:1;
- u16 hotkey_mask:1;
- u16 hotkey_wlsw:1;
- u16 light:1;
- u16 light_status:1;
- u16 wan:1;
- u16 fan_ctrl_status_undef:1;
- u16 input_device_registered:1;
- u16 platform_drv_registered:1;
- u16 platform_drv_attrs_registered:1;
+ u32 bluetooth:1;
+ u32 hotkey:1;
+ u32 hotkey_mask:1;
+ u32 hotkey_wlsw:1;
+ u32 light:1;
+ u32 light_status:1;
+ u32 wan:1;
+ u32 fan_ctrl_status_undef:1;
+ u32 input_device_registered:1;
+ u32 platform_drv_registered:1;
+ u32 platform_drv_attrs_registered:1;
+ u32 sensors_pdrv_registered:1;
+ u32 sensors_pdrv_attrs_registered:1;
+ u32 sensors_pdev_attrs_registered:1;
} tp_features;
struct thinkpad_id_data {
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index b0abc7d92805..1b9c9b6da5b7 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -13,6 +13,7 @@
#include <linux/blkdev.h>
#include <linux/freezer.h>
#include <linux/kthread.h>
+#include <linux/scatterlist.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
@@ -159,6 +160,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
ret = -ENOMEM;
goto cleanup_queue;
}
+ sg_init_table(mq->sg, 1);
mq->bounce_sg = kmalloc(sizeof(struct scatterlist) *
bouncesz / 512, GFP_KERNEL);
@@ -166,6 +168,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
ret = -ENOMEM;
goto cleanup_queue;
}
+ sg_init_table(mq->bounce_sg, bouncesz / 512);
}
}
#endif
@@ -177,7 +180,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
blk_queue_max_hw_segments(mq->queue, host->max_hw_segs);
blk_queue_max_segment_size(mq->queue, host->max_seg_size);
- mq->sg = kmalloc(sizeof(struct scatterlist) *
+ mq->sg = kzalloc(sizeof(struct scatterlist) *
host->max_phys_segs, GFP_KERNEL);
if (!mq->sg) {
ret = -ENOMEM;
@@ -302,12 +305,12 @@ static void copy_sg(struct scatterlist *dst, unsigned int dst_len,
BUG_ON(dst_len == 0);
if (dst_size == 0) {
- dst_buf = page_address(dst->page) + dst->offset;
+ dst_buf = sg_virt(dst);
dst_size = dst->length;
}
if (src_size == 0) {
- src_buf = page_address(src->page) + src->offset;
+ src_buf = sg_virt(src);
src_size = src->length;
}
@@ -353,9 +356,7 @@ unsigned int mmc_queue_map_sg(struct mmc_queue *mq)
return 1;
}
- mq->sg[0].page = virt_to_page(mq->bounce_buf);
- mq->sg[0].offset = offset_in_page(mq->bounce_buf);
- mq->sg[0].length = 0;
+ sg_init_one(mq->sg, mq->bounce_buf, 0);
while (sg_len) {
mq->sg[0].length += mq->bounce_sg[sg_len - 1].length;
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 09435e0ec680..b96667448eb5 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -19,7 +19,6 @@
#include <linux/pagemap.h>
#include <linux/err.h>
#include <linux/leds.h>
-#include <asm/scatterlist.h>
#include <linux/scatterlist.h>
#include <linux/mmc/card.h>
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 65fe28860f54..68c0e3b2f0e8 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -213,7 +213,8 @@ static int mmc_read_ext_csd(struct mmc_card *card)
printk(KERN_ERR "%s: unrecognised EXT_CSD structure "
"version %d\n", mmc_hostname(card->host),
ext_csd_struct);
- return -EINVAL;
+ err = -EINVAL;
+ goto out;
}
if (ext_csd_struct >= 2) {
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index bf4bc6adcfef..64b05c6270f2 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -10,7 +10,6 @@
*/
#include <linux/types.h>
-#include <asm/scatterlist.h>
#include <linux/scatterlist.h>
#include <linux/mmc/host.h>
@@ -267,15 +266,26 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host,
int mmc_send_csd(struct mmc_card *card, u32 *csd)
{
+ int ret, i;
+
if (!mmc_host_is_spi(card->host))
return mmc_send_cxd_native(card->host, card->rca << 16,
csd, MMC_SEND_CSD);
- return mmc_send_cxd_data(card, card->host, MMC_SEND_CSD, csd, 16);
+ ret = mmc_send_cxd_data(card, card->host, MMC_SEND_CSD, csd, 16);
+ if (ret)
+ return ret;
+
+ for (i = 0;i < 4;i++)
+ csd[i] = be32_to_cpu(csd[i]);
+
+ return 0;
}
int mmc_send_cid(struct mmc_host *host, u32 *cid)
{
+ int ret, i;
+
if (!mmc_host_is_spi(host)) {
if (!host->card)
return -EINVAL;
@@ -283,7 +293,14 @@ int mmc_send_cid(struct mmc_host *host, u32 *cid)
cid, MMC_SEND_CID);
}
- return mmc_send_cxd_data(NULL, host, MMC_SEND_CID, cid, 16);
+ ret = mmc_send_cxd_data(NULL, host, MMC_SEND_CID, cid, 16);
+ if (ret)
+ return ret;
+
+ for (i = 0;i < 4;i++)
+ cid[i] = be32_to_cpu(cid[i]);
+
+ return 0;
}
int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd)
diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c
index ee4029a24efd..0d96080d44b0 100644
--- a/drivers/mmc/core/sd_ops.c
+++ b/drivers/mmc/core/sd_ops.c
@@ -10,7 +10,6 @@
*/
#include <linux/types.h>
-#include <asm/scatterlist.h>
#include <linux/scatterlist.h>
#include <linux/mmc/host.h>
@@ -294,8 +293,8 @@ int mmc_app_send_scr(struct mmc_card *card, u32 *scr)
if (data.error)
return data.error;
- scr[0] = ntohl(scr[0]);
- scr[1] = ntohl(scr[1]);
+ scr[0] = be32_to_cpu(scr[0]);
+ scr[1] = be32_to_cpu(scr[1]);
return 0;
}
diff --git a/drivers/mmc/core/sdio_ops.c b/drivers/mmc/core/sdio_ops.c
index 4d289b275031..e1fca588e385 100644
--- a/drivers/mmc/core/sdio_ops.c
+++ b/drivers/mmc/core/sdio_ops.c
@@ -9,7 +9,6 @@
* your option) any later version.
*/
-#include <asm/scatterlist.h>
#include <linux/scatterlist.h>
#include <linux/mmc/host.h>
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c
index 6ba98a49612d..b1edcefdd4f9 100644
--- a/drivers/mmc/host/at91_mci.c
+++ b/drivers/mmc/host/at91_mci.c
@@ -149,7 +149,7 @@ static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data
sg = &data->sg[i];
- sgbuffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
+ sgbuffer = kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
amount = min(size, sg->length);
size -= amount;
@@ -226,7 +226,7 @@ static void at91_mci_pre_dma_read(struct at91mci_host *host)
sg = &data->sg[host->transfer_index++];
pr_debug("sg = %p\n", sg);
- sg->dma_address = dma_map_page(NULL, sg->page, sg->offset, sg->length, DMA_FROM_DEVICE);
+ sg->dma_address = dma_map_page(NULL, sg_page(sg), sg->offset, sg->length, DMA_FROM_DEVICE);
pr_debug("dma address = %08X, length = %d\n", sg->dma_address, sg->length);
@@ -283,7 +283,7 @@ static void at91_mci_post_dma_read(struct at91mci_host *host)
int index;
/* Swap the contents of the buffer */
- buffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
+ buffer = kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
pr_debug("buffer = %p, length = %d\n", buffer, sg->length);
for (index = 0; index < (sg->length / 4); index++)
@@ -292,7 +292,7 @@ static void at91_mci_post_dma_read(struct at91mci_host *host)
kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
}
- flush_dcache_page(sg->page);
+ flush_dcache_page(sg_page(sg));
}
/* Is there another transfer to trigger? */
@@ -581,9 +581,7 @@ static void at91_mci_completed_command(struct at91mci_host *host)
pr_debug("Status = %08X [%08X %08X %08X %08X]\n",
status, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
- if (status & (AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE |
- AT91_MCI_RENDE | AT91_MCI_RTOE | AT91_MCI_DCRCE |
- AT91_MCI_DTOE | AT91_MCI_OVRE | AT91_MCI_UNRE)) {
+ if (status & AT91_MCI_ERRORS) {
if ((status & AT91_MCI_RCRCE) && !(mmc_resp_type(cmd) & MMC_RSP_CRC)) {
cmd->error = 0;
}
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index 92c4d0dfee43..c3926eb3bf43 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -40,13 +40,13 @@
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
#include <linux/mmc/host.h>
#include <asm/io.h>
#include <asm/mach-au1x00/au1000.h>
#include <asm/mach-au1x00/au1xxx_dbdma.h>
#include <asm/mach-au1x00/au1100_mmc.h>
-#include <asm/scatterlist.h>
#include <au1xxx.h>
#include "au1xmmc.h"
@@ -212,12 +212,12 @@ static int au1xmmc_send_command(struct au1xmmc_host *host, int wait,
}
if (data) {
- if (flags & MMC_DATA_READ) {
+ if (data->flags & MMC_DATA_READ) {
if (data->blocks > 1)
mmccmd |= SD_CMD_CT_4;
else
mmccmd |= SD_CMD_CT_2;
- } else if (flags & MMC_DATA_WRITE) {
+ } else if (data->flags & MMC_DATA_WRITE) {
if (data->blocks > 1)
mmccmd |= SD_CMD_CT_3;
else
@@ -340,7 +340,7 @@ static void au1xmmc_send_pio(struct au1xmmc_host *host)
/* This is the pointer to the data buffer */
sg = &data->sg[host->pio.index];
- sg_ptr = page_address(sg->page) + sg->offset + host->pio.offset;
+ sg_ptr = sg_virt(sg) + host->pio.offset;
/* This is the space left inside the buffer */
sg_len = data->sg[host->pio.index].length - host->pio.offset;
@@ -400,7 +400,7 @@ static void au1xmmc_receive_pio(struct au1xmmc_host *host)
if (host->pio.index < host->dma.len) {
sg = &data->sg[host->pio.index];
- sg_ptr = page_address(sg->page) + sg->offset + host->pio.offset;
+ sg_ptr = sg_virt(sg) + host->pio.offset;
/* This is the space left inside the buffer */
sg_len = sg_dma_len(&data->sg[host->pio.index]) - host->pio.offset;
@@ -613,14 +613,11 @@ au1xmmc_prepare_data(struct au1xmmc_host *host, struct mmc_data *data)
if (host->flags & HOST_F_XMIT){
ret = au1xxx_dbdma_put_source_flags(channel,
- (void *) (page_address(sg->page) +
- sg->offset),
- len, flags);
+ (void *) sg_virt(sg), len, flags);
}
else {
ret = au1xxx_dbdma_put_dest_flags(channel,
- (void *) (page_address(sg->page) +
- sg->offset),
+ (void *) sg_virt(sg),
len, flags);
}
diff --git a/drivers/mmc/host/imxmmc.c b/drivers/mmc/host/imxmmc.c
index 6ebc41e7592c..f2070a19cfa7 100644
--- a/drivers/mmc/host/imxmmc.c
+++ b/drivers/mmc/host/imxmmc.c
@@ -262,7 +262,7 @@ static void imxmci_setup_data(struct imxmci_host *host, struct mmc_data *data)
}
/* Convert back to virtual address */
- host->data_ptr = (u16*)(page_address(data->sg->page) + data->sg->offset);
+ host->data_ptr = (u16*)sg_virt(data->sg);
host->data_cnt = 0;
clear_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events);
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
index 254b194e7625..a6469218f194 100644
--- a/drivers/mmc/host/mmc_spi.c
+++ b/drivers/mmc/host/mmc_spi.c
@@ -30,6 +30,7 @@
#include <linux/dma-mapping.h>
#include <linux/crc7.h>
#include <linux/crc-itu-t.h>
+#include <linux/scatterlist.h>
#include <linux/mmc/host.h>
#include <linux/mmc/mmc.h> /* for R1_SPI_* bit values */
@@ -812,7 +813,7 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd,
&& dir == DMA_FROM_DEVICE)
dir = DMA_BIDIRECTIONAL;
- dma_addr = dma_map_page(dma_dev, sg->page, 0,
+ dma_addr = dma_map_page(dma_dev, sg_page(sg), 0,
PAGE_SIZE, dir);
if (direction == DMA_TO_DEVICE)
t->tx_dma = dma_addr + sg->offset;
@@ -821,7 +822,7 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd,
}
/* allow pio too; we don't allow highmem */
- kmap_addr = kmap(sg->page);
+ kmap_addr = kmap(sg_page(sg));
if (direction == DMA_TO_DEVICE)
t->tx_buf = kmap_addr + sg->offset;
else
@@ -854,8 +855,8 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd,
/* discard mappings */
if (direction == DMA_FROM_DEVICE)
- flush_kernel_dcache_page(sg->page);
- kunmap(sg->page);
+ flush_kernel_dcache_page(sg_page(sg));
+ kunmap(sg_page(sg));
if (dma_dev)
dma_unmap_page(dma_dev, dma_addr, PAGE_SIZE, dir);
@@ -1164,6 +1165,23 @@ mmc_spi_detect_irq(int irq, void *mmc)
return IRQ_HANDLED;
}
+struct count_children {
+ unsigned n;
+ struct bus_type *bus;
+};
+
+static int maybe_count_child(struct device *dev, void *c)
+{
+ struct count_children *ccp = c;
+
+ if (dev->bus == ccp->bus) {
+ if (ccp->n)
+ return -EBUSY;
+ ccp->n++;
+ }
+ return 0;
+}
+
static int mmc_spi_probe(struct spi_device *spi)
{
void *ones;
@@ -1187,33 +1205,30 @@ static int mmc_spi_probe(struct spi_device *spi)
return status;
}
- /* We can use the bus safely iff nobody else will interfere with
- * us. That is, either we have the experimental exclusive access
- * primitives ... or else there's nobody to share it with.
+ /* We can use the bus safely iff nobody else will interfere with us.
+ * Most commands consist of one SPI message to issue a command, then
+ * several more to collect its response, then possibly more for data
+ * transfer. Clocking access to other devices during that period will
+ * corrupt the command execution.
+ *
+ * Until we have software primitives which guarantee non-interference,
+ * we'll aim for a hardware-level guarantee.
+ *
+ * REVISIT we can't guarantee another device won't be added later...
*/
if (spi->master->num_chipselect > 1) {
- struct device *parent = spi->dev.parent;
+ struct count_children cc;
- /* If there are multiple devices on this bus, we
- * can't proceed.
- */
- spin_lock(&parent->klist_children.k_lock);
- if (parent->klist_children.k_list.next
- != parent->klist_children.k_list.prev)
- status = -EMLINK;
- else
- status = 0;
- spin_unlock(&parent->klist_children.k_lock);
+ cc.n = 0;
+ cc.bus = spi->dev.bus;
+ status = device_for_each_child(spi->dev.parent, &cc,
+ maybe_count_child);
if (status < 0) {
dev_err(&spi->dev, "can't share SPI bus\n");
return status;
}
- /* REVISIT we can't guarantee another device won't
- * be added later. It's uncommon though ... for now,
- * work as if this is safe.
- */
- dev_warn(&spi->dev, "ASSUMING unshared SPI bus!\n");
+ dev_warn(&spi->dev, "ASSUMING SPI bus stays unshared!\n");
}
/* We need a supply of ones to transmit. This is the only time
@@ -1280,8 +1295,8 @@ static int mmc_spi_probe(struct spi_device *spi)
if (!host->data)
goto fail_nobuf1;
- if (spi->master->cdev.dev->dma_mask) {
- struct device *dev = spi->master->cdev.dev;
+ if (spi->master->dev.parent->dma_mask) {
+ struct device *dev = spi->master->dev.parent;
host->dma_dev = dev;
host->ones_dma = dma_map_single(dev, ones,
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index d0eb0a2abf4d..95244a7e7353 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -20,11 +20,11 @@
#include <linux/mmc/host.h>
#include <linux/amba/bus.h>
#include <linux/clk.h>
+#include <linux/scatterlist.h>
#include <asm/cacheflush.h>
#include <asm/div64.h>
#include <asm/io.h>
-#include <asm/scatterlist.h>
#include <asm/sizes.h>
#include <asm/mach/mmc.h>
@@ -167,7 +167,7 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
* partially written to a page is properly coherent.
*/
if (host->sg_len && data->flags & MMC_DATA_READ)
- flush_dcache_page(host->sg_ptr->page);
+ flush_dcache_page(sg_page(host->sg_ptr));
}
if (status & MCI_DATAEND) {
mmci_stop_data(host);
@@ -319,7 +319,7 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id)
* page, ensure that the data cache is coherent.
*/
if (status & MCI_RXACTIVE)
- flush_dcache_page(host->sg_ptr->page);
+ flush_dcache_page(sg_page(host->sg_ptr));
if (!mmci_next_sg(host))
break;
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index 000e6a919782..0f39c490f022 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -169,7 +169,7 @@ static inline char *mmci_kmap_atomic(struct mmci_host *host, unsigned long *flag
struct scatterlist *sg = host->sg_ptr;
local_irq_save(*flags);
- return kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
+ return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
}
static inline void mmci_kunmap_atomic(struct mmci_host *host, void *buffer, unsigned long *flags)
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 60a67dfcda6a..971e18b91f4a 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -24,10 +24,10 @@
#include <linux/mmc/host.h>
#include <linux/mmc/card.h>
#include <linux/clk.h>
+#include <linux/scatterlist.h>
#include <asm/io.h>
#include <asm/irq.h>
-#include <asm/scatterlist.h>
#include <asm/mach-types.h>
#include <asm/arch/board.h>
@@ -383,7 +383,7 @@ mmc_omap_sg_to_buf(struct mmc_omap_host *host)
sg = host->data->sg + host->sg_idx;
host->buffer_bytes_left = sg->length;
- host->buffer = page_address(sg->page) + sg->offset;
+ host->buffer = sg_virt(sg);
if (host->buffer_bytes_left > host->total_bytes_left)
host->buffer_bytes_left = host->total_bytes_left;
}
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index 657901eecfce..1654a3330340 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -23,11 +23,12 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+#include <linux/err.h>
#include <linux/mmc/host.h>
#include <asm/dma.h>
#include <asm/io.h>
-#include <asm/scatterlist.h>
#include <asm/sizes.h>
#include <asm/arch/pxa-regs.h>
@@ -38,12 +39,15 @@
#define DRIVER_NAME "pxa2xx-mci"
#define NR_SG 1
+#define CLKRT_OFF (~0)
struct pxamci_host {
struct mmc_host *mmc;
spinlock_t lock;
struct resource *res;
void __iomem *base;
+ struct clk *clk;
+ unsigned long clkrate;
int irq;
int dma;
unsigned int clkrt;
@@ -119,7 +123,7 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)
writel(nob, host->base + MMC_NOB);
writel(data->blksz, host->base + MMC_BLKLEN);
- clks = (unsigned long long)data->timeout_ns * CLOCKRATE;
+ clks = (unsigned long long)data->timeout_ns * host->clkrate;
do_div(clks, 1000000000UL);
timeout = (unsigned int)clks + (data->timeout_clks << host->clkrt);
writel((timeout + 255) / 256, host->base + MMC_RDTO);
@@ -365,18 +369,30 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
struct pxamci_host *host = mmc_priv(mmc);
if (ios->clock) {
- unsigned int clk = CLOCKRATE / ios->clock;
- if (CLOCKRATE / clk > ios->clock)
+ unsigned long rate = host->clkrate;
+ unsigned int clk = rate / ios->clock;
+
+ if (host->clkrt == CLKRT_OFF)
+ clk_enable(host->clk);
+
+ /*
+ * clk might result in a lower divisor than we
+ * desire. check for that condition and adjust
+ * as appropriate.
+ */
+ if (rate / clk > ios->clock)
clk <<= 1;
host->clkrt = fls(clk) - 1;
- pxa_set_cken(CKEN_MMC, 1);
/*
* we write clkrt on the next command
*/
} else {
pxamci_stop_clock(host);
- pxa_set_cken(CKEN_MMC, 0);
+ if (host->clkrt != CLKRT_OFF) {
+ host->clkrt = CLKRT_OFF;
+ clk_disable(host->clk);
+ }
}
if (host->power_mode != ios->power_mode) {
@@ -462,8 +478,6 @@ static int pxamci_probe(struct platform_device *pdev)
}
mmc->ops = &pxamci_ops;
- mmc->f_min = CLOCKRATE_MIN;
- mmc->f_max = CLOCKRATE_MAX;
/*
* We can do SG-DMA, but we don't because we never know how much
@@ -490,6 +504,23 @@ static int pxamci_probe(struct platform_device *pdev)
host->mmc = mmc;
host->dma = -1;
host->pdata = pdev->dev.platform_data;
+ host->clkrt = CLKRT_OFF;
+
+ host->clk = clk_get(&pdev->dev, "MMCCLK");
+ if (IS_ERR(host->clk)) {
+ ret = PTR_ERR(host->clk);
+ host->clk = NULL;
+ goto out;
+ }
+
+ host->clkrate = clk_get_rate(host->clk);
+
+ /*
+ * Calculate minimum clock rate, rounding up.
+ */
+ mmc->f_min = (host->clkrate + 63) / 64;
+ mmc->f_max = host->clkrate;
+
mmc->ocr_avail = host->pdata ?
host->pdata->ocr_mask :
MMC_VDD_32_33|MMC_VDD_33_34;
@@ -554,6 +585,8 @@ static int pxamci_probe(struct platform_device *pdev)
iounmap(host->base);
if (host->sg_cpu)
dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
+ if (host->clk)
+ clk_put(host->clk);
}
if (mmc)
mmc_free_host(mmc);
@@ -588,6 +621,8 @@ static int pxamci_remove(struct platform_device *pdev)
iounmap(host->base);
dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
+ clk_put(host->clk);
+
release_resource(host->res);
mmc_free_host(mmc);
diff --git a/drivers/mmc/host/pxamci.h b/drivers/mmc/host/pxamci.h
index 3153e779d46a..748c7706f237 100644
--- a/drivers/mmc/host/pxamci.h
+++ b/drivers/mmc/host/pxamci.h
@@ -88,17 +88,3 @@
#define MMC_RXFIFO 0x0040 /* 8 bit */
#define MMC_TXFIFO 0x0044 /* 8 bit */
-
-/*
- * The base MMC clock rate
- */
-#ifdef CONFIG_PXA27x
-#define CLOCKRATE_MIN 304688
-#define CLOCKRATE_MAX 19500000
-#else
-#define CLOCKRATE_MIN 312500
-#define CLOCKRATE_MAX 20000000
-#endif
-
-#define CLOCKRATE CLOCKRATE_MAX
-
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index b397121b947d..ff59d2e0475b 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -13,11 +13,10 @@
#include <linux/highmem.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
#include <linux/mmc/host.h>
-#include <asm/scatterlist.h>
-
#include "sdhci.h"
#define DRIVER_NAME "sdhci"
@@ -231,7 +230,7 @@ static void sdhci_deactivate_led(struct sdhci_host *host)
static inline char* sdhci_sg_to_buffer(struct sdhci_host* host)
{
- return page_address(host->cur_sg->page) + host->cur_sg->offset;
+ return sg_virt(host->cur_sg);
}
static inline int sdhci_next_sg(struct sdhci_host* host)
@@ -1302,7 +1301,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
if ((chip->quirks & SDHCI_QUIRK_BROKEN_DMA) &&
(host->flags & SDHCI_USE_DMA)) {
- DBG("Disabling DMA as it is marked broken");
+ DBG("Disabling DMA as it is marked broken\n");
host->flags &= ~SDHCI_USE_DMA;
}
diff --git a/drivers/mmc/host/tifm_sd.c b/drivers/mmc/host/tifm_sd.c
index 9b904795eb77..c11a3d256051 100644
--- a/drivers/mmc/host/tifm_sd.c
+++ b/drivers/mmc/host/tifm_sd.c
@@ -192,7 +192,7 @@ static void tifm_sd_transfer_data(struct tifm_sd *host)
}
off = sg[host->sg_pos].offset + host->block_pos;
- pg = nth_page(sg[host->sg_pos].page, off >> PAGE_SHIFT);
+ pg = nth_page(sg_page(&sg[host->sg_pos]), off >> PAGE_SHIFT);
p_off = offset_in_page(off);
p_cnt = PAGE_SIZE - p_off;
p_cnt = min(p_cnt, cnt);
@@ -241,18 +241,18 @@ static void tifm_sd_bounce_block(struct tifm_sd *host, struct mmc_data *r_data)
}
off = sg[host->sg_pos].offset + host->block_pos;
- pg = nth_page(sg[host->sg_pos].page, off >> PAGE_SHIFT);
+ pg = nth_page(sg_page(&sg[host->sg_pos]), off >> PAGE_SHIFT);
p_off = offset_in_page(off);
p_cnt = PAGE_SIZE - p_off;
p_cnt = min(p_cnt, cnt);
p_cnt = min(p_cnt, t_size);
if (r_data->flags & MMC_DATA_WRITE)
- tifm_sd_copy_page(host->bounce_buf.page,
+ tifm_sd_copy_page(sg_page(&host->bounce_buf),
r_data->blksz - t_size,
pg, p_off, p_cnt);
else if (r_data->flags & MMC_DATA_READ)
- tifm_sd_copy_page(pg, p_off, host->bounce_buf.page,
+ tifm_sd_copy_page(pg, p_off, sg_page(&host->bounce_buf),
r_data->blksz - t_size, p_cnt);
t_size -= p_cnt;
diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c
index 80db11c05f2a..4d5f37421874 100644
--- a/drivers/mmc/host/wbsd.c
+++ b/drivers/mmc/host/wbsd.c
@@ -33,10 +33,10 @@
#include <linux/pnp.h>
#include <linux/highmem.h>
#include <linux/mmc/host.h>
+#include <linux/scatterlist.h>
#include <asm/io.h>
#include <asm/dma.h>
-#include <asm/scatterlist.h>
#include "wbsd.h"
@@ -269,7 +269,7 @@ static inline int wbsd_next_sg(struct wbsd_host *host)
static inline char *wbsd_sg_to_buffer(struct wbsd_host *host)
{
- return page_address(host->cur_sg->page) + host->cur_sg->offset;
+ return sg_virt(host->cur_sg);
}
static inline void wbsd_sg_to_dma(struct wbsd_host *host, struct mmc_data *data)
@@ -283,7 +283,7 @@ static inline void wbsd_sg_to_dma(struct wbsd_host *host, struct mmc_data *data)
len = data->sg_len;
for (i = 0; i < len; i++) {
- sgbuf = page_address(sg[i].page) + sg[i].offset;
+ sgbuf = sg_virt(&sg[i]);
memcpy(dmabuf, sgbuf, sg[i].length);
dmabuf += sg[i].length;
}
@@ -300,7 +300,7 @@ static inline void wbsd_dma_to_sg(struct wbsd_host *host, struct mmc_data *data)
len = data->sg_len;
for (i = 0; i < len; i++) {
- sgbuf = page_address(sg[i].page) + sg[i].offset;
+ sgbuf = sg_virt(&sg[i]);
memcpy(sgbuf, dmabuf, sg[i].length);
dmabuf += sg[i].length;
}
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
index 3aa3dca56ae6..a9eb1c516247 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -85,6 +85,7 @@ static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len,
static void cfi_intelext_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from,
size_t len);
+static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long adr, int mode);
static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode);
static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr);
#include "fwh_lock.h"
@@ -641,73 +642,13 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd,
/*
* *********** CHIP ACCESS FUNCTIONS ***********
*/
-
-static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode)
+static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long adr, int mode)
{
DECLARE_WAITQUEUE(wait, current);
struct cfi_private *cfi = map->fldrv_priv;
map_word status, status_OK = CMD(0x80), status_PWS = CMD(0x01);
- unsigned long timeo;
struct cfi_pri_intelext *cfip = cfi->cmdset_priv;
-
- resettime:
- timeo = jiffies + HZ;
- retry:
- if (chip->priv && (mode == FL_WRITING || mode == FL_ERASING || mode == FL_OTP_WRITE || mode == FL_SHUTDOWN)) {
- /*
- * OK. We have possibility for contension on the write/erase
- * operations which are global to the real chip and not per
- * partition. So let's fight it over in the partition which
- * currently has authority on the operation.
- *
- * The rules are as follows:
- *
- * - any write operation must own shared->writing.
- *
- * - any erase operation must own _both_ shared->writing and
- * shared->erasing.
- *
- * - contension arbitration is handled in the owner's context.
- *
- * The 'shared' struct can be read and/or written only when
- * its lock is taken.
- */
- struct flchip_shared *shared = chip->priv;
- struct flchip *contender;
- spin_lock(&shared->lock);
- contender = shared->writing;
- if (contender && contender != chip) {
- /*
- * The engine to perform desired operation on this
- * partition is already in use by someone else.
- * Let's fight over it in the context of the chip
- * currently using it. If it is possible to suspend,
- * that other partition will do just that, otherwise
- * it'll happily send us to sleep. In any case, when
- * get_chip returns success we're clear to go ahead.
- */
- int ret = spin_trylock(contender->mutex);
- spin_unlock(&shared->lock);
- if (!ret)
- goto retry;
- spin_unlock(chip->mutex);
- ret = get_chip(map, contender, contender->start, mode);
- spin_lock(chip->mutex);
- if (ret) {
- spin_unlock(contender->mutex);
- return ret;
- }
- timeo = jiffies + HZ;
- spin_lock(&shared->lock);
- spin_unlock(contender->mutex);
- }
-
- /* We now own it */
- shared->writing = chip;
- if (mode == FL_ERASING)
- shared->erasing = chip;
- spin_unlock(&shared->lock);
- }
+ unsigned long timeo = jiffies + HZ;
switch (chip->state) {
@@ -722,16 +663,11 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
if (chip->priv && map_word_andequal(map, status, status_PWS, status_PWS))
break;
- if (time_after(jiffies, timeo)) {
- printk(KERN_ERR "%s: Waiting for chip to be ready timed out. Status %lx\n",
- map->name, status.x[0]);
- return -EIO;
- }
spin_unlock(chip->mutex);
cfi_udelay(1);
spin_lock(chip->mutex);
/* Someone else might have been playing with it. */
- goto retry;
+ return -EAGAIN;
}
case FL_READY:
@@ -809,10 +745,82 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
schedule();
remove_wait_queue(&chip->wq, &wait);
spin_lock(chip->mutex);
- goto resettime;
+ return -EAGAIN;
}
}
+static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode)
+{
+ int ret;
+
+ retry:
+ if (chip->priv && (mode == FL_WRITING || mode == FL_ERASING
+ || mode == FL_OTP_WRITE || mode == FL_SHUTDOWN)) {
+ /*
+ * OK. We have possibility for contention on the write/erase
+ * operations which are global to the real chip and not per
+ * partition. So let's fight it over in the partition which
+ * currently has authority on the operation.
+ *
+ * The rules are as follows:
+ *
+ * - any write operation must own shared->writing.
+ *
+ * - any erase operation must own _both_ shared->writing and
+ * shared->erasing.
+ *
+ * - contention arbitration is handled in the owner's context.
+ *
+ * The 'shared' struct can be read and/or written only when
+ * its lock is taken.
+ */
+ struct flchip_shared *shared = chip->priv;
+ struct flchip *contender;
+ spin_lock(&shared->lock);
+ contender = shared->writing;
+ if (contender && contender != chip) {
+ /*
+ * The engine to perform desired operation on this
+ * partition is already in use by someone else.
+ * Let's fight over it in the context of the chip
+ * currently using it. If it is possible to suspend,
+ * that other partition will do just that, otherwise
+ * it'll happily send us to sleep. In any case, when
+ * get_chip returns success we're clear to go ahead.
+ */
+ ret = spin_trylock(contender->mutex);
+ spin_unlock(&shared->lock);
+ if (!ret)
+ goto retry;
+ spin_unlock(chip->mutex);
+ ret = chip_ready(map, contender, contender->start, mode);
+ spin_lock(chip->mutex);
+
+ if (ret == -EAGAIN) {
+ spin_unlock(contender->mutex);
+ goto retry;
+ }
+ if (ret) {
+ spin_unlock(contender->mutex);
+ return ret;
+ }
+ spin_lock(&shared->lock);
+ spin_unlock(contender->mutex);
+ }
+
+ /* We now own it */
+ shared->writing = chip;
+ if (mode == FL_ERASING)
+ shared->erasing = chip;
+ spin_unlock(&shared->lock);
+ }
+ ret = chip_ready(map, chip, adr, mode);
+ if (ret == -EAGAIN)
+ goto retry;
+
+ return ret;
+}
+
static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr)
{
struct cfi_private *cfi = map->fldrv_priv;
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 2a2a125b0c76..a592fc04cf78 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -54,7 +54,7 @@ config MTD_PHYSMAP_BANKWIDTH
help
This is the total width of the data bus of the flash devices
in octets. For example, if you have a data bus width of 32
- bits, you would set the bus width octect value to 4. This is
+ bits, you would set the bus width octet value to 4. This is
used internally by the CFI drivers.
Ignore this option if you use run-time physmap configuration
(i.e., run-time calling physmap_configure()).
@@ -73,12 +73,12 @@ config MTD_PMC_MSP_EVM
depends on PMC_MSP && MTD_CFI
select MTD_PARTITIONS
help
- This provides a 'mapping' driver which support the way
- in which user-programmable flash chips are connected on the
- PMC-Sierra MSP eval/demo boards
+ This provides a 'mapping' driver which supports the way
+ in which user-programmable flash chips are connected on the
+ PMC-Sierra MSP eval/demo boards.
choice
- prompt "Maximum mappable memory avialable for flash IO"
+ prompt "Maximum mappable memory available for flash IO"
depends on MTD_PMC_MSP_EVM
default MSP_FLASH_MAP_LIMIT_32M
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 8f9c3baeb38e..246d4512f64b 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -300,7 +300,7 @@ config MTD_NAND_PLATFORM
via platform_data.
config MTD_ALAUDA
- tristate "MTD driver for Olympus MAUSB-10 and Fijufilm DPC-R1"
+ tristate "MTD driver for Olympus MAUSB-10 and Fujifilm DPC-R1"
depends on MTD_NAND && USB
help
These two (and possibly other) Alauda-based cardreaders for
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index ab9f5c5db38d..0e72153b3297 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -220,7 +220,7 @@ static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc)
}
}
/* If the parity is wrong, no rescue possible */
- return parity ? -1 : nerr;
+ return parity ? -EBADMSG : nerr;
}
static void DoC_Delay(struct doc_priv *doc, unsigned short cycles)
@@ -1034,7 +1034,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat,
WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf);
else
WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
- if (no_ecc_failures && (ret == -1)) {
+ if (no_ecc_failures && (ret == -EBADMSG)) {
printk(KERN_ERR "suppressing ECC failure\n");
ret = 0;
}
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index b4e0e7723894..e29c1da7f56e 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -789,7 +789,7 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
int stat;
stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
- if (stat == -1)
+ if (stat < 0)
mtd->ecc_stats.failed++;
else
mtd->ecc_stats.corrected += stat;
@@ -833,7 +833,7 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
int stat;
stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
- if (stat == -1)
+ if (stat < 0)
mtd->ecc_stats.failed++;
else
mtd->ecc_stats.corrected += stat;
@@ -874,7 +874,7 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
chip->read_buf(mtd, oob, eccbytes);
stat = chip->ecc.correct(mtd, p, oob, NULL);
- if (stat == -1)
+ if (stat < 0)
mtd->ecc_stats.failed++;
else
mtd->ecc_stats.corrected += stat;
diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c
index fde593e5e634..9003a135e050 100644
--- a/drivers/mtd/nand/nand_ecc.c
+++ b/drivers/mtd/nand/nand_ecc.c
@@ -189,7 +189,7 @@ int nand_correct_data(struct mtd_info *mtd, u_char *dat,
if(countbits(s0 | ((uint32_t)s1 << 8) | ((uint32_t)s2 <<16)) == 1)
return 1;
- return -1;
+ return -EBADMSG;
}
EXPORT_SYMBOL(nand_correct_data);
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index a7574807dc46..10490b48d9f7 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -511,7 +511,7 @@ static int init_nandsim(struct mtd_info *mtd)
}
if (ns->options & OPT_SMALLPAGE) {
- if (ns->geom.totsz < (64 << 20)) {
+ if (ns->geom.totsz < (32 << 20)) {
ns->geom.pgaddrbytes = 3;
ns->geom.secaddrbytes = 2;
} else {
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index b79a9cf2d162..66f76e9618dd 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -488,12 +488,24 @@ static void s3c2410_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
readsb(this->IO_ADDR_R, buf, len);
}
+static void s3c2440_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+{
+ struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
+ readsl(info->regs + S3C2440_NFDATA, buf, len / 4);
+}
+
static void s3c2410_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
{
struct nand_chip *this = mtd->priv;
writesb(this->IO_ADDR_W, buf, len);
}
+static void s3c2440_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
+{
+ struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
+ writesl(info->regs + S3C2440_NFDATA, buf, len / 4);
+}
+
/* device management functions */
static int s3c2410_nand_remove(struct platform_device *pdev)
@@ -604,6 +616,8 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
info->sel_bit = S3C2440_NFCONT_nFCE;
chip->cmd_ctrl = s3c2440_nand_hwcontrol;
chip->dev_ready = s3c2440_nand_devready;
+ chip->read_buf = s3c2440_nand_read_buf;
+ chip->write_buf = s3c2440_nand_write_buf;
break;
case TYPE_S3C2412:
@@ -696,7 +710,7 @@ static int s3c24xx_nand_probe(struct platform_device *pdev,
info->clk = clk_get(&pdev->dev, "nand");
if (IS_ERR(info->clk)) {
- dev_err(&pdev->dev, "failed to get clock");
+ dev_err(&pdev->dev, "failed to get clock\n");
err = -ENOENT;
goto exit_error;
}
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index dd2835569092..1b0b32011415 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -359,7 +359,7 @@ static int onenand_wait(struct mtd_info *mtd, int state)
*/
static irqreturn_t onenand_interrupt(int irq, void *data)
{
- struct onenand_chip *this = (struct onenand_chip *) data;
+ struct onenand_chip *this = data;
/* To handle shared interrupt */
if (!this->complete.done)
diff --git a/drivers/mtd/onenand/onenand_sim.c b/drivers/mtd/onenand/onenand_sim.c
index 0d89ad5776fa..d64200b7c94b 100644
--- a/drivers/mtd/onenand/onenand_sim.c
+++ b/drivers/mtd/onenand/onenand_sim.c
@@ -88,11 +88,11 @@ do { \
/**
* onenand_lock_handle - Handle Lock scheme
- * @param this OneNAND device structure
- * @param cmd The command to be sent
+ * @this: OneNAND device structure
+ * @cmd: The command to be sent
*
* Send lock command to OneNAND device.
- * The lock scheme is depends on chip type.
+ * The lock scheme depends on chip type.
*/
static void onenand_lock_handle(struct onenand_chip *this, int cmd)
{
@@ -131,8 +131,8 @@ static void onenand_lock_handle(struct onenand_chip *this, int cmd)
/**
* onenand_bootram_handle - Handle BootRAM area
- * @param this OneNAND device structure
- * @param cmd The command to be sent
+ * @this: OneNAND device structure
+ * @cmd: The command to be sent
*
* Emulate BootRAM area. It is possible to do basic operation using BootRAM.
*/
@@ -153,10 +153,10 @@ static void onenand_bootram_handle(struct onenand_chip *this, int cmd)
/**
* onenand_update_interrupt - Set interrupt register
- * @param this OneNAND device structure
- * @param cmd The command to be sent
+ * @this: OneNAND device structure
+ * @cmd: The command to be sent
*
- * Update interrupt register. The status is depends on command.
+ * Update interrupt register. The status depends on command.
*/
static void onenand_update_interrupt(struct onenand_chip *this, int cmd)
{
@@ -189,11 +189,12 @@ static void onenand_update_interrupt(struct onenand_chip *this, int cmd)
}
/**
- * onenand_check_overwrite - Check over-write if happend
- * @param dest The destination pointer
- * @param src The source pointer
- * @param count The length to be check
- * @return 0 on same, otherwise 1
+ * onenand_check_overwrite - Check if over-write happened
+ * @dest: The destination pointer
+ * @src: The source pointer
+ * @count: The length to be check
+ *
+ * Returns: 0 on same, otherwise 1
*
* Compare the source with destination
*/
@@ -213,10 +214,10 @@ static int onenand_check_overwrite(void *dest, void *src, size_t count)
/**
* onenand_data_handle - Handle OneNAND Core and DataRAM
- * @param this OneNAND device structure
- * @param cmd The command to be sent
- * @param dataram Which dataram used
- * @param offset The offset to OneNAND Core
+ * @this: OneNAND device structure
+ * @cmd: The command to be sent
+ * @dataram: Which dataram used
+ * @offset: The offset to OneNAND Core
*
* Copy data from OneNAND Core to DataRAM (read)
* Copy data from DataRAM to OneNAND Core (write)
@@ -295,8 +296,8 @@ static void onenand_data_handle(struct onenand_chip *this, int cmd,
/**
* onenand_command_handle - Handle command
- * @param this OneNAND device structure
- * @param cmd The command to be sent
+ * @this: OneNAND device structure
+ * @cmd: The command to be sent
*
* Emulate OneNAND command.
*/
@@ -350,8 +351,8 @@ static void onenand_command_handle(struct onenand_chip *this, int cmd)
/**
* onenand_writew - [OneNAND Interface] Emulate write operation
- * @param value value to write
- * @param addr address to write
+ * @value: value to write
+ * @addr: address to write
*
* Write OneNAND register with value
*/
@@ -373,7 +374,7 @@ static void onenand_writew(unsigned short value, void __iomem * addr)
/**
* flash_init - Initialize OneNAND simulator
- * @param flash OneNAND simulaotr data strucutres
+ * @flash: OneNAND simulator data strucutres
*
* Initialize OneNAND simulator.
*/
@@ -416,7 +417,7 @@ static int __init flash_init(struct onenand_flash *flash)
/**
* flash_exit - Clean up OneNAND simulator
- * @param flash OneNAND simulaotr data strucutres
+ * @flash: OneNAND simulator data structures
*
* Clean up OneNAND simulator.
*/
@@ -424,7 +425,6 @@ static void flash_exit(struct onenand_flash *flash)
{
vfree(ONENAND_CORE(flash));
kfree(flash->base);
- kfree(flash);
}
static int __init onenand_sim_init(void)
@@ -449,7 +449,7 @@ static int __init onenand_sim_init(void)
info->onenand.write_word = onenand_writew;
if (flash_init(&info->flash)) {
- printk(KERN_ERR "Unable to allocat flash.\n");
+ printk(KERN_ERR "Unable to allocate flash.\n");
kfree(ffchars);
kfree(info);
return -ENOMEM;
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index 1297732f4db9..880fa3690352 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -933,8 +933,7 @@ write_error:
* @cache: the lock tree entry slab cache
* @flags: constructor flags
*/
-static void ltree_entry_ctor(void *obj, struct kmem_cache *cache,
- unsigned long flags)
+static void ltree_entry_ctor(struct kmem_cache *cache, void *obj)
{
struct ltree_entry *le = obj;
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index a4f1bf33164a..6330c8cc72b5 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -1309,7 +1309,7 @@ static int ubi_thread(void *u)
struct ubi_device *ubi = u;
ubi_msg("background thread \"%s\" started, PID %d",
- ubi->bgt_name, current->pid);
+ ubi->bgt_name, task_pid_nr(current));
set_freezable();
for (;;) {
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 8d3893da06f5..6f8e7d4cf74d 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -1491,7 +1491,7 @@ vortex_up(struct net_device *dev)
struct vortex_private *vp = netdev_priv(dev);
void __iomem *ioaddr = vp->ioaddr;
unsigned int config;
- int i, mii_reg1, mii_reg5, err;
+ int i, mii_reg1, mii_reg5, err = 0;
if (VORTEX_PCI(vp)) {
pci_set_power_state(VORTEX_PCI(vp), PCI_D0); /* Go active */
@@ -3118,7 +3118,13 @@ static void acpi_set_WOL(struct net_device *dev)
iowrite16(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD);
iowrite16(RxEnable, ioaddr + EL3_CMD);
- pci_enable_wake(VORTEX_PCI(vp), 0, 1);
+ if (pci_enable_wake(VORTEX_PCI(vp), PCI_D3hot, 1)) {
+ printk(KERN_INFO "%s: WOL not supported.\n",
+ pci_name(VORTEX_PCI(vp)));
+
+ vp->enable_wol = 0;
+ return;
+ }
/* Change the power state to D3; RxEnable doesn't take effect. */
pci_set_power_state(VORTEX_PCI(vp), PCI_D3hot);
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index 973b684c11e3..eef6fecfff2a 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -73,7 +73,7 @@
Jean-Jacques Michel - bug fix
- Tobias Ringström - Rx interrupt status checking suggestion
+ Tobias Ringström - Rx interrupt status checking suggestion
Andrew Morton - Clear blocked signals, avoid
buffer overrun setting current->comm.
diff --git a/drivers/net/82596.c b/drivers/net/82596.c
index bb30d5be7824..2797da7eeee6 100644
--- a/drivers/net/82596.c
+++ b/drivers/net/82596.c
@@ -1192,6 +1192,8 @@ struct net_device * __init i82596_probe(int unit)
goto out;
}
+ dev->base_addr = ioaddr;
+
for (i = 0; i < 8; i++) {
eth_addr[i] = inb(ioaddr + 8 + i);
checksum += eth_addr[i];
@@ -1209,7 +1211,6 @@ struct net_device * __init i82596_probe(int unit)
goto out1;
}
- dev->base_addr = ioaddr;
dev->irq = 10;
}
#endif
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 9c635a237a9d..e8d69b0adf90 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -136,10 +136,11 @@ config TUN
If you don't know what to use this for, you don't need it.
config VETH
- tristate "Virtual ethernet device"
+ tristate "Virtual ethernet pair device"
---help---
- The device is an ethernet tunnel. Devices are created in pairs. When
- one end receives the packet it appears on its pair and vice versa.
+ This device is a local ethernet tunnel. Devices are created in pairs.
+ When one end receives the packet it appears on its pair and vice
+ versa.
config NET_SB1000
tristate "General Instruments Surfboard 1000"
@@ -166,13 +167,14 @@ config NET_SB1000
If you don't have this card, of course say N.
config IP1000
- tristate "IP1000 Gigabit Ethernet support"
- depends on PCI && EXPERIMENTAL
- ---help---
- This driver supports IP1000 gigabit Ethernet cards.
+ tristate "IP1000 Gigabit Ethernet support"
+ depends on PCI && EXPERIMENTAL
+ select MII
+ ---help---
+ This driver supports IP1000 gigabit Ethernet cards.
- To compile this driver as a module, choose M here: the module
- will be called ipg. This is recommended.
+ To compile this driver as a module, choose M here: the module
+ will be called ipg. This is recommended.
source "drivers/net/arcnet/Kconfig"
@@ -233,7 +235,7 @@ source "drivers/net/arm/Kconfig"
config AX88796
tristate "ASIX AX88796 NE2000 clone support"
- depends on ARM || MIPS
+ depends on ARM || MIPS || SUPERH
select CRC32
select MII
help
@@ -364,8 +366,7 @@ config MAC89x0
read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. This module will
+ To compile this driver as a module, choose M here. This module will
be called mac89x0.
config MACSONIC
@@ -378,8 +379,7 @@ config MACSONIC
one of these say Y and read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. This module will
+ To compile this driver as a module, choose M here. This module will
be called macsonic.
config MACMACE
@@ -617,8 +617,7 @@ config EL1
have problems. Some people suggest to ping ("man ping") a nearby
machine every minute ("man cron") when using this card.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called 3c501.
config EL2
@@ -630,8 +629,7 @@ config EL2
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called 3c503.
config ELPLUS
@@ -643,8 +641,7 @@ config ELPLUS
this type, say Y and read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called 3c505.
config EL16
@@ -655,8 +652,7 @@ config EL16
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called 3c507.
config EL3
@@ -671,8 +667,7 @@ config EL3
setup disk to disable Plug & Play mode, and to select the default
media type.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called 3c509.
config 3C515
@@ -683,8 +678,7 @@ config 3C515
network card, say Y and read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called 3c515.
config ELMC
@@ -695,8 +689,7 @@ config ELMC
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called 3c523.
config ELMC_II
@@ -707,8 +700,7 @@ config ELMC_II
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called 3c527.
config VORTEX
@@ -731,8 +723,7 @@ config VORTEX
<file:Documentation/networking/vortex.txt> and in the comments at
the beginning of <file:drivers/net/3c59x.c>.
- To compile this support as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>.
+ To compile this support as a module, choose M here.
config TYPHOON
tristate "3cr990 series \"Typhoon\" support"
@@ -749,8 +740,7 @@ config TYPHOON
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called typhoon.
config LANCE
@@ -787,8 +777,7 @@ config WD80x3
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called wd.
config ULTRAMCA
@@ -800,8 +789,7 @@ config ULTRAMCA
an MCA based system (PS/2), say Y and read the Ethernet-HOWTO,
available from <http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called smc-mca.
config ULTRA
@@ -820,8 +808,7 @@ config ULTRA
this but keep it in mind if you have such a SCSI card and have
problems.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called smc-ultra.
config ULTRA32
@@ -833,8 +820,7 @@ config ULTRA32
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called smc-ultra32.
config BFIN_MAC
@@ -855,7 +841,7 @@ config BFIN_MAC_USE_L1
depends on BFIN_MAC && BF537
default y
help
- To get maximum network performace, you should use L1 memory as rx/tx buffers.
+ To get maximum network performance, you should use L1 memory as rx/tx buffers.
Say N here if you want to reserve L1 memory for other uses.
config BFIN_TX_DESC_NUM
@@ -895,8 +881,7 @@ config SMC9194
<file:Documentation/networking/smc9.txt> and the Ethernet-HOWTO,
available from <http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called smc9194.
config SMC91X
@@ -914,8 +899,7 @@ config SMC91X
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called smc91x. If you want to compile it as a
- module, say M here and read <file:Documentation/kbuild/modules.txt>
- as well as <file:Documentation/networking/net-modules.txt>.
+ module, say M here and read <file:Documentation/kbuild/modules.txt>.
config NET_NETX
tristate "NetX Ethernet support"
@@ -924,8 +908,7 @@ config NET_NETX
help
This is support for the Hilscher netX builtin Ethernet ports
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called netx-eth.
config DM9000
@@ -936,9 +919,8 @@ config DM9000
---help---
Support for DM9000 chipset.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will be
- called dm9000.
+ To compile this driver as a module, choose M here. The module
+ will be called dm9000.
config SMC911X
tristate "SMSC LAN911[5678] support"
@@ -978,8 +960,7 @@ config NI5010
<http://www.tldp.org/docs.html#howto>. Note that this is still
experimental code.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called ni5010.
config NI52
@@ -990,8 +971,7 @@ config NI52
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called ni52.
config NI65
@@ -1002,8 +982,7 @@ config NI65
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called ni65.
source "drivers/net/tulip/Kconfig"
@@ -1017,8 +996,7 @@ config AT1700
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called at1700.
config DEPCA
@@ -1031,8 +1009,7 @@ config DEPCA
<http://www.tldp.org/docs.html#howto> as well as
<file:drivers/net/depca.c>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called depca.
config HP100
@@ -1043,8 +1020,7 @@ config HP100
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called hp100.
config NET_ISA
@@ -1073,8 +1049,7 @@ config E2100
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called e2100.
config EWRK3
@@ -1088,8 +1063,7 @@ config EWRK3
well as the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called ewrk3.
config EEXPRESS
@@ -1103,8 +1077,7 @@ config EEXPRESS
because the driver was very unreliable. We now have a new driver
that should do better.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called eexpress.
config EEXPRESS_PRO
@@ -1117,8 +1090,7 @@ config EEXPRESS_PRO
driver. Please read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called eepro.
config HPLAN_PLUS
@@ -1130,8 +1102,7 @@ config HPLAN_PLUS
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called hp-plus.
config HPLAN
@@ -1143,8 +1114,7 @@ config HPLAN
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called hp.
config LP486E
@@ -1163,8 +1133,7 @@ config ETH16I
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called eth16i.
config NE2000
@@ -1184,8 +1153,7 @@ config NE2000
laptops), say N here and Y to "NE/2 (ne2000 MCA version) support",
below.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called ne.
config ZNET
@@ -1206,8 +1174,7 @@ config SEEQ8005
is for you, read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called seeq8005.
config NE2_MCA
@@ -1219,8 +1186,7 @@ config NE2_MCA
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called ne2.
config IBMLANA
@@ -1231,8 +1197,7 @@ config IBMLANA
CONFIG_MCA to use this driver. It is both available as an in-kernel
driver and as a module.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The only
+ To compile this driver as a module, choose M here. The only
currently supported card is the IBM LAN Adapter/A for Ethernet. It
will both support 16K and 32K memory windows, however a 32K window
gives a better security against packet losses. Usage of multiple
@@ -1246,8 +1211,7 @@ config IBMVETH
This driver supports virtual ethernet adapters on newer IBM iSeries
and pSeries systems.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called ibmveth.
source "drivers/net/ibm_emac/Kconfig"
@@ -1277,8 +1241,7 @@ config PCNET32
answer Y here and read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called pcnet32.
config PCNET32_NAPI
@@ -1293,9 +1256,6 @@ config PCNET32_NAPI
deployed on potentially unfriendly networks (e.g. in a firewall),
then say Y here.
- See <file:Documentation/networking/NAPI_HOWTO.txt> for more
- information.
-
If in doubt, say N.
config AMD8111_ETH
@@ -1308,12 +1268,11 @@ config AMD8111_ETH
answer Y here and read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called amd8111e.
config AMD8111E_NAPI
- bool "Enable NAPI support"
+ bool "Use RX polling (NAPI)"
depends on AMD8111_ETH
help
NAPI is a new driver API designed to reduce CPU and interrupt load
@@ -1324,9 +1283,6 @@ config AMD8111E_NAPI
deployed on potentially unfriendly networks (e.g. in a firewall),
then say Y here.
- See <file:Documentation/networking/NAPI_HOWTO.txt> for more
- information.
-
If in doubt, say N.
config ADAPTEC_STARFIRE
@@ -1355,9 +1311,6 @@ config ADAPTEC_STARFIRE_NAPI
deployed on potentially unfriendly networks (e.g. in a firewall),
then say Y here.
- See <file:Documentation/networking/NAPI_HOWTO.txt> for more
- information.
-
If in doubt, say N.
config AC3200
@@ -1369,8 +1322,7 @@ config AC3200
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called ac3200.
config APRICOT
@@ -1381,9 +1333,8 @@ config APRICOT
read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will be
- called apricot.
+ To compile this driver as a module, choose M here. The module
+ will be called apricot.
config B44
tristate "Broadcom 440x/47xx ethernet support"
@@ -1395,9 +1346,8 @@ config B44
or M and read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will be
- called b44.
+ To compile this driver as a module, choose M here. The module
+ will be called b44.
# Auto-select SSB PCI-HOST support, if possible
config B44_PCI_AUTOSELECT
@@ -1426,12 +1376,11 @@ config FORCEDETH
read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will be
- called forcedeth.
+ To compile this driver as a module, choose M here. The module
+ will be called forcedeth.
config FORCEDETH_NAPI
- bool "Use Rx and Tx Polling (NAPI) (EXPERIMENTAL)"
+ bool "Use Rx Polling (NAPI) (EXPERIMENTAL)"
depends on FORCEDETH && EXPERIMENTAL
help
NAPI is a new driver API designed to reduce CPU and interrupt load
@@ -1442,9 +1391,6 @@ config FORCEDETH_NAPI
deployed on potentially unfriendly networks (e.g. in a firewall),
then say Y here.
- See <file:Documentation/networking/NAPI_HOWTO.txt> for more
- information.
-
If in doubt, say N.
config CS89x0
@@ -1457,9 +1403,8 @@ config CS89x0
<http://www.tldp.org/docs.html#howto> as well as
<file:Documentation/networking/cs89x0.txt>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will be
- called cs89x0.
+ To compile this driver as a module, choose M here. The module
+ will be called cs89x0.
config TC35815
tristate "TOSHIBA TC35815 Ethernet support"
@@ -1475,8 +1420,7 @@ config EEPRO100
card, say Y and read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called eepro100.
@@ -1503,8 +1447,7 @@ config E100
More specific information on configuring the driver is in
<file:Documentation/networking/e100.txt>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called e100.
config LNE390
@@ -1516,8 +1459,7 @@ config LNE390
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called lne390.
config FEALNX
@@ -1557,8 +1499,7 @@ config NE2K_PCI
NetVin NV5000SC Via 86C926 SureCom NE34 Winbond
Holtek HT80232 Holtek HT80229
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called ne2k-pci.
config NE3210
@@ -1571,8 +1512,7 @@ config NE3210
<http://www.tldp.org/docs.html#howto>. Note that this driver
will NOT WORK for NE3200 cards as they are completely different.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called ne3210.
config ES3210
@@ -1584,8 +1524,7 @@ config ES3210
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called es3210.
config 8139CP
@@ -1715,8 +1654,7 @@ config TLAN
Compaq NetFlex and Olicom cards. Please read the file
<file:Documentation/networking/tlan.txt> for more details.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called tlan.
Please email feedback to <torben.mathiasen@compaq.com>.
@@ -1756,9 +1694,6 @@ config VIA_RHINE_NAPI
deployed on potentially unfriendly networks (e.g. in a firewall),
then say Y here.
- See <file:Documentation/networking/NAPI_HOWTO.txt> for more
- information.
-
config LAN_SAA9730
bool "Philips SAA9730 Ethernet support"
depends on NET_PCI && PCI && MIPS_ATLAS
@@ -1780,6 +1715,15 @@ config SC92031
To compile this driver as a module, choose M here: the module
will be called sc92031. This is recommended.
+config CPMAC
+ tristate "TI AR7 CPMAC Ethernet support (EXPERIMENTAL)"
+ depends on NET_ETHERNET && EXPERIMENTAL && AR7
+ select PHYLIB
+ select FIXED_PHY
+ select FIXED_MII_100_FDX
+ help
+ TI AR7 CPMAC Ethernet support
+
config NET_POCKET
bool "Pocket and portable adapters"
depends on PARPORT
@@ -1886,6 +1830,28 @@ config FEC2
Say Y here if you want to use the second built-in 10/100 Fast
ethernet controller on some Motorola ColdFire processors.
+config FEC_MPC52xx
+ tristate "MPC52xx FEC driver"
+ depends on PPC_MERGE && PPC_MPC52xx && PPC_BESTCOMM_FEC
+ select CRC32
+ select PHYLIB
+ ---help---
+ This option enables support for the MPC5200's on-chip
+ Fast Ethernet Controller
+ If compiled as module, it will be called 'fec_mpc52xx.ko'.
+
+config FEC_MPC52xx_MDIO
+ bool "MPC52xx FEC MDIO bus driver"
+ depends on FEC_MPC52xx
+ default y
+ ---help---
+ The MPC5200's FEC can connect to the Ethernet either with
+ an external MII PHY chip or 10 Mbps 7-wire interface
+ (Motorola? industry standard).
+ If your board uses an external PHY connected to FEC, enable this.
+ If not sure, enable.
+ If compiled as module, it will be called 'fec_mpc52xx_phy.ko'.
+
config NE_H8300
tristate "NE2000 compatible support for H8/300"
depends on H8300
@@ -1978,8 +1944,7 @@ config E1000
More specific information on configuring the driver is in
<file:Documentation/networking/e1000.txt>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called e1000.
config E1000_NAPI
@@ -1994,9 +1959,6 @@ config E1000_NAPI
deployed on potentially unfriendly networks (e.g. in a firewall),
then say Y here.
- See <file:Documentation/networking/NAPI_HOWTO.txt> for more
- information.
-
If in doubt, say N.
config E1000_DISABLE_PACKET_SPLIT
@@ -2027,8 +1989,7 @@ config E1000E
More specific information on configuring the driver is in
<file:Documentation/networking/e1000e.txt>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called e1000e.
source "drivers/net/ixp2000/Kconfig"
@@ -2061,8 +2022,7 @@ config HAMACHI
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will be
+ To compile this driver as a module, choose M here. The module will be
called hamachi.
config YELLOWFIN
@@ -2090,7 +2050,7 @@ config R8169
will be called r8169. This is recommended.
config R8169_NAPI
- bool "Use Rx and Tx Polling (NAPI) (EXPERIMENTAL)"
+ bool "Use Rx Polling (NAPI) (EXPERIMENTAL)"
depends on R8169 && EXPERIMENTAL
help
NAPI is a new driver API designed to reduce CPU and interrupt load
@@ -2101,9 +2061,6 @@ config R8169_NAPI
deployed on potentially unfriendly networks (e.g. in a firewall),
then say Y here.
- See <file:Documentation/networking/NAPI_HOWTO.txt> for more
- information.
-
If in doubt, say N.
config R8169_VLAN
@@ -2164,6 +2121,16 @@ config SKGE
To compile this driver as a module, choose M here: the module
will be called skge. This is recommended.
+config SKGE_DEBUG
+ bool "Debugging interface"
+ depends on SKGE && DEBUG_FS
+ help
+ This option adds the ability to dump driver state for debugging.
+ The file debugfs/skge/ethX displays the state of the internal
+ transmit and receive rings.
+
+ If unsure, say N.
+
config SKY2
tristate "SysKonnect Yukon2 support"
depends on PCI
@@ -2345,7 +2312,7 @@ config GIANFAR
and MPC86xx family of chips, and the FEC on the 8540.
config GFAR_NAPI
- bool "NAPI Support"
+ bool "Use Rx Polling (NAPI)"
depends on GIANFAR
config UCC_GETH
@@ -2357,7 +2324,7 @@ config UCC_GETH
which is available on some Freescale SOCs.
config UGETH_NAPI
- bool "NAPI Support"
+ bool "Use Rx Polling (NAPI)"
depends on UCC_GETH
config UGETH_MAGIC_PACKET
@@ -2373,13 +2340,16 @@ config UGETH_TX_ON_DEMAND
depends on UCC_GETH
config MV643XX_ETH
- tristate "MV-643XX Ethernet support"
- depends on MV64360 || MV64X60 || (PPC_MULTIPLATFORM && PPC32)
+ tristate "Marvell Discovery (643XX) and Orion ethernet support"
+ depends on MV64360 || MV64X60 || (PPC_MULTIPLATFORM && PPC32) || ARCH_ORION
select MII
help
- This driver supports the gigabit Ethernet on the Marvell MV643XX
- chipset which is used in the Momenco Ocelot C and Jaguar ATX and
- Pegasos II, amongst other PPC and MIPS boards.
+ This driver supports the gigabit ethernet MACs in the
+ Marvell Discovery PPC/MIPS chipset family (MV643XX) and
+ in the Marvell Orion ARM SoC family.
+
+ Some boards that use the Discovery chipset are the Momenco
+ Ocelot C and Jaguar ATX and Pegasos II.
config QLA3XXX
tristate "QLogic QLA3XXX Network Driver Support"
@@ -2475,7 +2445,7 @@ config CHELSIO_T3
config EHEA
tristate "eHEA Ethernet support"
- depends on IBMEBUS
+ depends on IBMEBUS && INET
select INET_LRO
---help---
This driver supports the IBM pSeries eHEA ethernet adapter.
@@ -2501,8 +2471,7 @@ config IXGBE
More specific information on configuring the driver is in
<file:Documentation/networking/ixgbe.txt>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called ixgbe.
config IXGB
@@ -2524,8 +2493,7 @@ config IXGB
More specific information on configuring the driver is in
<file:Documentation/networking/ixgb.txt>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called ixgb.
config IXGB_NAPI
@@ -2540,9 +2508,6 @@ config IXGB_NAPI
deployed on potentially unfriendly networks (e.g. in a firewall),
then say Y here.
- See <file:Documentation/networking/NAPI_HOWTO.txt> for more
- information.
-
If in doubt, say N.
config S2IO
@@ -2565,14 +2530,11 @@ config S2IO_NAPI
deployed on potentially unfriendly networks (e.g. in a firewall),
then say Y here.
- See <file:Documentation/networking/NAPI_HOWTO.txt> for more
- information.
-
If in doubt, say N.
config MYRI10GE
tristate "Myricom Myri-10G Ethernet support"
- depends on PCI
+ depends on PCI && INET
select FW_LOADER
select CRC32
select INET_LRO
@@ -2584,8 +2546,7 @@ config MYRI10GE
<http://www.myri.com/scs/download-Myri10GE.html>
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called myri10ge.
config NETXEN_NIC
@@ -2809,10 +2770,9 @@ config PLIP
with the PLIP support in Linux versions 1.0.x. This option enlarges
your kernel by about 8 KB.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will be
- called plip. If unsure, say Y or M, in case you buy a laptop
- later.
+ To compile this driver as a module, choose M here. The module
+ will be called plip. If unsure, say Y or M, in case you buy
+ a laptop later.
config PPP
tristate "PPP (point-to-point protocol) support"
@@ -2842,8 +2802,7 @@ config PPP
If you said Y to "Version information on all symbols" above, then
you cannot compile the PPP driver into the kernel; you can then only
compile it as a module. To compile this driver as a module, choose M
- here and read <file:Documentation/networking/net-modules.txt>.
- The module will be called ppp_generic.
+ here. The module will be called ppp_generic.
config PPP_MULTILINK
bool "PPP multilink support (EXPERIMENTAL)"
@@ -3004,9 +2963,8 @@ config SLIP
<http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html>). SLIP
support will enlarge your kernel by about 4 KB. If unsure, say N.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will be
- called slip.
+ To compile this driver as a module, choose M here. The module
+ will be called slip.
config SLIP_COMPRESSED
bool "CSLIP compressed headers"
@@ -3108,4 +3066,10 @@ config NETPOLL_TRAP
config NET_POLL_CONTROLLER
def_bool NETPOLL
+config VIRTIO_NET
+ tristate "Virtio network driver (EXPERIMENTAL)"
+ depends on EXPERIMENTAL && VIRTIO
+ ---help---
+ This is the virtual network driver for lguest. Say Y or M.
+
endif # NETDEVICES
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index d2e0f35da42e..0e5fde4a1b2c 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -96,6 +96,10 @@ obj-$(CONFIG_SHAPER) += shaper.o
obj-$(CONFIG_HP100) += hp100.o
obj-$(CONFIG_SMC9194) += smc9194.o
obj-$(CONFIG_FEC) += fec.o
+obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o
+ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y)
+ obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx_phy.o
+endif
obj-$(CONFIG_68360_ENET) += 68360enet.o
obj-$(CONFIG_WD80x3) += wd.o 8390.o
obj-$(CONFIG_EL2) += 3c503.o 8390.o
@@ -159,6 +163,7 @@ obj-$(CONFIG_8139CP) += 8139cp.o
obj-$(CONFIG_8139TOO) += 8139too.o
obj-$(CONFIG_ZNET) += znet.o
obj-$(CONFIG_LAN_SAA9730) += saa9730.o
+obj-$(CONFIG_CPMAC) += cpmac.o
obj-$(CONFIG_DEPCA) += depca.o
obj-$(CONFIG_EWRK3) += ewrk3.o
obj-$(CONFIG_ATP) += atp.o
@@ -182,7 +187,6 @@ obj-$(CONFIG_ZORRO8390) += zorro8390.o
obj-$(CONFIG_HPLANCE) += hplance.o 7990.o
obj-$(CONFIG_MVME147_NET) += mvme147.o 7990.o
obj-$(CONFIG_EQUALIZER) += eql.o
-obj-$(CONFIG_LGUEST_NET) += lguest_net.o
obj-$(CONFIG_MIPS_JAZZ_SONIC) += jazzsonic.o
obj-$(CONFIG_MIPS_AU1X00_ENET) += au1000_eth.o
obj-$(CONFIG_MIPS_SIM_NET) += mipsnet.o
@@ -242,3 +246,4 @@ obj-$(CONFIG_FS_ENET) += fs_enet/
obj-$(CONFIG_NETXEN_NIC) += netxen/
obj-$(CONFIG_NIU) += niu.o
+obj-$(CONFIG_VIRTIO_NET) += virtio_net.o
diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c
index 1cc74ec88a58..eebf5bb2b03a 100644
--- a/drivers/net/amd8111e.c
+++ b/drivers/net/amd8111e.c
@@ -1111,7 +1111,7 @@ static struct net_device_stats *amd8111e_get_stats(struct net_device * dev)
return new_stats;
}
-/* This function recalculate the interupt coalescing mode on every interrupt
+/* This function recalculate the interrupt coalescing mode on every interrupt
according to the datarate and the packet rate.
*/
static int amd8111e_calc_coalesce(struct net_device *dev)
diff --git a/drivers/net/arcnet/Kconfig b/drivers/net/arcnet/Kconfig
index 4030274fe788..3b2f7f115464 100644
--- a/drivers/net/arcnet/Kconfig
+++ b/drivers/net/arcnet/Kconfig
@@ -19,8 +19,7 @@ menuconfig ARCNET
from <http://www.tldp.org/docs.html#howto>(even though ARCnet
is not really Ethernet).
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called arcnet.
if ARCNET
@@ -81,8 +80,7 @@ config ARCNET_COM90xx
have always used the old ARCnet driver without knowing what type of
card you had, this is probably the one for you.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called com90xx.
config ARCNET_COM90xxIO
@@ -93,8 +91,7 @@ config ARCNET_COM90xxIO
the normal driver. Only use it if your card doesn't support shared
memory.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called com90io.
config ARCNET_RIM_I
@@ -105,8 +102,7 @@ config ARCNET_RIM_I
driver is completely untested, so if you have one of these cards,
please mail <dwmw2@infradead.org>, especially if it works!
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called arc-rimi.
config ARCNET_COM20020
@@ -116,8 +112,7 @@ config ARCNET_COM20020
things as promiscuous mode, so packet sniffing is possible, and
extra diagnostic information.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called com20020.
config ARCNET_COM20020_ISA
diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c
index 3fa3bccd1adb..10f3a196be32 100644
--- a/drivers/net/ariadne.c
+++ b/drivers/net/ariadne.c
@@ -1,7 +1,7 @@
/*
* Amiga Linux/m68k Ariadne Ethernet Driver
*
- * © Copyright 1995-2003 by Geert Uytterhoeven (geert@linux-m68k.org)
+ * © Copyright 1995-2003 by Geert Uytterhoeven (geert@linux-m68k.org)
* Peter De Schrijver (p2@mind.be)
*
* ---------------------------------------------------------------------------
diff --git a/drivers/net/ariadne.h b/drivers/net/ariadne.h
index f7913d5a39f1..bb613f292e04 100644
--- a/drivers/net/ariadne.h
+++ b/drivers/net/ariadne.h
@@ -1,7 +1,7 @@
/*
* Amiga Linux/m68k Ariadne Ethernet Driver
*
- * © Copyright 1995 by Geert Uytterhoeven (geert@linux-m68k.org)
+ * © Copyright 1995 by Geert Uytterhoeven (geert@linux-m68k.org)
* Peter De Schrijver
* (Peter.DeSchrijver@linux.cc.kuleuven.ac.be)
*
diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c
index 7f016f3d5bf0..91a6590d107b 100644
--- a/drivers/net/arm/ep93xx_eth.c
+++ b/drivers/net/arm/ep93xx_eth.c
@@ -417,7 +417,7 @@ static irqreturn_t ep93xx_irq(int irq, void *dev_id)
if (status & REG_INTSTS_RX) {
spin_lock(&ep->rx_lock);
- if (likely(__netif_rx_schedule_prep(dev, &ep->napi))) {
+ if (likely(netif_rx_schedule_prep(dev, &ep->napi))) {
wrl(ep, REG_INTEN, REG_INTEN_TX);
__netif_rx_schedule(dev, &ep->napi);
}
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index b46c5d8a77bd..504b7ce2747d 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -54,13 +54,16 @@
#include <linux/delay.h>
#include <linux/crc32.h>
#include <linux/phy.h>
+
+#include <asm/cpu.h>
#include <asm/mipsregs.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/processor.h>
-#include <asm/mach-au1x00/au1000.h>
-#include <asm/cpu.h>
+#include <au1000.h>
+#include <prom.h>
+
#include "au1000_eth.h"
#ifdef AU1000_ETH_DEBUG
@@ -96,11 +99,6 @@ static void mdio_write(struct net_device *, int, int, u16);
static void au1000_adjust_link(struct net_device *);
static void enable_mac(struct net_device *, int);
-// externs
-extern int get_ethernet_addr(char *ethernet_addr);
-extern void str2eaddr(unsigned char *ea, unsigned char *str);
-extern char * prom_getcmdline(void);
-
/*
* Theory of operation
*
@@ -544,7 +542,7 @@ static struct {
static int num_ifs;
/*
- * Setup the base address and interupt of the Au1xxx ethernet macs
+ * Setup the base address and interrupt of the Au1xxx ethernet macs
* based on cpu type and whether the interface is enabled in sys_pinfunc
* register. The last interface is enabled if SYS_PF_NI2 (bit 4) is 0.
*/
@@ -619,7 +617,6 @@ static struct net_device * au1000_probe(int port_num)
struct au1000_private *aup = NULL;
struct net_device *dev = NULL;
db_dest_t *pDB, *pDBfree;
- char *pmac, *argptr;
char ethaddr[6];
int irq, i, err;
u32 base, macen;
@@ -677,21 +674,12 @@ static struct net_device * au1000_probe(int port_num)
au_macs[port_num] = aup;
if (port_num == 0) {
- /* Check the environment variables first */
- if (get_ethernet_addr(ethaddr) == 0)
+ if (prom_get_ethernet_addr(ethaddr) == 0)
memcpy(au1000_mac_addr, ethaddr, sizeof(au1000_mac_addr));
else {
- /* Check command line */
- argptr = prom_getcmdline();
- if ((pmac = strstr(argptr, "ethaddr=")) == NULL)
- printk(KERN_INFO "%s: No MAC address found\n",
- dev->name);
+ printk(KERN_INFO "%s: No MAC address found\n",
+ dev->name);
/* Use the hard coded MAC addresses */
- else {
- str2eaddr(ethaddr, pmac + strlen("ethaddr="));
- memcpy(au1000_mac_addr, ethaddr,
- sizeof(au1000_mac_addr));
- }
}
setup_hw_rings(aup, MAC0_RX_DMA_ADDR, MAC0_TX_DMA_ADDR);
diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c
index 9fe0517cf893..7495a9ee8f4b 100644
--- a/drivers/net/ax88796.c
+++ b/drivers/net/ax88796.c
@@ -900,7 +900,7 @@ static int ax_probe(struct platform_device *pdev)
ax->map2 = ioremap(res->start, size);
if (ax->map2 == NULL) {
- dev_err(&pdev->dev, "cannot map reset register");
+ dev_err(&pdev->dev, "cannot map reset register\n");
ret = -ENXIO;
goto exit_mem2;
}
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c
index 53fe7ded5d50..084acfd6fc5f 100644
--- a/drivers/net/bfin_mac.c
+++ b/drivers/net/bfin_mac.c
@@ -371,7 +371,6 @@ static void bf537_adjust_link(struct net_device *dev)
if (phydev->speed != lp->old_speed) {
#if defined(CONFIG_BFIN_MAC_RMII)
u32 opmode = bfin_read_EMAC_OPMODE();
- bf537mac_disable();
switch (phydev->speed) {
case 10:
opmode |= RMII_10;
@@ -386,7 +385,6 @@ static void bf537_adjust_link(struct net_device *dev)
break;
}
bfin_write_EMAC_OPMODE(opmode);
- bf537mac_enable();
#endif
new_state = 1;
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 78ed633ceb82..da767d3d5af5 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -26,7 +26,7 @@
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/dma-mapping.h>
-#include <asm/bitops.h>
+#include <linux/bitops.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <linux/delay.h>
@@ -56,8 +56,8 @@
#define DRV_MODULE_NAME "bnx2"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "1.6.7"
-#define DRV_MODULE_RELDATE "October 10, 2007"
+#define DRV_MODULE_VERSION "1.6.8"
+#define DRV_MODULE_RELDATE "October 17, 2007"
#define RUN_AT(x) (jiffies + (x))
@@ -3079,14 +3079,18 @@ bnx2_set_power_state(struct bnx2 *bp, pci_power_t state)
autoneg = bp->autoneg;
advertising = bp->advertising;
- bp->autoneg = AUTONEG_SPEED;
- bp->advertising = ADVERTISED_10baseT_Half |
- ADVERTISED_10baseT_Full |
- ADVERTISED_100baseT_Half |
- ADVERTISED_100baseT_Full |
- ADVERTISED_Autoneg;
+ if (bp->phy_port == PORT_TP) {
+ bp->autoneg = AUTONEG_SPEED;
+ bp->advertising = ADVERTISED_10baseT_Half |
+ ADVERTISED_10baseT_Full |
+ ADVERTISED_100baseT_Half |
+ ADVERTISED_100baseT_Full |
+ ADVERTISED_Autoneg;
+ }
- bnx2_setup_copper_phy(bp);
+ spin_lock_bh(&bp->phy_lock);
+ bnx2_setup_phy(bp, bp->phy_port);
+ spin_unlock_bh(&bp->phy_lock);
bp->autoneg = autoneg;
bp->advertising = advertising;
@@ -3097,10 +3101,16 @@ bnx2_set_power_state(struct bnx2 *bp, pci_power_t state)
/* Enable port mode. */
val &= ~BNX2_EMAC_MODE_PORT;
- val |= BNX2_EMAC_MODE_PORT_MII |
- BNX2_EMAC_MODE_MPKT_RCVD |
+ val |= BNX2_EMAC_MODE_MPKT_RCVD |
BNX2_EMAC_MODE_ACPI_RCVD |
BNX2_EMAC_MODE_MPKT;
+ if (bp->phy_port == PORT_TP)
+ val |= BNX2_EMAC_MODE_PORT_MII;
+ else {
+ val |= BNX2_EMAC_MODE_PORT_GMII;
+ if (bp->line_speed == SPEED_2500)
+ val |= BNX2_EMAC_MODE_25G_MODE;
+ }
REG_WR(bp, BNX2_EMAC_MODE, val);
@@ -6428,7 +6438,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
/* enable device (incl. PCI PM wakeup), and bus-mastering */
rc = pci_enable_device(pdev);
if (rc) {
- dev_err(&pdev->dev, "Cannot enable PCI device, aborting.");
+ dev_err(&pdev->dev, "Cannot enable PCI device, aborting.\n");
goto err_out;
}
diff --git a/drivers/net/bnx2_fw2.h b/drivers/net/bnx2_fw2.h
index 5bd52bead9bf..4b129b7cbfad 100644
--- a/drivers/net/bnx2_fw2.h
+++ b/drivers/net/bnx2_fw2.h
@@ -15,3248 +15,3270 @@
*/
static u8 bnx2_COM_b09FwText[] = {
-/* 0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, */
- 0xdc, 0x5b,
- 0x6d, 0x70, 0x5c, 0xd5, 0x79, 0x7e, 0xef, 0xd9, 0xbb, 0xf2, 0x5a, 0x92,
- 0xe5, 0x6b, 0x79, 0x23, 0x16, 0x4b, 0xc0, 0xae, 0x75, 0x6d, 0x69, 0xb0,
- 0x43, 0x16, 0xa1, 0x80, 0x9a, 0xd9, 0xc0, 0xb2, 0x2b, 0x33, 0x9e, 0x0c,
- 0x69, 0x64, 0x50, 0x80, 0xb6, 0x4c, 0x46, 0xec, 0x1a, 0x9a, 0x4e, 0x87,
- 0xd6, 0xa6, 0x6e, 0x9b, 0xc9, 0x34, 0x78, 0x47, 0x1f, 0x8d, 0xa7, 0x15,
- 0xba, 0x06, 0x1b, 0xd9, 0xd3, 0xd0, 0xa0, 0x6a, 0x71, 0xf1, 0x8f, 0x8d,
- 0xaf, 0xf9, 0x48, 0xaa, 0x4c, 0x4d, 0xa5, 0x18, 0x48, 0x69, 0xa7, 0x4d,
- 0xfb, 0xa3, 0x9e, 0xa1, 0x5f, 0x84, 0x32, 0xfd, 0xc1, 0x74, 0xda, 0x4e,
- 0x3a, 0x24, 0x53, 0x08, 0x84, 0xed, 0xf3, 0x9c, 0x7b, 0xee, 0xea, 0x6a,
- 0x25, 0x7f, 0xf1, 0x91, 0x1f, 0xd5, 0xcc, 0xfa, 0xde, 0xf3, 0xfd, 0x9e,
- 0xf7, 0xbc, 0xef, 0xf3, 0x7e, 0xdc, 0xe3, 0x4f, 0x8a, 0xb4, 0x8a, 0xf9,
- 0xdb, 0x80, 0x5f, 0xfa, 0xc1, 0xdf, 0x2c, 0x5f, 0x37, 0x78, 0xdd, 0x0d,
- 0x78, 0xbd, 0x41, 0xc5, 0xec, 0x18, 0xeb, 0xf9, 0x4f, 0x12, 0xbf, 0x01,
- 0xf3, 0xbe, 0xd6, 0x9f, 0x83, 0xdf, 0x9b, 0x68, 0x1c, 0xfb, 0x0f, 0x11,
- 0xeb, 0x3c, 0x7d, 0xa2, 0x7f, 0xf5, 0xfa, 0x85, 0xdb, 0x15, 0x69, 0xb9,
- 0x40, 0x7b, 0x2c, 0x58, 0x52, 0xd3, 0xcc, 0x9f, 0x24, 0x54, 0x6e, 0xec,
- 0xe1, 0x82, 0x2b, 0x89, 0x58, 0x6e, 0xf7, 0xc1, 0xb2, 0x2b, 0x92, 0xaf,
- 0xed, 0x48, 0x17, 0xe5, 0x67, 0xf5, 0x4a, 0xd2, 0x16, 0xd6, 0x5f, 0x95,
- 0x7b, 0xef, 0xc9, 0x17, 0x6e, 0xca, 0xfc, 0x68, 0x2e, 0x26, 0x09, 0x27,
- 0xf7, 0xbc, 0x38, 0xdb, 0x25, 0xd1, 0x83, 0x31, 0x4f, 0xf4, 0xe5, 0x2d,
- 0xe9, 0x08, 0xe7, 0x7a, 0xb3, 0xfe, 0x42, 0x9f, 0x54, 0xb6, 0xe4, 0x12,
- 0xa2, 0x72, 0xdb, 0x5e, 0x2d, 0xc4, 0x9c, 0xb1, 0x58, 0xce, 0x91, 0x45,
- 0x5f, 0x46, 0xee, 0x9f, 0x96, 0x44, 0x22, 0xf7, 0xe5, 0xc4, 0xba, 0x6d,
- 0x92, 0xb0, 0x73, 0x4b, 0x0f, 0xff, 0xbe, 0x7b, 0xb0, 0xae, 0x5c, 0xb7,
- 0x7f, 0x5e, 0xda, 0x87, 0x4e, 0x0c, 0xa2, 0xbd, 0x96, 0xe9, 0x17, 0xb9,
- 0x49, 0x94, 0x5b, 0x69, 0x8f, 0xb9, 0x09, 0x29, 0xf8, 0xae, 0x14, 0x7d,
- 0x91, 0xbf, 0xac, 0x59, 0x72, 0xc2, 0xed, 0x92, 0xf9, 0x9d, 0xef, 0xd5,
- 0xf3, 0xa0, 0xe5, 0xfb, 0xee, 0xd2, 0xc3, 0x93, 0x2e, 0xe9, 0x3d, 0x90,
- 0x08, 0xe8, 0xdd, 0xbb, 0xae, 0xec, 0xda, 0x32, 0x5e, 0x63, 0xdd, 0xa8,
- 0x62, 0x5d, 0x3c, 0x97, 0x68, 0x3d, 0xe1, 0xb6, 0x9b, 0xba, 0x57, 0x6f,
- 0x29, 0x60, 0xbe, 0x89, 0x1a, 0xfb, 0xe6, 0xaf, 0x2f, 0xbb, 0x49, 0x53,
- 0xbf, 0x70, 0x63, 0xc1, 0x4d, 0xa1, 0xbe, 0xc7, 0xb4, 0x8d, 0x3d, 0x58,
- 0x76, 0x5d, 0xd3, 0xf6, 0x76, 0xac, 0xe0, 0xf6, 0x9b, 0xfa, 0xf7, 0x6e,
- 0x2e, 0xbb, 0x3b, 0x4d, 0x7d, 0x0f, 0xe6, 0xca, 0x9a, 0xfa, 0x85, 0x7b,
- 0xca, 0xee, 0xa0, 0xa9, 0xdf, 0x7d, 0x73, 0xc1, 0x1d, 0x32, 0xf5, 0x89,
- 0xa1, 0xb2, 0x9b, 0x43, 0xfd, 0x97, 0x13, 0x6a, 0x9b, 0x23, 0x53, 0xb5,
- 0x34, 0x7e, 0x79, 0xb4, 0x0d, 0xa3, 0x6e, 0x37, 0x7e, 0xb7, 0xe3, 0xf7,
- 0xc8, 0x46, 0xe9, 0x18, 0xc1, 0xf3, 0xbf, 0xba, 0x03, 0xde, 0x81, 0x47,
- 0x5e, 0x42, 0x5e, 0x8f, 0xa5, 0xe4, 0x85, 0xbe, 0xd7, 0xc1, 0x43, 0x47,
- 0x4e, 0xfb, 0x62, 0x8d, 0xf4, 0xa5, 0xc0, 0xbb, 0xa4, 0x3c, 0xe3, 0xb7,
- 0x49, 0xec, 0xb1, 0x18, 0x78, 0xf3, 0xcb, 0x52, 0x4a, 0x26, 0x64, 0xd3,
- 0xac, 0x25, 0x5b, 0x07, 0x12, 0x92, 0x77, 0xb8, 0x36, 0x4e, 0x7b, 0x26,
- 0x29, 0xb1, 0xd9, 0xfc, 0x66, 0x25, 0xdb, 0x9c, 0xa2, 0x54, 0xc0, 0xbb,
- 0x57, 0x29, 0x97, 0x68, 0x4b, 0x4b, 0x71, 0xfa, 0x5a, 0x19, 0x73, 0x48,
- 0xd7, 0x1f, 0x5c, 0x15, 0xac, 0x95, 0xb0, 0x0a, 0xc7, 0x46, 0x65, 0xca,
- 0x6b, 0xb7, 0x8a, 0xc7, 0x6e, 0x96, 0x42, 0x56, 0x92, 0x18, 0x97, 0x2a,
- 0xa1, 0xa5, 0x5a, 0x1b, 0x95, 0x49, 0x4f, 0xac, 0x82, 0x47, 0x7e, 0x76,
- 0xa1, 0xbd, 0x43, 0xf7, 0x45, 0x5d, 0x4f, 0x4c, 0xcf, 0x9d, 0x40, 0xbd,
- 0x83, 0xfa, 0x4e, 0x6b, 0x58, 0xcf, 0xa1, 0xeb, 0xd3, 0x13, 0xd2, 0x2e,
- 0x4f, 0xd5, 0x92, 0xa6, 0x6f, 0xbd, 0x5e, 0xc8, 0x3a, 0xe8, 0x37, 0x2a,
- 0x13, 0x5e, 0x52, 0xc6, 0xf0, 0x1c, 0xf7, 0xb8, 0x7e, 0x0a, 0x32, 0x75,
- 0xdd, 0xc1, 0xd2, 0x51, 0x3d, 0x5f, 0x3a, 0x96, 0xe3, 0x7c, 0x3d, 0xe8,
- 0xf7, 0x12, 0xe8, 0xb2, 0xc4, 0xd6, 0x67, 0x99, 0x97, 0xd2, 0xb4, 0x05,
- 0x79, 0xc3, 0x53, 0xf3, 0x75, 0x18, 0xf4, 0xdb, 0xe2, 0x0e, 0x58, 0x52,
- 0xc6, 0x59, 0x55, 0x1c, 0x94, 0x6b, 0x0b, 0xaa, 0xe0, 0xad, 0x93, 0xa2,
- 0x9d, 0x96, 0xd8, 0x0c, 0x65, 0x69, 0x4c, 0x26, 0x30, 0x46, 0xb9, 0xec,
- 0xf3, 0x0e, 0xf6, 0x3d, 0xa6, 0xcf, 0xa1, 0x25, 0x57, 0x51, 0x45, 0xbf,
- 0x4b, 0xd4, 0xec, 0xbd, 0xf2, 0xd2, 0xb4, 0x38, 0x38, 0xc7, 0x7a, 0xc1,
- 0x9d, 0x54, 0x85, 0xa7, 0x6d, 0x89, 0xcf, 0x58, 0x32, 0xe9, 0x66, 0xa0,
- 0x01, 0x87, 0xd4, 0x2e, 0x7f, 0x01, 0xfd, 0x38, 0x0e, 0xfd, 0x6a, 0x0a,
- 0x7c, 0xe5, 0xfb, 0x0e, 0x47, 0x69, 0x79, 0x66, 0x1f, 0x9c, 0x01, 0xf6,
- 0xf1, 0x8c, 0x87, 0x33, 0xd1, 0x67, 0x94, 0xc6, 0x19, 0x89, 0x35, 0xdc,
- 0x07, 0x99, 0x3a, 0x6a, 0x4b, 0x29, 0x8b, 0x7d, 0xa1, 0x77, 0x29, 0xbb,
- 0x4c, 0xd7, 0xc4, 0x74, 0x33, 0x5d, 0x1c, 0x47, 0xba, 0x02, 0x9a, 0xc6,
- 0x8f, 0x92, 0xbe, 0x65, 0x7a, 0xa6, 0xa6, 0x43, 0x1a, 0xb9, 0x1e, 0x69,
- 0x0b, 0xe9, 0xe2, 0x38, 0xd2, 0xb5, 0x99, 0x67, 0xcd, 0x3f, 0x6b, 0x18,
- 0x74, 0x4c, 0x78, 0x36, 0xce, 0xa8, 0x5d, 0x4a, 0x4e, 0xc5, 0x9a, 0x18,
- 0xda, 0x91, 0x82, 0x36, 0x5b, 0xe3, 0x43, 0xa4, 0xd9, 0xc5, 0x39, 0xb6,
- 0xe8, 0xf3, 0x56, 0xb9, 0x49, 0xf2, 0x0e, 0xfd, 0xb9, 0x3e, 0xde, 0x6b,
- 0x8e, 0x4c, 0xea, 0xf9, 0x48, 0xd3, 0x47, 0x31, 0x0f, 0x69, 0x7d, 0x05,
- 0xb2, 0x3a, 0x08, 0x19, 0xcd, 0xca, 0x5f, 0xf8, 0x3b, 0xe5, 0xcf, 0xfc,
- 0x7e, 0xf9, 0x0e, 0xf4, 0xf6, 0xdb, 0x7e, 0x5a, 0x9e, 0xf7, 0x7b, 0xe4,
- 0x39, 0x3f, 0x25, 0xcf, 0x6a, 0xf9, 0x1d, 0x16, 0xe9, 0xa0, 0x4c, 0xa7,
- 0xa5, 0x13, 0xfa, 0xb3, 0x09, 0xba, 0xf9, 0x38, 0xf8, 0x77, 0xb4, 0x4f,
- 0xf2, 0x9b, 0x73, 0x92, 0xb8, 0x1a, 0xbf, 0x2b, 0xf0, 0xeb, 0xca, 0xd9,
- 0x5a, 0x56, 0xec, 0x1c, 0x79, 0x68, 0x4b, 0x51, 0xef, 0xd9, 0x96, 0x09,
- 0xff, 0x91, 0xab, 0x03, 0xd9, 0x15, 0x19, 0x01, 0x8f, 0xd5, 0xc0, 0x4f,
- 0xea, 0x79, 0x07, 0xfb, 0x18, 0xd8, 0xa1, 0x79, 0xaf, 0x06, 0x28, 0xb3,
- 0x69, 0xc8, 0xbd, 0x6d, 0x15, 0xbd, 0x93, 0xc0, 0x8d, 0x36, 0xab, 0x70,
- 0xa4, 0x22, 0xe5, 0x23, 0x75, 0x29, 0x67, 0xe3, 0xf2, 0x90, 0x53, 0x97,
- 0xe1, 0x6c, 0x8b, 0xec, 0x77, 0xc0, 0xfb, 0x9d, 0xbf, 0x6d, 0x85, 0x98,
- 0xfd, 0xb8, 0xff, 0x3b, 0x78, 0x67, 0x9d, 0xc8, 0x51, 0xfd, 0x1e, 0xd4,
- 0x57, 0xfc, 0xb8, 0xe4, 0x93, 0x95, 0x94, 0x2d, 0x5b, 0x54, 0xb0, 0xee,
- 0x78, 0xd8, 0x06, 0x7e, 0x2c, 0x01, 0x27, 0x33, 0x5a, 0x5f, 0x4a, 0xd3,
- 0xeb, 0xdf, 0xce, 0xeb, 0x6a, 0xf4, 0x77, 0x06, 0xe5, 0xac, 0xe6, 0x67,
- 0x7a, 0xcc, 0xca, 0x25, 0x65, 0x6b, 0x8d, 0xe5, 0x21, 0xeb, 0x4e, 0x9f,
- 0xf2, 0x8c, 0x77, 0x9f, 0x74, 0x5e, 0x89, 0x7e, 0x36, 0x9e, 0x79, 0x43,
- 0x6f, 0x94, 0x46, 0xce, 0x43, 0x1a, 0xf9, 0xfc, 0x66, 0x84, 0xc6, 0x27,
- 0x1b, 0xef, 0x47, 0x23, 0xef, 0x15, 0xff, 0x8f, 0x5a, 0x03, 0xda, 0x86,
- 0xe4, 0x8d, 0x99, 0xaf, 0x98, 0x75, 0xf0, 0x7e, 0x8a, 0xf3, 0x7f, 0xab,
- 0x1e, 0xc8, 0x4b, 0xe5, 0x22, 0xeb, 0x2c, 0x44, 0xd6, 0xf9, 0x6e, 0x64,
- 0x9d, 0xef, 0x46, 0xd6, 0xa9, 0x80, 0xa7, 0xb2, 0x51, 0x41, 0x86, 0x4b,
- 0x34, 0x63, 0x72, 0x08, 0x73, 0xbe, 0x2e, 0xb1, 0x1c, 0xf5, 0x3c, 0xc4,
- 0x9b, 0x73, 0xe8, 0x9f, 0x93, 0xb3, 0x33, 0x15, 0x29, 0x1d, 0x89, 0xcb,
- 0x1d, 0xba, 0xdf, 0x26, 0x43, 0x5f, 0xb4, 0x2d, 0x21, 0x7b, 0x92, 0x7c,
- 0x0f, 0xdb, 0x6c, 0xf0, 0x99, 0xe5, 0x6f, 0x5d, 0x19, 0x94, 0xf9, 0xbe,
- 0x60, 0xf6, 0x32, 0x1a, 0x8c, 0x3b, 0xf5, 0xa6, 0xc6, 0xc3, 0x45, 0x9f,
- 0xb8, 0x25, 0xd9, 0x98, 0x2b, 0xfb, 0x86, 0xb3, 0x5d, 0x32, 0xe1, 0x58,
- 0xd9, 0xf1, 0xfe, 0x75, 0xd4, 0x8b, 0xbc, 0x72, 0xdb, 0x80, 0x0d, 0x92,
- 0x56, 0xc4, 0x7c, 0xbd, 0x2f, 0x4b, 0x05, 0xf4, 0x3b, 0x2c, 0x8f, 0x28,
- 0xb7, 0xb3, 0xa9, 0x9e, 0xba, 0x1d, 0xc3, 0x3b, 0x65, 0x78, 0x97, 0x39,
- 0x63, 0x1b, 0x65, 0xe2, 0xf0, 0x35, 0xa6, 0x1c, 0xb6, 0x6f, 0xb6, 0x57,
- 0x96, 0xcf, 0x76, 0xaf, 0x2c, 0x87, 0x38, 0x11, 0xc5, 0x70, 0xee, 0x15,
- 0xf8, 0xe4, 0x52, 0xee, 0xe2, 0xa0, 0x35, 0x0b, 0x9d, 0x5b, 0x67, 0x68,
- 0xb8, 0xc2, 0xd0, 0x00, 0x5a, 0xfb, 0x20, 0x59, 0x5a, 0x97, 0xb4, 0x68,
- 0x35, 0x95, 0xc9, 0xfb, 0xf0, 0x7d, 0x83, 0x6e, 0x0f, 0x74, 0x2e, 0x7c,
- 0x86, 0xf8, 0xfe, 0x66, 0xc4, 0x5e, 0xf4, 0x40, 0x67, 0x93, 0xe0, 0x55,
- 0x88, 0xf5, 0xc4, 0xe0, 0x14, 0xec, 0x03, 0x64, 0x55, 0x63, 0x7b, 0x3b,
- 0xf0, 0xd0, 0x36, 0xd8, 0x9c, 0x30, 0xd8, 0xdc, 0x0e, 0x5c, 0x66, 0xd9,
- 0x31, 0xe5, 0xa4, 0x29, 0xa7, 0x50, 0x86, 0x1d, 0x9f, 0x25, 0x2e, 0x5f,
- 0x77, 0x70, 0xef, 0x51, 0x8d, 0xf7, 0xb4, 0x15, 0x40, 0x61, 0xe2, 0x35,
- 0x71, 0xbb, 0x47, 0xe6, 0x6b, 0x58, 0xaf, 0x81, 0x8d, 0xdc, 0x7b, 0x94,
- 0x1e, 0xd2, 0xb2, 0x5e, 0x14, 0x6c, 0x57, 0x3e, 0x49, 0x7a, 0x1f, 0xc4,
- 0xde, 0x89, 0x3f, 0xa4, 0xfb, 0x2a, 0xd0, 0xca, 0x7d, 0xfc, 0x3c, 0x69,
- 0xe5, 0x7a, 0xcd, 0xf4, 0x7e, 0x58, 0x1c, 0x24, 0xed, 0x27, 0xb1, 0xe7,
- 0x3c, 0x30, 0x4f, 0xac, 0xd1, 0xbe, 0x51, 0xec, 0x79, 0x04, 0x78, 0x78,
- 0x3b, 0xf0, 0x70, 0x37, 0xf0, 0x70, 0x18, 0x78, 0x98, 0x03, 0x16, 0x0e,
- 0x01, 0x0b, 0x07, 0x81, 0x85, 0x59, 0xf0, 0x26, 0x29, 0x73, 0xc0, 0xc6,
- 0x39, 0x60, 0xe4, 0x1c, 0xe6, 0x18, 0x9f, 0x15, 0xeb, 0x4b, 0xd8, 0xc3,
- 0x63, 0x33, 0x99, 0x93, 0x90, 0xa5, 0x54, 0x45, 0x41, 0xfe, 0xb3, 0x43,
- 0x90, 0xed, 0x7e, 0xa9, 0xfa, 0xb6, 0x94, 0x69, 0x53, 0xb7, 0xf7, 0x42,
- 0xd7, 0x20, 0xef, 0x29, 0x31, 0x7f, 0x1b, 0xcc, 0xf3, 0x1f, 0x45, 0xdc,
- 0xbf, 0xa3, 0x2c, 0xa6, 0x45, 0xce, 0x48, 0xc9, 0xeb, 0x75, 0x0a, 0xaa,
- 0x1f, 0xfd, 0x58, 0xce, 0xaa, 0xfb, 0x8f, 0x5c, 0xaf, 0xf6, 0x1e, 0x21,
- 0x5f, 0xa6, 0x81, 0x57, 0x75, 0x99, 0xcc, 0x52, 0xb7, 0xea, 0x72, 0x22,
- 0x9b, 0x19, 0xaa, 0x48, 0x9b, 0x4c, 0x25, 0xa7, 0xb5, 0xad, 0xb5, 0x73,
- 0x87, 0xb5, 0xbd, 0x2a, 0xbb, 0x78, 0xd6, 0x06, 0x54, 0xe9, 0x08, 0xf7,
- 0xdf, 0x8b, 0x5f, 0x1c, 0xb4, 0x70, 0x7e, 0x5b, 0x86, 0x07, 0x1d, 0xf5,
- 0x40, 0x5f, 0x05, 0x08, 0x96, 0x71, 0xce, 0x62, 0xe5, 0xe2, 0x74, 0x6f,
- 0xaa, 0xa8, 0x6c, 0x19, 0xb3, 0x2d, 0x19, 0x87, 0x7c, 0x0f, 0x67, 0xdf,
- 0xa9, 0x4f, 0x25, 0xd9, 0xbe, 0x4e, 0xbe, 0xae, 0x7d, 0x0e, 0xac, 0x5d,
- 0x3d, 0x8a, 0x75, 0xe3, 0x38, 0x03, 0xae, 0xcb, 0x79, 0x50, 0xae, 0xd9,
- 0x28, 0x67, 0x4e, 0x56, 0xc4, 0x87, 0x9e, 0x6c, 0x94, 0xc2, 0xce, 0x16,
- 0xc9, 0x8f, 0xa4, 0x65, 0x7c, 0xc6, 0x07, 0x4e, 0xe1, 0x1c, 0xdd, 0x56,
- 0x29, 0x8d, 0xa6, 0xe5, 0xd1, 0x19, 0xd6, 0x9d, 0xc6, 0xfe, 0x33, 0x87,
- 0xf2, 0xc2, 0xfd, 0xc7, 0xf5, 0xbe, 0xd2, 0xea, 0xb4, 0xec, 0xf7, 0xde,
- 0x30, 0x7a, 0x14, 0x94, 0xef, 0xc7, 0x99, 0x9e, 0xf0, 0x17, 0xb0, 0x7f,
- 0x57, 0xe6, 0x81, 0xff, 0xc5, 0x23, 0xc0, 0x41, 0xb7, 0x03, 0x98, 0x95,
- 0x59, 0xa0, 0x4d, 0x8d, 0xc1, 0xef, 0xab, 0x6a, 0x5e, 0xf7, 0xc8, 0x91,
- 0x19, 0x25, 0xdf, 0xbe, 0x31, 0x8d, 0x32, 0xb0, 0x31, 0x9b, 0x39, 0x3d,
- 0xa6, 0x7a, 0xe4, 0x86, 0xce, 0x14, 0xc6, 0xe5, 0x54, 0xc9, 0xdb, 0x18,
- 0x03, 0x2f, 0x8f, 0xa7, 0x15, 0xfb, 0x2a, 0x29, 0x66, 0x63, 0x38, 0xff,
- 0x0a, 0xfa, 0xbf, 0x8f, 0xf5, 0x7a, 0x64, 0x16, 0xbe, 0xd6, 0xec, 0x4c,
- 0x1e, 0xe3, 0x88, 0x5d, 0x99, 0xe3, 0x4b, 0x0a, 0x18, 0x33, 0x0b, 0xf9,
- 0x1e, 0x85, 0x2f, 0x33, 0x03, 0xd1, 0x69, 0x4d, 0xe3, 0x4c, 0x7b, 0x9d,
- 0x71, 0xe0, 0x41, 0xbe, 0x87, 0xef, 0x9c, 0xd3, 0x95, 0x13, 0x1e, 0xe5,
- 0x30, 0x2d, 0x4f, 0xf9, 0x1c, 0xd7, 0xbb, 0xf0, 0x1c, 0x7c, 0x9f, 0xdf,
- 0xf5, 0xae, 0x44, 0xff, 0x77, 0xe1, 0x07, 0x3b, 0x52, 0xc5, 0xb9, 0x95,
- 0xc1, 0xcb, 0x7c, 0x2a, 0x28, 0x8f, 0xcf, 0x66, 0x16, 0xde, 0x50, 0x7c,
- 0x77, 0x2b, 0xf3, 0xea, 0x5a, 0x91, 0x4e, 0xf2, 0x33, 0x0b, 0x5e, 0xba,
- 0x8e, 0x52, 0xdb, 0x8d, 0xef, 0x47, 0x3d, 0x72, 0x41, 0x9f, 0x2d, 0xf3,
- 0x03, 0x51, 0x3d, 0xa2, 0x3d, 0x0c, 0xf5, 0x28, 0x93, 0x5a, 0x52, 0x0a,
- 0xed, 0xb6, 0x1c, 0xd6, 0x65, 0x0b, 0xb4, 0x66, 0x52, 0xdc, 0xdf, 0x44,
- 0xad, 0x5f, 0x9e, 0xf2, 0xd8, 0x1f, 0x7c, 0x9e, 0x6e, 0x37, 0xfd, 0x4f,
- 0x83, 0x87, 0xf4, 0xdf, 0xfa, 0x41, 0x73, 0xa0, 0x5b, 0xf3, 0xd3, 0x49,
- 0xdd, 0x36, 0xe5, 0x05, 0x7e, 0x9a, 0x82, 0x2f, 0x37, 0x07, 0x5f, 0xae,
- 0xa8, 0xf5, 0xcc, 0xc9, 0xc3, 0xd7, 0x87, 0x9e, 0x04, 0x3a, 0x56, 0xad,
- 0x91, 0x96, 0xbb, 0x40, 0x5f, 0xa6, 0x02, 0x62, 0x0e, 0xab, 0x1c, 0xce,
- 0x7d, 0x50, 0x2a, 0xf4, 0xf7, 0xce, 0xc6, 0x9e, 0x92, 0xb1, 0x2a, 0xed,
- 0x11, 0x7e, 0x9e, 0xeb, 0x30, 0xbe, 0xc8, 0x6b, 0x5b, 0xd1, 0x0d, 0x39,
- 0x80, 0x1d, 0xc9, 0x6e, 0x32, 0x7e, 0xce, 0x13, 0x38, 0xcf, 0x33, 0x38,
- 0xf7, 0x9a, 0xec, 0x3d, 0xf6, 0x0a, 0x65, 0xba, 0xbf, 0x2a, 0x99, 0xfe,
- 0x29, 0xd9, 0xe1, 0xcc, 0x43, 0x1f, 0xf3, 0xa3, 0xf5, 0x5b, 0x54, 0x8e,
- 0x63, 0x0e, 0x62, 0x0c, 0x9e, 0xd5, 0x57, 0xe4, 0x21, 0x9f, 0x75, 0x0f,
- 0x81, 0x9f, 0xd0, 0x95, 0xc1, 0x27, 0x8c, 0x1e, 0x60, 0x3e, 0x3b, 0x9c,
- 0xef, 0x15, 0x33, 0x1f, 0xfb, 0xb1, 0x0f, 0xc7, 0x2c, 0xcf, 0xbb, 0x8b,
- 0xb6, 0x08, 0x78, 0xb4, 0x4b, 0xd5, 0x6f, 0x89, 0xa3, 0xfd, 0xc4, 0x20,
- 0xdf, 0x31, 0x0f, 0x6c, 0x91, 0xe3, 0x9e, 0x41, 0x5f, 0xf8, 0x7a, 0xde,
- 0x7a, 0x29, 0x74, 0x85, 0xf4, 0x52, 0x06, 0xe8, 0x27, 0x68, 0x1b, 0xbc,
- 0x39, 0xe0, 0xfd, 0x1f, 0xc6, 0x02, 0x99, 0x3c, 0x80, 0x32, 0xf5, 0xef,
- 0x80, 0x14, 0xbd, 0x0c, 0xf6, 0x09, 0x1d, 0xf3, 0x3b, 0xac, 0x60, 0x8f,
- 0xe0, 0xff, 0xc8, 0x39, 0xf0, 0x41, 0x2a, 0x01, 0x6f, 0xc8, 0x17, 0xf2,
- 0xa4, 0x03, 0xb2, 0x0f, 0xb9, 0x87, 0xdc, 0x96, 0x34, 0x0f, 0xfe, 0xbd,
- 0x33, 0xf0, 0x8b, 0x33, 0x95, 0x3c, 0xe3, 0xb9, 0x4e, 0xe2, 0x26, 0x30,
- 0xcc, 0x87, 0x70, 0x60, 0xee, 0x25, 0xb5, 0x9e, 0xf4, 0xa6, 0x97, 0x62,
- 0x7d, 0x2c, 0xf7, 0x2f, 0x41, 0x86, 0xab, 0x38, 0x9f, 0xc2, 0xce, 0x5e,
- 0x83, 0x5b, 0xcf, 0xc6, 0x28, 0xaf, 0x55, 0x60, 0x4c, 0xc9, 0xdb, 0xe1,
- 0xdc, 0x4d, 0xbe, 0x39, 0x8e, 0x3c, 0xe7, 0x45, 0xb1, 0x03, 0xb6, 0xcf,
- 0xa5, 0x1c, 0x26, 0x21, 0x07, 0x36, 0x6c, 0x68, 0x0a, 0x67, 0xfe, 0x6f,
- 0x9d, 0xc1, 0x5e, 0xf8, 0x6e, 0xcb, 0x9c, 0x83, 0x35, 0xbd, 0xc5, 0x8d,
- 0x41, 0x1d, 0xdf, 0xb7, 0xf0, 0x8c, 0x0e, 0xaf, 0xa4, 0x9d, 0xe7, 0xdb,
- 0x7c, 0xa6, 0x27, 0xb0, 0x17, 0xd6, 0xe3, 0x59, 0x3d, 0x2e, 0x7b, 0x89,
- 0x9b, 0x83, 0xdb, 0x52, 0x2f, 0xa2, 0x7f, 0x11, 0x36, 0xa1, 0x62, 0xb3,
- 0xed, 0x6d, 0x6b, 0x79, 0x8c, 0xa2, 0x5f, 0x0a, 0x1f, 0x78, 0xc9, 0xfa,
- 0x92, 0xff, 0x92, 0x55, 0xa8, 0xbe, 0x6d, 0x15, 0x21, 0x27, 0x55, 0x8f,
- 0xf1, 0x0b, 0xf5, 0xc7, 0xc1, 0xda, 0x99, 0xd4, 0x5b, 0xaa, 0x37, 0x3d,
- 0x0f, 0x2c, 0xb8, 0x1f, 0x3a, 0x5d, 0xb4, 0x17, 0xa4, 0xec, 0xd7, 0xa4,
- 0x74, 0x6c, 0x07, 0xf4, 0x2d, 0x1d, 0xa1, 0x8b, 0x78, 0x56, 0xa1, 0x1f,
- 0x6e, 0xed, 0xf2, 0xa4, 0xd2, 0x92, 0x23, 0xae, 0x6d, 0x83, 0xec, 0xa0,
- 0xae, 0xb6, 0x2c, 0x7f, 0xb7, 0xad, 0xa2, 0x15, 0xb1, 0xee, 0xe0, 0x4a,
- 0x7a, 0xab, 0x72, 0x71, 0x7a, 0x77, 0x35, 0xe8, 0x25, 0x66, 0x00, 0xff,
- 0x3d, 0xe0, 0xbf, 0x07, 0xfc, 0xf7, 0x80, 0xff, 0x1e, 0xf0, 0xdf, 0x83,
- 0x6d, 0xf0, 0x60, 0x03, 0x3c, 0xd8, 0x00, 0x0f, 0x36, 0xc0, 0x83, 0x0d,
- 0xf0, 0x0a, 0x38, 0x27, 0xe2, 0x3c, 0x6d, 0xc8, 0x3d, 0x0d, 0xbb, 0x19,
- 0xf8, 0x39, 0x57, 0x1a, 0xdf, 0x01, 0xfa, 0xe7, 0x6c, 0x91, 0xf1, 0xfe,
- 0x2b, 0xb0, 0xb7, 0x56, 0x3c, 0xdb, 0xf0, 0xc4, 0x1a, 0xfd, 0x9f, 0x35,
- 0x7a, 0xf2, 0x55, 0xd0, 0xa5, 0x50, 0xfe, 0x05, 0xc8, 0x61, 0x0b, 0xe8,
- 0xf9, 0x94, 0xf1, 0x31, 0xbe, 0x61, 0x07, 0x72, 0xd8, 0x86, 0xba, 0xcf,
- 0xa0, 0xae, 0x0d, 0x7d, 0xf6, 0xa3, 0x0f, 0x7d, 0x94, 0x0e, 0x53, 0x17,
- 0xed, 0x47, 0x5f, 0xe5, 0x0b, 0x58, 0x2b, 0x83, 0x7e, 0x1d, 0x98, 0xbb,
- 0x07, 0x7d, 0x6e, 0x46, 0x9f, 0xab, 0x50, 0xa6, 0x6f, 0xdb, 0x8d, 0xf2,
- 0xa7, 0x9b, 0xc6, 0x5c, 0x83, 0xba, 0xcf, 0x36, 0xd5, 0x9d, 0x45, 0x1d,
- 0x62, 0x62, 0xe7, 0x45, 0x33, 0xae, 0x82, 0x72, 0x57, 0x53, 0x9f, 0x57,
- 0x50, 0x37, 0x84, 0xba, 0xbf, 0xc2, 0x13, 0xb1, 0xb0, 0x43, 0x9a, 0xc2,
- 0x36, 0xfa, 0xa9, 0x69, 0xd4, 0xc7, 0x8d, 0xaf, 0xf9, 0x24, 0x7d, 0x2f,
- 0xd8, 0xdc, 0x3f, 0xb6, 0x03, 0xdf, 0x0c, 0xde, 0xab, 0x96, 0xc3, 0xb0,
- 0xfc, 0xcd, 0xa6, 0x32, 0xfb, 0x7e, 0xbf, 0xa9, 0xae, 0x6d, 0xd3, 0xca,
- 0xf2, 0x4f, 0xe3, 0xab, 0xc7, 0xdc, 0xdb, 0xd4, 0xe7, 0xeb, 0x9d, 0x2b,
- 0xcb, 0xbb, 0x5b, 0x56, 0x8f, 0xd9, 0xbe, 0x71, 0x65, 0xdd, 0xad, 0x9b,
- 0x57, 0x96, 0xe9, 0x03, 0x26, 0x11, 0xc3, 0x84, 0xfd, 0x77, 0x7e, 0x22,
- 0x68, 0x27, 0x7f, 0x9b, 0x65, 0x49, 0x2b, 0x23, 0xca, 0x0a, 0xe7, 0xb0,
- 0x64, 0x41, 0x9f, 0x1c, 0x95, 0x7b, 0xc9, 0x2a, 0x42, 0xa6, 0x0a, 0x7e,
- 0x38, 0x1f, 0x75, 0xb6, 0x39, 0x4f, 0x10, 0xe6, 0x07, 0xe8, 0x6f, 0xb5,
- 0x43, 0x6e, 0xee, 0xa2, 0x4d, 0x3a, 0x54, 0x91, 0x65, 0xfd, 0xdc, 0xaa,
- 0xce, 0xa7, 0x9f, 0xf7, 0x19, 0x8c, 0x3a, 0x07, 0x3a, 0xeb, 0x32, 0x92,
- 0x5d, 0x47, 0x1b, 0x63, 0xb0, 0x8b, 0xb8, 0x53, 0xaf, 0xc7, 0xb6, 0xd7,
- 0x65, 0x5f, 0xf6, 0xdd, 0xba, 0x68, 0xcc, 0xbb, 0x57, 0xe3, 0x4e, 0x5a,
- 0x75, 0xe3, 0x8c, 0x1c, 0xc4, 0x12, 0x88, 0xed, 0x93, 0xb4, 0x49, 0xc7,
- 0xe9, 0x9f, 0x1c, 0x0c, 0x30, 0x95, 0xb8, 0x83, 0xb2, 0x3f, 0x85, 0x39,
- 0xb9, 0x3e, 0x9e, 0x55, 0xe2, 0xb8, 0xad, 0x6d, 0x4a, 0xc9, 0xe1, 0xbc,
- 0x6b, 0x61, 0xe3, 0xbf, 0xd8, 0xf4, 0x0b, 0x6d, 0xf7, 0x24, 0xec, 0x1b,
- 0xdb, 0xe8, 0x2b, 0x9c, 0xa4, 0x5f, 0x12, 0xc1, 0xaa, 0x9b, 0x62, 0xe2,
- 0x2e, 0x63, 0x66, 0xb0, 0xaf, 0x2d, 0xf4, 0xfb, 0x2f, 0x61, 0xaf, 0x6b,
- 0x63, 0x51, 0xaf, 0xba, 0xb8, 0x6e, 0xef, 0x69, 0xe8, 0x76, 0x28, 0x7b,
- 0x6b, 0xe5, 0x03, 0x5e, 0xd5, 0x67, 0xf1, 0xac, 0x9f, 0x39, 0x5c, 0x81,
- 0x2e, 0x2d, 0xea, 0xd8, 0x37, 0x3c, 0x17, 0xfa, 0x38, 0x99, 0xe3, 0x73,
- 0x90, 0xed, 0xbd, 0x3a, 0x26, 0x60, 0x3c, 0x50, 0x97, 0x5d, 0xd9, 0x4f,
- 0x25, 0xc9, 0x87, 0xbc, 0xfa, 0x71, 0x9c, 0x3e, 0xc3, 0xa2, 0x47, 0x9e,
- 0x65, 0xd1, 0x9e, 0x05, 0x26, 0xfc, 0xab, 0x14, 0x93, 0xac, 0x7b, 0xab,
- 0x3e, 0x0f, 0xbf, 0x4a, 0xfb, 0x47, 0xda, 0xde, 0xd3, 0xbf, 0x83, 0x5d,
- 0xf7, 0xc9, 0xd3, 0x25, 0xf0, 0x39, 0xf4, 0x01, 0x7e, 0x40, 0x1f, 0x55,
- 0x56, 0xfa, 0xd2, 0x22, 0x0f, 0xd5, 0xfe, 0x01, 0x36, 0x47, 0x05, 0xbe,
- 0x0a, 0xe3, 0x65, 0x97, 0xf5, 0x37, 0xc6, 0xe9, 0xcb, 0x05, 0xb6, 0x3e,
- 0x86, 0xf5, 0x10, 0x5f, 0xd7, 0xfe, 0xd3, 0x2a, 0x79, 0x3d, 0xf4, 0xb3,
- 0xb0, 0x7f, 0xf8, 0x50, 0x3e, 0xdb, 0x58, 0x97, 0x30, 0xfe, 0x77, 0xbb,
- 0xf1, 0xb7, 0x1d, 0xe3, 0x6f, 0x6b, 0x3a, 0x12, 0x4e, 0x2e, 0xf4, 0x0b,
- 0x78, 0x66, 0xe9, 0x83, 0x6a, 0x3b, 0xfd, 0x82, 0x0e, 0x59, 0xdb, 0x2f,
- 0x08, 0x69, 0x3a, 0x85, 0x7d, 0xd2, 0xcf, 0xd3, 0x79, 0xa0, 0xce, 0x20,
- 0xf7, 0x44, 0x1a, 0x42, 0xfb, 0xa8, 0xed, 0xf0, 0x21, 0x98, 0x3c, 0xe6,
- 0x24, 0x41, 0xeb, 0x6e, 0x29, 0x4c, 0x9f, 0x32, 0xf6, 0x96, 0x71, 0x04,
- 0x7d, 0xf8, 0x40, 0x66, 0x0b, 0xd9, 0x0e, 0xcb, 0xcc, 0xd3, 0x05, 0x0b,
- 0x19, 0xc9, 0x51, 0x71, 0x2d, 0xfa, 0x31, 0xa1, 0x4f, 0xb3, 0x60, 0x7c,
- 0x9a, 0x33, 0xb2, 0xcf, 0x0b, 0xe2, 0x86, 0x91, 0xda, 0x12, 0xea, 0x34,
- 0xed, 0x29, 0xfa, 0x96, 0x0a, 0x3e, 0x77, 0xfe, 0xde, 0x0c, 0x02, 0x90,
- 0x60, 0x2f, 0x5b, 0xb1, 0x97, 0x6a, 0x63, 0x2f, 0x6d, 0x4b, 0xcd, 0x3e,
- 0x0e, 0xc7, 0x4e, 0xae, 0x1a, 0x2b, 0xd8, 0xc7, 0xdc, 0x79, 0xda, 0xb8,
- 0x47, 0xfa, 0x0d, 0x8e, 0xd9, 0x63, 0x78, 0x4e, 0x8f, 0x63, 0x8f, 0x49,
- 0xab, 0xa4, 0x7d, 0x2d, 0xfa, 0x2d, 0x88, 0xb3, 0x6b, 0x2f, 0xe1, 0x49,
- 0xfd, 0xd0, 0xf3, 0x60, 0x4f, 0xed, 0x7a, 0x4f, 0x53, 0xde, 0x2b, 0x7a,
- 0x1f, 0xf3, 0xb5, 0xbf, 0x91, 0xf2, 0xb1, 0x1f, 0xc0, 0xee, 0x45, 0x73,
- 0x73, 0xcc, 0x6b, 0x92, 0x1f, 0x95, 0x08, 0x7e, 0x72, 0xaf, 0xcc, 0xbb,
- 0xbd, 0x1c, 0x0f, 0xe2, 0x83, 0x69, 0x9c, 0xb1, 0x15, 0xb4, 0xeb, 0xf5,
- 0x43, 0xbe, 0xb6, 0x44, 0xe8, 0xa9, 0xc3, 0xe7, 0x4c, 0x81, 0x86, 0xe8,
- 0x98, 0x03, 0x32, 0xec, 0xf1, 0x3c, 0x7a, 0x53, 0x7b, 0xc5, 0x75, 0x4a,
- 0x12, 0xfa, 0x19, 0x5c, 0x9f, 0x3a, 0x5f, 0x84, 0xe3, 0xcb, 0x5c, 0x6a,
- 0xc8, 0xbb, 0x90, 0x6f, 0xed, 0x4b, 0xcd, 0x32, 0x30, 0x89, 0x58, 0xab,
- 0xec, 0x91, 0x4f, 0xa1, 0x6c, 0x86, 0x6b, 0xbf, 0x6a, 0x71, 0x3f, 0x13,
- 0x3a, 0x7f, 0xf8, 0x4f, 0x0d, 0x19, 0x1d, 0x07, 0x76, 0x04, 0x32, 0xf7,
- 0xf7, 0x86, 0x37, 0xa1, 0x6c, 0xb6, 0x9b, 0x73, 0x66, 0x2c, 0x48, 0xdd,
- 0x09, 0xe5, 0x60, 0x9b, 0x73, 0xa7, 0xe6, 0x05, 0xdb, 0xb4, 0xcf, 0xad,
- 0xcf, 0x72, 0xac, 0x71, 0x96, 0x1b, 0x9a, 0xe4, 0xf2, 0xdd, 0x8d, 0x81,
- 0x1e, 0x52, 0xdf, 0xa0, 0xb7, 0xe0, 0xd7, 0xb3, 0x2b, 0xf4, 0xbb, 0xff,
- 0x3c, 0x39, 0xd9, 0x76, 0x89, 0xcd, 0x7e, 0x0f, 0xbc, 0xbc, 0x06, 0xb1,
- 0x8a, 0x88, 0x3d, 0x43, 0x1c, 0xa2, 0xbf, 0xb1, 0xec, 0xef, 0xce, 0xcb,
- 0x5a, 0xbe, 0xee, 0xc5, 0x7c, 0x8d, 0x4f, 0x5e, 0xa2, 0xaf, 0x31, 0xdc,
- 0x22, 0xad, 0xc4, 0xa2, 0x33, 0xf0, 0x6d, 0x2d, 0x69, 0x71, 0xbf, 0x01,
- 0x1b, 0x76, 0xda, 0x5e, 0xe7, 0x86, 0x98, 0xd0, 0x2e, 0x9b, 0x66, 0xb7,
- 0x68, 0x5c, 0x70, 0x66, 0x96, 0x71, 0x61, 0x1c, 0xbc, 0x1f, 0x09, 0xf2,
- 0xbc, 0xc9, 0x4d, 0x72, 0xa9, 0xf1, 0xf5, 0xb2, 0xdf, 0x3f, 0xd6, 0xf0,
- 0xfb, 0xaf, 0x6c, 0xe2, 0xe3, 0x5a, 0xb8, 0x78, 0x1a, 0x7c, 0xcb, 0x21,
- 0xfe, 0x65, 0x5c, 0x3b, 0x8c, 0x78, 0x98, 0xb1, 0x58, 0x1e, 0x31, 0x71,
- 0xe6, 0xb4, 0xc8, 0x6e, 0xc4, 0xc8, 0x99, 0x1f, 0x31, 0x7f, 0xf5, 0xbc,
- 0x9f, 0x99, 0x13, 0xb9, 0x1d, 0x7c, 0x1d, 0x04, 0x6e, 0x66, 0x81, 0xa3,
- 0x3b, 0xc1, 0xdf, 0x7e, 0x8d, 0x9d, 0xf7, 0x1f, 0x11, 0xeb, 0x0e, 0x9d,
- 0xab, 0xa6, 0x3e, 0x27, 0x61, 0x47, 0xeb, 0xf5, 0xfd, 0xd9, 0x5e, 0xc4,
- 0xf5, 0x69, 0xb9, 0xd5, 0x66, 0x1c, 0x6b, 0xd9, 0x5b, 0x07, 0xe6, 0x63,
- 0x51, 0x9f, 0xb4, 0x70, 0x51, 0x3b, 0xb0, 0x9a, 0xf7, 0x45, 0x6d, 0x0b,
- 0x0e, 0xc7, 0x2e, 0xc4, 0xfb, 0x3b, 0x1a, 0xbc, 0x6f, 0x69, 0x95, 0xd6,
- 0xdb, 0x75, 0x1e, 0x61, 0xeb, 0xc0, 0x7e, 0xe2, 0x55, 0x16, 0x76, 0x1d,
- 0xf6, 0xb7, 0x2e, 0xb7, 0x65, 0xdf, 0xae, 0xbf, 0xe8, 0x6e, 0x94, 0xd2,
- 0xce, 0xfb, 0x0c, 0x66, 0x2f, 0x7d, 0xad, 0xe0, 0x56, 0xa0, 0x1f, 0x41,
- 0xce, 0x70, 0xef, 0x74, 0x02, 0x96, 0x80, 0x7f, 0x9d, 0x32, 0x3f, 0xf4,
- 0x16, 0xce, 0x70, 0xc7, 0x49, 0x26, 0x9c, 0x14, 0x70, 0x78, 0x3e, 0xd9,
- 0xae, 0xf3, 0xc5, 0x9f, 0x70, 0x59, 0xef, 0xe0, 0x4c, 0x47, 0x65, 0x1e,
- 0xfe, 0x43, 0x75, 0x08, 0x34, 0xee, 0xec, 0x42, 0x7f, 0xea, 0x1d, 0x79,
- 0x3e, 0x0a, 0xdb, 0x4b, 0x9e, 0x26, 0xd1, 0x7f, 0x0f, 0xfa, 0x74, 0xe2,
- 0x79, 0x5f, 0x6c, 0xde, 0x61, 0xec, 0xfc, 0x79, 0x94, 0x39, 0x47, 0xd4,
- 0x76, 0x7e, 0x2e, 0x2e, 0x7a, 0x4e, 0x8e, 0xe9, 0xd2, 0xfa, 0xbf, 0xbc,
- 0x16, 0xd7, 0x61, 0xdb, 0xcf, 0xea, 0xd7, 0x0f, 0x0c, 0x45, 0xd6, 0xeb,
- 0x88, 0xac, 0x37, 0x14, 0x59, 0x8f, 0x74, 0x76, 0x46, 0xe8, 0xec, 0xc4,
- 0xf8, 0x22, 0xd6, 0x26, 0x3f, 0xa2, 0x6b, 0x3e, 0x18, 0x59, 0x33, 0xdc,
- 0x5f, 0x57, 0x64, 0xdc, 0xbb, 0x58, 0x8f, 0x75, 0xc9, 0x48, 0x1d, 0x69,
- 0xd8, 0x8c, 0x3a, 0x96, 0x3b, 0x23, 0x74, 0x91, 0xd6, 0x0d, 0xa8, 0xd7,
- 0xfe, 0x13, 0xf8, 0xdc, 0x0a, 0xbb, 0xa5, 0x60, 0x3b, 0x5a, 0xe0, 0x5f,
- 0x35, 0xef, 0xf5, 0x51, 0xac, 0x1b, 0xce, 0x97, 0xc4, 0x1c, 0xec, 0xcf,
- 0xbe, 0x31, 0x33, 0x9e, 0xf5, 0x6c, 0xff, 0xf3, 0xfa, 0x9f, 0x6a, 0xbe,
- 0x6d, 0x06, 0xed, 0x3a, 0xef, 0x22, 0x73, 0x9d, 0x36, 0xce, 0x93, 0xf1,
- 0xb1, 0x25, 0x57, 0xbb, 0xca, 0xea, 0x1d, 0xe0, 0xd9, 0x6f, 0x34, 0x58,
- 0xda, 0x6a, 0x15, 0x8e, 0x30, 0x5f, 0xd0, 0x66, 0x62, 0x3e, 0xc4, 0x1e,
- 0xda, 0xc6, 0xd8, 0xa6, 0x9d, 0x36, 0x86, 0x7e, 0x0b, 0xed, 0xe7, 0x69,
- 0xf3, 0x8e, 0x27, 0x64, 0xf8, 0x81, 0x6a, 0xa7, 0xbc, 0xa8, 0x79, 0xea,
- 0xc8, 0xd9, 0x06, 0x4f, 0xe3, 0xe6, 0xbb, 0xcc, 0x01, 0xf3, 0xcd, 0xa3,
- 0x0f, 0x7e, 0x11, 0xde, 0x6b, 0x79, 0xd0, 0x90, 0x96, 0xde, 0x01, 0xc6,
- 0x6e, 0x15, 0x3c, 0x99, 0xa7, 0xb0, 0xf0, 0x0c, 0xf2, 0x17, 0xbd, 0x03,
- 0xb0, 0x4b, 0xc0, 0xa1, 0xde, 0x81, 0x73, 0x3a, 0x9e, 0xab, 0xfa, 0x8e,
- 0x75, 0x9b, 0x17, 0xe4, 0x88, 0xce, 0xba, 0x17, 0xca, 0x11, 0xdd, 0xb3,
- 0x8e, 0x79, 0x8d, 0x30, 0x47, 0x74, 0x56, 0x74, 0x8e, 0xe8, 0xf8, 0x45,
- 0x72, 0x44, 0xf9, 0x4b, 0xcf, 0x11, 0x71, 0x7e, 0x5b, 0xee, 0x1c, 0x74,
- 0xd4, 0xaf, 0x9a, 0x1c, 0xd1, 0x1b, 0x12, 0xe4, 0x88, 0x5e, 0x94, 0xb5,
- 0x73, 0x44, 0x87, 0x9a, 0x72, 0x44, 0x9b, 0x75, 0x8e, 0x88, 0xf3, 0x04,
- 0x39, 0x22, 0x96, 0x4b, 0x03, 0x43, 0x91, 0x5c, 0x07, 0xf0, 0xd7, 0xbb,
- 0x01, 0x7c, 0x73, 0xac, 0x51, 0x2f, 0xc4, 0x34, 0x62, 0xff, 0x15, 0x0d,
- 0xfb, 0xb5, 0x8c, 0x6f, 0x96, 0x96, 0xb9, 0x8b, 0xe1, 0xdb, 0x68, 0xe0,
- 0x97, 0xac, 0xc0, 0xb6, 0xc9, 0x86, 0xef, 0xe2, 0xad, 0x63, 0x0c, 0x3d,
- 0x51, 0x5b, 0x9e, 0x77, 0x02, 0xbc, 0x1e, 0x6b, 0xe4, 0x49, 0xce, 0xe7,
- 0x1f, 0x25, 0xe5, 0xc0, 0x9a, 0xdf, 0xbd, 0x52, 0xf9, 0xd5, 0xdf, 0xbd,
- 0x2c, 0x49, 0x82, 0xce, 0xd2, 0x40, 0x49, 0xc7, 0x5d, 0xf3, 0xde, 0xaf,
- 0xc8, 0xd2, 0xdd, 0x0e, 0xf0, 0x27, 0xcc, 0x9f, 0xf0, 0x7c, 0x97, 0x6d,
- 0x4a, 0x41, 0x7d, 0x7c, 0x39, 0x94, 0x07, 0x74, 0x0e, 0xe5, 0xc5, 0x75,
- 0xd1, 0x1c, 0xca, 0x59, 0xb9, 0x70, 0x0e, 0xe5, 0x81, 0x35, 0x72, 0x28,
- 0x2f, 0xcb, 0x72, 0x0e, 0xe5, 0x65, 0x09, 0x73, 0x28, 0x31, 0x59, 0xda,
- 0x1c, 0x48, 0xe3, 0x03, 0xfe, 0x12, 0x7e, 0x67, 0xf0, 0x0b, 0x72, 0x2a,
- 0x67, 0x1b, 0xf4, 0xaf, 0x95, 0x53, 0x79, 0x7d, 0xdd, 0x07, 0xc9, 0xa9,
- 0x04, 0x36, 0x20, 0xcc, 0xa9, 0xe0, 0xe7, 0xc0, 0xe6, 0xa8, 0x68, 0x4e,
- 0xe5, 0x27, 0xd4, 0x07, 0xd4, 0xb1, 0xcc, 0x7a, 0xe8, 0x05, 0xec, 0x52,
- 0x5e, 0xe7, 0x38, 0x3e, 0x67, 0x78, 0x38, 0x87, 0x3d, 0xa7, 0x71, 0x16,
- 0xe4, 0x63, 0xaf, 0xf6, 0x2d, 0xf3, 0x76, 0xca, 0x2a, 0xf4, 0xc1, 0x9a,
- 0x4d, 0xf3, 0xbb, 0xb8, 0x6d, 0xed, 0xf5, 0x29, 0xe3, 0x09, 0xab, 0x8c,
- 0xbd, 0x0c, 0x4f, 0xcf, 0xc9, 0x5e, 0x3f, 0xf4, 0xa9, 0x06, 0x1a, 0x73,
- 0x50, 0x37, 0xe7, 0x81, 0xb3, 0xc0, 0x89, 0x4b, 0xb0, 0x51, 0xa7, 0x40,
- 0x73, 0x74, 0x1f, 0x88, 0x89, 0x07, 0x51, 0xa7, 0xcf, 0x9c, 0xbe, 0x65,
- 0x48, 0x4b, 0x9a, 0x7a, 0x7e, 0x09, 0xf3, 0xb1, 0xee, 0x94, 0x8e, 0xc7,
- 0xca, 0x83, 0xdc, 0x2b, 0x6d, 0xdd, 0x22, 0xe8, 0x43, 0x5d, 0x95, 0x31,
- 0x20, 0xed, 0x5e, 0x18, 0xa3, 0xb5, 0xeb, 0x18, 0xad, 0x4b, 0xf3, 0x83,
- 0xbc, 0xbe, 0x35, 0x41, 0xac, 0xec, 0x72, 0xb9, 0x87, 0x33, 0x06, 0xeb,
- 0x58, 0x0e, 0x62, 0xc1, 0xbc, 0xe2, 0xfb, 0xef, 0xe1, 0x5c, 0x99, 0xa7,
- 0x09, 0xcf, 0xef, 0x2b, 0x66, 0xdf, 0x43, 0x52, 0xe9, 0x92, 0xc4, 0x66,
- 0xd0, 0x53, 0x9a, 0xa1, 0xdf, 0xfd, 0x69, 0x1d, 0x83, 0x24, 0xdd, 0xf3,
- 0xeb, 0xed, 0x1d, 0x97, 0xa1, 0xb7, 0x23, 0x17, 0xd4, 0xdb, 0xaf, 0x25,
- 0xa2, 0x7a, 0x7b, 0xc7, 0x65, 0xe8, 0xed, 0xbe, 0xcb, 0xd2, 0x5b, 0xee,
- 0x8d, 0x98, 0x14, 0xe6, 0xc4, 0x56, 0xfb, 0x59, 0xe1, 0xba, 0xe3, 0x58,
- 0x33, 0x7f, 0x9e, 0x35, 0xc7, 0xce, 0x9b, 0x5b, 0x6d, 0xf6, 0xb1, 0x2e,
- 0xe5, 0xbc, 0x19, 0x5b, 0xd1, 0xde, 0xb6, 0x1b, 0xbb, 0x74, 0x9f, 0x89,
- 0xe7, 0xc3, 0xb8, 0x3e, 0xaa, 0x3f, 0x94, 0x0b, 0xca, 0xc2, 0x77, 0xc0,
- 0x2f, 0xca, 0x43, 0xa8, 0x73, 0xdd, 0x4d, 0x32, 0xb8, 0x88, 0x78, 0xbf,
- 0xdb, 0xc8, 0x20, 0xcf, 0xba, 0x4f, 0x7f, 0x67, 0xaa, 0x7a, 0x4f, 0x05,
- 0x71, 0xbe, 0x8b, 0x67, 0x35, 0xd4, 0x35, 0xf0, 0x24, 0x19, 0xb6, 0x91,
- 0x8f, 0x2e, 0x7c, 0x9e, 0x1d, 0xf0, 0xd7, 0xc0, 0x23, 0x5d, 0xbf, 0x32,
- 0x27, 0x7c, 0x61, 0x3c, 0x93, 0x4a, 0x1c, 0x7d, 0x4f, 0x0c, 0x42, 0xc7,
- 0x07, 0x89, 0x51, 0x35, 0xc4, 0x3d, 0x94, 0x43, 0xca, 0xe6, 0xb6, 0xfe,
- 0x5d, 0x8a, 0x3e, 0xd5, 0x13, 0x88, 0x83, 0x29, 0xaf, 0x69, 0xd9, 0xe5,
- 0x6f, 0x3b, 0x7d, 0x56, 0x71, 0x8d, 0x7a, 0xbd, 0xc4, 0x58, 0xd1, 0x11,
- 0xb5, 0x75, 0xe0, 0xbf, 0x13, 0xb4, 0x4b, 0x57, 0xb8, 0x31, 0x23, 0x6b,
- 0x79, 0xbc, 0x53, 0x6e, 0x7f, 0x08, 0x7b, 0xcf, 0xef, 0xfd, 0xaf, 0xa1,
- 0x3e, 0x05, 0x9d, 0xa7, 0x7d, 0x67, 0x3c, 0x72, 0x93, 0xe9, 0xd7, 0xad,
- 0xbf, 0x57, 0x16, 0xb2, 0x37, 0x98, 0x6f, 0x57, 0xb4, 0x3f, 0x19, 0xda,
- 0xec, 0x15, 0xe7, 0xcc, 0xfb, 0x12, 0x45, 0x1d, 0xcf, 0x70, 0xbc, 0x96,
- 0x49, 0xc4, 0x20, 0x76, 0x24, 0x97, 0x9e, 0x30, 0xb1, 0x1b, 0x75, 0xac,
- 0x1d, 0x67, 0xe8, 0x9b, 0x58, 0x85, 0xf1, 0xeb, 0xca, 0x7b, 0x12, 0x6b,
- 0xcb, 0xc0, 0x96, 0x0f, 0x20, 0x03, 0xcd, 0xe7, 0x97, 0x80, 0xee, 0x87,
- 0xe7, 0x17, 0xfa, 0x31, 0x73, 0x66, 0xdf, 0xdd, 0xc1, 0x19, 0xfe, 0xbf,
- 0xd8, 0xa7, 0x15, 0xd9, 0x67, 0x88, 0x47, 0x0f, 0x98, 0x7d, 0xde, 0xd4,
- 0x84, 0x47, 0x23, 0x4d, 0x3a, 0xfb, 0x71, 0xe2, 0xd1, 0x9f, 0xac, 0xff,
- 0xf8, 0xf1, 0x88, 0xfb, 0xea, 0x5e, 0x13, 0x87, 0x82, 0x7d, 0x3c, 0x22,
- 0x2a, 0xf7, 0x51, 0xc6, 0x7b, 0x1f, 0xe4, 0x7c, 0xa2, 0x38, 0xc2, 0x33,
- 0xe9, 0xd0, 0x3e, 0x6c, 0xa0, 0x7b, 0xb0, 0xe5, 0xd5, 0xb8, 0xbc, 0x7e,
- 0x57, 0x42, 0xfe, 0xf7, 0x46, 0x7e, 0x0f, 0xb3, 0x4d, 0x4e, 0x8b, 0xe5,
- 0xd7, 0xd6, 0x07, 0x76, 0xe8, 0xb5, 0x4d, 0x81, 0xdd, 0xe1, 0x98, 0x50,
- 0x9f, 0x1d, 0xb4, 0xb3, 0xad, 0x5b, 0x96, 0x3a, 0x2f, 0x27, 0x06, 0xdc,
- 0xe6, 0xbc, 0xa1, 0xd6, 0x8a, 0x01, 0x2f, 0x9c, 0x0f, 0x5c, 0x8e, 0x01,
- 0x89, 0xb3, 0x9d, 0x5a, 0x36, 0x4a, 0x49, 0xc6, 0x3e, 0x7d, 0x06, 0x3b,
- 0xf9, 0x8e, 0xd8, 0xd6, 0x43, 0xbc, 0xeb, 0x21, 0xd6, 0xf5, 0x10, 0xff,
- 0x7a, 0x88, 0x71, 0x3d, 0xc4, 0xb6, 0x1e, 0x62, 0x5b, 0x0f, 0xb1, 0xad,
- 0xd7, 0x6f, 0x62, 0xe4, 0x11, 0x93, 0xf7, 0xe7, 0x77, 0x72, 0xe6, 0x17,
- 0x2a, 0xb0, 0x25, 0x93, 0xbc, 0xe7, 0xa0, 0x0a, 0xd9, 0xf5, 0x66, 0x7f,
- 0x61, 0x4e, 0xbc, 0xc7, 0xe4, 0x6c, 0x5e, 0xd7, 0x79, 0x43, 0x51, 0xb3,
- 0xad, 0xc1, 0xb7, 0x74, 0xde, 0xc7, 0xf8, 0x2d, 0xf8, 0x25, 0xfa, 0x3e,
- 0x13, 0x75, 0xb4, 0xae, 0x72, 0xcc, 0xc9, 0x88, 0x52, 0xb9, 0xeb, 0x31,
- 0x66, 0x47, 0x10, 0x13, 0x24, 0x25, 0xa6, 0x72, 0x6d, 0xe4, 0xa9, 0xa5,
- 0x72, 0x1b, 0xcc, 0x5c, 0x47, 0x5b, 0x03, 0xdf, 0xaa, 0x8f, 0x65, 0x5b,
- 0xe5, 0x6e, 0xe6, 0x13, 0xe7, 0x1e, 0xd6, 0xf7, 0x74, 0xae, 0x5c, 0x6b,
- 0x4a, 0xe3, 0x7b, 0x21, 0x7b, 0x37, 0xe6, 0xd3, 0xf7, 0x88, 0x1a, 0xfc,
- 0x56, 0xe7, 0xe5, 0xf7, 0x94, 0xe1, 0x77, 0xc0, 0xe3, 0x18, 0xfb, 0xe9,
- 0xbc, 0x30, 0x79, 0x1d, 0xce, 0xa7, 0xf3, 0x7a, 0x58, 0x47, 0xdf, 0xa5,
- 0xc0, 0x53, 0xc5, 0xa5, 0x63, 0xf4, 0x9e, 0xb8, 0x1b, 0x5d, 0x37, 0xfc,
- 0x26, 0x7e, 0x29, 0x6b, 0x76, 0xeb, 0xef, 0x68, 0x81, 0xcd, 0x98, 0xd2,
- 0x32, 0x68, 0xe7, 0xb8, 0xaf, 0xf7, 0x21, 0x7f, 0x53, 0x5a, 0xfe, 0x8a,
- 0x88, 0x63, 0x26, 0x07, 0xb7, 0xa5, 0x6d, 0x75, 0xa0, 0x95, 0xf9, 0xd7,
- 0x61, 0x3f, 0xc4, 0x3d, 0xae, 0xd7, 0x6c, 0xc7, 0x99, 0x57, 0x0b, 0xf1,
- 0x4c, 0xb6, 0x04, 0xf9, 0xb6, 0x0f, 0xa3, 0x4b, 0xad, 0x4d, 0xba, 0x14,
- 0xee, 0x93, 0xfb, 0xe7, 0x73, 0xed, 0x3b, 0x15, 0x8b, 0x7e, 0xe4, 0xfb,
- 0x48, 0x43, 0x36, 0x78, 0xb7, 0xe4, 0x8b, 0x90, 0x41, 0xfd, 0x9d, 0x02,
- 0x7a, 0x54, 0xaf, 0x0f, 0x33, 0xc7, 0xbc, 0xf3, 0x0b, 0xe6, 0xde, 0x82,
- 0x3c, 0xcc, 0xfc, 0x83, 0xbd, 0x2a, 0xff, 0x30, 0x0c, 0x59, 0x81, 0x0f,
- 0xe0, 0x75, 0x68, 0x9f, 0x4e, 0xb9, 0xf4, 0x07, 0x9a, 0xbf, 0xbf, 0x3c,
- 0xda, 0x16, 0xf0, 0xe1, 0xed, 0xd6, 0xe0, 0x1b, 0xc4, 0xdf, 0x26, 0x57,
- 0x96, 0x39, 0xfe, 0x7f, 0x8c, 0xac, 0x1c, 0x86, 0x6d, 0x1e, 0x86, 0x2c,
- 0x22, 0x26, 0xd7, 0xf3, 0x1d, 0x96, 0xd2, 0xd3, 0x0b, 0x9d, 0x2b, 0xfb,
- 0xa3, 0xee, 0x58, 0xd8, 0xff, 0xb1, 0xa6, 0xfe, 0x8f, 0xa1, 0xff, 0x0b,
- 0x4d, 0xfd, 0x1f, 0x8b, 0xf4, 0x3f, 0xda, 0xd4, 0x1f, 0x31, 0xe2, 0xd3,
- 0xff, 0xdc, 0xd4, 0xff, 0x68, 0xa4, 0xff, 0x6c, 0x53, 0xff, 0x59, 0xf4,
- 0x7f, 0xad, 0xa9, 0x3f, 0xea, 0x8e, 0xb5, 0x98, 0xef, 0x62, 0xc4, 0xd8,
- 0x7d, 0x26, 0x16, 0xc7, 0xb3, 0xd6, 0xfc, 0xad, 0x85, 0x72, 0xd7, 0x83,
- 0x33, 0x08, 0xef, 0xb4, 0x51, 0x5f, 0xf3, 0xd0, 0xd7, 0x65, 0x5f, 0x26,
- 0x90, 0xc7, 0xa8, 0x2c, 0x12, 0x1f, 0x2a, 0x12, 0x73, 0x7d, 0xfa, 0x47,
- 0x56, 0xb9, 0x1a, 0xda, 0x24, 0xde, 0x5b, 0xe2, 0x7d, 0xd7, 0xc0, 0xf6,
- 0xc6, 0xdd, 0x45, 0x13, 0x83, 0x5d, 0xd1, 0x06, 0xda, 0x81, 0x97, 0x21,
- 0x66, 0xca, 0xe1, 0x40, 0x6f, 0x28, 0xbf, 0x9c, 0xdf, 0xe8, 0x0f, 0x65,
- 0xd5, 0xac, 0x33, 0xbc, 0x0a, 0xd7, 0xd2, 0xab, 0x72, 0x5b, 0xb1, 0x4b,
- 0xc0, 0xb5, 0x91, 0x06, 0xae, 0x7d, 0x51, 0xe6, 0x1a, 0xf1, 0xf6, 0x19,
- 0xd9, 0xef, 0xed, 0xe1, 0x3d, 0x9d, 0xc3, 0x79, 0xf9, 0x68, 0xe2, 0xed,
- 0x3d, 0x0d, 0x3b, 0xc9, 0x3b, 0x1d, 0xe9, 0x83, 0xbc, 0x83, 0x1b, 0xe6,
- 0x66, 0x27, 0xbd, 0x5f, 0xc7, 0xfe, 0x69, 0x33, 0x2f, 0x37, 0xde, 0xe6,
- 0x7c, 0x49, 0xd9, 0x1f, 0xdc, 0x77, 0x68, 0xcc, 0x5b, 0x69, 0xcc, 0x9b,
- 0x32, 0xfa, 0x46, 0x1b, 0xbc, 0x6c, 0x2f, 0x8b, 0xb0, 0x97, 0x63, 0x88,
- 0xb9, 0x17, 0xbd, 0xb5, 0xf2, 0xa3, 0x97, 0x6b, 0x2f, 0x9b, 0xf3, 0xcc,
- 0xcd, 0xf6, 0x92, 0xeb, 0x34, 0xe7, 0x96, 0xd3, 0x4d, 0xf8, 0x4f, 0x79,
- 0x3a, 0x67, 0x7c, 0x6a, 0x3c, 0xab, 0xe7, 0xa0, 0x8f, 0x4a, 0xc6, 0xb4,
- 0xfc, 0xb2, 0x1c, 0xc6, 0x96, 0xf7, 0x34, 0x62, 0xcb, 0xe5, 0x78, 0x10,
- 0xbe, 0x6b, 0xff, 0x67, 0x0c, 0x3e, 0xd2, 0x47, 0x76, 0xac, 0xb2, 0xb7,
- 0x5b, 0xed, 0xd5, 0x6d, 0xcc, 0x97, 0x5e, 0x2b, 0xb7, 0xea, 0x38, 0xfe,
- 0x8c, 0xc9, 0x4d, 0xcd, 0x69, 0xff, 0x9f, 0xdf, 0x0b, 0xca, 0xd9, 0x4d,
- 0xc6, 0xdf, 0xbb, 0x18, 0xae, 0xae, 0x8c, 0x4d, 0x95, 0x3a, 0x88, 0xb1,
- 0x8c, 0x4d, 0xfb, 0xdb, 0x89, 0xa1, 0x05, 0xff, 0x82, 0xe3, 0x31, 0x8e,
- 0xe3, 0xd9, 0x47, 0xc7, 0xa1, 0xe8, 0xb7, 0x68, 0xc6, 0x07, 0x71, 0x68,
- 0xc1, 0xff, 0x71, 0x5b, 0x80, 0x83, 0x17, 0x8a, 0x59, 0x3e, 0xdf, 0xce,
- 0xbc, 0xde, 0xa2, 0x77, 0x31, 0x5a, 0x57, 0xc7, 0xbd, 0xb1, 0x55, 0x71,
- 0xaf, 0x6d, 0xe2, 0xda, 0x5f, 0xd2, 0x71, 0x6f, 0xc0, 0x63, 0xee, 0x25,
- 0x1a, 0x47, 0xb9, 0xc0, 0x42, 0x7e, 0x53, 0x21, 0x3e, 0xd0, 0x47, 0x81,
- 0x9f, 0x35, 0xfd, 0x8b, 0xe0, 0x73, 0x72, 0x0d, 0xb9, 0xf9, 0xb8, 0xed,
- 0x44, 0xb8, 0xf7, 0x73, 0x12, 0xe4, 0xeb, 0x76, 0x83, 0x16, 0xc6, 0x56,
- 0x71, 0x23, 0x0f, 0x3f, 0x35, 0xf7, 0x2a, 0xc3, 0x7e, 0x61, 0x1c, 0xdf,
- 0xf8, 0xee, 0x5a, 0xc9, 0xaf, 0xc8, 0x9f, 0x74, 0x33, 0x0d, 0x8d, 0x73,
- 0xcf, 0x5f, 0xc6, 0x77, 0x8b, 0x0f, 0x73, 0x3f, 0xa2, 0xd9, 0xae, 0xf1,
- 0xbb, 0x29, 0xbf, 0x95, 0x8a, 0x75, 0x67, 0x9f, 0x0b, 0x1d, 0xe0, 0xbd,
- 0xe1, 0x28, 0xbe, 0x26, 0xa4, 0x34, 0x2b, 0x89, 0x64, 0x8e, 0xdf, 0x00,
- 0x68, 0xff, 0x7f, 0x68, 0xf6, 0x99, 0x92, 0x7d, 0x33, 0x41, 0xce, 0x53,
- 0x5d, 0xf0, 0x5e, 0xdc, 0xe3, 0xe0, 0x43, 0xe6, 0x50, 0x98, 0xf3, 0x54,
- 0xc1, 0xbd, 0xb8, 0x43, 0x1f, 0xdd, 0xbd, 0x38, 0xce, 0x6f, 0xcb, 0x9e,
- 0x35, 0xee, 0xc5, 0xc5, 0x2e, 0xf1, 0x5e, 0xdc, 0x26, 0x9d, 0xf3, 0xe4,
- 0x3c, 0x41, 0xce, 0x93, 0xe5, 0xad, 0x03, 0xcc, 0x95, 0xf0, 0xee, 0xdb,
- 0xa0, 0xbe, 0x2f, 0xbc, 0x75, 0xe0, 0xe7, 0x11, 0xa3, 0xfc, 0x75, 0xfb,
- 0xc7, 0x1f, 0xa3, 0x70, 0x2f, 0xbf, 0x11, 0x7c, 0xdf, 0x95, 0xcb, 0xc9,
- 0x03, 0x7c, 0xb8, 0xbc, 0xe6, 0x3e, 0x9d, 0xd7, 0x7c, 0xa7, 0x3d, 0x9a,
- 0xd7, 0x54, 0x17, 0xb9, 0x1b, 0xb6, 0x6f, 0x8d, 0xbc, 0x66, 0x3c, 0x72,
- 0x37, 0x2c, 0x6e, 0xee, 0x86, 0x6d, 0x72, 0x11, 0x4b, 0x9a, 0x3c, 0xa6,
- 0xba, 0xe0, 0xdd, 0xb0, 0xce, 0x0d, 0x1f, 0x3e, 0x8f, 0xb9, 0xea, 0x6e,
- 0x18, 0x6c, 0xdd, 0x16, 0x49, 0x5f, 0x56, 0xdc, 0xf3, 0x61, 0x62, 0x1e,
- 0xde, 0xab, 0x6f, 0xc1, 0x9e, 0xe3, 0xb2, 0x27, 0x49, 0xf9, 0xe4, 0xdd,
- 0xc6, 0x3e, 0xe8, 0x02, 0x9e, 0x3e, 0xcb, 0xfd, 0x3c, 0x23, 0x6b, 0xa4,
- 0x6f, 0xe5, 0x3d, 0x84, 0xe5, 0x3b, 0xbd, 0x89, 0xc6, 0x9d, 0xde, 0x29,
- 0xc8, 0x8d, 0x9a, 0x49, 0xc8, 0x7c, 0x44, 0xa6, 0x26, 0x3d, 0xf8, 0x4b,
- 0xb3, 0x8e, 0x69, 0xe7, 0xff, 0xef, 0x48, 0x02, 0xf3, 0x78, 0x0f, 0xb8,
- 0x43, 0x62, 0xb3, 0xc1, 0x37, 0xcb, 0xe0, 0xff, 0xb8, 0xa4, 0xd0, 0x87,
- 0x77, 0x3c, 0xe3, 0xb2, 0x5f, 0xe7, 0x2c, 0x42, 0x59, 0xfe, 0x35, 0xf0,
- 0x78, 0x73, 0x7e, 0xb9, 0x9c, 0x5c, 0xc3, 0xee, 0x27, 0xa5, 0x3c, 0x43,
- 0x79, 0xbe, 0xc1, 0xfc, 0xff, 0x82, 0xd3, 0x52, 0xf6, 0x4f, 0x99, 0xf8,
- 0x42, 0x7f, 0xdb, 0x01, 0x2f, 0xb7, 0x18, 0x1b, 0x8c, 0x67, 0x75, 0x0b,
- 0x6d, 0x1e, 0xd6, 0x38, 0x2e, 0xc3, 0xd3, 0x3b, 0x52, 0x7b, 0x81, 0x77,
- 0x63, 0x7a, 0xcd, 0xcb, 0xe1, 0xb9, 0x75, 0x9e, 0xef, 0x8d, 0x97, 0xca,
- 0xf7, 0xd0, 0x3f, 0xae, 0x62, 0x7f, 0x5b, 0x20, 0x1f, 0x5f, 0x95, 0xe2,
- 0xb1, 0x6b, 0x65, 0xf8, 0x68, 0x06, 0xf4, 0xbc, 0x5f, 0x2f, 0x67, 0xe1,
- 0x4b, 0x3f, 0xcd, 0x7b, 0x63, 0xc0, 0x50, 0xf0, 0xed, 0xf9, 0x55, 0xdf,
- 0xb1, 0xa3, 0x77, 0xcd, 0xfa, 0x1b, 0x77, 0x87, 0x9e, 0xf5, 0x25, 0xd1,
- 0x49, 0x9a, 0x67, 0x96, 0xef, 0x8f, 0x2f, 0xfa, 0xbb, 0xb4, 0x6d, 0x7b,
- 0xc6, 0x5f, 0x91, 0xfb, 0xd1, 0x67, 0x38, 0x5e, 0xfb, 0x1e, 0xec, 0xdb,
- 0x39, 0x8b, 0xf6, 0x6d, 0xca, 0x93, 0xab, 0x63, 0xc2, 0xf3, 0x10, 0x0b,
- 0x3c, 0xd0, 0x77, 0x38, 0x82, 0xef, 0xfb, 0x3d, 0xfa, 0x5c, 0x03, 0xac,
- 0x58, 0x88, 0xdc, 0xc1, 0x58, 0x3e, 0xdb, 0xe0, 0x6e, 0x46, 0x70, 0x16,
- 0xc1, 0xfd, 0x11, 0xed, 0x6f, 0x1e, 0xdc, 0xe3, 0x06, 0xf7, 0x47, 0x7a,
- 0x67, 0x59, 0xd7, 0xd5, 0x64, 0xfb, 0x12, 0x90, 0x01, 0xde, 0x3b, 0xe2,
- 0xbd, 0x71, 0xd2, 0xac, 0x73, 0x1d, 0xff, 0x47, 0xdd, 0xd5, 0xc7, 0xb6,
- 0x75, 0x5d, 0xf7, 0xc3, 0x47, 0xea, 0xc3, 0xb4, 0x2c, 0x53, 0x32, 0x25,
- 0xd3, 0x96, 0x2c, 0xbf, 0x27, 0x3d, 0x59, 0x72, 0xac, 0x14, 0xac, 0xab,
- 0xad, 0x02, 0x46, 0xa4, 0x0c, 0x49, 0x7f, 0xb4, 0x08, 0x06, 0xfa, 0xa3,
- 0x99, 0x8b, 0x66, 0xab, 0x4b, 0xd9, 0x4e, 0x0a, 0xf4, 0x0f, 0xb7, 0xc5,
- 0x80, 0x6c, 0x58, 0x60, 0x86, 0xb4, 0x12, 0x63, 0x56, 0x4c, 0xd6, 0x66,
- 0x85, 0x0c, 0xd8, 0x30, 0x4e, 0x54, 0x9c, 0x14, 0x50, 0xc6, 0x04, 0x69,
- 0x83, 0xa2, 0x58, 0x61, 0x45, 0x76, 0x36, 0x6c, 0x7f, 0x65, 0x43, 0xd0,
- 0x05, 0x9b, 0xb3, 0x38, 0x76, 0xb0, 0x06, 0x45, 0xd6, 0x7d, 0x62, 0x18,
- 0xd0, 0x0d, 0xdc, 0xf9, 0xdd, 0x0f, 0xf2, 0xf1, 0xf1, 0x51, 0x1f, 0x89,
- 0x33, 0x60, 0x02, 0x04, 0xbe, 0xf7, 0x78, 0xdf, 0x7b, 0xf7, 0x9e, 0x7b,
- 0xce, 0xb9, 0xbf, 0x73, 0xee, 0x39, 0x87, 0x9e, 0x7b, 0xdb, 0x9b, 0xf3,
- 0xb9, 0xca, 0x77, 0x8e, 0x8a, 0x77, 0x0e, 0x28, 0x9d, 0xa5, 0xe3, 0xc5,
- 0x63, 0xc6, 0x6c, 0x61, 0x22, 0xe2, 0x67, 0xfe, 0x9e, 0xad, 0xc2, 0xbe,
- 0x6e, 0x87, 0xe1, 0xd6, 0xa2, 0x67, 0xbc, 0x85, 0x9e, 0xcd, 0x32, 0xc1,
- 0xf6, 0x78, 0x5d, 0x77, 0x4b, 0xda, 0xc9, 0xeb, 0x88, 0x85, 0xd7, 0x31,
- 0x0e, 0x92, 0x76, 0x75, 0x19, 0xba, 0xe2, 0x8c, 0x6f, 0x68, 0xd0, 0xee,
- 0x74, 0x9d, 0x76, 0x3b, 0xff, 0x1f, 0xd1, 0xee, 0x1d, 0x81, 0x7f, 0x5f,
- 0xad, 0x22, 0x6e, 0x4d, 0x63, 0x00, 0x9d, 0x3b, 0x04, 0x3a, 0x42, 0x9f,
- 0x5a, 0xe5, 0x15, 0x82, 0x4e, 0x45, 0x5c, 0x71, 0xad, 0xf6, 0x5a, 0xb4,
- 0xee, 0xa7, 0x64, 0xbb, 0x04, 0xf6, 0x09, 0xfc, 0x79, 0xed, 0xd7, 0xc8,
- 0x63, 0x1f, 0x6b, 0x8d, 0x04, 0x56, 0x72, 0xdb, 0x27, 0x0c, 0x08, 0x1d,
- 0xf6, 0xc9, 0xb1, 0x4d, 0xda, 0x27, 0xe7, 0xa5, 0x7d, 0x92, 0xdd, 0xb8,
- 0x7d, 0xb2, 0xbb, 0x25, 0xae, 0xab, 0x31, 0x9e, 0xcd, 0xdb, 0x27, 0xc6,
- 0x9a, 0xf6, 0xc9, 0x90, 0xc3, 0x17, 0x83, 0xfe, 0xfe, 0x06, 0x65, 0x8f,
- 0x43, 0xc7, 0x69, 0x3a, 0x83, 0xc6, 0xc7, 0x5d, 0x7e, 0xe1, 0x4f, 0x93,
- 0xd6, 0xbf, 0xf8, 0x3f, 0xa6, 0xf5, 0x50, 0x8b, 0xcf, 0xbb, 0x31, 0x1e,
- 0x0a, 0xef, 0xd8, 0x14, 0x8e, 0x77, 0xd3, 0x7a, 0xa8, 0xad, 0xef, 0xb4,
- 0x7d, 0xcc, 0x62, 0xb3, 0xef, 0x74, 0xd4, 0x68, 0xa7, 0xdb, 0xff, 0xd8,
- 0xe1, 0x53, 0x75, 0xea, 0x77, 0xc8, 0x14, 0xf9, 0x8e, 0x4d, 0xe8, 0x77,
- 0x41, 0x96, 0xac, 0x6c, 0x96, 0x60, 0x33, 0xe1, 0x7d, 0x11, 0x21, 0x6b,
- 0x2e, 0xbc, 0xc5, 0xef, 0x63, 0x7a, 0xbe, 0xf8, 0x87, 0x62, 0x9d, 0x92,
- 0xfe, 0x07, 0xb4, 0x0f, 0xfb, 0xce, 0x88, 0xb6, 0x32, 0xbe, 0x49, 0xf9,
- 0x23, 0x14, 0xf6, 0x6f, 0xe7, 0x87, 0x68, 0x5d, 0xf3, 0x36, 0x67, 0x2b,
- 0x68, 0x19, 0xdf, 0xcb, 0xf3, 0x12, 0x69, 0xb2, 0xb5, 0xa0, 0x3f, 0xcf,
- 0x33, 0x2e, 0x18, 0xad, 0x63, 0x82, 0xe6, 0xb9, 0xb9, 0x28, 0x6c, 0x3a,
- 0xad, 0x3b, 0x57, 0x64, 0xec, 0xa9, 0xb8, 0x0e, 0x9c, 0xa6, 0x75, 0xa7,
- 0x1b, 0x07, 0xef, 0xf5, 0xe0, 0x0b, 0xcf, 0xdc, 0x4f, 0x3d, 0x77, 0x26,
- 0x62, 0xce, 0x53, 0x9e, 0x73, 0x57, 0xcf, 0xe1, 0xca, 0x36, 0xda, 0xca,
- 0xfb, 0x53, 0x62, 0x5c, 0xdf, 0xfc, 0x62, 0x02, 0xb9, 0x6a, 0xf5, 0xfc,
- 0x21, 0x77, 0xce, 0x14, 0xd6, 0x01, 0x2d, 0x87, 0x3a, 0x3f, 0x1b, 0xb4,
- 0x18, 0xf1, 0xc8, 0x99, 0x72, 0xae, 0x25, 0xb8, 0xcf, 0x4d, 0x8b, 0xc6,
- 0x3a, 0x32, 0xa7, 0xd6, 0x91, 0x45, 0x87, 0x1e, 0x6f, 0xc5, 0xed, 0xfd,
- 0x1e, 0xb8, 0xdd, 0x2b, 0x6f, 0x0a, 0x7d, 0x7a, 0x92, 0x71, 0xc8, 0x67,
- 0x80, 0x43, 0x42, 0xc8, 0x5b, 0x92, 0x58, 0x04, 0xdf, 0x17, 0x19, 0x8f,
- 0x44, 0x98, 0x57, 0x7e, 0x44, 0xe7, 0x18, 0x6b, 0x5f, 0xa7, 0xfd, 0xca,
- 0x3e, 0x83, 0xdc, 0xea, 0x38, 0x53, 0xc4, 0xf1, 0xfb, 0x28, 0xfb, 0x98,
- 0x35, 0x19, 0xa7, 0x1f, 0xd1, 0x59, 0x11, 0x33, 0x83, 0xfd, 0x3d, 0xc4,
- 0x1c, 0x3c, 0x20, 0xde, 0x2f, 0x7d, 0x19, 0xf7, 0x23, 0xa6, 0x6e, 0xe3,
- 0xf1, 0xfb, 0x2a, 0xb7, 0x8e, 0xdb, 0xe1, 0x9d, 0x4b, 0x4a, 0xa6, 0xc4,
- 0x35, 0xbe, 0xff, 0x49, 0xa3, 0xf5, 0xfe, 0xb8, 0x91, 0xaa, 0xa6, 0x8c,
- 0x44, 0x05, 0xed, 0x9e, 0x34, 0x92, 0x55, 0xd8, 0x90, 0x9a, 0x47, 0xac,
- 0x28, 0xe4, 0x6d, 0x95, 0xd6, 0xdf, 0x8b, 0x58, 0x24, 0x57, 0x9e, 0xc4,
- 0x06, 0xfa, 0x7d, 0xb8, 0xa9, 0xdf, 0x9a, 0xbe, 0x38, 0x86, 0xbf, 0xe7,
- 0x15, 0xa6, 0xa9, 0xc6, 0xb5, 0x41, 0xf8, 0xd7, 0x27, 0xb3, 0xb4, 0x16,
- 0xae, 0xb5, 0x5a, 0x70, 0xed, 0xe2, 0xba, 0xfd, 0xfe, 0xa4, 0x32, 0x2e,
- 0xf3, 0xa3, 0xfd, 0xb6, 0xc0, 0xaf, 0xdc, 0xef, 0x26, 0x6c, 0xeb, 0xe2,
- 0x29, 0xb4, 0xd1, 0x7e, 0x70, 0xed, 0x07, 0xeb, 0x55, 0xf1, 0xc0, 0x3a,
- 0x3e, 0x21, 0x88, 0x7c, 0xaf, 0x90, 0x8c, 0x6b, 0x85, 0x8d, 0xb5, 0xc2,
- 0xfd, 0x83, 0xbd, 0x05, 0x9f, 0x8f, 0xb0, 0xb7, 0xcc, 0x24, 0x49, 0x5f,
- 0xf7, 0x99, 0xaa, 0xd3, 0xbf, 0xeb, 0x95, 0x4b, 0x39, 0xea, 0x91, 0x4b,
- 0xe9, 0x94, 0xb5, 0x80, 0x43, 0xd6, 0x22, 0x0e, 0xdc, 0x36, 0xcc, 0x76,
- 0x4b, 0x0f, 0xeb, 0x90, 0x1e, 0xb1, 0x6d, 0xe2, 0xbf, 0xea, 0xb4, 0x5b,
- 0xdc, 0x79, 0xf1, 0x90, 0x3b, 0x60, 0x33, 0x69, 0xc3, 0xa4, 0x4a, 0xf5,
- 0x9c, 0x7a, 0x1e, 0x77, 0x23, 0x6f, 0xb1, 0xd2, 0x92, 0x63, 0xe9, 0xd5,
- 0xdf, 0x91, 0x96, 0xfe, 0x62, 0xfd, 0x8a, 0xb7, 0xc5, 0x74, 0x5e, 0x76,
- 0xd5, 0xfd, 0xea, 0x9f, 0x5b, 0x9f, 0xe1, 0x5d, 0xa3, 0xc2, 0xe7, 0x9d,
- 0xad, 0xeb, 0xb2, 0x19, 0xd9, 0xdf, 0x42, 0xb3, 0x9d, 0xe1, 0xbf, 0x42,
- 0x8a, 0x76, 0xde, 0xba, 0x7d, 0x73, 0xfe, 0xb3, 0xad, 0x6e, 0x1c, 0xdc,
- 0x27, 0xfd, 0x62, 0x73, 0x2a, 0x0e, 0x7b, 0x40, 0xd9, 0x7b, 0xeb, 0xf1,
- 0x3b, 0xae, 0xcd, 0x29, 0x5f, 0xa2, 0x65, 0x96, 0x09, 0x7c, 0x7e, 0xfc,
- 0x54, 0x87, 0x1d, 0x52, 0x7b, 0x59, 0xd8, 0xaf, 0x02, 0xdf, 0xeb, 0xe7,
- 0x43, 0x67, 0x6f, 0x64, 0xce, 0xcc, 0x96, 0x39, 0x93, 0x7c, 0x05, 0x5b,
- 0x0b, 0xf1, 0xc5, 0x53, 0xae, 0x18, 0xef, 0x4f, 0x42, 0x8b, 0x5e, 0x8f,
- 0xb8, 0x67, 0xc4, 0x2d, 0xb7, 0xeb, 0xe7, 0x1d, 0x07, 0x2e, 0x47, 0x7f,
- 0x6b, 0xb5, 0x57, 0xa2, 0xbb, 0xe5, 0x5a, 0x5c, 0xf5, 0xc6, 0x48, 0xa1,
- 0x0d, 0xf7, 0xcf, 0xbd, 0xf6, 0xee, 0xda, 0xe0, 0xda, 0x2b, 0xea, 0x8b,
- 0xf8, 0x0e, 0x09, 0x1d, 0xd0, 0x43, 0x95, 0x12, 0xe2, 0xaf, 0x3f, 0x0b,
- 0x99, 0x67, 0x3d, 0xeb, 0xc8, 0x49, 0xf3, 0x9e, 0xc7, 0xfa, 0x9e, 0x4a,
- 0x20, 0x86, 0xbd, 0x3f, 0xc4, 0x96, 0xf4, 0xb3, 0xee, 0x41, 0xfb, 0x71,
- 0xf3, 0x16, 0xfc, 0xbd, 0xca, 0xff, 0x94, 0x52, 0xeb, 0xcb, 0xa1, 0x0d,
- 0xec, 0xad, 0x6c, 0x4e, 0x4f, 0x5b, 0xe6, 0x0a, 0x61, 0xdf, 0x07, 0xf1,
- 0xc2, 0xc7, 0x7a, 0xa9, 0xf7, 0x2b, 0x5d, 0x5d, 0xf6, 0x1f, 0xf4, 0xc9,
- 0xbd, 0x28, 0x7c, 0xd7, 0x43, 0x2f, 0x94, 0x10, 0xcb, 0x8d, 0xef, 0x7e,
- 0x8b, 0xbf, 0xf3, 0xd2, 0x51, 0x3a, 0x16, 0x1d, 0x58, 0x4e, 0xce, 0x4f,
- 0x99, 0x60, 0x2b, 0xd5, 0xe8, 0x6f, 0xa2, 0x9f, 0x93, 0xfb, 0x19, 0xd5,
- 0xfb, 0xbd, 0x57, 0xe3, 0xe5, 0x2f, 0xfc, 0x69, 0xdf, 0xc7, 0x8d, 0x8d,
- 0xfc, 0xd6, 0x86, 0xfc, 0x85, 0xd8, 0xe7, 0xdf, 0xc8, 0x9e, 0x89, 0xde,
- 0x1b, 0x9e, 0x16, 0x39, 0xa7, 0x4e, 0x3e, 0xb8, 0x3f, 0xfb, 0xc3, 0xe0,
- 0x87, 0x91, 0x16, 0x5d, 0xf5, 0xc9, 0xfd, 0xfd, 0x6e, 0xba, 0x06, 0x3d,
- 0x7d, 0x55, 0xde, 0xfb, 0xc0, 0xd8, 0xf3, 0x87, 0x9f, 0xba, 0x4a, 0x67,
- 0xae, 0x81, 0x87, 0x0d, 0xe6, 0xb6, 0x31, 0xca, 0x87, 0x91, 0x57, 0x24,
- 0x72, 0x73, 0xf4, 0xbe, 0xa1, 0xc8, 0x15, 0x3a, 0x23, 0x72, 0x20, 0xc7,
- 0x23, 0xf7, 0x78, 0x3d, 0x3c, 0x53, 0x7d, 0x9b, 0xce, 0x56, 0x82, 0xfc,
- 0xdf, 0xc0, 0xee, 0xad, 0x79, 0x90, 0xcd, 0x3c, 0x7e, 0x4f, 0xf0, 0xf8,
- 0xf0, 0x9a, 0x3c, 0x7e, 0xa4, 0xce, 0xe3, 0x5f, 0xe9, 0x97, 0xfc, 0xdc,
- 0xcb, 0xcf, 0xea, 0xa5, 0x43, 0xe2, 0xb9, 0x6f, 0xf3, 0xf1, 0x56, 0x3a,
- 0x14, 0x92, 0xc7, 0x67, 0x2b, 0xac, 0xe3, 0x0b, 0x6f, 0xd3, 0xb9, 0x6b,
- 0x59, 0x5f, 0x4a, 0xe4, 0x2f, 0x38, 0x6b, 0x69, 0xe8, 0xfb, 0xd1, 0xae,
- 0x1d, 0xff, 0x6b, 0xbd, 0x24, 0x73, 0xae, 0xca, 0x52, 0x3f, 0xd1, 0x5b,
- 0xd1, 0x21, 0x17, 0xff, 0x37, 0xdb, 0x8e, 0xe7, 0xd5, 0x1a, 0x78, 0x7c,
- 0x0d, 0xbf, 0x46, 0x2b, 0x5f, 0xf6, 0x79, 0xe0, 0xe1, 0xa7, 0xfb, 0xe5,
- 0x3e, 0xd5, 0x5a, 0x7e, 0x8d, 0xa6, 0xb8, 0x0e, 0xe7, 0xbe, 0x3d, 0xeb,
- 0xfd, 0x3d, 0x2a, 0x17, 0xf0, 0x87, 0xfd, 0x72, 0xbd, 0x40, 0x7e, 0xe0,
- 0x0a, 0xd3, 0xe1, 0x22, 0x63, 0x95, 0x21, 0xea, 0xbc, 0xaa, 0xc7, 0x3a,
- 0x24, 0xf4, 0xad, 0xd3, 0x4f, 0x73, 0x51, 0xe5, 0x76, 0xe7, 0x1c, 0x63,
- 0xba, 0x28, 0x6c, 0x9c, 0xf6, 0xf2, 0xd6, 0x3e, 0xe6, 0x6a, 0xd8, 0xb5,
- 0x26, 0xb8, 0xf9, 0x0d, 0x75, 0x4a, 0x30, 0xbf, 0x64, 0x48, 0x1c, 0x3c,
- 0xc3, 0xf8, 0x76, 0xb3, 0xfb, 0x45, 0x9f, 0x14, 0x23, 0xba, 0x6b, 0x60,
- 0xb8, 0x8f, 0x31, 0x0f, 0xd2, 0xe6, 0xc8, 0xbc, 0x58, 0x15, 0xba, 0xe0,
- 0xe2, 0x54, 0x8d, 0x92, 0xd1, 0x6d, 0x94, 0x99, 0xe2, 0x77, 0xcf, 0xd8,
- 0x6c, 0x7b, 0xf9, 0x29, 0xcb, 0xf2, 0x9b, 0x99, 0xda, 0xa2, 0xf0, 0xa2,
- 0xf6, 0xa7, 0x77, 0xa9, 0x38, 0x87, 0x5e, 0xb1, 0x2f, 0x29, 0x6b, 0xf5,
- 0xf0, 0x71, 0x45, 0x3f, 0x1b, 0xd7, 0xc1, 0xbb, 0x9d, 0xaa, 0xdd, 0x65,
- 0x47, 0x3b, 0xb4, 0xb9, 0xac, 0xda, 0xe2, 0x99, 0x1a, 0x53, 0x74, 0x2b,
- 0x7d, 0x0b, 0x39, 0x5c, 0x51, 0xb9, 0x7a, 0xc2, 0x7e, 0xa0, 0xd9, 0xfa,
- 0x58, 0x2e, 0x73, 0xdb, 0xff, 0xae, 0xc5, 0x85, 0x2d, 0x77, 0x99, 0x31,
- 0x6f, 0x55, 0xc8, 0x8a, 0xbb, 0x4f, 0x18, 0x8b, 0x5f, 0xec, 0x0f, 0xf1,
- 0xb1, 0x7a, 0xcf, 0xe9, 0x7a, 0x9f, 0x10, 0xa3, 0x61, 0x45, 0xe4, 0xb3,
- 0x74, 0xbb, 0xcb, 0x8e, 0x76, 0x5a, 0x57, 0xe8, 0xfd, 0x87, 0x8f, 0x7c,
- 0xb3, 0x85, 0xdb, 0x3e, 0x19, 0xc3, 0x1b, 0x12, 0xfb, 0xa7, 0x32, 0x46,
- 0x43, 0x1f, 0xc3, 0xbf, 0x8c, 0x98, 0x0a, 0xc4, 0x49, 0x38, 0xf5, 0x8d,
- 0x1c, 0x6f, 0x00, 0x6b, 0x51, 0x15, 0xfb, 0xa6, 0xd8, 0xaf, 0x68, 0x87,
- 0x9d, 0x77, 0x21, 0x36, 0x7f, 0x13, 0x18, 0x74, 0x23, 0xf2, 0x67, 0x7a,
- 0xc8, 0x9f, 0xf3, 0xfd, 0xc8, 0x83, 0x43, 0x3e, 0x5c, 0x76, 0xd2, 0xa0,
- 0x1a, 0xdb, 0x0a, 0x06, 0x95, 0x43, 0x3e, 0x3a, 0x67, 0x5b, 0xd1, 0x8a,
- 0xc0, 0x9a, 0x8f, 0xc0, 0x7f, 0x35, 0xb9, 0x42, 0x07, 0x44, 0xce, 0x38,
- 0x6a, 0x1f, 0x94, 0x79, 0x0d, 0x3e, 0xcd, 0x3c, 0x78, 0x96, 0xed, 0x8f,
- 0xec, 0x49, 0xec, 0xb7, 0xe8, 0x79, 0x41, 0x0e, 0x3c, 0x3e, 0x4d, 0x9e,
- 0xbb, 0xdf, 0xdd, 0x41, 0xc1, 0x38, 0x3f, 0xd3, 0x84, 0x7e, 0xe2, 0xe7,
- 0xa4, 0x29, 0xc1, 0x76, 0x12, 0x6c, 0xd6, 0xd3, 0x27, 0xad, 0x50, 0x99,
- 0x0c, 0x6e, 0x0b, 0xdb, 0x15, 0xcf, 0xc1, 0xfd, 0xf1, 0x50, 0x07, 0xb9,
- 0x73, 0x72, 0x7b, 0x45, 0x9e, 0xe2, 0x5b, 0xd1, 0x07, 0xc9, 0x18, 0x84,
- 0xbe, 0xc2, 0xbc, 0x3d, 0xa0, 0xf6, 0x89, 0xb6, 0xf3, 0xf1, 0x84, 0x3a,
- 0x0e, 0x8a, 0xf9, 0x94, 0xc7, 0x9a, 0xbf, 0xf1, 0xf7, 0xf3, 0x2e, 0xb2,
- 0xfd, 0x6a, 0xfe, 0x9a, 0x62, 0x41, 0x22, 0x63, 0x46, 0x90, 0xce, 0x57,
- 0xd6, 0xf2, 0xbf, 0x78, 0xe5, 0xba, 0x6e, 0xdf, 0x60, 0xae, 0xeb, 0x4f,
- 0x76, 0xc8, 0xdc, 0x32, 0x67, 0x5f, 0xfe, 0x93, 0xfb, 0xe2, 0x85, 0xc9,
- 0x5a, 0x70, 0x22, 0x8f, 0xb7, 0x46, 0x3f, 0x8b, 0x7e, 0x9e, 0xee, 0x84,
- 0x23, 0x2a, 0x66, 0x09, 0x31, 0x4a, 0x0f, 0x2a, 0xbe, 0xd6, 0xba, 0x9f,
- 0x3c, 0x74, 0xff, 0xa3, 0x22, 0x56, 0x53, 0xae, 0x1d, 0x43, 0x8a, 0x1e,
- 0xa0, 0x59, 0xc4, 0x41, 0xb3, 0x01, 0x07, 0xcd, 0x0c, 0x75, 0xbc, 0x4d,
- 0x9c, 0x9f, 0xaf, 0x3c, 0xb5, 0x5d, 0xe6, 0x8b, 0x63, 0x2f, 0xf1, 0x92,
- 0x3a, 0x5e, 0x6f, 0xbc, 0x56, 0x98, 0x82, 0xc2, 0xdf, 0xe4, 0x18, 0xeb,
- 0xcb, 0x44, 0xf6, 0x81, 0x70, 0x2b, 0x0d, 0x5e, 0x73, 0x5c, 0x47, 0x1f,
- 0xc7, 0x1d, 0x7d, 0x1c, 0x75, 0xf4, 0x71, 0x6f, 0x9b, 0x3e, 0xb2, 0x8e,
- 0xe7, 0xf7, 0x9c, 0xad, 0x7e, 0xdc, 0xbe, 0xa2, 0x9f, 0xc8, 0x23, 0x06,
- 0x3d, 0xb7, 0x52, 0x2e, 0x1c, 0x51, 0x6b, 0xc7, 0x2f, 0x55, 0x2e, 0xba,
- 0x57, 0x9f, 0xff, 0x8e, 0xda, 0xcf, 0x9b, 0x93, 0x57, 0x9d, 0xf9, 0xc7,
- 0xdf, 0xa5, 0xa4, 0xcc, 0x23, 0x57, 0xb2, 0x7d, 0xb9, 0x8d, 0x1f, 0x1a,
- 0xf1, 0x1c, 0xc0, 0x20, 0xc2, 0x2e, 0xdc, 0x2d, 0x6b, 0xc1, 0x05, 0x68,
- 0xa9, 0x9e, 0xcb, 0xeb, 0x57, 0xb9, 0x3b, 0xc7, 0xc3, 0xf7, 0x37, 0x8f,
- 0x17, 0xd7, 0xff, 0x4c, 0xf8, 0xf2, 0xe4, 0xfe, 0xd1, 0x8a, 0xca, 0x47,
- 0xb6, 0x4c, 0xc4, 0x06, 0x2c, 0x2e, 0xc3, 0xff, 0xda, 0x2e, 0x77, 0x57,
- 0xea, 0xa2, 0x4c, 0xbd, 0x3e, 0x4a, 0x59, 0xe4, 0x35, 0x48, 0xff, 0x98,
- 0xcc, 0xbf, 0x5d, 0x5c, 0xbe, 0x25, 0x72, 0x5e, 0x13, 0x2a, 0x8f, 0x37,
- 0x43, 0x3d, 0x02, 0xe7, 0x7e, 0xfc, 0xfc, 0xdb, 0x17, 0xc2, 0x9b, 0xcf,
- 0xbf, 0x75, 0xde, 0xb3, 0xb9, 0xfc, 0xdb, 0x10, 0x8f, 0xdd, 0x58, 0x90,
- 0xf9, 0xb7, 0xcd, 0x7b, 0x32, 0x32, 0xff, 0x36, 0xe3, 0xc0, 0x0f, 0x12,
- 0xaf, 0xbf, 0xe5, 0x88, 0xdf, 0x96, 0xb9, 0xb5, 0x8b, 0x75, 0xcc, 0x2a,
- 0x73, 0x6b, 0x65, 0xbc, 0xb7, 0xb3, 0x0e, 0x8c, 0xdc, 0xfb, 0x91, 0xef,
- 0xd9, 0xe6, 0xda, 0xfb, 0x91, 0x39, 0xb5, 0xa6, 0xd1, 0xce, 0x86, 0xc3,
- 0x1a, 0x81, 0x7a, 0x08, 0x71, 0xe6, 0xdd, 0xad, 0x6d, 0xea, 0x21, 0xc4,
- 0xdb, 0xd4, 0x43, 0x70, 0xea, 0x7e, 0x27, 0xc6, 0x02, 0x26, 0xc6, 0xda,
- 0x08, 0x2c, 0x8c, 0x7a, 0x06, 0x51, 0x3a, 0x5f, 0xc7, 0x9e, 0x0f, 0x52,
- 0x5a, 0x61, 0xcf, 0xf3, 0x15, 0xad, 0x8f, 0x46, 0x5d, 0xfa, 0xc8, 0x0b,
- 0x8b, 0x5a, 0x2a, 0xce, 0x47, 0xcb, 0x6b, 0xd6, 0x21, 0xaf, 0x59, 0x0f,
- 0x79, 0xc5, 0x3d, 0xd9, 0x36, 0xfd, 0xfe, 0xa5, 0xba, 0x07, 0xff, 0x4f,
- 0x46, 0x50, 0xb3, 0x85, 0x68, 0xf7, 0x80, 0xc2, 0x7f, 0x0e, 0x79, 0x3d,
- 0xcb, 0xf2, 0xaa, 0xaf, 0xa3, 0xbf, 0xed, 0x6c, 0x00, 0x8d, 0x19, 0x87,
- 0x7c, 0x87, 0xaf, 0xbd, 0x21, 0xe2, 0xa4, 0x9a, 0xed, 0x45, 0x8d, 0x27,
- 0xf6, 0x09, 0x59, 0xba, 0xe3, 0x47, 0xdc, 0x8a, 0xbe, 0x16, 0x52, 0x7e,
- 0x32, 0x4d, 0x8b, 0xce, 0x26, 0xcc, 0xd1, 0xc0, 0x1b, 0x22, 0xc6, 0xd7,
- 0xd1, 0xb7, 0x7f, 0xe5, 0xbe, 0xe9, 0xeb, 0x7a, 0xcd, 0x7c, 0xa7, 0xc9,
- 0x9f, 0x71, 0xa3, 0xa9, 0xee, 0x1f, 0x7c, 0x47, 0xdb, 0xd2, 0x86, 0x9d,
- 0x12, 0x31, 0xa6, 0x7d, 0x36, 0xfc, 0x64, 0x09, 0x96, 0xfd, 0xbe, 0x34,
- 0xe2, 0x99, 0xfb, 0xae, 0x98, 0x74, 0xa2, 0x70, 0x7e, 0x8f, 0xe4, 0x95,
- 0x0b, 0xa2, 0xa6, 0x25, 0x6a, 0x20, 0x26, 0x79, 0x7d, 0x4e, 0x30, 0xe8,
- 0x9c, 0xab, 0x76, 0xd1, 0x22, 0xa3, 0x7b, 0xbf, 0x5d, 0x16, 0xbe, 0x3e,
- 0xd6, 0x49, 0x45, 0xd4, 0x36, 0x35, 0x16, 0x3a, 0xf9, 0xb9, 0x83, 0xb4,
- 0x54, 0x1a, 0x17, 0x35, 0xa1, 0x64, 0x7d, 0x11, 0xb4, 0xf5, 0x51, 0xbf,
- 0xfd, 0x0d, 0xa6, 0xdd, 0xd7, 0x44, 0x8c, 0xe5, 0x62, 0xf1, 0x82, 0xfc,
- 0x2c, 0x3f, 0xa5, 0xde, 0xc1, 0xef, 0xab, 0xfe, 0x98, 0xe2, 0xfd, 0xa6,
- 0xc3, 0x96, 0x73, 0xfe, 0x79, 0xe3, 0x95, 0x63, 0x9b, 0xc2, 0x2b, 0xd9,
- 0x74, 0x03, 0xaf, 0x38, 0x9f, 0xad, 0xb1, 0xcb, 0xe4, 0xa0, 0xac, 0xf7,
- 0x00, 0x1a, 0x6c, 0x05, 0x16, 0x4b, 0x83, 0x96, 0x46, 0xcc, 0x8a, 0x24,
- 0xfc, 0x33, 0x94, 0xaf, 0x5e, 0xa7, 0x4c, 0x11, 0x98, 0x99, 0x3f, 0xcb,
- 0xe7, 0x76, 0x4a, 0x1f, 0x8d, 0xbe, 0x07, 0x7a, 0x65, 0x07, 0xb7, 0xff,
- 0xeb, 0x41, 0x19, 0x97, 0xed, 0xbc, 0xde, 0xcb, 0xd7, 0xbf, 0x10, 0x69,
- 0xbe, 0xbe, 0x85, 0xaf, 0xf7, 0xa7, 0x31, 0x87, 0xc6, 0x15, 0xf8, 0x25,
- 0x27, 0x29, 0xc7, 0xf3, 0x93, 0xaf, 0xf2, 0xda, 0x7a, 0x95, 0xf5, 0x55,
- 0x45, 0xb7, 0x1b, 0x40, 0xce, 0x8e, 0x98, 0x13, 0x83, 0xdb, 0x5c, 0x2c,
- 0x4c, 0x71, 0xbb, 0x21, 0xf2, 0x5f, 0x35, 0x29, 0x5f, 0xd1, 0xbc, 0xaa,
- 0xe3, 0xed, 0xdf, 0x18, 0x90, 0x31, 0x55, 0xef, 0xec, 0x94, 0xf4, 0x9b,
- 0x14, 0x3e, 0x4f, 0xc4, 0x73, 0x3c, 0x23, 0xf8, 0xd0, 0x9a, 0x31, 0xeb,
- 0xef, 0xdf, 0x06, 0xbe, 0x42, 0xdd, 0x54, 0x1e, 0x03, 0xeb, 0xc5, 0x98,
- 0x1d, 0xca, 0xd5, 0x63, 0xd5, 0x9e, 0xdb, 0x2d, 0xef, 0xff, 0xe9, 0x80,
- 0xac, 0x55, 0x7a, 0x5b, 0x9d, 0xeb, 0x35, 0x07, 0xf1, 0xcb, 0x3e, 0x41,
- 0x1b, 0xff, 0x02, 0xf4, 0xa5, 0xc1, 0xc7, 0x3c, 0x9e, 0x34, 0xfa, 0xf8,
- 0xb3, 0x01, 0x5d, 0x9f, 0x50, 0x8e, 0xeb, 0x28, 0xf7, 0x37, 0xc5, 0xe3,
- 0xd2, 0xd7, 0xe3, 0x7c, 0xee, 0x35, 0xbf, 0x78, 0x56, 0x30, 0x2d, 0xeb,
- 0x8b, 0x05, 0xd3, 0x99, 0x49, 0x39, 0xcf, 0x0d, 0x9f, 0x6e, 0xa4, 0xee,
- 0xd3, 0x9d, 0x2b, 0xf4, 0x0f, 0xc2, 0xbf, 0x61, 0x5c, 0xe1, 0xf9, 0x0e,
- 0x3f, 0xc3, 0x6d, 0x91, 0xab, 0x90, 0xe3, 0xcf, 0x1e, 0x15, 0xd7, 0xd3,
- 0xca, 0x2b, 0x32, 0x4e, 0x42, 0xaf, 0x5b, 0xb8, 0x77, 0x80, 0x9f, 0x21,
- 0xd7, 0xae, 0xf6, 0xef, 0xa1, 0x96, 0x38, 0x98, 0x56, 0x1e, 0x5b, 0xcb,
- 0x0f, 0x2b, 0xf6, 0x13, 0x3d, 0xf8, 0x6c, 0xad, 0x7a, 0x06, 0xef, 0x08,
- 0x3f, 0x5a, 0xb2, 0x45, 0x5e, 0x21, 0xc7, 0x01, 0xfa, 0xce, 0x7c, 0x96,
- 0xb6, 0xf0, 0x5c, 0x7d, 0xc3, 0xf8, 0x35, 0xec, 0xb7, 0x93, 0x8c, 0x79,
- 0x62, 0x1a, 0x17, 0xec, 0xc9, 0xb3, 0x06, 0xd3, 0xb9, 0x90, 0xad, 0x05,
- 0xec, 0x1e, 0xea, 0x64, 0x59, 0xfd, 0x22, 0x8d, 0xb1, 0xfd, 0x07, 0x99,
- 0xb5, 0x23, 0x29, 0x82, 0xbc, 0x59, 0xa1, 0xc3, 0xcc, 0x13, 0xc9, 0x2a,
- 0xf8, 0xd9, 0xa0, 0x27, 0x4a, 0x44, 0x8f, 0x97, 0xc6, 0x42, 0xdf, 0x27,
- 0xdb, 0x6c, 0x7c, 0x6f, 0x85, 0x12, 0xdc, 0x8f, 0x54, 0xf5, 0x77, 0xe8,
- 0x43, 0x51, 0xe7, 0x04, 0x74, 0xd4, 0xf3, 0xfe, 0xdb, 0x74, 0x3a, 0x8d,
- 0x7e, 0x6f, 0x5c, 0x3e, 0x4f, 0x6c, 0x4a, 0x3e, 0x83, 0x1e, 0xf2, 0xf9,
- 0xea, 0xa0, 0xe4, 0x9b, 0x1a, 0xf3, 0x68, 0x90, 0x66, 0x8b, 0x88, 0x01,
- 0x7b, 0x18, 0x75, 0xa7, 0x8a, 0x19, 0xd6, 0x4b, 0x99, 0x86, 0x5e, 0xba,
- 0x94, 0xf0, 0xc7, 0x21, 0xe3, 0xa8, 0xcb, 0xa6, 0xe2, 0x7e, 0x30, 0x8e,
- 0xdd, 0x34, 0xb6, 0xb0, 0x95, 0xef, 0xa5, 0x95, 0xc4, 0x74, 0x5c, 0xe5,
- 0xfa, 0x5b, 0x66, 0x92, 0xf5, 0xe3, 0x1c, 0xcb, 0x72, 0xae, 0xf8, 0x00,
- 0x2d, 0x86, 0x87, 0x69, 0x74, 0x41, 0xd7, 0x37, 0xc1, 0x58, 0xff, 0x6d,
- 0x48, 0xea, 0x24, 0x3d, 0xee, 0x5f, 0x11, 0xbe, 0x0b, 0xf3, 0xfa, 0xa7,
- 0x35, 0xee, 0xad, 0xeb, 0xe8, 0xa5, 0xbf, 0x52, 0x32, 0x5b, 0xbb, 0x91,
- 0x88, 0x52, 0x36, 0x31, 0xfd, 0x97, 0x82, 0xff, 0x47, 0xaf, 0xc3, 0x0f,
- 0x07, 0x1d, 0x6d, 0x52, 0xba, 0xe0, 0xa6, 0xc5, 0x30, 0x8f, 0x1b, 0xdf,
- 0xd7, 0xfe, 0x79, 0x36, 0xfa, 0x94, 0x58, 0xfb, 0xc7, 0xae, 0x73, 0x3b,
- 0xb1, 0x36, 0x69, 0xbd, 0xe1, 0xc5, 0x87, 0xba, 0x8e, 0xa5, 0xe6, 0x45,
- 0x19, 0xeb, 0xc9, 0xf8, 0x2d, 0x94, 0xf6, 0xbb, 0x79, 0xf2, 0x23, 0x3a,
- 0x36, 0x6f, 0xd2, 0xf1, 0x82, 0xf5, 0x7c, 0x96, 0x66, 0x58, 0xae, 0x9d,
- 0xeb, 0x05, 0xb7, 0x27, 0xf0, 0x59, 0x8c, 0x65, 0x9f, 0xed, 0xe6, 0xa2,
- 0x29, 0xe3, 0xee, 0x44, 0xed, 0xb9, 0x2e, 0xa1, 0x47, 0x43, 0xf6, 0x3f,
- 0x0d, 0xea, 0xf5, 0x20, 0x53, 0x44, 0x1e, 0x21, 0x7f, 0x96, 0xb9, 0x7d,
- 0x61, 0x90, 0x32, 0x25, 0x3c, 0x07, 0xeb, 0x1d, 0xfa, 0xce, 0xe7, 0x4b,
- 0x72, 0x5e, 0x47, 0xf9, 0xd9, 0xc8, 0xbb, 0x3f, 0x5e, 0x9d, 0x12, 0xb1,
- 0x77, 0xd0, 0xcd, 0x72, 0x3e, 0x63, 0x74, 0xd1, 0x53, 0xaf, 0x28, 0x4c,
- 0xe9, 0x90, 0xef, 0x8c, 0x90, 0xef, 0x98, 0x98, 0x8f, 0x4c, 0xc9, 0x60,
- 0xbc, 0xa6, 0x7d, 0x0f, 0xfd, 0x7c, 0x1e, 0x50, 0x3a, 0x04, 0xdf, 0x0d,
- 0xec, 0x14, 0x71, 0x89, 0x36, 0xae, 0xe3, 0x33, 0x46, 0xcf, 0x30, 0xee,
- 0x7c, 0xb6, 0xd0, 0x45, 0xb7, 0x8a, 0x5d, 0xf4, 0x66, 0x71, 0x98, 0x6e,
- 0xce, 0x6f, 0xa7, 0x8b, 0x8c, 0x99, 0x2f, 0xda, 0x01, 0x33, 0xc7, 0xf6,
- 0xc5, 0x0b, 0x51, 0x11, 0x33, 0xc4, 0x72, 0x87, 0xf6, 0xc0, 0x7f, 0x89,
- 0x5d, 0xcc, 0x73, 0x8c, 0xbd, 0xbb, 0xe9, 0x03, 0x7e, 0x67, 0xae, 0xa0,
- 0x63, 0x1d, 0xe0, 0x93, 0x1f, 0xaf, 0xe3, 0xd7, 0xf5, 0x79, 0x24, 0xb4,
- 0x0e, 0x8f, 0xc4, 0x84, 0xae, 0xcf, 0xcf, 0xf3, 0xf7, 0xf3, 0xf0, 0x9f,
- 0x33, 0xbd, 0x59, 0x3f, 0x7f, 0x3d, 0x80, 0xf6, 0xb8, 0x66, 0xcb, 0x58,
- 0x49, 0x31, 0xb6, 0x08, 0x9f, 0x83, 0xb6, 0x11, 0x45, 0x87, 0x6e, 0x1e,
- 0x9f, 0x4f, 0xb4, 0xcf, 0x2c, 0x75, 0xd3, 0x99, 0x12, 0x63, 0x90, 0x92,
- 0x9f, 0x6d, 0x18, 0xb4, 0x0d, 0xec, 0xd5, 0xf5, 0x5f, 0x2f, 0x72, 0xdf,
- 0x73, 0x25, 0x89, 0x41, 0x72, 0x4b, 0xbd, 0x94, 0x2f, 0xf5, 0xa8, 0xf3,
- 0x07, 0x44, 0x8c, 0xbb, 0xac, 0x63, 0x84, 0xef, 0xd6, 0xd2, 0x6f, 0x6f,
- 0x31, 0x4f, 0x61, 0x4d, 0x95, 0x76, 0x29, 0x74, 0xcd, 0x8d, 0x96, 0xba,
- 0xc4, 0xe0, 0xb9, 0x19, 0xfa, 0x2e, 0xaf, 0xb7, 0xa3, 0x57, 0xe1, 0x3f,
- 0xfe, 0x2a, 0xf8, 0xa6, 0x0c, 0x1e, 0x1b, 0xbd, 0x8a, 0xba, 0x48, 0x7e,
- 0x91, 0xe7, 0x94, 0x0c, 0x4f, 0x8a, 0xdc, 0x10, 0x29, 0xa3, 0x27, 0x45,
- 0x2d, 0xba, 0x1f, 0x0a, 0xdd, 0x64, 0x65, 0x4d, 0x03, 0x78, 0x04, 0x3e,
- 0x18, 0x19, 0x83, 0x75, 0xc2, 0xee, 0x7b, 0x6b, 0x20, 0x36, 0x41, 0xf1,
- 0x41, 0xf0, 0xbd, 0x94, 0x59, 0x55, 0x5f, 0x40, 0xe8, 0xfb, 0xd0, 0x3e,
- 0x9d, 0x2f, 0xa9, 0xcf, 0xf5, 0x5a, 0xa1, 0xcf, 0x7b, 0x5c, 0xdf, 0x87,
- 0x5c, 0xdf, 0xd7, 0xe3, 0xe5, 0x78, 0xcd, 0xe3, 0x75, 0x9e, 0x64, 0x8d,
- 0xa2, 0xcc, 0x82, 0xe4, 0xbf, 0xd0, 0xbe, 0xf1, 0xd0, 0x97, 0x15, 0x06,
- 0xcf, 0x2c, 0x8f, 0x45, 0xfa, 0x8c, 0x1e, 0x7f, 0x66, 0xea, 0xef, 0x6b,
- 0xf1, 0x34, 0x70, 0xd1, 0xdc, 0x4e, 0xa9, 0xe3, 0xd0, 0xaf, 0x6c, 0x14,
- 0xd0, 0xed, 0xe4, 0x72, 0x0f, 0xad, 0x88, 0x9a, 0x5c, 0xc0, 0x18, 0xb8,
- 0x1f, 0xcf, 0xc9, 0x86, 0x3a, 0x08, 0x35, 0xd7, 0x21, 0xe3, 0x07, 0x22,
- 0xd7, 0x79, 0x3e, 0x53, 0xcb, 0xff, 0x55, 0x3b, 0x2d, 0x6a, 0xdc, 0xa0,
- 0x2d, 0x63, 0x48, 0x81, 0xf9, 0x19, 0xbf, 0x34, 0xd9, 0x55, 0x33, 0xe8,
- 0x67, 0x16, 0x7b, 0x2b, 0x86, 0xfd, 0x22, 0xcb, 0x98, 0xdc, 0x2b, 0x4f,
- 0xb9, 0xf6, 0xca, 0x4f, 0x8a, 0xbd, 0x72, 0xec, 0x93, 0x83, 0xae, 0xa0,
- 0xa5, 0x57, 0x4c, 0x0b, 0xe6, 0x31, 0xca, 0xf3, 0x68, 0xd2, 0xc5, 0x6b,
- 0x42, 0xdf, 0x44, 0x93, 0x7e, 0x19, 0x5f, 0x9d, 0xa2, 0xac, 0x88, 0xbf,
- 0x96, 0x9f, 0x71, 0x23, 0x61, 0x5b, 0x93, 0xab, 0x8c, 0x29, 0x2a, 0xc5,
- 0x2d, 0x74, 0xb3, 0xdc, 0xc1, 0x98, 0xef, 0x6f, 0x69, 0xb5, 0x4c, 0x8c,
- 0x0d, 0xb7, 0x53, 0x3e, 0xca, 0xbc, 0x36, 0x19, 0xe4, 0x79, 0x65, 0x7c,
- 0x3b, 0xc9, 0xf2, 0xc7, 0x63, 0xa8, 0x94, 0x6a, 0xef, 0xe7, 0xa2, 0x71,
- 0x33, 0x31, 0xdd, 0xc3, 0xf6, 0x4b, 0x88, 0xff, 0x6d, 0xfe, 0xff, 0x6c,
- 0x04, 0xb4, 0x59, 0x5c, 0xc2, 0xf7, 0x8c, 0x7d, 0x0a, 0xb5, 0xf7, 0x67,
- 0xb9, 0xcd, 0xec, 0x34, 0xec, 0x20, 0xd8, 0x7b, 0x36, 0xff, 0xcb, 0x36,
- 0x15, 0xe6, 0xbb, 0xdc, 0xb5, 0x6c, 0xc4, 0x10, 0x3a, 0x1e, 0x75, 0x5d,
- 0xc6, 0xd4, 0x67, 0xdc, 0x98, 0xe5, 0xbe, 0xdc, 0x24, 0x3c, 0xc3, 0xa4,
- 0x4c, 0x74, 0x1f, 0xcb, 0xc1, 0x76, 0xfe, 0x44, 0x3e, 0xd6, 0x56, 0xca,
- 0x4f, 0x8d, 0xab, 0x7c, 0xac, 0x48, 0x9b, 0x7c, 0x2c, 0xdc, 0xc7, 0x38,
- 0x60, 0xbe, 0x76, 0x6f, 0x36, 0xea, 0x7c, 0x2f, 0x19, 0x99, 0xe8, 0x36,
- 0x81, 0x99, 0x2a, 0x4b, 0xfb, 0xb9, 0x0f, 0x71, 0x33, 0x33, 0xcd, 0x7d,
- 0x2d, 0x39, 0xfb, 0x5f, 0xbb, 0x97, 0x8c, 0xa2, 0x9d, 0xdf, 0xd5, 0x2e,
- 0x4e, 0xa2, 0xed, 0x12, 0xda, 0xd7, 0xfe, 0x27, 0x11, 0xd5, 0xe3, 0x74,
- 0xde, 0x8b, 0xf1, 0x40, 0xbe, 0xf8, 0xb3, 0x72, 0x9b, 0x6e, 0x16, 0x61,
- 0x8f, 0x1b, 0xcc, 0xf7, 0xe8, 0x91, 0x49, 0xd9, 0x0a, 0x63, 0xc0, 0x6b,
- 0x7b, 0x7d, 0xab, 0xc5, 0x37, 0x6a, 0x99, 0xa6, 0xd8, 0x96, 0x66, 0x3f,
- 0xbc, 0xb4, 0xc1, 0x86, 0xc9, 0xbe, 0x82, 0x35, 0x14, 0xeb, 0x67, 0xb6,
- 0xe6, 0xb7, 0x81, 0xf7, 0x60, 0x1b, 0x5d, 0x60, 0xfd, 0x25, 0xe3, 0x93,
- 0x58, 0x97, 0xb2, 0x0e, 0x93, 0xf2, 0x93, 0x6a, 0xfa, 0x39, 0x04, 0xc9,
- 0xc3, 0xa3, 0x8d, 0xb8, 0x48, 0xc7, 0xfe, 0x7a, 0xc0, 0xb1, 0xbf, 0x1e,
- 0x72, 0xc4, 0x45, 0x86, 0x05, 0x3e, 0x6b, 0x60, 0xaa, 0xb0, 0xc2, 0x54,
- 0xc0, 0x5e, 0x52, 0xb7, 0x2d, 0xd6, 0x75, 0xdb, 0x8e, 0x75, 0x74, 0x9b,
- 0x97, 0xad, 0xba, 0xa2, 0xf4, 0x88, 0x15, 0xc5, 0x1a, 0x73, 0x83, 0xf5,
- 0xc5, 0xeb, 0xd5, 0x69, 0xd6, 0x23, 0x51, 0xd6, 0x23, 0x53, 0xac, 0x47,
- 0x26, 0x59, 0x8f, 0xd8, 0x4c, 0x03, 0x93, 0xc7, 0xfe, 0x11, 0xeb, 0x69,
- 0xac, 0x1f, 0x33, 0xf4, 0x4c, 0x15, 0x3a, 0x79, 0x8a, 0x31, 0xd0, 0x47,
- 0xb4, 0x3a, 0xdf, 0xcb, 0xfc, 0x2b, 0x71, 0x4f, 0xb3, 0x5d, 0x83, 0xda,
- 0x2b, 0xf0, 0x17, 0xff, 0x39, 0xf4, 0xce, 0x2b, 0x59, 0x1a, 0xf1, 0xdd,
- 0x2c, 0x82, 0xce, 0xab, 0xa8, 0x55, 0xf1, 0x12, 0x64, 0x1b, 0x35, 0x82,
- 0x7f, 0x30, 0x31, 0xc3, 0x7d, 0x1f, 0xf1, 0xe5, 0x79, 0x5e, 0xbe, 0x1d,
- 0xcd, 0x86, 0xfa, 0x59, 0x06, 0x8e, 0x2b, 0x19, 0x38, 0xde, 0x90, 0x81,
- 0x6c, 0x8e, 0x47, 0xd2, 0xb7, 0xb0, 0x9d, 0xc6, 0x0f, 0x26, 0x76, 0xf5,
- 0xb1, 0xfc, 0x22, 0x66, 0xa2, 0x51, 0xbf, 0xc7, 0x4f, 0xa7, 0xc3, 0x41,
- 0x55, 0xf7, 0xc7, 0x14, 0x39, 0xef, 0xf9, 0xe2, 0xbb, 0x8c, 0x4b, 0x58,
- 0x4e, 0x43, 0x38, 0xbf, 0x0c, 0xbf, 0x28, 0xdb, 0x0d, 0xdd, 0xc2, 0xaf,
- 0xb4, 0x28, 0xda, 0xe2, 0xdc, 0x9a, 0x64, 0x1d, 0x17, 0x5d, 0x31, 0xac,
- 0x99, 0xb8, 0xf1, 0x9b, 0xc3, 0xa8, 0xe1, 0xfe, 0x83, 0xea, 0xe7, 0x86,
- 0xe5, 0xde, 0x5c, 0x72, 0x97, 0xd4, 0x27, 0xcc, 0xa3, 0xe1, 0xb8, 0xb0,
- 0xdd, 0x3a, 0xae, 0xc8, 0xf5, 0x73, 0x91, 0xe7, 0xbb, 0x12, 0x9d, 0xe4,
- 0xf9, 0xee, 0x51, 0x6b, 0x67, 0x96, 0xbf, 0x17, 0xeb, 0x32, 0xaf, 0xa1,
- 0xc3, 0xa8, 0x7f, 0x1f, 0x12, 0x75, 0x22, 0x4e, 0xa2, 0x0e, 0x4f, 0x02,
- 0xcf, 0x63, 0xee, 0x85, 0xfe, 0xf8, 0x07, 0x5e, 0xa3, 0xf1, 0x5e, 0xf0,
- 0x23, 0x1f, 0x97, 0x67, 0xe8, 0x52, 0x41, 0xf7, 0xe1, 0x3d, 0x32, 0xbe,
- 0x8b, 0x7e, 0xf8, 0x68, 0x87, 0xfd, 0x9e, 0xc8, 0x05, 0x31, 0xfe, 0xc4,
- 0xdd, 0xa7, 0xa3, 0xaa, 0x4f, 0xa8, 0x75, 0xd9, 0x85, 0xda, 0x3e, 0x84,
- 0x9a, 0x48, 0x8b, 0xa2, 0x16, 0x65, 0xa7, 0xb0, 0x59, 0x17, 0x85, 0xed,
- 0xb1, 0x7f, 0x57, 0xa3, 0x3e, 0xe6, 0x7e, 0xd7, 0xb5, 0x3b, 0xbc, 0x6e,
- 0x1d, 0x12, 0x18, 0x6d, 0x14, 0xf5, 0xda, 0x45, 0x5e, 0xea, 0x8c, 0xf8,
- 0xce, 0x58, 0xc0, 0x77, 0x0f, 0xa9, 0xef, 0x3e, 0x2f, 0xb0, 0xb1, 0x11,
- 0xeb, 0x66, 0xbd, 0x28, 0xf8, 0x9d, 0xe7, 0xd9, 0x9e, 0x64, 0x7e, 0x8f,
- 0x54, 0xf8, 0xb9, 0xa7, 0x05, 0x3d, 0x35, 0x3d, 0x40, 0x0b, 0xc8, 0x40,
- 0x8f, 0xe2, 0x7f, 0xcb, 0x4c, 0xf9, 0xf5, 0xb8, 0xdb, 0xd1, 0x99, 0xb1,
- 0x4e, 0x01, 0x63, 0xc5, 0x98, 0x4c, 0x5f, 0xbc, 0x1c, 0xf1, 0xe5, 0xe6,
- 0x61, 0xeb, 0x20, 0xdf, 0x65, 0x0f, 0xe2, 0xa9, 0xb8, 0x0f, 0x3b, 0x29,
- 0x9e, 0x46, 0xbf, 0xd0, 0x4e, 0xd3, 0xc0, 0x76, 0xd1, 0xc2, 0x79, 0xdf,
- 0x76, 0x75, 0x5f, 0xb7, 0x98, 0x0b, 0x32, 0xf0, 0x1e, 0xfd, 0x6e, 0xbc,
- 0x17, 0xef, 0xc7, 0x7d, 0x78, 0x9e, 0x7c, 0xee, 0x00, 0xeb, 0xed, 0xc4,
- 0xb4, 0x7c, 0x96, 0x71, 0x5d, 0x7e, 0x37, 0x60, 0x7b, 0xf7, 0x57, 0xce,
- 0x9f, 0x4f, 0xd5, 0xf1, 0xc1, 0xfc, 0x6d, 0xa7, 0xb2, 0xf0, 0x7d, 0xe2,
- 0xbb, 0x11, 0x9f, 0xb0, 0x6b, 0x6d, 0xfe, 0xe4, 0x79, 0x9d, 0xe3, 0xf3,
- 0x33, 0xc5, 0xdb, 0xc2, 0x66, 0xcf, 0xa5, 0x47, 0x7c, 0xe5, 0x32, 0xc6,
- 0x3b, 0xe2, 0x4b, 0xb1, 0x0c, 0x24, 0x8b, 0x89, 0x5a, 0x5e, 0xe2, 0x02,
- 0x3a, 0xdd, 0x6f, 0x85, 0x4e, 0x1b, 0xef, 0x0f, 0xcb, 0x9a, 0xb7, 0x38,
- 0x66, 0x39, 0x2c, 0xb0, 0x1c, 0x16, 0x58, 0x0e, 0x0b, 0x2c, 0x87, 0x6c,
- 0xab, 0xbe, 0x56, 0x60, 0x39, 0xe4, 0xb5, 0xe4, 0x55, 0x5e, 0x4b, 0xa4,
- 0xec, 0xc6, 0x95, 0x7f, 0x53, 0xcb, 0xae, 0x3b, 0x6f, 0x53, 0xcb, 0x2a,
- 0xd6, 0x6f, 0xf2, 0x1d, 0x99, 0x68, 0x96, 0xd9, 0x5b, 0x2c, 0xb3, 0x1d,
- 0xb1, 0x41, 0xba, 0x5b, 0xc2, 0x9c, 0x59, 0xe6, 0x1c, 0xeb, 0xea, 0x94,
- 0x1f, 0x58, 0x2b, 0xc0, 0xf2, 0x04, 0xac, 0x69, 0x31, 0xdd, 0x07, 0xe9,
- 0x1e, 0xeb, 0xeb, 0xbb, 0x25, 0xc8, 0xf0, 0x1e, 0x75, 0x6e, 0xb1, 0x0c,
- 0x63, 0xfd, 0xb3, 0x7d, 0xb7, 0x8a, 0x06, 0x63, 0xb2, 0x40, 0x28, 0x43,
- 0xd0, 0xa7, 0x02, 0xa7, 0xf1, 0xbc, 0xaf, 0xb0, 0xde, 0x87, 0x0f, 0x0f,
- 0xeb, 0xc5, 0x19, 0x1f, 0xaf, 0x17, 0x91, 0x9b, 0xac, 0x4f, 0xcf, 0x97,
- 0x6c, 0x96, 0xfb, 0x7e, 0xfa, 0x56, 0x09, 0xeb, 0x34, 0x68, 0xc4, 0xe7,
- 0x65, 0x12, 0xbe, 0x31, 0x23, 0x86, 0xb1, 0x8f, 0x67, 0x0d, 0xc1, 0x27,
- 0x7f, 0x0a, 0x3a, 0x30, 0xed, 0x5f, 0xdc, 0x85, 0xda, 0xf3, 0x71, 0xa3,
- 0x53, 0xf9, 0x1a, 0x71, 0x8c, 0xf6, 0x68, 0x0b, 0xba, 0xe1, 0xbc, 0xdd,
- 0xbe, 0x24, 0x7e, 0xb3, 0x21, 0x0a, 0xff, 0x9b, 0x4b, 0x7f, 0x5d, 0xe2,
- 0xfb, 0x05, 0xbd, 0x66, 0x12, 0x7e, 0xe4, 0x90, 0xd3, 0xd3, 0xfe, 0xd8,
- 0x0c, 0x3d, 0x5b, 0x45, 0xbf, 0xaf, 0x52, 0x3e, 0x0c, 0x7d, 0x64, 0x45,
- 0xef, 0x90, 0xa4, 0x5d, 0x37, 0xe3, 0xce, 0x27, 0xbc, 0x75, 0x9c, 0x99,
- 0x10, 0x38, 0xb9, 0x8b, 0xf5, 0x0b, 0x68, 0xf3, 0x13, 0xe6, 0x35, 0x7e,
- 0x5f, 0x41, 0xeb, 0xb7, 0x1f, 0xb3, 0xce, 0xc1, 0x9c, 0xe1, 0x7c, 0x6d,
- 0x9d, 0xb6, 0xaa, 0x74, 0x9a, 0xed, 0xd0, 0x69, 0xb9, 0xba, 0x4e, 0x63,
- 0xde, 0x10, 0xba, 0x0c, 0xba, 0xea, 0x51, 0xc6, 0x91, 0xf2, 0x18, 0xf8,
- 0x70, 0x87, 0xd0, 0x5d, 0xac, 0xfb, 0xd9, 0xae, 0x58, 0xac, 0x66, 0x7d,
- 0x87, 0x85, 0x0e, 0xd1, 0xfc, 0xbd, 0x7f, 0xb7, 0x94, 0x8b, 0x6e, 0xa1,
- 0x0f, 0x72, 0x27, 0xa1, 0xb7, 0xbc, 0xda, 0x8f, 0x73, 0x3b, 0xb4, 0xb7,
- 0x23, 0x2f, 0xb1, 0x3e, 0x5b, 0x8c, 0xc2, 0xa6, 0xed, 0x51, 0xb6, 0x0f,
- 0xea, 0x72, 0x61, 0xaf, 0x0b, 0x63, 0xd5, 0xfa, 0x6c, 0x40, 0xf9, 0x35,
- 0xe0, 0x87, 0xc4, 0x9c, 0xb7, 0xc5, 0x08, 0x26, 0x30, 0x02, 0xdf, 0x13,
- 0x60, 0x7a, 0x89, 0x1a, 0xe2, 0x44, 0xef, 0xd2, 0xaa, 0x90, 0x8d, 0x77,
- 0x05, 0x76, 0xc9, 0xf3, 0x77, 0xb3, 0xd3, 0x07, 0x45, 0x3f, 0xf3, 0x4b,
- 0x0d, 0xfd, 0x38, 0x57, 0x78, 0x0f, 0xeb, 0x86, 0xe8, 0x6b, 0x65, 0x42,
- 0xea, 0xc0, 0xc5, 0x32, 0x6a, 0x80, 0x89, 0x3e, 0x73, 0x5f, 0xf5, 0x38,
- 0xd1, 0x0f, 0xad, 0x0f, 0x36, 0x22, 0x7b, 0x8c, 0x6b, 0xfb, 0x31, 0x47,
- 0x59, 0x07, 0x0f, 0x3d, 0xcb, 0xef, 0xc7, 0xb5, 0xf5, 0xc7, 0x73, 0xaf,
- 0x3e, 0x1e, 0xf8, 0xf6, 0x70, 0xcf, 0xbb, 0x74, 0x57, 0x8d, 0xe7, 0x6e,
- 0x7d, 0x3c, 0xcf, 0xa8, 0xf1, 0x50, 0xce, 0x88, 0x0d, 0x28, 0xdc, 0xbf,
- 0xe1, 0x67, 0x77, 0x27, 0x18, 0xc7, 0xe4, 0x96, 0x40, 0xe7, 0xfd, 0x8a,
- 0x9f, 0x9c, 0x7e, 0x54, 0x67, 0x5f, 0xad, 0xc9, 0x3b, 0xac, 0x7f, 0xef,
- 0x09, 0x1c, 0x33, 0xc2, 0x38, 0x06, 0xd7, 0x29, 0x0f, 0x3d, 0x9d, 0x0b,
- 0xa3, 0x4e, 0xed, 0x0c, 0x8f, 0x9b, 0xed, 0xb1, 0x69, 0xfe, 0x14, 0xfe,
- 0x35, 0x3c, 0x47, 0xdf, 0xff, 0x3c, 0xdd, 0x9b, 0x87, 0x2e, 0x07, 0x8e,
- 0x95, 0xb5, 0x6c, 0xef, 0x2d, 0x4b, 0xff, 0x6e, 0xca, 0xd3, 0xbf, 0x0b,
- 0xdf, 0xee, 0x34, 0x70, 0x7e, 0x08, 0x7e, 0xe0, 0xa4, 0xfa, 0xad, 0x8f,
- 0x5c, 0x15, 0xcf, 0xf2, 0xd2, 0x4b, 0x33, 0x8e, 0xd8, 0x38, 0xc4, 0xaa,
- 0x64, 0x59, 0xcf, 0xd8, 0xa1, 0x0e, 0x43, 0xe6, 0xdc, 0xdc, 0xa8, 0x6a,
- 0xec, 0x74, 0x94, 0xe7, 0xcc, 0x8e, 0x1a, 0x46, 0x4a, 0xf8, 0x1a, 0xba,
- 0xed, 0x1e, 0xea, 0xe2, 0x75, 0xf4, 0x2c, 0xa1, 0x96, 0x9a, 0x65, 0x62,
- 0x0f, 0xe0, 0x12, 0xf3, 0x64, 0x3e, 0x6a, 0x45, 0x1e, 0x17, 0x76, 0x29,
- 0xd6, 0x17, 0x03, 0x74, 0x62, 0x5a, 0xa3, 0x0f, 0x7c, 0xbc, 0x84, 0x3a,
- 0x9a, 0x51, 0x1e, 0x3f, 0xfc, 0xc7, 0x63, 0xe6, 0x9b, 0xbc, 0x2e, 0x5d,
- 0x12, 0x7e, 0x99, 0x0b, 0x94, 0x63, 0x39, 0x3d, 0x22, 0xe4, 0xd4, 0x18,
- 0x61, 0x29, 0x62, 0xb9, 0x42, 0x6c, 0xc2, 0xb8, 0xa8, 0xdb, 0x23, 0x6d,
- 0x1d, 0x1e, 0xe5, 0xb2, 0xaa, 0x87, 0x90, 0x86, 0xee, 0xd8, 0xb8, 0x4f,
- 0x22, 0xfd, 0x89, 0x7d, 0x31, 0x4e, 0x4c, 0xe6, 0xf6, 0x7d, 0xc3, 0xae,
- 0x33, 0x45, 0xbd, 0x48, 0xd0, 0x4e, 0xf8, 0x13, 0x8d, 0x29, 0xa6, 0x9b,
- 0xfe, 0xdd, 0x19, 0xa7, 0xdf, 0xe0, 0x9c, 0xc8, 0xeb, 0x7f, 0xa5, 0x2a,
- 0xd7, 0xe0, 0x1c, 0xdb, 0xf4, 0xf9, 0x83, 0x4e, 0x4c, 0x62, 0x15, 0x93,
- 0xc2, 0x97, 0xb3, 0x9b, 0x12, 0x0b, 0x53, 0xf4, 0x68, 0x01, 0x3a, 0x8c,
- 0xee, 0x24, 0x6c, 0xfc, 0xa2, 0x0c, 0x64, 0x7c, 0x8a, 0x52, 0x55, 0xd0,
- 0xc8, 0xc7, 0x58, 0x89, 0x79, 0xaf, 0x88, 0x3d, 0x7f, 0x3e, 0x2e, 0xe3,
- 0x77, 0x54, 0x7e, 0x5d, 0xf9, 0xcb, 0x87, 0x29, 0xb9, 0x40, 0xd9, 0x4c,
- 0xf4, 0x4b, 0xa2, 0xd6, 0x75, 0x26, 0x3a, 0xa1, 0x7c, 0x3b, 0x11, 0xbe,
- 0x0e, 0x7f, 0x99, 0x49, 0x5f, 0x2e, 0x58, 0xd9, 0x0c, 0x49, 0x9f, 0x05,
- 0x71, 0x1f, 0x0c, 0x5e, 0x7b, 0x77, 0xb0, 0x0e, 0x39, 0x21, 0xfc, 0x16,
- 0x8c, 0x54, 0xe6, 0xd1, 0x1e, 0x3e, 0x87, 0x7e, 0x82, 0x9d, 0x96, 0x29,
- 0x3e, 0xa5, 0xda, 0xd6, 0x28, 0xc4, 0xbc, 0x10, 0xfa, 0x55, 0x3b, 0x1b,
- 0x35, 0x1a, 0xf7, 0xc3, 0xe7, 0x71, 0x42, 0xe0, 0xc8, 0x11, 0xb6, 0x79,
- 0x44, 0xbb, 0xda, 0xac, 0xf0, 0x5f, 0xf0, 0x79, 0xf9, 0x81, 0x21, 0xfd,
- 0x9b, 0x08, 0xb8, 0x2e, 0xfd, 0x1a, 0xfc, 0xcc, 0x32, 0xf7, 0xa3, 0x29,
- 0x9e, 0x7e, 0x98, 0xe2, 0x9b, 0xf0, 0x33, 0x9d, 0xbc, 0xaf, 0x7e, 0x26,
- 0xa6, 0x35, 0xaf, 0x3d, 0x37, 0x58, 0x36, 0x5e, 0x5f, 0xd7, 0xfe, 0xfb,
- 0x50, 0xaf, 0xe1, 0x4c, 0xab, 0x90, 0xf8, 0xdd, 0x0c, 0x60, 0xf0, 0x7c,
- 0xf5, 0x71, 0xfc, 0x5e, 0x8c, 0x2f, 0x2d, 0xb0, 0x71, 0x84, 0xb1, 0x0d,
- 0x30, 0xce, 0x98, 0xd8, 0x17, 0x8b, 0x3f, 0x16, 0xf1, 0xe5, 0x97, 0x07,
- 0xc9, 0x0f, 0x7f, 0x9c, 0xad, 0x63, 0x29, 0xba, 0x45, 0xdc, 0xbb, 0xdc,
- 0x8f, 0xc4, 0xfa, 0x0c, 0x9d, 0x78, 0x87, 0xed, 0x86, 0x09, 0x15, 0x87,
- 0xd3, 0x21, 0x6a, 0x53, 0xc9, 0xbd, 0x54, 0xad, 0x53, 0x34, 0xef, 0xe9,
- 0xbd, 0x0e, 0xe7, 0x6f, 0x73, 0x41, 0x76, 0x9d, 0x98, 0x02, 0xfe, 0x29,
- 0x31, 0x47, 0x97, 0x88, 0xe4, 0x1c, 0x37, 0xf6, 0x31, 0xba, 0x78, 0x9e,
- 0x60, 0x0f, 0xc2, 0xef, 0xf7, 0x35, 0xfe, 0xc4, 0x7e, 0xc4, 0xd5, 0x21,
- 0xe0, 0xa8, 0x3e, 0x9b, 0x79, 0x66, 0x1a, 0xe7, 0x83, 0x6c, 0x9f, 0x69,
- 0xdc, 0x2b, 0x7d, 0x51, 0x6c, 0xb3, 0xa9, 0xf9, 0x82, 0x1f, 0x6a, 0x54,
- 0xd5, 0x29, 0xb0, 0xc8, 0xec, 0x07, 0x9d, 0x3e, 0x2d, 0x79, 0x5c, 0x6f,
- 0xef, 0x62, 0x23, 0xb1, 0x4e, 0xf8, 0xdd, 0x30, 0xd4, 0xeb, 0xdc, 0x0b,
- 0xda, 0xf3, 0x1c, 0x39, 0xf7, 0x36, 0x1e, 0xdf, 0xa5, 0x7f, 0xb3, 0xe8,
- 0xfe, 0xcc, 0xdb, 0x16, 0x8f, 0x79, 0xfb, 0xf9, 0x90, 0xdc, 0x3b, 0x7b,
- 0x58, 0xb5, 0xf1, 0x8a, 0x6f, 0x5d, 0xfe, 0x0e, 0xfc, 0x50, 0x8d, 0xfc,
- 0x8b, 0x77, 0x84, 0x5e, 0x69, 0xf5, 0x85, 0x47, 0x58, 0x9f, 0x4a, 0x39,
- 0x3e, 0xe1, 0x21, 0xc7, 0xfd, 0x31, 0xe0, 0x96, 0x8f, 0x2f, 0xc7, 0xc7,
- 0xdb, 0xca, 0xf1, 0x9e, 0x61, 0xe9, 0x8b, 0x6d, 0x95, 0x63, 0xe4, 0x00,
- 0x9d, 0xa8, 0xb6, 0xf3, 0x7b, 0x61, 0x1e, 0x90, 0xcb, 0xee, 0xf4, 0x95,
- 0x80, 0x66, 0xda, 0x5f, 0x82, 0x7d, 0x43, 0xf0, 0x25, 0xf6, 0x5e, 0x4e,
- 0x1a, 0xa9, 0x79, 0xf7, 0x5e, 0xea, 0x46, 0xee, 0xbd, 0xed, 0x71, 0x2f,
- 0xb0, 0x3b, 0x64, 0xc3, 0x8a, 0x48, 0x5f, 0x80, 0xa6, 0xdf, 0xb0, 0xef,
- 0x70, 0xc9, 0xca, 0x96, 0x09, 0xbe, 0xee, 0x30, 0x9d, 0xc3, 0xfe, 0xb4,
- 0xf2, 0x25, 0x1f, 0x2b, 0x48, 0x3a, 0x84, 0x0e, 0x0a, 0xfe, 0x00, 0xbe,
- 0x8d, 0xa4, 0xfd, 0x69, 0x9e, 0x63, 0xe9, 0x47, 0xce, 0x2c, 0x45, 0xd4,
- 0xbc, 0x71, 0x5b, 0x3c, 0xcf, 0x33, 0x5f, 0x10, 0xf3, 0x65, 0x3d, 0xbf,
- 0x52, 0x8f, 0x4f, 0xc6, 0xda, 0x50, 0xa3, 0xff, 0xe0, 0x75, 0xcf, 0x7f,
- 0x30, 0x24, 0x6a, 0x37, 0xdc, 0xa8, 0x1e, 0x64, 0xbc, 0x89, 0x39, 0x85,
- 0x0f, 0x52, 0xfb, 0x88, 0x1f, 0xda, 0x4b, 0xbd, 0x07, 0x18, 0x05, 0x18,
- 0x64, 0x33, 0xbe, 0x34, 0x0e, 0x22, 0xce, 0xdc, 0xe4, 0x7b, 0x50, 0x73,
- 0x6a, 0xdc, 0x4c, 0x51, 0x0f, 0xfc, 0x10, 0xa8, 0x25, 0x6d, 0xe6, 0x9a,
- 0x64, 0xec, 0x94, 0x90, 0xb1, 0xd4, 0xf2, 0x29, 0x25, 0x63, 0xa7, 0x94,
- 0x1f, 0xfe, 0x94, 0x92, 0xb1, 0x53, 0x4a, 0xc6, 0x4e, 0x29, 0x19, 0x3b,
- 0xc5, 0x7c, 0x3e, 0xc6, 0xf8, 0x16, 0x58, 0x44, 0xfb, 0x41, 0x7b, 0x29,
- 0x53, 0xc2, 0x75, 0xac, 0xcf, 0x6e, 0x39, 0x7b, 0x69, 0x44, 0xca, 0x19,
- 0x63, 0x13, 0x19, 0xaf, 0xc7, 0xef, 0xc2, 0x1c, 0xfc, 0x1e, 0xd3, 0xef,
- 0x23, 0x3a, 0x33, 0x8f, 0xbe, 0xfa, 0x28, 0x29, 0x6a, 0xc9, 0x76, 0x50,
- 0xc2, 0x89, 0x85, 0x43, 0xc8, 0x0f, 0x93, 0xb6, 0x5f, 0xb6, 0x6d, 0xae,
- 0x98, 0xe6, 0x93, 0x98, 0x9a, 0x2f, 0xb7, 0x5d, 0xd4, 0x45, 0xe9, 0x22,
- 0xe8, 0x8a, 0x98, 0x4a, 0x93, 0xe7, 0x46, 0xd0, 0x49, 0x86, 0x44, 0xb9,
- 0x68, 0x70, 0x4c, 0xd1, 0xe0, 0xdb, 0x62, 0x8c, 0x88, 0x49, 0x84, 0x2f,
- 0xb3, 0x3d, 0x1d, 0x72, 0x85, 0x31, 0x7e, 0x0e, 0xcb, 0xc2, 0xc1, 0x08,
- 0xeb, 0xa4, 0x8d, 0xd3, 0xa1, 0x31, 0xf6, 0x76, 0xba, 0x67, 0xa3, 0x79,
- 0x39, 0x77, 0x1c, 0x6b, 0x49, 0x44, 0xad, 0x23, 0x12, 0x17, 0x6f, 0xb1,
- 0x6b, 0x74, 0x34, 0xba, 0x97, 0x8f, 0xad, 0x74, 0x96, 0x0e, 0x90, 0xd1,
- 0x57, 0xa3, 0xbf, 0x60, 0x39, 0xe8, 0x66, 0x39, 0x38, 0xaa, 0xec, 0x92,
- 0xa3, 0x75, 0xbb, 0x64, 0xcf, 0x1e, 0xc4, 0x65, 0x64, 0xc4, 0xbe, 0xd7,
- 0x56, 0x55, 0x43, 0x00, 0xbe, 0x6f, 0x9c, 0x77, 0x51, 0x7c, 0x18, 0xe7,
- 0xf8, 0x2d, 0x22, 0x6b, 0x32, 0xee, 0x1b, 0xdf, 0x23, 0xb0, 0xbb, 0xcf,
- 0xc2, 0x3d, 0x47, 0xa5, 0xde, 0xf3, 0x91, 0x7f, 0xfc, 0x36, 0xe3, 0x89,
- 0x1a, 0x3d, 0xc1, 0xef, 0xcc, 0x17, 0xf7, 0xf1, 0xb3, 0x75, 0x4d, 0x09,
- 0x3b, 0x6e, 0xf8, 0xb6, 0x92, 0xbf, 0xaf, 0xdd, 0xbb, 0x2d, 0xc1, 0x8f,
- 0x8c, 0xa7, 0x8d, 0xd9, 0xe8, 0x7b, 0xb5, 0xd3, 0x27, 0xe1, 0x63, 0x87,
- 0x9c, 0x58, 0x21, 0xd3, 0xe7, 0x25, 0x1f, 0x12, 0x2b, 0x35, 0xe2, 0x63,
- 0x21, 0x2f, 0x35, 0xfa, 0x77, 0x1e, 0x5b, 0x88, 0xb0, 0x77, 0x22, 0x9f,
- 0x9f, 0xa6, 0x19, 0x91, 0x83, 0x8d, 0x38, 0xe9, 0x33, 0xf3, 0xfa, 0x5d,
- 0xb6, 0xe2, 0x8d, 0xcf, 0x20, 0xce, 0xad, 0xb8, 0x48, 0x6b, 0xaf, 0x39,
- 0xf0, 0xd7, 0x8d, 0x2d, 0xac, 0xf6, 0x85, 0x45, 0x4e, 0xf8, 0x76, 0xc6,
- 0x48, 0x3a, 0x1e, 0x7a, 0x9c, 0x9f, 0x0f, 0x3f, 0x5e, 0x80, 0x92, 0x57,
- 0xd0, 0xae, 0x93, 0x46, 0x17, 0x6a, 0x5f, 0xe0, 0xef, 0xc5, 0xfe, 0x65,
- 0x86, 0xba, 0xd5, 0xde, 0x44, 0x8f, 0xda, 0xcf, 0x8a, 0xb0, 0xec, 0x35,
- 0x72, 0x9d, 0x47, 0xeb, 0x3e, 0x3d, 0xc8, 0x84, 0xdb, 0xa7, 0xf7, 0xf4,
- 0x3a, 0xeb, 0xd5, 0x7a, 0x72, 0x80, 0x58, 0xd6, 0x2e, 0x52, 0xbe, 0x4a,
- 0x33, 0x4f, 0x1b, 0xcd, 0xe9, 0xdb, 0xf4, 0x3d, 0xdd, 0x9d, 0x31, 0xf3,
- 0xc2, 0x9b, 0x76, 0x50, 0xf1, 0x5f, 0x27, 0x9d, 0x29, 0x05, 0x79, 0xcd,
- 0x87, 0x6e, 0x05, 0xbd, 0xfc, 0xc3, 0xc8, 0x73, 0xf9, 0x7a, 0xa0, 0x93,
- 0x96, 0x96, 0x10, 0x6b, 0xf1, 0x47, 0x7b, 0x64, 0x7c, 0x71, 0x9a, 0xe9,
- 0x72, 0x80, 0xd7, 0x47, 0x43, 0xed, 0x1d, 0xe1, 0x1a, 0x74, 0x89, 0xa8,
- 0x37, 0x1a, 0xf8, 0xd2, 0x44, 0x90, 0xed, 0x02, 0xb9, 0xf7, 0x70, 0x88,
- 0x9f, 0xfd, 0xfd, 0x52, 0x1a, 0xfe, 0xb2, 0xd0, 0x11, 0x7e, 0x7e, 0x92,
- 0xf1, 0x44, 0x9c, 0x3a, 0xa9, 0xb2, 0xd4, 0xc9, 0x76, 0x41, 0x27, 0xe3,
- 0x89, 0xb1, 0xd0, 0xa8, 0x4f, 0xbc, 0x4b, 0xe4, 0xd4, 0x3c, 0x1c, 0x38,
- 0xc0, 0x7c, 0x85, 0x77, 0xbd, 0xae, 0xde, 0xe5, 0x7e, 0xc7, 0x2f, 0x6a,
- 0x38, 0x3f, 0xe2, 0x37, 0x2f, 0xdc, 0xc2, 0xef, 0x51, 0xcd, 0xcf, 0x30,
- 0x76, 0x0e, 0x53, 0x7e, 0xbe, 0x83, 0xc7, 0x10, 0x63, 0x3b, 0x22, 0xca,
- 0xe7, 0x8f, 0x50, 0xb6, 0x7a, 0x92, 0x7e, 0xbf, 0xea, 0xf4, 0x09, 0x3f,
- 0xc2, 0x7d, 0x96, 0x39, 0xfd, 0x5d, 0xdc, 0xaf, 0x0f, 0x6d, 0xb7, 0x8e,
- 0x09, 0x92, 0xff, 0x7b, 0x61, 0xea, 0x7c, 0x0e, 0xbe, 0x97, 0x1a, 0x15,
- 0xa3, 0xd6, 0xa5, 0x3b, 0x24, 0xfd, 0xcf, 0x2f, 0x88, 0xb8, 0x5a, 0xbe,
- 0x9f, 0x9f, 0x39, 0x87, 0x76, 0x2f, 0x98, 0x74, 0xd3, 0x96, 0xf4, 0x7e,
- 0x23, 0x10, 0x26, 0xff, 0xcb, 0x88, 0x7d, 0x02, 0x56, 0x33, 0x2f, 0xd8,
- 0xfb, 0x58, 0xbf, 0x3f, 0x87, 0xfb, 0xf8, 0xf3, 0x65, 0x9c, 0x07, 0x79,
- 0x9c, 0x58, 0xaf, 0x11, 0xef, 0x02, 0xbd, 0x78, 0x20, 0x12, 0x12, 0xfc,
- 0xf7, 0x08, 0xf3, 0x54, 0x87, 0xf0, 0x35, 0xf6, 0xa3, 0xad, 0x3d, 0xc4,
- 0xd8, 0xc2, 0xbc, 0x30, 0xb1, 0x0f, 0xe7, 0xf1, 0x3e, 0x3f, 0xd3, 0x48,
- 0xf2, 0x10, 0xc6, 0xd3, 0xc4, 0xdc, 0x81, 0x43, 0x13, 0xc4, 0xf3, 0x09,
- 0xfc, 0xc1, 0xf3, 0x19, 0x42, 0x7d, 0xa7, 0x20, 0xa5, 0xf8, 0x1d, 0xc9,
- 0x92, 0x1c, 0xf7, 0x5c, 0xd5, 0x4f, 0xd2, 0x4f, 0x75, 0x74, 0x44, 0xff,
- 0x9e, 0x21, 0x0d, 0xe2, 0xd9, 0x5a, 0x56, 0x70, 0xdc, 0x4b, 0x77, 0x4b,
- 0x3d, 0x74, 0x4f, 0xed, 0x69, 0xdd, 0x15, 0x76, 0x19, 0xeb, 0xf0, 0x74,
- 0x2f, 0xdd, 0x59, 0xea, 0x20, 0xea, 0x0f, 0x8a, 0x3d, 0xe7, 0xbb, 0xa5,
- 0x32, 0xbf, 0x3f, 0x31, 0x22, 0xfd, 0x3a, 0x0d, 0x1e, 0xb9, 0xeb, 0xc1,
- 0x23, 0x1f, 0x08, 0x1e, 0xd9, 0x37, 0xb2, 0x36, 0x8f, 0xec, 0x52, 0xb6,
- 0x48, 0x90, 0x3a, 0x15, 0x7f, 0xbc, 0xc4, 0xfc, 0xf1, 0x2c, 0xf3, 0xc7,
- 0xe1, 0x36, 0xfc, 0x61, 0xb8, 0xf8, 0xe3, 0x88, 0xe0, 0x8f, 0x87, 0x46,
- 0xd6, 0xe2, 0x8f, 0xc3, 0xfe, 0xb5, 0x7c, 0x4d, 0xe2, 0xb7, 0x3c, 0x2f,
- 0xcc, 0xd9, 0xbb, 0x99, 0xd7, 0x6d, 0xaa, 0xcc, 0x23, 0x67, 0x61, 0x25,
- 0x6a, 0xd0, 0xbf, 0x08, 0x9b, 0x6c, 0x55, 0xd8, 0xfc, 0x31, 0x11, 0xc3,
- 0xba, 0x28, 0xf8, 0x8b, 0xd7, 0xff, 0x18, 0x72, 0xaa, 0xdc, 0x73, 0xd1,
- 0x4d, 0x37, 0xa3, 0x98, 0x0b, 0x53, 0xcd, 0x05, 0xae, 0x75, 0xe9, 0xfa,
- 0x90, 0x01, 0xbe, 0x7e, 0xe1, 0x03, 0xf0, 0xe8, 0x72, 0x4f, 0x20, 0x59,
- 0xf8, 0xe6, 0x08, 0xf0, 0x5f, 0x7e, 0x99, 0x1c, 0xd7, 0x03, 0x7c, 0x3d,
- 0x2c, 0x7e, 0xfb, 0x09, 0xb2, 0xf2, 0x8f, 0x88, 0x71, 0x64, 0x9e, 0xbc,
- 0x59, 0x1a, 0xa6, 0x5b, 0xa5, 0xdd, 0xb4, 0x5a, 0x1a, 0xa1, 0x37, 0x45,
- 0x2d, 0x0d, 0x99, 0x1b, 0xb9, 0x2a, 0xe6, 0xc8, 0xa0, 0x43, 0x61, 0x6e,
- 0xb3, 0xb4, 0x9b, 0x56, 0x96, 0x34, 0x7f, 0x83, 0xb7, 0xc1, 0x2f, 0xf1,
- 0x3e, 0x99, 0x2f, 0xd7, 0xca, 0x33, 0xc9, 0x26, 0x9e, 0x91, 0xf7, 0x80,
- 0x57, 0xf2, 0xad, 0xb9, 0xbe, 0xdd, 0xa1, 0x18, 0x62, 0xf5, 0x82, 0xd4,
- 0x81, 0xb8, 0x45, 0xc3, 0x9a, 0x3c, 0xe4, 0x07, 0x86, 0xfe, 0x2a, 0xaf,
- 0xb9, 0x3c, 0x67, 0x36, 0xe2, 0x9c, 0x46, 0x18, 0x0f, 0x6f, 0x17, 0xf8,
- 0x37, 0x61, 0x07, 0x22, 0x49, 0xaa, 0x5d, 0x30, 0x6c, 0xd4, 0x73, 0x4c,
- 0xf3, 0xf3, 0x0c, 0xe5, 0x6f, 0xda, 0xe6, 0xe0, 0x3f, 0x37, 0xd6, 0xc5,
- 0x5e, 0xf2, 0x63, 0xdc, 0x67, 0xac, 0xc3, 0x8d, 0xfd, 0x1a, 0xaa, 0xef,
- 0xd7, 0x74, 0xf3, 0xb8, 0xa5, 0xec, 0xcd, 0xda, 0xdc, 0xae, 0xca, 0xed,
- 0xaa, 0xd8, 0xfb, 0xe3, 0xeb, 0x4b, 0xd8, 0x77, 0x1e, 0xa6, 0xd5, 0x79,
- 0xc8, 0x28, 0xfc, 0x21, 0x8d, 0xbd, 0xde, 0xd5, 0x65, 0x5c, 0x87, 0x4f,
- 0xa4, 0xb1, 0xd7, 0xbb, 0xaa, 0xf6, 0x7a, 0x57, 0x97, 0x63, 0x42, 0x6f,
- 0xe7, 0x4b, 0x4c, 0xf7, 0x92, 0x5f, 0xc5, 0x39, 0xee, 0x53, 0xbf, 0x2d,
- 0xf4, 0x98, 0xf0, 0x69, 0xf7, 0xd9, 0x6b, 0xd3, 0xf0, 0x50, 0x0b, 0x0d,
- 0x63, 0x02, 0x67, 0xa5, 0xf8, 0x99, 0xc9, 0xd2, 0x63, 0xff, 0x3b, 0x60,
- 0x78, 0x46, 0x00, 0xf3, 0x9e, 0x30, 0x34, 0xef, 0xc1, 0xe6, 0x8e, 0xf9,
- 0x19, 0x20, 0xf7, 0x14, 0xd9, 0x80, 0xfb, 0x16, 0x90, 0xf2, 0x4a, 0x06,
- 0xad, 0xbc, 0x02, 0xa6, 0x09, 0x75, 0x88, 0xfe, 0xa6, 0xf5, 0x9f, 0xe5,
- 0x60, 0xe3, 0x80, 0x4d, 0x40, 0x73, 0x9b, 0xa7, 0x90, 0x32, 0xf7, 0x0c,
- 0xac, 0x6f, 0xb1, 0xae, 0x6d, 0xb4, 0x01, 0xef, 0xb1, 0x5e, 0x34, 0x85,
- 0x85, 0x61, 0x49, 0x0f, 0x03, 0xb0, 0x7e, 0x00, 0xa5, 0x75, 0x50, 0x1d,
- 0x01, 0x4f, 0xef, 0x02, 0x4d, 0x40, 0xf7, 0x39, 0x01, 0xdb, 0xa2, 0xce,
- 0xfd, 0xca, 0xe0, 0xb5, 0xb2, 0x0d, 0xd0, 0x73, 0xab, 0x16, 0xf5, 0x88,
- 0xc9, 0x83, 0xf2, 0x99, 0x93, 0x0a, 0x03, 0x19, 0x79, 0x81, 0x0d, 0x9a,
- 0x17, 0xc0, 0xe1, 0x04, 0x4c, 0xeb, 0xc0, 0x32, 0x6a, 0x8d, 0x2e, 0xd0,
- 0x3c, 0x1e, 0x16, 0x97, 0x7e, 0x90, 0x18, 0x03, 0x54, 0x8c, 0x05, 0xc8,
- 0x97, 0x01, 0xb6, 0x29, 0x41, 0x7e, 0x05, 0xe5, 0x05, 0x90, 0xd9, 0x20,
- 0xbf, 0x83, 0xca, 0x4e, 0x50, 0x5e, 0x04, 0xb2, 0x97, 0x08, 0x41, 0xfd,
- 0x0c, 0xa4, 0x81, 0xec, 0xe6, 0x29, 0x22, 0x60, 0x7e, 0x52, 0x80, 0x10,
- 0x43, 0x03, 0x3c, 0x1f, 0x10, 0x1b, 0xc6, 0x30, 0xf5, 0x31, 0x64, 0xe4,
- 0x1b, 0x88, 0x19, 0x88, 0x7c, 0xc3, 0xce, 0x70, 0x40, 0x00, 0x16, 0x56,
- 0xff, 0xff, 0x1f, 0x53, 0x61, 0x01, 0xa6, 0x53, 0xd0, 0x3a, 0xd6, 0xdf,
- 0xff, 0x0f, 0x88, 0xb0, 0x30, 0xb4, 0xc0, 0xd7, 0x23, 0xe6, 0xc8, 0x83,
- 0xca, 0xd0, 0x05, 0x40, 0x56, 0x1b, 0xbc, 0x4d, 0xc0, 0x02, 0xbe, 0xef,
- 0x79, 0x01, 0xc3, 0x2f, 0x60, 0x99, 0xf5, 0xff, 0xff, 0x52, 0xb8, 0x5a,
- 0x10, 0x00, 0x00, 0x19, 0x3f, 0x16, 0x21, 0xc4, 0x7d, 0x00, 0x00, 0x00 };
+ 0xdc, 0x5b, 0x6b, 0x6c, 0x1c, 0xd7, 0x75, 0x3e, 0x33, 0x3b, 0x4b, 0xae,
+ 0xc8, 0x15, 0x35, 0x22, 0x57, 0xd4, 0x9a, 0xa2, 0xed, 0x5d, 0x72, 0x28,
+ 0xb2, 0x96, 0xea, 0xae, 0x29, 0xa6, 0x62, 0xd3, 0x4d, 0xb4, 0xd9, 0xa5,
+ 0x5c, 0xb5, 0x75, 0x5a, 0x4a, 0x26, 0xfc, 0x48, 0x55, 0x83, 0xde, 0xa5,
+ 0x9c, 0xa0, 0xa8, 0x53, 0xc9, 0x76, 0x85, 0x20, 0x05, 0xaa, 0x05, 0x1f,
+ 0x89, 0x52, 0xb0, 0x1c, 0xc5, 0x92, 0x29, 0xb5, 0x71, 0x6b, 0x96, 0xb4,
+ 0x6c, 0x15, 0xd8, 0x6a, 0x65, 0xc7, 0x6d, 0x68, 0x54, 0x2e, 0x65, 0xca,
+ 0x69, 0x95, 0x26, 0x48, 0x8d, 0xa0, 0x42, 0x95, 0x3f, 0x8e, 0xe1, 0xf4,
+ 0x87, 0x5b, 0xf4, 0x87, 0xd1, 0x07, 0x22, 0xd7, 0x8f, 0xed, 0xf7, 0xdd,
+ 0xb9, 0x43, 0x0e, 0x97, 0x14, 0x45, 0xf9, 0xf5, 0xa3, 0x04, 0x56, 0x33,
+ 0xf7, 0x7d, 0xee, 0xb9, 0xe7, 0x7c, 0xe7, 0x31, 0x57, 0x3f, 0x2f, 0x52,
+ 0x27, 0xfa, 0x6f, 0x3d, 0x7e, 0x89, 0x87, 0x7f, 0xaf, 0x70, 0xfb, 0xce,
+ 0xdb, 0x77, 0xe0, 0xf5, 0x0e, 0xd3, 0xa8, 0x0d, 0xb1, 0x9e, 0xff, 0xc4,
+ 0xf0, 0xeb, 0xd6, 0xef, 0x2b, 0xfd, 0xd9, 0xf8, 0xbd, 0x89, 0xc6, 0xc1,
+ 0x7f, 0x17, 0x31, 0xae, 0xd1, 0x27, 0xf8, 0x57, 0xa9, 0xac, 0xde, 0x6e,
+ 0x92, 0x96, 0x55, 0xda, 0x43, 0xde, 0x92, 0x8a, 0x66, 0xfe, 0x24, 0x62,
+ 0xa6, 0x33, 0x47, 0xb2, 0x8e, 0x11, 0x09, 0xa5, 0xbb, 0x8a, 0x05, 0x47,
+ 0x24, 0x53, 0xda, 0x96, 0xc8, 0xc9, 0x7b, 0x95, 0x62, 0xcc, 0x92, 0xac,
+ 0x23, 0x91, 0x9b, 0xd3, 0xef, 0x3e, 0xf5, 0xd2, 0xce, 0xe4, 0x5b, 0x53,
+ 0x21, 0x89, 0xd8, 0xe9, 0x17, 0xc4, 0xde, 0x2a, 0x91, 0x56, 0x8c, 0x79,
+ 0xb2, 0x33, 0x63, 0x48, 0x83, 0x3f, 0xd7, 0x9b, 0x95, 0x97, 0x3a, 0xa5,
+ 0xd8, 0x92, 0x8e, 0x88, 0x99, 0xee, 0xb8, 0x92, 0x0d, 0xd9, 0x83, 0xa1,
+ 0xb4, 0x2d, 0x73, 0x65, 0xe9, 0x3f, 0x30, 0x2e, 0x91, 0x48, 0xfa, 0x4b,
+ 0x91, 0xda, 0x0e, 0x89, 0x58, 0xe9, 0xa9, 0x23, 0x5f, 0x73, 0x8e, 0x54,
+ 0x4c, 0xc7, 0xe9, 0x9a, 0x96, 0x68, 0xef, 0xe9, 0x1e, 0xb4, 0x97, 0x92,
+ 0x5d, 0x22, 0x3b, 0xc5, 0x74, 0x8a, 0xd1, 0x90, 0x13, 0x91, 0x6c, 0xd9,
+ 0x91, 0x5c, 0x59, 0xe4, 0x1f, 0x4a, 0x86, 0x9c, 0x76, 0x9a, 0x65, 0x7a,
+ 0xfb, 0xbb, 0x95, 0x0c, 0x68, 0xf9, 0x7b, 0x67, 0xea, 0xc8, 0xa8, 0x43,
+ 0x7a, 0x1f, 0x8b, 0x90, 0xae, 0x50, 0x7a, 0xa8, 0xb6, 0xe0, 0x58, 0x32,
+ 0x5c, 0x62, 0xdd, 0x80, 0xc9, 0xba, 0x70, 0x3a, 0x52, 0x77, 0xda, 0x89,
+ 0xea, 0xba, 0x52, 0x26, 0x8b, 0xf9, 0x46, 0x4a, 0xec, 0x1b, 0xe9, 0x2e,
+ 0x38, 0x31, 0x5d, 0x3f, 0xba, 0x33, 0xeb, 0xc4, 0x51, 0xdf, 0xaa, 0xdb,
+ 0x7a, 0xbe, 0x5c, 0x70, 0x1c, 0xdd, 0x76, 0x35, 0x94, 0x75, 0xba, 0x74,
+ 0xfd, 0xab, 0xbb, 0x0a, 0xce, 0x76, 0x5d, 0xff, 0xd6, 0xae, 0xac, 0x93,
+ 0xd2, 0xf5, 0xe3, 0xf7, 0x17, 0x9c, 0x1e, 0x5d, 0xdf, 0x8a, 0xfa, 0x5e,
+ 0x5d, 0xff, 0x83, 0xde, 0x82, 0x93, 0x46, 0xfd, 0x97, 0x22, 0x66, 0x87,
+ 0x2d, 0x63, 0xa5, 0x04, 0x7e, 0x19, 0xb4, 0xf5, 0xa1, 0x6e, 0x0f, 0x7e,
+ 0x77, 0xe1, 0x37, 0xbf, 0x41, 0x1a, 0xfa, 0xf1, 0x6c, 0x6b, 0xf5, 0x78,
+ 0x07, 0x1e, 0xb9, 0x11, 0x79, 0x3d, 0x14, 0x97, 0x97, 0x3a, 0x5f, 0x07,
+ 0x0f, 0x6d, 0x39, 0x57, 0x16, 0xa3, 0xbf, 0x33, 0x0e, 0xde, 0xc5, 0xe4,
+ 0xb9, 0x72, 0xbd, 0x84, 0x1e, 0x0f, 0x81, 0x37, 0x5f, 0x90, 0x7c, 0x2c,
+ 0x22, 0x1b, 0x27, 0x0d, 0x69, 0xeb, 0x8e, 0x48, 0xc6, 0xe6, 0xda, 0x38,
+ 0xed, 0x89, 0x98, 0x84, 0x26, 0x33, 0x4d, 0xa6, 0x74, 0xd8, 0x39, 0x29,
+ 0x82, 0x77, 0x57, 0x28, 0x97, 0x68, 0x4b, 0x48, 0x6e, 0xfc, 0x36, 0x19,
+ 0xb4, 0x49, 0xd7, 0xdc, 0xcd, 0xde, 0x5a, 0x11, 0x23, 0x7b, 0x72, 0x40,
+ 0xc6, 0xdc, 0xa8, 0x91, 0x3b, 0xf9, 0x59, 0xc9, 0xa6, 0x24, 0x86, 0x71,
+ 0xf1, 0x3c, 0x5a, 0x66, 0x4a, 0x03, 0x32, 0xea, 0x8a, 0x91, 0x75, 0xc9,
+ 0xcf, 0x66, 0xb4, 0x37, 0xa8, 0xbe, 0xa8, 0x6b, 0x0d, 0xa9, 0xb9, 0x23,
+ 0xa8, 0xb7, 0x51, 0xdf, 0x68, 0xf4, 0xa9, 0x39, 0x54, 0x7d, 0x62, 0x44,
+ 0xa2, 0xf2, 0x74, 0x29, 0xa6, 0xfb, 0x56, 0x2a, 0xd9, 0x94, 0x8d, 0x7e,
+ 0x03, 0x32, 0xe2, 0xc6, 0x64, 0x10, 0xcf, 0x61, 0x97, 0x72, 0x15, 0x87,
+ 0x4c, 0x35, 0x14, 0xf3, 0x27, 0xd4, 0x7c, 0x89, 0x50, 0x9a, 0xf3, 0xb5,
+ 0xa2, 0xdf, 0xdb, 0xa0, 0xcb, 0x10, 0x4b, 0x9d, 0x65, 0x46, 0xf2, 0xe3,
+ 0x06, 0xe4, 0x0d, 0x4f, 0xc5, 0xd7, 0x3e, 0xd0, 0x6f, 0x89, 0xd3, 0x6d,
+ 0x48, 0x01, 0x67, 0x55, 0xb4, 0x51, 0x2e, 0xcd, 0x9a, 0x59, 0xb7, 0x56,
+ 0x72, 0x56, 0x42, 0x42, 0x13, 0x94, 0xa5, 0x41, 0x19, 0xc1, 0x18, 0xd3,
+ 0x61, 0x9f, 0xb7, 0xb1, 0xef, 0x41, 0x75, 0x0e, 0x35, 0xe9, 0xa2, 0x99,
+ 0x2b, 0x37, 0x8b, 0x39, 0xb9, 0x5f, 0x5e, 0x19, 0x17, 0x3b, 0x94, 0x7e,
+ 0xb7, 0x92, 0x75, 0x46, 0xcd, 0xec, 0xb3, 0x96, 0x84, 0x27, 0x0c, 0x19,
+ 0x75, 0x92, 0xd0, 0x80, 0xa3, 0xe6, 0xee, 0xf2, 0x2c, 0xfa, 0x71, 0x1c,
+ 0xfa, 0x95, 0x4c, 0xf0, 0x95, 0xef, 0xdb, 0x6c, 0x53, 0xc9, 0x33, 0xfb,
+ 0xe0, 0x0c, 0xb0, 0x8f, 0xe7, 0x5c, 0x9c, 0x89, 0x3a, 0xa3, 0x04, 0xce,
+ 0x48, 0x8c, 0xbe, 0x4e, 0xc8, 0xd4, 0x09, 0x4b, 0xf2, 0x29, 0xec, 0x0b,
+ 0xbd, 0xf3, 0xa9, 0x45, 0xba, 0x46, 0xc6, 0xab, 0xe9, 0xe2, 0x38, 0xd2,
+ 0xe5, 0xd1, 0x34, 0x7c, 0x82, 0xf4, 0x2d, 0xd2, 0x33, 0x36, 0xee, 0xd3,
+ 0xc8, 0xf5, 0x48, 0x9b, 0x4f, 0x17, 0xc7, 0x91, 0xae, 0x26, 0x9e, 0x35,
+ 0xff, 0x8c, 0x3e, 0xd0, 0x31, 0xe2, 0x5a, 0x38, 0xa3, 0xa8, 0xe4, 0xed,
+ 0xa2, 0x31, 0xd2, 0xbb, 0x2d, 0x0e, 0x6d, 0x36, 0x86, 0x7b, 0x49, 0xb3,
+ 0x83, 0x73, 0xac, 0x51, 0xe7, 0x0d, 0xf9, 0x26, 0xef, 0xd0, 0x9f, 0xeb,
+ 0xe3, 0xbd, 0x64, 0xcb, 0xa8, 0x9a, 0x8f, 0x34, 0x7d, 0x14, 0xf3, 0x90,
+ 0xd6, 0x4b, 0x90, 0xd5, 0x1e, 0xc8, 0x68, 0x4a, 0xfe, 0xae, 0xbc, 0x5d,
+ 0xbe, 0x53, 0xee, 0x92, 0xbf, 0x81, 0xde, 0xfe, 0x75, 0x39, 0x21, 0x2f,
+ 0x94, 0x5b, 0xe5, 0xdb, 0xe5, 0xb8, 0x3c, 0xaf, 0xe4, 0xb7, 0x4f, 0xa4,
+ 0x81, 0x32, 0x9d, 0x90, 0x46, 0xe8, 0xcf, 0x46, 0xe8, 0xe6, 0x13, 0xe0,
+ 0xdf, 0x89, 0x4e, 0xc9, 0x34, 0xa5, 0x25, 0x72, 0x0b, 0x7e, 0x9b, 0xf1,
+ 0x6b, 0x4e, 0x43, 0xee, 0x5c, 0xf2, 0x8e, 0x3c, 0xb4, 0x24, 0xa7, 0xf6,
+ 0x6c, 0xc9, 0x48, 0x79, 0xfe, 0x16, 0x4f, 0x76, 0x45, 0xfa, 0xc1, 0x63,
+ 0xb3, 0xfb, 0x7f, 0x2a, 0x19, 0x1b, 0xfb, 0xe8, 0xde, 0xa6, 0x78, 0x6f,
+ 0x76, 0x53, 0x66, 0x13, 0x90, 0x7b, 0xcb, 0xc8, 0xb9, 0x67, 0x80, 0x1b,
+ 0xf5, 0x46, 0xf6, 0x78, 0x51, 0x0a, 0xc7, 0x2b, 0x52, 0x48, 0x85, 0xe5,
+ 0x11, 0xbb, 0x22, 0x7d, 0xa9, 0x1a, 0x39, 0x64, 0x83, 0xf7, 0xdb, 0x7f,
+ 0xdf, 0xf0, 0x31, 0xfb, 0x89, 0xf2, 0x61, 0xbc, 0xb3, 0x4e, 0xe4, 0x84,
+ 0x7a, 0xf7, 0xea, 0x8b, 0xe5, 0xb0, 0x64, 0x62, 0xc5, 0xb8, 0x25, 0x2d,
+ 0xa6, 0xb7, 0xee, 0xb0, 0xdf, 0x06, 0x7e, 0x4c, 0x01, 0x27, 0x93, 0x4a,
+ 0x5f, 0xf2, 0xe3, 0xeb, 0xae, 0x66, 0x54, 0x35, 0xfa, 0xdb, 0x3d, 0x32,
+ 0xaf, 0xf8, 0x99, 0x18, 0x34, 0xd2, 0x31, 0x69, 0x2b, 0xb1, 0xdc, 0x6b,
+ 0xdc, 0x5d, 0xa6, 0x3c, 0xe3, 0xbd, 0x4c, 0x3a, 0x6f, 0x42, 0x3f, 0x0b,
+ 0xcf, 0x8c, 0xa6, 0x37, 0x48, 0x23, 0xe7, 0x21, 0x8d, 0x7c, 0xfe, 0x79,
+ 0x80, 0xc6, 0xa7, 0x16, 0xde, 0x4f, 0x04, 0xde, 0x8b, 0xe5, 0x4b, 0x75,
+ 0x1e, 0x6d, 0xbd, 0xf2, 0xc6, 0xc4, 0x57, 0xf4, 0x3a, 0x78, 0x3f, 0xcb,
+ 0xf9, 0xff, 0xaa, 0xe2, 0xc9, 0x4b, 0xf1, 0x3a, 0xeb, 0xcc, 0x06, 0xd6,
+ 0x79, 0x31, 0xb0, 0xce, 0x8b, 0x81, 0x75, 0x8a, 0xe0, 0xa9, 0x6c, 0x30,
+ 0x21, 0xc3, 0x79, 0x9a, 0x31, 0x39, 0x8a, 0x39, 0x5f, 0x97, 0x50, 0x9a,
+ 0x7a, 0xee, 0xe3, 0xcd, 0x65, 0xf4, 0x4f, 0xcb, 0xfc, 0x44, 0x51, 0xf2,
+ 0xc7, 0xc3, 0xb2, 0x4f, 0xf5, 0xdb, 0xa5, 0xe9, 0x0b, 0xb6, 0x45, 0x64,
+ 0x6f, 0x8c, 0xef, 0x7e, 0x9b, 0x05, 0x3e, 0xb3, 0xfc, 0xc6, 0x4d, 0x5e,
+ 0x99, 0xef, 0xb3, 0x7a, 0x2f, 0x03, 0xde, 0xb8, 0xb3, 0x6f, 0x2a, 0x3c,
+ 0x9c, 0x2b, 0x13, 0xb7, 0x24, 0x15, 0x72, 0xe4, 0x60, 0x5f, 0xaa, 0x59,
+ 0x46, 0x6c, 0x23, 0x35, 0xdc, 0x55, 0x4b, 0xbd, 0xc8, 0x98, 0x4e, 0x3d,
+ 0xb0, 0x41, 0x12, 0x26, 0x31, 0x5f, 0xed, 0xcb, 0x30, 0x3d, 0xfa, 0x6d,
+ 0x96, 0xfb, 0x4d, 0xa7, 0xb1, 0xaa, 0x9e, 0xba, 0x1d, 0xc2, 0x3b, 0x65,
+ 0x78, 0xb7, 0x3e, 0x63, 0x0b, 0x65, 0xe2, 0xf0, 0xad, 0xba, 0xec, 0xb7,
+ 0xe3, 0xc0, 0x96, 0x94, 0x7f, 0xb6, 0x65, 0x69, 0xd9, 0xc7, 0x89, 0x20,
+ 0x86, 0x73, 0xaf, 0xc0, 0x27, 0x87, 0x72, 0x17, 0x06, 0xad, 0x29, 0xe8,
+ 0x5c, 0xad, 0xa6, 0x61, 0xb3, 0xa6, 0x01, 0xb4, 0x76, 0x42, 0xb2, 0x94,
+ 0x2e, 0x29, 0xd1, 0xaa, 0x2a, 0x93, 0xf7, 0xfe, 0xfb, 0x7a, 0xd5, 0xee,
+ 0xe9, 0x9c, 0xff, 0xf4, 0xf1, 0xfd, 0xcd, 0x80, 0xbd, 0x68, 0x85, 0xce,
+ 0xc6, 0xc0, 0x2b, 0x1f, 0xeb, 0x89, 0xc1, 0x71, 0xd8, 0x07, 0xc8, 0xaa,
+ 0xc2, 0xf6, 0x28, 0xf0, 0xd0, 0xd2, 0xd8, 0x1c, 0xd1, 0xd8, 0x1c, 0x05,
+ 0x2e, 0xb3, 0x6c, 0xeb, 0x72, 0x4c, 0x97, 0xe3, 0x28, 0xc3, 0x8e, 0x4f,
+ 0x12, 0xbb, 0x1b, 0x8a, 0x43, 0x27, 0x14, 0xde, 0xd3, 0x56, 0x00, 0x85,
+ 0x89, 0xd7, 0xc4, 0xed, 0x56, 0x99, 0x2e, 0x61, 0xbd, 0x05, 0x6c, 0xe4,
+ 0xde, 0x83, 0xf4, 0x90, 0x96, 0x75, 0x62, 0xc2, 0x76, 0x65, 0x62, 0xa4,
+ 0xf7, 0x61, 0xec, 0x9d, 0xf8, 0x43, 0xba, 0x6f, 0x06, 0xad, 0xdc, 0xc7,
+ 0x27, 0x49, 0x2b, 0xd7, 0xab, 0xa6, 0xf7, 0xc3, 0xe2, 0x20, 0x69, 0x3f,
+ 0x83, 0x3d, 0x67, 0x80, 0x79, 0x62, 0x0c, 0x74, 0x0e, 0x60, 0xcf, 0xfd,
+ 0xc0, 0xc3, 0xbb, 0x80, 0x87, 0x7b, 0x80, 0x87, 0x7d, 0xc0, 0xc3, 0x34,
+ 0xb0, 0xb0, 0x17, 0x58, 0xd8, 0x03, 0x2c, 0x4c, 0x81, 0x37, 0x31, 0x99,
+ 0x02, 0x36, 0x4e, 0x01, 0x23, 0xa7, 0x30, 0xc7, 0xf0, 0xa4, 0x18, 0x0f,
+ 0x60, 0x0f, 0xdf, 0x9c, 0x48, 0x9e, 0x82, 0x2c, 0xc5, 0x8b, 0x26, 0xe4,
+ 0x3f, 0xd5, 0x0b, 0xd9, 0xee, 0x92, 0x99, 0xb2, 0x25, 0x05, 0xd8, 0xd4,
+ 0xb6, 0xad, 0xed, 0xd0, 0x35, 0xc8, 0x7b, 0x5c, 0xf4, 0xdf, 0x7a, 0xfd,
+ 0xfc, 0xb1, 0x88, 0xf3, 0x4f, 0x94, 0xc5, 0x84, 0xc8, 0x79, 0xc9, 0xbb,
+ 0xed, 0x76, 0x9b, 0xd9, 0x85, 0x7e, 0x2c, 0xa7, 0xcc, 0x03, 0xc7, 0xef,
+ 0x30, 0x87, 0x8e, 0x2b, 0x7f, 0x05, 0x78, 0x55, 0x91, 0xd1, 0x14, 0x75,
+ 0xab, 0x22, 0xa7, 0x53, 0xc9, 0xde, 0xa2, 0xd4, 0xcb, 0x58, 0x6c, 0x5c,
+ 0xd9, 0x5a, 0x2b, 0x7d, 0x4c, 0xd9, 0xab, 0x82, 0x83, 0x67, 0xa9, 0xdb,
+ 0xcc, 0x1f, 0xe7, 0xfe, 0xdb, 0xf1, 0x0b, 0x83, 0x16, 0xce, 0x6f, 0x49,
+ 0x5f, 0x8f, 0x6d, 0x3e, 0xd4, 0x59, 0x84, 0x42, 0x24, 0xed, 0x79, 0xac,
+ 0x9c, 0x1b, 0x6f, 0x8f, 0xb7, 0x9b, 0x96, 0x0c, 0x5a, 0x86, 0x0c, 0x43,
+ 0xbe, 0xfb, 0x52, 0x6f, 0x57, 0xc6, 0x62, 0x6c, 0xaf, 0x95, 0xaf, 0x2b,
+ 0x9f, 0x03, 0x6b, 0xcf, 0x9c, 0xc0, 0xba, 0x61, 0x9c, 0x01, 0xd7, 0xe5,
+ 0x3c, 0x28, 0x97, 0x2c, 0x94, 0x93, 0xa7, 0x8a, 0x52, 0x86, 0x9e, 0x6c,
+ 0x90, 0xec, 0xf6, 0x1a, 0xc9, 0xf4, 0x27, 0x64, 0x78, 0xa2, 0x0c, 0x9c,
+ 0x8a, 0x28, 0x5d, 0xc9, 0x0f, 0x24, 0xe4, 0xf1, 0x09, 0xd6, 0x9d, 0xc3,
+ 0xfe, 0x93, 0xc7, 0x32, 0xc2, 0xfd, 0x1b, 0x92, 0xd9, 0x7f, 0x4e, 0x1e,
+ 0x71, 0xcf, 0xc9, 0x10, 0xce, 0xf0, 0xe9, 0xf2, 0xac, 0x1c, 0x70, 0x1d,
+ 0x39, 0x0d, 0xbc, 0xcf, 0x1d, 0x07, 0xee, 0x39, 0xeb, 0x81, 0x51, 0xc9,
+ 0x73, 0xb4, 0xa1, 0x26, 0xfc, 0xbc, 0x69, 0xf0, 0xf7, 0x89, 0x09, 0xf2,
+ 0xd7, 0x94, 0x47, 0x7f, 0xd1, 0x80, 0x3e, 0x26, 0xc0, 0xcf, 0x56, 0x39,
+ 0xec, 0x26, 0x67, 0x33, 0x26, 0x70, 0x31, 0x65, 0x87, 0xa4, 0x2e, 0x8e,
+ 0x7e, 0x5e, 0x9f, 0x5c, 0x2a, 0x84, 0xb3, 0x2e, 0xa2, 0xef, 0xdb, 0xa0,
+ 0x93, 0x63, 0x63, 0xf8, 0x65, 0xd0, 0x0f, 0xf2, 0x6b, 0x27, 0x67, 0xa7,
+ 0x4c, 0xf6, 0x4f, 0xe0, 0xcc, 0x80, 0x2b, 0x93, 0x00, 0x1e, 0x9b, 0xef,
+ 0x69, 0x33, 0x4f, 0x1a, 0x5c, 0xca, 0x59, 0x02, 0x34, 0x11, 0xd3, 0xda,
+ 0xcf, 0x7d, 0x47, 0xb8, 0xce, 0x46, 0xf4, 0x7f, 0x07, 0x7e, 0xae, 0x2d,
+ 0x33, 0x38, 0x97, 0x9f, 0x82, 0x57, 0x99, 0xb8, 0x57, 0x1e, 0x9e, 0x4c,
+ 0x9e, 0x9b, 0x37, 0xf9, 0xee, 0x14, 0xf3, 0xe6, 0x6d, 0x22, 0x8d, 0xe4,
+ 0x57, 0x0a, 0xbc, 0x72, 0x6c, 0xd3, 0xdc, 0xaa, 0x7d, 0x3b, 0xea, 0x89,
+ 0x03, 0x9a, 0xe0, 0x67, 0x74, 0x07, 0xf5, 0x84, 0xf6, 0xce, 0xd7, 0x93,
+ 0x64, 0x7c, 0xca, 0x84, 0xff, 0xd1, 0x6d, 0xc9, 0x31, 0x55, 0x06, 0x8f,
+ 0x06, 0x92, 0xf1, 0x8c, 0x49, 0x9f, 0xb7, 0x4b, 0x9e, 0x76, 0xd9, 0x1f,
+ 0x7c, 0x1c, 0x8f, 0xea, 0xfe, 0xe7, 0x20, 0x23, 0xf4, 0xcf, 0xba, 0x40,
+ 0xb3, 0xa7, 0x3b, 0xd3, 0xe3, 0x31, 0xd5, 0x36, 0xa6, 0xf6, 0x60, 0x60,
+ 0x5d, 0xc8, 0x26, 0x7c, 0xb5, 0x9c, 0xd2, 0x23, 0x3b, 0x03, 0x5f, 0x1e,
+ 0x7a, 0xe0, 0xe9, 0xd0, 0x4c, 0x89, 0xb4, 0xdc, 0x43, 0x7e, 0x14, 0x41,
+ 0xcc, 0x31, 0x33, 0x8d, 0x73, 0xed, 0x91, 0x22, 0xfd, 0xb9, 0xf9, 0xd0,
+ 0xd3, 0x32, 0x38, 0x43, 0x7b, 0x83, 0x9f, 0xeb, 0xd8, 0x8c, 0x1f, 0x32,
+ 0xca, 0x16, 0x6c, 0xc1, 0x39, 0xc3, 0x4e, 0xa4, 0x36, 0x6a, 0x3f, 0xe6,
+ 0x49, 0x9c, 0xdb, 0x79, 0x9c, 0x6b, 0x49, 0x86, 0x4e, 0x5e, 0xa2, 0xcc,
+ 0x76, 0xcd, 0x48, 0xb2, 0x6b, 0x4c, 0xb6, 0xd9, 0xd3, 0xd0, 0xb7, 0xcc,
+ 0x40, 0x65, 0x97, 0x99, 0xe6, 0x98, 0x23, 0x18, 0x83, 0xe7, 0xcc, 0x25,
+ 0x39, 0x54, 0x66, 0xdd, 0xef, 0x80, 0x9f, 0xb0, 0x3b, 0x3d, 0x4f, 0x6a,
+ 0x39, 0xc7, 0x7c, 0x96, 0x3f, 0xdf, 0x25, 0x3d, 0x1f, 0xfb, 0xb1, 0x0f,
+ 0xc7, 0x2c, 0xce, 0xbb, 0x9b, 0xb6, 0x06, 0x78, 0xd3, 0x61, 0x56, 0x76,
+ 0x85, 0xd1, 0x7e, 0xba, 0x87, 0xef, 0x98, 0x07, 0xb6, 0xc6, 0x76, 0xce,
+ 0xa3, 0x2f, 0xf6, 0xe5, 0xae, 0x93, 0xb6, 0x66, 0x9f, 0x5e, 0x9e, 0x3b,
+ 0xfd, 0x00, 0x96, 0x1f, 0x6e, 0xf2, 0x78, 0x3f, 0x12, 0xf2, 0xb0, 0xfb,
+ 0x2f, 0x51, 0xa6, 0x7e, 0x3d, 0x26, 0x39, 0x37, 0x89, 0x7d, 0x42, 0x87,
+ 0xca, 0x0d, 0x86, 0xb7, 0x47, 0xf0, 0xbf, 0xff, 0x32, 0xf8, 0x20, 0x45,
+ 0x8f, 0x37, 0xe4, 0x0b, 0x79, 0xd2, 0x00, 0xd9, 0xae, 0xc3, 0xbc, 0x58,
+ 0x47, 0xf1, 0xe0, 0x96, 0x26, 0xcf, 0xef, 0x4d, 0x16, 0x33, 0x8c, 0xd7,
+ 0x1a, 0x29, 0xb3, 0xc0, 0xa8, 0xf2, 0xfd, 0x36, 0xe7, 0x9e, 0x32, 0xd7,
+ 0x91, 0xde, 0xc4, 0x85, 0xd0, 0x7e, 0x96, 0xbb, 0xa6, 0x4c, 0xf0, 0x1e,
+ 0xe7, 0x93, 0xdd, 0xde, 0xae, 0x71, 0xe9, 0x99, 0x10, 0x65, 0x94, 0xf2,
+ 0x9c, 0x77, 0xb7, 0xd9, 0xf7, 0x08, 0x65, 0x34, 0x86, 0xf3, 0x26, 0x2e,
+ 0xf0, 0x69, 0xc1, 0x26, 0xc6, 0x71, 0xc6, 0x5b, 0x34, 0xed, 0x7c, 0xb7,
+ 0x64, 0xca, 0xc6, 0x1a, 0xee, 0x7f, 0x6f, 0xf0, 0xea, 0xf8, 0xde, 0xc2,
+ 0x33, 0x39, 0xb6, 0x94, 0x56, 0x9e, 0x67, 0xf5, 0x19, 0x9e, 0x06, 0xed,
+ 0xac, 0xc7, 0x73, 0xe6, 0x14, 0xf4, 0x0f, 0x58, 0xd1, 0xd3, 0x11, 0xbf,
+ 0x88, 0xfe, 0x39, 0x60, 0x7c, 0xd1, 0x62, 0xdb, 0x55, 0x63, 0x71, 0x8c,
+ 0x49, 0x3f, 0x13, 0x3e, 0xed, 0x05, 0xe3, 0x81, 0xf2, 0x2b, 0x46, 0x76,
+ 0xe6, 0xaa, 0x91, 0x83, 0x5c, 0xcc, 0xb8, 0x3b, 0x20, 0xcf, 0xd4, 0x17,
+ 0x1b, 0x6b, 0x27, 0xe3, 0xff, 0x62, 0xb6, 0x27, 0xa6, 0xa1, 0xdb, 0x07,
+ 0xc0, 0x58, 0xef, 0x2c, 0x5b, 0xd5, 0xd9, 0xce, 0x9b, 0x61, 0x8d, 0x75,
+ 0x2c, 0x27, 0xed, 0x7b, 0xe5, 0x35, 0xec, 0x77, 0x16, 0x7c, 0x9e, 0x95,
+ 0x42, 0xb9, 0x24, 0xf9, 0x93, 0xdb, 0xec, 0x61, 0xc4, 0xb8, 0x8b, 0xb4,
+ 0x13, 0xc3, 0x8a, 0xf4, 0xbd, 0x8d, 0xdd, 0xae, 0x14, 0x6b, 0xd2, 0xc4,
+ 0xb2, 0x0e, 0xc8, 0x13, 0xea, 0x4a, 0x8b, 0x32, 0x79, 0xe7, 0xb2, 0xfd,
+ 0x20, 0xbe, 0xed, 0x59, 0xba, 0xa7, 0x19, 0xb9, 0xfe, 0x9e, 0x76, 0x2f,
+ 0xec, 0x89, 0xd8, 0x01, 0xcc, 0x77, 0x81, 0xf9, 0x2e, 0x30, 0xdf, 0x05,
+ 0xe6, 0xbb, 0xc0, 0x7c, 0x17, 0xf6, 0xc0, 0x05, 0xee, 0xbb, 0xc0, 0x7d,
+ 0x17, 0xb8, 0xef, 0x02, 0xf7, 0xdd, 0x2c, 0xce, 0x8e, 0xd8, 0x4e, 0xbb,
+ 0x71, 0xdf, 0x82, 0xad, 0xf4, 0x7c, 0x9b, 0x9b, 0xb4, 0xbf, 0x00, 0x9d,
+ 0xb4, 0x5b, 0x64, 0xb8, 0x6b, 0x33, 0xf6, 0x56, 0x87, 0x67, 0x3d, 0x9e,
+ 0x58, 0xa3, 0xeb, 0x33, 0x5a, 0x77, 0xbe, 0x0a, 0xba, 0x4c, 0x94, 0x7f,
+ 0x09, 0xb2, 0x59, 0x03, 0x7a, 0x7e, 0x41, 0xfb, 0x15, 0xa7, 0x2c, 0x4f,
+ 0x36, 0xeb, 0x51, 0xf7, 0x69, 0xd4, 0xd5, 0xa3, 0xcf, 0x21, 0xf4, 0xa1,
+ 0x5f, 0xd2, 0xa0, 0xeb, 0x82, 0xfd, 0xe8, 0x9f, 0xfc, 0x26, 0xd6, 0x4a,
+ 0xa2, 0x5f, 0x03, 0xe6, 0x6e, 0x45, 0x9f, 0xcf, 0xa2, 0xcf, 0xcd, 0x28,
+ 0xd3, 0x9f, 0xdd, 0x82, 0xf2, 0xa7, 0xaa, 0xc6, 0xdc, 0x8a, 0xba, 0xcf,
+ 0x54, 0xd5, 0xcd, 0xa3, 0x0e, 0x71, 0xb0, 0x7d, 0x51, 0x8f, 0x2b, 0xa2,
+ 0xdc, 0x5c, 0xd5, 0xe7, 0x12, 0xea, 0x7a, 0x51, 0xf7, 0x3d, 0x3c, 0x11,
+ 0xff, 0xda, 0xa4, 0xc9, 0x6f, 0xa3, 0x6f, 0x9a, 0x40, 0x7d, 0x58, 0xfb,
+ 0x97, 0x4f, 0xd2, 0xdf, 0x82, 0x9d, 0xfd, 0x53, 0xcb, 0xf3, 0xc7, 0x9e,
+ 0xb1, 0x3d, 0x59, 0xf5, 0xcb, 0x3f, 0xaa, 0x2a, 0xb3, 0xef, 0xff, 0x56,
+ 0xd5, 0xed, 0xda, 0xb8, 0xb4, 0xfc, 0x7e, 0x78, 0xf9, 0x98, 0xe3, 0x55,
+ 0x7d, 0x5e, 0x6e, 0x5c, 0x5a, 0xfe, 0x7c, 0xcd, 0xf2, 0x31, 0xbf, 0xb5,
+ 0x61, 0x69, 0xdd, 0xe1, 0xa6, 0xa5, 0x65, 0xfa, 0x7d, 0x31, 0xc4, 0x2d,
+ 0x7e, 0xff, 0x07, 0x37, 0x79, 0xed, 0xe4, 0x6f, 0xb5, 0x2c, 0x29, 0xe3,
+ 0x8d, 0xb2, 0x89, 0x73, 0xb8, 0x60, 0x40, 0xe7, 0x6c, 0x33, 0xfd, 0x8a,
+ 0x91, 0x83, 0x4c, 0x65, 0xcb, 0xfe, 0x7c, 0xd4, 0xe5, 0xea, 0xdc, 0x80,
+ 0x9f, 0x13, 0xa0, 0x8f, 0x15, 0x85, 0xdc, 0x00, 0x8b, 0x63, 0xc9, 0xa3,
+ 0x45, 0x59, 0xd4, 0xe1, 0x36, 0xf3, 0x5a, 0x3a, 0x3c, 0xa9, 0x71, 0xeb,
+ 0x32, 0xe8, 0xac, 0x48, 0x7f, 0xaa, 0x96, 0x76, 0x47, 0xe3, 0x19, 0xb1,
+ 0xa8, 0x52, 0x09, 0x6d, 0xad, 0xc8, 0xc1, 0xd4, 0x3b, 0x15, 0x51, 0x38,
+ 0xf8, 0x4d, 0xcd, 0x57, 0xe2, 0xa1, 0x0d, 0xb9, 0x8d, 0x29, 0x3f, 0x2e,
+ 0x94, 0x3e, 0x45, 0x9f, 0xe4, 0x88, 0x87, 0xb3, 0xc4, 0x22, 0x94, 0xcb,
+ 0x63, 0xe8, 0xc3, 0xf5, 0xf1, 0x9c, 0x21, 0xb6, 0x5b, 0xca, 0xce, 0xe4,
+ 0x6d, 0xce, 0xbb, 0x12, 0x5e, 0xfe, 0xd8, 0xa2, 0x2f, 0x68, 0x39, 0x67,
+ 0x60, 0xf3, 0xd8, 0x46, 0xff, 0xe0, 0x0c, 0x7d, 0x91, 0x80, 0x6f, 0xd3,
+ 0x11, 0x12, 0x67, 0x11, 0x47, 0xbd, 0x7d, 0xb5, 0xd0, 0xd7, 0x5f, 0xc3,
+ 0x5e, 0x57, 0xc6, 0xab, 0x76, 0xf3, 0xfa, 0xba, 0xbd, 0x77, 0x41, 0xb7,
+ 0x7d, 0xd9, 0x5b, 0x29, 0x07, 0x70, 0x45, 0x9d, 0xc5, 0xf3, 0xe5, 0xe4,
+ 0xb1, 0x22, 0x74, 0x69, 0x4e, 0xc5, 0xbb, 0xfe, 0xb9, 0xd0, 0xaf, 0x49,
+ 0x9e, 0x9a, 0x82, 0x6c, 0x0f, 0xa9, 0x38, 0x80, 0x31, 0x40, 0x45, 0x76,
+ 0xa7, 0x86, 0x62, 0xe4, 0x43, 0xc6, 0xbc, 0x1a, 0xa6, 0x1f, 0x31, 0xe7,
+ 0x92, 0x67, 0x29, 0xb4, 0xa7, 0xc0, 0xdb, 0x7f, 0x95, 0x5c, 0x8c, 0x75,
+ 0xff, 0x55, 0x99, 0x86, 0xff, 0xa3, 0x7c, 0x22, 0xe5, 0x03, 0xd0, 0xa7,
+ 0x83, 0xad, 0x2f, 0x93, 0xa7, 0x17, 0xc0, 0x67, 0xdf, 0x2f, 0xb8, 0x4c,
+ 0xbf, 0x54, 0x96, 0xfa, 0xcf, 0x22, 0x8f, 0x94, 0xfe, 0x19, 0x76, 0xc8,
+ 0xc4, 0x7c, 0xb4, 0x77, 0xb4, 0x29, 0xac, 0xdf, 0x11, 0xa6, 0xff, 0xe6,
+ 0xd9, 0xff, 0x10, 0xd6, 0x43, 0x4c, 0x5d, 0xfa, 0x0f, 0x23, 0xef, 0xb6,
+ 0xd2, 0xb7, 0xc2, 0xfe, 0x89, 0xab, 0x6c, 0x63, 0x5d, 0x44, 0xfb, 0xdc,
+ 0x51, 0xed, 0x63, 0xdb, 0xda, 0xc7, 0x26, 0x1d, 0x46, 0xc4, 0x4e, 0xfb,
+ 0xbe, 0x02, 0xcf, 0x0c, 0x67, 0xb3, 0x55, 0xf9, 0x0a, 0xb2, 0xb2, 0xaf,
+ 0xe0, 0xd3, 0x74, 0x16, 0xfb, 0xa4, 0x6f, 0xa7, 0x72, 0x3f, 0x8d, 0x5e,
+ 0xbe, 0x89, 0x34, 0xf8, 0x36, 0x53, 0xd9, 0xe6, 0xa3, 0x30, 0x83, 0xd8,
+ 0xdb, 0x6f, 0x83, 0xd6, 0x3d, 0x92, 0x1d, 0x3f, 0xab, 0x6d, 0x30, 0x63,
+ 0x07, 0xfa, 0xed, 0x9e, 0xcc, 0x66, 0x53, 0x0d, 0x86, 0x9e, 0xa7, 0x19,
+ 0x56, 0x33, 0x90, 0x97, 0xe2, 0x5a, 0xf4, 0x6d, 0x7c, 0x3f, 0x67, 0x56,
+ 0xfb, 0x39, 0xe7, 0xe5, 0xa0, 0xeb, 0xc5, 0x0a, 0xfd, 0xa5, 0x0b, 0xa8,
+ 0x53, 0xb4, 0xc7, 0xe9, 0x4f, 0x9a, 0x26, 0xfd, 0xc9, 0x24, 0x82, 0x0e,
+ 0x6f, 0x2f, 0x6d, 0xd8, 0xcb, 0xcc, 0xc2, 0x5e, 0xea, 0x2f, 0x2c, 0xdd,
+ 0x0b, 0xe9, 0xb7, 0xc1, 0x4f, 0x4b, 0xe3, 0x14, 0xe7, 0xfc, 0x46, 0x98,
+ 0x18, 0xd6, 0x4f, 0x9f, 0xc8, 0xf5, 0x7c, 0xb1, 0xa5, 0xf3, 0xc2, 0x63,
+ 0x28, 0x4d, 0x5d, 0xa3, 0x8d, 0xfb, 0xf7, 0xf5, 0xca, 0xd2, 0xd8, 0xce,
+ 0x3d, 0xfc, 0x09, 0xe6, 0x8c, 0x19, 0x79, 0xe5, 0x9b, 0xd1, 0xcf, 0x41,
+ 0xdc, 0x5d, 0x7a, 0x05, 0x4f, 0xea, 0x8e, 0x9a, 0x07, 0xfb, 0x8d, 0xaa,
+ 0xfd, 0x8e, 0xb9, 0x97, 0xd4, 0x1e, 0xa7, 0x4b, 0x3f, 0x90, 0xc2, 0xc9,
+ 0x1f, 0xc2, 0x26, 0x06, 0x73, 0x75, 0xcc, 0x73, 0x92, 0x57, 0xc5, 0x00,
+ 0xb6, 0x92, 0x66, 0xe6, 0xe1, 0xbe, 0x17, 0xf6, 0xe2, 0x85, 0x71, 0x9c,
+ 0xbf, 0xe1, 0xb5, 0xab, 0xf5, 0x7d, 0x9e, 0xd7, 0x04, 0xe8, 0xa9, 0xc0,
+ 0x47, 0x8d, 0x83, 0x86, 0xe0, 0x98, 0xc7, 0xa4, 0xcf, 0xe5, 0x59, 0xb5,
+ 0xc7, 0x87, 0xc4, 0xb1, 0xf3, 0xe2, 0xfb, 0x25, 0x5c, 0x9f, 0x78, 0x90,
+ 0x43, 0x0c, 0xc5, 0xdc, 0xaa, 0xcf, 0x57, 0x9f, 0xa7, 0xd1, 0x0b, 0xd5,
+ 0xf2, 0x31, 0x8a, 0xd8, 0xab, 0xe0, 0x92, 0x4f, 0xbe, 0xdc, 0xfa, 0x6b,
+ 0x5f, 0x31, 0xb8, 0x9f, 0x11, 0x95, 0x4f, 0x7c, 0x6d, 0x41, 0x7e, 0x87,
+ 0x81, 0x2b, 0x9e, 0x3c, 0xbe, 0xaa, 0x79, 0xe3, 0xcb, 0x6d, 0x54, 0xcb,
+ 0x00, 0x63, 0x43, 0xea, 0x95, 0x2f, 0x23, 0x1d, 0xf6, 0xdd, 0x8a, 0x17,
+ 0x6c, 0x53, 0x79, 0x46, 0x75, 0xce, 0x83, 0x0b, 0xe7, 0xbc, 0xbe, 0x4a,
+ 0x66, 0x53, 0xb6, 0xa7, 0xa3, 0xd4, 0x45, 0xe8, 0x34, 0xf8, 0xf5, 0xfc,
+ 0x12, 0xdd, 0xef, 0xba, 0x46, 0x8e, 0x36, 0x2a, 0xa1, 0xc9, 0x97, 0xc1,
+ 0xcb, 0x5b, 0x11, 0xbb, 0x88, 0x58, 0x13, 0xc4, 0x28, 0xfa, 0x22, 0x8b,
+ 0xfe, 0xf1, 0xb4, 0xac, 0xe4, 0x1b, 0x5f, 0xcf, 0x0f, 0xb9, 0x7d, 0x8d,
+ 0x7e, 0xc8, 0xaf, 0xd6, 0x30, 0x96, 0x99, 0x83, 0x9e, 0x1e, 0xc0, 0xf8,
+ 0x1a, 0xe7, 0x47, 0xb0, 0x6f, 0xa7, 0xad, 0x5a, 0xc7, 0xc7, 0x8b, 0xa8,
+ 0x6c, 0x9c, 0xdc, 0xa2, 0x30, 0xc3, 0x9e, 0x58, 0xc4, 0x8c, 0x61, 0x97,
+ 0xf2, 0xab, 0xf4, 0x34, 0xb6, 0x51, 0x7c, 0x8c, 0x78, 0xd6, 0x62, 0xbe,
+ 0x67, 0x65, 0x1c, 0xf0, 0x72, 0xba, 0x2b, 0xc7, 0x0a, 0x37, 0x55, 0xf1,
+ 0x72, 0x25, 0xdc, 0x3c, 0x07, 0xde, 0xa5, 0x11, 0x13, 0x27, 0xcf, 0x88,
+ 0xec, 0x41, 0x9c, 0x9c, 0x7c, 0x4b, 0xa4, 0x0f, 0xb1, 0x72, 0x72, 0x56,
+ 0x24, 0x83, 0x78, 0x99, 0xf1, 0xdb, 0x5d, 0xe0, 0x69, 0x2f, 0xe2, 0xe9,
+ 0x1e, 0x60, 0x6a, 0x0a, 0x18, 0xbb, 0x1d, 0xfc, 0xed, 0x02, 0xbf, 0x6d,
+ 0xc4, 0x5b, 0x65, 0x39, 0x70, 0x5c, 0x8c, 0x7d, 0x2a, 0x7f, 0x4d, 0x7d,
+ 0x8f, 0xc1, 0xce, 0x56, 0x2a, 0x87, 0x52, 0xed, 0x88, 0xf5, 0x13, 0xf2,
+ 0x39, 0x8b, 0xb1, 0xad, 0x61, 0xb5, 0x75, 0x7f, 0x3f, 0x14, 0xf4, 0x6b,
+ 0xb3, 0xd7, 0xb5, 0x13, 0xcb, 0xf9, 0x9f, 0x53, 0xb6, 0xe2, 0xc5, 0xd0,
+ 0x6a, 0xfc, 0xdf, 0xb7, 0xc0, 0xff, 0x9e, 0x3a, 0xa9, 0xbb, 0x4b, 0xe5,
+ 0x16, 0xda, 0xba, 0x0f, 0x11, 0xcf, 0x52, 0xb0, 0xfb, 0xb0, 0xcf, 0x15,
+ 0xb9, 0x33, 0x75, 0xb5, 0x72, 0xd1, 0xd9, 0x20, 0xf9, 0xed, 0x0f, 0x6a,
+ 0x4c, 0x3f, 0xf5, 0x87, 0x59, 0xa7, 0x08, 0x1d, 0xf1, 0xf2, 0x88, 0x43,
+ 0xe3, 0x11, 0x58, 0x0a, 0xfe, 0x35, 0xca, 0x74, 0xef, 0x55, 0x9c, 0xe3,
+ 0xb6, 0x33, 0x4c, 0x42, 0x11, 0x6b, 0xa6, 0x63, 0x51, 0x95, 0x43, 0xde,
+ 0xe4, 0xb0, 0xde, 0xc6, 0xb9, 0x0e, 0xc8, 0x34, 0xfc, 0x8b, 0x99, 0x5e,
+ 0xd0, 0xb8, 0xbd, 0x19, 0xfd, 0xa9, 0x7b, 0xe4, 0xf9, 0x80, 0x0c, 0xc6,
+ 0xc8, 0xd3, 0x18, 0xfa, 0xef, 0x45, 0x9f, 0x46, 0x3c, 0xff, 0x28, 0x34,
+ 0x6d, 0x33, 0x9e, 0xfe, 0x3c, 0xca, 0x9c, 0x23, 0x68, 0x5b, 0x77, 0x85,
+ 0x45, 0xcd, 0xc9, 0x31, 0xcd, 0x0a, 0x03, 0x16, 0xd7, 0xe2, 0x3a, 0x6c,
+ 0x7b, 0xaf, 0x72, 0x47, 0x77, 0x6f, 0x60, 0xbd, 0x86, 0xc0, 0x7a, 0xbd,
+ 0x81, 0xf5, 0x48, 0x67, 0x63, 0x80, 0xce, 0x46, 0x8c, 0xff, 0x5d, 0xac,
+ 0x4d, 0x7e, 0x04, 0xd7, 0xcc, 0x07, 0xd6, 0xf4, 0xf7, 0xd7, 0x1c, 0x18,
+ 0xf7, 0x0e, 0xd6, 0x63, 0x5d, 0x2c, 0x50, 0x47, 0x1a, 0x9a, 0x50, 0xc7,
+ 0x72, 0x63, 0x80, 0xae, 0xa8, 0x8a, 0xf7, 0xa7, 0xd5, 0x19, 0x92, 0xcf,
+ 0x75, 0xb0, 0x6b, 0x26, 0x6c, 0x4b, 0x0d, 0xfc, 0xaf, 0xea, 0xbd, 0x7e,
+ 0x0d, 0xeb, 0xfa, 0xf3, 0xc5, 0x30, 0x07, 0xfb, 0xb3, 0x6f, 0x48, 0x8f,
+ 0x67, 0x3d, 0xdb, 0xff, 0xb6, 0xf2, 0x8c, 0xe2, 0x5b, 0x1a, 0xb4, 0x93,
+ 0xc6, 0x36, 0x99, 0x6a, 0xb4, 0x70, 0x9e, 0xa6, 0xb6, 0xa5, 0xc0, 0xda,
+ 0xb2, 0x69, 0xb4, 0x77, 0xf3, 0xfc, 0x37, 0x68, 0x4c, 0xad, 0x33, 0xb2,
+ 0xc7, 0x99, 0x4b, 0xa8, 0xd7, 0xb1, 0x22, 0xe2, 0x13, 0x65, 0x87, 0x7c,
+ 0x3b, 0x41, 0x3b, 0x44, 0xdf, 0x86, 0x36, 0xf6, 0x9c, 0x7e, 0xc7, 0x13,
+ 0x72, 0xfc, 0xd0, 0x4c, 0xa3, 0x5c, 0x54, 0x7c, 0xb5, 0x65, 0x7e, 0x81,
+ 0xaf, 0x61, 0xfd, 0xbd, 0xe6, 0x31, 0xfd, 0x2d, 0x64, 0x3f, 0x7c, 0x27,
+ 0xbc, 0x97, 0x32, 0xa0, 0x23, 0x21, 0xed, 0xdd, 0xcc, 0x61, 0x14, 0xf1,
+ 0x74, 0xf0, 0x34, 0xf0, 0x84, 0xcd, 0x42, 0x0c, 0xd2, 0xde, 0xcd, 0x58,
+ 0x50, 0x40, 0xdb, 0x15, 0x15, 0x07, 0xce, 0x94, 0x6d, 0xe3, 0x4e, 0xd7,
+ 0xcb, 0x1d, 0xcd, 0x3b, 0xab, 0xe5, 0x8e, 0x1e, 0xa8, 0xc5, 0x79, 0x9c,
+ 0xf2, 0x73, 0x47, 0xf3, 0xa2, 0x72, 0x47, 0xa7, 0xae, 0x93, 0x3b, 0xca,
+ 0xac, 0x3d, 0x77, 0xc4, 0xf9, 0x2d, 0xb9, 0xbb, 0xc7, 0x36, 0xbf, 0xa8,
+ 0x73, 0x47, 0x6f, 0x88, 0x97, 0x3b, 0xba, 0x28, 0x2b, 0xe7, 0x8e, 0x8e,
+ 0x56, 0xe5, 0x8e, 0x9a, 0x54, 0xee, 0x88, 0xf3, 0x78, 0xb9, 0x23, 0x96,
+ 0xf3, 0xdd, 0xbf, 0xac, 0x72, 0xe9, 0xf9, 0x6e, 0x60, 0xb0, 0xeb, 0x63,
+ 0x9c, 0x6d, 0x0c, 0xa8, 0xf8, 0xf2, 0x4a, 0xb8, 0xd9, 0xf1, 0x31, 0x8e,
+ 0xb6, 0x60, 0xf3, 0x82, 0x3d, 0xf3, 0xf1, 0x6e, 0x54, 0xd9, 0xbd, 0xe5,
+ 0xf9, 0xc5, 0x7b, 0xaa, 0xf2, 0x8b, 0x03, 0x9e, 0xdd, 0x50, 0x38, 0x37,
+ 0xa8, 0x71, 0x6e, 0x74, 0xc1, 0xcf, 0x39, 0x59, 0xcb, 0x18, 0x7c, 0xa4,
+ 0x14, 0xc4, 0x51, 0x4b, 0x8d, 0xf5, 0xf2, 0x2c, 0x8b, 0x18, 0x7a, 0xb8,
+ 0x0a, 0x43, 0x1f, 0x5b, 0xf1, 0xbb, 0x58, 0x3c, 0xb3, 0xfc, 0xbb, 0x98,
+ 0x21, 0xcd, 0xf4, 0x39, 0xba, 0xf3, 0xd8, 0x03, 0x63, 0xe6, 0xfd, 0x92,
+ 0x19, 0xb0, 0x81, 0x45, 0x7e, 0xfe, 0x85, 0xe7, 0xbc, 0x68, 0x63, 0xb2,
+ 0xe6, 0xc7, 0x97, 0x83, 0x79, 0x48, 0xe5, 0x60, 0xbe, 0x5f, 0x1b, 0xcc,
+ 0xc1, 0xcc, 0x03, 0xb3, 0x32, 0x16, 0xf3, 0x5b, 0x2b, 0xe7, 0x60, 0x1e,
+ 0x5a, 0x21, 0x07, 0xf3, 0x5d, 0x59, 0xcc, 0xc1, 0x7c, 0x57, 0xfc, 0x1c,
+ 0x0c, 0xe7, 0x08, 0x69, 0x9f, 0x56, 0x30, 0xee, 0x02, 0x7e, 0xe7, 0xf1,
+ 0xf3, 0xf2, 0x32, 0xf3, 0x0b, 0x7b, 0x58, 0x29, 0x2f, 0xf3, 0x6f, 0xb5,
+ 0x1f, 0x24, 0x2f, 0xe3, 0xd9, 0x04, 0x3f, 0x2f, 0x83, 0x9f, 0x0d, 0x1b,
+ 0x64, 0x06, 0xf3, 0x32, 0xef, 0x53, 0x37, 0x50, 0xc7, 0x32, 0xeb, 0xa1,
+ 0x23, 0xb0, 0x53, 0x19, 0xd8, 0x99, 0x69, 0xf7, 0xd7, 0xd5, 0x79, 0xcc,
+ 0xb8, 0x53, 0xd8, 0x77, 0x02, 0xe7, 0x41, 0x5e, 0xb6, 0x2b, 0x5f, 0x34,
+ 0x63, 0xc5, 0x8d, 0x6c, 0x27, 0xac, 0xda, 0x38, 0xbf, 0x9d, 0x5b, 0xc6,
+ 0x50, 0x99, 0xf2, 0x1e, 0x31, 0x0a, 0xd8, 0x4b, 0xdf, 0xf8, 0x94, 0x0c,
+ 0x95, 0x7d, 0x3f, 0xab, 0x5b, 0x9f, 0xc5, 0x94, 0xd2, 0xd3, 0x69, 0xf0,
+ 0x00, 0x98, 0xb1, 0x06, 0x9b, 0x75, 0x16, 0x34, 0x07, 0xf7, 0x81, 0x18,
+ 0xba, 0x07, 0x75, 0xea, 0xdc, 0xe9, 0x6f, 0xfa, 0xb4, 0x24, 0xa8, 0xf3,
+ 0x6b, 0x98, 0x8f, 0x75, 0x67, 0x55, 0xfc, 0x56, 0xe8, 0xe1, 0x5e, 0x69,
+ 0xfb, 0xe6, 0x40, 0x1f, 0xea, 0x66, 0x18, 0x33, 0xd2, 0x0e, 0xfa, 0x31,
+ 0x5d, 0x54, 0xc5, 0x74, 0x9b, 0x15, 0x3f, 0xc8, 0xeb, 0x5f, 0x8b, 0x10,
+ 0x3b, 0x37, 0x3b, 0xdc, 0xc3, 0x79, 0x8d, 0x7b, 0x2c, 0xfb, 0xb1, 0x23,
+ 0xdf, 0xc9, 0xa7, 0xa7, 0x54, 0xde, 0x67, 0xda, 0xf5, 0xcf, 0xf0, 0x5b,
+ 0xd8, 0x3b, 0xcb, 0xbd, 0x72, 0xa1, 0x59, 0x22, 0xb1, 0x34, 0x73, 0xbd,
+ 0xf4, 0xd5, 0x77, 0x30, 0xf7, 0x50, 0xd3, 0xb4, 0x8a, 0xfe, 0xee, 0x5b,
+ 0x45, 0x7f, 0xef, 0xae, 0xd2, 0xdf, 0xfe, 0x55, 0xf5, 0xf7, 0xeb, 0x91,
+ 0xa0, 0xfe, 0xee, 0x5b, 0x45, 0x7f, 0x1f, 0xad, 0xd2, 0xdf, 0x83, 0x37,
+ 0xa4, 0xbf, 0x3a, 0x36, 0x4e, 0xdd, 0xaa, 0x72, 0xc6, 0xc3, 0x13, 0xc4,
+ 0xac, 0x4f, 0xeb, 0xdc, 0xd5, 0x4a, 0xbe, 0x98, 0x4f, 0x43, 0x5b, 0xcd,
+ 0x47, 0xe3, 0x87, 0xfd, 0x23, 0xf6, 0xe9, 0xf9, 0xa3, 0xfd, 0xf0, 0x69,
+ 0xaf, 0xbd, 0xee, 0x1f, 0x8b, 0x99, 0xf6, 0x7d, 0xc0, 0xad, 0x1f, 0xd1,
+ 0xda, 0x6b, 0x91, 0x3f, 0xc6, 0x56, 0xf4, 0x07, 0xa2, 0xda, 0x66, 0x4e,
+ 0x6a, 0x1d, 0xf4, 0xf3, 0x12, 0x41, 0x7d, 0xa6, 0x9c, 0x52, 0x36, 0x7f,
+ 0x8a, 0x3d, 0x51, 0x3e, 0x7d, 0x0c, 0xd8, 0x52, 0xa5, 0x13, 0x73, 0x52,
+ 0x00, 0x6e, 0x79, 0x3a, 0x41, 0x39, 0xeb, 0xc4, 0xbe, 0x61, 0x2b, 0xdd,
+ 0xa7, 0xbd, 0xb3, 0x70, 0xf0, 0x9c, 0xf1, 0x75, 0x3f, 0x81, 0x75, 0xfd,
+ 0x36, 0xda, 0x1e, 0x07, 0x3e, 0xd9, 0x36, 0xf8, 0x93, 0x2d, 0xc0, 0x19,
+ 0xd6, 0x2f, 0xcd, 0x73, 0xaf, 0x8e, 0xb1, 0x52, 0x0c, 0xa3, 0xef, 0xe9,
+ 0x1e, 0x60, 0x4e, 0x0f, 0x71, 0xb3, 0x84, 0xd8, 0x8c, 0x7a, 0x41, 0x5d,
+ 0xe9, 0xe8, 0xda, 0x6d, 0xd2, 0xe7, 0x7b, 0x12, 0x71, 0xfc, 0x2d, 0x4a,
+ 0xaf, 0x76, 0x97, 0x3b, 0x66, 0xdf, 0x30, 0xb9, 0x46, 0xa5, 0x92, 0x57,
+ 0xdf, 0x19, 0xc4, 0x6c, 0xeb, 0xde, 0xb2, 0x8e, 0x36, 0xf3, 0x16, 0x27,
+ 0xa4, 0xe5, 0x3e, 0x83, 0x77, 0xea, 0xd1, 0xeb, 0xf0, 0x47, 0x78, 0x47,
+ 0xe1, 0x27, 0x2a, 0x5f, 0x37, 0xed, 0xd2, 0xf7, 0x60, 0xcc, 0xb4, 0x53,
+ 0xf7, 0xdb, 0xa2, 0xbe, 0xb1, 0x66, 0x53, 0x3b, 0xf4, 0xf7, 0x36, 0xda,
+ 0xc4, 0x24, 0x31, 0x75, 0xc9, 0x79, 0xf3, 0x8e, 0x47, 0x4e, 0xc5, 0x5c,
+ 0x1c, 0xaf, 0x7c, 0x7f, 0xc4, 0x49, 0x56, 0xe0, 0xfb, 0x40, 0x44, 0xc7,
+ 0x97, 0xd4, 0xf9, 0xa8, 0x8a, 0x7d, 0xbd, 0x78, 0x8a, 0xf1, 0xf7, 0xd2,
+ 0xbb, 0x1d, 0x2b, 0xcb, 0x40, 0xcb, 0x07, 0x90, 0x81, 0xea, 0xf3, 0x8b,
+ 0x00, 0x8b, 0xfc, 0xf3, 0xf3, 0x7d, 0xac, 0xbf, 0xd0, 0xfb, 0xde, 0xa2,
+ 0xf5, 0xe9, 0xff, 0xc3, 0x3e, 0x8d, 0xc0, 0x3e, 0x7d, 0x6c, 0xfc, 0xa2,
+ 0xde, 0xe7, 0xce, 0x2a, 0x6c, 0xec, 0x41, 0xfd, 0xe1, 0x9a, 0x8d, 0x1f,
+ 0x10, 0x1b, 0xf7, 0xde, 0x10, 0x36, 0xfe, 0x70, 0xdd, 0x5a, 0xb1, 0xf1,
+ 0xd0, 0x07, 0xc6, 0x46, 0xee, 0x6b, 0x65, 0x3c, 0xda, 0xb7, 0x0c, 0x8f,
+ 0xfe, 0xe0, 0x13, 0xc4, 0xa3, 0xd5, 0xb0, 0x84, 0xe7, 0xd2, 0xa0, 0x7c,
+ 0x6c, 0x4f, 0xff, 0xe0, 0x5f, 0xcc, 0x84, 0xe5, 0xc2, 0xbd, 0x11, 0x79,
+ 0x6d, 0x27, 0xfc, 0x6e, 0xf2, 0x48, 0x9d, 0x07, 0xcb, 0xd1, 0x3a, 0xcf,
+ 0x36, 0xc6, 0x1b, 0xbd, 0x9c, 0x02, 0xc7, 0xf8, 0x3a, 0x6d, 0xa3, 0x9d,
+ 0x6d, 0x5b, 0xe4, 0xf5, 0xc6, 0x1b, 0x89, 0x53, 0xf9, 0x8d, 0x66, 0xa5,
+ 0x38, 0x75, 0xf5, 0x9c, 0xe6, 0x62, 0x9c, 0x4a, 0xac, 0x6d, 0xd4, 0x79,
+ 0x2c, 0xc6, 0x67, 0xfb, 0x35, 0x7e, 0xf2, 0x1d, 0xf1, 0xb8, 0x8b, 0x58,
+ 0xdc, 0x45, 0x1c, 0xee, 0x22, 0x46, 0x87, 0x6d, 0x7e, 0x01, 0x32, 0xf7,
+ 0x6d, 0x17, 0x31, 0xb8, 0x8b, 0x18, 0xdc, 0xed, 0xd2, 0x71, 0x7c, 0xbf,
+ 0xfe, 0x76, 0xc1, 0xef, 0xfb, 0xcc, 0x83, 0x14, 0x61, 0x57, 0x46, 0x79,
+ 0x3f, 0xc3, 0xcc, 0xa6, 0xd6, 0xe9, 0xfd, 0xf9, 0x79, 0xfd, 0x56, 0x9d,
+ 0x5b, 0xda, 0xb4, 0x49, 0xf9, 0x0b, 0xe6, 0x2b, 0x75, 0xde, 0x1d, 0x00,
+ 0xde, 0x23, 0x79, 0x14, 0xbe, 0x92, 0xba, 0x87, 0x45, 0x3d, 0xad, 0x98,
+ 0x69, 0xe6, 0x8e, 0xc4, 0x34, 0xd3, 0x77, 0x60, 0xcc, 0x36, 0x2f, 0x66,
+ 0x89, 0x49, 0xc8, 0x4c, 0xd7, 0x93, 0xa7, 0x86, 0x99, 0x5e, 0xaf, 0xe7,
+ 0x9a, 0xaf, 0xf3, 0xfc, 0xbd, 0x4e, 0x96, 0x2d, 0x33, 0xfd, 0x59, 0x3e,
+ 0x71, 0xee, 0x7e, 0xfd, 0x3d, 0x8d, 0x4b, 0xd7, 0x1a, 0x53, 0x18, 0x9f,
+ 0x4d, 0xdd, 0x8b, 0xf9, 0xd4, 0xfd, 0xa7, 0x05, 0x7e, 0x9b, 0xd7, 0xe4,
+ 0xf7, 0x98, 0xe6, 0xb7, 0xc7, 0xe3, 0x10, 0xfb, 0xa9, 0xdc, 0x36, 0x79,
+ 0xed, 0xcf, 0xa7, 0x72, 0x93, 0x58, 0x47, 0xdd, 0x01, 0xc1, 0xb3, 0x62,
+ 0x49, 0xc3, 0xc0, 0x7d, 0x61, 0x27, 0xb8, 0xae, 0xff, 0x2d, 0x7f, 0x2d,
+ 0x6b, 0x6e, 0x51, 0xdf, 0x07, 0x3d, 0xbb, 0x31, 0xa6, 0x64, 0xd0, 0x4a,
+ 0x73, 0x5f, 0xef, 0x43, 0xfe, 0xc6, 0x94, 0xfc, 0xe5, 0x10, 0x67, 0x8d,
+ 0xf6, 0x74, 0x24, 0x2c, 0x73, 0xba, 0x8e, 0x39, 0xe4, 0xbe, 0xb2, 0x8f,
+ 0x7d, 0x5c, 0xaf, 0xda, 0xa6, 0x33, 0xff, 0xe7, 0x63, 0x9a, 0xb4, 0x78,
+ 0x79, 0xc1, 0xb5, 0xde, 0xa9, 0x58, 0xd4, 0xa5, 0xc1, 0x05, 0x5d, 0xaa,
+ 0xab, 0xd2, 0x25, 0x7f, 0x9f, 0xeb, 0xc5, 0xff, 0xe6, 0xbe, 0xd2, 0x5d,
+ 0x90, 0xb9, 0x72, 0xe0, 0x1b, 0xcf, 0x82, 0x6c, 0xf0, 0x4e, 0xcc, 0x3d,
+ 0x90, 0x41, 0x7e, 0xdf, 0xd8, 0x03, 0x3d, 0xaa, 0x54, 0xfa, 0x98, 0x27,
+ 0xdf, 0xde, 0xaf, 0xef, 0x5b, 0x5c, 0x51, 0x39, 0x12, 0x6b, 0x59, 0x8e,
+ 0xa4, 0x0f, 0xb2, 0x02, 0x3f, 0x00, 0x3a, 0x98, 0x57, 0x67, 0x49, 0x9f,
+ 0xa0, 0xfa, 0x1b, 0xd2, 0xc5, 0x7a, 0x8f, 0x0f, 0x9d, 0xf5, 0xde, 0x77,
+ 0x14, 0x73, 0xd3, 0xd2, 0x32, 0xc7, 0x27, 0xea, 0x3d, 0x59, 0x39, 0x06,
+ 0xfb, 0xdc, 0x07, 0x59, 0xac, 0x91, 0x9c, 0x9a, 0xef, 0x98, 0xe4, 0x9f,
+ 0xfd, 0xcf, 0xc6, 0xa5, 0xfd, 0x51, 0x77, 0xd2, 0xef, 0xff, 0x78, 0x55,
+ 0xff, 0xc7, 0xd1, 0xff, 0x67, 0x55, 0xfd, 0x1f, 0x0f, 0xf4, 0x3f, 0xa1,
+ 0xfb, 0xd7, 0xa2, 0xbf, 0xd2, 0x83, 0x26, 0xdf, 0x2f, 0x36, 0x1d, 0xc4,
+ 0xb3, 0xcf, 0xfa, 0x63, 0x4e, 0x04, 0xc6, 0x4c, 0x56, 0xad, 0x31, 0x89,
+ 0x7e, 0xf1, 0xa6, 0xa5, 0x6b, 0xa0, 0xee, 0x64, 0x8d, 0xfe, 0xbe, 0x47,
+ 0x9f, 0xe5, 0xa0, 0xce, 0x17, 0xe0, 0x59, 0x0a, 0x7e, 0x33, 0xe2, 0x77,
+ 0x0a, 0xca, 0x9e, 0xff, 0x8d, 0xc2, 0xbf, 0x93, 0x47, 0xbd, 0xcd, 0x40,
+ 0x6f, 0x17, 0xfd, 0x1a, 0x4f, 0x2e, 0x83, 0x32, 0x49, 0x9c, 0x28, 0x4a,
+ 0xc8, 0x29, 0xd3, 0x57, 0x32, 0x0a, 0x33, 0xbe, 0x7d, 0xe2, 0xbd, 0x2b,
+ 0xde, 0xd7, 0xf5, 0xec, 0x70, 0xd8, 0x99, 0xd3, 0x31, 0xe2, 0xaf, 0x90,
+ 0x7e, 0xe0, 0xa6, 0x8f, 0x9d, 0x72, 0xcc, 0xd3, 0x1f, 0xca, 0x31, 0xe7,
+ 0xd7, 0x7a, 0x44, 0x99, 0xd5, 0xeb, 0xf4, 0x2d, 0xc3, 0xb7, 0xc4, 0xb2,
+ 0x3c, 0x5c, 0x68, 0x0d, 0xf8, 0xd6, 0xbf, 0x80, 0x6f, 0xf7, 0xca, 0x94,
+ 0x9d, 0x50, 0x79, 0xd0, 0x43, 0x0b, 0x79, 0x81, 0xc3, 0x91, 0x46, 0x87,
+ 0x79, 0x81, 0xe4, 0xa9, 0x8c, 0x7c, 0xb0, 0xbc, 0xc0, 0xbe, 0x2a, 0x1d,
+ 0xd9, 0xbb, 0xaa, 0xed, 0xfc, 0xb3, 0xfa, 0xb5, 0xe6, 0x05, 0x1e, 0xa9,
+ 0xb2, 0x63, 0x87, 0x6e, 0xc0, 0x76, 0xe6, 0x95, 0xed, 0xe4, 0x5e, 0xaf,
+ 0xe7, 0xcb, 0x7f, 0x25, 0xf2, 0xd1, 0xd8, 0xce, 0xd5, 0x72, 0xe2, 0x41,
+ 0x7b, 0x40, 0xb9, 0xba, 0xac, 0xfd, 0x6c, 0x3c, 0x67, 0x2e, 0x43, 0x3f,
+ 0x4d, 0x19, 0x54, 0xb2, 0xcc, 0xb2, 0x1f, 0xff, 0xde, 0xb7, 0x10, 0xff,
+ 0x2e, 0xc6, 0xac, 0xf0, 0x67, 0xbb, 0xfc, 0xd8, 0x88, 0x7e, 0xb3, 0x6d,
+ 0x14, 0xdc, 0x3d, 0xe6, 0x90, 0x6a, 0x63, 0x8e, 0xf7, 0x36, 0xf9, 0x9c,
+ 0xba, 0x27, 0x70, 0x5e, 0xe7, 0xd2, 0xa6, 0x54, 0x4c, 0xc0, 0xef, 0x1c,
+ 0x85, 0xd4, 0x46, 0xed, 0x03, 0x5e, 0x0f, 0x67, 0x97, 0xc6, 0xcf, 0xa6,
+ 0x79, 0x04, 0x63, 0x19, 0x3f, 0x7f, 0x21, 0x4a, 0x4c, 0xcd, 0x96, 0x57,
+ 0x1d, 0x8f, 0x71, 0x1c, 0xcf, 0x3e, 0x2a, 0x56, 0x46, 0xbf, 0x39, 0x3d,
+ 0xde, 0x8b, 0x95, 0xb3, 0xe5, 0xad, 0x51, 0x0f, 0x17, 0x57, 0x8b, 0x63,
+ 0x8e, 0x44, 0x99, 0x8b, 0x9c, 0x73, 0xaf, 0x47, 0xeb, 0xf2, 0xd8, 0x3c,
+ 0xb4, 0x2c, 0x36, 0xb7, 0x74, 0xec, 0x7d, 0xbf, 0x8a, 0xcd, 0x3d, 0x1e,
+ 0x73, 0x2f, 0xc1, 0xd8, 0xca, 0x01, 0x36, 0xf2, 0x5b, 0x10, 0xb1, 0x82,
+ 0x3e, 0x0b, 0xe4, 0x67, 0xfc, 0x37, 0x94, 0x1f, 0xb3, 0x5c, 0x7e, 0x3e,
+ 0x6e, 0xbb, 0xe1, 0xef, 0xfd, 0xb2, 0x78, 0xf9, 0xc5, 0x3d, 0xa0, 0x85,
+ 0xf1, 0x56, 0x58, 0xcb, 0xc3, 0xcf, 0x69, 0xfc, 0xf6, 0xfb, 0xf9, 0xb9,
+ 0x86, 0x85, 0x6f, 0xc9, 0xc5, 0xcc, 0x92, 0x1c, 0xcf, 0x16, 0xa6, 0xce,
+ 0x71, 0xee, 0x99, 0x1b, 0xf8, 0xde, 0xf2, 0x61, 0xee, 0x7c, 0x54, 0xdb,
+ 0xb9, 0x57, 0x21, 0xfb, 0x09, 0x7d, 0xff, 0xaf, 0x0b, 0x3a, 0xc0, 0x3b,
+ 0xd0, 0xd5, 0x58, 0xab, 0xee, 0xf9, 0x45, 0x36, 0xa5, 0xf9, 0xed, 0x82,
+ 0x3e, 0xc1, 0x4f, 0xf4, 0x5e, 0xe3, 0x72, 0x6c, 0xc2, 0xcb, 0xd3, 0x9a,
+ 0xab, 0xde, 0xf1, 0xbb, 0x04, 0x5e, 0x24, 0x8f, 0xfa, 0x79, 0x5a, 0xd3,
+ 0xbb, 0xe3, 0x77, 0xf4, 0xa3, 0xbb, 0xe3, 0xc7, 0xf9, 0x2d, 0xd9, 0xbb,
+ 0xc2, 0x1d, 0xbf, 0xd0, 0x1a, 0xef, 0xf8, 0x6d, 0x54, 0x79, 0x5a, 0xce,
+ 0xe3, 0xe5, 0x69, 0x59, 0x6e, 0xeb, 0xfe, 0x94, 0xc2, 0xa8, 0xe9, 0x09,
+ 0xe6, 0x75, 0x1e, 0x5c, 0xf7, 0xc9, 0xe4, 0x75, 0xde, 0x8b, 0x7e, 0xfc,
+ 0x79, 0x1d, 0x7e, 0x17, 0xf8, 0xb2, 0xf7, 0xdd, 0x5a, 0x6e, 0x24, 0x3f,
+ 0xf0, 0xe1, 0x72, 0xb0, 0x07, 0x55, 0x0e, 0x76, 0xfb, 0xfa, 0x60, 0x0e,
+ 0xd6, 0xbc, 0xce, 0x3d, 0xb8, 0x83, 0x2b, 0xe4, 0x60, 0xc3, 0x81, 0x7b,
+ 0x70, 0x61, 0x7d, 0x0f, 0x6e, 0xa3, 0x83, 0x18, 0x53, 0xe7, 0x5b, 0xcd,
+ 0x55, 0xef, 0xc1, 0xed, 0x5e, 0xff, 0xe1, 0xf3, 0xad, 0xcb, 0xee, 0xc1,
+ 0x1d, 0xcd, 0x48, 0x8b, 0x24, 0x6e, 0x28, 0x16, 0xfa, 0x30, 0x71, 0x10,
+ 0xff, 0x8f, 0x40, 0x0d, 0xf6, 0x0c, 0x99, 0x8f, 0x51, 0x3e, 0x29, 0x77,
+ 0x69, 0x33, 0x5f, 0xe6, 0x7b, 0x17, 0xcf, 0xc7, 0xe8, 0xef, 0x5c, 0x7a,
+ 0xb7, 0x62, 0xf1, 0x6e, 0x72, 0x64, 0xe1, 0x6e, 0xf2, 0x18, 0x64, 0xc6,
+ 0x9c, 0x88, 0xc8, 0x74, 0xc0, 0xb6, 0x8e, 0xba, 0xf0, 0x9b, 0x26, 0x6d,
+ 0xdd, 0xce, 0xff, 0xa7, 0x82, 0xb8, 0xb0, 0xc4, 0xfb, 0xcc, 0x0d, 0x12,
+ 0x9a, 0x54, 0x98, 0x1a, 0xf3, 0xfe, 0xaf, 0x4e, 0x1c, 0x7d, 0x78, 0x77,
+ 0x35, 0x2c, 0x87, 0x62, 0x94, 0x65, 0x5f, 0x8e, 0xbf, 0x05, 0xfe, 0x36,
+ 0x65, 0x16, 0xcb, 0x31, 0x2d, 0xd7, 0x94, 0x69, 0x5f, 0xfe, 0x62, 0x32,
+ 0x32, 0x41, 0x59, 0xde, 0xa1, 0xff, 0x9f, 0xc4, 0x39, 0x29, 0x94, 0xcf,
+ 0xea, 0x78, 0x43, 0x7d, 0x8b, 0x02, 0x1f, 0x5b, 0xb4, 0x0d, 0xc6, 0x73,
+ 0xa6, 0x85, 0x36, 0x8f, 0xdf, 0x1e, 0xa5, 0x6f, 0x7c, 0x5b, 0x7c, 0x08,
+ 0x78, 0x37, 0xa8, 0x72, 0x27, 0x37, 0xc2, 0x6f, 0xe3, 0x1a, 0xdf, 0x48,
+ 0xd7, 0xca, 0x73, 0xdf, 0x5f, 0xbe, 0x8c, 0xfd, 0xb5, 0x40, 0x36, 0xbe,
+ 0x2a, 0xb9, 0x93, 0xb7, 0x49, 0xdf, 0x89, 0x24, 0xe8, 0x79, 0xbf, 0x52,
+ 0x48, 0xc1, 0xb7, 0x7e, 0x96, 0x77, 0xe1, 0x80, 0xa1, 0x2e, 0x30, 0x14,
+ 0xbc, 0x7b, 0x61, 0x99, 0xbf, 0x11, 0xbc, 0x43, 0x97, 0x5a, 0xb8, 0x13,
+ 0xf5, 0x7c, 0x59, 0x22, 0x8d, 0xa4, 0x7b, 0x62, 0xf1, 0x2e, 0xfc, 0x5c,
+ 0x39, 0xa7, 0xec, 0xdb, 0x73, 0xe5, 0x25, 0x39, 0x21, 0x75, 0x8e, 0xc3,
+ 0xa5, 0x97, 0x61, 0xe3, 0x2e, 0x1b, 0xb4, 0x71, 0x63, 0xae, 0xdc, 0x12,
+ 0x12, 0x9e, 0x89, 0x18, 0xe0, 0x83, 0xba, 0x9b, 0xe2, 0xdd, 0x4d, 0x68,
+ 0x55, 0x67, 0xfb, 0x7f, 0xd4, 0x5d, 0x7d, 0x6c, 0x5b, 0xd7, 0x75, 0x3f,
+ 0x7c, 0xa4, 0x3e, 0x4c, 0xcb, 0xd2, 0x93, 0x4c, 0xc9, 0xb4, 0x2d, 0xcb,
+ 0x8f, 0xd2, 0x93, 0xa5, 0xc4, 0x4a, 0xc1, 0x79, 0xda, 0xaa, 0x01, 0x5a,
+ 0xc7, 0x52, 0xf4, 0xc7, 0x82, 0x60, 0xa5, 0x65, 0x25, 0xf3, 0xd2, 0x2c,
+ 0x51, 0x29, 0xdb, 0xc9, 0xfe, 0x18, 0xe0, 0x25, 0xd9, 0x9a, 0xfd, 0x51,
+ 0xe4, 0x95, 0x94, 0x12, 0x63, 0x56, 0x4d, 0xc6, 0xe6, 0x84, 0x02, 0x0b,
+ 0x36, 0x56, 0x92, 0x9d, 0x14, 0x50, 0xc0, 0x24, 0x6d, 0x87, 0x2c, 0x6d,
+ 0x11, 0x55, 0x76, 0xda, 0x7f, 0x8d, 0x2d, 0xc0, 0xb2, 0x2e, 0x69, 0x14,
+ 0x3b, 0xc8, 0x02, 0x2c, 0x58, 0xbb, 0x6e, 0x28, 0xf6, 0x4f, 0xc7, 0x9d,
+ 0xdf, 0xfd, 0x20, 0x1f, 0xc9, 0x47, 0x7d, 0x24, 0x6e, 0x81, 0x09, 0x10,
+ 0xc8, 0xf7, 0xde, 0x7d, 0xef, 0xdd, 0x7b, 0xee, 0xf9, 0xf8, 0x9d, 0x73,
+ 0xcf, 0xb9, 0x94, 0xba, 0xe2, 0x35, 0x57, 0x6e, 0x49, 0x65, 0x7e, 0x65,
+ 0xce, 0x89, 0x9c, 0x0f, 0x95, 0x43, 0x0b, 0x9a, 0x3a, 0x27, 0x6d, 0x99,
+ 0x17, 0x33, 0xb0, 0x80, 0x73, 0x3d, 0x35, 0xf6, 0xaf, 0x95, 0xf9, 0xc0,
+ 0x14, 0x31, 0x85, 0x69, 0x13, 0x7d, 0xde, 0x2b, 0xf4, 0x81, 0xf7, 0xba,
+ 0x7c, 0x40, 0xe9, 0xbc, 0x56, 0xa5, 0xa3, 0x36, 0xc2, 0x6f, 0xf2, 0x9d,
+ 0xfd, 0xe2, 0x9d, 0xdd, 0x4a, 0x67, 0xe9, 0xdc, 0xf7, 0x71, 0x63, 0xba,
+ 0x08, 0x5f, 0x9b, 0xe9, 0x52, 0x87, 0xdf, 0xac, 0x4d, 0xe8, 0xf8, 0xb9,
+ 0x3a, 0x3a, 0x56, 0xcb, 0x03, 0xfb, 0xe6, 0x65, 0x9d, 0x2d, 0x69, 0x26,
+ 0xcf, 0x23, 0x9f, 0x5f, 0xe7, 0x65, 0x48, 0x9a, 0x95, 0xe5, 0xe7, 0x92,
+ 0x3b, 0x27, 0xa3, 0x42, 0xb3, 0xe9, 0x32, 0xcd, 0xf6, 0xfc, 0x3f, 0xa0,
+ 0xd9, 0x4d, 0x81, 0x79, 0x5f, 0x29, 0x22, 0xff, 0x6e, 0x58, 0xe4, 0x2e,
+ 0xac, 0xd2, 0x88, 0xb2, 0xff, 0xee, 0x1a, 0x28, 0xd0, 0x12, 0xba, 0x34,
+ 0x52, 0x58, 0xa7, 0x98, 0x8c, 0x43, 0x98, 0xa5, 0xd2, 0x77, 0xa2, 0x90,
+ 0x3f, 0xf8, 0x24, 0xf0, 0x51, 0x10, 0xdf, 0x3b, 0xc9, 0x63, 0xfb, 0x97,
+ 0x60, 0xd7, 0x06, 0x36, 0xf2, 0xe4, 0x36, 0x7c, 0x94, 0x8a, 0x8d, 0x04,
+ 0x5e, 0x22, 0x27, 0x6e, 0x57, 0xf2, 0x5e, 0x66, 0xb3, 0x3f, 0x6c, 0x67,
+ 0x3f, 0x92, 0x69, 0x5c, 0x79, 0xee, 0xd6, 0x7c, 0x14, 0x3c, 0x4f, 0xda,
+ 0xc9, 0xd9, 0x6c, 0xe5, 0xb9, 0x4e, 0xf9, 0xb9, 0x61, 0x0f, 0x5d, 0x65,
+ 0xd1, 0xcc, 0xa5, 0x7d, 0x75, 0xf9, 0x6a, 0x95, 0xf1, 0x48, 0x5f, 0x45,
+ 0x8f, 0xe7, 0xc9, 0x4d, 0xf1, 0xa5, 0xcc, 0x3b, 0xab, 0xe4, 0xf0, 0xd4,
+ 0xfa, 0x29, 0xfb, 0x5d, 0xf1, 0x19, 0xd0, 0xf8, 0x0f, 0x69, 0x75, 0x12,
+ 0x7a, 0xae, 0x96, 0xd6, 0xef, 0xff, 0x9a, 0x68, 0x1d, 0xe9, 0xf8, 0xf5,
+ 0xd2, 0x7a, 0x7f, 0x5d, 0x2c, 0xbc, 0x32, 0x1e, 0x0a, 0x75, 0x6f, 0x0b,
+ 0xcb, 0xd7, 0xd2, 0x7a, 0x7f, 0xc3, 0x78, 0x6a, 0xe3, 0x5c, 0xcc, 0xea,
+ 0x78, 0x6a, 0xbf, 0xc1, 0x32, 0x92, 0x65, 0x79, 0x69, 0xa8, 0xe3, 0xff,
+ 0xce, 0x15, 0x6f, 0x75, 0xeb, 0x79, 0xc8, 0x1a, 0xf9, 0x4e, 0x0e, 0xe9,
+ 0x77, 0x42, 0xae, 0x22, 0x8e, 0x43, 0xf0, 0x9f, 0xf0, 0x5e, 0xe4, 0x62,
+ 0xd5, 0xe1, 0x2e, 0x7e, 0x2f, 0xcb, 0xff, 0x0b, 0xcf, 0x0b, 0x9b, 0x25,
+ 0x63, 0x12, 0x68, 0x1f, 0xf2, 0x9d, 0x11, 0x6d, 0x65, 0x8e, 0x96, 0x8a,
+ 0x51, 0x28, 0x3f, 0xa0, 0x51, 0x6c, 0xa2, 0xde, 0xfe, 0x6d, 0xcf, 0x6f,
+ 0xd0, 0xf1, 0x88, 0x83, 0x3c, 0x3f, 0xe1, 0x2a, 0xbf, 0x0b, 0xfa, 0xf4,
+ 0x3c, 0x63, 0x84, 0xfe, 0x32, 0x3e, 0xa8, 0x9e, 0xa3, 0x59, 0xe1, 0xdf,
+ 0x69, 0x5d, 0xba, 0x2a, 0x73, 0x6b, 0xc5, 0x79, 0xe0, 0xb5, 0xb2, 0x2e,
+ 0xad, 0xc1, 0xc3, 0x07, 0x3d, 0xf8, 0xc3, 0xb3, 0x9e, 0x55, 0xcf, 0xa1,
+ 0x85, 0x9c, 0xfa, 0x84, 0xe7, 0x1c, 0x96, 0xeb, 0xd2, 0x9c, 0x4a, 0x5b,
+ 0x79, 0x7f, 0x42, 0x8c, 0x6b, 0xea, 0xde, 0x38, 0xea, 0xef, 0xca, 0x35,
+ 0x51, 0xb5, 0x75, 0x60, 0xb0, 0x0b, 0x5a, 0x1e, 0x75, 0xcd, 0x39, 0x68,
+ 0xd1, 0xe7, 0x51, 0x07, 0xe6, 0xb6, 0x2d, 0xb8, 0xaf, 0x96, 0x16, 0x15,
+ 0xbb, 0x32, 0xa7, 0xec, 0xca, 0xa2, 0x4b, 0xaf, 0xd7, 0xe3, 0xf7, 0x2e,
+ 0x0f, 0xfc, 0xee, 0x55, 0x0b, 0x86, 0x3e, 0x3d, 0xc5, 0x98, 0xe4, 0x33,
+ 0xc0, 0x24, 0x26, 0x6a, 0xb1, 0x24, 0x2e, 0xc1, 0xf5, 0x1c, 0x63, 0x93,
+ 0x30, 0xf3, 0xca, 0x6b, 0x74, 0x8e, 0x31, 0xf7, 0x35, 0xba, 0x4b, 0xf9,
+ 0x69, 0x90, 0x5f, 0x9d, 0x47, 0x8b, 0x5a, 0x06, 0x1f, 0x39, 0x0f, 0x45,
+ 0x86, 0x63, 0xf4, 0x1a, 0x9d, 0x15, 0xf9, 0x3e, 0x58, 0xff, 0x43, 0x9e,
+ 0xc4, 0xdd, 0xe2, 0xfd, 0x32, 0xae, 0x71, 0x27, 0xf2, 0x02, 0xb7, 0x5e,
+ 0x9f, 0xa0, 0xea, 0x05, 0xb9, 0x1d, 0xde, 0xb9, 0xac, 0x64, 0x4a, 0x9c,
+ 0xe3, 0xfb, 0x9f, 0x32, 0xea, 0xef, 0x8f, 0x19, 0x89, 0x62, 0xc2, 0x88,
+ 0x2f, 0xa1, 0xdd, 0x53, 0xc6, 0x44, 0x11, 0xbe, 0xa4, 0xe6, 0x91, 0x48,
+ 0x14, 0xf2, 0xb6, 0x46, 0x9b, 0xaf, 0x53, 0x2c, 0x52, 0x4d, 0xad, 0xc8,
+ 0x16, 0xfa, 0x7d, 0xac, 0xaa, 0xdf, 0x9a, 0xbe, 0xf8, 0x8e, 0xd8, 0xcf,
+ 0xcb, 0x4c, 0x53, 0x8d, 0x71, 0x83, 0x88, 0xbd, 0x0f, 0x3b, 0xb4, 0x11,
+ 0xc6, 0x8d, 0xd4, 0x61, 0xdc, 0xc5, 0x4d, 0xfb, 0xfd, 0x69, 0x65, 0x5c,
+ 0xd6, 0x7c, 0xfb, 0x6d, 0x81, 0x65, 0xb9, 0xdf, 0x55, 0x38, 0xb7, 0x86,
+ 0xa7, 0xd0, 0x46, 0xc7, 0xc8, 0x75, 0x4c, 0xac, 0x5d, 0xc5, 0x74, 0x75,
+ 0x3e, 0x45, 0x50, 0xc5, 0xb4, 0x71, 0x1d, 0xbe, 0xd6, 0x2a, 0xf7, 0x0f,
+ 0x7e, 0x17, 0xe2, 0x3f, 0x6e, 0xbf, 0xcb, 0x1d, 0xf3, 0xf5, 0xaa, 0x0d,
+ 0xed, 0xf7, 0xa8, 0x0d, 0x75, 0xcb, 0x59, 0xc0, 0x25, 0x67, 0x61, 0x17,
+ 0x86, 0xeb, 0x65, 0xff, 0xa5, 0x8d, 0xf5, 0x07, 0xfc, 0x97, 0x20, 0xf9,
+ 0x2f, 0xbb, 0xfd, 0x97, 0xda, 0x3a, 0x7f, 0xc8, 0x1c, 0x70, 0x9a, 0xf4,
+ 0x65, 0x12, 0xf9, 0xf2, 0x1e, 0x01, 0x3c, 0xe6, 0x4a, 0x1d, 0xe6, 0x52,
+ 0x5d, 0xcd, 0xa8, 0x57, 0x7f, 0xfb, 0xea, 0xfa, 0x0b, 0x1b, 0x16, 0x6b,
+ 0x88, 0xef, 0xbc, 0xfc, 0xab, 0x3b, 0xd5, 0xbf, 0x5a, 0x5d, 0x86, 0x77,
+ 0xf5, 0x8b, 0x18, 0xb8, 0x53, 0xd6, 0x63, 0x63, 0xb2, 0xbf, 0xd9, 0x6a,
+ 0x5f, 0xc3, 0x7f, 0x89, 0x14, 0xed, 0xbc, 0xf5, 0xfa, 0xf6, 0xe2, 0x68,
+ 0x3b, 0x6b, 0x6c, 0xef, 0x78, 0xa7, 0x8c, 0x8f, 0xcd, 0xa9, 0x3c, 0xf2,
+ 0x6e, 0xe5, 0xf7, 0x6d, 0xc6, 0xeb, 0x38, 0x37, 0xa7, 0x62, 0x8a, 0x11,
+ 0xab, 0x40, 0xe0, 0xf1, 0xc9, 0xd3, 0x4d, 0xb6, 0xa9, 0xd6, 0xb8, 0xb0,
+ 0x8e, 0x05, 0x9e, 0xd7, 0xcf, 0x97, 0x35, 0x65, 0x9b, 0xcf, 0x99, 0x55,
+ 0x37, 0x67, 0x92, 0xaf, 0xe0, 0x6f, 0x21, 0x3f, 0x7a, 0xa4, 0x26, 0x47,
+ 0xfd, 0xd3, 0xd0, 0xa2, 0xdd, 0x23, 0x6f, 0x1b, 0x79, 0xd7, 0x8d, 0xfa,
+ 0xb9, 0xee, 0xc2, 0xea, 0xb2, 0x6e, 0x63, 0x95, 0xd0, 0xef, 0x52, 0xe9,
+ 0xe5, 0x28, 0xb0, 0x69, 0x6f, 0x1d, 0xaf, 0x69, 0xbc, 0x64, 0xba, 0xfa,
+ 0xf9, 0xf8, 0xc6, 0xfd, 0xac, 0xb1, 0xbf, 0x7b, 0x3d, 0xec, 0x6f, 0x23,
+ 0x5f, 0x42, 0xec, 0x9d, 0xe2, 0x3b, 0x2a, 0x74, 0x41, 0x1b, 0x2d, 0xe5,
+ 0x91, 0x4b, 0xfe, 0x1b, 0xa8, 0x67, 0x65, 0x7d, 0xeb, 0xaa, 0xcf, 0xf3,
+ 0x9e, 0xd3, 0xf2, 0x7a, 0x4b, 0x60, 0x1c, 0xeb, 0x83, 0xc8, 0x41, 0xe9,
+ 0x62, 0x1d, 0x84, 0xf6, 0x83, 0xd6, 0x0d, 0xc4, 0x80, 0x55, 0x3c, 0x2a,
+ 0xa1, 0xec, 0xcc, 0xd1, 0x2d, 0xac, 0xbb, 0x6c, 0x4f, 0x5f, 0x47, 0xac,
+ 0x55, 0xc2, 0x9a, 0x10, 0xf2, 0x9e, 0x9d, 0x76, 0x6a, 0xbf, 0xbf, 0xa5,
+ 0xc5, 0xbe, 0xd9, 0x29, 0xd7, 0xaa, 0x70, 0xad, 0x8d, 0xae, 0xe6, 0x91,
+ 0x97, 0x8e, 0x6b, 0x0f, 0xf2, 0x35, 0x2f, 0x7d, 0xf5, 0xb6, 0xe2, 0x25,
+ 0x60, 0x3a, 0x39, 0x47, 0x05, 0x92, 0x73, 0xb6, 0x4e, 0xf0, 0xa5, 0x4a,
+ 0xf4, 0x4f, 0xd1, 0xdf, 0x14, 0xfe, 0x5f, 0x65, 0xae, 0xb6, 0xb7, 0x8e,
+ 0x53, 0x9b, 0x03, 0x31, 0xb9, 0x61, 0x1c, 0xb1, 0xa3, 0x6b, 0xab, 0xeb,
+ 0x38, 0xb5, 0x39, 0x10, 0x8f, 0x6f, 0x29, 0x8e, 0x18, 0xb1, 0xa6, 0x37,
+ 0xac, 0x33, 0x70, 0xaf, 0xa9, 0xe8, 0xb5, 0xe4, 0x51, 0x51, 0x7b, 0xeb,
+ 0xe6, 0x89, 0x3b, 0xb3, 0x9e, 0x0c, 0xde, 0xe8, 0xab, 0xd3, 0x61, 0x77,
+ 0x60, 0x3d, 0xa0, 0x86, 0xb6, 0x41, 0xcf, 0x58, 0x96, 0xf7, 0xba, 0x31,
+ 0x72, 0x04, 0x10, 0xc3, 0x2e, 0xd2, 0x99, 0x2b, 0xe0, 0x67, 0x83, 0x39,
+ 0x6f, 0x80, 0x32, 0x21, 0xd4, 0x52, 0x89, 0xba, 0x28, 0xbd, 0xbe, 0x28,
+ 0xea, 0xa3, 0xce, 0x88, 0xba, 0xcf, 0xc1, 0xf0, 0x6d, 0xb6, 0x91, 0x67,
+ 0x8a, 0x6f, 0xd1, 0xd9, 0xa5, 0x20, 0xff, 0x57, 0xf0, 0x7c, 0x7d, 0xed,
+ 0x67, 0x35, 0xbf, 0xdf, 0x16, 0xfc, 0xde, 0xbb, 0x21, 0xbf, 0x1f, 0x2f,
+ 0xf3, 0x3b, 0x77, 0x28, 0x28, 0x6b, 0x2b, 0x53, 0x57, 0xda, 0xe9, 0xa8,
+ 0x78, 0xee, 0x5b, 0xfc, 0x7d, 0x27, 0x1d, 0x35, 0xe5, 0xf7, 0xb3, 0x4b,
+ 0xac, 0xfb, 0xb3, 0x6f, 0xd1, 0xb9, 0x2b, 0x8e, 0x2f, 0x21, 0xea, 0x32,
+ 0xdc, 0x7b, 0x86, 0xe8, 0xfb, 0xd1, 0xce, 0x4b, 0x16, 0xea, 0xf5, 0x55,
+ 0x41, 0xea, 0x2b, 0xba, 0x29, 0x62, 0x20, 0xde, 0xfa, 0x0a, 0xfc, 0x79,
+ 0x5e, 0xd9, 0xc6, 0xc9, 0x0d, 0x62, 0x1f, 0xf5, 0xbc, 0xd9, 0xe9, 0x81,
+ 0x91, 0xbf, 0xdb, 0x25, 0xd7, 0xb1, 0x36, 0x8a, 0x81, 0x54, 0xe5, 0x81,
+ 0xb8, 0xd7, 0xf9, 0xd9, 0x1e, 0x4c, 0xaa, 0x75, 0xf7, 0x9f, 0x76, 0x49,
+ 0x3b, 0x82, 0x9a, 0xc8, 0x55, 0xa6, 0xc3, 0x3f, 0x30, 0x7e, 0xd9, 0x4f,
+ 0xcd, 0x97, 0xf5, 0x58, 0xf7, 0x0b, 0x7f, 0xc8, 0x1d, 0xcb, 0x99, 0x55,
+ 0x35, 0xee, 0x69, 0xd7, 0x98, 0x66, 0x85, 0xdf, 0xf3, 0x49, 0xd6, 0x31,
+ 0x7b, 0x6b, 0x6c, 0x45, 0x2d, 0xbf, 0x61, 0x3f, 0x16, 0xcc, 0x2f, 0x19,
+ 0x12, 0x1b, 0x8f, 0x31, 0xe6, 0xdd, 0xee, 0x7a, 0xd2, 0xa7, 0xc5, 0x8d,
+ 0xb5, 0x7b, 0x7d, 0xd4, 0x7e, 0xc7, 0x3c, 0x48, 0x3f, 0x24, 0xf5, 0x42,
+ 0x51, 0xe8, 0x82, 0xd9, 0x91, 0x12, 0x4d, 0x44, 0x77, 0x51, 0x6a, 0x84,
+ 0xdf, 0x3d, 0x66, 0xb3, 0x3f, 0xe6, 0x27, 0x87, 0xe5, 0x37, 0x35, 0xb2,
+ 0x43, 0xd5, 0xcc, 0xe9, 0x58, 0x7b, 0x8b, 0xc2, 0x90, 0xed, 0x62, 0xdd,
+ 0x52, 0xee, 0x49, 0xc4, 0xdf, 0x97, 0xf4, 0xb3, 0x71, 0x1e, 0xbc, 0xdb,
+ 0xac, 0xda, 0x5d, 0x74, 0xb5, 0x43, 0x9b, 0x8b, 0xaa, 0x2d, 0x9e, 0xa9,
+ 0xb1, 0x86, 0xae, 0xd3, 0x82, 0x1c, 0xae, 0xaa, 0xfa, 0x44, 0xf9, 0xbc,
+ 0x99, 0xe2, 0x45, 0x6e, 0xd3, 0xa5, 0xae, 0x5f, 0x64, 0xfc, 0x5b, 0x14,
+ 0x32, 0x22, 0xfb, 0xd2, 0x54, 0xee, 0x8b, 0xc4, 0xed, 0xb8, 0xa7, 0x5d,
+ 0xe5, 0x62, 0xbe, 0x25, 0xd7, 0x05, 0x54, 0x1f, 0xe4, 0x75, 0xfe, 0x5c,
+ 0xaa, 0xf6, 0x29, 0xdf, 0x28, 0xea, 0x75, 0x88, 0x8f, 0x7d, 0x33, 0xd9,
+ 0x77, 0x7c, 0x32, 0xe7, 0xd8, 0x14, 0x6b, 0xa9, 0x32, 0x7f, 0x43, 0x7f,
+ 0x47, 0xac, 0x19, 0x39, 0x16, 0xc8, 0x9f, 0x70, 0xeb, 0x16, 0x39, 0xb6,
+ 0x00, 0x6c, 0x50, 0x11, 0x6b, 0xa8, 0x1b, 0xe1, 0xe7, 0xbd, 0xcc, 0x9b,
+ 0xe6, 0x36, 0x70, 0xe8, 0x56, 0x64, 0xcd, 0xf2, 0x90, 0x35, 0xf7, 0xfb,
+ 0x51, 0xcb, 0x87, 0x9a, 0x3e, 0x67, 0xd8, 0xa0, 0x12, 0xfb, 0x0a, 0x06,
+ 0x15, 0x4c, 0x1f, 0x9d, 0xb3, 0x23, 0xd1, 0x25, 0x81, 0x37, 0xef, 0x43,
+ 0xce, 0xcf, 0xf0, 0x2a, 0x1d, 0x36, 0xcf, 0x92, 0xdc, 0xef, 0xa1, 0xc0,
+ 0xb6, 0x77, 0x9a, 0xf9, 0xed, 0x2c, 0xfb, 0x1f, 0xce, 0x14, 0xd6, 0x5d,
+ 0x34, 0xcd, 0xb0, 0x0f, 0x00, 0x3e, 0x2d, 0x9e, 0xa7, 0xe2, 0x6e, 0x0a,
+ 0xc6, 0xf8, 0x99, 0x16, 0x74, 0x11, 0x3f, 0x27, 0x49, 0x71, 0xf6, 0x93,
+ 0xe0, 0xb3, 0x4e, 0x4f, 0x45, 0xcc, 0x02, 0x19, 0xdc, 0x16, 0xbe, 0x2b,
+ 0x9e, 0x83, 0xfb, 0x63, 0x66, 0x13, 0xd5, 0xd6, 0x1c, 0xb7, 0x8b, 0x3a,
+ 0xcc, 0x9b, 0xd1, 0x7b, 0xc8, 0xe8, 0x81, 0x6e, 0xc2, 0x9c, 0xdd, 0xad,
+ 0xd6, 0x8b, 0x3a, 0xf8, 0xfb, 0x90, 0xfa, 0x2e, 0xe7, 0x5a, 0x7e, 0xd7,
+ 0xbc, 0x8c, 0xbf, 0x0f, 0x5b, 0xc8, 0xfe, 0x5d, 0x35, 0x7f, 0xd5, 0xeb,
+ 0x66, 0xfd, 0x46, 0x90, 0xce, 0x7b, 0xae, 0x9b, 0x6d, 0x54, 0xcb, 0xdb,
+ 0xb1, 0xc5, 0x5a, 0xde, 0x9f, 0xef, 0x96, 0xf5, 0x71, 0xee, 0xbe, 0xfc,
+ 0x9c, 0xfb, 0xe2, 0x15, 0x0f, 0x71, 0xeb, 0x5e, 0xad, 0x73, 0x4b, 0xf4,
+ 0x6f, 0xd1, 0xcf, 0xd2, 0x7a, 0x28, 0xac, 0xf2, 0x99, 0x90, 0xbf, 0x74,
+ 0x8f, 0xe2, 0x55, 0xad, 0xe7, 0xc9, 0x43, 0xcf, 0x3f, 0x20, 0xf2, 0x8e,
+ 0xa5, 0x9d, 0xd8, 0xaf, 0xe8, 0x01, 0x9a, 0x85, 0x5d, 0x34, 0xeb, 0x76,
+ 0xd1, 0xcc, 0x50, 0xdf, 0x77, 0x89, 0xe3, 0xf3, 0x4b, 0xaf, 0x76, 0xc8,
+ 0x7a, 0x78, 0xac, 0x29, 0x7e, 0x5f, 0x7d, 0xdf, 0x6c, 0xbc, 0x0f, 0x84,
+ 0x28, 0x28, 0xe2, 0x4d, 0xae, 0xb1, 0xbe, 0x44, 0x64, 0xb3, 0x37, 0x5c,
+ 0x47, 0x83, 0x6f, 0xb9, 0xce, 0xa3, 0x8f, 0x83, 0xae, 0x3e, 0xf6, 0xbb,
+ 0xfa, 0x78, 0xb0, 0x41, 0x1f, 0x59, 0x9f, 0xf3, 0x7b, 0xce, 0x16, 0x3f,
+ 0x69, 0x5f, 0xd1, 0x4f, 0xd4, 0x49, 0x83, 0x9e, 0x3b, 0x29, 0x1d, 0x0a,
+ 0x2b, 0x3b, 0x11, 0x55, 0xf5, 0x03, 0x5e, 0x7d, 0xfe, 0x31, 0x35, 0x9e,
+ 0x37, 0x37, 0xaf, 0xba, 0xeb, 0xab, 0x9f, 0xa3, 0x09, 0x59, 0x27, 0xaf,
+ 0x64, 0xfb, 0x62, 0x83, 0x78, 0x34, 0x72, 0x3b, 0x80, 0x37, 0x84, 0x6f,
+ 0xb8, 0x4f, 0xee, 0x6f, 0x17, 0xa0, 0xe5, 0x72, 0xad, 0xb2, 0x5f, 0xd5,
+ 0xf0, 0x3d, 0x1b, 0xba, 0xb3, 0x75, 0xca, 0x38, 0xff, 0x3d, 0x11, 0xcb,
+ 0x93, 0xeb, 0x48, 0xab, 0xaa, 0xde, 0x3a, 0x62, 0x21, 0x47, 0x60, 0x71,
+ 0x05, 0x71, 0xd8, 0x46, 0xb5, 0xc9, 0x52, 0x17, 0xa5, 0xca, 0x7b, 0xc2,
+ 0x14, 0x44, 0x1d, 0x86, 0x8c, 0x8f, 0xc9, 0x1a, 0xe2, 0xc5, 0x95, 0x1b,
+ 0xa2, 0x6e, 0x37, 0xae, 0x6a, 0x91, 0x53, 0xd4, 0x26, 0x70, 0xed, 0x27,
+ 0xaf, 0x21, 0xfe, 0x71, 0x68, 0xfb, 0x35, 0xc4, 0xee, 0x7b, 0xb6, 0x57,
+ 0x43, 0x6c, 0xf2, 0xd8, 0x8d, 0x05, 0x59, 0x43, 0x5c, 0xbd, 0x46, 0x23,
+ 0x6b, 0x88, 0x53, 0x2e, 0xac, 0x20, 0xf1, 0xf9, 0x4d, 0x57, 0x7e, 0xb7,
+ 0xac, 0x0f, 0x5e, 0x2c, 0xe3, 0x53, 0x59, 0x1f, 0x2c, 0xf3, 0xc1, 0xdd,
+ 0x7b, 0xdf, 0xc8, 0xb5, 0x20, 0xf9, 0x9e, 0x5d, 0x35, 0x6b, 0x41, 0xb2,
+ 0x2e, 0xd8, 0x32, 0xbc, 0xf8, 0x4e, 0xdb, 0x25, 0xec, 0xf7, 0x10, 0x63,
+ 0xde, 0xdd, 0xd9, 0x60, 0xbf, 0x87, 0x58, 0x83, 0xfd, 0x1e, 0xdc, 0xba,
+ 0xdf, 0x8d, 0xa7, 0x80, 0x7f, 0x61, 0x17, 0x81, 0x7b, 0xb1, 0x5f, 0x43,
+ 0x94, 0xce, 0x97, 0x71, 0xe6, 0x3d, 0x94, 0x54, 0x38, 0xf3, 0xfc, 0x92,
+ 0xd6, 0x47, 0xfd, 0x35, 0xfa, 0xc8, 0x0b, 0x77, 0x46, 0x54, 0xce, 0x8f,
+ 0x96, 0x57, 0xc7, 0x25, 0xaf, 0x8e, 0x87, 0xbc, 0xe2, 0x1e, 0xa7, 0x41,
+ 0xbf, 0x41, 0x13, 0xdc, 0x83, 0xff, 0x97, 0xc2, 0xd8, 0xa7, 0x86, 0xe8,
+ 0x0b, 0xdd, 0x0a, 0xeb, 0xb9, 0xe4, 0xf5, 0x2c, 0xcb, 0xab, 0x3e, 0x8f,
+ 0xfe, 0x36, 0xc2, 0xfb, 0x1a, 0x1f, 0xee, 0xf7, 0x1d, 0xbb, 0xf2, 0x0b,
+ 0x91, 0x17, 0x50, 0xed, 0x27, 0x6a, 0x0c, 0x71, 0x48, 0xc8, 0xd2, 0xba,
+ 0x1f, 0xf9, 0x2b, 0xfa, 0x1c, 0x6a, 0xa7, 0x20, 0x7f, 0x9a, 0x16, 0xcd,
+ 0x35, 0x38, 0xa3, 0x5d, 0xe1, 0x08, 0x91, 0xff, 0xeb, 0xea, 0xdb, 0x7f,
+ 0x72, 0xdf, 0xf4, 0x79, 0x6d, 0x33, 0xdf, 0xae, 0x8a, 0x69, 0x54, 0xe7,
+ 0x4d, 0x22, 0x7e, 0xb4, 0x2b, 0x69, 0xd8, 0x09, 0x91, 0x7f, 0xda, 0x69,
+ 0x23, 0x56, 0x16, 0x67, 0xd9, 0xef, 0x4c, 0x22, 0xd7, 0xb9, 0xf3, 0x92,
+ 0x45, 0xa7, 0xb2, 0x57, 0x0f, 0x48, 0x5e, 0x79, 0x5a, 0xec, 0xd3, 0x89,
+ 0x7d, 0x1d, 0x27, 0xd8, 0x3e, 0xc7, 0x19, 0x60, 0xce, 0x15, 0x5b, 0x68,
+ 0x91, 0x91, 0xbc, 0xdf, 0x2e, 0x88, 0x58, 0x1f, 0xeb, 0xa4, 0x1c, 0xf6,
+ 0x6b, 0x35, 0x16, 0x9a, 0xf9, 0xb9, 0x3d, 0xb4, 0x9c, 0x07, 0xcf, 0x35,
+ 0xa9, 0xfd, 0x53, 0xd0, 0xd6, 0x47, 0x5d, 0xf6, 0xdf, 0x32, 0xed, 0x1e,
+ 0x11, 0x79, 0x97, 0x8b, 0xb9, 0xa7, 0xe5, 0x67, 0xe1, 0x55, 0xf5, 0x0e,
+ 0x7e, 0x5f, 0xf1, 0x75, 0x8a, 0x75, 0xb9, 0xf3, 0x00, 0xdd, 0x7f, 0xde,
+ 0x78, 0xe5, 0xe4, 0xb6, 0xf0, 0x8a, 0x93, 0xac, 0xe0, 0x15, 0xf7, 0xb3,
+ 0x35, 0x76, 0xf9, 0xe3, 0x1e, 0xb9, 0x9f, 0x05, 0x68, 0xb0, 0x13, 0x58,
+ 0x2c, 0x09, 0x5a, 0x1a, 0xe3, 0x91, 0x70, 0xdc, 0x3f, 0x46, 0x99, 0xe2,
+ 0x35, 0x4a, 0xe5, 0x60, 0xe7, 0xf9, 0xb3, 0xf0, 0x37, 0x7b, 0x64, 0x9c,
+ 0x46, 0xdf, 0x03, 0xbd, 0xb2, 0x9b, 0xdb, 0x37, 0xef, 0x91, 0x39, 0xdb,
+ 0xee, 0xf3, 0xed, 0x7c, 0xfe, 0xc9, 0x70, 0xf5, 0xf9, 0x1d, 0x7c, 0xbe,
+ 0x2b, 0x89, 0x39, 0x34, 0x2e, 0x21, 0x36, 0x39, 0x4c, 0x69, 0x9e, 0x9f,
+ 0x4c, 0x91, 0x6d, 0xeb, 0x65, 0xd6, 0x57, 0x4b, 0xba, 0x5d, 0x37, 0xb7,
+ 0x0b, 0x89, 0x39, 0x31, 0xb8, 0xcd, 0x6c, 0x76, 0x84, 0xdb, 0xed, 0x27,
+ 0xff, 0x65, 0x8b, 0x32, 0x4b, 0x9a, 0x57, 0x75, 0x2e, 0xfe, 0x2f, 0xba,
+ 0x65, 0x6e, 0xd5, 0xae, 0xb0, 0xa4, 0xdf, 0xb0, 0x88, 0x7b, 0x22, 0xb7,
+ 0xe3, 0x19, 0xc1, 0x87, 0x91, 0x31, 0xab, 0xfc, 0x7e, 0xec, 0x31, 0x26,
+ 0xf6, 0x7c, 0xe5, 0x31, 0xb0, 0x5e, 0x1c, 0xb7, 0xcd, 0x74, 0x39, 0x6f,
+ 0x6d, 0x6d, 0x9f, 0xbc, 0x7f, 0x67, 0x8f, 0xdc, 0x7f, 0xb5, 0x53, 0xed,
+ 0x15, 0xa8, 0x6d, 0xce, 0x17, 0x90, 0xa7, 0x2d, 0x68, 0xe3, 0x5f, 0x80,
+ 0xbe, 0x34, 0xf8, 0x3b, 0x8f, 0x27, 0x89, 0x3e, 0xf6, 0xf6, 0xe8, 0x3d,
+ 0x17, 0xe5, 0xb8, 0x4e, 0x70, 0x7f, 0x13, 0x3c, 0x2e, 0x7d, 0x3e, 0xc6,
+ 0xc7, 0x5e, 0xf3, 0x8b, 0x67, 0x05, 0xf9, 0x39, 0x2c, 0x03, 0x53, 0xc1,
+ 0x64, 0x6a, 0x58, 0xce, 0x73, 0x25, 0xae, 0x1b, 0x2e, 0xc7, 0x75, 0xe7,
+ 0xb2, 0xc7, 0x7b, 0x10, 0xcf, 0x30, 0x2e, 0xf1, 0x7c, 0x87, 0x9e, 0xe1,
+ 0xb6, 0xa8, 0x63, 0x48, 0xf3, 0x67, 0x9b, 0xca, 0xef, 0xa9, 0xe7, 0x15,
+ 0x99, 0x2f, 0xa1, 0xed, 0x16, 0xee, 0xbd, 0x97, 0x9f, 0x21, 0x6d, 0x57,
+ 0xe3, 0xf7, 0x50, 0x5d, 0x4e, 0x4c, 0x3d, 0x8f, 0x6d, 0x14, 0x8b, 0x15,
+ 0xeb, 0x8a, 0x1e, 0x7c, 0xb6, 0x51, 0xac, 0x44, 0xe4, 0x39, 0xfb, 0x26,
+ 0xea, 0xe4, 0x15, 0x72, 0x1c, 0xa0, 0x27, 0xe6, 0x1d, 0xda, 0xc1, 0x73,
+ 0xf5, 0x27, 0x06, 0xea, 0x86, 0x4b, 0x24, 0x73, 0x9f, 0x98, 0xc6, 0x59,
+ 0x7b, 0xf8, 0xac, 0xc1, 0x74, 0xce, 0x3a, 0xa5, 0x80, 0xdd, 0x46, 0xcd,
+ 0x2c, 0xab, 0xbf, 0x4f, 0x03, 0xec, 0xeb, 0x41, 0x66, 0xed, 0x70, 0x82,
+ 0x20, 0x6f, 0x11, 0xf3, 0x18, 0xf3, 0xc4, 0x44, 0x11, 0xfc, 0x6c, 0xd0,
+ 0x63, 0x79, 0xa2, 0x47, 0xf3, 0x03, 0xe6, 0x37, 0xc9, 0xb6, 0x2a, 0xd7,
+ 0x23, 0x66, 0x9c, 0xfb, 0x91, 0x28, 0xfe, 0x25, 0x7d, 0x24, 0xf6, 0x71,
+ 0x01, 0x1d, 0xf5, 0xbc, 0xff, 0x39, 0x4d, 0x27, 0xd1, 0xef, 0xad, 0xcb,
+ 0xe7, 0xa9, 0x6d, 0xc9, 0x67, 0xd0, 0x43, 0x3e, 0x3f, 0x54, 0x7c, 0x53,
+ 0x62, 0x1e, 0x0d, 0xd2, 0x4c, 0x0e, 0xb9, 0x60, 0x9f, 0x47, 0x0d, 0x66,
+ 0x2e, 0xc5, 0x7a, 0x29, 0x55, 0xd1, 0x4b, 0x17, 0xe2, 0xfe, 0x18, 0x64,
+ 0x1c, 0x7b, 0xd1, 0xa9, 0x1c, 0x20, 0x8c, 0x63, 0x1f, 0x0d, 0x2c, 0xec,
+ 0xe4, 0x7b, 0x69, 0x35, 0x3e, 0x1a, 0x53, 0x7b, 0x15, 0x44, 0xac, 0x09,
+ 0xd6, 0x8f, 0x73, 0x2c, 0xcb, 0xe9, 0xdc, 0xdd, 0xb4, 0x18, 0xea, 0xa5,
+ 0xfe, 0x05, 0xbd, 0x7f, 0x0b, 0xc6, 0x3a, 0xd4, 0x2b, 0x75, 0x92, 0x1e,
+ 0xf7, 0x6f, 0x89, 0x38, 0x85, 0x75, 0xed, 0x57, 0x35, 0xee, 0x9d, 0x9b,
+ 0xe8, 0xa5, 0x92, 0x92, 0xd9, 0xd2, 0x1b, 0xf1, 0x28, 0x39, 0xf1, 0xd1,
+ 0xff, 0x15, 0xfc, 0xdf, 0x7f, 0x0d, 0xb5, 0x38, 0xd0, 0xd1, 0x16, 0x25,
+ 0xb3, 0xb5, 0xb4, 0xe8, 0xe5, 0x71, 0xe3, 0x7a, 0xe9, 0xa7, 0x33, 0xd1,
+ 0x57, 0x85, 0xed, 0x1f, 0xb8, 0xc6, 0xed, 0x84, 0x6d, 0xd2, 0x7a, 0xc3,
+ 0x8b, 0x0f, 0xf5, 0xde, 0x9c, 0x9a, 0x17, 0x65, 0xce, 0x27, 0xe3, 0x37,
+ 0x33, 0xe9, 0xaf, 0xe5, 0xc9, 0x8f, 0xe9, 0xe4, 0xbc, 0x45, 0x93, 0x59,
+ 0xec, 0x81, 0x38, 0xc6, 0x72, 0xed, 0xb6, 0x17, 0xdc, 0x9e, 0xc0, 0x67,
+ 0xe3, 0x2c, 0xfb, 0xec, 0xb7, 0xe7, 0x2c, 0x99, 0x7f, 0x27, 0xf6, 0xdb,
+ 0x6b, 0x11, 0x7a, 0xd4, 0xb4, 0xfb, 0xf7, 0x68, 0x7b, 0x90, 0xca, 0xa1,
+ 0xce, 0x90, 0x3f, 0x0b, 0xdc, 0x3e, 0xdb, 0x43, 0xa9, 0x3c, 0x9e, 0x03,
+ 0x7b, 0x87, 0xbe, 0xf3, 0xf1, 0xb2, 0x9c, 0xd7, 0x7e, 0x7e, 0x36, 0xf6,
+ 0x0e, 0x98, 0x2c, 0x8e, 0x88, 0x1c, 0x3c, 0xe8, 0x66, 0x39, 0x9f, 0xe3,
+ 0x34, 0xeb, 0xa9, 0x57, 0x14, 0xa6, 0x74, 0xc9, 0x77, 0x4a, 0xc8, 0xf7,
+ 0xb8, 0x98, 0x8f, 0x54, 0xde, 0x60, 0xbc, 0xa6, 0xe3, 0x0c, 0x5d, 0x7c,
+ 0x1c, 0x50, 0x3a, 0x04, 0xd7, 0xee, 0xdd, 0x23, 0xf2, 0x13, 0x6d, 0x9c,
+ 0xc7, 0xe7, 0x38, 0x3d, 0xc3, 0xb8, 0xf3, 0xd9, 0x6c, 0x0b, 0xdd, 0xc8,
+ 0xb5, 0xd0, 0x9b, 0xb9, 0x5e, 0xba, 0x3e, 0xdf, 0x41, 0xb3, 0x8c, 0x99,
+ 0x67, 0xed, 0x80, 0x95, 0x66, 0xff, 0xe2, 0x6a, 0x54, 0xe4, 0x10, 0xb1,
+ 0xdc, 0xa1, 0x3d, 0xf0, 0x5f, 0x7c, 0x2f, 0xf3, 0x1c, 0x63, 0xef, 0x56,
+ 0xfa, 0x80, 0xdf, 0x99, 0xce, 0xea, 0x9c, 0x07, 0xc4, 0xe3, 0x07, 0xcb,
+ 0xf8, 0x75, 0x73, 0x1e, 0x31, 0x37, 0xe1, 0x91, 0x71, 0xa1, 0xeb, 0x33,
+ 0xf3, 0x7c, 0x7d, 0x1e, 0x71, 0x73, 0x4b, 0xc4, 0x24, 0xbe, 0x14, 0x40,
+ 0x7b, 0x9c, 0xb3, 0x65, 0xce, 0xa4, 0x18, 0x5b, 0x98, 0x8f, 0x41, 0xdb,
+ 0xb0, 0xa2, 0x43, 0x2b, 0x8f, 0x4f, 0xc6, 0x30, 0x52, 0xcb, 0xad, 0x74,
+ 0x26, 0xcf, 0x18, 0x24, 0xef, 0x67, 0x1f, 0x06, 0x6d, 0x7f, 0xe7, 0xa0,
+ 0xde, 0xd3, 0x76, 0x96, 0xfb, 0x9e, 0xce, 0x4b, 0x0c, 0x92, 0x5e, 0x6e,
+ 0xa7, 0x4c, 0xbe, 0x4d, 0x1d, 0xdf, 0x2d, 0xf2, 0xdd, 0xe5, 0xde, 0x12,
+ 0xb8, 0xb6, 0x91, 0x7e, 0x43, 0xae, 0x11, 0x6c, 0xaa, 0xf4, 0x4b, 0xa1,
+ 0x6b, 0xbc, 0xf3, 0x8c, 0xc6, 0xe8, 0x39, 0xb6, 0xb7, 0xfd, 0x97, 0x11,
+ 0x2b, 0xfe, 0x22, 0xf8, 0xa6, 0x00, 0x1e, 0xeb, 0xbf, 0x8c, 0x7d, 0x9f,
+ 0xfc, 0x22, 0xf7, 0x68, 0x22, 0x34, 0x2c, 0x6a, 0x46, 0xa4, 0x8c, 0x4e,
+ 0x89, 0xba, 0xec, 0xef, 0x08, 0xdd, 0x14, 0x71, 0x2c, 0x03, 0x78, 0x24,
+ 0x12, 0x26, 0x92, 0x39, 0x59, 0xa7, 0xec, 0xce, 0x9b, 0xdd, 0xe3, 0x43,
+ 0x14, 0xeb, 0x01, 0xdf, 0x4b, 0x99, 0x95, 0x7b, 0x22, 0x90, 0xd0, 0xf7,
+ 0xe6, 0x21, 0x5d, 0x63, 0xa0, 0x8f, 0xb5, 0xad, 0xd0, 0xc7, 0x6d, 0x35,
+ 0xd7, 0xcd, 0x9a, 0xeb, 0x1a, 0x7f, 0x63, 0xad, 0x8c, 0xed, 0x3c, 0xc9,
+ 0x3d, 0x98, 0x52, 0x0b, 0x92, 0xff, 0xcc, 0x43, 0x83, 0xe6, 0xfd, 0x0a,
+ 0x83, 0xa7, 0x56, 0x06, 0xc2, 0x9d, 0x46, 0x9b, 0x3f, 0x35, 0xf2, 0xaf,
+ 0xa5, 0x58, 0x12, 0xb8, 0xe8, 0xf5, 0x3d, 0x52, 0xc7, 0xa1, 0x5f, 0x4e,
+ 0x14, 0xd0, 0x6d, 0x6a, 0xa5, 0x8d, 0x56, 0xc5, 0x9e, 0x63, 0xc0, 0x18,
+ 0xb8, 0x1f, 0xcf, 0x71, 0xcc, 0x26, 0xc2, 0x3e, 0xf2, 0x90, 0xf1, 0xc3,
+ 0xe1, 0x6b, 0x3c, 0x9f, 0x89, 0x95, 0xff, 0x29, 0x4d, 0x8b, 0x7d, 0x7a,
+ 0xd0, 0x96, 0x31, 0xa4, 0xc0, 0xfc, 0x8c, 0x5f, 0xaa, 0xfc, 0xaa, 0x31,
+ 0xf4, 0xd3, 0xc1, 0x9a, 0x8a, 0x61, 0xbf, 0xc0, 0x32, 0x26, 0xd7, 0xca,
+ 0x13, 0x35, 0x6b, 0xe5, 0x53, 0x62, 0xad, 0x1c, 0xeb, 0xe4, 0x1b, 0xe5,
+ 0x2d, 0xea, 0x3c, 0x16, 0x8b, 0x66, 0xaf, 0x08, 0x7d, 0x13, 0x9d, 0xf0,
+ 0xcb, 0x3c, 0xeb, 0x04, 0xbb, 0x37, 0x86, 0xa8, 0x6d, 0xc0, 0x67, 0xcc,
+ 0x88, 0xdb, 0x91, 0xe1, 0x35, 0xc6, 0x14, 0x4b, 0xb9, 0x1d, 0x74, 0xbd,
+ 0xd0, 0xc4, 0x98, 0xef, 0x9f, 0x69, 0xad, 0x40, 0x8c, 0x0d, 0x3b, 0x28,
+ 0x13, 0x65, 0x5e, 0x1b, 0x0e, 0xf2, 0xbc, 0x32, 0xbe, 0x1d, 0x66, 0xf9,
+ 0xe3, 0x31, 0x2c, 0xe5, 0x4b, 0xef, 0xa7, 0xa3, 0x31, 0x2b, 0x3e, 0xda,
+ 0xc6, 0xfe, 0x8b, 0xc9, 0xff, 0x36, 0xff, 0x9f, 0x0b, 0x83, 0x36, 0x8b,
+ 0xcb, 0xb8, 0xce, 0xd8, 0x27, 0x5b, 0x7a, 0x7f, 0x86, 0xdb, 0xcc, 0x8c,
+ 0xc2, 0x0f, 0x82, 0xbf, 0x67, 0xf3, 0xbf, 0x6c, 0xb3, 0xc4, 0x7c, 0x97,
+ 0xbe, 0xe2, 0x84, 0x0d, 0xa1, 0xe3, 0xb1, 0x2f, 0xcd, 0x80, 0xfa, 0x8c,
+ 0x19, 0x33, 0xdc, 0x97, 0xeb, 0x84, 0x67, 0x58, 0x94, 0x8a, 0x1e, 0x62,
+ 0x39, 0xe8, 0xe0, 0x4f, 0xd4, 0x6a, 0xed, 0xa4, 0xcc, 0xc8, 0xa0, 0xaa,
+ 0xd5, 0xfa, 0x59, 0x83, 0x5a, 0x2d, 0xdc, 0xc7, 0x38, 0x60, 0xbe, 0x74,
+ 0x7b, 0x26, 0xea, 0x7e, 0x2f, 0x19, 0xa9, 0xe8, 0x2e, 0x81, 0x99, 0x96,
+ 0x96, 0x1f, 0xe6, 0x3e, 0xc4, 0xac, 0xd4, 0x28, 0xf7, 0x35, 0xef, 0xee,
+ 0x7f, 0xe9, 0xf6, 0x44, 0x14, 0xed, 0xfc, 0x35, 0xed, 0x62, 0x24, 0xda,
+ 0x2e, 0xa3, 0x7d, 0xe9, 0x97, 0xf1, 0xa8, 0x1e, 0xa7, 0xfb, 0x5e, 0x8c,
+ 0x07, 0xf2, 0xc5, 0x9f, 0x4b, 0xef, 0xd0, 0xf5, 0x1c, 0xfc, 0x71, 0x43,
+ 0xd5, 0x5f, 0x59, 0xe4, 0x2c, 0x31, 0x06, 0xbc, 0x72, 0xd0, 0xb7, 0x96,
+ 0xfb, 0x41, 0x29, 0x55, 0x95, 0xdb, 0x52, 0x1d, 0x73, 0x97, 0x3e, 0x58,
+ 0x2f, 0xd9, 0x97, 0x60, 0x43, 0x61, 0x3f, 0x9d, 0x92, 0xdf, 0x06, 0xde,
+ 0x83, 0x6f, 0xf4, 0x34, 0xeb, 0x2f, 0x99, 0x9f, 0xc4, 0xba, 0x94, 0x75,
+ 0x98, 0x94, 0x9f, 0x44, 0xd5, 0x4f, 0x3c, 0x48, 0x1e, 0xee, 0xaf, 0xe4,
+ 0x49, 0xba, 0xd6, 0xd8, 0x03, 0xae, 0x35, 0x76, 0xd3, 0x95, 0x27, 0x19,
+ 0x12, 0xf8, 0xac, 0x82, 0xa9, 0x42, 0x0a, 0x53, 0x01, 0x7b, 0x49, 0xdd,
+ 0xb6, 0x58, 0xd6, 0x6d, 0xbb, 0x37, 0xd1, 0x6d, 0x5e, 0xbe, 0xea, 0xaa,
+ 0xd2, 0x23, 0x91, 0x28, 0x6c, 0x0c, 0xf6, 0x59, 0xfa, 0xfb, 0xe2, 0x28,
+ 0xeb, 0x91, 0x28, 0xeb, 0x91, 0x11, 0xd6, 0x23, 0xc3, 0xac, 0x47, 0x6c,
+ 0xa6, 0x81, 0xc5, 0x63, 0xff, 0x98, 0xf5, 0x34, 0xec, 0xc7, 0x18, 0x3d,
+ 0x53, 0x84, 0x4e, 0x1e, 0x61, 0x0c, 0xf4, 0x31, 0xad, 0xcd, 0xb7, 0x33,
+ 0xff, 0x4a, 0xdc, 0x53, 0xed, 0xd7, 0x60, 0xdf, 0x18, 0xc4, 0x86, 0x7f,
+ 0x08, 0xbd, 0xf3, 0xb2, 0x43, 0x7d, 0xbe, 0xeb, 0x39, 0xd0, 0x79, 0x0d,
+ 0x7b, 0x6b, 0xbc, 0x08, 0xd9, 0xc6, 0xbe, 0xc7, 0xdf, 0x1e, 0x1a, 0xe3,
+ 0xbe, 0xf7, 0xf9, 0x32, 0x3c, 0x2f, 0x8f, 0x47, 0x1d, 0xb3, 0x8b, 0x65,
+ 0x60, 0x52, 0xc9, 0xc0, 0x64, 0x45, 0x06, 0x9c, 0x34, 0x8f, 0xa4, 0x73,
+ 0xa1, 0x83, 0x06, 0x8f, 0xc4, 0xf7, 0x76, 0xb2, 0xfc, 0x22, 0x67, 0xa2,
+ 0xb2, 0xff, 0x90, 0x9f, 0xa6, 0x43, 0x41, 0xb5, 0x6f, 0x91, 0xc5, 0x76,
+ 0xf3, 0x27, 0x94, 0xc9, 0xbd, 0xcb, 0xb8, 0x84, 0xe5, 0xd4, 0xc4, 0xf1,
+ 0x45, 0xc4, 0x45, 0xd9, 0x6f, 0x68, 0x15, 0x71, 0xa5, 0x45, 0xd1, 0x16,
+ 0xc7, 0x91, 0x61, 0xd6, 0x71, 0xd1, 0x55, 0x23, 0x32, 0x16, 0x33, 0x2e,
+ 0xf7, 0x62, 0x5f, 0xfa, 0x6f, 0x17, 0x1f, 0xeb, 0x95, 0xf5, 0xb9, 0x4f,
+ 0xed, 0x95, 0xfa, 0x84, 0x79, 0x34, 0x14, 0x13, 0xbe, 0x5b, 0xd3, 0x25,
+ 0x69, 0x3f, 0x17, 0x79, 0xbe, 0x97, 0xa2, 0xc3, 0x3c, 0xdf, 0x6d, 0xca,
+ 0x76, 0x3a, 0x7c, 0x5d, 0xd8, 0x65, 0xb6, 0xa1, 0xbd, 0xd8, 0xd3, 0xdf,
+ 0x8c, 0x47, 0x9f, 0xe2, 0x77, 0x62, 0x1f, 0xa1, 0x2f, 0xe3, 0x79, 0xcc,
+ 0xbd, 0xd0, 0x1f, 0x3f, 0x61, 0x1b, 0x8d, 0xf7, 0x82, 0x1f, 0xf9, 0x7b,
+ 0x61, 0x8c, 0x2e, 0x64, 0x75, 0x1f, 0xde, 0x23, 0xe3, 0x39, 0xf4, 0xc3,
+ 0x47, 0xbb, 0xed, 0xf7, 0x44, 0x4d, 0x88, 0xf1, 0x8d, 0xda, 0x3e, 0x7d,
+ 0x45, 0xf5, 0x09, 0x7b, 0x79, 0xb6, 0xf0, 0x18, 0x76, 0x13, 0xf6, 0x74,
+ 0x5a, 0x14, 0x7b, 0x6d, 0x36, 0x0b, 0x9f, 0x75, 0x51, 0xf8, 0x1e, 0x0f,
+ 0xef, 0xad, 0xec, 0xff, 0x79, 0x57, 0xcd, 0xb9, 0x75, 0xb6, 0x5b, 0x47,
+ 0x05, 0x46, 0xeb, 0xc7, 0x1e, 0xf4, 0xa2, 0x66, 0xf5, 0x4f, 0xc5, 0x35,
+ 0x63, 0x01, 0xd7, 0x3e, 0xa7, 0xae, 0x7d, 0x56, 0x60, 0x63, 0x63, 0xbc,
+ 0x95, 0xf5, 0xa2, 0xe0, 0x77, 0x9e, 0x67, 0x7b, 0x98, 0xf9, 0x3d, 0xbc,
+ 0xc4, 0xcf, 0x9d, 0x16, 0xf4, 0xd4, 0xf4, 0x00, 0x2d, 0x20, 0x03, 0x6d,
+ 0x8a, 0xff, 0x23, 0x56, 0xc2, 0xaf, 0xc7, 0xdd, 0x88, 0xce, 0x63, 0xb0,
+ 0xcf, 0x3c, 0x56, 0x8c, 0xc9, 0xf2, 0xc5, 0x0a, 0x61, 0x5f, 0x7a, 0x1e,
+ 0xbe, 0x0e, 0xea, 0x5e, 0x0e, 0x20, 0x9f, 0x8a, 0xfb, 0xb0, 0x87, 0x62,
+ 0x49, 0xf4, 0x0b, 0xed, 0x34, 0x0d, 0xfe, 0xa8, 0x86, 0x16, 0xee, 0xfb,
+ 0x3a, 0xd4, 0x7d, 0xad, 0x62, 0x2e, 0xc8, 0xc0, 0x7b, 0xf4, 0xbb, 0xf1,
+ 0x5e, 0xbc, 0x1f, 0xf7, 0xe1, 0x79, 0xf2, 0xb9, 0xdd, 0xac, 0xb7, 0xe3,
+ 0xa3, 0xf2, 0x59, 0xc6, 0x35, 0x79, 0xad, 0xdb, 0xf6, 0xee, 0xaf, 0x9c,
+ 0x3f, 0x9f, 0xda, 0x83, 0x08, 0xf3, 0xd7, 0x41, 0x05, 0x11, 0xfb, 0xc4,
+ 0xb5, 0x3e, 0x9f, 0xf0, 0x6b, 0x6d, 0xfe, 0xe4, 0x79, 0x9d, 0xe3, 0xe3,
+ 0x33, 0xb9, 0x77, 0x84, 0xcf, 0x9e, 0x4e, 0xf6, 0xf9, 0x0a, 0x05, 0x8c,
+ 0xb7, 0xcf, 0x97, 0x60, 0x19, 0x98, 0xc8, 0xc5, 0x4b, 0x19, 0xa1, 0x6b,
+ 0x18, 0xeb, 0x76, 0x45, 0xcc, 0x69, 0xa3, 0x47, 0x60, 0x3e, 0x7e, 0x1f,
+ 0x7f, 0x67, 0x39, 0xcc, 0xb2, 0x1c, 0x66, 0x59, 0x0e, 0xb3, 0x2c, 0x87,
+ 0xec, 0xab, 0x7e, 0x2b, 0xcb, 0x72, 0xc8, 0xb6, 0xe4, 0x15, 0xb6, 0x25,
+ 0x52, 0x76, 0x63, 0x2a, 0xbe, 0xa9, 0x65, 0x17, 0xeb, 0x7f, 0x6e, 0x1f,
+ 0x47, 0xcb, 0x2a, 0xec, 0x37, 0xf9, 0x8e, 0x0f, 0x55, 0xcb, 0xec, 0x0d,
+ 0x96, 0xd9, 0xa6, 0xf1, 0x1e, 0xba, 0x95, 0xc7, 0x9c, 0x45, 0xac, 0x39,
+ 0xd6, 0xd5, 0x09, 0x3f, 0xb0, 0x56, 0x80, 0xe5, 0x09, 0x58, 0x33, 0xc2,
+ 0x74, 0xef, 0xa1, 0xdb, 0xac, 0xaf, 0x6f, 0xe5, 0x21, 0xc3, 0x07, 0xd4,
+ 0x71, 0x84, 0x65, 0x18, 0xf6, 0xcf, 0xf6, 0xdd, 0xc8, 0x19, 0x8c, 0xc9,
+ 0x02, 0x66, 0x8a, 0xa0, 0x4f, 0x05, 0x4e, 0xe3, 0x79, 0x5f, 0x65, 0xbd,
+ 0x8f, 0x18, 0x1e, 0xec, 0xc5, 0x19, 0x1f, 0xdb, 0x8b, 0xf0, 0x75, 0xd6,
+ 0xa7, 0xe7, 0xf3, 0x36, 0xcb, 0x7d, 0x17, 0xfd, 0x59, 0x1e, 0x76, 0x1a,
+ 0x34, 0xe2, 0xe3, 0x02, 0x89, 0xd8, 0x98, 0x31, 0x8e, 0xb1, 0x0f, 0x3a,
+ 0x86, 0xe0, 0x93, 0xdb, 0x98, 0x23, 0xa6, 0xfd, 0x3b, 0x7b, 0xb1, 0x9f,
+ 0x7e, 0xcc, 0x68, 0x56, 0xb1, 0x46, 0x7c, 0x47, 0xfb, 0x1e, 0x85, 0x4d,
+ 0x71, 0xdc, 0x68, 0x0d, 0x12, 0xbf, 0x43, 0x11, 0x65, 0x7a, 0xd4, 0xea,
+ 0xaf, 0x0b, 0x7c, 0xbf, 0xa0, 0xd7, 0x58, 0xdc, 0x8f, 0xfa, 0x72, 0xfa,
+ 0xaa, 0x7f, 0x7c, 0x8c, 0x9e, 0x2d, 0xa2, 0xdf, 0x97, 0x29, 0x13, 0x82,
+ 0x3e, 0x8a, 0x44, 0xd7, 0x49, 0xd2, 0xae, 0x95, 0x71, 0xe7, 0x63, 0xde,
+ 0x3a, 0xce, 0x8a, 0x0b, 0x9c, 0xdc, 0xc2, 0xfa, 0x05, 0xb4, 0xf9, 0x3e,
+ 0xf3, 0x5a, 0x14, 0x75, 0x69, 0x4a, 0xbf, 0xbd, 0xce, 0x3a, 0x07, 0x73,
+ 0x86, 0xe3, 0x8d, 0x75, 0xda, 0x9a, 0xd2, 0x69, 0xb6, 0x4b, 0xa7, 0xa5,
+ 0xcb, 0x3a, 0x8d, 0x79, 0x43, 0xe8, 0xb2, 0xa0, 0xa8, 0x8d, 0x4e, 0xab,
+ 0xef, 0xc0, 0x87, 0xbb, 0x85, 0xee, 0x62, 0xdd, 0x3f, 0x84, 0x3d, 0xc8,
+ 0x1c, 0xdf, 0x31, 0xa1, 0x43, 0x34, 0x7f, 0x3f, 0xbc, 0x4f, 0xca, 0x45,
+ 0xab, 0xd0, 0x07, 0xe9, 0x29, 0xe8, 0x2d, 0xaf, 0xf6, 0x0f, 0x72, 0x3b,
+ 0xb4, 0xb7, 0xc3, 0x2f, 0xb2, 0x3e, 0x5b, 0x8c, 0xc2, 0xa7, 0x6d, 0x53,
+ 0xbe, 0x0f, 0xf6, 0x14, 0xc3, 0x5a, 0x17, 0xc6, 0xaa, 0xf5, 0x59, 0xb7,
+ 0x8a, 0x6b, 0x20, 0x0e, 0x89, 0x39, 0x6f, 0x88, 0x11, 0x2c, 0x60, 0x04,
+ 0xbe, 0x27, 0xc0, 0xf4, 0x82, 0x7e, 0x61, 0x3b, 0xf0, 0x2e, 0xad, 0x09,
+ 0xd9, 0x78, 0x57, 0x60, 0x97, 0x0c, 0x5f, 0x9b, 0x19, 0x7d, 0x54, 0xf4,
+ 0x33, 0xb3, 0x5c, 0xd1, 0x8f, 0x73, 0xd9, 0xf7, 0x60, 0x37, 0x44, 0x5f,
+ 0x97, 0x86, 0xa4, 0x0e, 0x5c, 0x2c, 0x98, 0xd8, 0xe3, 0x0c, 0x7d, 0xe6,
+ 0xbe, 0xea, 0x71, 0xa2, 0x1f, 0x5a, 0x1f, 0x6c, 0x45, 0xf6, 0x18, 0xd7,
+ 0x76, 0x61, 0x8e, 0x1c, 0x17, 0x0f, 0x7d, 0x8f, 0xdf, 0x8f, 0x73, 0x9b,
+ 0x8f, 0xe7, 0x76, 0x79, 0x3c, 0x88, 0xed, 0xe1, 0x9e, 0x77, 0xe9, 0x96,
+ 0x1a, 0xcf, 0xad, 0xf2, 0x78, 0xbe, 0xab, 0xc6, 0x43, 0x69, 0x63, 0xbc,
+ 0x5b, 0xe1, 0xfe, 0x2d, 0x3f, 0xbb, 0x35, 0xce, 0x38, 0x26, 0xbd, 0x0c,
+ 0x3a, 0xdf, 0xa5, 0xf8, 0xc9, 0x1d, 0x47, 0x75, 0xf7, 0x35, 0x32, 0xbc,
+ 0xce, 0xfa, 0xf7, 0xb6, 0xc0, 0x31, 0x7d, 0x8c, 0x63, 0x70, 0x9e, 0x32,
+ 0xd0, 0xd3, 0xe9, 0x10, 0xf6, 0xe1, 0x1d, 0xe3, 0x71, 0xb3, 0x3f, 0x36,
+ 0xca, 0x9f, 0x22, 0xbe, 0x26, 0xe2, 0xbe, 0xea, 0xfe, 0xaf, 0xd3, 0xed,
+ 0x79, 0xe8, 0x72, 0xe0, 0x58, 0xb9, 0x57, 0xef, 0xed, 0x15, 0x19, 0xdf,
+ 0x4d, 0x78, 0xc6, 0x77, 0x11, 0xdb, 0x1d, 0x05, 0xce, 0x37, 0x11, 0x07,
+ 0x9e, 0x50, 0xbf, 0x5f, 0x92, 0x2e, 0xe2, 0x59, 0x5e, 0x7a, 0x69, 0xcc,
+ 0x95, 0x1f, 0x87, 0xbc, 0x14, 0x87, 0xf5, 0x8c, 0x6d, 0x36, 0x19, 0x47,
+ 0x65, 0x9c, 0xb9, 0xa8, 0xb1, 0xd3, 0x09, 0x9e, 0x33, 0x3b, 0x6a, 0x18,
+ 0x09, 0x11, 0x6b, 0x68, 0xb5, 0xdb, 0xa8, 0x85, 0xed, 0xe8, 0x59, 0xc2,
+ 0x3e, 0x70, 0x11, 0x0b, 0x6b, 0x00, 0x17, 0x98, 0x27, 0x33, 0xd1, 0x48,
+ 0xf8, 0x51, 0xe1, 0x97, 0xc2, 0xbe, 0x18, 0xa0, 0x13, 0xd3, 0x1a, 0x7d,
+ 0xe0, 0xef, 0xcb, 0xd8, 0x0b, 0x34, 0xca, 0xe3, 0x47, 0xfc, 0x78, 0xc0,
+ 0x7a, 0x93, 0xed, 0xd2, 0x05, 0x11, 0x97, 0x79, 0x9a, 0xd2, 0x2c, 0xa7,
+ 0xc7, 0x85, 0x9c, 0x1a, 0x7d, 0x2c, 0x45, 0x2c, 0x57, 0xc8, 0x43, 0x18,
+ 0x44, 0x0c, 0x50, 0xf9, 0x3a, 0x3c, 0xca, 0x15, 0xb5, 0x57, 0x42, 0x12,
+ 0xba, 0x63, 0xeb, 0x31, 0x89, 0xe4, 0xa7, 0x8e, 0xc5, 0xb8, 0x31, 0x59,
+ 0xa3, 0xda, 0x51, 0xf8, 0x69, 0x2a, 0x9e, 0x88, 0xfc, 0xf8, 0xf2, 0x6f,
+ 0xe9, 0xb8, 0xe3, 0x06, 0xe7, 0x44, 0x6e, 0xe8, 0xcb, 0x45, 0x69, 0x83,
+ 0xd3, 0xec, 0xd3, 0x67, 0x8e, 0xb8, 0x31, 0x49, 0x24, 0x37, 0x21, 0x62,
+ 0x39, 0xfb, 0x28, 0xbe, 0x30, 0x42, 0x0f, 0x64, 0xa1, 0xc3, 0x68, 0x3d,
+ 0x6e, 0xe3, 0x57, 0x72, 0x20, 0xe3, 0x23, 0x94, 0x28, 0x82, 0x46, 0x3e,
+ 0xc6, 0x4a, 0xcc, 0x7b, 0x39, 0xac, 0xef, 0xf3, 0xf7, 0x02, 0x7e, 0x1b,
+ 0xe6, 0x0f, 0x54, 0xbc, 0xbc, 0x97, 0x26, 0x16, 0xc8, 0x49, 0x45, 0xef,
+ 0x15, 0x7b, 0x79, 0xa7, 0xa2, 0x43, 0x2a, 0xb6, 0x13, 0xe6, 0xf3, 0x88,
+ 0x97, 0x59, 0x74, 0x7f, 0x36, 0xe2, 0xa4, 0x48, 0xc6, 0x2c, 0x88, 0xfb,
+ 0x60, 0xb0, 0xed, 0xdd, 0xcd, 0x3a, 0xe4, 0x94, 0x88, 0x5b, 0x30, 0x52,
+ 0x99, 0x47, 0x7b, 0xc4, 0x1c, 0xba, 0x08, 0x7e, 0x5a, 0x2a, 0xf7, 0xaa,
+ 0x6a, 0x5b, 0x22, 0x93, 0x79, 0xc1, 0xfc, 0x6d, 0xdb, 0x89, 0x1a, 0x95,
+ 0xfb, 0x11, 0xf3, 0x38, 0x25, 0x70, 0x64, 0x1f, 0xfb, 0x3c, 0xa2, 0x5d,
+ 0x69, 0x46, 0xc4, 0x2f, 0xf8, 0xb8, 0xf0, 0xc8, 0x7e, 0xa9, 0xdb, 0xe4,
+ 0x79, 0x19, 0xd7, 0xe0, 0x67, 0x16, 0xb8, 0x1f, 0x55, 0xf9, 0xf4, 0xbd,
+ 0x14, 0xdb, 0x46, 0x9c, 0x69, 0xea, 0x8e, 0xc6, 0x99, 0x98, 0xd6, 0xc5,
+ 0xcd, 0x6a, 0x1a, 0xb4, 0xff, 0xf7, 0x91, 0xb6, 0xe1, 0x4c, 0x2b, 0x53,
+ 0xfc, 0x16, 0x08, 0x30, 0x78, 0xa6, 0xf8, 0x3c, 0x7e, 0x03, 0xc7, 0x97,
+ 0x14, 0xd8, 0x38, 0xcc, 0xd8, 0x06, 0x18, 0x67, 0x40, 0xac, 0x8b, 0xc5,
+ 0x1e, 0x0a, 0xfb, 0x32, 0x2b, 0x3d, 0xe4, 0x47, 0x3c, 0xce, 0xd6, 0xb9,
+ 0x1c, 0xad, 0x22, 0xef, 0x5d, 0xae, 0x47, 0xc2, 0x3e, 0x43, 0x27, 0xae,
+ 0xb3, 0xdf, 0xf0, 0x90, 0xca, 0xb9, 0x41, 0xcd, 0xa6, 0xce, 0xb9, 0xd1,
+ 0x3a, 0x45, 0xf3, 0x9e, 0x5e, 0xeb, 0x70, 0xff, 0xde, 0x18, 0x64, 0xd7,
+ 0x8d, 0x29, 0x10, 0x9f, 0x12, 0x73, 0x74, 0x81, 0x48, 0xce, 0x71, 0x65,
+ 0x1d, 0xa3, 0x85, 0xe7, 0x09, 0xfe, 0x20, 0xe2, 0x7e, 0x8f, 0xf0, 0x27,
+ 0xd6, 0x23, 0x7e, 0xb4, 0x1f, 0x38, 0xaa, 0xd3, 0x66, 0x9e, 0x19, 0xc5,
+ 0x71, 0x0f, 0xfb, 0x67, 0x1a, 0xf7, 0xca, 0x58, 0x14, 0xfb, 0x6c, 0x6a,
+ 0xbe, 0x10, 0x87, 0xea, 0x97, 0x39, 0x4c, 0xd9, 0x08, 0x59, 0x5d, 0xa0,
+ 0xd3, 0xaf, 0x4a, 0x1e, 0x37, 0x5b, 0xbb, 0xd8, 0x4a, 0x5e, 0x13, 0x7e,
+ 0x0b, 0x0d, 0xfb, 0x8d, 0x1e, 0x04, 0xed, 0x79, 0x8e, 0xdc, 0x6b, 0x1b,
+ 0xcf, 0xef, 0xd5, 0xbf, 0xc3, 0x74, 0x67, 0xe6, 0x6d, 0x87, 0xc7, 0xbc,
+ 0x1d, 0xec, 0x95, 0x6b, 0x67, 0x7f, 0xa1, 0xda, 0x78, 0xe5, 0xb8, 0x3a,
+ 0x4f, 0x22, 0x0e, 0x55, 0xa9, 0xbf, 0x78, 0x5b, 0xe8, 0x95, 0xfa, 0x58,
+ 0x78, 0x98, 0xf5, 0xa9, 0x94, 0xe3, 0x53, 0x1e, 0x72, 0xdc, 0x35, 0x0e,
+ 0xdc, 0xf2, 0xc9, 0xe5, 0x78, 0xb2, 0xa1, 0x1c, 0x4f, 0xf6, 0xca, 0x58,
+ 0x6c, 0xbd, 0x1c, 0xbf, 0x81, 0xbe, 0x14, 0x37, 0xca, 0x81, 0x44, 0x4d,
+ 0xbb, 0x3b, 0x56, 0x02, 0x9a, 0xe9, 0x78, 0x09, 0xd6, 0x0d, 0xc1, 0x97,
+ 0x58, 0x7b, 0x99, 0x32, 0x12, 0xf3, 0xb5, 0x6b, 0xa9, 0x5b, 0xb9, 0x17,
+ 0xeb, 0x34, 0xb5, 0xf7, 0x02, 0xbb, 0x43, 0x36, 0x22, 0x61, 0x19, 0x0b,
+ 0xd0, 0xf4, 0xeb, 0xf5, 0x1d, 0xcb, 0x47, 0x9c, 0x02, 0x21, 0xd6, 0x1d,
+ 0xa2, 0x73, 0x58, 0x9f, 0x56, 0xb1, 0xe4, 0x93, 0x59, 0x49, 0x07, 0xf3,
+ 0x88, 0xe0, 0x0f, 0xe0, 0xdb, 0x70, 0xd2, 0x9f, 0xe4, 0x39, 0x96, 0x71,
+ 0xe4, 0xd4, 0x72, 0x58, 0xcd, 0x1b, 0xb7, 0xc5, 0xf3, 0xaa, 0xf6, 0x92,
+ 0xd7, 0x71, 0x07, 0xcc, 0x57, 0xe4, 0xeb, 0x95, 0xdc, 0x64, 0xd8, 0x86,
+ 0x12, 0xfd, 0x37, 0xdb, 0x3d, 0xff, 0x11, 0x53, 0xec, 0xe3, 0xf0, 0x46,
+ 0xf1, 0x08, 0xe3, 0x4d, 0xcc, 0x29, 0x62, 0x90, 0x3a, 0x46, 0xfc, 0xc4,
+ 0x41, 0x6a, 0x3f, 0xcc, 0x28, 0xc0, 0x20, 0x9b, 0xf1, 0xa5, 0x71, 0x04,
+ 0xb9, 0xe6, 0x16, 0xdf, 0x83, 0xfd, 0xa8, 0x06, 0xad, 0x04, 0xb5, 0x21,
+ 0x0e, 0x81, 0xfd, 0xb0, 0xad, 0x74, 0x95, 0x8c, 0x9d, 0x16, 0x32, 0x96,
+ 0x58, 0x39, 0xad, 0x64, 0xec, 0xb4, 0x8a, 0xc3, 0x9f, 0x56, 0x32, 0x76,
+ 0x5a, 0xc9, 0xd8, 0x69, 0x25, 0x63, 0xa7, 0x99, 0xcf, 0x07, 0x18, 0xdf,
+ 0x02, 0x8b, 0xe8, 0x38, 0x68, 0x3b, 0xa5, 0xf2, 0x38, 0x0f, 0xfb, 0x5c,
+ 0x2b, 0x67, 0xef, 0xf6, 0x49, 0x39, 0x63, 0x6c, 0x22, 0xeb, 0xc9, 0xf8,
+ 0x5d, 0x98, 0x83, 0x57, 0x98, 0xe6, 0x1f, 0xd3, 0x99, 0x79, 0xf4, 0xd5,
+ 0x47, 0x13, 0x62, 0x1f, 0xdc, 0x26, 0x8a, 0xbb, 0xb1, 0xb0, 0xc9, 0x63,
+ 0xcd, 0x4a, 0xdf, 0xcf, 0x31, 0x6c, 0xc1, 0x27, 0xde, 0x7a, 0x15, 0x7c,
+ 0x32, 0xae, 0xe6, 0xab, 0xd6, 0x2f, 0x6a, 0xa1, 0x64, 0x0e, 0x74, 0x45,
+ 0xfe, 0xa4, 0xc5, 0x73, 0x23, 0xe8, 0xe4, 0x98, 0x1e, 0x34, 0x38, 0xa9,
+ 0x68, 0xf0, 0xb8, 0x18, 0x23, 0xf2, 0x0f, 0x11, 0xcb, 0x6c, 0x4c, 0x87,
+ 0x74, 0x76, 0x80, 0x9f, 0xc3, 0xb2, 0x70, 0x24, 0xcc, 0x3a, 0x69, 0xeb,
+ 0x74, 0xa8, 0x8c, 0xbd, 0x91, 0xee, 0xd9, 0x6a, 0x5d, 0xce, 0xba, 0xcb,
+ 0x96, 0x84, 0x95, 0x1d, 0x91, 0xb8, 0x78, 0x87, 0x5d, 0xa2, 0x13, 0xd1,
+ 0x83, 0xfc, 0x3d, 0x92, 0x74, 0xe8, 0x30, 0x19, 0x9d, 0x25, 0xfa, 0x11,
+ 0xcb, 0x41, 0x2b, 0xcb, 0xc1, 0x09, 0xe5, 0x97, 0x9c, 0x28, 0xfb, 0x25,
+ 0x93, 0x07, 0x90, 0x97, 0x91, 0x12, 0xeb, 0x5e, 0x3b, 0xcb, 0xbf, 0xc3,
+ 0x02, 0x3d, 0xb6, 0x88, 0xfd, 0x28, 0x7a, 0x71, 0x6c, 0xd2, 0x55, 0xf6,
+ 0xab, 0x63, 0xbe, 0x07, 0x0f, 0x08, 0xec, 0xee, 0x7b, 0x00, 0xf7, 0x9c,
+ 0x90, 0x7a, 0xcf, 0x47, 0xfe, 0xc1, 0x77, 0x18, 0x4f, 0x94, 0xe8, 0x31,
+ 0x7e, 0x67, 0x26, 0x77, 0x88, 0x9f, 0xad, 0xf7, 0x96, 0xb0, 0x63, 0x86,
+ 0x6f, 0x27, 0xf9, 0x3b, 0x1b, 0xbd, 0x3b, 0x22, 0xf8, 0x91, 0xf1, 0xb4,
+ 0x31, 0x13, 0x7d, 0xaf, 0x34, 0x3d, 0x85, 0x18, 0x3b, 0xe4, 0x24, 0x62,
+ 0x5a, 0x3e, 0x2f, 0xf9, 0x90, 0x58, 0xa9, 0x92, 0x0b, 0x2b, 0xf3, 0xc2,
+ 0xff, 0x8b, 0xc7, 0x66, 0x12, 0xd6, 0x4e, 0xe4, 0xf3, 0x93, 0x04, 0x9f,
+ 0x00, 0xfb, 0x53, 0x58, 0x4c, 0x67, 0xfd, 0x2e, 0x5b, 0xf1, 0xc6, 0x67,
+ 0x90, 0xe7, 0x96, 0x5b, 0xa4, 0x8d, 0x6d, 0x0e, 0xe2, 0x75, 0x03, 0x0b,
+ 0x6b, 0x9d, 0x21, 0x51, 0x1b, 0xde, 0xc1, 0x18, 0x49, 0xe7, 0x3e, 0x0f,
+ 0xf2, 0xf3, 0x11, 0xc7, 0x0b, 0xd0, 0xc4, 0x25, 0xb4, 0x6b, 0xa6, 0xfe,
+ 0x85, 0xd2, 0xef, 0xf1, 0x75, 0xb1, 0x7e, 0x99, 0xa2, 0x56, 0xb5, 0x36,
+ 0xa1, 0xf7, 0xad, 0x08, 0xb3, 0xec, 0x55, 0x6a, 0x9f, 0xfb, 0xcb, 0x31,
+ 0x3d, 0x21, 0x13, 0x35, 0x31, 0xbd, 0xaf, 0x6e, 0x62, 0xaf, 0x36, 0x93,
+ 0x03, 0xe4, 0xd4, 0xb5, 0x90, 0x8a, 0x55, 0x5a, 0x19, 0xda, 0x6a, 0x4d,
+ 0xdf, 0x76, 0xef, 0xf1, 0xb5, 0x36, 0x8f, 0x93, 0xf3, 0xa6, 0x1d, 0x54,
+ 0xfc, 0xd7, 0x4c, 0x67, 0xf2, 0x41, 0xb6, 0xf9, 0xd0, 0xad, 0xa0, 0x97,
+ 0xbf, 0x17, 0xb5, 0x2e, 0x5f, 0x0a, 0x34, 0xd3, 0xf2, 0x32, 0x72, 0x2d,
+ 0xfe, 0xf1, 0x80, 0xcc, 0x25, 0x4e, 0x32, 0x5d, 0x0e, 0xb3, 0x7d, 0x34,
+ 0xd4, 0xda, 0x11, 0xce, 0x41, 0x97, 0x88, 0xdf, 0x21, 0x0a, 0xdc, 0x3b,
+ 0x14, 0x64, 0xbf, 0x40, 0xae, 0x3d, 0x1c, 0xe5, 0x67, 0x7f, 0x33, 0x9f,
+ 0x44, 0xbc, 0xcc, 0x3c, 0xce, 0xcf, 0x9f, 0x60, 0x3c, 0x11, 0xa3, 0x66,
+ 0x5a, 0x5a, 0x6e, 0x66, 0xbf, 0xa0, 0x99, 0xf1, 0xc4, 0x80, 0xd9, 0xef,
+ 0x13, 0xef, 0x12, 0x75, 0x35, 0x9f, 0x0f, 0x1c, 0x66, 0xbe, 0xc2, 0xbb,
+ 0xfe, 0x5d, 0xbd, 0xab, 0xf6, 0x1d, 0xff, 0x51, 0xc2, 0xf1, 0x71, 0x3f,
+ 0x39, 0x37, 0xf0, 0x1b, 0x5c, 0xf3, 0x63, 0x8c, 0x9d, 0x43, 0x94, 0x99,
+ 0x6f, 0xe2, 0x31, 0x8c, 0xb3, 0x1f, 0x11, 0xe5, 0xe3, 0xfb, 0xc8, 0x29,
+ 0x4e, 0xd1, 0x5f, 0x15, 0xdd, 0x31, 0xe1, 0xfb, 0xb8, 0xcf, 0xb2, 0xb6,
+ 0xbf, 0x85, 0xfb, 0xf5, 0x91, 0x5d, 0xab, 0x63, 0x82, 0xe4, 0xff, 0xeb,
+ 0x10, 0x35, 0x7f, 0x0d, 0xb1, 0x97, 0x12, 0xe5, 0xa2, 0xa8, 0x57, 0x90,
+ 0xf1, 0xe7, 0xab, 0x22, 0x87, 0x96, 0xef, 0xe7, 0x67, 0xce, 0xa1, 0xdd,
+ 0x55, 0x8b, 0xae, 0xdb, 0x92, 0xde, 0x3f, 0x08, 0x84, 0xc8, 0xff, 0x12,
+ 0x72, 0x9f, 0xc4, 0xfe, 0x1a, 0x8e, 0x7d, 0x88, 0xf5, 0xfb, 0xd7, 0x70,
+ 0x1f, 0x7f, 0xbe, 0x84, 0xe3, 0x20, 0x8f, 0x13, 0xf6, 0x1a, 0xf9, 0x2e,
+ 0xd0, 0x8b, 0x87, 0xc3, 0xa6, 0xe0, 0xbf, 0xfb, 0x98, 0xa7, 0x9a, 0x44,
+ 0xac, 0xb1, 0x0b, 0x6d, 0xed, 0xfd, 0xc0, 0x16, 0xce, 0xd0, 0x21, 0x1c,
+ 0xc7, 0x3a, 0xfd, 0x4c, 0x23, 0xc9, 0x43, 0x18, 0x4f, 0x15, 0x73, 0x07,
+ 0x8e, 0x0e, 0x11, 0xcf, 0x27, 0xf0, 0xc7, 0x2f, 0xf1, 0x1b, 0x91, 0x4e,
+ 0x3f, 0xbf, 0x23, 0xc1, 0xef, 0x98, 0xc8, 0xcb, 0x71, 0xcf, 0x15, 0xfd,
+ 0x24, 0xe3, 0x54, 0x5f, 0xe9, 0xd3, 0xbf, 0xd1, 0x48, 0x3d, 0x78, 0x76,
+ 0x59, 0x56, 0xf8, 0x7b, 0x3b, 0xdd, 0xca, 0xb7, 0xd1, 0x6d, 0xb5, 0xa6,
+ 0x75, 0x4b, 0xf8, 0x65, 0xac, 0xc3, 0x93, 0xed, 0xb4, 0xbe, 0xdc, 0x44,
+ 0xd4, 0x15, 0x14, 0x6b, 0xce, 0xb7, 0xf2, 0x05, 0x7e, 0xff, 0x97, 0xfb,
+ 0x64, 0x5c, 0xa7, 0xc2, 0x23, 0xb7, 0x3c, 0x78, 0xe4, 0x03, 0xc1, 0x23,
+ 0x5f, 0xec, 0xdb, 0x98, 0x47, 0x50, 0xf3, 0x0f, 0xde, 0x08, 0x52, 0xb3,
+ 0xe2, 0x8f, 0x17, 0x99, 0x3f, 0x9e, 0x65, 0xfe, 0x38, 0xd6, 0x80, 0x3f,
+ 0x8c, 0x1a, 0xfe, 0x38, 0x2e, 0xf8, 0xe3, 0x89, 0xbe, 0x8d, 0xf8, 0xe3,
+ 0x98, 0x7f, 0xa3, 0x58, 0x93, 0xaf, 0x35, 0xc0, 0xef, 0x9e, 0xb3, 0xf7,
+ 0x31, 0xaf, 0xdb, 0xb4, 0x34, 0x8f, 0xfa, 0x84, 0xd5, 0xa8, 0x41, 0x3f,
+ 0x13, 0x3e, 0xd9, 0x9a, 0xf0, 0xf9, 0xc7, 0x45, 0xcd, 0xc1, 0xa2, 0xe0,
+ 0x2f, 0xb6, 0xff, 0xe3, 0xa8, 0xab, 0xaa, 0x9d, 0x8b, 0x56, 0xba, 0x1e,
+ 0xc5, 0x5c, 0x58, 0x7a, 0x2e, 0x08, 0xeb, 0xbb, 0x6a, 0xef, 0xc8, 0x40,
+ 0x3c, 0x4b, 0xce, 0x07, 0xe0, 0xd1, 0x95, 0xb6, 0xc0, 0x44, 0xf6, 0x1b,
+ 0x7d, 0xc0, 0x7f, 0x99, 0x15, 0x72, 0x9d, 0x0f, 0xf0, 0xf9, 0x90, 0xf8,
+ 0x6d, 0x2b, 0xc8, 0xca, 0x87, 0xc8, 0x71, 0x64, 0x9e, 0xbc, 0x9e, 0xef,
+ 0xa5, 0x1b, 0xf9, 0x7d, 0xb4, 0x96, 0xef, 0xa3, 0x37, 0xc5, 0xbe, 0x1a,
+ 0xb2, 0x36, 0x72, 0x4d, 0xcc, 0x91, 0x41, 0x47, 0x43, 0xdc, 0x66, 0x79,
+ 0x1f, 0xad, 0x2e, 0x6b, 0xfe, 0x06, 0x6f, 0x83, 0x5f, 0x62, 0x9d, 0xb2,
+ 0x66, 0xae, 0x9e, 0x67, 0x26, 0xaa, 0x79, 0x46, 0xdc, 0x03, 0x5e, 0xc9,
+ 0xd4, 0xd5, 0xfa, 0x22, 0x5f, 0x11, 0xb9, 0x7a, 0x41, 0x6a, 0x42, 0xde,
+ 0xa2, 0x11, 0x19, 0x3e, 0xea, 0x07, 0x86, 0xce, 0xb1, 0xcd, 0xe5, 0x39,
+ 0xb3, 0x91, 0xe7, 0xd4, 0xc7, 0x78, 0xb8, 0x43, 0xe0, 0xdf, 0xb8, 0x1d,
+ 0x08, 0x4f, 0x50, 0xe9, 0x69, 0xc3, 0xc6, 0x5e, 0x8f, 0x49, 0x7e, 0x9e,
+ 0xa1, 0xe2, 0x4d, 0xbb, 0x5c, 0xfc, 0x57, 0x8b, 0x75, 0xb1, 0x96, 0xfc,
+ 0x10, 0xf7, 0x19, 0x76, 0xb8, 0xb2, 0x5e, 0x43, 0xe5, 0xf5, 0x9a, 0x56,
+ 0x1e, 0xb7, 0x94, 0xbd, 0x19, 0x9b, 0xdb, 0x15, 0xff, 0x6f, 0x40, 0x75,
+ 0xeb, 0x41, 0x73, 0x7f, 0x40, 0xf1, 0x25, 0xa0, 0x79, 0x67, 0x19, 0x86,
+ 0x43, 0x3d, 0xa0, 0x3c, 0x0a, 0x1a, 0x0f, 0x41, 0xcc, 0xf5, 0x1e, 0x5a,
+ 0x03, 0x12, 0x07, 0x8d, 0x89, 0x20, 0xe6, 0x7a, 0x0f, 0x41, 0xe7, 0x7a,
+ 0x0f, 0xad, 0xb1, 0x01, 0x97, 0xdb, 0xcd, 0x53, 0x80, 0xe1, 0x3e, 0x85,
+ 0x19, 0xba, 0xce, 0x51, 0x0d, 0x7a, 0x77, 0x52, 0x0c, 0x78, 0x4c, 0x5b,
+ 0x50, 0x05, 0x7f, 0x18, 0xba, 0x62, 0x84, 0xa1, 0x0d, 0xb8, 0x9d, 0xe5,
+ 0x02, 0x34, 0xd3, 0x79, 0x4a, 0x0c, 0x30, 0x3c, 0x23, 0x80, 0x79, 0x4f,
+ 0x18, 0x9a, 0xf7, 0x60, 0x73, 0xc7, 0xfc, 0x0c, 0x90, 0x7b, 0x98, 0x6c,
+ 0xc0, 0x7d, 0x0b, 0x48, 0x79, 0x25, 0x83, 0x56, 0x5e, 0x01, 0xd3, 0x84,
+ 0x3a, 0x44, 0x7f, 0xd3, 0x7a, 0x0d, 0x79, 0xd8, 0x38, 0x60, 0x13, 0xd0,
+ 0xdc, 0xe6, 0x29, 0xa4, 0xcc, 0x3d, 0x03, 0xeb, 0x5b, 0xac, 0x6b, 0x1b,
+ 0x6d, 0xc0, 0x7b, 0xac, 0x17, 0x4d, 0x61, 0x61, 0x58, 0xd2, 0xc3, 0x00,
+ 0xac, 0x1f, 0x40, 0x69, 0x1d, 0x54, 0x47, 0xc0, 0xd3, 0xbb, 0x40, 0x13,
+ 0xd0, 0x7d, 0x4e, 0xc0, 0xb6, 0xa8, 0x73, 0xbf, 0x32, 0x78, 0xad, 0x6c,
+ 0x03, 0xf4, 0xfc, 0xaa, 0x45, 0x3d, 0xde, 0xf2, 0xa0, 0x7c, 0xe6, 0xa4,
+ 0xc2, 0x40, 0x46, 0x5e, 0x60, 0x83, 0xe6, 0x05, 0x70, 0x38, 0x01, 0xd3,
+ 0x3a, 0xb0, 0x8c, 0x5a, 0x93, 0x04, 0x34, 0x8f, 0x87, 0xc5, 0xa5, 0x1f,
+ 0x24, 0xc6, 0x00, 0x15, 0x63, 0x01, 0xf2, 0x65, 0x80, 0x6d, 0x4a, 0x90,
+ 0x5f, 0x41, 0x79, 0x01, 0x64, 0x36, 0xc8, 0xef, 0xa0, 0xb2, 0x13, 0x94,
+ 0x17, 0x81, 0xec, 0x25, 0x42, 0x50, 0x3f, 0x03, 0x69, 0x20, 0xbb, 0x79,
+ 0x8a, 0x08, 0x98, 0x9f, 0x14, 0x20, 0xc4, 0xd0, 0x00, 0xcf, 0x07, 0xc4,
+ 0x86, 0x31, 0x4c, 0x7d, 0x0c, 0x19, 0xf9, 0x06, 0x62, 0x06, 0x22, 0xdf,
+ 0xb0, 0x33, 0x1c, 0x10, 0x80, 0x85, 0xd5, 0xff, 0xff, 0xc7, 0x54, 0x58,
+ 0x80, 0xe9, 0x14, 0xb4, 0x8e, 0xf5, 0xf7, 0xff, 0x03, 0x22, 0x2c, 0x0c,
+ 0x2d, 0xf0, 0xf5, 0x88, 0x0b, 0xe5, 0x41, 0x65, 0xe8, 0x02, 0x20, 0xab,
+ 0x0d, 0xde, 0x26, 0x60, 0x01, 0xdf, 0x61, 0xbd, 0x80, 0xe1, 0x17, 0xb0,
+ 0xcc, 0xfa, 0xff, 0x7f, 0x29, 0x5c, 0x2d, 0x08, 0x00, 0x00, 0xff, 0x88,
+ 0x78, 0xb5, 0x98, 0x7e, 0x00, 0x00, 0x00 };
static const u32 bnx2_COM_b09FwData[(0x0/4) + 1] = { 0x0 };
static const u32 bnx2_COM_b09FwRodata[(0x88/4) + 1] = {
- 0x08001b68, 0x08001ba4, 0x08001ba4, 0x08001ba4, 0x08001ba4, 0x08001ba4,
- 0x08001ab4, 0x08001ba4, 0x08001b28, 0x08001ba4, 0x08001a3c, 0x08001ba4,
- 0x08001ba4, 0x08001ba4, 0x08001a48, 0x00000000, 0x08002abc, 0x08002b0c,
- 0x08002b3c, 0x08002b6c, 0x08002b9c, 0x00000000, 0x0800604c, 0x0800604c,
- 0x0800604c, 0x0800604c, 0x0800604c, 0x08006078, 0x08006078, 0x080060b8,
- 0x080060c4, 0x080060c4, 0x0800604c, 0x00000000, 0x00000000 };
+ 0x08001b7c, 0x08001bb8, 0x08001bb8, 0x08001bb8, 0x08001bb8, 0x08001bb8,
+ 0x08001ac8, 0x08001bb8, 0x08001b3c, 0x08001bb8, 0x08001a50, 0x08001bb8,
+ 0x08001bb8, 0x08001bb8, 0x08001a5c, 0x00000000, 0x08002b74, 0x08002bc4,
+ 0x08002bf4, 0x08002c24, 0x08002c58, 0x00000000, 0x08006120, 0x08006120,
+ 0x08006120, 0x08006120, 0x08006120, 0x0800614c, 0x0800614c, 0x0800618c,
+ 0x08006198, 0x08006198, 0x08006120, 0x00000000, 0x00000000 };
static struct fw_info bnx2_com_fw_09 = {
+ /* Firmware version: 3.7.1 */
.ver_major = 0x3,
- .ver_minor = 0x4,
- .ver_fix = 0x3,
+ .ver_minor = 0x7,
+ .ver_fix = 0x1,
.start_addr = 0x080000b4,
.text_addr = 0x08000000,
- .text_len = 0x7dc0,
+ .text_len = 0x7e94,
.text_index = 0x0,
.gz_text = bnx2_COM_b09FwText,
.gz_text_len = sizeof(bnx2_COM_b09FwText),
- .data_addr = 0x08007e60,
+ .data_addr = 0x08007f40,
.data_len = 0x0,
.data_index = 0x0,
.data = bnx2_COM_b09FwData,
- .sbss_addr = 0x08007e60,
+ .sbss_addr = 0x08007f40,
.sbss_len = 0x60,
.sbss_index = 0x0,
- .bss_addr = 0x08007ec0,
+ .bss_addr = 0x08007fa0,
.bss_len = 0x88,
.bss_index = 0x0,
- .rodata_addr = 0x08007dc0,
+ .rodata_addr = 0x08007e98,
.rodata_len = 0x88,
.rodata_index = 0x0,
.rodata = bnx2_COM_b09FwRodata,
};
static u8 bnx2_CP_b09FwText[] = {
-/* 0x1f, 0x8b, 0x08, 0x00, 0x0f, 0x34, 0xe7, 0x45, 0x00, 0x03, */
- 0xbd, 0x7d,
- 0x0d, 0x74, 0x5c, 0x57, 0x7d, 0xe7, 0xff, 0xdd, 0x19, 0x49, 0x63, 0x59,
- 0x96, 0x9f, 0xe5, 0x89, 0x32, 0x51, 0x84, 0x3d, 0x23, 0x3d, 0xd9, 0x22,
- 0x12, 0xe1, 0xc5, 0x11, 0xac, 0xda, 0x2a, 0xe9, 0x30, 0x92, 0x3f, 0x12,
- 0x02, 0xab, 0x10, 0x43, 0xb3, 0x1c, 0x4a, 0xc5, 0x48, 0x4e, 0x02, 0x04,
- 0xea, 0x40, 0xe8, 0x86, 0xdd, 0xec, 0x66, 0x32, 0x92, 0x3f, 0x9a, 0x8e,
- 0x3d, 0x93, 0x44, 0x89, 0xbd, 0xdd, 0x9c, 0xad, 0x90, 0x14, 0x3b, 0x74,
- 0x07, 0x4f, 0xe2, 0x98, 0x96, 0x73, 0x0a, 0x8d, 0x50, 0x8c, 0x9b, 0xe6,
- 0xb0, 0xdd, 0xd0, 0xa6, 0x34, 0xdb, 0x86, 0x22, 0x8c, 0x81, 0xf4, 0x2c,
- 0xdd, 0x86, 0x42, 0x77, 0xd3, 0x36, 0xe5, 0xed, 0xef, 0x77, 0xef, 0x7d,
- 0x9a, 0x91, 0x34, 0xce, 0x07, 0xdd, 0xad, 0xcf, 0x79, 0x7e, 0xf3, 0xee,
- 0xbb, 0x1f, 0xff, 0xfb, 0xbf, 0xff, 0xef, 0xfb, 0xbf, 0x4f, 0x97, 0x8b,
- 0x34, 0x8b, 0xfd, 0xb7, 0x01, 0xd7, 0xd5, 0xc9, 0xfd, 0xe3, 0x57, 0x5f,
- 0x39, 0x70, 0x25, 0x9f, 0xa3, 0x91, 0x68, 0x44, 0xde, 0xc4, 0xbf, 0xe4,
- 0x1b, 0xa8, 0x83, 0x0e, 0xdd, 0x70, 0x2c, 0x5e, 0x12, 0x53, 0x43, 0xde,
- 0xfe, 0x8c, 0x27, 0xb1, 0xc8, 0x50, 0xee, 0xce, 0x71, 0x4f, 0x24, 0x5d,
- 0xee, 0x4b, 0x0e, 0xcb, 0x3f, 0x05, 0xb9, 0x78, 0x54, 0x58, 0xfe, 0x96,
- 0xa1, 0x57, 0x7f, 0xeb, 0x2b, 0xff, 0x2a, 0xf5, 0xf2, 0x4c, 0x44, 0x62,
- 0xee, 0xd0, 0xed, 0xe2, 0x6e, 0x93, 0x58, 0xe7, 0x50, 0x72, 0xff, 0x23,
- 0xdb, 0x97, 0x44, 0x5a, 0xc3, 0xbe, 0x5e, 0x0a, 0xbe, 0xb2, 0x5d, 0x72,
- 0x1d, 0x43, 0x89, 0xb1, 0x86, 0x21, 0x57, 0x9e, 0xaa, 0xc8, 0xe8, 0x89,
- 0xc2, 0xcb, 0x41, 0x74, 0x28, 0x88, 0x4c, 0x0d, 0x38, 0x12, 0x19, 0x92,
- 0xb3, 0xe3, 0x03, 0xf7, 0x04, 0xca, 0xf3, 0xfc, 0x45, 0x69, 0x19, 0x3c,
- 0x37, 0x80, 0xf7, 0x65, 0x41, 0xdd, 0xbd, 0xd7, 0x9c, 0x28, 0xc4, 0x44,
- 0x0d, 0xf5, 0xbc, 0x90, 0x89, 0x5c, 0x25, 0x7c, 0x7f, 0x56, 0x7a, 0xfc,
- 0xa7, 0x05, 0xe5, 0xe5, 0x98, 0x64, 0x2a, 0xd2, 0x82, 0x32, 0xdc, 0x9b,
- 0x51, 0x27, 0xe5, 0x66, 0x22, 0xae, 0xe4, 0x2b, 0x3f, 0x5e, 0x67, 0xc6,
- 0x9d, 0xb3, 0xf7, 0xbf, 0x8e, 0x99, 0x3b, 0xc6, 0x2d, 0xc6, 0x64, 0x29,
- 0x92, 0x10, 0xc0, 0x82, 0x79, 0x25, 0x64, 0xb2, 0x98, 0x94, 0x4c, 0x81,
- 0xb0, 0x45, 0x25, 0xeb, 0x12, 0xae, 0x04, 0xda, 0xb7, 0x39, 0xf5, 0xeb,
- 0xb3, 0xee, 0x0b, 0xa8, 0x9b, 0x44, 0xbd, 0x4e, 0x79, 0x12, 0x75, 0x4f,
- 0x57, 0xe2, 0xf2, 0x44, 0xe5, 0x57, 0x25, 0x8d, 0xb6, 0x8f, 0x57, 0x30,
- 0x76, 0xb1, 0x51, 0x86, 0xa7, 0x9b, 0x25, 0x33, 0xdd, 0x9d, 0xc8, 0x4a,
- 0x10, 0x7c, 0xda, 0xff, 0xa8, 0x8c, 0xb5, 0xa1, 0x7e, 0x91, 0xef, 0x12,
- 0x2b, 0xde, 0x65, 0xfd, 0x3e, 0x37, 0xab, 0x1c, 0x49, 0xef, 0x4d, 0x25,
- 0xc6, 0x14, 0x9f, 0x1b, 0x24, 0xd3, 0x8f, 0xe7, 0xd1, 0xa8, 0x44, 0xbc,
- 0x20, 0xb8, 0xc3, 0xbf, 0x0c, 0x70, 0xa4, 0x92, 0x49, 0xc5, 0xb6, 0x6c,
- 0x97, 0xca, 0x25, 0x55, 0x5c, 0x72, 0x95, 0x2b, 0x25, 0xd9, 0x16, 0x04,
- 0xef, 0xf3, 0x3b, 0x51, 0x2e, 0x32, 0x5c, 0x90, 0xfd, 0x58, 0x23, 0xf4,
- 0x29, 0xbe, 0x1a, 0xda, 0x8c, 0x79, 0xf4, 0xb9, 0xc3, 0xd2, 0x28, 0xe9,
- 0xb8, 0xa4, 0xd5, 0x90, 0x24, 0xd5, 0xd0, 0x3a, 0x94, 0x39, 0xd2, 0xe0,
- 0x7d, 0xc1, 0xd2, 0xd2, 0x46, 0x3c, 0xcb, 0xa8, 0x1a, 0x6a, 0x5b, 0x55,
- 0x9e, 0x4a, 0x8a, 0x5a, 0x07, 0x5c, 0xa5, 0x7a, 0xd3, 0x8a, 0x65, 0xb8,
- 0xeb, 0xb2, 0x0f, 0x36, 0xad, 0x2d, 0xdb, 0xef, 0xac, 0x2c, 0xbb, 0xbd,
- 0x85, 0xb0, 0x8a, 0xe2, 0xef, 0xb8, 0x9e, 0x6b, 0x3a, 0xde, 0xed, 0x36,
- 0x60, 0x5e, 0xa3, 0x7e, 0xca, 0xdd, 0xa9, 0x9e, 0x0f, 0xa4, 0x9d, 0x30,
- 0xf3, 0x9d, 0xc2, 0x3b, 0x54, 0x1d, 0xf2, 0xb1, 0x6e, 0xae, 0x1c, 0xc2,
- 0xdc, 0xce, 0x4f, 0xa7, 0xdc, 0x2e, 0x85, 0xfb, 0x3c, 0x7f, 0x07, 0x41,
- 0xc6, 0xcf, 0xe9, 0x35, 0xfd, 0xee, 0x74, 0x02, 0xcf, 0x80, 0x3f, 0x9e,
- 0x4e, 0x6d, 0x92, 0xab, 0xed, 0xba, 0x7c, 0x13, 0x63, 0x76, 0xbb, 0x77,
- 0xa8, 0x6e, 0xd7, 0x57, 0x29, 0x77, 0x56, 0xce, 0xe0, 0x39, 0x08, 0x6e,
- 0xf4, 0x53, 0x89, 0x1c, 0xd6, 0xec, 0x42, 0x21, 0x2e, 0xdf, 0x2b, 0xa4,
- 0x40, 0xc5, 0xa9, 0xde, 0x39, 0xe9, 0xf3, 0xe7, 0x00, 0x6f, 0x1e, 0xd7,
- 0x41, 0xbe, 0x2b, 0xe3, 0x5d, 0x99, 0x6d, 0x83, 0xe0, 0x26, 0xff, 0x37,
- 0x83, 0xb1, 0x76, 0xc3, 0x17, 0x4f, 0x15, 0xb1, 0x9e, 0x80, 0xf9, 0x74,
- 0x11, 0xeb, 0x89, 0xb5, 0x7a, 0x5c, 0xaf, 0x7b, 0x2f, 0xd6, 0x9d, 0xb4,
- 0x41, 0xba, 0xd8, 0x61, 0x69, 0xf9, 0x03, 0xf6, 0x2e, 0x92, 0x29, 0x3a,
- 0x92, 0xf1, 0xff, 0x31, 0x48, 0x6b, 0x7e, 0x11, 0x67, 0xb8, 0x48, 0x5a,
- 0x6c, 0x00, 0xac, 0x7c, 0xcc, 0xda, 0x7a, 0x1b, 0x1d, 0xe0, 0x96, 0xeb,
- 0xc0, 0xf7, 0x31, 0xe5, 0x35, 0xd9, 0xf7, 0x21, 0x5f, 0xf0, 0xdf, 0x26,
- 0x47, 0xbc, 0x6a, 0xbd, 0x0c, 0x69, 0xb2, 0x92, 0x93, 0xec, 0x83, 0x81,
- 0x0c, 0xfb, 0xc0, 0x13, 0xfb, 0x74, 0x7d, 0xd1, 0x6d, 0x5d, 0xd6, 0xd1,
- 0x75, 0xf1, 0x6f, 0x7d, 0x23, 0xc6, 0x70, 0x46, 0x8a, 0xd5, 0xb6, 0x23,
- 0xc5, 0xfc, 0x66, 0x0b, 0x1f, 0x9e, 0x07, 0x9d, 0x4c, 0xe5, 0x82, 0x5d,
- 0xdb, 0x70, 0x1e, 0x57, 0xd7, 0xa1, 0x6d, 0x17, 0x7c, 0xe0, 0x4a, 0xb6,
- 0x30, 0x88, 0x71, 0xe3, 0xb8, 0x07, 0xc1, 0x94, 0x9f, 0x4e, 0x45, 0x65,
- 0x08, 0xcf, 0xa3, 0xe4, 0x3d, 0xe0, 0x4f, 0xa2, 0x99, 0xed, 0xbe, 0x8c,
- 0x80, 0xee, 0xf3, 0x95, 0xd7, 0x97, 0x22, 0x7a, 0x0e, 0xfe, 0x3f, 0x59,
- 0xdc, 0x70, 0x1c, 0x33, 0xe6, 0x54, 0xb1, 0x43, 0xf2, 0xd3, 0x9e, 0x4c,
- 0x16, 0x16, 0x7a, 0x95, 0xbc, 0x4c, 0x7e, 0xc7, 0xfa, 0xa5, 0x40, 0xbb,
- 0x43, 0x32, 0x5c, 0xf1, 0x24, 0x5f, 0xc0, 0xbd, 0xd8, 0x0d, 0xfa, 0x8d,
- 0x4a, 0x3a, 0x61, 0xd6, 0x26, 0x5f, 0x18, 0xc1, 0xfc, 0x80, 0x6b, 0x8f,
- 0xbf, 0x07, 0x2d, 0x4c, 0xae, 0x64, 0x06, 0x48, 0x3f, 0x6f, 0x06, 0x96,
- 0x98, 0xcc, 0xfa, 0xe0, 0x0b, 0xd7, 0xc0, 0x92, 0x2f, 0xc6, 0xa2, 0xc3,
- 0x98, 0xf7, 0x70, 0xf9, 0x57, 0xd0, 0x7f, 0x8b, 0xfe, 0x0d, 0x7e, 0xb2,
- 0x65, 0x51, 0xdc, 0xe3, 0xb8, 0x13, 0xe6, 0x90, 0x56, 0x21, 0x1b, 0xa6,
- 0x3b, 0x65, 0x12, 0xb4, 0x3a, 0x2c, 0xf8, 0x3d, 0xcf, 0xb9, 0x10, 0xae,
- 0x0e, 0xfd, 0x7b, 0x72, 0x7a, 0x8b, 0x7e, 0xce, 0x8e, 0x76, 0x48, 0x6e,
- 0x3e, 0x9c, 0x33, 0xe5, 0x05, 0x65, 0x44, 0xea, 0xb0, 0x08, 0x65, 0x46,
- 0x10, 0x3c, 0xe8, 0x53, 0x6e, 0x04, 0xc1, 0x69, 0x9f, 0x72, 0xe4, 0x0c,
- 0xe4, 0x03, 0x65, 0x07, 0x79, 0xd9, 0x53, 0x5c, 0xab, 0x4c, 0xa1, 0x17,
- 0xeb, 0xd1, 0x28, 0xd9, 0xfe, 0xe3, 0x84, 0x15, 0x72, 0xe7, 0xa5, 0x4f,
- 0x66, 0xbc, 0x5c, 0x22, 0xa2, 0xf1, 0x04, 0xca, 0x82, 0x3c, 0x4c, 0xeb,
- 0x99, 0x75, 0x49, 0xbe, 0xbf, 0x64, 0xeb, 0xc8, 0xaf, 0xb2, 0x4e, 0x74,
- 0x4d, 0x9d, 0x7f, 0xa7, 0x0c, 0x5f, 0xf6, 0x62, 0xdd, 0x3a, 0x14, 0xf1,
- 0xd8, 0xb5, 0x8d, 0xcf, 0x12, 0x6b, 0x18, 0xfa, 0x3d, 0xbc, 0x7b, 0xee,
- 0x53, 0x8f, 0x7a, 0xf5, 0xde, 0xfd, 0x28, 0xba, 0xf6, 0xdd, 0x94, 0x44,
- 0xbd, 0x54, 0xef, 0x8d, 0xea, 0x4f, 0x1a, 0xa4, 0x35, 0x08, 0x1e, 0xf5,
- 0xc3, 0xf2, 0xc6, 0x86, 0xb5, 0x63, 0x5c, 0x55, 0xa7, 0xec, 0x68, 0x9d,
- 0xb2, 0xcf, 0xd7, 0x29, 0x7b, 0x7b, 0xe3, 0xda, 0xb2, 0xdb, 0xeb, 0x94,
- 0xcd, 0xd6, 0x29, 0xfb, 0x69, 0x9d, 0x32, 0x69, 0x5a, 0x5b, 0x16, 0xa9,
- 0x53, 0xd6, 0x57, 0xa7, 0x2c, 0x0a, 0xbe, 0xdb, 0x26, 0xf9, 0xf8, 0xbd,
- 0x9c, 0xbb, 0xc5, 0x4d, 0x29, 0xb2, 0x16, 0x37, 0x0d, 0xa8, 0xd7, 0xb9,
- 0xaa, 0xde, 0x17, 0xeb, 0xd4, 0x6b, 0x44, 0xbd, 0xb6, 0x55, 0xf5, 0x76,
- 0xd4, 0xc1, 0x75, 0x13, 0xea, 0xc5, 0x56, 0xd5, 0x7b, 0xb0, 0x4e, 0x3d,
- 0x96, 0x7f, 0xc6, 0x8e, 0xd3, 0x07, 0x2d, 0xf4, 0x5a, 0xeb, 0xd5, 0x28,
- 0xd2, 0xce, 0xf2, 0x5e, 0xe8, 0x90, 0x0e, 0x65, 0xe4, 0x02, 0x65, 0x10,
- 0xcb, 0x3a, 0x41, 0xe7, 0x71, 0xd0, 0x1d, 0xe5, 0x28, 0xf8, 0x8c, 0x73,
- 0xa9, 0x6c, 0x90, 0xb1, 0x78, 0x9f, 0x7b, 0xb5, 0x6a, 0x01, 0x8d, 0xa5,
- 0xdc, 0xa4, 0x22, 0xff, 0x49, 0x2e, 0x32, 0xe4, 0xe5, 0x86, 0x45, 0xc5,
- 0x95, 0x04, 0x32, 0xe2, 0xab, 0x36, 0x25, 0xf7, 0x80, 0xbf, 0xd2, 0xd0,
- 0x59, 0x37, 0x06, 0xc3, 0x9a, 0xb7, 0x4c, 0xdd, 0x8b, 0xcb, 0x54, 0x5f,
- 0x0e, 0x52, 0x16, 0x0e, 0x8d, 0x7e, 0x2a, 0xe3, 0x2d, 0x0c, 0x36, 0x82,
- 0x66, 0xcf, 0xa3, 0xcd, 0x6e, 0xb4, 0xdc, 0x57, 0x8e, 0xca, 0x48, 0x79,
- 0x00, 0xbc, 0xe0, 0xc8, 0x39, 0x6f, 0xa3, 0x9c, 0xf3, 0x51, 0xb7, 0x12,
- 0x91, 0xc5, 0xb8, 0x23, 0x8b, 0x78, 0xce, 0xf8, 0x78, 0x57, 0x09, 0x79,
- 0x6b, 0x40, 0x0e, 0x14, 0x7d, 0x39, 0x5c, 0xbc, 0x41, 0x85, 0x7a, 0x6d,
- 0xa7, 0xbf, 0x5e, 0x1e, 0x73, 0x4d, 0xdf, 0xbb, 0xbd, 0x05, 0x68, 0xd4,
- 0xa8, 0x9c, 0xf7, 0x52, 0x89, 0x45, 0xcd, 0x13, 0xff, 0x27, 0x18, 0x41,
- 0x3f, 0xb3, 0x5e, 0xca, 0xfd, 0x03, 0x3c, 0x8f, 0x95, 0x69, 0xcb, 0x54,
- 0xfb, 0x9a, 0x44, 0x5f, 0x87, 0x8a, 0x1b, 0xe4, 0x56, 0xdb, 0x7e, 0x97,
- 0xb7, 0xd0, 0x0b, 0x9e, 0x73, 0x4f, 0x50, 0x86, 0x14, 0x00, 0xd7, 0x5e,
- 0xf0, 0x36, 0xda, 0x7e, 0x4d, 0xcb, 0x33, 0xd8, 0x3e, 0x85, 0x8d, 0x90,
- 0xcf, 0x7f, 0x17, 0xdc, 0x1a, 0x67, 0x7d, 0x96, 0x51, 0xe7, 0x48, 0x49,
- 0x0d, 0x41, 0x26, 0x0c, 0x50, 0x66, 0x26, 0x21, 0x2f, 0x21, 0x7b, 0x8a,
- 0x3f, 0x0d, 0xd2, 0xd1, 0x5a, 0x39, 0x28, 0xb9, 0x6a, 0x1d, 0x96, 0x25,
- 0x8d, 0x5c, 0x2d, 0x2e, 0x2d, 0xcb, 0x8a, 0x1c, 0xe4, 0xcb, 0x53, 0x15,
- 0xca, 0x85, 0x0f, 0x82, 0x47, 0x3b, 0x65, 0xa4, 0x90, 0xca, 0xa5, 0x65,
- 0x1b, 0xd6, 0xef, 0xd7, 0xb1, 0xa6, 0x51, 0x5c, 0x0f, 0xad, 0x97, 0x56,
- 0x1f, 0xba, 0x9b, 0xe5, 0xe8, 0xb4, 0x9d, 0x36, 0xd2, 0x6f, 0x03, 0x0f,
- 0x93, 0x5c, 0xf3, 0x44, 0x26, 0xe2, 0x8c, 0xd2, 0x5e, 0x19, 0x85, 0x7c,
- 0xcc, 0x96, 0xd9, 0x37, 0xe1, 0x4d, 0xd8, 0xdf, 0xb0, 0x9b, 0x0a, 0x9d,
- 0xf6, 0x77, 0x0b, 0x7e, 0x27, 0xed, 0x6f, 0xc8, 0xd4, 0x82, 0x67, 0x7f,
- 0xc7, 0xb5, 0x1c, 0x32, 0xbf, 0x13, 0xf8, 0xdd, 0xaf, 0x7f, 0x4f, 0x15,
- 0x77, 0xed, 0x52, 0xde, 0x95, 0x92, 0x9d, 0xef, 0x94, 0x03, 0x85, 0x77,
- 0x58, 0xd9, 0x82, 0x4b, 0xbe, 0xe4, 0x98, 0x79, 0x26, 0xf4, 0xba, 0xe7,
- 0x8b, 0x39, 0x67, 0x94, 0xf0, 0xe3, 0xf7, 0x70, 0xa1, 0xcf, 0xdd, 0x24,
- 0xa4, 0x81, 0x29, 0x67, 0xb8, 0xe2, 0xa4, 0x23, 0x43, 0x3d, 0x89, 0x49,
- 0x39, 0x8c, 0xdf, 0xe2, 0x46, 0x86, 0xbe, 0x84, 0xbb, 0xc1, 0xc1, 0x57,
- 0xb6, 0x43, 0xb6, 0x16, 0x29, 0x2f, 0x3d, 0xcc, 0x3d, 0x29, 0x67, 0x56,
- 0xd8, 0x58, 0xc4, 0x85, 0x92, 0xec, 0x74, 0xea, 0x78, 0x4e, 0x52, 0xb9,
- 0x19, 0x30, 0xc4, 0x8d, 0x7e, 0x54, 0xde, 0xe7, 0x83, 0x76, 0xaf, 0x74,
- 0x64, 0xd7, 0x95, 0x51, 0xd8, 0x44, 0xde, 0xcc, 0x2e, 0xc8, 0x58, 0xc8,
- 0xbe, 0x08, 0xe9, 0x41, 0x9d, 0x92, 0xb1, 0xe8, 0x10, 0xb0, 0x7d, 0xaa,
- 0x7f, 0x64, 0xb2, 0x90, 0xbd, 0x5d, 0x0d, 0xed, 0xff, 0x6c, 0x66, 0xe0,
- 0xad, 0x92, 0xdd, 0xab, 0x80, 0xa3, 0xf6, 0x31, 0xc8, 0x4c, 0xcc, 0x2b,
- 0x08, 0x40, 0xcf, 0x90, 0xe7, 0x37, 0xdd, 0x14, 0x19, 0x6a, 0x90, 0xe1,
- 0xbd, 0xed, 0x68, 0xc3, 0x77, 0xc4, 0xd7, 0x79, 0xe0, 0x33, 0x95, 0x1c,
- 0x11, 0xb9, 0x7b, 0x6a, 0x60, 0xc9, 0x99, 0x2c, 0x7d, 0x10, 0x3c, 0x79,
- 0x15, 0xda, 0x3f, 0x80, 0xf6, 0x2f, 0x3b, 0xf9, 0xe9, 0x57, 0x9c, 0xc9,
- 0xe9, 0xbf, 0x75, 0xa6, 0xa6, 0xb7, 0x6c, 0xd9, 0x39, 0xb8, 0x65, 0xcb,
- 0xf8, 0x60, 0xd4, 0xea, 0x97, 0x2d, 0x5b, 0xa6, 0x06, 0x07, 0x81, 0x83,
- 0x3e, 0x77, 0x44, 0x3c, 0x77, 0x97, 0x80, 0x7f, 0xe2, 0x1c, 0x93, 0xfa,
- 0x27, 0x85, 0xf7, 0x6c, 0xef, 0xe9, 0xf7, 0xc3, 0xd2, 0x97, 0x68, 0x13,
- 0x8e, 0x1f, 0xb1, 0x75, 0xda, 0x01, 0xfb, 0x03, 0x76, 0x7d, 0x0b, 0xaa,
- 0xc1, 0x63, 0x39, 0xe7, 0xc2, 0x72, 0xae, 0xed, 0x8f, 0xac, 0x2d, 0xbb,
- 0x11, 0xe5, 0x7c, 0x26, 0xce, 0x88, 0x17, 0xda, 0x22, 0x0d, 0xda, 0x76,
- 0xcc, 0x16, 0x48, 0x33, 0x51, 0x99, 0x28, 0xb4, 0xa1, 0x0d, 0xe8, 0xe2,
- 0x94, 0xbd, 0x8e, 0x02, 0xb6, 0xbd, 0xe8, 0xeb, 0xe8, 0x21, 0xb4, 0xa3,
- 0xcc, 0x48, 0xf5, 0x8a, 0xfa, 0x04, 0xea, 0xf4, 0xb9, 0x9b, 0x85, 0x36,
- 0xc7, 0x71, 0xc9, 0x16, 0xc9, 0xdf, 0x3d, 0x80, 0x27, 0x26, 0xc9, 0x76,
- 0x3c, 0x57, 0x0e, 0xc0, 0x0e, 0x69, 0xb0, 0x3a, 0x33, 0x94, 0x17, 0xfc,
- 0x77, 0x87, 0x12, 0xef, 0x80, 0x8c, 0xcd, 0x5d, 0x8e, 0x7a, 0x0e, 0xf0,
- 0x42, 0x3b, 0x05, 0x36, 0xcb, 0x5c, 0x5a, 0x32, 0xdb, 0xee, 0xc5, 0xdd,
- 0xc5, 0x73, 0x1e, 0xf7, 0xb7, 0xe0, 0x3e, 0x89, 0x7b, 0x08, 0x27, 0xf0,
- 0xea, 0x47, 0xac, 0xce, 0xba, 0x06, 0x63, 0xff, 0x6b, 0xc9, 0x94, 0x12,
- 0xb4, 0x39, 0x36, 0x66, 0xbc, 0xb4, 0xab, 0x44, 0x6d, 0x56, 0x32, 0x85,
- 0xfa, 0xf0, 0x09, 0xbc, 0x83, 0x32, 0x7e, 0x12, 0xbf, 0x1f, 0xa4, 0x4d,
- 0x3c, 0x25, 0xe3, 0x73, 0x1c, 0xa7, 0x00, 0x98, 0x4a, 0x92, 0x3d, 0xf9,
- 0x00, 0xae, 0x69, 0x5c, 0x0f, 0xe3, 0xe2, 0xdc, 0xd8, 0xff, 0xe2, 0x26,
- 0x05, 0x5c, 0xf3, 0x39, 0x4b, 0x3a, 0xae, 0xe0, 0x37, 0x69, 0xb8, 0x42,
- 0xdb, 0x06, 0xf4, 0x5b, 0x09, 0xe9, 0xda, 0xb7, 0xbf, 0x13, 0x9a, 0xaf,
- 0x73, 0x6d, 0xa0, 0x99, 0xca, 0xa0, 0x96, 0x39, 0x19, 0x0f, 0xf7, 0x0a,
- 0x6c, 0x8f, 0x36, 0xce, 0xd1, 0xb3, 0x65, 0x9e, 0x2e, 0x4b, 0xea, 0xb2,
- 0x7e, 0x5b, 0x86, 0x7b, 0xa5, 0x41, 0xc6, 0xda, 0x01, 0x31, 0xe5, 0xb3,
- 0x84, 0xf8, 0xa4, 0x0c, 0x00, 0xfd, 0xc2, 0x66, 0x38, 0x73, 0x51, 0xf9,
- 0xb7, 0xa4, 0x6d, 0xb1, 0xc7, 0x2b, 0xa4, 0x63, 0xd2, 0x76, 0x10, 0xdc,
- 0xef, 0x37, 0xa1, 0x7f, 0xf2, 0xbc, 0x48, 0xc3, 0xd1, 0xa8, 0xcc, 0xb8,
- 0xa4, 0x85, 0x77, 0xb4, 0x90, 0x06, 0x1a, 0x3d, 0xd2, 0x70, 0x2d, 0x7f,
- 0x71, 0x0d, 0xd9, 0x5f, 0x0e, 0xf6, 0x1d, 0xed, 0xbc, 0x1e, 0xd8, 0xce,
- 0x1c, 0xe3, 0x30, 0x9f, 0x5d, 0x05, 0x9e, 0xca, 0x2c, 0xf3, 0x94, 0xc8,
- 0x6c, 0x81, 0xb8, 0x09, 0xed, 0x3f, 0xae, 0x33, 0xf1, 0xf3, 0x38, 0xe6,
- 0xcc, 0xfb, 0x19, 0x8b, 0xa7, 0x2f, 0x59, 0x3c, 0x7d, 0xd9, 0xde, 0x5d,
- 0x27, 0xab, 0x6d, 0xc1, 0x05, 0x3c, 0x73, 0x7d, 0xa2, 0x1a, 0x67, 0xd9,
- 0xc2, 0x0c, 0xee, 0xa8, 0x5b, 0x7c, 0x5c, 0xc6, 0xb5, 0x9d, 0x16, 0x91,
- 0x77, 0x69, 0xd9, 0x06, 0x21, 0xdd, 0x5c, 0x00, 0xcc, 0x0d, 0x92, 0x8b,
- 0x47, 0xf4, 0xda, 0x47, 0xbd, 0x03, 0x51, 0x43, 0xab, 0xc4, 0xc9, 0x0a,
- 0x5f, 0xaa, 0x06, 0xa6, 0xb8, 0x95, 0x73, 0x84, 0x8b, 0xb4, 0xfb, 0x88,
- 0x86, 0xeb, 0x16, 0xc8, 0xbb, 0x9c, 0xa8, 0xf6, 0x46, 0xb9, 0x0c, 0xb4,
- 0xa0, 0xe2, 0xd0, 0x5c, 0xc1, 0xd3, 0xb0, 0x9b, 0xb2, 0x73, 0xb4, 0xa1,
- 0xbb, 0xe8, 0xb7, 0xc4, 0xb2, 0xfd, 0xad, 0xa4, 0x23, 0xa5, 0x60, 0x7f,
- 0xe1, 0x59, 0x65, 0xfb, 0x35, 0x9d, 0x3a, 0xca, 0x8b, 0x6b, 0x3b, 0x19,
- 0xbc, 0x12, 0xb1, 0xbe, 0x73, 0x54, 0x79, 0x9b, 0x57, 0x97, 0x25, 0xa9,
- 0x87, 0xd1, 0x2e, 0x99, 0xed, 0x6f, 0x27, 0x8f, 0xb9, 0xca, 0x03, 0x2e,
- 0x3d, 0xed, 0x1b, 0xe5, 0xd4, 0xc0, 0xc6, 0x55, 0xf5, 0xf5, 0xdd, 0xb1,
- 0xcf, 0x51, 0x7b, 0x77, 0xed, 0x3d, 0x69, 0xef, 0xb9, 0xe8, 0x00, 0xef,
- 0x8e, 0x44, 0x87, 0x78, 0xc7, 0x1a, 0x0e, 0xb1, 0x0f, 0xcd, 0x57, 0x56,
- 0xce, 0xf4, 0xb8, 0x79, 0x21, 0x5f, 0xfd, 0xa9, 0xdc, 0x32, 0x67, 0xe4,
- 0xef, 0x2e, 0xc8, 0x20, 0xf8, 0x6f, 0xee, 0xa2, 0x00, 0xfe, 0xbd, 0x65,
- 0xb9, 0xa5, 0x42, 0xbc, 0xfd, 0x06, 0xf0, 0xb7, 0x35, 0x4a, 0xde, 0x74,
- 0x85, 0x72, 0xf7, 0x4e, 0xd1, 0xf6, 0x69, 0x81, 0x38, 0x3f, 0x2b, 0x5c,
- 0x9b, 0x7c, 0xe1, 0x19, 0xbd, 0x36, 0x07, 0x0b, 0x8b, 0xc0, 0xcf, 0xd7,
- 0x41, 0xf7, 0x41, 0xb0, 0xe8, 0xe7, 0x41, 0x39, 0x7f, 0x84, 0xdf, 0xe8,
- 0xbb, 0xf0, 0x1c, 0xde, 0xb7, 0x4a, 0xbe, 0x44, 0x9e, 0x8b, 0x5a, 0x1e,
- 0x3e, 0x05, 0x7e, 0xba, 0x0c, 0xfd, 0xa2, 0x6c, 0x80, 0xbf, 0xff, 0x11,
- 0xef, 0x70, 0x9f, 0xc3, 0x22, 0xb6, 0xd3, 0xd6, 0xe1, 0xd8, 0x5c, 0x3b,
- 0xae, 0x59, 0x5c, 0xfb, 0xad, 0x8f, 0x2f, 0xaf, 0x1b, 0xd7, 0x2b, 0xd5,
- 0x9b, 0x93, 0x70, 0xcd, 0x44, 0x1e, 0x2f, 0xb0, 0x3e, 0xe9, 0xff, 0x1f,
- 0x62, 0x46, 0x17, 0xfc, 0xc9, 0x3a, 0x73, 0x5f, 0xdd, 0x96, 0x6b, 0x5e,
- 0x4b, 0x83, 0xf4, 0x6f, 0x52, 0x83, 0x39, 0xc8, 0x9d, 0xa8, 0xd7, 0x2a,
- 0x23, 0xda, 0x27, 0x22, 0x4d, 0x90, 0x06, 0x6e, 0x56, 0x86, 0x36, 0x3f,
- 0xa4, 0x0c, 0x6d, 0x3e, 0x03, 0x5a, 0xc4, 0x55, 0x5c, 0x72, 0x0c, 0x6d,
- 0x7e, 0x1d, 0x77, 0x5c, 0xc5, 0x0b, 0x4e, 0xc8, 0xc7, 0xc3, 0xf0, 0xf9,
- 0x76, 0x15, 0xa2, 0xce, 0x78, 0x05, 0xf4, 0x5b, 0x8c, 0xa1, 0x7c, 0x81,
- 0x38, 0xc7, 0xfc, 0x39, 0xce, 0x56, 0xdb, 0xff, 0xe3, 0x32, 0x51, 0x0c,
- 0xb4, 0x5d, 0x95, 0x9d, 0xbb, 0x17, 0xf7, 0xf5, 0x5a, 0xce, 0x28, 0x2f,
- 0xad, 0x8c, 0xbc, 0x7a, 0x17, 0xee, 0xdd, 0x89, 0x83, 0xd2, 0xed, 0x46,
- 0xe4, 0x39, 0xf4, 0xf5, 0x43, 0x67, 0xa2, 0xf2, 0x32, 0xae, 0x9f, 0xe0,
- 0x7a, 0x15, 0xd7, 0x2b, 0xe8, 0xf7, 0x45, 0x94, 0xaf, 0x97, 0x05, 0xb7,
- 0x19, 0xf5, 0x45, 0x8d, 0x57, 0x5e, 0x70, 0xc6, 0x4e, 0xbe, 0x84, 0x2b,
- 0xaa, 0x26, 0x2a, 0xcf, 0x3b, 0xd9, 0xb9, 0x60, 0xe3, 0xa2, 0x47, 0x19,
- 0xf6, 0xa7, 0x8e, 0xe9, 0x7b, 0x08, 0x73, 0x00, 0x4d, 0x17, 0x17, 0x30,
- 0xf6, 0x33, 0x9a, 0x67, 0x46, 0x20, 0xf3, 0xb3, 0xb0, 0x4b, 0xc6, 0x34,
- 0x4c, 0x97, 0x03, 0x3e, 0xf8, 0xba, 0x03, 0xb8, 0xcf, 0x35, 0xca, 0x52,
- 0x9c, 0x76, 0xe4, 0x97, 0x75, 0xfd, 0x6c, 0xb1, 0x5b, 0xe3, 0x76, 0x66,
- 0x0d, 0xff, 0xd0, 0x3f, 0x0b, 0xe5, 0x81, 0x91, 0xc6, 0xb3, 0x05, 0xca,
- 0x02, 0xe8, 0x9f, 0xc2, 0x14, 0xee, 0x8d, 0x5a, 0x26, 0xe4, 0x25, 0x94,
- 0x07, 0x6c, 0x47, 0x99, 0x50, 0x2b, 0x77, 0x28, 0x6b, 0x28, 0x7b, 0x28,
- 0x4b, 0xcc, 0x7a, 0x8c, 0x3f, 0x48, 0x19, 0x7e, 0x2d, 0xfc, 0x53, 0xda,
- 0x1f, 0x9d, 0xc6, 0x07, 0x99, 0xce, 0x28, 0x23, 0x4f, 0xf7, 0xe8, 0xb5,
- 0x98, 0x28, 0xa8, 0x38, 0x20, 0x47, 0x19, 0xae, 0x63, 0x7b, 0x71, 0xcf,
- 0xaa, 0x09, 0x5c, 0xd9, 0x63, 0x1f, 0xc0, 0x6f, 0xae, 0xcd, 0x04, 0xea,
- 0xe1, 0x2a, 0x8e, 0xe2, 0x8e, 0x0b, 0xb6, 0x99, 0x91, 0x23, 0x5c, 0xd3,
- 0x84, 0x5d, 0xd3, 0x2f, 0x03, 0x0f, 0x9c, 0x9f, 0xd2, 0xf1, 0x07, 0xe5,
- 0xed, 0x00, 0xde, 0x2b, 0xd6, 0xdf, 0x6d, 0x15, 0xc3, 0x83, 0xb8, 0x7a,
- 0xc9, 0xcf, 0x2d, 0x66, 0xbd, 0x34, 0xed, 0x7e, 0x37, 0x6a, 0x78, 0x31,
- 0x8e, 0xb2, 0x08, 0xca, 0xda, 0x45, 0xf3, 0xfe, 0x32, 0x1e, 0xd3, 0x16,
- 0x8f, 0xfc, 0xad, 0xec, 0x6f, 0xd0, 0x13, 0x6c, 0xda, 0x8c, 0x37, 0x80,
- 0x71, 0x31, 0x97, 0x63, 0x7b, 0xd4, 0x38, 0xe4, 0xf7, 0xb8, 0x47, 0x19,
- 0xce, 0x38, 0x03, 0xe7, 0xc7, 0x7e, 0x51, 0xae, 0x71, 0xe0, 0x4b, 0xd5,
- 0x87, 0xff, 0x32, 0xd6, 0xec, 0x71, 0xd9, 0x57, 0xbc, 0x5a, 0xfb, 0xd4,
- 0x8d, 0x47, 0xcd, 0x7a, 0x88, 0x0a, 0xeb, 0xa1, 0xef, 0x38, 0x6d, 0x9b,
- 0x31, 0xfd, 0x3e, 0x7a, 0x94, 0xbf, 0x29, 0x9f, 0x6b, 0xe5, 0xbd, 0xb1,
- 0x6b, 0xf2, 0x2b, 0x64, 0x1d, 0x6d, 0x0b, 0xac, 0x59, 0xb9, 0x16, 0xef,
- 0xf4, 0xf1, 0x29, 0xf3, 0xc8, 0x4f, 0x07, 0xc1, 0x13, 0xaa, 0xc1, 0xf0,
- 0x3e, 0x7d, 0x8d, 0x7a, 0xfc, 0x04, 0xfb, 0x0b, 0xbc, 0x72, 0x02, 0xb6,
- 0xdb, 0xae, 0xe5, 0x3e, 0x20, 0x2b, 0xe3, 0x31, 0x39, 0x59, 0x68, 0x91,
- 0xb9, 0x82, 0x82, 0xc1, 0x60, 0x64, 0x67, 0x44, 0x12, 0x5a, 0xff, 0xd2,
- 0xbe, 0x1b, 0x9e, 0x8e, 0x58, 0xba, 0x83, 0xc3, 0xd2, 0xfc, 0x1b, 0xd0,
- 0xb1, 0x65, 0xe8, 0xd8, 0x56, 0xe8, 0xe0, 0xd5, 0x32, 0xa2, 0xab, 0x61,
- 0xad, 0x8c, 0x60, 0x9b, 0x14, 0xbc, 0xf2, 0x83, 0x68, 0x17, 0xd2, 0x5f,
- 0x4c, 0xd3, 0x5a, 0x56, 0x72, 0xce, 0xae, 0xca, 0x94, 0xb3, 0xbb, 0xb2,
- 0x5a, 0x07, 0xf5, 0xb9, 0x51, 0x31, 0xb0, 0x9e, 0xd4, 0x71, 0xbc, 0x94,
- 0x9f, 0x01, 0x4e, 0x76, 0x83, 0xee, 0x9e, 0x2e, 0xc1, 0x8f, 0xa7, 0x5c,
- 0x06, 0xcc, 0x8f, 0x01, 0xe6, 0xd9, 0x92, 0x13, 0xda, 0x06, 0xc2, 0xe0,
- 0xc9, 0xec, 0x74, 0xbf, 0x2c, 0xce, 0x93, 0x0e, 0x21, 0x03, 0x4a, 0x58,
- 0x4f, 0x7f, 0x1d, 0xec, 0x00, 0x8e, 0x0f, 0xb9, 0x3d, 0xdd, 0xa1, 0xdf,
- 0x19, 0x7d, 0xde, 0x29, 0x8b, 0xe5, 0xf7, 0x58, 0xd8, 0x0e, 0xd7, 0xc0,
- 0xb6, 0x6e, 0x19, 0xb6, 0xdd, 0x80, 0x6d, 0x4f, 0x5d, 0xd8, 0xea, 0xe9,
- 0xe2, 0x2e, 0xd8, 0x34, 0xe4, 0x8f, 0x10, 0xaf, 0xed, 0x96, 0x1e, 0x6e,
- 0xb7, 0xf6, 0x2e, 0x6d, 0xa2, 0x9f, 0x02, 0x1e, 0xd2, 0x18, 0x7e, 0xcf,
- 0x3d, 0x4a, 0x59, 0x86, 0x72, 0x3e, 0x7f, 0x06, 0x75, 0xf0, 0x3c, 0xf7,
- 0xe7, 0x56, 0x0e, 0xde, 0x65, 0x61, 0xa1, 0x9d, 0x90, 0x86, 0x4d, 0x3c,
- 0xe2, 0x64, 0xe6, 0x08, 0x43, 0x0e, 0xf0, 0xe2, 0x5d, 0xa5, 0xb6, 0x4f,
- 0xde, 0xd9, 0xef, 0x15, 0xb6, 0x1f, 0xf6, 0x1d, 0xce, 0x65, 0xbd, 0xd5,
- 0xf3, 0x21, 0x7d, 0x85, 0xf6, 0xf5, 0x94, 0x93, 0x5e, 0x33, 0xaf, 0x5a,
- 0x9a, 0xa3, 0xbc, 0x8d, 0xca, 0x4e, 0xd0, 0xc9, 0xce, 0x15, 0xb4, 0xa6,
- 0xdd, 0x10, 0x4b, 0xc7, 0xeb, 0xec, 0xfc, 0x0e, 0x18, 0xbe, 0xf1, 0x63,
- 0xd0, 0x87, 0x94, 0x37, 0x37, 0x1b, 0xdf, 0x5c, 0x4e, 0x00, 0xd6, 0xf0,
- 0x99, 0xb4, 0xc9, 0xdf, 0x94, 0x49, 0x55, 0x5a, 0x34, 0xbe, 0x4b, 0xa7,
- 0x8e, 0x9f, 0x56, 0xed, 0xf5, 0xa8, 0x8c, 0x9a, 0x35, 0x3f, 0xcc, 0x35,
- 0xa7, 0x2f, 0xd2, 0xfd, 0xc0, 0xa8, 0xe5, 0xaf, 0x54, 0x29, 0x27, 0xbb,
- 0xed, 0xdc, 0xbf, 0x5c, 0x67, 0xed, 0x5a, 0x97, 0xd7, 0x6e, 0xb4, 0xb2,
- 0x7a, 0x8e, 0x22, 0x5d, 0x0f, 0x44, 0xb5, 0x6f, 0x2b, 0xca, 0x97, 0x46,
- 0x8f, 0xf2, 0x93, 0xb6, 0x12, 0xca, 0x67, 0xfb, 0xdc, 0x36, 0xd0, 0xdb,
- 0x53, 0x6b, 0xec, 0xae, 0xa4, 0x95, 0x9b, 0xf4, 0x83, 0xc3, 0x31, 0x72,
- 0x56, 0x4e, 0xe6, 0xd0, 0xff, 0x94, 0xb3, 0xb3, 0x52, 0x4f, 0x5e, 0x86,
- 0x72, 0x92, 0xf3, 0xb9, 0x57, 0xee, 0x78, 0x90, 0x3c, 0x7a, 0xbb, 0xb6,
- 0xaf, 0xaf, 0xda, 0x71, 0x00, 0xf8, 0x23, 0xfc, 0x8b, 0x9b, 0x60, 0x32,
- 0x40, 0xe7, 0xa6, 0x65, 0xdc, 0xae, 0xdb, 0xf8, 0xf2, 0xfa, 0xf3, 0x6a,
- 0xc7, 0x6f, 0xc6, 0x59, 0x95, 0x85, 0x59, 0xdb, 0xb1, 0xb0, 0xeb, 0x56,
- 0xdb, 0xb2, 0x9c, 0x03, 0xed, 0xd9, 0x46, 0x63, 0x0b, 0x16, 0x69, 0x7f,
- 0x52, 0x76, 0xd1, 0xfe, 0x8c, 0x35, 0x4a, 0x33, 0xe7, 0x33, 0x68, 0xcb,
- 0x68, 0xa7, 0xae, 0x9e, 0xdf, 0x6a, 0xff, 0x91, 0x70, 0x12, 0x6e, 0x43,
- 0x5b, 0x49, 0x45, 0xd8, 0x02, 0x19, 0xf5, 0xaf, 0xd5, 0x6b, 0xa0, 0x68,
- 0xbb, 0xee, 0xf8, 0x76, 0x83, 0x89, 0x31, 0x27, 0xd1, 0x3f, 0xc7, 0x24,
- 0xff, 0xf1, 0x4e, 0x3b, 0xbf, 0x9e, 0x2c, 0xab, 0xd5, 0x3d, 0x97, 0x2d,
- 0xe3, 0x6f, 0xe7, 0x8a, 0x35, 0x0a, 0xf1, 0x17, 0xd2, 0x45, 0x2d, 0x0e,
- 0x49, 0x13, 0xa4, 0x85, 0x90, 0x16, 0xb7, 0x5a, 0x7d, 0x13, 0xd2, 0xde,
- 0xa5, 0xa0, 0xbd, 0xfb, 0x80, 0x27, 0xca, 0x70, 0xc6, 0xed, 0x36, 0xe3,
- 0xf9, 0x08, 0x9e, 0x43, 0x3e, 0xb9, 0x98, 0x0c, 0xa7, 0xfc, 0x66, 0x9b,
- 0x8c, 0x95, 0xfb, 0xa1, 0x9f, 0xcb, 0x36, 0x9c, 0x37, 0xe5, 0xff, 0x57,
- 0xe9, 0x77, 0x35, 0x1a, 0x3b, 0xfd, 0x43, 0x8d, 0x94, 0xaf, 0x9b, 0xe4,
- 0x60, 0x4d, 0xd9, 0xc5, 0xe4, 0x77, 0xed, 0x9c, 0x2f, 0xff, 0x7f, 0x30,
- 0xe7, 0xc4, 0xaa, 0x39, 0xbb, 0x76, 0xce, 0x15, 0xbc, 0x6f, 0xc3, 0xfb,
- 0x16, 0xea, 0x82, 0x64, 0x55, 0xde, 0x58, 0x5c, 0xe8, 0x79, 0xd5, 0xca,
- 0x89, 0x50, 0x46, 0x70, 0x5e, 0x1f, 0xb1, 0x73, 0x78, 0xa0, 0x66, 0x5e,
- 0x1f, 0x79, 0x13, 0xf3, 0xea, 0x5c, 0x31, 0xaf, 0x5d, 0x17, 0x9d, 0x57,
- 0x3d, 0x1e, 0x27, 0x2f, 0x87, 0xf3, 0x8b, 0xc9, 0x8d, 0x05, 0xce, 0x71,
- 0x27, 0xe6, 0x48, 0x18, 0xc2, 0x39, 0x0e, 0xd9, 0x39, 0x8a, 0xea, 0xda,
- 0xf1, 0x73, 0xf8, 0x5d, 0x3b, 0x3f, 0xea, 0xfe, 0x1f, 0x83, 0xa6, 0x9b,
- 0x24, 0xd3, 0xdf, 0x64, 0xe5, 0xff, 0x97, 0xe5, 0xd6, 0x22, 0xd7, 0x3a,
- 0x95, 0x16, 0xd9, 0xa3, 0xf6, 0x15, 0x9f, 0x6d, 0x64, 0x8c, 0x7f, 0x97,
- 0x6f, 0xf5, 0x18, 0xf4, 0xc5, 0x6e, 0xd8, 0x7c, 0x3b, 0x0b, 0x6a, 0x20,
- 0x22, 0x41, 0x70, 0x9b, 0xdf, 0x8c, 0xb1, 0x37, 0x6a, 0x5f, 0x75, 0x6d,
- 0x7c, 0xfd, 0x99, 0x46, 0xf1, 0x68, 0x6f, 0x50, 0x9f, 0x43, 0xdf, 0x1d,
- 0xa3, 0x0d, 0x96, 0x81, 0x9d, 0x9c, 0x4e, 0x44, 0xb4, 0x2d, 0x46, 0x9d,
- 0x98, 0x4a, 0xa4, 0xa5, 0x2c, 0xd9, 0x63, 0xe9, 0x84, 0x12, 0x8e, 0x01,
- 0x5b, 0x0d, 0x36, 0xe4, 0xad, 0x90, 0x35, 0xb7, 0x56, 0xf6, 0xaa, 0x5b,
- 0x60, 0xef, 0xdc, 0x72, 0xf2, 0x03, 0xea, 0x36, 0xd8, 0x3a, 0xb7, 0x9d,
- 0xbc, 0x41, 0xed, 0x83, 0x6d, 0xb3, 0x0f, 0x76, 0xce, 0xbe, 0x0a, 0x6d,
- 0xcf, 0x9b, 0x41, 0x7b, 0x9d, 0x35, 0xb4, 0x46, 0x1b, 0x87, 0xf3, 0x23,
- 0xee, 0x8f, 0x71, 0x0d, 0xfc, 0xa4, 0x7a, 0x45, 0xaf, 0x4b, 0xdb, 0x8a,
- 0xb2, 0xd7, 0x92, 0x55, 0xa1, 0x7e, 0xda, 0x60, 0xe3, 0x46, 0x94, 0xb7,
- 0xaf, 0x45, 0x5b, 0xa4, 0x11, 0x17, 0x78, 0x26, 0xfe, 0x48, 0x5b, 0xb5,
- 0xf3, 0xdf, 0xd4, 0x24, 0x5e, 0x67, 0x93, 0x34, 0xdf, 0x0b, 0xf9, 0x5a,
- 0x4b, 0x53, 0xbc, 0xbb, 0x56, 0xd7, 0x90, 0xb6, 0x28, 0x83, 0x43, 0x7a,
- 0xd8, 0xfa, 0x1a, 0xf2, 0xf7, 0xa2, 0xf4, 0x74, 0x4f, 0x64, 0x28, 0x08,
- 0xc6, 0x07, 0x64, 0x23, 0xe3, 0x01, 0x99, 0x4a, 0x35, 0x26, 0xa0, 0xbc,
- 0xda, 0x98, 0x00, 0xfd, 0xac, 0x47, 0x80, 0xdf, 0x19, 0x5c, 0x22, 0x63,
- 0x8c, 0x3b, 0x54, 0x42, 0xbb, 0xfc, 0x1b, 0xd6, 0x2e, 0x0f, 0xe1, 0x48,
- 0x02, 0x0e, 0x23, 0x9f, 0xd7, 0xea, 0xb9, 0x95, 0xfa, 0x3b, 0xb7, 0x6c,
- 0xd3, 0x26, 0xe5, 0xc6, 0x22, 0xe7, 0x4d, 0x19, 0x4c, 0xdc, 0xd4, 0xca,
- 0xe0, 0x84, 0xb5, 0xa3, 0x50, 0x47, 0xcb, 0xcf, 0xb5, 0xb2, 0x93, 0x72,
- 0x8f, 0xf1, 0xf9, 0x07, 0x7c, 0xd2, 0xfa, 0x7b, 0x24, 0xbd, 0x1c, 0x9f,
- 0x17, 0xd0, 0x9b, 0xf8, 0x91, 0x21, 0xbd, 0xdf, 0xe6, 0xce, 0xca, 0x6e,
- 0x19, 0x8e, 0x33, 0xd6, 0xc9, 0x78, 0x9e, 0x97, 0x9b, 0x05, 0x0f, 0x4c,
- 0x16, 0x15, 0x2c, 0xf8, 0x46, 0x19, 0x73, 0x03, 0xd9, 0xe5, 0x3b, 0x3a,
- 0x76, 0x6c, 0x74, 0xed, 0x4c, 0x93, 0xb1, 0x5d, 0x1d, 0x1d, 0xff, 0x5d,
- 0x04, 0xf5, 0x2d, 0x6a, 0xfb, 0x56, 0x69, 0xfd, 0xbb, 0xa0, 0xeb, 0x7c,
- 0xae, 0x29, 0x8c, 0x63, 0x2e, 0xba, 0x11, 0x5b, 0xaf, 0xb6, 0xfc, 0x8b,
- 0x36, 0x3e, 0x9d, 0x84, 0xec, 0x0f, 0xcb, 0xfe, 0xb0, 0x4e, 0xd9, 0xb7,
- 0xea, 0x94, 0xfd, 0xcf, 0x3a, 0x65, 0x26, 0x2e, 0xb8, 0xb3, 0xf0, 0xf7,
- 0x78, 0x37, 0xa5, 0x7d, 0x77, 0xb1, 0xfb, 0x61, 0xb9, 0xe5, 0x3a, 0x1b,
- 0xac, 0x5f, 0xc6, 0x18, 0xb1, 0x89, 0x0d, 0x67, 0x75, 0x6c, 0xb8, 0xcf,
- 0xdd, 0xa1, 0xf4, 0x5e, 0xca, 0x7e, 0xc6, 0x19, 0xf7, 0x69, 0xbc, 0x10,
- 0x27, 0x5f, 0x61, 0x0c, 0x38, 0xc7, 0xbd, 0xd8, 0xa4, 0xba, 0x18, 0x6d,
- 0x57, 0x6d, 0x13, 0xb3, 0x6e, 0xb4, 0x8b, 0x5b, 0x64, 0x04, 0xb6, 0xc2,
- 0xce, 0x42, 0x9b, 0xec, 0x9a, 0x1e, 0x58, 0x47, 0xbd, 0xb5, 0x7b, 0xda,
- 0xf8, 0x83, 0xfb, 0xc0, 0x57, 0x69, 0x21, 0x8c, 0x29, 0x5f, 0x84, 0x36,
- 0xf1, 0x5a, 0x5b, 0xf8, 0xb5, 0xfb, 0xfb, 0xa5, 0x8b, 0xf4, 0xe7, 0xc0,
- 0x76, 0x78, 0xa3, 0xfd, 0x35, 0xcb, 0xc8, 0x74, 0x88, 0x2b, 0xf5, 0x33,
- 0xb6, 0x8b, 0x5c, 0xa4, 0x9d, 0xb6, 0x4b, 0xe4, 0xe9, 0x65, 0x59, 0xbc,
- 0x15, 0x36, 0x93, 0x04, 0x99, 0x01, 0xe9, 0x8c, 0x88, 0x8e, 0xf1, 0xf8,
- 0x46, 0x36, 0xf7, 0x70, 0x6f, 0x07, 0xf4, 0x6f, 0x6c, 0x15, 0x13, 0x37,
- 0x0d, 0xed, 0x94, 0x7a, 0xb4, 0x7b, 0x9d, 0xa5, 0x5d, 0xee, 0xb9, 0xee,
- 0xa6, 0xcc, 0xd5, 0x6b, 0x42, 0x3a, 0xde, 0x55, 0x90, 0x64, 0x48, 0xc7,
- 0x8b, 0x92, 0x5e, 0x41, 0xc7, 0x8b, 0x32, 0xa4, 0xe9, 0xb8, 0x71, 0x05,
- 0x1d, 0x77, 0x5a, 0x3a, 0xde, 0x13, 0x33, 0x74, 0xa1, 0xb4, 0x9e, 0x22,
- 0x9d, 0x1a, 0x3a, 0x76, 0x34, 0x1d, 0x2f, 0xe2, 0x1e, 0xf5, 0xae, 0xb3,
- 0x75, 0x22, 0xb6, 0x8c, 0xbf, 0xc3, 0x32, 0xca, 0xc5, 0x4f, 0xc6, 0x8c,
- 0x5e, 0x1a, 0x02, 0x1d, 0x85, 0xe5, 0xfb, 0x6d, 0xfc, 0xa0, 0xb6, 0xcc,
- 0xc4, 0x47, 0x76, 0x16, 0xc6, 0x62, 0x2b, 0xe9, 0x73, 0x08, 0xf4, 0x19,
- 0xd6, 0x79, 0x2d, 0xfa, 0x6c, 0xb6, 0xfb, 0x16, 0x71, 0xbd, 0x2f, 0x9f,
- 0x8e, 0x1b, 0x5a, 0xbd, 0x45, 0xcf, 0x9d, 0xf3, 0x3e, 0xfb, 0x06, 0x68,
- 0xd5, 0xac, 0xcd, 0xb9, 0xaa, 0xbf, 0xcd, 0x58, 0x54, 0xd2, 0xc4, 0xb0,
- 0x19, 0x27, 0xbd, 0x98, 0xed, 0x68, 0xe4, 0x53, 0x83, 0x96, 0x4f, 0xad,
- 0x63, 0xcc, 0x35, 0xa8, 0xca, 0xec, 0x01, 0xe8, 0x0a, 0xda, 0xd8, 0x5a,
- 0x4e, 0xe3, 0x5d, 0x67, 0x32, 0x53, 0x78, 0x35, 0x88, 0x78, 0x8c, 0x0f,
- 0x71, 0x5f, 0x40, 0xc6, 0x1c, 0x94, 0x75, 0x95, 0xcd, 0xbc, 0x94, 0xd7,
- 0x8a, 0xe7, 0x01, 0xe9, 0x2a, 0x2b, 0xf9, 0xe8, 0x74, 0x8b, 0xec, 0x2f,
- 0x44, 0xe5, 0xe3, 0x68, 0xff, 0xb1, 0x82, 0x0b, 0x7f, 0xfc, 0x4c, 0x8c,
- 0x76, 0xe1, 0xbe, 0x02, 0xf7, 0x27, 0x59, 0x37, 0xbe, 0x6a, 0x7f, 0x36,
- 0x22, 0x5d, 0x3d, 0x79, 0x78, 0x2a, 0x12, 0xdd, 0x03, 0x38, 0x9a, 0x86,
- 0x86, 0xe4, 0x07, 0x03, 0x1b, 0x51, 0xf6, 0xb2, 0x1d, 0x6f, 0xd4, 0x31,
- 0xf1, 0xde, 0x41, 0x79, 0x77, 0x65, 0x48, 0xae, 0xaf, 0x98, 0x3d, 0xd5,
- 0xea, 0x9e, 0x69, 0xca, 0x5d, 0x80, 0xfe, 0x49, 0xbb, 0x41, 0x70, 0xce,
- 0xc3, 0xaa, 0x1f, 0x89, 0x4a, 0xac, 0x27, 0x95, 0x58, 0x10, 0xf3, 0x7c,
- 0xbe, 0xfc, 0x0f, 0xc1, 0x58, 0x3c, 0x2a, 0x3f, 0xf0, 0x38, 0xc7, 0x41,
- 0xb9, 0xae, 0x5c, 0x3b, 0x36, 0x97, 0xf3, 0x0f, 0x63, 0xdc, 0xa7, 0xc8,
- 0x54, 0x16, 0x62, 0x8c, 0xa5, 0xd3, 0xe7, 0xe8, 0x7a, 0x1b, 0xfc, 0x38,
- 0x48, 0xee, 0xae, 0xb7, 0x81, 0x6e, 0xe2, 0xd0, 0xf9, 0x57, 0x01, 0xc6,
- 0xab, 0x18, 0xfb, 0x62, 0xcc, 0x8b, 0xcf, 0x5f, 0xc7, 0xb8, 0x6c, 0xfb,
- 0x1b, 0xd6, 0x5e, 0xe6, 0xfa, 0x1b, 0xde, 0xa9, 0xaf, 0x77, 0x5a, 0xc7,
- 0x62, 0x43, 0xe2, 0xc4, 0xde, 0x91, 0x90, 0x75, 0x5e, 0xed, 0xf8, 0xdc,
- 0x27, 0x86, 0xc5, 0x38, 0x20, 0xd1, 0xdd, 0xdb, 0x07, 0x65, 0x04, 0xf3,
- 0xdb, 0xb9, 0x66, 0x7e, 0xf7, 0x08, 0xe3, 0xab, 0xe7, 0x0b, 0x9c, 0x43,
- 0x75, 0x5e, 0xea, 0x0b, 0x66, 0x5e, 0xb1, 0x9e, 0xd5, 0xf3, 0xd1, 0xed,
- 0xd5, 0x09, 0xc0, 0xf2, 0x35, 0x9d, 0x57, 0x10, 0x04, 0x6f, 0xed, 0x39,
- 0x1f, 0x24, 0x2f, 0x49, 0xf5, 0x2e, 0x54, 0xf7, 0x77, 0xc6, 0x22, 0x43,
- 0x69, 0xad, 0xcf, 0xf0, 0x9c, 0xcc, 0x96, 0xd3, 0x58, 0x47, 0x89, 0x66,
- 0xfb, 0xa3, 0x9a, 0x4f, 0xb2, 0x5e, 0xda, 0xee, 0x61, 0x85, 0x3e, 0x54,
- 0x10, 0x28, 0x6f, 0xb5, 0xdc, 0xa0, 0xbe, 0xc2, 0xdc, 0xe5, 0xdf, 0xda,
- 0x1c, 0x96, 0x5e, 0xc6, 0xb3, 0xc6, 0xa2, 0x43, 0xb1, 0x64, 0xbe, 0xec,
- 0xe1, 0x77, 0x0b, 0xee, 0x3b, 0x60, 0xaf, 0xf8, 0xb0, 0x67, 0x24, 0xae,
- 0x8c, 0x6c, 0x00, 0x2d, 0xf7, 0xe4, 0x94, 0x22, 0x6f, 0xba, 0xc9, 0xc9,
- 0x72, 0x3c, 0x59, 0x2a, 0x7f, 0x96, 0xed, 0x51, 0xb7, 0x5e, 0x2c, 0xcf,
- 0xc8, 0x86, 0xa7, 0x2a, 0x1c, 0x83, 0xfe, 0xef, 0x1b, 0x19, 0x23, 0x6a,
- 0xfb, 0x66, 0x9f, 0x21, 0x5e, 0xa2, 0x74, 0xc9, 0xf1, 0x2f, 0x6d, 0x7d,
- 0x13, 0xce, 0xef, 0xb3, 0x16, 0xee, 0xd5, 0xe3, 0xbe, 0xa0, 0xed, 0x97,
- 0xd3, 0x15, 0xda, 0x8c, 0xdc, 0xdf, 0x49, 0x1d, 0x9f, 0x11, 0xc2, 0x11,
- 0x04, 0xcf, 0xf9, 0x46, 0x77, 0x3f, 0x55, 0xe1, 0x1e, 0x47, 0x10, 0xfc,
- 0x88, 0x76, 0xf1, 0xde, 0x22, 0xc6, 0x0b, 0x71, 0xb0, 0x35, 0x17, 0x85,
- 0x5c, 0x9c, 0x1a, 0x20, 0x7e, 0x05, 0x1e, 0x6a, 0x8f, 0x7b, 0xa3, 0xc4,
- 0x92, 0x9f, 0x2a, 0xb7, 0x24, 0x3f, 0x5d, 0x76, 0x81, 0x67, 0xce, 0x3b,
- 0x9e, 0x9c, 0xb0, 0x73, 0xce, 0x96, 0x89, 0xdf, 0xd7, 0xda, 0x87, 0x7c,
- 0x61, 0x85, 0xbf, 0x44, 0x98, 0xaa, 0xb0, 0x10, 0xb6, 0xa4, 0xc5, 0x4d,
- 0x10, 0xfc, 0xd8, 0x37, 0x6b, 0x3a, 0x55, 0x94, 0x29, 0x8c, 0x9b, 0xdb,
- 0xac, 0x88, 0x87, 0x58, 0xf2, 0x0e, 0x8c, 0xfd, 0x29, 0x8c, 0xbd, 0xbf,
- 0xcc, 0xf1, 0x20, 0x2b, 0x30, 0xf7, 0xa9, 0x4a, 0x08, 0x6f, 0xbd, 0xb1,
- 0xc3, 0x35, 0xef, 0xb5, 0x36, 0x5e, 0xf8, 0xac, 0x11, 0xd9, 0xae, 0xbc,
- 0x7e, 0xd0, 0xd7, 0xe2, 0xa6, 0xa8, 0xfc, 0x22, 0xe4, 0x6e, 0x20, 0x8f,
- 0x42, 0x9e, 0x2d, 0x6a, 0xba, 0xc9, 0x5c, 0xce, 0xff, 0x23, 0xf2, 0xeb,
- 0xeb, 0x18, 0x5f, 0x1e, 0xf6, 0x68, 0xbb, 0x2e, 0x05, 0x8b, 0x1e, 0xe5,
- 0xf3, 0x06, 0x99, 0x71, 0x73, 0xbd, 0xd0, 0x15, 0x28, 0x6b, 0xa5, 0xbf,
- 0x9d, 0xcc, 0x44, 0x52, 0xc9, 0x49, 0x61, 0x3e, 0x14, 0x73, 0x15, 0x98,
- 0x23, 0x44, 0xd9, 0x10, 0x85, 0xcc, 0xe3, 0x1a, 0x9a, 0xf1, 0x26, 0xcb,
- 0xd5, 0xba, 0x07, 0x84, 0x7b, 0x86, 0xa9, 0xc4, 0x3e, 0x6d, 0x9f, 0x88,
- 0x8c, 0x17, 0x58, 0x77, 0x3b, 0xac, 0x13, 0xaf, 0xa6, 0xbe, 0xce, 0xe1,
- 0x02, 0x9f, 0x87, 0x71, 0xac, 0x58, 0x2c, 0x53, 0x90, 0x97, 0x23, 0x03,
- 0xf2, 0x32, 0xed, 0xce, 0x61, 0xd0, 0xb6, 0xeb, 0xf1, 0xbd, 0x29, 0xcf,
- 0xf8, 0xb2, 0x94, 0x19, 0xec, 0xa3, 0x9d, 0x9d, 0x53, 0x9a, 0x27, 0x44,
- 0xa1, 0x6d, 0x2c, 0x5b, 0x96, 0x91, 0x6c, 0xc1, 0xc6, 0x7a, 0x46, 0x39,
- 0xe7, 0x0d, 0x35, 0x73, 0x6f, 0x95, 0x28, 0x60, 0x1a, 0x89, 0x24, 0x9d,
- 0x06, 0xef, 0x23, 0x2d, 0x46, 0xe7, 0x43, 0xee, 0xb7, 0xdd, 0xdf, 0xce,
- 0x3d, 0x53, 0x05, 0x1f, 0x5a, 0xb5, 0xdf, 0x7e, 0x8d, 0x1a, 0xfa, 0xf3,
- 0x04, 0xf4, 0xa0, 0x95, 0x95, 0xb1, 0x91, 0xae, 0x65, 0xfa, 0xe6, 0xf8,
- 0xd2, 0x1e, 0xf1, 0x92, 0x23, 0xc3, 0x65, 0x51, 0x91, 0x21, 0x37, 0x36,
- 0x5c, 0x5e, 0x49, 0xf3, 0x4f, 0x55, 0xfe, 0xbd, 0xb5, 0x05, 0x6b, 0x63,
- 0xaa, 0xb5, 0xef, 0xc8, 0x77, 0x2b, 0xf6, 0x2b, 0x92, 0x26, 0x07, 0x86,
- 0xfb, 0xb4, 0x5c, 0x93, 0xf4, 0x5b, 0x1b, 0xa0, 0x7c, 0x66, 0xb4, 0x8f,
- 0xc6, 0x9c, 0x8b, 0x98, 0xcd, 0x3d, 0x33, 0xb8, 0x4e, 0x97, 0x1d, 0x99,
- 0x82, 0x7c, 0x38, 0x20, 0x7f, 0x1f, 0xa4, 0xe3, 0xe6, 0xbd, 0x59, 0x5f,
- 0xd6, 0xe7, 0x5e, 0x44, 0xb3, 0xe4, 0x4f, 0x46, 0x25, 0x77, 0x92, 0x7b,
- 0x60, 0xcf, 0xed, 0xaf, 0xe6, 0x6d, 0x50, 0x0e, 0x70, 0xbf, 0xd6, 0x91,
- 0x3c, 0xfc, 0xda, 0x11, 0xee, 0xc3, 0xf7, 0xff, 0x1f, 0xf4, 0xc1, 0x7a,
- 0x61, 0xdb, 0x16, 0xb4, 0x6d, 0xb4, 0x6d, 0x47, 0xef, 0x78, 0x73, 0x6d,
- 0x5b, 0xd1, 0x36, 0x16, 0x8e, 0xfb, 0x06, 0xdb, 0x6a, 0x7c, 0x5e, 0x33,
- 0x5c, 0x28, 0x2e, 0xc1, 0x4f, 0x4e, 0x4c, 0x48, 0xda, 0x19, 0x1f, 0xd0,
- 0xf3, 0xb9, 0x66, 0xb8, 0x0c, 0x38, 0xe2, 0x41, 0x90, 0xf7, 0x43, 0x3d,
- 0xcc, 0x7f, 0xc7, 0x44, 0x3c, 0x96, 0x71, 0xdf, 0x92, 0xfe, 0x04, 0xa3,
- 0xa4, 0x2e, 0xf3, 0xd9, 0x24, 0xcf, 0xfd, 0xc9, 0xf8, 0x46, 0xdc, 0x55,
- 0x17, 0x71, 0x92, 0xf5, 0x18, 0xef, 0xdd, 0x68, 0xcb, 0x23, 0x2c, 0x4f,
- 0x45, 0x21, 0x4b, 0x4c, 0x79, 0xc4, 0x96, 0x03, 0x26, 0x3f, 0x9f, 0x04,
- 0xb7, 0xd9, 0x72, 0x3e, 0x2b, 0x5d, 0x6e, 0x9e, 0x0d, 0x0f, 0x8d, 0x09,
- 0xe3, 0x3a, 0x99, 0xeb, 0x1a, 0x64, 0x2b, 0xd6, 0x87, 0x3e, 0xa3, 0x23,
- 0xcd, 0x80, 0xe3, 0x9c, 0xff, 0x76, 0xd8, 0xd6, 0x81, 0xfc, 0xc0, 0x37,
- 0xf4, 0x3f, 0x2b, 0x3d, 0x69, 0xe5, 0x30, 0x07, 0x20, 0x90, 0x9d, 0xfe,
- 0xb6, 0xc4, 0x2e, 0xfc, 0x1e, 0xef, 0x4f, 0xca, 0xec, 0x20, 0xe8, 0xb1,
- 0x9f, 0xbc, 0xb1, 0x15, 0x36, 0x0f, 0x7e, 0xf7, 0xb4, 0xc8, 0x92, 0x9b,
- 0x73, 0xd7, 0xc1, 0x5f, 0x1b, 0xc1, 0xac, 0xe6, 0x0a, 0x9e, 0x7b, 0x1b,
- 0x84, 0x5c, 0xda, 0xed, 0xc1, 0xbd, 0x76, 0xbe, 0xdf, 0xc2, 0x7c, 0x7f,
- 0xad, 0x59, 0x9a, 0x59, 0x5e, 0x5b, 0xb7, 0x51, 0xf6, 0xb8, 0xdb, 0xdd,
- 0xd8, 0x8a, 0xba, 0xe7, 0x51, 0x97, 0x65, 0x9e, 0xcb, 0x1c, 0x9d, 0xd9,
- 0x32, 0xe9, 0xcc, 0xc0, 0xda, 0xd5, 0x13, 0x04, 0xd7, 0xf9, 0x1c, 0x37,
- 0x08, 0xae, 0xf7, 0xfb, 0xdc, 0x67, 0xe5, 0xf9, 0xc0, 0xd8, 0x54, 0x21,
- 0xed, 0x3c, 0x67, 0xe5, 0x75, 0x10, 0xbc, 0xec, 0xf7, 0xca, 0xef, 0x54,
- 0x52, 0x8f, 0xd3, 0xe7, 0x3e, 0x83, 0xe7, 0x33, 0xbe, 0xc9, 0x2b, 0xfa,
- 0x13, 0xb4, 0x8b, 0xab, 0x7e, 0xd0, 0xb0, 0x27, 0x5f, 0xd4, 0x3e, 0x3a,
- 0xf1, 0x67, 0x62, 0xfc, 0x55, 0x18, 0x30, 0x61, 0x2f, 0xb3, 0xc9, 0x65,
- 0x7e, 0xa0, 0xa6, 0xdf, 0xda, 0x77, 0x0a, 0xef, 0x58, 0x16, 0x04, 0x97,
- 0x0c, 0xfc, 0x31, 0xe6, 0x94, 0x2a, 0x71, 0xef, 0xee, 0x03, 0x9a, 0xff,
- 0x04, 0x7e, 0x3d, 0xe9, 0x24, 0xea, 0x2a, 0xe5, 0x1d, 0xee, 0x52, 0xa9,
- 0x9c, 0xc8, 0x5b, 0xb0, 0xfe, 0x5c, 0x63, 0x30, 0x48, 0x1b, 0x60, 0xdf,
- 0xb6, 0xbd, 0xd9, 0xc4, 0x92, 0xe8, 0x4b, 0xa7, 0x37, 0xc1, 0xd7, 0xd5,
- 0xf6, 0x4c, 0x14, 0x7c, 0x3d, 0xd1, 0x16, 0x04, 0xef, 0xf7, 0xc3, 0x35,
- 0xb3, 0xb1, 0x6a, 0xe8, 0xf8, 0x6c, 0xff, 0xb9, 0x66, 0x63, 0xc7, 0x31,
- 0x4f, 0x30, 0xa9, 0xe3, 0xfa, 0xaa, 0x1d, 0x3a, 0x64, 0xdb, 0x57, 0x39,
- 0x7e, 0x8e, 0xe5, 0xef, 0xf3, 0x43, 0x98, 0xaa, 0xed, 0xb3, 0xfd, 0xeb,
- 0xac, 0xcd, 0x19, 0x05, 0x2e, 0x3d, 0xb7, 0x4b, 0xfd, 0x4d, 0x60, 0x74,
- 0x6b, 0x48, 0xc3, 0x7f, 0x17, 0x3c, 0x18, 0x37, 0xcf, 0x99, 0x6d, 0xec,
- 0x63, 0xab, 0x4c, 0x6e, 0xc3, 0x73, 0xf4, 0x5a, 0xdc, 0x87, 0x2f, 0x8b,
- 0xc8, 0x15, 0x89, 0x61, 0xb5, 0xcd, 0x7d, 0x50, 0xfa, 0xac, 0x8c, 0xfb,
- 0x1a, 0xf4, 0x7d, 0x0e, 0xfe, 0x78, 0x93, 0x3c, 0x08, 0x9a, 0x56, 0x03,
- 0xa9, 0xe4, 0x82, 0x4a, 0xf5, 0xce, 0xa8, 0x94, 0x3f, 0xa6, 0xae, 0xe7,
- 0xbc, 0x06, 0x89, 0x8b, 0x19, 0xe2, 0xb7, 0x08, 0xfc, 0x17, 0x81, 0xe3,
- 0x8b, 0xee, 0xf1, 0xfa, 0x56, 0xb7, 0x18, 0xfd, 0x96, 0xd3, 0xb4, 0x69,
- 0xec, 0xf2, 0x3f, 0xf6, 0xc3, 0x35, 0x84, 0x6d, 0xc8, 0x1c, 0x99, 0xba,
- 0x6b, 0x94, 0xe5, 0x1a, 0x41, 0x31, 0xe4, 0x40, 0xf7, 0xa9, 0xe4, 0x84,
- 0x5a, 0x0a, 0x36, 0xed, 0xe8, 0xee, 0x7d, 0x42, 0xf7, 0x93, 0xf2, 0xd3,
- 0x2a, 0x0f, 0x78, 0xb6, 0x4a, 0xd3, 0x0e, 0xe2, 0x99, 0xb0, 0xc6, 0x18,
- 0x4f, 0x72, 0xef, 0x40, 0xdd, 0x31, 0xa5, 0xf7, 0xa0, 0x6d, 0x1d, 0xc2,
- 0x1c, 0x5f, 0x2f, 0xcd, 0xd4, 0x43, 0x8c, 0x93, 0xbd, 0x96, 0x2e, 0x84,
- 0x4c, 0x3a, 0x46, 0x19, 0x18, 0x31, 0xb1, 0xdf, 0xca, 0xcf, 0xa1, 0x9d,
- 0xce, 0x67, 0x89, 0x45, 0x21, 0xa3, 0xa6, 0xc0, 0xc5, 0x87, 0x8e, 0x49,
- 0xb4, 0xc1, 0xfb, 0x5f, 0xcd, 0xc6, 0x6f, 0xa2, 0x0f, 0xc5, 0xb1, 0x1b,
- 0x24, 0xbf, 0x26, 0xde, 0x52, 0x02, 0xfc, 0xcd, 0x32, 0x79, 0x8c, 0x6b,
- 0x11, 0x85, 0xcc, 0xe1, 0xd8, 0x12, 0xcd, 0xf4, 0x07, 0xc1, 0x38, 0xcb,
- 0x4f, 0x92, 0x7f, 0x25, 0xc5, 0x77, 0xb9, 0x93, 0x0b, 0x9b, 0xd4, 0x0a,
- 0x59, 0xdb, 0x62, 0xe1, 0xd0, 0x78, 0x92, 0x92, 0x96, 0x23, 0xd4, 0x37,
- 0xb7, 0xd5, 0xc0, 0x33, 0x7a, 0xc7, 0x94, 0xd7, 0xf8, 0x26, 0xe0, 0xf9,
- 0x3d, 0xc0, 0xd3, 0x62, 0xe1, 0x69, 0x5c, 0x05, 0x4f, 0x4b, 0x08, 0x0f,
- 0xe4, 0x1c, 0xe5, 0x6a, 0xec, 0x9a, 0x74, 0x59, 0x9c, 0xbc, 0x27, 0x9d,
- 0x4a, 0xfb, 0x2f, 0xd4, 0x37, 0x8d, 0xee, 0xf8, 0x80, 0x2b, 0xe3, 0x5a,
- 0xd7, 0x44, 0xaf, 0xe9, 0x2e, 0x2f, 0xc0, 0x7a, 0x15, 0x27, 0xe3, 0x11,
- 0xf6, 0x7a, 0x76, 0xd5, 0x3d, 0x90, 0xff, 0x8b, 0xa9, 0xa8, 0xb5, 0x25,
- 0x4a, 0x3e, 0xfd, 0x96, 0xb8, 0xde, 0xdb, 0xaf, 0xc2, 0xf4, 0x12, 0x60,
- 0x82, 0x3c, 0x3e, 0xd6, 0xe7, 0x8e, 0xca, 0xa5, 0xda, 0x37, 0xb3, 0xb8,
- 0xc6, 0xdc, 0x62, 0x35, 0x73, 0x83, 0xfe, 0x53, 0xe1, 0xdc, 0x20, 0x13,
- 0x51, 0xaf, 0x24, 0xf7, 0x5b, 0x5c, 0xb4, 0x62, 0x4e, 0xb1, 0x9a, 0xf9,
- 0x74, 0x27, 0xf6, 0xb3, 0xcc, 0xcc, 0xa7, 0x27, 0xef, 0xc5, 0x2c, 0x7e,
- 0x57, 0xc3, 0x58, 0xf5, 0x17, 0x67, 0x24, 0x90, 0x29, 0x1f, 0x6b, 0xd4,
- 0x4b, 0xff, 0x24, 0x66, 0xf3, 0x98, 0x15, 0x9e, 0x37, 0x58, 0xfe, 0x72,
- 0x25, 0xaf, 0xfd, 0xb7, 0x2f, 0xad, 0x37, 0x7c, 0x1a, 0xb5, 0xf9, 0x6b,
- 0xfc, 0xdd, 0xb1, 0xde, 0xee, 0xef, 0xe7, 0xd2, 0xf2, 0xfb, 0xeb, 0x69,
- 0x97, 0x34, 0x78, 0x43, 0xab, 0xca, 0x62, 0x28, 0xbb, 0x7d, 0xbd, 0x95,
- 0x0b, 0x28, 0xbb, 0x07, 0x7e, 0x1a, 0xf3, 0x34, 0xf8, 0x8e, 0x32, 0xb8,
- 0x16, 0x27, 0x7d, 0x60, 0x45, 0xf2, 0x3c, 0xe5, 0x22, 0x6d, 0x4a, 0xcc,
- 0x51, 0x7d, 0x27, 0x8c, 0xa3, 0xe3, 0x77, 0x3d, 0xdb, 0x9f, 0xf8, 0x26,
- 0xae, 0xe5, 0xdb, 0x53, 0xe0, 0xfb, 0x03, 0xbe, 0x13, 0x9d, 0x65, 0x1e,
- 0x80, 0xa6, 0xe1, 0xda, 0xbe, 0xaf, 0x47, 0xdf, 0x21, 0x2d, 0x93, 0x5e,
- 0xae, 0xd7, 0x74, 0xd3, 0x44, 0x5d, 0x7c, 0x8c, 0xf4, 0xc7, 0x58, 0x72,
- 0xb3, 0xd6, 0x8f, 0xd5, 0x75, 0x6c, 0x82, 0xae, 0x89, 0x1b, 0x1e, 0x75,
- 0xcd, 0x7e, 0x77, 0xb5, 0xbf, 0x31, 0xf4, 0x47, 0x3b, 0x0d, 0x7e, 0xba,
- 0xc7, 0x68, 0x0e, 0xe5, 0x97, 0x13, 0x55, 0x57, 0x6a, 0x3f, 0x33, 0xa6,
- 0xf3, 0x8e, 0x96, 0xeb, 0x4e, 0xd8, 0xb1, 0x49, 0xb7, 0x26, 0xfe, 0x5f,
- 0x1d, 0x5f, 0x1c, 0xb5, 0x4d, 0x40, 0x65, 0x8d, 0x32, 0x35, 0x40, 0x1a,
- 0xe5, 0xdc, 0xb5, 0x0d, 0x75, 0x0d, 0xed, 0x08, 0x43, 0x9f, 0xb4, 0x9d,
- 0xa2, 0xd7, 0x64, 0x0b, 0x8d, 0xc6, 0x67, 0x89, 0xcb, 0xe6, 0x06, 0x9d,
- 0x47, 0x80, 0xb2, 0x72, 0xa8, 0xcb, 0xa2, 0x32, 0xdb, 0xff, 0xbf, 0x83,
- 0xf4, 0x5e, 0xd6, 0xad, 0xbb, 0x6f, 0x9f, 0x98, 0x11, 0x8d, 0xa7, 0xbf,
- 0xa8, 0xe2, 0xc9, 0xce, 0x2d, 0xbe, 0x7a, 0x6e, 0x05, 0xc0, 0x7b, 0x0f,
- 0x64, 0x27, 0xd7, 0xc9, 0xe4, 0x6f, 0x3f, 0x2e, 0x4e, 0x34, 0xd3, 0x5b,
- 0x6f, 0x6e, 0xa5, 0x10, 0xaf, 0x9c, 0x1b, 0x68, 0x35, 0x9c, 0x17, 0x69,
- 0x3b, 0xae, 0xf7, 0x89, 0x94, 0x22, 0x2c, 0xad, 0xab, 0x70, 0x1b, 0xd2,
- 0x9d, 0xa1, 0xb9, 0xa7, 0x34, 0xcd, 0xb5, 0x58, 0x9a, 0x43, 0x5d, 0x97,
- 0xfb, 0xde, 0xa3, 0x2d, 0x55, 0x9a, 0xdb, 0x60, 0x69, 0xee, 0x99, 0xf5,
- 0x66, 0x4f, 0xfc, 0xfd, 0x2d, 0x66, 0x4f, 0xea, 0x2f, 0x57, 0x3d, 0x6f,
- 0xa2, 0xcd, 0x08, 0x5f, 0x2c, 0x7c, 0xae, 0x85, 0xf5, 0x0c, 0x60, 0xad,
- 0x95, 0x35, 0x4d, 0x36, 0xee, 0xc6, 0xfd, 0x73, 0xfa, 0x7d, 0x51, 0x79,
- 0x14, 0x76, 0x50, 0xbe, 0xfc, 0x8f, 0xc1, 0x02, 0x7c, 0xbf, 0xa9, 0x65,
- 0xdd, 0x7b, 0x5b, 0x0b, 0xf9, 0x6d, 0x06, 0xbf, 0x0e, 0xd6, 0xf8, 0x3c,
- 0x98, 0x2f, 0xca, 0xfe, 0x01, 0xeb, 0x01, 0xb9, 0xbc, 0x5c, 0x97, 0x31,
- 0x0b, 0xe3, 0xe3, 0x30, 0x66, 0x68, 0xf6, 0x13, 0x29, 0xe7, 0xef, 0x84,
- 0x4f, 0x74, 0x0f, 0xf4, 0x24, 0xe9, 0xfb, 0xa5, 0x16, 0x93, 0xe7, 0x1b,
- 0x87, 0x1e, 0xfb, 0x65, 0x9b, 0x0b, 0x75, 0xf8, 0x57, 0xeb, 0xe7, 0xf8,
- 0x82, 0xf6, 0x1d, 0xd2, 0xcc, 0xdf, 0xb7, 0x98, 0x98, 0xf1, 0xb7, 0x5a,
- 0xc8, 0x67, 0x6a, 0xdb, 0x0f, 0x37, 0x68, 0xbe, 0x70, 0xc2, 0xe7, 0xcf,
- 0xb4, 0xae, 0x7c, 0x0e, 0xdb, 0x3d, 0xd9, 0xba, 0xb2, 0x5d, 0x58, 0xfe,
- 0x73, 0x1b, 0x57, 0x96, 0x5f, 0xe3, 0xae, 0x6c, 0xff, 0xf5, 0x55, 0xcf,
- 0x2d, 0x9b, 0x56, 0x3e, 0x5f, 0xbd, 0xea, 0x79, 0x6a, 0xd5, 0xf3, 0x85,
- 0x55, 0xcf, 0x57, 0xb5, 0xad, 0x7c, 0xbe, 0xbd, 0xad, 0x3e, 0xbc, 0x87,
- 0xdb, 0x56, 0xc2, 0x75, 0xa7, 0x8e, 0xf7, 0xcf, 0x54, 0xa2, 0xb2, 0xab,
- 0x80, 0xf7, 0x4e, 0xe7, 0x66, 0xa3, 0xd7, 0x6a, 0xdf, 0x33, 0xbe, 0xf6,
- 0xd7, 0xab, 0xfa, 0xab, 0xb6, 0xdb, 0x5d, 0x6d, 0xe7, 0x57, 0xdb, 0x19,
- 0xd9, 0x36, 0x5b, 0xe1, 0x3b, 0x96, 0x87, 0xfd, 0x9a, 0xb6, 0x53, 0xc5,
- 0x4e, 0x9d, 0x0b, 0x3b, 0xaa, 0x73, 0x61, 0x93, 0xe0, 0xc3, 0x3b, 0x75,
- 0x4c, 0x69, 0x93, 0x42, 0x79, 0xa5, 0x55, 0xc7, 0x95, 0x74, 0x2c, 0xb5,
- 0x30, 0x0a, 0xdb, 0x96, 0x39, 0xb0, 0x81, 0xec, 0xf1, 0xcd, 0xdd, 0xe4,
- 0xc4, 0x1e, 0x0e, 0x86, 0xdd, 0x20, 0x98, 0xf4, 0x6e, 0xb3, 0xf9, 0x62,
- 0xb8, 0x57, 0x4c, 0x1b, 0xea, 0xe0, 0x27, 0xa0, 0x83, 0xab, 0xba, 0xf7,
- 0x4e, 0x8c, 0xb5, 0x00, 0x9a, 0x19, 0x90, 0xdf, 0xad, 0xa4, 0xbe, 0x24,
- 0xfa, 0xcc, 0x4d, 0x3f, 0x6c, 0xb8, 0xa5, 0x4f, 0xbd, 0xdf, 0xf3, 0x61,
- 0xeb, 0x05, 0xf2, 0xb0, 0x3f, 0x08, 0x1a, 0xea, 0x85, 0xbd, 0xe7, 0x69,
- 0xbf, 0xf4, 0xb4, 0xa6, 0x2d, 0xd2, 0x58, 0x8b, 0xce, 0xd7, 0x7f, 0xd4,
- 0x77, 0x62, 0x99, 0xfe, 0x3f, 0x32, 0x71, 0x1a, 0xbf, 0xdb, 0xfd, 0x1a,
- 0xf8, 0x76, 0xa7, 0xb7, 0x05, 0x3e, 0x0a, 0x69, 0x88, 0xf1, 0xaf, 0xcb,
- 0x75, 0x1e, 0x21, 0x03, 0x68, 0x33, 0x51, 0xc6, 0x09, 0x53, 0x83, 0x63,
- 0xc2, 0x79, 0xa7, 0x12, 0x49, 0xa5, 0xed, 0xaa, 0xe0, 0x46, 0x9f, 0x39,
- 0xb6, 0xdc, 0x63, 0x21, 0x3f, 0xef, 0xff, 0xf4, 0x94, 0x97, 0x73, 0x23,
- 0x36, 0x2f, 0x37, 0x53, 0x30, 0xb4, 0x39, 0x41, 0xda, 0x84, 0x3f, 0xb5,
- 0xd8, 0xff, 0xb7, 0x01, 0xed, 0xfb, 0xa4, 0x22, 0xed, 0xff, 0x4d, 0x30,
- 0x17, 0x65, 0x5f, 0x84, 0x7b, 0xff, 0xa7, 0x33, 0x1a, 0x57, 0x77, 0xca,
- 0x81, 0x22, 0x6d, 0xe1, 0x98, 0xce, 0xe7, 0x18, 0xf7, 0x69, 0xa7, 0xc5,
- 0x80, 0xc7, 0x0f, 0x01, 0x7f, 0x2d, 0xb0, 0xb9, 0x47, 0x50, 0x27, 0x22,
- 0x63, 0x60, 0xf1, 0xd9, 0x02, 0xf9, 0x93, 0xf7, 0x28, 0xea, 0xbb, 0x32,
- 0x5f, 0xb8, 0x59, 0xe7, 0xdb, 0x9d, 0x46, 0xdb, 0x27, 0x71, 0xcd, 0x16,
- 0x26, 0xd0, 0x66, 0xaf, 0xae, 0x3f, 0x5b, 0x62, 0x8e, 0xb2, 0x40, 0x2e,
- 0xed, 0x97, 0xfc, 0x5c, 0x97, 0x8c, 0xc5, 0x17, 0x66, 0xa2, 0xcb, 0x71,
- 0x99, 0x8f, 0x6f, 0xe0, 0x1e, 0x47, 0xfe, 0x4a, 0xee, 0x07, 0x4b, 0x74,
- 0x74, 0xbb, 0xea, 0x6d, 0xd3, 0x3e, 0xd7, 0xa0, 0xec, 0xac, 0x0c, 0xc9,
- 0x4d, 0x95, 0xcf, 0x6e, 0x36, 0xb1, 0xa8, 0x15, 0xf1, 0xad, 0xc3, 0xc4,
- 0x8a, 0x3a, 0x1a, 0xe5, 0xb9, 0x25, 0x99, 0x3d, 0x25, 0x12, 0x39, 0x1a,
- 0xc6, 0x12, 0x59, 0xe6, 0x4a, 0xd7, 0x95, 0x80, 0xeb, 0x14, 0x64, 0x6b,
- 0x3c, 0x26, 0x5f, 0xdc, 0x16, 0x8e, 0x95, 0x0b, 0xa6, 0xb7, 0xe5, 0xe4,
- 0xd3, 0xb8, 0xb2, 0x57, 0xa6, 0x4a, 0x19, 0xc5, 0x71, 0xbf, 0x13, 0x50,
- 0x96, 0xa9, 0x21, 0x4f, 0x72, 0x6d, 0xe1, 0xd8, 0xf0, 0x6f, 0x76, 0x84,
- 0xe3, 0xd3, 0xe6, 0x36, 0x67, 0x1e, 0xf2, 0xdc, 0x77, 0x01, 0xfd, 0x45,
- 0x86, 0xee, 0xde, 0x40, 0xdf, 0x61, 0x58, 0xd8, 0x0e, 0x32, 0x5d, 0xb1,
- 0x6f, 0xc2, 0x49, 0xf8, 0x6b, 0xe1, 0x5c, 0x4c, 0xc6, 0x81, 0xa3, 0xdc,
- 0xeb, 0xc2, 0xdb, 0xe7, 0x7a, 0xaa, 0x1e, 0xbc, 0xa3, 0x36, 0x96, 0xc8,
- 0xf8, 0xe0, 0x3a, 0xe0, 0xad, 0x05, 0xe5, 0x1f, 0x94, 0xa9, 0x63, 0x6f,
- 0xdb, 0xcc, 0xbd, 0xec, 0x06, 0xcf, 0xb1, 0x39, 0xa7, 0x3c, 0xbf, 0x73,
- 0x37, 0xea, 0xf0, 0xfd, 0xcd, 0x68, 0x93, 0xca, 0x65, 0x22, 0x9b, 0xe1,
- 0x13, 0x71, 0xdc, 0x20, 0xd2, 0xb5, 0xa3, 0x59, 0xe7, 0x90, 0xca, 0x29,
- 0xea, 0xf3, 0xb0, 0xed, 0xdd, 0x3a, 0x47, 0x03, 0x7e, 0x7b, 0x6e, 0x24,
- 0x42, 0xf9, 0xd5, 0x2b, 0xc3, 0xd4, 0x27, 0xa7, 0x6e, 0xd6, 0xb4, 0xdf,
- 0xbd, 0x8d, 0x67, 0x99, 0xfa, 0x8c, 0x8d, 0x1e, 0x27, 0x8c, 0xa3, 0x28,
- 0x87, 0xfd, 0xfe, 0x9a, 0x30, 0xdc, 0xf5, 0x26, 0x61, 0xb8, 0xeb, 0x4d,
- 0xc2, 0x40, 0x5c, 0x00, 0x8e, 0xca, 0x5f, 0x6c, 0x08, 0x63, 0xd5, 0x97,
- 0x62, 0x1e, 0x07, 0x8b, 0x77, 0xc9, 0xa1, 0xa2, 0xa3, 0xe3, 0x8e, 0x0b,
- 0x8a, 0x32, 0xc1, 0x05, 0x4f, 0x82, 0xf7, 0x8a, 0xe0, 0xcd, 0x22, 0x78,
- 0xb1, 0x08, 0xbe, 0x84, 0xfd, 0x7f, 0x06, 0xf6, 0xff, 0x93, 0x58, 0x9b,
- 0xd3, 0x2b, 0x78, 0x39, 0xad, 0x79, 0x39, 0x5f, 0xa4, 0xaf, 0xd6, 0x7f,
- 0x11, 0x7e, 0x8d, 0xca, 0x70, 0x21, 0x05, 0x55, 0xe2, 0x44, 0xb3, 0xfd,
- 0x9f, 0x24, 0xbf, 0xca, 0x83, 0xfe, 0x0d, 0x68, 0x73, 0x18, 0x34, 0x9e,
- 0xa2, 0x1d, 0x48, 0xfb, 0x27, 0x07, 0xde, 0x3c, 0x4c, 0x5f, 0x4d, 0x5d,
- 0xb9, 0x49, 0xa8, 0x5f, 0xa2, 0x3b, 0x98, 0x7b, 0xc8, 0xb9, 0x26, 0x57,
- 0xe1, 0xc9, 0xf0, 0xef, 0x84, 0x47, 0x3d, 0x43, 0xbe, 0x7d, 0x99, 0x7c,
- 0x5b, 0xc3, 0xab, 0x01, 0xe7, 0x17, 0xb8, 0xdb, 0xea, 0xb5, 0xad, 0xd6,
- 0xdf, 0xb4, 0x5c, 0x5f, 0x8f, 0x5f, 0x22, 0x3f, 0x42, 0x27, 0x11, 0xf7,
- 0xc9, 0x4c, 0x64, 0x8b, 0xc5, 0x3d, 0x6c, 0xb7, 0x1d, 0x97, 0x00, 0xf7,
- 0x9d, 0x92, 0x9b, 0x0f, 0xc4, 0xdb, 0x11, 0xf6, 0x59, 0xed, 0xc7, 0xb5,
- 0xfd, 0x8c, 0x17, 0x1c, 0x19, 0xd9, 0xc6, 0x7d, 0x08, 0x07, 0x7a, 0x3e,
- 0x5c, 0x0f, 0xd8, 0xfb, 0x7a, 0xcd, 0x29, 0x63, 0x29, 0x5b, 0x5b, 0x6c,
- 0xfc, 0x89, 0xfd, 0x1d, 0x5e, 0xb5, 0x4e, 0x17, 0x02, 0x9e, 0x11, 0x9b,
- 0xf2, 0x6e, 0xa8, 0xa1, 0x95, 0xfb, 0x2c, 0xad, 0xa8, 0x55, 0xf3, 0xb8,
- 0xdd, 0xd2, 0x4a, 0x08, 0x6f, 0x3c, 0xa4, 0x95, 0xa6, 0x90, 0x56, 0x72,
- 0x33, 0x21, 0xad, 0xb0, 0xed, 0xed, 0x21, 0xad, 0x24, 0x6b, 0x69, 0x25,
- 0x37, 0xe3, 0xe0, 0x5a, 0x0d, 0x07, 0xe9, 0x85, 0xfd, 0x90, 0x5e, 0x00,
- 0x4b, 0xe5, 0xd6, 0xd6, 0x90, 0x5e, 0xe2, 0xe8, 0xe7, 0x50, 0xd1, 0xe4,
- 0x74, 0xc0, 0xef, 0xb2, 0x3a, 0xc4, 0xc5, 0x9a, 0x1b, 0x1f, 0xb1, 0x3e,
- 0x8d, 0xf8, 0x96, 0x46, 0xaa, 0x79, 0xee, 0xab, 0x68, 0x03, 0xb8, 0x67,
- 0x2e, 0xeb, 0x76, 0x4d, 0x1b, 0xf7, 0xfb, 0x53, 0xa8, 0xbb, 0x07, 0xb4,
- 0x11, 0xe2, 0xe0, 0x7a, 0x8b, 0x83, 0xd5, 0x6b, 0x39, 0x66, 0x71, 0xb0,
- 0xc7, 0xe2, 0x40, 0xf3, 0x4b, 0x8e, 0x6b, 0xa6, 0x34, 0x0e, 0x9a, 0x34,
- 0x0e, 0x44, 0x85, 0x6d, 0xc7, 0xea, 0xe0, 0x80, 0x75, 0xf6, 0xe8, 0xf9,
- 0x47, 0x30, 0xff, 0xfd, 0x98, 0xbf, 0xd2, 0xf3, 0xe7, 0x3a, 0x70, 0xfe,
- 0x80, 0xa5, 0x72, 0x72, 0x79, 0xfe, 0x6d, 0xe8, 0xe3, 0x60, 0x31, 0xa2,
- 0xe7, 0x0f, 0xdb, 0x7e, 0x30, 0x9c, 0xff, 0xe9, 0x8a, 0xc9, 0x7f, 0x3e,
- 0xbd, 0x46, 0xcf, 0x4d, 0x59, 0xde, 0xf0, 0xb4, 0x5f, 0xcc, 0x98, 0xf6,
- 0x19, 0xe8, 0xb6, 0x69, 0x3f, 0x69, 0xcf, 0x43, 0x19, 0x7b, 0xe9, 0x1b,
- 0x3e, 0x79, 0xe7, 0xe3, 0x3a, 0x0f, 0xe5, 0x71, 0xda, 0x4d, 0xc5, 0x36,
- 0x19, 0x99, 0xae, 0x85, 0x9b, 0xf0, 0xe6, 0xb4, 0x1c, 0xcd, 0x62, 0x7e,
- 0xe3, 0x7e, 0x2f, 0xe4, 0x9b, 0xa6, 0x25, 0x94, 0xa7, 0x72, 0xc3, 0x91,
- 0x26, 0x51, 0x0f, 0x7c, 0x08, 0x73, 0x8e, 0xca, 0x66, 0xaf, 0xdb, 0xdd,
- 0xa1, 0xa8, 0x0b, 0x2f, 0xab, 0xd1, 0x85, 0xed, 0x56, 0x17, 0x6e, 0xa2,
- 0x2e, 0x04, 0xdc, 0x77, 0xca, 0xe1, 0x22, 0xd7, 0x2f, 0x97, 0x6c, 0x82,
- 0xfe, 0xff, 0x81, 0xc7, 0xb3, 0x27, 0x3a, 0x6e, 0x96, 0x38, 0xac, 0x69,
- 0x99, 0x3a, 0x2d, 0xa5, 0xcf, 0x6a, 0x2c, 0xd2, 0xc6, 0x8e, 0x33, 0x16,
- 0x4a, 0xbd, 0xf7, 0xe3, 0xe0, 0x73, 0x75, 0xf4, 0xde, 0x64, 0xd1, 0xd8,
- 0x6f, 0x0d, 0xb0, 0x09, 0xe5, 0x44, 0x3b, 0xae, 0x8d, 0x3c, 0xab, 0xd0,
- 0xdb, 0xa3, 0x9a, 0xa5, 0xe1, 0x44, 0xab, 0x4c, 0x4c, 0x1b, 0x1b, 0x57,
- 0x9d, 0x00, 0xfe, 0x4f, 0x30, 0xdf, 0x55, 0x74, 0x7e, 0x7e, 0xb6, 0x04,
- 0x3b, 0x77, 0xf6, 0x4e, 0x93, 0xb7, 0x32, 0xdd, 0xa0, 0x7f, 0xd3, 0x06,
- 0xc9, 0xfb, 0x69, 0xe8, 0xbb, 0x98, 0x4c, 0xa0, 0xcf, 0xee, 0x6d, 0x8d,
- 0x98, 0x73, 0x1c, 0x6d, 0xe9, 0xf3, 0x31, 0x8e, 0xd6, 0x28, 0xd1, 0xd9,
- 0xb8, 0xce, 0xad, 0xe7, 0xd9, 0xd1, 0xcc, 0x60, 0x1b, 0xde, 0x31, 0x9f,
- 0xc1, 0xc5, 0x58, 0xa1, 0xec, 0x47, 0xbf, 0x47, 0xc5, 0xee, 0xf7, 0x0c,
- 0x69, 0xfd, 0x17, 0x39, 0xea, 0xda, 0x33, 0x74, 0x83, 0x58, 0xf7, 0x7a,
- 0x7a, 0xd1, 0x18, 0xb9, 0x19, 0xac, 0x9f, 0x3a, 0x15, 0xc5, 0xbd, 0x13,
- 0xf7, 0xb0, 0xbf, 0x50, 0x8f, 0x40, 0x37, 0xbe, 0xb3, 0x6f, 0xa3, 0x34,
- 0x03, 0xdf, 0xb3, 0x0a, 0xb8, 0x36, 0x39, 0x59, 0x39, 0xcd, 0x0b, 0x55,
- 0x7a, 0x78, 0xf2, 0x75, 0xf9, 0x81, 0x34, 0x41, 0x5a, 0xa0, 0x5c, 0x24,
- 0x6d, 0x50, 0x26, 0x3a, 0xfa, 0x6c, 0x03, 0xe9, 0xe1, 0x09, 0xdf, 0x8b,
- 0x70, 0xdf, 0xde, 0xc4, 0xe5, 0x49, 0x1b, 0xa4, 0xf9, 0xa4, 0x8e, 0xd7,
- 0xa7, 0xe5, 0x7b, 0x92, 0x6e, 0xeb, 0x86, 0x5d, 0xf6, 0x2f, 0xbb, 0xc6,
- 0xe6, 0xdc, 0xad, 0xa6, 0x39, 0xe8, 0x26, 0xe6, 0xd0, 0xf5, 0xca, 0xfb,
- 0x2a, 0x39, 0xe0, 0xe1, 0x5e, 0x28, 0xe5, 0x3b, 0x75, 0x5e, 0xe2, 0xee,
- 0xc2, 0x46, 0xb9, 0xc5, 0x8f, 0xd9, 0xb8, 0xfb, 0x41, 0xd0, 0xc1, 0xa2,
- 0x23, 0x27, 0xce, 0xe2, 0x3a, 0xe7, 0x70, 0xfd, 0xce, 0xfb, 0xe9, 0x94,
- 0x22, 0xb3, 0x7b, 0xd1, 0xc4, 0xa2, 0xf4, 0xb9, 0x13, 0xfa, 0x0c, 0xc8,
- 0x82, 0xd3, 0x74, 0xe2, 0xd0, 0x46, 0xe3, 0x4b, 0x03, 0x16, 0xaf, 0xd1,
- 0x1d, 0xa1, 0x2d, 0xe7, 0x07, 0x41, 0x96, 0x76, 0x83, 0x28, 0xed, 0x23,
- 0xc1, 0xe7, 0x43, 0x19, 0xe3, 0x13, 0x5b, 0x9d, 0xc6, 0x53, 0x2f, 0x5a,
- 0x5a, 0x91, 0x88, 0x1a, 0x7a, 0xc6, 0x69, 0x38, 0x71, 0x9c, 0x6b, 0xa6,
- 0xf3, 0xa4, 0x0d, 0x5d, 0x3d, 0xe7, 0x54, 0xe9, 0xea, 0x1b, 0xf6, 0xb7,
- 0x1a, 0x6a, 0x92, 0x74, 0xaa, 0x09, 0xf3, 0x1d, 0x2e, 0x84, 0x30, 0x7e,
- 0x1f, 0x70, 0x11, 0x1e, 0xd0, 0xed, 0xec, 0x9f, 0xe1, 0x5a, 0x02, 0x2c,
- 0xf7, 0x01, 0xee, 0xf3, 0x80, 0xf9, 0x02, 0x2e, 0xd5, 0x11, 0x91, 0x3f,
- 0x76, 0x22, 0xb3, 0xb5, 0xf0, 0x12, 0xc6, 0xd3, 0x16, 0xde, 0xd7, 0x82,
- 0xd5, 0x95, 0xc5, 0x81, 0x2e, 0xc0, 0x43, 0x38, 0x5f, 0x02, 0x8c, 0xb4,
- 0x5b, 0x9f, 0xc7, 0xb3, 0x0b, 0xf8, 0x5e, 0xb0, 0x30, 0x81, 0x1e, 0xa7,
- 0xff, 0x47, 0xf5, 0x77, 0x81, 0x76, 0xf4, 0x9f, 0xdb, 0xe7, 0xce, 0x55,
- 0x32, 0xa0, 0xc7, 0x21, 0x9e, 0xa7, 0x8a, 0x4b, 0xb4, 0x03, 0xc0, 0xf7,
- 0x3f, 0x94, 0xc8, 0xa9, 0x84, 0x1c, 0x2a, 0x70, 0x0f, 0xe8, 0x24, 0xf0,
- 0xa1, 0xcf, 0xa4, 0xa0, 0xce, 0x15, 0xb8, 0xa0, 0xec, 0x67, 0xb7, 0xe3,
- 0xea, 0xc5, 0xf5, 0x56, 0x5c, 0x20, 0x87, 0xd9, 0x13, 0xb8, 0xfa, 0xd0,
- 0xb7, 0x8a, 0x37, 0x09, 0x73, 0xa9, 0xbe, 0x8d, 0x36, 0xda, 0xb6, 0xcc,
- 0xa9, 0xa1, 0x01, 0xe0, 0x6f, 0x00, 0xb0, 0x25, 0x70, 0x31, 0xff, 0xf8,
- 0x87, 0x8e, 0x9c, 0x7a, 0x19, 0x17, 0x18, 0xec, 0x14, 0x08, 0xf3, 0xd4,
- 0x20, 0x2e, 0x28, 0xb1, 0x53, 0x69, 0x5c, 0x23, 0xb8, 0xfe, 0xd2, 0x31,
- 0x3c, 0xd7, 0x09, 0x7c, 0x85, 0x3c, 0x02, 0x9c, 0xaf, 0xe0, 0xb9, 0xaf,
- 0x3b, 0x6f, 0x9c, 0xe7, 0x7e, 0xe2, 0x18, 0x9e, 0x7b, 0xc5, 0xa9, 0xf2,
- 0xdc, 0x59, 0x47, 0x3d, 0xfc, 0x8c, 0x13, 0x79, 0x98, 0xbe, 0xc4, 0x59,
- 0xc7, 0xf0, 0x7f, 0x44, 0x86, 0xf7, 0x82, 0x96, 0x1e, 0x5e, 0xc0, 0x45,
- 0xba, 0x7a, 0x16, 0xe5, 0x2f, 0xac, 0x1a, 0xf7, 0xf9, 0x37, 0x31, 0xee,
- 0xab, 0x76, 0x5c, 0x51, 0xd5, 0x71, 0x2f, 0xa0, 0xef, 0x97, 0xec, 0xb8,
- 0x17, 0x6a, 0xc6, 0x05, 0xad, 0x3c, 0xbc, 0x84, 0x8b, 0x74, 0xf1, 0x22,
- 0xca, 0x43, 0x99, 0x80, 0x85, 0x6e, 0x6e, 0xd0, 0x67, 0x9d, 0xe2, 0x5e,
- 0xc3, 0xb2, 0x6e, 0x4c, 0xd7, 0xe8, 0x87, 0x37, 0xa2, 0x1f, 0x27, 0x8b,
- 0xb4, 0x11, 0x17, 0x6a, 0xe4, 0x02, 0x7d, 0xa3, 0x40, 0x8e, 0x69, 0x3f,
- 0x88, 0x3e, 0x11, 0xfd, 0xa3, 0xd5, 0xb6, 0xd5, 0x27, 0x75, 0xee, 0xd8,
- 0xaf, 0x15, 0x3a, 0xe5, 0xd3, 0x05, 0xda, 0x84, 0xa4, 0x97, 0x20, 0x98,
- 0xd8, 0x41, 0xfb, 0x34, 0x17, 0x5c, 0xe2, 0x91, 0x4e, 0x3c, 0xf7, 0x33,
- 0x6b, 0x75, 0x46, 0x69, 0x18, 0xbe, 0x7b, 0xe6, 0xe8, 0xaf, 0x40, 0x67,
- 0x34, 0x00, 0x6e, 0xd2, 0x5b, 0x87, 0xdc, 0x58, 0x52, 0x53, 0x9b, 0x25,
- 0x21, 0x37, 0x15, 0x1a, 0x61, 0xf7, 0x30, 0xaf, 0xaa, 0x59, 0xba, 0x77,
- 0xc4, 0x4c, 0xde, 0xb7, 0x1b, 0xc7, 0x6f, 0xd7, 0xe4, 0xa1, 0xc7, 0x13,
- 0x78, 0xff, 0x7b, 0x2e, 0xe5, 0x60, 0xdc, 0xbb, 0x56, 0xe7, 0xf4, 0x74,
- 0xed, 0xa0, 0xdd, 0x72, 0xbd, 0xd6, 0xe1, 0xd1, 0x35, 0x76, 0x92, 0xea,
- 0x70, 0xa5, 0x6a, 0xa3, 0x8d, 0x17, 0x52, 0x49, 0xc2, 0xf5, 0x90, 0x70,
- 0xff, 0xeb, 0x1e, 0xc9, 0xfb, 0xad, 0xf0, 0x0b, 0x18, 0x3b, 0x4f, 0xf5,
- 0xd2, 0x36, 0x9a, 0x9d, 0x76, 0x6d, 0x5e, 0xf4, 0x46, 0x79, 0x4e, 0x8f,
- 0xd3, 0xa8, 0x61, 0x34, 0x67, 0x25, 0xb8, 0x8f, 0x10, 0xd3, 0xe7, 0x73,
- 0x66, 0xcb, 0x2d, 0x5a, 0xef, 0xcc, 0x96, 0x99, 0x87, 0x0f, 0x7f, 0xaa,
- 0xcc, 0xbc, 0x7b, 0x5f, 0xdc, 0x77, 0xc2, 0xcf, 0x2d, 0x6f, 0x91, 0xf1,
- 0xe9, 0x75, 0xd2, 0xe8, 0xa9, 0xf8, 0x66, 0xc8, 0x47, 0xb6, 0xe9, 0xda,
- 0x01, 0xff, 0x70, 0x66, 0xab, 0x3c, 0x39, 0xc3, 0xbe, 0x3b, 0x64, 0x6e,
- 0x5e, 0x1c, 0xf7, 0x9d, 0xeb, 0x51, 0x07, 0x72, 0x7d, 0x07, 0xcb, 0x92,
- 0xb8, 0x8b, 0x72, 0xdf, 0x19, 0x95, 0x73, 0x03, 0x7c, 0x66, 0xee, 0xbf,
- 0x44, 0xd9, 0xdf, 0xb9, 0x81, 0x4e, 0x79, 0x7c, 0x1e, 0x34, 0x01, 0xb9,
- 0x3f, 0x72, 0x82, 0x30, 0x89, 0xec, 0x9a, 0x65, 0x2c, 0xbd, 0xdb, 0x65,
- 0xdc, 0x94, 0xfb, 0x34, 0xb7, 0x0c, 0x70, 0x2c, 0xe8, 0x25, 0xe8, 0xb8,
- 0xae, 0x1d, 0x46, 0x16, 0xa4, 0x67, 0x1b, 0x50, 0xce, 0x7e, 0xe1, 0x3f,
- 0xee, 0x65, 0x3f, 0x61, 0x5b, 0x85, 0x39, 0x35, 0x6a, 0x7a, 0x59, 0x5a,
- 0xa5, 0x3f, 0xce, 0xfc, 0x4c, 0xf6, 0x37, 0xfb, 0xe8, 0xd5, 0x7b, 0x21,
- 0xdc, 0x53, 0x36, 0xb6, 0x15, 0xd7, 0x44, 0xef, 0x29, 0xc0, 0xae, 0xba,
- 0x42, 0xdb, 0x17, 0x73, 0x15, 0xae, 0x20, 0x63, 0x51, 0xe1, 0x1a, 0x25,
- 0xe4, 0xd1, 0xe2, 0xf2, 0x3a, 0x6d, 0x69, 0x58, 0xb9, 0x4e, 0xa4, 0x15,
- 0x7f, 0xcc, 0xda, 0x1e, 0x8b, 0x92, 0x83, 0x5d, 0xd6, 0xab, 0xd7, 0x6c,
- 0x11, 0xb6, 0xac, 0x5d, 0x33, 0x6d, 0xcf, 0xe6, 0xc3, 0x35, 0x1b, 0x85,
- 0xc6, 0x29, 0xab, 0x4d, 0x5c, 0x33, 0x97, 0xf1, 0x6e, 0xe0, 0x3d, 0x87,
- 0x75, 0xca, 0x61, 0x8d, 0x72, 0xe5, 0x0e, 0x99, 0x3d, 0xa6, 0x3a, 0x1b,
- 0x44, 0x92, 0xe3, 0x5e, 0x87, 0x4c, 0xce, 0x33, 0x96, 0xb0, 0x05, 0x36,
- 0xd8, 0x56, 0x5c, 0x9d, 0x78, 0x66, 0x3b, 0xf0, 0x54, 0x59, 0xa1, 0x6d,
- 0xd3, 0x1a, 0x3b, 0xeb, 0x71, 0x8c, 0xcd, 0x1c, 0xe1, 0x27, 0x80, 0x87,
- 0x2a, 0xef, 0x4c, 0xd5, 0xc4, 0x9f, 0x38, 0x57, 0xad, 0x43, 0x31, 0xdf,
- 0xb8, 0x5e, 0x4f, 0x1d, 0x87, 0x2a, 0x36, 0xbe, 0x19, 0x7b, 0x2a, 0x41,
- 0x7b, 0x2a, 0x5b, 0x72, 0xcd, 0xf9, 0x80, 0x51, 0xf8, 0x4e, 0x5e, 0xef,
- 0x26, 0xd2, 0xfa, 0xd8, 0x0c, 0xe1, 0x8a, 0x85, 0x70, 0xad, 0x58, 0x33,
- 0x9e, 0xe7, 0x5a, 0x1b, 0xe7, 0x98, 0x5a, 0xce, 0x5f, 0x34, 0xb1, 0x7d,
- 0xc6, 0x51, 0x3a, 0xeb, 0xc0, 0x74, 0xa7, 0xb6, 0x61, 0x45, 0x8d, 0xc9,
- 0x81, 0x22, 0xcf, 0x82, 0x31, 0x9e, 0x78, 0x23, 0xe3, 0x49, 0xbd, 0xb3,
- 0xf2, 0x5e, 0x8c, 0xcd, 0x5c, 0x1d, 0x65, 0xe3, 0x37, 0x1b, 0x6c, 0x8e,
- 0x48, 0x6d, 0x0c, 0xc7, 0xe4, 0xf2, 0xac, 0xcc, 0x8b, 0x4e, 0x8d, 0x2e,
- 0x61, 0x9d, 0x7f, 0x5d, 0xef, 0x0d, 0x4a, 0x29, 0x02, 0xed, 0x37, 0x3e,
- 0x90, 0x1a, 0x34, 0xe7, 0x60, 0x92, 0xb2, 0xb3, 0x68, 0xe6, 0x7f, 0x5e,
- 0xe7, 0xf4, 0x98, 0xdc, 0x45, 0x93, 0xef, 0x73, 0x8f, 0x9c, 0x87, 0x0e,
- 0xaf, 0xae, 0x6d, 0x93, 0x4c, 0x02, 0x17, 0x59, 0xbd, 0x2f, 0x91, 0x94,
- 0xec, 0xc0, 0xc7, 0x37, 0xf1, 0x9c, 0x44, 0x0c, 0xeb, 0x93, 0x9f, 0xe1,
- 0xd9, 0x49, 0xf6, 0x7b, 0xb1, 0xbe, 0x28, 0x66, 0x99, 0x87, 0x0f, 0x59,
- 0xf9, 0xb6, 0xbe, 0x44, 0xb3, 0x7e, 0xbf, 0xce, 0xe6, 0x5b, 0x3b, 0x22,
- 0x37, 0x06, 0xf2, 0x87, 0x10, 0x9f, 0x8f, 0xd9, 0x39, 0x25, 0x75, 0xcc,
- 0x4a, 0x82, 0x73, 0x7e, 0xc2, 0xc6, 0x2c, 0x39, 0x97, 0x1b, 0x2c, 0x7d,
- 0x1b, 0xfb, 0xa7, 0x6a, 0x43, 0x9b, 0x7d, 0xbf, 0x27, 0xb5, 0x2c, 0xec,
- 0xb7, 0xb6, 0xb3, 0x8e, 0xf3, 0x1c, 0x17, 0x9d, 0x13, 0x10, 0xfa, 0x46,
- 0x3d, 0x35, 0x7e, 0x81, 0xf1, 0xe5, 0xf2, 0xd3, 0xf5, 0x64, 0x54, 0xd5,
- 0x27, 0xa4, 0x2f, 0x37, 0xb1, 0x8d, 0xdf, 0x2d, 0x08, 0x7d, 0xb9, 0x7e,
- 0xeb, 0xcb, 0xb5, 0x6a, 0x5f, 0xce, 0xc4, 0x1e, 0x5a, 0x97, 0x7d, 0xb9,
- 0xfc, 0x74, 0x0e, 0xb4, 0x12, 0x7e, 0x67, 0xc1, 0xd8, 0x42, 0x93, 0x05,
- 0x9e, 0x79, 0x69, 0x94, 0xec, 0xa8, 0x82, 0xdf, 0x60, 0x7c, 0x2c, 0xc6,
- 0x2a, 0x94, 0xfa, 0x96, 0xf5, 0x2f, 0x3a, 0x25, 0xdd, 0xbe, 0x0e, 0xf3,
- 0xbe, 0x53, 0xaf, 0xf9, 0x5c, 0xc1, 0xec, 0x7d, 0x66, 0xf7, 0x32, 0x26,
- 0xc4, 0x73, 0x4d, 0x9a, 0xbf, 0x92, 0xc3, 0x91, 0x5e, 0x63, 0xcf, 0x7a,
- 0xdf, 0x04, 0xde, 0x4f, 0x02, 0xe7, 0x31, 0x3b, 0x6e, 0x12, 0x30, 0x1d,
- 0xc0, 0xda, 0x5c, 0x6b, 0x65, 0x32, 0xc7, 0xde, 0xd3, 0xc4, 0xd8, 0xc0,
- 0x7c, 0x21, 0x8c, 0x11, 0x46, 0xec, 0x99, 0x4a, 0x2f, 0xd2, 0xe8, 0xad,
- 0xab, 0x6b, 0xab, 0x9e, 0x7e, 0x5d, 0xdd, 0x44, 0x5a, 0xba, 0x53, 0xe7,
- 0xb9, 0xac, 0x1f, 0x48, 0xed, 0xd1, 0x39, 0xf2, 0x3a, 0xc6, 0x98, 0x13,
- 0xe6, 0x94, 0x7d, 0x57, 0xde, 0xa1, 0x65, 0xfe, 0x01, 0x9f, 0xfa, 0x6b,
- 0x87, 0xfe, 0xdd, 0x38, 0x14, 0x04, 0xe7, 0x06, 0xee, 0x86, 0xad, 0xe2,
- 0xb9, 0xdf, 0x97, 0xee, 0xc4, 0xb0, 0xb6, 0x9d, 0xb0, 0x46, 0x7b, 0x9b,
- 0x65, 0x9d, 0x77, 0xb3, 0xcd, 0x99, 0xc9, 0x41, 0x6e, 0xa6, 0x60, 0x33,
- 0xf1, 0x4c, 0x70, 0x8f, 0x7d, 0x97, 0x0b, 0x9a, 0x41, 0x47, 0x1f, 0x13,
- 0x23, 0x63, 0xb2, 0x55, 0x19, 0xc3, 0x5c, 0x83, 0x34, 0x09, 0x39, 0x7a,
- 0x44, 0x52, 0xfc, 0xee, 0x07, 0xc7, 0xce, 0xcb, 0xa5, 0xd0, 0xcb, 0x6c,
- 0xa7, 0xbf, 0xd9, 0x83, 0x67, 0xee, 0xe1, 0x78, 0xee, 0x41, 0xe8, 0x96,
- 0xeb, 0xd7, 0xea, 0x96, 0x04, 0xfd, 0xfa, 0x6c, 0x89, 0xbe, 0xe1, 0x7a,
- 0xb4, 0xe9, 0x90, 0x8f, 0x4f, 0x77, 0xb7, 0x91, 0xb7, 0xc6, 0x20, 0xd7,
- 0xd5, 0xfd, 0xe1, 0x59, 0x20, 0x96, 0xf1, 0x3d, 0xfb, 0x6d, 0x92, 0xe4,
- 0xfb, 0x5d, 0xf9, 0x7c, 0x25, 0x95, 0x5c, 0x82, 0x6e, 0x1a, 0x73, 0x7e,
- 0xf1, 0x72, 0x13, 0x53, 0x7d, 0x7b, 0x9b, 0x39, 0x3b, 0xd0, 0x4c, 0x9b,
- 0xdd, 0xc6, 0x59, 0x6b, 0x69, 0x76, 0xc9, 0xca, 0xe3, 0x20, 0x68, 0x1e,
- 0xd0, 0x32, 0x78, 0x0f, 0x65, 0xf0, 0x01, 0xbf, 0xc7, 0xd0, 0xbe, 0xf6,
- 0x99, 0x02, 0xac, 0x23, 0xf0, 0x30, 0x10, 0x65, 0x7e, 0x9e, 0xe5, 0x4f,
- 0x2f, 0xbd, 0x68, 0xe5, 0x92, 0x72, 0xd6, 0xf2, 0xa5, 0xba, 0x2a, 0xb6,
- 0x42, 0xe6, 0x1e, 0x9a, 0xa6, 0x3e, 0xf6, 0x17, 0xbe, 0x0b, 0x39, 0x95,
- 0xd5, 0x78, 0xe8, 0x90, 0xfb, 0xa6, 0x25, 0x7d, 0x1e, 0xba, 0x2a, 0x3f,
- 0xbf, 0x92, 0x37, 0xd7, 0xf6, 0xc7, 0xb9, 0x7e, 0xb8, 0xcd, 0xf8, 0xb6,
- 0x2b, 0xe7, 0xba, 0x80, 0xb9, 0xa6, 0xf5, 0x5c, 0xb9, 0x6f, 0xf3, 0x31,
- 0x3b, 0xd7, 0xf5, 0xe1, 0x5c, 0x07, 0x57, 0xce, 0x35, 0xf4, 0xed, 0x43,
- 0xb9, 0x9b, 0xd4, 0xf9, 0xf2, 0x3a, 0x4f, 0x7b, 0x7a, 0xbd, 0x0c, 0x97,
- 0x5a, 0xad, 0xbc, 0x74, 0xa1, 0x7b, 0x98, 0xc3, 0xbe, 0x70, 0xaf, 0x2b,
- 0x16, 0x67, 0x8a, 0x78, 0xa0, 0xac, 0x6d, 0xd3, 0x67, 0x6c, 0x66, 0xe1,
- 0x5f, 0xdd, 0x5a, 0x60, 0xdd, 0xf0, 0xfd, 0xc5, 0x62, 0xc7, 0xa1, 0x4f,
- 0x4d, 0xbf, 0xa9, 0x77, 0x4d, 0x4c, 0xc1, 0xc4, 0x87, 0x19, 0x17, 0x36,
- 0x67, 0x7f, 0x99, 0x8b, 0x78, 0x07, 0x78, 0xea, 0x53, 0x85, 0xd4, 0x60,
- 0x26, 0x42, 0x39, 0x7a, 0x5c, 0x0e, 0x55, 0x46, 0xa4, 0x4b, 0x9f, 0xff,
- 0x7c, 0xdd, 0xd8, 0x71, 0xba, 0x36, 0x76, 0xcc, 0x74, 0x02, 0xc6, 0x8e,
- 0xf7, 0xfc, 0x0c, 0xb1, 0x63, 0x71, 0x4c, 0xec, 0xb8, 0x9e, 0x7f, 0x35,
- 0x55, 0x3c, 0x8e, 0x79, 0x35, 0x43, 0x96, 0x2c, 0x3a, 0xd9, 0xf9, 0x16,
- 0xdc, 0xcf, 0xe2, 0x1e, 0xc3, 0xfd, 0x3c, 0xee, 0x2e, 0xee, 0x17, 0x70,
- 0x8f, 0xcb, 0xd4, 0xb2, 0xce, 0x38, 0x0e, 0xb9, 0x41, 0x5d, 0xc6, 0xb6,
- 0xc6, 0x1f, 0x98, 0x2b, 0xb7, 0xf3, 0x7b, 0x2d, 0xce, 0xec, 0x3c, 0xe7,
- 0xd0, 0x2a, 0x93, 0xd3, 0x94, 0xd9, 0x6d, 0x52, 0x9a, 0x0e, 0x6d, 0xdb,
- 0x9f, 0xef, 0xe0, 0x9e, 0xc1, 0x98, 0x84, 0xb6, 0xeb, 0x3d, 0x1d, 0x66,
- 0xaf, 0xf1, 0x3b, 0x58, 0xe3, 0x8d, 0x58, 0x83, 0x93, 0x72, 0x7e, 0x66,
- 0xe3, 0x0a, 0x1b, 0x36, 0x69, 0x63, 0x82, 0x33, 0x56, 0xf7, 0xd6, 0x97,
- 0x11, 0xb5, 0xeb, 0x9f, 0xb0, 0x67, 0xcb, 0xc2, 0x1c, 0xa1, 0xa4, 0x5e,
- 0x9f, 0xd1, 0xca, 0x71, 0x8c, 0x37, 0x28, 0xe9, 0x19, 0xce, 0x73, 0xf9,
- 0x9b, 0x11, 0x90, 0x87, 0x27, 0xa0, 0x57, 0x57, 0xd0, 0x25, 0xe8, 0x96,
- 0x73, 0x73, 0x40, 0xbb, 0x8f, 0xca, 0x6c, 0x89, 0xf0, 0xf5, 0x24, 0x22,
- 0xfa, 0xac, 0x19, 0x9e, 0x67, 0x4c, 0x8e, 0xfb, 0x70, 0x25, 0x3c, 0x67,
- 0xb6, 0x89, 0x67, 0x07, 0x57, 0x9d, 0x35, 0xb3, 0xfa, 0x59, 0xdb, 0x0e,
- 0x3c, 0x73, 0x16, 0xce, 0xa1, 0x1e, 0x3d, 0x05, 0x32, 0xa9, 0xf3, 0xce,
- 0x36, 0xcb, 0x63, 0x0f, 0x2e, 0xe7, 0xbc, 0xb6, 0xc1, 0x46, 0xe9, 0x84,
- 0x89, 0x3c, 0x1a, 0x1d, 0xea, 0x81, 0x8f, 0xc7, 0x3c, 0x99, 0x9e, 0xc4,
- 0x6d, 0x3a, 0x17, 0xb9, 0x7a, 0xee, 0xaf, 0x9a, 0x8f, 0x1c, 0x9e, 0xb3,
- 0x4a, 0xe8, 0xef, 0x5a, 0xec, 0xd4, 0xe5, 0x71, 0xcc, 0x87, 0xfb, 0x7e,
- 0x1a, 0x0f, 0x09, 0x7e, 0xa7, 0xeb, 0x29, 0xe0, 0x60, 0xb2, 0xf2, 0x6d,
- 0xd0, 0xbb, 0x63, 0xcf, 0x9c, 0x91, 0xc6, 0x06, 0x64, 0xa2, 0x9c, 0x70,
- 0x26, 0xca, 0x03, 0xce, 0xbe, 0xb2, 0x7d, 0x37, 0xb0, 0x67, 0xb3, 0x34,
- 0xe3, 0xf7, 0x4c, 0x97, 0x33, 0x06, 0x7c, 0xe5, 0x8b, 0xdd, 0x4e, 0x5a,
- 0xdf, 0x3d, 0x7b, 0x87, 0x1c, 0xc0, 0x5a, 0x0d, 0xcf, 0xc4, 0xb5, 0x9c,
- 0xaf, 0x7e, 0x5b, 0x2a, 0x5c, 0x57, 0x7e, 0x13, 0x89, 0x7c, 0x7c, 0x5c,
- 0x7f, 0xe7, 0xc8, 0xd8, 0x0e, 0x27, 0xd1, 0xdf, 0x71, 0x1b, 0x13, 0xef,
- 0x73, 0xb2, 0xba, 0x1f, 0xb3, 0x1e, 0xf9, 0xe2, 0x09, 0xdc, 0x57, 0x9f,
- 0x79, 0x0e, 0xf5, 0x8c, 0x85, 0xbb, 0x10, 0xdc, 0x63, 0xe4, 0xd5, 0x71,
- 0x99, 0xaa, 0x30, 0x7f, 0xc4, 0xd1, 0x7c, 0x34, 0x59, 0x3e, 0x00, 0x9d,
- 0xb4, 0xf2, 0xcc, 0xdf, 0xce, 0xea, 0x3a, 0x24, 0x67, 0x84, 0xb0, 0x70,
- 0x0d, 0x56, 0x9e, 0x87, 0xbf, 0xf8, 0xbf, 0x70, 0x5f, 0xd1, 0xc8, 0x50,
- 0x0b, 0x47, 0x9a, 0xf2, 0xce, 0xc8, 0x95, 0x69, 0x39, 0x08, 0x78, 0x0e,
- 0xe3, 0x52, 0xf7, 0xf3, 0x3b, 0x2c, 0xf3, 0x92, 0x9f, 0xbb, 0x4f, 0xd4,
- 0x43, 0xe7, 0x9d, 0xe8, 0x43, 0x07, 0x25, 0xf2, 0xd0, 0xa2, 0xd3, 0xf0,
- 0x50, 0xb7, 0xf6, 0xcb, 0x77, 0xfb, 0xdd, 0x89, 0x7d, 0x72, 0x52, 0xa2,
- 0xf7, 0x2b, 0x7d, 0xfe, 0x2b, 0xef, 0x32, 0xc6, 0x77, 0x52, 0x22, 0xf7,
- 0xc7, 0xec, 0xd9, 0x51, 0x13, 0xd7, 0x5b, 0xd2, 0x7c, 0xff, 0x9b, 0x71,
- 0xe2, 0x6c, 0x49, 0x8e, 0x6b, 0xde, 0x19, 0x86, 0x9e, 0xc8, 0x94, 0x92,
- 0xcb, 0x75, 0x4c, 0xbe, 0xe7, 0xf3, 0x9b, 0x0d, 0xbf, 0xb0, 0x4e, 0x8f,
- 0xc3, 0xef, 0x38, 0x18, 0x9d, 0x91, 0xb9, 0x2c, 0xcc, 0xfd, 0x34, 0x6b,
- 0xca, 0xf7, 0x67, 0xb1, 0x86, 0x3d, 0x58, 0x2f, 0x8e, 0xe7, 0xe8, 0xfd,
- 0x5c, 0x9e, 0x9d, 0x75, 0xa5, 0x2f, 0xd1, 0xb4, 0x6c, 0x07, 0xb1, 0xee,
- 0x7d, 0xd2, 0x04, 0xb8, 0xd5, 0x43, 0x79, 0x63, 0xd7, 0x09, 0xe9, 0x54,
- 0x20, 0xb9, 0x49, 0xb3, 0x3d, 0x83, 0xbb, 0xf5, 0x1a, 0xde, 0x6b, 0x69,
- 0x66, 0x9d, 0xb1, 0x1f, 0xf1, 0x6c, 0xe8, 0x22, 0x2f, 0xbb, 0xa6, 0x7f,
- 0x08, 0x3d, 0xcf, 0x7d, 0x17, 0x6d, 0x2f, 0xd6, 0xb1, 0x05, 0xc9, 0x4b,
- 0xcf, 0x58, 0xbf, 0x32, 0x08, 0xa6, 0x7d, 0x1f, 0x78, 0xac, 0xe7, 0x4b,
- 0x6e, 0x71, 0xe6, 0x4a, 0x5b, 0x9d, 0xd9, 0x52, 0x20, 0x13, 0x3e, 0xbf,
- 0xe3, 0xc1, 0x1c, 0x00, 0xda, 0x5b, 0x2c, 0xeb, 0x86, 0x6e, 0xfd, 0xeb,
- 0xcd, 0x3c, 0x8f, 0x74, 0x93, 0xf7, 0xa2, 0x98, 0x7a, 0xc4, 0x31, 0x7d,
- 0xe4, 0xee, 0xe3, 0x59, 0xe1, 0xf7, 0x34, 0xfa, 0x12, 0x71, 0xfd, 0x5d,
- 0x8f, 0xcf, 0xa1, 0x1d, 0xc6, 0x28, 0x72, 0xdc, 0x67, 0x9d, 0x59, 0xc8,
- 0xb3, 0xb9, 0x69, 0x9e, 0xe1, 0x67, 0x3e, 0x6d, 0xa4, 0x53, 0xc9, 0x15,
- 0xee, 0xa4, 0xfd, 0x06, 0x5c, 0x0e, 0x2e, 0x50, 0x44, 0x97, 0xf5, 0xb9,
- 0xe3, 0xcb, 0xdf, 0x85, 0x0b, 0xcb, 0xc2, 0xef, 0xc3, 0x29, 0x9d, 0x3b,
- 0x0d, 0x5f, 0xf6, 0xb1, 0x31, 0xf9, 0x89, 0x33, 0x5f, 0x78, 0xc5, 0x79,
- 0xb4, 0x90, 0xbe, 0xea, 0x12, 0xd0, 0xc7, 0x39, 0xbf, 0x97, 0xf2, 0x0b,
- 0x36, 0x5f, 0x41, 0x72, 0x95, 0x09, 0x99, 0xe9, 0xe8, 0x76, 0xef, 0xd7,
- 0x6b, 0x33, 0x03, 0x9c, 0x7d, 0x1b, 0xeb, 0xf7, 0xc9, 0x38, 0xf5, 0xdb,
- 0x78, 0x41, 0x81, 0x97, 0xd5, 0xcf, 0xe3, 0x82, 0x6d, 0xdb, 0xa8, 0x6d,
- 0x94, 0x7d, 0x3e, 0xeb, 0x6d, 0x75, 0x86, 0x4b, 0x5b, 0xb0, 0x8e, 0x7b,
- 0xa1, 0x3f, 0x1d, 0xd8, 0x69, 0xa0, 0x6d, 0x94, 0x4d, 0x02, 0x07, 0xe3,
- 0xbe, 0x91, 0xe7, 0xc3, 0x92, 0xd3, 0x3e, 0x9e, 0xb9, 0xa7, 0x95, 0x89,
- 0x99, 0x05, 0xc1, 0x1c, 0xec, 0x83, 0x6c, 0x7f, 0x09, 0xbc, 0xf0, 0x08,
- 0xae, 0xb7, 0xdb, 0x3d, 0xed, 0x17, 0x2e, 0xb2, 0xa7, 0xed, 0xca, 0xc9,
- 0x8a, 0x3e, 0xd7, 0xae, 0xf3, 0xab, 0x92, 0xea, 0xbf, 0x5f, 0xa2, 0xd7,
- 0x4a, 0xf5, 0xe8, 0x9c, 0xb4, 0xb4, 0x7c, 0x38, 0x6e, 0xf4, 0x30, 0x61,
- 0x4a, 0x02, 0x9e, 0xad, 0xc0, 0x05, 0xe1, 0x31, 0x6d, 0x44, 0x6d, 0xba,
- 0x94, 0xfa, 0x70, 0x49, 0x3e, 0x12, 0x0f, 0xcf, 0x14, 0xa0, 0x1f, 0xc8,
- 0xb8, 0x8f, 0x5d, 0x6a, 0xf4, 0xe4, 0xe6, 0x3a, 0xfd, 0x84, 0x73, 0x73,
- 0xec, 0xdc, 0x48, 0xb7, 0x7f, 0x96, 0xa0, 0x4f, 0xb1, 0x24, 0x4d, 0xab,
- 0xea, 0x33, 0xa6, 0xbf, 0xe1, 0x72, 0x73, 0x46, 0x81, 0x75, 0x5d, 0xd8,
- 0xa6, 0xb4, 0x73, 0x89, 0x47, 0xbd, 0x6e, 0x05, 0x25, 0x3c, 0x67, 0x00,
- 0x6e, 0xae, 0x5c, 0xe1, 0xbe, 0x43, 0x91, 0x0e, 0x43, 0x5c, 0x7f, 0x5b,
- 0xf3, 0xc9, 0x78, 0x81, 0xb1, 0x95, 0x47, 0x83, 0xf4, 0x28, 0x79, 0x8c,
- 0x7d, 0xf0, 0x7d, 0x41, 0xc7, 0x73, 0xf7, 0xfa, 0x8c, 0x15, 0x75, 0x1f,
- 0xbf, 0x43, 0x85, 0x72, 0x0a, 0xfa, 0xb7, 0xb8, 0xe8, 0xf0, 0x1b, 0x78,
- 0x37, 0x0a, 0xee, 0xf3, 0x8b, 0xce, 0x77, 0xa7, 0x9f, 0xc5, 0x73, 0x83,
- 0xfd, 0xee, 0x9d, 0xd1, 0x53, 0x22, 0xc5, 0x70, 0xbe, 0x89, 0x1c, 0xd6,
- 0xfe, 0x02, 0xd6, 0xbe, 0xfe, 0x77, 0xee, 0xf0, 0xae, 0x8c, 0x77, 0xe5,
- 0x0f, 0x07, 0xe9, 0x36, 0xd2, 0x22, 0xe9, 0xef, 0xb5, 0xfc, 0xe6, 0x41,
- 0xcd, 0x17, 0x93, 0xc5, 0xc7, 0xc1, 0x17, 0x69, 0xee, 0x37, 0x07, 0x0f,
- 0xfb, 0x37, 0x80, 0x2f, 0xf6, 0xc8, 0xef, 0xc3, 0x2e, 0xf8, 0xdd, 0xca,
- 0x10, 0xf8, 0x63, 0x10, 0xfc, 0x32, 0x00, 0x1e, 0xf1, 0xb5, 0x8d, 0xfc,
- 0x04, 0xf4, 0x1f, 0xf4, 0x9a, 0xb3, 0xaf, 0xd4, 0xe5, 0x64, 0x4b, 0x9e,
- 0x33, 0x51, 0xe2, 0xf7, 0x5a, 0xd4, 0x5b, 0x1b, 0x24, 0x9a, 0x98, 0x13,
- 0xf2, 0x42, 0x37, 0x73, 0x1c, 0xdb, 0x81, 0xab, 0x53, 0xc4, 0xd5, 0x5c,
- 0xa5, 0xcf, 0xbd, 0x04, 0x3c, 0xd1, 0xae, 0x79, 0xa2, 0xd5, 0x49, 0xbb,
- 0x37, 0x58, 0x9e, 0x78, 0x11, 0x3c, 0x71, 0x7e, 0x0d, 0x4f, 0x3c, 0x6d,
- 0xe9, 0x7f, 0xa1, 0x86, 0x27, 0xe6, 0x6c, 0xd9, 0xcc, 0x45, 0x78, 0xe2,
- 0x52, 0x2f, 0xf5, 0xa5, 0x31, 0x79, 0x15, 0x3c, 0x21, 0x8a, 0x3c, 0x71,
- 0xa9, 0xe6, 0x09, 0xc6, 0x8e, 0xc8, 0x17, 0x9d, 0x90, 0x23, 0xe4, 0x8b,
- 0xb3, 0xb2, 0x04, 0xbe, 0x78, 0x5e, 0x71, 0xec, 0x19, 0xda, 0x0a, 0x25,
- 0xfa, 0x64, 0x27, 0x8a, 0x5d, 0xe0, 0x77, 0x25, 0xff, 0x65, 0x3a, 0x08,
- 0x16, 0xe1, 0xa7, 0x3f, 0x08, 0x7b, 0x3e, 0xaa, 0xbf, 0xa9, 0xb8, 0x00,
- 0xba, 0x0f, 0xe9, 0x7d, 0xc2, 0x01, 0xbd, 0x1f, 0x9e, 0xc5, 0x1c, 0x26,
- 0xd4, 0x7f, 0x86, 0x2f, 0xec, 0x62, 0x5d, 0x69, 0xe7, 0x1f, 0xd3, 0x3c,
- 0xd4, 0x00, 0x7d, 0xf0, 0xe8, 0x00, 0x63, 0x4d, 0x9e, 0xbb, 0x4f, 0x75,
- 0xe7, 0x46, 0x00, 0x73, 0x44, 0xdd, 0x2f, 0x8c, 0x73, 0xb4, 0xad, 0xb2,
- 0xf3, 0x29, 0x23, 0x46, 0x21, 0xeb, 0xcc, 0xbb, 0x5c, 0xd0, 0x04, 0x9b,
- 0xb4, 0x49, 0x19, 0x1b, 0x5d, 0xed, 0x48, 0xb9, 0x1f, 0x84, 0x00, 0x6d,
- 0x84, 0xbd, 0xb0, 0x0b, 0xab, 0x3d, 0x52, 0xa8, 0xb5, 0xf1, 0xff, 0x03,
- 0x6c, 0x7c, 0xb6, 0x91, 0xa8, 0xb1, 0xf1, 0x7f, 0xcd, 0xf2, 0x1a, 0x7f,
- 0xbb, 0xda, 0xde, 0x3f, 0x00, 0xf8, 0x76, 0x2f, 0xdb, 0xfb, 0xec, 0x83,
- 0x76, 0x87, 0xc8, 0xf5, 0xb0, 0xf9, 0xde, 0x0d, 0x1e, 0xbc, 0x01, 0xbe,
- 0xd4, 0x7b, 0x0a, 0xae, 0xec, 0x29, 0xb4, 0xc3, 0xe7, 0xee, 0x94, 0xf7,
- 0x4e, 0x6f, 0x95, 0x9d, 0x25, 0xff, 0x12, 0x69, 0xee, 0x80, 0x8d, 0x5a,
- 0x00, 0x9c, 0x11, 0x2b, 0xb7, 0xcf, 0x02, 0x6f, 0xdd, 0xc9, 0x9f, 0xa8,
- 0x17, 0xad, 0x5d, 0xc4, 0xb3, 0x8e, 0xf5, 0xfa, 0x89, 0xa3, 0x3d, 0x63,
- 0x29, 0x1d, 0x72, 0xea, 0x18, 0xbd, 0xaf, 0x24, 0xec, 0x72, 0x1f, 0x36,
- 0xc9, 0x16, 0xf4, 0xc7, 0x78, 0xf2, 0x46, 0x79, 0xfa, 0xaa, 0xe8, 0x5d,
- 0x59, 0xcd, 0x87, 0x9d, 0x4e, 0x66, 0x1a, 0x3e, 0xc0, 0xde, 0x18, 0xe6,
- 0xa0, 0xda, 0x37, 0xcb, 0x75, 0xb2, 0x53, 0xcf, 0x67, 0x46, 0x0e, 0x42,
- 0x37, 0xff, 0x41, 0x61, 0xa7, 0x2c, 0x8d, 0xb6, 0xe1, 0x39, 0x26, 0x4f,
- 0x17, 0xfa, 0xe0, 0xfb, 0xbc, 0x0b, 0x38, 0x6a, 0xc4, 0x73, 0xa3, 0x0c,
- 0x5f, 0x42, 0x5e, 0x6d, 0x91, 0x45, 0x94, 0xbf, 0x5b, 0x7e, 0xc1, 0x96,
- 0xb3, 0x8c, 0xbc, 0xd1, 0x82, 0xb6, 0x31, 0x39, 0x57, 0xa0, 0x5d, 0xa9,
- 0x79, 0x62, 0xf0, 0x7b, 0xd2, 0x97, 0xfe, 0x1e, 0xec, 0xd4, 0xb3, 0xb8,
- 0x9e, 0x91, 0xd4, 0x9e, 0x71, 0xa7, 0x2f, 0xd9, 0xed, 0x40, 0x77, 0xe2,
- 0x8a, 0x3a, 0x7d, 0x6e, 0xa3, 0x73, 0x85, 0xed, 0xa3, 0x41, 0x9e, 0xd9,
- 0xab, 0x12, 0x2d, 0x58, 0x93, 0xed, 0x4e, 0x8f, 0x2d, 0xe3, 0x73, 0xca,
- 0x78, 0x40, 0xa7, 0xd4, 0x96, 0x0d, 0x22, 0x5d, 0x2d, 0xb0, 0x79, 0x26,
- 0x44, 0xb5, 0xb7, 0x48, 0x54, 0xba, 0x67, 0x55, 0x27, 0xca, 0x3c, 0x5b,
- 0x16, 0x6f, 0x81, 0x7e, 0x40, 0x59, 0x07, 0xca, 0xb6, 0xd9, 0xb2, 0xb6,
- 0x16, 0x69, 0x44, 0xd9, 0x8c, 0xe6, 0xf9, 0xf3, 0x3d, 0x9e, 0x9b, 0x75,
- 0x9a, 0xa5, 0xeb, 0x44, 0x0b, 0x64, 0xc3, 0x46, 0x59, 0xbc, 0xaa, 0x49,
- 0xba, 0xf0, 0x8e, 0x71, 0x6e, 0xff, 0x44, 0x4c, 0xae, 0x3d, 0xd1, 0x9d,
- 0xf8, 0x38, 0xe6, 0xd0, 0x7d, 0x8a, 0x71, 0xef, 0xfc, 0x25, 0x8c, 0xfb,
- 0x74, 0x9d, 0xe2, 0xbd, 0x49, 0xcb, 0x1f, 0xe2, 0xc3, 0x7c, 0x93, 0x88,
- 0x32, 0xf9, 0x24, 0xfc, 0x5c, 0xea, 0xf0, 0x6e, 0xfb, 0xfd, 0x8c, 0xe3,
- 0x97, 0xd0, 0x6f, 0x9b, 0xa5, 0x5d, 0x52, 0x24, 0x3f, 0x52, 0x0f, 0xe1,
- 0x3e, 0xe3, 0x48, 0xbe, 0x2a, 0xb3, 0xe6, 0xc9, 0x57, 0xc7, 0x14, 0x73,
- 0x59, 0x50, 0x56, 0xf9, 0xc5, 0xc0, 0xac, 0x31, 0x79, 0xc1, 0xc8, 0xa5,
- 0x0f, 0x18, 0xb9, 0xf4, 0xd8, 0x99, 0x15, 0x72, 0xe9, 0xbc, 0x96, 0x4b,
- 0x7b, 0x05, 0xf7, 0xf9, 0xf3, 0x90, 0x4b, 0x2f, 0xe2, 0xd9, 0xd5, 0x72,
- 0x29, 0x2e, 0xd6, 0x5e, 0x96, 0xaf, 0xea, 0xf1, 0xe7, 0x8a, 0x51, 0x6d,
- 0x57, 0xe5, 0x67, 0x60, 0x93, 0x14, 0xa7, 0xac, 0xfe, 0x96, 0xa1, 0x36,
- 0xe9, 0x19, 0xfc, 0xa9, 0x84, 0x36, 0xe7, 0x7f, 0xba, 0x84, 0xdf, 0xee,
- 0x7c, 0x5e, 0x51, 0x86, 0xbd, 0x0a, 0x19, 0x26, 0xaa, 0xbe, 0x0c, 0xc3,
- 0xbb, 0x32, 0xde, 0x95, 0xd9, 0xef, 0x8f, 0x7e, 0x3a, 0xe6, 0x52, 0x7e,
- 0x50, 0x66, 0x40, 0x26, 0x15, 0x21, 0x93, 0x8a, 0x90, 0x53, 0x45, 0xc8,
- 0x25, 0xd8, 0x6c, 0x67, 0x8a, 0x90, 0x4b, 0x45, 0xc8, 0x25, 0xc8, 0xb8,
- 0x27, 0x20, 0xe3, 0x8c, 0x4c, 0x1b, 0x85, 0x4c, 0x9b, 0x91, 0xfb, 0xac,
- 0xae, 0x37, 0xb1, 0x92, 0x7e, 0xeb, 0x23, 0x0d, 0xe8, 0x18, 0xf2, 0x99,
- 0x9a, 0xd8, 0xe0, 0x8d, 0x47, 0x34, 0xbf, 0xbb, 0x9e, 0xba, 0xc2, 0x61,
- 0x0e, 0xcd, 0x4f, 0xb4, 0xff, 0xbe, 0x9d, 0xbf, 0xa5, 0x09, 0x7c, 0xfd,
- 0x03, 0xcb, 0xd7, 0xdb, 0x97, 0xf9, 0x3a, 0xe5, 0x30, 0x56, 0x5c, 0x9f,
- 0xaf, 0x3b, 0xec, 0xbb, 0x5c, 0xb0, 0x0e, 0x7c, 0xbd, 0x6e, 0x15, 0x5f,
- 0xc7, 0xc0, 0xd7, 0x7b, 0xd6, 0xf0, 0xf5, 0x06, 0x67, 0x58, 0xb7, 0xe1,
- 0x19, 0x09, 0x3e, 0x37, 0x3a, 0x55, 0xbe, 0xbe, 0x47, 0xf3, 0xf5, 0x21,
- 0xf0, 0xf5, 0x75, 0x35, 0x7c, 0xbd, 0x47, 0x52, 0x37, 0x67, 0x22, 0x5b,
- 0x65, 0xfc, 0x7e, 0xd5, 0xbe, 0x49, 0xfe, 0x49, 0x4c, 0x7b, 0xc3, 0x63,
- 0xc3, 0xd3, 0xed, 0x92, 0x7d, 0xe8, 0x15, 0x94, 0x91, 0xcf, 0x52, 0x63,
- 0x69, 0xc7, 0x95, 0x83, 0x47, 0x7e, 0x22, 0x0b, 0x9a, 0xb7, 0x44, 0x26,
- 0x8e, 0xc4, 0x64, 0xf2, 0x08, 0xe3, 0x10, 0x7f, 0x63, 0xe9, 0xbd, 0x49,
- 0x26, 0xf7, 0x32, 0x6f, 0x2e, 0x2a, 0xe3, 0x47, 0xe0, 0x6f, 0x1d, 0x61,
- 0x1c, 0xe2, 0xa5, 0x65, 0x1e, 0x5b, 0x80, 0x6c, 0x19, 0x3f, 0xc2, 0xb5,
- 0x8e, 0xa1, 0x9f, 0x16, 0x39, 0x74, 0x44, 0xe4, 0xb6, 0x23, 0x51, 0xf9,
- 0xe8, 0x91, 0x65, 0x5e, 0x1b, 0x0d, 0x79, 0xed, 0x59, 0xf0, 0x5a, 0xb7,
- 0xe5, 0x35, 0xb5, 0xcc, 0x6b, 0x7f, 0x5a, 0xc3, 0x6b, 0x6c, 0x4f, 0x5e,
- 0x7b, 0xce, 0x96, 0xf1, 0x39, 0x2a, 0xfb, 0x8e, 0x74, 0xca, 0xf8, 0x43,
- 0x6f, 0x91, 0x89, 0xfb, 0x09, 0xab, 0xf9, 0x8e, 0x13, 0x6d, 0xb1, 0x99,
- 0x4a, 0x37, 0xfa, 0x0f, 0x73, 0x88, 0xf4, 0xf7, 0x10, 0x7a, 0x67, 0x25,
- 0x95, 0xe3, 0x78, 0x8d, 0xf0, 0xa3, 0x4f, 0xc0, 0xbf, 0xd8, 0x07, 0x98,
- 0x6e, 0x39, 0x22, 0xa9, 0xa8, 0xbc, 0x2c, 0x53, 0xfe, 0x27, 0x2e, 0x37,
- 0xf6, 0x04, 0x6c, 0x11, 0x6d, 0xfb, 0xa4, 0x25, 0xfb, 0xce, 0x40, 0xfb,
- 0x18, 0xa5, 0xb2, 0x30, 0x16, 0xc0, 0xb8, 0xb9, 0x63, 0xbe, 0xc7, 0xc4,
- 0xfc, 0xc7, 0x06, 0x7d, 0xe6, 0x45, 0xc7, 0x6c, 0x07, 0xf8, 0x9e, 0xcf,
- 0xb0, 0x67, 0xf4, 0x59, 0x43, 0xb6, 0x7f, 0x44, 0x7f, 0x1b, 0x91, 0x31,
- 0xf5, 0x7c, 0x99, 0xdf, 0xb0, 0x81, 0xff, 0x59, 0xe6, 0xb7, 0xb0, 0xf6,
- 0xb7, 0x9b, 0xf8, 0x2c, 0xf9, 0xee, 0x87, 0x0e, 0xbf, 0x5d, 0x35, 0xa5,
- 0x73, 0xbd, 0xf0, 0xbb, 0xcc, 0x67, 0xd6, 0x7f, 0x84, 0xf1, 0x8e, 0x64,
- 0x52, 0xbd, 0xf7, 0x72, 0xe6, 0x1e, 0xec, 0x9d, 0x67, 0xdd, 0xad, 0x96,
- 0x47, 0xb7, 0x6a, 0xbf, 0x83, 0x36, 0xd6, 0x78, 0xe9, 0x45, 0xc9, 0xd3,
- 0x36, 0x19, 0xdd, 0xea, 0xe4, 0x66, 0x92, 0x97, 0x1b, 0xfb, 0x79, 0xdd,
- 0xa5, 0xcc, 0x3b, 0x4c, 0xab, 0xb5, 0x32, 0xf9, 0x84, 0x84, 0x32, 0x39,
- 0x75, 0x33, 0xbf, 0xb7, 0x9b, 0x3d, 0xa2, 0xbf, 0x2f, 0x95, 0xec, 0x56,
- 0x9c, 0xd3, 0xa7, 0x21, 0x5f, 0x43, 0x5a, 0x48, 0xc8, 0x27, 0x8f, 0x90,
- 0x1e, 0x54, 0xbc, 0x55, 0x3e, 0x61, 0xe9, 0x61, 0x46, 0x0a, 0x90, 0x3b,
- 0x47, 0x8e, 0x7c, 0x54, 0x66, 0x6e, 0x5c, 0x4d, 0x0f, 0x13, 0x55, 0x7a,
- 0x88, 0xc3, 0x3e, 0x73, 0x6a, 0xe9, 0xe1, 0x97, 0x97, 0xe9, 0x61, 0xc6,
- 0xf9, 0xe7, 0xd2, 0xc3, 0xf5, 0x2b, 0xe8, 0x61, 0x4a, 0xd3, 0xc3, 0xce,
- 0x65, 0x7a, 0x98, 0x3a, 0xc2, 0x71, 0xf5, 0xde, 0xa8, 0xbb, 0xe8, 0x70,
- 0xcd, 0x97, 0x69, 0x21, 0x39, 0xa9, 0xf3, 0xf5, 0x53, 0x39, 0x9e, 0x6f,
- 0xda, 0xa0, 0x18, 0x27, 0xa9, 0xae, 0x7f, 0xeb, 0xbf, 0xe8, 0xfa, 0xbf,
- 0xfc, 0xff, 0x79, 0xfd, 0xd5, 0xa5, 0xcc, 0xdd, 0xe7, 0x99, 0x55, 0x23,
- 0x8f, 0x43, 0x7a, 0x88, 0x5d, 0x6a, 0xf4, 0x02, 0xd7, 0x98, 0xcf, 0x90,
- 0x67, 0x90, 0x7f, 0x67, 0x20, 0xff, 0x9e, 0x84, 0xfc, 0x3b, 0xbd, 0x62,
- 0x4f, 0x60, 0xd0, 0xc6, 0x23, 0x02, 0x39, 0xe8, 0x57, 0xf1, 0xb1, 0x38,
- 0x40, 0x7c, 0x98, 0xfc, 0x13, 0xe6, 0xfe, 0xae, 0xc4, 0x49, 0x54, 0xe7,
- 0x1c, 0x3d, 0xea, 0xd7, 0xe2, 0x84, 0x70, 0xbf, 0x5c, 0x33, 0x47, 0xfc,
- 0x2e, 0xf3, 0x79, 0x46, 0xe7, 0x91, 0xe4, 0xf5, 0x1e, 0x14, 0xf1, 0xc2,
- 0x3d, 0x28, 0xe2, 0x24, 0xaa, 0xed, 0xfd, 0x7c, 0xb9, 0x49, 0xe7, 0xd0,
- 0x1f, 0x98, 0x8f, 0xcb, 0x62, 0x9c, 0x31, 0x3e, 0x7e, 0x97, 0x90, 0x7e,
- 0xb3, 0x97, 0xc8, 0x4b, 0x8e, 0xb9, 0x72, 0xe0, 0xe9, 0x0d, 0x96, 0xb6,
- 0x19, 0x1b, 0xe4, 0x99, 0xdd, 0x70, 0x2f, 0xa2, 0xd7, 0xca, 0xba, 0x96,
- 0x9a, 0x98, 0x25, 0xf0, 0x3e, 0x2d, 0xc9, 0xcc, 0x00, 0xee, 0xf3, 0x1c,
- 0x7b, 0xbf, 0x4c, 0x3d, 0x38, 0x01, 0x5b, 0x6e, 0x2f, 0x74, 0x0e, 0xcf,
- 0x9f, 0x99, 0xef, 0x70, 0x13, 0x86, 0x59, 0xfd, 0xdd, 0x29, 0xfa, 0x80,
- 0xa4, 0x87, 0x04, 0x9e, 0x67, 0x6c, 0x5c, 0x29, 0x21, 0xf9, 0xc2, 0x05,
- 0xf3, 0x6d, 0xcb, 0xc2, 0x4b, 0xb8, 0xbf, 0xde, 0x7a, 0x18, 0x3f, 0x64,
- 0xd4, 0xdc, 0xd1, 0xd7, 0x92, 0xa4, 0xcb, 0x26, 0xc7, 0xa5, 0x1a, 0x37,
- 0x99, 0x91, 0xc3, 0xda, 0x7e, 0x1e, 0xb2, 0xb9, 0x2d, 0xa9, 0xd1, 0x9c,
- 0x18, 0x1b, 0xfa, 0x77, 0x60, 0x43, 0x7f, 0xb1, 0x92, 0xd6, 0xfb, 0x58,
- 0xa7, 0x61, 0x43, 0x3f, 0x01, 0xdd, 0x43, 0x9d, 0x13, 0xb7, 0x3a, 0x67,
- 0x4a, 0xdd, 0xa8, 0x75, 0xce, 0x37, 0xb5, 0xce, 0x79, 0xef, 0x1a, 0x9d,
- 0x73, 0x48, 0x75, 0x97, 0xa8, 0x73, 0x86, 0xd5, 0x1e, 0x87, 0xf6, 0xe2,
- 0xe6, 0x3a, 0x3a, 0xe7, 0x7d, 0xf2, 0x2e, 0xfb, 0xee, 0x1e, 0x79, 0xff,
- 0x0e, 0xbd, 0x77, 0xe3, 0xce, 0x2a, 0x7e, 0x6b, 0xc9, 0xe8, 0xa0, 0xeb,
- 0x54, 0xaf, 0xde, 0xf3, 0xfd, 0x46, 0x8d, 0xce, 0xe9, 0x52, 0x03, 0xce,
- 0xb0, 0x6e, 0xc3, 0xd8, 0x04, 0x9f, 0x7d, 0x27, 0x3d, 0xda, 0x84, 0xe7,
- 0x84, 0x44, 0x8e, 0x60, 0xee, 0xe6, 0x7b, 0x50, 0xca, 0xbc, 0x7b, 0xab,
- 0x7d, 0xa7, 0xc2, 0xf2, 0xa8, 0x29, 0xef, 0xb6, 0xe5, 0x46, 0x57, 0x75,
- 0xa9, 0x4e, 0xad, 0xab, 0xb6, 0x83, 0xa1, 0x66, 0xa1, 0x5f, 0x67, 0x8b,
- 0xa1, 0xce, 0xe2, 0x6f, 0xc6, 0x9e, 0x19, 0xa3, 0x08, 0x63, 0xd8, 0x49,
- 0xd4, 0xc1, 0x55, 0x0c, 0x6d, 0x4a, 0xfe, 0x86, 0xaf, 0x80, 0x6b, 0x1e,
- 0x78, 0xbd, 0x19, 0xfc, 0xf3, 0x6f, 0x0a, 0x8c, 0x81, 0xb6, 0xcb, 0xd1,
- 0xe9, 0xda, 0x77, 0x9d, 0xf2, 0x9e, 0xe9, 0x2d, 0xb2, 0xbf, 0xf4, 0x2d,
- 0xf0, 0xc1, 0x56, 0x99, 0x2a, 0x15, 0xf4, 0x79, 0xf5, 0x4d, 0xfa, 0x3b,
- 0x1e, 0xfc, 0xbe, 0x8d, 0x91, 0x91, 0x3b, 0x1d, 0x23, 0x23, 0xd3, 0xaa,
- 0x6a, 0xb3, 0x86, 0x7d, 0xf2, 0xdb, 0x21, 0x23, 0xa5, 0x84, 0xfe, 0xc6,
- 0xe9, 0x6c, 0xe5, 0x0a, 0xf9, 0xc2, 0x31, 0x75, 0xa7, 0xaa, 0x9e, 0xef,
- 0xd5, 0x36, 0xeb, 0xdc, 0x0a, 0x9b, 0xf5, 0xaf, 0x64, 0xf1, 0xfd, 0x31,
- 0xcc, 0x13, 0x34, 0x7c, 0xe5, 0xf7, 0xb8, 0x17, 0xda, 0x1e, 0x97, 0x0b,
- 0x32, 0xa2, 0xf1, 0x47, 0x79, 0xda, 0x02, 0x39, 0xb8, 0xa4, 0xf5, 0xeb,
- 0x66, 0xd0, 0x20, 0x65, 0xe9, 0xc7, 0xe4, 0x45, 0x2d, 0xcf, 0x36, 0x5b,
- 0xdb, 0x75, 0x81, 0xb1, 0xd4, 0x23, 0xb4, 0x5d, 0xbf, 0x69, 0xcb, 0x59,
- 0x96, 0x4a, 0x2c, 0x09, 0xf5, 0x5d, 0x1c, 0x32, 0x94, 0xf2, 0xf4, 0x8d,
- 0xda, 0xae, 0x5f, 0xb3, 0x7d, 0x50, 0x7e, 0x1a, 0xd9, 0xbd, 0xdd, 0x59,
- 0xb0, 0x65, 0x7c, 0x0e, 0xe3, 0xe9, 0x5e, 0x3a, 0x6b, 0xf9, 0x4c, 0x39,
- 0x5f, 0xc2, 0xfb, 0x4d, 0x78, 0x4f, 0x3e, 0x3b, 0xad, 0xf9, 0x4c, 0xdb,
- 0x27, 0x4e, 0xbf, 0xdd, 0x5f, 0x58, 0xde, 0x1b, 0xc8, 0x91, 0xcf, 0xd4,
- 0x51, 0x77, 0xc1, 0xc8, 0x03, 0xe6, 0xa9, 0x7e, 0x1e, 0xba, 0x83, 0x6d,
- 0x51, 0xfe, 0x70, 0x9a, 0xbe, 0x2d, 0xfc, 0x9f, 0x56, 0x3c, 0xb7, 0xe3,
- 0x79, 0x56, 0xde, 0xbb, 0x37, 0xa6, 0xe7, 0x3d, 0x85, 0x79, 0x1c, 0x38,
- 0x82, 0x39, 0x39, 0xc6, 0x76, 0x8e, 0x9e, 0x8a, 0x4a, 0xc3, 0x29, 0xf2,
- 0x1d, 0xcf, 0xda, 0x04, 0xc1, 0xbe, 0x7e, 0xd2, 0x6d, 0xca, 0xdd, 0xa9,
- 0xcf, 0x96, 0x6e, 0x4f, 0x44, 0x80, 0x93, 0x03, 0x58, 0x8f, 0xa9, 0x82,
- 0xe7, 0x66, 0x1c, 0x2f, 0x81, 0x79, 0xc2, 0x06, 0xec, 0x86, 0x2d, 0xd8,
- 0x0d, 0x3b, 0xb0, 0x1b, 0x76, 0xe0, 0x46, 0x39, 0x71, 0x15, 0x73, 0x4c,
- 0x72, 0xd7, 0xc2, 0x2b, 0x97, 0xef, 0xe8, 0x38, 0x7d, 0xe3, 0xcd, 0x23,
- 0xf0, 0xd9, 0xc5, 0x4d, 0x8d, 0x32, 0x0f, 0x7f, 0xc9, 0x6d, 0xbc, 0x79,
- 0xa7, 0x74, 0x0f, 0xe2, 0xfd, 0xe0, 0x05, 0xe9, 0xb9, 0xf9, 0x56, 0xa7,
- 0x71, 0x74, 0x04, 0x78, 0x4c, 0x3b, 0xa9, 0xc4, 0x98, 0xb3, 0x80, 0x71,
- 0x32, 0xdb, 0x23, 0xc2, 0xb8, 0xe5, 0x02, 0x63, 0x11, 0x37, 0x77, 0x47,
- 0xfa, 0x92, 0xe3, 0x4e, 0x6a, 0x54, 0x45, 0x52, 0xa3, 0x23, 0x4e, 0x58,
- 0x8f, 0xdf, 0x48, 0x85, 0x9c, 0x01, 0xac, 0x07, 0x8a, 0xd3, 0xa0, 0xa7,
- 0xff, 0x28, 0xf9, 0x63, 0x2d, 0x32, 0x5f, 0xe8, 0x76, 0x33, 0x2a, 0xae,
- 0x73, 0x4b, 0xd4, 0x09, 0x10, 0xfd, 0xa9, 0x98, 0xcc, 0x96, 0xb6, 0x8a,
- 0xd2, 0xb6, 0x7b, 0x87, 0x64, 0xa6, 0x4b, 0x72, 0x6e, 0x40, 0xda, 0x14,
- 0xfa, 0xe7, 0xb7, 0x67, 0xd5, 0x09, 0xee, 0x25, 0x86, 0xbc, 0x70, 0x39,
- 0xf9, 0xa4, 0x04, 0x1c, 0x82, 0x6e, 0x19, 0xe3, 0x6d, 0x12, 0xca, 0xbd,
- 0x8f, 0xea, 0xf8, 0x29, 0x63, 0xb6, 0xb5, 0x7b, 0x0f, 0xe4, 0x8f, 0x58,
- 0x5d, 0xfe, 0x98, 0x2b, 0x72, 0x9f, 0x46, 0x72, 0x51, 0xc6, 0x88, 0x3d,
- 0xfc, 0x9e, 0x61, 0xdd, 0x26, 0x99, 0x1a, 0xc8, 0xd9, 0x3c, 0x8f, 0x47,
- 0x12, 0xcc, 0x21, 0x26, 0x4e, 0xc6, 0x07, 0xc8, 0xeb, 0xab, 0xf7, 0x36,
- 0x62, 0x35, 0xf2, 0xc0, 0x91, 0xc5, 0x52, 0xb8, 0x17, 0xc2, 0xfe, 0xf0,
- 0x3c, 0x63, 0xe4, 0x6d, 0x66, 0x4d, 0x3b, 0xc2, 0xc5, 0xfd, 0xca, 0x95,
- 0x32, 0x56, 0x79, 0x94, 0xa9, 0xae, 0x96, 0xaf, 0x8f, 0x55, 0x8c, 0x6c,
- 0x9d, 0xa9, 0x84, 0xba, 0x25, 0x66, 0x74, 0xe9, 0x1a, 0x7d, 0x62, 0xa2,
- 0x99, 0x55, 0x7d, 0x42, 0xbd, 0xa8, 0xe4, 0x03, 0xf3, 0x1d, 0x12, 0x7d,
- 0x58, 0x96, 0xa6, 0xbc, 0xec, 0xe5, 0xcc, 0xd5, 0x98, 0xf2, 0xdf, 0x8c,
- 0x7e, 0xfc, 0x6f, 0x09, 0xea, 0xc3, 0x31, 0xf5, 0x75, 0xdc, 0x37, 0x69,
- 0xfa, 0x03, 0x4f, 0xe1, 0xd9, 0xf8, 0x09, 0xbf, 0x03, 0x3f, 0xe1, 0x8b,
- 0xd0, 0x75, 0x67, 0xe0, 0x27, 0x3c, 0x09, 0x3f, 0xe1, 0x34, 0xfc, 0x84,
- 0x27, 0xa0, 0x27, 0x6b, 0xfd, 0x83, 0xc9, 0x15, 0xfe, 0x41, 0xa0, 0xf9,
- 0x9f, 0xf1, 0xc0, 0x27, 0x6b, 0x7c, 0x83, 0x7d, 0x46, 0x5f, 0xc1, 0xef,
- 0x37, 0x7c, 0xd4, 0xa5, 0x6e, 0xd2, 0xfa, 0xd1, 0xe4, 0xed, 0x8e, 0x2e,
- 0xeb, 0xab, 0x2e, 0x65, 0xf4, 0xd5, 0x6c, 0x55, 0x5f, 0x19, 0x3e, 0x7a,
- 0xb8, 0x24, 0x11, 0xaf, 0xb4, 0x90, 0xf1, 0x77, 0x69, 0x1e, 0x6a, 0xf3,
- 0xb6, 0x4a, 0xe4, 0x01, 0xd5, 0xde, 0x20, 0x19, 0xfb, 0x0c, 0xfa, 0x3a,
- 0x3a, 0x8d, 0xbe, 0xae, 0x95, 0xac, 0xb6, 0xcf, 0x2e, 0x8e, 0xef, 0x27,
- 0x56, 0xe1, 0x3b, 0x5f, 0xbc, 0x5b, 0xe3, 0xfc, 0xfe, 0x32, 0xf7, 0x59,
- 0x5a, 0x64, 0xb2, 0x1c, 0xe2, 0x9c, 0xe7, 0x59, 0x99, 0x8b, 0xd1, 0x29,
- 0x91, 0x87, 0x3b, 0x78, 0xce, 0x4a, 0x65, 0xfd, 0xf5, 0x3a, 0x87, 0xe5,
- 0xc4, 0x80, 0x24, 0xb2, 0x03, 0xa4, 0xd5, 0xfb, 0x64, 0x56, 0xaf, 0x45,
- 0x87, 0x34, 0x3c, 0x4c, 0x1b, 0x25, 0xdc, 0xcf, 0xeb, 0xba, 0xcc, 0x7e,
- 0x23, 0x35, 0x66, 0xea, 0x89, 0x1c, 0xd4, 0xeb, 0x75, 0x5c, 0xe7, 0x19,
- 0xde, 0x34, 0xcf, 0xb8, 0x3c, 0xbf, 0x47, 0xc5, 0x98, 0xfc, 0x3f, 0x67,
- 0xfd, 0x7e, 0xe1, 0x32, 0x63, 0xcf, 0x6c, 0xb2, 0x76, 0x8c, 0x89, 0x53,
- 0xd5, 0xb7, 0x61, 0xd8, 0x4f, 0xed, 0x37, 0x14, 0xb7, 0x38, 0x93, 0xa5,
- 0xad, 0x4e, 0xbe, 0xc4, 0xbd, 0x6c, 0xfb, 0xf7, 0x2e, 0xdc, 0x3d, 0xce,
- 0x01, 0x6f, 0x0b, 0xca, 0x18, 0xb3, 0x64, 0xcc, 0xe6, 0x97, 0x2e, 0x63,
- 0x8c, 0x36, 0xe3, 0x71, 0x6c, 0x96, 0x6d, 0x71, 0xa6, 0x4a, 0xdd, 0xf0,
- 0xcd, 0x79, 0xae, 0x8a, 0xef, 0x77, 0x72, 0xed, 0xa0, 0x83, 0x5d, 0x7d,
- 0x66, 0x77, 0x42, 0xae, 0xb0, 0x31, 0x68, 0xea, 0xe1, 0x9f, 0x5f, 0xb1,
- 0x77, 0x7b, 0x08, 0x7a, 0xec, 0x16, 0xc8, 0x23, 0xea, 0xe1, 0x43, 0x72,
- 0xb5, 0xa5, 0xe7, 0x95, 0x7a, 0xf8, 0xbc, 0x30, 0x4e, 0xdc, 0x8f, 0x77,
- 0xb9, 0x20, 0x06, 0x7a, 0x38, 0x5c, 0xe3, 0xab, 0xd1, 0xef, 0x6b, 0x1a,
- 0x32, 0xfb, 0x61, 0x2b, 0xfd, 0x3e, 0xc8, 0x81, 0x78, 0xe8, 0xe7, 0x35,
- 0x2e, 0xef, 0xd7, 0xee, 0xb1, 0x6d, 0xa7, 0xfc, 0xfb, 0x89, 0xa3, 0xe4,
- 0x21, 0xe9, 0x81, 0x2e, 0x63, 0x0e, 0xc8, 0x6f, 0x69, 0x9c, 0x89, 0x22,
- 0xed, 0x6d, 0xd2, 0x30, 0x5a, 0x39, 0x9f, 0x0c, 0x73, 0x38, 0xf2, 0xb6,
- 0xed, 0x84, 0xdd, 0x93, 0xcf, 0xcb, 0xdc, 0x65, 0xd4, 0x83, 0x23, 0x91,
- 0xf5, 0xfc, 0x7e, 0x22, 0xda, 0xf6, 0x18, 0xbd, 0x28, 0x61, 0x5f, 0x7c,
- 0x6e, 0xa8, 0xe9, 0x9b, 0x76, 0x14, 0xef, 0xab, 0xcf, 0x91, 0x3d, 0xa3,
- 0xf7, 0x19, 0xcd, 0xf7, 0x12, 0x42, 0x3e, 0x21, 0xef, 0x24, 0xf5, 0x59,
- 0x27, 0xef, 0x61, 0xda, 0x3d, 0xdc, 0x83, 0x75, 0x17, 0x26, 0xfd, 0x4f,
- 0xe8, 0x6f, 0xfc, 0xcd, 0x88, 0x38, 0x79, 0xff, 0x36, 0x9d, 0x7b, 0x92,
- 0xd7, 0xb1, 0xe6, 0x1c, 0xee, 0x55, 0x1f, 0xb5, 0xeb, 0x61, 0xfe, 0x4d,
- 0x0b, 0x96, 0x65, 0x01, 0x1b, 0x75, 0x08, 0x65, 0x6f, 0x5c, 0xba, 0x8e,
- 0x7e, 0x58, 0xf3, 0xc2, 0x66, 0xf8, 0x02, 0xc3, 0x47, 0xa1, 0xab, 0x8f,
- 0x26, 0x64, 0xe7, 0x51, 0xad, 0x1b, 0xd3, 0x6b, 0x63, 0x05, 0x7d, 0x6e,
- 0xd4, 0x79, 0x8f, 0x3e, 0xc7, 0xf6, 0xd6, 0xa3, 0x11, 0x39, 0x1c, 0xef,
- 0x73, 0x7b, 0x9c, 0xf7, 0x5a, 0x5d, 0x18, 0xc6, 0xb0, 0x5b, 0xd0, 0xfe,
- 0xf5, 0xe2, 0xd8, 0x61, 0xfc, 0x3a, 0x22, 0x33, 0x7b, 0x3b, 0x01, 0xdb,
- 0x5f, 0x5d, 0x66, 0xce, 0x20, 0x63, 0xad, 0xf4, 0xb7, 0xe7, 0xa3, 0x09,
- 0xca, 0xb2, 0x2e, 0xc0, 0x32, 0x72, 0x94, 0xfa, 0xcc, 0xd3, 0x3c, 0x0e,
- 0x18, 0xdc, 0x06, 0xed, 0x87, 0x90, 0x2f, 0xdf, 0x22, 0xde, 0x03, 0x90,
- 0x71, 0x47, 0x63, 0xd2, 0x73, 0xb4, 0x45, 0xb6, 0x1d, 0xa5, 0x1f, 0x52,
- 0xeb, 0x97, 0xd2, 0x2e, 0x7d, 0x04, 0x73, 0x7c, 0xb7, 0x96, 0x93, 0xdc,
- 0xd3, 0xdc, 0x4f, 0xde, 0x45, 0xdd, 0x2c, 0x6c, 0xe6, 0xcc, 0x51, 0x57,
- 0xef, 0x91, 0x66, 0x30, 0xe7, 0x6c, 0xd9, 0xc5, 0x38, 0x46, 0xe6, 0xe4,
- 0xe9, 0xa7, 0x8c, 0x76, 0x00, 0xc7, 0xef, 0xb5, 0xbc, 0xb3, 0xbe, 0xc3,
- 0xf2, 0xe8, 0xcf, 0xc8, 0x7b, 0x5b, 0x3a, 0x8c, 0xec, 0x7c, 0x4b, 0x07,
- 0x73, 0x93, 0x36, 0x7b, 0xbc, 0x37, 0x69, 0x7b, 0xc2, 0xc8, 0xd0, 0xd7,
- 0xe2, 0x45, 0x01, 0x8e, 0xc2, 0x7d, 0x29, 0x7d, 0x96, 0x2f, 0x38, 0xe7,
- 0xeb, 0xf3, 0x2b, 0xfe, 0xa2, 0xfe, 0x3b, 0x21, 0xdc, 0x23, 0xab, 0x7e,
- 0x6f, 0x65, 0x57, 0x85, 0x71, 0xf2, 0xcf, 0x86, 0x7f, 0x97, 0xa4, 0x26,
- 0xef, 0xb0, 0x76, 0x0f, 0x8c, 0xb1, 0xa6, 0xe5, 0xdc, 0xa0, 0xa0, 0xa4,
- 0xbf, 0x5f, 0xf4, 0x9c, 0x73, 0xbe, 0x70, 0xd6, 0xf9, 0xee, 0xb4, 0x04,
- 0x51, 0xef, 0x27, 0xce, 0xf7, 0x3d, 0xee, 0x99, 0x7f, 0xdd, 0xf9, 0x5e,
- 0xc1, 0x03, 0x1f, 0xde, 0x87, 0x79, 0xbc, 0xe2, 0xfc, 0x00, 0xeb, 0x7b,
- 0xb0, 0x98, 0x4e, 0xb9, 0x36, 0x26, 0x7e, 0xb6, 0xf0, 0x8a, 0xf3, 0xb5,
- 0x6a, 0x3c, 0x69, 0x30, 0xa4, 0x91, 0x43, 0x7c, 0x57, 0xc6, 0xbb, 0xb2,
- 0xde, 0xff, 0x71, 0xe6, 0xa6, 0x6d, 0x7e, 0x89, 0xe6, 0xe3, 0x85, 0xe5,
- 0x7d, 0x99, 0x51, 0xbd, 0x57, 0xf1, 0xac, 0x33, 0x37, 0x7f, 0x77, 0x87,
- 0xc9, 0x33, 0x3a, 0x8b, 0x77, 0x26, 0xe7, 0x72, 0x76, 0xfe, 0x2c, 0xea,
- 0x3c, 0xe3, 0xcc, 0xea, 0xf8, 0x97, 0xf6, 0xc5, 0x9d, 0x99, 0xf9, 0x67,
- 0x9c, 0x79, 0xbd, 0x07, 0x7d, 0xce, 0x79, 0x74, 0x9a, 0x7d, 0x9f, 0x43,
- 0x9d, 0x05, 0xe7, 0x04, 0xfa, 0x9b, 0x9f, 0xe6, 0x79, 0xdc, 0x6e, 0xd8,
- 0x05, 0xfc, 0x7b, 0x3f, 0xfc, 0x1e, 0xc7, 0xb3, 0xce, 0xfc, 0x72, 0xbf,
- 0x8b, 0xe8, 0x87, 0x75, 0x49, 0x8b, 0x1c, 0xf7, 0x59, 0xf4, 0xbf, 0x76,
- 0xaf, 0x6a, 0x2d, 0x4e, 0x5e, 0x00, 0x4e, 0x2e, 0x58, 0x9c, 0xbc, 0x6a,
- 0x71, 0xf2, 0x7c, 0x0d, 0x4e, 0x44, 0xad, 0xc4, 0xc9, 0xab, 0xc0, 0x89,
- 0xa8, 0xfa, 0x38, 0xc1, 0xbb, 0x32, 0xde, 0x69, 0x9c, 0xbc, 0xb4, 0x0a,
- 0x27, 0x4b, 0xcb, 0x71, 0x79, 0x83, 0x93, 0x17, 0x81, 0x93, 0xaf, 0x5a,
- 0xd8, 0x2f, 0x58, 0x9c, 0xe0, 0x3e, 0x7f, 0x01, 0x75, 0x5e, 0xaa, 0xc1,
- 0xc9, 0x05, 0xe0, 0xe4, 0x25, 0x8b, 0x93, 0xef, 0x5b, 0x9c, 0x7c, 0x1f,
- 0x75, 0x96, 0x80, 0x93, 0xf3, 0x75, 0x70, 0xf2, 0x22, 0x70, 0x12, 0xf6,
- 0x7b, 0x1e, 0xfd, 0x7c, 0xbf, 0x06, 0x27, 0x2f, 0xd6, 0xc1, 0x09, 0xf7,
- 0x62, 0xc3, 0x9c, 0xee, 0x99, 0xd7, 0xc9, 0xe9, 0x96, 0x3b, 0x5f, 0x3f,
- 0xa7, 0x9b, 0x75, 0x66, 0xa4, 0xfa, 0x37, 0x25, 0xee, 0xb6, 0x39, 0x6a,
- 0x26, 0x17, 0xb0, 0xfa, 0xcd, 0xa6, 0x6e, 0xf0, 0x79, 0x3e, 0xe7, 0x8a,
- 0xc9, 0x29, 0x8d, 0xee, 0xf8, 0x10, 0x78, 0x6d, 0x97, 0x1c, 0x38, 0xd6,
- 0x78, 0x38, 0x6b, 0xcb, 0xbc, 0x1d, 0xdd, 0x39, 0xa5, 0xf8, 0x2e, 0xcc,
- 0x49, 0xa0, 0x5f, 0xd2, 0xc0, 0x6f, 0x0b, 0xf6, 0xa6, 0xa5, 0x76, 0x4f,
- 0xba, 0xc0, 0x6f, 0x34, 0x61, 0xec, 0x25, 0xfe, 0xfd, 0x8b, 0x24, 0xf3,
- 0xac, 0xf2, 0x1a, 0xde, 0x14, 0xf4, 0xc7, 0xa0, 0xce, 0xad, 0xca, 0x14,
- 0x68, 0x73, 0x27, 0x99, 0xa3, 0x06, 0x5b, 0x79, 0xc8, 0x9e, 0x09, 0xf3,
- 0xf5, 0x39, 0x95, 0x2a, 0xff, 0xd4, 0x9e, 0x87, 0x26, 0xdf, 0x55, 0xe9,
- 0xe6, 0xe0, 0xf2, 0x77, 0x02, 0x4f, 0xca, 0xd3, 0x3a, 0x56, 0xdc, 0x8c,
- 0xf5, 0x09, 0x82, 0xc7, 0x7c, 0x13, 0xa3, 0x5d, 0xd4, 0x31, 0x5a, 0x81,
- 0x37, 0x3e, 0x69, 0xe3, 0xb4, 0x3d, 0x83, 0x2f, 0x2d, 0xc7, 0x68, 0x6b,
- 0xf3, 0x59, 0xcc, 0xfe, 0x7a, 0xa6, 0xf4, 0x88, 0xce, 0xd1, 0x19, 0xe1,
- 0xf7, 0x37, 0x20, 0x23, 0x26, 0x66, 0xe6, 0x65, 0xf2, 0x41, 0x3e, 0x53,
- 0xbf, 0x45, 0xa0, 0xc3, 0x28, 0xc3, 0x73, 0x92, 0x19, 0x64, 0x99, 0x69,
- 0x33, 0xa2, 0xfd, 0xe5, 0x93, 0x32, 0xbc, 0x3c, 0x3e, 0xf1, 0x7b, 0x57,
- 0xcd, 0x77, 0xab, 0x69, 0xf3, 0xa4, 0x9d, 0x4c, 0x85, 0xef, 0xc3, 0x3d,
- 0xf2, 0xbb, 0xec, 0xb7, 0xb3, 0xf8, 0xbe, 0xf6, 0x5b, 0xad, 0x5a, 0x74,
- 0xe0, 0x37, 0xbf, 0x87, 0x36, 0xe5, 0x8c, 0xa0, 0xcd, 0x82, 0xdb, 0x32,
- 0xaa, 0x86, 0x6e, 0x18, 0xe5, 0xb9, 0xb9, 0xd9, 0x35, 0xdf, 0xba, 0xae,
- 0xea, 0xc5, 0xbc, 0x5e, 0x53, 0xe6, 0x67, 0xdd, 0x05, 0x5a, 0xd4, 0xb4,
- 0xa5, 0xe9, 0xff, 0xc0, 0xb2, 0xbe, 0xa4, 0x9e, 0x35, 0xdf, 0x9e, 0x31,
- 0xfa, 0x32, 0x95, 0x18, 0xc1, 0xf8, 0xfa, 0x6f, 0x2a, 0xd8, 0x73, 0xbd,
- 0xd9, 0xf9, 0xdb, 0xb5, 0xae, 0x9f, 0xf2, 0xd3, 0xc9, 0xa8, 0xd4, 0xa9,
- 0x5b, 0xaa, 0xa9, 0xab, 0xe7, 0xed, 0xca, 0x7f, 0xc5, 0xda, 0x7c, 0xbe,
- 0x58, 0x96, 0xe1, 0xe9, 0xbf, 0x84, 0xff, 0x98, 0x90, 0xdf, 0x2e, 0x96,
- 0x40, 0xaf, 0xb9, 0xcd, 0xf6, 0x5b, 0x4d, 0x19, 0xc0, 0xcd, 0x6f, 0xaf,
- 0xe8, 0x7c, 0xe2, 0xc8, 0x17, 0x40, 0x17, 0x9f, 0x2b, 0x71, 0x0c, 0xc0,
- 0x12, 0x81, 0x6d, 0x0f, 0x3b, 0x61, 0xa6, 0xa4, 0x73, 0xe7, 0xae, 0x2b,
- 0x97, 0x74, 0xcc, 0x62, 0x67, 0xb9, 0x53, 0x76, 0x95, 0x5b, 0x64, 0x37,
- 0xf4, 0xc2, 0xee, 0xb2, 0x87, 0x2b, 0x26, 0xef, 0x2e, 0x9b, 0x75, 0xfa,
- 0x58, 0x99, 0xeb, 0xbd, 0x43, 0x66, 0x8f, 0xad, 0xfe, 0x3e, 0xe7, 0x42,
- 0x2e, 0xfc, 0x3b, 0x4b, 0x4a, 0x31, 0xbf, 0x8c, 0xb4, 0x84, 0xab, 0x98,
- 0x3a, 0xbc, 0xa0, 0xf1, 0xc0, 0x0c, 0xd7, 0x54, 0x69, 0x49, 0x98, 0xa7,
- 0xcf, 0xbf, 0xad, 0x34, 0x73, 0x39, 0xcf, 0x4d, 0xf3, 0x5b, 0x5e, 0x3b,
- 0x2b, 0x61, 0xde, 0x78, 0xbd, 0x9c, 0x71, 0xd8, 0xf9, 0x3b, 0xc2, 0x1c,
- 0xbf, 0x18, 0x73, 0xc6, 0xa5, 0xeb, 0x54, 0x0b, 0xee, 0xa7, 0x2f, 0xd7,
- 0x67, 0x9b, 0x4f, 0x89, 0x2d, 0xd3, 0xf9, 0xe4, 0x78, 0x5e, 0xfd, 0x7d,
- 0xb5, 0x90, 0x1f, 0xaa, 0x7f, 0xa7, 0x40, 0xe4, 0xff, 0x02, 0xfb, 0x2e,
- 0x88, 0x71, 0xec, 0x6e, 0x00, 0x00, 0x00 };
+ 0xbd, 0x7d, 0x0d, 0x74, 0x5c, 0xd7, 0x5d, 0xe7, 0xff, 0xdd, 0x79, 0x92,
+ 0xc6, 0xb2, 0x6c, 0x3f, 0xcb, 0x13, 0x79, 0x62, 0xab, 0xf6, 0x8c, 0xf4,
+ 0x64, 0xab, 0x91, 0x08, 0x2f, 0xae, 0x28, 0x82, 0x9d, 0x84, 0xe9, 0x48,
+ 0xb2, 0x9d, 0x34, 0xed, 0xca, 0x8d, 0x5b, 0xb2, 0x9c, 0x02, 0x62, 0x24,
+ 0x27, 0xe9, 0x77, 0xd2, 0x04, 0xb6, 0xec, 0xc9, 0x6e, 0x26, 0x23, 0xf9,
+ 0x83, 0x74, 0xec, 0x51, 0x12, 0x25, 0xce, 0xa1, 0x3d, 0xbb, 0xaa, 0xa4,
+ 0xd8, 0x06, 0x06, 0x8f, 0x93, 0xb8, 0xa5, 0xec, 0xa6, 0x54, 0x28, 0xae,
+ 0x09, 0xa1, 0x07, 0x52, 0x48, 0xd9, 0x40, 0x53, 0x2a, 0xdc, 0xb4, 0xcd,
+ 0x9e, 0x53, 0xb6, 0x01, 0xca, 0x12, 0x68, 0xe8, 0xdb, 0xdf, 0xef, 0xde,
+ 0xfb, 0x34, 0xa3, 0x0f, 0xe7, 0xa3, 0xec, 0xe2, 0x73, 0x9e, 0xdf, 0xbc,
+ 0xfb, 0xee, 0xc7, 0xff, 0xfe, 0xef, 0xff, 0xfb, 0xfe, 0xef, 0xd3, 0x76,
+ 0x91, 0x66, 0xb1, 0xff, 0x36, 0xe0, 0x7a, 0x5b, 0xea, 0xf6, 0xd1, 0x6b,
+ 0xae, 0xfe, 0xc9, 0xab, 0xf9, 0xec, 0x3a, 0x4d, 0x31, 0x79, 0x13, 0xff,
+ 0x52, 0x6f, 0xa0, 0x0e, 0x3a, 0xf4, 0xa2, 0xb1, 0x78, 0x49, 0x5c, 0x65,
+ 0xdc, 0x3b, 0x72, 0xbe, 0xc4, 0x63, 0x99, 0x91, 0x5f, 0x1e, 0xf5, 0x45,
+ 0xb2, 0x95, 0x9e, 0xd4, 0x80, 0xfc, 0x4b, 0x58, 0x48, 0xb8, 0xc2, 0xf2,
+ 0xb7, 0x64, 0x5e, 0xfd, 0x6f, 0x5f, 0xf8, 0xc9, 0xf4, 0xcb, 0xd3, 0x31,
+ 0x89, 0x7b, 0x99, 0x0f, 0x8b, 0xb7, 0x4b, 0xe2, 0xed, 0x19, 0xb9, 0xe3,
+ 0xd3, 0xbb, 0xff, 0x46, 0x64, 0x63, 0xd4, 0xd7, 0x4b, 0xe1, 0x17, 0x76,
+ 0x4b, 0x61, 0x5b, 0x26, 0x39, 0xd2, 0x90, 0x49, 0xc8, 0x17, 0xab, 0x9e,
+ 0x9c, 0xab, 0xca, 0xf0, 0xa9, 0xd2, 0xcb, 0xa1, 0x9b, 0x09, 0x63, 0x13,
+ 0x7d, 0x8e, 0xc4, 0x32, 0x72, 0x61, 0xb4, 0xef, 0x9e, 0x50, 0xf9, 0x32,
+ 0xe2, 0x65, 0xfc, 0x60, 0x41, 0x5a, 0xfa, 0x2f, 0xf6, 0xa1, 0x4e, 0xe5,
+ 0xe0, 0xb5, 0x8d, 0x27, 0xe2, 0xa2, 0x32, 0x5d, 0xcf, 0xe7, 0x62, 0xd7,
+ 0x88, 0xf2, 0xfd, 0xe0, 0x82, 0x74, 0x05, 0x4f, 0x09, 0xca, 0xcf, 0xc6,
+ 0x25, 0x57, 0x95, 0x16, 0x94, 0xe1, 0xde, 0x8c, 0x3a, 0x69, 0x2f, 0x17,
+ 0x4b, 0x48, 0xb1, 0xfa, 0x63, 0xcd, 0x66, 0xec, 0xaf, 0xaf, 0x33, 0xf7,
+ 0xdd, 0xf6, 0xbe, 0xee, 0x67, 0xdd, 0x4c, 0x3c, 0xae, 0x4e, 0xc8, 0xcb,
+ 0x13, 0x7d, 0x2f, 0x87, 0x31, 0xdf, 0xf7, 0x06, 0xa4, 0x41, 0x06, 0x13,
+ 0x80, 0xa9, 0xec, 0xa0, 0xef, 0x14, 0xda, 0xfe, 0x12, 0x70, 0x0e, 0xf8,
+ 0xca, 0x29, 0x29, 0x10, 0xce, 0x72, 0x5c, 0x16, 0x63, 0x49, 0x01, 0xfc,
+ 0xc0, 0x45, 0xbb, 0x8c, 0xa3, 0x3c, 0x57, 0xe2, 0x7c, 0x5c, 0xc9, 0x7b,
+ 0x1e, 0xe6, 0xd2, 0x8e, 0x36, 0x3b, 0x1d, 0xd3, 0x3f, 0x9e, 0x97, 0xd5,
+ 0x67, 0xdd, 0xe7, 0x51, 0x37, 0xa5, 0xeb, 0x3d, 0x51, 0x4d, 0xca, 0xe3,
+ 0xd5, 0x84, 0x3c, 0x56, 0xfd, 0x98, 0x64, 0x3d, 0xe2, 0x00, 0xb0, 0x96,
+ 0x1b, 0x65, 0x60, 0xaa, 0x59, 0x72, 0x53, 0x9d, 0xc9, 0xbc, 0x84, 0xe1,
+ 0x9d, 0xc1, 0x07, 0x64, 0xa4, 0x15, 0xf5, 0xcb, 0x7c, 0x97, 0x5c, 0xf6,
+ 0x2e, 0x1f, 0xf4, 0x78, 0x79, 0xe5, 0x48, 0xf6, 0x60, 0x3a, 0x39, 0xa2,
+ 0xf8, 0xdc, 0x20, 0xb9, 0x5e, 0x3c, 0x0f, 0xbb, 0x12, 0xf3, 0xc3, 0xf0,
+ 0x8e, 0x60, 0x17, 0xe0, 0x48, 0xa7, 0x52, 0x8a, 0x6d, 0xd9, 0x2e, 0x5d,
+ 0x48, 0xa9, 0x24, 0xe6, 0x71, 0xb5, 0xa4, 0x5a, 0xc3, 0xf0, 0x3d, 0x81,
+ 0x8f, 0x72, 0x91, 0x81, 0x92, 0xdc, 0xae, 0x32, 0x3e, 0xfa, 0x94, 0x40,
+ 0x65, 0xb6, 0x60, 0x1e, 0x3d, 0xc0, 0x43, 0xa3, 0x64, 0x13, 0x92, 0x55,
+ 0x19, 0x49, 0xa9, 0xcc, 0x3a, 0x94, 0x39, 0xd2, 0xe0, 0xff, 0x77, 0x4b,
+ 0x7f, 0x9b, 0xf0, 0x2c, 0xc3, 0x2a, 0xd3, 0xba, 0xa2, 0x3c, 0x9d, 0x12,
+ 0xf5, 0xe3, 0x71, 0x8c, 0xd9, 0x9d, 0x55, 0x2c, 0xc3, 0x5d, 0x97, 0x15,
+ 0x9a, 0x56, 0x97, 0x4d, 0x3a, 0xcb, 0xcb, 0x4e, 0xb5, 0x10, 0x56, 0x51,
+ 0xfc, 0x9d, 0xd4, 0x73, 0xcd, 0x26, 0x3a, 0xbd, 0x06, 0xcc, 0x6b, 0x38,
+ 0x48, 0x7b, 0x43, 0xea, 0xb9, 0x50, 0xda, 0x08, 0x33, 0xdf, 0x29, 0xbc,
+ 0x43, 0xd5, 0x4c, 0x80, 0x75, 0x4e, 0xc8, 0x51, 0xcc, 0xed, 0xd2, 0x54,
+ 0xda, 0xeb, 0x50, 0xb8, 0xcf, 0xf1, 0x77, 0x18, 0xe6, 0x82, 0x82, 0xa6,
+ 0x81, 0x6f, 0x4e, 0x25, 0xf1, 0x0c, 0xf8, 0x13, 0xd9, 0xf4, 0x66, 0xb9,
+ 0xc9, 0xae, 0xcb, 0x37, 0x31, 0x66, 0xa7, 0x77, 0x87, 0xea, 0xf4, 0x02,
+ 0x95, 0xf6, 0x66, 0xe4, 0xf7, 0xf1, 0x1c, 0x86, 0x07, 0x82, 0x74, 0xb2,
+ 0x80, 0x35, 0x7b, 0xb1, 0x94, 0x90, 0x6f, 0x95, 0xd2, 0xa0, 0xfc, 0x74,
+ 0xf7, 0xac, 0xf4, 0x04, 0xb3, 0x80, 0xb7, 0x88, 0xeb, 0x08, 0xdf, 0x55,
+ 0xf0, 0xae, 0xc2, 0xb6, 0x61, 0x78, 0x53, 0xf0, 0xeb, 0xe1, 0x48, 0x9b,
+ 0xe1, 0xa5, 0x2f, 0x96, 0xb1, 0x9e, 0x80, 0xf9, 0x71, 0xac, 0xd3, 0x63,
+ 0xe5, 0x88, 0x4e, 0xba, 0xb1, 0xee, 0xa4, 0x0d, 0xd2, 0xc5, 0x1e, 0x4b,
+ 0xff, 0xa3, 0xf6, 0x2e, 0x92, 0x03, 0x8d, 0xe5, 0x82, 0x1f, 0x84, 0x59,
+ 0xcd, 0x63, 0xe2, 0x0c, 0x94, 0x49, 0xbb, 0x0d, 0x80, 0x95, 0x8f, 0x1f,
+ 0xb3, 0xf5, 0xda, 0x1d, 0xe0, 0x96, 0xeb, 0xc0, 0xf7, 0x71, 0xe5, 0x37,
+ 0xd9, 0xf7, 0x11, 0x2f, 0xf1, 0x1f, 0xe8, 0xcd, 0xaf, 0xd5, 0xcb, 0x91,
+ 0x26, 0xab, 0x05, 0xc9, 0x3f, 0x18, 0xca, 0x40, 0x00, 0x3c, 0xb1, 0x4f,
+ 0x2f, 0x10, 0xdd, 0xd6, 0x63, 0x1d, 0x5d, 0x17, 0xff, 0xae, 0x69, 0xc4,
+ 0x18, 0xce, 0x60, 0xb9, 0xd6, 0x76, 0xb0, 0xfc, 0xe4, 0x16, 0x0b, 0x1f,
+ 0x9e, 0xfb, 0x9d, 0x5c, 0xf5, 0x6f, 0xed, 0xda, 0x46, 0xf3, 0xb8, 0x69,
+ 0x0d, 0xda, 0x0e, 0xc3, 0x89, 0x40, 0x46, 0x54, 0x66, 0x31, 0x9e, 0x2b,
+ 0x89, 0xd3, 0x90, 0xf1, 0xbd, 0x21, 0x59, 0x27, 0x76, 0x5e, 0xb6, 0xdc,
+ 0x03, 0xaf, 0x74, 0xa1, 0xdc, 0x11, 0xc8, 0x8d, 0x11, 0x07, 0x65, 0x1d,
+ 0x15, 0x94, 0x61, 0xfd, 0xc6, 0x81, 0xaf, 0x7c, 0xa9, 0x5f, 0xaf, 0x65,
+ 0xbe, 0x34, 0x0c, 0xde, 0xcf, 0xe0, 0x77, 0x76, 0xb3, 0x2b, 0x5d, 0xa0,
+ 0x43, 0xae, 0xb1, 0xb8, 0xb9, 0xdd, 0xa0, 0xd5, 0xea, 0xeb, 0x4b, 0x2c,
+ 0x3d, 0xf7, 0xe0, 0x5f, 0x88, 0xd3, 0x25, 0x78, 0x62, 0x19, 0xf2, 0xf5,
+ 0xf3, 0x21, 0xe8, 0x19, 0x65, 0x84, 0x99, 0x35, 0x13, 0x32, 0x51, 0xde,
+ 0x26, 0xc5, 0x29, 0x5f, 0xc6, 0x4b, 0xf3, 0xdd, 0x4a, 0x5e, 0x86, 0xac,
+ 0xf1, 0x41, 0x0b, 0x69, 0xf0, 0x41, 0x46, 0x06, 0xaa, 0x18, 0xaf, 0x84,
+ 0x7b, 0xb9, 0x13, 0x6d, 0x5d, 0xc9, 0x26, 0xcd, 0x3a, 0x17, 0x4b, 0x63,
+ 0xc0, 0x15, 0xd6, 0x8d, 0xb2, 0x41, 0xc3, 0x3c, 0x0c, 0x3a, 0xf4, 0x24,
+ 0xd7, 0xa7, 0xe1, 0x7c, 0x13, 0xf0, 0xc5, 0x65, 0x26, 0x68, 0xb4, 0x38,
+ 0x22, 0x7f, 0xc6, 0xdd, 0x01, 0xe0, 0x61, 0xa0, 0x72, 0x0f, 0xfa, 0x6f,
+ 0xc1, 0x6f, 0x96, 0x89, 0x2d, 0x73, 0xf5, 0xf3, 0x40, 0x85, 0x30, 0x47,
+ 0x74, 0x0f, 0x3e, 0x98, 0x82, 0xfc, 0x01, 0xdd, 0x0f, 0x90, 0x5f, 0xe6,
+ 0x38, 0x17, 0xc2, 0xb5, 0x4d, 0xff, 0x1e, 0x9f, 0xda, 0xa1, 0x9f, 0xf3,
+ 0xc3, 0xdb, 0xa4, 0x30, 0x17, 0xcd, 0x99, 0xb2, 0x87, 0xf2, 0x26, 0x7d,
+ 0x0c, 0x74, 0x05, 0xf9, 0x13, 0x86, 0x0f, 0x06, 0x94, 0x41, 0x61, 0xf8,
+ 0x78, 0x40, 0x99, 0x74, 0x1e, 0xb2, 0x86, 0x72, 0x88, 0x72, 0x61, 0x50,
+ 0x71, 0xdd, 0x73, 0xa5, 0x00, 0xeb, 0xd3, 0x28, 0xf9, 0xde, 0x47, 0x08,
+ 0x2b, 0x64, 0xd8, 0xb3, 0x1f, 0xcb, 0xf9, 0x85, 0x64, 0x4c, 0xe3, 0x49,
+ 0xb0, 0x5e, 0x71, 0xc9, 0xea, 0x99, 0x75, 0x48, 0xb1, 0x77, 0xd2, 0xd6,
+ 0x79, 0x49, 0xd7, 0x71, 0x57, 0xd5, 0xf9, 0x75, 0x65, 0x78, 0x3c, 0xc0,
+ 0x5a, 0xfe, 0xb4, 0x22, 0x1e, 0x3b, 0x76, 0xf1, 0x59, 0xe2, 0x0d, 0x99,
+ 0xaf, 0xe1, 0xdd, 0xb9, 0x3b, 0x1f, 0xf5, 0xd7, 0x7a, 0xb7, 0xb5, 0x61,
+ 0xf5, 0xbb, 0x09, 0x71, 0xfd, 0x74, 0xf7, 0x01, 0xf5, 0x4f, 0x78, 0x17,
+ 0x86, 0x8f, 0x06, 0x51, 0x79, 0x6f, 0xc3, 0xea, 0x31, 0x7e, 0x76, 0x8d,
+ 0xb2, 0xf3, 0x6b, 0x94, 0xfd, 0xc9, 0x1a, 0x65, 0xef, 0x6d, 0x5c, 0x5d,
+ 0xf6, 0xc0, 0x1a, 0x65, 0x4f, 0xaf, 0x51, 0xe6, 0x37, 0xad, 0x2e, 0xdb,
+ 0xb5, 0x46, 0xd9, 0x5b, 0xd7, 0x28, 0x3b, 0xb0, 0x46, 0x99, 0x0b, 0x1e,
+ 0xde, 0x25, 0xc5, 0xc4, 0xbd, 0x9c, 0xbb, 0xc5, 0xcd, 0xe7, 0x62, 0xab,
+ 0x71, 0xd3, 0x80, 0x7a, 0xed, 0x2b, 0xea, 0x7d, 0x6d, 0x8d, 0x7a, 0x8d,
+ 0xa8, 0xd7, 0xba, 0xa2, 0xde, 0xcd, 0xee, 0xea, 0x7a, 0x4d, 0xa8, 0x17,
+ 0x5f, 0x51, 0xef, 0x77, 0xd7, 0xa8, 0xc7, 0xf2, 0x4f, 0xd9, 0x71, 0x7a,
+ 0xa0, 0xd1, 0x5e, 0x6b, 0xbd, 0x1a, 0x45, 0xda, 0x58, 0x1e, 0x40, 0x1f,
+ 0xfd, 0xb4, 0x32, 0x32, 0x86, 0xf2, 0x4c, 0xe3, 0x0d, 0x74, 0x9e, 0x04,
+ 0xdd, 0x51, 0x26, 0x83, 0xcf, 0x7c, 0xf2, 0xfe, 0x06, 0x19, 0x49, 0xf4,
+ 0x78, 0x6f, 0x53, 0x2d, 0xa0, 0xb1, 0xb4, 0x97, 0x52, 0xe4, 0x3f, 0x29,
+ 0x80, 0xb7, 0x0b, 0x03, 0xa2, 0x12, 0x4a, 0x42, 0x19, 0x0c, 0x54, 0xab,
+ 0x92, 0x7b, 0xc0, 0x5f, 0x59, 0xe8, 0xbf, 0x03, 0xe1, 0x80, 0xe6, 0x2d,
+ 0x53, 0xf7, 0xf2, 0xf2, 0xb9, 0x5f, 0x8e, 0x50, 0xae, 0x66, 0x82, 0x3b,
+ 0x73, 0xfe, 0x7c, 0x7f, 0x23, 0x68, 0xf6, 0x12, 0xda, 0xec, 0x43, 0xcb,
+ 0x43, 0x15, 0x57, 0x06, 0x2b, 0x19, 0xf0, 0x82, 0x23, 0x17, 0xfd, 0x4d,
+ 0x72, 0x31, 0x40, 0xdd, 0x6a, 0x4c, 0x16, 0x12, 0x8e, 0x2c, 0xe0, 0x39,
+ 0x17, 0xe0, 0x5d, 0x35, 0xe2, 0xad, 0x8c, 0x1c, 0x2e, 0xf7, 0xcb, 0xb1,
+ 0xf2, 0x87, 0x55, 0xa4, 0x23, 0x87, 0x82, 0xf5, 0x72, 0xc6, 0x33, 0x7d,
+ 0xef, 0xf3, 0xe7, 0xa1, 0x9d, 0x5d, 0xb9, 0xe4, 0xa7, 0x93, 0x0b, 0x9a,
+ 0x27, 0xfe, 0x31, 0x1c, 0x44, 0x3f, 0x33, 0x7e, 0xda, 0xfb, 0x03, 0x0a,
+ 0xc9, 0x0a, 0x6d, 0xa9, 0x5a, 0x5f, 0xe3, 0xe8, 0xeb, 0x68, 0x79, 0x83,
+ 0xdc, 0x6a, 0xdb, 0xef, 0xf5, 0xe7, 0xbb, 0xc1, 0x73, 0xde, 0x29, 0xca,
+ 0x90, 0x12, 0xe0, 0x3a, 0x08, 0xde, 0x46, 0xdb, 0x2f, 0x09, 0xdb, 0xc0,
+ 0xf6, 0x2a, 0x6d, 0x82, 0xac, 0xff, 0x87, 0xf0, 0xd6, 0x04, 0xeb, 0xb3,
+ 0x8c, 0xfa, 0x4b, 0x26, 0x55, 0x06, 0x32, 0xa1, 0xaf, 0x0b, 0xfa, 0x2b,
+ 0x25, 0x83, 0x55, 0xc8, 0x9e, 0xf2, 0x0f, 0xc3, 0xac, 0xcb, 0x31, 0xa2,
+ 0xb1, 0xa4, 0x50, 0xab, 0xc3, 0x32, 0xd6, 0x23, 0xff, 0x2f, 0x2e, 0xc9,
+ 0x8a, 0x02, 0xe4, 0x8b, 0xb1, 0xd1, 0xfe, 0x13, 0x78, 0xb4, 0x5d, 0x06,
+ 0x4b, 0xe9, 0x42, 0x56, 0x76, 0x61, 0xfd, 0x7e, 0x0d, 0x6b, 0xea, 0xe2,
+ 0xfa, 0x93, 0xf5, 0xb2, 0x31, 0x80, 0x1d, 0xc0, 0x72, 0x74, 0xda, 0x46,
+ 0xfb, 0xec, 0x19, 0xe0, 0x61, 0x9c, 0x6b, 0x9e, 0xcc, 0xc5, 0x9c, 0x61,
+ 0xda, 0x3e, 0xc3, 0x90, 0x8f, 0xf9, 0x0a, 0xfb, 0x26, 0xbc, 0x49, 0xfb,
+ 0x1b, 0x36, 0x5b, 0xa9, 0xdd, 0xfe, 0x6e, 0xc1, 0xef, 0x94, 0xfd, 0x0d,
+ 0x99, 0x5a, 0xf2, 0xed, 0xef, 0x04, 0x7e, 0x77, 0xdb, 0xdf, 0x49, 0xfc,
+ 0xee, 0xd5, 0xbf, 0x27, 0xca, 0x7b, 0xf7, 0x2a, 0xff, 0x6a, 0xc9, 0xcf,
+ 0xb5, 0xcb, 0xe1, 0xd2, 0x7b, 0xad, 0x6c, 0xc1, 0x25, 0x9f, 0x77, 0xcc,
+ 0x3c, 0x01, 0x77, 0x99, 0x6d, 0x0a, 0xce, 0xb0, 0xb6, 0xdd, 0xda, 0x61,
+ 0xeb, 0xf4, 0x78, 0x9b, 0x85, 0x34, 0x30, 0xe1, 0x0c, 0x54, 0x9d, 0x6c,
+ 0x2c, 0xd3, 0x95, 0x1c, 0x97, 0x63, 0xf8, 0x2d, 0x5e, 0x2c, 0xf3, 0x79,
+ 0xdc, 0x0d, 0x0e, 0xbe, 0x00, 0x7d, 0x33, 0x5e, 0xa6, 0xbc, 0xf4, 0x31,
+ 0xf7, 0x94, 0x9c, 0x5f, 0x66, 0xaf, 0x11, 0x17, 0x4a, 0xf2, 0x53, 0xe9,
+ 0x47, 0x0a, 0x92, 0x2e, 0x4c, 0x83, 0x21, 0x0e, 0x04, 0xae, 0xbc, 0x27,
+ 0x00, 0xed, 0x5e, 0xed, 0xc8, 0xde, 0xab, 0x5d, 0xd8, 0x57, 0xfe, 0xf4,
+ 0x5e, 0xc8, 0xd8, 0x7c, 0xe9, 0xea, 0x18, 0xe9, 0x41, 0x9d, 0x95, 0x11,
+ 0x37, 0x03, 0x6c, 0x9f, 0xed, 0x1d, 0x1c, 0x2f, 0xe5, 0x3f, 0xac, 0x32,
+ 0xb7, 0xff, 0x6a, 0xae, 0x6f, 0x17, 0x74, 0x79, 0x18, 0xc6, 0x32, 0x6d,
+ 0xd0, 0x4b, 0x5c, 0x57, 0xea, 0xa9, 0x9b, 0x6e, 0x8a, 0x65, 0x1a, 0x64,
+ 0xe0, 0x60, 0x1b, 0xea, 0xb3, 0x9c, 0xb8, 0x72, 0xd0, 0x47, 0x3a, 0x35,
+ 0x28, 0x72, 0xf7, 0x44, 0xdf, 0xa2, 0x33, 0x3e, 0xf9, 0x73, 0xe0, 0xc7,
+ 0x7e, 0xc9, 0x1f, 0x7c, 0x00, 0xf8, 0x7d, 0xd9, 0x29, 0x4e, 0xbd, 0xe2,
+ 0x8c, 0x4f, 0xfd, 0x9d, 0x33, 0x31, 0xb5, 0x63, 0xc7, 0x50, 0xff, 0x8e,
+ 0x1d, 0xa3, 0xfd, 0xae, 0xd5, 0x2d, 0x3b, 0x76, 0x4c, 0xf4, 0x67, 0x31,
+ 0xff, 0x1e, 0x6f, 0x50, 0x7c, 0x6f, 0x2f, 0x95, 0x7c, 0xc2, 0xac, 0xfd,
+ 0x4c, 0xd0, 0x8d, 0xf7, 0x6c, 0xdf, 0xab, 0xdf, 0x0f, 0x48, 0x4f, 0xb2,
+ 0x55, 0x38, 0x7e, 0x87, 0xd5, 0x49, 0x6c, 0x07, 0x7a, 0xe9, 0xa5, 0x1d,
+ 0xa8, 0x50, 0x2f, 0x05, 0x7c, 0xd0, 0x26, 0xde, 0x06, 0x1b, 0x82, 0xed,
+ 0x94, 0x5d, 0xf7, 0x92, 0x6a, 0xf0, 0x63, 0xba, 0x5f, 0x75, 0x36, 0x13,
+ 0x33, 0x6b, 0xde, 0x63, 0xed, 0xeb, 0x4d, 0x28, 0xe7, 0x33, 0x71, 0x49,
+ 0x7c, 0xd1, 0xde, 0x69, 0xd0, 0xf6, 0x69, 0xbe, 0x44, 0x5a, 0x72, 0x65,
+ 0xac, 0xd4, 0x8f, 0x36, 0xa0, 0x97, 0xb3, 0xf6, 0x3a, 0x81, 0xf1, 0x0e,
+ 0xa2, 0xaf, 0x13, 0x47, 0xd1, 0x8e, 0xb2, 0x24, 0xdd, 0x2d, 0xea, 0x41,
+ 0xd4, 0xe9, 0xf1, 0xb6, 0x08, 0xed, 0x9a, 0x47, 0x24, 0x5f, 0x26, 0xdf,
+ 0xd3, 0x36, 0x88, 0x4b, 0xaa, 0x0d, 0xcf, 0xd5, 0xc3, 0xb0, 0x75, 0x1a,
+ 0x22, 0x7b, 0x43, 0x6a, 0x76, 0xd1, 0xaf, 0x2a, 0xf1, 0x0f, 0xcb, 0xc8,
+ 0xec, 0x76, 0xd4, 0x33, 0xf6, 0xbc, 0xf2, 0x61, 0x17, 0xcd, 0x66, 0x25,
+ 0xb7, 0xeb, 0x5e, 0xdc, 0x3d, 0x3c, 0x17, 0x71, 0x7f, 0x0b, 0xee, 0xe3,
+ 0xb8, 0x47, 0x70, 0x02, 0xe7, 0x41, 0xcc, 0xea, 0xb2, 0x51, 0x8c, 0xfd,
+ 0xef, 0x25, 0x37, 0x09, 0x7a, 0x2d, 0x85, 0x9b, 0x72, 0x7e, 0xd6, 0x53,
+ 0xa2, 0xb6, 0x28, 0x99, 0x40, 0x7d, 0xf8, 0x29, 0xfe, 0x11, 0x19, 0x3d,
+ 0x8d, 0xdf, 0x0f, 0xd2, 0xee, 0x9e, 0x90, 0xd1, 0x59, 0x8e, 0x53, 0x02,
+ 0x4c, 0x93, 0x92, 0x3f, 0xfd, 0x00, 0xae, 0x29, 0x5c, 0x0f, 0xe3, 0xe2,
+ 0xdc, 0xd8, 0xff, 0xc2, 0x66, 0x25, 0x2d, 0xfa, 0x39, 0x4f, 0xfa, 0xae,
+ 0xe2, 0x37, 0x69, 0xbb, 0x4a, 0x1b, 0x08, 0x74, 0x5d, 0x8d, 0xe8, 0x3d,
+ 0xb0, 0xbf, 0x93, 0x9a, 0xdf, 0x0b, 0xad, 0xa0, 0xa5, 0x6a, 0x56, 0xcb,
+ 0x22, 0xc0, 0x00, 0xb9, 0x03, 0x9b, 0xa4, 0x95, 0x73, 0xec, 0xb5, 0x65,
+ 0xbd, 0xba, 0x2c, 0xa5, 0xcb, 0xfa, 0x6c, 0x19, 0xee, 0xd5, 0x06, 0x19,
+ 0x69, 0x03, 0xc4, 0x94, 0xdb, 0x12, 0xe1, 0x93, 0xb2, 0x01, 0x74, 0x8d,
+ 0xf5, 0x3d, 0x7f, 0x59, 0xb9, 0xb8, 0xa8, 0xed, 0xbd, 0x73, 0x55, 0xd2,
+ 0x37, 0x69, 0x3e, 0x0c, 0xef, 0x0f, 0x9a, 0xd0, 0x3f, 0x65, 0x81, 0x48,
+ 0xc3, 0x09, 0x57, 0xa6, 0x3d, 0xd2, 0xc0, 0xc7, 0x5a, 0x48, 0x03, 0x8d,
+ 0x3e, 0x69, 0xbb, 0x9e, 0xef, 0xb8, 0x86, 0xec, 0xaf, 0x00, 0x1b, 0x92,
+ 0xb6, 0x64, 0x17, 0xec, 0x73, 0x8e, 0x71, 0x8c, 0xcf, 0x9e, 0x02, 0xaf,
+ 0xe5, 0x96, 0x78, 0x4d, 0x64, 0xa6, 0x44, 0xdc, 0x44, 0x36, 0x26, 0xd7,
+ 0x99, 0xf8, 0x39, 0x87, 0x39, 0xf3, 0x7e, 0xde, 0xe2, 0xe9, 0xf3, 0x16,
+ 0x4f, 0x4f, 0xda, 0xbb, 0xe7, 0xe4, 0xb5, 0xcd, 0x38, 0x8f, 0x67, 0xae,
+ 0x0f, 0xe8, 0xaa, 0x4a, 0x9e, 0x9b, 0xc6, 0x1d, 0x75, 0xcb, 0xe7, 0x64,
+ 0x54, 0xdb, 0x6f, 0x31, 0x79, 0x87, 0x96, 0x79, 0x5f, 0xc5, 0x5a, 0x96,
+ 0x00, 0x73, 0x83, 0x14, 0x12, 0x31, 0xbd, 0xf6, 0xae, 0xff, 0x5b, 0xae,
+ 0xa1, 0x55, 0xe2, 0x64, 0x99, 0xbf, 0x56, 0x07, 0x53, 0xe4, 0xa3, 0x12,
+ 0x2e, 0xd2, 0xee, 0xa7, 0x35, 0x5c, 0xb7, 0x40, 0x0e, 0x16, 0x44, 0xb5,
+ 0x35, 0xca, 0x95, 0xa0, 0x05, 0x95, 0x80, 0x46, 0x0b, 0x9f, 0x82, 0x3d,
+ 0x95, 0x9f, 0xa5, 0x9d, 0xde, 0x41, 0xdf, 0x28, 0x9e, 0xef, 0xdd, 0x48,
+ 0x3a, 0x52, 0x86, 0x6f, 0x1c, 0x95, 0xef, 0xd5, 0x74, 0xea, 0x28, 0x3f,
+ 0xa1, 0x6d, 0x71, 0xd7, 0xdf, 0xea, 0x5a, 0x9f, 0xde, 0x55, 0xfe, 0x96,
+ 0x95, 0x65, 0x29, 0xea, 0x67, 0xb4, 0x4b, 0xe5, 0x7b, 0xdb, 0xc8, 0x63,
+ 0x1e, 0xfc, 0xe1, 0xac, 0xf2, 0xb5, 0xff, 0x55, 0x50, 0x7d, 0x9b, 0x56,
+ 0xd4, 0xd7, 0x77, 0xc7, 0x3e, 0xbb, 0xf6, 0xee, 0xd9, 0x7b, 0xca, 0xde,
+ 0x0b, 0x6e, 0x1f, 0xef, 0x8e, 0xb8, 0x19, 0xde, 0xb1, 0x86, 0x19, 0xf6,
+ 0xa1, 0xf9, 0x2a, 0x34, 0xb6, 0x72, 0x97, 0x57, 0x14, 0xf2, 0xd5, 0x57,
+ 0xe5, 0x96, 0x59, 0x23, 0x97, 0xf7, 0x96, 0xc2, 0x10, 0x3e, 0xa2, 0xb7,
+ 0x00, 0xff, 0x38, 0x7b, 0xb0, 0x22, 0xb7, 0x54, 0x89, 0xb7, 0x4f, 0x02,
+ 0x7f, 0x43, 0x2e, 0x79, 0xd3, 0x13, 0xca, 0xe3, 0xbb, 0x84, 0xf6, 0x6a,
+ 0xb1, 0x44, 0x9c, 0x5f, 0x10, 0xae, 0x4d, 0xb1, 0xf4, 0xb4, 0x5e, 0x9b,
+ 0x23, 0xa5, 0x05, 0xe0, 0xe7, 0xcb, 0xa0, 0xfb, 0x30, 0x5c, 0x08, 0x8a,
+ 0xa0, 0x9c, 0x3f, 0xc6, 0x6f, 0xd8, 0x28, 0xa5, 0x67, 0xf1, 0x7e, 0xa3,
+ 0x14, 0x27, 0xc9, 0x73, 0xae, 0xe5, 0xe1, 0xb3, 0xe0, 0xa7, 0x9f, 0x41,
+ 0xbf, 0x28, 0xeb, 0xe3, 0xef, 0x1f, 0xe0, 0x1d, 0xee, 0xb3, 0x58, 0xc4,
+ 0x36, 0xda, 0x40, 0x1c, 0x9b, 0x6b, 0xc7, 0x35, 0xa3, 0xaf, 0x5e, 0xef,
+ 0x97, 0x73, 0xbd, 0xd2, 0xdd, 0x05, 0x59, 0x8a, 0x2b, 0xc8, 0xb9, 0x12,
+ 0xeb, 0x93, 0xfe, 0xfb, 0xd6, 0x19, 0x1d, 0xb1, 0xa1, 0xd9, 0xdc, 0x57,
+ 0xb6, 0xe5, 0x9a, 0xd7, 0xd3, 0x20, 0x7d, 0xa8, 0x74, 0x7f, 0x01, 0x72,
+ 0xc7, 0xf5, 0x37, 0xca, 0xa0, 0x96, 0x9d, 0xa4, 0x09, 0xd2, 0xc0, 0xcd,
+ 0xca, 0xd0, 0xe6, 0xfb, 0x95, 0xa1, 0xcd, 0xa7, 0x41, 0x8b, 0xb8, 0xca,
+ 0x8b, 0x8e, 0xa1, 0xcd, 0x2f, 0xe3, 0x8e, 0xab, 0xfc, 0xa2, 0x13, 0xf1,
+ 0xf1, 0x00, 0xfc, 0xca, 0xbd, 0x25, 0xd7, 0x19, 0xad, 0x82, 0x7e, 0xcb,
+ 0x71, 0x94, 0xcf, 0x13, 0xe7, 0x98, 0x3f, 0xc7, 0xd9, 0x69, 0xfb, 0x3f,
+ 0x27, 0x63, 0xe5, 0x50, 0xdb, 0x5b, 0xf9, 0xd9, 0x7b, 0x71, 0x5f, 0xaf,
+ 0xe5, 0x8c, 0xf2, 0xb3, 0xca, 0xc8, 0xab, 0x77, 0xe0, 0xde, 0x99, 0x3c,
+ 0x22, 0x9d, 0x5e, 0x4c, 0x9e, 0x45, 0x5f, 0xdf, 0x75, 0xc6, 0xaa, 0x2f,
+ 0xe3, 0xfa, 0x3e, 0xae, 0x57, 0x71, 0xbd, 0x82, 0x7e, 0x5f, 0x40, 0xf9,
+ 0x7a, 0x99, 0xf7, 0x9a, 0x51, 0x5f, 0xd4, 0x68, 0xf5, 0x79, 0x67, 0xe4,
+ 0xf4, 0x4b, 0xb8, 0x5c, 0x35, 0x56, 0x7d, 0xce, 0xc9, 0xcf, 0x86, 0x9b,
+ 0x16, 0x7c, 0xca, 0xb0, 0xaf, 0x3a, 0xa6, 0xef, 0x0c, 0xe6, 0x00, 0x9a,
+ 0x2e, 0xcf, 0x63, 0xec, 0xa7, 0x35, 0xcf, 0x0c, 0x42, 0x1f, 0xe4, 0x61,
+ 0xaf, 0x8c, 0x68, 0x98, 0xb6, 0x03, 0x3e, 0xf8, 0xd3, 0x7d, 0xb8, 0xcf,
+ 0x36, 0xca, 0x62, 0x82, 0xf6, 0xe5, 0x93, 0xba, 0x7e, 0xbe, 0x7c, 0xbd,
+ 0xc6, 0xed, 0xf4, 0x2a, 0xfe, 0xa1, 0x4f, 0x18, 0xc9, 0x03, 0x23, 0x8d,
+ 0x67, 0x4a, 0x94, 0x05, 0xd0, 0x4d, 0xa5, 0x09, 0xdc, 0x1b, 0xb5, 0x4c,
+ 0x28, 0x4a, 0x24, 0x0f, 0xd8, 0x8e, 0x32, 0xa1, 0x5e, 0xee, 0x50, 0xd6,
+ 0x50, 0xf6, 0x50, 0x96, 0x98, 0xf5, 0x18, 0x7d, 0x90, 0x32, 0xfc, 0x3a,
+ 0xe8, 0x4d, 0xda, 0x25, 0xbe, 0xf1, 0x4d, 0xa6, 0x72, 0xca, 0xc8, 0xd3,
+ 0xfd, 0x7a, 0x2d, 0xc6, 0x4a, 0x2a, 0x01, 0xc8, 0x51, 0x86, 0xeb, 0xe4,
+ 0x41, 0xdc, 0xf3, 0x6a, 0x0c, 0x57, 0xfe, 0xe4, 0xfb, 0xf0, 0x9b, 0x6b,
+ 0x33, 0x86, 0x7a, 0xb8, 0xca, 0xc3, 0xb8, 0xe3, 0x2a, 0xdf, 0xa8, 0x8c,
+ 0x1c, 0xe1, 0x9a, 0x26, 0xed, 0x9a, 0x3e, 0x09, 0x3c, 0x70, 0x7e, 0x4a,
+ 0xc7, 0x38, 0x94, 0xbf, 0x07, 0x78, 0xaf, 0x5a, 0x9f, 0x7a, 0xa3, 0x18,
+ 0x1e, 0xc4, 0xd5, 0x4d, 0x7e, 0x6e, 0x31, 0xeb, 0xa5, 0x69, 0x77, 0x5d,
+ 0x83, 0xe1, 0xc5, 0x04, 0xca, 0x62, 0x28, 0x6b, 0x33, 0x3a, 0x73, 0x09,
+ 0x8f, 0x59, 0x8b, 0x47, 0xfe, 0x56, 0xf6, 0x37, 0xe8, 0x09, 0xb6, 0x2e,
+ 0xe4, 0x35, 0xc6, 0xc5, 0x5c, 0x4e, 0xee, 0x57, 0xa3, 0x65, 0xfa, 0xc9,
+ 0x94, 0xe1, 0x8c, 0x65, 0x70, 0x7e, 0xec, 0x17, 0xe5, 0x1a, 0x07, 0x81,
+ 0xd4, 0xe2, 0x04, 0x4f, 0x62, 0xcd, 0xce, 0xc9, 0xa1, 0xf2, 0x47, 0xb4,
+ 0xdf, 0xde, 0x78, 0xc2, 0xac, 0x87, 0xa8, 0xa8, 0x1e, 0xfa, 0x4e, 0xd0,
+ 0xe6, 0xf9, 0x75, 0xfd, 0xde, 0x3d, 0xc1, 0xdf, 0x49, 0x1d, 0x4f, 0xaa,
+ 0xc9, 0x7b, 0x63, 0xef, 0x14, 0x97, 0xc9, 0x3a, 0xda, 0x1d, 0x58, 0xb3,
+ 0x4a, 0x3d, 0xde, 0x19, 0x47, 0xa0, 0xcc, 0x23, 0x3f, 0x1d, 0x01, 0x4f,
+ 0x60, 0xf2, 0x9a, 0xf7, 0xe9, 0x83, 0xac, 0xc5, 0x4f, 0x3e, 0x6c, 0x62,
+ 0x57, 0x4e, 0xc1, 0xa6, 0xdb, 0xbb, 0xd4, 0x07, 0x64, 0x65, 0x22, 0x2e,
+ 0xa7, 0x4b, 0x2d, 0x32, 0x5b, 0x52, 0x6d, 0x31, 0x2b, 0x3b, 0x63, 0x92,
+ 0xd4, 0xfa, 0x97, 0x76, 0xdf, 0xc0, 0x54, 0xcc, 0xd2, 0xdd, 0x8d, 0xe8,
+ 0xff, 0x93, 0xd0, 0xb1, 0x15, 0xe8, 0xd8, 0x8d, 0xd0, 0xc1, 0x2b, 0x65,
+ 0xc4, 0xfe, 0x86, 0xd5, 0x32, 0x82, 0x6d, 0xd2, 0xf0, 0xd6, 0x8f, 0xa0,
+ 0x5d, 0x44, 0x7f, 0x71, 0x4d, 0x6b, 0x79, 0x29, 0x38, 0x7b, 0xab, 0x13,
+ 0xce, 0xbe, 0xea, 0x4a, 0x1d, 0xd4, 0xe3, 0xb9, 0x62, 0x60, 0x3d, 0x5d,
+ 0xa2, 0xed, 0x9a, 0x0e, 0x72, 0xc0, 0xc9, 0x3e, 0xd0, 0xdd, 0x53, 0x93,
+ 0xf0, 0xef, 0x29, 0x97, 0x01, 0xf3, 0x19, 0xc0, 0x3c, 0x33, 0xe9, 0x44,
+ 0xb6, 0x81, 0x30, 0x40, 0x33, 0x33, 0xd5, 0x2b, 0x0b, 0x73, 0xa4, 0x43,
+ 0xc8, 0x80, 0x49, 0xac, 0x67, 0xb0, 0x0e, 0x76, 0x00, 0xc7, 0x87, 0xdc,
+ 0x9e, 0xda, 0xa6, 0xdf, 0x19, 0x7d, 0xde, 0x2e, 0x0b, 0x95, 0x3b, 0x2d,
+ 0x6c, 0xc7, 0xea, 0x60, 0x5b, 0xb7, 0x04, 0xdb, 0x3e, 0xc0, 0xb6, 0x7f,
+ 0x4d, 0xd8, 0xd6, 0xd2, 0xc5, 0x1d, 0xb0, 0x69, 0xc8, 0x1f, 0x11, 0x5e,
+ 0xdb, 0x2c, 0x3d, 0x94, 0xac, 0x1d, 0x4c, 0x9b, 0xe8, 0x87, 0x80, 0x87,
+ 0x34, 0x86, 0xdf, 0xb3, 0x8f, 0x52, 0x96, 0xa1, 0x9c, 0xcf, 0x0f, 0xa1,
+ 0x0e, 0x9e, 0x67, 0x13, 0x56, 0x0e, 0x7e, 0xc2, 0xc2, 0x42, 0x3b, 0x21,
+ 0x0b, 0x5b, 0x79, 0xd0, 0xc9, 0xcd, 0x12, 0x86, 0x53, 0x80, 0x17, 0xef,
+ 0xaa, 0xf5, 0x7d, 0xf2, 0xce, 0x7e, 0xaf, 0xb2, 0xfd, 0xb0, 0xef, 0x68,
+ 0x2e, 0xeb, 0xad, 0x9e, 0x8f, 0xe8, 0x2b, 0xb2, 0xbb, 0x27, 0x9c, 0xec,
+ 0xaa, 0x79, 0xd5, 0xd3, 0x1c, 0xe5, 0xad, 0x2b, 0x43, 0xa0, 0x93, 0xa1,
+ 0x65, 0xb4, 0xa6, 0xdd, 0x13, 0x4b, 0xc7, 0xeb, 0xec, 0xfc, 0x0e, 0x1b,
+ 0xbe, 0x09, 0xe2, 0xd0, 0x87, 0x94, 0x37, 0xff, 0xc5, 0xf8, 0xec, 0xf2,
+ 0xe5, 0x06, 0xc6, 0x69, 0xcd, 0x33, 0x69, 0x93, 0xbf, 0x29, 0x93, 0x6a,
+ 0xb4, 0x68, 0x7c, 0x9a, 0x76, 0x8c, 0x55, 0x6f, 0xc7, 0xbb, 0x32, 0x6c,
+ 0xd6, 0xfc, 0x18, 0xd7, 0x9c, 0x3e, 0x4a, 0xe7, 0x03, 0xc3, 0x96, 0xbf,
+ 0xd2, 0x93, 0x05, 0xb9, 0xd5, 0xce, 0xfd, 0xd2, 0x1a, 0x6b, 0xb7, 0x71,
+ 0x69, 0xed, 0x86, 0xab, 0x2b, 0xe7, 0x28, 0xd2, 0xf1, 0x80, 0xab, 0x7d,
+ 0x5e, 0xfa, 0xf0, 0x8d, 0x3e, 0xe5, 0x27, 0x6d, 0x25, 0x94, 0xcf, 0xf4,
+ 0x78, 0xad, 0xf0, 0x0d, 0xbe, 0xb8, 0xca, 0xee, 0x4a, 0x59, 0xb9, 0x49,
+ 0xff, 0x38, 0x1a, 0xa3, 0x60, 0xe5, 0x64, 0x01, 0xfd, 0x4f, 0x38, 0x43,
+ 0xd5, 0xb5, 0xe4, 0x65, 0x24, 0x27, 0x39, 0x9f, 0x7b, 0xe5, 0x8e, 0x07,
+ 0xc9, 0xa3, 0x25, 0x6d, 0x5f, 0x5f, 0xb3, 0xe7, 0x30, 0xf0, 0x47, 0xf8,
+ 0x17, 0x36, 0xc3, 0x64, 0x80, 0xce, 0xcd, 0xca, 0xa8, 0x5d, 0xb7, 0xd1,
+ 0xa5, 0xf5, 0xe7, 0x35, 0x0c, 0xdd, 0xc8, 0x58, 0xae, 0xb2, 0x30, 0x6b,
+ 0x3b, 0x16, 0x76, 0xdd, 0x4a, 0x5b, 0x96, 0x73, 0xa0, 0x3d, 0xdb, 0x68,
+ 0x6c, 0xc1, 0x32, 0xed, 0x4f, 0xca, 0x2e, 0xda, 0x9f, 0x57, 0x37, 0x4a,
+ 0x33, 0xe7, 0x93, 0xb5, 0x65, 0xb4, 0x53, 0x57, 0xce, 0x6f, 0xa5, 0x5f,
+ 0x49, 0x38, 0x09, 0xb7, 0xa1, 0xad, 0x94, 0x22, 0x6c, 0xa1, 0x0c, 0x07,
+ 0xd7, 0xe9, 0x35, 0x50, 0xb4, 0x5d, 0xf7, 0x34, 0x34, 0x9a, 0x38, 0xf6,
+ 0x5e, 0xf4, 0xcf, 0x31, 0xc9, 0x7f, 0xbc, 0xd3, 0xce, 0x5f, 0x4b, 0x96,
+ 0xd5, 0xeb, 0x9e, 0x2b, 0x97, 0xf0, 0x37, 0xb4, 0x6c, 0x8d, 0x22, 0xfc,
+ 0x45, 0x74, 0x51, 0x8f, 0x43, 0xd2, 0x04, 0x69, 0x21, 0xa2, 0xc5, 0x9d,
+ 0x56, 0xdf, 0x44, 0xb4, 0xb7, 0x15, 0xb4, 0x77, 0x1f, 0xf0, 0x44, 0x19,
+ 0xce, 0x78, 0xde, 0x16, 0x3c, 0x1f, 0xc7, 0x73, 0xc4, 0x27, 0x91, 0x0c,
+ 0xa7, 0x4d, 0xb4, 0x52, 0x8e, 0x53, 0x86, 0xc7, 0x61, 0xf7, 0x50, 0xd6,
+ 0x6f, 0xb7, 0xfc, 0x94, 0xb3, 0xbc, 0x44, 0x5d, 0xf0, 0xfb, 0xe8, 0xe7,
+ 0x86, 0x46, 0x63, 0xa7, 0x17, 0x1b, 0x29, 0x5f, 0x37, 0xcb, 0x91, 0xba,
+ 0xb2, 0xcb, 0xc9, 0xef, 0xfa, 0x39, 0x6f, 0xff, 0x7f, 0x30, 0xe7, 0xe4,
+ 0x8a, 0x39, 0x7b, 0x76, 0xce, 0x55, 0xbc, 0x6f, 0xc5, 0xfb, 0x16, 0xea,
+ 0x82, 0x54, 0x4d, 0xde, 0x58, 0x5c, 0x68, 0x7d, 0x56, 0x2f, 0x27, 0x22,
+ 0x19, 0xc1, 0x79, 0x1d, 0xb5, 0x73, 0xf8, 0x7c, 0xdd, 0xbc, 0x8e, 0xbe,
+ 0x89, 0x79, 0xb5, 0x2f, 0x9b, 0xd7, 0xde, 0xcb, 0xce, 0x6b, 0x2d, 0x1e,
+ 0x27, 0x2f, 0x47, 0xf3, 0x8b, 0xcb, 0x81, 0x12, 0xe7, 0x38, 0x84, 0x39,
+ 0x12, 0x86, 0x68, 0x8e, 0x19, 0x3b, 0x47, 0x51, 0x1d, 0x7b, 0x7e, 0x0a,
+ 0xbf, 0xeb, 0xe7, 0x47, 0xdd, 0xff, 0xf7, 0xa0, 0xe9, 0x26, 0xf8, 0xc4,
+ 0x4d, 0x56, 0xfe, 0x3f, 0x29, 0xb7, 0x96, 0xb9, 0xd6, 0xe9, 0xac, 0xc8,
+ 0x7e, 0x75, 0xa8, 0xfc, 0x72, 0x23, 0xf7, 0x11, 0xf6, 0x06, 0x56, 0x8f,
+ 0x41, 0x5f, 0xec, 0x83, 0xcd, 0x37, 0x54, 0x52, 0x7d, 0x31, 0x09, 0xc3,
+ 0xdb, 0x82, 0x66, 0x8c, 0xbd, 0x49, 0xfb, 0xaa, 0xab, 0x63, 0xf8, 0xcf,
+ 0x36, 0x8a, 0x4f, 0x7b, 0x83, 0xfa, 0x1c, 0xfa, 0xee, 0x24, 0x6d, 0xb0,
+ 0x1c, 0xec, 0xe4, 0x6c, 0x32, 0xa6, 0x6d, 0x31, 0xea, 0xc4, 0x74, 0x32,
+ 0x2b, 0x15, 0xc9, 0x9f, 0xcc, 0x26, 0xe1, 0xd8, 0x62, 0x0c, 0xd8, 0x6a,
+ 0xb0, 0x21, 0x6f, 0x85, 0xac, 0xb9, 0xb5, 0x7a, 0x50, 0xdd, 0x02, 0x7b,
+ 0xe7, 0x96, 0xd3, 0xef, 0x53, 0xb7, 0xc1, 0xd6, 0xb9, 0xed, 0xf4, 0x8d,
+ 0xea, 0x10, 0x6c, 0x9b, 0x43, 0xb0, 0x73, 0x0e, 0x55, 0x69, 0x7b, 0xde,
+ 0x0c, 0xba, 0x6b, 0x87, 0x1e, 0xe2, 0x5c, 0xb8, 0x26, 0xb4, 0x71, 0x38,
+ 0x3f, 0xe2, 0xfe, 0x0b, 0x5c, 0x83, 0x20, 0xa5, 0x76, 0x34, 0x71, 0x5d,
+ 0x5a, 0x97, 0x95, 0xbd, 0x96, 0xac, 0x8a, 0xf4, 0xd3, 0x06, 0x1b, 0x4f,
+ 0x32, 0x7e, 0xe5, 0xe5, 0x69, 0x8b, 0x34, 0xe2, 0x01, 0xcf, 0xc4, 0x1f,
+ 0x69, 0xab, 0x7e, 0xfe, 0x57, 0x36, 0x89, 0x9f, 0xc3, 0xf8, 0xf7, 0x42,
+ 0xbe, 0xd6, 0xd3, 0x14, 0xef, 0x5e, 0x1d, 0x7f, 0x50, 0x06, 0x47, 0xf4,
+ 0xb0, 0xf3, 0x35, 0xe4, 0xef, 0x65, 0xe9, 0xe9, 0x9e, 0x58, 0x26, 0x0c,
+ 0x47, 0xfb, 0x64, 0x13, 0xe3, 0x01, 0xb9, 0x6a, 0x2d, 0x26, 0xa0, 0xfc,
+ 0xfa, 0x98, 0x00, 0xfd, 0xac, 0x4f, 0x03, 0xbf, 0xd3, 0xb8, 0x44, 0x46,
+ 0x18, 0x77, 0xa8, 0x46, 0x76, 0xf9, 0x57, 0xac, 0x5d, 0x1e, 0xc1, 0x91,
+ 0x02, 0x1c, 0x46, 0x3e, 0xaf, 0xd6, 0x73, 0xcb, 0xf5, 0x77, 0x61, 0xc9,
+ 0xa6, 0x4d, 0xc9, 0x81, 0xb2, 0xb6, 0x13, 0x21, 0x83, 0x89, 0x9b, 0x7a,
+ 0x19, 0x9c, 0xb4, 0x76, 0x14, 0xea, 0x68, 0xf9, 0xb9, 0x5a, 0x76, 0x52,
+ 0xee, 0x31, 0x6e, 0xff, 0x40, 0x40, 0x5a, 0x7f, 0x97, 0x64, 0x97, 0xe2,
+ 0xf6, 0x02, 0x7a, 0x93, 0x20, 0x96, 0xd1, 0x7b, 0x7a, 0xde, 0x8c, 0xec,
+ 0x93, 0x81, 0x04, 0x63, 0xa0, 0x8c, 0xf3, 0xf9, 0x85, 0x19, 0xe9, 0x66,
+ 0x8c, 0x03, 0x16, 0x7c, 0xa3, 0x8c, 0x78, 0xa1, 0xec, 0x0d, 0x1c, 0x1d,
+ 0x53, 0x36, 0xba, 0xf6, 0x62, 0x93, 0xb1, 0x5d, 0x1d, 0x1d, 0x17, 0x5e,
+ 0x00, 0xf5, 0x2d, 0x68, 0xfb, 0x56, 0x69, 0xfd, 0x3b, 0xaf, 0xeb, 0xfc,
+ 0x41, 0x53, 0x14, 0xdf, 0x5c, 0xf0, 0x62, 0xb6, 0x5e, 0x7d, 0xf9, 0xd7,
+ 0x6c, 0xdc, 0xba, 0x1b, 0xb2, 0x3f, 0x2a, 0xfb, 0xde, 0x1a, 0x65, 0xb1,
+ 0xf8, 0xea, 0xb2, 0xcd, 0x6b, 0x94, 0x99, 0x78, 0xe1, 0x50, 0x69, 0x27,
+ 0xde, 0x4d, 0x68, 0xdf, 0x5d, 0xf4, 0x9e, 0x5b, 0xb7, 0x14, 0x96, 0xea,
+ 0x6c, 0xb0, 0x7e, 0x19, 0x63, 0xc7, 0x26, 0x66, 0x9c, 0xd7, 0x31, 0xe3,
+ 0x1e, 0x6f, 0x8f, 0xd2, 0x7b, 0x2c, 0xb7, 0x33, 0xfe, 0x78, 0x48, 0xe3,
+ 0x85, 0x38, 0xf9, 0x02, 0x63, 0xc3, 0x05, 0xee, 0x0f, 0xa7, 0xd4, 0xe5,
+ 0x68, 0xbb, 0x66, 0x9b, 0x98, 0x75, 0xa3, 0x5d, 0xdc, 0x22, 0x83, 0xb0,
+ 0x15, 0x86, 0x4a, 0xad, 0xb2, 0x77, 0xea, 0xa3, 0xeb, 0xa8, 0xb7, 0xf6,
+ 0x4d, 0x19, 0x7f, 0xf0, 0x10, 0xf8, 0x2a, 0x2b, 0x84, 0x31, 0x1d, 0x88,
+ 0xd0, 0x26, 0x5e, 0x6d, 0x0b, 0xbf, 0x76, 0x7f, 0xf7, 0x5f, 0xa6, 0x3f,
+ 0x07, 0xb6, 0xc3, 0x1b, 0xed, 0xaf, 0x59, 0x06, 0xa7, 0x22, 0x5c, 0xa9,
+ 0x1f, 0xb1, 0x5d, 0xec, 0x32, 0xed, 0xb4, 0x5d, 0x22, 0x4f, 0x2d, 0xc9,
+ 0xe2, 0x9d, 0xb0, 0x99, 0x24, 0xcc, 0xf5, 0x49, 0x7b, 0x4c, 0x74, 0x8c,
+ 0x27, 0x30, 0xb2, 0xb9, 0x8b, 0x7b, 0x3e, 0xa0, 0x7f, 0x63, 0xab, 0x98,
+ 0x78, 0x6a, 0x64, 0xa7, 0xac, 0x45, 0xbb, 0xd7, 0x5b, 0xda, 0xe5, 0xbe,
+ 0xee, 0x3e, 0xca, 0x5c, 0xac, 0x89, 0xa1, 0xe3, 0xbd, 0x25, 0x49, 0x45,
+ 0x74, 0xbc, 0x20, 0xd9, 0x65, 0x74, 0xbc, 0x20, 0x83, 0x9a, 0x8e, 0x1b,
+ 0x97, 0xd1, 0x71, 0xbb, 0xa5, 0xe3, 0x8f, 0xc6, 0x0d, 0x5d, 0x28, 0xad,
+ 0xa7, 0x48, 0xa7, 0x86, 0x8e, 0x1d, 0x4d, 0xc7, 0x0b, 0xb8, 0xbb, 0xfe,
+ 0xc7, 0x6c, 0x9d, 0x98, 0x2d, 0xe3, 0xef, 0xa8, 0x8c, 0x72, 0x71, 0x2a,
+ 0x6e, 0xf4, 0xd2, 0x20, 0xe8, 0x28, 0x2a, 0xff, 0x4d, 0x4b, 0x9f, 0xf5,
+ 0x65, 0x26, 0x3e, 0x32, 0x54, 0x3a, 0xb2, 0x82, 0x3e, 0x07, 0x41, 0x9f,
+ 0x51, 0x9d, 0xd7, 0xa2, 0xcf, 0x66, 0xbb, 0x9f, 0x91, 0xd4, 0x7b, 0xff,
+ 0xd9, 0x84, 0xa1, 0xd5, 0x5b, 0xf4, 0xdc, 0x39, 0xef, 0x0b, 0x6f, 0x80,
+ 0x56, 0xcd, 0xda, 0x5c, 0xac, 0xf9, 0xdb, 0x8c, 0x45, 0xa5, 0x4c, 0x6c,
+ 0x9b, 0x71, 0xd2, 0xcb, 0xd9, 0x8e, 0x2f, 0xd5, 0xf9, 0x15, 0x1b, 0xa4,
+ 0xc0, 0xbc, 0x87, 0xea, 0x46, 0xc6, 0xa2, 0x47, 0xdc, 0x4c, 0x9f, 0x64,
+ 0x2b, 0xed, 0xa9, 0x62, 0x89, 0x7e, 0xd1, 0xab, 0x36, 0x37, 0x02, 0xcf,
+ 0x95, 0x16, 0x79, 0xb4, 0x44, 0xda, 0x3a, 0x62, 0x70, 0xb1, 0x26, 0xad,
+ 0x73, 0xad, 0xd9, 0x4f, 0xbd, 0x0e, 0xe8, 0x83, 0xee, 0xa1, 0xcd, 0xae,
+ 0xe5, 0x3e, 0xde, 0xb5, 0xa7, 0x72, 0xa5, 0xa8, 0x5f, 0xee, 0x3f, 0x70,
+ 0x4f, 0xb8, 0x3d, 0xd5, 0x51, 0xf1, 0x6d, 0x9c, 0x79, 0x23, 0x9e, 0xfb,
+ 0xa4, 0xa3, 0xa2, 0xe4, 0x03, 0x53, 0x2d, 0x72, 0x7b, 0xc9, 0x95, 0x0f,
+ 0xa1, 0xfd, 0x07, 0x4b, 0x1e, 0xfc, 0xfb, 0xff, 0x1d, 0xa7, 0x9d, 0x79,
+ 0xa8, 0xc4, 0x7d, 0x50, 0x47, 0xdb, 0x2a, 0xcb, 0xf7, 0x86, 0x63, 0xd2,
+ 0xd1, 0x55, 0x84, 0xe7, 0x23, 0xee, 0x7e, 0xc0, 0xd1, 0x94, 0xc9, 0xc8,
+ 0x77, 0xfa, 0x36, 0xa1, 0x2c, 0xca, 0xf1, 0x18, 0x76, 0x4c, 0xfc, 0xb8,
+ 0x5f, 0xde, 0x59, 0xcd, 0xc8, 0x0d, 0x55, 0xb3, 0x77, 0x5b, 0xdb, 0x9b,
+ 0x4d, 0x7b, 0xf3, 0xd0, 0x67, 0x59, 0x2f, 0x0c, 0x2f, 0xfa, 0xa0, 0xa2,
+ 0xe3, 0xae, 0xc4, 0xbb, 0xd2, 0xc9, 0x79, 0x31, 0xcf, 0x97, 0x2a, 0xff,
+ 0x1c, 0x8e, 0x24, 0x5c, 0xf9, 0x8e, 0xcf, 0x39, 0xf6, 0xcb, 0xf5, 0x95,
+ 0xfa, 0xb1, 0xb9, 0x3f, 0x1b, 0x5b, 0xc7, 0xfd, 0x90, 0x5c, 0xf5, 0x9f,
+ 0xe3, 0x8c, 0xdb, 0xd3, 0x87, 0xe9, 0xf8, 0x31, 0xee, 0x87, 0xbb, 0xb8,
+ 0x83, 0x0e, 0x13, 0xb0, 0x21, 0xae, 0x01, 0x8c, 0xd7, 0x30, 0x96, 0xc6,
+ 0x18, 0x1a, 0x9f, 0xbf, 0x8c, 0x71, 0xd9, 0xf6, 0x93, 0xd6, 0xfe, 0x3e,
+ 0xb2, 0xc4, 0x8b, 0x6b, 0xeb, 0xb1, 0x8d, 0x23, 0xf1, 0x8c, 0x38, 0xf1,
+ 0x9f, 0x48, 0xca, 0x3a, 0xbf, 0x7e, 0x7c, 0xee, 0x47, 0xc3, 0xa2, 0xec,
+ 0x13, 0x77, 0xdf, 0xee, 0x7e, 0x19, 0xc4, 0xfc, 0x86, 0x56, 0xcd, 0xef,
+ 0x1e, 0x61, 0xbc, 0xf6, 0x52, 0x89, 0x73, 0xa8, 0xcd, 0x4b, 0xfd, 0xb6,
+ 0x99, 0x57, 0xbc, 0x6b, 0xe5, 0x7c, 0x74, 0x7b, 0x75, 0x0a, 0xb0, 0x7c,
+ 0x49, 0xe7, 0x42, 0x84, 0xe1, 0x5b, 0xbb, 0x2e, 0x85, 0xa9, 0x2b, 0xd2,
+ 0xdd, 0xf3, 0xb5, 0x7d, 0xa4, 0x91, 0x58, 0x26, 0xab, 0xf5, 0x23, 0x9e,
+ 0x53, 0xf9, 0xca, 0x7e, 0xac, 0xa3, 0xb8, 0xf9, 0x5e, 0x57, 0xf3, 0x5d,
+ 0xde, 0xdf, 0x6f, 0xf7, 0xca, 0x22, 0x9f, 0x2c, 0x0c, 0x95, 0xbf, 0x52,
+ 0x0e, 0x51, 0xff, 0x61, 0xee, 0xf2, 0x98, 0xdd, 0x3f, 0xe8, 0x66, 0x7c,
+ 0x0c, 0xb4, 0x18, 0x07, 0xdd, 0xf9, 0xf8, 0xdd, 0x82, 0xfb, 0x1e, 0xd8,
+ 0x3f, 0x01, 0xec, 0x23, 0x49, 0x28, 0x23, 0x6b, 0xc0, 0x1b, 0x5d, 0x05,
+ 0xa5, 0xc8, 0xeb, 0x5e, 0x6a, 0xbc, 0x92, 0x48, 0x4d, 0x56, 0x9e, 0x60,
+ 0x7b, 0xd4, 0x5d, 0x2b, 0x36, 0x68, 0xf2, 0x6c, 0xbe, 0x58, 0xe5, 0x18,
+ 0xa4, 0xfb, 0x37, 0x32, 0x86, 0x6b, 0xfb, 0x66, 0x9f, 0x11, 0x5e, 0x5c,
+ 0xba, 0xf8, 0xf8, 0xb7, 0xdf, 0xfa, 0x3a, 0x9c, 0xdf, 0x13, 0x16, 0xee,
+ 0x95, 0xe3, 0x3e, 0xaf, 0xed, 0xa1, 0xc7, 0xab, 0xb4, 0x41, 0xb9, 0x8f,
+ 0x94, 0x7e, 0x64, 0x5a, 0x08, 0x47, 0x18, 0x3e, 0x1b, 0x18, 0x5b, 0xe0,
+ 0x8b, 0x55, 0xee, 0x99, 0x84, 0xe1, 0xdf, 0xd2, 0xce, 0x3e, 0x58, 0xc6,
+ 0x78, 0x11, 0x0e, 0x76, 0x16, 0x5c, 0xc8, 0xd9, 0x89, 0x3e, 0xe2, 0x57,
+ 0xe0, 0xf1, 0x76, 0x79, 0x07, 0x24, 0x9e, 0xfa, 0x78, 0xa5, 0x25, 0x75,
+ 0x67, 0xc5, 0x03, 0x9e, 0x39, 0xef, 0x44, 0x6a, 0xcc, 0xce, 0x39, 0x5f,
+ 0x21, 0x7e, 0x5f, 0x6b, 0xbf, 0xf3, 0xf9, 0x65, 0xfe, 0x17, 0x61, 0xaa,
+ 0xc1, 0x42, 0xd8, 0x52, 0x16, 0x37, 0x61, 0xf8, 0xf7, 0x01, 0xc7, 0xdc,
+ 0x0f, 0x1f, 0x46, 0x26, 0x30, 0x6e, 0x61, 0x8b, 0x22, 0x1e, 0xe2, 0xa9,
+ 0x3b, 0x30, 0xf6, 0xc7, 0x31, 0xf6, 0xed, 0x15, 0x8e, 0x07, 0xd9, 0x83,
+ 0xb9, 0x4f, 0x54, 0x23, 0x78, 0xd7, 0x1a, 0x3b, 0x5a, 0xf3, 0x6e, 0x6b,
+ 0x33, 0x46, 0xcf, 0x1a, 0x91, 0x6d, 0x0a, 0xbe, 0x63, 0xae, 0xba, 0xb0,
+ 0xd9, 0x95, 0x9f, 0x81, 0x1c, 0x0f, 0xe5, 0x51, 0xc8, 0xc7, 0x05, 0x4d,
+ 0x37, 0xb9, 0xed, 0xfc, 0x3f, 0x26, 0x4f, 0xad, 0x63, 0xbc, 0x7a, 0xc0,
+ 0xa7, 0x2d, 0xbc, 0x18, 0x2e, 0xf8, 0x94, 0xf7, 0x1b, 0x64, 0xda, 0x2b,
+ 0x74, 0x43, 0xf7, 0xa0, 0x6c, 0x23, 0xfd, 0xf7, 0x54, 0x2e, 0x96, 0x4e,
+ 0x8d, 0x0b, 0x73, 0xbe, 0x98, 0x13, 0xc1, 0xbc, 0x26, 0xca, 0x06, 0x17,
+ 0x32, 0x94, 0x6b, 0x68, 0xc6, 0x1b, 0xaf, 0xd4, 0xea, 0x1e, 0x16, 0xee,
+ 0x4d, 0xa6, 0x93, 0x87, 0xb4, 0xbd, 0x23, 0x32, 0x5a, 0x62, 0xdd, 0xdd,
+ 0xb0, 0x76, 0xfc, 0xba, 0xfa, 0x3a, 0x57, 0x0d, 0x7c, 0x1e, 0xc5, 0xc5,
+ 0xe2, 0xcc, 0x29, 0x79, 0x39, 0xd6, 0x27, 0x2f, 0xd3, 0x8e, 0x1d, 0x00,
+ 0x6d, 0x7b, 0xbe, 0xce, 0x2b, 0xd1, 0xe5, 0xb9, 0x40, 0x16, 0x73, 0xfd,
+ 0x3d, 0xb4, 0xdb, 0x0b, 0x4a, 0xf3, 0x84, 0x28, 0xb4, 0x8d, 0xe7, 0x2b,
+ 0x32, 0x98, 0x2f, 0xd9, 0xd8, 0xd1, 0x30, 0xe7, 0xbc, 0xa1, 0x6e, 0xee,
+ 0x1b, 0xc5, 0x05, 0x4c, 0x83, 0xb1, 0x94, 0xd3, 0xe0, 0x7f, 0xaa, 0xc5,
+ 0xd8, 0x10, 0xd0, 0x23, 0xad, 0xf7, 0xb7, 0x71, 0x6f, 0x56, 0xc1, 0x27,
+ 0x57, 0x6d, 0x1f, 0xbe, 0x56, 0x65, 0xfe, 0x32, 0x09, 0xbd, 0x6a, 0x65,
+ 0x65, 0x7c, 0xb0, 0x63, 0x89, 0xbe, 0x39, 0xbe, 0xb4, 0xc5, 0xfc, 0xd4,
+ 0xe0, 0x40, 0x45, 0x54, 0x2c, 0xe3, 0xc5, 0x07, 0x2a, 0xcb, 0x69, 0xfe,
+ 0x8b, 0xd5, 0xcf, 0x5a, 0xdb, 0xb2, 0x3e, 0x46, 0x5b, 0xff, 0x8e, 0x7c,
+ 0xb7, 0x6c, 0xff, 0x23, 0x05, 0xbe, 0xb2, 0xfb, 0xc6, 0x5c, 0x93, 0xec,
+ 0x5b, 0x19, 0xd8, 0x9c, 0xd6, 0x3e, 0x1f, 0x73, 0x3b, 0xe2, 0x36, 0xbf,
+ 0xce, 0xe0, 0x3a, 0x5b, 0x71, 0x64, 0x02, 0xf2, 0xe1, 0xb0, 0xfc, 0x53,
+ 0x98, 0x4d, 0x98, 0xf7, 0x66, 0x7d, 0x59, 0x9f, 0x7b, 0x1b, 0xcd, 0x52,
+ 0x3c, 0xed, 0x4a, 0xe1, 0x34, 0xf7, 0xd4, 0xce, 0xdd, 0x51, 0xcb, 0x0f,
+ 0xa1, 0x1c, 0xe0, 0xbe, 0xb0, 0x23, 0x45, 0xf8, 0xc8, 0x83, 0xdc, 0xef,
+ 0xef, 0xfd, 0x47, 0xe6, 0xea, 0xc4, 0xb9, 0x4e, 0xa6, 0x6d, 0x0b, 0xda,
+ 0x36, 0xda, 0xb6, 0xc1, 0xc7, 0xdf, 0x5c, 0xdb, 0x8d, 0x68, 0x1b, 0x8f,
+ 0xc6, 0x7d, 0x83, 0x6d, 0x35, 0x3e, 0xaf, 0x1d, 0x28, 0x95, 0x17, 0x5d,
+ 0xdf, 0x4f, 0x8e, 0x49, 0xd6, 0x19, 0xed, 0xd3, 0xf3, 0xb9, 0x76, 0xa0,
+ 0x02, 0x38, 0x12, 0x61, 0x58, 0x0c, 0x22, 0xbd, 0xce, 0x7f, 0x27, 0xa1,
+ 0xde, 0x59, 0xc6, 0x7d, 0x50, 0xfa, 0x27, 0x8c, 0xba, 0x7a, 0xcc, 0xc1,
+ 0x93, 0x22, 0xf7, 0x3b, 0x13, 0x9b, 0x70, 0x57, 0x1d, 0xc4, 0x49, 0xde,
+ 0x67, 0xfc, 0x78, 0x93, 0x2d, 0x8f, 0xb1, 0x3c, 0xed, 0x42, 0x96, 0x98,
+ 0xf2, 0x98, 0x2d, 0x07, 0x4c, 0x41, 0x31, 0x05, 0x6e, 0xb3, 0xe5, 0x7c,
+ 0x56, 0xba, 0xdc, 0x3c, 0x1b, 0x1e, 0x1a, 0x11, 0xc6, 0x89, 0x72, 0xd7,
+ 0x37, 0xc8, 0x4e, 0xac, 0x0f, 0x7d, 0x50, 0x47, 0x9a, 0x01, 0xc7, 0xc5,
+ 0xe0, 0xc7, 0x61, 0xab, 0x87, 0xf2, 0x9d, 0xc0, 0xd0, 0xff, 0x8c, 0x74,
+ 0x65, 0x95, 0xc3, 0x5c, 0x83, 0x50, 0x86, 0x82, 0x5d, 0xc9, 0xbd, 0xf8,
+ 0x3d, 0xda, 0x9b, 0x92, 0x99, 0x7e, 0xd0, 0x63, 0x2f, 0x79, 0x63, 0x27,
+ 0x6c, 0x28, 0xfc, 0xee, 0x6a, 0x91, 0x45, 0xaf, 0xe0, 0xad, 0x83, 0xff,
+ 0x37, 0x88, 0x59, 0xcd, 0x96, 0x7c, 0xef, 0x36, 0x08, 0xb9, 0xac, 0xd7,
+ 0x85, 0x7b, 0xfd, 0x7c, 0xbf, 0x8e, 0xf9, 0x9e, 0x6b, 0x96, 0x66, 0x96,
+ 0xd7, 0xd7, 0x6d, 0x94, 0xfd, 0xde, 0x6e, 0x2f, 0xbe, 0xac, 0xee, 0x25,
+ 0xd4, 0x65, 0x99, 0xef, 0x31, 0x17, 0x68, 0xa6, 0x42, 0x3a, 0x33, 0xb0,
+ 0x76, 0x74, 0x85, 0xe1, 0xf5, 0x01, 0xc7, 0x0d, 0xc3, 0x1b, 0x82, 0x1e,
+ 0xef, 0x19, 0x79, 0x2e, 0x34, 0x36, 0x5a, 0x44, 0x3b, 0xcf, 0x5a, 0x79,
+ 0x1d, 0x86, 0x2f, 0x07, 0xdd, 0xf2, 0xb9, 0x6a, 0xfa, 0x1c, 0x7d, 0xf8,
+ 0xf3, 0x78, 0x3e, 0x1f, 0x98, 0xfc, 0xa5, 0x3f, 0x43, 0xbb, 0x84, 0xea,
+ 0x05, 0x0d, 0xfb, 0xf2, 0x59, 0xed, 0xf3, 0x13, 0x7f, 0x66, 0xcf, 0xa0,
+ 0x06, 0x03, 0x26, 0xec, 0xe7, 0x36, 0x7b, 0xcc, 0x69, 0xd4, 0xf4, 0x5b,
+ 0xff, 0x4e, 0xe1, 0x1d, 0xcb, 0xc2, 0xf0, 0x8a, 0xbe, 0x96, 0xf5, 0xd0,
+ 0xd7, 0x93, 0xdc, 0x0b, 0x7c, 0x9f, 0xe6, 0x3f, 0x91, 0x03, 0xdc, 0xf7,
+ 0x02, 0x0e, 0x95, 0xf2, 0x8f, 0x75, 0xa8, 0x74, 0x41, 0xe4, 0x2d, 0x58,
+ 0x7f, 0xae, 0x31, 0x18, 0xa4, 0x15, 0xb0, 0xef, 0xfa, 0xa5, 0x66, 0x13,
+ 0x9b, 0xa2, 0x6f, 0x9e, 0xdd, 0x0c, 0xdf, 0x59, 0xdb, 0x33, 0xdc, 0x57,
+ 0x1f, 0x6b, 0x0d, 0xc3, 0xf7, 0x06, 0xd1, 0x9a, 0xd9, 0xd8, 0x37, 0x74,
+ 0x7c, 0xbe, 0x57, 0xd6, 0x1b, 0xbb, 0x90, 0xb9, 0x8d, 0x29, 0xbd, 0x4f,
+ 0xa0, 0xda, 0xa0, 0x43, 0x76, 0xfd, 0x00, 0x38, 0xe5, 0x18, 0xcc, 0x73,
+ 0x8c, 0x60, 0xaa, 0xb5, 0xcf, 0xf7, 0xae, 0xb3, 0x36, 0xac, 0x0b, 0x5c,
+ 0xfa, 0x5e, 0x87, 0xfa, 0x5e, 0x68, 0x74, 0x6b, 0x44, 0xc3, 0xff, 0x10,
+ 0x3e, 0x98, 0x30, 0xcf, 0xb9, 0x5d, 0xec, 0x63, 0xa7, 0x8c, 0xef, 0xc2,
+ 0xb3, 0x7b, 0x1d, 0xee, 0x03, 0x57, 0xc6, 0xe4, 0xaa, 0xe4, 0x80, 0xda,
+ 0xe5, 0x3d, 0x28, 0x3d, 0x56, 0xc6, 0x7d, 0x09, 0xfa, 0xbe, 0x00, 0xff,
+ 0xbe, 0x49, 0x1e, 0x04, 0x4d, 0xab, 0xbe, 0x74, 0x6a, 0x5e, 0xa5, 0xbb,
+ 0xa7, 0x55, 0x3a, 0x18, 0x51, 0x13, 0x9c, 0x57, 0x3f, 0x71, 0x31, 0x4d,
+ 0xfc, 0x96, 0x81, 0xff, 0x32, 0x70, 0x7c, 0xd9, 0x3d, 0xe3, 0xc0, 0xea,
+ 0x16, 0xa3, 0xdf, 0x0a, 0x9a, 0x36, 0x8d, 0x9d, 0xff, 0xa7, 0x41, 0xb4,
+ 0x86, 0x3d, 0x5e, 0x03, 0x73, 0x71, 0xd6, 0x5c, 0xa3, 0x3c, 0xd7, 0x08,
+ 0x8a, 0xa1, 0x00, 0xba, 0x4f, 0xa7, 0xc6, 0xd4, 0x62, 0xb8, 0x79, 0x4f,
+ 0x67, 0xf7, 0x63, 0xba, 0x9f, 0x74, 0x90, 0x55, 0x4f, 0x02, 0x9e, 0x9d,
+ 0xd2, 0xb4, 0x87, 0x78, 0x26, 0xac, 0x71, 0xc6, 0xa7, 0xbc, 0x3b, 0x50,
+ 0x77, 0x44, 0xe9, 0x3d, 0x6d, 0x5b, 0x87, 0x30, 0xbf, 0x1b, 0xf8, 0xa5,
+ 0x1e, 0x62, 0xcc, 0xed, 0xb5, 0x74, 0x21, 0x64, 0xd2, 0x49, 0xca, 0xc0,
+ 0x98, 0x89, 0x25, 0x57, 0xef, 0xe4, 0xfa, 0xd3, 0x13, 0x88, 0xbb, 0x90,
+ 0x51, 0x13, 0xe0, 0xe2, 0xa3, 0x27, 0xc5, 0x6d, 0xf0, 0xbb, 0xd7, 0x1b,
+ 0x3f, 0x8c, 0x3e, 0x19, 0xc7, 0x6e, 0x90, 0xe2, 0xaa, 0xf8, 0xcd, 0x24,
+ 0xe0, 0x6f, 0x96, 0xf1, 0x93, 0x5c, 0x0b, 0x17, 0x32, 0x87, 0x63, 0x8b,
+ 0x9b, 0xeb, 0x0d, 0xc3, 0x51, 0x96, 0x9f, 0x26, 0xff, 0x4a, 0x9a, 0xef,
+ 0x0a, 0xa7, 0xe7, 0x37, 0xab, 0x65, 0xb2, 0xb6, 0xc5, 0xc2, 0xa1, 0xf1,
+ 0x24, 0x93, 0x5a, 0x8e, 0x50, 0xdf, 0xcc, 0xd4, 0xc1, 0x13, 0x7c, 0x7c,
+ 0xc2, 0x6f, 0x7c, 0x13, 0xf0, 0xfc, 0x0f, 0xc0, 0xd3, 0x62, 0xe1, 0x69,
+ 0x5c, 0x01, 0x4f, 0x4b, 0x04, 0x0f, 0xe4, 0x1c, 0xe5, 0x6a, 0xfc, 0xda,
+ 0x6c, 0x45, 0x9c, 0xa2, 0x2f, 0xed, 0x4a, 0xfb, 0x43, 0xd4, 0x37, 0x8d,
+ 0xde, 0x68, 0x9f, 0x27, 0xa3, 0x5a, 0xd7, 0xb8, 0xd7, 0x76, 0x56, 0xe6,
+ 0x61, 0xbd, 0x8a, 0x93, 0xf3, 0x09, 0xfb, 0x5a, 0x76, 0xd5, 0x3d, 0x90,
+ 0xff, 0x0b, 0x69, 0xd7, 0xda, 0x12, 0x93, 0x01, 0xfd, 0xa0, 0x84, 0xce,
+ 0x15, 0xa8, 0xc1, 0xf4, 0x12, 0x60, 0x82, 0x3c, 0x3e, 0xd9, 0xe3, 0x0d,
+ 0xcb, 0x56, 0xed, 0xeb, 0x59, 0x5c, 0x63, 0x6e, 0xf1, 0xba, 0xb9, 0x41,
+ 0xff, 0xa9, 0x68, 0x6e, 0x90, 0x89, 0xa8, 0x37, 0x29, 0x7f, 0x64, 0x71,
+ 0xb1, 0x11, 0x73, 0x8a, 0xd7, 0xcd, 0xa7, 0x33, 0x79, 0x3b, 0xcb, 0xcc,
+ 0x7c, 0xba, 0x8a, 0x7e, 0xdc, 0xe2, 0x77, 0x2d, 0x9f, 0xc4, 0xd8, 0x3d,
+ 0xd3, 0x12, 0xca, 0x44, 0x80, 0x35, 0xea, 0xa6, 0x7f, 0x12, 0xb7, 0xb9,
+ 0xd7, 0x0a, 0xcf, 0x1b, 0x2c, 0x7f, 0x79, 0x52, 0xd4, 0xfe, 0xe0, 0xdf,
+ 0x59, 0x3e, 0x75, 0x6d, 0x9e, 0x1c, 0x7f, 0x1f, 0x5c, 0x6f, 0xf3, 0x05,
+ 0x0a, 0x59, 0x79, 0x65, 0x3d, 0xed, 0x92, 0x06, 0xff, 0x57, 0x56, 0x94,
+ 0xc5, 0x51, 0x76, 0x6a, 0xbd, 0x95, 0x0b, 0x28, 0xbb, 0x07, 0x7e, 0x1f,
+ 0xf3, 0x3e, 0xf8, 0x8e, 0x32, 0xb8, 0x1e, 0x27, 0x3d, 0x60, 0x45, 0xf2,
+ 0x3c, 0xe5, 0x22, 0x6d, 0x4a, 0xcc, 0x51, 0x6d, 0x8f, 0xe2, 0xf2, 0xf8,
+ 0xbd, 0x96, 0xed, 0x4f, 0x7c, 0x13, 0xd7, 0xf2, 0x8d, 0x09, 0xf0, 0xfd,
+ 0xe1, 0xc0, 0x71, 0x67, 0x98, 0x57, 0xa0, 0x69, 0xb8, 0xbe, 0xef, 0x1b,
+ 0x18, 0x26, 0xb4, 0xb4, 0x4c, 0x7a, 0x21, 0x4f, 0x3b, 0xd2, 0x44, 0x5d,
+ 0x7c, 0xd2, 0xd3, 0x39, 0xee, 0x39, 0xad, 0x97, 0xeb, 0xd7, 0xb1, 0x09,
+ 0xba, 0x26, 0x61, 0x78, 0xd4, 0x33, 0xfb, 0xe7, 0xb5, 0xfe, 0x46, 0xd0,
+ 0x1f, 0xed, 0x34, 0xf8, 0xfd, 0x3e, 0xa3, 0x43, 0x94, 0x5f, 0x8e, 0xab,
+ 0xae, 0xd6, 0x7e, 0x6b, 0x5c, 0xe7, 0x37, 0x2d, 0xd5, 0x1d, 0xb3, 0x63,
+ 0x93, 0x6e, 0xcd, 0x7e, 0x42, 0x6d, 0x7c, 0x71, 0xd4, 0x2e, 0x01, 0x95,
+ 0x35, 0xca, 0x44, 0x1f, 0x69, 0x94, 0x73, 0xd7, 0x36, 0xd4, 0xb5, 0xb4,
+ 0x23, 0x0c, 0x7d, 0xd2, 0x76, 0x72, 0xaf, 0xcd, 0x97, 0x1a, 0x8d, 0xcf,
+ 0x92, 0x90, 0x2d, 0x0d, 0x3a, 0x2f, 0x01, 0x65, 0x95, 0x48, 0x97, 0xb9,
+ 0x32, 0xd3, 0xfb, 0x7f, 0xc2, 0xec, 0x41, 0xd6, 0x5d, 0x33, 0x0f, 0x20,
+ 0x39, 0x2d, 0x1a, 0x4f, 0x5f, 0xab, 0xe1, 0xc9, 0xce, 0x2d, 0xb1, 0x72,
+ 0x6e, 0x70, 0x6a, 0xfd, 0x7b, 0x20, 0x3b, 0xb9, 0x4e, 0x26, 0xe7, 0xfc,
+ 0x9c, 0x38, 0x6e, 0xae, 0x7b, 0xad, 0xb9, 0x4d, 0x46, 0x78, 0xe5, 0xdc,
+ 0x40, 0xab, 0xd1, 0xbc, 0x48, 0xdb, 0x09, 0xbd, 0xef, 0xa4, 0x14, 0x61,
+ 0xd9, 0xb8, 0x02, 0xb7, 0x11, 0xdd, 0x19, 0x9a, 0xfb, 0xa2, 0xa6, 0xb9,
+ 0x16, 0x4b, 0x73, 0xa8, 0xeb, 0x71, 0x1f, 0xfd, 0xbe, 0x96, 0x1a, 0xcd,
+ 0x6d, 0xb0, 0x34, 0xa7, 0x5a, 0xcc, 0x1e, 0x7b, 0xb9, 0xc5, 0xec, 0x71,
+ 0x25, 0x57, 0x3c, 0xbf, 0x93, 0xcf, 0xf0, 0xc5, 0xa2, 0xe7, 0x7a, 0x58,
+ 0xcf, 0x03, 0xd6, 0x7a, 0x59, 0xd3, 0x64, 0xe3, 0x78, 0xdc, 0x8f, 0xa7,
+ 0xdf, 0xe7, 0xca, 0xa3, 0xb0, 0x83, 0x8a, 0x95, 0x1f, 0x84, 0xf3, 0xf0,
+ 0xfd, 0x26, 0x96, 0x74, 0xef, 0x4c, 0x0b, 0xf9, 0x6d, 0x1a, 0xbf, 0x8e,
+ 0xd4, 0xf9, 0x3c, 0x98, 0x2f, 0xca, 0xfe, 0x19, 0xeb, 0x01, 0xb9, 0xbc,
+ 0x54, 0x97, 0x31, 0x10, 0xe3, 0xe3, 0x9c, 0xab, 0xb6, 0xdb, 0xfd, 0x49,
+ 0xca, 0xf9, 0xbb, 0xe1, 0x13, 0xdd, 0x03, 0x3d, 0x49, 0xfa, 0xee, 0xd8,
+ 0x60, 0xf2, 0x89, 0x13, 0xd0, 0x63, 0x3f, 0x6f, 0x73, 0xab, 0x6e, 0xbf,
+ 0x7d, 0xed, 0x5c, 0x62, 0xd0, 0xbe, 0x43, 0x9a, 0x79, 0xdb, 0x06, 0x13,
+ 0x83, 0xde, 0xba, 0x81, 0x7c, 0xa6, 0x76, 0xed, 0xda, 0xa8, 0xf9, 0xc2,
+ 0x89, 0x9e, 0xab, 0x2b, 0x9e, 0xa3, 0x76, 0x7f, 0xb3, 0x71, 0x79, 0xbb,
+ 0xa8, 0xfc, 0xce, 0x4d, 0xcb, 0xcb, 0xff, 0xa3, 0xb7, 0xbc, 0x7d, 0xe3,
+ 0xe6, 0xe5, 0xcf, 0x7b, 0x57, 0x3c, 0x7f, 0x64, 0xc5, 0xf3, 0xef, 0xad,
+ 0x78, 0xde, 0xd1, 0xba, 0xfc, 0xf9, 0x43, 0x2b, 0x9e, 0x4f, 0xb5, 0xae,
+ 0x0d, 0xef, 0x42, 0xeb, 0x72, 0xb8, 0xee, 0xd6, 0xfb, 0x07, 0xd3, 0x55,
+ 0x57, 0xf6, 0x96, 0xf0, 0xde, 0x79, 0xdf, 0x16, 0xa3, 0xd7, 0xea, 0xdf,
+ 0x33, 0x5e, 0xb7, 0x7b, 0xcb, 0xf2, 0xfe, 0x6a, 0xed, 0xf6, 0xd5, 0xda,
+ 0x05, 0xb5, 0x76, 0x46, 0xb6, 0xcd, 0x54, 0xf9, 0x8e, 0xe5, 0x51, 0xbf,
+ 0xa6, 0xed, 0x44, 0xd9, 0xd7, 0x39, 0xb7, 0xc3, 0x3a, 0xe7, 0x36, 0x05,
+ 0x3e, 0xbc, 0x5b, 0xc7, 0xa8, 0x36, 0xc3, 0x50, 0x1e, 0xaf, 0x6e, 0xd4,
+ 0x71, 0x2a, 0xd1, 0x79, 0xb7, 0xc3, 0xb0, 0x6d, 0x99, 0x6b, 0x1b, 0xca,
+ 0xfe, 0xc0, 0xdc, 0x4d, 0xee, 0xed, 0xb1, 0x70, 0xc0, 0x0b, 0xc3, 0x71,
+ 0xff, 0x76, 0x9b, 0x7f, 0x86, 0x7b, 0xd5, 0xb4, 0xa1, 0x0e, 0x7e, 0x0c,
+ 0x3a, 0xb8, 0xa6, 0x7b, 0xef, 0xc6, 0x58, 0xf3, 0xa0, 0x99, 0x3e, 0xf9,
+ 0x9d, 0x6a, 0xfa, 0xf3, 0xa2, 0xcf, 0x16, 0xf5, 0xc2, 0x86, 0x9b, 0xbf,
+ 0xf3, 0xbd, 0x7e, 0x00, 0x5b, 0x2f, 0x94, 0x87, 0x83, 0x7e, 0xd0, 0x50,
+ 0x37, 0xec, 0x3d, 0x5f, 0xfb, 0xa5, 0x8f, 0x6b, 0xda, 0x22, 0x8d, 0x31,
+ 0xdf, 0x86, 0x76, 0x81, 0x13, 0xcf, 0xf5, 0xfe, 0xb1, 0x89, 0xd3, 0x04,
+ 0x9d, 0xde, 0x97, 0xc0, 0xb7, 0x43, 0xfe, 0x0e, 0xf8, 0x28, 0xa4, 0x21,
+ 0xc6, 0xd3, 0xb6, 0xdb, 0x7c, 0xc7, 0x36, 0x99, 0x76, 0x19, 0x77, 0x4c,
+ 0xf7, 0x8f, 0x08, 0xe7, 0x9d, 0x4e, 0xa6, 0x94, 0xb6, 0xab, 0xc2, 0x03,
+ 0x01, 0x73, 0x79, 0xb9, 0x67, 0x43, 0x7e, 0x1e, 0xbe, 0x6b, 0xc2, 0x2f,
+ 0x78, 0x31, 0x9b, 0xff, 0x9b, 0x2b, 0x19, 0xda, 0x1c, 0x23, 0x6d, 0xc2,
+ 0x9f, 0x5a, 0xe8, 0xfd, 0xbb, 0x90, 0xf6, 0x7d, 0x4a, 0x91, 0xf6, 0xbf,
+ 0x17, 0xce, 0xba, 0xec, 0x8b, 0x70, 0x0f, 0xdf, 0x95, 0xd3, 0xb8, 0xba,
+ 0x5b, 0x0e, 0x97, 0x69, 0x0b, 0xc7, 0x75, 0x7e, 0xc8, 0x68, 0x40, 0x3b,
+ 0x2d, 0x0e, 0x3c, 0x8e, 0x01, 0x7f, 0x2d, 0xb0, 0xb9, 0x6f, 0x44, 0x9d,
+ 0x98, 0x8c, 0x0c, 0xb7, 0x80, 0xf7, 0xc8, 0x9f, 0xbc, 0xbb, 0xa8, 0xef,
+ 0xc9, 0x5c, 0x69, 0x44, 0xe7, 0xef, 0x3d, 0x8e, 0xb6, 0x4f, 0xe0, 0x9a,
+ 0x29, 0x7d, 0x18, 0x6d, 0xde, 0xaf, 0xeb, 0xcf, 0x4c, 0x32, 0x17, 0x5a,
+ 0x20, 0x97, 0x3e, 0x21, 0xc5, 0xd9, 0x0e, 0x19, 0x49, 0xcc, 0x4f, 0xbb,
+ 0x4b, 0x71, 0x99, 0x47, 0x37, 0x70, 0xcf, 0xa4, 0x78, 0x35, 0xf7, 0x97,
+ 0xc5, 0x1d, 0xde, 0xad, 0xba, 0x5b, 0xb5, 0xcf, 0xd5, 0x2f, 0x43, 0xd5,
+ 0x8c, 0xdc, 0x54, 0x7d, 0x62, 0x8b, 0x89, 0x45, 0x2d, 0x8b, 0x6f, 0x1d,
+ 0xd3, 0x52, 0xe5, 0x84, 0xcb, 0xf3, 0x59, 0x32, 0x73, 0x56, 0x24, 0x76,
+ 0x22, 0x8a, 0x4d, 0xb2, 0xcc, 0x93, 0x8e, 0xab, 0x01, 0xd7, 0x59, 0xc8,
+ 0xd6, 0x44, 0x5c, 0x3e, 0xbb, 0x2b, 0x1a, 0xab, 0x10, 0x4e, 0xed, 0x2a,
+ 0xc8, 0x9d, 0xb8, 0xf2, 0x57, 0xa7, 0x27, 0x73, 0x8a, 0xe3, 0xfe, 0x75,
+ 0x48, 0x59, 0xa6, 0x32, 0xbe, 0x14, 0x5a, 0xa3, 0xb1, 0xe1, 0xdf, 0xec,
+ 0x89, 0xc6, 0xa7, 0xcd, 0x6d, 0xce, 0x56, 0x14, 0xb9, 0x8f, 0x03, 0xfa,
+ 0x8b, 0x65, 0x3e, 0xb7, 0x81, 0xbe, 0xc3, 0x80, 0xb0, 0x1d, 0x64, 0xba,
+ 0x62, 0xdf, 0x84, 0x93, 0xf0, 0xd7, 0xc3, 0xb9, 0x90, 0x4a, 0x00, 0x47,
+ 0x85, 0xd7, 0x85, 0xb7, 0xc7, 0xf3, 0xd5, 0x5a, 0xf0, 0xde, 0x6c, 0x63,
+ 0x89, 0x8c, 0x0f, 0xae, 0x03, 0xde, 0x5a, 0x50, 0x9e, 0x97, 0x89, 0x93,
+ 0xb7, 0x6e, 0xe1, 0xde, 0x78, 0x83, 0xef, 0xd8, 0x1c, 0x56, 0x9e, 0x39,
+ 0x9a, 0x40, 0x1d, 0xbe, 0x1f, 0x41, 0x9b, 0x74, 0x21, 0x17, 0xdb, 0x02,
+ 0x9f, 0x88, 0xe3, 0x86, 0xb1, 0x8e, 0x3d, 0xcd, 0x3a, 0x27, 0x55, 0xce,
+ 0x52, 0x9f, 0x47, 0x6d, 0x27, 0x74, 0xce, 0x07, 0xfc, 0xf6, 0xc2, 0x60,
+ 0x8c, 0xf2, 0xab, 0x5b, 0x06, 0xa8, 0x4f, 0xce, 0x8e, 0x68, 0xda, 0xef,
+ 0xdc, 0xc5, 0xf3, 0x57, 0x3d, 0xc6, 0x46, 0x4f, 0x10, 0xc6, 0x9b, 0x51,
+ 0x0e, 0xfb, 0xfd, 0x35, 0x61, 0x28, 0xbc, 0x49, 0x18, 0x0a, 0x6f, 0x12,
+ 0x06, 0xe2, 0x02, 0x70, 0x54, 0xaf, 0xd8, 0x18, 0xc5, 0xbe, 0xb7, 0x62,
+ 0x1e, 0x47, 0xca, 0x05, 0x39, 0x5a, 0x76, 0x74, 0xdc, 0x71, 0x5e, 0x51,
+ 0x26, 0x78, 0xe0, 0x49, 0xf0, 0x5e, 0x19, 0xbc, 0x59, 0x06, 0x2f, 0x96,
+ 0xc1, 0x97, 0xb0, 0xff, 0xcf, 0x43, 0x3e, 0x3c, 0x81, 0xb5, 0x79, 0x7c,
+ 0x19, 0x2f, 0x67, 0x35, 0x2f, 0x17, 0xcb, 0xf4, 0xd5, 0x7a, 0x2f, 0xc3,
+ 0xaf, 0xae, 0x0c, 0x94, 0xd2, 0x50, 0x25, 0x8e, 0x9b, 0xef, 0xfd, 0x28,
+ 0xf9, 0x55, 0x1e, 0x0c, 0x0e, 0xa2, 0xcd, 0x24, 0x68, 0x3c, 0x4d, 0x3b,
+ 0x90, 0xf6, 0x4f, 0x01, 0xbc, 0x79, 0x8c, 0xbe, 0x9a, 0xba, 0x7a, 0xb3,
+ 0x50, 0xbf, 0xb8, 0x7b, 0x98, 0xcb, 0xc8, 0xb9, 0xa6, 0x56, 0xe0, 0xc9,
+ 0xf0, 0xef, 0x98, 0x4f, 0x3d, 0x43, 0xbe, 0x7d, 0x96, 0x7c, 0x5b, 0xc7,
+ 0xab, 0x3f, 0xc5, 0xf9, 0x85, 0xde, 0xae, 0xb5, 0xda, 0xd6, 0xea, 0x6f,
+ 0x5e, 0xaa, 0xaf, 0xc7, 0x9f, 0x24, 0x3f, 0xaa, 0xcc, 0x24, 0x71, 0x9f,
+ 0xca, 0xc5, 0x76, 0x58, 0xdc, 0xc3, 0x76, 0xdb, 0x73, 0x05, 0x70, 0xdf,
+ 0x2e, 0x85, 0xb9, 0x50, 0xfc, 0x3d, 0x51, 0x9f, 0xb5, 0x7e, 0x3c, 0xdb,
+ 0xcf, 0x68, 0xc9, 0x91, 0xc1, 0x5d, 0xdc, 0xd7, 0x70, 0xa0, 0xe7, 0xa3,
+ 0xf5, 0x80, 0xbd, 0xaf, 0xd7, 0x9c, 0x32, 0x96, 0xb2, 0xb5, 0xc5, 0xc6,
+ 0x9f, 0xd8, 0xdf, 0xe4, 0x8a, 0x75, 0x7a, 0x31, 0xe4, 0xb9, 0xb6, 0x09,
+ 0xff, 0x60, 0x1d, 0xad, 0x3c, 0x60, 0x69, 0x45, 0xad, 0x98, 0xc7, 0x5d,
+ 0x96, 0x56, 0x22, 0x78, 0x13, 0x11, 0xad, 0x34, 0x45, 0xb4, 0x52, 0x98,
+ 0x8e, 0x68, 0x85, 0x6d, 0xef, 0x8a, 0x68, 0x25, 0x55, 0x4f, 0x2b, 0x85,
+ 0x69, 0x07, 0xd7, 0x4a, 0x38, 0x48, 0x2f, 0xec, 0x87, 0xf4, 0x02, 0x58,
+ 0xaa, 0x9f, 0x59, 0xa2, 0x97, 0x04, 0xfa, 0x39, 0x5a, 0x36, 0x39, 0x22,
+ 0xf0, 0xbb, 0xac, 0x0e, 0xf1, 0xb0, 0xe6, 0xc6, 0x47, 0x5c, 0x9b, 0x46,
+ 0x02, 0x4b, 0x23, 0xb5, 0x7c, 0xfa, 0x15, 0xb4, 0x01, 0xdc, 0x33, 0x37,
+ 0x76, 0xb7, 0xa6, 0x8d, 0xfb, 0x83, 0x12, 0xea, 0x0e, 0x83, 0x36, 0x22,
+ 0x1c, 0xbc, 0xc7, 0xe2, 0x60, 0xe5, 0x5a, 0xde, 0x66, 0x71, 0x30, 0x6c,
+ 0x71, 0xa0, 0xf9, 0xa5, 0xc0, 0x35, 0x53, 0x1a, 0x07, 0x4d, 0x1a, 0x07,
+ 0xa2, 0xa2, 0xb6, 0xb7, 0xad, 0x81, 0x03, 0xd6, 0x19, 0xd6, 0xf3, 0x8f,
+ 0x61, 0xfe, 0xb7, 0x63, 0xfe, 0x4a, 0xcf, 0x9f, 0xeb, 0x60, 0x72, 0xb9,
+ 0x8b, 0xd5, 0xbf, 0x5e, 0x9a, 0x7f, 0x2b, 0xfa, 0x38, 0x52, 0x8e, 0xe9,
+ 0xf9, 0xc3, 0xb6, 0xef, 0x8f, 0xe6, 0xff, 0x78, 0xd5, 0xe4, 0x53, 0x3f,
+ 0xbe, 0x4a, 0xcf, 0x95, 0x2c, 0x6f, 0xf8, 0xda, 0x2f, 0x66, 0x4c, 0xfb,
+ 0x3c, 0x74, 0xdb, 0x54, 0x90, 0xb2, 0xe7, 0xae, 0x8c, 0xbd, 0xf4, 0x95,
+ 0x80, 0xbc, 0xf3, 0x21, 0x9d, 0xd7, 0x72, 0x8e, 0x76, 0x53, 0xb9, 0x55,
+ 0x06, 0xa7, 0xea, 0xe1, 0x26, 0xbc, 0x05, 0x2d, 0x47, 0xf3, 0x98, 0xdf,
+ 0x68, 0xd0, 0x0d, 0xf9, 0xa6, 0x69, 0x09, 0xe5, 0xe9, 0xc2, 0x40, 0xac,
+ 0x49, 0xd4, 0x03, 0xef, 0xc7, 0x9c, 0x5d, 0xd9, 0xe2, 0x77, 0x7a, 0x7b,
+ 0x14, 0x75, 0xe1, 0x95, 0x75, 0xba, 0xb0, 0xcd, 0xea, 0xc2, 0xcd, 0xd4,
+ 0x85, 0x80, 0xfb, 0x6e, 0x39, 0x56, 0xe6, 0xfa, 0x15, 0x52, 0x4d, 0xd0,
+ 0xff, 0xdf, 0xf1, 0x79, 0xc6, 0x45, 0xc7, 0xcd, 0x92, 0xc7, 0x34, 0x2d,
+ 0x53, 0xa7, 0xa5, 0xf5, 0x99, 0x90, 0x05, 0xda, 0xd8, 0x09, 0xc6, 0x42,
+ 0xa9, 0xf7, 0xfe, 0x3e, 0xfc, 0xcc, 0x1a, 0x7a, 0x6f, 0xbc, 0x6c, 0xec,
+ 0xb7, 0x06, 0xd8, 0x84, 0x72, 0xaa, 0x0d, 0xd7, 0x26, 0x9e, 0x89, 0xe8,
+ 0xee, 0x52, 0xcd, 0xd2, 0x70, 0x6a, 0xa3, 0x8c, 0x4d, 0x19, 0x1b, 0x57,
+ 0x9d, 0x02, 0xfe, 0x4f, 0x31, 0x7f, 0x56, 0x74, 0xbe, 0x7f, 0x7e, 0x12,
+ 0x76, 0xee, 0xcc, 0xdd, 0xe6, 0x1c, 0xc8, 0x54, 0x83, 0xfe, 0x4d, 0x1b,
+ 0xa4, 0x18, 0x64, 0xa1, 0xef, 0xe2, 0x32, 0x86, 0x3e, 0x3b, 0x77, 0x35,
+ 0x62, 0xce, 0x09, 0xb4, 0xa5, 0xcf, 0xc7, 0x38, 0x5a, 0xa3, 0xb8, 0x33,
+ 0x49, 0x9d, 0xab, 0xcf, 0xf3, 0xae, 0xb9, 0xfe, 0x56, 0xbc, 0x63, 0x7e,
+ 0x84, 0x87, 0xb1, 0x22, 0xd9, 0x8f, 0x7e, 0x4f, 0x88, 0xdd, 0xef, 0xc9,
+ 0x68, 0xfd, 0x17, 0x3b, 0xe1, 0xd9, 0xb3, 0x7a, 0xfd, 0x58, 0xf7, 0xb5,
+ 0xf4, 0xa2, 0x31, 0x72, 0x73, 0x58, 0x3f, 0x75, 0xd6, 0xc5, 0xbd, 0x1d,
+ 0xf7, 0xa8, 0xbf, 0x48, 0x8f, 0x40, 0x37, 0xbe, 0xfd, 0xd0, 0x26, 0x69,
+ 0x06, 0xbe, 0x67, 0x14, 0x70, 0x6d, 0x72, 0xbc, 0x0a, 0x9a, 0x17, 0x6a,
+ 0xf4, 0xf0, 0xc4, 0xeb, 0xf2, 0x03, 0x69, 0x82, 0xb4, 0x40, 0xb9, 0x48,
+ 0xda, 0xa0, 0x4c, 0x24, 0x6d, 0x1b, 0x7a, 0x78, 0x2c, 0xf0, 0x63, 0xcc,
+ 0x03, 0x30, 0x71, 0x79, 0xd2, 0x06, 0x69, 0x3e, 0xa5, 0xe3, 0xf5, 0x59,
+ 0xf9, 0x96, 0x64, 0x5b, 0x3b, 0x61, 0x97, 0xfd, 0xdb, 0xae, 0xb1, 0x39,
+ 0x2b, 0xac, 0x69, 0x0e, 0xba, 0x89, 0x39, 0x79, 0xdd, 0xf2, 0x9e, 0x6a,
+ 0x01, 0x78, 0xb8, 0x17, 0x4a, 0xf9, 0x6e, 0x9d, 0xe7, 0xb8, 0xaf, 0xb4,
+ 0x49, 0x6e, 0x09, 0xe2, 0x36, 0xee, 0x7e, 0x04, 0x74, 0xb0, 0xe0, 0xc8,
+ 0xa9, 0x0b, 0xb8, 0x2e, 0x3a, 0x5c, 0xbf, 0x4b, 0x41, 0x36, 0xad, 0xc8,
+ 0xec, 0xbe, 0x9b, 0x5c, 0x90, 0x1e, 0x6f, 0x4c, 0x18, 0xeb, 0x98, 0x77,
+ 0x9a, 0x4e, 0xfd, 0xfe, 0x26, 0xe3, 0x4b, 0x03, 0x16, 0xbf, 0xd1, 0x1b,
+ 0xa4, 0x2d, 0x17, 0x84, 0x61, 0x9e, 0x76, 0x83, 0x28, 0xed, 0x23, 0xc1,
+ 0xe7, 0x43, 0x19, 0xe3, 0x13, 0x3b, 0x9d, 0xc6, 0xb3, 0x2f, 0x58, 0x5a,
+ 0x91, 0x98, 0xca, 0x3c, 0xed, 0x34, 0x9c, 0x7a, 0x84, 0x6b, 0xa6, 0xf3,
+ 0xae, 0x0d, 0x5d, 0x3d, 0xeb, 0xd4, 0xe8, 0xea, 0x2b, 0xf6, 0xb7, 0xca,
+ 0x34, 0x49, 0x36, 0xdd, 0x84, 0xf9, 0x0e, 0x94, 0x22, 0x18, 0xbf, 0x0d,
+ 0xb8, 0x08, 0x0f, 0xe8, 0x76, 0xe6, 0x7f, 0xe2, 0x5a, 0x04, 0x2c, 0xf7,
+ 0x01, 0xee, 0x4b, 0x80, 0xf9, 0x45, 0x5c, 0x6a, 0x5b, 0x4c, 0xfe, 0xd4,
+ 0x89, 0xcd, 0xd4, 0xc3, 0x4b, 0x18, 0xbf, 0x6b, 0xe1, 0x7d, 0x2d, 0x58,
+ 0x3d, 0x59, 0xe8, 0xeb, 0x00, 0x3c, 0x84, 0xf3, 0x25, 0xc0, 0x48, 0xbb,
+ 0xf5, 0x39, 0x3c, 0x7b, 0x80, 0xef, 0x79, 0x0b, 0x13, 0xe8, 0x71, 0xea,
+ 0x2f, 0x6a, 0xbf, 0x4b, 0xb4, 0xa3, 0xff, 0xd2, 0x3e, 0xb7, 0xaf, 0x90,
+ 0x01, 0x5d, 0x0e, 0xf1, 0x3c, 0x51, 0x5e, 0xa4, 0x1d, 0x00, 0xbe, 0xff,
+ 0xae, 0xc4, 0xce, 0x26, 0xe5, 0x68, 0x89, 0x7b, 0x40, 0xa7, 0x81, 0x0f,
+ 0x7d, 0xc6, 0x05, 0x75, 0xae, 0xc2, 0x05, 0x65, 0x3f, 0xb3, 0x1b, 0x57,
+ 0x37, 0xae, 0xb7, 0xe2, 0x02, 0x39, 0xcc, 0x9c, 0xc2, 0xd5, 0x83, 0xbe,
+ 0x55, 0xa2, 0x49, 0x98, 0x9b, 0xf5, 0x0d, 0xb4, 0xd1, 0xb6, 0x65, 0x41,
+ 0x65, 0xfa, 0x80, 0xbf, 0x3e, 0xc0, 0x96, 0xc4, 0xc5, 0x7c, 0xe6, 0xef,
+ 0x3a, 0x72, 0xf6, 0x65, 0x5c, 0x60, 0xb0, 0xb3, 0x20, 0xcc, 0xb3, 0xfd,
+ 0xb8, 0xa0, 0xc4, 0xce, 0x66, 0x71, 0x0d, 0xe2, 0xfa, 0x2b, 0xc7, 0xf0,
+ 0x5c, 0x3b, 0xf0, 0x15, 0xf1, 0x08, 0x70, 0xbe, 0x8c, 0xe7, 0xbe, 0xec,
+ 0xbc, 0x71, 0x9e, 0xfb, 0xbe, 0x63, 0x78, 0xee, 0x15, 0xa7, 0xc6, 0x73,
+ 0x17, 0x1c, 0xf5, 0xf0, 0xd3, 0x4e, 0xec, 0x61, 0xfa, 0x12, 0x17, 0x1c,
+ 0xc3, 0xff, 0x31, 0x19, 0x38, 0x08, 0x5a, 0x7a, 0x78, 0x1e, 0x17, 0xe9,
+ 0xea, 0x19, 0x94, 0x3f, 0xbf, 0x62, 0xdc, 0xe7, 0xde, 0xc4, 0xb8, 0xaf,
+ 0xda, 0x71, 0x45, 0xd5, 0xc6, 0x7d, 0x11, 0x7d, 0xbf, 0x64, 0xc7, 0x7d,
+ 0xb1, 0x6e, 0x5c, 0xd0, 0xca, 0xc3, 0x8b, 0xb8, 0x48, 0x17, 0x2f, 0xa0,
+ 0x3c, 0x92, 0x09, 0x1f, 0xf4, 0xa4, 0xb9, 0x01, 0xbc, 0x1b, 0x87, 0x7e,
+ 0x6c, 0x58, 0xd2, 0x8d, 0xd9, 0x3a, 0xfd, 0xf0, 0x46, 0xf4, 0xe3, 0x78,
+ 0x99, 0x36, 0xe2, 0x7c, 0x9d, 0x5c, 0xa0, 0x6f, 0x14, 0xca, 0x49, 0xed,
+ 0x07, 0xd1, 0x27, 0xa2, 0x7f, 0xb4, 0xd2, 0xb6, 0xfa, 0xa8, 0xce, 0x45,
+ 0xfb, 0x95, 0x52, 0xbb, 0xdc, 0x59, 0xa2, 0x4d, 0x48, 0x7a, 0x09, 0xc3,
+ 0xb1, 0x3d, 0xb4, 0x4f, 0x0b, 0xe1, 0x15, 0x3e, 0xe9, 0xc4, 0xf7, 0x7e,
+ 0x79, 0xb5, 0xce, 0x98, 0x1c, 0x80, 0xef, 0x9e, 0x3b, 0xf1, 0x8b, 0xd0,
+ 0x19, 0x0d, 0x80, 0x9b, 0xf4, 0xb6, 0x4d, 0x0e, 0x4c, 0xaa, 0x89, 0x2d,
+ 0x90, 0x25, 0x37, 0x95, 0x1a, 0x61, 0xf7, 0x30, 0x4f, 0xab, 0x59, 0x3a,
+ 0xf7, 0xc4, 0x4d, 0x1e, 0xb9, 0x97, 0xc0, 0x6f, 0xcf, 0xe4, 0xb5, 0x27,
+ 0x92, 0x78, 0xff, 0x0f, 0x1e, 0xe5, 0x60, 0xc2, 0xbf, 0x4e, 0xe7, 0x08,
+ 0x75, 0xec, 0xa1, 0xdd, 0x72, 0x83, 0xd6, 0xe1, 0xee, 0x2a, 0x3b, 0x49,
+ 0x6d, 0xf3, 0xa4, 0x66, 0xa3, 0x8d, 0x96, 0xd2, 0x29, 0xc2, 0xf5, 0x90,
+ 0x70, 0xff, 0xeb, 0x1e, 0x29, 0x06, 0x1b, 0xe1, 0x17, 0x30, 0x76, 0x9e,
+ 0xee, 0xa6, 0x6d, 0x34, 0x33, 0xe5, 0xd9, 0x3c, 0xeb, 0x4d, 0xf2, 0xac,
+ 0x1e, 0xa7, 0x51, 0xc3, 0x68, 0xce, 0x5e, 0x70, 0x1f, 0x21, 0xae, 0xcf,
+ 0xfb, 0xcc, 0x54, 0x5a, 0xb4, 0xde, 0x99, 0xa9, 0x30, 0xaf, 0x1f, 0xfe,
+ 0x54, 0x85, 0x79, 0xfc, 0x81, 0x78, 0x6f, 0x87, 0x9f, 0x5b, 0xd9, 0x21,
+ 0xa3, 0x53, 0xeb, 0xa4, 0xd1, 0x57, 0x89, 0x2d, 0xd0, 0x1f, 0x6c, 0xd3,
+ 0xb1, 0x07, 0xfe, 0xe1, 0xf4, 0x4e, 0x79, 0x62, 0x9a, 0x7d, 0x6f, 0x93,
+ 0xd9, 0x39, 0x71, 0xbc, 0xb7, 0xaf, 0x47, 0x1d, 0xc8, 0xf5, 0x3d, 0x2c,
+ 0x4b, 0xe1, 0x2e, 0xca, 0x7b, 0xbb, 0x2b, 0x17, 0xfb, 0xf8, 0xcc, 0xb3,
+ 0x04, 0xe2, 0xb2, 0xbf, 0x8b, 0x7d, 0xed, 0x72, 0x6e, 0x0e, 0x34, 0x01,
+ 0xb9, 0x3f, 0x78, 0x8a, 0x30, 0x89, 0xec, 0x9d, 0x61, 0x2c, 0xbd, 0xd3,
+ 0x63, 0xdc, 0x94, 0xfb, 0x34, 0xb7, 0xf4, 0x71, 0x2c, 0xe8, 0x25, 0xe8,
+ 0xb8, 0x8e, 0x3d, 0x46, 0x16, 0x64, 0x67, 0x1a, 0x50, 0xce, 0x7e, 0xe1,
+ 0x3f, 0x1e, 0x64, 0x3f, 0x51, 0x5b, 0x85, 0x39, 0x35, 0x6a, 0x7a, 0x59,
+ 0x5c, 0xa1, 0x3f, 0xce, 0xff, 0x48, 0xf6, 0x37, 0xfb, 0xe8, 0xd6, 0x7b,
+ 0x21, 0xdc, 0x53, 0x36, 0xb6, 0x15, 0xd7, 0x44, 0xef, 0x29, 0xc0, 0xae,
+ 0xba, 0x4a, 0xdb, 0x17, 0xb3, 0x55, 0xae, 0x20, 0x63, 0x51, 0xd1, 0x1a,
+ 0x25, 0xe5, 0xd1, 0xf2, 0xd2, 0x3a, 0xed, 0x68, 0x58, 0xbe, 0x4e, 0xa4,
+ 0x95, 0x60, 0xc4, 0xda, 0x1e, 0x0b, 0x72, 0x0c, 0x76, 0x59, 0xb7, 0x5e,
+ 0xb3, 0x05, 0xd8, 0xb2, 0x76, 0xcd, 0xb4, 0x3d, 0x5b, 0x8c, 0xd6, 0x6c,
+ 0x18, 0x1a, 0xa7, 0x92, 0xd9, 0xcc, 0x35, 0xf3, 0x18, 0xef, 0x06, 0xde,
+ 0x0b, 0x58, 0xa7, 0x02, 0xd6, 0xa8, 0x50, 0xd9, 0x26, 0x33, 0x27, 0x55,
+ 0x7b, 0x83, 0x48, 0x6a, 0xd4, 0xdf, 0x26, 0xe3, 0x73, 0x8c, 0x25, 0xec,
+ 0x80, 0x0d, 0xb6, 0x13, 0x57, 0x3b, 0x9e, 0xd9, 0x2e, 0x21, 0xc5, 0x8a,
+ 0x42, 0xdb, 0xa6, 0x55, 0x76, 0xd6, 0x39, 0x8c, 0xcd, 0x33, 0x9d, 0x8f,
+ 0x01, 0x0f, 0x35, 0xde, 0x29, 0xd5, 0xc5, 0x9f, 0x38, 0x57, 0xad, 0x43,
+ 0x31, 0xdf, 0x84, 0x5e, 0x4f, 0x1d, 0x87, 0x2a, 0x37, 0xbe, 0x19, 0x7b,
+ 0x2a, 0x49, 0x7b, 0x2a, 0x3f, 0xe9, 0x99, 0xf3, 0x06, 0xc3, 0xf0, 0x9d,
+ 0xfc, 0xfc, 0x66, 0xd2, 0xfa, 0xc8, 0x34, 0xe1, 0x8a, 0x47, 0x70, 0x2d,
+ 0x5b, 0x33, 0x9e, 0x0f, 0x5b, 0x1d, 0xe7, 0x28, 0x2d, 0xe5, 0x43, 0x9a,
+ 0xd8, 0x3e, 0xe3, 0x28, 0xed, 0x6b, 0xc0, 0x74, 0xb7, 0xb6, 0x61, 0x45,
+ 0xdd, 0x26, 0x87, 0xcb, 0x3c, 0x5b, 0xc6, 0x78, 0xe2, 0x27, 0x19, 0x5f,
+ 0xea, 0x9e, 0x91, 0x63, 0x18, 0x9b, 0xb9, 0x3f, 0xca, 0xc6, 0x6f, 0x36,
+ 0xd8, 0x1c, 0x91, 0xfa, 0x18, 0x8e, 0xc9, 0x0d, 0x5a, 0x9e, 0x67, 0x9d,
+ 0x1e, 0x5e, 0xc4, 0x3a, 0xff, 0x9a, 0xde, 0x1b, 0x94, 0xc9, 0x18, 0xb4,
+ 0xdf, 0x68, 0x5f, 0xba, 0xdf, 0x9c, 0xab, 0x49, 0xc9, 0x50, 0xd9, 0xcc,
+ 0xff, 0x92, 0xce, 0x11, 0x32, 0xb9, 0x90, 0x26, 0x7f, 0xe8, 0x1e, 0xb9,
+ 0x04, 0x1d, 0x5e, 0x5b, 0xdb, 0x26, 0x19, 0x07, 0x2e, 0xf2, 0x7a, 0x5f,
+ 0x22, 0x25, 0xf9, 0xbe, 0x47, 0x37, 0xf3, 0xdc, 0x45, 0x1c, 0xeb, 0x53,
+ 0x9c, 0xe6, 0x59, 0x4c, 0xf6, 0x7b, 0xb9, 0xbe, 0x28, 0x66, 0x99, 0xd7,
+ 0x0f, 0x59, 0xf9, 0x63, 0x3d, 0xc9, 0x66, 0xfd, 0x7e, 0x9d, 0xcd, 0xdf,
+ 0x76, 0x44, 0x0e, 0x84, 0xf2, 0x87, 0xd0, 0x93, 0x67, 0xec, 0x9c, 0x52,
+ 0x3a, 0x66, 0x25, 0xe1, 0xc5, 0x20, 0x69, 0x63, 0x96, 0x9c, 0xcb, 0x41,
+ 0x4b, 0xdf, 0xc6, 0xfe, 0xa9, 0xd9, 0xd0, 0x66, 0xdf, 0xef, 0x09, 0x2d,
+ 0x0b, 0x7b, 0xad, 0xed, 0xac, 0xe3, 0x3c, 0x8f, 0x88, 0xce, 0x09, 0x88,
+ 0x7c, 0xa3, 0xae, 0x3a, 0xbf, 0xc0, 0xf8, 0x72, 0xc5, 0xa9, 0xb5, 0x64,
+ 0x54, 0xcd, 0x27, 0xa4, 0x2f, 0x37, 0xb6, 0x8b, 0xdf, 0x47, 0x88, 0x7c,
+ 0xb9, 0x5e, 0xeb, 0xcb, 0x6d, 0xd4, 0xbe, 0x9c, 0x89, 0x3d, 0x6c, 0x5c,
+ 0xf2, 0xe5, 0x8a, 0x53, 0x05, 0xd0, 0x4a, 0xf4, 0x3d, 0x07, 0x63, 0x0b,
+ 0x8d, 0x97, 0x78, 0x86, 0xa6, 0x51, 0xf2, 0xc3, 0x0a, 0x7e, 0x83, 0xf1,
+ 0xb1, 0x18, 0xab, 0x50, 0xea, 0xeb, 0xd6, 0xbf, 0x68, 0x97, 0x6c, 0xdb,
+ 0x3a, 0xcc, 0xfb, 0x6e, 0xbd, 0xe6, 0xb3, 0x25, 0xb3, 0xf7, 0x99, 0x3f,
+ 0xc8, 0x98, 0x10, 0xcf, 0x49, 0x69, 0xfe, 0x4a, 0x0d, 0xc4, 0xba, 0x8d,
+ 0x3d, 0xeb, 0x7b, 0xad, 0xd2, 0x7c, 0x1a, 0x38, 0x8f, 0xdb, 0x71, 0x53,
+ 0x80, 0xe9, 0x30, 0xd6, 0xe6, 0x3a, 0x2b, 0x93, 0x39, 0xf6, 0x47, 0x9b,
+ 0x18, 0x1b, 0x98, 0x2b, 0x45, 0x31, 0xc2, 0x98, 0x3d, 0xa3, 0xe9, 0xc7,
+ 0x1a, 0xfd, 0x75, 0x6b, 0xda, 0xaa, 0x8f, 0xbf, 0xae, 0x6e, 0x22, 0x2d,
+ 0xdd, 0xad, 0xf3, 0x5c, 0xd6, 0xf7, 0xa5, 0xf7, 0xeb, 0x9c, 0x7b, 0x1d,
+ 0x63, 0x2c, 0x08, 0x73, 0xd4, 0xbe, 0x29, 0x3f, 0xa1, 0x65, 0xfe, 0xe1,
+ 0x80, 0xfa, 0x6b, 0x8f, 0xfe, 0xdd, 0x98, 0x09, 0xc3, 0x8b, 0x7d, 0x13,
+ 0x8c, 0x29, 0x7a, 0xdf, 0x96, 0xce, 0xe4, 0x80, 0xb6, 0x9d, 0xb0, 0x46,
+ 0x07, 0x9b, 0x65, 0x9d, 0x3f, 0x62, 0x73, 0x66, 0x0a, 0x90, 0x9b, 0x69,
+ 0xd8, 0x4c, 0x3c, 0x7f, 0xdc, 0x65, 0xdf, 0x15, 0xc2, 0x66, 0xd0, 0xd1,
+ 0x07, 0xc5, 0xc8, 0x98, 0x7c, 0x4d, 0xc6, 0x30, 0xd7, 0x20, 0x4b, 0x42,
+ 0x76, 0x8f, 0x4b, 0x9a, 0xdf, 0x2a, 0xe1, 0xd8, 0x45, 0xd9, 0x0a, 0xbd,
+ 0xcc, 0x76, 0xb4, 0x55, 0xf9, 0xcc, 0x3d, 0x1c, 0xdf, 0x3b, 0x02, 0xdd,
+ 0x72, 0xc3, 0x6a, 0xdd, 0x92, 0xa4, 0x5f, 0x9f, 0x9f, 0xa4, 0x6f, 0xb8,
+ 0x1e, 0x6d, 0xb6, 0xc9, 0x87, 0xa6, 0x7e, 0xbe, 0x95, 0xbc, 0x35, 0x02,
+ 0xb9, 0xae, 0xee, 0x8f, 0xce, 0x16, 0xb1, 0x8c, 0xef, 0xd9, 0x6f, 0x93,
+ 0xa4, 0xde, 0xeb, 0xc9, 0x6f, 0x54, 0xd3, 0xa9, 0x45, 0xe8, 0xa6, 0x11,
+ 0xe7, 0x57, 0xb7, 0x9b, 0x98, 0xea, 0x07, 0x5a, 0xcd, 0x59, 0x84, 0x66,
+ 0xe0, 0x34, 0x8a, 0xb3, 0xd6, 0xd3, 0xec, 0xa2, 0x95, 0xc7, 0x61, 0xd8,
+ 0xdc, 0xa7, 0x65, 0xf0, 0x7e, 0xca, 0xe0, 0xc3, 0x41, 0x97, 0xa1, 0x7d,
+ 0xed, 0x33, 0x85, 0x58, 0x47, 0xe0, 0xa1, 0xcf, 0x65, 0xbe, 0x9f, 0xe5,
+ 0x4f, 0x3f, 0xbb, 0x60, 0xe5, 0x92, 0x72, 0x56, 0xf3, 0xa5, 0xba, 0x26,
+ 0xbe, 0x4c, 0xe6, 0x1e, 0x9d, 0xa2, 0x3e, 0x0e, 0xe6, 0xbf, 0x09, 0x39,
+ 0x95, 0xd7, 0x78, 0xd8, 0x26, 0xf7, 0x4d, 0x49, 0xf6, 0x12, 0x74, 0x55,
+ 0x71, 0x6e, 0x39, 0x6f, 0xae, 0xee, 0x8f, 0x73, 0x7d, 0xa4, 0xd5, 0xf8,
+ 0xb6, 0xcb, 0xe7, 0x3a, 0x8f, 0xb9, 0x66, 0xf5, 0x5c, 0xb9, 0x6f, 0x33,
+ 0x67, 0xe7, 0xba, 0x3e, 0x9a, 0x6b, 0xff, 0xf2, 0xb9, 0x46, 0xbe, 0x7d,
+ 0x24, 0x77, 0x53, 0x3a, 0xff, 0x5e, 0xe7, 0x7d, 0x4f, 0xad, 0x97, 0x81,
+ 0xc9, 0x8d, 0x56, 0x5e, 0x7a, 0xd0, 0x3d, 0xcc, 0x89, 0x9f, 0xbf, 0xd7,
+ 0x13, 0x8b, 0x33, 0x45, 0x3c, 0x50, 0xd6, 0xb6, 0xea, 0x33, 0x3b, 0x33,
+ 0xf0, 0xaf, 0x6e, 0x2d, 0xb1, 0x6e, 0xf4, 0xfe, 0x72, 0xb1, 0xe3, 0xc8,
+ 0xa7, 0xa6, 0xdf, 0xd4, 0xbd, 0x2a, 0xa6, 0x60, 0xe2, 0xc3, 0x8c, 0x0b,
+ 0x9b, 0xb3, 0xc4, 0xcc, 0x45, 0xbc, 0x03, 0x3c, 0xf5, 0xf1, 0x52, 0xba,
+ 0x3f, 0x17, 0xa3, 0x1c, 0x9d, 0x96, 0xa3, 0xd5, 0x41, 0xe9, 0xd0, 0xe7,
+ 0x49, 0x5f, 0x37, 0x76, 0x9c, 0xad, 0x8f, 0x1d, 0x33, 0x9d, 0x80, 0xb1,
+ 0xe3, 0xfd, 0x3f, 0x42, 0xec, 0x58, 0x1c, 0x13, 0x3b, 0x5e, 0xcb, 0xbf,
+ 0x9a, 0x28, 0x4f, 0x63, 0x5e, 0xcd, 0x90, 0x25, 0x0b, 0x4e, 0x7e, 0xae,
+ 0x05, 0xf7, 0x0b, 0xb8, 0xc7, 0x71, 0xbf, 0x84, 0xbb, 0x87, 0xfb, 0x8b,
+ 0xb8, 0x27, 0x64, 0x62, 0x49, 0x67, 0x4c, 0x43, 0x6e, 0x50, 0x97, 0xb1,
+ 0xad, 0xf1, 0x07, 0x66, 0x2b, 0x6d, 0xfc, 0x2e, 0x8c, 0x33, 0x33, 0xc7,
+ 0x39, 0x6c, 0x94, 0xf1, 0x29, 0xca, 0xec, 0x56, 0x99, 0x9c, 0x8a, 0x6c,
+ 0xdb, 0xbb, 0xb6, 0x71, 0xcf, 0x60, 0x44, 0x22, 0xdb, 0xf5, 0x77, 0xb7,
+ 0xd9, 0x5c, 0xfb, 0x2d, 0xd2, 0xbc, 0x09, 0x6b, 0x70, 0x5a, 0x2e, 0x4d,
+ 0x6f, 0x5a, 0x66, 0xc3, 0xa6, 0x6c, 0x4c, 0x70, 0xda, 0xea, 0xde, 0xb5,
+ 0x65, 0x44, 0xfd, 0xfa, 0x27, 0x6d, 0x4e, 0x69, 0x94, 0x23, 0x94, 0xd2,
+ 0xeb, 0x33, 0x5c, 0x9d, 0xc6, 0x78, 0xfd, 0x92, 0x9d, 0xe6, 0x3c, 0x97,
+ 0xbe, 0x4d, 0x01, 0x79, 0x78, 0x0a, 0x7a, 0x75, 0x19, 0x5d, 0x82, 0x6e,
+ 0x39, 0x37, 0x07, 0xb4, 0xfb, 0xa8, 0xcc, 0x4c, 0x12, 0xbe, 0xae, 0x64,
+ 0x4c, 0x9f, 0x5d, 0xc3, 0xf3, 0xb4, 0xc9, 0x99, 0x1f, 0xa8, 0x46, 0xe7,
+ 0xd6, 0x36, 0xeb, 0xef, 0x11, 0x2c, 0x3f, 0xbb, 0x66, 0xf5, 0xb3, 0xb6,
+ 0x1d, 0x78, 0x86, 0x2d, 0x9a, 0xc3, 0x5a, 0xf4, 0x14, 0xca, 0xb8, 0xce,
+ 0x3b, 0xdb, 0x22, 0x67, 0x1e, 0x5c, 0xca, 0xa1, 0x6d, 0x85, 0x8d, 0xd2,
+ 0x0e, 0x13, 0x79, 0xd8, 0xcd, 0x74, 0xc1, 0xc7, 0x63, 0x9e, 0x4c, 0x57,
+ 0xf2, 0x36, 0x9d, 0xdb, 0x5c, 0x3b, 0x47, 0x58, 0xcb, 0x6f, 0x8e, 0xce,
+ 0x6d, 0x25, 0x65, 0x10, 0x74, 0x38, 0xa4, 0xcb, 0x13, 0x98, 0x0f, 0xf7,
+ 0xfd, 0x34, 0x1e, 0x20, 0x7b, 0xb8, 0xe7, 0x87, 0xb9, 0x57, 0xbf, 0x01,
+ 0x7a, 0x77, 0xec, 0x19, 0x36, 0xd2, 0x58, 0x9f, 0x8c, 0x55, 0x92, 0xce,
+ 0x58, 0xa5, 0xcf, 0x39, 0x54, 0xb1, 0xef, 0xfa, 0x8a, 0x58, 0x0f, 0xfc,
+ 0x9e, 0xee, 0x70, 0x46, 0x80, 0xaf, 0x62, 0xb9, 0xd3, 0xc9, 0xea, 0xbb,
+ 0x6f, 0xef, 0x90, 0x03, 0x58, 0xab, 0x81, 0xe9, 0xa4, 0x96, 0xf3, 0xb5,
+ 0xef, 0x61, 0x45, 0xeb, 0xfa, 0xa4, 0xde, 0x1b, 0x9a, 0x97, 0x69, 0xfd,
+ 0x7d, 0x25, 0x63, 0x3b, 0x9c, 0x46, 0x7f, 0xd3, 0x36, 0x26, 0xde, 0xe3,
+ 0xe4, 0x75, 0x3f, 0x66, 0x3d, 0x8a, 0xe5, 0x53, 0xb8, 0xaf, 0x3c, 0x43,
+ 0x1d, 0xe9, 0x19, 0xc2, 0xfd, 0x08, 0xf4, 0x59, 0x78, 0x8f, 0x91, 0x57,
+ 0xd3, 0x32, 0x51, 0x65, 0xfe, 0x08, 0xfb, 0x41, 0x79, 0xe5, 0x30, 0x74,
+ 0xd2, 0xf2, 0x33, 0x84, 0x43, 0xb5, 0x75, 0x48, 0x4d, 0x0b, 0x61, 0xe1,
+ 0x1a, 0x2c, 0x3f, 0x5f, 0x7f, 0xf9, 0x7f, 0xd1, 0xbe, 0xa2, 0x91, 0xa1,
+ 0x16, 0x8e, 0x2c, 0xe5, 0x9d, 0x91, 0x2b, 0x9f, 0x96, 0x23, 0xc0, 0xe3,
+ 0x31, 0xc0, 0xa4, 0xee, 0xe7, 0xf7, 0x5e, 0x2a, 0x52, 0x9c, 0xbd, 0x4f,
+ 0xd4, 0x43, 0x97, 0x1c, 0xf7, 0xa1, 0x23, 0x12, 0x7b, 0x68, 0xc1, 0x69,
+ 0x78, 0xa8, 0x53, 0xfb, 0xe5, 0xfb, 0x82, 0xce, 0xe4, 0x21, 0x39, 0x2d,
+ 0xee, 0xfd, 0x4a, 0x9f, 0x27, 0x2b, 0x7a, 0x8c, 0xf1, 0x9d, 0x96, 0xd8,
+ 0xfd, 0x71, 0x7b, 0x16, 0xd5, 0xc4, 0xf5, 0x16, 0x35, 0xdf, 0x3f, 0x97,
+ 0x20, 0xce, 0x16, 0x65, 0x5a, 0xf3, 0xce, 0x00, 0xf4, 0x44, 0x6e, 0x32,
+ 0xb5, 0x54, 0xc7, 0xe4, 0x7b, 0x6e, 0x4c, 0x18, 0x7e, 0x61, 0x9d, 0x2e,
+ 0x87, 0xdf, 0x85, 0xb0, 0x3a, 0xff, 0xca, 0x28, 0xf7, 0xd3, 0xac, 0x29,
+ 0xdf, 0xff, 0x10, 0x6b, 0xd8, 0x85, 0xf5, 0xe2, 0x78, 0x8e, 0xde, 0xcf,
+ 0xe5, 0x59, 0x5c, 0x4f, 0x7a, 0x92, 0x4d, 0x4b, 0x76, 0x10, 0xeb, 0xde,
+ 0x27, 0x4d, 0x80, 0x5b, 0x3d, 0x54, 0x34, 0x76, 0x9d, 0x90, 0x4e, 0x05,
+ 0x92, 0x9b, 0x34, 0xdb, 0xd5, 0xbf, 0x4f, 0xaf, 0xe1, 0xbd, 0x96, 0x66,
+ 0xd6, 0x19, 0xfb, 0x11, 0xcf, 0x86, 0x2e, 0x8a, 0xb2, 0x77, 0xea, 0xbb,
+ 0xd0, 0xf3, 0xdc, 0x77, 0xd1, 0xf6, 0xe2, 0x1a, 0xb6, 0x20, 0x79, 0xe9,
+ 0x69, 0xeb, 0x57, 0x86, 0xe1, 0x54, 0x10, 0x00, 0x8f, 0x6b, 0xf9, 0x92,
+ 0x3b, 0x9c, 0xd9, 0xc9, 0x9d, 0xce, 0xcc, 0x64, 0x28, 0x63, 0x01, 0xbf,
+ 0x19, 0xc2, 0x1c, 0x00, 0xda, 0x5b, 0x2c, 0xeb, 0x84, 0x6e, 0xdd, 0x9d,
+ 0xe0, 0xf9, 0xa6, 0x9b, 0xfc, 0x17, 0xc4, 0xd4, 0x23, 0x8e, 0xe9, 0x23,
+ 0x77, 0x3e, 0x92, 0x17, 0x7e, 0x9f, 0xa3, 0x27, 0x99, 0xd0, 0xdf, 0x10,
+ 0xf9, 0x0c, 0xda, 0x61, 0x8c, 0x32, 0xc7, 0x7d, 0xc6, 0x99, 0x81, 0x3c,
+ 0x9b, 0x9d, 0xe2, 0x37, 0x01, 0x98, 0x4f, 0x1b, 0x6b, 0x57, 0x72, 0x95,
+ 0x37, 0x6e, 0xbf, 0x5b, 0x57, 0x80, 0x0b, 0x14, 0xd3, 0x65, 0x3d, 0xde,
+ 0xe8, 0xd2, 0xb7, 0xec, 0xa2, 0xb2, 0xe8, 0x9b, 0x76, 0x4a, 0xe7, 0x4e,
+ 0xc3, 0x97, 0x3d, 0x33, 0x22, 0xdf, 0x77, 0xe6, 0x4a, 0xaf, 0x38, 0x8f,
+ 0x96, 0xb2, 0xd7, 0x5c, 0x01, 0xfa, 0xb8, 0x18, 0xe4, 0x29, 0xbf, 0x60,
+ 0xf3, 0x4d, 0x49, 0xa1, 0x3a, 0x26, 0xd3, 0xdb, 0x3a, 0xbd, 0xfb, 0xf5,
+ 0xda, 0x9c, 0x01, 0xce, 0xbe, 0x81, 0xf5, 0x3b, 0x93, 0xa0, 0x7e, 0x1b,
+ 0x2d, 0x29, 0xf0, 0xb2, 0xfa, 0x69, 0x5c, 0xb0, 0x6d, 0x1b, 0xb5, 0x8d,
+ 0x72, 0x28, 0x60, 0xbd, 0x9d, 0xce, 0xc0, 0xe4, 0x0e, 0xac, 0xe3, 0x41,
+ 0xe8, 0x4f, 0x07, 0x76, 0x1a, 0x68, 0x1b, 0x65, 0xe3, 0xc0, 0xc1, 0x68,
+ 0x60, 0xe4, 0xf9, 0x80, 0x14, 0xb4, 0x8f, 0x67, 0xee, 0x59, 0x65, 0x62,
+ 0x66, 0x61, 0x38, 0x0b, 0xfb, 0x80, 0xdf, 0xc5, 0x9a, 0xa8, 0xce, 0xe1,
+ 0xfa, 0x71, 0xbb, 0xa7, 0x3d, 0x7f, 0x99, 0x3d, 0x6d, 0x4f, 0x4e, 0x57,
+ 0xf5, 0x39, 0x79, 0x9d, 0x5f, 0x95, 0x52, 0xeb, 0xda, 0xf4, 0x5a, 0xa9,
+ 0x2e, 0x9d, 0x93, 0x96, 0x95, 0x47, 0x12, 0x46, 0x0f, 0x13, 0xa6, 0x14,
+ 0xe0, 0xd9, 0x09, 0x5c, 0x10, 0x1e, 0xd3, 0x46, 0xd4, 0x3b, 0xb7, 0x52,
+ 0x1f, 0x2e, 0xca, 0xa7, 0x12, 0xd1, 0x19, 0x05, 0xf4, 0x03, 0x19, 0x37,
+ 0xb7, 0xd5, 0xe8, 0xc9, 0x2d, 0x6b, 0xf4, 0x13, 0xcd, 0xcd, 0xb1, 0x73,
+ 0x23, 0xdd, 0x6e, 0xbe, 0x92, 0x3e, 0xc5, 0xa2, 0x34, 0xad, 0xa8, 0xcf,
+ 0x98, 0xfe, 0xbe, 0xed, 0xe6, 0xcc, 0x03, 0xeb, 0x7a, 0xb0, 0x4d, 0x69,
+ 0xe7, 0x12, 0x8f, 0x7a, 0xdd, 0x4a, 0x4a, 0x78, 0x6e, 0xe1, 0x0c, 0x64,
+ 0xcb, 0x55, 0xde, 0x4f, 0x28, 0xd2, 0x61, 0x84, 0xeb, 0x6f, 0x68, 0x3e,
+ 0x19, 0x2d, 0x31, 0xb6, 0xf2, 0x68, 0x98, 0x1d, 0x26, 0x8f, 0xb1, 0x0f,
+ 0xbe, 0x9f, 0xd2, 0xf1, 0xdc, 0x83, 0x01, 0x63, 0x45, 0x9d, 0x8f, 0xdc,
+ 0xa1, 0x22, 0x39, 0x05, 0xfd, 0x5b, 0x5e, 0x70, 0xf8, 0xdd, 0xbe, 0x03,
+ 0x82, 0xfb, 0xdc, 0x82, 0xf3, 0xcd, 0xa9, 0x67, 0xf0, 0xdc, 0x60, 0xbf,
+ 0xd5, 0x67, 0xf4, 0x94, 0xc8, 0x1f, 0x46, 0xf3, 0x4d, 0x16, 0xb0, 0xf6,
+ 0x2f, 0x62, 0xed, 0xd7, 0xfe, 0x36, 0x1f, 0xde, 0x55, 0xf0, 0xae, 0xf2,
+ 0x0b, 0x61, 0xb6, 0x95, 0xb4, 0x18, 0xe8, 0xb3, 0xa9, 0x97, 0xf7, 0x9b,
+ 0xfb, 0x35, 0x5f, 0x8c, 0x97, 0xcf, 0x81, 0x2f, 0xb2, 0xdc, 0x6f, 0x0e,
+ 0x1f, 0x0e, 0x6e, 0x04, 0x5f, 0xec, 0x97, 0xdf, 0x83, 0x5d, 0xf0, 0x3b,
+ 0xd5, 0x0c, 0xf8, 0xa3, 0x1f, 0xfc, 0xd2, 0x07, 0x1e, 0x09, 0xb4, 0x8d,
+ 0xfc, 0x18, 0xf4, 0x1f, 0xf4, 0x9a, 0x73, 0x68, 0xb2, 0xc3, 0xc9, 0x4f,
+ 0xfa, 0xce, 0xd8, 0x24, 0xbf, 0xff, 0xa2, 0xde, 0xda, 0x20, 0x6e, 0x72,
+ 0x56, 0xc8, 0x0b, 0x9d, 0xcc, 0x71, 0x6c, 0x03, 0xae, 0xce, 0x12, 0x57,
+ 0xb3, 0xd5, 0x1e, 0xef, 0x0a, 0xf0, 0x44, 0x9b, 0xe6, 0x89, 0x8d, 0x4e,
+ 0xd6, 0xbb, 0xd1, 0xf2, 0xc4, 0x0b, 0xe0, 0x89, 0x4b, 0xab, 0x78, 0xe2,
+ 0x29, 0x4b, 0xff, 0xf3, 0x75, 0x3c, 0x31, 0x6b, 0xcb, 0xa6, 0x2f, 0xc3,
+ 0x13, 0x5b, 0xfd, 0xf4, 0xe7, 0x47, 0xe4, 0x55, 0xf0, 0x84, 0x28, 0xf2,
+ 0xc4, 0x56, 0xcd, 0x13, 0x8c, 0x1d, 0x91, 0x2f, 0xda, 0x21, 0x47, 0xc8,
+ 0x17, 0x17, 0x64, 0x11, 0x7c, 0xf1, 0x9c, 0xe2, 0xd8, 0x67, 0x68, 0x2b,
+ 0x4c, 0xd2, 0x27, 0x3b, 0x55, 0xee, 0x00, 0xbf, 0x2b, 0xf9, 0xaf, 0x53,
+ 0x61, 0xb8, 0x00, 0x3f, 0xfd, 0x41, 0xd8, 0xf3, 0xae, 0xfe, 0x0e, 0xe4,
+ 0x3c, 0xe8, 0x3e, 0xa2, 0xf7, 0x31, 0x07, 0xf4, 0x7e, 0x6c, 0x06, 0x73,
+ 0x18, 0x53, 0x9f, 0x82, 0x2f, 0xec, 0x61, 0x5d, 0x69, 0xe7, 0x9f, 0xd4,
+ 0x3c, 0xd4, 0x00, 0x7d, 0xf0, 0x68, 0x1f, 0x63, 0x4d, 0xbe, 0x77, 0x48,
+ 0x75, 0x16, 0x06, 0x01, 0x73, 0x4c, 0xdd, 0x2f, 0x8c, 0x73, 0xb4, 0xae,
+ 0xb0, 0xf3, 0x29, 0x23, 0x86, 0x21, 0xeb, 0xcc, 0xbb, 0x42, 0xd8, 0x04,
+ 0x9b, 0xb4, 0x49, 0x19, 0x1b, 0x5d, 0xed, 0x49, 0x7b, 0x3f, 0x07, 0x01,
+ 0xda, 0x08, 0x7b, 0x61, 0x2f, 0x56, 0x7b, 0xb0, 0x54, 0x6f, 0xe3, 0xff,
+ 0x67, 0xd8, 0xf8, 0x6c, 0x23, 0xae, 0xb1, 0xf1, 0x7f, 0xc5, 0xf2, 0x1a,
+ 0x7f, 0x7b, 0xda, 0xde, 0x3f, 0x0c, 0xf8, 0xf6, 0x2d, 0xd9, 0xfb, 0xec,
+ 0x83, 0x76, 0x87, 0xc8, 0x0d, 0xb0, 0xf9, 0xde, 0x09, 0x1e, 0xbc, 0x11,
+ 0xbe, 0xd4, 0xbb, 0x4a, 0x9e, 0xec, 0x2f, 0xb5, 0xc1, 0xe7, 0x6e, 0x97,
+ 0x77, 0x4f, 0xed, 0x94, 0xa1, 0xc9, 0x0f, 0x5e, 0x21, 0xcd, 0xdb, 0x60,
+ 0xa3, 0x4e, 0x01, 0xce, 0x98, 0x95, 0xdb, 0x3f, 0x04, 0xde, 0x3a, 0x53,
+ 0xdf, 0x57, 0x6d, 0xdb, 0x8d, 0x9c, 0xe7, 0xd9, 0xc9, 0xb5, 0xfa, 0x49,
+ 0xa0, 0x3d, 0x63, 0x29, 0xdb, 0xe4, 0xec, 0x49, 0x7a, 0x5f, 0x29, 0xd8,
+ 0xe5, 0x01, 0x6c, 0x92, 0x1d, 0xe8, 0x8f, 0xf1, 0xe4, 0x4d, 0xf2, 0xd4,
+ 0x35, 0xee, 0x27, 0xf2, 0x9a, 0x0f, 0xdb, 0x9d, 0xdc, 0xd4, 0x8d, 0x52,
+ 0x3c, 0x18, 0xc7, 0x1c, 0x54, 0xdb, 0x16, 0xb9, 0x5e, 0x86, 0xf4, 0x7c,
+ 0xce, 0xc8, 0x11, 0xe8, 0xe6, 0x3f, 0x28, 0x0d, 0xc9, 0xe2, 0x70, 0x2b,
+ 0x9e, 0xe3, 0xf2, 0x54, 0xa9, 0x07, 0xbe, 0xcf, 0x3b, 0x80, 0xa3, 0x46,
+ 0x3c, 0x37, 0xca, 0xc0, 0x15, 0xe4, 0xd5, 0x16, 0x59, 0x40, 0xf9, 0x3b,
+ 0xe5, 0xdf, 0xd9, 0x72, 0x96, 0x91, 0x37, 0x5a, 0xd0, 0x36, 0x2e, 0x17,
+ 0x4b, 0xb4, 0x2b, 0x35, 0x4f, 0xf4, 0x7f, 0x4b, 0x7a, 0xb2, 0xdf, 0x82,
+ 0x9d, 0x7a, 0x01, 0xd7, 0xd3, 0x92, 0xde, 0x3f, 0xea, 0xf4, 0xa4, 0x3a,
+ 0x1d, 0xe8, 0x4e, 0x5c, 0xae, 0xd3, 0xe3, 0x35, 0x3a, 0x57, 0xd9, 0x3e,
+ 0x1a, 0xe4, 0xe9, 0x83, 0x2a, 0xd9, 0x82, 0x35, 0xd9, 0xed, 0x74, 0xd9,
+ 0x32, 0x3e, 0xeb, 0x9c, 0x3c, 0xe9, 0x3c, 0xab, 0x76, 0x6c, 0x10, 0xe9,
+ 0x68, 0x81, 0xcd, 0x33, 0x26, 0xaa, 0xad, 0x45, 0x5c, 0xe9, 0x9c, 0x51,
+ 0xed, 0x28, 0xf3, 0x6d, 0x59, 0xa2, 0x05, 0xfa, 0x01, 0x65, 0xdb, 0x50,
+ 0xb6, 0xcb, 0x96, 0xb5, 0xb6, 0x48, 0x23, 0xca, 0xce, 0x68, 0x9e, 0xbf,
+ 0xd4, 0xe5, 0x7b, 0x79, 0xa7, 0x59, 0x3a, 0x4e, 0xb5, 0x40, 0x36, 0x6c,
+ 0x92, 0x85, 0x6b, 0x9a, 0xa4, 0x03, 0xef, 0x18, 0xe7, 0x0e, 0x4e, 0xc5,
+ 0xe5, 0xba, 0x53, 0x9d, 0xc9, 0x0f, 0x61, 0x0e, 0x9d, 0x67, 0x19, 0xf7,
+ 0x7e, 0xf2, 0x0a, 0xc6, 0x7d, 0x3a, 0xce, 0xf2, 0xde, 0xa4, 0xe5, 0x0f,
+ 0xf1, 0x61, 0xbe, 0x71, 0x44, 0x99, 0x7c, 0x1a, 0x7e, 0x2e, 0x75, 0x78,
+ 0xa7, 0xfd, 0x1e, 0xc7, 0x9f, 0x5e, 0x41, 0xbf, 0x6d, 0x86, 0xf6, 0x54,
+ 0x99, 0xfc, 0x48, 0x3d, 0x84, 0xfb, 0xb4, 0x23, 0xc5, 0x9a, 0xcc, 0x9a,
+ 0x23, 0x5f, 0x9d, 0x54, 0xcc, 0x65, 0x41, 0x59, 0xf5, 0x67, 0x42, 0xb3,
+ 0xc6, 0xe4, 0x05, 0x23, 0x97, 0xde, 0x67, 0xe4, 0xd2, 0x99, 0xf3, 0xcb,
+ 0xe4, 0xd2, 0x25, 0x2d, 0x97, 0x0e, 0x0a, 0xee, 0x73, 0x97, 0x20, 0x97,
+ 0x5e, 0xc0, 0xb3, 0xa7, 0xe5, 0x52, 0x42, 0xac, 0xbd, 0x2c, 0x3f, 0xd0,
+ 0xe3, 0xcf, 0x96, 0x5d, 0x6d, 0x57, 0x15, 0xa7, 0x61, 0x93, 0x94, 0x27,
+ 0xac, 0xfe, 0x96, 0x4c, 0xab, 0x74, 0xf5, 0xff, 0x50, 0x22, 0x9b, 0xf3,
+ 0xcf, 0xae, 0xe0, 0xf7, 0x46, 0x9f, 0x53, 0x94, 0x61, 0xaf, 0x42, 0x86,
+ 0x89, 0x5a, 0x5b, 0x86, 0xe1, 0x5d, 0x05, 0xef, 0x2a, 0xec, 0xf7, 0x6f,
+ 0x7f, 0x38, 0xe2, 0x51, 0x7e, 0x50, 0x66, 0x40, 0x26, 0x95, 0x21, 0x93,
+ 0xca, 0x90, 0x53, 0x65, 0xc8, 0x25, 0xd8, 0x6c, 0xe7, 0xcb, 0x90, 0x4b,
+ 0x65, 0xc8, 0x25, 0xc8, 0xb8, 0xc7, 0x20, 0xe3, 0x8c, 0x4c, 0x1b, 0x86,
+ 0x4c, 0x3b, 0x23, 0xf7, 0x59, 0x5d, 0x6f, 0x62, 0x25, 0xbd, 0xd6, 0x47,
+ 0xea, 0xd3, 0x31, 0xe4, 0xf3, 0x75, 0xb1, 0xc1, 0x03, 0xc7, 0x35, 0xbf,
+ 0x7b, 0xbe, 0xba, 0xca, 0x61, 0x0e, 0xcd, 0xf7, 0xb5, 0xff, 0xbe, 0x9b,
+ 0xbf, 0xa5, 0x09, 0x7c, 0xfd, 0x1d, 0xcb, 0xd7, 0xbb, 0x97, 0xf8, 0x3a,
+ 0xed, 0x30, 0x56, 0xbc, 0x36, 0x5f, 0x6f, 0xb3, 0xef, 0x0a, 0xe1, 0x3a,
+ 0xf0, 0xf5, 0xba, 0x15, 0x7c, 0x1d, 0x07, 0x5f, 0xef, 0x5f, 0xc5, 0xd7,
+ 0x1b, 0x9c, 0x01, 0xdd, 0x86, 0x67, 0x24, 0xf8, 0xdc, 0xe8, 0xd4, 0xf8,
+ 0xfa, 0x1e, 0xcd, 0xd7, 0x47, 0xc1, 0xd7, 0xd7, 0xd7, 0xf1, 0xf5, 0x7e,
+ 0x49, 0xdf, 0x9c, 0x8b, 0xed, 0x94, 0xd1, 0xfb, 0x55, 0xdb, 0x66, 0xf9,
+ 0x17, 0x31, 0xed, 0x0d, 0x8f, 0x0d, 0x4c, 0xb5, 0x49, 0xfe, 0xa1, 0x57,
+ 0x50, 0x46, 0x3e, 0x4b, 0x8f, 0x64, 0x1d, 0x4f, 0x8e, 0x1c, 0xff, 0xbe,
+ 0xcc, 0x6b, 0xde, 0x12, 0x19, 0x3b, 0x1e, 0x97, 0xf1, 0xe3, 0x8c, 0x43,
+ 0x7c, 0xcf, 0xd2, 0x7b, 0x93, 0x8c, 0x1f, 0x64, 0xde, 0x9c, 0x2b, 0xa3,
+ 0xc7, 0xe1, 0x6f, 0x1d, 0x67, 0x1c, 0xe2, 0xa5, 0x25, 0x1e, 0x9b, 0x87,
+ 0x6c, 0x19, 0x3d, 0xce, 0xb5, 0x8e, 0xa3, 0x9f, 0x16, 0x39, 0x7a, 0x5c,
+ 0xe4, 0xb6, 0xe3, 0xae, 0x7c, 0xe0, 0xf8, 0x12, 0xaf, 0x0d, 0x47, 0xbc,
+ 0xf6, 0x0c, 0x78, 0xad, 0xd3, 0xf2, 0x9a, 0x5a, 0xe2, 0xb5, 0xaf, 0xd6,
+ 0xf1, 0x1a, 0xdb, 0x93, 0xd7, 0x9e, 0xb5, 0x65, 0x7c, 0x76, 0xe5, 0xd0,
+ 0xf1, 0x76, 0x19, 0x7d, 0xe8, 0x2d, 0x32, 0x76, 0x3f, 0x61, 0x35, 0xdf,
+ 0x85, 0xa2, 0x2d, 0x36, 0x5d, 0xed, 0x44, 0xff, 0x51, 0x0e, 0x11, 0x71,
+ 0xed, 0x77, 0xcf, 0x48, 0xba, 0xc0, 0xf1, 0x1a, 0xe1, 0x47, 0x9f, 0x82,
+ 0x7f, 0x71, 0x08, 0x30, 0xdd, 0x72, 0x5c, 0xd2, 0xae, 0xbc, 0x2c, 0x13,
+ 0xc1, 0xe9, 0xed, 0xc6, 0x9e, 0x80, 0x2d, 0xa2, 0x6d, 0x9f, 0xac, 0xe4,
+ 0xdf, 0x1e, 0x6a, 0x1f, 0x63, 0xb2, 0x22, 0x8c, 0x05, 0x30, 0x6e, 0x6e,
+ 0xbf, 0x85, 0xca, 0xfc, 0xc7, 0x06, 0x7d, 0xe6, 0x45, 0xc7, 0x6c, 0xfb,
+ 0xf8, 0x9e, 0xcf, 0xb0, 0x67, 0xf4, 0xd9, 0x45, 0xb6, 0x67, 0x3f, 0x09,
+ 0x1d, 0x53, 0x2f, 0x56, 0xf8, 0x4d, 0x1c, 0xf8, 0x9f, 0x15, 0x7e, 0x5b,
+ 0xeb, 0x37, 0xdb, 0x4c, 0x7c, 0x96, 0x7c, 0xf7, 0x5d, 0x27, 0x5f, 0x9a,
+ 0xd3, 0xdf, 0x38, 0xc8, 0xf9, 0xf8, 0x5d, 0xe1, 0x33, 0xeb, 0xcf, 0x31,
+ 0xde, 0x91, 0x4a, 0xa9, 0x63, 0xdb, 0x99, 0x7b, 0x70, 0x70, 0x8e, 0x75,
+ 0x77, 0x5a, 0x1e, 0xdd, 0xa9, 0xfd, 0x0e, 0xda, 0x58, 0xa3, 0x93, 0x2f,
+ 0x48, 0x91, 0xb6, 0xc9, 0xf0, 0x4e, 0xa7, 0x30, 0xfd, 0x73, 0xdb, 0x8d,
+ 0xfd, 0x3c, 0xb0, 0x95, 0x79, 0x87, 0x59, 0xb5, 0x5a, 0x26, 0x9f, 0x92,
+ 0x48, 0x26, 0xa7, 0x6f, 0xce, 0xc2, 0xce, 0xce, 0x1f, 0xd7, 0xdf, 0xab,
+ 0x4a, 0x75, 0x2a, 0xce, 0xe9, 0x4e, 0xc8, 0xd7, 0x88, 0x16, 0x92, 0xf2,
+ 0xd1, 0xe3, 0xa4, 0x07, 0x95, 0xd8, 0x28, 0x1f, 0xb1, 0xf4, 0x70, 0x46,
+ 0x4a, 0x90, 0x3b, 0xc7, 0x8f, 0x7f, 0x40, 0xa6, 0x0f, 0xac, 0xa4, 0x87,
+ 0xb1, 0x1a, 0x3d, 0x24, 0x60, 0x9f, 0x39, 0xf5, 0xf4, 0xf0, 0xf3, 0x4b,
+ 0xf4, 0x30, 0xed, 0xfc, 0x6b, 0xe9, 0xe1, 0x86, 0x65, 0xf4, 0x30, 0xa1,
+ 0xe9, 0x61, 0x68, 0x89, 0x1e, 0x26, 0x8e, 0x73, 0x5c, 0xbd, 0x37, 0xea,
+ 0x2d, 0x38, 0x5c, 0xf3, 0x25, 0x5a, 0x48, 0x8d, 0xeb, 0x7c, 0xfd, 0x74,
+ 0x81, 0xe7, 0x9b, 0x36, 0x28, 0xc6, 0x49, 0x6a, 0xeb, 0xbf, 0xf1, 0xdf,
+ 0x74, 0xfd, 0xaf, 0xda, 0xfa, 0xff, 0x77, 0xfd, 0x33, 0x5b, 0x99, 0xbb,
+ 0xcf, 0x33, 0xb0, 0x46, 0x1e, 0x47, 0xf4, 0x90, 0xdb, 0x6a, 0xf4, 0x02,
+ 0xd7, 0x98, 0xcf, 0x90, 0x67, 0x90, 0x7f, 0xe7, 0x21, 0xff, 0x9e, 0x80,
+ 0xfc, 0x7b, 0x7c, 0xd9, 0x9e, 0x40, 0xbf, 0x8d, 0x47, 0x84, 0x72, 0x24,
+ 0xa8, 0xe1, 0x63, 0xa1, 0x8f, 0xf8, 0x30, 0xf9, 0x27, 0xcc, 0xfd, 0x5d,
+ 0x8e, 0x13, 0x57, 0xe7, 0x1c, 0x3d, 0x1a, 0xd4, 0xe3, 0x84, 0x70, 0xbf,
+ 0x5c, 0x37, 0x47, 0xfc, 0xae, 0xf0, 0xf9, 0x8c, 0xce, 0x23, 0x29, 0xea,
+ 0x3d, 0x28, 0xe2, 0x85, 0x7b, 0x50, 0xc4, 0x89, 0xab, 0xed, 0xfd, 0x62,
+ 0xa5, 0x49, 0xe7, 0xd0, 0x1f, 0x9e, 0x4b, 0xc8, 0x42, 0x82, 0x31, 0x3e,
+ 0x7e, 0xe7, 0x90, 0x7e, 0xb3, 0x9f, 0x2c, 0x4a, 0x81, 0xb9, 0x72, 0xe0,
+ 0xe9, 0x0d, 0x96, 0xb6, 0x19, 0x1b, 0xe4, 0x19, 0xe0, 0x68, 0x2f, 0xa2,
+ 0xdb, 0xca, 0xba, 0x96, 0xba, 0x98, 0x25, 0xf0, 0x3e, 0x25, 0xa9, 0x5c,
+ 0x1f, 0xee, 0x73, 0x1c, 0xfb, 0x13, 0x32, 0xf1, 0xe0, 0x87, 0x61, 0xcb,
+ 0xbd, 0x1f, 0x3a, 0x87, 0xe7, 0xcf, 0xb8, 0xf7, 0xe0, 0x69, 0x18, 0x66,
+ 0xf4, 0x77, 0xac, 0xe8, 0x03, 0x92, 0x1e, 0x92, 0x78, 0x3e, 0x63, 0xe3,
+ 0x4a, 0x49, 0x29, 0x96, 0x5e, 0x94, 0x7c, 0x85, 0xdf, 0x5c, 0x7b, 0x09,
+ 0xf7, 0xd7, 0x5b, 0x0f, 0xe3, 0x87, 0x0c, 0xeb, 0x3b, 0xd7, 0x66, 0x51,
+ 0xb2, 0x15, 0x93, 0xe3, 0x52, 0x8b, 0x9b, 0x9c, 0x91, 0x63, 0xda, 0x7e,
+ 0xce, 0xd8, 0xdc, 0x96, 0xf4, 0x70, 0x41, 0x8c, 0x0d, 0xfd, 0x39, 0xd8,
+ 0xd0, 0x9f, 0xad, 0x66, 0xf5, 0x3e, 0xd6, 0xe3, 0xb0, 0xa1, 0x1f, 0x83,
+ 0xee, 0xa1, 0xce, 0x49, 0x58, 0x9d, 0x33, 0xa1, 0x0e, 0x68, 0x9d, 0xf3,
+ 0xe7, 0x5a, 0xe7, 0xbc, 0x7b, 0x95, 0xce, 0x39, 0xaa, 0x3a, 0x27, 0xa9,
+ 0x73, 0x06, 0xd4, 0x7e, 0x87, 0xf6, 0xe2, 0x96, 0x35, 0x74, 0xce, 0x7b,
+ 0xe4, 0x1d, 0xf6, 0xdd, 0x3d, 0xf2, 0xde, 0x3d, 0x7a, 0xef, 0xc6, 0x9b,
+ 0x51, 0xfc, 0x76, 0x93, 0xd1, 0x41, 0xd7, 0xab, 0x6e, 0xbd, 0xe7, 0xfb,
+ 0x95, 0x3a, 0x9d, 0xd3, 0xa1, 0xfa, 0x9c, 0x01, 0xdd, 0x86, 0xb1, 0x09,
+ 0x3e, 0x07, 0x4e, 0x76, 0xb8, 0x09, 0xcf, 0x49, 0x89, 0x1d, 0xc7, 0xdc,
+ 0xcd, 0xf7, 0xa5, 0x94, 0x79, 0xf7, 0x56, 0xfb, 0x4e, 0x45, 0xe5, 0xae,
+ 0x29, 0xef, 0xb4, 0xe5, 0x46, 0x57, 0x75, 0xa8, 0x76, 0xad, 0xab, 0x76,
+ 0x83, 0xa1, 0x66, 0xa0, 0x5f, 0x67, 0xca, 0x91, 0xce, 0xe2, 0x6f, 0xc6,
+ 0x9e, 0x19, 0xa3, 0x88, 0x62, 0xd8, 0x29, 0xd4, 0xc1, 0x55, 0x8e, 0x6c,
+ 0x4a, 0xfe, 0x86, 0xaf, 0x80, 0x6b, 0x0e, 0x78, 0xbd, 0x19, 0xfc, 0xf3,
+ 0x1f, 0x4a, 0x8c, 0x81, 0xb6, 0xc9, 0x89, 0xa9, 0xfa, 0x77, 0xed, 0xf2,
+ 0xae, 0xa9, 0x1d, 0x72, 0xfb, 0xe4, 0xd6, 0xa4, 0x34, 0xef, 0x94, 0x89,
+ 0xc9, 0x29, 0x7d, 0xfe, 0x7d, 0xb3, 0xfe, 0x2e, 0x08, 0xbf, 0x97, 0x63,
+ 0x64, 0xe4, 0x90, 0x63, 0x64, 0x64, 0x56, 0xd5, 0x6c, 0xd6, 0xa8, 0x4f,
+ 0x7e, 0x8b, 0x64, 0x70, 0x32, 0xa9, 0xbf, 0xa5, 0x3a, 0x53, 0xbd, 0x4a,
+ 0x7e, 0xfb, 0xa4, 0xba, 0x4b, 0xd5, 0xce, 0xf7, 0x6a, 0x9b, 0x75, 0x76,
+ 0x99, 0xcd, 0xfa, 0xbf, 0x64, 0xe1, 0xbd, 0x71, 0xcc, 0x13, 0x34, 0x7c,
+ 0xf5, 0xb7, 0xb8, 0x17, 0xda, 0x96, 0x90, 0x17, 0x65, 0x50, 0xe3, 0x8f,
+ 0xf2, 0xb4, 0x05, 0x72, 0x70, 0x51, 0xeb, 0xd7, 0x2d, 0xa0, 0x41, 0xca,
+ 0xd2, 0x0f, 0xca, 0x0b, 0x5a, 0x9e, 0x6d, 0xb1, 0xb6, 0xeb, 0x3c, 0xbf,
+ 0x6d, 0x7d, 0x9c, 0xb6, 0xeb, 0x9f, 0xdb, 0x72, 0x96, 0xa5, 0x93, 0x8b,
+ 0x42, 0x7d, 0x97, 0x80, 0x0c, 0xa5, 0x3c, 0x7d, 0xa3, 0xb6, 0xeb, 0x97,
+ 0x6c, 0x1f, 0x94, 0x9f, 0x46, 0x76, 0xef, 0x76, 0xe6, 0x6d, 0x19, 0x9f,
+ 0xa3, 0x78, 0xba, 0x9f, 0xcd, 0x5b, 0x3e, 0x53, 0xce, 0xe7, 0xf1, 0x7e,
+ 0x33, 0xde, 0x93, 0xcf, 0x1e, 0xd7, 0x7c, 0xa6, 0xed, 0x13, 0xa7, 0xd7,
+ 0xee, 0x2f, 0x2c, 0xed, 0x0d, 0x14, 0xc8, 0x67, 0xea, 0x84, 0x37, 0x6f,
+ 0xe4, 0x01, 0xf3, 0x54, 0x7f, 0x03, 0xba, 0x83, 0x6d, 0x51, 0xfe, 0x70,
+ 0x96, 0xbe, 0x2d, 0xfc, 0x9f, 0x8d, 0x78, 0x6e, 0xc3, 0xf3, 0x8c, 0xbc,
+ 0xfb, 0x60, 0x5c, 0xcf, 0x7b, 0x02, 0xf3, 0x38, 0x7c, 0x1c, 0x73, 0x72,
+ 0x8c, 0xed, 0xec, 0x9e, 0x75, 0xa5, 0xe1, 0x2c, 0xf9, 0x8e, 0x67, 0x6d,
+ 0xc2, 0xf0, 0x50, 0x2f, 0xe9, 0x36, 0xed, 0x0d, 0xe9, 0xb3, 0xa5, 0xbb,
+ 0x93, 0x31, 0xe0, 0xe4, 0x30, 0xd6, 0x63, 0xa2, 0xe4, 0x7b, 0x39, 0xc7,
+ 0x4f, 0x62, 0x9e, 0xb0, 0x01, 0x3b, 0x61, 0x0b, 0x76, 0xc2, 0x0e, 0xec,
+ 0x84, 0x1d, 0xb8, 0x49, 0x4e, 0x5d, 0xc3, 0x1c, 0x93, 0xc2, 0x75, 0xf0,
+ 0xca, 0xe5, 0xaf, 0x75, 0x9c, 0xbe, 0xf1, 0xe6, 0x41, 0xf8, 0xec, 0xe2,
+ 0xa5, 0x87, 0x99, 0x87, 0xbf, 0xe8, 0x35, 0xde, 0x3c, 0x24, 0x9d, 0xfd,
+ 0x78, 0xdf, 0xff, 0xa2, 0x74, 0xdd, 0x7c, 0xab, 0xd3, 0x38, 0x3c, 0x08,
+ 0x3c, 0x66, 0x9d, 0x74, 0x72, 0xc4, 0x99, 0xc7, 0x38, 0xb9, 0xdd, 0x31,
+ 0x61, 0xdc, 0x72, 0x9e, 0xb1, 0x88, 0x9b, 0x3b, 0x63, 0x3d, 0xa9, 0x51,
+ 0x27, 0x3d, 0xac, 0x62, 0xe9, 0xe1, 0x41, 0x27, 0xaa, 0xc7, 0x6f, 0xae,
+ 0x42, 0xce, 0x00, 0xd6, 0xc3, 0xe5, 0x4f, 0x83, 0x9e, 0x8e, 0x48, 0xf1,
+ 0x64, 0x8b, 0xcc, 0x95, 0x3a, 0xbd, 0x9c, 0x4a, 0xe8, 0xdc, 0x12, 0x75,
+ 0x0a, 0x44, 0x7f, 0x36, 0x2e, 0x33, 0x93, 0x3b, 0x45, 0x69, 0xdb, 0x7d,
+ 0x9b, 0xe4, 0xa6, 0x26, 0xe5, 0x62, 0x9f, 0xb4, 0x2a, 0xf4, 0xcf, 0x6f,
+ 0xdc, 0xaa, 0x53, 0xdc, 0x4b, 0x8c, 0x78, 0x61, 0x3b, 0xf9, 0x64, 0x12,
+ 0x38, 0x04, 0xdd, 0x32, 0xc6, 0xdb, 0x24, 0x94, 0x7b, 0x1f, 0xd0, 0xf1,
+ 0x53, 0xc6, 0x6c, 0xeb, 0xf7, 0x1e, 0xc8, 0x1f, 0xf1, 0x35, 0xf9, 0x63,
+ 0xb6, 0xcc, 0x7d, 0x1a, 0x29, 0xb8, 0x8c, 0x11, 0xfb, 0xf8, 0x3d, 0xcd,
+ 0xba, 0x4d, 0x32, 0xd1, 0x57, 0xb0, 0x79, 0x1e, 0x7f, 0x9e, 0x64, 0x0e,
+ 0x31, 0x71, 0x32, 0xda, 0x47, 0x5e, 0x5f, 0xb9, 0xb7, 0x11, 0xaf, 0x93,
+ 0x07, 0x8e, 0x2c, 0x4c, 0x46, 0x7b, 0x21, 0xec, 0x0f, 0xcf, 0xd3, 0x46,
+ 0xde, 0xe6, 0x56, 0xb5, 0x23, 0x5c, 0xdc, 0xaf, 0x5c, 0x2e, 0x63, 0x95,
+ 0x4f, 0x99, 0xea, 0x69, 0xf9, 0x7a, 0xa6, 0x6a, 0x64, 0xeb, 0x74, 0x35,
+ 0xd2, 0x2d, 0x71, 0xa3, 0x4b, 0x57, 0xe9, 0x13, 0x13, 0xcd, 0xac, 0xe9,
+ 0x13, 0xea, 0x45, 0x25, 0xef, 0x9b, 0xdb, 0x26, 0xee, 0xc3, 0xb2, 0x38,
+ 0xe1, 0x7f, 0x7a, 0x3b, 0x73, 0x35, 0x26, 0x82, 0x37, 0xa3, 0x1f, 0x9b,
+ 0xae, 0xa4, 0x3e, 0x1c, 0x51, 0x8d, 0xb8, 0x6f, 0xd6, 0xf4, 0x07, 0x9e,
+ 0xc2, 0xb3, 0xf1, 0x13, 0x3e, 0x07, 0x3f, 0xe1, 0xb3, 0xd0, 0x75, 0xe7,
+ 0xe1, 0x27, 0x3c, 0x01, 0x3f, 0xe1, 0x71, 0xf8, 0x09, 0x8f, 0x41, 0x4f,
+ 0xd6, 0xfb, 0x07, 0xe3, 0xcb, 0xfc, 0x83, 0x50, 0xf3, 0x3f, 0xe3, 0x81,
+ 0x4f, 0xd4, 0xf9, 0x06, 0x87, 0x8c, 0xbe, 0x82, 0xdf, 0x6f, 0xf8, 0xa8,
+ 0x43, 0xdd, 0xa4, 0xf5, 0xa3, 0xc9, 0xdb, 0x1d, 0x5e, 0xd2, 0x57, 0x1d,
+ 0xca, 0xe8, 0xab, 0x99, 0x9a, 0xbe, 0x32, 0x7c, 0xf4, 0xf0, 0xa4, 0xc4,
+ 0xfc, 0xc9, 0xf9, 0x5c, 0xb0, 0x57, 0xf3, 0x50, 0xab, 0xbf, 0x53, 0x62,
+ 0x0f, 0xa8, 0xb6, 0x06, 0xc9, 0xd9, 0x67, 0xd0, 0xd7, 0x89, 0x4f, 0xa3,
+ 0xaf, 0xeb, 0x24, 0xaf, 0xed, 0xb3, 0xcb, 0xe3, 0xfb, 0xb1, 0x15, 0xf8,
+ 0x2e, 0x96, 0x27, 0x34, 0xce, 0xef, 0xaf, 0x70, 0x9f, 0xa5, 0x45, 0xc6,
+ 0x2b, 0x11, 0xce, 0x79, 0x9e, 0x95, 0xb9, 0x18, 0xed, 0x12, 0x7b, 0x78,
+ 0x1b, 0xcf, 0x59, 0xa9, 0x7c, 0xb0, 0x5e, 0xe7, 0xb0, 0x9c, 0xea, 0x93,
+ 0x64, 0xbe, 0x8f, 0xb4, 0x7a, 0x9f, 0xcc, 0xe8, 0xb5, 0xd8, 0x26, 0x0d,
+ 0x0f, 0xd3, 0x46, 0x89, 0xf6, 0xf3, 0xde, 0x7f, 0xa5, 0xfd, 0xe6, 0x6a,
+ 0xdc, 0xd4, 0x13, 0x39, 0xa2, 0xd7, 0x6b, 0x5a, 0xe7, 0x19, 0xde, 0x34,
+ 0xc7, 0xb8, 0x3c, 0xbf, 0x6f, 0xc5, 0x98, 0xfc, 0xbf, 0x66, 0xfd, 0x7e,
+ 0xf9, 0x4a, 0x63, 0xcf, 0x6c, 0xb6, 0x76, 0x8c, 0x89, 0x53, 0xad, 0x6d,
+ 0xc3, 0xb0, 0x9f, 0xfa, 0x6f, 0x32, 0xee, 0x70, 0xc6, 0x27, 0x77, 0x3a,
+ 0xc5, 0x49, 0xee, 0x65, 0xdb, 0xbf, 0xd1, 0xe1, 0xed, 0x77, 0x0e, 0xfb,
+ 0x3b, 0x50, 0xc6, 0x98, 0x25, 0x63, 0x36, 0xf7, 0x5f, 0xc9, 0x18, 0x6d,
+ 0xce, 0xe7, 0xd8, 0x2c, 0xdb, 0xe1, 0x4c, 0x4c, 0x76, 0xc2, 0x37, 0xe7,
+ 0xb9, 0x2a, 0xbe, 0x1f, 0xe2, 0xda, 0x41, 0x07, 0x7b, 0xfa, 0xcc, 0xee,
+ 0x98, 0x5c, 0x65, 0x63, 0xd0, 0xd4, 0xc3, 0x3f, 0xbd, 0x6c, 0xef, 0xf6,
+ 0x28, 0xf4, 0xd8, 0x2d, 0x90, 0x47, 0xd4, 0xc3, 0x47, 0xe5, 0x6d, 0x96,
+ 0x9e, 0x97, 0xeb, 0xe1, 0x4b, 0xc2, 0x38, 0x71, 0x2f, 0xde, 0x15, 0xc2,
+ 0x38, 0xe8, 0xe1, 0x58, 0x9d, 0xaf, 0x46, 0xbf, 0xaf, 0x29, 0x63, 0xf6,
+ 0xc3, 0x96, 0xfb, 0x7d, 0x90, 0x03, 0x89, 0xc8, 0xcf, 0x6b, 0x5c, 0xda,
+ 0xaf, 0xdd, 0x6f, 0xdb, 0x4e, 0x04, 0x7f, 0x44, 0x1c, 0xa5, 0x8e, 0xca,
+ 0x2f, 0x42, 0xa7, 0x31, 0x07, 0xe4, 0x2f, 0x34, 0xce, 0x44, 0x91, 0xf6,
+ 0x36, 0x6b, 0x18, 0xad, 0x9c, 0x4f, 0x45, 0x39, 0x1c, 0x45, 0xdb, 0x76,
+ 0xcc, 0xee, 0xc9, 0x17, 0xe5, 0xeb, 0x8c, 0x73, 0xa6, 0x06, 0x63, 0xeb,
+ 0xf9, 0x3d, 0x46, 0xb4, 0xfd, 0x45, 0xed, 0xb7, 0x67, 0x25, 0xea, 0x8b,
+ 0xcf, 0x0d, 0x75, 0x7d, 0xd3, 0x8e, 0xe2, 0x7d, 0xe5, 0x39, 0xb2, 0xa7,
+ 0xf5, 0x3e, 0xa3, 0xf9, 0x5e, 0x42, 0xc4, 0x27, 0xe4, 0x9d, 0x94, 0x3e,
+ 0xeb, 0xe4, 0x3f, 0x4c, 0xbb, 0x87, 0x7b, 0xb0, 0xde, 0xfc, 0x78, 0xf0,
+ 0x11, 0xfd, 0xcd, 0xc0, 0x69, 0x11, 0xa7, 0x18, 0xdc, 0xa6, 0x73, 0x4f,
+ 0x8a, 0x3a, 0xd6, 0x5c, 0xc0, 0xbd, 0xe6, 0xa3, 0x76, 0x3c, 0xcc, 0xbf,
+ 0xc3, 0xc1, 0xb2, 0x3c, 0x60, 0xa3, 0x0e, 0xa1, 0xec, 0x4d, 0x48, 0xc7,
+ 0x89, 0x5f, 0xd0, 0xbc, 0xb0, 0x05, 0xbe, 0xc0, 0xc0, 0x09, 0xe8, 0xea,
+ 0x13, 0x49, 0x19, 0x3a, 0xa1, 0x75, 0x63, 0x76, 0x75, 0xac, 0xa0, 0xc7,
+ 0x73, 0x9d, 0x77, 0xe9, 0x73, 0x6c, 0x6f, 0x3d, 0x11, 0x93, 0x63, 0x89,
+ 0x1e, 0xaf, 0xcb, 0x79, 0xb7, 0xd5, 0x85, 0x51, 0x0c, 0xbb, 0x05, 0xed,
+ 0x5f, 0x2f, 0x8e, 0x1d, 0xc5, 0xaf, 0x63, 0x32, 0x7d, 0xb0, 0x1d, 0xb0,
+ 0x75, 0x6e, 0x33, 0x67, 0x90, 0xb1, 0x56, 0xfa, 0x1b, 0xf7, 0x6e, 0x92,
+ 0xb2, 0xac, 0x03, 0xb0, 0x0c, 0x9e, 0xa0, 0x3e, 0xf3, 0x35, 0x8f, 0x03,
+ 0x06, 0xaf, 0x41, 0xfb, 0x21, 0xe4, 0xcb, 0xb7, 0x88, 0xff, 0x00, 0x64,
+ 0xdc, 0x89, 0xb8, 0x74, 0x9d, 0x68, 0x91, 0x5d, 0x27, 0xe8, 0x87, 0xd4,
+ 0xfb, 0xa5, 0xb4, 0x4b, 0xe7, 0x30, 0xc7, 0x77, 0x6a, 0x39, 0xc9, 0x3d,
+ 0xcd, 0xdb, 0xc9, 0xbb, 0xa8, 0x9b, 0x87, 0xcd, 0x9c, 0x3b, 0xe1, 0xe9,
+ 0x3d, 0xd2, 0x1c, 0xe6, 0x9c, 0xaf, 0x78, 0x18, 0xc7, 0xc8, 0x9c, 0x22,
+ 0xfd, 0x94, 0xe1, 0x6d, 0xc0, 0xf1, 0x31, 0xcb, 0x3b, 0x43, 0xdb, 0x2c,
+ 0x8f, 0xfe, 0x88, 0xbc, 0x77, 0xf3, 0x36, 0x23, 0x3b, 0x7f, 0x76, 0x1b,
+ 0x73, 0x93, 0xb6, 0xf8, 0xbc, 0x37, 0x69, 0x7b, 0xc2, 0xc8, 0xd0, 0xd7,
+ 0xe2, 0x45, 0x01, 0x8e, 0xa2, 0x7d, 0x29, 0x7d, 0x96, 0x2f, 0xbc, 0x18,
+ 0xe8, 0xf3, 0x2b, 0xc1, 0x02, 0xf3, 0x08, 0xf5, 0x77, 0x14, 0x6a, 0xdf,
+ 0x5b, 0xd9, 0x5b, 0x65, 0x9c, 0xfc, 0x89, 0xe8, 0x6f, 0xa9, 0xd4, 0xe5,
+ 0x1d, 0xd6, 0xef, 0x81, 0x31, 0xd6, 0xb4, 0x94, 0x1b, 0x14, 0x4e, 0xea,
+ 0xef, 0x21, 0x3d, 0xeb, 0x5c, 0x2a, 0x5d, 0x70, 0xbe, 0x39, 0x25, 0xa1,
+ 0xeb, 0x7f, 0xdf, 0xf9, 0xb6, 0xcf, 0x3d, 0xf3, 0x2f, 0x3b, 0xdf, 0x2a,
+ 0xf9, 0xe0, 0xc3, 0x0b, 0x98, 0xc7, 0x2b, 0xce, 0x77, 0xb0, 0xbe, 0x47,
+ 0xca, 0xd9, 0xb4, 0x67, 0x63, 0xe2, 0x17, 0x4a, 0xaf, 0x38, 0x5f, 0xaa,
+ 0xc5, 0x93, 0xfa, 0x23, 0x1a, 0x39, 0xca, 0x77, 0x15, 0xbc, 0xab, 0xe8,
+ 0xfd, 0x1f, 0x67, 0x76, 0xca, 0xe6, 0x97, 0x68, 0x3e, 0x9e, 0x5f, 0xda,
+ 0x97, 0x19, 0xd6, 0x7b, 0x15, 0xcf, 0x38, 0xb3, 0x73, 0x9f, 0xdb, 0x66,
+ 0xf2, 0x8c, 0x2e, 0xe0, 0x9d, 0xc9, 0xb9, 0x9c, 0x99, 0xbb, 0x80, 0x3a,
+ 0x4f, 0x3b, 0x33, 0x3a, 0xfe, 0xc5, 0x76, 0x17, 0x9c, 0xe9, 0xb9, 0xa7,
+ 0x9d, 0x39, 0xbd, 0x07, 0x7d, 0xd1, 0x79, 0x74, 0x8a, 0x7d, 0x5f, 0x44,
+ 0x9d, 0x79, 0xe7, 0x14, 0xfa, 0x9b, 0x9b, 0xe2, 0x79, 0xdc, 0x4e, 0xd8,
+ 0x05, 0xfc, 0x1b, 0x45, 0xfc, 0x1e, 0xc7, 0x33, 0xce, 0xdc, 0x52, 0xbf,
+ 0x0b, 0xe8, 0x87, 0x75, 0x49, 0x8b, 0x1c, 0xf7, 0x19, 0xf4, 0xbf, 0x7a,
+ 0xaf, 0x6a, 0x35, 0x4e, 0x9e, 0x07, 0x4e, 0x5e, 0xb4, 0x38, 0x79, 0xd5,
+ 0xe2, 0xe4, 0xb9, 0x3a, 0x9c, 0x88, 0x5a, 0x8e, 0x93, 0x57, 0x81, 0x13,
+ 0x51, 0x6b, 0xe3, 0x04, 0xef, 0x2a, 0x78, 0xa7, 0x71, 0xf2, 0xd2, 0x0a,
+ 0x9c, 0x2c, 0x2e, 0xc5, 0xe5, 0x0d, 0x4e, 0x5e, 0x00, 0x4e, 0x7e, 0x60,
+ 0x61, 0x7f, 0xd1, 0xe2, 0x04, 0xf7, 0xb9, 0x17, 0x51, 0xe7, 0xa5, 0x3a,
+ 0x9c, 0xbc, 0x08, 0x9c, 0xbc, 0x64, 0x71, 0xf2, 0x6d, 0x8b, 0x93, 0x6f,
+ 0xa3, 0xce, 0x22, 0x70, 0x72, 0x69, 0x0d, 0x9c, 0xbc, 0x00, 0x9c, 0x44,
+ 0xfd, 0x5e, 0x42, 0x3f, 0xdf, 0xae, 0xc3, 0xc9, 0x0b, 0x6b, 0xe0, 0x84,
+ 0x7b, 0xb1, 0x51, 0x4e, 0xf7, 0x99, 0xd7, 0xc9, 0xe9, 0x5e, 0x7c, 0x03,
+ 0x39, 0xdd, 0xac, 0x73, 0x46, 0x6a, 0x7f, 0xbb, 0x62, 0xc2, 0xe6, 0xa8,
+ 0x99, 0x5c, 0xc0, 0xda, 0x37, 0x9b, 0x3a, 0xc1, 0xe7, 0xc5, 0x02, 0xbc,
+ 0x11, 0x9d, 0x53, 0xea, 0xee, 0x19, 0x03, 0xaf, 0xbd, 0x5b, 0x0e, 0x9f,
+ 0x6c, 0x3c, 0x96, 0xb7, 0x65, 0xfe, 0x9e, 0xce, 0x82, 0x52, 0x7c, 0x17,
+ 0xe5, 0x24, 0xd0, 0x2f, 0x69, 0xe0, 0xb7, 0x0a, 0xbb, 0xb3, 0x52, 0xbf,
+ 0x27, 0x3d, 0xc5, 0x6f, 0x34, 0x71, 0x7f, 0x8c, 0x7f, 0x67, 0x23, 0xc5,
+ 0x3c, 0xab, 0xa2, 0x86, 0x37, 0x0d, 0xfd, 0xd1, 0xaf, 0x73, 0xab, 0xf8,
+ 0x37, 0x82, 0x62, 0xf0, 0xfb, 0x47, 0xfb, 0x68, 0x2b, 0x67, 0xec, 0x99,
+ 0xb0, 0x40, 0x9f, 0x53, 0xa9, 0xf1, 0x4f, 0xfd, 0x79, 0x68, 0xf2, 0x5d,
+ 0x8d, 0x6e, 0x8e, 0x2c, 0x7d, 0x77, 0xf0, 0xb4, 0x3c, 0xa5, 0x63, 0xc5,
+ 0xcd, 0xfa, 0xef, 0x2b, 0x9c, 0x09, 0x4c, 0x8c, 0x76, 0x41, 0xc7, 0x68,
+ 0x05, 0xde, 0xf8, 0xb8, 0x8d, 0xd3, 0x76, 0xf5, 0xbf, 0xb4, 0x14, 0xa3,
+ 0xad, 0xcf, 0x67, 0x31, 0xfb, 0xeb, 0xb9, 0xc9, 0x39, 0x9d, 0xa3, 0x33,
+ 0xc8, 0xef, 0x6f, 0x40, 0x46, 0x8c, 0x4d, 0x57, 0x64, 0xfc, 0x41, 0x3e,
+ 0x53, 0xbf, 0xc5, 0xa0, 0xc3, 0x28, 0xc3, 0x0b, 0x92, 0xeb, 0x67, 0x99,
+ 0x69, 0x33, 0xa8, 0xfd, 0xe5, 0xd3, 0x32, 0xb0, 0x34, 0x3e, 0xf1, 0xfb,
+ 0x89, 0xba, 0xef, 0x60, 0xd3, 0xe6, 0xc9, 0x3a, 0xb9, 0x2a, 0xdf, 0x47,
+ 0x7b, 0xe4, 0x9f, 0xb0, 0xdf, 0x0a, 0xe4, 0xfb, 0xfa, 0x6f, 0xbf, 0x6a,
+ 0xd1, 0x81, 0xdf, 0xfc, 0xbe, 0xda, 0x84, 0x33, 0x88, 0x36, 0xf3, 0x5e,
+ 0xcb, 0xb0, 0xca, 0xdc, 0x38, 0xcc, 0x73, 0x73, 0x33, 0xab, 0xbe, 0x9d,
+ 0x5d, 0xd3, 0x8b, 0x45, 0xbd, 0xa6, 0xcc, 0xcf, 0x2a, 0x80, 0x16, 0x35,
+ 0x6d, 0x69, 0xfa, 0x3f, 0xbc, 0xa4, 0x2f, 0xa9, 0x67, 0xcd, 0xb7, 0x67,
+ 0x8c, 0xbe, 0x4c, 0x27, 0x07, 0x31, 0xbe, 0xfe, 0x1b, 0x0d, 0xf6, 0x5c,
+ 0x6f, 0x7e, 0xee, 0x2e, 0xad, 0xeb, 0x27, 0x82, 0x6c, 0xca, 0x95, 0x35,
+ 0xea, 0x4e, 0xd6, 0xd5, 0xd5, 0xf3, 0xf6, 0xe4, 0xb7, 0xb0, 0x36, 0xbf,
+ 0x51, 0xae, 0xc8, 0xc0, 0xd4, 0x5f, 0xc1, 0x7f, 0x4c, 0xca, 0x6f, 0x96,
+ 0x1f, 0x01, 0xbd, 0x16, 0xb6, 0xd8, 0x6f, 0x35, 0xe5, 0x00, 0x37, 0xbf,
+ 0xbd, 0xa2, 0xf3, 0x89, 0x63, 0xbf, 0x0d, 0xba, 0xf8, 0xcc, 0x23, 0x1c,
+ 0x03, 0xb0, 0xc4, 0x60, 0xdb, 0xc3, 0x4e, 0x98, 0x7e, 0x44, 0xe7, 0xce,
+ 0x5d, 0x5f, 0x79, 0x44, 0xc7, 0x2c, 0x86, 0x2a, 0xed, 0xb2, 0xb7, 0xd2,
+ 0x22, 0xfb, 0xa0, 0x17, 0xf6, 0x55, 0x7c, 0x5c, 0x71, 0x79, 0x67, 0xc5,
+ 0xac, 0xd3, 0x07, 0x2b, 0x5c, 0xef, 0x3d, 0x32, 0x73, 0x72, 0xe5, 0xf7,
+ 0x3e, 0xe7, 0x0b, 0xd1, 0xdf, 0x73, 0x52, 0x8a, 0xf9, 0x65, 0xa4, 0x25,
+ 0x5c, 0xe5, 0xf4, 0xb1, 0x79, 0x8d, 0x07, 0x66, 0xb8, 0xa6, 0x27, 0x17,
+ 0x85, 0x79, 0xfa, 0xfc, 0x1b, 0x4e, 0x7f, 0xb9, 0x9d, 0xe7, 0xa6, 0xf9,
+ 0x2d, 0xaf, 0xa1, 0x6a, 0x94, 0x37, 0xbe, 0x56, 0xce, 0x38, 0xec, 0xfc,
+ 0x3d, 0x51, 0x8e, 0x5f, 0x9c, 0x39, 0xe3, 0xd2, 0x71, 0xb6, 0x05, 0xf7,
+ 0xef, 0x6e, 0xd7, 0x67, 0x9b, 0xcf, 0x8a, 0x2d, 0xd3, 0xf9, 0xe4, 0x78,
+ 0x5e, 0xf9, 0xbd, 0xb6, 0x88, 0x1f, 0x6a, 0x7f, 0xf7, 0x40, 0xe4, 0xff,
+ 0x02, 0x06, 0x86, 0xe5, 0x0a, 0xd4, 0x6f, 0x00, 0x00, 0x00 };
static const u32 bnx2_CP_b09FwData[(0x0/4) + 1] = { 0x0 };
static const u32 bnx2_CP_b09FwRodata[(0x118/4) + 1] = {
- 0x0800061c, 0x0800083c, 0x08000780, 0x080007a8, 0x080007d0, 0x080007f8,
- 0x08000654, 0x08000640, 0x08000864, 0x08000864, 0x08000670, 0x0800068c,
- 0x0800068c, 0x08000864, 0x080006a4, 0x080006b8, 0x08000864, 0x080006cc,
- 0x08000864, 0x08000864, 0x080006e0, 0x08000864, 0x08000864, 0x08000864,
- 0x08000864, 0x08000864, 0x08000864, 0x08000864, 0x08000864, 0x08000864,
- 0x08000864, 0x080006f4, 0x08000864, 0x08000708, 0x0800071c, 0x08000730,
- 0x08000864, 0x08000744, 0x08000758, 0x0800076c, 0x08003200, 0x08003218,
- 0x08003228, 0x08003238, 0x08003250, 0x08003268, 0x08003278, 0x08003288,
- 0x080032a8, 0x080032b8, 0x080032c8, 0x08003358, 0x08003298, 0x080032d8,
- 0x080032e8, 0x08003300, 0x08003320, 0x08003358, 0x08003338, 0x08003338,
- 0x080050d4, 0x080050d4, 0x080050d4, 0x080050d4, 0x080050d4, 0x080050fc,
- 0x080050fc, 0x08005124, 0x08005174, 0x08005144, 0x00000000 };
+ 0x0800069c, 0x080008bc, 0x08000800, 0x08000828, 0x08000850, 0x08000878,
+ 0x080006d4, 0x080006c0, 0x080008e4, 0x080008e4, 0x080006f0, 0x0800070c,
+ 0x0800070c, 0x080008e4, 0x08000724, 0x08000738, 0x080008e4, 0x0800074c,
+ 0x080008e4, 0x080008e4, 0x08000760, 0x080008e4, 0x080008e4, 0x080008e4,
+ 0x080008e4, 0x080008e4, 0x080008e4, 0x080008e4, 0x080008e4, 0x080008e4,
+ 0x080008e4, 0x08000774, 0x080008e4, 0x08000788, 0x0800079c, 0x080007b0,
+ 0x080008e4, 0x080007c4, 0x080007d8, 0x080007ec, 0x080032e8, 0x08003300,
+ 0x08003310, 0x08003320, 0x08003338, 0x08003350, 0x08003360, 0x08003370,
+ 0x08003390, 0x080033a0, 0x080033b0, 0x08003440, 0x08003380, 0x080033c0,
+ 0x080033d0, 0x080033e8, 0x08003408, 0x08003440, 0x08003420, 0x08003420,
+ 0x080051bc, 0x080051bc, 0x080051bc, 0x080051bc, 0x080051bc, 0x080051e4,
+ 0x080051e4, 0x0800520c, 0x0800525c, 0x0800522c, 0x00000000 };
static struct fw_info bnx2_cp_fw_09 = {
+ /* Firmware version: 3.7.1 */
.ver_major = 0x3,
- .ver_minor = 0x4,
- .ver_fix = 0x3,
+ .ver_minor = 0x7,
+ .ver_fix = 0x1,
.start_addr = 0x0800006c,
.text_addr = 0x08000000,
- .text_len = 0x6ee8,
+ .text_len = 0x6fd0,
.text_index = 0x0,
.gz_text = bnx2_CP_b09FwText,
.gz_text_len = sizeof(bnx2_CP_b09FwText),
- .data_addr = 0x08007020,
+ .data_addr = 0x08007100,
.data_len = 0x0,
.data_index = 0x0,
.data = bnx2_CP_b09FwData,
- .sbss_addr = 0x08007024,
- .sbss_len = 0xa1,
+ .sbss_addr = 0x08007104,
+ .sbss_len = 0xa9,
.sbss_index = 0x0,
- .bss_addr = 0x080070d0,
+ .bss_addr = 0x080071b0,
.bss_len = 0x3b0,
.bss_index = 0x0,
- .rodata_addr = 0x08006ee8,
+ .rodata_addr = 0x08006fd0,
.rodata_len = 0x118,
.rodata_index = 0x0,
.rodata = bnx2_CP_b09FwRodata,
};
static u8 bnx2_RXP_b09FwText[] = {
-/* 0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, */
- 0xec, 0x5c,
- 0x5d, 0x6c, 0x1c, 0xd7, 0x75, 0x3e, 0xf3, 0x43, 0x6a, 0x49, 0xf1, 0x67,
- 0xb8, 0x5c, 0xb1, 0x2b, 0x99, 0x96, 0x77, 0xc9, 0x91, 0xc8, 0x58, 0x8a,
- 0x31, 0xa2, 0x09, 0x5b, 0x48, 0x17, 0xf6, 0x76, 0x76, 0x25, 0xb1, 0xb1,
- 0x03, 0x53, 0xb6, 0x62, 0x07, 0x45, 0x6a, 0xb0, 0x4b, 0xb9, 0x0e, 0x8c,
- 0x06, 0x90, 0xff, 0x52, 0xbf, 0xb0, 0xde, 0x2c, 0xa9, 0x58, 0x4d, 0x17,
- 0x9c, 0xb5, 0x4d, 0x9b, 0x0e, 0x60, 0xb7, 0x0b, 0x92, 0x12, 0xf5, 0xb0,
- 0xd0, 0xb2, 0xa9, 0xdb, 0xea, 0xc1, 0x8e, 0x09, 0x56, 0xb1, 0x53, 0xa0,
- 0x2d, 0x5c, 0x27, 0x69, 0xfc, 0x10, 0x14, 0xaa, 0xec, 0xc4, 0x42, 0xd1,
- 0xa2, 0x02, 0x12, 0xd8, 0x29, 0x22, 0x7b, 0xfa, 0x7d, 0x77, 0x66, 0xc8,
- 0x25, 0x2d, 0xdb, 0x41, 0x1f, 0xfa, 0xd2, 0xbd, 0xc0, 0x62, 0xee, 0xbd,
- 0x73, 0xee, 0xb9, 0xe7, 0x9e, 0xff, 0x73, 0x87, 0xd2, 0x1f, 0x74, 0x48,
- 0xbb, 0x84, 0xad, 0x13, 0xbf, 0xd4, 0x89, 0x27, 0x1e, 0xb9, 0x69, 0xf4,
- 0xa6, 0x9b, 0xd1, 0xbd, 0xd9, 0x30, 0x4c, 0x23, 0x9a, 0x6f, 0xb6, 0x66,
- 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66,
- 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66,
- 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66,
- 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66,
- 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66,
- 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0xfb, 0xff, 0xde,
- 0x0c, 0x11, 0x8b, 0xcf, 0xce, 0xf0, 0x27, 0x31, 0x3d, 0x23, 0x0f, 0xb9,
- 0xb6, 0xc4, 0x8c, 0xcc, 0xd5, 0xa9, 0x49, 0x5b, 0x24, 0x5b, 0xdb, 0x97,
- 0xca, 0xc9, 0x87, 0x7e, 0x31, 0x61, 0x0a, 0xe7, 0xaf, 0xcf, 0x5c, 0xfd,
- 0x8b, 0x57, 0x6f, 0x4d, 0x5f, 0xa9, 0x1a, 0x12, 0xb3, 0x32, 0x33, 0x07,
- 0xac, 0xbd, 0x12, 0xeb, 0xc7, 0x9a, 0x17, 0x87, 0xfe, 0xa9, 0x4b, 0xba,
- 0x22, 0x5c, 0x22, 0x0b, 0xe5, 0xb4, 0x73, 0x18, 0xcf, 0x33, 0xb5, 0x7d,
- 0xce, 0x9a, 0x98, 0xb2, 0x6a, 0x05, 0x3b, 0x96, 0xca, 0x1a, 0xf1, 0x48,
- 0xa9, 0x16, 0x93, 0x8b, 0xea, 0xdf, 0x79, 0x60, 0x4f, 0x9b, 0xfd, 0xf3,
- 0x9a, 0x5b, 0xf7, 0xfd, 0xd3, 0x8e, 0xef, 0xbf, 0x8e, 0xdf, 0x7b, 0x0e,
- 0xc6, 0xde, 0x47, 0x7e, 0xd6, 0x34, 0x44, 0xb7, 0xff, 0x4c, 0x73, 0x17,
- 0x5b, 0xa5, 0x34, 0x2f, 0x32, 0xed, 0xc5, 0xe4, 0x94, 0x57, 0xd4, 0xf2,
- 0xf5, 0xb2, 0x76, 0x68, 0x79, 0x56, 0x3b, 0xbc, 0x7c, 0x4a, 0x3b, 0xb2,
- 0x5c, 0xd1, 0xdc, 0x65, 0x29, 0xea, 0x07, 0x3a, 0x24, 0x6b, 0x9d, 0xd5,
- 0x72, 0xf5, 0x3e, 0xcd, 0x9d, 0xbf, 0xea, 0xbb, 0x4e, 0xda, 0xfa, 0x3d,
- 0x31, 0xb3, 0xdc, 0xcf, 0x2d, 0xfb, 0x18, 0x9b, 0x92, 0x4d, 0xf8, 0xbe,
- 0x9e, 0xf1, 0x9f, 0x74, 0x47, 0x6d, 0x4b, 0xd7, 0x62, 0x52, 0xaa, 0xb7,
- 0x03, 0x6f, 0x87, 0x96, 0x9b, 0x37, 0xb5, 0xbc, 0xe7, 0xbf, 0xe6, 0x3a,
- 0xd2, 0x6f, 0x88, 0xef, 0xcf, 0x38, 0x7b, 0x92, 0xc7, 0xe5, 0x0c, 0xf0,
- 0xd6, 0x80, 0x4f, 0x2c, 0x3d, 0x43, 0xfa, 0x22, 0x9a, 0x8b, 0x5a, 0x6e,
- 0x28, 0xa2, 0x4f, 0x52, 0xa4, 0xbf, 0xb0, 0xa4, 0x83, 0xce, 0xed, 0x52,
- 0xa8, 0x5a, 0x32, 0xb1, 0xb4, 0x15, 0xfe, 0xa2, 0xff, 0xea, 0x50, 0x42,
- 0xfe, 0xb2, 0x9e, 0x3e, 0x55, 0x04, 0x2f, 0x66, 0xbc, 0x94, 0x80, 0xcf,
- 0x59, 0x77, 0xb4, 0x5f, 0x5e, 0xab, 0x27, 0xe5, 0xbb, 0x75, 0x3b, 0x59,
- 0x92, 0x6d, 0x52, 0x48, 0x58, 0xb2, 0x82, 0x35, 0xd3, 0xa0, 0x43, 0xb7,
- 0x6d, 0xab, 0x04, 0xd8, 0x52, 0xfd, 0x27, 0xfc, 0xb7, 0x32, 0xd6, 0xe4,
- 0xa8, 0x5a, 0x53, 0x04, 0xdd, 0x21, 0x2c, 0xcf, 0xa1, 0x60, 0xd5, 0x59,
- 0x02, 0x58, 0x29, 0x4e, 0x8e, 0x62, 0xae, 0xfe, 0x85, 0x50, 0x16, 0xad,
- 0x38, 0x2f, 0x9f, 0xbb, 0x71, 0xbe, 0xdd, 0xe0, 0x89, 0x24, 0x74, 0xd9,
- 0x93, 0x2c, 0x60, 0x66, 0xba, 0xde, 0x81, 0x31, 0x69, 0xf1, 0xfd, 0x23,
- 0x8e, 0x58, 0x25, 0xa7, 0x1b, 0xbc, 0x4b, 0x49, 0xc9, 0xe9, 0xc2, 0x9a,
- 0x16, 0xb1, 0x6c, 0x9e, 0x81, 0x78, 0xdb, 0x30, 0xef, 0x77, 0x1a, 0x19,
- 0xdf, 0x9f, 0x1c, 0x95, 0xae, 0x60, 0x6e, 0x1f, 0x70, 0x98, 0x32, 0x31,
- 0xae, 0x01, 0xee, 0x03, 0xd2, 0x17, 0x8b, 0x67, 0xd8, 0xe7, 0x73, 0x54,
- 0xdc, 0xd9, 0x54, 0xb8, 0x6f, 0x87, 0x94, 0xbc, 0xeb, 0xc3, 0x3e, 0x78,
- 0xed, 0xe1, 0xcc, 0xce, 0x4e, 0x8c, 0xb5, 0x1b, 0x80, 0xc7, 0x29, 0x09,
- 0xf7, 0xd8, 0x21, 0x6b, 0x09, 0xd1, 0x2f, 0x39, 0xbd, 0x21, 0x5c, 0x17,
- 0x68, 0x8d, 0x64, 0xde, 0x2e, 0x33, 0xf3, 0xad, 0x72, 0x72, 0x9e, 0xbc,
- 0x2d, 0x43, 0x16, 0x78, 0xde, 0x52, 0xd4, 0xb2, 0xf5, 0x53, 0xe8, 0x9b,
- 0x32, 0x69, 0xfb, 0xaf, 0xcd, 0x38, 0xb3, 0x5a, 0x6e, 0xf9, 0x8c, 0x96,
- 0x87, 0x0e, 0x1c, 0x5a, 0x3e, 0xaf, 0x1d, 0xae, 0xaf, 0x76, 0x4a, 0x7b,
- 0x1a, 0xda, 0x66, 0xca, 0x49, 0x4f, 0x13, 0xd2, 0xbb, 0x00, 0x7e, 0x65,
- 0x2d, 0x70, 0xde, 0xee, 0xd2, 0x0e, 0x03, 0x57, 0x8b, 0xfd, 0xad, 0x0e,
- 0xe9, 0x32, 0x64, 0x9b, 0x1d, 0xc1, 0xc6, 0xe4, 0x5b, 0xa0, 0x6d, 0xcd,
- 0x49, 0x00, 0x4e, 0xba, 0x83, 0x35, 0x3d, 0x21, 0x3d, 0xd4, 0x25, 0xea,
- 0x91, 0x9e, 0xcd, 0xcf, 0xfd, 0x69, 0x6f, 0x69, 0xff, 0x76, 0xc2, 0xc0,
- 0x3e, 0x52, 0x0f, 0x4d, 0xda, 0x6e, 0x8f, 0x29, 0x45, 0x4b, 0x97, 0xb4,
- 0x95, 0x93, 0x1b, 0x64, 0xc6, 0x11, 0xc9, 0x41, 0xbf, 0x75, 0xdb, 0x04,
- 0x8f, 0x6c, 0xf0, 0x68, 0xcf, 0xa9, 0x41, 0xfd, 0x0e, 0x49, 0xf5, 0x15,
- 0x35, 0x33, 0xe4, 0xe7, 0x82, 0xdc, 0xa6, 0xd6, 0xeb, 0x19, 0x07, 0x3a,
- 0xd9, 0xce, 0x3e, 0xf6, 0x8d, 0xa9, 0x7d, 0x8d, 0x8c, 0x9d, 0x5c, 0x14,
- 0xd1, 0xf4, 0xcc, 0x3e, 0xe0, 0xa3, 0xae, 0x12, 0xee, 0x29, 0xd0, 0x48,
- 0xda, 0xd9, 0xb7, 0xb1, 0x26, 0x26, 0xae, 0xd3, 0xd9, 0x40, 0x27, 0xe8,
- 0x49, 0x90, 0xe7, 0xe4, 0xa1, 0x3a, 0xa7, 0xb6, 0x71, 0xce, 0x5f, 0xfb,
- 0xdb, 0x46, 0x4c, 0x79, 0x5d, 0x9d, 0x97, 0x76, 0x45, 0x38, 0x75, 0x46,
- 0x21, 0x7f, 0xa6, 0x3d, 0xd1, 0x0a, 0x8e, 0xb5, 0x8e, 0x0b, 0x7a, 0xa1,
- 0x1b, 0x99, 0x0e, 0xc9, 0x29, 0xfa, 0x0e, 0x62, 0x2f, 0xda, 0x1b, 0xec,
- 0xc6, 0xe6, 0x59, 0x38, 0x97, 0x81, 0xed, 0xa6, 0x95, 0xfe, 0x14, 0x2a,
- 0xf4, 0x07, 0xa4, 0x6d, 0x35, 0xad, 0x4b, 0x80, 0xaf, 0xf4, 0x6c, 0x37,
- 0x68, 0xe3, 0x18, 0xb6, 0x67, 0xe3, 0xfd, 0x7e, 0xd8, 0xfa, 0xc1, 0x41,
- 0xf0, 0x87, 0x70, 0x76, 0x0a, 0xf2, 0xce, 0xba, 0xd8, 0xd3, 0x75, 0x6e,
- 0x56, 0x3c, 0xe8, 0xc1, 0x79, 0x06, 0x67, 0xc9, 0xaf, 0x76, 0xe8, 0xb3,
- 0x26, 0x05, 0x27, 0x9d, 0xa2, 0xfc, 0x03, 0xda, 0x75, 0xd9, 0x76, 0x4b,
- 0x23, 0xed, 0x91, 0xac, 0xa8, 0x8f, 0xa6, 0xc4, 0x47, 0x08, 0x4b, 0x38,
- 0xc2, 0xa7, 0x0f, 0x8a, 0xfe, 0x6b, 0xdf, 0xda, 0x74, 0x56, 0x5b, 0x06,
- 0x66, 0x41, 0x43, 0xc0, 0x5b, 0xf0, 0xe4, 0xb3, 0x60, 0xc9, 0xd7, 0xad,
- 0xfc, 0x23, 0x6c, 0x23, 0x1c, 0x74, 0xa2, 0x8f, 0x34, 0xac, 0x74, 0x04,
- 0xf6, 0x15, 0xd1, 0x14, 0xc9, 0x46, 0x0b, 0x71, 0x7c, 0xda, 0x39, 0x08,
- 0x0f, 0xbb, 0xf7, 0x60, 0xf7, 0x1e, 0x7c, 0x82, 0x07, 0x9b, 0xf7, 0xe8,
- 0x27, 0x52, 0xf2, 0xea, 0x10, 0xfc, 0xda, 0x86, 0x5f, 0x41, 0x1b, 0x43,
- 0x5f, 0x17, 0x03, 0x7e, 0x65, 0xba, 0xaa, 0xc3, 0x76, 0x61, 0x43, 0x4b,
- 0x9c, 0xb3, 0xf0, 0xcc, 0xe3, 0x69, 0xc3, 0x8f, 0x52, 0xaf, 0x22, 0xff,
- 0x49, 0x3f, 0x93, 0x84, 0x4f, 0xa1, 0xaf, 0xa1, 0x2f, 0x21, 0xac, 0xef,
- 0xe7, 0x1d, 0xae, 0xf5, 0x65, 0xdc, 0xa1, 0x1d, 0x75, 0x88, 0x1e, 0x2f,
- 0x6a, 0x47, 0x87, 0x60, 0x63, 0x37, 0xb6, 0x80, 0x56, 0xda, 0xda, 0x75,
- 0x74, 0x15, 0x68, 0xbf, 0xe8, 0x0c, 0xfe, 0x5d, 0xde, 0x36, 0xc0, 0x28,
- 0xa1, 0x76, 0x05, 0xe3, 0xb6, 0xd0, 0x9f, 0xf0, 0x7d, 0x3a, 0x95, 0x95,
- 0xdd, 0xe1, 0x98, 0xfd, 0x75, 0x7a, 0x1d, 0xfd, 0x96, 0x98, 0x0c, 0x9c,
- 0x09, 0xfc, 0xe0, 0xc0, 0x82, 0x25, 0xf6, 0x99, 0x80, 0xc6, 0x81, 0x73,
- 0x91, 0x3f, 0x6c, 0x01, 0x3e, 0xd0, 0xe7, 0x6d, 0xc4, 0x09, 0x91, 0xf7,
- 0x34, 0x98, 0x0a, 0xe6, 0xb6, 0xf2, 0x82, 0x3e, 0x98, 0xf6, 0x66, 0x35,
- 0xda, 0xdb, 0x01, 0xd8, 0x9b, 0xd3, 0x2a, 0x69, 0xe7, 0xef, 0x60, 0x6f,
- 0x4f, 0x39, 0x1a, 0x78, 0x23, 0x72, 0xa1, 0xdc, 0x01, 0x5b, 0x37, 0x93,
- 0xef, 0xc8, 0x9e, 0xd4, 0xb4, 0x68, 0x72, 0x9a, 0x73, 0x35, 0xcc, 0x29,
- 0xff, 0x1b, 0xd8, 0xf7, 0x45, 0xe3, 0x69, 0xd0, 0xe5, 0xfb, 0xd3, 0xc0,
- 0x59, 0xd8, 0x6f, 0x84, 0xb6, 0x15, 0xcd, 0xa7, 0x10, 0xf3, 0xdc, 0xcf,
- 0x19, 0x52, 0x1c, 0x6e, 0x91, 0xf4, 0xf0, 0x02, 0x70, 0x4f, 0x3a, 0x81,
- 0x1d, 0x53, 0xd7, 0x17, 0x81, 0x7f, 0xc6, 0x1b, 0x82, 0x1e, 0xd3, 0x0e,
- 0x40, 0x17, 0xf0, 0x2f, 0x02, 0xff, 0x4c, 0xbd, 0x45, 0xbe, 0x69, 0x46,
- 0xb1, 0x34, 0x3a, 0x4f, 0x1b, 0xc0, 0xa2, 0x7d, 0x4f, 0xc8, 0x17, 0xbd,
- 0xb8, 0xe6, 0x3e, 0x4b, 0x3f, 0x5b, 0x1a, 0x86, 0x9d, 0x68, 0x25, 0x87,
- 0x7b, 0x1b, 0xb2, 0xb8, 0x0e, 0x23, 0xd9, 0x52, 0x60, 0x83, 0x59, 0x77,
- 0xa8, 0x98, 0x34, 0x94, 0x2f, 0x11, 0x39, 0x5c, 0x36, 0x01, 0xc3, 0x31,
- 0xe7, 0x83, 0xb9, 0xb1, 0x72, 0x1f, 0x7c, 0x23, 0xc7, 0x57, 0xfd, 0x49,
- 0x27, 0x98, 0xfb, 0xdd, 0x72, 0x81, 0x32, 0x62, 0xdc, 0x4e, 0x95, 0x9c,
- 0x7f, 0xf7, 0xa1, 0xbf, 0x9b, 0xd6, 0x5c, 0x1b, 0x4f, 0x7a, 0x2c, 0x8c,
- 0xf5, 0xda, 0x11, 0x5b, 0xef, 0x6b, 0x0d, 0x7d, 0xd8, 0x11, 0x4c, 0x1e,
- 0x2a, 0x97, 0x7a, 0x5b, 0xe5, 0xaa, 0xc1, 0xd8, 0x79, 0x09, 0x46, 0xed,
- 0x96, 0xf7, 0x82, 0x1f, 0xa5, 0x9e, 0x86, 0xb9, 0x58, 0xbe, 0xec, 0xcb,
- 0x9a, 0x13, 0xac, 0xc1, 0xb8, 0x23, 0x57, 0xd6, 0xfb, 0x62, 0xb2, 0x3e,
- 0xb6, 0xb8, 0x66, 0x49, 0xf6, 0x0e, 0x2f, 0x8a, 0x5a, 0xdb, 0x1b, 0xdb,
- 0x58, 0x9b, 0xc8, 0x97, 0x4b, 0x3d, 0x0d, 0xe3, 0x64, 0x0e, 0xb8, 0xf4,
- 0x03, 0xeb, 0x6b, 0xfb, 0x37, 0xd6, 0xee, 0x90, 0x54, 0x0f, 0xd7, 0xeb,
- 0x7d, 0x6d, 0x1b, 0xb8, 0x53, 0x21, 0x3d, 0xbd, 0x6d, 0x1b, 0x38, 0x6c,
- 0xe2, 0x6c, 0x18, 0x0f, 0x13, 0xe7, 0xc0, 0x06, 0xce, 0xfd, 0x9b, 0xe9,
- 0x39, 0x21, 0xf0, 0x41, 0xb1, 0xd6, 0x8c, 0x1c, 0xb8, 0x50, 0x1e, 0x1c,
- 0xff, 0xa2, 0x20, 0xe6, 0xed, 0xdf, 0x16, 0xfa, 0x64, 0xf3, 0x80, 0x0b,
- 0x5e, 0x99, 0x42, 0x1f, 0xa7, 0x49, 0x09, 0x72, 0x7e, 0xa8, 0x26, 0x07,
- 0xd6, 0x6a, 0x12, 0xea, 0x12, 0x75, 0xe2, 0x32, 0x6c, 0x4c, 0x8a, 0xbb,
- 0x32, 0x1d, 0x13, 0x66, 0xc6, 0x82, 0xad, 0xc9, 0x78, 0x09, 0x3e, 0xd9,
- 0xc8, 0xec, 0x79, 0x3b, 0x67, 0x3c, 0xe9, 0x1b, 0x88, 0xdb, 0x39, 0xe9,
- 0x38, 0xe8, 0x8e, 0x62, 0xbe, 0x46, 0xdb, 0x82, 0x5f, 0xa9, 0x13, 0xf7,
- 0x7c, 0xb7, 0x74, 0x21, 0x2e, 0xd6, 0x5e, 0xda, 0x11, 0xd8, 0x8e, 0x98,
- 0x26, 0x7c, 0xed, 0xcc, 0x28, 0xe3, 0x78, 0x6b, 0x0c, 0xf0, 0x13, 0x46,
- 0x66, 0x6c, 0xe7, 0xf1, 0xda, 0x9d, 0x3b, 0x0b, 0xb5, 0xe2, 0xce, 0x42,
- 0xd9, 0xa2, 0x9d, 0xe8, 0xee, 0x28, 0xfa, 0x2a, 0x57, 0x4a, 0xc2, 0x26,
- 0x2e, 0xab, 0x3c, 0xe2, 0xb5, 0x7a, 0x1d, 0xf6, 0x47, 0xfb, 0x16, 0x19,
- 0xf7, 0xb0, 0xc7, 0xc8, 0x87, 0x90, 0x3b, 0x68, 0x83, 0x4f, 0xcb, 0xe2,
- 0xd4, 0xfa, 0xc8, 0xbf, 0x85, 0xf6, 0xc9, 0xfe, 0xfb, 0x7e, 0xe0, 0xef,
- 0xef, 0xe8, 0x0e, 0xe6, 0xde, 0x0a, 0x6d, 0x3a, 0xc2, 0x45, 0x3c, 0xc3,
- 0xda, 0x38, 0x72, 0x92, 0xf1, 0xba, 0xa9, 0xd1, 0x3f, 0xe7, 0x3c, 0xe6,
- 0x12, 0xcc, 0x23, 0xa6, 0x43, 0x3f, 0x27, 0xd9, 0x1c, 0xfc, 0x88, 0x8e,
- 0xdc, 0xa2, 0x00, 0xbb, 0x31, 0x33, 0x57, 0x64, 0x46, 0xf9, 0x48, 0x89,
- 0xb5, 0x64, 0x9e, 0x00, 0xcc, 0x7f, 0xc0, 0xe6, 0xda, 0xba, 0x43, 0x3d,
- 0x0c, 0x7d, 0xbc, 0xf2, 0xbb, 0x80, 0xbd, 0xbc, 0x05, 0xf6, 0xdd, 0x46,
- 0x58, 0xbc, 0xbf, 0xb8, 0xe5, 0xfd, 0x4f, 0x69, 0xbf, 0x78, 0xb7, 0x0a,
- 0x7f, 0xda, 0x1a, 0xda, 0xfe, 0x05, 0x29, 0xc0, 0xb7, 0x9a, 0x36, 0x73,
- 0xc7, 0xdb, 0xb0, 0x16, 0xe3, 0x1a, 0x68, 0x84, 0xbf, 0x40, 0xcc, 0x04,
- 0xbf, 0x11, 0x13, 0x12, 0x37, 0x30, 0x3f, 0xa2, 0x9f, 0x00, 0x2c, 0xfd,
- 0x2f, 0x61, 0x5f, 0xe9, 0x20, 0xcf, 0x0b, 0x35, 0xae, 0xa1, 0xaf, 0x12,
- 0xdf, 0x1d, 0x6d, 0x83, 0x46, 0xf9, 0xaf, 0x19, 0x76, 0x04, 0x1b, 0xe1,
- 0xdd, 0x0a, 0xcb, 0x7c, 0x85, 0xb8, 0xbb, 0xc3, 0x3c, 0x60, 0x4c, 0xb2,
- 0xf5, 0x2c, 0x7e, 0x45, 0x99, 0x7c, 0x16, 0xb9, 0x98, 0xdd, 0x42, 0x5e,
- 0x90, 0x35, 0x56, 0xc0, 0xa3, 0x68, 0xdd, 0x13, 0xbd, 0x9b, 0xc7, 0xf7,
- 0xc5, 0x37, 0x7c, 0x25, 0x2d, 0x4d, 0xb2, 0x88, 0x15, 0xe0, 0x71, 0x6a,
- 0x42, 0xcf, 0x24, 0x24, 0x57, 0x0b, 0xf8, 0x8b, 0x78, 0x0b, 0xff, 0xc8,
- 0x2e, 0x64, 0xb2, 0xee, 0x07, 0x23, 0x99, 0x53, 0xcf, 0xb2, 0x90, 0x4d,
- 0x0a, 0xba, 0x34, 0x86, 0xb5, 0x72, 0x02, 0x38, 0x18, 0x87, 0x1d, 0x3d,
- 0x13, 0x97, 0x82, 0xc5, 0x7c, 0x41, 0xe5, 0x7a, 0x59, 0xfa, 0x01, 0x3d,
- 0xd3, 0x86, 0x39, 0xf6, 0x1f, 0xee, 0x0e, 0x64, 0xdd, 0xc9, 0xf1, 0xb8,
- 0x9e, 0xe9, 0xde, 0x32, 0xff, 0x7a, 0x67, 0x40, 0x9b, 0x1a, 0x63, 0xfe,
- 0x5f, 0xb6, 0x8c, 0xbf, 0x1e, 0xdf, 0x3c, 0x7e, 0x60, 0x67, 0xa4, 0x0f,
- 0x7a, 0xe6, 0x89, 0x90, 0x5e, 0xea, 0xe9, 0x56, 0x5a, 0x7f, 0x13, 0x7d,
- 0x79, 0x0e, 0x38, 0x95, 0x8e, 0xff, 0x06, 0xfa, 0xb2, 0x0e, 0xfb, 0x09,
- 0xfa, 0xd2, 0x48, 0xc3, 0x7a, 0x5d, 0x51, 0xd1, 0x91, 0x93, 0xba, 0xa3,
- 0x7b, 0x90, 0x77, 0xa4, 0x24, 0x5f, 0x07, 0xef, 0xd6, 0xe3, 0xea, 0x3a,
- 0x4c, 0x71, 0x03, 0x26, 0x88, 0x3b, 0xf9, 0xba, 0x8f, 0x3c, 0xae, 0x31,
- 0x06, 0x0f, 0xa3, 0x5f, 0xc4, 0x59, 0x57, 0x64, 0xd2, 0x5b, 0xcb, 0xea,
- 0xf6, 0xa9, 0x20, 0x0f, 0xb5, 0xbf, 0xad, 0xe5, 0x17, 0x99, 0xa3, 0xc6,
- 0xd0, 0x57, 0xf5, 0x07, 0x62, 0xdc, 0x33, 0x5a, 0x76, 0x79, 0x0e, 0xf9,
- 0xe9, 0x12, 0x7e, 0x67, 0xf1, 0xab, 0xe1, 0x17, 0xd5, 0x01, 0x2f, 0xa0,
- 0x8e, 0x50, 0xfe, 0x1e, 0xb1, 0x29, 0xd8, 0xff, 0x67, 0x4b, 0xc8, 0x8f,
- 0xe7, 0x12, 0xf2, 0x94, 0xad, 0xf7, 0xea, 0x81, 0x8f, 0xcb, 0x22, 0xb7,
- 0xb6, 0x2e, 0xcb, 0x97, 0xc2, 0x1c, 0x4d, 0xe4, 0x9d, 0x0a, 0x64, 0xb9,
- 0xff, 0x48, 0xe8, 0x9f, 0xbe, 0xf6, 0xa0, 0xab, 0x7c, 0x79, 0x98, 0x83,
- 0xc1, 0xef, 0x64, 0x15, 0xd4, 0x1b, 0xe0, 0x8f, 0x26, 0xef, 0x41, 0x8f,
- 0xdf, 0xa9, 0xb4, 0x83, 0x1e, 0x5b, 0x0a, 0xc7, 0x90, 0xbb, 0x68, 0x83,
- 0xd6, 0x36, 0xad, 0x1d, 0x79, 0x18, 0xfc, 0x8e, 0x1a, 0x93, 0x67, 0x17,
- 0xa7, 0x16, 0xca, 0x3a, 0x60, 0xc1, 0xf3, 0x51, 0xf4, 0xa1, 0x7f, 0x97,
- 0x2a, 0x5c, 0xa7, 0xcb, 0xbb, 0x15, 0x43, 0x7e, 0x8e, 0xbc, 0xee, 0x3d,
- 0xfb, 0xe2, 0x14, 0x6c, 0xb0, 0x0f, 0xf1, 0x0a, 0xb5, 0xd0, 0x1e, 0xc6,
- 0x8c, 0x01, 0x13, 0xcf, 0x3c, 0x7e, 0x87, 0x91, 0xe7, 0x5d, 0x7b, 0xcd,
- 0x27, 0xc1, 0x93, 0xb6, 0x18, 0xd6, 0x10, 0xde, 0x04, 0x6d, 0x5d, 0xd0,
- 0xc1, 0xb4, 0x35, 0x21, 0xdd, 0x96, 0xca, 0x9d, 0x34, 0xce, 0x07, 0x7e,
- 0xf2, 0xe3, 0xf3, 0xe4, 0xb3, 0x01, 0x1d, 0xe2, 0x98, 0xef, 0xe8, 0xcf,
- 0x89, 0x2f, 0x7d, 0x30, 0x8b, 0xc3, 0x5c, 0xaa, 0x04, 0xfd, 0x68, 0x4e,
- 0xb4, 0x28, 0xa6, 0xd2, 0x4f, 0xe7, 0x61, 0xab, 0x1c, 0x8f, 0x8b, 0x92,
- 0xc1, 0x26, 0x79, 0x52, 0x8f, 0x56, 0xa7, 0x66, 0x6c, 0xca, 0xd5, 0x92,
- 0xe9, 0x72, 0x24, 0x57, 0xca, 0x08, 0x75, 0x66, 0xe5, 0xdb, 0x90, 0xab,
- 0x1e, 0xd6, 0x20, 0xf0, 0x03, 0x73, 0x94, 0x2f, 0xea, 0xc4, 0x0a, 0xf2,
- 0xb0, 0x8a, 0xc4, 0x83, 0x1a, 0xea, 0x19, 0xd4, 0x1d, 0x90, 0x5f, 0x79,
- 0x0e, 0x38, 0x12, 0x78, 0x2e, 0xe1, 0x99, 0xc4, 0xf3, 0x2c, 0x9e, 0xfd,
- 0x78, 0xd6, 0x68, 0x1f, 0x61, 0xde, 0xf3, 0x31, 0x7a, 0x60, 0x27, 0x79,
- 0xda, 0xb4, 0x7c, 0xaf, 0x9e, 0x91, 0xbf, 0xad, 0x1f, 0x94, 0xbf, 0xa9,
- 0x8f, 0xca, 0x5f, 0xd7, 0x1d, 0x79, 0xb9, 0xbe, 0x5f, 0xfe, 0xaa, 0x3e,
- 0xcc, 0x9a, 0x10, 0x39, 0x5c, 0x0a, 0xbe, 0xf9, 0xbc, 0x3c, 0xe8, 0xd5,
- 0xe1, 0x73, 0x28, 0xff, 0x8b, 0x53, 0xd9, 0xda, 0x75, 0x52, 0x78, 0xd6,
- 0x42, 0x9e, 0x69, 0xb0, 0x2e, 0x93, 0xc7, 0x9c, 0x3b, 0xe2, 0x94, 0xbd,
- 0x6e, 0xb3, 0x4e, 0x39, 0x49, 0x38, 0xd4, 0xbb, 0x1a, 0xf2, 0x97, 0x16,
- 0x99, 0x48, 0xa4, 0x57, 0x5c, 0x23, 0x19, 0xfa, 0xa3, 0x3b, 0x01, 0x87,
- 0x3d, 0xbd, 0x0e, 0x59, 0x7b, 0x1e, 0xb6, 0xe0, 0xa0, 0x56, 0x4e, 0xc4,
- 0xe0, 0xfb, 0x54, 0x7e, 0xa2, 0x7c, 0x4b, 0xe0, 0x4b, 0xa3, 0x9a, 0x91,
- 0x73, 0xd9, 0x70, 0x8e, 0xf1, 0xd1, 0x02, 0xec, 0x72, 0x18, 0x43, 0xb6,
- 0xe2, 0xa4, 0x6f, 0x3c, 0x16, 0xfa, 0xc7, 0x15, 0x39, 0xe1, 0x0d, 0x66,
- 0xaf, 0x20, 0xf6, 0x68, 0x2d, 0x51, 0x5e, 0xb4, 0x0b, 0xb4, 0xf9, 0xfe,
- 0xdd, 0xac, 0xbf, 0xe3, 0xa6, 0xfc, 0x70, 0x36, 0x6d, 0x3d, 0xa2, 0xcf,
- 0x40, 0xce, 0xbe, 0x7f, 0xd4, 0x4e, 0x9f, 0x9a, 0xd0, 0x3b, 0xe5, 0x27,
- 0xcf, 0x30, 0x26, 0xaf, 0x4e, 0x7d, 0x1f, 0x7a, 0x50, 0x5d, 0x6a, 0x95,
- 0x6a, 0xd5, 0x94, 0x4b, 0x23, 0x83, 0x6a, 0xdf, 0x6a, 0x2d, 0x8e, 0x3c,
- 0xaf, 0x4d, 0xa6, 0xfb, 0x94, 0xb2, 0xc3, 0x6f, 0x0f, 0x2b, 0xbf, 0xed,
- 0xda, 0x78, 0xd6, 0x92, 0xd6, 0x66, 0x5a, 0x5e, 0x96, 0x82, 0x07, 0x1d,
- 0x8b, 0xef, 0x02, 0x4f, 0xd8, 0x1f, 0xb4, 0x0a, 0x3a, 0x62, 0xa0, 0x39,
- 0x68, 0x3d, 0xa8, 0xff, 0xd2, 0xff, 0x1d, 0x93, 0x7c, 0x7c, 0x1b, 0xb1,
- 0x85, 0xb1, 0x52, 0x53, 0x7a, 0xb7, 0xb0, 0xf4, 0x53, 0x8b, 0xfe, 0x65,
- 0xa5, 0xb6, 0x2b, 0x1c, 0xd3, 0xbf, 0x73, 0xdc, 0x2e, 0x2f, 0x57, 0xb7,
- 0xcb, 0x62, 0x95, 0xef, 0x5b, 0x65, 0xa1, 0x3a, 0x78, 0xa5, 0x57, 0xef,
- 0x93, 0xd5, 0xeb, 0x6e, 0xb4, 0xee, 0xd7, 0xc1, 0x93, 0x63, 0x1f, 0xc9,
- 0x07, 0x23, 0xdd, 0xf2, 0xd6, 0x7d, 0xe9, 0x17, 0xfe, 0x44, 0x87, 0x3e,
- 0x8e, 0x74, 0xd0, 0xce, 0xd0, 0xe7, 0x7c, 0xfa, 0x4a, 0x56, 0xa7, 0x9e,
- 0xfd, 0x00, 0xfa, 0x95, 0xae, 0x04, 0x3a, 0x49, 0xdc, 0xc4, 0x0b, 0xf9,
- 0xd8, 0x6f, 0x00, 0x27, 0xde, 0xd5, 0x06, 0x81, 0xeb, 0x0d, 0xc5, 0x8b,
- 0xbb, 0x9d, 0xf4, 0x15, 0x84, 0x28, 0xff, 0x92, 0x3d, 0x38, 0x3c, 0xa0,
- 0xef, 0x92, 0x6a, 0xf2, 0x46, 0xeb, 0xbb, 0x88, 0x07, 0xd9, 0x44, 0xfa,
- 0xd4, 0x45, 0x59, 0x9d, 0xba, 0x60, 0x53, 0x17, 0x69, 0xc3, 0xff, 0x80,
- 0x9c, 0xd4, 0x92, 0x4a, 0x8d, 0xbe, 0x8b, 0xb8, 0x58, 0x17, 0xec, 0xb5,
- 0x4e, 0x80, 0x06, 0x77, 0x3f, 0xde, 0x61, 0xde, 0xf8, 0x3c, 0xe5, 0xd6,
- 0xc2, 0xb5, 0xc3, 0x59, 0xbd, 0x7f, 0x0b, 0x8f, 0x06, 0xad, 0x43, 0x3a,
- 0xf7, 0xfb, 0x2f, 0xec, 0xfb, 0x3e, 0x68, 0x1d, 0xc4, 0x5a, 0xc4, 0xd0,
- 0x64, 0xe3, 0x1e, 0x3f, 0x52, 0x7b, 0x3c, 0x5b, 0x43, 0x0e, 0xb8, 0xbe,
- 0x07, 0xe6, 0x6a, 0x3a, 0xce, 0x69, 0x2a, 0xb9, 0x5c, 0x1a, 0x21, 0x7f,
- 0x6f, 0xef, 0x61, 0x2c, 0x37, 0x32, 0x2f, 0x85, 0x79, 0x46, 0x4c, 0x7e,
- 0x8c, 0xba, 0x6b, 0x12, 0xfe, 0x7f, 0x61, 0xef, 0x20, 0x68, 0x40, 0x7d,
- 0x9a, 0x54, 0xf1, 0x7c, 0xca, 0x05, 0x8e, 0x9c, 0xc2, 0xfd, 0xa6, 0x2c,
- 0x01, 0xf7, 0x38, 0xf9, 0x00, 0xdc, 0x33, 0x9c, 0x57, 0x32, 0xc0, 0x7c,
- 0x2d, 0x05, 0xbc, 0xbd, 0xa1, 0xff, 0x8b, 0x43, 0x57, 0xf7, 0x59, 0x77,
- 0x4b, 0x2c, 0xf4, 0x7f, 0x71, 0x79, 0xeb, 0x79, 0xe8, 0x7d, 0x9c, 0xfa,
- 0x93, 0xe8, 0xd9, 0xd0, 0x9f, 0x46, 0xfc, 0xad, 0x92, 0xaf, 0xc4, 0x80,
- 0x17, 0x39, 0xf7, 0x28, 0xf1, 0x62, 0x5c, 0xa5, 0x2e, 0x17, 0x43, 0x5d,
- 0xee, 0x08, 0x71, 0xaf, 0x41, 0x97, 0xd3, 0xa9, 0x55, 0x9d, 0xf5, 0xd5,
- 0x4e, 0x55, 0xf3, 0x1a, 0xb0, 0xaf, 0x42, 0x99, 0xb1, 0x88, 0xb6, 0x75,
- 0x71, 0x6a, 0x12, 0x35, 0x6c, 0xa1, 0x7c, 0x50, 0x2f, 0xd4, 0x47, 0xf5,
- 0x82, 0x47, 0x7d, 0xdb, 0x6b, 0x2d, 0x28, 0x1e, 0x27, 0x65, 0xa1, 0xfe,
- 0x81, 0x5f, 0xda, 0xbb, 0x0d, 0x7d, 0xe8, 0xfe, 0x38, 0xe5, 0x7b, 0x3d,
- 0xe9, 0x42, 0x50, 0x27, 0xbf, 0x13, 0x72, 0x66, 0xe8, 0x7b, 0xdd, 0xcc,
- 0xd1, 0x96, 0x87, 0x88, 0x1f, 0x74, 0x24, 0x12, 0xb2, 0xe8, 0x71, 0x8f,
- 0xd5, 0x29, 0xf2, 0xb2, 0x30, 0x67, 0xc9, 0x09, 0x25, 0x3f, 0x9e, 0x9b,
- 0xf7, 0x47, 0x86, 0x4c, 0xc6, 0x07, 0xad, 0x47, 0x25, 0x7d, 0x65, 0xcd,
- 0x48, 0xbf, 0x30, 0x81, 0xb8, 0xba, 0x30, 0x6f, 0x88, 0xab, 0xea, 0x30,
- 0xca, 0x28, 0x5d, 0x81, 0x35, 0x86, 0x67, 0xbf, 0xa7, 0xe1, 0xec, 0x5d,
- 0x72, 0xe1, 0xf9, 0xcf, 0xc3, 0xee, 0x5f, 0x81, 0x2c, 0xcc, 0xd4, 0x71,
- 0xe4, 0x19, 0xcf, 0xc9, 0xa0, 0x55, 0x42, 0xfe, 0x0c, 0xbe, 0xa3, 0xbd,
- 0xa2, 0x6c, 0x60, 0x41, 0xc7, 0xb8, 0x9f, 0x7c, 0xe2, 0x78, 0xb7, 0x2c,
- 0xf4, 0x05, 0x36, 0xce, 0x77, 0x03, 0xc0, 0x11, 0xbc, 0xe3, 0xf8, 0xb7,
- 0x64, 0x40, 0xbd, 0xab, 0xaa, 0x75, 0x25, 0xe9, 0x0d, 0xe5, 0xf7, 0x18,
- 0xf6, 0x24, 0x8f, 0xa3, 0xf9, 0x4e, 0x09, 0x6c, 0x29, 0xe2, 0xbb, 0x25,
- 0x47, 0x6b, 0x09, 0xb9, 0xa7, 0x96, 0x94, 0x2f, 0xd7, 0xfa, 0x25, 0x0f,
- 0x39, 0x4e, 0x8e, 0x3e, 0xd9, 0xc3, 0xb3, 0xe5, 0x96, 0xd2, 0x2f, 0x88,
- 0x4e, 0x5a, 0xab, 0x72, 0xdc, 0x8b, 0xe8, 0xe9, 0x08, 0xe9, 0x33, 0xc3,
- 0x71, 0x2c, 0xa4, 0xa1, 0x11, 0x5f, 0x07, 0x70, 0x65, 0x81, 0xe7, 0xa5,
- 0x10, 0x0f, 0xfd, 0x08, 0x68, 0x3d, 0x96, 0x94, 0x25, 0x8f, 0x74, 0x6c,
- 0x97, 0x52, 0x82, 0xfd, 0x57, 0xa0, 0x6f, 0xc4, 0xb3, 0x8d, 0xf9, 0xcd,
- 0x26, 0x1e, 0x3f, 0x5c, 0x2b, 0x82, 0xc7, 0xe4, 0x2f, 0xe1, 0xe0, 0xaf,
- 0xbf, 0x40, 0xf9, 0xed, 0x43, 0x8e, 0x6f, 0x07, 0xba, 0x69, 0x6d, 0xec,
- 0x99, 0x9f, 0xeb, 0x82, 0xac, 0xb8, 0x6f, 0xbb, 0x1c, 0x83, 0xdd, 0xe7,
- 0xaa, 0xdc, 0xff, 0x18, 0xf4, 0xe8, 0x2d, 0xb5, 0x7f, 0x7e, 0xa9, 0x2f,
- 0x5c, 0xcf, 0xb5, 0x5d, 0x5b, 0xd6, 0xb6, 0xca, 0xa1, 0x8a, 0x75, 0x8d,
- 0xf5, 0xbf, 0x8f, 0xf5, 0xba, 0x9c, 0x1e, 0xe5, 0x7a, 0xe2, 0x01, 0x5c,
- 0x35, 0xf1, 0x29, 0x78, 0xe2, 0xaa, 0xde, 0xcf, 0x55, 0x5b, 0x25, 0x57,
- 0x89, 0x70, 0x11, 0xcf, 0x47, 0xa8, 0x87, 0xbf, 0xaa, 0x70, 0x4d, 0x2a,
- 0x5c, 0x78, 0x5f, 0xa5, 0xcf, 0xb9, 0x15, 0xeb, 0x3b, 0xe8, 0xff, 0xa5,
- 0x14, 0xef, 0x94, 0x92, 0xaa, 0xe9, 0xdb, 0x95, 0xaf, 0x29, 0xc5, 0xdb,
- 0xf0, 0xbe, 0x13, 0x36, 0xbf, 0x0f, 0xb9, 0x45, 0x17, 0xeb, 0xdc, 0x2d,
- 0x73, 0x5b, 0xe9, 0x8f, 0x6d, 0xa1, 0x3f, 0x06, 0xb8, 0x5e, 0xec, 0x19,
- 0xc0, 0xe5, 0x01, 0x37, 0x3d, 0x07, 0x3e, 0x3b, 0xf4, 0x2b, 0x8c, 0x93,
- 0xd7, 0x29, 0x5a, 0xa6, 0x97, 0xfe, 0x1b, 0xe7, 0xea, 0xc3, 0xda, 0x68,
- 0x1c, 0xf0, 0xe1, 0x69, 0xe0, 0x99, 0xab, 0xaa, 0xbb, 0x0b, 0xc8, 0x60,
- 0x7b, 0x9c, 0x67, 0x2f, 0x55, 0x3f, 0x8b, 0x67, 0xd7, 0x35, 0xf0, 0x8b,
- 0xbc, 0x22, 0xbd, 0xa4, 0x95, 0xf7, 0x48, 0xb0, 0x37, 0x07, 0x7a, 0x1c,
- 0x37, 0x24, 0x3f, 0x6a, 0x21, 0x3f, 0xe7, 0x3d, 0x2c, 0xed, 0xd2, 0xe2,
- 0xdd, 0x67, 0x4c, 0xb7, 0x19, 0x6b, 0x4d, 0x75, 0xf6, 0xe3, 0x4b, 0xbc,
- 0x8b, 0x4d, 0xf1, 0xee, 0x6e, 0x98, 0xd7, 0x18, 0x8f, 0x2c, 0xd9, 0xf2,
- 0x78, 0x6d, 0x58, 0x1e, 0xad, 0xa5, 0xad, 0xfb, 0xe1, 0x03, 0x0a, 0xeb,
- 0x77, 0xb4, 0x43, 0x71, 0xfa, 0x2f, 0x13, 0x79, 0x60, 0x8b, 0x1d, 0xe4,
- 0x05, 0x25, 0xd6, 0x6c, 0x73, 0x69, 0xde, 0xe3, 0x58, 0x55, 0xd9, 0x9a,
- 0x3b, 0xfc, 0x5f, 0xe6, 0x0d, 0xdc, 0x9f, 0xfe, 0x1a, 0x79, 0x82, 0x87,
- 0x3c, 0xc1, 0x43, 0x9e, 0xe0, 0x21, 0x4f, 0xf0, 0x90, 0x27, 0x78, 0xc8,
- 0x13, 0x3c, 0xe4, 0x09, 0x1e, 0xf2, 0x04, 0xc4, 0xee, 0xa0, 0x5e, 0x18,
- 0x43, 0xfe, 0x0b, 0xff, 0xe5, 0xdd, 0x06, 0x3e, 0xf1, 0xfe, 0x92, 0x31,
- 0x87, 0xb1, 0x99, 0x73, 0xab, 0xdb, 0x5c, 0xca, 0x4d, 0xf9, 0xbe, 0x3b,
- 0x31, 0x37, 0x1e, 0xe6, 0x23, 0x84, 0x89, 0x62, 0x37, 0xe1, 0xe4, 0xa0,
- 0xeb, 0x68, 0xb0, 0x31, 0xe6, 0x2b, 0x41, 0xcc, 0x0a, 0x72, 0xe5, 0xb7,
- 0x91, 0xb3, 0xa4, 0x90, 0xb3, 0xf4, 0x23, 0x3f, 0xe1, 0x9d, 0x75, 0x74,
- 0xc7, 0x94, 0xd5, 0x8e, 0x7a, 0x63, 0xda, 0x3d, 0x1e, 0x73, 0x69, 0x3b,
- 0x55, 0xd0, 0xf5, 0xb9, 0x5e, 0xf1, 0x25, 0x37, 0xf2, 0x4d, 0xe4, 0xad,
- 0xcf, 0xa9, 0xfb, 0xb4, 0xf1, 0x21, 0xca, 0xbc, 0xf2, 0x09, 0xb9, 0x6b,
- 0xc4, 0xdf, 0xe0, 0x1e, 0x50, 0x5f, 0x20, 0xff, 0x44, 0x7a, 0xce, 0x81,
- 0xe1, 0xe7, 0x62, 0x12, 0x3f, 0xb3, 0x1d, 0x73, 0x96, 0xf4, 0xaa, 0xbb,
- 0x24, 0x88, 0xf2, 0xdc, 0x55, 0xc8, 0xcb, 0x16, 0xfd, 0x1c, 0x6f, 0x1c,
- 0x88, 0x97, 0xfe, 0x75, 0x65, 0x2a, 0x57, 0x5d, 0x51, 0x3a, 0x75, 0xb4,
- 0x96, 0x47, 0x7d, 0xd4, 0xd3, 0x2b, 0xed, 0x26, 0x6a, 0xab, 0x08, 0x37,
- 0x71, 0xfe, 0x32, 0xae, 0x6a, 0x9e, 0x73, 0xeb, 0xf2, 0x84, 0xac, 0xb9,
- 0xcf, 0xca, 0x54, 0xa9, 0x92, 0x4e, 0xb2, 0x56, 0xce, 0x5a, 0x2b, 0x53,
- 0x27, 0x81, 0x63, 0x11, 0xb9, 0x81, 0xa1, 0xf6, 0x5e, 0x99, 0x9a, 0xae,
- 0x04, 0xf7, 0x59, 0x01, 0x0d, 0x8c, 0x57, 0xed, 0x62, 0x2c, 0x04, 0xf7,
- 0x5a, 0xba, 0x5a, 0xcb, 0x75, 0x5c, 0x6f, 0x62, 0x1d, 0xe5, 0x36, 0x8c,
- 0xb5, 0x94, 0x1d, 0x69, 0x58, 0x99, 0x2a, 0x56, 0x1b, 0x69, 0x20, 0x1e,
- 0xe2, 0x8d, 0xce, 0xc3, 0xb3, 0xc4, 0x45, 0x3f, 0xe3, 0xfb, 0x85, 0x91,
- 0xfe, 0x30, 0xef, 0x3a, 0x89, 0xfc, 0xce, 0x0c, 0xf4, 0x5c, 0x8d, 0xbf,
- 0xa3, 0xe2, 0x54, 0x4a, 0xe7, 0x3c, 0x9f, 0x78, 0x37, 0xba, 0x80, 0x39,
- 0x8c, 0x17, 0x23, 0x58, 0x3d, 0x84, 0xed, 0x6c, 0xe0, 0x67, 0x4b, 0xb8,
- 0x1f, 0x69, 0xe2, 0x39, 0x2f, 0x61, 0x2f, 0xd2, 0x45, 0x98, 0x38, 0x68,
- 0x83, 0x2c, 0xbd, 0xff, 0x2d, 0xef, 0x1b, 0xcf, 0x44, 0x9e, 0x9a, 0x58,
- 0x43, 0x78, 0xe2, 0x88, 0xd6, 0xe0, 0xc5, 0xb9, 0x60, 0x9d, 0xbe, 0x7e,
- 0xff, 0xf7, 0x69, 0xfb, 0x36, 0xd2, 0x1a, 0xed, 0x1f, 0xe1, 0x19, 0x0e,
- 0xe4, 0xb6, 0xbe, 0x5e, 0xfd, 0x9f, 0x61, 0x78, 0x42, 0x17, 0x3f, 0x76,
- 0x8f, 0x3a, 0xdc, 0x50, 0x87, 0x46, 0xf7, 0x17, 0xbc, 0x0f, 0x60, 0x7d,
- 0xcf, 0x6f, 0x07, 0x8d, 0xb5, 0xe2, 0xcb, 0x61, 0x2c, 0xdb, 0x29, 0x59,
- 0x93, 0x75, 0xc3, 0xf9, 0x70, 0xbc, 0x03, 0xb1, 0x8d, 0xe3, 0x3a, 0xf8,
- 0x0b, 0x5d, 0x76, 0xda, 0xc3, 0xba, 0x25, 0x1e, 0x7c, 0xe3, 0x19, 0xa6,
- 0x1d, 0xb1, 0xee, 0x6b, 0x0b, 0xe7, 0x22, 0x3b, 0xa2, 0x1f, 0x36, 0xc3,
- 0x39, 0xfa, 0x5b, 0x1d, 0xb5, 0x0b, 0xfb, 0xc0, 0xb3, 0xd8, 0x68, 0x4b,
- 0xd1, 0x33, 0x2e, 0x67, 0xe7, 0x23, 0xbf, 0x05, 0x9f, 0x32, 0x64, 0x86,
- 0xbe, 0xbf, 0x03, 0xbe, 0xaf, 0x4b, 0x0e, 0xc1, 0x67, 0x1d, 0x86, 0xcf,
- 0x3a, 0x82, 0x7a, 0x71, 0x6c, 0xa9, 0xf1, 0x9e, 0x97, 0x35, 0x6a, 0x97,
- 0x76, 0x5c, 0xc9, 0xbf, 0xe8, 0x1b, 0xf6, 0x47, 0xd0, 0x01, 0xd6, 0x5d,
- 0x91, 0x4e, 0xc0, 0xdf, 0x3a, 0x71, 0xe8, 0xc4, 0xd6, 0xfb, 0xe4, 0x61,
- 0xd8, 0x46, 0x7b, 0x56, 0xc5, 0x86, 0xa5, 0x80, 0xf7, 0xa5, 0x6a, 0xc0,
- 0x7b, 0xf8, 0x65, 0xe0, 0x37, 0xa5, 0x58, 0xb3, 0xa4, 0x88, 0x7d, 0x8b,
- 0xd8, 0xb7, 0x88, 0x3a, 0x6f, 0xba, 0xd6, 0xf8, 0x1d, 0xab, 0x33, 0xa4,
- 0x9d, 0x6b, 0xa3, 0xbe, 0xd5, 0x70, 0xfe, 0xe8, 0x79, 0x0a, 0xfc, 0x7f,
- 0x0c, 0xfc, 0x3f, 0x81, 0xfa, 0xe6, 0x8f, 0x50, 0xdf, 0x7c, 0x0d, 0xf5,
- 0xcd, 0x71, 0xd4, 0x37, 0x13, 0xa8, 0x6f, 0xbe, 0x0a, 0xff, 0xf1, 0x15,
- 0xf8, 0x8f, 0x63, 0xf0, 0x1f, 0xe3, 0xea, 0xee, 0xe9, 0xa8, 0xb7, 0xf5,
- 0x4e, 0x25, 0xda, 0x8b, 0xed, 0x67, 0x22, 0x76, 0x11, 0x67, 0x1a, 0x93,
- 0x6a, 0x9d, 0xf5, 0x8d, 0x23, 0xee, 0x41, 0xd6, 0x37, 0xc7, 0xb4, 0x09,
- 0xe4, 0xef, 0xf7, 0xef, 0x67, 0xdd, 0x13, 0xd7, 0x72, 0xaa, 0xee, 0x49,
- 0x9f, 0x77, 0x91, 0x22, 0x21, 0xf7, 0xc3, 0x99, 0xd3, 0x67, 0x73, 0xa0,
- 0x25, 0xc8, 0xf9, 0x7a, 0x42, 0xbf, 0xd7, 0x21, 0x8b, 0xb3, 0xa8, 0x19,
- 0xbc, 0x1f, 0x6b, 0x05, 0xe5, 0x1b, 0x2d, 0x8c, 0x51, 0x2b, 0x7b, 0xff,
- 0x1c, 0x8e, 0x47, 0x64, 0x72, 0x1e, 0xb5, 0xed, 0xf3, 0xff, 0xa8, 0xe5,
- 0xd4, 0xd8, 0xc1, 0x18, 0xf9, 0xee, 0xf3, 0x7f, 0x1f, 0x8e, 0x8b, 0xa1,
- 0x3e, 0x84, 0xb4, 0x5a, 0x0e, 0x9e, 0xdd, 0x61, 0xce, 0xf1, 0x6a, 0xef,
- 0xe6, 0xff, 0xd3, 0x8e, 0xad, 0x45, 0x13, 0xfb, 0x1b, 0x3b, 0x82, 0xfa,
- 0xac, 0x71, 0xbe, 0xab, 0x61, 0xfe, 0x8a, 0xfa, 0xce, 0x5a, 0x28, 0xb7,
- 0xfd, 0x0a, 0x1e, 0x58, 0x96, 0x86, 0x98, 0xe7, 0x7d, 0xe4, 0xf3, 0xfb,
- 0x9f, 0xab, 0xb7, 0xab, 0x6f, 0x72, 0xae, 0xca, 0xb7, 0x61, 0xe7, 0x23,
- 0xa5, 0x1d, 0x81, 0x2f, 0x60, 0x3f, 0xa1, 0x05, 0xfe, 0xfd, 0x8f, 0x81,
- 0x07, 0xbc, 0xf6, 0x1a, 0x6b, 0x38, 0x2b, 0xbc, 0x4b, 0xb9, 0x32, 0xc5,
- 0xdc, 0xba, 0xa4, 0x70, 0xb3, 0xd6, 0x63, 0xdd, 0x17, 0xc5, 0x80, 0x08,
- 0xd7, 0xcf, 0x13, 0x01, 0xdd, 0xe3, 0xa8, 0xe9, 0x08, 0x13, 0x8d, 0x1b,
- 0xeb, 0xbf, 0x8e, 0xf0, 0x1e, 0xee, 0x4a, 0x90, 0x57, 0x29, 0x7c, 0x66,
- 0x88, 0xef, 0x3f, 0xfd, 0xc0, 0xf7, 0x70, 0xbd, 0xd5, 0xb0, 0xfe, 0x3c,
- 0x72, 0x3d, 0xde, 0x99, 0xec, 0x52, 0xdf, 0x19, 0xdf, 0x9f, 0xed, 0x94,
- 0x5f, 0x3c, 0xe3, 0xfb, 0xe3, 0x4e, 0x7a, 0xf8, 0x4d, 0xd4, 0x1e, 0x67,
- 0x68, 0x27, 0x23, 0xa4, 0x73, 0x30, 0x35, 0x2d, 0x03, 0xbd, 0x41, 0x2e,
- 0xfe, 0x75, 0xed, 0xe3, 0x74, 0xeb, 0xe1, 0x3e, 0x3f, 0x6c, 0xd8, 0x27,
- 0xd5, 0xb0, 0xcf, 0x0a, 0x6d, 0xb6, 0x7a, 0x2f, 0xce, 0x5c, 0xdc, 0x75,
- 0xa3, 0x95, 0x08, 0xeb, 0xb2, 0x47, 0x47, 0xda, 0xa4, 0xd2, 0x97, 0x5e,
- 0xf9, 0x11, 0xf2, 0xf5, 0xc2, 0x08, 0xe6, 0x12, 0x83, 0x78, 0xc7, 0xf9,
- 0x74, 0x15, 0xb9, 0xe8, 0x4a, 0x55, 0x86, 0xb0, 0x3e, 0x5d, 0x14, 0xe1,
- 0x3c, 0xfb, 0x8a, 0xb6, 0x6a, 0xe8, 0x03, 0x92, 0x6b, 0x38, 0xf3, 0x04,
- 0xea, 0xaf, 0x13, 0xeb, 0xf5, 0x30, 0xf7, 0xb9, 0x59, 0x5b, 0x53, 0xb9,
- 0xf1, 0x01, 0xad, 0x98, 0x08, 0xce, 0xf8, 0x87, 0xf0, 0x17, 0x86, 0xce,
- 0xb5, 0xef, 0x03, 0xb7, 0x26, 0x0b, 0xcf, 0x18, 0xea, 0x0e, 0xb6, 0x30,
- 0x42, 0x59, 0xf3, 0x79, 0x2d, 0xde, 0x45, 0x67, 0xfa, 0xf3, 0xf0, 0x4c,
- 0xd9, 0xb0, 0x9e, 0x8e, 0xce, 0x14, 0x93, 0x77, 0x67, 0x2d, 0xac, 0xfd,
- 0x1c, 0xf8, 0x91, 0x97, 0xa5, 0x7a, 0xea, 0x33, 0xf0, 0x94, 0x1b, 0x78,
- 0x63, 0x6e, 0x91, 0x61, 0x71, 0xa3, 0x86, 0x1f, 0x4f, 0xc2, 0x0e, 0xbf,
- 0xd1, 0x1b, 0xdd, 0x0d, 0x1b, 0xb6, 0xcf, 0xba, 0x07, 0x8d, 0xf3, 0xfd,
- 0xb0, 0xc5, 0x14, 0xec, 0x93, 0x39, 0x53, 0x9e, 0xb5, 0x0a, 0xed, 0xc9,
- 0x72, 0x8d, 0xb4, 0x75, 0x4c, 0x86, 0x51, 0xef, 0xf0, 0xfc, 0x19, 0x59,
- 0xac, 0x47, 0x34, 0x8c, 0xc2, 0x1e, 0x0f, 0xe2, 0xb7, 0x1f, 0xef, 0x1c,
- 0xfc, 0x58, 0x2b, 0xad, 0xc8, 0xe3, 0x2a, 0x17, 0x47, 0xae, 0x3d, 0x44,
- 0xfa, 0xee, 0x04, 0x3c, 0xf5, 0x99, 0x7a, 0x7a, 0xa7, 0xb8, 0x7d, 0xf4,
- 0x15, 0x49, 0xe0, 0xc6, 0x1a, 0xef, 0x22, 0x6c, 0xbd, 0x1f, 0xcf, 0xb4,
- 0x55, 0x20, 0x6f, 0x15, 0x7e, 0xdf, 0x37, 0x46, 0xf9, 0x8d, 0xe2, 0x7c,
- 0x38, 0x1e, 0xb4, 0xbe, 0x4c, 0xdd, 0x4b, 0xee, 0x96, 0x95, 0xf9, 0x28,
- 0x0e, 0x9e, 0x86, 0x0d, 0xf2, 0xce, 0x76, 0x0c, 0x7c, 0xe1, 0x58, 0x0b,
- 0xe3, 0x21, 0xe6, 0x17, 0x97, 0x71, 0xee, 0x8c, 0x9c, 0x41, 0xfd, 0x2f,
- 0x7d, 0x7c, 0xa6, 0x80, 0x7f, 0x7b, 0xa8, 0xef, 0x9b, 0xd7, 0x1b, 0x36,
- 0xfb, 0x63, 0xa0, 0xcf, 0x6c, 0x58, 0xcf, 0x35, 0x41, 0x7d, 0xb2, 0x26,
- 0x88, 0xc7, 0x49, 0xff, 0x76, 0x3d, 0xf3, 0xa2, 0x3c, 0xa0, 0xce, 0x54,
- 0x93, 0xe3, 0xf3, 0xbe, 0xef, 0x8e, 0x0e, 0x0e, 0x2f, 0x4a, 0x7a, 0xf8,
- 0xa4, 0xec, 0xb3, 0x0e, 0xb1, 0x1e, 0xb3, 0x88, 0xc7, 0xbf, 0xbd, 0x25,
- 0xe3, 0xfb, 0xa7, 0x41, 0xfb, 0xf7, 0xd5, 0x3e, 0x2f, 0x82, 0x7e, 0xf0,
- 0x4a, 0xd5, 0x24, 0xa4, 0x15, 0xcf, 0x04, 0xe9, 0x2d, 0xcb, 0xf1, 0xfa,
- 0x85, 0x50, 0x36, 0x8f, 0x89, 0xeb, 0x5d, 0x36, 0x5c, 0xbb, 0x0c, 0xd8,
- 0x85, 0x90, 0xb6, 0x0c, 0xe8, 0xc5, 0xfe, 0xf5, 0xb7, 0x13, 0xf4, 0x0d,
- 0x94, 0xb9, 0x8b, 0xac, 0xd1, 0x1d, 0x41, 0x1e, 0x95, 0xf8, 0x24, 0x3f,
- 0x10, 0x97, 0xcd, 0x7e, 0x80, 0xeb, 0xe2, 0xd7, 0xd0, 0x15, 0xd2, 0x51,
- 0x54, 0xfe, 0x53, 0xc5, 0x2d, 0x85, 0xcf, 0xd8, 0xe2, 0x0b, 0x2a, 0xea,
- 0xb9, 0x6a, 0xd0, 0x37, 0x31, 0xfe, 0x51, 0x87, 0xbb, 0xe0, 0xff, 0xa0,
- 0x83, 0xb0, 0xe3, 0xdc, 0x3c, 0xef, 0x27, 0x86, 0x78, 0xaf, 0x74, 0x36,
- 0x0f, 0xd9, 0x2e, 0xf0, 0xfb, 0x63, 0x22, 0xa8, 0x31, 0x83, 0xfa, 0x2b,
- 0x45, 0x5f, 0x88, 0xb6, 0xa4, 0xfc, 0x64, 0x5e, 0x7d, 0x6f, 0x8c, 0x03,
- 0xc6, 0xa7, 0xef, 0x6c, 0xf8, 0x9b, 0x89, 0x1f, 0x64, 0x83, 0xbf, 0x99,
- 0x08, 0xbf, 0xfd, 0x56, 0x83, 0x3c, 0xe2, 0xe1, 0x9a, 0x29, 0x13, 0xb5,
- 0xe8, 0x6f, 0x28, 0x28, 0x07, 0xf8, 0xe6, 0x5a, 0x94, 0x3b, 0xf8, 0x41,
- 0x4d, 0xb3, 0x49, 0x96, 0x4b, 0x61, 0x4e, 0xc4, 0x1a, 0x80, 0x3c, 0xc4,
- 0x78, 0x31, 0xaa, 0x2f, 0x07, 0x20, 0x3f, 0xf0, 0x1c, 0x74, 0xbd, 0x3b,
- 0x1b, 0xd4, 0xb9, 0x25, 0xfa, 0xc5, 0xfe, 0xa8, 0xee, 0xdd, 0x25, 0xa5,
- 0x63, 0x7c, 0x1f, 0x93, 0x77, 0x66, 0x63, 0xea, 0x7d, 0x41, 0x62, 0xe1,
- 0x7b, 0x8e, 0xe3, 0x52, 0x50, 0xef, 0xab, 0x21, 0x3e, 0xd4, 0x69, 0x5f,
- 0x89, 0xc6, 0xa6, 0x76, 0xbc, 0x1e, 0xac, 0x9b, 0xac, 0x57, 0xe5, 0xf1,
- 0xfa, 0x2a, 0xce, 0xaf, 0x49, 0x6e, 0xbc, 0x28, 0xbb, 0x6d, 0x4b, 0xc5,
- 0x7d, 0x37, 0x4e, 0x1d, 0xa3, 0x7e, 0x8d, 0xa9, 0xba, 0xb3, 0x88, 0x7c,
- 0xa1, 0x30, 0xc2, 0x6f, 0x3c, 0xbf, 0xba, 0xab, 0x50, 0x4e, 0x5b, 0x59,
- 0xf9, 0xd0, 0x77, 0x4d, 0x8e, 0x45, 0x47, 0x3d, 0x74, 0xd7, 0xc3, 0xb5,
- 0x0b, 0x77, 0x05, 0x67, 0xc5, 0xfb, 0x1a, 0x61, 0x0d, 0xf5, 0x6d, 0xf6,
- 0x5f, 0x6f, 0x35, 0x65, 0xed, 0x56, 0xdf, 0xbf, 0xdf, 0xb1, 0xc4, 0x0d,
- 0x6b, 0x57, 0x4b, 0xd5, 0xae, 0xed, 0x2a, 0x07, 0x71, 0x47, 0x52, 0x5a,
- 0x1e, 0xf6, 0x7a, 0xc6, 0x43, 0x9d, 0xa3, 0xa7, 0x0f, 0xae, 0xea, 0x16,
- 0x62, 0x6e, 0x3a, 0x35, 0x27, 0x6e, 0x2f, 0xbf, 0x37, 0xcf, 0x38, 0x84,
- 0xd9, 0x19, 0xdc, 0x75, 0xdd, 0x34, 0xae, 0xfc, 0xac, 0x48, 0x18, 0x7b,
- 0x6e, 0x6a, 0xb4, 0x89, 0xc6, 0xdc, 0x92, 0xb6, 0x20, 0x13, 0x26, 0x68,
- 0x29, 0x95, 0xa3, 0x3c, 0x8d, 0x7f, 0x1b, 0xb0, 0x7a, 0xd7, 0xd3, 0xa0,
- 0x73, 0x1a, 0x74, 0xf2, 0x1c, 0xd3, 0xb5, 0x48, 0xe7, 0xa2, 0x5a, 0x81,
- 0x7d, 0xc4, 0x7c, 0x0f, 0x31, 0xdf, 0x43, 0xcc, 0xf7, 0x10, 0xf3, 0x3d,
- 0xc4, 0x7c, 0x0f, 0x31, 0xdf, 0x43, 0xcc, 0xf7, 0x10, 0xf3, 0xbd, 0xf1,
- 0x30, 0x4f, 0x7b, 0x62, 0x3d, 0x4f, 0x5b, 0xa9, 0xf3, 0x3b, 0x94, 0xa2,
- 0xa5, 0x58, 0x94, 0x20, 0xcf, 0x15, 0x9d, 0x39, 0x4d, 0x94, 0xe7, 0x5e,
- 0xfb, 0x9b, 0x48, 0xb0, 0x8e, 0x39, 0x1e, 0xd7, 0x15, 0x35, 0xdd, 0xe6,
- 0xba, 0x20, 0xcf, 0x63, 0x6d, 0xb5, 0x79, 0x0d, 0xf2, 0xb5, 0x0c, 0xfd,
- 0x19, 0xed, 0x22, 0x11, 0xd4, 0x8b, 0x99, 0xf3, 0xf7, 0xba, 0x88, 0xbf,
- 0x85, 0x9a, 0x8a, 0xc1, 0xbc, 0x17, 0xbc, 0x97, 0x7f, 0xb7, 0x00, 0x39,
- 0xf0, 0xdd, 0x7d, 0xac, 0x27, 0x0a, 0xb5, 0xa4, 0x14, 0x17, 0xa3, 0xfc,
- 0x07, 0xeb, 0xbc, 0x7d, 0x5a, 0xbe, 0x42, 0xd9, 0xea, 0x32, 0x9d, 0x00,
- 0x53, 0xec, 0xc6, 0xbc, 0xee, 0x4d, 0x55, 0x23, 0xad, 0xd4, 0x49, 0xcf,
- 0x7e, 0xd0, 0x16, 0xdd, 0xe3, 0x8a, 0x18, 0xb3, 0x09, 0xd1, 0x67, 0x91,
- 0xd3, 0xda, 0x43, 0xea, 0x6f, 0x1d, 0x7a, 0xb0, 0x8f, 0x3e, 0x3b, 0x10,
- 0xfd, 0x2d, 0x06, 0xeb, 0xae, 0xec, 0xc6, 0xfd, 0x2b, 0xcf, 0x91, 0x80,
- 0xbd, 0x7e, 0x69, 0x27, 0xce, 0x06, 0xb9, 0x5e, 0xde, 0xa1, 0xf2, 0x6e,
- 0xf8, 0xce, 0xd3, 0x43, 0xe9, 0x3e, 0xe9, 0xda, 0x25, 0x67, 0x86, 0x58,
- 0xa3, 0xb5, 0x01, 0x1f, 0x61, 0x79, 0xe7, 0xb4, 0x4b, 0x96, 0xe7, 0xe1,
- 0x5b, 0xe7, 0xd3, 0x0e, 0xff, 0xbe, 0x60, 0x01, 0x21, 0x6d, 0xa1, 0x3e,
- 0xd6, 0xc7, 0x98, 0xbc, 0x58, 0xa7, 0xae, 0xf4, 0x60, 0x7d, 0x3f, 0x74,
- 0x71, 0x1b, 0x6c, 0x48, 0xc7, 0xfe, 0x11, 0xee, 0xf7, 0x14, 0xee, 0x1e,
- 0xfb, 0xb7, 0x77, 0x2a, 0xdd, 0xd0, 0xd3, 0x56, 0x4a, 0x07, 0xed, 0x1f,
- 0xab, 0x2d, 0x1d, 0xe1, 0xf7, 0xc2, 0x69, 0xaf, 0xf1, 0xbb, 0xe1, 0x3e,
- 0xad, 0x50, 0xe1, 0xdf, 0x38, 0x0c, 0xc9, 0x21, 0x8b, 0x7f, 0xff, 0xb3,
- 0x4f, 0x7b, 0xa0, 0x4a, 0x18, 0x1b, 0x7d, 0xd6, 0xe1, 0xcb, 0xb0, 0xe5,
- 0xff, 0x29, 0xdc, 0xea, 0x62, 0xdb, 0x3a, 0xcb, 0xf0, 0xfb, 0x1d, 0xe7,
- 0xc7, 0x4d, 0xdd, 0xe4, 0x34, 0x71, 0x12, 0x27, 0xca, 0xc0, 0xc7, 0x39,
- 0x49, 0x3d, 0x39, 0xd5, 0x4e, 0xa2, 0x14, 0x22, 0x88, 0x84, 0xe5, 0xfc,
- 0xcc, 0x63, 0x14, 0x3c, 0xc8, 0xa6, 0x4e, 0x42, 0x55, 0x94, 0x74, 0x5b,
- 0x27, 0xee, 0xb8, 0x40, 0x5c, 0x80, 0x6a, 0x39, 0x69, 0xe9, 0x86, 0x3d,
- 0xa7, 0x5b, 0xba, 0x00, 0x57, 0x9e, 0xe3, 0xa4, 0x4d, 0xe7, 0xcc, 0x1a,
- 0x03, 0x69, 0x70, 0x41, 0x23, 0x33, 0x6d, 0xe3, 0x66, 0x37, 0x48, 0x5c,
- 0x57, 0x29, 0x83, 0x02, 0x6b, 0x2b, 0xb8, 0xe1, 0xef, 0xe2, 0xf0, 0x3c,
- 0xdf, 0x39, 0x76, 0xd3, 0xc0, 0x44, 0x24, 0xeb, 0x7c, 0xe7, 0x3b, 0xdf,
- 0xff, 0xf7, 0xbe, 0xcf, 0xfb, 0x9b, 0x6e, 0xb9, 0x08, 0x3a, 0xce, 0x8d,
- 0xb5, 0xfa, 0xfe, 0xd6, 0x0e, 0x9f, 0x87, 0x07, 0xfb, 0x7c, 0x19, 0xa5,
- 0x75, 0xc9, 0x9c, 0xd6, 0xa7, 0xbb, 0x0e, 0x7d, 0x7b, 0x16, 0x6b, 0x8a,
- 0xe0, 0x1c, 0x1e, 0xe9, 0xd3, 0x78, 0x64, 0xf0, 0xbd, 0xff, 0xd0, 0x7b,
- 0xdf, 0xa1, 0xf7, 0xde, 0xff, 0xd1, 0x9e, 0xe5, 0xc3, 0xf4, 0xc0, 0x75,
- 0x5a, 0x53, 0x1a, 0xfd, 0xf2, 0x93, 0x6a, 0x39, 0x6f, 0x25, 0xa9, 0x0b,
- 0xcc, 0x88, 0xab, 0x66, 0x9c, 0x36, 0x60, 0x5c, 0x9b, 0xac, 0xae, 0x83,
- 0xe6, 0xb1, 0x8f, 0x76, 0x9b, 0xf1, 0xf2, 0x89, 0x3e, 0xf2, 0x4c, 0x10,
- 0xd7, 0x60, 0xd8, 0xc3, 0x11, 0xb4, 0x73, 0x5f, 0x74, 0x12, 0xe6, 0x39,
- 0xed, 0xbf, 0xa1, 0x0e, 0xe3, 0xaa, 0x9c, 0xce, 0xfd, 0x60, 0x9b, 0x16,
- 0xb9, 0x6d, 0xa7, 0xba, 0xfd, 0xdc, 0x20, 0xd8, 0xbb, 0xa9, 0x3e, 0xea,
- 0x17, 0x2f, 0x38, 0xcd, 0x3a, 0x73, 0x5f, 0x98, 0x77, 0x05, 0xa2, 0x79,
- 0x4a, 0xa4, 0x54, 0x11, 0xb9, 0x86, 0xdf, 0x6f, 0x2a, 0x7e, 0xfc, 0x42,
- 0xd1, 0xd6, 0x9e, 0x96, 0x1b, 0xc5, 0x2f, 0x48, 0x15, 0x32, 0x67, 0xc7,
- 0x71, 0xdd, 0x3b, 0x4e, 0x54, 0x9f, 0xf9, 0x0f, 0xf2, 0x4a, 0x62, 0xe3,
- 0x94, 0x69, 0x6d, 0xf2, 0xc3, 0x75, 0xe6, 0xd5, 0x59, 0xe6, 0x1d, 0x61,
- 0x7e, 0x5b, 0x44, 0xd2, 0xe1, 0x80, 0xd6, 0x4b, 0xe5, 0x69, 0x68, 0x12,
- 0xf8, 0xf6, 0x87, 0xf5, 0xb3, 0x7d, 0xf4, 0xb9, 0x7c, 0xbc, 0xce, 0x77,
- 0x03, 0x4f, 0x43, 0xea, 0x76, 0x00, 0xfa, 0x2b, 0x80, 0xc7, 0xe4, 0xb9,
- 0x73, 0xbf, 0xcf, 0x73, 0x6d, 0xa8, 0xa3, 0x0d, 0xdb, 0x26, 0xb9, 0x11,
- 0xe0, 0xa0, 0x1a, 0xd6, 0xf9, 0x47, 0xf5, 0xb0, 0xc6, 0xe5, 0x40, 0x99,
- 0x7e, 0x7b, 0xf3, 0xa8, 0xc6, 0xe8, 0xd4, 0xee, 0xf7, 0xf4, 0x5e, 0x50,
- 0xce, 0x96, 0x1d, 0xd2, 0xaa, 0x29, 0x3b, 0xe0, 0xb5, 0xeb, 0xb5, 0x37,
- 0xfa, 0x79, 0x57, 0x37, 0x6a, 0xdf, 0xef, 0xf3, 0x6c, 0x34, 0xd6, 0x5d,
- 0xe8, 0xf3, 0xea, 0xa2, 0xbe, 0xcd, 0x45, 0xdb, 0xac, 0x84, 0xbd, 0x7d,
- 0x5b, 0x6a, 0x1b, 0xdf, 0x95, 0x77, 0x8b, 0xdf, 0x91, 0x5f, 0x6c, 0x9c,
- 0x81, 0xce, 0x61, 0x95, 0xb2, 0x90, 0x27, 0x6f, 0xd7, 0x5c, 0xf7, 0x6d,
- 0x67, 0x01, 0xf6, 0x81, 0xeb, 0xfe, 0xd6, 0xd9, 0x93, 0xd8, 0xc4, 0x37,
- 0xb1, 0xe7, 0x0c, 0x78, 0x88, 0x58, 0x98, 0x06, 0xbd, 0x7d, 0xb1, 0x5f,
- 0x3a, 0x42, 0x9a, 0x4e, 0x86, 0x27, 0x5a, 0xb1, 0x07, 0xc3, 0xd7, 0xc3,
- 0xb9, 0x97, 0xe9, 0x7e, 0xd2, 0x8c, 0x51, 0xfb, 0x09, 0xe6, 0x6f, 0x05,
- 0x5f, 0x1c, 0xc5, 0x4f, 0xc9, 0x9d, 0x71, 0xac, 0x75, 0x9c, 0xb4, 0xd7,
- 0x2a, 0xb1, 0xc7, 0xb0, 0x8f, 0x4c, 0x8b, 0xdc, 0xcb, 0x6f, 0xf6, 0xd1,
- 0x9f, 0x77, 0x2f, 0xcf, 0xb2, 0xf1, 0xb9, 0x4e, 0x71, 0xa5, 0x05, 0xf2,
- 0x7b, 0x75, 0xd2, 0xd3, 0x95, 0x7e, 0xad, 0x4e, 0xa0, 0xbd, 0x9d, 0x7d,
- 0x4f, 0x51, 0xb7, 0xcb, 0xba, 0xad, 0xd0, 0xc5, 0xe7, 0xa0, 0x03, 0xa5,
- 0x6a, 0x17, 0xa4, 0x3e, 0x1e, 0x42, 0x1b, 0xea, 0x28, 0x1a, 0x4b, 0x64,
- 0x26, 0xcf, 0x7c, 0x2d, 0xe6, 0x4e, 0x61, 0x8d, 0x0b, 0xc4, 0x0d, 0xae,
- 0xb1, 0x8d, 0x31, 0x38, 0xbf, 0xce, 0x06, 0x8d, 0xb0, 0x8e, 0xf4, 0x9d,
- 0x04, 0x4f, 0x26, 0x29, 0x37, 0x31, 0xde, 0x18, 0xc6, 0x63, 0xb9, 0x13,
- 0xe3, 0x5d, 0x90, 0x94, 0xd3, 0x18, 0x73, 0x0a, 0x6d, 0x88, 0x33, 0x53,
- 0xd0, 0x1f, 0x86, 0xd4, 0xec, 0x7a, 0x18, 0xf2, 0xbb, 0x4f, 0x66, 0xcd,
- 0x23, 0x07, 0xf6, 0x98, 0xd5, 0xf6, 0x81, 0x61, 0x8c, 0xf9, 0x6b, 0xea,
- 0x3c, 0xb0, 0x26, 0xf6, 0xc7, 0x0f, 0xb6, 0x71, 0x6a, 0x7d, 0x0d, 0x38,
- 0xb5, 0xf6, 0x61, 0xca, 0x39, 0x2b, 0x33, 0x61, 0xae, 0x89, 0xf5, 0x61,
- 0xac, 0x99, 0x7e, 0xac, 0x67, 0x81, 0x43, 0x47, 0xfc, 0x3a, 0xb6, 0x15,
- 0x23, 0x85, 0xb3, 0xf7, 0xec, 0x5a, 0xd6, 0x7d, 0x56, 0x52, 0x6b, 0x19,
- 0x99, 0xd7, 0xfd, 0x78, 0x86, 0x83, 0x5a, 0xf7, 0x20, 0xaf, 0xc6, 0x7a,
- 0x70, 0x96, 0x89, 0x07, 0x36, 0x70, 0xb4, 0x47, 0xcb, 0xcc, 0x7e, 0x8f,
- 0x67, 0xf1, 0xad, 0x87, 0x77, 0xd4, 0x26, 0xb1, 0x6f, 0x40, 0x46, 0xe6,
- 0x1b, 0xf5, 0x21, 0xf9, 0x24, 0xdf, 0xd1, 0xcf, 0x38, 0xcb, 0xdd, 0xbc,
- 0x29, 0x1f, 0xe7, 0x75, 0x2c, 0x74, 0x31, 0x20, 0xd6, 0x79, 0xcf, 0x3e,
- 0x1f, 0x59, 0x5c, 0x55, 0xfc, 0x3e, 0x72, 0x7e, 0x4b, 0x05, 0xd1, 0x36,
- 0x84, 0x76, 0x5c, 0x87, 0x29, 0x73, 0xf9, 0xbf, 0xb9, 0x4b, 0xa3, 0xae,
- 0x3b, 0xaf, 0xf3, 0xc3, 0x12, 0xe6, 0xaa, 0x6a, 0xe8, 0xe4, 0x71, 0xc9,
- 0x87, 0xdb, 0x31, 0x57, 0xc2, 0xdc, 0x52, 0x23, 0x58, 0x0f, 0xcb, 0x3d,
- 0xe4, 0x89, 0xc8, 0x9e, 0x70, 0x7c, 0x2b, 0xbd, 0xa9, 0x12, 0xd1, 0x61,
- 0x65, 0x25, 0x73, 0xf8, 0xb5, 0x28, 0x1d, 0x47, 0x8c, 0x44, 0x15, 0x78,
- 0x17, 0x7b, 0xb2, 0x4f, 0xba, 0x6e, 0xda, 0x66, 0x7d, 0xc2, 0x0c, 0x29,
- 0xfa, 0x5b, 0x3a, 0x74, 0xbc, 0xf1, 0x72, 0x6f, 0xc2, 0x3c, 0xa9, 0x8e,
- 0xfb, 0xef, 0x53, 0xc0, 0xcc, 0xe6, 0x78, 0x67, 0x36, 0x95, 0x29, 0x2f,
- 0xe5, 0x13, 0xd1, 0x65, 0x65, 0x65, 0x30, 0x66, 0x66, 0x56, 0x11, 0x37,
- 0x12, 0x66, 0x87, 0xa2, 0x4f, 0xb4, 0x5d, 0xef, 0x3b, 0x8d, 0xfe, 0x09,
- 0xd5, 0xe2, 0xaf, 0x87, 0xf7, 0xf5, 0xe3, 0x7e, 0x8f, 0x67, 0x88, 0x39,
- 0xa3, 0xc0, 0x4c, 0xe6, 0x9a, 0xe9, 0xdc, 0x86, 0x64, 0x6c, 0x62, 0x54,
- 0x63, 0xe8, 0xfd, 0x53, 0x7f, 0x47, 0x1d, 0xca, 0x25, 0xd6, 0xc5, 0x7d,
- 0x7e, 0x1b, 0xd5, 0x3a, 0xf3, 0xfd, 0x53, 0x59, 0x9d, 0xc7, 0x58, 0x57,
- 0x31, 0x7f, 0xdf, 0xcd, 0x3b, 0x8b, 0xa6, 0x9c, 0x47, 0x38, 0xce, 0x5a,
- 0x60, 0xba, 0x5d, 0x98, 0x23, 0x3a, 0x57, 0x6c, 0xd0, 0x06, 0xfd, 0x01,
- 0xcc, 0x17, 0x68, 0xc4, 0xbd, 0x2f, 0x88, 0x31, 0x11, 0x3c, 0x40, 0x27,
- 0xd0, 0x35, 0xa1, 0xa3, 0x56, 0x30, 0x4e, 0x6e, 0x5d, 0xb2, 0x5e, 0x7f,
- 0x09, 0x32, 0x27, 0x35, 0x57, 0xf9, 0xb4, 0x31, 0x38, 0x37, 0xe6, 0xc0,
- 0xfb, 0xfd, 0x53, 0xa4, 0x4f, 0x9e, 0x4d, 0x54, 0xcd, 0x6d, 0x70, 0x3d,
- 0x83, 0x32, 0xbf, 0x3e, 0x24, 0xcb, 0xf8, 0xad, 0xae, 0x7b, 0xf7, 0xb6,
- 0x0d, 0xdd, 0x7a, 0x3e, 0x6f, 0x6a, 0x7e, 0x5d, 0x76, 0x18, 0x33, 0x01,
- 0xaf, 0xe8, 0x9c, 0x2a, 0xf6, 0x65, 0x5e, 0xe1, 0x10, 0xe5, 0xa3, 0x53,
- 0x87, 0x5c, 0xdd, 0xae, 0x51, 0x4f, 0x65, 0xbd, 0x35, 0x15, 0x0d, 0x74,
- 0xc9, 0x2a, 0xf0, 0xae, 0x0c, 0xd9, 0x99, 0x7b, 0x25, 0x24, 0xcb, 0x79,
- 0x1d, 0x4f, 0x8e, 0xfe, 0x5e, 0x39, 0x52, 0xad, 0x4d, 0xca, 0x6e, 0x2d,
- 0xae, 0xbf, 0x51, 0xae, 0xe5, 0x5e, 0x37, 0xe4, 0xf9, 0x51, 0x9d, 0x57,
- 0x17, 0x2f, 0x4b, 0xef, 0x00, 0x75, 0x9e, 0x2d, 0x9d, 0x63, 0x07, 0xec,
- 0x80, 0xce, 0xf1, 0x33, 0xe8, 0x1c, 0xef, 0x40, 0xe7, 0xf8, 0x69, 0x11,
- 0xf8, 0x52, 0x4c, 0xfb, 0xf8, 0xbf, 0x08, 0x1c, 0xa2, 0xac, 0xb6, 0xce,
- 0xe0, 0x4e, 0x17, 0xb3, 0xa0, 0xc1, 0x5b, 0x92, 0x06, 0xde, 0xa6, 0xe4,
- 0xfa, 0xc6, 0xbc, 0xec, 0x6c, 0x78, 0x79, 0xc8, 0x1f, 0x30, 0x07, 0x6c,
- 0x9c, 0xf7, 0x14, 0x07, 0x0e, 0x1d, 0x91, 0xd8, 0x49, 0xe2, 0x47, 0x50,
- 0x36, 0x0b, 0xef, 0x68, 0x1c, 0xda, 0x2c, 0xb0, 0x1c, 0x10, 0x9d, 0x4f,
- 0xb6, 0xb0, 0x27, 0x65, 0xe7, 0x97, 0xa8, 0x3f, 0xa6, 0x7d, 0x40, 0x9e,
- 0x4f, 0x9e, 0x78, 0xf9, 0x67, 0xff, 0xee, 0x95, 0xce, 0xb3, 0x5b, 0x32,
- 0xbb, 0xd0, 0xae, 0x81, 0x5d, 0xc3, 0x5e, 0xcc, 0x5b, 0xfd, 0x05, 0x6d,
- 0x30, 0x47, 0xb1, 0x4b, 0xb6, 0x21, 0x43, 0xea, 0xf1, 0x2e, 0xad, 0xfb,
- 0xd5, 0xe3, 0x43, 0x3a, 0x17, 0x97, 0xe3, 0xe4, 0x0a, 0xb6, 0xac, 0x14,
- 0xac, 0x68, 0x16, 0xf4, 0xb7, 0x0b, 0x5b, 0xed, 0x3a, 0xee, 0x60, 0x07,
- 0x67, 0x70, 0xa3, 0x46, 0x39, 0x7f, 0x57, 0x63, 0xef, 0x66, 0xed, 0x4f,
- 0x18, 0xc7, 0x3a, 0x93, 0x94, 0x3f, 0xf6, 0x13, 0x03, 0xe9, 0x8f, 0x9a,
- 0xd1, 0xfd, 0xbd, 0x7e, 0xd7, 0xd1, 0x76, 0xa7, 0x46, 0x3c, 0x16, 0xb9,
- 0x94, 0xb7, 0x21, 0x4b, 0x5e, 0x8f, 0x50, 0x07, 0x28, 0xa9, 0x46, 0x3f,
- 0xd7, 0x5f, 0xb3, 0xeb, 0x1e, 0xb5, 0xb9, 0xae, 0xb8, 0x8f, 0xdb, 0x94,
- 0xfd, 0x7b, 0x5a, 0xee, 0xe7, 0x8b, 0x67, 0xe5, 0x2d, 0xdc, 0xb7, 0xa7,
- 0xe3, 0x64, 0xe4, 0x4d, 0xe8, 0x78, 0xb5, 0x62, 0x23, 0x6f, 0x7b, 0x1a,
- 0xe7, 0x64, 0xa9, 0x95, 0x2b, 0x2f, 0xcb, 0xe5, 0xab, 0xfb, 0xea, 0xa5,
- 0xab, 0x31, 0xf5, 0xf2, 0x95, 0x61, 0x95, 0xbb, 0xe2, 0xba, 0xff, 0x74,
- 0x96, 0xe4, 0xdd, 0x0d, 0x57, 0x4e, 0x3b, 0xc6, 0x40, 0x40, 0x1a, 0xb9,
- 0x75, 0xae, 0x1b, 0x04, 0x36, 0xdf, 0xe8, 0x75, 0xdd, 0x47, 0xc7, 0xc7,
- 0x25, 0xde, 0x4b, 0x1d, 0xe5, 0xf3, 0x11, 0xe6, 0xbb, 0x12, 0x73, 0x52,
- 0xb6, 0x7d, 0xbe, 0xac, 0x14, 0xf0, 0xad, 0xcb, 0xd3, 0x5f, 0x1e, 0x3b,
- 0xe6, 0xc7, 0x4a, 0x7e, 0xf4, 0x22, 0x7d, 0xc9, 0x91, 0xff, 0xf2, 0x25,
- 0x9b, 0x72, 0xae, 0xf0, 0x19, 0xf4, 0x0f, 0xcb, 0xb7, 0x0a, 0xa1, 0x43,
- 0x65, 0x13, 0xcf, 0x31, 0x95, 0x2b, 0xdc, 0x73, 0x87, 0x75, 0xcc, 0x00,
- 0x3a, 0x89, 0xe9, 0xba, 0xcb, 0x0e, 0xe7, 0xeb, 0xc2, 0x7c, 0x7b, 0xe6,
- 0x31, 0xc8, 0xff, 0xd3, 0x5a, 0x3e, 0x9f, 0x53, 0xb0, 0x7d, 0xc1, 0xdf,
- 0x61, 0x99, 0x2d, 0x40, 0xc6, 0x2b, 0xe6, 0x9c, 0x52, 0x57, 0xb0, 0x22,
- 0xcb, 0xc0, 0x8e, 0x25, 0xe0, 0xcd, 0x93, 0x3a, 0xb6, 0xda, 0xa3, 0xb1,
- 0x67, 0x85, 0xe5, 0x8c, 0x24, 0xcb, 0x4e, 0xb7, 0x3e, 0xbf, 0xfd, 0xdd,
- 0x57, 0x23, 0xde, 0x9d, 0x83, 0x8f, 0x33, 0x4a, 0xda, 0x60, 0x03, 0xcd,
- 0x6c, 0x2d, 0x80, 0x27, 0x22, 0x38, 0xdb, 0x56, 0xcd, 0x0f, 0x75, 0xc8,
- 0xef, 0xba, 0xf6, 0x23, 0x7a, 0xf1, 0x8a, 0xba, 0xc9, 0x76, 0xcf, 0xa0,
- 0x5f, 0xbb, 0xa4, 0xae, 0xb4, 0x69, 0x5c, 0x7d, 0xb8, 0x2e, 0x09, 0x3d,
- 0xe4, 0x69, 0x94, 0x03, 0xa8, 0x8b, 0xfa, 0x65, 0x03, 0xe5, 0x45, 0x94,
- 0x5b, 0xf0, 0x64, 0x9b, 0x11, 0xe8, 0x15, 0x78, 0xbe, 0x81, 0xf1, 0xc6,
- 0xb1, 0xe6, 0x8c, 0x29, 0x1f, 0x9d, 0xa2, 0x2c, 0x19, 0x53, 0xcc, 0x4b,
- 0x5e, 0xb6, 0xf1, 0xac, 0x0e, 0xab, 0x99, 0x35, 0x96, 0xf1, 0x2c, 0x79,
- 0xdf, 0x1f, 0xc2, 0x24, 0xf4, 0x49, 0x5d, 0xf5, 0x30, 0xe9, 0xa3, 0x26,
- 0x26, 0xb1, 0xae, 0x5d, 0x66, 0xaf, 0x90, 0xd7, 0x4d, 0xd0, 0x5b, 0x87,
- 0xcc, 0x5c, 0x0d, 0x6b, 0x7d, 0xb4, 0x0c, 0x5a, 0xdc, 0x06, 0x5d, 0x6d,
- 0x82, 0xa6, 0x52, 0x05, 0x6b, 0x6a, 0x51, 0x45, 0xb5, 0x2f, 0xe0, 0x09,
- 0xd0, 0x6b, 0xf0, 0x15, 0xea, 0xa2, 0xe4, 0xe5, 0x38, 0x68, 0x4f, 0xdc,
- 0xa0, 0x6d, 0xa7, 0xe3, 0xca, 0x06, 0x0d, 0x82, 0x2e, 0x0b, 0x1e, 0x4f,
- 0xbf, 0xa7, 0x34, 0xae, 0x4e, 0xdd, 0x96, 0x44, 0xf2, 0xb6, 0x58, 0xc0,
- 0x02, 0xcb, 0xf9, 0x50, 0x1c, 0x8c, 0x39, 0x29, 0xd7, 0x30, 0x8f, 0x01,
- 0xfe, 0x1e, 0x3d, 0xa1, 0xf9, 0x7b, 0x4a, 0x02, 0x87, 0x79, 0x1c, 0xf4,
- 0x06, 0x0c, 0xf2, 0x78, 0x3a, 0xe9, 0xd3, 0xe8, 0xd7, 0xc1, 0xbf, 0x16,
- 0x2c, 0xb1, 0xb0, 0xac, 0x82, 0xff, 0xb7, 0xf1, 0xfd, 0x66, 0x6d, 0x44,
- 0xad, 0xac, 0x29, 0x3f, 0x97, 0xe4, 0x19, 0xe8, 0xc9, 0xb7, 0x70, 0x76,
- 0x9d, 0x5a, 0x77, 0x8f, 0x8d, 0x33, 0x7e, 0x96, 0x56, 0x97, 0xed, 0x93,
- 0xb2, 0x3f, 0x36, 0x89, 0xf2, 0x31, 0x3c, 0x0d, 0x9c, 0x43, 0x48, 0xc7,
- 0xbf, 0x37, 0xf3, 0x8e, 0xf2, 0xfe, 0x67, 0x61, 0x42, 0xe7, 0xe7, 0x1b,
- 0x76, 0x2f, 0xbe, 0xd3, 0x17, 0xc3, 0xbd, 0x41, 0x67, 0x52, 0x11, 0x9d,
- 0x6f, 0x5a, 0x86, 0x2e, 0xb1, 0x85, 0xf1, 0xde, 0xa7, 0x2f, 0xaf, 0x0a,
- 0x1e, 0x1e, 0xfb, 0x97, 0x9b, 0x0c, 0x33, 0x47, 0xfd, 0x6e, 0xc4, 0x93,
- 0x7f, 0x9f, 0xb8, 0xfb, 0xf6, 0xca, 0x94, 0x81, 0x97, 0x5b, 0x66, 0x18,
- 0x6d, 0x21, 0xcb, 0x20, 0x8b, 0x4a, 0x9a, 0x7e, 0xd9, 0xce, 0xeb, 0x9b,
- 0xab, 0x26, 0xcc, 0x0f, 0xc4, 0xeb, 0xbb, 0x6a, 0x53, 0xee, 0xb4, 0x03,
- 0x5f, 0xa2, 0x5a, 0xaf, 0x7c, 0xdf, 0xce, 0x02, 0x15, 0xac, 0x68, 0x1a,
- 0x34, 0xda, 0x26, 0x56, 0x7c, 0x4e, 0x1e, 0xcc, 0xbb, 0xac, 0xfb, 0xb2,
- 0x6d, 0xa3, 0x6f, 0x63, 0x5e, 0xae, 0x9f, 0x7b, 0xe1, 0x1e, 0xe8, 0x9b,
- 0x36, 0x35, 0x8d, 0xd6, 0xab, 0xdd, 0x03, 0x1e, 0x8d, 0x36, 0xf6, 0x11,
- 0xfe, 0x3f, 0xfb, 0x20, 0x9d, 0x38, 0xca, 0xcb, 0xbb, 0xc0, 0xb3, 0xca,
- 0xf3, 0x1c, 0x01, 0x6d, 0x1c, 0xa4, 0x9f, 0x86, 0x6f, 0xd1, 0xa3, 0x9f,
- 0x47, 0x9b, 0xf4, 0x43, 0xba, 0xe9, 0x90, 0xd9, 0xab, 0xb6, 0xcc, 0x17,
- 0xf4, 0x7d, 0x43, 0xd7, 0xa4, 0xcf, 0x68, 0x12, 0x74, 0x43, 0x5a, 0x27,
- 0x6f, 0x99, 0x52, 0x02, 0x1d, 0x95, 0x80, 0x4f, 0x25, 0xd0, 0x54, 0x19,
- 0xf8, 0x56, 0x02, 0xbe, 0x95, 0x6a, 0x56, 0xbc, 0x82, 0x3d, 0x53, 0x66,
- 0x6f, 0x81, 0x8e, 0xb6, 0x6b, 0xbc, 0x7f, 0xbd, 0x66, 0x93, 0x72, 0xf0,
- 0x66, 0xf3, 0xee, 0xff, 0x81, 0xbb, 0x1f, 0x92, 0x5d, 0xd8, 0x2d, 0x6f,
- 0x15, 0xc7, 0x80, 0x49, 0x02, 0x8c, 0x72, 0x40, 0x1b, 0x53, 0x72, 0xbd,
- 0x38, 0x2d, 0x3b, 0x90, 0x4f, 0x37, 0x36, 0x62, 0xd0, 0xa7, 0x23, 0xb2,
- 0xf2, 0xda, 0xa8, 0xbc, 0xb9, 0xa1, 0x64, 0x09, 0xf4, 0x9b, 0xdb, 0xa4,
- 0xdf, 0x1d, 0xf4, 0x5c, 0xea, 0xd0, 0x71, 0xfa, 0xd9, 0x8a, 0xe7, 0x7f,
- 0x9f, 0xab, 0x74, 0xca, 0x7c, 0xc5, 0x94, 0xc7, 0x2b, 0xdd, 0xf2, 0xe5,
- 0x4a, 0x58, 0x4e, 0xc3, 0x0e, 0xfc, 0x4a, 0x65, 0x50, 0x9e, 0xac, 0x0c,
- 0xc9, 0x57, 0xab, 0x51, 0xf9, 0x5a, 0xd5, 0x96, 0x4c, 0x35, 0x2e, 0xe9,
- 0xea, 0x98, 0x3c, 0x51, 0xa5, 0x5f, 0x1d, 0xf3, 0xe1, 0x37, 0xd3, 0xf4,
- 0x57, 0x70, 0x5d, 0x41, 0xac, 0x2b, 0xae, 0xe6, 0x74, 0x9c, 0x52, 0x32,
- 0x9e, 0xcf, 0x43, 0xe4, 0x39, 0x8c, 0x75, 0xf1, 0x35, 0x25, 0x65, 0x3d,
- 0x7f, 0xe3, 0xff, 0x46, 0x42, 0xda, 0x36, 0x7a, 0xae, 0x34, 0x88, 0x36,
- 0x90, 0x7b, 0xf9, 0x86, 0xef, 0xa3, 0xe1, 0xf3, 0x6f, 0xd8, 0x5e, 0x86,
- 0xf6, 0x5b, 0xdf, 0xa4, 0xed, 0xa5, 0xcf, 0x9e, 0xf8, 0x41, 0x3b, 0xe7,
- 0x9a, 0xf6, 0x9b, 0x3c, 0x88, 0x6d, 0x34, 0xe6, 0xbd, 0x98, 0x79, 0xf8,
- 0xff, 0x53, 0xbc, 0x18, 0xd5, 0xb9, 0xea, 0x20, 0xff, 0x4f, 0x05, 0x6b,
- 0xf9, 0xf4, 0xdc, 0xf1, 0xf9, 0xe2, 0xac, 0x7a, 0xbc, 0x48, 0x8d, 0xc6,
- 0x95, 0x8b, 0xcd, 0x9c, 0xb8, 0x2f, 0xc9, 0xa6, 0x13, 0xd2, 0x6b, 0xf0,
- 0xf3, 0x1f, 0x75, 0x7e, 0xdc, 0xec, 0x09, 0xd2, 0x1f, 0x63, 0x6f, 0x9d,
- 0x7e, 0x3c, 0x01, 0xba, 0xad, 0x63, 0xca, 0xa5, 0x8a, 0xe7, 0xb3, 0x5a,
- 0xd1, 0xf4, 0xf2, 0x2b, 0xd0, 0x1c, 0x63, 0x0e, 0xde, 0x33, 0x5b, 0xf2,
- 0xfa, 0xce, 0xe0, 0xde, 0x60, 0x8f, 0x63, 0xbf, 0x46, 0x37, 0xe7, 0xe2,
- 0xff, 0xe9, 0xa0, 0xec, 0xaf, 0x97, 0xb9, 0xc6, 0xb6, 0xa6, 0x45, 0x2f,
- 0xae, 0x1b, 0x97, 0x17, 0x70, 0x7e, 0x65, 0x93, 0xeb, 0x0f, 0x4a, 0x39,
- 0x4e, 0xdb, 0x96, 0xf8, 0x7d, 0x42, 0x4a, 0x98, 0xa7, 0x1c, 0x6f, 0xf8,
- 0xc3, 0x3c, 0x9c, 0x2d, 0x9b, 0x0f, 0xe6, 0x5d, 0x2c, 0x1d, 0xc7, 0x3b,
- 0xea, 0xe2, 0xd0, 0x99, 0x16, 0xf8, 0x7e, 0x11, 0x65, 0xfa, 0x46, 0x56,
- 0xf0, 0x8c, 0xf8, 0x75, 0xd5, 0x01, 0xad, 0xab, 0x4f, 0x3f, 0xe8, 0xb7,
- 0x54, 0xb2, 0xb2, 0xa9, 0x40, 0x42, 0x19, 0xaf, 0xfe, 0x7c, 0x80, 0x98,
- 0x7b, 0xdc, 0xe6, 0x2f, 0x24, 0x7f, 0x35, 0xb5, 0x4f, 0xc1, 0xff, 0x76,
- 0x44, 0x9e, 0x32, 0x99, 0xc7, 0x9e, 0x54, 0xb3, 0xc5, 0x9c, 0x9f, 0xe3,
- 0x9b, 0x50, 0xc7, 0xcb, 0x37, 0x07, 0xbc, 0x9c, 0x77, 0x8e, 0x7d, 0x30,
- 0xcf, 0xfd, 0x20, 0x9d, 0x30, 0xdf, 0xbd, 0xbd, 0xf9, 0x3f, 0x52, 0xe5,
- 0x3c, 0xf0, 0xce, 0x6e, 0xd1, 0xfc, 0x98, 0xab, 0xfe, 0xdb, 0xdd, 0xd3,
- 0xfc, 0xdc, 0xf0, 0x31, 0xfc, 0x6e, 0x80, 0xb6, 0x2d, 0x71, 0xe3, 0x92,
- 0x97, 0x3b, 0xaa, 0x6d, 0x68, 0x60, 0x05, 0xea, 0xc8, 0xab, 0xe0, 0x93,
- 0x66, 0x5b, 0xfe, 0xfd, 0x07, 0x69, 0x3f, 0x51, 0x42, 0x6c, 0x67, 0x00,
- 0x00, 0x00 };
+ 0xec, 0x5c, 0x7d, 0x6c, 0x1c, 0xc7, 0x75, 0x7f, 0x3b, 0xbb, 0xa4, 0x8e,
+ 0xd4, 0x91, 0x5c, 0x1e, 0x4f, 0xcc, 0x51, 0xa6, 0xed, 0x5b, 0x71, 0x25,
+ 0x9e, 0x4d, 0xc6, 0x59, 0xd1, 0x07, 0x9b, 0x28, 0x0e, 0xc9, 0x66, 0xef,
+ 0x24, 0xb1, 0x86, 0x5b, 0x53, 0x35, 0x1d, 0x1b, 0x6d, 0xea, 0xb2, 0x47,
+ 0xb5, 0x29, 0x8c, 0x06, 0x90, 0xbf, 0x00, 0x17, 0xa8, 0xe4, 0xcb, 0x91,
+ 0x8a, 0x55, 0xf7, 0xc0, 0xbd, 0xc8, 0x8c, 0x18, 0x20, 0x6e, 0x7d, 0x25,
+ 0x29, 0x4a, 0x08, 0x0e, 0x3a, 0xa6, 0x71, 0x1a, 0xfd, 0x61, 0xd7, 0x04,
+ 0x2b, 0x1b, 0x6e, 0x91, 0xd6, 0x72, 0xe3, 0xb6, 0x46, 0x50, 0x04, 0x84,
+ 0xec, 0x34, 0x6e, 0xd0, 0x0f, 0xa1, 0x2e, 0x6c, 0x03, 0x96, 0xbd, 0xfd,
+ 0xbd, 0xd9, 0x5d, 0xf2, 0x48, 0x5b, 0x76, 0xd0, 0x3f, 0xfa, 0x4f, 0x77,
+ 0x80, 0xc3, 0xce, 0xcc, 0xbe, 0xf7, 0xe6, 0xcd, 0x9b, 0xf7, 0x39, 0x4b,
+ 0xe9, 0xb7, 0xe3, 0xd4, 0x4e, 0x41, 0xeb, 0xc0, 0x2f, 0x7d, 0xf4, 0xb1,
+ 0x87, 0x6e, 0xb9, 0xfd, 0x96, 0x5b, 0xd1, 0xdd, 0xaf, 0x2a, 0x3b, 0xd4,
+ 0x70, 0x3e, 0x6a, 0x51, 0x8b, 0x5a, 0xd4, 0xa2, 0x16, 0xb5, 0xa8, 0x45,
+ 0x2d, 0x6a, 0x51, 0x8b, 0x5a, 0xd4, 0xa2, 0x16, 0xb5, 0xa8, 0x45, 0x2d,
+ 0x6a, 0x51, 0x8b, 0x5a, 0xd4, 0xa2, 0x16, 0xb5, 0xa8, 0x45, 0x2d, 0x6a,
+ 0x51, 0x8b, 0x5a, 0xd4, 0xa2, 0x16, 0xb5, 0xa8, 0x45, 0x2d, 0x6a, 0x51,
+ 0x8b, 0x5a, 0xd4, 0xa2, 0x16, 0xb5, 0xa8, 0x45, 0x2d, 0x6a, 0x51, 0x8b,
+ 0x5a, 0xd4, 0xa2, 0x16, 0xb5, 0xa8, 0x45, 0xed, 0xff, 0x7b, 0x53, 0x89,
+ 0x74, 0x7e, 0x76, 0x04, 0x3f, 0x8a, 0x89, 0x5c, 0xfa, 0x01, 0xc7, 0xa4,
+ 0x98, 0x9a, 0xeb, 0x3f, 0x3e, 0x65, 0x12, 0xd9, 0xf5, 0xa1, 0x74, 0x9e,
+ 0x3e, 0xf0, 0x4a, 0x49, 0x8d, 0x78, 0xfe, 0xfa, 0xdc, 0xd5, 0x67, 0x9e,
+ 0xbf, 0xdd, 0xb8, 0x52, 0x53, 0x29, 0xa6, 0xe7, 0x66, 0xf6, 0xeb, 0xfb,
+ 0x28, 0xd6, 0x0f, 0x9c, 0xa7, 0x07, 0xff, 0xb1, 0x93, 0x3a, 0x43, 0x5a,
+ 0x44, 0x0b, 0x15, 0xc3, 0x3a, 0x88, 0xe7, 0x72, 0x7d, 0xc8, 0x5a, 0x23,
+ 0x8d, 0x56, 0x75, 0x7f, 0xc5, 0x72, 0x45, 0x61, 0x3a, 0x54, 0xae, 0xc7,
+ 0x68, 0x5d, 0xfe, 0x3b, 0x0f, 0xac, 0x69, 0x72, 0xff, 0x82, 0xe2, 0x34,
+ 0x3c, 0xef, 0x8c, 0xe5, 0x79, 0x2f, 0xe1, 0xf7, 0x33, 0x0b, 0x63, 0xf7,
+ 0x43, 0xcf, 0xd6, 0x54, 0x12, 0xe6, 0x1f, 0x2b, 0xce, 0x62, 0x2b, 0x95,
+ 0xe7, 0x89, 0xa6, 0xdd, 0x18, 0x9d, 0x74, 0x4b, 0x4a, 0xa1, 0x51, 0x51,
+ 0x0e, 0x9c, 0x9d, 0x55, 0x0e, 0x9e, 0x3d, 0xa9, 0x1c, 0x3a, 0x5b, 0x55,
+ 0x9c, 0xb3, 0x54, 0x12, 0xfb, 0xe3, 0x64, 0xeb, 0xe7, 0x94, 0x7c, 0xa3,
+ 0x57, 0x71, 0xe6, 0xaf, 0x7a, 0x8e, 0x65, 0xe8, 0xbf, 0x4e, 0x9a, 0xcd,
+ 0xeb, 0x39, 0x15, 0x0f, 0x63, 0x8d, 0xec, 0xa4, 0xe7, 0x89, 0x9c, 0xf7,
+ 0xb8, 0x93, 0x35, 0x75, 0xa1, 0xc4, 0xa8, 0xdc, 0x68, 0x07, 0x5d, 0x4d,
+ 0xc9, 0xbb, 0xde, 0x0b, 0x8e, 0xb5, 0x0c, 0x3a, 0x75, 0xe0, 0x93, 0x2e,
+ 0x72, 0xcc, 0x4f, 0xc8, 0x63, 0x49, 0xc9, 0x0f, 0x86, 0xfc, 0x50, 0x9a,
+ 0xf9, 0x2d, 0x2e, 0x09, 0xf0, 0xb5, 0x93, 0x8a, 0x35, 0x9d, 0x26, 0x97,
+ 0xb6, 0xc3, 0xaf, 0x7b, 0xcf, 0x0f, 0xea, 0xb4, 0xd2, 0x30, 0x4a, 0x25,
+ 0xec, 0x7d, 0xc6, 0x4d, 0x93, 0xc8, 0x91, 0xed, 0x64, 0xfb, 0xe9, 0x85,
+ 0x46, 0x8a, 0xfe, 0xbc, 0x61, 0xa6, 0xca, 0xb4, 0x83, 0x8a, 0xc9, 0x24,
+ 0x7d, 0x17, 0x38, 0xd3, 0x58, 0x5b, 0x98, 0xa6, 0x5e, 0x06, 0x6c, 0xb9,
+ 0xf1, 0x23, 0xfe, 0xb7, 0x31, 0xfa, 0x54, 0x56, 0xe2, 0x94, 0xc0, 0x67,
+ 0x00, 0xcb, 0x7c, 0x4b, 0x58, 0xc9, 0xbb, 0x0f, 0x4b, 0xa5, 0xa9, 0x2c,
+ 0xe6, 0x1a, 0x4e, 0x20, 0xfb, 0x56, 0xec, 0x8f, 0x9f, 0x37, 0x28, 0xf9,
+ 0xf9, 0x1b, 0x20, 0x03, 0x4a, 0x0a, 0xda, 0x9b, 0x2a, 0x62, 0x66, 0xba,
+ 0x11, 0xc7, 0x98, 0x79, 0xf1, 0xbc, 0x43, 0x16, 0xe9, 0x65, 0xab, 0x0b,
+ 0xb2, 0x4a, 0x53, 0xd9, 0xea, 0x04, 0x4e, 0x0b, 0x75, 0x9b, 0xbc, 0x07,
+ 0xa6, 0xdb, 0x86, 0x79, 0xaf, 0x43, 0xcd, 0x79, 0xde, 0x54, 0x96, 0x3a,
+ 0xfd, 0xb9, 0x21, 0xd0, 0xd0, 0x68, 0x72, 0x5c, 0x01, 0xdc, 0xdb, 0xcc,
+ 0x5f, 0x2c, 0x91, 0xe3, 0x3e, 0x3f, 0xb3, 0xe4, 0xcc, 0xa6, 0x83, 0x75,
+ 0xe3, 0x54, 0x76, 0xaf, 0x0f, 0xfa, 0x90, 0xad, 0x8b, 0x3d, 0x5b, 0x7d,
+ 0x18, 0x2b, 0x37, 0x82, 0x8e, 0x55, 0x26, 0x5e, 0x63, 0x17, 0xad, 0x25,
+ 0x49, 0x5c, 0xb6, 0x7a, 0x02, 0xb8, 0x4e, 0xf0, 0x1a, 0x9e, 0x71, 0x3b,
+ 0xcd, 0xcc, 0xb7, 0xd2, 0x89, 0x79, 0x96, 0x6d, 0x05, 0x67, 0x21, 0x68,
+ 0xcf, 0x6d, 0x25, 0xc5, 0x6e, 0x9c, 0x44, 0x5f, 0xa3, 0x29, 0xd3, 0x7b,
+ 0x61, 0xc6, 0x9a, 0x55, 0xf2, 0x67, 0x97, 0x95, 0x02, 0xce, 0xfc, 0xc0,
+ 0xd9, 0x0b, 0xca, 0xc1, 0xc6, 0xcb, 0x1d, 0xd4, 0x6e, 0x40, 0xbb, 0x34,
+ 0x3a, 0xe1, 0x2a, 0xc4, 0xfc, 0x2e, 0x40, 0x5e, 0xb6, 0x0e, 0xc9, 0x9b,
+ 0x9d, 0xca, 0x41, 0xd0, 0x6a, 0x31, 0xbf, 0x1e, 0xa7, 0x4e, 0x95, 0x76,
+ 0x98, 0x21, 0x6c, 0x8c, 0xbe, 0x0e, 0xde, 0xd6, 0xac, 0x24, 0xe0, 0xa8,
+ 0xcb, 0xc7, 0xe9, 0x0e, 0xf8, 0x61, 0xdd, 0x61, 0xbd, 0x11, 0x76, 0x61,
+ 0xee, 0x8f, 0x7a, 0xca, 0xc3, 0x3b, 0x19, 0x06, 0xf6, 0x60, 0x3f, 0x30,
+ 0x65, 0x3a, 0xdd, 0x1a, 0x95, 0x74, 0x41, 0x86, 0x9e, 0xa7, 0x1b, 0x69,
+ 0xc6, 0x22, 0xca, 0x43, 0x9f, 0x85, 0xa9, 0x41, 0x46, 0x26, 0x64, 0xb4,
+ 0xb7, 0xa4, 0x8a, 0x7b, 0x41, 0xa2, 0xa4, 0x68, 0x81, 0x3c, 0x17, 0xe8,
+ 0x0e, 0x89, 0x2f, 0x72, 0x16, 0x74, 0xb0, 0x9d, 0xfb, 0x58, 0x37, 0x26,
+ 0xd7, 0x55, 0x73, 0x66, 0x6a, 0x91, 0x48, 0x11, 0xb9, 0x21, 0xd0, 0x63,
+ 0xdd, 0x64, 0x38, 0x17, 0x3c, 0x32, 0xef, 0xdc, 0x37, 0x81, 0x13, 0x23,
+ 0xc7, 0xea, 0x68, 0xe2, 0x13, 0xfc, 0x24, 0x59, 0xe6, 0x2c, 0x43, 0xb9,
+ 0x4f, 0x65, 0x73, 0x9f, 0xef, 0x7b, 0x83, 0x23, 0x1a, 0xbd, 0x24, 0xf7,
+ 0xcb, 0x76, 0xc4, 0x70, 0x72, 0x8f, 0xc4, 0xf2, 0x99, 0x76, 0x49, 0x29,
+ 0x5a, 0xfa, 0x06, 0x2d, 0xe8, 0x85, 0x50, 0x73, 0x71, 0xca, 0x4b, 0xfe,
+ 0x46, 0xb1, 0x16, 0xdb, 0x17, 0xec, 0xc4, 0xe4, 0xbd, 0xf0, 0x5c, 0x0e,
+ 0xb6, 0x6a, 0x48, 0xfd, 0x29, 0x56, 0xd9, 0xfe, 0x99, 0xb7, 0x55, 0x43,
+ 0x50, 0x48, 0x4f, 0xf4, 0xaa, 0xd4, 0x45, 0xe3, 0xd6, 0x55, 0x4f, 0xec,
+ 0xc3, 0xfb, 0xe1, 0x14, 0x78, 0x33, 0xd2, 0xb0, 0xb6, 0x84, 0x4a, 0xb0,
+ 0x73, 0x6b, 0x28, 0xa5, 0x93, 0x89, 0xbd, 0x25, 0xc8, 0x1e, 0x5f, 0x85,
+ 0xe0, 0xaf, 0xc5, 0xa7, 0x4f, 0x17, 0x6c, 0xda, 0x0e, 0x78, 0x74, 0xac,
+ 0x5b, 0xa5, 0xcc, 0x74, 0xec, 0x5f, 0x9d, 0x65, 0xf9, 0xb6, 0x43, 0xff,
+ 0x15, 0x2a, 0x5a, 0x4c, 0x3b, 0xa4, 0x21, 0x68, 0xf0, 0xb6, 0x66, 0x1a,
+ 0xe1, 0xd9, 0xb2, 0xfe, 0x6a, 0x34, 0x32, 0xc2, 0xb0, 0x0c, 0xc7, 0xf0,
+ 0xc6, 0x68, 0x5a, 0xbc, 0xef, 0xed, 0xdf, 0xb2, 0xa6, 0x49, 0x62, 0x16,
+ 0x3c, 0xfb, 0x67, 0x01, 0x19, 0x7e, 0x1a, 0x2c, 0x9f, 0xc3, 0x76, 0x79,
+ 0x33, 0x6c, 0x33, 0x1c, 0x74, 0xa8, 0x97, 0x79, 0xa8, 0xc7, 0x7d, 0x7b,
+ 0x0c, 0x79, 0x0a, 0xcf, 0x52, 0x09, 0x68, 0x7c, 0xd2, 0x3e, 0x18, 0x1e,
+ 0x7e, 0xc2, 0x85, 0x9f, 0x70, 0xe1, 0x1f, 0x5c, 0xf8, 0x11, 0x97, 0xfd,
+ 0x4a, 0x9a, 0x9e, 0x1f, 0x84, 0xdf, 0xdb, 0xf4, 0x43, 0x68, 0x63, 0xe8,
+ 0x0b, 0x52, 0xe1, 0x87, 0xa6, 0x6b, 0x02, 0xb6, 0x0e, 0x9b, 0x5b, 0xe2,
+ 0x39, 0x1d, 0xcf, 0x02, 0x9e, 0x26, 0xfc, 0x2c, 0xeb, 0x61, 0xe8, 0x5f,
+ 0xd9, 0x2f, 0xa5, 0xe0, 0x83, 0xd8, 0xef, 0xb0, 0x7f, 0x62, 0x58, 0xcf,
+ 0x2b, 0x58, 0x8c, 0xeb, 0xe1, 0x1c, 0xd9, 0xee, 0xe2, 0x24, 0x12, 0x25,
+ 0xe5, 0xf0, 0x20, 0x6c, 0xf2, 0xe6, 0x16, 0xf0, 0xca, 0xb6, 0x79, 0x1d,
+ 0xbb, 0x16, 0xb4, 0xf7, 0x3b, 0xfc, 0x7f, 0xb7, 0xb7, 0x03, 0x30, 0xd2,
+ 0xc6, 0x3b, 0xfd, 0x71, 0x77, 0xe0, 0x7f, 0xf8, 0xbd, 0x91, 0xb6, 0x69,
+ 0x5f, 0x30, 0xe6, 0xfe, 0x06, 0xbf, 0x96, 0xb8, 0x2d, 0x46, 0x7b, 0x96,
+ 0x7d, 0xbf, 0xb9, 0x67, 0x01, 0x9a, 0xb1, 0xec, 0xf3, 0xb8, 0xe7, 0x7c,
+ 0xe8, 0x3f, 0x3b, 0x40, 0x0f, 0xfc, 0xb9, 0x9b, 0x71, 0x84, 0xe8, 0xbf,
+ 0x14, 0x98, 0x16, 0xe6, 0xb6, 0xcb, 0xc2, 0xf3, 0x66, 0x2c, 0xb6, 0x4f,
+ 0xbd, 0xd9, 0x3e, 0xf7, 0xc3, 0x3e, 0xad, 0x56, 0x32, 0xac, 0xbf, 0x82,
+ 0x7d, 0x3e, 0x61, 0x29, 0x90, 0x0d, 0xd1, 0xc5, 0x4a, 0x1c, 0xbe, 0x41,
+ 0x4b, 0xbd, 0x41, 0x7b, 0xd3, 0xd3, 0xd0, 0xcb, 0x33, 0x3c, 0x87, 0x23,
+ 0x3a, 0x21, 0xfd, 0xb5, 0xef, 0x0f, 0xd6, 0xd5, 0x6f, 0x80, 0x2f, 0xcf,
+ 0x9b, 0x06, 0xcd, 0xe2, 0xb0, 0x1a, 0xd8, 0x62, 0x38, 0x6f, 0x23, 0x26,
+ 0x3a, 0x37, 0xa9, 0x54, 0xca, 0xb4, 0x90, 0x91, 0x59, 0x00, 0xed, 0x29,
+ 0xcb, 0xb7, 0x7b, 0xb6, 0x8d, 0x45, 0xd0, 0x9f, 0x71, 0x07, 0xe1, 0x17,
+ 0xd8, 0x6e, 0xc0, 0x17, 0xe8, 0x2f, 0x82, 0xfe, 0x4c, 0xa3, 0x85, 0xbe,
+ 0xa6, 0x85, 0xb1, 0x36, 0xdc, 0x0f, 0x44, 0x6d, 0x86, 0xeb, 0x1e, 0xa5,
+ 0x3b, 0xdc, 0x84, 0xe2, 0x3c, 0xc5, 0x7e, 0xb9, 0x9c, 0x81, 0x5d, 0x29,
+ 0x65, 0x8b, 0xd7, 0x56, 0x69, 0x71, 0x03, 0x86, 0xec, 0xb2, 0x6f, 0xb3,
+ 0xb6, 0x33, 0x58, 0x4a, 0xa9, 0xd2, 0xf7, 0x10, 0x1d, 0xac, 0x68, 0x80,
+ 0xe1, 0x31, 0xcf, 0xfb, 0x73, 0x63, 0x95, 0x5e, 0xf8, 0x52, 0x1e, 0x5f,
+ 0xf5, 0xa6, 0x2c, 0x7f, 0xee, 0x97, 0x2b, 0x0f, 0xf0, 0x19, 0x61, 0x2f,
+ 0x94, 0x2e, 0x5b, 0x3f, 0xf7, 0xa0, 0xbf, 0x5b, 0x70, 0x3e, 0x9e, 0x8e,
+ 0x31, 0xe6, 0xeb, 0x2c, 0x29, 0x87, 0x4c, 0xd1, 0xdb, 0x1a, 0xf8, 0xbc,
+ 0x43, 0x98, 0x3c, 0x50, 0x29, 0xf7, 0xb4, 0xd2, 0x55, 0x95, 0x63, 0xeb,
+ 0x65, 0x38, 0x01, 0xa7, 0xb2, 0x0f, 0xf2, 0x28, 0x77, 0x37, 0xcd, 0xc5,
+ 0x0a, 0x15, 0x8f, 0xd6, 0x2c, 0x1f, 0x07, 0xe3, 0x78, 0xbe, 0x22, 0x7a,
+ 0x63, 0xb4, 0x31, 0xd6, 0x19, 0x67, 0x89, 0xf6, 0x65, 0x16, 0x49, 0xe2,
+ 0xf6, 0xc4, 0x36, 0x71, 0x93, 0x85, 0x4a, 0xb9, 0xbb, 0x69, 0x9c, 0xca,
+ 0x83, 0x96, 0xd8, 0xbf, 0x81, 0xdb, 0xbf, 0x89, 0xbb, 0x8b, 0xd2, 0xdd,
+ 0x8c, 0x2f, 0x7a, 0xdb, 0x36, 0x69, 0xa7, 0x03, 0x7e, 0x7a, 0xda, 0x36,
+ 0x69, 0x98, 0x4c, 0xb3, 0x69, 0x9c, 0x61, 0x9a, 0x7b, 0x36, 0x69, 0x0e,
+ 0x6f, 0xe5, 0xe7, 0x28, 0xc1, 0x07, 0xc5, 0x5a, 0x73, 0xb4, 0xff, 0x62,
+ 0x65, 0x60, 0xfc, 0x0e, 0x42, 0x8c, 0x1c, 0xde, 0x11, 0xf8, 0x70, 0x6d,
+ 0xbf, 0x03, 0x59, 0x69, 0xc4, 0x3e, 0x51, 0xa1, 0x32, 0xce, 0xf9, 0x81,
+ 0x3a, 0xed, 0x5f, 0xab, 0x53, 0xa0, 0x4b, 0xac, 0x13, 0x6f, 0xc1, 0xc6,
+ 0xa8, 0xb4, 0x3b, 0x17, 0x9f, 0xd4, 0x72, 0x3a, 0x6c, 0x8d, 0xc6, 0xcb,
+ 0xf0, 0xe1, 0x6a, 0x6e, 0xef, 0xeb, 0x79, 0xf5, 0x71, 0x4f, 0x35, 0xd9,
+ 0x1f, 0xc6, 0x47, 0x9d, 0x2c, 0xe6, 0xeb, 0x6c, 0x5b, 0xf0, 0x2b, 0x0d,
+ 0xa6, 0xfd, 0x4c, 0x17, 0x75, 0x22, 0x8e, 0xd6, 0xcf, 0xec, 0xf2, 0x6d,
+ 0x87, 0x34, 0x0d, 0xbe, 0x79, 0x26, 0xcb, 0x71, 0xbf, 0x35, 0x06, 0xf8,
+ 0x49, 0x35, 0x37, 0xd6, 0x77, 0xa4, 0x7e, 0x67, 0x5f, 0xb1, 0x5e, 0xea,
+ 0x2b, 0x56, 0x74, 0xb6, 0x13, 0xe1, 0x64, 0xd1, 0x97, 0xb9, 0x54, 0x0a,
+ 0x36, 0xc1, 0x6b, 0x27, 0xb1, 0xe6, 0x0f, 0x60, 0x7f, 0x6c, 0xdf, 0x44,
+ 0xe3, 0x2e, 0xd6, 0x18, 0xf9, 0x00, 0xe7, 0x0e, 0xde, 0xe0, 0xd3, 0x6c,
+ 0xec, 0x5a, 0x8c, 0xfc, 0x6b, 0x60, 0x9f, 0xdc, 0x7f, 0xc7, 0xf3, 0xe3,
+ 0xc3, 0xdd, 0x5d, 0xfe, 0xdc, 0x8f, 0x03, 0x9b, 0x0e, 0x69, 0x31, 0x9d,
+ 0x8c, 0x32, 0x8e, 0x1c, 0x66, 0xbc, 0xa1, 0x29, 0xec, 0x9f, 0xf3, 0x2e,
+ 0xe7, 0x1e, 0x9c, 0x77, 0x4c, 0x07, 0x7e, 0x8e, 0x6c, 0xe4, 0x4f, 0x9e,
+ 0x40, 0x2e, 0x52, 0x84, 0xdd, 0x68, 0xb9, 0x2b, 0x34, 0x23, 0x7d, 0x24,
+ 0xc5, 0x5a, 0x72, 0x8f, 0x01, 0xe6, 0xdf, 0x60, 0x73, 0xdd, 0x5d, 0x81,
+ 0x1e, 0x06, 0x3e, 0x5e, 0xfa, 0x5d, 0xc0, 0xbe, 0xb5, 0x0d, 0xf6, 0xcd,
+ 0x66, 0x58, 0xbc, 0x5f, 0xdf, 0xf6, 0xfe, 0x9f, 0xd9, 0x7e, 0xf1, 0x6e,
+ 0x15, 0xfe, 0xb4, 0x35, 0xb0, 0xfd, 0x8b, 0x54, 0x84, 0x6f, 0xd5, 0x4c,
+ 0xce, 0x2d, 0x0f, 0x02, 0x17, 0xe3, 0x3a, 0x78, 0x84, 0xbf, 0x40, 0x8c,
+ 0x85, 0xbc, 0x11, 0x13, 0x92, 0x37, 0x72, 0x3e, 0x05, 0xd8, 0x34, 0x60,
+ 0xd9, 0xff, 0x32, 0xec, 0x85, 0x38, 0xcb, 0xbc, 0x58, 0x67, 0x1c, 0xf6,
+ 0x55, 0xe4, 0x39, 0xd9, 0x36, 0x68, 0x94, 0xf7, 0x82, 0x6a, 0x86, 0xb0,
+ 0x21, 0xdd, 0xed, 0xb0, 0x9c, 0xdf, 0x30, 0xed, 0xae, 0x20, 0x6f, 0x18,
+ 0x23, 0xbb, 0x61, 0xe3, 0x57, 0xa2, 0xa9, 0xa7, 0x90, 0xbb, 0x99, 0x2d,
+ 0x2c, 0x0b, 0x9e, 0xd7, 0x7d, 0x19, 0x85, 0x78, 0xa5, 0x9e, 0xad, 0xe3,
+ 0xdf, 0x4a, 0x6c, 0xfa, 0x4a, 0xb6, 0x34, 0xb2, 0x11, 0x2b, 0x20, 0xe3,
+ 0xf4, 0xa4, 0xc8, 0x25, 0x29, 0x5f, 0xf7, 0xe5, 0x8b, 0xf8, 0x0c, 0xff,
+ 0x28, 0xfd, 0x07, 0xce, 0x3d, 0xf4, 0x83, 0xe1, 0x99, 0xb3, 0x9e, 0xd9,
+ 0x38, 0x9b, 0x34, 0x74, 0x69, 0x0c, 0xb8, 0x74, 0x14, 0x34, 0x38, 0x6e,
+ 0x5b, 0x22, 0x97, 0xa0, 0xa2, 0xce, 0xf9, 0x85, 0xcc, 0x0d, 0x6d, 0xf6,
+ 0x03, 0x22, 0xd7, 0x86, 0x39, 0xee, 0xff, 0x41, 0x97, 0x7f, 0xd6, 0x1d,
+ 0x3c, 0x1e, 0x17, 0xb9, 0xae, 0x6d, 0xf3, 0x7f, 0xd7, 0xe1, 0xf3, 0x26,
+ 0xc7, 0x98, 0xff, 0xc9, 0xb6, 0xf1, 0xa3, 0x89, 0xad, 0xe3, 0xaf, 0xf6,
+ 0x85, 0xfa, 0x20, 0x72, 0x8f, 0x05, 0xfc, 0xb2, 0x9e, 0x6e, 0xe7, 0xf5,
+ 0x17, 0xd1, 0x97, 0x3f, 0x01, 0x4d, 0xa9, 0xe3, 0xbf, 0x80, 0xbe, 0x6c,
+ 0xc0, 0x5e, 0x43, 0x5f, 0x9a, 0x79, 0xd8, 0xa8, 0x3b, 0xaa, 0x02, 0x39,
+ 0xac, 0x93, 0xdd, 0x9b, 0x2e, 0xc3, 0xc6, 0x0b, 0x0d, 0xc8, 0x6e, 0x23,
+ 0xae, 0x6e, 0xc0, 0x94, 0x36, 0x61, 0xfc, 0xb8, 0x53, 0x68, 0x78, 0xc8,
+ 0xfb, 0x9a, 0x63, 0x70, 0x06, 0xfd, 0x12, 0xf6, 0xba, 0x42, 0x53, 0xee,
+ 0x9a, 0x2d, 0xcc, 0x93, 0x32, 0x6f, 0x15, 0xe6, 0x93, 0x4a, 0x61, 0x91,
+ 0x73, 0xda, 0x18, 0xfa, 0xb2, 0x3e, 0x41, 0x8c, 0x3b, 0xa5, 0xd8, 0x67,
+ 0xe7, 0x90, 0xcf, 0x2e, 0xe1, 0x77, 0x0e, 0xbf, 0x3a, 0x7e, 0x61, 0xdd,
+ 0xf0, 0x2d, 0xd4, 0x1d, 0xd2, 0xdf, 0x23, 0x36, 0xf9, 0xeb, 0xff, 0x74,
+ 0x09, 0xf9, 0xf4, 0x5c, 0x92, 0x9e, 0x30, 0x45, 0x8f, 0xf0, 0x7d, 0x9c,
+ 0x8d, 0x5c, 0x5c, 0x7f, 0x8b, 0x7e, 0x25, 0xc8, 0xe9, 0x88, 0xde, 0xa8,
+ 0xe2, 0x2c, 0x87, 0x0f, 0x05, 0xfe, 0xe9, 0xe4, 0x57, 0x1c, 0xe9, 0xcb,
+ 0x83, 0x9c, 0x0d, 0x7e, 0xc7, 0x96, 0x50, 0xaf, 0x40, 0x3e, 0x0a, 0xfd,
+ 0x0c, 0x7a, 0xfc, 0x46, 0xb5, 0x1d, 0xfc, 0x98, 0x54, 0x9c, 0x30, 0x46,
+ 0x49, 0x19, 0xd0, 0x77, 0x28, 0xed, 0xc8, 0xdb, 0xe0, 0x77, 0xe4, 0x98,
+ 0x65, 0x46, 0xc7, 0x17, 0x2a, 0x02, 0xb0, 0x90, 0x79, 0x16, 0x7d, 0xe8,
+ 0xdf, 0xe5, 0x2a, 0xe3, 0x09, 0x7a, 0xb3, 0xaa, 0xd2, 0xbf, 0x20, 0x0f,
+ 0xc4, 0xbb, 0xe3, 0xb0, 0xc1, 0x5e, 0xc4, 0xab, 0x7e, 0x95, 0xf6, 0x72,
+ 0xcc, 0xd8, 0xa3, 0xe1, 0x59, 0xc0, 0xef, 0x20, 0xf2, 0xc2, 0x6b, 0xe0,
+ 0x5c, 0x03, 0x9e, 0x79, 0x8b, 0x01, 0x87, 0xe1, 0x35, 0xf0, 0xd6, 0x09,
+ 0x1d, 0x34, 0xf4, 0x49, 0xfa, 0x8c, 0x2e, 0x73, 0x27, 0x85, 0xe7, 0x7d,
+ 0x3f, 0xf9, 0xd1, 0x79, 0x96, 0xb3, 0x0a, 0x1d, 0xe2, 0x31, 0xbf, 0x63,
+ 0x7f, 0xce, 0xf4, 0x8c, 0x51, 0x1b, 0x9b, 0xb9, 0x5c, 0xf5, 0xfb, 0xe1,
+ 0x1c, 0x29, 0x61, 0x4c, 0x65, 0x3f, 0x5d, 0x80, 0xad, 0xf2, 0x78, 0x9c,
+ 0xe4, 0x19, 0x6c, 0x39, 0x4f, 0xa9, 0x47, 0xc7, 0x66, 0x4c, 0x3e, 0x57,
+ 0x9d, 0xa6, 0x2b, 0xe1, 0xb9, 0xf2, 0x19, 0xa1, 0x0e, 0xad, 0x3e, 0x89,
+ 0x73, 0x15, 0x41, 0xcd, 0x02, 0x3f, 0x30, 0xc7, 0xe7, 0x8b, 0x3a, 0xb2,
+ 0x8a, 0x3c, 0xac, 0x4a, 0x09, 0xbf, 0xe6, 0x3a, 0x85, 0x3a, 0x05, 0xe7,
+ 0x57, 0x99, 0x03, 0x8d, 0x24, 0x9e, 0x4b, 0x78, 0xa6, 0xf0, 0x3c, 0x87,
+ 0x67, 0x3f, 0x9e, 0x75, 0xb6, 0x8f, 0x20, 0xef, 0xf9, 0x08, 0x3f, 0xb0,
+ 0x93, 0x02, 0xdb, 0x34, 0xfd, 0x65, 0x23, 0x47, 0x3f, 0x68, 0x8c, 0xd2,
+ 0x5f, 0x34, 0xb2, 0xf4, 0xfd, 0x86, 0x45, 0xcf, 0x36, 0x86, 0xe9, 0x7b,
+ 0x8d, 0x0c, 0xd7, 0x90, 0xc8, 0xe1, 0xd2, 0xf0, 0xcd, 0x17, 0xe8, 0x2b,
+ 0x6e, 0x03, 0x3e, 0x47, 0xfa, 0xcb, 0xe3, 0x76, 0xfd, 0x3a, 0x2a, 0x3e,
+ 0xa5, 0x23, 0xcf, 0x54, 0xb9, 0x8e, 0xa3, 0x47, 0xad, 0xbb, 0x13, 0x7c,
+ 0xf6, 0xc2, 0xe4, 0xba, 0xe6, 0x04, 0xc3, 0xa1, 0x1e, 0x56, 0x90, 0xbf,
+ 0xb4, 0xd0, 0x64, 0xd2, 0x58, 0x71, 0xd4, 0x74, 0xe0, 0x8f, 0x26, 0x00,
+ 0x87, 0x35, 0xdd, 0x38, 0xad, 0x9d, 0x86, 0x2d, 0x58, 0xa8, 0xa5, 0x93,
+ 0x31, 0xf8, 0x3e, 0x99, 0x9f, 0x48, 0xdf, 0xe2, 0xfb, 0xd2, 0xb0, 0xc6,
+ 0xe4, 0x39, 0x3b, 0x98, 0xe3, 0xf8, 0xa8, 0x03, 0xb6, 0x11, 0xc4, 0x90,
+ 0xed, 0x34, 0xd9, 0x37, 0x4e, 0x04, 0xfe, 0x71, 0x85, 0x1e, 0x76, 0x07,
+ 0xec, 0xb7, 0x11, 0x7b, 0x94, 0x96, 0x30, 0x2f, 0xda, 0x0d, 0xde, 0x3c,
+ 0xef, 0x30, 0xea, 0xf3, 0x74, 0x42, 0xa3, 0xbf, 0x9f, 0x35, 0xf4, 0xc3,
+ 0x02, 0x01, 0xae, 0xdd, 0xf3, 0xc6, 0x4d, 0xa3, 0x64, 0x8b, 0x0e, 0xfa,
+ 0xa7, 0x53, 0x1c, 0x93, 0xd7, 0x8f, 0xbd, 0x08, 0x3d, 0xa8, 0x2d, 0xb5,
+ 0x52, 0xad, 0xa6, 0xd1, 0xe5, 0x91, 0x01, 0xb9, 0x6e, 0xad, 0x9e, 0x40,
+ 0x9e, 0xd7, 0x46, 0x8b, 0xbd, 0x52, 0xd9, 0xe1, 0xb7, 0x33, 0xd2, 0x6f,
+ 0x3b, 0x26, 0x9e, 0xf5, 0xb4, 0xbe, 0x95, 0x97, 0x67, 0xa9, 0xe8, 0x76,
+ 0xa2, 0x42, 0xd9, 0x0d, 0x99, 0x70, 0x7f, 0x40, 0x77, 0x04, 0x62, 0xa0,
+ 0x36, 0xa0, 0x1f, 0x12, 0xff, 0xed, 0x7d, 0x51, 0x63, 0x39, 0xbe, 0x8e,
+ 0xd8, 0xc2, 0xb1, 0x52, 0x91, 0x7a, 0xb7, 0xb0, 0xf4, 0xa6, 0xce, 0xfe,
+ 0xe5, 0x7b, 0xf5, 0xdd, 0xc1, 0x98, 0xfd, 0x3b, 0x8f, 0xdb, 0xe9, 0xfb,
+ 0xb5, 0x9d, 0xb4, 0x58, 0xe3, 0xf7, 0xad, 0xb4, 0x50, 0x1b, 0xb8, 0xf2,
+ 0x90, 0xe8, 0xa5, 0xd5, 0xeb, 0x6e, 0xd6, 0x3f, 0x2f, 0x20, 0x93, 0x89,
+ 0x0f, 0xe9, 0xdd, 0x91, 0x2e, 0x7a, 0xf5, 0x5e, 0xa3, 0x7a, 0xbf, 0x80,
+ 0x3e, 0x8e, 0xc4, 0xd9, 0xce, 0xd0, 0xe7, 0x79, 0xe3, 0x4a, 0x5a, 0xb0,
+ 0x9e, 0xbd, 0x0c, 0xfd, 0x32, 0x4e, 0xfa, 0x3a, 0xc9, 0xb4, 0x99, 0x2e,
+ 0xce, 0xc7, 0x7c, 0x05, 0x34, 0xf1, 0xae, 0x3e, 0x00, 0x5a, 0xaf, 0x48,
+ 0x59, 0x1c, 0xb6, 0x8c, 0x2b, 0x08, 0x51, 0xde, 0x65, 0x73, 0x20, 0x23,
+ 0xc4, 0x6e, 0xaa, 0xa5, 0x6e, 0xd6, 0xbf, 0x8b, 0x78, 0x80, 0x9a, 0xab,
+ 0xb4, 0x4e, 0xeb, 0xc7, 0x2e, 0x9a, 0xac, 0x8b, 0x6c, 0xc3, 0x3f, 0x44,
+ 0x4e, 0xaa, 0xd3, 0x53, 0x75, 0xf6, 0x5d, 0x4c, 0x8b, 0xeb, 0x82, 0x7d,
+ 0xfa, 0xdd, 0xe0, 0xc1, 0x19, 0xc6, 0x3b, 0xcc, 0xab, 0x9f, 0xe5, 0x73,
+ 0x6b, 0x61, 0xdc, 0x4c, 0x9a, 0x37, 0xb3, 0x45, 0x46, 0x03, 0xfa, 0x5e,
+ 0xc1, 0xeb, 0xbd, 0x8b, 0x75, 0xdf, 0x01, 0xaf, 0x03, 0xc0, 0x45, 0x0c,
+ 0x4d, 0x35, 0xaf, 0xf1, 0x9a, 0x5c, 0xe3, 0x54, 0x1d, 0x39, 0xe0, 0xc6,
+ 0x1a, 0x98, 0xab, 0x0b, 0xec, 0xf3, 0x57, 0x65, 0xfe, 0xac, 0x22, 0xff,
+ 0xb9, 0x3c, 0xf2, 0x4c, 0x90, 0x5f, 0x3c, 0x07, 0x59, 0xc7, 0xe8, 0xb5,
+ 0x59, 0xae, 0x2f, 0x0f, 0x51, 0x39, 0xb1, 0x7e, 0x6c, 0xca, 0x44, 0x4d,
+ 0x8f, 0x38, 0x50, 0xde, 0x37, 0xe0, 0xeb, 0x55, 0x3f, 0xe3, 0x3c, 0x27,
+ 0xcf, 0xa4, 0x2c, 0x5a, 0xe9, 0x8b, 0x5a, 0x1a, 0xf8, 0x3c, 0x77, 0x29,
+ 0x38, 0xcf, 0x6f, 0x83, 0x1f, 0xf4, 0xeb, 0x3d, 0x81, 0xff, 0x4b, 0x40,
+ 0x57, 0x87, 0xf4, 0xc3, 0x14, 0x0b, 0xfc, 0x5f, 0x82, 0x5e, 0x3d, 0xad,
+ 0x42, 0x87, 0x58, 0x7f, 0xfa, 0xbb, 0x37, 0xf5, 0x87, 0xdf, 0xad, 0x1f,
+ 0x73, 0xc0, 0x63, 0x7e, 0xae, 0x95, 0x0a, 0xd5, 0x18, 0x4d, 0x65, 0x91,
+ 0x73, 0x23, 0xfe, 0xe4, 0xa1, 0x4b, 0x85, 0x1a, 0xeb, 0x72, 0x29, 0xd0,
+ 0xe5, 0x78, 0x40, 0xfb, 0x6f, 0xa0, 0xcb, 0x46, 0x7a, 0x55, 0x70, 0x7d,
+ 0xd5, 0x27, 0x6b, 0x64, 0x15, 0xf6, 0x55, 0xac, 0x70, 0x2c, 0x62, 0xdb,
+ 0xa2, 0xe3, 0xcc, 0x7f, 0xb1, 0x32, 0x2a, 0x8a, 0x8d, 0xac, 0x28, 0xba,
+ 0xcc, 0xdf, 0x3e, 0xf0, 0xad, 0xc8, 0x3a, 0x78, 0xa1, 0xf1, 0xae, 0xb7,
+ 0xb0, 0x6f, 0x07, 0xfa, 0xd0, 0xfd, 0x71, 0x3e, 0xdf, 0xeb, 0x99, 0xaf,
+ 0xb4, 0x2d, 0x58, 0xde, 0x49, 0x5a, 0x1e, 0x7c, 0xa9, 0x8b, 0x73, 0xb4,
+ 0xb3, 0x83, 0x4c, 0x1f, 0x7c, 0x24, 0x93, 0xb4, 0xe8, 0xf2, 0x1a, 0x2c,
+ 0x17, 0xf8, 0xba, 0x39, 0x9d, 0x1e, 0x96, 0xe7, 0xc7, 0xba, 0xc5, 0xf7,
+ 0x4d, 0x2a, 0xe5, 0x13, 0x03, 0xfa, 0x43, 0x64, 0x5c, 0x59, 0x53, 0x8d,
+ 0xea, 0x24, 0xe2, 0xea, 0xc2, 0xbc, 0x4a, 0x7b, 0x64, 0x1d, 0xc6, 0x67,
+ 0x64, 0x9c, 0x84, 0x35, 0x06, 0x7b, 0xff, 0x8d, 0xa6, 0xbd, 0x77, 0xd2,
+ 0xc5, 0xd3, 0x9f, 0x85, 0xdd, 0xb3, 0x5c, 0xb5, 0xf4, 0x11, 0xe4, 0x19,
+ 0x73, 0x04, 0xf9, 0x22, 0x7f, 0xb6, 0x53, 0xe1, 0xb9, 0xb0, 0xbc, 0x77,
+ 0x49, 0xf9, 0x0b, 0x29, 0xff, 0x1b, 0xa8, 0xdc, 0xeb, 0xdb, 0x38, 0xbf,
+ 0x13, 0xa0, 0xe1, 0xbf, 0xe3, 0xf1, 0x67, 0x90, 0x1f, 0xf1, 0xbb, 0x9a,
+ 0x8f, 0x47, 0x3d, 0x4c, 0x07, 0xef, 0xfe, 0x10, 0x6b, 0xb2, 0x8c, 0xc3,
+ 0xf9, 0x0e, 0xf2, 0x6d, 0x29, 0x94, 0x3b, 0x12, 0x8c, 0x7a, 0x92, 0x7e,
+ 0xad, 0x9e, 0xa2, 0x89, 0x7a, 0x3f, 0x15, 0xea, 0x69, 0x9c, 0xc1, 0x13,
+ 0xdd, 0xbc, 0xb7, 0xfc, 0x12, 0xf6, 0x23, 0x98, 0xd7, 0x1a, 0x1d, 0x71,
+ 0x43, 0x7e, 0xe2, 0x01, 0x7f, 0x5a, 0x30, 0x8e, 0x05, 0x3c, 0x34, 0xd3,
+ 0x8b, 0x83, 0x96, 0x0d, 0x3a, 0x67, 0x02, 0x3a, 0xec, 0x47, 0xc0, 0xeb,
+ 0x44, 0x8a, 0x96, 0x5c, 0xe6, 0x63, 0x27, 0x95, 0x93, 0xdc, 0x7f, 0x0e,
+ 0x7a, 0xc6, 0x74, 0x76, 0x70, 0x7e, 0xb3, 0x45, 0xc6, 0x47, 0xeb, 0x25,
+ 0xc8, 0x98, 0xe5, 0xcb, 0x70, 0x71, 0x5a, 0xf8, 0x25, 0x3e, 0xbf, 0x21,
+ 0xe4, 0xf8, 0xac, 0x0b, 0x3b, 0x03, 0xbd, 0xf2, 0xd7, 0x2c, 0xcc, 0x75,
+ 0xe2, 0xac, 0x78, 0xdd, 0x76, 0xba, 0x07, 0x76, 0x9f, 0xaf, 0xf1, 0xfa,
+ 0x13, 0xd0, 0xa3, 0x1f, 0xcb, 0xf5, 0x0b, 0x4b, 0xbd, 0x01, 0x3e, 0xe3,
+ 0x76, 0x6e, 0xc3, 0x6d, 0xa5, 0x03, 0x55, 0xfd, 0x63, 0xf0, 0x7f, 0x13,
+ 0xf8, 0x82, 0xce, 0x64, 0x19, 0x9f, 0xe9, 0x00, 0xae, 0x96, 0xfc, 0x04,
+ 0x3a, 0x09, 0x59, 0xef, 0xe7, 0x6b, 0xad, 0x94, 0xaf, 0x86, 0xb4, 0x98,
+ 0xce, 0x87, 0xa8, 0x87, 0xbf, 0x2c, 0x69, 0x4d, 0x49, 0x5a, 0x78, 0x5f,
+ 0x63, 0x9f, 0x73, 0x3b, 0xf0, 0xe3, 0xec, 0xff, 0x69, 0x21, 0xd1, 0x41,
+ 0x0b, 0xb2, 0xa6, 0x6f, 0xf7, 0x7d, 0x4d, 0xa2, 0x0d, 0xef, 0x77, 0xc1,
+ 0xe6, 0x87, 0x90, 0x5b, 0x74, 0x62, 0x2e, 0xbd, 0x6d, 0x6e, 0x3b, 0xff,
+ 0xb1, 0x6d, 0xfc, 0xeb, 0x80, 0xeb, 0xc1, 0x9a, 0x3e, 0x5c, 0x01, 0x70,
+ 0xd3, 0x73, 0x90, 0xb3, 0xc5, 0x7e, 0x85, 0xe3, 0xe4, 0x75, 0x92, 0x97,
+ 0xe9, 0x25, 0x05, 0x70, 0xbd, 0xc0, 0x0d, 0xc7, 0xbe, 0x1c, 0xaa, 0xa0,
+ 0xf3, 0xcd, 0x9a, 0xbc, 0xbb, 0xc0, 0x19, 0xf4, 0x24, 0x78, 0xef, 0xe5,
+ 0xda, 0xa7, 0xc9, 0xec, 0xba, 0x26, 0x79, 0xb1, 0xac, 0x98, 0x5f, 0xe6,
+ 0x15, 0x7a, 0x8a, 0x38, 0xe4, 0x58, 0xa8, 0x0b, 0x13, 0x2a, 0x15, 0xb2,
+ 0x3a, 0xf2, 0x73, 0xbe, 0xb7, 0x65, 0xbb, 0xd4, 0xf9, 0xae, 0x34, 0x26,
+ 0x4c, 0x8e, 0xb5, 0x9a, 0xdc, 0xfb, 0x91, 0x25, 0xbe, 0xbb, 0x4d, 0xf3,
+ 0x5d, 0x5f, 0x86, 0xb0, 0xf7, 0x07, 0x97, 0x4c, 0x7a, 0xa4, 0x9e, 0xa1,
+ 0x87, 0xea, 0x86, 0x7e, 0x3f, 0x7c, 0x40, 0x71, 0xe3, 0x4e, 0xf7, 0x73,
+ 0x09, 0xae, 0x45, 0x34, 0xe4, 0x81, 0x2d, 0xa6, 0x9f, 0x17, 0x94, 0xb9,
+ 0x66, 0x9b, 0x33, 0xf8, 0x1e, 0x47, 0xaf, 0xd1, 0xf6, 0xdc, 0xe1, 0xff,
+ 0x32, 0x6f, 0xe0, 0xf5, 0xd9, 0x5f, 0x23, 0x4f, 0x70, 0x91, 0x27, 0xb8,
+ 0xc8, 0x13, 0x5c, 0xe4, 0x09, 0x2e, 0xf2, 0x04, 0x17, 0x79, 0x82, 0x8b,
+ 0x3c, 0xc1, 0x45, 0x9e, 0x80, 0xd8, 0xed, 0xd7, 0x0b, 0x63, 0xc8, 0x7f,
+ 0xe1, 0xbf, 0xdc, 0xcf, 0x43, 0x4e, 0x7c, 0xdf, 0xc9, 0x31, 0x87, 0x63,
+ 0x33, 0xcf, 0xad, 0xee, 0x70, 0xf8, 0xdc, 0xa4, 0xef, 0xbb, 0x13, 0x73,
+ 0xe3, 0x41, 0x3e, 0xc2, 0x30, 0x61, 0xec, 0x66, 0x38, 0x1a, 0x75, 0x2c,
+ 0x05, 0x36, 0xc6, 0xf9, 0x8a, 0x1f, 0xb3, 0xfc, 0x5c, 0xf9, 0x75, 0xe4,
+ 0x2c, 0x69, 0xe4, 0x2c, 0xfd, 0xc8, 0x4f, 0xf8, 0x8e, 0x3b, 0xbc, 0x63,
+ 0xb2, 0x95, 0xc3, 0xee, 0x98, 0x72, 0xb7, 0xcb, 0xb9, 0xb4, 0x99, 0x2e,
+ 0x0a, 0x31, 0xd7, 0x43, 0x1e, 0xe5, 0x47, 0xbe, 0x86, 0xbc, 0xf5, 0x9b,
+ 0xf2, 0x3e, 0x6d, 0x7c, 0x90, 0xcf, 0x7c, 0xe5, 0x1a, 0xb9, 0x6b, 0x28,
+ 0x5f, 0xff, 0x1e, 0x50, 0x2c, 0xb0, 0xfc, 0x88, 0xba, 0xcf, 0x43, 0xe0,
+ 0xe7, 0x63, 0x94, 0x58, 0xde, 0x89, 0x39, 0x9d, 0x7a, 0xe4, 0x5d, 0x12,
+ 0x8e, 0xf2, 0xbc, 0xd6, 0x43, 0xed, 0x26, 0x89, 0xf3, 0x7c, 0xe3, 0xc0,
+ 0x74, 0xd9, 0xbf, 0x5e, 0x3a, 0x96, 0xaf, 0x5d, 0x92, 0x3a, 0x75, 0xb8,
+ 0x5e, 0x40, 0x7d, 0xd4, 0x07, 0x18, 0x0d, 0xb5, 0x55, 0x48, 0x9b, 0x69,
+ 0x5e, 0x4d, 0xc8, 0x9a, 0xe7, 0xfc, 0xc6, 0x79, 0xe2, 0xac, 0x79, 0x9d,
+ 0x4b, 0xc7, 0xca, 0x55, 0x23, 0xc5, 0xb5, 0xb2, 0xad, 0x5f, 0x3a, 0x76,
+ 0x02, 0x34, 0x16, 0x91, 0x1b, 0xa8, 0x72, 0xed, 0x4b, 0xc7, 0xa6, 0xab,
+ 0xfe, 0x7d, 0x96, 0xcf, 0x03, 0xe2, 0x60, 0xb6, 0x9d, 0xd4, 0x05, 0xff,
+ 0x5e, 0x4b, 0x48, 0x5c, 0xc6, 0x63, 0x7c, 0x0d, 0x78, 0x7c, 0x6e, 0x19,
+ 0xe0, 0xf2, 0xd9, 0x31, 0x0f, 0x97, 0x8e, 0x95, 0x6a, 0xcd, 0x3c, 0x30,
+ 0x1d, 0xa6, 0x1b, 0xee, 0x87, 0xf7, 0x92, 0x20, 0xb1, 0xec, 0x79, 0xc5,
+ 0x91, 0xfe, 0x20, 0xef, 0x3a, 0x81, 0xfc, 0x4e, 0x93, 0x7a, 0xee, 0x8f,
+ 0xff, 0x4c, 0xc6, 0xa9, 0xb4, 0xe0, 0x79, 0x7e, 0xe2, 0x5d, 0xf6, 0x3b,
+ 0x98, 0xc3, 0x78, 0x31, 0x84, 0x15, 0x01, 0x6c, 0x47, 0x93, 0x3c, 0x5b,
+ 0x82, 0xf5, 0x98, 0x27, 0xde, 0xe7, 0xcf, 0xb1, 0x7f, 0x79, 0x07, 0xc7,
+ 0xf9, 0x18, 0xd6, 0xc5, 0x59, 0xba, 0xff, 0x5b, 0xd9, 0x37, 0xef, 0x89,
+ 0x65, 0xaa, 0x01, 0x87, 0xe1, 0x99, 0x46, 0x88, 0x83, 0x17, 0xe7, 0x7d,
+ 0x3c, 0xb1, 0x71, 0xff, 0xf7, 0x49, 0xeb, 0x36, 0xf3, 0x1a, 0xae, 0x1f,
+ 0xd2, 0xc9, 0xf8, 0xe7, 0xb6, 0x81, 0x2f, 0xff, 0x4f, 0x31, 0x3c, 0xa1,
+ 0x8b, 0x1f, 0xb9, 0x47, 0xcd, 0x34, 0xd5, 0xa1, 0xe1, 0xfd, 0x05, 0xdf,
+ 0x07, 0x70, 0x7d, 0xcf, 0xdf, 0x1a, 0x9a, 0x6b, 0xc5, 0x67, 0x83, 0x58,
+ 0xd6, 0x47, 0xb6, 0xc6, 0x75, 0xc3, 0x85, 0x60, 0xbc, 0x0b, 0xb1, 0x8d,
+ 0xc7, 0x0d, 0xc8, 0x17, 0xba, 0x6c, 0xb5, 0x07, 0x75, 0x4b, 0xc2, 0xff,
+ 0x26, 0x94, 0x61, 0x3b, 0xe2, 0xba, 0xaf, 0x2d, 0x98, 0x0b, 0xed, 0x88,
+ 0xfd, 0xb0, 0x16, 0xcc, 0xb1, 0xbf, 0x15, 0xa8, 0x5d, 0xb8, 0x0f, 0x3a,
+ 0x8b, 0xcd, 0xb6, 0x14, 0x3e, 0x13, 0x74, 0x6e, 0x3e, 0xf4, 0x5b, 0xf0,
+ 0x29, 0x83, 0x5a, 0xe0, 0xfb, 0xe3, 0xf0, 0x7d, 0x9d, 0x74, 0x00, 0x3e,
+ 0xeb, 0x20, 0x7c, 0xd6, 0x21, 0xd4, 0x8b, 0x63, 0x4b, 0xcd, 0xf7, 0xbc,
+ 0x5c, 0xa3, 0x76, 0x2a, 0x47, 0xe4, 0xf9, 0x97, 0x3c, 0xd5, 0xfc, 0x10,
+ 0x3a, 0xc0, 0x75, 0x57, 0xa8, 0x13, 0xf0, 0xb7, 0x56, 0x02, 0x3a, 0xb1,
+ 0xfd, 0x3e, 0x39, 0x03, 0xdb, 0x68, 0xb7, 0x85, 0xcc, 0xe5, 0x7c, 0xd9,
+ 0x97, 0x6b, 0xbe, 0xec, 0xe1, 0x97, 0x41, 0x5f, 0xa3, 0x52, 0x5d, 0xa7,
+ 0x12, 0xd6, 0x2d, 0x61, 0xdd, 0x12, 0xea, 0xbc, 0xe9, 0x7a, 0xf3, 0x77,
+ 0xaf, 0x8e, 0x80, 0x77, 0xc6, 0x0d, 0xfb, 0x7a, 0xd3, 0xfe, 0xc3, 0xe7,
+ 0x49, 0xc8, 0xff, 0x11, 0xc8, 0xff, 0x28, 0xea, 0x9b, 0xdf, 0x47, 0x7d,
+ 0xf3, 0x7b, 0xa8, 0x6f, 0x8e, 0xa0, 0xbe, 0x99, 0x44, 0x7d, 0xf3, 0x65,
+ 0xf8, 0x8f, 0xfb, 0xe0, 0x3f, 0x26, 0xe0, 0x3f, 0xc6, 0xe5, 0xdd, 0xd3,
+ 0x61, 0x77, 0xfb, 0x9d, 0x4a, 0xb8, 0x16, 0xb7, 0x9f, 0x12, 0x99, 0x25,
+ 0xec, 0x69, 0x8c, 0x6a, 0x0d, 0xae, 0x6f, 0x2c, 0x72, 0x46, 0xb9, 0xbe,
+ 0x99, 0x50, 0x26, 0x91, 0xbf, 0xdf, 0x3f, 0xcc, 0x75, 0x4f, 0x42, 0xc9,
+ 0xcb, 0xba, 0xc7, 0xb8, 0xe0, 0x20, 0x75, 0x43, 0xee, 0x87, 0x3d, 0x1b,
+ 0xe7, 0xf2, 0xe0, 0xc5, 0xcf, 0xf9, 0xba, 0x03, 0xbf, 0x17, 0xa7, 0xc5,
+ 0x59, 0xd4, 0x0c, 0xee, 0x3f, 0x28, 0x45, 0xe9, 0x1b, 0x75, 0x8c, 0x51,
+ 0x2b, 0xbb, 0xaf, 0x06, 0xe3, 0x11, 0x9a, 0x9a, 0x47, 0x6d, 0x7b, 0xfa,
+ 0x6f, 0x95, 0xbc, 0x1c, 0x5b, 0x18, 0x23, 0xdf, 0x3d, 0xfd, 0xd7, 0xc1,
+ 0xb8, 0x14, 0xe8, 0x43, 0xc0, 0xab, 0x6e, 0xe1, 0xd9, 0x15, 0xe4, 0x1c,
+ 0x2f, 0xf6, 0x6c, 0xfd, 0x3f, 0xef, 0xb8, 0xb5, 0x28, 0x64, 0x1e, 0xdf,
+ 0xe5, 0xd7, 0x67, 0xcd, 0xf3, 0x9d, 0x4d, 0xf3, 0xba, 0xfc, 0x0e, 0x5b,
+ 0xac, 0xb4, 0xbd, 0x07, 0x0f, 0x4c, 0x4b, 0x83, 0x46, 0xd5, 0xa6, 0x0f,
+ 0x3d, 0xfe, 0x5e, 0xe8, 0x88, 0x76, 0xf9, 0x0d, 0xcf, 0x91, 0xf7, 0x7a,
+ 0xb0, 0xf3, 0x91, 0x27, 0x77, 0xf9, 0xbe, 0x80, 0xfb, 0x49, 0xc5, 0xf7,
+ 0xef, 0x8f, 0x83, 0x0e, 0x64, 0xed, 0x36, 0xd7, 0x70, 0x7a, 0x70, 0x97,
+ 0xa2, 0x1f, 0x9f, 0xe1, 0xb3, 0x96, 0xb4, 0xb9, 0xd6, 0xe3, 0xba, 0x2f,
+ 0x8c, 0x01, 0x21, 0xad, 0xff, 0x48, 0xfa, 0x7c, 0xdf, 0x87, 0x9a, 0x8e,
+ 0x61, 0xc2, 0x71, 0x73, 0xfd, 0x17, 0x0f, 0xee, 0xe1, 0x98, 0xd7, 0x58,
+ 0xc0, 0xab, 0x16, 0xd0, 0xfb, 0x77, 0xcf, 0xf7, 0x3d, 0x8c, 0xaf, 0x37,
+ 0xe1, 0x5f, 0x40, 0xae, 0xc7, 0x77, 0x26, 0xbb, 0xe5, 0x77, 0xc9, 0x77,
+ 0x66, 0x3b, 0xe8, 0xed, 0x53, 0xc8, 0x59, 0x2d, 0x23, 0x73, 0x09, 0xb5,
+ 0xc7, 0x32, 0xdb, 0xc9, 0x08, 0xf3, 0x39, 0x90, 0x9e, 0xa6, 0x9b, 0x7b,
+ 0xfc, 0x5c, 0xfc, 0xab, 0xca, 0x47, 0xf9, 0x16, 0xc1, 0x3a, 0x3f, 0x6a,
+ 0x5a, 0x27, 0xdd, 0xb4, 0xce, 0x0a, 0xdb, 0x6c, 0xed, 0x4b, 0xd8, 0x73,
+ 0x69, 0xf7, 0xcd, 0x7a, 0x32, 0xa8, 0xcb, 0x1e, 0x1e, 0x69, 0xa3, 0x6a,
+ 0xaf, 0xb1, 0xf2, 0x1a, 0xf2, 0xf5, 0xe2, 0x08, 0xe6, 0x92, 0x03, 0x78,
+ 0xc7, 0xf3, 0x46, 0x8d, 0x84, 0xb1, 0x52, 0xa3, 0xcf, 0x01, 0xdf, 0x28,
+ 0x11, 0xf1, 0x3c, 0xf7, 0x25, 0x6f, 0xb5, 0xc0, 0x07, 0xa4, 0xd6, 0xb0,
+ 0xe7, 0x49, 0xd4, 0x5f, 0x47, 0x37, 0xea, 0x61, 0x5e, 0xe7, 0x56, 0x65,
+ 0x4d, 0xe6, 0xc6, 0xfb, 0x95, 0x52, 0xd2, 0xdf, 0xe3, 0xef, 0xc2, 0x5f,
+ 0xa8, 0x82, 0x71, 0xdf, 0x01, 0x6d, 0x85, 0x16, 0x4e, 0xa9, 0xf2, 0x0e,
+ 0xb6, 0x38, 0xc2, 0x67, 0xcd, 0xcf, 0x8f, 0x93, 0x5d, 0xb8, 0xa7, 0x3f,
+ 0x0d, 0xf6, 0x34, 0x16, 0xd4, 0xd3, 0xe1, 0x9e, 0x62, 0xf4, 0xe6, 0xac,
+ 0x0e, 0xdc, 0x9b, 0x20, 0x8f, 0x02, 0x2d, 0x35, 0xd2, 0x9f, 0x42, 0xa7,
+ 0xd2, 0x24, 0x1b, 0x6d, 0xdb, 0x19, 0x96, 0x36, 0x6b, 0xf8, 0xf1, 0x14,
+ 0xec, 0xf0, 0x78, 0x4f, 0x78, 0x37, 0xac, 0x9a, 0x1e, 0xd7, 0x3d, 0x68,
+ 0x3c, 0xdf, 0x0f, 0x5b, 0x4c, 0xc3, 0x3e, 0x39, 0x67, 0x2a, 0x70, 0xad,
+ 0xc2, 0xf6, 0xa4, 0x3b, 0xaa, 0xa1, 0x4f, 0x50, 0x06, 0xf5, 0x0e, 0xef,
+ 0x3f, 0x47, 0x8b, 0x8d, 0x90, 0x87, 0x2c, 0xec, 0x71, 0x14, 0xbf, 0x61,
+ 0xbc, 0xb3, 0xf0, 0xe3, 0x5a, 0x69, 0x85, 0x1e, 0x95, 0xb9, 0x38, 0x72,
+ 0xed, 0x41, 0xe6, 0xef, 0x4e, 0xc0, 0xb3, 0x3e, 0xb3, 0x9e, 0xde, 0x49,
+ 0x4e, 0x2f, 0xfb, 0x8a, 0x14, 0x68, 0x03, 0xc7, 0x5d, 0x87, 0xad, 0xf7,
+ 0xe3, 0x69, 0xe8, 0x45, 0x96, 0xad, 0xa4, 0xef, 0x79, 0x6a, 0x96, 0xbf,
+ 0x51, 0x5c, 0x08, 0xc6, 0x03, 0xfa, 0x3d, 0xac, 0x7b, 0xa9, 0x1b, 0x68,
+ 0x65, 0x3e, 0x8c, 0x83, 0x67, 0x60, 0x83, 0x7c, 0x67, 0x3b, 0x06, 0xb9,
+ 0xf0, 0x58, 0x09, 0xe2, 0x21, 0xe6, 0x17, 0x91, 0x94, 0xb4, 0xe7, 0x68,
+ 0x19, 0xf5, 0x3f, 0xf5, 0xf2, 0x13, 0xf9, 0xae, 0xbb, 0x33, 0xd0, 0xf7,
+ 0xad, 0xf8, 0xaa, 0xc9, 0xfd, 0x31, 0xf0, 0xa7, 0x35, 0xe1, 0x33, 0x8e,
+ 0x5f, 0x9f, 0xac, 0x11, 0xe2, 0x71, 0xca, 0xfb, 0x82, 0xc8, 0x3d, 0x4d,
+ 0xbf, 0x23, 0xf7, 0x54, 0xa7, 0x23, 0xf3, 0xa8, 0x6d, 0xb3, 0x03, 0x99,
+ 0x45, 0x32, 0x32, 0x27, 0x68, 0x48, 0x3f, 0x40, 0xaa, 0xfc, 0xd6, 0x97,
+ 0x16, 0xde, 0x17, 0x5a, 0x72, 0x9e, 0x77, 0x06, 0xbc, 0xbf, 0x28, 0xd7,
+ 0x79, 0x1a, 0xfc, 0x43, 0x56, 0xb2, 0x26, 0x61, 0x5e, 0xf1, 0x4c, 0x32,
+ 0xbf, 0x15, 0x3a, 0xd2, 0xf8, 0x61, 0x70, 0x36, 0x8f, 0x90, 0xe3, 0xbe,
+ 0xa5, 0x3a, 0x66, 0x05, 0xb0, 0xdf, 0x09, 0x78, 0xcb, 0x81, 0x5f, 0xac,
+ 0xdf, 0x58, 0x4f, 0xb2, 0x6f, 0xe0, 0x33, 0x77, 0x90, 0x35, 0x3a, 0x23,
+ 0xc8, 0xa3, 0x92, 0xd7, 0xf2, 0x03, 0x09, 0xda, 0xea, 0x07, 0x18, 0x2f,
+ 0xf1, 0x31, 0xba, 0xc2, 0x7c, 0x94, 0xa4, 0xff, 0x94, 0x71, 0x4b, 0xd2,
+ 0x53, 0xb7, 0xf9, 0x82, 0x6f, 0xc9, 0xe7, 0xaa, 0xca, 0xbe, 0x89, 0xe3,
+ 0x1f, 0xeb, 0x70, 0x27, 0xfc, 0x1f, 0x74, 0x10, 0x76, 0x9c, 0x9f, 0xe7,
+ 0xfb, 0x89, 0x41, 0xbe, 0x57, 0x3a, 0x57, 0xc0, 0xd9, 0x2e, 0xf0, 0xf7,
+ 0xc7, 0xa4, 0x5f, 0x63, 0xfa, 0xf5, 0x57, 0x9a, 0x7d, 0x21, 0xda, 0x92,
+ 0xf4, 0x93, 0x05, 0xf9, 0xbd, 0x31, 0x01, 0x18, 0x8f, 0x7d, 0x67, 0xd3,
+ 0xdf, 0x58, 0xbc, 0x6c, 0xfb, 0x7f, 0x63, 0x11, 0x7c, 0xfb, 0xad, 0xf9,
+ 0x79, 0xc4, 0x83, 0x75, 0x8d, 0x26, 0xeb, 0xe1, 0xdf, 0x5c, 0xf0, 0x39,
+ 0xc0, 0x37, 0xd7, 0xc3, 0xdc, 0xc1, 0x93, 0xf1, 0xa5, 0xbc, 0xe5, 0x2c,
+ 0x97, 0x82, 0x9c, 0x88, 0x6b, 0x00, 0x96, 0x21, 0xc6, 0x8b, 0xfe, 0xf9,
+ 0x2d, 0x88, 0x3d, 0x38, 0x3f, 0xc8, 0x1c, 0x7c, 0xbd, 0x39, 0xeb, 0xd7,
+ 0xb9, 0x65, 0xf6, 0x8b, 0xfd, 0x61, 0xdd, 0xbb, 0x9b, 0xca, 0x13, 0xfc,
+ 0x3e, 0x46, 0x6f, 0xcc, 0xc6, 0xe4, 0xfb, 0x22, 0xc5, 0x82, 0xf7, 0x3c,
+ 0x4e, 0x50, 0x51, 0xbe, 0xaf, 0x05, 0xf4, 0x50, 0xa7, 0xdd, 0x17, 0x8e,
+ 0x35, 0xe5, 0x48, 0xc3, 0xc7, 0x9b, 0x6a, 0xd4, 0xe8, 0xd1, 0xc6, 0x2a,
+ 0xf6, 0xaf, 0x50, 0x7e, 0xbc, 0x44, 0x37, 0x98, 0xba, 0x8c, 0xfb, 0x4e,
+ 0x82, 0x75, 0x8c, 0xf5, 0x6b, 0x4c, 0xd6, 0x9d, 0x25, 0xe4, 0x0b, 0xc5,
+ 0x11, 0xfe, 0xc6, 0xf3, 0xde, 0x5d, 0xc5, 0x8a, 0xa1, 0xdb, 0xf4, 0x81,
+ 0xe7, 0x68, 0x3c, 0x26, 0x21, 0x72, 0xab, 0x77, 0x3d, 0x58, 0xbf, 0x78,
+ 0x97, 0xbf, 0x57, 0xbc, 0xaf, 0x33, 0xac, 0x2a, 0xbf, 0xcd, 0xfe, 0xe4,
+ 0x76, 0x8d, 0xd6, 0x6e, 0xf7, 0xbc, 0xfb, 0x2d, 0x9d, 0x9c, 0xa0, 0x76,
+ 0xf5, 0xbf, 0xb9, 0xb7, 0xcb, 0x1c, 0xc4, 0x19, 0x49, 0x2b, 0x05, 0xd8,
+ 0xeb, 0xb2, 0x8b, 0x3a, 0x47, 0x18, 0xa3, 0xab, 0x42, 0x47, 0xcc, 0xe5,
+ 0x3b, 0x80, 0x3b, 0x7a, 0xf8, 0x7b, 0xf3, 0x8c, 0xc5, 0x30, 0x7d, 0xfe,
+ 0x5d, 0xd7, 0x2d, 0xf7, 0x49, 0x3f, 0x4b, 0x14, 0xc4, 0x9e, 0x5b, 0x9a,
+ 0x6d, 0xa2, 0x39, 0xb7, 0x64, 0x5b, 0xa0, 0x49, 0x0d, 0xbc, 0x94, 0x2b,
+ 0x61, 0x9e, 0xc6, 0x7f, 0x4b, 0xb0, 0x7a, 0xd7, 0x37, 0xc0, 0xe7, 0x34,
+ 0xf8, 0xe4, 0x7d, 0x4c, 0xd7, 0x43, 0x9d, 0x0b, 0x6b, 0x05, 0xee, 0x23,
+ 0xe6, 0xbb, 0x88, 0xf9, 0x2e, 0x62, 0xbe, 0x8b, 0x98, 0xef, 0x22, 0xe6,
+ 0xbb, 0x88, 0xf9, 0x2e, 0x62, 0xbe, 0x8b, 0x98, 0xef, 0x8e, 0x07, 0x79,
+ 0xda, 0x63, 0x1b, 0x79, 0xda, 0x4a, 0x83, 0xbf, 0x43, 0x49, 0x5e, 0x4a,
+ 0x25, 0xf2, 0xf3, 0x5c, 0x12, 0x9c, 0xd3, 0x84, 0x79, 0xee, 0xc7, 0x7f,
+ 0x13, 0xf1, 0xf1, 0x38, 0xc7, 0x63, 0xbc, 0x92, 0x22, 0x4c, 0xc6, 0xf3,
+ 0xf3, 0x3c, 0xae, 0xad, 0xb6, 0xe2, 0x20, 0x5f, 0xcb, 0xb1, 0x3f, 0x63,
+ 0xbb, 0x48, 0xfa, 0xf5, 0x62, 0xee, 0xf5, 0x2f, 0xa1, 0x76, 0x3c, 0x5e,
+ 0xac, 0xcb, 0x18, 0x8c, 0xf1, 0x7b, 0x18, 0x6b, 0xac, 0x73, 0xfc, 0xee,
+ 0x5e, 0xae, 0x27, 0x8a, 0xf5, 0x14, 0x95, 0x16, 0xc3, 0xfc, 0x07, 0x78,
+ 0xee, 0x90, 0x52, 0xa8, 0xf2, 0xd9, 0x0a, 0x9a, 0x4e, 0x42, 0x28, 0x66,
+ 0x73, 0x5e, 0x77, 0x49, 0xd6, 0x48, 0xfe, 0xdf, 0x05, 0x0d, 0x83, 0xb7,
+ 0xf0, 0x1e, 0x97, 0x48, 0x9d, 0x4d, 0xca, 0xbf, 0x31, 0x48, 0x98, 0x83,
+ 0xf2, 0x6f, 0x1d, 0xba, 0xb1, 0x8e, 0x98, 0xdd, 0x13, 0xfe, 0xed, 0x06,
+ 0xd7, 0x5d, 0xf6, 0xe6, 0xfd, 0x2b, 0xef, 0x23, 0x09, 0x7b, 0xbd, 0xa7,
+ 0x0f, 0x7b, 0xc3, 0xb9, 0x5e, 0xd9, 0x25, 0xf3, 0x6e, 0xf8, 0xce, 0x33,
+ 0x83, 0x37, 0xf5, 0x52, 0xe7, 0x6e, 0x5a, 0x1e, 0xe4, 0x1a, 0xad, 0x0d,
+ 0xf4, 0x18, 0xd6, 0xc8, 0xd8, 0x62, 0x37, 0x9d, 0x9d, 0x87, 0x6f, 0x9d,
+ 0x37, 0x2c, 0xfe, 0xfb, 0x82, 0x85, 0xc1, 0x24, 0x7c, 0xf2, 0x78, 0x2f,
+ 0xc7, 0xe4, 0xc5, 0x06, 0xeb, 0x4a, 0x37, 0xf0, 0xfb, 0xa1, 0x8b, 0x3b,
+ 0x60, 0x43, 0x02, 0xeb, 0x87, 0xb4, 0xff, 0x53, 0xd2, 0xee, 0x36, 0xf3,
+ 0x7d, 0x52, 0x37, 0x84, 0xa1, 0xa7, 0x05, 0x78, 0xff, 0x48, 0x6d, 0x69,
+ 0x11, 0x7f, 0x2f, 0x9c, 0x76, 0x9b, 0xbf, 0x1b, 0x0e, 0x29, 0xc5, 0x2a,
+ 0xff, 0x8d, 0xc3, 0x20, 0xfd, 0x4f, 0xe1, 0x56, 0x17, 0xd3, 0xd6, 0x79,
+ 0x86, 0xdf, 0xcf, 0xe6, 0x2f, 0xc4, 0x81, 0x13, 0xe2, 0x80, 0x41, 0x54,
+ 0xf3, 0x31, 0x07, 0xe2, 0xca, 0x44, 0x3d, 0x20, 0x32, 0x59, 0x15, 0x52,
+ 0x2d, 0xdb, 0x50, 0xb7, 0x5d, 0x36, 0x77, 0xcb, 0xa6, 0x4c, 0xda, 0x22,
+ 0x06, 0x49, 0x9b, 0x6a, 0xd2, 0x2e, 0x76, 0x31, 0xed, 0x2e, 0x96, 0x81,
+ 0x34, 0xcd, 0xec, 0x1a, 0x56, 0x32, 0xa4, 0x5d, 0x4c, 0xae, 0x31, 0x04,
+ 0x88, 0x53, 0xab, 0x5b, 0x2f, 0x32, 0x4d, 0x53, 0x90, 0x57, 0x25, 0xdd,
+ 0x4d, 0x6f, 0x76, 0x3f, 0x55, 0x64, 0xad, 0x72, 0xd1, 0x25, 0x6a, 0xa7,
+ 0x6a, 0x7f, 0x17, 0x67, 0xcf, 0xf3, 0x9d, 0x63, 0x20, 0x6c, 0xd5, 0x90,
+ 0xac, 0xf3, 0x9d, 0xef, 0x7c, 0xff, 0xdf, 0xfb, 0x3e, 0xef, 0x2f, 0x53,
+ 0xa0, 0x2f, 0xc3, 0x8a, 0xa9, 0x4b, 0x65, 0xb6, 0xb1, 0x50, 0xa6, 0x1d,
+ 0x7e, 0x13, 0xbc, 0xdc, 0x23, 0x8b, 0xa0, 0xe3, 0xfc, 0x68, 0xab, 0xe7,
+ 0x6f, 0xed, 0xf4, 0x78, 0x38, 0xd2, 0xeb, 0xc9, 0x28, 0xad, 0x4b, 0xe6,
+ 0xb5, 0x3e, 0xdd, 0x7d, 0xe8, 0xdb, 0x0f, 0xb0, 0xa6, 0x10, 0xce, 0x61,
+ 0xb8, 0x57, 0xe3, 0x91, 0x8f, 0xef, 0x7d, 0x87, 0xde, 0x7b, 0x0f, 0xbd,
+ 0x9f, 0xfc, 0x1f, 0xed, 0x59, 0x3e, 0x4c, 0x0f, 0x5c, 0xa7, 0x19, 0xe7,
+ 0x2c, 0xf9, 0xc2, 0x84, 0x9a, 0x2b, 0x98, 0x09, 0xea, 0x02, 0x29, 0x71,
+ 0x54, 0xca, 0x6e, 0x03, 0xc6, 0xb5, 0xc9, 0xc2, 0x0a, 0x68, 0x1e, 0xfb,
+ 0x68, 0xb7, 0x18, 0x2f, 0x7f, 0xb6, 0x97, 0x3c, 0xd3, 0x81, 0x6b, 0xf0,
+ 0x59, 0x43, 0x21, 0xb4, 0x73, 0x5e, 0xb3, 0x63, 0xc6, 0x45, 0xed, 0xbf,
+ 0xa1, 0x0e, 0xe3, 0xa8, 0xbc, 0xce, 0xfd, 0x60, 0x9b, 0x16, 0x79, 0x60,
+ 0x25, 0x7b, 0xbc, 0x5c, 0x22, 0xd8, 0xbb, 0x2f, 0xf6, 0x52, 0xbf, 0x78,
+ 0xd5, 0xde, 0xab, 0x33, 0x76, 0x85, 0x79, 0x5a, 0x20, 0x9a, 0x97, 0x45,
+ 0xca, 0x55, 0x91, 0x9b, 0xf8, 0xfd, 0xb1, 0xea, 0xc5, 0x2f, 0x14, 0x6d,
+ 0xed, 0x49, 0xd9, 0x2e, 0x3d, 0x2b, 0x35, 0xc8, 0x9c, 0x2d, 0xdb, 0x71,
+ 0x1e, 0xda, 0x61, 0x7d, 0xe6, 0xaf, 0x17, 0x94, 0x44, 0xc6, 0x28, 0xd3,
+ 0xda, 0xe4, 0x67, 0x2b, 0xcc, 0xbb, 0x33, 0x8d, 0x87, 0xc2, 0xfc, 0xb7,
+ 0x90, 0x64, 0x82, 0x7e, 0xad, 0x97, 0xca, 0xb7, 0x45, 0x3e, 0xc1, 0xb7,
+ 0x4f, 0x56, 0x5e, 0xe9, 0xa5, 0xcf, 0xe5, 0xe3, 0x15, 0xbe, 0xfb, 0xf0,
+ 0xf4, 0x49, 0xc3, 0xf2, 0x43, 0x7f, 0x05, 0xf0, 0x18, 0x3c, 0x77, 0xee,
+ 0xf7, 0x47, 0x5c, 0x1b, 0xea, 0x68, 0xc3, 0xb6, 0x49, 0x7e, 0x18, 0x38,
+ 0xa8, 0x86, 0x74, 0xbe, 0x52, 0x23, 0xa8, 0x71, 0xd9, 0x5f, 0x61, 0x5e,
+ 0x9d, 0x71, 0x54, 0x63, 0x74, 0xf2, 0xf6, 0x82, 0xde, 0x0b, 0xca, 0xb9,
+ 0x8a, 0x4d, 0x5a, 0x35, 0x64, 0x0b, 0xbc, 0xb6, 0x59, 0xdf, 0xea, 0xe3,
+ 0x5d, 0x6d, 0xd7, 0x17, 0x7b, 0x5d, 0x1b, 0x8d, 0x75, 0xaf, 0xf7, 0xba,
+ 0x75, 0x61, 0xcf, 0xe6, 0xa2, 0x6d, 0x56, 0xc6, 0xde, 0x7e, 0x2c, 0xf5,
+ 0xd5, 0x9f, 0xca, 0x9d, 0xd2, 0x4f, 0xe4, 0xb7, 0xab, 0xe7, 0xa1, 0x73,
+ 0x98, 0xe5, 0x1c, 0xe4, 0xc9, 0xbb, 0x75, 0xc7, 0x79, 0xd7, 0x3e, 0x07,
+ 0xfb, 0xc0, 0x71, 0xfe, 0x64, 0xef, 0x48, 0x64, 0xfc, 0x7b, 0xd8, 0x73,
+ 0x16, 0x3c, 0x44, 0x2c, 0xcc, 0x80, 0xde, 0x52, 0x7d, 0xd2, 0x19, 0xd0,
+ 0x74, 0x32, 0x34, 0xde, 0x8a, 0x3d, 0xf8, 0x3c, 0x3d, 0x9c, 0x7b, 0x49,
+ 0xf7, 0x91, 0x66, 0x7c, 0xf5, 0x0a, 0xe6, 0x6f, 0x05, 0x5f, 0x1c, 0xc5,
+ 0x4f, 0xc9, 0xc3, 0x31, 0xac, 0x75, 0x8c, 0xb4, 0xd7, 0x2a, 0x91, 0x67,
+ 0xb0, 0x8f, 0x6c, 0x8b, 0x3c, 0x2a, 0xdc, 0xea, 0xa5, 0x3f, 0xef, 0x51,
+ 0x81, 0x65, 0xdf, 0x57, 0xbb, 0xc4, 0x91, 0x16, 0xc8, 0xef, 0x85, 0x09,
+ 0x57, 0x57, 0xfa, 0x83, 0x3a, 0x85, 0xf6, 0x56, 0xee, 0x7d, 0x45, 0xdd,
+ 0x2e, 0xe7, 0xb4, 0x42, 0x17, 0x9f, 0x82, 0x0e, 0x94, 0xac, 0x5f, 0x91,
+ 0xc6, 0x58, 0x00, 0x6d, 0xa8, 0xa3, 0x68, 0x2c, 0x91, 0x54, 0x81, 0xf9,
+ 0x5d, 0xcc, 0xb5, 0xc2, 0x1a, 0xcf, 0x11, 0x37, 0xb8, 0xc6, 0x36, 0xc6,
+ 0xe0, 0xbc, 0x3a, 0x0b, 0x34, 0xc2, 0x3a, 0xd2, 0x77, 0x02, 0x3c, 0x99,
+ 0xa0, 0xdc, 0xc4, 0x78, 0xa3, 0x18, 0x8f, 0xe5, 0x2e, 0x8c, 0x77, 0x45,
+ 0x92, 0x76, 0x73, 0xcc, 0x38, 0xda, 0x10, 0x67, 0xe2, 0xd0, 0x1f, 0x06,
+ 0x55, 0x7a, 0x25, 0x08, 0xf9, 0xdd, 0x2b, 0x69, 0xe3, 0xc8, 0x81, 0x3d,
+ 0xe6, 0xb4, 0x7d, 0xe0, 0xf3, 0x8d, 0x7a, 0x6b, 0xea, 0x3a, 0xb0, 0x26,
+ 0xf6, 0xc7, 0x0f, 0xb6, 0x71, 0x72, 0x65, 0x09, 0x38, 0xb5, 0xf4, 0x41,
+ 0xd2, 0xbe, 0x20, 0xa9, 0x20, 0xd7, 0xc4, 0xfa, 0x20, 0xd6, 0x4c, 0x3f,
+ 0xd6, 0x77, 0x81, 0x43, 0x47, 0xbc, 0x3a, 0xb6, 0x15, 0x5f, 0x12, 0x67,
+ 0xef, 0xda, 0xb5, 0xac, 0xfb, 0x8a, 0x24, 0x97, 0xb2, 0x32, 0xad, 0xfb,
+ 0xf1, 0x0c, 0x07, 0xb4, 0xee, 0x41, 0x5e, 0x8d, 0x9c, 0xc0, 0x59, 0xc6,
+ 0xf6, 0x6d, 0xe0, 0xf0, 0x09, 0x72, 0x91, 0xd1, 0xe7, 0xf2, 0x2c, 0xbe,
+ 0x9d, 0xe0, 0x1d, 0xb5, 0x49, 0xe4, 0x5b, 0x90, 0x91, 0x85, 0x66, 0x7d,
+ 0x40, 0x3e, 0x2d, 0xf4, 0xf4, 0x31, 0xce, 0xf2, 0xd7, 0x82, 0x21, 0x1f,
+ 0x17, 0x74, 0x2c, 0x74, 0xc6, 0x2f, 0xe6, 0x65, 0xd7, 0x3e, 0x1f, 0x9e,
+ 0x59, 0x50, 0xfc, 0x3e, 0x7c, 0x79, 0x5d, 0x75, 0xa0, 0x6d, 0x00, 0xed,
+ 0xb8, 0x0e, 0x43, 0xa6, 0x0a, 0x9f, 0x3b, 0xb3, 0x23, 0x8e, 0x33, 0xad,
+ 0xf3, 0xc3, 0x62, 0xc6, 0x82, 0x6a, 0xea, 0xe4, 0x51, 0x29, 0x04, 0xdb,
+ 0x31, 0x57, 0xcc, 0x58, 0x57, 0xc3, 0x58, 0x0f, 0xcb, 0x27, 0xc8, 0x13,
+ 0xa1, 0x1d, 0xe1, 0xf8, 0x66, 0x66, 0x4d, 0xc5, 0xc2, 0x43, 0xca, 0x4c,
+ 0xe4, 0xf1, 0x6b, 0x51, 0x3a, 0x8e, 0x18, 0x0a, 0x2b, 0xf0, 0x2e, 0xf6,
+ 0x64, 0x9d, 0x76, 0x9c, 0x8c, 0xc5, 0xfa, 0x98, 0x11, 0x50, 0xf4, 0xb7,
+ 0x74, 0xea, 0x78, 0xe3, 0xb5, 0x93, 0x31, 0xe3, 0xb4, 0x3a, 0xee, 0xbd,
+ 0xc7, 0x81, 0x99, 0x7b, 0xe3, 0x9d, 0x5f, 0x53, 0x86, 0xbc, 0x51, 0x88,
+ 0x85, 0xe7, 0x94, 0x99, 0xc5, 0x98, 0xd9, 0xb4, 0x22, 0x6e, 0xc4, 0x8c,
+ 0x4e, 0x45, 0x9f, 0x68, 0xbb, 0xde, 0x77, 0x06, 0xfd, 0x63, 0xaa, 0xc5,
+ 0x5b, 0x0f, 0xef, 0xeb, 0xed, 0x3e, 0x97, 0x67, 0x88, 0x39, 0x23, 0xc0,
+ 0x4c, 0xe6, 0x9a, 0xe9, 0xdc, 0x86, 0x44, 0x64, 0x7c, 0x44, 0x63, 0xe8,
+ 0xe3, 0x33, 0x7f, 0x47, 0x1d, 0xca, 0x65, 0xd6, 0x45, 0x3d, 0x7e, 0x1b,
+ 0xd1, 0x3a, 0xf3, 0xe3, 0x33, 0x39, 0x9d, 0xf7, 0xd8, 0x50, 0x11, 0x6f,
+ 0xdf, 0x7b, 0x77, 0x16, 0x4e, 0xda, 0x4f, 0x71, 0x9c, 0x25, 0xff, 0x64,
+ 0xbb, 0x30, 0xa7, 0x74, 0xaa, 0xd4, 0xa4, 0x0d, 0xfa, 0x03, 0x98, 0x2f,
+ 0xd0, 0x8c, 0x7b, 0x5f, 0x11, 0xdf, 0x78, 0xc7, 0x01, 0x3a, 0x81, 0xae,
+ 0x09, 0x1d, 0xb5, 0x8a, 0x71, 0xf2, 0x2b, 0x92, 0x73, 0xfb, 0x4b, 0x07,
+ 0x73, 0x58, 0xf3, 0xd5, 0x2f, 0x1b, 0x83, 0x73, 0x63, 0x0e, 0xbc, 0x3f,
+ 0x3e, 0x43, 0xfa, 0xe4, 0xd9, 0x84, 0xd5, 0xd4, 0x2a, 0xd7, 0x33, 0x20,
+ 0xd3, 0x2b, 0x83, 0x32, 0x87, 0xdf, 0xc2, 0x8a, 0x7b, 0x6f, 0x1b, 0xd0,
+ 0xad, 0xa7, 0x0b, 0x86, 0xe6, 0xd7, 0x39, 0x9b, 0x31, 0x13, 0xf0, 0x8a,
+ 0xce, 0xa9, 0x62, 0x5f, 0xc6, 0x89, 0x06, 0x29, 0x1f, 0xed, 0x06, 0xe4,
+ 0xea, 0x46, 0x9d, 0x7a, 0x2a, 0xeb, 0xcd, 0x78, 0xd8, 0xdf, 0x2d, 0x0b,
+ 0xc0, 0xbb, 0x0a, 0x64, 0x67, 0xfe, 0xcd, 0x80, 0xcc, 0x15, 0x74, 0x3c,
+ 0x39, 0xfc, 0x17, 0x65, 0x4b, 0xad, 0x3e, 0x21, 0xb7, 0xeb, 0x51, 0xfd,
+ 0x8d, 0x72, 0x2d, 0xff, 0x0b, 0x9f, 0xbc, 0x32, 0xa2, 0xf3, 0xea, 0xa2,
+ 0x15, 0x79, 0xaa, 0x9f, 0x3a, 0xcf, 0xba, 0xce, 0xb1, 0x03, 0x76, 0x40,
+ 0xe7, 0x78, 0x0f, 0x3a, 0xc7, 0x6f, 0xa0, 0x73, 0xfc, 0xba, 0x04, 0x7c,
+ 0x29, 0x65, 0x3c, 0xfc, 0x9f, 0x01, 0x0e, 0x51, 0x56, 0x9b, 0xe7, 0x71,
+ 0xa7, 0x33, 0x39, 0xd0, 0xe0, 0x47, 0x92, 0x01, 0xde, 0x26, 0x65, 0x73,
+ 0x75, 0x5a, 0xb6, 0x56, 0xdd, 0x3c, 0xe5, 0xfb, 0xcc, 0x01, 0x1b, 0xe3,
+ 0x3d, 0x45, 0x81, 0x43, 0x47, 0x24, 0x72, 0x9a, 0xf8, 0xd1, 0x21, 0x6b,
+ 0xc5, 0xdf, 0x69, 0x1c, 0x5a, 0x2b, 0xb2, 0xec, 0x17, 0x9d, 0x4f, 0x76,
+ 0x6e, 0x47, 0x2a, 0x76, 0x03, 0xf5, 0xc7, 0xb4, 0x0f, 0xc8, 0xf5, 0xc9,
+ 0x13, 0x2f, 0x3f, 0xf7, 0xee, 0x5e, 0xe9, 0x3c, 0xbb, 0x59, 0xa3, 0x1b,
+ 0xed, 0x9a, 0xd8, 0x35, 0xe4, 0xc6, 0xbc, 0xd5, 0xdf, 0xd0, 0x06, 0x73,
+ 0x94, 0xba, 0x65, 0x03, 0x32, 0xa4, 0x11, 0xed, 0xd6, 0xba, 0x5f, 0x23,
+ 0x3a, 0xa8, 0x73, 0x77, 0x39, 0x4e, 0xbe, 0x68, 0xc9, 0x7c, 0xd1, 0x0c,
+ 0xe7, 0x40, 0x7f, 0xb7, 0x61, 0xab, 0x6d, 0xe2, 0x0e, 0xb6, 0x70, 0x06,
+ 0xdb, 0x75, 0xca, 0xf9, 0x2f, 0x34, 0xf6, 0xae, 0xd5, 0x3f, 0xc3, 0x38,
+ 0xe6, 0xf9, 0x84, 0x3c, 0xee, 0x23, 0x06, 0xd2, 0x1f, 0x95, 0xd2, 0xfd,
+ 0xdd, 0x7e, 0x9b, 0x68, 0xbb, 0x55, 0x27, 0x1e, 0x8b, 0x5c, 0x2d, 0x58,
+ 0x90, 0x25, 0xbf, 0x0a, 0x51, 0x07, 0x28, 0xab, 0x66, 0x3f, 0xc7, 0x5b,
+ 0xb3, 0xe3, 0x1c, 0xb5, 0xb8, 0xae, 0xa8, 0x87, 0xdb, 0x94, 0xfd, 0x3b,
+ 0x5a, 0xee, 0x17, 0x4a, 0x17, 0xe4, 0x1d, 0xdc, 0xb7, 0xab, 0xe3, 0x64,
+ 0xe5, 0x16, 0x74, 0xbc, 0x7a, 0xa9, 0x99, 0xd7, 0x3d, 0x89, 0x73, 0x32,
+ 0xd5, 0xfc, 0xf2, 0x75, 0xb9, 0x76, 0x63, 0x57, 0xbd, 0x71, 0x23, 0xa2,
+ 0xae, 0x2f, 0x0f, 0xa9, 0xfc, 0xb2, 0xe3, 0xfc, 0xd3, 0x9e, 0x95, 0x3b,
+ 0xab, 0x8e, 0x9c, 0xb5, 0x7d, 0xfd, 0x7e, 0x69, 0xe6, 0xd6, 0x39, 0x4e,
+ 0x07, 0xb0, 0x79, 0xfb, 0xa4, 0xe3, 0x3c, 0x3d, 0x36, 0x26, 0xd1, 0x93,
+ 0xd4, 0x51, 0x9e, 0x0b, 0x31, 0x3f, 0x96, 0x98, 0x93, 0xb4, 0xac, 0xcb,
+ 0x15, 0xa5, 0x80, 0x6f, 0xdd, 0xae, 0xfe, 0xf2, 0xcc, 0x31, 0x2f, 0x56,
+ 0x72, 0xe7, 0x35, 0xfa, 0x92, 0x43, 0xff, 0xe5, 0x4b, 0x36, 0xe4, 0x62,
+ 0x71, 0x04, 0xfd, 0x83, 0xf2, 0xc3, 0x62, 0xe0, 0x50, 0xd9, 0xc0, 0x73,
+ 0x54, 0xe5, 0x8b, 0x8f, 0x9c, 0x21, 0x1d, 0x33, 0x80, 0x4e, 0x62, 0x38,
+ 0xce, 0x9c, 0xcd, 0xf9, 0xba, 0x31, 0xdf, 0x8e, 0x71, 0x0c, 0xf2, 0xff,
+ 0xac, 0x96, 0xcf, 0x17, 0x15, 0x6c, 0x5f, 0xf0, 0x77, 0x50, 0xd2, 0x45,
+ 0xc8, 0x78, 0xc5, 0x9c, 0x53, 0xea, 0x0a, 0x66, 0x68, 0x0e, 0xd8, 0x31,
+ 0x0b, 0xbc, 0x79, 0x49, 0xc7, 0x56, 0x4f, 0x68, 0xec, 0x99, 0x67, 0x39,
+ 0x2b, 0x89, 0x8a, 0xdd, 0xa3, 0xcf, 0x6f, 0xf7, 0xf6, 0x2f, 0x43, 0xee,
+ 0x9d, 0x83, 0x8f, 0xb3, 0x4a, 0xda, 0x60, 0x03, 0xa5, 0xd6, 0xcf, 0x81,
+ 0x27, 0x42, 0x38, 0xdb, 0x56, 0xcd, 0x0f, 0x0d, 0xc8, 0xef, 0x86, 0xf6,
+ 0x23, 0xba, 0xf1, 0x8a, 0x86, 0xc1, 0x76, 0x17, 0xd0, 0xaf, 0x5d, 0x92,
+ 0xcb, 0x6d, 0x1a, 0x57, 0x9f, 0xac, 0x4b, 0x40, 0x0f, 0xf9, 0x3e, 0xca,
+ 0x7e, 0xd4, 0x85, 0xbd, 0xb2, 0x0f, 0xe5, 0x19, 0x94, 0x5b, 0xf0, 0x64,
+ 0x9b, 0x61, 0xe8, 0x15, 0x78, 0xbe, 0x8d, 0xf1, 0xc6, 0xb0, 0xe6, 0xac,
+ 0x21, 0x1f, 0x9e, 0xa1, 0x2c, 0x19, 0x55, 0xcc, 0x63, 0x9e, 0xb3, 0xf0,
+ 0xac, 0x0d, 0xa9, 0xd4, 0x12, 0xcb, 0x78, 0x96, 0xdd, 0xef, 0x4f, 0x60,
+ 0x12, 0xfa, 0x24, 0x6f, 0xb8, 0x98, 0xf4, 0xe1, 0x1e, 0x26, 0xb1, 0xae,
+ 0x5d, 0xd2, 0xcb, 0xe4, 0x75, 0x03, 0xf4, 0xd6, 0x29, 0xa9, 0x1b, 0x41,
+ 0xad, 0x8f, 0x56, 0x40, 0x8b, 0x1b, 0xa0, 0xab, 0x35, 0xd0, 0x54, 0xb2,
+ 0x68, 0xc6, 0x67, 0x54, 0x58, 0xfb, 0x02, 0x5e, 0x00, 0xbd, 0x76, 0xbc,
+ 0x49, 0x5d, 0x94, 0xbc, 0x1c, 0x05, 0xed, 0x89, 0xd3, 0x61, 0x59, 0x99,
+ 0xa8, 0xb2, 0x40, 0x83, 0xa0, 0xcb, 0xa2, 0xcb, 0xd3, 0xef, 0x2b, 0x8d,
+ 0xab, 0xf1, 0x07, 0x12, 0x4b, 0x3c, 0x10, 0x13, 0x58, 0x60, 0xda, 0x1f,
+ 0x88, 0x8d, 0x31, 0x27, 0xe4, 0x26, 0xe6, 0xf1, 0x81, 0xbf, 0x47, 0x4e,
+ 0x69, 0xfe, 0x8e, 0x8b, 0xff, 0x30, 0x8f, 0x83, 0xde, 0x80, 0x41, 0x2e,
+ 0x4f, 0x27, 0x3c, 0x1a, 0xfd, 0x26, 0xf8, 0xd7, 0x84, 0x25, 0x16, 0x94,
+ 0x05, 0xf0, 0xff, 0x06, 0xbe, 0xdf, 0xad, 0x0f, 0xab, 0xf9, 0x25, 0xe5,
+ 0xe5, 0x92, 0x7c, 0x07, 0x7a, 0xf2, 0x43, 0x9c, 0x5d, 0x97, 0xd6, 0xdd,
+ 0x23, 0x63, 0x8c, 0x9f, 0x65, 0xd4, 0x35, 0xeb, 0xb4, 0xec, 0x8e, 0x4e,
+ 0xa0, 0x7c, 0x0c, 0x4f, 0x1f, 0xce, 0x21, 0xa0, 0xe3, 0xdf, 0x6b, 0x05,
+ 0x5b, 0xb9, 0xff, 0xd3, 0x30, 0x8e, 0xbe, 0xc4, 0xb2, 0x93, 0xf8, 0x4e,
+ 0x5f, 0x0c, 0xf7, 0x06, 0x9d, 0x49, 0x85, 0x74, 0xbe, 0x69, 0x05, 0xba,
+ 0xc4, 0x3a, 0xc6, 0xbb, 0x47, 0x5f, 0x5e, 0x0d, 0x3c, 0x3c, 0xfa, 0x2f,
+ 0x27, 0x11, 0x64, 0x4e, 0xfb, 0x17, 0x21, 0x57, 0xfe, 0x7d, 0xea, 0xec,
+ 0x5a, 0xf3, 0x71, 0x1f, 0x5e, 0x3e, 0x32, 0x82, 0x68, 0x0b, 0x59, 0x06,
+ 0x59, 0x54, 0xd6, 0xf4, 0xcb, 0x76, 0x6e, 0xdf, 0x7c, 0x2d, 0x66, 0xdc,
+ 0x17, 0xb7, 0xef, 0x82, 0x45, 0xb9, 0xd3, 0x0e, 0x7c, 0x09, 0x6b, 0xbd,
+ 0xf2, 0x9e, 0x95, 0x03, 0x2a, 0x98, 0xe1, 0x0c, 0x68, 0xb4, 0x4d, 0xcc,
+ 0xe8, 0x94, 0xec, 0xcf, 0x3b, 0xa7, 0xfb, 0xb2, 0x6d, 0xb3, 0x6f, 0x73,
+ 0x5e, 0xae, 0x9f, 0x7b, 0xe1, 0x1e, 0xe8, 0x9b, 0x36, 0x34, 0x8d, 0x36,
+ 0x6a, 0x03, 0xfd, 0x2e, 0x8d, 0x36, 0xf7, 0x11, 0xfc, 0x3f, 0xfb, 0x20,
+ 0x9d, 0xd8, 0xca, 0x8d, 0xd3, 0xe3, 0x59, 0xe3, 0x79, 0x0e, 0x83, 0x36,
+ 0x0e, 0xd2, 0x4f, 0xd3, 0xb7, 0xe8, 0xd2, 0xcf, 0xd3, 0x7b, 0xf4, 0x43,
+ 0xba, 0xe9, 0x94, 0xf4, 0x0d, 0x4b, 0xa6, 0x8b, 0xfa, 0xbe, 0xa1, 0x6b,
+ 0xd2, 0x67, 0x34, 0x01, 0xba, 0x21, 0xad, 0x93, 0xb7, 0x0c, 0x29, 0x83,
+ 0x8e, 0xca, 0xc0, 0xa7, 0x32, 0x68, 0xaa, 0x02, 0x7c, 0x2b, 0x03, 0xdf,
+ 0xca, 0x75, 0x33, 0x5a, 0xc5, 0x9e, 0x29, 0xb3, 0xd7, 0x41, 0x47, 0x1b,
+ 0x75, 0xde, 0xbf, 0x5e, 0xb3, 0x41, 0x39, 0x78, 0x77, 0xef, 0xee, 0xff,
+ 0x81, 0xbb, 0x1f, 0x94, 0xdb, 0xb0, 0x5b, 0xde, 0x29, 0x8d, 0x02, 0x93,
+ 0x04, 0x18, 0x65, 0x83, 0x36, 0xe2, 0xb2, 0x59, 0x9a, 0x94, 0x2d, 0xc8,
+ 0xa7, 0xed, 0xd5, 0x08, 0xf4, 0xe9, 0x90, 0xcc, 0xbf, 0x35, 0x22, 0xb7,
+ 0x56, 0x95, 0xcc, 0x82, 0x7e, 0xf3, 0x6b, 0xf4, 0xbb, 0x83, 0x9e, 0xcb,
+ 0x9d, 0x3a, 0x4e, 0x9f, 0xae, 0xba, 0xfe, 0xf7, 0xa9, 0x6a, 0x97, 0x4c,
+ 0x57, 0x0d, 0x79, 0xbe, 0xda, 0x23, 0x2f, 0x56, 0x83, 0x72, 0x16, 0x76,
+ 0xe0, 0xd7, 0xaa, 0x03, 0xf2, 0x52, 0x75, 0x50, 0xbe, 0x5e, 0x0b, 0xcb,
+ 0x37, 0x6a, 0x96, 0x64, 0x6b, 0x51, 0xc9, 0xd4, 0x46, 0xe5, 0x85, 0x1a,
+ 0xfd, 0xea, 0x98, 0x0f, 0xbf, 0xd4, 0x9e, 0xbf, 0x82, 0xeb, 0xea, 0xc0,
+ 0xba, 0xa2, 0x6a, 0x4a, 0xc7, 0x29, 0x25, 0xeb, 0xfa, 0x3c, 0x44, 0x2e,
+ 0x61, 0xac, 0xc5, 0xb7, 0x94, 0x54, 0xf4, 0xfc, 0xcd, 0xff, 0x33, 0x09,
+ 0x68, 0xdb, 0xe8, 0x52, 0x79, 0x00, 0x6d, 0x20, 0xf7, 0x0a, 0x4d, 0xdf,
+ 0x47, 0xd3, 0xe7, 0xdf, 0xb4, 0xbd, 0x7c, 0xda, 0x6f, 0x7d, 0x97, 0xb6,
+ 0x97, 0x3e, 0x7b, 0xe2, 0x07, 0xed, 0x9c, 0x9b, 0xda, 0x6f, 0xb2, 0x1f,
+ 0xdb, 0x68, 0xce, 0xbb, 0x98, 0x7d, 0xf2, 0xff, 0x59, 0xdc, 0x18, 0xd5,
+ 0xc5, 0xda, 0x00, 0xff, 0xaf, 0x05, 0x6b, 0xf9, 0xf2, 0xdc, 0xf1, 0xe9,
+ 0x52, 0x5a, 0x3d, 0x5f, 0xa2, 0x46, 0xe3, 0xc8, 0xe2, 0x5e, 0x4e, 0xdc,
+ 0x73, 0xb2, 0x66, 0x07, 0xf4, 0x1a, 0x5c, 0x5f, 0x7d, 0x42, 0xe7, 0xc7,
+ 0xa5, 0x4f, 0x91, 0xfe, 0x18, 0x7b, 0xeb, 0xf2, 0xe2, 0x09, 0xd0, 0x6d,
+ 0x6d, 0x43, 0xae, 0x56, 0x5d, 0x9f, 0xd5, 0xbc, 0xa6, 0x97, 0x7b, 0xa0,
+ 0x39, 0xc6, 0x1c, 0xdc, 0x67, 0xae, 0xec, 0xf6, 0x4d, 0xe1, 0xde, 0x60,
+ 0x8f, 0x63, 0xbf, 0xbe, 0x1e, 0xce, 0xc5, 0xff, 0xe3, 0x41, 0xd9, 0x5b,
+ 0x2f, 0x73, 0x8d, 0x2d, 0x4d, 0x8b, 0x6e, 0x5c, 0x37, 0x2a, 0xaf, 0xe2,
+ 0xfc, 0x2a, 0x06, 0xd7, 0xdf, 0x21, 0x95, 0x28, 0x6d, 0x5b, 0xe2, 0xf7,
+ 0x29, 0x29, 0x63, 0x9e, 0x4a, 0xb4, 0xe9, 0x0f, 0x73, 0x71, 0xb6, 0x62,
+ 0xec, 0xcf, 0x3b, 0x53, 0x3e, 0x8e, 0x77, 0xd4, 0x45, 0xa1, 0x33, 0x9d,
+ 0xe3, 0xfb, 0x22, 0xca, 0xf4, 0x8d, 0xcc, 0xe3, 0x19, 0xf2, 0xea, 0xde,
+ 0xeb, 0xd7, 0xba, 0xfa, 0xe4, 0x7e, 0xbf, 0xd9, 0xb2, 0x99, 0x4b, 0xfa,
+ 0x63, 0xca, 0xf7, 0xf3, 0xdf, 0xf7, 0x13, 0x73, 0x8f, 0x5b, 0xfc, 0x05,
+ 0xe4, 0x33, 0x43, 0xfb, 0x14, 0xbc, 0x6f, 0x47, 0xe4, 0x65, 0x83, 0x79,
+ 0xec, 0x09, 0x95, 0x2e, 0x5d, 0xf7, 0x72, 0x7c, 0x63, 0xea, 0x78, 0xe5,
+ 0x7e, 0xbf, 0x9b, 0xf3, 0xce, 0xb1, 0x0f, 0xe6, 0xb9, 0x1f, 0xa4, 0x13,
+ 0xe6, 0xbb, 0xb7, 0xef, 0xfd, 0x0f, 0x55, 0xa5, 0x00, 0xbc, 0xb3, 0x5a,
+ 0x34, 0x3f, 0xe6, 0x6b, 0xff, 0x76, 0x76, 0x34, 0x3f, 0x37, 0x7d, 0x0c,
+ 0x7f, 0xee, 0xa7, 0x6d, 0x4b, 0xdc, 0xb8, 0xea, 0xe6, 0x8e, 0x6a, 0x1b,
+ 0x1a, 0x58, 0x81, 0x3a, 0xf2, 0x2a, 0xf8, 0x64, 0xaf, 0x2d, 0xff, 0xfe,
+ 0x03, 0x9a, 0xb8, 0x8a, 0x6c, 0x8c, 0x67, 0x00, 0x00, 0x00 };
static const u32 bnx2_RXP_b09FwData[(0x0/4) + 1] = { 0x0 };
static const u32 bnx2_RXP_b09FwRodata[(0x278/4) + 1] = {
- 0x08004050, 0x08003f50, 0x08003ff4, 0x0800400c, 0x08004024, 0x08004044,
- 0x08004050, 0x08004050, 0x08003f58, 0x00000000, 0x08004a0c, 0x08004a44,
- 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004a7c, 0x08004c40,
- 0x08004b88, 0x08004bc0, 0x08004c40, 0x08004b10, 0x08004c40, 0x08004c40,
- 0x08004bc0, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
- 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c00,
- 0x08004c40, 0x08004c00, 0x08004b88, 0x08004c40, 0x08004c40, 0x08004c00,
- 0x08004c00, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
- 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
- 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
- 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
- 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
- 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
- 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
- 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
- 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
- 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
- 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
- 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
- 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
- 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
- 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
- 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
- 0x08004aec, 0x00000000, 0x08006058, 0x08006070, 0x08006070, 0x08006070,
- 0x08006058, 0x08006070, 0x08006070, 0x08006070, 0x08006058, 0x08006070,
- 0x08006070, 0x08006070, 0x08006058, 0x08006070, 0x08006070, 0x08006070,
- 0x08006064, 0x00000000, 0x00000000 };
+ 0x08004070, 0x08003f70, 0x08004014, 0x0800402c, 0x08004044, 0x08004064,
+ 0x08004070, 0x08004070, 0x08003f78, 0x00000000, 0x08004a2c, 0x08004a64,
+ 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004a9c, 0x08004c60,
+ 0x08004ba8, 0x08004be0, 0x08004c60, 0x08004b30, 0x08004c60, 0x08004c60,
+ 0x08004be0, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60,
+ 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c20,
+ 0x08004c60, 0x08004c20, 0x08004ba8, 0x08004c60, 0x08004c60, 0x08004c20,
+ 0x08004c20, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60,
+ 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60,
+ 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60,
+ 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60,
+ 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60,
+ 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60,
+ 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60,
+ 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60,
+ 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60,
+ 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60,
+ 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60,
+ 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60,
+ 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60,
+ 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60,
+ 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60,
+ 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60, 0x08004c60,
+ 0x08004b0c, 0x00000000, 0x08006078, 0x08006090, 0x08006090, 0x08006090,
+ 0x08006078, 0x08006090, 0x08006090, 0x08006090, 0x08006078, 0x08006090,
+ 0x08006090, 0x08006090, 0x08006078, 0x08006090, 0x08006090, 0x08006090,
+ 0x08006084, 0x00000000, 0x00000000 };
static struct fw_info bnx2_rxp_fw_09 = {
+ /* Firmware version: 3.7.1 */
.ver_major = 0x3,
- .ver_minor = 0x4,
- .ver_fix = 0x3,
+ .ver_minor = 0x7,
+ .ver_fix = 0x1,
.start_addr = 0x08003184,
.text_addr = 0x08000000,
- .text_len = 0x6768,
+ .text_len = 0x6788,
.text_index = 0x0,
.gz_text = bnx2_RXP_b09FwText,
.gz_text_len = sizeof(bnx2_RXP_b09FwText),
- .data_addr = 0x08006a00,
+ .data_addr = 0x08006a20,
.data_len = 0x0,
.data_index = 0x0,
.data = bnx2_RXP_b09FwData,
- .sbss_addr = 0x08006a00,
+ .sbss_addr = 0x08006a20,
.sbss_len = 0x20,
.sbss_index = 0x0,
- .bss_addr = 0x08006a20,
+ .bss_addr = 0x08006a40,
.bss_len = 0x13dc,
.bss_index = 0x0,
- .rodata_addr = 0x08006768,
+ .rodata_addr = 0x08006788,
.rodata_len = 0x278,
.rodata_index = 0x0,
.rodata = bnx2_RXP_b09FwRodata,
};
static u8 bnx2_TPAT_b09FwText[] = {
-/* 0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, */
- 0xcd, 0x58,
- 0x5d, 0x68, 0x1c, 0xd7, 0x15, 0x3e, 0xf3, 0xb7, 0x3b, 0x52, 0x24, 0xeb,
- 0x5a, 0xd9, 0xa6, 0xeb, 0xa0, 0x34, 0x33, 0xda, 0x91, 0xac, 0x22, 0x13,
- 0x4f, 0x9d, 0x25, 0x16, 0x65, 0x21, 0x93, 0xd9, 0x91, 0xac, 0x98, 0x3c,
- 0x28, 0xc5, 0x90, 0x87, 0x52, 0x50, 0x57, 0x32, 0x09, 0x79, 0x69, 0xda,
- 0xc6, 0x90, 0x3e, 0x79, 0x3b, 0x2b, 0xc7, 0x0e, 0x6c, 0xbc, 0x8d, 0x52,
- 0xe4, 0x52, 0xfa, 0x60, 0xd6, 0xb1, 0x05, 0xcd, 0x46, 0x93, 0xd4, 0x7e,
- 0x35, 0x36, 0x4e, 0x93, 0xa7, 0x42, 0x9f, 0x52, 0xf4, 0x18, 0xd2, 0x12,
- 0xda, 0x52, 0x8a, 0x69, 0xa1, 0x09, 0x8d, 0xeb, 0xdb, 0xef, 0xdc, 0x99,
- 0x91, 0x57, 0xb6, 0xec, 0xa4, 0x25, 0x85, 0x0a, 0x56, 0x77, 0xe6, 0xce,
- 0x3d, 0xe7, 0x9e, 0x7b, 0xee, 0x77, 0xbe, 0x73, 0xee, 0x2d, 0xeb, 0x34,
- 0x48, 0xd9, 0xdf, 0x30, 0x7e, 0x2f, 0x7e, 0xf7, 0x85, 0x17, 0xab, 0x8f,
- 0x3c, 0xea, 0x10, 0x3d, 0xfa, 0x88, 0x66, 0x98, 0x06, 0x7d, 0x09, 0x7f,
- 0x50, 0x22, 0x72, 0xfd, 0xfc, 0x23, 0x5b, 0xaf, 0x9d, 0x72, 0x42, 0x8f,
- 0x6c, 0xa3, 0x26, 0xbe, 0xbe, 0xe4, 0x11, 0x05, 0xbd, 0x69, 0xa7, 0x4e,
- 0xff, 0x92, 0xcd, 0x92, 0x49, 0xdc, 0xff, 0x50, 0xed, 0xc6, 0xfe, 0xcb,
- 0x07, 0xdd, 0xeb, 0x67, 0x0d, 0xb2, 0x45, 0x6d, 0xd1, 0x16, 0x93, 0x64,
- 0x8f, 0xd5, 0x9a, 0xce, 0x2f, 0xf6, 0x1e, 0x28, 0xd0, 0xae, 0x5c, 0x97,
- 0xa0, 0xb8, 0x43, 0x4d, 0xab, 0x66, 0x53, 0xd4, 0x7e, 0x49, 0x0b, 0x3b,
- 0x9e, 0x98, 0x85, 0x8e, 0xa0, 0x04, 0xfd, 0x1e, 0xde, 0x13, 0x53, 0x8b,
- 0xce, 0xd8, 0xa4, 0xd7, 0x02, 0x3c, 0x4f, 0x51, 0xab, 0x23, 0xe5, 0x2b,
- 0xbe, 0x46, 0x4b, 0xbe, 0x4d, 0x8b, 0xc2, 0x0d, 0x1c, 0xed, 0xa6, 0xac,
- 0x4c, 0x48, 0xf9, 0x9c, 0xaf, 0x93, 0xee, 0xcd, 0x69, 0xe1, 0xfa, 0xbc,
- 0x56, 0x5f, 0x9f, 0x67, 0x7f, 0xc0, 0xbe, 0x39, 0x2d, 0x58, 0xe7, 0xb6,
- 0x66, 0xd7, 0xdb, 0xbb, 0x68, 0xb1, 0x44, 0x23, 0xba, 0x37, 0x85, 0xf9,
- 0x4a, 0xd0, 0xe3, 0x50, 0xe8, 0x4f, 0x0b, 0x9d, 0x2a, 0xf8, 0x0d, 0xd0,
- 0xac, 0x4f, 0x03, 0xba, 0xa7, 0x53, 0xa3, 0xa4, 0xd1, 0x1b, 0x55, 0x0b,
- 0xbf, 0xc3, 0x5a, 0xb4, 0xfe, 0x7c, 0xa6, 0x87, 0xc7, 0xdb, 0xf8, 0xc6,
- 0x36, 0xb3, 0x7c, 0xbf, 0xec, 0x30, 0x9e, 0x9f, 0xc3, 0x38, 0x8b, 0xc2,
- 0xea, 0xed, 0xdf, 0x06, 0xf0, 0xac, 0xa1, 0xff, 0x30, 0xec, 0x62, 0x3d,
- 0x0e, 0xec, 0x28, 0xd3, 0x4a, 0x67, 0x1e, 0xeb, 0x29, 0x50, 0x53, 0x4c,
- 0x4c, 0x35, 0xc8, 0x84, 0x8c, 0x41, 0x41, 0xe9, 0x8a, 0xd4, 0x6b, 0x52,
- 0x86, 0x55, 0x6f, 0xaa, 0xab, 0xe6, 0xd0, 0xc9, 0xf0, 0x0a, 0x14, 0xf9,
- 0xc3, 0xd4, 0x12, 0x06, 0xc5, 0xfb, 0x2c, 0x0a, 0x16, 0x4c, 0xac, 0x71,
- 0x14, 0x72, 0x1a, 0xe4, 0x5f, 0xcb, 0xf6, 0xbc, 0x48, 0xb1, 0x28, 0xa0,
- 0x7f, 0x84, 0xe2, 0xd2, 0x6e, 0x4d, 0xaf, 0xbd, 0x82, 0xfe, 0x09, 0xd1,
- 0xa5, 0x53, 0x68, 0x35, 0xbc, 0xef, 0xc6, 0x58, 0x7e, 0xd7, 0xa0, 0x8f,
- 0x44, 0x98, 0x78, 0xd4, 0x4a, 0x72, 0x59, 0xee, 0x4f, 0xfb, 0x9a, 0xc9,
- 0xed, 0xfb, 0xed, 0xc1, 0x4e, 0x41, 0x27, 0x3a, 0xb3, 0x98, 0x8f, 0x9a,
- 0x46, 0x0d, 0xe3, 0xb0, 0x37, 0xbc, 0xbf, 0x81, 0xc2, 0xc1, 0xe3, 0xdc,
- 0xcf, 0x7f, 0xe8, 0x77, 0xc8, 0xa8, 0xf1, 0xb7, 0x6f, 0x52, 0xfa, 0x2d,
- 0xb5, 0x3f, 0xf4, 0x1f, 0xcb, 0xde, 0x4b, 0x22, 0x3c, 0xf3, 0x28, 0xd6,
- 0xa8, 0x60, 0x83, 0xe7, 0x02, 0xf0, 0x11, 0xcf, 0xe8, 0xd4, 0x2c, 0x17,
- 0xc9, 0xf5, 0x8f, 0xa2, 0xf7, 0xd7, 0x6d, 0x83, 0xea, 0xec, 0x2b, 0xdf,
- 0xcc, 0x64, 0x18, 0x1b, 0x1f, 0x64, 0x76, 0x0a, 0x5a, 0x3c, 0x22, 0xe5,
- 0x8a, 0x2f, 0xa5, 0x55, 0xf3, 0x9c, 0x13, 0x34, 0x5d, 0x36, 0x69, 0x52,
- 0xa0, 0x85, 0x8f, 0xbd, 0x72, 0x83, 0x2c, 0x60, 0xa1, 0x1f, 0xff, 0xfc,
- 0xf7, 0xa6, 0x86, 0x25, 0xd0, 0xb5, 0x36, 0xeb, 0x98, 0x70, 0x66, 0x95,
- 0x8c, 0x94, 0xf1, 0xcc, 0xbd, 0x64, 0x2e, 0x65, 0x32, 0x52, 0x46, 0x55,
- 0x81, 0x3d, 0x6f, 0x0a, 0xd8, 0x87, 0x75, 0x31, 0xc6, 0x89, 0xa2, 0x9e,
- 0x6f, 0x37, 0xda, 0xb0, 0xd1, 0x43, 0xdb, 0x13, 0xf0, 0x0f, 0x51, 0x0b,
- 0x63, 0xf5, 0xea, 0x7d, 0x8c, 0x0d, 0xec, 0xef, 0x82, 0x1d, 0xb5, 0xdd,
- 0xf2, 0x29, 0x5a, 0xb0, 0xeb, 0xbd, 0xe9, 0xf2, 0x32, 0x3d, 0xc4, 0x73,
- 0xd8, 0x56, 0xed, 0x88, 0xdd, 0x55, 0x72, 0x88, 0xc4, 0x41, 0x3c, 0xf7,
- 0x88, 0xe2, 0x36, 0x69, 0xa1, 0x7f, 0x1f, 0xaf, 0x15, 0x72, 0xf3, 0x99,
- 0xdc, 0x7c, 0x26, 0x37, 0x92, 0xc9, 0x3d, 0xd5, 0x27, 0xf7, 0x14, 0xcb,
- 0x61, 0x6c, 0x90, 0x8d, 0x0d, 0xb2, 0xb1, 0x66, 0x36, 0x36, 0xca, 0xc6,
- 0xa2, 0xed, 0x8d, 0xc1, 0x36, 0x77, 0xca, 0xd1, 0x6c, 0x8a, 0x3d, 0xf9,
- 0x70, 0xe8, 0x53, 0x50, 0xf7, 0xdc, 0xcd, 0xba, 0x31, 0x42, 0xe7, 0xfc,
- 0x21, 0x5a, 0x49, 0xc6, 0x28, 0x4e, 0x56, 0x28, 0x4c, 0x74, 0xc8, 0x8e,
- 0x50, 0xd7, 0xbb, 0x2e, 0x67, 0x7d, 0x1f, 0x7b, 0x66, 0xb3, 0x5c, 0x79,
- 0x96, 0x1c, 0x7c, 0x9f, 0x16, 0xcb, 0xe4, 0x03, 0x2b, 0x3a, 0xf6, 0xad,
- 0xa2, 0x9e, 0xe3, 0xc4, 0xe7, 0x35, 0x37, 0xf5, 0xaa, 0x2b, 0x62, 0x72,
- 0xcb, 0xa1, 0x41, 0x42, 0xaf, 0xc1, 0x4f, 0x49, 0x93, 0xa2, 0xc4, 0xa6,
- 0x0f, 0x8d, 0x97, 0x54, 0x8c, 0xc6, 0x9d, 0x4d, 0x79, 0x79, 0xaf, 0x43,
- 0x57, 0x30, 0xcf, 0xc5, 0xa4, 0x4c, 0xbf, 0x4a, 0x4a, 0xf4, 0x4e, 0x42,
- 0x7a, 0xe8, 0x03, 0xc3, 0x25, 0x41, 0x6f, 0x27, 0xfd, 0x3e, 0xff, 0x88,
- 0x7d, 0x6e, 0xdf, 0x5f, 0x23, 0x7b, 0xb4, 0xc6, 0x38, 0x4b, 0x39, 0xa0,
- 0x9e, 0x72, 0x80, 0xc2, 0x52, 0xab, 0x13, 0x3f, 0x68, 0x80, 0x7f, 0x96,
- 0xfc, 0x60, 0xb7, 0xa1, 0xf6, 0xa3, 0x89, 0x3d, 0xcc, 0x5b, 0xde, 0x9b,
- 0xab, 0xce, 0x92, 0xe7, 0x9e, 0xaa, 0x33, 0x6a, 0x4f, 0x5b, 0x39, 0x2e,
- 0xfb, 0xe6, 0xf8, 0x33, 0xe6, 0x18, 0xa2, 0x06, 0xe2, 0xec, 0x09, 0x13,
- 0xb1, 0xe3, 0xfd, 0xdd, 0x60, 0x5c, 0x39, 0x1b, 0x8c, 0x6f, 0xa2, 0xf1,
- 0x0d, 0x9b, 0xd6, 0xdb, 0x45, 0x72, 0xba, 0x43, 0xb4, 0xd4, 0x19, 0xa4,
- 0xca, 0x05, 0x13, 0x63, 0xef, 0xa3, 0xca, 0xaa, 0x5e, 0xe2, 0x38, 0xae,
- 0xc3, 0xc7, 0xe3, 0x5d, 0x09, 0x7c, 0x0e, 0xd2, 0xf8, 0x9a, 0xab, 0xb0,
- 0xb3, 0xe4, 0xb5, 0x7c, 0x83, 0x7e, 0x4c, 0xd7, 0xf6, 0x15, 0xb0, 0xa6,
- 0x12, 0xf9, 0x93, 0xfd, 0xf3, 0xe9, 0x80, 0x18, 0xf7, 0xc5, 0x45, 0xda,
- 0xe5, 0x3a, 0xa4, 0xb3, 0x3e, 0x9b, 0xc6, 0x2f, 0xd8, 0x5a, 0xbd, 0xc3,
- 0x3e, 0x63, 0xfc, 0xd9, 0x19, 0xfe, 0x4c, 0x2d, 0x3c, 0x53, 0xc4, 0x5c,
- 0x7f, 0x91, 0xa1, 0x27, 0xb1, 0x0f, 0x3a, 0x2d, 0x55, 0x7f, 0x04, 0xfb,
- 0xd0, 0xd7, 0xe5, 0x6f, 0xd7, 0xb3, 0x7e, 0xd6, 0x01, 0x7e, 0xf0, 0xef,
- 0xa7, 0x90, 0xb9, 0xe0, 0x08, 0xcb, 0x14, 0x69, 0x7c, 0x95, 0xf9, 0x05,
- 0x6d, 0x97, 0xdf, 0x79, 0x6d, 0x03, 0xd4, 0x80, 0x57, 0x1a, 0x53, 0x25,
- 0xd8, 0xa5, 0x2b, 0xbe, 0x68, 0x80, 0x3f, 0x74, 0x6f, 0x10, 0x2d, 0xcf,
- 0xf7, 0x73, 0x23, 0x8f, 0xa9, 0xb8, 0x33, 0x44, 0x75, 0xe0, 0xd7, 0x84,
- 0x3d, 0xcb, 0x34, 0x51, 0x3e, 0xaa, 0xbe, 0xa1, 0xaf, 0xc7, 0xdf, 0xc4,
- 0x6d, 0xdf, 0xf0, 0xde, 0xcb, 0x6d, 0x40, 0x6c, 0x7b, 0x2d, 0xcc, 0x62,
- 0x65, 0x7e, 0xe1, 0xf1, 0xcd, 0x32, 0xf6, 0x06, 0x7c, 0x46, 0xf0, 0x25,
- 0x51, 0xb7, 0x6d, 0x82, 0x6f, 0xf4, 0xaf, 0xea, 0x2c, 0x57, 0x62, 0x3d,
- 0x58, 0xff, 0x9a, 0xa9, 0xd5, 0xcf, 0x78, 0xce, 0x1f, 0x88, 0xe5, 0x2b,
- 0xf0, 0xc1, 0xc4, 0x4c, 0x8b, 0xc7, 0xf7, 0x2c, 0xf2, 0x56, 0x9b, 0xc2,
- 0xc4, 0x9e, 0xc2, 0x73, 0x54, 0xff, 0xc9, 0x08, 0xf6, 0xda, 0x75, 0x5a,
- 0xf4, 0x5b, 0xd8, 0x53, 0x20, 0xaf, 0x6b, 0xd2, 0x1b, 0x6d, 0xf6, 0x85,
- 0x4d, 0x95, 0x35, 0x29, 0x4f, 0xfa, 0xbc, 0x27, 0xbf, 0x83, 0x5f, 0x08,
- 0x2b, 0x9c, 0x98, 0xf9, 0x08, 0xfb, 0xb3, 0xde, 0xe3, 0xbd, 0xb1, 0x94,
- 0x4f, 0xbc, 0xd5, 0x29, 0xec, 0xeb, 0x54, 0x66, 0x23, 0xef, 0x97, 0x49,
- 0x2b, 0x55, 0x9d, 0xce, 0x57, 0x3f, 0x93, 0xba, 0xc7, 0xfc, 0x5a, 0x80,
- 0x6f, 0x31, 0xae, 0x8b, 0x71, 0x49, 0x01, 0x3e, 0xfc, 0x07, 0x78, 0x45,
- 0xca, 0xf3, 0x55, 0xf4, 0xaf, 0x1e, 0x87, 0xad, 0x06, 0x64, 0x53, 0x8c,
- 0xb1, 0x3d, 0x73, 0xed, 0x7c, 0x7d, 0xde, 0xcc, 0x7b, 0x4a, 0xdf, 0x10,
- 0x4d, 0x6e, 0x0c, 0xd1, 0xb3, 0xbd, 0x21, 0x1a, 0x3f, 0xcd, 0x32, 0xe0,
- 0xa6, 0xaa, 0x27, 0x22, 0xc6, 0xa8, 0xa7, 0xfc, 0x50, 0x36, 0x74, 0x5e,
- 0x27, 0xbe, 0x6f, 0x10, 0x2d, 0xf7, 0x78, 0x0e, 0xb3, 0x4f, 0xa7, 0x4e,
- 0x87, 0x7e, 0x4a, 0x74, 0xa8, 0xc7, 0xb2, 0x5b, 0xbe, 0x83, 0x5e, 0x01,
- 0x9d, 0x82, 0x38, 0x0f, 0x19, 0x1e, 0xf2, 0xdd, 0x7a, 0x88, 0xfc, 0x15,
- 0xe1, 0x37, 0x87, 0x9c, 0xc6, 0xeb, 0x9f, 0x42, 0xfc, 0x31, 0x8f, 0xdf,
- 0xc4, 0xda, 0x0b, 0xb4, 0xe2, 0xcf, 0x63, 0x0c, 0xef, 0xf1, 0x61, 0x7c,
- 0x1f, 0x46, 0x1e, 0xc8, 0xf2, 0x84, 0xe0, 0x3c, 0xb1, 0x1b, 0x71, 0x30,
- 0x00, 0xee, 0xdf, 0x63, 0x6e, 0xcf, 0x13, 0x18, 0x57, 0xda, 0x83, 0xbc,
- 0x70, 0x3f, 0xfa, 0x59, 0xd7, 0x28, 0xda, 0x01, 0xbc, 0xef, 0xc1, 0xd8,
- 0xfe, 0x1c, 0x91, 0xcb, 0xdd, 0x2d, 0x3f, 0x20, 0x26, 0x56, 0x11, 0x2b,
- 0x6b, 0x9c, 0x27, 0x38, 0x16, 0x79, 0x4f, 0x8b, 0xe0, 0x6f, 0x1b, 0x3a,
- 0x78, 0x6f, 0x8b, 0xd8, 0x43, 0xce, 0x71, 0x82, 0x2a, 0x1b, 0x3b, 0xe5,
- 0x0f, 0x5e, 0x0f, 0x38, 0xec, 0x34, 0xaf, 0xc5, 0x15, 0x0d, 0xf0, 0x59,
- 0xb8, 0x31, 0x8d, 0xef, 0xc8, 0x85, 0x22, 0xb2, 0x1b, 0xa7, 0x53, 0x2e,
- 0x6b, 0x6c, 0x8c, 0x29, 0x9c, 0xc6, 0x89, 0xc0, 0x3b, 0x73, 0x59, 0xce,
- 0x5d, 0x8c, 0x25, 0x0a, 0x20, 0xbb, 0x19, 0x1a, 0x52, 0x2e, 0xf9, 0x23,
- 0xd4, 0x00, 0x2e, 0x03, 0xf0, 0x59, 0x03, 0x7c, 0x56, 0xef, 0xe3, 0xb3,
- 0xfa, 0xe7, 0xf2, 0x19, 0xb8, 0xaa, 0x03, 0xae, 0xea, 0x80, 0xab, 0x50,
- 0x1b, 0xbc, 0x03, 0xec, 0xbf, 0xdd, 0xd9, 0x89, 0xe3, 0x98, 0xdf, 0x98,
- 0xe7, 0xa6, 0xe8, 0xf2, 0xde, 0xff, 0x94, 0xe7, 0x8e, 0x83, 0x13, 0x6c,
- 0xfa, 0xfe, 0xde, 0x7b, 0x73, 0xdd, 0x09, 0x70, 0x9d, 0xf5, 0xf9, 0x5c,
- 0xd7, 0x64, 0xae, 0x33, 0x81, 0xbd, 0x26, 0x78, 0x40, 0x5f, 0xed, 0x9f,
- 0xe7, 0x24, 0xe6, 0xe1, 0x3e, 0x33, 0xcb, 0xa5, 0x3a, 0x75, 0x81, 0x7b,
- 0xc3, 0xe3, 0x79, 0x60, 0x73, 0x92, 0x72, 0xd1, 0x13, 0x66, 0x89, 0xac,
- 0x49, 0xe0, 0x61, 0x75, 0x88, 0x8c, 0xd3, 0xb7, 0xf0, 0x8e, 0x7a, 0x00,
- 0x71, 0x8e, 0x7f, 0x1b, 0xb9, 0x8e, 0x41, 0x70, 0x8d, 0x49, 0x85, 0x55,
- 0x0b, 0xef, 0xda, 0xb6, 0x71, 0x87, 0x90, 0x6f, 0x8c, 0x9a, 0x3b, 0xf3,
- 0x7b, 0x7e, 0xee, 0xf1, 0x98, 0x41, 0xd2, 0xd7, 0x5c, 0xc7, 0xd1, 0x5d,
- 0xff, 0x1a, 0xb8, 0xe1, 0x7d, 0x8f, 0xf9, 0x2f, 0x06, 0x0a, 0x0a, 0x64,
- 0xae, 0xca, 0xe3, 0x56, 0x8d, 0xe7, 0x6e, 0x3a, 0x88, 0x73, 0xe7, 0x35,
- 0xe0, 0x87, 0x73, 0xe7, 0xf9, 0x2a, 0xd7, 0x7b, 0x69, 0x8c, 0xb6, 0x7a,
- 0xf9, 0x9c, 0xa3, 0xb0, 0xdb, 0x82, 0x4c, 0xff, 0x58, 0xc6, 0x8b, 0x94,
- 0xcf, 0x62, 0x4d, 0x06, 0xe6, 0xb1, 0xd6, 0x6c, 0x2a, 0xac, 0xb1, 0x5f,
- 0x5c, 0xc8, 0x57, 0xc4, 0x1c, 0x6d, 0x6e, 0xe3, 0x83, 0x93, 0xbd, 0x0f,
- 0x4c, 0xe6, 0x50, 0x03, 0xb1, 0x59, 0xc4, 0xbc, 0xd6, 0x96, 0x2e, 0xca,
- 0x74, 0xb1, 0xbc, 0x57, 0x7e, 0x76, 0x4b, 0x9e, 0x79, 0x6d, 0xa2, 0xcc,
- 0xfc, 0xc5, 0x76, 0x18, 0x8a, 0x4b, 0x07, 0x33, 0x2e, 0xad, 0x60, 0x3f,
- 0x07, 0x55, 0x5c, 0xea, 0xde, 0xc3, 0x19, 0x9f, 0xee, 0x46, 0xcb, 0x7d,
- 0x37, 0xb2, 0x38, 0x31, 0x61, 0x2f, 0xeb, 0x1d, 0x24, 0x03, 0x76, 0x45,
- 0x6a, 0x4d, 0x7f, 0x93, 0x4b, 0x1e, 0x73, 0x04, 0xe3, 0x53, 0x71, 0x29,
- 0xfa, 0x27, 0x60, 0x33, 0xf3, 0x02, 0xcb, 0xb1, 0xfc, 0x4e, 0x72, 0x7f,
- 0x85, 0x9c, 0xd8, 0x41, 0x0e, 0x7d, 0x1b, 0x2c, 0xc3, 0xdc, 0x30, 0x8a,
- 0xf1, 0x21, 0xf3, 0x02, 0x7c, 0xc6, 0xb2, 0xe5, 0x2c, 0x0e, 0x23, 0x7c,
- 0xe3, 0xba, 0x97, 0xe3, 0x23, 0x20, 0xab, 0xc6, 0xeb, 0xe0, 0x9a, 0x98,
- 0xf3, 0x22, 0xd7, 0xa1, 0x5c, 0x6f, 0xe6, 0xf5, 0xa9, 0x37, 0x35, 0x7b,
- 0xb7, 0x5a, 0x53, 0xf4, 0xd7, 0x9a, 0xe8, 0xd8, 0xb1, 0xd6, 0xf4, 0xac,
- 0xb4, 0xd6, 0xac, 0x58, 0x77, 0xaf, 0x35, 0x73, 0xd9, 0x7b, 0xd7, 0x9a,
- 0x71, 0x87, 0xf7, 0x08, 0xb9, 0x54, 0xf0, 0x5a, 0xa8, 0x69, 0x66, 0x7c,
- 0x11, 0xdd, 0xc6, 0x17, 0xd1, 0x69, 0xb7, 0x7c, 0x8e, 0x38, 0xa6, 0xdd,
- 0x72, 0x8b, 0x6b, 0xa0, 0x0d, 0xae, 0x81, 0x0c, 0xe4, 0xd2, 0x7e, 0xce,
- 0xc8, 0x7d, 0xc2, 0xbe, 0x1c, 0x04, 0x27, 0xb3, 0x1f, 0x8b, 0x19, 0x3f,
- 0xa0, 0xf5, 0x3e, 0x05, 0x3f, 0xe4, 0xbc, 0xc2, 0x3e, 0xfb, 0x7f, 0xe2,
- 0x15, 0xb2, 0x07, 0xc0, 0x0f, 0x36, 0xea, 0xcd, 0x46, 0x47, 0xd9, 0x02,
- 0x5f, 0x48, 0x39, 0xe7, 0x33, 0xf6, 0x53, 0xbe, 0x50, 0x3e, 0x51, 0x78,
- 0x2c, 0xd2, 0xbb, 0x3e, 0x63, 0x01, 0xe7, 0x23, 0x8f, 0x73, 0x22, 0xf3,
- 0xef, 0x4d, 0xf9, 0xae, 0x17, 0xa2, 0x2f, 0xc2, 0x9e, 0x33, 0x0e, 0xe6,
- 0xb5, 0x43, 0xeb, 0x36, 0xe4, 0x18, 0x0b, 0xe5, 0x3b, 0xce, 0x3d, 0xe9,
- 0xf9, 0x84, 0x6b, 0xe1, 0xff, 0x16, 0x1b, 0x17, 0xef, 0x82, 0x8d, 0x37,
- 0x33, 0x6c, 0xfc, 0xf2, 0x1e, 0xd8, 0xb8, 0xf8, 0x05, 0xb1, 0xe1, 0x3a,
- 0x1f, 0xa3, 0x5e, 0x7a, 0xcf, 0x63, 0x7c, 0x48, 0xf9, 0xb1, 0xbf, 0x53,
- 0x3e, 0x09, 0x6c, 0xe3, 0xd5, 0x9b, 0x32, 0xce, 0x72, 0x89, 0xfe, 0xd6,
- 0xad, 0x5c, 0x32, 0xfe, 0x6a, 0x8a, 0x8b, 0xf1, 0xb7, 0xa4, 0x3c, 0xb7,
- 0x03, 0x0e, 0xb8, 0x56, 0xbe, 0x0a, 0x1e, 0x68, 0xd1, 0xff, 0xa2, 0x56,
- 0x66, 0xce, 0xae, 0xda, 0x47, 0xdb, 0xf9, 0xbe, 0xe7, 0x7b, 0x5e, 0xa0,
- 0xb3, 0x62, 0x17, 0xfc, 0xb5, 0x9f, 0x5a, 0xaf, 0x9b, 0x7c, 0x7e, 0x00,
- 0x1e, 0x1e, 0x37, 0x39, 0x56, 0x71, 0x56, 0xc4, 0x73, 0x7f, 0x3d, 0x0d,
- 0x3c, 0xfa, 0xbc, 0x76, 0xb5, 0xee, 0x3e, 0xae, 0xff, 0x1e, 0x4a, 0x92,
- 0x3b, 0xf2, 0xc8, 0xb6, 0x73, 0xb3, 0x81, 0x73, 0x73, 0x5d, 0xe9, 0xe0,
- 0xb3, 0x55, 0xea, 0xbf, 0x13, 0xea, 0xac, 0x7c, 0x53, 0x9e, 0x53, 0xe7,
- 0xe5, 0xd1, 0x02, 0x0d, 0xce, 0x67, 0x58, 0x61, 0x5f, 0x0c, 0xab, 0x7a,
- 0x82, 0x31, 0xd5, 0x42, 0xbe, 0x5d, 0x82, 0x3f, 0x1a, 0x2a, 0x16, 0xb0,
- 0xf6, 0xcc, 0x1f, 0x2d, 0xf8, 0xa3, 0x9e, 0xa4, 0x31, 0xf1, 0xe5, 0x9e,
- 0x1d, 0xfe, 0x88, 0x7c, 0x6a, 0x2f, 0x9a, 0x38, 0x6f, 0x5f, 0x49, 0x54,
- 0xfe, 0x5c, 0x68, 0xb5, 0xa9, 0xf9, 0x60, 0xed, 0x38, 0xd7, 0x6d, 0x5c,
- 0x77, 0xcd, 0x2c, 0x55, 0xd1, 0xd7, 0xb3, 0x29, 0x84, 0x4f, 0xbe, 0x7d,
- 0x90, 0x16, 0x8d, 0x1a, 0xe3, 0x17, 0xef, 0x09, 0x35, 0xc3, 0x83, 0xa8,
- 0xa5, 0x92, 0xb1, 0x45, 0xbd, 0x36, 0x06, 0x1c, 0x35, 0x29, 0x80, 0x9d,
- 0x01, 0x74, 0xcf, 0xb5, 0x6d, 0x7b, 0xb9, 0xcd, 0x67, 0xa4, 0x26, 0xf1,
- 0x19, 0xbc, 0xdb, 0xbb, 0x0e, 0x7d, 0x03, 0xcf, 0xe0, 0xcc, 0xea, 0xc4,
- 0xc0, 0xd5, 0xcb, 0x89, 0x45, 0xad, 0x12, 0xdf, 0x51, 0x30, 0x57, 0x96,
- 0xa1, 0xe3, 0x99, 0x42, 0x8a, 0xcb, 0x32, 0xf4, 0x70, 0xcc, 0x10, 0xe6,
- 0x63, 0xff, 0xe5, 0x58, 0x2b, 0xf7, 0xd5, 0xee, 0x85, 0xec, 0xbc, 0x4a,
- 0xca, 0x07, 0xec, 0xdf, 0xd0, 0x7b, 0xbe, 0x90, 0xdf, 0xc7, 0xb4, 0x10,
- 0xf3, 0x8d, 0x7d, 0x8c, 0x43, 0x0d, 0x78, 0xc3, 0x98, 0x84, 0xfb, 0x90,
- 0x57, 0xf6, 0x21, 0x37, 0x97, 0x8a, 0xaa, 0x6d, 0x26, 0xc7, 0xb2, 0xf1,
- 0xba, 0x1a, 0xc7, 0x39, 0x21, 0x4e, 0xd4, 0x59, 0x41, 0x8b, 0x3a, 0xe4,
- 0x34, 0x7c, 0x9c, 0x81, 0x50, 0x5b, 0xac, 0x24, 0x9c, 0xcf, 0xf7, 0xd9,
- 0xba, 0xe2, 0xb9, 0x4d, 0xc8, 0xe0, 0x79, 0x83, 0xf4, 0x86, 0xcf, 0xf7,
- 0x07, 0xd9, 0xdd, 0x46, 0x89, 0x86, 0x21, 0x0f, 0xbb, 0xc6, 0xd8, 0xae,
- 0xa0, 0xa1, 0x6a, 0x11, 0xd6, 0xbd, 0x5f, 0x4f, 0xef, 0x5c, 0x7e, 0x93,
- 0xcd, 0x65, 0x83, 0x5f, 0x08, 0xe7, 0x1d, 0x9f, 0xf3, 0xda, 0xd7, 0x0c,
- 0xba, 0x4e, 0x8a, 0x23, 0xc5, 0x37, 0x90, 0xef, 0x0e, 0x42, 0x26, 0x50,
- 0xfc, 0x92, 0x9e, 0x19, 0x72, 0x99, 0x8a, 0xb1, 0x5d, 0xc7, 0x77, 0xcc,
- 0xed, 0xef, 0x01, 0x62, 0xab, 0x9a, 0xcd, 0xd7, 0x8f, 0xd3, 0x4d, 0xe0,
- 0x74, 0xb3, 0xb0, 0x75, 0xee, 0x28, 0x15, 0x30, 0x8e, 0x6d, 0x64, 0x2e,
- 0x61, 0x99, 0x4f, 0xac, 0xed, 0x7a, 0x2a, 0x3b, 0xe8, 0xf8, 0x53, 0x9f,
- 0x8e, 0x12, 0xaf, 0x4d, 0x34, 0xd2, 0xf3, 0xb3, 0xfa, 0x6b, 0xc0, 0xcf,
- 0x38, 0x6f, 0x3c, 0xa0, 0x63, 0x1d, 0x5c, 0x7f, 0xd5, 0x55, 0x3f, 0x0e,
- 0x56, 0xdb, 0xf4, 0xfe, 0x30, 0x9b, 0x67, 0x5f, 0x1a, 0x0f, 0x1e, 0xda,
- 0x64, 0xb3, 0xcf, 0x76, 0x6b, 0x87, 0x79, 0x91, 0xd8, 0xbd, 0x19, 0x8d,
- 0xf1, 0x66, 0xd4, 0x38, 0x07, 0xe3, 0x79, 0x0b, 0x1f, 0x8c, 0xd5, 0xcf,
- 0xc7, 0xa8, 0xf5, 0x05, 0x31, 0xfa, 0x46, 0x9b, 0xb9, 0x22, 0xc5, 0x68,
- 0xe3, 0x0e, 0x8c, 0xa2, 0x06, 0x2a, 0xe5, 0xf8, 0xe4, 0x78, 0xc9, 0xf1,
- 0x99, 0x3f, 0xf3, 0xfd, 0x08, 0x38, 0x38, 0xe3, 0xb6, 0x18, 0xdc, 0x16,
- 0xa9, 0x1c, 0xe7, 0x96, 0x23, 0x4a, 0xe3, 0x78, 0x19, 0x71, 0x1c, 0x19,
- 0x9c, 0xf3, 0x38, 0x86, 0x59, 0x8e, 0xe3, 0x98, 0xe5, 0x46, 0x32, 0x39,
- 0xb4, 0x88, 0xe7, 0x28, 0x8b, 0xe7, 0x16, 0x78, 0x37, 0xca, 0xe2, 0xb9,
- 0x85, 0x18, 0x5e, 0xc9, 0xe2, 0xb9, 0x95, 0xc5, 0x33, 0xdf, 0xdb, 0x19,
- 0x55, 0x95, 0x8b, 0x9d, 0x3a, 0x78, 0x6d, 0x45, 0xe9, 0x6c, 0x62, 0x9d,
- 0xb0, 0xb1, 0x93, 0xc7, 0xc5, 0x1d, 0xf7, 0x5b, 0x58, 0xcf, 0xad, 0xbc,
- 0x32, 0x8b, 0xbc, 0x72, 0x0e, 0x79, 0xa5, 0xdb, 0x77, 0xbf, 0x75, 0x56,
- 0xe5, 0x95, 0x27, 0x8b, 0x79, 0x5e, 0xe9, 0x66, 0x79, 0xa5, 0xab, 0xf2,
- 0xca, 0x13, 0x45, 0xce, 0x2b, 0x31, 0x05, 0xc5, 0xfe, 0xbc, 0x12, 0x6f,
- 0xcb, 0x2b, 0xb9, 0x2c, 0xf7, 0xef, 0x94, 0x57, 0x72, 0x9f, 0x71, 0x6e,
- 0xb1, 0x72, 0x5e, 0xbd, 0x2d, 0x9f, 0xe4, 0x63, 0xd8, 0x56, 0xe6, 0x25,
- 0xe6, 0xe0, 0xb4, 0xae, 0xbf, 0x92, 0xe4, 0xb1, 0x74, 0x0c, 0xf3, 0xe0,
- 0xbd, 0xb3, 0x53, 0x2c, 0xd9, 0x59, 0x2c, 0x0d, 0xa7, 0x32, 0x9d, 0xfe,
- 0x78, 0x3a, 0x56, 0xdc, 0x1e, 0x4f, 0xb9, 0x9e, 0x3c, 0x9e, 0x52, 0x9d,
- 0x1f, 0x1a, 0x65, 0xae, 0x07, 0x70, 0x96, 0x76, 0xfd, 0x39, 0xf4, 0x5e,
- 0xe8, 0x4d, 0xa3, 0xae, 0x36, 0xe9, 0x6a, 0xce, 0x37, 0xea, 0xbe, 0x07,
- 0x6d, 0x2f, 0xb7, 0xb5, 0xb8, 0xf5, 0xad, 0x8b, 0xda, 0xfa, 0x7d, 0xf0,
- 0xc8, 0x79, 0xf5, 0xfd, 0x33, 0x79, 0xb5, 0x84, 0x33, 0xb0, 0x97, 0x8f,
- 0x7b, 0x1d, 0xf3, 0xb9, 0xe2, 0x2c, 0x9e, 0x5e, 0xee, 0xdd, 0x82, 0xf9,
- 0x8a, 0xc7, 0x7d, 0xff, 0x44, 0x0e, 0x41, 0x5d, 0xbe, 0x35, 0x96, 0xcf,
- 0x38, 0x1e, 0xd6, 0xec, 0xd0, 0xa5, 0x6d, 0xe7, 0x9c, 0xf4, 0x7c, 0x83,
- 0x75, 0xa3, 0x3e, 0xe1, 0x3a, 0x25, 0xfc, 0x8a, 0x4e, 0x2f, 0xd1, 0xb7,
- 0x7c, 0xee, 0xd3, 0x69, 0xf6, 0x31, 0x29, 0x5f, 0x40, 0xcd, 0xf2, 0xf4,
- 0xb6, 0x9a, 0xa5, 0x48, 0xe3, 0x07, 0xfa, 0xcf, 0x87, 0x37, 0xe5, 0xf8,
- 0xa4, 0x7b, 0x36, 0xa0, 0x40, 0x9b, 0x5d, 0xe7, 0x5a, 0x76, 0xab, 0x76,
- 0x25, 0x1a, 0xbd, 0x21, 0xf5, 0x49, 0xce, 0x85, 0x57, 0x33, 0x5f, 0xe1,
- 0xdb, 0x99, 0x1b, 0xe0, 0xd6, 0x48, 0xdd, 0xf1, 0x06, 0xeb, 0x3c, 0x0f,
- 0xbf, 0xa3, 0x4d, 0xb8, 0xbe, 0xb9, 0xdb, 0xbd, 0xab, 0x89, 0x7d, 0x71,
- 0x9d, 0xa3, 0x06, 0xa9, 0xbb, 0x8b, 0x25, 0xdf, 0xfd, 0x59, 0x8b, 0x52,
- 0x9e, 0x88, 0xfc, 0x05, 0xd8, 0x02, 0x9c, 0x8b, 0x45, 0xec, 0xcd, 0x24,
- 0x78, 0xc9, 0x75, 0x0e, 0xe8, 0x42, 0x61, 0x7f, 0x19, 0xba, 0x8d, 0x03,
- 0x5c, 0x3f, 0x7e, 0x2a, 0x97, 0x7b, 0x2a, 0x07, 0xfb, 0x8c, 0x91, 0x7a,
- 0xb2, 0x5b, 0xe7, 0x36, 0x48, 0xf8, 0xb9, 0x80, 0x79, 0x9c, 0xbb, 0xe0,
- 0xa7, 0x24, 0xa2, 0x33, 0x8e, 0x98, 0xed, 0x38, 0x62, 0xae, 0xa3, 0x03,
- 0xdd, 0xb6, 0x4d, 0xbb, 0xb0, 0x27, 0xc8, 0xc1, 0xf4, 0x00, 0x6c, 0xb9,
- 0xe0, 0x88, 0x3a, 0x6a, 0xc1, 0x1f, 0x18, 0xae, 0x78, 0x9a, 0x3e, 0xc1,
- 0x1a, 0x6f, 0xc8, 0xf4, 0xde, 0xc5, 0x11, 0xd1, 0xd6, 0xdc, 0x37, 0x30,
- 0x37, 0xdb, 0xc4, 0x31, 0xca, 0xf9, 0x72, 0x5e, 0x5b, 0x80, 0x8f, 0x8e,
- 0xac, 0x6b, 0xe0, 0x35, 0xce, 0x97, 0x23, 0xd9, 0xfd, 0x12, 0xf6, 0x07,
- 0xeb, 0xbf, 0x74, 0x47, 0xad, 0x99, 0xd7, 0x94, 0xe9, 0xdd, 0x69, 0x3c,
- 0xc3, 0xf3, 0x13, 0x6c, 0x99, 0x98, 0xba, 0xa0, 0xce, 0x3d, 0xd3, 0xa8,
- 0xf1, 0xb8, 0x95, 0xa8, 0x83, 0xf8, 0xae, 0x8b, 0x6b, 0x27, 0x89, 0xf8,
- 0x4f, 0x9f, 0x63, 0x3e, 0x13, 0xcd, 0xb0, 0x0e, 0x3e, 0x1b, 0x71, 0xfc,
- 0xfc, 0x1b, 0x2f, 0xf3, 0x0a, 0xbd, 0x68, 0x18, 0x00, 0x00, 0x00 };
+ 0xcd, 0x58, 0x5d, 0x6c, 0x1c, 0x57, 0x15, 0x3e, 0xf3, 0xb7, 0x3b, 0xde,
+ 0x38, 0xf1, 0x24, 0x19, 0xca, 0xa6, 0x72, 0xe9, 0x8c, 0x3d, 0x76, 0x8c,
+ 0x6c, 0x35, 0xd3, 0x76, 0xd5, 0x58, 0x68, 0xa4, 0x4e, 0x67, 0x76, 0x1d,
+ 0x2b, 0xf4, 0xc1, 0x85, 0x48, 0x3c, 0xf0, 0xe2, 0xae, 0x1d, 0x05, 0x78,
+ 0x2a, 0x28, 0x0f, 0x11, 0x2f, 0x59, 0x76, 0x37, 0xfd, 0x41, 0xdb, 0x2c,
+ 0x35, 0xc8, 0x41, 0x02, 0xa4, 0xb0, 0x69, 0xe2, 0x97, 0xad, 0x27, 0x2d,
+ 0x45, 0xea, 0x4b, 0x95, 0x28, 0x55, 0x2b, 0xc4, 0x13, 0x2f, 0x54, 0x79,
+ 0xac, 0x52, 0x5a, 0xf1, 0x00, 0x28, 0x42, 0x15, 0xaa, 0x68, 0xf0, 0xe5,
+ 0x3b, 0x77, 0x66, 0xdc, 0xdd, 0xc4, 0x49, 0xcb, 0x9f, 0x84, 0xa5, 0xf5,
+ 0x9d, 0xb9, 0xf7, 0x9e, 0x73, 0xcf, 0x3d, 0x3f, 0xdf, 0x39, 0x67, 0xca,
+ 0x2a, 0x95, 0x28, 0xfb, 0xdb, 0x8d, 0xdf, 0xc9, 0xa7, 0x9f, 0x39, 0x79,
+ 0xf8, 0xa1, 0x47, 0x1d, 0xa2, 0x87, 0x1f, 0x52, 0x94, 0xa2, 0x46, 0xff,
+ 0x85, 0x3f, 0x30, 0xb1, 0x72, 0xfe, 0xfc, 0x23, 0x53, 0x0d, 0x7e, 0xe3,
+ 0x44, 0x1e, 0x99, 0x5a, 0xb0, 0xf4, 0xe5, 0x15, 0x8f, 0x28, 0xec, 0xcf,
+ 0x3a, 0x31, 0xfd, 0x43, 0x34, 0x6c, 0x9d, 0x78, 0xfe, 0x81, 0xe0, 0xd6,
+ 0xa1, 0x37, 0x0f, 0xbb, 0x37, 0xcf, 0x6b, 0x64, 0x5a, 0xc1, 0xb2, 0x69,
+ 0x4d, 0x93, 0x39, 0x1e, 0x5c, 0x75, 0x7e, 0x7e, 0x30, 0x28, 0xd0, 0x9e,
+ 0x9c, 0x97, 0x4d, 0xcd, 0x2e, 0x35, 0xf4, 0xc0, 0xa4, 0x5a, 0xe7, 0x94,
+ 0x12, 0x75, 0x3d, 0xab, 0x0a, 0x1e, 0xa1, 0x0d, 0xfe, 0x1e, 0xde, 0x13,
+ 0x5d, 0xa9, 0x9e, 0x33, 0x49, 0x0d, 0x42, 0x3c, 0xcf, 0x51, 0xab, 0x2b,
+ 0xc4, 0x0f, 0x7d, 0x85, 0x56, 0x7c, 0x93, 0x96, 0x2d, 0x77, 0x31, 0x54,
+ 0xb6, 0x44, 0x3c, 0x25, 0xc4, 0xb7, 0x7d, 0x95, 0x54, 0x6f, 0x41, 0x89,
+ 0x36, 0x16, 0x95, 0x78, 0x63, 0x91, 0xf5, 0x01, 0xf9, 0x16, 0x94, 0x70,
+ 0x83, 0xc7, 0xc0, 0x8c, 0x3b, 0x7b, 0x68, 0xd9, 0xa6, 0x31, 0xd5, 0x9b,
+ 0xc3, 0x79, 0x65, 0xf0, 0x71, 0x28, 0xf2, 0x67, 0x2d, 0x95, 0x26, 0xf1,
+ 0x1b, 0xa1, 0x9a, 0x4f, 0x23, 0xaa, 0xa7, 0x52, 0xdd, 0x56, 0xe8, 0xe5,
+ 0x8a, 0x81, 0xdf, 0x51, 0xa5, 0xba, 0xf1, 0x9d, 0x8c, 0x0f, 0xef, 0x37,
+ 0xb1, 0xc6, 0x32, 0x33, 0xfd, 0x20, 0xed, 0x6e, 0x3c, 0x7f, 0x0b, 0xfb,
+ 0x0c, 0x8a, 0x2a, 0xb7, 0xaf, 0x8d, 0xe0, 0x59, 0xc1, 0xfc, 0x51, 0xc8,
+ 0xc5, 0x7c, 0x1c, 0xc8, 0x31, 0x4e, 0xed, 0xee, 0x22, 0xee, 0x53, 0xa0,
+ 0x86, 0x35, 0x35, 0x53, 0x27, 0x1d, 0x34, 0x1a, 0x85, 0xf6, 0x15, 0xa1,
+ 0x06, 0x42, 0x44, 0x15, 0x6f, 0xa6, 0x27, 0xcf, 0x50, 0x49, 0xf3, 0x0a,
+ 0x54, 0xf5, 0x77, 0x53, 0xcb, 0xd2, 0xa8, 0x39, 0x67, 0x50, 0xb8, 0xa4,
+ 0xe3, 0x8e, 0xfb, 0x40, 0xa7, 0x80, 0xfe, 0xa5, 0xcc, 0xe6, 0x45, 0x6a,
+ 0x5a, 0x05, 0xcc, 0x8f, 0x51, 0xd3, 0xde, 0xab, 0xa8, 0xc1, 0x0b, 0x98,
+ 0x9f, 0xb2, 0x7a, 0xf4, 0x3c, 0x46, 0x05, 0xef, 0x7b, 0xb1, 0x97, 0xdf,
+ 0x15, 0xf0, 0x23, 0x2b, 0x4a, 0x66, 0xa8, 0x95, 0xe4, 0xb4, 0x3c, 0x9f,
+ 0xce, 0x35, 0x92, 0xdb, 0xed, 0x8d, 0x7d, 0xdd, 0x1a, 0x74, 0xcc, 0xb6,
+ 0xc1, 0x9e, 0xdc, 0x2e, 0xd2, 0x07, 0x1e, 0xe7, 0x79, 0xfe, 0xc3, 0xbc,
+ 0x43, 0x5a, 0xe0, 0x59, 0x31, 0x7d, 0x85, 0xd2, 0xb5, 0x54, 0xf6, 0xc8,
+ 0x7f, 0x2c, 0x7b, 0xb7, 0xad, 0xe8, 0xdc, 0xa3, 0xb8, 0x9f, 0x74, 0x19,
+ 0x3c, 0xdb, 0xb8, 0x7f, 0x01, 0xfe, 0xd1, 0x0c, 0x55, 0x6a, 0x94, 0x4d,
+ 0x72, 0xe7, 0x57, 0xb1, 0xf2, 0x41, 0x47, 0xa3, 0x98, 0x75, 0xe5, 0xeb,
+ 0x19, 0x1d, 0xfb, 0xc6, 0xbb, 0x90, 0xb3, 0x61, 0x99, 0x70, 0xbc, 0xe5,
+ 0x63, 0x42, 0x5c, 0xf4, 0x85, 0x28, 0x04, 0xde, 0xcc, 0x25, 0x9a, 0x2d,
+ 0x1b, 0x34, 0x6d, 0x61, 0x84, 0x8e, 0xbd, 0x72, 0x9d, 0x8c, 0x5c, 0x9e,
+ 0xdc, 0x37, 0xf1, 0xd7, 0x57, 0x08, 0x3e, 0x79, 0xa3, 0xf3, 0x7b, 0xd6,
+ 0xc7, 0xcc, 0x82, 0xa4, 0x11, 0xa2, 0x37, 0x7f, 0x2f, 0x9a, 0x5f, 0x67,
+ 0x34, 0x42, 0xd4, 0x2a, 0x7c, 0xae, 0x8b, 0x3b, 0xb3, 0x7f, 0x13, 0xd5,
+ 0xfa, 0xbe, 0x59, 0xef, 0x40, 0x3e, 0x0f, 0x63, 0x9f, 0xa8, 0xde, 0xe5,
+ 0x7b, 0x98, 0xd4, 0x84, 0xde, 0x5a, 0xd8, 0xaf, 0x56, 0x76, 0xb1, 0x7f,
+ 0xc0, 0xc6, 0x4b, 0x66, 0xb5, 0xe3, 0x96, 0x5f, 0xa0, 0x25, 0x33, 0xee,
+ 0xcf, 0x96, 0x57, 0xe9, 0x01, 0x3e, 0xc7, 0x34, 0x82, 0x63, 0x66, 0x4f,
+ 0xd2, 0x1b, 0x1a, 0x95, 0xf0, 0x0c, 0x1e, 0xcd, 0x0e, 0x29, 0x91, 0xbf,
+ 0x8b, 0xef, 0x0b, 0xba, 0xc5, 0x8c, 0x6e, 0x31, 0xa3, 0x1b, 0xcb, 0xe8,
+ 0x9e, 0x1c, 0xa0, 0x7b, 0x92, 0xe9, 0xb0, 0x37, 0xcc, 0xf6, 0x86, 0xd9,
+ 0x5e, 0x3d, 0xdb, 0x5b, 0xcd, 0xf6, 0x62, 0xec, 0x3b, 0x90, 0xcf, 0x9d,
+ 0x09, 0x15, 0xc8, 0xe8, 0x89, 0x07, 0x23, 0x9f, 0xc2, 0xd8, 0x73, 0xaf,
+ 0xc7, 0xda, 0x18, 0x5d, 0xf0, 0x2d, 0x6a, 0x27, 0x0e, 0x64, 0x6f, 0x53,
+ 0x94, 0xa8, 0xa0, 0x1d, 0xa3, 0x9e, 0x77, 0x53, 0xd4, 0xfc, 0x0a, 0x6c,
+ 0x37, 0xca, 0x74, 0xe5, 0x1a, 0x14, 0xd1, 0x4c, 0x66, 0xad, 0x55, 0xaa,
+ 0xc0, 0x5f, 0x54, 0xd8, 0x6f, 0x52, 0x3e, 0x37, 0x93, 0x0a, 0xd6, 0xa9,
+ 0xa1, 0x56, 0x5c, 0xab, 0x49, 0x6e, 0x39, 0xd2, 0xc8, 0x52, 0x03, 0x1b,
+ 0x7b, 0x1a, 0x54, 0x4d, 0x4c, 0x7a, 0x4f, 0x3b, 0x25, 0xe3, 0xb4, 0xd9,
+ 0xbd, 0x2e, 0xde, 0x3c, 0xe8, 0xd0, 0x95, 0x64, 0x9c, 0x7e, 0x95, 0x94,
+ 0xe9, 0xb5, 0xc4, 0xa6, 0x57, 0x13, 0x52, 0x23, 0x1f, 0x7e, 0x6c, 0x5b,
+ 0x74, 0x39, 0x19, 0xd4, 0xfb, 0x07, 0xac, 0x77, 0x73, 0x7f, 0x40, 0xe6,
+ 0xbe, 0x80, 0x1a, 0x5a, 0x90, 0xe2, 0x40, 0x9c, 0xe2, 0x80, 0xf4, 0xa9,
+ 0x56, 0xb7, 0x79, 0xbf, 0x06, 0x0c, 0x5a, 0xf1, 0xc3, 0xbd, 0x1a, 0xec,
+ 0x12, 0x23, 0x0a, 0xd4, 0xed, 0x51, 0xda, 0xc8, 0x5d, 0xf1, 0xdc, 0xe7,
+ 0x63, 0xec, 0xf6, 0xce, 0x1a, 0x98, 0xbd, 0xdd, 0xb6, 0x7f, 0xc6, 0x19,
+ 0xa3, 0xb0, 0x9b, 0x46, 0x4f, 0xe8, 0x88, 0x1f, 0xef, 0x23, 0x8d, 0x63,
+ 0xc0, 0xd9, 0xb4, 0xe9, 0x4c, 0x97, 0x68, 0x62, 0xd3, 0xa4, 0x8d, 0x4e,
+ 0x91, 0x9c, 0xde, 0x28, 0xad, 0x74, 0x4b, 0x34, 0x79, 0x49, 0xc7, 0xde,
+ 0x5d, 0x34, 0xb9, 0xa6, 0xda, 0x1c, 0xcb, 0x31, 0x74, 0x3c, 0xd1, 0x13,
+ 0xf0, 0xd1, 0x12, 0x4d, 0xac, 0xbb, 0xd2, 0x7f, 0x56, 0xbc, 0x96, 0xaf,
+ 0xd1, 0x0f, 0xe8, 0xda, 0x5c, 0x01, 0x77, 0xb2, 0xc9, 0x9f, 0x1e, 0x3c,
+ 0xcf, 0x80, 0x9b, 0xf1, 0x1c, 0x98, 0xee, 0x71, 0x1d, 0x52, 0x99, 0x9f,
+ 0x49, 0x13, 0x97, 0x4c, 0x25, 0xee, 0xb2, 0xce, 0xd8, 0x07, 0xcd, 0xcc,
+ 0x07, 0x75, 0x25, 0x3a, 0x57, 0xc4, 0x59, 0x7f, 0x12, 0x91, 0x07, 0xdf,
+ 0x03, 0x96, 0xad, 0x54, 0xbe, 0x0f, 0xf9, 0x30, 0xd7, 0xe3, 0xb5, 0x9b,
+ 0xd9, 0x3c, 0xf3, 0x00, 0x46, 0xf8, 0xfb, 0x29, 0x62, 0x3c, 0x38, 0xc6,
+ 0x34, 0x45, 0x9a, 0x58, 0x63, 0x8c, 0xc1, 0xd8, 0xe3, 0x77, 0xbe, 0xdb,
+ 0x08, 0xd5, 0xa1, 0x95, 0xfa, 0x8c, 0x0d, 0xb9, 0x54, 0x89, 0x19, 0x75,
+ 0x60, 0x88, 0xea, 0x95, 0x30, 0xf2, 0x79, 0x3f, 0xd3, 0xd2, 0xf8, 0xb7,
+ 0xa5, 0xbd, 0x63, 0xf8, 0xaf, 0x0e, 0x79, 0x56, 0x69, 0xaa, 0x7c, 0x5c,
+ 0xae, 0x61, 0xae, 0xcf, 0x6b, 0xd6, 0x6d, 0x6b, 0x78, 0xef, 0xe7, 0x32,
+ 0x20, 0xc6, 0xbd, 0x16, 0x4e, 0x31, 0x32, 0xbd, 0xf0, 0xfe, 0x46, 0x19,
+ 0xb6, 0x01, 0xa6, 0x11, 0x74, 0x49, 0xd4, 0xeb, 0xe8, 0xc0, 0x1c, 0xf5,
+ 0x8b, 0x2a, 0xd3, 0xd9, 0xcc, 0x07, 0xf7, 0x5f, 0xd7, 0x95, 0xf8, 0x9c,
+ 0xe7, 0xfc, 0x81, 0x98, 0x7e, 0x12, 0x3a, 0x98, 0x9a, 0x6f, 0xf1, 0xfe,
+ 0xbe, 0x41, 0xde, 0x5a, 0xc3, 0xd2, 0x61, 0x53, 0x15, 0x06, 0x8d, 0x7f,
+ 0x34, 0x06, 0x5b, 0xbb, 0x4e, 0x8b, 0x7e, 0x07, 0x79, 0x0a, 0xe4, 0xf5,
+ 0x74, 0x7a, 0xb9, 0xc3, 0xba, 0x30, 0x69, 0x72, 0x5d, 0x88, 0xe7, 0x7c,
+ 0xb6, 0xc9, 0xbb, 0xd0, 0x0b, 0xe1, 0x86, 0x53, 0xf3, 0x37, 0x60, 0x9f,
+ 0x8d, 0x3e, 0xdb, 0xc6, 0x90, 0x3a, 0xf1, 0xd6, 0xe6, 0x60, 0xd7, 0x99,
+ 0x4c, 0x46, 0xb6, 0x97, 0x4e, 0xed, 0x8a, 0x4a, 0x17, 0x2b, 0x9f, 0x08,
+ 0xd5, 0x63, 0x8c, 0x2d, 0x40, 0xb7, 0xd8, 0xd7, 0xc3, 0xbe, 0xa4, 0x00,
+ 0x1d, 0xfe, 0x4d, 0x18, 0xc0, 0xdf, 0x8b, 0x15, 0xcc, 0xaf, 0x9d, 0x86,
+ 0xac, 0x1a, 0x68, 0x53, 0x1f, 0x63, 0x79, 0x16, 0x3a, 0xf9, 0xfd, 0xbc,
+ 0xf9, 0xb7, 0x25, 0xbf, 0x51, 0x9a, 0xde, 0x1c, 0xa5, 0x13, 0xfd, 0x51,
+ 0x9a, 0x38, 0xcb, 0x34, 0x42, 0xb4, 0x2b, 0x8c, 0x91, 0xf0, 0x51, 0x4f,
+ 0xea, 0xa1, 0xac, 0xa9, 0x7c, 0x4f, 0xac, 0x6f, 0x12, 0xad, 0xf6, 0xf9,
+ 0x0c, 0x7d, 0x80, 0xa7, 0x4a, 0x47, 0x7e, 0x42, 0x74, 0xa4, 0xcf, 0xb4,
+ 0xdb, 0xba, 0x03, 0x5f, 0x0b, 0x3c, 0x2d, 0xe2, 0x5c, 0xa4, 0x79, 0xc8,
+ 0x79, 0x1b, 0x11, 0x72, 0x58, 0x15, 0xbf, 0x05, 0xe4, 0x35, 0xbe, 0xff,
+ 0x1c, 0xe2, 0x8f, 0xb1, 0x7c, 0x0b, 0x77, 0x2f, 0x50, 0xdb, 0x5f, 0xc4,
+ 0x1e, 0xb6, 0xf1, 0x51, 0xac, 0xef, 0x46, 0x2e, 0xc8, 0x72, 0x85, 0xc5,
+ 0xb9, 0x62, 0x2f, 0xe2, 0x60, 0x04, 0xf8, 0x7f, 0xbf, 0x3e, 0x9c, 0x2b,
+ 0xb0, 0xcf, 0x3e, 0x80, 0xdc, 0x80, 0x44, 0x5d, 0x62, 0x5e, 0xfb, 0x31,
+ 0x8e, 0xe0, 0xfd, 0x00, 0xf6, 0x0e, 0xe6, 0x89, 0x9c, 0xee, 0x6e, 0x39,
+ 0x02, 0x31, 0xb1, 0x86, 0x58, 0x59, 0x9f, 0x61, 0xcc, 0x80, 0x3d, 0xd8,
+ 0xa6, 0x45, 0x60, 0xb8, 0x09, 0x1e, 0x6c, 0xdb, 0x22, 0x6c, 0xc8, 0x79,
+ 0xce, 0xa2, 0xc9, 0x4d, 0x8e, 0xeb, 0x34, 0x8f, 0xc4, 0xdb, 0x79, 0x84,
+ 0x64, 0x4c, 0x34, 0x13, 0xf6, 0x89, 0xd0, 0x8c, 0xce, 0x6e, 0x09, 0xc4,
+ 0x70, 0x39, 0x66, 0x5c, 0xdb, 0x9c, 0x05, 0xbd, 0x86, 0xf8, 0xa8, 0x9a,
+ 0xf5, 0xb3, 0x29, 0xa6, 0xd5, 0x37, 0x1d, 0xe9, 0x93, 0xcd, 0xc4, 0xc2,
+ 0x3b, 0x63, 0x5a, 0x8e, 0x61, 0x4c, 0x4f, 0x61, 0x04, 0x7c, 0x8b, 0x34,
+ 0x21, 0x56, 0xfc, 0x31, 0xaa, 0xc3, 0x3f, 0x43, 0xe0, 0x5a, 0x1d, 0xb8,
+ 0x16, 0x0f, 0xe0, 0x5a, 0xfc, 0x99, 0xb8, 0x06, 0xcc, 0xea, 0x02, 0xb3,
+ 0x50, 0x23, 0xbc, 0x06, 0x8c, 0x7f, 0x15, 0xe7, 0x5d, 0xee, 0xee, 0x84,
+ 0x75, 0x8c, 0x73, 0x8c, 0x77, 0x33, 0xf4, 0xe6, 0xc1, 0x7f, 0x15, 0xef,
+ 0xda, 0xc0, 0x06, 0x93, 0xbe, 0x7b, 0xf0, 0xde, 0x98, 0x77, 0x06, 0x98,
+ 0x67, 0x7c, 0x36, 0xe6, 0x35, 0x18, 0xf3, 0x74, 0xf8, 0x60, 0x03, 0x78,
+ 0xa0, 0xae, 0x0d, 0x9e, 0xd3, 0xc1, 0x39, 0x3c, 0xa7, 0x67, 0x79, 0x55,
+ 0xa5, 0x1e, 0xfc, 0x5f, 0xf3, 0xf8, 0x9c, 0x39, 0xd6, 0xbb, 0xd4, 0xff,
+ 0x13, 0xba, 0x4d, 0xc6, 0x34, 0xfc, 0x62, 0x6d, 0x94, 0xb4, 0xb3, 0x9f,
+ 0xfa, 0x3d, 0x6a, 0x03, 0xc4, 0x3b, 0xfe, 0x6d, 0xe6, 0x3c, 0x4a, 0xc0,
+ 0x1c, 0x9d, 0x0a, 0x6b, 0x06, 0xde, 0x95, 0xa1, 0x7d, 0x47, 0x90, 0x77,
+ 0xb4, 0xc0, 0x9d, 0x7f, 0x9f, 0x9f, 0xfb, 0xbc, 0xa7, 0x44, 0xea, 0xba,
+ 0xeb, 0x38, 0xaa, 0xeb, 0x5f, 0x03, 0x46, 0xbc, 0xe3, 0x31, 0x0e, 0x36,
+ 0xe1, 0x0d, 0x05, 0xd2, 0xd7, 0xc4, 0x69, 0x23, 0xe0, 0xb3, 0x1b, 0x0e,
+ 0xe2, 0xdd, 0x79, 0x09, 0x7e, 0xc4, 0x39, 0xf4, 0x22, 0xe2, 0xa7, 0x96,
+ 0xc5, 0x6a, 0xab, 0x9f, 0x9f, 0xb9, 0x0f, 0x72, 0x1b, 0xa0, 0x19, 0xdc,
+ 0xcb, 0x71, 0x20, 0xc4, 0x09, 0xdc, 0x49, 0xc3, 0x39, 0xc6, 0xba, 0x49,
+ 0x85, 0x75, 0xd6, 0x8b, 0x0b, 0xfa, 0x49, 0x6b, 0x81, 0xae, 0x0f, 0xe1,
+ 0xc2, 0x73, 0xfd, 0xeb, 0x3a, 0x63, 0xa9, 0x86, 0x18, 0x2d, 0xe2, 0x5c,
+ 0x63, 0x9b, 0x17, 0x65, 0xbc, 0x98, 0xde, 0x2b, 0x9f, 0xd8, 0xa6, 0x67,
+ 0x7c, 0x9b, 0x2a, 0x33, 0x8e, 0xb1, 0x1c, 0x9a, 0xc4, 0xd4, 0x52, 0x86,
+ 0xa9, 0x93, 0xb0, 0x67, 0x49, 0xc6, 0xa7, 0xea, 0x3d, 0x98, 0xe1, 0xea,
+ 0x5e, 0x8c, 0x3c, 0x27, 0xb2, 0x78, 0xd1, 0x21, 0x2f, 0xf3, 0x2d, 0x91,
+ 0xb6, 0xce, 0x35, 0x04, 0xdf, 0xe9, 0xaf, 0xf0, 0x6d, 0xc6, 0x0a, 0xf6,
+ 0x4f, 0x89, 0xa9, 0x98, 0x9f, 0x82, 0xcc, 0x8c, 0x0f, 0x4c, 0xc7, 0xf4,
+ 0x3b, 0xd1, 0xfd, 0x05, 0x74, 0xd6, 0x0e, 0x74, 0x98, 0xdb, 0x64, 0x1a,
+ 0xc6, 0x88, 0x7d, 0xd8, 0x1f, 0x31, 0x3e, 0x40, 0x67, 0x4c, 0x3b, 0x9e,
+ 0xc5, 0x63, 0x15, 0x6b, 0x5c, 0x03, 0xcb, 0xf8, 0x22, 0x23, 0xe0, 0x7b,
+ 0x70, 0x7d, 0xcc, 0xf9, 0x91, 0x6b, 0x52, 0xae, 0x3d, 0xf3, 0x5a, 0xd5,
+ 0x9b, 0xa9, 0xdd, 0xad, 0xee, 0xb4, 0x06, 0xeb, 0xce, 0x43, 0xc6, 0xce,
+ 0x75, 0xe7, 0x41, 0x23, 0xad, 0x3b, 0xa7, 0x8d, 0xbb, 0xd7, 0x9d, 0x39,
+ 0xed, 0xbd, 0xeb, 0xce, 0x66, 0x97, 0xcf, 0xdc, 0x19, 0x2f, 0x56, 0xe0,
+ 0xaf, 0xad, 0x24, 0xbf, 0x27, 0xf7, 0x06, 0xa1, 0x59, 0x3b, 0x9b, 0xda,
+ 0xbe, 0x29, 0x7d, 0x11, 0x38, 0xb2, 0x39, 0x0b, 0x3b, 0xa2, 0xa6, 0x1e,
+ 0xc2, 0x8e, 0x9c, 0x86, 0x75, 0x5a, 0x02, 0x46, 0xb3, 0x3e, 0x8b, 0x19,
+ 0x4e, 0x60, 0xf4, 0x3e, 0x06, 0x4e, 0xe4, 0xf8, 0xc2, 0xfc, 0xfe, 0x9f,
+ 0xf0, 0x85, 0xcc, 0x11, 0xe0, 0x84, 0x19, 0x30, 0x5e, 0x4a, 0x59, 0x50,
+ 0x93, 0x0b, 0xb1, 0xe0, 0x73, 0x0c, 0x0c, 0xf6, 0x4c, 0xec, 0x0f, 0x45,
+ 0x7a, 0xcb, 0x67, 0x9f, 0x40, 0xcf, 0xe4, 0x71, 0x8e, 0x64, 0x3c, 0xde,
+ 0x12, 0x6f, 0x79, 0x11, 0xe6, 0xaa, 0xb0, 0x3d, 0xfb, 0xc3, 0xa2, 0x72,
+ 0x64, 0xc3, 0x04, 0x1d, 0xfb, 0xc4, 0xf8, 0x1d, 0xbd, 0x50, 0xda, 0xb3,
+ 0x70, 0x7d, 0xfc, 0xef, 0xfa, 0xc8, 0x1b, 0x77, 0xf1, 0x91, 0xcb, 0x99,
+ 0x8f, 0x24, 0xf7, 0xf0, 0x91, 0x37, 0x3e, 0xa7, 0x8f, 0xb8, 0xe5, 0x0f,
+ 0x51, 0x3f, 0xbd, 0x0d, 0x39, 0x42, 0x4b, 0x88, 0x0f, 0xfd, 0x9d, 0xfa,
+ 0x94, 0xd0, 0xd4, 0x5f, 0x64, 0x9d, 0xa5, 0x79, 0xa5, 0x85, 0x77, 0xed,
+ 0x15, 0xae, 0x97, 0x39, 0xe7, 0xa4, 0xb9, 0x65, 0xe2, 0xc5, 0xd4, 0x3f,
+ 0x26, 0x5e, 0x11, 0xe2, 0xc2, 0x0e, 0xfe, 0xc0, 0x35, 0xf4, 0x55, 0xf8,
+ 0x55, 0x8b, 0xfe, 0x17, 0x35, 0x34, 0x63, 0x78, 0xc5, 0x3c, 0xde, 0xc9,
+ 0xed, 0x9f, 0xdb, 0xbe, 0x40, 0xe7, 0xad, 0x3d, 0xd0, 0xdb, 0xa3, 0xd4,
+ 0xfa, 0xb1, 0xce, 0x7d, 0x05, 0xfc, 0xe2, 0x71, 0x9d, 0x63, 0x17, 0x7d,
+ 0x24, 0x9e, 0x07, 0xeb, 0x6c, 0xf8, 0xa5, 0x5f, 0xc8, 0xe3, 0x65, 0x00,
+ 0xfb, 0x4f, 0xa1, 0x54, 0xb9, 0x23, 0xaf, 0x0c, 0xf5, 0xd4, 0x1a, 0x7a,
+ 0xea, 0x58, 0xf2, 0xe0, 0xbe, 0x2b, 0xd5, 0x63, 0x5b, 0xf6, 0xd1, 0x5b,
+ 0xa2, 0x25, 0x7b, 0xe9, 0x03, 0x05, 0x2a, 0x2d, 0x66, 0x3e, 0xe3, 0x20,
+ 0x1f, 0xb9, 0x7e, 0x03, 0xfc, 0xb9, 0xd6, 0x80, 0x1c, 0xb4, 0x8a, 0x58,
+ 0xbc, 0x80, 0x3c, 0xbc, 0x02, 0xbd, 0xd4, 0x65, 0x6c, 0x8c, 0xd1, 0x35,
+ 0xe4, 0xfe, 0x36, 0xf2, 0xf3, 0x19, 0xe8, 0xa6, 0x05, 0xdd, 0xc4, 0x49,
+ 0x1a, 0x27, 0xd7, 0xa0, 0x9b, 0x85, 0x01, 0xdd, 0x2c, 0xfc, 0x47, 0xfd,
+ 0xc5, 0x1f, 0x91, 0x6b, 0xcd, 0x65, 0x1d, 0xf3, 0x57, 0x12, 0x99, 0x5b,
+ 0x97, 0x5a, 0x1d, 0x6a, 0xdc, 0x1f, 0x9c, 0xe6, 0xda, 0x8e, 0x6b, 0xb3,
+ 0xf9, 0x95, 0x0a, 0xe6, 0xfa, 0x26, 0x45, 0xd0, 0xcf, 0x37, 0x0f, 0xd3,
+ 0xb2, 0x16, 0xb0, 0x4f, 0xe3, 0x3d, 0xa1, 0x46, 0x74, 0x18, 0xf5, 0x56,
+ 0x32, 0xbe, 0x8c, 0x7e, 0x1c, 0xbe, 0xd5, 0xa0, 0x10, 0x72, 0x86, 0xe0,
+ 0xbd, 0xd0, 0x31, 0xcd, 0xd5, 0x0e, 0xf7, 0x51, 0x0d, 0xe2, 0x5e, 0xbd,
+ 0xd7, 0xbf, 0x09, 0x7e, 0x23, 0xdf, 0x40, 0x7f, 0xeb, 0x34, 0x81, 0xd3,
+ 0xcf, 0xc2, 0x6d, 0x5b, 0x36, 0x7f, 0xcb, 0x60, 0x1c, 0x1d, 0x07, 0x8f,
+ 0xa7, 0x0b, 0xa9, 0xaf, 0x8e, 0x83, 0x0f, 0xc7, 0x11, 0xe1, 0x3c, 0xd6,
+ 0x65, 0xee, 0x7f, 0xe5, 0x81, 0xfa, 0xbe, 0x40, 0x39, 0x86, 0x35, 0xa1,
+ 0x37, 0xd6, 0x75, 0xe4, 0x9d, 0x2c, 0xe4, 0xdf, 0x6d, 0x5a, 0xc0, 0x81,
+ 0xfa, 0x1c, 0x63, 0x96, 0x02, 0xdf, 0xa3, 0xb4, 0xaf, 0x44, 0x1f, 0x52,
+ 0x9f, 0x43, 0xde, 0xb6, 0x8b, 0x72, 0x6c, 0x24, 0xa7, 0xb3, 0xfd, 0xaa,
+ 0xdc, 0xc7, 0xf9, 0xa2, 0x99, 0xc8, 0x7e, 0x42, 0xa9, 0x76, 0xc9, 0xa9,
+ 0xfb, 0xe8, 0x93, 0x50, 0x7b, 0xb4, 0x13, 0xce, 0xf5, 0x73, 0xa6, 0x2a,
+ 0xb1, 0xef, 0x06, 0x68, 0xf0, 0xbc, 0x49, 0x6a, 0xdd, 0xe7, 0xef, 0x0c,
+ 0xfc, 0x0d, 0x04, 0xf1, 0x63, 0xd3, 0x6e, 0xd0, 0x43, 0xae, 0x71, 0x96,
+ 0x2b, 0xac, 0xcb, 0x3a, 0x85, 0x79, 0x1f, 0x52, 0xd3, 0x6f, 0x33, 0xef,
+ 0x66, 0x67, 0x99, 0x88, 0x1f, 0xc6, 0x5d, 0x9f, 0x73, 0xde, 0x97, 0x34,
+ 0xba, 0x49, 0x12, 0x37, 0xad, 0x87, 0x91, 0x0b, 0x0f, 0x83, 0x26, 0x94,
+ 0x98, 0x93, 0xf6, 0x15, 0x39, 0x8d, 0xa7, 0x0d, 0xf3, 0x58, 0xd6, 0x87,
+ 0xdf, 0x43, 0xc4, 0x59, 0x25, 0x3b, 0x6f, 0xd0, 0x67, 0xdf, 0x87, 0xcf,
+ 0xde, 0xc8, 0xf6, 0x00, 0x87, 0xed, 0x02, 0xf6, 0xb1, 0x8c, 0x8c, 0x2f,
+ 0x4c, 0xb3, 0x65, 0x0c, 0xf3, 0x99, 0xdc, 0x81, 0xc7, 0x47, 0x03, 0x3c,
+ 0x6c, 0xbe, 0x9b, 0x55, 0x4f, 0x7b, 0x6c, 0xf9, 0x57, 0x87, 0x9e, 0xd1,
+ 0x93, 0xdc, 0xa7, 0xe2, 0x1e, 0x5c, 0x9b, 0xc5, 0x72, 0xfe, 0x97, 0xc5,
+ 0x61, 0xbe, 0xa7, 0xb2, 0x73, 0xfc, 0x34, 0x36, 0x3c, 0x8c, 0xc9, 0x8d,
+ 0x01, 0xd9, 0x8d, 0x1d, 0xce, 0xdd, 0xa5, 0xa3, 0x35, 0x50, 0xd8, 0xdf,
+ 0xb4, 0x80, 0xf3, 0x33, 0x9e, 0xb7, 0xfd, 0x83, 0x7d, 0xf5, 0xb3, 0x7d,
+ 0xd4, 0xf8, 0x9c, 0x3e, 0xfa, 0x72, 0x87, 0x71, 0x23, 0xf5, 0xd1, 0xfa,
+ 0x1d, 0x3e, 0x8a, 0xfa, 0xc8, 0xce, 0xfd, 0x93, 0xe3, 0x25, 0xf7, 0xcf,
+ 0xfc, 0x99, 0x63, 0x1c, 0xb8, 0x9c, 0xe1, 0x5c, 0x13, 0x38, 0x57, 0x95,
+ 0x79, 0xcf, 0x2d, 0x57, 0x29, 0x8d, 0xe5, 0x55, 0xc4, 0x72, 0x55, 0xe3,
+ 0x3c, 0xc8, 0x31, 0xcc, 0x74, 0x1c, 0xc7, 0x4c, 0x37, 0x96, 0xd1, 0x61,
+ 0x44, 0x3c, 0x57, 0xb3, 0x78, 0x6e, 0x75, 0x5d, 0xa7, 0x9a, 0xc5, 0x73,
+ 0x0b, 0x31, 0xdc, 0xce, 0xe2, 0xb9, 0x95, 0xc5, 0x33, 0x7f, 0xdf, 0xd3,
+ 0x2a, 0x9c, 0x1b, 0x5d, 0x27, 0x06, 0xc6, 0xb5, 0x25, 0xcf, 0x06, 0xee,
+ 0x09, 0x19, 0xbb, 0x79, 0x5c, 0xdc, 0xf1, 0x1d, 0x0c, 0xf7, 0xf9, 0x34,
+ 0xd7, 0xd4, 0x90, 0x6b, 0x2e, 0x20, 0xd7, 0xf4, 0x06, 0xbe, 0x83, 0x9d,
+ 0x97, 0xb9, 0xe6, 0xeb, 0xc5, 0x3c, 0xd7, 0xf4, 0xb2, 0x5c, 0xd3, 0x93,
+ 0xb9, 0xe6, 0xab, 0x45, 0xce, 0x35, 0x4d, 0x3a, 0x5a, 0x1c, 0xcc, 0x35,
+ 0xcd, 0xa1, 0x5c, 0x93, 0xd3, 0xf2, 0xfc, 0x4e, 0xb9, 0x26, 0xd7, 0xd9,
+ 0xbd, 0x6a, 0x92, 0x7c, 0x0f, 0xcb, 0xca, 0xb8, 0xc4, 0x78, 0x9c, 0xd6,
+ 0xfc, 0x57, 0x92, 0x3c, 0x96, 0x4e, 0xe3, 0x1c, 0xbc, 0x77, 0x77, 0x8a,
+ 0x25, 0x33, 0x8b, 0xa5, 0xdd, 0x29, 0x4d, 0x77, 0x30, 0x9e, 0x4e, 0x17,
+ 0x87, 0xe3, 0x29, 0xe7, 0x93, 0xc7, 0x53, 0xca, 0xf3, 0x3d, 0xad, 0xcc,
+ 0x35, 0x02, 0xfa, 0x6d, 0xd7, 0x5f, 0xc0, 0xec, 0xa5, 0xfe, 0x2c, 0x6a,
+ 0x6e, 0x9d, 0xae, 0xe6, 0x78, 0x23, 0xbf, 0x09, 0x61, 0xec, 0xe7, 0xb2,
+ 0x16, 0xb7, 0xd7, 0x7a, 0xa8, 0xbb, 0xdf, 0x01, 0x8e, 0x5c, 0x94, 0xeb,
+ 0x9f, 0x88, 0xab, 0x68, 0x09, 0xdb, 0x5e, 0xbe, 0xef, 0x17, 0x38, 0xcf,
+ 0xb5, 0xce, 0xe3, 0xe9, 0xd9, 0x7e, 0xae, 0x13, 0x5e, 0xe7, 0xb9, 0xbf,
+ 0x23, 0x9f, 0xa0, 0x66, 0xdf, 0xde, 0xcb, 0xfd, 0x8f, 0x87, 0x3b, 0x3b,
+ 0xf4, 0xfa, 0x50, 0x0f, 0x94, 0xf6, 0x3e, 0x75, 0xf9, 0x8d, 0x97, 0x6b,
+ 0x97, 0xe8, 0x0b, 0x2a, 0x9d, 0xa2, 0xaf, 0xf9, 0x3c, 0xa7, 0x52, 0xed,
+ 0x31, 0x21, 0x9e, 0x41, 0x1d, 0xf3, 0xd4, 0x50, 0x1d, 0x53, 0xa4, 0x89,
+ 0x47, 0x06, 0x7b, 0xc8, 0x2d, 0x31, 0x31, 0xed, 0x9e, 0x0f, 0x29, 0x54,
+ 0x6a, 0x1b, 0x5c, 0xe7, 0x6e, 0xd7, 0xb5, 0x44, 0xfb, 0x6e, 0x09, 0x75,
+ 0x9a, 0xf3, 0xe2, 0x6f, 0x33, 0x5d, 0x61, 0xed, 0xdc, 0x2d, 0x60, 0x6b,
+ 0x55, 0x7e, 0x0b, 0x0e, 0x37, 0xf8, 0x1c, 0x7e, 0xc7, 0x98, 0x70, 0xcd,
+ 0x73, 0xb7, 0xef, 0xb3, 0x3a, 0xec, 0xe2, 0x3a, 0xc7, 0x35, 0x92, 0xdf,
+ 0x37, 0x56, 0x7c, 0xf7, 0xa7, 0x2d, 0x4a, 0x71, 0xa2, 0xea, 0x2f, 0x41,
+ 0x16, 0xd4, 0x9d, 0xd6, 0x32, 0x6c, 0x33, 0x0d, 0x5c, 0x72, 0x9d, 0x47,
+ 0x54, 0x5b, 0xe2, 0xf8, 0x2a, 0x78, 0x6b, 0x8f, 0x70, 0x4d, 0xf9, 0xb1,
+ 0x58, 0xed, 0xcb, 0x7c, 0xec, 0xb3, 0x8f, 0xc4, 0xc9, 0x5e, 0x95, 0xc7,
+ 0x30, 0xe1, 0xe7, 0x02, 0x71, 0x2d, 0xb9, 0xb3, 0xff, 0xd8, 0x56, 0xf5,
+ 0x9c, 0x63, 0xd5, 0xba, 0x8e, 0xb5, 0xd0, 0x55, 0xe1, 0xdd, 0xfb, 0x4c,
+ 0xda, 0x03, 0x9b, 0x20, 0x1f, 0xd3, 0x7d, 0x90, 0xe5, 0x92, 0x63, 0xc5,
+ 0xa8, 0x0f, 0xbf, 0xa7, 0xb9, 0xd6, 0x53, 0xa4, 0x98, 0x54, 0xba, 0x25,
+ 0xd2, 0x6f, 0x33, 0x8e, 0x55, 0xdd, 0x3e, 0xfb, 0x16, 0xce, 0x66, 0x99,
+ 0x38, 0x46, 0x39, 0x5f, 0x2e, 0x2a, 0x4b, 0xd0, 0xd1, 0xb1, 0x8d, 0x5d,
+ 0xc0, 0x35, 0xce, 0x97, 0x07, 0xb2, 0x6f, 0x50, 0xb0, 0x0f, 0xee, 0xff,
+ 0xfa, 0x1d, 0xf5, 0x67, 0x5e, 0x67, 0x32, 0xbd, 0x10, 0xcd, 0x79, 0x3e,
+ 0x9f, 0x20, 0xcb, 0xd4, 0xcc, 0x25, 0xd9, 0x13, 0xcd, 0xa2, 0xee, 0xe3,
+ 0x51, 0xa0, 0x26, 0xe2, 0xef, 0x61, 0xae, 0x55, 0xc7, 0x73, 0x35, 0x7b,
+ 0x6e, 0x72, 0xbf, 0x34, 0xcf, 0x3c, 0xb8, 0x6f, 0xe2, 0xf8, 0xf9, 0x27,
+ 0x6e, 0xb7, 0x92, 0x82, 0x90, 0x18, 0x00, 0x00, 0x00 };
static const u32 bnx2_TPAT_b09FwData[(0x0/4) + 1] = { 0x0 };
static const u32 bnx2_TPAT_b09FwRodata[(0x0/4) + 1] = { 0x0 };
static struct fw_info bnx2_tpat_fw_09 = {
+ /* Firmware version: 3.7.1 */
.ver_major = 0x3,
- .ver_minor = 0x4,
- .ver_fix = 0x3,
+ .ver_minor = 0x7,
+ .ver_fix = 0x1,
.start_addr = 0x08000860,
.text_addr = 0x08000800,
- .text_len = 0x1864,
+ .text_len = 0x188c,
.text_index = 0x0,
.gz_text = bnx2_TPAT_b09FwText,
.gz_text_len = sizeof(bnx2_TPAT_b09FwText),
- .data_addr = 0x08002080,
+ .data_addr = 0x080020c0,
.data_len = 0x0,
.data_index = 0x0,
.data = bnx2_TPAT_b09FwData,
- .sbss_addr = 0x08002088,
- .sbss_len = 0x2c,
+ .sbss_addr = 0x080020c8,
+ .sbss_len = 0x30,
.sbss_index = 0x0,
- .bss_addr = 0x080020c0,
+ .bss_addr = 0x08002100,
.bss_len = 0x850,
.bss_index = 0x0,
@@ -3267,768 +3289,770 @@ static struct fw_info bnx2_tpat_fw_09 = {
};
static u8 bnx2_TXP_b09FwText[] = {
-/* 0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, */
- 0xcd, 0x7c,
- 0x6f, 0x70, 0x5b, 0xd7, 0x95, 0xdf, 0x79, 0xef, 0x81, 0x24, 0x48, 0xd1,
- 0xd4, 0x13, 0x17, 0x56, 0x60, 0x87, 0x71, 0x00, 0xf1, 0x81, 0x66, 0x42,
- 0xae, 0x04, 0x2b, 0x4c, 0xc2, 0x6d, 0xd1, 0xf8, 0x05, 0x00, 0x29, 0x48,
- 0xd1, 0x6c, 0x68, 0x95, 0x49, 0x94, 0x54, 0xe3, 0x62, 0x41, 0x52, 0xf1,
- 0xb6, 0xce, 0x54, 0x9b, 0x78, 0x5a, 0x4d, 0xeb, 0xad, 0x11, 0x90, 0xfa,
- 0xe7, 0x85, 0x04, 0xda, 0x62, 0x44, 0x7f, 0xc8, 0x07, 0x18, 0x80, 0x24,
- 0x6f, 0xf2, 0x44, 0x28, 0x9b, 0x7f, 0xfd, 0xd0, 0xac, 0x50, 0x4a, 0xd6,
- 0xba, 0x9b, 0xb4, 0xa3, 0xed, 0x66, 0x67, 0x3b, 0xd3, 0x2f, 0x1c, 0x49,
- 0xf6, 0x7a, 0x77, 0x67, 0x36, 0xda, 0x6e, 0xb6, 0xab, 0xb6, 0xb2, 0xd1,
- 0xdf, 0xef, 0xbe, 0xf7, 0x28, 0x90, 0xa6, 0x6c, 0xcb, 0xb3, 0xed, 0x94,
- 0x33, 0x18, 0xe0, 0xdd, 0x77, 0xdf, 0xb9, 0xe7, 0x9e, 0x73, 0xee, 0x39,
- 0xe7, 0x77, 0xee, 0x7d, 0x0c, 0x8b, 0x74, 0x89, 0xf7, 0xf7, 0x00, 0x3e,
- 0x91, 0x43, 0x87, 0x9f, 0xd9, 0x3e, 0xb2, 0xfd, 0x13, 0xf8, 0xf9, 0x09,
- 0x31, 0x02, 0x06, 0x6f, 0xbe, 0x69, 0x88, 0x64, 0xff, 0x42, 0x3e, 0xf0,
- 0x1f, 0x1e, 0x37, 0x7d, 0xfa, 0xfc, 0x48, 0x50, 0x4f, 0x4c, 0xec, 0x4a,
- 0x5a, 0x12, 0x34, 0x12, 0xb2, 0x6f, 0xca, 0x12, 0xb1, 0x9d, 0xa1, 0x48,
- 0x4a, 0xde, 0x6a, 0xe6, 0x43, 0x01, 0x61, 0xfb, 0x47, 0x12, 0x77, 0x9e,
- 0xfb, 0xc9, 0xa7, 0xa3, 0xb7, 0xca, 0x86, 0x04, 0xcd, 0x44, 0x56, 0xcc,
- 0x01, 0x09, 0xf6, 0xe1, 0x99, 0x6f, 0x3f, 0x6a, 0x18, 0xd2, 0xb3, 0xca,
- 0xab, 0xcc, 0x95, 0x56, 0x9a, 0x3f, 0x79, 0x34, 0x2c, 0xbf, 0x57, 0x0f,
- 0xc9, 0xf7, 0xea, 0xa6, 0x5c, 0xac, 0x07, 0xb4, 0xf1, 0x92, 0x29, 0xb3,
- 0xa5, 0x69, 0xfd, 0x48, 0x31, 0x2f, 0xa9, 0x7a, 0x56, 0x2f, 0x2c, 0x98,
- 0x3d, 0xc9, 0xf3, 0x39, 0x7d, 0x76, 0xa1, 0xb7, 0x27, 0x75, 0x7e, 0x5a,
- 0x2f, 0x14, 0xc3, 0x3d, 0xc9, 0xba, 0xd9, 0x93, 0x5a, 0x0c, 0xe1, 0xba,
- 0xb7, 0x27, 0xb9, 0x18, 0x9d, 0x17, 0xd9, 0x8a, 0x3e, 0xe1, 0x9e, 0x54,
- 0x29, 0x9a, 0x15, 0xe9, 0x8f, 0xbf, 0x2a, 0x7d, 0x3d, 0xa9, 0xfa, 0x3f,
- 0xd1, 0x1b, 0xa6, 0x26, 0x85, 0x5f, 0x15, 0x33, 0x9c, 0xb8, 0xd5, 0x7c,
- 0xc8, 0xd2, 0xc4, 0xb4, 0x6e, 0x37, 0xb7, 0x58, 0x41, 0xc9, 0x9d, 0xee,
- 0x14, 0x5b, 0xcd, 0xc9, 0x94, 0xdc, 0xe2, 0x90, 0xb9, 0x2c, 0x6d, 0x62,
- 0x87, 0xfc, 0xeb, 0x66, 0x33, 0x19, 0xff, 0x32, 0xe5, 0x8a, 0x71, 0xa4,
- 0x67, 0xbc, 0x2e, 0x92, 0x2c, 0x05, 0x25, 0x19, 0x7f, 0xab, 0xe9, 0x3e,
- 0x13, 0xc4, 0x98, 0x81, 0x9e, 0xb1, 0x52, 0xb3, 0x99, 0x8e, 0x83, 0x7e,
- 0xdc, 0x7f, 0xb6, 0x4d, 0xca, 0x21, 0xbb, 0x3c, 0x1b, 0xff, 0x6f, 0xba,
- 0xab, 0x13, 0xce, 0x91, 0xd7, 0xb6, 0xe8, 0x56, 0x5e, 0x72, 0x21, 0x29,
- 0x17, 0xe2, 0x9f, 0x92, 0x13, 0xf1, 0x30, 0xe6, 0x17, 0x94, 0x63, 0x71,
- 0xc8, 0xd1, 0x3a, 0xac, 0x25, 0xeb, 0xd1, 0x48, 0x56, 0x9e, 0x97, 0xe4,
- 0x62, 0xbf, 0x99, 0x16, 0x8c, 0x6d, 0x35, 0x3f, 0x9a, 0x8c, 0x63, 0xbc,
- 0xe1, 0xff, 0xd5, 0xb4, 0x43, 0xd1, 0x6c, 0x59, 0x06, 0xa5, 0x50, 0xea,
- 0x8f, 0xff, 0x4c, 0x34, 0x09, 0x5a, 0x62, 0x4f, 0x59, 0x26, 0xe4, 0x16,
- 0x1d, 0x4c, 0x19, 0x4d, 0xd9, 0x83, 0xf1, 0x93, 0x16, 0xee, 0xd7, 0x65,
- 0xb3, 0x6e, 0xb5, 0x4b, 0xc1, 0x94, 0x50, 0x97, 0x3c, 0x22, 0x85, 0xd3,
- 0x68, 0x8f, 0xdb, 0xbd, 0x3a, 0x9e, 0xc9, 0x8c, 0xb0, 0x4d, 0x34, 0x23,
- 0x11, 0x33, 0x53, 0xe0, 0xa8, 0xe2, 0x0c, 0x62, 0xfc, 0x98, 0xdd, 0xa9,
- 0x99, 0xb2, 0x62, 0x06, 0xa4, 0xea, 0xc4, 0xec, 0xb0, 0xd6, 0x2e, 0xc7,
- 0x62, 0x5d, 0x90, 0x69, 0x18, 0xb4, 0xe5, 0x9b, 0x7a, 0x22, 0x16, 0xce,
- 0x41, 0x51, 0x3a, 0x64, 0x35, 0x07, 0x7e, 0xe6, 0xe2, 0x59, 0x2d, 0x55,
- 0xff, 0x8a, 0x96, 0x3c, 0xbf, 0x5f, 0xdb, 0x75, 0x1e, 0x7d, 0xea, 0xe7,
- 0x3c, 0xbb, 0x0b, 0x83, 0x37, 0x1d, 0xcf, 0xb2, 0x1d, 0x3c, 0x2b, 0xde,
- 0xd1, 0x06, 0x5d, 0x36, 0x26, 0x43, 0x3d, 0x49, 0xa5, 0x4b, 0xf2, 0xa6,
- 0x4b, 0x6e, 0x42, 0x93, 0x5e, 0xcb, 0x96, 0xe0, 0x27, 0xa1, 0xcf, 0x45,
- 0xe8, 0x72, 0x31, 0x22, 0x47, 0x4a, 0x12, 0xd2, 0x85, 0x63, 0x65, 0xf5,
- 0xaa, 0x43, 0x7b, 0x80, 0x6e, 0xa1, 0xfb, 0x82, 0xc3, 0x67, 0xa1, 0xc3,
- 0x52, 0x1a, 0xf2, 0xc9, 0x60, 0xec, 0x7d, 0xda, 0x9e, 0xea, 0xa4, 0x96,
- 0x81, 0x9d, 0x14, 0x4e, 0x0f, 0x41, 0x77, 0xd1, 0xc8, 0x8a, 0x6c, 0x96,
- 0x82, 0x65, 0x45, 0xbe, 0x2c, 0xdd, 0x72, 0x6c, 0xd1, 0x92, 0x23, 0x8b,
- 0x21, 0xc9, 0x9b, 0x51, 0xb3, 0x26, 0x7d, 0xd9, 0x4d, 0x89, 0x1e, 0x79,
- 0xfe, 0x74, 0x34, 0x53, 0x96, 0x7e, 0xfb, 0x75, 0xdc, 0xcf, 0x9d, 0xa4,
- 0x4e, 0x25, 0x9f, 0x8a, 0x1b, 0x92, 0x85, 0x4d, 0x18, 0xd6, 0x1f, 0x81,
- 0xff, 0xe6, 0x73, 0xc9, 0x78, 0x34, 0x2c, 0xa2, 0x4b, 0xea, 0x0b, 0xfd,
- 0xe6, 0x6e, 0x89, 0x9a, 0x19, 0xca, 0x3f, 0x3e, 0x04, 0x3d, 0xfc, 0x77,
- 0xca, 0x1e, 0xb4, 0xa8, 0xe3, 0xa1, 0xf0, 0x31, 0xe8, 0x32, 0xab, 0x74,
- 0xdc, 0x83, 0xf1, 0x03, 0x9e, 0xed, 0xf4, 0x48, 0xbe, 0x7a, 0xc3, 0x93,
- 0x43, 0x8f, 0xcc, 0x57, 0xbb, 0xa5, 0x00, 0x1d, 0x16, 0xc4, 0x92, 0xc2,
- 0xf9, 0x3f, 0xf7, 0xda, 0x2d, 0x99, 0x3b, 0xff, 0x32, 0xec, 0xe1, 0xb0,
- 0xb6, 0xbf, 0xfe, 0x0b, 0xcd, 0xb3, 0x1f, 0xd8, 0x5f, 0x50, 0xec, 0x89,
- 0xa0, 0x9c, 0xab, 0xbb, 0xf6, 0x57, 0xc1, 0x1a, 0xb3, 0x4d, 0x1b, 0xb6,
- 0xf4, 0xc6, 0x6a, 0x9f, 0x73, 0xf5, 0x3e, 0x3c, 0x1b, 0x94, 0x23, 0x75,
- 0xf6, 0xcf, 0xc3, 0xc6, 0x82, 0xb2, 0xf4, 0x68, 0xb7, 0x64, 0xd1, 0x5e,
- 0x58, 0x14, 0x3b, 0x19, 0xd7, 0xf1, 0x4c, 0x0f, 0xe6, 0xb2, 0x15, 0x9f,
- 0x2e, 0x99, 0xaa, 0x76, 0xd8, 0x86, 0x15, 0x92, 0xa9, 0x3a, 0xf5, 0x8f,
- 0xef, 0x92, 0x6f, 0x03, 0x94, 0x2f, 0xdb, 0xf9, 0x1c, 0xdb, 0x4d, 0xb4,
- 0xb7, 0xb6, 0xd1, 0xb6, 0x37, 0x53, 0xa6, 0x83, 0x82, 0xb6, 0x5c, 0x29,
- 0x66, 0xee, 0xe7, 0x77, 0x9d, 0xf6, 0xd0, 0x6a, 0x0b, 0x01, 0xf4, 0x87,
- 0x1e, 0xab, 0x18, 0xeb, 0xf4, 0x9d, 0x66, 0xdb, 0x08, 0xae, 0x2d, 0x2c,
- 0xaa, 0x2e, 0x8e, 0x1d, 0x00, 0x5f, 0xba, 0x64, 0xab, 0x8a, 0xb7, 0x08,
- 0x6d, 0xc0, 0x9d, 0x47, 0x9f, 0xcc, 0x2e, 0x76, 0xf7, 0xa4, 0x17, 0xd9,
- 0x9e, 0x0c, 0x1b, 0x98, 0xe7, 0x54, 0x5c, 0x1a, 0x73, 0x71, 0xbd, 0x3f,
- 0x00, 0xbe, 0xa6, 0xb1, 0xe0, 0x30, 0x0f, 0x8f, 0xc7, 0x06, 0xee, 0xf7,
- 0xca, 0xd4, 0x79, 0xf6, 0xe5, 0x18, 0x85, 0x2d, 0xba, 0x24, 0xc0, 0x1b,
- 0x3e, 0x56, 0x14, 0xf7, 0x3b, 0x31, 0x4e, 0x37, 0x6c, 0x27, 0x83, 0x31,
- 0x9b, 0x8f, 0x27, 0xe3, 0xbd, 0x92, 0x5d, 0xed, 0x2b, 0xb0, 0x3b, 0xf6,
- 0x1f, 0x5c, 0xd7, 0x17, 0xf2, 0x3d, 0x0f, 0x9a, 0x8b, 0x9d, 0x90, 0x21,
- 0xdb, 0x75, 0xf0, 0xdc, 0x01, 0x1e, 0x82, 0x98, 0x4f, 0x3f, 0xd6, 0x43,
- 0x07, 0xe8, 0x6f, 0xc2, 0x9c, 0x3a, 0x65, 0xfa, 0x74, 0x2f, 0x74, 0x61,
- 0xa2, 0x6f, 0x50, 0x9e, 0x2f, 0x45, 0x61, 0x03, 0xec, 0x0f, 0x1d, 0x2c,
- 0x46, 0xc3, 0x55, 0xb1, 0x65, 0x2e, 0xde, 0x01, 0xfb, 0x6a, 0x36, 0x67,
- 0x60, 0x1f, 0xdf, 0x51, 0xfe, 0x62, 0xc8, 0x1c, 0xd3, 0x24, 0xdf, 0x91,
- 0x38, 0x0c, 0x7e, 0xa2, 0x4f, 0x89, 0xf0, 0x7a, 0x87, 0xc6, 0x35, 0x0b,
- 0x39, 0x72, 0x6c, 0xf8, 0xa4, 0xad, 0x90, 0x21, 0xfd, 0x56, 0x1f, 0xec,
- 0x39, 0xac, 0xfc, 0xc9, 0xd8, 0x86, 0xfe, 0x24, 0x3a, 0x51, 0xc6, 0x58,
- 0x85, 0xf3, 0x01, 0xfa, 0xb0, 0x51, 0x2c, 0x57, 0x79, 0x00, 0x6b, 0x6f,
- 0x56, 0xd9, 0xc7, 0x09, 0xce, 0xb7, 0xf9, 0xf9, 0x38, 0xf9, 0xe2, 0x7c,
- 0x6d, 0x3c, 0x4b, 0x1b, 0x8c, 0x1e, 0xb6, 0xd5, 0xf8, 0x27, 0xbc, 0xf1,
- 0x5d, 0xde, 0x0b, 0xa5, 0x1e, 0x2d, 0xa5, 0x78, 0xf0, 0xe9, 0x88, 0x2c,
- 0x9f, 0xec, 0x37, 0xf7, 0xc0, 0x86, 0xe9, 0xa7, 0x96, 0x2f, 0x50, 0xc7,
- 0xa0, 0x31, 0x42, 0x1d, 0x9b, 0x8a, 0xbf, 0xe4, 0x22, 0xd7, 0x9e, 0xf4,
- 0x19, 0x42, 0x1f, 0x01, 0x9f, 0x8b, 0xb5, 0x38, 0xeb, 0xad, 0xc5, 0x9c,
- 0x43, 0xfb, 0x7b, 0x06, 0xcf, 0xea, 0x32, 0x16, 0xa3, 0x7f, 0x78, 0x5e,
- 0x52, 0xf0, 0x91, 0xd0, 0xa3, 0x54, 0x31, 0x97, 0x4a, 0xa9, 0xd5, 0x6f,
- 0xc1, 0xb6, 0x86, 0xff, 0xae, 0xe9, 0xfa, 0x43, 0xfa, 0x06, 0xfa, 0x9a,
- 0x82, 0xa9, 0x43, 0x72, 0x3a, 0x9c, 0x21, 0x74, 0x13, 0x4f, 0x1a, 0xd1,
- 0x4c, 0x16, 0x7c, 0x4d, 0x59, 0x4d, 0xb1, 0x1e, 0x13, 0x44, 0x0c, 0xf4,
- 0xa9, 0xcb, 0x4e, 0xdf, 0x3f, 0x2d, 0x3b, 0xbe, 0x2e, 0xa8, 0x57, 0xea,
- 0xc1, 0xf7, 0x11, 0x01, 0xb9, 0x0c, 0xdf, 0x35, 0x57, 0xea, 0x96, 0x06,
- 0x78, 0xba, 0xe2, 0xf8, 0xb6, 0x66, 0x78, 0xb6, 0xc6, 0x67, 0xba, 0xf1,
- 0x7c, 0x00, 0x7e, 0x4d, 0xf2, 0x46, 0x02, 0xbf, 0x8b, 0xa4, 0xc9, 0x36,
- 0xdf, 0xce, 0xb9, 0x66, 0xa2, 0x76, 0x59, 0xda, 0x25, 0x13, 0x43, 0xfc,
- 0x58, 0xd4, 0x31, 0x56, 0x1f, 0x7c, 0x79, 0x40, 0x0e, 0x96, 0x42, 0xf2,
- 0xd5, 0x12, 0xe7, 0x95, 0xd6, 0x52, 0xd0, 0x5b, 0x72, 0xb1, 0x09, 0x9d,
- 0x8f, 0xc3, 0xe7, 0x65, 0xb4, 0x31, 0xf8, 0x9f, 0xdd, 0xd5, 0xaf, 0x68,
- 0xe9, 0xf3, 0x59, 0x6d, 0xbc, 0xbe, 0x5f, 0xcb, 0x9c, 0x9f, 0xd4, 0x76,
- 0xb5, 0xf8, 0x22, 0xd1, 0xde, 0xdd, 0x17, 0x9d, 0x38, 0xcd, 0x31, 0xfb,
- 0xe3, 0x1b, 0xfb, 0xa2, 0x5f, 0x6a, 0xad, 0xbe, 0xa8, 0x1f, 0xbe, 0x28,
- 0x03, 0x5f, 0x34, 0x7e, 0xdf, 0xbe, 0xa8, 0x5d, 0xdf, 0xd8, 0x17, 0x75,
- 0xeb, 0x77, 0x7d, 0x11, 0x63, 0xcf, 0xbf, 0xc6, 0xb5, 0x29, 0xdb, 0x76,
- 0xfa, 0x72, 0x0e, 0xc3, 0x0f, 0x6f, 0x82, 0xac, 0xbb, 0xb8, 0x76, 0x22,
- 0x05, 0xd8, 0xfd, 0x34, 0xc6, 0xfa, 0x4d, 0xd8, 0xfb, 0xb6, 0x98, 0x65,
- 0x3e, 0xa1, 0xc6, 0x7d, 0xa7, 0xce, 0xc7, 0x56, 0x75, 0x4e, 0x1e, 0xdf,
- 0x53, 0xe7, 0xb6, 0xab, 0x73, 0xea, 0xba, 0x53, 0x66, 0xd4, 0xb8, 0x4d,
- 0x09, 0x3c, 0x26, 0xf0, 0x2a, 0xf2, 0x59, 0x23, 0x11, 0x05, 0x3d, 0x1d,
- 0xe3, 0x53, 0x5f, 0x31, 0xf0, 0x20, 0xd0, 0x6f, 0xb7, 0xf2, 0x45, 0xbb,
- 0xa0, 0xf7, 0x65, 0xe7, 0xfe, 0x74, 0x95, 0x69, 0xd1, 0xd5, 0x9e, 0x35,
- 0xba, 0xea, 0x90, 0xe1, 0x98, 0xaf, 0xa3, 0xcd, 0x92, 0x8c, 0x51, 0x67,
- 0xf7, 0xa3, 0xab, 0x7f, 0xaa, 0xff, 0xfd, 0xe8, 0xea, 0xb7, 0xee, 0xa1,
- 0xab, 0x7f, 0xb5, 0x4e, 0x57, 0x96, 0xf9, 0x82, 0x46, 0xda, 0x8c, 0x1f,
- 0xf4, 0x47, 0xcd, 0x8f, 0x4e, 0x31, 0x7f, 0xa8, 0x73, 0x4d, 0xfb, 0x79,
- 0x07, 0xd7, 0xf3, 0xa5, 0xa6, 0x61, 0x59, 0x90, 0x1d, 0xd7, 0x34, 0xe5,
- 0x16, 0x35, 0x3f, 0x4f, 0xfe, 0x11, 0x3b, 0xa6, 0x10, 0x6b, 0x5c, 0x1e,
- 0xda, 0xa5, 0xbc, 0xc5, 0xed, 0x3f, 0x55, 0x6a, 0xfe, 0x42, 0x4f, 0xbc,
- 0xdd, 0x4c, 0x8e, 0x58, 0x5e, 0x1c, 0x08, 0xca, 0xd7, 0xaa, 0xd1, 0xac,
- 0xad, 0x75, 0x4b, 0xfe, 0x41, 0xc4, 0x9e, 0x12, 0xfd, 0xd7, 0xd6, 0x7b,
- 0xc4, 0xe8, 0x3e, 0x2f, 0x46, 0x57, 0xc1, 0x2b, 0xf3, 0xab, 0xef, 0xbe,
- 0xd5, 0x08, 0xf1, 0x3b, 0x66, 0xee, 0x93, 0x2f, 0x73, 0x8e, 0x88, 0xf7,
- 0x8c, 0xfb, 0x16, 0x73, 0x9e, 0x7c, 0x20, 0xd1, 0x25, 0xf9, 0x2d, 0x5c,
- 0x8f, 0xf4, 0x73, 0xf4, 0x5d, 0xed, 0x1e, 0xdf, 0x7e, 0x8e, 0xa4, 0x78,
- 0x33, 0x30, 0x65, 0xf4, 0x41, 0x3e, 0x54, 0xe2, 0x3c, 0xde, 0xf2, 0xec,
- 0x89, 0xb9, 0x82, 0xb4, 0xb9, 0xbe, 0x61, 0x2f, 0x72, 0x01, 0xda, 0x81,
- 0xaf, 0x73, 0xea, 0x9b, 0x39, 0x82, 0x44, 0x74, 0x8b, 0x39, 0x82, 0x98,
- 0x46, 0x62, 0x9f, 0x66, 0x43, 0xf7, 0x36, 0x74, 0x6f, 0x43, 0xf7, 0x36,
- 0x74, 0x9f, 0xac, 0x1f, 0xc6, 0x3d, 0x95, 0x87, 0x80, 0x17, 0x97, 0x7e,
- 0xda, 0xa5, 0x0f, 0x3e, 0xb7, 0x4a, 0x4e, 0xe9, 0x84, 0xf3, 0x45, 0xae,
- 0xa1, 0xfc, 0xf5, 0xb8, 0xe6, 0xfa, 0x6b, 0xd2, 0xcb, 0xe0, 0xf9, 0xdb,
- 0x98, 0xa7, 0xad, 0xeb, 0xd6, 0x5d, 0x99, 0xcc, 0xb5, 0xc8, 0x64, 0xd6,
- 0xa1, 0x8c, 0xd8, 0x9f, 0x3e, 0x77, 0x5a, 0xaf, 0xac, 0xca, 0x65, 0x2f,
- 0x78, 0xe8, 0xe0, 0xdc, 0xbd, 0x79, 0x90, 0x7e, 0xaf, 0x47, 0xff, 0x6f,
- 0xd1, 0x87, 0xfe, 0x75, 0xa3, 0x71, 0x39, 0x26, 0x73, 0xc6, 0x77, 0x9b,
- 0x0f, 0x72, 0x66, 0xac, 0x81, 0xef, 0x21, 0x96, 0x5f, 0x44, 0x2c, 0x59,
- 0x31, 0x22, 0xf2, 0x93, 0x47, 0xaf, 0x21, 0x97, 0x96, 0xfc, 0xc3, 0x89,
- 0x66, 0x24, 0x90, 0x78, 0xab, 0x39, 0x37, 0x82, 0x18, 0x97, 0x88, 0x86,
- 0x93, 0xc6, 0xb0, 0x5c, 0xaa, 0x0f, 0xca, 0x8f, 0xea, 0x96, 0xfc, 0xb0,
- 0x1e, 0x91, 0x1f, 0x20, 0xe6, 0x7f, 0xbf, 0xde, 0x9a, 0x73, 0x47, 0x68,
- 0x4f, 0x3d, 0xe9, 0xfa, 0x46, 0xb9, 0x7f, 0x13, 0x34, 0xde, 0x82, 0x9d,
- 0x04, 0xb2, 0xc8, 0xf5, 0x19, 0xbf, 0x26, 0x0e, 0x15, 0x9f, 0x6b, 0x82,
- 0xb7, 0x6c, 0x5b, 0xc2, 0xca, 0xeb, 0x7a, 0xf7, 0xa8, 0xf9, 0x29, 0xb4,
- 0x39, 0xa3, 0x81, 0x6a, 0xb1, 0x53, 0xe5, 0x8b, 0xd0, 0x91, 0xd8, 0xf5,
- 0x60, 0xb0, 0x56, 0xbc, 0x85, 0x7e, 0xcd, 0xe6, 0xa1, 0xf8, 0x6f, 0xed,
- 0x30, 0xff, 0x81, 0x85, 0x35, 0xdd, 0xf9, 0x25, 0x23, 0xb1, 0x49, 0x66,
- 0x43, 0xdf, 0x6f, 0x98, 0x03, 0x7d, 0x59, 0x3d, 0x11, 0x94, 0x74, 0x91,
- 0x6b, 0x2a, 0x24, 0xb3, 0x55, 0x28, 0xff, 0x3c, 0xd7, 0x85, 0x3c, 0x3b,
- 0x17, 0xef, 0x86, 0xed, 0xff, 0x9a, 0xe1, 0xae, 0x03, 0x18, 0x50, 0x75,
- 0x50, 0xf2, 0xe0, 0x37, 0x5f, 0x7f, 0xcb, 0xc3, 0x0e, 0xf0, 0x2a, 0x5b,
- 0x21, 0xf8, 0xc4, 0x70, 0xda, 0x76, 0xfe, 0x30, 0x88, 0xb6, 0xe0, 0x56,
- 0xeb, 0xce, 0x26, 0x7c, 0x3f, 0x10, 0xb2, 0x88, 0x4d, 0x24, 0xf3, 0x05,
- 0x7c, 0xff, 0x4a, 0x42, 0x36, 0xf7, 0xe2, 0x7b, 0x4b, 0x02, 0x26, 0x99,
- 0x60, 0xcc, 0xd5, 0x5a, 0x62, 0xae, 0x68, 0x69, 0xc8, 0x6e, 0x0e, 0x73,
- 0x4f, 0x43, 0x9e, 0x5f, 0xac, 0x07, 0xb5, 0xd4, 0xe9, 0x47, 0xc0, 0x87,
- 0x9f, 0x3b, 0x23, 0x3f, 0x33, 0x97, 0xb7, 0x04, 0xe4, 0x16, 0x7c, 0x5c,
- 0x12, 0x7e, 0xcc, 0x46, 0x6e, 0xb1, 0x03, 0xcb, 0x35, 0xfa, 0x5f, 0xbf,
- 0x20, 0x5f, 0xf3, 0x78, 0x6b, 0x93, 0x05, 0x65, 0xa3, 0x6c, 0xcf, 0x67,
- 0xfe, 0xcd, 0xc0, 0xdd, 0xf6, 0x17, 0x57, 0xdb, 0xcb, 0x99, 0x7f, 0xb8,
- 0xda, 0xde, 0xdb, 0xe6, 0xf2, 0x3f, 0xaa, 0x4d, 0xd4, 0xf7, 0x78, 0x6d,
- 0xb7, 0xa1, 0xb3, 0x66, 0x93, 0xb9, 0x45, 0x01, 0xd8, 0x24, 0x1d, 0xa7,
- 0x2f, 0xbe, 0x1f, 0x5f, 0xbb, 0xc6, 0xcf, 0x9a, 0x49, 0x83, 0xb6, 0x10,
- 0x14, 0x97, 0x26, 0xef, 0x77, 0x20, 0x7f, 0xbf, 0x8d, 0xdf, 0x8c, 0xa3,
- 0x7e, 0x6e, 0xce, 0x3e, 0x7c, 0xfe, 0xcd, 0x7b, 0xd8, 0x4b, 0x08, 0xf6,
- 0xf2, 0xff, 0xab, 0x5d, 0x5c, 0xba, 0x1f, 0xbb, 0xc0, 0x9f, 0xb2, 0x0b,
- 0xd5, 0xff, 0xd2, 0xea, 0x5a, 0x09, 0x43, 0x3e, 0x8c, 0x07, 0x83, 0xd0,
- 0xf1, 0x66, 0x99, 0xb5, 0xc8, 0x8f, 0x15, 0xc9, 0xc1, 0x5f, 0x9e, 0x58,
- 0x17, 0xbb, 0xbb, 0x10, 0x0f, 0x8e, 0x9f, 0x8e, 0x8e, 0x32, 0x1e, 0xc4,
- 0xe0, 0x1b, 0x93, 0xef, 0x88, 0x07, 0x37, 0x8c, 0xd6, 0x78, 0x60, 0x20,
- 0x1e, 0xec, 0x7a, 0x97, 0x78, 0x70, 0xe2, 0x1d, 0xf1, 0x40, 0x83, 0x6c,
- 0x38, 0xbf, 0xbf, 0x35, 0xfc, 0x78, 0x50, 0x58, 0x13, 0x0f, 0x7c, 0x5d,
- 0x59, 0x0a, 0x0b, 0xdc, 0xd5, 0x5b, 0x97, 0xa7, 0x2b, 0x09, 0x06, 0x12,
- 0x8d, 0xcc, 0x9c, 0xf5, 0xb0, 0xb4, 0xc1, 0xe7, 0x5e, 0xaa, 0x8f, 0x40,
- 0x67, 0x97, 0x30, 0xf7, 0x68, 0x9c, 0x89, 0x65, 0x5b, 0x82, 0xeb, 0xe1,
- 0xcd, 0x08, 0x30, 0xe2, 0x6e, 0xe0, 0xbe, 0xdd, 0x67, 0xd5, 0xfa, 0x78,
- 0x33, 0xea, 0x61, 0xf7, 0x6d, 0xc0, 0xee, 0x78, 0x3e, 0x00, 0x4c, 0xc8,
- 0xf6, 0x2b, 0x66, 0x12, 0x7a, 0xaa, 0x3a, 0xf6, 0xee, 0x02, 0x3e, 0x73,
- 0xaa, 0xef, 0xad, 0x08, 0xfb, 0x76, 0x24, 0x12, 0xd1, 0x3f, 0xc3, 0x77,
- 0x7b, 0x22, 0xbc, 0xed, 0xaa, 0x45, 0xba, 0x87, 0xa2, 0x67, 0x15, 0x8d,
- 0x80, 0x14, 0xd4, 0xb3, 0x91, 0x6d, 0x7c, 0xf6, 0x18, 0x62, 0xf6, 0x51,
- 0xc7, 0x94, 0x23, 0x4e, 0x76, 0x77, 0x0e, 0x1f, 0x62, 0xd5, 0x4b, 0x25,
- 0xde, 0x1f, 0xc5, 0xfd, 0x80, 0x30, 0x97, 0xfc, 0x2a, 0xfa, 0x1c, 0x44,
- 0x9f, 0x19, 0xc7, 0xd7, 0x05, 0xef, 0x37, 0x32, 0x29, 0xdc, 0x9f, 0x29,
- 0x36, 0x32, 0xe9, 0x22, 0xf3, 0xd6, 0xa1, 0xf0, 0x11, 0xc8, 0x33, 0x8b,
- 0x5c, 0xcd, 0x96, 0xe8, 0x60, 0x5e, 0x9e, 0xee, 0x1c, 0x07, 0x4e, 0x3a,
- 0x87, 0x1c, 0xc2, 0x9e, 0x8c, 0xc6, 0xcb, 0xf2, 0xe1, 0xce, 0xe4, 0x69,
- 0xe4, 0x0b, 0xf1, 0xed, 0x90, 0x61, 0x23, 0xa3, 0xc7, 0x04, 0xb6, 0x1e,
- 0x87, 0x5f, 0x1e, 0xd1, 0x53, 0xc5, 0x7e, 0x73, 0x56, 0x1e, 0x95, 0x86,
- 0x19, 0x0d, 0x8f, 0xcb, 0x26, 0x49, 0x05, 0xd0, 0x6f, 0xf0, 0x43, 0x92,
- 0x0d, 0x53, 0xd6, 0x0f, 0xc2, 0xdf, 0x6b, 0xd2, 0x61, 0xb5, 0xc6, 0x9e,
- 0x5b, 0x10, 0x6f, 0x2e, 0x40, 0x9f, 0xdd, 0x61, 0x75, 0x7a, 0x3a, 0xd9,
- 0x24, 0xcb, 0xef, 0xe8, 0x77, 0xbb, 0xa5, 0x5f, 0x6b, 0xfb, 0xdb, 0x68,
- 0xdf, 0x84, 0x9c, 0xb3, 0x91, 0x09, 0xc4, 0x20, 0x7f, 0xcc, 0xa1, 0x0d,
- 0x76, 0x72, 0x15, 0xf3, 0x61, 0x1c, 0x2c, 0x94, 0x99, 0xf7, 0x18, 0x52,
- 0x36, 0x71, 0xcf, 0x69, 0x36, 0x2b, 0x16, 0xf8, 0xbd, 0x40, 0x9e, 0x83,
- 0x32, 0xee, 0x0c, 0x88, 0x5d, 0xa3, 0x1c, 0xa2, 0xf0, 0x4a, 0x0f, 0x77,
- 0xa5, 0x16, 0xa3, 0x76, 0x1e, 0x14, 0x8d, 0x0b, 0x7d, 0x5d, 0x49, 0xe4,
- 0x39, 0xfa, 0x85, 0x48, 0x57, 0x0a, 0x36, 0x6b, 0x5c, 0x78, 0xa8, 0x2b,
- 0x7d, 0x9a, 0x7c, 0x19, 0xc8, 0x73, 0x3e, 0x0a, 0x9c, 0xdf, 0x94, 0xdf,
- 0x45, 0x2e, 0x5b, 0x18, 0x44, 0x0e, 0x80, 0xd5, 0xaf, 0x83, 0xef, 0xbc,
- 0x29, 0xc1, 0xae, 0xc4, 0xab, 0xe0, 0x6f, 0x18, 0xb2, 0xd9, 0x84, 0x3e,
- 0x06, 0xda, 0x07, 0x58, 0x13, 0x68, 0x69, 0xb7, 0xba, 0x10, 0x4f, 0x11,
- 0xbb, 0x24, 0x98, 0x1c, 0xe9, 0x06, 0xfd, 0x2b, 0x01, 0xe6, 0x82, 0xc1,
- 0xd8, 0x6a, 0xfb, 0x37, 0xdd, 0xf6, 0x41, 0xf0, 0xc2, 0xe7, 0x88, 0x09,
- 0x24, 0x38, 0x35, 0x62, 0x82, 0x07, 0xf6, 0x0d, 0xa9, 0xbe, 0xe9, 0x45,
- 0xda, 0x40, 0x23, 0x53, 0xb1, 0x1e, 0x91, 0xd4, 0xc2, 0x56, 0x19, 0x5f,
- 0xe8, 0x95, 0x5d, 0x0b, 0xc4, 0x30, 0xac, 0x69, 0x60, 0x2a, 0xc0, 0x18,
- 0xfa, 0x05, 0xe6, 0x76, 0xd1, 0xf0, 0x41, 0xe9, 0x0f, 0x7f, 0x15, 0xeb,
- 0x60, 0xca, 0x8a, 0x45, 0x66, 0xb1, 0xc6, 0x02, 0x8a, 0x4e, 0xd8, 0x1f,
- 0x93, 0x36, 0xba, 0x66, 0xdc, 0xf4, 0xe2, 0xbd, 0xe8, 0x62, 0xe1, 0x5c,
- 0x08, 0xaf, 0xa3, 0xfb, 0x57, 0x1e, 0x5d, 0x13, 0x74, 0xfb, 0x40, 0x93,
- 0x73, 0x7c, 0xa8, 0x73, 0xec, 0xb4, 0xd8, 0x1d, 0xe0, 0x2f, 0x1d, 0x7b,
- 0x58, 0x66, 0x41, 0xe7, 0xe8, 0x02, 0xfd, 0xa4, 0x6c, 0xc5, 0x67, 0xb8,
- 0x4d, 0x62, 0x83, 0xe7, 0x81, 0x73, 0xc6, 0x14, 0x0d, 0x17, 0x73, 0xe8,
- 0x17, 0x12, 0xc0, 0xa9, 0x1f, 0x07, 0x3f, 0xcc, 0xb1, 0x38, 0xe7, 0x00,
- 0xe6, 0x9b, 0xc0, 0x3a, 0x64, 0x7d, 0x85, 0xeb, 0x1b, 0xbf, 0xcf, 0x87,
- 0x3b, 0x53, 0xa7, 0xdb, 0xb1, 0xee, 0xe4, 0x11, 0x43, 0xc5, 0x7e, 0xea,
- 0xc5, 0xea, 0x4c, 0x96, 0x14, 0xdf, 0x9d, 0xa9, 0x12, 0x65, 0x14, 0xef,
- 0x4c, 0x97, 0x28, 0x23, 0x01, 0x3f, 0x71, 0xd8, 0x64, 0x40, 0x22, 0x5b,
- 0xa8, 0xc7, 0x43, 0xe8, 0xf7, 0x57, 0x01, 0xe2, 0xb8, 0xa4, 0xc5, 0xdf,
- 0xf0, 0xb5, 0x17, 0x0e, 0xa3, 0x2f, 0x7f, 0x6f, 0x07, 0xdd, 0xfe, 0xc1,
- 0x82, 0xb4, 0x0f, 0xce, 0xc0, 0x4f, 0xe8, 0x23, 0xc0, 0x91, 0xca, 0xce,
- 0x9b, 0xc0, 0xd8, 0x3b, 0x30, 0x1f, 0xac, 0x8d, 0x98, 0x25, 0xd3, 0xf3,
- 0x94, 0xab, 0x7c, 0x08, 0x73, 0xc0, 0xfc, 0x63, 0xf0, 0x2d, 0x9c, 0x03,
- 0xc7, 0x16, 0xe4, 0x36, 0x4b, 0x92, 0x9b, 0x0f, 0x2a, 0x2c, 0x6b, 0x9b,
- 0x1c, 0x5f, 0xd3, 0xf4, 0x44, 0x17, 0x74, 0xcc, 0xb9, 0xcd, 0x81, 0xb7,
- 0x67, 0x10, 0xff, 0xa2, 0x0a, 0x43, 0x19, 0x17, 0xb8, 0x56, 0x46, 0xb1,
- 0x4e, 0xc8, 0xbf, 0x67, 0x7b, 0x5a, 0x03, 0x3e, 0x45, 0xf9, 0x7f, 0xe4,
- 0xea, 0x09, 0xf8, 0x91, 0x51, 0xf9, 0x7d, 0xf8, 0x92, 0x1f, 0xd7, 0xe3,
- 0xc8, 0x1b, 0x86, 0x91, 0x37, 0x0c, 0x22, 0x6f, 0xb0, 0x90, 0x37, 0x44,
- 0x90, 0x37, 0xf4, 0x21, 0x6f, 0x08, 0x23, 0x3e, 0x88, 0x1c, 0xad, 0xe7,
- 0x61, 0x63, 0x0d, 0xf8, 0x41, 0x33, 0x68, 0xd7, 0x43, 0xc1, 0x64, 0x3d,
- 0x1c, 0x4c, 0xd5, 0x03, 0x98, 0xd3, 0x01, 0x8e, 0x89, 0xf9, 0xe5, 0x3b,
- 0xc7, 0x4a, 0xc3, 0x88, 0x39, 0x36, 0xfc, 0x52, 0x1a, 0xf1, 0x36, 0x2e,
- 0x47, 0xf0, 0xcc, 0xf2, 0x7c, 0x04, 0xcf, 0x34, 0x25, 0x1d, 0x6f, 0x93,
- 0x59, 0x33, 0x0e, 0x1a, 0x5b, 0x94, 0x9d, 0x22, 0xdf, 0x6a, 0x83, 0x9d,
- 0x4a, 0xae, 0xc8, 0x7c, 0xab, 0x0f, 0xf4, 0x3a, 0x11, 0x97, 0xe9, 0x1f,
- 0xe8, 0x0b, 0xec, 0xdd, 0x5f, 0xb2, 0xb8, 0xe6, 0xba, 0xb4, 0xe4, 0xe9,
- 0xbc, 0x10, 0x6b, 0x22, 0x0e, 0xc2, 0x2e, 0xd8, 0x36, 0x81, 0xe7, 0xf8,
- 0xfb, 0x6d, 0xcf, 0xef, 0x7f, 0x24, 0x28, 0x30, 0xde, 0x4b, 0x8c, 0xf9,
- 0x16, 0xe8, 0x39, 0xad, 0xeb, 0xb5, 0xa6, 0x8b, 0xe5, 0xdf, 0x67, 0xfd,
- 0x8d, 0x35, 0xc7, 0xd7, 0xc0, 0x73, 0xbf, 0xb9, 0x8c, 0x1c, 0xd9, 0xde,
- 0xbf, 0x82, 0xdf, 0xad, 0xfd, 0xeb, 0xe8, 0xaf, 0xda, 0x82, 0x66, 0x22,
- 0xce, 0x7c, 0x18, 0x3e, 0x73, 0x10, 0xfe, 0xf1, 0x56, 0x46, 0x5f, 0xba,
- 0x89, 0x79, 0x42, 0x9e, 0xc5, 0x5b, 0x99, 0xc0, 0xc0, 0xb5, 0xe6, 0x8b,
- 0xc0, 0x37, 0x63, 0x4b, 0x23, 0x92, 0x5a, 0xea, 0x0f, 0x5f, 0x96, 0xce,
- 0xdb, 0xb6, 0x5c, 0x6b, 0xce, 0x3a, 0xd1, 0xe3, 0xb6, 0x10, 0x6f, 0x99,
- 0x52, 0x01, 0xa9, 0x6d, 0x3b, 0x3b, 0x88, 0x19, 0x2f, 0x8a, 0x1e, 0x91,
- 0xe4, 0x29, 0x5b, 0x46, 0x76, 0xfa, 0xb9, 0xfb, 0x9d, 0x0e, 0xe9, 0x42,
- 0xdb, 0x52, 0x04, 0x7d, 0x88, 0x53, 0x39, 0xef, 0x2c, 0xe6, 0xac, 0xb9,
- 0xcf, 0x78, 0xf5, 0xc9, 0x42, 0x09, 0x73, 0xaf, 0xdf, 0xca, 0x5c, 0x3e,
- 0x05, 0xec, 0x0e, 0x1d, 0x25, 0x4f, 0xb1, 0xae, 0xb0, 0x09, 0x72, 0x1a,
- 0x83, 0xad, 0xd0, 0x06, 0xfa, 0xf1, 0x6c, 0x53, 0xbe, 0x11, 0xa7, 0x5d,
- 0xbc, 0x04, 0x59, 0x82, 0x56, 0xc0, 0x9f, 0x0f, 0x70, 0xde, 0x3c, 0xe5,
- 0x17, 0x46, 0x6e, 0xce, 0xb1, 0x25, 0xd8, 0x99, 0x58, 0x9f, 0x77, 0xdf,
- 0xca, 0x2c, 0x9f, 0x02, 0xfd, 0x01, 0xd6, 0xde, 0xe0, 0xb3, 0x8b, 0xac,
- 0x1d, 0x32, 0x27, 0xdd, 0x05, 0x3d, 0xed, 0x55, 0xb5, 0xb8, 0x64, 0x35,
- 0x2e, 0xd6, 0x49, 0xfa, 0x2c, 0x89, 0x18, 0xd6, 0x7e, 0xe4, 0xaf, 0x62,
- 0xea, 0x89, 0x49, 0xdc, 0xa3, 0x3c, 0x35, 0xe4, 0x1c, 0xb8, 0x7f, 0x61,
- 0x45, 0xe9, 0xc4, 0x80, 0xee, 0x72, 0x3b, 0x99, 0x84, 0xc9, 0xbc, 0x91,
- 0x80, 0x2f, 0x1c, 0xe1, 0x1c, 0xd4, 0xd8, 0xc8, 0xc7, 0xb9, 0xfe, 0x30,
- 0x67, 0xd8, 0x55, 0x4b, 0x5e, 0xae, 0xfe, 0x66, 0x4b, 0x47, 0x60, 0xd3,
- 0x92, 0x6f, 0x43, 0x3e, 0x90, 0x1c, 0xc1, 0x6f, 0x38, 0x81, 0xa3, 0xd0,
- 0xe7, 0xd9, 0x11, 0xd6, 0x3f, 0x5f, 0x02, 0xb6, 0x27, 0xdf, 0xb1, 0xc8,
- 0x11, 0xb5, 0x86, 0x71, 0xed, 0x30, 0x97, 0xdb, 0x24, 0x97, 0xd5, 0xfc,
- 0x1e, 0x22, 0xf6, 0x80, 0x9e, 0xee, 0x67, 0x7e, 0xe3, 0xf7, 0x39, 0x3f,
- 0x97, 0x3e, 0x63, 0x57, 0xd2, 0x8a, 0x48, 0xaa, 0x78, 0xa9, 0x19, 0xb0,
- 0x2c, 0x60, 0x67, 0x57, 0x8f, 0x29, 0x27, 0x08, 0x3e, 0x58, 0x6b, 0xdb,
- 0xa9, 0x74, 0x09, 0x3e, 0x68, 0x3b, 0xf9, 0x60, 0x62, 0xb3, 0x9c, 0x9b,
- 0xef, 0x91, 0xca, 0xfc, 0xcf, 0xa5, 0x3a, 0xdf, 0x25, 0xe7, 0xe7, 0x9b,
- 0x72, 0x35, 0xae, 0x7c, 0x93, 0xd5, 0xae, 0xd6, 0xb5, 0x3c, 0xec, 0xd6,
- 0x61, 0x62, 0xa3, 0xd7, 0xe5, 0x79, 0x39, 0x57, 0x76, 0x79, 0xcf, 0xb4,
- 0xf0, 0x7e, 0x15, 0xb6, 0xf6, 0xaa, 0x45, 0xfe, 0x47, 0xa4, 0x52, 0x24,
- 0xef, 0xfb, 0x14, 0xef, 0xbb, 0x56, 0x79, 0x97, 0xac, 0x61, 0x91, 0xff,
- 0x8d, 0x78, 0xef, 0x90, 0xec, 0x56, 0xf2, 0x1f, 0xc1, 0xb3, 0xef, 0xb4,
- 0xbf, 0x8a, 0x73, 0xad, 0xb9, 0x5c, 0x6c, 0x53, 0x3c, 0x1b, 0x89, 0x11,
- 0xc8, 0xe7, 0x5a, 0xb3, 0xe1, 0x70, 0x1d, 0xe1, 0xb7, 0xf3, 0x2f, 0xe0,
- 0xab, 0x7a, 0x55, 0xce, 0x92, 0x9b, 0xec, 0xee, 0x4c, 0x2e, 0x8e, 0x42,
- 0xb7, 0x9d, 0x6a, 0x1d, 0xc2, 0x6d, 0x40, 0x67, 0xff, 0x1e, 0xfd, 0xbf,
- 0xcd, 0xf5, 0xa6, 0xe4, 0x92, 0x86, 0x5c, 0x0a, 0xc5, 0xf1, 0x76, 0xe0,
- 0x27, 0x8c, 0xd3, 0xc8, 0x64, 0x1d, 0x3e, 0xd3, 0x07, 0xdf, 0xc6, 0xef,
- 0xf7, 0x6d, 0x0f, 0x79, 0xf8, 0x5c, 0xe8, 0x1c, 0x79, 0x05, 0xd7, 0xf3,
- 0x48, 0x03, 0x31, 0x36, 0x36, 0x58, 0x51, 0xfb, 0x10, 0x71, 0x85, 0x85,
- 0x67, 0x9d, 0x6f, 0xe3, 0xe3, 0x8e, 0x37, 0x56, 0xe7, 0x98, 0x6b, 0xe7,
- 0x54, 0x70, 0x1a, 0xc8, 0xdf, 0x2d, 0xd0, 0xe5, 0xb8, 0x79, 0x31, 0x12,
- 0x06, 0xc6, 0x65, 0x5b, 0x37, 0x7c, 0x4c, 0x04, 0x3e, 0x6b, 0x18, 0xbe,
- 0x9f, 0x6b, 0x99, 0x7e, 0xde, 0xe7, 0x7d, 0x18, 0x34, 0xe9, 0x7f, 0x87,
- 0x31, 0x67, 0xe6, 0xd8, 0xf4, 0x9f, 0x88, 0x27, 0xb5, 0x70, 0x57, 0xf2,
- 0xb4, 0x5b, 0x1b, 0x74, 0x7f, 0xf3, 0xbe, 0x04, 0x1f, 0x49, 0x44, 0xcb,
- 0x79, 0xe4, 0x7e, 0x29, 0xac, 0xd1, 0xa4, 0x85, 0x3c, 0xbb, 0x16, 0x7d,
- 0x85, 0x98, 0x5b, 0xa7, 0x0c, 0x96, 0x28, 0x27, 0xd6, 0xa9, 0x4c, 0xc9,
- 0x57, 0xbe, 0x0b, 0x79, 0x04, 0x65, 0x8b, 0x95, 0x85, 0x4f, 0x01, 0xff,
- 0x98, 0xfb, 0x5c, 0x89, 0xb5, 0xc8, 0x7e, 0xc4, 0x31, 0x03, 0x42, 0x40,
- 0x4e, 0xb5, 0x64, 0xc8, 0x67, 0x03, 0x43, 0xc8, 0x01, 0x9f, 0x45, 0xdf,
- 0x80, 0xe4, 0x97, 0x18, 0x0f, 0x02, 0x32, 0xb7, 0x24, 0x72, 0xfd, 0x14,
- 0xfd, 0x8a, 0xfa, 0x83, 0xcc, 0x1b, 0x99, 0x69, 0x62, 0xed, 0x79, 0xfa,
- 0x18, 0xfa, 0x89, 0x07, 0xa1, 0x8b, 0xd8, 0x4b, 0xdf, 0x40, 0x6c, 0x9a,
- 0x2d, 0xf6, 0xc3, 0x67, 0x4a, 0x43, 0x87, 0x4c, 0x11, 0xd3, 0x98, 0xa3,
- 0x6f, 0x50, 0x77, 0xf4, 0x6b, 0x8e, 0x41, 0x29, 0x9c, 0x62, 0xbd, 0x31,
- 0x08, 0x5e, 0x98, 0xb7, 0x1a, 0x2a, 0x0f, 0x7a, 0x50, 0xf9, 0x56, 0x7e,
- 0x07, 0x5a, 0xc6, 0x8d, 0x1d, 0xdf, 0xa6, 0xd3, 0x8f, 0x3d, 0x22, 0xf6,
- 0xc4, 0xa1, 0xce, 0x5d, 0xa5, 0x76, 0x29, 0xf7, 0xd2, 0x2e, 0xa9, 0xff,
- 0xac, 0x4e, 0x5f, 0x8b, 0x3c, 0x0c, 0xf4, 0x58, 0x23, 0x08, 0xa0, 0x5f,
- 0xc8, 0xeb, 0x47, 0xb9, 0xfe, 0xb6, 0x4c, 0xed, 0xfc, 0x3b, 0xf0, 0xe5,
- 0xfa, 0xb5, 0xdc, 0x4e, 0xf8, 0xdb, 0x09, 0x5d, 0x1e, 0xfb, 0x54, 0x1a,
- 0xcf, 0x32, 0x16, 0xde, 0xf2, 0xf0, 0x38, 0xdb, 0x58, 0xa3, 0x45, 0x9e,
- 0x7e, 0xce, 0xc4, 0x77, 0xaf, 0xe4, 0xcf, 0x05, 0x21, 0x07, 0xe4, 0xc4,
- 0x15, 0x97, 0x16, 0xf3, 0xde, 0xe3, 0xd0, 0x91, 0x7e, 0x32, 0x28, 0x6d,
- 0x27, 0x7b, 0x25, 0xf0, 0xad, 0x2e, 0x69, 0xff, 0xd6, 0x80, 0x18, 0xdf,
- 0x62, 0x2d, 0x29, 0x1a, 0x39, 0xaa, 0xea, 0x58, 0x69, 0x39, 0x86, 0xf8,
- 0xa5, 0x23, 0x16, 0x2b, 0x3b, 0x35, 0xb7, 0x8a, 0x81, 0xc4, 0x55, 0x7f,
- 0xc1, 0x96, 0xaf, 0xef, 0xfc, 0x85, 0xaa, 0xa3, 0x26, 0x47, 0x70, 0xfd,
- 0x72, 0x06, 0xd8, 0x44, 0x83, 0xad, 0x34, 0x32, 0xd7, 0x1e, 0xf5, 0x73,
- 0xcb, 0x41, 0x55, 0x93, 0xff, 0xfa, 0x4e, 0x37, 0xb7, 0x9c, 0x45, 0x6e,
- 0x99, 0x56, 0xb9, 0x25, 0xfc, 0x6b, 0x80, 0xfd, 0xb6, 0x8a, 0x8e, 0xb1,
- 0x72, 0xc2, 0x5c, 0xfd, 0xa3, 0x62, 0x1f, 0xc0, 0xba, 0x38, 0x23, 0xf3,
- 0x7a, 0x42, 0x53, 0x34, 0x8d, 0x17, 0xe8, 0xa7, 0xe8, 0xbf, 0x68, 0xe3,
- 0xac, 0x69, 0xa1, 0xed, 0x65, 0xfa, 0x28, 0xd7, 0xb6, 0xc7, 0x5a, 0x7c,
- 0xdd, 0x5c, 0xa9, 0x0e, 0x1d, 0x22, 0xa7, 0xb7, 0xda, 0x30, 0x7f, 0xc4,
- 0x74, 0x8b, 0xd7, 0x9c, 0x3f, 0x7c, 0x67, 0x28, 0xa4, 0xae, 0x0b, 0x65,
- 0xb7, 0x86, 0xe1, 0xd2, 0x67, 0xfe, 0x01, 0x1f, 0x53, 0x27, 0x1f, 0x1c,
- 0xb7, 0x4f, 0x8c, 0x33, 0x21, 0x09, 0x9c, 0xa1, 0xfd, 0x45, 0x23, 0x69,
- 0xc8, 0x6f, 0xce, 0x22, 0x06, 0x3c, 0x04, 0x6c, 0xf4, 0x88, 0xe8, 0xe7,
- 0x06, 0xb1, 0x76, 0xa2, 0xe1, 0xb2, 0xc4, 0xc4, 0xa8, 0x04, 0xe5, 0x8d,
- 0x53, 0xd1, 0x08, 0xed, 0xe5, 0x2c, 0xe2, 0xd5, 0x91, 0x7a, 0xe7, 0xed,
- 0x86, 0xe2, 0x82, 0x6d, 0xdf, 0x08, 0x00, 0x3b, 0x0c, 0xda, 0x7a, 0xb7,
- 0xdc, 0x80, 0xbe, 0xb3, 0xaa, 0xed, 0x11, 0xd0, 0x05, 0x0f, 0x67, 0x58,
- 0x1b, 0x24, 0xdd, 0xa3, 0xa0, 0x49, 0xda, 0x8d, 0xcc, 0x32, 0x73, 0xd3,
- 0x53, 0xb4, 0xdd, 0x5e, 0xd8, 0x1d, 0xae, 0xeb, 0xed, 0x92, 0x9d, 0x8c,
- 0x88, 0x7e, 0x6a, 0x8f, 0xf4, 0xef, 0xd4, 0xdd, 0xf9, 0xa8, 0x39, 0xb2,
- 0x8d, 0x35, 0xe7, 0x11, 0xb5, 0x1e, 0xf5, 0x25, 0xd8, 0xcc, 0x3e, 0xea,
- 0x18, 0xb1, 0x1f, 0x71, 0x8c, 0x7e, 0xcc, 0x40, 0x1c, 0x4b, 0xd5, 0x5d,
- 0xbd, 0x97, 0xf7, 0x6d, 0x95, 0x63, 0x67, 0x68, 0x4f, 0xb8, 0xb7, 0x6a,
- 0x53, 0xfe, 0xde, 0x10, 0xef, 0x59, 0x72, 0xfc, 0x45, 0xe6, 0x1e, 0xcc,
- 0x39, 0x98, 0x67, 0x45, 0xc3, 0xbb, 0x30, 0x1f, 0xfd, 0x31, 0xfa, 0x03,
- 0x5d, 0xd9, 0x6e, 0x0e, 0x3e, 0xba, 0x50, 0xa7, 0xde, 0x86, 0xb9, 0x7f,
- 0x66, 0x32, 0x5f, 0xb3, 0xc3, 0xae, 0xbc, 0x0b, 0x68, 0x9b, 0x85, 0xef,
- 0x4f, 0x39, 0x6d, 0xb2, 0x32, 0x69, 0x43, 0xf7, 0x5f, 0x02, 0x5f, 0x07,
- 0x3a, 0x59, 0x23, 0x58, 0x99, 0x4c, 0xe3, 0xfa, 0x80, 0xca, 0xd1, 0x8c,
- 0xc7, 0x6c, 0xd0, 0xd8, 0xca, 0x75, 0xe4, 0xe9, 0x29, 0xae, 0x17, 0xe6,
- 0x1f, 0xd3, 0x67, 0xe1, 0xb3, 0xc7, 0xe3, 0x8c, 0xf1, 0xdc, 0x4b, 0xe8,
- 0x00, 0x1f, 0xdd, 0x0a, 0x57, 0xe8, 0xd6, 0x4e, 0xbd, 0x50, 0xa6, 0x9f,
- 0xcf, 0x87, 0xdb, 0x85, 0x78, 0xc4, 0xd4, 0x2b, 0x16, 0x75, 0xa2, 0xc9,
- 0x65, 0xb5, 0xef, 0x20, 0x92, 0x76, 0x0e, 0x61, 0xac, 0xb8, 0x5e, 0x2d,
- 0xef, 0xd4, 0xf3, 0x65, 0x43, 0x56, 0x42, 0xe4, 0x3b, 0xa2, 0xf2, 0xf8,
- 0x9d, 0xca, 0xd6, 0x8a, 0x88, 0x25, 0xb0, 0x99, 0xf8, 0x87, 0x31, 0xae,
- 0x6a, 0x83, 0x4d, 0x51, 0xf7, 0xd4, 0xbb, 0xf2, 0x91, 0x9e, 0xee, 0x37,
- 0x8a, 0x99, 0x45, 0xf8, 0x5f, 0xd6, 0x2f, 0x3a, 0xbc, 0x5a, 0xe3, 0x4b,
- 0x5e, 0x3e, 0xf4, 0x8c, 0x30, 0x4f, 0x99, 0x2b, 0x91, 0x97, 0x22, 0xfc,
- 0xe1, 0x46, 0xb6, 0x44, 0x39, 0xba, 0x3e, 0xe5, 0x10, 0xec, 0x42, 0x5f,
- 0x32, 0x3d, 0x1b, 0xe0, 0xdf, 0x28, 0xee, 0x31, 0x06, 0xe0, 0xbb, 0xde,
- 0x86, 0xf5, 0xbe, 0x17, 0x32, 0xa2, 0x6e, 0xa0, 0xbf, 0x25, 0xee, 0xbb,
- 0x42, 0x7f, 0x4b, 0x57, 0xde, 0xb6, 0x7b, 0xe9, 0xf3, 0x46, 0xe4, 0x18,
- 0xfc, 0xe8, 0xd1, 0x45, 0xf2, 0x93, 0xf6, 0x70, 0xd9, 0x30, 0x64, 0x42,
- 0x1f, 0x3f, 0x2c, 0x6f, 0xd4, 0x7e, 0xa0, 0x70, 0xe0, 0xb6, 0x9d, 0x0d,
- 0x99, 0x86, 0x7f, 0x98, 0x71, 0x20, 0x7f, 0x33, 0x82, 0xf5, 0x19, 0x56,
- 0xfe, 0x71, 0xe6, 0xfd, 0xe5, 0x24, 0x01, 0x37, 0x66, 0x7f, 0xf6, 0x3e,
- 0x63, 0xf6, 0x03, 0xc0, 0x61, 0xef, 0x8b, 0xbe, 0xe1, 0xd2, 0xff, 0x33,
- 0xe8, 0xea, 0xd7, 0x55, 0xfd, 0x22, 0xb7, 0x73, 0x2b, 0x65, 0xfa, 0x5e,
- 0xcf, 0xe9, 0xee, 0x73, 0x9f, 0xbb, 0x4f, 0xbe, 0x4c, 0xa9, 0x01, 0x2b,
- 0xe4, 0x55, 0x1c, 0x65, 0xae, 0xd8, 0xe6, 0xe9, 0x6f, 0x10, 0x18, 0x9a,
- 0x74, 0x7d, 0xdf, 0xdb, 0x21, 0xf9, 0x5e, 0x3f, 0xff, 0x84, 0xcf, 0x5e,
- 0x6d, 0xf7, 0xf3, 0x59, 0x3e, 0xbf, 0x92, 0x41, 0xfe, 0x0c, 0x1b, 0x60,
- 0x2c, 0x60, 0x5b, 0x5c, 0xf9, 0xa1, 0x77, 0xe7, 0x9b, 0xf5, 0x0b, 0xf2,
- 0xbd, 0x5b, 0xf1, 0x9d, 0x56, 0x7c, 0xb3, 0x06, 0xb9, 0x5f, 0x4b, 0x9d,
- 0x67, 0x1d, 0xd2, 0xaf, 0x3b, 0x92, 0x1e, 0xb0, 0x01, 0xf4, 0xfd, 0x63,
- 0xd0, 0xfd, 0x11, 0xf4, 0xfa, 0xc3, 0x12, 0xb0, 0x41, 0x09, 0xd8, 0xa0,
- 0x04, 0x6c, 0x50, 0x02, 0x36, 0x28, 0x85, 0xbd, 0x3a, 0x8b, 0x4d, 0x6c,
- 0xff, 0x3e, 0x6d, 0xd7, 0xaf, 0x6d, 0xac, 0xb7, 0x4b, 0xb7, 0xb6, 0x99,
- 0xaa, 0xfb, 0x18, 0x39, 0xc8, 0x5a, 0x2b, 0xb0, 0x9a, 0x5f, 0xf7, 0xf0,
- 0x62, 0x44, 0x8d, 0xfb, 0x5e, 0x88, 0x11, 0x35, 0x1b, 0xeb, 0x66, 0x28,
- 0x6c, 0x00, 0x1b, 0x1a, 0x12, 0xc6, 0x6f, 0x13, 0xbe, 0x17, 0xb4, 0x86,
- 0xfb, 0xb1, 0x92, 0xda, 0x55, 0x5d, 0xef, 0x88, 0xaa, 0x3b, 0x58, 0x32,
- 0x5b, 0xf6, 0x73, 0xb7, 0x98, 0x8c, 0xcd, 0x13, 0x6f, 0xca, 0x16, 0x3d,
- 0x01, 0x1d, 0x38, 0xc4, 0x88, 0xdc, 0x27, 0xe4, 0xf8, 0xb1, 0xc1, 0x2a,
- 0xc6, 0x2c, 0x58, 0x2e, 0x7f, 0x47, 0x9c, 0xbb, 0xcf, 0xec, 0x82, 0x7f,
- 0xce, 0x14, 0x23, 0x32, 0x5e, 0x74, 0x31, 0x01, 0xf2, 0x9f, 0x75, 0xf5,
- 0xe5, 0x5b, 0xd0, 0xc3, 0xad, 0xcc, 0x94, 0xb5, 0x6a, 0x1b, 0x91, 0xcb,
- 0x71, 0xca, 0x98, 0xfa, 0xdf, 0xab, 0xf6, 0x29, 0x76, 0x55, 0xdd, 0xbd,
- 0xa4, 0x71, 0x65, 0x0b, 0x01, 0xfa, 0x19, 0xd0, 0x89, 0xbb, 0x6b, 0x18,
- 0x76, 0x91, 0x73, 0x7c, 0xb9, 0xb4, 0xe2, 0x91, 0x2f, 0x6a, 0x62, 0x6d,
- 0xd4, 0xfe, 0x1b, 0x2d, 0xed, 0xab, 0xf7, 0x3d, 0x7e, 0xe1, 0xfb, 0x56,
- 0x6b, 0x0d, 0xf4, 0x53, 0x77, 0xdb, 0x81, 0xdd, 0x24, 0xa0, 0xee, 0xc3,
- 0x87, 0xd7, 0x42, 0x92, 0xaa, 0x59, 0x92, 0x2e, 0xb3, 0x1f, 0xeb, 0x17,
- 0xf4, 0x47, 0x7f, 0x22, 0x29, 0xe4, 0xab, 0xd9, 0x50, 0x34, 0x6e, 0xcb,
- 0x7f, 0x96, 0xe5, 0x85, 0x7c, 0x84, 0xe7, 0x0a, 0xf2, 0x13, 0x1a, 0x9e,
- 0xfb, 0x19, 0xae, 0xc9, 0xb3, 0x25, 0x33, 0x45, 0xc6, 0x9d, 0xa1, 0x70,
- 0x0d, 0xf7, 0xb2, 0x93, 0xac, 0xd9, 0x7c, 0x07, 0x36, 0x19, 0x8d, 0x94,
- 0xa1, 0xef, 0x2b, 0x45, 0x8e, 0x07, 0x6c, 0x54, 0x64, 0x5d, 0xc7, 0xbf,
- 0xff, 0x27, 0xc0, 0x81, 0xf0, 0xd5, 0x21, 0xaf, 0x8f, 0x9a, 0xab, 0x6d,
- 0x06, 0x60, 0xe3, 0x0d, 0xcf, 0xdf, 0x56, 0x8a, 0x6e, 0x1d, 0xe5, 0x2c,
- 0xf9, 0x70, 0xfe, 0x77, 0xb3, 0x11, 0x42, 0x0e, 0xb4, 0x3a, 0xc7, 0xab,
- 0xa4, 0x6f, 0xc2, 0xdd, 0xca, 0x51, 0xc7, 0x97, 0x05, 0xef, 0xb3, 0x8d,
- 0x67, 0x27, 0x9a, 0xcd, 0xb3, 0xd6, 0x07, 0xad, 0x99, 0xf5, 0x6d, 0x4f,
- 0x5a, 0xf9, 0xdd, 0x15, 0x27, 0xef, 0xd5, 0xcc, 0xbe, 0xbd, 0xc3, 0xad,
- 0x99, 0xd5, 0x76, 0xac, 0xad, 0x99, 0x59, 0xdb, 0xdd, 0x9a, 0xd9, 0xfc,
- 0xee, 0x02, 0x3e, 0x6e, 0xcd, 0x2c, 0xbb, 0xdd, 0xad, 0x99, 0x95, 0xb7,
- 0xbb, 0x35, 0x33, 0x67, 0x87, 0x5b, 0x33, 0xfb, 0xf9, 0xf6, 0xb5, 0x35,
- 0xb3, 0x1f, 0xec, 0x58, 0x5b, 0x33, 0xbb, 0xb8, 0x3b, 0x87, 0xcf, 0xdd,
- 0x9a, 0xd9, 0xcf, 0x76, 0xdc, 0xbb, 0x66, 0xf6, 0x9a, 0x8f, 0xd7, 0x31,
- 0x9f, 0x11, 0xcc, 0x21, 0x0e, 0xbc, 0x3e, 0x0c, 0xbc, 0xfe, 0x6e, 0x75,
- 0xfe, 0x00, 0xe6, 0x39, 0xe8, 0xc5, 0x83, 0x0f, 0x82, 0xdb, 0x47, 0xbc,
- 0x67, 0x6d, 0xe4, 0xbb, 0x11, 0x2f, 0x57, 0x21, 0x76, 0xdf, 0xec, 0xe5,
- 0x6c, 0xff, 0xa8, 0xf3, 0xee, 0xb9, 0x97, 0xd6, 0xef, 0x0f, 0x21, 0xf5,
- 0xf6, 0xf1, 0x3c, 0xe7, 0x95, 0x47, 0xee, 0x47, 0x39, 0xd8, 0xe8, 0x3f,
- 0xbf, 0xfb, 0x1b, 0x16, 0x31, 0xfe, 0x73, 0x58, 0xab, 0xf6, 0x16, 0x43,
- 0x9d, 0x01, 0x60, 0x8c, 0x3a, 0x2e, 0x29, 0xf4, 0x4f, 0xa9, 0xfe, 0xd7,
- 0x5a, 0xfa, 0xaf, 0xa0, 0x3f, 0xe9, 0x46, 0xff, 0x1d, 0x3e, 0x2f, 0x29,
- 0xfb, 0xb6, 0x5c, 0x0c, 0x9f, 0x2e, 0xf9, 0x78, 0x2b, 0xe0, 0x61, 0xe7,
- 0x46, 0xc6, 0x76, 0x3e, 0x8f, 0x67, 0xa2, 0x17, 0x6d, 0xb9, 0xa9, 0xf0,
- 0xbb, 0x91, 0x88, 0x5e, 0xcc, 0xaa, 0x7c, 0xad, 0x91, 0xc9, 0x39, 0x7e,
- 0xfe, 0x8d, 0x1c, 0x6a, 0x80, 0x39, 0x0c, 0xec, 0x7d, 0x69, 0x10, 0x71,
- 0xac, 0x35, 0xc7, 0x66, 0x5e, 0xad, 0x7b, 0x79, 0xb5, 0x29, 0x9f, 0xd9,
- 0xd9, 0x8a, 0xcd, 0x2f, 0xee, 0xfe, 0xc7, 0x0a, 0x9b, 0x6f, 0x42, 0x6e,
- 0x4e, 0xec, 0x4d, 0x1c, 0x43, 0x0c, 0x41, 0x7c, 0xce, 0x7a, 0x01, 0xf3,
- 0x19, 0xc6, 0x46, 0xe6, 0x37, 0x21, 0x7c, 0x78, 0x26, 0xc9, 0xc7, 0xe8,
- 0xed, 0x9e, 0x7f, 0x67, 0x5e, 0xe4, 0x63, 0x95, 0xe4, 0x26, 0x37, 0x37,
- 0xda, 0xa4, 0xb9, 0xf9, 0x67, 0xc4, 0xeb, 0x13, 0x58, 0xc5, 0xc2, 0x81,
- 0x55, 0x2c, 0xbc, 0x66, 0x1f, 0x4b, 0xd4, 0xf9, 0x27, 0xb5, 0x1f, 0xc6,
- 0xfd, 0xb1, 0x46, 0xe6, 0xca, 0x80, 0x68, 0x7a, 0x82, 0xfb, 0x64, 0xc0,
- 0x3a, 0x16, 0xf7, 0xcd, 0xe8, 0x3b, 0xf7, 0x69, 0xa9, 0x2a, 0xe3, 0x0f,
- 0xf1, 0x91, 0xbf, 0x17, 0xee, 0xeb, 0x89, 0xb2, 0x63, 0xdb, 0x1f, 0x6b,
- 0xc8, 0x79, 0xe3, 0xed, 0xd6, 0x53, 0xe0, 0x25, 0x83, 0x6f, 0x5f, 0xa6,
- 0x9f, 0x55, 0xb1, 0xaf, 0x03, 0xb6, 0x7b, 0xa4, 0x44, 0xec, 0xba, 0x59,
- 0x6a, 0x1e, 0x7e, 0x3d, 0x37, 0xef, 0x62, 0xd7, 0xc0, 0x5a, 0xec, 0x1a,
- 0x5f, 0x16, 0x97, 0xc7, 0x5d, 0x1b, 0xf2, 0x48, 0xbc, 0x4a, 0xfe, 0x18,
- 0x77, 0xf6, 0xc2, 0xff, 0x35, 0x80, 0x69, 0x19, 0x73, 0x18, 0x6f, 0x22,
- 0xc0, 0xf6, 0xf7, 0xe2, 0x4f, 0xb5, 0x1d, 0xea, 0xb0, 0x82, 0xf8, 0x4c,
- 0xc3, 0x7f, 0x4c, 0xe0, 0x99, 0x8c, 0xcc, 0x9e, 0xfe, 0x1a, 0xe6, 0x36,
- 0x2d, 0x57, 0xe6, 0x27, 0xc1, 0xdf, 0x73, 0x32, 0x17, 0xcf, 0xc3, 0x8f,
- 0x70, 0xcf, 0x83, 0xb8, 0xad, 0xdf, 0xfb, 0x9e, 0xd6, 0xcf, 0x5a, 0x51,
- 0xe2, 0x46, 0xa9, 0x16, 0xe9, 0x83, 0xb9, 0x67, 0xc8, 0xbd, 0x61, 0xda,
- 0x0f, 0xeb, 0x27, 0xc8, 0x5d, 0x99, 0xc3, 0x9e, 0xe2, 0xf8, 0x6b, 0x75,
- 0xb2, 0xec, 0x10, 0x7f, 0x35, 0x32, 0x8d, 0x25, 0xe2, 0xc7, 0xf7, 0x8b,
- 0x25, 0xa9, 0x07, 0xe2, 0xc9, 0xfb, 0xc1, 0x91, 0xd1, 0x79, 0x60, 0xc8,
- 0x57, 0x1a, 0x7a, 0x2b, 0x8e, 0x74, 0x31, 0x64, 0x72, 0x29, 0x0b, 0x9a,
- 0x71, 0x85, 0x95, 0x91, 0xc7, 0xc1, 0xed, 0xf5, 0xe3, 0xd9, 0x7e, 0xe4,
- 0xe4, 0x2e, 0x66, 0x4c, 0x01, 0x33, 0xfe, 0x06, 0x30, 0xe3, 0xac, 0x74,
- 0x76, 0x11, 0x33, 0xda, 0x1e, 0x66, 0x4c, 0xc3, 0x9e, 0x73, 0x6b, 0xec,
- 0x59, 0x53, 0xb5, 0x28, 0xde, 0xcb, 0x01, 0xf3, 0xa5, 0x4e, 0x45, 0xef,
- 0x03, 0x27, 0x6a, 0x12, 0x52, 0xe7, 0x52, 0x02, 0x2d, 0x34, 0x7d, 0x3c,
- 0xb8, 0x4d, 0xe1, 0xbc, 0xdd, 0xa5, 0x4d, 0xc8, 0x51, 0x14, 0xee, 0xf3,
- 0xf6, 0x4b, 0x03, 0xeb, 0xf6, 0x90, 0x03, 0x2d, 0x7b, 0xc8, 0x77, 0xf1,
- 0x21, 0x9e, 0xf3, 0x6a, 0x7d, 0x6d, 0xf0, 0x05, 0xff, 0x13, 0x3c, 0x71,
- 0x7d, 0x71, 0x2d, 0x68, 0xee, 0x7a, 0x59, 0x83, 0x13, 0xff, 0x7a, 0x1d,
- 0x4e, 0x44, 0xec, 0x3a, 0x17, 0x92, 0x24, 0x30, 0xa2, 0xbd, 0x44, 0x5a,
- 0x5c, 0xd3, 0xc3, 0xd2, 0x8e, 0xf9, 0x75, 0x9c, 0xea, 0x05, 0x36, 0xea,
- 0x92, 0x20, 0x30, 0x52, 0x9b, 0xc2, 0x48, 0x03, 0xc4, 0x32, 0x83, 0x33,
- 0xc0, 0x36, 0xb5, 0x55, 0x9c, 0x14, 0x8d, 0xff, 0x01, 0xf4, 0xf2, 0x94,
- 0xf2, 0x3d, 0x69, 0x39, 0x01, 0x5f, 0xda, 0xbe, 0x04, 0x7c, 0x77, 0xce,
- 0xc5, 0x4f, 0x6d, 0xeb, 0xf0, 0xd3, 0xc1, 0x0d, 0xf1, 0x93, 0xaa, 0xdf,
- 0x8f, 0x52, 0x26, 0x37, 0x1c, 0xb7, 0x7e, 0x7f, 0xdd, 0x71, 0xeb, 0xf7,
- 0x37, 0x9c, 0xd6, 0xfa, 0xfd, 0x47, 0xa4, 0x60, 0x46, 0xed, 0x15, 0x59,
- 0x57, 0xbf, 0x9f, 0x60, 0x3d, 0xdc, 0xe9, 0x72, 0xeb, 0xf4, 0x5d, 0x5e,
- 0xfd, 0x3e, 0x2a, 0x85, 0x35, 0xed, 0xa6, 0xbc, 0x69, 0xf9, 0xf5, 0xfb,
- 0xef, 0xa2, 0xad, 0x1b, 0x63, 0xac, 0xad, 0xdd, 0x5f, 0x77, 0x58, 0xbb,
- 0x0f, 0xb1, 0x9f, 0x57, 0xbb, 0x67, 0x3f, 0xe4, 0xf2, 0x0e, 0xeb, 0xf6,
- 0x8f, 0x40, 0x16, 0x5b, 0x21, 0x87, 0x5e, 0x69, 0x3f, 0x13, 0x66, 0x1f,
- 0x55, 0xaf, 0x5f, 0x71, 0x42, 0x78, 0xce, 0xad, 0xab, 0xcf, 0xc0, 0xae,
- 0x0e, 0xae, 0xd6, 0xeb, 0xdd, 0x31, 0x6e, 0x3a, 0x6b, 0xe9, 0xaf, 0xa5,
- 0xd3, 0xe7, 0xd1, 0x09, 0x81, 0x4e, 0x78, 0x1d, 0x9d, 0xbb, 0xf5, 0xf9,
- 0x9b, 0x8e, 0x5b, 0x9b, 0x4f, 0x9f, 0x16, 0xbb, 0x1d, 0xbe, 0xf9, 0xe2,
- 0xc0, 0xc3, 0x1e, 0x8d, 0xd5, 0xda, 0x3c, 0x7d, 0x08, 0x70, 0x7b, 0x4c,
- 0x9d, 0xbd, 0x9a, 0xf9, 0x7f, 0x50, 0x9b, 0x67, 0x5d, 0xde, 0xdd, 0x5f,
- 0xe1, 0xfa, 0x04, 0x3e, 0x7f, 0xd1, 0xad, 0xc9, 0x8f, 0x95, 0xfc, 0x5a,
- 0x3b, 0xf3, 0x47, 0xff, 0x5c, 0x54, 0x7f, 0xe4, 0x88, 0xd0, 0x56, 0xc8,
- 0x1f, 0xe9, 0x76, 0xcb, 0x94, 0xc2, 0x47, 0xb0, 0xa9, 0xd8, 0xbd, 0x31,
- 0x72, 0xe5, 0x94, 0x8f, 0x91, 0x43, 0x0a, 0x23, 0x57, 0x96, 0x7c, 0x8c,
- 0x9c, 0xbc, 0x07, 0x46, 0x6e, 0x76, 0xb9, 0x71, 0x20, 0x28, 0x79, 0x85,
- 0x91, 0xef, 0x75, 0x96, 0x8c, 0xf7, 0xba, 0x88, 0x07, 0xc4, 0x3d, 0x5f,
- 0xd0, 0x7b, 0x8f, 0xb5, 0xe6, 0xe3, 0x66, 0xc6, 0xfe, 0xad, 0x32, 0x71,
- 0xe6, 0x2e, 0x6e, 0x76, 0xb1, 0x71, 0x34, 0x72, 0x48, 0xc5, 0x44, 0xe0,
- 0x84, 0x3a, 0xeb, 0xdf, 0xc4, 0xbe, 0x8c, 0x39, 0x01, 0x85, 0xcf, 0x72,
- 0x45, 0xe6, 0x01, 0x6c, 0x23, 0x16, 0xee, 0xe4, 0x31, 0x2b, 0x2f, 0x26,
- 0xf9, 0x58, 0xd3, 0x3f, 0xd7, 0xc2, 0x3d, 0x86, 0x37, 0x8d, 0xa4, 0x85,
- 0x76, 0xc7, 0xcf, 0x15, 0xe2, 0xea, 0x3c, 0x50, 0x12, 0x58, 0x72, 0x6a,
- 0x15, 0x4b, 0xd2, 0x57, 0xfc, 0xf4, 0x6d, 0xdb, 0xa4, 0x5f, 0xf3, 0xb1,
- 0x22, 0x72, 0xa2, 0x12, 0xd7, 0xb6, 0x8f, 0x15, 0x5d, 0x9c, 0x98, 0x72,
- 0x1a, 0xc0, 0xcb, 0x01, 0x19, 0x03, 0x4e, 0x6f, 0x7c, 0x89, 0x35, 0x28,
- 0x1f, 0x1b, 0xd9, 0xf8, 0x6e, 0xad, 0x49, 0xf1, 0xba, 0x5d, 0xed, 0x05,
- 0x5e, 0x1e, 0x08, 0xb6, 0xb4, 0x3f, 0x0b, 0xff, 0x8d, 0xfc, 0x08, 0xd8,
- 0xc4, 0xc5, 0x44, 0x3b, 0xa0, 0x83, 0x91, 0x7b, 0x60, 0xa2, 0xf5, 0x31,
- 0x8a, 0x31, 0xf3, 0x6e, 0x8c, 0x4a, 0xd7, 0xe9, 0xcf, 0xef, 0xc6, 0xa8,
- 0x7b, 0xc7, 0x50, 0xb6, 0x61, 0x76, 0x56, 0x06, 0x9f, 0x69, 0x29, 0xac,
- 0x8b, 0x51, 0x73, 0x1f, 0x20, 0x46, 0xb9, 0xf8, 0xc0, 0xe5, 0xfb, 0xf7,
- 0x21, 0x9b, 0x1f, 0x43, 0xa6, 0x3f, 0x02, 0xe6, 0xfa, 0x21, 0xe6, 0xf5,
- 0x03, 0xe0, 0xa1, 0xef, 0x97, 0xd6, 0x9f, 0x07, 0x19, 0x15, 0xe6, 0x87,
- 0x2e, 0x66, 0x72, 0x31, 0xfd, 0x0c, 0x56, 0x57, 0xad, 0xd8, 0xc8, 0x4c,
- 0x15, 0x87, 0xcc, 0x69, 0x77, 0x1f, 0x35, 0x92, 0x95, 0xa7, 0x3b, 0x53,
- 0x8b, 0x8c, 0x19, 0xea, 0x3a, 0xcc, 0xfa, 0x25, 0xb1, 0x43, 0x55, 0xe5,
- 0x99, 0x03, 0x52, 0xae, 0xb9, 0x78, 0x6b, 0x6e, 0xd1, 0xa5, 0x31, 0xe5,
- 0xe1, 0xad, 0x9c, 0x87, 0xb7, 0xb2, 0xb5, 0xe5, 0x48, 0x00, 0xfd, 0xe7,
- 0xe2, 0x6b, 0x31, 0xd6, 0x8c, 0x87, 0xb1, 0xa6, 0x3f, 0x20, 0xc6, 0xe2,
- 0x58, 0x39, 0x3c, 0x33, 0x3e, 0x1f, 0x91, 0x5d, 0x90, 0xf3, 0x58, 0x91,
- 0xfa, 0xe2, 0x19, 0xb2, 0xf7, 0xd2, 0x19, 0xf5, 0xe5, 0xea, 0x2a, 0x10,
- 0xdb, 0xa7, 0x8d, 0x43, 0x57, 0x63, 0xef, 0xa9, 0x2b, 0x31, 0xdf, 0x18,
- 0x09, 0xe2, 0xf3, 0xf7, 0xa5, 0x2b, 0xce, 0x83, 0xfa, 0x5a, 0x8f, 0xc5,
- 0xee, 0x07, 0x93, 0xad, 0xc5, 0x63, 0xb6, 0xc2, 0x63, 0xed, 0x5e, 0x1f,
- 0xd9, 0x33, 0x0e, 0x5d, 0xfe, 0x27, 0xf4, 0xf9, 0x99, 0xd5, 0x2d, 0x3f,
- 0x85, 0xff, 0xfe, 0x43, 0xe8, 0xe4, 0x3f, 0x22, 0x57, 0x78, 0xcd, 0xea,
- 0x93, 0x3f, 0x40, 0xdb, 0x5d, 0x9c, 0xc3, 0xfe, 0xc1, 0xc7, 0x92, 0xd6,
- 0x35, 0xe0, 0x93, 0x6b, 0x1e, 0x3e, 0x79, 0x3a, 0x99, 0xb4, 0x26, 0x59,
- 0x37, 0x87, 0x9c, 0x0f, 0xa4, 0xa6, 0x14, 0x36, 0xf1, 0x31, 0xc9, 0xed,
- 0x34, 0xc7, 0x9f, 0x75, 0x56, 0x80, 0x7d, 0x56, 0x3c, 0xec, 0x73, 0x60,
- 0xcc, 0xc5, 0x3e, 0xc1, 0xcf, 0x50, 0xff, 0x2e, 0xee, 0x59, 0xb1, 0x93,
- 0x18, 0xa7, 0x0a, 0x4c, 0x52, 0x71, 0x0e, 0x48, 0xbe, 0xbe, 0x57, 0x7d,
- 0x8e, 0x94, 0xec, 0x68, 0x1b, 0xe4, 0xc4, 0xda, 0xeb, 0x49, 0xae, 0x4a,
- 0x27, 0x6a, 0x16, 0xf1, 0x9d, 0x75, 0xa2, 0xe1, 0xdf, 0xf1, 0xae, 0x9f,
- 0xf7, 0xae, 0x4f, 0x78, 0xd7, 0xc7, 0x11, 0x87, 0x8f, 0xa9, 0x58, 0xca,
- 0x76, 0xb6, 0x41, 0xc9, 0x0e, 0x68, 0x01, 0x7b, 0x9c, 0x1d, 0xfe, 0x8b,
- 0x66, 0x59, 0xe9, 0x98, 0xf4, 0x27, 0xf0, 0x39, 0x8e, 0xcf, 0x34, 0x3e,
- 0xfb, 0xf1, 0xc9, 0xe3, 0xb3, 0x2a, 0x53, 0x2d, 0x55, 0x9a, 0x84, 0x8d,
- 0x0c, 0x4a, 0xaa, 0xfe, 0x12, 0xf4, 0xf8, 0x1c, 0x74, 0x7b, 0x58, 0x0a,
- 0xd5, 0x3f, 0x95, 0xd9, 0x79, 0x4d, 0xba, 0x2c, 0xe8, 0xb4, 0x0a, 0x5b,
- 0x9e, 0x77, 0xf7, 0x13, 0x3b, 0x13, 0x7b, 0xd1, 0xb7, 0x29, 0x4f, 0xc5,
- 0x9f, 0x13, 0xfd, 0xb1, 0x39, 0xf4, 0x13, 0xbd, 0x30, 0xfc, 0x31, 0xb5,
- 0x6f, 0x56, 0x8d, 0xbb, 0x32, 0xde, 0x65, 0xd9, 0x51, 0xe8, 0x7c, 0xf0,
- 0x18, 0x68, 0x27, 0xd5, 0xd9, 0xd8, 0x8c, 0x1c, 0x3d, 0xbd, 0xbc, 0xc5,
- 0xf5, 0xad, 0x51, 0xf3, 0x26, 0xf5, 0x8e, 0x79, 0xd8, 0xf0, 0x85, 0x19,
- 0xd8, 0xfb, 0x41, 0x27, 0xa0, 0x8d, 0x21, 0xde, 0x8c, 0x39, 0x37, 0x55,
- 0xbc, 0x81, 0xef, 0xca, 0xc4, 0x4e, 0x86, 0x70, 0xcd, 0xb3, 0x45, 0x88,
- 0x8b, 0xea, 0x6c, 0xe5, 0x32, 0xf0, 0x8d, 0xa6, 0xea, 0x80, 0xb3, 0xab,
- 0xfb, 0x43, 0x86, 0xf2, 0x5b, 0xb1, 0x98, 0x2e, 0xb9, 0x11, 0xe2, 0xdc,
- 0xbd, 0x2a, 0x36, 0xd5, 0x8a, 0xf6, 0x43, 0xcc, 0x15, 0x6f, 0x08, 0xe3,
- 0xdc, 0xe3, 0xe8, 0xd7, 0x07, 0x7f, 0x8c, 0x7b, 0x75, 0xda, 0x27, 0xe7,
- 0xca, 0x67, 0xa6, 0xa5, 0x5a, 0x1e, 0xc5, 0x7c, 0xbd, 0x1c, 0x49, 0xe5,
- 0x12, 0x11, 0xd8, 0xa3, 0xbf, 0x17, 0xe5, 0xd6, 0x4f, 0xaa, 0x8e, 0x8f,
- 0x29, 0xba, 0xd1, 0x87, 0x79, 0x05, 0x64, 0xe4, 0xee, 0x9f, 0xa9, 0xbd,
- 0xb3, 0x82, 0x33, 0x0a, 0x39, 0x25, 0xd1, 0xce, 0x5a, 0x35, 0x7e, 0x97,
- 0x75, 0x55, 0x13, 0x58, 0x31, 0x66, 0xa4, 0x56, 0x6e, 0x82, 0x5f, 0xc4,
- 0xdc, 0x2d, 0x33, 0x52, 0x29, 0x4f, 0xcb, 0x2b, 0xe5, 0x9f, 0x77, 0x03,
- 0x53, 0x41, 0xa6, 0xe4, 0xbf, 0x5b, 0xee, 0x9e, 0xbf, 0xf5, 0xdb, 0x21,
- 0xcf, 0xd3, 0xf9, 0xb0, 0x9b, 0xe7, 0xe6, 0x55, 0x2d, 0xc6, 0xfd, 0xb6,
- 0xf5, 0x29, 0x2b, 0x1a, 0x9e, 0x45, 0xcf, 0x83, 0x0b, 0xb4, 0xcd, 0xfc,
- 0xf8, 0x9c, 0xb5, 0x43, 0xae, 0xc6, 0x37, 0xcb, 0x72, 0x5c, 0xe5, 0xc5,
- 0xc4, 0x0f, 0x58, 0xeb, 0x51, 0xb3, 0x21, 0x7b, 0xe4, 0x28, 0xd6, 0xed,
- 0xd5, 0xf8, 0xd3, 0xb0, 0xd3, 0x67, 0x61, 0x0b, 0xac, 0x01, 0x1c, 0x62,
- 0xae, 0x25, 0x0d, 0x55, 0x23, 0x6b, 0x36, 0xc7, 0xd5, 0x19, 0xee, 0x76,
- 0x59, 0x56, 0x58, 0xcc, 0xad, 0x9d, 0x2f, 0x4f, 0xba, 0x6b, 0xc4, 0x50,
- 0x76, 0xff, 0xc7, 0xe0, 0xc7, 0x84, 0xed, 0xb6, 0xa9, 0x3e, 0x46, 0xa2,
- 0xc3, 0xeb, 0xa3, 0xf4, 0xdb, 0xd2, 0xe7, 0x95, 0x44, 0xd2, 0xda, 0xff,
- 0x89, 0xa4, 0x75, 0x73, 0xb7, 0x5b, 0x6f, 0x89, 0x9a, 0xb6, 0xc6, 0xf7,
- 0x52, 0xdc, 0xf5, 0x98, 0xc1, 0xba, 0xba, 0xb4, 0x8a, 0xa1, 0x61, 0xa4,
- 0x2f, 0x5f, 0x81, 0x7e, 0x03, 0xd2, 0x7e, 0xb2, 0xf9, 0xf8, 0x54, 0x7c,
- 0x28, 0x72, 0x50, 0x78, 0x02, 0x8b, 0x79, 0x75, 0x34, 0x9e, 0x95, 0x2b,
- 0x88, 0x93, 0x77, 0x88, 0x1d, 0x06, 0x2f, 0xcb, 0x9d, 0xc7, 0x93, 0xf1,
- 0x51, 0xad, 0x32, 0x89, 0xac, 0xe5, 0xe5, 0x49, 0xc6, 0xd9, 0x43, 0x22,
- 0xc0, 0x97, 0x27, 0x47, 0x24, 0x5d, 0x54, 0xef, 0xa9, 0xf0, 0x9c, 0xad,
- 0x36, 0x0d, 0xf9, 0xe1, 0xf9, 0x09, 0x06, 0x46, 0xdd, 0xea, 0x8f, 0xa4,
- 0xe5, 0x69, 0xd6, 0xc0, 0x24, 0xb7, 0x20, 0xdb, 0x92, 0xf0, 0xab, 0xf6,
- 0x44, 0xbb, 0x4c, 0xd7, 0x1a, 0x99, 0xfe, 0x53, 0xcf, 0x82, 0xc6, 0x14,
- 0x68, 0xed, 0x45, 0x6e, 0x92, 0x45, 0xac, 0xa6, 0x7c, 0xe9, 0xbb, 0x9f,
- 0x81, 0x8c, 0x3e, 0xc2, 0x3d, 0xe5, 0xd1, 0xac, 0x44, 0x27, 0xf2, 0x8a,
- 0xee, 0x5b, 0x5a, 0x6e, 0xf8, 0x57, 0x10, 0xeb, 0x02, 0xb2, 0x2b, 0x26,
- 0xfa, 0xde, 0x58, 0xe0, 0xed, 0x29, 0x8b, 0x6d, 0x41, 0xb6, 0xe9, 0x68,
- 0x0b, 0xfc, 0x7a, 0x2c, 0xa8, 0x27, 0x63, 0xd1, 0x51, 0x9e, 0x8f, 0x36,
- 0xac, 0x29, 0xee, 0x4d, 0x3c, 0x20, 0x5d, 0x7b, 0xa5, 0xe7, 0x42, 0x74,
- 0xf4, 0x06, 0x78, 0x09, 0x28, 0x5f, 0x3f, 0x25, 0xba, 0xd7, 0xde, 0xbd,
- 0xda, 0x1e, 0xf0, 0xda, 0xf7, 0x4a, 0xd7, 0x85, 0x21, 0xf3, 0x75, 0x99,
- 0x01, 0x4d, 0x43, 0xae, 0x23, 0xd7, 0xb1, 0x06, 0xa6, 0x60, 0x8b, 0x4f,
- 0x92, 0x97, 0xfd, 0xc0, 0x1a, 0x58, 0x1b, 0xc8, 0xbf, 0xad, 0x0f, 0xcb,
- 0x57, 0xcd, 0x4e, 0xc9, 0xa9, 0x5c, 0x37, 0xe0, 0xd6, 0x52, 0x61, 0xef,
- 0x8f, 0x0e, 0x1c, 0xec, 0x71, 0xeb, 0x05, 0xdc, 0xef, 0x18, 0x46, 0xdb,
- 0x9d, 0xe6, 0x39, 0x8b, 0x6d, 0xbc, 0x77, 0xa7, 0x59, 0xb5, 0x86, 0xcc,
- 0x94, 0x16, 0xf4, 0xf6, 0xbd, 0x0f, 0xa9, 0xb9, 0xe7, 0xcb, 0xfd, 0x66,
- 0x45, 0x1e, 0xd5, 0x52, 0x0f, 0x22, 0x5e, 0x38, 0xd3, 0xe8, 0x7b, 0x87,
- 0xe7, 0x29, 0x54, 0x7d, 0xbf, 0x22, 0xfe, 0x35, 0xe9, 0x0c, 0x99, 0xe3,
- 0xea, 0xd9, 0x21, 0xf3, 0xa8, 0xd6, 0xfa, 0x6c, 0x58, 0x1b, 0x5f, 0xf3,
- 0x6c, 0x97, 0x92, 0x91, 0x61, 0xb9, 0x7d, 0x66, 0xcb, 0x7b, 0xe5, 0x79,
- 0x87, 0xfd, 0xee, 0x34, 0x53, 0xd6, 0x03, 0xda, 0xd1, 0x07, 0xe9, 0x0b,
- 0xd9, 0xf7, 0xf6, 0xba, 0x71, 0x78, 0x7d, 0xaf, 0x31, 0x9a, 0xb2, 0x76,
- 0x8c, 0x4d, 0xaa, 0xcf, 0x55, 0xd5, 0x27, 0xa0, 0x64, 0xbd, 0x76, 0x9c,
- 0xbf, 0x91, 0xb5, 0xe3, 0x74, 0xad, 0xce, 0x79, 0x16, 0x34, 0x8f, 0xa1,
- 0x6f, 0xd1, 0xe9, 0x0f, 0x57, 0xe5, 0x76, 0x33, 0x67, 0xbd, 0x29, 0x57,
- 0x57, 0x69, 0xff, 0x12, 0xd7, 0xad, 0x3c, 0xfd, 0xd2, 0xe3, 0x91, 0xbf,
- 0xd9, 0xf6, 0x2f, 0x95, 0xbc, 0x1f, 0xb0, 0xfa, 0xf7, 0x57, 0xb4, 0xe8,
- 0xe8, 0x5f, 0x0a, 0x75, 0xf5, 0xcf, 0x94, 0xaf, 0xf9, 0x18, 0xf4, 0xb4,
- 0xed, 0x05, 0xac, 0xdd, 0xe1, 0xa4, 0xea, 0x73, 0xdd, 0xda, 0x2b, 0xdb,
- 0x4e, 0xf6, 0x9b, 0xd7, 0xe5, 0x33, 0x92, 0x0e, 0xf1, 0x1a, 0x39, 0x94,
- 0xc5, 0xf7, 0x52, 0x3e, 0xc1, 0xbc, 0x00, 0xba, 0xec, 0x1f, 0xfc, 0x4b,
- 0x79, 0x56, 0x8e, 0x96, 0xe6, 0xe0, 0x7b, 0xa6, 0x64, 0xf0, 0x05, 0xfa,
- 0x9f, 0xbc, 0xe9, 0xd6, 0x6a, 0xdc, 0x98, 0x98, 0xf2, 0x62, 0xe2, 0x9c,
- 0xf2, 0x73, 0xaf, 0x79, 0xe7, 0x22, 0xfa, 0x07, 0xcf, 0xe1, 0xd9, 0x57,
- 0x94, 0x0f, 0xf8, 0x3d, 0xa9, 0x62, 0x2d, 0x44, 0x5e, 0xde, 0x2c, 0x0f,
- 0x3c, 0x41, 0x9b, 0x44, 0x06, 0xf0, 0xb1, 0x36, 0xf5, 0x1e, 0x8c, 0x6e,
- 0x75, 0x88, 0x6c, 0xa1, 0xfd, 0x5c, 0x86, 0xad, 0x4d, 0xb9, 0x7b, 0x5f,
- 0x6b, 0xae, 0xa3, 0x13, 0x2b, 0xf2, 0x1f, 0x94, 0x1d, 0x7e, 0xfc, 0x82,
- 0xfb, 0x3d, 0x7c, 0x01, 0xe9, 0x72, 0x6c, 0xaf, 0x6c, 0xbf, 0xe0, 0xda,
- 0xdd, 0xec, 0xfc, 0xb3, 0x4a, 0xbe, 0x53, 0x4a, 0xbe, 0x4d, 0x99, 0x89,
- 0x53, 0xf6, 0x9c, 0x13, 0xcf, 0x4f, 0xba, 0x32, 0xf9, 0x9c, 0x67, 0x47,
- 0xfd, 0x2f, 0xf0, 0x3d, 0x35, 0xca, 0x88, 0x7c, 0xcf, 0xf4, 0x70, 0x3f,
- 0x76, 0xdb, 0x05, 0xce, 0xb7, 0x6f, 0xcd, 0x7c, 0x4f, 0xc0, 0xc7, 0x0e,
- 0x0c, 0xb8, 0x73, 0x7e, 0x6d, 0xfe, 0xfd, 0xcf, 0xf9, 0x77, 0x57, 0xe7,
- 0x6c, 0x48, 0x55, 0xe5, 0xb9, 0xb1, 0xcd, 0xd2, 0x95, 0x93, 0x06, 0xec,
- 0xe3, 0xcf, 0x85, 0x67, 0xc6, 0xc9, 0x8b, 0x3b, 0xee, 0xb2, 0x43, 0x9e,
- 0xfc, 0x39, 0x90, 0xaf, 0x29, 0x4f, 0x7f, 0xe4, 0xe3, 0xd9, 0x0d, 0xef,
- 0x5d, 0x97, 0x46, 0x66, 0x10, 0x6d, 0xba, 0xd2, 0xe1, 0x98, 0xb7, 0xde,
- 0xf6, 0x8a, 0xae, 0x74, 0x98, 0x5c, 0xd5, 0xe1, 0x0d, 0xe8, 0xb0, 0x2a,
- 0x9f, 0xc6, 0x9c, 0xb0, 0xbe, 0x5f, 0x18, 0x32, 0x67, 0x64, 0xab, 0xd2,
- 0xbf, 0x35, 0x00, 0x9f, 0xea, 0xe9, 0xb2, 0xfd, 0x3e, 0x74, 0xf9, 0xba,
- 0x28, 0x7d, 0xaa, 0x73, 0x44, 0x55, 0x45, 0x87, 0xbe, 0x8d, 0x73, 0x6b,
- 0x57, 0x3e, 0x81, 0x3c, 0xaa, 0xb3, 0x01, 0x13, 0xae, 0x7e, 0xd5, 0x9a,
- 0xf7, 0xf4, 0x9b, 0x9d, 0xa0, 0x0e, 0x7f, 0xad, 0xc7, 0xd5, 0x67, 0x87,
- 0xea, 0x73, 0x2a, 0x36, 0xaa, 0xd6, 0xbb, 0x35, 0xf0, 0xe9, 0x1e, 0xea,
- 0xf4, 0x79, 0xc7, 0xfd, 0x2e, 0x22, 0xce, 0x9d, 0x72, 0xde, 0x4b, 0xaf,
- 0xae, 0x4e, 0xc7, 0xc4, 0x5d, 0x57, 0xeb, 0xf5, 0xa9, 0x5f, 0x08, 0x28,
- 0x1b, 0x1e, 0x83, 0x0c, 0x8f, 0x97, 0x1e, 0xf4, 0xec, 0xde, 0x9d, 0xf3,
- 0xc0, 0xfb, 0x9c, 0xf3, 0x91, 0x62, 0xbf, 0xf9, 0x26, 0xee, 0x8d, 0x63,
- 0xce, 0x33, 0xd2, 0x26, 0x29, 0x6f, 0xce, 0x91, 0xd5, 0x39, 0xfb, 0x3c,
- 0xba, 0xfd, 0x52, 0xcc, 0x63, 0x1d, 0xfa, 0xaf, 0x7f, 0xab, 0xde, 0x37,
- 0xb9, 0x59, 0xa4, 0xdf, 0x06, 0x56, 0x0a, 0xf5, 0xca, 0xf5, 0x5a, 0x44,
- 0xae, 0x13, 0x83, 0x8c, 0xe0, 0xdb, 0x99, 0xf3, 0x62, 0x78, 0x50, 0x5e,
- 0x2f, 0x6e, 0xc4, 0xc7, 0xb0, 0xdc, 0x28, 0xfa, 0xbc, 0x10, 0x0b, 0x33,
- 0x5f, 0x98, 0x92, 0x37, 0xe6, 0xfb, 0xa5, 0x31, 0x81, 0xb8, 0x3f, 0x40,
- 0x99, 0x0c, 0x99, 0x7b, 0xd4, 0x7b, 0x48, 0x77, 0x9a, 0x97, 0x2d, 0xd0,
- 0x5f, 0x68, 0xca, 0x41, 0xee, 0x67, 0xf3, 0x77, 0xed, 0x21, 0x69, 0x30,
- 0xa7, 0x18, 0xe8, 0x95, 0xca, 0x02, 0xf2, 0xf9, 0x22, 0xe9, 0x53, 0x6e,
- 0x7b, 0xd5, 0xef, 0x71, 0x8c, 0xf7, 0x39, 0xbe, 0x1f, 0x10, 0xa2, 0x6e,
- 0xee, 0x34, 0x97, 0x2d, 0xee, 0x67, 0x4e, 0x49, 0x0d, 0xfa, 0xfb, 0xe7,
- 0x31, 0xee, 0xb7, 0xe7, 0xd4, 0xf9, 0xdb, 0x4a, 0x6d, 0x02, 0xb9, 0xc3,
- 0x9d, 0xe6, 0x9c, 0x75, 0x56, 0xe9, 0xad, 0x56, 0x7e, 0xc2, 0x6b, 0xe7,
- 0x35, 0xef, 0x35, 0x32, 0xdb, 0x06, 0x98, 0xaf, 0x3e, 0x81, 0x7c, 0x81,
- 0xb9, 0xea, 0x04, 0xf0, 0x1a, 0x65, 0x12, 0x91, 0xd9, 0x22, 0x69, 0x49,
- 0x68, 0x13, 0xf2, 0xfb, 0x9c, 0x8c, 0x83, 0x9f, 0x08, 0x72, 0x7b, 0xc6,
- 0x87, 0x47, 0x65, 0x39, 0xe4, 0xc6, 0x01, 0x9e, 0xfb, 0x5a, 0x46, 0x6c,
- 0x58, 0x5e, 0x8d, 0x0d, 0x5b, 0x71, 0xdd, 0xc8, 0xc4, 0x07, 0xfe, 0x06,
- 0xf4, 0x59, 0xb7, 0x61, 0x6c, 0x18, 0x45, 0x7f, 0xb6, 0xf5, 0xca, 0xec,
- 0x02, 0x92, 0x08, 0xe4, 0x2c, 0x15, 0xe1, 0x99, 0x8e, 0xac, 0x9c, 0xaa,
- 0xf5, 0x87, 0x2f, 0x6b, 0x69, 0x75, 0xf6, 0x23, 0x36, 0xc0, 0xf3, 0x2c,
- 0xbd, 0x52, 0x5b, 0x90, 0x88, 0x91, 0x78, 0x52, 0x9c, 0x9a, 0x8b, 0xd9,
- 0xe7, 0x34, 0x9e, 0x69, 0xb1, 0xa5, 0xb6, 0xb6, 0x8f, 0x89, 0xdc, 0x57,
- 0xbe, 0xe3, 0xf5, 0x49, 0xab, 0x3e, 0x7f, 0xdd, 0xc3, 0x3d, 0xb4, 0x9a,
- 0xd3, 0x03, 0x1e, 0xc8, 0xdb, 0xc3, 0xad, 0xe3, 0x46, 0xee, 0x8e, 0xcb,
- 0x31, 0x91, 0xcd, 0x6c, 0xb1, 0x31, 0xee, 0x4d, 0x3c, 0xf3, 0x24, 0xf8,
- 0xb8, 0x63, 0xe8, 0xd6, 0x93, 0x52, 0xa8, 0xad, 0x1f, 0xa3, 0x95, 0x07,
- 0x3e, 0x43, 0xfa, 0x1c, 0xe7, 0x00, 0xf8, 0xbb, 0xa3, 0xe9, 0xd6, 0x01,
- 0xc8, 0xd2, 0x1d, 0xc3, 0x38, 0x13, 0x35, 0x7f, 0x2a, 0x03, 0xa2, 0x9f,
- 0xd3, 0x94, 0xfc, 0xf5, 0xca, 0x30, 0x16, 0x48, 0x46, 0xba, 0x96, 0x26,
- 0xc5, 0x58, 0x62, 0x0d, 0xe1, 0xb5, 0xce, 0xb4, 0xda, 0xbf, 0xdd, 0x84,
- 0xf5, 0x2d, 0x76, 0xc0, 0x62, 0xbd, 0x80, 0xf5, 0xe0, 0x9f, 0x6e, 0x96,
- 0x1e, 0xd6, 0x0b, 0x98, 0x37, 0xec, 0xc7, 0x37, 0x73, 0x87, 0x4b, 0x4d,
- 0xe4, 0x7a, 0x9b, 0x19, 0x5f, 0x73, 0x35, 0xde, 0x8f, 0x46, 0x44, 0x78,
- 0x8f, 0x7e, 0xa3, 0x57, 0xda, 0xbe, 0x35, 0x08, 0x5f, 0xf1, 0x34, 0xb0,
- 0x37, 0xe8, 0x9e, 0x1c, 0x90, 0x80, 0x7b, 0x66, 0x42, 0xd5, 0x5b, 0xde,
- 0x58, 0x88, 0x7a, 0xef, 0x73, 0xc9, 0xb6, 0xcb, 0x71, 0xd6, 0x44, 0xfb,
- 0x58, 0xf3, 0x41, 0x3f, 0xd1, 0x97, 0x91, 0x9f, 0x5e, 0xaf, 0x59, 0x9b,
- 0x79, 0x7e, 0xf3, 0x86, 0x83, 0x6b, 0x62, 0xff, 0x90, 0xc2, 0x98, 0xde,
- 0x3d, 0xfe, 0x46, 0xbe, 0xf4, 0x8e, 0x77, 0x13, 0x98, 0x4f, 0x4d, 0x7a,
- 0x67, 0xe7, 0x1a, 0x99, 0xa3, 0x6b, 0x72, 0xaa, 0x41, 0x55, 0xef, 0x6d,
- 0x38, 0x16, 0xfc, 0xe3, 0x08, 0xec, 0x93, 0x6b, 0xa0, 0xa9, 0x3d, 0x01,
- 0x6c, 0x16, 0xe9, 0x55, 0x39, 0xd1, 0xf1, 0x27, 0xc4, 0xb5, 0x77, 0x58,
- 0x99, 0xf2, 0x65, 0x8d, 0xb2, 0x9b, 0x83, 0x2c, 0x97, 0x33, 0xf2, 0x47,
- 0xce, 0x15, 0x55, 0x6b, 0x9d, 0x47, 0x5e, 0x12, 0x38, 0xa5, 0x72, 0xb2,
- 0x16, 0x7c, 0x0b, 0xbf, 0xf7, 0xe2, 0xd7, 0xb1, 0x16, 0xa3, 0xea, 0x8c,
- 0x82, 0x7e, 0xae, 0xd9, 0x4c, 0xc1, 0x7f, 0xe8, 0x96, 0x65, 0x16, 0x10,
- 0x0f, 0x53, 0xea, 0x9c, 0x0b, 0xd7, 0xf1, 0x6f, 0x2b, 0xff, 0x2c, 0x15,
- 0xc8, 0xe6, 0x4c, 0x04, 0x74, 0x34, 0x65, 0x9f, 0x86, 0xd2, 0xc3, 0x13,
- 0x0a, 0xf3, 0x1a, 0xe7, 0xe0, 0xb0, 0x96, 0x06, 0x44, 0xce, 0x65, 0x64,
- 0x0e, 0x6b, 0x38, 0xb0, 0x44, 0x1d, 0x50, 0xb6, 0x93, 0xd2, 0x06, 0xd9,
- 0x1f, 0x01, 0xf6, 0x30, 0x4e, 0x51, 0xc6, 0x61, 0xac, 0x8b, 0x5e, 0x09,
- 0x9c, 0x81, 0x8c, 0x4f, 0x01, 0x23, 0x2c, 0xb4, 0xcb, 0xf7, 0x6a, 0xbe,
- 0x4c, 0x2f, 0xf1, 0x5c, 0xbf, 0x3e, 0x35, 0xd2, 0x47, 0x1c, 0x25, 0xd5,
- 0xda, 0x9c, 0xcc, 0x9d, 0x66, 0xce, 0x3e, 0xa9, 0xce, 0x0c, 0x04, 0xd4,
- 0x99, 0x15, 0x37, 0x67, 0x76, 0xbf, 0x5d, 0x8c, 0x59, 0x15, 0xee, 0xb5,
- 0x09, 0x6c, 0x67, 0x18, 0xe3, 0x6e, 0x24, 0x5f, 0x37, 0x57, 0x1d, 0x07,
- 0xbf, 0x97, 0xe7, 0xa3, 0x99, 0xbc, 0xc4, 0x79, 0x76, 0x7a, 0xc2, 0xc6,
- 0xfc, 0x97, 0xe1, 0x3f, 0xe7, 0x4a, 0x3c, 0x27, 0x5d, 0xc0, 0x0a, 0xcb,
- 0xc8, 0xe5, 0x22, 0x73, 0xc6, 0x8f, 0x43, 0x6f, 0xbc, 0x2e, 0x8c, 0x1a,
- 0xf0, 0x03, 0x2b, 0xea, 0xdd, 0xcf, 0xa8, 0xdd, 0x40, 0x0e, 0x1b, 0xd1,
- 0xf6, 0x43, 0xd7, 0x79, 0xb3, 0xcd, 0xb3, 0x07, 0x9e, 0xc5, 0x3f, 0x0b,
- 0x3f, 0x7a, 0x5e, 0xf8, 0x4e, 0xd6, 0xed, 0x26, 0xf3, 0xa5, 0xab, 0xf0,
- 0x7b, 0x99, 0x58, 0x06, 0x36, 0x94, 0x0f, 0x77, 0x80, 0xe7, 0xdf, 0xc4,
- 0xbd, 0x9c, 0xc3, 0x71, 0xa2, 0xf1, 0x15, 0x29, 0x44, 0x02, 0x32, 0x14,
- 0xb9, 0x22, 0x9b, 0xe1, 0xc9, 0x34, 0x79, 0xdd, 0x8a, 0x8e, 0x8a, 0xa6,
- 0xe8, 0x0d, 0xee, 0x86, 0x0d, 0xde, 0x84, 0xbf, 0x6b, 0xf7, 0x72, 0xfd,
- 0x54, 0x91, 0x18, 0xea, 0x59, 0x75, 0xb6, 0xe0, 0xaa, 0xc5, 0x3a, 0x20,
- 0xdf, 0xc5, 0xfe, 0x1f, 0x6a, 0x8c, 0xbb, 0x7b, 0x77, 0xac, 0x43, 0x93,
- 0x3f, 0x77, 0x8e, 0xbb, 0x2c, 0x97, 0x47, 0xd2, 0x69, 0x6b, 0xa1, 0x73,
- 0xd9, 0xa3, 0x73, 0xd6, 0xa3, 0x53, 0xf1, 0xe8, 0x5c, 0x5d, 0xa5, 0xb3,
- 0x07, 0x76, 0xd0, 0x6c, 0x9e, 0x00, 0xde, 0x48, 0xc6, 0x9b, 0xcd, 0x34,
- 0xf2, 0xb2, 0xd9, 0xe1, 0x69, 0xb5, 0xe7, 0xaa, 0x27, 0x46, 0xc7, 0x93,
- 0x96, 0x2b, 0x7f, 0x58, 0x81, 0x4c, 0xc3, 0x1e, 0xf3, 0xe2, 0x62, 0x75,
- 0xee, 0x07, 0xba, 0xfb, 0x85, 0x5d, 0xf0, 0x03, 0x4f, 0x23, 0x96, 0x5c,
- 0x1c, 0x3f, 0x6f, 0x49, 0x7e, 0xdb, 0x27, 0x75, 0xd8, 0x7b, 0x0f, 0xdf,
- 0x27, 0x35, 0xa5, 0xeb, 0xe2, 0x78, 0xb5, 0xf6, 0x34, 0xf2, 0x23, 0xf6,
- 0xdf, 0x4e, 0x0c, 0xb6, 0xab, 0x52, 0x8b, 0xec, 0x3a, 0xcb, 0xfd, 0x21,
- 0xf4, 0xab, 0xd4, 0xba, 0x21, 0xf7, 0x6e, 0x55, 0x57, 0xb9, 0x52, 0x0c,
- 0x41, 0x8f, 0x26, 0x6c, 0x3e, 0x84, 0xb6, 0x30, 0xec, 0xa0, 0x0f, 0xed,
- 0x3f, 0xc7, 0xda, 0x8e, 0xa0, 0x7d, 0xa5, 0x73, 0x5c, 0xe1, 0x58, 0x4b,
- 0xce, 0x39, 0x37, 0x11, 0x73, 0xdf, 0x84, 0x1f, 0x1d, 0x44, 0x9f, 0x61,
- 0xf4, 0xf9, 0x14, 0xc6, 0xe1, 0x3b, 0xcd, 0x1b, 0xf1, 0xd4, 0x00, 0x4f,
- 0x7a, 0x0b, 0x4f, 0x0d, 0xf0, 0x03, 0xdf, 0x79, 0x92, 0x35, 0xe8, 0x61,
- 0x39, 0x5a, 0xe4, 0x19, 0x29, 0xbe, 0x17, 0x6f, 0x4a, 0x00, 0x98, 0xb4,
- 0xed, 0x64, 0x34, 0xdc, 0x50, 0xb5, 0x1e, 0xda, 0xd6, 0x50, 0xbc, 0x2a,
- 0x2a, 0xce, 0x44, 0x8e, 0x22, 0x7e, 0xdd, 0x74, 0xba, 0xe5, 0x75, 0x6f,
- 0xac, 0x15, 0xe1, 0xfe, 0xe5, 0xda, 0xb1, 0x8e, 0x95, 0xae, 0x8d, 0xbf,
- 0x6a, 0x19, 0xde, 0xbc, 0x7a, 0x31, 0xd6, 0xaf, 0xa2, 0xef, 0xb5, 0xf1,
- 0xcb, 0xb5, 0x8d, 0xfa, 0xde, 0x44, 0xdf, 0xb6, 0x96, 0xbe, 0x37, 0xd1,
- 0xaf, 0x1b, 0x71, 0xb0, 0x5b, 0xcd, 0x69, 0x16, 0x7c, 0x5d, 0x2f, 0xaa,
- 0xf7, 0xb4, 0x21, 0x77, 0x8e, 0x69, 0x12, 0x53, 0x67, 0xdc, 0x5a, 0x49,
- 0xd4, 0x8c, 0x68, 0xef, 0xa8, 0xf7, 0x28, 0x1b, 0x18, 0xb3, 0x80, 0x7b,
- 0xe7, 0x27, 0xb4, 0x54, 0x35, 0x87, 0x98, 0xf5, 0x30, 0xf1, 0x53, 0xdc,
- 0x46, 0xcc, 0xac, 0x80, 0x5e, 0xad, 0xd8, 0xe0, 0x79, 0x6a, 0xd8, 0xc5,
- 0x2d, 0xe2, 0xec, 0x87, 0x0d, 0x75, 0xae, 0x21, 0xad, 0x6a, 0x76, 0x95,
- 0xa2, 0x98, 0xc9, 0x11, 0x9e, 0x65, 0xf8, 0x0c, 0xd6, 0xe5, 0x57, 0xd0,
- 0x96, 0x44, 0x7c, 0x3c, 0xa0, 0x25, 0xcf, 0x8f, 0xe3, 0xfa, 0x49, 0x5c,
- 0xc3, 0x1f, 0x2f, 0x64, 0x71, 0xff, 0x49, 0x5c, 0x4f, 0x6b, 0xa9, 0x7a,
- 0x16, 0xd7, 0x4f, 0xe1, 0x7a, 0xca, 0x64, 0x9e, 0xf2, 0xaa, 0x95, 0xd1,
- 0x6c, 0xd0, 0xb2, 0xcf, 0x8f, 0xe3, 0xd3, 0x4a, 0x8f, 0xf7, 0xa0, 0xa7,
- 0x22, 0xf7, 0xda, 0x62, 0xe0, 0x69, 0x9f, 0x96, 0xae, 0x76, 0x81, 0xc6,
- 0x00, 0x9e, 0xa7, 0x4d, 0xed, 0xf7, 0xc6, 0x67, 0xcd, 0xe9, 0x63, 0xaa,
- 0xe6, 0x64, 0x24, 0x32, 0xc0, 0xc9, 0x87, 0x91, 0x07, 0x68, 0x92, 0xb6,
- 0x9e, 0x93, 0x42, 0x1c, 0x7e, 0xa5, 0x6a, 0x48, 0x2a, 0x94, 0xc7, 0xef,
- 0xbc, 0x24, 0x47, 0x71, 0xbf, 0x4a, 0x5b, 0x60, 0xbf, 0x3f, 0x95, 0x42,
- 0x99, 0xb8, 0x9f, 0x75, 0x26, 0xd6, 0xa6, 0x58, 0x5f, 0xca, 0x41, 0x06,
- 0x21, 0xda, 0xef, 0x06, 0x35, 0x31, 0xf7, 0x8c, 0x34, 0xe2, 0xb2, 0x96,
- 0xac, 0x72, 0xdf, 0xaf, 0x91, 0xb9, 0x6c, 0xf1, 0xfd, 0xb1, 0x69, 0xee,
- 0x23, 0x16, 0x8c, 0x04, 0xeb, 0x23, 0xaa, 0xbe, 0x1e, 0x77, 0xf7, 0x07,
- 0x5b, 0xcf, 0xa4, 0xf8, 0xeb, 0x85, 0xe3, 0x7e, 0x0d, 0xcf, 0xbb, 0xf5,
- 0xac, 0x54, 0xfd, 0x9d, 0xba, 0xe0, 0x3b, 0x00, 0xe7, 0xa0, 0x8b, 0xcb,
- 0x2a, 0x37, 0xe6, 0x1e, 0xee, 0xbb, 0xe5, 0x54, 0xc8, 0x61, 0x8a, 0xac,
- 0x91, 0xf9, 0xfb, 0x76, 0xbe, 0x1c, 0xd7, 0xf3, 0x4a, 0x3e, 0x67, 0x40,
- 0x53, 0xe2, 0xf4, 0xbb, 0xd9, 0x10, 0xf7, 0xdf, 0xf8, 0x8c, 0x7c, 0xf3,
- 0x2e, 0xdf, 0xe4, 0x99, 0xf2, 0x38, 0x0c, 0xff, 0xc9, 0xf7, 0x2b, 0x9e,
- 0x93, 0x5c, 0x9c, 0x35, 0x1e, 0x03, 0xb1, 0x31, 0x8f, 0xdf, 0x77, 0xe5,
- 0x37, 0xeb, 0xc9, 0x2f, 0x57, 0xfe, 0x2f, 0x4a, 0x87, 0x15, 0x8b, 0xe3,
- 0xf9, 0xb5, 0x8f, 0xbd, 0x4a, 0x77, 0x15, 0x75, 0x7e, 0xd7, 0x97, 0x81,
- 0x5f, 0xbf, 0xdb, 0xd8, 0xf6, 0xc6, 0x2d, 0xf2, 0xf6, 0x10, 0xcf, 0x43,
- 0x0c, 0xda, 0x42, 0xfe, 0x39, 0x0f, 0xc6, 0x30, 0x7f, 0xaf, 0xd5, 0x9f,
- 0x83, 0x3f, 0xcf, 0xfb, 0x95, 0x0f, 0xf9, 0xfd, 0xe4, 0x16, 0xe9, 0xca,
- 0x98, 0x86, 0xc5, 0xd8, 0xf0, 0xb8, 0xb7, 0x3f, 0xf0, 0x7f, 0x43, 0xce,
- 0xae, 0x2c, 0x02, 0x09, 0x99, 0xf5, 0xde, 0xbf, 0xde, 0xc0, 0x1e, 0xd6,
- 0xef, 0x35, 0x37, 0x32, 0x67, 0xad, 0xbb, 0xf3, 0xae, 0x6c, 0x30, 0xef,
- 0x8a, 0x37, 0xef, 0xea, 0x7d, 0xf2, 0x5b, 0x99, 0xb7, 0x31, 0x67, 0xda,
- 0xdc, 0x46, 0xf6, 0x28, 0xea, 0xdd, 0xb0, 0x15, 0x23, 0x18, 0xb4, 0x9d,
- 0x7b, 0xd5, 0x50, 0x99, 0x57, 0xbb, 0x76, 0x79, 0x16, 0xb1, 0xb0, 0x5c,
- 0x76, 0x73, 0xec, 0xb2, 0xc3, 0x5a, 0xf6, 0xbb, 0xf1, 0xc0, 0x77, 0xb9,
- 0xbe, 0xa8, 0xce, 0xbb, 0xcc, 0x3a, 0x6e, 0xdd, 0xab, 0x5c, 0x6e, 0x8d,
- 0xa9, 0x0f, 0x32, 0x9e, 0x0e, 0xe6, 0x65, 0x82, 0xef, 0x94, 0xe3, 0xfa,
- 0x11, 0xb9, 0xb2, 0xa0, 0xf6, 0xac, 0xbc, 0xbd, 0x21, 0xee, 0xf9, 0xa8,
- 0xfd, 0x6f, 0xf8, 0xb5, 0x49, 0xe5, 0xd7, 0x97, 0x17, 0xd4, 0x3d, 0x17,
- 0x2b, 0x39, 0x13, 0xf0, 0xfb, 0xc8, 0x25, 0xac, 0x07, 0xa4, 0x80, 0x9c,
- 0xfb, 0xac, 0x75, 0x78, 0x0b, 0x71, 0x0e, 0x69, 0x2d, 0x83, 0xd6, 0xe5,
- 0x05, 0xd9, 0xc2, 0x33, 0x25, 0x65, 0xb5, 0xcf, 0xe6, 0xd6, 0xc5, 0xa7,
- 0xc5, 0xff, 0x7f, 0x1d, 0x41, 0x2f, 0x16, 0xf2, 0x5c, 0x0b, 0xdf, 0x73,
- 0xa6, 0xaf, 0x40, 0x1e, 0x34, 0xc1, 0x7d, 0x9c, 0x66, 0xd3, 0xad, 0x9b,
- 0x37, 0xb1, 0x2e, 0xda, 0xf8, 0x0e, 0x05, 0xfe, 0x0e, 0xc3, 0x7e, 0xb0,
- 0x4e, 0x56, 0xdb, 0x79, 0xcd, 0xdc, 0xc3, 0xbf, 0x66, 0x60, 0xfb, 0x3f,
- 0xe8, 0xf3, 0x49, 0x14, 0x38, 0x46, 0x00, 0x00, 0x00 };
+ 0xbd, 0x7c, 0x7d, 0x70, 0x1c, 0xe7, 0x79, 0xdf, 0xb3, 0xbb, 0x07, 0xe0,
+ 0x00, 0x82, 0xe0, 0x12, 0x39, 0x52, 0x27, 0x0a, 0xa6, 0x6e, 0x89, 0x3d,
+ 0x08, 0x32, 0x20, 0x71, 0xc5, 0x20, 0x36, 0x26, 0xb9, 0xca, 0xab, 0xbb,
+ 0x03, 0x78, 0x94, 0x31, 0x31, 0xc4, 0xc2, 0x16, 0xed, 0x70, 0xd4, 0xeb,
+ 0x01, 0xa4, 0x95, 0x54, 0x9e, 0xb2, 0xb6, 0xda, 0x72, 0x5a, 0x35, 0x3a,
+ 0x1f, 0xc0, 0x0f, 0x29, 0x47, 0x1c, 0x24, 0xc0, 0x84, 0xfe, 0x70, 0x93,
+ 0x13, 0x0e, 0x24, 0x64, 0xf7, 0x88, 0x93, 0xfc, 0xd9, 0x3f, 0x62, 0x0b,
+ 0x03, 0xd2, 0xb4, 0x5a, 0xbb, 0xb5, 0xda, 0x28, 0x13, 0xcf, 0xf4, 0x63,
+ 0x30, 0x14, 0xa5, 0x28, 0x71, 0xa7, 0x56, 0x9b, 0x4c, 0xa2, 0x36, 0x94,
+ 0xaf, 0xbf, 0xdf, 0xbb, 0xbb, 0xe0, 0x01, 0x22, 0x65, 0x51, 0x93, 0x14,
+ 0x33, 0x37, 0x77, 0xfb, 0xee, 0xbb, 0xef, 0xfb, 0x7c, 0xbd, 0xcf, 0xf3,
+ 0xfc, 0x9e, 0xf7, 0x5d, 0x44, 0x45, 0xda, 0xc4, 0xff, 0xdb, 0x8a, 0x4f,
+ 0xec, 0xd8, 0xf1, 0xc7, 0xef, 0xfd, 0xf8, 0xbd, 0xbf, 0x8a, 0x9f, 0xf7,
+ 0x89, 0xd6, 0x62, 0xf0, 0xe6, 0x5b, 0x86, 0x48, 0xf6, 0xcf, 0xe5, 0x43,
+ 0xff, 0xe1, 0x71, 0x33, 0x18, 0x9f, 0x1f, 0x09, 0xeb, 0x89, 0x57, 0x87,
+ 0x93, 0xb6, 0x84, 0x8d, 0x44, 0xfe, 0xa1, 0x71, 0x5b, 0xc4, 0xad, 0xf6,
+ 0xc5, 0x52, 0xf2, 0x6e, 0x3d, 0x1f, 0x09, 0x09, 0xdb, 0x3f, 0x92, 0xb8,
+ 0xf6, 0xe4, 0xf7, 0x3e, 0x6e, 0xbd, 0x5d, 0x36, 0x24, 0x6c, 0x26, 0xb2,
+ 0x62, 0xf6, 0x48, 0xb8, 0x0b, 0xcf, 0x7c, 0xf5, 0xae, 0x47, 0x0d, 0xe9,
+ 0x08, 0xc6, 0x7a, 0xab, 0xfe, 0xbd, 0xbb, 0x24, 0xbf, 0x2b, 0x51, 0x8f,
+ 0x85, 0x12, 0xef, 0xd6, 0xa7, 0x06, 0xc2, 0xa2, 0x27, 0xac, 0x68, 0xd2,
+ 0x88, 0xc8, 0xcb, 0x35, 0x53, 0x5e, 0xac, 0xc5, 0x64, 0xb2, 0x26, 0x1d,
+ 0xe9, 0xda, 0x8d, 0x68, 0xaa, 0xa3, 0xef, 0xbb, 0xf5, 0xe4, 0x40, 0x28,
+ 0x6b, 0x24, 0xa4, 0x23, 0x59, 0x93, 0xd1, 0x63, 0xc5, 0xd6, 0x87, 0x9b,
+ 0x12, 0x4f, 0xd6, 0x75, 0x5b, 0xb2, 0xa1, 0x84, 0x9d, 0xd7, 0xf5, 0xf6,
+ 0x41, 0xf3, 0x63, 0x68, 0xaf, 0x0e, 0x86, 0x26, 0x8b, 0xa6, 0x9c, 0x1b,
+ 0x68, 0x15, 0xdd, 0x0e, 0x4b, 0xb2, 0xd6, 0xfa, 0xb0, 0x9e, 0x88, 0x88,
+ 0x5b, 0xab, 0xd7, 0x8f, 0x39, 0xff, 0x64, 0xaf, 0xf9, 0xeb, 0xe1, 0xf0,
+ 0x64, 0x51, 0xde, 0x0e, 0xd9, 0x76, 0x74, 0x42, 0x7a, 0xcc, 0x9c, 0x68,
+ 0x92, 0xec, 0xef, 0x89, 0x1e, 0xc1, 0xf7, 0x78, 0x7f, 0xdc, 0x4c, 0xc9,
+ 0x16, 0x71, 0xcd, 0x6f, 0xae, 0x98, 0x3d, 0x5d, 0x59, 0x3d, 0x11, 0x96,
+ 0x74, 0x51, 0x13, 0xc3, 0x8e, 0xc8, 0x64, 0xc5, 0x96, 0xfc, 0x52, 0x87,
+ 0xe4, 0x2b, 0xf2, 0xc4, 0x94, 0xd3, 0x2e, 0x53, 0x4b, 0x47, 0x7d, 0x5d,
+ 0x44, 0xd0, 0xd6, 0x2b, 0xf9, 0x5a, 0x14, 0x9f, 0x9f, 0xf8, 0xfc, 0xea,
+ 0x22, 0x3b, 0x05, 0xcf, 0xf7, 0xa7, 0xdd, 0xea, 0xd7, 0xc2, 0x5e, 0xdb,
+ 0x7f, 0xd9, 0xe2, 0x7d, 0x83, 0xdf, 0x12, 0xf8, 0x2d, 0x85, 0x65, 0xcd,
+ 0x88, 0xca, 0xf7, 0xee, 0x8a, 0xc9, 0x54, 0x69, 0x0d, 0xb2, 0x89, 0xca,
+ 0x37, 0x6a, 0x11, 0x79, 0x49, 0xc9, 0x22, 0xa4, 0x0d, 0xa3, 0xcf, 0x64,
+ 0x69, 0x42, 0x3f, 0x51, 0xcc, 0x4b, 0xaa, 0x96, 0xd5, 0x0b, 0x73, 0x66,
+ 0x47, 0x72, 0x29, 0xa7, 0x4f, 0xce, 0x75, 0x76, 0xa4, 0x96, 0x26, 0xf4,
+ 0x42, 0x31, 0x0a, 0x39, 0x98, 0x1d, 0xa9, 0xf9, 0x08, 0xae, 0x3b, 0x3b,
+ 0x92, 0xf3, 0xd6, 0x0c, 0x26, 0x45, 0x9f, 0x68, 0x47, 0xaa, 0x64, 0x65,
+ 0x45, 0xba, 0x9d, 0x1f, 0x48, 0x57, 0x47, 0xaa, 0xf6, 0x5b, 0xfa, 0x8a,
+ 0xa9, 0x49, 0xe1, 0x1e, 0x31, 0xa3, 0x89, 0xb7, 0xeb, 0xb7, 0xdb, 0x9a,
+ 0x98, 0xf6, 0x3b, 0xf5, 0xed, 0x90, 0x4d, 0x6e, 0xb6, 0x15, 0xbc, 0x92,
+ 0x26, 0x53, 0x72, 0xf3, 0x7d, 0xe6, 0xaa, 0x34, 0x89, 0x1b, 0x09, 0xae,
+ 0xeb, 0xf5, 0xa4, 0xf3, 0x07, 0xe4, 0x91, 0xf2, 0xee, 0x18, 0x86, 0x5e,
+ 0x92, 0xa0, 0x39, 0xe9, 0xbc, 0x5b, 0xf7, 0x9e, 0x09, 0x63, 0xce, 0x50,
+ 0xc7, 0x50, 0xa9, 0x5e, 0x4f, 0x3b, 0x18, 0xdf, 0x09, 0x9e, 0x6d, 0x92,
+ 0x72, 0xc4, 0x2d, 0x4f, 0x3a, 0x96, 0xe1, 0xc9, 0x87, 0xba, 0xe7, 0xb5,
+ 0x0b, 0x7d, 0xe4, 0x25, 0x17, 0x91, 0x72, 0xc1, 0xf9, 0x98, 0x3c, 0xe5,
+ 0x44, 0xc1, 0x5f, 0x58, 0x4e, 0x39, 0xb0, 0x2f, 0xfb, 0xb8, 0x96, 0xac,
+ 0x59, 0xb1, 0xac, 0x3c, 0x2d, 0xc9, 0xf9, 0x6e, 0x33, 0x2d, 0x98, 0xdb,
+ 0xae, 0xdf, 0x99, 0x74, 0x30, 0x5f, 0xff, 0xff, 0xad, 0xbb, 0x11, 0x2b,
+ 0x5b, 0x96, 0x5e, 0x29, 0x94, 0xba, 0x9d, 0x1f, 0x43, 0x4f, 0x61, 0x5b,
+ 0xdc, 0x71, 0xdb, 0x84, 0xdc, 0xac, 0xde, 0x94, 0x51, 0x97, 0x07, 0x31,
+ 0x7f, 0xd2, 0xc6, 0xfd, 0x9a, 0x6c, 0xd3, 0xed, 0x66, 0x29, 0x98, 0x12,
+ 0x69, 0x93, 0xdd, 0x52, 0x98, 0x45, 0xbb, 0xe3, 0x76, 0xea, 0x78, 0x26,
+ 0x33, 0xc0, 0x36, 0xd1, 0x8c, 0x04, 0x75, 0x2c, 0xb2, 0x50, 0xed, 0xc5,
+ 0xfc, 0x71, 0xb7, 0x55, 0x33, 0x65, 0xcd, 0x0c, 0x49, 0xa5, 0x1a, 0x77,
+ 0xa3, 0x5a, 0xb3, 0x9c, 0x8a, 0xb7, 0x41, 0xa6, 0x51, 0x8c, 0x2d, 0x5f,
+ 0xd6, 0x13, 0xf1, 0x68, 0x0e, 0x4a, 0xa3, 0x1d, 0x4d, 0x81, 0x9e, 0x29,
+ 0x27, 0xab, 0xa5, 0x6a, 0x9f, 0xd3, 0x92, 0x4b, 0x87, 0xb4, 0xfd, 0x4b,
+ 0xe8, 0x53, 0xfb, 0x1f, 0xbe, 0x0d, 0x44, 0x41, 0x9b, 0x8e, 0x67, 0xd9,
+ 0x0e, 0x9a, 0x15, 0xed, 0x68, 0x83, 0x2e, 0x57, 0xc6, 0x22, 0x1d, 0x49,
+ 0xa5, 0x4b, 0xd2, 0xa6, 0x4b, 0x6e, 0x54, 0x93, 0x4e, 0xdb, 0x95, 0xf0,
+ 0xaf, 0x41, 0x9f, 0xf3, 0xd0, 0xe5, 0x7c, 0x4c, 0x4e, 0x94, 0x24, 0xa2,
+ 0x0b, 0xe7, 0xca, 0xea, 0x95, 0x2a, 0xed, 0x01, 0xba, 0x85, 0xee, 0x0b,
+ 0x55, 0x3e, 0x0b, 0x1d, 0x96, 0xd2, 0x90, 0x4f, 0x06, 0x73, 0x1f, 0xd4,
+ 0x1e, 0xac, 0x8c, 0x69, 0x19, 0xd8, 0x49, 0x61, 0xb6, 0x0f, 0xba, 0xb3,
+ 0x62, 0x6b, 0xb2, 0x4d, 0x0a, 0xb6, 0x1d, 0xfb, 0xac, 0xb4, 0xcb, 0xa9,
+ 0x79, 0x5b, 0x4e, 0xcc, 0xc3, 0x1e, 0x4d, 0xcb, 0x5c, 0x94, 0xae, 0xec,
+ 0x96, 0x44, 0x87, 0x3c, 0x3d, 0x6b, 0x65, 0xca, 0xd2, 0xed, 0xbe, 0x81,
+ 0xfb, 0xb9, 0x33, 0xd4, 0xa9, 0xe4, 0x53, 0x8e, 0x21, 0x59, 0x93, 0x76,
+ 0x7d, 0x9b, 0x26, 0x6d, 0xf5, 0x27, 0x93, 0x8e, 0x15, 0xa5, 0xcd, 0xa6,
+ 0x3e, 0xdd, 0x6d, 0x1e, 0x10, 0xcb, 0xcc, 0x50, 0xfe, 0x4e, 0x1f, 0xf4,
+ 0xf0, 0xbf, 0x29, 0x7b, 0x8c, 0x45, 0x1d, 0xf7, 0x45, 0x4f, 0x41, 0x97,
+ 0x59, 0xa5, 0xe3, 0x0e, 0xcc, 0x1f, 0xf2, 0x6d, 0x87, 0x6b, 0xe2, 0x6e,
+ 0xcd, 0x93, 0x43, 0x87, 0xcc, 0x54, 0xda, 0xa5, 0x00, 0x1d, 0x16, 0xc4,
+ 0x96, 0xc2, 0xd2, 0x5e, 0xbf, 0xdd, 0xc6, 0x7a, 0xf9, 0x53, 0x5d, 0xda,
+ 0x8e, 0x6b, 0x87, 0x6a, 0x3f, 0xd7, 0x7c, 0xfb, 0x81, 0xfd, 0x85, 0xc5,
+ 0x1d, 0x0d, 0xcb, 0xf9, 0x9a, 0x67, 0x7f, 0x0b, 0xf0, 0x3d, 0xae, 0xe9,
+ 0xc2, 0x96, 0xde, 0x5c, 0xef, 0x73, 0xbe, 0xd6, 0x85, 0x67, 0xc3, 0x72,
+ 0xa2, 0xc6, 0xfe, 0x79, 0xd8, 0x58, 0x58, 0x96, 0xef, 0x6a, 0x97, 0x2c,
+ 0xda, 0x0b, 0xf3, 0xe2, 0x26, 0x1d, 0x1d, 0xcf, 0x74, 0x80, 0x97, 0x9d,
+ 0xf8, 0xb4, 0xc9, 0x78, 0xa5, 0xc5, 0xe5, 0x7a, 0x1d, 0xaf, 0x51, 0xff,
+ 0xf8, 0x2e, 0x05, 0x36, 0x40, 0xf9, 0xb2, 0x9d, 0xcf, 0xb1, 0xdd, 0x44,
+ 0x7b, 0x63, 0x1b, 0x6d, 0x7b, 0x1b, 0x65, 0xda, 0xcb, 0x35, 0x9a, 0x2b,
+ 0xc5, 0xcd, 0x43, 0xfc, 0xae, 0xd1, 0x1e, 0x1a, 0x6d, 0x21, 0x84, 0xfe,
+ 0xd0, 0x63, 0x05, 0x73, 0xcd, 0x5e, 0xab, 0x37, 0x0d, 0xe0, 0xda, 0xfe,
+ 0x1d, 0xf0, 0xc9, 0xb9, 0x43, 0xa0, 0x4b, 0x97, 0x6c, 0x45, 0xd1, 0x16,
+ 0xa3, 0x0d, 0x78, 0x7c, 0x74, 0xc9, 0xe4, 0x7c, 0x7b, 0x47, 0x7a, 0x9e,
+ 0xed, 0xc9, 0xa8, 0x01, 0x3e, 0xc7, 0x1d, 0x59, 0x99, 0x72, 0xf4, 0xee,
+ 0x10, 0xe8, 0x9a, 0xc0, 0x82, 0x03, 0x1f, 0x3e, 0x8d, 0x2b, 0xb8, 0xdf,
+ 0x29, 0xe3, 0x4b, 0xec, 0xcb, 0x39, 0x0a, 0xdb, 0x75, 0x49, 0x80, 0x36,
+ 0x7c, 0x6c, 0x0b, 0xf7, 0x5b, 0x31, 0x4f, 0x3b, 0x6c, 0x67, 0x9a, 0xba,
+ 0xfb, 0x44, 0xd2, 0xe9, 0x94, 0xec, 0x7a, 0x5f, 0x81, 0xdd, 0xb1, 0x7f,
+ 0xef, 0xa6, 0xbe, 0x90, 0xef, 0x12, 0xc6, 0x9c, 0x6f, 0x85, 0x0c, 0xd9,
+ 0xae, 0x83, 0xe6, 0x16, 0xd0, 0x00, 0x1f, 0x6c, 0x77, 0x63, 0x3d, 0xb4,
+ 0x60, 0xfc, 0x2d, 0xe0, 0xa9, 0x55, 0x26, 0x66, 0x3b, 0xa1, 0x0b, 0x13,
+ 0x7d, 0xc3, 0xf2, 0x74, 0xc9, 0x82, 0x0d, 0xb0, 0x3f, 0x74, 0x30, 0x6f,
+ 0x45, 0x2b, 0xe2, 0xca, 0x94, 0xd3, 0x02, 0xfb, 0xaa, 0xd7, 0x8f, 0xc0,
+ 0x3e, 0xbe, 0xae, 0xfc, 0x45, 0x9f, 0x39, 0xa4, 0x49, 0xbe, 0x25, 0xf1,
+ 0x7d, 0xd0, 0x63, 0x3d, 0x2a, 0xc2, 0xeb, 0xbd, 0x1a, 0xd7, 0x2c, 0xe4,
+ 0xc8, 0xb9, 0xe1, 0x93, 0x76, 0x42, 0x86, 0xf4, 0x5b, 0x5d, 0xb0, 0xe7,
+ 0xa8, 0xf2, 0x27, 0x43, 0x37, 0xf4, 0x27, 0xd6, 0x68, 0x19, 0x73, 0x15,
+ 0x96, 0x42, 0xf4, 0x61, 0x83, 0x58, 0xae, 0xb2, 0x15, 0x6b, 0x6f, 0x52,
+ 0xd9, 0xc7, 0x4f, 0xc8, 0x6f, 0xfd, 0x53, 0x0e, 0xe9, 0x22, 0xbf, 0x2e,
+ 0x9e, 0xa5, 0x0d, 0x5a, 0xc7, 0x5d, 0x35, 0xff, 0x4f, 0xfc, 0xf9, 0x3d,
+ 0xda, 0x0b, 0xa5, 0x0e, 0x2d, 0xa5, 0x68, 0x08, 0xc6, 0x11, 0x59, 0x3d,
+ 0xd3, 0x6d, 0x3e, 0x08, 0x1b, 0xa6, 0x9f, 0x5a, 0xbd, 0x40, 0x1d, 0x63,
+ 0x8c, 0x01, 0xea, 0xd8, 0x54, 0xf4, 0x25, 0xe7, 0xb9, 0xf6, 0xa4, 0xcb,
+ 0x10, 0xfa, 0x08, 0xf8, 0x5c, 0xac, 0xc5, 0x49, 0x7f, 0x2d, 0xe6, 0xaa,
+ 0xb4, 0xbf, 0xc7, 0xf1, 0xac, 0x2e, 0x43, 0x71, 0xfa, 0x87, 0xa7, 0x25,
+ 0x05, 0x1f, 0x09, 0x3d, 0x4a, 0x05, 0xbc, 0x2c, 0x94, 0x1a, 0xfd, 0x16,
+ 0x6c, 0xab, 0xff, 0xaf, 0xeb, 0x9e, 0x3f, 0xa4, 0x6f, 0xa0, 0xaf, 0x29,
+ 0x98, 0x3a, 0x24, 0x87, 0xc8, 0xe0, 0x42, 0x37, 0x4e, 0xd2, 0xb0, 0x32,
+ 0x59, 0xc6, 0x1c, 0xbb, 0x2e, 0xf6, 0x7d, 0x82, 0x48, 0xda, 0xcb, 0xf8,
+ 0xb7, 0x2f, 0xf0, 0x4f, 0xab, 0xd5, 0x40, 0x17, 0xd4, 0x2b, 0xf5, 0x10,
+ 0xf8, 0x88, 0x90, 0x5c, 0x84, 0xef, 0x9a, 0x2a, 0xb5, 0xcb, 0x0a, 0x68,
+ 0xba, 0x54, 0x0d, 0x6c, 0xcd, 0xf0, 0x6d, 0x8d, 0xcf, 0xb4, 0xe3, 0xf9,
+ 0x10, 0xfc, 0x9a, 0xe4, 0x8d, 0x04, 0x7e, 0x17, 0x39, 0x26, 0xdb, 0x02,
+ 0x3b, 0xe7, 0x9a, 0xb1, 0xdc, 0xb2, 0x34, 0x4b, 0x26, 0x8e, 0xf8, 0x31,
+ 0xaf, 0x63, 0xae, 0x2e, 0xf8, 0xf2, 0x90, 0x1c, 0x2d, 0x45, 0xe4, 0xf3,
+ 0x25, 0xf2, 0x95, 0xd6, 0x52, 0xd0, 0x5b, 0x72, 0xbe, 0x0e, 0x9d, 0x0f,
+ 0xc3, 0xe7, 0x65, 0xb4, 0x21, 0xf8, 0x9f, 0x03, 0x95, 0xcf, 0x69, 0xe9,
+ 0xa5, 0xac, 0x36, 0x5c, 0x3b, 0xa4, 0x65, 0x96, 0xc6, 0xb4, 0xfd, 0x0d,
+ 0xbe, 0x48, 0xb4, 0xf7, 0xf7, 0x45, 0x4f, 0xcd, 0x72, 0xce, 0x6e, 0xe7,
+ 0xc6, 0xbe, 0xe8, 0xd7, 0xf5, 0x46, 0x5f, 0xd4, 0x0d, 0x5f, 0x94, 0x81,
+ 0x2f, 0x1a, 0xbe, 0x65, 0x5f, 0x34, 0xa2, 0xdf, 0xd8, 0x17, 0x1d, 0xd4,
+ 0xaf, 0xfb, 0x22, 0xc6, 0x9e, 0x15, 0x5c, 0x9b, 0xb2, 0x67, 0x5f, 0x20,
+ 0xe7, 0x28, 0xfc, 0xf0, 0x16, 0xc8, 0xba, 0x8d, 0x6b, 0x27, 0x56, 0x80,
+ 0xdd, 0x4f, 0x60, 0xae, 0xdf, 0x86, 0xbd, 0xef, 0x89, 0xdb, 0xe6, 0x43,
+ 0x6a, 0xde, 0xf7, 0xea, 0x7c, 0x68, 0x5d, 0xe7, 0xa4, 0xf1, 0x97, 0xea,
+ 0xdc, 0xf5, 0x74, 0x4e, 0x5d, 0xb7, 0xca, 0x11, 0x35, 0x6f, 0x5d, 0x42,
+ 0xf7, 0x09, 0xbc, 0x8a, 0x3c, 0x60, 0x24, 0x2c, 0x8c, 0xa7, 0x63, 0x7e,
+ 0xea, 0x2b, 0x0e, 0x1a, 0x04, 0xfa, 0x6d, 0x57, 0xbe, 0x68, 0x3f, 0xf4,
+ 0xbe, 0x5a, 0xbd, 0x35, 0x5d, 0x65, 0x1a, 0x74, 0xf5, 0xe0, 0x06, 0x5d,
+ 0xb5, 0x48, 0x7f, 0x3c, 0xd0, 0xd1, 0x36, 0x49, 0xc6, 0xa9, 0xb3, 0x5b,
+ 0xd1, 0xd5, 0xb9, 0xbf, 0x25, 0x5d, 0x7d, 0xf7, 0x26, 0xba, 0xfa, 0xde,
+ 0x26, 0x5d, 0xd9, 0xe6, 0x33, 0x1a, 0xc7, 0x66, 0xfc, 0xa0, 0x3f, 0xaa,
+ 0xdf, 0x39, 0xce, 0xfc, 0xa1, 0xc6, 0x35, 0x1d, 0xe4, 0x1d, 0x5c, 0xcf,
+ 0x2f, 0xd7, 0x0d, 0xdb, 0x86, 0xec, 0xb8, 0xa6, 0x29, 0x37, 0xcb, 0xfc,
+ 0x14, 0xe9, 0x47, 0xec, 0x18, 0x47, 0xac, 0xf1, 0x68, 0x68, 0x96, 0xf2,
+ 0x76, 0xaf, 0xff, 0x78, 0xa9, 0xfe, 0x73, 0x3d, 0xf1, 0x0b, 0xe4, 0x95,
+ 0xb6, 0x1f, 0x07, 0xc2, 0xf2, 0x85, 0x8a, 0x95, 0x75, 0xb5, 0x76, 0xc9,
+ 0xef, 0x40, 0xec, 0x29, 0xd1, 0x7f, 0xed, 0xbc, 0x49, 0x8c, 0xee, 0xf2,
+ 0x63, 0xf4, 0x9f, 0x81, 0x56, 0xe6, 0x57, 0xff, 0xe6, 0xdd, 0x95, 0x08,
+ 0xbf, 0xe3, 0xe6, 0x41, 0xf9, 0x2c, 0x79, 0x44, 0xbc, 0x67, 0xdc, 0xb7,
+ 0x99, 0xf3, 0xe4, 0x43, 0x89, 0x36, 0xc9, 0x6f, 0xe7, 0x7a, 0xa4, 0x9f,
+ 0xa3, 0xef, 0x6a, 0xf6, 0xe9, 0x0e, 0x72, 0x24, 0xfe, 0xb5, 0x18, 0x60,
+ 0x19, 0x7d, 0x90, 0x0f, 0x95, 0xc8, 0xc7, 0xbb, 0xbe, 0x3d, 0x31, 0x57,
+ 0x90, 0x26, 0xcf, 0x37, 0x8c, 0x20, 0x17, 0xa0, 0x1d, 0x04, 0x3a, 0xa7,
+ 0xbe, 0x99, 0x23, 0x48, 0x4c, 0xb7, 0x99, 0x23, 0x88, 0x69, 0x24, 0x0e,
+ 0x6a, 0x2e, 0x74, 0xef, 0x42, 0xf7, 0x2e, 0x74, 0xef, 0x42, 0xf7, 0xc9,
+ 0xda, 0x71, 0xdc, 0x53, 0x79, 0x08, 0x68, 0xf1, 0xc6, 0x4f, 0x7b, 0xe3,
+ 0x83, 0xce, 0x9d, 0x92, 0x53, 0x3a, 0x21, 0xbf, 0xc8, 0x35, 0x94, 0xbf,
+ 0x1e, 0xd6, 0x3c, 0x7f, 0xcd, 0xf1, 0x32, 0x78, 0xfe, 0x7e, 0xe4, 0x73,
+ 0xae, 0xae, 0xdb, 0xd7, 0x65, 0x32, 0xd5, 0x20, 0x93, 0xc9, 0x2a, 0x65,
+ 0xc4, 0xfe, 0xf4, 0xb9, 0x13, 0xfa, 0xc2, 0xba, 0x5c, 0x46, 0x40, 0x43,
+ 0x0b, 0x79, 0xf7, 0xf9, 0xe0, 0xf8, 0x9d, 0xfe, 0xf8, 0xbf, 0x81, 0x31,
+ 0xe9, 0x5f, 0x6f, 0x34, 0x2f, 0xe7, 0x64, 0xce, 0xf8, 0x7e, 0xfc, 0x20,
+ 0x67, 0xc6, 0x1a, 0x78, 0x69, 0x3d, 0x9f, 0x8e, 0x21, 0x9f, 0x7e, 0x07,
+ 0xb9, 0x74, 0xbd, 0xce, 0x38, 0x55, 0x40, 0x9e, 0x9b, 0x76, 0xb8, 0xae,
+ 0x6f, 0x65, 0xdd, 0x6e, 0x58, 0xb3, 0x66, 0xd2, 0xe0, 0xb8, 0x61, 0xf1,
+ 0xc6, 0xe4, 0xfd, 0x16, 0xe4, 0x82, 0xef, 0xe0, 0x37, 0x7d, 0x72, 0x90,
+ 0xe7, 0xb1, 0x0f, 0x9f, 0x7f, 0x15, 0x73, 0xf7, 0x03, 0xcf, 0xf4, 0xca,
+ 0x77, 0x6a, 0xb6, 0x7c, 0x1b, 0x98, 0xe6, 0x5b, 0xc8, 0x2d, 0xbe, 0x59,
+ 0x0b, 0x72, 0xfb, 0xbd, 0x30, 0x75, 0xe6, 0xf7, 0x12, 0xde, 0x69, 0x13,
+ 0x57, 0xe5, 0xf7, 0x7f, 0xda, 0x96, 0xad, 0x11, 0xfc, 0xfe, 0x95, 0x84,
+ 0x6c, 0xeb, 0xc4, 0xf7, 0xf6, 0x04, 0x4c, 0x27, 0xc1, 0xd8, 0xa8, 0x35,
+ 0xc4, 0x46, 0xd1, 0xd2, 0xe0, 0x71, 0x0a, 0xe3, 0xa5, 0xc1, 0xf7, 0x67,
+ 0x6a, 0x61, 0x2d, 0x35, 0xbb, 0x1b, 0x98, 0x24, 0xc8, 0x71, 0x91, 0x47,
+ 0x99, 0xab, 0xdb, 0x43, 0xf2, 0x36, 0x78, 0x4a, 0x82, 0x76, 0x17, 0x39,
+ 0xc0, 0x3f, 0xc5, 0x5c, 0xd6, 0x4f, 0x3f, 0x2d, 0xff, 0xda, 0xcf, 0xc3,
+ 0x9b, 0x64, 0x4e, 0xf1, 0xc8, 0x76, 0xc9, 0xfc, 0xcb, 0x9e, 0xeb, 0xed,
+ 0xcf, 0xae, 0xb7, 0xc7, 0x32, 0xbf, 0xb1, 0xde, 0x7e, 0x35, 0xe4, 0xe1,
+ 0x95, 0x41, 0x6d, 0xb4, 0xf6, 0x2f, 0x8c, 0x00, 0xeb, 0x14, 0x66, 0x7b,
+ 0x31, 0xd7, 0x36, 0x99, 0xb4, 0xdf, 0x06, 0xf6, 0xb2, 0x63, 0x39, 0xac,
+ 0xaf, 0xa7, 0x36, 0xf9, 0xfa, 0x36, 0xf8, 0x8f, 0xd3, 0xb3, 0xd6, 0x20,
+ 0xfd, 0x47, 0x1c, 0x6b, 0x29, 0xf9, 0x1e, 0xff, 0xf1, 0x6d, 0xa3, 0xd1,
+ 0x7f, 0x18, 0xf0, 0x1f, 0xfb, 0xdf, 0xc7, 0x7f, 0x3c, 0xf5, 0x1e, 0xff,
+ 0xa1, 0xc1, 0x2e, 0xe8, 0x3f, 0x7e, 0x68, 0x04, 0xfe, 0xa3, 0xb0, 0xc1,
+ 0x7f, 0x04, 0xfa, 0xb0, 0x55, 0xee, 0xe8, 0xfd, 0x26, 0xfe, 0x6c, 0xf3,
+ 0x31, 0xa7, 0x84, 0x43, 0x09, 0x37, 0x33, 0x65, 0xef, 0x92, 0x26, 0xac,
+ 0xd1, 0x97, 0x6b, 0x03, 0xf0, 0x25, 0xbf, 0x0f, 0x9c, 0x66, 0x39, 0x4c,
+ 0x44, 0x9a, 0x12, 0xd4, 0xcd, 0x48, 0x2c, 0x69, 0xbf, 0x90, 0x59, 0xa8,
+ 0xbe, 0x90, 0x39, 0xa7, 0x74, 0x35, 0x61, 0x79, 0x18, 0xf8, 0x09, 0x0b,
+ 0x18, 0x18, 0xcf, 0x87, 0x80, 0x21, 0xd8, 0xde, 0x6e, 0x26, 0x91, 0xa3,
+ 0x54, 0xaa, 0x2b, 0x99, 0x02, 0x3e, 0x53, 0xaa, 0xef, 0x58, 0x8c, 0x7d,
+ 0x5b, 0x12, 0xe5, 0xd8, 0x9f, 0xe2, 0xbb, 0x39, 0x31, 0x67, 0x5d, 0xb6,
+ 0x39, 0xee, 0x6b, 0xb1, 0x73, 0x6a, 0x8c, 0x90, 0x14, 0xd4, 0xb3, 0x5f,
+ 0xb5, 0xf8, 0xec, 0x29, 0xf8, 0xf8, 0x93, 0x55, 0x53, 0x4e, 0x54, 0xd7,
+ 0x32, 0x39, 0x7c, 0x88, 0x6d, 0x5e, 0x2e, 0xf1, 0xfe, 0xb7, 0x70, 0x3f,
+ 0x24, 0xcc, 0x3d, 0x3e, 0x8f, 0x3e, 0x47, 0xd1, 0xe7, 0x48, 0x35, 0xc0,
+ 0x8d, 0xbc, 0xef, 0x66, 0x52, 0xb8, 0x7f, 0xa4, 0xe8, 0x66, 0xd2, 0x45,
+ 0xe6, 0x39, 0x7d, 0xd1, 0x13, 0x90, 0x67, 0x16, 0xb1, 0xdd, 0x15, 0xab,
+ 0x37, 0x2f, 0x8f, 0xb5, 0x0e, 0x23, 0xaf, 0x3e, 0x8f, 0x98, 0xe3, 0x8e,
+ 0x59, 0x4e, 0x19, 0xcc, 0x4d, 0x95, 0xee, 0x90, 0xc2, 0x0c, 0x62, 0x8c,
+ 0x73, 0x0f, 0x73, 0xed, 0x8c, 0x1e, 0x77, 0xe0, 0x13, 0x06, 0x80, 0x27,
+ 0xbb, 0x81, 0x85, 0xef, 0x92, 0x15, 0xd3, 0x8a, 0x0e, 0x03, 0x03, 0xa7,
+ 0x42, 0xe8, 0xd3, 0x7b, 0x9b, 0x64, 0xa3, 0x94, 0xf5, 0x0e, 0xf8, 0x07,
+ 0x4d, 0x5a, 0xec, 0x46, 0x5f, 0xf5, 0x17, 0x10, 0x2f, 0x92, 0xdf, 0x36,
+ 0xb6, 0xb7, 0xfa, 0x3a, 0xd9, 0x22, 0xab, 0xef, 0xe9, 0xf7, 0x37, 0x0d,
+ 0xfd, 0x1a, 0xdb, 0x35, 0x4d, 0xd0, 0x7f, 0x0d, 0x34, 0x84, 0xe2, 0x90,
+ 0x3f, 0x78, 0x68, 0x82, 0x9d, 0x5c, 0x06, 0x3f, 0xf4, 0x9b, 0x85, 0x32,
+ 0xe3, 0xa4, 0x21, 0x65, 0x13, 0xf7, 0xaa, 0xf5, 0xfa, 0x82, 0x0d, 0x5a,
+ 0x2f, 0x90, 0xde, 0xb0, 0x0c, 0x57, 0x7b, 0xc4, 0x5d, 0xa4, 0x1c, 0x2c,
+ 0xac, 0x8e, 0x5d, 0x6d, 0xa9, 0x79, 0xcb, 0xcd, 0x63, 0x44, 0xe3, 0x42,
+ 0x57, 0x5b, 0x12, 0x71, 0x51, 0xbf, 0x10, 0x6b, 0x4b, 0xc1, 0x1f, 0x18,
+ 0x17, 0x6e, 0x6f, 0x4b, 0xcf, 0x92, 0x2e, 0x03, 0x71, 0xf1, 0x4e, 0xe0,
+ 0xc2, 0xba, 0x7c, 0x0d, 0xb9, 0x4f, 0xa1, 0x17, 0x31, 0x03, 0xab, 0x44,
+ 0x07, 0xdd, 0x79, 0x53, 0xc2, 0x6d, 0x89, 0x79, 0xd0, 0xd7, 0xdf, 0x9a,
+ 0x9c, 0xdd, 0x82, 0x3e, 0x06, 0xda, 0x7b, 0x88, 0x21, 0x1b, 0xda, 0xed,
+ 0x36, 0xf8, 0x5f, 0xf8, 0x3a, 0x09, 0x27, 0x07, 0xda, 0x31, 0xfe, 0xd9,
+ 0x10, 0x73, 0x87, 0x70, 0x7c, 0xbd, 0xfd, 0xcb, 0x5e, 0x7b, 0x2f, 0x68,
+ 0xe1, 0x73, 0xcc, 0x21, 0x25, 0x3c, 0x3e, 0x60, 0x82, 0x06, 0xf6, 0x8d,
+ 0xa8, 0xbe, 0xe9, 0x79, 0xda, 0x80, 0x9b, 0x59, 0xb0, 0x77, 0x4b, 0x6a,
+ 0x6e, 0xa7, 0x0c, 0xcf, 0x75, 0xca, 0xfe, 0x39, 0xe6, 0xbc, 0xc4, 0xc0,
+ 0x60, 0x05, 0x39, 0xa9, 0x7e, 0x81, 0xb9, 0x80, 0x15, 0x3d, 0x2a, 0xdd,
+ 0xd1, 0xcf, 0x63, 0x1d, 0x8c, 0xdb, 0xf1, 0xd8, 0x24, 0xd6, 0x58, 0x48,
+ 0x8d, 0x13, 0x0d, 0xe6, 0xa4, 0x8d, 0x6e, 0x98, 0x37, 0x3d, 0x7f, 0xb3,
+ 0x71, 0xb1, 0x70, 0x2e, 0x44, 0x37, 0x8d, 0xfb, 0x3f, 0xfd, 0x71, 0x4d,
+ 0x8c, 0xdb, 0x85, 0x31, 0xc9, 0xe3, 0xed, 0xad, 0x43, 0xb3, 0xe2, 0xb6,
+ 0x80, 0xbe, 0x74, 0x7c, 0x97, 0x4c, 0x62, 0x9c, 0x93, 0x73, 0xf4, 0x85,
+ 0xb2, 0x13, 0x9f, 0xfe, 0x26, 0x89, 0xf7, 0x2e, 0x21, 0x2f, 0x1e, 0x52,
+ 0x63, 0x78, 0x39, 0xaa, 0x7e, 0x21, 0x01, 0x5c, 0xf3, 0x51, 0xd0, 0xc3,
+ 0x98, 0x4c, 0x9e, 0x43, 0xe0, 0x37, 0x81, 0x75, 0x48, 0x3c, 0xce, 0xf5,
+ 0x8d, 0xdf, 0x4b, 0xd1, 0xd6, 0xd4, 0x6c, 0x33, 0xd6, 0x9d, 0xec, 0x36,
+ 0x54, 0xac, 0xa0, 0x5e, 0xec, 0xd6, 0x64, 0x49, 0xd1, 0xdd, 0x9a, 0x2a,
+ 0x51, 0x46, 0x4e, 0x6b, 0xba, 0x44, 0x19, 0x09, 0xe8, 0x71, 0xe0, 0x63,
+ 0x43, 0x12, 0xdb, 0x4e, 0x3d, 0x1e, 0x43, 0xbf, 0x95, 0x10, 0xf3, 0xfe,
+ 0xa4, 0xcd, 0xdf, 0xc0, 0x2b, 0x17, 0x8e, 0xa3, 0x2f, 0x7f, 0xdf, 0x8b,
+ 0x71, 0xbb, 0x7b, 0x0b, 0xd2, 0xdc, 0x7b, 0x04, 0x7e, 0x42, 0x1f, 0x00,
+ 0xee, 0x50, 0x76, 0x5e, 0x07, 0x26, 0xdb, 0x0b, 0x7e, 0xb0, 0x36, 0xe2,
+ 0xb6, 0x4c, 0xcc, 0x50, 0xae, 0x72, 0x1b, 0x78, 0x00, 0xff, 0x71, 0xf8,
+ 0x16, 0xf2, 0xc0, 0xb9, 0x05, 0x76, 0xbf, 0x2c, 0xb9, 0x99, 0xb0, 0xc2,
+ 0x3e, 0xae, 0xc9, 0xf9, 0x35, 0x4d, 0x4f, 0xb4, 0x41, 0xc7, 0xe4, 0x6d,
+ 0x0a, 0xb4, 0x3d, 0x0e, 0x3f, 0x6c, 0xa9, 0x9c, 0xdb, 0x40, 0xff, 0x42,
+ 0x69, 0x50, 0x4f, 0x15, 0x49, 0xbf, 0x6f, 0x7b, 0xda, 0x0a, 0x7c, 0x8a,
+ 0xaa, 0x63, 0x21, 0xb7, 0x4b, 0xc0, 0x8f, 0x0c, 0xca, 0xf7, 0xe1, 0x4b,
+ 0xbe, 0x5b, 0x73, 0xe0, 0xff, 0xfb, 0xe1, 0xff, 0x7b, 0xe1, 0xff, 0x6d,
+ 0xf8, 0xff, 0x18, 0xfc, 0x7f, 0x17, 0xfc, 0x7f, 0x94, 0xbe, 0x5f, 0x4e,
+ 0xd6, 0xf2, 0xb0, 0xb1, 0x15, 0xf8, 0x41, 0x33, 0xec, 0xd6, 0x22, 0xe1,
+ 0x64, 0x2d, 0x1a, 0x4e, 0xd5, 0x42, 0xe0, 0xe9, 0x30, 0xe7, 0x04, 0x7f,
+ 0xf9, 0xd6, 0xa1, 0x52, 0x3f, 0xe2, 0x8a, 0x0b, 0xbf, 0x94, 0x86, 0xdf,
+ 0x77, 0x80, 0x7f, 0xf3, 0xb2, 0x3a, 0x13, 0xc3, 0x33, 0x75, 0x49, 0x3b,
+ 0x4d, 0x32, 0x69, 0x3a, 0x18, 0x63, 0xbb, 0xb2, 0x53, 0x23, 0xb1, 0xab,
+ 0x09, 0x76, 0x2a, 0xb9, 0x22, 0xe3, 0x73, 0x17, 0xc6, 0x6b, 0x45, 0x7c,
+ 0xa0, 0x7f, 0xa0, 0x2f, 0x58, 0xc9, 0x3c, 0x6c, 0x73, 0xcd, 0xb5, 0x69,
+ 0x49, 0xe0, 0x67, 0x62, 0x13, 0xc4, 0x3a, 0xd8, 0x05, 0xdb, 0xf6, 0xe0,
+ 0x39, 0xfe, 0xfe, 0x6f, 0x7e, 0x8d, 0xea, 0xaf, 0x5a, 0x04, 0xc6, 0xfb,
+ 0x32, 0x63, 0x8f, 0x8d, 0xf1, 0xaa, 0x8d, 0xeb, 0x75, 0x49, 0x17, 0x3b,
+ 0xb8, 0xcf, 0x7a, 0x0d, 0x6b, 0x54, 0xaf, 0x80, 0xde, 0x7a, 0x7d, 0x55,
+ 0x61, 0x48, 0xe4, 0x33, 0x87, 0xd6, 0xc0, 0x43, 0xe3, 0x33, 0xdf, 0xc0,
+ 0x33, 0xaa, 0x2d, 0x6c, 0x26, 0x1c, 0xe6, 0x50, 0xf0, 0x9b, 0x2f, 0xc0,
+ 0x47, 0x1e, 0xcb, 0xe8, 0xcb, 0x57, 0xf1, 0x2c, 0x64, 0x5a, 0x3c, 0x96,
+ 0x09, 0xf5, 0xbc, 0x5a, 0x7f, 0x16, 0x39, 0xf1, 0xd0, 0xf2, 0x80, 0xa4,
+ 0x96, 0xbb, 0xa3, 0x17, 0xa5, 0xf5, 0x1d, 0x17, 0xb1, 0x74, 0xb2, 0x6a,
+ 0x9d, 0x76, 0x85, 0x39, 0xba, 0x29, 0x0b, 0xc0, 0xd5, 0x7b, 0xf6, 0x3d,
+ 0x0f, 0xda, 0xad, 0x17, 0x45, 0x8f, 0xe1, 0x37, 0x31, 0x0c, 0x79, 0x5c,
+ 0x03, 0x7f, 0x1a, 0xae, 0x5b, 0xd6, 0x6b, 0x57, 0x85, 0x12, 0xf8, 0xac,
+ 0x1d, 0xcb, 0x5c, 0x9c, 0x06, 0xae, 0x83, 0x3e, 0x92, 0xd3, 0xc4, 0x9c,
+ 0x5b, 0x20, 0x93, 0x21, 0xd8, 0x05, 0xf5, 0x1d, 0xc7, 0xb3, 0x75, 0xf9,
+ 0x92, 0x43, 0x1b, 0x78, 0x0e, 0x72, 0xc3, 0x58, 0xa1, 0x80, 0x6e, 0x60,
+ 0x80, 0x19, 0xca, 0x6a, 0x17, 0xf2, 0x36, 0x57, 0x06, 0xf6, 0x49, 0x78,
+ 0x47, 0x62, 0x73, 0x4e, 0x76, 0x2c, 0xb3, 0x3a, 0x8d, 0xf1, 0x7b, 0x80,
+ 0x79, 0x84, 0xb5, 0x19, 0xfa, 0x60, 0x81, 0xed, 0xec, 0x87, 0x7e, 0x98,
+ 0x7b, 0x33, 0x47, 0xa3, 0x6f, 0x3a, 0xa8, 0xa5, 0x2a, 0x65, 0x43, 0x3a,
+ 0x0e, 0x21, 0xb7, 0x71, 0x64, 0x71, 0x9a, 0x39, 0x1a, 0xf3, 0x99, 0x20,
+ 0x7f, 0xd1, 0x90, 0x4b, 0xa0, 0x7d, 0xf9, 0x25, 0xa5, 0x07, 0x03, 0xfa,
+ 0xca, 0xed, 0xbb, 0x9f, 0x7c, 0xcd, 0x18, 0x09, 0xf8, 0xbf, 0x01, 0xf2,
+ 0xa2, 0x68, 0x40, 0xce, 0xc6, 0x35, 0x17, 0x03, 0x5f, 0xf8, 0x5c, 0xcf,
+ 0xdd, 0xd4, 0xdf, 0x64, 0xe9, 0x04, 0xec, 0x58, 0xf2, 0x4d, 0x09, 0xf0,
+ 0x36, 0x80, 0xdf, 0x58, 0xf8, 0x27, 0xa1, 0xc3, 0x73, 0x03, 0xac, 0x91,
+ 0x3d, 0x07, 0xfc, 0x47, 0xfa, 0xe3, 0xb1, 0x13, 0x6a, 0xdd, 0xe2, 0xba,
+ 0xca, 0x3c, 0x62, 0x8b, 0x5c, 0x54, 0x7c, 0xde, 0xc1, 0xfc, 0x14, 0x7a,
+ 0xb9, 0x15, 0x3e, 0x87, 0x3f, 0x24, 0x9f, 0xde, 0x3c, 0x8c, 0x5b, 0x49,
+ 0x3b, 0x26, 0xa9, 0xe2, 0xcb, 0x75, 0xaf, 0x0e, 0xfb, 0x47, 0xb0, 0x2b,
+ 0x5c, 0x57, 0xc3, 0xa0, 0x87, 0x75, 0x99, 0x01, 0xa5, 0x5b, 0xd0, 0x43,
+ 0x9b, 0xc9, 0x87, 0x13, 0xdb, 0xe4, 0xfc, 0x4c, 0x87, 0x2c, 0xcc, 0xbc,
+ 0x26, 0x95, 0x99, 0x36, 0x59, 0x9a, 0xa9, 0xcb, 0x65, 0x47, 0xf9, 0x25,
+ 0xbb, 0x59, 0xad, 0x69, 0xd9, 0xe5, 0x61, 0xf6, 0xf8, 0xe0, 0x15, 0x79,
+ 0x5a, 0xce, 0x97, 0x3d, 0x1e, 0x32, 0x0d, 0x3c, 0xbc, 0x0a, 0x1b, 0xeb,
+ 0xec, 0x21, 0x0f, 0xb4, 0x07, 0xf2, 0xc3, 0xdc, 0x83, 0x39, 0xe6, 0x41,
+ 0xac, 0xa3, 0x11, 0x60, 0xa3, 0x83, 0x5a, 0xd2, 0xe7, 0x21, 0xe5, 0xf1,
+ 0x90, 0x7d, 0x2f, 0x0f, 0x2d, 0x92, 0xdd, 0x49, 0x3e, 0xa0, 0x83, 0x69,
+ 0xea, 0x25, 0xc0, 0x1b, 0x1e, 0xfd, 0xc9, 0xe5, 0x57, 0xeb, 0xfa, 0x74,
+ 0x93, 0xa2, 0xdd, 0x48, 0x0c, 0xc0, 0xae, 0x5e, 0xad, 0xcb, 0x32, 0xd7,
+ 0x12, 0x7e, 0x57, 0xff, 0x31, 0xfc, 0x55, 0xa7, 0xca, 0x5b, 0x72, 0x63,
+ 0xed, 0xad, 0xc9, 0xf9, 0x41, 0xe8, 0xba, 0x55, 0xad, 0x45, 0xb8, 0x0e,
+ 0xe8, 0xf0, 0x0f, 0xd1, 0xff, 0xab, 0x5c, 0x73, 0x4a, 0x3e, 0x69, 0xc8,
+ 0xa7, 0x50, 0xbc, 0xbd, 0x19, 0x39, 0x37, 0xe6, 0x71, 0x33, 0xd9, 0x2a,
+ 0x9f, 0xe9, 0x82, 0x7f, 0xe3, 0xf7, 0x07, 0xb6, 0x8f, 0x3c, 0xfc, 0x2e,
+ 0x6c, 0x00, 0xb9, 0x05, 0xd7, 0xf4, 0xc0, 0x0a, 0xe2, 0x6c, 0xbc, 0x77,
+ 0x41, 0xd5, 0xf4, 0x1d, 0x85, 0x9f, 0x26, 0xab, 0x5f, 0xc5, 0xc7, 0x9b,
+ 0x6f, 0xa8, 0xc6, 0x39, 0x37, 0xf2, 0x84, 0x9c, 0x06, 0xb9, 0xa4, 0x8d,
+ 0x71, 0x39, 0x6f, 0x5e, 0x8c, 0x84, 0x81, 0x79, 0xd9, 0xd6, 0x0e, 0x3f,
+ 0x13, 0x83, 0xdf, 0xea, 0x87, 0xff, 0xe7, 0x5a, 0xa6, 0xaf, 0x0f, 0x68,
+ 0xef, 0xc7, 0x98, 0xf4, 0xc1, 0xfd, 0xe0, 0x99, 0xb9, 0x34, 0x7d, 0x28,
+ 0x62, 0xca, 0x62, 0xb4, 0x2d, 0x39, 0xeb, 0xd5, 0x93, 0xbc, 0xdf, 0xbc,
+ 0x2f, 0xe1, 0xdd, 0x09, 0xab, 0x9c, 0x47, 0xfe, 0x97, 0xc2, 0xda, 0x4d,
+ 0xda, 0xc8, 0xa7, 0x17, 0xad, 0x17, 0x88, 0xd3, 0x74, 0xca, 0x60, 0x99,
+ 0x72, 0x62, 0x6d, 0xc3, 0x94, 0xfc, 0xc2, 0xef, 0x42, 0x1e, 0x61, 0xd9,
+ 0x6e, 0x67, 0xe1, 0x53, 0x98, 0xb7, 0xb8, 0xe0, 0x8d, 0xbe, 0xa7, 0x1b,
+ 0xb1, 0xcc, 0x80, 0x10, 0x90, 0x57, 0x2d, 0x1b, 0xf2, 0x40, 0xa8, 0x0f,
+ 0x79, 0xe0, 0xa7, 0xd0, 0x37, 0x24, 0xf9, 0x65, 0xc6, 0x84, 0x90, 0x4c,
+ 0x2d, 0x8b, 0x5c, 0x99, 0xa6, 0x5f, 0x51, 0x7f, 0x90, 0xb9, 0x9b, 0x99,
+ 0x20, 0x3e, 0x9b, 0xa1, 0x8f, 0xa1, 0xff, 0xd8, 0x01, 0x5d, 0xc4, 0x9f,
+ 0xfb, 0x12, 0xe2, 0xd3, 0x64, 0xb1, 0x1b, 0x7e, 0x53, 0x56, 0x74, 0xc8,
+ 0x14, 0x71, 0x8d, 0xf5, 0xaa, 0x1b, 0xd4, 0xaa, 0x82, 0x3a, 0x55, 0x58,
+ 0x0a, 0xd3, 0xac, 0x51, 0x85, 0x41, 0x0b, 0x73, 0x57, 0x43, 0xe5, 0x42,
+ 0x3b, 0x94, 0x7f, 0xe5, 0x77, 0xa8, 0x61, 0xde, 0xf8, 0xe9, 0x3d, 0x3a,
+ 0xfd, 0xd8, 0x6e, 0x71, 0x47, 0x8f, 0xb5, 0xee, 0x2f, 0x01, 0x8b, 0x76,
+ 0xd2, 0x3e, 0xa9, 0xff, 0xac, 0x4e, 0x7f, 0x3b, 0x55, 0x1a, 0xc0, 0x78,
+ 0xc4, 0x95, 0x21, 0xf4, 0x8b, 0xf8, 0xfd, 0x28, 0xd7, 0x7f, 0x25, 0xe3,
+ 0xfb, 0xfe, 0x1a, 0x74, 0x79, 0xfe, 0x8e, 0x75, 0xee, 0xdc, 0x67, 0x74,
+ 0xb9, 0xef, 0x63, 0x69, 0x3c, 0xcb, 0x78, 0xf8, 0xb6, 0x8f, 0xe1, 0xd8,
+ 0xc6, 0xba, 0x1e, 0x72, 0xf5, 0xf3, 0x26, 0xbe, 0x3b, 0x25, 0x7f, 0x3e,
+ 0x0c, 0x39, 0x20, 0x2f, 0x5e, 0xf0, 0xc6, 0x62, 0xee, 0x7b, 0x1a, 0x3a,
+ 0xd2, 0xcf, 0x84, 0xa5, 0xe9, 0x4c, 0xa7, 0x84, 0xbe, 0xd2, 0x26, 0xcd,
+ 0x5f, 0xe9, 0x11, 0xe3, 0x2b, 0xac, 0x3f, 0x58, 0xb1, 0x93, 0xaa, 0xf6,
+ 0x91, 0x96, 0x53, 0x88, 0x61, 0x3a, 0xe2, 0xb1, 0xb2, 0x53, 0x73, 0xa7,
+ 0x18, 0x48, 0x5e, 0xf5, 0x67, 0x5c, 0xf9, 0xe2, 0xbe, 0x9f, 0xab, 0xda,
+ 0x1b, 0x70, 0xb3, 0xe8, 0xcf, 0x67, 0xc4, 0xad, 0xbd, 0x46, 0x3b, 0xcd,
+ 0xbc, 0x7a, 0xd7, 0x1d, 0xd0, 0x39, 0x73, 0xcb, 0x5e, 0x55, 0xc7, 0xfd,
+ 0xe2, 0x3e, 0xc6, 0x4c, 0x2f, 0xbf, 0x4c, 0x23, 0xbf, 0x9c, 0x94, 0x6e,
+ 0xf8, 0x59, 0xf6, 0xdb, 0x29, 0x3a, 0xe6, 0xca, 0x09, 0xf3, 0xf5, 0x3b,
+ 0xc5, 0x3d, 0x8c, 0x75, 0x71, 0x56, 0x66, 0xf4, 0x84, 0xa6, 0xc6, 0x34,
+ 0x9e, 0xa1, 0xdf, 0xa2, 0x3f, 0xa3, 0x8d, 0xb3, 0x0e, 0x82, 0xb6, 0xe7,
+ 0xe9, 0xb3, 0x3c, 0xdb, 0x1e, 0x6a, 0xf0, 0x7d, 0x53, 0xa5, 0x1a, 0x74,
+ 0x88, 0xbc, 0xde, 0x6e, 0x02, 0xff, 0x88, 0xeb, 0x36, 0xaf, 0xc9, 0x3f,
+ 0x7c, 0x69, 0x24, 0xa2, 0xae, 0x0b, 0x65, 0x0f, 0xf7, 0x7a, 0xe3, 0x33,
+ 0x07, 0x81, 0xaf, 0xa9, 0x91, 0x0e, 0xce, 0xdb, 0x25, 0xc6, 0xd9, 0x88,
+ 0x84, 0xce, 0xd2, 0xfe, 0xac, 0x58, 0x1a, 0xf2, 0x9b, 0xb2, 0x89, 0xf5,
+ 0x0e, 0xc0, 0x17, 0xec, 0x16, 0xfd, 0x7c, 0x2f, 0xd6, 0x8e, 0x15, 0x2d,
+ 0x4b, 0x5c, 0x8c, 0x85, 0xb0, 0xbc, 0x09, 0xdf, 0x41, 0x7b, 0x39, 0x87,
+ 0x78, 0x75, 0xa2, 0xd6, 0xfa, 0xce, 0x8a, 0xa2, 0x82, 0x6d, 0x43, 0xc0,
+ 0x4b, 0x56, 0xaf, 0xab, 0xb7, 0xcb, 0xeb, 0xd0, 0x77, 0x56, 0xb5, 0xed,
+ 0xc6, 0xb8, 0xa0, 0xe1, 0x2c, 0xeb, 0x49, 0x1c, 0xf7, 0x1f, 0x60, 0x4c,
+ 0x8e, 0xed, 0x66, 0x56, 0x99, 0x9f, 0x4e, 0xd3, 0x76, 0x3b, 0x61, 0x77,
+ 0xb8, 0xae, 0x35, 0x4b, 0x76, 0x2c, 0x26, 0xfa, 0xf4, 0x83, 0xd2, 0xbd,
+ 0x4f, 0xf7, 0xf8, 0x51, 0x3c, 0xb2, 0x8d, 0x75, 0xca, 0x16, 0xb5, 0x1e,
+ 0xf5, 0x65, 0xd8, 0xcc, 0x41, 0xea, 0x18, 0xf1, 0x1f, 0xf1, 0x8d, 0xfe,
+ 0xcc, 0x40, 0x7c, 0x4b, 0xd5, 0x3c, 0xbd, 0x97, 0x0f, 0xee, 0x94, 0x53,
+ 0x67, 0x69, 0x4f, 0xb8, 0xb7, 0x6e, 0x53, 0xc1, 0x7e, 0x02, 0xef, 0xd9,
+ 0x72, 0xfa, 0x59, 0xe6, 0x1f, 0xcc, 0x3b, 0x98, 0x6b, 0x59, 0xd1, 0xfd,
+ 0xe0, 0x47, 0xbf, 0x8f, 0xfe, 0x40, 0x57, 0xb6, 0x9b, 0x83, 0xaf, 0x2e,
+ 0xd4, 0xa8, 0xb7, 0x7e, 0xee, 0xb9, 0x98, 0xcc, 0xd9, 0xdc, 0xa8, 0x27,
+ 0xef, 0x02, 0xda, 0x26, 0x11, 0x07, 0x52, 0xd5, 0x26, 0x59, 0x1b, 0x73,
+ 0xa1, 0xfb, 0x8f, 0x82, 0xae, 0xc3, 0xad, 0xc4, 0xab, 0x6b, 0x63, 0x69,
+ 0x5c, 0x1f, 0x56, 0x79, 0x9a, 0x71, 0x9f, 0x8b, 0x31, 0x76, 0x72, 0x1d,
+ 0xf9, 0x7a, 0x72, 0xf4, 0xc2, 0xcc, 0x7d, 0xfa, 0x24, 0x7c, 0xf7, 0xb0,
+ 0xc3, 0x18, 0xcf, 0xfa, 0x73, 0x0b, 0xe8, 0x68, 0x57, 0xd8, 0x42, 0xb7,
+ 0xf7, 0xe9, 0x85, 0x32, 0xfd, 0x7d, 0x3e, 0xda, 0x2c, 0x0e, 0x7d, 0x96,
+ 0xbe, 0x60, 0x53, 0x27, 0x9a, 0x5c, 0x54, 0xb5, 0x6a, 0x44, 0xa0, 0x6a,
+ 0x0a, 0x73, 0x39, 0x7a, 0xa5, 0xbc, 0x4f, 0xcf, 0xc3, 0x55, 0xaf, 0x45,
+ 0x48, 0x77, 0x4c, 0xe5, 0xf2, 0xfb, 0x94, 0xad, 0x15, 0x11, 0x53, 0x60,
+ 0x33, 0xce, 0x1d, 0x98, 0x57, 0xb5, 0xc1, 0xa6, 0xa8, 0x7b, 0xea, 0x5d,
+ 0xf9, 0x48, 0x5f, 0xf7, 0x37, 0x8a, 0xa1, 0x45, 0xf8, 0x5f, 0x62, 0xe9,
+ 0x16, 0xbf, 0x3e, 0xf5, 0xcf, 0xfd, 0x9c, 0xe8, 0x71, 0x61, 0x9e, 0x32,
+ 0x55, 0x22, 0x2d, 0x45, 0xf8, 0xc3, 0x1b, 0xd9, 0x12, 0xe5, 0xe8, 0xf9,
+ 0x94, 0x63, 0xb0, 0x0b, 0x7d, 0xd9, 0xf4, 0x6d, 0x40, 0xe1, 0x67, 0xdc,
+ 0x63, 0x0c, 0xc0, 0x77, 0xad, 0x09, 0xeb, 0x7d, 0x04, 0x32, 0xa2, 0x6e,
+ 0xa0, 0xbf, 0x65, 0xee, 0xd5, 0x41, 0x7f, 0xcb, 0x97, 0x7e, 0xe1, 0x76,
+ 0xd2, 0xe7, 0x0d, 0xc8, 0x29, 0xf8, 0xd1, 0x93, 0xf3, 0xa4, 0x27, 0xad,
+ 0xd6, 0xce, 0x14, 0xe4, 0x7d, 0x42, 0xf9, 0xf8, 0x7e, 0x79, 0x73, 0xf1,
+ 0x5b, 0x0a, 0x0b, 0xee, 0xd9, 0xb7, 0x22, 0x13, 0xf0, 0x0f, 0x47, 0xaa,
+ 0x90, 0xb7, 0x19, 0xc3, 0xfa, 0xdc, 0xa5, 0xfc, 0xe3, 0x17, 0x3f, 0x78,
+ 0xae, 0x12, 0xd2, 0x13, 0x0f, 0x7c, 0xc8, 0x18, 0xbe, 0x55, 0xdc, 0xce,
+ 0x0f, 0x3c, 0x8f, 0xa1, 0x27, 0xfe, 0x10, 0x3a, 0xfb, 0x4d, 0xcc, 0x15,
+ 0x06, 0x9d, 0x6a, 0x3f, 0xe4, 0x83, 0x3c, 0xa7, 0xeb, 0x89, 0x4f, 0x7e,
+ 0x48, 0xfa, 0x4c, 0x59, 0x04, 0x7e, 0xc8, 0xab, 0xb8, 0xca, 0xdc, 0xb1,
+ 0xc9, 0xd7, 0xe7, 0x0b, 0xc0, 0xd5, 0xc0, 0xd2, 0xc5, 0xc0, 0x17, 0xb7,
+ 0x48, 0xbe, 0x33, 0xc8, 0x47, 0xe1, 0xc3, 0xd7, 0xdb, 0x83, 0x1c, 0x97,
+ 0xcf, 0x67, 0x33, 0xc8, 0xa9, 0x61, 0x13, 0xb7, 0x61, 0x8d, 0xb2, 0x4d,
+ 0xe5, 0xb0, 0x37, 0xa1, 0xdf, 0xa3, 0x3d, 0x57, 0x6c, 0xcc, 0x2d, 0x0e,
+ 0xa8, 0xdc, 0x62, 0x68, 0x43, 0x6e, 0x11, 0xd4, 0xb4, 0x02, 0xba, 0x39,
+ 0x2e, 0x70, 0x03, 0xec, 0xe0, 0xbb, 0x18, 0xff, 0x3b, 0xd0, 0xf7, 0xb7,
+ 0x4b, 0xc0, 0x0d, 0x25, 0xe0, 0x86, 0x12, 0x70, 0x43, 0x09, 0xb8, 0xa1,
+ 0x14, 0xf5, 0xeb, 0x5b, 0x2e, 0x71, 0xff, 0x07, 0xb4, 0xe9, 0xa0, 0xee,
+ 0xb1, 0xd9, 0x5e, 0xbd, 0x3a, 0x59, 0xaa, 0x16, 0xe0, 0xe7, 0x30, 0xeb,
+ 0x76, 0xc0, 0x71, 0x41, 0x4d, 0xc4, 0x8f, 0x1d, 0x8b, 0xdc, 0x43, 0x41,
+ 0xec, 0x58, 0x74, 0xb1, 0x9e, 0xfa, 0xa2, 0x06, 0x70, 0xa3, 0x21, 0x51,
+ 0xfc, 0x36, 0xe1, 0x93, 0xb9, 0x67, 0xde, 0x8d, 0x15, 0xd6, 0xac, 0x6a,
+ 0x4f, 0x27, 0x54, 0x4d, 0xc2, 0x96, 0xc9, 0x72, 0x90, 0xdb, 0xc5, 0x65,
+ 0x68, 0x86, 0x58, 0x54, 0xb6, 0xeb, 0x09, 0xe8, 0xa2, 0x4a, 0xfc, 0xc8,
+ 0x3d, 0x27, 0xce, 0x1f, 0xef, 0xad, 0x60, 0xce, 0x82, 0xed, 0xd1, 0x77,
+ 0xa2, 0xaa, 0xce, 0x05, 0xf8, 0xcf, 0x05, 0x67, 0x01, 0xe2, 0xb2, 0x7f,
+ 0x86, 0x7b, 0xef, 0x31, 0x19, 0x2d, 0x3a, 0xc8, 0x65, 0x55, 0x8e, 0x84,
+ 0x78, 0xe0, 0xc9, 0x7d, 0xc8, 0x97, 0x7b, 0x0e, 0xd8, 0x61, 0xdc, 0x0e,
+ 0xe4, 0x4e, 0x79, 0x8f, 0x68, 0xc3, 0x90, 0xf5, 0x7e, 0x5f, 0xd6, 0xe9,
+ 0x25, 0x31, 0x91, 0xff, 0xc4, 0x8c, 0x7d, 0x63, 0xda, 0x68, 0x4d, 0x61,
+ 0x16, 0xfa, 0x23, 0x8c, 0xe5, 0x78, 0x6b, 0x1d, 0xf6, 0x92, 0xab, 0x6e,
+ 0xde, 0x8f, 0x6f, 0xc4, 0x2f, 0x9f, 0xd5, 0xc4, 0x0e, 0xe4, 0xd8, 0xd8,
+ 0x3e, 0xd1, 0xd0, 0xbe, 0x7e, 0xdf, 0xe7, 0x01, 0xbe, 0x72, 0xbd, 0x3e,
+ 0x41, 0xbf, 0x76, 0xbd, 0x1d, 0x78, 0x4f, 0x42, 0xea, 0x3e, 0x7c, 0xfe,
+ 0x62, 0x44, 0x52, 0x8b, 0xb6, 0xa4, 0xcb, 0xec, 0xc7, 0x9a, 0x07, 0xfd,
+ 0xd7, 0x1f, 0x4b, 0x0a, 0x79, 0x6e, 0x36, 0x62, 0x39, 0xae, 0xfc, 0x47,
+ 0x59, 0x9d, 0xcb, 0xc7, 0xb8, 0x77, 0x9d, 0x1f, 0xd5, 0xf0, 0xdc, 0x8f,
+ 0x71, 0x4d, 0xda, 0x6d, 0xac, 0x0f, 0xc6, 0xa9, 0xbe, 0xe8, 0x22, 0xee,
+ 0x65, 0xc7, 0x58, 0xe7, 0x79, 0x2a, 0x2c, 0x6d, 0x56, 0xac, 0x0c, 0x3b,
+ 0xb8, 0x54, 0xe4, 0x7c, 0xc0, 0x52, 0x45, 0xd6, 0x82, 0x82, 0xfb, 0x7f,
+ 0x0c, 0xec, 0xa8, 0x13, 0x3b, 0x79, 0x7d, 0x94, 0xbe, 0x5c, 0x33, 0x84,
+ 0x35, 0xb0, 0xe2, 0xfb, 0xe7, 0x85, 0xa2, 0x57, 0x7b, 0x39, 0x47, 0x3a,
+ 0xaa, 0x7f, 0x53, 0x5f, 0x89, 0x20, 0x67, 0x5a, 0xe7, 0xf1, 0x1c, 0xc7,
+ 0x37, 0xe1, 0x9e, 0xe5, 0x64, 0x35, 0x90, 0x05, 0xef, 0xb3, 0x8d, 0xfb,
+ 0xf3, 0xf5, 0xfa, 0x39, 0xfb, 0xc3, 0xd6, 0xd9, 0x9e, 0xbb, 0x27, 0x69,
+ 0xcb, 0x81, 0x85, 0xaa, 0x1c, 0xf0, 0xea, 0x6c, 0xd1, 0xbd, 0x5e, 0x9d,
+ 0x2d, 0xb6, 0x77, 0x63, 0x9d, 0xad, 0x7c, 0x8f, 0x57, 0x67, 0x33, 0x0f,
+ 0xc0, 0x07, 0x1f, 0xf0, 0xea, 0x6c, 0xff, 0xf5, 0x1e, 0xaf, 0xce, 0xd6,
+ 0x75, 0xaf, 0x57, 0x67, 0xeb, 0xdd, 0xeb, 0xd5, 0xd9, 0x46, 0xef, 0xdd,
+ 0x58, 0x67, 0x73, 0xf6, 0x6e, 0xac, 0xb3, 0x39, 0x07, 0x72, 0xf8, 0x5c,
+ 0xaf, 0xb3, 0x65, 0xf6, 0xde, 0xbc, 0xce, 0xf6, 0x4a, 0x80, 0xf1, 0xc1,
+ 0xcf, 0x00, 0x78, 0x70, 0x80, 0xf1, 0xfb, 0x81, 0xf1, 0x6f, 0x56, 0xe3,
+ 0x55, 0xe7, 0x37, 0xc0, 0xa7, 0xe6, 0xc7, 0x8f, 0x0f, 0x83, 0xf5, 0xb7,
+ 0xfa, 0xcf, 0xba, 0xc8, 0x8f, 0x63, 0x7e, 0x6e, 0x43, 0xbc, 0xbf, 0xcd,
+ 0xcf, 0xf1, 0xba, 0x5a, 0xaf, 0x9f, 0xad, 0x68, 0xfc, 0xbe, 0x0d, 0xa9,
+ 0x7a, 0x50, 0x03, 0x20, 0x5f, 0x72, 0xe0, 0x61, 0x25, 0x87, 0x3b, 0xd1,
+ 0xdf, 0x3c, 0xf0, 0x25, 0x9b, 0x75, 0x81, 0x27, 0xb1, 0x86, 0xdd, 0xed,
+ 0x86, 0xda, 0x67, 0x66, 0x4c, 0x3b, 0x2d, 0x29, 0xf4, 0x4f, 0xa9, 0xfe,
+ 0xa3, 0x0d, 0xfd, 0xb3, 0xe8, 0xcf, 0x71, 0xad, 0x7f, 0x8b, 0xcf, 0x73,
+ 0xca, 0xbe, 0x6d, 0x0f, 0xf7, 0xa7, 0x4b, 0x01, 0x4e, 0x0b, 0xf9, 0x18,
+ 0xdc, 0xcd, 0xb8, 0xd5, 0x7b, 0xf1, 0x8c, 0xf5, 0xa2, 0x2b, 0x57, 0x15,
+ 0xde, 0x37, 0x12, 0xd6, 0x8b, 0x59, 0x95, 0xdf, 0xb9, 0x99, 0x5c, 0x75,
+ 0x3d, 0x5f, 0x07, 0x0e, 0x63, 0xce, 0x03, 0x7b, 0x5f, 0xee, 0x45, 0xdc,
+ 0x6b, 0xcc, 0xc9, 0x99, 0x87, 0xeb, 0x7e, 0x1e, 0x6e, 0xca, 0xfd, 0xfb,
+ 0x1a, 0x31, 0xbe, 0x73, 0xe0, 0xef, 0x2b, 0x8c, 0xbf, 0x05, 0xb9, 0x3c,
+ 0x31, 0x3c, 0x71, 0x0f, 0x31, 0x07, 0x71, 0x3e, 0xeb, 0x0b, 0xcc, 0x7f,
+ 0x18, 0x4b, 0x99, 0x0f, 0x45, 0xf0, 0xe1, 0xb9, 0x97, 0x00, 0xeb, 0x37,
+ 0xfb, 0xfe, 0x9f, 0x79, 0x54, 0x80, 0x6d, 0xac, 0x2d, 0x5e, 0x2e, 0xb5,
+ 0x45, 0xf3, 0xf2, 0xd5, 0x98, 0xdf, 0x27, 0xb4, 0x8e, 0xa5, 0x43, 0xeb,
+ 0x58, 0x7a, 0xc3, 0x5e, 0x89, 0xa8, 0x33, 0x36, 0x6a, 0xcf, 0x85, 0x7b,
+ 0x30, 0x6e, 0xe6, 0x52, 0x0f, 0xf1, 0x30, 0xf7, 0x62, 0x80, 0x8d, 0xec,
+ 0xc6, 0x58, 0xc5, 0x38, 0x45, 0x3c, 0x15, 0xec, 0xb7, 0x06, 0x7a, 0xa2,
+ 0xec, 0xd8, 0xf6, 0x47, 0x1a, 0x72, 0x64, 0xa7, 0xd9, 0xde, 0x0f, 0x5a,
+ 0x32, 0xf8, 0x0e, 0x64, 0xfa, 0x80, 0x8a, 0x91, 0x2d, 0xb0, 0xdd, 0x13,
+ 0x25, 0x62, 0xde, 0x6d, 0xb2, 0xe8, 0xe3, 0xde, 0xf3, 0x33, 0x1e, 0xe6,
+ 0x0d, 0x6d, 0xc4, 0xbc, 0xce, 0xaa, 0x78, 0x34, 0xee, 0xbf, 0x21, 0x8d,
+ 0xc4, 0xb7, 0xa4, 0x8f, 0x31, 0x89, 0xfe, 0xd1, 0xcd, 0x5c, 0xee, 0x61,
+ 0x3c, 0x62, 0x2c, 0x8a, 0xc9, 0xea, 0x4d, 0xe9, 0x53, 0x6d, 0xc7, 0x5a,
+ 0xec, 0x30, 0x3e, 0x13, 0xf0, 0x1f, 0xa3, 0x78, 0x26, 0x23, 0x93, 0xb3,
+ 0x5f, 0x00, 0x6f, 0x13, 0x72, 0x69, 0x66, 0x0c, 0xf4, 0x3d, 0x29, 0x53,
+ 0x4e, 0x1e, 0x7e, 0x84, 0x7b, 0x21, 0xc4, 0x79, 0xdd, 0xfe, 0xf7, 0x84,
+ 0x7e, 0xce, 0xb6, 0x88, 0x33, 0xa5, 0x52, 0xa4, 0x0f, 0xe6, 0xbe, 0x14,
+ 0xf7, 0x1f, 0x69, 0x3f, 0xac, 0xc3, 0x20, 0xd7, 0x65, 0xce, 0x3b, 0xcd,
+ 0xf9, 0x37, 0xea, 0x64, 0xb5, 0x4a, 0xbc, 0xe6, 0x66, 0x56, 0x96, 0x89,
+ 0x37, 0x3f, 0x28, 0xf6, 0xa4, 0x1e, 0x88, 0x3f, 0x6f, 0x05, 0x77, 0x5a,
+ 0x33, 0xc0, 0x9c, 0x2f, 0xac, 0xe8, 0x8d, 0xb8, 0xd3, 0xc3, 0x9c, 0xc9,
+ 0xe5, 0x2c, 0xc6, 0x74, 0x14, 0xb6, 0x46, 0xde, 0x07, 0xb7, 0xd7, 0x8d,
+ 0x67, 0xbb, 0x91, 0xc3, 0x7b, 0x18, 0x33, 0x05, 0x8c, 0xf9, 0x0f, 0x81,
+ 0x31, 0x27, 0xe5, 0xad, 0x56, 0x62, 0x4c, 0xd7, 0xc7, 0x98, 0x69, 0xd8,
+ 0x73, 0x6e, 0x83, 0x3d, 0x6b, 0xaa, 0x76, 0xc5, 0x7b, 0x39, 0x60, 0xc4,
+ 0xd4, 0xb4, 0x75, 0x0b, 0xb8, 0x52, 0x93, 0x88, 0x3a, 0xfb, 0x10, 0x6a,
+ 0x18, 0x33, 0xc0, 0x8f, 0x7b, 0x14, 0x2e, 0x3c, 0x50, 0xda, 0x82, 0x1c,
+ 0x46, 0xe1, 0x44, 0x7f, 0x4f, 0x2e, 0xb4, 0x69, 0x9f, 0x32, 0xd4, 0xb0,
+ 0x4f, 0x79, 0x1d, 0x4f, 0xe2, 0x39, 0xbf, 0x3e, 0xd8, 0x04, 0x5f, 0xf0,
+ 0x7f, 0x40, 0x13, 0xd7, 0x17, 0xd7, 0x82, 0xe6, 0xad, 0x97, 0xd1, 0x46,
+ 0x5c, 0xf9, 0xbf, 0x36, 0xe1, 0x4a, 0xc4, 0xae, 0xf3, 0x11, 0x49, 0x02,
+ 0x53, 0xba, 0xcb, 0x1c, 0x8b, 0x6b, 0xba, 0x5f, 0x9a, 0xc1, 0x5f, 0xcb,
+ 0x74, 0x27, 0xb0, 0x54, 0x9b, 0x84, 0x81, 0xa9, 0x9a, 0x14, 0xa6, 0xea,
+ 0x21, 0xf6, 0xe9, 0x3d, 0x02, 0x2c, 0xb4, 0xb8, 0x8e, 0xab, 0x2c, 0xe7,
+ 0x87, 0xd0, 0xcb, 0xa3, 0xca, 0xf7, 0xa4, 0xe5, 0x29, 0xf8, 0xd2, 0xe6,
+ 0x65, 0xe0, 0xc1, 0xf3, 0x1e, 0xde, 0x6a, 0xda, 0x84, 0xb7, 0x8e, 0xde,
+ 0x10, 0x6f, 0xa9, 0x9a, 0xff, 0x20, 0x65, 0xf2, 0x7a, 0xd5, 0xab, 0xf9,
+ 0x5f, 0xa9, 0x7a, 0x35, 0xff, 0xd7, 0xab, 0x8d, 0x35, 0xff, 0x8f, 0x48,
+ 0xc1, 0xb4, 0xdc, 0x35, 0xd9, 0x54, 0xf3, 0x1f, 0x65, 0x0d, 0xfd, 0xf7,
+ 0xda, 0xbc, 0xda, 0x7e, 0x9b, 0x5f, 0xf3, 0xb7, 0xa4, 0xb0, 0xa1, 0xdd,
+ 0x94, 0xb7, 0xec, 0xa0, 0xe6, 0xff, 0x34, 0xda, 0xda, 0x31, 0xc7, 0xc6,
+ 0x7a, 0xff, 0x95, 0x2a, 0xeb, 0xfd, 0x11, 0xf6, 0xf3, 0xeb, 0xfd, 0xec,
+ 0x87, 0xdc, 0xbf, 0xca, 0x5a, 0xff, 0x6e, 0xc8, 0x62, 0x27, 0xe4, 0xd0,
+ 0x29, 0xcd, 0x67, 0xa3, 0xec, 0xa3, 0x6a, 0xfc, 0x6b, 0xc8, 0x37, 0xae,
+ 0x54, 0xbd, 0x5a, 0xfc, 0x11, 0xd8, 0xd5, 0xd1, 0xf5, 0x1a, 0xbf, 0x37,
+ 0xc7, 0xd5, 0xea, 0xc6, 0xf1, 0x37, 0x8e, 0xd3, 0xe5, 0x8f, 0x13, 0xc1,
+ 0x38, 0xd1, 0x4d, 0xe3, 0x5c, 0xaf, 0xe9, 0x5f, 0xad, 0x7a, 0xf5, 0xfc,
+ 0xf4, 0xac, 0xb8, 0xcd, 0xf0, 0xcd, 0x2f, 0xf6, 0xec, 0xf2, 0xc7, 0x58,
+ 0xaf, 0xe7, 0xd3, 0x87, 0x00, 0xe7, 0xc7, 0xd5, 0xf9, 0x9e, 0x23, 0xff,
+ 0x1f, 0xea, 0xf9, 0xac, 0xe5, 0x7b, 0x7b, 0x32, 0x5c, 0x9f, 0xc0, 0xf3,
+ 0xcf, 0x7a, 0x75, 0xfc, 0xa1, 0x52, 0x50, 0x9f, 0x67, 0x5e, 0x19, 0x9c,
+ 0xbd, 0xe9, 0x8e, 0x9d, 0x10, 0xda, 0x0a, 0xe9, 0xe3, 0xb8, 0xed, 0x32,
+ 0xae, 0xf0, 0x14, 0x6c, 0x2a, 0x7e, 0x73, 0x4c, 0xbd, 0x30, 0x1d, 0x60,
+ 0xea, 0x88, 0xc2, 0xd4, 0x0b, 0xcb, 0x01, 0xa6, 0x4e, 0xde, 0x04, 0x53,
+ 0xff, 0xf7, 0x36, 0x2f, 0x0e, 0x84, 0x25, 0xaf, 0x30, 0xf5, 0xcd, 0xce,
+ 0x2b, 0xf1, 0x5e, 0x1b, 0xf1, 0x82, 0x78, 0x7b, 0xd8, 0x9d, 0x37, 0x59,
+ 0x6b, 0x01, 0xce, 0x66, 0xec, 0xdf, 0x29, 0xa3, 0x67, 0xaf, 0xe3, 0x6c,
+ 0x0f, 0x4b, 0x5b, 0xb1, 0x63, 0x2a, 0x26, 0x02, 0xd7, 0xd5, 0x58, 0x2f,
+ 0x27, 0x56, 0x66, 0xcc, 0x09, 0x29, 0x3c, 0x97, 0x2b, 0x32, 0x0f, 0x60,
+ 0x1b, 0xb1, 0x73, 0x2b, 0x8f, 0xf2, 0xf8, 0x31, 0x29, 0xc0, 0xa6, 0xc1,
+ 0xd9, 0x09, 0xee, 0x4b, 0xbc, 0x65, 0x24, 0x6d, 0xb4, 0x57, 0x83, 0x5c,
+ 0xc1, 0x51, 0x67, 0x4e, 0x92, 0xc0, 0x3f, 0xe3, 0xeb, 0xd8, 0x93, 0xbe,
+ 0xe2, 0x47, 0xbf, 0x70, 0x4d, 0xfa, 0xb5, 0x00, 0x5b, 0x22, 0x27, 0x2a,
+ 0x71, 0x6d, 0x07, 0xd8, 0xd2, 0xc3, 0x95, 0xa9, 0xea, 0x0a, 0xf0, 0x75,
+ 0x48, 0x86, 0x80, 0xeb, 0x57, 0x1e, 0x66, 0xcd, 0x2a, 0xc0, 0x4e, 0x2e,
+ 0xbe, 0x1b, 0x6b, 0x58, 0xbc, 0x6e, 0x56, 0x7b, 0x87, 0x17, 0x7b, 0xc2,
+ 0x0d, 0xed, 0xbf, 0x05, 0xff, 0x8d, 0xfc, 0x08, 0x98, 0xc5, 0xc3, 0x4c,
+ 0x7b, 0xa1, 0x83, 0x01, 0x85, 0x99, 0xa6, 0xde, 0x83, 0x99, 0x36, 0xc7,
+ 0x28, 0xc6, 0xcc, 0xeb, 0x31, 0x2a, 0x5d, 0xa3, 0x3f, 0xbf, 0x1e, 0xa3,
+ 0x6e, 0x1e, 0x43, 0xd9, 0x06, 0xee, 0xec, 0x0c, 0x3e, 0x13, 0x52, 0xd8,
+ 0x14, 0xa3, 0xa6, 0x3e, 0x44, 0x8c, 0x1a, 0x56, 0x31, 0xca, 0xa3, 0xfb,
+ 0xfb, 0x90, 0xcd, 0x77, 0x21, 0xd3, 0xef, 0x00, 0x8b, 0x7d, 0x1b, 0x7c,
+ 0x7d, 0x0b, 0x38, 0xe9, 0x9b, 0xa5, 0xcd, 0x67, 0x0e, 0x06, 0x85, 0xf9,
+ 0xa1, 0x87, 0xa5, 0xbc, 0x1a, 0xc0, 0x11, 0xac, 0xae, 0xc5, 0xa2, 0x9b,
+ 0x19, 0x2f, 0xf6, 0x99, 0x13, 0xde, 0xde, 0x6b, 0x2c, 0x2b, 0x8f, 0xb5,
+ 0xa6, 0xe6, 0x19, 0x33, 0xd4, 0x75, 0x94, 0xf5, 0x4e, 0x62, 0x87, 0x8a,
+ 0xca, 0x33, 0x7b, 0xa4, 0xbc, 0xe8, 0xe1, 0xb0, 0xa9, 0x79, 0x6f, 0x8c,
+ 0x71, 0x1f, 0x87, 0xe5, 0x7c, 0x1c, 0x96, 0x5d, 0x5c, 0x8d, 0x85, 0xd0,
+ 0x7f, 0xca, 0xd9, 0x88, 0xbd, 0x8e, 0xf8, 0xd8, 0x6b, 0xe2, 0x43, 0x61,
+ 0x2f, 0x6f, 0xae, 0x1c, 0x9e, 0x19, 0x9e, 0x89, 0xc9, 0x7e, 0xc8, 0x79,
+ 0xa8, 0x48, 0x7d, 0xf1, 0x9c, 0xd2, 0x2f, 0xd3, 0x19, 0xf5, 0xe5, 0xe9,
+ 0x2a, 0x14, 0x3f, 0xa8, 0x0d, 0x43, 0x57, 0x43, 0xbf, 0x54, 0x57, 0x62,
+ 0xbe, 0x39, 0x10, 0xc6, 0xe7, 0x6f, 0x4b, 0x57, 0xe4, 0x83, 0xfa, 0xda,
+ 0x8c, 0xc5, 0x6e, 0x05, 0x93, 0x6d, 0xc4, 0x63, 0xae, 0xc2, 0x63, 0xcd,
+ 0x7e, 0x9f, 0xfc, 0x81, 0x61, 0xe8, 0xf2, 0x3f, 0xa0, 0xcf, 0x8f, 0xed,
+ 0x76, 0xf9, 0x11, 0xfc, 0xf7, 0xbf, 0x87, 0x4e, 0xfe, 0x1d, 0x72, 0x85,
+ 0x57, 0xec, 0x2e, 0xf9, 0x21, 0xda, 0xae, 0xe3, 0x1c, 0xf6, 0x9f, 0x72,
+ 0x92, 0xf6, 0x28, 0xf0, 0xc9, 0xa8, 0x8f, 0x4f, 0xde, 0x7a, 0x20, 0x69,
+ 0x8f, 0xb1, 0xce, 0x0e, 0x39, 0xff, 0x34, 0x39, 0xae, 0xb0, 0x49, 0x80,
+ 0x49, 0x1e, 0x4f, 0x73, 0xfe, 0xc9, 0x6a, 0x16, 0xd8, 0x27, 0xeb, 0x63,
+ 0x9f, 0x9f, 0xa6, 0x3d, 0xec, 0x33, 0xf5, 0xf7, 0xa8, 0x7f, 0x0f, 0xf7,
+ 0x1c, 0x76, 0x93, 0x98, 0x07, 0xb8, 0x07, 0xd7, 0x87, 0x25, 0x5f, 0x1b,
+ 0x51, 0x9f, 0x13, 0x25, 0xd7, 0x6a, 0x82, 0x9c, 0x58, 0xab, 0x3d, 0xc3,
+ 0x55, 0x59, 0xb5, 0xcc, 0x22, 0xbe, 0xb3, 0x55, 0x2b, 0xfa, 0x7b, 0xfe,
+ 0xf5, 0xd3, 0xfe, 0xf5, 0x53, 0xfe, 0xf5, 0x69, 0xc4, 0xe1, 0x53, 0x2a,
+ 0x96, 0xb2, 0x9d, 0x6d, 0x50, 0x72, 0x15, 0x63, 0x01, 0x7b, 0x9c, 0xeb,
+ 0xff, 0xf3, 0x7a, 0x59, 0xe9, 0x98, 0xe3, 0x8f, 0xe2, 0x73, 0x1a, 0x9f,
+ 0x09, 0x7c, 0x0e, 0xe1, 0x93, 0xc7, 0x67, 0x5d, 0xa6, 0x5a, 0xaa, 0x34,
+ 0x06, 0x1b, 0xe9, 0x95, 0x54, 0xed, 0x39, 0xe8, 0xf1, 0x49, 0xe8, 0xf6,
+ 0xb8, 0x14, 0x2a, 0x7f, 0x22, 0x93, 0x33, 0x9a, 0xb4, 0xd9, 0xd0, 0x69,
+ 0x05, 0xb6, 0x3c, 0xe3, 0xed, 0x41, 0xb6, 0x26, 0x46, 0xd0, 0xb7, 0x2e,
+ 0x8f, 0x3a, 0x4f, 0x8a, 0x7e, 0xdf, 0x14, 0xfa, 0x89, 0x5e, 0xe8, 0xbf,
+ 0x5b, 0xed, 0xbf, 0x55, 0x1c, 0x4f, 0xc6, 0xfb, 0x6d, 0xd7, 0x82, 0xce,
+ 0x7b, 0x4f, 0x61, 0xec, 0xa4, 0x3a, 0x7f, 0x99, 0x91, 0x93, 0xb3, 0xab,
+ 0xdb, 0x3d, 0xdf, 0x6a, 0x99, 0x57, 0xa9, 0x77, 0xf0, 0xe1, 0xc2, 0x17,
+ 0x66, 0x60, 0xef, 0x47, 0xab, 0x21, 0x6d, 0x08, 0xf1, 0x66, 0xa8, 0x7a,
+ 0x55, 0xc5, 0x9b, 0x54, 0xd5, 0xcd, 0xc4, 0xcf, 0x44, 0x70, 0xcd, 0x73,
+ 0x31, 0x88, 0x8b, 0xea, 0xfc, 0xde, 0x2a, 0xf0, 0x8d, 0xa6, 0xea, 0x86,
+ 0x93, 0xeb, 0xfb, 0x4a, 0xea, 0x7c, 0x71, 0x26, 0x1e, 0xd7, 0x25, 0x37,
+ 0x40, 0x9c, 0x3b, 0xa2, 0x62, 0x13, 0xd6, 0xea, 0xed, 0xcc, 0x15, 0x5f,
+ 0xe7, 0xbb, 0x00, 0xf6, 0x27, 0xd0, 0xaf, 0x0b, 0xfe, 0x18, 0xf7, 0x6a,
+ 0xb4, 0x4f, 0xf2, 0xca, 0x67, 0x26, 0xa4, 0x52, 0x1e, 0x04, 0xbf, 0x7e,
+ 0x8e, 0xa4, 0x72, 0x89, 0x18, 0xec, 0x31, 0xd8, 0xc3, 0xf2, 0xea, 0x2a,
+ 0x95, 0x6a, 0x80, 0x29, 0xda, 0xd1, 0x87, 0x79, 0x05, 0x64, 0xe4, 0xed,
+ 0xbf, 0xa9, 0xbd, 0xb7, 0x42, 0x75, 0x10, 0x72, 0x4a, 0xa2, 0x9d, 0xb5,
+ 0x6d, 0xfc, 0x2e, 0xeb, 0xaa, 0x26, 0xb0, 0x66, 0x1c, 0x91, 0xc5, 0x72,
+ 0x1d, 0xf4, 0x22, 0xe6, 0x6e, 0x3f, 0x22, 0x0b, 0xe5, 0x09, 0x79, 0xa1,
+ 0xfc, 0xcd, 0x76, 0x60, 0x2a, 0xc8, 0x94, 0xf4, 0xb7, 0xcb, 0xf5, 0x33,
+ 0x9e, 0x41, 0x3b, 0xe4, 0x39, 0x9b, 0x8f, 0x7a, 0x79, 0x6e, 0x5e, 0xd5,
+ 0x68, 0xbc, 0x6f, 0x57, 0x1f, 0xb7, 0xad, 0xe8, 0x24, 0x7a, 0x1e, 0x9d,
+ 0x53, 0xb6, 0x39, 0x3c, 0x65, 0xef, 0x95, 0xcb, 0xce, 0x36, 0x59, 0x75,
+ 0x54, 0x5e, 0x4c, 0xfc, 0x80, 0xb5, 0x6e, 0x99, 0x2b, 0xf2, 0xa0, 0x9c,
+ 0xc4, 0xba, 0xbd, 0xec, 0x3c, 0x06, 0x3b, 0x7d, 0x02, 0xb6, 0xc0, 0x1a,
+ 0xc0, 0x31, 0xe6, 0x5a, 0xb2, 0xa2, 0x6a, 0x68, 0xf5, 0xfa, 0xb0, 0x3a,
+ 0x27, 0xdc, 0x2c, 0xab, 0x0a, 0x8b, 0x79, 0xb5, 0xf6, 0xd5, 0x31, 0x6f,
+ 0x8d, 0x18, 0xca, 0xee, 0xbf, 0x01, 0x7a, 0x8a, 0xb0, 0xdd, 0x26, 0xd5,
+ 0xc7, 0x48, 0xb4, 0xf8, 0x7d, 0x14, 0x06, 0x6d, 0xe8, 0x63, 0x27, 0x92,
+ 0xf6, 0x6b, 0xfb, 0x92, 0xf6, 0xc4, 0x81, 0x5c, 0xd5, 0xf3, 0x99, 0xae,
+ 0xb6, 0xb6, 0x5e, 0xff, 0xc9, 0x60, 0x5d, 0xbd, 0xbc, 0x8e, 0xa1, 0x61,
+ 0xa4, 0xcf, 0x5f, 0x82, 0x7e, 0x43, 0xd2, 0x7c, 0xa6, 0xfe, 0x89, 0x71,
+ 0xa7, 0x2f, 0x76, 0x54, 0x78, 0x32, 0x8b, 0x79, 0xb5, 0xe5, 0x64, 0xe5,
+ 0x12, 0xe2, 0xe4, 0x35, 0x62, 0x87, 0xde, 0x8b, 0x72, 0xed, 0x13, 0x49,
+ 0x67, 0x50, 0x5b, 0x18, 0x43, 0xd6, 0xf2, 0xfc, 0x18, 0xe3, 0xec, 0x31,
+ 0x11, 0xe0, 0xcb, 0x33, 0x03, 0x92, 0x2e, 0xaa, 0x77, 0x21, 0x78, 0x96,
+ 0x53, 0x9b, 0x80, 0xfc, 0xf0, 0xfc, 0x28, 0x03, 0xa3, 0x6e, 0x77, 0xc7,
+ 0xd2, 0xf2, 0x18, 0x6b, 0x63, 0x92, 0x9b, 0x93, 0x3d, 0x49, 0xf8, 0x55,
+ 0x77, 0xb4, 0x59, 0x26, 0x16, 0xdd, 0x4c, 0xf7, 0xf4, 0x13, 0x18, 0x63,
+ 0x1c, 0x63, 0x8d, 0x20, 0x37, 0xc9, 0x22, 0x56, 0x53, 0xbe, 0xf4, 0xdd,
+ 0x8f, 0x43, 0x46, 0x1f, 0xe1, 0x59, 0xd7, 0xc1, 0xac, 0x58, 0xa3, 0x79,
+ 0x35, 0xee, 0xbb, 0x5a, 0xae, 0xff, 0x57, 0x10, 0xeb, 0x42, 0xb2, 0x3f,
+ 0x2e, 0xfa, 0x48, 0x3c, 0xf4, 0x8b, 0x71, 0x9b, 0x6d, 0x61, 0xb6, 0xe9,
+ 0x68, 0x0b, 0xfd, 0x66, 0x3c, 0xac, 0x27, 0xe3, 0xd6, 0x20, 0xcf, 0xe0,
+ 0x1a, 0xf6, 0xb8, 0x18, 0xcf, 0xd7, 0x21, 0x8b, 0x11, 0xe9, 0xb8, 0x60,
+ 0x0d, 0xbe, 0x0e, 0x5a, 0x42, 0xca, 0xd7, 0x8f, 0x8b, 0xee, 0xb7, 0xb7,
+ 0xaf, 0xb7, 0x87, 0xfc, 0xf6, 0x11, 0x69, 0xbb, 0xd0, 0x67, 0xbe, 0x21,
+ 0x47, 0x30, 0xa6, 0x21, 0x57, 0x90, 0xeb, 0xd8, 0x3d, 0xe3, 0xb0, 0xc5,
+ 0x47, 0x48, 0xcb, 0x21, 0xd6, 0x1b, 0x5d, 0xd8, 0x5f, 0x8b, 0x7d, 0x87,
+ 0x7c, 0xde, 0x6c, 0x95, 0x9c, 0xca, 0x75, 0x43, 0xea, 0xbd, 0x85, 0x1c,
+ 0xec, 0xfd, 0xae, 0x9e, 0xa1, 0x0e, 0xaf, 0x5e, 0xc0, 0xfd, 0x91, 0x7e,
+ 0xb4, 0x5d, 0xab, 0x9f, 0xb7, 0xd9, 0xc6, 0x7b, 0xd7, 0xea, 0x15, 0xbb,
+ 0xcf, 0x4c, 0x69, 0x61, 0x7f, 0xff, 0xfc, 0x98, 0xe2, 0x3d, 0x5f, 0xee,
+ 0x36, 0x17, 0xe4, 0x2e, 0x2d, 0xb5, 0x03, 0xf1, 0xa2, 0x9a, 0x42, 0xdf,
+ 0x6b, 0x3c, 0x83, 0xa1, 0xf6, 0x03, 0x16, 0x24, 0xb8, 0xe6, 0x38, 0x7d,
+ 0xe6, 0xb0, 0x7a, 0xb6, 0xcf, 0x3c, 0xa9, 0x35, 0x3e, 0x1b, 0xd5, 0x86,
+ 0x37, 0x3c, 0xdb, 0xa6, 0x64, 0x64, 0xd8, 0x5e, 0x9f, 0xc9, 0xf2, 0x88,
+ 0x3c, 0x5d, 0x65, 0xbf, 0x6b, 0xf5, 0x94, 0xbd, 0x55, 0x3b, 0xb9, 0x83,
+ 0xbe, 0x90, 0x7d, 0xdf, 0xd9, 0x34, 0x0f, 0xaf, 0x6f, 0x36, 0x47, 0x5d,
+ 0x36, 0xce, 0xb1, 0x45, 0xf5, 0xb9, 0xac, 0xfa, 0x84, 0x94, 0xac, 0x37,
+ 0xce, 0xf3, 0x17, 0xb2, 0x71, 0x9e, 0xb6, 0x75, 0x9e, 0x27, 0x31, 0xe6,
+ 0x29, 0xf4, 0x2d, 0x56, 0xbb, 0xa3, 0x15, 0x79, 0xa7, 0x9e, 0xb3, 0xdf,
+ 0x92, 0xcb, 0xeb, 0x63, 0xff, 0x25, 0xae, 0x1b, 0x69, 0xfa, 0x4b, 0x9f,
+ 0x46, 0xfe, 0x66, 0xdb, 0x3f, 0x53, 0xf2, 0xde, 0x6a, 0x77, 0x1f, 0x5a,
+ 0xd0, 0xac, 0xc1, 0x9f, 0x09, 0x75, 0xf5, 0x3b, 0xca, 0xd7, 0xdc, 0x0d,
+ 0x3d, 0xed, 0x79, 0x06, 0x6b, 0xb7, 0x3f, 0xa9, 0xfa, 0x5c, 0xb1, 0x47,
+ 0x64, 0xcf, 0x99, 0x6e, 0xf3, 0x8a, 0xdc, 0x2f, 0xe9, 0x08, 0xaf, 0x91,
+ 0x43, 0xd9, 0x7c, 0xf7, 0xe1, 0x57, 0x99, 0x17, 0x40, 0x97, 0xdd, 0xbd,
+ 0x3f, 0x93, 0x27, 0xe4, 0x64, 0x69, 0x0a, 0xbe, 0x67, 0x5c, 0x7a, 0x9f,
+ 0xa1, 0xff, 0xc9, 0x9b, 0x5e, 0xad, 0xc6, 0x8b, 0x89, 0x29, 0x3f, 0x26,
+ 0x4e, 0x29, 0x3f, 0xf7, 0x8a, 0x7f, 0x8e, 0xa2, 0xbb, 0xf7, 0x3c, 0x9e,
+ 0x7d, 0x41, 0xf9, 0x80, 0x6f, 0x48, 0x05, 0x6b, 0x21, 0xf6, 0xfc, 0x36,
+ 0xd9, 0xfa, 0x10, 0x6d, 0x12, 0x19, 0xc0, 0xdd, 0x4d, 0xea, 0x5d, 0x0b,
+ 0xdd, 0x6e, 0x11, 0xd9, 0x4e, 0xfb, 0x59, 0xd8, 0x2a, 0x6d, 0xe3, 0xde,
+ 0x5e, 0xd9, 0x86, 0x6b, 0x6b, 0x74, 0x4d, 0xca, 0x5b, 0x69, 0x87, 0x1f,
+ 0xbd, 0xe0, 0x7d, 0xf7, 0x5f, 0x40, 0xba, 0x1c, 0x1f, 0x91, 0x7b, 0x2f,
+ 0x78, 0x76, 0x37, 0x39, 0xf3, 0x84, 0x92, 0xef, 0xb8, 0x92, 0x6f, 0x5d,
+ 0x8e, 0x38, 0x94, 0x3d, 0x79, 0xe2, 0xb9, 0x4a, 0x4f, 0x26, 0x9f, 0xf4,
+ 0xed, 0xa8, 0xfb, 0x19, 0xbe, 0x23, 0x46, 0x19, 0x91, 0xee, 0x74, 0x07,
+ 0xf7, 0x6f, 0xf7, 0x5c, 0x20, 0xbf, 0x5d, 0x1b, 0xf8, 0x7d, 0x0a, 0x3e,
+ 0xb6, 0xa7, 0xc7, 0xe3, 0xf9, 0x95, 0x99, 0x0f, 0xce, 0xf3, 0xd7, 0xd6,
+ 0x79, 0x36, 0xa4, 0xa2, 0xf2, 0xdc, 0xd0, 0x36, 0x69, 0xcb, 0xc9, 0x0a,
+ 0xec, 0xe3, 0xcf, 0x84, 0xe7, 0x92, 0x49, 0x8b, 0x37, 0xef, 0x6a, 0x95,
+ 0x34, 0x05, 0x3c, 0x90, 0xae, 0xa4, 0xaf, 0x3f, 0xd2, 0xf1, 0xc4, 0x0d,
+ 0xef, 0x5d, 0x11, 0x37, 0xd3, 0x8b, 0x36, 0x5d, 0xe9, 0x70, 0xc8, 0x5f,
+ 0x6f, 0x23, 0xa2, 0x2b, 0x1d, 0x26, 0xd7, 0x75, 0xf8, 0x3a, 0x74, 0x58,
+ 0x91, 0x8f, 0x83, 0x27, 0xac, 0xef, 0x67, 0xfa, 0xcc, 0x23, 0xb2, 0x53,
+ 0xe9, 0xdf, 0xee, 0x81, 0x4f, 0xf5, 0x75, 0xd9, 0x7c, 0x0b, 0xba, 0x7c,
+ 0x43, 0x94, 0x3e, 0xd5, 0xd9, 0xa3, 0x8a, 0x1a, 0x87, 0xbe, 0x8d, 0xbc,
+ 0x35, 0x2b, 0x9f, 0x40, 0x1a, 0xd5, 0x59, 0x82, 0x51, 0x4f, 0xbf, 0x6a,
+ 0xcd, 0xfb, 0xfa, 0xcd, 0x8e, 0x52, 0x87, 0xd1, 0x0e, 0x4f, 0x9f, 0x2d,
+ 0xaa, 0xcf, 0x74, 0xfc, 0x36, 0xb5, 0xde, 0xed, 0x9e, 0x9d, 0x1d, 0xd4,
+ 0xe9, 0xd3, 0x55, 0xef, 0xbb, 0x88, 0x38, 0x37, 0x5d, 0xfd, 0x65, 0x7a,
+ 0xf5, 0x74, 0x3a, 0x24, 0xde, 0xba, 0xda, 0xac, 0x4f, 0xfd, 0x42, 0x48,
+ 0xd9, 0xf0, 0x10, 0x64, 0x78, 0xba, 0xb4, 0xc3, 0xb7, 0x7b, 0x8f, 0xe7,
+ 0x9e, 0x0f, 0xc8, 0xf3, 0x89, 0x62, 0xb7, 0xf9, 0x16, 0xee, 0x0d, 0x83,
+ 0xe7, 0x23, 0xd2, 0x24, 0x29, 0x9f, 0xe7, 0xd8, 0x3a, 0xcf, 0x01, 0x8d,
+ 0x5e, 0xbf, 0x14, 0xf3, 0xd8, 0x2a, 0xfd, 0xd7, 0xef, 0xaa, 0x77, 0x1a,
+ 0xae, 0x16, 0xe9, 0xb7, 0x81, 0x95, 0x22, 0x9d, 0x72, 0x65, 0x31, 0x26,
+ 0x57, 0x88, 0x41, 0x06, 0xf0, 0x5d, 0x9d, 0xf2, 0x63, 0x78, 0x58, 0xde,
+ 0x28, 0xde, 0x88, 0x8e, 0x7e, 0x79, 0xbd, 0x18, 0xd0, 0x42, 0x2c, 0xcc,
+ 0x7c, 0x61, 0x5c, 0xde, 0x9c, 0xe9, 0x96, 0x95, 0x51, 0xc4, 0xfd, 0x1e,
+ 0xca, 0xa4, 0xcf, 0x7c, 0x50, 0xbd, 0xeb, 0x72, 0xad, 0x7e, 0xd1, 0xc6,
+ 0xf8, 0x73, 0x75, 0x39, 0xca, 0xfd, 0x6f, 0xfe, 0x5e, 0xbc, 0x5d, 0x56,
+ 0x98, 0x53, 0xf4, 0x74, 0xca, 0xc2, 0x1c, 0xf2, 0xf9, 0x22, 0xc7, 0xa7,
+ 0xdc, 0x46, 0xd4, 0xef, 0x61, 0xcc, 0xf7, 0x49, 0x9e, 0x41, 0x8f, 0x50,
+ 0x37, 0xd7, 0xea, 0xab, 0x36, 0xf7, 0x3f, 0xc7, 0x65, 0x11, 0xfa, 0xfb,
+ 0x47, 0x71, 0xee, 0xcf, 0xe7, 0xd4, 0xfb, 0x85, 0x0b, 0x8b, 0xa3, 0xc8,
+ 0x1d, 0xae, 0xd5, 0xa7, 0xec, 0x29, 0xa5, 0xb7, 0xc5, 0xf2, 0x43, 0x7e,
+ 0x3b, 0xaf, 0x79, 0xcf, 0xcd, 0xec, 0xe9, 0x61, 0xbe, 0xfa, 0x10, 0xf2,
+ 0x05, 0xe6, 0xaa, 0xa3, 0xc0, 0x6b, 0x94, 0x49, 0x4c, 0x26, 0x8b, 0x1c,
+ 0x4b, 0x22, 0x5b, 0x90, 0xdf, 0xe7, 0x64, 0x18, 0xf4, 0xc4, 0x90, 0xdb,
+ 0x33, 0x3e, 0xdc, 0x25, 0xab, 0x11, 0x2f, 0x0e, 0xf0, 0xac, 0xd8, 0x2a,
+ 0x62, 0xc3, 0xea, 0x7a, 0x6c, 0xd8, 0x89, 0x6b, 0x37, 0xe3, 0xf4, 0xfc,
+ 0x67, 0x8c, 0xcf, 0xba, 0x0d, 0x63, 0xc3, 0x20, 0xfa, 0xb3, 0xad, 0x53,
+ 0x26, 0xe7, 0x90, 0x44, 0x20, 0x67, 0x59, 0x10, 0x9e, 0x01, 0xc9, 0xca,
+ 0xf4, 0x62, 0x77, 0xf4, 0xa2, 0x96, 0x56, 0x67, 0x45, 0xe2, 0x98, 0x73,
+ 0xa1, 0xd8, 0x29, 0x8b, 0x73, 0x12, 0x33, 0x12, 0x8f, 0x48, 0x75, 0xd1,
+ 0xc3, 0xec, 0x53, 0x1a, 0xda, 0xab, 0xae, 0x2c, 0x6e, 0xec, 0x63, 0x1a,
+ 0x89, 0xc3, 0xf2, 0x75, 0xbf, 0x4f, 0x5a, 0xf5, 0x79, 0xb5, 0x83, 0x7b,
+ 0x6c, 0x8b, 0xd5, 0x0e, 0xd0, 0x40, 0xda, 0x76, 0x35, 0xce, 0x1b, 0xbb,
+ 0x3e, 0x2f, 0xe7, 0x44, 0x36, 0xb3, 0xdd, 0xc5, 0xbc, 0x17, 0xf1, 0xcc,
+ 0x23, 0xa0, 0xe3, 0x9a, 0xa1, 0xdb, 0x8f, 0x48, 0x61, 0x71, 0xf3, 0x1c,
+ 0x8d, 0x34, 0xf0, 0x19, 0x8e, 0xcf, 0x79, 0x0e, 0x83, 0xbe, 0x6b, 0x9a,
+ 0x6e, 0x1f, 0x86, 0x2c, 0xbd, 0x39, 0x8c, 0xb3, 0x96, 0xf9, 0x23, 0xe9,
+ 0x11, 0xfd, 0xbc, 0xa6, 0xe4, 0xaf, 0x2f, 0xf4, 0x63, 0x81, 0x64, 0xa4,
+ 0x6d, 0x79, 0x4c, 0x8c, 0x65, 0xd6, 0x10, 0x5e, 0x69, 0x4d, 0xab, 0xfd,
+ 0xde, 0x2d, 0x58, 0xdf, 0xe2, 0x86, 0x6c, 0xd6, 0x0b, 0x58, 0x0f, 0xfe,
+ 0xfa, 0x36, 0xe9, 0x60, 0xbd, 0x80, 0x79, 0xc3, 0x21, 0x7c, 0x33, 0x77,
+ 0x78, 0xb9, 0x9e, 0x74, 0x7e, 0xa6, 0xe2, 0x6b, 0x6e, 0x91, 0xf7, 0xad,
+ 0x98, 0x08, 0xef, 0xd1, 0x6f, 0x74, 0x4a, 0xd3, 0x57, 0x7a, 0xe1, 0x2b,
+ 0x1e, 0x03, 0xf6, 0xc6, 0xb8, 0x67, 0x7a, 0x24, 0xe4, 0x9d, 0xb1, 0x50,
+ 0xf5, 0x96, 0x37, 0xe7, 0x2c, 0xff, 0x9d, 0x21, 0xd9, 0x73, 0xd1, 0x61,
+ 0x4d, 0xb4, 0x8b, 0x35, 0x1f, 0xf4, 0x13, 0x7d, 0x15, 0xf9, 0xe9, 0x95,
+ 0x45, 0x63, 0x1b, 0xcf, 0x7c, 0xbe, 0x5e, 0xc5, 0x35, 0xb1, 0x7f, 0x44,
+ 0x61, 0x4c, 0xff, 0x1e, 0x7f, 0x23, 0x5f, 0x7a, 0xcf, 0xf9, 0x77, 0xe6,
+ 0x53, 0x63, 0xfe, 0x59, 0x3b, 0x37, 0x73, 0x72, 0x43, 0x4e, 0xd5, 0xab,
+ 0xea, 0xbd, 0x2b, 0x55, 0x1b, 0xfe, 0x71, 0x00, 0xf6, 0xc9, 0x35, 0x50,
+ 0xd7, 0x1e, 0x02, 0x36, 0x8b, 0x75, 0xaa, 0x9c, 0xe8, 0xf4, 0x43, 0xe2,
+ 0xd9, 0x3b, 0xac, 0x4c, 0xf9, 0xb2, 0x95, 0xb2, 0x97, 0x83, 0xac, 0x96,
+ 0x33, 0xf2, 0x9f, 0xaa, 0x97, 0x54, 0xad, 0x75, 0x06, 0x79, 0x49, 0x68,
+ 0x5a, 0xe5, 0x64, 0x0d, 0xf8, 0x16, 0x7e, 0xef, 0xd9, 0x2f, 0x62, 0x2d,
+ 0x5a, 0xea, 0x4c, 0x83, 0x7e, 0xbe, 0x5e, 0x4f, 0xc1, 0x7f, 0xe8, 0xb6,
+ 0x6d, 0x16, 0x10, 0x0f, 0x53, 0xea, 0x5c, 0x0c, 0xd7, 0xf1, 0x61, 0xe5,
+ 0x9f, 0x65, 0x01, 0xb2, 0x39, 0x1b, 0xc3, 0x38, 0x9a, 0xb2, 0x4f, 0x43,
+ 0xe9, 0xe1, 0x21, 0x85, 0x79, 0x8d, 0xf3, 0x70, 0x58, 0xcb, 0x3d, 0x22,
+ 0xe7, 0x33, 0x32, 0x85, 0x35, 0x1c, 0x5a, 0xa6, 0x0e, 0x28, 0xdb, 0x31,
+ 0x69, 0x82, 0xec, 0x4f, 0x00, 0x7b, 0x18, 0xd3, 0x94, 0x71, 0x14, 0xeb,
+ 0xa2, 0x53, 0x42, 0x67, 0x21, 0xe3, 0x69, 0x60, 0x84, 0xb9, 0x66, 0x79,
+ 0x69, 0x31, 0x90, 0xe9, 0xcb, 0x3c, 0xef, 0xaf, 0x8f, 0x0f, 0x74, 0x11,
+ 0x47, 0x49, 0x65, 0x71, 0x4a, 0xa6, 0x66, 0x99, 0xb3, 0x8f, 0xa9, 0x33,
+ 0x06, 0x21, 0x75, 0xc6, 0xc5, 0xcb, 0x99, 0xbd, 0x6f, 0x0f, 0x63, 0x56,
+ 0x84, 0x7b, 0x6d, 0x02, 0xdb, 0xe9, 0xc7, 0xbc, 0x37, 0x92, 0xaf, 0x97,
+ 0xab, 0x0e, 0x83, 0xde, 0x8b, 0x33, 0x56, 0x26, 0x2f, 0x0e, 0xcf, 0x5b,
+ 0x8f, 0xba, 0xe0, 0x7f, 0x15, 0xfe, 0x73, 0xaa, 0x74, 0x2f, 0xf8, 0x2c,
+ 0x60, 0x85, 0x65, 0xe4, 0x62, 0x91, 0x39, 0xe3, 0x47, 0xa1, 0x37, 0x5e,
+ 0x17, 0x06, 0x0d, 0xf8, 0x81, 0x35, 0xf5, 0x7e, 0xa1, 0xe5, 0xae, 0x20,
+ 0x87, 0x8d, 0x69, 0x87, 0xa0, 0xeb, 0xbc, 0xd9, 0xe4, 0xdb, 0x03, 0xdf,
+ 0x35, 0x3e, 0x07, 0x3f, 0xba, 0x24, 0x7c, 0xef, 0xe7, 0x9d, 0x3a, 0xf3,
+ 0xa5, 0xcb, 0xf0, 0x7b, 0x99, 0x78, 0x06, 0x36, 0x94, 0x8f, 0xb6, 0x80,
+ 0xe6, 0xdf, 0xc6, 0xbd, 0x5c, 0x95, 0xf3, 0x58, 0xce, 0x9a, 0x14, 0x62,
+ 0x21, 0xe9, 0x8b, 0x5d, 0x92, 0x6d, 0xf0, 0x64, 0x9a, 0xbc, 0x61, 0x5b,
+ 0x83, 0xa2, 0xa9, 0xf1, 0x7a, 0x0f, 0xc0, 0x06, 0xaf, 0xc2, 0xdf, 0x35,
+ 0xfb, 0xb9, 0x7e, 0xaa, 0x48, 0x0c, 0xf5, 0x84, 0x3a, 0x8b, 0x70, 0xd9,
+ 0x66, 0x1d, 0x90, 0xef, 0xfb, 0xfe, 0x95, 0x9a, 0xe3, 0xfa, 0xde, 0x1d,
+ 0xeb, 0xd0, 0xa4, 0xcf, 0xe3, 0x71, 0xbf, 0xed, 0xd1, 0xc8, 0x71, 0x9a,
+ 0x1a, 0xc6, 0xb9, 0xe8, 0x8f, 0x73, 0xce, 0x1f, 0x67, 0xc1, 0x1f, 0xe7,
+ 0xf2, 0xfa, 0x38, 0x0f, 0xc2, 0x0e, 0xea, 0xf5, 0xa7, 0x80, 0x37, 0x92,
+ 0x4e, 0xbd, 0x9e, 0x46, 0x5e, 0x36, 0xd9, 0x3f, 0xa1, 0xf6, 0x5e, 0xf5,
+ 0xc4, 0x8b, 0x43, 0x49, 0xdb, 0x93, 0x3f, 0xac, 0x40, 0x26, 0x60, 0x8f,
+ 0x79, 0xf1, 0xb0, 0x3a, 0xf7, 0x03, 0xbd, 0xfd, 0xc2, 0x36, 0xf8, 0x81,
+ 0xc7, 0x10, 0x4b, 0x9c, 0xe1, 0x25, 0x5b, 0xf2, 0x7b, 0x7e, 0x4d, 0x87,
+ 0xbd, 0x77, 0x20, 0x2e, 0xbd, 0x09, 0xdb, 0x71, 0x86, 0x2b, 0x8b, 0x8f,
+ 0xa9, 0x3d, 0xe1, 0xa6, 0xc4, 0xbd, 0xd0, 0x67, 0x79, 0x78, 0x61, 0xb1,
+ 0x3c, 0x7c, 0x8e, 0xfb, 0x43, 0xe8, 0xb7, 0xb0, 0xd8, 0x0e, 0xb9, 0xb7,
+ 0xab, 0xba, 0xca, 0xa5, 0x62, 0x04, 0x7a, 0x34, 0x61, 0xf3, 0x11, 0xb4,
+ 0x45, 0x61, 0x07, 0x5d, 0x68, 0x7f, 0x0d, 0x6b, 0x3b, 0x86, 0xf6, 0xb5,
+ 0xd6, 0x61, 0x85, 0x63, 0x6d, 0x39, 0x5f, 0xbd, 0x8a, 0x98, 0xfb, 0x16,
+ 0xfc, 0x68, 0x2f, 0xfa, 0xf4, 0xa3, 0xcf, 0x0e, 0x13, 0xf8, 0x2a, 0x53,
+ 0xbe, 0x21, 0x4d, 0x2e, 0x68, 0xd2, 0x1b, 0x68, 0x72, 0x41, 0x0f, 0x7c,
+ 0xe7, 0x19, 0xd6, 0xa0, 0xfb, 0xe5, 0x64, 0x91, 0x67, 0xaa, 0xf8, 0xee,
+ 0xb5, 0x29, 0x21, 0x60, 0xd2, 0xa6, 0x33, 0x56, 0x74, 0x45, 0xd5, 0x7a,
+ 0x68, 0x5b, 0x7d, 0x4e, 0x45, 0x54, 0x9c, 0x89, 0x9d, 0x44, 0xfc, 0xba,
+ 0x5a, 0x6d, 0x97, 0x37, 0xfc, 0xb9, 0xd6, 0x84, 0xfb, 0x97, 0x1b, 0xe7,
+ 0x3a, 0x55, 0x1a, 0x1d, 0xfe, 0x81, 0x6d, 0xf8, 0x7c, 0x75, 0x62, 0xae,
+ 0x76, 0xf4, 0x1d, 0x1d, 0xbe, 0xb8, 0x78, 0xa3, 0xbe, 0x13, 0xe8, 0xdb,
+ 0xd4, 0xd0, 0x77, 0x02, 0xfd, 0xda, 0x11, 0x07, 0xdb, 0x15, 0x4f, 0x93,
+ 0xa0, 0xeb, 0x4a, 0x51, 0xbd, 0x0b, 0x0c, 0xb9, 0x73, 0x4e, 0x93, 0x98,
+ 0x3a, 0xe3, 0xd5, 0x4a, 0x2c, 0x33, 0xa6, 0xbd, 0xa7, 0xde, 0xa3, 0x6c,
+ 0x60, 0xc8, 0x06, 0xee, 0x9d, 0x19, 0xd5, 0x52, 0x95, 0x1c, 0x62, 0xd6,
+ 0x2e, 0xe2, 0x27, 0xc7, 0x45, 0xcc, 0x5c, 0xc0, 0x78, 0x8b, 0xc5, 0x15,
+ 0x9e, 0xc1, 0x86, 0x5d, 0xbc, 0x4d, 0x9c, 0xbd, 0xcb, 0x50, 0x67, 0x1e,
+ 0xd2, 0xaa, 0x66, 0xb7, 0x50, 0x14, 0x33, 0x39, 0xc0, 0x33, 0x0e, 0xf7,
+ 0x63, 0x5d, 0x7e, 0x0e, 0x6d, 0x49, 0xc4, 0xc7, 0xc3, 0x5a, 0x72, 0x69,
+ 0x18, 0xd7, 0x8f, 0xe0, 0x1a, 0xfe, 0x78, 0x2e, 0x8b, 0xfb, 0x8f, 0xe0,
+ 0x7a, 0x42, 0x4b, 0xd5, 0xb2, 0xb8, 0x7e, 0x14, 0xd7, 0x49, 0x93, 0x79,
+ 0xca, 0x0f, 0xec, 0x8c, 0xe6, 0x62, 0x2c, 0x77, 0x69, 0x18, 0x9f, 0xc6,
+ 0xf1, 0x78, 0x0f, 0x7a, 0x2a, 0x72, 0xaf, 0x2d, 0x0e, 0x9a, 0x0e, 0x6a,
+ 0xe9, 0x4a, 0x1b, 0xc6, 0xe8, 0xc1, 0xf3, 0xb4, 0xa9, 0x43, 0xfe, 0xfc,
+ 0xac, 0x39, 0xdd, 0xad, 0x6a, 0x4e, 0x46, 0x22, 0x03, 0x9c, 0x7c, 0x1c,
+ 0x79, 0x80, 0x26, 0x69, 0xfb, 0x49, 0x29, 0x38, 0xf0, 0x2b, 0x15, 0x43,
+ 0x52, 0x91, 0x3c, 0x7e, 0xe7, 0x25, 0x39, 0x88, 0xfb, 0x15, 0xda, 0x02,
+ 0xfb, 0xfd, 0x89, 0x14, 0xca, 0xc4, 0xfd, 0xac, 0x33, 0xb1, 0x36, 0xc5,
+ 0xfa, 0x52, 0x0e, 0x32, 0x88, 0xd0, 0x7e, 0x6f, 0x50, 0x13, 0xf3, 0xce,
+ 0x55, 0x23, 0x2e, 0x6b, 0xc9, 0x0a, 0xf7, 0xfd, 0xdc, 0xcc, 0x45, 0x9b,
+ 0xef, 0x28, 0x4d, 0x70, 0x1f, 0xb1, 0x60, 0x24, 0x58, 0x1f, 0x51, 0xf5,
+ 0x75, 0xc7, 0xdb, 0x1f, 0xe4, 0xb8, 0x63, 0xe0, 0xb7, 0xb1, 0x6e, 0xc5,
+ 0x79, 0xbf, 0x80, 0xe7, 0xbd, 0x7a, 0x56, 0xaa, 0xf6, 0x5e, 0x5d, 0xf0,
+ 0xbd, 0x81, 0xf3, 0xd0, 0xc5, 0x45, 0x95, 0x1b, 0x73, 0x0f, 0xf7, 0xfd,
+ 0x72, 0x2a, 0xe4, 0x30, 0x45, 0xd6, 0xc8, 0x82, 0x7d, 0xbb, 0x40, 0x8e,
+ 0x9b, 0x69, 0x25, 0x9d, 0x47, 0x30, 0xa6, 0x38, 0xf4, 0xbb, 0xd9, 0x08,
+ 0xf7, 0xdf, 0xf8, 0x8c, 0x7c, 0xf9, 0x3a, 0xdd, 0xa4, 0x99, 0xf2, 0x38,
+ 0x0e, 0xff, 0xc9, 0x77, 0x32, 0x9e, 0x94, 0x9c, 0xc3, 0x1a, 0x8f, 0x81,
+ 0xd8, 0x98, 0xc7, 0xef, 0xeb, 0xf2, 0x9b, 0xf4, 0xe5, 0x97, 0x2b, 0xbf,
+ 0xa4, 0x74, 0xb8, 0x60, 0x73, 0xbe, 0xa0, 0xf6, 0x31, 0xa2, 0x74, 0xb7,
+ 0xa0, 0xce, 0xfd, 0x06, 0x32, 0x08, 0xea, 0x77, 0x37, 0xb6, 0xbd, 0x61,
+ 0x9b, 0xb4, 0xdd, 0xce, 0xf3, 0x10, 0xbd, 0xae, 0x90, 0x7e, 0xf2, 0xc1,
+ 0x18, 0x16, 0xec, 0xb5, 0x06, 0x3c, 0x04, 0x7c, 0xde, 0xaa, 0x7c, 0x48,
+ 0x6f, 0x64, 0xbb, 0xb4, 0x65, 0x4c, 0xc3, 0x66, 0x6c, 0xf8, 0x84, 0xbf,
+ 0x3f, 0xf0, 0x77, 0x21, 0x67, 0x4f, 0x16, 0xa1, 0x84, 0x4c, 0xfa, 0xef,
+ 0xf8, 0xde, 0xc0, 0x1e, 0x36, 0xef, 0x35, 0xbb, 0x99, 0x73, 0xf6, 0x75,
+ 0xbe, 0x17, 0x6e, 0xc0, 0xf7, 0x82, 0xcf, 0x77, 0xe5, 0x16, 0xe9, 0x5d,
+ 0x98, 0x71, 0xc1, 0x33, 0x6d, 0xee, 0x46, 0xf6, 0x28, 0xea, 0x7f, 0x5f,
+ 0xac, 0x19, 0xe1, 0xb0, 0x5b, 0xbd, 0x59, 0x0d, 0x95, 0x79, 0xb5, 0x67,
+ 0x97, 0xe7, 0x10, 0x0b, 0xcb, 0x65, 0x2f, 0xc7, 0x2e, 0x57, 0x59, 0xcb,
+ 0x7e, 0x3f, 0x1a, 0xf8, 0xfe, 0xd7, 0x67, 0xd4, 0x79, 0x97, 0xc9, 0xaa,
+ 0x57, 0xf7, 0x2a, 0x97, 0x1b, 0x63, 0xea, 0x0e, 0xc6, 0xd3, 0xde, 0xbc,
+ 0x8c, 0xf2, 0xbd, 0x65, 0x5c, 0xef, 0x96, 0x4b, 0x73, 0x6a, 0xcf, 0xca,
+ 0xdf, 0x1b, 0xe2, 0x9e, 0x8f, 0xda, 0xff, 0x86, 0x5f, 0x1b, 0x53, 0x7e,
+ 0x7d, 0x75, 0x4e, 0xdd, 0xf3, 0xb0, 0x52, 0x75, 0x14, 0x7e, 0x1f, 0xb9,
+ 0x84, 0xbd, 0x55, 0x0a, 0xc8, 0xb9, 0xcf, 0xd9, 0x0f, 0x6f, 0x27, 0xce,
+ 0xe1, 0x58, 0xab, 0x18, 0xeb, 0xe2, 0x9c, 0x6c, 0xe7, 0x99, 0x92, 0xb2,
+ 0xda, 0x67, 0xf3, 0xea, 0xe2, 0x13, 0x12, 0xfc, 0x4f, 0x88, 0xb0, 0x1f,
+ 0x0b, 0x79, 0xae, 0x85, 0xef, 0xd2, 0xd2, 0x57, 0x20, 0x0f, 0x1a, 0xe5,
+ 0x3e, 0x4e, 0xbd, 0xee, 0xd5, 0xcd, 0xeb, 0x58, 0x17, 0x4d, 0x7c, 0xef,
+ 0x02, 0x7f, 0xc7, 0x61, 0x3f, 0x58, 0x27, 0xeb, 0xed, 0xbc, 0x66, 0xee,
+ 0x11, 0x5c, 0x33, 0xb0, 0xfd, 0x3f, 0xd4, 0x46, 0x90, 0x7c, 0xb4, 0x45,
+ 0x00, 0x00, 0x00 };
static const u32 bnx2_TXP_b09FwData[(0xd0/4) + 1] = {
0x00000000, 0x00000014, 0x00000014, 0x00000014, 0x00000014, 0x00000010,
@@ -4041,37 +4065,38 @@ static const u32 bnx2_TXP_b09FwData[(0xd0/4) + 1] = {
0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 };
static const u32 bnx2_TXP_b09FwRodata[(0x30/4) + 1] = {
- 0x08004060, 0x0800408c, 0x080040d4, 0x080040d4, 0x08003f60, 0x08003f8c,
- 0x08003f8c, 0x080040d4, 0x080040d4, 0x080040d4, 0x08003ff4, 0x00000000,
+ 0x08003fdc, 0x08004008, 0x08004050, 0x08004050, 0x08003edc, 0x08003f08,
+ 0x08003f08, 0x08004050, 0x08004050, 0x08004050, 0x08003f70, 0x00000000,
0x00000000 };
static struct fw_info bnx2_txp_fw_09 = {
+ /* Firmware version: 3.7.1 */
.ver_major = 0x3,
- .ver_minor = 0x4,
- .ver_fix = 0x3,
+ .ver_minor = 0x7,
+ .ver_fix = 0x1,
.start_addr = 0x08000060,
.text_addr = 0x08000000,
- .text_len = 0x4634,
+ .text_len = 0x45b0,
.text_index = 0x0,
.gz_text = bnx2_TXP_b09FwText,
.gz_text_len = sizeof(bnx2_TXP_b09FwText),
- .data_addr = 0x08004680,
+ .data_addr = 0x08004600,
.data_len = 0xd0,
.data_index = 0x0,
.data = bnx2_TXP_b09FwData,
- .sbss_addr = 0x08004750,
+ .sbss_addr = 0x080046d0,
.sbss_len = 0x8c,
.sbss_index = 0x0,
- .bss_addr = 0x080047e0,
+ .bss_addr = 0x08004760,
.bss_len = 0xa20,
.bss_index = 0x0,
- .rodata_addr = 0x08004638,
+ .rodata_addr = 0x080045b0,
.rodata_len = 0x30,
.rodata_index = 0x0,
.rodata = bnx2_TXP_b09FwRodata,
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 7a045a37056e..cb3c6faa7888 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -126,7 +126,7 @@ static struct aggregator *__get_active_agg(struct aggregator *aggregator);
// ================= main 802.3ad protocol functions ==================
static int ad_lacpdu_send(struct port *port);
-static int ad_marker_send(struct port *port, struct marker *marker);
+static int ad_marker_send(struct port *port, struct bond_marker *marker);
static void ad_mux_machine(struct port *port);
static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port);
static void ad_tx_machine(struct port *port);
@@ -139,8 +139,8 @@ static void ad_initialize_port(struct port *port, int lacp_fast);
static void ad_initialize_lacpdu(struct lacpdu *Lacpdu);
static void ad_enable_collecting_distributing(struct port *port);
static void ad_disable_collecting_distributing(struct port *port);
-static void ad_marker_info_received(struct marker *marker_info, struct port *port);
-static void ad_marker_response_received(struct marker *marker, struct port *port);
+static void ad_marker_info_received(struct bond_marker *marker_info, struct port *port);
+static void ad_marker_response_received(struct bond_marker *marker, struct port *port);
/////////////////////////////////////////////////////////////////////////////////
@@ -889,12 +889,12 @@ static int ad_lacpdu_send(struct port *port)
* Returns: 0 on success
* < 0 on error
*/
-static int ad_marker_send(struct port *port, struct marker *marker)
+static int ad_marker_send(struct port *port, struct bond_marker *marker)
{
struct slave *slave = port->slave;
struct sk_buff *skb;
- struct marker_header *marker_header;
- int length = sizeof(struct marker_header);
+ struct bond_marker_header *marker_header;
+ int length = sizeof(struct bond_marker_header);
struct mac_addr lacpdu_multicast_address = AD_MULTICAST_LACPDU_ADDR;
skb = dev_alloc_skb(length + 16);
@@ -909,7 +909,7 @@ static int ad_marker_send(struct port *port, struct marker *marker)
skb->network_header = skb->mac_header + ETH_HLEN;
skb->protocol = PKT_TYPE_LACPDU;
- marker_header = (struct marker_header *)skb_put(skb, length);
+ marker_header = (struct bond_marker_header *)skb_put(skb, length);
marker_header->ad_header.destination_address = lacpdu_multicast_address;
/* Note: source addres is set to be the member's PERMANENT address, because we use it
@@ -1709,7 +1709,7 @@ static void ad_disable_collecting_distributing(struct port *port)
*/
static void ad_marker_info_send(struct port *port)
{
- struct marker marker;
+ struct bond_marker marker;
u16 index;
// fill the marker PDU with the appropriate values
@@ -1742,13 +1742,14 @@ static void ad_marker_info_send(struct port *port)
* @port: the port we're looking at
*
*/
-static void ad_marker_info_received(struct marker *marker_info,struct port *port)
+static void ad_marker_info_received(struct bond_marker *marker_info,
+ struct port *port)
{
- struct marker marker;
+ struct bond_marker marker;
// copy the received marker data to the response marker
//marker = *marker_info;
- memcpy(&marker, marker_info, sizeof(struct marker));
+ memcpy(&marker, marker_info, sizeof(struct bond_marker));
// change the marker subtype to marker response
marker.tlv_type=AD_MARKER_RESPONSE_SUBTYPE;
// send the marker response
@@ -1767,7 +1768,8 @@ static void ad_marker_info_received(struct marker *marker_info,struct port *port
* response for marker PDU's, in this stage, but only to respond to marker
* information.
*/
-static void ad_marker_response_received(struct marker *marker, struct port *port)
+static void ad_marker_response_received(struct bond_marker *marker,
+ struct port *port)
{
marker=NULL; // just to satisfy the compiler
port=NULL; // just to satisfy the compiler
@@ -2074,8 +2076,10 @@ void bond_3ad_unbind_slave(struct slave *slave)
* times out, and it selects an aggregator for the ports that are yet not
* related to any aggregator, and selects the active aggregator for a bond.
*/
-void bond_3ad_state_machine_handler(struct bonding *bond)
+void bond_3ad_state_machine_handler(struct work_struct *work)
{
+ struct bonding *bond = container_of(work, struct bonding,
+ ad_work.work);
struct port *port;
struct aggregator *aggregator;
@@ -2126,7 +2130,7 @@ void bond_3ad_state_machine_handler(struct bonding *bond)
}
re_arm:
- mod_timer(&(BOND_AD_INFO(bond).ad_timer), jiffies + ad_delta_in_ticks);
+ queue_delayed_work(bond->wq, &bond->ad_work, ad_delta_in_ticks);
out:
read_unlock(&bond->lock);
}
@@ -2164,15 +2168,15 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u
case AD_TYPE_MARKER:
// No need to convert fields to Little Endian since we don't use the marker's fields.
- switch (((struct marker *)lacpdu)->tlv_type) {
+ switch (((struct bond_marker *)lacpdu)->tlv_type) {
case AD_MARKER_INFORMATION_SUBTYPE:
dprintk("Received Marker Information on port %d\n", port->actor_port_number);
- ad_marker_info_received((struct marker *)lacpdu, port);
+ ad_marker_info_received((struct bond_marker *)lacpdu, port);
break;
case AD_MARKER_RESPONSE_SUBTYPE:
dprintk("Received Marker Response on port %d\n", port->actor_port_number);
- ad_marker_response_received((struct marker *)lacpdu, port);
+ ad_marker_response_received((struct bond_marker *)lacpdu, port);
break;
default:
diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h
index 862952fa6fd9..b5ee45f6d55a 100644
--- a/drivers/net/bonding/bond_3ad.h
+++ b/drivers/net/bonding/bond_3ad.h
@@ -92,7 +92,7 @@ typedef enum {
typedef enum {
AD_MARKER_INFORMATION_SUBTYPE = 1, // marker imformation subtype
AD_MARKER_RESPONSE_SUBTYPE // marker response subtype
-} marker_subtype_t;
+} bond_marker_subtype_t;
// timers types(43.4.9 in the 802.3ad standard)
typedef enum {
@@ -148,7 +148,7 @@ typedef struct lacpdu_header {
} lacpdu_header_t;
// Marker Protocol Data Unit(PDU) structure(43.5.3.2 in the 802.3ad standard)
-typedef struct marker {
+typedef struct bond_marker {
u8 subtype; // = 0x02 (marker PDU)
u8 version_number; // = 0x01
u8 tlv_type; // = 0x01 (marker information)
@@ -161,12 +161,12 @@ typedef struct marker {
u8 tlv_type_terminator; // = 0x00
u8 terminator_length; // = 0x00
u8 reserved_90[90]; // = 0
-} marker_t;
+} bond_marker_t;
-typedef struct marker_header {
+typedef struct bond_marker_header {
struct ad_header ad_header;
- struct marker marker;
-} marker_header_t;
+ struct bond_marker marker;
+} bond_marker_header_t;
#pragma pack()
@@ -276,7 +276,7 @@ struct ad_slave_info {
void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution, int lacp_fast);
int bond_3ad_bind_slave(struct slave *slave);
void bond_3ad_unbind_slave(struct slave *slave);
-void bond_3ad_state_machine_handler(struct bonding *bond);
+void bond_3ad_state_machine_handler(struct work_struct *);
void bond_3ad_adapter_speed_changed(struct slave *slave);
void bond_3ad_adapter_duplex_changed(struct slave *slave);
void bond_3ad_handle_link_change(struct slave *slave, char link);
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index aea2217c56eb..25b8dbf6cfd7 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -128,12 +128,12 @@ static inline u8 _simple_hash(const u8 *hash_start, int hash_size)
static inline void _lock_tx_hashtbl(struct bonding *bond)
{
- spin_lock(&(BOND_ALB_INFO(bond).tx_hashtbl_lock));
+ spin_lock_bh(&(BOND_ALB_INFO(bond).tx_hashtbl_lock));
}
static inline void _unlock_tx_hashtbl(struct bonding *bond)
{
- spin_unlock(&(BOND_ALB_INFO(bond).tx_hashtbl_lock));
+ spin_unlock_bh(&(BOND_ALB_INFO(bond).tx_hashtbl_lock));
}
/* Caller must hold tx_hashtbl lock */
@@ -305,12 +305,12 @@ static struct slave *tlb_choose_channel(struct bonding *bond, u32 hash_index, u3
/*********************** rlb specific functions ***************************/
static inline void _lock_rx_hashtbl(struct bonding *bond)
{
- spin_lock(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
+ spin_lock_bh(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
}
static inline void _unlock_rx_hashtbl(struct bonding *bond)
{
- spin_unlock(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
+ spin_unlock_bh(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
}
/* when an ARP REPLY is received from a client update its info
@@ -472,13 +472,13 @@ static void rlb_clear_slave(struct bonding *bond, struct slave *slave)
_unlock_rx_hashtbl(bond);
- write_lock(&bond->curr_slave_lock);
+ write_lock_bh(&bond->curr_slave_lock);
if (slave != bond->curr_active_slave) {
rlb_teach_disabled_mac_on_primary(bond, slave->dev->dev_addr);
}
- write_unlock(&bond->curr_slave_lock);
+ write_unlock_bh(&bond->curr_slave_lock);
}
static void rlb_update_client(struct rlb_client_info *client_info)
@@ -959,19 +959,34 @@ static int alb_set_slave_mac_addr(struct slave *slave, u8 addr[], int hw)
return 0;
}
-/* Caller must hold bond lock for write or curr_slave_lock for write*/
+/*
+ * Swap MAC addresses between two slaves.
+ *
+ * Called with RTNL held, and no other locks.
+ *
+ */
+
static void alb_swap_mac_addr(struct bonding *bond, struct slave *slave1, struct slave *slave2)
{
- struct slave *disabled_slave = NULL;
u8 tmp_mac_addr[ETH_ALEN];
- int slaves_state_differ;
-
- slaves_state_differ = (SLAVE_IS_OK(slave1) != SLAVE_IS_OK(slave2));
memcpy(tmp_mac_addr, slave1->dev->dev_addr, ETH_ALEN);
alb_set_slave_mac_addr(slave1, slave2->dev->dev_addr, bond->alb_info.rlb_enabled);
alb_set_slave_mac_addr(slave2, tmp_mac_addr, bond->alb_info.rlb_enabled);
+}
+
+/*
+ * Send learning packets after MAC address swap.
+ *
+ * Called with RTNL and bond->lock held for read.
+ */
+static void alb_fasten_mac_swap(struct bonding *bond, struct slave *slave1,
+ struct slave *slave2)
+{
+ int slaves_state_differ = (SLAVE_IS_OK(slave1) != SLAVE_IS_OK(slave2));
+ struct slave *disabled_slave = NULL;
+
/* fasten the change in the switch */
if (SLAVE_IS_OK(slave1)) {
alb_send_learning_packets(slave1, slave1->dev->dev_addr);
@@ -1044,7 +1059,9 @@ static void alb_change_hw_addr_on_detach(struct bonding *bond, struct slave *sla
}
if (found) {
+ /* locking: needs RTNL and nothing else */
alb_swap_mac_addr(bond, slave, tmp_slave);
+ alb_fasten_mac_swap(bond, slave, tmp_slave);
}
}
}
@@ -1375,8 +1392,10 @@ out:
return 0;
}
-void bond_alb_monitor(struct bonding *bond)
+void bond_alb_monitor(struct work_struct *work)
{
+ struct bonding *bond = container_of(work, struct bonding,
+ alb_work.work);
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
struct slave *slave;
int i;
@@ -1436,16 +1455,16 @@ void bond_alb_monitor(struct bonding *bond)
/* handle rlb stuff */
if (bond_info->rlb_enabled) {
- /* the following code changes the promiscuity of the
- * the curr_active_slave. It needs to be locked with a
- * write lock to protect from other code that also
- * sets the promiscuity.
- */
- write_lock_bh(&bond->curr_slave_lock);
-
if (bond_info->primary_is_promisc &&
(++bond_info->rlb_promisc_timeout_counter >= RLB_PROMISC_TIMEOUT)) {
+ /*
+ * dev_set_promiscuity requires rtnl and
+ * nothing else.
+ */
+ read_unlock(&bond->lock);
+ rtnl_lock();
+
bond_info->rlb_promisc_timeout_counter = 0;
/* If the primary was set to promiscuous mode
@@ -1454,9 +1473,10 @@ void bond_alb_monitor(struct bonding *bond)
*/
dev_set_promiscuity(bond->curr_active_slave->dev, -1);
bond_info->primary_is_promisc = 0;
- }
- write_unlock_bh(&bond->curr_slave_lock);
+ rtnl_unlock();
+ read_lock(&bond->lock);
+ }
if (bond_info->rlb_rebalance) {
bond_info->rlb_rebalance = 0;
@@ -1479,7 +1499,7 @@ void bond_alb_monitor(struct bonding *bond)
}
re_arm:
- mod_timer(&(bond_info->alb_timer), jiffies + alb_delta_in_ticks);
+ queue_delayed_work(bond->wq, &bond->alb_work, alb_delta_in_ticks);
out:
read_unlock(&bond->lock);
}
@@ -1500,11 +1520,11 @@ int bond_alb_init_slave(struct bonding *bond, struct slave *slave)
/* caller must hold the bond lock for write since the mac addresses
* are compared and may be swapped.
*/
- write_lock_bh(&bond->lock);
+ read_lock(&bond->lock);
res = alb_handle_addr_collision_on_attach(bond, slave);
- write_unlock_bh(&bond->lock);
+ read_unlock(&bond->lock);
if (res) {
return res;
@@ -1569,13 +1589,21 @@ void bond_alb_handle_link_change(struct bonding *bond, struct slave *slave, char
* Set the bond->curr_active_slave to @new_slave and handle
* mac address swapping and promiscuity changes as needed.
*
- * Caller must hold bond curr_slave_lock for write (or bond lock for write)
+ * If new_slave is NULL, caller must hold curr_slave_lock or
+ * bond->lock for write.
+ *
+ * If new_slave is not NULL, caller must hold RTNL, bond->lock for
+ * read and curr_slave_lock for write. Processing here may sleep, so
+ * no other locks may be held.
*/
void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave)
{
struct slave *swap_slave;
int i;
+ if (new_slave)
+ ASSERT_RTNL();
+
if (bond->curr_active_slave == new_slave) {
return;
}
@@ -1608,6 +1636,19 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave
}
}
+ /*
+ * Arrange for swap_slave and new_slave to temporarily be
+ * ignored so we can mess with their MAC addresses without
+ * fear of interference from transmit activity.
+ */
+ if (swap_slave) {
+ tlb_clear_slave(bond, swap_slave, 1);
+ }
+ tlb_clear_slave(bond, new_slave, 1);
+
+ write_unlock_bh(&bond->curr_slave_lock);
+ read_unlock(&bond->lock);
+
/* curr_active_slave must be set before calling alb_swap_mac_addr */
if (swap_slave) {
/* swap mac address */
@@ -1616,11 +1657,23 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave
/* set the new_slave to the bond mac address */
alb_set_slave_mac_addr(new_slave, bond->dev->dev_addr,
bond->alb_info.rlb_enabled);
+ }
+
+ read_lock(&bond->lock);
+
+ if (swap_slave) {
+ alb_fasten_mac_swap(bond, swap_slave, new_slave);
+ } else {
/* fasten bond mac on new current slave */
alb_send_learning_packets(new_slave, bond->dev->dev_addr);
}
+
+ write_lock_bh(&bond->curr_slave_lock);
}
+/*
+ * Called with RTNL
+ */
int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr)
{
struct bonding *bond = bond_dev->priv;
@@ -1657,8 +1710,12 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr)
}
}
+ write_unlock_bh(&bond->curr_slave_lock);
+ read_unlock(&bond->lock);
+
if (swap_slave) {
alb_swap_mac_addr(bond, swap_slave, bond->curr_active_slave);
+ alb_fasten_mac_swap(bond, swap_slave, bond->curr_active_slave);
} else {
alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr,
bond->alb_info.rlb_enabled);
@@ -1670,6 +1727,9 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr)
}
}
+ read_lock(&bond->lock);
+ write_lock_bh(&bond->curr_slave_lock);
+
return 0;
}
diff --git a/drivers/net/bonding/bond_alb.h b/drivers/net/bonding/bond_alb.h
index fd8726429890..50968f8196cf 100644
--- a/drivers/net/bonding/bond_alb.h
+++ b/drivers/net/bonding/bond_alb.h
@@ -125,7 +125,7 @@ void bond_alb_deinit_slave(struct bonding *bond, struct slave *slave);
void bond_alb_handle_link_change(struct bonding *bond, struct slave *slave, char link);
void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave);
int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev);
-void bond_alb_monitor(struct bonding *bond);
+void bond_alb_monitor(struct work_struct *);
int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr);
void bond_alb_clear_vlan(struct bonding *bond, unsigned short vlan_id);
#endif /* __BOND_ALB_H__ */
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 64bfec32e2a6..423298c84a1d 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -98,6 +98,7 @@ static char *xmit_hash_policy = NULL;
static int arp_interval = BOND_LINK_ARP_INTERV;
static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, };
static char *arp_validate = NULL;
+static int fail_over_mac = 0;
struct bond_params bonding_defaults;
module_param(max_bonds, int, 0);
@@ -131,6 +132,8 @@ module_param_array(arp_ip_target, charp, NULL, 0);
MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form");
module_param(arp_validate, charp, 0);
MODULE_PARM_DESC(arp_validate, "validate src/dst of ARP probes: none (default), active, backup or all");
+module_param(fail_over_mac, int, 0);
+MODULE_PARM_DESC(fail_over_mac, "For active-backup, do not set all slaves to the same MAC. 0 of off (default), 1 for on.");
/*----------------------------- Global variables ----------------------------*/
@@ -185,6 +188,7 @@ struct bond_parm_tbl arp_validate_tbl[] = {
/*-------------------------- Forward declarations ---------------------------*/
static void bond_send_gratuitous_arp(struct bonding *bond);
+static void bond_deinit(struct net_device *bond_dev);
/*---------------------------- General routines -----------------------------*/
@@ -1096,7 +1100,21 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
if (new_active) {
bond_set_slave_active_flags(new_active);
}
- bond_send_gratuitous_arp(bond);
+
+ /* when bonding does not set the slave MAC address, the bond MAC
+ * address is the one of the active slave.
+ */
+ if (new_active && bond->params.fail_over_mac)
+ memcpy(bond->dev->dev_addr, new_active->dev->dev_addr,
+ new_active->dev->addr_len);
+ if (bond->curr_active_slave &&
+ test_bit(__LINK_STATE_LINKWATCH_PENDING,
+ &bond->curr_active_slave->dev->state)) {
+ dprintk("delaying gratuitous arp on %s\n",
+ bond->curr_active_slave->dev->name);
+ bond->send_grat_arp = 1;
+ } else
+ bond_send_gratuitous_arp(bond);
}
}
@@ -1217,7 +1235,8 @@ static int bond_compute_features(struct bonding *bond)
struct slave *slave;
struct net_device *bond_dev = bond->dev;
unsigned long features = bond_dev->features;
- unsigned short max_hard_header_len = ETH_HLEN;
+ unsigned short max_hard_header_len = max((u16)ETH_HLEN,
+ bond_dev->hard_header_len);
int i;
features &= ~(NETIF_F_ALL_CSUM | BOND_VLAN_FEATURES);
@@ -1238,6 +1257,24 @@ static int bond_compute_features(struct bonding *bond)
return 0;
}
+
+static void bond_setup_by_slave(struct net_device *bond_dev,
+ struct net_device *slave_dev)
+{
+ struct bonding *bond = bond_dev->priv;
+
+ bond_dev->neigh_setup = slave_dev->neigh_setup;
+ bond_dev->header_ops = slave_dev->header_ops;
+
+ bond_dev->type = slave_dev->type;
+ bond_dev->hard_header_len = slave_dev->hard_header_len;
+ bond_dev->addr_len = slave_dev->addr_len;
+
+ memcpy(bond_dev->broadcast, slave_dev->broadcast,
+ slave_dev->addr_len);
+ bond->setup_by_slave = 1;
+}
+
/* enslave device <slave> to bond device <master> */
int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
{
@@ -1258,8 +1295,9 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
/* bond must be initialized by bond_open() before enslaving */
if (!(bond_dev->flags & IFF_UP)) {
- dprintk("Error, master_dev is not up\n");
- return -EPERM;
+ printk(KERN_WARNING DRV_NAME
+ " %s: master_dev is not up in bond_enslave\n",
+ bond_dev->name);
}
/* already enslaved */
@@ -1312,14 +1350,42 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
goto err_undo_flags;
}
+ /* set bonding device ether type by slave - bonding netdevices are
+ * created with ether_setup, so when the slave type is not ARPHRD_ETHER
+ * there is a need to override some of the type dependent attribs/funcs.
+ *
+ * bond ether type mutual exclusion - don't allow slaves of dissimilar
+ * ether type (eg ARPHRD_ETHER and ARPHRD_INFINIBAND) share the same bond
+ */
+ if (bond->slave_cnt == 0) {
+ if (slave_dev->type != ARPHRD_ETHER)
+ bond_setup_by_slave(bond_dev, slave_dev);
+ } else if (bond_dev->type != slave_dev->type) {
+ printk(KERN_ERR DRV_NAME ": %s ether type (%d) is different "
+ "from other slaves (%d), can not enslave it.\n",
+ slave_dev->name,
+ slave_dev->type, bond_dev->type);
+ res = -EINVAL;
+ goto err_undo_flags;
+ }
+
if (slave_dev->set_mac_address == NULL) {
- printk(KERN_ERR DRV_NAME
- ": %s: Error: The slave device you specified does "
- "not support setting the MAC address. "
- "Your kernel likely does not support slave "
- "devices.\n", bond_dev->name);
- res = -EOPNOTSUPP;
- goto err_undo_flags;
+ if (bond->slave_cnt == 0) {
+ printk(KERN_WARNING DRV_NAME
+ ": %s: Warning: The first slave device "
+ "specified does not support setting the MAC "
+ "address. Enabling the fail_over_mac option.",
+ bond_dev->name);
+ bond->params.fail_over_mac = 1;
+ } else if (!bond->params.fail_over_mac) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Error: The slave device specified "
+ "does not support setting the MAC address, "
+ "but fail_over_mac is not enabled.\n"
+ , bond_dev->name);
+ res = -EOPNOTSUPP;
+ goto err_undo_flags;
+ }
}
new_slave = kzalloc(sizeof(struct slave), GFP_KERNEL);
@@ -1340,16 +1406,18 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
*/
memcpy(new_slave->perm_hwaddr, slave_dev->dev_addr, ETH_ALEN);
- /*
- * Set slave to master's mac address. The application already
- * set the master's mac address to that of the first slave
- */
- memcpy(addr.sa_data, bond_dev->dev_addr, bond_dev->addr_len);
- addr.sa_family = slave_dev->type;
- res = dev_set_mac_address(slave_dev, &addr);
- if (res) {
- dprintk("Error %d calling set_mac_address\n", res);
- goto err_free;
+ if (!bond->params.fail_over_mac) {
+ /*
+ * Set slave to master's mac address. The application already
+ * set the master's mac address to that of the first slave
+ */
+ memcpy(addr.sa_data, bond_dev->dev_addr, bond_dev->addr_len);
+ addr.sa_family = slave_dev->type;
+ res = dev_set_mac_address(slave_dev, &addr);
+ if (res) {
+ dprintk("Error %d calling set_mac_address\n", res);
+ goto err_free;
+ }
}
res = netdev_set_master(slave_dev, bond_dev);
@@ -1523,15 +1591,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
case BOND_MODE_TLB:
case BOND_MODE_ALB:
new_slave->state = BOND_STATE_ACTIVE;
- if ((!bond->curr_active_slave) &&
- (new_slave->link != BOND_LINK_DOWN)) {
- /* first slave or no active slave yet, and this link
- * is OK, so make this interface the active one
- */
- bond_change_active_slave(bond, new_slave);
- } else {
- bond_set_slave_inactive_flags(new_slave);
- }
+ bond_set_slave_inactive_flags(new_slave);
break;
default:
dprintk("This slave is always active in trunk mode\n");
@@ -1574,9 +1634,11 @@ err_close:
dev_close(slave_dev);
err_restore_mac:
- memcpy(addr.sa_data, new_slave->perm_hwaddr, ETH_ALEN);
- addr.sa_family = slave_dev->type;
- dev_set_mac_address(slave_dev, &addr);
+ if (!bond->params.fail_over_mac) {
+ memcpy(addr.sa_data, new_slave->perm_hwaddr, ETH_ALEN);
+ addr.sa_family = slave_dev->type;
+ dev_set_mac_address(slave_dev, &addr);
+ }
err_free:
kfree(new_slave);
@@ -1685,9 +1747,23 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
bond_alb_deinit_slave(bond, slave);
}
- if (oldcurrent == slave)
+ if (oldcurrent == slave) {
+ /*
+ * Note that we hold RTNL over this sequence, so there
+ * is no concern that another slave add/remove event
+ * will interfere.
+ */
+ write_unlock_bh(&bond->lock);
+ read_lock(&bond->lock);
+ write_lock_bh(&bond->curr_slave_lock);
+
bond_select_active_slave(bond);
+ write_unlock_bh(&bond->curr_slave_lock);
+ read_unlock(&bond->lock);
+ write_lock_bh(&bond->lock);
+ }
+
if (bond->slave_cnt == 0) {
bond_set_carrier(bond);
@@ -1749,10 +1825,12 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
/* close slave before restoring its mac address */
dev_close(slave_dev);
- /* restore original ("permanent") mac address */
- memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN);
- addr.sa_family = slave_dev->type;
- dev_set_mac_address(slave_dev, &addr);
+ if (!bond->params.fail_over_mac) {
+ /* restore original ("permanent") mac address */
+ memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN);
+ addr.sa_family = slave_dev->type;
+ dev_set_mac_address(slave_dev, &addr);
+ }
slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB |
IFF_SLAVE_INACTIVE | IFF_BONDING |
@@ -1764,6 +1842,35 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
}
/*
+* Destroy a bonding device.
+* Must be under rtnl_lock when this function is called.
+*/
+void bond_destroy(struct bonding *bond)
+{
+ bond_deinit(bond->dev);
+ bond_destroy_sysfs_entry(bond);
+ unregister_netdevice(bond->dev);
+}
+
+/*
+* First release a slave and than destroy the bond if no more slaves iare left.
+* Must be under rtnl_lock when this function is called.
+*/
+int bond_release_and_destroy(struct net_device *bond_dev, struct net_device *slave_dev)
+{
+ struct bonding *bond = bond_dev->priv;
+ int ret;
+
+ ret = bond_release(bond_dev, slave_dev);
+ if ((ret == 0) && (bond->slave_cnt == 0)) {
+ printk(KERN_INFO DRV_NAME ": %s: destroying bond %s.\n",
+ bond_dev->name, bond_dev->name);
+ bond_destroy(bond);
+ }
+ return ret;
+}
+
+/*
* This function releases all slaves.
*/
static int bond_release_all(struct net_device *bond_dev)
@@ -1839,10 +1946,12 @@ static int bond_release_all(struct net_device *bond_dev)
/* close slave before restoring its mac address */
dev_close(slave_dev);
- /* restore original ("permanent") mac address*/
- memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN);
- addr.sa_family = slave_dev->type;
- dev_set_mac_address(slave_dev, &addr);
+ if (!bond->params.fail_over_mac) {
+ /* restore original ("permanent") mac address*/
+ memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN);
+ addr.sa_family = slave_dev->type;
+ dev_set_mac_address(slave_dev, &addr);
+ }
slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB |
IFF_SLAVE_INACTIVE);
@@ -1910,16 +2019,19 @@ static int bond_ioctl_change_active(struct net_device *bond_dev, struct net_devi
return -EINVAL;
}
- write_lock_bh(&bond->lock);
+ read_lock(&bond->lock);
+ read_lock(&bond->curr_slave_lock);
old_active = bond->curr_active_slave;
+ read_unlock(&bond->curr_slave_lock);
+
new_active = bond_get_slave_by_dev(bond, slave_dev);
/*
* Changing to the current active: do nothing; return success.
*/
if (new_active && (new_active == old_active)) {
- write_unlock_bh(&bond->lock);
+ read_unlock(&bond->lock);
return 0;
}
@@ -1927,12 +2039,14 @@ static int bond_ioctl_change_active(struct net_device *bond_dev, struct net_devi
(old_active) &&
(new_active->link == BOND_LINK_UP) &&
IS_UP(new_active->dev)) {
+ write_lock_bh(&bond->curr_slave_lock);
bond_change_active_slave(bond, new_active);
+ write_unlock_bh(&bond->curr_slave_lock);
} else {
res = -EINVAL;
}
- write_unlock_bh(&bond->lock);
+ read_unlock(&bond->lock);
return res;
}
@@ -1944,9 +2058,9 @@ static int bond_info_query(struct net_device *bond_dev, struct ifbond *info)
info->bond_mode = bond->params.mode;
info->miimon = bond->params.miimon;
- read_lock_bh(&bond->lock);
+ read_lock(&bond->lock);
info->num_slaves = bond->slave_cnt;
- read_unlock_bh(&bond->lock);
+ read_unlock(&bond->lock);
return 0;
}
@@ -1961,7 +2075,7 @@ static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *in
return -ENODEV;
}
- read_lock_bh(&bond->lock);
+ read_lock(&bond->lock);
bond_for_each_slave(bond, slave, i) {
if (i == (int)info->slave_id) {
@@ -1970,7 +2084,7 @@ static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *in
}
}
- read_unlock_bh(&bond->lock);
+ read_unlock(&bond->lock);
if (found) {
strcpy(info->slave_name, slave->dev->name);
@@ -1986,26 +2100,25 @@ static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *in
/*-------------------------------- Monitoring -------------------------------*/
-/* this function is called regularly to monitor each slave's link. */
-void bond_mii_monitor(struct net_device *bond_dev)
+/*
+ * if !have_locks, return nonzero if a failover is necessary. if
+ * have_locks, do whatever failover activities are needed.
+ *
+ * This is to separate the inspection and failover steps for locking
+ * purposes; failover requires rtnl, but acquiring it for every
+ * inspection is undesirable, so a wrapper first does inspection, and
+ * the acquires the necessary locks and calls again to perform
+ * failover if needed. Since all locks are dropped, a complete
+ * restart is needed between calls.
+ */
+static int __bond_mii_monitor(struct bonding *bond, int have_locks)
{
- struct bonding *bond = bond_dev->priv;
struct slave *slave, *oldcurrent;
int do_failover = 0;
- int delta_in_ticks;
int i;
- read_lock(&bond->lock);
-
- delta_in_ticks = (bond->params.miimon * HZ) / 1000;
-
- if (bond->kill_timers) {
+ if (bond->slave_cnt == 0)
goto out;
- }
-
- if (bond->slave_cnt == 0) {
- goto re_arm;
- }
/* we will try to read the link status of each of our slaves, and
* set their IFF_RUNNING flag appropriately. For each slave not
@@ -2013,6 +2126,17 @@ void bond_mii_monitor(struct net_device *bond_dev)
* program could monitor the link itself if needed.
*/
+ if (bond->send_grat_arp) {
+ if (bond->curr_active_slave && test_bit(__LINK_STATE_LINKWATCH_PENDING,
+ &bond->curr_active_slave->dev->state))
+ dprintk("Needs to send gratuitous arp but not yet\n");
+ else {
+ dprintk("sending delayed gratuitous arp on on %s\n",
+ bond->curr_active_slave->dev->name);
+ bond_send_gratuitous_arp(bond);
+ bond->send_grat_arp = 0;
+ }
+ }
read_lock(&bond->curr_slave_lock);
oldcurrent = bond->curr_active_slave;
read_unlock(&bond->curr_slave_lock);
@@ -2028,7 +2152,11 @@ void bond_mii_monitor(struct net_device *bond_dev)
switch (slave->link) {
case BOND_LINK_UP: /* the link was up */
if (link_state == BMSR_LSTATUS) {
- /* link stays up, nothing more to do */
+ if (!oldcurrent) {
+ if (!have_locks)
+ return 1;
+ do_failover = 1;
+ }
break;
} else { /* link going down */
slave->link = BOND_LINK_FAIL;
@@ -2043,7 +2171,7 @@ void bond_mii_monitor(struct net_device *bond_dev)
": %s: link status down for %s "
"interface %s, disabling it in "
"%d ms.\n",
- bond_dev->name,
+ bond->dev->name,
IS_UP(slave_dev)
? ((bond->params.mode == BOND_MODE_ACTIVEBACKUP)
? ((slave == oldcurrent)
@@ -2061,6 +2189,9 @@ void bond_mii_monitor(struct net_device *bond_dev)
if (link_state != BMSR_LSTATUS) {
/* link stays down */
if (slave->delay <= 0) {
+ if (!have_locks)
+ return 1;
+
/* link down for too long time */
slave->link = BOND_LINK_DOWN;
@@ -2076,7 +2207,7 @@ void bond_mii_monitor(struct net_device *bond_dev)
": %s: link status definitely "
"down for interface %s, "
"disabling it\n",
- bond_dev->name,
+ bond->dev->name,
slave_dev->name);
/* notify ad that the link status has changed */
@@ -2102,7 +2233,7 @@ void bond_mii_monitor(struct net_device *bond_dev)
printk(KERN_INFO DRV_NAME
": %s: link status up again after %d "
"ms for interface %s.\n",
- bond_dev->name,
+ bond->dev->name,
(bond->params.downdelay - slave->delay) * bond->params.miimon,
slave_dev->name);
}
@@ -2122,7 +2253,7 @@ void bond_mii_monitor(struct net_device *bond_dev)
": %s: link status up for "
"interface %s, enabling it "
"in %d ms.\n",
- bond_dev->name,
+ bond->dev->name,
slave_dev->name,
bond->params.updelay * bond->params.miimon);
}
@@ -2138,12 +2269,15 @@ void bond_mii_monitor(struct net_device *bond_dev)
printk(KERN_INFO DRV_NAME
": %s: link status down again after %d "
"ms for interface %s.\n",
- bond_dev->name,
+ bond->dev->name,
(bond->params.updelay - slave->delay) * bond->params.miimon,
slave_dev->name);
} else {
/* link stays up */
if (slave->delay == 0) {
+ if (!have_locks)
+ return 1;
+
/* now the link has been up for long time enough */
slave->link = BOND_LINK_UP;
slave->jiffies = jiffies;
@@ -2162,7 +2296,7 @@ void bond_mii_monitor(struct net_device *bond_dev)
printk(KERN_INFO DRV_NAME
": %s: link status definitely "
"up for interface %s.\n",
- bond_dev->name,
+ bond->dev->name,
slave_dev->name);
/* notify ad that the link status has changed */
@@ -2188,7 +2322,7 @@ void bond_mii_monitor(struct net_device *bond_dev)
/* Should not happen */
printk(KERN_ERR DRV_NAME
": %s: Error: %s Illegal value (link=%d)\n",
- bond_dev->name,
+ bond->dev->name,
slave->dev->name,
slave->link);
goto out;
@@ -2209,22 +2343,52 @@ void bond_mii_monitor(struct net_device *bond_dev)
} /* end of for */
if (do_failover) {
- write_lock(&bond->curr_slave_lock);
+ ASSERT_RTNL();
+
+ write_lock_bh(&bond->curr_slave_lock);
bond_select_active_slave(bond);
- write_unlock(&bond->curr_slave_lock);
+ write_unlock_bh(&bond->curr_slave_lock);
+
} else
bond_set_carrier(bond);
-re_arm:
- if (bond->params.miimon) {
- mod_timer(&bond->mii_timer, jiffies + delta_in_ticks);
- }
out:
- read_unlock(&bond->lock);
+ return 0;
}
+/*
+ * bond_mii_monitor
+ *
+ * Really a wrapper that splits the mii monitor into two phases: an
+ * inspection, then (if inspection indicates something needs to be
+ * done) an acquisition of appropriate locks followed by another pass
+ * to implement whatever link state changes are indicated.
+ */
+void bond_mii_monitor(struct work_struct *work)
+{
+ struct bonding *bond = container_of(work, struct bonding,
+ mii_work.work);
+ unsigned long delay;
+
+ read_lock(&bond->lock);
+ if (bond->kill_timers) {
+ read_unlock(&bond->lock);
+ return;
+ }
+ if (__bond_mii_monitor(bond, 0)) {
+ read_unlock(&bond->lock);
+ rtnl_lock();
+ read_lock(&bond->lock);
+ __bond_mii_monitor(bond, 1);
+ rtnl_unlock();
+ }
+
+ delay = ((bond->params.miimon * HZ) / 1000) ? : 1;
+ read_unlock(&bond->lock);
+ queue_delayed_work(bond->wq, &bond->mii_work, delay);
+}
static __be32 bond_glean_dev_ip(struct net_device *dev)
{
@@ -2414,7 +2578,7 @@ static void bond_send_gratuitous_arp(struct bonding *bond)
if (bond->master_ip) {
bond_arp_send(slave->dev, ARPOP_REPLY, bond->master_ip,
- bond->master_ip, 0);
+ bond->master_ip, 0);
}
list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
@@ -2523,9 +2687,10 @@ out:
* arp is transmitted to generate traffic. see activebackup_arp_monitor for
* arp monitoring in active backup mode.
*/
-void bond_loadbalance_arp_mon(struct net_device *bond_dev)
+void bond_loadbalance_arp_mon(struct work_struct *work)
{
- struct bonding *bond = bond_dev->priv;
+ struct bonding *bond = container_of(work, struct bonding,
+ arp_work.work);
struct slave *slave, *oldcurrent;
int do_failover = 0;
int delta_in_ticks;
@@ -2572,13 +2737,13 @@ void bond_loadbalance_arp_mon(struct net_device *bond_dev)
printk(KERN_INFO DRV_NAME
": %s: link status definitely "
"up for interface %s, ",
- bond_dev->name,
+ bond->dev->name,
slave->dev->name);
do_failover = 1;
} else {
printk(KERN_INFO DRV_NAME
": %s: interface %s is now up\n",
- bond_dev->name,
+ bond->dev->name,
slave->dev->name);
}
}
@@ -2602,7 +2767,7 @@ void bond_loadbalance_arp_mon(struct net_device *bond_dev)
printk(KERN_INFO DRV_NAME
": %s: interface %s is now down.\n",
- bond_dev->name,
+ bond->dev->name,
slave->dev->name);
if (slave == oldcurrent) {
@@ -2624,17 +2789,19 @@ void bond_loadbalance_arp_mon(struct net_device *bond_dev)
}
if (do_failover) {
- write_lock(&bond->curr_slave_lock);
+ rtnl_lock();
+ write_lock_bh(&bond->curr_slave_lock);
bond_select_active_slave(bond);
- write_unlock(&bond->curr_slave_lock);
+ write_unlock_bh(&bond->curr_slave_lock);
+ rtnl_unlock();
+
}
re_arm:
- if (bond->params.arp_interval) {
- mod_timer(&bond->arp_timer, jiffies + delta_in_ticks);
- }
+ if (bond->params.arp_interval)
+ queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks);
out:
read_unlock(&bond->lock);
}
@@ -2654,9 +2821,10 @@ out:
* may have received.
* see loadbalance_arp_monitor for arp monitoring in load balancing mode
*/
-void bond_activebackup_arp_mon(struct net_device *bond_dev)
+void bond_activebackup_arp_mon(struct work_struct *work)
{
- struct bonding *bond = bond_dev->priv;
+ struct bonding *bond = container_of(work, struct bonding,
+ arp_work.work);
struct slave *slave;
int delta_in_ticks;
int i;
@@ -2685,7 +2853,9 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev)
slave->link = BOND_LINK_UP;
- write_lock(&bond->curr_slave_lock);
+ rtnl_lock();
+
+ write_lock_bh(&bond->curr_slave_lock);
if ((!bond->curr_active_slave) &&
((jiffies - slave->dev->trans_start) <= delta_in_ticks)) {
@@ -2708,18 +2878,19 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev)
printk(KERN_INFO DRV_NAME
": %s: %s is up and now the "
"active interface\n",
- bond_dev->name,
+ bond->dev->name,
slave->dev->name);
netif_carrier_on(bond->dev);
} else {
printk(KERN_INFO DRV_NAME
": %s: backup interface %s is "
"now up\n",
- bond_dev->name,
+ bond->dev->name,
slave->dev->name);
}
- write_unlock(&bond->curr_slave_lock);
+ write_unlock_bh(&bond->curr_slave_lock);
+ rtnl_unlock();
}
} else {
read_lock(&bond->curr_slave_lock);
@@ -2751,7 +2922,7 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev)
printk(KERN_INFO DRV_NAME
": %s: backup interface %s is now down\n",
- bond_dev->name,
+ bond->dev->name,
slave->dev->name);
} else {
read_unlock(&bond->curr_slave_lock);
@@ -2786,15 +2957,18 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev)
printk(KERN_INFO DRV_NAME
": %s: link status down for active interface "
"%s, disabling it\n",
- bond_dev->name,
+ bond->dev->name,
slave->dev->name);
- write_lock(&bond->curr_slave_lock);
+ rtnl_lock();
+ write_lock_bh(&bond->curr_slave_lock);
bond_select_active_slave(bond);
slave = bond->curr_active_slave;
- write_unlock(&bond->curr_slave_lock);
+ write_unlock_bh(&bond->curr_slave_lock);
+
+ rtnl_unlock();
bond->current_arp_slave = slave;
@@ -2808,14 +2982,17 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev)
printk(KERN_INFO DRV_NAME
": %s: changing from interface %s to primary "
"interface %s\n",
- bond_dev->name,
+ bond->dev->name,
slave->dev->name,
bond->primary_slave->dev->name);
/* primary is up so switch to it */
- write_lock(&bond->curr_slave_lock);
+ rtnl_lock();
+ write_lock_bh(&bond->curr_slave_lock);
bond_change_active_slave(bond, bond->primary_slave);
- write_unlock(&bond->curr_slave_lock);
+ write_unlock_bh(&bond->curr_slave_lock);
+
+ rtnl_unlock();
slave = bond->primary_slave;
slave->jiffies = jiffies;
@@ -2872,7 +3049,7 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev)
printk(KERN_INFO DRV_NAME
": %s: backup interface %s is "
"now down.\n",
- bond_dev->name,
+ bond->dev->name,
slave->dev->name);
}
}
@@ -2881,7 +3058,7 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev)
re_arm:
if (bond->params.arp_interval) {
- mod_timer(&bond->arp_timer, jiffies + delta_in_ticks);
+ queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks);
}
out:
read_unlock(&bond->lock);
@@ -2902,7 +3079,7 @@ static void *bond_info_seq_start(struct seq_file *seq, loff_t *pos)
/* make sure the bond won't be taken away */
read_lock(&dev_base_lock);
- read_lock_bh(&bond->lock);
+ read_lock(&bond->lock);
if (*pos == 0) {
return SEQ_START_TOKEN;
@@ -2936,7 +3113,7 @@ static void bond_info_seq_stop(struct seq_file *seq, void *v)
{
struct bonding *bond = seq->private;
- read_unlock_bh(&bond->lock);
+ read_unlock(&bond->lock);
read_unlock(&dev_base_lock);
}
@@ -2951,9 +3128,15 @@ static void bond_info_show_master(struct seq_file *seq)
curr = bond->curr_active_slave;
read_unlock(&bond->curr_slave_lock);
- seq_printf(seq, "Bonding Mode: %s\n",
+ seq_printf(seq, "Bonding Mode: %s",
bond_mode_name(bond->params.mode));
+ if (bond->params.mode == BOND_MODE_ACTIVEBACKUP &&
+ bond->params.fail_over_mac)
+ seq_printf(seq, " (fail_over_mac)");
+
+ seq_printf(seq, "\n");
+
if (bond->params.mode == BOND_MODE_XOR ||
bond->params.mode == BOND_MODE_8023AD) {
seq_printf(seq, "Transmit Hash Policy: %s (%d)\n",
@@ -3233,7 +3416,10 @@ static int bond_slave_netdev_event(unsigned long event, struct net_device *slave
switch (event) {
case NETDEV_UNREGISTER:
if (bond_dev) {
- bond_release(bond_dev, slave_dev);
+ if (bond->setup_by_slave)
+ bond_release_and_destroy(bond_dev, slave_dev);
+ else
+ bond_release(bond_dev, slave_dev);
}
break;
case NETDEV_CHANGE:
@@ -3460,15 +3646,11 @@ static int bond_xmit_hash_policy_l2(struct sk_buff *skb,
static int bond_open(struct net_device *bond_dev)
{
struct bonding *bond = bond_dev->priv;
- struct timer_list *mii_timer = &bond->mii_timer;
- struct timer_list *arp_timer = &bond->arp_timer;
bond->kill_timers = 0;
if ((bond->params.mode == BOND_MODE_TLB) ||
(bond->params.mode == BOND_MODE_ALB)) {
- struct timer_list *alb_timer = &(BOND_ALB_INFO(bond).alb_timer);
-
/* bond_alb_initialize must be called before the timer
* is started.
*/
@@ -3477,44 +3659,31 @@ static int bond_open(struct net_device *bond_dev)
return -1;
}
- init_timer(alb_timer);
- alb_timer->expires = jiffies + 1;
- alb_timer->data = (unsigned long)bond;
- alb_timer->function = (void *)&bond_alb_monitor;
- add_timer(alb_timer);
+ INIT_DELAYED_WORK(&bond->alb_work, bond_alb_monitor);
+ queue_delayed_work(bond->wq, &bond->alb_work, 0);
}
if (bond->params.miimon) { /* link check interval, in milliseconds. */
- init_timer(mii_timer);
- mii_timer->expires = jiffies + 1;
- mii_timer->data = (unsigned long)bond_dev;
- mii_timer->function = (void *)&bond_mii_monitor;
- add_timer(mii_timer);
+ INIT_DELAYED_WORK(&bond->mii_work, bond_mii_monitor);
+ queue_delayed_work(bond->wq, &bond->mii_work, 0);
}
if (bond->params.arp_interval) { /* arp interval, in milliseconds. */
- init_timer(arp_timer);
- arp_timer->expires = jiffies + 1;
- arp_timer->data = (unsigned long)bond_dev;
- if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) {
- arp_timer->function = (void *)&bond_activebackup_arp_mon;
- } else {
- arp_timer->function = (void *)&bond_loadbalance_arp_mon;
- }
+ if (bond->params.mode == BOND_MODE_ACTIVEBACKUP)
+ INIT_DELAYED_WORK(&bond->arp_work,
+ bond_activebackup_arp_mon);
+ else
+ INIT_DELAYED_WORK(&bond->arp_work,
+ bond_loadbalance_arp_mon);
+
+ queue_delayed_work(bond->wq, &bond->arp_work, 0);
if (bond->params.arp_validate)
bond_register_arp(bond);
-
- add_timer(arp_timer);
}
if (bond->params.mode == BOND_MODE_8023AD) {
- struct timer_list *ad_timer = &(BOND_AD_INFO(bond).ad_timer);
- init_timer(ad_timer);
- ad_timer->expires = jiffies + 1;
- ad_timer->data = (unsigned long)bond;
- ad_timer->function = (void *)&bond_3ad_state_machine_handler;
- add_timer(ad_timer);
-
+ INIT_DELAYED_WORK(&bond->ad_work, bond_3ad_state_machine_handler);
+ queue_delayed_work(bond->wq, &bond->ad_work, 0);
/* register to receive LACPDUs */
bond_register_lacpdu(bond);
}
@@ -3542,25 +3711,21 @@ static int bond_close(struct net_device *bond_dev)
write_unlock_bh(&bond->lock);
- /* del_timer_sync must run without holding the bond->lock
- * because a running timer might be trying to hold it too
- */
-
if (bond->params.miimon) { /* link check interval, in milliseconds. */
- del_timer_sync(&bond->mii_timer);
+ cancel_delayed_work(&bond->mii_work);
}
if (bond->params.arp_interval) { /* arp interval, in milliseconds. */
- del_timer_sync(&bond->arp_timer);
+ cancel_delayed_work(&bond->arp_work);
}
switch (bond->params.mode) {
case BOND_MODE_8023AD:
- del_timer_sync(&(BOND_AD_INFO(bond).ad_timer));
+ cancel_delayed_work(&bond->ad_work);
break;
case BOND_MODE_TLB:
case BOND_MODE_ALB:
- del_timer_sync(&(BOND_ALB_INFO(bond).alb_timer));
+ cancel_delayed_work(&bond->alb_work);
break;
default:
break;
@@ -3657,13 +3822,13 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
if (mii->reg_num == 1) {
struct bonding *bond = bond_dev->priv;
mii->val_out = 0;
- read_lock_bh(&bond->lock);
+ read_lock(&bond->lock);
read_lock(&bond->curr_slave_lock);
if (netif_carrier_ok(bond->dev)) {
mii->val_out = BMSR_LSTATUS;
}
read_unlock(&bond->curr_slave_lock);
- read_unlock_bh(&bond->lock);
+ read_unlock(&bond->lock);
}
return 0;
@@ -3880,6 +4045,13 @@ static int bond_set_mac_address(struct net_device *bond_dev, void *addr)
dprintk("bond=%p, name=%s\n", bond, (bond_dev ? bond_dev->name : "None"));
+ /*
+ * If fail_over_mac is enabled, do nothing and return success.
+ * Returning an error causes ifenslave to fail.
+ */
+ if (bond->params.fail_over_mac)
+ return 0;
+
if (!is_valid_ether_addr(sa->sa_data)) {
return -EADDRNOTAVAIL;
}
@@ -3948,8 +4120,7 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev
{
struct bonding *bond = bond_dev->priv;
struct slave *slave, *start_at;
- int i;
- int res = 1;
+ int i, slave_no, res = 1;
read_lock(&bond->lock);
@@ -3957,29 +4128,29 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev
goto out;
}
- read_lock(&bond->curr_slave_lock);
- slave = start_at = bond->curr_active_slave;
- read_unlock(&bond->curr_slave_lock);
+ /*
+ * Concurrent TX may collide on rr_tx_counter; we accept that
+ * as being rare enough not to justify using an atomic op here
+ */
+ slave_no = bond->rr_tx_counter++ % bond->slave_cnt;
- if (!slave) {
- goto out;
+ bond_for_each_slave(bond, slave, i) {
+ slave_no--;
+ if (slave_no < 0) {
+ break;
+ }
}
+ start_at = slave;
bond_for_each_slave_from(bond, slave, i, start_at) {
if (IS_UP(slave->dev) &&
(slave->link == BOND_LINK_UP) &&
(slave->state == BOND_STATE_ACTIVE)) {
res = bond_dev_queue_xmit(bond, skb, slave->dev);
-
- write_lock(&bond->curr_slave_lock);
- bond->curr_active_slave = slave->next;
- write_unlock(&bond->curr_slave_lock);
-
break;
}
}
-
out:
if (res) {
/* no suitable interface, frame not sent */
@@ -4211,12 +4382,18 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params)
bond->params = *params; /* copy params struct */
+ bond->wq = create_singlethread_workqueue(bond_dev->name);
+ if (!bond->wq)
+ return -ENOMEM;
+
/* Initialize pointers */
bond->first_slave = NULL;
bond->curr_active_slave = NULL;
bond->current_arp_slave = NULL;
bond->primary_slave = NULL;
bond->dev = bond_dev;
+ bond->send_grat_arp = 0;
+ bond->setup_by_slave = 0;
INIT_LIST_HEAD(&bond->vlan_list);
/* Initialize the device entry points */
@@ -4228,6 +4405,7 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params)
bond_dev->set_multicast_list = bond_set_multicast_list;
bond_dev->change_mtu = bond_change_mtu;
bond_dev->set_mac_address = bond_set_mac_address;
+ bond_dev->validate_addr = NULL;
bond_set_mode_ops(bond, bond->params.mode);
@@ -4265,7 +4443,6 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params)
#ifdef CONFIG_PROC_FS
bond_create_proc_entry(bond);
#endif
-
list_add_tail(&bond->bond_list, &bond_dev_list);
return 0;
@@ -4274,7 +4451,7 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params)
/* De-initialize device specific data.
* Caller must hold rtnl_lock.
*/
-void bond_deinit(struct net_device *bond_dev)
+static void bond_deinit(struct net_device *bond_dev)
{
struct bonding *bond = bond_dev->priv;
@@ -4599,6 +4776,11 @@ static int bond_check_params(struct bond_params *params)
primary = NULL;
}
+ if (fail_over_mac && (bond_mode != BOND_MODE_ACTIVEBACKUP))
+ printk(KERN_WARNING DRV_NAME
+ ": Warning: fail_over_mac only affects "
+ "active-backup mode.\n");
+
/* fill params struct with the proper values */
params->mode = bond_mode;
params->xmit_policy = xmit_hashtype;
@@ -4610,6 +4792,7 @@ static int bond_check_params(struct bond_params *params)
params->use_carrier = use_carrier;
params->lacp_fast = lacp_fast;
params->primary[0] = 0;
+ params->fail_over_mac = fail_over_mac;
if (primary) {
strncpy(params->primary, primary, IFNAMSIZ);
@@ -4690,10 +4873,32 @@ out_rtnl:
return res;
}
+static void bond_work_cancel_all(struct bonding *bond)
+{
+ write_lock_bh(&bond->lock);
+ bond->kill_timers = 1;
+ write_unlock_bh(&bond->lock);
+
+ if (bond->params.miimon && delayed_work_pending(&bond->mii_work))
+ cancel_delayed_work(&bond->mii_work);
+
+ if (bond->params.arp_interval && delayed_work_pending(&bond->arp_work))
+ cancel_delayed_work(&bond->arp_work);
+
+ if (bond->params.mode == BOND_MODE_ALB &&
+ delayed_work_pending(&bond->alb_work))
+ cancel_delayed_work(&bond->alb_work);
+
+ if (bond->params.mode == BOND_MODE_8023AD &&
+ delayed_work_pending(&bond->ad_work))
+ cancel_delayed_work(&bond->ad_work);
+}
+
static int __init bonding_init(void)
{
int i;
int res;
+ struct bonding *bond, *nxt;
printk(KERN_INFO "%s", version);
@@ -4720,6 +4925,11 @@ static int __init bonding_init(void)
goto out;
err:
+ list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list) {
+ bond_work_cancel_all(bond);
+ destroy_workqueue(bond->wq);
+ }
+
rtnl_lock();
bond_free_all();
bond_destroy_sysfs();
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 6f49ca7e9b66..b29330d8e309 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -55,7 +55,7 @@ static int expected_refcount = -1;
static struct class *netdev_class;
/*--------------------------- Data Structures -----------------------------*/
-/* Bonding sysfs lock. Why can't we just use the subsytem lock?
+/* Bonding sysfs lock. Why can't we just use the subsystem lock?
* Because kobject_register tries to acquire the subsystem lock. If
* we already hold the lock (which we would if the user was creating
* a new bond through the sysfs interface), we deadlock.
@@ -164,9 +164,7 @@ static ssize_t bonding_store_bonds(struct class *cls, const char *buffer, size_t
printk(KERN_INFO DRV_NAME
": %s is being deleted...\n",
bond->dev->name);
- bond_deinit(bond->dev);
- bond_destroy_sysfs_entry(bond);
- unregister_netdevice(bond->dev);
+ bond_destroy(bond);
rtnl_unlock();
goto out;
}
@@ -231,7 +229,7 @@ static ssize_t bonding_show_slaves(struct device *d,
int i, res = 0;
struct bonding *bond = to_bond(d);
- read_lock_bh(&bond->lock);
+ read_lock(&bond->lock);
bond_for_each_slave(bond, slave, i) {
if (res > (PAGE_SIZE - IFNAMSIZ)) {
/* not enough space for another interface name */
@@ -242,7 +240,7 @@ static ssize_t bonding_show_slaves(struct device *d,
}
res += sprintf(buf + res, "%s ", slave->dev->name);
}
- read_unlock_bh(&bond->lock);
+ read_unlock(&bond->lock);
res += sprintf(buf + res, "\n");
res++;
return res;
@@ -260,17 +258,16 @@ static ssize_t bonding_store_slaves(struct device *d,
char command[IFNAMSIZ + 1] = { 0, };
char *ifname;
int i, res, found, ret = count;
+ u32 original_mtu;
struct slave *slave;
struct net_device *dev = NULL;
struct bonding *bond = to_bond(d);
/* Quick sanity check -- is the bond interface up? */
if (!(bond->dev->flags & IFF_UP)) {
- printk(KERN_ERR DRV_NAME
- ": %s: Unable to update slaves because interface is down.\n",
+ printk(KERN_WARNING DRV_NAME
+ ": %s: doing slave updates when interface is down.\n",
bond->dev->name);
- ret = -EPERM;
- goto out;
}
/* Note: We can't hold bond->lock here, as bond_create grabs it. */
@@ -285,18 +282,18 @@ static ssize_t bonding_store_slaves(struct device *d,
/* Got a slave name in ifname. Is it already in the list? */
found = 0;
- read_lock_bh(&bond->lock);
+ read_lock(&bond->lock);
bond_for_each_slave(bond, slave, i)
if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) {
printk(KERN_ERR DRV_NAME
": %s: Interface %s is already enslaved!\n",
bond->dev->name, ifname);
ret = -EPERM;
- read_unlock_bh(&bond->lock);
+ read_unlock(&bond->lock);
goto out;
}
- read_unlock_bh(&bond->lock);
+ read_unlock(&bond->lock);
printk(KERN_INFO DRV_NAME ": %s: Adding slave %s.\n",
bond->dev->name, ifname);
dev = dev_get_by_name(&init_net, ifname);
@@ -327,6 +324,7 @@ static ssize_t bonding_store_slaves(struct device *d,
}
/* Set the slave's MTU to match the bond */
+ original_mtu = dev->mtu;
if (dev->mtu != bond->dev->mtu) {
if (dev->change_mtu) {
res = dev->change_mtu(dev,
@@ -341,6 +339,9 @@ static ssize_t bonding_store_slaves(struct device *d,
}
rtnl_lock();
res = bond_enslave(bond->dev, dev);
+ bond_for_each_slave(bond, slave, i)
+ if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0)
+ slave->original_mtu = original_mtu;
rtnl_unlock();
if (res) {
ret = res;
@@ -353,13 +354,17 @@ static ssize_t bonding_store_slaves(struct device *d,
bond_for_each_slave(bond, slave, i)
if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) {
dev = slave->dev;
+ original_mtu = slave->original_mtu;
break;
}
if (dev) {
printk(KERN_INFO DRV_NAME ": %s: Removing slave %s\n",
bond->dev->name, dev->name);
rtnl_lock();
- res = bond_release(bond->dev, dev);
+ if (bond->setup_by_slave)
+ res = bond_release_and_destroy(bond->dev, dev);
+ else
+ res = bond_release(bond->dev, dev);
rtnl_unlock();
if (res) {
ret = res;
@@ -367,9 +372,9 @@ static ssize_t bonding_store_slaves(struct device *d,
}
/* set the slave MTU to the default */
if (dev->change_mtu) {
- dev->change_mtu(dev, 1500);
+ dev->change_mtu(dev, original_mtu);
} else {
- dev->mtu = 1500;
+ dev->mtu = original_mtu;
}
}
else {
@@ -563,6 +568,54 @@ static ssize_t bonding_store_arp_validate(struct device *d,
static DEVICE_ATTR(arp_validate, S_IRUGO | S_IWUSR, bonding_show_arp_validate, bonding_store_arp_validate);
/*
+ * Show and store fail_over_mac. User only allowed to change the
+ * value when there are no slaves.
+ */
+static ssize_t bonding_show_fail_over_mac(struct device *d, struct device_attribute *attr, char *buf)
+{
+ struct bonding *bond = to_bond(d);
+
+ return sprintf(buf, "%d\n", bond->params.fail_over_mac) + 1;
+}
+
+static ssize_t bonding_store_fail_over_mac(struct device *d, struct device_attribute *attr, const char *buf, size_t count)
+{
+ int new_value;
+ int ret = count;
+ struct bonding *bond = to_bond(d);
+
+ if (bond->slave_cnt != 0) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Can't alter fail_over_mac with slaves in bond.\n",
+ bond->dev->name);
+ ret = -EPERM;
+ goto out;
+ }
+
+ if (sscanf(buf, "%d", &new_value) != 1) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: no fail_over_mac value specified.\n",
+ bond->dev->name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if ((new_value == 0) || (new_value == 1)) {
+ bond->params.fail_over_mac = new_value;
+ printk(KERN_INFO DRV_NAME ": %s: Setting fail_over_mac to %d.\n",
+ bond->dev->name, new_value);
+ } else {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Ignoring invalid fail_over_mac value %d.\n",
+ bond->dev->name, new_value);
+ }
+out:
+ return ret;
+}
+
+static DEVICE_ATTR(fail_over_mac, S_IRUGO | S_IWUSR, bonding_show_fail_over_mac, bonding_store_fail_over_mac);
+
+/*
* Show and set the arp timer interval. There are two tricky bits
* here. First, if ARP monitoring is activated, then we must disable
* MII monitoring. Second, if the ARP timer isn't running, we must
@@ -609,12 +662,9 @@ static ssize_t bonding_store_arp_interval(struct device *d,
"%s Disabling MII monitoring.\n",
bond->dev->name, bond->dev->name);
bond->params.miimon = 0;
- /* Kill MII timer, else it brings bond's link down */
- if (bond->arp_timer.function) {
- printk(KERN_INFO DRV_NAME
- ": %s: Kill MII timer, else it brings bond's link down...\n",
- bond->dev->name);
- del_timer_sync(&bond->mii_timer);
+ if (delayed_work_pending(&bond->mii_work)) {
+ cancel_delayed_work(&bond->mii_work);
+ flush_workqueue(bond->wq);
}
}
if (!bond->params.arp_targets[0]) {
@@ -629,25 +679,15 @@ static ssize_t bonding_store_arp_interval(struct device *d,
* timer will get fired off when the open function
* is called.
*/
- if (bond->arp_timer.function) {
- /* The timer's already set up, so fire it off */
- mod_timer(&bond->arp_timer, jiffies + 1);
- } else {
- /* Set up the timer. */
- init_timer(&bond->arp_timer);
- bond->arp_timer.expires = jiffies + 1;
- bond->arp_timer.data =
- (unsigned long) bond->dev;
- if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) {
- bond->arp_timer.function =
- (void *)
- &bond_activebackup_arp_mon;
- } else {
- bond->arp_timer.function =
- (void *)
- &bond_loadbalance_arp_mon;
- }
- add_timer(&bond->arp_timer);
+ if (!delayed_work_pending(&bond->arp_work)) {
+ if (bond->params.mode == BOND_MODE_ACTIVEBACKUP)
+ INIT_DELAYED_WORK(&bond->arp_work,
+ bond_activebackup_arp_mon);
+ else
+ INIT_DELAYED_WORK(&bond->arp_work,
+ bond_loadbalance_arp_mon);
+
+ queue_delayed_work(bond->wq, &bond->arp_work, 0);
}
}
@@ -1003,12 +1043,9 @@ static ssize_t bonding_store_miimon(struct device *d,
bond->params.arp_validate =
BOND_ARP_VALIDATE_NONE;
}
- /* Kill ARP timer, else it brings bond's link down */
- if (bond->mii_timer.function) {
- printk(KERN_INFO DRV_NAME
- ": %s: Kill ARP timer, else it brings bond's link down...\n",
- bond->dev->name);
- del_timer_sync(&bond->arp_timer);
+ if (delayed_work_pending(&bond->arp_work)) {
+ cancel_delayed_work(&bond->arp_work);
+ flush_workqueue(bond->wq);
}
}
@@ -1018,18 +1055,11 @@ static ssize_t bonding_store_miimon(struct device *d,
* timer will get fired off when the open function
* is called.
*/
- if (bond->mii_timer.function) {
- /* The timer's already set up, so fire it off */
- mod_timer(&bond->mii_timer, jiffies + 1);
- } else {
- /* Set up the timer. */
- init_timer(&bond->mii_timer);
- bond->mii_timer.expires = jiffies + 1;
- bond->mii_timer.data =
- (unsigned long) bond->dev;
- bond->mii_timer.function =
- (void *) &bond_mii_monitor;
- add_timer(&bond->mii_timer);
+ if (!delayed_work_pending(&bond->mii_work)) {
+ INIT_DELAYED_WORK(&bond->mii_work,
+ bond_mii_monitor);
+ queue_delayed_work(bond->wq,
+ &bond->mii_work, 0);
}
}
}
@@ -1103,6 +1133,9 @@ static ssize_t bonding_store_primary(struct device *d,
}
out:
write_unlock_bh(&bond->lock);
+
+ rtnl_unlock();
+
return count;
}
static DEVICE_ATTR(primary, S_IRUGO | S_IWUSR, bonding_show_primary, bonding_store_primary);
@@ -1160,7 +1193,6 @@ static ssize_t bonding_show_active_slave(struct device *d,
struct bonding *bond = to_bond(d);
int count;
-
read_lock(&bond->curr_slave_lock);
curr = bond->curr_active_slave;
read_unlock(&bond->curr_slave_lock);
@@ -1182,7 +1214,9 @@ static ssize_t bonding_store_active_slave(struct device *d,
struct slave *new_active = NULL;
struct bonding *bond = to_bond(d);
+ rtnl_lock();
write_lock_bh(&bond->lock);
+
if (!USES_PRIMARY(bond->params.mode)) {
printk(KERN_INFO DRV_NAME
": %s: Unable to change active slave; %s is in mode %d\n",
@@ -1239,6 +1273,8 @@ static ssize_t bonding_store_active_slave(struct device *d,
}
out:
write_unlock_bh(&bond->lock);
+ rtnl_unlock();
+
return count;
}
@@ -1383,6 +1419,7 @@ static DEVICE_ATTR(ad_partner_mac, S_IRUGO, bonding_show_ad_partner_mac, NULL);
static struct attribute *per_bond_attrs[] = {
&dev_attr_slaves.attr,
&dev_attr_mode.attr,
+ &dev_attr_fail_over_mac.attr,
&dev_attr_arp_validate.attr,
&dev_attr_arp_interval.attr,
&dev_attr_arp_ip_target.attr,
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 2a6af7d23728..61c1b4536d34 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -22,8 +22,8 @@
#include "bond_3ad.h"
#include "bond_alb.h"
-#define DRV_VERSION "3.1.3"
-#define DRV_RELDATE "June 13, 2007"
+#define DRV_VERSION "3.2.1"
+#define DRV_RELDATE "October 15, 2007"
#define DRV_NAME "bonding"
#define DRV_DESCRIPTION "Ethernet Channel Bonding Driver"
@@ -128,6 +128,7 @@ struct bond_params {
int arp_interval;
int arp_validate;
int use_carrier;
+ int fail_over_mac;
int updelay;
int downdelay;
int lacp_fast;
@@ -156,6 +157,7 @@ struct slave {
s8 link; /* one of BOND_LINK_XXXX */
s8 state; /* one of BOND_STATE_XXXX */
u32 original_flags;
+ u32 original_mtu;
u32 link_failure_count;
u16 speed;
u8 duplex;
@@ -182,9 +184,9 @@ struct bonding {
s32 slave_cnt; /* never change this value outside the attach/detach wrappers */
rwlock_t lock;
rwlock_t curr_slave_lock;
- struct timer_list mii_timer;
- struct timer_list arp_timer;
s8 kill_timers;
+ s8 send_grat_arp;
+ s8 setup_by_slave;
struct net_device_stats stats;
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc_entry;
@@ -195,12 +197,18 @@ struct bonding {
int (*xmit_hash_policy)(struct sk_buff *, struct net_device *, int);
__be32 master_ip;
u16 flags;
+ u16 rr_tx_counter;
struct ad_bond_info ad_info;
struct alb_bond_info alb_info;
struct bond_params params;
struct list_head vlan_list;
struct vlan_group *vlgrp;
struct packet_type arp_mon_pt;
+ struct workqueue_struct *wq;
+ struct delayed_work mii_work;
+ struct delayed_work arp_work;
+ struct delayed_work alb_work;
+ struct delayed_work ad_work;
};
/**
@@ -292,7 +300,8 @@ static inline void bond_unset_master_alb_flags(struct bonding *bond)
struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr);
int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev);
int bond_create(char *name, struct bond_params *params, struct bonding **newbond);
-void bond_deinit(struct net_device *bond_dev);
+void bond_destroy(struct bonding *bond);
+int bond_release_and_destroy(struct net_device *bond_dev, struct net_device *slave_dev);
int bond_create_sysfs(void);
void bond_destroy_sysfs(void);
void bond_destroy_sysfs_entry(struct bonding *bond);
@@ -301,9 +310,9 @@ int bond_create_slave_symlinks(struct net_device *master, struct net_device *sla
void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *slave);
int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev);
int bond_release(struct net_device *bond_dev, struct net_device *slave_dev);
-void bond_mii_monitor(struct net_device *bond_dev);
-void bond_loadbalance_arp_mon(struct net_device *bond_dev);
-void bond_activebackup_arp_mon(struct net_device *bond_dev);
+void bond_mii_monitor(struct work_struct *);
+void bond_loadbalance_arp_mon(struct work_struct *);
+void bond_activebackup_arp_mon(struct work_struct *);
void bond_set_mode_ops(struct bonding *bond, int mode);
int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl);
void bond_select_active_slave(struct bonding *bond);
diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
index 563bf5f6fa2a..7df31b5561cc 100644
--- a/drivers/net/cassini.c
+++ b/drivers/net/cassini.c
@@ -4443,7 +4443,7 @@ static struct {
{REG_MAC_COLL_EXCESS},
{REG_MAC_COLL_LATE}
};
-#define CAS_REG_LEN (sizeof(ethtool_register_table)/sizeof(int))
+#define CAS_REG_LEN ARRAY_SIZE(ethtool_register_table)
#define CAS_MAX_REGS (sizeof (u32)*CAS_REG_LEN)
static void cas_read_regs(struct cas *cp, u8 *ptr, int len)
diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c
index ffa7e649a6ef..443666292a5c 100644
--- a/drivers/net/chelsio/sge.c
+++ b/drivers/net/chelsio/sge.c
@@ -1379,11 +1379,11 @@ static void sge_rx(struct sge *sge, struct freelQ *fl, unsigned int len)
}
__skb_pull(skb, sizeof(*p));
- skb->dev->last_rx = jiffies;
st = per_cpu_ptr(sge->port_stats[p->iff], smp_processor_id());
st->rx_packets++;
skb->protocol = eth_type_trans(skb, adapter->port[p->iff].dev);
+ skb->dev->last_rx = jiffies;
if ((adapter->flags & RX_CSUM_ENABLED) && p->csum == 0xffff &&
skb->protocol == htons(ETH_P_IP) &&
(skb->data[9] == IPPROTO_TCP || skb->data[9] == IPPROTO_UDP)) {
diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c
new file mode 100644
index 000000000000..6fd95a2c8cec
--- /dev/null
+++ b/drivers/net/cpmac.c
@@ -0,0 +1,1196 @@
+/*
+ * Copyright (C) 2006, 2007 Eugene Konev
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/skbuff.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
+#include <linux/phy_fixed.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <asm/gpio.h>
+
+MODULE_AUTHOR("Eugene Konev <ejka@imfi.kspu.ru>");
+MODULE_DESCRIPTION("TI AR7 ethernet driver (CPMAC)");
+MODULE_LICENSE("GPL");
+
+static int debug_level = 8;
+static int dumb_switch;
+
+/* Next 2 are only used in cpmac_probe, so it's pointless to change them */
+module_param(debug_level, int, 0444);
+module_param(dumb_switch, int, 0444);
+
+MODULE_PARM_DESC(debug_level, "Number of NETIF_MSG bits to enable");
+MODULE_PARM_DESC(dumb_switch, "Assume switch is not connected to MDIO bus");
+
+#define CPMAC_VERSION "0.5.0"
+/* frame size + 802.1q tag */
+#define CPMAC_SKB_SIZE (ETH_FRAME_LEN + 4)
+#define CPMAC_QUEUES 8
+
+/* Ethernet registers */
+#define CPMAC_TX_CONTROL 0x0004
+#define CPMAC_TX_TEARDOWN 0x0008
+#define CPMAC_RX_CONTROL 0x0014
+#define CPMAC_RX_TEARDOWN 0x0018
+#define CPMAC_MBP 0x0100
+# define MBP_RXPASSCRC 0x40000000
+# define MBP_RXQOS 0x20000000
+# define MBP_RXNOCHAIN 0x10000000
+# define MBP_RXCMF 0x01000000
+# define MBP_RXSHORT 0x00800000
+# define MBP_RXCEF 0x00400000
+# define MBP_RXPROMISC 0x00200000
+# define MBP_PROMISCCHAN(channel) (((channel) & 0x7) << 16)
+# define MBP_RXBCAST 0x00002000
+# define MBP_BCASTCHAN(channel) (((channel) & 0x7) << 8)
+# define MBP_RXMCAST 0x00000020
+# define MBP_MCASTCHAN(channel) ((channel) & 0x7)
+#define CPMAC_UNICAST_ENABLE 0x0104
+#define CPMAC_UNICAST_CLEAR 0x0108
+#define CPMAC_MAX_LENGTH 0x010c
+#define CPMAC_BUFFER_OFFSET 0x0110
+#define CPMAC_MAC_CONTROL 0x0160
+# define MAC_TXPTYPE 0x00000200
+# define MAC_TXPACE 0x00000040
+# define MAC_MII 0x00000020
+# define MAC_TXFLOW 0x00000010
+# define MAC_RXFLOW 0x00000008
+# define MAC_MTEST 0x00000004
+# define MAC_LOOPBACK 0x00000002
+# define MAC_FDX 0x00000001
+#define CPMAC_MAC_STATUS 0x0164
+# define MAC_STATUS_QOS 0x00000004
+# define MAC_STATUS_RXFLOW 0x00000002
+# define MAC_STATUS_TXFLOW 0x00000001
+#define CPMAC_TX_INT_ENABLE 0x0178
+#define CPMAC_TX_INT_CLEAR 0x017c
+#define CPMAC_MAC_INT_VECTOR 0x0180
+# define MAC_INT_STATUS 0x00080000
+# define MAC_INT_HOST 0x00040000
+# define MAC_INT_RX 0x00020000
+# define MAC_INT_TX 0x00010000
+#define CPMAC_MAC_EOI_VECTOR 0x0184
+#define CPMAC_RX_INT_ENABLE 0x0198
+#define CPMAC_RX_INT_CLEAR 0x019c
+#define CPMAC_MAC_INT_ENABLE 0x01a8
+#define CPMAC_MAC_INT_CLEAR 0x01ac
+#define CPMAC_MAC_ADDR_LO(channel) (0x01b0 + (channel) * 4)
+#define CPMAC_MAC_ADDR_MID 0x01d0
+#define CPMAC_MAC_ADDR_HI 0x01d4
+#define CPMAC_MAC_HASH_LO 0x01d8
+#define CPMAC_MAC_HASH_HI 0x01dc
+#define CPMAC_TX_PTR(channel) (0x0600 + (channel) * 4)
+#define CPMAC_RX_PTR(channel) (0x0620 + (channel) * 4)
+#define CPMAC_TX_ACK(channel) (0x0640 + (channel) * 4)
+#define CPMAC_RX_ACK(channel) (0x0660 + (channel) * 4)
+#define CPMAC_REG_END 0x0680
+/*
+ * Rx/Tx statistics
+ * TODO: use some of them to fill stats in cpmac_stats()
+ */
+#define CPMAC_STATS_RX_GOOD 0x0200
+#define CPMAC_STATS_RX_BCAST 0x0204
+#define CPMAC_STATS_RX_MCAST 0x0208
+#define CPMAC_STATS_RX_PAUSE 0x020c
+#define CPMAC_STATS_RX_CRC 0x0210
+#define CPMAC_STATS_RX_ALIGN 0x0214
+#define CPMAC_STATS_RX_OVER 0x0218
+#define CPMAC_STATS_RX_JABBER 0x021c
+#define CPMAC_STATS_RX_UNDER 0x0220
+#define CPMAC_STATS_RX_FRAG 0x0224
+#define CPMAC_STATS_RX_FILTER 0x0228
+#define CPMAC_STATS_RX_QOSFILTER 0x022c
+#define CPMAC_STATS_RX_OCTETS 0x0230
+
+#define CPMAC_STATS_TX_GOOD 0x0234
+#define CPMAC_STATS_TX_BCAST 0x0238
+#define CPMAC_STATS_TX_MCAST 0x023c
+#define CPMAC_STATS_TX_PAUSE 0x0240
+#define CPMAC_STATS_TX_DEFER 0x0244
+#define CPMAC_STATS_TX_COLLISION 0x0248
+#define CPMAC_STATS_TX_SINGLECOLL 0x024c
+#define CPMAC_STATS_TX_MULTICOLL 0x0250
+#define CPMAC_STATS_TX_EXCESSCOLL 0x0254
+#define CPMAC_STATS_TX_LATECOLL 0x0258
+#define CPMAC_STATS_TX_UNDERRUN 0x025c
+#define CPMAC_STATS_TX_CARRIERSENSE 0x0260
+#define CPMAC_STATS_TX_OCTETS 0x0264
+
+#define cpmac_read(base, reg) (readl((void __iomem *)(base) + (reg)))
+#define cpmac_write(base, reg, val) (writel(val, (void __iomem *)(base) + \
+ (reg)))
+
+/* MDIO bus */
+#define CPMAC_MDIO_VERSION 0x0000
+#define CPMAC_MDIO_CONTROL 0x0004
+# define MDIOC_IDLE 0x80000000
+# define MDIOC_ENABLE 0x40000000
+# define MDIOC_PREAMBLE 0x00100000
+# define MDIOC_FAULT 0x00080000
+# define MDIOC_FAULTDETECT 0x00040000
+# define MDIOC_INTTEST 0x00020000
+# define MDIOC_CLKDIV(div) ((div) & 0xff)
+#define CPMAC_MDIO_ALIVE 0x0008
+#define CPMAC_MDIO_LINK 0x000c
+#define CPMAC_MDIO_ACCESS(channel) (0x0080 + (channel) * 8)
+# define MDIO_BUSY 0x80000000
+# define MDIO_WRITE 0x40000000
+# define MDIO_REG(reg) (((reg) & 0x1f) << 21)
+# define MDIO_PHY(phy) (((phy) & 0x1f) << 16)
+# define MDIO_DATA(data) ((data) & 0xffff)
+#define CPMAC_MDIO_PHYSEL(channel) (0x0084 + (channel) * 8)
+# define PHYSEL_LINKSEL 0x00000040
+# define PHYSEL_LINKINT 0x00000020
+
+struct cpmac_desc {
+ u32 hw_next;
+ u32 hw_data;
+ u16 buflen;
+ u16 bufflags;
+ u16 datalen;
+ u16 dataflags;
+#define CPMAC_SOP 0x8000
+#define CPMAC_EOP 0x4000
+#define CPMAC_OWN 0x2000
+#define CPMAC_EOQ 0x1000
+ struct sk_buff *skb;
+ struct cpmac_desc *next;
+ dma_addr_t mapping;
+ dma_addr_t data_mapping;
+};
+
+struct cpmac_priv {
+ spinlock_t lock;
+ spinlock_t rx_lock;
+ struct cpmac_desc *rx_head;
+ int ring_size;
+ struct cpmac_desc *desc_ring;
+ dma_addr_t dma_ring;
+ void __iomem *regs;
+ struct mii_bus *mii_bus;
+ struct phy_device *phy;
+ char phy_name[BUS_ID_SIZE];
+ int oldlink, oldspeed, oldduplex;
+ u32 msg_enable;
+ struct net_device *dev;
+ struct work_struct reset_work;
+ struct platform_device *pdev;
+ struct napi_struct napi;
+};
+
+static irqreturn_t cpmac_irq(int, void *);
+static void cpmac_hw_start(struct net_device *dev);
+static void cpmac_hw_stop(struct net_device *dev);
+static int cpmac_stop(struct net_device *dev);
+static int cpmac_open(struct net_device *dev);
+
+static void cpmac_dump_regs(struct net_device *dev)
+{
+ int i;
+ struct cpmac_priv *priv = netdev_priv(dev);
+ for (i = 0; i < CPMAC_REG_END; i += 4) {
+ if (i % 16 == 0) {
+ if (i)
+ printk("\n");
+ printk(KERN_DEBUG "%s: reg[%p]:", dev->name,
+ priv->regs + i);
+ }
+ printk(" %08x", cpmac_read(priv->regs, i));
+ }
+ printk("\n");
+}
+
+static void cpmac_dump_desc(struct net_device *dev, struct cpmac_desc *desc)
+{
+ int i;
+ printk(KERN_DEBUG "%s: desc[%p]:", dev->name, desc);
+ for (i = 0; i < sizeof(*desc) / 4; i++)
+ printk(" %08x", ((u32 *)desc)[i]);
+ printk("\n");
+}
+
+static void cpmac_dump_skb(struct net_device *dev, struct sk_buff *skb)
+{
+ int i;
+ printk(KERN_DEBUG "%s: skb 0x%p, len=%d\n", dev->name, skb, skb->len);
+ for (i = 0; i < skb->len; i++) {
+ if (i % 16 == 0) {
+ if (i)
+ printk("\n");
+ printk(KERN_DEBUG "%s: data[%p]:", dev->name,
+ skb->data + i);
+ }
+ printk(" %02x", ((u8 *)skb->data)[i]);
+ }
+ printk("\n");
+}
+
+static int cpmac_mdio_read(struct mii_bus *bus, int phy_id, int reg)
+{
+ u32 val;
+
+ while (cpmac_read(bus->priv, CPMAC_MDIO_ACCESS(0)) & MDIO_BUSY)
+ cpu_relax();
+ cpmac_write(bus->priv, CPMAC_MDIO_ACCESS(0), MDIO_BUSY | MDIO_REG(reg) |
+ MDIO_PHY(phy_id));
+ while ((val = cpmac_read(bus->priv, CPMAC_MDIO_ACCESS(0))) & MDIO_BUSY)
+ cpu_relax();
+ return MDIO_DATA(val);
+}
+
+static int cpmac_mdio_write(struct mii_bus *bus, int phy_id,
+ int reg, u16 val)
+{
+ while (cpmac_read(bus->priv, CPMAC_MDIO_ACCESS(0)) & MDIO_BUSY)
+ cpu_relax();
+ cpmac_write(bus->priv, CPMAC_MDIO_ACCESS(0), MDIO_BUSY | MDIO_WRITE |
+ MDIO_REG(reg) | MDIO_PHY(phy_id) | MDIO_DATA(val));
+ return 0;
+}
+
+static int cpmac_mdio_reset(struct mii_bus *bus)
+{
+ ar7_device_reset(AR7_RESET_BIT_MDIO);
+ cpmac_write(bus->priv, CPMAC_MDIO_CONTROL, MDIOC_ENABLE |
+ MDIOC_CLKDIV(ar7_cpmac_freq() / 2200000 - 1));
+ return 0;
+}
+
+static int mii_irqs[PHY_MAX_ADDR] = { PHY_POLL, };
+
+static struct mii_bus cpmac_mii = {
+ .name = "cpmac-mii",
+ .read = cpmac_mdio_read,
+ .write = cpmac_mdio_write,
+ .reset = cpmac_mdio_reset,
+ .irq = mii_irqs,
+};
+
+static int cpmac_config(struct net_device *dev, struct ifmap *map)
+{
+ if (dev->flags & IFF_UP)
+ return -EBUSY;
+
+ /* Don't allow changing the I/O address */
+ if (map->base_addr != dev->base_addr)
+ return -EOPNOTSUPP;
+
+ /* ignore other fields */
+ return 0;
+}
+
+static void cpmac_set_multicast_list(struct net_device *dev)
+{
+ struct dev_mc_list *iter;
+ int i;
+ u8 tmp;
+ u32 mbp, bit, hash[2] = { 0, };
+ struct cpmac_priv *priv = netdev_priv(dev);
+
+ mbp = cpmac_read(priv->regs, CPMAC_MBP);
+ if (dev->flags & IFF_PROMISC) {
+ cpmac_write(priv->regs, CPMAC_MBP, (mbp & ~MBP_PROMISCCHAN(0)) |
+ MBP_RXPROMISC);
+ } else {
+ cpmac_write(priv->regs, CPMAC_MBP, mbp & ~MBP_RXPROMISC);
+ if (dev->flags & IFF_ALLMULTI) {
+ /* enable all multicast mode */
+ cpmac_write(priv->regs, CPMAC_MAC_HASH_LO, 0xffffffff);
+ cpmac_write(priv->regs, CPMAC_MAC_HASH_HI, 0xffffffff);
+ } else {
+ /*
+ * cpmac uses some strange mac address hashing
+ * (not crc32)
+ */
+ for (i = 0, iter = dev->mc_list; i < dev->mc_count;
+ i++, iter = iter->next) {
+ bit = 0;
+ tmp = iter->dmi_addr[0];
+ bit ^= (tmp >> 2) ^ (tmp << 4);
+ tmp = iter->dmi_addr[1];
+ bit ^= (tmp >> 4) ^ (tmp << 2);
+ tmp = iter->dmi_addr[2];
+ bit ^= (tmp >> 6) ^ tmp;
+ tmp = iter->dmi_addr[3];
+ bit ^= (tmp >> 2) ^ (tmp << 4);
+ tmp = iter->dmi_addr[4];
+ bit ^= (tmp >> 4) ^ (tmp << 2);
+ tmp = iter->dmi_addr[5];
+ bit ^= (tmp >> 6) ^ tmp;
+ bit &= 0x3f;
+ hash[bit / 32] |= 1 << (bit % 32);
+ }
+
+ cpmac_write(priv->regs, CPMAC_MAC_HASH_LO, hash[0]);
+ cpmac_write(priv->regs, CPMAC_MAC_HASH_HI, hash[1]);
+ }
+ }
+}
+
+static struct sk_buff *cpmac_rx_one(struct cpmac_priv *priv,
+ struct cpmac_desc *desc)
+{
+ struct sk_buff *skb, *result = NULL;
+
+ if (unlikely(netif_msg_hw(priv)))
+ cpmac_dump_desc(priv->dev, desc);
+ cpmac_write(priv->regs, CPMAC_RX_ACK(0), (u32)desc->mapping);
+ if (unlikely(!desc->datalen)) {
+ if (netif_msg_rx_err(priv) && net_ratelimit())
+ printk(KERN_WARNING "%s: rx: spurious interrupt\n",
+ priv->dev->name);
+ return NULL;
+ }
+
+ skb = netdev_alloc_skb(priv->dev, CPMAC_SKB_SIZE);
+ if (likely(skb)) {
+ skb_reserve(skb, 2);
+ skb_put(desc->skb, desc->datalen);
+ desc->skb->protocol = eth_type_trans(desc->skb, priv->dev);
+ desc->skb->ip_summed = CHECKSUM_NONE;
+ priv->dev->stats.rx_packets++;
+ priv->dev->stats.rx_bytes += desc->datalen;
+ result = desc->skb;
+ dma_unmap_single(&priv->dev->dev, desc->data_mapping,
+ CPMAC_SKB_SIZE, DMA_FROM_DEVICE);
+ desc->skb = skb;
+ desc->data_mapping = dma_map_single(&priv->dev->dev, skb->data,
+ CPMAC_SKB_SIZE,
+ DMA_FROM_DEVICE);
+ desc->hw_data = (u32)desc->data_mapping;
+ if (unlikely(netif_msg_pktdata(priv))) {
+ printk(KERN_DEBUG "%s: received packet:\n",
+ priv->dev->name);
+ cpmac_dump_skb(priv->dev, result);
+ }
+ } else {
+ if (netif_msg_rx_err(priv) && net_ratelimit())
+ printk(KERN_WARNING
+ "%s: low on skbs, dropping packet\n",
+ priv->dev->name);
+ priv->dev->stats.rx_dropped++;
+ }
+
+ desc->buflen = CPMAC_SKB_SIZE;
+ desc->dataflags = CPMAC_OWN;
+
+ return result;
+}
+
+static int cpmac_poll(struct napi_struct *napi, int budget)
+{
+ struct sk_buff *skb;
+ struct cpmac_desc *desc;
+ int received = 0;
+ struct cpmac_priv *priv = container_of(napi, struct cpmac_priv, napi);
+
+ spin_lock(&priv->rx_lock);
+ if (unlikely(!priv->rx_head)) {
+ if (netif_msg_rx_err(priv) && net_ratelimit())
+ printk(KERN_WARNING "%s: rx: polling, but no queue\n",
+ priv->dev->name);
+ netif_rx_complete(priv->dev, napi);
+ return 0;
+ }
+
+ desc = priv->rx_head;
+ while (((desc->dataflags & CPMAC_OWN) == 0) && (received < budget)) {
+ skb = cpmac_rx_one(priv, desc);
+ if (likely(skb)) {
+ netif_receive_skb(skb);
+ received++;
+ }
+ desc = desc->next;
+ }
+
+ priv->rx_head = desc;
+ spin_unlock(&priv->rx_lock);
+ if (unlikely(netif_msg_rx_status(priv)))
+ printk(KERN_DEBUG "%s: poll processed %d packets\n",
+ priv->dev->name, received);
+ if (desc->dataflags & CPMAC_OWN) {
+ netif_rx_complete(priv->dev, napi);
+ cpmac_write(priv->regs, CPMAC_RX_PTR(0), (u32)desc->mapping);
+ cpmac_write(priv->regs, CPMAC_RX_INT_ENABLE, 1);
+ return 0;
+ }
+
+ return 1;
+}
+
+static int cpmac_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ int queue, len;
+ struct cpmac_desc *desc;
+ struct cpmac_priv *priv = netdev_priv(dev);
+
+ if (unlikely(skb_padto(skb, ETH_ZLEN)))
+ return NETDEV_TX_OK;
+
+ len = max(skb->len, ETH_ZLEN);
+ queue = skb->queue_mapping;
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+ netif_stop_subqueue(dev, queue);
+#else
+ netif_stop_queue(dev);
+#endif
+
+ desc = &priv->desc_ring[queue];
+ if (unlikely(desc->dataflags & CPMAC_OWN)) {
+ if (netif_msg_tx_err(priv) && net_ratelimit())
+ printk(KERN_WARNING "%s: tx dma ring full\n",
+ dev->name);
+ return NETDEV_TX_BUSY;
+ }
+
+ spin_lock(&priv->lock);
+ dev->trans_start = jiffies;
+ spin_unlock(&priv->lock);
+ desc->dataflags = CPMAC_SOP | CPMAC_EOP | CPMAC_OWN;
+ desc->skb = skb;
+ desc->data_mapping = dma_map_single(&dev->dev, skb->data, len,
+ DMA_TO_DEVICE);
+ desc->hw_data = (u32)desc->data_mapping;
+ desc->datalen = len;
+ desc->buflen = len;
+ if (unlikely(netif_msg_tx_queued(priv)))
+ printk(KERN_DEBUG "%s: sending 0x%p, len=%d\n", dev->name, skb,
+ skb->len);
+ if (unlikely(netif_msg_hw(priv)))
+ cpmac_dump_desc(dev, desc);
+ if (unlikely(netif_msg_pktdata(priv)))
+ cpmac_dump_skb(dev, skb);
+ cpmac_write(priv->regs, CPMAC_TX_PTR(queue), (u32)desc->mapping);
+
+ return NETDEV_TX_OK;
+}
+
+static void cpmac_end_xmit(struct net_device *dev, int queue)
+{
+ struct cpmac_desc *desc;
+ struct cpmac_priv *priv = netdev_priv(dev);
+
+ desc = &priv->desc_ring[queue];
+ cpmac_write(priv->regs, CPMAC_TX_ACK(queue), (u32)desc->mapping);
+ if (likely(desc->skb)) {
+ spin_lock(&priv->lock);
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += desc->skb->len;
+ spin_unlock(&priv->lock);
+ dma_unmap_single(&dev->dev, desc->data_mapping, desc->skb->len,
+ DMA_TO_DEVICE);
+
+ if (unlikely(netif_msg_tx_done(priv)))
+ printk(KERN_DEBUG "%s: sent 0x%p, len=%d\n", dev->name,
+ desc->skb, desc->skb->len);
+
+ dev_kfree_skb_irq(desc->skb);
+ desc->skb = NULL;
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+ if (netif_subqueue_stopped(dev, queue))
+ netif_wake_subqueue(dev, queue);
+#else
+ if (netif_queue_stopped(dev))
+ netif_wake_queue(dev);
+#endif
+ } else {
+ if (netif_msg_tx_err(priv) && net_ratelimit())
+ printk(KERN_WARNING
+ "%s: end_xmit: spurious interrupt\n", dev->name);
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+ if (netif_subqueue_stopped(dev, queue))
+ netif_wake_subqueue(dev, queue);
+#else
+ if (netif_queue_stopped(dev))
+ netif_wake_queue(dev);
+#endif
+ }
+}
+
+static void cpmac_hw_stop(struct net_device *dev)
+{
+ int i;
+ struct cpmac_priv *priv = netdev_priv(dev);
+ struct plat_cpmac_data *pdata = priv->pdev->dev.platform_data;
+
+ ar7_device_reset(pdata->reset_bit);
+ cpmac_write(priv->regs, CPMAC_RX_CONTROL,
+ cpmac_read(priv->regs, CPMAC_RX_CONTROL) & ~1);
+ cpmac_write(priv->regs, CPMAC_TX_CONTROL,
+ cpmac_read(priv->regs, CPMAC_TX_CONTROL) & ~1);
+ for (i = 0; i < 8; i++) {
+ cpmac_write(priv->regs, CPMAC_TX_PTR(i), 0);
+ cpmac_write(priv->regs, CPMAC_RX_PTR(i), 0);
+ }
+ cpmac_write(priv->regs, CPMAC_UNICAST_CLEAR, 0xff);
+ cpmac_write(priv->regs, CPMAC_RX_INT_CLEAR, 0xff);
+ cpmac_write(priv->regs, CPMAC_TX_INT_CLEAR, 0xff);
+ cpmac_write(priv->regs, CPMAC_MAC_INT_CLEAR, 0xff);
+ cpmac_write(priv->regs, CPMAC_MAC_CONTROL,
+ cpmac_read(priv->regs, CPMAC_MAC_CONTROL) & ~MAC_MII);
+}
+
+static void cpmac_hw_start(struct net_device *dev)
+{
+ int i;
+ struct cpmac_priv *priv = netdev_priv(dev);
+ struct plat_cpmac_data *pdata = priv->pdev->dev.platform_data;
+
+ ar7_device_reset(pdata->reset_bit);
+ for (i = 0; i < 8; i++) {
+ cpmac_write(priv->regs, CPMAC_TX_PTR(i), 0);
+ cpmac_write(priv->regs, CPMAC_RX_PTR(i), 0);
+ }
+ cpmac_write(priv->regs, CPMAC_RX_PTR(0), priv->rx_head->mapping);
+
+ cpmac_write(priv->regs, CPMAC_MBP, MBP_RXSHORT | MBP_RXBCAST |
+ MBP_RXMCAST);
+ cpmac_write(priv->regs, CPMAC_BUFFER_OFFSET, 0);
+ for (i = 0; i < 8; i++)
+ cpmac_write(priv->regs, CPMAC_MAC_ADDR_LO(i), dev->dev_addr[5]);
+ cpmac_write(priv->regs, CPMAC_MAC_ADDR_MID, dev->dev_addr[4]);
+ cpmac_write(priv->regs, CPMAC_MAC_ADDR_HI, dev->dev_addr[0] |
+ (dev->dev_addr[1] << 8) | (dev->dev_addr[2] << 16) |
+ (dev->dev_addr[3] << 24));
+ cpmac_write(priv->regs, CPMAC_MAX_LENGTH, CPMAC_SKB_SIZE);
+ cpmac_write(priv->regs, CPMAC_UNICAST_CLEAR, 0xff);
+ cpmac_write(priv->regs, CPMAC_RX_INT_CLEAR, 0xff);
+ cpmac_write(priv->regs, CPMAC_TX_INT_CLEAR, 0xff);
+ cpmac_write(priv->regs, CPMAC_MAC_INT_CLEAR, 0xff);
+ cpmac_write(priv->regs, CPMAC_UNICAST_ENABLE, 1);
+ cpmac_write(priv->regs, CPMAC_RX_INT_ENABLE, 1);
+ cpmac_write(priv->regs, CPMAC_TX_INT_ENABLE, 0xff);
+ cpmac_write(priv->regs, CPMAC_MAC_INT_ENABLE, 3);
+
+ cpmac_write(priv->regs, CPMAC_RX_CONTROL,
+ cpmac_read(priv->regs, CPMAC_RX_CONTROL) | 1);
+ cpmac_write(priv->regs, CPMAC_TX_CONTROL,
+ cpmac_read(priv->regs, CPMAC_TX_CONTROL) | 1);
+ cpmac_write(priv->regs, CPMAC_MAC_CONTROL,
+ cpmac_read(priv->regs, CPMAC_MAC_CONTROL) | MAC_MII |
+ MAC_FDX);
+}
+
+static void cpmac_clear_rx(struct net_device *dev)
+{
+ struct cpmac_priv *priv = netdev_priv(dev);
+ struct cpmac_desc *desc;
+ int i;
+ if (unlikely(!priv->rx_head))
+ return;
+ desc = priv->rx_head;
+ for (i = 0; i < priv->ring_size; i++) {
+ if ((desc->dataflags & CPMAC_OWN) == 0) {
+ if (netif_msg_rx_err(priv) && net_ratelimit())
+ printk(KERN_WARNING "%s: packet dropped\n",
+ dev->name);
+ if (unlikely(netif_msg_hw(priv)))
+ cpmac_dump_desc(dev, desc);
+ desc->dataflags = CPMAC_OWN;
+ dev->stats.rx_dropped++;
+ }
+ desc = desc->next;
+ }
+}
+
+static void cpmac_clear_tx(struct net_device *dev)
+{
+ struct cpmac_priv *priv = netdev_priv(dev);
+ int i;
+ if (unlikely(!priv->desc_ring))
+ return;
+ for (i = 0; i < CPMAC_QUEUES; i++) {
+ priv->desc_ring[i].dataflags = 0;
+ if (priv->desc_ring[i].skb) {
+ dev_kfree_skb_any(priv->desc_ring[i].skb);
+ if (netif_subqueue_stopped(dev, i))
+ netif_wake_subqueue(dev, i);
+ }
+ }
+}
+
+static void cpmac_hw_error(struct work_struct *work)
+{
+ struct cpmac_priv *priv =
+ container_of(work, struct cpmac_priv, reset_work);
+
+ spin_lock(&priv->rx_lock);
+ cpmac_clear_rx(priv->dev);
+ spin_unlock(&priv->rx_lock);
+ cpmac_clear_tx(priv->dev);
+ cpmac_hw_start(priv->dev);
+ napi_enable(&priv->napi);
+ netif_start_queue(priv->dev);
+}
+
+static irqreturn_t cpmac_irq(int irq, void *dev_id)
+{
+ struct net_device *dev = dev_id;
+ struct cpmac_priv *priv;
+ int queue;
+ u32 status;
+
+ if (!dev)
+ return IRQ_NONE;
+
+ priv = netdev_priv(dev);
+
+ status = cpmac_read(priv->regs, CPMAC_MAC_INT_VECTOR);
+
+ if (unlikely(netif_msg_intr(priv)))
+ printk(KERN_DEBUG "%s: interrupt status: 0x%08x\n", dev->name,
+ status);
+
+ if (status & MAC_INT_TX)
+ cpmac_end_xmit(dev, (status & 7));
+
+ if (status & MAC_INT_RX) {
+ queue = (status >> 8) & 7;
+ if (netif_rx_schedule_prep(dev, &priv->napi)) {
+ cpmac_write(priv->regs, CPMAC_RX_INT_CLEAR, 1 << queue);
+ __netif_rx_schedule(dev, &priv->napi);
+ }
+ }
+
+ cpmac_write(priv->regs, CPMAC_MAC_EOI_VECTOR, 0);
+
+ if (unlikely(status & (MAC_INT_HOST | MAC_INT_STATUS))) {
+ if (netif_msg_drv(priv) && net_ratelimit())
+ printk(KERN_ERR "%s: hw error, resetting...\n",
+ dev->name);
+ netif_stop_queue(dev);
+ napi_disable(&priv->napi);
+ cpmac_hw_stop(dev);
+ schedule_work(&priv->reset_work);
+ if (unlikely(netif_msg_hw(priv)))
+ cpmac_dump_regs(dev);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static void cpmac_tx_timeout(struct net_device *dev)
+{
+ struct cpmac_priv *priv = netdev_priv(dev);
+ int i;
+
+ spin_lock(&priv->lock);
+ dev->stats.tx_errors++;
+ spin_unlock(&priv->lock);
+ if (netif_msg_tx_err(priv) && net_ratelimit())
+ printk(KERN_WARNING "%s: transmit timeout\n", dev->name);
+ /*
+ * FIXME: waking up random queue is not the best thing to
+ * do... on the other hand why we got here at all?
+ */
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+ for (i = 0; i < CPMAC_QUEUES; i++)
+ if (priv->desc_ring[i].skb) {
+ priv->desc_ring[i].dataflags = 0;
+ dev_kfree_skb_any(priv->desc_ring[i].skb);
+ netif_wake_subqueue(dev, i);
+ break;
+ }
+#else
+ priv->desc_ring[0].dataflags = 0;
+ if (priv->desc_ring[0].skb)
+ dev_kfree_skb_any(priv->desc_ring[0].skb);
+ netif_wake_queue(dev);
+#endif
+}
+
+static int cpmac_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ struct cpmac_priv *priv = netdev_priv(dev);
+ if (!(netif_running(dev)))
+ return -EINVAL;
+ if (!priv->phy)
+ return -EINVAL;
+ if ((cmd == SIOCGMIIPHY) || (cmd == SIOCGMIIREG) ||
+ (cmd == SIOCSMIIREG))
+ return phy_mii_ioctl(priv->phy, if_mii(ifr), cmd);
+
+ return -EOPNOTSUPP;
+}
+
+static int cpmac_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct cpmac_priv *priv = netdev_priv(dev);
+
+ if (priv->phy)
+ return phy_ethtool_gset(priv->phy, cmd);
+
+ return -EINVAL;
+}
+
+static int cpmac_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct cpmac_priv *priv = netdev_priv(dev);
+
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ if (priv->phy)
+ return phy_ethtool_sset(priv->phy, cmd);
+
+ return -EINVAL;
+}
+
+static void cpmac_get_ringparam(struct net_device *dev, struct ethtool_ringparam* ring)
+{
+ struct cpmac_priv *priv = netdev_priv(dev);
+
+ ring->rx_max_pending = 1024;
+ ring->rx_mini_max_pending = 1;
+ ring->rx_jumbo_max_pending = 1;
+ ring->tx_max_pending = 1;
+
+ ring->rx_pending = priv->ring_size;
+ ring->rx_mini_pending = 1;
+ ring->rx_jumbo_pending = 1;
+ ring->tx_pending = 1;
+}
+
+static int cpmac_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ring)
+{
+ struct cpmac_priv *priv = netdev_priv(dev);
+
+ if (netif_running(dev))
+ return -EBUSY;
+ priv->ring_size = ring->rx_pending;
+ return 0;
+}
+
+static void cpmac_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ strcpy(info->driver, "cpmac");
+ strcpy(info->version, CPMAC_VERSION);
+ info->fw_version[0] = '\0';
+ sprintf(info->bus_info, "%s", "cpmac");
+ info->regdump_len = 0;
+}
+
+static const struct ethtool_ops cpmac_ethtool_ops = {
+ .get_settings = cpmac_get_settings,
+ .set_settings = cpmac_set_settings,
+ .get_drvinfo = cpmac_get_drvinfo,
+ .get_link = ethtool_op_get_link,
+ .get_ringparam = cpmac_get_ringparam,
+ .set_ringparam = cpmac_set_ringparam,
+};
+
+static void cpmac_adjust_link(struct net_device *dev)
+{
+ struct cpmac_priv *priv = netdev_priv(dev);
+ int new_state = 0;
+
+ spin_lock(&priv->lock);
+ if (priv->phy->link) {
+ netif_start_queue(dev);
+ if (priv->phy->duplex != priv->oldduplex) {
+ new_state = 1;
+ priv->oldduplex = priv->phy->duplex;
+ }
+
+ if (priv->phy->speed != priv->oldspeed) {
+ new_state = 1;
+ priv->oldspeed = priv->phy->speed;
+ }
+
+ if (!priv->oldlink) {
+ new_state = 1;
+ priv->oldlink = 1;
+ netif_schedule(dev);
+ }
+ } else if (priv->oldlink) {
+ netif_stop_queue(dev);
+ new_state = 1;
+ priv->oldlink = 0;
+ priv->oldspeed = 0;
+ priv->oldduplex = -1;
+ }
+
+ if (new_state && netif_msg_link(priv) && net_ratelimit())
+ phy_print_status(priv->phy);
+
+ spin_unlock(&priv->lock);
+}
+
+static int cpmac_link_update(struct net_device *dev,
+ struct fixed_phy_status *status)
+{
+ status->link = 1;
+ status->speed = 100;
+ status->duplex = 1;
+ return 0;
+}
+
+static int cpmac_open(struct net_device *dev)
+{
+ int i, size, res;
+ struct cpmac_priv *priv = netdev_priv(dev);
+ struct resource *mem;
+ struct cpmac_desc *desc;
+ struct sk_buff *skb;
+
+ mem = platform_get_resource_byname(priv->pdev, IORESOURCE_MEM, "regs");
+ if (!request_mem_region(mem->start, mem->end - mem->start, dev->name)) {
+ if (netif_msg_drv(priv))
+ printk(KERN_ERR "%s: failed to request registers\n",
+ dev->name);
+ res = -ENXIO;
+ goto fail_reserve;
+ }
+
+ priv->regs = ioremap(mem->start, mem->end - mem->start);
+ if (!priv->regs) {
+ if (netif_msg_drv(priv))
+ printk(KERN_ERR "%s: failed to remap registers\n",
+ dev->name);
+ res = -ENXIO;
+ goto fail_remap;
+ }
+
+ size = priv->ring_size + CPMAC_QUEUES;
+ priv->desc_ring = dma_alloc_coherent(&dev->dev,
+ sizeof(struct cpmac_desc) * size,
+ &priv->dma_ring,
+ GFP_KERNEL);
+ if (!priv->desc_ring) {
+ res = -ENOMEM;
+ goto fail_alloc;
+ }
+
+ for (i = 0; i < size; i++)
+ priv->desc_ring[i].mapping = priv->dma_ring + sizeof(*desc) * i;
+
+ priv->rx_head = &priv->desc_ring[CPMAC_QUEUES];
+ for (i = 0, desc = priv->rx_head; i < priv->ring_size; i++, desc++) {
+ skb = netdev_alloc_skb(dev, CPMAC_SKB_SIZE);
+ if (unlikely(!skb)) {
+ res = -ENOMEM;
+ goto fail_desc;
+ }
+ skb_reserve(skb, 2);
+ desc->skb = skb;
+ desc->data_mapping = dma_map_single(&dev->dev, skb->data,
+ CPMAC_SKB_SIZE,
+ DMA_FROM_DEVICE);
+ desc->hw_data = (u32)desc->data_mapping;
+ desc->buflen = CPMAC_SKB_SIZE;
+ desc->dataflags = CPMAC_OWN;
+ desc->next = &priv->rx_head[(i + 1) % priv->ring_size];
+ desc->hw_next = (u32)desc->next->mapping;
+ }
+
+ if ((res = request_irq(dev->irq, cpmac_irq, IRQF_SHARED,
+ dev->name, dev))) {
+ if (netif_msg_drv(priv))
+ printk(KERN_ERR "%s: failed to obtain irq\n",
+ dev->name);
+ goto fail_irq;
+ }
+
+ INIT_WORK(&priv->reset_work, cpmac_hw_error);
+ cpmac_hw_start(dev);
+
+ napi_enable(&priv->napi);
+ priv->phy->state = PHY_CHANGELINK;
+ phy_start(priv->phy);
+
+ return 0;
+
+fail_irq:
+fail_desc:
+ for (i = 0; i < priv->ring_size; i++) {
+ if (priv->rx_head[i].skb) {
+ dma_unmap_single(&dev->dev,
+ priv->rx_head[i].data_mapping,
+ CPMAC_SKB_SIZE,
+ DMA_FROM_DEVICE);
+ kfree_skb(priv->rx_head[i].skb);
+ }
+ }
+fail_alloc:
+ kfree(priv->desc_ring);
+ iounmap(priv->regs);
+
+fail_remap:
+ release_mem_region(mem->start, mem->end - mem->start);
+
+fail_reserve:
+ return res;
+}
+
+static int cpmac_stop(struct net_device *dev)
+{
+ int i;
+ struct cpmac_priv *priv = netdev_priv(dev);
+ struct resource *mem;
+
+ netif_stop_queue(dev);
+
+ cancel_work_sync(&priv->reset_work);
+ napi_disable(&priv->napi);
+ phy_stop(priv->phy);
+
+ cpmac_hw_stop(dev);
+
+ for (i = 0; i < 8; i++)
+ cpmac_write(priv->regs, CPMAC_TX_PTR(i), 0);
+ cpmac_write(priv->regs, CPMAC_RX_PTR(0), 0);
+ cpmac_write(priv->regs, CPMAC_MBP, 0);
+
+ free_irq(dev->irq, dev);
+ iounmap(priv->regs);
+ mem = platform_get_resource_byname(priv->pdev, IORESOURCE_MEM, "regs");
+ release_mem_region(mem->start, mem->end - mem->start);
+ priv->rx_head = &priv->desc_ring[CPMAC_QUEUES];
+ for (i = 0; i < priv->ring_size; i++) {
+ if (priv->rx_head[i].skb) {
+ dma_unmap_single(&dev->dev,
+ priv->rx_head[i].data_mapping,
+ CPMAC_SKB_SIZE,
+ DMA_FROM_DEVICE);
+ kfree_skb(priv->rx_head[i].skb);
+ }
+ }
+
+ dma_free_coherent(&dev->dev, sizeof(struct cpmac_desc) *
+ (CPMAC_QUEUES + priv->ring_size),
+ priv->desc_ring, priv->dma_ring);
+ return 0;
+}
+
+static int external_switch;
+
+static int __devinit cpmac_probe(struct platform_device *pdev)
+{
+ int rc, phy_id, i;
+ struct resource *mem;
+ struct cpmac_priv *priv;
+ struct net_device *dev;
+ struct plat_cpmac_data *pdata;
+ struct fixed_info *fixed_phy;
+ DECLARE_MAC_BUF(mac);
+
+ pdata = pdev->dev.platform_data;
+
+ for (phy_id = 0; phy_id < PHY_MAX_ADDR; phy_id++) {
+ if (!(pdata->phy_mask & (1 << phy_id)))
+ continue;
+ if (!cpmac_mii.phy_map[phy_id])
+ continue;
+ break;
+ }
+
+ if (phy_id == PHY_MAX_ADDR) {
+ if (external_switch || dumb_switch)
+ phy_id = 0;
+ else {
+ printk(KERN_ERR "cpmac: no PHY present\n");
+ return -ENODEV;
+ }
+ }
+
+ dev = alloc_etherdev_mq(sizeof(*priv), CPMAC_QUEUES);
+
+ if (!dev) {
+ printk(KERN_ERR "cpmac: Unable to allocate net_device\n");
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(pdev, dev);
+ priv = netdev_priv(dev);
+
+ priv->pdev = pdev;
+ mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
+ if (!mem) {
+ rc = -ENODEV;
+ goto fail;
+ }
+
+ dev->irq = platform_get_irq_byname(pdev, "irq");
+
+ dev->open = cpmac_open;
+ dev->stop = cpmac_stop;
+ dev->set_config = cpmac_config;
+ dev->hard_start_xmit = cpmac_start_xmit;
+ dev->do_ioctl = cpmac_ioctl;
+ dev->set_multicast_list = cpmac_set_multicast_list;
+ dev->tx_timeout = cpmac_tx_timeout;
+ dev->ethtool_ops = &cpmac_ethtool_ops;
+ dev->features |= NETIF_F_MULTI_QUEUE;
+
+ netif_napi_add(dev, &priv->napi, cpmac_poll, 64);
+
+ spin_lock_init(&priv->lock);
+ spin_lock_init(&priv->rx_lock);
+ priv->dev = dev;
+ priv->ring_size = 64;
+ priv->msg_enable = netif_msg_init(debug_level, 0xff);
+ memcpy(dev->dev_addr, pdata->dev_addr, sizeof(dev->dev_addr));
+
+ if (phy_id == 31) {
+ snprintf(priv->phy_name, BUS_ID_SIZE, PHY_ID_FMT, cpmac_mii.id,
+ phy_id);
+ } else {
+ /* Let's try to get a free fixed phy... */
+ for (i = 0; i < MAX_PHY_AMNT; i++) {
+ fixed_phy = fixed_mdio_get_phydev(i);
+ if (!fixed_phy)
+ continue;
+ if (!fixed_phy->phydev->attached_dev) {
+ strncpy(priv->phy_name,
+ fixed_phy->phydev->dev.bus_id,
+ BUS_ID_SIZE);
+ fixed_mdio_set_link_update(fixed_phy->phydev,
+ &cpmac_link_update);
+ goto phy_found;
+ }
+ }
+ if (netif_msg_drv(priv))
+ printk(KERN_ERR "%s: Could not find fixed PHY\n",
+ dev->name);
+ rc = -ENODEV;
+ goto fail;
+ }
+
+phy_found:
+ priv->phy = phy_connect(dev, priv->phy_name, &cpmac_adjust_link, 0,
+ PHY_INTERFACE_MODE_MII);
+ if (IS_ERR(priv->phy)) {
+ if (netif_msg_drv(priv))
+ printk(KERN_ERR "%s: Could not attach to PHY\n",
+ dev->name);
+ return PTR_ERR(priv->phy);
+ }
+
+ if ((rc = register_netdev(dev))) {
+ printk(KERN_ERR "cpmac: error %i registering device %s\n", rc,
+ dev->name);
+ goto fail;
+ }
+
+ if (netif_msg_probe(priv)) {
+ printk(KERN_INFO
+ "cpmac: device %s (regs: %p, irq: %d, phy: %s, "
+ "mac: %s)\n", dev->name, (void *)mem->start, dev->irq,
+ priv->phy_name, print_mac(mac, dev->dev_addr));
+ }
+ return 0;
+
+fail:
+ free_netdev(dev);
+ return rc;
+}
+
+static int __devexit cpmac_remove(struct platform_device *pdev)
+{
+ struct net_device *dev = platform_get_drvdata(pdev);
+ unregister_netdev(dev);
+ free_netdev(dev);
+ return 0;
+}
+
+static struct platform_driver cpmac_driver = {
+ .driver.name = "cpmac",
+ .probe = cpmac_probe,
+ .remove = __devexit_p(cpmac_remove),
+};
+
+int __devinit cpmac_init(void)
+{
+ u32 mask;
+ int i, res;
+
+ cpmac_mii.priv = ioremap(AR7_REGS_MDIO, 256);
+
+ if (!cpmac_mii.priv) {
+ printk(KERN_ERR "Can't ioremap mdio registers\n");
+ return -ENXIO;
+ }
+
+#warning FIXME: unhardcode gpio&reset bits
+ ar7_gpio_disable(26);
+ ar7_gpio_disable(27);
+ ar7_device_reset(AR7_RESET_BIT_CPMAC_LO);
+ ar7_device_reset(AR7_RESET_BIT_CPMAC_HI);
+ ar7_device_reset(AR7_RESET_BIT_EPHY);
+
+ cpmac_mii.reset(&cpmac_mii);
+
+ for (i = 0; i < 300000; i++)
+ if ((mask = cpmac_read(cpmac_mii.priv, CPMAC_MDIO_ALIVE)))
+ break;
+ else
+ cpu_relax();
+
+ mask &= 0x7fffffff;
+ if (mask & (mask - 1)) {
+ external_switch = 1;
+ mask = 0;
+ }
+
+ cpmac_mii.phy_mask = ~(mask | 0x80000000);
+
+ res = mdiobus_register(&cpmac_mii);
+ if (res)
+ goto fail_mii;
+
+ res = platform_driver_register(&cpmac_driver);
+ if (res)
+ goto fail_cpmac;
+
+ return 0;
+
+fail_cpmac:
+ mdiobus_unregister(&cpmac_mii);
+
+fail_mii:
+ iounmap(cpmac_mii.priv);
+
+ return res;
+}
+
+void __devexit cpmac_exit(void)
+{
+ platform_driver_unregister(&cpmac_driver);
+ mdiobus_unregister(&cpmac_mii);
+ iounmap(cpmac_mii.priv);
+}
+
+module_init(cpmac_init);
+module_exit(cpmac_exit);
diff --git a/drivers/net/cris/eth_v10.c b/drivers/net/cris/eth_v10.c
index 314b2f68f78f..917b7b46f1a7 100644
--- a/drivers/net/cris/eth_v10.c
+++ b/drivers/net/cris/eth_v10.c
@@ -234,6 +234,7 @@
#include <linux/spinlock.h>
#include <linux/errno.h>
#include <linux/init.h>
+#include <linux/bitops.h>
#include <linux/if.h>
#include <linux/mii.h>
@@ -247,9 +248,9 @@
#include <asm/irq.h>
#include <asm/dma.h>
#include <asm/system.h>
-#include <asm/bitops.h>
#include <asm/ethernet.h>
#include <asm/cache.h>
+#include <asm/arch/io_interface_mux.h>
//#define ETHDEBUG
#define D(x)
@@ -279,6 +280,9 @@ struct net_local {
* by this lock as well.
*/
spinlock_t lock;
+
+ spinlock_t led_lock; /* Protect LED state */
+ spinlock_t transceiver_lock; /* Protect transceiver state. */
};
typedef struct etrax_eth_descr
@@ -295,8 +299,6 @@ struct transceiver_ops
void (*check_duplex)(struct net_device* dev);
};
-struct transceiver_ops* transceiver;
-
/* Duplex settings */
enum duplex
{
@@ -307,7 +309,7 @@ enum duplex
/* Dma descriptors etc. */
-#define MAX_MEDIA_DATA_SIZE 1518
+#define MAX_MEDIA_DATA_SIZE 1522
#define MIN_PACKET_LEN 46
#define ETHER_HEAD_LEN 14
@@ -332,8 +334,8 @@ enum duplex
/*Intel LXT972A specific*/
#define MDIO_INT_STATUS_REG_2 0x0011
-#define MDIO_INT_FULL_DUPLEX_IND ( 1 << 9 )
-#define MDIO_INT_SPEED ( 1 << 14 )
+#define MDIO_INT_FULL_DUPLEX_IND (1 << 9)
+#define MDIO_INT_SPEED (1 << 14)
/* Network flash constants */
#define NET_FLASH_TIME (HZ/50) /* 20 ms */
@@ -344,8 +346,8 @@ enum duplex
#define NO_NETWORK_ACTIVITY 0
#define NETWORK_ACTIVITY 1
-#define NBR_OF_RX_DESC 64
-#define NBR_OF_TX_DESC 256
+#define NBR_OF_RX_DESC 32
+#define NBR_OF_TX_DESC 16
/* Large packets are sent directly to upper layers while small packets are */
/* copied (to reduce memory waste). The following constant decides the breakpoint */
@@ -367,7 +369,6 @@ enum duplex
static etrax_eth_descr *myNextRxDesc; /* Points to the next descriptor to
to be processed */
static etrax_eth_descr *myLastRxDesc; /* The last processed descriptor */
-static etrax_eth_descr *myPrevRxDesc; /* The descriptor right before myNextRxDesc */
static etrax_eth_descr RxDescList[NBR_OF_RX_DESC] __attribute__ ((aligned(32)));
@@ -377,7 +378,6 @@ static etrax_eth_descr* myNextTxDesc; /* Next descriptor to use */
static etrax_eth_descr TxDescList[NBR_OF_TX_DESC] __attribute__ ((aligned(32)));
static unsigned int network_rec_config_shadow = 0;
-static unsigned int mdio_phy_addr; /* Transciever address */
static unsigned int network_tr_ctrl_shadow = 0;
@@ -411,7 +411,7 @@ static int e100_set_config(struct net_device* dev, struct ifmap* map);
static void e100_tx_timeout(struct net_device *dev);
static struct net_device_stats *e100_get_stats(struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
-static void e100_hardware_send_packet(char *buf, int length);
+static void e100_hardware_send_packet(struct net_local* np, char *buf, int length);
static void update_rx_stats(struct net_device_stats *);
static void update_tx_stats(struct net_device_stats *);
static int e100_probe_transceiver(struct net_device* dev);
@@ -434,7 +434,10 @@ static void e100_clear_network_leds(unsigned long dummy);
static void e100_set_network_leds(int active);
static const struct ethtool_ops e100_ethtool_ops;
-
+#if defined(CONFIG_ETRAX_NO_PHY)
+static void dummy_check_speed(struct net_device* dev);
+static void dummy_check_duplex(struct net_device* dev);
+#else
static void broadcom_check_speed(struct net_device* dev);
static void broadcom_check_duplex(struct net_device* dev);
static void tdk_check_speed(struct net_device* dev);
@@ -443,16 +446,28 @@ static void intel_check_speed(struct net_device* dev);
static void intel_check_duplex(struct net_device* dev);
static void generic_check_speed(struct net_device* dev);
static void generic_check_duplex(struct net_device* dev);
+#endif
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void e100_netpoll(struct net_device* dev);
+#endif
+
+static int autoneg_normal = 1;
struct transceiver_ops transceivers[] =
{
+#if defined(CONFIG_ETRAX_NO_PHY)
+ {0x0000, dummy_check_speed, dummy_check_duplex} /* Dummy */
+#else
{0x1018, broadcom_check_speed, broadcom_check_duplex}, /* Broadcom */
{0xC039, tdk_check_speed, tdk_check_duplex}, /* TDK 2120 */
{0x039C, tdk_check_speed, tdk_check_duplex}, /* TDK 2120C */
{0x04de, intel_check_speed, intel_check_duplex}, /* Intel LXT972A*/
{0x0000, generic_check_speed, generic_check_duplex} /* Generic, must be last */
+#endif
};
+struct transceiver_ops* transceiver = &transceivers[0];
+
#define tx_done(dev) (*R_DMA_CH0_CMD == 0)
/*
@@ -471,14 +486,22 @@ etrax_ethernet_init(void)
int i, err;
printk(KERN_INFO
- "ETRAX 100LX 10/100MBit ethernet v2.0 (c) 2000-2003 Axis Communications AB\n");
+ "ETRAX 100LX 10/100MBit ethernet v2.0 (c) 1998-2007 Axis Communications AB\n");
- dev = alloc_etherdev(sizeof(struct net_local));
- np = dev->priv;
+ if (cris_request_io_interface(if_eth, cardname)) {
+ printk(KERN_CRIT "etrax_ethernet_init failed to get IO interface\n");
+ return -EBUSY;
+ }
+ dev = alloc_etherdev(sizeof(struct net_local));
if (!dev)
return -ENOMEM;
+ np = netdev_priv(dev);
+
+ /* we do our own locking */
+ dev->features |= NETIF_F_LLTX;
+
dev->base_addr = (unsigned int)R_NETWORK_SA_0; /* just to have something to show */
/* now setup our etrax specific stuff */
@@ -498,14 +521,22 @@ etrax_ethernet_init(void)
dev->do_ioctl = e100_ioctl;
dev->set_config = e100_set_config;
dev->tx_timeout = e100_tx_timeout;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = e100_netpoll;
+#endif
+
+ spin_lock_init(&np->lock);
+ spin_lock_init(&np->led_lock);
+ spin_lock_init(&np->transceiver_lock);
/* Initialise the list of Etrax DMA-descriptors */
/* Initialise receive descriptors */
for (i = 0; i < NBR_OF_RX_DESC; i++) {
- /* Allocate two extra cachelines to make sure that buffer used by DMA
- * does not share cacheline with any other data (to avoid cache bug)
+ /* Allocate two extra cachelines to make sure that buffer used
+ * by DMA does not share cacheline with any other data (to
+ * avoid cache bug)
*/
RxDescList[i].skb = dev_alloc_skb(MAX_MEDIA_DATA_SIZE + 2 * L1_CACHE_BYTES);
if (!RxDescList[i].skb)
@@ -541,7 +572,6 @@ etrax_ethernet_init(void)
myNextRxDesc = &RxDescList[0];
myLastRxDesc = &RxDescList[NBR_OF_RX_DESC - 1];
- myPrevRxDesc = &RxDescList[NBR_OF_RX_DESC - 1];
myFirstTxDesc = &TxDescList[0];
myNextTxDesc = &TxDescList[0];
myLastTxDesc = &TxDescList[NBR_OF_TX_DESC - 1];
@@ -562,10 +592,11 @@ etrax_ethernet_init(void)
current_speed = 10;
current_speed_selection = 0; /* Auto */
speed_timer.expires = jiffies + NET_LINK_UP_CHECK_INTERVAL;
- duplex_timer.data = (unsigned long)dev;
+ speed_timer.data = (unsigned long)dev;
speed_timer.function = e100_check_speed;
clear_led_timer.function = e100_clear_network_leds;
+ clear_led_timer.data = (unsigned long)dev;
full_duplex = 0;
current_duplex = autoneg;
@@ -574,7 +605,6 @@ etrax_ethernet_init(void)
duplex_timer.function = e100_check_duplex;
/* Initialize mii interface */
- np->mii_if.phy_id = mdio_phy_addr;
np->mii_if.phy_id_mask = 0x1f;
np->mii_if.reg_num_mask = 0x1f;
np->mii_if.dev = dev;
@@ -585,6 +615,9 @@ etrax_ethernet_init(void)
/* unwanted addresses are matched */
*R_NETWORK_GA_0 = 0x00000000;
*R_NETWORK_GA_1 = 0x00000000;
+
+ /* Initialize next time the led can flash */
+ led_next_time = jiffies;
return 0;
}
@@ -595,9 +628,9 @@ etrax_ethernet_init(void)
static int
e100_set_mac_address(struct net_device *dev, void *p)
{
- struct net_local *np = (struct net_local *)dev->priv;
+ struct net_local *np = netdev_priv(dev);
struct sockaddr *addr = p;
- int i;
+ DECLARE_MAC_BUF(mac);
spin_lock(&np->lock); /* preemption protection */
@@ -686,6 +719,25 @@ e100_open(struct net_device *dev)
goto grace_exit2;
}
+ /*
+ * Always allocate the DMA channels after the IRQ,
+ * and clean up on failure.
+ */
+
+ if (cris_request_dma(NETWORK_TX_DMA_NBR,
+ cardname,
+ DMA_VERBOSE_ON_ERROR,
+ dma_eth)) {
+ goto grace_exit3;
+ }
+
+ if (cris_request_dma(NETWORK_RX_DMA_NBR,
+ cardname,
+ DMA_VERBOSE_ON_ERROR,
+ dma_eth)) {
+ goto grace_exit4;
+ }
+
/* give the HW an idea of what MAC address we want */
*R_NETWORK_SA_0 = dev->dev_addr[0] | (dev->dev_addr[1] << 8) |
@@ -700,6 +752,7 @@ e100_open(struct net_device *dev)
*R_NETWORK_REC_CONFIG = 0xd; /* broadcast rec, individ. rec, ma0 enabled */
#else
+ SETS(network_rec_config_shadow, R_NETWORK_REC_CONFIG, max_size, size1522);
SETS(network_rec_config_shadow, R_NETWORK_REC_CONFIG, broadcast, receive);
SETS(network_rec_config_shadow, R_NETWORK_REC_CONFIG, ma0, enable);
SETF(network_rec_config_shadow, R_NETWORK_REC_CONFIG, duplex, full_duplex);
@@ -719,8 +772,7 @@ e100_open(struct net_device *dev)
SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, crc, enable);
*R_NETWORK_TR_CTRL = network_tr_ctrl_shadow;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* enable the irq's for ethernet DMA */
@@ -752,12 +804,13 @@ e100_open(struct net_device *dev)
*R_DMA_CH0_FIRST = 0;
*R_DMA_CH0_DESCR = virt_to_phys(myLastTxDesc);
+ netif_start_queue(dev);
- restore_flags(flags);
+ local_irq_restore(flags);
/* Probe for transceiver */
if (e100_probe_transceiver(dev))
- goto grace_exit3;
+ goto grace_exit5;
/* Start duplex/speed timers */
add_timer(&speed_timer);
@@ -766,10 +819,14 @@ e100_open(struct net_device *dev)
/* We are now ready to accept transmit requeusts from
* the queueing layer of the networking.
*/
- netif_start_queue(dev);
+ netif_carrier_on(dev);
return 0;
+grace_exit5:
+ cris_free_dma(NETWORK_RX_DMA_NBR, cardname);
+grace_exit4:
+ cris_free_dma(NETWORK_TX_DMA_NBR, cardname);
grace_exit3:
free_irq(NETWORK_STATUS_IRQ_NBR, (void *)dev);
grace_exit2:
@@ -780,12 +837,20 @@ grace_exit0:
return -EAGAIN;
}
-
+#if defined(CONFIG_ETRAX_NO_PHY)
+static void
+dummy_check_speed(struct net_device* dev)
+{
+ current_speed = 100;
+}
+#else
static void
generic_check_speed(struct net_device* dev)
{
unsigned long data;
- data = e100_get_mdio_reg(dev, mdio_phy_addr, MII_ADVERTISE);
+ struct net_local *np = netdev_priv(dev);
+
+ data = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_ADVERTISE);
if ((data & ADVERTISE_100FULL) ||
(data & ADVERTISE_100HALF))
current_speed = 100;
@@ -797,7 +862,10 @@ static void
tdk_check_speed(struct net_device* dev)
{
unsigned long data;
- data = e100_get_mdio_reg(dev, mdio_phy_addr, MDIO_TDK_DIAGNOSTIC_REG);
+ struct net_local *np = netdev_priv(dev);
+
+ data = e100_get_mdio_reg(dev, np->mii_if.phy_id,
+ MDIO_TDK_DIAGNOSTIC_REG);
current_speed = (data & MDIO_TDK_DIAGNOSTIC_RATE ? 100 : 10);
}
@@ -805,7 +873,10 @@ static void
broadcom_check_speed(struct net_device* dev)
{
unsigned long data;
- data = e100_get_mdio_reg(dev, mdio_phy_addr, MDIO_AUX_CTRL_STATUS_REG);
+ struct net_local *np = netdev_priv(dev);
+
+ data = e100_get_mdio_reg(dev, np->mii_if.phy_id,
+ MDIO_AUX_CTRL_STATUS_REG);
current_speed = (data & MDIO_BC_SPEED ? 100 : 10);
}
@@ -813,46 +884,62 @@ static void
intel_check_speed(struct net_device* dev)
{
unsigned long data;
- data = e100_get_mdio_reg(dev, mdio_phy_addr, MDIO_INT_STATUS_REG_2);
+ struct net_local *np = netdev_priv(dev);
+
+ data = e100_get_mdio_reg(dev, np->mii_if.phy_id,
+ MDIO_INT_STATUS_REG_2);
current_speed = (data & MDIO_INT_SPEED ? 100 : 10);
}
-
+#endif
static void
e100_check_speed(unsigned long priv)
{
struct net_device* dev = (struct net_device*)priv;
+ struct net_local *np = netdev_priv(dev);
static int led_initiated = 0;
unsigned long data;
int old_speed = current_speed;
- data = e100_get_mdio_reg(dev, mdio_phy_addr, MII_BMSR);
+ spin_lock(&np->transceiver_lock);
+
+ data = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_BMSR);
if (!(data & BMSR_LSTATUS)) {
current_speed = 0;
} else {
transceiver->check_speed(dev);
}
+ spin_lock(&np->led_lock);
if ((old_speed != current_speed) || !led_initiated) {
led_initiated = 1;
e100_set_network_leds(NO_NETWORK_ACTIVITY);
+ if (current_speed)
+ netif_carrier_on(dev);
+ else
+ netif_carrier_off(dev);
}
+ spin_unlock(&np->led_lock);
/* Reinitialize the timer. */
speed_timer.expires = jiffies + NET_LINK_UP_CHECK_INTERVAL;
add_timer(&speed_timer);
+
+ spin_unlock(&np->transceiver_lock);
}
static void
e100_negotiate(struct net_device* dev)
{
- unsigned short data = e100_get_mdio_reg(dev, mdio_phy_addr, MII_ADVERTISE);
+ struct net_local *np = netdev_priv(dev);
+ unsigned short data = e100_get_mdio_reg(dev, np->mii_if.phy_id,
+ MII_ADVERTISE);
/* Discard old speed and duplex settings */
data &= ~(ADVERTISE_100HALF | ADVERTISE_100FULL |
ADVERTISE_10HALF | ADVERTISE_10FULL);
switch (current_speed_selection) {
- case 10 :
+ case 10:
if (current_duplex == full)
data |= ADVERTISE_10FULL;
else if (current_duplex == half)
@@ -861,7 +948,7 @@ e100_negotiate(struct net_device* dev)
data |= ADVERTISE_10HALF | ADVERTISE_10FULL;
break;
- case 100 :
+ case 100:
if (current_duplex == full)
data |= ADVERTISE_100FULL;
else if (current_duplex == half)
@@ -870,7 +957,7 @@ e100_negotiate(struct net_device* dev)
data |= ADVERTISE_100HALF | ADVERTISE_100FULL;
break;
- case 0 : /* Auto */
+ case 0: /* Auto */
if (current_duplex == full)
data |= ADVERTISE_100FULL | ADVERTISE_10FULL;
else if (current_duplex == half)
@@ -880,35 +967,44 @@ e100_negotiate(struct net_device* dev)
ADVERTISE_100HALF | ADVERTISE_100FULL;
break;
- default : /* assume autoneg speed and duplex */
+ default: /* assume autoneg speed and duplex */
data |= ADVERTISE_10HALF | ADVERTISE_10FULL |
ADVERTISE_100HALF | ADVERTISE_100FULL;
+ break;
}
- e100_set_mdio_reg(dev, mdio_phy_addr, MII_ADVERTISE, data);
+ e100_set_mdio_reg(dev, np->mii_if.phy_id, MII_ADVERTISE, data);
/* Renegotiate with link partner */
- data = e100_get_mdio_reg(dev, mdio_phy_addr, MII_BMCR);
+ if (autoneg_normal) {
+ data = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_BMCR);
data |= BMCR_ANENABLE | BMCR_ANRESTART;
-
- e100_set_mdio_reg(dev, mdio_phy_addr, MII_BMCR, data);
+ }
+ e100_set_mdio_reg(dev, np->mii_if.phy_id, MII_BMCR, data);
}
static void
e100_set_speed(struct net_device* dev, unsigned long speed)
{
+ struct net_local *np = netdev_priv(dev);
+
+ spin_lock(&np->transceiver_lock);
if (speed != current_speed_selection) {
current_speed_selection = speed;
e100_negotiate(dev);
}
+ spin_unlock(&np->transceiver_lock);
}
static void
e100_check_duplex(unsigned long priv)
{
struct net_device *dev = (struct net_device *)priv;
- struct net_local *np = (struct net_local *)dev->priv;
- int old_duplex = full_duplex;
+ struct net_local *np = netdev_priv(dev);
+ int old_duplex;
+
+ spin_lock(&np->transceiver_lock);
+ old_duplex = full_duplex;
transceiver->check_duplex(dev);
if (old_duplex != full_duplex) {
/* Duplex changed */
@@ -920,13 +1016,22 @@ e100_check_duplex(unsigned long priv)
duplex_timer.expires = jiffies + NET_DUPLEX_CHECK_INTERVAL;
add_timer(&duplex_timer);
np->mii_if.full_duplex = full_duplex;
+ spin_unlock(&np->transceiver_lock);
}
-
+#if defined(CONFIG_ETRAX_NO_PHY)
+static void
+dummy_check_duplex(struct net_device* dev)
+{
+ full_duplex = 1;
+}
+#else
static void
generic_check_duplex(struct net_device* dev)
{
unsigned long data;
- data = e100_get_mdio_reg(dev, mdio_phy_addr, MII_ADVERTISE);
+ struct net_local *np = netdev_priv(dev);
+
+ data = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_ADVERTISE);
if ((data & ADVERTISE_10FULL) ||
(data & ADVERTISE_100FULL))
full_duplex = 1;
@@ -938,7 +1043,10 @@ static void
tdk_check_duplex(struct net_device* dev)
{
unsigned long data;
- data = e100_get_mdio_reg(dev, mdio_phy_addr, MDIO_TDK_DIAGNOSTIC_REG);
+ struct net_local *np = netdev_priv(dev);
+
+ data = e100_get_mdio_reg(dev, np->mii_if.phy_id,
+ MDIO_TDK_DIAGNOSTIC_REG);
full_duplex = (data & MDIO_TDK_DIAGNOSTIC_DPLX) ? 1 : 0;
}
@@ -946,7 +1054,10 @@ static void
broadcom_check_duplex(struct net_device* dev)
{
unsigned long data;
- data = e100_get_mdio_reg(dev, mdio_phy_addr, MDIO_AUX_CTRL_STATUS_REG);
+ struct net_local *np = netdev_priv(dev);
+
+ data = e100_get_mdio_reg(dev, np->mii_if.phy_id,
+ MDIO_AUX_CTRL_STATUS_REG);
full_duplex = (data & MDIO_BC_FULL_DUPLEX_IND) ? 1 : 0;
}
@@ -954,38 +1065,55 @@ static void
intel_check_duplex(struct net_device* dev)
{
unsigned long data;
- data = e100_get_mdio_reg(dev, mdio_phy_addr, MDIO_INT_STATUS_REG_2);
+ struct net_local *np = netdev_priv(dev);
+
+ data = e100_get_mdio_reg(dev, np->mii_if.phy_id,
+ MDIO_INT_STATUS_REG_2);
full_duplex = (data & MDIO_INT_FULL_DUPLEX_IND) ? 1 : 0;
}
-
+#endif
static void
e100_set_duplex(struct net_device* dev, enum duplex new_duplex)
{
+ struct net_local *np = netdev_priv(dev);
+
+ spin_lock(&np->transceiver_lock);
if (new_duplex != current_duplex) {
current_duplex = new_duplex;
e100_negotiate(dev);
}
+ spin_unlock(&np->transceiver_lock);
}
static int
e100_probe_transceiver(struct net_device* dev)
{
+ int ret = 0;
+
+#if !defined(CONFIG_ETRAX_NO_PHY)
unsigned int phyid_high;
unsigned int phyid_low;
unsigned int oui;
struct transceiver_ops* ops = NULL;
+ struct net_local *np = netdev_priv(dev);
+
+ spin_lock(&np->transceiver_lock);
/* Probe MDIO physical address */
- for (mdio_phy_addr = 0; mdio_phy_addr <= 31; mdio_phy_addr++) {
- if (e100_get_mdio_reg(dev, mdio_phy_addr, MII_BMSR) != 0xffff)
+ for (np->mii_if.phy_id = 0; np->mii_if.phy_id <= 31;
+ np->mii_if.phy_id++) {
+ if (e100_get_mdio_reg(dev,
+ np->mii_if.phy_id, MII_BMSR) != 0xffff)
break;
}
- if (mdio_phy_addr == 32)
- return -ENODEV;
+ if (np->mii_if.phy_id == 32) {
+ ret = -ENODEV;
+ goto out;
+ }
/* Get manufacturer */
- phyid_high = e100_get_mdio_reg(dev, mdio_phy_addr, MII_PHYSID1);
- phyid_low = e100_get_mdio_reg(dev, mdio_phy_addr, MII_PHYSID2);
+ phyid_high = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_PHYSID1);
+ phyid_low = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_PHYSID2);
oui = (phyid_high << 6) | (phyid_low >> 10);
for (ops = &transceivers[0]; ops->oui; ops++) {
@@ -993,8 +1121,10 @@ e100_probe_transceiver(struct net_device* dev)
break;
}
transceiver = ops;
-
- return 0;
+out:
+ spin_unlock(&np->transceiver_lock);
+#endif
+ return ret;
}
static int
@@ -1088,13 +1218,14 @@ e100_receive_mdio_bit()
static void
e100_reset_transceiver(struct net_device* dev)
{
+ struct net_local *np = netdev_priv(dev);
unsigned short cmd;
unsigned short data;
int bitCounter;
- data = e100_get_mdio_reg(dev, mdio_phy_addr, MII_BMCR);
+ data = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_BMCR);
- cmd = (MDIO_START << 14) | (MDIO_WRITE << 12) | (mdio_phy_addr << 7) | (MII_BMCR << 2);
+ cmd = (MDIO_START << 14) | (MDIO_WRITE << 12) | (np->mii_if.phy_id << 7) | (MII_BMCR << 2);
e100_send_mdio_cmd(cmd, 1);
@@ -1112,7 +1243,7 @@ e100_reset_transceiver(struct net_device* dev)
static void
e100_tx_timeout(struct net_device *dev)
{
- struct net_local *np = (struct net_local *)dev->priv;
+ struct net_local *np = netdev_priv(dev);
unsigned long flags;
spin_lock_irqsave(&np->lock, flags);
@@ -1134,8 +1265,7 @@ e100_tx_timeout(struct net_device *dev)
e100_reset_transceiver(dev);
/* and get rid of the packets that never got an interrupt */
- while (myFirstTxDesc != myNextTxDesc)
- {
+ while (myFirstTxDesc != myNextTxDesc) {
dev_kfree_skb(myFirstTxDesc->skb);
myFirstTxDesc->skb = 0;
myFirstTxDesc = phys_to_virt(myFirstTxDesc->descr.next);
@@ -1161,7 +1291,7 @@ e100_tx_timeout(struct net_device *dev)
static int
e100_send_packet(struct sk_buff *skb, struct net_device *dev)
{
- struct net_local *np = (struct net_local *)dev->priv;
+ struct net_local *np = netdev_priv(dev);
unsigned char *buf = skb->data;
unsigned long flags;
@@ -1174,7 +1304,7 @@ e100_send_packet(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
- e100_hardware_send_packet(buf, skb->len);
+ e100_hardware_send_packet(np, buf, skb->len);
myNextTxDesc = phys_to_virt(myNextTxDesc->descr.next);
@@ -1197,13 +1327,15 @@ static irqreturn_t
e100rxtx_interrupt(int irq, void *dev_id)
{
struct net_device *dev = (struct net_device *)dev_id;
- struct net_local *np = (struct net_local *)dev->priv;
- unsigned long irqbits = *R_IRQ_MASK2_RD;
+ struct net_local *np = netdev_priv(dev);
+ unsigned long irqbits;
- /* Disable RX/TX IRQs to avoid reentrancy */
- *R_IRQ_MASK2_CLR =
- IO_STATE(R_IRQ_MASK2_CLR, dma0_eop, clr) |
- IO_STATE(R_IRQ_MASK2_CLR, dma1_eop, clr);
+ /*
+ * Note that both rx and tx interrupts are blocked at this point,
+ * regardless of which got us here.
+ */
+
+ irqbits = *R_IRQ_MASK2_RD;
/* Handle received packets */
if (irqbits & IO_STATE(R_IRQ_MASK2_RD, dma1_eop, active)) {
@@ -1219,7 +1351,7 @@ e100rxtx_interrupt(int irq, void *dev_id)
* allocate a new buffer to put a packet in.
*/
e100_rx(dev);
- ((struct net_local *)dev->priv)->stats.rx_packets++;
+ np->stats.rx_packets++;
/* restart/continue on the channel, for safety */
*R_DMA_CH1_CMD = IO_STATE(R_DMA_CH1_CMD, cmd, restart);
/* clear dma channel 1 eop/descr irq bits */
@@ -1233,9 +1365,8 @@ e100rxtx_interrupt(int irq, void *dev_id)
}
/* Report any packets that have been sent */
- while (myFirstTxDesc != phys_to_virt(*R_DMA_CH0_FIRST) &&
- myFirstTxDesc != myNextTxDesc)
- {
+ while (virt_to_phys(myFirstTxDesc) != *R_DMA_CH0_FIRST &&
+ (netif_queue_stopped(dev) || myFirstTxDesc != myNextTxDesc)) {
np->stats.tx_bytes += myFirstTxDesc->skb->len;
np->stats.tx_packets++;
@@ -1244,19 +1375,15 @@ e100rxtx_interrupt(int irq, void *dev_id)
dev_kfree_skb_irq(myFirstTxDesc->skb);
myFirstTxDesc->skb = 0;
myFirstTxDesc = phys_to_virt(myFirstTxDesc->descr.next);
+ /* Wake up queue. */
+ netif_wake_queue(dev);
}
if (irqbits & IO_STATE(R_IRQ_MASK2_RD, dma0_eop, active)) {
- /* acknowledge the eop interrupt and wake up queue */
+ /* acknowledge the eop interrupt. */
*R_DMA_CH0_CLR_INTR = IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do);
- netif_wake_queue(dev);
}
- /* Enable RX/TX IRQs again */
- *R_IRQ_MASK2_SET =
- IO_STATE(R_IRQ_MASK2_SET, dma0_eop, set) |
- IO_STATE(R_IRQ_MASK2_SET, dma1_eop, set);
-
return IRQ_HANDLED;
}
@@ -1264,7 +1391,7 @@ static irqreturn_t
e100nw_interrupt(int irq, void *dev_id)
{
struct net_device *dev = (struct net_device *)dev_id;
- struct net_local *np = (struct net_local *)dev->priv;
+ struct net_local *np = netdev_priv(dev);
unsigned long irqbits = *R_IRQ_MASK0_RD;
/* check for underrun irq */
@@ -1286,7 +1413,6 @@ e100nw_interrupt(int irq, void *dev_id)
SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, clr_error, clr);
*R_NETWORK_TR_CTRL = network_tr_ctrl_shadow;
SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, clr_error, nop);
- *R_NETWORK_TR_CTRL = IO_STATE(R_NETWORK_TR_CTRL, clr_error, clr);
np->stats.tx_errors++;
D(printk("ethernet excessive collisions!\n"));
}
@@ -1299,12 +1425,13 @@ e100_rx(struct net_device *dev)
{
struct sk_buff *skb;
int length = 0;
- struct net_local *np = (struct net_local *)dev->priv;
+ struct net_local *np = netdev_priv(dev);
unsigned char *skb_data_ptr;
#ifdef ETHDEBUG
int i;
#endif
-
+ etrax_eth_descr *prevRxDesc; /* The descriptor right before myNextRxDesc */
+ spin_lock(&np->led_lock);
if (!led_active && time_after(jiffies, led_next_time)) {
/* light the network leds depending on the current speed. */
e100_set_network_leds(NETWORK_ACTIVITY);
@@ -1314,9 +1441,10 @@ e100_rx(struct net_device *dev)
led_active = 1;
mod_timer(&clear_led_timer, jiffies + HZ/10);
}
+ spin_unlock(&np->led_lock);
length = myNextRxDesc->descr.hw_len - 4;
- ((struct net_local *)dev->priv)->stats.rx_bytes += length;
+ np->stats.rx_bytes += length;
#ifdef ETHDEBUG
printk("Got a packet of length %d:\n", length);
@@ -1336,7 +1464,7 @@ e100_rx(struct net_device *dev)
if (!skb) {
np->stats.rx_errors++;
printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
- return;
+ goto update_nextrxdesc;
}
skb_put(skb, length - ETHER_HEAD_LEN); /* allocate room for the packet body */
@@ -1354,15 +1482,15 @@ e100_rx(struct net_device *dev)
else {
/* Large packet, send directly to upper layers and allocate new
* memory (aligned to cache line boundary to avoid bug).
- * Before sending the skb to upper layers we must make sure that
- * skb->data points to the aligned start of the packet.
+ * Before sending the skb to upper layers we must make sure
+ * that skb->data points to the aligned start of the packet.
*/
int align;
struct sk_buff *new_skb = dev_alloc_skb(MAX_MEDIA_DATA_SIZE + 2 * L1_CACHE_BYTES);
if (!new_skb) {
np->stats.rx_errors++;
printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
- return;
+ goto update_nextrxdesc;
}
skb = myNextRxDesc->skb;
align = (int)phys_to_virt(myNextRxDesc->descr.buf) - (int)skb->data;
@@ -1377,9 +1505,10 @@ e100_rx(struct net_device *dev)
/* Send the packet to the upper layers */
netif_rx(skb);
+ update_nextrxdesc:
/* Prepare for next packet */
myNextRxDesc->descr.status = 0;
- myPrevRxDesc = myNextRxDesc;
+ prevRxDesc = myNextRxDesc;
myNextRxDesc = phys_to_virt(myNextRxDesc->descr.next);
rx_queue_len++;
@@ -1387,9 +1516,9 @@ e100_rx(struct net_device *dev)
/* Check if descriptors should be returned */
if (rx_queue_len == RX_QUEUE_THRESHOLD) {
flush_etrax_cache();
- myPrevRxDesc->descr.ctrl |= d_eol;
+ prevRxDesc->descr.ctrl |= d_eol;
myLastRxDesc->descr.ctrl &= ~d_eol;
- myLastRxDesc = myPrevRxDesc;
+ myLastRxDesc = prevRxDesc;
rx_queue_len = 0;
}
}
@@ -1398,7 +1527,7 @@ e100_rx(struct net_device *dev)
static int
e100_close(struct net_device *dev)
{
- struct net_local *np = (struct net_local *)dev->priv;
+ struct net_local *np = netdev_priv(dev);
printk(KERN_INFO "Closing %s.\n", dev->name);
@@ -1426,6 +1555,9 @@ e100_close(struct net_device *dev)
free_irq(NETWORK_DMA_TX_IRQ_NBR, (void *)dev);
free_irq(NETWORK_STATUS_IRQ_NBR, (void *)dev);
+ cris_free_dma(NETWORK_TX_DMA_NBR, cardname);
+ cris_free_dma(NETWORK_RX_DMA_NBR, cardname);
+
/* Update the statistics here. */
update_rx_stats(&np->stats);
@@ -1443,18 +1575,11 @@ e100_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
struct mii_ioctl_data *data = if_mii(ifr);
struct net_local *np = netdev_priv(dev);
+ int rc = 0;
+ int old_autoneg;
spin_lock(&np->lock); /* Preempt protection */
switch (cmd) {
- case SIOCGMIIPHY: /* Get PHY address */
- data->phy_id = mdio_phy_addr;
- break;
- case SIOCGMIIREG: /* Read MII register */
- data->val_out = e100_get_mdio_reg(dev, mdio_phy_addr, data->reg_num);
- break;
- case SIOCSMIIREG: /* Write MII register */
- e100_set_mdio_reg(dev, mdio_phy_addr, data->reg_num, data->val_in);
- break;
/* The ioctls below should be considered obsolete but are */
/* still present for compatability with old scripts/apps */
case SET_ETH_SPEED_10: /* 10 Mbps */
@@ -1463,60 +1588,47 @@ e100_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
case SET_ETH_SPEED_100: /* 100 Mbps */
e100_set_speed(dev, 100);
break;
- case SET_ETH_SPEED_AUTO: /* Auto negotiate speed */
+ case SET_ETH_SPEED_AUTO: /* Auto-negotiate speed */
e100_set_speed(dev, 0);
break;
- case SET_ETH_DUPLEX_HALF: /* Half duplex. */
+ case SET_ETH_DUPLEX_HALF: /* Half duplex */
e100_set_duplex(dev, half);
break;
- case SET_ETH_DUPLEX_FULL: /* Full duplex. */
+ case SET_ETH_DUPLEX_FULL: /* Full duplex */
e100_set_duplex(dev, full);
break;
- case SET_ETH_DUPLEX_AUTO: /* Autonegotiate duplex*/
+ case SET_ETH_DUPLEX_AUTO: /* Auto-negotiate duplex */
e100_set_duplex(dev, autoneg);
break;
+ case SET_ETH_AUTONEG:
+ old_autoneg = autoneg_normal;
+ autoneg_normal = *(int*)data;
+ if (autoneg_normal != old_autoneg)
+ e100_negotiate(dev);
+ break;
default:
- return -EINVAL;
+ rc = generic_mii_ioctl(&np->mii_if, if_mii(ifr),
+ cmd, NULL);
+ break;
}
spin_unlock(&np->lock);
- return 0;
+ return rc;
}
-static int e100_set_settings(struct net_device *dev,
- struct ethtool_cmd *ecmd)
+static int e100_get_settings(struct net_device *dev,
+ struct ethtool_cmd *cmd)
{
- ecmd->supported = SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII |
- SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
- SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full;
- ecmd->port = PORT_TP;
- ecmd->transceiver = XCVR_EXTERNAL;
- ecmd->phy_address = mdio_phy_addr;
- ecmd->speed = current_speed;
- ecmd->duplex = full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
- ecmd->advertising = ADVERTISED_TP;
+ struct net_local *np = netdev_priv(dev);
+ int err;
- if (current_duplex == autoneg && current_speed_selection == 0)
- ecmd->advertising |= ADVERTISED_Autoneg;
- else {
- ecmd->advertising |=
- ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
- ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full;
- if (current_speed_selection == 10)
- ecmd->advertising &= ~(ADVERTISED_100baseT_Half |
- ADVERTISED_100baseT_Full);
- else if (current_speed_selection == 100)
- ecmd->advertising &= ~(ADVERTISED_10baseT_Half |
- ADVERTISED_10baseT_Full);
- if (current_duplex == half)
- ecmd->advertising &= ~(ADVERTISED_10baseT_Full |
- ADVERTISED_100baseT_Full);
- else if (current_duplex == full)
- ecmd->advertising &= ~(ADVERTISED_10baseT_Half |
- ADVERTISED_100baseT_Half);
- }
+ spin_lock_irq(&np->lock);
+ err = mii_ethtool_gset(&np->mii_if, cmd);
+ spin_unlock_irq(&np->lock);
- ecmd->autoneg = AUTONEG_ENABLE;
- return 0;
+ /* The PHY may support 1000baseT, but the Etrax100 does not. */
+ cmd->supported &= ~(SUPPORTED_1000baseT_Half
+ | SUPPORTED_1000baseT_Full);
+ return err;
}
static int e100_set_settings(struct net_device *dev,
@@ -1560,7 +1672,8 @@ static const struct ethtool_ops e100_ethtool_ops = {
static int
e100_set_config(struct net_device *dev, struct ifmap *map)
{
- struct net_local *np = (struct net_local *)dev->priv;
+ struct net_local *np = netdev_priv(dev);
+
spin_lock(&np->lock); /* Preempt protection */
switch(map->port) {
@@ -1612,7 +1725,6 @@ update_tx_stats(struct net_device_stats *es)
es->collisions +=
IO_EXTRACT(R_TR_COUNTERS, single_col, r) +
IO_EXTRACT(R_TR_COUNTERS, multiple_col, r);
- es->tx_errors += IO_EXTRACT(R_TR_COUNTERS, deferred, r);
}
/*
@@ -1622,8 +1734,9 @@ update_tx_stats(struct net_device_stats *es)
static struct net_device_stats *
e100_get_stats(struct net_device *dev)
{
- struct net_local *lp = (struct net_local *)dev->priv;
+ struct net_local *lp = netdev_priv(dev);
unsigned long flags;
+
spin_lock_irqsave(&lp->lock, flags);
update_rx_stats(&lp->stats);
@@ -1643,13 +1756,13 @@ e100_get_stats(struct net_device *dev)
static void
set_multicast_list(struct net_device *dev)
{
- struct net_local *lp = (struct net_local *)dev->priv;
+ struct net_local *lp = netdev_priv(dev);
int num_addr = dev->mc_count;
unsigned long int lo_bits;
unsigned long int hi_bits;
+
spin_lock(&lp->lock);
- if (dev->flags & IFF_PROMISC)
- {
+ if (dev->flags & IFF_PROMISC) {
/* promiscuous mode */
lo_bits = 0xfffffffful;
hi_bits = 0xfffffffful;
@@ -1679,9 +1792,10 @@ set_multicast_list(struct net_device *dev)
struct dev_mc_list *dmi = dev->mc_list;
int i;
char *baddr;
+
lo_bits = 0x00000000ul;
hi_bits = 0x00000000ul;
- for (i=0; i<num_addr; i++) {
+ for (i = 0; i < num_addr; i++) {
/* Calculate the hash index for the GA registers */
hash_ix = 0;
@@ -1708,8 +1822,7 @@ set_multicast_list(struct net_device *dev)
if (hash_ix >= 32) {
hi_bits |= (1 << (hash_ix-32));
- }
- else {
+ } else {
lo_bits |= (1 << hash_ix);
}
dmi = dmi->next;
@@ -1724,10 +1837,11 @@ set_multicast_list(struct net_device *dev)
}
void
-e100_hardware_send_packet(char *buf, int length)
+e100_hardware_send_packet(struct net_local *np, char *buf, int length)
{
D(printk("e100 send pack, buf 0x%x len %d\n", buf, length));
+ spin_lock(&np->led_lock);
if (!led_active && time_after(jiffies, led_next_time)) {
/* light the network leds depending on the current speed. */
e100_set_network_leds(NETWORK_ACTIVITY);
@@ -1737,6 +1851,7 @@ e100_hardware_send_packet(char *buf, int length)
led_active = 1;
mod_timer(&clear_led_timer, jiffies + HZ/10);
}
+ spin_unlock(&np->led_lock);
/* configure the tx dma descriptor */
myNextTxDesc->descr.sw_len = length;
@@ -1754,6 +1869,11 @@ e100_hardware_send_packet(char *buf, int length)
static void
e100_clear_network_leds(unsigned long dummy)
{
+ struct net_device *dev = (struct net_device *)dummy;
+ struct net_local *np = netdev_priv(dev);
+
+ spin_lock(&np->led_lock);
+
if (led_active && time_after(jiffies, led_next_time)) {
e100_set_network_leds(NO_NETWORK_ACTIVITY);
@@ -1761,6 +1881,8 @@ e100_clear_network_leds(unsigned long dummy)
led_next_time = jiffies + NET_FLASH_PAUSE;
led_active = 0;
}
+
+ spin_unlock(&np->led_lock);
}
static void
@@ -1781,19 +1903,25 @@ e100_set_network_leds(int active)
#else
LED_NETWORK_SET(LED_OFF);
#endif
- }
- else if (light_leds) {
+ } else if (light_leds) {
if (current_speed == 10) {
LED_NETWORK_SET(LED_ORANGE);
} else {
LED_NETWORK_SET(LED_GREEN);
}
- }
- else {
+ } else {
LED_NETWORK_SET(LED_OFF);
}
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void
+e100_netpoll(struct net_device* netdev)
+{
+ e100rxtx_interrupt(NETWORK_DMA_TX_IRQ_NBR, netdev, NULL);
+}
+#endif
+
static int
etrax_init_module(void)
{
diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h
index 044261703381..60a62f510db7 100644
--- a/drivers/net/cxgb3/adapter.h
+++ b/drivers/net/cxgb3/adapter.h
@@ -41,13 +41,11 @@
#include <linux/timer.h>
#include <linux/cache.h>
#include <linux/mutex.h>
+#include <linux/bitops.h>
#include "t3cdev.h"
#include <asm/semaphore.h>
-#include <asm/bitops.h>
#include <asm/io.h>
-typedef irqreturn_t(*intr_handler_t) (int, void *);
-
struct vlan_group;
struct adapter;
struct sge_qset;
@@ -270,7 +268,7 @@ void t3_sge_start(struct adapter *adap);
void t3_sge_stop(struct adapter *adap);
void t3_free_sge_resources(struct adapter *adap);
void t3_sge_err_intr_handler(struct adapter *adapter);
-intr_handler_t t3_intr_handler(struct adapter *adap, int polling);
+irq_handler_t t3_intr_handler(struct adapter *adap, int polling);
int t3_eth_xmit(struct sk_buff *skb, struct net_device *dev);
int t3_mgmt_tx(struct adapter *adap, struct sk_buff *skb);
void t3_update_qset_coalesce(struct sge_qset *qs, const struct qset_params *p);
diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c
index 994b5d6404df..c15e43a8543b 100644
--- a/drivers/net/cxgb3/sge.c
+++ b/drivers/net/cxgb3/sge.c
@@ -2431,7 +2431,7 @@ static irqreturn_t t3b_intr_napi(int irq, void *cookie)
* (MSI-X, MSI, or legacy) and whether NAPI will be used to service the
* response queues.
*/
-intr_handler_t t3_intr_handler(struct adapter *adap, int polling)
+irq_handler_t t3_intr_handler(struct adapter *adap, int polling)
{
if (adap->flags & USING_MSIX)
return polling ? t3_sge_intr_msix_napi : t3_sge_intr_msix;
diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c
index b07613e61f53..ddc30c4bf34a 100644
--- a/drivers/net/defxx.c
+++ b/drivers/net/defxx.c
@@ -805,7 +805,7 @@ static void __devinit dfx_bus_init(struct net_device *dev)
* Interrupts are disabled at the adapter bus-specific logic.
*/
-static void __devinit dfx_bus_uninit(struct net_device *dev)
+static void __devexit dfx_bus_uninit(struct net_device *dev)
{
DFX_board_t *bp = netdev_priv(dev);
struct device *bdev = bp->bus_dev;
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index 27ac010900ab..3286d2a0a870 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -542,7 +542,8 @@ dm9000_probe(struct platform_device *pdev)
if (id_val != DM9000_ID) {
printk("%s: wrong id: 0x%08x\n", CARDNAME, id_val);
- goto release;
+ ret = -ENODEV;
+ goto out;
}
/* from this point we assume that we have found a DM9000 */
@@ -602,8 +603,7 @@ dm9000_probe(struct platform_device *pdev)
}
return 0;
- release:
- out:
+out:
printk("%s: not found (%d).\n", CARDNAME, ret);
dm9000_release_board(pdev, db);
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 64f35e20fd48..3dbaec680b46 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -1324,7 +1324,7 @@ static inline int e100_exec_cb_wait(struct nic *nic, struct sk_buff *skb,
if (!--counter) break;
}
- /* ack any interupts, something could have been set */
+ /* ack any interrupts, something could have been set */
iowrite8(~0, &nic->csr->scb.stat_ack);
/* if the command failed, or is not OK, notify and return */
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index 781ed9968489..3b840283a9c3 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -351,4 +351,12 @@ enum e1000_state_t {
__E1000_DOWN
};
+extern char e1000_driver_name[];
+extern const char e1000_driver_version[];
+
+extern void e1000_power_up_phy(struct e1000_adapter *);
+extern void e1000_set_ethtool_ops(struct net_device *netdev);
+extern void e1000_check_options(struct e1000_adapter *adapter);
+
+
#endif /* _E1000_H_ */
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index 6c9a643426f5..667f18bcc172 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -32,9 +32,6 @@
#include <asm/uaccess.h>
-extern char e1000_driver_name[];
-extern char e1000_driver_version[];
-
extern int e1000_up(struct e1000_adapter *adapter);
extern void e1000_down(struct e1000_adapter *adapter);
extern void e1000_reinit_locked(struct e1000_adapter *adapter);
@@ -733,16 +730,16 @@ err_setup:
#define REG_PATTERN_TEST(R, M, W) \
{ \
- uint32_t pat, value; \
- uint32_t test[] = \
+ uint32_t pat, val; \
+ const uint32_t test[] = \
{0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; \
- for (pat = 0; pat < ARRAY_SIZE(test); pat++) { \
+ for (pat = 0; pat < ARRAY_SIZE(test); pat++) { \
E1000_WRITE_REG(&adapter->hw, R, (test[pat] & W)); \
- value = E1000_READ_REG(&adapter->hw, R); \
- if (value != (test[pat] & W & M)) { \
+ val = E1000_READ_REG(&adapter->hw, R); \
+ if (val != (test[pat] & W & M)) { \
DPRINTK(DRV, ERR, "pattern test reg %04X failed: got " \
"0x%08X expected 0x%08X\n", \
- E1000_##R, value, (test[pat] & W & M)); \
+ E1000_##R, val, (test[pat] & W & M)); \
*data = (adapter->hw.mac_type < e1000_82543) ? \
E1000_82542_##R : E1000_##R; \
return 1; \
@@ -752,12 +749,12 @@ err_setup:
#define REG_SET_AND_CHECK(R, M, W) \
{ \
- uint32_t value; \
+ uint32_t val; \
E1000_WRITE_REG(&adapter->hw, R, W & M); \
- value = E1000_READ_REG(&adapter->hw, R); \
- if ((W & M) != (value & M)) { \
+ val = E1000_READ_REG(&adapter->hw, R); \
+ if ((W & M) != (val & M)) { \
DPRINTK(DRV, ERR, "set/check reg %04X test failed: got 0x%08X "\
- "expected 0x%08X\n", E1000_##R, (value & M), (W & M)); \
+ "expected 0x%08X\n", E1000_##R, (val & M), (W & M)); \
*data = (adapter->hw.mac_type < e1000_82543) ? \
E1000_82542_##R : E1000_##R; \
return 1; \
@@ -1621,8 +1618,6 @@ e1000_get_sset_count(struct net_device *netdev, int sset)
}
}
-extern void e1000_power_up_phy(struct e1000_adapter *);
-
static void
e1000_diag_test(struct net_device *netdev,
struct ethtool_test *eth_test, uint64_t *data)
@@ -1859,8 +1854,8 @@ e1000_phys_id(struct net_device *netdev, uint32_t data)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- if (!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ))
- data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ);
+ if (!data)
+ data = INT_MAX;
if (adapter->hw.mac_type < e1000_82571) {
if (!adapter->blink_timer.function) {
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
index 8fa0fe4009d5..7c6888c58c21 100644
--- a/drivers/net/e1000/e1000_hw.c
+++ b/drivers/net/e1000/e1000_hw.c
@@ -8607,7 +8607,7 @@ e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index,
DEBUGFUNC("e1000_read_ich8_data");
- if (size < 1 || size > 2 || data == 0x0 ||
+ if (size < 1 || size > 2 || data == NULL ||
index > ICH_FLASH_LINEAR_ADDR_MASK)
return error;
@@ -8841,7 +8841,7 @@ e1000_read_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t *data)
* amount of NVM used in each bank is a *minimum* of 4 KBytes, but in fact the
* bank size may be 4, 8 or 64 KBytes
*****************************************************************************/
-int32_t
+static int32_t
e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t bank)
{
union ich8_hws_flash_status hsfsts;
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 047263830e6a..cf39473ef90a 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -37,8 +37,8 @@ static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
#define DRIVERNAPI "-NAPI"
#endif
#define DRV_VERSION "7.3.20-k2"DRIVERNAPI
-char e1000_driver_version[] = DRV_VERSION;
-static char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
+const char e1000_driver_version[] = DRV_VERSION;
+static const char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
/* e1000_pci_tbl - PCI Device ID Table
*
@@ -188,7 +188,6 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
int cmd);
-void e1000_set_ethtool_ops(struct net_device *netdev);
static void e1000_enter_82542_rst(struct e1000_adapter *adapter);
static void e1000_leave_82542_rst(struct e1000_adapter *adapter);
static void e1000_tx_timeout(struct net_device *dev);
@@ -213,8 +212,6 @@ static void e1000_shutdown(struct pci_dev *pdev);
static void e1000_netpoll (struct net_device *netdev);
#endif
-extern void e1000_check_options(struct e1000_adapter *adapter);
-
#define COPYBREAK_DEFAULT 256
static unsigned int copybreak __read_mostly = COPYBREAK_DEFAULT;
module_param(copybreak, uint, 0644);
@@ -3590,7 +3587,7 @@ e1000_update_stats(struct e1000_adapter *adapter)
spin_lock_irqsave(&adapter->stats_lock, flags);
- /* these counters are modified from e1000_adjust_tbi_stats,
+ /* these counters are modified from e1000_tbi_adjust_stats,
* called from the interrupt context, so they must only
* be written while holding adapter->stats_lock
*/
@@ -4807,6 +4804,7 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
spin_unlock_irqrestore(&adapter->stats_lock, flags);
return -EIO;
}
+ spin_unlock_irqrestore(&adapter->stats_lock, flags);
if (adapter->hw.media_type == e1000_media_type_copper) {
switch (data->reg_num) {
case PHY_CTRL:
@@ -4827,12 +4825,8 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
DUPLEX_HALF;
retval = e1000_set_spd_dplx(adapter,
spddplx);
- if (retval) {
- spin_unlock_irqrestore(
- &adapter->stats_lock,
- flags);
+ if (retval)
return retval;
- }
}
if (netif_running(adapter->netdev))
e1000_reinit_locked(adapter);
@@ -4841,11 +4835,8 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
break;
case M88E1000_PHY_SPEC_CTRL:
case M88E1000_EXT_PHY_SPEC_CTRL:
- if (e1000_phy_reset(&adapter->hw)) {
- spin_unlock_irqrestore(
- &adapter->stats_lock, flags);
+ if (e1000_phy_reset(&adapter->hw))
return -EIO;
- }
break;
}
} else {
@@ -4860,7 +4851,6 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
break;
}
}
- spin_unlock_irqrestore(&adapter->stats_lock, flags);
break;
default:
return -EOPNOTSUPP;
diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c
index f485874a63f5..e6565ce686bc 100644
--- a/drivers/net/e1000/e1000_param.c
+++ b/drivers/net/e1000/e1000_param.c
@@ -46,7 +46,7 @@
#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
#define E1000_PARAM(X, desc) \
static int __devinitdata X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \
- static int num_##X = 0; \
+ static unsigned int num_##X; \
module_param_array_named(X, X, int, &num_##X, 0); \
MODULE_PARM_DESC(X, desc);
@@ -198,9 +198,9 @@ E1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround");
struct e1000_option {
enum { enable_option, range_option, list_option } type;
- char *name;
- char *err;
- int def;
+ const char *name;
+ const char *err;
+ int def;
union {
struct { /* range_option info */
int min;
@@ -214,8 +214,9 @@ struct e1000_option {
};
static int __devinit
-e1000_validate_option(int *value, struct e1000_option *opt,
- struct e1000_adapter *adapter)
+e1000_validate_option(unsigned int *value,
+ const struct e1000_option *opt,
+ struct e1000_adapter *adapter)
{
if (*value == OPTION_UNSET) {
*value = opt->def;
@@ -348,7 +349,7 @@ e1000_check_options(struct e1000_adapter *adapter)
};
if (num_XsumRX > bd) {
- int rx_csum = XsumRX[bd];
+ unsigned int rx_csum = XsumRX[bd];
e1000_validate_option(&rx_csum, &opt, adapter);
adapter->rx_csum = rx_csum;
} else {
@@ -374,7 +375,7 @@ e1000_check_options(struct e1000_adapter *adapter)
};
if (num_FlowControl > bd) {
- int fc = FlowControl[bd];
+ unsigned int fc = FlowControl[bd];
e1000_validate_option(&fc, &opt, adapter);
adapter->hw.fc = adapter->hw.original_fc = fc;
} else {
@@ -506,7 +507,7 @@ e1000_check_options(struct e1000_adapter *adapter)
};
if (num_SmartPowerDownEnable > bd) {
- int spd = SmartPowerDownEnable[bd];
+ unsigned int spd = SmartPowerDownEnable[bd];
e1000_validate_option(&spd, &opt, adapter);
adapter->smart_power_down = spd;
} else {
@@ -522,7 +523,7 @@ e1000_check_options(struct e1000_adapter *adapter)
};
if (num_KumeranLockLoss > bd) {
- int kmrn_lock_loss = KumeranLockLoss[bd];
+ unsigned int kmrn_lock_loss = KumeranLockLoss[bd];
e1000_validate_option(&kmrn_lock_loss, &opt, adapter);
adapter->hw.kmrn_lock_loss_workaround_disabled = !kmrn_lock_loss;
} else {
@@ -581,7 +582,7 @@ e1000_check_fiber_options(struct e1000_adapter *adapter)
static void __devinit
e1000_check_copper_options(struct e1000_adapter *adapter)
{
- int speed, dplx, an;
+ unsigned int speed, dplx, an;
int bd = adapter->bd_number;
{ /* Speed */
diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c
index cf70522fc851..14141a55eaa6 100644
--- a/drivers/net/e1000e/82571.c
+++ b/drivers/net/e1000e/82571.c
@@ -283,7 +283,7 @@ static s32 e1000_get_invariants_82571(struct e1000_adapter *adapter)
adapter->flags &= ~FLAG_HAS_WOL;
/* quad ports only support WoL on port A */
if (adapter->flags & FLAG_IS_QUAD_PORT &&
- (!adapter->flags & FLAG_IS_QUAD_PORT_A))
+ (!(adapter->flags & FLAG_IS_QUAD_PORT_A)))
adapter->flags &= ~FLAG_HAS_WOL;
break;
diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h
index d2499bb07c13..473f78de4be0 100644
--- a/drivers/net/e1000e/e1000.h
+++ b/drivers/net/e1000e/e1000.h
@@ -122,7 +122,8 @@ struct e1000_buffer {
u16 next_to_watch;
};
/* RX */
- struct page *page;
+ /* arrays of page information for packet split */
+ struct e1000_ps_page *ps_pages;
};
};
@@ -142,8 +143,6 @@ struct e1000_ring {
/* array of buffer information structs */
struct e1000_buffer *buffer_info;
- /* arrays of page information for packet split */
- struct e1000_ps_page *ps_pages;
struct sk_buff *rx_skb_top;
struct e1000_queue_stats stats;
diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c
index b7a7e2ae5e13..6a39784e7ee2 100644
--- a/drivers/net/e1000e/ethtool.c
+++ b/drivers/net/e1000e/ethtool.c
@@ -110,6 +110,7 @@ static int e1000_get_settings(struct net_device *netdev,
{
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
+ u32 status;
if (hw->media_type == e1000_media_type_copper) {
@@ -147,16 +148,16 @@ static int e1000_get_settings(struct net_device *netdev,
ecmd->transceiver = XCVR_EXTERNAL;
}
- if (er32(STATUS) & E1000_STATUS_LU) {
-
- adapter->hw.mac.ops.get_link_up_info(hw, &adapter->link_speed,
- &adapter->link_duplex);
- ecmd->speed = adapter->link_speed;
-
- /* unfortunately FULL_DUPLEX != DUPLEX_FULL
- * and HALF_DUPLEX != DUPLEX_HALF */
+ status = er32(STATUS);
+ if (status & E1000_STATUS_LU) {
+ if (status & E1000_STATUS_SPEED_1000)
+ ecmd->speed = 1000;
+ else if (status & E1000_STATUS_SPEED_100)
+ ecmd->speed = 100;
+ else
+ ecmd->speed = 10;
- if (adapter->link_duplex == FULL_DUPLEX)
+ if (status & E1000_STATUS_FD)
ecmd->duplex = DUPLEX_FULL;
else
ecmd->duplex = DUPLEX_HALF;
@@ -170,6 +171,16 @@ static int e1000_get_settings(struct net_device *netdev,
return 0;
}
+static u32 e1000_get_link(struct net_device *netdev)
+{
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
+ u32 status;
+
+ status = er32(STATUS);
+ return (status & E1000_STATUS_LU);
+}
+
static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx)
{
struct e1000_mac_info *mac = &adapter->hw.mac;
@@ -1451,11 +1462,11 @@ static int e1000_loopback_test(struct e1000_adapter *adapter, u64 *data)
}
*data = e1000_setup_desc_rings(adapter);
- if (data)
+ if (*data)
goto out;
*data = e1000_setup_loopback_test(adapter);
- if (data)
+ if (*data)
goto err_loopback;
*data = e1000_run_loopback_test(adapter);
@@ -1669,8 +1680,8 @@ static int e1000_phys_id(struct net_device *netdev, u32 data)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))
- data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
+ if (!data)
+ data = INT_MAX;
if (adapter->hw.phy.type == e1000_phy_ife) {
if (!adapter->blink_timer.function) {
@@ -1751,7 +1762,7 @@ static const struct ethtool_ops e1000_ethtool_ops = {
.get_msglevel = e1000_get_msglevel,
.set_msglevel = e1000_set_msglevel,
.nway_reset = e1000_nway_reset,
- .get_link = ethtool_op_get_link,
+ .get_link = e1000_get_link,
.get_eeprom_len = e1000_get_eeprom_len,
.get_eeprom = e1000_get_eeprom,
.set_eeprom = e1000_set_eeprom,
diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h
index aa82f1afb7fb..64515789fd4d 100644
--- a/drivers/net/e1000e/hw.h
+++ b/drivers/net/e1000e/hw.h
@@ -852,7 +852,7 @@ struct e1000_hw {
#ifdef DEBUG
#define hw_dbg(hw, format, arg...) \
- printk(KERN_DEBUG, "%s: " format, e1000e_get_hw_dev_name(hw), ##arg);
+ printk(KERN_DEBUG "%s: " format, e1000e_get_hw_dev_name(hw), ##arg)
#else
static inline int __attribute__ ((format (printf, 2, 3)))
hw_dbg(struct e1000_hw *hw, const char *format, ...)
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 033e124d1c1f..4fd2e23720b6 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -245,37 +245,36 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
for (j = 0; j < PS_PAGE_BUFFERS; j++) {
- ps_page = &rx_ring->ps_pages[(i * PS_PAGE_BUFFERS)
- + j];
- if (j < adapter->rx_ps_pages) {
+ ps_page = &buffer_info->ps_pages[j];
+ if (j >= adapter->rx_ps_pages) {
+ /* all unused desc entries get hw null ptr */
+ rx_desc->read.buffer_addr[j+1] = ~0;
+ continue;
+ }
+ if (!ps_page->page) {
+ ps_page->page = alloc_page(GFP_ATOMIC);
if (!ps_page->page) {
- ps_page->page = alloc_page(GFP_ATOMIC);
- if (!ps_page->page) {
- adapter->alloc_rx_buff_failed++;
- goto no_buffers;
- }
- ps_page->dma = pci_map_page(pdev,
- ps_page->page,
- 0, PAGE_SIZE,
- PCI_DMA_FROMDEVICE);
- if (pci_dma_mapping_error(
- ps_page->dma)) {
- dev_err(&adapter->pdev->dev,
- "RX DMA page map failed\n");
- adapter->rx_dma_failed++;
- goto no_buffers;
- }
+ adapter->alloc_rx_buff_failed++;
+ goto no_buffers;
+ }
+ ps_page->dma = pci_map_page(pdev,
+ ps_page->page,
+ 0, PAGE_SIZE,
+ PCI_DMA_FROMDEVICE);
+ if (pci_dma_mapping_error(ps_page->dma)) {
+ dev_err(&adapter->pdev->dev,
+ "RX DMA page map failed\n");
+ adapter->rx_dma_failed++;
+ goto no_buffers;
}
- /*
- * Refresh the desc even if buffer_addrs
- * didn't change because each write-back
- * erases this info.
- */
- rx_desc->read.buffer_addr[j+1] =
- cpu_to_le64(ps_page->dma);
- } else {
- rx_desc->read.buffer_addr[j+1] = ~0;
}
+ /*
+ * Refresh the desc even if buffer_addrs
+ * didn't change because each write-back
+ * erases this info.
+ */
+ rx_desc->read.buffer_addr[j+1] =
+ cpu_to_le64(ps_page->dma);
}
skb = netdev_alloc_skb(netdev,
@@ -334,94 +333,6 @@ no_buffers:
}
/**
- * e1000_alloc_rx_buffers_jumbo - Replace used jumbo receive buffers
- *
- * @adapter: address of board private structure
- * @cleaned_count: number of buffers to allocate this pass
- **/
-static void e1000_alloc_rx_buffers_jumbo(struct e1000_adapter *adapter,
- int cleaned_count)
-{
- struct net_device *netdev = adapter->netdev;
- struct pci_dev *pdev = adapter->pdev;
- struct e1000_ring *rx_ring = adapter->rx_ring;
- struct e1000_rx_desc *rx_desc;
- struct e1000_buffer *buffer_info;
- struct sk_buff *skb;
- unsigned int i;
- unsigned int bufsz = 256 -
- 16 /*for skb_reserve */ -
- NET_IP_ALIGN;
-
- i = rx_ring->next_to_use;
- buffer_info = &rx_ring->buffer_info[i];
-
- while (cleaned_count--) {
- skb = buffer_info->skb;
- if (skb) {
- skb_trim(skb, 0);
- goto check_page;
- }
-
- skb = netdev_alloc_skb(netdev, bufsz);
- if (!skb) {
- /* Better luck next round */
- adapter->alloc_rx_buff_failed++;
- break;
- }
-
- /* Make buffer alignment 2 beyond a 16 byte boundary
- * this will result in a 16 byte aligned IP header after
- * the 14 byte MAC header is removed
- */
- skb_reserve(skb, NET_IP_ALIGN);
-
- buffer_info->skb = skb;
-check_page:
- /* allocate a new page if necessary */
- if (!buffer_info->page) {
- buffer_info->page = alloc_page(GFP_ATOMIC);
- if (!buffer_info->page) {
- adapter->alloc_rx_buff_failed++;
- break;
- }
- }
-
- if (!buffer_info->dma)
- buffer_info->dma = pci_map_page(pdev,
- buffer_info->page, 0,
- PAGE_SIZE,
- PCI_DMA_FROMDEVICE);
- if (pci_dma_mapping_error(buffer_info->dma)) {
- dev_err(&adapter->pdev->dev, "RX DMA page map failed\n");
- adapter->rx_dma_failed++;
- break;
- }
-
- rx_desc = E1000_RX_DESC(*rx_ring, i);
- rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
-
- i++;
- if (i == rx_ring->count)
- i = 0;
- buffer_info = &rx_ring->buffer_info[i];
- }
-
- if (rx_ring->next_to_use != i) {
- rx_ring->next_to_use = i;
- if (i-- == 0)
- i = (rx_ring->count - 1);
-
- /* Force memory writes to complete before letting h/w
- * know there are new descriptors to fetch. (Only
- * applicable for weak-ordered memory model archs,
- * such as IA-64). */
- wmb();
- writel(i, adapter->hw.hw_addr + rx_ring->tail);
- }
-}
-
-/**
* e1000_clean_rx_irq - Send received data up the network stack; legacy
* @adapter: board private structure
*
@@ -495,10 +406,6 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
goto next_desc;
}
- /* adjust length to remove Ethernet CRC */
- length -= 4;
-
- /* probably a little skewed due to removing CRC */
total_rx_bytes += length;
total_rx_packets++;
@@ -554,15 +461,6 @@ next_desc:
return cleaned;
}
-static void e1000_consume_page(struct e1000_buffer *bi, struct sk_buff *skb,
- u16 length)
-{
- bi->page = NULL;
- skb->len += length;
- skb->data_len += length;
- skb->truesize += length;
-}
-
static void e1000_put_txbuf(struct e1000_adapter *adapter,
struct e1000_buffer *buffer_info)
{
@@ -699,174 +597,6 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter)
}
/**
- * e1000_clean_rx_irq_jumbo - Send received data up the network stack; legacy
- * @adapter: board private structure
- *
- * the return value indicates whether actual cleaning was done, there
- * is no guarantee that everything was cleaned
- **/
-static bool e1000_clean_rx_irq_jumbo(struct e1000_adapter *adapter,
- int *work_done, int work_to_do)
-{
- struct net_device *netdev = adapter->netdev;
- struct pci_dev *pdev = adapter->pdev;
- struct e1000_ring *rx_ring = adapter->rx_ring;
- struct e1000_rx_desc *rx_desc, *next_rxd;
- struct e1000_buffer *buffer_info, *next_buffer;
- u32 length;
- unsigned int i;
- int cleaned_count = 0;
- bool cleaned = 0;
- unsigned int total_rx_bytes = 0, total_rx_packets = 0;
-
- i = rx_ring->next_to_clean;
- rx_desc = E1000_RX_DESC(*rx_ring, i);
- buffer_info = &rx_ring->buffer_info[i];
-
- while (rx_desc->status & E1000_RXD_STAT_DD) {
- struct sk_buff *skb;
- u8 status;
-
- if (*work_done >= work_to_do)
- break;
- (*work_done)++;
-
- status = rx_desc->status;
- skb = buffer_info->skb;
- buffer_info->skb = NULL;
-
- i++;
- if (i == rx_ring->count)
- i = 0;
- next_rxd = E1000_RX_DESC(*rx_ring, i);
- prefetch(next_rxd);
-
- next_buffer = &rx_ring->buffer_info[i];
-
- cleaned = 1;
- cleaned_count++;
- pci_unmap_page(pdev,
- buffer_info->dma,
- PAGE_SIZE,
- PCI_DMA_FROMDEVICE);
- buffer_info->dma = 0;
-
- length = le16_to_cpu(rx_desc->length);
-
- /* errors is only valid for DD + EOP descriptors */
- if ((status & E1000_RXD_STAT_EOP) &&
- (rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) {
- /* recycle both page and skb */
- buffer_info->skb = skb;
- /* an error means any chain goes out the window too */
- if (rx_ring->rx_skb_top)
- dev_kfree_skb(rx_ring->rx_skb_top);
- rx_ring->rx_skb_top = NULL;
- goto next_desc;
- }
-
-#define rxtop rx_ring->rx_skb_top
- if (!(status & E1000_RXD_STAT_EOP)) {
- /* this descriptor is only the beginning (or middle) */
- if (!rxtop) {
- /* this is the beginning of a chain */
- rxtop = skb;
- skb_fill_page_desc(rxtop, 0, buffer_info->page,
- 0, length);
- } else {
- /* this is the middle of a chain */
- skb_fill_page_desc(rxtop,
- skb_shinfo(rxtop)->nr_frags,
- buffer_info->page, 0,
- length);
- /* re-use the skb, only consumed the page */
- buffer_info->skb = skb;
- }
- e1000_consume_page(buffer_info, rxtop, length);
- goto next_desc;
- } else {
- if (rxtop) {
- /* end of the chain */
- skb_fill_page_desc(rxtop,
- skb_shinfo(rxtop)->nr_frags,
- buffer_info->page, 0, length);
- /* re-use the current skb, we only consumed the
- * page */
- buffer_info->skb = skb;
- skb = rxtop;
- rxtop = NULL;
- e1000_consume_page(buffer_info, skb, length);
- } else {
- /* no chain, got EOP, this buf is the packet
- * copybreak to save the put_page/alloc_page */
- if (length <= copybreak &&
- skb_tailroom(skb) >= length) {
- u8 *vaddr;
- vaddr = kmap_atomic(buffer_info->page,
- KM_SKB_DATA_SOFTIRQ);
- memcpy(skb_tail_pointer(skb),
- vaddr, length);
- kunmap_atomic(vaddr,
- KM_SKB_DATA_SOFTIRQ);
- /* re-use the page, so don't erase
- * buffer_info->page */
- skb_put(skb, length);
- } else {
- skb_fill_page_desc(skb, 0,
- buffer_info->page, 0,
- length);
- e1000_consume_page(buffer_info, skb,
- length);
- }
- }
- }
-
- /* Receive Checksum Offload XXX recompute due to CRC strip? */
- e1000_rx_checksum(adapter,
- (u32)(status) |
- ((u32)(rx_desc->errors) << 24),
- le16_to_cpu(rx_desc->csum), skb);
-
- pskb_trim(skb, skb->len - 4);
-
- /* probably a little skewed due to removing CRC */
- total_rx_bytes += skb->len;
- total_rx_packets++;
-
- /* eth type trans needs skb->data to point to something */
- if (!pskb_may_pull(skb, ETH_HLEN)) {
- ndev_err(netdev, "__pskb_pull_tail failed.\n");
- dev_kfree_skb(skb);
- goto next_desc;
- }
-
- e1000_receive_skb(adapter, netdev, skb,status,rx_desc->special);
-
-next_desc:
- rx_desc->status = 0;
-
- /* return some buffers to hardware, one at a time is too slow */
- if (cleaned_count >= E1000_RX_BUFFER_WRITE) {
- adapter->alloc_rx_buf(adapter, cleaned_count);
- cleaned_count = 0;
- }
-
- /* use prefetched values */
- rx_desc = next_rxd;
- buffer_info = next_buffer;
- }
- rx_ring->next_to_clean = i;
-
- cleaned_count = e1000_desc_unused(rx_ring);
- if (cleaned_count)
- adapter->alloc_rx_buf(adapter, cleaned_count);
-
- adapter->total_rx_packets += total_rx_packets;
- adapter->total_rx_bytes += total_rx_bytes;
- return cleaned;
-}
-
-/**
* e1000_clean_rx_irq_ps - Send received data up the network stack; packet split
* @adapter: board private structure
*
@@ -953,7 +683,7 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
((length + l1) <= adapter->rx_ps_bsize0)) {
u8 *vaddr;
- ps_page = &rx_ring->ps_pages[i * PS_PAGE_BUFFERS];
+ ps_page = &buffer_info->ps_pages[0];
/* there is no documentation about how to call
* kmap_atomic, so we can't hold the mapping
@@ -965,8 +695,7 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
kunmap_atomic(vaddr, KM_SKB_DATA_SOFTIRQ);
pci_dma_sync_single_for_device(pdev, ps_page->dma,
PAGE_SIZE, PCI_DMA_FROMDEVICE);
- /* remove the CRC */
- l1 -= 4;
+
skb_put(skb, l1);
goto copydone;
} /* if */
@@ -977,7 +706,7 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
if (!length)
break;
- ps_page = &rx_ring->ps_pages[(i * PS_PAGE_BUFFERS) + j];
+ ps_page = &buffer_info->ps_pages[j];
pci_unmap_page(pdev, ps_page->dma, PAGE_SIZE,
PCI_DMA_FROMDEVICE);
ps_page->dma = 0;
@@ -988,10 +717,6 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
skb->truesize += length;
}
- /* strip the ethernet crc, problem is we're using pages now so
- * this whole operation can get a little cpu intensive */
- pskb_trim(skb, skb->len - 4);
-
copydone:
total_rx_bytes += skb->len;
total_rx_packets++;
@@ -1043,7 +768,6 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter)
struct e1000_buffer *buffer_info;
struct e1000_ps_page *ps_page;
struct pci_dev *pdev = adapter->pdev;
- unsigned long size;
unsigned int i, j;
/* Free all the Rx ring sk_buffs */
@@ -1054,9 +778,6 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter)
pci_unmap_single(pdev, buffer_info->dma,
adapter->rx_buffer_len,
PCI_DMA_FROMDEVICE);
- else if (adapter->clean_rx == e1000_clean_rx_irq_jumbo)
- pci_unmap_page(pdev, buffer_info->dma,
- PAGE_SIZE, PCI_DMA_FROMDEVICE);
else if (adapter->clean_rx == e1000_clean_rx_irq_ps)
pci_unmap_single(pdev, buffer_info->dma,
adapter->rx_ps_bsize0,
@@ -1064,19 +785,13 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter)
buffer_info->dma = 0;
}
- if (buffer_info->page) {
- put_page(buffer_info->page);
- buffer_info->page = NULL;
- }
-
if (buffer_info->skb) {
dev_kfree_skb(buffer_info->skb);
buffer_info->skb = NULL;
}
for (j = 0; j < PS_PAGE_BUFFERS; j++) {
- ps_page = &rx_ring->ps_pages[(i * PS_PAGE_BUFFERS)
- + j];
+ ps_page = &buffer_info->ps_pages[j];
if (!ps_page->page)
break;
pci_unmap_page(pdev, ps_page->dma, PAGE_SIZE,
@@ -1093,12 +808,6 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter)
rx_ring->rx_skb_top = NULL;
}
- size = sizeof(struct e1000_buffer) * rx_ring->count;
- memset(rx_ring->buffer_info, 0, size);
- size = sizeof(struct e1000_ps_page)
- * (rx_ring->count * PS_PAGE_BUFFERS);
- memset(rx_ring->ps_pages, 0, size);
-
/* Zero out the descriptor ring */
memset(rx_ring->desc, 0, rx_ring->size);
@@ -1421,7 +1130,8 @@ err:
int e1000e_setup_rx_resources(struct e1000_adapter *adapter)
{
struct e1000_ring *rx_ring = adapter->rx_ring;
- int size, desc_len, err = -ENOMEM;
+ struct e1000_buffer *buffer_info;
+ int i, size, desc_len, err = -ENOMEM;
size = sizeof(struct e1000_buffer) * rx_ring->count;
rx_ring->buffer_info = vmalloc(size);
@@ -1429,11 +1139,14 @@ int e1000e_setup_rx_resources(struct e1000_adapter *adapter)
goto err;
memset(rx_ring->buffer_info, 0, size);
- rx_ring->ps_pages = kcalloc(rx_ring->count * PS_PAGE_BUFFERS,
- sizeof(struct e1000_ps_page),
- GFP_KERNEL);
- if (!rx_ring->ps_pages)
- goto err;
+ for (i = 0; i < rx_ring->count; i++) {
+ buffer_info = &rx_ring->buffer_info[i];
+ buffer_info->ps_pages = kcalloc(PS_PAGE_BUFFERS,
+ sizeof(struct e1000_ps_page),
+ GFP_KERNEL);
+ if (!buffer_info->ps_pages)
+ goto err_pages;
+ }
desc_len = sizeof(union e1000_rx_desc_packet_split);
@@ -1443,16 +1156,21 @@ int e1000e_setup_rx_resources(struct e1000_adapter *adapter)
err = e1000_alloc_ring_dma(adapter, rx_ring);
if (err)
- goto err;
+ goto err_pages;
rx_ring->next_to_clean = 0;
rx_ring->next_to_use = 0;
rx_ring->rx_skb_top = NULL;
return 0;
+
+err_pages:
+ for (i = 0; i < rx_ring->count; i++) {
+ buffer_info = &rx_ring->buffer_info[i];
+ kfree(buffer_info->ps_pages);
+ }
err:
vfree(rx_ring->buffer_info);
- kfree(rx_ring->ps_pages);
ndev_err(adapter->netdev,
"Unable to allocate memory for the transmit descriptor ring\n");
return err;
@@ -1518,15 +1236,17 @@ void e1000e_free_rx_resources(struct e1000_adapter *adapter)
{
struct pci_dev *pdev = adapter->pdev;
struct e1000_ring *rx_ring = adapter->rx_ring;
+ int i;
e1000_clean_rx_ring(adapter);
+ for (i = 0; i < rx_ring->count; i++) {
+ kfree(rx_ring->buffer_info[i].ps_pages);
+ }
+
vfree(rx_ring->buffer_info);
rx_ring->buffer_info = NULL;
- kfree(rx_ring->ps_pages);
- rx_ring->ps_pages = NULL;
-
dma_free_coherent(&pdev->dev, rx_ring->size, rx_ring->desc,
rx_ring->dma);
rx_ring->desc = NULL;
@@ -2032,9 +1752,11 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
ew32(RFCTL, rfctl);
- /* disable the stripping of CRC because it breaks
- * BMC firmware connected over SMBUS */
- rctl |= E1000_RCTL_DTYP_PS /* | E1000_RCTL_SECRC */;
+ /* Enable Packet split descriptors */
+ rctl |= E1000_RCTL_DTYP_PS;
+
+ /* Enable hardware CRC frame stripping */
+ rctl |= E1000_RCTL_SECRC;
psrctl |= adapter->rx_ps_bsize0 >>
E1000_PSRCTL_BSIZE0_SHIFT;
@@ -2077,11 +1799,6 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
sizeof(union e1000_rx_desc_packet_split);
adapter->clean_rx = e1000_clean_rx_irq_ps;
adapter->alloc_rx_buf = e1000_alloc_rx_buffers_ps;
- } else if (adapter->netdev->mtu > ETH_FRAME_LEN + VLAN_HLEN + 4) {
- rdlen = rx_ring->count *
- sizeof(struct e1000_rx_desc);
- adapter->clean_rx = e1000_clean_rx_irq_jumbo;
- adapter->alloc_rx_buf = e1000_alloc_rx_buffers_jumbo;
} else {
rdlen = rx_ring->count *
sizeof(struct e1000_rx_desc);
@@ -2326,8 +2043,11 @@ void e1000e_reset(struct e1000_adapter *adapter)
struct e1000_mac_info *mac = &adapter->hw.mac;
struct e1000_hw *hw = &adapter->hw;
u32 tx_space, min_tx_space, min_rx_space;
+ u32 pba;
u16 hwm;
+ ew32(PBA, adapter->pba);
+
if (mac->max_frame_size > ETH_FRAME_LEN + ETH_FCS_LEN ) {
/* To maintain wire speed transmits, the Tx FIFO should be
* large enough to accommodate two full transmit packets,
@@ -2335,11 +2055,11 @@ void e1000e_reset(struct e1000_adapter *adapter)
* the Rx FIFO should be large enough to accommodate at least
* one full receive packet and is similarly rounded up and
* expressed in KB. */
- adapter->pba = er32(PBA);
+ pba = er32(PBA);
/* upper 16 bits has Tx packet buffer allocation size in KB */
- tx_space = adapter->pba >> 16;
+ tx_space = pba >> 16;
/* lower 16 bits has Rx packet buffer allocation size in KB */
- adapter->pba &= 0xffff;
+ pba &= 0xffff;
/* the tx fifo also stores 16 bytes of information about the tx
* but don't include ethernet FCS because hardware appends it */
min_tx_space = (mac->max_frame_size +
@@ -2355,20 +2075,21 @@ void e1000e_reset(struct e1000_adapter *adapter)
/* If current Tx allocation is less than the min Tx FIFO size,
* and the min Tx FIFO size is less than the current Rx FIFO
* allocation, take space away from current Rx allocation */
- if (tx_space < min_tx_space &&
- ((min_tx_space - tx_space) < adapter->pba)) {
- adapter->pba -= - (min_tx_space - tx_space);
+ if ((tx_space < min_tx_space) &&
+ ((min_tx_space - tx_space) < pba)) {
+ pba -= min_tx_space - tx_space;
/* if short on rx space, rx wins and must trump tx
* adjustment or use Early Receive if available */
- if ((adapter->pba < min_rx_space) &&
+ if ((pba < min_rx_space) &&
(!(adapter->flags & FLAG_HAS_ERT)))
/* ERT enabled in e1000_configure_rx */
- adapter->pba = min_rx_space;
+ pba = min_rx_space;
}
+
+ ew32(PBA, pba);
}
- ew32(PBA, adapter->pba);
/* flow control settings */
/* The high water mark must be low enough to fit one full frame
@@ -3624,9 +3345,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
/* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
* means we reserve 2 more, this pushes us to allocate from the next
* larger slab size.
- * i.e. RXBUFFER_2048 --> size-4096 slab
- * however with the new *_jumbo* routines, jumbo receives will use
- * fragmented skbs */
+ * i.e. RXBUFFER_2048 --> size-4096 slab */
if (max_frame <= 256)
adapter->rx_buffer_len = 256;
diff --git a/drivers/net/e1000e/param.c b/drivers/net/e1000e/param.c
index e4e655efb23c..332789238b9c 100644
--- a/drivers/net/e1000e/param.c
+++ b/drivers/net/e1000e/param.c
@@ -52,10 +52,11 @@ MODULE_PARM_DESC(copybreak,
*/
#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
-#define E1000_PARAM(X, desc) \
- static int __devinitdata X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \
- static int num_##X; \
- module_param_array_named(X, X, int, &num_##X, 0); \
+#define E1000_PARAM(X, desc) \
+ static int __devinitdata X[E1000_MAX_NIC+1] \
+ = E1000_PARAM_INIT; \
+ static unsigned int num_##X; \
+ module_param_array_named(X, X, int, &num_##X, 0); \
MODULE_PARM_DESC(X, desc);
@@ -124,9 +125,9 @@ E1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround");
struct e1000_option {
enum { enable_option, range_option, list_option } type;
- char *name;
- char *err;
- int def;
+ const char *name;
+ const char *err;
+ int def;
union {
struct { /* range_option info */
int min;
@@ -139,8 +140,8 @@ struct e1000_option {
} arg;
};
-static int __devinit e1000_validate_option(int *value,
- struct e1000_option *opt,
+static int __devinit e1000_validate_option(unsigned int *value,
+ const struct e1000_option *opt,
struct e1000_adapter *adapter)
{
if (*value == OPTION_UNSET) {
@@ -213,7 +214,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
}
{ /* Transmit Interrupt Delay */
- struct e1000_option opt = {
+ const struct e1000_option opt = {
.type = range_option,
.name = "Transmit Interrupt Delay",
.err = "using default of "
@@ -232,7 +233,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
}
}
{ /* Transmit Absolute Interrupt Delay */
- struct e1000_option opt = {
+ const struct e1000_option opt = {
.type = range_option,
.name = "Transmit Absolute Interrupt Delay",
.err = "using default of "
@@ -277,7 +278,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
}
}
{ /* Receive Absolute Interrupt Delay */
- struct e1000_option opt = {
+ const struct e1000_option opt = {
.type = range_option,
.name = "Receive Absolute Interrupt Delay",
.err = "using default of "
@@ -296,7 +297,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
}
}
{ /* Interrupt Throttling Rate */
- struct e1000_option opt = {
+ const struct e1000_option opt = {
.type = range_option,
.name = "Interrupt Throttling Rate (ints/sec)",
.err = "using default of "
@@ -344,7 +345,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
}
}
{ /* Smart Power Down */
- struct e1000_option opt = {
+ const struct e1000_option opt = {
.type = enable_option,
.name = "PHY Smart Power Down",
.err = "defaulting to Disabled",
@@ -352,7 +353,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
};
if (num_SmartPowerDownEnable > bd) {
- int spd = SmartPowerDownEnable[bd];
+ unsigned int spd = SmartPowerDownEnable[bd];
e1000_validate_option(&spd, &opt, adapter);
if ((adapter->flags & FLAG_HAS_SMART_POWER_DOWN)
&& spd)
@@ -360,7 +361,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
}
}
{ /* Kumeran Lock Loss Workaround */
- struct e1000_option opt = {
+ const struct e1000_option opt = {
.type = enable_option,
.name = "Kumeran Lock Loss Workaround",
.err = "defaulting to Enabled",
@@ -368,7 +369,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
};
if (num_KumeranLockLoss > bd) {
- int kmrn_lock_loss = KumeranLockLoss[bd];
+ unsigned int kmrn_lock_loss = KumeranLockLoss[bd];
e1000_validate_option(&kmrn_lock_loss, &opt, adapter);
if (hw->mac.type == e1000_ich8lan)
e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw,
diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c
index 9c85e50014b4..70509ed6c11d 100644
--- a/drivers/net/eexpress.c
+++ b/drivers/net/eexpress.c
@@ -651,9 +651,9 @@ static void eexp_timeout(struct net_device *dev)
*/
static int eexp_xmit(struct sk_buff *buf, struct net_device *dev)
{
- struct net_local *lp = netdev_priv(dev);
short length = buf->len;
#ifdef CONFIG_SMP
+ struct net_local *lp = netdev_priv(dev);
unsigned long flags;
#endif
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index ac21526b6de8..f78e5bf7cb33 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -40,7 +40,7 @@
#include <asm/io.h>
#define DRV_NAME "ehea"
-#define DRV_VERSION "EHEA_0078"
+#define DRV_VERSION "EHEA_0080"
/* eHEA capability flags */
#define DLPAR_PORT_ADD_REM 1
@@ -388,7 +388,7 @@ struct ehea_port_res {
#define EHEA_MAX_PORTS 16
struct ehea_adapter {
u64 handle;
- struct ibmebus_dev *ebus_dev;
+ struct of_device *ofdev;
struct ehea_port *port[EHEA_MAX_PORTS];
struct ehea_eq *neq; /* notification event queue */
struct tasklet_struct neq_tasklet;
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index 2ba57e6ace4d..f0319f1e8e05 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -33,6 +33,9 @@
#include <linux/if.h>
#include <linux/list.h>
#include <linux/if_ether.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+
#include <net/ip.h>
#include "ehea.h"
@@ -98,10 +101,10 @@ struct work_struct ehea_rereg_mr_task;
struct semaphore dlpar_mem_lock;
-static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
+static int __devinit ehea_probe_adapter(struct of_device *dev,
const struct of_device_id *id);
-static int __devexit ehea_remove(struct ibmebus_dev *dev);
+static int __devexit ehea_remove(struct of_device *dev);
static struct of_device_id ehea_device_table[] = {
{
@@ -111,9 +114,9 @@ static struct of_device_id ehea_device_table[] = {
{},
};
-static struct ibmebus_driver ehea_driver = {
+static struct of_platform_driver ehea_driver = {
.name = "ehea",
- .id_table = ehea_device_table,
+ .match_table = ehea_device_table,
.probe = ehea_probe_adapter,
.remove = ehea_remove,
};
@@ -1044,7 +1047,7 @@ static int ehea_reg_interrupts(struct net_device *dev)
snprintf(port->int_aff_name, EHEA_IRQ_NAME_SIZE - 1, "%s-aff",
dev->name);
- ret = ibmebus_request_irq(NULL, port->qp_eq->attr.ist1,
+ ret = ibmebus_request_irq(port->qp_eq->attr.ist1,
ehea_qp_aff_irq_handler,
IRQF_DISABLED, port->int_aff_name, port);
if (ret) {
@@ -1062,7 +1065,7 @@ static int ehea_reg_interrupts(struct net_device *dev)
pr = &port->port_res[i];
snprintf(pr->int_send_name, EHEA_IRQ_NAME_SIZE - 1,
"%s-queue%d", dev->name, i);
- ret = ibmebus_request_irq(NULL, pr->eq->attr.ist1,
+ ret = ibmebus_request_irq(pr->eq->attr.ist1,
ehea_recv_irq_handler,
IRQF_DISABLED, pr->int_send_name,
pr);
@@ -1083,11 +1086,11 @@ out:
out_free_req:
while (--i >= 0) {
u32 ist = port->port_res[i].eq->attr.ist1;
- ibmebus_free_irq(NULL, ist, &port->port_res[i]);
+ ibmebus_free_irq(ist, &port->port_res[i]);
}
out_free_qpeq:
- ibmebus_free_irq(NULL, port->qp_eq->attr.ist1, port);
+ ibmebus_free_irq(port->qp_eq->attr.ist1, port);
i = port->num_def_qps;
goto out;
@@ -1104,14 +1107,14 @@ static void ehea_free_interrupts(struct net_device *dev)
for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
pr = &port->port_res[i];
- ibmebus_free_irq(NULL, pr->eq->attr.ist1, pr);
+ ibmebus_free_irq(pr->eq->attr.ist1, pr);
if (netif_msg_intr(port))
ehea_info("free send irq for res %d with handle 0x%X",
i, pr->eq->attr.ist1);
}
/* associated events */
- ibmebus_free_irq(NULL, port->qp_eq->attr.ist1, port);
+ ibmebus_free_irq(port->qp_eq->attr.ist1, port);
if (netif_msg_intr(port))
ehea_info("associated event interrupt for handle 0x%X freed",
port->qp_eq->attr.ist1);
@@ -2329,7 +2332,7 @@ static void port_napi_disable(struct ehea_port *port)
{
int i;
- for (i = 0; i < port->num_def_qps; i++)
+ for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++)
napi_disable(&port->port_res[i].napi);
}
@@ -2337,7 +2340,7 @@ static void port_napi_enable(struct ehea_port *port)
{
int i;
- for (i = 0; i < port->num_def_qps; i++)
+ for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++)
napi_enable(&port->port_res[i].napi);
}
@@ -2373,8 +2376,6 @@ static int ehea_down(struct net_device *dev)
ehea_drop_multicast_list(dev);
ehea_free_interrupts(dev);
- port_napi_disable(port);
-
port->state = EHEA_PORT_DOWN;
ret = ehea_clean_all_portres(port);
@@ -2396,6 +2397,7 @@ static int ehea_stop(struct net_device *dev)
flush_scheduled_work();
down(&port->port_lock);
netif_stop_queue(dev);
+ port_napi_disable(port);
ret = ehea_down(dev);
up(&port->port_lock);
return ret;
@@ -2832,7 +2834,7 @@ static struct device *ehea_register_port(struct ehea_port *port,
int ret;
port->ofdev.node = of_node_get(dn);
- port->ofdev.dev.parent = &port->adapter->ebus_dev->ofdev.dev;
+ port->ofdev.dev.parent = &port->adapter->ofdev->dev;
port->ofdev.dev.bus = &ibmebus_bus_type;
sprintf(port->ofdev.dev.bus_id, "port%d", port_name_cnt++);
@@ -3011,7 +3013,7 @@ static int ehea_setup_ports(struct ehea_adapter *adapter)
const u32 *dn_log_port_id;
int i = 0;
- lhea_dn = adapter->ebus_dev->ofdev.node;
+ lhea_dn = adapter->ofdev->node;
while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) {
dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no",
@@ -3051,7 +3053,7 @@ static struct device_node *ehea_get_eth_dn(struct ehea_adapter *adapter,
struct device_node *eth_dn = NULL;
const u32 *dn_log_port_id;
- lhea_dn = adapter->ebus_dev->ofdev.node;
+ lhea_dn = adapter->ofdev->node;
while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) {
dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no",
@@ -3157,31 +3159,31 @@ static ssize_t ehea_remove_port(struct device *dev,
static DEVICE_ATTR(probe_port, S_IWUSR, NULL, ehea_probe_port);
static DEVICE_ATTR(remove_port, S_IWUSR, NULL, ehea_remove_port);
-int ehea_create_device_sysfs(struct ibmebus_dev *dev)
+int ehea_create_device_sysfs(struct of_device *dev)
{
- int ret = device_create_file(&dev->ofdev.dev, &dev_attr_probe_port);
+ int ret = device_create_file(&dev->dev, &dev_attr_probe_port);
if (ret)
goto out;
- ret = device_create_file(&dev->ofdev.dev, &dev_attr_remove_port);
+ ret = device_create_file(&dev->dev, &dev_attr_remove_port);
out:
return ret;
}
-void ehea_remove_device_sysfs(struct ibmebus_dev *dev)
+void ehea_remove_device_sysfs(struct of_device *dev)
{
- device_remove_file(&dev->ofdev.dev, &dev_attr_probe_port);
- device_remove_file(&dev->ofdev.dev, &dev_attr_remove_port);
+ device_remove_file(&dev->dev, &dev_attr_probe_port);
+ device_remove_file(&dev->dev, &dev_attr_remove_port);
}
-static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
+static int __devinit ehea_probe_adapter(struct of_device *dev,
const struct of_device_id *id)
{
struct ehea_adapter *adapter;
const u64 *adapter_handle;
int ret;
- if (!dev || !dev->ofdev.node) {
+ if (!dev || !dev->node) {
ehea_error("Invalid ibmebus device probed");
return -EINVAL;
}
@@ -3189,36 +3191,36 @@ static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
if (!adapter) {
ret = -ENOMEM;
- dev_err(&dev->ofdev.dev, "no mem for ehea_adapter\n");
+ dev_err(&dev->dev, "no mem for ehea_adapter\n");
goto out;
}
list_add(&adapter->list, &adapter_list);
- adapter->ebus_dev = dev;
+ adapter->ofdev = dev;
- adapter_handle = of_get_property(dev->ofdev.node, "ibm,hea-handle",
+ adapter_handle = of_get_property(dev->node, "ibm,hea-handle",
NULL);
if (adapter_handle)
adapter->handle = *adapter_handle;
if (!adapter->handle) {
- dev_err(&dev->ofdev.dev, "failed getting handle for adapter"
- " '%s'\n", dev->ofdev.node->full_name);
+ dev_err(&dev->dev, "failed getting handle for adapter"
+ " '%s'\n", dev->node->full_name);
ret = -ENODEV;
goto out_free_ad;
}
adapter->pd = EHEA_PD_ID;
- dev->ofdev.dev.driver_data = adapter;
+ dev->dev.driver_data = adapter;
/* initialize adapter and ports */
/* get adapter properties */
ret = ehea_sense_adapter_attr(adapter);
if (ret) {
- dev_err(&dev->ofdev.dev, "sense_adapter_attr failed: %d", ret);
+ dev_err(&dev->dev, "sense_adapter_attr failed: %d\n", ret);
goto out_free_ad;
}
@@ -3226,18 +3228,18 @@ static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
EHEA_NEQ, EHEA_MAX_ENTRIES_EQ, 1);
if (!adapter->neq) {
ret = -EIO;
- dev_err(&dev->ofdev.dev, "NEQ creation failed");
+ dev_err(&dev->dev, "NEQ creation failed\n");
goto out_free_ad;
}
tasklet_init(&adapter->neq_tasklet, ehea_neq_tasklet,
(unsigned long)adapter);
- ret = ibmebus_request_irq(NULL, adapter->neq->attr.ist1,
+ ret = ibmebus_request_irq(adapter->neq->attr.ist1,
ehea_interrupt_neq, IRQF_DISABLED,
"ehea_neq", adapter);
if (ret) {
- dev_err(&dev->ofdev.dev, "requesting NEQ IRQ failed");
+ dev_err(&dev->dev, "requesting NEQ IRQ failed\n");
goto out_kill_eq;
}
@@ -3247,7 +3249,7 @@ static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
ret = ehea_setup_ports(adapter);
if (ret) {
- dev_err(&dev->ofdev.dev, "setup_ports failed");
+ dev_err(&dev->dev, "setup_ports failed\n");
goto out_rem_dev_sysfs;
}
@@ -3258,7 +3260,7 @@ out_rem_dev_sysfs:
ehea_remove_device_sysfs(dev);
out_free_irq:
- ibmebus_free_irq(NULL, adapter->neq->attr.ist1, adapter);
+ ibmebus_free_irq(adapter->neq->attr.ist1, adapter);
out_kill_eq:
ehea_destroy_eq(adapter->neq);
@@ -3269,9 +3271,9 @@ out:
return ret;
}
-static int __devexit ehea_remove(struct ibmebus_dev *dev)
+static int __devexit ehea_remove(struct of_device *dev)
{
- struct ehea_adapter *adapter = dev->ofdev.dev.driver_data;
+ struct ehea_adapter *adapter = dev->dev.driver_data;
int i;
for (i = 0; i < EHEA_MAX_PORTS; i++)
@@ -3284,7 +3286,7 @@ static int __devexit ehea_remove(struct ibmebus_dev *dev)
flush_scheduled_work();
- ibmebus_free_irq(NULL, adapter->neq->attr.ist1, adapter);
+ ibmebus_free_irq(adapter->neq->attr.ist1, adapter);
tasklet_kill(&adapter->neq_tasklet);
ehea_destroy_eq(adapter->neq);
@@ -3296,6 +3298,20 @@ static int __devexit ehea_remove(struct ibmebus_dev *dev)
return 0;
}
+static int ehea_reboot_notifier(struct notifier_block *nb,
+ unsigned long action, void *unused)
+{
+ if (action == SYS_RESTART) {
+ ehea_info("Reboot: freeing all eHEA resources");
+ ibmebus_unregister_driver(&ehea_driver);
+ }
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block ehea_reboot_nb = {
+ .notifier_call = ehea_reboot_notifier,
+};
+
static int check_module_parm(void)
{
int ret = 0;
@@ -3352,6 +3368,8 @@ int __init ehea_module_init(void)
if (ret)
goto out;
+ register_reboot_notifier(&ehea_reboot_nb);
+
ret = ibmebus_register_driver(&ehea_driver);
if (ret) {
ehea_error("failed registering eHEA device driver on ebus");
@@ -3363,6 +3381,7 @@ int __init ehea_module_init(void)
if (ret) {
ehea_error("failed to register capabilities attribute, ret=%d",
ret);
+ unregister_reboot_notifier(&ehea_reboot_nb);
ibmebus_unregister_driver(&ehea_driver);
goto out;
}
@@ -3376,6 +3395,7 @@ static void __exit ehea_module_exit(void)
flush_scheduled_work();
driver_remove_file(&ehea_driver.driver, &driver_attr_capabilities);
ibmebus_unregister_driver(&ehea_driver);
+ unregister_reboot_notifier(&ehea_reboot_nb);
ehea_destroy_busmap();
}
diff --git a/drivers/net/eth16i.c b/drivers/net/eth16i.c
index 243fc6b354b5..e3dd8b136908 100644
--- a/drivers/net/eth16i.c
+++ b/drivers/net/eth16i.c
@@ -170,7 +170,6 @@ static char *version =
/* Few macros */
-#define BIT(a) ( (1 << (a)) )
#define BITSET(ioaddr, bnum) ((outb(((inb(ioaddr)) | (bnum)), ioaddr)))
#define BITCLR(ioaddr, bnum) ((outb(((inb(ioaddr)) & (~(bnum))), ioaddr)))
diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c
index 43f7647ff246..7bb9c728a1d3 100644
--- a/drivers/net/fealnx.c
+++ b/drivers/net/fealnx.c
@@ -111,7 +111,6 @@ MODULE_AUTHOR("Myson or whoever");
MODULE_DESCRIPTION("Myson MTD-8xx 100/10M Ethernet PCI Adapter Driver");
MODULE_LICENSE("GPL");
module_param(max_interrupt_work, int, 0);
-//MODULE_PARM(min_pci_latency, "i");
module_param(debug, int, 0);
module_param(rx_copybreak, int, 0);
module_param(multicast_filter_limit, int, 0);
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 2b5782056dda..0fbf1bbbaee9 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -751,13 +751,11 @@ mii_queue(struct net_device *dev, int regval, void (*func)(uint, struct net_devi
if (mii_head) {
mii_tail->mii_next = mip;
mii_tail = mip;
- }
- else {
+ } else {
mii_head = mii_tail = mip;
fep->hwp->fec_mii_data = regval;
}
- }
- else {
+ } else {
retval = 1;
}
@@ -768,14 +766,11 @@ mii_queue(struct net_device *dev, int regval, void (*func)(uint, struct net_devi
static void mii_do_cmd(struct net_device *dev, const phy_cmd_t *c)
{
- int k;
-
if(!c)
return;
- for(k = 0; (c+k)->mii_data != mk_mii_end; k++) {
- mii_queue(dev, (c+k)->mii_data, (c+k)->funct);
- }
+ for (; c->mii_data != mk_mii_end; c++)
+ mii_queue(dev, c->mii_data, c->funct);
}
static void mii_parse_sr(uint mii_reg, struct net_device *dev)
@@ -792,7 +787,6 @@ static void mii_parse_sr(uint mii_reg, struct net_device *dev)
status |= PHY_STAT_FAULT;
if (mii_reg & 0x0020)
status |= PHY_STAT_ANC;
-
*s = status;
}
@@ -1239,7 +1233,6 @@ mii_link_interrupt(int irq, void * dev_id);
#endif
#if defined(CONFIG_M5272)
-
/*
* Code specific to Coldfire 5272 setup.
*/
@@ -2020,8 +2013,7 @@ static void mii_relink(struct work_struct *work)
& (PHY_STAT_100FDX | PHY_STAT_10FDX))
duplex = 1;
fec_restart(dev, duplex);
- }
- else
+ } else
fec_stop(dev);
#if 0
@@ -2119,8 +2111,7 @@ mii_discover_phy(uint mii_reg, struct net_device *dev)
fep->phy_id = phytype << 16;
mii_queue(dev, mk_mii_read(MII_REG_PHYIR2),
mii_discover_phy3);
- }
- else {
+ } else {
fep->phy_addr++;
mii_queue(dev, mk_mii_read(MII_REG_PHYIR1),
mii_discover_phy);
@@ -2574,8 +2565,7 @@ fec_restart(struct net_device *dev, int duplex)
if (duplex) {
fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x04;/* MII enable */
fecp->fec_x_cntrl = 0x04; /* FD enable */
- }
- else {
+ } else {
/* MII enable|No Rcv on Xmit */
fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x06;
fecp->fec_x_cntrl = 0x00;
diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c
new file mode 100644
index 000000000000..a8a0ee220da6
--- /dev/null
+++ b/drivers/net/fec_mpc52xx.c
@@ -0,0 +1,1112 @@
+/*
+ * Driver for the MPC5200 Fast Ethernet Controller
+ *
+ * Originally written by Dale Farnsworth <dfarnsworth@mvista.com> and
+ * now maintained by Sylvain Munaut <tnt@246tNt.com>
+ *
+ * Copyright (C) 2007 Domen Puncer, Telargo, Inc.
+ * Copyright (C) 2007 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003-2004 MontaVista, Software, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ */
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/crc32.h>
+#include <linux/hardirq.h>
+#include <linux/delay.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/skbuff.h>
+
+#include <asm/io.h>
+#include <asm/delay.h>
+#include <asm/mpc52xx.h>
+
+#include <sysdev/bestcomm/bestcomm.h>
+#include <sysdev/bestcomm/fec.h>
+
+#include "fec_mpc52xx.h"
+
+#define DRIVER_NAME "mpc52xx-fec"
+
+static irqreturn_t mpc52xx_fec_interrupt(int, void *);
+static irqreturn_t mpc52xx_fec_rx_interrupt(int, void *);
+static irqreturn_t mpc52xx_fec_tx_interrupt(int, void *);
+static void mpc52xx_fec_stop(struct net_device *dev);
+static void mpc52xx_fec_start(struct net_device *dev);
+static void mpc52xx_fec_reset(struct net_device *dev);
+
+static u8 mpc52xx_fec_mac_addr[6];
+module_param_array_named(mac, mpc52xx_fec_mac_addr, byte, NULL, 0);
+MODULE_PARM_DESC(mac, "six hex digits, ie. 0x1,0x2,0xc0,0x01,0xba,0xbe");
+
+#define MPC52xx_MESSAGES_DEFAULT ( NETIF_MSG_DRV | NETIF_MSG_PROBE | \
+ NETIF_MSG_LINK | NETIF_MSG_IFDOWN | NETIF_MSG_IFDOWN )
+static int debug = -1; /* the above default */
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "debugging messages level");
+
+static void mpc52xx_fec_tx_timeout(struct net_device *dev)
+{
+ dev_warn(&dev->dev, "transmit timed out\n");
+
+ mpc52xx_fec_reset(dev);
+
+ dev->stats.tx_errors++;
+
+ netif_wake_queue(dev);
+}
+
+static void mpc52xx_fec_set_paddr(struct net_device *dev, u8 *mac)
+{
+ struct mpc52xx_fec_priv *priv = netdev_priv(dev);
+ struct mpc52xx_fec __iomem *fec = priv->fec;
+
+ out_be32(&fec->paddr1, *(u32 *)(&mac[0]));
+ out_be32(&fec->paddr2, (*(u16 *)(&mac[4]) << 16) | FEC_PADDR2_TYPE);
+}
+
+static void mpc52xx_fec_get_paddr(struct net_device *dev, u8 *mac)
+{
+ struct mpc52xx_fec_priv *priv = netdev_priv(dev);
+ struct mpc52xx_fec __iomem *fec = priv->fec;
+
+ *(u32 *)(&mac[0]) = in_be32(&fec->paddr1);
+ *(u16 *)(&mac[4]) = in_be32(&fec->paddr2) >> 16;
+}
+
+static int mpc52xx_fec_set_mac_address(struct net_device *dev, void *addr)
+{
+ struct sockaddr *sock = addr;
+
+ memcpy(dev->dev_addr, sock->sa_data, dev->addr_len);
+
+ mpc52xx_fec_set_paddr(dev, sock->sa_data);
+ return 0;
+}
+
+static void mpc52xx_fec_free_rx_buffers(struct net_device *dev, struct bcom_task *s)
+{
+ while (!bcom_queue_empty(s)) {
+ struct bcom_fec_bd *bd;
+ struct sk_buff *skb;
+
+ skb = bcom_retrieve_buffer(s, NULL, (struct bcom_bd **)&bd);
+ dma_unmap_single(&dev->dev, bd->skb_pa, skb->len, DMA_FROM_DEVICE);
+ kfree_skb(skb);
+ }
+}
+
+static int mpc52xx_fec_alloc_rx_buffers(struct net_device *dev, struct bcom_task *rxtsk)
+{
+ while (!bcom_queue_full(rxtsk)) {
+ struct sk_buff *skb;
+ struct bcom_fec_bd *bd;
+
+ skb = dev_alloc_skb(FEC_RX_BUFFER_SIZE);
+ if (skb == NULL)
+ return -EAGAIN;
+
+ /* zero out the initial receive buffers to aid debugging */
+ memset(skb->data, 0, FEC_RX_BUFFER_SIZE);
+
+ bd = (struct bcom_fec_bd *)bcom_prepare_next_buffer(rxtsk);
+
+ bd->status = FEC_RX_BUFFER_SIZE;
+ bd->skb_pa = dma_map_single(&dev->dev, skb->data,
+ FEC_RX_BUFFER_SIZE, DMA_FROM_DEVICE);
+
+ bcom_submit_next_buffer(rxtsk, skb);
+ }
+
+ return 0;
+}
+
+/* based on generic_adjust_link from fs_enet-main.c */
+static void mpc52xx_fec_adjust_link(struct net_device *dev)
+{
+ struct mpc52xx_fec_priv *priv = netdev_priv(dev);
+ struct phy_device *phydev = priv->phydev;
+ int new_state = 0;
+
+ if (phydev->link != PHY_DOWN) {
+ if (phydev->duplex != priv->duplex) {
+ struct mpc52xx_fec __iomem *fec = priv->fec;
+ u32 rcntrl;
+ u32 tcntrl;
+
+ new_state = 1;
+ priv->duplex = phydev->duplex;
+
+ rcntrl = in_be32(&fec->r_cntrl);
+ tcntrl = in_be32(&fec->x_cntrl);
+
+ rcntrl &= ~FEC_RCNTRL_DRT;
+ tcntrl &= ~FEC_TCNTRL_FDEN;
+ if (phydev->duplex == DUPLEX_FULL)
+ tcntrl |= FEC_TCNTRL_FDEN; /* FD enable */
+ else
+ rcntrl |= FEC_RCNTRL_DRT; /* disable Rx on Tx (HD) */
+
+ out_be32(&fec->r_cntrl, rcntrl);
+ out_be32(&fec->x_cntrl, tcntrl);
+ }
+
+ if (phydev->speed != priv->speed) {
+ new_state = 1;
+ priv->speed = phydev->speed;
+ }
+
+ if (priv->link == PHY_DOWN) {
+ new_state = 1;
+ priv->link = phydev->link;
+ netif_schedule(dev);
+ netif_carrier_on(dev);
+ netif_start_queue(dev);
+ }
+
+ } else if (priv->link) {
+ new_state = 1;
+ priv->link = PHY_DOWN;
+ priv->speed = 0;
+ priv->duplex = -1;
+ netif_stop_queue(dev);
+ netif_carrier_off(dev);
+ }
+
+ if (new_state && netif_msg_link(priv))
+ phy_print_status(phydev);
+}
+
+static int mpc52xx_fec_init_phy(struct net_device *dev)
+{
+ struct mpc52xx_fec_priv *priv = netdev_priv(dev);
+ struct phy_device *phydev;
+ char phy_id[BUS_ID_SIZE];
+
+ snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT,
+ (unsigned int)dev->base_addr, priv->phy_addr);
+
+ priv->link = PHY_DOWN;
+ priv->speed = 0;
+ priv->duplex = -1;
+
+ phydev = phy_connect(dev, phy_id, &mpc52xx_fec_adjust_link, 0, PHY_INTERFACE_MODE_MII);
+ if (IS_ERR(phydev)) {
+ dev_err(&dev->dev, "phy_connect failed\n");
+ return PTR_ERR(phydev);
+ }
+ dev_info(&dev->dev, "attached phy %i to driver %s\n",
+ phydev->addr, phydev->drv->name);
+
+ priv->phydev = phydev;
+
+ return 0;
+}
+
+static int mpc52xx_fec_phy_start(struct net_device *dev)
+{
+ struct mpc52xx_fec_priv *priv = netdev_priv(dev);
+ int err;
+
+ if (!priv->has_phy)
+ return 0;
+
+ err = mpc52xx_fec_init_phy(dev);
+ if (err) {
+ dev_err(&dev->dev, "mpc52xx_fec_init_phy failed\n");
+ return err;
+ }
+
+ /* reset phy - this also wakes it from PDOWN */
+ phy_write(priv->phydev, MII_BMCR, BMCR_RESET);
+ phy_start(priv->phydev);
+
+ return 0;
+}
+
+static void mpc52xx_fec_phy_stop(struct net_device *dev)
+{
+ struct mpc52xx_fec_priv *priv = netdev_priv(dev);
+
+ if (!priv->has_phy)
+ return;
+
+ phy_disconnect(priv->phydev);
+ /* power down phy */
+ phy_stop(priv->phydev);
+ phy_write(priv->phydev, MII_BMCR, BMCR_PDOWN);
+}
+
+static int mpc52xx_fec_phy_mii_ioctl(struct mpc52xx_fec_priv *priv,
+ struct mii_ioctl_data *mii_data, int cmd)
+{
+ if (!priv->has_phy)
+ return -ENOTSUPP;
+
+ return phy_mii_ioctl(priv->phydev, mii_data, cmd);
+}
+
+static void mpc52xx_fec_phy_hw_init(struct mpc52xx_fec_priv *priv)
+{
+ struct mpc52xx_fec __iomem *fec = priv->fec;
+
+ if (!priv->has_phy)
+ return;
+
+ out_be32(&fec->mii_speed, priv->phy_speed);
+}
+
+static int mpc52xx_fec_open(struct net_device *dev)
+{
+ struct mpc52xx_fec_priv *priv = netdev_priv(dev);
+ int err = -EBUSY;
+
+ if (request_irq(dev->irq, &mpc52xx_fec_interrupt, IRQF_SHARED,
+ DRIVER_NAME "_ctrl", dev)) {
+ dev_err(&dev->dev, "ctrl interrupt request failed\n");
+ goto out;
+ }
+ if (request_irq(priv->r_irq, &mpc52xx_fec_rx_interrupt, 0,
+ DRIVER_NAME "_rx", dev)) {
+ dev_err(&dev->dev, "rx interrupt request failed\n");
+ goto free_ctrl_irq;
+ }
+ if (request_irq(priv->t_irq, &mpc52xx_fec_tx_interrupt, 0,
+ DRIVER_NAME "_tx", dev)) {
+ dev_err(&dev->dev, "tx interrupt request failed\n");
+ goto free_2irqs;
+ }
+
+ bcom_fec_rx_reset(priv->rx_dmatsk);
+ bcom_fec_tx_reset(priv->tx_dmatsk);
+
+ err = mpc52xx_fec_alloc_rx_buffers(dev, priv->rx_dmatsk);
+ if (err) {
+ dev_err(&dev->dev, "mpc52xx_fec_alloc_rx_buffers failed\n");
+ goto free_irqs;
+ }
+
+ err = mpc52xx_fec_phy_start(dev);
+ if (err)
+ goto free_skbs;
+
+ bcom_enable(priv->rx_dmatsk);
+ bcom_enable(priv->tx_dmatsk);
+
+ mpc52xx_fec_start(dev);
+
+ netif_start_queue(dev);
+
+ return 0;
+
+ free_skbs:
+ mpc52xx_fec_free_rx_buffers(dev, priv->rx_dmatsk);
+
+ free_irqs:
+ free_irq(priv->t_irq, dev);
+ free_2irqs:
+ free_irq(priv->r_irq, dev);
+ free_ctrl_irq:
+ free_irq(dev->irq, dev);
+ out:
+
+ return err;
+}
+
+static int mpc52xx_fec_close(struct net_device *dev)
+{
+ struct mpc52xx_fec_priv *priv = netdev_priv(dev);
+
+ netif_stop_queue(dev);
+
+ mpc52xx_fec_stop(dev);
+
+ mpc52xx_fec_free_rx_buffers(dev, priv->rx_dmatsk);
+
+ free_irq(dev->irq, dev);
+ free_irq(priv->r_irq, dev);
+ free_irq(priv->t_irq, dev);
+
+ mpc52xx_fec_phy_stop(dev);
+
+ return 0;
+}
+
+/* This will only be invoked if your driver is _not_ in XOFF state.
+ * What this means is that you need not check it, and that this
+ * invariant will hold if you make sure that the netif_*_queue()
+ * calls are done at the proper times.
+ */
+static int mpc52xx_fec_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct mpc52xx_fec_priv *priv = netdev_priv(dev);
+ struct bcom_fec_bd *bd;
+
+ if (bcom_queue_full(priv->tx_dmatsk)) {
+ if (net_ratelimit())
+ dev_err(&dev->dev, "transmit queue overrun\n");
+ return 1;
+ }
+
+ spin_lock_irq(&priv->lock);
+ dev->trans_start = jiffies;
+
+ bd = (struct bcom_fec_bd *)
+ bcom_prepare_next_buffer(priv->tx_dmatsk);
+
+ bd->status = skb->len | BCOM_FEC_TX_BD_TFD | BCOM_FEC_TX_BD_TC;
+ bd->skb_pa = dma_map_single(&dev->dev, skb->data, skb->len, DMA_TO_DEVICE);
+
+ bcom_submit_next_buffer(priv->tx_dmatsk, skb);
+
+ if (bcom_queue_full(priv->tx_dmatsk)) {
+ netif_stop_queue(dev);
+ }
+
+ spin_unlock_irq(&priv->lock);
+
+ return 0;
+}
+
+/* This handles BestComm transmit task interrupts
+ */
+static irqreturn_t mpc52xx_fec_tx_interrupt(int irq, void *dev_id)
+{
+ struct net_device *dev = dev_id;
+ struct mpc52xx_fec_priv *priv = netdev_priv(dev);
+
+ spin_lock(&priv->lock);
+
+ while (bcom_buffer_done(priv->tx_dmatsk)) {
+ struct sk_buff *skb;
+ struct bcom_fec_bd *bd;
+ skb = bcom_retrieve_buffer(priv->tx_dmatsk, NULL,
+ (struct bcom_bd **)&bd);
+ dma_unmap_single(&dev->dev, bd->skb_pa, skb->len, DMA_TO_DEVICE);
+
+ dev_kfree_skb_irq(skb);
+ }
+
+ netif_wake_queue(dev);
+
+ spin_unlock(&priv->lock);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t mpc52xx_fec_rx_interrupt(int irq, void *dev_id)
+{
+ struct net_device *dev = dev_id;
+ struct mpc52xx_fec_priv *priv = netdev_priv(dev);
+
+ while (bcom_buffer_done(priv->rx_dmatsk)) {
+ struct sk_buff *skb;
+ struct sk_buff *rskb;
+ struct bcom_fec_bd *bd;
+ u32 status;
+
+ rskb = bcom_retrieve_buffer(priv->rx_dmatsk, &status,
+ (struct bcom_bd **)&bd);
+ dma_unmap_single(&dev->dev, bd->skb_pa, skb->len, DMA_FROM_DEVICE);
+
+ /* Test for errors in received frame */
+ if (status & BCOM_FEC_RX_BD_ERRORS) {
+ /* Drop packet and reuse the buffer */
+ bd = (struct bcom_fec_bd *)
+ bcom_prepare_next_buffer(priv->rx_dmatsk);
+
+ bd->status = FEC_RX_BUFFER_SIZE;
+ bd->skb_pa = dma_map_single(&dev->dev, rskb->data,
+ FEC_RX_BUFFER_SIZE, DMA_FROM_DEVICE);
+
+ bcom_submit_next_buffer(priv->rx_dmatsk, rskb);
+
+ dev->stats.rx_dropped++;
+
+ continue;
+ }
+
+ /* skbs are allocated on open, so now we allocate a new one,
+ * and remove the old (with the packet) */
+ skb = dev_alloc_skb(FEC_RX_BUFFER_SIZE);
+ if (skb) {
+ /* Process the received skb */
+ int length = status & BCOM_FEC_RX_BD_LEN_MASK;
+
+ skb_put(rskb, length - 4); /* length without CRC32 */
+
+ rskb->dev = dev;
+ rskb->protocol = eth_type_trans(rskb, dev);
+
+ netif_rx(rskb);
+ dev->last_rx = jiffies;
+ } else {
+ /* Can't get a new one : reuse the same & drop pkt */
+ dev_notice(&dev->dev, "Memory squeeze, dropping packet.\n");
+ dev->stats.rx_dropped++;
+
+ skb = rskb;
+ }
+
+ bd = (struct bcom_fec_bd *)
+ bcom_prepare_next_buffer(priv->rx_dmatsk);
+
+ bd->status = FEC_RX_BUFFER_SIZE;
+ bd->skb_pa = dma_map_single(&dev->dev, rskb->data,
+ FEC_RX_BUFFER_SIZE, DMA_FROM_DEVICE);
+
+ bcom_submit_next_buffer(priv->rx_dmatsk, skb);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t mpc52xx_fec_interrupt(int irq, void *dev_id)
+{
+ struct net_device *dev = dev_id;
+ struct mpc52xx_fec_priv *priv = netdev_priv(dev);
+ struct mpc52xx_fec __iomem *fec = priv->fec;
+ u32 ievent;
+
+ ievent = in_be32(&fec->ievent);
+
+ ievent &= ~FEC_IEVENT_MII; /* mii is handled separately */
+ if (!ievent)
+ return IRQ_NONE;
+
+ out_be32(&fec->ievent, ievent); /* clear pending events */
+
+ if (ievent & ~(FEC_IEVENT_RFIFO_ERROR | FEC_IEVENT_XFIFO_ERROR)) {
+ if (ievent & ~FEC_IEVENT_TFINT)
+ dev_dbg(&dev->dev, "ievent: %08x\n", ievent);
+ return IRQ_HANDLED;
+ }
+
+ if (net_ratelimit() && (ievent & FEC_IEVENT_RFIFO_ERROR))
+ dev_warn(&dev->dev, "FEC_IEVENT_RFIFO_ERROR\n");
+ if (net_ratelimit() && (ievent & FEC_IEVENT_XFIFO_ERROR))
+ dev_warn(&dev->dev, "FEC_IEVENT_XFIFO_ERROR\n");
+
+ mpc52xx_fec_reset(dev);
+
+ netif_wake_queue(dev);
+ return IRQ_HANDLED;
+}
+
+/*
+ * Get the current statistics.
+ * This may be called with the card open or closed.
+ */
+static struct net_device_stats *mpc52xx_fec_get_stats(struct net_device *dev)
+{
+ struct mpc52xx_fec_priv *priv = netdev_priv(dev);
+ struct net_device_stats *stats = &dev->stats;
+ struct mpc52xx_fec __iomem *fec = priv->fec;
+
+ stats->rx_bytes = in_be32(&fec->rmon_r_octets);
+ stats->rx_packets = in_be32(&fec->rmon_r_packets);
+ stats->rx_errors = in_be32(&fec->rmon_r_crc_align) +
+ in_be32(&fec->rmon_r_undersize) +
+ in_be32(&fec->rmon_r_oversize) +
+ in_be32(&fec->rmon_r_frag) +
+ in_be32(&fec->rmon_r_jab);
+
+ stats->tx_bytes = in_be32(&fec->rmon_t_octets);
+ stats->tx_packets = in_be32(&fec->rmon_t_packets);
+ stats->tx_errors = in_be32(&fec->rmon_t_crc_align) +
+ in_be32(&fec->rmon_t_undersize) +
+ in_be32(&fec->rmon_t_oversize) +
+ in_be32(&fec->rmon_t_frag) +
+ in_be32(&fec->rmon_t_jab);
+
+ stats->multicast = in_be32(&fec->rmon_r_mc_pkt);
+ stats->collisions = in_be32(&fec->rmon_t_col);
+
+ /* detailed rx_errors: */
+ stats->rx_length_errors = in_be32(&fec->rmon_r_undersize)
+ + in_be32(&fec->rmon_r_oversize)
+ + in_be32(&fec->rmon_r_frag)
+ + in_be32(&fec->rmon_r_jab);
+ stats->rx_over_errors = in_be32(&fec->r_macerr);
+ stats->rx_crc_errors = in_be32(&fec->ieee_r_crc);
+ stats->rx_frame_errors = in_be32(&fec->ieee_r_align);
+ stats->rx_fifo_errors = in_be32(&fec->rmon_r_drop);
+ stats->rx_missed_errors = in_be32(&fec->rmon_r_drop);
+
+ /* detailed tx_errors: */
+ stats->tx_aborted_errors = 0;
+ stats->tx_carrier_errors = in_be32(&fec->ieee_t_cserr);
+ stats->tx_fifo_errors = in_be32(&fec->rmon_t_drop);
+ stats->tx_heartbeat_errors = in_be32(&fec->ieee_t_sqe);
+ stats->tx_window_errors = in_be32(&fec->ieee_t_lcol);
+
+ return stats;
+}
+
+/*
+ * Read MIB counters in order to reset them,
+ * then zero all the stats fields in memory
+ */
+static void mpc52xx_fec_reset_stats(struct net_device *dev)
+{
+ struct mpc52xx_fec_priv *priv = netdev_priv(dev);
+ struct mpc52xx_fec __iomem *fec = priv->fec;
+
+ out_be32(&fec->mib_control, FEC_MIB_DISABLE);
+ memset_io(&fec->rmon_t_drop, 0, (__force u32)&fec->reserved10 -
+ (__force u32)&fec->rmon_t_drop);
+ out_be32(&fec->mib_control, 0);
+
+ memset(&dev->stats, 0, sizeof(dev->stats));
+}
+
+/*
+ * Set or clear the multicast filter for this adaptor.
+ */
+static void mpc52xx_fec_set_multicast_list(struct net_device *dev)
+{
+ struct mpc52xx_fec_priv *priv = netdev_priv(dev);
+ struct mpc52xx_fec __iomem *fec = priv->fec;
+ u32 rx_control;
+
+ rx_control = in_be32(&fec->r_cntrl);
+
+ if (dev->flags & IFF_PROMISC) {
+ rx_control |= FEC_RCNTRL_PROM;
+ out_be32(&fec->r_cntrl, rx_control);
+ } else {
+ rx_control &= ~FEC_RCNTRL_PROM;
+ out_be32(&fec->r_cntrl, rx_control);
+
+ if (dev->flags & IFF_ALLMULTI) {
+ out_be32(&fec->gaddr1, 0xffffffff);
+ out_be32(&fec->gaddr2, 0xffffffff);
+ } else {
+ u32 crc;
+ int i;
+ struct dev_mc_list *dmi;
+ u32 gaddr1 = 0x00000000;
+ u32 gaddr2 = 0x00000000;
+
+ dmi = dev->mc_list;
+ for (i=0; i<dev->mc_count; i++) {
+ crc = ether_crc_le(6, dmi->dmi_addr) >> 26;
+ if (crc >= 32)
+ gaddr1 |= 1 << (crc-32);
+ else
+ gaddr2 |= 1 << crc;
+ dmi = dmi->next;
+ }
+ out_be32(&fec->gaddr1, gaddr1);
+ out_be32(&fec->gaddr2, gaddr2);
+ }
+ }
+}
+
+/**
+ * mpc52xx_fec_hw_init
+ * @dev: network device
+ *
+ * Setup various hardware setting, only needed once on start
+ */
+static void mpc52xx_fec_hw_init(struct net_device *dev)
+{
+ struct mpc52xx_fec_priv *priv = netdev_priv(dev);
+ struct mpc52xx_fec __iomem *fec = priv->fec;
+ int i;
+
+ /* Whack a reset. We should wait for this. */
+ out_be32(&fec->ecntrl, FEC_ECNTRL_RESET);
+ for (i = 0; i < FEC_RESET_DELAY; ++i) {
+ if ((in_be32(&fec->ecntrl) & FEC_ECNTRL_RESET) == 0)
+ break;
+ udelay(1);
+ }
+ if (i == FEC_RESET_DELAY)
+ dev_err(&dev->dev, "FEC Reset timeout!\n");
+
+ /* set pause to 0x20 frames */
+ out_be32(&fec->op_pause, FEC_OP_PAUSE_OPCODE | 0x20);
+
+ /* high service request will be deasserted when there's < 7 bytes in fifo
+ * low service request will be deasserted when there's < 4*7 bytes in fifo
+ */
+ out_be32(&fec->rfifo_cntrl, FEC_FIFO_CNTRL_FRAME | FEC_FIFO_CNTRL_LTG_7);
+ out_be32(&fec->tfifo_cntrl, FEC_FIFO_CNTRL_FRAME | FEC_FIFO_CNTRL_LTG_7);
+
+ /* alarm when <= x bytes in FIFO */
+ out_be32(&fec->rfifo_alarm, 0x0000030c);
+ out_be32(&fec->tfifo_alarm, 0x00000100);
+
+ /* begin transmittion when 256 bytes are in FIFO (or EOF or FIFO full) */
+ out_be32(&fec->x_wmrk, FEC_FIFO_WMRK_256B);
+
+ /* enable crc generation */
+ out_be32(&fec->xmit_fsm, FEC_XMIT_FSM_APPEND_CRC | FEC_XMIT_FSM_ENABLE_CRC);
+ out_be32(&fec->iaddr1, 0x00000000); /* No individual filter */
+ out_be32(&fec->iaddr2, 0x00000000); /* No individual filter */
+
+ /* set phy speed.
+ * this can't be done in phy driver, since it needs to be called
+ * before fec stuff (even on resume) */
+ mpc52xx_fec_phy_hw_init(priv);
+}
+
+/**
+ * mpc52xx_fec_start
+ * @dev: network device
+ *
+ * This function is called to start or restart the FEC during a link
+ * change. This happens on fifo errors or when switching between half
+ * and full duplex.
+ */
+static void mpc52xx_fec_start(struct net_device *dev)
+{
+ struct mpc52xx_fec_priv *priv = netdev_priv(dev);
+ struct mpc52xx_fec __iomem *fec = priv->fec;
+ u32 rcntrl;
+ u32 tcntrl;
+ u32 tmp;
+
+ /* clear sticky error bits */
+ tmp = FEC_FIFO_STATUS_ERR | FEC_FIFO_STATUS_UF | FEC_FIFO_STATUS_OF;
+ out_be32(&fec->rfifo_status, in_be32(&fec->rfifo_status) & tmp);
+ out_be32(&fec->tfifo_status, in_be32(&fec->tfifo_status) & tmp);
+
+ /* FIFOs will reset on mpc52xx_fec_enable */
+ out_be32(&fec->reset_cntrl, FEC_RESET_CNTRL_ENABLE_IS_RESET);
+
+ /* Set station address. */
+ mpc52xx_fec_set_paddr(dev, dev->dev_addr);
+
+ mpc52xx_fec_set_multicast_list(dev);
+
+ /* set max frame len, enable flow control, select mii mode */
+ rcntrl = FEC_RX_BUFFER_SIZE << 16; /* max frame length */
+ rcntrl |= FEC_RCNTRL_FCE;
+
+ if (priv->has_phy)
+ rcntrl |= FEC_RCNTRL_MII_MODE;
+
+ if (priv->duplex == DUPLEX_FULL)
+ tcntrl = FEC_TCNTRL_FDEN; /* FD enable */
+ else {
+ rcntrl |= FEC_RCNTRL_DRT; /* disable Rx on Tx (HD) */
+ tcntrl = 0;
+ }
+ out_be32(&fec->r_cntrl, rcntrl);
+ out_be32(&fec->x_cntrl, tcntrl);
+
+ /* Clear any outstanding interrupt. */
+ out_be32(&fec->ievent, 0xffffffff);
+
+ /* Enable interrupts we wish to service. */
+ out_be32(&fec->imask, FEC_IMASK_ENABLE);
+
+ /* And last, enable the transmit and receive processing. */
+ out_be32(&fec->ecntrl, FEC_ECNTRL_ETHER_EN);
+ out_be32(&fec->r_des_active, 0x01000000);
+}
+
+/**
+ * mpc52xx_fec_stop
+ * @dev: network device
+ *
+ * stop all activity on fec and empty dma buffers
+ */
+static void mpc52xx_fec_stop(struct net_device *dev)
+{
+ struct mpc52xx_fec_priv *priv = netdev_priv(dev);
+ struct mpc52xx_fec __iomem *fec = priv->fec;
+ unsigned long timeout;
+
+ /* disable all interrupts */
+ out_be32(&fec->imask, 0);
+
+ /* Disable the rx task. */
+ bcom_disable(priv->rx_dmatsk);
+
+ /* Wait for tx queue to drain, but only if we're in process context */
+ if (!in_interrupt()) {
+ timeout = jiffies + msecs_to_jiffies(2000);
+ while (time_before(jiffies, timeout) &&
+ !bcom_queue_empty(priv->tx_dmatsk))
+ msleep(100);
+
+ if (time_after_eq(jiffies, timeout))
+ dev_err(&dev->dev, "queues didn't drain\n");
+#if 1
+ if (time_after_eq(jiffies, timeout)) {
+ dev_err(&dev->dev, " tx: index: %i, outdex: %i\n",
+ priv->tx_dmatsk->index,
+ priv->tx_dmatsk->outdex);
+ dev_err(&dev->dev, " rx: index: %i, outdex: %i\n",
+ priv->rx_dmatsk->index,
+ priv->rx_dmatsk->outdex);
+ }
+#endif
+ }
+
+ bcom_disable(priv->tx_dmatsk);
+
+ /* Stop FEC */
+ out_be32(&fec->ecntrl, in_be32(&fec->ecntrl) & ~FEC_ECNTRL_ETHER_EN);
+
+ return;
+}
+
+/* reset fec and bestcomm tasks */
+static void mpc52xx_fec_reset(struct net_device *dev)
+{
+ struct mpc52xx_fec_priv *priv = netdev_priv(dev);
+ struct mpc52xx_fec __iomem *fec = priv->fec;
+
+ mpc52xx_fec_stop(dev);
+
+ out_be32(&fec->rfifo_status, in_be32(&fec->rfifo_status));
+ out_be32(&fec->reset_cntrl, FEC_RESET_CNTRL_RESET_FIFO);
+
+ mpc52xx_fec_free_rx_buffers(dev, priv->rx_dmatsk);
+
+ mpc52xx_fec_hw_init(dev);
+
+ phy_stop(priv->phydev);
+ phy_write(priv->phydev, MII_BMCR, BMCR_RESET);
+ phy_start(priv->phydev);
+
+ bcom_fec_rx_reset(priv->rx_dmatsk);
+ bcom_fec_tx_reset(priv->tx_dmatsk);
+
+ mpc52xx_fec_alloc_rx_buffers(dev, priv->rx_dmatsk);
+
+ bcom_enable(priv->rx_dmatsk);
+ bcom_enable(priv->tx_dmatsk);
+
+ mpc52xx_fec_start(dev);
+}
+
+
+/* ethtool interface */
+static void mpc52xx_fec_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ strcpy(info->driver, DRIVER_NAME);
+}
+
+static int mpc52xx_fec_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct mpc52xx_fec_priv *priv = netdev_priv(dev);
+ return phy_ethtool_gset(priv->phydev, cmd);
+}
+
+static int mpc52xx_fec_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct mpc52xx_fec_priv *priv = netdev_priv(dev);
+ return phy_ethtool_sset(priv->phydev, cmd);
+}
+
+static u32 mpc52xx_fec_get_msglevel(struct net_device *dev)
+{
+ struct mpc52xx_fec_priv *priv = netdev_priv(dev);
+ return priv->msg_enable;
+}
+
+static void mpc52xx_fec_set_msglevel(struct net_device *dev, u32 level)
+{
+ struct mpc52xx_fec_priv *priv = netdev_priv(dev);
+ priv->msg_enable = level;
+}
+
+static const struct ethtool_ops mpc52xx_fec_ethtool_ops = {
+ .get_drvinfo = mpc52xx_fec_get_drvinfo,
+ .get_settings = mpc52xx_fec_get_settings,
+ .set_settings = mpc52xx_fec_set_settings,
+ .get_link = ethtool_op_get_link,
+ .get_msglevel = mpc52xx_fec_get_msglevel,
+ .set_msglevel = mpc52xx_fec_set_msglevel,
+};
+
+
+static int mpc52xx_fec_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+ struct mpc52xx_fec_priv *priv = netdev_priv(dev);
+
+ return mpc52xx_fec_phy_mii_ioctl(priv, if_mii(rq), cmd);
+}
+
+/* ======================================================================== */
+/* OF Driver */
+/* ======================================================================== */
+
+static int __devinit
+mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match)
+{
+ int rv;
+ struct net_device *ndev;
+ struct mpc52xx_fec_priv *priv = NULL;
+ struct resource mem;
+ const phandle *ph;
+
+ phys_addr_t rx_fifo;
+ phys_addr_t tx_fifo;
+
+ /* Get the ether ndev & it's private zone */
+ ndev = alloc_etherdev(sizeof(struct mpc52xx_fec_priv));
+ if (!ndev)
+ return -ENOMEM;
+
+ priv = netdev_priv(ndev);
+
+ /* Reserve FEC control zone */
+ rv = of_address_to_resource(op->node, 0, &mem);
+ if (rv) {
+ printk(KERN_ERR DRIVER_NAME ": "
+ "Error while parsing device node resource\n" );
+ return rv;
+ }
+ if ((mem.end - mem.start + 1) < sizeof(struct mpc52xx_fec)) {
+ printk(KERN_ERR DRIVER_NAME
+ " - invalid resource size (%lx < %x), check mpc52xx_devices.c\n",
+ (unsigned long)(mem.end - mem.start + 1), sizeof(struct mpc52xx_fec));
+ return -EINVAL;
+ }
+
+ if (!request_mem_region(mem.start, sizeof(struct mpc52xx_fec), DRIVER_NAME))
+ return -EBUSY;
+
+ /* Init ether ndev with what we have */
+ ndev->open = mpc52xx_fec_open;
+ ndev->stop = mpc52xx_fec_close;
+ ndev->hard_start_xmit = mpc52xx_fec_hard_start_xmit;
+ ndev->do_ioctl = mpc52xx_fec_ioctl;
+ ndev->ethtool_ops = &mpc52xx_fec_ethtool_ops;
+ ndev->get_stats = mpc52xx_fec_get_stats;
+ ndev->set_mac_address = mpc52xx_fec_set_mac_address;
+ ndev->set_multicast_list = mpc52xx_fec_set_multicast_list;
+ ndev->tx_timeout = mpc52xx_fec_tx_timeout;
+ ndev->watchdog_timeo = FEC_WATCHDOG_TIMEOUT;
+ ndev->base_addr = mem.start;
+
+ priv->t_irq = priv->r_irq = ndev->irq = NO_IRQ; /* IRQ are free for now */
+
+ spin_lock_init(&priv->lock);
+
+ /* ioremap the zones */
+ priv->fec = ioremap(mem.start, sizeof(struct mpc52xx_fec));
+
+ if (!priv->fec) {
+ rv = -ENOMEM;
+ goto probe_error;
+ }
+
+ /* Bestcomm init */
+ rx_fifo = ndev->base_addr + offsetof(struct mpc52xx_fec, rfifo_data);
+ tx_fifo = ndev->base_addr + offsetof(struct mpc52xx_fec, tfifo_data);
+
+ priv->rx_dmatsk = bcom_fec_rx_init(FEC_RX_NUM_BD, rx_fifo, FEC_RX_BUFFER_SIZE);
+ priv->tx_dmatsk = bcom_fec_tx_init(FEC_TX_NUM_BD, tx_fifo);
+
+ if (!priv->rx_dmatsk || !priv->tx_dmatsk) {
+ printk(KERN_ERR DRIVER_NAME ": Can not init SDMA tasks\n" );
+ rv = -ENOMEM;
+ goto probe_error;
+ }
+
+ /* Get the IRQ we need one by one */
+ /* Control */
+ ndev->irq = irq_of_parse_and_map(op->node, 0);
+
+ /* RX */
+ priv->r_irq = bcom_get_task_irq(priv->rx_dmatsk);
+
+ /* TX */
+ priv->t_irq = bcom_get_task_irq(priv->tx_dmatsk);
+
+ /* MAC address init */
+ if (!is_zero_ether_addr(mpc52xx_fec_mac_addr))
+ memcpy(ndev->dev_addr, mpc52xx_fec_mac_addr, 6);
+ else
+ mpc52xx_fec_get_paddr(ndev, ndev->dev_addr);
+
+ priv->msg_enable = netif_msg_init(debug, MPC52xx_MESSAGES_DEFAULT);
+ priv->duplex = DUPLEX_FULL;
+
+ /* is the phy present in device tree? */
+ ph = of_get_property(op->node, "phy-handle", NULL);
+ if (ph) {
+ const unsigned int *prop;
+ struct device_node *phy_dn;
+ priv->has_phy = 1;
+
+ phy_dn = of_find_node_by_phandle(*ph);
+ prop = of_get_property(phy_dn, "reg", NULL);
+ priv->phy_addr = *prop;
+
+ of_node_put(phy_dn);
+
+ /* Phy speed */
+ priv->phy_speed = ((mpc52xx_find_ipb_freq(op->node) >> 20) / 5) << 1;
+ } else {
+ dev_info(&ndev->dev, "can't find \"phy-handle\" in device"
+ " tree, using 7-wire mode\n");
+ }
+
+ /* Hardware init */
+ mpc52xx_fec_hw_init(ndev);
+
+ mpc52xx_fec_reset_stats(ndev);
+
+ /* Register the new network device */
+ rv = register_netdev(ndev);
+ if (rv < 0)
+ goto probe_error;
+
+ /* We're done ! */
+ dev_set_drvdata(&op->dev, ndev);
+
+ return 0;
+
+
+ /* Error handling - free everything that might be allocated */
+probe_error:
+
+ irq_dispose_mapping(ndev->irq);
+
+ if (priv->rx_dmatsk)
+ bcom_fec_rx_release(priv->rx_dmatsk);
+ if (priv->tx_dmatsk)
+ bcom_fec_tx_release(priv->tx_dmatsk);
+
+ if (priv->fec)
+ iounmap(priv->fec);
+
+ release_mem_region(mem.start, sizeof(struct mpc52xx_fec));
+
+ free_netdev(ndev);
+
+ return rv;
+}
+
+static int
+mpc52xx_fec_remove(struct of_device *op)
+{
+ struct net_device *ndev;
+ struct mpc52xx_fec_priv *priv;
+
+ ndev = dev_get_drvdata(&op->dev);
+ priv = netdev_priv(ndev);
+
+ unregister_netdev(ndev);
+
+ irq_dispose_mapping(ndev->irq);
+
+ bcom_fec_rx_release(priv->rx_dmatsk);
+ bcom_fec_tx_release(priv->tx_dmatsk);
+
+ iounmap(priv->fec);
+
+ release_mem_region(ndev->base_addr, sizeof(struct mpc52xx_fec));
+
+ free_netdev(ndev);
+
+ dev_set_drvdata(&op->dev, NULL);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int mpc52xx_fec_of_suspend(struct of_device *op, pm_message_t state)
+{
+ struct net_device *dev = dev_get_drvdata(&op->dev);
+
+ if (netif_running(dev))
+ mpc52xx_fec_close(dev);
+
+ return 0;
+}
+
+static int mpc52xx_fec_of_resume(struct of_device *op)
+{
+ struct net_device *dev = dev_get_drvdata(&op->dev);
+
+ mpc52xx_fec_hw_init(dev);
+ mpc52xx_fec_reset_stats(dev);
+
+ if (netif_running(dev))
+ mpc52xx_fec_open(dev);
+
+ return 0;
+}
+#endif
+
+static struct of_device_id mpc52xx_fec_match[] = {
+ {
+ .type = "network",
+ .compatible = "mpc5200-fec",
+ },
+ { }
+};
+
+MODULE_DEVICE_TABLE(of, mpc52xx_fec_match);
+
+static struct of_platform_driver mpc52xx_fec_driver = {
+ .owner = THIS_MODULE,
+ .name = DRIVER_NAME,
+ .match_table = mpc52xx_fec_match,
+ .probe = mpc52xx_fec_probe,
+ .remove = mpc52xx_fec_remove,
+#ifdef CONFIG_PM
+ .suspend = mpc52xx_fec_of_suspend,
+ .resume = mpc52xx_fec_of_resume,
+#endif
+};
+
+
+/* ======================================================================== */
+/* Module */
+/* ======================================================================== */
+
+static int __init
+mpc52xx_fec_init(void)
+{
+#ifdef CONFIG_FEC_MPC52xx_MDIO
+ int ret;
+ ret = of_register_platform_driver(&mpc52xx_fec_mdio_driver);
+ if (ret) {
+ printk(KERN_ERR DRIVER_NAME ": failed to register mdio driver\n");
+ return ret;
+ }
+#endif
+ return of_register_platform_driver(&mpc52xx_fec_driver);
+}
+
+static void __exit
+mpc52xx_fec_exit(void)
+{
+ of_unregister_platform_driver(&mpc52xx_fec_driver);
+#ifdef CONFIG_FEC_MPC52xx_MDIO
+ of_unregister_platform_driver(&mpc52xx_fec_mdio_driver);
+#endif
+}
+
+
+module_init(mpc52xx_fec_init);
+module_exit(mpc52xx_fec_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Dale Farnsworth");
+MODULE_DESCRIPTION("Ethernet driver for the Freescale MPC52xx FEC");
diff --git a/drivers/net/fec_mpc52xx.h b/drivers/net/fec_mpc52xx.h
new file mode 100644
index 000000000000..8b1f75397b9a
--- /dev/null
+++ b/drivers/net/fec_mpc52xx.h
@@ -0,0 +1,313 @@
+/*
+ * drivers/drivers/net/fec_mpc52xx/fec.h
+ *
+ * Driver for the MPC5200 Fast Ethernet Controller
+ *
+ * Author: Dale Farnsworth <dfarnsworth@mvista.com>
+ *
+ * 2003-2004 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef __DRIVERS_NET_MPC52XX_FEC_H__
+#define __DRIVERS_NET_MPC52XX_FEC_H__
+
+#include <linux/phy.h>
+
+/* Tunable constant */
+/* FEC_RX_BUFFER_SIZE includes 4 bytes for CRC32 */
+#define FEC_RX_BUFFER_SIZE 1522 /* max receive packet size */
+#define FEC_RX_NUM_BD 256
+#define FEC_TX_NUM_BD 64
+
+#define FEC_RESET_DELAY 50 /* uS */
+
+#define FEC_WATCHDOG_TIMEOUT ((400*HZ)/1000)
+
+struct mpc52xx_fec_priv {
+ int duplex;
+ int r_irq;
+ int t_irq;
+ struct mpc52xx_fec __iomem *fec;
+ struct bcom_task *rx_dmatsk;
+ struct bcom_task *tx_dmatsk;
+ spinlock_t lock;
+ int msg_enable;
+
+ int has_phy;
+ unsigned int phy_speed;
+ unsigned int phy_addr;
+ struct phy_device *phydev;
+ enum phy_state link;
+ int speed;
+};
+
+
+/* ======================================================================== */
+/* Hardware register sets & bits */
+/* ======================================================================== */
+
+struct mpc52xx_fec {
+ u32 fec_id; /* FEC + 0x000 */
+ u32 ievent; /* FEC + 0x004 */
+ u32 imask; /* FEC + 0x008 */
+
+ u32 reserved0[1]; /* FEC + 0x00C */
+ u32 r_des_active; /* FEC + 0x010 */
+ u32 x_des_active; /* FEC + 0x014 */
+ u32 r_des_active_cl; /* FEC + 0x018 */
+ u32 x_des_active_cl; /* FEC + 0x01C */
+ u32 ivent_set; /* FEC + 0x020 */
+ u32 ecntrl; /* FEC + 0x024 */
+
+ u32 reserved1[6]; /* FEC + 0x028-03C */
+ u32 mii_data; /* FEC + 0x040 */
+ u32 mii_speed; /* FEC + 0x044 */
+ u32 mii_status; /* FEC + 0x048 */
+
+ u32 reserved2[5]; /* FEC + 0x04C-05C */
+ u32 mib_data; /* FEC + 0x060 */
+ u32 mib_control; /* FEC + 0x064 */
+
+ u32 reserved3[6]; /* FEC + 0x068-7C */
+ u32 r_activate; /* FEC + 0x080 */
+ u32 r_cntrl; /* FEC + 0x084 */
+ u32 r_hash; /* FEC + 0x088 */
+ u32 r_data; /* FEC + 0x08C */
+ u32 ar_done; /* FEC + 0x090 */
+ u32 r_test; /* FEC + 0x094 */
+ u32 r_mib; /* FEC + 0x098 */
+ u32 r_da_low; /* FEC + 0x09C */
+ u32 r_da_high; /* FEC + 0x0A0 */
+
+ u32 reserved4[7]; /* FEC + 0x0A4-0BC */
+ u32 x_activate; /* FEC + 0x0C0 */
+ u32 x_cntrl; /* FEC + 0x0C4 */
+ u32 backoff; /* FEC + 0x0C8 */
+ u32 x_data; /* FEC + 0x0CC */
+ u32 x_status; /* FEC + 0x0D0 */
+ u32 x_mib; /* FEC + 0x0D4 */
+ u32 x_test; /* FEC + 0x0D8 */
+ u32 fdxfc_da1; /* FEC + 0x0DC */
+ u32 fdxfc_da2; /* FEC + 0x0E0 */
+ u32 paddr1; /* FEC + 0x0E4 */
+ u32 paddr2; /* FEC + 0x0E8 */
+ u32 op_pause; /* FEC + 0x0EC */
+
+ u32 reserved5[4]; /* FEC + 0x0F0-0FC */
+ u32 instr_reg; /* FEC + 0x100 */
+ u32 context_reg; /* FEC + 0x104 */
+ u32 test_cntrl; /* FEC + 0x108 */
+ u32 acc_reg; /* FEC + 0x10C */
+ u32 ones; /* FEC + 0x110 */
+ u32 zeros; /* FEC + 0x114 */
+ u32 iaddr1; /* FEC + 0x118 */
+ u32 iaddr2; /* FEC + 0x11C */
+ u32 gaddr1; /* FEC + 0x120 */
+ u32 gaddr2; /* FEC + 0x124 */
+ u32 random; /* FEC + 0x128 */
+ u32 rand1; /* FEC + 0x12C */
+ u32 tmp; /* FEC + 0x130 */
+
+ u32 reserved6[3]; /* FEC + 0x134-13C */
+ u32 fifo_id; /* FEC + 0x140 */
+ u32 x_wmrk; /* FEC + 0x144 */
+ u32 fcntrl; /* FEC + 0x148 */
+ u32 r_bound; /* FEC + 0x14C */
+ u32 r_fstart; /* FEC + 0x150 */
+ u32 r_count; /* FEC + 0x154 */
+ u32 r_lag; /* FEC + 0x158 */
+ u32 r_read; /* FEC + 0x15C */
+ u32 r_write; /* FEC + 0x160 */
+ u32 x_count; /* FEC + 0x164 */
+ u32 x_lag; /* FEC + 0x168 */
+ u32 x_retry; /* FEC + 0x16C */
+ u32 x_write; /* FEC + 0x170 */
+ u32 x_read; /* FEC + 0x174 */
+
+ u32 reserved7[2]; /* FEC + 0x178-17C */
+ u32 fm_cntrl; /* FEC + 0x180 */
+ u32 rfifo_data; /* FEC + 0x184 */
+ u32 rfifo_status; /* FEC + 0x188 */
+ u32 rfifo_cntrl; /* FEC + 0x18C */
+ u32 rfifo_lrf_ptr; /* FEC + 0x190 */
+ u32 rfifo_lwf_ptr; /* FEC + 0x194 */
+ u32 rfifo_alarm; /* FEC + 0x198 */
+ u32 rfifo_rdptr; /* FEC + 0x19C */
+ u32 rfifo_wrptr; /* FEC + 0x1A0 */
+ u32 tfifo_data; /* FEC + 0x1A4 */
+ u32 tfifo_status; /* FEC + 0x1A8 */
+ u32 tfifo_cntrl; /* FEC + 0x1AC */
+ u32 tfifo_lrf_ptr; /* FEC + 0x1B0 */
+ u32 tfifo_lwf_ptr; /* FEC + 0x1B4 */
+ u32 tfifo_alarm; /* FEC + 0x1B8 */
+ u32 tfifo_rdptr; /* FEC + 0x1BC */
+ u32 tfifo_wrptr; /* FEC + 0x1C0 */
+
+ u32 reset_cntrl; /* FEC + 0x1C4 */
+ u32 xmit_fsm; /* FEC + 0x1C8 */
+
+ u32 reserved8[3]; /* FEC + 0x1CC-1D4 */
+ u32 rdes_data0; /* FEC + 0x1D8 */
+ u32 rdes_data1; /* FEC + 0x1DC */
+ u32 r_length; /* FEC + 0x1E0 */
+ u32 x_length; /* FEC + 0x1E4 */
+ u32 x_addr; /* FEC + 0x1E8 */
+ u32 cdes_data; /* FEC + 0x1EC */
+ u32 status; /* FEC + 0x1F0 */
+ u32 dma_control; /* FEC + 0x1F4 */
+ u32 des_cmnd; /* FEC + 0x1F8 */
+ u32 data; /* FEC + 0x1FC */
+
+ u32 rmon_t_drop; /* FEC + 0x200 */
+ u32 rmon_t_packets; /* FEC + 0x204 */
+ u32 rmon_t_bc_pkt; /* FEC + 0x208 */
+ u32 rmon_t_mc_pkt; /* FEC + 0x20C */
+ u32 rmon_t_crc_align; /* FEC + 0x210 */
+ u32 rmon_t_undersize; /* FEC + 0x214 */
+ u32 rmon_t_oversize; /* FEC + 0x218 */
+ u32 rmon_t_frag; /* FEC + 0x21C */
+ u32 rmon_t_jab; /* FEC + 0x220 */
+ u32 rmon_t_col; /* FEC + 0x224 */
+ u32 rmon_t_p64; /* FEC + 0x228 */
+ u32 rmon_t_p65to127; /* FEC + 0x22C */
+ u32 rmon_t_p128to255; /* FEC + 0x230 */
+ u32 rmon_t_p256to511; /* FEC + 0x234 */
+ u32 rmon_t_p512to1023; /* FEC + 0x238 */
+ u32 rmon_t_p1024to2047; /* FEC + 0x23C */
+ u32 rmon_t_p_gte2048; /* FEC + 0x240 */
+ u32 rmon_t_octets; /* FEC + 0x244 */
+ u32 ieee_t_drop; /* FEC + 0x248 */
+ u32 ieee_t_frame_ok; /* FEC + 0x24C */
+ u32 ieee_t_1col; /* FEC + 0x250 */
+ u32 ieee_t_mcol; /* FEC + 0x254 */
+ u32 ieee_t_def; /* FEC + 0x258 */
+ u32 ieee_t_lcol; /* FEC + 0x25C */
+ u32 ieee_t_excol; /* FEC + 0x260 */
+ u32 ieee_t_macerr; /* FEC + 0x264 */
+ u32 ieee_t_cserr; /* FEC + 0x268 */
+ u32 ieee_t_sqe; /* FEC + 0x26C */
+ u32 t_fdxfc; /* FEC + 0x270 */
+ u32 ieee_t_octets_ok; /* FEC + 0x274 */
+
+ u32 reserved9[2]; /* FEC + 0x278-27C */
+ u32 rmon_r_drop; /* FEC + 0x280 */
+ u32 rmon_r_packets; /* FEC + 0x284 */
+ u32 rmon_r_bc_pkt; /* FEC + 0x288 */
+ u32 rmon_r_mc_pkt; /* FEC + 0x28C */
+ u32 rmon_r_crc_align; /* FEC + 0x290 */
+ u32 rmon_r_undersize; /* FEC + 0x294 */
+ u32 rmon_r_oversize; /* FEC + 0x298 */
+ u32 rmon_r_frag; /* FEC + 0x29C */
+ u32 rmon_r_jab; /* FEC + 0x2A0 */
+
+ u32 rmon_r_resvd_0; /* FEC + 0x2A4 */
+
+ u32 rmon_r_p64; /* FEC + 0x2A8 */
+ u32 rmon_r_p65to127; /* FEC + 0x2AC */
+ u32 rmon_r_p128to255; /* FEC + 0x2B0 */
+ u32 rmon_r_p256to511; /* FEC + 0x2B4 */
+ u32 rmon_r_p512to1023; /* FEC + 0x2B8 */
+ u32 rmon_r_p1024to2047; /* FEC + 0x2BC */
+ u32 rmon_r_p_gte2048; /* FEC + 0x2C0 */
+ u32 rmon_r_octets; /* FEC + 0x2C4 */
+ u32 ieee_r_drop; /* FEC + 0x2C8 */
+ u32 ieee_r_frame_ok; /* FEC + 0x2CC */
+ u32 ieee_r_crc; /* FEC + 0x2D0 */
+ u32 ieee_r_align; /* FEC + 0x2D4 */
+ u32 r_macerr; /* FEC + 0x2D8 */
+ u32 r_fdxfc; /* FEC + 0x2DC */
+ u32 ieee_r_octets_ok; /* FEC + 0x2E0 */
+
+ u32 reserved10[7]; /* FEC + 0x2E4-2FC */
+
+ u32 reserved11[64]; /* FEC + 0x300-3FF */
+};
+
+#define FEC_MIB_DISABLE 0x80000000
+
+#define FEC_IEVENT_HBERR 0x80000000
+#define FEC_IEVENT_BABR 0x40000000
+#define FEC_IEVENT_BABT 0x20000000
+#define FEC_IEVENT_GRA 0x10000000
+#define FEC_IEVENT_TFINT 0x08000000
+#define FEC_IEVENT_MII 0x00800000
+#define FEC_IEVENT_LATE_COL 0x00200000
+#define FEC_IEVENT_COL_RETRY_LIM 0x00100000
+#define FEC_IEVENT_XFIFO_UN 0x00080000
+#define FEC_IEVENT_XFIFO_ERROR 0x00040000
+#define FEC_IEVENT_RFIFO_ERROR 0x00020000
+
+#define FEC_IMASK_HBERR 0x80000000
+#define FEC_IMASK_BABR 0x40000000
+#define FEC_IMASK_BABT 0x20000000
+#define FEC_IMASK_GRA 0x10000000
+#define FEC_IMASK_MII 0x00800000
+#define FEC_IMASK_LATE_COL 0x00200000
+#define FEC_IMASK_COL_RETRY_LIM 0x00100000
+#define FEC_IMASK_XFIFO_UN 0x00080000
+#define FEC_IMASK_XFIFO_ERROR 0x00040000
+#define FEC_IMASK_RFIFO_ERROR 0x00020000
+
+/* all but MII, which is enabled separately */
+#define FEC_IMASK_ENABLE (FEC_IMASK_HBERR | FEC_IMASK_BABR | \
+ FEC_IMASK_BABT | FEC_IMASK_GRA | FEC_IMASK_LATE_COL | \
+ FEC_IMASK_COL_RETRY_LIM | FEC_IMASK_XFIFO_UN | \
+ FEC_IMASK_XFIFO_ERROR | FEC_IMASK_RFIFO_ERROR)
+
+#define FEC_RCNTRL_MAX_FL_SHIFT 16
+#define FEC_RCNTRL_LOOP 0x01
+#define FEC_RCNTRL_DRT 0x02
+#define FEC_RCNTRL_MII_MODE 0x04
+#define FEC_RCNTRL_PROM 0x08
+#define FEC_RCNTRL_BC_REJ 0x10
+#define FEC_RCNTRL_FCE 0x20
+
+#define FEC_TCNTRL_GTS 0x00000001
+#define FEC_TCNTRL_HBC 0x00000002
+#define FEC_TCNTRL_FDEN 0x00000004
+#define FEC_TCNTRL_TFC_PAUSE 0x00000008
+#define FEC_TCNTRL_RFC_PAUSE 0x00000010
+
+#define FEC_ECNTRL_RESET 0x00000001
+#define FEC_ECNTRL_ETHER_EN 0x00000002
+
+#define FEC_MII_DATA_ST 0x40000000 /* Start frame */
+#define FEC_MII_DATA_OP_RD 0x20000000 /* Perform read */
+#define FEC_MII_DATA_OP_WR 0x10000000 /* Perform write */
+#define FEC_MII_DATA_PA_MSK 0x0f800000 /* PHY Address mask */
+#define FEC_MII_DATA_RA_MSK 0x007c0000 /* PHY Register mask */
+#define FEC_MII_DATA_TA 0x00020000 /* Turnaround */
+#define FEC_MII_DATA_DATAMSK 0x0000ffff /* PHY data mask */
+
+#define FEC_MII_READ_FRAME (FEC_MII_DATA_ST | FEC_MII_DATA_OP_RD | FEC_MII_DATA_TA)
+#define FEC_MII_WRITE_FRAME (FEC_MII_DATA_ST | FEC_MII_DATA_OP_WR | FEC_MII_DATA_TA)
+
+#define FEC_MII_DATA_RA_SHIFT 0x12 /* MII reg addr bits */
+#define FEC_MII_DATA_PA_SHIFT 0x17 /* MII PHY addr bits */
+
+#define FEC_PADDR2_TYPE 0x8808
+
+#define FEC_OP_PAUSE_OPCODE 0x00010000
+
+#define FEC_FIFO_WMRK_256B 0x3
+
+#define FEC_FIFO_STATUS_ERR 0x00400000
+#define FEC_FIFO_STATUS_UF 0x00200000
+#define FEC_FIFO_STATUS_OF 0x00100000
+
+#define FEC_FIFO_CNTRL_FRAME 0x08000000
+#define FEC_FIFO_CNTRL_LTG_7 0x07000000
+
+#define FEC_RESET_CNTRL_RESET_FIFO 0x02000000
+#define FEC_RESET_CNTRL_ENABLE_IS_RESET 0x01000000
+
+#define FEC_XMIT_FSM_APPEND_CRC 0x02000000
+#define FEC_XMIT_FSM_ENABLE_CRC 0x01000000
+
+
+extern struct of_platform_driver mpc52xx_fec_mdio_driver;
+
+#endif /* __DRIVERS_NET_MPC52XX_FEC_H__ */
diff --git a/drivers/net/fec_mpc52xx_phy.c b/drivers/net/fec_mpc52xx_phy.c
new file mode 100644
index 000000000000..ba6e8b218e0a
--- /dev/null
+++ b/drivers/net/fec_mpc52xx_phy.c
@@ -0,0 +1,198 @@
+/*
+ * Driver for the MPC5200 Fast Ethernet Controller - MDIO bus driver
+ *
+ * Copyright (C) 2007 Domen Puncer, Telargo, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/phy.h>
+#include <linux/of_platform.h>
+#include <asm/io.h>
+#include <asm/mpc52xx.h>
+#include "fec_mpc52xx.h"
+
+struct mpc52xx_fec_mdio_priv {
+ struct mpc52xx_fec __iomem *regs;
+};
+
+static int mpc52xx_fec_mdio_read(struct mii_bus *bus, int phy_id, int reg)
+{
+ struct mpc52xx_fec_mdio_priv *priv = bus->priv;
+ struct mpc52xx_fec __iomem *fec;
+ int tries = 100;
+ u32 request = FEC_MII_READ_FRAME;
+
+ fec = priv->regs;
+ out_be32(&fec->ievent, FEC_IEVENT_MII);
+
+ request |= (phy_id << FEC_MII_DATA_PA_SHIFT) & FEC_MII_DATA_PA_MSK;
+ request |= (reg << FEC_MII_DATA_RA_SHIFT) & FEC_MII_DATA_RA_MSK;
+
+ out_be32(&priv->regs->mii_data, request);
+
+ /* wait for it to finish, this takes about 23 us on lite5200b */
+ while (!(in_be32(&fec->ievent) & FEC_IEVENT_MII) && --tries)
+ udelay(5);
+
+ if (tries == 0)
+ return -ETIMEDOUT;
+
+ return in_be32(&priv->regs->mii_data) & FEC_MII_DATA_DATAMSK;
+}
+
+static int mpc52xx_fec_mdio_write(struct mii_bus *bus, int phy_id, int reg, u16 data)
+{
+ struct mpc52xx_fec_mdio_priv *priv = bus->priv;
+ struct mpc52xx_fec __iomem *fec;
+ u32 value = data;
+ int tries = 100;
+
+ fec = priv->regs;
+ out_be32(&fec->ievent, FEC_IEVENT_MII);
+
+ value |= FEC_MII_WRITE_FRAME;
+ value |= (phy_id << FEC_MII_DATA_PA_SHIFT) & FEC_MII_DATA_PA_MSK;
+ value |= (reg << FEC_MII_DATA_RA_SHIFT) & FEC_MII_DATA_RA_MSK;
+
+ out_be32(&priv->regs->mii_data, value);
+
+ /* wait for request to finish */
+ while (!(in_be32(&fec->ievent) & FEC_IEVENT_MII) && --tries)
+ udelay(5);
+
+ if (tries == 0)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+static int mpc52xx_fec_mdio_probe(struct of_device *of, const struct of_device_id *match)
+{
+ struct device *dev = &of->dev;
+ struct device_node *np = of->node;
+ struct device_node *child = NULL;
+ struct mii_bus *bus;
+ struct mpc52xx_fec_mdio_priv *priv;
+ struct resource res = {};
+ int err;
+ int i;
+
+ bus = kzalloc(sizeof(*bus), GFP_KERNEL);
+ if (bus == NULL)
+ return -ENOMEM;
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (priv == NULL) {
+ err = -ENOMEM;
+ goto out_free;
+ }
+
+ bus->name = "mpc52xx MII bus";
+ bus->read = mpc52xx_fec_mdio_read;
+ bus->write = mpc52xx_fec_mdio_write;
+
+ /* setup irqs */
+ bus->irq = kmalloc(sizeof(bus->irq[0]) * PHY_MAX_ADDR, GFP_KERNEL);
+ if (bus->irq == NULL) {
+ err = -ENOMEM;
+ goto out_free;
+ }
+ for (i=0; i<PHY_MAX_ADDR; i++)
+ bus->irq[i] = PHY_POLL;
+
+ while ((child = of_get_next_child(np, child)) != NULL) {
+ int irq = irq_of_parse_and_map(child, 0);
+ if (irq != NO_IRQ) {
+ const u32 *id = of_get_property(child, "reg", NULL);
+ bus->irq[*id] = irq;
+ }
+ }
+
+ /* setup registers */
+ err = of_address_to_resource(np, 0, &res);
+ if (err)
+ goto out_free;
+ priv->regs = ioremap(res.start, res.end - res.start + 1);
+ if (priv->regs == NULL) {
+ err = -ENOMEM;
+ goto out_free;
+ }
+
+ bus->id = res.start;
+ bus->priv = priv;
+
+ bus->dev = dev;
+ dev_set_drvdata(dev, bus);
+
+ /* set MII speed */
+ out_be32(&priv->regs->mii_speed, ((mpc52xx_find_ipb_freq(of->node) >> 20) / 5) << 1);
+
+ /* enable MII interrupt */
+ out_be32(&priv->regs->imask, in_be32(&priv->regs->imask) | FEC_IMASK_MII);
+
+ err = mdiobus_register(bus);
+ if (err)
+ goto out_unmap;
+
+ return 0;
+
+ out_unmap:
+ iounmap(priv->regs);
+ out_free:
+ for (i=0; i<PHY_MAX_ADDR; i++)
+ if (bus->irq[i] != PHY_POLL)
+ irq_dispose_mapping(bus->irq[i]);
+ kfree(bus->irq);
+ kfree(priv);
+ kfree(bus);
+
+ return err;
+}
+
+static int mpc52xx_fec_mdio_remove(struct of_device *of)
+{
+ struct device *dev = &of->dev;
+ struct mii_bus *bus = dev_get_drvdata(dev);
+ struct mpc52xx_fec_mdio_priv *priv = bus->priv;
+ int i;
+
+ mdiobus_unregister(bus);
+ dev_set_drvdata(dev, NULL);
+
+ iounmap(priv->regs);
+ for (i=0; i<PHY_MAX_ADDR; i++)
+ if (bus->irq[i])
+ irq_dispose_mapping(bus->irq[i]);
+ kfree(priv);
+ kfree(bus->irq);
+ kfree(bus);
+
+ return 0;
+}
+
+
+static struct of_device_id mpc52xx_fec_mdio_match[] = {
+ {
+ .type = "mdio",
+ .compatible = "mpc5200b-fec-phy",
+ },
+ {},
+};
+
+struct of_platform_driver mpc52xx_fec_mdio_driver = {
+ .name = "mpc5200b-fec-phy",
+ .probe = mpc52xx_fec_mdio_probe,
+ .remove = mpc52xx_fec_mdio_remove,
+ .match_table = mpc52xx_fec_mdio_match,
+};
+
+/* let fec driver call it, since this has to be registered before it */
+EXPORT_SYMBOL_GPL(mpc52xx_fec_mdio_driver);
+
+
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index dae30b731342..92ce2e38f0d5 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -128,7 +128,7 @@
#else
#define DRIVERNAPI
#endif
-#define FORCEDETH_VERSION "0.60"
+#define FORCEDETH_VERSION "0.61"
#define DRV_NAME "forcedeth"
#include <linux/module.h>
@@ -752,7 +752,6 @@ struct fe_priv {
/* General data:
* Locking: spin_lock(&np->lock); */
- struct net_device_stats stats;
struct nv_ethtool_stats estats;
int in_shutdown;
u32 linkspeed;
@@ -993,7 +992,7 @@ static void nv_enable_irq(struct net_device *dev)
if (np->msi_flags & NV_MSI_X_ENABLED)
enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
else
- enable_irq(dev->irq);
+ enable_irq(np->pci_dev->irq);
} else {
enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);
@@ -1009,7 +1008,7 @@ static void nv_disable_irq(struct net_device *dev)
if (np->msi_flags & NV_MSI_X_ENABLED)
disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
else
- disable_irq(dev->irq);
+ disable_irq(np->pci_dev->irq);
} else {
disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);
@@ -1505,15 +1504,16 @@ static struct net_device_stats *nv_get_stats(struct net_device *dev)
nv_get_hw_stats(dev);
/* copy to net_device stats */
- np->stats.tx_bytes = np->estats.tx_bytes;
- np->stats.tx_fifo_errors = np->estats.tx_fifo_errors;
- np->stats.tx_carrier_errors = np->estats.tx_carrier_errors;
- np->stats.rx_crc_errors = np->estats.rx_crc_errors;
- np->stats.rx_over_errors = np->estats.rx_over_errors;
- np->stats.rx_errors = np->estats.rx_errors_total;
- np->stats.tx_errors = np->estats.tx_errors_total;
- }
- return &np->stats;
+ dev->stats.tx_bytes = np->estats.tx_bytes;
+ dev->stats.tx_fifo_errors = np->estats.tx_fifo_errors;
+ dev->stats.tx_carrier_errors = np->estats.tx_carrier_errors;
+ dev->stats.rx_crc_errors = np->estats.rx_crc_errors;
+ dev->stats.rx_over_errors = np->estats.rx_over_errors;
+ dev->stats.rx_errors = np->estats.rx_errors_total;
+ dev->stats.tx_errors = np->estats.tx_errors_total;
+ }
+
+ return &dev->stats;
}
/*
@@ -1607,7 +1607,7 @@ static void nv_do_rx_refill(unsigned long data)
if (np->msi_flags & NV_MSI_X_ENABLED)
disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
else
- disable_irq(dev->irq);
+ disable_irq(np->pci_dev->irq);
} else {
disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
}
@@ -1625,7 +1625,7 @@ static void nv_do_rx_refill(unsigned long data)
if (np->msi_flags & NV_MSI_X_ENABLED)
enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
else
- enable_irq(dev->irq);
+ enable_irq(np->pci_dev->irq);
} else {
enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
}
@@ -1733,7 +1733,7 @@ static void nv_drain_tx(struct net_device *dev)
np->tx_ring.ex[i].buflow = 0;
}
if (nv_release_txskb(dev, &np->tx_skb[i]))
- np->stats.tx_dropped++;
+ dev->stats.tx_dropped++;
}
}
@@ -2049,13 +2049,13 @@ static void nv_tx_done(struct net_device *dev)
if (flags & NV_TX_LASTPACKET) {
if (flags & NV_TX_ERROR) {
if (flags & NV_TX_UNDERFLOW)
- np->stats.tx_fifo_errors++;
+ dev->stats.tx_fifo_errors++;
if (flags & NV_TX_CARRIERLOST)
- np->stats.tx_carrier_errors++;
- np->stats.tx_errors++;
+ dev->stats.tx_carrier_errors++;
+ dev->stats.tx_errors++;
} else {
- np->stats.tx_packets++;
- np->stats.tx_bytes += np->get_tx_ctx->skb->len;
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += np->get_tx_ctx->skb->len;
}
dev_kfree_skb_any(np->get_tx_ctx->skb);
np->get_tx_ctx->skb = NULL;
@@ -2064,13 +2064,13 @@ static void nv_tx_done(struct net_device *dev)
if (flags & NV_TX2_LASTPACKET) {
if (flags & NV_TX2_ERROR) {
if (flags & NV_TX2_UNDERFLOW)
- np->stats.tx_fifo_errors++;
+ dev->stats.tx_fifo_errors++;
if (flags & NV_TX2_CARRIERLOST)
- np->stats.tx_carrier_errors++;
- np->stats.tx_errors++;
+ dev->stats.tx_carrier_errors++;
+ dev->stats.tx_errors++;
} else {
- np->stats.tx_packets++;
- np->stats.tx_bytes += np->get_tx_ctx->skb->len;
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += np->get_tx_ctx->skb->len;
}
dev_kfree_skb_any(np->get_tx_ctx->skb);
np->get_tx_ctx->skb = NULL;
@@ -2107,7 +2107,7 @@ static void nv_tx_done_optimized(struct net_device *dev, int limit)
if (flags & NV_TX2_LASTPACKET) {
if (!(flags & NV_TX2_ERROR))
- np->stats.tx_packets++;
+ dev->stats.tx_packets++;
dev_kfree_skb_any(np->get_tx_ctx->skb);
np->get_tx_ctx->skb = NULL;
}
@@ -2268,13 +2268,13 @@ static int nv_rx_process(struct net_device *dev, int limit)
{
struct fe_priv *np = netdev_priv(dev);
u32 flags;
- u32 rx_processed_cnt = 0;
+ int rx_work = 0;
struct sk_buff *skb;
int len;
while((np->get_rx.orig != np->put_rx.orig) &&
!((flags = le32_to_cpu(np->get_rx.orig->flaglen)) & NV_RX_AVAIL) &&
- (rx_processed_cnt++ < limit)) {
+ (rx_work < limit)) {
dprintk(KERN_DEBUG "%s: nv_rx_process: flags 0x%x.\n",
dev->name, flags);
@@ -2308,7 +2308,7 @@ static int nv_rx_process(struct net_device *dev, int limit)
if (flags & NV_RX_ERROR4) {
len = nv_getlen(dev, skb->data, len);
if (len < 0) {
- np->stats.rx_errors++;
+ dev->stats.rx_errors++;
dev_kfree_skb(skb);
goto next_pkt;
}
@@ -2322,12 +2322,12 @@ static int nv_rx_process(struct net_device *dev, int limit)
/* the rest are hard errors */
else {
if (flags & NV_RX_MISSEDFRAME)
- np->stats.rx_missed_errors++;
+ dev->stats.rx_missed_errors++;
if (flags & NV_RX_CRCERR)
- np->stats.rx_crc_errors++;
+ dev->stats.rx_crc_errors++;
if (flags & NV_RX_OVERFLOW)
- np->stats.rx_over_errors++;
- np->stats.rx_errors++;
+ dev->stats.rx_over_errors++;
+ dev->stats.rx_errors++;
dev_kfree_skb(skb);
goto next_pkt;
}
@@ -2343,7 +2343,7 @@ static int nv_rx_process(struct net_device *dev, int limit)
if (flags & NV_RX2_ERROR4) {
len = nv_getlen(dev, skb->data, len);
if (len < 0) {
- np->stats.rx_errors++;
+ dev->stats.rx_errors++;
dev_kfree_skb(skb);
goto next_pkt;
}
@@ -2357,10 +2357,10 @@ static int nv_rx_process(struct net_device *dev, int limit)
/* the rest are hard errors */
else {
if (flags & NV_RX2_CRCERR)
- np->stats.rx_crc_errors++;
+ dev->stats.rx_crc_errors++;
if (flags & NV_RX2_OVERFLOW)
- np->stats.rx_over_errors++;
- np->stats.rx_errors++;
+ dev->stats.rx_over_errors++;
+ dev->stats.rx_errors++;
dev_kfree_skb(skb);
goto next_pkt;
}
@@ -2389,16 +2389,18 @@ static int nv_rx_process(struct net_device *dev, int limit)
netif_rx(skb);
#endif
dev->last_rx = jiffies;
- np->stats.rx_packets++;
- np->stats.rx_bytes += len;
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += len;
next_pkt:
if (unlikely(np->get_rx.orig++ == np->last_rx.orig))
np->get_rx.orig = np->first_rx.orig;
if (unlikely(np->get_rx_ctx++ == np->last_rx_ctx))
np->get_rx_ctx = np->first_rx_ctx;
+
+ rx_work++;
}
- return rx_processed_cnt;
+ return rx_work;
}
static int nv_rx_process_optimized(struct net_device *dev, int limit)
@@ -2406,13 +2408,13 @@ static int nv_rx_process_optimized(struct net_device *dev, int limit)
struct fe_priv *np = netdev_priv(dev);
u32 flags;
u32 vlanflags = 0;
- u32 rx_processed_cnt = 0;
+ int rx_work = 0;
struct sk_buff *skb;
int len;
while((np->get_rx.ex != np->put_rx.ex) &&
!((flags = le32_to_cpu(np->get_rx.ex->flaglen)) & NV_RX2_AVAIL) &&
- (rx_processed_cnt++ < limit)) {
+ (rx_work < limit)) {
dprintk(KERN_DEBUG "%s: nv_rx_process_optimized: flags 0x%x.\n",
dev->name, flags);
@@ -2505,8 +2507,8 @@ static int nv_rx_process_optimized(struct net_device *dev, int limit)
}
dev->last_rx = jiffies;
- np->stats.rx_packets++;
- np->stats.rx_bytes += len;
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += len;
} else {
dev_kfree_skb(skb);
}
@@ -2515,9 +2517,11 @@ next_pkt:
np->get_rx.ex = np->first_rx.ex;
if (unlikely(np->get_rx_ctx++ == np->last_rx_ctx))
np->get_rx_ctx = np->first_rx_ctx;
+
+ rx_work++;
}
- return rx_processed_cnt;
+ return rx_work;
}
static void set_bufsize(struct net_device *dev)
@@ -3556,10 +3560,12 @@ static int nv_request_irq(struct net_device *dev, int intr_test)
if (ret != 0 && np->msi_flags & NV_MSI_CAPABLE) {
if ((ret = pci_enable_msi(np->pci_dev)) == 0) {
np->msi_flags |= NV_MSI_ENABLED;
+ dev->irq = np->pci_dev->irq;
if (request_irq(np->pci_dev->irq, handler, IRQF_SHARED, dev->name, dev) != 0) {
printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret);
pci_disable_msi(np->pci_dev);
np->msi_flags &= ~NV_MSI_ENABLED;
+ dev->irq = np->pci_dev->irq;
goto out_err;
}
@@ -3622,7 +3628,7 @@ static void nv_do_nic_poll(unsigned long data)
if (np->msi_flags & NV_MSI_X_ENABLED)
disable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
else
- disable_irq_lockdep(dev->irq);
+ disable_irq_lockdep(np->pci_dev->irq);
mask = np->irqmask;
} else {
if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) {
@@ -3640,6 +3646,8 @@ static void nv_do_nic_poll(unsigned long data)
}
np->nic_poll_irq = 0;
+ /* disable_irq() contains synchronize_irq, thus no irq handler can run now */
+
if (np->recover_error) {
np->recover_error = 0;
printk(KERN_INFO "forcedeth: MAC in recoverable error state\n");
@@ -3676,7 +3684,6 @@ static void nv_do_nic_poll(unsigned long data)
}
}
- /* FIXME: Do we need synchronize_irq(dev->irq) here? */
writel(mask, base + NvRegIrqMask);
pci_push(base);
@@ -3689,7 +3696,7 @@ static void nv_do_nic_poll(unsigned long data)
if (np->msi_flags & NV_MSI_X_ENABLED)
enable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
else
- enable_irq_lockdep(dev->irq);
+ enable_irq_lockdep(np->pci_dev->irq);
} else {
if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) {
nv_nic_irq_rx(0, dev);
@@ -3727,7 +3734,7 @@ static void nv_do_stats_poll(unsigned long data)
static void nv_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
struct fe_priv *np = netdev_priv(dev);
- strcpy(info->driver, "forcedeth");
+ strcpy(info->driver, DRV_NAME);
strcpy(info->version, FORCEDETH_VERSION);
strcpy(info->bus_info, pci_name(np->pci_dev));
}
@@ -4946,7 +4953,7 @@ static int nv_close(struct net_device *dev)
#ifdef CONFIG_FORCEDETH_NAPI
napi_disable(&np->napi);
#endif
- synchronize_irq(dev->irq);
+ synchronize_irq(np->pci_dev->irq);
del_timer_sync(&np->oom_kick);
del_timer_sync(&np->nic_poll);
@@ -4991,6 +4998,11 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
u32 phystate_orig = 0, phystate;
int phyinitialized = 0;
DECLARE_MAC_BUF(mac);
+ static int printed_version;
+
+ if (!printed_version++)
+ printk(KERN_INFO "%s: Reverse Engineered nForce ethernet"
+ " driver. Version %s.\n", DRV_NAME, FORCEDETH_VERSION);
dev = alloc_etherdev(sizeof(struct fe_priv));
err = -ENOMEM;
@@ -5014,11 +5026,8 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
np->stats_poll.function = &nv_do_stats_poll; /* timer handler */
err = pci_enable_device(pci_dev);
- if (err) {
- printk(KERN_INFO "forcedeth: pci_enable_dev failed (%d) for device %s\n",
- err, pci_name(pci_dev));
+ if (err)
goto out_free;
- }
pci_set_master(pci_dev);
@@ -5047,8 +5056,8 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
}
}
if (i == DEVICE_COUNT_RESOURCE) {
- printk(KERN_INFO "forcedeth: Couldn't find register window for device %s.\n",
- pci_name(pci_dev));
+ dev_printk(KERN_INFO, &pci_dev->dev,
+ "Couldn't find register window\n");
goto out_relreg;
}
@@ -5061,16 +5070,14 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
np->desc_ver = DESC_VER_3;
np->txrxctl_bits = NVREG_TXRXCTL_DESC_3;
if (dma_64bit) {
- if (pci_set_dma_mask(pci_dev, DMA_39BIT_MASK)) {
- printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n",
- pci_name(pci_dev));
- } else {
+ if (pci_set_dma_mask(pci_dev, DMA_39BIT_MASK))
+ dev_printk(KERN_INFO, &pci_dev->dev,
+ "64-bit DMA failed, using 32-bit addressing\n");
+ else
dev->features |= NETIF_F_HIGHDMA;
- printk(KERN_INFO "forcedeth: using HIGHDMA\n");
- }
if (pci_set_consistent_dma_mask(pci_dev, DMA_39BIT_MASK)) {
- printk(KERN_INFO "forcedeth: 64-bit DMA (consistent) failed, using 32-bit ring buffers for device %s.\n",
- pci_name(pci_dev));
+ dev_printk(KERN_INFO, &pci_dev->dev,
+ "64-bit DMA (consistent) failed, using 32-bit ring buffers\n");
}
}
} else if (id->driver_data & DEV_HAS_LARGEDESC) {
@@ -5205,9 +5212,11 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
* Bad mac address. At least one bios sets the mac address
* to 01:23:45:67:89:ab
*/
- printk(KERN_ERR "%s: Invalid Mac address detected: %s\n",
- pci_name(pci_dev), print_mac(mac, dev->dev_addr));
- printk(KERN_ERR "Please complain to your hardware vendor. Switching to a random MAC.\n");
+ dev_printk(KERN_ERR, &pci_dev->dev,
+ "Invalid Mac address detected: %s\n",
+ print_mac(mac, dev->dev_addr));
+ dev_printk(KERN_ERR, &pci_dev->dev,
+ "Please complain to your hardware vendor. Switching to a random MAC.\n");
dev->dev_addr[0] = 0x00;
dev->dev_addr[1] = 0x00;
dev->dev_addr[2] = 0x6c;
@@ -5321,8 +5330,8 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
break;
}
if (i == 33) {
- printk(KERN_INFO "%s: open: Could not find a valid PHY.\n",
- pci_name(pci_dev));
+ dev_printk(KERN_INFO, &pci_dev->dev,
+ "open: Could not find a valid PHY.\n");
goto out_error;
}
@@ -5344,12 +5353,37 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
err = register_netdev(dev);
if (err) {
- printk(KERN_INFO "forcedeth: unable to register netdev: %d\n", err);
+ dev_printk(KERN_INFO, &pci_dev->dev,
+ "unable to register netdev: %d\n", err);
goto out_error;
}
- printk(KERN_INFO "%s: forcedeth.c: subsystem: %05x:%04x bound to %s\n",
- dev->name, pci_dev->subsystem_vendor, pci_dev->subsystem_device,
- pci_name(pci_dev));
+
+ dev_printk(KERN_INFO, &pci_dev->dev, "ifname %s, PHY OUI 0x%x @ %d, "
+ "addr %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
+ dev->name,
+ np->phy_oui,
+ np->phyaddr,
+ dev->dev_addr[0],
+ dev->dev_addr[1],
+ dev->dev_addr[2],
+ dev->dev_addr[3],
+ dev->dev_addr[4],
+ dev->dev_addr[5]);
+
+ dev_printk(KERN_INFO, &pci_dev->dev, "%s%s%s%s%s%s%s%s%s%sdesc-v%u\n",
+ dev->features & NETIF_F_HIGHDMA ? "highdma " : "",
+ dev->features & (NETIF_F_HW_CSUM | NETIF_F_SG) ?
+ "csum " : "",
+ dev->features & (NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX) ?
+ "vlan " : "",
+ id->driver_data & DEV_HAS_POWER_CNTRL ? "pwrctl " : "",
+ id->driver_data & DEV_HAS_MGMT_UNIT ? "mgmt " : "",
+ id->driver_data & DEV_NEED_TIMERIRQ ? "timirq " : "",
+ np->gigabit == PHY_GIGABIT ? "gbit " : "",
+ np->need_linktimer ? "lnktim " : "",
+ np->msi_flags & NV_MSI_CAPABLE ? "msi " : "",
+ np->msi_flags & NV_MSI_X_CAPABLE ? "msi-x " : "",
+ np->desc_ver);
return 0;
@@ -5563,21 +5597,36 @@ static struct pci_device_id pci_tbl[] = {
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_31),
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
},
+ { /* MCP77 Ethernet Controller */
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_32),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
+ },
+ { /* MCP77 Ethernet Controller */
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_33),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
+ },
+ { /* MCP77 Ethernet Controller */
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_34),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
+ },
+ { /* MCP77 Ethernet Controller */
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_35),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
+ },
{0,},
};
static struct pci_driver driver = {
- .name = "forcedeth",
- .id_table = pci_tbl,
- .probe = nv_probe,
- .remove = __devexit_p(nv_remove),
- .suspend = nv_suspend,
- .resume = nv_resume,
+ .name = DRV_NAME,
+ .id_table = pci_tbl,
+ .probe = nv_probe,
+ .remove = __devexit_p(nv_remove),
+ .suspend = nv_suspend,
+ .resume = nv_resume,
};
static int __init init_nic(void)
{
- printk(KERN_INFO "forcedeth.c: Reverse Engineered nForce ethernet driver. Version %s.\n", FORCEDETH_VERSION);
return pci_register_driver(&driver);
}
diff --git a/drivers/net/fs_enet/Kconfig b/drivers/net/fs_enet/Kconfig
index 2765e49e07df..562ea68ed99b 100644
--- a/drivers/net/fs_enet/Kconfig
+++ b/drivers/net/fs_enet/Kconfig
@@ -2,6 +2,7 @@ config FS_ENET
tristate "Freescale Ethernet Driver"
depends on CPM1 || CPM2
select MII
+ select PHYLIB
config FS_ENET_HAS_SCC
bool "Chip has an SCC usable for ethernet"
@@ -11,11 +12,19 @@ config FS_ENET_HAS_SCC
config FS_ENET_HAS_FCC
bool "Chip has an FCC usable for ethernet"
depends on FS_ENET && CPM2
- select MDIO_BITBANG
default y
config FS_ENET_HAS_FEC
bool "Chip has an FEC usable for ethernet"
depends on FS_ENET && CPM1
+ select FS_ENET_MDIO_FEC
default y
+config FS_ENET_MDIO_FEC
+ tristate "MDIO driver for FEC"
+ depends on FS_ENET && CPM1
+
+config FS_ENET_MDIO_FCC
+ tristate "MDIO driver for FCC"
+ depends on FS_ENET && CPM2
+ select MDIO_BITBANG
diff --git a/drivers/net/fs_enet/Makefile b/drivers/net/fs_enet/Makefile
index 02d4dc18ba69..1ffbe0756a0c 100644
--- a/drivers/net/fs_enet/Makefile
+++ b/drivers/net/fs_enet/Makefile
@@ -4,7 +4,16 @@
obj-$(CONFIG_FS_ENET) += fs_enet.o
-obj-$(CONFIG_8xx) += mac-fec.o mac-scc.o mii-fec.o
-obj-$(CONFIG_CPM2) += mac-fcc.o mii-bitbang.o
+fs_enet-$(CONFIG_FS_ENET_HAS_SCC) += mac-scc.o
+fs_enet-$(CONFIG_FS_ENET_HAS_FEC) += mac-fec.o
+fs_enet-$(CONFIG_FS_ENET_HAS_FCC) += mac-fcc.o
-fs_enet-objs := fs_enet-main.o
+ifeq ($(CONFIG_PPC_CPM_NEW_BINDING),y)
+obj-$(CONFIG_FS_ENET_MDIO_FEC) += mii-fec.o
+obj-$(CONFIG_FS_ENET_MDIO_FCC) += mii-bitbang.o
+else
+fs_enet-$(CONFIG_FS_ENET_MDIO_FEC) += mii-fec.o
+fs_enet-$(CONFIG_FS_ENET_MDIO_FCC) += mii-bitbang.o
+endif
+
+fs_enet-objs := fs_enet-main.o $(fs_enet-m)
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index 04c6faec88d2..f2a4d399a6e5 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -88,7 +88,7 @@ static void skb_align(struct sk_buff *skb, int align)
static int fs_enet_rx_napi(struct napi_struct *napi, int budget)
{
struct fs_enet_private *fep = container_of(napi, struct fs_enet_private, napi);
- struct net_device *dev = to_net_dev(fep->dev);
+ struct net_device *dev = fep->ndev;
const struct fs_platform_info *fpi = fep->fpi;
cbd_t __iomem *bdp;
struct sk_buff *skb, *skbn, *skbt;
@@ -217,7 +217,7 @@ static int fs_enet_rx_napi(struct napi_struct *napi, int budget)
fep->cur_rx = bdp;
- if (received >= budget) {
+ if (received < budget) {
/* done */
netif_rx_complete(dev, napi);
(*fep->ops->napi_enable_rx)(dev);
@@ -807,20 +807,23 @@ static int fs_enet_open(struct net_device *dev)
int r;
int err;
- napi_enable(&fep->napi);
+ if (fep->fpi->use_napi)
+ napi_enable(&fep->napi);
/* Install our interrupt handler. */
r = fs_request_irq(dev, fep->interrupt, "fs_enet-mac", fs_enet_interrupt);
if (r != 0) {
printk(KERN_ERR DRV_MODULE_NAME
": %s Could not allocate FS_ENET IRQ!", dev->name);
- napi_disable(&fep->napi);
+ if (fep->fpi->use_napi)
+ napi_disable(&fep->napi);
return -EINVAL;
}
err = fs_init_phy(dev);
- if(err) {
- napi_disable(&fep->napi);
+ if (err) {
+ if (fep->fpi->use_napi)
+ napi_disable(&fep->napi);
return err;
}
phy_start(fep->phydev);
@@ -1232,7 +1235,7 @@ static int __devinit fs_enet_probe(struct of_device *ofdev,
fpi->rx_ring = 32;
fpi->tx_ring = 32;
fpi->rx_copybreak = 240;
- fpi->use_napi = 0;
+ fpi->use_napi = 1;
fpi->napi_weight = 17;
ret = find_phy(ofdev->node, fpi);
@@ -1249,11 +1252,11 @@ static int __devinit fs_enet_probe(struct of_device *ofdev,
goto out_free_fpi;
}
- SET_MODULE_OWNER(ndev);
dev_set_drvdata(&ofdev->dev, ndev);
fep = netdev_priv(ndev);
fep->dev = &ofdev->dev;
+ fep->ndev = ndev;
fep->fpi = fpi;
fep->ops = match->data;
@@ -1288,10 +1291,11 @@ static int __devinit fs_enet_probe(struct of_device *ofdev,
ndev->stop = fs_enet_close;
ndev->get_stats = fs_enet_get_stats;
ndev->set_multicast_list = fs_set_multicast_list;
- if (fpi->use_napi) {
- ndev->poll = fs_enet_rx_napi;
- ndev->weight = fpi->napi_weight;
- }
+
+ if (fpi->use_napi)
+ netif_napi_add(ndev, &fep->napi, fs_enet_rx_napi,
+ fpi->napi_weight);
+
ndev->ethtool_ops = &fs_ethtool_ops;
ndev->do_ioctl = fs_ioctl;
diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/fs_enet/fs_enet.h
index baf6477165af..c675e29aadcc 100644
--- a/drivers/net/fs_enet/fs_enet.h
+++ b/drivers/net/fs_enet/fs_enet.h
@@ -75,6 +75,7 @@ struct phy_info {
struct fs_enet_private {
struct napi_struct napi;
struct device *dev; /* pointer back to the device (must be initialized first) */
+ struct net_device *ndev;
spinlock_t lock; /* during all ops except TX pckt processing */
spinlock_t tx_lock; /* during fs_start_xmit and fs_tx */
struct fs_platform_info *fpi;
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 0db5e6fabe73..38268d7335a8 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -168,7 +168,6 @@ static int gfar_probe(struct platform_device *pdev)
struct gfar_private *priv = NULL;
struct gianfar_platform_data *einfo;
struct resource *r;
- int idx;
int err = 0;
DECLARE_MAC_BUF(mac);
@@ -261,7 +260,9 @@ static int gfar_probe(struct platform_device *pdev)
dev->hard_start_xmit = gfar_start_xmit;
dev->tx_timeout = gfar_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
+#ifdef CONFIG_GFAR_NAPI
netif_napi_add(dev, &priv->napi, gfar_poll, GFAR_DEV_WEIGHT);
+#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = gfar_netpoll;
#endif
@@ -931,9 +932,14 @@ tx_skb_fail:
/* Returns 0 for success. */
static int gfar_enet_open(struct net_device *dev)
{
+#ifdef CONFIG_GFAR_NAPI
+ struct gfar_private *priv = netdev_priv(dev);
+#endif
int err;
+#ifdef CONFIG_GFAR_NAPI
napi_enable(&priv->napi);
+#endif
/* Initialize a bunch of registers */
init_registers(dev);
@@ -943,13 +949,19 @@ static int gfar_enet_open(struct net_device *dev)
err = init_phy(dev);
if(err) {
+#ifdef CONFIG_GFAR_NAPI
napi_disable(&priv->napi);
+#endif
return err;
}
err = startup_gfar(dev);
- if (err)
+ if (err) {
+#ifdef CONFIG_GFAR_NAPI
napi_disable(&priv->napi);
+#endif
+ return err;
+ }
netif_start_queue(dev);
@@ -1103,7 +1115,9 @@ static int gfar_close(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
+#ifdef CONFIG_GFAR_NAPI
napi_disable(&priv->napi);
+#endif
stop_gfar(dev);
@@ -1225,8 +1239,6 @@ static int gfar_change_mtu(struct net_device *dev, int new_mtu)
* starting over will fix the problem. */
static void gfar_timeout(struct net_device *dev)
{
- struct gfar_private *priv = netdev_priv(dev);
-
dev->stats.tx_errors++;
if (dev->flags & IFF_UP) {
@@ -1332,8 +1344,9 @@ struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp)
return skb;
}
-static inline void count_errors(unsigned short status, struct gfar_private *priv)
+static inline void count_errors(unsigned short status, struct net_device *dev)
{
+ struct gfar_private *priv = netdev_priv(dev);
struct net_device_stats *stats = &dev->stats;
struct gfar_extra_stats *estats = &priv->extra_stats;
@@ -1527,7 +1540,7 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
dev->stats.rx_bytes += pkt_len;
} else {
- count_errors(bdp->status, priv);
+ count_errors(bdp->status, dev);
if (skb)
dev_kfree_skb_any(skb);
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index c16cc8b946a9..46cd7735e6fe 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -749,7 +749,6 @@ struct gfar_private {
uint32_t msg_enable;
/* Network Statistics */
- struct net_device_stats stats;
struct gfar_extra_stats extra_stats;
};
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index ad9e327c3b03..580cb4ab2af1 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -3,7 +3,7 @@
* devices like TTY. It interfaces between a raw TTY and the
* kernel's AX.25 protocol layers.
*
- * Authors: Andreas Könsgen <ajk@iehk.rwth-aachen.de>
+ * Authors: Andreas Könsgen <ajk@iehk.rwth-aachen.de>
* Ralf Baechle DL5RB <ralf@linux-mips.org>
*
* Quite a lot of stuff "stolen" by Joerg Reuter from slip.c, written by
@@ -762,26 +762,20 @@ static int sixpack_ioctl(struct tty_struct *tty, struct file *file,
if (copy_from_user(&addr,
(void __user *) arg, AX25_ADDR_LEN)) {
- err = -EFAULT;
- break;
- }
+ err = -EFAULT;
+ break;
+ }
- netif_tx_lock_bh(dev);
- memcpy(dev->dev_addr, &addr, AX25_ADDR_LEN);
- netif_tx_unlock_bh(dev);
+ netif_tx_lock_bh(dev);
+ memcpy(dev->dev_addr, &addr, AX25_ADDR_LEN);
+ netif_tx_unlock_bh(dev);
- err = 0;
- break;
- }
-
- /* Allow stty to read, but not set, the serial port */
- case TCGETS:
- case TCGETA:
- err = n_tty_ioctl(tty, (struct file *) file, cmd, arg);
- break;
+ err = 0;
+ break;
+ }
default:
- err = -ENOIOCTLCMD;
+ err = tty_mode_ioctl(tty, file, cmd, arg);
}
sp_put(sp);
diff --git a/drivers/net/hamradio/Kconfig b/drivers/net/hamradio/Kconfig
index 36d2c7d4f4d0..62d5d5cfd6a6 100644
--- a/drivers/net/hamradio/Kconfig
+++ b/drivers/net/hamradio/Kconfig
@@ -64,7 +64,7 @@ config DMASCC
dmascc. If you don't pass any parameter to the driver, all
possible I/O addresses are probed. This could irritate other devices
that are currently not in use. You may specify the list of addresses
- to be probed by "dmascc=addr1,addr2,..." (when compiled into the
+ to be probed by "dmascc.io=addr1,addr2,..." (when compiled into the
kernel image) or "io=addr1,addr2,..." (when loaded as a module). The
network interfaces will be called dmascc0 and dmascc1 for the board
detected first, dmascc2 and dmascc3 for the second one, and so on.
diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c
index 1a5a75acf73e..dde9c7e6408a 100644
--- a/drivers/net/hamradio/baycom_epp.c
+++ b/drivers/net/hamradio/baycom_epp.c
@@ -325,12 +325,6 @@ static int eppconfig(struct baycom_state *bc)
/* ---------------------------------------------------------------------- */
-static void epp_interrupt(int irq, void *dev_id)
-{
-}
-
-/* ---------------------------------------------------------------------- */
-
static inline void do_kiss_params(struct baycom_state *bc,
unsigned char *data, unsigned long len)
{
@@ -871,7 +865,7 @@ static int epp_open(struct net_device *dev)
}
memset(&bc->modem, 0, sizeof(bc->modem));
bc->pdev = parport_register_device(pp, dev->name, NULL, epp_wakeup,
- epp_interrupt, PARPORT_DEV_EXCL, dev);
+ NULL, PARPORT_DEV_EXCL, dev);
parport_put_port(pp);
if (!bc->pdev) {
printk(KERN_ERR "%s: cannot register parport at 0x%lx\n", bc_drvname, pp->base);
diff --git a/drivers/net/hamradio/baycom_par.c b/drivers/net/hamradio/baycom_par.c
index 5930aeb35015..2e6fc4dc74b1 100644
--- a/drivers/net/hamradio/baycom_par.c
+++ b/drivers/net/hamradio/baycom_par.c
@@ -270,9 +270,9 @@ static __inline__ void par96_rx(struct net_device *dev, struct baycom_state *bc)
/* --------------------------------------------------------------------- */
-static void par96_interrupt(int irq, void *dev_id)
+static void par96_interrupt(void *dev_id)
{
- struct net_device *dev = (struct net_device *)dev_id;
+ struct net_device *dev = dev_id;
struct baycom_state *bc = netdev_priv(dev);
baycom_int_freq(bc);
diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
index bc02e4694804..11b83dae00ac 100644
--- a/drivers/net/hamradio/dmascc.c
+++ b/drivers/net/hamradio/dmascc.c
@@ -21,6 +21,7 @@
#include <linux/module.h>
+#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/if_arp.h>
@@ -35,7 +36,6 @@
#include <linux/sockios.h>
#include <linux/workqueue.h>
#include <asm/atomic.h>
-#include <asm/bitops.h>
#include <asm/dma.h>
#include <asm/io.h>
#include <asm/irq.h>
diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c
index e4fde17e2841..49421d1cd3a5 100644
--- a/drivers/net/hp100.c
+++ b/drivers/net/hp100.c
@@ -8,7 +8,7 @@
** Extended for new busmaster capable chipsets by
** Siegfried "Frieder" Loeffler (dg1sek) <floeff@mathematik.uni-stuttgart.de>
**
-** Maintained by: Jaroslav Kysela <perex@suse.cz>
+** Maintained by: Jaroslav Kysela <perex@perex.cz>
**
** This driver has only been tested with
** -- HP J2585B 10/100 Mbit/s PCI Busmaster
@@ -2951,7 +2951,7 @@ static struct pci_driver hp100_pci_driver = {
*/
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, "
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, "
"Siegfried \"Frieder\" Loeffler (dg1sek) <floeff@mathematik.uni-stuttgart.de>");
MODULE_DESCRIPTION("HP CASCADE Architecture Driver for 100VG-AnyLan Network Adapters");
diff --git a/drivers/net/ibm_emac/ibm_emac_mal.c b/drivers/net/ibm_emac/ibm_emac_mal.c
index 4e49e8c4f871..dcd8826fc749 100644
--- a/drivers/net/ibm_emac/ibm_emac_mal.c
+++ b/drivers/net/ibm_emac/ibm_emac_mal.c
@@ -413,7 +413,10 @@ static int __init mal_probe(struct ocp_device *ocpdev)
ocpdev->def->index);
return -ENOMEM;
}
- mal->dcrbase = maldata->dcr_base;
+
+ /* XXX This only works for native dcr for now */
+ mal->dcrhost = dcr_map(NULL, maldata->dcr_base, 0);
+
mal->def = ocpdev->def;
INIT_LIST_HEAD(&mal->poll_list);
diff --git a/drivers/net/ibm_emac/ibm_emac_mal.h b/drivers/net/ibm_emac/ibm_emac_mal.h
index 8f54d621994d..b8adbe6d4b01 100644
--- a/drivers/net/ibm_emac/ibm_emac_mal.h
+++ b/drivers/net/ibm_emac/ibm_emac_mal.h
@@ -191,7 +191,6 @@ struct mal_commac {
};
struct ibm_ocp_mal {
- int dcrbase;
dcr_host_t dcrhost;
struct list_head poll_list;
@@ -209,12 +208,12 @@ struct ibm_ocp_mal {
static inline u32 get_mal_dcrn(struct ibm_ocp_mal *mal, int reg)
{
- return dcr_read(mal->dcrhost, mal->dcrbase + reg);
+ return dcr_read(mal->dcrhost, reg);
}
static inline void set_mal_dcrn(struct ibm_ocp_mal *mal, int reg, u32 val)
{
- dcr_write(mal->dcrhost, mal->dcrbase + reg, val);
+ dcr_write(mal->dcrhost, reg, val);
}
/* Register MAL devices */
diff --git a/drivers/net/ibm_newemac/mal.c b/drivers/net/ibm_newemac/mal.c
index 58854117b1a9..9a88f71db004 100644
--- a/drivers/net/ibm_newemac/mal.c
+++ b/drivers/net/ibm_newemac/mal.c
@@ -45,6 +45,8 @@ int __devinit mal_register_commac(struct mal_instance *mal,
return -EBUSY;
}
+ if (list_empty(&mal->list))
+ napi_enable(&mal->napi);
mal->tx_chan_mask |= commac->tx_chan_mask;
mal->rx_chan_mask |= commac->rx_chan_mask;
list_add(&commac->list, &mal->list);
@@ -67,6 +69,8 @@ void __devexit mal_unregister_commac(struct mal_instance *mal,
mal->tx_chan_mask &= ~commac->tx_chan_mask;
mal->rx_chan_mask &= ~commac->rx_chan_mask;
list_del_init(&commac->list);
+ if (list_empty(&mal->list))
+ napi_disable(&mal->napi);
spin_unlock_irqrestore(&mal->lock, flags);
}
@@ -182,7 +186,7 @@ static inline void mal_enable_eob_irq(struct mal_instance *mal)
set_mal_dcrn(mal, MAL_CFG, get_mal_dcrn(mal, MAL_CFG) | MAL_CFG_EOPIE);
}
-/* synchronized by __LINK_STATE_RX_SCHED bit in ndev->state */
+/* synchronized by NAPI state */
static inline void mal_disable_eob_irq(struct mal_instance *mal)
{
// XXX might want to cache MAL_CFG as the DCR read can be slooooow
@@ -317,8 +321,8 @@ void mal_poll_disable(struct mal_instance *mal, struct mal_commac *commac)
while (test_and_set_bit(MAL_COMMAC_POLL_DISABLED, &commac->flags))
msleep(1);
- /* Synchronize with the MAL NAPI poller. */
- napi_disable(&mal->napi);
+ /* Synchronize with the MAL NAPI poller */
+ napi_synchronize(&mal->napi);
}
void mal_poll_enable(struct mal_instance *mal, struct mal_commac *commac)
@@ -326,7 +330,12 @@ void mal_poll_enable(struct mal_instance *mal, struct mal_commac *commac)
smp_wmb();
clear_bit(MAL_COMMAC_POLL_DISABLED, &commac->flags);
- // XXX might want to kick a poll now...
+ /* Feels better to trigger a poll here to catch up with events that
+ * may have happened on this channel while disabled. It will most
+ * probably be delayed until the next interrupt but that's mostly a
+ * non-issue in the context where this is called.
+ */
+ napi_schedule(&mal->napi);
}
static int mal_poll(struct napi_struct *napi, int budget)
@@ -336,8 +345,7 @@ static int mal_poll(struct napi_struct *napi, int budget)
int received = 0;
unsigned long flags;
- MAL_DBG2(mal, "poll(%d) %d ->" NL, *budget,
- rx_work_limit);
+ MAL_DBG2(mal, "poll(%d)" NL, budget);
again:
/* Process TX skbs */
list_for_each(l, &mal->poll_list) {
@@ -461,6 +469,7 @@ static int __devinit mal_probe(struct of_device *ofdev,
struct mal_instance *mal;
int err = 0, i, bd_size;
int index = mal_count++;
+ unsigned int dcr_base;
const u32 *prop;
u32 cfg;
@@ -497,14 +506,14 @@ static int __devinit mal_probe(struct of_device *ofdev,
}
mal->num_rx_chans = prop[0];
- mal->dcr_base = dcr_resource_start(ofdev->node, 0);
- if (mal->dcr_base == 0) {
+ dcr_base = dcr_resource_start(ofdev->node, 0);
+ if (dcr_base == 0) {
printk(KERN_ERR
"mal%d: can't find DCR resource!\n", index);
err = -ENODEV;
goto fail;
}
- mal->dcr_host = dcr_map(ofdev->node, mal->dcr_base, 0x100);
+ mal->dcr_host = dcr_map(ofdev->node, dcr_base, 0x100);
if (!DCR_MAP_OK(mal->dcr_host)) {
printk(KERN_ERR
"mal%d: failed to map DCRs !\n", index);
@@ -527,11 +536,12 @@ static int __devinit mal_probe(struct of_device *ofdev,
}
INIT_LIST_HEAD(&mal->poll_list);
- mal->napi.weight = CONFIG_IBM_NEW_EMAC_POLL_WEIGHT;
- mal->napi.poll = mal_poll;
INIT_LIST_HEAD(&mal->list);
spin_lock_init(&mal->lock);
+ netif_napi_add(NULL, &mal->napi, mal_poll,
+ CONFIG_IBM_NEW_EMAC_POLL_WEIGHT);
+
/* Load power-on reset defaults */
mal_reset(mal);
@@ -626,7 +636,7 @@ static int __devinit mal_probe(struct of_device *ofdev,
fail2:
dma_free_coherent(&ofdev->dev, bd_size, mal->bd_virt, mal->bd_dma);
fail_unmap:
- dcr_unmap(mal->dcr_host, mal->dcr_base, 0x100);
+ dcr_unmap(mal->dcr_host, 0x100);
fail:
kfree(mal);
diff --git a/drivers/net/ibm_newemac/mal.h b/drivers/net/ibm_newemac/mal.h
index cb1a16d589fe..784edb8ea822 100644
--- a/drivers/net/ibm_newemac/mal.h
+++ b/drivers/net/ibm_newemac/mal.h
@@ -185,7 +185,6 @@ struct mal_commac {
struct mal_instance {
int version;
- int dcr_base;
dcr_host_t dcr_host;
int num_tx_chans; /* Number of TX channels */
@@ -213,12 +212,12 @@ struct mal_instance {
static inline u32 get_mal_dcrn(struct mal_instance *mal, int reg)
{
- return dcr_read(mal->dcr_host, mal->dcr_base + reg);
+ return dcr_read(mal->dcr_host, reg);
}
static inline void set_mal_dcrn(struct mal_instance *mal, int reg, u32 val)
{
- dcr_write(mal->dcr_host, mal->dcr_base + reg, val);
+ dcr_write(mal->dcr_host, reg, val);
}
/* Register MAL devices */
diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c
index 68887235d7e9..dbd23bb65d1e 100644
--- a/drivers/net/ipg.c
+++ b/drivers/net/ipg.c
@@ -55,6 +55,26 @@ MODULE_DESCRIPTION("IC Plus IP1000 Gigabit Ethernet Adapter Linux Driver "
DrvVer);
MODULE_LICENSE("GPL");
+//variable record -- index by leading revision/length
+//Revision/Length(=N*4), Address1, Data1, Address2, Data2,...,AddressN,DataN
+static unsigned short DefaultPhyParam[] = {
+ // 11/12/03 IP1000A v1-3 rev=0x40
+ /*--------------------------------------------------------------------------
+ (0x4000|(15*4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 22, 0x85bd, 24, 0xfff2,
+ 27, 0x0c10, 28, 0x0c10, 29, 0x2c10, 31, 0x0003, 23, 0x92f6,
+ 31, 0x0000, 23, 0x003d, 30, 0x00de, 20, 0x20e7, 9, 0x0700,
+ --------------------------------------------------------------------------*/
+ // 12/17/03 IP1000A v1-4 rev=0x40
+ (0x4000 | (07 * 4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31,
+ 0x0000,
+ 30, 0x005e, 9, 0x0700,
+ // 01/09/04 IP1000A v1-5 rev=0x41
+ (0x4100 | (07 * 4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31,
+ 0x0000,
+ 30, 0x005e, 9, 0x0700,
+ 0x0000
+};
+
static const char *ipg_brand_name[] = {
"IC PLUS IP1000 1000/100/10 based NIC",
"Sundance Technology ST2021 based NIC",
@@ -990,7 +1010,7 @@ static void ipg_nic_txcleanup(struct net_device *dev)
}
/* Provides statistical information about the IPG NIC. */
-struct net_device_stats *ipg_nic_get_stats(struct net_device *dev)
+static struct net_device_stats *ipg_nic_get_stats(struct net_device *dev)
{
struct ipg_nic_private *sp = netdev_priv(dev);
void __iomem *ioaddr = sp->ioaddr;
diff --git a/drivers/net/ipg.h b/drivers/net/ipg.h
index e418b9035cac..d5d092c9d0af 100644
--- a/drivers/net/ipg.h
+++ b/drivers/net/ipg.h
@@ -833,24 +833,4 @@ struct ipg_nic_private {
struct delayed_work task;
};
-//variable record -- index by leading revision/length
-//Revision/Length(=N*4), Address1, Data1, Address2, Data2,...,AddressN,DataN
-unsigned short DefaultPhyParam[] = {
- // 11/12/03 IP1000A v1-3 rev=0x40
- /*--------------------------------------------------------------------------
- (0x4000|(15*4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 22, 0x85bd, 24, 0xfff2,
- 27, 0x0c10, 28, 0x0c10, 29, 0x2c10, 31, 0x0003, 23, 0x92f6,
- 31, 0x0000, 23, 0x003d, 30, 0x00de, 20, 0x20e7, 9, 0x0700,
- --------------------------------------------------------------------------*/
- // 12/17/03 IP1000A v1-4 rev=0x40
- (0x4000 | (07 * 4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31,
- 0x0000,
- 30, 0x005e, 9, 0x0700,
- // 01/09/04 IP1000A v1-5 rev=0x41
- (0x4100 | (07 * 4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31,
- 0x0000,
- 30, 0x005e, 9, 0x0700,
- 0x0000
-};
-
#endif /* __LINUX_IPG_H */
diff --git a/drivers/net/irda/actisys-sir.c b/drivers/net/irda/actisys-sir.c
index ccf6ec548a64..736d2473b7e1 100644
--- a/drivers/net/irda/actisys-sir.c
+++ b/drivers/net/irda/actisys-sir.c
@@ -21,7 +21,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
diff --git a/drivers/net/irda/actisys.c b/drivers/net/irda/actisys.c
index b2e31f4a384c..ae0b80a5680c 100644
--- a/drivers/net/irda/actisys.c
+++ b/drivers/net/irda/actisys.c
@@ -19,7 +19,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
diff --git a/drivers/net/irda/au1k_ir.c b/drivers/net/irda/au1k_ir.c
index 4dbdfaaf37bf..a1e4508717c8 100644
--- a/drivers/net/irda/au1k_ir.c
+++ b/drivers/net/irda/au1k_ir.c
@@ -627,19 +627,16 @@ static int au1k_irda_rx(struct net_device *dev)
}
-void au1k_irda_interrupt(int irq, void *dev_id)
+static irqreturn_t au1k_irda_interrupt(int dummy, void *dev_id)
{
- struct net_device *dev = (struct net_device *) dev_id;
-
- if (dev == NULL) {
- printk(KERN_ERR "%s: isr: null dev ptr\n", dev->name);
- return;
- }
+ struct net_device *dev = dev_id;
writel(0, IR_INT_CLEAR); /* ack irda interrupts */
au1k_irda_rx(dev);
au1k_tx_ack(dev);
+
+ return IRQ_HANDLED;
}
diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c
index 3e5eca1aa987..1257e1a7e819 100644
--- a/drivers/net/irda/donauboe.c
+++ b/drivers/net/irda/donauboe.c
@@ -595,7 +595,7 @@ toshoboe_startchip (struct toshoboe_cb *self)
OUTB ((physaddr >> 18) & 0xff, OBOE_RING_BASE1);
OUTB ((physaddr >> 26) & 0x3f, OBOE_RING_BASE2);
- /*Enable DMA controler in byte mode and RX */
+ /*Enable DMA controller in byte mode and RX */
OUTB (CONFIG0H_DMA_ON, OBOE_CONFIG0H);
/* Start up the clocks */
@@ -840,7 +840,7 @@ toshoboe_probe (struct toshoboe_cb *self)
/* test 1: SIR filter and back to back */
- for (j = 0; j < (sizeof (bauds) / sizeof (int)); ++j)
+ for (j = 0; j < ARRAY_SIZE(bauds); ++j)
{
int fir = (j > 1);
toshoboe_stopchip (self);
diff --git a/drivers/net/irda/girbil-sir.c b/drivers/net/irda/girbil-sir.c
index 0d2fe87fb9b7..738531b16bd3 100644
--- a/drivers/net/irda/girbil-sir.c
+++ b/drivers/net/irda/girbil-sir.c
@@ -16,7 +16,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
diff --git a/drivers/net/irda/girbil.c b/drivers/net/irda/girbil.c
index 248aeb0c726c..1f57391a618b 100644
--- a/drivers/net/irda/girbil.c
+++ b/drivers/net/irda/girbil.c
@@ -16,7 +16,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
diff --git a/drivers/net/irda/irport.h b/drivers/net/irda/irport.h
index 3f46b84c6c85..66fc2433e97d 100644
--- a/drivers/net/irda/irport.h
+++ b/drivers/net/irda/irport.h
@@ -17,7 +17,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c
index 6f5f697ec9f8..fc753d7f674e 100644
--- a/drivers/net/irda/irtty-sir.c
+++ b/drivers/net/irda/irtty-sir.c
@@ -20,7 +20,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
@@ -434,11 +434,6 @@ static int irtty_ioctl(struct tty_struct *tty, struct file *file, unsigned int c
IRDA_ASSERT(dev != NULL, return -1;);
switch (cmd) {
- case TCGETS:
- case TCGETA:
- err = n_tty_ioctl(tty, file, cmd, arg);
- break;
-
case IRTTY_IOCTDONGLE:
/* this call blocks for completion */
err = sirdev_set_dongle(dev, (IRDA_DONGLE) arg);
@@ -454,7 +449,7 @@ static int irtty_ioctl(struct tty_struct *tty, struct file *file, unsigned int c
err = -EFAULT;
break;
default:
- err = -ENOIOCTLCMD;
+ err = tty_mode_ioctl(tty, file, cmd, arg);
break;
}
return err;
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
index 12b9378c587f..a873d2b315ca 100644
--- a/drivers/net/irda/nsc-ircc.c
+++ b/drivers/net/irda/nsc-ircc.c
@@ -20,7 +20,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
diff --git a/drivers/net/irda/nsc-ircc.h b/drivers/net/irda/nsc-ircc.h
index dacf671abcd6..bbdc97ff83ca 100644
--- a/drivers/net/irda/nsc-ircc.h
+++ b/drivers/net/irda/nsc-ircc.h
@@ -19,7 +19,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
index 55ff0fbe525a..8c09344f58dc 100644
--- a/drivers/net/irda/pxaficp_ir.c
+++ b/drivers/net/irda/pxaficp_ir.c
@@ -23,6 +23,7 @@
#include <linux/dma-mapping.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
+#include <linux/clk.h>
#include <net/irda/irda.h>
#include <net/irda/irmod.h>
@@ -87,8 +88,30 @@ struct pxa_irda {
struct device *dev;
struct pxaficp_platform_data *pdata;
+ struct clk *fir_clk;
+ struct clk *sir_clk;
+ struct clk *cur_clk;
};
+static inline void pxa_irda_disable_clk(struct pxa_irda *si)
+{
+ if (si->cur_clk)
+ clk_disable(si->cur_clk);
+ si->cur_clk = NULL;
+}
+
+static inline void pxa_irda_enable_firclk(struct pxa_irda *si)
+{
+ si->cur_clk = si->fir_clk;
+ clk_enable(si->fir_clk);
+}
+
+static inline void pxa_irda_enable_sirclk(struct pxa_irda *si)
+{
+ si->cur_clk = si->sir_clk;
+ clk_enable(si->sir_clk);
+}
+
#define IS_FIR(si) ((si)->speed >= 4000000)
#define IRDA_FRAME_SIZE_LIMIT 2047
@@ -134,7 +157,7 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed)
DCSR(si->rxdma) &= ~DCSR_RUN;
/* disable FICP */
ICCR0 = 0;
- pxa_set_cken(CKEN_FICP, 0);
+ pxa_irda_disable_clk(si);
/* set board transceiver to SIR mode */
si->pdata->transceiver_mode(si->dev, IR_SIRMODE);
@@ -144,7 +167,7 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed)
pxa_gpio_mode(GPIO47_STTXD_MD);
/* enable the STUART clock */
- pxa_set_cken(CKEN_STUART, 1);
+ pxa_irda_enable_sirclk(si);
}
/* disable STUART first */
@@ -169,7 +192,7 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed)
/* disable STUART */
STIER = 0;
STISR = 0;
- pxa_set_cken(CKEN_STUART, 0);
+ pxa_irda_disable_clk(si);
/* disable FICP first */
ICCR0 = 0;
@@ -182,7 +205,7 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed)
pxa_gpio_mode(GPIO47_ICPTXD_MD);
/* enable the FICP clock */
- pxa_set_cken(CKEN_FICP, 1);
+ pxa_irda_enable_firclk(si);
si->speed = speed;
pxa_irda_fir_dma_rx_start(si);
@@ -592,16 +615,15 @@ static void pxa_irda_shutdown(struct pxa_irda *si)
STIER = 0;
/* disable STUART SIR mode */
STISR = 0;
- /* disable the STUART clock */
- pxa_set_cken(CKEN_STUART, 0);
/* disable DMA */
DCSR(si->txdma) &= ~DCSR_RUN;
DCSR(si->rxdma) &= ~DCSR_RUN;
/* disable FICP */
ICCR0 = 0;
- /* disable the FICP clock */
- pxa_set_cken(CKEN_FICP, 0);
+
+ /* disable the STUART or FICP clocks */
+ pxa_irda_disable_clk(si);
DRCMR17 = 0;
DRCMR18 = 0;
@@ -792,6 +814,13 @@ static int pxa_irda_probe(struct platform_device *pdev)
si->dev = &pdev->dev;
si->pdata = pdev->dev.platform_data;
+ si->sir_clk = clk_get(&pdev->dev, "UARTCLK");
+ si->fir_clk = clk_get(&pdev->dev, "FICPCLK");
+ if (IS_ERR(si->sir_clk) || IS_ERR(si->fir_clk)) {
+ err = PTR_ERR(IS_ERR(si->sir_clk) ? si->sir_clk : si->fir_clk);
+ goto err_mem_4;
+ }
+
/*
* Initialise the SIR buffers
*/
@@ -831,6 +860,10 @@ static int pxa_irda_probe(struct platform_device *pdev)
err_mem_5:
kfree(si->rx_buff.head);
err_mem_4:
+ if (si->sir_clk && !IS_ERR(si->sir_clk))
+ clk_put(si->sir_clk);
+ if (si->fir_clk && !IS_ERR(si->fir_clk))
+ clk_put(si->fir_clk);
free_netdev(dev);
err_mem_3:
release_mem_region(__PREG(FICP), 0x1c);
@@ -850,6 +883,8 @@ static int pxa_irda_remove(struct platform_device *_dev)
unregister_netdev(dev);
kfree(si->tx_buff.head);
kfree(si->rx_buff.head);
+ clk_put(si->fir_clk);
+ clk_put(si->sir_clk);
free_netdev(dev);
}
diff --git a/drivers/net/irda/tekram-sir.c b/drivers/net/irda/tekram-sir.c
index 0dd6bc7af3f2..d1ce5ae6a172 100644
--- a/drivers/net/irda/tekram-sir.c
+++ b/drivers/net/irda/tekram-sir.c
@@ -18,7 +18,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
diff --git a/drivers/net/irda/tekram.c b/drivers/net/irda/tekram.c
index 8f6258221cb0..9bfd2441adbf 100644
--- a/drivers/net/irda/tekram.c
+++ b/drivers/net/irda/tekram.c
@@ -16,7 +16,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
diff --git a/drivers/net/irda/w83977af_ir.h b/drivers/net/irda/w83977af_ir.h
index 0b7661deafee..87c3975baf62 100644
--- a/drivers/net/irda/w83977af_ir.h
+++ b/drivers/net/irda/w83977af_ir.h
@@ -16,7 +16,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h
index 1eee8894c732..3d2e7217e9af 100644
--- a/drivers/net/ixgb/ixgb.h
+++ b/drivers/net/ixgb/ixgb.h
@@ -196,4 +196,11 @@ struct ixgb_adapter {
uint32_t alloc_rx_buff_failed;
boolean_t have_msi;
};
+
+/* Exported from other modules */
+extern void ixgb_check_options(struct ixgb_adapter *adapter);
+extern void ixgb_set_ethtool_ops(struct net_device *netdev);
+extern char ixgb_driver_name[];
+extern const char ixgb_driver_version[];
+
#endif /* _IXGB_H_ */
diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c
index fddd5844168d..a267dd862520 100644
--- a/drivers/net/ixgb/ixgb_ethtool.c
+++ b/drivers/net/ixgb/ixgb_ethtool.c
@@ -32,9 +32,6 @@
#include <asm/uaccess.h>
-extern char ixgb_driver_name[];
-extern char ixgb_driver_version[];
-
extern int ixgb_up(struct ixgb_adapter *adapter);
extern void ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog);
extern void ixgb_reset(struct ixgb_adapter *adapter);
@@ -639,8 +636,8 @@ ixgb_phys_id(struct net_device *netdev, uint32_t data)
{
struct ixgb_adapter *adapter = netdev_priv(netdev);
- if(!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ))
- data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ);
+ if (!data)
+ data = INT_MAX;
if(!adapter->blink_timer.function) {
init_timer(&adapter->blink_timer);
diff --git a/drivers/net/ixgb/ixgb_hw.c b/drivers/net/ixgb/ixgb_hw.c
index ecbf45861c68..2c6367ace3cd 100644
--- a/drivers/net/ixgb/ixgb_hw.c
+++ b/drivers/net/ixgb/ixgb_hw.c
@@ -1174,7 +1174,7 @@ mac_addr_valid(uint8_t *mac_addr)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-boolean_t
+static boolean_t
ixgb_link_reset(struct ixgb_hw *hw)
{
boolean_t link_status = FALSE;
@@ -1205,7 +1205,7 @@ ixgb_link_reset(struct ixgb_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-void
+static void
ixgb_optics_reset(struct ixgb_hw *hw)
{
if (hw->phy_type == ixgb_phy_type_txn17401) {
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index d444de58ba34..3021234b1e17 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -37,8 +37,8 @@ static char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver";
#define DRIVERNAPI "-NAPI"
#endif
#define DRV_VERSION "1.0.126-k2"DRIVERNAPI
-char ixgb_driver_version[] = DRV_VERSION;
-static char ixgb_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
+const char ixgb_driver_version[] = DRV_VERSION;
+static const char ixgb_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
/* ixgb_pci_tbl - PCI Device ID Table
*
@@ -104,7 +104,6 @@ static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter,
static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter);
#endif
static void ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter);
-void ixgb_set_ethtool_ops(struct net_device *netdev);
static void ixgb_tx_timeout(struct net_device *dev);
static void ixgb_tx_timeout_task(struct work_struct *work);
static void ixgb_vlan_rx_register(struct net_device *netdev,
@@ -123,9 +122,6 @@ static pci_ers_result_t ixgb_io_error_detected (struct pci_dev *pdev,
static pci_ers_result_t ixgb_io_slot_reset (struct pci_dev *pdev);
static void ixgb_io_resume (struct pci_dev *pdev);
-/* Exported from other modules */
-extern void ixgb_check_options(struct ixgb_adapter *adapter);
-
static struct pci_error_handlers ixgb_err_handler = {
.error_detected = ixgb_io_error_detected,
.slot_reset = ixgb_io_slot_reset,
@@ -1085,7 +1081,8 @@ ixgb_set_multi(struct net_device *netdev)
rctl |= IXGB_RCTL_MPE;
IXGB_WRITE_REG(hw, RCTL, rctl);
} else {
- uint8_t mta[netdev->mc_count * IXGB_ETH_LENGTH_OF_ADDRESS];
+ uint8_t mta[IXGB_MAX_NUM_MULTICAST_ADDRESSES *
+ IXGB_ETH_LENGTH_OF_ADDRESS];
IXGB_WRITE_REG(hw, RCTL, rctl);
@@ -1324,8 +1321,8 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb,
/* Workaround for premature desc write-backs
* in TSO mode. Append 4-byte sentinel desc */
- if (unlikely(mss && !nr_frags && size == len
- && size > 8))
+ if (unlikely(mss && (f == (nr_frags - 1))
+ && size == len && size > 8))
size -= 4;
buffer_info->length = size;
diff --git a/drivers/net/ixgb/ixgb_param.c b/drivers/net/ixgb/ixgb_param.c
index 5d5ddabf4360..865d14d6e5a7 100644
--- a/drivers/net/ixgb/ixgb_param.c
+++ b/drivers/net/ixgb/ixgb_param.c
@@ -44,10 +44,11 @@
*/
#define IXGB_PARAM_INIT { [0 ... IXGB_MAX_NIC] = OPTION_UNSET }
-#define IXGB_PARAM(X, desc) \
- static int __devinitdata X[IXGB_MAX_NIC+1] = IXGB_PARAM_INIT; \
- static int num_##X = 0; \
- module_param_array_named(X, X, int, &num_##X, 0); \
+#define IXGB_PARAM(X, desc) \
+ static int __devinitdata X[IXGB_MAX_NIC+1] \
+ = IXGB_PARAM_INIT; \
+ static unsigned int num_##X = 0; \
+ module_param_array_named(X, X, int, &num_##X, 0); \
MODULE_PARM_DESC(X, desc);
/* Transmit Descriptor Count
@@ -178,8 +179,8 @@ IXGB_PARAM(IntDelayEnable, "Transmit Interrupt Delay Enable");
struct ixgb_option {
enum { enable_option, range_option, list_option } type;
- char *name;
- char *err;
+ const char *name;
+ const char *err;
int def;
union {
struct { /* range_option info */
@@ -197,7 +198,7 @@ struct ixgb_option {
};
static int __devinit
-ixgb_validate_option(int *value, struct ixgb_option *opt)
+ixgb_validate_option(unsigned int *value, const struct ixgb_option *opt)
{
if(*value == OPTION_UNSET) {
*value = opt->def;
@@ -266,7 +267,7 @@ ixgb_check_options(struct ixgb_adapter *adapter)
}
{ /* Transmit Descriptor Count */
- struct ixgb_option opt = {
+ const struct ixgb_option opt = {
.type = range_option,
.name = "Transmit Descriptors",
.err = "using default of " __MODULE_STRING(DEFAULT_TXD),
@@ -285,7 +286,7 @@ ixgb_check_options(struct ixgb_adapter *adapter)
tx_ring->count = ALIGN(tx_ring->count, IXGB_REQ_TX_DESCRIPTOR_MULTIPLE);
}
{ /* Receive Descriptor Count */
- struct ixgb_option opt = {
+ const struct ixgb_option opt = {
.type = range_option,
.name = "Receive Descriptors",
.err = "using default of " __MODULE_STRING(DEFAULT_RXD),
@@ -304,7 +305,7 @@ ixgb_check_options(struct ixgb_adapter *adapter)
rx_ring->count = ALIGN(rx_ring->count, IXGB_REQ_RX_DESCRIPTOR_MULTIPLE);
}
{ /* Receive Checksum Offload Enable */
- struct ixgb_option opt = {
+ const struct ixgb_option opt = {
.type = enable_option,
.name = "Receive Checksum Offload",
.err = "defaulting to Enabled",
@@ -312,7 +313,7 @@ ixgb_check_options(struct ixgb_adapter *adapter)
};
if(num_XsumRX > bd) {
- int rx_csum = XsumRX[bd];
+ unsigned int rx_csum = XsumRX[bd];
ixgb_validate_option(&rx_csum, &opt);
adapter->rx_csum = rx_csum;
} else {
@@ -328,7 +329,7 @@ ixgb_check_options(struct ixgb_adapter *adapter)
{ ixgb_fc_full, "Flow Control Enabled" },
{ ixgb_fc_default, "Flow Control Hardware Default" }};
- struct ixgb_option opt = {
+ const struct ixgb_option opt = {
.type = list_option,
.name = "Flow Control",
.err = "reading default settings from EEPROM",
@@ -338,7 +339,7 @@ ixgb_check_options(struct ixgb_adapter *adapter)
};
if(num_FlowControl > bd) {
- int fc = FlowControl[bd];
+ unsigned int fc = FlowControl[bd];
ixgb_validate_option(&fc, &opt);
adapter->hw.fc.type = fc;
} else {
@@ -346,7 +347,7 @@ ixgb_check_options(struct ixgb_adapter *adapter)
}
}
{ /* Receive Flow Control High Threshold */
- struct ixgb_option opt = {
+ const struct ixgb_option opt = {
.type = range_option,
.name = "Rx Flow Control High Threshold",
.err = "using default of " __MODULE_STRING(DEFAULT_FCRTH),
@@ -366,7 +367,7 @@ ixgb_check_options(struct ixgb_adapter *adapter)
"Ignoring RxFCHighThresh when no RxFC\n");
}
{ /* Receive Flow Control Low Threshold */
- struct ixgb_option opt = {
+ const struct ixgb_option opt = {
.type = range_option,
.name = "Rx Flow Control Low Threshold",
.err = "using default of " __MODULE_STRING(DEFAULT_FCRTL),
@@ -386,7 +387,7 @@ ixgb_check_options(struct ixgb_adapter *adapter)
"Ignoring RxFCLowThresh when no RxFC\n");
}
{ /* Flow Control Pause Time Request*/
- struct ixgb_option opt = {
+ const struct ixgb_option opt = {
.type = range_option,
.name = "Flow Control Pause Time Request",
.err = "using default of "__MODULE_STRING(DEFAULT_FCPAUSE),
@@ -396,7 +397,7 @@ ixgb_check_options(struct ixgb_adapter *adapter)
};
if(num_FCReqTimeout > bd) {
- int pause_time = FCReqTimeout[bd];
+ unsigned int pause_time = FCReqTimeout[bd];
ixgb_validate_option(&pause_time, &opt);
adapter->hw.fc.pause_time = pause_time;
} else {
@@ -419,7 +420,7 @@ ixgb_check_options(struct ixgb_adapter *adapter)
}
}
{ /* Receive Interrupt Delay */
- struct ixgb_option opt = {
+ const struct ixgb_option opt = {
.type = range_option,
.name = "Receive Interrupt Delay",
.err = "using default of " __MODULE_STRING(DEFAULT_RDTR),
@@ -436,7 +437,7 @@ ixgb_check_options(struct ixgb_adapter *adapter)
}
}
{ /* Transmit Interrupt Delay */
- struct ixgb_option opt = {
+ const struct ixgb_option opt = {
.type = range_option,
.name = "Transmit Interrupt Delay",
.err = "using default of " __MODULE_STRING(DEFAULT_TIDV),
@@ -454,7 +455,7 @@ ixgb_check_options(struct ixgb_adapter *adapter)
}
{ /* Transmit Interrupt Delay Enable */
- struct ixgb_option opt = {
+ const struct ixgb_option opt = {
.type = enable_option,
.name = "Tx Interrupt Delay Enable",
.err = "defaulting to Enabled",
@@ -462,7 +463,7 @@ ixgb_check_options(struct ixgb_adapter *adapter)
};
if(num_IntDelayEnable > bd) {
- int ide = IntDelayEnable[bd];
+ unsigned int ide = IntDelayEnable[bd];
ixgb_validate_option(&ide, &opt);
adapter->tx_int_delay_enable = ide;
} else {
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
index c160a7d91e21..bc51432b8d26 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ixgbe/ixgbe.h
@@ -244,7 +244,7 @@ extern struct ixgbe_info ixgbe_82598EB_info;
extern struct ixgbe_info ixgbe_82598AT_info;
extern char ixgbe_driver_name[];
-extern char ixgbe_driver_version[];
+extern const char ixgbe_driver_version[];
extern int ixgbe_up(struct ixgbe_adapter *adapter);
extern void ixgbe_down(struct ixgbe_adapter *adapter);
diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c
index 00ee20125ca9..4d64673164ca 100644
--- a/drivers/net/ixgbe/ixgbe_82598.c
+++ b/drivers/net/ixgbe/ixgbe_82598.c
@@ -30,8 +30,7 @@
#include <linux/delay.h>
#include <linux/sched.h>
-#include "ixgbe_type.h"
-#include "ixgbe_common.h"
+#include "ixgbe.h"
#include "ixgbe_phy.h"
#define IXGBE_82598_MAX_TX_QUEUES 32
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index b75f1c6efc42..00bc525c6560 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -45,12 +45,13 @@
#include "ixgbe_common.h"
char ixgbe_driver_name[] = "ixgbe";
-static char ixgbe_driver_string[] =
- "Intel(R) 10 Gigabit PCI Express Network Driver";
+static const char ixgbe_driver_string[] =
+ "Intel(R) 10 Gigabit PCI Express Network Driver";
#define DRV_VERSION "1.1.18"
-char ixgbe_driver_version[] = DRV_VERSION;
-static char ixgbe_copyright[] = "Copyright (c) 1999-2007 Intel Corporation.";
+const char ixgbe_driver_version[] = DRV_VERSION;
+static const char ixgbe_copyright[] =
+ "Copyright (c) 1999-2007 Intel Corporation.";
static const struct ixgbe_info *ixgbe_info_tbl[] = {
[board_82598AF] = &ixgbe_82598AF_info,
diff --git a/drivers/net/jazzsonic.c b/drivers/net/jazzsonic.c
index d3825c8ee994..5c154fe13859 100644
--- a/drivers/net/jazzsonic.c
+++ b/drivers/net/jazzsonic.c
@@ -208,7 +208,6 @@ static int __init jazz_sonic_probe(struct platform_device *pdev)
struct sonic_local *lp;
struct resource *res;
int err = 0;
- int i;
DECLARE_MAC_BUF(mac);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/drivers/net/lguest_net.c b/drivers/net/lguest_net.c
deleted file mode 100644
index abce2ee8430a..000000000000
--- a/drivers/net/lguest_net.c
+++ /dev/null
@@ -1,555 +0,0 @@
-/*D:500
- * The Guest network driver.
- *
- * This is very simple a virtual network driver, and our last Guest driver.
- * The only trick is that it can talk directly to multiple other recipients
- * (ie. other Guests on the same network). It can also be used with only the
- * Host on the network.
- :*/
-
-/* Copyright 2006 Rusty Russell <rusty@rustcorp.com.au> IBM Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-//#define DEBUG
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/module.h>
-#include <linux/mm_types.h>
-#include <linux/io.h>
-#include <linux/lguest_bus.h>
-
-#define SHARED_SIZE PAGE_SIZE
-#define MAX_LANS 4
-#define NUM_SKBS 8
-
-/*M:011 Network code master Jeff Garzik points out numerous shortcomings in
- * this driver if it aspires to greatness.
- *
- * Firstly, it doesn't use "NAPI": the networking's New API, and is poorer for
- * it. As he says "NAPI means system-wide load leveling, across multiple
- * network interfaces. Lack of NAPI can mean competition at higher loads."
- *
- * He also points out that we don't implement set_mac_address, so users cannot
- * change the devices hardware address. When I asked why one would want to:
- * "Bonding, and situations where you /do/ want the MAC address to "leak" out
- * of the host onto the wider net."
- *
- * Finally, he would like module unloading: "It is not unrealistic to think of
- * [un|re|]loading the net support module in an lguest guest. And, adding
- * module support makes the programmer more responsible, because they now have
- * to learn to clean up after themselves. Any driver that cannot clean up
- * after itself is an incomplete driver in my book."
- :*/
-
-/*D:530 The "struct lguestnet_info" contains all the information we need to
- * know about the network device. */
-struct lguestnet_info
-{
- /* The mapped device page(s) (an array of "struct lguest_net"). */
- struct lguest_net *peer;
- /* The physical address of the device page(s) */
- unsigned long peer_phys;
- /* The size of the device page(s). */
- unsigned long mapsize;
-
- /* The lguest_device I come from */
- struct lguest_device *lgdev;
-
- /* My peerid (ie. my slot in the array). */
- unsigned int me;
-
- /* Receive queue: the network packets waiting to be filled. */
- struct sk_buff *skb[NUM_SKBS];
- struct lguest_dma dma[NUM_SKBS];
-};
-/*:*/
-
-/* How many bytes left in this page. */
-static unsigned int rest_of_page(void *data)
-{
- return PAGE_SIZE - ((unsigned long)data % PAGE_SIZE);
-}
-
-/*D:570 Each peer (ie. Guest or Host) on the network binds their receive
- * buffers to a different key: we simply use the physical address of the
- * device's memory page plus the peer number. The Host insists that all keys
- * be a multiple of 4, so we multiply the peer number by 4. */
-static unsigned long peer_key(struct lguestnet_info *info, unsigned peernum)
-{
- return info->peer_phys + 4 * peernum;
-}
-
-/* This is the routine which sets up a "struct lguest_dma" to point to a
- * network packet, similar to req_to_dma() in lguest_blk.c. The structure of a
- * "struct sk_buff" has grown complex over the years: it consists of a "head"
- * linear section pointed to by "skb->data", and possibly an array of
- * "fragments" in the case of a non-linear packet.
- *
- * Our receive buffers don't use fragments at all but outgoing skbs might, so
- * we handle it. */
-static void skb_to_dma(const struct sk_buff *skb, unsigned int headlen,
- struct lguest_dma *dma)
-{
- unsigned int i, seg;
-
- /* First, we put the linear region into the "struct lguest_dma". Each
- * entry can't go over a page boundary, so even though all our packets
- * are 1514 bytes or less, we might need to use two entries here: */
- for (i = seg = 0; i < headlen; seg++, i += rest_of_page(skb->data+i)) {
- dma->addr[seg] = virt_to_phys(skb->data + i);
- dma->len[seg] = min((unsigned)(headlen - i),
- rest_of_page(skb->data + i));
- }
-
- /* Now we handle the fragments: at least they're guaranteed not to go
- * over a page. skb_shinfo(skb) returns a pointer to the structure
- * which tells us about the number of fragments and the fragment
- * array. */
- for (i = 0; i < skb_shinfo(skb)->nr_frags; i++, seg++) {
- const skb_frag_t *f = &skb_shinfo(skb)->frags[i];
- /* Should not happen with MTU less than 64k - 2 * PAGE_SIZE. */
- if (seg == LGUEST_MAX_DMA_SECTIONS) {
- /* We will end up sending a truncated packet should
- * this ever happen. Plus, a cool log message! */
- printk("Woah dude! Megapacket!\n");
- break;
- }
- dma->addr[seg] = page_to_phys(f->page) + f->page_offset;
- dma->len[seg] = f->size;
- }
-
- /* If after all that we didn't use the entire "struct lguest_dma"
- * array, we terminate it with a 0 length. */
- if (seg < LGUEST_MAX_DMA_SECTIONS)
- dma->len[seg] = 0;
-}
-
-/*
- * Packet transmission.
- *
- * Our packet transmission is a little unusual. A real network card would just
- * send out the packet and leave the receivers to decide if they're interested.
- * Instead, we look through the network device memory page and see if any of
- * the ethernet addresses match the packet destination, and if so we send it to
- * that Guest.
- *
- * This is made a little more complicated in two cases. The first case is
- * broadcast packets: for that we send the packet to all Guests on the network,
- * one at a time. The second case is "promiscuous" mode, where a Guest wants
- * to see all the packets on the network. We need a way for the Guest to tell
- * us it wants to see all packets, so it sets the "multicast" bit on its
- * published MAC address, which is never valid in a real ethernet address.
- */
-#define PROMISC_BIT 0x01
-
-/* This is the callback which is summoned whenever the network device's
- * multicast or promiscuous state changes. If the card is in promiscuous mode,
- * we advertise that in our ethernet address in the device's memory. We do the
- * same if Linux wants any or all multicast traffic. */
-static void lguestnet_set_multicast(struct net_device *dev)
-{
- struct lguestnet_info *info = netdev_priv(dev);
-
- if ((dev->flags & (IFF_PROMISC|IFF_ALLMULTI)) || dev->mc_count)
- info->peer[info->me].mac[0] |= PROMISC_BIT;
- else
- info->peer[info->me].mac[0] &= ~PROMISC_BIT;
-}
-
-/* A simple test function to see if a peer wants to see all packets.*/
-static int promisc(struct lguestnet_info *info, unsigned int peer)
-{
- return info->peer[peer].mac[0] & PROMISC_BIT;
-}
-
-/* Another simple function to see if a peer's advertised ethernet address
- * matches a packet's destination ethernet address. */
-static int mac_eq(const unsigned char mac[ETH_ALEN],
- struct lguestnet_info *info, unsigned int peer)
-{
- /* Ignore multicast bit, which peer turns on to mean promisc. */
- if ((info->peer[peer].mac[0] & (~PROMISC_BIT)) != mac[0])
- return 0;
- return memcmp(mac+1, info->peer[peer].mac+1, ETH_ALEN-1) == 0;
-}
-
-/* This is the function which actually sends a packet once we've decided a
- * peer wants it: */
-static void transfer_packet(struct net_device *dev,
- struct sk_buff *skb,
- unsigned int peernum)
-{
- struct lguestnet_info *info = netdev_priv(dev);
- struct lguest_dma dma;
-
- /* We use our handy "struct lguest_dma" packing function to prepare
- * the skb for sending. */
- skb_to_dma(skb, skb_headlen(skb), &dma);
- pr_debug("xfer length %04x (%u)\n", htons(skb->len), skb->len);
-
- /* This is the actual send call which copies the packet. */
- lguest_send_dma(peer_key(info, peernum), &dma);
-
- /* Check that the entire packet was transmitted. If not, it could mean
- * that the other Guest registered a short receive buffer, but this
- * driver should never do that. More likely, the peer is dead. */
- if (dma.used_len != skb->len) {
- dev->stats.tx_carrier_errors++;
- pr_debug("Bad xfer to peer %i: %i of %i (dma %p/%i)\n",
- peernum, dma.used_len, skb->len,
- (void *)dma.addr[0], dma.len[0]);
- } else {
- /* On success we update the stats. */
- dev->stats.tx_bytes += skb->len;
- dev->stats.tx_packets++;
- }
-}
-
-/* Another helper function to tell is if a slot in the device memory is unused.
- * Since we always set the Local Assignment bit in the ethernet address, the
- * first byte can never be 0. */
-static int unused_peer(const struct lguest_net peer[], unsigned int num)
-{
- return peer[num].mac[0] == 0;
-}
-
-/* Finally, here is the routine which handles an outgoing packet. It's called
- * "start_xmit" for traditional reasons. */
-static int lguestnet_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- unsigned int i;
- int broadcast;
- struct lguestnet_info *info = netdev_priv(dev);
- /* Extract the destination ethernet address from the packet. */
- const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest;
- DECLARE_MAC_BUF(mac);
-
- pr_debug("%s: xmit %s\n", dev->name, print_mac(mac, dest));
-
- /* If it's a multicast packet, we broadcast to everyone. That's not
- * very efficient, but there are very few applications which actually
- * use multicast, which is a shame really.
- *
- * As etherdevice.h points out: "By definition the broadcast address is
- * also a multicast address." So we don't have to test for broadcast
- * packets separately. */
- broadcast = is_multicast_ether_addr(dest);
-
- /* Look through all the published ethernet addresses to see if we
- * should send this packet. */
- for (i = 0; i < info->mapsize/sizeof(struct lguest_net); i++) {
- /* We don't send to ourselves (we actually can't SEND_DMA to
- * ourselves anyway), and don't send to unused slots.*/
- if (i == info->me || unused_peer(info->peer, i))
- continue;
-
- /* If it's broadcast we send it. If they want every packet we
- * send it. If the destination matches their address we send
- * it. Otherwise we go to the next peer. */
- if (!broadcast && !promisc(info, i) && !mac_eq(dest, info, i))
- continue;
-
- pr_debug("lguestnet %s: sending from %i to %i\n",
- dev->name, info->me, i);
- /* Our routine which actually does the transfer. */
- transfer_packet(dev, skb, i);
- }
-
- /* An xmit routine is expected to dispose of the packet, so we do. */
- dev_kfree_skb(skb);
-
- /* As per kernel convention, 0 means success. This is why I love
- * networking: even if we never sent to anyone, that's still
- * success! */
- return 0;
-}
-
-/*D:560
- * Packet receiving.
- *
- * First, here's a helper routine which fills one of our array of receive
- * buffers: */
-static int fill_slot(struct net_device *dev, unsigned int slot)
-{
- struct lguestnet_info *info = netdev_priv(dev);
-
- /* We can receive ETH_DATA_LEN (1500) byte packets, plus a standard
- * ethernet header of ETH_HLEN (14) bytes. */
- info->skb[slot] = netdev_alloc_skb(dev, ETH_HLEN + ETH_DATA_LEN);
- if (!info->skb[slot]) {
- printk("%s: could not fill slot %i\n", dev->name, slot);
- return -ENOMEM;
- }
-
- /* skb_to_dma() is a helper which sets up the "struct lguest_dma" to
- * point to the data in the skb: we also use it for sending out a
- * packet. */
- skb_to_dma(info->skb[slot], ETH_HLEN + ETH_DATA_LEN, &info->dma[slot]);
-
- /* This is a Write Memory Barrier: it ensures that the entry in the
- * receive buffer array is written *before* we set the "used_len" entry
- * to 0. If the Host were looking at the receive buffer array from a
- * different CPU, it could potentially see "used_len = 0" and not see
- * the updated receive buffer information. This would be a horribly
- * nasty bug, so make sure the compiler and CPU know this has to happen
- * first. */
- wmb();
- /* Writing 0 to "used_len" tells the Host it can use this receive
- * buffer now. */
- info->dma[slot].used_len = 0;
- return 0;
-}
-
-/* This is the actual receive routine. When we receive an interrupt from the
- * Host to tell us a packet has been delivered, we arrive here: */
-static irqreturn_t lguestnet_rcv(int irq, void *dev_id)
-{
- struct net_device *dev = dev_id;
- struct lguestnet_info *info = netdev_priv(dev);
- unsigned int i, done = 0;
-
- /* Look through our entire receive array for an entry which has data
- * in it. */
- for (i = 0; i < ARRAY_SIZE(info->dma); i++) {
- unsigned int length;
- struct sk_buff *skb;
-
- length = info->dma[i].used_len;
- if (length == 0)
- continue;
-
- /* We've found one! Remember the skb (we grabbed the length
- * above), and immediately refill the slot we've taken it
- * from. */
- done++;
- skb = info->skb[i];
- fill_slot(dev, i);
-
- /* This shouldn't happen: micropackets could be sent by a
- * badly-behaved Guest on the network, but the Host will never
- * stuff more data in the buffer than the buffer length. */
- if (length < ETH_HLEN || length > ETH_HLEN + ETH_DATA_LEN) {
- pr_debug(KERN_WARNING "%s: unbelievable skb len: %i\n",
- dev->name, length);
- dev_kfree_skb(skb);
- continue;
- }
-
- /* skb_put(), what a great function! I've ranted about this
- * function before (http://lkml.org/lkml/1999/9/26/24). You
- * call it after you've added data to the end of an skb (in
- * this case, it was the Host which wrote the data). */
- skb_put(skb, length);
-
- /* The ethernet header contains a protocol field: we use the
- * standard helper to extract it, and place the result in
- * skb->protocol. The helper also sets up skb->pkt_type and
- * eats up the ethernet header from the front of the packet. */
- skb->protocol = eth_type_trans(skb, dev);
-
- /* If this device doesn't need checksums for sending, we also
- * don't need to check the packets when they come in. */
- if (dev->features & NETIF_F_NO_CSUM)
- skb->ip_summed = CHECKSUM_UNNECESSARY;
-
- /* As a last resort for debugging the driver or the lguest I/O
- * subsystem, you can uncomment the "#define DEBUG" at the top
- * of this file, which turns all the pr_debug() into printk()
- * and floods the logs. */
- pr_debug("Receiving skb proto 0x%04x len %i type %i\n",
- ntohs(skb->protocol), skb->len, skb->pkt_type);
-
- /* Update the packet and byte counts (visible from ifconfig,
- * and good for debugging). */
- dev->stats.rx_bytes += skb->len;
- dev->stats.rx_packets++;
-
- /* Hand our fresh network packet into the stack's "network
- * interface receive" routine. That will free the packet
- * itself when it's finished. */
- netif_rx(skb);
- }
-
- /* If we found any packets, we assume the interrupt was for us. */
- return done ? IRQ_HANDLED : IRQ_NONE;
-}
-
-/*D:550 This is where we start: when the device is brought up by dhcpd or
- * ifconfig. At this point we advertise our MAC address to the rest of the
- * network, and register receive buffers ready for incoming packets. */
-static int lguestnet_open(struct net_device *dev)
-{
- int i;
- struct lguestnet_info *info = netdev_priv(dev);
-
- /* Copy our MAC address into the device page, so others on the network
- * can find us. */
- memcpy(info->peer[info->me].mac, dev->dev_addr, ETH_ALEN);
-
- /* We might already be in promisc mode (dev->flags & IFF_PROMISC). Our
- * set_multicast callback handles this already, so we call it now. */
- lguestnet_set_multicast(dev);
-
- /* Allocate packets and put them into our "struct lguest_dma" array.
- * If we fail to allocate all the packets we could still limp along,
- * but it's a sign of real stress so we should probably give up now. */
- for (i = 0; i < ARRAY_SIZE(info->dma); i++) {
- if (fill_slot(dev, i) != 0)
- goto cleanup;
- }
-
- /* Finally we tell the Host where our array of "struct lguest_dma"
- * receive buffers is, binding it to the key corresponding to the
- * device's physical memory plus our peerid. */
- if (lguest_bind_dma(peer_key(info,info->me), info->dma,
- NUM_SKBS, lgdev_irq(info->lgdev)) != 0)
- goto cleanup;
- return 0;
-
-cleanup:
- while (--i >= 0)
- dev_kfree_skb(info->skb[i]);
- return -ENOMEM;
-}
-/*:*/
-
-/* The close routine is called when the device is no longer in use: we clean up
- * elegantly. */
-static int lguestnet_close(struct net_device *dev)
-{
- unsigned int i;
- struct lguestnet_info *info = netdev_priv(dev);
-
- /* Clear all trace of our existence out of the device memory by setting
- * the slot which held our MAC address to 0 (unused). */
- memset(&info->peer[info->me], 0, sizeof(info->peer[info->me]));
-
- /* Unregister our array of receive buffers */
- lguest_unbind_dma(peer_key(info, info->me), info->dma);
- for (i = 0; i < ARRAY_SIZE(info->dma); i++)
- dev_kfree_skb(info->skb[i]);
- return 0;
-}
-
-/*D:510 The network device probe function is basically a standard ethernet
- * device setup. It reads the "struct lguest_device_desc" and sets the "struct
- * net_device". Oh, the line-by-line excitement! Let's skip over it. :*/
-static int lguestnet_probe(struct lguest_device *lgdev)
-{
- int err, irqf = IRQF_SHARED;
- struct net_device *dev;
- struct lguestnet_info *info;
- struct lguest_device_desc *desc = &lguest_devices[lgdev->index];
-
- pr_debug("lguest_net: probing for device %i\n", lgdev->index);
-
- dev = alloc_etherdev(sizeof(struct lguestnet_info));
- if (!dev)
- return -ENOMEM;
-
- /* Ethernet defaults with some changes */
- ether_setup(dev);
- dev->set_mac_address = NULL;
-
- dev->dev_addr[0] = 0x02; /* set local assignment bit (IEEE802) */
- dev->dev_addr[1] = 0x00;
- memcpy(&dev->dev_addr[2], &lguest_data.guestid, 2);
- dev->dev_addr[4] = 0x00;
- dev->dev_addr[5] = 0x00;
-
- dev->open = lguestnet_open;
- dev->stop = lguestnet_close;
- dev->hard_start_xmit = lguestnet_start_xmit;
-
- /* We don't actually support multicast yet, but turning on/off
- * promisc also calls dev->set_multicast_list. */
- dev->set_multicast_list = lguestnet_set_multicast;
- SET_NETDEV_DEV(dev, &lgdev->dev);
-
- /* The network code complains if you have "scatter-gather" capability
- * if you don't also handle checksums (it seem that would be
- * "illogical"). So we use a lie of omission and don't tell it that we
- * can handle scattered packets unless we also don't want checksums,
- * even though to us they're completely independent. */
- if (desc->features & LGUEST_NET_F_NOCSUM)
- dev->features = NETIF_F_SG|NETIF_F_NO_CSUM;
-
- info = netdev_priv(dev);
- info->mapsize = PAGE_SIZE * desc->num_pages;
- info->peer_phys = ((unsigned long)desc->pfn << PAGE_SHIFT);
- info->lgdev = lgdev;
- info->peer = lguest_map(info->peer_phys, desc->num_pages);
- if (!info->peer) {
- err = -ENOMEM;
- goto free;
- }
-
- /* This stores our peerid (upper bits reserved for future). */
- info->me = (desc->features & (info->mapsize-1));
-
- err = register_netdev(dev);
- if (err) {
- pr_debug("lguestnet: registering device failed\n");
- goto unmap;
- }
-
- if (lguest_devices[lgdev->index].features & LGUEST_DEVICE_F_RANDOMNESS)
- irqf |= IRQF_SAMPLE_RANDOM;
- if (request_irq(lgdev_irq(lgdev), lguestnet_rcv, irqf, "lguestnet",
- dev) != 0) {
- pr_debug("lguestnet: cannot get irq %i\n", lgdev_irq(lgdev));
- goto unregister;
- }
-
- pr_debug("lguestnet: registered device %s\n", dev->name);
- /* Finally, we put the "struct net_device" in the generic "struct
- * lguest_device"s private pointer. Again, it's not necessary, but
- * makes sure the cool kernel kids don't tease us. */
- lgdev->private = dev;
- return 0;
-
-unregister:
- unregister_netdev(dev);
-unmap:
- lguest_unmap(info->peer);
-free:
- free_netdev(dev);
- return err;
-}
-
-static struct lguest_driver lguestnet_drv = {
- .name = "lguestnet",
- .owner = THIS_MODULE,
- .device_type = LGUEST_DEVICE_T_NET,
- .probe = lguestnet_probe,
-};
-
-static __init int lguestnet_init(void)
-{
- return register_lguest_driver(&lguestnet_drv);
-}
-module_init(lguestnet_init);
-
-MODULE_DESCRIPTION("Lguest network driver");
-MODULE_LICENSE("GPL");
-
-/*D:580
- * This is the last of the Drivers, and with this we have covered the many and
- * wonderous and fine (and boring) details of the Guest.
- *
- * "make Launcher" beckons, where we answer questions like "Where do Guests
- * come from?", and "What do you do when someone asks for optimization?"
- */
diff --git a/drivers/net/lib82596.c b/drivers/net/lib82596.c
index ffaa14f2cd01..9a855e512147 100644
--- a/drivers/net/lib82596.c
+++ b/drivers/net/lib82596.c
@@ -1124,12 +1124,6 @@ static irqreturn_t i596_interrupt(int irq, void *dev_id)
struct i596_dma *dma;
unsigned short status, ack_cmd = 0;
- if (dev == NULL) {
- printk(KERN_WARNING "%s: irq %d for unknown device.\n",
- __FUNCTION__, irq);
- return IRQ_NONE;
- }
-
lp = netdev_priv(dev);
dma = lp->dma;
@@ -1140,7 +1134,7 @@ static irqreturn_t i596_interrupt(int irq, void *dev_id)
DEB(DEB_INTS, printk(KERN_DEBUG
"%s: i596 interrupt, IRQ %d, status %4.4x.\n",
- dev->name, irq, status));
+ dev->name, dev->irq, status));
ack_cmd = status & 0xf000;
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index be25aa33971c..662b8d16803c 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -265,17 +265,16 @@ static __net_init int loopback_net_init(struct net *net)
if (err)
goto out_free_netdev;
- err = 0;
net->loopback_dev = dev;
+ return 0;
-out:
- if (err)
- panic("loopback: Failed to register netdevice: %d\n", err);
- return err;
out_free_netdev:
free_netdev(dev);
- goto out;
+out:
+ if (net == &init_net)
+ panic("loopback: Failed to register netdevice: %d\n", err);
+ return err;
}
static __net_exit void loopback_net_exit(struct net *net)
diff --git a/drivers/net/mac89x0.c b/drivers/net/mac89x0.c
index 30854f094965..a19b5958cee9 100644
--- a/drivers/net/mac89x0.c
+++ b/drivers/net/mac89x0.c
@@ -99,9 +99,9 @@ static char *version =
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/delay.h>
+#include <linux/bitops.h>
#include <asm/system.h>
-#include <asm/bitops.h>
#include <asm/io.h>
#include <asm/hwtest.h>
#include <asm/macints.h>
diff --git a/drivers/net/meth.c b/drivers/net/meth.c
index e25dbab67363..0c89b028a80c 100644
--- a/drivers/net/meth.c
+++ b/drivers/net/meth.c
@@ -33,7 +33,6 @@
#include <asm/ip32/ip32_ints.h>
#include <asm/io.h>
-#include <asm/scatterlist.h>
#include "meth.h"
diff --git a/drivers/net/meth.h b/drivers/net/meth.h
index ea3b8fc86d1e..a78dc1ca8c29 100644
--- a/drivers/net/meth.h
+++ b/drivers/net/meth.h
@@ -28,9 +28,6 @@
#define RX_BUFFER_OFFSET (sizeof(rx_status_vector)+2) /* staus vector + 2 bytes of padding */
#define RX_BUCKET_SIZE 256
-#undef BIT
-#define BIT(x) (1UL << (x))
-
/* For more detailed explanations of what each field menas,
see Nick's great comments to #defines below (or docs, if
you are lucky enough toget hold of them :)*/
diff --git a/drivers/net/mipsnet.c b/drivers/net/mipsnet.c
index d593175ab6f0..aafc3ce59cbb 100644
--- a/drivers/net/mipsnet.c
+++ b/drivers/net/mipsnet.c
@@ -7,12 +7,12 @@
#define DEBUG
#include <linux/init.h>
+#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/platform_device.h>
-#include <asm/io.h>
#include <asm/mips-boards/simint.h>
#include "mipsnet.h" /* actual device IO mapping */
@@ -30,12 +30,12 @@ static int ioiocpy_frommipsnet(struct net_device *dev, unsigned char *kdata,
int len)
{
uint32_t available_len = inl(mipsnet_reg_address(dev, rxDataCount));
+
if (available_len < len)
return -EFAULT;
- for (; len > 0; len--, kdata++) {
+ for (; len > 0; len--, kdata++)
*kdata = inb(mipsnet_reg_address(dev, rxDataBuffer));
- }
return inl(mipsnet_reg_address(dev, rxDataCount));
}
@@ -46,17 +46,10 @@ static inline ssize_t mipsnet_put_todevice(struct net_device *dev,
int count_to_go = skb->len;
char *buf_ptr = skb->data;
- pr_debug("%s: %s(): telling MIPSNET txDataCount(%d)\n",
- dev->name, __FUNCTION__, skb->len);
-
outl(skb->len, mipsnet_reg_address(dev, txDataCount));
- pr_debug("%s: %s(): sending data to MIPSNET txDataBuffer(%d)\n",
- dev->name, __FUNCTION__, skb->len);
-
- for (; count_to_go; buf_ptr++, count_to_go--) {
+ for (; count_to_go; buf_ptr++, count_to_go--)
outb(*buf_ptr, mipsnet_reg_address(dev, txDataBuffer));
- }
dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len;
@@ -66,10 +59,8 @@ static inline ssize_t mipsnet_put_todevice(struct net_device *dev,
static int mipsnet_xmit(struct sk_buff *skb, struct net_device *dev)
{
- pr_debug("%s:%s(): transmitting %d bytes\n",
- dev->name, __FUNCTION__, skb->len);
-
- /* Only one packet at a time. Once TXDONE interrupt is serviced, the
+ /*
+ * Only one packet at a time. Once TXDONE interrupt is serviced, the
* queue will be restarted.
*/
netif_stop_queue(dev);
@@ -83,7 +74,8 @@ static inline ssize_t mipsnet_get_fromdev(struct net_device *dev, size_t count)
struct sk_buff *skb;
size_t len = count;
- if (!(skb = alloc_skb(len + 2, GFP_KERNEL))) {
+ skb = alloc_skb(len + 2, GFP_KERNEL);
+ if (!skb) {
dev->stats.rx_dropped++;
return -ENOMEM;
}
@@ -95,8 +87,6 @@ static inline ssize_t mipsnet_get_fromdev(struct net_device *dev, size_t count)
skb->protocol = eth_type_trans(skb, dev);
skb->ip_summed = CHECKSUM_UNNECESSARY;
- pr_debug("%s:%s(): pushing RXed data to kernel\n",
- dev->name, __FUNCTION__);
netif_rx(skb);
dev->stats.rx_packets++;
@@ -113,43 +103,30 @@ static irqreturn_t mipsnet_interrupt(int irq, void *dev_id)
uint64_t interruptFlags;
if (irq == dev->irq) {
- pr_debug("%s:%s(): irq %d for device\n",
- dev->name, __FUNCTION__, irq);
-
retval = IRQ_HANDLED;
interruptFlags =
inl(mipsnet_reg_address(dev, interruptControl));
- pr_debug("%s:%s(): intCtl=0x%016llx\n", dev->name,
- __FUNCTION__, interruptFlags);
if (interruptFlags & MIPSNET_INTCTL_TXDONE) {
- pr_debug("%s:%s(): got TXDone\n",
- dev->name, __FUNCTION__);
outl(MIPSNET_INTCTL_TXDONE,
mipsnet_reg_address(dev, interruptControl));
- // only one packet at a time, we are done.
+ /* only one packet at a time, we are done. */
netif_wake_queue(dev);
} else if (interruptFlags & MIPSNET_INTCTL_RXDONE) {
- pr_debug("%s:%s(): got RX data\n",
- dev->name, __FUNCTION__);
mipsnet_get_fromdev(dev,
- inl(mipsnet_reg_address(dev, rxDataCount)));
- pr_debug("%s:%s(): clearing RX int\n",
- dev->name, __FUNCTION__);
+ inl(mipsnet_reg_address(dev, rxDataCount)));
outl(MIPSNET_INTCTL_RXDONE,
mipsnet_reg_address(dev, interruptControl));
} else if (interruptFlags & MIPSNET_INTCTL_TESTBIT) {
- pr_debug("%s:%s(): got test interrupt\n",
- dev->name, __FUNCTION__);
- // TESTBIT is cleared on read.
- // And takes effect after a write with 0
+ /*
+ * TESTBIT is cleared on read.
+ * And takes effect after a write with 0
+ */
outl(0, mipsnet_reg_address(dev, interruptControl));
} else {
- pr_debug("%s:%s(): no valid fags 0x%016llx\n",
- dev->name, __FUNCTION__, interruptFlags);
- // Maybe shared IRQ, just ignore, no clearing.
+ /* Maybe shared IRQ, just ignore, no clearing. */
retval = IRQ_NONE;
}
@@ -159,30 +136,23 @@ static irqreturn_t mipsnet_interrupt(int irq, void *dev_id)
retval = IRQ_NONE;
}
return retval;
-} //mipsnet_interrupt()
+}
static int mipsnet_open(struct net_device *dev)
{
int err;
- pr_debug("%s: mipsnet_open\n", dev->name);
err = request_irq(dev->irq, &mipsnet_interrupt,
IRQF_SHARED, dev->name, (void *) dev);
if (err) {
- pr_debug("%s: %s(): can't get irq %d\n",
- dev->name, __FUNCTION__, dev->irq);
release_region(dev->base_addr, MIPSNET_IO_EXTENT);
return err;
}
- pr_debug("%s: %s(): got IO region at 0x%04lx and irq %d for dev.\n",
- dev->name, __FUNCTION__, dev->base_addr, dev->irq);
-
-
netif_start_queue(dev);
- // test interrupt handler
+ /* test interrupt handler */
outl(MIPSNET_INTCTL_TESTBIT,
mipsnet_reg_address(dev, interruptControl));
@@ -192,15 +162,13 @@ static int mipsnet_open(struct net_device *dev)
static int mipsnet_close(struct net_device *dev)
{
- pr_debug("%s: %s()\n", dev->name, __FUNCTION__);
netif_stop_queue(dev);
+
return 0;
}
static void mipsnet_set_mclist(struct net_device *dev)
{
- // we don't do anything
- return;
}
static int __init mipsnet_probe(struct device *dev)
@@ -226,13 +194,10 @@ static int __init mipsnet_probe(struct device *dev)
*/
netdev->base_addr = 0x4200;
netdev->irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_MB0 +
- inl(mipsnet_reg_address(netdev, interruptInfo));
+ inl(mipsnet_reg_address(netdev, interruptInfo));
- // Get the io region now, get irq on open()
+ /* Get the io region now, get irq on open() */
if (!request_region(netdev->base_addr, MIPSNET_IO_EXTENT, "mipsnet")) {
- pr_debug("%s: %s(): IO region {start: 0x%04lux, len: %d} "
- "for dev is not availble.\n", netdev->name,
- __FUNCTION__, netdev->base_addr, MIPSNET_IO_EXTENT);
err = -EBUSY;
goto out_free_netdev;
}
@@ -296,8 +261,6 @@ static int __init mipsnet_init_module(void)
static void __exit mipsnet_exit_module(void)
{
- pr_debug("MIPSNet Ethernet driver exiting\n");
-
driver_unregister(&mipsnet_driver);
}
diff --git a/drivers/net/mipsnet.h b/drivers/net/mipsnet.h
index 026c732024c9..0132c6714a40 100644
--- a/drivers/net/mipsnet.h
+++ b/drivers/net/mipsnet.h
@@ -9,32 +9,34 @@
/*
* Id of this Net device, as seen by the core.
*/
-#define MIPS_NET_DEV_ID ((uint64_t) \
- ((uint64_t)'M'<< 0)| \
- ((uint64_t)'I'<< 8)| \
- ((uint64_t)'P'<<16)| \
- ((uint64_t)'S'<<24)| \
- ((uint64_t)'N'<<32)| \
- ((uint64_t)'E'<<40)| \
- ((uint64_t)'T'<<48)| \
- ((uint64_t)'0'<<56))
+#define MIPS_NET_DEV_ID ((uint64_t) \
+ ((uint64_t) 'M' << 0)| \
+ ((uint64_t) 'I' << 8)| \
+ ((uint64_t) 'P' << 16)| \
+ ((uint64_t) 'S' << 24)| \
+ ((uint64_t) 'N' << 32)| \
+ ((uint64_t) 'E' << 40)| \
+ ((uint64_t) 'T' << 48)| \
+ ((uint64_t) '0' << 56))
/*
* Net status/control block as seen by sw in the core.
* (Why not use bit fields? can't be bothered with cross-platform struct
* packing.)
*/
-typedef struct _net_control_block {
- /// dev info for probing
- /// reads as MIPSNET%d where %d is some form of version
- uint64_t devId; /*0x00 */
+struct net_control_block {
+ /*
+ * dev info for probing
+ * reads as MIPSNET%d where %d is some form of version
+ */
+ uint64_t devId; /* 0x00 */
/*
* read only busy flag.
* Set and cleared by the Net Device to indicate that an rx or a tx
* is in progress.
*/
- uint32_t busy; /*0x08 */
+ uint32_t busy; /* 0x08 */
/*
* Set by the Net Device.
@@ -43,16 +45,16 @@ typedef struct _net_control_block {
* rxDataBuffer. The value will decrease till 0 until all the data
* from rxDataBuffer has been read.
*/
- uint32_t rxDataCount; /*0x0c */
+ uint32_t rxDataCount; /* 0x0c */
#define MIPSNET_MAX_RXTX_DATACOUNT (1<<16)
/*
- * Settable from the MIPS core, cleared by the Net Device.
- * The core should set the number of bytes it wants to send,
- * then it should write those bytes of data to txDataBuffer.
- * The device will clear txDataCount has been processed (not necessarily sent).
+ * Settable from the MIPS core, cleared by the Net Device. The core
+ * should set the number of bytes it wants to send, then it should
+ * write those bytes of data to txDataBuffer. The device will clear
+ * txDataCount has been processed (not necessarily sent).
*/
- uint32_t txDataCount; /*0x10 */
+ uint32_t txDataCount; /* 0x10 */
/*
* Interrupt control
@@ -69,39 +71,42 @@ typedef struct _net_control_block {
* To clear the test interrupt, write 0 to this register.
*/
uint32_t interruptControl; /*0x14 */
-#define MIPSNET_INTCTL_TXDONE ((uint32_t)(1<< 0))
-#define MIPSNET_INTCTL_RXDONE ((uint32_t)(1<< 1))
-#define MIPSNET_INTCTL_TESTBIT ((uint32_t)(1<<31))
-#define MIPSNET_INTCTL_ALLSOURCES (MIPSNET_INTCTL_TXDONE|MIPSNET_INTCTL_RXDONE|MIPSNET_INTCTL_TESTBIT)
+#define MIPSNET_INTCTL_TXDONE ((uint32_t)(1 << 0))
+#define MIPSNET_INTCTL_RXDONE ((uint32_t)(1 << 1))
+#define MIPSNET_INTCTL_TESTBIT ((uint32_t)(1 << 31))
+#define MIPSNET_INTCTL_ALLSOURCES (MIPSNET_INTCTL_TXDONE | \
+ MIPSNET_INTCTL_RXDONE | \
+ MIPSNET_INTCTL_TESTBIT)
/*
- * Readonly core-specific interrupt info for the device to signal the core.
- * The meaning of the contents of this field might change.
- */
- /*###\todo: the whole memIntf interrupt scheme is messy: the device should have
- * no control what so ever of what VPE/register set is being used.
- * The MemIntf should only expose interrupt lines, and something in the
- * config should be responsible for the line<->core/vpe bindings.
+ * Readonly core-specific interrupt info for the device to signal the
+ * core. The meaning of the contents of this field might change.
+ *
+ * TODO: the whole memIntf interrupt scheme is messy: the device should
+ * have no control what so ever of what VPE/register set is being
+ * used. The MemIntf should only expose interrupt lines, and
+ * something in the config should be responsible for the
+ * line<->core/vpe bindings.
*/
- uint32_t interruptInfo; /*0x18 */
+ uint32_t interruptInfo; /* 0x18 */
/*
* This is where the received data is read out.
* There is more data to read until rxDataReady is 0.
* Only 1 byte at this regs offset is used.
*/
- uint32_t rxDataBuffer; /*0x1c */
+ uint32_t rxDataBuffer; /* 0x1c */
/*
- * This is where the data to transmit is written.
- * Data should be written for the amount specified in the txDataCount register.
- * Only 1 byte at this regs offset is used.
+ * This is where the data to transmit is written. Data should be
+ * written for the amount specified in the txDataCount register. Only
+ * 1 byte at this regs offset is used.
*/
- uint32_t txDataBuffer; /*0x20 */
-} MIPS_T_NetControl;
+ uint32_t txDataBuffer; /* 0x20 */
+};
#define MIPSNET_IO_EXTENT 0x40 /* being generous */
-#define field_offset(field) ((int)&((MIPS_T_NetControl*)(0))->field)
+#define field_offset(field) (offsetof(struct net_control_block, field))
#endif /* __MIPSNET_H */
diff --git a/drivers/net/mlx4/alloc.c b/drivers/net/mlx4/alloc.c
index f8d63d39f592..b226e019bc8b 100644
--- a/drivers/net/mlx4/alloc.c
+++ b/drivers/net/mlx4/alloc.c
@@ -171,9 +171,10 @@ void mlx4_buf_free(struct mlx4_dev *dev, int size, struct mlx4_buf *buf)
buf->u.direct.map);
else {
for (i = 0; i < buf->nbufs; ++i)
- dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
- buf->u.page_list[i].buf,
- buf->u.page_list[i].map);
+ if (buf->u.page_list[i].buf)
+ dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
+ buf->u.page_list[i].buf,
+ buf->u.page_list[i].map);
kfree(buf->u.page_list);
}
}
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index 6471d33afb7d..50648738d679 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -736,7 +736,7 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
MLX4_PUT(inbox, (u8) (PAGE_SHIFT - 12), INIT_HCA_UAR_PAGE_SZ_OFFSET);
MLX4_PUT(inbox, param->log_uar_sz, INIT_HCA_LOG_UAR_SZ_OFFSET);
- err = mlx4_cmd(dev, mailbox->dma, 0, 0, MLX4_CMD_INIT_HCA, 1000);
+ err = mlx4_cmd(dev, mailbox->dma, 0, 0, MLX4_CMD_INIT_HCA, 10000);
if (err)
mlx4_err(dev, "INIT_HCA returns %d\n", err);
diff --git a/drivers/net/mlx4/icm.c b/drivers/net/mlx4/icm.c
index 4b3c109d5eae..2a5bef6388fe 100644
--- a/drivers/net/mlx4/icm.c
+++ b/drivers/net/mlx4/icm.c
@@ -60,7 +60,7 @@ static void mlx4_free_icm_pages(struct mlx4_dev *dev, struct mlx4_icm_chunk *chu
PCI_DMA_BIDIRECTIONAL);
for (i = 0; i < chunk->npages; ++i)
- __free_pages(chunk->mem[i].page,
+ __free_pages(sg_page(&chunk->mem[i]),
get_order(chunk->mem[i].length));
}
@@ -70,7 +70,7 @@ static void mlx4_free_icm_coherent(struct mlx4_dev *dev, struct mlx4_icm_chunk *
for (i = 0; i < chunk->npages; ++i)
dma_free_coherent(&dev->pdev->dev, chunk->mem[i].length,
- lowmem_page_address(chunk->mem[i].page),
+ lowmem_page_address(sg_page(&chunk->mem[i])),
sg_dma_address(&chunk->mem[i]));
}
@@ -95,12 +95,13 @@ void mlx4_free_icm(struct mlx4_dev *dev, struct mlx4_icm *icm, int coherent)
static int mlx4_alloc_icm_pages(struct scatterlist *mem, int order, gfp_t gfp_mask)
{
- mem->page = alloc_pages(gfp_mask, order);
- if (!mem->page)
+ struct page *page;
+
+ page = alloc_pages(gfp_mask, order);
+ if (!page)
return -ENOMEM;
- mem->length = PAGE_SIZE << order;
- mem->offset = 0;
+ sg_set_page(mem, page, PAGE_SIZE << order, 0);
return 0;
}
@@ -145,6 +146,7 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages,
if (!chunk)
goto fail;
+ sg_init_table(chunk->mem, MLX4_ICM_CHUNK_LEN);
chunk->npages = 0;
chunk->nsg = 0;
list_add_tail(&chunk->list, &icm->chunk_list);
@@ -334,7 +336,7 @@ void *mlx4_table_find(struct mlx4_icm_table *table, int obj, dma_addr_t *dma_han
* been assigned to.
*/
if (chunk->mem[i].length > offset) {
- page = chunk->mem[i].page;
+ page = sg_page(&chunk->mem[i]);
goto out;
}
offset -= chunk->mem[i].length;
diff --git a/drivers/net/mlx4/qp.c b/drivers/net/mlx4/qp.c
index cc4b1be18219..42b47639c81c 100644
--- a/drivers/net/mlx4/qp.c
+++ b/drivers/net/mlx4/qp.c
@@ -240,7 +240,7 @@ void mlx4_qp_free(struct mlx4_dev *dev, struct mlx4_qp *qp)
mlx4_table_put(dev, &qp_table->auxc_table, qp->qpn);
mlx4_table_put(dev, &qp_table->qp_table, qp->qpn);
- if (qp->qpn < dev->caps.sqp_start + 8)
+ if (qp->qpn >= dev->caps.sqp_start + 8)
mlx4_bitmap_free(&qp_table->bitmap, qp->qpn);
}
EXPORT_SYMBOL_GPL(mlx4_qp_free);
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 84f2d6382f1e..651c2699d5e1 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -1,5 +1,5 @@
/*
- * drivers/net/mv643xx_eth.c - Driver for MV643XX ethernet ports
+ * Driver for Marvell Discovery (MV643XX) and Marvell Orion ethernet ports
* Copyright (C) 2002 Matthew Dharm <mdharm@momenco.com>
*
* Based on the 64360 driver from:
@@ -43,14 +43,567 @@
#include <linux/ethtool.h>
#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/mii.h>
+
+#include <linux/mv643xx_eth.h>
+
#include <asm/io.h>
#include <asm/types.h>
#include <asm/pgtable.h>
#include <asm/system.h>
#include <asm/delay.h>
-#include "mv643xx_eth.h"
+#include <asm/dma-mapping.h>
+
+#define MV643XX_CHECKSUM_OFFLOAD_TX
+#define MV643XX_NAPI
+#define MV643XX_TX_FAST_REFILL
+#undef MV643XX_COAL
+
+/*
+ * Number of RX / TX descriptors on RX / TX rings.
+ * Note that allocating RX descriptors is done by allocating the RX
+ * ring AND a preallocated RX buffers (skb's) for each descriptor.
+ * The TX descriptors only allocates the TX descriptors ring,
+ * with no pre allocated TX buffers (skb's are allocated by higher layers.
+ */
+
+/* Default TX ring size is 1000 descriptors */
+#define MV643XX_DEFAULT_TX_QUEUE_SIZE 1000
+
+/* Default RX ring size is 400 descriptors */
+#define MV643XX_DEFAULT_RX_QUEUE_SIZE 400
+
+#define MV643XX_TX_COAL 100
+#ifdef MV643XX_COAL
+#define MV643XX_RX_COAL 100
+#endif
+
+#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
+#define MAX_DESCS_PER_SKB (MAX_SKB_FRAGS + 1)
+#else
+#define MAX_DESCS_PER_SKB 1
+#endif
+
+#define ETH_VLAN_HLEN 4
+#define ETH_FCS_LEN 4
+#define ETH_HW_IP_ALIGN 2 /* hw aligns IP header */
+#define ETH_WRAPPER_LEN (ETH_HW_IP_ALIGN + ETH_HLEN + \
+ ETH_VLAN_HLEN + ETH_FCS_LEN)
+#define ETH_RX_SKB_SIZE (dev->mtu + ETH_WRAPPER_LEN + \
+ dma_get_cache_alignment())
+
+/*
+ * Registers shared between all ports.
+ */
+#define PHY_ADDR_REG 0x0000
+#define SMI_REG 0x0004
+
+/*
+ * Per-port registers.
+ */
+#define PORT_CONFIG_REG(p) (0x0400 + ((p) << 10))
+#define PORT_CONFIG_EXTEND_REG(p) (0x0404 + ((p) << 10))
+#define MAC_ADDR_LOW(p) (0x0414 + ((p) << 10))
+#define MAC_ADDR_HIGH(p) (0x0418 + ((p) << 10))
+#define SDMA_CONFIG_REG(p) (0x041c + ((p) << 10))
+#define PORT_SERIAL_CONTROL_REG(p) (0x043c + ((p) << 10))
+#define PORT_STATUS_REG(p) (0x0444 + ((p) << 10))
+#define TRANSMIT_QUEUE_COMMAND_REG(p) (0x0448 + ((p) << 10))
+#define MAXIMUM_TRANSMIT_UNIT(p) (0x0458 + ((p) << 10))
+#define INTERRUPT_CAUSE_REG(p) (0x0460 + ((p) << 10))
+#define INTERRUPT_CAUSE_EXTEND_REG(p) (0x0464 + ((p) << 10))
+#define INTERRUPT_MASK_REG(p) (0x0468 + ((p) << 10))
+#define INTERRUPT_EXTEND_MASK_REG(p) (0x046c + ((p) << 10))
+#define TX_FIFO_URGENT_THRESHOLD_REG(p) (0x0474 + ((p) << 10))
+#define RX_CURRENT_QUEUE_DESC_PTR_0(p) (0x060c + ((p) << 10))
+#define RECEIVE_QUEUE_COMMAND_REG(p) (0x0680 + ((p) << 10))
+#define TX_CURRENT_QUEUE_DESC_PTR_0(p) (0x06c0 + ((p) << 10))
+#define MIB_COUNTERS_BASE(p) (0x1000 + ((p) << 7))
+#define DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(p) (0x1400 + ((p) << 10))
+#define DA_FILTER_OTHER_MULTICAST_TABLE_BASE(p) (0x1500 + ((p) << 10))
+#define DA_FILTER_UNICAST_TABLE_BASE(p) (0x1600 + ((p) << 10))
+
+/* These macros describe Ethernet Port configuration reg (Px_cR) bits */
+#define UNICAST_NORMAL_MODE (0 << 0)
+#define UNICAST_PROMISCUOUS_MODE (1 << 0)
+#define DEFAULT_RX_QUEUE(queue) ((queue) << 1)
+#define DEFAULT_RX_ARP_QUEUE(queue) ((queue) << 4)
+#define RECEIVE_BC_IF_NOT_IP_OR_ARP (0 << 7)
+#define REJECT_BC_IF_NOT_IP_OR_ARP (1 << 7)
+#define RECEIVE_BC_IF_IP (0 << 8)
+#define REJECT_BC_IF_IP (1 << 8)
+#define RECEIVE_BC_IF_ARP (0 << 9)
+#define REJECT_BC_IF_ARP (1 << 9)
+#define TX_AM_NO_UPDATE_ERROR_SUMMARY (1 << 12)
+#define CAPTURE_TCP_FRAMES_DIS (0 << 14)
+#define CAPTURE_TCP_FRAMES_EN (1 << 14)
+#define CAPTURE_UDP_FRAMES_DIS (0 << 15)
+#define CAPTURE_UDP_FRAMES_EN (1 << 15)
+#define DEFAULT_RX_TCP_QUEUE(queue) ((queue) << 16)
+#define DEFAULT_RX_UDP_QUEUE(queue) ((queue) << 19)
+#define DEFAULT_RX_BPDU_QUEUE(queue) ((queue) << 22)
+
+#define PORT_CONFIG_DEFAULT_VALUE \
+ UNICAST_NORMAL_MODE | \
+ DEFAULT_RX_QUEUE(0) | \
+ DEFAULT_RX_ARP_QUEUE(0) | \
+ RECEIVE_BC_IF_NOT_IP_OR_ARP | \
+ RECEIVE_BC_IF_IP | \
+ RECEIVE_BC_IF_ARP | \
+ CAPTURE_TCP_FRAMES_DIS | \
+ CAPTURE_UDP_FRAMES_DIS | \
+ DEFAULT_RX_TCP_QUEUE(0) | \
+ DEFAULT_RX_UDP_QUEUE(0) | \
+ DEFAULT_RX_BPDU_QUEUE(0)
+
+/* These macros describe Ethernet Port configuration extend reg (Px_cXR) bits*/
+#define CLASSIFY_EN (1 << 0)
+#define SPAN_BPDU_PACKETS_AS_NORMAL (0 << 1)
+#define SPAN_BPDU_PACKETS_TO_RX_QUEUE_7 (1 << 1)
+#define PARTITION_DISABLE (0 << 2)
+#define PARTITION_ENABLE (1 << 2)
+
+#define PORT_CONFIG_EXTEND_DEFAULT_VALUE \
+ SPAN_BPDU_PACKETS_AS_NORMAL | \
+ PARTITION_DISABLE
+
+/* These macros describe Ethernet Port Sdma configuration reg (SDCR) bits */
+#define RIFB (1 << 0)
+#define RX_BURST_SIZE_1_64BIT (0 << 1)
+#define RX_BURST_SIZE_2_64BIT (1 << 1)
+#define RX_BURST_SIZE_4_64BIT (2 << 1)
+#define RX_BURST_SIZE_8_64BIT (3 << 1)
+#define RX_BURST_SIZE_16_64BIT (4 << 1)
+#define BLM_RX_NO_SWAP (1 << 4)
+#define BLM_RX_BYTE_SWAP (0 << 4)
+#define BLM_TX_NO_SWAP (1 << 5)
+#define BLM_TX_BYTE_SWAP (0 << 5)
+#define DESCRIPTORS_BYTE_SWAP (1 << 6)
+#define DESCRIPTORS_NO_SWAP (0 << 6)
+#define IPG_INT_RX(value) (((value) & 0x3fff) << 8)
+#define TX_BURST_SIZE_1_64BIT (0 << 22)
+#define TX_BURST_SIZE_2_64BIT (1 << 22)
+#define TX_BURST_SIZE_4_64BIT (2 << 22)
+#define TX_BURST_SIZE_8_64BIT (3 << 22)
+#define TX_BURST_SIZE_16_64BIT (4 << 22)
+
+#if defined(__BIG_ENDIAN)
+#define PORT_SDMA_CONFIG_DEFAULT_VALUE \
+ RX_BURST_SIZE_4_64BIT | \
+ IPG_INT_RX(0) | \
+ TX_BURST_SIZE_4_64BIT
+#elif defined(__LITTLE_ENDIAN)
+#define PORT_SDMA_CONFIG_DEFAULT_VALUE \
+ RX_BURST_SIZE_4_64BIT | \
+ BLM_RX_NO_SWAP | \
+ BLM_TX_NO_SWAP | \
+ IPG_INT_RX(0) | \
+ TX_BURST_SIZE_4_64BIT
+#else
+#error One of __BIG_ENDIAN or __LITTLE_ENDIAN must be defined
+#endif
+
+/* These macros describe Ethernet Port serial control reg (PSCR) bits */
+#define SERIAL_PORT_DISABLE (0 << 0)
+#define SERIAL_PORT_ENABLE (1 << 0)
+#define DO_NOT_FORCE_LINK_PASS (0 << 1)
+#define FORCE_LINK_PASS (1 << 1)
+#define ENABLE_AUTO_NEG_FOR_DUPLX (0 << 2)
+#define DISABLE_AUTO_NEG_FOR_DUPLX (1 << 2)
+#define ENABLE_AUTO_NEG_FOR_FLOW_CTRL (0 << 3)
+#define DISABLE_AUTO_NEG_FOR_FLOW_CTRL (1 << 3)
+#define ADV_NO_FLOW_CTRL (0 << 4)
+#define ADV_SYMMETRIC_FLOW_CTRL (1 << 4)
+#define FORCE_FC_MODE_NO_PAUSE_DIS_TX (0 << 5)
+#define FORCE_FC_MODE_TX_PAUSE_DIS (1 << 5)
+#define FORCE_BP_MODE_NO_JAM (0 << 7)
+#define FORCE_BP_MODE_JAM_TX (1 << 7)
+#define FORCE_BP_MODE_JAM_TX_ON_RX_ERR (2 << 7)
+#define SERIAL_PORT_CONTROL_RESERVED (1 << 9)
+#define FORCE_LINK_FAIL (0 << 10)
+#define DO_NOT_FORCE_LINK_FAIL (1 << 10)
+#define RETRANSMIT_16_ATTEMPTS (0 << 11)
+#define RETRANSMIT_FOREVER (1 << 11)
+#define ENABLE_AUTO_NEG_SPEED_GMII (0 << 13)
+#define DISABLE_AUTO_NEG_SPEED_GMII (1 << 13)
+#define DTE_ADV_0 (0 << 14)
+#define DTE_ADV_1 (1 << 14)
+#define DISABLE_AUTO_NEG_BYPASS (0 << 15)
+#define ENABLE_AUTO_NEG_BYPASS (1 << 15)
+#define AUTO_NEG_NO_CHANGE (0 << 16)
+#define RESTART_AUTO_NEG (1 << 16)
+#define MAX_RX_PACKET_1518BYTE (0 << 17)
+#define MAX_RX_PACKET_1522BYTE (1 << 17)
+#define MAX_RX_PACKET_1552BYTE (2 << 17)
+#define MAX_RX_PACKET_9022BYTE (3 << 17)
+#define MAX_RX_PACKET_9192BYTE (4 << 17)
+#define MAX_RX_PACKET_9700BYTE (5 << 17)
+#define MAX_RX_PACKET_MASK (7 << 17)
+#define CLR_EXT_LOOPBACK (0 << 20)
+#define SET_EXT_LOOPBACK (1 << 20)
+#define SET_HALF_DUPLEX_MODE (0 << 21)
+#define SET_FULL_DUPLEX_MODE (1 << 21)
+#define DISABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX (0 << 22)
+#define ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX (1 << 22)
+#define SET_GMII_SPEED_TO_10_100 (0 << 23)
+#define SET_GMII_SPEED_TO_1000 (1 << 23)
+#define SET_MII_SPEED_TO_10 (0 << 24)
+#define SET_MII_SPEED_TO_100 (1 << 24)
+
+#define PORT_SERIAL_CONTROL_DEFAULT_VALUE \
+ DO_NOT_FORCE_LINK_PASS | \
+ ENABLE_AUTO_NEG_FOR_DUPLX | \
+ DISABLE_AUTO_NEG_FOR_FLOW_CTRL | \
+ ADV_SYMMETRIC_FLOW_CTRL | \
+ FORCE_FC_MODE_NO_PAUSE_DIS_TX | \
+ FORCE_BP_MODE_NO_JAM | \
+ (1 << 9) /* reserved */ | \
+ DO_NOT_FORCE_LINK_FAIL | \
+ RETRANSMIT_16_ATTEMPTS | \
+ ENABLE_AUTO_NEG_SPEED_GMII | \
+ DTE_ADV_0 | \
+ DISABLE_AUTO_NEG_BYPASS | \
+ AUTO_NEG_NO_CHANGE | \
+ MAX_RX_PACKET_9700BYTE | \
+ CLR_EXT_LOOPBACK | \
+ SET_FULL_DUPLEX_MODE | \
+ ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX
+
+/* These macros describe Ethernet Serial Status reg (PSR) bits */
+#define PORT_STATUS_MODE_10_BIT (1 << 0)
+#define PORT_STATUS_LINK_UP (1 << 1)
+#define PORT_STATUS_FULL_DUPLEX (1 << 2)
+#define PORT_STATUS_FLOW_CONTROL (1 << 3)
+#define PORT_STATUS_GMII_1000 (1 << 4)
+#define PORT_STATUS_MII_100 (1 << 5)
+/* PSR bit 6 is undocumented */
+#define PORT_STATUS_TX_IN_PROGRESS (1 << 7)
+#define PORT_STATUS_AUTONEG_BYPASSED (1 << 8)
+#define PORT_STATUS_PARTITION (1 << 9)
+#define PORT_STATUS_TX_FIFO_EMPTY (1 << 10)
+/* PSR bits 11-31 are reserved */
+
+#define PORT_DEFAULT_TRANSMIT_QUEUE_SIZE 800
+#define PORT_DEFAULT_RECEIVE_QUEUE_SIZE 400
+
+#define DESC_SIZE 64
+
+#define ETH_RX_QUEUES_ENABLED (1 << 0) /* use only Q0 for receive */
+#define ETH_TX_QUEUES_ENABLED (1 << 0) /* use only Q0 for transmit */
+
+#define ETH_INT_CAUSE_RX_DONE (ETH_RX_QUEUES_ENABLED << 2)
+#define ETH_INT_CAUSE_RX_ERROR (ETH_RX_QUEUES_ENABLED << 9)
+#define ETH_INT_CAUSE_RX (ETH_INT_CAUSE_RX_DONE | ETH_INT_CAUSE_RX_ERROR)
+#define ETH_INT_CAUSE_EXT 0x00000002
+#define ETH_INT_UNMASK_ALL (ETH_INT_CAUSE_RX | ETH_INT_CAUSE_EXT)
+
+#define ETH_INT_CAUSE_TX_DONE (ETH_TX_QUEUES_ENABLED << 0)
+#define ETH_INT_CAUSE_TX_ERROR (ETH_TX_QUEUES_ENABLED << 8)
+#define ETH_INT_CAUSE_TX (ETH_INT_CAUSE_TX_DONE | ETH_INT_CAUSE_TX_ERROR)
+#define ETH_INT_CAUSE_PHY 0x00010000
+#define ETH_INT_CAUSE_STATE 0x00100000
+#define ETH_INT_UNMASK_ALL_EXT (ETH_INT_CAUSE_TX | ETH_INT_CAUSE_PHY | \
+ ETH_INT_CAUSE_STATE)
+
+#define ETH_INT_MASK_ALL 0x00000000
+#define ETH_INT_MASK_ALL_EXT 0x00000000
+
+#define PHY_WAIT_ITERATIONS 1000 /* 1000 iterations * 10uS = 10mS max */
+#define PHY_WAIT_MICRO_SECONDS 10
+
+/* Buffer offset from buffer pointer */
+#define RX_BUF_OFFSET 0x2
+
+/* Gigabit Ethernet Unit Global Registers */
+
+/* MIB Counters register definitions */
+#define ETH_MIB_GOOD_OCTETS_RECEIVED_LOW 0x0
+#define ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH 0x4
+#define ETH_MIB_BAD_OCTETS_RECEIVED 0x8
+#define ETH_MIB_INTERNAL_MAC_TRANSMIT_ERR 0xc
+#define ETH_MIB_GOOD_FRAMES_RECEIVED 0x10
+#define ETH_MIB_BAD_FRAMES_RECEIVED 0x14
+#define ETH_MIB_BROADCAST_FRAMES_RECEIVED 0x18
+#define ETH_MIB_MULTICAST_FRAMES_RECEIVED 0x1c
+#define ETH_MIB_FRAMES_64_OCTETS 0x20
+#define ETH_MIB_FRAMES_65_TO_127_OCTETS 0x24
+#define ETH_MIB_FRAMES_128_TO_255_OCTETS 0x28
+#define ETH_MIB_FRAMES_256_TO_511_OCTETS 0x2c
+#define ETH_MIB_FRAMES_512_TO_1023_OCTETS 0x30
+#define ETH_MIB_FRAMES_1024_TO_MAX_OCTETS 0x34
+#define ETH_MIB_GOOD_OCTETS_SENT_LOW 0x38
+#define ETH_MIB_GOOD_OCTETS_SENT_HIGH 0x3c
+#define ETH_MIB_GOOD_FRAMES_SENT 0x40
+#define ETH_MIB_EXCESSIVE_COLLISION 0x44
+#define ETH_MIB_MULTICAST_FRAMES_SENT 0x48
+#define ETH_MIB_BROADCAST_FRAMES_SENT 0x4c
+#define ETH_MIB_UNREC_MAC_CONTROL_RECEIVED 0x50
+#define ETH_MIB_FC_SENT 0x54
+#define ETH_MIB_GOOD_FC_RECEIVED 0x58
+#define ETH_MIB_BAD_FC_RECEIVED 0x5c
+#define ETH_MIB_UNDERSIZE_RECEIVED 0x60
+#define ETH_MIB_FRAGMENTS_RECEIVED 0x64
+#define ETH_MIB_OVERSIZE_RECEIVED 0x68
+#define ETH_MIB_JABBER_RECEIVED 0x6c
+#define ETH_MIB_MAC_RECEIVE_ERROR 0x70
+#define ETH_MIB_BAD_CRC_EVENT 0x74
+#define ETH_MIB_COLLISION 0x78
+#define ETH_MIB_LATE_COLLISION 0x7c
+
+/* Port serial status reg (PSR) */
+#define ETH_INTERFACE_PCM 0x00000001
+#define ETH_LINK_IS_UP 0x00000002
+#define ETH_PORT_AT_FULL_DUPLEX 0x00000004
+#define ETH_RX_FLOW_CTRL_ENABLED 0x00000008
+#define ETH_GMII_SPEED_1000 0x00000010
+#define ETH_MII_SPEED_100 0x00000020
+#define ETH_TX_IN_PROGRESS 0x00000080
+#define ETH_BYPASS_ACTIVE 0x00000100
+#define ETH_PORT_AT_PARTITION_STATE 0x00000200
+#define ETH_PORT_TX_FIFO_EMPTY 0x00000400
+
+/* SMI reg */
+#define ETH_SMI_BUSY 0x10000000 /* 0 - Write, 1 - Read */
+#define ETH_SMI_READ_VALID 0x08000000 /* 0 - Write, 1 - Read */
+#define ETH_SMI_OPCODE_WRITE 0 /* Completion of Read */
+#define ETH_SMI_OPCODE_READ 0x04000000 /* Operation is in progress */
+
+/* Interrupt Cause Register Bit Definitions */
+
+/* SDMA command status fields macros */
+
+/* Tx & Rx descriptors status */
+#define ETH_ERROR_SUMMARY 0x00000001
+
+/* Tx & Rx descriptors command */
+#define ETH_BUFFER_OWNED_BY_DMA 0x80000000
+
+/* Tx descriptors status */
+#define ETH_LC_ERROR 0
+#define ETH_UR_ERROR 0x00000002
+#define ETH_RL_ERROR 0x00000004
+#define ETH_LLC_SNAP_FORMAT 0x00000200
+
+/* Rx descriptors status */
+#define ETH_OVERRUN_ERROR 0x00000002
+#define ETH_MAX_FRAME_LENGTH_ERROR 0x00000004
+#define ETH_RESOURCE_ERROR 0x00000006
+#define ETH_VLAN_TAGGED 0x00080000
+#define ETH_BPDU_FRAME 0x00100000
+#define ETH_UDP_FRAME_OVER_IP_V_4 0x00200000
+#define ETH_OTHER_FRAME_TYPE 0x00400000
+#define ETH_LAYER_2_IS_ETH_V_2 0x00800000
+#define ETH_FRAME_TYPE_IP_V_4 0x01000000
+#define ETH_FRAME_HEADER_OK 0x02000000
+#define ETH_RX_LAST_DESC 0x04000000
+#define ETH_RX_FIRST_DESC 0x08000000
+#define ETH_UNKNOWN_DESTINATION_ADDR 0x10000000
+#define ETH_RX_ENABLE_INTERRUPT 0x20000000
+#define ETH_LAYER_4_CHECKSUM_OK 0x40000000
+
+/* Rx descriptors byte count */
+#define ETH_FRAME_FRAGMENTED 0x00000004
+
+/* Tx descriptors command */
+#define ETH_LAYER_4_CHECKSUM_FIRST_DESC 0x00000400
+#define ETH_FRAME_SET_TO_VLAN 0x00008000
+#define ETH_UDP_FRAME 0x00010000
+#define ETH_GEN_TCP_UDP_CHECKSUM 0x00020000
+#define ETH_GEN_IP_V_4_CHECKSUM 0x00040000
+#define ETH_ZERO_PADDING 0x00080000
+#define ETH_TX_LAST_DESC 0x00100000
+#define ETH_TX_FIRST_DESC 0x00200000
+#define ETH_GEN_CRC 0x00400000
+#define ETH_TX_ENABLE_INTERRUPT 0x00800000
+#define ETH_AUTO_MODE 0x40000000
+
+#define ETH_TX_IHL_SHIFT 11
+
+/* typedefs */
+
+typedef enum _eth_func_ret_status {
+ ETH_OK, /* Returned as expected. */
+ ETH_ERROR, /* Fundamental error. */
+ ETH_RETRY, /* Could not process request. Try later.*/
+ ETH_END_OF_JOB, /* Ring has nothing to process. */
+ ETH_QUEUE_FULL, /* Ring resource error. */
+ ETH_QUEUE_LAST_RESOURCE /* Ring resources about to exhaust. */
+} ETH_FUNC_RET_STATUS;
+
+typedef enum _eth_target {
+ ETH_TARGET_DRAM,
+ ETH_TARGET_DEVICE,
+ ETH_TARGET_CBS,
+ ETH_TARGET_PCI0,
+ ETH_TARGET_PCI1
+} ETH_TARGET;
+
+/* These are for big-endian machines. Little endian needs different
+ * definitions.
+ */
+#if defined(__BIG_ENDIAN)
+struct eth_rx_desc {
+ u16 byte_cnt; /* Descriptor buffer byte count */
+ u16 buf_size; /* Buffer size */
+ u32 cmd_sts; /* Descriptor command status */
+ u32 next_desc_ptr; /* Next descriptor pointer */
+ u32 buf_ptr; /* Descriptor buffer pointer */
+};
+
+struct eth_tx_desc {
+ u16 byte_cnt; /* buffer byte count */
+ u16 l4i_chk; /* CPU provided TCP checksum */
+ u32 cmd_sts; /* Command/status field */
+ u32 next_desc_ptr; /* Pointer to next descriptor */
+ u32 buf_ptr; /* pointer to buffer for this descriptor*/
+};
+#elif defined(__LITTLE_ENDIAN)
+struct eth_rx_desc {
+ u32 cmd_sts; /* Descriptor command status */
+ u16 buf_size; /* Buffer size */
+ u16 byte_cnt; /* Descriptor buffer byte count */
+ u32 buf_ptr; /* Descriptor buffer pointer */
+ u32 next_desc_ptr; /* Next descriptor pointer */
+};
+
+struct eth_tx_desc {
+ u32 cmd_sts; /* Command/status field */
+ u16 l4i_chk; /* CPU provided TCP checksum */
+ u16 byte_cnt; /* buffer byte count */
+ u32 buf_ptr; /* pointer to buffer for this descriptor*/
+ u32 next_desc_ptr; /* Pointer to next descriptor */
+};
+#else
+#error One of __BIG_ENDIAN or __LITTLE_ENDIAN must be defined
+#endif
+
+/* Unified struct for Rx and Tx operations. The user is not required to */
+/* be familier with neither Tx nor Rx descriptors. */
+struct pkt_info {
+ unsigned short byte_cnt; /* Descriptor buffer byte count */
+ unsigned short l4i_chk; /* Tx CPU provided TCP Checksum */
+ unsigned int cmd_sts; /* Descriptor command status */
+ dma_addr_t buf_ptr; /* Descriptor buffer pointer */
+ struct sk_buff *return_info; /* User resource return information */
+};
+
+/* Ethernet port specific information */
+struct mv643xx_mib_counters {
+ u64 good_octets_received;
+ u32 bad_octets_received;
+ u32 internal_mac_transmit_err;
+ u32 good_frames_received;
+ u32 bad_frames_received;
+ u32 broadcast_frames_received;
+ u32 multicast_frames_received;
+ u32 frames_64_octets;
+ u32 frames_65_to_127_octets;
+ u32 frames_128_to_255_octets;
+ u32 frames_256_to_511_octets;
+ u32 frames_512_to_1023_octets;
+ u32 frames_1024_to_max_octets;
+ u64 good_octets_sent;
+ u32 good_frames_sent;
+ u32 excessive_collision;
+ u32 multicast_frames_sent;
+ u32 broadcast_frames_sent;
+ u32 unrec_mac_control_received;
+ u32 fc_sent;
+ u32 good_fc_received;
+ u32 bad_fc_received;
+ u32 undersize_received;
+ u32 fragments_received;
+ u32 oversize_received;
+ u32 jabber_received;
+ u32 mac_receive_error;
+ u32 bad_crc_event;
+ u32 collision;
+ u32 late_collision;
+};
+
+struct mv643xx_private {
+ int port_num; /* User Ethernet port number */
+
+ u32 rx_sram_addr; /* Base address of rx sram area */
+ u32 rx_sram_size; /* Size of rx sram area */
+ u32 tx_sram_addr; /* Base address of tx sram area */
+ u32 tx_sram_size; /* Size of tx sram area */
+
+ int rx_resource_err; /* Rx ring resource error flag */
+
+ /* Tx/Rx rings managment indexes fields. For driver use */
+
+ /* Next available and first returning Rx resource */
+ int rx_curr_desc_q, rx_used_desc_q;
+
+ /* Next available and first returning Tx resource */
+ int tx_curr_desc_q, tx_used_desc_q;
+
+#ifdef MV643XX_TX_FAST_REFILL
+ u32 tx_clean_threshold;
+#endif
+
+ struct eth_rx_desc *p_rx_desc_area;
+ dma_addr_t rx_desc_dma;
+ int rx_desc_area_size;
+ struct sk_buff **rx_skb;
+
+ struct eth_tx_desc *p_tx_desc_area;
+ dma_addr_t tx_desc_dma;
+ int tx_desc_area_size;
+ struct sk_buff **tx_skb;
+
+ struct work_struct tx_timeout_task;
+
+ struct net_device *dev;
+ struct napi_struct napi;
+ struct net_device_stats stats;
+ struct mv643xx_mib_counters mib_counters;
+ spinlock_t lock;
+ /* Size of Tx Ring per queue */
+ int tx_ring_size;
+ /* Number of tx descriptors in use */
+ int tx_desc_count;
+ /* Size of Rx Ring per queue */
+ int rx_ring_size;
+ /* Number of rx descriptors in use */
+ int rx_desc_count;
+
+ /*
+ * Used in case RX Ring is empty, which can be caused when
+ * system does not have resources (skb's)
+ */
+ struct timer_list timeout;
+
+ u32 rx_int_coal;
+ u32 tx_int_coal;
+ struct mii_if_info mii;
+};
/* Static function declarations */
+static void eth_port_init(struct mv643xx_private *mp);
+static void eth_port_reset(unsigned int eth_port_num);
+static void eth_port_start(struct net_device *dev);
+
+static void ethernet_phy_reset(unsigned int eth_port_num);
+
+static void eth_port_write_smi_reg(unsigned int eth_port_num,
+ unsigned int phy_reg, unsigned int value);
+
+static void eth_port_read_smi_reg(unsigned int eth_port_num,
+ unsigned int phy_reg, unsigned int *value);
+
+static void eth_clear_mib_counters(unsigned int eth_port_num);
+
+static ETH_FUNC_RET_STATUS eth_port_receive(struct mv643xx_private *mp,
+ struct pkt_info *p_pkt_info);
+static ETH_FUNC_RET_STATUS eth_rx_return_buff(struct mv643xx_private *mp,
+ struct pkt_info *p_pkt_info);
+
static void eth_port_uc_addr_get(unsigned int port_num, unsigned char *p_addr);
static void eth_port_uc_addr_set(unsigned int port_num, unsigned char *p_addr);
static void eth_port_set_multicast_list(struct net_device *);
@@ -78,26 +631,19 @@ static const struct ethtool_ops mv643xx_ethtool_ops;
static char mv643xx_driver_name[] = "mv643xx_eth";
static char mv643xx_driver_version[] = "1.0";
-static void __iomem *mv643xx_eth_shared_base;
+static void __iomem *mv643xx_eth_base;
-/* used to protect MV643XX_ETH_SMI_REG, which is shared across ports */
+/* used to protect SMI_REG, which is shared across ports */
static DEFINE_SPINLOCK(mv643xx_eth_phy_lock);
static inline u32 mv_read(int offset)
{
- void __iomem *reg_base;
-
- reg_base = mv643xx_eth_shared_base - MV643XX_ETH_SHARED_REGS;
-
- return readl(reg_base + offset);
+ return readl(mv643xx_eth_base + offset);
}
static inline void mv_write(int offset, u32 data)
{
- void __iomem *reg_base;
-
- reg_base = mv643xx_eth_shared_base - MV643XX_ETH_SHARED_REGS;
- writel(data, reg_base + offset);
+ writel(data, mv643xx_eth_base + offset);
}
/*
@@ -221,12 +767,12 @@ static void mv643xx_eth_set_rx_mode(struct net_device *dev)
struct mv643xx_private *mp = netdev_priv(dev);
u32 config_reg;
- config_reg = mv_read(MV643XX_ETH_PORT_CONFIG_REG(mp->port_num));
+ config_reg = mv_read(PORT_CONFIG_REG(mp->port_num));
if (dev->flags & IFF_PROMISC)
- config_reg |= (u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE;
+ config_reg |= (u32) UNICAST_PROMISCUOUS_MODE;
else
- config_reg &= ~(u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE;
- mv_write(MV643XX_ETH_PORT_CONFIG_REG(mp->port_num), config_reg);
+ config_reg &= ~(u32) UNICAST_PROMISCUOUS_MODE;
+ mv_write(PORT_CONFIG_REG(mp->port_num), config_reg);
eth_port_set_multicast_list(dev);
}
@@ -462,41 +1008,37 @@ static void mv643xx_eth_update_pscr(struct net_device *dev,
u32 o_pscr, n_pscr;
unsigned int queues;
- o_pscr = mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num));
+ o_pscr = mv_read(PORT_SERIAL_CONTROL_REG(port_num));
n_pscr = o_pscr;
/* clear speed, duplex and rx buffer size fields */
- n_pscr &= ~(MV643XX_ETH_SET_MII_SPEED_TO_100 |
- MV643XX_ETH_SET_GMII_SPEED_TO_1000 |
- MV643XX_ETH_SET_FULL_DUPLEX_MODE |
- MV643XX_ETH_MAX_RX_PACKET_MASK);
+ n_pscr &= ~(SET_MII_SPEED_TO_100 |
+ SET_GMII_SPEED_TO_1000 |
+ SET_FULL_DUPLEX_MODE |
+ MAX_RX_PACKET_MASK);
if (ecmd->duplex == DUPLEX_FULL)
- n_pscr |= MV643XX_ETH_SET_FULL_DUPLEX_MODE;
+ n_pscr |= SET_FULL_DUPLEX_MODE;
if (ecmd->speed == SPEED_1000)
- n_pscr |= MV643XX_ETH_SET_GMII_SPEED_TO_1000 |
- MV643XX_ETH_MAX_RX_PACKET_9700BYTE;
+ n_pscr |= SET_GMII_SPEED_TO_1000 |
+ MAX_RX_PACKET_9700BYTE;
else {
if (ecmd->speed == SPEED_100)
- n_pscr |= MV643XX_ETH_SET_MII_SPEED_TO_100;
- n_pscr |= MV643XX_ETH_MAX_RX_PACKET_1522BYTE;
+ n_pscr |= SET_MII_SPEED_TO_100;
+ n_pscr |= MAX_RX_PACKET_1522BYTE;
}
if (n_pscr != o_pscr) {
- if ((o_pscr & MV643XX_ETH_SERIAL_PORT_ENABLE) == 0)
- mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num),
- n_pscr);
+ if ((o_pscr & SERIAL_PORT_ENABLE) == 0)
+ mv_write(PORT_SERIAL_CONTROL_REG(port_num), n_pscr);
else {
queues = mv643xx_eth_port_disable_tx(port_num);
- o_pscr &= ~MV643XX_ETH_SERIAL_PORT_ENABLE;
- mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num),
- o_pscr);
- mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num),
- n_pscr);
- mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num),
- n_pscr);
+ o_pscr &= ~SERIAL_PORT_ENABLE;
+ mv_write(PORT_SERIAL_CONTROL_REG(port_num), o_pscr);
+ mv_write(PORT_SERIAL_CONTROL_REG(port_num), n_pscr);
+ mv_write(PORT_SERIAL_CONTROL_REG(port_num), n_pscr);
if (queues)
mv643xx_eth_port_enable_tx(port_num, queues);
}
@@ -522,13 +1064,13 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id)
unsigned int port_num = mp->port_num;
/* Read interrupt cause registers */
- eth_int_cause = mv_read(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num)) &
+ eth_int_cause = mv_read(INTERRUPT_CAUSE_REG(port_num)) &
ETH_INT_UNMASK_ALL;
if (eth_int_cause & ETH_INT_CAUSE_EXT) {
eth_int_cause_ext = mv_read(
- MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num)) &
+ INTERRUPT_CAUSE_EXTEND_REG(port_num)) &
ETH_INT_UNMASK_ALL_EXT;
- mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num),
+ mv_write(INTERRUPT_CAUSE_EXTEND_REG(port_num),
~eth_int_cause_ext);
}
@@ -556,10 +1098,10 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id)
#ifdef MV643XX_NAPI
if (eth_int_cause & ETH_INT_CAUSE_RX) {
/* schedule the NAPI poll routine to maintain port */
- mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
- ETH_INT_MASK_ALL);
+ mv_write(INTERRUPT_MASK_REG(port_num), ETH_INT_MASK_ALL);
+
/* wait for previous write to complete */
- mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
+ mv_read(INTERRUPT_MASK_REG(port_num));
netif_rx_schedule(dev, &mp->napi);
}
@@ -611,9 +1153,9 @@ static unsigned int eth_port_set_rx_coal(unsigned int eth_port_num,
unsigned int coal = ((t_clk / 1000000) * delay) / 64;
/* Set RX Coalescing mechanism */
- mv_write(MV643XX_ETH_SDMA_CONFIG_REG(eth_port_num),
+ mv_write(SDMA_CONFIG_REG(eth_port_num),
((coal & 0x3fff) << 8) |
- (mv_read(MV643XX_ETH_SDMA_CONFIG_REG(eth_port_num))
+ (mv_read(SDMA_CONFIG_REG(eth_port_num))
& 0xffc000ff));
return coal;
@@ -649,8 +1191,7 @@ static unsigned int eth_port_set_tx_coal(unsigned int eth_port_num,
unsigned int coal;
coal = ((t_clk / 1000000) * delay) / 64;
/* Set TX Coalescing mechanism */
- mv_write(MV643XX_ETH_TX_FIFO_URGENT_THRESHOLD_REG(eth_port_num),
- coal << 4);
+ mv_write(TX_FIFO_URGENT_THRESHOLD_REG(eth_port_num), coal << 4);
return coal;
}
@@ -786,10 +1327,10 @@ static int mv643xx_eth_open(struct net_device *dev)
int err;
/* Clear any pending ethernet port interrupts */
- mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
- mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
+ mv_write(INTERRUPT_CAUSE_REG(port_num), 0);
+ mv_write(INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
/* wait for previous write to complete */
- mv_read (MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num));
+ mv_read (INTERRUPT_CAUSE_EXTEND_REG(port_num));
err = request_irq(dev->irq, mv643xx_eth_int_handler,
IRQF_SHARED | IRQF_SAMPLE_RANDOM, dev->name, dev);
@@ -896,11 +1437,10 @@ static int mv643xx_eth_open(struct net_device *dev)
eth_port_set_tx_coal(port_num, 133000000, MV643XX_TX_COAL);
/* Unmask phy and link status changes interrupts */
- mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
- ETH_INT_UNMASK_ALL_EXT);
+ mv_write(INTERRUPT_EXTEND_MASK_REG(port_num), ETH_INT_UNMASK_ALL_EXT);
/* Unmask RX buffer and TX end interrupt */
- mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), ETH_INT_UNMASK_ALL);
+ mv_write(INTERRUPT_MASK_REG(port_num), ETH_INT_UNMASK_ALL);
return 0;
@@ -980,9 +1520,9 @@ static int mv643xx_eth_stop(struct net_device *dev)
unsigned int port_num = mp->port_num;
/* Mask all interrupts on ethernet port */
- mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), ETH_INT_MASK_ALL);
+ mv_write(INTERRUPT_MASK_REG(port_num), ETH_INT_MASK_ALL);
/* wait for previous write to complete */
- mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
+ mv_read(INTERRUPT_MASK_REG(port_num));
#ifdef MV643XX_NAPI
napi_disable(&mp->napi);
@@ -1021,16 +1561,15 @@ static int mv643xx_poll(struct napi_struct *napi, int budget)
#endif
work_done = 0;
- if ((mv_read(MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(port_num)))
+ if ((mv_read(RX_CURRENT_QUEUE_DESC_PTR_0(port_num)))
!= (u32) mp->rx_used_desc_q)
work_done = mv643xx_eth_receive_queue(dev, budget);
if (work_done < budget) {
netif_rx_complete(dev, napi);
- mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
- mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
- mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
- ETH_INT_UNMASK_ALL);
+ mv_write(INTERRUPT_CAUSE_REG(port_num), 0);
+ mv_write(INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
+ mv_write(INTERRUPT_MASK_REG(port_num), ETH_INT_UNMASK_ALL);
}
return work_done;
@@ -1233,13 +1772,13 @@ static void mv643xx_netpoll(struct net_device *netdev)
struct mv643xx_private *mp = netdev_priv(netdev);
int port_num = mp->port_num;
- mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), ETH_INT_MASK_ALL);
+ mv_write(INTERRUPT_MASK_REG(port_num), ETH_INT_MASK_ALL);
/* wait for previous write to complete */
- mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
+ mv_read(INTERRUPT_MASK_REG(port_num));
mv643xx_eth_int_handler(netdev->irq, netdev);
- mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), ETH_INT_UNMASK_ALL);
+ mv_write(INTERRUPT_MASK_REG(port_num), ETH_INT_UNMASK_ALL);
}
#endif
@@ -1357,8 +1896,8 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
/* set default config values */
eth_port_uc_addr_get(port_num, dev->dev_addr);
- mp->rx_ring_size = MV643XX_ETH_PORT_DEFAULT_RECEIVE_QUEUE_SIZE;
- mp->tx_ring_size = MV643XX_ETH_PORT_DEFAULT_TRANSMIT_QUEUE_SIZE;
+ mp->rx_ring_size = PORT_DEFAULT_RECEIVE_QUEUE_SIZE;
+ mp->tx_ring_size = PORT_DEFAULT_TRANSMIT_QUEUE_SIZE;
if (is_valid_ether_addr(pd->mac_addr))
memcpy(dev->dev_addr, pd->mac_addr, 6);
@@ -1470,9 +2009,8 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
if (res == NULL)
return -ENODEV;
- mv643xx_eth_shared_base = ioremap(res->start,
- MV643XX_ETH_SHARED_REGS_SIZE);
- if (mv643xx_eth_shared_base == NULL)
+ mv643xx_eth_base = ioremap(res->start, res->end - res->start + 1);
+ if (mv643xx_eth_base == NULL)
return -ENOMEM;
return 0;
@@ -1481,8 +2019,8 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
static int mv643xx_eth_shared_remove(struct platform_device *pdev)
{
- iounmap(mv643xx_eth_shared_base);
- mv643xx_eth_shared_base = NULL;
+ iounmap(mv643xx_eth_base);
+ mv643xx_eth_base = NULL;
return 0;
}
@@ -1494,8 +2032,8 @@ static void mv643xx_eth_shutdown(struct platform_device *pdev)
unsigned int port_num = mp->port_num;
/* Mask all interrupts on ethernet port */
- mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), 0);
- mv_read (MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
+ mv_write(INTERRUPT_MASK_REG(port_num), 0);
+ mv_read (INTERRUPT_MASK_REG(port_num));
eth_port_reset(port_num);
}
@@ -1762,49 +2300,49 @@ static void eth_port_start(struct net_device *dev)
/* Assignment of Tx CTRP of given queue */
tx_curr_desc = mp->tx_curr_desc_q;
- mv_write(MV643XX_ETH_TX_CURRENT_QUEUE_DESC_PTR_0(port_num),
+ mv_write(TX_CURRENT_QUEUE_DESC_PTR_0(port_num),
(u32)((struct eth_tx_desc *)mp->tx_desc_dma + tx_curr_desc));
/* Assignment of Rx CRDP of given queue */
rx_curr_desc = mp->rx_curr_desc_q;
- mv_write(MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(port_num),
+ mv_write(RX_CURRENT_QUEUE_DESC_PTR_0(port_num),
(u32)((struct eth_rx_desc *)mp->rx_desc_dma + rx_curr_desc));
/* Add the assigned Ethernet address to the port's address table */
eth_port_uc_addr_set(port_num, dev->dev_addr);
/* Assign port configuration and command. */
- mv_write(MV643XX_ETH_PORT_CONFIG_REG(port_num),
- MV643XX_ETH_PORT_CONFIG_DEFAULT_VALUE);
+ mv_write(PORT_CONFIG_REG(port_num),
+ PORT_CONFIG_DEFAULT_VALUE);
- mv_write(MV643XX_ETH_PORT_CONFIG_EXTEND_REG(port_num),
- MV643XX_ETH_PORT_CONFIG_EXTEND_DEFAULT_VALUE);
+ mv_write(PORT_CONFIG_EXTEND_REG(port_num),
+ PORT_CONFIG_EXTEND_DEFAULT_VALUE);
- pscr = mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num));
+ pscr = mv_read(PORT_SERIAL_CONTROL_REG(port_num));
- pscr &= ~(MV643XX_ETH_SERIAL_PORT_ENABLE | MV643XX_ETH_FORCE_LINK_PASS);
- mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), pscr);
+ pscr &= ~(SERIAL_PORT_ENABLE | FORCE_LINK_PASS);
+ mv_write(PORT_SERIAL_CONTROL_REG(port_num), pscr);
- pscr |= MV643XX_ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL |
- MV643XX_ETH_DISABLE_AUTO_NEG_SPEED_GMII |
- MV643XX_ETH_DISABLE_AUTO_NEG_FOR_DUPLX |
- MV643XX_ETH_DO_NOT_FORCE_LINK_FAIL |
- MV643XX_ETH_SERIAL_PORT_CONTROL_RESERVED;
+ pscr |= DISABLE_AUTO_NEG_FOR_FLOW_CTRL |
+ DISABLE_AUTO_NEG_SPEED_GMII |
+ DISABLE_AUTO_NEG_FOR_DUPLX |
+ DO_NOT_FORCE_LINK_FAIL |
+ SERIAL_PORT_CONTROL_RESERVED;
- mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), pscr);
+ mv_write(PORT_SERIAL_CONTROL_REG(port_num), pscr);
- pscr |= MV643XX_ETH_SERIAL_PORT_ENABLE;
- mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), pscr);
+ pscr |= SERIAL_PORT_ENABLE;
+ mv_write(PORT_SERIAL_CONTROL_REG(port_num), pscr);
/* Assign port SDMA configuration */
- mv_write(MV643XX_ETH_SDMA_CONFIG_REG(port_num),
- MV643XX_ETH_PORT_SDMA_CONFIG_DEFAULT_VALUE);
+ mv_write(SDMA_CONFIG_REG(port_num),
+ PORT_SDMA_CONFIG_DEFAULT_VALUE);
/* Enable port Rx. */
mv643xx_eth_port_enable_rx(port_num, ETH_RX_QUEUES_ENABLED);
/* Disable port bandwidth limits by clearing MTU register */
- mv_write(MV643XX_ETH_MAXIMUM_TRANSMIT_UNIT(port_num), 0);
+ mv_write(MAXIMUM_TRANSMIT_UNIT(port_num), 0);
/* save phy settings across reset */
mv643xx_get_settings(dev, &ethtool_cmd);
@@ -1825,11 +2363,11 @@ static void eth_port_uc_addr_set(unsigned int port_num, unsigned char *p_addr)
mac_h = (p_addr[0] << 24) | (p_addr[1] << 16) | (p_addr[2] << 8) |
(p_addr[3] << 0);
- mv_write(MV643XX_ETH_MAC_ADDR_LOW(port_num), mac_l);
- mv_write(MV643XX_ETH_MAC_ADDR_HIGH(port_num), mac_h);
+ mv_write(MAC_ADDR_LOW(port_num), mac_l);
+ mv_write(MAC_ADDR_HIGH(port_num), mac_h);
/* Accept frames with this address */
- table = MV643XX_ETH_DA_FILTER_UNICAST_TABLE_BASE(port_num);
+ table = DA_FILTER_UNICAST_TABLE_BASE(port_num);
eth_port_set_filter_table_entry(table, p_addr[5] & 0x0f);
}
@@ -1841,8 +2379,8 @@ static void eth_port_uc_addr_get(unsigned int port_num, unsigned char *p_addr)
unsigned int mac_h;
unsigned int mac_l;
- mac_h = mv_read(MV643XX_ETH_MAC_ADDR_HIGH(port_num));
- mac_l = mv_read(MV643XX_ETH_MAC_ADDR_LOW(port_num));
+ mac_h = mv_read(MAC_ADDR_HIGH(port_num));
+ mac_l = mv_read(MAC_ADDR_LOW(port_num));
p_addr[0] = (mac_h >> 24) & 0xff;
p_addr[1] = (mac_h >> 16) & 0xff;
@@ -1902,7 +2440,7 @@ static void eth_port_mc_addr(unsigned int eth_port_num, unsigned char *p_addr)
if ((p_addr[0] == 0x01) && (p_addr[1] == 0x00) &&
(p_addr[2] == 0x5E) && (p_addr[3] == 0x00) && (p_addr[4] == 0x00)) {
- table = MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
+ table = DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
(eth_port_num);
eth_port_set_filter_table_entry(table, p_addr[5]);
return;
@@ -1976,7 +2514,7 @@ static void eth_port_mc_addr(unsigned int eth_port_num, unsigned char *p_addr)
for (i = 0; i < 8; i++)
crc_result = crc_result | (crc[i] << i);
- table = MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(eth_port_num);
+ table = DA_FILTER_OTHER_MULTICAST_TABLE_BASE(eth_port_num);
eth_port_set_filter_table_entry(table, crc_result);
}
@@ -2006,7 +2544,7 @@ static void eth_port_set_multicast_list(struct net_device *dev)
* 3-1 Queue ETH_Q0=0
* 7-4 Reserved = 0;
*/
- mv_write(MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101);
+ mv_write(DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101);
/* Set all entries in DA filter other multicast
* table (Ex_dFOMT)
@@ -2016,7 +2554,7 @@ static void eth_port_set_multicast_list(struct net_device *dev)
* 3-1 Queue ETH_Q0=0
* 7-4 Reserved = 0;
*/
- mv_write(MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101);
+ mv_write(DA_FILTER_OTHER_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101);
}
return;
}
@@ -2026,11 +2564,11 @@ static void eth_port_set_multicast_list(struct net_device *dev)
*/
for (table_index = 0; table_index <= 0xFC; table_index += 4) {
/* Clear DA filter special multicast table (Ex_dFSMT) */
- mv_write(MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
+ mv_write(DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
(eth_port_num) + table_index, 0);
/* Clear DA filter other multicast table (Ex_dFOMT) */
- mv_write(MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE
+ mv_write(DA_FILTER_OTHER_MULTICAST_TABLE_BASE
(eth_port_num) + table_index, 0);
}
@@ -2064,15 +2602,15 @@ static void eth_port_init_mac_tables(unsigned int eth_port_num)
/* Clear DA filter unicast table (Ex_dFUT) */
for (table_index = 0; table_index <= 0xC; table_index += 4)
- mv_write(MV643XX_ETH_DA_FILTER_UNICAST_TABLE_BASE
+ mv_write(DA_FILTER_UNICAST_TABLE_BASE
(eth_port_num) + table_index, 0);
for (table_index = 0; table_index <= 0xFC; table_index += 4) {
/* Clear DA filter special multicast table (Ex_dFSMT) */
- mv_write(MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
+ mv_write(DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
(eth_port_num) + table_index, 0);
/* Clear DA filter other multicast table (Ex_dFOMT) */
- mv_write(MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE
+ mv_write(DA_FILTER_OTHER_MULTICAST_TABLE_BASE
(eth_port_num) + table_index, 0);
}
}
@@ -2101,12 +2639,12 @@ static void eth_clear_mib_counters(unsigned int eth_port_num)
/* Perform dummy reads from MIB counters */
for (i = ETH_MIB_GOOD_OCTETS_RECEIVED_LOW; i < ETH_MIB_LATE_COLLISION;
i += 4)
- mv_read(MV643XX_ETH_MIB_COUNTERS_BASE(eth_port_num) + i);
+ mv_read(MIB_COUNTERS_BASE(eth_port_num) + i);
}
static inline u32 read_mib(struct mv643xx_private *mp, int offset)
{
- return mv_read(MV643XX_ETH_MIB_COUNTERS_BASE(mp->port_num) + offset);
+ return mv_read(MIB_COUNTERS_BASE(mp->port_num) + offset);
}
static void eth_update_mib_counters(struct mv643xx_private *mp)
@@ -2191,7 +2729,7 @@ static int ethernet_phy_get(unsigned int eth_port_num)
{
unsigned int reg_data;
- reg_data = mv_read(MV643XX_ETH_PHY_ADDR_REG);
+ reg_data = mv_read(PHY_ADDR_REG);
return ((reg_data >> (5 * eth_port_num)) & 0x1f);
}
@@ -2218,10 +2756,10 @@ static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr)
u32 reg_data;
int addr_shift = 5 * eth_port_num;
- reg_data = mv_read(MV643XX_ETH_PHY_ADDR_REG);
+ reg_data = mv_read(PHY_ADDR_REG);
reg_data &= ~(0x1f << addr_shift);
reg_data |= (phy_addr & 0x1f) << addr_shift;
- mv_write(MV643XX_ETH_PHY_ADDR_REG, reg_data);
+ mv_write(PHY_ADDR_REG, reg_data);
}
/*
@@ -2259,13 +2797,13 @@ static void ethernet_phy_reset(unsigned int eth_port_num)
static void mv643xx_eth_port_enable_tx(unsigned int port_num,
unsigned int queues)
{
- mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num), queues);
+ mv_write(TRANSMIT_QUEUE_COMMAND_REG(port_num), queues);
}
static void mv643xx_eth_port_enable_rx(unsigned int port_num,
unsigned int queues)
{
- mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), queues);
+ mv_write(RECEIVE_QUEUE_COMMAND_REG(port_num), queues);
}
static unsigned int mv643xx_eth_port_disable_tx(unsigned int port_num)
@@ -2273,21 +2811,18 @@ static unsigned int mv643xx_eth_port_disable_tx(unsigned int port_num)
u32 queues;
/* Stop Tx port activity. Check port Tx activity. */
- queues = mv_read(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num))
- & 0xFF;
+ queues = mv_read(TRANSMIT_QUEUE_COMMAND_REG(port_num)) & 0xFF;
if (queues) {
/* Issue stop command for active queues only */
- mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num),
- (queues << 8));
+ mv_write(TRANSMIT_QUEUE_COMMAND_REG(port_num), (queues << 8));
/* Wait for all Tx activity to terminate. */
/* Check port cause register that all Tx queues are stopped */
- while (mv_read(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num))
- & 0xFF)
+ while (mv_read(TRANSMIT_QUEUE_COMMAND_REG(port_num)) & 0xFF)
udelay(PHY_WAIT_MICRO_SECONDS);
/* Wait for Tx FIFO to empty */
- while (mv_read(MV643XX_ETH_PORT_STATUS_REG(port_num)) &
+ while (mv_read(PORT_STATUS_REG(port_num)) &
ETH_PORT_TX_FIFO_EMPTY)
udelay(PHY_WAIT_MICRO_SECONDS);
}
@@ -2300,17 +2835,14 @@ static unsigned int mv643xx_eth_port_disable_rx(unsigned int port_num)
u32 queues;
/* Stop Rx port activity. Check port Rx activity. */
- queues = mv_read(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num))
- & 0xFF;
+ queues = mv_read(RECEIVE_QUEUE_COMMAND_REG(port_num)) & 0xFF;
if (queues) {
/* Issue stop command for active queues only */
- mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num),
- (queues << 8));
+ mv_write(RECEIVE_QUEUE_COMMAND_REG(port_num), (queues << 8));
/* Wait for all Rx activity to terminate. */
/* Check port cause register that all Rx queues are stopped */
- while (mv_read(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num))
- & 0xFF)
+ while (mv_read(RECEIVE_QUEUE_COMMAND_REG(port_num)) & 0xFF)
udelay(PHY_WAIT_MICRO_SECONDS);
}
@@ -2346,11 +2878,11 @@ static void eth_port_reset(unsigned int port_num)
eth_clear_mib_counters(port_num);
/* Reset the Enable bit in the Configuration Register */
- reg_data = mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num));
- reg_data &= ~(MV643XX_ETH_SERIAL_PORT_ENABLE |
- MV643XX_ETH_DO_NOT_FORCE_LINK_FAIL |
- MV643XX_ETH_FORCE_LINK_PASS);
- mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), reg_data);
+ reg_data = mv_read(PORT_SERIAL_CONTROL_REG(port_num));
+ reg_data &= ~(SERIAL_PORT_ENABLE |
+ DO_NOT_FORCE_LINK_FAIL |
+ FORCE_LINK_PASS);
+ mv_write(PORT_SERIAL_CONTROL_REG(port_num), reg_data);
}
@@ -2385,7 +2917,7 @@ static void eth_port_read_smi_reg(unsigned int port_num,
spin_lock_irqsave(&mv643xx_eth_phy_lock, flags);
/* wait for the SMI register to become available */
- for (i = 0; mv_read(MV643XX_ETH_SMI_REG) & ETH_SMI_BUSY; i++) {
+ for (i = 0; mv_read(SMI_REG) & ETH_SMI_BUSY; i++) {
if (i == PHY_WAIT_ITERATIONS) {
printk("mv643xx PHY busy timeout, port %d\n", port_num);
goto out;
@@ -2393,11 +2925,11 @@ static void eth_port_read_smi_reg(unsigned int port_num,
udelay(PHY_WAIT_MICRO_SECONDS);
}
- mv_write(MV643XX_ETH_SMI_REG,
+ mv_write(SMI_REG,
(phy_addr << 16) | (phy_reg << 21) | ETH_SMI_OPCODE_READ);
/* now wait for the data to be valid */
- for (i = 0; !(mv_read(MV643XX_ETH_SMI_REG) & ETH_SMI_READ_VALID); i++) {
+ for (i = 0; !(mv_read(SMI_REG) & ETH_SMI_READ_VALID); i++) {
if (i == PHY_WAIT_ITERATIONS) {
printk("mv643xx PHY read timeout, port %d\n", port_num);
goto out;
@@ -2405,7 +2937,7 @@ static void eth_port_read_smi_reg(unsigned int port_num,
udelay(PHY_WAIT_MICRO_SECONDS);
}
- *value = mv_read(MV643XX_ETH_SMI_REG) & 0xffff;
+ *value = mv_read(SMI_REG) & 0xffff;
out:
spin_unlock_irqrestore(&mv643xx_eth_phy_lock, flags);
}
@@ -2443,7 +2975,7 @@ static void eth_port_write_smi_reg(unsigned int eth_port_num,
spin_lock_irqsave(&mv643xx_eth_phy_lock, flags);
/* wait for the SMI register to become available */
- for (i = 0; mv_read(MV643XX_ETH_SMI_REG) & ETH_SMI_BUSY; i++) {
+ for (i = 0; mv_read(SMI_REG) & ETH_SMI_BUSY; i++) {
if (i == PHY_WAIT_ITERATIONS) {
printk("mv643xx PHY busy timeout, port %d\n",
eth_port_num);
@@ -2452,7 +2984,7 @@ static void eth_port_write_smi_reg(unsigned int eth_port_num,
udelay(PHY_WAIT_MICRO_SECONDS);
}
- mv_write(MV643XX_ETH_SMI_REG, (phy_addr << 16) | (phy_reg << 21) |
+ mv_write(SMI_REG, (phy_addr << 16) | (phy_reg << 21) |
ETH_SMI_OPCODE_WRITE | (value & 0xffff));
out:
spin_unlock_irqrestore(&mv643xx_eth_phy_lock, flags);
@@ -2742,6 +3274,7 @@ static const struct ethtool_ops mv643xx_ethtool_ops = {
.get_drvinfo = mv643xx_get_drvinfo,
.get_link = mv643xx_eth_get_link,
.set_sg = ethtool_op_set_sg,
+ .get_sset_count = mv643xx_get_sset_count,
.get_ethtool_stats = mv643xx_get_ethtool_stats,
.get_strings = mv643xx_get_strings,
.nway_reset = mv643xx_eth_nway_restart,
diff --git a/drivers/net/mv643xx_eth.h b/drivers/net/mv643xx_eth.h
deleted file mode 100644
index be669eb23788..000000000000
--- a/drivers/net/mv643xx_eth.h
+++ /dev/null
@@ -1,370 +0,0 @@
-#ifndef __MV643XX_ETH_H__
-#define __MV643XX_ETH_H__
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/mii.h>
-
-#include <linux/mv643xx.h>
-
-#include <asm/dma-mapping.h>
-
-/* Checksum offload for Tx works for most packets, but
- * fails if previous packet sent did not use hw csum
- */
-#define MV643XX_CHECKSUM_OFFLOAD_TX
-#define MV643XX_NAPI
-#define MV643XX_TX_FAST_REFILL
-#undef MV643XX_COAL
-
-/*
- * Number of RX / TX descriptors on RX / TX rings.
- * Note that allocating RX descriptors is done by allocating the RX
- * ring AND a preallocated RX buffers (skb's) for each descriptor.
- * The TX descriptors only allocates the TX descriptors ring,
- * with no pre allocated TX buffers (skb's are allocated by higher layers.
- */
-
-/* Default TX ring size is 1000 descriptors */
-#define MV643XX_DEFAULT_TX_QUEUE_SIZE 1000
-
-/* Default RX ring size is 400 descriptors */
-#define MV643XX_DEFAULT_RX_QUEUE_SIZE 400
-
-#define MV643XX_TX_COAL 100
-#ifdef MV643XX_COAL
-#define MV643XX_RX_COAL 100
-#endif
-
-#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
-#define MAX_DESCS_PER_SKB (MAX_SKB_FRAGS + 1)
-#else
-#define MAX_DESCS_PER_SKB 1
-#endif
-
-#define ETH_VLAN_HLEN 4
-#define ETH_FCS_LEN 4
-#define ETH_HW_IP_ALIGN 2 /* hw aligns IP header */
-#define ETH_WRAPPER_LEN (ETH_HW_IP_ALIGN + ETH_HLEN + \
- ETH_VLAN_HLEN + ETH_FCS_LEN)
-#define ETH_RX_SKB_SIZE (dev->mtu + ETH_WRAPPER_LEN + dma_get_cache_alignment())
-
-#define ETH_RX_QUEUES_ENABLED (1 << 0) /* use only Q0 for receive */
-#define ETH_TX_QUEUES_ENABLED (1 << 0) /* use only Q0 for transmit */
-
-#define ETH_INT_CAUSE_RX_DONE (ETH_RX_QUEUES_ENABLED << 2)
-#define ETH_INT_CAUSE_RX_ERROR (ETH_RX_QUEUES_ENABLED << 9)
-#define ETH_INT_CAUSE_RX (ETH_INT_CAUSE_RX_DONE | ETH_INT_CAUSE_RX_ERROR)
-#define ETH_INT_CAUSE_EXT 0x00000002
-#define ETH_INT_UNMASK_ALL (ETH_INT_CAUSE_RX | ETH_INT_CAUSE_EXT)
-
-#define ETH_INT_CAUSE_TX_DONE (ETH_TX_QUEUES_ENABLED << 0)
-#define ETH_INT_CAUSE_TX_ERROR (ETH_TX_QUEUES_ENABLED << 8)
-#define ETH_INT_CAUSE_TX (ETH_INT_CAUSE_TX_DONE | ETH_INT_CAUSE_TX_ERROR)
-#define ETH_INT_CAUSE_PHY 0x00010000
-#define ETH_INT_CAUSE_STATE 0x00100000
-#define ETH_INT_UNMASK_ALL_EXT (ETH_INT_CAUSE_TX | ETH_INT_CAUSE_PHY | \
- ETH_INT_CAUSE_STATE)
-
-#define ETH_INT_MASK_ALL 0x00000000
-#define ETH_INT_MASK_ALL_EXT 0x00000000
-
-#define PHY_WAIT_ITERATIONS 1000 /* 1000 iterations * 10uS = 10mS max */
-#define PHY_WAIT_MICRO_SECONDS 10
-
-/* Buffer offset from buffer pointer */
-#define RX_BUF_OFFSET 0x2
-
-/* Gigabit Ethernet Unit Global Registers */
-
-/* MIB Counters register definitions */
-#define ETH_MIB_GOOD_OCTETS_RECEIVED_LOW 0x0
-#define ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH 0x4
-#define ETH_MIB_BAD_OCTETS_RECEIVED 0x8
-#define ETH_MIB_INTERNAL_MAC_TRANSMIT_ERR 0xc
-#define ETH_MIB_GOOD_FRAMES_RECEIVED 0x10
-#define ETH_MIB_BAD_FRAMES_RECEIVED 0x14
-#define ETH_MIB_BROADCAST_FRAMES_RECEIVED 0x18
-#define ETH_MIB_MULTICAST_FRAMES_RECEIVED 0x1c
-#define ETH_MIB_FRAMES_64_OCTETS 0x20
-#define ETH_MIB_FRAMES_65_TO_127_OCTETS 0x24
-#define ETH_MIB_FRAMES_128_TO_255_OCTETS 0x28
-#define ETH_MIB_FRAMES_256_TO_511_OCTETS 0x2c
-#define ETH_MIB_FRAMES_512_TO_1023_OCTETS 0x30
-#define ETH_MIB_FRAMES_1024_TO_MAX_OCTETS 0x34
-#define ETH_MIB_GOOD_OCTETS_SENT_LOW 0x38
-#define ETH_MIB_GOOD_OCTETS_SENT_HIGH 0x3c
-#define ETH_MIB_GOOD_FRAMES_SENT 0x40
-#define ETH_MIB_EXCESSIVE_COLLISION 0x44
-#define ETH_MIB_MULTICAST_FRAMES_SENT 0x48
-#define ETH_MIB_BROADCAST_FRAMES_SENT 0x4c
-#define ETH_MIB_UNREC_MAC_CONTROL_RECEIVED 0x50
-#define ETH_MIB_FC_SENT 0x54
-#define ETH_MIB_GOOD_FC_RECEIVED 0x58
-#define ETH_MIB_BAD_FC_RECEIVED 0x5c
-#define ETH_MIB_UNDERSIZE_RECEIVED 0x60
-#define ETH_MIB_FRAGMENTS_RECEIVED 0x64
-#define ETH_MIB_OVERSIZE_RECEIVED 0x68
-#define ETH_MIB_JABBER_RECEIVED 0x6c
-#define ETH_MIB_MAC_RECEIVE_ERROR 0x70
-#define ETH_MIB_BAD_CRC_EVENT 0x74
-#define ETH_MIB_COLLISION 0x78
-#define ETH_MIB_LATE_COLLISION 0x7c
-
-/* Port serial status reg (PSR) */
-#define ETH_INTERFACE_PCM 0x00000001
-#define ETH_LINK_IS_UP 0x00000002
-#define ETH_PORT_AT_FULL_DUPLEX 0x00000004
-#define ETH_RX_FLOW_CTRL_ENABLED 0x00000008
-#define ETH_GMII_SPEED_1000 0x00000010
-#define ETH_MII_SPEED_100 0x00000020
-#define ETH_TX_IN_PROGRESS 0x00000080
-#define ETH_BYPASS_ACTIVE 0x00000100
-#define ETH_PORT_AT_PARTITION_STATE 0x00000200
-#define ETH_PORT_TX_FIFO_EMPTY 0x00000400
-
-/* SMI reg */
-#define ETH_SMI_BUSY 0x10000000 /* 0 - Write, 1 - Read */
-#define ETH_SMI_READ_VALID 0x08000000 /* 0 - Write, 1 - Read */
-#define ETH_SMI_OPCODE_WRITE 0 /* Completion of Read */
-#define ETH_SMI_OPCODE_READ 0x04000000 /* Operation is in progress */
-
-/* Interrupt Cause Register Bit Definitions */
-
-/* SDMA command status fields macros */
-
-/* Tx & Rx descriptors status */
-#define ETH_ERROR_SUMMARY 0x00000001
-
-/* Tx & Rx descriptors command */
-#define ETH_BUFFER_OWNED_BY_DMA 0x80000000
-
-/* Tx descriptors status */
-#define ETH_LC_ERROR 0
-#define ETH_UR_ERROR 0x00000002
-#define ETH_RL_ERROR 0x00000004
-#define ETH_LLC_SNAP_FORMAT 0x00000200
-
-/* Rx descriptors status */
-#define ETH_OVERRUN_ERROR 0x00000002
-#define ETH_MAX_FRAME_LENGTH_ERROR 0x00000004
-#define ETH_RESOURCE_ERROR 0x00000006
-#define ETH_VLAN_TAGGED 0x00080000
-#define ETH_BPDU_FRAME 0x00100000
-#define ETH_UDP_FRAME_OVER_IP_V_4 0x00200000
-#define ETH_OTHER_FRAME_TYPE 0x00400000
-#define ETH_LAYER_2_IS_ETH_V_2 0x00800000
-#define ETH_FRAME_TYPE_IP_V_4 0x01000000
-#define ETH_FRAME_HEADER_OK 0x02000000
-#define ETH_RX_LAST_DESC 0x04000000
-#define ETH_RX_FIRST_DESC 0x08000000
-#define ETH_UNKNOWN_DESTINATION_ADDR 0x10000000
-#define ETH_RX_ENABLE_INTERRUPT 0x20000000
-#define ETH_LAYER_4_CHECKSUM_OK 0x40000000
-
-/* Rx descriptors byte count */
-#define ETH_FRAME_FRAGMENTED 0x00000004
-
-/* Tx descriptors command */
-#define ETH_LAYER_4_CHECKSUM_FIRST_DESC 0x00000400
-#define ETH_FRAME_SET_TO_VLAN 0x00008000
-#define ETH_UDP_FRAME 0x00010000
-#define ETH_GEN_TCP_UDP_CHECKSUM 0x00020000
-#define ETH_GEN_IP_V_4_CHECKSUM 0x00040000
-#define ETH_ZERO_PADDING 0x00080000
-#define ETH_TX_LAST_DESC 0x00100000
-#define ETH_TX_FIRST_DESC 0x00200000
-#define ETH_GEN_CRC 0x00400000
-#define ETH_TX_ENABLE_INTERRUPT 0x00800000
-#define ETH_AUTO_MODE 0x40000000
-
-#define ETH_TX_IHL_SHIFT 11
-
-/* typedefs */
-
-typedef enum _eth_func_ret_status {
- ETH_OK, /* Returned as expected. */
- ETH_ERROR, /* Fundamental error. */
- ETH_RETRY, /* Could not process request. Try later.*/
- ETH_END_OF_JOB, /* Ring has nothing to process. */
- ETH_QUEUE_FULL, /* Ring resource error. */
- ETH_QUEUE_LAST_RESOURCE /* Ring resources about to exhaust. */
-} ETH_FUNC_RET_STATUS;
-
-typedef enum _eth_target {
- ETH_TARGET_DRAM,
- ETH_TARGET_DEVICE,
- ETH_TARGET_CBS,
- ETH_TARGET_PCI0,
- ETH_TARGET_PCI1
-} ETH_TARGET;
-
-/* These are for big-endian machines. Little endian needs different
- * definitions.
- */
-#if defined(__BIG_ENDIAN)
-struct eth_rx_desc {
- u16 byte_cnt; /* Descriptor buffer byte count */
- u16 buf_size; /* Buffer size */
- u32 cmd_sts; /* Descriptor command status */
- u32 next_desc_ptr; /* Next descriptor pointer */
- u32 buf_ptr; /* Descriptor buffer pointer */
-};
-
-struct eth_tx_desc {
- u16 byte_cnt; /* buffer byte count */
- u16 l4i_chk; /* CPU provided TCP checksum */
- u32 cmd_sts; /* Command/status field */
- u32 next_desc_ptr; /* Pointer to next descriptor */
- u32 buf_ptr; /* pointer to buffer for this descriptor*/
-};
-
-#elif defined(__LITTLE_ENDIAN)
-struct eth_rx_desc {
- u32 cmd_sts; /* Descriptor command status */
- u16 buf_size; /* Buffer size */
- u16 byte_cnt; /* Descriptor buffer byte count */
- u32 buf_ptr; /* Descriptor buffer pointer */
- u32 next_desc_ptr; /* Next descriptor pointer */
-};
-
-struct eth_tx_desc {
- u32 cmd_sts; /* Command/status field */
- u16 l4i_chk; /* CPU provided TCP checksum */
- u16 byte_cnt; /* buffer byte count */
- u32 buf_ptr; /* pointer to buffer for this descriptor*/
- u32 next_desc_ptr; /* Pointer to next descriptor */
-};
-#else
-#error One of __BIG_ENDIAN or __LITTLE_ENDIAN must be defined
-#endif
-
-/* Unified struct for Rx and Tx operations. The user is not required to */
-/* be familier with neither Tx nor Rx descriptors. */
-struct pkt_info {
- unsigned short byte_cnt; /* Descriptor buffer byte count */
- unsigned short l4i_chk; /* Tx CPU provided TCP Checksum */
- unsigned int cmd_sts; /* Descriptor command status */
- dma_addr_t buf_ptr; /* Descriptor buffer pointer */
- struct sk_buff *return_info; /* User resource return information */
-};
-
-/* Ethernet port specific information */
-
-struct mv643xx_mib_counters {
- u64 good_octets_received;
- u32 bad_octets_received;
- u32 internal_mac_transmit_err;
- u32 good_frames_received;
- u32 bad_frames_received;
- u32 broadcast_frames_received;
- u32 multicast_frames_received;
- u32 frames_64_octets;
- u32 frames_65_to_127_octets;
- u32 frames_128_to_255_octets;
- u32 frames_256_to_511_octets;
- u32 frames_512_to_1023_octets;
- u32 frames_1024_to_max_octets;
- u64 good_octets_sent;
- u32 good_frames_sent;
- u32 excessive_collision;
- u32 multicast_frames_sent;
- u32 broadcast_frames_sent;
- u32 unrec_mac_control_received;
- u32 fc_sent;
- u32 good_fc_received;
- u32 bad_fc_received;
- u32 undersize_received;
- u32 fragments_received;
- u32 oversize_received;
- u32 jabber_received;
- u32 mac_receive_error;
- u32 bad_crc_event;
- u32 collision;
- u32 late_collision;
-};
-
-struct mv643xx_private {
- int port_num; /* User Ethernet port number */
-
- u32 rx_sram_addr; /* Base address of rx sram area */
- u32 rx_sram_size; /* Size of rx sram area */
- u32 tx_sram_addr; /* Base address of tx sram area */
- u32 tx_sram_size; /* Size of tx sram area */
-
- int rx_resource_err; /* Rx ring resource error flag */
-
- /* Tx/Rx rings managment indexes fields. For driver use */
-
- /* Next available and first returning Rx resource */
- int rx_curr_desc_q, rx_used_desc_q;
-
- /* Next available and first returning Tx resource */
- int tx_curr_desc_q, tx_used_desc_q;
-
-#ifdef MV643XX_TX_FAST_REFILL
- u32 tx_clean_threshold;
-#endif
-
- struct eth_rx_desc *p_rx_desc_area;
- dma_addr_t rx_desc_dma;
- int rx_desc_area_size;
- struct sk_buff **rx_skb;
-
- struct eth_tx_desc *p_tx_desc_area;
- dma_addr_t tx_desc_dma;
- int tx_desc_area_size;
- struct sk_buff **tx_skb;
-
- struct work_struct tx_timeout_task;
-
- struct net_device *dev;
- struct napi_struct napi;
- struct net_device_stats stats;
- struct mv643xx_mib_counters mib_counters;
- spinlock_t lock;
- /* Size of Tx Ring per queue */
- int tx_ring_size;
- /* Number of tx descriptors in use */
- int tx_desc_count;
- /* Size of Rx Ring per queue */
- int rx_ring_size;
- /* Number of rx descriptors in use */
- int rx_desc_count;
-
- /*
- * Used in case RX Ring is empty, which can be caused when
- * system does not have resources (skb's)
- */
- struct timer_list timeout;
-
- u32 rx_int_coal;
- u32 tx_int_coal;
- struct mii_if_info mii;
-};
-
-/* Port operation control routines */
-static void eth_port_init(struct mv643xx_private *mp);
-static void eth_port_reset(unsigned int eth_port_num);
-static void eth_port_start(struct net_device *dev);
-
-/* PHY and MIB routines */
-static void ethernet_phy_reset(unsigned int eth_port_num);
-
-static void eth_port_write_smi_reg(unsigned int eth_port_num,
- unsigned int phy_reg, unsigned int value);
-
-static void eth_port_read_smi_reg(unsigned int eth_port_num,
- unsigned int phy_reg, unsigned int *value);
-
-static void eth_clear_mib_counters(unsigned int eth_port_num);
-
-/* Port data flow control routines */
-static ETH_FUNC_RET_STATUS eth_port_receive(struct mv643xx_private *mp,
- struct pkt_info *p_pkt_info);
-static ETH_FUNC_RET_STATUS eth_rx_return_buff(struct mv643xx_private *mp,
- struct pkt_info *p_pkt_info);
-
-#endif /* __MV643XX_ETH_H__ */
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index e8afa101433e..0f306ddb5630 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -75,7 +75,7 @@
#include "myri10ge_mcp.h"
#include "myri10ge_mcp_gen_header.h"
-#define MYRI10GE_VERSION_STR "1.3.2-1.269"
+#define MYRI10GE_VERSION_STR "1.3.2-1.287"
MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
MODULE_AUTHOR("Maintainer: help@myri.com");
@@ -214,6 +214,8 @@ struct myri10ge_priv {
unsigned long serial_number;
int vendor_specific_offset;
int fw_multicast_support;
+ unsigned long features;
+ u32 max_tso6;
u32 read_dma;
u32 write_dma;
u32 read_write_dma;
@@ -311,6 +313,7 @@ MODULE_PARM_DESC(myri10ge_wcfifo, "Enable WC Fifo when WC is enabled\n");
#define myri10ge_pio_copy(to,from,size) __iowrite64_copy(to,from,size/8)
static void myri10ge_set_multicast_list(struct net_device *dev);
+static int myri10ge_sw_tso(struct sk_buff *skb, struct net_device *dev);
static inline void put_be32(__be32 val, __be32 __iomem * p)
{
@@ -612,6 +615,7 @@ static int myri10ge_load_firmware(struct myri10ge_priv *mgp)
__be32 buf[16];
u32 dma_low, dma_high, size;
int status, i;
+ struct myri10ge_cmd cmd;
size = 0;
status = myri10ge_load_hotplug_firmware(mgp, &size);
@@ -688,6 +692,14 @@ static int myri10ge_load_firmware(struct myri10ge_priv *mgp)
dev_info(&mgp->pdev->dev, "handoff confirmed\n");
myri10ge_dummy_rdma(mgp, 1);
+ /* probe for IPv6 TSO support */
+ mgp->features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO;
+ status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_MAX_TSO6_HDR_SIZE,
+ &cmd, 0);
+ if (status == 0) {
+ mgp->max_tso6 = cmd.data0;
+ mgp->features |= NETIF_F_TSO6;
+ }
return 0;
}
@@ -1047,7 +1059,8 @@ myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx,
hlen = MYRI10GE_HLEN > len ? len : MYRI10GE_HLEN;
- /* allocate an skb to attach the page(s) to. */
+ /* allocate an skb to attach the page(s) to. This is done
+ * after trying LRO, so as to avoid skb allocation overheads */
skb = netdev_alloc_skb(dev, MYRI10GE_HLEN + 16);
if (unlikely(skb == NULL)) {
@@ -1138,7 +1151,7 @@ static inline int myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int budget)
u16 length;
__wsum checksum;
- while (rx_done->entry[idx].length != 0 && work_done++ < budget) {
+ while (rx_done->entry[idx].length != 0 && work_done < budget) {
length = ntohs(rx_done->entry[idx].length);
rx_done->entry[idx].length = 0;
checksum = csum_unfold(rx_done->entry[idx].checksum);
@@ -1154,6 +1167,7 @@ static inline int myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int budget)
rx_bytes += rx_ok * (unsigned long)length;
cnt++;
idx = cnt & (myri10ge_max_intr_slots - 1);
+ work_done++;
}
rx_done->idx = idx;
rx_done->cnt = cnt;
@@ -1217,15 +1231,15 @@ static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp)
static int myri10ge_poll(struct napi_struct *napi, int budget)
{
- struct myri10ge_priv *mgp = container_of(napi, struct myri10ge_priv, napi);
+ struct myri10ge_priv *mgp =
+ container_of(napi, struct myri10ge_priv, napi);
struct net_device *netdev = mgp->dev;
- struct myri10ge_rx_done *rx_done = &mgp->rx_done;
int work_done;
/* process as many rx events as NAPI will allow */
work_done = myri10ge_clean_rx_done(mgp, budget);
- if (rx_done->entry[rx_done->idx].length == 0 || !netif_running(netdev)) {
+ if (work_done < budget || !netif_running(netdev)) {
netif_rx_complete(netdev, napi);
put_be32(htonl(3), mgp->irq_claim);
}
@@ -1382,6 +1396,18 @@ static int myri10ge_set_rx_csum(struct net_device *netdev, u32 csum_enabled)
return 0;
}
+static int myri10ge_set_tso(struct net_device *netdev, u32 tso_enabled)
+{
+ struct myri10ge_priv *mgp = netdev_priv(netdev);
+ unsigned long flags = mgp->features & (NETIF_F_TSO6 | NETIF_F_TSO);
+
+ if (tso_enabled)
+ netdev->features |= flags;
+ else
+ netdev->features &= ~flags;
+ return 0;
+}
+
static const char myri10ge_gstrings_stats[][ETH_GSTRING_LEN] = {
"rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors",
"tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions",
@@ -1506,7 +1532,7 @@ static const struct ethtool_ops myri10ge_ethtool_ops = {
.set_rx_csum = myri10ge_set_rx_csum,
.set_tx_csum = ethtool_op_set_tx_hw_csum,
.set_sg = ethtool_op_set_sg,
- .set_tso = ethtool_op_set_tso,
+ .set_tso = myri10ge_set_tso,
.get_link = ethtool_op_get_link,
.get_strings = myri10ge_get_strings,
.get_sset_count = myri10ge_get_sset_count,
@@ -2164,7 +2190,8 @@ again:
pseudo_hdr_offset = cksum_offset + skb->csum_offset;
/* If the headers are excessively large, then we must
* fall back to a software checksum */
- if (unlikely(cksum_offset > 255 || pseudo_hdr_offset > 127)) {
+ if (unlikely(!mss && (cksum_offset > 255 ||
+ pseudo_hdr_offset > 127))) {
if (skb_checksum_help(skb))
goto drop;
cksum_offset = 0;
@@ -2184,9 +2211,18 @@ again:
/* negative cum_len signifies to the
* send loop that we are still in the
* header portion of the TSO packet.
- * TSO header must be at most 134 bytes long */
+ * TSO header can be at most 1KB long */
cum_len = -(skb_transport_offset(skb) + tcp_hdrlen(skb));
+ /* for IPv6 TSO, the checksum offset stores the
+ * TCP header length, to save the firmware from
+ * the need to parse the headers */
+ if (skb_is_gso_v6(skb)) {
+ cksum_offset = tcp_hdrlen(skb);
+ /* Can only handle headers <= max_tso6 long */
+ if (unlikely(-cum_len > mgp->max_tso6))
+ return myri10ge_sw_tso(skb, dev);
+ }
/* for TSO, pseudo_hdr_offset holds mss.
* The firmware figures out where to put
* the checksum by parsing the header. */
@@ -2301,10 +2337,12 @@ again:
req++;
count++;
rdma_count++;
- if (unlikely(cksum_offset > seglen))
- cksum_offset -= seglen;
- else
- cksum_offset = 0;
+ if (cksum_offset != 0 && !(mss && skb_is_gso_v6(skb))) {
+ if (unlikely(cksum_offset > seglen))
+ cksum_offset -= seglen;
+ else
+ cksum_offset = 0;
+ }
}
if (frag_idx == frag_cnt)
break;
@@ -2387,6 +2425,41 @@ drop:
}
+static int myri10ge_sw_tso(struct sk_buff *skb, struct net_device *dev)
+{
+ struct sk_buff *segs, *curr;
+ struct myri10ge_priv *mgp = dev->priv;
+ int status;
+
+ segs = skb_gso_segment(skb, dev->features & ~NETIF_F_TSO6);
+ if (unlikely(IS_ERR(segs)))
+ goto drop;
+
+ while (segs) {
+ curr = segs;
+ segs = segs->next;
+ curr->next = NULL;
+ status = myri10ge_xmit(curr, dev);
+ if (status != 0) {
+ dev_kfree_skb_any(curr);
+ if (segs != NULL) {
+ curr = segs;
+ segs = segs->next;
+ curr->next = NULL;
+ dev_kfree_skb_any(segs);
+ }
+ goto drop;
+ }
+ }
+ dev_kfree_skb_any(skb);
+ return 0;
+
+drop:
+ dev_kfree_skb_any(skb);
+ mgp->stats.tx_dropped += 1;
+ return 0;
+}
+
static struct net_device_stats *myri10ge_get_stats(struct net_device *dev)
{
struct myri10ge_priv *mgp = netdev_priv(dev);
@@ -2706,7 +2779,6 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp)
}
#ifdef CONFIG_PM
-
static int myri10ge_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct myri10ge_priv *mgp;
@@ -2787,7 +2859,6 @@ abort_with_enabled:
return -EIO;
}
-
#endif /* CONFIG_PM */
static u32 myri10ge_read_reboot(struct myri10ge_priv *mgp)
@@ -2954,8 +3025,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
mgp = netdev_priv(netdev);
mgp->dev = netdev;
- netif_napi_add(netdev, &mgp->napi,
- myri10ge_poll, myri10ge_napi_weight);
+ netif_napi_add(netdev, &mgp->napi, myri10ge_poll, myri10ge_napi_weight);
mgp->pdev = pdev;
mgp->csum_flag = MXGEFW_FLAGS_CKSUM;
mgp->pause = myri10ge_flow_control;
@@ -2988,7 +3058,8 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (status != 0) {
dac_enabled = 0;
dev_err(&pdev->dev,
- "64-bit pci address mask was refused, trying 32-bit");
+ "64-bit pci address mask was refused, "
+ "trying 32-bit\n");
status = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
}
if (status != 0) {
@@ -3077,7 +3148,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->change_mtu = myri10ge_change_mtu;
netdev->set_multicast_list = myri10ge_set_multicast_list;
netdev->set_mac_address = myri10ge_set_mac_address;
- netdev->features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO;
+ netdev->features = mgp->features;
if (dac_enabled)
netdev->features |= NETIF_F_HIGHDMA;
diff --git a/drivers/net/myri10ge/myri10ge_mcp.h b/drivers/net/myri10ge/myri10ge_mcp.h
index a1d2a22296a9..58e57178c563 100644
--- a/drivers/net/myri10ge/myri10ge_mcp.h
+++ b/drivers/net/myri10ge/myri10ge_mcp.h
@@ -10,7 +10,7 @@ struct mcp_dma_addr {
__be32 low;
};
-/* 4 Bytes */
+/* 4 Bytes. 8 Bytes for NDIS drivers. */
struct mcp_slot {
__sum16 checksum;
__be16 length;
@@ -205,8 +205,87 @@ enum myri10ge_mcp_cmd_type {
/* same than DMA_TEST (same args) but abort with UNALIGNED on unaligned
* chipset */
- MXGEFW_CMD_UNALIGNED_STATUS
- /* return data = boolean, true if the chipset is known to be unaligned */
+ MXGEFW_CMD_UNALIGNED_STATUS,
+ /* return data = boolean, true if the chipset is known to be unaligned */
+
+ MXGEFW_CMD_ALWAYS_USE_N_BIG_BUFFERS,
+ /* data0 = number of big buffers to use. It must be 0 or a power of 2.
+ * 0 indicates that the NIC consumes as many buffers as they are required
+ * for packet. This is the default behavior.
+ * A power of 2 number indicates that the NIC always uses the specified
+ * number of buffers for each big receive packet.
+ * It is up to the driver to ensure that this value is big enough for
+ * the NIC to be able to receive maximum-sized packets.
+ */
+
+ MXGEFW_CMD_GET_MAX_RSS_QUEUES,
+ MXGEFW_CMD_ENABLE_RSS_QUEUES,
+ /* data0 = number of slices n (0, 1, ..., n-1) to enable
+ * data1 = interrupt mode. 0=share one INTx/MSI, 1=use one MSI-X per queue.
+ * If all queues share one interrupt, the driver must have set
+ * RSS_SHARED_INTERRUPT_DMA before enabling queues.
+ */
+ MXGEFW_CMD_GET_RSS_SHARED_INTERRUPT_MASK_OFFSET,
+ MXGEFW_CMD_SET_RSS_SHARED_INTERRUPT_DMA,
+ /* data0, data1 = bus address lsw, msw */
+ MXGEFW_CMD_GET_RSS_TABLE_OFFSET,
+ /* get the offset of the indirection table */
+ MXGEFW_CMD_SET_RSS_TABLE_SIZE,
+ /* set the size of the indirection table */
+ MXGEFW_CMD_GET_RSS_KEY_OFFSET,
+ /* get the offset of the secret key */
+ MXGEFW_CMD_RSS_KEY_UPDATED,
+ /* tell nic that the secret key's been updated */
+ MXGEFW_CMD_SET_RSS_ENABLE,
+ /* data0 = enable/disable rss
+ * 0: disable rss. nic does not distribute receive packets.
+ * 1: enable rss. nic distributes receive packets among queues.
+ * data1 = hash type
+ * 1: IPV4
+ * 2: TCP_IPV4
+ * 3: IPV4 | TCP_IPV4
+ */
+
+ MXGEFW_CMD_GET_MAX_TSO6_HDR_SIZE,
+ /* Return data = the max. size of the entire headers of a IPv6 TSO packet.
+ * If the header size of a IPv6 TSO packet is larger than the specified
+ * value, then the driver must not use TSO.
+ * This size restriction only applies to IPv6 TSO.
+ * For IPv4 TSO, the maximum size of the headers is fixed, and the NIC
+ * always has enough header buffer to store maximum-sized headers.
+ */
+
+ MXGEFW_CMD_SET_TSO_MODE,
+ /* data0 = TSO mode.
+ * 0: Linux/FreeBSD style (NIC default)
+ * 1: NDIS/NetBSD style
+ */
+
+ MXGEFW_CMD_MDIO_READ,
+ /* data0 = dev_addr (PMA/PMD or PCS ...), data1 = register/addr */
+ MXGEFW_CMD_MDIO_WRITE,
+ /* data0 = dev_addr, data1 = register/addr, data2 = value */
+
+ MXGEFW_CMD_XFP_I2C_READ,
+ /* Starts to get a fresh copy of one byte or of the whole xfp i2c table, the
+ * obtained data is cached inside the xaui-xfi chip :
+ * data0 : "all" flag : 0 => get one byte, 1=> get 256 bytes,
+ * data1 : if (data0 == 0): index of byte to refresh [ not used otherwise ]
+ * The operation might take ~1ms for a single byte or ~65ms when refreshing all 256 bytes
+ * During the i2c operation, MXGEFW_CMD_XFP_I2C_READ or MXGEFW_CMD_XFP_BYTE attempts
+ * will return MXGEFW_CMD_ERROR_BUSY
+ */
+ MXGEFW_CMD_XFP_BYTE,
+ /* Return the last obtained copy of a given byte in the xfp i2c table
+ * (copy cached during the last relevant MXGEFW_CMD_XFP_I2C_READ)
+ * data0 : index of the desired table entry
+ * Return data = the byte stored at the requested index in the table
+ */
+
+ MXGEFW_CMD_GET_VPUMP_OFFSET,
+ /* Return data = NIC memory offset of mcp_vpump_public_global */
+ MXGEFW_CMD_RESET_VPUMP,
+ /* Resets the VPUMP state */
};
enum myri10ge_mcp_cmd_status {
@@ -220,7 +299,10 @@ enum myri10ge_mcp_cmd_status {
MXGEFW_CMD_ERROR_BAD_PORT,
MXGEFW_CMD_ERROR_RESOURCES,
MXGEFW_CMD_ERROR_MULTICAST,
- MXGEFW_CMD_ERROR_UNALIGNED
+ MXGEFW_CMD_ERROR_UNALIGNED,
+ MXGEFW_CMD_ERROR_NO_MDIO,
+ MXGEFW_CMD_ERROR_XFP_FAILURE,
+ MXGEFW_CMD_ERROR_XFP_ABSENT
};
#define MXGEFW_OLD_IRQ_DATA_LEN 40
diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c
index 8d29319cc5cb..656a260fc956 100644
--- a/drivers/net/myri_sbus.c
+++ b/drivers/net/myri_sbus.c
@@ -134,7 +134,7 @@ static int myri_do_handshake(struct myri_eth *mp)
myri_disable_irq(mp->lregs, cregs);
- while (tick++ <= 25) {
+ while (tick++ < 25) {
u32 softstate;
/* Wake it up. */
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index 527f9dcc7f69..87cde062fd63 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -864,6 +864,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
np = netdev_priv(dev);
netif_napi_add(dev, &np->napi, natsemi_poll, 64);
+ np->dev = dev;
np->pci_dev = pdev;
pci_set_drvdata(pdev, dev);
@@ -996,7 +997,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
a delay. Note that pre-2.0.34 kernels had a cache-alignment bug that
made udelay() unreliable.
The old method of using an ISA access as a delay, __SLOW_DOWN_IO__, is
- depricated.
+ deprecated.
*/
#define eeprom_delay(ee_addr) readl(ee_addr)
@@ -1576,7 +1577,7 @@ static int netdev_open(struct net_device *dev)
/* Set the timer to check for link beat. */
init_timer(&np->timer);
- np->timer.expires = jiffies + NATSEMI_TIMER_FREQ;
+ np->timer.expires = round_jiffies(jiffies + NATSEMI_TIMER_FREQ);
np->timer.data = (unsigned long)dev;
np->timer.function = &netdev_timer; /* timer handler */
add_timer(&np->timer);
@@ -1856,7 +1857,11 @@ static void netdev_timer(unsigned long data)
next_tick = 1;
}
}
- mod_timer(&np->timer, jiffies + next_tick);
+
+ if (next_tick > 1)
+ mod_timer(&np->timer, round_jiffies(jiffies + next_tick));
+ else
+ mod_timer(&np->timer, jiffies + next_tick);
}
static void dump_ring(struct net_device *dev)
@@ -3310,13 +3315,19 @@ static int natsemi_resume (struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata (pdev);
struct netdev_private *np = netdev_priv(dev);
+ int ret = 0;
rtnl_lock();
if (netif_device_present(dev))
goto out;
if (netif_running(dev)) {
BUG_ON(!np->hands_off);
- pci_enable_device(pdev);
+ ret = pci_enable_device(pdev);
+ if (ret < 0) {
+ dev_err(&pdev->dev,
+ "pci_enable_device() failed: %d\n", ret);
+ goto out;
+ }
/* pci_power_on(pdev); */
napi_enable(&np->napi);
@@ -3331,12 +3342,12 @@ static int natsemi_resume (struct pci_dev *pdev)
spin_unlock_irq(&np->lock);
enable_irq(dev->irq);
- mod_timer(&np->timer, jiffies + 1*HZ);
+ mod_timer(&np->timer, round_jiffies(jiffies + 1*HZ));
}
netif_device_attach(dev);
out:
rtnl_unlock();
- return 0;
+ return ret;
}
#endif /* CONFIG_PM */
diff --git a/drivers/net/ne-h8300.c b/drivers/net/ne-h8300.c
index 368f2560856d..fbc7531d3c7d 100644
--- a/drivers/net/ne-h8300.c
+++ b/drivers/net/ne-h8300.c
@@ -93,7 +93,7 @@ static int __init init_reg_offset(struct net_device *dev,unsigned long base_addr
bus_width = *(volatile unsigned char *)ABWCR;
bus_width &= 1 << ((base_addr >> 21) & 7);
- for (i = 0; i < sizeof(reg_offset) / sizeof(u32); i++)
+ for (i = 0; i < ARRAY_SIZE(reg_offset); i++)
if (bus_width == 0)
reg_offset[i] = i * 2 + 1;
else
@@ -115,7 +115,7 @@ static int h8300_ne_irq[] = {EXT_IRQ5};
static inline int init_dev(struct net_device *dev)
{
- if (h8300_ne_count < (sizeof(h8300_ne_base) / sizeof(unsigned long))) {
+ if (h8300_ne_count < ARRAY_SIZE(h8300_ne_base)) {
dev->base_addr = h8300_ne_base[h8300_ne_count];
dev->irq = h8300_ne_irq[h8300_ne_count];
h8300_ne_count++;
diff --git a/drivers/net/netx-eth.c b/drivers/net/netx-eth.c
index eb0aff787dfd..5267e031daa0 100644
--- a/drivers/net/netx-eth.c
+++ b/drivers/net/netx-eth.c
@@ -128,8 +128,8 @@ netx_eth_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev)
FIFO_PTR_FRAMELEN(len));
ndev->trans_start = jiffies;
- dev->stats.tx_packets++;
- dev->stats.tx_bytes += skb->len;
+ ndev->stats.tx_packets++;
+ ndev->stats.tx_bytes += skb->len;
netif_stop_queue(ndev);
spin_unlock_irq(&priv->lock);
@@ -155,7 +155,7 @@ static void netx_eth_receive(struct net_device *ndev)
if (unlikely(skb == NULL)) {
printk(KERN_NOTICE "%s: Low memory, packet dropped.\n",
ndev->name);
- dev->stats.rx_dropped++;
+ ndev->stats.rx_dropped++;
return;
}
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 2a1d6d7ec351..a80f0cd6b528 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -53,9 +53,6 @@ static char netxen_nic_driver_string[] = "NetXen Network Driver version "
#define NETXEN_ADAPTER_UP_MAGIC 777
#define NETXEN_NIC_PEG_TUNE 0
-#define DMA_32BIT_MASK 0x00000000ffffffffULL
-#define DMA_35BIT_MASK 0x00000007ffffffffULL
-
/* Local functions to NetXen NIC driver */
static int __devinit netxen_nic_probe(struct pci_dev *pdev,
const struct pci_device_id *ent);
@@ -1271,17 +1268,10 @@ netxen_handle_int(struct netxen_adapter *adapter, struct net_device *netdev)
*/
irqreturn_t netxen_intr(int irq, void *data)
{
- struct netxen_adapter *adapter;
- struct net_device *netdev;
+ struct netxen_adapter *adapter = data;
+ struct net_device *netdev = adapter->netdev;
u32 our_int = 0;
- if (unlikely(!irq)) {
- return IRQ_NONE; /* Not our interrupt */
- }
-
- adapter = (struct netxen_adapter *)data;
- netdev = adapter->netdev;
-
if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
our_int = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
/* not our interrupt */
diff --git a/drivers/net/ni5010.c b/drivers/net/ni5010.c
index 14a768fbce2e..a20005c09e07 100644
--- a/drivers/net/ni5010.c
+++ b/drivers/net/ni5010.c
@@ -518,7 +518,6 @@ static void dump_packet(void *buf, int len)
/* We have a good packet, get it out of the buffer. */
static void ni5010_rx(struct net_device *dev)
{
- struct ni5010_local *lp = netdev_priv(dev);
int ioaddr = dev->base_addr;
unsigned char rcv_stat;
struct sk_buff *skb;
@@ -577,7 +576,6 @@ static void ni5010_rx(struct net_device *dev)
PRINTK2((KERN_DEBUG "%s: Received packet, size=%#4.4x\n",
dev->name, i_pkt_size));
-
}
static int process_xmt_interrupt(struct net_device *dev)
diff --git a/drivers/net/niu.c b/drivers/net/niu.c
index 43bfe7e6b6f5..112ab079ce7d 100644
--- a/drivers/net/niu.c
+++ b/drivers/net/niu.c
@@ -3103,31 +3103,12 @@ static int niu_alloc_tx_ring_info(struct niu *np,
static void niu_size_rbr(struct niu *np, struct rx_ring_info *rp)
{
- u16 bs;
+ u16 bss;
- switch (PAGE_SIZE) {
- case 4 * 1024:
- case 8 * 1024:
- case 16 * 1024:
- case 32 * 1024:
- rp->rbr_block_size = PAGE_SIZE;
- rp->rbr_blocks_per_page = 1;
- break;
+ bss = min(PAGE_SHIFT, 15);
- default:
- if (PAGE_SIZE % (32 * 1024) == 0)
- bs = 32 * 1024;
- else if (PAGE_SIZE % (16 * 1024) == 0)
- bs = 16 * 1024;
- else if (PAGE_SIZE % (8 * 1024) == 0)
- bs = 8 * 1024;
- else if (PAGE_SIZE % (4 * 1024) == 0)
- bs = 4 * 1024;
- else
- BUG();
- rp->rbr_block_size = bs;
- rp->rbr_blocks_per_page = PAGE_SIZE / bs;
- }
+ rp->rbr_block_size = 1 << bss;
+ rp->rbr_blocks_per_page = 1 << (PAGE_SHIFT-bss);
rp->rbr_sizes[0] = 256;
rp->rbr_sizes[1] = 1024;
@@ -6123,19 +6104,19 @@ static int __devinit niu_pci_probe_sprom(struct niu *np)
val = nr64(ESPC_PHY_TYPE);
switch (np->port) {
case 0:
- val = (val & ESPC_PHY_TYPE_PORT0) >>
+ val8 = (val & ESPC_PHY_TYPE_PORT0) >>
ESPC_PHY_TYPE_PORT0_SHIFT;
break;
case 1:
- val = (val & ESPC_PHY_TYPE_PORT1) >>
+ val8 = (val & ESPC_PHY_TYPE_PORT1) >>
ESPC_PHY_TYPE_PORT1_SHIFT;
break;
case 2:
- val = (val & ESPC_PHY_TYPE_PORT2) >>
+ val8 = (val & ESPC_PHY_TYPE_PORT2) >>
ESPC_PHY_TYPE_PORT2_SHIFT;
break;
case 3:
- val = (val & ESPC_PHY_TYPE_PORT3) >>
+ val8 = (val & ESPC_PHY_TYPE_PORT3) >>
ESPC_PHY_TYPE_PORT3_SHIFT;
break;
default:
@@ -6143,9 +6124,9 @@ static int __devinit niu_pci_probe_sprom(struct niu *np)
np->port);
return -EINVAL;
}
- niudbg(PROBE, "SPROM: PHY type %llx\n", (unsigned long long) val);
+ niudbg(PROBE, "SPROM: PHY type %x\n", val8);
- switch (val) {
+ switch (val8) {
case ESPC_PHY_TYPE_1G_COPPER:
/* 1G copper, MII */
np->flags &= ~(NIU_FLAGS_FIBER |
@@ -6175,8 +6156,7 @@ static int __devinit niu_pci_probe_sprom(struct niu *np)
break;
default:
- dev_err(np->device, PFX "Bogus SPROM phy type %llu\n",
- (unsigned long long) val);
+ dev_err(np->device, PFX "Bogus SPROM phy type %u\n", val8);
return -EINVAL;
}
@@ -6213,7 +6193,7 @@ static int __devinit niu_pci_probe_sprom(struct niu *np)
val = nr64(ESPC_MOD_STR_LEN);
niudbg(PROBE, "SPROM: MOD_STR_LEN[%llu]\n",
(unsigned long long) val);
- if (val > 8 * 4)
+ if (val >= 8 * 4)
return -EINVAL;
for (i = 0; i < val; i += 4) {
@@ -6229,7 +6209,7 @@ static int __devinit niu_pci_probe_sprom(struct niu *np)
val = nr64(ESPC_BD_MOD_STR_LEN);
niudbg(PROBE, "SPROM: BD_MOD_STR_LEN[%llu]\n",
(unsigned long long) val);
- if (val > 4 * 4)
+ if (val >= 4 * 4)
return -EINVAL;
for (i = 0; i < val; i += 4) {
@@ -7903,12 +7883,7 @@ static int __init niu_init(void)
{
int err = 0;
- BUILD_BUG_ON((PAGE_SIZE < 4 * 1024) ||
- ((PAGE_SIZE > 32 * 1024) &&
- ((PAGE_SIZE % (32 * 1024)) != 0 &&
- (PAGE_SIZE % (16 * 1024)) != 0 &&
- (PAGE_SIZE % (8 * 1024)) != 0 &&
- (PAGE_SIZE % (4 * 1024)) != 0)));
+ BUILD_BUG_ON(PAGE_SIZE < 4 * 1024);
niu_debug = netif_msg_init(debug, NIU_MSG_DEFAULT);
diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c
index 9f9a421c99b3..09b4fde8d924 100644
--- a/drivers/net/pasemi_mac.c
+++ b/drivers/net/pasemi_mac.c
@@ -550,7 +550,7 @@ static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit)
n = mac->rx->next_to_clean;
- prefetch(RX_RING(mac, n));
+ prefetch(&RX_RING(mac, n));
for (count = 0; count < limit; count++) {
macrx = RX_RING(mac, n);
@@ -580,6 +580,16 @@ static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit)
len = (macrx & XCT_MACRX_LLEN_M) >> XCT_MACRX_LLEN_S;
+ pci_unmap_single(mac->dma_pdev, dma, len, PCI_DMA_FROMDEVICE);
+
+ if (macrx & XCT_MACRX_CRC) {
+ /* CRC error flagged */
+ mac->netdev->stats.rx_errors++;
+ mac->netdev->stats.rx_crc_errors++;
+ dev_kfree_skb_irq(skb);
+ goto next;
+ }
+
if (len < 256) {
struct sk_buff *new_skb;
@@ -595,11 +605,10 @@ static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit)
} else
info->skb = NULL;
- pci_unmap_single(mac->dma_pdev, dma, len, PCI_DMA_FROMDEVICE);
-
info->dma = 0;
- skb_put(skb, len);
+ /* Don't include CRC */
+ skb_put(skb, len-4);
if (likely((macrx & XCT_MACRX_HTY_M) == XCT_MACRX_HTY_IPV4_OK)) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -614,6 +623,7 @@ static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit)
skb->protocol = eth_type_trans(skb, mac->netdev);
netif_receive_skb(skb);
+next:
RX_RING(mac, n) = 0;
RX_RING(mac, n+1) = 0;
@@ -1126,7 +1136,7 @@ static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev)
unsigned long flags;
int i, nfrags;
- dflags = XCT_MACTX_O | XCT_MACTX_ST | XCT_MACTX_SS | XCT_MACTX_CRC_PAD;
+ dflags = XCT_MACTX_O | XCT_MACTX_ST | XCT_MACTX_CRC_PAD;
if (skb->ip_summed == CHECKSUM_PARTIAL) {
const unsigned char *nh = skb_network_header(skb);
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
index 73dcbb7296da..ad134a61302a 100644
--- a/drivers/net/pcmcia/3c574_cs.c
+++ b/drivers/net/pcmcia/3c574_cs.c
@@ -274,7 +274,7 @@ static int tc574_probe(struct pcmcia_device *link)
spin_lock_init(&lp->window_lock);
link->io.NumPorts1 = 32;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_HANDLE_PRESENT;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->irq.Handler = &el3_interrupt;
link->irq.Instance = dev;
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
index 32076ca6a9e1..a98fe07cce70 100644
--- a/drivers/net/pcmcia/3c589_cs.c
+++ b/drivers/net/pcmcia/3c589_cs.c
@@ -188,7 +188,7 @@ static int tc589_probe(struct pcmcia_device *link)
spin_lock_init(&lp->lock);
link->io.NumPorts1 = 16;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_HANDLE_PRESENT;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->irq.Handler = &el3_interrupt;
link->irq.Instance = dev;
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index a95a2cae6b23..8d910a372f89 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -158,7 +158,7 @@ static int axnet_probe(struct pcmcia_device *link)
info = PRIV(dev);
info->p_dev = link;
link->priv = dev;
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+ link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->conf.Attributes = CONF_ENABLE_IRQ;
link->conf.IntType = INT_MEMORY_AND_IO;
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index 62844677c784..8c719b4df544 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -249,7 +249,7 @@ static int fmvj18x_probe(struct pcmcia_device *link)
link->io.IOAddrLines = 5;
/* Interrupt setup */
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_HANDLE_PRESENT;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->irq.Handler = &fjn_interrupt;
link->irq.Instance = dev;
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index 9d45e9696e16..db6a97d1d7b1 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -254,7 +254,7 @@ static int pcnet_probe(struct pcmcia_device *link)
info->p_dev = link;
link->priv = dev;
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+ link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->conf.Attributes = CONF_ENABLE_IRQ;
link->conf.IntType = INT_MEMORY_AND_IO;
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index 58d716fd17cf..c9868e9dac4c 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -328,7 +328,7 @@ static int smc91c92_probe(struct pcmcia_device *link)
link->io.NumPorts1 = 16;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
link->io.IOAddrLines = 4;
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_HANDLE_PRESENT;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->irq.Handler = &smc_interrupt;
link->irq.Instance = dev;
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index c3b69602e275..1f09bea6db5a 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -886,7 +886,7 @@ xirc2ps_config(struct pcmcia_device * link)
}
printk(KNOT_XIRC "no ports available\n");
} else {
- link->irq.Attributes |= IRQ_TYPE_EXCLUSIVE;
+ link->irq.Attributes |= IRQ_TYPE_DYNAMIC_SHARING;
link->io.NumPorts1 = 16;
for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
link->io.BasePort1 = ioaddr;
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index 5f994b5beda1..ff92aca0a7b3 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -282,7 +282,6 @@ struct pcnet32_private {
struct net_device *dev;
struct napi_struct napi;
- struct net_device_stats stats;
char tx_full;
char phycount; /* number of phys found */
int options;
@@ -442,7 +441,9 @@ static struct pcnet32_access pcnet32_dwio = {
static void pcnet32_netif_stop(struct net_device *dev)
{
+#ifdef CONFIG_PCNET32_NAPI
struct pcnet32_private *lp = netdev_priv(dev);
+#endif
dev->trans_start = jiffies;
#ifdef CONFIG_PCNET32_NAPI
napi_disable(&lp->napi);
@@ -452,7 +453,9 @@ static void pcnet32_netif_stop(struct net_device *dev)
static void pcnet32_netif_start(struct net_device *dev)
{
+#ifdef CONFIG_PCNET32_NAPI
struct pcnet32_private *lp = netdev_priv(dev);
+#endif
netif_wake_queue(dev);
#ifdef CONFIG_PCNET32_NAPI
napi_enable(&lp->napi);
@@ -1178,15 +1181,15 @@ static void pcnet32_rx_entry(struct net_device *dev,
* buffers, with only the last correctly noting the error.
*/
if (status & 0x01) /* Only count a general error at the */
- lp->stats.rx_errors++; /* end of a packet. */
+ dev->stats.rx_errors++; /* end of a packet. */
if (status & 0x20)
- lp->stats.rx_frame_errors++;
+ dev->stats.rx_frame_errors++;
if (status & 0x10)
- lp->stats.rx_over_errors++;
+ dev->stats.rx_over_errors++;
if (status & 0x08)
- lp->stats.rx_crc_errors++;
+ dev->stats.rx_crc_errors++;
if (status & 0x04)
- lp->stats.rx_fifo_errors++;
+ dev->stats.rx_fifo_errors++;
return;
}
@@ -1197,13 +1200,13 @@ static void pcnet32_rx_entry(struct net_device *dev,
if (netif_msg_drv(lp))
printk(KERN_ERR "%s: Impossible packet size %d!\n",
dev->name, pkt_len);
- lp->stats.rx_errors++;
+ dev->stats.rx_errors++;
return;
}
if (pkt_len < 60) {
if (netif_msg_rx_err(lp))
printk(KERN_ERR "%s: Runt packet!\n", dev->name);
- lp->stats.rx_errors++;
+ dev->stats.rx_errors++;
return;
}
@@ -1237,7 +1240,7 @@ static void pcnet32_rx_entry(struct net_device *dev,
printk(KERN_ERR
"%s: Memory squeeze, dropping packet.\n",
dev->name);
- lp->stats.rx_dropped++;
+ dev->stats.rx_dropped++;
return;
}
skb->dev = dev;
@@ -1256,7 +1259,7 @@ static void pcnet32_rx_entry(struct net_device *dev,
pkt_len,
PCI_DMA_FROMDEVICE);
}
- lp->stats.rx_bytes += skb->len;
+ dev->stats.rx_bytes += skb->len;
skb->protocol = eth_type_trans(skb, dev);
#ifdef CONFIG_PCNET32_NAPI
netif_receive_skb(skb);
@@ -1264,7 +1267,7 @@ static void pcnet32_rx_entry(struct net_device *dev,
netif_rx(skb);
#endif
dev->last_rx = jiffies;
- lp->stats.rx_packets++;
+ dev->stats.rx_packets++;
return;
}
@@ -1312,21 +1315,21 @@ static int pcnet32_tx(struct net_device *dev)
if (status & 0x4000) {
/* There was a major error, log it. */
int err_status = le32_to_cpu(lp->tx_ring[entry].misc);
- lp->stats.tx_errors++;
+ dev->stats.tx_errors++;
if (netif_msg_tx_err(lp))
printk(KERN_ERR
"%s: Tx error status=%04x err_status=%08x\n",
dev->name, status,
err_status);
if (err_status & 0x04000000)
- lp->stats.tx_aborted_errors++;
+ dev->stats.tx_aborted_errors++;
if (err_status & 0x08000000)
- lp->stats.tx_carrier_errors++;
+ dev->stats.tx_carrier_errors++;
if (err_status & 0x10000000)
- lp->stats.tx_window_errors++;
+ dev->stats.tx_window_errors++;
#ifndef DO_DXSUFLO
if (err_status & 0x40000000) {
- lp->stats.tx_fifo_errors++;
+ dev->stats.tx_fifo_errors++;
/* Ackk! On FIFO errors the Tx unit is turned off! */
/* Remove this verbosity later! */
if (netif_msg_tx_err(lp))
@@ -1337,7 +1340,7 @@ static int pcnet32_tx(struct net_device *dev)
}
#else
if (err_status & 0x40000000) {
- lp->stats.tx_fifo_errors++;
+ dev->stats.tx_fifo_errors++;
if (!lp->dxsuflo) { /* If controller doesn't recover ... */
/* Ackk! On FIFO errors the Tx unit is turned off! */
/* Remove this verbosity later! */
@@ -1351,8 +1354,8 @@ static int pcnet32_tx(struct net_device *dev)
#endif
} else {
if (status & 0x1800)
- lp->stats.collisions++;
- lp->stats.tx_packets++;
+ dev->stats.collisions++;
+ dev->stats.tx_packets++;
}
/* We must free the original skb */
@@ -1849,6 +1852,9 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
lp->mii_if.mdio_read = mdio_read;
lp->mii_if.mdio_write = mdio_write;
+ /* napi.weight is used in both the napi and non-napi cases */
+ lp->napi.weight = lp->rx_ring_size / 2;
+
#ifdef CONFIG_PCNET32_NAPI
netif_napi_add(dev, &lp->napi, pcnet32_poll, lp->rx_ring_size / 2);
#endif
@@ -2471,7 +2477,7 @@ static void pcnet32_tx_timeout(struct net_device *dev)
"%s: transmit timed out, status %4.4x, resetting.\n",
dev->name, lp->a.read_csr(ioaddr, CSR0));
lp->a.write_csr(ioaddr, CSR0, CSR0_STOP);
- lp->stats.tx_errors++;
+ dev->stats.tx_errors++;
if (netif_msg_tx_err(lp)) {
int i;
printk(KERN_DEBUG
@@ -2541,7 +2547,7 @@ static int pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev)
lp->tx_ring[entry].status = cpu_to_le16(status);
lp->cur_tx++;
- lp->stats.tx_bytes += skb->len;
+ dev->stats.tx_bytes += skb->len;
/* Trigger an immediate send poll. */
lp->a.write_csr(ioaddr, CSR0, CSR0_INTEN | CSR0_TXPOLL);
@@ -2586,7 +2592,7 @@ pcnet32_interrupt(int irq, void *dev_id)
/* Log misc errors. */
if (csr0 & 0x4000)
- lp->stats.tx_errors++; /* Tx babble. */
+ dev->stats.tx_errors++; /* Tx babble. */
if (csr0 & 0x1000) {
/*
* This happens when our receive ring is full. This
@@ -2599,7 +2605,7 @@ pcnet32_interrupt(int irq, void *dev_id)
* don't get a rx interrupt, but a missed frame
* interrupt sooner or later.
*/
- lp->stats.rx_errors++; /* Missed a Rx frame. */
+ dev->stats.rx_errors++; /* Missed a Rx frame. */
}
if (csr0 & 0x0800) {
if (netif_msg_drv(lp))
@@ -2661,7 +2667,7 @@ static int pcnet32_close(struct net_device *dev)
spin_lock_irqsave(&lp->lock, flags);
- lp->stats.rx_missed_errors = lp->a.read_csr(ioaddr, 112);
+ dev->stats.rx_missed_errors = lp->a.read_csr(ioaddr, 112);
if (netif_msg_ifdown(lp))
printk(KERN_DEBUG
@@ -2698,10 +2704,10 @@ static struct net_device_stats *pcnet32_get_stats(struct net_device *dev)
unsigned long flags;
spin_lock_irqsave(&lp->lock, flags);
- lp->stats.rx_missed_errors = lp->a.read_csr(ioaddr, 112);
+ dev->stats.rx_missed_errors = lp->a.read_csr(ioaddr, 112);
spin_unlock_irqrestore(&lp->lock, flags);
- return &lp->stats;
+ return &dev->stats;
}
/* taken from the sunlance driver, which it took from the depca driver */
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index d2ede5ff9fff..035fd41fb61f 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -265,7 +265,7 @@ static struct phy_driver marvell_drivers[] = {
.read_status = &genphy_read_status,
.ack_interrupt = &marvell_ack_interrupt,
.config_intr = &marvell_config_intr,
- .driver = {.owner = THIS_MODULE,},
+ .driver = { .owner = THIS_MODULE },
},
{
.phy_id = 0x01410c90,
@@ -278,7 +278,7 @@ static struct phy_driver marvell_drivers[] = {
.read_status = &genphy_read_status,
.ack_interrupt = &marvell_ack_interrupt,
.config_intr = &marvell_config_intr,
- .driver = {.owner = THIS_MODULE,},
+ .driver = { .owner = THIS_MODULE },
},
{
.phy_id = 0x01410cc0,
@@ -291,7 +291,7 @@ static struct phy_driver marvell_drivers[] = {
.read_status = &genphy_read_status,
.ack_interrupt = &marvell_ack_interrupt,
.config_intr = &marvell_config_intr,
- .driver = {.owner = THIS_MODULE,},
+ .driver = { .owner = THIS_MODULE },
},
{
.phy_id = 0x01410cd0,
@@ -304,8 +304,21 @@ static struct phy_driver marvell_drivers[] = {
.read_status = &genphy_read_status,
.ack_interrupt = &marvell_ack_interrupt,
.config_intr = &marvell_config_intr,
- .driver = {.owner = THIS_MODULE,},
- }
+ .driver = { .owner = THIS_MODULE },
+ },
+ {
+ .phy_id = 0x01410e30,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Marvell 88E1240",
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = &m88e1111_config_init,
+ .config_aneg = &marvell_config_aneg,
+ .read_status = &genphy_read_status,
+ .ack_interrupt = &marvell_ack_interrupt,
+ .config_intr = &marvell_config_intr,
+ .driver = { .owner = THIS_MODULE },
+ },
};
static int __init marvell_init(void)
diff --git a/drivers/net/phy/mdio-bitbang.c b/drivers/net/phy/mdio-bitbang.c
index 8cd243d92af3..2747b1f89ffe 100644
--- a/drivers/net/phy/mdio-bitbang.c
+++ b/drivers/net/phy/mdio-bitbang.c
@@ -185,3 +185,5 @@ void free_mdio_bitbang(struct mii_bus *bus)
module_put(ctrl->ops->owner);
kfree(bus);
}
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index c0461217b108..f6e484812a98 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -706,7 +706,7 @@ int phy_driver_register(struct phy_driver *new_driver)
return retval;
}
- pr_info("%s: Registered new driver\n", new_driver->name);
+ pr_debug("%s: Registered new driver\n", new_driver->name);
return 0;
}
diff --git a/drivers/net/plip.c b/drivers/net/plip.c
index b5e9981d1060..5071fcd8a0bd 100644
--- a/drivers/net/plip.c
+++ b/drivers/net/plip.c
@@ -143,7 +143,7 @@ static void plip_bh(struct work_struct *work);
static void plip_timer_bh(struct work_struct *work);
/* Interrupt handler */
-static void plip_interrupt(int irq, void *dev_id);
+static void plip_interrupt(void *dev_id);
/* Functions for DEV methods */
static int plip_tx_packet(struct sk_buff *skb, struct net_device *dev);
@@ -380,7 +380,7 @@ plip_timer_bh(struct work_struct *work)
container_of(work, struct net_local, timer.work);
if (!(atomic_read (&nl->kill_timer))) {
- plip_interrupt (-1, nl->dev);
+ plip_interrupt (nl->dev);
schedule_delayed_work(&nl->timer, 1);
}
@@ -897,7 +897,7 @@ plip_error(struct net_device *dev, struct net_local *nl,
/* Handle the parallel port interrupts. */
static void
-plip_interrupt(int irq, void *dev_id)
+plip_interrupt(void *dev_id)
{
struct net_device *dev = dev_id;
struct net_local *nl;
diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c
index 27f5b904f48e..f023d5b67e6e 100644
--- a/drivers/net/ppp_async.c
+++ b/drivers/net/ppp_async.c
@@ -160,7 +160,7 @@ ppp_asynctty_open(struct tty_struct *tty)
err = -ENOMEM;
ap = kzalloc(sizeof(*ap), GFP_KERNEL);
- if (ap == 0)
+ if (!ap)
goto out;
/* initialize the asyncppp structure */
@@ -215,7 +215,7 @@ ppp_asynctty_close(struct tty_struct *tty)
ap = tty->disc_data;
tty->disc_data = NULL;
write_unlock_irq(&disc_data_lock);
- if (ap == 0)
+ if (!ap)
return;
/*
@@ -230,10 +230,10 @@ ppp_asynctty_close(struct tty_struct *tty)
tasklet_kill(&ap->tsk);
ppp_unregister_channel(&ap->chan);
- if (ap->rpkt != 0)
+ if (ap->rpkt)
kfree_skb(ap->rpkt);
skb_queue_purge(&ap->rqueue);
- if (ap->tpkt != 0)
+ if (ap->tpkt)
kfree_skb(ap->tpkt);
kfree(ap);
}
@@ -285,13 +285,13 @@ ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file,
int err, val;
int __user *p = (int __user *)arg;
- if (ap == 0)
+ if (!ap)
return -ENXIO;
err = -EFAULT;
switch (cmd) {
case PPPIOCGCHAN:
err = -ENXIO;
- if (ap == 0)
+ if (!ap)
break;
err = -EFAULT;
if (put_user(ppp_channel_index(&ap->chan), p))
@@ -301,7 +301,7 @@ ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file,
case PPPIOCGUNIT:
err = -ENXIO;
- if (ap == 0)
+ if (!ap)
break;
err = -EFAULT;
if (put_user(ppp_unit_number(&ap->chan), p))
@@ -309,16 +309,11 @@ ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file,
err = 0;
break;
- case TCGETS:
- case TCGETA:
- err = n_tty_ioctl(tty, file, cmd, arg);
- break;
-
case TCFLSH:
/* flush our buffers and the serial port's buffer */
if (arg == TCIOFLUSH || arg == TCOFLUSH)
ppp_async_flush_output(ap);
- err = n_tty_ioctl(tty, file, cmd, arg);
+ err = tty_perform_flush(tty, arg);
break;
case FIONREAD:
@@ -329,7 +324,8 @@ ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file,
break;
default:
- err = -ENOIOCTLCMD;
+ /* Try the various mode ioctls */
+ err = tty_mode_ioctl(tty, file, cmd, arg);
}
ap_put(ap);
@@ -354,7 +350,7 @@ ppp_asynctty_receive(struct tty_struct *tty, const unsigned char *buf,
struct asyncppp *ap = ap_get(tty);
unsigned long flags;
- if (ap == 0)
+ if (!ap)
return;
spin_lock_irqsave(&ap->recv_lock, flags);
ppp_async_input(ap, buf, cflags, count);
@@ -373,7 +369,7 @@ ppp_asynctty_wakeup(struct tty_struct *tty)
struct asyncppp *ap = ap_get(tty);
clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
- if (ap == 0)
+ if (!ap)
return;
set_bit(XMIT_WAKEUP, &ap->xmit_flags);
tasklet_schedule(&ap->tsk);
@@ -688,7 +684,7 @@ ppp_async_push(struct asyncppp *ap)
tty_stuffed = 1;
continue;
}
- if (ap->optr >= ap->olim && ap->tpkt != 0) {
+ if (ap->optr >= ap->olim && ap->tpkt) {
if (ppp_async_encode(ap)) {
/* finished processing ap->tpkt */
clear_bit(XMIT_FULL, &ap->xmit_flags);
@@ -708,7 +704,7 @@ ppp_async_push(struct asyncppp *ap)
clear_bit(XMIT_BUSY, &ap->xmit_flags);
/* any more work to do? if not, exit the loop */
if (!(test_bit(XMIT_WAKEUP, &ap->xmit_flags)
- || (!tty_stuffed && ap->tpkt != 0)))
+ || (!tty_stuffed && ap->tpkt)))
break;
/* more work to do, see if we can do it now */
if (test_and_set_bit(XMIT_BUSY, &ap->xmit_flags))
@@ -719,7 +715,7 @@ ppp_async_push(struct asyncppp *ap)
flush:
clear_bit(XMIT_BUSY, &ap->xmit_flags);
- if (ap->tpkt != 0) {
+ if (ap->tpkt) {
kfree_skb(ap->tpkt);
ap->tpkt = NULL;
clear_bit(XMIT_FULL, &ap->xmit_flags);
@@ -852,7 +848,7 @@ ppp_async_input(struct asyncppp *ap, const unsigned char *buf,
s = 0;
for (i = 0; i < count; ++i) {
c = buf[i];
- if (flags != 0 && flags[i] != 0)
+ if (flags && flags[i] != 0)
continue;
s |= (c & 0x80)? SC_RCV_B7_1: SC_RCV_B7_0;
c = ((c >> 4) ^ c) & 0xf;
@@ -869,7 +865,7 @@ ppp_async_input(struct asyncppp *ap, const unsigned char *buf,
n = scan_ordinary(ap, buf, count);
f = 0;
- if (flags != 0 && (ap->state & SC_TOSS) == 0) {
+ if (flags && (ap->state & SC_TOSS) == 0) {
/* check the flags to see if any char had an error */
for (j = 0; j < n; ++j)
if ((f = flags[j]) != 0)
@@ -882,9 +878,9 @@ ppp_async_input(struct asyncppp *ap, const unsigned char *buf,
} else if (n > 0 && (ap->state & SC_TOSS) == 0) {
/* stuff the chars in the skb */
skb = ap->rpkt;
- if (skb == 0) {
+ if (!skb) {
skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2);
- if (skb == 0)
+ if (!skb)
goto nomem;
ap->rpkt = skb;
}
@@ -931,7 +927,7 @@ ppp_async_input(struct asyncppp *ap, const unsigned char *buf,
++n;
buf += n;
- if (flags != 0)
+ if (flags)
flags += n;
count -= n;
}
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 4b49d0e8c7eb..4f690378bb77 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -367,7 +367,7 @@ static int ppp_release(struct inode *inode, struct file *file)
struct ppp_file *pf = file->private_data;
struct ppp *ppp;
- if (pf != 0) {
+ if (pf) {
file->private_data = NULL;
if (pf->kind == INTERFACE) {
ppp = PF_TO_PPP(pf);
@@ -398,7 +398,7 @@ static ssize_t ppp_read(struct file *file, char __user *buf,
ret = count;
- if (pf == 0)
+ if (!pf)
return -ENXIO;
add_wait_queue(&pf->rwait, &wait);
for (;;) {
@@ -431,7 +431,7 @@ static ssize_t ppp_read(struct file *file, char __user *buf,
set_current_state(TASK_RUNNING);
remove_wait_queue(&pf->rwait, &wait);
- if (skb == 0)
+ if (!skb)
goto out;
ret = -EOVERFLOW;
@@ -455,11 +455,11 @@ static ssize_t ppp_write(struct file *file, const char __user *buf,
struct sk_buff *skb;
ssize_t ret;
- if (pf == 0)
+ if (!pf)
return -ENXIO;
ret = -ENOMEM;
skb = alloc_skb(count + pf->hdrlen, GFP_KERNEL);
- if (skb == 0)
+ if (!skb)
goto out;
skb_reserve(skb, pf->hdrlen);
ret = -EFAULT;
@@ -491,11 +491,11 @@ static unsigned int ppp_poll(struct file *file, poll_table *wait)
struct ppp_file *pf = file->private_data;
unsigned int mask;
- if (pf == 0)
+ if (!pf)
return 0;
poll_wait(file, &pf->rwait, wait);
mask = POLLOUT | POLLWRNORM;
- if (skb_peek(&pf->rq) != 0)
+ if (skb_peek(&pf->rq))
mask |= POLLIN | POLLRDNORM;
if (pf->dead)
mask |= POLLHUP;
@@ -559,7 +559,7 @@ static int ppp_ioctl(struct inode *inode, struct file *file,
void __user *argp = (void __user *)arg;
int __user *p = argp;
- if (pf == 0)
+ if (!pf)
return ppp_unattached_ioctl(pf, file, cmd, arg);
if (cmd == PPPIOCDETACH) {
@@ -689,13 +689,13 @@ static int ppp_ioctl(struct inode *inode, struct file *file,
val &= 0xffff;
}
vj = slhc_init(val2+1, val+1);
- if (vj == 0) {
+ if (!vj) {
printk(KERN_ERR "PPP: no memory (VJ compressor)\n");
err = -ENOMEM;
break;
}
ppp_lock(ppp);
- if (ppp->vj != 0)
+ if (ppp->vj)
slhc_free(ppp->vj);
ppp->vj = vj;
ppp_unlock(ppp);
@@ -786,7 +786,7 @@ static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file,
if (get_user(unit, p))
break;
ppp = ppp_create_interface(unit, &err);
- if (ppp == 0)
+ if (!ppp)
break;
file->private_data = &ppp->file;
ppp->owner = file;
@@ -803,7 +803,7 @@ static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file,
mutex_lock(&all_ppp_mutex);
err = -ENXIO;
ppp = ppp_find_unit(unit);
- if (ppp != 0) {
+ if (ppp) {
atomic_inc(&ppp->file.refcnt);
file->private_data = &ppp->file;
err = 0;
@@ -817,7 +817,7 @@ static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file,
spin_lock_bh(&all_channels_lock);
err = -ENXIO;
chan = ppp_find_channel(unit);
- if (chan != 0) {
+ if (chan) {
atomic_inc(&chan->file.refcnt);
file->private_data = &chan->file;
err = 0;
@@ -946,9 +946,9 @@ ppp_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
case SIOCGPPPCSTATS:
memset(&cstats, 0, sizeof(cstats));
- if (ppp->xc_state != 0)
+ if (ppp->xc_state)
ppp->xcomp->comp_stat(ppp->xc_state, &cstats.c);
- if (ppp->rc_state != 0)
+ if (ppp->rc_state)
ppp->rcomp->decomp_stat(ppp->rc_state, &cstats.d);
if (copy_to_user(addr, &cstats, sizeof(cstats)))
break;
@@ -993,14 +993,14 @@ ppp_xmit_process(struct ppp *ppp)
struct sk_buff *skb;
ppp_xmit_lock(ppp);
- if (ppp->dev != 0) {
+ if (ppp->dev) {
ppp_push(ppp);
- while (ppp->xmit_pending == 0
- && (skb = skb_dequeue(&ppp->file.xq)) != 0)
+ while (!ppp->xmit_pending
+ && (skb = skb_dequeue(&ppp->file.xq)))
ppp_send_frame(ppp, skb);
/* If there's no work left to do, tell the core net
code that we can accept some more. */
- if (ppp->xmit_pending == 0 && skb_peek(&ppp->file.xq) == 0)
+ if (!ppp->xmit_pending && !skb_peek(&ppp->file.xq))
netif_wake_queue(ppp->dev);
}
ppp_xmit_unlock(ppp);
@@ -1100,12 +1100,12 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
switch (proto) {
case PPP_IP:
- if (ppp->vj == 0 || (ppp->flags & SC_COMP_TCP) == 0)
+ if (!ppp->vj || (ppp->flags & SC_COMP_TCP) == 0)
break;
/* try to do VJ TCP header compression */
new_skb = alloc_skb(skb->len + ppp->dev->hard_header_len - 2,
GFP_ATOMIC);
- if (new_skb == 0) {
+ if (!new_skb) {
printk(KERN_ERR "PPP: no memory (VJ comp pkt)\n");
goto drop;
}
@@ -1140,7 +1140,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
}
/* try to do packet compression */
- if ((ppp->xstate & SC_COMP_RUN) && ppp->xc_state != 0
+ if ((ppp->xstate & SC_COMP_RUN) && ppp->xc_state
&& proto != PPP_LCP && proto != PPP_CCP) {
if (!(ppp->flags & SC_CCP_UP) && (ppp->flags & SC_MUST_COMP)) {
if (net_ratelimit())
@@ -1185,7 +1185,7 @@ ppp_push(struct ppp *ppp)
struct channel *pch;
struct sk_buff *skb = ppp->xmit_pending;
- if (skb == 0)
+ if (!skb)
return;
list = &ppp->channels;
@@ -1355,7 +1355,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
if (flen == len && nfree == 0)
bits |= E;
frag = alloc_skb(flen + hdrlen + (flen == 0), GFP_ATOMIC);
- if (frag == 0)
+ if (!frag)
goto noskb;
q = skb_put(frag, flen + hdrlen);
@@ -1425,7 +1425,7 @@ ppp_channel_push(struct channel *pch)
struct ppp *ppp;
spin_lock_bh(&pch->downl);
- if (pch->chan != 0) {
+ if (pch->chan) {
while (!skb_queue_empty(&pch->file.xq)) {
skb = skb_dequeue(&pch->file.xq);
if (!pch->chan->ops->start_xmit(pch->chan, skb)) {
@@ -1443,7 +1443,7 @@ ppp_channel_push(struct channel *pch)
if (skb_queue_empty(&pch->file.xq)) {
read_lock_bh(&pch->upl);
ppp = pch->ppp;
- if (ppp != 0)
+ if (ppp)
ppp_xmit_process(ppp);
read_unlock_bh(&pch->upl);
}
@@ -1462,7 +1462,7 @@ ppp_do_recv(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
{
ppp_recv_lock(ppp);
/* ppp->dev == 0 means interface is closing down */
- if (ppp->dev != 0)
+ if (ppp->dev)
ppp_receive_frame(ppp, skb, pch);
else
kfree_skb(skb);
@@ -1475,19 +1475,19 @@ ppp_input(struct ppp_channel *chan, struct sk_buff *skb)
struct channel *pch = chan->ppp;
int proto;
- if (pch == 0 || skb->len == 0) {
+ if (!pch || skb->len == 0) {
kfree_skb(skb);
return;
}
proto = PPP_PROTO(skb);
read_lock_bh(&pch->upl);
- if (pch->ppp == 0 || proto >= 0xc000 || proto == PPP_CCPFRAG) {
+ if (!pch->ppp || proto >= 0xc000 || proto == PPP_CCPFRAG) {
/* put it on the channel queue */
skb_queue_tail(&pch->file.rq, skb);
/* drop old frames if queue too long */
while (pch->file.rq.qlen > PPP_MAX_RQLEN
- && (skb = skb_dequeue(&pch->file.rq)) != 0)
+ && (skb = skb_dequeue(&pch->file.rq)))
kfree_skb(skb);
wake_up_interruptible(&pch->file.rwait);
} else {
@@ -1503,13 +1503,13 @@ ppp_input_error(struct ppp_channel *chan, int code)
struct channel *pch = chan->ppp;
struct sk_buff *skb;
- if (pch == 0)
+ if (!pch)
return;
read_lock_bh(&pch->upl);
- if (pch->ppp != 0) {
+ if (pch->ppp) {
skb = alloc_skb(0, GFP_ATOMIC);
- if (skb != 0) {
+ if (skb) {
skb->len = 0; /* probably unnecessary */
skb->cb[0] = code;
ppp_do_recv(pch->ppp, skb, pch);
@@ -1548,7 +1548,7 @@ static void
ppp_receive_error(struct ppp *ppp)
{
++ppp->stats.rx_errors;
- if (ppp->vj != 0)
+ if (ppp->vj)
slhc_toss(ppp->vj);
}
@@ -1563,7 +1563,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
* Note that some decompressors need to see uncompressed frames
* that come in as well as compressed frames.
*/
- if (ppp->rc_state != 0 && (ppp->rstate & SC_DECOMP_RUN)
+ if (ppp->rc_state && (ppp->rstate & SC_DECOMP_RUN)
&& (ppp->rstate & (SC_DC_FERROR | SC_DC_ERROR)) == 0)
skb = ppp_decompress_frame(ppp, skb);
@@ -1574,13 +1574,13 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
switch (proto) {
case PPP_VJC_COMP:
/* decompress VJ compressed packets */
- if (ppp->vj == 0 || (ppp->flags & SC_REJ_COMP_TCP))
+ if (!ppp->vj || (ppp->flags & SC_REJ_COMP_TCP))
goto err;
if (skb_tailroom(skb) < 124 || skb_cloned(skb)) {
/* copy to a new sk_buff with more tailroom */
ns = dev_alloc_skb(skb->len + 128);
- if (ns == 0) {
+ if (!ns) {
printk(KERN_ERR"PPP: no memory (VJ decomp)\n");
goto err;
}
@@ -1606,7 +1606,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
break;
case PPP_VJC_UNCOMP:
- if (ppp->vj == 0 || (ppp->flags & SC_REJ_COMP_TCP))
+ if (!ppp->vj || (ppp->flags & SC_REJ_COMP_TCP))
goto err;
/* Until we fix the decompressor need to make sure
@@ -1636,7 +1636,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
skb_queue_tail(&ppp->file.rq, skb);
/* limit queue length by dropping old frames */
while (ppp->file.rq.qlen > PPP_MAX_RQLEN
- && (skb = skb_dequeue(&ppp->file.rq)) != 0)
+ && (skb = skb_dequeue(&ppp->file.rq)))
kfree_skb(skb);
/* wake up any process polling or blocking on read */
wake_up_interruptible(&ppp->file.rwait);
@@ -1718,7 +1718,7 @@ ppp_decompress_frame(struct ppp *ppp, struct sk_buff *skb)
}
ns = dev_alloc_skb(obuff_size);
- if (ns == 0) {
+ if (!ns) {
printk(KERN_ERR "ppp_decompress_frame: no memory\n");
goto err;
}
@@ -1836,7 +1836,7 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
ppp->minseq = ppp->mrq.next->sequence;
/* Pull completed packets off the queue and receive them. */
- while ((skb = ppp_mp_reconstruct(ppp)) != 0)
+ while ((skb = ppp_mp_reconstruct(ppp)))
ppp_receive_nonmp_frame(ppp, skb);
return;
@@ -2002,7 +2002,7 @@ ppp_register_channel(struct ppp_channel *chan)
struct channel *pch;
pch = kzalloc(sizeof(struct channel), GFP_KERNEL);
- if (pch == 0)
+ if (!pch)
return -ENOMEM;
pch->ppp = NULL;
pch->chan = chan;
@@ -2030,7 +2030,7 @@ int ppp_channel_index(struct ppp_channel *chan)
{
struct channel *pch = chan->ppp;
- if (pch != 0)
+ if (pch)
return pch->file.index;
return -1;
}
@@ -2043,9 +2043,9 @@ int ppp_unit_number(struct ppp_channel *chan)
struct channel *pch = chan->ppp;
int unit = -1;
- if (pch != 0) {
+ if (pch) {
read_lock_bh(&pch->upl);
- if (pch->ppp != 0)
+ if (pch->ppp)
unit = pch->ppp->file.index;
read_unlock_bh(&pch->upl);
}
@@ -2061,7 +2061,7 @@ ppp_unregister_channel(struct ppp_channel *chan)
{
struct channel *pch = chan->ppp;
- if (pch == 0)
+ if (!pch)
return; /* should never happen */
chan->ppp = NULL;
@@ -2093,7 +2093,7 @@ ppp_output_wakeup(struct ppp_channel *chan)
{
struct channel *pch = chan->ppp;
- if (pch == 0)
+ if (!pch)
return;
ppp_channel_push(pch);
}
@@ -2124,18 +2124,18 @@ ppp_set_compress(struct ppp *ppp, unsigned long arg)
cp = find_compressor(ccp_option[0]);
#ifdef CONFIG_KMOD
- if (cp == 0) {
+ if (!cp) {
request_module("ppp-compress-%d", ccp_option[0]);
cp = find_compressor(ccp_option[0]);
}
#endif /* CONFIG_KMOD */
- if (cp == 0)
+ if (!cp)
goto out;
err = -ENOBUFS;
if (data.transmit) {
state = cp->comp_alloc(ccp_option, data.length);
- if (state != 0) {
+ if (state) {
ppp_xmit_lock(ppp);
ppp->xstate &= ~SC_COMP_RUN;
ocomp = ppp->xcomp;
@@ -2143,7 +2143,7 @@ ppp_set_compress(struct ppp *ppp, unsigned long arg)
ppp->xcomp = cp;
ppp->xc_state = state;
ppp_xmit_unlock(ppp);
- if (ostate != 0) {
+ if (ostate) {
ocomp->comp_free(ostate);
module_put(ocomp->owner);
}
@@ -2153,7 +2153,7 @@ ppp_set_compress(struct ppp *ppp, unsigned long arg)
} else {
state = cp->decomp_alloc(ccp_option, data.length);
- if (state != 0) {
+ if (state) {
ppp_recv_lock(ppp);
ppp->rstate &= ~SC_DECOMP_RUN;
ocomp = ppp->rcomp;
@@ -2161,7 +2161,7 @@ ppp_set_compress(struct ppp *ppp, unsigned long arg)
ppp->rcomp = cp;
ppp->rc_state = state;
ppp_recv_unlock(ppp);
- if (ostate != 0) {
+ if (ostate) {
ocomp->decomp_free(ostate);
module_put(ocomp->owner);
}
@@ -2228,7 +2228,7 @@ ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound)
break;
if (inbound) {
/* we will start receiving compressed packets */
- if (ppp->rc_state == 0)
+ if (!ppp->rc_state)
break;
if (ppp->rcomp->decomp_init(ppp->rc_state, dp, len,
ppp->file.index, 0, ppp->mru, ppp->debug)) {
@@ -2237,7 +2237,7 @@ ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound)
}
} else {
/* we will soon start sending compressed packets */
- if (ppp->xc_state == 0)
+ if (!ppp->xc_state)
break;
if (ppp->xcomp->comp_init(ppp->xc_state, dp, len,
ppp->file.index, 0, ppp->debug))
@@ -2320,11 +2320,11 @@ ppp_register_compressor(struct compressor *cp)
int ret;
spin_lock(&compressor_list_lock);
ret = -EEXIST;
- if (find_comp_entry(cp->compress_proto) != 0)
+ if (find_comp_entry(cp->compress_proto))
goto out;
ret = -ENOMEM;
ce = kmalloc(sizeof(struct compressor_entry), GFP_ATOMIC);
- if (ce == 0)
+ if (!ce)
goto out;
ret = 0;
ce->comp = cp;
@@ -2342,7 +2342,7 @@ ppp_unregister_compressor(struct compressor *cp)
spin_lock(&compressor_list_lock);
ce = find_comp_entry(cp->compress_proto);
- if (ce != 0 && ce->comp == cp) {
+ if (ce && ce->comp == cp) {
list_del(&ce->list);
kfree(ce);
}
@@ -2358,7 +2358,7 @@ find_compressor(int type)
spin_lock(&compressor_list_lock);
ce = find_comp_entry(type);
- if (ce != 0) {
+ if (ce) {
cp = ce->comp;
if (!try_module_get(cp->owner))
cp = NULL;
@@ -2383,7 +2383,7 @@ ppp_get_stats(struct ppp *ppp, struct ppp_stats *st)
st->p.ppp_opackets = ppp->stats.tx_packets;
st->p.ppp_oerrors = ppp->stats.tx_errors;
st->p.ppp_obytes = ppp->stats.tx_bytes;
- if (vj == 0)
+ if (!vj)
return;
st->vj.vjs_packets = vj->sls_o_compressed + vj->sls_o_uncompressed;
st->vj.vjs_compressed = vj->sls_o_compressed;
@@ -2604,11 +2604,11 @@ ppp_connect_channel(struct channel *pch, int unit)
mutex_lock(&all_ppp_mutex);
ppp = ppp_find_unit(unit);
- if (ppp == 0)
+ if (!ppp)
goto out;
write_lock_bh(&pch->upl);
ret = -EINVAL;
- if (pch->ppp != 0)
+ if (pch->ppp)
goto outl;
ppp_lock(ppp);
@@ -2644,7 +2644,7 @@ ppp_disconnect_channel(struct channel *pch)
ppp = pch->ppp;
pch->ppp = NULL;
write_unlock_bh(&pch->upl);
- if (ppp != 0) {
+ if (ppp) {
/* remove it from the ppp unit's list */
ppp_lock(ppp);
list_del(&pch->clist);
diff --git a/drivers/net/ppp_mppe.c b/drivers/net/ppp_mppe.c
index c0b6d19d1457..b35d79449500 100644
--- a/drivers/net/ppp_mppe.c
+++ b/drivers/net/ppp_mppe.c
@@ -55,7 +55,7 @@
#include <linux/mm.h>
#include <linux/ppp_defs.h>
#include <linux/ppp-comp.h>
-#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
#include "ppp_mppe.h"
@@ -68,9 +68,7 @@ MODULE_VERSION("1.0.2");
static unsigned int
setup_sg(struct scatterlist *sg, const void *address, unsigned int length)
{
- sg[0].page = virt_to_page(address);
- sg[0].offset = offset_in_page(address);
- sg[0].length = length;
+ sg_set_buf(sg, address, length);
return length;
}
@@ -142,6 +140,8 @@ static void get_new_key_from_sha(struct ppp_mppe_state * state)
struct scatterlist sg[4];
unsigned int nbytes;
+ sg_init_table(sg, 4);
+
nbytes = setup_sg(&sg[0], state->master_key, state->keylen);
nbytes += setup_sg(&sg[1], sha_pad->sha_pad1,
sizeof(sha_pad->sha_pad1));
@@ -168,6 +168,8 @@ static void mppe_rekey(struct ppp_mppe_state * state, int initial_key)
if (!initial_key) {
crypto_blkcipher_setkey(state->arc4, state->sha1_digest,
state->keylen);
+ sg_init_table(sg_in, 1);
+ sg_init_table(sg_out, 1);
setup_sg(sg_in, state->sha1_digest, state->keylen);
setup_sg(sg_out, state->session_key, state->keylen);
if (crypto_blkcipher_encrypt(&desc, sg_out, sg_in,
@@ -423,6 +425,8 @@ mppe_compress(void *arg, unsigned char *ibuf, unsigned char *obuf,
isize -= 2;
/* Encrypt packet */
+ sg_init_table(sg_in, 1);
+ sg_init_table(sg_out, 1);
setup_sg(sg_in, ibuf, isize);
setup_sg(sg_out, obuf, osize);
if (crypto_blkcipher_encrypt(&desc, sg_out, sg_in, isize) != 0) {
@@ -610,6 +614,8 @@ mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf,
* Decrypt the first byte in order to check if it is
* a compressed or uncompressed protocol field.
*/
+ sg_init_table(sg_in, 1);
+ sg_init_table(sg_out, 1);
setup_sg(sg_in, ibuf, 1);
setup_sg(sg_out, obuf, 1);
if (crypto_blkcipher_decrypt(&desc, sg_out, sg_in, 1) != 0) {
diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c
index ce64032a465a..f0c6a1926a02 100644
--- a/drivers/net/ppp_synctty.c
+++ b/drivers/net/ppp_synctty.c
@@ -209,7 +209,7 @@ ppp_sync_open(struct tty_struct *tty)
ap = kzalloc(sizeof(*ap), GFP_KERNEL);
err = -ENOMEM;
- if (ap == 0)
+ if (!ap)
goto out;
/* initialize the syncppp structure */
@@ -262,7 +262,7 @@ ppp_sync_close(struct tty_struct *tty)
ap = tty->disc_data;
tty->disc_data = NULL;
write_unlock_irq(&disc_data_lock);
- if (ap == 0)
+ if (!ap)
return;
/*
@@ -278,7 +278,7 @@ ppp_sync_close(struct tty_struct *tty)
ppp_unregister_channel(&ap->chan);
skb_queue_purge(&ap->rqueue);
- if (ap->tpkt != 0)
+ if (ap->tpkt)
kfree_skb(ap->tpkt);
kfree(ap);
}
@@ -325,13 +325,13 @@ ppp_synctty_ioctl(struct tty_struct *tty, struct file *file,
int __user *p = (int __user *)arg;
int err, val;
- if (ap == 0)
+ if (!ap)
return -ENXIO;
err = -EFAULT;
switch (cmd) {
case PPPIOCGCHAN:
err = -ENXIO;
- if (ap == 0)
+ if (!ap)
break;
err = -EFAULT;
if (put_user(ppp_channel_index(&ap->chan), p))
@@ -341,7 +341,7 @@ ppp_synctty_ioctl(struct tty_struct *tty, struct file *file,
case PPPIOCGUNIT:
err = -ENXIO;
- if (ap == 0)
+ if (!ap)
break;
err = -EFAULT;
if (put_user(ppp_unit_number(&ap->chan), p))
@@ -349,16 +349,11 @@ ppp_synctty_ioctl(struct tty_struct *tty, struct file *file,
err = 0;
break;
- case TCGETS:
- case TCGETA:
- err = n_tty_ioctl(tty, file, cmd, arg);
- break;
-
case TCFLSH:
/* flush our buffers and the serial port's buffer */
if (arg == TCIOFLUSH || arg == TCOFLUSH)
ppp_sync_flush_output(ap);
- err = n_tty_ioctl(tty, file, cmd, arg);
+ err = tty_perform_flush(tty, arg);
break;
case FIONREAD:
@@ -369,7 +364,8 @@ ppp_synctty_ioctl(struct tty_struct *tty, struct file *file,
break;
default:
- err = -ENOIOCTLCMD;
+ err = tty_mode_ioctl(tty, file, cmd, arg);
+ break;
}
sp_put(ap);
@@ -394,7 +390,7 @@ ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf,
struct syncppp *ap = sp_get(tty);
unsigned long flags;
- if (ap == 0)
+ if (!ap)
return;
spin_lock_irqsave(&ap->recv_lock, flags);
ppp_sync_input(ap, buf, cflags, count);
@@ -413,7 +409,7 @@ ppp_sync_wakeup(struct tty_struct *tty)
struct syncppp *ap = sp_get(tty);
clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
- if (ap == 0)
+ if (!ap)
return;
set_bit(XMIT_WAKEUP, &ap->xmit_flags);
tasklet_schedule(&ap->tsk);
@@ -655,7 +651,7 @@ ppp_sync_push(struct syncppp *ap)
for (;;) {
if (test_and_clear_bit(XMIT_WAKEUP, &ap->xmit_flags))
tty_stuffed = 0;
- if (!tty_stuffed && ap->tpkt != 0) {
+ if (!tty_stuffed && ap->tpkt) {
set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
sent = tty->driver->write(tty, ap->tpkt->data, ap->tpkt->len);
if (sent < 0)
@@ -673,7 +669,7 @@ ppp_sync_push(struct syncppp *ap)
/* haven't made any progress */
spin_unlock_bh(&ap->xmit_lock);
if (!(test_bit(XMIT_WAKEUP, &ap->xmit_flags)
- || (!tty_stuffed && ap->tpkt != 0)))
+ || (!tty_stuffed && ap->tpkt)))
break;
if (!spin_trylock_bh(&ap->xmit_lock))
break;
@@ -681,7 +677,7 @@ ppp_sync_push(struct syncppp *ap)
return done;
flush:
- if (ap->tpkt != 0) {
+ if (ap->tpkt) {
kfree_skb(ap->tpkt);
ap->tpkt = NULL;
clear_bit(XMIT_FULL, &ap->xmit_flags);
@@ -736,7 +732,8 @@ ppp_sync_input(struct syncppp *ap, const unsigned char *buf,
ppp_print_buffer ("receive buffer", buf, count);
/* stuff the chars in the skb */
- if ((skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2)) == 0) {
+ skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2);
+ if (!skb) {
printk(KERN_ERR "PPPsync: no memory (input pkt)\n");
goto err;
}
@@ -744,7 +741,7 @@ ppp_sync_input(struct syncppp *ap, const unsigned char *buf,
if (buf[0] != PPP_ALLSTATIONS)
skb_reserve(skb, 2 + (buf[0] & 1));
- if (flags != 0 && *flags) {
+ if (flags && *flags) {
/* error flag set, ignore frame */
goto err;
} else if (count > skb_tailroom(skb)) {
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index 8936ed3469cf..a005d8f4c38e 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -491,7 +491,7 @@ static int pppoe_create(struct net *net, struct socket *sock)
int error = -ENOMEM;
struct sock *sk;
- sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pppoe_sk_proto, 1);
+ sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pppoe_sk_proto);
if (!sk)
goto out;
diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c
index 921d4ef6d14b..a7556cd2df79 100644
--- a/drivers/net/pppol2tp.c
+++ b/drivers/net/pppol2tp.c
@@ -488,7 +488,7 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb)
{
struct pppol2tp_session *session = NULL;
struct pppol2tp_tunnel *tunnel;
- unsigned char *ptr;
+ unsigned char *ptr, *optr;
u16 hdrflags;
u16 tunnel_id, session_id;
int length;
@@ -496,7 +496,7 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb)
tunnel = pppol2tp_sock_to_tunnel(sock);
if (tunnel == NULL)
- goto error;
+ goto no_tunnel;
/* UDP always verifies the packet length. */
__skb_pull(skb, sizeof(struct udphdr));
@@ -509,7 +509,7 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb)
}
/* Point to L2TP header */
- ptr = skb->data;
+ optr = ptr = skb->data;
/* Get L2TP header flags */
hdrflags = ntohs(*(__be16*)ptr);
@@ -637,12 +637,14 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb)
/* If offset bit set, skip it. */
if (hdrflags & L2TP_HDRFLAG_O) {
offset = ntohs(*(__be16 *)ptr);
- skb->transport_header += 2 + offset;
- if (!pskb_may_pull(skb, skb_transport_offset(skb) + 2))
- goto discard;
+ ptr += 2 + offset;
}
- __skb_pull(skb, skb_transport_offset(skb));
+ offset = ptr - optr;
+ if (!pskb_may_pull(skb, offset))
+ goto discard;
+
+ __skb_pull(skb, offset);
/* Skip PPP header, if present. In testing, Microsoft L2TP clients
* don't send the PPP header (PPP header compression enabled), but
@@ -652,6 +654,9 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb)
* Note that skb->data[] isn't dereferenced from a u16 ptr here since
* the field may be unaligned.
*/
+ if (!pskb_may_pull(skb, 2))
+ goto discard;
+
if ((skb->data[0] == 0xff) && (skb->data[1] == 0x03))
skb_pull(skb, 2);
@@ -709,6 +714,10 @@ discard:
return 0;
error:
+ /* Put UDP header back */
+ __skb_push(skb, sizeof(struct udphdr));
+
+no_tunnel:
return 1;
}
@@ -1050,6 +1059,8 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
/* Get routing info from the tunnel socket */
dst_release(skb->dst);
skb->dst = sk_dst_get(sk_tun);
+ skb_orphan(skb);
+ skb->sk = sk_tun;
/* Queue the packet to IP for output */
len = skb->len;
@@ -1416,7 +1427,7 @@ static int pppol2tp_create(struct net *net, struct socket *sock)
int error = -ENOMEM;
struct sock *sk;
- sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pppol2tp_sk_proto, 1);
+ sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pppol2tp_sk_proto);
if (!sk)
goto out;
diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index 30adf726743c..a5791114b7bd 100644
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -1456,16 +1456,11 @@ static void ql_phy_start_neg_ex(struct ql3_adapter *qdev)
PHYAddr[qdev->mac_index]);
reg &= ~PHY_GIG_ALL_PARAMS;
- if(portConfiguration &
- PORT_CONFIG_FULL_DUPLEX_ENABLED &
- PORT_CONFIG_1000MB_SPEED) {
- reg |= PHY_GIG_ADV_1000F;
- }
-
- if(portConfiguration &
- PORT_CONFIG_HALF_DUPLEX_ENABLED &
- PORT_CONFIG_1000MB_SPEED) {
- reg |= PHY_GIG_ADV_1000H;
+ if(portConfiguration & PORT_CONFIG_1000MB_SPEED) {
+ if(portConfiguration & PORT_CONFIG_FULL_DUPLEX_ENABLED)
+ reg |= PHY_GIG_ADV_1000F;
+ else
+ reg |= PHY_GIG_ADV_1000H;
}
ql_mii_write_reg_ex(qdev, PHY_GIG_CONTROL, reg,
@@ -1645,8 +1640,11 @@ static int ql_finish_auto_neg(struct ql3_adapter *qdev)
return 0;
}
-static void ql_link_state_machine(struct ql3_adapter *qdev)
+static void ql_link_state_machine_work(struct work_struct *work)
{
+ struct ql3_adapter *qdev =
+ container_of(work, struct ql3_adapter, link_state_work.work);
+
u32 curr_link_state;
unsigned long hw_flags;
@@ -1661,6 +1659,10 @@ static void ql_link_state_machine(struct ql3_adapter *qdev)
"state.\n", qdev->ndev->name);
spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+
+ /* Restart timer on 2 second interval. */
+ mod_timer(&qdev->adapter_timer, jiffies + HZ * 1);\
+
return;
}
@@ -1705,6 +1707,9 @@ static void ql_link_state_machine(struct ql3_adapter *qdev)
break;
}
spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+
+ /* Restart timer on 2 second interval. */
+ mod_timer(&qdev->adapter_timer, jiffies + HZ * 1);
}
/*
@@ -3941,19 +3946,7 @@ static void ql_get_board_info(struct ql3_adapter *qdev)
static void ql3xxx_timer(unsigned long ptr)
{
struct ql3_adapter *qdev = (struct ql3_adapter *)ptr;
-
- if (test_bit(QL_RESET_ACTIVE,&qdev->flags)) {
- printk(KERN_DEBUG PFX
- "%s: Reset in progress.\n",
- qdev->ndev->name);
- goto end;
- }
-
- ql_link_state_machine(qdev);
-
- /* Restart timer on 2 second interval. */
-end:
- mod_timer(&qdev->adapter_timer, jiffies + HZ * 1);
+ queue_delayed_work(qdev->workqueue, &qdev->link_state_work, 0);
}
static int __devinit ql3xxx_probe(struct pci_dev *pdev,
@@ -4103,6 +4096,7 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev,
qdev->workqueue = create_singlethread_workqueue(ndev->name);
INIT_DELAYED_WORK(&qdev->reset_work, ql_reset_work);
INIT_DELAYED_WORK(&qdev->tx_timeout_work, ql_tx_timeout_work);
+ INIT_DELAYED_WORK(&qdev->link_state_work, ql_link_state_machine_work);
init_timer(&qdev->adapter_timer);
qdev->adapter_timer.function = ql3xxx_timer;
diff --git a/drivers/net/qla3xxx.h b/drivers/net/qla3xxx.h
index fbcb0b949639..d0ffb30ef371 100644
--- a/drivers/net/qla3xxx.h
+++ b/drivers/net/qla3xxx.h
@@ -1286,6 +1286,7 @@ struct ql3_adapter {
struct workqueue_struct *workqueue;
struct delayed_work reset_work;
struct delayed_work tx_timeout_work;
+ struct delayed_work link_state_work;
u32 max_frame_size;
u32 device_id;
u16 phyType;
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 419c00cbe6e9..1f647b9ce352 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -44,7 +44,8 @@
printk( "Assertion failed! %s,%s,%s,line=%d\n", \
#expr,__FILE__,__FUNCTION__,__LINE__); \
}
-#define dprintk(fmt, args...) do { printk(PFX fmt, ## args); } while (0)
+#define dprintk(fmt, args...) \
+ do { printk(KERN_DEBUG PFX fmt, ## args); } while (0)
#else
#define assert(expr) do {} while (0)
#define dprintk(fmt, args...) do {} while (0)
@@ -111,19 +112,15 @@ enum mac_version {
RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd
RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe
RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb
- RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be 8168Bf
- RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb 8101Ec
- RTL_GIGA_MAC_VER_14 = 0x0e, // 8101
- RTL_GIGA_MAC_VER_15 = 0x0f // 8101
-};
-
-enum phy_version {
- RTL_GIGA_PHY_VER_C = 0x03, /* PHY Reg 0x03 bit0-3 == 0x0000 */
- RTL_GIGA_PHY_VER_D = 0x04, /* PHY Reg 0x03 bit0-3 == 0x0000 */
- RTL_GIGA_PHY_VER_E = 0x05, /* PHY Reg 0x03 bit0-3 == 0x0000 */
- RTL_GIGA_PHY_VER_F = 0x06, /* PHY Reg 0x03 bit0-3 == 0x0001 */
- RTL_GIGA_PHY_VER_G = 0x07, /* PHY Reg 0x03 bit0-3 == 0x0002 */
- RTL_GIGA_PHY_VER_H = 0x08, /* PHY Reg 0x03 bit0-3 == 0x0003 */
+ RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be
+ RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb
+ RTL_GIGA_MAC_VER_14 = 0x0e, // 8101 ?
+ RTL_GIGA_MAC_VER_15 = 0x0f, // 8101 ?
+ RTL_GIGA_MAC_VER_16 = 0x11, // 8101Ec
+ RTL_GIGA_MAC_VER_17 = 0x10, // 8168Bf
+ RTL_GIGA_MAC_VER_18 = 0x12, // 8168CP
+ RTL_GIGA_MAC_VER_19 = 0x13, // 8168C
+ RTL_GIGA_MAC_VER_20 = 0x14 // 8168C
};
#define _R(NAME,MAC,MASK) \
@@ -144,7 +141,12 @@ static const struct {
_R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E
_R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139
_R("RTL8100e", RTL_GIGA_MAC_VER_14, 0xff7e1880), // PCI-E 8139
- _R("RTL8100e", RTL_GIGA_MAC_VER_15, 0xff7e1880) // PCI-E 8139
+ _R("RTL8100e", RTL_GIGA_MAC_VER_15, 0xff7e1880), // PCI-E 8139
+ _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_17, 0xff7e1880), // PCI-E
+ _R("RTL8101e", RTL_GIGA_MAC_VER_16, 0xff7e1880), // PCI-E
+ _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_18, 0xff7e1880), // PCI-E
+ _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_19, 0xff7e1880), // PCI-E
+ _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, 0xff7e1880) // PCI-E
};
#undef _R
@@ -165,10 +167,12 @@ static struct pci_device_id rtl8169_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 },
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 },
{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 },
- { PCI_DEVICE(0x1259, 0xc107), 0, 0, RTL_CFG_0 },
+ { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 },
{ PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 },
{ PCI_VENDOR_ID_LINKSYS, 0x1032,
PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 },
+ { 0x0001, 0x8168,
+ PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 },
{0,},
};
@@ -277,6 +281,7 @@ enum rtl_register_content {
TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */
/* Config1 register p.24 */
+ MSIEnable = (1 << 5), /* Enable Message Signaled Interrupt */
PMEnable = (1 << 0), /* Power Management Enable */
/* Config2 register p. 25 */
@@ -380,17 +385,22 @@ struct ring_info {
u8 __pad[sizeof(void *) - sizeof(u32)];
};
+enum features {
+ RTL_FEATURE_WOL = (1 << 0),
+ RTL_FEATURE_MSI = (1 << 1),
+};
+
struct rtl8169_private {
void __iomem *mmio_addr; /* memory map physical address */
struct pci_dev *pci_dev; /* Index of PCI device */
struct net_device *dev;
+#ifdef CONFIG_R8169_NAPI
struct napi_struct napi;
- struct net_device_stats stats; /* statistics of net device */
+#endif
spinlock_t lock; /* spin lock flag */
u32 msg_enable;
int chipset;
int mac_version;
- int phy_version;
u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */
u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */
u32 dirty_rx;
@@ -420,7 +430,7 @@ struct rtl8169_private {
unsigned int (*phy_reset_pending)(void __iomem *);
unsigned int (*link_ok)(void __iomem *);
struct delayed_work task;
- unsigned wol_enabled : 1;
+ unsigned features;
};
MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
@@ -460,7 +470,7 @@ static void mdio_write(void __iomem *ioaddr, int reg_addr, int value)
{
int i;
- RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0xFF) << 16 | value);
+ RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0x1f) << 16 | (value & 0xffff));
for (i = 20; i > 0; i--) {
/*
@@ -477,7 +487,7 @@ static int mdio_read(void __iomem *ioaddr, int reg_addr)
{
int i, value = -1;
- RTL_W32(PHYAR, 0x0 | (reg_addr & 0xFF) << 16);
+ RTL_W32(PHYAR, 0x0 | (reg_addr & 0x1f) << 16);
for (i = 20; i > 0; i--) {
/*
@@ -485,7 +495,7 @@ static int mdio_read(void __iomem *ioaddr, int reg_addr)
* the specified MII register.
*/
if (RTL_R32(PHYAR) & 0x80000000) {
- value = (int) (RTL_R32(PHYAR) & 0xFFFF);
+ value = RTL_R32(PHYAR) & 0xffff;
break;
}
udelay(25);
@@ -626,7 +636,10 @@ static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
RTL_W8(Cfg9346, Cfg9346_Lock);
- tp->wol_enabled = (wol->wolopts) ? 1 : 0;
+ if (wol->wolopts)
+ tp->features |= RTL_FEATURE_WOL;
+ else
+ tp->features &= ~RTL_FEATURE_WOL;
spin_unlock_irq(&tp->lock);
@@ -707,7 +720,8 @@ static int rtl8169_set_speed_xmii(struct net_device *dev,
/* This tweak comes straight from Realtek's driver. */
if ((speed == SPEED_100) && (duplex == DUPLEX_HALF) &&
- (tp->mac_version == RTL_GIGA_MAC_VER_13)) {
+ ((tp->mac_version == RTL_GIGA_MAC_VER_13) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_16))) {
auto_nego = ADVERTISE_100HALF | ADVERTISE_CSMA;
}
}
@@ -715,7 +729,8 @@ static int rtl8169_set_speed_xmii(struct net_device *dev,
/* The 8100e/8101e do Fast Ethernet only. */
if ((tp->mac_version == RTL_GIGA_MAC_VER_13) ||
(tp->mac_version == RTL_GIGA_MAC_VER_14) ||
- (tp->mac_version == RTL_GIGA_MAC_VER_15)) {
+ (tp->mac_version == RTL_GIGA_MAC_VER_15) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_16)) {
if ((giga_ctrl & (ADVERTISE_1000FULL | ADVERTISE_1000HALF)) &&
netif_msg_link(tp)) {
printk(KERN_INFO "%s: PHY does not support 1000Mbps.\n",
@@ -726,7 +741,8 @@ static int rtl8169_set_speed_xmii(struct net_device *dev,
auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
- if (tp->mac_version == RTL_GIGA_MAC_VER_12) {
+ if ((tp->mac_version == RTL_GIGA_MAC_VER_12) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_17)) {
/* Vendor specific (0x1f) and reserved (0x0e) MII registers. */
mdio_write(ioaddr, 0x1f, 0x0000);
mdio_write(ioaddr, 0x0e, 0x0000);
@@ -1104,26 +1120,51 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp,
*/
const struct {
u32 mask;
+ u32 val;
int mac_version;
} mac_info[] = {
- { 0x38800000, RTL_GIGA_MAC_VER_15 },
- { 0x38000000, RTL_GIGA_MAC_VER_12 },
- { 0x34000000, RTL_GIGA_MAC_VER_13 },
- { 0x30800000, RTL_GIGA_MAC_VER_14 },
- { 0x30000000, RTL_GIGA_MAC_VER_11 },
- { 0x98000000, RTL_GIGA_MAC_VER_06 },
- { 0x18000000, RTL_GIGA_MAC_VER_05 },
- { 0x10000000, RTL_GIGA_MAC_VER_04 },
- { 0x04000000, RTL_GIGA_MAC_VER_03 },
- { 0x00800000, RTL_GIGA_MAC_VER_02 },
- { 0x00000000, RTL_GIGA_MAC_VER_01 } /* Catch-all */
+ /* 8168B family. */
+ { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_18 },
+ { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 },
+ { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 },
+ { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_20 },
+
+ /* 8168B family. */
+ { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 },
+ { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 },
+ { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 },
+ { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 },
+
+ /* 8101 family. */
+ { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 },
+ { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 },
+ { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 },
+ /* FIXME: where did these entries come from ? -- FR */
+ { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 },
+ { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 },
+
+ /* 8110 family. */
+ { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 },
+ { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 },
+ { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 },
+ { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 },
+ { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 },
+ { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 },
+
+ { 0x00000000, 0x00000000, RTL_GIGA_MAC_VER_01 } /* Catch-all */
}, *p = mac_info;
u32 reg;
- reg = RTL_R32(TxConfig) & 0xfc800000;
- while ((reg & p->mask) != p->mask)
+ reg = RTL_R32(TxConfig);
+ while ((reg & p->mask) != p->val)
p++;
tp->mac_version = p->mac_version;
+
+ if (p->mask == 0x00000000) {
+ struct pci_dev *pdev = tp->pci_dev;
+
+ dev_info(&pdev->dev, "unknown MAC (%08x)\n", reg);
+ }
}
static void rtl8169_print_mac_version(struct rtl8169_private *tp)
@@ -1131,54 +1172,21 @@ static void rtl8169_print_mac_version(struct rtl8169_private *tp)
dprintk("mac_version = 0x%02x\n", tp->mac_version);
}
-static void rtl8169_get_phy_version(struct rtl8169_private *tp,
- void __iomem *ioaddr)
-{
- const struct {
- u16 mask;
- u16 set;
- int phy_version;
- } phy_info[] = {
- { 0x000f, 0x0002, RTL_GIGA_PHY_VER_G },
- { 0x000f, 0x0001, RTL_GIGA_PHY_VER_F },
- { 0x000f, 0x0000, RTL_GIGA_PHY_VER_E },
- { 0x0000, 0x0000, RTL_GIGA_PHY_VER_D } /* Catch-all */
- }, *p = phy_info;
+struct phy_reg {
u16 reg;
+ u16 val;
+};
- reg = mdio_read(ioaddr, MII_PHYSID2) & 0xffff;
- while ((reg & p->mask) != p->set)
- p++;
- tp->phy_version = p->phy_version;
-}
-
-static void rtl8169_print_phy_version(struct rtl8169_private *tp)
+static void rtl_phy_write(void __iomem *ioaddr, struct phy_reg *regs, int len)
{
- struct {
- int version;
- char *msg;
- u32 reg;
- } phy_print[] = {
- { RTL_GIGA_PHY_VER_G, "RTL_GIGA_PHY_VER_G", 0x0002 },
- { RTL_GIGA_PHY_VER_F, "RTL_GIGA_PHY_VER_F", 0x0001 },
- { RTL_GIGA_PHY_VER_E, "RTL_GIGA_PHY_VER_E", 0x0000 },
- { RTL_GIGA_PHY_VER_D, "RTL_GIGA_PHY_VER_D", 0x0000 },
- { 0, NULL, 0x0000 }
- }, *p;
-
- for (p = phy_print; p->msg; p++) {
- if (tp->phy_version == p->version) {
- dprintk("phy_version == %s (%04x)\n", p->msg, p->reg);
- return;
- }
+ while (len-- > 0) {
+ mdio_write(ioaddr, regs->reg, regs->val);
+ regs++;
}
- dprintk("phy_version == Unknown\n");
}
-static void rtl8169_hw_phy_config(struct net_device *dev)
+static void rtl8169s_hw_phy_config(void __iomem *ioaddr)
{
- struct rtl8169_private *tp = netdev_priv(dev);
- void __iomem *ioaddr = tp->mmio_addr;
struct {
u16 regs[5]; /* Beware of bit-sign propagation */
} phy_magic[5] = { {
@@ -1211,33 +1219,9 @@ static void rtl8169_hw_phy_config(struct net_device *dev)
}, *p = phy_magic;
unsigned int i;
- rtl8169_print_mac_version(tp);
- rtl8169_print_phy_version(tp);
-
- if (tp->mac_version <= RTL_GIGA_MAC_VER_01)
- return;
- if (tp->phy_version >= RTL_GIGA_PHY_VER_H)
- return;
-
- dprintk("MAC version != 0 && PHY version == 0 or 1\n");
- dprintk("Do final_reg2.cfg\n");
-
- /* Shazam ! */
-
- if (tp->mac_version == RTL_GIGA_MAC_VER_04) {
- mdio_write(ioaddr, 31, 0x0002);
- mdio_write(ioaddr, 1, 0x90d0);
- mdio_write(ioaddr, 31, 0x0000);
- return;
- }
-
- if ((tp->mac_version != RTL_GIGA_MAC_VER_02) &&
- (tp->mac_version != RTL_GIGA_MAC_VER_03))
- return;
-
- mdio_write(ioaddr, 31, 0x0001); //w 31 2 0 1
- mdio_write(ioaddr, 21, 0x1000); //w 21 15 0 1000
- mdio_write(ioaddr, 24, 0x65c7); //w 24 15 0 65c7
+ mdio_write(ioaddr, 0x1f, 0x0001); //w 31 2 0 1
+ mdio_write(ioaddr, 0x15, 0x1000); //w 21 15 0 1000
+ mdio_write(ioaddr, 0x18, 0x65c7); //w 24 15 0 65c7
rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0
for (i = 0; i < ARRAY_SIZE(phy_magic); i++, p++) {
@@ -1250,7 +1234,100 @@ static void rtl8169_hw_phy_config(struct net_device *dev)
rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 1); //w 4 11 11 1
rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0
}
- mdio_write(ioaddr, 31, 0x0000); //w 31 2 0 0
+ mdio_write(ioaddr, 0x1f, 0x0000); //w 31 2 0 0
+}
+
+static void rtl8169sb_hw_phy_config(void __iomem *ioaddr)
+{
+ struct phy_reg phy_reg_init[] = {
+ { 0x1f, 0x0002 },
+ { 0x01, 0x90d0 },
+ { 0x1f, 0x0000 }
+ };
+
+ rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+}
+
+static void rtl8168cp_hw_phy_config(void __iomem *ioaddr)
+{
+ struct phy_reg phy_reg_init[] = {
+ { 0x1f, 0x0000 },
+ { 0x1d, 0x0f00 },
+ { 0x1f, 0x0002 },
+ { 0x0c, 0x1ec8 },
+ { 0x1f, 0x0000 }
+ };
+
+ rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+}
+
+static void rtl8168c_hw_phy_config(void __iomem *ioaddr)
+{
+ struct phy_reg phy_reg_init[] = {
+ { 0x1f, 0x0001 },
+ { 0x12, 0x2300 },
+ { 0x1f, 0x0002 },
+ { 0x00, 0x88d4 },
+ { 0x01, 0x82b1 },
+ { 0x03, 0x7002 },
+ { 0x08, 0x9e30 },
+ { 0x09, 0x01f0 },
+ { 0x0a, 0x5500 },
+ { 0x0c, 0x00c8 },
+ { 0x1f, 0x0003 },
+ { 0x12, 0xc096 },
+ { 0x16, 0x000a },
+ { 0x1f, 0x0000 }
+ };
+
+ rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+}
+
+static void rtl8168cx_hw_phy_config(void __iomem *ioaddr)
+{
+ struct phy_reg phy_reg_init[] = {
+ { 0x1f, 0x0000 },
+ { 0x12, 0x2300 },
+ { 0x1f, 0x0003 },
+ { 0x16, 0x0f0a },
+ { 0x1f, 0x0000 },
+ { 0x1f, 0x0002 },
+ { 0x0c, 0x7eb8 },
+ { 0x1f, 0x0000 }
+ };
+
+ rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+}
+
+static void rtl_hw_phy_config(struct net_device *dev)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ rtl8169_print_mac_version(tp);
+
+ switch (tp->mac_version) {
+ case RTL_GIGA_MAC_VER_01:
+ break;
+ case RTL_GIGA_MAC_VER_02:
+ case RTL_GIGA_MAC_VER_03:
+ rtl8169s_hw_phy_config(ioaddr);
+ break;
+ case RTL_GIGA_MAC_VER_04:
+ rtl8169sb_hw_phy_config(ioaddr);
+ break;
+ case RTL_GIGA_MAC_VER_18:
+ rtl8168cp_hw_phy_config(ioaddr);
+ break;
+ case RTL_GIGA_MAC_VER_19:
+ rtl8168c_hw_phy_config(ioaddr);
+ break;
+ case RTL_GIGA_MAC_VER_20:
+ rtl8168cx_hw_phy_config(ioaddr);
+ break;
+ default:
+ break;
+ }
}
static void rtl8169_phy_timer(unsigned long __opaque)
@@ -1262,7 +1339,6 @@ static void rtl8169_phy_timer(unsigned long __opaque)
unsigned long timeout = RTL8169_PHY_TIMEOUT;
assert(tp->mac_version > RTL_GIGA_MAC_VER_01);
- assert(tp->phy_version < RTL_GIGA_PHY_VER_H);
if (!(tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL))
return;
@@ -1297,8 +1373,7 @@ static inline void rtl8169_delete_timer(struct net_device *dev)
struct rtl8169_private *tp = netdev_priv(dev);
struct timer_list *timer = &tp->timer;
- if ((tp->mac_version <= RTL_GIGA_MAC_VER_01) ||
- (tp->phy_version >= RTL_GIGA_PHY_VER_H))
+ if (tp->mac_version <= RTL_GIGA_MAC_VER_01)
return;
del_timer_sync(timer);
@@ -1309,8 +1384,7 @@ static inline void rtl8169_request_timer(struct net_device *dev)
struct rtl8169_private *tp = netdev_priv(dev);
struct timer_list *timer = &tp->timer;
- if ((tp->mac_version <= RTL_GIGA_MAC_VER_01) ||
- (tp->phy_version >= RTL_GIGA_PHY_VER_H))
+ if (tp->mac_version <= RTL_GIGA_MAC_VER_01)
return;
mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT);
@@ -1362,7 +1436,7 @@ static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)
{
void __iomem *ioaddr = tp->mmio_addr;
- rtl8169_hw_phy_config(dev);
+ rtl_hw_phy_config(dev);
dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
RTL_W8(0x82, 0x01);
@@ -1457,6 +1531,7 @@ static const struct rtl_cfg_info {
unsigned int align;
u16 intr_event;
u16 napi_event;
+ unsigned msi;
} rtl_cfg_infos [] = {
[RTL_CFG_0] = {
.hw_start = rtl_hw_start_8169,
@@ -1464,7 +1539,8 @@ static const struct rtl_cfg_info {
.align = 0,
.intr_event = SYSErr | LinkChg | RxOverflow |
RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
- .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow
+ .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow,
+ .msi = 0
},
[RTL_CFG_1] = {
.hw_start = rtl_hw_start_8168,
@@ -1472,7 +1548,8 @@ static const struct rtl_cfg_info {
.align = 8,
.intr_event = SYSErr | LinkChg | RxOverflow |
TxErr | TxOK | RxOK | RxErr,
- .napi_event = TxErr | TxOK | RxOK | RxOverflow
+ .napi_event = TxErr | TxOK | RxOK | RxOverflow,
+ .msi = RTL_FEATURE_MSI
},
[RTL_CFG_2] = {
.hw_start = rtl_hw_start_8101,
@@ -1480,10 +1557,39 @@ static const struct rtl_cfg_info {
.align = 8,
.intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout |
RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
- .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow
+ .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow,
+ .msi = RTL_FEATURE_MSI
}
};
+/* Cfg9346_Unlock assumed. */
+static unsigned rtl_try_msi(struct pci_dev *pdev, void __iomem *ioaddr,
+ const struct rtl_cfg_info *cfg)
+{
+ unsigned msi = 0;
+ u8 cfg2;
+
+ cfg2 = RTL_R8(Config2) & ~MSIEnable;
+ if (cfg->msi) {
+ if (pci_enable_msi(pdev)) {
+ dev_info(&pdev->dev, "no MSI. Back to INTx.\n");
+ } else {
+ cfg2 |= MSIEnable;
+ msi = RTL_FEATURE_MSI;
+ }
+ }
+ RTL_W8(Config2, cfg2);
+ return msi;
+}
+
+static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp)
+{
+ if (tp->features & RTL_FEATURE_MSI) {
+ pci_disable_msi(pdev);
+ tp->features &= ~RTL_FEATURE_MSI;
+ }
+}
+
static int __devinit
rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
@@ -1596,10 +1702,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Identify chip attached to board */
rtl8169_get_mac_version(tp, ioaddr);
- rtl8169_get_phy_version(tp, ioaddr);
rtl8169_print_mac_version(tp);
- rtl8169_print_phy_version(tp);
for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--) {
if (tp->mac_version == rtl_chip_info[i].mac_version)
@@ -1619,9 +1723,11 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
RTL_W8(Cfg9346, Cfg9346_Unlock);
RTL_W8(Config1, RTL_R8(Config1) | PMEnable);
RTL_W8(Config5, RTL_R8(Config5) & PMEStatus);
+ tp->features |= rtl_try_msi(pdev, ioaddr, cfg);
RTL_W8(Cfg9346, Cfg9346_Lock);
- if (RTL_R8(PHYstatus) & TBI_Enable) {
+ if ((tp->mac_version <= RTL_GIGA_MAC_VER_06) &&
+ (RTL_R8(PHYstatus) & TBI_Enable)) {
tp->set_speed = rtl8169_set_speed_tbi;
tp->get_settings = rtl8169_gset_tbi;
tp->phy_reset_enable = rtl8169_tbi_reset_enable;
@@ -1686,7 +1792,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
rc = register_netdev(dev);
if (rc < 0)
- goto err_out_unmap_5;
+ goto err_out_msi_5;
pci_set_drvdata(pdev, dev);
@@ -1709,7 +1815,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
out:
return rc;
-err_out_unmap_5:
+err_out_msi_5:
+ rtl_disable_msi(pdev, tp);
iounmap(ioaddr);
err_out_free_res_4:
pci_release_regions(pdev);
@@ -1730,6 +1837,7 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
flush_scheduled_work();
unregister_netdev(dev);
+ rtl_disable_msi(pdev, tp);
rtl8169_release_board(pdev, dev, tp->mmio_addr);
pci_set_drvdata(pdev, NULL);
}
@@ -1773,7 +1881,8 @@ static int rtl8169_open(struct net_device *dev)
smp_mb();
- retval = request_irq(dev->irq, rtl8169_interrupt, IRQF_SHARED,
+ retval = request_irq(dev->irq, rtl8169_interrupt,
+ (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED,
dev->name, dev);
if (retval < 0)
goto err_release_ring_2;
@@ -1933,7 +2042,7 @@ static void rtl_hw_start_8169(struct net_device *dev)
if ((tp->mac_version == RTL_GIGA_MAC_VER_02) ||
(tp->mac_version == RTL_GIGA_MAC_VER_03)) {
- dprintk(KERN_INFO PFX "Set MAC Reg C+CR Offset 0xE0. "
+ dprintk("Set MAC Reg C+CR Offset 0xE0. "
"Bit-3 and bit-14 MUST be 1\n");
tp->cp_cmd |= (1 << 14);
}
@@ -2029,7 +2138,8 @@ static void rtl_hw_start_8101(struct net_device *dev)
void __iomem *ioaddr = tp->mmio_addr;
struct pci_dev *pdev = tp->pci_dev;
- if (tp->mac_version == RTL_GIGA_MAC_VER_13) {
+ if ((tp->mac_version == RTL_GIGA_MAC_VER_13) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_16)) {
pci_write_config_word(pdev, 0x68, 0x00);
pci_write_config_word(pdev, 0x69, 0x08);
}
@@ -2259,7 +2369,7 @@ static void rtl8169_tx_clear(struct rtl8169_private *tp)
dev_kfree_skb(skb);
tx_skb->skb = NULL;
}
- tp->stats.tx_dropped++;
+ tp->dev->stats.tx_dropped++;
}
}
tp->cur_tx = tp->dirty_tx = 0;
@@ -2310,7 +2420,7 @@ static void rtl8169_reinit_task(struct work_struct *work)
ret = rtl8169_open(dev);
if (unlikely(ret < 0)) {
if (net_ratelimit() && netif_msg_drv(tp)) {
- printk(PFX KERN_ERR "%s: reinit failure (status = %d)."
+ printk(KERN_ERR PFX "%s: reinit failure (status = %d)."
" Rescheduling.\n", dev->name, ret);
}
rtl8169_schedule_work(dev, rtl8169_reinit_task);
@@ -2340,9 +2450,10 @@ static void rtl8169_reset_task(struct work_struct *work)
rtl8169_init_ring_indexes(tp);
rtl_hw_start(dev);
netif_wake_queue(dev);
+ rtl8169_check_link_status(dev, tp, tp->mmio_addr);
} else {
if (net_ratelimit() && netif_msg_intr(tp)) {
- printk(PFX KERN_EMERG "%s: Rx buffers shortage\n",
+ printk(KERN_EMERG PFX "%s: Rx buffers shortage\n",
dev->name);
}
rtl8169_schedule_work(dev, rtl8169_reset_task);
@@ -2496,7 +2607,7 @@ err_stop:
netif_stop_queue(dev);
ret = NETDEV_TX_BUSY;
err_update_stats:
- tp->stats.tx_dropped++;
+ dev->stats.tx_dropped++;
goto out;
}
@@ -2571,8 +2682,8 @@ static void rtl8169_tx_interrupt(struct net_device *dev,
if (status & DescOwn)
break;
- tp->stats.tx_bytes += len;
- tp->stats.tx_packets++;
+ dev->stats.tx_bytes += len;
+ dev->stats.tx_packets++;
rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, tp->TxDescArray + entry);
@@ -2672,14 +2783,14 @@ static int rtl8169_rx_interrupt(struct net_device *dev,
"%s: Rx ERROR. status = %08x\n",
dev->name, status);
}
- tp->stats.rx_errors++;
+ dev->stats.rx_errors++;
if (status & (RxRWT | RxRUNT))
- tp->stats.rx_length_errors++;
+ dev->stats.rx_length_errors++;
if (status & RxCRC)
- tp->stats.rx_crc_errors++;
+ dev->stats.rx_crc_errors++;
if (status & RxFOVF) {
rtl8169_schedule_work(dev, rtl8169_reset_task);
- tp->stats.rx_fifo_errors++;
+ dev->stats.rx_fifo_errors++;
}
rtl8169_mark_to_asic(desc, tp->rx_buf_sz);
} else {
@@ -2694,8 +2805,8 @@ static int rtl8169_rx_interrupt(struct net_device *dev,
* sized frames.
*/
if (unlikely(rtl8169_fragmented_frame(status))) {
- tp->stats.rx_dropped++;
- tp->stats.rx_length_errors++;
+ dev->stats.rx_dropped++;
+ dev->stats.rx_length_errors++;
rtl8169_mark_to_asic(desc, tp->rx_buf_sz);
continue;
}
@@ -2719,8 +2830,8 @@ static int rtl8169_rx_interrupt(struct net_device *dev,
rtl8169_rx_skb(skb);
dev->last_rx = jiffies;
- tp->stats.rx_bytes += pkt_size;
- tp->stats.rx_packets++;
+ dev->stats.rx_bytes += pkt_size;
+ dev->stats.rx_packets++;
}
/* Work around for AMD plateform. */
@@ -2868,31 +2979,29 @@ static void rtl8169_down(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
- unsigned int poll_locked = 0;
unsigned int intrmask;
rtl8169_delete_timer(dev);
netif_stop_queue(dev);
+#ifdef CONFIG_R8169_NAPI
+ napi_disable(&tp->napi);
+#endif
+
core_down:
spin_lock_irq(&tp->lock);
rtl8169_asic_down(ioaddr);
/* Update the error counts. */
- tp->stats.rx_missed_errors += RTL_R32(RxMissed);
+ dev->stats.rx_missed_errors += RTL_R32(RxMissed);
RTL_W32(RxMissed, 0);
spin_unlock_irq(&tp->lock);
synchronize_irq(dev->irq);
- if (!poll_locked) {
- napi_disable(&tp->napi);
- poll_locked++;
- }
-
/* Give a racing hard_start_xmit a few cycles to complete. */
synchronize_sched(); /* FIXME: should this be synchronize_irq()? */
@@ -2984,7 +3093,9 @@ static void rtl_set_rx_mode(struct net_device *dev)
(tp->mac_version == RTL_GIGA_MAC_VER_12) ||
(tp->mac_version == RTL_GIGA_MAC_VER_13) ||
(tp->mac_version == RTL_GIGA_MAC_VER_14) ||
- (tp->mac_version == RTL_GIGA_MAC_VER_15)) {
+ (tp->mac_version == RTL_GIGA_MAC_VER_15) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_16) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_17)) {
mc_filter[0] = 0xffffffff;
mc_filter[1] = 0xffffffff;
}
@@ -3011,12 +3122,12 @@ static struct net_device_stats *rtl8169_get_stats(struct net_device *dev)
if (netif_running(dev)) {
spin_lock_irqsave(&tp->lock, flags);
- tp->stats.rx_missed_errors += RTL_R32(RxMissed);
+ dev->stats.rx_missed_errors += RTL_R32(RxMissed);
RTL_W32(RxMissed, 0);
spin_unlock_irqrestore(&tp->lock, flags);
}
- return &tp->stats;
+ return &dev->stats;
}
#ifdef CONFIG_PM
@@ -3037,14 +3148,15 @@ static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state)
rtl8169_asic_down(ioaddr);
- tp->stats.rx_missed_errors += RTL_R32(RxMissed);
+ dev->stats.rx_missed_errors += RTL_R32(RxMissed);
RTL_W32(RxMissed, 0);
spin_unlock_irq(&tp->lock);
out_pci_suspend:
pci_save_state(pdev);
- pci_enable_wake(pdev, pci_choose_state(pdev, state), tp->wol_enabled);
+ pci_enable_wake(pdev, pci_choose_state(pdev, state),
+ (tp->features & RTL_FEATURE_WOL) ? 1 : 0);
pci_set_power_state(pdev, pci_choose_state(pdev, state));
return 0;
diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c
index 19152f54ef2b..73a7e6529ee0 100644
--- a/drivers/net/rrunner.c
+++ b/drivers/net/rrunner.c
@@ -78,14 +78,6 @@ static char version[] __devinitdata = "rrunner.c: v0.50 11/11/2002 Jes Sorensen
* stack will need to know about I/O vectors or something similar.
*/
-/*
- * These are checked at init time to see if they are at least 256KB
- * and increased to 256KB if they are not. This is done to avoid ending
- * up with socket buffers smaller than the MTU size,
- */
-extern __u32 sysctl_wmem_max;
-extern __u32 sysctl_rmem_max;
-
static int __devinit rr_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -563,18 +555,6 @@ static int __devinit rr_init(struct net_device *dev)
sram_size = rr_read_eeprom_word(rrpriv, (void *)8);
printk(" SRAM size 0x%06x\n", sram_size);
- if (sysctl_rmem_max < 262144){
- printk(" Receive socket buffer limit too low (%i), "
- "setting to 262144\n", sysctl_rmem_max);
- sysctl_rmem_max = 262144;
- }
-
- if (sysctl_wmem_max < 262144){
- printk(" Transmit socket buffer limit too low (%i), "
- "setting to 262144\n", sysctl_wmem_max);
- sysctl_wmem_max = 262144;
- }
-
return 0;
}
diff --git a/drivers/net/s2io-regs.h b/drivers/net/s2io-regs.h
index aef66e2d98d2..01f08d726ace 100644
--- a/drivers/net/s2io-regs.h
+++ b/drivers/net/s2io-regs.h
@@ -20,17 +20,17 @@ struct XENA_dev_config {
/* General Control-Status Registers */
u64 general_int_status;
-#define GEN_INTR_TXPIC BIT(0)
-#define GEN_INTR_TXDMA BIT(1)
-#define GEN_INTR_TXMAC BIT(2)
-#define GEN_INTR_TXXGXS BIT(3)
-#define GEN_INTR_TXTRAFFIC BIT(8)
-#define GEN_INTR_RXPIC BIT(32)
-#define GEN_INTR_RXDMA BIT(33)
-#define GEN_INTR_RXMAC BIT(34)
-#define GEN_INTR_MC BIT(35)
-#define GEN_INTR_RXXGXS BIT(36)
-#define GEN_INTR_RXTRAFFIC BIT(40)
+#define GEN_INTR_TXPIC s2BIT(0)
+#define GEN_INTR_TXDMA s2BIT(1)
+#define GEN_INTR_TXMAC s2BIT(2)
+#define GEN_INTR_TXXGXS s2BIT(3)
+#define GEN_INTR_TXTRAFFIC s2BIT(8)
+#define GEN_INTR_RXPIC s2BIT(32)
+#define GEN_INTR_RXDMA s2BIT(33)
+#define GEN_INTR_RXMAC s2BIT(34)
+#define GEN_INTR_MC s2BIT(35)
+#define GEN_INTR_RXXGXS s2BIT(36)
+#define GEN_INTR_RXTRAFFIC s2BIT(40)
#define GEN_ERROR_INTR GEN_INTR_TXPIC | GEN_INTR_RXPIC | \
GEN_INTR_TXDMA | GEN_INTR_RXDMA | \
GEN_INTR_TXMAC | GEN_INTR_RXMAC | \
@@ -54,36 +54,36 @@ struct XENA_dev_config {
u64 adapter_status;
-#define ADAPTER_STATUS_TDMA_READY BIT(0)
-#define ADAPTER_STATUS_RDMA_READY BIT(1)
-#define ADAPTER_STATUS_PFC_READY BIT(2)
-#define ADAPTER_STATUS_TMAC_BUF_EMPTY BIT(3)
-#define ADAPTER_STATUS_PIC_QUIESCENT BIT(5)
-#define ADAPTER_STATUS_RMAC_REMOTE_FAULT BIT(6)
-#define ADAPTER_STATUS_RMAC_LOCAL_FAULT BIT(7)
+#define ADAPTER_STATUS_TDMA_READY s2BIT(0)
+#define ADAPTER_STATUS_RDMA_READY s2BIT(1)
+#define ADAPTER_STATUS_PFC_READY s2BIT(2)
+#define ADAPTER_STATUS_TMAC_BUF_EMPTY s2BIT(3)
+#define ADAPTER_STATUS_PIC_QUIESCENT s2BIT(5)
+#define ADAPTER_STATUS_RMAC_REMOTE_FAULT s2BIT(6)
+#define ADAPTER_STATUS_RMAC_LOCAL_FAULT s2BIT(7)
#define ADAPTER_STATUS_RMAC_PCC_IDLE vBIT(0xFF,8,8)
#define ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE vBIT(0x0F,8,8)
#define ADAPTER_STATUS_RC_PRC_QUIESCENT vBIT(0xFF,16,8)
-#define ADAPTER_STATUS_MC_DRAM_READY BIT(24)
-#define ADAPTER_STATUS_MC_QUEUES_READY BIT(25)
-#define ADAPTER_STATUS_M_PLL_LOCK BIT(30)
-#define ADAPTER_STATUS_P_PLL_LOCK BIT(31)
+#define ADAPTER_STATUS_MC_DRAM_READY s2BIT(24)
+#define ADAPTER_STATUS_MC_QUEUES_READY s2BIT(25)
+#define ADAPTER_STATUS_M_PLL_LOCK s2BIT(30)
+#define ADAPTER_STATUS_P_PLL_LOCK s2BIT(31)
u64 adapter_control;
-#define ADAPTER_CNTL_EN BIT(7)
-#define ADAPTER_EOI_TX_ON BIT(15)
-#define ADAPTER_LED_ON BIT(23)
+#define ADAPTER_CNTL_EN s2BIT(7)
+#define ADAPTER_EOI_TX_ON s2BIT(15)
+#define ADAPTER_LED_ON s2BIT(23)
#define ADAPTER_UDPI(val) vBIT(val,36,4)
-#define ADAPTER_WAIT_INT BIT(48)
-#define ADAPTER_ECC_EN BIT(55)
+#define ADAPTER_WAIT_INT s2BIT(48)
+#define ADAPTER_ECC_EN s2BIT(55)
u64 serr_source;
-#define SERR_SOURCE_PIC BIT(0)
-#define SERR_SOURCE_TXDMA BIT(1)
-#define SERR_SOURCE_RXDMA BIT(2)
-#define SERR_SOURCE_MAC BIT(3)
-#define SERR_SOURCE_MC BIT(4)
-#define SERR_SOURCE_XGXS BIT(5)
+#define SERR_SOURCE_PIC s2BIT(0)
+#define SERR_SOURCE_TXDMA s2BIT(1)
+#define SERR_SOURCE_RXDMA s2BIT(2)
+#define SERR_SOURCE_MAC s2BIT(3)
+#define SERR_SOURCE_MC s2BIT(4)
+#define SERR_SOURCE_XGXS s2BIT(5)
#define SERR_SOURCE_ANY (SERR_SOURCE_PIC | \
SERR_SOURCE_TXDMA | \
SERR_SOURCE_RXDMA | \
@@ -101,41 +101,41 @@ struct XENA_dev_config {
#define PCI_MODE_PCIX_M2_66 0x5
#define PCI_MODE_PCIX_M2_100 0x6
#define PCI_MODE_PCIX_M2_133 0x7
-#define PCI_MODE_UNSUPPORTED BIT(0)
-#define PCI_MODE_32_BITS BIT(8)
-#define PCI_MODE_UNKNOWN_MODE BIT(9)
+#define PCI_MODE_UNSUPPORTED s2BIT(0)
+#define PCI_MODE_32_BITS s2BIT(8)
+#define PCI_MODE_UNKNOWN_MODE s2BIT(9)
u8 unused_0[0x800 - 0x128];
/* PCI-X Controller registers */
u64 pic_int_status;
u64 pic_int_mask;
-#define PIC_INT_TX BIT(0)
-#define PIC_INT_FLSH BIT(1)
-#define PIC_INT_MDIO BIT(2)
-#define PIC_INT_IIC BIT(3)
-#define PIC_INT_GPIO BIT(4)
-#define PIC_INT_RX BIT(32)
+#define PIC_INT_TX s2BIT(0)
+#define PIC_INT_FLSH s2BIT(1)
+#define PIC_INT_MDIO s2BIT(2)
+#define PIC_INT_IIC s2BIT(3)
+#define PIC_INT_GPIO s2BIT(4)
+#define PIC_INT_RX s2BIT(32)
u64 txpic_int_reg;
u64 txpic_int_mask;
-#define PCIX_INT_REG_ECC_SG_ERR BIT(0)
-#define PCIX_INT_REG_ECC_DB_ERR BIT(1)
-#define PCIX_INT_REG_FLASHR_R_FSM_ERR BIT(8)
-#define PCIX_INT_REG_FLASHR_W_FSM_ERR BIT(9)
-#define PCIX_INT_REG_INI_TX_FSM_SERR BIT(10)
-#define PCIX_INT_REG_INI_TXO_FSM_ERR BIT(11)
-#define PCIX_INT_REG_TRT_FSM_SERR BIT(13)
-#define PCIX_INT_REG_SRT_FSM_SERR BIT(14)
-#define PCIX_INT_REG_PIFR_FSM_SERR BIT(15)
-#define PCIX_INT_REG_WRC_TX_SEND_FSM_SERR BIT(21)
-#define PCIX_INT_REG_RRC_TX_REQ_FSM_SERR BIT(23)
-#define PCIX_INT_REG_INI_RX_FSM_SERR BIT(48)
-#define PCIX_INT_REG_RA_RX_FSM_SERR BIT(50)
+#define PCIX_INT_REG_ECC_SG_ERR s2BIT(0)
+#define PCIX_INT_REG_ECC_DB_ERR s2BIT(1)
+#define PCIX_INT_REG_FLASHR_R_FSM_ERR s2BIT(8)
+#define PCIX_INT_REG_FLASHR_W_FSM_ERR s2BIT(9)
+#define PCIX_INT_REG_INI_TX_FSM_SERR s2BIT(10)
+#define PCIX_INT_REG_INI_TXO_FSM_ERR s2BIT(11)
+#define PCIX_INT_REG_TRT_FSM_SERR s2BIT(13)
+#define PCIX_INT_REG_SRT_FSM_SERR s2BIT(14)
+#define PCIX_INT_REG_PIFR_FSM_SERR s2BIT(15)
+#define PCIX_INT_REG_WRC_TX_SEND_FSM_SERR s2BIT(21)
+#define PCIX_INT_REG_RRC_TX_REQ_FSM_SERR s2BIT(23)
+#define PCIX_INT_REG_INI_RX_FSM_SERR s2BIT(48)
+#define PCIX_INT_REG_RA_RX_FSM_SERR s2BIT(50)
/*
-#define PCIX_INT_REG_WRC_RX_SEND_FSM_SERR BIT(52)
-#define PCIX_INT_REG_RRC_RX_REQ_FSM_SERR BIT(54)
-#define PCIX_INT_REG_RRC_RX_SPLIT_FSM_SERR BIT(58)
+#define PCIX_INT_REG_WRC_RX_SEND_FSM_SERR s2BIT(52)
+#define PCIX_INT_REG_RRC_RX_REQ_FSM_SERR s2BIT(54)
+#define PCIX_INT_REG_RRC_RX_SPLIT_FSM_SERR s2BIT(58)
*/
u64 txpic_alarms;
u64 rxpic_int_reg;
@@ -144,92 +144,92 @@ struct XENA_dev_config {
u64 flsh_int_reg;
u64 flsh_int_mask;
-#define PIC_FLSH_INT_REG_CYCLE_FSM_ERR BIT(63)
-#define PIC_FLSH_INT_REG_ERR BIT(62)
+#define PIC_FLSH_INT_REG_CYCLE_FSM_ERR s2BIT(63)
+#define PIC_FLSH_INT_REG_ERR s2BIT(62)
u64 flash_alarms;
u64 mdio_int_reg;
u64 mdio_int_mask;
-#define MDIO_INT_REG_MDIO_BUS_ERR BIT(0)
-#define MDIO_INT_REG_DTX_BUS_ERR BIT(8)
-#define MDIO_INT_REG_LASI BIT(39)
+#define MDIO_INT_REG_MDIO_BUS_ERR s2BIT(0)
+#define MDIO_INT_REG_DTX_BUS_ERR s2BIT(8)
+#define MDIO_INT_REG_LASI s2BIT(39)
u64 mdio_alarms;
u64 iic_int_reg;
u64 iic_int_mask;
-#define IIC_INT_REG_BUS_FSM_ERR BIT(4)
-#define IIC_INT_REG_BIT_FSM_ERR BIT(5)
-#define IIC_INT_REG_CYCLE_FSM_ERR BIT(6)
-#define IIC_INT_REG_REQ_FSM_ERR BIT(7)
-#define IIC_INT_REG_ACK_ERR BIT(8)
+#define IIC_INT_REG_BUS_FSM_ERR s2BIT(4)
+#define IIC_INT_REG_BIT_FSM_ERR s2BIT(5)
+#define IIC_INT_REG_CYCLE_FSM_ERR s2BIT(6)
+#define IIC_INT_REG_REQ_FSM_ERR s2BIT(7)
+#define IIC_INT_REG_ACK_ERR s2BIT(8)
u64 iic_alarms;
u8 unused4[0x08];
u64 gpio_int_reg;
-#define GPIO_INT_REG_DP_ERR_INT BIT(0)
-#define GPIO_INT_REG_LINK_DOWN BIT(1)
-#define GPIO_INT_REG_LINK_UP BIT(2)
+#define GPIO_INT_REG_DP_ERR_INT s2BIT(0)
+#define GPIO_INT_REG_LINK_DOWN s2BIT(1)
+#define GPIO_INT_REG_LINK_UP s2BIT(2)
u64 gpio_int_mask;
-#define GPIO_INT_MASK_LINK_DOWN BIT(1)
-#define GPIO_INT_MASK_LINK_UP BIT(2)
+#define GPIO_INT_MASK_LINK_DOWN s2BIT(1)
+#define GPIO_INT_MASK_LINK_UP s2BIT(2)
u64 gpio_alarms;
u8 unused5[0x38];
u64 tx_traffic_int;
-#define TX_TRAFFIC_INT_n(n) BIT(n)
+#define TX_TRAFFIC_INT_n(n) s2BIT(n)
u64 tx_traffic_mask;
u64 rx_traffic_int;
-#define RX_TRAFFIC_INT_n(n) BIT(n)
+#define RX_TRAFFIC_INT_n(n) s2BIT(n)
u64 rx_traffic_mask;
/* PIC Control registers */
u64 pic_control;
-#define PIC_CNTL_RX_ALARM_MAP_1 BIT(0)
+#define PIC_CNTL_RX_ALARM_MAP_1 s2BIT(0)
#define PIC_CNTL_SHARED_SPLITS(n) vBIT(n,11,5)
u64 swapper_ctrl;
-#define SWAPPER_CTRL_PIF_R_FE BIT(0)
-#define SWAPPER_CTRL_PIF_R_SE BIT(1)
-#define SWAPPER_CTRL_PIF_W_FE BIT(8)
-#define SWAPPER_CTRL_PIF_W_SE BIT(9)
-#define SWAPPER_CTRL_TXP_FE BIT(16)
-#define SWAPPER_CTRL_TXP_SE BIT(17)
-#define SWAPPER_CTRL_TXD_R_FE BIT(18)
-#define SWAPPER_CTRL_TXD_R_SE BIT(19)
-#define SWAPPER_CTRL_TXD_W_FE BIT(20)
-#define SWAPPER_CTRL_TXD_W_SE BIT(21)
-#define SWAPPER_CTRL_TXF_R_FE BIT(22)
-#define SWAPPER_CTRL_TXF_R_SE BIT(23)
-#define SWAPPER_CTRL_RXD_R_FE BIT(32)
-#define SWAPPER_CTRL_RXD_R_SE BIT(33)
-#define SWAPPER_CTRL_RXD_W_FE BIT(34)
-#define SWAPPER_CTRL_RXD_W_SE BIT(35)
-#define SWAPPER_CTRL_RXF_W_FE BIT(36)
-#define SWAPPER_CTRL_RXF_W_SE BIT(37)
-#define SWAPPER_CTRL_XMSI_FE BIT(40)
-#define SWAPPER_CTRL_XMSI_SE BIT(41)
-#define SWAPPER_CTRL_STATS_FE BIT(48)
-#define SWAPPER_CTRL_STATS_SE BIT(49)
+#define SWAPPER_CTRL_PIF_R_FE s2BIT(0)
+#define SWAPPER_CTRL_PIF_R_SE s2BIT(1)
+#define SWAPPER_CTRL_PIF_W_FE s2BIT(8)
+#define SWAPPER_CTRL_PIF_W_SE s2BIT(9)
+#define SWAPPER_CTRL_TXP_FE s2BIT(16)
+#define SWAPPER_CTRL_TXP_SE s2BIT(17)
+#define SWAPPER_CTRL_TXD_R_FE s2BIT(18)
+#define SWAPPER_CTRL_TXD_R_SE s2BIT(19)
+#define SWAPPER_CTRL_TXD_W_FE s2BIT(20)
+#define SWAPPER_CTRL_TXD_W_SE s2BIT(21)
+#define SWAPPER_CTRL_TXF_R_FE s2BIT(22)
+#define SWAPPER_CTRL_TXF_R_SE s2BIT(23)
+#define SWAPPER_CTRL_RXD_R_FE s2BIT(32)
+#define SWAPPER_CTRL_RXD_R_SE s2BIT(33)
+#define SWAPPER_CTRL_RXD_W_FE s2BIT(34)
+#define SWAPPER_CTRL_RXD_W_SE s2BIT(35)
+#define SWAPPER_CTRL_RXF_W_FE s2BIT(36)
+#define SWAPPER_CTRL_RXF_W_SE s2BIT(37)
+#define SWAPPER_CTRL_XMSI_FE s2BIT(40)
+#define SWAPPER_CTRL_XMSI_SE s2BIT(41)
+#define SWAPPER_CTRL_STATS_FE s2BIT(48)
+#define SWAPPER_CTRL_STATS_SE s2BIT(49)
u64 pif_rd_swapper_fb;
#define IF_RD_SWAPPER_FB 0x0123456789ABCDEF
u64 scheduled_int_ctrl;
-#define SCHED_INT_CTRL_TIMER_EN BIT(0)
-#define SCHED_INT_CTRL_ONE_SHOT BIT(1)
+#define SCHED_INT_CTRL_TIMER_EN s2BIT(0)
+#define SCHED_INT_CTRL_ONE_SHOT s2BIT(1)
#define SCHED_INT_CTRL_INT2MSI(val) vBIT(val,10,6)
#define SCHED_INT_PERIOD TBD
u64 txreqtimeout;
#define TXREQTO_VAL(val) vBIT(val,0,32)
-#define TXREQTO_EN BIT(63)
+#define TXREQTO_EN s2BIT(63)
u64 statsreqtimeout;
#define STATREQTO_VAL(n) TBD
-#define STATREQTO_EN BIT(63)
+#define STATREQTO_EN s2BIT(63)
u64 read_retry_delay;
u64 read_retry_acceleration;
@@ -255,10 +255,10 @@ struct XENA_dev_config {
/* Automated statistics collection */
u64 stat_cfg;
-#define STAT_CFG_STAT_EN BIT(0)
-#define STAT_CFG_ONE_SHOT_EN BIT(1)
-#define STAT_CFG_STAT_NS_EN BIT(8)
-#define STAT_CFG_STAT_RO BIT(9)
+#define STAT_CFG_STAT_EN s2BIT(0)
+#define STAT_CFG_ONE_SHOT_EN s2BIT(1)
+#define STAT_CFG_STAT_NS_EN s2BIT(8)
+#define STAT_CFG_STAT_RO s2BIT(9)
#define STAT_TRSF_PER(n) TBD
#define PER_SEC 0x208d5
#define SET_UPDT_PERIOD(n) vBIT((PER_SEC*n),32,32)
@@ -290,18 +290,18 @@ struct XENA_dev_config {
#define I2C_CONTROL_DEV_ID(id) vBIT(id,1,3)
#define I2C_CONTROL_ADDR(addr) vBIT(addr,5,11)
#define I2C_CONTROL_BYTE_CNT(cnt) vBIT(cnt,22,2)
-#define I2C_CONTROL_READ BIT(24)
-#define I2C_CONTROL_NACK BIT(25)
+#define I2C_CONTROL_READ s2BIT(24)
+#define I2C_CONTROL_NACK s2BIT(25)
#define I2C_CONTROL_CNTL_START vBIT(0xE,28,4)
#define I2C_CONTROL_CNTL_END(val) (val & vBIT(0x1,28,4))
#define I2C_CONTROL_GET_DATA(val) (u32)(val & 0xFFFFFFFF)
#define I2C_CONTROL_SET_DATA(val) vBIT(val,32,32)
u64 gpio_control;
-#define GPIO_CTRL_GPIO_0 BIT(8)
+#define GPIO_CTRL_GPIO_0 s2BIT(8)
u64 misc_control;
-#define FAULT_BEHAVIOUR BIT(0)
-#define EXT_REQ_EN BIT(1)
+#define FAULT_BEHAVIOUR s2BIT(0)
+#define EXT_REQ_EN s2BIT(1)
#define MISC_LINK_STABILITY_PRD(val) vBIT(val,29,3)
u8 unused7_1[0x230 - 0x208];
@@ -317,29 +317,29 @@ struct XENA_dev_config {
/* TxDMA registers */
u64 txdma_int_status;
u64 txdma_int_mask;
-#define TXDMA_PFC_INT BIT(0)
-#define TXDMA_TDA_INT BIT(1)
-#define TXDMA_PCC_INT BIT(2)
-#define TXDMA_TTI_INT BIT(3)
-#define TXDMA_LSO_INT BIT(4)
-#define TXDMA_TPA_INT BIT(5)
-#define TXDMA_SM_INT BIT(6)
+#define TXDMA_PFC_INT s2BIT(0)
+#define TXDMA_TDA_INT s2BIT(1)
+#define TXDMA_PCC_INT s2BIT(2)
+#define TXDMA_TTI_INT s2BIT(3)
+#define TXDMA_LSO_INT s2BIT(4)
+#define TXDMA_TPA_INT s2BIT(5)
+#define TXDMA_SM_INT s2BIT(6)
u64 pfc_err_reg;
-#define PFC_ECC_SG_ERR BIT(7)
-#define PFC_ECC_DB_ERR BIT(15)
-#define PFC_SM_ERR_ALARM BIT(23)
-#define PFC_MISC_0_ERR BIT(31)
-#define PFC_MISC_1_ERR BIT(32)
-#define PFC_PCIX_ERR BIT(39)
+#define PFC_ECC_SG_ERR s2BIT(7)
+#define PFC_ECC_DB_ERR s2BIT(15)
+#define PFC_SM_ERR_ALARM s2BIT(23)
+#define PFC_MISC_0_ERR s2BIT(31)
+#define PFC_MISC_1_ERR s2BIT(32)
+#define PFC_PCIX_ERR s2BIT(39)
u64 pfc_err_mask;
u64 pfc_err_alarm;
u64 tda_err_reg;
#define TDA_Fn_ECC_SG_ERR vBIT(0xff,0,8)
#define TDA_Fn_ECC_DB_ERR vBIT(0xff,8,8)
-#define TDA_SM0_ERR_ALARM BIT(22)
-#define TDA_SM1_ERR_ALARM BIT(23)
-#define TDA_PCIX_ERR BIT(39)
+#define TDA_SM0_ERR_ALARM s2BIT(22)
+#define TDA_SM1_ERR_ALARM s2BIT(23)
+#define TDA_PCIX_ERR s2BIT(39)
u64 tda_err_mask;
u64 tda_err_alarm;
@@ -351,40 +351,40 @@ struct XENA_dev_config {
#define PCC_SM_ERR_ALARM vBIT(0xff,32,8)
#define PCC_WR_ERR_ALARM vBIT(0xff,40,8)
#define PCC_N_SERR vBIT(0xff,48,8)
-#define PCC_6_COF_OV_ERR BIT(56)
-#define PCC_7_COF_OV_ERR BIT(57)
-#define PCC_6_LSO_OV_ERR BIT(58)
-#define PCC_7_LSO_OV_ERR BIT(59)
+#define PCC_6_COF_OV_ERR s2BIT(56)
+#define PCC_7_COF_OV_ERR s2BIT(57)
+#define PCC_6_LSO_OV_ERR s2BIT(58)
+#define PCC_7_LSO_OV_ERR s2BIT(59)
#define PCC_ENABLE_FOUR vBIT(0x0F,0,8)
u64 pcc_err_mask;
u64 pcc_err_alarm;
u64 tti_err_reg;
-#define TTI_ECC_SG_ERR BIT(7)
-#define TTI_ECC_DB_ERR BIT(15)
-#define TTI_SM_ERR_ALARM BIT(23)
+#define TTI_ECC_SG_ERR s2BIT(7)
+#define TTI_ECC_DB_ERR s2BIT(15)
+#define TTI_SM_ERR_ALARM s2BIT(23)
u64 tti_err_mask;
u64 tti_err_alarm;
u64 lso_err_reg;
-#define LSO6_SEND_OFLOW BIT(12)
-#define LSO7_SEND_OFLOW BIT(13)
-#define LSO6_ABORT BIT(14)
-#define LSO7_ABORT BIT(15)
-#define LSO6_SM_ERR_ALARM BIT(22)
-#define LSO7_SM_ERR_ALARM BIT(23)
+#define LSO6_SEND_OFLOW s2BIT(12)
+#define LSO7_SEND_OFLOW s2BIT(13)
+#define LSO6_ABORT s2BIT(14)
+#define LSO7_ABORT s2BIT(15)
+#define LSO6_SM_ERR_ALARM s2BIT(22)
+#define LSO7_SM_ERR_ALARM s2BIT(23)
u64 lso_err_mask;
u64 lso_err_alarm;
u64 tpa_err_reg;
-#define TPA_TX_FRM_DROP BIT(7)
-#define TPA_SM_ERR_ALARM BIT(23)
+#define TPA_TX_FRM_DROP s2BIT(7)
+#define TPA_SM_ERR_ALARM s2BIT(23)
u64 tpa_err_mask;
u64 tpa_err_alarm;
u64 sm_err_reg;
-#define SM_SM_ERR_ALARM BIT(15)
+#define SM_SM_ERR_ALARM s2BIT(15)
u64 sm_err_mask;
u64 sm_err_alarm;
@@ -397,7 +397,7 @@ struct XENA_dev_config {
#define X_MAX_FIFOS 8
#define X_FIFO_MAX_LEN 0x1FFF /*8191 */
u64 tx_fifo_partition_0;
-#define TX_FIFO_PARTITION_EN BIT(0)
+#define TX_FIFO_PARTITION_EN s2BIT(0)
#define TX_FIFO_PARTITION_0_PRI(val) vBIT(val,5,3)
#define TX_FIFO_PARTITION_0_LEN(val) vBIT(val,19,13)
#define TX_FIFO_PARTITION_1_PRI(val) vBIT(val,37,3)
@@ -437,16 +437,16 @@ struct XENA_dev_config {
u64 tx_w_round_robin_4;
u64 tti_command_mem;
-#define TTI_CMD_MEM_WE BIT(7)
-#define TTI_CMD_MEM_STROBE_NEW_CMD BIT(15)
-#define TTI_CMD_MEM_STROBE_BEING_EXECUTED BIT(15)
+#define TTI_CMD_MEM_WE s2BIT(7)
+#define TTI_CMD_MEM_STROBE_NEW_CMD s2BIT(15)
+#define TTI_CMD_MEM_STROBE_BEING_EXECUTED s2BIT(15)
#define TTI_CMD_MEM_OFFSET(n) vBIT(n,26,6)
u64 tti_data1_mem;
#define TTI_DATA1_MEM_TX_TIMER_VAL(n) vBIT(n,6,26)
#define TTI_DATA1_MEM_TX_TIMER_AC_CI(n) vBIT(n,38,2)
-#define TTI_DATA1_MEM_TX_TIMER_AC_EN BIT(38)
-#define TTI_DATA1_MEM_TX_TIMER_CI_EN BIT(39)
+#define TTI_DATA1_MEM_TX_TIMER_AC_EN s2BIT(38)
+#define TTI_DATA1_MEM_TX_TIMER_CI_EN s2BIT(39)
#define TTI_DATA1_MEM_TX_URNG_A(n) vBIT(n,41,7)
#define TTI_DATA1_MEM_TX_URNG_B(n) vBIT(n,49,7)
#define TTI_DATA1_MEM_TX_URNG_C(n) vBIT(n,57,7)
@@ -459,11 +459,11 @@ struct XENA_dev_config {
/* Tx Protocol assist */
u64 tx_pa_cfg;
-#define TX_PA_CFG_IGNORE_FRM_ERR BIT(1)
-#define TX_PA_CFG_IGNORE_SNAP_OUI BIT(2)
-#define TX_PA_CFG_IGNORE_LLC_CTRL BIT(3)
-#define TX_PA_CFG_IGNORE_L2_ERR BIT(6)
-#define RX_PA_CFG_STRIP_VLAN_TAG BIT(15)
+#define TX_PA_CFG_IGNORE_FRM_ERR s2BIT(1)
+#define TX_PA_CFG_IGNORE_SNAP_OUI s2BIT(2)
+#define TX_PA_CFG_IGNORE_LLC_CTRL s2BIT(3)
+#define TX_PA_CFG_IGNORE_L2_ERR s2BIT(6)
+#define RX_PA_CFG_STRIP_VLAN_TAG s2BIT(15)
/* Recent add, used only debug purposes. */
u64 pcc_enable;
@@ -477,31 +477,31 @@ struct XENA_dev_config {
/* RxDMA Registers */
u64 rxdma_int_status;
u64 rxdma_int_mask;
-#define RXDMA_INT_RC_INT_M BIT(0)
-#define RXDMA_INT_RPA_INT_M BIT(1)
-#define RXDMA_INT_RDA_INT_M BIT(2)
-#define RXDMA_INT_RTI_INT_M BIT(3)
+#define RXDMA_INT_RC_INT_M s2BIT(0)
+#define RXDMA_INT_RPA_INT_M s2BIT(1)
+#define RXDMA_INT_RDA_INT_M s2BIT(2)
+#define RXDMA_INT_RTI_INT_M s2BIT(3)
u64 rda_err_reg;
#define RDA_RXDn_ECC_SG_ERR vBIT(0xFF,0,8)
#define RDA_RXDn_ECC_DB_ERR vBIT(0xFF,8,8)
-#define RDA_FRM_ECC_SG_ERR BIT(23)
-#define RDA_FRM_ECC_DB_N_AERR BIT(31)
-#define RDA_SM1_ERR_ALARM BIT(38)
-#define RDA_SM0_ERR_ALARM BIT(39)
-#define RDA_MISC_ERR BIT(47)
-#define RDA_PCIX_ERR BIT(55)
-#define RDA_RXD_ECC_DB_SERR BIT(63)
+#define RDA_FRM_ECC_SG_ERR s2BIT(23)
+#define RDA_FRM_ECC_DB_N_AERR s2BIT(31)
+#define RDA_SM1_ERR_ALARM s2BIT(38)
+#define RDA_SM0_ERR_ALARM s2BIT(39)
+#define RDA_MISC_ERR s2BIT(47)
+#define RDA_PCIX_ERR s2BIT(55)
+#define RDA_RXD_ECC_DB_SERR s2BIT(63)
u64 rda_err_mask;
u64 rda_err_alarm;
u64 rc_err_reg;
#define RC_PRCn_ECC_SG_ERR vBIT(0xFF,0,8)
#define RC_PRCn_ECC_DB_ERR vBIT(0xFF,8,8)
-#define RC_FTC_ECC_SG_ERR BIT(23)
-#define RC_FTC_ECC_DB_ERR BIT(31)
+#define RC_FTC_ECC_SG_ERR s2BIT(23)
+#define RC_FTC_ECC_DB_ERR s2BIT(31)
#define RC_PRCn_SM_ERR_ALARM vBIT(0xFF,32,8)
-#define RC_FTC_SM_ERR_ALARM BIT(47)
+#define RC_FTC_SM_ERR_ALARM s2BIT(47)
#define RC_RDA_FAIL_WR_Rn vBIT(0xFF,48,8)
u64 rc_err_mask;
u64 rc_err_alarm;
@@ -517,18 +517,18 @@ struct XENA_dev_config {
u64 prc_pcix_err_alarm;
u64 rpa_err_reg;
-#define RPA_ECC_SG_ERR BIT(7)
-#define RPA_ECC_DB_ERR BIT(15)
-#define RPA_FLUSH_REQUEST BIT(22)
-#define RPA_SM_ERR_ALARM BIT(23)
-#define RPA_CREDIT_ERR BIT(31)
+#define RPA_ECC_SG_ERR s2BIT(7)
+#define RPA_ECC_DB_ERR s2BIT(15)
+#define RPA_FLUSH_REQUEST s2BIT(22)
+#define RPA_SM_ERR_ALARM s2BIT(23)
+#define RPA_CREDIT_ERR s2BIT(31)
u64 rpa_err_mask;
u64 rpa_err_alarm;
u64 rti_err_reg;
-#define RTI_ECC_SG_ERR BIT(7)
-#define RTI_ECC_DB_ERR BIT(15)
-#define RTI_SM_ERR_ALARM BIT(23)
+#define RTI_ECC_SG_ERR s2BIT(7)
+#define RTI_ECC_DB_ERR s2BIT(15)
+#define RTI_SM_ERR_ALARM s2BIT(23)
u64 rti_err_mask;
u64 rti_err_alarm;
@@ -568,49 +568,49 @@ struct XENA_dev_config {
#endif
u64 prc_rxd0_n[RX_MAX_RINGS];
u64 prc_ctrl_n[RX_MAX_RINGS];
-#define PRC_CTRL_RC_ENABLED BIT(7)
-#define PRC_CTRL_RING_MODE (BIT(14)|BIT(15))
+#define PRC_CTRL_RC_ENABLED s2BIT(7)
+#define PRC_CTRL_RING_MODE (s2BIT(14)|s2BIT(15))
#define PRC_CTRL_RING_MODE_1 vBIT(0,14,2)
#define PRC_CTRL_RING_MODE_3 vBIT(1,14,2)
#define PRC_CTRL_RING_MODE_5 vBIT(2,14,2)
#define PRC_CTRL_RING_MODE_x vBIT(3,14,2)
-#define PRC_CTRL_NO_SNOOP (BIT(22)|BIT(23))
-#define PRC_CTRL_NO_SNOOP_DESC BIT(22)
-#define PRC_CTRL_NO_SNOOP_BUFF BIT(23)
-#define PRC_CTRL_BIMODAL_INTERRUPT BIT(37)
-#define PRC_CTRL_GROUP_READS BIT(38)
+#define PRC_CTRL_NO_SNOOP (s2BIT(22)|s2BIT(23))
+#define PRC_CTRL_NO_SNOOP_DESC s2BIT(22)
+#define PRC_CTRL_NO_SNOOP_BUFF s2BIT(23)
+#define PRC_CTRL_BIMODAL_INTERRUPT s2BIT(37)
+#define PRC_CTRL_GROUP_READS s2BIT(38)
#define PRC_CTRL_RXD_BACKOFF_INTERVAL(val) vBIT(val,40,24)
u64 prc_alarm_action;
-#define PRC_ALARM_ACTION_RR_R0_STOP BIT(3)
-#define PRC_ALARM_ACTION_RW_R0_STOP BIT(7)
-#define PRC_ALARM_ACTION_RR_R1_STOP BIT(11)
-#define PRC_ALARM_ACTION_RW_R1_STOP BIT(15)
-#define PRC_ALARM_ACTION_RR_R2_STOP BIT(19)
-#define PRC_ALARM_ACTION_RW_R2_STOP BIT(23)
-#define PRC_ALARM_ACTION_RR_R3_STOP BIT(27)
-#define PRC_ALARM_ACTION_RW_R3_STOP BIT(31)
-#define PRC_ALARM_ACTION_RR_R4_STOP BIT(35)
-#define PRC_ALARM_ACTION_RW_R4_STOP BIT(39)
-#define PRC_ALARM_ACTION_RR_R5_STOP BIT(43)
-#define PRC_ALARM_ACTION_RW_R5_STOP BIT(47)
-#define PRC_ALARM_ACTION_RR_R6_STOP BIT(51)
-#define PRC_ALARM_ACTION_RW_R6_STOP BIT(55)
-#define PRC_ALARM_ACTION_RR_R7_STOP BIT(59)
-#define PRC_ALARM_ACTION_RW_R7_STOP BIT(63)
+#define PRC_ALARM_ACTION_RR_R0_STOP s2BIT(3)
+#define PRC_ALARM_ACTION_RW_R0_STOP s2BIT(7)
+#define PRC_ALARM_ACTION_RR_R1_STOP s2BIT(11)
+#define PRC_ALARM_ACTION_RW_R1_STOP s2BIT(15)
+#define PRC_ALARM_ACTION_RR_R2_STOP s2BIT(19)
+#define PRC_ALARM_ACTION_RW_R2_STOP s2BIT(23)
+#define PRC_ALARM_ACTION_RR_R3_STOP s2BIT(27)
+#define PRC_ALARM_ACTION_RW_R3_STOP s2BIT(31)
+#define PRC_ALARM_ACTION_RR_R4_STOP s2BIT(35)
+#define PRC_ALARM_ACTION_RW_R4_STOP s2BIT(39)
+#define PRC_ALARM_ACTION_RR_R5_STOP s2BIT(43)
+#define PRC_ALARM_ACTION_RW_R5_STOP s2BIT(47)
+#define PRC_ALARM_ACTION_RR_R6_STOP s2BIT(51)
+#define PRC_ALARM_ACTION_RW_R6_STOP s2BIT(55)
+#define PRC_ALARM_ACTION_RR_R7_STOP s2BIT(59)
+#define PRC_ALARM_ACTION_RW_R7_STOP s2BIT(63)
/* Receive traffic interrupts */
u64 rti_command_mem;
-#define RTI_CMD_MEM_WE BIT(7)
-#define RTI_CMD_MEM_STROBE BIT(15)
-#define RTI_CMD_MEM_STROBE_NEW_CMD BIT(15)
-#define RTI_CMD_MEM_STROBE_CMD_BEING_EXECUTED BIT(15)
+#define RTI_CMD_MEM_WE s2BIT(7)
+#define RTI_CMD_MEM_STROBE s2BIT(15)
+#define RTI_CMD_MEM_STROBE_NEW_CMD s2BIT(15)
+#define RTI_CMD_MEM_STROBE_CMD_BEING_EXECUTED s2BIT(15)
#define RTI_CMD_MEM_OFFSET(n) vBIT(n,29,3)
u64 rti_data1_mem;
#define RTI_DATA1_MEM_RX_TIMER_VAL(n) vBIT(n,3,29)
-#define RTI_DATA1_MEM_RX_TIMER_AC_EN BIT(38)
-#define RTI_DATA1_MEM_RX_TIMER_CI_EN BIT(39)
+#define RTI_DATA1_MEM_RX_TIMER_AC_EN s2BIT(38)
+#define RTI_DATA1_MEM_RX_TIMER_CI_EN s2BIT(39)
#define RTI_DATA1_MEM_RX_URNG_A(n) vBIT(n,41,7)
#define RTI_DATA1_MEM_RX_URNG_B(n) vBIT(n,49,7)
#define RTI_DATA1_MEM_RX_URNG_C(n) vBIT(n,57,7)
@@ -622,10 +622,10 @@ struct XENA_dev_config {
#define RTI_DATA2_MEM_RX_UFC_D(n) vBIT(n,48,16)
u64 rx_pa_cfg;
-#define RX_PA_CFG_IGNORE_FRM_ERR BIT(1)
-#define RX_PA_CFG_IGNORE_SNAP_OUI BIT(2)
-#define RX_PA_CFG_IGNORE_LLC_CTRL BIT(3)
-#define RX_PA_CFG_IGNORE_L2_ERR BIT(6)
+#define RX_PA_CFG_IGNORE_FRM_ERR s2BIT(1)
+#define RX_PA_CFG_IGNORE_SNAP_OUI s2BIT(2)
+#define RX_PA_CFG_IGNORE_LLC_CTRL s2BIT(3)
+#define RX_PA_CFG_IGNORE_L2_ERR s2BIT(6)
u64 unused_11_1;
@@ -641,64 +641,64 @@ struct XENA_dev_config {
/* Media Access Controller Register */
u64 mac_int_status;
u64 mac_int_mask;
-#define MAC_INT_STATUS_TMAC_INT BIT(0)
-#define MAC_INT_STATUS_RMAC_INT BIT(1)
+#define MAC_INT_STATUS_TMAC_INT s2BIT(0)
+#define MAC_INT_STATUS_RMAC_INT s2BIT(1)
u64 mac_tmac_err_reg;
-#define TMAC_ECC_SG_ERR BIT(7)
-#define TMAC_ECC_DB_ERR BIT(15)
-#define TMAC_TX_BUF_OVRN BIT(23)
-#define TMAC_TX_CRI_ERR BIT(31)
-#define TMAC_TX_SM_ERR BIT(39)
-#define TMAC_DESC_ECC_SG_ERR BIT(47)
-#define TMAC_DESC_ECC_DB_ERR BIT(55)
+#define TMAC_ECC_SG_ERR s2BIT(7)
+#define TMAC_ECC_DB_ERR s2BIT(15)
+#define TMAC_TX_BUF_OVRN s2BIT(23)
+#define TMAC_TX_CRI_ERR s2BIT(31)
+#define TMAC_TX_SM_ERR s2BIT(39)
+#define TMAC_DESC_ECC_SG_ERR s2BIT(47)
+#define TMAC_DESC_ECC_DB_ERR s2BIT(55)
u64 mac_tmac_err_mask;
u64 mac_tmac_err_alarm;
u64 mac_rmac_err_reg;
-#define RMAC_RX_BUFF_OVRN BIT(0)
-#define RMAC_FRM_RCVD_INT BIT(1)
-#define RMAC_UNUSED_INT BIT(2)
-#define RMAC_RTS_PNUM_ECC_SG_ERR BIT(5)
-#define RMAC_RTS_DS_ECC_SG_ERR BIT(6)
-#define RMAC_RD_BUF_ECC_SG_ERR BIT(7)
-#define RMAC_RTH_MAP_ECC_SG_ERR BIT(8)
-#define RMAC_RTH_SPDM_ECC_SG_ERR BIT(9)
-#define RMAC_RTS_VID_ECC_SG_ERR BIT(10)
-#define RMAC_DA_SHADOW_ECC_SG_ERR BIT(11)
-#define RMAC_RTS_PNUM_ECC_DB_ERR BIT(13)
-#define RMAC_RTS_DS_ECC_DB_ERR BIT(14)
-#define RMAC_RD_BUF_ECC_DB_ERR BIT(15)
-#define RMAC_RTH_MAP_ECC_DB_ERR BIT(16)
-#define RMAC_RTH_SPDM_ECC_DB_ERR BIT(17)
-#define RMAC_RTS_VID_ECC_DB_ERR BIT(18)
-#define RMAC_DA_SHADOW_ECC_DB_ERR BIT(19)
-#define RMAC_LINK_STATE_CHANGE_INT BIT(31)
-#define RMAC_RX_SM_ERR BIT(39)
-#define RMAC_SINGLE_ECC_ERR (BIT(5) | BIT(6) | BIT(7) |\
- BIT(8) | BIT(9) | BIT(10)|\
- BIT(11))
-#define RMAC_DOUBLE_ECC_ERR (BIT(13) | BIT(14) | BIT(15) |\
- BIT(16) | BIT(17) | BIT(18)|\
- BIT(19))
+#define RMAC_RX_BUFF_OVRN s2BIT(0)
+#define RMAC_FRM_RCVD_INT s2BIT(1)
+#define RMAC_UNUSED_INT s2BIT(2)
+#define RMAC_RTS_PNUM_ECC_SG_ERR s2BIT(5)
+#define RMAC_RTS_DS_ECC_SG_ERR s2BIT(6)
+#define RMAC_RD_BUF_ECC_SG_ERR s2BIT(7)
+#define RMAC_RTH_MAP_ECC_SG_ERR s2BIT(8)
+#define RMAC_RTH_SPDM_ECC_SG_ERR s2BIT(9)
+#define RMAC_RTS_VID_ECC_SG_ERR s2BIT(10)
+#define RMAC_DA_SHADOW_ECC_SG_ERR s2BIT(11)
+#define RMAC_RTS_PNUM_ECC_DB_ERR s2BIT(13)
+#define RMAC_RTS_DS_ECC_DB_ERR s2BIT(14)
+#define RMAC_RD_BUF_ECC_DB_ERR s2BIT(15)
+#define RMAC_RTH_MAP_ECC_DB_ERR s2BIT(16)
+#define RMAC_RTH_SPDM_ECC_DB_ERR s2BIT(17)
+#define RMAC_RTS_VID_ECC_DB_ERR s2BIT(18)
+#define RMAC_DA_SHADOW_ECC_DB_ERR s2BIT(19)
+#define RMAC_LINK_STATE_CHANGE_INT s2BIT(31)
+#define RMAC_RX_SM_ERR s2BIT(39)
+#define RMAC_SINGLE_ECC_ERR (s2BIT(5) | s2BIT(6) | s2BIT(7) |\
+ s2BIT(8) | s2BIT(9) | s2BIT(10)|\
+ s2BIT(11))
+#define RMAC_DOUBLE_ECC_ERR (s2BIT(13) | s2BIT(14) | s2BIT(15) |\
+ s2BIT(16) | s2BIT(17) | s2BIT(18)|\
+ s2BIT(19))
u64 mac_rmac_err_mask;
u64 mac_rmac_err_alarm;
u8 unused14[0x100 - 0x40];
u64 mac_cfg;
-#define MAC_CFG_TMAC_ENABLE BIT(0)
-#define MAC_CFG_RMAC_ENABLE BIT(1)
-#define MAC_CFG_LAN_NOT_WAN BIT(2)
-#define MAC_CFG_TMAC_LOOPBACK BIT(3)
-#define MAC_CFG_TMAC_APPEND_PAD BIT(4)
-#define MAC_CFG_RMAC_STRIP_FCS BIT(5)
-#define MAC_CFG_RMAC_STRIP_PAD BIT(6)
-#define MAC_CFG_RMAC_PROM_ENABLE BIT(7)
-#define MAC_RMAC_DISCARD_PFRM BIT(8)
-#define MAC_RMAC_BCAST_ENABLE BIT(9)
-#define MAC_RMAC_ALL_ADDR_ENABLE BIT(10)
+#define MAC_CFG_TMAC_ENABLE s2BIT(0)
+#define MAC_CFG_RMAC_ENABLE s2BIT(1)
+#define MAC_CFG_LAN_NOT_WAN s2BIT(2)
+#define MAC_CFG_TMAC_LOOPBACK s2BIT(3)
+#define MAC_CFG_TMAC_APPEND_PAD s2BIT(4)
+#define MAC_CFG_RMAC_STRIP_FCS s2BIT(5)
+#define MAC_CFG_RMAC_STRIP_PAD s2BIT(6)
+#define MAC_CFG_RMAC_PROM_ENABLE s2BIT(7)
+#define MAC_RMAC_DISCARD_PFRM s2BIT(8)
+#define MAC_RMAC_BCAST_ENABLE s2BIT(9)
+#define MAC_RMAC_ALL_ADDR_ENABLE s2BIT(10)
#define MAC_RMAC_INVLD_IPG_THR(val) vBIT(val,16,8)
u64 tmac_avg_ipg;
@@ -710,14 +710,14 @@ struct XENA_dev_config {
#define RMAC_MAX_PYLD_LEN_JUMBO_DEF vBIT(9600,2,14)
u64 rmac_err_cfg;
-#define RMAC_ERR_FCS BIT(0)
-#define RMAC_ERR_FCS_ACCEPT BIT(1)
-#define RMAC_ERR_TOO_LONG BIT(1)
-#define RMAC_ERR_TOO_LONG_ACCEPT BIT(1)
-#define RMAC_ERR_RUNT BIT(2)
-#define RMAC_ERR_RUNT_ACCEPT BIT(2)
-#define RMAC_ERR_LEN_MISMATCH BIT(3)
-#define RMAC_ERR_LEN_MISMATCH_ACCEPT BIT(3)
+#define RMAC_ERR_FCS s2BIT(0)
+#define RMAC_ERR_FCS_ACCEPT s2BIT(1)
+#define RMAC_ERR_TOO_LONG s2BIT(1)
+#define RMAC_ERR_TOO_LONG_ACCEPT s2BIT(1)
+#define RMAC_ERR_RUNT s2BIT(2)
+#define RMAC_ERR_RUNT_ACCEPT s2BIT(2)
+#define RMAC_ERR_LEN_MISMATCH s2BIT(3)
+#define RMAC_ERR_LEN_MISMATCH_ACCEPT s2BIT(3)
u64 rmac_cfg_key;
#define RMAC_CFG_KEY(val) vBIT(val,0,16)
@@ -728,15 +728,15 @@ struct XENA_dev_config {
#define MAC_MC_ADDR_START_OFFSET 16
#define MAC_MC_ALL_MC_ADDR_OFFSET 63 /* enables all multicast pkts */
u64 rmac_addr_cmd_mem;
-#define RMAC_ADDR_CMD_MEM_WE BIT(7)
+#define RMAC_ADDR_CMD_MEM_WE s2BIT(7)
#define RMAC_ADDR_CMD_MEM_RD 0
-#define RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD BIT(15)
-#define RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING BIT(15)
+#define RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD s2BIT(15)
+#define RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING s2BIT(15)
#define RMAC_ADDR_CMD_MEM_OFFSET(n) vBIT(n,26,6)
u64 rmac_addr_data0_mem;
#define RMAC_ADDR_DATA0_MEM_ADDR(n) vBIT(n,0,48)
-#define RMAC_ADDR_DATA0_MEM_USER BIT(48)
+#define RMAC_ADDR_DATA0_MEM_USER s2BIT(48)
u64 rmac_addr_data1_mem;
#define RMAC_ADDR_DATA1_MEM_MASK(n) vBIT(n,0,48)
@@ -753,10 +753,10 @@ struct XENA_dev_config {
u64 tmac_ipg_cfg;
u64 rmac_pause_cfg;
-#define RMAC_PAUSE_GEN BIT(0)
-#define RMAC_PAUSE_GEN_ENABLE BIT(0)
-#define RMAC_PAUSE_RX BIT(1)
-#define RMAC_PAUSE_RX_ENABLE BIT(1)
+#define RMAC_PAUSE_GEN s2BIT(0)
+#define RMAC_PAUSE_GEN_ENABLE s2BIT(0)
+#define RMAC_PAUSE_RX s2BIT(1)
+#define RMAC_PAUSE_RX_ENABLE s2BIT(1)
#define RMAC_PAUSE_HG_PTIME_DEF vBIT(0xFFFF,16,16)
#define RMAC_PAUSE_HG_PTIME(val) vBIT(val,16,16)
@@ -787,29 +787,29 @@ struct XENA_dev_config {
#define MAX_DIX_MAP 4
u64 rts_dix_map_n[MAX_DIX_MAP];
#define RTS_DIX_MAP_ETYPE(val) vBIT(val,0,16)
-#define RTS_DIX_MAP_SCW(val) BIT(val,21)
+#define RTS_DIX_MAP_SCW(val) s2BIT(val,21)
u64 rts_q_alternates;
u64 rts_default_q;
u64 rts_ctrl;
-#define RTS_CTRL_IGNORE_SNAP_OUI BIT(2)
-#define RTS_CTRL_IGNORE_LLC_CTRL BIT(3)
+#define RTS_CTRL_IGNORE_SNAP_OUI s2BIT(2)
+#define RTS_CTRL_IGNORE_LLC_CTRL s2BIT(3)
u64 rts_pn_cam_ctrl;
-#define RTS_PN_CAM_CTRL_WE BIT(7)
-#define RTS_PN_CAM_CTRL_STROBE_NEW_CMD BIT(15)
-#define RTS_PN_CAM_CTRL_STROBE_BEING_EXECUTED BIT(15)
+#define RTS_PN_CAM_CTRL_WE s2BIT(7)
+#define RTS_PN_CAM_CTRL_STROBE_NEW_CMD s2BIT(15)
+#define RTS_PN_CAM_CTRL_STROBE_BEING_EXECUTED s2BIT(15)
#define RTS_PN_CAM_CTRL_OFFSET(n) vBIT(n,24,8)
u64 rts_pn_cam_data;
-#define RTS_PN_CAM_DATA_TCP_SELECT BIT(7)
+#define RTS_PN_CAM_DATA_TCP_SELECT s2BIT(7)
#define RTS_PN_CAM_DATA_PORT(val) vBIT(val,8,16)
#define RTS_PN_CAM_DATA_SCW(val) vBIT(val,24,8)
u64 rts_ds_mem_ctrl;
-#define RTS_DS_MEM_CTRL_WE BIT(7)
-#define RTS_DS_MEM_CTRL_STROBE_NEW_CMD BIT(15)
-#define RTS_DS_MEM_CTRL_STROBE_CMD_BEING_EXECUTED BIT(15)
+#define RTS_DS_MEM_CTRL_WE s2BIT(7)
+#define RTS_DS_MEM_CTRL_STROBE_NEW_CMD s2BIT(15)
+#define RTS_DS_MEM_CTRL_STROBE_CMD_BEING_EXECUTED s2BIT(15)
#define RTS_DS_MEM_CTRL_OFFSET(n) vBIT(n,26,6)
u64 rts_ds_mem_data;
#define RTS_DS_MEM_DATA(n) vBIT(n,0,8)
@@ -823,23 +823,23 @@ struct XENA_dev_config {
/* memory controller registers */
u64 mc_int_status;
-#define MC_INT_STATUS_MC_INT BIT(0)
+#define MC_INT_STATUS_MC_INT s2BIT(0)
u64 mc_int_mask;
-#define MC_INT_MASK_MC_INT BIT(0)
+#define MC_INT_MASK_MC_INT s2BIT(0)
u64 mc_err_reg;
-#define MC_ERR_REG_ECC_DB_ERR_L BIT(14)
-#define MC_ERR_REG_ECC_DB_ERR_U BIT(15)
-#define MC_ERR_REG_MIRI_ECC_DB_ERR_0 BIT(18)
-#define MC_ERR_REG_MIRI_ECC_DB_ERR_1 BIT(20)
-#define MC_ERR_REG_MIRI_CRI_ERR_0 BIT(22)
-#define MC_ERR_REG_MIRI_CRI_ERR_1 BIT(23)
-#define MC_ERR_REG_SM_ERR BIT(31)
-#define MC_ERR_REG_ECC_ALL_SNG (BIT(2) | BIT(3) | BIT(4) | BIT(5) |\
- BIT(17) | BIT(19))
-#define MC_ERR_REG_ECC_ALL_DBL (BIT(10) | BIT(11) | BIT(12) |\
- BIT(13) | BIT(18) | BIT(20))
-#define PLL_LOCK_N BIT(39)
+#define MC_ERR_REG_ECC_DB_ERR_L s2BIT(14)
+#define MC_ERR_REG_ECC_DB_ERR_U s2BIT(15)
+#define MC_ERR_REG_MIRI_ECC_DB_ERR_0 s2BIT(18)
+#define MC_ERR_REG_MIRI_ECC_DB_ERR_1 s2BIT(20)
+#define MC_ERR_REG_MIRI_CRI_ERR_0 s2BIT(22)
+#define MC_ERR_REG_MIRI_CRI_ERR_1 s2BIT(23)
+#define MC_ERR_REG_SM_ERR s2BIT(31)
+#define MC_ERR_REG_ECC_ALL_SNG (s2BIT(2) | s2BIT(3) | s2BIT(4) | s2BIT(5) |\
+ s2BIT(17) | s2BIT(19))
+#define MC_ERR_REG_ECC_ALL_DBL (s2BIT(10) | s2BIT(11) | s2BIT(12) |\
+ s2BIT(13) | s2BIT(18) | s2BIT(20))
+#define PLL_LOCK_N s2BIT(39)
u64 mc_err_mask;
u64 mc_err_alarm;
@@ -857,8 +857,8 @@ struct XENA_dev_config {
#define RX_QUEUE_CFG_Q7_SZ(n) vBIT(n,56,8)
u64 mc_rldram_mrs;
-#define MC_RLDRAM_QUEUE_SIZE_ENABLE BIT(39)
-#define MC_RLDRAM_MRS_ENABLE BIT(47)
+#define MC_RLDRAM_QUEUE_SIZE_ENABLE s2BIT(39)
+#define MC_RLDRAM_MRS_ENABLE s2BIT(47)
u64 mc_rldram_interleave;
@@ -871,11 +871,11 @@ struct XENA_dev_config {
u64 mc_rldram_ref_per;
u8 unused20[0x220 - 0x208];
u64 mc_rldram_test_ctrl;
-#define MC_RLDRAM_TEST_MODE BIT(47)
-#define MC_RLDRAM_TEST_WRITE BIT(7)
-#define MC_RLDRAM_TEST_GO BIT(15)
-#define MC_RLDRAM_TEST_DONE BIT(23)
-#define MC_RLDRAM_TEST_PASS BIT(31)
+#define MC_RLDRAM_TEST_MODE s2BIT(47)
+#define MC_RLDRAM_TEST_WRITE s2BIT(7)
+#define MC_RLDRAM_TEST_GO s2BIT(15)
+#define MC_RLDRAM_TEST_DONE s2BIT(23)
+#define MC_RLDRAM_TEST_PASS s2BIT(31)
u8 unused21[0x240 - 0x228];
u64 mc_rldram_test_add;
@@ -888,7 +888,7 @@ struct XENA_dev_config {
u8 unused24_1[0x360 - 0x308];
u64 mc_rldram_ctrl;
-#define MC_RLDRAM_ENABLE_ODT BIT(7)
+#define MC_RLDRAM_ENABLE_ODT s2BIT(7)
u8 unused24_2[0x640 - 0x368];
u64 mc_rldram_ref_per_herc;
@@ -906,24 +906,24 @@ struct XENA_dev_config {
/* XGXS control registers */
u64 xgxs_int_status;
-#define XGXS_INT_STATUS_TXGXS BIT(0)
-#define XGXS_INT_STATUS_RXGXS BIT(1)
+#define XGXS_INT_STATUS_TXGXS s2BIT(0)
+#define XGXS_INT_STATUS_RXGXS s2BIT(1)
u64 xgxs_int_mask;
-#define XGXS_INT_MASK_TXGXS BIT(0)
-#define XGXS_INT_MASK_RXGXS BIT(1)
+#define XGXS_INT_MASK_TXGXS s2BIT(0)
+#define XGXS_INT_MASK_RXGXS s2BIT(1)
u64 xgxs_txgxs_err_reg;
-#define TXGXS_ECC_SG_ERR BIT(7)
-#define TXGXS_ECC_DB_ERR BIT(15)
-#define TXGXS_ESTORE_UFLOW BIT(31)
-#define TXGXS_TX_SM_ERR BIT(39)
+#define TXGXS_ECC_SG_ERR s2BIT(7)
+#define TXGXS_ECC_DB_ERR s2BIT(15)
+#define TXGXS_ESTORE_UFLOW s2BIT(31)
+#define TXGXS_TX_SM_ERR s2BIT(39)
u64 xgxs_txgxs_err_mask;
u64 xgxs_txgxs_err_alarm;
u64 xgxs_rxgxs_err_reg;
-#define RXGXS_ESTORE_OFLOW BIT(7)
-#define RXGXS_RX_SM_ERR BIT(39)
+#define RXGXS_ESTORE_OFLOW s2BIT(7)
+#define RXGXS_RX_SM_ERR s2BIT(39)
u64 xgxs_rxgxs_err_mask;
u64 xgxs_rxgxs_err_alarm;
@@ -942,10 +942,10 @@ struct XENA_dev_config {
#define SPI_CONTROL_BYTECNT(cnt) vBIT(cnt,29,3)
#define SPI_CONTROL_CMD(cmd) vBIT(cmd,32,8)
#define SPI_CONTROL_ADDR(addr) vBIT(addr,40,24)
-#define SPI_CONTROL_SEL1 BIT(4)
-#define SPI_CONTROL_REQ BIT(7)
-#define SPI_CONTROL_NACK BIT(5)
-#define SPI_CONTROL_DONE BIT(6)
+#define SPI_CONTROL_SEL1 s2BIT(4)
+#define SPI_CONTROL_REQ s2BIT(7)
+#define SPI_CONTROL_NACK s2BIT(5)
+#define SPI_CONTROL_DONE s2BIT(6)
u64 spi_data;
#define SPI_DATA_WRITE(data,len) vBIT(data,0,len)
};
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 22e4054d4fcb..632666706247 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -84,7 +84,7 @@
#include "s2io.h"
#include "s2io-regs.h"
-#define DRV_VERSION "2.0.26.5"
+#define DRV_VERSION "2.0.26.6"
/* S2io Driver name & version. */
static char s2io_driver_name[] = "Neterion";
@@ -1716,7 +1716,7 @@ static int init_nic(struct s2io_nic *nic)
MISC_LINK_STABILITY_PRD(3);
writeq(val64, &bar0->misc_control);
val64 = readq(&bar0->pic_control2);
- val64 &= ~(BIT(13)|BIT(14)|BIT(15));
+ val64 &= ~(s2BIT(13)|s2BIT(14)|s2BIT(15));
writeq(val64, &bar0->pic_control2);
}
if (strstr(nic->product_name, "CX4")) {
@@ -2427,7 +2427,7 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
}
if ((rxdp->Control_1 & RXD_OWN_XENA) &&
((nic->rxd_mode == RXD_MODE_3B) &&
- (rxdp->Control_2 & BIT(0)))) {
+ (rxdp->Control_2 & s2BIT(0)))) {
mac_control->rings[ring_no].rx_curr_put_info.
offset = off;
goto end;
@@ -2540,7 +2540,7 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
rxdp->Control_2 |= SET_BUFFER2_SIZE_3
(dev->mtu + 4);
}
- rxdp->Control_2 |= BIT(0);
+ rxdp->Control_2 |= s2BIT(0);
}
rxdp->Host_Control = (unsigned long) (skb);
if (alloc_tab & ((1 << rxsync_frequency) - 1))
@@ -3377,7 +3377,7 @@ static void s2io_reset(struct s2io_nic * sp)
pci_write_config_dword(sp->pdev, 0x68, 0x7C);
/* Clearing PCI_STATUS error reflected here */
- writeq(BIT(62), &bar0->txpic_int_reg);
+ writeq(s2BIT(62), &bar0->txpic_int_reg);
}
/* Reset device statistics maintained by OS */
@@ -3575,7 +3575,7 @@ static int wait_for_msix_trans(struct s2io_nic *nic, int i)
do {
val64 = readq(&bar0->xmsi_access);
- if (!(val64 & BIT(15)))
+ if (!(val64 & s2BIT(15)))
break;
mdelay(1);
cnt++;
@@ -3597,7 +3597,7 @@ static void restore_xmsi_data(struct s2io_nic *nic)
for (i=0; i < MAX_REQUESTED_MSI_X; i++) {
writeq(nic->msix_info[i].addr, &bar0->xmsi_address);
writeq(nic->msix_info[i].data, &bar0->xmsi_data);
- val64 = (BIT(7) | BIT(15) | vBIT(i, 26, 6));
+ val64 = (s2BIT(7) | s2BIT(15) | vBIT(i, 26, 6));
writeq(val64, &bar0->xmsi_access);
if (wait_for_msix_trans(nic, i)) {
DBG_PRINT(ERR_DBG, "failed in %s\n", __FUNCTION__);
@@ -3614,7 +3614,7 @@ static void store_xmsi_data(struct s2io_nic *nic)
/* Store and display */
for (i=0; i < MAX_REQUESTED_MSI_X; i++) {
- val64 = (BIT(15) | vBIT(i, 26, 6));
+ val64 = (s2BIT(15) | vBIT(i, 26, 6));
writeq(val64, &bar0->xmsi_access);
if (wait_for_msix_trans(nic, i)) {
DBG_PRINT(ERR_DBG, "failed in %s\n", __FUNCTION__);
@@ -3775,6 +3775,40 @@ static int __devinit s2io_test_msi(struct s2io_nic *sp)
return err;
}
+
+static void remove_msix_isr(struct s2io_nic *sp)
+{
+ int i;
+ u16 msi_control;
+
+ for (i = 0; i < MAX_REQUESTED_MSI_X; i++) {
+ if (sp->s2io_entries[i].in_use ==
+ MSIX_REGISTERED_SUCCESS) {
+ int vector = sp->entries[i].vector;
+ void *arg = sp->s2io_entries[i].arg;
+ free_irq(vector, arg);
+ }
+ }
+
+ kfree(sp->entries);
+ kfree(sp->s2io_entries);
+ sp->entries = NULL;
+ sp->s2io_entries = NULL;
+
+ pci_read_config_word(sp->pdev, 0x42, &msi_control);
+ msi_control &= 0xFFFE; /* Disable MSI */
+ pci_write_config_word(sp->pdev, 0x42, msi_control);
+
+ pci_disable_msix(sp->pdev);
+}
+
+static void remove_inta_isr(struct s2io_nic *sp)
+{
+ struct net_device *dev = sp->dev;
+
+ free_irq(sp->pdev->irq, dev);
+}
+
/* ********************************************************* *
* Functions defined below concern the OS part of the driver *
* ********************************************************* */
@@ -3809,28 +3843,9 @@ static int s2io_open(struct net_device *dev)
int ret = s2io_enable_msi_x(sp);
if (!ret) {
- u16 msi_control;
-
ret = s2io_test_msi(sp);
-
/* rollback MSI-X, will re-enable during add_isr() */
- kfree(sp->entries);
- sp->mac_control.stats_info->sw_stat.mem_freed +=
- (MAX_REQUESTED_MSI_X *
- sizeof(struct msix_entry));
- kfree(sp->s2io_entries);
- sp->mac_control.stats_info->sw_stat.mem_freed +=
- (MAX_REQUESTED_MSI_X *
- sizeof(struct s2io_msix_entry));
- sp->entries = NULL;
- sp->s2io_entries = NULL;
-
- pci_read_config_word(sp->pdev, 0x42, &msi_control);
- msi_control &= 0xFFFE; /* Disable MSI */
- pci_write_config_word(sp->pdev, 0x42, msi_control);
-
- pci_disable_msix(sp->pdev);
-
+ remove_msix_isr(sp);
}
if (ret) {
@@ -4634,7 +4649,7 @@ static void s2io_updt_stats(struct s2io_nic *sp)
do {
udelay(100);
val64 = readq(&bar0->stat_cfg);
- if (!(val64 & BIT(0)))
+ if (!(val64 & s2BIT(0)))
break;
cnt++;
if (cnt == 5)
@@ -6719,15 +6734,22 @@ static int s2io_add_isr(struct s2io_nic * sp)
}
}
if (err) {
+ remove_msix_isr(sp);
DBG_PRINT(ERR_DBG,"%s:MSI-X-%d registration "
"failed\n", dev->name, i);
- DBG_PRINT(ERR_DBG, "Returned: %d\n", err);
- return -1;
+ DBG_PRINT(ERR_DBG, "%s: defaulting to INTA\n",
+ dev->name);
+ sp->config.intr_type = INTA;
+ break;
}
sp->s2io_entries[i].in_use = MSIX_REGISTERED_SUCCESS;
}
- printk("MSI-X-TX %d entries enabled\n",msix_tx_cnt);
- printk("MSI-X-RX %d entries enabled\n",msix_rx_cnt);
+ if (!err) {
+ printk(KERN_INFO "MSI-X-TX %d entries enabled\n",
+ msix_tx_cnt);
+ printk(KERN_INFO "MSI-X-RX %d entries enabled\n",
+ msix_rx_cnt);
+ }
}
if (sp->config.intr_type == INTA) {
err = request_irq((int) sp->pdev->irq, s2io_isr, IRQF_SHARED,
@@ -6742,40 +6764,10 @@ static int s2io_add_isr(struct s2io_nic * sp)
}
static void s2io_rem_isr(struct s2io_nic * sp)
{
- struct net_device *dev = sp->dev;
- struct swStat *stats = &sp->mac_control.stats_info->sw_stat;
-
- if (sp->config.intr_type == MSI_X) {
- int i;
- u16 msi_control;
-
- for (i=1; (sp->s2io_entries[i].in_use ==
- MSIX_REGISTERED_SUCCESS); i++) {
- int vector = sp->entries[i].vector;
- void *arg = sp->s2io_entries[i].arg;
-
- synchronize_irq(vector);
- free_irq(vector, arg);
- }
-
- kfree(sp->entries);
- stats->mem_freed +=
- (MAX_REQUESTED_MSI_X * sizeof(struct msix_entry));
- kfree(sp->s2io_entries);
- stats->mem_freed +=
- (MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry));
- sp->entries = NULL;
- sp->s2io_entries = NULL;
-
- pci_read_config_word(sp->pdev, 0x42, &msi_control);
- msi_control &= 0xFFFE; /* Disable MSI */
- pci_write_config_word(sp->pdev, 0x42, msi_control);
-
- pci_disable_msix(sp->pdev);
- } else {
- synchronize_irq(sp->pdev->irq);
- free_irq(sp->pdev->irq, dev);
- }
+ if (sp->config.intr_type == MSI_X)
+ remove_msix_isr(sp);
+ else
+ remove_inta_isr(sp);
}
static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index f6b45565304f..cc1797a071aa 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -14,7 +14,7 @@
#define _S2IO_H
#define TBD 0
-#define BIT(loc) (0x8000000000000000ULL >> (loc))
+#define s2BIT(loc) (0x8000000000000000ULL >> (loc))
#define vBIT(val, loc, sz) (((u64)val) << (64-loc-sz))
#define INV(d) ((d&0xff)<<24) | (((d>>8)&0xff)<<16) | (((d>>16)&0xff)<<8)| ((d>>24)&0xff)
@@ -473,42 +473,42 @@ struct TxFIFO_element {
u64 List_Control;
#define TX_FIFO_LAST_TXD_NUM( val) vBIT(val,0,8)
-#define TX_FIFO_FIRST_LIST BIT(14)
-#define TX_FIFO_LAST_LIST BIT(15)
+#define TX_FIFO_FIRST_LIST s2BIT(14)
+#define TX_FIFO_LAST_LIST s2BIT(15)
#define TX_FIFO_FIRSTNLAST_LIST vBIT(3,14,2)
-#define TX_FIFO_SPECIAL_FUNC BIT(23)
-#define TX_FIFO_DS_NO_SNOOP BIT(31)
-#define TX_FIFO_BUFF_NO_SNOOP BIT(30)
+#define TX_FIFO_SPECIAL_FUNC s2BIT(23)
+#define TX_FIFO_DS_NO_SNOOP s2BIT(31)
+#define TX_FIFO_BUFF_NO_SNOOP s2BIT(30)
};
/* Tx descriptor structure */
struct TxD {
u64 Control_1;
/* bit mask */
-#define TXD_LIST_OWN_XENA BIT(7)
-#define TXD_T_CODE (BIT(12)|BIT(13)|BIT(14)|BIT(15))
+#define TXD_LIST_OWN_XENA s2BIT(7)
+#define TXD_T_CODE (s2BIT(12)|s2BIT(13)|s2BIT(14)|s2BIT(15))
#define TXD_T_CODE_OK(val) (|(val & TXD_T_CODE))
#define GET_TXD_T_CODE(val) ((val & TXD_T_CODE)<<12)
-#define TXD_GATHER_CODE (BIT(22) | BIT(23))
-#define TXD_GATHER_CODE_FIRST BIT(22)
-#define TXD_GATHER_CODE_LAST BIT(23)
-#define TXD_TCP_LSO_EN BIT(30)
-#define TXD_UDP_COF_EN BIT(31)
-#define TXD_UFO_EN BIT(31) | BIT(30)
+#define TXD_GATHER_CODE (s2BIT(22) | s2BIT(23))
+#define TXD_GATHER_CODE_FIRST s2BIT(22)
+#define TXD_GATHER_CODE_LAST s2BIT(23)
+#define TXD_TCP_LSO_EN s2BIT(30)
+#define TXD_UDP_COF_EN s2BIT(31)
+#define TXD_UFO_EN s2BIT(31) | s2BIT(30)
#define TXD_TCP_LSO_MSS(val) vBIT(val,34,14)
#define TXD_UFO_MSS(val) vBIT(val,34,14)
#define TXD_BUFFER0_SIZE(val) vBIT(val,48,16)
u64 Control_2;
-#define TXD_TX_CKO_CONTROL (BIT(5)|BIT(6)|BIT(7))
-#define TXD_TX_CKO_IPV4_EN BIT(5)
-#define TXD_TX_CKO_TCP_EN BIT(6)
-#define TXD_TX_CKO_UDP_EN BIT(7)
-#define TXD_VLAN_ENABLE BIT(15)
+#define TXD_TX_CKO_CONTROL (s2BIT(5)|s2BIT(6)|s2BIT(7))
+#define TXD_TX_CKO_IPV4_EN s2BIT(5)
+#define TXD_TX_CKO_TCP_EN s2BIT(6)
+#define TXD_TX_CKO_UDP_EN s2BIT(7)
+#define TXD_VLAN_ENABLE s2BIT(15)
#define TXD_VLAN_TAG(val) vBIT(val,16,16)
#define TXD_INT_NUMBER(val) vBIT(val,34,6)
-#define TXD_INT_TYPE_PER_LIST BIT(47)
-#define TXD_INT_TYPE_UTILZ BIT(46)
+#define TXD_INT_TYPE_PER_LIST s2BIT(47)
+#define TXD_INT_TYPE_UTILZ s2BIT(46)
#define TXD_SET_MARKER vBIT(0x6,0,4)
u64 Buffer_Pointer;
@@ -525,14 +525,14 @@ struct list_info_hold {
struct RxD_t {
u64 Host_Control; /* reserved for host */
u64 Control_1;
-#define RXD_OWN_XENA BIT(7)
-#define RXD_T_CODE (BIT(12)|BIT(13)|BIT(14)|BIT(15))
+#define RXD_OWN_XENA s2BIT(7)
+#define RXD_T_CODE (s2BIT(12)|s2BIT(13)|s2BIT(14)|s2BIT(15))
#define RXD_FRAME_PROTO vBIT(0xFFFF,24,8)
-#define RXD_FRAME_PROTO_IPV4 BIT(27)
-#define RXD_FRAME_PROTO_IPV6 BIT(28)
-#define RXD_FRAME_IP_FRAG BIT(29)
-#define RXD_FRAME_PROTO_TCP BIT(30)
-#define RXD_FRAME_PROTO_UDP BIT(31)
+#define RXD_FRAME_PROTO_IPV4 s2BIT(27)
+#define RXD_FRAME_PROTO_IPV6 s2BIT(28)
+#define RXD_FRAME_IP_FRAG s2BIT(29)
+#define RXD_FRAME_PROTO_TCP s2BIT(30)
+#define RXD_FRAME_PROTO_UDP s2BIT(31)
#define TCP_OR_UDP_FRAME (RXD_FRAME_PROTO_TCP | RXD_FRAME_PROTO_UDP)
#define RXD_GET_L3_CKSUM(val) ((u16)(val>> 16) & 0xFFFF)
#define RXD_GET_L4_CKSUM(val) ((u16)(val) & 0xFFFF)
@@ -998,26 +998,26 @@ static inline void SPECIAL_REG_WRITE(u64 val, void __iomem *addr, int order)
/* Interrupt masks for the general interrupt mask register */
#define DISABLE_ALL_INTRS 0xFFFFFFFFFFFFFFFFULL
-#define TXPIC_INT_M BIT(0)
-#define TXDMA_INT_M BIT(1)
-#define TXMAC_INT_M BIT(2)
-#define TXXGXS_INT_M BIT(3)
-#define TXTRAFFIC_INT_M BIT(8)
-#define PIC_RX_INT_M BIT(32)
-#define RXDMA_INT_M BIT(33)
-#define RXMAC_INT_M BIT(34)
-#define MC_INT_M BIT(35)
-#define RXXGXS_INT_M BIT(36)
-#define RXTRAFFIC_INT_M BIT(40)
+#define TXPIC_INT_M s2BIT(0)
+#define TXDMA_INT_M s2BIT(1)
+#define TXMAC_INT_M s2BIT(2)
+#define TXXGXS_INT_M s2BIT(3)
+#define TXTRAFFIC_INT_M s2BIT(8)
+#define PIC_RX_INT_M s2BIT(32)
+#define RXDMA_INT_M s2BIT(33)
+#define RXMAC_INT_M s2BIT(34)
+#define MC_INT_M s2BIT(35)
+#define RXXGXS_INT_M s2BIT(36)
+#define RXTRAFFIC_INT_M s2BIT(40)
/* PIC level Interrupts TODO*/
/* DMA level Inressupts */
-#define TXDMA_PFC_INT_M BIT(0)
-#define TXDMA_PCC_INT_M BIT(2)
+#define TXDMA_PFC_INT_M s2BIT(0)
+#define TXDMA_PCC_INT_M s2BIT(2)
/* PFC block interrupts */
-#define PFC_MISC_ERR_1 BIT(0) /* Interrupt to indicate FIFO full */
+#define PFC_MISC_ERR_1 s2BIT(0) /* Interrupt to indicate FIFO full */
/* PCC block interrupts. */
#define PCC_FB_ECC_ERR vBIT(0xff, 16, 8) /* Interrupt to indicate
diff --git a/drivers/net/saa9730.c b/drivers/net/saa9730.c
index 14361e885415..c65199df8a7f 100644
--- a/drivers/net/saa9730.c
+++ b/drivers/net/saa9730.c
@@ -97,13 +97,16 @@ static void evm_saa9730_unblock_lan_int(struct lan_saa9730_private *lp)
&lp->evm_saa9730_regs->InterruptBlock1);
}
-static void __attribute_used__ show_saa9730_regs(struct lan_saa9730_private *lp)
+static void __used show_saa9730_regs(struct net_device *dev)
{
+ struct lan_saa9730_private *lp = netdev_priv(dev);
int i, j;
+
printk("TxmBufferA = %p\n", lp->TxmBuffer[0][0]);
printk("TxmBufferB = %p\n", lp->TxmBuffer[1][0]);
printk("RcvBufferA = %p\n", lp->RcvBuffer[0][0]);
printk("RcvBufferB = %p\n", lp->RcvBuffer[1][0]);
+
for (i = 0; i < LAN_SAA9730_BUFFERS; i++) {
for (j = 0; j < LAN_SAA9730_TXM_Q_SIZE; j++) {
printk("TxmBuffer[%d][%d] = %x\n", i, j,
@@ -146,11 +149,13 @@ static void __attribute_used__ show_saa9730_regs(struct lan_saa9730_private *lp)
readl(&lp->lan_saa9730_regs->RxCtl));
printk("lp->lan_saa9730_regs->RxStatus = %x\n",
readl(&lp->lan_saa9730_regs->RxStatus));
+
for (i = 0; i < LAN_SAA9730_CAM_DWORDS; i++) {
writel(i, &lp->lan_saa9730_regs->CamAddress);
printk("lp->lan_saa9730_regs->CamData = %x\n",
readl(&lp->lan_saa9730_regs->CamData));
}
+
printk("dev->stats.tx_packets = %lx\n", dev->stats.tx_packets);
printk("dev->stats.tx_errors = %lx\n", dev->stats.tx_errors);
printk("dev->stats.tx_aborted_errors = %lx\n",
@@ -855,7 +860,7 @@ static void lan_saa9730_tx_timeout(struct net_device *dev)
/* Transmitter timeout, serious problems */
dev->stats.tx_errors++;
printk("%s: transmit timed out, reset\n", dev->name);
- /*show_saa9730_regs(lp); */
+ /*show_saa9730_regs(dev); */
lan_saa9730_restart(lp);
dev->trans_start = jiffies;
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index 2aae9fe38c5a..6d62250fba07 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -36,13 +36,15 @@
#include <linux/delay.h>
#include <linux/crc32.h>
#include <linux/dma-mapping.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
#include <linux/mii.h>
#include <asm/irq.h>
#include "skge.h"
#define DRV_NAME "skge"
-#define DRV_VERSION "1.11"
+#define DRV_VERSION "1.12"
#define PFX DRV_NAME " "
#define DEFAULT_TX_RING_SIZE 128
@@ -57,7 +59,10 @@
#define TX_WATCHDOG (5 * HZ)
#define NAPI_WEIGHT 64
#define BLINK_MS 250
-#define LINK_HZ (HZ/2)
+#define LINK_HZ HZ
+
+#define SKGE_EEPROM_MAGIC 0x9933aabb
+
MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver");
MODULE_AUTHOR("Stephen Hemminger <shemminger@linux-foundation.org>");
@@ -445,15 +450,15 @@ static struct net_device_stats *skge_get_stats(struct net_device *dev)
else
yukon_get_stats(skge, data);
- skge->net_stats.tx_bytes = data[0];
- skge->net_stats.rx_bytes = data[1];
- skge->net_stats.tx_packets = data[2] + data[4] + data[6];
- skge->net_stats.rx_packets = data[3] + data[5] + data[7];
- skge->net_stats.multicast = data[3] + data[5];
- skge->net_stats.collisions = data[10];
- skge->net_stats.tx_aborted_errors = data[12];
+ dev->stats.tx_bytes = data[0];
+ dev->stats.rx_bytes = data[1];
+ dev->stats.tx_packets = data[2] + data[4] + data[6];
+ dev->stats.rx_packets = data[3] + data[5] + data[7];
+ dev->stats.multicast = data[3] + data[5];
+ dev->stats.collisions = data[10];
+ dev->stats.tx_aborted_errors = data[12];
- return &skge->net_stats;
+ return &dev->stats;
}
static void skge_get_strings(struct net_device *dev, u32 stringset, u8 *data)
@@ -798,6 +803,98 @@ static int skge_phys_id(struct net_device *dev, u32 data)
return 0;
}
+static int skge_get_eeprom_len(struct net_device *dev)
+{
+ struct skge_port *skge = netdev_priv(dev);
+ u32 reg2;
+
+ pci_read_config_dword(skge->hw->pdev, PCI_DEV_REG2, &reg2);
+ return 1 << ( ((reg2 & PCI_VPD_ROM_SZ) >> 14) + 8);
+}
+
+static u32 skge_vpd_read(struct pci_dev *pdev, int cap, u16 offset)
+{
+ u32 val;
+
+ pci_write_config_word(pdev, cap + PCI_VPD_ADDR, offset);
+
+ do {
+ pci_read_config_word(pdev, cap + PCI_VPD_ADDR, &offset);
+ } while (!(offset & PCI_VPD_ADDR_F));
+
+ pci_read_config_dword(pdev, cap + PCI_VPD_DATA, &val);
+ return val;
+}
+
+static void skge_vpd_write(struct pci_dev *pdev, int cap, u16 offset, u32 val)
+{
+ pci_write_config_dword(pdev, cap + PCI_VPD_DATA, val);
+ pci_write_config_word(pdev, cap + PCI_VPD_ADDR,
+ offset | PCI_VPD_ADDR_F);
+
+ do {
+ pci_read_config_word(pdev, cap + PCI_VPD_ADDR, &offset);
+ } while (offset & PCI_VPD_ADDR_F);
+}
+
+static int skge_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
+ u8 *data)
+{
+ struct skge_port *skge = netdev_priv(dev);
+ struct pci_dev *pdev = skge->hw->pdev;
+ int cap = pci_find_capability(pdev, PCI_CAP_ID_VPD);
+ int length = eeprom->len;
+ u16 offset = eeprom->offset;
+
+ if (!cap)
+ return -EINVAL;
+
+ eeprom->magic = SKGE_EEPROM_MAGIC;
+
+ while (length > 0) {
+ u32 val = skge_vpd_read(pdev, cap, offset);
+ int n = min_t(int, length, sizeof(val));
+
+ memcpy(data, &val, n);
+ length -= n;
+ data += n;
+ offset += n;
+ }
+ return 0;
+}
+
+static int skge_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
+ u8 *data)
+{
+ struct skge_port *skge = netdev_priv(dev);
+ struct pci_dev *pdev = skge->hw->pdev;
+ int cap = pci_find_capability(pdev, PCI_CAP_ID_VPD);
+ int length = eeprom->len;
+ u16 offset = eeprom->offset;
+
+ if (!cap)
+ return -EINVAL;
+
+ if (eeprom->magic != SKGE_EEPROM_MAGIC)
+ return -EINVAL;
+
+ while (length > 0) {
+ u32 val;
+ int n = min_t(int, length, sizeof(val));
+
+ if (n < sizeof(val))
+ val = skge_vpd_read(pdev, cap, offset);
+ memcpy(&val, data, n);
+
+ skge_vpd_write(pdev, cap, offset, val);
+
+ length -= n;
+ data += n;
+ offset += n;
+ }
+ return 0;
+}
+
static const struct ethtool_ops skge_ethtool_ops = {
.get_settings = skge_get_settings,
.set_settings = skge_set_settings,
@@ -810,6 +907,9 @@ static const struct ethtool_ops skge_ethtool_ops = {
.set_msglevel = skge_set_msglevel,
.nway_reset = skge_nway_reset,
.get_link = ethtool_op_get_link,
+ .get_eeprom_len = skge_get_eeprom_len,
+ .get_eeprom = skge_get_eeprom,
+ .set_eeprom = skge_set_eeprom,
.get_ringparam = skge_get_ring_param,
.set_ringparam = skge_set_ring_param,
.get_pauseparam = skge_get_pauseparam,
@@ -995,19 +1095,15 @@ static void xm_link_down(struct skge_hw *hw, int port)
{
struct net_device *dev = hw->dev[port];
struct skge_port *skge = netdev_priv(dev);
- u16 cmd, msk;
+ u16 cmd = xm_read16(hw, port, XM_MMU_CMD);
- if (hw->phy_type == SK_PHY_XMAC) {
- msk = xm_read16(hw, port, XM_IMSK);
- msk |= XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE | XM_IS_AND;
- xm_write16(hw, port, XM_IMSK, msk);
- }
+ xm_write16(hw, port, XM_IMSK, XM_IMSK_DISABLE);
- cmd = xm_read16(hw, port, XM_MMU_CMD);
cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX);
xm_write16(hw, port, XM_MMU_CMD, cmd);
+
/* dummy read to ensure writing */
- (void) xm_read16(hw, port, XM_MMU_CMD);
+ xm_read16(hw, port, XM_MMU_CMD);
if (netif_carrier_ok(dev))
skge_link_down(skge);
@@ -1103,7 +1199,7 @@ static void genesis_reset(struct skge_hw *hw, int port)
/* reset the statistics module */
xm_write32(hw, port, XM_GP_PORT, XM_GP_RES_STAT);
- xm_write16(hw, port, XM_IMSK, 0xffff); /* disable XMAC IRQs */
+ xm_write16(hw, port, XM_IMSK, XM_IMSK_DISABLE);
xm_write32(hw, port, XM_MODE, 0); /* clear Mode Reg */
xm_write16(hw, port, XM_TX_CMD, 0); /* reset TX CMD Reg */
xm_write16(hw, port, XM_RX_CMD, 0); /* reset RX CMD Reg */
@@ -1141,7 +1237,7 @@ static void bcom_check_link(struct skge_hw *hw, int port)
u16 status;
/* read twice because of latch */
- (void) xm_phy_read(hw, port, PHY_BCOM_STAT);
+ xm_phy_read(hw, port, PHY_BCOM_STAT);
status = xm_phy_read(hw, port, PHY_BCOM_STAT);
if ((status & PHY_ST_LSYNC) == 0) {
@@ -1342,7 +1438,7 @@ static void xm_phy_init(struct skge_port *skge)
mod_timer(&skge->link_timer, jiffies + LINK_HZ);
}
-static void xm_check_link(struct net_device *dev)
+static int xm_check_link(struct net_device *dev)
{
struct skge_port *skge = netdev_priv(dev);
struct skge_hw *hw = skge->hw;
@@ -1350,25 +1446,25 @@ static void xm_check_link(struct net_device *dev)
u16 status;
/* read twice because of latch */
- (void) xm_phy_read(hw, port, PHY_XMAC_STAT);
+ xm_phy_read(hw, port, PHY_XMAC_STAT);
status = xm_phy_read(hw, port, PHY_XMAC_STAT);
if ((status & PHY_ST_LSYNC) == 0) {
xm_link_down(hw, port);
- return;
+ return 0;
}
if (skge->autoneg == AUTONEG_ENABLE) {
u16 lpa, res;
if (!(status & PHY_ST_AN_OVER))
- return;
+ return 0;
lpa = xm_phy_read(hw, port, PHY_XMAC_AUNE_LP);
if (lpa & PHY_B_AN_RF) {
printk(KERN_NOTICE PFX "%s: remote fault\n",
dev->name);
- return;
+ return 0;
}
res = xm_phy_read(hw, port, PHY_XMAC_RES_ABI);
@@ -1384,7 +1480,7 @@ static void xm_check_link(struct net_device *dev)
default:
printk(KERN_NOTICE PFX "%s: duplex mismatch\n",
dev->name);
- return;
+ return 0;
}
/* We are using IEEE 802.3z/D5.0 Table 37-4 */
@@ -1408,11 +1504,14 @@ static void xm_check_link(struct net_device *dev)
if (!netif_carrier_ok(dev))
genesis_link_up(skge);
+ return 1;
}
/* Poll to check for link coming up.
+ *
* Since internal PHY is wired to a level triggered pin, can't
- * get an interrupt when carrier is detected.
+ * get an interrupt when carrier is detected, need to poll for
+ * link coming up.
*/
static void xm_link_timer(unsigned long arg)
{
@@ -1420,29 +1519,35 @@ static void xm_link_timer(unsigned long arg)
struct net_device *dev = skge->netdev;
struct skge_hw *hw = skge->hw;
int port = skge->port;
+ int i;
+ unsigned long flags;
if (!netif_running(dev))
return;
- if (netif_carrier_ok(dev)) {
+ spin_lock_irqsave(&hw->phy_lock, flags);
+
+ /*
+ * Verify that the link by checking GPIO register three times.
+ * This pin has the signal from the link_sync pin connected to it.
+ */
+ for (i = 0; i < 3; i++) {
+ if (xm_read16(hw, port, XM_GP_PORT) & XM_GP_INP_ASS)
+ goto link_down;
+ }
+
+ /* Re-enable interrupt to detect link down */
+ if (xm_check_link(dev)) {
+ u16 msk = xm_read16(hw, port, XM_IMSK);
+ msk &= ~XM_IS_INP_ASS;
+ xm_write16(hw, port, XM_IMSK, msk);
xm_read16(hw, port, XM_ISRC);
- if (!(xm_read16(hw, port, XM_ISRC) & XM_IS_INP_ASS))
- goto nochange;
} else {
- if (xm_read32(hw, port, XM_GP_PORT) & XM_GP_INP_ASS)
- goto nochange;
- xm_read16(hw, port, XM_ISRC);
- if (xm_read16(hw, port, XM_ISRC) & XM_IS_INP_ASS)
- goto nochange;
+link_down:
+ mod_timer(&skge->link_timer,
+ round_jiffies(jiffies + LINK_HZ));
}
-
- spin_lock(&hw->phy_lock);
- xm_check_link(dev);
- spin_unlock(&hw->phy_lock);
-
-nochange:
- if (netif_running(dev))
- mod_timer(&skge->link_timer, jiffies + LINK_HZ);
+ spin_unlock_irqrestore(&hw->phy_lock, flags);
}
static void genesis_mac_init(struct skge_hw *hw, int port)
@@ -1679,24 +1784,27 @@ static void genesis_get_stats(struct skge_port *skge, u64 *data)
static void genesis_mac_intr(struct skge_hw *hw, int port)
{
- struct skge_port *skge = netdev_priv(hw->dev[port]);
+ struct net_device *dev = hw->dev[port];
+ struct skge_port *skge = netdev_priv(dev);
u16 status = xm_read16(hw, port, XM_ISRC);
if (netif_msg_intr(skge))
printk(KERN_DEBUG PFX "%s: mac interrupt status 0x%x\n",
- skge->netdev->name, status);
+ dev->name, status);
- if (hw->phy_type == SK_PHY_XMAC &&
- (status & (XM_IS_INP_ASS | XM_IS_LIPA_RC)))
- xm_link_down(hw, port);
+ if (hw->phy_type == SK_PHY_XMAC && (status & XM_IS_INP_ASS)) {
+ xm_link_down(hw, port);
+ mod_timer(&skge->link_timer, jiffies + 1);
+ }
if (status & XM_IS_TXF_UR) {
xm_write32(hw, port, XM_MODE, XM_MD_FTF);
- ++skge->net_stats.tx_fifo_errors;
+ ++dev->stats.tx_fifo_errors;
}
+
if (status & XM_IS_RXF_OV) {
xm_write32(hw, port, XM_MODE, XM_MD_FRF);
- ++skge->net_stats.rx_fifo_errors;
+ ++dev->stats.rx_fifo_errors;
}
}
@@ -1753,11 +1861,12 @@ static void genesis_link_up(struct skge_port *skge)
}
xm_write32(hw, port, XM_MODE, mode);
- msk = XM_DEF_MSK;
- if (hw->phy_type != SK_PHY_XMAC)
- msk |= XM_IS_INP_ASS; /* disable GP0 interrupt bit */
+ /* Turn on detection of Tx underrun, Rx overrun */
+ msk = xm_read16(hw, port, XM_IMSK);
+ msk &= ~(XM_IS_RXF_OV | XM_IS_TXF_UR);
xm_write16(hw, port, XM_IMSK, msk);
+
xm_read16(hw, port, XM_ISRC);
/* get MMU Command Reg. */
@@ -2192,12 +2301,12 @@ static void yukon_mac_intr(struct skge_hw *hw, int port)
dev->name, status);
if (status & GM_IS_RX_FF_OR) {
- ++skge->net_stats.rx_fifo_errors;
+ ++dev->stats.rx_fifo_errors;
skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_CLI_RX_FO);
}
if (status & GM_IS_TX_FF_UR) {
- ++skge->net_stats.tx_fifo_errors;
+ ++dev->stats.tx_fifo_errors;
skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_CLI_TX_FU);
}
@@ -2544,6 +2653,15 @@ static int skge_up(struct net_device *dev)
return err;
}
+/* stop receiver */
+static void skge_rx_stop(struct skge_hw *hw, int port)
+{
+ skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_STOP);
+ skge_write32(hw, RB_ADDR(port ? Q_R2 : Q_R1, RB_CTRL),
+ RB_RST_SET|RB_DIS_OP_MD);
+ skge_write32(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_SET_RESET);
+}
+
static int skge_down(struct net_device *dev)
{
struct skge_port *skge = netdev_priv(dev);
@@ -2595,11 +2713,8 @@ static int skge_down(struct net_device *dev)
/* Reset the RAM Buffer async Tx queue */
skge_write8(hw, RB_ADDR(port == 0 ? Q_XA1 : Q_XA2, RB_CTRL), RB_RST_SET);
- /* stop receiver */
- skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_STOP);
- skge_write32(hw, RB_ADDR(port ? Q_R2 : Q_R1, RB_CTRL),
- RB_RST_SET|RB_DIS_OP_MD);
- skge_write32(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_SET_RESET);
+
+ skge_rx_stop(hw, port);
if (hw->chip_id == CHIP_ID_GENESIS) {
skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_RST_SET);
@@ -2782,7 +2897,11 @@ static void skge_tx_timeout(struct net_device *dev)
static int skge_change_mtu(struct net_device *dev, int new_mtu)
{
+ struct skge_port *skge = netdev_priv(dev);
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
int err;
+ u16 ctl, reg;
if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU)
return -EINVAL;
@@ -2792,13 +2911,40 @@ static int skge_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
- skge_down(dev);
+ skge_write32(hw, B0_IMSK, 0);
+ dev->trans_start = jiffies; /* prevent tx timeout */
+ netif_stop_queue(dev);
+ napi_disable(&skge->napi);
+
+ ctl = gma_read16(hw, port, GM_GP_CTRL);
+ gma_write16(hw, port, GM_GP_CTRL, ctl & ~GM_GPCR_RX_ENA);
+
+ skge_rx_clean(skge);
+ skge_rx_stop(hw, port);
dev->mtu = new_mtu;
- err = skge_up(dev);
+ reg = GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF);
+ if (new_mtu > 1500)
+ reg |= GM_SMOD_JUMBO_ENA;
+ gma_write16(hw, port, GM_SERIAL_MODE, reg);
+
+ skge_write8(hw, RB_ADDR(rxqaddr[port], RB_CTRL), RB_ENA_OP_MD);
+
+ err = skge_rx_fill(dev);
+ wmb();
+ if (!err)
+ skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F);
+ skge_write32(hw, B0_IMSK, hw->intr_mask);
+
if (err)
dev_close(dev);
+ else {
+ gma_write16(hw, port, GM_GP_CTRL, ctl);
+
+ napi_enable(&skge->napi);
+ netif_wake_queue(dev);
+ }
return err;
}
@@ -2994,18 +3140,18 @@ error:
if (skge->hw->chip_id == CHIP_ID_GENESIS) {
if (status & (XMR_FS_RUNT|XMR_FS_LNG_ERR))
- skge->net_stats.rx_length_errors++;
+ dev->stats.rx_length_errors++;
if (status & XMR_FS_FRA_ERR)
- skge->net_stats.rx_frame_errors++;
+ dev->stats.rx_frame_errors++;
if (status & XMR_FS_FCS_ERR)
- skge->net_stats.rx_crc_errors++;
+ dev->stats.rx_crc_errors++;
} else {
if (status & (GMR_FS_LONG_ERR|GMR_FS_UN_SIZE))
- skge->net_stats.rx_length_errors++;
+ dev->stats.rx_length_errors++;
if (status & GMR_FS_FRAGMENT)
- skge->net_stats.rx_frame_errors++;
+ dev->stats.rx_frame_errors++;
if (status & GMR_FS_CRC_ERR)
- skge->net_stats.rx_crc_errors++;
+ dev->stats.rx_crc_errors++;
}
resubmit:
@@ -3103,10 +3249,7 @@ static void skge_mac_parity(struct skge_hw *hw, int port)
{
struct net_device *dev = hw->dev[port];
- if (dev) {
- struct skge_port *skge = netdev_priv(dev);
- ++skge->net_stats.tx_heartbeat_errors;
- }
+ ++dev->stats.tx_heartbeat_errors;
if (hw->chip_id == CHIP_ID_GENESIS)
skge_write16(hw, SK_REG(port, TX_MFF_CTRL1),
@@ -3259,9 +3402,7 @@ static irqreturn_t skge_intr(int irq, void *dev_id)
skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_TX1);
if (status & IS_PA_TO_RX1) {
- struct skge_port *skge = netdev_priv(hw->dev[0]);
-
- ++skge->net_stats.rx_over_errors;
+ ++hw->dev[0]->stats.rx_over_errors;
skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_RX1);
}
@@ -3278,7 +3419,7 @@ static irqreturn_t skge_intr(int irq, void *dev_id)
}
if (status & IS_PA_TO_RX2) {
- ++skge->net_stats.rx_over_errors;
+ ++hw->dev[1]->stats.rx_over_errors;
skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_RX2);
}
@@ -3540,6 +3681,145 @@ static int skge_reset(struct skge_hw *hw)
return 0;
}
+
+#ifdef CONFIG_SKGE_DEBUG
+
+static struct dentry *skge_debug;
+
+static int skge_debug_show(struct seq_file *seq, void *v)
+{
+ struct net_device *dev = seq->private;
+ const struct skge_port *skge = netdev_priv(dev);
+ const struct skge_hw *hw = skge->hw;
+ const struct skge_element *e;
+
+ if (!netif_running(dev))
+ return -ENETDOWN;
+
+ seq_printf(seq, "IRQ src=%x mask=%x\n", skge_read32(hw, B0_ISRC),
+ skge_read32(hw, B0_IMSK));
+
+ seq_printf(seq, "Tx Ring: (%d)\n", skge_avail(&skge->tx_ring));
+ for (e = skge->tx_ring.to_clean; e != skge->tx_ring.to_use; e = e->next) {
+ const struct skge_tx_desc *t = e->desc;
+ seq_printf(seq, "%#x dma=%#x%08x %#x csum=%#x/%x/%x\n",
+ t->control, t->dma_hi, t->dma_lo, t->status,
+ t->csum_offs, t->csum_write, t->csum_start);
+ }
+
+ seq_printf(seq, "\nRx Ring: \n");
+ for (e = skge->rx_ring.to_clean; ; e = e->next) {
+ const struct skge_rx_desc *r = e->desc;
+
+ if (r->control & BMU_OWN)
+ break;
+
+ seq_printf(seq, "%#x dma=%#x%08x %#x %#x csum=%#x/%x\n",
+ r->control, r->dma_hi, r->dma_lo, r->status,
+ r->timestamp, r->csum1, r->csum1_start);
+ }
+
+ return 0;
+}
+
+static int skge_debug_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, skge_debug_show, inode->i_private);
+}
+
+static const struct file_operations skge_debug_fops = {
+ .owner = THIS_MODULE,
+ .open = skge_debug_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+/*
+ * Use network device events to create/remove/rename
+ * debugfs file entries
+ */
+static int skge_device_event(struct notifier_block *unused,
+ unsigned long event, void *ptr)
+{
+ struct net_device *dev = ptr;
+ struct skge_port *skge;
+ struct dentry *d;
+
+ if (dev->open != &skge_up || !skge_debug)
+ goto done;
+
+ skge = netdev_priv(dev);
+ switch(event) {
+ case NETDEV_CHANGENAME:
+ if (skge->debugfs) {
+ d = debugfs_rename(skge_debug, skge->debugfs,
+ skge_debug, dev->name);
+ if (d)
+ skge->debugfs = d;
+ else {
+ pr_info(PFX "%s: rename failed\n", dev->name);
+ debugfs_remove(skge->debugfs);
+ }
+ }
+ break;
+
+ case NETDEV_GOING_DOWN:
+ if (skge->debugfs) {
+ debugfs_remove(skge->debugfs);
+ skge->debugfs = NULL;
+ }
+ break;
+
+ case NETDEV_UP:
+ d = debugfs_create_file(dev->name, S_IRUGO,
+ skge_debug, dev,
+ &skge_debug_fops);
+ if (!d || IS_ERR(d))
+ pr_info(PFX "%s: debugfs create failed\n",
+ dev->name);
+ else
+ skge->debugfs = d;
+ break;
+ }
+
+done:
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block skge_notifier = {
+ .notifier_call = skge_device_event,
+};
+
+
+static __init void skge_debug_init(void)
+{
+ struct dentry *ent;
+
+ ent = debugfs_create_dir("skge", NULL);
+ if (!ent || IS_ERR(ent)) {
+ pr_info(PFX "debugfs create directory failed\n");
+ return;
+ }
+
+ skge_debug = ent;
+ register_netdevice_notifier(&skge_notifier);
+}
+
+static __exit void skge_debug_cleanup(void)
+{
+ if (skge_debug) {
+ unregister_netdevice_notifier(&skge_notifier);
+ debugfs_remove(skge_debug);
+ skge_debug = NULL;
+ }
+}
+
+#else
+#define skge_debug_init()
+#define skge_debug_cleanup()
+#endif
+
/* Initialize network device */
static struct net_device *skge_devinit(struct skge_hw *hw, int port,
int highmem)
@@ -3904,12 +4184,14 @@ static struct pci_driver skge_driver = {
static int __init skge_init_module(void)
{
+ skge_debug_init();
return pci_register_driver(&skge_driver);
}
static void __exit skge_cleanup_module(void)
{
pci_unregister_driver(&skge_driver);
+ skge_debug_cleanup();
}
module_init(skge_init_module);
diff --git a/drivers/net/skge.h b/drivers/net/skge.h
index 1a57bdd1ddf1..17caccbb7685 100644
--- a/drivers/net/skge.h
+++ b/drivers/net/skge.h
@@ -1,5 +1,5 @@
/*
- * Definitions for the new Marvell Yukon / SysKonenct driver.
+ * Definitions for the new Marvell Yukon / SysKonnect driver.
*/
#ifndef _SKGE_H
#define _SKGE_H
@@ -8,8 +8,10 @@
#define PCI_DEV_REG1 0x40
#define PCI_PHY_COMA 0x8000000
#define PCI_VIO 0x2000000
+
#define PCI_DEV_REG2 0x44
-#define PCI_REV_DESC 0x4
+#define PCI_VPD_ROM_SZ 7L<<14 /* VPD ROM size 0=256, 1=512, ... */
+#define PCI_REV_DESC 1<<2 /* Reverse Descriptor bytes */
#define PCI_STATUS_ERROR_BITS (PCI_STATUS_DETECTED_PARITY | \
PCI_STATUS_SIG_SYSTEM_ERROR | \
@@ -2191,11 +2193,9 @@ enum {
XM_IS_TXF_UR = 1<<2, /* Bit 2: Transmit FIFO Underrun */
XM_IS_TX_COMP = 1<<1, /* Bit 1: Frame Tx Complete */
XM_IS_RX_COMP = 1<<0, /* Bit 0: Frame Rx Complete */
-};
-
-#define XM_DEF_MSK (~(XM_IS_INP_ASS | XM_IS_LIPA_RC | \
- XM_IS_RXF_OV | XM_IS_TXF_UR))
+ XM_IMSK_DISABLE = 0xffff,
+};
/* XM_HW_CFG 16 bit r/w Hardware Config Register */
enum {
@@ -2469,8 +2469,9 @@ struct skge_port {
void *mem; /* PCI memory for rings */
dma_addr_t dma;
unsigned long mem_size;
-
- struct net_device_stats net_stats;
+#ifdef CONFIG_SKGE_DEBUG
+ struct dentry *debugfs;
+#endif
};
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 7967240534d5..a2070db725c9 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -52,7 +52,7 @@
#include "sky2.h"
#define DRV_NAME "sky2"
-#define DRV_VERSION "1.19"
+#define DRV_VERSION "1.20"
#define PFX DRV_NAME " "
/*
@@ -121,6 +121,7 @@ static const struct pci_device_id sky2_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4353) }, /* 88E8039 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4354) }, /* 88E8040 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4356) }, /* 88EC033 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4357) }, /* 88E8042 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x435A) }, /* 88E8048 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4360) }, /* 88E8052 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) }, /* 88E8050 */
@@ -134,6 +135,7 @@ static const struct pci_device_id sky2_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4369) }, /* 88EC042 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436A) }, /* 88E8058 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436B) }, /* 88E8071 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436C) }, /* 88E8072 */
{ 0 }
};
@@ -156,7 +158,7 @@ static const char *yukon2_name[] = {
static void sky2_set_multicast(struct net_device *dev);
-/* Access to external PHY */
+/* Access to PHY via serial interconnect */
static int gm_phy_write(struct sky2_hw *hw, unsigned port, u16 reg, u16 val)
{
int i;
@@ -166,13 +168,22 @@ static int gm_phy_write(struct sky2_hw *hw, unsigned port, u16 reg, u16 val)
GM_SMI_CT_PHY_AD(PHY_ADDR_MARV) | GM_SMI_CT_REG_AD(reg));
for (i = 0; i < PHY_RETRIES; i++) {
- if (!(gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_BUSY))
+ u16 ctrl = gma_read16(hw, port, GM_SMI_CTRL);
+ if (ctrl == 0xffff)
+ goto io_error;
+
+ if (!(ctrl & GM_SMI_CT_BUSY))
return 0;
- udelay(1);
+
+ udelay(10);
}
- printk(KERN_WARNING PFX "%s: phy write timeout\n", hw->dev[port]->name);
+ dev_warn(&hw->pdev->dev,"%s: phy write timeout\n", hw->dev[port]->name);
return -ETIMEDOUT;
+
+io_error:
+ dev_err(&hw->pdev->dev, "%s: phy I/O error\n", hw->dev[port]->name);
+ return -EIO;
}
static int __gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg, u16 *val)
@@ -183,23 +194,29 @@ static int __gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg, u16 *val)
| GM_SMI_CT_REG_AD(reg) | GM_SMI_CT_OP_RD);
for (i = 0; i < PHY_RETRIES; i++) {
- if (gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_RD_VAL) {
+ u16 ctrl = gma_read16(hw, port, GM_SMI_CTRL);
+ if (ctrl == 0xffff)
+ goto io_error;
+
+ if (ctrl & GM_SMI_CT_RD_VAL) {
*val = gma_read16(hw, port, GM_SMI_DATA);
return 0;
}
- udelay(1);
+ udelay(10);
}
+ dev_warn(&hw->pdev->dev, "%s: phy read timeout\n", hw->dev[port]->name);
return -ETIMEDOUT;
+io_error:
+ dev_err(&hw->pdev->dev, "%s: phy I/O error\n", hw->dev[port]->name);
+ return -EIO;
}
-static u16 gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg)
+static inline u16 gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg)
{
u16 v;
-
- if (__gm_phy_read(hw, port, reg, &v) != 0)
- printk(KERN_WARNING PFX "%s: phy read timeout\n", hw->dev[port]->name);
+ __gm_phy_read(hw, port, reg, &v);
return v;
}
@@ -273,8 +290,6 @@ static void sky2_gmac_reset(struct sky2_hw *hw, unsigned port)
/* disable all GMAC IRQ's */
sky2_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0);
- /* disable PHY IRQs */
- gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);
gma_write16(hw, port, GM_MC_ADDR_H1, 0); /* clear MC hash */
gma_write16(hw, port, GM_MC_ADDR_H2, 0);
@@ -1384,13 +1399,9 @@ static int sky2_up(struct net_device *dev)
sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map,
TX_RING_SIZE - 1);
- napi_enable(&hw->napi);
-
err = sky2_rx_start(sky2);
- if (err) {
- napi_disable(&hw->napi);
+ if (err)
goto err_out;
- }
/* Enable interrupts from phy/mac for port */
imask = sky2_read32(hw, B0_IMSK);
@@ -1679,13 +1690,13 @@ static int sky2_down(struct net_device *dev)
/* Stop more packets from being queued */
netif_stop_queue(dev);
- napi_disable(&hw->napi);
-
/* Disable port IRQ */
imask = sky2_read32(hw, B0_IMSK);
imask &= ~portirq_msk[port];
sky2_write32(hw, B0_IMSK, imask);
+ synchronize_irq(hw->pdev->irq);
+
sky2_gmac_reset(hw, port);
/* Stop transmitter */
@@ -1699,6 +1710,9 @@ static int sky2_down(struct net_device *dev)
ctrl &= ~(GM_GPCR_TX_ENA | GM_GPCR_RX_ENA);
gma_write16(hw, port, GM_GP_CTRL, ctrl);
+ /* Make sure no packets are pending */
+ napi_synchronize(&hw->napi);
+
sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
/* Workaround shared GMAC reset */
@@ -1736,8 +1750,6 @@ static int sky2_down(struct net_device *dev)
/* turn off LED's */
sky2_write16(hw, B0_Y2LED, LED_STAT_OFF);
- synchronize_irq(hw->pdev->irq);
-
sky2_tx_clean(dev);
sky2_rx_clean(sky2);
@@ -1808,29 +1820,6 @@ static void sky2_link_up(struct sky2_port *sky2)
sky2_write8(hw, SK_REG(port, LNK_LED_REG),
LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF);
- if (hw->flags & SKY2_HW_NEWER_PHY) {
- u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
- u16 led = PHY_M_LEDC_LOS_CTRL(1); /* link active */
-
- switch(sky2->speed) {
- case SPEED_10:
- led |= PHY_M_LEDC_INIT_CTRL(7);
- break;
-
- case SPEED_100:
- led |= PHY_M_LEDC_STA1_CTRL(7);
- break;
-
- case SPEED_1000:
- led |= PHY_M_LEDC_STA0_CTRL(7);
- break;
- }
-
- gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3);
- gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, led);
- gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
- }
-
if (netif_msg_link(sky2))
printk(KERN_INFO PFX
"%s: Link is up at %d Mbps, %s duplex, flow control %s\n",
@@ -2048,9 +2037,6 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu)
err = sky2_rx_start(sky2);
sky2_write32(hw, B0_IMSK, imask);
- /* Unconditionally re-enable NAPI because even if we
- * call dev_close() that will do a napi_disable().
- */
napi_enable(&hw->napi);
if (err)
@@ -2253,20 +2239,26 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)
do {
struct sky2_port *sky2;
struct sky2_status_le *le = hw->st_le + hw->st_idx;
- unsigned port = le->css & CSS_LINK_BIT;
+ unsigned port;
struct net_device *dev;
struct sk_buff *skb;
u32 status;
u16 length;
+ u8 opcode = le->opcode;
+
+ if (!(opcode & HW_OWNER))
+ break;
hw->st_idx = RING_NEXT(hw->st_idx, STATUS_RING_SIZE);
+ port = le->css & CSS_LINK_BIT;
dev = hw->dev[port];
sky2 = netdev_priv(dev);
length = le16_to_cpu(le->length);
status = le32_to_cpu(le->status);
- switch (le->opcode & ~HW_OWNER) {
+ le->opcode = 0;
+ switch (opcode & ~HW_OWNER) {
case OP_RXSTAT:
++rx[port];
skb = sky2_receive(dev, length, status);
@@ -2359,7 +2351,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)
default:
if (net_ratelimit())
printk(KERN_WARNING PFX
- "unknown status opcode 0x%x\n", le->opcode);
+ "unknown status opcode 0x%x\n", opcode);
}
} while (hw->st_idx != idx);
@@ -2445,13 +2437,26 @@ static void sky2_hw_intr(struct sky2_hw *hw)
if (status & Y2_IS_PCI_EXP) {
/* PCI-Express uncorrectable Error occurred */
- int pos = pci_find_aer_capability(hw->pdev);
+ int aer = pci_find_aer_capability(hw->pdev);
u32 err;
- pci_read_config_dword(pdev, pos + PCI_ERR_UNCOR_STATUS, &err);
+ if (aer) {
+ pci_read_config_dword(pdev, aer + PCI_ERR_UNCOR_STATUS,
+ &err);
+ pci_cleanup_aer_uncorrect_error_status(pdev);
+ } else {
+ /* Either AER not configured, or not working
+ * because of bad MMCONFIG, so just do recover
+ * manually.
+ */
+ err = sky2_read32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS);
+ sky2_write32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS,
+ 0xfffffffful);
+ }
+
if (net_ratelimit())
dev_err(&pdev->dev, "PCI Express error (0x%x)\n", err);
- pci_cleanup_aer_uncorrect_error_status(pdev);
+
}
if (status & Y2_HWE_L1_MASK)
@@ -2797,6 +2802,9 @@ static void sky2_reset(struct sky2_hw *hw)
sky2_write8(hw, B0_CTST, CS_RST_SET);
sky2_write8(hw, B0_CTST, CS_RST_CLR);
+ /* allow writes to PCI config */
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+
/* clear PCI errors, if any */
pci_read_config_word(pdev, PCI_STATUS, &status);
status |= PCI_STATUS_ERROR_BITS;
@@ -2806,9 +2814,18 @@ static void sky2_reset(struct sky2_hw *hw)
cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
if (cap) {
- /* Check for advanced error reporting */
- pci_cleanup_aer_uncorrect_error_status(pdev);
- pci_cleanup_aer_correct_error_status(pdev);
+ if (pci_find_aer_capability(pdev)) {
+ /* Check for advanced error reporting */
+ pci_cleanup_aer_uncorrect_error_status(pdev);
+ pci_cleanup_aer_correct_error_status(pdev);
+ } else {
+ dev_warn(&pdev->dev,
+ "PCI Express Advanced Error Reporting"
+ " not configured or MMCONFIG problem?\n");
+
+ sky2_write32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS,
+ 0xfffffffful);
+ }
/* If error bit is stuck on ignore it */
if (sky2_read32(hw, B0_HWE_ISRC) & Y2_IS_PCI_EXP)
@@ -2915,6 +2932,7 @@ static void sky2_restart(struct work_struct *work)
rtnl_lock();
sky2_write32(hw, B0_IMSK, 0);
sky2_read32(hw, B0_IMSK);
+ napi_disable(&hw->napi);
for (i = 0; i < hw->ports; i++) {
dev = hw->dev[i];
@@ -2924,6 +2942,7 @@ static void sky2_restart(struct work_struct *work)
sky2_reset(hw);
sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
+ napi_enable(&hw->napi);
for (i = 0; i < hw->ports; i++) {
dev = hw->dev[i];
@@ -3961,7 +3980,7 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
struct net_device *dev = alloc_etherdev(sizeof(*sky2));
if (!dev) {
- dev_err(&hw->pdev->dev, "etherdev alloc failed");
+ dev_err(&hw->pdev->dev, "etherdev alloc failed\n");
return NULL;
}
@@ -3978,7 +3997,8 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
dev->tx_timeout = sky2_tx_timeout;
dev->watchdog_timeo = TX_WATCHDOG;
#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = sky2_netpoll;
+ if (port == 0)
+ dev->poll_controller = sky2_netpoll;
#endif
sky2 = netdev_priv(dev);
@@ -4191,7 +4211,6 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
err = -ENOMEM;
goto err_out_free_pci;
}
- netif_napi_add(dev, &hw->napi, sky2_poll, NAPI_WEIGHT);
if (!disable_msi && pci_enable_msi(pdev) == 0) {
err = sky2_test_msi(hw);
@@ -4207,6 +4226,8 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
goto err_out_free_netdev;
}
+ netif_napi_add(dev, &hw->napi, sky2_poll, NAPI_WEIGHT);
+
err = request_irq(pdev->irq, sky2_intr,
(hw->flags & SKY2_HW_USE_MSI) ? 0 : IRQF_SHARED,
dev->name, hw);
@@ -4215,6 +4236,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
goto err_out_unregister;
}
sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
+ napi_enable(&hw->napi);
sky2_show_addr(dev);
@@ -4265,23 +4287,18 @@ err_out:
static void __devexit sky2_remove(struct pci_dev *pdev)
{
struct sky2_hw *hw = pci_get_drvdata(pdev);
- struct net_device *dev0, *dev1;
+ int i;
if (!hw)
return;
del_timer_sync(&hw->watchdog_timer);
+ cancel_work_sync(&hw->restart_work);
- flush_scheduled_work();
+ for (i = hw->ports-1; i >= 0; --i)
+ unregister_netdev(hw->dev[i]);
sky2_write32(hw, B0_IMSK, 0);
- synchronize_irq(hw->pdev->irq);
-
- dev0 = hw->dev[0];
- dev1 = hw->dev[1];
- if (dev1)
- unregister_netdev(dev1);
- unregister_netdev(dev0);
sky2_power_aux(hw);
@@ -4296,9 +4313,9 @@ static void __devexit sky2_remove(struct pci_dev *pdev)
pci_release_regions(pdev);
pci_disable_device(pdev);
- if (dev1)
- free_netdev(dev1);
- free_netdev(dev0);
+ for (i = hw->ports-1; i >= 0; --i)
+ free_netdev(hw->dev[i]);
+
iounmap(hw->regs);
kfree(hw);
@@ -4328,6 +4345,7 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state)
}
sky2_write32(hw, B0_IMSK, 0);
+ napi_disable(&hw->napi);
sky2_power_aux(hw);
pci_save_state(pdev);
@@ -4362,8 +4380,8 @@ static int sky2_resume(struct pci_dev *pdev)
pci_write_config_dword(pdev, PCI_DEV_REG3, 0);
sky2_reset(hw);
-
sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
+ napi_enable(&hw->napi);
for (i = 0; i < hw->ports; i++) {
struct net_device *dev = hw->dev[i];
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index 49ee264064ab..69525fd7908d 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -247,7 +247,8 @@ enum csr_regs {
B3_PA_CTRL = 0x01f0,
B3_PA_TEST = 0x01f2,
- Y2_CFG_SPC = 0x1c00,
+ Y2_CFG_SPC = 0x1c00, /* PCI config space region */
+ Y2_CFG_AER = 0x1d00, /* PCI Advanced Error Report region */
};
/* B0_CTST 16 bit Control/Status register */
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
index 335b7cc80eba..251a3ce376ac 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip.c
@@ -1218,14 +1218,8 @@ static int slip_ioctl(struct tty_struct *tty, struct file *file, unsigned int cm
return 0;
/* VSV changes end */
#endif
-
- /* Allow stty to read, but not set, the serial port */
- case TCGETS:
- case TCGETA:
- return n_tty_ioctl(tty, file, cmd, arg);
-
default:
- return -ENOIOCTLCMD;
+ return tty_mode_ioctl(tty, file, cmd, arg);
}
}
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
index 7c60df46fc65..dd18af0ce676 100644
--- a/drivers/net/smc911x.c
+++ b/drivers/net/smc911x.c
@@ -1223,7 +1223,7 @@ static irqreturn_t smc911x_interrupt(int irq, void *dev_id)
}
#endif
- /* Handle PHY interupt condition */
+ /* Handle PHY interrupt condition */
if (status & INT_STS_PHY_INT_) {
DBG(SMC_DEBUG_MISC, "%s: PHY irq\n", dev->name);
smc911x_phy_interrupt(dev);
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index 24e610e711e8..7da7589d45dd 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -173,49 +173,6 @@ MODULE_LICENSE("GPL");
*/
#define MII_DELAY 1
-/* store this information for the driver.. */
-struct smc_local {
- /*
- * If I have to wait until memory is available to send a
- * packet, I will store the skbuff here, until I get the
- * desired memory. Then, I'll send it out and free it.
- */
- struct sk_buff *pending_tx_skb;
- struct tasklet_struct tx_task;
-
- /* version/revision of the SMC91x chip */
- int version;
-
- /* Contains the current active transmission mode */
- int tcr_cur_mode;
-
- /* Contains the current active receive mode */
- int rcr_cur_mode;
-
- /* Contains the current active receive/phy mode */
- int rpc_cur_mode;
- int ctl_rfduplx;
- int ctl_rspeed;
-
- u32 msg_enable;
- u32 phy_type;
- struct mii_if_info mii;
-
- /* work queue */
- struct work_struct phy_configure;
- struct net_device *dev;
- int work_pending;
-
- spinlock_t lock;
-
-#ifdef SMC_USE_PXA_DMA
- /* DMA needs the physical address of the chip */
- u_long physaddr;
-#endif
- void __iomem *base;
- void __iomem *datacs;
-};
-
#if SMC_DEBUG > 0
#define DBG(n, args...) \
do { \
@@ -2215,17 +2172,19 @@ static int smc_drv_probe(struct platform_device *pdev)
goto out_release_attrib;
}
- platform_set_drvdata(pdev, ndev);
- ret = smc_probe(ndev, addr);
- if (ret != 0)
- goto out_iounmap;
#ifdef SMC_USE_PXA_DMA
- else {
+ {
struct smc_local *lp = netdev_priv(ndev);
+ lp->device = &pdev->dev;
lp->physaddr = res->start;
}
#endif
+ platform_set_drvdata(pdev, ndev);
+ ret = smc_probe(ndev, addr);
+ if (ret != 0)
+ goto out_iounmap;
+
smc_request_datacs(pdev, ndev);
return 0;
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index af9e6bf59552..db34e1eb67e9 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -224,6 +224,21 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
}
}
+#elif defined(CONFIG_MACH_ZYLONITE)
+
+#define SMC_CAN_USE_8BIT 1
+#define SMC_CAN_USE_16BIT 1
+#define SMC_CAN_USE_32BIT 0
+#define SMC_IO_SHIFT 0
+#define SMC_NOWAIT 1
+#define SMC_USE_PXA_DMA 1
+#define SMC_inb(a, r) readb((a) + (r))
+#define SMC_inw(a, r) readw((a) + (r))
+#define SMC_insw(a, r, p, l) insw((a) + (r), p, l)
+#define SMC_outsw(a, r, p, l) outsw((a) + (r), p, l)
+#define SMC_outb(v, a, r) writeb(v, (a) + (r))
+#define SMC_outw(v, a, r) writew(v, (a) + (r))
+
#elif defined(CONFIG_ARCH_OMAP)
/* We can only do 16-bit reads and writes in the static memory space. */
@@ -462,6 +477,52 @@ static inline void LPD7_SMC_outsw (unsigned char* a, int r,
#endif
+
+/* store this information for the driver.. */
+struct smc_local {
+ /*
+ * If I have to wait until memory is available to send a
+ * packet, I will store the skbuff here, until I get the
+ * desired memory. Then, I'll send it out and free it.
+ */
+ struct sk_buff *pending_tx_skb;
+ struct tasklet_struct tx_task;
+
+ /* version/revision of the SMC91x chip */
+ int version;
+
+ /* Contains the current active transmission mode */
+ int tcr_cur_mode;
+
+ /* Contains the current active receive mode */
+ int rcr_cur_mode;
+
+ /* Contains the current active receive/phy mode */
+ int rpc_cur_mode;
+ int ctl_rfduplx;
+ int ctl_rspeed;
+
+ u32 msg_enable;
+ u32 phy_type;
+ struct mii_if_info mii;
+
+ /* work queue */
+ struct work_struct phy_configure;
+ struct net_device *dev;
+ int work_pending;
+
+ spinlock_t lock;
+
+#ifdef SMC_USE_PXA_DMA
+ /* DMA needs the physical address of the chip */
+ u_long physaddr;
+ struct device *device;
+#endif
+ void __iomem *base;
+ void __iomem *datacs;
+};
+
+
#ifdef SMC_USE_PXA_DMA
/*
* Let's use the DMA engine on the XScale PXA2xx for RX packets. This is
@@ -476,11 +537,12 @@ static inline void LPD7_SMC_outsw (unsigned char* a, int r,
#ifdef SMC_insl
#undef SMC_insl
#define SMC_insl(a, r, p, l) \
- smc_pxa_dma_insl(a, lp->physaddr, r, dev->dma, p, l)
+ smc_pxa_dma_insl(a, lp, r, dev->dma, p, l)
static inline void
-smc_pxa_dma_insl(void __iomem *ioaddr, u_long physaddr, int reg, int dma,
+smc_pxa_dma_insl(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma,
u_char *buf, int len)
{
+ u_long physaddr = lp->physaddr;
dma_addr_t dmabuf;
/* fallback if no DMA available */
@@ -497,7 +559,7 @@ smc_pxa_dma_insl(void __iomem *ioaddr, u_long physaddr, int reg, int dma,
}
len *= 4;
- dmabuf = dma_map_single(NULL, buf, len, DMA_FROM_DEVICE);
+ dmabuf = dma_map_single(lp->device, buf, len, DMA_FROM_DEVICE);
DCSR(dma) = DCSR_NODESC;
DTADR(dma) = dmabuf;
DSADR(dma) = physaddr + reg;
@@ -507,18 +569,19 @@ smc_pxa_dma_insl(void __iomem *ioaddr, u_long physaddr, int reg, int dma,
while (!(DCSR(dma) & DCSR_STOPSTATE))
cpu_relax();
DCSR(dma) = 0;
- dma_unmap_single(NULL, dmabuf, len, DMA_FROM_DEVICE);
+ dma_unmap_single(lp->device, dmabuf, len, DMA_FROM_DEVICE);
}
#endif
#ifdef SMC_insw
#undef SMC_insw
#define SMC_insw(a, r, p, l) \
- smc_pxa_dma_insw(a, lp->physaddr, r, dev->dma, p, l)
+ smc_pxa_dma_insw(a, lp, r, dev->dma, p, l)
static inline void
-smc_pxa_dma_insw(void __iomem *ioaddr, u_long physaddr, int reg, int dma,
+smc_pxa_dma_insw(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma,
u_char *buf, int len)
{
+ u_long physaddr = lp->physaddr;
dma_addr_t dmabuf;
/* fallback if no DMA available */
@@ -535,7 +598,7 @@ smc_pxa_dma_insw(void __iomem *ioaddr, u_long physaddr, int reg, int dma,
}
len *= 2;
- dmabuf = dma_map_single(NULL, buf, len, DMA_FROM_DEVICE);
+ dmabuf = dma_map_single(lp->device, buf, len, DMA_FROM_DEVICE);
DCSR(dma) = DCSR_NODESC;
DTADR(dma) = dmabuf;
DSADR(dma) = physaddr + reg;
@@ -545,7 +608,7 @@ smc_pxa_dma_insw(void __iomem *ioaddr, u_long physaddr, int reg, int dma,
while (!(DCSR(dma) & DCSR_STOPSTATE))
cpu_relax();
DCSR(dma) = 0;
- dma_unmap_single(NULL, dmabuf, len, DMA_FROM_DEVICE);
+ dma_unmap_single(lp->device, dmabuf, len, DMA_FROM_DEVICE);
}
#endif
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index fab055ffcc90..bccae7e5c6ad 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -46,7 +46,7 @@
#include <linux/vmalloc.h>
#include <linux/wait.h>
#include <linux/workqueue.h>
-#include <asm/bitops.h>
+#include <linux/bitops.h>
#include <asm/pci-bridge.h>
#include <net/checksum.h>
@@ -1639,7 +1639,7 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
/**
* spider_net_interrupt - interrupt handler for spider_net
- * @irq: interupt number
+ * @irq: interrupt number
* @ptr: pointer to net_device
* @regs: PU registers
*
diff --git a/drivers/net/spider_net.h b/drivers/net/spider_net.h
index a897beee7d5d..e1d05c0f47eb 100644
--- a/drivers/net/spider_net.h
+++ b/drivers/net/spider_net.h
@@ -494,7 +494,4 @@ struct spider_net_card {
struct spider_net_descr darray[0];
};
-#define pr_err(fmt,arg...) \
- printk(KERN_ERR fmt ,##arg)
-
#endif
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index 53b8344a68ef..f6fedcc32de1 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -2333,10 +2333,10 @@ static int gem_close(struct net_device *dev)
{
struct gem *gp = dev->priv;
- napi_disable(&gp->napi);
-
mutex_lock(&gp->pm_mutex);
+ napi_disable(&gp->napi);
+
gp->opened = 0;
if (!gp->asleep)
gem_do_stop(dev, 0);
@@ -2355,8 +2355,6 @@ static int gem_suspend(struct pci_dev *pdev, pm_message_t state)
mutex_lock(&gp->pm_mutex);
- napi_disable(&gp->napi);
-
printk(KERN_INFO "%s: suspending, WakeOnLan %s\n",
dev->name,
(gp->wake_on_lan && gp->opened) ? "enabled" : "disabled");
@@ -2370,6 +2368,8 @@ static int gem_suspend(struct pci_dev *pdev, pm_message_t state)
/* If the driver is opened, we stop the MAC */
if (gp->opened) {
+ napi_disable(&gp->napi);
+
/* Stop traffic, mark us closed */
netif_device_detach(dev);
@@ -2460,6 +2460,7 @@ static int gem_resume(struct pci_dev *pdev)
/* Re-attach net device */
netif_device_attach(dev);
+ napi_enable(&gp->napi);
}
spin_lock_irqsave(&gp->lock, flags);
@@ -2479,8 +2480,6 @@ static int gem_resume(struct pci_dev *pdev)
spin_unlock(&gp->tx_lock);
spin_unlock_irqrestore(&gp->lock, flags);
- napi_enable(&gp->napi);
-
mutex_unlock(&gp->pm_mutex);
return 0;
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index 120c8affe83d..9cc13dd8a821 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -1281,7 +1281,7 @@ static void happy_meal_init_rings(struct happy_meal *hp)
skb->dev = dev;
/* Because we reserve afterwards. */
- skb_put(skb, (ETH_FRAME_LEN + RX_OFFSET));
+ skb_put(skb, (ETH_FRAME_LEN + RX_OFFSET + 4));
hme_write_rxd(hp, &hb->happy_meal_rxd[i],
(RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16)),
hme_dma_map(hp, skb->data, RX_BUF_ALLOC_SIZE, DMA_FROMDEVICE));
@@ -1700,6 +1700,11 @@ static int happy_meal_init(struct happy_meal *hp)
HMD(("tx old[%08x] and rx [%08x] ON!\n",
hme_read32(hp, bregs + BMAC_TXCFG),
hme_read32(hp, bregs + BMAC_RXCFG)));
+
+ /* Set larger TX/RX size to allow for 802.1q */
+ hme_write32(hp, bregs + BMAC_TXMAX, ETH_FRAME_LEN + 8);
+ hme_write32(hp, bregs + BMAC_RXMAX, ETH_FRAME_LEN + 8);
+
hme_write32(hp, bregs + BMAC_TXCFG,
hme_read32(hp, bregs + BMAC_TXCFG) | BIGMAC_TXCFG_ENABLE);
hme_write32(hp, bregs + BMAC_RXCFG,
@@ -2039,7 +2044,7 @@ static void happy_meal_rx(struct happy_meal *hp, struct net_device *dev)
hme_dma_unmap(hp, dma_addr, RX_BUF_ALLOC_SIZE, DMA_FROMDEVICE);
hp->rx_skbs[elem] = new_skb;
new_skb->dev = dev;
- skb_put(new_skb, (ETH_FRAME_LEN + RX_OFFSET));
+ skb_put(new_skb, (ETH_FRAME_LEN + RX_OFFSET + 4));
hme_write_rxd(hp, this,
(RXFLAG_OWN|((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)),
hme_dma_map(hp, new_skb->data, RX_BUF_ALLOC_SIZE, DMA_FROMDEVICE));
@@ -2809,8 +2814,8 @@ static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe
dev->watchdog_timeo = 5*HZ;
dev->ethtool_ops = &hme_ethtool_ops;
- /* Happy Meal can do it all... except VLAN. */
- dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_VLAN_CHALLENGED;
+ /* Happy Meal can do it all... */
+ dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM;
dev->irq = sdev->irqs[0];
diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c
index a679f4310ce1..d887c05588d5 100644
--- a/drivers/net/tc35815.c
+++ b/drivers/net/tc35815.c
@@ -1461,7 +1461,6 @@ static irqreturn_t tc35815_interrupt(int irq, void *dev_id)
}
return IRQ_NONE;
#else
- struct tc35815_local *lp = dev->priv;
int handled;
u32 status;
@@ -1655,7 +1654,7 @@ tc35815_rx(struct net_device *dev)
panic_queues(dev);
}
#endif
- /* pass BD to controler */
+ /* pass BD to controller */
#ifndef TC35815_USE_PACKEDBUFFER
if (!lp->rx_skbs[curid].skb) {
lp->rx_skbs[curid].skb =
@@ -1695,7 +1694,7 @@ tc35815_rx(struct net_device *dev)
}
#endif
for (i = 0; i < (bd_count + 1) / 2 + 1; i++) {
- /* pass FD to controler */
+ /* pass FD to controller */
#ifdef DEBUG
lp->rfd_cur->fd.FDNext = cpu_to_le32(0xdeaddead);
#else
diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c
index 8d04654f0c59..21230c97b2a0 100644
--- a/drivers/net/tehuti.c
+++ b/drivers/net/tehuti.c
@@ -1906,7 +1906,7 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/************** pci *****************/
if ((err = pci_enable_device(pdev))) /* it trigers interrupt, dunno why. */
- RET(err); /* it's not a problem though */
+ goto err_pci; /* it's not a problem though */
if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK)) &&
!(err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))) {
@@ -2076,6 +2076,7 @@ err_out_res:
pci_release_regions(pdev);
err_dma:
pci_disable_device(pdev);
+err_pci:
vfree(nic);
RET(err);
@@ -2167,10 +2168,10 @@ bdx_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
{
struct bdx_priv *priv = netdev->priv;
- strncat(drvinfo->driver, BDX_DRV_NAME, sizeof(drvinfo->driver));
- strncat(drvinfo->version, BDX_DRV_VERSION, sizeof(drvinfo->version));
- strncat(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
- strncat(drvinfo->bus_info, pci_name(priv->pdev),
+ strlcat(drvinfo->driver, BDX_DRV_NAME, sizeof(drvinfo->driver));
+ strlcat(drvinfo->version, BDX_DRV_VERSION, sizeof(drvinfo->version));
+ strlcat(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
+ strlcat(drvinfo->bus_info, pci_name(priv->pdev),
sizeof(drvinfo->bus_info));
drvinfo->n_stats = ((priv->stats_flag) ?
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 30b1cca8144c..4942f7d18937 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -64,8 +64,8 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "3.83"
-#define DRV_MODULE_RELDATE "October 10, 2007"
+#define DRV_MODULE_VERSION "3.86"
+#define DRV_MODULE_RELDATE "November 9, 2007"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
@@ -200,6 +200,7 @@ static struct pci_device_id tg3_pci_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5906M)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5784)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5764)},
+ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5723)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5761)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5761E)},
{PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX)},
@@ -1105,6 +1106,24 @@ static int tg3_phy_reset(struct tg3 *tp)
if (err)
return err;
+ if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) {
+ u32 val;
+
+ val = tr32(TG3_CPMU_LSPD_1000MB_CLK);
+ if ((val & CPMU_LSPD_1000MB_MACCLK_MASK) ==
+ CPMU_LSPD_1000MB_MACCLK_12_5) {
+ val &= ~CPMU_LSPD_1000MB_MACCLK_MASK;
+ udelay(40);
+ tw32_f(TG3_CPMU_LSPD_1000MB_CLK, val);
+ }
+
+ /* Disable GPHY autopowerdown. */
+ tg3_writephy(tp, MII_TG3_MISC_SHDW,
+ MII_TG3_MISC_SHDW_WREN |
+ MII_TG3_MISC_SHDW_APD_SEL |
+ MII_TG3_MISC_SHDW_APD_WKTM_84MS);
+ }
+
out:
if (tp->tg3_flags2 & TG3_FLG2_PHY_ADC_BUG) {
tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
@@ -1296,6 +1315,8 @@ static void tg3_nvram_unlock(struct tg3 *);
static void tg3_power_down_phy(struct tg3 *tp)
{
+ u32 val;
+
if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
u32 sg_dig_ctrl = tr32(SG_DIG_CTRL);
@@ -1310,8 +1331,6 @@ static void tg3_power_down_phy(struct tg3 *tp)
}
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
- u32 val;
-
tg3_bmcr_reset(tp);
val = tr32(GRC_MISC_CFG);
tw32_f(GRC_MISC_CFG, val | GRC_MISC_CFG_EPHY_IDDQ);
@@ -1331,6 +1350,14 @@ static void tg3_power_down_phy(struct tg3 *tp)
(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 &&
(tp->tg3_flags2 & TG3_FLG2_MII_SERDES)))
return;
+
+ if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) {
+ val = tr32(TG3_CPMU_LSPD_1000MB_CLK);
+ val &= ~CPMU_LSPD_1000MB_MACCLK_MASK;
+ val |= CPMU_LSPD_1000MB_MACCLK_12_5;
+ tw32_f(TG3_CPMU_LSPD_1000MB_CLK, val);
+ }
+
tg3_writephy(tp, MII_BMCR, BMCR_PDOWN);
}
@@ -3125,6 +3152,23 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset)
err = tg3_setup_copper_phy(tp, force_reset);
}
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5784_A1) {
+ u32 val, scale;
+
+ val = tr32(TG3_CPMU_CLCK_STAT) & CPMU_CLCK_STAT_MAC_CLCK_MASK;
+ if (val == CPMU_CLCK_STAT_MAC_CLCK_62_5)
+ scale = 65;
+ else if (val == CPMU_CLCK_STAT_MAC_CLCK_6_25)
+ scale = 6;
+ else
+ scale = 12;
+
+ val = tr32(GRC_MISC_CFG) & ~GRC_MISC_CFG_PRESCALAR_MASK;
+ val |= (scale << GRC_MISC_CFG_PRESCALAR_SHIFT);
+ tw32(GRC_MISC_CFG, val);
+ }
+
if (tp->link_config.active_speed == SPEED_1000 &&
tp->link_config.active_duplex == DUPLEX_HALF)
tw32(MAC_TX_LENGTHS,
@@ -5028,10 +5072,7 @@ static int tg3_poll_fw(struct tg3 *tp)
/* Save PCI command register before chip reset */
static void tg3_save_pci_state(struct tg3 *tp)
{
- u32 val;
-
- pci_read_config_dword(tp->pdev, TG3PCI_COMMAND, &val);
- tp->pci_cmd = val;
+ pci_read_config_word(tp->pdev, PCI_COMMAND, &tp->pci_cmd);
}
/* Restore PCI state after chip reset */
@@ -5054,7 +5095,16 @@ static void tg3_restore_pci_state(struct tg3 *tp)
PCISTATE_ALLOW_APE_SHMEM_WR;
pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val);
- pci_write_config_dword(tp->pdev, TG3PCI_COMMAND, tp->pci_cmd);
+ pci_write_config_word(tp->pdev, PCI_COMMAND, tp->pci_cmd);
+
+ if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)
+ pcie_set_readrq(tp->pdev, 4096);
+ else {
+ pci_write_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE,
+ tp->pci_cacheline_sz);
+ pci_write_config_byte(tp->pdev, PCI_LATENCY_TIMER,
+ tp->pci_lat_timer);
+ }
/* Make sure PCI-X relaxed ordering bit is clear. */
if (tp->pcix_cap) {
@@ -6339,10 +6389,26 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
tg3_write_sig_legacy(tp, RESET_KIND_INIT);
- if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0) {
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5784_A1) {
val = tr32(TG3_CPMU_CTRL);
val &= ~(CPMU_CTRL_LINK_AWARE_MODE | CPMU_CTRL_LINK_IDLE_MODE);
tw32(TG3_CPMU_CTRL, val);
+
+ val = tr32(TG3_CPMU_LSPD_10MB_CLK);
+ val &= ~CPMU_LSPD_10MB_MACCLK_MASK;
+ val |= CPMU_LSPD_10MB_MACCLK_6_25;
+ tw32(TG3_CPMU_LSPD_10MB_CLK, val);
+
+ val = tr32(TG3_CPMU_LNK_AWARE_PWRMD);
+ val &= ~CPMU_LNK_AWARE_MACCLK_MASK;
+ val |= CPMU_LNK_AWARE_MACCLK_6_25;
+ tw32(TG3_CPMU_LNK_AWARE_PWRMD, val);
+
+ val = tr32(TG3_CPMU_HST_ACC);
+ val &= ~CPMU_HST_ACC_MACCLK_MASK;
+ val |= CPMU_HST_ACC_MACCLK_6_25;
+ tw32(TG3_CPMU_HST_ACC, val);
}
/* This works around an issue with Athlon chipsets on
@@ -7361,10 +7427,6 @@ static int tg3_open(struct net_device *dev)
} else if (pci_enable_msi(tp->pdev) == 0) {
u32 msi_mode;
- /* Hardware bug - MSI won't work if INTX disabled. */
- if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)
- pci_intx(tp->pdev, 1);
-
msi_mode = tr32(MSGINT_MODE);
tw32(MSGINT_MODE, msi_mode | MSGINT_MODE_ENABLE);
tp->tg3_flags2 |= TG3_FLG2_USING_MSI;
@@ -8267,7 +8329,7 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
SUPPORTED_100baseT_Full |
SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
- SUPPORTED_MII);
+ SUPPORTED_TP);
cmd->port = PORT_TP;
} else {
cmd->supported |= SUPPORTED_FIBRE;
@@ -8664,7 +8726,9 @@ static void tg3_get_ethtool_stats (struct net_device *dev,
}
#define NVRAM_TEST_SIZE 0x100
-#define NVRAM_SELFBOOT_FORMAT1_SIZE 0x14
+#define NVRAM_SELFBOOT_FORMAT1_0_SIZE 0x14
+#define NVRAM_SELFBOOT_FORMAT1_2_SIZE 0x18
+#define NVRAM_SELFBOOT_FORMAT1_3_SIZE 0x1c
#define NVRAM_SELFBOOT_HW_SIZE 0x20
#define NVRAM_SELFBOOT_DATA_SIZE 0x1c
@@ -8679,9 +8743,22 @@ static int tg3_test_nvram(struct tg3 *tp)
if (magic == TG3_EEPROM_MAGIC)
size = NVRAM_TEST_SIZE;
else if ((magic & TG3_EEPROM_MAGIC_FW_MSK) == TG3_EEPROM_MAGIC_FW) {
- if ((magic & 0xe00000) == 0x200000)
- size = NVRAM_SELFBOOT_FORMAT1_SIZE;
- else
+ if ((magic & TG3_EEPROM_SB_FORMAT_MASK) ==
+ TG3_EEPROM_SB_FORMAT_1) {
+ switch (magic & TG3_EEPROM_SB_REVISION_MASK) {
+ case TG3_EEPROM_SB_REVISION_0:
+ size = NVRAM_SELFBOOT_FORMAT1_0_SIZE;
+ break;
+ case TG3_EEPROM_SB_REVISION_2:
+ size = NVRAM_SELFBOOT_FORMAT1_2_SIZE;
+ break;
+ case TG3_EEPROM_SB_REVISION_3:
+ size = NVRAM_SELFBOOT_FORMAT1_3_SIZE;
+ break;
+ default:
+ return 0;
+ }
+ } else
return 0;
} else if ((magic & TG3_EEPROM_MAGIC_HW_MSK) == TG3_EEPROM_MAGIC_HW)
size = NVRAM_SELFBOOT_HW_SIZE;
@@ -8708,8 +8785,17 @@ static int tg3_test_nvram(struct tg3 *tp)
TG3_EEPROM_MAGIC_FW) {
u8 *buf8 = (u8 *) buf, csum8 = 0;
- for (i = 0; i < size; i++)
- csum8 += buf8[i];
+ if ((cpu_to_be32(buf[0]) & TG3_EEPROM_SB_REVISION_MASK) ==
+ TG3_EEPROM_SB_REVISION_2) {
+ /* For rev 2, the csum doesn't include the MBA. */
+ for (i = 0; i < TG3_EEPROM_SB_F1R2_MBA_OFF; i++)
+ csum8 += buf8[i];
+ for (i = TG3_EEPROM_SB_F1R2_MBA_OFF + 4; i < size; i++)
+ csum8 += buf8[i];
+ } else {
+ for (i = 0; i < size; i++)
+ csum8 += buf8[i];
+ }
if (csum8 == 0) {
err = 0;
@@ -9034,7 +9120,7 @@ static int tg3_do_mem_test(struct tg3 *tp, u32 offset, u32 len)
int i;
u32 j;
- for (i = 0; i < sizeof(test_pattern)/sizeof(u32); i++) {
+ for (i = 0; i < ARRAY_SIZE(test_pattern); i++) {
for (j = 0; j < len; j += 4) {
u32 val;
@@ -9293,7 +9379,7 @@ static int tg3_test_loopback(struct tg3 *tp)
if (err)
return TG3_LOOPBACK_FAILED;
- if (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) {
+ if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) {
int i;
u32 status;
@@ -9310,17 +9396,17 @@ static int tg3_test_loopback(struct tg3 *tp)
if (status != CPMU_MUTEX_GNT_DRIVER)
return TG3_LOOPBACK_FAILED;
- cpmuctrl = tr32(TG3_CPMU_CTRL);
-
/* Turn off power management based on link speed. */
+ cpmuctrl = tr32(TG3_CPMU_CTRL);
tw32(TG3_CPMU_CTRL,
- cpmuctrl & ~CPMU_CTRL_LINK_SPEED_MODE);
+ cpmuctrl & ~(CPMU_CTRL_LINK_SPEED_MODE |
+ CPMU_CTRL_LINK_AWARE_MODE));
}
if (tg3_run_loopback(tp, TG3_MAC_LOOPBACK))
err |= TG3_MAC_LOOPBACK_FAILED;
- if (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) {
+ if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) {
tw32(TG3_CPMU_CTRL, cpmuctrl);
/* Release the mutex */
@@ -10541,6 +10627,10 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL)
tp->led_ctrl = LED_CTRL_MODE_PHY_2;
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5784_A1)
+ tp->led_ctrl = LED_CTRL_MODE_MAC;
+
if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP) {
tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
if ((tp->pdev->subsystem_vendor ==
@@ -10814,9 +10904,24 @@ out_not_found:
strcpy(tp->board_part_number, "none");
}
+static int __devinit tg3_fw_img_is_valid(struct tg3 *tp, u32 offset)
+{
+ u32 val;
+
+ if (tg3_nvram_read_swab(tp, offset, &val) ||
+ (val & 0xfc000000) != 0x0c000000 ||
+ tg3_nvram_read_swab(tp, offset + 4, &val) ||
+ val != 0)
+ return 0;
+
+ return 1;
+}
+
static void __devinit tg3_read_fw_ver(struct tg3 *tp)
{
u32 val, offset, start;
+ u32 ver_offset;
+ int i, bcnt;
if (tg3_nvram_read_swab(tp, 0, &val))
return;
@@ -10829,29 +10934,71 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp)
return;
offset = tg3_nvram_logical_addr(tp, offset);
- if (tg3_nvram_read_swab(tp, offset, &val))
+
+ if (!tg3_fw_img_is_valid(tp, offset) ||
+ tg3_nvram_read_swab(tp, offset + 8, &ver_offset))
return;
- if ((val & 0xfc000000) == 0x0c000000) {
- u32 ver_offset, addr;
- int i;
+ offset = offset + ver_offset - start;
+ for (i = 0; i < 16; i += 4) {
+ if (tg3_nvram_read(tp, offset + i, &val))
+ return;
+
+ val = le32_to_cpu(val);
+ memcpy(tp->fw_ver + i, &val, 4);
+ }
- if (tg3_nvram_read_swab(tp, offset + 4, &val) ||
- tg3_nvram_read_swab(tp, offset + 8, &ver_offset))
+ if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) ||
+ (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE))
+ return;
+
+ for (offset = TG3_NVM_DIR_START;
+ offset < TG3_NVM_DIR_END;
+ offset += TG3_NVM_DIRENT_SIZE) {
+ if (tg3_nvram_read_swab(tp, offset, &val))
return;
- if (val != 0)
+ if ((val >> TG3_NVM_DIRTYPE_SHIFT) == TG3_NVM_DIRTYPE_ASFINI)
+ break;
+ }
+
+ if (offset == TG3_NVM_DIR_END)
+ return;
+
+ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
+ start = 0x08000000;
+ else if (tg3_nvram_read_swab(tp, offset - 4, &start))
+ return;
+
+ if (tg3_nvram_read_swab(tp, offset + 4, &offset) ||
+ !tg3_fw_img_is_valid(tp, offset) ||
+ tg3_nvram_read_swab(tp, offset + 8, &val))
+ return;
+
+ offset += val - start;
+
+ bcnt = strlen(tp->fw_ver);
+
+ tp->fw_ver[bcnt++] = ',';
+ tp->fw_ver[bcnt++] = ' ';
+
+ for (i = 0; i < 4; i++) {
+ if (tg3_nvram_read(tp, offset, &val))
return;
- addr = offset + ver_offset - start;
- for (i = 0; i < 16; i += 4) {
- if (tg3_nvram_read(tp, addr + i, &val))
- return;
+ val = le32_to_cpu(val);
+ offset += sizeof(val);
- val = cpu_to_le32(val);
- memcpy(tp->fw_ver + i, &val, 4);
+ if (bcnt > TG3_VER_SIZE - sizeof(val)) {
+ memcpy(&tp->fw_ver[bcnt], &val, TG3_VER_SIZE - bcnt);
+ break;
}
+
+ memcpy(&tp->fw_ver[bcnt], &val, sizeof(val));
+ bcnt += sizeof(val);
}
+
+ tp->fw_ver[TG3_VER_SIZE - 1] = 0;
}
static struct pci_dev * __devinit tg3_find_peer(struct tg3 *);
@@ -11070,6 +11217,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
pcie_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_EXP);
if (pcie_cap != 0) {
tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS;
+
+ pcie_set_readrq(tp->pdev, 4096);
+
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
u16 lnkctl;
@@ -11250,9 +11400,16 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
}
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) {
tp->tg3_flags |= TG3_FLAG_CPMU_PRESENT;
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5784_A1 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5761_A0 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5761_A1)
+ tp->tg3_flags3 |= TG3_FLG3_5761_5784_AX_FIXES;
+ }
+
/* Set up tp->grc_local_ctrl before calling tg3_set_power_state().
* GPIO1 driven high will bring 5700's external PHY out of reset.
* It is also used as eeprom write protect on LOMs.
@@ -12407,6 +12564,28 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
goto err_out_iounmap;
}
+ if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
+ if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) {
+ printk(KERN_ERR PFX "Cannot find proper PCI device "
+ "base address for APE, aborting.\n");
+ err = -ENODEV;
+ goto err_out_iounmap;
+ }
+
+ tg3reg_base = pci_resource_start(pdev, 2);
+ tg3reg_len = pci_resource_len(pdev, 2);
+
+ tp->aperegs = ioremap_nocache(tg3reg_base, tg3reg_len);
+ if (tp->aperegs == 0UL) {
+ printk(KERN_ERR PFX "Cannot map APE registers, "
+ "aborting.\n");
+ err = -ENOMEM;
+ goto err_out_iounmap;
+ }
+
+ tg3_ape_lock_init(tp);
+ }
+
/*
* Reset chip in case UNDI or EFI driver did not shutdown
* DMA self test will enable WDMAC and we'll see (spurious)
@@ -12421,7 +12600,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
err = tg3_test_dma(tp);
if (err) {
printk(KERN_ERR PFX "DMA engine test failed, aborting.\n");
- goto err_out_iounmap;
+ goto err_out_apeunmap;
}
/* Tigon3 can do ipv4 only... and some chips have buggy
@@ -12444,28 +12623,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
tg3_init_coal(tp);
- if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
- if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) {
- printk(KERN_ERR PFX "Cannot find proper PCI device "
- "base address for APE, aborting.\n");
- err = -ENODEV;
- goto err_out_iounmap;
- }
-
- tg3reg_base = pci_resource_start(pdev, 2);
- tg3reg_len = pci_resource_len(pdev, 2);
-
- tp->aperegs = ioremap_nocache(tg3reg_base, tg3reg_len);
- if (tp->aperegs == 0UL) {
- printk(KERN_ERR PFX "Cannot map APE registers, "
- "aborting.\n");
- err = -ENOMEM;
- goto err_out_iounmap;
- }
-
- tg3_ape_lock_init(tp);
- }
-
pci_set_drvdata(pdev, dev);
err = register_netdev(dev);
@@ -12620,11 +12777,6 @@ static int tg3_resume(struct pci_dev *pdev)
if (err)
return err;
- /* Hardware bug - MSI won't work if INTX disabled. */
- if ((tp->tg3_flags2 & TG3_FLG2_5780_CLASS) &&
- (tp->tg3_flags2 & TG3_FLG2_USING_MSI))
- pci_intx(tp->pdev, 1);
-
netif_device_attach(dev);
tg3_full_lock(tp, 0);
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 6dbdad2b8f88..da18fb220712 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -109,6 +109,9 @@
#define CHIPREV_ID_5714_A2 0x9002
#define CHIPREV_ID_5906_A1 0xc001
#define CHIPREV_ID_5784_A0 0x5784000
+#define CHIPREV_ID_5784_A1 0x5784001
+#define CHIPREV_ID_5761_A0 0x5761000
+#define CHIPREV_ID_5761_A1 0x5761001
#define GET_ASIC_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 12)
#define ASIC_REV_5700 0x07
#define ASIC_REV_5701 0x00
@@ -856,7 +859,31 @@
#define CPMU_CTRL_LINK_IDLE_MODE 0x00000200
#define CPMU_CTRL_LINK_AWARE_MODE 0x00000400
#define CPMU_CTRL_LINK_SPEED_MODE 0x00004000
-/* 0x3604 --> 0x365c unused */
+#define TG3_CPMU_LSPD_10MB_CLK 0x00003604
+#define CPMU_LSPD_10MB_MACCLK_MASK 0x001f0000
+#define CPMU_LSPD_10MB_MACCLK_6_25 0x00130000
+/* 0x3608 --> 0x360c unused */
+
+#define TG3_CPMU_LSPD_1000MB_CLK 0x0000360c
+#define CPMU_LSPD_1000MB_MACCLK_62_5 0x00000000
+#define CPMU_LSPD_1000MB_MACCLK_12_5 0x00110000
+#define CPMU_LSPD_1000MB_MACCLK_MASK 0x001f0000
+#define TG3_CPMU_LNK_AWARE_PWRMD 0x00003610
+#define CPMU_LNK_AWARE_MACCLK_MASK 0x001f0000
+#define CPMU_LNK_AWARE_MACCLK_6_25 0x00130000
+/* 0x3614 --> 0x361c unused */
+
+#define TG3_CPMU_HST_ACC 0x0000361c
+#define CPMU_HST_ACC_MACCLK_MASK 0x001f0000
+#define CPMU_HST_ACC_MACCLK_6_25 0x00130000
+/* 0x3620 --> 0x3630 unused */
+
+#define TG3_CPMU_CLCK_STAT 0x00003630
+#define CPMU_CLCK_STAT_MAC_CLCK_MASK 0x001f0000
+#define CPMU_CLCK_STAT_MAC_CLCK_62_5 0x00000000
+#define CPMU_CLCK_STAT_MAC_CLCK_12_5 0x00110000
+#define CPMU_CLCK_STAT_MAC_CLCK_6_25 0x00130000
+/* 0x3634 --> 0x365c unused */
#define TG3_CPMU_MUTEX_REQ 0x0000365c
#define CPMU_MUTEX_REQ_DRIVER 0x00001000
@@ -1537,9 +1564,21 @@
#define TG3_EEPROM_MAGIC 0x669955aa
#define TG3_EEPROM_MAGIC_FW 0xa5000000
#define TG3_EEPROM_MAGIC_FW_MSK 0xff000000
+#define TG3_EEPROM_SB_FORMAT_MASK 0x00e00000
+#define TG3_EEPROM_SB_FORMAT_1 0x00200000
+#define TG3_EEPROM_SB_REVISION_MASK 0x001f0000
+#define TG3_EEPROM_SB_REVISION_0 0x00000000
+#define TG3_EEPROM_SB_REVISION_2 0x00020000
+#define TG3_EEPROM_SB_REVISION_3 0x00030000
#define TG3_EEPROM_MAGIC_HW 0xabcd
#define TG3_EEPROM_MAGIC_HW_MSK 0xffff
+#define TG3_NVM_DIR_START 0x18
+#define TG3_NVM_DIR_END 0x78
+#define TG3_NVM_DIRENT_SIZE 0xc
+#define TG3_NVM_DIRTYPE_SHIFT 24
+#define TG3_NVM_DIRTYPE_ASFINI 1
+
/* 32K Window into NIC internal memory */
#define NIC_SRAM_WIN_BASE 0x00008000
@@ -1685,6 +1724,12 @@
#define MII_TG3_ISTAT 0x1a /* IRQ status register */
#define MII_TG3_IMASK 0x1b /* IRQ mask register */
+#define MII_TG3_MISC_SHDW 0x1c
+#define MII_TG3_MISC_SHDW_WREN 0x8000
+#define MII_TG3_MISC_SHDW_APD_SEL 0x2800
+
+#define MII_TG3_MISC_SHDW_APD_WKTM_84MS 0x0001
+
/* ISTAT/IMASK event bits */
#define MII_TG3_INT_LINKCHG 0x0002
#define MII_TG3_INT_SPEEDCHG 0x0004
@@ -1741,6 +1786,8 @@
/* APE convenience enumerations. */
#define TG3_APE_LOCK_MEM 4
+#define TG3_EEPROM_SB_F1R2_MBA_OFF 0x10
+
/* There are two ways to manage the TX descriptors on the tigon3.
* Either the descriptors are in host DMA'able memory, or they
@@ -2346,6 +2393,7 @@ struct tg3 {
u32 tg3_flags3;
#define TG3_FLG3_NO_NVRAM_ADDR_TRANS 0x00000001
#define TG3_FLG3_ENABLE_APE 0x00000002
+#define TG3_FLG3_5761_5784_AX_FIXES 0x00000004
struct timer_list timer;
u16 timer_counter;
@@ -2415,10 +2463,11 @@ struct tg3 {
#define PHY_REV_BCM5411_X0 0x1 /* Found on Netgear GA302T */
u32 led_ctrl;
- u32 pci_cmd;
+ u16 pci_cmd;
char board_part_number[24];
- char fw_ver[16];
+#define TG3_VER_SIZE 32
+ char fw_ver[TG3_VER_SIZE];
u32 nic_sram_data_cfg;
u32 pci_clock_ctrl;
struct pci_dev *pdev_peer;
diff --git a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c
index 7224d368b2a7..5d31519a6c67 100644
--- a/drivers/net/tokenring/3c359.c
+++ b/drivers/net/tokenring/3c359.c
@@ -760,7 +760,7 @@ static int xl_open_hw(struct net_device *dev)
if (xl_priv->xl_laa[0]) { /* If using a LAA address */
for (i=10;i<16;i++) {
writel( (MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb) + i, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
- writeb(xl_priv->xl_laa[i],xl_mmio + MMIO_MACDATA) ;
+ writeb(xl_priv->xl_laa[i-10],xl_mmio + MMIO_MACDATA) ;
}
memcpy(dev->dev_addr,xl_priv->xl_laa,dev->addr_len) ;
} else { /* Regular hardware address */
diff --git a/drivers/net/tsi108_eth.c b/drivers/net/tsi108_eth.c
index df10af7df7b8..35d15e850075 100644
--- a/drivers/net/tsi108_eth.c
+++ b/drivers/net/tsi108_eth.c
@@ -1629,7 +1629,7 @@ tsi108_init_one(struct platform_device *pdev)
goto register_fail;
}
- printk(KERN_INFO "%s: Tsi108 Gigabit Ethernet, MAC: %s\n"
+ printk(KERN_INFO "%s: Tsi108 Gigabit Ethernet, MAC: %s\n",
dev->name, print_mac(mac, dev->dev_addr));
#ifdef DEBUG
data->msg_enable = DEBUG;
diff --git a/drivers/net/tulip/Kconfig b/drivers/net/tulip/Kconfig
index 1c537d5a3062..20ac1503021e 100644
--- a/drivers/net/tulip/Kconfig
+++ b/drivers/net/tulip/Kconfig
@@ -24,8 +24,7 @@ config DE2104X
will say Y here.) Do read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called de2104x.
config TULIP
@@ -42,8 +41,7 @@ config TULIP
will say Y here.) Do read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called tulip.
config TULIP_MWI
@@ -67,7 +65,7 @@ config TULIP_MMIO
If in doubt, say N.
config TULIP_NAPI
- bool "Use NAPI RX polling "
+ bool "Use RX polling (NAPI)"
depends on TULIP
help
NAPI is a new driver API designed to reduce CPU and interrupt load
@@ -78,18 +76,16 @@ config TULIP_NAPI
deployed on potentially unfriendly networks (e.g. in a firewall),
then say Y here.
- See <file:Documentation/networking/NAPI_HOWTO.txt> for more
- information.
-
If in doubt, say N.
config TULIP_NAPI_HW_MITIGATION
- bool "Use Interrupt Mitigation "
+ bool "Use Interrupt Mitigation"
depends on TULIP_NAPI
---help---
- Use HW to reduce RX interrupts. Not strict necessary since NAPI reduces
- RX interrupts but itself. Although this reduces RX interrupts even at
- low levels traffic at the cost of a small latency.
+ Use HW to reduce RX interrupts. Not strictly necessary since NAPI
+ reduces RX interrupts by itself. Interrupt mitigation reduces RX
+ interrupts even at low levels of traffic at the cost of a small
+ latency.
If in doubt, say Y.
@@ -106,8 +102,7 @@ config DE4X5
information is contained in
<file:Documentation/networking/de4x5.txt>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called de4x5.
config WINBOND_840
@@ -131,8 +126,7 @@ config DM9102
(Ethernet) card, say Y. Some information is contained in the file
<file:Documentation/networking/dmfe.txt>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called dmfe.
config ULI526X
@@ -143,8 +137,7 @@ config ULI526X
This driver is for ULi M5261/M5263 10/100M Ethernet Controller
(<http://www.uli.com.tw/>).
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called uli526x.
config PCMCIA_XIRCOM
@@ -156,8 +149,7 @@ config PCMCIA_XIRCOM
as with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and
ASIX.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called xircom_cb. If unsure, say N.
config PCMCIA_XIRTULIP
@@ -170,8 +162,7 @@ config PCMCIA_XIRTULIP
as with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and
ASIX.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called xircom_tulip_cb. If unsure, say N.
endif # NET_TULIP
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
index 9b9cd83fb8b6..41f34bb91cad 100644
--- a/drivers/net/tulip/de4x5.c
+++ b/drivers/net/tulip/de4x5.c
@@ -1041,7 +1041,7 @@ static struct InfoLeaf infoleaf_array[] = {
{DC21142, dc21142_infoleaf},
{DC21143, dc21143_infoleaf}
};
-#define INFOLEAF_SIZE (sizeof(infoleaf_array)/(sizeof(int)+sizeof(int *)))
+#define INFOLEAF_SIZE ARRAY_SIZE(infoleaf_array)
/*
** List the SROM info block functions
@@ -1056,7 +1056,7 @@ static int (*dc_infoblock[])(struct net_device *dev, u_char, u_char *) = {
compact_infoblock
};
-#define COMPACT (sizeof(dc_infoblock)/sizeof(int *) - 1)
+#define COMPACT (ARRAY_SIZE(dc_infoblock) - 1)
/*
** Miscellaneous defines...
diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c
index 76e55612430b..a7afeea156bd 100644
--- a/drivers/net/tulip/uli526x.c
+++ b/drivers/net/tulip/uli526x.c
@@ -34,9 +34,9 @@
#include <linux/delay.h>
#include <linux/spinlock.h>
#include <linux/dma-mapping.h>
+#include <linux/bitops.h>
#include <asm/processor.h>
-#include <asm/bitops.h>
#include <asm/io.h>
#include <asm/dma.h>
#include <asm/uaccess.h>
diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c
index 3c8e3b63be07..35d0cfcf8c47 100644
--- a/drivers/net/tulip/winbond-840.c
+++ b/drivers/net/tulip/winbond-840.c
@@ -483,7 +483,7 @@ err_out_netdev:
a delay. Note that pre-2.0.34 kernels had a cache-alignment bug that
made udelay() unreliable.
The old method of using an ISA access as a delay, __SLOW_DOWN_IO__, is
- depricated.
+ deprecated.
*/
#define eeprom_delay(ee_addr) ioread32(ee_addr)
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index 72e5e9be7e99..94ac5869bb18 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -1801,7 +1801,7 @@ typhoon_poll(struct napi_struct *napi, int budget)
static irqreturn_t
typhoon_interrupt(int irq, void *dev_instance)
{
- struct net_device *dev = (struct net_device *) dev_instance;
+ struct net_device *dev = dev_instance;
struct typhoon *tp = dev->priv;
void __iomem *ioaddr = tp->ioaddr;
u32 intr_status;
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index d00e7d41f6a5..a3ff270593f1 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -63,7 +63,7 @@
#define UGETH_MSG_DEFAULT (NETIF_MSG_IFUP << 1 ) - 1
void uec_set_ethtool_ops(struct net_device *netdev);
-
+
static DEFINE_SPINLOCK(ugeth_lock);
static struct {
@@ -2214,9 +2214,7 @@ static void ucc_geth_set_multi(struct net_device *dev)
struct dev_mc_list *dmi;
struct ucc_fast *uf_regs;
struct ucc_geth_82xx_address_filtering_pram *p_82xx_addr_filt;
- u8 tempaddr[6];
- u8 *mcptr, *tdptr;
- int i, j;
+ int i;
ugeth = netdev_priv(dev);
@@ -2255,19 +2253,10 @@ static void ucc_geth_set_multi(struct net_device *dev)
if (!(dmi->dmi_addr[0] & 1))
continue;
- /* The address in dmi_addr is LSB first,
- * and taddr is MSB first. We have to
- * copy bytes MSB first from dmi_addr.
- */
- mcptr = (u8 *) dmi->dmi_addr + 5;
- tdptr = (u8 *) tempaddr;
- for (j = 0; j < 6; j++)
- *tdptr++ = *mcptr--;
-
/* Ask CPM to run CRC and set bit in
* filter mask.
*/
- hw_add_addr_in_hash(ugeth, tempaddr);
+ hw_add_addr_in_hash(ugeth, dmi->dmi_addr);
}
}
}
@@ -3454,9 +3443,12 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit
u16 length, howmany = 0;
u32 bd_status;
u8 *bdBuffer;
+ struct net_device * dev;
ugeth_vdbg("%s: IN", __FUNCTION__);
+ dev = ugeth->dev;
+
/* collect received buffers */
bd = ugeth->rxBd[rxQ];
@@ -3604,7 +3596,7 @@ static int ucc_geth_poll(struct napi_struct *napi, int budget)
static irqreturn_t ucc_geth_irq_handler(int irq, void *info)
{
- struct net_device *dev = (struct net_device *)info;
+ struct net_device *dev = info;
struct ucc_geth_private *ugeth = netdev_priv(dev);
struct ucc_fast_private *uccf;
struct ucc_geth_info *ug_info;
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
index 8dc09a3790cb..a12c9c41b217 100644
--- a/drivers/net/usb/Kconfig
+++ b/drivers/net/usb/Kconfig
@@ -71,7 +71,7 @@ config USB_PEGASUS
select MII
---help---
Say Y here if you know you have Pegasus or Pegasus-II based adapter.
- If in doubt then look at <file:drivers/usb/net/pegasus.h> for the
+ If in doubt then look at <file:drivers/net/usb/pegasus.h> for the
complete list of supported devices.
If your particular adapter is not in the list and you are _sure_ it
@@ -93,13 +93,9 @@ config USB_RTL8150
To compile this driver as a module, choose M here: the
module will be called rtl8150.
-config USB_USBNET_MII
- tristate
- default n
-
config USB_USBNET
tristate "Multi-purpose USB Networking Framework"
- select MII if USB_USBNET_MII != n
+ select MII
---help---
This driver supports several kinds of network links over USB,
with "minidrivers" built around a common network driver core
@@ -135,7 +131,6 @@ config USB_NET_AX8817X
tristate "ASIX AX88xxx Based USB 2.0 Ethernet Adapters"
depends on USB_USBNET && NET_ETHERNET
select CRC32
- select USB_USBNET_MII
default y
help
This option adds support for ASIX AX88xxx based USB 2.0
@@ -190,7 +185,6 @@ config USB_NET_DM9601
tristate "Davicom DM9601 based USB 1.1 10/100 ethernet devices"
depends on USB_USBNET
select CRC32
- select USB_USBNET_MII
help
This option adds support for Davicom DM9601 based USB 1.1
10/100 Ethernet adapters.
@@ -225,7 +219,6 @@ config USB_NET_PLUSB
config USB_NET_MCS7830
tristate "MosChip MCS7830 based Ethernet adapters"
depends on USB_USBNET
- select USB_USBNET_MII
help
Choose this option if you're using a 10/100 Ethernet USB2
adapter based on the MosChip 7830 controller. This includes
diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c
index a2de32fabc17..2c685734b7a4 100644
--- a/drivers/net/usb/dm9601.c
+++ b/drivers/net/usb/dm9601.c
@@ -586,6 +586,10 @@ static const struct usb_device_id products[] = {
USB_DEVICE(0x0a46, 0x0268), /* ShanTou ST268 USB NIC */
.driver_info = (unsigned long)&dm9601_info,
},
+ {
+ USB_DEVICE(0x0a46, 0x8515), /* ADMtek ADM8515 USB NIC */
+ .driver_info = (unsigned long)&dm9601_info,
+ },
{}, // END
};
diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c
index 6240b978fe3d..f55a5951733a 100644
--- a/drivers/net/usb/mcs7830.c
+++ b/drivers/net/usb/mcs7830.c
@@ -114,8 +114,8 @@ static void mcs7830_async_cmd_callback(struct urb *urb)
struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
if (urb->status < 0)
- printk(KERN_DEBUG "mcs7830_async_cmd_callback() failed with %d",
- urb->status);
+ printk(KERN_DEBUG "%s() failed with %d\n",
+ __FUNCTION__, urb->status);
kfree(req);
usb_free_urb(urb);
@@ -129,15 +129,15 @@ static void mcs7830_set_reg_async(struct usbnet *dev, u16 index, u16 size, void
urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb) {
- dev_dbg(&dev->udev->dev, "Error allocating URB "
- "in write_cmd_async!");
+ dev_dbg(&dev->udev->dev,
+ "Error allocating URB in write_cmd_async!\n");
return;
}
req = kmalloc(sizeof *req, GFP_ATOMIC);
if (!req) {
- dev_err(&dev->udev->dev, "Failed to allocate memory for "
- "control request");
+ dev_err(&dev->udev->dev,
+ "Failed to allocate memory for control request\n");
goto out;
}
req->bRequestType = MCS7830_WR_BMREQ;
@@ -153,8 +153,8 @@ static void mcs7830_set_reg_async(struct usbnet *dev, u16 index, u16 size, void
ret = usb_submit_urb(urb, GFP_ATOMIC);
if (ret < 0) {
- dev_err(&dev->udev->dev, "Error submitting the control "
- "message: ret=%d", ret);
+ dev_err(&dev->udev->dev,
+ "Error submitting the control message: ret=%d\n", ret);
goto out;
}
return;
diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c
index cd991a0f75bb..1ebe3259be0d 100644
--- a/drivers/net/usb/rndis_host.c
+++ b/drivers/net/usb/rndis_host.c
@@ -512,11 +512,19 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf)
}
tmp = le32_to_cpu(u.init_c->max_transfer_size);
if (tmp < dev->hard_mtu) {
- dev_err(&intf->dev,
- "dev can't take %u byte packets (max %u)\n",
- dev->hard_mtu, tmp);
- retval = -EINVAL;
- goto fail_and_release;
+ if (tmp <= net->hard_header_len) {
+ dev_err(&intf->dev,
+ "dev can't take %u byte packets (max %u)\n",
+ dev->hard_mtu, tmp);
+ retval = -EINVAL;
+ goto fail_and_release;
+ }
+ dev->hard_mtu = tmp;
+ net->mtu = dev->hard_mtu - net->hard_header_len;
+ dev_warn(&intf->dev,
+ "dev can't take %u byte packets (max %u), "
+ "adjusting MTU to %u\n",
+ dev->hard_mtu, tmp, net->mtu);
}
/* REVISIT: peripheral "alignment" request is ignored ... */
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index acd5f1c0e63a..8ed1fc5cbc70 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -683,9 +683,6 @@ done_nopm:
* they'll probably want to use this base set.
*/
-#if defined(CONFIG_MII) || defined(CONFIG_MII_MODULE)
-#define HAVE_MII
-
int usbnet_get_settings (struct net_device *net, struct ethtool_cmd *cmd)
{
struct usbnet *dev = netdev_priv(net);
@@ -744,8 +741,6 @@ int usbnet_nway_reset(struct net_device *net)
}
EXPORT_SYMBOL_GPL(usbnet_nway_reset);
-#endif /* HAVE_MII */
-
void usbnet_get_drvinfo (struct net_device *net, struct ethtool_drvinfo *info)
{
struct usbnet *dev = netdev_priv(net);
@@ -776,12 +771,10 @@ EXPORT_SYMBOL_GPL(usbnet_set_msglevel);
/* drivers may override default ethtool_ops in their bind() routine */
static struct ethtool_ops usbnet_ethtool_ops = {
-#ifdef HAVE_MII
.get_settings = usbnet_get_settings,
.set_settings = usbnet_set_settings,
.get_link = usbnet_get_link,
.nway_reset = usbnet_nway_reset,
-#endif
.get_drvinfo = usbnet_get_drvinfo,
.get_msglevel = usbnet_get_msglevel,
.set_msglevel = usbnet_set_msglevel,
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index 4ae05799ac44..450e29d7a9f3 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -1648,7 +1648,7 @@ static int velocity_alloc_rx_buf(struct velocity_info *vptr, int idx)
*
* Scan the queues looking for transmitted packets that
* we can complete and clean up. Update any statistics as
- * neccessary/
+ * necessary/
*/
static int velocity_tx_srv(struct velocity_info *vptr, u32 status)
@@ -1963,6 +1963,11 @@ static int velocity_change_mtu(struct net_device *dev, int new_mtu)
return -EINVAL;
}
+ if (!netif_running(dev)) {
+ dev->mtu = new_mtu;
+ return 0;
+ }
+
if (new_mtu != oldmtu) {
spin_lock_irqsave(&vptr->lock, flags);
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
new file mode 100644
index 000000000000..a75be57fb209
--- /dev/null
+++ b/drivers/net/virtio_net.c
@@ -0,0 +1,438 @@
+/* A simple network driver using virtio.
+ *
+ * Copyright 2007 Rusty Russell <rusty@rustcorp.com.au> IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+//#define DEBUG
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/module.h>
+#include <linux/virtio.h>
+#include <linux/virtio_net.h>
+#include <linux/scatterlist.h>
+
+/* FIXME: MTU in config. */
+#define MAX_PACKET_LEN (ETH_HLEN+ETH_DATA_LEN)
+
+struct virtnet_info
+{
+ struct virtio_device *vdev;
+ struct virtqueue *rvq, *svq;
+ struct net_device *dev;
+ struct napi_struct napi;
+
+ /* Number of input buffers, and max we've ever had. */
+ unsigned int num, max;
+
+ /* Receive & send queues. */
+ struct sk_buff_head recv;
+ struct sk_buff_head send;
+};
+
+static inline struct virtio_net_hdr *skb_vnet_hdr(struct sk_buff *skb)
+{
+ return (struct virtio_net_hdr *)skb->cb;
+}
+
+static inline void vnet_hdr_to_sg(struct scatterlist *sg, struct sk_buff *skb)
+{
+ sg_init_one(sg, skb_vnet_hdr(skb), sizeof(struct virtio_net_hdr));
+}
+
+static bool skb_xmit_done(struct virtqueue *rvq)
+{
+ struct virtnet_info *vi = rvq->vdev->priv;
+
+ /* In case we were waiting for output buffers. */
+ netif_wake_queue(vi->dev);
+ return true;
+}
+
+static void receive_skb(struct net_device *dev, struct sk_buff *skb,
+ unsigned len)
+{
+ struct virtio_net_hdr *hdr = skb_vnet_hdr(skb);
+
+ if (unlikely(len < sizeof(struct virtio_net_hdr) + ETH_HLEN)) {
+ pr_debug("%s: short packet %i\n", dev->name, len);
+ dev->stats.rx_length_errors++;
+ goto drop;
+ }
+ len -= sizeof(struct virtio_net_hdr);
+ BUG_ON(len > MAX_PACKET_LEN);
+
+ skb_trim(skb, len);
+ skb->protocol = eth_type_trans(skb, dev);
+ pr_debug("Receiving skb proto 0x%04x len %i type %i\n",
+ ntohs(skb->protocol), skb->len, skb->pkt_type);
+ dev->stats.rx_bytes += skb->len;
+ dev->stats.rx_packets++;
+
+ if (hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
+ pr_debug("Needs csum!\n");
+ skb->ip_summed = CHECKSUM_PARTIAL;
+ skb->csum_start = hdr->csum_start;
+ skb->csum_offset = hdr->csum_offset;
+ if (skb->csum_start > skb->len - 2
+ || skb->csum_offset > skb->len - 2) {
+ if (net_ratelimit())
+ printk(KERN_WARNING "%s: csum=%u/%u len=%u\n",
+ dev->name, skb->csum_start,
+ skb->csum_offset, skb->len);
+ goto frame_err;
+ }
+ }
+
+ if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) {
+ pr_debug("GSO!\n");
+ switch (hdr->gso_type) {
+ case VIRTIO_NET_HDR_GSO_TCPV4:
+ skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
+ break;
+ case VIRTIO_NET_HDR_GSO_TCPV4_ECN:
+ skb_shinfo(skb)->gso_type = SKB_GSO_TCP_ECN;
+ break;
+ case VIRTIO_NET_HDR_GSO_UDP:
+ skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
+ break;
+ case VIRTIO_NET_HDR_GSO_TCPV6:
+ skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
+ break;
+ default:
+ if (net_ratelimit())
+ printk(KERN_WARNING "%s: bad gso type %u.\n",
+ dev->name, hdr->gso_type);
+ goto frame_err;
+ }
+
+ skb_shinfo(skb)->gso_size = hdr->gso_size;
+ if (skb_shinfo(skb)->gso_size == 0) {
+ if (net_ratelimit())
+ printk(KERN_WARNING "%s: zero gso size.\n",
+ dev->name);
+ goto frame_err;
+ }
+
+ /* Header must be checked, and gso_segs computed. */
+ skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
+ skb_shinfo(skb)->gso_segs = 0;
+ }
+
+ netif_receive_skb(skb);
+ return;
+
+frame_err:
+ dev->stats.rx_frame_errors++;
+drop:
+ dev_kfree_skb(skb);
+}
+
+static void try_fill_recv(struct virtnet_info *vi)
+{
+ struct sk_buff *skb;
+ struct scatterlist sg[1+MAX_SKB_FRAGS];
+ int num, err;
+
+ sg_init_table(sg, 1+MAX_SKB_FRAGS);
+ for (;;) {
+ skb = netdev_alloc_skb(vi->dev, MAX_PACKET_LEN);
+ if (unlikely(!skb))
+ break;
+
+ skb_put(skb, MAX_PACKET_LEN);
+ vnet_hdr_to_sg(sg, skb);
+ num = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1;
+ skb_queue_head(&vi->recv, skb);
+
+ err = vi->rvq->vq_ops->add_buf(vi->rvq, sg, 0, num, skb);
+ if (err) {
+ skb_unlink(skb, &vi->recv);
+ kfree_skb(skb);
+ break;
+ }
+ vi->num++;
+ }
+ if (unlikely(vi->num > vi->max))
+ vi->max = vi->num;
+ vi->rvq->vq_ops->kick(vi->rvq);
+}
+
+static bool skb_recv_done(struct virtqueue *rvq)
+{
+ struct virtnet_info *vi = rvq->vdev->priv;
+ netif_rx_schedule(vi->dev, &vi->napi);
+ /* Suppress further interrupts. */
+ return false;
+}
+
+static int virtnet_poll(struct napi_struct *napi, int budget)
+{
+ struct virtnet_info *vi = container_of(napi, struct virtnet_info, napi);
+ struct sk_buff *skb = NULL;
+ unsigned int len, received = 0;
+
+again:
+ while (received < budget &&
+ (skb = vi->rvq->vq_ops->get_buf(vi->rvq, &len)) != NULL) {
+ __skb_unlink(skb, &vi->recv);
+ receive_skb(vi->dev, skb, len);
+ vi->num--;
+ received++;
+ }
+
+ /* FIXME: If we oom and completely run out of inbufs, we need
+ * to start a timer trying to fill more. */
+ if (vi->num < vi->max / 2)
+ try_fill_recv(vi);
+
+ /* All done? */
+ if (!skb) {
+ netif_rx_complete(vi->dev, napi);
+ if (unlikely(!vi->rvq->vq_ops->restart(vi->rvq))
+ && netif_rx_reschedule(vi->dev, napi))
+ goto again;
+ }
+
+ return received;
+}
+
+static void free_old_xmit_skbs(struct virtnet_info *vi)
+{
+ struct sk_buff *skb;
+ unsigned int len;
+
+ while ((skb = vi->svq->vq_ops->get_buf(vi->svq, &len)) != NULL) {
+ pr_debug("Sent skb %p\n", skb);
+ __skb_unlink(skb, &vi->send);
+ vi->dev->stats.tx_bytes += len;
+ vi->dev->stats.tx_packets++;
+ kfree_skb(skb);
+ }
+}
+
+static int start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct virtnet_info *vi = netdev_priv(dev);
+ int num, err;
+ struct scatterlist sg[1+MAX_SKB_FRAGS];
+ struct virtio_net_hdr *hdr;
+ const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest;
+ DECLARE_MAC_BUF(mac);
+
+ sg_init_table(sg, 1+MAX_SKB_FRAGS);
+
+ pr_debug("%s: xmit %p %s\n", dev->name, skb, print_mac(mac, dest));
+
+ free_old_xmit_skbs(vi);
+
+ /* Encode metadata header at front. */
+ hdr = skb_vnet_hdr(skb);
+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
+ hdr->csum_start = skb->csum_start - skb_headroom(skb);
+ hdr->csum_offset = skb->csum_offset;
+ } else {
+ hdr->flags = 0;
+ hdr->csum_offset = hdr->csum_start = 0;
+ }
+
+ if (skb_is_gso(skb)) {
+ hdr->gso_size = skb_shinfo(skb)->gso_size;
+ if (skb_shinfo(skb)->gso_type & SKB_GSO_TCP_ECN)
+ hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4_ECN;
+ else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4)
+ hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
+ else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
+ hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
+ else if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP)
+ hdr->gso_type = VIRTIO_NET_HDR_GSO_UDP;
+ else
+ BUG();
+ } else {
+ hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE;
+ hdr->gso_size = 0;
+ }
+
+ vnet_hdr_to_sg(sg, skb);
+ num = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1;
+ __skb_queue_head(&vi->send, skb);
+ err = vi->svq->vq_ops->add_buf(vi->svq, sg, num, 0, skb);
+ if (err) {
+ pr_debug("%s: virtio not prepared to send\n", dev->name);
+ skb_unlink(skb, &vi->send);
+ netif_stop_queue(dev);
+ return NETDEV_TX_BUSY;
+ }
+ vi->svq->vq_ops->kick(vi->svq);
+
+ return 0;
+}
+
+static int virtnet_open(struct net_device *dev)
+{
+ struct virtnet_info *vi = netdev_priv(dev);
+
+ try_fill_recv(vi);
+
+ /* If we didn't even get one input buffer, we're useless. */
+ if (vi->num == 0)
+ return -ENOMEM;
+
+ napi_enable(&vi->napi);
+ return 0;
+}
+
+static int virtnet_close(struct net_device *dev)
+{
+ struct virtnet_info *vi = netdev_priv(dev);
+ struct sk_buff *skb;
+
+ napi_disable(&vi->napi);
+
+ /* networking core has neutered skb_xmit_done/skb_recv_done, so don't
+ * worry about races vs. get(). */
+ vi->rvq->vq_ops->shutdown(vi->rvq);
+ while ((skb = __skb_dequeue(&vi->recv)) != NULL) {
+ kfree_skb(skb);
+ vi->num--;
+ }
+ vi->svq->vq_ops->shutdown(vi->svq);
+ while ((skb = __skb_dequeue(&vi->send)) != NULL)
+ kfree_skb(skb);
+
+ BUG_ON(vi->num != 0);
+ return 0;
+}
+
+static int virtnet_probe(struct virtio_device *vdev)
+{
+ int err;
+ unsigned int len;
+ struct net_device *dev;
+ struct virtnet_info *vi;
+ void *token;
+
+ /* Allocate ourselves a network device with room for our info */
+ dev = alloc_etherdev(sizeof(struct virtnet_info));
+ if (!dev)
+ return -ENOMEM;
+
+ /* Set up network device as normal. */
+ ether_setup(dev);
+ dev->open = virtnet_open;
+ dev->stop = virtnet_close;
+ dev->hard_start_xmit = start_xmit;
+ dev->features = NETIF_F_HIGHDMA;
+ SET_NETDEV_DEV(dev, &vdev->dev);
+
+ /* Do we support "hardware" checksums? */
+ token = vdev->config->find(vdev, VIRTIO_CONFIG_NET_F, &len);
+ if (virtio_use_bit(vdev, token, len, VIRTIO_NET_F_NO_CSUM)) {
+ /* This opens up the world of extra features. */
+ dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST;
+ if (virtio_use_bit(vdev, token, len, VIRTIO_NET_F_TSO4))
+ dev->features |= NETIF_F_TSO;
+ if (virtio_use_bit(vdev, token, len, VIRTIO_NET_F_UFO))
+ dev->features |= NETIF_F_UFO;
+ if (virtio_use_bit(vdev, token, len, VIRTIO_NET_F_TSO4_ECN))
+ dev->features |= NETIF_F_TSO_ECN;
+ if (virtio_use_bit(vdev, token, len, VIRTIO_NET_F_TSO6))
+ dev->features |= NETIF_F_TSO6;
+ }
+
+ /* Configuration may specify what MAC to use. Otherwise random. */
+ token = vdev->config->find(vdev, VIRTIO_CONFIG_NET_MAC_F, &len);
+ if (token) {
+ dev->addr_len = len;
+ vdev->config->get(vdev, token, dev->dev_addr, len);
+ } else
+ random_ether_addr(dev->dev_addr);
+
+ /* Set up our device-specific information */
+ vi = netdev_priv(dev);
+ netif_napi_add(dev, &vi->napi, virtnet_poll, 16);
+ vi->dev = dev;
+ vi->vdev = vdev;
+
+ /* We expect two virtqueues, receive then send. */
+ vi->rvq = vdev->config->find_vq(vdev, skb_recv_done);
+ if (IS_ERR(vi->rvq)) {
+ err = PTR_ERR(vi->rvq);
+ goto free;
+ }
+
+ vi->svq = vdev->config->find_vq(vdev, skb_xmit_done);
+ if (IS_ERR(vi->svq)) {
+ err = PTR_ERR(vi->svq);
+ goto free_recv;
+ }
+
+ /* Initialize our empty receive and send queues. */
+ skb_queue_head_init(&vi->recv);
+ skb_queue_head_init(&vi->send);
+
+ err = register_netdev(dev);
+ if (err) {
+ pr_debug("virtio_net: registering device failed\n");
+ goto free_send;
+ }
+ pr_debug("virtnet: registered device %s\n", dev->name);
+ vdev->priv = vi;
+ return 0;
+
+free_send:
+ vdev->config->del_vq(vi->svq);
+free_recv:
+ vdev->config->del_vq(vi->rvq);
+free:
+ free_netdev(dev);
+ return err;
+}
+
+static void virtnet_remove(struct virtio_device *vdev)
+{
+ unregister_netdev(vdev->priv);
+ free_netdev(vdev->priv);
+}
+
+static struct virtio_device_id id_table[] = {
+ { VIRTIO_ID_NET, VIRTIO_DEV_ANY_ID },
+ { 0 },
+};
+
+static struct virtio_driver virtio_net = {
+ .driver.name = KBUILD_MODNAME,
+ .driver.owner = THIS_MODULE,
+ .id_table = id_table,
+ .probe = virtnet_probe,
+ .remove = __devexit_p(virtnet_remove),
+};
+
+static int __init init(void)
+{
+ return register_virtio_driver(&virtio_net);
+}
+
+static void __exit fini(void)
+{
+ unregister_virtio_driver(&virtio_net);
+}
+module_init(init);
+module_exit(fini);
+
+MODULE_DEVICE_TABLE(virtio, id_table);
+MODULE_DESCRIPTION("Virtio network driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c
index 5ea877221f46..37c52e131750 100644
--- a/drivers/net/wan/lmc/lmc_main.c
+++ b/drivers/net/wan/lmc/lmc_main.c
@@ -142,9 +142,10 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
* To date internally, just copy this out to the user.
*/
case LMCIOCGINFO: /*fold01*/
- if (copy_to_user(ifr->ifr_data, &sc->ictl, sizeof (lmc_ctl_t)))
- return -EFAULT;
- ret = 0;
+ if (copy_to_user(ifr->ifr_data, &sc->ictl, sizeof(lmc_ctl_t)))
+ ret = -EFAULT;
+ else
+ ret = 0;
break;
case LMCIOCSINFO: /*fold01*/
@@ -159,8 +160,10 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
break;
}
- if (copy_from_user(&ctl, ifr->ifr_data, sizeof (lmc_ctl_t)))
- return -EFAULT;
+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(lmc_ctl_t))) {
+ ret = -EFAULT;
+ break;
+ }
sc->lmc_media->set_status (sc, &ctl);
@@ -190,8 +193,10 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
break;
}
- if (copy_from_user(&new_type, ifr->ifr_data, sizeof(u_int16_t)))
- return -EFAULT;
+ if (copy_from_user(&new_type, ifr->ifr_data, sizeof(u_int16_t))) {
+ ret = -EFAULT;
+ break;
+ }
if (new_type == old_type)
@@ -229,9 +234,10 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
sc->lmc_xinfo.Magic1 = 0xDEADBEEF;
if (copy_to_user(ifr->ifr_data, &sc->lmc_xinfo,
- sizeof (struct lmc_xinfo)))
- return -EFAULT;
- ret = 0;
+ sizeof(struct lmc_xinfo)))
+ ret = -EFAULT;
+ else
+ ret = 0;
break;
@@ -262,9 +268,9 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
if (copy_to_user(ifr->ifr_data, &sc->stats,
sizeof (struct lmc_statistics)))
- return -EFAULT;
-
- ret = 0;
+ ret = -EFAULT;
+ else
+ ret = 0;
break;
case LMCIOCCLEARLMCSTATS: /*fold01*/
@@ -292,8 +298,10 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
break;
}
- if (copy_from_user(&ctl, ifr->ifr_data, sizeof (lmc_ctl_t)))
- return -EFAULT;
+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(lmc_ctl_t))) {
+ ret = -EFAULT;
+ break;
+ }
sc->lmc_media->set_circuit_type(sc, ctl.circuit_type);
sc->ictl.circuit_type = ctl.circuit_type;
ret = 0;
@@ -318,12 +326,15 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
#ifdef DEBUG
case LMCIOCDUMPEVENTLOG:
- if (copy_to_user(ifr->ifr_data, &lmcEventLogIndex, sizeof (u32)))
- return -EFAULT;
+ if (copy_to_user(ifr->ifr_data, &lmcEventLogIndex, sizeof(u32))) {
+ ret = -EFAULT;
+ break;
+ }
if (copy_to_user(ifr->ifr_data + sizeof (u32), lmcEventLogBuf, sizeof (lmcEventLogBuf)))
- return -EFAULT;
+ ret = -EFAULT;
+ else
+ ret = 0;
- ret = 0;
break;
#endif /* end ifdef _DBG_EVENTLOG */
case LMCIOCT1CONTROL: /*fold01*/
@@ -346,8 +357,10 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
*/
netif_stop_queue(dev);
- if (copy_from_user(&xc, ifr->ifr_data, sizeof (struct lmc_xilinx_control)))
- return -EFAULT;
+ if (copy_from_user(&xc, ifr->ifr_data, sizeof(struct lmc_xilinx_control))) {
+ ret = -EFAULT;
+ break;
+ }
switch(xc.command){
case lmc_xilinx_reset: /*fold02*/
{
diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c
index 76db40d200d8..2e8b5c2de887 100644
--- a/drivers/net/wan/sbni.c
+++ b/drivers/net/wan/sbni.c
@@ -502,8 +502,8 @@ sbni_start_xmit( struct sk_buff *skb, struct net_device *dev )
static irqreturn_t
sbni_interrupt( int irq, void *dev_id )
{
- struct net_device *dev = (struct net_device *) dev_id;
- struct net_local *nl = (struct net_local *) dev->priv;
+ struct net_device *dev = dev_id;
+ struct net_local *nl = dev->priv;
int repeat;
spin_lock( &nl->lock );
diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c
index b39a541b2509..05df0a345b60 100644
--- a/drivers/net/wan/sdla.c
+++ b/drivers/net/wan/sdla.c
@@ -1342,11 +1342,11 @@ static int sdla_set_config(struct net_device *dev, struct ifmap *map)
if (flp->initialized)
return(-EINVAL);
- for(i=0;i < sizeof(valid_port) / sizeof (int) ; i++)
+ for(i=0; i < ARRAY_SIZE(valid_port); i++)
if (valid_port[i] == map->base_addr)
break;
- if (i == sizeof(valid_port) / sizeof(int))
+ if (i == ARRAY_SIZE(valid_port))
return(-EINVAL);
if (!request_region(map->base_addr, SDLA_IO_EXTENTS, dev->name)){
@@ -1487,12 +1487,12 @@ got_type:
}
}
- for(i=0;i < sizeof(valid_mem) / sizeof (int) ; i++)
+ for(i=0; i < ARRAY_SIZE(valid_mem); i++)
if (valid_mem[i] == map->mem_start)
break;
err = -EINVAL;
- if (i == sizeof(valid_mem) / sizeof(int))
+ if (i == ARRAY_SIZE(valid_mem))
goto fail2;
if (flp->type == SDLA_S502A && (map->mem_start & 0xF000) >> 12 == 0x0E)
diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
index c48b1cc63fd5..1e89d4de1bb7 100644
--- a/drivers/net/wan/x25_asy.c
+++ b/drivers/net/wan/x25_asy.c
@@ -719,12 +719,8 @@ static int x25_asy_ioctl(struct tty_struct *tty, struct file *file,
return 0;
case SIOCSIFHWADDR:
return -EINVAL;
- /* Allow stty to read, but not set, the serial port */
- case TCGETS:
- case TCGETA:
- return n_tty_ioctl(tty, file, cmd, arg);
default:
- return -ENOIOCTLCMD;
+ return tty_mode_ioctl(tty, file, cmd, arg);
}
}
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 5a6fdfd0f140..2b733c582915 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -282,6 +282,12 @@ config LIBERTAS_CS
---help---
A driver for Marvell Libertas 8385 CompactFlash devices.
+config LIBERTAS_SDIO
+ tristate "Marvell Libertas 8385 and 8686 SDIO 802.11b/g cards"
+ depends on LIBERTAS && MMC
+ ---help---
+ A driver for Marvell Libertas 8385 and 8686 SDIO devices.
+
config LIBERTAS_DEBUG
bool "Enable full debugging output in the Libertas module."
depends on LIBERTAS
@@ -319,7 +325,7 @@ config HERMES
Cabletron/EnteraSys Roamabout, ELSA AirLancer, MELCO Buffalo, Avaya,
IBM High Rate Wireless, Farralon Syyline, Samsung MagicLAN, Netgear
MA401, LinkSys WPC-11, D-Link DWL-650, 3Com AirConnect, Intel
- PRO/Wireless, and Symbol Spectrum24 High Rate amongst others.
+ IPW2011, and Symbol Spectrum24 High Rate amongst others.
This option includes the guts of the driver, but in order to
actually use a card you will also need to enable support for PCMCIA
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig
index e3c573e56b63..fdbc351ac333 100644
--- a/drivers/net/wireless/b43/Kconfig
+++ b/drivers/net/wireless/b43/Kconfig
@@ -61,16 +61,18 @@ config B43_PCMCIA
If unsure, say N.
-# LED support
+# This config option automatically enables b43 LEDS support,
+# if it's possible.
config B43_LEDS
bool
- depends on B43 && MAC80211_LEDS
+ depends on B43 && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = B43)
default y
-# RFKILL support
+# This config option automatically enables b43 RFKILL support,
+# if it's possible.
config B43_RFKILL
bool
- depends on B43 && RFKILL && RFKILL_INPUT && INPUT_POLLDEV
+ depends on B43 && (RFKILL = y || RFKILL = B43) && RFKILL_INPUT && (INPUT_POLLDEV = y || INPUT_POLLDEV = B43)
default y
config B43_DEBUG
diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c
index 734e70e1a06d..ef0075d9f9cb 100644
--- a/drivers/net/wireless/b43/debugfs.c
+++ b/drivers/net/wireless/b43/debugfs.c
@@ -128,7 +128,7 @@ static ssize_t shm_read_file(struct b43_wldev *dev,
__le16 *le16buf = (__le16 *)buf;
for (i = 0; i < 0x1000; i++) {
- if (bufsize <= 0)
+ if (bufsize < sizeof(tmp))
break;
tmp = b43_shm_read16(dev, B43_SHM_SHARED, 2 * i);
le16buf[i] = cpu_to_le16(tmp);
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index c141a264ac45..2b17c1dc46f1 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -49,7 +49,6 @@
#include "pio.h"
#include "sysfs.h"
#include "xmit.h"
-#include "sysfs.h"
#include "lo.h"
#include "pcmcia.h"
@@ -2392,7 +2391,7 @@ out_requeue:
if (b43_debug(dev, B43_DBG_PWORK_FAST))
delay = msecs_to_jiffies(50);
else
- delay = round_jiffies(HZ * 15);
+ delay = round_jiffies_relative(HZ * 15);
queue_delayed_work(wl->hw->workqueue, &dev->periodic_work, delay);
out:
mutex_unlock(&wl->mutex);
@@ -2986,6 +2985,16 @@ static void b43_wireless_core_stop(struct b43_wldev *dev)
if (b43_status(dev) < B43_STAT_STARTED)
return;
+
+ /* Disable and sync interrupts. We must do this before than
+ * setting the status to INITIALIZED, as the interrupt handler
+ * won't care about IRQs then. */
+ spin_lock_irqsave(&wl->irq_lock, flags);
+ dev->irq_savedstate = b43_interrupt_disable(dev, B43_IRQ_ALL);
+ b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* flush */
+ spin_unlock_irqrestore(&wl->irq_lock, flags);
+ b43_synchronize_irq(dev);
+
b43_set_status(dev, B43_STAT_INITIALIZED);
mutex_unlock(&wl->mutex);
@@ -2996,13 +3005,6 @@ static void b43_wireless_core_stop(struct b43_wldev *dev)
ieee80211_stop_queues(wl->hw); //FIXME this could cause a deadlock, as mac80211 seems buggy.
- /* Disable and sync interrupts. */
- spin_lock_irqsave(&wl->irq_lock, flags);
- dev->irq_savedstate = b43_interrupt_disable(dev, B43_IRQ_ALL);
- b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* flush */
- spin_unlock_irqrestore(&wl->irq_lock, flags);
- b43_synchronize_irq(dev);
-
b43_mac_suspend(dev);
free_irq(dev->dev->irq, dev);
b43dbg(wl, "Wireless interface stopped\n");
@@ -3495,7 +3497,7 @@ static int b43_start(struct ieee80211_hw *hw)
struct b43_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev = wl->current_dev;
int did_init = 0;
- int err;
+ int err = 0;
mutex_lock(&wl->mutex);
@@ -3521,7 +3523,7 @@ static int b43_start(struct ieee80211_hw *hw)
return err;
}
-void b43_stop(struct ieee80211_hw *hw)
+static void b43_stop(struct ieee80211_hw *hw)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev = wl->current_dev;
@@ -3662,7 +3664,6 @@ static int b43_setup_modes(struct b43_wldev *dev,
static void b43_wireless_core_detach(struct b43_wldev *dev)
{
- b43_rfkill_free(dev);
/* We release firmware that late to not be required to re-request
* is all the time when we reinit the core. */
b43_release_firmware(dev);
@@ -3748,7 +3749,6 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
if (!wl->current_dev)
wl->current_dev = dev;
INIT_WORK(&dev->restart_work, b43_chip_reset);
- b43_rfkill_alloc(dev);
b43_radio_turn_off(dev, 1);
b43_switch_analog(dev, 0);
diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c
index b242a9a90dd2..b79a6bd5396d 100644
--- a/drivers/net/wireless/b43/pcmcia.c
+++ b/drivers/net/wireless/b43/pcmcia.c
@@ -65,12 +65,12 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)
tuple_t tuple;
cisparse_t parse;
int err = -ENOMEM;
- int res;
+ int res = 0;
unsigned char buf[64];
ssb = kzalloc(sizeof(*ssb), GFP_KERNEL);
if (!ssb)
- goto out;
+ goto out_error;
err = -ENODEV;
tuple.DesiredTuple = CISTPL_CONFIG;
@@ -96,10 +96,12 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)
dev->io.NumPorts2 = 0;
dev->io.Attributes2 = 0;
- win.Attributes = WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT;
+ win.Attributes = WIN_ADDR_SPACE_MEM | WIN_MEMORY_TYPE_CM |
+ WIN_ENABLE | WIN_DATA_WIDTH_16 |
+ WIN_USE_WAIT;
win.Base = 0;
win.Size = SSB_CORE_SIZE;
- win.AccessSpeed = 1000;
+ win.AccessSpeed = 250;
res = pcmcia_request_window(&dev, &win, &dev->win);
if (res != CS_SUCCESS)
goto err_kfree_ssb;
@@ -108,21 +110,34 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)
mem.Page = 0;
res = pcmcia_map_mem_page(dev->win, &mem);
if (res != CS_SUCCESS)
- goto err_kfree_ssb;
+ goto err_disable;
+
+ dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_FIRST_SHARED;
+ dev->irq.IRQInfo1 = IRQ_LEVEL_ID | IRQ_SHARE_ID;
+ dev->irq.Handler = NULL; /* The handler is registered later. */
+ dev->irq.Instance = NULL;
+ res = pcmcia_request_irq(dev, &dev->irq);
+ if (res != CS_SUCCESS)
+ goto err_disable;
res = pcmcia_request_configuration(dev, &dev->conf);
if (res != CS_SUCCESS)
goto err_disable;
err = ssb_bus_pcmciabus_register(ssb, dev, win.Base);
+ if (err)
+ goto err_disable;
dev->priv = ssb;
- out:
- return err;
- err_disable:
+ return 0;
+
+err_disable:
pcmcia_disable_device(dev);
- err_kfree_ssb:
+err_kfree_ssb:
kfree(ssb);
+out_error:
+ printk(KERN_ERR "b43-pcmcia: Initialization failed (%d, %d)\n",
+ res, err);
return err;
}
@@ -131,22 +146,21 @@ static void __devexit b43_pcmcia_remove(struct pcmcia_device *dev)
struct ssb_bus *ssb = dev->priv;
ssb_bus_unregister(ssb);
- pcmcia_release_window(dev->win);
pcmcia_disable_device(dev);
kfree(ssb);
dev->priv = NULL;
}
static struct pcmcia_driver b43_pcmcia_driver = {
- .owner = THIS_MODULE,
- .drv = {
- .name = "b43-pcmcia",
- },
- .id_table = b43_pcmcia_tbl,
- .probe = b43_pcmcia_probe,
- .remove = b43_pcmcia_remove,
- .suspend = b43_pcmcia_suspend,
- .resume = b43_pcmcia_resume,
+ .owner = THIS_MODULE,
+ .drv = {
+ .name = "b43-pcmcia",
+ },
+ .id_table = b43_pcmcia_tbl,
+ .probe = b43_pcmcia_probe,
+ .remove = __devexit_p(b43_pcmcia_remove),
+ .suspend = b43_pcmcia_suspend,
+ .resume = b43_pcmcia_resume,
};
int b43_pcmcia_init(void)
diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c
index 800e0a61a7f5..9b1f905ffbf4 100644
--- a/drivers/net/wireless/b43/rfkill.c
+++ b/drivers/net/wireless/b43/rfkill.c
@@ -47,32 +47,35 @@ static void b43_rfkill_poll(struct input_polled_dev *poll_dev)
struct b43_wldev *dev = poll_dev->private;
struct b43_wl *wl = dev->wl;
bool enabled;
+ bool report_change = 0;
mutex_lock(&wl->mutex);
B43_WARN_ON(b43_status(dev) < B43_STAT_INITIALIZED);
enabled = b43_is_hw_radio_enabled(dev);
if (unlikely(enabled != dev->radio_hw_enable)) {
dev->radio_hw_enable = enabled;
+ report_change = 1;
b43info(wl, "Radio hardware status changed to %s\n",
enabled ? "ENABLED" : "DISABLED");
- mutex_unlock(&wl->mutex);
+ }
+ mutex_unlock(&wl->mutex);
+
+ if (unlikely(report_change))
input_report_key(poll_dev->input, KEY_WLAN, enabled);
- } else
- mutex_unlock(&wl->mutex);
}
-/* Called when the RFKILL toggled in software.
- * This is called without locking. */
+/* Called when the RFKILL toggled in software. */
static int b43_rfkill_soft_toggle(void *data, enum rfkill_state state)
{
struct b43_wldev *dev = data;
struct b43_wl *wl = dev->wl;
int err = 0;
- mutex_lock(&wl->mutex);
- if (b43_status(dev) < B43_STAT_INITIALIZED)
- goto out_unlock;
+ if (!wl->rfkill.registered)
+ return 0;
+ mutex_lock(&wl->mutex);
+ B43_WARN_ON(b43_status(dev) < B43_STAT_INITIALIZED);
switch (state) {
case RFKILL_STATE_ON:
if (!dev->radio_hw_enable) {
@@ -89,7 +92,6 @@ static int b43_rfkill_soft_toggle(void *data, enum rfkill_state state)
b43_radio_turn_off(dev, 0);
break;
}
-
out_unlock:
mutex_unlock(&wl->mutex);
@@ -98,11 +100,11 @@ out_unlock:
char * b43_rfkill_led_name(struct b43_wldev *dev)
{
- struct b43_wl *wl = dev->wl;
+ struct b43_rfkill *rfk = &(dev->wl->rfkill);
- if (!wl->rfkill.rfkill)
+ if (!rfk->registered)
return NULL;
- return rfkill_get_led_name(wl->rfkill.rfkill);
+ return rfkill_get_led_name(rfk->rfkill);
}
void b43_rfkill_init(struct b43_wldev *dev)
@@ -111,53 +113,13 @@ void b43_rfkill_init(struct b43_wldev *dev)
struct b43_rfkill *rfk = &(wl->rfkill);
int err;
- if (rfk->rfkill) {
- err = rfkill_register(rfk->rfkill);
- if (err) {
- b43warn(wl, "Failed to register RF-kill button\n");
- goto err_free_rfk;
- }
- }
- if (rfk->poll_dev) {
- err = input_register_polled_device(rfk->poll_dev);
- if (err) {
- b43warn(wl, "Failed to register RF-kill polldev\n");
- goto err_free_polldev;
- }
- }
-
- return;
-err_free_rfk:
- rfkill_free(rfk->rfkill);
- rfk->rfkill = NULL;
-err_free_polldev:
- input_free_polled_device(rfk->poll_dev);
- rfk->poll_dev = NULL;
-}
-
-void b43_rfkill_exit(struct b43_wldev *dev)
-{
- struct b43_rfkill *rfk = &(dev->wl->rfkill);
-
- if (rfk->poll_dev)
- input_unregister_polled_device(rfk->poll_dev);
- if (rfk->rfkill)
- rfkill_unregister(rfk->rfkill);
-}
-
-void b43_rfkill_alloc(struct b43_wldev *dev)
-{
- struct b43_wl *wl = dev->wl;
- struct b43_rfkill *rfk = &(wl->rfkill);
+ rfk->registered = 0;
+ rfk->rfkill = rfkill_allocate(dev->dev->dev, RFKILL_TYPE_WLAN);
+ if (!rfk->rfkill)
+ goto out_error;
snprintf(rfk->name, sizeof(rfk->name),
"b43-%s", wiphy_name(wl->hw->wiphy));
-
- rfk->rfkill = rfkill_allocate(dev->dev->dev, RFKILL_TYPE_WLAN);
- if (!rfk->rfkill) {
- b43warn(wl, "Failed to allocate RF-kill button\n");
- return;
- }
rfk->rfkill->name = rfk->name;
rfk->rfkill->state = RFKILL_STATE_ON;
rfk->rfkill->data = dev;
@@ -165,18 +127,45 @@ void b43_rfkill_alloc(struct b43_wldev *dev)
rfk->rfkill->user_claim_unsupported = 1;
rfk->poll_dev = input_allocate_polled_device();
- if (rfk->poll_dev) {
- rfk->poll_dev->private = dev;
- rfk->poll_dev->poll = b43_rfkill_poll;
- rfk->poll_dev->poll_interval = 1000; /* msecs */
- } else
- b43warn(wl, "Failed to allocate RF-kill polldev\n");
+ if (!rfk->poll_dev)
+ goto err_free_rfk;
+ rfk->poll_dev->private = dev;
+ rfk->poll_dev->poll = b43_rfkill_poll;
+ rfk->poll_dev->poll_interval = 1000; /* msecs */
+
+ err = rfkill_register(rfk->rfkill);
+ if (err)
+ goto err_free_polldev;
+ err = input_register_polled_device(rfk->poll_dev);
+ if (err)
+ goto err_unreg_rfk;
+
+ rfk->registered = 1;
+
+ return;
+err_unreg_rfk:
+ rfkill_unregister(rfk->rfkill);
+err_free_polldev:
+ input_free_polled_device(rfk->poll_dev);
+ rfk->poll_dev = NULL;
+err_free_rfk:
+ rfkill_free(rfk->rfkill);
+ rfk->rfkill = NULL;
+out_error:
+ rfk->registered = 0;
+ b43warn(wl, "RF-kill button init failed\n");
}
-void b43_rfkill_free(struct b43_wldev *dev)
+void b43_rfkill_exit(struct b43_wldev *dev)
{
struct b43_rfkill *rfk = &(dev->wl->rfkill);
+ if (!rfk->registered)
+ return;
+ rfk->registered = 0;
+
+ input_unregister_polled_device(rfk->poll_dev);
+ rfkill_unregister(rfk->rfkill);
input_free_polled_device(rfk->poll_dev);
rfk->poll_dev = NULL;
rfkill_free(rfk->rfkill);
diff --git a/drivers/net/wireless/b43/rfkill.h b/drivers/net/wireless/b43/rfkill.h
index 29544e8c9e5f..adacf936d815 100644
--- a/drivers/net/wireless/b43/rfkill.h
+++ b/drivers/net/wireless/b43/rfkill.h
@@ -15,14 +15,14 @@ struct b43_rfkill {
struct rfkill *rfkill;
/* The poll device for the RFKILL input button */
struct input_polled_dev *poll_dev;
+ /* Did initialization succeed? Used for freeing. */
+ bool registered;
/* The unique name of this rfkill switch */
- char name[32];
+ char name[sizeof("b43-phy4294967295")];
};
-/* All the init functions return void, because we are not interested
+/* The init function returns void, because we are not interested
* in failing the b43 init process when rfkill init failed. */
-void b43_rfkill_alloc(struct b43_wldev *dev);
-void b43_rfkill_free(struct b43_wldev *dev);
void b43_rfkill_init(struct b43_wldev *dev);
void b43_rfkill_exit(struct b43_wldev *dev);
@@ -36,12 +36,6 @@ struct b43_rfkill {
/* empty */
};
-static inline void b43_rfkill_alloc(struct b43_wldev *dev)
-{
-}
-static inline void b43_rfkill_free(struct b43_wldev *dev)
-{
-}
static inline void b43_rfkill_init(struct b43_wldev *dev)
{
}
diff --git a/drivers/net/wireless/b43legacy/debugfs.c b/drivers/net/wireless/b43legacy/debugfs.c
index eefa6fb79685..619b4534ef09 100644
--- a/drivers/net/wireless/b43legacy/debugfs.c
+++ b/drivers/net/wireless/b43legacy/debugfs.c
@@ -124,7 +124,7 @@ static ssize_t shm_read_file(struct b43legacy_wldev *dev, char *buf, size_t bufs
__le16 *le16buf = (__le16 *)buf;
for (i = 0; i < 0x1000; i++) {
- if (bufsize <= 0)
+ if (bufsize < sizeof(tmp))
break;
tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 2 * i);
le16buf[i] = cpu_to_le16(tmp);
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index f0749510bcd7..3bde1e9ab428 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -2260,7 +2260,7 @@ out_requeue:
if (b43legacy_debug(dev, B43legacy_DBG_PWORK_FAST))
delay = msecs_to_jiffies(50);
else
- delay = round_jiffies(HZ);
+ delay = round_jiffies_relative(HZ);
queue_delayed_work(dev->wl->hw->workqueue,
&dev->periodic_work, delay);
out:
@@ -2781,6 +2781,17 @@ static void b43legacy_wireless_core_stop(struct b43legacy_wldev *dev)
if (b43legacy_status(dev) < B43legacy_STAT_STARTED)
return;
+
+ /* Disable and sync interrupts. We must do this before than
+ * setting the status to INITIALIZED, as the interrupt handler
+ * won't care about IRQs then. */
+ spin_lock_irqsave(&wl->irq_lock, flags);
+ dev->irq_savedstate = b43legacy_interrupt_disable(dev,
+ B43legacy_IRQ_ALL);
+ b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK); /* flush */
+ spin_unlock_irqrestore(&wl->irq_lock, flags);
+ b43legacy_synchronize_irq(dev);
+
b43legacy_set_status(dev, B43legacy_STAT_INITIALIZED);
mutex_unlock(&wl->mutex);
@@ -2791,14 +2802,6 @@ static void b43legacy_wireless_core_stop(struct b43legacy_wldev *dev)
ieee80211_stop_queues(wl->hw); /* FIXME this could cause a deadlock */
- /* Disable and sync interrupts. */
- spin_lock_irqsave(&wl->irq_lock, flags);
- dev->irq_savedstate = b43legacy_interrupt_disable(dev,
- B43legacy_IRQ_ALL);
- b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK); /* flush */
- spin_unlock_irqrestore(&wl->irq_lock, flags);
- b43legacy_synchronize_irq(dev);
-
b43legacy_mac_suspend(dev);
free_irq(dev->dev->irq, dev);
b43legacydbg(wl, "Wireless interface stopped\n");
@@ -3306,7 +3309,7 @@ static int b43legacy_start(struct ieee80211_hw *hw)
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev = wl->current_dev;
int did_init = 0;
- int err;
+ int err = 0;
mutex_lock(&wl->mutex);
@@ -3332,7 +3335,7 @@ out_mutex_unlock:
return err;
}
-void b43legacy_stop(struct ieee80211_hw *hw)
+static void b43legacy_stop(struct ieee80211_hw *hw)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev = wl->current_dev;
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c
index 8f198befba39..cb51dc51cce6 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c
@@ -29,7 +29,7 @@
#include "bcm43xx_radio.h"
#include "bcm43xx.h"
-#include <asm/bitops.h>
+#include <linux/bitops.h>
static void bcm43xx_led_changestate(struct bcm43xx_led *led)
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h
index 9ecf2bf0d25d..47c135a7f4dc 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h
@@ -87,7 +87,7 @@ void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm,
/* RX header as received from the hardware. */
struct bcm43xx_rxhdr {
- /* Frame Length. Must be generated explicitely in PIO mode. */
+ /* Frame Length. Must be generated explicitly in PIO mode. */
__le16 frame_length;
PAD_BYTES(2);
/* Flags field 1 */
diff --git a/drivers/net/wireless/hostap/hostap_common.h b/drivers/net/wireless/hostap/hostap_common.h
index ceb7f1e5e9e0..517f89845144 100644
--- a/drivers/net/wireless/hostap/hostap_common.h
+++ b/drivers/net/wireless/hostap/hostap_common.h
@@ -4,9 +4,6 @@
#include <linux/types.h>
#include <linux/if_ether.h>
-#define BIT(x) (1 << (x))
-
-
/* IEEE 802.11 defines */
/* Information Element IDs */
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
index 40f516d42c5e..d8f5efcfcab9 100644
--- a/drivers/net/wireless/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -2920,7 +2920,7 @@ static int prism2_ioctl_priv_monitor(struct net_device *dev, int *i)
printk(KERN_DEBUG "%s: process %d (%s) used deprecated iwpriv monitor "
"- update software to use iwconfig mode monitor\n",
- dev->name, current->pid, current->comm);
+ dev->name, task_pid_nr(current), current->comm);
/* Backward compatibility code - this can be removed at some point */
diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c
index 7da3664b8515..fc876ba18572 100644
--- a/drivers/net/wireless/hostap/hostap_pci.c
+++ b/drivers/net/wireless/hostap/hostap_pci.c
@@ -444,7 +444,7 @@ static int prism2_pci_resume(struct pci_dev *pdev)
MODULE_DEVICE_TABLE(pci, prism2_pci_id_table);
-static struct pci_driver prism2_pci_drv_id = {
+static struct pci_driver prism2_pci_driver = {
.name = "hostap_pci",
.id_table = prism2_pci_id_table,
.probe = prism2_pci_probe,
@@ -458,13 +458,13 @@ static struct pci_driver prism2_pci_drv_id = {
static int __init init_prism2_pci(void)
{
- return pci_register_driver(&prism2_pci_drv_id);
+ return pci_register_driver(&prism2_pci_driver);
}
static void __exit exit_prism2_pci(void)
{
- pci_unregister_driver(&prism2_pci_drv_id);
+ pci_unregister_driver(&prism2_pci_driver);
}
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index 2d46a16c0945..fc6cdd8086c1 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -1267,7 +1267,7 @@ static int ipw2100_start_adapter(struct ipw2100_priv *priv)
IPW2100_INTA_FATAL_ERROR |
IPW2100_INTA_PARITY_ERROR);
}
- } while (i--);
+ } while (--i);
/* Clear out any pending INTAs since we aren't supposed to have
* interrupts enabled at this point... */
@@ -1339,7 +1339,7 @@ static int ipw2100_power_cycle_adapter(struct ipw2100_priv *priv)
if (reg & IPW_AUX_HOST_RESET_REG_MASTER_DISABLED)
break;
- } while (i--);
+ } while (--i);
priv->status &= ~STATUS_RESET_PENDING;
@@ -1769,7 +1769,7 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred)
if (priv->stop_rf_kill) {
priv->stop_rf_kill = 0;
queue_delayed_work(priv->workqueue, &priv->rf_kill,
- round_jiffies(HZ));
+ round_jiffies_relative(HZ));
}
deferred = 1;
@@ -1858,14 +1858,6 @@ static void ipw2100_down(struct ipw2100_priv *priv)
modify_acceptable_latency("ipw2100", INFINITE_LATENCY);
-#ifdef ACPI_CSTATE_LIMIT_DEFINED
- if (priv->config & CFG_C3_DISABLED) {
- IPW_DEBUG_INFO(": Resetting C3 transitions.\n");
- acpi_set_cstate_limit(priv->cstate_limit);
- priv->config &= ~CFG_C3_DISABLED;
- }
-#endif
-
/* We have to signal any supplicant if we are disassociating */
if (associated)
wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL);
@@ -2091,18 +2083,33 @@ static void isr_indicate_rf_kill(struct ipw2100_priv *priv, u32 status)
/* RF_KILL is now enabled (else we wouldn't be here) */
priv->status |= STATUS_RF_KILL_HW;
-#ifdef ACPI_CSTATE_LIMIT_DEFINED
- if (priv->config & CFG_C3_DISABLED) {
- IPW_DEBUG_INFO(": Resetting C3 transitions.\n");
- acpi_set_cstate_limit(priv->cstate_limit);
- priv->config &= ~CFG_C3_DISABLED;
- }
-#endif
-
/* Make sure the RF Kill check timer is running */
priv->stop_rf_kill = 0;
cancel_delayed_work(&priv->rf_kill);
- queue_delayed_work(priv->workqueue, &priv->rf_kill, round_jiffies(HZ));
+ queue_delayed_work(priv->workqueue, &priv->rf_kill,
+ round_jiffies_relative(HZ));
+}
+
+static void send_scan_event(void *data)
+{
+ struct ipw2100_priv *priv = data;
+ union iwreq_data wrqu;
+
+ wrqu.data.length = 0;
+ wrqu.data.flags = 0;
+ wireless_send_event(priv->net_dev, SIOCGIWSCAN, &wrqu, NULL);
+}
+
+static void ipw2100_scan_event_later(struct work_struct *work)
+{
+ send_scan_event(container_of(work, struct ipw2100_priv,
+ scan_event_later.work));
+}
+
+static void ipw2100_scan_event_now(struct work_struct *work)
+{
+ send_scan_event(container_of(work, struct ipw2100_priv,
+ scan_event_now));
}
static void isr_scan_complete(struct ipw2100_priv *priv, u32 status)
@@ -2111,6 +2118,18 @@ static void isr_scan_complete(struct ipw2100_priv *priv, u32 status)
/* Age the scan results... */
priv->ieee->scans++;
priv->status &= ~STATUS_SCANNING;
+
+ /* Only userspace-requested scan completion events go out immediately */
+ if (!priv->user_requested_scan) {
+ if (!delayed_work_pending(&priv->scan_event_later))
+ queue_delayed_work(priv->workqueue,
+ &priv->scan_event_later,
+ round_jiffies_relative(msecs_to_jiffies(4000)));
+ } else {
+ priv->user_requested_scan = 0;
+ cancel_delayed_work(&priv->scan_event_later);
+ queue_work(priv->workqueue, &priv->scan_event_now);
+ }
}
#ifdef CONFIG_IPW2100_DEBUG
@@ -2329,23 +2348,10 @@ static void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i)
u32 match, reg;
int j;
#endif
-#ifdef ACPI_CSTATE_LIMIT_DEFINED
- int limit;
-#endif
IPW_DEBUG_INFO(": PCI latency error detected at 0x%04zX.\n",
i * sizeof(struct ipw2100_status));
-#ifdef ACPI_CSTATE_LIMIT_DEFINED
- IPW_DEBUG_INFO(": Disabling C3 transitions.\n");
- limit = acpi_get_cstate_limit();
- if (limit > 2) {
- priv->cstate_limit = limit;
- acpi_set_cstate_limit(2);
- priv->config |= CFG_C3_DISABLED;
- }
-#endif
-
#ifdef IPW2100_DEBUG_C3
/* Halt the fimrware so we can get a good image */
write_register(priv->net_dev, IPW_REG_RESET_REG,
@@ -4237,7 +4243,7 @@ static int ipw_radio_kill_sw(struct ipw2100_priv *priv, int disable_radio)
priv->stop_rf_kill = 0;
cancel_delayed_work(&priv->rf_kill);
queue_delayed_work(priv->workqueue, &priv->rf_kill,
- round_jiffies(HZ));
+ round_jiffies_relative(HZ));
} else
schedule_reset(priv);
}
@@ -4378,6 +4384,7 @@ static void ipw2100_kill_workqueue(struct ipw2100_priv *priv)
cancel_delayed_work(&priv->wx_event_work);
cancel_delayed_work(&priv->hang_check);
cancel_delayed_work(&priv->rf_kill);
+ cancel_delayed_work(&priv->scan_event_later);
destroy_workqueue(priv->workqueue);
priv->workqueue = NULL;
}
@@ -5975,7 +5982,7 @@ static void ipw2100_rf_kill(struct work_struct *work)
IPW_DEBUG_RF_KILL("RF Kill active, rescheduling GPIO check\n");
if (!priv->stop_rf_kill)
queue_delayed_work(priv->workqueue, &priv->rf_kill,
- round_jiffies(HZ));
+ round_jiffies_relative(HZ));
goto exit_unlock;
}
@@ -6041,7 +6048,7 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev,
* ends up causing problems. So, we just handle
* the WX extensions through the ipw2100_ioctl interface */
- /* memset() puts everything to 0, so we only have explicitely set
+ /* memset() puts everything to 0, so we only have explicitly set
* those values that need to be something else */
/* If power management is turned on, default to AUTO mode */
@@ -6121,6 +6128,8 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev,
INIT_DELAYED_WORK(&priv->wx_event_work, ipw2100_wx_event_work);
INIT_DELAYED_WORK(&priv->hang_check, ipw2100_hang_check);
INIT_DELAYED_WORK(&priv->rf_kill, ipw2100_rf_kill);
+ INIT_WORK(&priv->scan_event_now, ipw2100_scan_event_now);
+ INIT_DELAYED_WORK(&priv->scan_event_later, ipw2100_scan_event_later);
tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
ipw2100_irq_tasklet, (unsigned long)priv);
@@ -7425,6 +7434,8 @@ static int ipw2100_wx_set_scan(struct net_device *dev,
}
IPW_DEBUG_WX("Initiating scan...\n");
+
+ priv->user_requested_scan = 1;
if (ipw2100_set_scan_options(priv) || ipw2100_start_scan(priv)) {
IPW_DEBUG_WX("Start scan failed.\n");
@@ -7499,7 +7510,7 @@ static int ipw2100_wx_set_power(struct net_device *dev,
switch (wrqu->power.flags & IW_POWER_MODE) {
case IW_POWER_ON: /* If not specified */
case IW_POWER_MODE: /* If set all mask */
- case IW_POWER_ALL_R: /* If explicitely state all */
+ case IW_POWER_ALL_R: /* If explicitly state all */
break;
default: /* Otherwise we don't support it */
IPW_DEBUG_WX("SET PM Mode: %X not supported.\n",
diff --git a/drivers/net/wireless/ipw2100.h b/drivers/net/wireless/ipw2100.h
index de7d384d38af..bbf1ddcafba8 100644
--- a/drivers/net/wireless/ipw2100.h
+++ b/drivers/net/wireless/ipw2100.h
@@ -479,7 +479,6 @@ enum {
#define CFG_ASSOCIATE (1<<6)
#define CFG_FIXED_RATE (1<<7)
#define CFG_ADHOC_CREATE (1<<8)
-#define CFG_C3_DISABLED (1<<9)
#define CFG_PASSIVE_SCAN (1<<10)
#ifdef CONFIG_IPW2100_MONITOR
#define CFG_CRC_CHECK (1<<11)
@@ -508,7 +507,6 @@ struct ipw2100_priv {
u8 bssid[ETH_ALEN];
u8 channel;
int last_mode;
- int cstate_limit;
unsigned long connect_start;
unsigned long last_reset;
@@ -588,6 +586,10 @@ struct ipw2100_priv {
struct delayed_work wx_event_work;
struct delayed_work hang_check;
struct delayed_work rf_kill;
+ struct work_struct scan_event_now;
+ struct delayed_work scan_event_later;
+
+ int user_requested_scan;
u32 interrupts;
int tx_interrupts;
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index feb8fcbab2d5..54f44e5473c0 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -1753,7 +1753,7 @@ static int ipw_radio_kill_sw(struct ipw_priv *priv, int disable_radio)
/* Make sure the RF_KILL check timer is running */
cancel_delayed_work(&priv->rf_kill);
queue_delayed_work(priv->workqueue, &priv->rf_kill,
- round_jiffies(2 * HZ));
+ round_jiffies_relative(2 * HZ));
} else
queue_work(priv->workqueue, &priv->up);
}
@@ -4364,7 +4364,7 @@ static void handle_scan_event(struct ipw_priv *priv)
if (!priv->user_requested_scan) {
if (!delayed_work_pending(&priv->scan_event))
queue_delayed_work(priv->workqueue, &priv->scan_event,
- round_jiffies(msecs_to_jiffies(4000)));
+ round_jiffies_relative(msecs_to_jiffies(4000)));
} else {
union iwreq_data wrqu;
@@ -4728,7 +4728,7 @@ static void ipw_rx_notification(struct ipw_priv *priv,
&& priv->status & STATUS_ASSOCIATED)
queue_delayed_work(priv->workqueue,
&priv->request_scan,
- round_jiffies(HZ));
+ round_jiffies_relative(HZ));
/* Send an empty event to user space.
* We don't send the received data on the event because
@@ -9603,7 +9603,7 @@ static int ipw_wx_set_power(struct net_device *dev,
switch (wrqu->power.flags & IW_POWER_MODE) {
case IW_POWER_ON: /* If not specified */
case IW_POWER_MODE: /* If set all mask */
- case IW_POWER_ALL_R: /* If explicitely state all */
+ case IW_POWER_ALL_R: /* If explicitly state all */
break;
default: /* Otherwise we don't support it */
IPW_DEBUG_WX("SET PM Mode: %X not supported.\n",
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index 25cfc6c32509..8d52a26c248a 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -96,8 +96,8 @@ config IWL4965
If you want to compile the driver as a module ( = code which can be
inserted in and remvoed from the running kernel whenever you want),
- say M here and read <file:Documentation/modules.txt>. The module
- will be called iwl4965.ko.
+ say M here and read <file:Documentation/kbuild/modules.txt>. The
+ module will be called iwl4965.ko.
config IWL3945
tristate "Intel PRO/Wireless 3945ABG/BG Network Connection"
@@ -124,5 +124,5 @@ config IWL3945
If you want to compile the driver as a module ( = code which can be
inserted in and remvoed from the running kernel whenever you want),
- say M here and read <file:Documentation/modules.txt>. The module
- will be called iwl3945.ko.
+ say M here and read <file:Documentation/kbuild/modules.txt>. The
+ module will be called iwl3945.ko.
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
index f4aabcf480e4..c48b1b537d2b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
@@ -37,9 +37,6 @@
#include <linux/workqueue.h>
-#include <net/mac80211.h>
-#include <linux/wireless.h>
-
#define IWL 3945
#include "../net/mac80211/ieee80211_rate.h"
@@ -74,19 +71,19 @@ struct iwl_rate_scale_priv {
};
static s32 iwl_expected_tpt_g[IWL_RATE_COUNT] = {
- 0, 0, 76, 104, 130, 168, 191, 202, 7, 13, 35, 58
+ 7, 13, 35, 58, 0, 0, 76, 104, 130, 168, 191, 202
};
static s32 iwl_expected_tpt_g_prot[IWL_RATE_COUNT] = {
- 0, 0, 0, 80, 93, 113, 123, 125, 7, 13, 35, 58
+ 7, 13, 35, 58, 0, 0, 0, 80, 93, 113, 123, 125
};
static s32 iwl_expected_tpt_a[IWL_RATE_COUNT] = {
- 40, 57, 72, 98, 121, 154, 177, 186, 0, 0, 0, 0
+ 0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186
};
static s32 iwl_expected_tpt_b[IWL_RATE_COUNT] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 7, 13, 35, 58
+ 7, 13, 35, 58, 0, 0, 0, 0, 0, 0, 0, 0
};
struct iwl_tpt_entry {
@@ -353,6 +350,10 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
sta->last_txrate = sta->txrate;
+ /* For MODE_IEEE80211A mode it start at IWL_FIRST_OFDM_RATE */
+ if (local->hw.conf.phymode == MODE_IEEE80211A)
+ sta->last_txrate += IWL_FIRST_OFDM_RATE;
+
IWL_DEBUG_RATE("leave\n");
}
@@ -420,6 +421,33 @@ static void rs_free_sta(void *priv, void *priv_sta)
IWL_DEBUG_RATE("leave\n");
}
+
+/*
+ * get ieee prev rate from rate scale table.
+ * for A and B mode we need to overright prev
+ * value
+ */
+static int rs_adjust_next_rate(struct iwl_priv *priv, int rate)
+{
+ int next_rate = iwl_get_prev_ieee_rate(rate);
+
+ switch (priv->phymode) {
+ case MODE_IEEE80211A:
+ if (rate == IWL_RATE_12M_INDEX)
+ next_rate = IWL_RATE_9M_INDEX;
+ else if (rate == IWL_RATE_6M_INDEX)
+ next_rate = IWL_RATE_6M_INDEX;
+ break;
+ case MODE_IEEE80211B:
+ if (rate == IWL_RATE_11M_INDEX_TABLE)
+ next_rate = IWL_RATE_5M_INDEX_TABLE;
+ break;
+ default:
+ break;
+ }
+
+ return next_rate;
+}
/**
* rs_tx_status - Update rate control values based on Tx results
*
@@ -482,7 +510,8 @@ static void rs_tx_status(void *priv_rate,
last_index = scale_rate_index;
} else {
current_count = priv->retry_rate;
- last_index = iwl_get_prev_ieee_rate(scale_rate_index);
+ last_index = rs_adjust_next_rate(priv,
+ scale_rate_index);
}
/* Update this rate accounting for as many retries
@@ -497,9 +526,10 @@ static void rs_tx_status(void *priv_rate,
if (retries)
scale_rate_index =
- iwl_get_prev_ieee_rate(scale_rate_index);
+ rs_adjust_next_rate(priv, scale_rate_index);
}
+
/* Update the last index window with success/failure based on ACK */
IWL_DEBUG_RATE("Update rate %d with %s.\n",
last_index,
@@ -675,7 +705,10 @@ static struct ieee80211_rate *rs_get_rate(void *priv_rate,
}
rate_mask = sta->supp_rates;
- index = min(sta->txrate & 0xffff, IWL_RATE_COUNT - 1);
+ index = min(sta->last_txrate & 0xffff, IWL_RATE_COUNT - 1);
+
+ if (priv->phymode == (u8) MODE_IEEE80211A)
+ rate_mask = rate_mask << IWL_FIRST_OFDM_RATE;
rs_priv = (void *)sta->rate_ctrl_priv;
@@ -804,7 +837,11 @@ static struct ieee80211_rate *rs_get_rate(void *priv_rate,
out:
sta->last_txrate = index;
- sta->txrate = sta->last_txrate;
+ if (priv->phymode == (u8) MODE_IEEE80211A)
+ sta->txrate = sta->last_txrate - IWL_FIRST_OFDM_RATE;
+ else
+ sta->txrate = sta->last_txrate;
+
sta_info_put(sta);
IWL_DEBUG_RATE("leave: %d\n", index);
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h
index b926738e0ea1..bec4d3ffca1d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h
@@ -36,10 +36,17 @@ struct iwl_rate_info {
u8 next_rs; /* next rate used in rs algo */
u8 prev_rs_tgg; /* previous rate used in TGG rs algo */
u8 next_rs_tgg; /* next rate used in TGG rs algo */
+ u8 table_rs_index; /* index in rate scale table cmd */
+ u8 prev_table_rs; /* prev in rate table cmd */
+
};
enum {
- IWL_RATE_6M_INDEX = 0,
+ IWL_RATE_1M_INDEX = 0,
+ IWL_RATE_2M_INDEX,
+ IWL_RATE_5M_INDEX,
+ IWL_RATE_11M_INDEX,
+ IWL_RATE_6M_INDEX,
IWL_RATE_9M_INDEX,
IWL_RATE_12M_INDEX,
IWL_RATE_18M_INDEX,
@@ -47,16 +54,28 @@ enum {
IWL_RATE_36M_INDEX,
IWL_RATE_48M_INDEX,
IWL_RATE_54M_INDEX,
- IWL_RATE_1M_INDEX,
- IWL_RATE_2M_INDEX,
- IWL_RATE_5M_INDEX,
- IWL_RATE_11M_INDEX,
IWL_RATE_COUNT,
IWL_RATE_INVM_INDEX,
IWL_RATE_INVALID = IWL_RATE_INVM_INDEX
};
enum {
+ IWL_RATE_6M_INDEX_TABLE = 0,
+ IWL_RATE_9M_INDEX_TABLE,
+ IWL_RATE_12M_INDEX_TABLE,
+ IWL_RATE_18M_INDEX_TABLE,
+ IWL_RATE_24M_INDEX_TABLE,
+ IWL_RATE_36M_INDEX_TABLE,
+ IWL_RATE_48M_INDEX_TABLE,
+ IWL_RATE_54M_INDEX_TABLE,
+ IWL_RATE_1M_INDEX_TABLE,
+ IWL_RATE_2M_INDEX_TABLE,
+ IWL_RATE_5M_INDEX_TABLE,
+ IWL_RATE_11M_INDEX_TABLE,
+ IWL_RATE_INVM_INDEX_TABLE = IWL_RATE_INVM_INDEX,
+};
+
+enum {
IWL_FIRST_OFDM_RATE = IWL_RATE_6M_INDEX,
IWL_LAST_OFDM_RATE = IWL_RATE_54M_INDEX,
IWL_FIRST_CCK_RATE = IWL_RATE_1M_INDEX,
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index acb38750535f..3a45fe99a83e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -38,7 +38,6 @@
#include <net/mac80211.h>
#include <linux/etherdevice.h>
-#include <linux/delay.h>
#define IWL 3945
@@ -55,7 +54,9 @@
IWL_RATE_##rp##M_INDEX, \
IWL_RATE_##rn##M_INDEX, \
IWL_RATE_##pp##M_INDEX, \
- IWL_RATE_##np##M_INDEX }
+ IWL_RATE_##np##M_INDEX, \
+ IWL_RATE_##r##M_INDEX_TABLE, \
+ IWL_RATE_##ip##M_INDEX_TABLE }
/*
* Parameter order:
@@ -66,6 +67,10 @@
*
*/
const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT] = {
+ IWL_DECLARE_RATE_INFO(1, INV, 2, INV, 2, INV, 2), /* 1mbps */
+ IWL_DECLARE_RATE_INFO(2, 1, 5, 1, 5, 1, 5), /* 2mbps */
+ IWL_DECLARE_RATE_INFO(5, 2, 6, 2, 11, 2, 11), /*5.5mbps */
+ IWL_DECLARE_RATE_INFO(11, 9, 12, 5, 12, 5, 18), /* 11mbps */
IWL_DECLARE_RATE_INFO(6, 5, 9, 5, 11, 5, 11), /* 6mbps */
IWL_DECLARE_RATE_INFO(9, 6, 11, 5, 11, 5, 11), /* 9mbps */
IWL_DECLARE_RATE_INFO(12, 11, 18, 11, 18, 11, 18), /* 12mbps */
@@ -74,10 +79,6 @@ const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT] = {
IWL_DECLARE_RATE_INFO(36, 24, 48, 24, 48, 24, 48), /* 36mbps */
IWL_DECLARE_RATE_INFO(48, 36, 54, 36, 54, 36, 54), /* 48mbps */
IWL_DECLARE_RATE_INFO(54, 48, INV, 48, INV, 48, INV),/* 54mbps */
- IWL_DECLARE_RATE_INFO(1, INV, 2, INV, 2, INV, 2), /* 1mbps */
- IWL_DECLARE_RATE_INFO(2, 1, 5, 1, 5, 1, 5), /* 2mbps */
- IWL_DECLARE_RATE_INFO(5, 2, 6, 2, 11, 2, 11), /*5.5mbps */
- IWL_DECLARE_RATE_INFO(11, 9, 12, 5, 12, 5, 18), /* 11mbps */
};
/* 1 = enable the iwl_disable_events() function */
@@ -663,10 +664,11 @@ void iwl_hw_build_tx_cmd_rate(struct iwl_priv *priv,
cmd->cmd.tx.tx_flags = tx_flags;
/* OFDM */
- cmd->cmd.tx.supp_rates[0] = rate_mask & IWL_OFDM_RATES_MASK;
+ cmd->cmd.tx.supp_rates[0] =
+ ((rate_mask & IWL_OFDM_RATES_MASK) >> IWL_FIRST_OFDM_RATE) & 0xFF;
/* CCK */
- cmd->cmd.tx.supp_rates[1] = (rate_mask >> 8) & 0xF;
+ cmd->cmd.tx.supp_rates[1] = (rate_mask & 0xF);
IWL_DEBUG_RATE("Tx sta id: %d, rate: %d (plcp), flags: 0x%4X "
"cck/ofdm mask: 0x%x/0x%x\n", sta_id,
@@ -1433,7 +1435,7 @@ static void iwl_hw_reg_set_scan_power(struct iwl_priv *priv, u32 scan_tbl_index,
/* use this channel group's 6Mbit clipping/saturation pwr,
* but cap at regulatory scan power restriction (set during init
* based on eeprom channel data) for this channel. */
- power = min(ch_info->scan_power, clip_pwrs[IWL_RATE_6M_INDEX]);
+ power = min(ch_info->scan_power, clip_pwrs[IWL_RATE_6M_INDEX_TABLE]);
/* further limit to user's max power preference.
* FIXME: Other spectrum management power limitations do not
@@ -1448,7 +1450,7 @@ static void iwl_hw_reg_set_scan_power(struct iwl_priv *priv, u32 scan_tbl_index,
* *index*. */
power_index = ch_info->power_info[rate_index].power_table_index
- (power - ch_info->power_info
- [IWL_RATE_6M_INDEX].requested_power) * 2;
+ [IWL_RATE_6M_INDEX_TABLE].requested_power) * 2;
/* store reference index that we use when adjusting *all* scan
* powers. So we can accommodate user (all channel) or spectrum
@@ -1477,7 +1479,7 @@ static void iwl_hw_reg_set_scan_power(struct iwl_priv *priv, u32 scan_tbl_index,
*/
int iwl_hw_reg_send_txpower(struct iwl_priv *priv)
{
- int rate_idx;
+ int rate_idx, i;
const struct iwl_channel_info *ch_info = NULL;
struct iwl_txpowertable_cmd txpower = {
.channel = priv->active_rxon.channel,
@@ -1501,20 +1503,36 @@ int iwl_hw_reg_send_txpower(struct iwl_priv *priv)
}
/* fill cmd with power settings for all rates for current channel */
- for (rate_idx = 0; rate_idx < IWL_RATE_COUNT; rate_idx++) {
- txpower.power[rate_idx].tpc = ch_info->power_info[rate_idx].tpc;
- txpower.power[rate_idx].rate = iwl_rates[rate_idx].plcp;
+ /* Fill OFDM rate */
+ for (rate_idx = IWL_FIRST_OFDM_RATE, i = 0;
+ rate_idx <= IWL_LAST_OFDM_RATE; rate_idx++, i++) {
+
+ txpower.power[i].tpc = ch_info->power_info[i].tpc;
+ txpower.power[i].rate = iwl_rates[rate_idx].plcp;
IWL_DEBUG_POWER("ch %d:%d rf %d dsp %3d rate code 0x%02x\n",
le16_to_cpu(txpower.channel),
txpower.band,
- txpower.power[rate_idx].tpc.tx_gain,
- txpower.power[rate_idx].tpc.dsp_atten,
- txpower.power[rate_idx].rate);
+ txpower.power[i].tpc.tx_gain,
+ txpower.power[i].tpc.dsp_atten,
+ txpower.power[i].rate);
+ }
+ /* Fill CCK rates */
+ for (rate_idx = IWL_FIRST_CCK_RATE;
+ rate_idx <= IWL_LAST_CCK_RATE; rate_idx++, i++) {
+ txpower.power[i].tpc = ch_info->power_info[i].tpc;
+ txpower.power[i].rate = iwl_rates[rate_idx].plcp;
+
+ IWL_DEBUG_POWER("ch %d:%d rf %d dsp %3d rate code 0x%02x\n",
+ le16_to_cpu(txpower.channel),
+ txpower.band,
+ txpower.power[i].tpc.tx_gain,
+ txpower.power[i].tpc.dsp_atten,
+ txpower.power[i].rate);
}
return iwl_send_cmd_pdu(priv, REPLY_TX_PWR_TABLE_CMD,
- sizeof(struct iwl_txpowertable_cmd), &txpower);
+ sizeof(struct iwl_txpowertable_cmd), &txpower);
}
@@ -1550,7 +1568,7 @@ static int iwl_hw_reg_set_new_power(struct iwl_priv *priv,
power_info = ch_info->power_info;
/* update OFDM Txpower settings */
- for (i = IWL_FIRST_OFDM_RATE; i <= IWL_LAST_OFDM_RATE;
+ for (i = IWL_RATE_6M_INDEX_TABLE; i <= IWL_RATE_54M_INDEX_TABLE;
i++, ++power_info) {
int delta_idx;
@@ -1574,14 +1592,14 @@ static int iwl_hw_reg_set_new_power(struct iwl_priv *priv,
* ... all CCK power settings for a given channel are the *same*. */
if (power_changed) {
power =
- ch_info->power_info[IWL_RATE_12M_INDEX].
+ ch_info->power_info[IWL_RATE_12M_INDEX_TABLE].
requested_power + IWL_CCK_FROM_OFDM_POWER_DIFF;
/* do all CCK rates' iwl_channel_power_info structures */
- for (i = IWL_FIRST_CCK_RATE; i <= IWL_LAST_CCK_RATE; i++) {
+ for (i = IWL_RATE_1M_INDEX_TABLE; i <= IWL_RATE_11M_INDEX_TABLE; i++) {
power_info->requested_power = power;
power_info->base_power_index =
- ch_info->power_info[IWL_RATE_12M_INDEX].
+ ch_info->power_info[IWL_RATE_12M_INDEX_TABLE].
base_power_index + IWL_CCK_FROM_OFDM_INDEX_DIFF;
++power_info;
}
@@ -1675,7 +1693,7 @@ static int iwl_hw_reg_comp_txpower_temp(struct iwl_priv *priv)
for (scan_tbl_index = 0;
scan_tbl_index < IWL_NUM_SCAN_RATES; scan_tbl_index++) {
s32 actual_index = (scan_tbl_index == 0) ?
- IWL_RATE_1M_INDEX : IWL_RATE_6M_INDEX;
+ IWL_RATE_1M_INDEX_TABLE : IWL_RATE_6M_INDEX_TABLE;
iwl_hw_reg_set_scan_power(priv, scan_tbl_index,
actual_index, clip_pwrs,
ch_info, a_band);
@@ -1906,19 +1924,19 @@ static void iwl_hw_reg_init_channel_groups(struct iwl_priv *priv)
for (rate_index = 0;
rate_index < IWL_RATE_COUNT; rate_index++, clip_pwrs++) {
switch (rate_index) {
- case IWL_RATE_36M_INDEX:
+ case IWL_RATE_36M_INDEX_TABLE:
if (i == 0) /* B/G */
*clip_pwrs = satur_pwr;
else /* A */
*clip_pwrs = satur_pwr - 5;
break;
- case IWL_RATE_48M_INDEX:
+ case IWL_RATE_48M_INDEX_TABLE:
if (i == 0)
*clip_pwrs = satur_pwr - 7;
else
*clip_pwrs = satur_pwr - 10;
break;
- case IWL_RATE_54M_INDEX:
+ case IWL_RATE_54M_INDEX_TABLE:
if (i == 0)
*clip_pwrs = satur_pwr - 9;
else
@@ -2032,7 +2050,7 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
}
/* set tx power for CCK rates, based on OFDM 12 Mbit settings*/
- pwr_info = &ch_info->power_info[IWL_RATE_12M_INDEX];
+ pwr_info = &ch_info->power_info[IWL_RATE_12M_INDEX_TABLE];
power = pwr_info->requested_power +
IWL_CCK_FROM_OFDM_POWER_DIFF;
pwr_index = pwr_info->power_table_index +
@@ -2048,9 +2066,9 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
/* fill each CCK rate's iwl_channel_power_info structure
* NOTE: All CCK-rate Txpwrs are the same for a given chnl!
* NOTE: CCK rates start at end of OFDM rates! */
- for (rate_index = IWL_OFDM_RATES;
- rate_index < IWL_RATE_COUNT; rate_index++) {
- pwr_info = &ch_info->power_info[rate_index];
+ for (rate_index = 0;
+ rate_index < IWL_CCK_RATES; rate_index++) {
+ pwr_info = &ch_info->power_info[rate_index+IWL_OFDM_RATES];
pwr_info->requested_power = power;
pwr_info->power_table_index = pwr_index;
pwr_info->base_power_index = base_pwr_index;
@@ -2062,7 +2080,7 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
for (scan_tbl_index = 0;
scan_tbl_index < IWL_NUM_SCAN_RATES; scan_tbl_index++) {
s32 actual_index = (scan_tbl_index == 0) ?
- IWL_RATE_1M_INDEX : IWL_RATE_6M_INDEX;
+ IWL_RATE_1M_INDEX_TABLE : IWL_RATE_6M_INDEX_TABLE;
iwl_hw_reg_set_scan_power(priv, scan_tbl_index,
actual_index, clip_pwrs, ch_info, a_band);
}
@@ -2140,17 +2158,20 @@ int iwl_hw_get_rx_read(struct iwl_priv *priv)
*/
int iwl3945_init_hw_rate_table(struct iwl_priv *priv)
{
- int rc, i;
+ int rc, i, index, prev_index;
struct iwl_rate_scaling_cmd rate_cmd = {
.reserved = {0, 0, 0},
};
struct iwl_rate_scaling_info *table = rate_cmd.table;
for (i = 0; i < ARRAY_SIZE(iwl_rates); i++) {
- table[i].rate_n_flags =
+ index = iwl_rates[i].table_rs_index;
+
+ table[index].rate_n_flags =
iwl_hw_set_rate_n_flags(iwl_rates[i].plcp, 0);
- table[i].try_cnt = priv->retry_rate;
- table[i].next_rate_index = iwl_get_prev_ieee_rate(i);
+ table[index].try_cnt = priv->retry_rate;
+ prev_index = iwl_get_prev_ieee_rate(i);
+ table[index].next_rate_index = iwl_rates[prev_index].table_rs_index;
}
switch (priv->phymode) {
@@ -2158,26 +2179,26 @@ int iwl3945_init_hw_rate_table(struct iwl_priv *priv)
IWL_DEBUG_RATE("Select A mode rate scale\n");
/* If one of the following CCK rates is used,
* have it fall back to the 6M OFDM rate */
- for (i = IWL_FIRST_CCK_RATE; i <= IWL_LAST_CCK_RATE; i++)
- table[i].next_rate_index = IWL_FIRST_OFDM_RATE;
+ for (i = IWL_RATE_1M_INDEX_TABLE; i <= IWL_RATE_11M_INDEX_TABLE; i++)
+ table[i].next_rate_index = iwl_rates[IWL_FIRST_OFDM_RATE].table_rs_index;
/* Don't fall back to CCK rates */
- table[IWL_RATE_12M_INDEX].next_rate_index = IWL_RATE_9M_INDEX;
+ table[IWL_RATE_12M_INDEX_TABLE].next_rate_index = IWL_RATE_9M_INDEX_TABLE;
/* Don't drop out of OFDM rates */
- table[IWL_FIRST_OFDM_RATE].next_rate_index =
- IWL_FIRST_OFDM_RATE;
+ table[IWL_RATE_6M_INDEX_TABLE].next_rate_index =
+ iwl_rates[IWL_FIRST_OFDM_RATE].table_rs_index;
break;
case MODE_IEEE80211B:
IWL_DEBUG_RATE("Select B mode rate scale\n");
/* If an OFDM rate is used, have it fall back to the
* 1M CCK rates */
- for (i = IWL_FIRST_OFDM_RATE; i <= IWL_LAST_OFDM_RATE; i++)
- table[i].next_rate_index = IWL_FIRST_CCK_RATE;
+ for (i = IWL_RATE_6M_INDEX_TABLE; i <= IWL_RATE_54M_INDEX_TABLE; i++)
+ table[i].next_rate_index = iwl_rates[IWL_FIRST_CCK_RATE].table_rs_index;
/* CCK shouldn't fall back to OFDM... */
- table[IWL_RATE_11M_INDEX].next_rate_index = IWL_RATE_5M_INDEX;
+ table[IWL_RATE_11M_INDEX_TABLE].next_rate_index = IWL_RATE_5M_INDEX_TABLE;
break;
default:
@@ -2249,22 +2270,12 @@ unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
tx_beacon_cmd->tx.tx_flags = (TX_CMD_FLG_SEQ_CTL_MSK |
TX_CMD_FLG_TSF_MSK);
- /* supp_rates[0] == OFDM */
- tx_beacon_cmd->tx.supp_rates[0] = IWL_OFDM_BASIC_RATES_MASK;
-
- /* supp_rates[1] == CCK
- *
- * NOTE: IWL_*_RATES_MASK are not in the order that supp_rates
- * expects so we have to shift them around.
- *
- * supp_rates expects:
- * CCK rates are bit0..3
- *
- * However IWL_*_RATES_MASK has:
- * CCK rates are bit8..11
- */
+ /* supp_rates[0] == OFDM start at IWL_FIRST_OFDM_RATE*/
+ tx_beacon_cmd->tx.supp_rates[0] =
+ (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
+
tx_beacon_cmd->tx.supp_rates[1] =
- (IWL_CCK_BASIC_RATES_MASK >> 8) & 0xF;
+ (IWL_CCK_BASIC_RATES_MASK & 0xF);
return (sizeof(struct iwl_tx_beacon_cmd) + frame_size);
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
index 287c75705c44..8dc78c0bf1ff 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
@@ -36,9 +36,6 @@
#include <linux/workqueue.h>
-#include <net/mac80211.h>
-#include <linux/wireless.h>
-
#define IWL 4965
#include "../net/mac80211/ieee80211_rate.h"
@@ -2024,12 +2021,18 @@ static int open_file_generic(struct inode *inode, struct file *file)
static void rs_dbgfs_set_mcs(struct iwl_rate_scale_priv *rs_priv,
struct iwl_rate *mcs, int index)
{
- const u32 cck_rate = 0x820A;
+ u32 base_rate;
+
+ if (rs_priv->phymode == (u8) MODE_IEEE80211A)
+ base_rate = 0x800D;
+ else
+ base_rate = 0x820A;
+
if (rs_priv->dbg_fixed.rate_n_flags) {
if (index < 12)
mcs->rate_n_flags = rs_priv->dbg_fixed.rate_n_flags;
else
- mcs->rate_n_flags = cck_rate;
+ mcs->rate_n_flags = base_rate;
IWL_DEBUG_RATE("Fixed rate ON\n");
return;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index b50d20267c8a..891f90d2f019 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -35,9 +35,7 @@
#include <linux/netdevice.h>
#include <linux/wireless.h>
#include <net/mac80211.h>
-#include <linux/netdevice.h>
#include <linux/etherdevice.h>
-#include <linux/delay.h>
#define IWL 4965
@@ -3234,9 +3232,7 @@ int iwl4965_tx_cmd(struct iwl_priv *priv, struct iwl_cmd *out_cmd,
tx->rate_n_flags = iwl_hw_set_rate_n_flags(iwl_rates[rate_index].plcp,
rate_flags);
- if (ieee80211_is_probe_request(fc))
- tx->tx_flags |= TX_CMD_FLG_TSF_MSK;
- else if (ieee80211_is_back_request(fc))
+ if (ieee80211_is_back_request(fc))
tx->tx_flags |= TX_CMD_FLG_ACK_MSK |
TX_CMD_FLG_IMM_BA_RSP_MASK;
#ifdef CONFIG_IWLWIFI_HT
@@ -3874,7 +3870,7 @@ static void iwl4965_rx_reply_rx(struct iwl_priv *priv,
*/
case IEEE80211_STYPE_ASSOC_RESP:
case IEEE80211_STYPE_REASSOC_RESP:
- if (network_packet && iwl_is_associated(priv)) {
+ if (network_packet) {
#ifdef CONFIG_IWLWIFI_HT
u8 *pos = NULL;
struct ieee802_11_elems elems;
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 75e3b5c3f155..465da4f67ce7 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -48,8 +48,6 @@
#include <linux/netdevice.h>
#include <linux/wireless.h>
#include <linux/firmware.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/if_arp.h>
@@ -1749,21 +1747,22 @@ static void iwl_unset_hw_setting(struct iwl_priv *priv)
* return : set the bit for each supported rate insert in ie
*/
static u16 iwl_supported_rate_to_ie(u8 *ie, u16 supported_rate,
- u16 basic_rate, int max_count)
+ u16 basic_rate, int *left)
{
u16 ret_rates = 0, bit;
int i;
- u8 *rates;
-
- rates = &(ie[1]);
+ u8 *cnt = ie;
+ u8 *rates = ie + 1;
for (bit = 1, i = 0; i < IWL_RATE_COUNT; i++, bit <<= 1) {
if (bit & supported_rate) {
ret_rates |= bit;
- rates[*ie] = iwl_rates[i].ieee |
- ((bit & basic_rate) ? 0x80 : 0x00);
- *ie = *ie + 1;
- if (*ie >= max_count)
+ rates[*cnt] = iwl_rates[i].ieee |
+ ((bit & basic_rate) ? 0x80 : 0x00);
+ (*cnt)++;
+ (*left)--;
+ if ((*left <= 0) ||
+ (*cnt >= IWL_SUPPORTED_RATES_IE_LEN))
break;
}
}
@@ -1780,7 +1779,7 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv,
{
int len = 0;
u8 *pos = NULL;
- u16 ret_rates;
+ u16 active_rates, ret_rates, cck_rates;
/* Make sure there is enough space for the probe request,
* two mandatory IEs and the data */
@@ -1825,19 +1824,27 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv,
left -= 2;
if (left < 0)
return 0;
+
/* ... fill it in... */
*pos++ = WLAN_EID_SUPP_RATES;
*pos = 0;
- ret_rates = priv->active_rate = priv->rates_mask;
+
+ priv->active_rate = priv->rates_mask;
+ active_rates = priv->active_rate;
priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK;
- iwl_supported_rate_to_ie(pos, priv->active_rate,
- priv->active_rate_basic, left);
+ cck_rates = IWL_CCK_RATES_MASK & active_rates;
+ ret_rates = iwl_supported_rate_to_ie(pos, cck_rates,
+ priv->active_rate_basic, &left);
+ active_rates &= ~ret_rates;
+
+ ret_rates = iwl_supported_rate_to_ie(pos, active_rates,
+ priv->active_rate_basic, &left);
+ active_rates &= ~ret_rates;
+
len += 2 + *pos;
pos += (*pos) + 1;
- ret_rates = ~ret_rates & priv->active_rate;
-
- if (ret_rates == 0)
+ if (active_rates == 0)
goto fill_end;
/* fill in supported extended rate */
@@ -1848,7 +1855,8 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv,
/* ... fill it in... */
*pos++ = WLAN_EID_EXT_SUPP_RATES;
*pos = 0;
- iwl_supported_rate_to_ie(pos, ret_rates, priv->active_rate_basic, left);
+ iwl_supported_rate_to_ie(pos, active_rates,
+ priv->active_rate_basic, &left);
if (*pos > 0)
len += 2 + *pos;
@@ -4842,7 +4850,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
/* Hardware disappeared */
IWL_WARNING("HARDWARE GONE?? INTA == 0x%080x\n", inta);
- goto none;
+ goto unplugged;
}
IWL_DEBUG_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
@@ -4850,6 +4858,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
/* iwl_irq_tasklet() will service interrupts and re-enable them */
tasklet_schedule(&priv->irq_tasklet);
+unplugged:
spin_unlock(&priv->lock);
return IRQ_HANDLED;
@@ -5323,13 +5332,13 @@ static int iwl_init_geos(struct iwl_priv *priv)
/* 5.2GHz channels start after the 2.4GHz channels */
modes[A].mode = MODE_IEEE80211A;
modes[A].channels = &channels[ARRAY_SIZE(iwl_eeprom_band_1)];
- modes[A].rates = rates;
+ modes[A].rates = &rates[4];
modes[A].num_rates = 8; /* just OFDM */
modes[A].num_channels = 0;
modes[B].mode = MODE_IEEE80211B;
modes[B].channels = channels;
- modes[B].rates = &rates[8];
+ modes[B].rates = rates;
modes[B].num_rates = 4; /* just CCK */
modes[B].num_channels = 0;
@@ -6470,8 +6479,9 @@ static void iwl_bg_scan_check(struct work_struct *data)
IWL_DEBUG(IWL_DL_INFO | IWL_DL_SCAN,
"Scan completion watchdog resetting adapter (%dms)\n",
jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG));
+
if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
- queue_work(priv->workqueue, &priv->restart);
+ iwl_send_scan_abort(priv);
}
mutex_unlock(&priv->mutex);
}
@@ -6567,7 +6577,7 @@ static void iwl_bg_request_scan(struct work_struct *data)
spin_unlock_irqrestore(&priv->lock, flags);
scan->suspend_time = 0;
- scan->max_out_time = cpu_to_le32(600 * 1024);
+ scan->max_out_time = cpu_to_le32(200 * 1024);
if (!interval)
interval = suspend_time;
/*
@@ -6597,7 +6607,7 @@ static void iwl_bg_request_scan(struct work_struct *data)
memcpy(scan->direct_scan[0].ssid,
priv->direct_ssid, priv->direct_ssid_len);
direct_mask = 1;
- } else if (!iwl_is_associated(priv)) {
+ } else if (!iwl_is_associated(priv) && priv->essid_len) {
scan->direct_scan[0].id = WLAN_EID_SSID;
scan->direct_scan[0].len = priv->essid_len;
memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len);
@@ -6736,6 +6746,12 @@ static void iwl_bg_post_associate(struct work_struct *data)
mutex_lock(&priv->mutex);
+ if (!priv->interface_id || !priv->is_open) {
+ mutex_unlock(&priv->mutex);
+ return;
+ }
+ iwl_scan_cancel_timeout(priv, 200);
+
conf = ieee80211_get_hw_conf(priv->hw);
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
@@ -6874,9 +6890,19 @@ static void iwl_mac_stop(struct ieee80211_hw *hw)
struct iwl_priv *priv = hw->priv;
IWL_DEBUG_MAC80211("enter\n");
+
+
+ mutex_lock(&priv->mutex);
+ /* stop mac, cancel any scan request and clear
+ * RXON_FILTER_ASSOC_MSK BIT
+ */
priv->is_open = 0;
- /*netif_stop_queue(dev); */
- flush_workqueue(priv->workqueue);
+ iwl_scan_cancel_timeout(priv, 100);
+ cancel_delayed_work(&priv->post_associate);
+ priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+ iwl_commit_rxon(priv);
+ mutex_unlock(&priv->mutex);
+
IWL_DEBUG_MAC80211("leave\n");
}
@@ -7161,8 +7187,6 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, int if_id,
if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
iwl_config_ap(priv);
else {
- priv->staging_rxon.filter_flags |=
- RXON_FILTER_ASSOC_MSK;
rc = iwl_commit_rxon(priv);
if ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && rc)
iwl_add_station(priv,
@@ -7170,6 +7194,7 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, int if_id,
}
} else {
+ iwl_scan_cancel_timeout(priv, 100);
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
iwl_commit_rxon(priv);
}
@@ -7209,6 +7234,12 @@ static void iwl_mac_remove_interface(struct ieee80211_hw *hw,
IWL_DEBUG_MAC80211("enter\n");
mutex_lock(&priv->mutex);
+
+ iwl_scan_cancel_timeout(priv, 100);
+ cancel_delayed_work(&priv->post_associate);
+ priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+ iwl_commit_rxon(priv);
+
if (priv->interface_id == conf->if_id) {
priv->interface_id = 0;
memset(priv->bssid, 0, ETH_ALEN);
@@ -7230,6 +7261,7 @@ static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
IWL_DEBUG_MAC80211("enter\n");
+ mutex_lock(&priv->mutex);
spin_lock_irqsave(&priv->lock, flags);
if (!iwl_is_ready_rf(priv)) {
@@ -7260,7 +7292,8 @@ static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
priv->direct_ssid_len = (u8)
min((u8) len, (u8) IW_ESSID_MAX_SIZE);
memcpy(priv->direct_ssid, ssid, priv->direct_ssid_len);
- }
+ } else
+ priv->one_direct_scan = 0;
rc = iwl_scan_initiate(priv);
@@ -7268,6 +7301,7 @@ static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
out_unlock:
spin_unlock_irqrestore(&priv->lock, flags);
+ mutex_unlock(&priv->mutex);
return rc;
}
@@ -7302,6 +7336,8 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
mutex_lock(&priv->mutex);
+ iwl_scan_cancel_timeout(priv, 100);
+
switch (cmd) {
case SET_KEY:
rc = iwl_update_sta_key_info(priv, key, sta_id);
@@ -7471,8 +7507,18 @@ static void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
spin_unlock_irqrestore(&priv->lock, flags);
+ /* we are restarting association process
+ * clear RXON_FILTER_ASSOC_MSK bit
+ */
+ if (priv->iw_mode != IEEE80211_IF_TYPE_AP) {
+ iwl_scan_cancel_timeout(priv, 100);
+ priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+ iwl_commit_rxon(priv);
+ }
+
/* Per mac80211.h: This is only used in IBSS mode... */
if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) {
+
IWL_DEBUG_MAC80211("leave - not in IBSS\n");
mutex_unlock(&priv->mutex);
return;
@@ -8309,6 +8355,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
SET_IEEE80211_DEV(hw, &pdev->dev);
+ hw->rate_control_algorithm = "iwl-3945-rs";
+
IWL_DEBUG_INFO("*** LOAD DRIVER ***\n");
priv = hw->priv;
priv->hw = hw;
@@ -8550,6 +8598,9 @@ static void iwl_pci_remove(struct pci_dev *pdev)
iwl_rate_control_unregister(priv->hw);
}
+ /*netif_stop_queue(dev); */
+ flush_workqueue(priv->workqueue);
+
/* ieee80211_unregister_hw calls iwl_mac_stop, which flushes
* priv->workqueue... so we can't take down the workqueue
* until now... */
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index b1a6e39f7821..9918780f5e86 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -48,8 +48,6 @@
#include <linux/netdevice.h>
#include <linux/wireless.h>
#include <linux/firmware.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/if_arp.h>
@@ -1802,21 +1800,22 @@ static void iwl_unset_hw_setting(struct iwl_priv *priv)
* return : set the bit for each supported rate insert in ie
*/
static u16 iwl_supported_rate_to_ie(u8 *ie, u16 supported_rate,
- u16 basic_rate, int max_count)
+ u16 basic_rate, int *left)
{
u16 ret_rates = 0, bit;
int i;
- u8 *rates;
-
- rates = &(ie[1]);
+ u8 *cnt = ie;
+ u8 *rates = ie + 1;
for (bit = 1, i = 0; i < IWL_RATE_COUNT; i++, bit <<= 1) {
if (bit & supported_rate) {
ret_rates |= bit;
- rates[*ie] = iwl_rates[i].ieee |
- ((bit & basic_rate) ? 0x80 : 0x00);
- *ie = *ie + 1;
- if (*ie >= max_count)
+ rates[*cnt] = iwl_rates[i].ieee |
+ ((bit & basic_rate) ? 0x80 : 0x00);
+ (*cnt)++;
+ (*left)--;
+ if ((*left <= 0) ||
+ (*cnt >= IWL_SUPPORTED_RATES_IE_LEN))
break;
}
}
@@ -1839,7 +1838,7 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv,
{
int len = 0;
u8 *pos = NULL;
- u16 ret_rates;
+ u16 active_rates, ret_rates, cck_rates;
/* Make sure there is enough space for the probe request,
* two mandatory IEs and the data */
@@ -1884,19 +1883,27 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv,
left -= 2;
if (left < 0)
return 0;
+
/* ... fill it in... */
*pos++ = WLAN_EID_SUPP_RATES;
*pos = 0;
- ret_rates = priv->active_rate = priv->rates_mask;
+
+ priv->active_rate = priv->rates_mask;
+ active_rates = priv->active_rate;
priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK;
- iwl_supported_rate_to_ie(pos, priv->active_rate,
- priv->active_rate_basic, left);
+ cck_rates = IWL_CCK_RATES_MASK & active_rates;
+ ret_rates = iwl_supported_rate_to_ie(pos, cck_rates,
+ priv->active_rate_basic, &left);
+ active_rates &= ~ret_rates;
+
+ ret_rates = iwl_supported_rate_to_ie(pos, active_rates,
+ priv->active_rate_basic, &left);
+ active_rates &= ~ret_rates;
+
len += 2 + *pos;
pos += (*pos) + 1;
- ret_rates = ~ret_rates & priv->active_rate;
-
- if (ret_rates == 0)
+ if (active_rates == 0)
goto fill_end;
/* fill in supported extended rate */
@@ -1907,7 +1914,8 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv,
/* ... fill it in... */
*pos++ = WLAN_EID_EXT_SUPP_RATES;
*pos = 0;
- iwl_supported_rate_to_ie(pos, ret_rates, priv->active_rate_basic, left);
+ iwl_supported_rate_to_ie(pos, active_rates,
+ priv->active_rate_basic, &left);
if (*pos > 0)
len += 2 + *pos;
@@ -4494,13 +4502,13 @@ static u8 ratio2dB[100] = {
* Conversion assumes that levels are voltages (20*log), not powers (10*log). */
int iwl_calc_db_from_ratio(int sig_ratio)
{
- /* Anything above 1000:1 just report as 60 dB */
- if (sig_ratio > 1000)
+ /* 1000:1 or higher just report as 60 dB */
+ if (sig_ratio >= 1000)
return 60;
- /* Above 100:1, divide by 10 and use table,
+ /* 100:1 or higher, divide by 10 and use table,
* add 20 dB to make up for divide by 10 */
- if (sig_ratio > 100)
+ if (sig_ratio >= 100)
return (20 + (int)ratio2dB[sig_ratio/10]);
/* We shouldn't see this */
@@ -5148,9 +5156,10 @@ static irqreturn_t iwl_isr(int irq, void *data)
}
if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
- /* Hardware disappeared */
+ /* Hardware disappeared. It might have already raised
+ * an interrupt */
IWL_WARNING("HARDWARE GONE?? INTA == 0x%080x\n", inta);
- goto none;
+ goto unplugged;
}
IWL_DEBUG_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
@@ -5158,8 +5167,9 @@ static irqreturn_t iwl_isr(int irq, void *data)
/* iwl_irq_tasklet() will service interrupts and re-enable them */
tasklet_schedule(&priv->irq_tasklet);
- spin_unlock(&priv->lock);
+ unplugged:
+ spin_unlock(&priv->lock);
return IRQ_HANDLED;
none:
@@ -6837,8 +6847,9 @@ static void iwl_bg_scan_check(struct work_struct *data)
IWL_DEBUG(IWL_DL_INFO | IWL_DL_SCAN,
"Scan completion watchdog resetting adapter (%dms)\n",
jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG));
+
if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
- queue_work(priv->workqueue, &priv->restart);
+ iwl_send_scan_abort(priv);
}
mutex_unlock(&priv->mutex);
}
@@ -6934,7 +6945,7 @@ static void iwl_bg_request_scan(struct work_struct *data)
spin_unlock_irqrestore(&priv->lock, flags);
scan->suspend_time = 0;
- scan->max_out_time = cpu_to_le32(600 * 1024);
+ scan->max_out_time = cpu_to_le32(200 * 1024);
if (!interval)
interval = suspend_time;
@@ -6957,7 +6968,7 @@ static void iwl_bg_request_scan(struct work_struct *data)
memcpy(scan->direct_scan[0].ssid,
priv->direct_ssid, priv->direct_ssid_len);
direct_mask = 1;
- } else if (!iwl_is_associated(priv)) {
+ } else if (!iwl_is_associated(priv) && priv->essid_len) {
scan->direct_scan[0].id = WLAN_EID_SSID;
scan->direct_scan[0].len = priv->essid_len;
memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len);
@@ -7110,6 +7121,12 @@ static void iwl_bg_post_associate(struct work_struct *data)
mutex_lock(&priv->mutex);
+ if (!priv->interface_id || !priv->is_open) {
+ mutex_unlock(&priv->mutex);
+ return;
+ }
+ iwl_scan_cancel_timeout(priv, 200);
+
conf = ieee80211_get_hw_conf(priv->hw);
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
@@ -7263,9 +7280,19 @@ static void iwl_mac_stop(struct ieee80211_hw *hw)
struct iwl_priv *priv = hw->priv;
IWL_DEBUG_MAC80211("enter\n");
+
+
+ mutex_lock(&priv->mutex);
+ /* stop mac, cancel any scan request and clear
+ * RXON_FILTER_ASSOC_MSK BIT
+ */
priv->is_open = 0;
- /*netif_stop_queue(dev); */
- flush_workqueue(priv->workqueue);
+ iwl_scan_cancel_timeout(priv, 100);
+ cancel_delayed_work(&priv->post_associate);
+ priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+ iwl_commit_rxon(priv);
+ mutex_unlock(&priv->mutex);
+
IWL_DEBUG_MAC80211("leave\n");
}
@@ -7565,8 +7592,6 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, int if_id,
if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
iwl_config_ap(priv);
else {
- priv->staging_rxon.filter_flags |=
- RXON_FILTER_ASSOC_MSK;
rc = iwl_commit_rxon(priv);
if ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && rc)
iwl_rxon_add_station(
@@ -7574,6 +7599,7 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, int if_id,
}
} else {
+ iwl_scan_cancel_timeout(priv, 100);
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
iwl_commit_rxon(priv);
}
@@ -7613,6 +7639,12 @@ static void iwl_mac_remove_interface(struct ieee80211_hw *hw,
IWL_DEBUG_MAC80211("enter\n");
mutex_lock(&priv->mutex);
+
+ iwl_scan_cancel_timeout(priv, 100);
+ cancel_delayed_work(&priv->post_associate);
+ priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+ iwl_commit_rxon(priv);
+
if (priv->interface_id == conf->if_id) {
priv->interface_id = 0;
memset(priv->bssid, 0, ETH_ALEN);
@@ -7634,6 +7666,7 @@ static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
IWL_DEBUG_MAC80211("enter\n");
+ mutex_lock(&priv->mutex);
spin_lock_irqsave(&priv->lock, flags);
if (!iwl_is_ready_rf(priv)) {
@@ -7664,7 +7697,8 @@ static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
priv->direct_ssid_len = (u8)
min((u8) len, (u8) IW_ESSID_MAX_SIZE);
memcpy(priv->direct_ssid, ssid, priv->direct_ssid_len);
- }
+ } else
+ priv->one_direct_scan = 0;
rc = iwl_scan_initiate(priv);
@@ -7672,6 +7706,7 @@ static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
out_unlock:
spin_unlock_irqrestore(&priv->lock, flags);
+ mutex_unlock(&priv->mutex);
return rc;
}
@@ -7705,6 +7740,8 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
mutex_lock(&priv->mutex);
+ iwl_scan_cancel_timeout(priv, 100);
+
switch (cmd) {
case SET_KEY:
rc = iwl_update_sta_key_info(priv, key, sta_id);
@@ -7895,8 +7932,18 @@ static void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
spin_unlock_irqrestore(&priv->lock, flags);
+ /* we are restarting association process
+ * clear RXON_FILTER_ASSOC_MSK bit
+ */
+ if (priv->iw_mode != IEEE80211_IF_TYPE_AP) {
+ iwl_scan_cancel_timeout(priv, 100);
+ priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+ iwl_commit_rxon(priv);
+ }
+
/* Per mac80211.h: This is only used in IBSS mode... */
if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) {
+
IWL_DEBUG_MAC80211("leave - not in IBSS\n");
mutex_unlock(&priv->mutex);
return;
@@ -8910,6 +8957,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
SET_IEEE80211_DEV(hw, &pdev->dev);
+ hw->rate_control_algorithm = "iwl-4965-rs";
+
IWL_DEBUG_INFO("*** LOAD DRIVER ***\n");
priv = hw->priv;
priv->hw = hw;
@@ -9144,6 +9193,9 @@ static void iwl_pci_remove(struct pci_dev *pdev)
iwl_rate_control_unregister(priv->hw);
}
+ /*netif_stop_queue(dev); */
+ flush_workqueue(priv->workqueue);
+
/* ieee80211_unregister_hw calls iwl_mac_stop, which flushes
* priv->workqueue... so we can't take down the workqueue
* until now... */
diff --git a/drivers/net/wireless/iwlwifi/iwlwifi.h b/drivers/net/wireless/iwlwifi/iwlwifi.h
index e0b97c341215..432ce887807f 100644
--- a/drivers/net/wireless/iwlwifi/iwlwifi.h
+++ b/drivers/net/wireless/iwlwifi/iwlwifi.h
@@ -39,18 +39,13 @@ struct iwl_priv;
/* Hardware specific file defines the PCI IDs table for that hardware module */
extern struct pci_device_id iwl_hw_card_ids[];
+#include "iwl-hw.h"
#if IWL == 3945
-
#define DRV_NAME "iwl3945"
-#include "iwl-hw.h"
#include "iwl-3945-hw.h"
-
#elif IWL == 4965
-
#define DRV_NAME "iwl4965"
-#include "iwl-hw.h"
#include "iwl-4965-hw.h"
-
#endif
#include "iwl-prph.h"
diff --git a/drivers/net/wireless/libertas/Makefile b/drivers/net/wireless/libertas/Makefile
index c469d569f090..0e2787691f96 100644
--- a/drivers/net/wireless/libertas/Makefile
+++ b/drivers/net/wireless/libertas/Makefile
@@ -7,7 +7,9 @@ libertas-objs := main.o wext.o \
usb8xxx-objs += if_usb.o
libertas_cs-objs += if_cs.o
+libertas_sdio-objs += if_sdio.o
obj-$(CONFIG_LIBERTAS) += libertas.o
obj-$(CONFIG_LIBERTAS_USB) += usb8xxx.o
obj-$(CONFIG_LIBERTAS_CS) += libertas_cs.o
+obj-$(CONFIG_LIBERTAS_SDIO) += libertas_sdio.o
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index 1cbbd96fdbde..be5cfd8402c7 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -912,6 +912,10 @@ static int wlan_cmd_set_boot2_ver(wlan_private * priv,
return 0;
}
+/*
+ * Note: NEVER use libertas_queue_cmd() with addtail==0 other than for
+ * the command timer, because it does not account for queued commands.
+ */
void libertas_queue_cmd(wlan_adapter * adapter, struct cmd_ctrl_node *cmdnode, u8 addtail)
{
unsigned long flags;
@@ -941,10 +945,11 @@ void libertas_queue_cmd(wlan_adapter * adapter, struct cmd_ctrl_node *cmdnode, u
spin_lock_irqsave(&adapter->driver_lock, flags);
- if (addtail)
+ if (addtail) {
list_add_tail((struct list_head *)cmdnode,
&adapter->cmdpendingq);
- else
+ adapter->nr_cmd_pending++;
+ } else
list_add((struct list_head *)cmdnode, &adapter->cmdpendingq);
spin_unlock_irqrestore(&adapter->driver_lock, flags);
@@ -1412,7 +1417,6 @@ int libertas_prepare_and_send_command(wlan_private * priv,
cmdnode->cmdwaitqwoken = 0;
libertas_queue_cmd(adapter, cmdnode, 1);
- adapter->nr_cmd_pending++;
wake_up_interruptible(&priv->waitq);
if (wait_option & CMD_OPTION_WAITFORRSP) {
diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h
index 7c5b7f7b45db..3a0c9beefcf8 100644
--- a/drivers/net/wireless/libertas/defs.h
+++ b/drivers/net/wireless/libertas/defs.h
@@ -39,6 +39,7 @@
#define LBS_DEB_FW 0x00080000
#define LBS_DEB_THREAD 0x00100000
#define LBS_DEB_HEX 0x00200000
+#define LBS_DEB_SDIO 0x00400000
extern unsigned int libertas_debug;
@@ -80,6 +81,7 @@ do { if ((libertas_debug & (grp)) == (grp)) \
#define lbs_deb_usbd(dev, fmt, args...) LBS_DEB_LL(LBS_DEB_USB, " usbd", "%s:" fmt, (dev)->bus_id, ##args)
#define lbs_deb_cs(fmt, args...) LBS_DEB_LL(LBS_DEB_CS, " cs", fmt, ##args)
#define lbs_deb_thread(fmt, args...) LBS_DEB_LL(LBS_DEB_THREAD, " thread", fmt, ##args)
+#define lbs_deb_sdio(fmt, args...) LBS_DEB_LL(LBS_DEB_SDIO, " thread", fmt, ##args)
#define lbs_pr_info(format, args...) \
printk(KERN_INFO DRV_NAME": " format, ## args)
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c
index 0360cad363a8..ec89dabc412c 100644
--- a/drivers/net/wireless/libertas/if_cs.c
+++ b/drivers/net/wireless/libertas/if_cs.c
@@ -148,11 +148,11 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r
{
int i;
- for (i = 0; i < 500; i++) {
+ for (i = 0; i < 1000; i++) {
u8 val = if_cs_read8(card, addr);
if (val == reg)
return i;
- udelay(100);
+ udelay(500);
}
return -ETIME;
}
@@ -878,6 +878,9 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
goto out3;
}
+ /* Clear any interrupt cause that happend while sending
+ * firmware/initializing card */
+ if_cs_write16(card, IF_CS_C_INT_CAUSE, IF_CS_C_IC_MASK);
if_cs_enable_ints(card);
/* And finally bring the card up */
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
new file mode 100644
index 000000000000..b24425f74883
--- /dev/null
+++ b/drivers/net/wireless/libertas/if_sdio.c
@@ -0,0 +1,1081 @@
+/*
+ * linux/drivers/net/wireless/libertas/if_sdio.c
+ *
+ * Copyright 2007 Pierre Ossman
+ *
+ * Inspired by if_cs.c, Copyright 2007 Holger Schurig
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This hardware has more or less no CMD53 support, so all registers
+ * must be accessed using sdio_readb()/sdio_writeb().
+ *
+ * Transfers must be in one transaction or the firmware goes bonkers.
+ * This means that the transfer must either be small enough to do a
+ * byte based transfer or it must be padded to a multiple of the
+ * current block size.
+ *
+ * As SDIO is still new to the kernel, it is unfortunately common with
+ * bugs in the host controllers related to that. One such bug is that
+ * controllers cannot do transfers that aren't a multiple of 4 bytes.
+ * If you don't have time to fix the host controller driver, you can
+ * work around the problem by modifying if_sdio_host_to_card() and
+ * if_sdio_card_to_host() to pad the data.
+ */
+
+#include <linux/moduleparam.h>
+#include <linux/firmware.h>
+#include <linux/netdevice.h>
+#include <linux/delay.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+
+#include "host.h"
+#include "decl.h"
+#include "defs.h"
+#include "dev.h"
+#include "if_sdio.h"
+
+static char *libertas_helper_name = NULL;
+module_param_named(helper_name, libertas_helper_name, charp, 0644);
+
+static char *libertas_fw_name = NULL;
+module_param_named(fw_name, libertas_fw_name, charp, 0644);
+
+static const struct sdio_device_id if_sdio_ids[] = {
+ { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_LIBERTAS) },
+ { /* end: all zeroes */ },
+};
+
+MODULE_DEVICE_TABLE(sdio, if_sdio_ids);
+
+struct if_sdio_model {
+ int model;
+ const char *helper;
+ const char *firmware;
+};
+
+static struct if_sdio_model if_sdio_models[] = {
+ {
+ /* 8385 */
+ .model = 0x04,
+ .helper = "sd8385_helper.bin",
+ .firmware = "sd8385.bin",
+ },
+ {
+ /* 8686 */
+ .model = 0x0B,
+ .helper = "sd8686_helper.bin",
+ .firmware = "sd8686.bin",
+ },
+};
+
+struct if_sdio_packet {
+ struct if_sdio_packet *next;
+ u16 nb;
+ u8 buffer[0] __attribute__((aligned(4)));
+};
+
+struct if_sdio_card {
+ struct sdio_func *func;
+ wlan_private *priv;
+
+ int model;
+ unsigned long ioport;
+
+ const char *helper;
+ const char *firmware;
+
+ u8 buffer[65536];
+ u8 int_cause;
+ u32 event;
+
+ spinlock_t lock;
+ struct if_sdio_packet *packets;
+ struct work_struct packet_worker;
+};
+
+/********************************************************************/
+/* I/O */
+/********************************************************************/
+
+static u16 if_sdio_read_scratch(struct if_sdio_card *card, int *err)
+{
+ int ret, reg;
+ u16 scratch;
+
+ if (card->model == 0x04)
+ reg = IF_SDIO_SCRATCH_OLD;
+ else
+ reg = IF_SDIO_SCRATCH;
+
+ scratch = sdio_readb(card->func, reg, &ret);
+ if (!ret)
+ scratch |= sdio_readb(card->func, reg + 1, &ret) << 8;
+
+ if (err)
+ *err = ret;
+
+ if (ret)
+ return 0xffff;
+
+ return scratch;
+}
+
+static int if_sdio_handle_cmd(struct if_sdio_card *card,
+ u8 *buffer, unsigned size)
+{
+ int ret;
+ unsigned long flags;
+
+ lbs_deb_enter(LBS_DEB_SDIO);
+
+ spin_lock_irqsave(&card->priv->adapter->driver_lock, flags);
+
+ if (!card->priv->adapter->cur_cmd) {
+ lbs_deb_sdio("discarding spurious response\n");
+ ret = 0;
+ goto out;
+ }
+
+ if (size > MRVDRV_SIZE_OF_CMD_BUFFER) {
+ lbs_deb_sdio("response packet too large (%d bytes)\n",
+ (int)size);
+ ret = -E2BIG;
+ goto out;
+ }
+
+ memcpy(card->priv->adapter->cur_cmd->bufvirtualaddr, buffer, size);
+ card->priv->upld_len = size;
+
+ card->int_cause |= MRVDRV_CMD_UPLD_RDY;
+
+ libertas_interrupt(card->priv->dev);
+
+ ret = 0;
+
+out:
+ spin_unlock_irqrestore(&card->priv->adapter->driver_lock, flags);
+
+ lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
+
+ return ret;
+}
+
+static int if_sdio_handle_data(struct if_sdio_card *card,
+ u8 *buffer, unsigned size)
+{
+ int ret;
+ struct sk_buff *skb;
+ char *data;
+
+ lbs_deb_enter(LBS_DEB_SDIO);
+
+ if (size > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) {
+ lbs_deb_sdio("response packet too large (%d bytes)\n",
+ (int)size);
+ ret = -E2BIG;
+ goto out;
+ }
+
+ skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + NET_IP_ALIGN);
+ if (!skb) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ skb_reserve(skb, NET_IP_ALIGN);
+
+ data = skb_put(skb, size);
+
+ memcpy(data, buffer, size);
+
+ libertas_process_rxed_packet(card->priv, skb);
+
+ ret = 0;
+
+out:
+ lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
+
+ return ret;
+}
+
+static int if_sdio_handle_event(struct if_sdio_card *card,
+ u8 *buffer, unsigned size)
+{
+ int ret;
+ unsigned long flags;
+ u32 event;
+
+ lbs_deb_enter(LBS_DEB_SDIO);
+
+ if (card->model == 0x04) {
+ event = sdio_readb(card->func, IF_SDIO_EVENT, &ret);
+ if (ret)
+ goto out;
+ } else {
+ if (size < 4) {
+ lbs_deb_sdio("event packet too small (%d bytes)\n",
+ (int)size);
+ ret = -EINVAL;
+ goto out;
+ }
+ event = buffer[3] << 24;
+ event |= buffer[2] << 16;
+ event |= buffer[1] << 8;
+ event |= buffer[0] << 0;
+ event <<= SBI_EVENT_CAUSE_SHIFT;
+ }
+
+ spin_lock_irqsave(&card->priv->adapter->driver_lock, flags);
+
+ card->event = event;
+ card->int_cause |= MRVDRV_CARDEVENT;
+
+ libertas_interrupt(card->priv->dev);
+
+ spin_unlock_irqrestore(&card->priv->adapter->driver_lock, flags);
+
+ ret = 0;
+
+out:
+ lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
+
+ return ret;
+}
+
+static int if_sdio_card_to_host(struct if_sdio_card *card)
+{
+ int ret;
+ u8 status;
+ u16 size, type, chunk;
+ unsigned long timeout;
+
+ lbs_deb_enter(LBS_DEB_SDIO);
+
+ size = if_sdio_read_scratch(card, &ret);
+ if (ret)
+ goto out;
+
+ if (size < 4) {
+ lbs_deb_sdio("invalid packet size (%d bytes) from firmware\n",
+ (int)size);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ timeout = jiffies + HZ;
+ while (1) {
+ status = sdio_readb(card->func, IF_SDIO_STATUS, &ret);
+ if (ret)
+ goto out;
+ if (status & IF_SDIO_IO_RDY)
+ break;
+ if (time_after(jiffies, timeout)) {
+ ret = -ETIMEDOUT;
+ goto out;
+ }
+ mdelay(1);
+ }
+
+ /*
+ * The transfer must be in one transaction or the firmware
+ * goes suicidal.
+ */
+ chunk = size;
+ if ((chunk > card->func->cur_blksize) || (chunk > 512)) {
+ chunk = (chunk + card->func->cur_blksize - 1) /
+ card->func->cur_blksize * card->func->cur_blksize;
+ }
+
+ ret = sdio_readsb(card->func, card->buffer, card->ioport, chunk);
+ if (ret)
+ goto out;
+
+ chunk = card->buffer[0] | (card->buffer[1] << 8);
+ type = card->buffer[2] | (card->buffer[3] << 8);
+
+ lbs_deb_sdio("packet of type %d and size %d bytes\n",
+ (int)type, (int)chunk);
+
+ if (chunk > size) {
+ lbs_deb_sdio("packet fragment (%d > %d)\n",
+ (int)chunk, (int)size);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (chunk < size) {
+ lbs_deb_sdio("packet fragment (%d < %d)\n",
+ (int)chunk, (int)size);
+ }
+
+ switch (type) {
+ case MVMS_CMD:
+ ret = if_sdio_handle_cmd(card, card->buffer + 4, chunk - 4);
+ if (ret)
+ goto out;
+ break;
+ case MVMS_DAT:
+ ret = if_sdio_handle_data(card, card->buffer + 4, chunk - 4);
+ if (ret)
+ goto out;
+ break;
+ case MVMS_EVENT:
+ ret = if_sdio_handle_event(card, card->buffer + 4, chunk - 4);
+ if (ret)
+ goto out;
+ break;
+ default:
+ lbs_deb_sdio("invalid type (%d) from firmware\n",
+ (int)type);
+ ret = -EINVAL;
+ goto out;
+ }
+
+out:
+ if (ret)
+ lbs_pr_err("problem fetching packet from firmware\n");
+
+ lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
+
+ return ret;
+}
+
+static void if_sdio_host_to_card_worker(struct work_struct *work)
+{
+ struct if_sdio_card *card;
+ struct if_sdio_packet *packet;
+ unsigned long timeout;
+ u8 status;
+ int ret;
+ unsigned long flags;
+
+ lbs_deb_enter(LBS_DEB_SDIO);
+
+ card = container_of(work, struct if_sdio_card, packet_worker);
+
+ while (1) {
+ spin_lock_irqsave(&card->lock, flags);
+ packet = card->packets;
+ if (packet)
+ card->packets = packet->next;
+ spin_unlock_irqrestore(&card->lock, flags);
+
+ if (!packet)
+ break;
+
+ sdio_claim_host(card->func);
+
+ timeout = jiffies + HZ;
+ while (1) {
+ status = sdio_readb(card->func, IF_SDIO_STATUS, &ret);
+ if (ret)
+ goto release;
+ if (status & IF_SDIO_IO_RDY)
+ break;
+ if (time_after(jiffies, timeout)) {
+ ret = -ETIMEDOUT;
+ goto release;
+ }
+ mdelay(1);
+ }
+
+ ret = sdio_writesb(card->func, card->ioport,
+ packet->buffer, packet->nb);
+ if (ret)
+ goto release;
+release:
+ sdio_release_host(card->func);
+
+ kfree(packet);
+ }
+
+ lbs_deb_leave(LBS_DEB_SDIO);
+}
+
+/********************************************************************/
+/* Firmware */
+/********************************************************************/
+
+static int if_sdio_prog_helper(struct if_sdio_card *card)
+{
+ int ret;
+ u8 status;
+ const struct firmware *fw;
+ unsigned long timeout;
+ u8 *chunk_buffer;
+ u32 chunk_size;
+ u8 *firmware;
+ size_t size;
+
+ lbs_deb_enter(LBS_DEB_SDIO);
+
+ ret = request_firmware(&fw, card->helper, &card->func->dev);
+ if (ret) {
+ lbs_pr_err("can't load helper firmware\n");
+ goto out;
+ }
+
+ chunk_buffer = kzalloc(64, GFP_KERNEL);
+ if (!chunk_buffer) {
+ ret = -ENOMEM;
+ goto release_fw;
+ }
+
+ sdio_claim_host(card->func);
+
+ ret = sdio_set_block_size(card->func, 32);
+ if (ret)
+ goto release;
+
+ firmware = fw->data;
+ size = fw->size;
+
+ while (size) {
+ timeout = jiffies + HZ;
+ while (1) {
+ status = sdio_readb(card->func, IF_SDIO_STATUS, &ret);
+ if (ret)
+ goto release;
+ if ((status & IF_SDIO_IO_RDY) &&
+ (status & IF_SDIO_DL_RDY))
+ break;
+ if (time_after(jiffies, timeout)) {
+ ret = -ETIMEDOUT;
+ goto release;
+ }
+ mdelay(1);
+ }
+
+ chunk_size = min(size, (size_t)60);
+
+ *((u32*)chunk_buffer) = cpu_to_le32(chunk_size);
+ memcpy(chunk_buffer + 4, firmware, chunk_size);
+/*
+ lbs_deb_sdio("sending %d bytes chunk\n", chunk_size);
+*/
+ ret = sdio_writesb(card->func, card->ioport,
+ chunk_buffer, 64);
+ if (ret)
+ goto release;
+
+ firmware += chunk_size;
+ size -= chunk_size;
+ }
+
+ /* an empty block marks the end of the transfer */
+ memset(chunk_buffer, 0, 4);
+ ret = sdio_writesb(card->func, card->ioport, chunk_buffer, 64);
+ if (ret)
+ goto release;
+
+ lbs_deb_sdio("waiting for helper to boot...\n");
+
+ /* wait for the helper to boot by looking at the size register */
+ timeout = jiffies + HZ;
+ while (1) {
+ u16 req_size;
+
+ req_size = sdio_readb(card->func, IF_SDIO_RD_BASE, &ret);
+ if (ret)
+ goto release;
+
+ req_size |= sdio_readb(card->func, IF_SDIO_RD_BASE + 1, &ret) << 8;
+ if (ret)
+ goto release;
+
+ if (req_size != 0)
+ break;
+
+ if (time_after(jiffies, timeout)) {
+ ret = -ETIMEDOUT;
+ goto release;
+ }
+
+ msleep(10);
+ }
+
+ ret = 0;
+
+release:
+ sdio_set_block_size(card->func, 0);
+ sdio_release_host(card->func);
+ kfree(chunk_buffer);
+release_fw:
+ release_firmware(fw);
+
+out:
+ if (ret)
+ lbs_pr_err("failed to load helper firmware\n");
+
+ lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
+
+ return ret;
+}
+
+static int if_sdio_prog_real(struct if_sdio_card *card)
+{
+ int ret;
+ u8 status;
+ const struct firmware *fw;
+ unsigned long timeout;
+ u8 *chunk_buffer;
+ u32 chunk_size;
+ u8 *firmware;
+ size_t size, req_size;
+
+ lbs_deb_enter(LBS_DEB_SDIO);
+
+ ret = request_firmware(&fw, card->firmware, &card->func->dev);
+ if (ret) {
+ lbs_pr_err("can't load firmware\n");
+ goto out;
+ }
+
+ chunk_buffer = kzalloc(512, GFP_KERNEL);
+ if (!chunk_buffer) {
+ ret = -ENOMEM;
+ goto release_fw;
+ }
+
+ sdio_claim_host(card->func);
+
+ ret = sdio_set_block_size(card->func, 32);
+ if (ret)
+ goto release;
+
+ firmware = fw->data;
+ size = fw->size;
+
+ while (size) {
+ timeout = jiffies + HZ;
+ while (1) {
+ status = sdio_readb(card->func, IF_SDIO_STATUS, &ret);
+ if (ret)
+ goto release;
+ if ((status & IF_SDIO_IO_RDY) &&
+ (status & IF_SDIO_DL_RDY))
+ break;
+ if (time_after(jiffies, timeout)) {
+ ret = -ETIMEDOUT;
+ goto release;
+ }
+ mdelay(1);
+ }
+
+ req_size = sdio_readb(card->func, IF_SDIO_RD_BASE, &ret);
+ if (ret)
+ goto release;
+
+ req_size |= sdio_readb(card->func, IF_SDIO_RD_BASE + 1, &ret) << 8;
+ if (ret)
+ goto release;
+/*
+ lbs_deb_sdio("firmware wants %d bytes\n", (int)req_size);
+*/
+ if (req_size == 0) {
+ lbs_deb_sdio("firmware helper gave up early\n");
+ ret = -EIO;
+ goto release;
+ }
+
+ if (req_size & 0x01) {
+ lbs_deb_sdio("firmware helper signalled error\n");
+ ret = -EIO;
+ goto release;
+ }
+
+ if (req_size > size)
+ req_size = size;
+
+ while (req_size) {
+ chunk_size = min(req_size, (size_t)512);
+
+ memcpy(chunk_buffer, firmware, chunk_size);
+/*
+ lbs_deb_sdio("sending %d bytes (%d bytes) chunk\n",
+ chunk_size, (chunk_size + 31) / 32 * 32);
+*/
+ ret = sdio_writesb(card->func, card->ioport,
+ chunk_buffer, (chunk_size + 31) / 32 * 32);
+ if (ret)
+ goto release;
+
+ firmware += chunk_size;
+ size -= chunk_size;
+ req_size -= chunk_size;
+ }
+ }
+
+ ret = 0;
+
+ lbs_deb_sdio("waiting for firmware to boot...\n");
+
+ /* wait for the firmware to boot */
+ timeout = jiffies + HZ;
+ while (1) {
+ u16 scratch;
+
+ scratch = if_sdio_read_scratch(card, &ret);
+ if (ret)
+ goto release;
+
+ if (scratch == IF_SDIO_FIRMWARE_OK)
+ break;
+
+ if (time_after(jiffies, timeout)) {
+ ret = -ETIMEDOUT;
+ goto release;
+ }
+
+ msleep(10);
+ }
+
+ ret = 0;
+
+release:
+ sdio_set_block_size(card->func, 0);
+ sdio_release_host(card->func);
+ kfree(chunk_buffer);
+release_fw:
+ release_firmware(fw);
+
+out:
+ if (ret)
+ lbs_pr_err("failed to load firmware\n");
+
+ lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
+
+ return ret;
+}
+
+static int if_sdio_prog_firmware(struct if_sdio_card *card)
+{
+ int ret;
+ u16 scratch;
+
+ lbs_deb_enter(LBS_DEB_SDIO);
+
+ sdio_claim_host(card->func);
+ scratch = if_sdio_read_scratch(card, &ret);
+ sdio_release_host(card->func);
+
+ if (ret)
+ goto out;
+
+ if (scratch == IF_SDIO_FIRMWARE_OK) {
+ lbs_deb_sdio("firmware already loaded\n");
+ goto success;
+ }
+
+ ret = if_sdio_prog_helper(card);
+ if (ret)
+ goto out;
+
+ ret = if_sdio_prog_real(card);
+ if (ret)
+ goto out;
+
+success:
+ ret = 0;
+
+out:
+ lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
+
+ return ret;
+}
+
+/*******************************************************************/
+/* Libertas callbacks */
+/*******************************************************************/
+
+static int if_sdio_host_to_card(wlan_private *priv, u8 type, u8 *buf, u16 nb)
+{
+ int ret;
+ struct if_sdio_card *card;
+ struct if_sdio_packet *packet, *cur;
+ u16 size;
+ unsigned long flags;
+
+ lbs_deb_enter_args(LBS_DEB_SDIO, "type %d, bytes %d", type, nb);
+
+ card = priv->card;
+
+ if (nb > (65536 - sizeof(struct if_sdio_packet) - 4)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /*
+ * The transfer must be in one transaction or the firmware
+ * goes suicidal.
+ */
+ size = nb + 4;
+ if ((size > card->func->cur_blksize) || (size > 512)) {
+ size = (size + card->func->cur_blksize - 1) /
+ card->func->cur_blksize * card->func->cur_blksize;
+ }
+
+ packet = kzalloc(sizeof(struct if_sdio_packet) + size,
+ GFP_ATOMIC);
+ if (!packet) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ packet->next = NULL;
+ packet->nb = size;
+
+ /*
+ * SDIO specific header.
+ */
+ packet->buffer[0] = (nb + 4) & 0xff;
+ packet->buffer[1] = ((nb + 4) >> 8) & 0xff;
+ packet->buffer[2] = type;
+ packet->buffer[3] = 0;
+
+ memcpy(packet->buffer + 4, buf, nb);
+
+ spin_lock_irqsave(&card->lock, flags);
+
+ if (!card->packets)
+ card->packets = packet;
+ else {
+ cur = card->packets;
+ while (cur->next)
+ cur = cur->next;
+ cur->next = packet;
+ }
+
+ switch (type) {
+ case MVMS_CMD:
+ priv->dnld_sent = DNLD_CMD_SENT;
+ break;
+ case MVMS_DAT:
+ priv->dnld_sent = DNLD_DATA_SENT;
+ break;
+ default:
+ lbs_deb_sdio("unknown packet type %d\n", (int)type);
+ }
+
+ spin_unlock_irqrestore(&card->lock, flags);
+
+ schedule_work(&card->packet_worker);
+
+ ret = 0;
+
+out:
+ lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
+
+ return ret;
+}
+
+static int if_sdio_get_int_status(wlan_private *priv, u8 *ireg)
+{
+ struct if_sdio_card *card;
+
+ lbs_deb_enter(LBS_DEB_SDIO);
+
+ card = priv->card;
+
+ *ireg = card->int_cause;
+ card->int_cause = 0;
+
+ lbs_deb_leave(LBS_DEB_SDIO);
+
+ return 0;
+}
+
+static int if_sdio_read_event_cause(wlan_private *priv)
+{
+ struct if_sdio_card *card;
+
+ lbs_deb_enter(LBS_DEB_SDIO);
+
+ card = priv->card;
+
+ priv->adapter->eventcause = card->event;
+
+ lbs_deb_leave(LBS_DEB_SDIO);
+
+ return 0;
+}
+
+/*******************************************************************/
+/* SDIO callbacks */
+/*******************************************************************/
+
+static void if_sdio_interrupt(struct sdio_func *func)
+{
+ int ret;
+ struct if_sdio_card *card;
+ u8 cause;
+
+ lbs_deb_enter(LBS_DEB_SDIO);
+
+ card = sdio_get_drvdata(func);
+
+ cause = sdio_readb(card->func, IF_SDIO_H_INT_STATUS, &ret);
+ if (ret)
+ goto out;
+
+ lbs_deb_sdio("interrupt: 0x%X\n", (unsigned)cause);
+
+ sdio_writeb(card->func, ~cause, IF_SDIO_H_INT_STATUS, &ret);
+ if (ret)
+ goto out;
+
+ /*
+ * Ignore the define name, this really means the card has
+ * successfully received the command.
+ */
+ if (cause & IF_SDIO_H_INT_DNLD) {
+ if ((card->priv->dnld_sent == DNLD_DATA_SENT) &&
+ (card->priv->adapter->connect_status == LIBERTAS_CONNECTED))
+ netif_wake_queue(card->priv->dev);
+ card->priv->dnld_sent = DNLD_RES_RECEIVED;
+ }
+
+ if (cause & IF_SDIO_H_INT_UPLD) {
+ ret = if_sdio_card_to_host(card);
+ if (ret)
+ goto out;
+ }
+
+ ret = 0;
+
+out:
+ lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
+}
+
+static int if_sdio_probe(struct sdio_func *func,
+ const struct sdio_device_id *id)
+{
+ struct if_sdio_card *card;
+ wlan_private *priv;
+ int ret, i;
+ unsigned int model;
+ struct if_sdio_packet *packet;
+
+ lbs_deb_enter(LBS_DEB_SDIO);
+
+ for (i = 0;i < func->card->num_info;i++) {
+ if (sscanf(func->card->info[i],
+ "802.11 SDIO ID: %x", &model) == 1)
+ break;
+ if (sscanf(func->card->info[i],
+ "ID: %x", &model) == 1)
+ break;
+ }
+
+ if (i == func->card->num_info) {
+ lbs_pr_err("unable to identify card model\n");
+ return -ENODEV;
+ }
+
+ card = kzalloc(sizeof(struct if_sdio_card), GFP_KERNEL);
+ if (!card)
+ return -ENOMEM;
+
+ card->func = func;
+ card->model = model;
+ spin_lock_init(&card->lock);
+ INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker);
+
+ for (i = 0;i < ARRAY_SIZE(if_sdio_models);i++) {
+ if (card->model == if_sdio_models[i].model)
+ break;
+ }
+
+ if (i == ARRAY_SIZE(if_sdio_models)) {
+ lbs_pr_err("unkown card model 0x%x\n", card->model);
+ ret = -ENODEV;
+ goto free;
+ }
+
+ card->helper = if_sdio_models[i].helper;
+ card->firmware = if_sdio_models[i].firmware;
+
+ if (libertas_helper_name) {
+ lbs_deb_sdio("overriding helper firmware: %s\n",
+ libertas_helper_name);
+ card->helper = libertas_helper_name;
+ }
+
+ if (libertas_fw_name) {
+ lbs_deb_sdio("overriding firmware: %s\n", libertas_fw_name);
+ card->firmware = libertas_fw_name;
+ }
+
+ sdio_claim_host(func);
+
+ ret = sdio_enable_func(func);
+ if (ret)
+ goto release;
+
+ ret = sdio_claim_irq(func, if_sdio_interrupt);
+ if (ret)
+ goto disable;
+
+ card->ioport = sdio_readb(func, IF_SDIO_IOPORT, &ret);
+ if (ret)
+ goto release_int;
+
+ card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 1, &ret) << 8;
+ if (ret)
+ goto release_int;
+
+ card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 2, &ret) << 16;
+ if (ret)
+ goto release_int;
+
+ sdio_release_host(func);
+
+ sdio_set_drvdata(func, card);
+
+ lbs_deb_sdio("class = 0x%X, vendor = 0x%X, "
+ "device = 0x%X, model = 0x%X, ioport = 0x%X\n",
+ func->class, func->vendor, func->device,
+ model, (unsigned)card->ioport);
+
+ ret = if_sdio_prog_firmware(card);
+ if (ret)
+ goto reclaim;
+
+ priv = libertas_add_card(card, &func->dev);
+ if (!priv) {
+ ret = -ENOMEM;
+ goto reclaim;
+ }
+
+ card->priv = priv;
+
+ priv->card = card;
+ priv->hw_host_to_card = if_sdio_host_to_card;
+ priv->hw_get_int_status = if_sdio_get_int_status;
+ priv->hw_read_event_cause = if_sdio_read_event_cause;
+
+ priv->adapter->fw_ready = 1;
+
+ /*
+ * Enable interrupts now that everything is set up
+ */
+ sdio_claim_host(func);
+ sdio_writeb(func, 0x0f, IF_SDIO_H_INT_MASK, &ret);
+ sdio_release_host(func);
+ if (ret)
+ goto reclaim;
+
+ ret = libertas_start_card(priv);
+ if (ret)
+ goto err_activate_card;
+
+out:
+ lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
+
+ return ret;
+
+err_activate_card:
+ flush_scheduled_work();
+ free_netdev(priv->dev);
+ kfree(priv->adapter);
+reclaim:
+ sdio_claim_host(func);
+release_int:
+ sdio_release_irq(func);
+disable:
+ sdio_disable_func(func);
+release:
+ sdio_release_host(func);
+free:
+ while (card->packets) {
+ packet = card->packets;
+ card->packets = card->packets->next;
+ kfree(packet);
+ }
+
+ kfree(card);
+
+ goto out;
+}
+
+static void if_sdio_remove(struct sdio_func *func)
+{
+ struct if_sdio_card *card;
+ struct if_sdio_packet *packet;
+
+ lbs_deb_enter(LBS_DEB_SDIO);
+
+ card = sdio_get_drvdata(func);
+
+ card->priv->adapter->surpriseremoved = 1;
+
+ lbs_deb_sdio("call remove card\n");
+ libertas_stop_card(card->priv);
+ libertas_remove_card(card->priv);
+
+ flush_scheduled_work();
+
+ sdio_claim_host(func);
+ sdio_release_irq(func);
+ sdio_disable_func(func);
+ sdio_release_host(func);
+
+ while (card->packets) {
+ packet = card->packets;
+ card->packets = card->packets->next;
+ kfree(packet);
+ }
+
+ kfree(card);
+
+ lbs_deb_leave(LBS_DEB_SDIO);
+}
+
+static struct sdio_driver if_sdio_driver = {
+ .name = "libertas_sdio",
+ .id_table = if_sdio_ids,
+ .probe = if_sdio_probe,
+ .remove = if_sdio_remove,
+};
+
+/*******************************************************************/
+/* Module functions */
+/*******************************************************************/
+
+static int if_sdio_init_module(void)
+{
+ int ret = 0;
+
+ lbs_deb_enter(LBS_DEB_SDIO);
+
+ printk(KERN_INFO "libertas_sdio: Libertas SDIO driver\n");
+ printk(KERN_INFO "libertas_sdio: Copyright Pierre Ossman\n");
+
+ ret = sdio_register_driver(&if_sdio_driver);
+
+ lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
+
+ return ret;
+}
+
+static void if_sdio_exit_module(void)
+{
+ lbs_deb_enter(LBS_DEB_SDIO);
+
+ sdio_unregister_driver(&if_sdio_driver);
+
+ lbs_deb_leave(LBS_DEB_SDIO);
+}
+
+module_init(if_sdio_init_module);
+module_exit(if_sdio_exit_module);
+
+MODULE_DESCRIPTION("Libertas SDIO WLAN Driver");
+MODULE_AUTHOR("Pierre Ossman");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/libertas/if_sdio.h b/drivers/net/wireless/libertas/if_sdio.h
new file mode 100644
index 000000000000..dfcaea7b168f
--- /dev/null
+++ b/drivers/net/wireless/libertas/if_sdio.h
@@ -0,0 +1,45 @@
+/*
+ * linux/drivers/net/wireless/libertas/if_sdio.h
+ *
+ * Copyright 2007 Pierre Ossman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#ifndef LIBERTAS_IF_SDIO_H
+#define LIBERTAS_IF_SDIO_H
+
+#define IF_SDIO_IOPORT 0x00
+
+#define IF_SDIO_H_INT_MASK 0x04
+#define IF_SDIO_H_INT_OFLOW 0x08
+#define IF_SDIO_H_INT_UFLOW 0x04
+#define IF_SDIO_H_INT_DNLD 0x02
+#define IF_SDIO_H_INT_UPLD 0x01
+
+#define IF_SDIO_H_INT_STATUS 0x05
+#define IF_SDIO_H_INT_RSR 0x06
+#define IF_SDIO_H_INT_STATUS2 0x07
+
+#define IF_SDIO_RD_BASE 0x10
+
+#define IF_SDIO_STATUS 0x20
+#define IF_SDIO_IO_RDY 0x08
+#define IF_SDIO_CIS_RDY 0x04
+#define IF_SDIO_UL_RDY 0x02
+#define IF_SDIO_DL_RDY 0x01
+
+#define IF_SDIO_C_INT_MASK 0x24
+#define IF_SDIO_C_INT_STATUS 0x28
+#define IF_SDIO_C_INT_RSR 0x2C
+
+#define IF_SDIO_SCRATCH 0x34
+#define IF_SDIO_SCRATCH_OLD 0x80fe
+#define IF_SDIO_FIRMWARE_OK 0xfedc
+
+#define IF_SDIO_EVENT 0x80fc
+
+#endif
diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c
index c2d71afd57e5..2402cb8dd328 100644
--- a/drivers/net/wireless/netwave_cs.c
+++ b/drivers/net/wireless/netwave_cs.c
@@ -4,18 +4,18 @@
* Version: 0.4.1
* Description: Netwave AirSurfer Wireless LAN PC Card driver
* Status: Experimental.
- * Authors: John Markus Bjørndalen <johnm@cs.uit.no>
+ * Authors: John Markus Bjørndalen <johnm@cs.uit.no>
* Dag Brattli <dagb@cs.uit.no>
* David Hinds <dahinds@users.sourceforge.net>
* Created at: A long time ago!
* Modified at: Mon Nov 10 11:54:37 1997
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
- * Copyright (c) 1997 University of Tromsø, Norway
+ * Copyright (c) 1997 University of Tromsø, Norway
*
* Revision History:
*
- * 08-Nov-97 15:14:47 John Markus Bjørndalen <johnm@cs.uit.no>
+ * 08-Nov-97 15:14:47 John Markus Bjørndalen <johnm@cs.uit.no>
* - Fixed some bugs in netwave_rx and cleaned it up a bit.
* (One of the bugs would have destroyed packets when receiving
* multiple packets per interrupt).
@@ -158,7 +158,7 @@ static int pc_debug = PCMCIA_DEBUG;
module_param(pc_debug, int, 0);
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static char *version =
-"netwave_cs.c 0.3.0 Thu Jul 17 14:36:02 1997 (John Markus Bjørndalen)\n";
+"netwave_cs.c 0.3.0 Thu Jul 17 14:36:02 1997 (John Markus Bjørndalen)\n";
#else
#define DEBUG(n, args...)
#endif
diff --git a/drivers/net/wireless/p54common.c b/drivers/net/wireless/p54common.c
index 2c63cf0ad2cd..1437db0cf4b2 100644
--- a/drivers/net/wireless/p54common.c
+++ b/drivers/net/wireless/p54common.c
@@ -577,7 +577,7 @@ static int p54_set_filter(struct ieee80211_hw *dev, u16 filter_type,
struct p54_tx_control_filter *filter;
hdr = kzalloc(sizeof(*hdr) + sizeof(*filter) +
- priv->tx_hdr_len, GFP_KERNEL);
+ priv->tx_hdr_len, GFP_ATOMIC);
if (!hdr)
return -ENOMEM;
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index ff2d63267b19..702321c30164 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -620,7 +620,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev)
* up to version C the link tuning should halt after 20
* seconds.
*/
- if (rt2x00_get_rev(&rt2x00dev->chip) < RT2560_VERSION_D &&
+ if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D &&
rt2x00dev->link.count > 20)
return;
@@ -630,7 +630,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev)
* Chipset versions C and lower should directly continue
* to the dynamic CCA tuning.
*/
- if (rt2x00_get_rev(&rt2x00dev->chip) < RT2560_VERSION_D)
+ if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D)
goto dynamic_cca_tune;
/*
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 7cdc80a122bb..277a020b35e9 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -753,7 +753,7 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&reg, MAC_CSR1_HOST_READY, 1);
rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg);
- if (rt2x00_get_rev(&rt2x00dev->chip) >= RT2570_VERSION_C) {
+ if (rt2x00_rev(&rt2x00dev->chip) >= RT2570_VERSION_C) {
rt2500usb_register_read(rt2x00dev, PHY_CSR2, &reg);
reg &= ~0x0002;
} else {
@@ -1257,7 +1257,7 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
rt2500usb_register_read(rt2x00dev, MAC_CSR0, &reg);
rt2x00_set_chip(rt2x00dev, RT2570, value, reg);
- if (rt2x00_rev(&rt2x00dev->chip, 0xffff0)) {
+ if (!rt2x00_check_rev(&rt2x00dev->chip, 0)) {
ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
return -ENODEV;
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 9845e584b731..d1ad5251a77a 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -751,14 +751,16 @@ static inline char rt2x00_rf(const struct rt2x00_chip *chipset, const u16 chip)
return (chipset->rf == chip);
}
-static inline u16 rt2x00_get_rev(const struct rt2x00_chip *chipset)
+static inline u16 rt2x00_rev(const struct rt2x00_chip *chipset)
{
return chipset->rev;
}
-static inline u16 rt2x00_rev(const struct rt2x00_chip *chipset, const u32 mask)
+static inline u16 rt2x00_check_rev(const struct rt2x00_chip *chipset,
+ const u32 rev)
{
- return chipset->rev & mask;
+ return (((chipset->rev & 0xffff0) == rev) &&
+ !!(chipset->rev & 0x0000f));
}
/*
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index bb6f46cfbb9f..ff399f8083e9 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -550,7 +550,7 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev,
/*
* Check if we need to set the Length Extension
*/
- if (bitrate == 110 && residual <= 3)
+ if (bitrate == 110 && residual <= 30)
desc.service |= 0x80;
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index 298faa9d3f61..06d9bc0015c0 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -30,7 +30,7 @@
* Interval defines
* Both the link tuner as the rfkill will be called once per second.
*/
-#define LINK_TUNE_INTERVAL ( round_jiffies(HZ) )
+#define LINK_TUNE_INTERVAL ( round_jiffies_relative(HZ) )
#define RFKILL_POLL_INTERVAL ( 1000 )
/*
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 4a6a0bd01ff1..85ea8a8e658e 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -196,6 +196,14 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
struct rt2x00_dev *rt2x00dev = hw->priv;
struct interface *intf = &rt2x00dev->interface;
+ /* FIXME: Beaconing is broken in rt2x00. */
+ if (conf->type == IEEE80211_IF_TYPE_IBSS ||
+ conf->type == IEEE80211_IF_TYPE_AP) {
+ ERROR(rt2x00dev,
+ "rt2x00 does not support Adhoc or Master mode");
+ return -EOPNOTSUPP;
+ }
+
/*
* Don't allow interfaces to be added while
* either the device has disappeared or when
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 3e42759473c3..dc640bf6b5eb 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -1486,7 +1486,7 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
rt73usb_register_read(rt2x00dev, MAC_CSR0, &reg);
rt2x00_set_chip(rt2x00dev, RT2571, value, reg);
- if (!rt2x00_rev(&rt2x00dev->chip, 0x25730)) {
+ if (!rt2x00_check_rev(&rt2x00dev->chip, 0x25730)) {
ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
return -ENODEV;
}
@@ -2029,6 +2029,7 @@ static struct usb_device_id rt73usb_device_table[] = {
{ USB_DEVICE(0x050d, 0x7050), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x050d, 0x705a), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x050d, 0x905b), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x050d, 0x905c), USB_DEVICE_DATA(&rt73usb_ops) },
/* Billionton */
{ USB_DEVICE(0x1631, 0xc019), USB_DEVICE_DATA(&rt73usb_ops) },
/* Buffalo */
diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c
index 0ef887dd2867..e454ae83e97a 100644
--- a/drivers/net/wireless/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl8187_dev.c
@@ -131,7 +131,8 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
struct rtl8187_tx_hdr *hdr;
struct rtl8187_tx_info *info;
struct urb *urb;
- u32 tmp;
+ __le16 rts_dur = 0;
+ u32 flags;
urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb) {
@@ -139,24 +140,24 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
return 0;
}
- hdr = (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr));
- tmp = skb->len - sizeof(*hdr);
- tmp |= RTL8187_TX_FLAG_NO_ENCRYPT;
- tmp |= control->rts_cts_rate << 19;
- tmp |= control->tx_rate << 24;
- if (ieee80211_get_morefrag((struct ieee80211_hdr *)skb))
- tmp |= RTL8187_TX_FLAG_MORE_FRAG;
+ flags = skb->len;
+ flags |= RTL8187_TX_FLAG_NO_ENCRYPT;
+ flags |= control->rts_cts_rate << 19;
+ flags |= control->tx_rate << 24;
+ if (ieee80211_get_morefrag((struct ieee80211_hdr *)skb->data))
+ flags |= RTL8187_TX_FLAG_MORE_FRAG;
if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
- tmp |= RTL8187_TX_FLAG_RTS;
- hdr->rts_duration =
- ieee80211_rts_duration(dev, priv->if_id, skb->len, control);
+ flags |= RTL8187_TX_FLAG_RTS;
+ rts_dur = ieee80211_rts_duration(dev, priv->if_id, skb->len, control);
}
if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
- tmp |= RTL8187_TX_FLAG_CTS;
- hdr->flags = cpu_to_le32(tmp);
+ flags |= RTL8187_TX_FLAG_CTS;
+
+ hdr = (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr));
+ hdr->flags = cpu_to_le32(flags);
hdr->len = 0;
- tmp = control->retry_limit << 8;
- hdr->retry = cpu_to_le32(tmp);
+ hdr->rts_duration = rts_dur;
+ hdr->retry = cpu_to_le32(control->retry_limit << 8);
info = (struct rtl8187_tx_info *)skb->cb;
info->control = kmemdup(control, sizeof(*control), GFP_ATOMIC);
@@ -432,6 +433,9 @@ static int rtl8187_start(struct ieee80211_hw *dev)
rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF);
+ rtl818x_iowrite32(priv, &priv->map->MAR[0], ~0);
+ rtl818x_iowrite32(priv, &priv->map->MAR[1], ~0);
+
rtl8187_init_urbs(dev);
reg = RTL818X_RX_CONF_ONLYERLPKT |
@@ -581,36 +585,31 @@ static int rtl8187_config_interface(struct ieee80211_hw *dev, int if_id,
static void rtl8187_configure_filter(struct ieee80211_hw *dev,
unsigned int changed_flags,
unsigned int *total_flags,
- int mc_count, struct dev_addr_list *mc_list)
+ int mc_count, struct dev_addr_list *mclist)
{
struct rtl8187_priv *priv = dev->priv;
- *total_flags = 0;
-
- if (changed_flags & FIF_PROMISC_IN_BSS)
- priv->rx_conf ^= RTL818X_RX_CONF_NICMAC;
- if (changed_flags & FIF_ALLMULTI)
- priv->rx_conf ^= RTL818X_RX_CONF_MULTICAST;
if (changed_flags & FIF_FCSFAIL)
priv->rx_conf ^= RTL818X_RX_CONF_FCS;
if (changed_flags & FIF_CONTROL)
priv->rx_conf ^= RTL818X_RX_CONF_CTRL;
if (changed_flags & FIF_OTHER_BSS)
priv->rx_conf ^= RTL818X_RX_CONF_MONITOR;
-
- if (mc_count > 0)
+ if (*total_flags & FIF_ALLMULTI || mc_count > 0)
priv->rx_conf |= RTL818X_RX_CONF_MULTICAST;
+ else
+ priv->rx_conf &= ~RTL818X_RX_CONF_MULTICAST;
+
+ *total_flags = 0;
- if (priv->rx_conf & RTL818X_RX_CONF_NICMAC)
- *total_flags |= FIF_PROMISC_IN_BSS;
- if (priv->rx_conf & RTL818X_RX_CONF_MULTICAST)
- *total_flags |= FIF_ALLMULTI;
if (priv->rx_conf & RTL818X_RX_CONF_FCS)
*total_flags |= FIF_FCSFAIL;
if (priv->rx_conf & RTL818X_RX_CONF_CTRL)
*total_flags |= FIF_CONTROL;
if (priv->rx_conf & RTL818X_RX_CONF_MONITOR)
*total_flags |= FIF_OTHER_BSS;
+ if (priv->rx_conf & RTL818X_RX_CONF_MULTICAST)
+ *total_flags |= FIF_ALLMULTI;
rtl818x_iowrite32_async(priv, &priv->map->RX_CONF, priv->rx_conf);
}
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
index 4bd14b331862..88efe1bae58f 100644
--- a/drivers/net/wireless/strip.c
+++ b/drivers/net/wireless/strip.c
@@ -2735,16 +2735,8 @@ static int strip_ioctl(struct tty_struct *tty, struct file *file,
return -EFAULT;
return set_mac_address(strip_info, &addr);
}
- /*
- * Allow stty to read, but not set, the serial port
- */
-
- case TCGETS:
- case TCGETA:
- return n_tty_ioctl(tty, file, cmd, arg);
- break;
default:
- return -ENOIOCTLCMD;
+ return tty_mode_ioctl(tty, file, cmd, arg);
break;
}
return 0;
diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c
index 935b144d9b56..d5c0c66188ca 100644
--- a/drivers/net/wireless/zd1201.c
+++ b/drivers/net/wireless/zd1201.c
@@ -327,8 +327,8 @@ static void zd1201_usbrx(struct urb *urb)
memcpy(skb_put(skb, 6), &data[datalen-8], 6);
memcpy(skb_put(skb, 2), &data[datalen-24], 2);
memcpy(skb_put(skb, len), data, len);
- skb->dev->last_rx = jiffies;
skb->protocol = eth_type_trans(skb, zd->dev);
+ skb->dev->last_rx = jiffies;
zd->stats.rx_packets++;
zd->stats.rx_bytes += skb->len;
netif_rx(skb);
@@ -384,8 +384,8 @@ static void zd1201_usbrx(struct urb *urb)
memcpy(skb_put(skb, 2), &data[6], 2);
memcpy(skb_put(skb, len), data+8, len);
}
- skb->dev->last_rx = jiffies;
skb->protocol = eth_type_trans(skb, zd->dev);
+ skb->dev->last_rx = jiffies;
zd->stats.rx_packets++;
zd->stats.rx_bytes += skb->len;
netif_rx(skb);
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index b0684f965761..c755b6923812 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -1044,14 +1044,17 @@ error:
static void disconnect(struct usb_interface *intf)
{
struct net_device *netdev = zd_intf_to_netdev(intf);
- struct zd_mac *mac = zd_netdev_mac(netdev);
- struct zd_usb *usb = &mac->chip.usb;
+ struct zd_mac *mac;
+ struct zd_usb *usb;
/* Either something really bad happened, or we're just dealing with
* a DEVICE_INSTALLER. */
if (netdev == NULL)
return;
+ mac = zd_netdev_mac(netdev);
+ usb = &mac->chip.usb;
+
dev_dbg_f(zd_usb_dev(usb), "\n");
zd_netdev_disconnect(netdev);
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index f464b82c7d5f..2a8fc431099f 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -74,22 +74,12 @@ struct netfront_info {
struct napi_struct napi;
- struct xen_netif_tx_front_ring tx;
- struct xen_netif_rx_front_ring rx;
-
- spinlock_t tx_lock;
- spinlock_t rx_lock;
-
unsigned int evtchn;
+ struct xenbus_device *xbdev;
- /* Receive-ring batched refills. */
-#define RX_MIN_TARGET 8
-#define RX_DFL_MIN_TARGET 64
-#define RX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256)
- unsigned rx_min_target, rx_max_target, rx_target;
- struct sk_buff_head rx_batch;
-
- struct timer_list rx_refill_timer;
+ spinlock_t tx_lock;
+ struct xen_netif_tx_front_ring tx;
+ int tx_ring_ref;
/*
* {tx,rx}_skbs store outstanding skbuffs. Free tx_skb entries
@@ -108,14 +98,23 @@ struct netfront_info {
grant_ref_t grant_tx_ref[NET_TX_RING_SIZE];
unsigned tx_skb_freelist;
+ spinlock_t rx_lock ____cacheline_aligned_in_smp;
+ struct xen_netif_rx_front_ring rx;
+ int rx_ring_ref;
+
+ /* Receive-ring batched refills. */
+#define RX_MIN_TARGET 8
+#define RX_DFL_MIN_TARGET 64
+#define RX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256)
+ unsigned rx_min_target, rx_max_target, rx_target;
+ struct sk_buff_head rx_batch;
+
+ struct timer_list rx_refill_timer;
+
struct sk_buff *rx_skbs[NET_RX_RING_SIZE];
grant_ref_t gref_rx_head;
grant_ref_t grant_rx_ref[NET_RX_RING_SIZE];
- struct xenbus_device *xbdev;
- int tx_ring_ref;
- int rx_ring_ref;
-
unsigned long rx_pfn_array[NET_RX_RING_SIZE];
struct multicall_entry rx_mcl[NET_RX_RING_SIZE+1];
struct mmu_update rx_mmu[NET_RX_RING_SIZE];
@@ -1527,7 +1526,7 @@ static int xennet_connect(struct net_device *dev)
if (!feature_rx_copy) {
dev_info(&dev->dev,
- "backend does not support copying recieve path");
+ "backend does not support copying receive path\n");
return -ENODEV;
}
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 864f09fd9f86..b47bb2d7476a 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -12,6 +12,7 @@
*
*/
#include <linux/errno.h>
+#include <linux/module.h>
#include <linux/device.h>
#include <linux/of_device.h>
#include <linux/of_platform.h>
@@ -94,3 +95,23 @@ int of_bus_type_init(struct bus_type *bus, const char *name)
bus->resume = of_platform_device_resume;
return bus_register(bus);
}
+
+int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus)
+{
+ /* initialize common driver fields */
+ if (!drv->driver.name)
+ drv->driver.name = drv->name;
+ if (!drv->driver.owner)
+ drv->driver.owner = drv->owner;
+ drv->driver.bus = bus;
+
+ /* register with core */
+ return driver_register(&drv->driver);
+}
+EXPORT_SYMBOL(of_register_driver);
+
+void of_unregister_driver(struct of_platform_driver *drv)
+{
+ driver_unregister(&drv->driver);
+}
+EXPORT_SYMBOL(of_unregister_driver);
diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c
index a83c3db7d18f..c93d3d2640ab 100644
--- a/drivers/oprofile/cpu_buffer.c
+++ b/drivers/oprofile/cpu_buffer.c
@@ -64,6 +64,8 @@ int alloc_cpu_buffers(void)
b->head_pos = 0;
b->sample_received = 0;
b->sample_lost_overflow = 0;
+ b->backtrace_aborted = 0;
+ b->sample_invalid_eip = 0;
b->cpu = i;
INIT_DELAYED_WORK(&b->work, wq_sync_buffer);
}
@@ -175,6 +177,11 @@ static int log_sample(struct oprofile_cpu_buffer * cpu_buf, unsigned long pc,
cpu_buf->sample_received++;
+ if (pc == ESCAPE_CODE) {
+ cpu_buf->sample_invalid_eip++;
+ return 0;
+ }
+
if (nr_available_slots(cpu_buf) < 3) {
cpu_buf->sample_lost_overflow++;
return 0;
diff --git a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h
index 49900d9e3235..c66c025abe75 100644
--- a/drivers/oprofile/cpu_buffer.h
+++ b/drivers/oprofile/cpu_buffer.h
@@ -42,6 +42,7 @@ struct oprofile_cpu_buffer {
unsigned long sample_received;
unsigned long sample_lost_overflow;
unsigned long backtrace_aborted;
+ unsigned long sample_invalid_eip;
int cpu;
struct delayed_work work;
} ____cacheline_aligned;
diff --git a/drivers/oprofile/oprofile_stats.c b/drivers/oprofile/oprofile_stats.c
index f0acb661c253..d1f6d776e9e4 100644
--- a/drivers/oprofile/oprofile_stats.c
+++ b/drivers/oprofile/oprofile_stats.c
@@ -26,6 +26,8 @@ void oprofile_reset_stats(void)
cpu_buf = &cpu_buffer[i];
cpu_buf->sample_received = 0;
cpu_buf->sample_lost_overflow = 0;
+ cpu_buf->backtrace_aborted = 0;
+ cpu_buf->sample_invalid_eip = 0;
}
atomic_set(&oprofile_stats.sample_lost_no_mm, 0);
@@ -61,6 +63,8 @@ void oprofile_create_stats_files(struct super_block * sb, struct dentry * root)
&cpu_buf->sample_lost_overflow);
oprofilefs_create_ro_ulong(sb, cpudir, "backtrace_aborted",
&cpu_buf->backtrace_aborted);
+ oprofilefs_create_ro_ulong(sb, cpudir, "sample_invalid_eip",
+ &cpu_buf->sample_invalid_eip);
}
oprofilefs_create_ro_atomic(sb, dir, "sample_lost_no_mm",
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
index b3c4dbff26b8..7c60cbd85dc8 100644
--- a/drivers/parisc/ccio-dma.c
+++ b/drivers/parisc/ccio-dma.c
@@ -42,6 +42,7 @@
#include <linux/reboot.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <linux/scatterlist.h>
#include <asm/byteorder.h>
#include <asm/cache.h> /* for L1_CACHE_BYTES */
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c
index 5b86ee5c1eeb..5eace9e66e14 100644
--- a/drivers/parisc/lba_pci.c
+++ b/drivers/parisc/lba_pci.c
@@ -557,44 +557,6 @@ lba_bios_init(void)
#ifdef CONFIG_64BIT
/*
-** Determine if a device is already configured.
-** If so, reserve it resources.
-**
-** Read PCI cfg command register and see if I/O or MMIO is enabled.
-** PAT has to enable the devices it's using.
-**
-** Note: resources are fixed up before we try to claim them.
-*/
-static void
-lba_claim_dev_resources(struct pci_dev *dev)
-{
- u16 cmd;
- int i, srch_flags;
-
- (void) pci_read_config_word(dev, PCI_COMMAND, &cmd);
-
- srch_flags = (cmd & PCI_COMMAND_IO) ? IORESOURCE_IO : 0;
- if (cmd & PCI_COMMAND_MEMORY)
- srch_flags |= IORESOURCE_MEM;
-
- if (!srch_flags)
- return;
-
- for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
- if (dev->resource[i].flags & srch_flags) {
- pci_claim_resource(dev, i);
- DBG(" claimed %s %d [%lx,%lx]/%lx\n",
- pci_name(dev), i,
- dev->resource[i].start,
- dev->resource[i].end,
- dev->resource[i].flags
- );
- }
- }
-}
-
-
-/*
* truncate_pat_collision: Deal with overlaps or outright collisions
* between PAT PDC reported ranges.
*
@@ -653,7 +615,6 @@ truncate_pat_collision(struct resource *root, struct resource *new)
}
#else
-#define lba_claim_dev_resources(dev) do { } while (0)
#define truncate_pat_collision(r,n) (0)
#endif
@@ -684,8 +645,12 @@ lba_fixup_bus(struct pci_bus *bus)
** pci_alloc_primary_bus() mangles this.
*/
if (bus->self) {
+ int i;
/* PCI-PCI Bridge */
pci_read_bridge_bases(bus);
+ for (i = PCI_BRIDGE_RESOURCES; i < PCI_NUM_RESOURCES; i++) {
+ pci_claim_resource(bus->self, i);
+ }
} else {
/* Host-PCI Bridge */
int err, i;
@@ -803,6 +768,9 @@ lba_fixup_bus(struct pci_bus *bus)
DBG("lba_fixup_bus() WTF? 0x%lx [%lx/%lx] XXX",
res->flags, res->start, res->end);
}
+ if ((i != PCI_ROM_RESOURCE) ||
+ (res->flags & IORESOURCE_ROM_ENABLE))
+ pci_claim_resource(dev, i);
}
#ifdef FBB_SUPPORT
@@ -814,11 +782,6 @@ lba_fixup_bus(struct pci_bus *bus)
bus->bridge_ctl &= ~(status & PCI_STATUS_FAST_BACK);
#endif
- if (is_pdc_pat()) {
- /* Claim resources for PDC's devices */
- lba_claim_dev_resources(dev);
- }
-
/*
** P2PB's have no IRQs. ignore them.
*/
diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c
index fc4bde259dc7..ebb09e98d215 100644
--- a/drivers/parisc/pdc_stable.c
+++ b/drivers/parisc/pdc_stable.c
@@ -282,6 +282,7 @@ pdcspath_hwpath_write(struct pdcspath_entry *entry, const char *buf, size_t coun
unsigned short i;
char in[count+1], *temp;
struct device *dev;
+ int ret;
if (!entry || !buf || !count)
return -EINVAL;
@@ -333,7 +334,9 @@ pdcspath_hwpath_write(struct pdcspath_entry *entry, const char *buf, size_t coun
/* Update the symlink to the real device */
sysfs_remove_link(&entry->kobj, "device");
- sysfs_create_link(&entry->kobj, &entry->dev->kobj, "device");
+ ret = sysfs_create_link(&entry->kobj, &entry->dev->kobj, "device");
+ WARN_ON(ret);
+
write_unlock(&entry->rw_lock);
printk(KERN_INFO PDCS_PREFIX ": changed \"%s\" path to \"%s\"\n",
@@ -1003,8 +1006,10 @@ pdcs_register_pathentries(void)
entry->ready = 2;
/* Add a nice symlink to the real device */
- if (entry->dev)
- sysfs_create_link(&entry->kobj, &entry->dev->kobj, "device");
+ if (entry->dev) {
+ err = sysfs_create_link(&entry->kobj, &entry->dev->kobj, "device");
+ WARN_ON(err);
+ }
write_unlock(&entry->rw_lock);
}
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index d044c48323e6..e527a0e1d6c0 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -28,6 +28,7 @@
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/pci.h>
+#include <linux/scatterlist.h>
#include <asm/byteorder.h>
#include <asm/io.h>
@@ -1909,8 +1910,8 @@ sba_driver_callback(struct parisc_device *dev)
global_ioc_cnt *= 2;
}
- printk(KERN_INFO "%s found %s at 0x%lx\n",
- MODULE_NAME, version, dev->hpa.start);
+ printk(KERN_INFO "%s found %s at 0x%llx\n",
+ MODULE_NAME, version, (unsigned long long)dev->hpa.start);
sba_dev = kzalloc(sizeof(struct sba_device), GFP_KERNEL);
if (!sba_dev) {
diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c
index 38cdf9fa36a7..1e8d2d17f04c 100644
--- a/drivers/parisc/superio.c
+++ b/drivers/parisc/superio.c
@@ -155,6 +155,7 @@ superio_init(struct pci_dev *pcidev)
struct superio_device *sio = &sio_dev;
struct pci_dev *pdev = sio->lio_pdev;
u16 word;
+ int ret;
if (sio->suckyio_irq_enabled)
return;
@@ -200,7 +201,8 @@ superio_init(struct pci_dev *pcidev)
pci_write_config_word (pdev, PCI_COMMAND, word);
pci_set_master (pdev);
- pci_enable_device(pdev);
+ ret = pci_enable_device(pdev);
+ BUG_ON(ret < 0); /* not too much we can do about this... */
/*
* Next project is programming the onboard interrupt controllers.
diff --git a/drivers/parport/daisy.c b/drivers/parport/daisy.c
index ff9f34453530..3c8f06c3a5a0 100644
--- a/drivers/parport/daisy.c
+++ b/drivers/parport/daisy.c
@@ -199,11 +199,6 @@ void parport_daisy_fini(struct parport *port)
* parport_open - find a device by canonical device number
* @devnum: canonical device number
* @name: name to associate with the device
- * @pf: preemption callback
- * @kf: kick callback
- * @irqf: interrupt handler
- * @flags: registration flags
- * @handle: driver data
*
* This function is similar to parport_register_device(), except
* that it locates a device by its number rather than by the port
@@ -214,10 +209,7 @@ void parport_daisy_fini(struct parport *port)
* for parport_register_device().
**/
-struct pardevice *parport_open(int devnum, const char *name,
- int (*pf) (void *), void (*kf) (void *),
- void (*irqf) (int, void *),
- int flags, void *handle)
+struct pardevice *parport_open(int devnum, const char *name)
{
struct daisydev *p = topology;
struct parport *port;
@@ -237,8 +229,7 @@ struct pardevice *parport_open(int devnum, const char *name,
port = parport_get_port(p->port);
spin_unlock(&topology_lock);
- dev = parport_register_device(port, name, pf, kf,
- irqf, flags, handle);
+ dev = parport_register_device(port, name, NULL, NULL, NULL, 0, NULL);
parport_put_port(port);
if (!dev)
return NULL;
@@ -275,35 +266,6 @@ void parport_close(struct pardevice *dev)
parport_unregister_device(dev);
}
-/**
- * parport_device_num - convert device coordinates
- * @parport: parallel port number
- * @mux: multiplexor port number (-1 for no multiplexor)
- * @daisy: daisy chain address (-1 for no daisy chain address)
- *
- * This tries to locate a device on the given parallel port,
- * multiplexor port and daisy chain address, and returns its
- * device number or %-ENXIO if no device with those coordinates
- * exists.
- **/
-
-int parport_device_num(int parport, int mux, int daisy)
-{
- int res = -ENXIO;
- struct daisydev *dev;
-
- spin_lock(&topology_lock);
- dev = topology;
- while (dev && dev->port->portnum != parport &&
- dev->port->muxport != mux && dev->daisy != daisy)
- dev = dev->next;
- if (dev)
- res = dev->devnum;
- spin_unlock(&topology_lock);
-
- return res;
-}
-
/* Send a daisy-chain-style CPP command packet. */
static int cpp_daisy(struct parport *port, int cmd)
{
diff --git a/drivers/parport/ieee1284.c b/drivers/parport/ieee1284.c
index 5accaa7bde31..54a6ef72906e 100644
--- a/drivers/parport/ieee1284.c
+++ b/drivers/parport/ieee1284.c
@@ -571,7 +571,7 @@ static int parport_ieee1284_ack_data_avail (struct parport *port)
#endif /* IEEE1284 support */
/* Handle an interrupt. */
-void parport_ieee1284_interrupt (int which, void *handle)
+void parport_ieee1284_interrupt (void *handle)
{
struct parport *port = handle;
parport_ieee1284_wakeup (port);
diff --git a/drivers/parport/parport_amiga.c b/drivers/parport/parport_amiga.c
index a0afaee5ebe5..1586e1caa2f5 100644
--- a/drivers/parport/parport_amiga.c
+++ b/drivers/parport/parport_amiga.c
@@ -137,13 +137,6 @@ static unsigned char amiga_read_status(struct parport *p)
return status;
}
-/* as this ports irq handling is already done, we use a generic funktion */
-static irqreturn_t amiga_interrupt(int irq, void *dev_id)
-{
- parport_generic_irq(irq, (struct parport *) dev_id);
- return IRQ_HANDLED;
-}
-
static void amiga_enable_irq(struct parport *p)
{
enable_irq(IRQ_AMIGA_CIAA_FLG);
@@ -255,7 +248,7 @@ static int __init parport_amiga_init(void)
if (!p)
goto out_port;
- err = request_irq(IRQ_AMIGA_CIAA_FLG, amiga_interrupt, 0, p->name, p);
+ err = request_irq(IRQ_AMIGA_CIAA_FLG, parport_irq_handler, 0, p->name, p);
if (err)
goto out_irq;
diff --git a/drivers/parport/parport_atari.c b/drivers/parport/parport_atari.c
index 6ea9929b8c7f..ad4cdd256137 100644
--- a/drivers/parport/parport_atari.c
+++ b/drivers/parport/parport_atari.c
@@ -103,13 +103,6 @@ parport_atari_restore_state(struct parport *p, struct parport_state *s)
{
}
-static irqreturn_t
-parport_atari_interrupt(int irq, void *dev_id)
-{
- parport_generic_irq(irq, (struct parport *) dev_id);
- return IRQ_HANDLED;
-}
-
static void
parport_atari_enable_irq(struct parport *p)
{
@@ -208,7 +201,7 @@ static int __init parport_atari_init(void)
&parport_atari_ops);
if (!p)
return -ENODEV;
- if (request_irq(IRQ_MFP_BUSY, parport_atari_interrupt,
+ if (request_irq(IRQ_MFP_BUSY, parport_irq_handler,
IRQ_TYPE_SLOW, p->name, p)) {
parport_put_port (p);
return -ENODEV;
diff --git a/drivers/parport/parport_ax88796.c b/drivers/parport/parport_ax88796.c
index 74f4e9742c6c..4ec220b2eae7 100644
--- a/drivers/parport/parport_ax88796.c
+++ b/drivers/parport/parport_ax88796.c
@@ -232,14 +232,6 @@ parport_ax88796_restore_state(struct parport *p, struct parport_state *s)
writeb(s->u.ax88796.cpr, dd->spp_cpr);
}
-static irqreturn_t
-parport_ax88796_interrupt(int irq, void *dev_id)
-{
- parport_generic_irq(irq, dev_id);
- return IRQ_HANDLED;
-}
-
-
static struct parport_operations parport_ax88796_ops = {
.write_data = parport_ax88796_write_data,
.read_data = parport_ax88796_read_data,
@@ -344,7 +336,7 @@ static int parport_ax88796_probe(struct platform_device *pdev)
if (irq >= 0) {
/* request irq */
- ret = request_irq(irq, parport_ax88796_interrupt,
+ ret = request_irq(irq, parport_irq_handler,
IRQF_TRIGGER_FALLING, pdev->name, pp);
if (ret < 0)
diff --git a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c
index 43652ba523eb..0e77ae2b71a0 100644
--- a/drivers/parport/parport_gsc.c
+++ b/drivers/parport/parport_gsc.c
@@ -80,12 +80,6 @@ static int clear_epp_timeout(struct parport *pb)
* of these are in parport_gsc.h.
*/
-static irqreturn_t parport_gsc_interrupt(int irq, void *dev_id)
-{
- parport_generic_irq(irq, (struct parport *) dev_id);
- return IRQ_HANDLED;
-}
-
void parport_gsc_init_state(struct pardevice *dev, struct parport_state *s)
{
s->u.pc.ctr = 0xc | (dev->irq_func ? 0x10 : 0x0);
@@ -324,7 +318,7 @@ struct parport *__devinit parport_gsc_probe_port (unsigned long base,
printk("]\n");
if (p->irq != PARPORT_IRQ_NONE) {
- if (request_irq (p->irq, parport_gsc_interrupt,
+ if (request_irq (p->irq, parport_irq_handler,
0, p->name, p)) {
printk (KERN_WARNING "%s: irq %d in use, "
"resorting to polled operation\n",
diff --git a/drivers/parport/parport_ip32.c b/drivers/parport/parport_ip32.c
index ec44efdbb84e..6d58bf895b1a 100644
--- a/drivers/parport/parport_ip32.c
+++ b/drivers/parport/parport_ip32.c
@@ -778,14 +778,16 @@ static irqreturn_t parport_ip32_interrupt(int irq, void *dev_id)
struct parport * const p = dev_id;
struct parport_ip32_private * const priv = p->physport->private_data;
enum parport_ip32_irq_mode irq_mode = priv->irq_mode;
+
switch (irq_mode) {
case PARPORT_IP32_IRQ_FWD:
- parport_generic_irq(irq, p);
- break;
+ return parport_irq_handler(irq, dev_id);
+
case PARPORT_IP32_IRQ_HERE:
parport_ip32_wakeup(p);
break;
}
+
return IRQ_HANDLED;
}
diff --git a/drivers/parport/parport_mfc3.c b/drivers/parport/parport_mfc3.c
index 77726fc49766..6dec9ba5ed28 100644
--- a/drivers/parport/parport_mfc3.c
+++ b/drivers/parport/parport_mfc3.c
@@ -219,7 +219,7 @@ static irqreturn_t mfc3_interrupt(int irq, void *dev_id)
if (this_port[i] != NULL)
if (pia(this_port[i])->crb & 128) { /* Board caused interrupt */
dummy = pia(this_port[i])->pprb; /* clear irq bit */
- parport_generic_irq(irq, this_port[i]);
+ parport_generic_irq(this_port[i]);
}
return IRQ_HANDLED;
}
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index e2be84001105..e9743d3efaf6 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -272,13 +272,6 @@ static int clear_epp_timeout(struct parport *pb)
* of these are in parport_pc.h.
*/
-static irqreturn_t parport_pc_interrupt(int irq, void *dev_id)
-{
- parport_generic_irq(irq, (struct parport *) dev_id);
- /* FIXME! Was it really ours? */
- return IRQ_HANDLED;
-}
-
static void parport_pc_init_state(struct pardevice *dev, struct parport_state *s)
{
s->u.pc.ctr = 0xc;
@@ -2301,7 +2294,7 @@ struct parport *parport_pc_probe_port (unsigned long int base,
EPP_res = NULL;
}
if (p->irq != PARPORT_IRQ_NONE) {
- if (request_irq (p->irq, parport_pc_interrupt,
+ if (request_irq (p->irq, parport_irq_handler,
0, p->name, p)) {
printk (KERN_WARNING "%s: irq %d in use, "
"resorting to polled operation\n",
diff --git a/drivers/parport/parport_sunbpp.c b/drivers/parport/parport_sunbpp.c
index d27019c2f860..9d595aa91e46 100644
--- a/drivers/parport/parport_sunbpp.c
+++ b/drivers/parport/parport_sunbpp.c
@@ -46,12 +46,6 @@
#define dprintk(x)
#endif
-static irqreturn_t parport_sunbpp_interrupt(int irq, void *dev_id)
-{
- parport_generic_irq(irq, (struct parport *) dev_id);
- return IRQ_HANDLED;
-}
-
static void parport_sunbpp_disable_irq(struct parport *p)
{
struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base;
@@ -324,7 +318,7 @@ static int __devinit init_one_port(struct sbus_dev *sdev)
p->size = size;
p->dev = &sdev->ofdev.dev;
- if ((err = request_irq(p->irq, parport_sunbpp_interrupt,
+ if ((err = request_irq(p->irq, parport_irq_handler,
IRQF_SHARED, p->name, p)) != 0) {
goto out_put_port;
}
diff --git a/drivers/parport/probe.c b/drivers/parport/probe.c
index ea83b70e0de2..853a15f44f88 100644
--- a/drivers/parport/probe.c
+++ b/drivers/parport/probe.c
@@ -255,8 +255,7 @@ static ssize_t parport_read_device_id (struct parport *port, char *buffer,
ssize_t parport_device_id (int devnum, char *buffer, size_t count)
{
ssize_t retval = -ENXIO;
- struct pardevice *dev = parport_open (devnum, "Device ID probe",
- NULL, NULL, NULL, 0, NULL);
+ struct pardevice *dev = parport_open (devnum, "Device ID probe");
if (!dev)
return -ENXIO;
diff --git a/drivers/parport/procfs.c b/drivers/parport/procfs.c
index bdbdab9285ca..ed82e41210d1 100644
--- a/drivers/parport/procfs.c
+++ b/drivers/parport/procfs.c
@@ -237,7 +237,7 @@ static int do_hardware_modes (ctl_table *table, int write,
#define PARPORT_PARPORT_DIR(CHILD) { .ctl_name = DEV_PARPORT, .procname = "parport", \
.mode = 0555, .child = CHILD }
#define PARPORT_DEV_DIR(CHILD) { .ctl_name = CTL_DEV, .procname = "dev", .mode = 0555, .child = CHILD }
-#define PARPORT_DEVICES_ROOT_DIR { .ctl_name = DEV_PARPORT_DEVICES, .procname = "devices", \
+#define PARPORT_DEVICES_ROOT_DIR { .procname = "devices", \
.mode = 0555, .child = NULL }
static const unsigned long parport_min_timeslice_value =
@@ -266,7 +266,6 @@ static const struct parport_sysctl_table parport_sysctl_template = {
.sysctl_header = NULL,
{
{
- .ctl_name = DEV_PARPORT_SPINTIME,
.procname = "spintime",
.data = NULL,
.maxlen = sizeof(int),
@@ -276,7 +275,6 @@ static const struct parport_sysctl_table parport_sysctl_template = {
.extra2 = (void*) &parport_max_spintime_value
},
{
- .ctl_name = DEV_PARPORT_BASE_ADDR,
.procname = "base-addr",
.data = NULL,
.maxlen = 0,
@@ -284,7 +282,6 @@ static const struct parport_sysctl_table parport_sysctl_template = {
.proc_handler = &do_hardware_base_addr
},
{
- .ctl_name = DEV_PARPORT_IRQ,
.procname = "irq",
.data = NULL,
.maxlen = 0,
@@ -292,7 +289,6 @@ static const struct parport_sysctl_table parport_sysctl_template = {
.proc_handler = &do_hardware_irq
},
{
- .ctl_name = DEV_PARPORT_DMA,
.procname = "dma",
.data = NULL,
.maxlen = 0,
@@ -300,7 +296,6 @@ static const struct parport_sysctl_table parport_sysctl_template = {
.proc_handler = &do_hardware_dma
},
{
- .ctl_name = DEV_PARPORT_MODES,
.procname = "modes",
.data = NULL,
.maxlen = 0,
@@ -310,7 +305,6 @@ static const struct parport_sysctl_table parport_sysctl_template = {
PARPORT_DEVICES_ROOT_DIR,
#ifdef CONFIG_PARPORT_1284
{
- .ctl_name = DEV_PARPORT_AUTOPROBE,
.procname = "autoprobe",
.data = NULL,
.maxlen = 0,
@@ -318,7 +312,6 @@ static const struct parport_sysctl_table parport_sysctl_template = {
.proc_handler = &do_autoprobe
},
{
- .ctl_name = DEV_PARPORT_AUTOPROBE + 1,
.procname = "autoprobe0",
.data = NULL,
.maxlen = 0,
@@ -326,7 +319,6 @@ static const struct parport_sysctl_table parport_sysctl_template = {
.proc_handler = &do_autoprobe
},
{
- .ctl_name = DEV_PARPORT_AUTOPROBE + 2,
.procname = "autoprobe1",
.data = NULL,
.maxlen = 0,
@@ -334,7 +326,6 @@ static const struct parport_sysctl_table parport_sysctl_template = {
.proc_handler = &do_autoprobe
},
{
- .ctl_name = DEV_PARPORT_AUTOPROBE + 3,
.procname = "autoprobe2",
.data = NULL,
.maxlen = 0,
@@ -342,7 +333,6 @@ static const struct parport_sysctl_table parport_sysctl_template = {
.proc_handler = &do_autoprobe
},
{
- .ctl_name = DEV_PARPORT_AUTOPROBE + 4,
.procname = "autoprobe3",
.data = NULL,
.maxlen = 0,
@@ -354,7 +344,6 @@ static const struct parport_sysctl_table parport_sysctl_template = {
},
{
{
- .ctl_name = DEV_PARPORT_DEVICES_ACTIVE,
.procname = "active",
.data = NULL,
.maxlen = 0,
@@ -393,7 +382,6 @@ parport_device_sysctl_template = {
.sysctl_header = NULL,
{
{
- .ctl_name = DEV_PARPORT_DEVICE_TIMESLICE,
.procname = "timeslice",
.data = NULL,
.maxlen = sizeof(int),
@@ -449,7 +437,6 @@ parport_default_sysctl_table = {
.sysctl_header = NULL,
{
{
- .ctl_name = DEV_PARPORT_DEFAULT_TIMESLICE,
.procname = "timeslice",
.data = &parport_default_timeslice,
.maxlen = sizeof(parport_default_timeslice),
@@ -459,7 +446,6 @@ parport_default_sysctl_table = {
.extra2 = (void*) &parport_max_timeslice_value
},
{
- .ctl_name = DEV_PARPORT_DEFAULT_SPINTIME,
.procname = "spintime",
.data = &parport_default_spintime,
.maxlen = sizeof(parport_default_spintime),
@@ -502,7 +488,7 @@ int parport_proc_register(struct parport *port)
t->device_dir[0].extra1 = port;
- for (i = 0; i < 8; i++)
+ for (i = 0; i < 5; i++)
t->vars[i].extra1 = port;
t->vars[0].data = &port->spintime;
@@ -512,7 +498,7 @@ int parport_proc_register(struct parport *port)
t->vars[6 + i].extra2 = &port->probe_info[i];
t->port_dir[0].procname = port->name;
- t->port_dir[0].ctl_name = port->number + 1; /* nb 0 isn't legal here */
+ t->port_dir[0].ctl_name = 0;
t->port_dir[0].child = t->vars;
t->parport_dir[0].child = t->port_dir;
@@ -551,26 +537,12 @@ int parport_device_proc_register(struct pardevice *device)
t->dev_dir[0].child = t->parport_dir;
t->parport_dir[0].child = t->port_dir;
t->port_dir[0].procname = port->name;
- t->port_dir[0].ctl_name = port->number + 1; /* nb 0 isn't legal here */
+ t->port_dir[0].ctl_name = 0;
t->port_dir[0].child = t->devices_root_dir;
t->devices_root_dir[0].child = t->device_dir;
-#ifdef CONFIG_PARPORT_1284
-
- t->device_dir[0].ctl_name =
- parport_device_num(port->number, port->muxport,
- device->daisy)
- + 1; /* nb 0 isn't legal here */
-
-#else /* No IEEE 1284 support */
-
- /* parport_device_num isn't available. */
- t->device_dir[0].ctl_name = 1;
-
-#endif /* IEEE 1284 support or not */
-
+ t->device_dir[0].ctl_name = 0;
t->device_dir[0].procname = device->name;
- t->device_dir[0].extra1 = device;
t->device_dir[0].child = t->vars;
t->vars[0].data = &device->timeslice;
diff --git a/drivers/parport/share.c b/drivers/parport/share.c
index cd66442acfee..a8a62bbbb576 100644
--- a/drivers/parport/share.c
+++ b/drivers/parport/share.c
@@ -524,7 +524,7 @@ void parport_remove_port(struct parport *port)
struct pardevice *
parport_register_device(struct parport *port, const char *name,
int (*pf)(void *), void (*kf)(void *),
- void (*irq_func)(int, void *),
+ void (*irq_func)(void *),
int flags, void *handle)
{
struct pardevice *tmp;
@@ -995,6 +995,15 @@ void parport_release(struct pardevice *dev)
}
}
+irqreturn_t parport_irq_handler(int irq, void *dev_id)
+{
+ struct parport *port = dev_id;
+
+ parport_generic_irq(port);
+
+ return IRQ_HANDLED;
+}
+
/* Exported symbols for modules. */
EXPORT_SYMBOL(parport_claim);
@@ -1011,5 +1020,6 @@ EXPORT_SYMBOL(parport_get_port);
EXPORT_SYMBOL(parport_put_port);
EXPORT_SYMBOL(parport_find_number);
EXPORT_SYMBOL(parport_find_base);
+EXPORT_SYMBOL(parport_irq_handler);
MODULE_LICENSE("GPL");
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 7a1d6d512837..e1ca42591ac4 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -21,6 +21,17 @@ config PCI_MSI
If you don't know what to do here, say N.
+config PCI_LEGACY
+ bool "Enable deprecated pci_find_* API"
+ depends on PCI
+ default y
+ help
+ Say Y here if you want to include support for the deprecated
+ pci_find_slot() and pci_find_device() APIs. Most drivers have
+ been converted over to using the proper hotplug APIs, so this
+ option serves to include/exclude only a few drivers that are
+ still using this API.
+
config PCI_DEBUG
bool "PCI Debugging"
depends on PCI && DEBUG_KERNEL
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 006054a40995..555055650733 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -20,6 +20,9 @@ obj-$(CONFIG_PCI_MSI) += msi.o
# Build the Hypertransport interrupt support
obj-$(CONFIG_HT_IRQ) += htirq.o
+# Build Intel IOMMU support
+obj-$(CONFIG_DMAR) += dmar.o iova.o intel-iommu.o
+
#
# Some architectures use the generic PCI setup functions
#
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
new file mode 100644
index 000000000000..5dfdfdac92e1
--- /dev/null
+++ b/drivers/pci/dmar.c
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Copyright (C) Ashok Raj <ashok.raj@intel.com>
+ * Copyright (C) Shaohua Li <shaohua.li@intel.com>
+ * Copyright (C) Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
+ *
+ * This file implements early detection/parsing of DMA Remapping Devices
+ * reported to OS through BIOS via DMA remapping reporting (DMAR) ACPI
+ * tables.
+ */
+
+#include <linux/pci.h>
+#include <linux/dmar.h>
+
+#undef PREFIX
+#define PREFIX "DMAR:"
+
+/* No locks are needed as DMA remapping hardware unit
+ * list is constructed at boot time and hotplug of
+ * these units are not supported by the architecture.
+ */
+LIST_HEAD(dmar_drhd_units);
+LIST_HEAD(dmar_rmrr_units);
+
+static struct acpi_table_header * __initdata dmar_tbl;
+
+static void __init dmar_register_drhd_unit(struct dmar_drhd_unit *drhd)
+{
+ /*
+ * add INCLUDE_ALL at the tail, so scan the list will find it at
+ * the very end.
+ */
+ if (drhd->include_all)
+ list_add_tail(&drhd->list, &dmar_drhd_units);
+ else
+ list_add(&drhd->list, &dmar_drhd_units);
+}
+
+static void __init dmar_register_rmrr_unit(struct dmar_rmrr_unit *rmrr)
+{
+ list_add(&rmrr->list, &dmar_rmrr_units);
+}
+
+static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope,
+ struct pci_dev **dev, u16 segment)
+{
+ struct pci_bus *bus;
+ struct pci_dev *pdev = NULL;
+ struct acpi_dmar_pci_path *path;
+ int count;
+
+ bus = pci_find_bus(segment, scope->bus);
+ path = (struct acpi_dmar_pci_path *)(scope + 1);
+ count = (scope->length - sizeof(struct acpi_dmar_device_scope))
+ / sizeof(struct acpi_dmar_pci_path);
+
+ while (count) {
+ if (pdev)
+ pci_dev_put(pdev);
+ /*
+ * Some BIOSes list non-exist devices in DMAR table, just
+ * ignore it
+ */
+ if (!bus) {
+ printk(KERN_WARNING
+ PREFIX "Device scope bus [%d] not found\n",
+ scope->bus);
+ break;
+ }
+ pdev = pci_get_slot(bus, PCI_DEVFN(path->dev, path->fn));
+ if (!pdev) {
+ printk(KERN_WARNING PREFIX
+ "Device scope device [%04x:%02x:%02x.%02x] not found\n",
+ segment, bus->number, path->dev, path->fn);
+ break;
+ }
+ path ++;
+ count --;
+ bus = pdev->subordinate;
+ }
+ if (!pdev) {
+ printk(KERN_WARNING PREFIX
+ "Device scope device [%04x:%02x:%02x.%02x] not found\n",
+ segment, scope->bus, path->dev, path->fn);
+ *dev = NULL;
+ return 0;
+ }
+ if ((scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT && \
+ pdev->subordinate) || (scope->entry_type == \
+ ACPI_DMAR_SCOPE_TYPE_BRIDGE && !pdev->subordinate)) {
+ pci_dev_put(pdev);
+ printk(KERN_WARNING PREFIX
+ "Device scope type does not match for %s\n",
+ pci_name(pdev));
+ return -EINVAL;
+ }
+ *dev = pdev;
+ return 0;
+}
+
+static int __init dmar_parse_dev_scope(void *start, void *end, int *cnt,
+ struct pci_dev ***devices, u16 segment)
+{
+ struct acpi_dmar_device_scope *scope;
+ void * tmp = start;
+ int index;
+ int ret;
+
+ *cnt = 0;
+ while (start < end) {
+ scope = start;
+ if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT ||
+ scope->entry_type == ACPI_DMAR_SCOPE_TYPE_BRIDGE)
+ (*cnt)++;
+ else
+ printk(KERN_WARNING PREFIX
+ "Unsupported device scope\n");
+ start += scope->length;
+ }
+ if (*cnt == 0)
+ return 0;
+
+ *devices = kcalloc(*cnt, sizeof(struct pci_dev *), GFP_KERNEL);
+ if (!*devices)
+ return -ENOMEM;
+
+ start = tmp;
+ index = 0;
+ while (start < end) {
+ scope = start;
+ if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT ||
+ scope->entry_type == ACPI_DMAR_SCOPE_TYPE_BRIDGE) {
+ ret = dmar_parse_one_dev_scope(scope,
+ &(*devices)[index], segment);
+ if (ret) {
+ kfree(*devices);
+ return ret;
+ }
+ index ++;
+ }
+ start += scope->length;
+ }
+
+ return 0;
+}
+
+/**
+ * dmar_parse_one_drhd - parses exactly one DMA remapping hardware definition
+ * structure which uniquely represent one DMA remapping hardware unit
+ * present in the platform
+ */
+static int __init
+dmar_parse_one_drhd(struct acpi_dmar_header *header)
+{
+ struct acpi_dmar_hardware_unit *drhd;
+ struct dmar_drhd_unit *dmaru;
+ int ret = 0;
+ static int include_all;
+
+ dmaru = kzalloc(sizeof(*dmaru), GFP_KERNEL);
+ if (!dmaru)
+ return -ENOMEM;
+
+ drhd = (struct acpi_dmar_hardware_unit *)header;
+ dmaru->reg_base_addr = drhd->address;
+ dmaru->include_all = drhd->flags & 0x1; /* BIT0: INCLUDE_ALL */
+
+ if (!dmaru->include_all)
+ ret = dmar_parse_dev_scope((void *)(drhd + 1),
+ ((void *)drhd) + header->length,
+ &dmaru->devices_cnt, &dmaru->devices,
+ drhd->segment);
+ else {
+ /* Only allow one INCLUDE_ALL */
+ if (include_all) {
+ printk(KERN_WARNING PREFIX "Only one INCLUDE_ALL "
+ "device scope is allowed\n");
+ ret = -EINVAL;
+ }
+ include_all = 1;
+ }
+
+ if (ret || (dmaru->devices_cnt == 0 && !dmaru->include_all))
+ kfree(dmaru);
+ else
+ dmar_register_drhd_unit(dmaru);
+ return ret;
+}
+
+static int __init
+dmar_parse_one_rmrr(struct acpi_dmar_header *header)
+{
+ struct acpi_dmar_reserved_memory *rmrr;
+ struct dmar_rmrr_unit *rmrru;
+ int ret = 0;
+
+ rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL);
+ if (!rmrru)
+ return -ENOMEM;
+
+ rmrr = (struct acpi_dmar_reserved_memory *)header;
+ rmrru->base_address = rmrr->base_address;
+ rmrru->end_address = rmrr->end_address;
+ ret = dmar_parse_dev_scope((void *)(rmrr + 1),
+ ((void *)rmrr) + header->length,
+ &rmrru->devices_cnt, &rmrru->devices, rmrr->segment);
+
+ if (ret || (rmrru->devices_cnt == 0))
+ kfree(rmrru);
+ else
+ dmar_register_rmrr_unit(rmrru);
+ return ret;
+}
+
+static void __init
+dmar_table_print_dmar_entry(struct acpi_dmar_header *header)
+{
+ struct acpi_dmar_hardware_unit *drhd;
+ struct acpi_dmar_reserved_memory *rmrr;
+
+ switch (header->type) {
+ case ACPI_DMAR_TYPE_HARDWARE_UNIT:
+ drhd = (struct acpi_dmar_hardware_unit *)header;
+ printk (KERN_INFO PREFIX
+ "DRHD (flags: 0x%08x)base: 0x%016Lx\n",
+ drhd->flags, drhd->address);
+ break;
+ case ACPI_DMAR_TYPE_RESERVED_MEMORY:
+ rmrr = (struct acpi_dmar_reserved_memory *)header;
+
+ printk (KERN_INFO PREFIX
+ "RMRR base: 0x%016Lx end: 0x%016Lx\n",
+ rmrr->base_address, rmrr->end_address);
+ break;
+ }
+}
+
+/**
+ * parse_dmar_table - parses the DMA reporting table
+ */
+static int __init
+parse_dmar_table(void)
+{
+ struct acpi_table_dmar *dmar;
+ struct acpi_dmar_header *entry_header;
+ int ret = 0;
+
+ dmar = (struct acpi_table_dmar *)dmar_tbl;
+ if (!dmar)
+ return -ENODEV;
+
+ if (!dmar->width) {
+ printk (KERN_WARNING PREFIX "Zero: Invalid DMAR haw\n");
+ return -EINVAL;
+ }
+
+ printk (KERN_INFO PREFIX "Host address width %d\n",
+ dmar->width + 1);
+
+ entry_header = (struct acpi_dmar_header *)(dmar + 1);
+ while (((unsigned long)entry_header) <
+ (((unsigned long)dmar) + dmar_tbl->length)) {
+ dmar_table_print_dmar_entry(entry_header);
+
+ switch (entry_header->type) {
+ case ACPI_DMAR_TYPE_HARDWARE_UNIT:
+ ret = dmar_parse_one_drhd(entry_header);
+ break;
+ case ACPI_DMAR_TYPE_RESERVED_MEMORY:
+ ret = dmar_parse_one_rmrr(entry_header);
+ break;
+ default:
+ printk(KERN_WARNING PREFIX
+ "Unknown DMAR structure type\n");
+ ret = 0; /* for forward compatibility */
+ break;
+ }
+ if (ret)
+ break;
+
+ entry_header = ((void *)entry_header + entry_header->length);
+ }
+ return ret;
+}
+
+
+int __init dmar_table_init(void)
+{
+
+ parse_dmar_table();
+ if (list_empty(&dmar_drhd_units)) {
+ printk(KERN_INFO PREFIX "No DMAR devices found\n");
+ return -ENODEV;
+ }
+ return 0;
+}
+
+/**
+ * early_dmar_detect - checks to see if the platform supports DMAR devices
+ */
+int __init early_dmar_detect(void)
+{
+ acpi_status status = AE_OK;
+
+ /* if we could find DMAR table, then there are DMAR devices */
+ status = acpi_get_table(ACPI_SIG_DMAR, 0,
+ (struct acpi_table_header **)&dmar_tbl);
+
+ if (ACPI_SUCCESS(status) && !dmar_tbl) {
+ printk (KERN_WARNING PREFIX "Unable to map DMAR\n");
+ status = AE_NOT_FOUND;
+ }
+
+ return (ACPI_SUCCESS(status) ? 1 : 0);
+}
diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
index 63d62752fb91..a64449d489d6 100644
--- a/drivers/pci/hotplug/Kconfig
+++ b/drivers/pci/hotplug/Kconfig
@@ -41,7 +41,7 @@ config HOTPLUG_PCI_FAKE
config HOTPLUG_PCI_COMPAQ
tristate "Compaq PCI Hotplug driver"
- depends on X86 && PCI_BIOS
+ depends on X86 && PCI_BIOS && PCI_LEGACY
help
Say Y here if you have a motherboard with a Compaq PCI Hotplug
controller.
@@ -63,7 +63,7 @@ config HOTPLUG_PCI_COMPAQ_NVRAM
config HOTPLUG_PCI_IBM
tristate "IBM PCI Hotplug driver"
- depends on X86_IO_APIC && X86 && PCI_BIOS
+ depends on X86_IO_APIC && X86 && PCI_BIOS && PCI_LEGACY
help
Say Y here if you have a motherboard with a IBM PCI Hotplug
controller.
@@ -119,7 +119,7 @@ config HOTPLUG_PCI_CPCI_ZT5550
config HOTPLUG_PCI_CPCI_GENERIC
tristate "Generic port I/O CompactPCI Hotplug driver"
- depends on HOTPLUG_PCI_CPCI && X86
+ depends on HOTPLUG_PCI_CPCI && X86 && PCI_LEGACY
help
Say Y here if you have a CompactPCI system card that exposes the #ENUM
hotswap signal as a bit in a system register that can be read through
diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c
index 3ef0a4875a62..856d57b4d604 100644
--- a/drivers/pci/hotplug/cpqphp_ctrl.c
+++ b/drivers/pci/hotplug/cpqphp_ctrl.c
@@ -1931,16 +1931,14 @@ void cpqhp_pushbutton_thread(unsigned long slot)
return ;
}
- if (func != NULL && ctrl != NULL) {
- if (cpqhp_process_SS(ctrl, func) != 0) {
- amber_LED_on (ctrl, hp_slot);
- green_LED_on (ctrl, hp_slot);
-
- set_SOGO(ctrl);
+ if (cpqhp_process_SS(ctrl, func) != 0) {
+ amber_LED_on(ctrl, hp_slot);
+ green_LED_on(ctrl, hp_slot);
- /* Wait for SOBS to be unset */
- wait_for_ctrl_irq (ctrl);
- }
+ set_SOGO(ctrl);
+
+ /* Wait for SOBS to be unset */
+ wait_for_ctrl_irq(ctrl);
}
p_slot->state = STATIC_STATE;
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
new file mode 100644
index 000000000000..e079a5237c94
--- /dev/null
+++ b/drivers/pci/intel-iommu.c
@@ -0,0 +1,2270 @@
+/*
+ * Copyright (c) 2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Copyright (C) Ashok Raj <ashok.raj@intel.com>
+ * Copyright (C) Shaohua Li <shaohua.li@intel.com>
+ * Copyright (C) Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
+ */
+
+#include <linux/init.h>
+#include <linux/bitmap.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/sysdev.h>
+#include <linux/spinlock.h>
+#include <linux/pci.h>
+#include <linux/dmar.h>
+#include <linux/dma-mapping.h>
+#include <linux/mempool.h>
+#include "iova.h"
+#include "intel-iommu.h"
+#include <asm/proto.h> /* force_iommu in this header in x86-64*/
+#include <asm/cacheflush.h>
+#include <asm/gart.h>
+#include "pci.h"
+
+#define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
+#define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA)
+
+#define IOAPIC_RANGE_START (0xfee00000)
+#define IOAPIC_RANGE_END (0xfeefffff)
+#define IOVA_START_ADDR (0x1000)
+
+#define DEFAULT_DOMAIN_ADDRESS_WIDTH 48
+
+#define DMAR_OPERATION_TIMEOUT (HZ*60) /* 1m */
+
+#define DOMAIN_MAX_ADDR(gaw) ((((u64)1) << gaw) - 1)
+
+static void domain_remove_dev_info(struct dmar_domain *domain);
+
+static int dmar_disabled;
+static int __initdata dmar_map_gfx = 1;
+static int dmar_forcedac;
+
+#define DUMMY_DEVICE_DOMAIN_INFO ((struct device_domain_info *)(-1))
+static DEFINE_SPINLOCK(device_domain_lock);
+static LIST_HEAD(device_domain_list);
+
+static int __init intel_iommu_setup(char *str)
+{
+ if (!str)
+ return -EINVAL;
+ while (*str) {
+ if (!strncmp(str, "off", 3)) {
+ dmar_disabled = 1;
+ printk(KERN_INFO"Intel-IOMMU: disabled\n");
+ } else if (!strncmp(str, "igfx_off", 8)) {
+ dmar_map_gfx = 0;
+ printk(KERN_INFO
+ "Intel-IOMMU: disable GFX device mapping\n");
+ } else if (!strncmp(str, "forcedac", 8)) {
+ printk (KERN_INFO
+ "Intel-IOMMU: Forcing DAC for PCI devices\n");
+ dmar_forcedac = 1;
+ }
+
+ str += strcspn(str, ",");
+ while (*str == ',')
+ str++;
+ }
+ return 0;
+}
+__setup("intel_iommu=", intel_iommu_setup);
+
+static struct kmem_cache *iommu_domain_cache;
+static struct kmem_cache *iommu_devinfo_cache;
+static struct kmem_cache *iommu_iova_cache;
+
+static inline void *iommu_kmem_cache_alloc(struct kmem_cache *cachep)
+{
+ unsigned int flags;
+ void *vaddr;
+
+ /* trying to avoid low memory issues */
+ flags = current->flags & PF_MEMALLOC;
+ current->flags |= PF_MEMALLOC;
+ vaddr = kmem_cache_alloc(cachep, GFP_ATOMIC);
+ current->flags &= (~PF_MEMALLOC | flags);
+ return vaddr;
+}
+
+
+static inline void *alloc_pgtable_page(void)
+{
+ unsigned int flags;
+ void *vaddr;
+
+ /* trying to avoid low memory issues */
+ flags = current->flags & PF_MEMALLOC;
+ current->flags |= PF_MEMALLOC;
+ vaddr = (void *)get_zeroed_page(GFP_ATOMIC);
+ current->flags &= (~PF_MEMALLOC | flags);
+ return vaddr;
+}
+
+static inline void free_pgtable_page(void *vaddr)
+{
+ free_page((unsigned long)vaddr);
+}
+
+static inline void *alloc_domain_mem(void)
+{
+ return iommu_kmem_cache_alloc(iommu_domain_cache);
+}
+
+static inline void free_domain_mem(void *vaddr)
+{
+ kmem_cache_free(iommu_domain_cache, vaddr);
+}
+
+static inline void * alloc_devinfo_mem(void)
+{
+ return iommu_kmem_cache_alloc(iommu_devinfo_cache);
+}
+
+static inline void free_devinfo_mem(void *vaddr)
+{
+ kmem_cache_free(iommu_devinfo_cache, vaddr);
+}
+
+struct iova *alloc_iova_mem(void)
+{
+ return iommu_kmem_cache_alloc(iommu_iova_cache);
+}
+
+void free_iova_mem(struct iova *iova)
+{
+ kmem_cache_free(iommu_iova_cache, iova);
+}
+
+static inline void __iommu_flush_cache(
+ struct intel_iommu *iommu, void *addr, int size)
+{
+ if (!ecap_coherent(iommu->ecap))
+ clflush_cache_range(addr, size);
+}
+
+/* Gets context entry for a given bus and devfn */
+static struct context_entry * device_to_context_entry(struct intel_iommu *iommu,
+ u8 bus, u8 devfn)
+{
+ struct root_entry *root;
+ struct context_entry *context;
+ unsigned long phy_addr;
+ unsigned long flags;
+
+ spin_lock_irqsave(&iommu->lock, flags);
+ root = &iommu->root_entry[bus];
+ context = get_context_addr_from_root(root);
+ if (!context) {
+ context = (struct context_entry *)alloc_pgtable_page();
+ if (!context) {
+ spin_unlock_irqrestore(&iommu->lock, flags);
+ return NULL;
+ }
+ __iommu_flush_cache(iommu, (void *)context, PAGE_SIZE_4K);
+ phy_addr = virt_to_phys((void *)context);
+ set_root_value(root, phy_addr);
+ set_root_present(root);
+ __iommu_flush_cache(iommu, root, sizeof(*root));
+ }
+ spin_unlock_irqrestore(&iommu->lock, flags);
+ return &context[devfn];
+}
+
+static int device_context_mapped(struct intel_iommu *iommu, u8 bus, u8 devfn)
+{
+ struct root_entry *root;
+ struct context_entry *context;
+ int ret;
+ unsigned long flags;
+
+ spin_lock_irqsave(&iommu->lock, flags);
+ root = &iommu->root_entry[bus];
+ context = get_context_addr_from_root(root);
+ if (!context) {
+ ret = 0;
+ goto out;
+ }
+ ret = context_present(context[devfn]);
+out:
+ spin_unlock_irqrestore(&iommu->lock, flags);
+ return ret;
+}
+
+static void clear_context_table(struct intel_iommu *iommu, u8 bus, u8 devfn)
+{
+ struct root_entry *root;
+ struct context_entry *context;
+ unsigned long flags;
+
+ spin_lock_irqsave(&iommu->lock, flags);
+ root = &iommu->root_entry[bus];
+ context = get_context_addr_from_root(root);
+ if (context) {
+ context_clear_entry(context[devfn]);
+ __iommu_flush_cache(iommu, &context[devfn], \
+ sizeof(*context));
+ }
+ spin_unlock_irqrestore(&iommu->lock, flags);
+}
+
+static void free_context_table(struct intel_iommu *iommu)
+{
+ struct root_entry *root;
+ int i;
+ unsigned long flags;
+ struct context_entry *context;
+
+ spin_lock_irqsave(&iommu->lock, flags);
+ if (!iommu->root_entry) {
+ goto out;
+ }
+ for (i = 0; i < ROOT_ENTRY_NR; i++) {
+ root = &iommu->root_entry[i];
+ context = get_context_addr_from_root(root);
+ if (context)
+ free_pgtable_page(context);
+ }
+ free_pgtable_page(iommu->root_entry);
+ iommu->root_entry = NULL;
+out:
+ spin_unlock_irqrestore(&iommu->lock, flags);
+}
+
+/* page table handling */
+#define LEVEL_STRIDE (9)
+#define LEVEL_MASK (((u64)1 << LEVEL_STRIDE) - 1)
+
+static inline int agaw_to_level(int agaw)
+{
+ return agaw + 2;
+}
+
+static inline int agaw_to_width(int agaw)
+{
+ return 30 + agaw * LEVEL_STRIDE;
+
+}
+
+static inline int width_to_agaw(int width)
+{
+ return (width - 30) / LEVEL_STRIDE;
+}
+
+static inline unsigned int level_to_offset_bits(int level)
+{
+ return (12 + (level - 1) * LEVEL_STRIDE);
+}
+
+static inline int address_level_offset(u64 addr, int level)
+{
+ return ((addr >> level_to_offset_bits(level)) & LEVEL_MASK);
+}
+
+static inline u64 level_mask(int level)
+{
+ return ((u64)-1 << level_to_offset_bits(level));
+}
+
+static inline u64 level_size(int level)
+{
+ return ((u64)1 << level_to_offset_bits(level));
+}
+
+static inline u64 align_to_level(u64 addr, int level)
+{
+ return ((addr + level_size(level) - 1) & level_mask(level));
+}
+
+static struct dma_pte * addr_to_dma_pte(struct dmar_domain *domain, u64 addr)
+{
+ int addr_width = agaw_to_width(domain->agaw);
+ struct dma_pte *parent, *pte = NULL;
+ int level = agaw_to_level(domain->agaw);
+ int offset;
+ unsigned long flags;
+
+ BUG_ON(!domain->pgd);
+
+ addr &= (((u64)1) << addr_width) - 1;
+ parent = domain->pgd;
+
+ spin_lock_irqsave(&domain->mapping_lock, flags);
+ while (level > 0) {
+ void *tmp_page;
+
+ offset = address_level_offset(addr, level);
+ pte = &parent[offset];
+ if (level == 1)
+ break;
+
+ if (!dma_pte_present(*pte)) {
+ tmp_page = alloc_pgtable_page();
+
+ if (!tmp_page) {
+ spin_unlock_irqrestore(&domain->mapping_lock,
+ flags);
+ return NULL;
+ }
+ __iommu_flush_cache(domain->iommu, tmp_page,
+ PAGE_SIZE_4K);
+ dma_set_pte_addr(*pte, virt_to_phys(tmp_page));
+ /*
+ * high level table always sets r/w, last level page
+ * table control read/write
+ */
+ dma_set_pte_readable(*pte);
+ dma_set_pte_writable(*pte);
+ __iommu_flush_cache(domain->iommu, pte, sizeof(*pte));
+ }
+ parent = phys_to_virt(dma_pte_addr(*pte));
+ level--;
+ }
+
+ spin_unlock_irqrestore(&domain->mapping_lock, flags);
+ return pte;
+}
+
+/* return address's pte at specific level */
+static struct dma_pte *dma_addr_level_pte(struct dmar_domain *domain, u64 addr,
+ int level)
+{
+ struct dma_pte *parent, *pte = NULL;
+ int total = agaw_to_level(domain->agaw);
+ int offset;
+
+ parent = domain->pgd;
+ while (level <= total) {
+ offset = address_level_offset(addr, total);
+ pte = &parent[offset];
+ if (level == total)
+ return pte;
+
+ if (!dma_pte_present(*pte))
+ break;
+ parent = phys_to_virt(dma_pte_addr(*pte));
+ total--;
+ }
+ return NULL;
+}
+
+/* clear one page's page table */
+static void dma_pte_clear_one(struct dmar_domain *domain, u64 addr)
+{
+ struct dma_pte *pte = NULL;
+
+ /* get last level pte */
+ pte = dma_addr_level_pte(domain, addr, 1);
+
+ if (pte) {
+ dma_clear_pte(*pte);
+ __iommu_flush_cache(domain->iommu, pte, sizeof(*pte));
+ }
+}
+
+/* clear last level pte, a tlb flush should be followed */
+static void dma_pte_clear_range(struct dmar_domain *domain, u64 start, u64 end)
+{
+ int addr_width = agaw_to_width(domain->agaw);
+
+ start &= (((u64)1) << addr_width) - 1;
+ end &= (((u64)1) << addr_width) - 1;
+ /* in case it's partial page */
+ start = PAGE_ALIGN_4K(start);
+ end &= PAGE_MASK_4K;
+
+ /* we don't need lock here, nobody else touches the iova range */
+ while (start < end) {
+ dma_pte_clear_one(domain, start);
+ start += PAGE_SIZE_4K;
+ }
+}
+
+/* free page table pages. last level pte should already be cleared */
+static void dma_pte_free_pagetable(struct dmar_domain *domain,
+ u64 start, u64 end)
+{
+ int addr_width = agaw_to_width(domain->agaw);
+ struct dma_pte *pte;
+ int total = agaw_to_level(domain->agaw);
+ int level;
+ u64 tmp;
+
+ start &= (((u64)1) << addr_width) - 1;
+ end &= (((u64)1) << addr_width) - 1;
+
+ /* we don't need lock here, nobody else touches the iova range */
+ level = 2;
+ while (level <= total) {
+ tmp = align_to_level(start, level);
+ if (tmp >= end || (tmp + level_size(level) > end))
+ return;
+
+ while (tmp < end) {
+ pte = dma_addr_level_pte(domain, tmp, level);
+ if (pte) {
+ free_pgtable_page(
+ phys_to_virt(dma_pte_addr(*pte)));
+ dma_clear_pte(*pte);
+ __iommu_flush_cache(domain->iommu,
+ pte, sizeof(*pte));
+ }
+ tmp += level_size(level);
+ }
+ level++;
+ }
+ /* free pgd */
+ if (start == 0 && end >= ((((u64)1) << addr_width) - 1)) {
+ free_pgtable_page(domain->pgd);
+ domain->pgd = NULL;
+ }
+}
+
+/* iommu handling */
+static int iommu_alloc_root_entry(struct intel_iommu *iommu)
+{
+ struct root_entry *root;
+ unsigned long flags;
+
+ root = (struct root_entry *)alloc_pgtable_page();
+ if (!root)
+ return -ENOMEM;
+
+ __iommu_flush_cache(iommu, root, PAGE_SIZE_4K);
+
+ spin_lock_irqsave(&iommu->lock, flags);
+ iommu->root_entry = root;
+ spin_unlock_irqrestore(&iommu->lock, flags);
+
+ return 0;
+}
+
+#define IOMMU_WAIT_OP(iommu, offset, op, cond, sts) \
+{\
+ unsigned long start_time = jiffies;\
+ while (1) {\
+ sts = op (iommu->reg + offset);\
+ if (cond)\
+ break;\
+ if (time_after(jiffies, start_time + DMAR_OPERATION_TIMEOUT))\
+ panic("DMAR hardware is malfunctioning\n");\
+ cpu_relax();\
+ }\
+}
+
+static void iommu_set_root_entry(struct intel_iommu *iommu)
+{
+ void *addr;
+ u32 cmd, sts;
+ unsigned long flag;
+
+ addr = iommu->root_entry;
+
+ spin_lock_irqsave(&iommu->register_lock, flag);
+ dmar_writeq(iommu->reg + DMAR_RTADDR_REG, virt_to_phys(addr));
+
+ cmd = iommu->gcmd | DMA_GCMD_SRTP;
+ writel(cmd, iommu->reg + DMAR_GCMD_REG);
+
+ /* Make sure hardware complete it */
+ IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
+ readl, (sts & DMA_GSTS_RTPS), sts);
+
+ spin_unlock_irqrestore(&iommu->register_lock, flag);
+}
+
+static void iommu_flush_write_buffer(struct intel_iommu *iommu)
+{
+ u32 val;
+ unsigned long flag;
+
+ if (!cap_rwbf(iommu->cap))
+ return;
+ val = iommu->gcmd | DMA_GCMD_WBF;
+
+ spin_lock_irqsave(&iommu->register_lock, flag);
+ writel(val, iommu->reg + DMAR_GCMD_REG);
+
+ /* Make sure hardware complete it */
+ IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
+ readl, (!(val & DMA_GSTS_WBFS)), val);
+
+ spin_unlock_irqrestore(&iommu->register_lock, flag);
+}
+
+/* return value determine if we need a write buffer flush */
+static int __iommu_flush_context(struct intel_iommu *iommu,
+ u16 did, u16 source_id, u8 function_mask, u64 type,
+ int non_present_entry_flush)
+{
+ u64 val = 0;
+ unsigned long flag;
+
+ /*
+ * In the non-present entry flush case, if hardware doesn't cache
+ * non-present entry we do nothing and if hardware cache non-present
+ * entry, we flush entries of domain 0 (the domain id is used to cache
+ * any non-present entries)
+ */
+ if (non_present_entry_flush) {
+ if (!cap_caching_mode(iommu->cap))
+ return 1;
+ else
+ did = 0;
+ }
+
+ switch (type) {
+ case DMA_CCMD_GLOBAL_INVL:
+ val = DMA_CCMD_GLOBAL_INVL;
+ break;
+ case DMA_CCMD_DOMAIN_INVL:
+ val = DMA_CCMD_DOMAIN_INVL|DMA_CCMD_DID(did);
+ break;
+ case DMA_CCMD_DEVICE_INVL:
+ val = DMA_CCMD_DEVICE_INVL|DMA_CCMD_DID(did)
+ | DMA_CCMD_SID(source_id) | DMA_CCMD_FM(function_mask);
+ break;
+ default:
+ BUG();
+ }
+ val |= DMA_CCMD_ICC;
+
+ spin_lock_irqsave(&iommu->register_lock, flag);
+ dmar_writeq(iommu->reg + DMAR_CCMD_REG, val);
+
+ /* Make sure hardware complete it */
+ IOMMU_WAIT_OP(iommu, DMAR_CCMD_REG,
+ dmar_readq, (!(val & DMA_CCMD_ICC)), val);
+
+ spin_unlock_irqrestore(&iommu->register_lock, flag);
+
+ /* flush context entry will implictly flush write buffer */
+ return 0;
+}
+
+static int inline iommu_flush_context_global(struct intel_iommu *iommu,
+ int non_present_entry_flush)
+{
+ return __iommu_flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL,
+ non_present_entry_flush);
+}
+
+static int inline iommu_flush_context_domain(struct intel_iommu *iommu, u16 did,
+ int non_present_entry_flush)
+{
+ return __iommu_flush_context(iommu, did, 0, 0, DMA_CCMD_DOMAIN_INVL,
+ non_present_entry_flush);
+}
+
+static int inline iommu_flush_context_device(struct intel_iommu *iommu,
+ u16 did, u16 source_id, u8 function_mask, int non_present_entry_flush)
+{
+ return __iommu_flush_context(iommu, did, source_id, function_mask,
+ DMA_CCMD_DEVICE_INVL, non_present_entry_flush);
+}
+
+/* return value determine if we need a write buffer flush */
+static int __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did,
+ u64 addr, unsigned int size_order, u64 type,
+ int non_present_entry_flush)
+{
+ int tlb_offset = ecap_iotlb_offset(iommu->ecap);
+ u64 val = 0, val_iva = 0;
+ unsigned long flag;
+
+ /*
+ * In the non-present entry flush case, if hardware doesn't cache
+ * non-present entry we do nothing and if hardware cache non-present
+ * entry, we flush entries of domain 0 (the domain id is used to cache
+ * any non-present entries)
+ */
+ if (non_present_entry_flush) {
+ if (!cap_caching_mode(iommu->cap))
+ return 1;
+ else
+ did = 0;
+ }
+
+ switch (type) {
+ case DMA_TLB_GLOBAL_FLUSH:
+ /* global flush doesn't need set IVA_REG */
+ val = DMA_TLB_GLOBAL_FLUSH|DMA_TLB_IVT;
+ break;
+ case DMA_TLB_DSI_FLUSH:
+ val = DMA_TLB_DSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did);
+ break;
+ case DMA_TLB_PSI_FLUSH:
+ val = DMA_TLB_PSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did);
+ /* Note: always flush non-leaf currently */
+ val_iva = size_order | addr;
+ break;
+ default:
+ BUG();
+ }
+ /* Note: set drain read/write */
+#if 0
+ /*
+ * This is probably to be super secure.. Looks like we can
+ * ignore it without any impact.
+ */
+ if (cap_read_drain(iommu->cap))
+ val |= DMA_TLB_READ_DRAIN;
+#endif
+ if (cap_write_drain(iommu->cap))
+ val |= DMA_TLB_WRITE_DRAIN;
+
+ spin_lock_irqsave(&iommu->register_lock, flag);
+ /* Note: Only uses first TLB reg currently */
+ if (val_iva)
+ dmar_writeq(iommu->reg + tlb_offset, val_iva);
+ dmar_writeq(iommu->reg + tlb_offset + 8, val);
+
+ /* Make sure hardware complete it */
+ IOMMU_WAIT_OP(iommu, tlb_offset + 8,
+ dmar_readq, (!(val & DMA_TLB_IVT)), val);
+
+ spin_unlock_irqrestore(&iommu->register_lock, flag);
+
+ /* check IOTLB invalidation granularity */
+ if (DMA_TLB_IAIG(val) == 0)
+ printk(KERN_ERR"IOMMU: flush IOTLB failed\n");
+ if (DMA_TLB_IAIG(val) != DMA_TLB_IIRG(type))
+ pr_debug("IOMMU: tlb flush request %Lx, actual %Lx\n",
+ DMA_TLB_IIRG(type), DMA_TLB_IAIG(val));
+ /* flush context entry will implictly flush write buffer */
+ return 0;
+}
+
+static int inline iommu_flush_iotlb_global(struct intel_iommu *iommu,
+ int non_present_entry_flush)
+{
+ return __iommu_flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH,
+ non_present_entry_flush);
+}
+
+static int inline iommu_flush_iotlb_dsi(struct intel_iommu *iommu, u16 did,
+ int non_present_entry_flush)
+{
+ return __iommu_flush_iotlb(iommu, did, 0, 0, DMA_TLB_DSI_FLUSH,
+ non_present_entry_flush);
+}
+
+static int iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did,
+ u64 addr, unsigned int pages, int non_present_entry_flush)
+{
+ unsigned int mask;
+
+ BUG_ON(addr & (~PAGE_MASK_4K));
+ BUG_ON(pages == 0);
+
+ /* Fallback to domain selective flush if no PSI support */
+ if (!cap_pgsel_inv(iommu->cap))
+ return iommu_flush_iotlb_dsi(iommu, did,
+ non_present_entry_flush);
+
+ /*
+ * PSI requires page size to be 2 ^ x, and the base address is naturally
+ * aligned to the size
+ */
+ mask = ilog2(__roundup_pow_of_two(pages));
+ /* Fallback to domain selective flush if size is too big */
+ if (mask > cap_max_amask_val(iommu->cap))
+ return iommu_flush_iotlb_dsi(iommu, did,
+ non_present_entry_flush);
+
+ return __iommu_flush_iotlb(iommu, did, addr, mask,
+ DMA_TLB_PSI_FLUSH, non_present_entry_flush);
+}
+
+static int iommu_enable_translation(struct intel_iommu *iommu)
+{
+ u32 sts;
+ unsigned long flags;
+
+ spin_lock_irqsave(&iommu->register_lock, flags);
+ writel(iommu->gcmd|DMA_GCMD_TE, iommu->reg + DMAR_GCMD_REG);
+
+ /* Make sure hardware complete it */
+ IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
+ readl, (sts & DMA_GSTS_TES), sts);
+
+ iommu->gcmd |= DMA_GCMD_TE;
+ spin_unlock_irqrestore(&iommu->register_lock, flags);
+ return 0;
+}
+
+static int iommu_disable_translation(struct intel_iommu *iommu)
+{
+ u32 sts;
+ unsigned long flag;
+
+ spin_lock_irqsave(&iommu->register_lock, flag);
+ iommu->gcmd &= ~DMA_GCMD_TE;
+ writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
+
+ /* Make sure hardware complete it */
+ IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
+ readl, (!(sts & DMA_GSTS_TES)), sts);
+
+ spin_unlock_irqrestore(&iommu->register_lock, flag);
+ return 0;
+}
+
+/* iommu interrupt handling. Most stuff are MSI-like. */
+
+static char *fault_reason_strings[] =
+{
+ "Software",
+ "Present bit in root entry is clear",
+ "Present bit in context entry is clear",
+ "Invalid context entry",
+ "Access beyond MGAW",
+ "PTE Write access is not set",
+ "PTE Read access is not set",
+ "Next page table ptr is invalid",
+ "Root table address invalid",
+ "Context table ptr is invalid",
+ "non-zero reserved fields in RTP",
+ "non-zero reserved fields in CTP",
+ "non-zero reserved fields in PTE",
+ "Unknown"
+};
+#define MAX_FAULT_REASON_IDX ARRAY_SIZE(fault_reason_strings) - 1
+
+char *dmar_get_fault_reason(u8 fault_reason)
+{
+ if (fault_reason >= MAX_FAULT_REASON_IDX)
+ return fault_reason_strings[MAX_FAULT_REASON_IDX - 1];
+ else
+ return fault_reason_strings[fault_reason];
+}
+
+void dmar_msi_unmask(unsigned int irq)
+{
+ struct intel_iommu *iommu = get_irq_data(irq);
+ unsigned long flag;
+
+ /* unmask it */
+ spin_lock_irqsave(&iommu->register_lock, flag);
+ writel(0, iommu->reg + DMAR_FECTL_REG);
+ /* Read a reg to force flush the post write */
+ readl(iommu->reg + DMAR_FECTL_REG);
+ spin_unlock_irqrestore(&iommu->register_lock, flag);
+}
+
+void dmar_msi_mask(unsigned int irq)
+{
+ unsigned long flag;
+ struct intel_iommu *iommu = get_irq_data(irq);
+
+ /* mask it */
+ spin_lock_irqsave(&iommu->register_lock, flag);
+ writel(DMA_FECTL_IM, iommu->reg + DMAR_FECTL_REG);
+ /* Read a reg to force flush the post write */
+ readl(iommu->reg + DMAR_FECTL_REG);
+ spin_unlock_irqrestore(&iommu->register_lock, flag);
+}
+
+void dmar_msi_write(int irq, struct msi_msg *msg)
+{
+ struct intel_iommu *iommu = get_irq_data(irq);
+ unsigned long flag;
+
+ spin_lock_irqsave(&iommu->register_lock, flag);
+ writel(msg->data, iommu->reg + DMAR_FEDATA_REG);
+ writel(msg->address_lo, iommu->reg + DMAR_FEADDR_REG);
+ writel(msg->address_hi, iommu->reg + DMAR_FEUADDR_REG);
+ spin_unlock_irqrestore(&iommu->register_lock, flag);
+}
+
+void dmar_msi_read(int irq, struct msi_msg *msg)
+{
+ struct intel_iommu *iommu = get_irq_data(irq);
+ unsigned long flag;
+
+ spin_lock_irqsave(&iommu->register_lock, flag);
+ msg->data = readl(iommu->reg + DMAR_FEDATA_REG);
+ msg->address_lo = readl(iommu->reg + DMAR_FEADDR_REG);
+ msg->address_hi = readl(iommu->reg + DMAR_FEUADDR_REG);
+ spin_unlock_irqrestore(&iommu->register_lock, flag);
+}
+
+static int iommu_page_fault_do_one(struct intel_iommu *iommu, int type,
+ u8 fault_reason, u16 source_id, u64 addr)
+{
+ char *reason;
+
+ reason = dmar_get_fault_reason(fault_reason);
+
+ printk(KERN_ERR
+ "DMAR:[%s] Request device [%02x:%02x.%d] "
+ "fault addr %llx \n"
+ "DMAR:[fault reason %02d] %s\n",
+ (type ? "DMA Read" : "DMA Write"),
+ (source_id >> 8), PCI_SLOT(source_id & 0xFF),
+ PCI_FUNC(source_id & 0xFF), addr, fault_reason, reason);
+ return 0;
+}
+
+#define PRIMARY_FAULT_REG_LEN (16)
+static irqreturn_t iommu_page_fault(int irq, void *dev_id)
+{
+ struct intel_iommu *iommu = dev_id;
+ int reg, fault_index;
+ u32 fault_status;
+ unsigned long flag;
+
+ spin_lock_irqsave(&iommu->register_lock, flag);
+ fault_status = readl(iommu->reg + DMAR_FSTS_REG);
+
+ /* TBD: ignore advanced fault log currently */
+ if (!(fault_status & DMA_FSTS_PPF))
+ goto clear_overflow;
+
+ fault_index = dma_fsts_fault_record_index(fault_status);
+ reg = cap_fault_reg_offset(iommu->cap);
+ while (1) {
+ u8 fault_reason;
+ u16 source_id;
+ u64 guest_addr;
+ int type;
+ u32 data;
+
+ /* highest 32 bits */
+ data = readl(iommu->reg + reg +
+ fault_index * PRIMARY_FAULT_REG_LEN + 12);
+ if (!(data & DMA_FRCD_F))
+ break;
+
+ fault_reason = dma_frcd_fault_reason(data);
+ type = dma_frcd_type(data);
+
+ data = readl(iommu->reg + reg +
+ fault_index * PRIMARY_FAULT_REG_LEN + 8);
+ source_id = dma_frcd_source_id(data);
+
+ guest_addr = dmar_readq(iommu->reg + reg +
+ fault_index * PRIMARY_FAULT_REG_LEN);
+ guest_addr = dma_frcd_page_addr(guest_addr);
+ /* clear the fault */
+ writel(DMA_FRCD_F, iommu->reg + reg +
+ fault_index * PRIMARY_FAULT_REG_LEN + 12);
+
+ spin_unlock_irqrestore(&iommu->register_lock, flag);
+
+ iommu_page_fault_do_one(iommu, type, fault_reason,
+ source_id, guest_addr);
+
+ fault_index++;
+ if (fault_index > cap_num_fault_regs(iommu->cap))
+ fault_index = 0;
+ spin_lock_irqsave(&iommu->register_lock, flag);
+ }
+clear_overflow:
+ /* clear primary fault overflow */
+ fault_status = readl(iommu->reg + DMAR_FSTS_REG);
+ if (fault_status & DMA_FSTS_PFO)
+ writel(DMA_FSTS_PFO, iommu->reg + DMAR_FSTS_REG);
+
+ spin_unlock_irqrestore(&iommu->register_lock, flag);
+ return IRQ_HANDLED;
+}
+
+int dmar_set_interrupt(struct intel_iommu *iommu)
+{
+ int irq, ret;
+
+ irq = create_irq();
+ if (!irq) {
+ printk(KERN_ERR "IOMMU: no free vectors\n");
+ return -EINVAL;
+ }
+
+ set_irq_data(irq, iommu);
+ iommu->irq = irq;
+
+ ret = arch_setup_dmar_msi(irq);
+ if (ret) {
+ set_irq_data(irq, NULL);
+ iommu->irq = 0;
+ destroy_irq(irq);
+ return 0;
+ }
+
+ /* Force fault register is cleared */
+ iommu_page_fault(irq, iommu);
+
+ ret = request_irq(irq, iommu_page_fault, 0, iommu->name, iommu);
+ if (ret)
+ printk(KERN_ERR "IOMMU: can't request irq\n");
+ return ret;
+}
+
+static int iommu_init_domains(struct intel_iommu *iommu)
+{
+ unsigned long ndomains;
+ unsigned long nlongs;
+
+ ndomains = cap_ndoms(iommu->cap);
+ pr_debug("Number of Domains supportd <%ld>\n", ndomains);
+ nlongs = BITS_TO_LONGS(ndomains);
+
+ /* TBD: there might be 64K domains,
+ * consider other allocation for future chip
+ */
+ iommu->domain_ids = kcalloc(nlongs, sizeof(unsigned long), GFP_KERNEL);
+ if (!iommu->domain_ids) {
+ printk(KERN_ERR "Allocating domain id array failed\n");
+ return -ENOMEM;
+ }
+ iommu->domains = kcalloc(ndomains, sizeof(struct dmar_domain *),
+ GFP_KERNEL);
+ if (!iommu->domains) {
+ printk(KERN_ERR "Allocating domain array failed\n");
+ kfree(iommu->domain_ids);
+ return -ENOMEM;
+ }
+
+ /*
+ * if Caching mode is set, then invalid translations are tagged
+ * with domainid 0. Hence we need to pre-allocate it.
+ */
+ if (cap_caching_mode(iommu->cap))
+ set_bit(0, iommu->domain_ids);
+ return 0;
+}
+
+static struct intel_iommu *alloc_iommu(struct dmar_drhd_unit *drhd)
+{
+ struct intel_iommu *iommu;
+ int ret;
+ int map_size;
+ u32 ver;
+
+ iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
+ if (!iommu)
+ return NULL;
+ iommu->reg = ioremap(drhd->reg_base_addr, PAGE_SIZE_4K);
+ if (!iommu->reg) {
+ printk(KERN_ERR "IOMMU: can't map the region\n");
+ goto error;
+ }
+ iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG);
+ iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG);
+
+ /* the registers might be more than one page */
+ map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap),
+ cap_max_fault_reg_offset(iommu->cap));
+ map_size = PAGE_ALIGN_4K(map_size);
+ if (map_size > PAGE_SIZE_4K) {
+ iounmap(iommu->reg);
+ iommu->reg = ioremap(drhd->reg_base_addr, map_size);
+ if (!iommu->reg) {
+ printk(KERN_ERR "IOMMU: can't map the region\n");
+ goto error;
+ }
+ }
+
+ ver = readl(iommu->reg + DMAR_VER_REG);
+ pr_debug("IOMMU %llx: ver %d:%d cap %llx ecap %llx\n",
+ drhd->reg_base_addr, DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver),
+ iommu->cap, iommu->ecap);
+ ret = iommu_init_domains(iommu);
+ if (ret)
+ goto error_unmap;
+ spin_lock_init(&iommu->lock);
+ spin_lock_init(&iommu->register_lock);
+
+ drhd->iommu = iommu;
+ return iommu;
+error_unmap:
+ iounmap(iommu->reg);
+error:
+ kfree(iommu);
+ return NULL;
+}
+
+static void domain_exit(struct dmar_domain *domain);
+static void free_iommu(struct intel_iommu *iommu)
+{
+ struct dmar_domain *domain;
+ int i;
+
+ if (!iommu)
+ return;
+
+ i = find_first_bit(iommu->domain_ids, cap_ndoms(iommu->cap));
+ for (; i < cap_ndoms(iommu->cap); ) {
+ domain = iommu->domains[i];
+ clear_bit(i, iommu->domain_ids);
+ domain_exit(domain);
+ i = find_next_bit(iommu->domain_ids,
+ cap_ndoms(iommu->cap), i+1);
+ }
+
+ if (iommu->gcmd & DMA_GCMD_TE)
+ iommu_disable_translation(iommu);
+
+ if (iommu->irq) {
+ set_irq_data(iommu->irq, NULL);
+ /* This will mask the irq */
+ free_irq(iommu->irq, iommu);
+ destroy_irq(iommu->irq);
+ }
+
+ kfree(iommu->domains);
+ kfree(iommu->domain_ids);
+
+ /* free context mapping */
+ free_context_table(iommu);
+
+ if (iommu->reg)
+ iounmap(iommu->reg);
+ kfree(iommu);
+}
+
+static struct dmar_domain * iommu_alloc_domain(struct intel_iommu *iommu)
+{
+ unsigned long num;
+ unsigned long ndomains;
+ struct dmar_domain *domain;
+ unsigned long flags;
+
+ domain = alloc_domain_mem();
+ if (!domain)
+ return NULL;
+
+ ndomains = cap_ndoms(iommu->cap);
+
+ spin_lock_irqsave(&iommu->lock, flags);
+ num = find_first_zero_bit(iommu->domain_ids, ndomains);
+ if (num >= ndomains) {
+ spin_unlock_irqrestore(&iommu->lock, flags);
+ free_domain_mem(domain);
+ printk(KERN_ERR "IOMMU: no free domain ids\n");
+ return NULL;
+ }
+
+ set_bit(num, iommu->domain_ids);
+ domain->id = num;
+ domain->iommu = iommu;
+ iommu->domains[num] = domain;
+ spin_unlock_irqrestore(&iommu->lock, flags);
+
+ return domain;
+}
+
+static void iommu_free_domain(struct dmar_domain *domain)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&domain->iommu->lock, flags);
+ clear_bit(domain->id, domain->iommu->domain_ids);
+ spin_unlock_irqrestore(&domain->iommu->lock, flags);
+}
+
+static struct iova_domain reserved_iova_list;
+
+static void dmar_init_reserved_ranges(void)
+{
+ struct pci_dev *pdev = NULL;
+ struct iova *iova;
+ int i;
+ u64 addr, size;
+
+ init_iova_domain(&reserved_iova_list);
+
+ /* IOAPIC ranges shouldn't be accessed by DMA */
+ iova = reserve_iova(&reserved_iova_list, IOVA_PFN(IOAPIC_RANGE_START),
+ IOVA_PFN(IOAPIC_RANGE_END));
+ if (!iova)
+ printk(KERN_ERR "Reserve IOAPIC range failed\n");
+
+ /* Reserve all PCI MMIO to avoid peer-to-peer access */
+ for_each_pci_dev(pdev) {
+ struct resource *r;
+
+ for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+ r = &pdev->resource[i];
+ if (!r->flags || !(r->flags & IORESOURCE_MEM))
+ continue;
+ addr = r->start;
+ addr &= PAGE_MASK_4K;
+ size = r->end - addr;
+ size = PAGE_ALIGN_4K(size);
+ iova = reserve_iova(&reserved_iova_list, IOVA_PFN(addr),
+ IOVA_PFN(size + addr) - 1);
+ if (!iova)
+ printk(KERN_ERR "Reserve iova failed\n");
+ }
+ }
+
+}
+
+static void domain_reserve_special_ranges(struct dmar_domain *domain)
+{
+ copy_reserved_iova(&reserved_iova_list, &domain->iovad);
+}
+
+static inline int guestwidth_to_adjustwidth(int gaw)
+{
+ int agaw;
+ int r = (gaw - 12) % 9;
+
+ if (r == 0)
+ agaw = gaw;
+ else
+ agaw = gaw + 9 - r;
+ if (agaw > 64)
+ agaw = 64;
+ return agaw;
+}
+
+static int domain_init(struct dmar_domain *domain, int guest_width)
+{
+ struct intel_iommu *iommu;
+ int adjust_width, agaw;
+ unsigned long sagaw;
+
+ init_iova_domain(&domain->iovad);
+ spin_lock_init(&domain->mapping_lock);
+
+ domain_reserve_special_ranges(domain);
+
+ /* calculate AGAW */
+ iommu = domain->iommu;
+ if (guest_width > cap_mgaw(iommu->cap))
+ guest_width = cap_mgaw(iommu->cap);
+ domain->gaw = guest_width;
+ adjust_width = guestwidth_to_adjustwidth(guest_width);
+ agaw = width_to_agaw(adjust_width);
+ sagaw = cap_sagaw(iommu->cap);
+ if (!test_bit(agaw, &sagaw)) {
+ /* hardware doesn't support it, choose a bigger one */
+ pr_debug("IOMMU: hardware doesn't support agaw %d\n", agaw);
+ agaw = find_next_bit(&sagaw, 5, agaw);
+ if (agaw >= 5)
+ return -ENODEV;
+ }
+ domain->agaw = agaw;
+ INIT_LIST_HEAD(&domain->devices);
+
+ /* always allocate the top pgd */
+ domain->pgd = (struct dma_pte *)alloc_pgtable_page();
+ if (!domain->pgd)
+ return -ENOMEM;
+ __iommu_flush_cache(iommu, domain->pgd, PAGE_SIZE_4K);
+ return 0;
+}
+
+static void domain_exit(struct dmar_domain *domain)
+{
+ u64 end;
+
+ /* Domain 0 is reserved, so dont process it */
+ if (!domain)
+ return;
+
+ domain_remove_dev_info(domain);
+ /* destroy iovas */
+ put_iova_domain(&domain->iovad);
+ end = DOMAIN_MAX_ADDR(domain->gaw);
+ end = end & (~PAGE_MASK_4K);
+
+ /* clear ptes */
+ dma_pte_clear_range(domain, 0, end);
+
+ /* free page tables */
+ dma_pte_free_pagetable(domain, 0, end);
+
+ iommu_free_domain(domain);
+ free_domain_mem(domain);
+}
+
+static int domain_context_mapping_one(struct dmar_domain *domain,
+ u8 bus, u8 devfn)
+{
+ struct context_entry *context;
+ struct intel_iommu *iommu = domain->iommu;
+ unsigned long flags;
+
+ pr_debug("Set context mapping for %02x:%02x.%d\n",
+ bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+ BUG_ON(!domain->pgd);
+ context = device_to_context_entry(iommu, bus, devfn);
+ if (!context)
+ return -ENOMEM;
+ spin_lock_irqsave(&iommu->lock, flags);
+ if (context_present(*context)) {
+ spin_unlock_irqrestore(&iommu->lock, flags);
+ return 0;
+ }
+
+ context_set_domain_id(*context, domain->id);
+ context_set_address_width(*context, domain->agaw);
+ context_set_address_root(*context, virt_to_phys(domain->pgd));
+ context_set_translation_type(*context, CONTEXT_TT_MULTI_LEVEL);
+ context_set_fault_enable(*context);
+ context_set_present(*context);
+ __iommu_flush_cache(iommu, context, sizeof(*context));
+
+ /* it's a non-present to present mapping */
+ if (iommu_flush_context_device(iommu, domain->id,
+ (((u16)bus) << 8) | devfn, DMA_CCMD_MASK_NOBIT, 1))
+ iommu_flush_write_buffer(iommu);
+ else
+ iommu_flush_iotlb_dsi(iommu, 0, 0);
+ spin_unlock_irqrestore(&iommu->lock, flags);
+ return 0;
+}
+
+static int
+domain_context_mapping(struct dmar_domain *domain, struct pci_dev *pdev)
+{
+ int ret;
+ struct pci_dev *tmp, *parent;
+
+ ret = domain_context_mapping_one(domain, pdev->bus->number,
+ pdev->devfn);
+ if (ret)
+ return ret;
+
+ /* dependent device mapping */
+ tmp = pci_find_upstream_pcie_bridge(pdev);
+ if (!tmp)
+ return 0;
+ /* Secondary interface's bus number and devfn 0 */
+ parent = pdev->bus->self;
+ while (parent != tmp) {
+ ret = domain_context_mapping_one(domain, parent->bus->number,
+ parent->devfn);
+ if (ret)
+ return ret;
+ parent = parent->bus->self;
+ }
+ if (tmp->is_pcie) /* this is a PCIE-to-PCI bridge */
+ return domain_context_mapping_one(domain,
+ tmp->subordinate->number, 0);
+ else /* this is a legacy PCI bridge */
+ return domain_context_mapping_one(domain,
+ tmp->bus->number, tmp->devfn);
+}
+
+static int domain_context_mapped(struct dmar_domain *domain,
+ struct pci_dev *pdev)
+{
+ int ret;
+ struct pci_dev *tmp, *parent;
+
+ ret = device_context_mapped(domain->iommu,
+ pdev->bus->number, pdev->devfn);
+ if (!ret)
+ return ret;
+ /* dependent device mapping */
+ tmp = pci_find_upstream_pcie_bridge(pdev);
+ if (!tmp)
+ return ret;
+ /* Secondary interface's bus number and devfn 0 */
+ parent = pdev->bus->self;
+ while (parent != tmp) {
+ ret = device_context_mapped(domain->iommu, parent->bus->number,
+ parent->devfn);
+ if (!ret)
+ return ret;
+ parent = parent->bus->self;
+ }
+ if (tmp->is_pcie)
+ return device_context_mapped(domain->iommu,
+ tmp->subordinate->number, 0);
+ else
+ return device_context_mapped(domain->iommu,
+ tmp->bus->number, tmp->devfn);
+}
+
+static int
+domain_page_mapping(struct dmar_domain *domain, dma_addr_t iova,
+ u64 hpa, size_t size, int prot)
+{
+ u64 start_pfn, end_pfn;
+ struct dma_pte *pte;
+ int index;
+
+ if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0)
+ return -EINVAL;
+ iova &= PAGE_MASK_4K;
+ start_pfn = ((u64)hpa) >> PAGE_SHIFT_4K;
+ end_pfn = (PAGE_ALIGN_4K(((u64)hpa) + size)) >> PAGE_SHIFT_4K;
+ index = 0;
+ while (start_pfn < end_pfn) {
+ pte = addr_to_dma_pte(domain, iova + PAGE_SIZE_4K * index);
+ if (!pte)
+ return -ENOMEM;
+ /* We don't need lock here, nobody else
+ * touches the iova range
+ */
+ BUG_ON(dma_pte_addr(*pte));
+ dma_set_pte_addr(*pte, start_pfn << PAGE_SHIFT_4K);
+ dma_set_pte_prot(*pte, prot);
+ __iommu_flush_cache(domain->iommu, pte, sizeof(*pte));
+ start_pfn++;
+ index++;
+ }
+ return 0;
+}
+
+static void detach_domain_for_dev(struct dmar_domain *domain, u8 bus, u8 devfn)
+{
+ clear_context_table(domain->iommu, bus, devfn);
+ iommu_flush_context_global(domain->iommu, 0);
+ iommu_flush_iotlb_global(domain->iommu, 0);
+}
+
+static void domain_remove_dev_info(struct dmar_domain *domain)
+{
+ struct device_domain_info *info;
+ unsigned long flags;
+
+ spin_lock_irqsave(&device_domain_lock, flags);
+ while (!list_empty(&domain->devices)) {
+ info = list_entry(domain->devices.next,
+ struct device_domain_info, link);
+ list_del(&info->link);
+ list_del(&info->global);
+ if (info->dev)
+ info->dev->dev.archdata.iommu = NULL;
+ spin_unlock_irqrestore(&device_domain_lock, flags);
+
+ detach_domain_for_dev(info->domain, info->bus, info->devfn);
+ free_devinfo_mem(info);
+
+ spin_lock_irqsave(&device_domain_lock, flags);
+ }
+ spin_unlock_irqrestore(&device_domain_lock, flags);
+}
+
+/*
+ * find_domain
+ * Note: we use struct pci_dev->dev.archdata.iommu stores the info
+ */
+struct dmar_domain *
+find_domain(struct pci_dev *pdev)
+{
+ struct device_domain_info *info;
+
+ /* No lock here, assumes no domain exit in normal case */
+ info = pdev->dev.archdata.iommu;
+ if (info)
+ return info->domain;
+ return NULL;
+}
+
+static int dmar_pci_device_match(struct pci_dev *devices[], int cnt,
+ struct pci_dev *dev)
+{
+ int index;
+
+ while (dev) {
+ for (index = 0; index < cnt; index ++)
+ if (dev == devices[index])
+ return 1;
+
+ /* Check our parent */
+ dev = dev->bus->self;
+ }
+
+ return 0;
+}
+
+static struct dmar_drhd_unit *
+dmar_find_matched_drhd_unit(struct pci_dev *dev)
+{
+ struct dmar_drhd_unit *drhd = NULL;
+
+ list_for_each_entry(drhd, &dmar_drhd_units, list) {
+ if (drhd->include_all || dmar_pci_device_match(drhd->devices,
+ drhd->devices_cnt, dev))
+ return drhd;
+ }
+
+ return NULL;
+}
+
+/* domain is initialized */
+static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
+{
+ struct dmar_domain *domain, *found = NULL;
+ struct intel_iommu *iommu;
+ struct dmar_drhd_unit *drhd;
+ struct device_domain_info *info, *tmp;
+ struct pci_dev *dev_tmp;
+ unsigned long flags;
+ int bus = 0, devfn = 0;
+
+ domain = find_domain(pdev);
+ if (domain)
+ return domain;
+
+ dev_tmp = pci_find_upstream_pcie_bridge(pdev);
+ if (dev_tmp) {
+ if (dev_tmp->is_pcie) {
+ bus = dev_tmp->subordinate->number;
+ devfn = 0;
+ } else {
+ bus = dev_tmp->bus->number;
+ devfn = dev_tmp->devfn;
+ }
+ spin_lock_irqsave(&device_domain_lock, flags);
+ list_for_each_entry(info, &device_domain_list, global) {
+ if (info->bus == bus && info->devfn == devfn) {
+ found = info->domain;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&device_domain_lock, flags);
+ /* pcie-pci bridge already has a domain, uses it */
+ if (found) {
+ domain = found;
+ goto found_domain;
+ }
+ }
+
+ /* Allocate new domain for the device */
+ drhd = dmar_find_matched_drhd_unit(pdev);
+ if (!drhd) {
+ printk(KERN_ERR "IOMMU: can't find DMAR for device %s\n",
+ pci_name(pdev));
+ return NULL;
+ }
+ iommu = drhd->iommu;
+
+ domain = iommu_alloc_domain(iommu);
+ if (!domain)
+ goto error;
+
+ if (domain_init(domain, gaw)) {
+ domain_exit(domain);
+ goto error;
+ }
+
+ /* register pcie-to-pci device */
+ if (dev_tmp) {
+ info = alloc_devinfo_mem();
+ if (!info) {
+ domain_exit(domain);
+ goto error;
+ }
+ info->bus = bus;
+ info->devfn = devfn;
+ info->dev = NULL;
+ info->domain = domain;
+ /* This domain is shared by devices under p2p bridge */
+ domain->flags |= DOMAIN_FLAG_MULTIPLE_DEVICES;
+
+ /* pcie-to-pci bridge already has a domain, uses it */
+ found = NULL;
+ spin_lock_irqsave(&device_domain_lock, flags);
+ list_for_each_entry(tmp, &device_domain_list, global) {
+ if (tmp->bus == bus && tmp->devfn == devfn) {
+ found = tmp->domain;
+ break;
+ }
+ }
+ if (found) {
+ free_devinfo_mem(info);
+ domain_exit(domain);
+ domain = found;
+ } else {
+ list_add(&info->link, &domain->devices);
+ list_add(&info->global, &device_domain_list);
+ }
+ spin_unlock_irqrestore(&device_domain_lock, flags);
+ }
+
+found_domain:
+ info = alloc_devinfo_mem();
+ if (!info)
+ goto error;
+ info->bus = pdev->bus->number;
+ info->devfn = pdev->devfn;
+ info->dev = pdev;
+ info->domain = domain;
+ spin_lock_irqsave(&device_domain_lock, flags);
+ /* somebody is fast */
+ found = find_domain(pdev);
+ if (found != NULL) {
+ spin_unlock_irqrestore(&device_domain_lock, flags);
+ if (found != domain) {
+ domain_exit(domain);
+ domain = found;
+ }
+ free_devinfo_mem(info);
+ return domain;
+ }
+ list_add(&info->link, &domain->devices);
+ list_add(&info->global, &device_domain_list);
+ pdev->dev.archdata.iommu = info;
+ spin_unlock_irqrestore(&device_domain_lock, flags);
+ return domain;
+error:
+ /* recheck it here, maybe others set it */
+ return find_domain(pdev);
+}
+
+static int iommu_prepare_identity_map(struct pci_dev *pdev, u64 start, u64 end)
+{
+ struct dmar_domain *domain;
+ unsigned long size;
+ u64 base;
+ int ret;
+
+ printk(KERN_INFO
+ "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n",
+ pci_name(pdev), start, end);
+ /* page table init */
+ domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
+ if (!domain)
+ return -ENOMEM;
+
+ /* The address might not be aligned */
+ base = start & PAGE_MASK_4K;
+ size = end - base;
+ size = PAGE_ALIGN_4K(size);
+ if (!reserve_iova(&domain->iovad, IOVA_PFN(base),
+ IOVA_PFN(base + size) - 1)) {
+ printk(KERN_ERR "IOMMU: reserve iova failed\n");
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ pr_debug("Mapping reserved region %lx@%llx for %s\n",
+ size, base, pci_name(pdev));
+ /*
+ * RMRR range might have overlap with physical memory range,
+ * clear it first
+ */
+ dma_pte_clear_range(domain, base, base + size);
+
+ ret = domain_page_mapping(domain, base, base, size,
+ DMA_PTE_READ|DMA_PTE_WRITE);
+ if (ret)
+ goto error;
+
+ /* context entry init */
+ ret = domain_context_mapping(domain, pdev);
+ if (!ret)
+ return 0;
+error:
+ domain_exit(domain);
+ return ret;
+
+}
+
+static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr,
+ struct pci_dev *pdev)
+{
+ if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
+ return 0;
+ return iommu_prepare_identity_map(pdev, rmrr->base_address,
+ rmrr->end_address + 1);
+}
+
+#ifdef CONFIG_DMAR_GFX_WA
+extern int arch_get_ram_range(int slot, u64 *addr, u64 *size);
+static void __init iommu_prepare_gfx_mapping(void)
+{
+ struct pci_dev *pdev = NULL;
+ u64 base, size;
+ int slot;
+ int ret;
+
+ for_each_pci_dev(pdev) {
+ if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO ||
+ !IS_GFX_DEVICE(pdev))
+ continue;
+ printk(KERN_INFO "IOMMU: gfx device %s 1-1 mapping\n",
+ pci_name(pdev));
+ slot = arch_get_ram_range(0, &base, &size);
+ while (slot >= 0) {
+ ret = iommu_prepare_identity_map(pdev,
+ base, base + size);
+ if (ret)
+ goto error;
+ slot = arch_get_ram_range(slot, &base, &size);
+ }
+ continue;
+error:
+ printk(KERN_ERR "IOMMU: mapping reserved region failed\n");
+ }
+}
+#endif
+
+#ifdef CONFIG_DMAR_FLOPPY_WA
+static inline void iommu_prepare_isa(void)
+{
+ struct pci_dev *pdev;
+ int ret;
+
+ pdev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
+ if (!pdev)
+ return;
+
+ printk(KERN_INFO "IOMMU: Prepare 0-16M unity mapping for LPC\n");
+ ret = iommu_prepare_identity_map(pdev, 0, 16*1024*1024);
+
+ if (ret)
+ printk("IOMMU: Failed to create 0-64M identity map, "
+ "floppy might not work\n");
+
+}
+#else
+static inline void iommu_prepare_isa(void)
+{
+ return;
+}
+#endif /* !CONFIG_DMAR_FLPY_WA */
+
+int __init init_dmars(void)
+{
+ struct dmar_drhd_unit *drhd;
+ struct dmar_rmrr_unit *rmrr;
+ struct pci_dev *pdev;
+ struct intel_iommu *iommu;
+ int ret, unit = 0;
+
+ /*
+ * for each drhd
+ * allocate root
+ * initialize and program root entry to not present
+ * endfor
+ */
+ for_each_drhd_unit(drhd) {
+ if (drhd->ignored)
+ continue;
+ iommu = alloc_iommu(drhd);
+ if (!iommu) {
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ /*
+ * TBD:
+ * we could share the same root & context tables
+ * amoung all IOMMU's. Need to Split it later.
+ */
+ ret = iommu_alloc_root_entry(iommu);
+ if (ret) {
+ printk(KERN_ERR "IOMMU: allocate root entry failed\n");
+ goto error;
+ }
+ }
+
+ /*
+ * For each rmrr
+ * for each dev attached to rmrr
+ * do
+ * locate drhd for dev, alloc domain for dev
+ * allocate free domain
+ * allocate page table entries for rmrr
+ * if context not allocated for bus
+ * allocate and init context
+ * set present in root table for this bus
+ * init context with domain, translation etc
+ * endfor
+ * endfor
+ */
+ for_each_rmrr_units(rmrr) {
+ int i;
+ for (i = 0; i < rmrr->devices_cnt; i++) {
+ pdev = rmrr->devices[i];
+ /* some BIOS lists non-exist devices in DMAR table */
+ if (!pdev)
+ continue;
+ ret = iommu_prepare_rmrr_dev(rmrr, pdev);
+ if (ret)
+ printk(KERN_ERR
+ "IOMMU: mapping reserved region failed\n");
+ }
+ }
+
+ iommu_prepare_gfx_mapping();
+
+ iommu_prepare_isa();
+
+ /*
+ * for each drhd
+ * enable fault log
+ * global invalidate context cache
+ * global invalidate iotlb
+ * enable translation
+ */
+ for_each_drhd_unit(drhd) {
+ if (drhd->ignored)
+ continue;
+ iommu = drhd->iommu;
+ sprintf (iommu->name, "dmar%d", unit++);
+
+ iommu_flush_write_buffer(iommu);
+
+ ret = dmar_set_interrupt(iommu);
+ if (ret)
+ goto error;
+
+ iommu_set_root_entry(iommu);
+
+ iommu_flush_context_global(iommu, 0);
+ iommu_flush_iotlb_global(iommu, 0);
+
+ ret = iommu_enable_translation(iommu);
+ if (ret)
+ goto error;
+ }
+
+ return 0;
+error:
+ for_each_drhd_unit(drhd) {
+ if (drhd->ignored)
+ continue;
+ iommu = drhd->iommu;
+ free_iommu(iommu);
+ }
+ return ret;
+}
+
+static inline u64 aligned_size(u64 host_addr, size_t size)
+{
+ u64 addr;
+ addr = (host_addr & (~PAGE_MASK_4K)) + size;
+ return PAGE_ALIGN_4K(addr);
+}
+
+struct iova *
+iommu_alloc_iova(struct dmar_domain *domain, size_t size, u64 end)
+{
+ struct iova *piova;
+
+ /* Make sure it's in range */
+ end = min_t(u64, DOMAIN_MAX_ADDR(domain->gaw), end);
+ if (!size || (IOVA_START_ADDR + size > end))
+ return NULL;
+
+ piova = alloc_iova(&domain->iovad,
+ size >> PAGE_SHIFT_4K, IOVA_PFN(end), 1);
+ return piova;
+}
+
+static struct iova *
+__intel_alloc_iova(struct device *dev, struct dmar_domain *domain,
+ size_t size)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct iova *iova = NULL;
+
+ if ((pdev->dma_mask <= DMA_32BIT_MASK) || (dmar_forcedac)) {
+ iova = iommu_alloc_iova(domain, size, pdev->dma_mask);
+ } else {
+ /*
+ * First try to allocate an io virtual address in
+ * DMA_32BIT_MASK and if that fails then try allocating
+ * from higer range
+ */
+ iova = iommu_alloc_iova(domain, size, DMA_32BIT_MASK);
+ if (!iova)
+ iova = iommu_alloc_iova(domain, size, pdev->dma_mask);
+ }
+
+ if (!iova) {
+ printk(KERN_ERR"Allocating iova for %s failed", pci_name(pdev));
+ return NULL;
+ }
+
+ return iova;
+}
+
+static struct dmar_domain *
+get_valid_domain_for_dev(struct pci_dev *pdev)
+{
+ struct dmar_domain *domain;
+ int ret;
+
+ domain = get_domain_for_dev(pdev,
+ DEFAULT_DOMAIN_ADDRESS_WIDTH);
+ if (!domain) {
+ printk(KERN_ERR
+ "Allocating domain for %s failed", pci_name(pdev));
+ return NULL;
+ }
+
+ /* make sure context mapping is ok */
+ if (unlikely(!domain_context_mapped(domain, pdev))) {
+ ret = domain_context_mapping(domain, pdev);
+ if (ret) {
+ printk(KERN_ERR
+ "Domain context map for %s failed",
+ pci_name(pdev));
+ return NULL;
+ }
+ }
+
+ return domain;
+}
+
+static dma_addr_t intel_map_single(struct device *hwdev, void *addr,
+ size_t size, int dir)
+{
+ struct pci_dev *pdev = to_pci_dev(hwdev);
+ int ret;
+ struct dmar_domain *domain;
+ unsigned long start_addr;
+ struct iova *iova;
+ int prot = 0;
+
+ BUG_ON(dir == DMA_NONE);
+ if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
+ return virt_to_bus(addr);
+
+ domain = get_valid_domain_for_dev(pdev);
+ if (!domain)
+ return 0;
+
+ addr = (void *)virt_to_phys(addr);
+ size = aligned_size((u64)addr, size);
+
+ iova = __intel_alloc_iova(hwdev, domain, size);
+ if (!iova)
+ goto error;
+
+ start_addr = iova->pfn_lo << PAGE_SHIFT_4K;
+
+ /*
+ * Check if DMAR supports zero-length reads on write only
+ * mappings..
+ */
+ if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
+ !cap_zlr(domain->iommu->cap))
+ prot |= DMA_PTE_READ;
+ if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
+ prot |= DMA_PTE_WRITE;
+ /*
+ * addr - (addr + size) might be partial page, we should map the whole
+ * page. Note: if two part of one page are separately mapped, we
+ * might have two guest_addr mapping to the same host addr, but this
+ * is not a big problem
+ */
+ ret = domain_page_mapping(domain, start_addr,
+ ((u64)addr) & PAGE_MASK_4K, size, prot);
+ if (ret)
+ goto error;
+
+ pr_debug("Device %s request: %lx@%llx mapping: %lx@%llx, dir %d\n",
+ pci_name(pdev), size, (u64)addr,
+ size, (u64)start_addr, dir);
+
+ /* it's a non-present to present mapping */
+ ret = iommu_flush_iotlb_psi(domain->iommu, domain->id,
+ start_addr, size >> PAGE_SHIFT_4K, 1);
+ if (ret)
+ iommu_flush_write_buffer(domain->iommu);
+
+ return (start_addr + ((u64)addr & (~PAGE_MASK_4K)));
+
+error:
+ if (iova)
+ __free_iova(&domain->iovad, iova);
+ printk(KERN_ERR"Device %s request: %lx@%llx dir %d --- failed\n",
+ pci_name(pdev), size, (u64)addr, dir);
+ return 0;
+}
+
+static void intel_unmap_single(struct device *dev, dma_addr_t dev_addr,
+ size_t size, int dir)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct dmar_domain *domain;
+ unsigned long start_addr;
+ struct iova *iova;
+
+ if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
+ return;
+ domain = find_domain(pdev);
+ BUG_ON(!domain);
+
+ iova = find_iova(&domain->iovad, IOVA_PFN(dev_addr));
+ if (!iova)
+ return;
+
+ start_addr = iova->pfn_lo << PAGE_SHIFT_4K;
+ size = aligned_size((u64)dev_addr, size);
+
+ pr_debug("Device %s unmapping: %lx@%llx\n",
+ pci_name(pdev), size, (u64)start_addr);
+
+ /* clear the whole page */
+ dma_pte_clear_range(domain, start_addr, start_addr + size);
+ /* free page tables */
+ dma_pte_free_pagetable(domain, start_addr, start_addr + size);
+
+ if (iommu_flush_iotlb_psi(domain->iommu, domain->id, start_addr,
+ size >> PAGE_SHIFT_4K, 0))
+ iommu_flush_write_buffer(domain->iommu);
+
+ /* free iova */
+ __free_iova(&domain->iovad, iova);
+}
+
+static void * intel_alloc_coherent(struct device *hwdev, size_t size,
+ dma_addr_t *dma_handle, gfp_t flags)
+{
+ void *vaddr;
+ int order;
+
+ size = PAGE_ALIGN_4K(size);
+ order = get_order(size);
+ flags &= ~(GFP_DMA | GFP_DMA32);
+
+ vaddr = (void *)__get_free_pages(flags, order);
+ if (!vaddr)
+ return NULL;
+ memset(vaddr, 0, size);
+
+ *dma_handle = intel_map_single(hwdev, vaddr, size, DMA_BIDIRECTIONAL);
+ if (*dma_handle)
+ return vaddr;
+ free_pages((unsigned long)vaddr, order);
+ return NULL;
+}
+
+static void intel_free_coherent(struct device *hwdev, size_t size,
+ void *vaddr, dma_addr_t dma_handle)
+{
+ int order;
+
+ size = PAGE_ALIGN_4K(size);
+ order = get_order(size);
+
+ intel_unmap_single(hwdev, dma_handle, size, DMA_BIDIRECTIONAL);
+ free_pages((unsigned long)vaddr, order);
+}
+
+#define SG_ENT_VIRT_ADDRESS(sg) (sg_virt((sg)))
+static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist,
+ int nelems, int dir)
+{
+ int i;
+ struct pci_dev *pdev = to_pci_dev(hwdev);
+ struct dmar_domain *domain;
+ unsigned long start_addr;
+ struct iova *iova;
+ size_t size = 0;
+ void *addr;
+ struct scatterlist *sg;
+
+ if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
+ return;
+
+ domain = find_domain(pdev);
+
+ iova = find_iova(&domain->iovad, IOVA_PFN(sglist[0].dma_address));
+ if (!iova)
+ return;
+ for_each_sg(sglist, sg, nelems, i) {
+ addr = SG_ENT_VIRT_ADDRESS(sg);
+ size += aligned_size((u64)addr, sg->length);
+ }
+
+ start_addr = iova->pfn_lo << PAGE_SHIFT_4K;
+
+ /* clear the whole page */
+ dma_pte_clear_range(domain, start_addr, start_addr + size);
+ /* free page tables */
+ dma_pte_free_pagetable(domain, start_addr, start_addr + size);
+
+ if (iommu_flush_iotlb_psi(domain->iommu, domain->id, start_addr,
+ size >> PAGE_SHIFT_4K, 0))
+ iommu_flush_write_buffer(domain->iommu);
+
+ /* free iova */
+ __free_iova(&domain->iovad, iova);
+}
+
+static int intel_nontranslate_map_sg(struct device *hddev,
+ struct scatterlist *sglist, int nelems, int dir)
+{
+ int i;
+ struct scatterlist *sg;
+
+ for_each_sg(sglist, sg, nelems, i) {
+ BUG_ON(!sg_page(sg));
+ sg->dma_address = virt_to_bus(SG_ENT_VIRT_ADDRESS(sg));
+ sg->dma_length = sg->length;
+ }
+ return nelems;
+}
+
+static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist,
+ int nelems, int dir)
+{
+ void *addr;
+ int i;
+ struct pci_dev *pdev = to_pci_dev(hwdev);
+ struct dmar_domain *domain;
+ size_t size = 0;
+ int prot = 0;
+ size_t offset = 0;
+ struct iova *iova = NULL;
+ int ret;
+ struct scatterlist *sg;
+ unsigned long start_addr;
+
+ BUG_ON(dir == DMA_NONE);
+ if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
+ return intel_nontranslate_map_sg(hwdev, sglist, nelems, dir);
+
+ domain = get_valid_domain_for_dev(pdev);
+ if (!domain)
+ return 0;
+
+ for_each_sg(sglist, sg, nelems, i) {
+ addr = SG_ENT_VIRT_ADDRESS(sg);
+ addr = (void *)virt_to_phys(addr);
+ size += aligned_size((u64)addr, sg->length);
+ }
+
+ iova = __intel_alloc_iova(hwdev, domain, size);
+ if (!iova) {
+ sglist->dma_length = 0;
+ return 0;
+ }
+
+ /*
+ * Check if DMAR supports zero-length reads on write only
+ * mappings..
+ */
+ if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
+ !cap_zlr(domain->iommu->cap))
+ prot |= DMA_PTE_READ;
+ if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
+ prot |= DMA_PTE_WRITE;
+
+ start_addr = iova->pfn_lo << PAGE_SHIFT_4K;
+ offset = 0;
+ for_each_sg(sglist, sg, nelems, i) {
+ addr = SG_ENT_VIRT_ADDRESS(sg);
+ addr = (void *)virt_to_phys(addr);
+ size = aligned_size((u64)addr, sg->length);
+ ret = domain_page_mapping(domain, start_addr + offset,
+ ((u64)addr) & PAGE_MASK_4K,
+ size, prot);
+ if (ret) {
+ /* clear the page */
+ dma_pte_clear_range(domain, start_addr,
+ start_addr + offset);
+ /* free page tables */
+ dma_pte_free_pagetable(domain, start_addr,
+ start_addr + offset);
+ /* free iova */
+ __free_iova(&domain->iovad, iova);
+ return 0;
+ }
+ sg->dma_address = start_addr + offset +
+ ((u64)addr & (~PAGE_MASK_4K));
+ sg->dma_length = sg->length;
+ offset += size;
+ }
+
+ /* it's a non-present to present mapping */
+ if (iommu_flush_iotlb_psi(domain->iommu, domain->id,
+ start_addr, offset >> PAGE_SHIFT_4K, 1))
+ iommu_flush_write_buffer(domain->iommu);
+ return nelems;
+}
+
+static struct dma_mapping_ops intel_dma_ops = {
+ .alloc_coherent = intel_alloc_coherent,
+ .free_coherent = intel_free_coherent,
+ .map_single = intel_map_single,
+ .unmap_single = intel_unmap_single,
+ .map_sg = intel_map_sg,
+ .unmap_sg = intel_unmap_sg,
+};
+
+static inline int iommu_domain_cache_init(void)
+{
+ int ret = 0;
+
+ iommu_domain_cache = kmem_cache_create("iommu_domain",
+ sizeof(struct dmar_domain),
+ 0,
+ SLAB_HWCACHE_ALIGN,
+
+ NULL);
+ if (!iommu_domain_cache) {
+ printk(KERN_ERR "Couldn't create iommu_domain cache\n");
+ ret = -ENOMEM;
+ }
+
+ return ret;
+}
+
+static inline int iommu_devinfo_cache_init(void)
+{
+ int ret = 0;
+
+ iommu_devinfo_cache = kmem_cache_create("iommu_devinfo",
+ sizeof(struct device_domain_info),
+ 0,
+ SLAB_HWCACHE_ALIGN,
+
+ NULL);
+ if (!iommu_devinfo_cache) {
+ printk(KERN_ERR "Couldn't create devinfo cache\n");
+ ret = -ENOMEM;
+ }
+
+ return ret;
+}
+
+static inline int iommu_iova_cache_init(void)
+{
+ int ret = 0;
+
+ iommu_iova_cache = kmem_cache_create("iommu_iova",
+ sizeof(struct iova),
+ 0,
+ SLAB_HWCACHE_ALIGN,
+
+ NULL);
+ if (!iommu_iova_cache) {
+ printk(KERN_ERR "Couldn't create iova cache\n");
+ ret = -ENOMEM;
+ }
+
+ return ret;
+}
+
+static int __init iommu_init_mempool(void)
+{
+ int ret;
+ ret = iommu_iova_cache_init();
+ if (ret)
+ return ret;
+
+ ret = iommu_domain_cache_init();
+ if (ret)
+ goto domain_error;
+
+ ret = iommu_devinfo_cache_init();
+ if (!ret)
+ return ret;
+
+ kmem_cache_destroy(iommu_domain_cache);
+domain_error:
+ kmem_cache_destroy(iommu_iova_cache);
+
+ return -ENOMEM;
+}
+
+static void __init iommu_exit_mempool(void)
+{
+ kmem_cache_destroy(iommu_devinfo_cache);
+ kmem_cache_destroy(iommu_domain_cache);
+ kmem_cache_destroy(iommu_iova_cache);
+
+}
+
+void __init detect_intel_iommu(void)
+{
+ if (swiotlb || no_iommu || iommu_detected || dmar_disabled)
+ return;
+ if (early_dmar_detect()) {
+ iommu_detected = 1;
+ }
+}
+
+static void __init init_no_remapping_devices(void)
+{
+ struct dmar_drhd_unit *drhd;
+
+ for_each_drhd_unit(drhd) {
+ if (!drhd->include_all) {
+ int i;
+ for (i = 0; i < drhd->devices_cnt; i++)
+ if (drhd->devices[i] != NULL)
+ break;
+ /* ignore DMAR unit if no pci devices exist */
+ if (i == drhd->devices_cnt)
+ drhd->ignored = 1;
+ }
+ }
+
+ if (dmar_map_gfx)
+ return;
+
+ for_each_drhd_unit(drhd) {
+ int i;
+ if (drhd->ignored || drhd->include_all)
+ continue;
+
+ for (i = 0; i < drhd->devices_cnt; i++)
+ if (drhd->devices[i] &&
+ !IS_GFX_DEVICE(drhd->devices[i]))
+ break;
+
+ if (i < drhd->devices_cnt)
+ continue;
+
+ /* bypass IOMMU if it is just for gfx devices */
+ drhd->ignored = 1;
+ for (i = 0; i < drhd->devices_cnt; i++) {
+ if (!drhd->devices[i])
+ continue;
+ drhd->devices[i]->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
+ }
+ }
+}
+
+int __init intel_iommu_init(void)
+{
+ int ret = 0;
+
+ if (no_iommu || swiotlb || dmar_disabled)
+ return -ENODEV;
+
+ if (dmar_table_init())
+ return -ENODEV;
+
+ iommu_init_mempool();
+ dmar_init_reserved_ranges();
+
+ init_no_remapping_devices();
+
+ ret = init_dmars();
+ if (ret) {
+ printk(KERN_ERR "IOMMU: dmar init failed\n");
+ put_iova_domain(&reserved_iova_list);
+ iommu_exit_mempool();
+ return ret;
+ }
+ printk(KERN_INFO
+ "PCI-DMA: Intel(R) Virtualization Technology for Directed I/O\n");
+
+ force_iommu = 1;
+ dma_ops = &intel_dma_ops;
+ return 0;
+}
+
diff --git a/drivers/pci/intel-iommu.h b/drivers/pci/intel-iommu.h
new file mode 100644
index 000000000000..459ad1f9dc54
--- /dev/null
+++ b/drivers/pci/intel-iommu.h
@@ -0,0 +1,325 @@
+/*
+ * Copyright (c) 2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Copyright (C) Ashok Raj <ashok.raj@intel.com>
+ * Copyright (C) Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
+ */
+
+#ifndef _INTEL_IOMMU_H_
+#define _INTEL_IOMMU_H_
+
+#include <linux/types.h>
+#include <linux/msi.h>
+#include "iova.h"
+#include <linux/io.h>
+
+/*
+ * Intel IOMMU register specification per version 1.0 public spec.
+ */
+
+#define DMAR_VER_REG 0x0 /* Arch version supported by this IOMMU */
+#define DMAR_CAP_REG 0x8 /* Hardware supported capabilities */
+#define DMAR_ECAP_REG 0x10 /* Extended capabilities supported */
+#define DMAR_GCMD_REG 0x18 /* Global command register */
+#define DMAR_GSTS_REG 0x1c /* Global status register */
+#define DMAR_RTADDR_REG 0x20 /* Root entry table */
+#define DMAR_CCMD_REG 0x28 /* Context command reg */
+#define DMAR_FSTS_REG 0x34 /* Fault Status register */
+#define DMAR_FECTL_REG 0x38 /* Fault control register */
+#define DMAR_FEDATA_REG 0x3c /* Fault event interrupt data register */
+#define DMAR_FEADDR_REG 0x40 /* Fault event interrupt addr register */
+#define DMAR_FEUADDR_REG 0x44 /* Upper address register */
+#define DMAR_AFLOG_REG 0x58 /* Advanced Fault control */
+#define DMAR_PMEN_REG 0x64 /* Enable Protected Memory Region */
+#define DMAR_PLMBASE_REG 0x68 /* PMRR Low addr */
+#define DMAR_PLMLIMIT_REG 0x6c /* PMRR low limit */
+#define DMAR_PHMBASE_REG 0x70 /* pmrr high base addr */
+#define DMAR_PHMLIMIT_REG 0x78 /* pmrr high limit */
+
+#define OFFSET_STRIDE (9)
+/*
+#define dmar_readl(dmar, reg) readl(dmar + reg)
+#define dmar_readq(dmar, reg) ({ \
+ u32 lo, hi; \
+ lo = readl(dmar + reg); \
+ hi = readl(dmar + reg + 4); \
+ (((u64) hi) << 32) + lo; })
+*/
+static inline u64 dmar_readq(void __iomem *addr)
+{
+ u32 lo, hi;
+ lo = readl(addr);
+ hi = readl(addr + 4);
+ return (((u64) hi) << 32) + lo;
+}
+
+static inline void dmar_writeq(void __iomem *addr, u64 val)
+{
+ writel((u32)val, addr);
+ writel((u32)(val >> 32), addr + 4);
+}
+
+#define DMAR_VER_MAJOR(v) (((v) & 0xf0) >> 4)
+#define DMAR_VER_MINOR(v) ((v) & 0x0f)
+
+/*
+ * Decoding Capability Register
+ */
+#define cap_read_drain(c) (((c) >> 55) & 1)
+#define cap_write_drain(c) (((c) >> 54) & 1)
+#define cap_max_amask_val(c) (((c) >> 48) & 0x3f)
+#define cap_num_fault_regs(c) ((((c) >> 40) & 0xff) + 1)
+#define cap_pgsel_inv(c) (((c) >> 39) & 1)
+
+#define cap_super_page_val(c) (((c) >> 34) & 0xf)
+#define cap_super_offset(c) (((find_first_bit(&cap_super_page_val(c), 4)) \
+ * OFFSET_STRIDE) + 21)
+
+#define cap_fault_reg_offset(c) ((((c) >> 24) & 0x3ff) * 16)
+#define cap_max_fault_reg_offset(c) \
+ (cap_fault_reg_offset(c) + cap_num_fault_regs(c) * 16)
+
+#define cap_zlr(c) (((c) >> 22) & 1)
+#define cap_isoch(c) (((c) >> 23) & 1)
+#define cap_mgaw(c) ((((c) >> 16) & 0x3f) + 1)
+#define cap_sagaw(c) (((c) >> 8) & 0x1f)
+#define cap_caching_mode(c) (((c) >> 7) & 1)
+#define cap_phmr(c) (((c) >> 6) & 1)
+#define cap_plmr(c) (((c) >> 5) & 1)
+#define cap_rwbf(c) (((c) >> 4) & 1)
+#define cap_afl(c) (((c) >> 3) & 1)
+#define cap_ndoms(c) (((unsigned long)1) << (4 + 2 * ((c) & 0x7)))
+/*
+ * Extended Capability Register
+ */
+
+#define ecap_niotlb_iunits(e) ((((e) >> 24) & 0xff) + 1)
+#define ecap_iotlb_offset(e) ((((e) >> 8) & 0x3ff) * 16)
+#define ecap_max_iotlb_offset(e) \
+ (ecap_iotlb_offset(e) + ecap_niotlb_iunits(e) * 16)
+#define ecap_coherent(e) ((e) & 0x1)
+
+
+/* IOTLB_REG */
+#define DMA_TLB_GLOBAL_FLUSH (((u64)1) << 60)
+#define DMA_TLB_DSI_FLUSH (((u64)2) << 60)
+#define DMA_TLB_PSI_FLUSH (((u64)3) << 60)
+#define DMA_TLB_IIRG(type) ((type >> 60) & 7)
+#define DMA_TLB_IAIG(val) (((val) >> 57) & 7)
+#define DMA_TLB_READ_DRAIN (((u64)1) << 49)
+#define DMA_TLB_WRITE_DRAIN (((u64)1) << 48)
+#define DMA_TLB_DID(id) (((u64)((id) & 0xffff)) << 32)
+#define DMA_TLB_IVT (((u64)1) << 63)
+#define DMA_TLB_IH_NONLEAF (((u64)1) << 6)
+#define DMA_TLB_MAX_SIZE (0x3f)
+
+/* GCMD_REG */
+#define DMA_GCMD_TE (((u32)1) << 31)
+#define DMA_GCMD_SRTP (((u32)1) << 30)
+#define DMA_GCMD_SFL (((u32)1) << 29)
+#define DMA_GCMD_EAFL (((u32)1) << 28)
+#define DMA_GCMD_WBF (((u32)1) << 27)
+
+/* GSTS_REG */
+#define DMA_GSTS_TES (((u32)1) << 31)
+#define DMA_GSTS_RTPS (((u32)1) << 30)
+#define DMA_GSTS_FLS (((u32)1) << 29)
+#define DMA_GSTS_AFLS (((u32)1) << 28)
+#define DMA_GSTS_WBFS (((u32)1) << 27)
+
+/* CCMD_REG */
+#define DMA_CCMD_ICC (((u64)1) << 63)
+#define DMA_CCMD_GLOBAL_INVL (((u64)1) << 61)
+#define DMA_CCMD_DOMAIN_INVL (((u64)2) << 61)
+#define DMA_CCMD_DEVICE_INVL (((u64)3) << 61)
+#define DMA_CCMD_FM(m) (((u64)((m) & 0x3)) << 32)
+#define DMA_CCMD_MASK_NOBIT 0
+#define DMA_CCMD_MASK_1BIT 1
+#define DMA_CCMD_MASK_2BIT 2
+#define DMA_CCMD_MASK_3BIT 3
+#define DMA_CCMD_SID(s) (((u64)((s) & 0xffff)) << 16)
+#define DMA_CCMD_DID(d) ((u64)((d) & 0xffff))
+
+/* FECTL_REG */
+#define DMA_FECTL_IM (((u32)1) << 31)
+
+/* FSTS_REG */
+#define DMA_FSTS_PPF ((u32)2)
+#define DMA_FSTS_PFO ((u32)1)
+#define dma_fsts_fault_record_index(s) (((s) >> 8) & 0xff)
+
+/* FRCD_REG, 32 bits access */
+#define DMA_FRCD_F (((u32)1) << 31)
+#define dma_frcd_type(d) ((d >> 30) & 1)
+#define dma_frcd_fault_reason(c) (c & 0xff)
+#define dma_frcd_source_id(c) (c & 0xffff)
+#define dma_frcd_page_addr(d) (d & (((u64)-1) << 12)) /* low 64 bit */
+
+/*
+ * 0: Present
+ * 1-11: Reserved
+ * 12-63: Context Ptr (12 - (haw-1))
+ * 64-127: Reserved
+ */
+struct root_entry {
+ u64 val;
+ u64 rsvd1;
+};
+#define ROOT_ENTRY_NR (PAGE_SIZE_4K/sizeof(struct root_entry))
+static inline bool root_present(struct root_entry *root)
+{
+ return (root->val & 1);
+}
+static inline void set_root_present(struct root_entry *root)
+{
+ root->val |= 1;
+}
+static inline void set_root_value(struct root_entry *root, unsigned long value)
+{
+ root->val |= value & PAGE_MASK_4K;
+}
+
+struct context_entry;
+static inline struct context_entry *
+get_context_addr_from_root(struct root_entry *root)
+{
+ return (struct context_entry *)
+ (root_present(root)?phys_to_virt(
+ root->val & PAGE_MASK_4K):
+ NULL);
+}
+
+/*
+ * low 64 bits:
+ * 0: present
+ * 1: fault processing disable
+ * 2-3: translation type
+ * 12-63: address space root
+ * high 64 bits:
+ * 0-2: address width
+ * 3-6: aval
+ * 8-23: domain id
+ */
+struct context_entry {
+ u64 lo;
+ u64 hi;
+};
+#define context_present(c) ((c).lo & 1)
+#define context_fault_disable(c) (((c).lo >> 1) & 1)
+#define context_translation_type(c) (((c).lo >> 2) & 3)
+#define context_address_root(c) ((c).lo & PAGE_MASK_4K)
+#define context_address_width(c) ((c).hi & 7)
+#define context_domain_id(c) (((c).hi >> 8) & ((1 << 16) - 1))
+
+#define context_set_present(c) do {(c).lo |= 1;} while (0)
+#define context_set_fault_enable(c) \
+ do {(c).lo &= (((u64)-1) << 2) | 1;} while (0)
+#define context_set_translation_type(c, val) \
+ do { \
+ (c).lo &= (((u64)-1) << 4) | 3; \
+ (c).lo |= ((val) & 3) << 2; \
+ } while (0)
+#define CONTEXT_TT_MULTI_LEVEL 0
+#define context_set_address_root(c, val) \
+ do {(c).lo |= (val) & PAGE_MASK_4K;} while (0)
+#define context_set_address_width(c, val) do {(c).hi |= (val) & 7;} while (0)
+#define context_set_domain_id(c, val) \
+ do {(c).hi |= ((val) & ((1 << 16) - 1)) << 8;} while (0)
+#define context_clear_entry(c) do {(c).lo = 0; (c).hi = 0;} while (0)
+
+/*
+ * 0: readable
+ * 1: writable
+ * 2-6: reserved
+ * 7: super page
+ * 8-11: available
+ * 12-63: Host physcial address
+ */
+struct dma_pte {
+ u64 val;
+};
+#define dma_clear_pte(p) do {(p).val = 0;} while (0)
+
+#define DMA_PTE_READ (1)
+#define DMA_PTE_WRITE (2)
+
+#define dma_set_pte_readable(p) do {(p).val |= DMA_PTE_READ;} while (0)
+#define dma_set_pte_writable(p) do {(p).val |= DMA_PTE_WRITE;} while (0)
+#define dma_set_pte_prot(p, prot) \
+ do {(p).val = ((p).val & ~3) | ((prot) & 3); } while (0)
+#define dma_pte_addr(p) ((p).val & PAGE_MASK_4K)
+#define dma_set_pte_addr(p, addr) do {\
+ (p).val |= ((addr) & PAGE_MASK_4K); } while (0)
+#define dma_pte_present(p) (((p).val & 3) != 0)
+
+struct intel_iommu;
+
+struct dmar_domain {
+ int id; /* domain id */
+ struct intel_iommu *iommu; /* back pointer to owning iommu */
+
+ struct list_head devices; /* all devices' list */
+ struct iova_domain iovad; /* iova's that belong to this domain */
+
+ struct dma_pte *pgd; /* virtual address */
+ spinlock_t mapping_lock; /* page table lock */
+ int gaw; /* max guest address width */
+
+ /* adjusted guest address width, 0 is level 2 30-bit */
+ int agaw;
+
+#define DOMAIN_FLAG_MULTIPLE_DEVICES 1
+ int flags;
+};
+
+/* PCI domain-device relationship */
+struct device_domain_info {
+ struct list_head link; /* link to domain siblings */
+ struct list_head global; /* link to global list */
+ u8 bus; /* PCI bus numer */
+ u8 devfn; /* PCI devfn number */
+ struct pci_dev *dev; /* it's NULL for PCIE-to-PCI bridge */
+ struct dmar_domain *domain; /* pointer to domain */
+};
+
+extern int init_dmars(void);
+
+struct intel_iommu {
+ void __iomem *reg; /* Pointer to hardware regs, virtual addr */
+ u64 cap;
+ u64 ecap;
+ unsigned long *domain_ids; /* bitmap of domains */
+ struct dmar_domain **domains; /* ptr to domains */
+ int seg;
+ u32 gcmd; /* Holds TE, EAFL. Don't need SRTP, SFL, WBF */
+ spinlock_t lock; /* protect context, domain ids */
+ spinlock_t register_lock; /* protect register handling */
+ struct root_entry *root_entry; /* virtual address */
+
+ unsigned int irq;
+ unsigned char name[7]; /* Device Name */
+ struct msi_msg saved_msg;
+ struct sys_device sysdev;
+};
+
+#ifndef CONFIG_DMAR_GFX_WA
+static inline void iommu_prepare_gfx_mapping(void)
+{
+ return;
+}
+#endif /* !CONFIG_DMAR_GFX_WA */
+
+#endif
diff --git a/drivers/pci/iova.c b/drivers/pci/iova.c
new file mode 100644
index 000000000000..a84571c29360
--- /dev/null
+++ b/drivers/pci/iova.c
@@ -0,0 +1,394 @@
+/*
+ * Copyright (c) 2006, Intel Corporation.
+ *
+ * This file is released under the GPLv2.
+ *
+ * Copyright (C) 2006 Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
+ */
+
+#include "iova.h"
+
+void
+init_iova_domain(struct iova_domain *iovad)
+{
+ spin_lock_init(&iovad->iova_alloc_lock);
+ spin_lock_init(&iovad->iova_rbtree_lock);
+ iovad->rbroot = RB_ROOT;
+ iovad->cached32_node = NULL;
+
+}
+
+static struct rb_node *
+__get_cached_rbnode(struct iova_domain *iovad, unsigned long *limit_pfn)
+{
+ if ((*limit_pfn != DMA_32BIT_PFN) ||
+ (iovad->cached32_node == NULL))
+ return rb_last(&iovad->rbroot);
+ else {
+ struct rb_node *prev_node = rb_prev(iovad->cached32_node);
+ struct iova *curr_iova =
+ container_of(iovad->cached32_node, struct iova, node);
+ *limit_pfn = curr_iova->pfn_lo - 1;
+ return prev_node;
+ }
+}
+
+static void
+__cached_rbnode_insert_update(struct iova_domain *iovad,
+ unsigned long limit_pfn, struct iova *new)
+{
+ if (limit_pfn != DMA_32BIT_PFN)
+ return;
+ iovad->cached32_node = &new->node;
+}
+
+static void
+__cached_rbnode_delete_update(struct iova_domain *iovad, struct iova *free)
+{
+ struct iova *cached_iova;
+ struct rb_node *curr;
+
+ if (!iovad->cached32_node)
+ return;
+ curr = iovad->cached32_node;
+ cached_iova = container_of(curr, struct iova, node);
+
+ if (free->pfn_lo >= cached_iova->pfn_lo)
+ iovad->cached32_node = rb_next(&free->node);
+}
+
+/* Computes the padding size required, to make the
+ * the start address naturally aligned on its size
+ */
+static int
+iova_get_pad_size(int size, unsigned int limit_pfn)
+{
+ unsigned int pad_size = 0;
+ unsigned int order = ilog2(size);
+
+ if (order)
+ pad_size = (limit_pfn + 1) % (1 << order);
+
+ return pad_size;
+}
+
+static int __alloc_iova_range(struct iova_domain *iovad, unsigned long size,
+ unsigned long limit_pfn, struct iova *new, bool size_aligned)
+{
+ struct rb_node *curr = NULL;
+ unsigned long flags;
+ unsigned long saved_pfn;
+ unsigned int pad_size = 0;
+
+ /* Walk the tree backwards */
+ spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
+ saved_pfn = limit_pfn;
+ curr = __get_cached_rbnode(iovad, &limit_pfn);
+ while (curr) {
+ struct iova *curr_iova = container_of(curr, struct iova, node);
+ if (limit_pfn < curr_iova->pfn_lo)
+ goto move_left;
+ else if (limit_pfn < curr_iova->pfn_hi)
+ goto adjust_limit_pfn;
+ else {
+ if (size_aligned)
+ pad_size = iova_get_pad_size(size, limit_pfn);
+ if ((curr_iova->pfn_hi + size + pad_size) <= limit_pfn)
+ break; /* found a free slot */
+ }
+adjust_limit_pfn:
+ limit_pfn = curr_iova->pfn_lo - 1;
+move_left:
+ curr = rb_prev(curr);
+ }
+
+ if (!curr) {
+ if (size_aligned)
+ pad_size = iova_get_pad_size(size, limit_pfn);
+ if ((IOVA_START_PFN + size + pad_size) > limit_pfn) {
+ spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
+ return -ENOMEM;
+ }
+ }
+
+ /* pfn_lo will point to size aligned address if size_aligned is set */
+ new->pfn_lo = limit_pfn - (size + pad_size) + 1;
+ new->pfn_hi = new->pfn_lo + size - 1;
+
+ spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
+ return 0;
+}
+
+static void
+iova_insert_rbtree(struct rb_root *root, struct iova *iova)
+{
+ struct rb_node **new = &(root->rb_node), *parent = NULL;
+ /* Figure out where to put new node */
+ while (*new) {
+ struct iova *this = container_of(*new, struct iova, node);
+ parent = *new;
+
+ if (iova->pfn_lo < this->pfn_lo)
+ new = &((*new)->rb_left);
+ else if (iova->pfn_lo > this->pfn_lo)
+ new = &((*new)->rb_right);
+ else
+ BUG(); /* this should not happen */
+ }
+ /* Add new node and rebalance tree. */
+ rb_link_node(&iova->node, parent, new);
+ rb_insert_color(&iova->node, root);
+}
+
+/**
+ * alloc_iova - allocates an iova
+ * @iovad - iova domain in question
+ * @size - size of page frames to allocate
+ * @limit_pfn - max limit address
+ * @size_aligned - set if size_aligned address range is required
+ * This function allocates an iova in the range limit_pfn to IOVA_START_PFN
+ * looking from limit_pfn instead from IOVA_START_PFN. If the size_aligned
+ * flag is set then the allocated address iova->pfn_lo will be naturally
+ * aligned on roundup_power_of_two(size).
+ */
+struct iova *
+alloc_iova(struct iova_domain *iovad, unsigned long size,
+ unsigned long limit_pfn,
+ bool size_aligned)
+{
+ unsigned long flags;
+ struct iova *new_iova;
+ int ret;
+
+ new_iova = alloc_iova_mem();
+ if (!new_iova)
+ return NULL;
+
+ /* If size aligned is set then round the size to
+ * to next power of two.
+ */
+ if (size_aligned)
+ size = __roundup_pow_of_two(size);
+
+ spin_lock_irqsave(&iovad->iova_alloc_lock, flags);
+ ret = __alloc_iova_range(iovad, size, limit_pfn, new_iova,
+ size_aligned);
+
+ if (ret) {
+ spin_unlock_irqrestore(&iovad->iova_alloc_lock, flags);
+ free_iova_mem(new_iova);
+ return NULL;
+ }
+
+ /* Insert the new_iova into domain rbtree by holding writer lock */
+ spin_lock(&iovad->iova_rbtree_lock);
+ iova_insert_rbtree(&iovad->rbroot, new_iova);
+ __cached_rbnode_insert_update(iovad, limit_pfn, new_iova);
+ spin_unlock(&iovad->iova_rbtree_lock);
+
+ spin_unlock_irqrestore(&iovad->iova_alloc_lock, flags);
+
+ return new_iova;
+}
+
+/**
+ * find_iova - find's an iova for a given pfn
+ * @iovad - iova domain in question.
+ * pfn - page frame number
+ * This function finds and returns an iova belonging to the
+ * given doamin which matches the given pfn.
+ */
+struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn)
+{
+ unsigned long flags;
+ struct rb_node *node;
+
+ /* Take the lock so that no other thread is manipulating the rbtree */
+ spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
+ node = iovad->rbroot.rb_node;
+ while (node) {
+ struct iova *iova = container_of(node, struct iova, node);
+
+ /* If pfn falls within iova's range, return iova */
+ if ((pfn >= iova->pfn_lo) && (pfn <= iova->pfn_hi)) {
+ spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
+ /* We are not holding the lock while this iova
+ * is referenced by the caller as the same thread
+ * which called this function also calls __free_iova()
+ * and it is by desing that only one thread can possibly
+ * reference a particular iova and hence no conflict.
+ */
+ return iova;
+ }
+
+ if (pfn < iova->pfn_lo)
+ node = node->rb_left;
+ else if (pfn > iova->pfn_lo)
+ node = node->rb_right;
+ }
+
+ spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
+ return NULL;
+}
+
+/**
+ * __free_iova - frees the given iova
+ * @iovad: iova domain in question.
+ * @iova: iova in question.
+ * Frees the given iova belonging to the giving domain
+ */
+void
+__free_iova(struct iova_domain *iovad, struct iova *iova)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
+ __cached_rbnode_delete_update(iovad, iova);
+ rb_erase(&iova->node, &iovad->rbroot);
+ spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
+ free_iova_mem(iova);
+}
+
+/**
+ * free_iova - finds and frees the iova for a given pfn
+ * @iovad: - iova domain in question.
+ * @pfn: - pfn that is allocated previously
+ * This functions finds an iova for a given pfn and then
+ * frees the iova from that domain.
+ */
+void
+free_iova(struct iova_domain *iovad, unsigned long pfn)
+{
+ struct iova *iova = find_iova(iovad, pfn);
+ if (iova)
+ __free_iova(iovad, iova);
+
+}
+
+/**
+ * put_iova_domain - destroys the iova doamin
+ * @iovad: - iova domain in question.
+ * All the iova's in that domain are destroyed.
+ */
+void put_iova_domain(struct iova_domain *iovad)
+{
+ struct rb_node *node;
+ unsigned long flags;
+
+ spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
+ node = rb_first(&iovad->rbroot);
+ while (node) {
+ struct iova *iova = container_of(node, struct iova, node);
+ rb_erase(node, &iovad->rbroot);
+ free_iova_mem(iova);
+ node = rb_first(&iovad->rbroot);
+ }
+ spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
+}
+
+static int
+__is_range_overlap(struct rb_node *node,
+ unsigned long pfn_lo, unsigned long pfn_hi)
+{
+ struct iova *iova = container_of(node, struct iova, node);
+
+ if ((pfn_lo <= iova->pfn_hi) && (pfn_hi >= iova->pfn_lo))
+ return 1;
+ return 0;
+}
+
+static struct iova *
+__insert_new_range(struct iova_domain *iovad,
+ unsigned long pfn_lo, unsigned long pfn_hi)
+{
+ struct iova *iova;
+
+ iova = alloc_iova_mem();
+ if (!iova)
+ return iova;
+
+ iova->pfn_hi = pfn_hi;
+ iova->pfn_lo = pfn_lo;
+ iova_insert_rbtree(&iovad->rbroot, iova);
+ return iova;
+}
+
+static void
+__adjust_overlap_range(struct iova *iova,
+ unsigned long *pfn_lo, unsigned long *pfn_hi)
+{
+ if (*pfn_lo < iova->pfn_lo)
+ iova->pfn_lo = *pfn_lo;
+ if (*pfn_hi > iova->pfn_hi)
+ *pfn_lo = iova->pfn_hi + 1;
+}
+
+/**
+ * reserve_iova - reserves an iova in the given range
+ * @iovad: - iova domain pointer
+ * @pfn_lo: - lower page frame address
+ * @pfn_hi:- higher pfn adderss
+ * This function allocates reserves the address range from pfn_lo to pfn_hi so
+ * that this address is not dished out as part of alloc_iova.
+ */
+struct iova *
+reserve_iova(struct iova_domain *iovad,
+ unsigned long pfn_lo, unsigned long pfn_hi)
+{
+ struct rb_node *node;
+ unsigned long flags;
+ struct iova *iova;
+ unsigned int overlap = 0;
+
+ spin_lock_irqsave(&iovad->iova_alloc_lock, flags);
+ spin_lock(&iovad->iova_rbtree_lock);
+ for (node = rb_first(&iovad->rbroot); node; node = rb_next(node)) {
+ if (__is_range_overlap(node, pfn_lo, pfn_hi)) {
+ iova = container_of(node, struct iova, node);
+ __adjust_overlap_range(iova, &pfn_lo, &pfn_hi);
+ if ((pfn_lo >= iova->pfn_lo) &&
+ (pfn_hi <= iova->pfn_hi))
+ goto finish;
+ overlap = 1;
+
+ } else if (overlap)
+ break;
+ }
+
+ /* We are here either becasue this is the first reserver node
+ * or need to insert remaining non overlap addr range
+ */
+ iova = __insert_new_range(iovad, pfn_lo, pfn_hi);
+finish:
+
+ spin_unlock(&iovad->iova_rbtree_lock);
+ spin_unlock_irqrestore(&iovad->iova_alloc_lock, flags);
+ return iova;
+}
+
+/**
+ * copy_reserved_iova - copies the reserved between domains
+ * @from: - source doamin from where to copy
+ * @to: - destination domin where to copy
+ * This function copies reserved iova's from one doamin to
+ * other.
+ */
+void
+copy_reserved_iova(struct iova_domain *from, struct iova_domain *to)
+{
+ unsigned long flags;
+ struct rb_node *node;
+
+ spin_lock_irqsave(&from->iova_alloc_lock, flags);
+ spin_lock(&from->iova_rbtree_lock);
+ for (node = rb_first(&from->rbroot); node; node = rb_next(node)) {
+ struct iova *iova = container_of(node, struct iova, node);
+ struct iova *new_iova;
+ new_iova = reserve_iova(to, iova->pfn_lo, iova->pfn_hi);
+ if (!new_iova)
+ printk(KERN_ERR "Reserve iova range %lx@%lx failed\n",
+ iova->pfn_lo, iova->pfn_lo);
+ }
+ spin_unlock(&from->iova_rbtree_lock);
+ spin_unlock_irqrestore(&from->iova_alloc_lock, flags);
+}
diff --git a/drivers/pci/iova.h b/drivers/pci/iova.h
new file mode 100644
index 000000000000..ae3028d5a941
--- /dev/null
+++ b/drivers/pci/iova.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2006, Intel Corporation.
+ *
+ * This file is released under the GPLv2.
+ *
+ * Copyright (C) 2006 Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
+ *
+ */
+
+#ifndef _IOVA_H_
+#define _IOVA_H_
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/rbtree.h>
+#include <linux/dma-mapping.h>
+
+/*
+ * We need a fixed PAGE_SIZE of 4K irrespective of
+ * arch PAGE_SIZE for IOMMU page tables.
+ */
+#define PAGE_SHIFT_4K (12)
+#define PAGE_SIZE_4K (1UL << PAGE_SHIFT_4K)
+#define PAGE_MASK_4K (((u64)-1) << PAGE_SHIFT_4K)
+#define PAGE_ALIGN_4K(addr) (((addr) + PAGE_SIZE_4K - 1) & PAGE_MASK_4K)
+
+/* IO virtual address start page frame number */
+#define IOVA_START_PFN (1)
+
+#define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT_4K)
+#define DMA_32BIT_PFN IOVA_PFN(DMA_32BIT_MASK)
+#define DMA_64BIT_PFN IOVA_PFN(DMA_64BIT_MASK)
+
+/* iova structure */
+struct iova {
+ struct rb_node node;
+ unsigned long pfn_hi; /* IOMMU dish out addr hi */
+ unsigned long pfn_lo; /* IOMMU dish out addr lo */
+};
+
+/* holds all the iova translations for a domain */
+struct iova_domain {
+ spinlock_t iova_alloc_lock;/* Lock to protect iova allocation */
+ spinlock_t iova_rbtree_lock; /* Lock to protect update of rbtree */
+ struct rb_root rbroot; /* iova domain rbtree root */
+ struct rb_node *cached32_node; /* Save last alloced node */
+};
+
+struct iova *alloc_iova_mem(void);
+void free_iova_mem(struct iova *iova);
+void free_iova(struct iova_domain *iovad, unsigned long pfn);
+void __free_iova(struct iova_domain *iovad, struct iova *iova);
+struct iova *alloc_iova(struct iova_domain *iovad, unsigned long size,
+ unsigned long limit_pfn,
+ bool size_aligned);
+struct iova *reserve_iova(struct iova_domain *iovad, unsigned long pfn_lo,
+ unsigned long pfn_hi);
+void copy_reserved_iova(struct iova_domain *from, struct iova_domain *to);
+void init_iova_domain(struct iova_domain *iovad);
+struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn);
+void put_iova_domain(struct iova_domain *iovad);
+
+#endif
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 87e01615053d..07c9f09c856d 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -224,6 +224,12 @@ static struct msi_desc* alloc_msi_entry(void)
return entry;
}
+static void pci_intx_for_msi(struct pci_dev *dev, int enable)
+{
+ if (!(dev->dev_flags & PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG))
+ pci_intx(dev, enable);
+}
+
#ifdef CONFIG_PM
static void __pci_restore_msi_state(struct pci_dev *dev)
{
@@ -237,7 +243,7 @@ static void __pci_restore_msi_state(struct pci_dev *dev)
entry = get_irq_msi(dev->irq);
pos = entry->msi_attrib.pos;
- pci_intx(dev, 0); /* disable intx */
+ pci_intx_for_msi(dev, 0);
msi_set_enable(dev, 0);
write_msi_msg(dev->irq, &entry->msg);
if (entry->msi_attrib.maskbit)
@@ -260,7 +266,7 @@ static void __pci_restore_msix_state(struct pci_dev *dev)
return;
/* route the table */
- pci_intx(dev, 0); /* disable intx */
+ pci_intx_for_msi(dev, 0);
msix_set_enable(dev, 0);
list_for_each_entry(entry, &dev->msi_list, list) {
@@ -343,7 +349,7 @@ static int msi_capability_init(struct pci_dev *dev)
}
/* Set MSI enabled bits */
- pci_intx(dev, 0); /* disable intx */
+ pci_intx_for_msi(dev, 0);
msi_set_enable(dev, 1);
dev->msi_enabled = 1;
@@ -433,7 +439,7 @@ static int msix_capability_init(struct pci_dev *dev,
i++;
}
/* Set MSI-X enabled bits */
- pci_intx(dev, 0); /* disable intx */
+ pci_intx_for_msi(dev, 0);
msix_set_enable(dev, 1);
dev->msix_enabled = 1;
@@ -528,7 +534,7 @@ void pci_disable_msi(struct pci_dev* dev)
return;
msi_set_enable(dev, 0);
- pci_intx(dev, 1); /* enable intx */
+ pci_intx_for_msi(dev, 1);
dev->msi_enabled = 0;
BUG_ON(list_empty(&dev->msi_list));
@@ -640,7 +646,7 @@ void pci_disable_msix(struct pci_dev* dev)
return;
msix_set_enable(dev, 0);
- pci_intx(dev, 1); /* enable intx */
+ pci_intx_for_msi(dev, 1);
dev->msix_enabled = 0;
msix_free_all_irqs(dev);
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 6e2760b6c20a..6d1a21611818 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -143,8 +143,8 @@ const struct pci_device_id *pci_match_id(const struct pci_device_id *ids,
* system is in its list of supported devices. Returns the matching
* pci_device_id structure or %NULL if there is no match.
*/
-const struct pci_device_id *pci_match_device(struct pci_driver *drv,
- struct pci_dev *dev)
+static const struct pci_device_id *pci_match_device(struct pci_driver *drv,
+ struct pci_dev *dev)
{
struct pci_dynid *dynid;
@@ -559,7 +559,6 @@ static int __init pci_driver_init(void)
postcore_initcall(pci_driver_init);
EXPORT_SYMBOL(pci_match_id);
-EXPORT_SYMBOL(pci_match_device);
EXPORT_SYMBOL(__pci_register_driver);
EXPORT_SYMBOL(pci_unregister_driver);
EXPORT_SYMBOL(pci_dev_driver);
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 6fda33de84e8..fc87e14b50de 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -90,3 +90,4 @@ pci_match_one_device(const struct pci_device_id *id, const struct pci_dev *dev)
return NULL;
}
+struct pci_dev *pci_find_upstream_pcie_bridge(struct pci_dev *pdev);
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 5db6b6690b59..463a5a9d583d 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -837,6 +837,19 @@ static void pci_release_dev(struct device *dev)
kfree(pci_dev);
}
+static void set_pcie_port_type(struct pci_dev *pdev)
+{
+ int pos;
+ u16 reg16;
+
+ pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+ if (!pos)
+ return;
+ pdev->is_pcie = 1;
+ pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, &reg16);
+ pdev->pcie_type = (reg16 & PCI_EXP_FLAGS_TYPE) >> 4;
+}
+
/**
* pci_cfg_space_size - get the configuration space size of the PCI device.
* @dev: PCI device
@@ -951,6 +964,7 @@ pci_scan_device(struct pci_bus *bus, int devfn)
dev->device = (l >> 16) & 0xffff;
dev->cfg_size = pci_cfg_space_size(dev);
dev->error_state = pci_channel_io_normal;
+ set_pcie_port_type(dev);
/* Assume 32-bit PCI; let 64-bit PCI cards (which are far rarer)
set this higher, assuming the system even supports it. */
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 59d4da2734c1..26cc4dcf4f0e 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -1230,7 +1230,7 @@ static void quirk_jmicron_ata(struct pci_dev *pdev)
case PCI_DEVICE_ID_JMICRON_JMB363:
/* Enable dual function mode, AHCI on fn 0, IDE fn1 */
/* Set the class codes correctly and then direct IDE 0 */
- conf1 |= 0x00C2A102; /* Set 1, 8, 13, 15, 17, 22, 23 */
+ conf1 |= 0x00C2A1B3; /* Set 0, 1, 4, 5, 7, 8, 13, 15, 17, 22, 23 */
break;
case PCI_DEVICE_ID_JMICRON_JMB368:
@@ -1621,12 +1621,8 @@ static void __init quirk_disable_all_msi(struct pci_dev *dev)
printk(KERN_WARNING "PCI: MSI quirk detected. MSI deactivated.\n");
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_GCNB_LE, quirk_disable_all_msi);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000_PCIX, quirk_disable_all_msi);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS400_200, quirk_disable_all_msi);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS480, quirk_disable_all_msi);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RD580, quirk_disable_all_msi);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RX790, quirk_disable_all_msi);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS690, quirk_disable_all_msi);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3351, quirk_disable_all_msi);
/* Disable MSI on chipsets that are known to not support it */
@@ -1678,6 +1674,9 @@ static void __devinit quirk_msi_ht_cap(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE,
quirk_msi_ht_cap);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS,
+ PCI_DEVICE_ID_SERVERWORKS_HT1000_PXB,
+ quirk_msi_ht_cap);
/* The nVidia CK804 chipset may have 2 HT MSI mappings.
* MSI are supported if the MSI capability set in any of these mappings.
@@ -1705,4 +1704,48 @@ static void __devinit quirk_nvidia_ck804_msi_ht_cap(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
quirk_nvidia_ck804_msi_ht_cap);
+
+static void __devinit quirk_msi_intx_disable_bug(struct pci_dev *dev)
+{
+ dev->dev_flags |= PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG;
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM,
+ PCI_DEVICE_ID_TIGON3_5780,
+ quirk_msi_intx_disable_bug);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM,
+ PCI_DEVICE_ID_TIGON3_5780S,
+ quirk_msi_intx_disable_bug);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM,
+ PCI_DEVICE_ID_TIGON3_5714,
+ quirk_msi_intx_disable_bug);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM,
+ PCI_DEVICE_ID_TIGON3_5714S,
+ quirk_msi_intx_disable_bug);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM,
+ PCI_DEVICE_ID_TIGON3_5715,
+ quirk_msi_intx_disable_bug);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM,
+ PCI_DEVICE_ID_TIGON3_5715S,
+ quirk_msi_intx_disable_bug);
+
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4390,
+ quirk_msi_intx_disable_bug);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4391,
+ quirk_msi_intx_disable_bug);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4392,
+ quirk_msi_intx_disable_bug);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4393,
+ quirk_msi_intx_disable_bug);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4394,
+ quirk_msi_intx_disable_bug);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4395,
+ quirk_msi_intx_disable_bug);
+
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4373,
+ quirk_msi_intx_disable_bug);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4374,
+ quirk_msi_intx_disable_bug);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4375,
+ quirk_msi_intx_disable_bug);
+
#endif /* CONFIG_PCI_MSI */
diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index c6e79d01ce3d..8541034021f0 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -14,6 +14,40 @@
#include "pci.h"
DECLARE_RWSEM(pci_bus_sem);
+/*
+ * find the upstream PCIE-to-PCI bridge of a PCI device
+ * if the device is PCIE, return NULL
+ * if the device isn't connected to a PCIE bridge (that is its parent is a
+ * legacy PCI bridge and the bridge is directly connected to bus 0), return its
+ * parent
+ */
+struct pci_dev *
+pci_find_upstream_pcie_bridge(struct pci_dev *pdev)
+{
+ struct pci_dev *tmp = NULL;
+
+ if (pdev->is_pcie)
+ return NULL;
+ while (1) {
+ if (!pdev->bus->self)
+ break;
+ pdev = pdev->bus->self;
+ /* a p2p bridge */
+ if (!pdev->is_pcie) {
+ tmp = pdev;
+ continue;
+ }
+ /* PCI device should connect to a PCIE bridge */
+ if (pdev->pcie_type != PCI_EXP_TYPE_PCI_BRIDGE) {
+ /* Busted hardware? */
+ WARN_ON_ONCE(1);
+ return NULL;
+ }
+ return pdev;
+ }
+
+ return tmp;
+}
static struct pci_bus *pci_do_find_bus(struct pci_bus *bus, unsigned char busnr)
{
@@ -79,6 +113,8 @@ pci_find_next_bus(const struct pci_bus *from)
return b;
}
+#ifdef CONFIG_PCI_LEGACY
+
/**
* pci_find_slot - locate PCI device from a given PCI slot
* @bus: number of PCI bus on which desired PCI device resides
@@ -103,6 +139,8 @@ pci_find_slot(unsigned int bus, unsigned int devfn)
return NULL;
}
+#endif /* CONFIG_PCI_LEGACY */
+
/**
* pci_get_slot - locate PCI device for a given PCI slot
* @bus: PCI bus on which desired PCI device resides
@@ -166,6 +204,7 @@ struct pci_dev * pci_get_bus_and_slot(unsigned int bus, unsigned int devfn)
return NULL;
}
+#ifdef CONFIG_PCI_LEGACY
/**
* pci_find_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id
* @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
@@ -244,6 +283,7 @@ pci_find_device(unsigned int vendor, unsigned int device, const struct pci_dev *
{
return pci_find_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from);
}
+#endif /* CONFIG_PCI_LEGACY */
/**
* pci_get_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id
@@ -434,8 +474,11 @@ int pci_dev_present(const struct pci_device_id *ids)
EXPORT_SYMBOL(pci_dev_present);
EXPORT_SYMBOL(pci_find_present);
+#ifdef CONFIG_PCI_LEGACY
EXPORT_SYMBOL(pci_find_device);
EXPORT_SYMBOL(pci_find_slot);
+#endif /* CONFIG_PCI_LEGACY */
+
/* For boot time work */
EXPORT_SYMBOL(pci_find_bus);
EXPORT_SYMBOL(pci_find_next_bus);
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index c0c77f82d051..519b4ff79f7f 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -2,9 +2,7 @@
# PCCARD (PCMCIA/CardBus) bus subsystem configuration
#
-menu "PCCARD (PCMCIA/CardBus) support"
-
-config PCCARD
+menuconfig PCCARD
tristate "PCCard (PCMCIA/CardBus) support"
depends on HOTPLUG
---help---
@@ -271,6 +269,13 @@ config AT91_CF
Say Y here to support the CompactFlash controller on AT91 chips.
Or choose M to compile the driver as a module named "at91_cf".
+config ELECTRA_CF
+ tristate "Electra CompactFlash Controller"
+ depends on PCMCIA && PPC_PASEMI
+ help
+ Say Y here to support the CompactFlash controller on the
+ PA Semi Electra eval board.
+
config PCCARD_NONSTATIC
tristate
@@ -278,5 +283,3 @@ config PCCARD_IODYN
bool
endif # PCCARD
-
-endmenu
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index 4276965517f2..6f6478ba7174 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_PCMCIA_VRC4171) += vrc4171_card.o
obj-$(CONFIG_PCMCIA_VRC4173) += vrc4173_cardu.o
obj-$(CONFIG_OMAP_CF) += omap_cf.o
obj-$(CONFIG_AT91_CF) += at91_cf.o
+obj-$(CONFIG_ELECTRA_CF) += electra_cf.o
sa11xx_core-y += soc_common.o sa11xx_base.o
pxa2xx_core-y += soc_common.o pxa2xx_base.o
@@ -69,4 +70,5 @@ sa1100_cs-$(CONFIG_SA1100_SIMPAD) += sa1100_simpad.o
pxa2xx_cs-$(CONFIG_ARCH_LUBBOCK) += pxa2xx_lubbock.o sa1111_generic.o
pxa2xx_cs-$(CONFIG_MACH_MAINSTONE) += pxa2xx_mainstone.o
pxa2xx_cs-$(CONFIG_PXA_SHARPSL) += pxa2xx_sharpsl.o
+pxa2xx_cs-$(CONFIG_MACH_ARMCORE) += pxa2xx_cm_x270.o
diff --git a/drivers/pcmcia/au1000_xxs1500.c b/drivers/pcmcia/au1000_xxs1500.c
index 01874b0bb03b..ce9d5c44a7b5 100644
--- a/drivers/pcmcia/au1000_xxs1500.c
+++ b/drivers/pcmcia/au1000_xxs1500.c
@@ -50,7 +50,10 @@
#include <asm/au1000.h>
#include <asm/au1000_pcmcia.h>
-#include <asm/xxs1500.h>
+
+#define PCMCIA_MAX_SOCK 0
+#define PCMCIA_NUM_SOCKS (PCMCIA_MAX_SOCK + 1)
+#define PCMCIA_IRQ AU1000_GPIO_4
#if 0
#define DEBUG(x,args...) printk(__FUNCTION__ ": " x,##args)
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index d154dee76e7f..06a85d7d5aa2 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -25,6 +25,7 @@
#include <linux/ioport.h>
#include <asm/io.h>
#include <asm/byteorder.h>
+#include <asm/unaligned.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/ss.h>
@@ -401,6 +402,15 @@ EXPORT_SYMBOL(pcmcia_replace_cis);
======================================================================*/
+static inline u16 cis_get_u16(void *ptr)
+{
+ return le16_to_cpu(get_unaligned((__le16 *) ptr));
+}
+static inline u32 cis_get_u32(void *ptr)
+{
+ return le32_to_cpu(get_unaligned((__le32 *) ptr));
+}
+
typedef struct tuple_flags {
u_int link_space:4;
u_int has_link:1;
@@ -461,7 +471,7 @@ static int follow_link(struct pcmcia_socket *s, tuple_t *tuple)
/* Get indirect link from the MFC tuple */
read_cis_cache(s, LINK_SPACE(tuple->Flags),
tuple->LinkOffset, 5, link);
- ofs = le32_to_cpu(*(__le32 *)(link+1));
+ ofs = cis_get_u32(link + 1);
SPACE(tuple->Flags) = (link[0] == CISTPL_MFC_ATTR);
/* Move to the next indirect link */
tuple->LinkOffset += 5;
@@ -668,10 +678,10 @@ static int parse_checksum(tuple_t *tuple, cistpl_checksum_t *csum)
u_char *p;
if (tuple->TupleDataLen < 5)
return CS_BAD_TUPLE;
- p = (u_char *)tuple->TupleData;
- csum->addr = tuple->CISOffset+(short)le16_to_cpu(*(__le16 *)p)-2;
- csum->len = le16_to_cpu(*(__le16 *)(p + 2));
- csum->sum = *(p+4);
+ p = (u_char *) tuple->TupleData;
+ csum->addr = tuple->CISOffset + cis_get_u16(p) - 2;
+ csum->len = cis_get_u16(p + 2);
+ csum->sum = *(p + 4);
return CS_SUCCESS;
}
@@ -681,7 +691,7 @@ static int parse_longlink(tuple_t *tuple, cistpl_longlink_t *link)
{
if (tuple->TupleDataLen < 4)
return CS_BAD_TUPLE;
- link->addr = le32_to_cpu(*(__le32 *)tuple->TupleData);
+ link->addr = cis_get_u32(tuple->TupleData);
return CS_SUCCESS;
}
@@ -700,7 +710,8 @@ static int parse_longlink_mfc(tuple_t *tuple,
return CS_BAD_TUPLE;
for (i = 0; i < link->nfn; i++) {
link->fn[i].space = *p; p++;
- link->fn[i].addr = le32_to_cpu(*(__le32 *)p); p += 4;
+ link->fn[i].addr = cis_get_u32(p);
+ p += 4;
}
return CS_SUCCESS;
}
@@ -787,12 +798,10 @@ static int parse_jedec(tuple_t *tuple, cistpl_jedec_t *jedec)
static int parse_manfid(tuple_t *tuple, cistpl_manfid_t *m)
{
- __le16 *p;
if (tuple->TupleDataLen < 4)
return CS_BAD_TUPLE;
- p = (__le16 *)tuple->TupleData;
- m->manf = le16_to_cpu(p[0]);
- m->card = le16_to_cpu(p[1]);
+ m->manf = cis_get_u16(tuple->TupleData);
+ m->card = cis_get_u16(tuple->TupleData + 2);
return CS_SUCCESS;
}
@@ -1091,7 +1100,7 @@ static int parse_cftable_entry(tuple_t *tuple,
break;
case 0x20:
entry->mem.nwin = 1;
- entry->mem.win[0].len = le16_to_cpu(*(__le16 *)p) << 8;
+ entry->mem.win[0].len = cis_get_u16(p) << 8;
entry->mem.win[0].card_addr = 0;
entry->mem.win[0].host_addr = 0;
p += 2;
@@ -1099,9 +1108,8 @@ static int parse_cftable_entry(tuple_t *tuple,
break;
case 0x40:
entry->mem.nwin = 1;
- entry->mem.win[0].len = le16_to_cpu(*(__le16 *)p) << 8;
- entry->mem.win[0].card_addr =
- le16_to_cpu(*(__le16 *)(p+2)) << 8;
+ entry->mem.win[0].len = cis_get_u16(p) << 8;
+ entry->mem.win[0].card_addr = cis_get_u16(p + 2) << 8;
entry->mem.win[0].host_addr = 0;
p += 4;
if (p > q) return CS_BAD_TUPLE;
@@ -1138,7 +1146,7 @@ static int parse_bar(tuple_t *tuple, cistpl_bar_t *bar)
p = (u_char *)tuple->TupleData;
bar->attr = *p;
p += 2;
- bar->size = le32_to_cpu(*(__le32 *)p);
+ bar->size = cis_get_u32(p);
return CS_SUCCESS;
}
@@ -1151,7 +1159,7 @@ static int parse_config_cb(tuple_t *tuple, cistpl_config_t *config)
return CS_BAD_TUPLE;
config->last_idx = *(++p);
p++;
- config->base = le32_to_cpu(*(__le32 *)p);
+ config->base = cis_get_u32(p);
config->subtuples = tuple->TupleDataLen - 6;
return CS_SUCCESS;
}
@@ -1267,7 +1275,7 @@ static int parse_vers_2(tuple_t *tuple, cistpl_vers_2_t *v2)
v2->vers = p[0];
v2->comply = p[1];
- v2->dindex = le16_to_cpu(*(__le16 *)(p+2));
+ v2->dindex = cis_get_u16(p +2 );
v2->vspec8 = p[6];
v2->vspec9 = p[7];
v2->nhdr = p[8];
@@ -1308,8 +1316,8 @@ static int parse_format(tuple_t *tuple, cistpl_format_t *fmt)
fmt->type = p[0];
fmt->edc = p[1];
- fmt->offset = le32_to_cpu(*(__le32 *)(p+2));
- fmt->length = le32_to_cpu(*(__le32 *)(p+6));
+ fmt->offset = cis_get_u32(p + 2);
+ fmt->length = cis_get_u32(p + 6);
return CS_SUCCESS;
}
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 55baa1f0fcbb..7bf78c127898 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -23,6 +23,7 @@
#include <linux/crc32.h>
#include <linux/firmware.h>
#include <linux/kref.h>
+#include <linux/dma-mapping.h>
#define IN_CARD_SERVICES
#include <pcmcia/cs_types.h>
@@ -670,6 +671,9 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
p_dev->dev.bus = &pcmcia_bus_type;
p_dev->dev.parent = s->dev.parent;
p_dev->dev.release = pcmcia_release_dev;
+ /* by default don't allow DMA */
+ p_dev->dma_mask = DMA_MASK_NONE;
+ p_dev->dev.dma_mask = &p_dev->dma_mask;
bus_id_len = sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no);
p_dev->devname = kmalloc(6 + bus_id_len + 1, GFP_KERNEL);
diff --git a/drivers/pcmcia/electra_cf.c b/drivers/pcmcia/electra_cf.c
new file mode 100644
index 000000000000..0a6cea1316b4
--- /dev/null
+++ b/drivers/pcmcia/electra_cf.c
@@ -0,0 +1,377 @@
+/*
+ * Copyright (C) 2007 PA Semi, Inc
+ *
+ * Maintained by: Olof Johansson <olof@lixom.net>
+ *
+ * Based on drivers/pcmcia/omap_cf.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+
+#include <pcmcia/ss.h>
+#include <asm/of_platform.h>
+
+static const char driver_name[] = "electra-cf";
+
+struct electra_cf_socket {
+ struct pcmcia_socket socket;
+
+ struct timer_list timer;
+ unsigned present:1;
+ unsigned active:1;
+
+ struct of_device *ofdev;
+ unsigned long mem_phys;
+ void __iomem * mem_base;
+ unsigned long mem_size;
+ void __iomem * io_virt;
+ unsigned int io_base;
+ unsigned int io_size;
+ u_int irq;
+ struct resource iomem;
+ void __iomem * gpio_base;
+ int gpio_detect;
+ int gpio_vsense;
+ int gpio_3v;
+ int gpio_5v;
+};
+
+#define POLL_INTERVAL (2 * HZ)
+
+
+static int electra_cf_present(struct electra_cf_socket *cf)
+{
+ unsigned int gpio;
+
+ gpio = in_le32(cf->gpio_base+0x40);
+ return !(gpio & (1 << cf->gpio_detect));
+}
+
+static int electra_cf_ss_init(struct pcmcia_socket *s)
+{
+ return 0;
+}
+
+/* the timer is primarily to kick this socket's pccardd */
+static void electra_cf_timer(unsigned long _cf)
+{
+ struct electra_cf_socket *cf = (void *) _cf;
+ int present = electra_cf_present(cf);
+
+ if (present != cf->present) {
+ cf->present = present;
+ pcmcia_parse_events(&cf->socket, SS_DETECT);
+ }
+
+ if (cf->active)
+ mod_timer(&cf->timer, jiffies + POLL_INTERVAL);
+}
+
+static irqreturn_t electra_cf_irq(int irq, void *_cf)
+{
+ electra_cf_timer((unsigned long)_cf);
+ return IRQ_HANDLED;
+}
+
+static int electra_cf_get_status(struct pcmcia_socket *s, u_int *sp)
+{
+ struct electra_cf_socket *cf;
+
+ if (!sp)
+ return -EINVAL;
+
+ cf = container_of(s, struct electra_cf_socket, socket);
+
+ /* NOTE CF is always 3VCARD */
+ if (electra_cf_present(cf)) {
+ *sp = SS_READY | SS_DETECT | SS_POWERON | SS_3VCARD;
+
+ s->pci_irq = cf->irq;
+ } else
+ *sp = 0;
+ return 0;
+}
+
+static int electra_cf_set_socket(struct pcmcia_socket *sock,
+ struct socket_state_t *s)
+{
+ unsigned int gpio;
+ unsigned int vcc;
+ struct electra_cf_socket *cf;
+
+ cf = container_of(sock, struct electra_cf_socket, socket);
+
+ /* "reset" means no power in our case */
+ vcc = (s->flags & SS_RESET) ? 0 : s->Vcc;
+
+ switch (vcc) {
+ case 0:
+ gpio = 0;
+ break;
+ case 33:
+ gpio = (1 << cf->gpio_3v);
+ break;
+ case 5:
+ gpio = (1 << cf->gpio_5v);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ gpio |= 1 << (cf->gpio_3v + 16); /* enwr */
+ gpio |= 1 << (cf->gpio_5v + 16); /* enwr */
+ out_le32(cf->gpio_base+0x90, gpio);
+
+ pr_debug("%s: Vcc %d, io_irq %d, flags %04x csc %04x\n",
+ driver_name, s->Vcc, s->io_irq, s->flags, s->csc_mask);
+
+ return 0;
+}
+
+static int electra_cf_set_io_map(struct pcmcia_socket *s,
+ struct pccard_io_map *io)
+{
+ return 0;
+}
+
+static int electra_cf_set_mem_map(struct pcmcia_socket *s,
+ struct pccard_mem_map *map)
+{
+ struct electra_cf_socket *cf;
+
+ if (map->card_start)
+ return -EINVAL;
+ cf = container_of(s, struct electra_cf_socket, socket);
+ map->static_start = cf->mem_phys;
+ map->flags &= MAP_ACTIVE|MAP_ATTRIB;
+ if (!(map->flags & MAP_ATTRIB))
+ map->static_start += 0x800;
+ return 0;
+}
+
+static struct pccard_operations electra_cf_ops = {
+ .init = electra_cf_ss_init,
+ .get_status = electra_cf_get_status,
+ .set_socket = electra_cf_set_socket,
+ .set_io_map = electra_cf_set_io_map,
+ .set_mem_map = electra_cf_set_mem_map,
+};
+
+static int __devinit electra_cf_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
+{
+ struct device *device = &ofdev->dev;
+ struct device_node *np = ofdev->node;
+ struct electra_cf_socket *cf;
+ struct resource mem, io;
+ int status;
+ const unsigned int *prop;
+ int err;
+ struct vm_struct *area;
+
+ err = of_address_to_resource(np, 0, &mem);
+ if (err)
+ return -EINVAL;
+
+ err = of_address_to_resource(np, 1, &io);
+ if (err)
+ return -EINVAL;
+
+ cf = kzalloc(sizeof *cf, GFP_KERNEL);
+ if (!cf)
+ return -ENOMEM;
+
+ setup_timer(&cf->timer, electra_cf_timer, (unsigned long)cf);
+ cf->irq = NO_IRQ;
+
+ cf->ofdev = ofdev;
+ cf->mem_phys = mem.start;
+ cf->mem_size = PAGE_ALIGN(mem.end - mem.start);
+ cf->mem_base = ioremap(cf->mem_phys, cf->mem_size);
+ cf->io_size = PAGE_ALIGN(io.end - io.start);
+
+ area = __get_vm_area(cf->io_size, 0, PHB_IO_BASE, PHB_IO_END);
+ if (area == NULL)
+ return -ENOMEM;
+
+ cf->io_virt = (void __iomem *)(area->addr);
+
+ cf->gpio_base = ioremap(0xfc103000, 0x1000);
+ dev_set_drvdata(device, cf);
+
+ if (!cf->mem_base || !cf->io_virt || !cf->gpio_base ||
+ (__ioremap_at(io.start, cf->io_virt, cf->io_size,
+ _PAGE_NO_CACHE | _PAGE_GUARDED) == NULL)) {
+ dev_err(device, "can't ioremap ranges\n");
+ status = -ENOMEM;
+ goto fail1;
+ }
+
+
+ cf->io_base = (unsigned long)cf->io_virt - VMALLOC_END;
+
+ cf->iomem.start = (unsigned long)cf->mem_base;
+ cf->iomem.end = (unsigned long)cf->mem_base + (mem.end - mem.start);
+ cf->iomem.flags = IORESOURCE_MEM;
+
+ cf->irq = irq_of_parse_and_map(np, 0);
+
+ status = request_irq(cf->irq, electra_cf_irq, IRQF_SHARED,
+ driver_name, cf);
+ if (status < 0) {
+ dev_err(device, "request_irq failed\n");
+ goto fail1;
+ }
+
+ cf->socket.pci_irq = cf->irq;
+
+ prop = of_get_property(np, "card-detect-gpio", NULL);
+ if (!prop)
+ goto fail1;
+ cf->gpio_detect = *prop;
+
+ prop = of_get_property(np, "card-vsense-gpio", NULL);
+ if (!prop)
+ goto fail1;
+ cf->gpio_vsense = *prop;
+
+ prop = of_get_property(np, "card-3v-gpio", NULL);
+ if (!prop)
+ goto fail1;
+ cf->gpio_3v = *prop;
+
+ prop = of_get_property(np, "card-5v-gpio", NULL);
+ if (!prop)
+ goto fail1;
+ cf->gpio_5v = *prop;
+
+ cf->socket.io_offset = cf->io_base;
+
+ /* reserve chip-select regions */
+ if (!request_mem_region(cf->mem_phys, cf->mem_size, driver_name)) {
+ status = -ENXIO;
+ dev_err(device, "Can't claim memory region\n");
+ goto fail1;
+ }
+
+ if (!request_region(cf->io_base, cf->io_size, driver_name)) {
+ status = -ENXIO;
+ dev_err(device, "Can't claim I/O region\n");
+ goto fail2;
+ }
+
+ cf->socket.owner = THIS_MODULE;
+ cf->socket.dev.parent = &ofdev->dev;
+ cf->socket.ops = &electra_cf_ops;
+ cf->socket.resource_ops = &pccard_static_ops;
+ cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP |
+ SS_CAP_MEM_ALIGN;
+ cf->socket.map_size = 0x800;
+
+ status = pcmcia_register_socket(&cf->socket);
+ if (status < 0) {
+ dev_err(device, "pcmcia_register_socket failed\n");
+ goto fail3;
+ }
+
+ dev_info(device, "at mem 0x%lx io 0x%lx irq %d\n",
+ cf->mem_phys, io.start, cf->irq);
+
+ cf->active = 1;
+ electra_cf_timer((unsigned long)cf);
+ return 0;
+
+fail3:
+ release_region(cf->io_base, cf->io_size);
+fail2:
+ release_mem_region(cf->mem_phys, cf->mem_size);
+fail1:
+ if (cf->irq != NO_IRQ)
+ free_irq(cf->irq, cf);
+
+ if (cf->io_virt)
+ __iounmap_at(cf->io_virt, cf->io_size);
+ if (cf->mem_base)
+ iounmap(cf->mem_base);
+ if (cf->gpio_base)
+ iounmap(cf->gpio_base);
+ device_init_wakeup(&ofdev->dev, 0);
+ kfree(cf);
+ return status;
+
+}
+
+static int __devexit electra_cf_remove(struct of_device *ofdev)
+{
+ struct device *device = &ofdev->dev;
+ struct electra_cf_socket *cf;
+
+ cf = dev_get_drvdata(device);
+
+ cf->active = 0;
+ pcmcia_unregister_socket(&cf->socket);
+ free_irq(cf->irq, cf);
+ del_timer_sync(&cf->timer);
+
+ __iounmap_at(cf->io_virt, cf->io_size);
+ iounmap(cf->mem_base);
+ iounmap(cf->gpio_base);
+ release_mem_region(cf->mem_phys, cf->mem_size);
+ release_region(cf->io_base, cf->io_size);
+
+ kfree(cf);
+
+ return 0;
+}
+
+static struct of_device_id electra_cf_match[] = {
+ {
+ .compatible = "electra-cf",
+ },
+ {},
+};
+
+static struct of_platform_driver electra_cf_driver = {
+ .name = (char *)driver_name,
+ .match_table = electra_cf_match,
+ .probe = electra_cf_probe,
+ .remove = electra_cf_remove,
+};
+
+static int __init electra_cf_init(void)
+{
+ return of_register_platform_driver(&electra_cf_driver);
+}
+module_init(electra_cf_init);
+
+static void __exit electra_cf_exit(void)
+{
+ of_unregister_platform_driver(&electra_cf_driver);
+}
+module_exit(electra_cf_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>");
+MODULE_DESCRIPTION("PA Semi Electra CF driver");
diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c
index 67d28ee80f22..c5e0d89c3ece 100644
--- a/drivers/pcmcia/m32r_pcc.c
+++ b/drivers/pcmcia/m32r_pcc.c
@@ -22,9 +22,9 @@
#include <linux/workqueue.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
+#include <linux/bitops.h>
#include <asm/irq.h>
#include <asm/io.h>
-#include <asm/bitops.h>
#include <asm/system.h>
#include <asm/addrspace.h>
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c
index b01985498460..d182760f035b 100644
--- a/drivers/pcmcia/m8xx_pcmcia.c
+++ b/drivers/pcmcia/m8xx_pcmcia.c
@@ -48,9 +48,9 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/fsl_devices.h>
+#include <linux/bitops.h>
#include <asm/io.h>
-#include <asm/bitops.h>
#include <asm/system.h>
#include <asm/time.h>
#include <asm/mpc8xx.h>
diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c
index dca9f8549b32..874923fcb2f9 100644
--- a/drivers/pcmcia/pxa2xx_base.c
+++ b/drivers/pcmcia/pxa2xx_base.c
@@ -58,7 +58,7 @@ static inline u_int pxa2xx_mcxx_asst(u_int pcmcia_cycle_ns,
u_int mem_clk_10khz)
{
u_int code = pcmcia_cycle_ns * mem_clk_10khz;
- return (code / 300000) + ((code % 300000) ? 1 : 0) - 1;
+ return (code / 300000) + ((code % 300000) ? 1 : 0) + 1;
}
static inline u_int pxa2xx_mcxx_setup(u_int pcmcia_cycle_ns,
diff --git a/drivers/pcmcia/pxa2xx_cm_x270.c b/drivers/pcmcia/pxa2xx_cm_x270.c
new file mode 100644
index 000000000000..fbf2f3a6984c
--- /dev/null
+++ b/drivers/pcmcia/pxa2xx_cm_x270.c
@@ -0,0 +1,175 @@
+/*
+ * linux/drivers/pcmcia/pxa/pxa_cm_x270.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Compulab Ltd., 2003, 2007
+ * Mike Rapoport <mike@compulab.co.il>
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+
+#include <pcmcia/ss.h>
+#include <asm/hardware.h>
+
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/cm-x270.h>
+
+#include "soc_common.h"
+
+static struct pcmcia_irqs irqs[] = {
+ { 0, PCMCIA_S0_CD_VALID, "PCMCIA0 CD" },
+ { 1, PCMCIA_S1_CD_VALID, "PCMCIA1 CD" },
+};
+
+static int cmx270_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
+{
+ GPSR(GPIO48_nPOE) = GPIO_bit(GPIO48_nPOE) |
+ GPIO_bit(GPIO49_nPWE) |
+ GPIO_bit(GPIO50_nPIOR) |
+ GPIO_bit(GPIO51_nPIOW) |
+ GPIO_bit(GPIO85_nPCE_1) |
+ GPIO_bit(GPIO54_nPCE_2);
+
+ pxa_gpio_mode(GPIO48_nPOE_MD);
+ pxa_gpio_mode(GPIO49_nPWE_MD);
+ pxa_gpio_mode(GPIO50_nPIOR_MD);
+ pxa_gpio_mode(GPIO51_nPIOW_MD);
+ pxa_gpio_mode(GPIO85_nPCE_1_MD);
+ pxa_gpio_mode(GPIO54_nPCE_2_MD);
+ pxa_gpio_mode(GPIO55_nPREG_MD);
+ pxa_gpio_mode(GPIO56_nPWAIT_MD);
+ pxa_gpio_mode(GPIO57_nIOIS16_MD);
+
+ /* Reset signal */
+ pxa_gpio_mode(GPIO53_nPCE_2 | GPIO_OUT);
+ GPCR(GPIO53_nPCE_2) = GPIO_bit(GPIO53_nPCE_2);
+
+ set_irq_type(PCMCIA_S0_CD_VALID, IRQ_TYPE_EDGE_BOTH);
+ set_irq_type(PCMCIA_S1_CD_VALID, IRQ_TYPE_EDGE_BOTH);
+
+ /* irq's for slots: */
+ set_irq_type(PCMCIA_S0_RDYINT, IRQ_TYPE_EDGE_FALLING);
+ set_irq_type(PCMCIA_S1_RDYINT, IRQ_TYPE_EDGE_FALLING);
+
+ skt->irq = (skt->nr == 0) ? PCMCIA_S0_RDYINT : PCMCIA_S1_RDYINT;
+ return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
+}
+
+static void cmx270_pcmcia_shutdown(struct soc_pcmcia_socket *skt)
+{
+ soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
+
+ set_irq_type(IRQ_TO_GPIO(PCMCIA_S0_CD_VALID), IRQ_TYPE_NONE);
+ set_irq_type(IRQ_TO_GPIO(PCMCIA_S1_CD_VALID), IRQ_TYPE_NONE);
+
+ set_irq_type(IRQ_TO_GPIO(PCMCIA_S0_RDYINT), IRQ_TYPE_NONE);
+ set_irq_type(IRQ_TO_GPIO(PCMCIA_S1_RDYINT), IRQ_TYPE_NONE);
+}
+
+
+static void cmx270_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
+ struct pcmcia_state *state)
+{
+ state->detect = (PCC_DETECT(skt->nr) == 0) ? 1 : 0;
+ state->ready = (PCC_READY(skt->nr) == 0) ? 0 : 1;
+ state->bvd1 = 1;
+ state->bvd2 = 1;
+ state->vs_3v = 0;
+ state->vs_Xv = 0;
+ state->wrprot = 0; /* not available */
+}
+
+
+static int cmx270_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
+ const socket_state_t *state)
+{
+ GPSR(GPIO49_nPWE) = GPIO_bit(GPIO49_nPWE);
+ pxa_gpio_mode(GPIO49_nPWE | GPIO_OUT);
+
+ switch (skt->nr) {
+ case 0:
+ if (state->flags & SS_RESET) {
+ GPCR(GPIO49_nPWE) = GPIO_bit(GPIO49_nPWE);
+ GPSR(GPIO53_nPCE_2) = GPIO_bit(GPIO53_nPCE_2);
+ udelay(10);
+ GPCR(GPIO53_nPCE_2) = GPIO_bit(GPIO53_nPCE_2);
+ GPSR(GPIO49_nPWE) = GPIO_bit(GPIO49_nPWE);
+ }
+ break;
+ case 1:
+ if (state->flags & SS_RESET) {
+ GPCR(GPIO49_nPWE) = GPIO_bit(GPIO49_nPWE);
+ GPSR(GPIO53_nPCE_2) = GPIO_bit(GPIO53_nPCE_2);
+ udelay(10);
+ GPCR(GPIO53_nPCE_2) = GPIO_bit(GPIO53_nPCE_2);
+ GPSR(GPIO49_nPWE) = GPIO_bit(GPIO49_nPWE);
+ }
+ break;
+ }
+
+ pxa_gpio_mode(GPIO49_nPWE_MD);
+
+ return 0;
+}
+
+static void cmx270_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
+{
+}
+
+static void cmx270_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
+{
+}
+
+
+static struct pcmcia_low_level cmx270_pcmcia_ops = {
+ .owner = THIS_MODULE,
+ .hw_init = cmx270_pcmcia_hw_init,
+ .hw_shutdown = cmx270_pcmcia_shutdown,
+ .socket_state = cmx270_pcmcia_socket_state,
+ .configure_socket = cmx270_pcmcia_configure_socket,
+ .socket_init = cmx270_pcmcia_socket_init,
+ .socket_suspend = cmx270_pcmcia_socket_suspend,
+ .nr = 2,
+};
+
+static struct platform_device *cmx270_pcmcia_device;
+
+static int __init cmx270_pcmcia_init(void)
+{
+ int ret;
+
+ cmx270_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
+
+ if (!cmx270_pcmcia_device)
+ return -ENOMEM;
+
+ cmx270_pcmcia_device->dev.platform_data = &cmx270_pcmcia_ops;
+
+ printk(KERN_INFO "Registering cm-x270 PCMCIA interface.\n");
+ ret = platform_device_add(cmx270_pcmcia_device);
+
+ if (ret)
+ platform_device_put(cmx270_pcmcia_device);
+
+ return ret;
+}
+
+static void __exit cmx270_pcmcia_exit(void)
+{
+ platform_device_unregister(cmx270_pcmcia_device);
+}
+
+module_init(cmx270_pcmcia_init);
+module_exit(cmx270_pcmcia_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
+MODULE_DESCRIPTION("CM-x270 PCMCIA driver");
diff --git a/drivers/pcmcia/pxa2xx_lubbock.c b/drivers/pcmcia/pxa2xx_lubbock.c
index 5e9b9a3fd027..1510d6cde3e2 100644
--- a/drivers/pcmcia/pxa2xx_lubbock.c
+++ b/drivers/pcmcia/pxa2xx_lubbock.c
@@ -30,35 +30,6 @@
#include "sa1111_generic.h"
static int
-lubbock_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
-{
- /*
- * Setup default state of GPIO outputs
- * before we enable them as outputs.
- */
- GPSR(GPIO48_nPOE) =
- GPIO_bit(GPIO48_nPOE) |
- GPIO_bit(GPIO49_nPWE) |
- GPIO_bit(GPIO50_nPIOR) |
- GPIO_bit(GPIO51_nPIOW) |
- GPIO_bit(GPIO52_nPCE_1) |
- GPIO_bit(GPIO53_nPCE_2);
-
- pxa_gpio_mode(GPIO48_nPOE_MD);
- pxa_gpio_mode(GPIO49_nPWE_MD);
- pxa_gpio_mode(GPIO50_nPIOR_MD);
- pxa_gpio_mode(GPIO51_nPIOW_MD);
- pxa_gpio_mode(GPIO52_nPCE_1_MD);
- pxa_gpio_mode(GPIO53_nPCE_2_MD);
- pxa_gpio_mode(GPIO54_pSKTSEL_MD);
- pxa_gpio_mode(GPIO55_nPREG_MD);
- pxa_gpio_mode(GPIO56_nPWAIT_MD);
- pxa_gpio_mode(GPIO57_nIOIS16_MD);
-
- return sa1111_pcmcia_hw_init(skt);
-}
-
-static int
lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
const socket_state_t *state)
{
@@ -230,7 +201,7 @@ lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
static struct pcmcia_low_level lubbock_pcmcia_ops = {
.owner = THIS_MODULE,
- .hw_init = lubbock_pcmcia_hw_init,
+ .hw_init = sa1111_pcmcia_hw_init,
.hw_shutdown = sa1111_pcmcia_hw_shutdown,
.socket_state = sa1111_pcmcia_socket_state,
.configure_socket = lubbock_pcmcia_configure_socket,
diff --git a/drivers/pcmcia/pxa2xx_mainstone.c b/drivers/pcmcia/pxa2xx_mainstone.c
index f6722ba0dd1e..6fa5eaaab8af 100644
--- a/drivers/pcmcia/pxa2xx_mainstone.c
+++ b/drivers/pcmcia/pxa2xx_mainstone.c
@@ -43,24 +43,6 @@ static int mst_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
* Setup default state of GPIO outputs
* before we enable them as outputs.
*/
- GPSR(GPIO48_nPOE) =
- GPIO_bit(GPIO48_nPOE) |
- GPIO_bit(GPIO49_nPWE) |
- GPIO_bit(GPIO50_nPIOR) |
- GPIO_bit(GPIO51_nPIOW) |
- GPIO_bit(GPIO85_nPCE_1) |
- GPIO_bit(GPIO54_nPCE_2);
-
- pxa_gpio_mode(GPIO48_nPOE_MD);
- pxa_gpio_mode(GPIO49_nPWE_MD);
- pxa_gpio_mode(GPIO50_nPIOR_MD);
- pxa_gpio_mode(GPIO51_nPIOW_MD);
- pxa_gpio_mode(GPIO85_nPCE_1_MD);
- pxa_gpio_mode(GPIO54_nPCE_2_MD);
- pxa_gpio_mode(GPIO79_pSKTSEL_MD);
- pxa_gpio_mode(GPIO55_nPREG_MD);
- pxa_gpio_mode(GPIO56_nPWAIT_MD);
- pxa_gpio_mode(GPIO57_nIOIS16_MD);
skt->irq = (skt->nr == 0) ? MAINSTONE_S0_IRQ : MAINSTONE_S1_IRQ;
return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
diff --git a/drivers/pnp/Makefile b/drivers/pnp/Makefile
index a381a92fd1b6..26f5abc9c3f7 100644
--- a/drivers/pnp/Makefile
+++ b/drivers/pnp/Makefile
@@ -7,3 +7,7 @@ obj-y := core.o card.o driver.o resource.o manager.o support.o interface.o quir
obj-$(CONFIG_PNPACPI) += pnpacpi/
obj-$(CONFIG_PNPBIOS) += pnpbios/
obj-$(CONFIG_ISAPNP) += isapnp/
+
+ifeq ($(CONFIG_PNP_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c
index 6c0440c20e31..da1c9909eb44 100644
--- a/drivers/pnp/card.c
+++ b/drivers/pnp/card.c
@@ -104,10 +104,6 @@ int pnp_add_card_id(struct pnp_id *id, struct pnp_card *card)
{
struct pnp_id *ptr;
- if (!id)
- return -EINVAL;
- if (!card)
- return -EINVAL;
id->next = NULL;
ptr = card->id;
while (ptr && ptr->next)
@@ -124,8 +120,6 @@ static void pnp_free_card_ids(struct pnp_card *card)
struct pnp_id *id;
struct pnp_id *next;
- if (!card)
- return;
id = card->id;
while (id) {
next = id->next;
@@ -197,42 +191,39 @@ int pnp_add_card(struct pnp_card *card)
int error;
struct list_head *pos, *temp;
- if (!card || !card->protocol)
- return -EINVAL;
-
sprintf(card->dev.bus_id, "%02x:%02x", card->protocol->number,
card->number);
card->dev.parent = &card->protocol->dev;
card->dev.bus = NULL;
card->dev.release = &pnp_release_card;
error = device_register(&card->dev);
+ if (error) {
+ dev_err(&card->dev, "could not register (err=%d)\n", error);
+ return error;
+ }
- if (error == 0) {
- pnp_interface_attach_card(card);
- spin_lock(&pnp_lock);
- list_add_tail(&card->global_list, &pnp_cards);
- list_add_tail(&card->protocol_list, &card->protocol->cards);
- spin_unlock(&pnp_lock);
-
- /* we wait until now to add devices in order to ensure the drivers
- * will be able to use all of the related devices on the card
- * without waiting any unresonable length of time */
- list_for_each(pos, &card->devices) {
- struct pnp_dev *dev = card_to_pnp_dev(pos);
- __pnp_add_device(dev);
- }
+ pnp_interface_attach_card(card);
+ spin_lock(&pnp_lock);
+ list_add_tail(&card->global_list, &pnp_cards);
+ list_add_tail(&card->protocol_list, &card->protocol->cards);
+ spin_unlock(&pnp_lock);
- /* match with card drivers */
- list_for_each_safe(pos, temp, &pnp_card_drivers) {
- struct pnp_card_driver *drv =
- list_entry(pos, struct pnp_card_driver,
- global_list);
- card_probe(card, drv);
- }
- } else
- pnp_err("sysfs failure, card '%s' will be unavailable",
- card->dev.bus_id);
- return error;
+ /* we wait until now to add devices in order to ensure the drivers
+ * will be able to use all of the related devices on the card
+ * without waiting an unreasonable length of time */
+ list_for_each(pos, &card->devices) {
+ struct pnp_dev *dev = card_to_pnp_dev(pos);
+ __pnp_add_device(dev);
+ }
+
+ /* match with card drivers */
+ list_for_each_safe(pos, temp, &pnp_card_drivers) {
+ struct pnp_card_driver *drv =
+ list_entry(pos, struct pnp_card_driver,
+ global_list);
+ card_probe(card, drv);
+ }
+ return 0;
}
/**
@@ -243,8 +234,6 @@ void pnp_remove_card(struct pnp_card *card)
{
struct list_head *pos, *temp;
- if (!card)
- return;
device_unregister(&card->dev);
spin_lock(&pnp_lock);
list_del(&card->global_list);
@@ -263,8 +252,6 @@ void pnp_remove_card(struct pnp_card *card)
*/
int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev)
{
- if (!card || !dev || !dev->protocol)
- return -EINVAL;
dev->dev.parent = &card->dev;
dev->card_link = NULL;
snprintf(dev->dev.bus_id, BUS_ID_SIZE, "%02x:%02x.%02x",
@@ -304,14 +291,15 @@ struct pnp_dev *pnp_request_card_device(struct pnp_card_link *clink,
struct pnp_card *card;
if (!clink || !id)
- goto done;
+ return NULL;
+
card = clink->card;
drv = clink->driver;
if (!from) {
pos = card->devices.next;
} else {
if (from->card != card)
- goto done;
+ return NULL;
pos = from->card_list.next;
}
while (pos != &card->devices) {
@@ -321,7 +309,6 @@ struct pnp_dev *pnp_request_card_device(struct pnp_card_link *clink,
pos = pos->next;
}
-done:
return NULL;
found:
@@ -348,8 +335,6 @@ void pnp_release_card_device(struct pnp_dev *dev)
{
struct pnp_card_driver *drv = dev->card_link->driver;
- if (!drv)
- return;
drv->link.remove = &card_remove;
device_release_driver(&dev->dev);
drv->link.remove = &card_remove_first;
diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c
index d5964feb14de..7d366ca672d3 100644
--- a/drivers/pnp/core.c
+++ b/drivers/pnp/core.c
@@ -125,9 +125,11 @@ int __pnp_add_device(struct pnp_dev *dev)
spin_unlock(&pnp_lock);
ret = device_register(&dev->dev);
- if (ret == 0)
- pnp_interface_attach_device(dev);
- return ret;
+ if (ret)
+ return ret;
+
+ pnp_interface_attach_device(dev);
+ return 0;
}
/*
@@ -138,12 +140,30 @@ int __pnp_add_device(struct pnp_dev *dev)
*/
int pnp_add_device(struct pnp_dev *dev)
{
+ int ret;
+
if (dev->card)
return -EINVAL;
+
dev->dev.parent = &dev->protocol->dev;
sprintf(dev->dev.bus_id, "%02x:%02x", dev->protocol->number,
dev->number);
- return __pnp_add_device(dev);
+ ret = __pnp_add_device(dev);
+ if (ret)
+ return ret;
+
+#ifdef CONFIG_PNP_DEBUG
+ {
+ struct pnp_id *id;
+
+ dev_printk(KERN_DEBUG, &dev->dev, "%s device, IDs",
+ dev->protocol->name);
+ for (id = dev->id; id; id = id->next)
+ printk(" %s", id->id);
+ printk(" (%s)\n", dev->active ? "active" : "disabled");
+ }
+#endif
+ return 0;
}
void __pnp_remove_device(struct pnp_dev *dev)
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c
index 2fa64a6b25c8..a262762c5b88 100644
--- a/drivers/pnp/driver.c
+++ b/drivers/pnp/driver.c
@@ -86,9 +86,6 @@ static int pnp_device_probe(struct device *dev)
pnp_dev = to_pnp_dev(dev);
pnp_drv = to_pnp_driver(dev->driver);
- pnp_dbg("match found with the PnP device '%s' and the driver '%s'",
- dev->bus_id, pnp_drv->name);
-
error = pnp_device_attach(pnp_dev);
if (error < 0)
return error;
@@ -116,6 +113,8 @@ static int pnp_device_probe(struct device *dev)
error = 0;
} else
goto fail;
+
+ dev_dbg(dev, "driver attached\n");
return error;
fail:
diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c
index a0cfb75bbb8d..31548044fdde 100644
--- a/drivers/pnp/interface.c
+++ b/drivers/pnp/interface.c
@@ -1,7 +1,7 @@
/*
* interface.c - contains everything related to the user interface
*
- * Some code, especially possible resource dumping is based on isapnp_proc.c (c) Jaroslav Kysela <perex@suse.cz>
+ * Some code, especially possible resource dumping is based on isapnp_proc.c (c) Jaroslav Kysela <perex@perex.cz>
* Copyright 2002 Adam Belay <ambx1@neo.rr.com>
*/
@@ -327,8 +327,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
if (dev->status & PNP_ATTACHED) {
retval = -EBUSY;
- pnp_info("Device %s cannot be configured because it is in use.",
- dev->dev.bus_id);
+ dev_info(&dev->dev, "in use; can't configure\n");
goto done;
}
diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
index b035d60a1dcc..2c925b7cd93e 100644
--- a/drivers/pnp/isapnp/core.c
+++ b/drivers/pnp/isapnp/core.c
@@ -1,6 +1,6 @@
/*
* ISA Plug & Play support
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -53,7 +53,7 @@ static int isapnp_rdp; /* Read Data Port */
static int isapnp_reset = 1; /* reset all PnP cards (deactivate) */
static int isapnp_verbose = 1; /* verbose mode */
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Generic ISA Plug & Play support");
module_param(isapnp_disable, int, 0);
MODULE_PARM_DESC(isapnp_disable, "ISA Plug & Play disable");
diff --git a/drivers/pnp/isapnp/proc.c b/drivers/pnp/isapnp/proc.c
index 560ccb640816..2b8266c3d40f 100644
--- a/drivers/pnp/isapnp/proc.c
+++ b/drivers/pnp/isapnp/proc.c
@@ -1,6 +1,6 @@
/*
* ISA Plug & Play support
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
* 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
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c
index 0826287eef53..c6b3d4e63ccc 100644
--- a/drivers/pnp/manager.c
+++ b/drivers/pnp/manager.c
@@ -1,7 +1,7 @@
/*
* manager.c - Resource Management, Conflict Resolution, Activation and Disabling of Devices
*
- * based on isapnp.c resource management (c) Jaroslav Kysela <perex@suse.cz>
+ * based on isapnp.c resource management (c) Jaroslav Kysela <perex@perex.cz>
* Copyright 2003 Adam Belay <ambx1@neo.rr.com>
*/
@@ -22,8 +22,7 @@ static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx)
unsigned long *flags;
if (idx >= PNP_MAX_PORT) {
- pnp_err
- ("More than 4 ports is incompatible with pnp specifications.");
+ dev_err(&dev->dev, "too many I/O port resources\n");
/* pretend we were successful so at least the manager won't try again */
return 1;
}
@@ -64,8 +63,7 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
unsigned long *flags;
if (idx >= PNP_MAX_MEM) {
- pnp_err
- ("More than 8 mems is incompatible with pnp specifications.");
+ dev_err(&dev->dev, "too many memory resources\n");
/* pretend we were successful so at least the manager won't try again */
return 1;
}
@@ -122,8 +120,7 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
};
if (idx >= PNP_MAX_IRQ) {
- pnp_err
- ("More than 2 irqs is incompatible with pnp specifications.");
+ dev_err(&dev->dev, "too many IRQ resources\n");
/* pretend we were successful so at least the manager won't try again */
return 1;
}
@@ -161,7 +158,7 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
return 0;
}
-static int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
+static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
{
resource_size_t *start, *end;
unsigned long *flags;
@@ -173,15 +170,13 @@ static int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
};
if (idx >= PNP_MAX_DMA) {
- pnp_err
- ("More than 2 dmas is incompatible with pnp specifications.");
- /* pretend we were successful so at least the manager won't try again */
- return 1;
+ dev_err(&dev->dev, "too many DMA resources\n");
+ return;
}
/* check if this resource has been manually set, if so skip */
if (!(dev->res.dma_resource[idx].flags & IORESOURCE_AUTO))
- return 1;
+ return;
start = &dev->res.dma_resource[idx].start;
end = &dev->res.dma_resource[idx].end;
@@ -191,19 +186,17 @@ static int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
*flags |= rule->flags | IORESOURCE_DMA;
*flags &= ~IORESOURCE_UNSET;
- if (!rule->map) {
- *flags |= IORESOURCE_DISABLED;
- return 1; /* skip disabled resource requests */
- }
-
for (i = 0; i < 8; i++) {
if (rule->map & (1 << xtab[i])) {
*start = *end = xtab[i];
if (pnp_check_dma(dev, idx))
- return 1;
+ return;
}
}
- return 0;
+#ifdef MAX_DMA_CHANNELS
+ *start = *end = MAX_DMA_CHANNELS;
+#endif
+ *flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED;
}
/**
@@ -330,8 +323,7 @@ static int pnp_assign_resources(struct pnp_dev *dev, int depnum)
irq = irq->next;
}
while (dma) {
- if (!pnp_assign_dma(dev, dma, ndma))
- goto fail;
+ pnp_assign_dma(dev, dma, ndma);
ndma++;
dma = dma->next;
}
@@ -367,8 +359,7 @@ static int pnp_assign_resources(struct pnp_dev *dev, int depnum)
irq = irq->next;
}
while (dma) {
- if (!pnp_assign_dma(dev, dma, ndma))
- goto fail;
+ pnp_assign_dma(dev, dma, ndma);
ndma++;
dma = dma->next;
}
@@ -447,8 +438,7 @@ int pnp_auto_config_dev(struct pnp_dev *dev)
int i = 1;
if (!pnp_can_configure(dev)) {
- pnp_dbg("Device %s does not support resource configuration.",
- dev->dev.bus_id);
+ dev_dbg(&dev->dev, "configuration not supported\n");
return -ENODEV;
}
@@ -465,7 +455,7 @@ int pnp_auto_config_dev(struct pnp_dev *dev)
} while (dep);
}
- pnp_err("Unable to assign resources to device %s.", dev->dev.bus_id);
+ dev_err(&dev->dev, "unable to assign resources\n");
return -EBUSY;
}
@@ -478,17 +468,16 @@ int pnp_auto_config_dev(struct pnp_dev *dev)
int pnp_start_dev(struct pnp_dev *dev)
{
if (!pnp_can_write(dev)) {
- pnp_dbg("Device %s does not support activation.",
- dev->dev.bus_id);
+ dev_dbg(&dev->dev, "activation not supported\n");
return -EINVAL;
}
if (dev->protocol->set(dev, &dev->res) < 0) {
- pnp_err("Failed to activate device %s.", dev->dev.bus_id);
+ dev_err(&dev->dev, "activation failed\n");
return -EIO;
}
- pnp_info("Device %s activated.", dev->dev.bus_id);
+ dev_info(&dev->dev, "activated\n");
return 0;
}
@@ -501,16 +490,15 @@ int pnp_start_dev(struct pnp_dev *dev)
int pnp_stop_dev(struct pnp_dev *dev)
{
if (!pnp_can_disable(dev)) {
- pnp_dbg("Device %s does not support disabling.",
- dev->dev.bus_id);
+ dev_dbg(&dev->dev, "disabling not supported\n");
return -EINVAL;
}
if (dev->protocol->disable(dev) < 0) {
- pnp_err("Failed to disable device %s.", dev->dev.bus_id);
+ dev_err(&dev->dev, "disable failed\n");
return -EIO;
}
- pnp_info("Device %s disabled.", dev->dev.bus_id);
+ dev_info(&dev->dev, "disabled\n");
return 0;
}
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index a5a372222d69..dada89906314 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -130,11 +130,16 @@ static int pnpacpi_disable_resources(struct pnp_dev *dev)
#ifdef CONFIG_ACPI_SLEEP
static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state)
{
- return acpi_bus_set_power((acpi_handle) dev->data,
- acpi_pm_device_sleep_state(&dev->dev,
- device_may_wakeup
- (&dev->dev),
- NULL));
+ int power_state;
+
+ power_state = acpi_pm_device_sleep_state(&dev->dev,
+ device_may_wakeup(&dev->dev),
+ NULL);
+ if (power_state < 0)
+ power_state = (state.event == PM_EVENT_ON) ?
+ ACPI_STATE_D0 : ACPI_STATE_D3;
+
+ return acpi_bus_set_power((acpi_handle) dev->data, power_state);
}
static int pnpacpi_resume(struct pnp_dev *dev)
@@ -166,7 +171,6 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
is_exclusive_device(device))
return 0;
- pnp_dbg("ACPI device : hid %s", acpi_device_hid(device));
dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL);
if (!dev) {
pnp_err("Out of memory");
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 0e3b8d0ff06b..cd0a204d96d1 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -85,6 +85,16 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res,
if (i >= PNP_MAX_IRQ)
return;
+#ifdef CONFIG_X86
+ if (gsi < 16 && (triggering != ACPI_EDGE_SENSITIVE ||
+ polarity != ACPI_ACTIVE_HIGH)) {
+ pnp_warn("BIOS BUG: legacy PNP IRQ %d should be edge trigger, "
+ "active high", gsi);
+ triggering = ACPI_EDGE_SENSITIVE;
+ polarity = ACPI_ACTIVE_HIGH;
+ }
+#endif
+
res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag
res->irq_resource[i].flags |= irq_flags(triggering, polarity);
irq = acpi_register_gsi(gsi, triggering, polarity);
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
index 4e9fd37cff35..e33e03f71084 100644
--- a/drivers/pnp/pnpbios/core.c
+++ b/drivers/pnp/pnpbios/core.c
@@ -315,25 +315,31 @@ struct pnp_protocol pnpbios_protocol = {
.disable = pnpbios_disable_resources,
};
-static int insert_device(struct pnp_dev *dev, struct pnp_bios_node *node)
+static int insert_device(struct pnp_bios_node *node)
{
struct list_head *pos;
- struct pnp_dev *pnp_dev;
+ struct pnp_dev *dev;
struct pnp_id *dev_id;
char id[8];
/* check if the device is already added */
- dev->number = node->handle;
list_for_each(pos, &pnpbios_protocol.devices) {
- pnp_dev = list_entry(pos, struct pnp_dev, protocol_list);
- if (dev->number == pnp_dev->number)
+ dev = list_entry(pos, struct pnp_dev, protocol_list);
+ if (dev->number == node->handle)
return -1;
}
- /* set the initial values for the PnP device */
+ dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL);
+ if (!dev)
+ return -1;
+
dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
- if (!dev_id)
+ if (!dev_id) {
+ kfree(dev);
return -1;
+ }
+
+ dev->number = node->handle;
pnpid32_to_pnpid(node->eisa_id, id);
memcpy(dev_id->id, id, 7);
pnp_add_id(dev_id, dev);
@@ -367,7 +373,6 @@ static void __init build_devlist(void)
unsigned int nodes_got = 0;
unsigned int devs = 0;
struct pnp_bios_node *node;
- struct pnp_dev *dev;
node = kzalloc(node_info.max_node_size, GFP_KERNEL);
if (!node)
@@ -388,12 +393,7 @@ static void __init build_devlist(void)
break;
}
nodes_got++;
- dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL);
- if (!dev)
- break;
- if (insert_device(dev, node) < 0)
- kfree(dev);
- else
+ if (insert_device(node) == 0)
devs++;
if (nodenum <= thisnodenum) {
printk(KERN_ERR
diff --git a/drivers/pnp/pnpbios/proc.c b/drivers/pnp/pnpbios/proc.c
index 9d9841f24a85..bb19bc957bad 100644
--- a/drivers/pnp/pnpbios/proc.c
+++ b/drivers/pnp/pnpbios/proc.c
@@ -94,8 +94,9 @@ static int proc_read_escd(char *buf, char **start, off_t pos,
/* sanity check */
if (escd_size > MAX_SANE_ESCD_SIZE) {
- printk(KERN_ERR
- "PnPBIOS: proc_read_escd: ESCD size reported by BIOS read_escd call is too great\n");
+ printk(KERN_ERR "PnPBIOS: proc_read_escd: ESCD size reported by"
+ " BIOS read_escd call is too great\n");
+ kfree(tmpbuf);
return -EFBIG;
}
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c
index 6b0cf0c2a088..e903b8c2b1fa 100644
--- a/drivers/pnp/quirks.c
+++ b/drivers/pnp/quirks.c
@@ -17,6 +17,7 @@
#include <linux/slab.h>
#include <linux/pnp.h>
#include <linux/io.h>
+#include <linux/kallsyms.h>
#include "base.h"
static void quirk_awe32_resources(struct pnp_dev *dev)
@@ -133,11 +134,18 @@ static struct pnp_fixup pnp_fixups[] = {
void pnp_fixup_device(struct pnp_dev *dev)
{
int i = 0;
+ void (*quirk)(struct pnp_dev *);
while (*pnp_fixups[i].id) {
if (compare_pnp_id(dev->id, pnp_fixups[i].id)) {
- pnp_dbg("Calling quirk for %s", dev->dev.bus_id);
- pnp_fixups[i].quirk_function(dev);
+ quirk = pnp_fixups[i].quirk_function;
+
+#ifdef DEBUG
+ dev_dbg(&dev->dev, "calling quirk 0x%p", quirk);
+ print_fn_descriptor_symbol(": %s()\n",
+ (unsigned long) *quirk);
+#endif
+ (*quirk)(dev);
}
i++;
}
diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c
index ef1286900db3..41d73a5e9312 100644
--- a/drivers/pnp/resource.c
+++ b/drivers/pnp/resource.c
@@ -1,7 +1,7 @@
/*
* resource.c - Contains functions for registering and analyzing resource information
*
- * based on isapnp.c resource management (c) Jaroslav Kysela <perex@suse.cz>
+ * based on isapnp.c resource management (c) Jaroslav Kysela <perex@perex.cz>
* Copyright 2003 Adam Belay <ambx1@neo.rr.com>
*/
@@ -51,7 +51,7 @@ struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev)
/* this should never happen but if it does we'll try to continue */
if (dev->independent)
- pnp_err("independent resource already registered");
+ dev_err(&dev->dev, "independent resource already registered\n");
dev->independent = option;
return option;
}
diff --git a/drivers/pnp/system.c b/drivers/pnp/system.c
index a06f980b3ac9..55c4563986b3 100644
--- a/drivers/pnp/system.c
+++ b/drivers/pnp/system.c
@@ -22,36 +22,39 @@ static const struct pnp_device_id pnp_dev_table[] = {
{"", 0}
};
-static void reserve_range(const char *pnpid, resource_size_t start,
+static void reserve_range(struct pnp_dev *dev, resource_size_t start,
resource_size_t end, int port)
{
- struct resource *res;
char *regionid;
+ const char *pnpid = dev->dev.bus_id;
+ struct resource *res;
regionid = kmalloc(16, GFP_KERNEL);
- if (regionid == NULL)
+ if (!regionid)
return;
+
snprintf(regionid, 16, "pnp %s", pnpid);
if (port)
res = request_region(start, end - start + 1, regionid);
else
res = request_mem_region(start, end - start + 1, regionid);
- if (res == NULL)
- kfree(regionid);
- else
+ if (res)
res->flags &= ~IORESOURCE_BUSY;
+ else
+ kfree(regionid);
+
/*
* Failures at this point are usually harmless. pci quirks for
* example do reserve stuff they know about too, so we may well
* have double reservations.
*/
- printk(KERN_INFO "pnp: %s: %s range 0x%llx-0x%llx %s reserved\n",
- pnpid, port ? "ioport" : "iomem",
- (unsigned long long)start, (unsigned long long)end,
- NULL != res ? "has been" : "could not be");
+ dev_info(&dev->dev, "%s range 0x%llx-0x%llx %s reserved\n",
+ port ? "ioport" : "iomem",
+ (unsigned long long) start, (unsigned long long) end,
+ res ? "has been" : "could not be");
}
-static void reserve_resources_of_dev(const struct pnp_dev *dev)
+static void reserve_resources_of_dev(struct pnp_dev *dev)
{
int i;
@@ -73,7 +76,7 @@ static void reserve_resources_of_dev(const struct pnp_dev *dev)
if (pnp_port_end(dev, i) < pnp_port_start(dev, i))
continue; /* invalid */
- reserve_range(dev->dev.bus_id, pnp_port_start(dev, i),
+ reserve_range(dev, pnp_port_start(dev, i),
pnp_port_end(dev, i), 1);
}
@@ -81,7 +84,7 @@ static void reserve_resources_of_dev(const struct pnp_dev *dev)
if (!pnp_mem_valid(dev, i))
continue;
- reserve_range(dev->dev.bus_id, pnp_mem_start(dev, i),
+ reserve_range(dev, pnp_mem_start(dev, i),
pnp_mem_end(dev, i), 0);
}
}
diff --git a/drivers/power/apm_power.c b/drivers/power/apm_power.c
index 39a90a6f0f80..bbf3ee10da04 100644
--- a/drivers/power/apm_power.c
+++ b/drivers/power/apm_power.c
@@ -26,65 +26,124 @@ static struct power_supply *main_battery;
static void find_main_battery(void)
{
struct device *dev;
- struct power_supply *bat, *batm;
+ struct power_supply *bat = NULL;
+ struct power_supply *max_charge_bat = NULL;
+ struct power_supply *max_energy_bat = NULL;
union power_supply_propval full;
int max_charge = 0;
+ int max_energy = 0;
main_battery = NULL;
- batm = NULL;
+
list_for_each_entry(dev, &power_supply_class->devices, node) {
bat = dev_get_drvdata(dev);
- /* If none of battery devices cantains 'use_for_apm' flag,
- choice one with maximum design charge */
- if (!PSY_PROP(bat, CHARGE_FULL_DESIGN, &full)) {
+
+ if (bat->use_for_apm) {
+ /* nice, we explicitly asked to report this battery. */
+ main_battery = bat;
+ return;
+ }
+
+ if (!PSY_PROP(bat, CHARGE_FULL_DESIGN, &full) ||
+ !PSY_PROP(bat, CHARGE_FULL, &full)) {
if (full.intval > max_charge) {
- batm = bat;
+ max_charge_bat = bat;
max_charge = full.intval;
}
+ } else if (!PSY_PROP(bat, ENERGY_FULL_DESIGN, &full) ||
+ !PSY_PROP(bat, ENERGY_FULL, &full)) {
+ if (full.intval > max_energy) {
+ max_energy_bat = bat;
+ max_energy = full.intval;
+ }
}
+ }
- if (bat->use_for_apm)
- main_battery = bat;
+ if ((max_energy_bat && max_charge_bat) &&
+ (max_energy_bat != max_charge_bat)) {
+ /* try guess battery with more capacity */
+ if (!PSY_PROP(max_charge_bat, VOLTAGE_MAX_DESIGN, &full)) {
+ if (max_energy > max_charge * full.intval)
+ main_battery = max_energy_bat;
+ else
+ main_battery = max_charge_bat;
+ } else if (!PSY_PROP(max_energy_bat, VOLTAGE_MAX_DESIGN,
+ &full)) {
+ if (max_charge > max_energy / full.intval)
+ main_battery = max_charge_bat;
+ else
+ main_battery = max_energy_bat;
+ } else {
+ /* give up, choice any */
+ main_battery = max_energy_bat;
+ }
+ } else if (max_charge_bat) {
+ main_battery = max_charge_bat;
+ } else if (max_energy_bat) {
+ main_battery = max_energy_bat;
+ } else {
+ /* give up, try the last if any */
+ main_battery = bat;
}
- if (!main_battery)
- main_battery = batm;
}
-static int calculate_time(int status)
+static int calculate_time(int status, int using_charge)
{
- union power_supply_propval charge_full, charge_empty;
- union power_supply_propval charge, I;
+ union power_supply_propval full;
+ union power_supply_propval empty;
+ union power_supply_propval cur;
+ union power_supply_propval I;
+ enum power_supply_property full_prop;
+ enum power_supply_property full_design_prop;
+ enum power_supply_property empty_prop;
+ enum power_supply_property empty_design_prop;
+ enum power_supply_property cur_avg_prop;
+ enum power_supply_property cur_now_prop;
- if (MPSY_PROP(CHARGE_FULL, &charge_full)) {
- /* if battery can't report this property, use design value */
- if (MPSY_PROP(CHARGE_FULL_DESIGN, &charge_full))
+ if (MPSY_PROP(CURRENT_AVG, &I)) {
+ /* if battery can't report average value, use momentary */
+ if (MPSY_PROP(CURRENT_NOW, &I))
return -1;
}
- if (MPSY_PROP(CHARGE_EMPTY, &charge_empty)) {
- /* if battery can't report this property, use design value */
- if (MPSY_PROP(CHARGE_EMPTY_DESIGN, &charge_empty))
- charge_empty.intval = 0;
+ if (using_charge) {
+ full_prop = POWER_SUPPLY_PROP_CHARGE_FULL;
+ full_design_prop = POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN;
+ empty_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY;
+ empty_design_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY;
+ cur_avg_prop = POWER_SUPPLY_PROP_CHARGE_AVG;
+ cur_now_prop = POWER_SUPPLY_PROP_CHARGE_NOW;
+ } else {
+ full_prop = POWER_SUPPLY_PROP_ENERGY_FULL;
+ full_design_prop = POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN;
+ empty_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY;
+ empty_design_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY;
+ cur_avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG;
+ cur_now_prop = POWER_SUPPLY_PROP_ENERGY_NOW;
}
- if (MPSY_PROP(CHARGE_AVG, &charge)) {
- /* if battery can't report average value, use momentary */
- if (MPSY_PROP(CHARGE_NOW, &charge))
+ if (_MPSY_PROP(full_prop, &full)) {
+ /* if battery can't report this property, use design value */
+ if (_MPSY_PROP(full_design_prop, &full))
return -1;
}
- if (MPSY_PROP(CURRENT_AVG, &I)) {
+ if (_MPSY_PROP(empty_prop, &empty)) {
+ /* if battery can't report this property, use design value */
+ if (_MPSY_PROP(empty_design_prop, &empty))
+ empty.intval = 0;
+ }
+
+ if (_MPSY_PROP(cur_avg_prop, &cur)) {
/* if battery can't report average value, use momentary */
- if (MPSY_PROP(CURRENT_NOW, &I))
+ if (_MPSY_PROP(cur_now_prop, &cur))
return -1;
}
if (status == POWER_SUPPLY_STATUS_CHARGING)
- return ((charge.intval - charge_full.intval) * 60L) /
- I.intval;
+ return ((cur.intval - full.intval) * 60L) / I.intval;
else
- return -((charge.intval - charge_empty.intval) * 60L) /
- I.intval;
+ return -((cur.intval - empty.intval) * 60L) / I.intval;
}
static int calculate_capacity(int using_charge)
@@ -200,18 +259,22 @@ static void apm_battery_apm_get_power_status(struct apm_power_info *info)
info->units = APM_UNITS_MINS;
if (status.intval == POWER_SUPPLY_STATUS_CHARGING) {
- if (MPSY_PROP(TIME_TO_FULL_AVG, &time_to_full)) {
- if (MPSY_PROP(TIME_TO_FULL_NOW, &time_to_full))
- info->time = calculate_time(status.intval);
- else
- info->time = time_to_full.intval / 60;
+ if (!MPSY_PROP(TIME_TO_FULL_AVG, &time_to_full) ||
+ !MPSY_PROP(TIME_TO_FULL_NOW, &time_to_full)) {
+ info->time = time_to_full.intval / 60;
+ } else {
+ info->time = calculate_time(status.intval, 0);
+ if (info->time == -1)
+ info->time = calculate_time(status.intval, 1);
}
} else {
- if (MPSY_PROP(TIME_TO_EMPTY_AVG, &time_to_empty)) {
- if (MPSY_PROP(TIME_TO_EMPTY_NOW, &time_to_empty))
- info->time = calculate_time(status.intval);
- else
- info->time = time_to_empty.intval / 60;
+ if (!MPSY_PROP(TIME_TO_EMPTY_AVG, &time_to_empty) ||
+ !MPSY_PROP(TIME_TO_EMPTY_NOW, &time_to_empty)) {
+ info->time = time_to_empty.intval / 60;
+ } else {
+ info->time = calculate_time(status.intval, 0);
+ if (info->time == -1)
+ info->time = calculate_time(status.intval, 1);
}
}
diff --git a/drivers/power/ds2760_battery.c b/drivers/power/ds2760_battery.c
index be7021ee3611..bdb9b7285b3d 100644
--- a/drivers/power/ds2760_battery.c
+++ b/drivers/power/ds2760_battery.c
@@ -366,7 +366,7 @@ static int ds2760_battery_probe(struct platform_device *pdev)
retval = power_supply_register(&pdev->dev, &di->bat);
if (retval) {
- dev_err(di->dev, "failed to register battery");
+ dev_err(di->dev, "failed to register battery\n");
goto batt_failed;
}
diff --git a/drivers/ps3/ps3av.c b/drivers/ps3/ps3av.c
index 85e21614f868..87b3493d88e5 100644
--- a/drivers/ps3/ps3av.c
+++ b/drivers/ps3/ps3av.c
@@ -23,6 +23,7 @@
#include <linux/delay.h>
#include <linux/notifier.h>
#include <linux/ioctl.h>
+#include <linux/fb.h>
#include <asm/firmware.h>
#include <asm/ps3av.h>
@@ -33,6 +34,8 @@
#define BUFSIZE 4096 /* vuart buf size */
#define PS3AV_BUF_SIZE 512 /* max packet size */
+static int safe_mode;
+
static int timeout = 5000; /* in msec ( 5 sec ) */
module_param(timeout, int, 0644);
@@ -491,10 +494,10 @@ static int ps3av_set_videomode(void)
return 0;
}
-static void ps3av_set_videomode_cont(u32 id, u32 old_id)
+static void ps3av_set_videomode_packet(u32 id)
{
struct ps3av_pkt_avb_param avb_param;
- int i;
+ unsigned int i;
u32 len = 0, av_video_cs;
const struct avset_video_mode *video_mode;
int res;
@@ -507,24 +510,6 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id)
ps3av->av_hw_conf.num_of_avmulti;
avb_param.num_of_av_audio_pkt = 0;
- /* video signal off */
- ps3av_set_video_disable_sig();
-
- /* Retail PS3 product doesn't support this */
- if (id & PS3AV_MODE_HDCP_OFF) {
- res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_HDCP_OFF);
- if (res == PS3AV_STATUS_UNSUPPORTED_HDMI_MODE)
- dev_dbg(&ps3av->dev->core, "Not supported\n");
- else if (res)
- dev_dbg(&ps3av->dev->core,
- "ps3av_cmd_av_hdmi_mode failed\n");
- } else if (old_id & PS3AV_MODE_HDCP_OFF) {
- res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_MODE_NORMAL);
- if (res < 0 && res != PS3AV_STATUS_UNSUPPORTED_HDMI_MODE)
- dev_dbg(&ps3av->dev->core,
- "ps3av_cmd_av_hdmi_mode failed\n");
- }
-
/* video_pkt */
for (i = 0; i < avb_param.num_of_video_pkt; i++)
len += ps3av_cmd_set_video_mode(&avb_param.buf[len],
@@ -555,6 +540,42 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id)
__func__);
else if (res)
dev_dbg(&ps3av->dev->core, "ps3av_cmd_avb_param failed\n");
+}
+
+static void ps3av_set_videomode_cont(u32 id, u32 old_id)
+{
+ static int vesa = 0;
+ int res;
+
+ /* video signal off */
+ ps3av_set_video_disable_sig();
+
+ /*
+ * AV backend needs non-VESA mode setting at least one time
+ * when VESA mode is used.
+ */
+ if (vesa == 0 && (id & PS3AV_MODE_MASK) >= 11) {
+ /* vesa mode */
+ ps3av_set_videomode_packet(2); /* 480P */
+ }
+ vesa = 1;
+
+ /* Retail PS3 product doesn't support this */
+ if (id & PS3AV_MODE_HDCP_OFF) {
+ res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_HDCP_OFF);
+ if (res == PS3AV_STATUS_UNSUPPORTED_HDMI_MODE)
+ dev_dbg(&ps3av->dev->core, "Not supported\n");
+ else if (res)
+ dev_dbg(&ps3av->dev->core,
+ "ps3av_cmd_av_hdmi_mode failed\n");
+ } else if (old_id & PS3AV_MODE_HDCP_OFF) {
+ res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_MODE_NORMAL);
+ if (res < 0 && res != PS3AV_STATUS_UNSUPPORTED_HDMI_MODE)
+ dev_dbg(&ps3av->dev->core,
+ "ps3av_cmd_av_hdmi_mode failed\n");
+ }
+
+ ps3av_set_videomode_packet(id);
msleep(1500);
/* av video mute */
@@ -567,165 +588,247 @@ static void ps3avd(struct work_struct *work)
complete(&ps3av->done);
}
-static int ps3av_vid2table_id(int vid)
-{
- int i;
-
- for (i = 1; i < ARRAY_SIZE(video_mode_table); i++)
- if (video_mode_table[i].vid == vid)
- return i;
- return -1;
-}
+#define SHIFT_50 0
+#define SHIFT_60 4
+#define SHIFT_VESA 8
+
+static const struct {
+ unsigned mask : 19;
+ unsigned id : 4;
+} ps3av_preferred_modes[] = {
+ { .mask = PS3AV_RESBIT_WUXGA << SHIFT_VESA, .id = 13 },
+ { .mask = PS3AV_RESBIT_1920x1080P << SHIFT_60, .id = 5 },
+ { .mask = PS3AV_RESBIT_1920x1080P << SHIFT_50, .id = 10 },
+ { .mask = PS3AV_RESBIT_1920x1080I << SHIFT_60, .id = 4 },
+ { .mask = PS3AV_RESBIT_1920x1080I << SHIFT_50, .id = 9 },
+ { .mask = PS3AV_RESBIT_SXGA << SHIFT_VESA, .id = 12 },
+ { .mask = PS3AV_RESBIT_WXGA << SHIFT_VESA, .id = 11 },
+ { .mask = PS3AV_RESBIT_1280x720P << SHIFT_60, .id = 3 },
+ { .mask = PS3AV_RESBIT_1280x720P << SHIFT_50, .id = 8 },
+ { .mask = PS3AV_RESBIT_720x480P << SHIFT_60, .id = 2 },
+ { .mask = PS3AV_RESBIT_720x576P << SHIFT_50, .id = 7 },
+};
-static int ps3av_resbit2vid(u32 res_50, u32 res_60)
+static int ps3av_resbit2id(u32 res_50, u32 res_60, u32 res_vesa)
{
- int vid = -1;
+ unsigned int i;
+ u32 res_all;
+
+ /*
+ * We mask off the resolution bits we care about and combine the
+ * results in one bitfield, so make sure there's no overlap
+ */
+ BUILD_BUG_ON(PS3AV_RES_MASK_50 << SHIFT_50 &
+ PS3AV_RES_MASK_60 << SHIFT_60);
+ BUILD_BUG_ON(PS3AV_RES_MASK_50 << SHIFT_50 &
+ PS3AV_RES_MASK_VESA << SHIFT_VESA);
+ BUILD_BUG_ON(PS3AV_RES_MASK_60 << SHIFT_60 &
+ PS3AV_RES_MASK_VESA << SHIFT_VESA);
+ res_all = (res_50 & PS3AV_RES_MASK_50) << SHIFT_50 |
+ (res_60 & PS3AV_RES_MASK_60) << SHIFT_60 |
+ (res_vesa & PS3AV_RES_MASK_VESA) << SHIFT_VESA;
+
+ if (!res_all)
+ return 0;
+
+ for (i = 0; i < ARRAY_SIZE(ps3av_preferred_modes); i++)
+ if (res_all & ps3av_preferred_modes[i].mask)
+ return ps3av_preferred_modes[i].id;
- if (res_50 > res_60) { /* if res_50 == res_60, res_60 will be used */
- if (res_50 & PS3AV_RESBIT_1920x1080P)
- vid = PS3AV_CMD_VIDEO_VID_1080P_50HZ;
- else if (res_50 & PS3AV_RESBIT_1920x1080I)
- vid = PS3AV_CMD_VIDEO_VID_1080I_50HZ;
- else if (res_50 & PS3AV_RESBIT_1280x720P)
- vid = PS3AV_CMD_VIDEO_VID_720P_50HZ;
- else if (res_50 & PS3AV_RESBIT_720x576P)
- vid = PS3AV_CMD_VIDEO_VID_576P;
- else
- vid = -1;
- } else {
- if (res_60 & PS3AV_RESBIT_1920x1080P)
- vid = PS3AV_CMD_VIDEO_VID_1080P_60HZ;
- else if (res_60 & PS3AV_RESBIT_1920x1080I)
- vid = PS3AV_CMD_VIDEO_VID_1080I_60HZ;
- else if (res_60 & PS3AV_RESBIT_1280x720P)
- vid = PS3AV_CMD_VIDEO_VID_720P_60HZ;
- else if (res_60 & PS3AV_RESBIT_720x480P)
- vid = PS3AV_CMD_VIDEO_VID_480P;
- else
- vid = -1;
- }
- return vid;
+ return 0;
}
-static int ps3av_hdmi_get_vid(struct ps3av_info_monitor *info)
+static int ps3av_hdmi_get_id(struct ps3av_info_monitor *info)
{
- u32 res_50, res_60;
- int vid = -1;
+ int id;
- if (info->monitor_type != PS3AV_MONITOR_TYPE_HDMI)
- return -1;
+ if (safe_mode)
+ return PS3AV_DEFAULT_HDMI_MODE_ID_REG_60;
/* check native resolution */
- res_50 = info->res_50.native & PS3AV_RES_MASK_50;
- res_60 = info->res_60.native & PS3AV_RES_MASK_60;
- if (res_50 || res_60) {
- vid = ps3av_resbit2vid(res_50, res_60);
- return vid;
+ id = ps3av_resbit2id(info->res_50.native, info->res_60.native,
+ info->res_vesa.native);
+ if (id) {
+ pr_debug("%s: Using native mode %d\n", __func__, id);
+ return id;
}
- /* check resolution */
- res_50 = info->res_50.res_bits & PS3AV_RES_MASK_50;
- res_60 = info->res_60.res_bits & PS3AV_RES_MASK_60;
- if (res_50 || res_60) {
- vid = ps3av_resbit2vid(res_50, res_60);
- return vid;
+ /* check supported resolutions */
+ id = ps3av_resbit2id(info->res_50.res_bits, info->res_60.res_bits,
+ info->res_vesa.res_bits);
+ if (id) {
+ pr_debug("%s: Using supported mode %d\n", __func__, id);
+ return id;
}
if (ps3av->region & PS3AV_REGION_60)
- vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
+ id = PS3AV_DEFAULT_HDMI_MODE_ID_REG_60;
else
- vid = PS3AV_DEFAULT_HDMI_VID_REG_50;
- return vid;
+ id = PS3AV_DEFAULT_HDMI_MODE_ID_REG_50;
+ pr_debug("%s: Using default mode %d\n", __func__, id);
+ return id;
}
-static int ps3av_auto_videomode(struct ps3av_pkt_av_get_hw_conf *av_hw_conf,
- int boot)
+static void ps3av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info *monitor_info)
{
- int i, res, vid = -1, dvi = 0, rgb = 0;
+ const struct ps3av_info_monitor *info = &monitor_info->info;
+ const struct ps3av_info_audio *audio = info->audio;
+ char id[sizeof(info->monitor_id)*3+1];
+ int i;
+
+ pr_debug("Monitor Info: size %u\n", monitor_info->send_hdr.size);
+
+ pr_debug("avport: %02x\n", info->avport);
+ for (i = 0; i < sizeof(info->monitor_id); i++)
+ sprintf(&id[i*3], " %02x", info->monitor_id[i]);
+ pr_debug("monitor_id: %s\n", id);
+ pr_debug("monitor_type: %02x\n", info->monitor_type);
+ pr_debug("monitor_name: %.*s\n", (int)sizeof(info->monitor_name),
+ info->monitor_name);
+
+ /* resolution */
+ pr_debug("resolution_60: bits: %08x native: %08x\n",
+ info->res_60.res_bits, info->res_60.native);
+ pr_debug("resolution_50: bits: %08x native: %08x\n",
+ info->res_50.res_bits, info->res_50.native);
+ pr_debug("resolution_other: bits: %08x native: %08x\n",
+ info->res_other.res_bits, info->res_other.native);
+ pr_debug("resolution_vesa: bits: %08x native: %08x\n",
+ info->res_vesa.res_bits, info->res_vesa.native);
+
+ /* color space */
+ pr_debug("color space rgb: %02x\n", info->cs.rgb);
+ pr_debug("color space yuv444: %02x\n", info->cs.yuv444);
+ pr_debug("color space yuv422: %02x\n", info->cs.yuv422);
+
+ /* color info */
+ pr_debug("color info red: X %04x Y %04x\n", info->color.red_x,
+ info->color.red_y);
+ pr_debug("color info green: X %04x Y %04x\n", info->color.green_x,
+ info->color.green_y);
+ pr_debug("color info blue: X %04x Y %04x\n", info->color.blue_x,
+ info->color.blue_y);
+ pr_debug("color info white: X %04x Y %04x\n", info->color.white_x,
+ info->color.white_y);
+ pr_debug("color info gamma: %08x\n", info->color.gamma);
+
+ /* other info */
+ pr_debug("supported_AI: %02x\n", info->supported_ai);
+ pr_debug("speaker_info: %02x\n", info->speaker_info);
+ pr_debug("num of audio: %02x\n", info->num_of_audio_block);
+
+ /* audio block */
+ for (i = 0; i < info->num_of_audio_block; i++) {
+ pr_debug("audio[%d] type: %02x max_ch: %02x fs: %02x sbit: "
+ "%02x\n",
+ i, audio->type, audio->max_num_of_ch, audio->fs,
+ audio->sbit);
+ audio++;
+ }
+}
+
+static const struct ps3av_monitor_quirk {
+ const char *monitor_name;
+ u32 clear_60;
+} ps3av_monitor_quirks[] = {
+ {
+ .monitor_name = "DELL 2007WFP",
+ .clear_60 = PS3AV_RESBIT_1920x1080I
+ }, {
+ .monitor_name = "L226WTQ",
+ .clear_60 = PS3AV_RESBIT_1920x1080I |
+ PS3AV_RESBIT_1920x1080P
+ }, {
+ .monitor_name = "SyncMaster",
+ .clear_60 = PS3AV_RESBIT_1920x1080I
+ }
+};
+
+static void ps3av_fixup_monitor_info(struct ps3av_info_monitor *info)
+{
+ unsigned int i;
+ const struct ps3av_monitor_quirk *quirk;
+
+ for (i = 0; i < ARRAY_SIZE(ps3av_monitor_quirks); i++) {
+ quirk = &ps3av_monitor_quirks[i];
+ if (!strncmp(info->monitor_name, quirk->monitor_name,
+ sizeof(info->monitor_name))) {
+ pr_info("%s: Applying quirk for %s\n", __func__,
+ quirk->monitor_name);
+ info->res_60.res_bits &= ~quirk->clear_60;
+ info->res_60.native &= ~quirk->clear_60;
+ break;
+ }
+ }
+}
+
+static int ps3av_auto_videomode(struct ps3av_pkt_av_get_hw_conf *av_hw_conf)
+{
+ int i, res, id = 0, dvi = 0, rgb = 0;
struct ps3av_pkt_av_get_monitor_info monitor_info;
struct ps3av_info_monitor *info;
- /* get vid for hdmi */
- for (i = 0; i < av_hw_conf->num_of_hdmi; i++) {
+ /* get mode id for hdmi */
+ for (i = 0; i < av_hw_conf->num_of_hdmi && !id; i++) {
res = ps3av_cmd_video_get_monitor_info(&monitor_info,
PS3AV_CMD_AVPORT_HDMI_0 +
i);
if (res < 0)
return -1;
- ps3av_cmd_av_monitor_info_dump(&monitor_info);
+ ps3av_monitor_info_dump(&monitor_info);
+
info = &monitor_info.info;
- /* check DVI */
- if (info->monitor_type == PS3AV_MONITOR_TYPE_DVI) {
+ ps3av_fixup_monitor_info(info);
+
+ switch (info->monitor_type) {
+ case PS3AV_MONITOR_TYPE_DVI:
dvi = PS3AV_MODE_DVI;
- break;
- }
- /* check HDMI */
- vid = ps3av_hdmi_get_vid(info);
- if (vid != -1) {
- /* got valid vid */
+ /* fall through */
+ case PS3AV_MONITOR_TYPE_HDMI:
+ id = ps3av_hdmi_get_id(info);
break;
}
}
- if (dvi) {
- /* DVI mode */
- vid = PS3AV_DEFAULT_DVI_VID;
- } else if (vid == -1) {
+ if (!id) {
/* no HDMI interface or HDMI is off */
if (ps3av->region & PS3AV_REGION_60)
- vid = PS3AV_DEFAULT_AVMULTI_VID_REG_60;
+ id = PS3AV_DEFAULT_AVMULTI_MODE_ID_REG_60;
else
- vid = PS3AV_DEFAULT_AVMULTI_VID_REG_50;
+ id = PS3AV_DEFAULT_AVMULTI_MODE_ID_REG_50;
if (ps3av->region & PS3AV_REGION_RGB)
rgb = PS3AV_MODE_RGB;
- } else if (boot) {
- /* HDMI: using DEFAULT HDMI_VID while booting up */
- info = &monitor_info.info;
- if (ps3av->region & PS3AV_REGION_60) {
- if (info->res_60.res_bits & PS3AV_RESBIT_720x480P)
- vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
- else if (info->res_50.res_bits & PS3AV_RESBIT_720x576P)
- vid = PS3AV_DEFAULT_HDMI_VID_REG_50;
- else {
- /* default */
- vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
- }
- } else {
- if (info->res_50.res_bits & PS3AV_RESBIT_720x576P)
- vid = PS3AV_DEFAULT_HDMI_VID_REG_50;
- else if (info->res_60.res_bits & PS3AV_RESBIT_720x480P)
- vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
- else {
- /* default */
- vid = PS3AV_DEFAULT_HDMI_VID_REG_50;
- }
- }
+ pr_debug("%s: Using avmulti mode %d\n", __func__, id);
}
- return (ps3av_vid2table_id(vid) | dvi | rgb);
+ return id | dvi | rgb;
}
static int ps3av_get_hw_conf(struct ps3av *ps3av)
{
int i, j, k, res;
+ const struct ps3av_pkt_av_get_hw_conf *hw_conf;
/* get av_hw_conf */
res = ps3av_cmd_av_get_hw_conf(&ps3av->av_hw_conf);
if (res < 0)
return -1;
- ps3av_cmd_av_hw_conf_dump(&ps3av->av_hw_conf);
+ hw_conf = &ps3av->av_hw_conf;
+ pr_debug("av_h_conf: num of hdmi: %u\n", hw_conf->num_of_hdmi);
+ pr_debug("av_h_conf: num of avmulti: %u\n", hw_conf->num_of_avmulti);
+ pr_debug("av_h_conf: num of spdif: %u\n", hw_conf->num_of_spdif);
for (i = 0; i < PS3AV_HEAD_MAX; i++)
ps3av->head[i] = PS3AV_CMD_VIDEO_HEAD_A + i;
for (i = 0; i < PS3AV_OPT_PORT_MAX; i++)
ps3av->opt_port[i] = PS3AV_CMD_AVPORT_SPDIF_0 + i;
- for (i = 0; i < ps3av->av_hw_conf.num_of_hdmi; i++)
+ for (i = 0; i < hw_conf->num_of_hdmi; i++)
ps3av->av_port[i] = PS3AV_CMD_AVPORT_HDMI_0 + i;
- for (j = 0; j < ps3av->av_hw_conf.num_of_avmulti; j++)
+ for (j = 0; j < hw_conf->num_of_avmulti; j++)
ps3av->av_port[i + j] = PS3AV_CMD_AVPORT_AVMULTI_0 + j;
- for (k = 0; k < ps3av->av_hw_conf.num_of_spdif; k++)
+ for (k = 0; k < hw_conf->num_of_spdif; k++)
ps3av->av_port[i + j + k] = PS3AV_CMD_AVPORT_SPDIF_0 + k;
/* set all audio port */
@@ -738,7 +841,7 @@ static int ps3av_get_hw_conf(struct ps3av *ps3av)
}
/* set mode using id */
-int ps3av_set_video_mode(u32 id, int boot)
+int ps3av_set_video_mode(u32 id)
{
int size;
u32 option;
@@ -752,7 +855,7 @@ int ps3av_set_video_mode(u32 id, int boot)
/* auto mode */
option = id & ~PS3AV_MODE_MASK;
if ((id & PS3AV_MODE_MASK) == 0) {
- id = ps3av_auto_videomode(&ps3av->av_hw_conf, boot);
+ id = ps3av_auto_videomode(&ps3av->av_hw_conf);
if (id < 1) {
printk(KERN_ERR "%s: invalid id :%d\n", __func__, id);
return -EINVAL;
@@ -772,34 +875,13 @@ int ps3av_set_video_mode(u32 id, int boot)
EXPORT_SYMBOL_GPL(ps3av_set_video_mode);
-int ps3av_get_auto_mode(int boot)
+int ps3av_get_auto_mode(void)
{
- return ps3av_auto_videomode(&ps3av->av_hw_conf, boot);
+ return ps3av_auto_videomode(&ps3av->av_hw_conf);
}
EXPORT_SYMBOL_GPL(ps3av_get_auto_mode);
-int ps3av_set_mode(u32 id, int boot)
-{
- int res;
-
- res = ps3av_set_video_mode(id, boot);
- if (res)
- return res;
-
- res = ps3av_set_audio_mode(PS3AV_CMD_AUDIO_NUM_OF_CH_2,
- PS3AV_CMD_AUDIO_FS_48K,
- PS3AV_CMD_AUDIO_WORD_BITS_16,
- PS3AV_CMD_AUDIO_FORMAT_PCM,
- PS3AV_CMD_AUDIO_SOURCE_SERIAL);
- if (res)
- return res;
-
- return 0;
-}
-
-EXPORT_SYMBOL_GPL(ps3av_set_mode);
-
int ps3av_get_mode(void)
{
return ps3av ? ps3av->ps3av_mode : 0;
@@ -941,7 +1023,14 @@ static int ps3av_probe(struct ps3_system_bus_device *dev)
res);
ps3av_get_hw_conf(ps3av);
- id = ps3av_auto_videomode(&ps3av->av_hw_conf, 1);
+
+#ifdef CONFIG_FB
+ if (fb_mode_option && !strcmp(fb_mode_option, "safe"))
+ safe_mode = 1;
+#endif /* CONFIG_FB */
+ id = ps3av_auto_videomode(&ps3av->av_hw_conf);
+ safe_mode = 0;
+
mutex_lock(&ps3av->mutex);
ps3av->ps3av_mode = id;
mutex_unlock(&ps3av->mutex);
diff --git a/drivers/ps3/ps3av_cmd.c b/drivers/ps3/ps3av_cmd.c
index f72f5ddf18e4..7f880c26122f 100644
--- a/drivers/ps3/ps3av_cmd.c
+++ b/drivers/ps3/ps3av_cmd.c
@@ -512,7 +512,6 @@ static const u32 ps3av_ns_table[][5] = {
static void ps3av_cnv_ns(u8 *ns, u32 fs, u32 video_vid)
{
u32 av_vid, ns_val;
- u8 *p = ns;
int d;
d = ns_val = 0;
@@ -551,24 +550,22 @@ static void ps3av_cnv_ns(u8 *ns, u32 fs, u32 video_vid)
else
ns_val = ps3av_ns_table[PS3AV_CMD_AUDIO_FS_44K-BASE][d];
- *p++ = ns_val & 0x000000FF;
- *p++ = (ns_val & 0x0000FF00) >> 8;
- *p = (ns_val & 0x00FF0000) >> 16;
+ *ns++ = ns_val & 0x000000FF;
+ *ns++ = (ns_val & 0x0000FF00) >> 8;
+ *ns = (ns_val & 0x00FF0000) >> 16;
}
#undef BASE
static u8 ps3av_cnv_enable(u32 source, const u8 *enable)
{
- const u8 *p;
u8 ret = 0;
if (source == PS3AV_CMD_AUDIO_SOURCE_SPDIF) {
ret = 0x03;
} else if (source == PS3AV_CMD_AUDIO_SOURCE_SERIAL) {
- p = enable;
- ret = ((p[0] << 4) + (p[1] << 5) + (p[2] << 6) + (p[3] << 7)) |
- 0x01;
+ ret = ((enable[0] << 4) + (enable[1] << 5) + (enable[2] << 6) +
+ (enable[3] << 7)) | 0x01;
} else
printk(KERN_ERR "%s failed, source:%x\n", __func__, source);
return ret;
@@ -576,11 +573,9 @@ static u8 ps3av_cnv_enable(u32 source, const u8 *enable)
static u8 ps3av_cnv_fifomap(const u8 *map)
{
- const u8 *p;
u8 ret = 0;
- p = map;
- ret = p[0] + (p[1] << 2) + (p[2] << 4) + (p[3] << 6);
+ ret = map[0] + (map[1] << 2) + (map[2] << 4) + (map[3] << 6);
return ret;
}
@@ -927,72 +922,6 @@ int ps3av_cmd_video_get_monitor_info(struct ps3av_pkt_av_get_monitor_info *info,
return res;
}
-#ifdef PS3AV_DEBUG
-void ps3av_cmd_av_hw_conf_dump(const struct ps3av_pkt_av_get_hw_conf *hw_conf)
-{
- printk("av_h_conf:num of hdmi:%d\n", hw_conf->num_of_hdmi);
- printk("av_h_conf:num of avmulti:%d\n", hw_conf->num_of_avmulti);
- printk("av_h_conf:num of spdif:%d\n", hw_conf->num_of_spdif);
-}
-
-void ps3av_cmd_av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info *monitor_info)
-{
- const struct ps3av_info_monitor *info = &monitor_info->info;
- const struct ps3av_info_audio *audio = info->audio;
- int i;
-
- printk("Monitor Info: size%d\n", monitor_info->send_hdr.size);
-
- printk("avport:%02x\n", info->avport);
- printk("monitor_id:");
- for (i = 0; i < 10; i++)
- printk("%02x ", info->monitor_id[i]);
- printk("\nmonitor_type:%02x\n", info->monitor_type);
- printk("monitor_name:");
- for (i = 0; i < 16; i++)
- printk("%c", info->monitor_name[i]);
-
- /* resolution */
- printk("\nresolution_60: bits:%08x native:%08x\n",
- info->res_60.res_bits, info->res_60.native);
- printk("resolution_50: bits:%08x native:%08x\n",
- info->res_50.res_bits, info->res_50.native);
- printk("resolution_other: bits:%08x native:%08x\n",
- info->res_other.res_bits, info->res_other.native);
- printk("resolution_vesa: bits:%08x native:%08x\n",
- info->res_vesa.res_bits, info->res_vesa.native);
-
- /* color space */
- printk("color space rgb:%02x\n", info->cs.rgb);
- printk("color space yuv444:%02x\n", info->cs.yuv444);
- printk("color space yuv422:%02x\n", info->cs.yuv422);
-
- /* color info */
- printk("color info red:X %04x Y %04x\n",
- info->color.red_x, info->color.red_y);
- printk("color info green:X %04x Y %04x\n",
- info->color.green_x, info->color.green_y);
- printk("color info blue:X %04x Y %04x\n",
- info->color.blue_x, info->color.blue_y);
- printk("color info white:X %04x Y %04x\n",
- info->color.white_x, info->color.white_y);
- printk("color info gamma: %08x\n", info->color.gamma);
-
- /* other info */
- printk("supported_AI:%02x\n", info->supported_ai);
- printk("speaker_info:%02x\n", info->speaker_info);
- printk("num of audio:%02x\n", info->num_of_audio_block);
-
- /* audio block */
- for (i = 0; i < info->num_of_audio_block; i++) {
- printk("audio[%d] type:%02x max_ch:%02x fs:%02x sbit:%02x\n",
- i, audio->type, audio->max_num_of_ch, audio->fs,
- audio->sbit);
- audio++;
- }
-}
-#endif /* PS3AV_DEBUG */
-
#define PS3AV_AV_LAYOUT_0 (PS3AV_CMD_AV_LAYOUT_32 \
| PS3AV_CMD_AV_LAYOUT_44 \
| PS3AV_CMD_AV_LAYOUT_48)
diff --git a/drivers/ps3/ps3stor_lib.c b/drivers/ps3/ps3stor_lib.c
index 3a9824e3b251..55955f16ad91 100644
--- a/drivers/ps3/ps3stor_lib.c
+++ b/drivers/ps3/ps3stor_lib.c
@@ -66,7 +66,7 @@ static int ps3stor_probe_access(struct ps3_storage_device *dev)
if (n > 1)
dev_info(&dev->sbd.core,
"%s:%u: %lu accessible regions found. Only the first "
- "one will be used",
+ "one will be used\n",
__func__, __LINE__, n);
dev->region_idx = __ffs(dev->accessible_regions);
dev_info(&dev->sbd.core,
diff --git a/drivers/ps3/vuart.c b/drivers/ps3/vuart.c
index bea25a1391ee..9dea585ef806 100644
--- a/drivers/ps3/vuart.c
+++ b/drivers/ps3/vuart.c
@@ -22,11 +22,11 @@
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/workqueue.h>
+#include <linux/bitops.h>
#include <asm/ps3.h>
#include <asm/firmware.h>
#include <asm/lv1call.h>
-#include <asm/bitops.h>
#include "vuart.h"
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index ff9e35cb308d..e5cdc0294aaa 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -36,7 +36,9 @@ config RTC_HCTOSYS_DEVICE
help
The RTC device that will be used to (re)initialize the system
clock, usually rtc0. Initialization is done when the system
- starts up, and when it resumes from a low power state.
+ starts up, and when it resumes from a low power state. This
+ device should record time in UTC, since the kernel won't do
+ timezone correction.
The driver for this RTC device must be loaded before late_initcall
functions run, so it must usually be statically linked.
@@ -133,12 +135,23 @@ config RTC_DRV_DS1307
The first seven registers on these chips hold an RTC, and other
registers may add features such as NVRAM, a trickle charger for
- the RTC/NVRAM backup power, and alarms. This driver may not
- expose all those available chip features.
+ the RTC/NVRAM backup power, and alarms. NVRAM is visible in
+ sysfs, but other chip features may not be available.
This driver can also be built as a module. If so, the module
will be called rtc-ds1307.
+config RTC_DRV_DS1374
+ tristate "Maxim/Dallas Semiconductor DS1374 Real Time Clock"
+ depends on RTC_CLASS && I2C
+ help
+ If you say yes here you get support for Dallas Semiconductor
+ DS1374 real-time clock chips. If an interrupt is associated
+ with the device, the alarm functionality is supported.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-ds1374.
+
config RTC_DRV_DS1672
tristate "Dallas/Maxim DS1672"
help
@@ -229,7 +242,7 @@ config RTC_DRV_TWL92330
depends on MENELAUS
help
If you say yes here you get support for the RTC on the
- TWL92330 "Menelaus" power mangement chip, used with OMAP2
+ TWL92330 "Menelaus" power management chip, used with OMAP2
platforms. The support is integrated with the rest of
the Menelaus driver; it's not separate module.
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index d3a33aa2696f..465db4dd50b2 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o
obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o
obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o
obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o
+obj-$(CONFIG_RTC_DRV_DS1374) += rtc-ds1374.o
obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o
obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o
obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index 10ab3b71ffc6..4dfdf019fccc 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -153,6 +153,7 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
mutex_init(&rtc->ops_lock);
spin_lock_init(&rtc->irq_lock);
spin_lock_init(&rtc->irq_task_lock);
+ init_waitqueue_head(&rtc->irq_queue);
strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE);
snprintf(rtc->dev.bus_id, BUS_ID_SIZE, "rtc%d", id);
diff --git a/drivers/rtc/hctosys.c b/drivers/rtc/hctosys.c
index 178527252c6a..33c0e98243ee 100644
--- a/drivers/rtc/hctosys.c
+++ b/drivers/rtc/hctosys.c
@@ -47,8 +47,8 @@ static int __init rtc_hctosys(void)
do_settimeofday(&tv);
dev_info(rtc->dev.parent,
- "setting the system clock to "
- "%d-%02d-%02d %02d:%02d:%02d (%u)\n",
+ "setting system clock to "
+ "%d-%02d-%02d %02d:%02d:%02d UTC (%u)\n",
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec,
(unsigned int) tv.tv_sec);
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index ad66c6ecf365..de0da545c7a1 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -12,6 +12,7 @@
*/
#include <linux/rtc.h>
+#include <linux/log2.h>
int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm)
{
@@ -99,7 +100,7 @@ int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs)
}
EXPORT_SYMBOL_GPL(rtc_set_mmss);
-int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
+static int rtc_read_alarm_internal(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
{
int err;
@@ -119,6 +120,87 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
mutex_unlock(&rtc->ops_lock);
return err;
}
+
+int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
+{
+ int err;
+ struct rtc_time before, now;
+ int first_time = 1;
+
+ /* The lower level RTC driver may not be capable of filling
+ * in all fields of the rtc_time struct (eg. rtc-cmos),
+ * and so might instead return -1 in some fields.
+ * We deal with that here by grabbing a current RTC timestamp
+ * and using values from that for any missing (-1) values.
+ *
+ * But this can be racey, because some fields of the RTC timestamp
+ * may have wrapped in the interval since we read the RTC alarm,
+ * which would lead to us inserting inconsistent values in place
+ * of the -1 fields.
+ *
+ * Reading the alarm and timestamp in the reverse sequence
+ * would have the same race condition, and not solve the issue.
+ *
+ * So, we must first read the RTC timestamp,
+ * then read the RTC alarm value,
+ * and then read a second RTC timestamp.
+ *
+ * If any fields of the second timestamp have changed
+ * when compared with the first timestamp, then we know
+ * our timestamp may be inconsistent with that used by
+ * the low-level rtc_read_alarm_internal() function.
+ *
+ * So, when the two timestamps disagree, we just loop and do
+ * the process again to get a fully consistent set of values.
+ *
+ * This could all instead be done in the lower level driver,
+ * but since more than one lower level RTC implementation needs it,
+ * then it's probably best best to do it here instead of there..
+ */
+
+ /* Get the "before" timestamp */
+ err = rtc_read_time(rtc, &before);
+ if (err < 0)
+ return err;
+ do {
+ if (!first_time)
+ memcpy(&before, &now, sizeof(struct rtc_time));
+ first_time = 0;
+
+ /* get the RTC alarm values, which may be incomplete */
+ err = rtc_read_alarm_internal(rtc, alarm);
+ if (err)
+ return err;
+ if (!alarm->enabled)
+ return 0;
+
+ /* get the "after" timestamp, to detect wrapped fields */
+ err = rtc_read_time(rtc, &now);
+ if (err < 0)
+ return err;
+
+ /* note that tm_sec is a "don't care" value here: */
+ } while ( before.tm_min != now.tm_min
+ || before.tm_hour != now.tm_hour
+ || before.tm_mon != now.tm_mon
+ || before.tm_year != now.tm_year
+ || before.tm_isdst != now.tm_isdst);
+
+ /* Fill in any missing alarm fields using the timestamp */
+ if (alarm->time.tm_sec == -1)
+ alarm->time.tm_sec = now.tm_sec;
+ if (alarm->time.tm_min == -1)
+ alarm->time.tm_min = now.tm_min;
+ if (alarm->time.tm_hour == -1)
+ alarm->time.tm_hour = now.tm_hour;
+ if (alarm->time.tm_mday == -1)
+ alarm->time.tm_mday = now.tm_mday;
+ if (alarm->time.tm_mon == -1)
+ alarm->time.tm_mon = now.tm_mon;
+ if (alarm->time.tm_year == -1)
+ alarm->time.tm_year = now.tm_year;
+ return 0;
+}
EXPORT_SYMBOL_GPL(rtc_read_alarm);
int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
@@ -210,6 +292,10 @@ int rtc_irq_register(struct rtc_device *rtc, struct rtc_task *task)
if (task == NULL || task->func == NULL)
return -EINVAL;
+ /* Cannot register while the char dev is in use */
+ if (!(mutex_trylock(&rtc->char_lock)))
+ return -EBUSY;
+
spin_lock_irq(&rtc->irq_task_lock);
if (rtc->irq_task == NULL) {
rtc->irq_task = task;
@@ -217,13 +303,14 @@ int rtc_irq_register(struct rtc_device *rtc, struct rtc_task *task)
}
spin_unlock_irq(&rtc->irq_task_lock);
+ mutex_unlock(&rtc->char_lock);
+
return retval;
}
EXPORT_SYMBOL_GPL(rtc_irq_register);
void rtc_irq_unregister(struct rtc_device *rtc, struct rtc_task *task)
{
-
spin_lock_irq(&rtc->irq_task_lock);
if (rtc->irq_task == task)
rtc->irq_task = NULL;
@@ -231,6 +318,16 @@ void rtc_irq_unregister(struct rtc_device *rtc, struct rtc_task *task)
}
EXPORT_SYMBOL_GPL(rtc_irq_unregister);
+/**
+ * rtc_irq_set_state - enable/disable 2^N Hz periodic IRQs
+ * @rtc: the rtc device
+ * @task: currently registered with rtc_irq_register()
+ * @enabled: true to enable periodic IRQs
+ * Context: any
+ *
+ * Note that rtc_irq_set_freq() should previously have been used to
+ * specify the desired frequency of periodic IRQ task->func() callbacks.
+ */
int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled)
{
int err = 0;
@@ -240,8 +337,10 @@ int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled
return -ENXIO;
spin_lock_irqsave(&rtc->irq_task_lock, flags);
+ if (rtc->irq_task != NULL && task == NULL)
+ err = -EBUSY;
if (rtc->irq_task != task)
- err = -ENXIO;
+ err = -EACCES;
spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
if (err == 0)
@@ -251,6 +350,16 @@ int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled
}
EXPORT_SYMBOL_GPL(rtc_irq_set_state);
+/**
+ * rtc_irq_set_freq - set 2^N Hz periodic IRQ frequency for IRQ
+ * @rtc: the rtc device
+ * @task: currently registered with rtc_irq_register()
+ * @freq: positive frequency with which task->func() will be called
+ * Context: any
+ *
+ * Note that rtc_irq_set_state() is used to enable or disable the
+ * periodic IRQs.
+ */
int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq)
{
int err = 0;
@@ -259,9 +368,14 @@ int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq)
if (rtc->ops->irq_set_freq == NULL)
return -ENXIO;
+ if (!is_power_of_2(freq))
+ return -EINVAL;
+
spin_lock_irqsave(&rtc->irq_task_lock, flags);
+ if (rtc->irq_task != NULL && task == NULL)
+ err = -EBUSY;
if (rtc->irq_task != task)
- err = -ENXIO;
+ err = -EACCES;
spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
if (err == 0) {
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index 5d760bb6c2cd..29cf1457ca10 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -120,7 +120,8 @@ static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t)
t->time.tm_hour = CMOS_READ(RTC_HOURS_ALARM);
if (cmos->day_alrm) {
- t->time.tm_mday = CMOS_READ(cmos->day_alrm);
+ /* ignore upper bits on readback per ACPI spec */
+ t->time.tm_mday = CMOS_READ(cmos->day_alrm) & 0x3f;
if (!t->time.tm_mday)
t->time.tm_mday = -1;
@@ -246,11 +247,9 @@ static int cmos_irq_set_freq(struct device *dev, int freq)
/* 0 = no irqs; 1 = 2^15 Hz ... 15 = 2^0 Hz */
f = ffs(freq);
- if (f != 0) {
- if (f-- > 16 || freq != (1 << f))
- return -EINVAL;
- f = 16 - f;
- }
+ if (f-- > 16)
+ return -EINVAL;
+ f = 16 - f;
spin_lock_irqsave(&rtc_lock, flags);
CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT);
@@ -435,6 +434,19 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
if (!ports)
return -ENODEV;
+ /* Claim I/O ports ASAP, minimizing conflict with legacy driver.
+ *
+ * REVISIT non-x86 systems may instead use memory space resources
+ * (needing ioremap etc), not i/o space resources like this ...
+ */
+ ports = request_region(ports->start,
+ ports->end + 1 - ports->start,
+ driver_name);
+ if (!ports) {
+ dev_dbg(dev, "i/o registers already in use\n");
+ return -EBUSY;
+ }
+
cmos_rtc.irq = rtc_irq;
cmos_rtc.iomem = ports;
@@ -456,24 +468,13 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
cmos_rtc.rtc = rtc_device_register(driver_name, dev,
&cmos_rtc_ops, THIS_MODULE);
- if (IS_ERR(cmos_rtc.rtc))
- return PTR_ERR(cmos_rtc.rtc);
+ if (IS_ERR(cmos_rtc.rtc)) {
+ retval = PTR_ERR(cmos_rtc.rtc);
+ goto cleanup0;
+ }
cmos_rtc.dev = dev;
dev_set_drvdata(dev, &cmos_rtc);
-
- /* platform and pnp busses handle resources incompatibly.
- *
- * REVISIT for non-x86 systems we may need to handle io memory
- * resources: ioremap them, and request_mem_region().
- */
- if (is_pnp()) {
- retval = request_resource(&ioport_resource, ports);
- if (retval < 0) {
- dev_dbg(dev, "i/o registers already in use\n");
- goto cleanup0;
- }
- }
rename_region(ports, cmos_rtc.rtc->dev.bus_id);
spin_lock_irq(&rtc_lock);
@@ -536,9 +537,10 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
return 0;
cleanup1:
- rename_region(ports, NULL);
-cleanup0:
+ cmos_rtc.dev = NULL;
rtc_device_unregister(cmos_rtc.rtc);
+cleanup0:
+ release_region(ports->start, ports->end + 1 - ports->start);
return retval;
}
@@ -557,19 +559,21 @@ static void cmos_do_shutdown(void)
static void __exit cmos_do_remove(struct device *dev)
{
struct cmos_rtc *cmos = dev_get_drvdata(dev);
+ struct resource *ports;
cmos_do_shutdown();
- if (is_pnp())
- release_resource(cmos->iomem);
- rename_region(cmos->iomem, NULL);
-
if (is_valid_irq(cmos->irq))
- free_irq(cmos->irq, cmos_rtc.rtc);
+ free_irq(cmos->irq, cmos->rtc);
- rtc_device_unregister(cmos_rtc.rtc);
+ rtc_device_unregister(cmos->rtc);
+ cmos->rtc = NULL;
- cmos_rtc.dev = NULL;
+ ports = cmos->iomem;
+ release_region(ports->start, ports->end + 1 - ports->start);
+ cmos->iomem = NULL;
+
+ cmos->dev = NULL;
dev_set_drvdata(dev, NULL);
}
@@ -656,7 +660,8 @@ static int cmos_resume(struct device *dev)
/*----------------------------------------------------------------*/
/* The "CMOS" RTC normally lives on the platform_bus. On ACPI systems,
- * the device node will always be created as a PNPACPI device.
+ * the device node will always be created as a PNPACPI device. Plus
+ * pre-ACPI PCs probably list it in the PNPBIOS tables.
*/
#ifdef CONFIG_PNP
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index 005fff3a3508..814583bd2fe7 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -142,7 +142,7 @@ static int set_uie(struct rtc_device *rtc)
static ssize_t
rtc_dev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
- struct rtc_device *rtc = to_rtc_device(file->private_data);
+ struct rtc_device *rtc = file->private_data;
DECLARE_WAITQUEUE(wait, current);
unsigned long data;
@@ -196,7 +196,7 @@ rtc_dev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
static unsigned int rtc_dev_poll(struct file *file, poll_table *wait)
{
- struct rtc_device *rtc = to_rtc_device(file->private_data);
+ struct rtc_device *rtc = file->private_data;
unsigned long data;
poll_wait(file, &rtc->irq_queue, wait);
@@ -233,22 +233,12 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
break;
case RTC_PIE_ON:
- if (!capable(CAP_SYS_RESOURCE))
+ if (rtc->irq_freq > rtc->max_user_freq &&
+ !capable(CAP_SYS_RESOURCE))
return -EACCES;
break;
}
- /* avoid conflicting IRQ users */
- if (cmd == RTC_PIE_ON || cmd == RTC_PIE_OFF || cmd == RTC_IRQP_SET) {
- spin_lock_irq(&rtc->irq_task_lock);
- if (rtc->irq_task)
- err = -EBUSY;
- spin_unlock_irq(&rtc->irq_task_lock);
-
- if (err < 0)
- return err;
- }
-
/* try the driver's ioctl interface */
if (ops->ioctl) {
err = ops->ioctl(rtc->dev.parent, cmd, arg);
@@ -338,18 +328,20 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
err = rtc_set_time(rtc, &tm);
break;
- case RTC_IRQP_READ:
- if (ops->irq_set_freq)
- err = put_user(rtc->irq_freq, (unsigned long __user *)uarg);
- else
- err = -ENOTTY;
+ case RTC_PIE_ON:
+ err = rtc_irq_set_state(rtc, NULL, 1);
+ break;
+
+ case RTC_PIE_OFF:
+ err = rtc_irq_set_state(rtc, NULL, 0);
break;
case RTC_IRQP_SET:
- if (ops->irq_set_freq)
- err = rtc_irq_set_freq(rtc, rtc->irq_task, arg);
- else
- err = -ENOTTY;
+ err = rtc_irq_set_freq(rtc, NULL, arg);
+ break;
+
+ case RTC_IRQP_READ:
+ err = put_user(rtc->irq_freq, (unsigned long __user *)uarg);
break;
#if 0
@@ -405,7 +397,7 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
static int rtc_dev_release(struct inode *inode, struct file *file)
{
- struct rtc_device *rtc = to_rtc_device(file->private_data);
+ struct rtc_device *rtc = file->private_data;
#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
clear_uie(rtc);
@@ -419,7 +411,7 @@ static int rtc_dev_release(struct inode *inode, struct file *file)
static int rtc_dev_fasync(int fd, struct file *file, int on)
{
- struct rtc_device *rtc = to_rtc_device(file->private_data);
+ struct rtc_device *rtc = file->private_data;
return fasync_helper(fd, file, on, &rtc->async_queue);
}
@@ -449,8 +441,6 @@ void rtc_dev_prepare(struct rtc_device *rtc)
rtc->dev.devt = MKDEV(MAJOR(rtc_devt), rtc->id);
mutex_init(&rtc->char_lock);
- spin_lock_init(&rtc->irq_lock);
- init_waitqueue_head(&rtc->irq_queue);
#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
INIT_WORK(&rtc->uie_task, rtc_uie_task);
setup_timer(&rtc->uie_timer, rtc_uie_timer, (unsigned long)rtc);
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index db6f3f0d8982..bc1c7fe94ad3 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -89,6 +89,7 @@ enum ds_type {
struct ds1307 {
u8 reg_addr;
+ bool has_nvram;
u8 regs[8];
enum ds_type type;
struct i2c_msg msg[2];
@@ -242,6 +243,87 @@ static const struct rtc_class_ops ds13xx_rtc_ops = {
.set_time = ds1307_set_time,
};
+/*----------------------------------------------------------------------*/
+
+#define NVRAM_SIZE 56
+
+static ssize_t
+ds1307_nvram_read(struct kobject *kobj, struct bin_attribute *attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct i2c_client *client;
+ struct ds1307 *ds1307;
+ struct i2c_msg msg[2];
+ int result;
+
+ client = to_i2c_client(container_of(kobj, struct device, kobj));
+ ds1307 = i2c_get_clientdata(client);
+
+ if (unlikely(off >= NVRAM_SIZE))
+ return 0;
+ if ((off + count) > NVRAM_SIZE)
+ count = NVRAM_SIZE - off;
+ if (unlikely(!count))
+ return count;
+
+ msg[0].addr = client->addr;
+ msg[0].flags = 0;
+ msg[0].len = 1;
+ msg[0].buf = buf;
+
+ buf[0] = 8 + off;
+
+ msg[1].addr = client->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = count;
+ msg[1].buf = buf;
+
+ result = i2c_transfer(to_i2c_adapter(client->dev.parent), msg, 2);
+ if (result != 2) {
+ dev_err(&client->dev, "%s error %d\n", "nvram read", result);
+ return -EIO;
+ }
+ return count;
+}
+
+static ssize_t
+ds1307_nvram_write(struct kobject *kobj, struct bin_attribute *attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct i2c_client *client;
+ u8 buffer[NVRAM_SIZE + 1];
+ int ret;
+
+ client = to_i2c_client(container_of(kobj, struct device, kobj));
+
+ if (unlikely(off >= NVRAM_SIZE))
+ return -EFBIG;
+ if ((off + count) > NVRAM_SIZE)
+ count = NVRAM_SIZE - off;
+ if (unlikely(!count))
+ return count;
+
+ buffer[0] = 8 + off;
+ memcpy(buffer + 1, buf, count);
+
+ ret = i2c_master_send(client, buffer, count + 1);
+ return (ret < 0) ? ret : (ret - 1);
+}
+
+static struct bin_attribute nvram = {
+ .attr = {
+ .name = "nvram",
+ .mode = S_IRUGO | S_IWUSR,
+ .owner = THIS_MODULE,
+ },
+
+ .read = ds1307_nvram_read,
+ .write = ds1307_nvram_write,
+ .size = NVRAM_SIZE,
+};
+
+/*----------------------------------------------------------------------*/
+
static struct i2c_driver ds1307_driver;
static int __devinit ds1307_probe(struct i2c_client *client)
@@ -413,6 +495,14 @@ read_rtc:
goto exit_free;
}
+ if (chip->nvram56) {
+ err = sysfs_create_bin_file(&client->dev.kobj, &nvram);
+ if (err == 0) {
+ ds1307->has_nvram = true;
+ dev_info(&client->dev, "56 bytes nvram\n");
+ }
+ }
+
return 0;
exit_bad:
@@ -432,6 +522,9 @@ static int __devexit ds1307_remove(struct i2c_client *client)
{
struct ds1307 *ds1307 = i2c_get_clientdata(client);
+ if (ds1307->has_nvram)
+ sysfs_remove_bin_file(&client->dev.kobj, &nvram);
+
rtc_device_unregister(ds1307->rtc);
kfree(ds1307);
return 0;
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c
new file mode 100644
index 000000000000..45bda186befc
--- /dev/null
+++ b/drivers/rtc/rtc-ds1374.c
@@ -0,0 +1,449 @@
+/*
+ * RTC client/driver for the Maxim/Dallas DS1374 Real-Time Clock over I2C
+ *
+ * Based on code by Randy Vinson <rvinson@mvista.com>,
+ * which was based on the m41t00.c by Mark Greer <mgreer@mvista.com>.
+ *
+ * Copyright (C) 2006-2007 Freescale Semiconductor
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+/*
+ * It would be more efficient to use i2c msgs/i2c_transfer directly but, as
+ * recommened in .../Documentation/i2c/writing-clients section
+ * "Sending and receiving", using SMBus level communication is preferred.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+#include <linux/workqueue.h>
+
+#define DS1374_REG_TOD0 0x00 /* Time of Day */
+#define DS1374_REG_TOD1 0x01
+#define DS1374_REG_TOD2 0x02
+#define DS1374_REG_TOD3 0x03
+#define DS1374_REG_WDALM0 0x04 /* Watchdog/Alarm */
+#define DS1374_REG_WDALM1 0x05
+#define DS1374_REG_WDALM2 0x06
+#define DS1374_REG_CR 0x07 /* Control */
+#define DS1374_REG_CR_AIE 0x01 /* Alarm Int. Enable */
+#define DS1374_REG_CR_WDALM 0x20 /* 1=Watchdog, 0=Alarm */
+#define DS1374_REG_CR_WACE 0x40 /* WD/Alarm counter enable */
+#define DS1374_REG_SR 0x08 /* Status */
+#define DS1374_REG_SR_OSF 0x80 /* Oscillator Stop Flag */
+#define DS1374_REG_SR_AF 0x01 /* Alarm Flag */
+#define DS1374_REG_TCR 0x09 /* Trickle Charge */
+
+struct ds1374 {
+ struct i2c_client *client;
+ struct rtc_device *rtc;
+ struct work_struct work;
+
+ /* The mutex protects alarm operations, and prevents a race
+ * between the enable_irq() in the workqueue and the free_irq()
+ * in the remove function.
+ */
+ struct mutex mutex;
+ int exiting;
+};
+
+static struct i2c_driver ds1374_driver;
+
+static int ds1374_read_rtc(struct i2c_client *client, u32 *time,
+ int reg, int nbytes)
+{
+ u8 buf[4];
+ int ret;
+ int i;
+
+ if (nbytes > 4) {
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ ret = i2c_smbus_read_i2c_block_data(client, reg, nbytes, buf);
+
+ if (ret < 0)
+ return ret;
+ if (ret < nbytes)
+ return -EIO;
+
+ for (i = nbytes - 1, *time = 0; i >= 0; i--)
+ *time = (*time << 8) | buf[i];
+
+ return 0;
+}
+
+static int ds1374_write_rtc(struct i2c_client *client, u32 time,
+ int reg, int nbytes)
+{
+ u8 buf[4];
+ int i;
+
+ if (nbytes > 4) {
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < nbytes; i++) {
+ buf[i] = time & 0xff;
+ time >>= 8;
+ }
+
+ return i2c_smbus_write_i2c_block_data(client, reg, nbytes, buf);
+}
+
+static int ds1374_check_rtc_status(struct i2c_client *client)
+{
+ int ret = 0;
+ int control, stat;
+
+ stat = i2c_smbus_read_byte_data(client, DS1374_REG_SR);
+ if (stat < 0)
+ return stat;
+
+ if (stat & DS1374_REG_SR_OSF)
+ dev_warn(&client->dev,
+ "oscillator discontinuity flagged, "
+ "time unreliable\n");
+
+ stat &= ~(DS1374_REG_SR_OSF | DS1374_REG_SR_AF);
+
+ ret = i2c_smbus_write_byte_data(client, DS1374_REG_SR, stat);
+ if (ret < 0)
+ return ret;
+
+ /* If the alarm is pending, clear it before requesting
+ * the interrupt, so an interrupt event isn't reported
+ * before everything is initialized.
+ */
+
+ control = i2c_smbus_read_byte_data(client, DS1374_REG_CR);
+ if (control < 0)
+ return control;
+
+ control &= ~(DS1374_REG_CR_WACE | DS1374_REG_CR_AIE);
+ return i2c_smbus_write_byte_data(client, DS1374_REG_CR, control);
+}
+
+static int ds1374_read_time(struct device *dev, struct rtc_time *time)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ u32 itime;
+ int ret;
+
+ ret = ds1374_read_rtc(client, &itime, DS1374_REG_TOD0, 4);
+ if (!ret)
+ rtc_time_to_tm(itime, time);
+
+ return ret;
+}
+
+static int ds1374_set_time(struct device *dev, struct rtc_time *time)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ unsigned long itime;
+
+ rtc_tm_to_time(time, &itime);
+ return ds1374_write_rtc(client, itime, DS1374_REG_TOD0, 4);
+}
+
+/* The ds1374 has a decrementer for an alarm, rather than a comparator.
+ * If the time of day is changed, then the alarm will need to be
+ * reset.
+ */
+static int ds1374_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct ds1374 *ds1374 = i2c_get_clientdata(client);
+ u32 now, cur_alarm;
+ int cr, sr;
+ int ret = 0;
+
+ if (client->irq < 0)
+ return -EINVAL;
+
+ mutex_lock(&ds1374->mutex);
+
+ cr = ret = i2c_smbus_read_byte_data(client, DS1374_REG_CR);
+ if (ret < 0)
+ goto out;
+
+ sr = ret = i2c_smbus_read_byte_data(client, DS1374_REG_SR);
+ if (ret < 0)
+ goto out;
+
+ ret = ds1374_read_rtc(client, &now, DS1374_REG_TOD0, 4);
+ if (ret)
+ goto out;
+
+ ret = ds1374_read_rtc(client, &cur_alarm, DS1374_REG_WDALM0, 3);
+ if (ret)
+ goto out;
+
+ rtc_time_to_tm(now + cur_alarm, &alarm->time);
+ alarm->enabled = !!(cr & DS1374_REG_CR_WACE);
+ alarm->pending = !!(sr & DS1374_REG_SR_AF);
+
+out:
+ mutex_unlock(&ds1374->mutex);
+ return ret;
+}
+
+static int ds1374_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct ds1374 *ds1374 = i2c_get_clientdata(client);
+ struct rtc_time now;
+ unsigned long new_alarm, itime;
+ int cr;
+ int ret = 0;
+
+ if (client->irq < 0)
+ return -EINVAL;
+
+ ret = ds1374_read_time(dev, &now);
+ if (ret < 0)
+ return ret;
+
+ rtc_tm_to_time(&alarm->time, &new_alarm);
+ rtc_tm_to_time(&now, &itime);
+
+ new_alarm -= itime;
+
+ /* This can happen due to races, in addition to dates that are
+ * truly in the past. To avoid requiring the caller to check for
+ * races, dates in the past are assumed to be in the recent past
+ * (i.e. not something that we'd rather the caller know about via
+ * an error), and the alarm is set to go off as soon as possible.
+ */
+ if (new_alarm <= 0)
+ new_alarm = 1;
+
+ mutex_lock(&ds1374->mutex);
+
+ ret = cr = i2c_smbus_read_byte_data(client, DS1374_REG_CR);
+ if (ret < 0)
+ goto out;
+
+ /* Disable any existing alarm before setting the new one
+ * (or lack thereof). */
+ cr &= ~DS1374_REG_CR_WACE;
+
+ ret = i2c_smbus_write_byte_data(client, DS1374_REG_CR, cr);
+ if (ret < 0)
+ goto out;
+
+ ret = ds1374_write_rtc(client, new_alarm, DS1374_REG_WDALM0, 3);
+ if (ret)
+ goto out;
+
+ if (alarm->enabled) {
+ cr |= DS1374_REG_CR_WACE | DS1374_REG_CR_AIE;
+ cr &= ~DS1374_REG_CR_WDALM;
+
+ ret = i2c_smbus_write_byte_data(client, DS1374_REG_CR, cr);
+ }
+
+out:
+ mutex_unlock(&ds1374->mutex);
+ return ret;
+}
+
+static irqreturn_t ds1374_irq(int irq, void *dev_id)
+{
+ struct i2c_client *client = dev_id;
+ struct ds1374 *ds1374 = i2c_get_clientdata(client);
+
+ disable_irq_nosync(irq);
+ schedule_work(&ds1374->work);
+ return IRQ_HANDLED;
+}
+
+static void ds1374_work(struct work_struct *work)
+{
+ struct ds1374 *ds1374 = container_of(work, struct ds1374, work);
+ struct i2c_client *client = ds1374->client;
+ int stat, control;
+
+ mutex_lock(&ds1374->mutex);
+
+ stat = i2c_smbus_read_byte_data(client, DS1374_REG_SR);
+ if (stat < 0)
+ return;
+
+ if (stat & DS1374_REG_SR_AF) {
+ stat &= ~DS1374_REG_SR_AF;
+ i2c_smbus_write_byte_data(client, DS1374_REG_SR, stat);
+
+ control = i2c_smbus_read_byte_data(client, DS1374_REG_CR);
+ if (control < 0)
+ goto out;
+
+ control &= ~(DS1374_REG_CR_WACE | DS1374_REG_CR_AIE);
+ i2c_smbus_write_byte_data(client, DS1374_REG_CR, control);
+
+ /* rtc_update_irq() assumes that it is called
+ * from IRQ-disabled context.
+ */
+ local_irq_disable();
+ rtc_update_irq(ds1374->rtc, 1, RTC_AF | RTC_IRQF);
+ local_irq_enable();
+ }
+
+out:
+ if (!ds1374->exiting)
+ enable_irq(client->irq);
+
+ mutex_unlock(&ds1374->mutex);
+}
+
+static int ds1374_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct ds1374 *ds1374 = i2c_get_clientdata(client);
+ int ret = -ENOIOCTLCMD;
+
+ mutex_lock(&ds1374->mutex);
+
+ switch (cmd) {
+ case RTC_AIE_OFF:
+ ret = i2c_smbus_read_byte_data(client, DS1374_REG_CR);
+ if (ret < 0)
+ goto out;
+
+ ret &= ~DS1374_REG_CR_WACE;
+
+ ret = i2c_smbus_write_byte_data(client, DS1374_REG_CR, ret);
+ if (ret < 0)
+ goto out;
+
+ break;
+
+ case RTC_AIE_ON:
+ ret = i2c_smbus_read_byte_data(client, DS1374_REG_CR);
+ if (ret < 0)
+ goto out;
+
+ ret |= DS1374_REG_CR_WACE | DS1374_REG_CR_AIE;
+ ret &= ~DS1374_REG_CR_WDALM;
+
+ ret = i2c_smbus_write_byte_data(client, DS1374_REG_CR, ret);
+ if (ret < 0)
+ goto out;
+
+ break;
+ }
+
+out:
+ mutex_unlock(&ds1374->mutex);
+ return ret;
+}
+
+static const struct rtc_class_ops ds1374_rtc_ops = {
+ .read_time = ds1374_read_time,
+ .set_time = ds1374_set_time,
+ .read_alarm = ds1374_read_alarm,
+ .set_alarm = ds1374_set_alarm,
+ .ioctl = ds1374_ioctl,
+};
+
+static int ds1374_probe(struct i2c_client *client)
+{
+ struct ds1374 *ds1374;
+ int ret;
+
+ ds1374 = kzalloc(sizeof(struct ds1374), GFP_KERNEL);
+ if (!ds1374)
+ return -ENOMEM;
+
+ ds1374->client = client;
+ i2c_set_clientdata(client, ds1374);
+
+ INIT_WORK(&ds1374->work, ds1374_work);
+ mutex_init(&ds1374->mutex);
+
+ ret = ds1374_check_rtc_status(client);
+ if (ret)
+ goto out_free;
+
+ if (client->irq >= 0) {
+ ret = request_irq(client->irq, ds1374_irq, 0,
+ "ds1374", client);
+ if (ret) {
+ dev_err(&client->dev, "unable to request IRQ\n");
+ goto out_free;
+ }
+ }
+
+ ds1374->rtc = rtc_device_register(client->name, &client->dev,
+ &ds1374_rtc_ops, THIS_MODULE);
+ if (IS_ERR(ds1374->rtc)) {
+ ret = PTR_ERR(ds1374->rtc);
+ dev_err(&client->dev, "unable to register the class device\n");
+ goto out_irq;
+ }
+
+ return 0;
+
+out_irq:
+ if (client->irq >= 0)
+ free_irq(client->irq, client);
+
+out_free:
+ i2c_set_clientdata(client, NULL);
+ kfree(ds1374);
+ return ret;
+}
+
+static int __devexit ds1374_remove(struct i2c_client *client)
+{
+ struct ds1374 *ds1374 = i2c_get_clientdata(client);
+
+ if (client->irq >= 0) {
+ mutex_lock(&ds1374->mutex);
+ ds1374->exiting = 1;
+ mutex_unlock(&ds1374->mutex);
+
+ free_irq(client->irq, client);
+ flush_scheduled_work();
+ }
+
+ rtc_device_unregister(ds1374->rtc);
+ i2c_set_clientdata(client, NULL);
+ kfree(ds1374);
+ return 0;
+}
+
+static struct i2c_driver ds1374_driver = {
+ .driver = {
+ .name = "rtc-ds1374",
+ .owner = THIS_MODULE,
+ },
+ .probe = ds1374_probe,
+ .remove = __devexit_p(ds1374_remove),
+};
+
+static int __init ds1374_init(void)
+{
+ return i2c_add_driver(&ds1374_driver);
+}
+
+static void __exit ds1374_exit(void)
+{
+ i2c_del_driver(&ds1374_driver);
+}
+
+module_init(ds1374_init);
+module_exit(ds1374_exit);
+
+MODULE_AUTHOR("Scott Wood <scottwood@freescale.com>");
+MODULE_DESCRIPTION("Maxim/Dallas DS1374 RTC Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c
index 5ab3492817d1..d9e848dcd450 100644
--- a/drivers/rtc/rtc-ds1553.c
+++ b/drivers/rtc/rtc-ds1553.c
@@ -291,7 +291,7 @@ static ssize_t ds1553_nvram_write(struct kobject *kobj,
static struct bin_attribute ds1553_nvram_attr = {
.attr = {
.name = "nvram",
- .mode = S_IRUGO | S_IWUGO,
+ .mode = S_IRUGO | S_IWUSR,
},
.size = RTC_OFFSET,
.read = ds1553_nvram_read,
@@ -395,7 +395,7 @@ static struct platform_driver ds1553_rtc_driver = {
.probe = ds1553_rtc_probe,
.remove = __devexit_p(ds1553_rtc_remove),
.driver = {
- .name = "ds1553",
+ .name = "rtc-ds1553",
.owner = THIS_MODULE,
},
};
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c
index 67291b0f8283..2e73f0b183b2 100644
--- a/drivers/rtc/rtc-ds1742.c
+++ b/drivers/rtc/rtc-ds1742.c
@@ -160,10 +160,13 @@ static ssize_t ds1742_nvram_write(struct kobject *kobj,
static struct bin_attribute ds1742_nvram_attr = {
.attr = {
.name = "nvram",
- .mode = S_IRUGO | S_IWUGO,
+ .mode = S_IRUGO | S_IWUSR,
},
.read = ds1742_nvram_read,
.write = ds1742_nvram_write,
+ /* REVISIT: size in sysfs won't match actual size... if it's
+ * not a constant, each RTC should have its own attribute.
+ */
};
static int __devinit ds1742_rtc_probe(struct platform_device *pdev)
@@ -251,7 +254,7 @@ static struct platform_driver ds1742_rtc_driver = {
.probe = ds1742_rtc_probe,
.remove = __devexit_p(ds1742_rtc_remove),
.driver = {
- .name = "ds1742",
+ .name = "rtc-ds1742",
.owner = THIS_MODULE,
},
};
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c
index bf60d35f580b..cd0bbc0e8038 100644
--- a/drivers/rtc/rtc-m48t59.c
+++ b/drivers/rtc/rtc-m48t59.c
@@ -353,11 +353,12 @@ static ssize_t m48t59_nvram_write(struct kobject *kobj,
static struct bin_attribute m48t59_nvram_attr = {
.attr = {
.name = "nvram",
- .mode = S_IRUGO | S_IWUGO,
+ .mode = S_IRUGO | S_IWUSR,
.owner = THIS_MODULE,
},
.read = m48t59_nvram_read,
.write = m48t59_nvram_write,
+ .size = M48T59_NVRAM_SIZE,
};
static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
@@ -464,7 +465,7 @@ static int __devexit m48t59_rtc_remove(struct platform_device *pdev)
return 0;
}
-static struct platform_driver m48t59_rtc_platdrv = {
+static struct platform_driver m48t59_rtc_driver = {
.driver = {
.name = "rtc-m48t59",
.owner = THIS_MODULE,
@@ -475,12 +476,12 @@ static struct platform_driver m48t59_rtc_platdrv = {
static int __init m48t59_rtc_init(void)
{
- return platform_driver_register(&m48t59_rtc_platdrv);
+ return platform_driver_register(&m48t59_rtc_driver);
}
static void __exit m48t59_rtc_exit(void)
{
- platform_driver_unregister(&m48t59_rtc_platdrv);
+ platform_driver_unregister(&m48t59_rtc_driver);
}
module_init(m48t59_rtc_init);
diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c
index d48b03374586..556d0e7da35b 100644
--- a/drivers/rtc/rtc-pcf8583.c
+++ b/drivers/rtc/rtc-pcf8583.c
@@ -332,6 +332,9 @@ static int pcf8583_probe(struct i2c_adapter *adap, int addr, int kind)
}
};
+ if (!i2c_check_functionality(adap, I2C_FUNC_I2C))
+ return 0;
+
pcf = kzalloc(sizeof(*pcf), GFP_KERNEL);
if (!pcf)
return -ENOMEM;
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c
index e4bf68ca96f7..2fd49edcc712 100644
--- a/drivers/rtc/rtc-pl031.c
+++ b/drivers/rtc/rtc-pl031.c
@@ -21,11 +21,11 @@
#include <linux/interrupt.h>
#include <linux/string.h>
#include <linux/pm.h>
+#include <linux/bitops.h>
#include <linux/amba/bus.h>
#include <asm/io.h>
-#include <asm/bitops.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/rtc.h>
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index 8c1012b432bb..e2041b4d0c85 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -542,8 +542,6 @@ static int s3c_rtc_probe(struct platform_device *pdev)
/* RTC Power management control */
-static struct timespec s3c_rtc_delta;
-
static int ticnt_save;
static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state)
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
index 0918b787c4dd..6f1e9a9804bc 100644
--- a/drivers/rtc/rtc-sa1100.c
+++ b/drivers/rtc/rtc-sa1100.c
@@ -29,8 +29,8 @@
#include <linux/interrupt.h>
#include <linux/string.h>
#include <linux/pm.h>
+#include <linux/bitops.h>
-#include <asm/bitops.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/rtc.h>
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c
index 78277a118b67..8e8c8b8e81ee 100644
--- a/drivers/rtc/rtc-sh.c
+++ b/drivers/rtc/rtc-sh.c
@@ -351,8 +351,10 @@ static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_wday);
- if (rtc_valid_tm(tm) < 0)
+ if (rtc_valid_tm(tm) < 0) {
dev_err(dev, "invalid date\n");
+ rtc_time_to_tm(0, tm);
+ }
return 0;
}
@@ -588,7 +590,7 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
rtc->rtc_dev = rtc_device_register("sh", &pdev->dev,
&sh_rtc_ops, THIS_MODULE);
- if (IS_ERR(rtc)) {
+ if (IS_ERR(rtc->rtc_dev)) {
ret = PTR_ERR(rtc->rtc_dev);
goto err_badmap;
}
diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c
index 8288b6b2bf2b..a265da7c6ff8 100644
--- a/drivers/rtc/rtc-stk17ta8.c
+++ b/drivers/rtc/rtc-stk17ta8.c
@@ -291,7 +291,7 @@ static ssize_t stk17ta8_nvram_write(struct kobject *kobj,
static struct bin_attribute stk17ta8_nvram_attr = {
.attr = {
.name = "nvram",
- .mode = S_IRUGO | S_IWUGO,
+ .mode = S_IRUGO | S_IWUSR,
.owner = THIS_MODULE,
},
.size = RTC_OFFSET,
diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c
index 69df94b44841..2ae0e8304d3a 100644
--- a/drivers/rtc/rtc-sysfs.c
+++ b/drivers/rtc/rtc-sysfs.c
@@ -73,11 +73,35 @@ rtc_sysfs_show_since_epoch(struct device *dev, struct device_attribute *attr,
return retval;
}
+static ssize_t
+rtc_sysfs_show_max_user_freq(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%d\n", to_rtc_device(dev)->max_user_freq);
+}
+
+static ssize_t
+rtc_sysfs_set_max_user_freq(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t n)
+{
+ struct rtc_device *rtc = to_rtc_device(dev);
+ unsigned long val = simple_strtoul(buf, NULL, 0);
+
+ if (val >= 4096 || val == 0)
+ return -EINVAL;
+
+ rtc->max_user_freq = (int)val;
+
+ return n;
+}
+
static struct device_attribute rtc_attrs[] = {
__ATTR(name, S_IRUGO, rtc_sysfs_show_name, NULL),
__ATTR(date, S_IRUGO, rtc_sysfs_show_date, NULL),
__ATTR(time, S_IRUGO, rtc_sysfs_show_time, NULL),
__ATTR(since_epoch, S_IRUGO, rtc_sysfs_show_since_epoch, NULL),
+ __ATTR(max_user_freq, S_IRUGO | S_IWUSR, rtc_sysfs_show_max_user_freq,
+ rtc_sysfs_set_max_user_freq),
{ },
};
@@ -176,9 +200,8 @@ void rtc_sysfs_add_device(struct rtc_device *rtc)
err = device_create_file(&rtc->dev, &dev_attr_wakealarm);
if (err)
- dev_err(rtc->dev.parent, "failed to create "
- "alarm attribute, %d",
- err);
+ dev_err(rtc->dev.parent,
+ "failed to create alarm attribute, %d\n", err);
}
void rtc_sysfs_del_device(struct rtc_device *rtc)
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c
index 8b9d68f6e016..5b7385e430ea 100644
--- a/drivers/s390/block/dasd_3990_erp.c
+++ b/drivers/s390/block/dasd_3990_erp.c
@@ -40,7 +40,7 @@ struct DCTL_data {
*
* Each bit configuration leading to an action code 2 (Exit with
* programming error or unusual condition indication)
- * are handled as fatal error´s.
+ * are handled as fatal errors.
*
* All other configurations are handled as recoverable errors.
*
@@ -2001,7 +2001,7 @@ dasd_3990_erp_compound_code(struct dasd_ccw_req * erp, char *sense)
switch (sense[28]) {
case 0x17:
/* issue a Diagnostic Control command with an
- * Inhibit Write subcommand and controler modifier */
+ * Inhibit Write subcommand and controller modifier */
erp = dasd_3990_erp_DCTL(erp, 0x20);
break;
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index 859f870552e3..5e083d1f57e7 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -193,6 +193,12 @@ dcssblk_segment_warn(int rc, char* seg_name)
}
}
+static void dcssblk_unregister_callback(struct device *dev)
+{
+ device_unregister(dev);
+ put_device(dev);
+}
+
/*
* device attribute for switching shared/nonshared (exclusive)
* operation (show + store)
@@ -276,8 +282,7 @@ removeseg:
blk_cleanup_queue(dev_info->dcssblk_queue);
dev_info->gd->queue = NULL;
put_disk(dev_info->gd);
- device_unregister(dev);
- put_device(dev);
+ rc = device_schedule_callback(dev, dcssblk_unregister_callback);
out:
up_write(&dcssblk_devices_sem);
return rc;
diff --git a/drivers/s390/char/defkeymap.c b/drivers/s390/char/defkeymap.c
index 564baca01b7c..389346cda6c8 100644
--- a/drivers/s390/char/defkeymap.c
+++ b/drivers/s390/char/defkeymap.c
@@ -150,7 +150,7 @@ char *func_table[MAX_NR_FUNC] = {
NULL,
};
-struct kbdiacr accent_table[MAX_DIACR] = {
+struct kbdiacruc accent_table[MAX_DIACR] = {
{'^', 'c', '\003'}, {'^', 'd', '\004'},
{'^', 'z', '\032'}, {'^', '\012', '\000'},
};
diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c
index f62f9a4e8950..cee4d4e42429 100644
--- a/drivers/s390/char/keyboard.c
+++ b/drivers/s390/char/keyboard.c
@@ -11,6 +11,7 @@
#include <linux/sched.h>
#include <linux/sysrq.h>
+#include <linux/consolemap.h>
#include <linux/kbd_kern.h>
#include <linux/kbd_diacr.h>
#include <asm/uaccess.h>
@@ -82,11 +83,11 @@ kbd_alloc(void) {
if (!kbd->fn_handler)
goto out_func;
kbd->accent_table =
- kmalloc(sizeof(struct kbdiacr)*MAX_DIACR, GFP_KERNEL);
+ kmalloc(sizeof(struct kbdiacruc)*MAX_DIACR, GFP_KERNEL);
if (!kbd->accent_table)
goto out_fn_handler;
memcpy(kbd->accent_table, accent_table,
- sizeof(struct kbdiacr)*MAX_DIACR);
+ sizeof(struct kbdiacruc)*MAX_DIACR);
kbd->accent_table_size = accent_table_size;
return kbd;
@@ -183,8 +184,8 @@ kbd_ebcasc(struct kbd_data *kbd, unsigned char *ebcasc)
* Otherwise, conclude that DIACR was not combining after all,
* queue it and return CH.
*/
-static unsigned char
-handle_diacr(struct kbd_data *kbd, unsigned char ch)
+static unsigned int
+handle_diacr(struct kbd_data *kbd, unsigned int ch)
{
int i, d;
@@ -460,7 +461,6 @@ int
kbd_ioctl(struct kbd_data *kbd, struct file *file,
unsigned int cmd, unsigned long arg)
{
- struct kbdiacrs __user *a;
void __user *argp;
int ct, perm;
@@ -481,17 +481,40 @@ kbd_ioctl(struct kbd_data *kbd, struct file *file,
case KDSKBSENT:
return do_kdgkb_ioctl(kbd, argp, cmd, perm);
case KDGKBDIACR:
- a = argp;
+ {
+ struct kbdiacrs __user *a = argp;
+ struct kbdiacr diacr;
+ int i;
if (put_user(kbd->accent_table_size, &a->kb_cnt))
return -EFAULT;
+ for (i = 0; i < kbd->accent_table_size; i++) {
+ diacr.diacr = kbd->accent_table[i].diacr;
+ diacr.base = kbd->accent_table[i].base;
+ diacr.result = kbd->accent_table[i].result;
+ if (copy_to_user(a->kbdiacr + i, &diacr, sizeof(struct kbdiacr)))
+ return -EFAULT;
+ }
+ return 0;
+ }
+ case KDGKBDIACRUC:
+ {
+ struct kbdiacrsuc __user *a = argp;
+
ct = kbd->accent_table_size;
- if (copy_to_user(a->kbdiacr, kbd->accent_table,
- ct * sizeof(struct kbdiacr)))
+ if (put_user(ct, &a->kb_cnt))
+ return -EFAULT;
+ if (copy_to_user(a->kbdiacruc, kbd->accent_table,
+ ct * sizeof(struct kbdiacruc)))
return -EFAULT;
return 0;
+ }
case KDSKBDIACR:
- a = argp;
+ {
+ struct kbdiacrs __user *a = argp;
+ struct kbdiacr diacr;
+ int i;
+
if (!perm)
return -EPERM;
if (get_user(ct, &a->kb_cnt))
@@ -499,10 +522,31 @@ kbd_ioctl(struct kbd_data *kbd, struct file *file,
if (ct >= MAX_DIACR)
return -EINVAL;
kbd->accent_table_size = ct;
- if (copy_from_user(kbd->accent_table, a->kbdiacr,
- ct * sizeof(struct kbdiacr)))
+ for (i = 0; i < ct; i++) {
+ if (copy_from_user(&diacr, a->kbdiacr + i, sizeof(struct kbdiacr)))
+ return -EFAULT;
+ kbd->accent_table[i].diacr = diacr.diacr;
+ kbd->accent_table[i].base = diacr.base;
+ kbd->accent_table[i].result = diacr.result;
+ }
+ return 0;
+ }
+ case KDSKBDIACRUC:
+ {
+ struct kbdiacrsuc __user *a = argp;
+
+ if (!perm)
+ return -EPERM;
+ if (get_user(ct, &a->kb_cnt))
+ return -EFAULT;
+ if (ct >= MAX_DIACR)
+ return -EINVAL;
+ kbd->accent_table_size = ct;
+ if (copy_from_user(kbd->accent_table, a->kbdiacruc,
+ ct * sizeof(struct kbdiacruc)))
return -EFAULT;
return 0;
+ }
default:
return -ENOIOCTLCMD;
}
diff --git a/drivers/s390/char/keyboard.h b/drivers/s390/char/keyboard.h
index f7bf45c6bf0d..5ccfe9cf126d 100644
--- a/drivers/s390/char/keyboard.h
+++ b/drivers/s390/char/keyboard.h
@@ -25,9 +25,9 @@ struct kbd_data {
unsigned short **key_maps;
char **func_table;
fn_handler_fn **fn_handler;
- struct kbdiacr *accent_table;
+ struct kbdiacruc *accent_table;
unsigned int accent_table_size;
- unsigned char diacr;
+ unsigned int diacr;
unsigned short sysrq;
};
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index 2edd5fb6d3dc..8d1c64a24dec 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -48,8 +48,8 @@ struct raw3270 {
struct timer_list timer; /* Device timer. */
unsigned char *ascebc; /* ascii -> ebcdic table */
- struct class_device *clttydev; /* 3270-class tty device ptr */
- struct class_device *cltubdev; /* 3270-class tub device ptr */
+ struct device *clttydev; /* 3270-class tty device ptr */
+ struct device *cltubdev; /* 3270-class tub device ptr */
struct raw3270_request init_request;
unsigned char init_data[256];
@@ -1107,11 +1107,9 @@ raw3270_delete_device(struct raw3270 *rp)
/* Remove from device chain. */
mutex_lock(&raw3270_mutex);
if (rp->clttydev && !IS_ERR(rp->clttydev))
- class_device_destroy(class3270,
- MKDEV(IBM_TTY3270_MAJOR, rp->minor));
+ device_destroy(class3270, MKDEV(IBM_TTY3270_MAJOR, rp->minor));
if (rp->cltubdev && !IS_ERR(rp->cltubdev))
- class_device_destroy(class3270,
- MKDEV(IBM_FS3270_MAJOR, rp->minor));
+ device_destroy(class3270, MKDEV(IBM_FS3270_MAJOR, rp->minor));
list_del_init(&rp->list);
mutex_unlock(&raw3270_mutex);
@@ -1181,24 +1179,22 @@ static int raw3270_create_attributes(struct raw3270 *rp)
if (rc)
goto out;
- rp->clttydev = class_device_create(class3270, NULL,
- MKDEV(IBM_TTY3270_MAJOR, rp->minor),
- &rp->cdev->dev, "tty%s",
- rp->cdev->dev.bus_id);
+ rp->clttydev = device_create(class3270, &rp->cdev->dev,
+ MKDEV(IBM_TTY3270_MAJOR, rp->minor),
+ "tty%s", rp->cdev->dev.bus_id);
if (IS_ERR(rp->clttydev)) {
rc = PTR_ERR(rp->clttydev);
goto out_ttydev;
}
- rp->cltubdev = class_device_create(class3270, NULL,
- MKDEV(IBM_FS3270_MAJOR, rp->minor),
- &rp->cdev->dev, "tub%s",
- rp->cdev->dev.bus_id);
+ rp->cltubdev = device_create(class3270, &rp->cdev->dev,
+ MKDEV(IBM_FS3270_MAJOR, rp->minor),
+ "tub%s", rp->cdev->dev.bus_id);
if (!IS_ERR(rp->cltubdev))
goto out;
rc = PTR_ERR(rp->cltubdev);
- class_device_destroy(class3270, MKDEV(IBM_TTY3270_MAJOR, rp->minor));
+ device_destroy(class3270, MKDEV(IBM_TTY3270_MAJOR, rp->minor));
out_ttydev:
sysfs_remove_group(&rp->cdev->dev.kobj, &raw3270_attr_group);
diff --git a/drivers/s390/char/sclp_cpi.c b/drivers/s390/char/sclp_cpi.c
index 29fe2a5ec2fe..82a13d9fdfe4 100644
--- a/drivers/s390/char/sclp_cpi.c
+++ b/drivers/s390/char/sclp_cpi.c
@@ -157,7 +157,7 @@ cpi_prepare_req(void)
sclp_ascebc_str(evb->system_name, CPI_LENGTH_SYSTEM_NAME);
EBC_TOUPPER(evb->system_name, CPI_LENGTH_SYSTEM_NAME);
- /* set sytem level */
+ /* set system level */
evb->system_level = LINUX_VERSION_CODE;
/* set sysplex name */
diff --git a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c
index 2e0d29730b67..aa7f166f4034 100644
--- a/drivers/s390/char/tape_class.c
+++ b/drivers/s390/char/tape_class.c
@@ -69,12 +69,9 @@ struct tape_class_device *register_tape_dev(
if (rc)
goto fail_with_cdev;
- tcd->class_device = class_device_create(
- tape_class,
- NULL,
- tcd->char_device->dev,
- device,
- "%s", tcd->device_name
+ tcd->class_device = device_create(tape_class, device,
+ tcd->char_device->dev,
+ "%s", tcd->device_name
);
rc = IS_ERR(tcd->class_device) ? PTR_ERR(tcd->class_device) : 0;
if (rc)
@@ -90,7 +87,7 @@ struct tape_class_device *register_tape_dev(
return tcd;
fail_with_class_device:
- class_device_destroy(tape_class, tcd->char_device->dev);
+ device_destroy(tape_class, tcd->char_device->dev);
fail_with_cdev:
cdev_del(tcd->char_device);
@@ -105,11 +102,9 @@ EXPORT_SYMBOL(register_tape_dev);
void unregister_tape_dev(struct tape_class_device *tcd)
{
if (tcd != NULL && !IS_ERR(tcd)) {
- sysfs_remove_link(
- &tcd->class_device->dev->kobj,
- tcd->mode_name
- );
- class_device_destroy(tape_class, tcd->char_device->dev);
+ sysfs_remove_link(&tcd->class_device->kobj,
+ tcd->mode_name);
+ device_destroy(tape_class, tcd->char_device->dev);
cdev_del(tcd->char_device);
kfree(tcd);
}
diff --git a/drivers/s390/char/tape_class.h b/drivers/s390/char/tape_class.h
index a8bd9b47fad6..e2b5ac918acf 100644
--- a/drivers/s390/char/tape_class.h
+++ b/drivers/s390/char/tape_class.h
@@ -24,8 +24,8 @@
#define TAPECLASS_NAME_LEN 32
struct tape_class_device {
- struct cdev * char_device;
- struct class_device * class_device;
+ struct cdev *char_device;
+ struct device *class_device;
char device_name[TAPECLASS_NAME_LEN];
char mode_name[TAPECLASS_NAME_LEN];
};
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index 12f7a4ce82c1..e0c4c508e121 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -74,7 +74,7 @@ struct vmlogrdr_priv_t {
int dev_in_use; /* 1: already opened, 0: not opened*/
spinlock_t priv_lock;
struct device *device;
- struct class_device *class_device;
+ struct device *class_device;
int autorecording;
int autopurge;
};
@@ -762,12 +762,10 @@ static int vmlogrdr_register_device(struct vmlogrdr_priv_t *priv)
device_unregister(dev);
return ret;
}
- priv->class_device = class_device_create(
- vmlogrdr_class,
- NULL,
- MKDEV(vmlogrdr_major, priv->minor_num),
- dev,
- "%s", dev->bus_id );
+ priv->class_device = device_create(vmlogrdr_class, dev,
+ MKDEV(vmlogrdr_major,
+ priv->minor_num),
+ "%s", dev->bus_id);
if (IS_ERR(priv->class_device)) {
ret = PTR_ERR(priv->class_device);
priv->class_device=NULL;
@@ -783,8 +781,7 @@ static int vmlogrdr_register_device(struct vmlogrdr_priv_t *priv)
static int vmlogrdr_unregister_device(struct vmlogrdr_priv_t *priv)
{
- class_device_destroy(vmlogrdr_class,
- MKDEV(vmlogrdr_major, priv->minor_num));
+ device_destroy(vmlogrdr_class, MKDEV(vmlogrdr_major, priv->minor_num));
if (priv->device != NULL) {
sysfs_remove_group(&priv->device->kobj, &vmlogrdr_attr_group);
device_unregister(priv->device);
diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c
index 42c1f4659adb..297cdceb0ca4 100644
--- a/drivers/s390/cio/chp.c
+++ b/drivers/s390/cio/chp.c
@@ -246,7 +246,7 @@ int chp_add_cmg_attr(struct channel_path *chp)
static ssize_t chp_status_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct channel_path *chp = container_of(dev, struct channel_path, dev);
+ struct channel_path *chp = to_channelpath(dev);
if (!chp)
return 0;
@@ -258,7 +258,7 @@ static ssize_t chp_status_write(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct channel_path *cp = container_of(dev, struct channel_path, dev);
+ struct channel_path *cp = to_channelpath(dev);
char cmd[10];
int num_args;
int error;
@@ -286,7 +286,7 @@ static ssize_t chp_configure_show(struct device *dev,
struct channel_path *cp;
int status;
- cp = container_of(dev, struct channel_path, dev);
+ cp = to_channelpath(dev);
status = chp_info_get_status(cp->chpid);
if (status < 0)
return status;
@@ -308,7 +308,7 @@ static ssize_t chp_configure_write(struct device *dev,
return -EINVAL;
if (val != 0 && val != 1)
return -EINVAL;
- cp = container_of(dev, struct channel_path, dev);
+ cp = to_channelpath(dev);
chp_cfg_schedule(cp->chpid, val);
cfg_wait_idle();
@@ -320,7 +320,7 @@ static DEVICE_ATTR(configure, 0644, chp_configure_show, chp_configure_write);
static ssize_t chp_type_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
- struct channel_path *chp = container_of(dev, struct channel_path, dev);
+ struct channel_path *chp = to_channelpath(dev);
if (!chp)
return 0;
@@ -374,7 +374,7 @@ static void chp_release(struct device *dev)
{
struct channel_path *cp;
- cp = container_of(dev, struct channel_path, dev);
+ cp = to_channelpath(dev);
kfree(cp);
}
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c
index b960f66843e4..f4c132ab39ed 100644
--- a/drivers/s390/cio/cmf.c
+++ b/drivers/s390/cio/cmf.c
@@ -158,7 +158,7 @@ static inline u64 time_to_avg_nsec(u32 value, u32 count)
if (count == 0)
return 0;
- /* value comes in units of 128 µsec */
+ /* value comes in units of 128 µsec */
ret = time_to_nsec(value);
do_div(ret, count);
@@ -343,10 +343,10 @@ static int cmf_copy_block(struct ccw_device *cdev)
if (sch->schib.scsw.fctl & SCSW_FCTL_START_FUNC) {
/* Don't copy if a start function is in progress. */
- if ((!sch->schib.scsw.actl & SCSW_ACTL_SUSPENDED) &&
+ if ((!(sch->schib.scsw.actl & SCSW_ACTL_SUSPENDED)) &&
(sch->schib.scsw.actl &
(SCSW_ACTL_DEVACT | SCSW_ACTL_SCHACT)) &&
- (!sch->schib.scsw.stctl & SCSW_STCTL_SEC_STATUS))
+ (!(sch->schib.scsw.stctl & SCSW_STCTL_SEC_STATUS)))
return -EBUSY;
}
cmb_data = cdev->private->cmb;
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 5d83dd471461..838f7ac0dc32 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -182,6 +182,15 @@ static int css_register_subchannel(struct subchannel *sch)
sch->dev.bus = &css_bus_type;
sch->dev.release = &css_subchannel_release;
sch->dev.groups = subch_attr_groups;
+ /*
+ * We don't want to generate uevents for I/O subchannels that don't
+ * have a working ccw device behind them since they will be
+ * unregistered before they can be used anyway, so we delay the add
+ * uevent until after device recognition was successful.
+ */
+ if (!cio_is_console(sch->schid))
+ /* Console is special, no need to suppress. */
+ sch->dev.uevent_suppress = 1;
css_update_ssd_info(sch);
/* make it known to the system */
ret = css_sch_device_register(sch);
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 7ee57f084a89..74f6b539974a 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -738,7 +738,7 @@ static int io_subchannel_initialize_dev(struct subchannel *sch,
atomic_set(&cdev->private->onoff, 0);
cdev->dev.parent = &sch->dev;
cdev->dev.release = ccw_device_release;
- INIT_LIST_HEAD(&cdev->private->kick_work.entry);
+ INIT_WORK(&cdev->private->kick_work, NULL);
cdev->dev.groups = ccwdev_attr_groups;
/* Do first half of device_register. */
device_initialize(&cdev->dev);
diff --git a/drivers/s390/cio/idset.c b/drivers/s390/cio/idset.c
index 16ea828e99f7..ef7bc0a125ef 100644
--- a/drivers/s390/cio/idset.c
+++ b/drivers/s390/cio/idset.c
@@ -6,7 +6,7 @@
*/
#include <linux/slab.h>
-#include <asm/bitops.h>
+#include <linux/bitops.h>
#include "idset.h"
#include "css.h"
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index 399695f7b1af..3561982749e3 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -59,13 +59,13 @@
* 1.15 Changed for 2.6 Kernel No longer compiles on 2.4 or lower
* 1.25 Added Packing support
*/
-#include <asm/bitops.h>
#include <asm/ccwdev.h>
#include <asm/ccwgroup.h>
#include <asm/debug.h>
#include <asm/idals.h>
#include <asm/io.h>
+#include <linux/bitops.h>
#include <linux/ctype.h>
#include <linux/delay.h>
#include <linux/errno.h>
diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c
index 449937233732..6bf3ebbe985a 100644
--- a/drivers/s390/net/ctcmain.c
+++ b/drivers/s390/net/ctcmain.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
* Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
- * Fixes by : Jochen Röhrig (roehrig@de.ibm.com)
+ * Fixes by : Jochen Röhrig (roehrig@de.ibm.com)
* Arnaldo Carvalho de Melo <acme@conectiva.com.br>
Peter Tiedemann (ptiedem@de.ibm.com)
* Driver Model stuff by : Cornelia Huck <cornelia.huck@de.ibm.com>
@@ -19,7 +19,7 @@
* Dieter Wellerdiek (wel@de.ibm.com)
* Martin Schwidefsky (schwidefsky@de.ibm.com)
* Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
- * Jochen Röhrig (roehrig@de.ibm.com)
+ * Jochen Röhrig (roehrig@de.ibm.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -885,7 +885,7 @@ ch_action_firstio(fsm_instance * fi, int event, void *arg)
}
/**
- * Don´t setup a timer for receiving the initial RX frame
+ * Don't setup a timer for receiving the initial RX frame
* if in compatibility mode, since VM TCP delays the initial
* frame until it has some data to send.
*/
@@ -905,10 +905,10 @@ ch_action_firstio(fsm_instance * fi, int event, void *arg)
ccw_check_return_code(ch, rc, "init IO");
}
/**
- * If in compatibility mode since we don´t setup a timer, we
+ * If in compatibility mode since we don't setup a timer, we
* also signal RX channel up immediately. This enables us
* to send packets early which in turn usually triggers some
- * reply from VM TCP which brings up the RX channel to it´s
+ * reply from VM TCP which brings up the RX channel to it's
* final state.
*/
if ((CHANNEL_DIRECTION(ch->flags) == READ) &&
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index a2d08c9ba3c4..ff999ff0b627 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -6643,7 +6643,8 @@ qeth_netdev_init(struct net_device *dev)
dev->vlan_rx_kill_vid = qeth_vlan_rx_kill_vid;
dev->vlan_rx_add_vid = qeth_vlan_rx_add_vid;
#endif
- dev->header_ops = &qeth_null_ops;
+ if (qeth_get_netdev_flags(card) & IFF_NOARP)
+ dev->header_ops = &qeth_null_ops;
#ifdef CONFIG_QETH_IPV6
/*IPv6 address autoconfiguration stuff*/
diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c
index 3ccca5871fdf..47bb47b48581 100644
--- a/drivers/s390/net/smsgiucv.c
+++ b/drivers/s390/net/smsgiucv.c
@@ -148,6 +148,10 @@ static int __init smsg_init(void)
{
int rc;
+ if (!MACHINE_IS_VM) {
+ rc = -EPROTONOSUPPORT;
+ goto out;
+ }
rc = driver_register(&smsg_driver);
if (rc != 0)
goto out;
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 7507067351bd..00118499018b 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -559,10 +559,9 @@ zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size)
retval = -ENOMEM;
goto out;
}
+ sg_init_table(sg_list->sg, sg_list->count);
for (i = 0, sg = sg_list->sg; i < sg_list->count; i++, sg++) {
- sg->length = min(size, PAGE_SIZE);
- sg->offset = 0;
address = (void *) get_zeroed_page(GFP_KERNEL);
if (address == NULL) {
sg_list->count = i;
@@ -570,7 +569,7 @@ zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size)
retval = -ENOMEM;
goto out;
}
- zfcp_address_to_sg(address, sg);
+ zfcp_address_to_sg(address, sg, min(size, PAGE_SIZE));
size -= sg->length;
}
@@ -1517,13 +1516,13 @@ zfcp_gid_pn_buffers_alloc(struct zfcp_gid_pn_data **gid_pn, mempool_t *pool)
return -ENOMEM;
memset(data, 0, sizeof(*data));
+ sg_init_table(&data->req , 1);
+ sg_init_table(&data->resp , 1);
data->ct.req = &data->req;
data->ct.resp = &data->resp;
data->ct.req_count = data->ct.resp_count = 1;
- zfcp_address_to_sg(&data->ct_iu_req, &data->req);
- zfcp_address_to_sg(&data->ct_iu_resp, &data->resp);
- data->req.length = sizeof(struct ct_iu_gid_pn_req);
- data->resp.length = sizeof(struct ct_iu_gid_pn_resp);
+ zfcp_address_to_sg(&data->ct_iu_req, &data->req, sizeof(struct ct_iu_gid_pn_req));
+ zfcp_address_to_sg(&data->ct_iu_resp, &data->resp, sizeof(struct ct_iu_gid_pn_resp));
*gid_pn = data;
return 0;
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index 16e5563e0c65..e268f79bdbd2 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -34,6 +34,7 @@
#include <linux/slab.h>
#include <linux/mempool.h>
#include <linux/syscalls.h>
+#include <linux/scatterlist.h>
#include <linux/ioctl.h>
#include <scsi/scsi.h>
#include <scsi/scsi_tcq.h>
@@ -62,19 +63,19 @@
static inline void *
zfcp_sg_to_address(struct scatterlist *list)
{
- return (void *) (page_address(list->page) + list->offset);
+ return sg_virt(list);
}
/**
* zfcp_address_to_sg - set up struct scatterlist from kernel address
* @address: kernel address
* @list: struct scatterlist
+ * @size: buffer size
*/
static inline void
-zfcp_address_to_sg(void *address, struct scatterlist *list)
+zfcp_address_to_sg(void *address, struct scatterlist *list, unsigned int size)
{
- list->page = virt_to_page(address);
- list->offset = ((unsigned long) address) & (PAGE_SIZE - 1);
+ sg_set_buf(list, address, size);
}
#define REQUEST_LIST_SIZE 128
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index a6475a2bb8a7..5552b755c08a 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -308,21 +308,23 @@ zfcp_erp_adisc(struct zfcp_port *port)
if (send_els == NULL)
goto nomem;
- send_els->req = kzalloc(sizeof(struct scatterlist), GFP_ATOMIC);
+ send_els->req = kmalloc(sizeof(struct scatterlist), GFP_ATOMIC);
if (send_els->req == NULL)
goto nomem;
+ sg_init_table(send_els->req, 1);
- send_els->resp = kzalloc(sizeof(struct scatterlist), GFP_ATOMIC);
+ send_els->resp = kmalloc(sizeof(struct scatterlist), GFP_ATOMIC);
if (send_els->resp == NULL)
goto nomem;
+ sg_init_table(send_els->resp, 1);
address = (void *) get_zeroed_page(GFP_ATOMIC);
if (address == NULL)
goto nomem;
- zfcp_address_to_sg(address, send_els->req);
+ zfcp_address_to_sg(address, send_els->req, sizeof(struct zfcp_ls_adisc));
address += PAGE_SIZE >> 1;
- zfcp_address_to_sg(address, send_els->resp);
+ zfcp_address_to_sg(address, send_els->resp, sizeof(struct zfcp_ls_adisc_acc));
send_els->req_count = send_els->resp_count = 1;
send_els->adapter = adapter;
@@ -334,9 +336,6 @@ zfcp_erp_adisc(struct zfcp_port *port)
adisc = zfcp_sg_to_address(send_els->req);
send_els->ls_code = adisc->code = ZFCP_LS_ADISC;
- send_els->req->length = sizeof(struct zfcp_ls_adisc);
- send_els->resp->length = sizeof(struct zfcp_ls_adisc_acc);
-
/* acc. to FC-FS, hard_nport_id in ADISC should not be set for ports
without FC-AL-2 capability, so we don't set it */
adisc->wwpn = fc_host_port_name(adapter->scsi_host);
@@ -363,7 +362,7 @@ zfcp_erp_adisc(struct zfcp_port *port)
retval = -ENOMEM;
freemem:
if (address != NULL)
- __free_pages(send_els->req->page, 0);
+ __free_pages(sg_page(send_els->req), 0);
if (send_els != NULL) {
kfree(send_els->req);
kfree(send_els->resp);
@@ -437,7 +436,7 @@ zfcp_erp_adisc_handler(unsigned long data)
out:
zfcp_port_put(port);
- __free_pages(send_els->req->page, 0);
+ __free_pages(sg_page(send_els->req), 0);
kfree(send_els->req);
kfree(send_els->resp);
kfree(send_els);
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
index 3f105fdcf239..51d92b196ee7 100644
--- a/drivers/s390/scsi/zfcp_qdio.c
+++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -590,7 +590,7 @@ zfcp_qdio_sbals_from_segment(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
*/
int
zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
- struct scatterlist *sg, int sg_count, int max_sbals)
+ struct scatterlist *sgl, int sg_count, int max_sbals)
{
int sg_index;
struct scatterlist *sg_segment;
@@ -606,9 +606,7 @@ zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
sbale->flags |= sbtype;
/* process all segements of scatter-gather list */
- for (sg_index = 0, sg_segment = sg, bytes = 0;
- sg_index < sg_count;
- sg_index++, sg_segment++) {
+ for_each_sg(sgl, sg_segment, sg_count, sg_index) {
retval = zfcp_qdio_sbals_from_segment(
fsf_req,
sbtype,
diff --git a/drivers/sbus/char/vfc.h b/drivers/sbus/char/vfc.h
index 63941a259b92..f1aa1389ea4a 100644
--- a/drivers/sbus/char/vfc.h
+++ b/drivers/sbus/char/vfc.h
@@ -126,7 +126,7 @@ struct vfc_dev {
volatile struct vfc_regs __iomem *regs;
struct vfc_regs *phys_regs;
unsigned int control_reg;
- struct semaphore device_lock_sem;
+ struct mutex device_lock_mtx;
int instance;
int busy;
unsigned long which_io;
diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c
index 9269f7fbd363..d4f8fcded51d 100644
--- a/drivers/sbus/char/vfc_dev.c
+++ b/drivers/sbus/char/vfc_dev.c
@@ -22,6 +22,7 @@
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
+#include <linux/mutex.h>
#include <linux/mm.h>
#include <asm/openprom.h>
@@ -54,12 +55,12 @@ static unsigned char saa9051_init_array[VFC_SAA9051_NR] = {
void vfc_lock_device(struct vfc_dev *dev)
{
- down(&dev->device_lock_sem);
+ mutex_lock(&dev->device_lock_mtx);
}
void vfc_unlock_device(struct vfc_dev *dev)
{
- up(&dev->device_lock_sem);
+ mutex_unlock(&dev->device_lock_mtx);
}
@@ -133,7 +134,7 @@ int init_vfc_hw(struct vfc_dev *dev)
int init_vfc_devstruct(struct vfc_dev *dev, int instance)
{
dev->instance=instance;
- init_MUTEX(&dev->device_lock_sem);
+ mutex_init(&dev->device_lock_mtx);
dev->control_reg=0;
dev->busy=0;
return 0;
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index efd9d8d3a890..afb262b4be15 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -1840,7 +1840,7 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
(scsi_bufflen(srb) < TW_MIN_SGL_LENGTH)) {
if (srb->sc_data_direction == DMA_TO_DEVICE || srb->sc_data_direction == DMA_BIDIRECTIONAL) {
struct scatterlist *sg = scsi_sglist(srb);
- char *buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+ char *buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
memcpy(tw_dev->generic_buffer_virt[request_id], buf, sg->length);
kunmap_atomic(buf - sg->offset, KM_IRQ0);
}
@@ -1919,7 +1919,7 @@ static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int re
char *buf;
unsigned long flags = 0;
local_irq_save(flags);
- buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+ buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
memcpy(buf, tw_dev->generic_buffer_virt[request_id], sg->length);
kunmap_atomic(buf - sg->offset, KM_IRQ0);
local_irq_restore(flags);
@@ -1990,6 +1990,7 @@ static struct scsi_host_template driver_template = {
.max_sectors = TW_MAX_SECTORS,
.cmd_per_lun = TW_MAX_CMDS_PER_LUN,
.use_clustering = ENABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
.shost_attrs = twa_host_attrs,
.emulated = 1
};
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index c7995fc216e8..59716ebeb10c 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -1469,7 +1469,7 @@ static void tw_transfer_internal(TW_Device_Extension *tw_dev, int request_id,
struct scatterlist *sg = scsi_sglist(cmd);
local_irq_save(flags);
- buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+ buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
transfer_len = min(sg->length, len);
memcpy(buf, data, transfer_len);
@@ -2261,6 +2261,7 @@ static struct scsi_host_template driver_template = {
.max_sectors = TW_MAX_SECTORS,
.cmd_per_lun = TW_MAX_CMDS_PER_LUN,
.use_clustering = ENABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
.shost_attrs = tw_host_attrs,
.emulated = 1
};
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
index 9b206176f717..49e1ffa4b2ff 100644
--- a/drivers/scsi/BusLogic.c
+++ b/drivers/scsi/BusLogic.c
@@ -3575,6 +3575,7 @@ static struct scsi_host_template Bus_Logic_template = {
.unchecked_isa_dma = 1,
.max_sectors = 128,
.use_clustering = ENABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
};
/*
diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c
index a7f916c0c9cd..1c9078191d9e 100644
--- a/drivers/scsi/FlashPoint.c
+++ b/drivers/scsi/FlashPoint.c
@@ -25,9 +25,6 @@
#define FAILURE 0xFFFFFFFFL
-#define BIT(x) ((unsigned char)(1<<(x))) /* single-bit mask in bit position x */
-#define BITW(x) ((unsigned short)(1<<(x))) /* single-bit mask in bit position x */
-
struct sccb;
typedef void (*CALL_BK_FN) (struct sccb *);
@@ -374,9 +371,9 @@ typedef struct SCCBscam_info {
#define SCAM_ENABLED BIT(2)
#define SCAM_LEVEL2 BIT(3)
-#define RENEGO_ENA BITW(10)
-#define CONNIO_ENA BITW(11)
-#define GREEN_PC_ENA BITW(12)
+#define RENEGO_ENA BIT(10)
+#define CONNIO_ENA BIT(11)
+#define GREEN_PC_ENA BIT(12)
#define AUTO_RATE_00 00
#define AUTO_RATE_05 01
@@ -511,23 +508,23 @@ typedef struct SCCBscam_info {
#define hp_intena 0x40
-#define RESET BITW(7)
-#define PROG_HLT BITW(6)
-#define PARITY BITW(5)
-#define FIFO BITW(4)
-#define SEL BITW(3)
-#define SCAM_SEL BITW(2)
-#define RSEL BITW(1)
-#define TIMEOUT BITW(0)
-#define BUS_FREE BITW(15)
-#define XFER_CNT_0 BITW(14)
-#define PHASE BITW(13)
-#define IUNKWN BITW(12)
-#define ICMD_COMP BITW(11)
-#define ITICKLE BITW(10)
-#define IDO_STRT BITW(9)
-#define ITAR_DISC BITW(8)
-#define AUTO_INT (BITW(12)+BITW(11)+BITW(10)+BITW(9)+BITW(8))
+#define RESET BIT(7)
+#define PROG_HLT BIT(6)
+#define PARITY BIT(5)
+#define FIFO BIT(4)
+#define SEL BIT(3)
+#define SCAM_SEL BIT(2)
+#define RSEL BIT(1)
+#define TIMEOUT BIT(0)
+#define BUS_FREE BIT(15)
+#define XFER_CNT_0 BIT(14)
+#define PHASE BIT(13)
+#define IUNKWN BIT(12)
+#define ICMD_COMP BIT(11)
+#define ITICKLE BIT(10)
+#define IDO_STRT BIT(9)
+#define ITAR_DISC BIT(8)
+#define AUTO_INT (BIT(12)+BIT(11)+BIT(10)+BIT(9)+BIT(8))
#define CLR_ALL_INT 0xFFFF
#define CLR_ALL_INT_1 0xFF00
@@ -674,37 +671,37 @@ typedef struct SCCBscam_info {
#define BIOS_DATA_OFFSET 0x60
#define BIOS_RELATIVE_CARD 0x64
-#define AR3 (BITW(9) + BITW(8))
-#define SDATA BITW(10)
+#define AR3 (BIT(9) + BIT(8))
+#define SDATA BIT(10)
-#define CRD_OP BITW(11) /* Cmp Reg. w/ Data */
+#define CRD_OP BIT(11) /* Cmp Reg. w/ Data */
-#define CRR_OP BITW(12) /* Cmp Reg. w. Reg. */
+#define CRR_OP BIT(12) /* Cmp Reg. w. Reg. */
-#define CPE_OP (BITW(14)+BITW(11)) /* Cmp SCSI phs & Branch EQ */
+#define CPE_OP (BIT(14)+BIT(11)) /* Cmp SCSI phs & Branch EQ */
-#define CPN_OP (BITW(14)+BITW(12)) /* Cmp SCSI phs & Branch NOT EQ */
+#define CPN_OP (BIT(14)+BIT(12)) /* Cmp SCSI phs & Branch NOT EQ */
#define ADATA_OUT 0x00
-#define ADATA_IN BITW(8)
-#define ACOMMAND BITW(10)
-#define ASTATUS (BITW(10)+BITW(8))
-#define AMSG_OUT (BITW(10)+BITW(9))
-#define AMSG_IN (BITW(10)+BITW(9)+BITW(8))
+#define ADATA_IN BIT(8)
+#define ACOMMAND BIT(10)
+#define ASTATUS (BIT(10)+BIT(8))
+#define AMSG_OUT (BIT(10)+BIT(9))
+#define AMSG_IN (BIT(10)+BIT(9)+BIT(8))
-#define BRH_OP BITW(13) /* Branch */
+#define BRH_OP BIT(13) /* Branch */
#define ALWAYS 0x00
-#define EQUAL BITW(8)
-#define NOT_EQ BITW(9)
+#define EQUAL BIT(8)
+#define NOT_EQ BIT(9)
-#define TCB_OP (BITW(13)+BITW(11)) /* Test condition & branch */
+#define TCB_OP (BIT(13)+BIT(11)) /* Test condition & branch */
-#define FIFO_0 BITW(10)
+#define FIFO_0 BIT(10)
-#define MPM_OP BITW(15) /* Match phase and move data */
+#define MPM_OP BIT(15) /* Match phase and move data */
-#define MRR_OP BITW(14) /* Move DReg. to Reg. */
+#define MRR_OP BIT(14) /* Move DReg. to Reg. */
#define S_IDREG (BIT(2)+BIT(1)+BIT(0))
@@ -712,9 +709,9 @@ typedef struct SCCBscam_info {
#define D_AR1 BIT(0)
#define D_BUCKET (BIT(2) + BIT(1) + BIT(0))
-#define RAT_OP (BITW(14)+BITW(13)+BITW(11))
+#define RAT_OP (BIT(14)+BIT(13)+BIT(11))
-#define SSI_OP (BITW(15)+BITW(11))
+#define SSI_OP (BIT(15)+BIT(11))
#define SSI_ITAR_DISC (ITAR_DISC >> 8)
#define SSI_IDO_STRT (IDO_STRT >> 8)
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 30905cebefbb..a6676be87843 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -172,12 +172,12 @@ config CHR_DEV_SCH
don't need this for those tiny 6-slot cdrom changers. Media
changers are listed as "Type: Medium Changer" in /proc/scsi/scsi.
If you have such hardware and want to use it with linux, say Y
- here. Check <file:Documentation/scsi-changer.txt> for details.
+ here. Check <file:Documentation/scsi/scsi-changer.txt> for details.
If you want to compile this as a module ( = code which can be
inserted in and removed from the running kernel whenever you want),
say M here and read <file:Documentation/kbuild/modules.txt> and
- <file:Documentation/scsi.txt>. The module will be called ch.o.
+ <file:Documentation/scsi/scsi.txt>. The module will be called ch.o.
If unsure, say N.
@@ -521,7 +521,7 @@ config SCSI_DPT_I2O
config SCSI_ADVANSYS
tristate "AdvanSys SCSI support"
- depends on SCSI
+ depends on SCSI && VIRT_TO_BUS
depends on ISA || EISA || PCI
help
This is a driver for all SCSI host adapters manufactured by
@@ -725,7 +725,7 @@ config SCSI_FD_MCS
config SCSI_GDTH
tristate "Intel/ICP (former GDT SCSI Disk Array) RAID Controller support"
- depends on (ISA || EISA || PCI) && SCSI && ISA_DMA_API
+ depends on (ISA || EISA || PCI) && SCSI && ISA_DMA_API && PCI_LEGACY
---help---
Formerly called GDT SCSI Disk Array Controller Support.
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 6141389dcdb2..2e6129f13d38 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -115,7 +115,6 @@ obj-$(CONFIG_SCSI_QLOGICPTI) += qlogicpti.o
obj-$(CONFIG_BLK_DEV_IDESCSI) += ide-scsi.o
obj-$(CONFIG_SCSI_MESH) += mesh.o
obj-$(CONFIG_SCSI_MAC53C94) += mac53c94.o
-obj-$(CONFIG_SCSI_PLUTO) += pluto.o
obj-$(CONFIG_SCSI_DECNCR) += NCR53C9x.o dec_esp.o
obj-$(CONFIG_BLK_DEV_3W_XXXX_RAID) += 3w-xxxx.o
obj-$(CONFIG_SCSI_3W_9XXX) += 3w-9xxx.o
@@ -123,7 +122,6 @@ obj-$(CONFIG_SCSI_PPA) += ppa.o
obj-$(CONFIG_SCSI_IMM) += imm.o
obj-$(CONFIG_JAZZ_ESP) += esp_scsi.o jazz_esp.o
obj-$(CONFIG_SUN3X_ESP) += NCR53C9x.o sun3x_esp.o
-obj-$(CONFIG_SCSI_FCAL) += fcal.o
obj-$(CONFIG_SCSI_LASI700) += 53c700.o lasi700.o
obj-$(CONFIG_SCSI_SNI_53C710) += 53c700.o sni_53c710.o
obj-$(CONFIG_SCSI_NSP32) += nsp32.o
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index 988f0bc5eda5..2597209183d0 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -298,8 +298,7 @@ static __inline__ void initialize_SCp(Scsi_Cmnd * cmd)
if (cmd->use_sg) {
cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer;
cmd->SCp.buffers_residual = cmd->use_sg - 1;
- cmd->SCp.ptr = page_address(cmd->SCp.buffer->page)+
- cmd->SCp.buffer->offset;
+ cmd->SCp.ptr = sg_virt(cmd->SCp.buffer);
cmd->SCp.this_residual = cmd->SCp.buffer->length;
} else {
cmd->SCp.buffer = NULL;
@@ -2143,8 +2142,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
++cmd->SCp.buffer;
--cmd->SCp.buffers_residual;
cmd->SCp.this_residual = cmd->SCp.buffer->length;
- cmd->SCp.ptr = page_address(cmd->SCp.buffer->page)+
- cmd->SCp.buffer->offset;
+ cmd->SCp.ptr = sg_virt(cmd->SCp.buffer);
dprintk(NDEBUG_INFORMATION, ("scsi%d : %d bytes and %d buffers left\n", instance->host_no, cmd->SCp.this_residual, cmd->SCp.buffers_residual));
}
/*
diff --git a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c
index 96e8e29aa05d..5b0efc903918 100644
--- a/drivers/scsi/NCR53C9x.c
+++ b/drivers/scsi/NCR53C9x.c
@@ -927,7 +927,7 @@ static void esp_get_dmabufs(struct NCR_ESP *esp, Scsi_Cmnd *sp)
esp->dma_mmu_get_scsi_sgl(esp, sp);
else
sp->SCp.ptr =
- (char *) virt_to_phys((page_address(sp->SCp.buffer->page) + sp->SCp.buffer->offset));
+ (char *) virt_to_phys(sg_virt(sp->SCp.buffer));
}
}
@@ -1748,7 +1748,7 @@ static inline void advance_sg(struct NCR_ESP *esp, Scsi_Cmnd *sp)
if (esp->dma_advance_sg)
esp->dma_advance_sg (sp);
else
- sp->SCp.ptr = (char *) virt_to_phys((page_address(sp->SCp.buffer->page) + sp->SCp.buffer->offset));
+ sp->SCp.ptr = (char *) virt_to_phys(sg_virt(sp->SCp.buffer));
}
diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c
index eda8c48f6be7..137d065db3da 100644
--- a/drivers/scsi/NCR53c406a.c
+++ b/drivers/scsi/NCR53c406a.c
@@ -875,8 +875,7 @@ static void NCR53c406a_intr(void *dev_id)
outb(TRANSFER_INFO | DMA_OP, CMD_REG);
#if USE_PIO
scsi_for_each_sg(current_SC, sg, scsi_sg_count(current_SC), i) {
- NCR53c406a_pio_write(page_address(sg->page) + sg->offset,
- sg->length);
+ NCR53c406a_pio_write(sg_virt(sg), sg->length);
}
REG0;
#endif /* USE_PIO */
@@ -897,8 +896,7 @@ static void NCR53c406a_intr(void *dev_id)
outb(TRANSFER_INFO | DMA_OP, CMD_REG);
#if USE_PIO
scsi_for_each_sg(current_SC, sg, scsi_sg_count(current_SC), i) {
- NCR53c406a_pio_read(page_address(sg->page) + sg->offset,
- sg->length);
+ NCR53c406a_pio_read(sg_virt(sg), sg->length);
}
REG0;
#endif /* USE_PIO */
@@ -1066,7 +1064,8 @@ static struct scsi_host_template driver_template =
.sg_tablesize = 32 /*SG_ALL*/ /*SG_NONE*/,
.cmd_per_lun = 1 /* commands per lun */,
.unchecked_isa_dma = 1 /* unchecked_isa_dma */,
- .use_clustering = ENABLE_CLUSTERING
+ .use_clustering = ENABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
};
#include "scsi_module.c"
diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c
index f608d4a1d6da..d3a6d15fb77a 100644
--- a/drivers/scsi/a100u2w.c
+++ b/drivers/scsi/a100u2w.c
@@ -1071,6 +1071,7 @@ static struct scsi_host_template inia100_template = {
.sg_tablesize = SG_ALL,
.cmd_per_lun = 1,
.use_clustering = ENABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
};
static int __devinit inia100_probe_one(struct pci_dev *pdev,
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index 80e448d0f3db..a77ab8d693d4 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -356,7 +356,7 @@ static void aac_internal_transfer(struct scsi_cmnd *scsicmd, void *data, unsigne
int transfer_len;
struct scatterlist *sg = scsi_sglist(scsicmd);
- buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+ buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
transfer_len = min(sg->length, len + offset);
transfer_len -= offset;
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 03b51025a8f4..9abba8b90f70 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -1526,7 +1526,7 @@ struct aac_mntent {
__le32 capacityhigh;
};
-#define FSCS_NOTCLEAN 0x0001 /* fsck is neccessary before mounting */
+#define FSCS_NOTCLEAN 0x0001 /* fsck is necessary before mounting */
#define FSCS_READONLY 0x0002 /* possible result of broken mirror */
#define FSCS_HIDDEN 0x0004 /* should be ignored - set during a clear */
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index 72b0393b4596..1e6d7a9c75bf 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -391,7 +391,7 @@ static int close_getadapter_fib(struct aac_dev * dev, void __user *arg)
/*
* Extract the fibctx from the input parameters
*/
- if (fibctx->unique == (u32)(ptrdiff_t)arg) /* We found a winner */
+ if (fibctx->unique == (u32)(uintptr_t)arg) /* We found a winner */
break;
entry = entry->next;
fibctx = NULL;
@@ -590,7 +590,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
}
addr = (u64)upsg->sg[i].addr[0];
addr += ((u64)upsg->sg[i].addr[1]) << 32;
- sg_user[i] = (void __user *)(ptrdiff_t)addr;
+ sg_user[i] = (void __user *)(uintptr_t)addr;
sg_list[i] = p; // save so we can clean up later
sg_indx = i;
@@ -633,7 +633,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
rcode = -ENOMEM;
goto cleanup;
}
- sg_user[i] = (void __user *)(ptrdiff_t)usg->sg[i].addr;
+ sg_user[i] = (void __user *)(uintptr_t)usg->sg[i].addr;
sg_list[i] = p; // save so we can clean up later
sg_indx = i;
@@ -664,7 +664,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
if (actual_fibsize64 == fibsize) {
struct user_sgmap64* usg = (struct user_sgmap64 *)upsg;
for (i = 0; i < upsg->count; i++) {
- u64 addr;
+ uintptr_t addr;
void* p;
/* Does this really need to be GFP_DMA? */
p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA);
@@ -676,7 +676,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
}
addr = (u64)usg->sg[i].addr[0];
addr += ((u64)usg->sg[i].addr[1]) << 32;
- sg_user[i] = (void __user *)(ptrdiff_t)addr;
+ sg_user[i] = (void __user *)addr;
sg_list[i] = p; // save so we can clean up later
sg_indx = i;
@@ -704,7 +704,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
rcode = -ENOMEM;
goto cleanup;
}
- sg_user[i] = (void __user *)(ptrdiff_t)upsg->sg[i].addr;
+ sg_user[i] = (void __user *)(uintptr_t)upsg->sg[i].addr;
sg_list[i] = p; // save so we can clean up later
sg_indx = i;
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index 3009ad8c4073..8736813a0296 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -110,7 +110,7 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
/*
* Align the beginning of Headers to commalign
*/
- align = (commalign - ((ptrdiff_t)(base) & (commalign - 1)));
+ align = (commalign - ((uintptr_t)(base) & (commalign - 1)));
base = base + align;
phys = phys + align;
/*
diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c
index fcd25f7d0bc6..e6032ffc66a6 100644
--- a/drivers/scsi/aacraid/dpcsup.c
+++ b/drivers/scsi/aacraid/dpcsup.c
@@ -254,7 +254,7 @@ unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index)
kfree (fib);
return 1;
}
- memcpy(hw_fib, (struct hw_fib *)(((ptrdiff_t)(dev->regs.sa)) +
+ memcpy(hw_fib, (struct hw_fib *)(((uintptr_t)(dev->regs.sa)) +
(index & ~0x00000002L)), sizeof(struct hw_fib));
INIT_LIST_HEAD(&fib->fiblink);
fib->type = FSAFS_NTC_FIB_CONTEXT;
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index a7f42a17b5c7..038980be763d 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -944,6 +944,7 @@ static struct scsi_host_template aac_driver_template = {
.cmd_per_lun = AAC_NUM_IO_FIB,
#endif
.use_clustering = ENABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
.emulated = 1,
};
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
index f08e71e0205a..ea8c69947644 100644
--- a/drivers/scsi/aha152x.c
+++ b/drivers/scsi/aha152x.c
@@ -1,6 +1,6 @@
/* aha152x.c -- Adaptec AHA-152x driver
- * Author: Jürgen E. Fischer, fischer@norbit.de
- * Copyright 1993-2004 Jürgen E. Fischer
+ * Author: Jürgen E. Fischer, fischer@norbit.de
+ * Copyright 1993-2004 Jürgen E. Fischer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -357,7 +357,7 @@ enum {
check_condition = 0x0800, /* requesting sense after CHECK CONDITION */
};
-MODULE_AUTHOR("Jürgen Fischer");
+MODULE_AUTHOR("Jürgen Fischer");
MODULE_DESCRIPTION(AHA152X_REVID);
MODULE_LICENSE("GPL");
@@ -613,7 +613,7 @@ struct aha152x_scdata {
#define SCNEXT(SCpnt) SCDATA(SCpnt)->next
#define SCSEM(SCpnt) SCDATA(SCpnt)->done
-#define SG_ADDRESS(buffer) ((char *) (page_address((buffer)->page)+(buffer)->offset))
+#define SG_ADDRESS(buffer) ((char *) sg_virt((buffer)))
/* state handling */
static void seldi_run(struct Scsi_Host *shpnt);
diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
index cbbfbc9f3e0f..bbcc2c52d79f 100644
--- a/drivers/scsi/aha1542.c
+++ b/drivers/scsi/aha1542.c
@@ -49,7 +49,7 @@
#include "aha1542.h"
#define SCSI_BUF_PA(address) isa_virt_to_bus(address)
-#define SCSI_SG_PA(sgent) (isa_page_to_bus((sgent)->page) + (sgent)->offset)
+#define SCSI_SG_PA(sgent) (isa_page_to_bus(sg_page((sgent))) + (sgent)->offset)
static void BAD_DMA(void *address, unsigned int length)
{
@@ -61,15 +61,14 @@ static void BAD_DMA(void *address, unsigned int length)
}
static void BAD_SG_DMA(Scsi_Cmnd * SCpnt,
- struct scatterlist *sgpnt,
+ struct scatterlist *sgp,
int nseg,
int badseg)
{
printk(KERN_CRIT "sgpnt[%d:%d] page %p/0x%llx length %u\n",
- badseg, nseg,
- page_address(sgpnt[badseg].page) + sgpnt[badseg].offset,
- (unsigned long long)SCSI_SG_PA(&sgpnt[badseg]),
- sgpnt[badseg].length);
+ badseg, nseg, sg_virt(sgp),
+ (unsigned long long)SCSI_SG_PA(sgp),
+ sgp->length);
/*
* Not safe to continue.
@@ -691,7 +690,7 @@ static int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
memcpy(ccb[mbo].cdb, cmd, ccb[mbo].cdblen);
if (SCpnt->use_sg) {
- struct scatterlist *sgpnt;
+ struct scatterlist *sg;
struct chain *cptr;
#ifdef DEBUG
unsigned char *ptr;
@@ -699,23 +698,20 @@ static int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
int i;
ccb[mbo].op = 2; /* SCSI Initiator Command w/scatter-gather */
SCpnt->host_scribble = kmalloc(512, GFP_KERNEL | GFP_DMA);
- sgpnt = (struct scatterlist *) SCpnt->request_buffer;
cptr = (struct chain *) SCpnt->host_scribble;
if (cptr == NULL) {
/* free the claimed mailbox slot */
HOSTDATA(SCpnt->device->host)->SCint[mbo] = NULL;
return SCSI_MLQUEUE_HOST_BUSY;
}
- for (i = 0; i < SCpnt->use_sg; i++) {
- if (sgpnt[i].length == 0 || SCpnt->use_sg > 16 ||
- (((int) sgpnt[i].offset) & 1) || (sgpnt[i].length & 1)) {
+ scsi_for_each_sg(SCpnt, sg, SCpnt->use_sg, i) {
+ if (sg->length == 0 || SCpnt->use_sg > 16 ||
+ (((int) sg->offset) & 1) || (sg->length & 1)) {
unsigned char *ptr;
printk(KERN_CRIT "Bad segment list supplied to aha1542.c (%d, %d)\n", SCpnt->use_sg, i);
- for (i = 0; i < SCpnt->use_sg; i++) {
+ scsi_for_each_sg(SCpnt, sg, SCpnt->use_sg, i) {
printk(KERN_CRIT "%d: %p %d\n", i,
- (page_address(sgpnt[i].page) +
- sgpnt[i].offset),
- sgpnt[i].length);
+ sg_virt(sg), sg->length);
};
printk(KERN_CRIT "cptr %x: ", (unsigned int) cptr);
ptr = (unsigned char *) &cptr[i];
@@ -723,10 +719,10 @@ static int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
printk("%02x ", ptr[i]);
panic("Foooooooood fight!");
};
- any2scsi(cptr[i].dataptr, SCSI_SG_PA(&sgpnt[i]));
- if (SCSI_SG_PA(&sgpnt[i]) + sgpnt[i].length - 1 > ISA_DMA_THRESHOLD)
- BAD_SG_DMA(SCpnt, sgpnt, SCpnt->use_sg, i);
- any2scsi(cptr[i].datalen, sgpnt[i].length);
+ any2scsi(cptr[i].dataptr, SCSI_SG_PA(sg));
+ if (SCSI_SG_PA(sg) + sg->length - 1 > ISA_DMA_THRESHOLD)
+ BAD_SG_DMA(SCpnt, sg, SCpnt->use_sg, i);
+ any2scsi(cptr[i].datalen, sg->length);
};
any2scsi(ccb[mbo].datalen, SCpnt->use_sg * sizeof(struct chain));
any2scsi(ccb[mbo].dataptr, SCSI_BUF_PA(cptr));
diff --git a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c
index e4a4f3a965d9..f6722fd46008 100644
--- a/drivers/scsi/aha1740.c
+++ b/drivers/scsi/aha1740.c
@@ -563,6 +563,7 @@ static struct scsi_host_template aha1740_template = {
.sg_tablesize = AHA1740_SCATTER,
.cmd_per_lun = AHA1740_CMDLUN,
.use_clustering = ENABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
.eh_abort_handler = aha1740_eh_abort_handler,
};
diff --git a/drivers/scsi/aic7xxx/aic7770.c b/drivers/scsi/aic7xxx/aic7770.c
index c4d17231c828..6d86a9be538f 100644
--- a/drivers/scsi/aic7xxx/aic7770.c
+++ b/drivers/scsi/aic7xxx/aic7770.c
@@ -60,8 +60,6 @@
#define ID_OLV_274xD 0x04907783 /* Olivetti OEM (Differential) */
static int aic7770_chip_init(struct ahc_softc *ahc);
-static int aic7770_suspend(struct ahc_softc *ahc);
-static int aic7770_resume(struct ahc_softc *ahc);
static int aha2840_load_seeprom(struct ahc_softc *ahc);
static ahc_device_setup_t ahc_aic7770_VL_setup;
static ahc_device_setup_t ahc_aic7770_EISA_setup;
@@ -155,8 +153,6 @@ aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io)
return (error);
ahc->bus_chip_init = aic7770_chip_init;
- ahc->bus_suspend = aic7770_suspend;
- ahc->bus_resume = aic7770_resume;
error = ahc_reset(ahc, /*reinit*/FALSE);
if (error != 0)
@@ -272,18 +268,6 @@ aic7770_chip_init(struct ahc_softc *ahc)
return (ahc_chip_init(ahc));
}
-static int
-aic7770_suspend(struct ahc_softc *ahc)
-{
- return (ahc_suspend(ahc));
-}
-
-static int
-aic7770_resume(struct ahc_softc *ahc)
-{
- return (ahc_resume(ahc));
-}
-
/*
* Read the 284x SEEPROM.
*/
diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h
index 27adbb294ac1..ce638aa6005a 100644
--- a/drivers/scsi/aic7xxx/aic79xx.h
+++ b/drivers/scsi/aic7xxx/aic79xx.h
@@ -1003,8 +1003,15 @@ struct ahd_suspend_channel_state {
uint8_t seqctl;
};
+struct ahd_suspend_pci_state {
+ uint32_t devconfig;
+ uint8_t command;
+ uint8_t csize_lattime;
+};
+
struct ahd_suspend_state {
struct ahd_suspend_channel_state channel[2];
+ struct ahd_suspend_pci_state pci_state;
uint8_t optionmode;
uint8_t dscommand0;
uint8_t dspcistatus;
@@ -1333,6 +1340,8 @@ struct ahd_pci_identity *ahd_find_pci_device(ahd_dev_softc_t);
int ahd_pci_config(struct ahd_softc *,
struct ahd_pci_identity *);
int ahd_pci_test_register_access(struct ahd_softc *);
+void ahd_pci_suspend(struct ahd_softc *);
+void ahd_pci_resume(struct ahd_softc *);
/************************** SCB and SCB queue management **********************/
void ahd_qinfifo_requeue_tail(struct ahd_softc *ahd,
@@ -1343,6 +1352,8 @@ struct ahd_softc *ahd_alloc(void *platform_arg, char *name);
int ahd_softc_init(struct ahd_softc *);
void ahd_controller_info(struct ahd_softc *ahd, char *buf);
int ahd_init(struct ahd_softc *ahd);
+int ahd_suspend(struct ahd_softc *ahd);
+void ahd_resume(struct ahd_softc *ahd);
int ahd_default_config(struct ahd_softc *ahd);
int ahd_parse_vpddata(struct ahd_softc *ahd,
struct vpd_config *vpd);
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c
index 05f692bd0adc..a7dd8cdda472 100644
--- a/drivers/scsi/aic7xxx/aic79xx_core.c
+++ b/drivers/scsi/aic7xxx/aic79xx_core.c
@@ -7175,7 +7175,6 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd)
ahd->flags &= ~AHD_ALL_INTERRUPTS;
}
-#if 0
int
ahd_suspend(struct ahd_softc *ahd)
{
@@ -7189,19 +7188,15 @@ ahd_suspend(struct ahd_softc *ahd)
ahd_shutdown(ahd);
return (0);
}
-#endif /* 0 */
-#if 0
-int
+void
ahd_resume(struct ahd_softc *ahd)
{
ahd_reset(ahd, /*reinit*/TRUE);
ahd_intr_enable(ahd, TRUE);
ahd_restart(ahd);
- return (0);
}
-#endif /* 0 */
/************************** Busy Target Table *********************************/
/*
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index a055a96e3ad3..2d020405480c 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -315,8 +315,8 @@ uint32_t aic79xx_slowcrc;
*/
static char *aic79xx = NULL;
-MODULE_AUTHOR("Maintainer: Justin T. Gibbs <gibbs@scsiguy.com>");
-MODULE_DESCRIPTION("Adaptec Aic790X U320 SCSI Host Bus Adapter driver");
+MODULE_AUTHOR("Maintainer: Hannes Reinecke <hare@suse.de>");
+MODULE_DESCRIPTION("Adaptec AIC790X U320 SCSI Host Bus Adapter driver");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_VERSION(AIC79XX_DRIVER_VERSION);
module_param(aic79xx, charp, 0444);
@@ -766,6 +766,7 @@ struct scsi_host_template aic79xx_driver_template = {
.max_sectors = 8192,
.cmd_per_lun = 2,
.use_clustering = ENABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
.slave_alloc = ahd_linux_slave_alloc,
.slave_configure = ahd_linux_slave_configure,
.target_alloc = ahd_linux_target_alloc,
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
index c62ce41f2793..66f0259edb69 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
@@ -50,6 +50,8 @@ static int ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd,
static int ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd,
u_long *bus_addr,
uint8_t __iomem **maddr);
+static int ahd_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg);
+static int ahd_linux_pci_dev_resume(struct pci_dev *pdev);
static void ahd_linux_pci_dev_remove(struct pci_dev *pdev);
/* Define the macro locally since it's different for different class of chips.
@@ -86,10 +88,58 @@ MODULE_DEVICE_TABLE(pci, ahd_linux_pci_id_table);
static struct pci_driver aic79xx_pci_driver = {
.name = "aic79xx",
.probe = ahd_linux_pci_dev_probe,
+#ifdef CONFIG_PM
+ .suspend = ahd_linux_pci_dev_suspend,
+ .resume = ahd_linux_pci_dev_resume,
+#endif
.remove = ahd_linux_pci_dev_remove,
.id_table = ahd_linux_pci_id_table
};
+static int
+ahd_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg)
+{
+ struct ahd_softc *ahd = pci_get_drvdata(pdev);
+ int rc;
+
+ if ((rc = ahd_suspend(ahd)))
+ return rc;
+
+ ahd_pci_suspend(ahd);
+
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
+
+ if (mesg.event == PM_EVENT_SUSPEND)
+ pci_set_power_state(pdev, PCI_D3hot);
+
+ return rc;
+}
+
+static int
+ahd_linux_pci_dev_resume(struct pci_dev *pdev)
+{
+ struct ahd_softc *ahd = pci_get_drvdata(pdev);
+ int rc;
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+
+ if ((rc = pci_enable_device(pdev))) {
+ dev_printk(KERN_ERR, &pdev->dev,
+ "failed to enable device after resume (%d)\n", rc);
+ return rc;
+ }
+
+ pci_set_master(pdev);
+
+ ahd_pci_resume(ahd);
+
+ ahd_resume(ahd);
+
+ return rc;
+}
+
static void
ahd_linux_pci_dev_remove(struct pci_dev *pdev)
{
diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c
index 0bada0028aa0..7a203a90601a 100644
--- a/drivers/scsi/aic7xxx/aic79xx_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_pci.c
@@ -389,6 +389,33 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
return error;
}
+void
+ahd_pci_suspend(struct ahd_softc *ahd)
+{
+ /*
+ * Save chip register configuration data for chip resets
+ * that occur during runtime and resume events.
+ */
+ ahd->suspend_state.pci_state.devconfig =
+ ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4);
+ ahd->suspend_state.pci_state.command =
+ ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/1);
+ ahd->suspend_state.pci_state.csize_lattime =
+ ahd_pci_read_config(ahd->dev_softc, CSIZE_LATTIME, /*bytes*/1);
+
+}
+
+void
+ahd_pci_resume(struct ahd_softc *ahd)
+{
+ ahd_pci_write_config(ahd->dev_softc, DEVCONFIG,
+ ahd->suspend_state.pci_state.devconfig, /*bytes*/4);
+ ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND,
+ ahd->suspend_state.pci_state.command, /*bytes*/1);
+ ahd_pci_write_config(ahd->dev_softc, CSIZE_LATTIME,
+ ahd->suspend_state.pci_state.csize_lattime, /*bytes*/1);
+}
+
/*
* Perform some simple tests that should catch situations where
* our registers are invalidly mapped.
diff --git a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h
index e1bd57b9f23d..3d4e42d90452 100644
--- a/drivers/scsi/aic7xxx/aic7xxx.h
+++ b/drivers/scsi/aic7xxx/aic7xxx.h
@@ -962,16 +962,6 @@ struct ahc_softc {
ahc_bus_chip_init_t bus_chip_init;
/*
- * Bus specific suspend routine.
- */
- ahc_bus_suspend_t bus_suspend;
-
- /*
- * Bus specific resume routine.
- */
- ahc_bus_resume_t bus_resume;
-
- /*
* Target mode related state kept on a per enabled lun basis.
* Targets that are not enabled will have null entries.
* As an initiator, we keep one target entry for our initiator
@@ -1153,6 +1143,7 @@ struct ahc_pci_identity *ahc_find_pci_device(ahc_dev_softc_t);
int ahc_pci_config(struct ahc_softc *,
struct ahc_pci_identity *);
int ahc_pci_test_register_access(struct ahc_softc *);
+void ahc_pci_resume(struct ahc_softc *ahc);
/*************************** EISA/VL Front End ********************************/
struct aic7770_identity *aic7770_find_device(uint32_t);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index 2e9c38f2e8a6..390b0fc991c5 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -335,8 +335,8 @@ static uint32_t aic7xxx_periodic_otag;
*/
static char *aic7xxx = NULL;
-MODULE_AUTHOR("Maintainer: Justin T. Gibbs <gibbs@scsiguy.com>");
-MODULE_DESCRIPTION("Adaptec Aic77XX/78XX SCSI Host Bus Adapter driver");
+MODULE_AUTHOR("Maintainer: Hannes Reinecke <hare@suse.de>");
+MODULE_DESCRIPTION("Adaptec AIC77XX/78XX SCSI Host Bus Adapter driver");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_VERSION(AIC7XXX_DRIVER_VERSION);
module_param(aic7xxx, charp, 0444);
@@ -747,6 +747,7 @@ struct scsi_host_template aic7xxx_driver_template = {
.max_sectors = 8192,
.cmd_per_lun = 2,
.use_clustering = ENABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
.slave_alloc = ahc_linux_slave_alloc,
.slave_configure = ahc_linux_slave_configure,
.target_alloc = ahc_linux_target_alloc,
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
index ea5687df732d..4488946cff2e 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
@@ -49,6 +49,8 @@ static int ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc,
static int ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc,
u_long *bus_addr,
uint8_t __iomem **maddr);
+static int ahc_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg);
+static int ahc_linux_pci_dev_resume(struct pci_dev *pdev);
static void ahc_linux_pci_dev_remove(struct pci_dev *pdev);
/* Define the macro locally since it's different for different class of chips.
@@ -133,10 +135,54 @@ MODULE_DEVICE_TABLE(pci, ahc_linux_pci_id_table);
static struct pci_driver aic7xxx_pci_driver = {
.name = "aic7xxx",
.probe = ahc_linux_pci_dev_probe,
+#ifdef CONFIG_PM
+ .suspend = ahc_linux_pci_dev_suspend,
+ .resume = ahc_linux_pci_dev_resume,
+#endif
.remove = ahc_linux_pci_dev_remove,
.id_table = ahc_linux_pci_id_table
};
+static int
+ahc_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg)
+{
+ struct ahc_softc *ahc = pci_get_drvdata(pdev);
+ int rc;
+
+ if ((rc = ahc_suspend(ahc)))
+ return rc;
+
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
+
+ if (mesg.event == PM_EVENT_SUSPEND)
+ pci_set_power_state(pdev, PCI_D3hot);
+
+ return rc;
+}
+
+static int
+ahc_linux_pci_dev_resume(struct pci_dev *pdev)
+{
+ struct ahc_softc *ahc = pci_get_drvdata(pdev);
+ int rc;
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+
+ if ((rc = pci_enable_device(pdev))) {
+ dev_printk(KERN_ERR, &pdev->dev,
+ "failed to enable device after resume (%d)\n", rc);
+ return rc;
+ }
+
+ pci_set_master(pdev);
+
+ ahc_pci_resume(ahc);
+
+ return (ahc_resume(ahc));
+}
+
static void
ahc_linux_pci_dev_remove(struct pci_dev *pdev)
{
diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c
index 09c8172c9e5e..ae35937b8055 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_pci.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c
@@ -633,8 +633,6 @@ static void write_brdctl(struct ahc_softc *ahc, uint8_t value);
static uint8_t read_brdctl(struct ahc_softc *ahc);
static void ahc_pci_intr(struct ahc_softc *ahc);
static int ahc_pci_chip_init(struct ahc_softc *ahc);
-static int ahc_pci_suspend(struct ahc_softc *ahc);
-static int ahc_pci_resume(struct ahc_softc *ahc);
static int
ahc_9005_subdevinfo_valid(uint16_t device, uint16_t vendor,
@@ -791,8 +789,6 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
ahc->bus_intr = ahc_pci_intr;
ahc->bus_chip_init = ahc_pci_chip_init;
- ahc->bus_suspend = ahc_pci_suspend;
- ahc->bus_resume = ahc_pci_resume;
/* Remeber how the card was setup in case there is no SEEPROM */
if ((ahc_inb(ahc, HCNTRL) & POWRDN) == 0) {
@@ -2024,18 +2020,9 @@ ahc_pci_chip_init(struct ahc_softc *ahc)
return (ahc_chip_init(ahc));
}
-static int
-ahc_pci_suspend(struct ahc_softc *ahc)
-{
- return (ahc_suspend(ahc));
-}
-
-static int
+void
ahc_pci_resume(struct ahc_softc *ahc)
{
-
- pci_set_power_state(ahc->dev_softc, AHC_POWER_STATE_D0);
-
/*
* We assume that the OS has restored our register
* mappings, etc. Just update the config space registers
@@ -2063,7 +2050,6 @@ ahc_pci_resume(struct ahc_softc *ahc)
&sxfrctl1);
ahc_release_seeprom(&sd);
}
- return (ahc_resume(ahc));
}
static int
diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l b/drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l
index f06e7035cb35..c0457b8c3b77 100644
--- a/drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l
+++ b/drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l
@@ -66,6 +66,7 @@ static char string_buf[MAX_STR_CONST];
static char *string_buf_ptr;
static int parren_count;
static char buf[255];
+int mmlineno;
%}
WORD [A-Za-z_][-A-Za-z_0-9]*
@@ -76,7 +77,7 @@ MCARG [^(), \t]+
%%
\n {
- ++yylineno;
+ ++mmlineno;
}
\r ;
<ARGLIST>{SPACE} ;
diff --git a/drivers/scsi/aic7xxx/cam.h b/drivers/scsi/aic7xxx/cam.h
index 26f17e3fc45c..687aef6ef185 100644
--- a/drivers/scsi/aic7xxx/cam.h
+++ b/drivers/scsi/aic7xxx/cam.h
@@ -48,7 +48,7 @@ typedef enum {
CAM_REQ_ABORTED, /* CCB request aborted by the host */
CAM_UA_ABORT, /* Unable to abort CCB request */
CAM_REQ_CMP_ERR, /* CCB request completed with an error */
- CAM_BUSY, /* CAM subsytem is busy */
+ CAM_BUSY, /* CAM subsystem is busy */
CAM_REQ_INVALID, /* CCB request was invalid */
CAM_PATH_INVALID, /* Supplied Path ID is invalid */
CAM_SEL_TIMEOUT, /* Target Selection Timeout */
diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
index 1a71b0236c97..8f8db5f0aef7 100644
--- a/drivers/scsi/aic7xxx_old.c
+++ b/drivers/scsi/aic7xxx_old.c
@@ -8417,7 +8417,7 @@ aic7xxx_alloc(struct scsi_host_template *sht, struct aic7xxx_host *temp)
p->host = host;
p->scb_data = kzalloc(sizeof(scb_data_type), GFP_ATOMIC);
- if (!p->scb_data)
+ if (p->scb_data)
{
scbq_init (&p->scb_data->free_scbs);
}
@@ -11142,6 +11142,7 @@ static struct scsi_host_template driver_template = {
.max_sectors = 2048,
.cmd_per_lun = 3,
.use_clustering = ENABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
};
#include "scsi_module.c"
diff --git a/drivers/scsi/aic94xx/aic94xx_sds.c b/drivers/scsi/aic94xx/aic94xx_sds.c
index 5b0932f61473..06509bff71f7 100644
--- a/drivers/scsi/aic94xx/aic94xx_sds.c
+++ b/drivers/scsi/aic94xx/aic94xx_sds.c
@@ -377,7 +377,7 @@ out:
#define FLASH_RESET 0xF0
-#define FLASH_SIZE 0x200000
+#define ASD_FLASH_SIZE 0x200000
#define FLASH_DIR_COOKIE "*** ADAPTEC FLASH DIRECTORY *** "
#define FLASH_NEXT_ENTRY_OFFS 0x2000
#define FLASH_MAX_DIR_ENTRIES 32
@@ -609,7 +609,7 @@ static int asd_find_flash_dir(struct asd_ha_struct *asd_ha,
struct asd_flash_dir *flash_dir)
{
u32 v;
- for (v = 0; v < FLASH_SIZE; v += FLASH_NEXT_ENTRY_OFFS) {
+ for (v = 0; v < ASD_FLASH_SIZE; v += FLASH_NEXT_ENTRY_OFFS) {
asd_read_flash_seg(asd_ha, flash_dir, v,
sizeof(FLASH_DIR_COOKIE)-1);
if (memcmp(flash_dir->cookie, FLASH_DIR_COOKIE,
diff --git a/drivers/scsi/aic94xx/aic94xx_task.c b/drivers/scsi/aic94xx/aic94xx_task.c
index f2b23e01401a..ee0a98bffcd4 100644
--- a/drivers/scsi/aic94xx/aic94xx_task.c
+++ b/drivers/scsi/aic94xx/aic94xx_task.c
@@ -94,7 +94,7 @@ static inline int asd_map_scatterlist(struct sas_task *task,
res = -ENOMEM;
goto err_unmap;
}
- for (sc = task->scatter, i = 0; i < num_sg; i++, sc++) {
+ for_each_sg(task->scatter, sc, num_sg, i) {
struct sg_el *sg =
&((struct sg_el *)ascb->sg_arr->vaddr)[i];
sg->bus_addr = cpu_to_le64((u64)sg_dma_address(sc));
@@ -103,7 +103,7 @@ static inline int asd_map_scatterlist(struct sas_task *task,
sg->flags |= ASD_SG_EL_LIST_EOL;
}
- for (sc = task->scatter, i = 0; i < 2; i++, sc++) {
+ for_each_sg(task->scatter, sc, 2, i) {
sg_arr[i].bus_addr =
cpu_to_le64((u64)sg_dma_address(sc));
sg_arr[i].size = cpu_to_le32((u32)sg_dma_len(sc));
@@ -115,7 +115,7 @@ static inline int asd_map_scatterlist(struct sas_task *task,
sg_arr[2].bus_addr=cpu_to_le64((u64)ascb->sg_arr->dma_handle);
} else {
int i;
- for (sc = task->scatter, i = 0; i < num_sg; i++, sc++) {
+ for_each_sg(task->scatter, sc, num_sg, i) {
sg_arr[i].bus_addr =
cpu_to_le64((u64)sg_dma_address(sc));
sg_arr[i].size = cpu_to_le32((u32)sg_dma_len(sc));
diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h
index ace7a15b413e..a67e29f83ae5 100644
--- a/drivers/scsi/arcmsr/arcmsr.h
+++ b/drivers/scsi/arcmsr/arcmsr.h
@@ -141,14 +141,14 @@ struct CMD_MESSAGE_FIELD
#define IS_SG64_ADDR 0x01000000 /* bit24 */
struct SG32ENTRY
{
- uint32_t length;
- uint32_t address;
+ __le32 length;
+ __le32 address;
};
struct SG64ENTRY
{
- uint32_t length;
- uint32_t address;
- uint32_t addresshigh;
+ __le32 length;
+ __le32 address;
+ __le32 addresshigh;
};
struct SGENTRY_UNION
{
@@ -339,23 +339,15 @@ struct MessageUnit_B
uint32_t done_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE];
uint32_t postq_index;
uint32_t doneq_index;
- uint32_t *drv2iop_doorbell_reg;
- uint32_t *drv2iop_doorbell_mask_reg;
- uint32_t *iop2drv_doorbell_reg;
- uint32_t *iop2drv_doorbell_mask_reg;
- uint32_t *msgcode_rwbuffer_reg;
- uint32_t *ioctl_wbuffer_reg;
- uint32_t *ioctl_rbuffer_reg;
+ uint32_t __iomem *drv2iop_doorbell_reg;
+ uint32_t __iomem *drv2iop_doorbell_mask_reg;
+ uint32_t __iomem *iop2drv_doorbell_reg;
+ uint32_t __iomem *iop2drv_doorbell_mask_reg;
+ uint32_t __iomem *msgcode_rwbuffer_reg;
+ uint32_t __iomem *ioctl_wbuffer_reg;
+ uint32_t __iomem *ioctl_rbuffer_reg;
};
-struct MessageUnit
-{
- union
- {
- struct MessageUnit_A pmu_A;
- struct MessageUnit_B pmu_B;
- } u;
-};
/*
*******************************************************************************
** Adapter Control Block
@@ -374,7 +366,10 @@ struct AdapterControlBlock
/* Offset is used in making arc cdb physical to virtual calculations */
uint32_t outbound_int_enable;
- struct MessageUnit * pmu;
+ union {
+ struct MessageUnit_A __iomem * pmuA;
+ struct MessageUnit_B * pmuB;
+ };
/* message unit ATU inbound base address0 */
uint32_t acb_flags;
@@ -558,7 +553,7 @@ struct SENSE_DATA
extern void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *);
extern void arcmsr_iop_message_read(struct AdapterControlBlock *);
-extern struct QBUFFER *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *);
+extern struct QBUFFER __iomem *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *);
extern struct class_device_attribute *arcmsr_host_attrs[];
extern int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *);
void arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb);
diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c
index d04d1aa28fa4..7d7b0a554276 100644
--- a/drivers/scsi/arcmsr/arcmsr_attr.c
+++ b/drivers/scsi/arcmsr/arcmsr_attr.c
@@ -85,13 +85,13 @@ static ssize_t arcmsr_sysfs_iop_message_read(struct kobject *kobj,
allxfer_len++;
}
if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
- struct QBUFFER *prbuffer;
- uint8_t *iop_data;
+ struct QBUFFER __iomem *prbuffer;
+ uint8_t __iomem *iop_data;
int32_t iop_len;
acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
prbuffer = arcmsr_get_iop_rqbuffer(acb);
- iop_data = (uint8_t *)prbuffer->data;
+ iop_data = prbuffer->data;
iop_len = readl(&prbuffer->data_len);
while (iop_len > 0) {
acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data);
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
index cfcf40159eab..d466a2dac1db 100644
--- a/drivers/scsi/arcmsr/arcmsr_hba.c
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c
@@ -122,6 +122,7 @@ static struct scsi_host_template arcmsr_scsi_host_template = {
.max_sectors = ARCMSR_MAX_XFER_SECTORS,
.cmd_per_lun = ARCMSR_MAX_CMD_PERLUN,
.use_clustering = ENABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
.shost_attrs = arcmsr_host_attrs,
};
#ifdef CONFIG_SCSI_ARCMSR_AER
@@ -235,18 +236,22 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
uint32_t intmask_org;
int i, j;
- acb->pmu = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
- if (!acb->pmu) {
+ acb->pmuA = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
+ if (!acb->pmuA) {
printk(KERN_NOTICE "arcmsr%d: memory mapping region fail \n",
acb->host->host_no);
+ return -ENOMEM;
}
dma_coherent = dma_alloc_coherent(&pdev->dev,
ARCMSR_MAX_FREECCB_NUM *
sizeof (struct CommandControlBlock) + 0x20,
&dma_coherent_handle, GFP_KERNEL);
- if (!dma_coherent)
+
+ if (!dma_coherent) {
+ iounmap(acb->pmuA);
return -ENOMEM;
+ }
acb->dma_coherent = dma_coherent;
acb->dma_coherent_handle = dma_coherent_handle;
@@ -286,7 +291,7 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
struct pci_dev *pdev = acb->pdev;
struct MessageUnit_B *reg;
- void *mem_base0, *mem_base1;
+ void __iomem *mem_base0, *mem_base1;
void *dma_coherent;
dma_addr_t dma_coherent_handle, dma_addr;
uint32_t intmask_org;
@@ -327,25 +332,28 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
reg = (struct MessageUnit_B *)(dma_coherent +
ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock));
- acb->pmu = (struct MessageUnit *)reg;
+ acb->pmuB = reg;
mem_base0 = ioremap(pci_resource_start(pdev, 0),
pci_resource_len(pdev, 0));
+ if (!mem_base0)
+ goto out;
+
mem_base1 = ioremap(pci_resource_start(pdev, 2),
pci_resource_len(pdev, 2));
- reg->drv2iop_doorbell_reg = (uint32_t *)((char *)mem_base0 +
- ARCMSR_DRV2IOP_DOORBELL);
- reg->drv2iop_doorbell_mask_reg = (uint32_t *)((char *)mem_base0 +
- ARCMSR_DRV2IOP_DOORBELL_MASK);
- reg->iop2drv_doorbell_reg = (uint32_t *)((char *)mem_base0 +
- ARCMSR_IOP2DRV_DOORBELL);
- reg->iop2drv_doorbell_mask_reg = (uint32_t *)((char *)mem_base0 +
- ARCMSR_IOP2DRV_DOORBELL_MASK);
- reg->ioctl_wbuffer_reg = (uint32_t *)((char *)mem_base1 +
- ARCMSR_IOCTL_WBUFFER);
- reg->ioctl_rbuffer_reg = (uint32_t *)((char *)mem_base1 +
- ARCMSR_IOCTL_RBUFFER);
- reg->msgcode_rwbuffer_reg = (uint32_t *)((char *)mem_base1 +
- ARCMSR_MSGCODE_RWBUFFER);
+ if (!mem_base1) {
+ iounmap(mem_base0);
+ goto out;
+ }
+
+ reg->drv2iop_doorbell_reg = mem_base0 + ARCMSR_DRV2IOP_DOORBELL;
+ reg->drv2iop_doorbell_mask_reg = mem_base0 +
+ ARCMSR_DRV2IOP_DOORBELL_MASK;
+ reg->iop2drv_doorbell_reg = mem_base0 + ARCMSR_IOP2DRV_DOORBELL;
+ reg->iop2drv_doorbell_mask_reg = mem_base0 +
+ ARCMSR_IOP2DRV_DOORBELL_MASK;
+ reg->ioctl_wbuffer_reg = mem_base1 + ARCMSR_IOCTL_WBUFFER;
+ reg->ioctl_rbuffer_reg = mem_base1 + ARCMSR_IOCTL_RBUFFER;
+ reg->msgcode_rwbuffer_reg = mem_base1 + ARCMSR_MSGCODE_RWBUFFER;
acb->vir2phy_offset = (unsigned long)ccb_tmp -(unsigned long)dma_addr;
for (i = 0; i < ARCMSR_MAX_TARGETID; i++)
@@ -361,6 +369,12 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
break;
}
return 0;
+
+out:
+ dma_free_coherent(&acb->pdev->dev,
+ ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock) + 0x20,
+ acb->dma_coherent, acb->dma_coherent_handle);
+ return -ENOMEM;
}
static int arcmsr_probe(struct pci_dev *pdev,
@@ -453,7 +467,6 @@ static int arcmsr_probe(struct pci_dev *pdev,
free_irq(pdev->irq, acb);
out_free_ccb_pool:
arcmsr_free_ccb_pool(acb);
- iounmap(acb->pmu);
out_release_regions:
pci_release_regions(pdev);
out_host_put:
@@ -466,7 +479,7 @@ static int arcmsr_probe(struct pci_dev *pdev,
static uint8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb)
{
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
uint32_t Index;
uint8_t Retries = 0x00;
@@ -487,7 +500,7 @@ static uint8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb)
static uint8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb)
{
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
uint32_t Index;
uint8_t Retries = 0x00;
@@ -508,7 +521,7 @@ static uint8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb)
static void arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb)
{
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
writel(ARCMSR_INBOUND_MESG0_ABORT_CMD, &reg->inbound_msgaddr0);
if (arcmsr_hba_wait_msgint_ready(acb))
@@ -519,7 +532,7 @@ static void arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb)
static void arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb)
{
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
writel(ARCMSR_MESSAGE_ABORT_CMD, reg->drv2iop_doorbell_reg);
if (arcmsr_hbb_wait_msgint_ready(acb))
@@ -565,7 +578,7 @@ static void arcmsr_ccb_complete(struct CommandControlBlock *ccb, int stand_flag)
static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb)
{
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
int retry_count = 30;
writel(ARCMSR_INBOUND_MESG0_FLUSH_CACHE, &reg->inbound_msgaddr0);
@@ -582,7 +595,7 @@ static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb)
static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb)
{
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
int retry_count = 30;
writel(ARCMSR_MESSAGE_FLUSH_CACHE, reg->drv2iop_doorbell_reg);
@@ -636,7 +649,7 @@ static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb)
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A : {
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
orig_mask = readl(&reg->outbound_intmask)|\
ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE;
writel(orig_mask|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE, \
@@ -645,7 +658,7 @@ static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb)
break;
case ACB_ADAPTER_TYPE_B : {
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
orig_mask = readl(reg->iop2drv_doorbell_mask_reg) & \
(~ARCMSR_IOP2DRV_MESSAGE_CMD_DONE);
writel(0, reg->iop2drv_doorbell_mask_reg);
@@ -747,14 +760,13 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb)
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
- struct MessageUnit_A __iomem *reg = \
- (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
uint32_t outbound_intstatus;
- outbound_intstatus = readl(&reg->outbound_intstatus) & \
+ outbound_intstatus = readl(&reg->outbound_intstatus) &
acb->outbound_int_enable;
/*clear and abort all outbound posted Q*/
writel(outbound_intstatus, &reg->outbound_intstatus);/*clear interrupt*/
- while (((flag_ccb = readl(&reg->outbound_queueport)) != 0xFFFFFFFF) \
+ while (((flag_ccb = readl(&reg->outbound_queueport)) != 0xFFFFFFFF)
&& (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) {
arcmsr_drain_donequeue(acb, flag_ccb);
}
@@ -762,7 +774,7 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb)
break;
case ACB_ADAPTER_TYPE_B: {
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
/*clear all outbound posted Q*/
for (i = 0; i < ARCMSR_MAX_HBB_POSTQUEUE; i++) {
if ((flag_ccb = readl(&reg->done_qbuffer[i])) != 0) {
@@ -815,7 +827,6 @@ static void arcmsr_remove(struct pci_dev *pdev)
}
free_irq(pdev->irq, acb);
- iounmap(acb->pmu);
arcmsr_free_ccb_pool(acb);
pci_release_regions(pdev);
@@ -858,7 +869,7 @@ static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, \
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A : {
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
mask = intmask_org & ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE |
ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE);
writel(mask, &reg->outbound_intmask);
@@ -867,7 +878,7 @@ static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, \
break;
case ACB_ADAPTER_TYPE_B : {
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
mask = intmask_org | (ARCMSR_IOP2DRV_DATA_WRITE_OK | \
ARCMSR_IOP2DRV_DATA_READ_OK | ARCMSR_IOP2DRV_CDB_DONE);
writel(mask, reg->iop2drv_doorbell_mask_reg);
@@ -881,7 +892,7 @@ static void arcmsr_build_ccb(struct AdapterControlBlock *acb,
{
struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&ccb->arcmsr_cdb;
int8_t *psge = (int8_t *)&arcmsr_cdb->u;
- uint32_t address_lo, address_hi;
+ __le32 address_lo, address_hi;
int arccdbsize = 0x30;
int nseg;
@@ -899,7 +910,8 @@ static void arcmsr_build_ccb(struct AdapterControlBlock *acb,
BUG_ON(nseg < 0);
if (nseg) {
- int length, i, cdb_sgcount = 0;
+ __le32 length;
+ int i, cdb_sgcount = 0;
struct scatterlist *sg;
/* map stor port SG list to our iop SG List. */
@@ -920,7 +932,7 @@ static void arcmsr_build_ccb(struct AdapterControlBlock *acb,
pdma_sg->addresshigh = address_hi;
pdma_sg->address = address_lo;
- pdma_sg->length = length|IS_SG64_ADDR;
+ pdma_sg->length = length|cpu_to_le32(IS_SG64_ADDR);
psge += sizeof (struct SG64ENTRY);
arccdbsize += sizeof (struct SG64ENTRY);
}
@@ -946,7 +958,7 @@ static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandContr
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
- struct MessageUnit_A *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
if (arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE)
writel(cdb_shifted_phyaddr | ARCMSR_CCBPOST_FLAG_SGL_BSIZE,
@@ -958,7 +970,7 @@ static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandContr
break;
case ACB_ADAPTER_TYPE_B: {
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
uint32_t ending_index, index = reg->postq_index;
ending_index = ((index + 1) % ARCMSR_MAX_HBB_POSTQUEUE);
@@ -981,7 +993,7 @@ static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandContr
static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb)
{
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
writel(ARCMSR_INBOUND_MESG0_STOP_BGRB, &reg->inbound_msgaddr0);
@@ -994,7 +1006,7 @@ static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb)
static void arcmsr_stop_hbb_bgrb(struct AdapterControlBlock *acb)
{
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
writel(ARCMSR_MESSAGE_STOP_BGRB, reg->drv2iop_doorbell_reg);
@@ -1022,6 +1034,17 @@ static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb)
static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb)
{
+ switch (acb->adapter_type) {
+ case ACB_ADAPTER_TYPE_A: {
+ iounmap(acb->pmuA);
+ break;
+ }
+ case ACB_ADAPTER_TYPE_B: {
+ struct MessageUnit_B *reg = acb->pmuB;
+ iounmap(reg->drv2iop_doorbell_reg - ARCMSR_DRV2IOP_DOORBELL);
+ iounmap(reg->ioctl_wbuffer_reg - ARCMSR_IOCTL_WBUFFER);
+ }
+ }
dma_free_coherent(&acb->pdev->dev,
ARCMSR_MAX_FREECCB_NUM * sizeof (struct CommandControlBlock) + 0x20,
acb->dma_coherent,
@@ -1032,13 +1055,13 @@ void arcmsr_iop_message_read(struct AdapterControlBlock *acb)
{
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, &reg->inbound_doorbell);
}
break;
case ACB_ADAPTER_TYPE_B: {
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
writel(ARCMSR_DRV2IOP_DATA_READ_OK, reg->drv2iop_doorbell_reg);
}
break;
@@ -1049,7 +1072,7 @@ static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb)
{
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
/*
** push inbound doorbell tell iop, driver data write ok
** and wait reply on next hwinterrupt for next Qbuffer post
@@ -1059,7 +1082,7 @@ static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb)
break;
case ACB_ADAPTER_TYPE_B: {
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
/*
** push inbound doorbell tell iop, driver data write ok
** and wait reply on next hwinterrupt for next Qbuffer post
@@ -1070,41 +1093,41 @@ static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb)
}
}
-struct QBUFFER *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *acb)
+struct QBUFFER __iomem *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *acb)
{
- static struct QBUFFER *qbuffer;
+ struct QBUFFER __iomem *qbuffer = NULL;
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
- qbuffer = (struct QBUFFER __iomem *) &reg->message_rbuffer;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
+ qbuffer = (struct QBUFFER __iomem *)&reg->message_rbuffer;
}
break;
case ACB_ADAPTER_TYPE_B: {
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
- qbuffer = (struct QBUFFER __iomem *) reg->ioctl_rbuffer_reg;
+ struct MessageUnit_B *reg = acb->pmuB;
+ qbuffer = (struct QBUFFER __iomem *)reg->ioctl_rbuffer_reg;
}
break;
}
return qbuffer;
}
-static struct QBUFFER *arcmsr_get_iop_wqbuffer(struct AdapterControlBlock *acb)
+static struct QBUFFER __iomem *arcmsr_get_iop_wqbuffer(struct AdapterControlBlock *acb)
{
- static struct QBUFFER *pqbuffer;
+ struct QBUFFER __iomem *pqbuffer = NULL;
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
- pqbuffer = (struct QBUFFER *) &reg->message_wbuffer;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
+ pqbuffer = (struct QBUFFER __iomem *) &reg->message_wbuffer;
}
break;
case ACB_ADAPTER_TYPE_B: {
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
pqbuffer = (struct QBUFFER __iomem *)reg->ioctl_wbuffer_reg;
}
break;
@@ -1114,15 +1137,15 @@ static struct QBUFFER *arcmsr_get_iop_wqbuffer(struct AdapterControlBlock *acb)
static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb)
{
- struct QBUFFER *prbuffer;
+ struct QBUFFER __iomem *prbuffer;
struct QBUFFER *pQbuffer;
- uint8_t *iop_data;
+ uint8_t __iomem *iop_data;
int32_t my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex;
rqbuf_lastindex = acb->rqbuf_lastindex;
rqbuf_firstindex = acb->rqbuf_firstindex;
prbuffer = arcmsr_get_iop_rqbuffer(acb);
- iop_data = (uint8_t *)prbuffer->data;
+ iop_data = (uint8_t __iomem *)prbuffer->data;
iop_len = prbuffer->data_len;
my_empty_len = (rqbuf_firstindex - rqbuf_lastindex -1)&(ARCMSR_MAX_QBUFFER -1);
@@ -1150,8 +1173,8 @@ static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb)
acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READED;
if (acb->wqbuf_firstindex != acb->wqbuf_lastindex) {
uint8_t *pQbuffer;
- struct QBUFFER *pwbuffer;
- uint8_t *iop_data;
+ struct QBUFFER __iomem *pwbuffer;
+ uint8_t __iomem *iop_data;
int32_t allxfer_len = 0;
acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED);
@@ -1180,7 +1203,7 @@ static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb)
static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb)
{
uint32_t outbound_doorbell;
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
outbound_doorbell = readl(&reg->outbound_doorbell);
writel(outbound_doorbell, &reg->outbound_doorbell);
@@ -1196,7 +1219,7 @@ static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb)
static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb)
{
uint32_t flag_ccb;
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
while ((flag_ccb = readl(&reg->outbound_queueport)) != 0xFFFFFFFF) {
arcmsr_drain_donequeue(acb, flag_ccb);
@@ -1207,7 +1230,7 @@ static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb)
{
uint32_t index;
uint32_t flag_ccb;
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
index = reg->doneq_index;
@@ -1223,7 +1246,7 @@ static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb)
static int arcmsr_handle_hba_isr(struct AdapterControlBlock *acb)
{
uint32_t outbound_intstatus;
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
outbound_intstatus = readl(&reg->outbound_intstatus) & \
acb->outbound_int_enable;
@@ -1243,7 +1266,7 @@ static int arcmsr_handle_hba_isr(struct AdapterControlBlock *acb)
static int arcmsr_handle_hbb_isr(struct AdapterControlBlock *acb)
{
uint32_t outbound_doorbell;
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
outbound_doorbell = readl(reg->iop2drv_doorbell_reg) & \
acb->outbound_int_enable;
@@ -1304,8 +1327,8 @@ void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb)
{
int32_t wqbuf_firstindex, wqbuf_lastindex;
uint8_t *pQbuffer;
- struct QBUFFER *pwbuffer;
- uint8_t *iop_data;
+ struct QBUFFER __iomem *pwbuffer;
+ uint8_t __iomem *iop_data;
int32_t allxfer_len = 0;
pwbuffer = arcmsr_get_iop_wqbuffer(acb);
@@ -1342,7 +1365,7 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \
/* 4 bytes: Areca io control code */
sg = scsi_sglist(cmd);
- buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+ buffer = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
if (scsi_sg_count(cmd) > 1) {
retvalue = ARCMSR_MESSAGE_FAIL;
goto message_out;
@@ -1379,13 +1402,13 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \
}
if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
- struct QBUFFER *prbuffer;
- uint8_t *iop_data;
+ struct QBUFFER __iomem *prbuffer;
+ uint8_t __iomem *iop_data;
int32_t iop_len;
acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
prbuffer = arcmsr_get_iop_rqbuffer(acb);
- iop_data = (uint8_t *)prbuffer->data;
+ iop_data = prbuffer->data;
iop_len = readl(&prbuffer->data_len);
while (iop_len > 0) {
acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data);
@@ -1592,7 +1615,7 @@ static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb,
strncpy(&inqdata[32], "R001", 4); /* Product Revision */
sg = scsi_sglist(cmd);
- buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+ buffer = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
memcpy(buffer, inqdata, sizeof(inqdata));
sg = scsi_sglist(cmd);
@@ -1668,11 +1691,11 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd,
static void arcmsr_get_hba_config(struct AdapterControlBlock *acb)
{
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
char *acb_firm_model = acb->firm_model;
char *acb_firm_version = acb->firm_version;
- char *iop_firm_model = (char *) (&reg->message_rwbuffer[15]);
- char *iop_firm_version = (char *) (&reg->message_rwbuffer[17]);
+ char __iomem *iop_firm_model = (char __iomem *)(&reg->message_rwbuffer[15]);
+ char __iomem *iop_firm_version = (char __iomem *)(&reg->message_rwbuffer[17]);
int count;
writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, &reg->inbound_msgaddr0);
@@ -1709,13 +1732,13 @@ static void arcmsr_get_hba_config(struct AdapterControlBlock *acb)
static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb)
{
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
- uint32_t *lrwbuffer = reg->msgcode_rwbuffer_reg;
+ struct MessageUnit_B *reg = acb->pmuB;
+ uint32_t __iomem *lrwbuffer = reg->msgcode_rwbuffer_reg;
char *acb_firm_model = acb->firm_model;
char *acb_firm_version = acb->firm_version;
- char *iop_firm_model = (char *) (&lrwbuffer[15]);
+ char __iomem *iop_firm_model = (char __iomem *)(&lrwbuffer[15]);
/*firm_model,15,60-67*/
- char *iop_firm_version = (char *) (&lrwbuffer[17]);
+ char __iomem *iop_firm_version = (char __iomem *)(&lrwbuffer[17]);
/*firm_version,17,68-83*/
int count;
@@ -1776,7 +1799,7 @@ static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb)
static void arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb,
struct CommandControlBlock *poll_ccb)
{
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
struct CommandControlBlock *ccb;
uint32_t flag_ccb, outbound_intstatus, poll_ccb_done = 0, poll_count = 0;
@@ -1825,7 +1848,7 @@ static void arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb,
static void arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb, \
struct CommandControlBlock *poll_ccb)
{
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
struct CommandControlBlock *ccb;
uint32_t flag_ccb, poll_ccb_done = 0, poll_count = 0;
int index;
@@ -1917,8 +1940,7 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb)
case ACB_ADAPTER_TYPE_A: {
if (ccb_phyaddr_hi32 != 0) {
- struct MessageUnit_A __iomem *reg = \
- (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
uint32_t intmask_org;
intmask_org = arcmsr_disable_outbound_ints(acb);
writel(ARCMSR_SIGNATURE_SET_CONFIG, \
@@ -1939,9 +1961,9 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb)
case ACB_ADAPTER_TYPE_B: {
unsigned long post_queue_phyaddr;
- uint32_t *rwbuffer;
+ uint32_t __iomem *rwbuffer;
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
uint32_t intmask_org;
intmask_org = arcmsr_disable_outbound_ints(acb);
reg->postq_index = 0;
@@ -1993,7 +2015,7 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb)
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
do {
firmware_state = readl(&reg->outbound_msgaddr1);
} while ((firmware_state & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0);
@@ -2001,7 +2023,7 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb)
break;
case ACB_ADAPTER_TYPE_B: {
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
do {
firmware_state = readl(reg->iop2drv_doorbell_reg);
} while ((firmware_state & ARCMSR_MESSAGE_FIRMWARE_OK) == 0);
@@ -2012,7 +2034,7 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb)
static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb)
{
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
acb->acb_flags |= ACB_F_MSG_START_BGRB;
writel(ARCMSR_INBOUND_MESG0_START_BGRB, &reg->inbound_msgaddr0);
if (arcmsr_hba_wait_msgint_ready(acb)) {
@@ -2023,7 +2045,7 @@ static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb)
static void arcmsr_start_hbb_bgrb(struct AdapterControlBlock *acb)
{
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
acb->acb_flags |= ACB_F_MSG_START_BGRB;
writel(ARCMSR_MESSAGE_START_BGRB, reg->drv2iop_doorbell_reg);
if (arcmsr_hbb_wait_msgint_ready(acb)) {
@@ -2048,7 +2070,7 @@ static void arcmsr_clear_doorbell_queue_buffer(struct AdapterControlBlock *acb)
{
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
- struct MessageUnit_A *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
uint32_t outbound_doorbell;
/* empty doorbell Qbuffer if door bell ringed */
outbound_doorbell = readl(&reg->outbound_doorbell);
@@ -2059,7 +2081,7 @@ static void arcmsr_clear_doorbell_queue_buffer(struct AdapterControlBlock *acb)
break;
case ACB_ADAPTER_TYPE_B: {
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
/*clear interrupt and message state*/
writel(ARCMSR_MESSAGE_INT_CLEAR_PATTERN, reg->iop2drv_doorbell_reg);
writel(ARCMSR_DRV2IOP_DATA_READ_OK, reg->drv2iop_doorbell_reg);
diff --git a/drivers/scsi/arm/scsi.h b/drivers/scsi/arm/scsi.h
index 21ba57155bea..bb6550e31926 100644
--- a/drivers/scsi/arm/scsi.h
+++ b/drivers/scsi/arm/scsi.h
@@ -38,9 +38,7 @@ static inline int next_SCp(struct scsi_pointer *SCp)
if (ret) {
SCp->buffer++;
SCp->buffers_residual--;
- SCp->ptr = (char *)
- (page_address(SCp->buffer->page) +
- SCp->buffer->offset);
+ SCp->ptr = sg_virt(SCp->buffer);
SCp->this_residual = SCp->buffer->length;
} else {
SCp->ptr = NULL;
@@ -76,9 +74,7 @@ static inline void init_SCp(struct scsi_cmnd *SCpnt)
SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->request_buffer;
SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1;
- SCpnt->SCp.ptr = (char *)
- (page_address(SCpnt->SCp.buffer->page) +
- SCpnt->SCp.buffer->offset);
+ SCpnt->SCp.ptr = sg_virt(SCpnt->SCp.buffer);
SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;
SCpnt->SCp.phase = SCpnt->request_bufflen;
diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c
index 52d0b87e9aa4..a9680b5e8ac6 100644
--- a/drivers/scsi/atari_NCR5380.c
+++ b/drivers/scsi/atari_NCR5380.c
@@ -477,10 +477,9 @@ static void merge_contiguous_buffers(Scsi_Cmnd *cmd)
for (endaddr = virt_to_phys(cmd->SCp.ptr + cmd->SCp.this_residual - 1) + 1;
cmd->SCp.buffers_residual &&
- virt_to_phys(page_address(cmd->SCp.buffer[1].page) +
- cmd->SCp.buffer[1].offset) == endaddr;) {
+ virt_to_phys(sg_virt(&cmd->SCp.buffer[1])) == endaddr;) {
MER_PRINTK("VTOP(%p) == %08lx -> merging\n",
- page_address(cmd->SCp.buffer[1].page), endaddr);
+ page_address(sg_page(&cmd->SCp.buffer[1])), endaddr);
#if (NDEBUG & NDEBUG_MERGING)
++cnt;
#endif
@@ -515,8 +514,7 @@ static inline void initialize_SCp(Scsi_Cmnd *cmd)
if (cmd->use_sg) {
cmd->SCp.buffer = (struct scatterlist *)cmd->request_buffer;
cmd->SCp.buffers_residual = cmd->use_sg - 1;
- cmd->SCp.ptr = (char *)page_address(cmd->SCp.buffer->page) +
- cmd->SCp.buffer->offset;
+ cmd->SCp.ptr = sg_virt(cmd->SCp.buffer);
cmd->SCp.this_residual = cmd->SCp.buffer->length;
/* ++roman: Try to merge some scatter-buffers if they are at
* contiguous physical addresses.
@@ -2054,8 +2052,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
++cmd->SCp.buffer;
--cmd->SCp.buffers_residual;
cmd->SCp.this_residual = cmd->SCp.buffer->length;
- cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) +
- cmd->SCp.buffer->offset;
+ cmd->SCp.ptr = sg_virt(cmd->SCp.buffer);
/* ++roman: Try to merge some scatter-buffers if
* they are at contiguous physical addresses.
*/
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index 1591824cf4b3..a9def6e1d30e 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -1808,12 +1808,12 @@ static irqreturn_t dc395x_interrupt(int irq, void *dev_id)
irqreturn_t handled = IRQ_NONE;
/*
- * Check for pending interupt
+ * Check for pending interrupt
*/
scsi_status = DC395x_read16(acb, TRM_S1040_SCSI_STATUS);
dma_status = DC395x_read8(acb, TRM_S1040_DMA_STATUS);
if (scsi_status & SCSIINTERRUPT) {
- /* interupt pending - let's process it! */
+ /* interrupt pending - let's process it! */
dc395x_handle_interrupt(acb, scsi_status);
handled = IRQ_HANDLED;
}
@@ -4579,7 +4579,7 @@ static void adapter_uninit_chip(struct AdapterCtlBlk *acb)
if (acb->config & HCC_SCSI_RESET)
reset_scsi_bus(acb);
- /* clear any pending interupt state */
+ /* clear any pending interrupt state */
DC395x_read8(acb, TRM_S1040_SCSI_INTSTATUS);
}
@@ -4765,6 +4765,7 @@ static struct scsi_host_template dc395x_driver_template = {
.eh_bus_reset_handler = dc395x_eh_bus_reset,
.unchecked_isa_dma = 0,
.use_clustering = DISABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
};
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index bea9d659af15..8258506ba7d7 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -3295,6 +3295,7 @@ static struct scsi_host_template adpt_template = {
.this_id = 7,
.cmd_per_lun = 1,
.use_clustering = ENABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
};
static s32 adpt_scsi_register(adpt_hba* pHba)
diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c
index ec2233114bc9..7ead5210de96 100644
--- a/drivers/scsi/eata.c
+++ b/drivers/scsi/eata.c
@@ -523,7 +523,8 @@ static struct scsi_host_template driver_template = {
.slave_configure = eata2x_slave_configure,
.this_id = 7,
.unchecked_isa_dma = 1,
- .use_clustering = ENABLE_CLUSTERING
+ .use_clustering = ENABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
};
#if !defined(__BIG_ENDIAN_BITFIELD) && !defined(__LITTLE_ENDIAN_BITFIELD)
diff --git a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c
index 96180bb47e41..982c5092be11 100644
--- a/drivers/scsi/eata_pio.c
+++ b/drivers/scsi/eata_pio.c
@@ -172,7 +172,7 @@ static void IncStat(struct scsi_pointer *SCp, unsigned int Increment)
SCp->Status = 0;
else {
SCp->buffer++;
- SCp->ptr = page_address(SCp->buffer->page) + SCp->buffer->offset;
+ SCp->ptr = sg_virt(SCp->buffer);
SCp->this_residual = SCp->buffer->length;
}
}
@@ -410,7 +410,7 @@ static int eata_pio_queue(struct scsi_cmnd *cmd,
} else {
cmd->SCp.buffer = cmd->request_buffer;
cmd->SCp.buffers_residual = cmd->use_sg;
- cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) + cmd->SCp.buffer->offset;
+ cmd->SCp.ptr = sg_virt(cmd->SCp.buffer);
cmd->SCp.this_residual = cmd->SCp.buffer->length;
}
cmd->SCp.Status = (cmd->SCp.this_residual != 0); /* TRUE as long as bytes
diff --git a/drivers/scsi/fcal.c b/drivers/scsi/fcal.c
deleted file mode 100644
index c4e16c0775de..000000000000
--- a/drivers/scsi/fcal.c
+++ /dev/null
@@ -1,317 +0,0 @@
-/* fcal.c: Fibre Channel Arbitrated Loop SCSI host adapter driver.
- *
- * Copyright (C) 1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/blkdev.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <linux/init.h>
-#ifdef CONFIG_KMOD
-#include <linux/kmod.h>
-#endif
-
-#include <asm/irq.h>
-
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-#include "../fc4/fcp_impl.h"
-#include "fcal.h"
-
-#include <linux/module.h>
-
-/* #define FCAL_DEBUG */
-
-#define fcal_printk printk ("FCAL %s: ", fc->name); printk
-
-#ifdef FCAL_DEBUG
-#define FCALD(x) fcal_printk x;
-#define FCALND(x) printk ("FCAL: "); printk x;
-#else
-#define FCALD(x)
-#define FCALND(x)
-#endif
-
-static unsigned char alpa2target[] = {
-0x7e, 0x7d, 0x7c, 0xff, 0x7b, 0xff, 0xff, 0xff, 0x7a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x79,
-0x78, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x77, 0x76, 0xff, 0xff, 0x75, 0xff, 0x74, 0x73, 0x72,
-0xff, 0xff, 0xff, 0x71, 0xff, 0x70, 0x6f, 0x6e, 0xff, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0xff,
-0xff, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0xff, 0xff, 0x61, 0x60, 0xff, 0x5f, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0x5e, 0xff, 0x5d, 0x5c, 0x5b, 0xff, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0xff,
-0xff, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0xff, 0xff, 0x4e, 0x4d, 0xff, 0x4c, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0x4b, 0xff, 0x4a, 0x49, 0x48, 0xff, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0xff,
-0xff, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0xff, 0xff, 0x3b, 0x3a, 0xff, 0x39, 0xff, 0xff, 0xff,
-0x38, 0x37, 0x36, 0xff, 0x35, 0xff, 0xff, 0xff, 0x34, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x33,
-0x32, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x31, 0x30, 0xff, 0xff, 0x2f, 0xff, 0x2e, 0x2d, 0x2c,
-0xff, 0xff, 0xff, 0x2b, 0xff, 0x2a, 0x29, 0x28, 0xff, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0xff,
-0xff, 0x21, 0x20, 0x1f, 0x1e, 0x1d, 0x1c, 0xff, 0xff, 0x1b, 0x1a, 0xff, 0x19, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0x18, 0xff, 0x17, 0x16, 0x15, 0xff, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0xff,
-0xff, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0xff, 0xff, 0x08, 0x07, 0xff, 0x06, 0xff, 0xff, 0xff,
-0x05, 0x04, 0x03, 0xff, 0x02, 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00
-};
-
-static unsigned char target2alpa[] = {
-0xef, 0xe8, 0xe4, 0xe2, 0xe1, 0xe0, 0xdc, 0xda, 0xd9, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xce,
-0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc7, 0xc6, 0xc5, 0xc3, 0xbc, 0xba, 0xb9, 0xb6, 0xb5, 0xb4, 0xb3,
-0xb2, 0xb1, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9, 0xa7, 0xa6, 0xa5, 0xa3, 0x9f, 0x9e, 0x9d, 0x9b,
-0x98, 0x97, 0x90, 0x8f, 0x88, 0x84, 0x82, 0x81, 0x80, 0x7c, 0x7a, 0x79, 0x76, 0x75, 0x74, 0x73,
-0x72, 0x71, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x67, 0x66, 0x65, 0x63, 0x5c, 0x5a, 0x59, 0x56,
-0x55, 0x54, 0x53, 0x52, 0x51, 0x4e, 0x4d, 0x4c, 0x4b, 0x4a, 0x49, 0x47, 0x46, 0x45, 0x43, 0x3c,
-0x3a, 0x39, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x27, 0x26,
-0x25, 0x23, 0x1f, 0x1e, 0x1d, 0x1b, 0x18, 0x17, 0x10, 0x0f, 0x08, 0x04, 0x02, 0x01, 0x00
-};
-
-static int fcal_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr, fc_channel *fc, fcp_cmnd *fcmd);
-
-int fcal_slave_configure(struct scsi_device *device)
-{
- int depth_to_use;
-
- if (device->tagged_supported)
- depth_to_use = /* 254 */ 8;
- else
- depth_to_use = 2;
-
- scsi_adjust_queue_depth(device,
- (device->tagged_supported ?
- MSG_SIMPLE_TAG : 0),
- depth_to_use);
-
- return 0;
-}
-
-/* Detect all FC Arbitrated Loops attached to the machine.
- fc4 module has done all the work for us... */
-int __init fcal_detect(struct scsi_host_template *tpnt)
-{
- int nfcals = 0;
- fc_channel *fc;
- int fcalcount;
- int i;
-
- tpnt->proc_name = "fcal";
- fcalcount = 0;
- for_each_online_fc_channel(fc)
- if (fc->posmap)
- fcalcount++;
- FCALND(("%d channels online\n", fcalcount))
- if (!fcalcount) {
-#if defined(MODULE) && defined(CONFIG_FC4_SOCAL_MODULE) && defined(CONFIG_KMOD)
- request_module("socal");
-
- for_each_online_fc_channel(fc)
- if (fc->posmap)
- fcalcount++;
- if (!fcalcount)
-#endif
- return 0;
- }
- for_each_online_fc_channel(fc) {
- struct Scsi_Host *host;
- long *ages;
- struct fcal *fcal;
-
- if (!fc->posmap) continue;
-
- /* Strange, this is already registered to some other SCSI host, then it cannot be fcal */
- if (fc->scsi_name[0]) continue;
- memcpy (fc->scsi_name, "FCAL", 4);
-
- fc->can_queue = FCAL_CAN_QUEUE;
- fc->rsp_size = 64;
- fc->encode_addr = fcal_encode_addr;
-
- ages = kmalloc (128 * sizeof(long), GFP_KERNEL);
- if (!ages) continue;
-
- host = scsi_register (tpnt, sizeof (struct fcal));
- if (!host)
- {
- kfree(ages);
- continue;
- }
-
- if (!try_module_get(fc->module)) {
- kfree(ages);
- scsi_unregister(host);
- continue;
- }
-
- nfcals++;
-
- fcal = (struct fcal *)host->hostdata;
-
- fc->fcp_register(fc, TYPE_SCSI_FCP, 0);
-
- for (i = 0; i < fc->posmap->len; i++) {
- int status, target, alpa;
-
- alpa = fc->posmap->list[i];
- FCALD(("Sending PLOGI to %02x\n", alpa))
- target = alpa2target[alpa];
- status = fc_do_plogi(fc, alpa, fcal->node_wwn + target,
- fcal->nport_wwn + target);
- FCALD(("PLOGI returned with status %d\n", status))
- if (status != FC_STATUS_OK)
- continue;
- FCALD(("Sending PRLI to %02x\n", alpa))
- status = fc_do_prli(fc, alpa);
- FCALD(("PRLI returned with status %d\n", status))
- if (status == FC_STATUS_OK)
- fcal->map[target] = 1;
- }
-
- host->max_id = 127;
- host->irq = fc->irq;
-#ifdef __sparc_v9__
- host->unchecked_isa_dma = 1;
-#endif
-
- fc->channels = 1;
- fc->targets = 127;
- fc->ages = ages;
- memset (ages, 0, 128 * sizeof(long));
-
- fcal->fc = fc;
-
- FCALD(("Found FCAL\n"))
- }
- if (nfcals)
-#ifdef __sparc__
- printk ("FCAL: Total of %d Sun Enterprise Network Array (A5000 or EX500) channels found\n", nfcals);
-#else
- printk ("FCAL: Total of %d Fibre Channel Arbitrated Loops found\n", nfcals);
-#endif
- return nfcals;
-}
-
-int fcal_release(struct Scsi_Host *host)
-{
- struct fcal *fcal = (struct fcal *)host->hostdata;
- fc_channel *fc = fcal->fc;
-
- module_put(fc->module);
-
- fc->fcp_register(fc, TYPE_SCSI_FCP, 1);
- FCALND((" releasing fcal.\n"));
- kfree (fc->ages);
- FCALND(("released fcal!\n"));
- return 0;
-}
-
-#undef SPRINTF
-#define SPRINTF(args...) { if (pos < (buffer + length)) pos += sprintf (pos, ## args); }
-
-int fcal_proc_info (struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int inout)
-{
- struct fcal *fcal;
- fc_channel *fc;
- char *pos = buffer;
- int i, j;
-
- if (inout) return length;
-
- fcal = (struct fcal *)host->hostdata;
- fc = fcal->fc;
-
-#ifdef __sparc__
- SPRINTF ("Sun Enterprise Network Array (A5000 or E?500) on %s PROM node %x\n", fc->name, fc->dev->prom_node);
-#else
- SPRINTF ("Fibre Channel Arbitrated Loop on %s\n", fc->name);
-#endif
- SPRINTF ("Initiator AL-PA: %02x\n", fc->sid);
-
- SPRINTF ("\nAttached devices:\n");
-
- for (i = 0; i < fc->posmap->len; i++) {
- unsigned char alpa = fc->posmap->list[i];
- unsigned char target;
- u32 *u1, *u2;
-
- target = alpa2target[alpa];
- u1 = (u32 *)&fcal->nport_wwn[target];
- u2 = (u32 *)&fcal->node_wwn[target];
- if (!u1[0] && !u1[1]) {
- SPRINTF (" [AL-PA: %02x] Not responded to PLOGI\n", alpa);
- } else if (!fcal->map[target]) {
- SPRINTF (" [AL-PA: %02x, Port WWN: %08x%08x, Node WWN: %08x%08x] Not responded to PRLI\n",
- alpa, u1[0], u1[1], u2[0], u2[1]);
- } else {
- struct scsi_device *scd;
- shost_for_each_device(scd, host)
- if (scd->id == target) {
- SPRINTF (" [AL-PA: %02x, Id: %02d, Port WWN: %08x%08x, Node WWN: %08x%08x] ",
- alpa, target, u1[0], u1[1], u2[0], u2[1]);
- SPRINTF ("%s ", scsi_device_type(scd->type));
-
- for (j = 0; (j < 8) && (scd->vendor[j] >= 0x20); j++)
- SPRINTF ("%c", scd->vendor[j]);
- SPRINTF (" ");
-
- for (j = 0; (j < 16) && (scd->model[j] >= 0x20); j++)
- SPRINTF ("%c", scd->model[j]);
-
- SPRINTF ("\n");
- }
- }
- }
- SPRINTF ("\n");
-
- *start = buffer + offset;
-
- if ((pos - buffer) < offset)
- return 0;
- else if (pos - buffer - offset < length)
- return pos - buffer - offset;
- else
- return length;
-}
-
-/*
- For FC-AL, we use a simple addressing: we have just one channel 0,
- and all AL-PAs are mapped to targets 0..0x7e
- */
-static int fcal_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr, fc_channel *fc, fcp_cmnd *fcmd)
-{
- struct fcal *f;
-
- /* We don't support LUNs yet - I'm not sure if LUN should be in SCSI fcp_cdb, or in second byte of addr[0] */
- if (SCpnt->cmnd[1] & 0xe0) return -EINVAL;
- /* FC-PLDA tells us... */
- memset(addr, 0, 8);
- f = (struct fcal *)SCpnt->device->host->hostdata;
- if (!f->map[SCpnt->device->id])
- return -EINVAL;
- /* Now, determine DID: It will be Native Identifier, so we zero upper
- 2 bytes of the 3 byte DID, lowest byte will be AL-PA */
- fcmd->did = target2alpa[SCpnt->device->id];
- FCALD(("trying DID %06x\n", fcmd->did))
- return 0;
-}
-
-static struct scsi_host_template driver_template = {
- .name = "Fibre Channel Arbitrated Loop",
- .detect = fcal_detect,
- .release = fcal_release,
- .proc_info = fcal_proc_info,
- .queuecommand = fcp_scsi_queuecommand,
- .slave_configure = fcal_slave_configure,
- .can_queue = FCAL_CAN_QUEUE,
- .this_id = -1,
- .sg_tablesize = 1,
- .cmd_per_lun = 1,
- .use_clustering = ENABLE_CLUSTERING,
- .eh_abort_handler = fcp_scsi_abort,
- .eh_device_reset_handler = fcp_scsi_dev_reset,
- .eh_host_reset_handler = fcp_scsi_host_reset,
-};
-#include "scsi_module.c"
-
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/scsi/fcal.h b/drivers/scsi/fcal.h
deleted file mode 100644
index 7ff2c3494f9e..000000000000
--- a/drivers/scsi/fcal.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* fcal.h: Generic Fibre Channel Arbitrated Loop SCSI host adapter driver definitions.
- *
- * Copyright (C) 1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
- */
-
-#ifndef _FCAL_H
-#define _FCAL_H
-
-#include "../fc4/fcp_impl.h"
-
-struct fcal {
- /* fc must be first */
- fc_channel *fc;
- unsigned char map[128];
- fc_wwn nport_wwn[128];
- fc_wwn node_wwn[128];
-};
-
-/* Arbitrary constant. Cannot be too large, as fc4 layer has limitations
- for a particular channel */
-#define FCAL_CAN_QUEUE 512
-
-int fcal_detect(struct scsi_host_template *);
-int fcal_release(struct Scsi_Host *);
-int fcal_slave_configure(struct scsi_device *);
-
-#endif /* !(_FCAL_H) */
diff --git a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c
index 668569e8856b..8335b608e571 100644
--- a/drivers/scsi/fd_mcs.c
+++ b/drivers/scsi/fd_mcs.c
@@ -973,7 +973,7 @@ static irqreturn_t fd_mcs_intr(int irq, void *dev_id)
if (current_SC->SCp.buffers_residual) {
--current_SC->SCp.buffers_residual;
++current_SC->SCp.buffer;
- current_SC->SCp.ptr = page_address(current_SC->SCp.buffer->page) + current_SC->SCp.buffer->offset;
+ current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer);
current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
} else
break;
@@ -1006,7 +1006,7 @@ static irqreturn_t fd_mcs_intr(int irq, void *dev_id)
if (!current_SC->SCp.this_residual && current_SC->SCp.buffers_residual) {
--current_SC->SCp.buffers_residual;
++current_SC->SCp.buffer;
- current_SC->SCp.ptr = page_address(current_SC->SCp.buffer->page) + current_SC->SCp.buffer->offset;
+ current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer);
current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
}
}
@@ -1109,7 +1109,7 @@ static int fd_mcs_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
if (current_SC->use_sg) {
current_SC->SCp.buffer = (struct scatterlist *) current_SC->request_buffer;
- current_SC->SCp.ptr = page_address(current_SC->SCp.buffer->page) + current_SC->SCp.buffer->offset;
+ current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer);
current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
current_SC->SCp.buffers_residual = current_SC->use_sg - 1;
} else {
diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c
index 5d282e6a6ae1..2cd6b4959eb2 100644
--- a/drivers/scsi/fdomain.c
+++ b/drivers/scsi/fdomain.c
@@ -1321,7 +1321,7 @@ static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id)
if (current_SC->SCp.buffers_residual) {
--current_SC->SCp.buffers_residual;
++current_SC->SCp.buffer;
- current_SC->SCp.ptr = page_address(current_SC->SCp.buffer->page) + current_SC->SCp.buffer->offset;
+ current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer);
current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
} else
break;
@@ -1354,7 +1354,7 @@ static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id)
&& current_SC->SCp.buffers_residual) {
--current_SC->SCp.buffers_residual;
++current_SC->SCp.buffer;
- current_SC->SCp.ptr = page_address(current_SC->SCp.buffer->page) + current_SC->SCp.buffer->offset;
+ current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer);
current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
}
}
@@ -1439,8 +1439,7 @@ static int fdomain_16x0_queue(struct scsi_cmnd *SCpnt,
if (scsi_sg_count(current_SC)) {
current_SC->SCp.buffer = scsi_sglist(current_SC);
- current_SC->SCp.ptr = page_address(current_SC->SCp.buffer->page)
- + current_SC->SCp.buffer->offset;
+ current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer);
current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
current_SC->SCp.buffers_residual = scsi_sg_count(current_SC) - 1;
} else {
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 3ac080ee6e2f..b253b8c718d3 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -2374,18 +2374,18 @@ static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp,
if (cpsum+cpnow > cpcount)
cpnow = cpcount - cpsum;
cpsum += cpnow;
- if (!sl->page) {
+ if (!sg_page(sl)) {
printk("GDT-HA %d: invalid sc/gt element in gdth_copy_internal_data()\n",
ha->hanum);
return;
}
local_irq_save(flags);
- address = kmap_atomic(sl->page, KM_BIO_SRC_IRQ) + sl->offset;
+ address = kmap_atomic(sg_page(sl), KM_BIO_SRC_IRQ) + sl->offset;
if (to_buffer)
memcpy(buffer, address, cpnow);
else
memcpy(address, buffer, cpnow);
- flush_dcache_page(sl->page);
+ flush_dcache_page(sg_page(sl));
kunmap_atomic(address, KM_BIO_SRC_IRQ);
local_irq_restore(flags);
if (cpsum == cpcount)
@@ -4734,7 +4734,7 @@ static struct scsi_host_template gdth_template = {
};
#ifdef CONFIG_ISA
-static int gdth_isa_probe_one(ulong32 isa_bios)
+static int __init gdth_isa_probe_one(ulong32 isa_bios)
{
struct Scsi_Host *shp;
gdth_ha_str *ha;
@@ -4862,7 +4862,7 @@ static int gdth_isa_probe_one(ulong32 isa_bios)
#endif /* CONFIG_ISA */
#ifdef CONFIG_EISA
-static int gdth_eisa_probe_one(ushort eisa_slot)
+static int __init gdth_eisa_probe_one(ushort eisa_slot)
{
struct Scsi_Host *shp;
gdth_ha_str *ha;
@@ -4991,7 +4991,7 @@ static int gdth_eisa_probe_one(ushort eisa_slot)
#endif /* CONFIG_EISA */
#ifdef CONFIG_PCI
-static int gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr)
+static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr)
{
struct Scsi_Host *shp;
gdth_ha_str *ha;
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index adc9559cb6f4..24271a871b8c 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -343,6 +343,13 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
shost->use_clustering = sht->use_clustering;
shost->ordered_tag = sht->ordered_tag;
shost->active_mode = sht->supported_mode;
+ shost->use_sg_chaining = sht->use_sg_chaining;
+
+ if (sht->supported_mode == MODE_UNKNOWN)
+ /* means we didn't set it ... default to INITIATOR */
+ shost->active_mode = MODE_INITIATOR;
+ else
+ shost->active_mode = sht->supported_mode;
if (sht->max_host_blocked)
shost->max_host_blocked = sht->max_host_blocked;
diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c
index 8b384fa7f048..0844331abb87 100644
--- a/drivers/scsi/hptiop.c
+++ b/drivers/scsi/hptiop.c
@@ -375,8 +375,9 @@ static void hptiop_host_request_callback(struct hptiop_hba *hba, u32 _tag)
scp->result = SAM_STAT_CHECK_CONDITION;
memset(&scp->sense_buffer,
0, sizeof(scp->sense_buffer));
- memcpy(&scp->sense_buffer,
- &req->sg_list, le32_to_cpu(req->dataxfer_length));
+ memcpy(&scp->sense_buffer, &req->sg_list,
+ min(sizeof(scp->sense_buffer),
+ le32_to_cpu(req->dataxfer_length)));
break;
default:
@@ -655,6 +656,7 @@ static struct scsi_host_template driver_template = {
.unchecked_isa_dma = 0,
.emulated = 0,
.use_clustering = ENABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
.proc_name = driver_name,
.shost_attrs = hptiop_attrs,
.this_id = -1,
diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c
index 1a924e9b0271..db004a450732 100644
--- a/drivers/scsi/ibmmca.c
+++ b/drivers/scsi/ibmmca.c
@@ -1501,6 +1501,7 @@ static struct scsi_host_template ibmmca_driver_template = {
.sg_tablesize = 16,
.cmd_per_lun = 1,
.use_clustering = ENABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
};
static int ibmmca_probe(struct device *dev)
@@ -1827,7 +1828,7 @@ static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
BUG_ON(scsi_sg_count(cmd) > 16);
scsi_for_each_sg(cmd, sg, scsi_sg_count(cmd), i) {
- ld(shpnt)[ldn].sge[i].address = (void *) (isa_page_to_bus(sg->page) + sg->offset);
+ ld(shpnt)[ldn].sge[i].address = (void *) (isa_page_to_bus(sg_page(sg)) + sg->offset);
ld(shpnt)[ldn].sge[i].byte_length = sg->length;
}
scb->enable |= IM_POINTER_TO_LIST;
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index cda0cc3d182f..5f2396c03958 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -556,7 +556,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
unsigned long timeout)
{
u64 *crq_as_u64 = (u64 *) &evt_struct->crq;
- int request_status;
+ int request_status = 0;
int rc;
/* If we have exhausted our request limit, just fail this request,
@@ -574,6 +574,13 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
if (request_status < -1)
goto send_error;
/* Otherwise, we may have run out of requests. */
+ /* If request limit was 0 when we started the adapter is in the
+ * process of performing a login with the server adapter, or
+ * we may have run out of requests.
+ */
+ else if (request_status == -1 &&
+ evt_struct->iu.srp.login_req.opcode != SRP_LOGIN_REQ)
+ goto send_busy;
/* Abort and reset calls should make it through.
* Nothing except abort and reset should use the last two
* slots unless we had two or less to begin with.
@@ -633,7 +640,8 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev);
free_event_struct(&hostdata->pool, evt_struct);
- atomic_inc(&hostdata->request_limit);
+ if (request_status != -1)
+ atomic_inc(&hostdata->request_limit);
return SCSI_MLQUEUE_HOST_BUSY;
send_error:
@@ -927,10 +935,11 @@ static int send_srp_login(struct ibmvscsi_host_data *hostdata)
login->req_buf_fmt = SRP_BUF_FORMAT_DIRECT | SRP_BUF_FORMAT_INDIRECT;
spin_lock_irqsave(hostdata->host->host_lock, flags);
- /* Start out with a request limit of 1, since this is negotiated in
- * the login request we are just sending
+ /* Start out with a request limit of 0, since this is negotiated in
+ * the login request we are just sending and login requests always
+ * get sent by the driver regardless of request_limit.
*/
- atomic_set(&hostdata->request_limit, 1);
+ atomic_set(&hostdata->request_limit, 0);
rc = ibmvscsi_send_srp_event(evt_struct, hostdata, init_timeout * 2);
spin_unlock_irqrestore(hostdata->host->host_lock, flags);
@@ -1548,6 +1557,7 @@ static struct scsi_host_template driver_template = {
.this_id = -1,
.sg_tablesize = SG_ALL,
.use_clustering = ENABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
.shost_attrs = ibmvscsi_attrs,
};
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index d81bb076a15a..8d0244c2e7d4 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -47,9 +47,9 @@
#include <linux/scatterlist.h>
#include <linux/delay.h>
#include <linux/mutex.h>
+#include <linux/bitops.h>
#include <asm/io.h>
-#include <asm/bitops.h>
#include <asm/uaccess.h>
#include <scsi/scsi.h>
@@ -70,6 +70,7 @@ typedef struct idescsi_pc_s {
u8 *buffer; /* Data buffer */
u8 *current_position; /* Pointer into the above buffer */
struct scatterlist *sg; /* Scatter gather table */
+ unsigned int sg_cnt; /* Number of entries in sg */
int b_count; /* Bytes transferred from current entry */
struct scsi_cmnd *scsi_cmd; /* SCSI command */
void (*done)(struct scsi_cmnd *); /* Scsi completion routine */
@@ -173,34 +174,35 @@ static void idescsi_input_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigne
char *buf;
while (bcount) {
- if (pc->sg - scsi_sglist(pc->scsi_cmd) >
- scsi_sg_count(pc->scsi_cmd)) {
- printk (KERN_ERR "ide-scsi: scatter gather table too small, discarding data\n");
- idescsi_discard_data (drive, bcount);
- return;
- }
count = min(pc->sg->length - pc->b_count, bcount);
- if (PageHighMem(pc->sg->page)) {
+ if (PageHighMem(sg_page(pc->sg))) {
unsigned long flags;
local_irq_save(flags);
- buf = kmap_atomic(pc->sg->page, KM_IRQ0) +
+ buf = kmap_atomic(sg_page(pc->sg), KM_IRQ0) +
pc->sg->offset;
drive->hwif->atapi_input_bytes(drive,
buf + pc->b_count, count);
kunmap_atomic(buf - pc->sg->offset, KM_IRQ0);
local_irq_restore(flags);
} else {
- buf = page_address(pc->sg->page) + pc->sg->offset;
+ buf = sg_virt(pc->sg);
drive->hwif->atapi_input_bytes(drive,
buf + pc->b_count, count);
}
bcount -= count; pc->b_count += count;
if (pc->b_count == pc->sg->length) {
- pc->sg++;
+ if (!--pc->sg_cnt)
+ break;
+ pc->sg = sg_next(pc->sg);
pc->b_count = 0;
}
}
+
+ if (bcount) {
+ printk (KERN_ERR "ide-scsi: scatter gather table too small, discarding data\n");
+ idescsi_discard_data (drive, bcount);
+ }
}
static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigned int bcount)
@@ -209,34 +211,35 @@ static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsign
char *buf;
while (bcount) {
- if (pc->sg - scsi_sglist(pc->scsi_cmd) >
- scsi_sg_count(pc->scsi_cmd)) {
- printk (KERN_ERR "ide-scsi: scatter gather table too small, padding with zeros\n");
- idescsi_output_zeros (drive, bcount);
- return;
- }
count = min(pc->sg->length - pc->b_count, bcount);
- if (PageHighMem(pc->sg->page)) {
+ if (PageHighMem(sg_page(pc->sg))) {
unsigned long flags;
local_irq_save(flags);
- buf = kmap_atomic(pc->sg->page, KM_IRQ0) +
+ buf = kmap_atomic(sg_page(pc->sg), KM_IRQ0) +
pc->sg->offset;
drive->hwif->atapi_output_bytes(drive,
buf + pc->b_count, count);
kunmap_atomic(buf - pc->sg->offset, KM_IRQ0);
local_irq_restore(flags);
} else {
- buf = page_address(pc->sg->page) + pc->sg->offset;
+ buf = sg_virt(pc->sg);
drive->hwif->atapi_output_bytes(drive,
buf + pc->b_count, count);
}
bcount -= count; pc->b_count += count;
if (pc->b_count == pc->sg->length) {
- pc->sg++;
+ if (!--pc->sg_cnt)
+ break;
+ pc->sg = sg_next(pc->sg);
pc->b_count = 0;
}
}
+
+ if (bcount) {
+ printk (KERN_ERR "ide-scsi: scatter gather table too small, padding with zeros\n");
+ idescsi_output_zeros (drive, bcount);
+ }
}
static void hexdump(u8 *x, int len)
@@ -804,6 +807,7 @@ static int idescsi_queue (struct scsi_cmnd *cmd,
memcpy (pc->c, cmd->cmnd, cmd->cmd_len);
pc->buffer = NULL;
pc->sg = scsi_sglist(cmd);
+ pc->sg_cnt = scsi_sg_count(cmd);
pc->b_count = 0;
pc->request_transfer = pc->buffer_size = scsi_bufflen(cmd);
pc->scsi_cmd = cmd;
diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c
index 74cdc1f0a78f..a3d0c6b14958 100644
--- a/drivers/scsi/imm.c
+++ b/drivers/scsi/imm.c
@@ -705,9 +705,7 @@ static int imm_completion(struct scsi_cmnd *cmd)
cmd->SCp.buffer++;
cmd->SCp.this_residual =
cmd->SCp.buffer->length;
- cmd->SCp.ptr =
- page_address(cmd->SCp.buffer->page) +
- cmd->SCp.buffer->offset;
+ cmd->SCp.ptr = sg_virt(cmd->SCp.buffer);
/*
* Make sure that we transfer even number of bytes
@@ -844,9 +842,7 @@ static int imm_engine(imm_struct *dev, struct scsi_cmnd *cmd)
cmd->SCp.buffer =
(struct scatterlist *) cmd->request_buffer;
cmd->SCp.this_residual = cmd->SCp.buffer->length;
- cmd->SCp.ptr =
- page_address(cmd->SCp.buffer->page) +
- cmd->SCp.buffer->offset;
+ cmd->SCp.ptr = sg_virt(cmd->SCp.buffer);
} else {
/* else fill the only available buffer */
cmd->SCp.buffer = NULL;
diff --git a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c
index ab7cbf3449ce..c8b452f2878c 100644
--- a/drivers/scsi/in2000.c
+++ b/drivers/scsi/in2000.c
@@ -372,7 +372,7 @@ static int in2000_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
if (cmd->use_sg) {
cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer;
cmd->SCp.buffers_residual = cmd->use_sg - 1;
- cmd->SCp.ptr = (char *) page_address(cmd->SCp.buffer->page) + cmd->SCp.buffer->offset;
+ cmd->SCp.ptr = sg_virt(cmd->SCp.buffer);
cmd->SCp.this_residual = cmd->SCp.buffer->length;
} else {
cmd->SCp.buffer = NULL;
@@ -764,7 +764,7 @@ static void transfer_bytes(Scsi_Cmnd * cmd, int data_in_dir)
++cmd->SCp.buffer;
--cmd->SCp.buffers_residual;
cmd->SCp.this_residual = cmd->SCp.buffer->length;
- cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) + cmd->SCp.buffer->offset;
+ cmd->SCp.ptr = sg_virt(cmd->SCp.buffer);
}
/* Set up hardware registers */
diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c
index d9dfb69ae031..4c4465d39a1d 100644
--- a/drivers/scsi/initio.c
+++ b/drivers/scsi/initio.c
@@ -665,7 +665,7 @@ static void initio_init(struct initio_host * host, u8 *bios_addr)
host->max_tags[i] = 0xFF;
} /* for */
printk("i91u: PCI Base=0x%04X, IRQ=%d, BIOS=0x%04X0, SCSI ID=%d\n",
- host->addr, host->irq,
+ host->addr, host->pci_dev->irq,
host->bios_addr, host->scsi_id);
/* Reset SCSI Bus */
if (host->config & HCC_SCSI_RESET) {
@@ -2831,6 +2831,7 @@ static struct scsi_host_template initio_template = {
.sg_tablesize = SG_ALL,
.cmd_per_lun = 1,
.use_clustering = ENABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
};
static int initio_probe_one(struct pci_dev *pdev,
@@ -2890,6 +2891,8 @@ static int initio_probe_one(struct pci_dev *pdev,
goto out_release_region;
}
+ host->pci_dev = pdev;
+
host->num_scbs = num_scb;
host->scb = scb;
host->next_pending = scb;
@@ -2904,6 +2907,7 @@ static int initio_probe_one(struct pci_dev *pdev,
host->scb_end = tmp;
host->first_avail = scb;
host->last_avail = prev;
+ spin_lock_init(&host->avail_lock);
initio_init(host, phys_to_virt(bios_seg << 4));
@@ -2927,7 +2931,6 @@ static int initio_probe_one(struct pci_dev *pdev,
}
pci_set_drvdata(pdev, shost);
- host->pci_dev = pdev;
error = scsi_add_host(shost, &pdev->dev);
if (error)
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index b41dfb539021..0841df01bc19 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -2872,6 +2872,7 @@ static struct ipr_sglist *ipr_alloc_ucode_buffer(int buf_len)
}
scatterlist = sglist->scatterlist;
+ sg_init_table(scatterlist, num_elem);
sglist->order = order;
sglist->num_sg = num_elem;
@@ -2884,12 +2885,12 @@ static struct ipr_sglist *ipr_alloc_ucode_buffer(int buf_len)
/* Free up what we already allocated */
for (j = i - 1; j >= 0; j--)
- __free_pages(scatterlist[j].page, order);
+ __free_pages(sg_page(&scatterlist[j]), order);
kfree(sglist);
return NULL;
}
- scatterlist[i].page = page;
+ sg_set_page(&scatterlist[i], page, 0, 0);
}
return sglist;
@@ -2910,7 +2911,7 @@ static void ipr_free_ucode_buffer(struct ipr_sglist *sglist)
int i;
for (i = 0; i < sglist->num_sg; i++)
- __free_pages(sglist->scatterlist[i].page, sglist->order);
+ __free_pages(sg_page(&sglist->scatterlist[i]), sglist->order);
kfree(sglist);
}
@@ -2940,9 +2941,11 @@ static int ipr_copy_ucode_buffer(struct ipr_sglist *sglist,
scatterlist = sglist->scatterlist;
for (i = 0; i < (len / bsize_elem); i++, buffer += bsize_elem) {
- kaddr = kmap(scatterlist[i].page);
+ struct page *page = sg_page(&scatterlist[i]);
+
+ kaddr = kmap(page);
memcpy(kaddr, buffer, bsize_elem);
- kunmap(scatterlist[i].page);
+ kunmap(page);
scatterlist[i].length = bsize_elem;
@@ -2953,9 +2956,11 @@ static int ipr_copy_ucode_buffer(struct ipr_sglist *sglist,
}
if (len % bsize_elem) {
- kaddr = kmap(scatterlist[i].page);
+ struct page *page = sg_page(&scatterlist[i]);
+
+ kaddr = kmap(page);
memcpy(kaddr, buffer, len % bsize_elem);
- kunmap(scatterlist[i].page);
+ kunmap(page);
scatterlist[i].length = len % bsize_elem;
}
@@ -5134,6 +5139,7 @@ static void ipr_build_ata_ioadl(struct ipr_cmnd *ipr_cmd,
u32 ioadl_flags = 0;
struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb;
struct ipr_ioadl_desc *ioadl = ipr_cmd->ioadl;
+ struct ipr_ioadl_desc *last_ioadl = NULL;
int len = qc->nbytes + qc->pad_len;
struct scatterlist *sg;
@@ -5156,11 +5162,13 @@ static void ipr_build_ata_ioadl(struct ipr_cmnd *ipr_cmd,
ata_for_each_sg(sg, qc) {
ioadl->flags_and_data_len = cpu_to_be32(ioadl_flags | sg_dma_len(sg));
ioadl->address = cpu_to_be32(sg_dma_address(sg));
- if (ata_sg_is_last(sg, qc))
- ioadl->flags_and_data_len |= cpu_to_be32(IPR_IOADL_FLAGS_LAST);
- else
- ioadl++;
+
+ last_ioadl = ioadl;
+ ioadl++;
}
+
+ if (likely(last_ioadl))
+ last_ioadl->flags_and_data_len |= cpu_to_be32(IPR_IOADL_FLAGS_LAST);
}
/**
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index 2ed099e2c20d..5c5a9b2628fc 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -1515,7 +1515,7 @@ static int ips_is_passthru(struct scsi_cmnd *SC)
/* kmap_atomic() ensures addressability of the user buffer.*/
/* local_irq_save() protects the KM_IRQ0 address slot. */
local_irq_save(flags);
- buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+ buffer = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
if (buffer && buffer[0] == 'C' && buffer[1] == 'O' &&
buffer[2] == 'P' && buffer[3] == 'P') {
kunmap_atomic(buffer - sg->offset, KM_IRQ0);
@@ -3252,7 +3252,7 @@ ips_done(ips_ha_t * ha, ips_scb_t * scb)
*/
if ((scb->breakup) || (scb->sg_break)) {
struct scatterlist *sg;
- int sg_dma_index, ips_sg_index = 0;
+ int i, sg_dma_index, ips_sg_index = 0;
/* we had a data breakup */
scb->data_len = 0;
@@ -3261,20 +3261,22 @@ ips_done(ips_ha_t * ha, ips_scb_t * scb)
/* Spin forward to last dma chunk */
sg_dma_index = scb->breakup;
+ for (i = 0; i < scb->breakup; i++)
+ sg = sg_next(sg);
/* Take care of possible partial on last chunk */
ips_fill_scb_sg_single(ha,
- sg_dma_address(&sg[sg_dma_index]),
+ sg_dma_address(sg),
scb, ips_sg_index++,
- sg_dma_len(&sg[sg_dma_index]));
+ sg_dma_len(sg));
for (; sg_dma_index < scsi_sg_count(scb->scsi_cmd);
- sg_dma_index++) {
+ sg_dma_index++, sg = sg_next(sg)) {
if (ips_fill_scb_sg_single
(ha,
- sg_dma_address(&sg[sg_dma_index]),
+ sg_dma_address(sg),
scb, ips_sg_index++,
- sg_dma_len(&sg[sg_dma_index])) < 0)
+ sg_dma_len(sg)) < 0)
break;
}
@@ -3521,7 +3523,7 @@ ips_scmd_buf_write(struct scsi_cmnd *scmd, void *data, unsigned int count)
/* kmap_atomic() ensures addressability of the data buffer.*/
/* local_irq_save() protects the KM_IRQ0 address slot. */
local_irq_save(flags);
- buffer = kmap_atomic(sg[i].page, KM_IRQ0) + sg[i].offset;
+ buffer = kmap_atomic(sg_page(&sg[i]), KM_IRQ0) + sg[i].offset;
memcpy(buffer, &cdata[xfer_cnt], min_cnt);
kunmap_atomic(buffer - sg[i].offset, KM_IRQ0);
local_irq_restore(flags);
@@ -3554,7 +3556,7 @@ ips_scmd_buf_read(struct scsi_cmnd *scmd, void *data, unsigned int count)
/* kmap_atomic() ensures addressability of the data buffer.*/
/* local_irq_save() protects the KM_IRQ0 address slot. */
local_irq_save(flags);
- buffer = kmap_atomic(sg[i].page, KM_IRQ0) + sg[i].offset;
+ buffer = kmap_atomic(sg_page(&sg[i]), KM_IRQ0) + sg[i].offset;
memcpy(&cdata[xfer_cnt], buffer, min_cnt);
kunmap_atomic(buffer - sg[i].offset, KM_IRQ0);
local_irq_restore(flags);
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index a21455d0274c..4bcf916c21a7 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -70,9 +70,7 @@ module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO);
static inline void
iscsi_buf_init_iov(struct iscsi_buf *ibuf, char *vbuf, int size)
{
- ibuf->sg.page = virt_to_page(vbuf);
- ibuf->sg.offset = offset_in_page(vbuf);
- ibuf->sg.length = size;
+ sg_init_one(&ibuf->sg, vbuf, size);
ibuf->sent = 0;
ibuf->use_sendmsg = 1;
}
@@ -80,13 +78,12 @@ iscsi_buf_init_iov(struct iscsi_buf *ibuf, char *vbuf, int size)
static inline void
iscsi_buf_init_sg(struct iscsi_buf *ibuf, struct scatterlist *sg)
{
- ibuf->sg.page = sg->page;
- ibuf->sg.offset = sg->offset;
- ibuf->sg.length = sg->length;
+ sg_init_table(&ibuf->sg, 1);
+ sg_set_page(&ibuf->sg, sg_page(sg), sg->length, sg->offset);
/*
* Fastpath: sg element fits into single page
*/
- if (sg->length + sg->offset <= PAGE_SIZE && !PageSlab(sg->page))
+ if (sg->length + sg->offset <= PAGE_SIZE && !PageSlab(sg_page(sg)))
ibuf->use_sendmsg = 0;
else
ibuf->use_sendmsg = 1;
@@ -677,9 +674,8 @@ partial_sg_digest_update(struct hash_desc *desc, struct scatterlist *sg,
{
struct scatterlist temp;
- memcpy(&temp, sg, sizeof(struct scatterlist));
- temp.offset = offset;
- temp.length = length;
+ sg_init_table(&temp, 1);
+ sg_set_page(&temp, sg_page(sg), length, offset);
crypto_hash_update(desc, &temp, length);
}
@@ -716,7 +712,7 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn)
for (i = tcp_ctask->sg_count; i < scsi_sg_count(sc); i++) {
char *dest;
- dest = kmap_atomic(sg[i].page, KM_SOFTIRQ0);
+ dest = kmap_atomic(sg_page(&sg[i]), KM_SOFTIRQ0);
rc = iscsi_ctask_copy(tcp_conn, ctask, dest + sg[i].offset,
sg[i].length, offset);
kunmap_atomic(dest, KM_SOFTIRQ0);
@@ -1103,9 +1099,9 @@ iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags)
* slab case.
*/
if (buf->use_sendmsg)
- res = sock_no_sendpage(sk, buf->sg.page, offset, size, flags);
+ res = sock_no_sendpage(sk, sg_page(&buf->sg), offset, size, flags);
else
- res = tcp_conn->sendpage(sk, buf->sg.page, offset, size, flags);
+ res = tcp_conn->sendpage(sk, sg_page(&buf->sg), offset, size, flags);
if (res >= 0) {
conn->txdata_octets += res;
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c
index 7ef0afc3cd68..5f3a0d7b18de 100644
--- a/drivers/scsi/libsas/sas_discover.c
+++ b/drivers/scsi/libsas/sas_discover.c
@@ -285,7 +285,7 @@ static void sas_discover_domain(struct work_struct *work)
dev = port->port_dev;
SAS_DPRINTK("DOING DISCOVERY on port %d, pid:%d\n", port->id,
- current->pid);
+ task_pid_nr(current));
switch (dev->dev_type) {
case SAS_END_DEV:
@@ -320,7 +320,7 @@ static void sas_discover_domain(struct work_struct *work)
}
SAS_DPRINTK("DONE DISCOVERY on port %d, pid:%d, result:%d\n", port->id,
- current->pid, error);
+ task_pid_nr(current), error);
}
static void sas_revalidate_domain(struct work_struct *work)
@@ -334,12 +334,12 @@ static void sas_revalidate_domain(struct work_struct *work)
&port->disc.pending);
SAS_DPRINTK("REVALIDATING DOMAIN on port %d, pid:%d\n", port->id,
- current->pid);
+ task_pid_nr(current));
if (port->port_dev)
res = sas_ex_revalidate_domain(port->port_dev);
SAS_DPRINTK("done REVALIDATING DOMAIN on port %d, pid:%d, res 0x%x\n",
- port->id, current->pid, res);
+ port->id, task_pid_nr(current), res);
}
/* ---------- Events ---------- */
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index 149fdd25f8e8..d6a98bc970ff 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -901,7 +901,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
}
}
- vport->disc_trc = kmzlloc(
+ vport->disc_trc = kzalloc(
(sizeof(struct lpfc_debugfs_trc) * lpfc_debugfs_max_disc_trc),
GFP_KERNEL);
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index cd674938ccd5..4e46045dea6d 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -682,6 +682,7 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb;
struct lpfc_iocbq *piocbq = &(lpfc_cmd->cur_iocbq);
int datadir = scsi_cmnd->sc_data_direction;
+ char tag[2];
lpfc_cmd->fcp_rsp->rspSnsLen = 0;
/* clear task management bits */
@@ -692,8 +693,8 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
memcpy(&fcp_cmnd->fcpCdb[0], scsi_cmnd->cmnd, 16);
- if (scsi_cmnd->device->tagged_supported) {
- switch (scsi_cmnd->tag) {
+ if (scsi_populate_tag_msg(scsi_cmnd, tag)) {
+ switch (tag[0]) {
case HEAD_OF_QUEUE_TAG:
fcp_cmnd->fcpCntl1 = HEAD_OF_Q;
break;
@@ -1438,6 +1439,7 @@ struct scsi_host_template lpfc_template = {
.scan_finished = lpfc_scan_finished,
.this_id = -1,
.sg_tablesize = LPFC_SG_SEG_CNT,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
.cmd_per_lun = LPFC_CMD_PER_LUN,
.use_clustering = ENABLE_CLUSTERING,
.shost_attrs = lpfc_hba_attrs,
@@ -1460,6 +1462,7 @@ struct scsi_host_template lpfc_vport_template = {
.sg_tablesize = LPFC_SG_SEG_CNT,
.cmd_per_lun = LPFC_CMD_PER_LUN,
.use_clustering = ENABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
.shost_attrs = lpfc_vport_attrs,
.max_sectors = 0xFFFF,
};
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index e5337ad4121e..ce348c5c706c 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -1243,7 +1243,8 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba *phba)
memset(adaptermsg, 0, LPFC_MAX_ADPTMSG);
memcpy(&adaptermsg[0], (uint8_t *) irsp,
MAX_MSG_DATA);
- dev_warn(&((phba->pcidev)->dev), "lpfc%d: %s",
+ dev_warn(&((phba->pcidev)->dev),
+ "lpfc%d: %s\n",
phba->brd_no, adaptermsg);
} else {
/* Unknown IOCB command */
@@ -1430,7 +1431,8 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba,
memset(adaptermsg, 0, LPFC_MAX_ADPTMSG);
memcpy(&adaptermsg[0], (uint8_t *) irsp,
MAX_MSG_DATA);
- dev_warn(&((phba->pcidev)->dev), "lpfc%d: %s",
+ dev_warn(&((phba->pcidev)->dev),
+ "lpfc%d: %s\n",
phba->brd_no, adaptermsg);
} else {
/* Unknown IOCB command */
@@ -1681,7 +1683,7 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba,
memcpy(&adaptermsg[0], (uint8_t *) irsp,
MAX_MSG_DATA);
dev_warn(&((phba->pcidev)->dev),
- "lpfc%d: %s",
+ "lpfc%d: %s\n",
phba->brd_no, adaptermsg);
} else {
/* Unknown IOCB command */
diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c
index b12ad7c7c673..a035001f4438 100644
--- a/drivers/scsi/mac53c94.c
+++ b/drivers/scsi/mac53c94.c
@@ -402,6 +402,7 @@ static struct scsi_host_template mac53c94_template = {
.sg_tablesize = SG_ALL,
.cmd_per_lun = 1,
.use_clustering = DISABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
};
static int mac53c94_probe(struct macio_dev *mdev, const struct of_device_id *match)
diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c
index cdbcaa5ad6cf..abe2bda6ac37 100644
--- a/drivers/scsi/mac_scsi.c
+++ b/drivers/scsi/mac_scsi.c
@@ -53,6 +53,11 @@
#include "scsi.h"
#include <scsi/scsi_host.h>
#include "mac_scsi.h"
+
+/* These control the behaviour of the generic 5380 core */
+#define AUTOSENSE
+#define PSEUDO_DMA
+
#include "NCR5380.h"
#if 0
@@ -571,10 +576,6 @@ static int macscsi_pwrite (struct Scsi_Host *instance,
}
-/* These control the behaviour of the generic 5380 core */
-#define AUTOSENSE
-#define PSEUDO_DMA
-
#include "NCR5380.c"
static struct scsi_host_template driver_template = {
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index e7e11f282c8f..66c652035730 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -658,7 +658,7 @@ mega_build_cmd(adapter_t *adapter, Scsi_Cmnd *cmd, int *busy)
struct scatterlist *sg;
sg = scsi_sglist(cmd);
- buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+ buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
memset(buf, 0, cmd->cmnd[4]);
kunmap_atomic(buf - sg->offset, KM_IRQ0);
@@ -1542,10 +1542,8 @@ mega_cmd_done(adapter_t *adapter, u8 completed[], int nstatus, int status)
if( cmd->cmnd[0] == INQUIRY && !islogical ) {
sgl = scsi_sglist(cmd);
- if( sgl->page ) {
- c = *(unsigned char *)
- page_address((&sgl[0])->page) +
- (&sgl[0])->offset;
+ if( sg_page(sgl) ) {
+ c = *(unsigned char *) sg_virt(&sgl[0]);
} else {
printk(KERN_WARNING
"megaraid: invalid sg.\n");
@@ -4492,6 +4490,7 @@ static struct scsi_host_template megaraid_template = {
.sg_tablesize = MAX_SGLIST,
.cmd_per_lun = DEF_CMD_PER_LUN,
.use_clustering = ENABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
.eh_abort_handler = megaraid_abort,
.eh_device_reset_handler = megaraid_reset,
.eh_bus_reset_handler = megaraid_reset,
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
index c6a53dccc16a..c8923108183a 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -361,6 +361,7 @@ static struct scsi_host_template megaraid_template_g = {
.eh_host_reset_handler = megaraid_reset_handler,
.change_queue_depth = megaraid_change_queue_depth,
.use_clustering = ENABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
.sdev_attrs = megaraid_sdev_attrs,
.shost_attrs = megaraid_shost_attrs,
};
@@ -426,7 +427,7 @@ megaraid_exit(void)
* @id : pci device id of the class of controllers
*
* This routine should be called whenever a new adapter is detected by the
- * PCI hotplug susbsytem.
+ * PCI hotplug susbsystem.
*/
static int __devinit
megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
@@ -1583,10 +1584,8 @@ megaraid_mbox_build_cmd(adapter_t *adapter, struct scsi_cmnd *scp, int *busy)
caddr_t vaddr;
sgl = scsi_sglist(scp);
- if (sgl->page) {
- vaddr = (caddr_t)
- (page_address((&sgl[0])->page)
- + (&sgl[0])->offset);
+ if (sg_page(sgl)) {
+ vaddr = (caddr_t) sg_virt(&sgl[0]);
memset(vaddr, 0, scp->cmnd[4]);
}
@@ -2327,10 +2326,8 @@ megaraid_mbox_dpc(unsigned long devp)
&& IS_RAID_CH(raid_dev, scb->dev_channel)) {
sgl = scsi_sglist(scp);
- if (sgl->page) {
- c = *(unsigned char *)
- (page_address((&sgl[0])->page) +
- (&sgl[0])->offset);
+ if (sg_page(sgl)) {
+ c = *(unsigned char *) sg_virt(&sgl[0]);
} else {
con_log(CL_ANN, (KERN_WARNING
"megaraid mailbox: invalid sg:%d\n",
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index ebb948c016bb..e3c5c5282203 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -1110,6 +1110,7 @@ static struct scsi_host_template megasas_template = {
.eh_timed_out = megasas_reset_timer,
.bios_param = megasas_bios_param,
.use_clustering = ENABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
};
/**
diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c
index 651d09b08f2a..7470ff39ab22 100644
--- a/drivers/scsi/mesh.c
+++ b/drivers/scsi/mesh.c
@@ -1843,6 +1843,7 @@ static struct scsi_host_template mesh_template = {
.sg_tablesize = SG_ALL,
.cmd_per_lun = 2,
.use_clustering = DISABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
};
static int mesh_probe(struct macio_dev *mdev, const struct of_device_id *match)
diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c
index 7fed35372150..28161dc95e0d 100644
--- a/drivers/scsi/nsp32.c
+++ b/drivers/scsi/nsp32.c
@@ -281,6 +281,7 @@ static struct scsi_host_template nsp32_template = {
.cmd_per_lun = 1,
.this_id = NSP32_HOST_SCSIID,
.use_clustering = DISABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
.eh_abort_handler = nsp32_eh_abort,
.eh_bus_reset_handler = nsp32_eh_bus_reset,
.eh_host_reset_handler = nsp32_eh_host_reset,
diff --git a/drivers/scsi/nsp32.h b/drivers/scsi/nsp32.h
index a976e8193d16..6715ecb3bfca 100644
--- a/drivers/scsi/nsp32.h
+++ b/drivers/scsi/nsp32.h
@@ -69,11 +69,6 @@ typedef u32 u32_le;
typedef u16 u16_le;
/*
- * MACRO
- */
-#define BIT(x) (1UL << (x))
-
-/*
* BASIC Definitions
*/
#ifndef TRUE
diff --git a/drivers/scsi/oktagon_esp.c b/drivers/scsi/oktagon_esp.c
index 26a6d55faf3e..8e5eadbd5c51 100644
--- a/drivers/scsi/oktagon_esp.c
+++ b/drivers/scsi/oktagon_esp.c
@@ -550,8 +550,7 @@ void dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd *sp)
void dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd *sp)
{
- sp->SCp.ptr = page_address(sp->SCp.buffer->page)+
- sp->SCp.buffer->offset;
+ sp->SCp.ptr = sg_virt(sp->SCp.buffer);
}
void dma_mmu_release_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd *sp)
@@ -564,8 +563,7 @@ void dma_mmu_release_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd *sp)
void dma_advance_sg(Scsi_Cmnd *sp)
{
- sp->SCp.ptr = page_address(sp->SCp.buffer->page)+
- sp->SCp.buffer->offset;
+ sp->SCp.ptr = sg_virt(sp->SCp.buffer);
}
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index 331b789937c4..abef7048f25b 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -542,7 +542,7 @@ static int osst_verify_frame(struct osst_tape * STp, int frame_seq_number, int q
if (STp->raw) {
if (STp->buffer->syscall_result) {
for (i=0; i < STp->buffer->sg_segs; i++)
- memset(page_address(STp->buffer->sg[i].page),
+ memset(page_address(sg_page(&STp->buffer->sg[i])),
0, STp->buffer->sg[i].length);
strcpy(STp->buffer->b_data, "READ ERROR ON FRAME");
} else
@@ -593,10 +593,11 @@ static int osst_verify_frame(struct osst_tape * STp, int frame_seq_number, int q
if (aux->frame_type != OS_FRAME_TYPE_DATA &&
aux->frame_type != OS_FRAME_TYPE_EOD &&
aux->frame_type != OS_FRAME_TYPE_MARKER) {
- if (!quiet)
+ if (!quiet) {
#if DEBUG
printk(OSST_DEB_MSG "%s:D: Skipping frame, frame type %x\n", name, aux->frame_type);
#endif
+ }
goto err_out;
}
if (aux->frame_type == OS_FRAME_TYPE_EOD &&
@@ -606,11 +607,12 @@ static int osst_verify_frame(struct osst_tape * STp, int frame_seq_number, int q
goto err_out;
}
if (frame_seq_number != -1 && ntohl(aux->frame_seq_num) != frame_seq_number) {
- if (!quiet)
+ if (!quiet) {
#if DEBUG
printk(OSST_DEB_MSG "%s:D: Skipping frame, sequence number %u (expected %d)\n",
name, ntohl(aux->frame_seq_num), frame_seq_number);
#endif
+ }
goto err_out;
}
if (aux->frame_type == OS_FRAME_TYPE_MARKER) {
@@ -4437,7 +4439,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
for (i = 0, b_size = 0;
(i < STp->buffer->sg_segs) && ((b_size + STp->buffer->sg[i].length) <= OS_DATA_SIZE);
b_size += STp->buffer->sg[i++].length);
- STp->buffer->aux = (os_aux_t *) (page_address(STp->buffer->sg[i].page) + OS_DATA_SIZE - b_size);
+ STp->buffer->aux = (os_aux_t *) (page_address(sg_page(&STp->buffer->sg[i])) + OS_DATA_SIZE - b_size);
#if DEBUG
printk(OSST_DEB_MSG "%s:D: b_data points to %p in segment 0 at %p\n", name,
STp->buffer->b_data, page_address(STp->buffer->sg[0].page));
@@ -5252,25 +5254,25 @@ static int enlarge_buffer(struct osst_buffer *STbuffer, int need_dma)
/* Try to allocate the first segment up to OS_DATA_SIZE and the others
big enough to reach the goal (code assumes no segments in place) */
for (b_size = OS_DATA_SIZE, order = OSST_FIRST_ORDER; b_size >= PAGE_SIZE; order--, b_size /= 2) {
- STbuffer->sg[0].page = alloc_pages(priority, order);
+ struct page *page = alloc_pages(priority, order);
+
STbuffer->sg[0].offset = 0;
- if (STbuffer->sg[0].page != NULL) {
- STbuffer->sg[0].length = b_size;
- STbuffer->b_data = page_address(STbuffer->sg[0].page);
+ if (page != NULL) {
+ sg_set_page(&STbuffer->sg[0], page, b_size, 0);
+ STbuffer->b_data = page_address(page);
break;
}
}
- if (STbuffer->sg[0].page == NULL) {
+ if (sg_page(&STbuffer->sg[0]) == NULL) {
printk(KERN_NOTICE "osst :I: Can't allocate tape buffer main segment.\n");
return 0;
}
/* Got initial segment of 'bsize,order', continue with same size if possible, except for AUX */
for (segs=STbuffer->sg_segs=1, got=b_size;
segs < max_segs && got < OS_FRAME_SIZE; ) {
- STbuffer->sg[segs].page =
- alloc_pages(priority, (OS_FRAME_SIZE - got <= PAGE_SIZE) ? 0 : order);
+ struct page *page = alloc_pages(priority, (OS_FRAME_SIZE - got <= PAGE_SIZE) ? 0 : order);
STbuffer->sg[segs].offset = 0;
- if (STbuffer->sg[segs].page == NULL) {
+ if (page == NULL) {
if (OS_FRAME_SIZE - got <= (max_segs - segs) * b_size / 2 && order) {
b_size /= 2; /* Large enough for the rest of the buffers */
order--;
@@ -5284,7 +5286,7 @@ static int enlarge_buffer(struct osst_buffer *STbuffer, int need_dma)
normalize_buffer(STbuffer);
return 0;
}
- STbuffer->sg[segs].length = (OS_FRAME_SIZE - got <= PAGE_SIZE / 2) ? (OS_FRAME_SIZE - got) : b_size;
+ sg_set_page(&STbuffer->sg[segs], page, (OS_FRAME_SIZE - got <= PAGE_SIZE / 2) ? (OS_FRAME_SIZE - got) : b_size, 0);
got += STbuffer->sg[segs].length;
STbuffer->buffer_size = got;
STbuffer->sg_segs = ++segs;
@@ -5316,7 +5318,7 @@ static void normalize_buffer(struct osst_buffer *STbuffer)
b_size < STbuffer->sg[i].length;
b_size *= 2, order++);
- __free_pages(STbuffer->sg[i].page, order);
+ __free_pages(sg_page(&STbuffer->sg[i]), order);
STbuffer->buffer_size -= STbuffer->sg[i].length;
}
#if DEBUG
@@ -5344,7 +5346,7 @@ static int append_to_buffer(const char __user *ubp, struct osst_buffer *st_bp, i
for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
cnt = st_bp->sg[i].length - offset < do_count ?
st_bp->sg[i].length - offset : do_count;
- res = copy_from_user(page_address(st_bp->sg[i].page) + offset, ubp, cnt);
+ res = copy_from_user(page_address(sg_page(&st_bp->sg[i])) + offset, ubp, cnt);
if (res)
return (-EFAULT);
do_count -= cnt;
@@ -5377,7 +5379,7 @@ static int from_buffer(struct osst_buffer *st_bp, char __user *ubp, int do_count
for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
cnt = st_bp->sg[i].length - offset < do_count ?
st_bp->sg[i].length - offset : do_count;
- res = copy_to_user(ubp, page_address(st_bp->sg[i].page) + offset, cnt);
+ res = copy_to_user(ubp, page_address(sg_page(&st_bp->sg[i])) + offset, cnt);
if (res)
return (-EFAULT);
do_count -= cnt;
@@ -5410,7 +5412,7 @@ static int osst_zero_buffer_tail(struct osst_buffer *st_bp)
i < st_bp->sg_segs && do_count > 0; i++) {
cnt = st_bp->sg[i].length - offset < do_count ?
st_bp->sg[i].length - offset : do_count ;
- memset(page_address(st_bp->sg[i].page) + offset, 0, cnt);
+ memset(page_address(sg_page(&st_bp->sg[i])) + offset, 0, cnt);
do_count -= cnt;
offset = 0;
}
@@ -5430,7 +5432,7 @@ static int osst_copy_to_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
cnt = st_bp->sg[i].length < do_count ?
st_bp->sg[i].length : do_count ;
- memcpy(page_address(st_bp->sg[i].page), ptr, cnt);
+ memcpy(page_address(sg_page(&st_bp->sg[i])), ptr, cnt);
do_count -= cnt;
ptr += cnt;
}
@@ -5451,7 +5453,7 @@ static int osst_copy_from_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
cnt = st_bp->sg[i].length < do_count ?
st_bp->sg[i].length : do_count ;
- memcpy(ptr, page_address(st_bp->sg[i].page), cnt);
+ memcpy(ptr, page_address(sg_page(&st_bp->sg[i])), cnt);
do_count -= cnt;
ptr += cnt;
}
diff --git a/drivers/scsi/pcmcia/nsp_cs.h b/drivers/scsi/pcmcia/nsp_cs.h
index b7f0fa246413..7db28cd49446 100644
--- a/drivers/scsi/pcmcia/nsp_cs.h
+++ b/drivers/scsi/pcmcia/nsp_cs.h
@@ -24,7 +24,6 @@
/************************************
* Some useful macros...
*/
-#define BIT(x) (1L << (x))
/* SCSI initiator must be ID 7 */
#define NSP_INITIATOR_ID 7
@@ -394,7 +393,7 @@ enum _burst_mode {
#define MSG_EXT_SDTR 0x01
/* scatter-gather table */
-# define BUFFER_ADDR ((char *)((unsigned int)(SCpnt->SCp.buffer->page) + SCpnt->SCp.buffer->offset))
+# define BUFFER_ADDR ((char *)((sg_virt(SCpnt->SCp.buffer))))
#endif /*__nsp_cs__*/
/* end */
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
index 961839ecfe86..969b9387a0c3 100644
--- a/drivers/scsi/pcmcia/sym53c500_cs.c
+++ b/drivers/scsi/pcmcia/sym53c500_cs.c
@@ -443,8 +443,7 @@ SYM53C500_intr(int irq, void *dev_id)
scsi_for_each_sg(curSC, sg, scsi_sg_count(curSC), i) {
SYM53C500_pio_write(fast_pio, port_base,
- page_address(sg->page) + sg->offset,
- sg->length);
+ sg_virt(sg), sg->length);
}
REG0(port_base);
}
@@ -463,8 +462,7 @@ SYM53C500_intr(int irq, void *dev_id)
scsi_for_each_sg(curSC, sg, scsi_sg_count(curSC), i) {
SYM53C500_pio_read(fast_pio, port_base,
- page_address(sg->page) + sg->offset,
- sg->length);
+ sg_virt(sg), sg->length);
}
REG0(port_base);
}
@@ -694,6 +692,7 @@ static struct scsi_host_template sym53c500_driver_template = {
.sg_tablesize = 32,
.cmd_per_lun = 1,
.use_clustering = ENABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
.shost_attrs = SYM53C500_shost_attrs
};
diff --git a/drivers/scsi/pluto.c b/drivers/scsi/pluto.c
deleted file mode 100644
index 0363c1cd68c1..000000000000
--- a/drivers/scsi/pluto.c
+++ /dev/null
@@ -1,349 +0,0 @@
-/* pluto.c: SparcSTORAGE Array SCSI host adapter driver.
- *
- * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- *
- */
-
-#include <linux/completion.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/blkdev.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <linux/init.h>
-#ifdef CONFIG_KMOD
-#include <linux/kmod.h>
-#endif
-
-#include <asm/irq.h>
-
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-#include "../fc4/fcp_impl.h"
-#include "pluto.h"
-
-#include <linux/module.h>
-
-#define RQ_SCSI_BUSY 0xffff
-#define RQ_SCSI_DONE 0xfffe
-
-/* #define PLUTO_DEBUG */
-
-#define pluto_printk printk ("PLUTO %s: ", fc->name); printk
-
-#ifdef PLUTO_DEBUG
-#define PLD(x) pluto_printk x;
-#define PLND(x) printk ("PLUTO: "); printk x;
-#else
-#define PLD(x)
-#define PLND(x)
-#endif
-
-static struct ctrl_inquiry {
- struct Scsi_Host host;
- struct pluto pluto;
- Scsi_Cmnd cmd;
- char inquiry[256];
- fc_channel *fc;
-} *fcs __initdata;
-static int fcscount __initdata = 0;
-static atomic_t fcss __initdata = ATOMIC_INIT(0);
-static DECLARE_COMPLETION(fc_detect_complete);
-
-static int pluto_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr, fc_channel *fc, fcp_cmnd *fcmd);
-
-static void __init pluto_detect_done(Scsi_Cmnd *SCpnt)
-{
- /* Do nothing */
-}
-
-static void __init pluto_detect_scsi_done(Scsi_Cmnd *SCpnt)
-{
- PLND(("Detect done %08lx\n", (long)SCpnt))
- if (atomic_dec_and_test (&fcss))
- complete(&fc_detect_complete);
-}
-
-int pluto_slave_configure(struct scsi_device *device)
-{
- int depth_to_use;
-
- if (device->tagged_supported)
- depth_to_use = /* 254 */ 8;
- else
- depth_to_use = 2;
-
- scsi_adjust_queue_depth(device,
- (device->tagged_supported ?
- MSG_SIMPLE_TAG : 0),
- depth_to_use);
-
- return 0;
-}
-
-/* Detect all SSAs attached to the machine.
- To be fast, do it on all online FC channels at the same time. */
-int __init pluto_detect(struct scsi_host_template *tpnt)
-{
- int i, retry, nplutos;
- fc_channel *fc;
- struct scsi_device dev;
-
- tpnt->proc_name = "pluto";
- fcscount = 0;
- for_each_online_fc_channel(fc) {
- if (!fc->posmap)
- fcscount++;
- }
- PLND(("%d channels online\n", fcscount))
- if (!fcscount) {
-#if defined(MODULE) && defined(CONFIG_FC4_SOC_MODULE) && defined(CONFIG_KMOD)
- request_module("soc");
-
- for_each_online_fc_channel(fc) {
- if (!fc->posmap)
- fcscount++;
- }
- if (!fcscount)
-#endif
- return 0;
- }
- fcs = kcalloc(fcscount, sizeof (struct ctrl_inquiry), GFP_DMA);
- if (!fcs) {
- printk ("PLUTO: Not enough memory to probe\n");
- return 0;
- }
-
- memset (&dev, 0, sizeof(dev));
- atomic_set (&fcss, fcscount);
-
- i = 0;
- for_each_online_fc_channel(fc) {
- Scsi_Cmnd *SCpnt;
- struct Scsi_Host *host;
- struct pluto *pluto;
-
- if (i == fcscount) break;
- if (fc->posmap) continue;
-
- PLD(("trying to find SSA\n"))
-
- /* If this is already registered to some other SCSI host, then it cannot be pluto */
- if (fc->scsi_name[0]) continue;
- memcpy (fc->scsi_name, "SSA", 4);
-
- fcs[i].fc = fc;
-
- fc->can_queue = PLUTO_CAN_QUEUE;
- fc->rsp_size = 64;
- fc->encode_addr = pluto_encode_addr;
-
- fc->fcp_register(fc, TYPE_SCSI_FCP, 0);
-
- SCpnt = &(fcs[i].cmd);
- host = &(fcs[i].host);
- pluto = (struct pluto *)host->hostdata;
-
- pluto->fc = fc;
-
- SCpnt->cmnd[0] = INQUIRY;
- SCpnt->cmnd[4] = 255;
-
- /* FC layer requires this, so that SCpnt->device->tagged_supported is initially 0 */
- SCpnt->device = &dev;
- dev.host = host;
-
- SCpnt->cmd_len = COMMAND_SIZE(INQUIRY);
-
- SCpnt->request->cmd_flags &= ~REQ_STARTED;
-
- SCpnt->request_bufflen = 256;
- SCpnt->request_buffer = fcs[i].inquiry;
- PLD(("set up %d %08lx\n", i, (long)SCpnt))
- i++;
- }
-
- for (retry = 0; retry < 5; retry++) {
- for (i = 0; i < fcscount; i++) {
- if (!fcs[i].fc) break;
- if (!(fcs[i].cmd.request->cmd_flags & REQ_STARTED)) {
- fcs[i].cmd.request->cmd_flags |= REQ_STARTED;
- disable_irq(fcs[i].fc->irq);
- PLND(("queuecommand %d %d\n", retry, i))
- fcp_scsi_queuecommand (&(fcs[i].cmd),
- pluto_detect_scsi_done);
- enable_irq(fcs[i].fc->irq);
- }
- }
-
- wait_for_completion_timeout(&fc_detect_complete, 10 * HZ);
- PLND(("Woken up\n"))
- if (!atomic_read(&fcss))
- break; /* All fc channels have answered us */
- }
-
- PLND(("Finished search\n"))
- for (i = 0, nplutos = 0; i < fcscount; i++) {
- Scsi_Cmnd *SCpnt;
-
- if (!(fc = fcs[i].fc)) break;
-
- SCpnt = &(fcs[i].cmd);
-
- /* Let FC mid-level free allocated resources */
- pluto_detect_scsi_done(SCpnt);
-
- if (!SCpnt->result) {
- struct pluto_inquiry *inq;
- struct pluto *pluto;
- struct Scsi_Host *host;
-
- inq = (struct pluto_inquiry *)fcs[i].inquiry;
-
- if ((inq->dtype & 0x1f) == TYPE_PROCESSOR &&
- !strncmp (inq->vendor_id, "SUN", 3) &&
- !strncmp (inq->product_id, "SSA", 3)) {
- char *p;
- long *ages;
-
- ages = kcalloc((inq->channels + 1) * inq->targets, sizeof(long), GFP_KERNEL);
- if (!ages) continue;
-
- host = scsi_register (tpnt, sizeof (struct pluto));
- if(!host)
- {
- kfree(ages);
- continue;
- }
-
- if (!try_module_get(fc->module)) {
- kfree(ages);
- scsi_unregister(host);
- continue;
- }
-
- nplutos++;
-
- pluto = (struct pluto *)host->hostdata;
-
- host->max_id = inq->targets;
- host->max_channel = inq->channels;
- host->irq = fc->irq;
-
- fc->channels = inq->channels + 1;
- fc->targets = inq->targets;
- fc->ages = ages;
-
- pluto->fc = fc;
- memcpy (pluto->rev_str, inq->revision, 4);
- pluto->rev_str[4] = 0;
- p = strchr (pluto->rev_str, ' ');
- if (p) *p = 0;
- memcpy (pluto->fw_rev_str, inq->fw_revision, 4);
- pluto->fw_rev_str[4] = 0;
- p = strchr (pluto->fw_rev_str, ' ');
- if (p) *p = 0;
- memcpy (pluto->serial_str, inq->serial, 12);
- pluto->serial_str[12] = 0;
- p = strchr (pluto->serial_str, ' ');
- if (p) *p = 0;
-
- PLD(("Found SSA rev %s fw rev %s serial %s %dx%d\n", pluto->rev_str, pluto->fw_rev_str, pluto->serial_str, host->max_channel, host->max_id))
- } else
- fc->fcp_register(fc, TYPE_SCSI_FCP, 1);
- } else
- fc->fcp_register(fc, TYPE_SCSI_FCP, 1);
- }
- kfree(fcs);
- if (nplutos)
- printk ("PLUTO: Total of %d SparcSTORAGE Arrays found\n", nplutos);
- return nplutos;
-}
-
-int pluto_release(struct Scsi_Host *host)
-{
- struct pluto *pluto = (struct pluto *)host->hostdata;
- fc_channel *fc = pluto->fc;
-
- module_put(fc->module);
-
- fc->fcp_register(fc, TYPE_SCSI_FCP, 1);
- PLND((" releasing pluto.\n"));
- kfree (fc->ages);
- PLND(("released pluto!\n"));
- return 0;
-}
-
-const char *pluto_info(struct Scsi_Host *host)
-{
- static char buf[128], *p;
- struct pluto *pluto = (struct pluto *) host->hostdata;
-
- sprintf(buf, "SUN SparcSTORAGE Array %s fw %s serial %s %dx%d on %s",
- pluto->rev_str, pluto->fw_rev_str, pluto->serial_str,
- host->max_channel, host->max_id, pluto->fc->name);
-#ifdef __sparc__
- p = strchr(buf, 0);
- sprintf(p, " PROM node %x", pluto->fc->dev->prom_node);
-#endif
- return buf;
-}
-
-/* SSA uses this FC4S addressing:
- switch (addr[0])
- {
- case 0: CONTROLLER - All of addr[1]..addr[3] has to be 0
- case 1: SINGLE DISK - addr[1] channel, addr[2] id, addr[3] 0
- case 2: DISK GROUP - ???
- }
-
- So that SCSI mid-layer can access to these, we reserve
- channel 0 id 0 lun 0 for CONTROLLER
- and channels 1 .. max_channel are normal single disks.
- */
-static int pluto_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr, fc_channel *fc, fcp_cmnd *fcmd)
-{
- PLND(("encode addr %d %d %d\n", SCpnt->device->channel, SCpnt->device->id, SCpnt->cmnd[1] & 0xe0))
- /* We don't support LUNs - neither does SSA :) */
- if (SCpnt->cmnd[1] & 0xe0)
- return -EINVAL;
- if (!SCpnt->device->channel) {
- if (SCpnt->device->id)
- return -EINVAL;
- memset (addr, 0, 4 * sizeof(u16));
- } else {
- addr[0] = 1;
- addr[1] = SCpnt->device->channel - 1;
- addr[2] = SCpnt->device->id;
- addr[3] = 0;
- }
- /* We're Point-to-Point, so target it to the default DID */
- fcmd->did = fc->did;
- PLND(("trying %04x%04x%04x%04x\n", addr[0], addr[1], addr[2], addr[3]))
- return 0;
-}
-
-static struct scsi_host_template driver_template = {
- .name = "Sparc Storage Array 100/200",
- .detect = pluto_detect,
- .release = pluto_release,
- .info = pluto_info,
- .queuecommand = fcp_scsi_queuecommand,
- .slave_configure = pluto_slave_configure,
- .can_queue = PLUTO_CAN_QUEUE,
- .this_id = -1,
- .sg_tablesize = 1,
- .cmd_per_lun = 1,
- .use_clustering = ENABLE_CLUSTERING,
- .eh_abort_handler = fcp_scsi_abort,
- .eh_device_reset_handler = fcp_scsi_dev_reset,
- .eh_host_reset_handler = fcp_scsi_host_reset,
-};
-
-#include "scsi_module.c"
-
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/scsi/pluto.h b/drivers/scsi/pluto.h
deleted file mode 100644
index 5da20616ac36..000000000000
--- a/drivers/scsi/pluto.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* pluto.h: SparcSTORAGE Array SCSI host adapter driver definitions.
- *
- * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- */
-
-#ifndef _PLUTO_H
-#define _PLUTO_H
-
-#include "../fc4/fcp_impl.h"
-
-struct pluto {
- /* This must be first */
- fc_channel *fc;
- char rev_str[5];
- char fw_rev_str[5];
- char serial_str[13];
-};
-
-struct pluto_inquiry {
- u8 dtype;
- u8 removable:1, qualifier:7;
- u8 iso:2, ecma:3, ansi:3;
- u8 aenc:1, trmiop:1, :2, rdf:4;
- u8 len;
- u8 xxx1;
- u8 xxx2;
- u8 reladdr:1, wbus32:1, wbus16:1, sync:1, linked:1, :1, cmdque:1, softreset:1;
- u8 vendor_id[8];
- u8 product_id[16];
- u8 revision[4];
- u8 fw_revision[4];
- u8 serial[12];
- u8 xxx3[2];
- u8 channels;
- u8 targets;
-};
-
-/* This is the max number of outstanding SCSI commands per pluto */
-#define PLUTO_CAN_QUEUE 254
-
-int pluto_detect(struct scsi_host_template *);
-int pluto_release(struct Scsi_Host *);
-const char * pluto_info(struct Scsi_Host *);
-int pluto_slave_configure(struct scsi_device *);
-
-#endif /* !(_PLUTO_H) */
-
diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c
index 67b6d76a6c8d..67ee51a3d7e1 100644
--- a/drivers/scsi/ppa.c
+++ b/drivers/scsi/ppa.c
@@ -608,9 +608,7 @@ static int ppa_completion(struct scsi_cmnd *cmd)
cmd->SCp.buffer++;
cmd->SCp.this_residual =
cmd->SCp.buffer->length;
- cmd->SCp.ptr =
- page_address(cmd->SCp.buffer->page) +
- cmd->SCp.buffer->offset;
+ cmd->SCp.ptr = sg_virt(cmd->SCp.buffer);
}
}
/* Now check to see if the drive is ready to comunicate */
@@ -756,8 +754,7 @@ static int ppa_engine(ppa_struct *dev, struct scsi_cmnd *cmd)
/* if many buffers are available, start filling the first */
cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer;
cmd->SCp.this_residual = cmd->SCp.buffer->length;
- cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) +
- cmd->SCp.buffer->offset;
+ cmd->SCp.ptr = sg_virt(cmd->SCp.buffer);
} else {
/* else fill the only available buffer */
cmd->SCp.buffer = NULL;
diff --git a/drivers/scsi/ps3rom.c b/drivers/scsi/ps3rom.c
index 0f43d1d046d9..17b4a7c4618c 100644
--- a/drivers/scsi/ps3rom.c
+++ b/drivers/scsi/ps3rom.c
@@ -111,14 +111,14 @@ static int fill_from_dev_buffer(struct scsi_cmnd *cmd, const void *buf)
req_len = act_len = 0;
scsi_for_each_sg(cmd, sgpnt, scsi_sg_count(cmd), k) {
if (active) {
- kaddr = kmap_atomic(sgpnt->page, KM_IRQ0);
+ kaddr = kmap_atomic(sg_page(sgpnt), KM_IRQ0);
len = sgpnt->length;
if ((req_len + len) > buflen) {
active = 0;
len = buflen - req_len;
}
memcpy(kaddr + sgpnt->offset, buf + req_len, len);
- flush_kernel_dcache_page(sgpnt->page);
+ flush_kernel_dcache_page(sg_page(sgpnt));
kunmap_atomic(kaddr, KM_IRQ0);
act_len += len;
}
@@ -147,7 +147,7 @@ static int fetch_to_dev_buffer(struct scsi_cmnd *cmd, void *buf)
req_len = fin = 0;
scsi_for_each_sg(cmd, sgpnt, scsi_sg_count(cmd), k) {
- kaddr = kmap_atomic(sgpnt->page, KM_IRQ0);
+ kaddr = kmap_atomic(sg_page(sgpnt), KM_IRQ0);
len = sgpnt->length;
if ((req_len + len) > buflen) {
len = buflen - req_len;
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index fba8aa8a81b5..3aeb68bcb7ac 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -2775,7 +2775,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
struct device_reg __iomem *reg = ha->iobase;
struct scsi_cmnd *cmd = sp->cmd;
cmd_a64_entry_t *pkt;
- struct scatterlist *sg = NULL;
+ struct scatterlist *sg = NULL, *s;
__le32 *dword_ptr;
dma_addr_t dma_handle;
int status = 0;
@@ -2889,13 +2889,16 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
* Load data segments.
*/
if (seg_cnt) { /* If data transfer. */
+ int remseg = seg_cnt;
/* Setup packet address segment pointer. */
dword_ptr = (u32 *)&pkt->dseg_0_address;
if (cmd->use_sg) { /* If scatter gather */
/* Load command entry data segments. */
- for (cnt = 0; cnt < 2 && seg_cnt; cnt++, seg_cnt--) {
- dma_handle = sg_dma_address(sg);
+ for_each_sg(sg, s, seg_cnt, cnt) {
+ if (cnt == 2)
+ break;
+ dma_handle = sg_dma_address(s);
#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
if (ha->flags.use_pci_vchannel)
sn_pci_set_vchan(ha->pdev,
@@ -2906,12 +2909,12 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
cpu_to_le32(pci_dma_lo32(dma_handle));
*dword_ptr++ =
cpu_to_le32(pci_dma_hi32(dma_handle));
- *dword_ptr++ = cpu_to_le32(sg_dma_len(sg));
- sg++;
+ *dword_ptr++ = cpu_to_le32(sg_dma_len(s));
dprintk(3, "S/G Segment phys_addr=%x %x, len=0x%x\n",
cpu_to_le32(pci_dma_hi32(dma_handle)),
cpu_to_le32(pci_dma_lo32(dma_handle)),
- cpu_to_le32(sg_dma_len(sg)));
+ cpu_to_le32(sg_dma_len(sg_next(s))));
+ remseg--;
}
dprintk(5, "qla1280_64bit_start_scsi: Scatter/gather "
"command packet data - b %i, t %i, l %i \n",
@@ -2926,7 +2929,9 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
dprintk(3, "S/G Building Continuation...seg_cnt=0x%x "
"remains\n", seg_cnt);
- while (seg_cnt > 0) {
+ while (remseg > 0) {
+ /* Update sg start */
+ sg = s;
/* Adjust ring index. */
ha->req_ring_index++;
if (ha->req_ring_index == REQUEST_ENTRY_CNT) {
@@ -2952,9 +2957,10 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
(u32 *)&((struct cont_a64_entry *) pkt)->dseg_0_address;
/* Load continuation entry data segments. */
- for (cnt = 0; cnt < 5 && seg_cnt;
- cnt++, seg_cnt--) {
- dma_handle = sg_dma_address(sg);
+ for_each_sg(sg, s, remseg, cnt) {
+ if (cnt == 5)
+ break;
+ dma_handle = sg_dma_address(s);
#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
if (ha->flags.use_pci_vchannel)
sn_pci_set_vchan(ha->pdev,
@@ -2966,13 +2972,13 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
*dword_ptr++ =
cpu_to_le32(pci_dma_hi32(dma_handle));
*dword_ptr++ =
- cpu_to_le32(sg_dma_len(sg));
+ cpu_to_le32(sg_dma_len(s));
dprintk(3, "S/G Segment Cont. phys_addr=%x %x, len=0x%x\n",
cpu_to_le32(pci_dma_hi32(dma_handle)),
cpu_to_le32(pci_dma_lo32(dma_handle)),
- cpu_to_le32(sg_dma_len(sg)));
- sg++;
+ cpu_to_le32(sg_dma_len(s)));
}
+ remseg -= cnt;
dprintk(5, "qla1280_64bit_start_scsi: "
"continuation packet data - b %i, t "
"%i, l %i \n", SCSI_BUS_32(cmd),
@@ -3062,7 +3068,7 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
struct device_reg __iomem *reg = ha->iobase;
struct scsi_cmnd *cmd = sp->cmd;
struct cmd_entry *pkt;
- struct scatterlist *sg = NULL;
+ struct scatterlist *sg = NULL, *s;
__le32 *dword_ptr;
int status = 0;
int cnt;
@@ -3188,6 +3194,7 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
* Load data segments.
*/
if (seg_cnt) {
+ int remseg = seg_cnt;
/* Setup packet address segment pointer. */
dword_ptr = &pkt->dseg_0_address;
@@ -3196,22 +3203,25 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
qla1280_dump_buffer(1, (char *)sg, 4 * 16);
/* Load command entry data segments. */
- for (cnt = 0; cnt < 4 && seg_cnt; cnt++, seg_cnt--) {
+ for_each_sg(sg, s, seg_cnt, cnt) {
+ if (cnt == 4)
+ break;
*dword_ptr++ =
- cpu_to_le32(pci_dma_lo32(sg_dma_address(sg)));
- *dword_ptr++ =
- cpu_to_le32(sg_dma_len(sg));
+ cpu_to_le32(pci_dma_lo32(sg_dma_address(s)));
+ *dword_ptr++ = cpu_to_le32(sg_dma_len(s));
dprintk(3, "S/G Segment phys_addr=0x%lx, len=0x%x\n",
- (pci_dma_lo32(sg_dma_address(sg))),
- (sg_dma_len(sg)));
- sg++;
+ (pci_dma_lo32(sg_dma_address(s))),
+ (sg_dma_len(s)));
+ remseg--;
}
/*
* Build continuation packets.
*/
dprintk(3, "S/G Building Continuation"
"...seg_cnt=0x%x remains\n", seg_cnt);
- while (seg_cnt > 0) {
+ while (remseg > 0) {
+ /* Continue from end point */
+ sg = s;
/* Adjust ring index. */
ha->req_ring_index++;
if (ha->req_ring_index == REQUEST_ENTRY_CNT) {
@@ -3239,19 +3249,20 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
&((struct cont_entry *) pkt)->dseg_0_address;
/* Load continuation entry data segments. */
- for (cnt = 0; cnt < 7 && seg_cnt;
- cnt++, seg_cnt--) {
+ for_each_sg(sg, s, remseg, cnt) {
+ if (cnt == 7)
+ break;
*dword_ptr++ =
- cpu_to_le32(pci_dma_lo32(sg_dma_address(sg)));
+ cpu_to_le32(pci_dma_lo32(sg_dma_address(s)));
*dword_ptr++ =
- cpu_to_le32(sg_dma_len(sg));
+ cpu_to_le32(sg_dma_len(s));
dprintk(1,
"S/G Segment Cont. phys_addr=0x%x, "
"len=0x%x\n",
- cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))),
- cpu_to_le32(sg_dma_len(sg)));
- sg++;
+ cpu_to_le32(pci_dma_lo32(sg_dma_address(s))),
+ cpu_to_le32(sg_dma_len(s)));
}
+ remseg -= cnt;
dprintk(5, "qla1280_32bit_start_scsi: "
"continuation packet data - "
"scsi(%i:%i:%i)\n", SCSI_BUS_32(cmd),
@@ -4248,6 +4259,7 @@ static struct scsi_host_template qla1280_driver_template = {
.sg_tablesize = SG_ALL,
.cmd_per_lun = 1,
.use_clustering = ENABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
};
@@ -4298,7 +4310,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
printk(KERN_WARNING "scsi(%li): Unable to set a "
"suitable DMA mask - aborting\n", ha->host_no);
error = -ENODEV;
- goto error_free_irq;
+ goto error_put_host;
}
} else
dprintk(2, "scsi(%li): 64 Bit PCI Addressing Enabled\n",
@@ -4308,7 +4320,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
printk(KERN_WARNING "scsi(%li): Unable to set a "
"suitable DMA mask - aborting\n", ha->host_no);
error = -ENODEV;
- goto error_free_irq;
+ goto error_put_host;
}
#endif
diff --git a/drivers/scsi/qla1280.h b/drivers/scsi/qla1280.h
index 59915fb70301..ff2c363ead26 100644
--- a/drivers/scsi/qla1280.h
+++ b/drivers/scsi/qla1280.h
@@ -91,8 +91,8 @@
#define INVALID_HANDLE (MAX_OUTSTANDING_COMMANDS + 2)
/* ISP request and response entry counts (37-65535) */
-#define REQUEST_ENTRY_CNT 256 /* Number of request entries. */
-#define RESPONSE_ENTRY_CNT 16 /* Number of response entries. */
+#define REQUEST_ENTRY_CNT 255 /* Number of request entries. */
+#define RESPONSE_ENTRY_CNT 63 /* Number of response entries. */
/*
* SCSI Request Block structure (sp) that is placed
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 05fa7796a559..fb388b8c07cf 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -114,7 +114,6 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj,
{
struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
struct device, kobj)));
- unsigned long flags;
uint16_t cnt;
if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->nvram_size)
@@ -144,11 +143,9 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj,
}
/* Write NVRAM. */
- spin_lock_irqsave(&ha->hardware_lock, flags);
ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->nvram_base, count);
ha->isp_ops->read_nvram(ha, (uint8_t *)ha->nvram, ha->nvram_base,
count);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
@@ -397,16 +394,13 @@ qla2x00_sysfs_write_vpd(struct kobject *kobj,
{
struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
struct device, kobj)));
- unsigned long flags;
if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size)
return 0;
/* Write NVRAM. */
- spin_lock_irqsave(&ha->hardware_lock, flags);
ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->vpd_base, count);
ha->isp_ops->read_nvram(ha, (uint8_t *)ha->vpd, ha->vpd_base, count);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
return count;
}
@@ -544,6 +538,9 @@ qla2x00_serial_num_show(struct class_device *cdev, char *buf)
scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
uint32_t sn;
+ if (IS_FWI2_CAPABLE(ha))
+ return snprintf(buf, PAGE_SIZE, "\n");
+
sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1;
return snprintf(buf, PAGE_SIZE, "%c%05d\n", 'A' + sn / 100000,
sn % 100000);
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 1900fbf6cd74..04e8cbca4c0d 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2271,6 +2271,7 @@ typedef struct scsi_qla_host {
spinlock_t hardware_lock ____cacheline_aligned;
+ int bars;
device_reg_t __iomem *iobase; /* Base I/O address */
unsigned long pio_address;
unsigned long pio_length;
diff --git a/drivers/scsi/qla2xxx/qla_devtbl.h b/drivers/scsi/qla2xxx/qla_devtbl.h
index dd435410dfa2..d78d35e681ab 100644
--- a/drivers/scsi/qla2xxx/qla_devtbl.h
+++ b/drivers/scsi/qla2xxx/qla_devtbl.h
@@ -1,4 +1,4 @@
-#define QLA_MODEL_NAMES 0x57
+#define QLA_MODEL_NAMES 0x5C
/*
* Adapter model names and descriptions.
@@ -91,4 +91,9 @@ static char *qla2x00_model_name[QLA_MODEL_NAMES*2] = {
" ", " ", /* 0x154 */
"QLE220", "PCI-Express to 4Gb FC, Single Channel", /* 0x155 */
"QLE220", "PCI-Express to 4Gb FC, Single Channel", /* 0x156 */
+ " ", " ", /* 0x157 */
+ " ", " ", /* 0x158 */
+ " ", " ", /* 0x159 */
+ " ", " ", /* 0x15a */
+ "QME2472", "Dell BS PCI-Express to 4Gb FC, Dual Channel", /* 0x15b */
};
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 7f6a89bd94f3..024c662ec34d 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -525,7 +525,7 @@ qla2x00_req_pkt(scsi_qla_host_t *ha)
/* Check for pending interrupts. */
/* During init we issue marker directly */
- if (!ha->marker_needed)
+ if (!ha->marker_needed && !ha->flags.init_done)
qla2x00_poll(ha);
spin_lock_irq(&ha->hardware_lock);
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index c4768c4f3990..1104bd2eed40 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1012,8 +1012,14 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
case CS_DATA_UNDERRUN:
resid = resid_len;
/* Use F/W calculated residual length. */
- if (IS_FWI2_CAPABLE(ha))
+ if (IS_FWI2_CAPABLE(ha)) {
+ if (scsi_status & SS_RESIDUAL_UNDER &&
+ resid != fw_resid_len) {
+ scsi_status &= ~SS_RESIDUAL_UNDER;
+ lscsi_status = 0;
+ }
resid = fw_resid_len;
+ }
if (scsi_status & SS_RESIDUAL_UNDER) {
scsi_set_resid(cp, resid);
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index c53ec67c47f4..ccd662a6f5dc 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -252,7 +252,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp)
/* Clean up */
ha->mcp = NULL;
- if (!abort_active) {
+ if (abort_active || !io_lock_on) {
DEBUG11(printk("%s(%ld): checking for additional resp "
"interrupt.\n", __func__, ha->host_no));
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index a6bb8d0ecf13..a5bcf1f390b3 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -132,6 +132,7 @@ struct scsi_host_template qla2x00_driver_template = {
.this_id = -1,
.cmd_per_lun = 3,
.use_clustering = ENABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
.sg_tablesize = SG_ALL,
/*
@@ -163,6 +164,7 @@ struct scsi_host_template qla24xx_driver_template = {
.this_id = -1,
.cmd_per_lun = 3,
.use_clustering = ENABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
.sg_tablesize = SG_ALL,
.max_sectors = 0xFFFF,
@@ -1480,6 +1482,17 @@ qla2x00_iospace_config(scsi_qla_host_t *ha)
unsigned long pio, pio_len, pio_flags;
unsigned long mmio, mmio_len, mmio_flags;
+ if (pci_request_selected_regions(ha->pdev, ha->bars,
+ QLA2XXX_DRIVER_NAME)) {
+ qla_printk(KERN_WARNING, ha,
+ "Failed to reserve PIO/MMIO regions (%s)\n",
+ pci_name(ha->pdev));
+
+ goto iospace_error_exit;
+ }
+ if (!(ha->bars & 1))
+ goto skip_pio;
+
/* We only need PIO for Flash operations on ISP2312 v2 chips. */
pio = pci_resource_start(ha->pdev, 0);
pio_len = pci_resource_len(ha->pdev, 0);
@@ -1497,7 +1510,10 @@ qla2x00_iospace_config(scsi_qla_host_t *ha)
pci_name(ha->pdev));
pio = 0;
}
+ ha->pio_address = pio;
+ ha->pio_length = pio_len;
+skip_pio:
/* Use MMIO operations for all accesses. */
mmio = pci_resource_start(ha->pdev, 1);
mmio_len = pci_resource_len(ha->pdev, 1);
@@ -1516,16 +1532,6 @@ qla2x00_iospace_config(scsi_qla_host_t *ha)
goto iospace_error_exit;
}
- if (pci_request_regions(ha->pdev, QLA2XXX_DRIVER_NAME)) {
- qla_printk(KERN_WARNING, ha,
- "Failed to reserve PIO/MMIO regions (%s)\n",
- pci_name(ha->pdev));
-
- goto iospace_error_exit;
- }
-
- ha->pio_address = pio;
- ha->pio_length = pio_len;
ha->iobase = ioremap(mmio, MIN_IOBASE_LEN);
if (!ha->iobase) {
qla_printk(KERN_ERR, ha,
@@ -1577,21 +1583,26 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
char pci_info[30];
char fw_str[30];
struct scsi_host_template *sht;
+ int bars;
- if (pci_enable_device(pdev))
- goto probe_out;
-
- if (pci_find_aer_capability(pdev))
- if (pci_enable_pcie_error_reporting(pdev))
- goto probe_out;
-
+ bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO);
sht = &qla2x00_driver_template;
if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 ||
pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432 ||
pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5422 ||
pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5432 ||
- pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532)
+ pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532) {
+ bars = pci_select_bars(pdev, IORESOURCE_MEM);
sht = &qla24xx_driver_template;
+ }
+
+ if (pci_enable_device_bars(pdev, bars))
+ goto probe_out;
+
+ if (pci_find_aer_capability(pdev))
+ if (pci_enable_pcie_error_reporting(pdev))
+ goto probe_out;
+
host = scsi_host_alloc(sht, sizeof(scsi_qla_host_t));
if (host == NULL) {
printk(KERN_WARNING
@@ -1608,6 +1619,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
ha->host_no = host->host_no;
sprintf(ha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, ha->host_no);
ha->parent = NULL;
+ ha->bars = bars;
/* Set ISP-type information. */
qla2x00_set_isp_flags(ha);
@@ -1878,7 +1890,7 @@ qla2x00_free_device(scsi_qla_host_t *ha)
/* release io space registers */
if (ha->iobase)
iounmap(ha->iobase);
- pci_release_regions(ha->pdev);
+ pci_release_selected_regions(ha->pdev, ha->bars);
}
static inline void
@@ -2888,7 +2900,7 @@ qla2xxx_pci_slot_reset(struct pci_dev *pdev)
pci_ers_result_t ret = PCI_ERS_RESULT_DISCONNECT;
scsi_qla_host_t *ha = pci_get_drvdata(pdev);
- if (pci_enable_device(pdev)) {
+ if (pci_enable_device_bars(pdev, ha->bars)) {
qla_printk(KERN_WARNING, ha,
"Can't re-enable PCI device after reset.\n");
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index 40b059fc1981..ad2fa01bd233 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -7,6 +7,7 @@
#include "qla_def.h"
#include <linux/delay.h>
+#include <linux/vmalloc.h>
#include <asm/uaccess.h>
static uint16_t qla2x00_nvram_request(scsi_qla_host_t *, uint32_t);
@@ -642,7 +643,7 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
}
/* Go with burst-write. */
- if (optrom && (liter + OPTROM_BURST_DWORDS) < dwords) {
+ if (optrom && (liter + OPTROM_BURST_DWORDS) <= dwords) {
/* Copy data to DMA'ble buffer. */
for (miter = 0, s = optrom, d = dwptr;
miter < OPTROM_BURST_DWORDS; miter++, s++, d++)
@@ -656,7 +657,7 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
"Unable to burst-write optrom segment "
"(%x/%x/%llx).\n", ret,
flash_data_to_access_addr(faddr),
- optrom_dma);
+ (unsigned long long)optrom_dma);
qla_printk(KERN_WARNING, ha,
"Reverting to slow-write.\n");
@@ -745,9 +746,11 @@ qla2x00_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
int ret, stat;
uint32_t i;
uint16_t *wptr;
+ unsigned long flags;
ret = QLA_SUCCESS;
+ spin_lock_irqsave(&ha->hardware_lock, flags);
qla2x00_lock_nvram_access(ha);
/* Disable NVRAM write-protection. */
@@ -764,6 +767,7 @@ qla2x00_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
qla2x00_set_nvram_protection(ha, stat);
qla2x00_unlock_nvram_access(ha);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
return ret;
}
@@ -776,9 +780,11 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
uint32_t i;
uint32_t *dwptr;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+ unsigned long flags;
ret = QLA_SUCCESS;
+ spin_lock_irqsave(&ha->hardware_lock, flags);
/* Enable flash write. */
WRT_REG_DWORD(&reg->ctrl_status,
RD_REG_DWORD(&reg->ctrl_status) | CSRX_FLASH_ENABLE);
@@ -812,6 +818,7 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
WRT_REG_DWORD(&reg->ctrl_status,
RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
RD_REG_DWORD(&reg->ctrl_status); /* PCI Posting. */
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
return ret;
}
@@ -836,8 +843,20 @@ int
qla25xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
uint32_t bytes)
{
- return qla24xx_write_flash_data(ha, (uint32_t *)buf,
- FA_VPD_NVRAM_ADDR | naddr, bytes >> 2);
+#define RMW_BUFFER_SIZE (64 * 1024)
+ uint8_t *dbuf;
+
+ dbuf = vmalloc(RMW_BUFFER_SIZE);
+ if (!dbuf)
+ return QLA_MEMORY_ALLOC_FAILED;
+ ha->isp_ops->read_optrom(ha, dbuf, FA_VPD_NVRAM_ADDR << 2,
+ RMW_BUFFER_SIZE);
+ memcpy(dbuf + (naddr << 2), buf, bytes);
+ ha->isp_ops->write_optrom(ha, dbuf, FA_VPD_NVRAM_ADDR << 2,
+ RMW_BUFFER_SIZE);
+ vfree(dbuf);
+
+ return QLA_SUCCESS;
}
static inline void
@@ -1853,7 +1872,8 @@ qla25xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
qla_printk(KERN_WARNING, ha,
"Unable to burst-read optrom segment "
"(%x/%x/%llx).\n", rval,
- flash_data_to_access_addr(faddr), optrom_dma);
+ flash_data_to_access_addr(faddr),
+ (unsigned long long)optrom_dma);
qla_printk(KERN_WARNING, ha,
"Reverting to slow-read.\n");
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index 2d551a3006f6..ae6f7a2fb19f 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.02.00-k4"
+#define QLA2XXX_VERSION "8.02.00-k5"
#define QLA_DRIVER_MAJOR_VER 8
#define QLA_DRIVER_MINOR_VER 2
diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h
index 9bb3d1d2a925..fe415ec85655 100644
--- a/drivers/scsi/qla4xxx/ql4_fw.h
+++ b/drivers/scsi/qla4xxx/ql4_fw.h
@@ -671,7 +671,7 @@ struct continuation_t1_entry {
#define ET_CONTINUE ET_CONT_T1
/* Marker entry structure*/
-struct marker_entry {
+struct qla4_marker_entry {
struct qla4_header hdr; /* 00-03 */
uint32_t system_defined; /* 04-07 */
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
index 1e29f51d596b..d692c713416a 100644
--- a/drivers/scsi/qla4xxx/ql4_init.c
+++ b/drivers/scsi/qla4xxx/ql4_init.c
@@ -1006,7 +1006,7 @@ int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a)
* qla4xxx_start_firmware - starts qla4xxx firmware
* @ha: Pointer to host adapter structure.
*
- * This routine performs the neccessary steps to start the firmware for
+ * This routine performs the necessary steps to start the firmware for
* the QLA4010 adapter.
**/
static int qla4xxx_start_firmware(struct scsi_qla_host *ha)
diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c
index 5006ecb3ef5e..e4461b5d767a 100644
--- a/drivers/scsi/qla4xxx/ql4_iocb.c
+++ b/drivers/scsi/qla4xxx/ql4_iocb.c
@@ -69,7 +69,7 @@ static int qla4xxx_get_req_pkt(struct scsi_qla_host *ha,
static int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
struct ddb_entry *ddb_entry, int lun)
{
- struct marker_entry *marker_entry;
+ struct qla4_marker_entry *marker_entry;
unsigned long flags = 0;
uint8_t status = QLA_SUCCESS;
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index b1d565c12c5b..89460d27c689 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -94,6 +94,7 @@ static struct scsi_host_template qla4xxx_driver_template = {
.this_id = -1,
.cmd_per_lun = 3,
.use_clustering = ENABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
.sg_tablesize = SG_ALL,
.max_sectors = 0xFFFF,
@@ -1285,7 +1286,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
ret = scsi_init_shared_tag_map(host, MAX_SRBS);
if (ret) {
- dev_warn(&ha->pdev->dev, "scsi_init_shared_tag_map failed");
+ dev_warn(&ha->pdev->dev, "scsi_init_shared_tag_map failed\n");
goto probe_failed;
}
diff --git a/drivers/scsi/qlogicfas.c b/drivers/scsi/qlogicfas.c
index 1e874f1fb5c6..1769f965eedf 100644
--- a/drivers/scsi/qlogicfas.c
+++ b/drivers/scsi/qlogicfas.c
@@ -197,6 +197,7 @@ static struct scsi_host_template qlogicfas_driver_template = {
.sg_tablesize = SG_ALL,
.cmd_per_lun = 1,
.use_clustering = DISABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
};
static __init int qlogicfas_init(void)
diff --git a/drivers/scsi/qlogicfas408.c b/drivers/scsi/qlogicfas408.c
index 2bfbf26c00ed..de7b3bc2cbc9 100644
--- a/drivers/scsi/qlogicfas408.c
+++ b/drivers/scsi/qlogicfas408.c
@@ -317,7 +317,7 @@ static unsigned int ql_pcmd(struct scsi_cmnd *cmd)
return ((priv->qabort == 1 ?
DID_ABORT : DID_RESET) << 16);
}
- buf = page_address(sg->page) + sg->offset;
+ buf = sg_virt(sg);
if (ql_pdma(priv, phase, buf, sg->length))
break;
}
diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c
index e93f80316a19..7a2e7986b038 100644
--- a/drivers/scsi/qlogicpti.c
+++ b/drivers/scsi/qlogicpti.c
@@ -868,7 +868,7 @@ static inline int load_cmd(struct scsi_cmnd *Cmnd, struct Command_Entry *cmd,
struct qlogicpti *qpti, u_int in_ptr, u_int out_ptr)
{
struct dataseg *ds;
- struct scatterlist *sg;
+ struct scatterlist *sg, *s;
int i, n;
if (Cmnd->use_sg) {
@@ -884,11 +884,12 @@ static inline int load_cmd(struct scsi_cmnd *Cmnd, struct Command_Entry *cmd,
n = sg_count;
if (n > 4)
n = 4;
- for (i = 0; i < n; i++, sg++) {
- ds[i].d_base = sg_dma_address(sg);
- ds[i].d_count = sg_dma_len(sg);
+ for_each_sg(sg, s, n, i) {
+ ds[i].d_base = sg_dma_address(s);
+ ds[i].d_count = sg_dma_len(s);
}
sg_count -= 4;
+ sg = s;
while (sg_count > 0) {
struct Continuation_Entry *cont;
@@ -907,9 +908,9 @@ static inline int load_cmd(struct scsi_cmnd *Cmnd, struct Command_Entry *cmd,
n = sg_count;
if (n > 7)
n = 7;
- for (i = 0; i < n; i++, sg++) {
- ds[i].d_base = sg_dma_address(sg);
- ds[i].d_count = sg_dma_len(sg);
+ for_each_sg(sg, s, n, i) {
+ ds[i].d_base = sg_dma_address(s);
+ ds[i].d_count = sg_dma_len(s);
}
sg_count -= n;
}
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 4947dfe625a6..46cae5a212de 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -38,6 +38,7 @@
#include <linux/proc_fs.h>
#include <linux/vmalloc.h>
#include <linux/moduleparam.h>
+#include <linux/scatterlist.h>
#include <linux/blkdev.h>
#include "scsi.h"
@@ -600,7 +601,7 @@ static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
int k, req_len, act_len, len, active;
void * kaddr;
void * kaddr_off;
- struct scatterlist * sgpnt;
+ struct scatterlist * sg;
if (0 == scp->request_bufflen)
return 0;
@@ -619,16 +620,16 @@ static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
scp->resid = req_len - act_len;
return 0;
}
- sgpnt = (struct scatterlist *)scp->request_buffer;
active = 1;
- for (k = 0, req_len = 0, act_len = 0; k < scp->use_sg; ++k, ++sgpnt) {
+ req_len = act_len = 0;
+ scsi_for_each_sg(scp, sg, scp->use_sg, k) {
if (active) {
kaddr = (unsigned char *)
- kmap_atomic(sgpnt->page, KM_USER0);
+ kmap_atomic(sg_page(sg), KM_USER0);
if (NULL == kaddr)
return (DID_ERROR << 16);
- kaddr_off = (unsigned char *)kaddr + sgpnt->offset;
- len = sgpnt->length;
+ kaddr_off = (unsigned char *)kaddr + sg->offset;
+ len = sg->length;
if ((req_len + len) > arr_len) {
active = 0;
len = arr_len - req_len;
@@ -637,7 +638,7 @@ static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
kunmap_atomic(kaddr, KM_USER0);
act_len += len;
}
- req_len += sgpnt->length;
+ req_len += sg->length;
}
if (scp->resid)
scp->resid -= act_len;
@@ -653,7 +654,7 @@ static int fetch_to_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
int k, req_len, len, fin;
void * kaddr;
void * kaddr_off;
- struct scatterlist * sgpnt;
+ struct scatterlist * sg;
if (0 == scp->request_bufflen)
return 0;
@@ -668,13 +669,14 @@ static int fetch_to_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
memcpy(arr, scp->request_buffer, len);
return len;
}
- sgpnt = (struct scatterlist *)scp->request_buffer;
- for (k = 0, req_len = 0, fin = 0; k < scp->use_sg; ++k, ++sgpnt) {
- kaddr = (unsigned char *)kmap_atomic(sgpnt->page, KM_USER0);
+ sg = scsi_sglist(scp);
+ req_len = fin = 0;
+ for (k = 0; k < scp->use_sg; ++k, sg = sg_next(sg)) {
+ kaddr = (unsigned char *)kmap_atomic(sg_page(sg), KM_USER0);
if (NULL == kaddr)
return -1;
- kaddr_off = (unsigned char *)kaddr + sgpnt->offset;
- len = sgpnt->length;
+ kaddr_off = (unsigned char *)kaddr + sg->offset;
+ len = sg->length;
if ((req_len + len) > max_arr_len) {
len = max_arr_len - req_len;
fin = 1;
@@ -683,7 +685,7 @@ static int fetch_to_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
kunmap_atomic(kaddr, KM_USER0);
if (fin)
return req_len + len;
- req_len += sgpnt->length;
+ req_len += sg->length;
}
return req_len;
}
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index d29f8464b74f..ebaca4ca4a13 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -24,7 +24,6 @@
#include <linux/interrupt.h>
#include <linux/blkdev.h>
#include <linux/delay.h>
-#include <linux/scatterlist.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 207f1aa08869..0e81e4cf8876 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -17,6 +17,7 @@
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/hardirq.h>
+#include <linux/scatterlist.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@@ -33,35 +34,34 @@
#define SG_MEMPOOL_NR ARRAY_SIZE(scsi_sg_pools)
#define SG_MEMPOOL_SIZE 2
+/*
+ * The maximum number of SG segments that we will put inside a scatterlist
+ * (unless chaining is used). Should ideally fit inside a single page, to
+ * avoid a higher order allocation.
+ */
+#define SCSI_MAX_SG_SEGMENTS 128
+
struct scsi_host_sg_pool {
size_t size;
- char *name;
+ char *name;
struct kmem_cache *slab;
mempool_t *pool;
};
-#if (SCSI_MAX_PHYS_SEGMENTS < 32)
-#error SCSI_MAX_PHYS_SEGMENTS is too small
-#endif
-
-#define SP(x) { x, "sgpool-" #x }
+#define SP(x) { x, "sgpool-" #x }
static struct scsi_host_sg_pool scsi_sg_pools[] = {
SP(8),
SP(16),
+#if (SCSI_MAX_SG_SEGMENTS > 16)
SP(32),
-#if (SCSI_MAX_PHYS_SEGMENTS > 32)
+#if (SCSI_MAX_SG_SEGMENTS > 32)
SP(64),
-#if (SCSI_MAX_PHYS_SEGMENTS > 64)
+#if (SCSI_MAX_SG_SEGMENTS > 64)
SP(128),
-#if (SCSI_MAX_PHYS_SEGMENTS > 128)
- SP(256),
-#if (SCSI_MAX_PHYS_SEGMENTS > 256)
-#error SCSI_MAX_PHYS_SEGMENTS is too large
#endif
#endif
#endif
-#endif
-};
+};
#undef SP
static void scsi_run_queue(struct request_queue *q);
@@ -289,14 +289,16 @@ static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl,
struct request_queue *q = rq->q;
int nr_pages = (bufflen + sgl[0].offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
unsigned int data_len = bufflen, len, bytes, off;
+ struct scatterlist *sg;
struct page *page;
struct bio *bio = NULL;
int i, err, nr_vecs = 0;
- for (i = 0; i < nsegs; i++) {
- page = sgl[i].page;
- off = sgl[i].offset;
- len = sgl[i].length;
+ for_each_sg(sgl, sg, nsegs, i) {
+ page = sg_page(sg);
+ off = sg->offset;
+ len = sg->length;
+ data_len += len;
while (len > 0 && data_len > 0) {
/*
@@ -695,56 +697,177 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate,
return NULL;
}
-struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_mask)
-{
- struct scsi_host_sg_pool *sgp;
- struct scatterlist *sgl;
+/*
+ * Like SCSI_MAX_SG_SEGMENTS, but for archs that have sg chaining. This limit
+ * is totally arbitrary, a setting of 2048 will get you at least 8mb ios.
+ */
+#define SCSI_MAX_SG_CHAIN_SEGMENTS 2048
- BUG_ON(!cmd->use_sg);
+static inline unsigned int scsi_sgtable_index(unsigned short nents)
+{
+ unsigned int index;
- switch (cmd->use_sg) {
+ switch (nents) {
case 1 ... 8:
- cmd->sglist_len = 0;
+ index = 0;
break;
case 9 ... 16:
- cmd->sglist_len = 1;
+ index = 1;
break;
+#if (SCSI_MAX_SG_SEGMENTS > 16)
case 17 ... 32:
- cmd->sglist_len = 2;
+ index = 2;
break;
-#if (SCSI_MAX_PHYS_SEGMENTS > 32)
+#if (SCSI_MAX_SG_SEGMENTS > 32)
case 33 ... 64:
- cmd->sglist_len = 3;
+ index = 3;
break;
-#if (SCSI_MAX_PHYS_SEGMENTS > 64)
+#if (SCSI_MAX_SG_SEGMENTS > 64)
case 65 ... 128:
- cmd->sglist_len = 4;
- break;
-#if (SCSI_MAX_PHYS_SEGMENTS > 128)
- case 129 ... 256:
- cmd->sglist_len = 5;
+ index = 4;
break;
#endif
#endif
#endif
default:
- return NULL;
+ printk(KERN_ERR "scsi: bad segment count=%d\n", nents);
+ BUG();
}
- sgp = scsi_sg_pools + cmd->sglist_len;
- sgl = mempool_alloc(sgp->pool, gfp_mask);
- return sgl;
+ return index;
+}
+
+struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_mask)
+{
+ struct scsi_host_sg_pool *sgp;
+ struct scatterlist *sgl, *prev, *ret;
+ unsigned int index;
+ int this, left;
+
+ BUG_ON(!cmd->use_sg);
+
+ left = cmd->use_sg;
+ ret = prev = NULL;
+ do {
+ this = left;
+ if (this > SCSI_MAX_SG_SEGMENTS) {
+ this = SCSI_MAX_SG_SEGMENTS - 1;
+ index = SG_MEMPOOL_NR - 1;
+ } else
+ index = scsi_sgtable_index(this);
+
+ left -= this;
+
+ sgp = scsi_sg_pools + index;
+
+ sgl = mempool_alloc(sgp->pool, gfp_mask);
+ if (unlikely(!sgl))
+ goto enomem;
+
+ sg_init_table(sgl, sgp->size);
+
+ /*
+ * first loop through, set initial index and return value
+ */
+ if (!ret)
+ ret = sgl;
+
+ /*
+ * chain previous sglist, if any. we know the previous
+ * sglist must be the biggest one, or we would not have
+ * ended up doing another loop.
+ */
+ if (prev)
+ sg_chain(prev, SCSI_MAX_SG_SEGMENTS, sgl);
+
+ /*
+ * if we have nothing left, mark the last segment as
+ * end-of-list
+ */
+ if (!left)
+ sg_mark_end(&sgl[this - 1]);
+
+ /*
+ * don't allow subsequent mempool allocs to sleep, it would
+ * violate the mempool principle.
+ */
+ gfp_mask &= ~__GFP_WAIT;
+ gfp_mask |= __GFP_HIGH;
+ prev = sgl;
+ } while (left);
+
+ /*
+ * ->use_sg may get modified after dma mapping has potentially
+ * shrunk the number of segments, so keep a copy of it for free.
+ */
+ cmd->__use_sg = cmd->use_sg;
+ return ret;
+enomem:
+ if (ret) {
+ /*
+ * Free entries chained off ret. Since we were trying to
+ * allocate another sglist, we know that all entries are of
+ * the max size.
+ */
+ sgp = scsi_sg_pools + SG_MEMPOOL_NR - 1;
+ prev = ret;
+ ret = &ret[SCSI_MAX_SG_SEGMENTS - 1];
+
+ while ((sgl = sg_chain_ptr(ret)) != NULL) {
+ ret = &sgl[SCSI_MAX_SG_SEGMENTS - 1];
+ mempool_free(sgl, sgp->pool);
+ }
+
+ mempool_free(prev, sgp->pool);
+ }
+ return NULL;
}
EXPORT_SYMBOL(scsi_alloc_sgtable);
-void scsi_free_sgtable(struct scatterlist *sgl, int index)
+void scsi_free_sgtable(struct scsi_cmnd *cmd)
{
+ struct scatterlist *sgl = cmd->request_buffer;
struct scsi_host_sg_pool *sgp;
- BUG_ON(index >= SG_MEMPOOL_NR);
+ /*
+ * if this is the biggest size sglist, check if we have
+ * chained parts we need to free
+ */
+ if (cmd->__use_sg > SCSI_MAX_SG_SEGMENTS) {
+ unsigned short this, left;
+ struct scatterlist *next;
+ unsigned int index;
+
+ left = cmd->__use_sg - (SCSI_MAX_SG_SEGMENTS - 1);
+ next = sg_chain_ptr(&sgl[SCSI_MAX_SG_SEGMENTS - 1]);
+ while (left && next) {
+ sgl = next;
+ this = left;
+ if (this > SCSI_MAX_SG_SEGMENTS) {
+ this = SCSI_MAX_SG_SEGMENTS - 1;
+ index = SG_MEMPOOL_NR - 1;
+ } else
+ index = scsi_sgtable_index(this);
+
+ left -= this;
+
+ sgp = scsi_sg_pools + index;
+
+ if (left)
+ next = sg_chain_ptr(&sgl[sgp->size - 1]);
+
+ mempool_free(sgl, sgp->pool);
+ }
+
+ /*
+ * Restore original, will be freed below
+ */
+ sgl = cmd->request_buffer;
+ sgp = scsi_sg_pools + SG_MEMPOOL_NR - 1;
+ } else
+ sgp = scsi_sg_pools + scsi_sgtable_index(cmd->__use_sg);
- sgp = scsi_sg_pools + index;
mempool_free(sgl, sgp->pool);
}
@@ -770,7 +893,7 @@ EXPORT_SYMBOL(scsi_free_sgtable);
static void scsi_release_buffers(struct scsi_cmnd *cmd)
{
if (cmd->use_sg)
- scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len);
+ scsi_free_sgtable(cmd);
/*
* Zero these out. They now point to freed memory, and it is
@@ -984,7 +1107,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
static int scsi_init_io(struct scsi_cmnd *cmd)
{
struct request *req = cmd->request;
- struct scatterlist *sgpnt;
int count;
/*
@@ -997,14 +1119,13 @@ static int scsi_init_io(struct scsi_cmnd *cmd)
/*
* If sg table allocation fails, requeue request later.
*/
- sgpnt = scsi_alloc_sgtable(cmd, GFP_ATOMIC);
- if (unlikely(!sgpnt)) {
+ cmd->request_buffer = scsi_alloc_sgtable(cmd, GFP_ATOMIC);
+ if (unlikely(!cmd->request_buffer)) {
scsi_unprep_request(req);
return BLKPREP_DEFER;
}
req->buffer = NULL;
- cmd->request_buffer = (char *) sgpnt;
if (blk_pc_request(req))
cmd->request_bufflen = req->data_len;
else
@@ -1529,8 +1650,25 @@ struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost,
if (!q)
return NULL;
+ /*
+ * this limit is imposed by hardware restrictions
+ */
blk_queue_max_hw_segments(q, shost->sg_tablesize);
- blk_queue_max_phys_segments(q, SCSI_MAX_PHYS_SEGMENTS);
+
+ /*
+ * In the future, sg chaining support will be mandatory and this
+ * ifdef can then go away. Right now we don't have all archs
+ * converted, so better keep it safe.
+ */
+#ifdef ARCH_HAS_SG_CHAIN
+ if (shost->use_sg_chaining)
+ blk_queue_max_phys_segments(q, SCSI_MAX_SG_CHAIN_SEGMENTS);
+ else
+ blk_queue_max_phys_segments(q, SCSI_MAX_SG_SEGMENTS);
+#else
+ blk_queue_max_phys_segments(q, SCSI_MAX_SG_SEGMENTS);
+#endif
+
blk_queue_max_sectors(q, shost->max_sectors);
blk_queue_bounce_limit(q, scsi_calculate_bounce_limit(shost));
blk_queue_segment_boundary(q, shost->dma_boundary);
@@ -1977,6 +2115,142 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state)
EXPORT_SYMBOL(scsi_device_set_state);
/**
+ * sdev_evt_emit - emit a single SCSI device uevent
+ * @sdev: associated SCSI device
+ * @evt: event to emit
+ *
+ * Send a single uevent (scsi_event) to the associated scsi_device.
+ */
+static void scsi_evt_emit(struct scsi_device *sdev, struct scsi_event *evt)
+{
+ int idx = 0;
+ char *envp[3];
+
+ switch (evt->evt_type) {
+ case SDEV_EVT_MEDIA_CHANGE:
+ envp[idx++] = "SDEV_MEDIA_CHANGE=1";
+ break;
+
+ default:
+ /* do nothing */
+ break;
+ }
+
+ envp[idx++] = NULL;
+
+ kobject_uevent_env(&sdev->sdev_gendev.kobj, KOBJ_CHANGE, envp);
+}
+
+/**
+ * sdev_evt_thread - send a uevent for each scsi event
+ * @work: work struct for scsi_device
+ *
+ * Dispatch queued events to their associated scsi_device kobjects
+ * as uevents.
+ */
+void scsi_evt_thread(struct work_struct *work)
+{
+ struct scsi_device *sdev;
+ LIST_HEAD(event_list);
+
+ sdev = container_of(work, struct scsi_device, event_work);
+
+ while (1) {
+ struct scsi_event *evt;
+ struct list_head *this, *tmp;
+ unsigned long flags;
+
+ spin_lock_irqsave(&sdev->list_lock, flags);
+ list_splice_init(&sdev->event_list, &event_list);
+ spin_unlock_irqrestore(&sdev->list_lock, flags);
+
+ if (list_empty(&event_list))
+ break;
+
+ list_for_each_safe(this, tmp, &event_list) {
+ evt = list_entry(this, struct scsi_event, node);
+ list_del(&evt->node);
+ scsi_evt_emit(sdev, evt);
+ kfree(evt);
+ }
+ }
+}
+
+/**
+ * sdev_evt_send - send asserted event to uevent thread
+ * @sdev: scsi_device event occurred on
+ * @evt: event to send
+ *
+ * Assert scsi device event asynchronously.
+ */
+void sdev_evt_send(struct scsi_device *sdev, struct scsi_event *evt)
+{
+ unsigned long flags;
+
+ if (!test_bit(evt->evt_type, sdev->supported_events)) {
+ kfree(evt);
+ return;
+ }
+
+ spin_lock_irqsave(&sdev->list_lock, flags);
+ list_add_tail(&evt->node, &sdev->event_list);
+ schedule_work(&sdev->event_work);
+ spin_unlock_irqrestore(&sdev->list_lock, flags);
+}
+EXPORT_SYMBOL_GPL(sdev_evt_send);
+
+/**
+ * sdev_evt_alloc - allocate a new scsi event
+ * @evt_type: type of event to allocate
+ * @gfpflags: GFP flags for allocation
+ *
+ * Allocates and returns a new scsi_event.
+ */
+struct scsi_event *sdev_evt_alloc(enum scsi_device_event evt_type,
+ gfp_t gfpflags)
+{
+ struct scsi_event *evt = kzalloc(sizeof(struct scsi_event), gfpflags);
+ if (!evt)
+ return NULL;
+
+ evt->evt_type = evt_type;
+ INIT_LIST_HEAD(&evt->node);
+
+ /* evt_type-specific initialization, if any */
+ switch (evt_type) {
+ case SDEV_EVT_MEDIA_CHANGE:
+ default:
+ /* do nothing */
+ break;
+ }
+
+ return evt;
+}
+EXPORT_SYMBOL_GPL(sdev_evt_alloc);
+
+/**
+ * sdev_evt_send_simple - send asserted event to uevent thread
+ * @sdev: scsi_device event occurred on
+ * @evt_type: type of event to send
+ * @gfpflags: GFP flags for allocation
+ *
+ * Assert scsi device event asynchronously, given an event type.
+ */
+void sdev_evt_send_simple(struct scsi_device *sdev,
+ enum scsi_device_event evt_type, gfp_t gfpflags)
+{
+ struct scsi_event *evt = sdev_evt_alloc(evt_type, gfpflags);
+ if (!evt) {
+ sdev_printk(KERN_ERR, sdev, "event %d eaten due to OOM\n",
+ evt_type);
+ return;
+ }
+
+ sdev_evt_send(sdev, evt);
+}
+EXPORT_SYMBOL_GPL(sdev_evt_send_simple);
+
+/**
* scsi_device_quiesce - Block user issued commands.
* @sdev: scsi device to quiesce.
*
@@ -2193,18 +2467,19 @@ EXPORT_SYMBOL_GPL(scsi_target_unblock);
*
* Returns virtual address of the start of the mapped page
*/
-void *scsi_kmap_atomic_sg(struct scatterlist *sg, int sg_count,
+void *scsi_kmap_atomic_sg(struct scatterlist *sgl, int sg_count,
size_t *offset, size_t *len)
{
int i;
size_t sg_len = 0, len_complete = 0;
+ struct scatterlist *sg;
struct page *page;
WARN_ON(!irqs_disabled());
- for (i = 0; i < sg_count; i++) {
+ for_each_sg(sgl, sg, sg_count, i) {
len_complete = sg_len; /* Complete sg-entries */
- sg_len += sg[i].length;
+ sg_len += sg->length;
if (sg_len > *offset)
break;
}
@@ -2218,10 +2493,10 @@ void *scsi_kmap_atomic_sg(struct scatterlist *sg, int sg_count,
}
/* Offset starting from the beginning of first page in this sg-entry */
- *offset = *offset - len_complete + sg[i].offset;
+ *offset = *offset - len_complete + sg->offset;
/* Assumption: contiguous pages can be accessed as "page + i" */
- page = nth_page(sg[i].page, (*offset >> PAGE_SHIFT));
+ page = nth_page(sg_page(sg), (*offset >> PAGE_SHIFT));
*offset &= ~PAGE_MASK;
/* Bytes in this sg-entry from *offset to the end of the page */
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index b53c5f67e372..40ea71cd2ca6 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -236,6 +236,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
struct scsi_device *sdev;
int display_failure_msg = 1, ret;
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ extern void scsi_evt_thread(struct work_struct *work);
sdev = kzalloc(sizeof(*sdev) + shost->transportt->device_size,
GFP_ATOMIC);
@@ -254,7 +255,9 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
INIT_LIST_HEAD(&sdev->same_target_siblings);
INIT_LIST_HEAD(&sdev->cmd_list);
INIT_LIST_HEAD(&sdev->starved_entry);
+ INIT_LIST_HEAD(&sdev->event_list);
spin_lock_init(&sdev->list_lock);
+ INIT_WORK(&sdev->event_work, scsi_evt_thread);
sdev->sdev_gendev.parent = get_device(&starget->dev);
sdev->sdev_target = starget;
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index daed37df00b1..f374fdcb6815 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -209,11 +209,13 @@ show_shost_mode(unsigned int mode, char *buf)
static ssize_t show_shost_supported_mode(struct class_device *class_dev, char *buf)
{
struct Scsi_Host *shost = class_to_shost(class_dev);
+ unsigned int supported_mode = shost->hostt->supported_mode;
- if (shost->hostt->supported_mode == MODE_UNKNOWN)
- return snprintf(buf, 20, "unknown\n");
- else
- return show_shost_mode(shost->hostt->supported_mode, buf);
+ if (supported_mode == MODE_UNKNOWN)
+ /* by default this should be initiator */
+ supported_mode = MODE_INITIATOR;
+
+ return show_shost_mode(supported_mode, buf);
}
static CLASS_DEVICE_ATTR(supported_mode, S_IRUGO | S_IWUSR, show_shost_supported_mode, NULL);
@@ -266,6 +268,7 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work)
struct scsi_device *sdev;
struct device *parent;
struct scsi_target *starget;
+ struct list_head *this, *tmp;
unsigned long flags;
sdev = container_of(work, struct scsi_device, ew.work);
@@ -280,6 +283,16 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work)
list_del(&sdev->starved_entry);
spin_unlock_irqrestore(sdev->host->host_lock, flags);
+ cancel_work_sync(&sdev->event_work);
+
+ list_for_each_safe(this, tmp, &sdev->event_list) {
+ struct scsi_event *evt;
+
+ evt = list_entry(this, struct scsi_event, node);
+ list_del(&evt->node);
+ kfree(evt);
+ }
+
if (sdev->request_queue) {
sdev->request_queue->queuedata = NULL;
/* user context needed to free queue */
@@ -612,6 +625,41 @@ sdev_show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
}
static DEVICE_ATTR(modalias, S_IRUGO, sdev_show_modalias, NULL);
+#define DECLARE_EVT_SHOW(name, Cap_name) \
+static ssize_t \
+sdev_show_evt_##name(struct device *dev, struct device_attribute *attr, \
+ char *buf) \
+{ \
+ struct scsi_device *sdev = to_scsi_device(dev); \
+ int val = test_bit(SDEV_EVT_##Cap_name, sdev->supported_events);\
+ return snprintf(buf, 20, "%d\n", val); \
+}
+
+#define DECLARE_EVT_STORE(name, Cap_name) \
+static ssize_t \
+sdev_store_evt_##name(struct device *dev, struct device_attribute *attr, \
+ const char *buf, size_t count) \
+{ \
+ struct scsi_device *sdev = to_scsi_device(dev); \
+ int val = simple_strtoul(buf, NULL, 0); \
+ if (val == 0) \
+ clear_bit(SDEV_EVT_##Cap_name, sdev->supported_events); \
+ else if (val == 1) \
+ set_bit(SDEV_EVT_##Cap_name, sdev->supported_events); \
+ else \
+ return -EINVAL; \
+ return count; \
+}
+
+#define DECLARE_EVT(name, Cap_name) \
+ DECLARE_EVT_SHOW(name, Cap_name) \
+ DECLARE_EVT_STORE(name, Cap_name) \
+ static DEVICE_ATTR(evt_##name, S_IRUGO, sdev_show_evt_##name, \
+ sdev_store_evt_##name);
+#define REF_EVT(name) &dev_attr_evt_##name.attr
+
+DECLARE_EVT(media_change, MEDIA_CHANGE)
+
/* Default template for device attributes. May NOT be modified */
static struct attribute *scsi_sdev_attrs[] = {
&dev_attr_device_blocked.attr,
@@ -629,6 +677,7 @@ static struct attribute *scsi_sdev_attrs[] = {
&dev_attr_iodone_cnt.attr,
&dev_attr_ioerr_cnt.attr,
&dev_attr_modalias.attr,
+ REF_EVT(media_change),
NULL
};
diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c
index 66c692ffa305..a91761c3645f 100644
--- a/drivers/scsi/scsi_tgt_lib.c
+++ b/drivers/scsi/scsi_tgt_lib.c
@@ -332,7 +332,7 @@ static void scsi_tgt_cmd_done(struct scsi_cmnd *cmd)
scsi_tgt_uspace_send_status(cmd, tcmd->itn_id, tcmd->tag);
if (cmd->request_buffer)
- scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len);
+ scsi_free_sgtable(cmd);
queue_work(scsi_tgtd, &tcmd->work);
}
@@ -373,7 +373,7 @@ static int scsi_tgt_init_cmd(struct scsi_cmnd *cmd, gfp_t gfp_mask)
}
eprintk("cmd %p cnt %d\n", cmd, cmd->use_sg);
- scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len);
+ scsi_free_sgtable(cmd);
return -EINVAL;
}
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 0a3a528212c2..a69b155f39a2 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -676,7 +676,7 @@ static int sd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
* success as well). Returns a negated errno value in case of error.
*
* Note: most ioctls are forward onto the block subsystem or further
- * down in the scsi subsytem.
+ * down in the scsi subsystem.
**/
static int sd_ioctl(struct inode * inode, struct file * filp,
unsigned int cmd, unsigned long arg)
@@ -826,27 +826,6 @@ static int sd_sync_cache(struct scsi_disk *sdkp)
return 0;
}
-static int sd_issue_flush(struct request_queue *q, struct gendisk *disk,
- sector_t *error_sector)
-{
- int ret = 0;
- struct scsi_device *sdp = q->queuedata;
- struct scsi_disk *sdkp;
-
- if (sdp->sdev_state != SDEV_RUNNING)
- return -ENXIO;
-
- sdkp = scsi_disk_get_from_dev(&sdp->sdev_gendev);
-
- if (!sdkp)
- return -ENODEV;
-
- if (sdkp->WCE)
- ret = sd_sync_cache(sdkp);
- scsi_disk_put(sdkp);
- return ret;
-}
-
static void sd_prepare_flush(struct request_queue *q, struct request *rq)
{
memset(rq->cmd, 0, sizeof(rq->cmd));
@@ -1697,7 +1676,6 @@ static int sd_probe(struct device *dev)
sd_revalidate_disk(gd);
blk_queue_prep_rq(sdp->request_queue, sd_prep_fn);
- blk_queue_issue_flush_fn(sdp->request_queue, sd_issue_flush);
gd->driverfs_dev = &sdp->sdev_gendev;
gd->flags = GENHD_FL_DRIVERFS;
diff --git a/drivers/scsi/seagate.c b/drivers/scsi/seagate.c
index ce80fa9ad815..b11324479b5b 100644
--- a/drivers/scsi/seagate.c
+++ b/drivers/scsi/seagate.c
@@ -999,14 +999,14 @@ connect_loop:
for (i = 0; i < nobuffs; ++i)
printk("scsi%d : buffer %d address = %p length = %d\n",
hostno, i,
- page_address(buffer[i].page) + buffer[i].offset,
+ sg_virt(&buffer[i]),
buffer[i].length);
}
#endif
buffer = (struct scatterlist *) SCint->request_buffer;
len = buffer->length;
- data = page_address(buffer->page) + buffer->offset;
+ data = sg_virt(buffer);
} else {
DPRINTK (DEBUG_SG, "scsi%d : scatter gather not requested.\n", hostno);
buffer = NULL;
@@ -1239,7 +1239,7 @@ connect_loop:
--nobuffs;
++buffer;
len = buffer->length;
- data = page_address(buffer->page) + buffer->offset;
+ data = sg_virt(buffer);
DPRINTK (DEBUG_SG,
"scsi%d : next scatter-gather buffer len = %d address = %08x\n",
hostno, len, data);
@@ -1396,7 +1396,7 @@ connect_loop:
--nobuffs;
++buffer;
len = buffer->length;
- data = page_address(buffer->page) + buffer->offset;
+ data = sg_virt(buffer);
DPRINTK (DEBUG_SG, "scsi%d : next scatter-gather buffer len = %d address = %08x\n", hostno, len, data);
}
break;
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index f6f5fc7d0cee..f1871ea04045 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1165,11 +1165,11 @@ sg_vma_nopage(struct vm_area_struct *vma, unsigned long addr, int *type)
sg = rsv_schp->buffer;
sa = vma->vm_start;
for (k = 0; (k < rsv_schp->k_use_sg) && (sa < vma->vm_end);
- ++k, ++sg) {
+ ++k, sg = sg_next(sg)) {
len = vma->vm_end - sa;
len = (len < sg->length) ? len : sg->length;
if (offset < len) {
- page = virt_to_page(page_address(sg->page) + offset);
+ page = virt_to_page(page_address(sg_page(sg)) + offset);
get_page(page); /* increment page count */
break;
}
@@ -1209,7 +1209,7 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma)
sa = vma->vm_start;
sg = rsv_schp->buffer;
for (k = 0; (k < rsv_schp->k_use_sg) && (sa < vma->vm_end);
- ++k, ++sg) {
+ ++k, sg = sg_next(sg)) {
len = vma->vm_end - sa;
len = (len < sg->length) ? len : sg->length;
sa += len;
@@ -1652,6 +1652,7 @@ sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp, int tablesize)
schp->buffer = kzalloc(sg_bufflen, gfp_flags);
if (!schp->buffer)
return -ENOMEM;
+ sg_init_table(schp->buffer, tablesize);
schp->sglist_len = sg_bufflen;
return tablesize; /* number of scat_gath elements allocated */
}
@@ -1717,16 +1718,12 @@ st_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages,
goto out_unlock; */
}
- sgl[0].page = pages[0];
- sgl[0].offset = uaddr & ~PAGE_MASK;
+ sg_set_page(sgl, pages[0], 0, uaddr & ~PAGE_MASK);
if (nr_pages > 1) {
sgl[0].length = PAGE_SIZE - sgl[0].offset;
count -= sgl[0].length;
- for (i=1; i < nr_pages ; i++) {
- sgl[i].page = pages[i];
- sgl[i].length = count < PAGE_SIZE ? count : PAGE_SIZE;
- count -= PAGE_SIZE;
- }
+ for (i=1; i < nr_pages ; i++)
+ sg_set_page(&sgl[i], pages[i], count < PAGE_SIZE ? count : PAGE_SIZE, 0);
}
else {
sgl[0].length = count;
@@ -1754,7 +1751,7 @@ st_unmap_user_pages(struct scatterlist *sgl, const unsigned int nr_pages,
int i;
for (i=0; i < nr_pages; i++) {
- struct page *page = sgl[i].page;
+ struct page *page = sg_page(&sgl[i]);
if (dirtied)
SetPageDirty(page);
@@ -1840,7 +1837,7 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size)
}
for (k = 0, sg = schp->buffer, rem_sz = blk_size;
(rem_sz > 0) && (k < mx_sc_elems);
- ++k, rem_sz -= ret_sz, ++sg) {
+ ++k, rem_sz -= ret_sz, sg = sg_next(sg)) {
num = (rem_sz > scatter_elem_sz_prev) ?
scatter_elem_sz_prev : rem_sz;
@@ -1854,8 +1851,7 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size)
scatter_elem_sz_prev = ret_sz;
}
}
- sg->page = p;
- sg->length = (ret_sz > num) ? num : ret_sz;
+ sg_set_page(sg, p, (ret_sz > num) ? num : ret_sz, 0);
SCSI_LOG_TIMEOUT(5, printk("sg_build_indirect: k=%d, num=%d, "
"ret_sz=%d\n", k, num, ret_sz));
@@ -1907,14 +1903,14 @@ sg_write_xfer(Sg_request * srp)
onum = 1;
ksglen = sg->length;
- p = page_address(sg->page);
+ p = page_address(sg_page(sg));
for (j = 0, k = 0; j < onum; ++j) {
res = sg_u_iovec(hp, iovec_count, j, 1, &usglen, &up);
if (res)
return res;
- for (; p; ++sg, ksglen = sg->length,
- p = page_address(sg->page)) {
+ for (; p; sg = sg_next(sg), ksglen = sg->length,
+ p = page_address(sg_page(sg))) {
if (usglen <= 0)
break;
if (ksglen > usglen) {
@@ -1991,12 +1987,12 @@ sg_remove_scat(Sg_scatter_hold * schp)
} else {
int k;
- for (k = 0; (k < schp->k_use_sg) && sg->page;
- ++k, ++sg) {
+ for (k = 0; (k < schp->k_use_sg) && sg_page(sg);
+ ++k, sg = sg_next(sg)) {
SCSI_LOG_TIMEOUT(5, printk(
"sg_remove_scat: k=%d, pg=0x%p, len=%d\n",
- k, sg->page, sg->length));
- sg_page_free(sg->page, sg->length);
+ k, sg_page(sg), sg->length));
+ sg_page_free(sg_page(sg), sg->length);
}
}
kfree(schp->buffer);
@@ -2038,15 +2034,15 @@ sg_read_xfer(Sg_request * srp)
} else
onum = 1;
- p = page_address(sg->page);
+ p = page_address(sg_page(sg));
ksglen = sg->length;
for (j = 0, k = 0; j < onum; ++j) {
res = sg_u_iovec(hp, iovec_count, j, 0, &usglen, &up);
if (res)
return res;
- for (; p; ++sg, ksglen = sg->length,
- p = page_address(sg->page)) {
+ for (; p; sg = sg_next(sg), ksglen = sg->length,
+ p = page_address(sg_page(sg))) {
if (usglen <= 0)
break;
if (ksglen > usglen) {
@@ -2092,15 +2088,15 @@ sg_read_oxfer(Sg_request * srp, char __user *outp, int num_read_xfer)
if ((!outp) || (num_read_xfer <= 0))
return 0;
- for (k = 0; (k < schp->k_use_sg) && sg->page; ++k, ++sg) {
+ for (k = 0; (k < schp->k_use_sg) && sg_page(sg); ++k, sg = sg_next(sg)) {
num = sg->length;
if (num > num_read_xfer) {
- if (__copy_to_user(outp, page_address(sg->page),
+ if (__copy_to_user(outp, page_address(sg_page(sg)),
num_read_xfer))
return -EFAULT;
break;
} else {
- if (__copy_to_user(outp, page_address(sg->page),
+ if (__copy_to_user(outp, page_address(sg_page(sg)),
num))
return -EFAULT;
num_read_xfer -= num;
@@ -2142,7 +2138,7 @@ sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size)
SCSI_LOG_TIMEOUT(4, printk("sg_link_reserve: size=%d\n", size));
rem = size;
- for (k = 0; k < rsv_schp->k_use_sg; ++k, ++sg) {
+ for (k = 0; k < rsv_schp->k_use_sg; ++k, sg = sg_next(sg)) {
num = sg->length;
if (rem <= num) {
sfp->save_scat_len = num;
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 73c44cbdea47..98dfd6ea209c 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -3797,13 +3797,11 @@ static void buf_to_sg(struct st_buffer *STbp, unsigned int length)
sg = &(STbp->sg[0]);
frp = STbp->frp;
for (i=count=0; count < length; i++) {
- sg[i].page = frp[i].page;
if (length - count > frp[i].length)
- sg[i].length = frp[i].length;
+ sg_set_page(&sg[i], frp[i].page, frp[i].length, 0);
else
- sg[i].length = length - count;
+ sg_set_page(&sg[i], frp[i].page, length - count, 0);
count += sg[i].length;
- sg[i].offset = 0;
}
STbp->sg_segs = i;
STbp->frp_sg_current = length;
@@ -4446,15 +4444,13 @@ static int sgl_map_user_pages(struct scatterlist *sgl, const unsigned int max_pa
}
/* Populate the scatter/gather list */
- sgl[0].page = pages[0];
- sgl[0].offset = uaddr & ~PAGE_MASK;
+ sg_set_page(&sgl[0], pages[0], 0, uaddr & ~PAGE_MASK);
if (nr_pages > 1) {
sgl[0].length = PAGE_SIZE - sgl[0].offset;
count -= sgl[0].length;
for (i=1; i < nr_pages ; i++) {
- sgl[i].offset = 0;
- sgl[i].page = pages[i];
- sgl[i].length = count < PAGE_SIZE ? count : PAGE_SIZE;
+ sg_set_page(&sgl[i], pages[i],
+ count < PAGE_SIZE ? count : PAGE_SIZE, 0);;
count -= PAGE_SIZE;
}
}
@@ -4483,7 +4479,7 @@ static int sgl_unmap_user_pages(struct scatterlist *sgl, const unsigned int nr_p
int i;
for (i=0; i < nr_pages; i++) {
- struct page *page = sgl[i].page;
+ struct page *page = sg_page(&sgl[i]);
if (dirtied)
SetPageDirty(page);
diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c
index 72f6d8015358..e3fab3a6aed7 100644
--- a/drivers/scsi/stex.c
+++ b/drivers/scsi/stex.c
@@ -1123,6 +1123,7 @@ static struct scsi_host_template driver_template = {
.this_id = -1,
.sg_tablesize = ST_MAX_SG,
.cmd_per_lun = ST_CMD_PER_LUN,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
};
static int stex_set_dma_mask(struct pci_dev * pdev)
diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c
index dc15a22105f7..2dcde373b20e 100644
--- a/drivers/scsi/sun3_NCR5380.c
+++ b/drivers/scsi/sun3_NCR5380.c
@@ -272,8 +272,7 @@ static struct scsi_host_template *the_template = NULL;
#define HOSTNO instance->host_no
#define H_NO(cmd) (cmd)->device->host->host_no
-#define SGADDR(buffer) (void *)(((unsigned long)page_address((buffer)->page)) + \
- (buffer)->offset)
+#define SGADDR(buffer) (void *)(((unsigned long)sg_virt(((buffer)))))
#ifdef SUPPORT_TAGS
@@ -1596,7 +1595,7 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd,
* IO while SEL is true. But again, there are some disks out the in the
* world that do that nevertheless. (Somebody claimed that this announces
* reselection capability of the target.) So we better skip that test and
- * only wait for BSY... (Famous german words: Der Klügere gibt nach :-)
+ * only wait for BSY... (Famous german words: Der Klügere gibt nach :-)
*/
while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) &
diff --git a/drivers/scsi/sun3x_esp.c b/drivers/scsi/sun3x_esp.c
index 80fb3f88af2e..1bc41907a038 100644
--- a/drivers/scsi/sun3x_esp.c
+++ b/drivers/scsi/sun3x_esp.c
@@ -332,8 +332,8 @@ static void dma_mmu_get_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp)
struct scatterlist *sg = sp->SCp.buffer;
while (sz >= 0) {
- sg[sz].dma_address = dvma_map((unsigned long)page_address(sg[sz].page) +
- sg[sz].offset, sg[sz].length);
+ sg[sz].dma_address = dvma_map((unsigned long)sg_virt(&sg[sz]),
+ sg[sz].length);
sz--;
}
sp->SCp.ptr=(char *)((unsigned long)sp->SCp.buffer->dma_address);
diff --git a/drivers/scsi/sym53c416.c b/drivers/scsi/sym53c416.c
index 92bfaeafe30d..90cee94d9522 100644
--- a/drivers/scsi/sym53c416.c
+++ b/drivers/scsi/sym53c416.c
@@ -196,7 +196,7 @@ static unsigned int sym53c416_base_3[2] = {0,0};
#define MAXHOSTS 4
-#define SG_ADDRESS(buffer) ((char *) (page_address((buffer)->page)+(buffer)->offset))
+#define SG_ADDRESS(buffer) ((char *) sg_virt((buffer)))
enum phases
{
@@ -854,5 +854,6 @@ static struct scsi_host_template driver_template = {
.cmd_per_lun = 1,
.unchecked_isa_dma = 1,
.use_clustering = ENABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
};
#include "scsi_module.c"
diff --git a/drivers/scsi/sym53c8xx_2/sym53c8xx.h b/drivers/scsi/sym53c8xx_2/sym53c8xx.h
index 7519728dfc38..62d29cfac9e4 100644
--- a/drivers/scsi/sym53c8xx_2/sym53c8xx.h
+++ b/drivers/scsi/sym53c8xx_2/sym53c8xx.h
@@ -127,7 +127,6 @@ struct sym_driver_setup {
u_char settle_delay;
u_char use_nvram;
u_long excludes[8];
- char tag_ctrl[100];
};
#define SYM_SETUP_MAX_TAG sym_driver_setup.max_tag
diff --git a/drivers/scsi/sym53c8xx_2/sym_fw.c b/drivers/scsi/sym53c8xx_2/sym_fw.c
index 9916a2a22558..190770bdc194 100644
--- a/drivers/scsi/sym53c8xx_2/sym_fw.c
+++ b/drivers/scsi/sym53c8xx_2/sym_fw.c
@@ -104,8 +104,9 @@ static struct sym_fwz_ofs sym_fw2z_ofs = {
* Patch routine for firmware #1.
*/
static void
-sym_fw1_patch(struct sym_hcb *np)
+sym_fw1_patch(struct Scsi_Host *shost)
{
+ struct sym_hcb *np = sym_get_hcb(shost);
struct sym_fw1a_scr *scripta0;
struct sym_fw1b_scr *scriptb0;
@@ -145,8 +146,11 @@ sym_fw1_patch(struct sym_hcb *np)
* Patch routine for firmware #2.
*/
static void
-sym_fw2_patch(struct sym_hcb *np)
+sym_fw2_patch(struct Scsi_Host *shost)
{
+ struct sym_data *sym_data = shost_priv(shost);
+ struct pci_dev *pdev = sym_data->pdev;
+ struct sym_hcb *np = sym_data->ncb;
struct sym_fw2a_scr *scripta0;
struct sym_fw2b_scr *scriptb0;
@@ -167,7 +171,7 @@ sym_fw2_patch(struct sym_hcb *np)
* Remove useless 64 bit DMA specific SCRIPTS,
* when this feature is not available.
*/
- if (!np->use_dac) {
+ if (!use_dac(np)) {
scripta0->is_dmap_dirty[0] = cpu_to_scr(SCR_NO_OP);
scripta0->is_dmap_dirty[1] = 0;
scripta0->is_dmap_dirty[2] = cpu_to_scr(SCR_NO_OP);
@@ -205,14 +209,14 @@ sym_fw2_patch(struct sym_hcb *np)
* Remove a couple of work-arounds specific to C1010 if
* they are not desirable. See `sym_fw2.h' for more details.
*/
- if (!(np->device_id == PCI_DEVICE_ID_LSI_53C1010_66 &&
- np->revision_id < 0x1 &&
+ if (!(pdev->device == PCI_DEVICE_ID_LSI_53C1010_66 &&
+ pdev->revision < 0x1 &&
np->pciclk_khz < 60000)) {
scripta0->datao_phase[0] = cpu_to_scr(SCR_NO_OP);
scripta0->datao_phase[1] = cpu_to_scr(0);
}
- if (!(np->device_id == PCI_DEVICE_ID_LSI_53C1010_33 &&
- /* np->revision_id < 0xff */ 1)) {
+ if (!(pdev->device == PCI_DEVICE_ID_LSI_53C1010_33 /* &&
+ pdev->revision < 0xff */)) {
scripta0->sel_done[0] = cpu_to_scr(SCR_NO_OP);
scripta0->sel_done[1] = cpu_to_scr(0);
}
diff --git a/drivers/scsi/sym53c8xx_2/sym_fw.h b/drivers/scsi/sym53c8xx_2/sym_fw.h
index 66ec35beab5b..ae7e0f9e93fc 100644
--- a/drivers/scsi/sym53c8xx_2/sym_fw.h
+++ b/drivers/scsi/sym53c8xx_2/sym_fw.h
@@ -143,7 +143,7 @@ struct sym_fw {
*z_ofs; /* Useful offsets in script Z */
/* Setup and patch methods for this firmware */
void (*setup)(struct sym_hcb *, struct sym_fw *);
- void (*patch)(struct sym_hcb *);
+ void (*patch)(struct Scsi_Host *);
};
/*
diff --git a/drivers/scsi/sym53c8xx_2/sym_fw2.h b/drivers/scsi/sym53c8xx_2/sym_fw2.h
index 6e5b952312e3..ae1fb179b88e 100644
--- a/drivers/scsi/sym53c8xx_2/sym_fw2.h
+++ b/drivers/scsi/sym53c8xx_2/sym_fw2.h
@@ -1781,7 +1781,7 @@ static struct SYM_FWB_SCR SYM_FWB_SCR = {
* While testing with bogus QUANTUM drives, the C1010
* sometimes raised a spurious phase mismatch with
* WSR and the CHMOV(1) triggered another PM.
- * Waiting explicitely for the PHASE seemed to avoid
+ * Waiting explicitly for the PHASE seemed to avoid
* the nested phase mismatch. Btw, this didn't happen
* using my IBM drives.
*/
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index 3db22325ea2c..0f74aba5b237 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -39,7 +39,6 @@
*/
#include <linux/ctype.h>
#include <linux/init.h>
-#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/spinlock.h>
@@ -54,16 +53,12 @@
#define NAME53C "sym53c"
#define NAME53C8XX "sym53c8xx"
-#define IRQ_FMT "%d"
-#define IRQ_PRM(x) (x)
-
struct sym_driver_setup sym_driver_setup = SYM_LINUX_DRIVER_SETUP;
unsigned int sym_debug_flags = 0;
static char *excl_string;
static char *safe_string;
module_param_named(cmd_per_lun, sym_driver_setup.max_tag, ushort, 0);
-module_param_string(tag_ctrl, sym_driver_setup.tag_ctrl, 100, 0);
module_param_named(burst, sym_driver_setup.burst_order, byte, 0);
module_param_named(led, sym_driver_setup.scsi_led, byte, 0);
module_param_named(diff, sym_driver_setup.scsi_diff, byte, 0);
@@ -78,7 +73,6 @@ module_param_named(excl, excl_string, charp, 0);
module_param_named(safe, safe_string, charp, 0);
MODULE_PARM_DESC(cmd_per_lun, "The maximum number of tags to use by default");
-MODULE_PARM_DESC(tag_ctrl, "More detailed control over tags per LUN");
MODULE_PARM_DESC(burst, "Maximum burst. 0 to disable, 255 to read from registers");
MODULE_PARM_DESC(led, "Set to 1 to enable LED support");
MODULE_PARM_DESC(diff, "0 for no differential mode, 1 for BIOS, 2 for always, 3 for not GPIO3");
@@ -134,56 +128,26 @@ static struct scsi_transport_template *sym2_transport_template = NULL;
* Driver private area in the SCSI command structure.
*/
struct sym_ucmd { /* Override the SCSI pointer structure */
- dma_addr_t data_mapping;
- unsigned char data_mapped;
- unsigned char to_do; /* For error handling */
- void (*old_done)(struct scsi_cmnd *); /* For error handling */
- struct completion *eh_done; /* For error handling */
+ struct completion *eh_done; /* SCSI error handling */
};
#define SYM_UCMD_PTR(cmd) ((struct sym_ucmd *)(&(cmd)->SCp))
#define SYM_SOFTC_PTR(cmd) sym_get_hcb(cmd->device->host)
-static void __unmap_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
-{
- if (SYM_UCMD_PTR(cmd)->data_mapped)
- scsi_dma_unmap(cmd);
-
- SYM_UCMD_PTR(cmd)->data_mapped = 0;
-}
-
-static int __map_scsi_sg_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
-{
- int use_sg;
-
- use_sg = scsi_dma_map(cmd);
- if (use_sg > 0) {
- SYM_UCMD_PTR(cmd)->data_mapped = 2;
- SYM_UCMD_PTR(cmd)->data_mapping = use_sg;
- }
-
- return use_sg;
-}
-
-#define unmap_scsi_data(np, cmd) \
- __unmap_scsi_data(np->s.device, cmd)
-#define map_scsi_sg_data(np, cmd) \
- __map_scsi_sg_data(np->s.device, cmd)
/*
* Complete a pending CAM CCB.
*/
void sym_xpt_done(struct sym_hcb *np, struct scsi_cmnd *cmd)
{
- unmap_scsi_data(np, cmd);
- cmd->scsi_done(cmd);
-}
+ struct sym_ucmd *ucmd = SYM_UCMD_PTR(cmd);
+ BUILD_BUG_ON(sizeof(struct scsi_pointer) < sizeof(struct sym_ucmd));
-static void sym_xpt_done2(struct sym_hcb *np, struct scsi_cmnd *cmd, int cam_status)
-{
- sym_set_cam_status(cmd, cam_status);
- sym_xpt_done(np, cmd);
-}
+ if (ucmd->eh_done)
+ complete(ucmd->eh_done);
+ scsi_dma_unmap(cmd);
+ cmd->scsi_done(cmd);
+}
/*
* Tell the SCSI layer about a BUS RESET.
@@ -199,14 +163,6 @@ void sym_xpt_async_bus_reset(struct sym_hcb *np)
}
/*
- * Tell the SCSI layer about a BUS DEVICE RESET message sent.
- */
-void sym_xpt_async_sent_bdr(struct sym_hcb *np, int target)
-{
- printf_notice("%s: TARGET %d has been reset.\n", sym_name(np), target);
-}
-
-/*
* Choose the more appropriate CAM status if
* the IO encountered an extended error.
*/
@@ -307,14 +263,14 @@ static int sym_scatter(struct sym_hcb *np, struct sym_ccb *cp, struct scsi_cmnd
cp->data_len = 0;
- use_sg = map_scsi_sg_data(np, cmd);
+ use_sg = scsi_dma_map(cmd);
if (use_sg > 0) {
struct scatterlist *sg;
struct sym_tcb *tp = &np->target[cp->target];
struct sym_tblmove *data;
if (use_sg > SYM_CONF_MAX_SG) {
- unmap_scsi_data(np, cmd);
+ scsi_dma_unmap(cmd);
return -1;
}
@@ -351,15 +307,6 @@ static int sym_queue_command(struct sym_hcb *np, struct scsi_cmnd *cmd)
int order;
/*
- * Minimal checkings, so that we will not
- * go outside our tables.
- */
- if (sdev->id == np->myaddr) {
- sym_xpt_done2(np, cmd, DID_NO_CONNECT);
- return 0;
- }
-
- /*
* Retrieve the target descriptor.
*/
tp = &np->target[sdev->id];
@@ -433,7 +380,7 @@ int sym_setup_data_and_start(struct sym_hcb *np, struct scsi_cmnd *cmd, struct s
*/
switch (dir) {
case DMA_BIDIRECTIONAL:
- printk("%s: got DMA_BIDIRECTIONAL command", sym_name(np));
+ scmd_printk(KERN_INFO, cmd, "got DMA_BIDIRECTIONAL command");
sym_set_cam_status(cmd, DID_ERROR);
goto out_abort;
case DMA_TO_DEVICE:
@@ -542,14 +489,16 @@ static void sym_timer(struct sym_hcb *np)
/*
* PCI BUS error handler.
*/
-void sym_log_bus_error(struct sym_hcb *np)
+void sym_log_bus_error(struct Scsi_Host *shost)
{
- u_short pci_sts;
- pci_read_config_word(np->s.device, PCI_STATUS, &pci_sts);
+ struct sym_data *sym_data = shost_priv(shost);
+ struct pci_dev *pdev = sym_data->pdev;
+ unsigned short pci_sts;
+ pci_read_config_word(pdev, PCI_STATUS, &pci_sts);
if (pci_sts & 0xf900) {
- pci_write_config_word(np->s.device, PCI_STATUS, pci_sts);
- printf("%s: PCI STATUS = 0x%04x\n",
- sym_name(np), pci_sts & 0xf900);
+ pci_write_config_word(pdev, PCI_STATUS, pci_sts);
+ shost_printk(KERN_WARNING, shost,
+ "PCI bus error: status = 0x%04x\n", pci_sts & 0xf900);
}
}
@@ -564,7 +513,7 @@ static int sym53c8xx_queue_command(struct scsi_cmnd *cmd,
struct sym_ucmd *ucp = SYM_UCMD_PTR(cmd);
int sts = 0;
- cmd->scsi_done = done;
+ cmd->scsi_done = done;
memset(ucp, 0, sizeof(*ucp));
/*
@@ -593,18 +542,23 @@ static int sym53c8xx_queue_command(struct scsi_cmnd *cmd,
*/
static irqreturn_t sym53c8xx_intr(int irq, void *dev_id)
{
- unsigned long flags;
- struct sym_hcb *np = (struct sym_hcb *)dev_id;
+ struct Scsi_Host *shost = dev_id;
+ struct sym_data *sym_data = shost_priv(shost);
+ irqreturn_t result;
+
+ /* Avoid spinloop trying to handle interrupts on frozen device */
+ if (pci_channel_offline(sym_data->pdev))
+ return IRQ_NONE;
if (DEBUG_FLAGS & DEBUG_TINY) printf_debug ("[");
- spin_lock_irqsave(np->s.host->host_lock, flags);
- sym_interrupt(np);
- spin_unlock_irqrestore(np->s.host->host_lock, flags);
+ spin_lock(shost->host_lock);
+ result = sym_interrupt(shost);
+ spin_unlock(shost->host_lock);
if (DEBUG_FLAGS & DEBUG_TINY) printf_debug ("]\n");
- return IRQ_HANDLED;
+ return result;
}
/*
@@ -630,59 +584,61 @@ static void sym53c8xx_timer(unsigned long npref)
#define SYM_EH_HOST_RESET 3
/*
- * What we will do regarding the involved SCSI command.
- */
-#define SYM_EH_DO_IGNORE 0
-#define SYM_EH_DO_WAIT 2
-
-/*
- * scsi_done() alias when error recovery is in progress.
- */
-static void sym_eh_done(struct scsi_cmnd *cmd)
-{
- struct sym_ucmd *ucmd = SYM_UCMD_PTR(cmd);
- BUILD_BUG_ON(sizeof(struct scsi_pointer) < sizeof(struct sym_ucmd));
-
- cmd->scsi_done = ucmd->old_done;
-
- if (ucmd->to_do == SYM_EH_DO_WAIT)
- complete(ucmd->eh_done);
-}
-
-/*
* Generic method for our eh processing.
* The 'op' argument tells what we have to do.
*/
static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd)
{
- struct sym_hcb *np = SYM_SOFTC_PTR(cmd);
struct sym_ucmd *ucmd = SYM_UCMD_PTR(cmd);
- struct Scsi_Host *host = cmd->device->host;
+ struct Scsi_Host *shost = cmd->device->host;
+ struct sym_data *sym_data = shost_priv(shost);
+ struct pci_dev *pdev = sym_data->pdev;
+ struct sym_hcb *np = sym_data->ncb;
SYM_QUEHEAD *qp;
- int to_do = SYM_EH_DO_IGNORE;
+ int cmd_queued = 0;
int sts = -1;
struct completion eh_done;
- dev_warn(&cmd->device->sdev_gendev, "%s operation started.\n", opname);
+ scmd_printk(KERN_WARNING, cmd, "%s operation started\n", opname);
+
+ /* We may be in an error condition because the PCI bus
+ * went down. In this case, we need to wait until the
+ * PCI bus is reset, the card is reset, and only then
+ * proceed with the scsi error recovery. There's no
+ * point in hurrying; take a leisurely wait.
+ */
+#define WAIT_FOR_PCI_RECOVERY 35
+ if (pci_channel_offline(pdev)) {
+ struct completion *io_reset;
+ int finished_reset = 0;
+ init_completion(&eh_done);
+ spin_lock_irq(shost->host_lock);
+ /* Make sure we didn't race */
+ if (pci_channel_offline(pdev)) {
+ if (!sym_data->io_reset)
+ sym_data->io_reset = &eh_done;
+ io_reset = sym_data->io_reset;
+ } else {
+ finished_reset = 1;
+ }
+ spin_unlock_irq(shost->host_lock);
+ if (!finished_reset)
+ finished_reset = wait_for_completion_timeout(io_reset,
+ WAIT_FOR_PCI_RECOVERY*HZ);
+ if (!finished_reset)
+ return SCSI_FAILED;
+ }
- spin_lock_irq(host->host_lock);
+ spin_lock_irq(shost->host_lock);
/* This one is queued in some place -> to wait for completion */
FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) {
struct sym_ccb *cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
if (cp->cmd == cmd) {
- to_do = SYM_EH_DO_WAIT;
+ cmd_queued = 1;
break;
}
}
- if (to_do == SYM_EH_DO_WAIT) {
- init_completion(&eh_done);
- ucmd->old_done = cmd->scsi_done;
- ucmd->eh_done = &eh_done;
- wmb();
- cmd->scsi_done = sym_eh_done;
- }
-
/* Try to proceed the operation we have been asked for */
sts = -1;
switch(op) {
@@ -698,7 +654,7 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd)
break;
case SYM_EH_HOST_RESET:
sym_reset_scsi_bus(np, 0);
- sym_start_up (np, 1);
+ sym_start_up(shost, 1);
sts = 0;
break;
default:
@@ -706,21 +662,21 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd)
}
/* On error, restore everything and cross fingers :) */
- if (sts) {
- cmd->scsi_done = ucmd->old_done;
- to_do = SYM_EH_DO_IGNORE;
- }
-
- ucmd->to_do = to_do;
- spin_unlock_irq(host->host_lock);
+ if (sts)
+ cmd_queued = 0;
- if (to_do == SYM_EH_DO_WAIT) {
+ if (cmd_queued) {
+ init_completion(&eh_done);
+ ucmd->eh_done = &eh_done;
+ spin_unlock_irq(shost->host_lock);
if (!wait_for_completion_timeout(&eh_done, 5*HZ)) {
- ucmd->to_do = SYM_EH_DO_IGNORE;
- wmb();
+ ucmd->eh_done = NULL;
sts = -2;
}
+ } else {
+ spin_unlock_irq(shost->host_lock);
}
+
dev_warn(&cmd->device->sdev_gendev, "%s operation %s.\n", opname,
sts==0 ? "complete" :sts==-2 ? "timed-out" : "failed");
return sts ? SCSI_FAILED : SCSI_SUCCESS;
@@ -775,59 +731,6 @@ static void sym_tune_dev_queuing(struct sym_tcb *tp, int lun, u_short reqtags)
}
}
-/*
- * Linux select queue depths function
- */
-#define DEF_DEPTH (sym_driver_setup.max_tag)
-#define ALL_TARGETS -2
-#define NO_TARGET -1
-#define ALL_LUNS -2
-#define NO_LUN -1
-
-static int device_queue_depth(struct sym_hcb *np, int target, int lun)
-{
- int c, h, t, u, v;
- char *p = sym_driver_setup.tag_ctrl;
- char *ep;
-
- h = -1;
- t = NO_TARGET;
- u = NO_LUN;
- while ((c = *p++) != 0) {
- v = simple_strtoul(p, &ep, 0);
- switch(c) {
- case '/':
- ++h;
- t = ALL_TARGETS;
- u = ALL_LUNS;
- break;
- case 't':
- if (t != target)
- t = (target == v) ? v : NO_TARGET;
- u = ALL_LUNS;
- break;
- case 'u':
- if (u != lun)
- u = (lun == v) ? v : NO_LUN;
- break;
- case 'q':
- if (h == np->s.unit &&
- (t == ALL_TARGETS || t == target) &&
- (u == ALL_LUNS || u == lun))
- return v;
- break;
- case '-':
- t = ALL_TARGETS;
- u = ALL_LUNS;
- break;
- default:
- break;
- }
- p = ep;
- }
- return DEF_DEPTH;
-}
-
static int sym53c8xx_slave_alloc(struct scsi_device *sdev)
{
struct sym_hcb *np = sym_get_hcb(sdev->host);
@@ -892,21 +795,16 @@ static int sym53c8xx_slave_configure(struct scsi_device *sdev)
* Use at least 2.
* Donnot use more than our maximum.
*/
- reqtags = device_queue_depth(np, sdev->id, sdev->lun);
+ reqtags = sym_driver_setup.max_tag;
if (reqtags > tp->usrtags)
reqtags = tp->usrtags;
if (!sdev->tagged_supported)
reqtags = 0;
-#if 1 /* Avoid to locally queue commands for no good reasons */
if (reqtags > SYM_CONF_MAX_TAG)
reqtags = SYM_CONF_MAX_TAG;
- depth_to_use = (reqtags ? reqtags : 2);
-#else
- depth_to_use = (reqtags ? SYM_CONF_MAX_TAG : 2);
-#endif
+ depth_to_use = reqtags ? reqtags : 2;
scsi_adjust_queue_depth(sdev,
- (sdev->tagged_supported ?
- MSG_SIMPLE_TAG : 0),
+ sdev->tagged_supported ? MSG_SIMPLE_TAG : 0,
depth_to_use);
lp->s.scdev_depth = depth_to_use;
sym_tune_dev_queuing(tp, sdev->lun, reqtags);
@@ -1089,8 +987,9 @@ static int is_keyword(char *ptr, int len, char *verb)
* Parse a control command
*/
-static int sym_user_command(struct sym_hcb *np, char *buffer, int length)
+static int sym_user_command(struct Scsi_Host *shost, char *buffer, int length)
{
+ struct sym_hcb *np = sym_get_hcb(shost);
char *ptr = buffer;
int len = length;
struct sym_usrcmd cmd, *uc = &cmd;
@@ -1217,9 +1116,9 @@ printk("sym_user_command: data=%ld\n", uc->data);
else {
unsigned long flags;
- spin_lock_irqsave(np->s.host->host_lock, flags);
- sym_exec_user_command (np, uc);
- spin_unlock_irqrestore(np->s.host->host_lock, flags);
+ spin_lock_irqsave(shost->host_lock, flags);
+ sym_exec_user_command(np, uc);
+ spin_unlock_irqrestore(shost->host_lock, flags);
}
return length;
}
@@ -1275,8 +1174,11 @@ static int copy_info(struct info_str *info, char *fmt, ...)
/*
* Copy formatted information into the input buffer.
*/
-static int sym_host_info(struct sym_hcb *np, char *ptr, off_t offset, int len)
+static int sym_host_info(struct Scsi_Host *shost, char *ptr, off_t offset, int len)
{
+ struct sym_data *sym_data = shost_priv(shost);
+ struct pci_dev *pdev = sym_data->pdev;
+ struct sym_hcb *np = sym_data->ncb;
struct info_str info;
info.buffer = ptr;
@@ -1285,10 +1187,10 @@ static int sym_host_info(struct sym_hcb *np, char *ptr, off_t offset, int len)
info.pos = 0;
copy_info(&info, "Chip " NAME53C "%s, device id 0x%x, "
- "revision id 0x%x\n",
- np->s.chip_name, np->device_id, np->revision_id);
- copy_info(&info, "At PCI address %s, IRQ " IRQ_FMT "\n",
- pci_name(np->s.device), IRQ_PRM(np->s.irq));
+ "revision id 0x%x\n", np->s.chip_name,
+ pdev->device, pdev->revision);
+ copy_info(&info, "At PCI address %s, IRQ %u\n",
+ pci_name(pdev), pdev->irq);
copy_info(&info, "Min. period factor %d, %s SCSI BUS%s\n",
(int) (np->minsync_dt ? np->minsync_dt : np->minsync),
np->maxwide ? "Wide" : "Narrow",
@@ -1307,15 +1209,14 @@ static int sym_host_info(struct sym_hcb *np, char *ptr, off_t offset, int len)
* - func = 0 means read (returns adapter infos)
* - func = 1 means write (not yet merget from sym53c8xx)
*/
-static int sym53c8xx_proc_info(struct Scsi_Host *host, char *buffer,
+static int sym53c8xx_proc_info(struct Scsi_Host *shost, char *buffer,
char **start, off_t offset, int length, int func)
{
- struct sym_hcb *np = sym_get_hcb(host);
int retv;
if (func) {
#ifdef SYM_LINUX_USER_COMMAND_SUPPORT
- retv = sym_user_command(np, buffer, length);
+ retv = sym_user_command(shost, buffer, length);
#else
retv = -EINVAL;
#endif
@@ -1323,7 +1224,7 @@ static int sym53c8xx_proc_info(struct Scsi_Host *host, char *buffer,
if (start)
*start = buffer;
#ifdef SYM_LINUX_USER_INFO_SUPPORT
- retv = sym_host_info(np, buffer, offset, length);
+ retv = sym_host_info(shost, buffer, offset, length);
#else
retv = -EINVAL;
#endif
@@ -1341,8 +1242,8 @@ static void sym_free_resources(struct sym_hcb *np, struct pci_dev *pdev)
/*
* Free O/S specific resources.
*/
- if (np->s.irq)
- free_irq(np->s.irq, np);
+ if (pdev->irq)
+ free_irq(pdev->irq, np);
if (np->s.ioaddr)
pci_iounmap(pdev, np->s.ioaddr);
if (np->s.ramaddr)
@@ -1356,31 +1257,6 @@ static void sym_free_resources(struct sym_hcb *np, struct pci_dev *pdev)
}
/*
- * Ask/tell the system about DMA addressing.
- */
-static int sym_setup_bus_dma_mask(struct sym_hcb *np)
-{
-#if SYM_CONF_DMA_ADDRESSING_MODE > 0
-#if SYM_CONF_DMA_ADDRESSING_MODE == 1
-#define DMA_DAC_MASK DMA_40BIT_MASK
-#elif SYM_CONF_DMA_ADDRESSING_MODE == 2
-#define DMA_DAC_MASK DMA_64BIT_MASK
-#endif
- if ((np->features & FE_DAC) &&
- !pci_set_dma_mask(np->s.device, DMA_DAC_MASK)) {
- np->use_dac = 1;
- return 0;
- }
-#endif
-
- if (!pci_set_dma_mask(np->s.device, DMA_32BIT_MASK))
- return 0;
-
- printf_warning("%s: No suitable DMA available\n", sym_name(np));
- return -1;
-}
-
-/*
* Host attach and initialisations.
*
* Allocate host data and ncb structure.
@@ -1392,32 +1268,28 @@ static int sym_setup_bus_dma_mask(struct sym_hcb *np)
static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
int unit, struct sym_device *dev)
{
- struct host_data *host_data;
+ struct sym_data *sym_data;
struct sym_hcb *np = NULL;
- struct Scsi_Host *instance = NULL;
+ struct Scsi_Host *shost;
struct pci_dev *pdev = dev->pdev;
unsigned long flags;
struct sym_fw *fw;
- printk(KERN_INFO
- "sym%d: <%s> rev 0x%x at pci %s irq " IRQ_FMT "\n",
- unit, dev->chip.name, dev->chip.revision_id,
- pci_name(pdev), IRQ_PRM(pdev->irq));
+ printk(KERN_INFO "sym%d: <%s> rev 0x%x at pci %s irq %u\n",
+ unit, dev->chip.name, pdev->revision, pci_name(pdev),
+ pdev->irq);
/*
* Get the firmware for this chip.
*/
fw = sym_find_firmware(&dev->chip);
if (!fw)
- goto attach_failed;
+ return NULL;
- /*
- * Allocate host_data structure
- */
- instance = scsi_host_alloc(tpnt, sizeof(*host_data));
- if (!instance)
- goto attach_failed;
- host_data = (struct host_data *) instance->hostdata;
+ shost = scsi_host_alloc(tpnt, sizeof(*sym_data));
+ if (!shost)
+ return NULL;
+ sym_data = shost_priv(shost);
/*
* Allocate immediately the host control block,
@@ -1428,22 +1300,19 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
np = __sym_calloc_dma(&pdev->dev, sizeof(*np), "HCB");
if (!np)
goto attach_failed;
- np->s.device = pdev;
np->bus_dmat = &pdev->dev; /* Result in 1 DMA pool per HBA */
- host_data->ncb = np;
- np->s.host = instance;
+ sym_data->ncb = np;
+ sym_data->pdev = pdev;
+ np->s.host = shost;
- pci_set_drvdata(pdev, np);
+ pci_set_drvdata(pdev, shost);
/*
* Copy some useful infos to the HCB.
*/
np->hcb_ba = vtobus(np);
np->verbose = sym_driver_setup.verbose;
- np->s.device = pdev;
np->s.unit = unit;
- np->device_id = dev->chip.device_id;
- np->revision_id = dev->chip.revision_id;
np->features = dev->chip.features;
np->clock_divn = dev->chip.nr_divisor;
np->maxoffs = dev->chip.offset_max;
@@ -1456,8 +1325,13 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
strlcpy(np->s.chip_name, dev->chip.name, sizeof(np->s.chip_name));
sprintf(np->s.inst_name, "sym%d", np->s.unit);
- if (sym_setup_bus_dma_mask(np))
+ if ((SYM_CONF_DMA_ADDRESSING_MODE > 0) && (np->features & FE_DAC) &&
+ !pci_set_dma_mask(pdev, DMA_DAC_MASK)) {
+ set_dac(np);
+ } else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
+ printf_warning("%s: No suitable DMA available\n", sym_name(np));
goto attach_failed;
+ }
/*
* Try to map the controller chip to
@@ -1466,19 +1340,16 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
np->mmio_ba = (u32)dev->mmio_base;
np->s.ioaddr = dev->s.ioaddr;
np->s.ramaddr = dev->s.ramaddr;
- np->s.io_ws = (np->features & FE_IO256) ? 256 : 128;
/*
* Map on-chip RAM if present and supported.
*/
if (!(np->features & FE_RAM))
dev->ram_base = 0;
- if (dev->ram_base) {
+ if (dev->ram_base)
np->ram_ba = (u32)dev->ram_base;
- np->ram_ws = (np->features & FE_RAM8K) ? 8192 : 4096;
- }
- if (sym_hcb_attach(instance, fw, dev->nvram))
+ if (sym_hcb_attach(shost, fw, dev->nvram))
goto attach_failed;
/*
@@ -1486,25 +1357,25 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
* If we synchonize the C code with SCRIPTS on interrupt,
* we do not want to share the INTR line at all.
*/
- if (request_irq(pdev->irq, sym53c8xx_intr, IRQF_SHARED, NAME53C8XX, np)) {
- printf_err("%s: request irq %d failure\n",
+ if (request_irq(pdev->irq, sym53c8xx_intr, IRQF_SHARED, NAME53C8XX,
+ shost)) {
+ printf_err("%s: request irq %u failure\n",
sym_name(np), pdev->irq);
goto attach_failed;
}
- np->s.irq = pdev->irq;
/*
* After SCSI devices have been opened, we cannot
* reset the bus safely, so we do it here.
*/
- spin_lock_irqsave(instance->host_lock, flags);
+ spin_lock_irqsave(shost->host_lock, flags);
if (sym_reset_scsi_bus(np, 0))
goto reset_failed;
/*
* Start the SCRIPTS.
*/
- sym_start_up (np, 1);
+ sym_start_up(shost, 1);
/*
* Start the timer daemon
@@ -1519,33 +1390,37 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
* Fill Linux host instance structure
* and return success.
*/
- instance->max_channel = 0;
- instance->this_id = np->myaddr;
- instance->max_id = np->maxwide ? 16 : 8;
- instance->max_lun = SYM_CONF_MAX_LUN;
- instance->unique_id = pci_resource_start(pdev, 0);
- instance->cmd_per_lun = SYM_CONF_MAX_TAG;
- instance->can_queue = (SYM_CONF_MAX_START-2);
- instance->sg_tablesize = SYM_CONF_MAX_SG;
- instance->max_cmd_len = 16;
+ shost->max_channel = 0;
+ shost->this_id = np->myaddr;
+ shost->max_id = np->maxwide ? 16 : 8;
+ shost->max_lun = SYM_CONF_MAX_LUN;
+ shost->unique_id = pci_resource_start(pdev, 0);
+ shost->cmd_per_lun = SYM_CONF_MAX_TAG;
+ shost->can_queue = (SYM_CONF_MAX_START-2);
+ shost->sg_tablesize = SYM_CONF_MAX_SG;
+ shost->max_cmd_len = 16;
BUG_ON(sym2_transport_template == NULL);
- instance->transportt = sym2_transport_template;
+ shost->transportt = sym2_transport_template;
+
+ /* 53c896 rev 1 errata: DMA may not cross 16MB boundary */
+ if (pdev->device == PCI_DEVICE_ID_NCR_53C896 && pdev->revision < 2)
+ shost->dma_boundary = 0xFFFFFF;
- spin_unlock_irqrestore(instance->host_lock, flags);
+ spin_unlock_irqrestore(shost->host_lock, flags);
- return instance;
+ return shost;
reset_failed:
printf_err("%s: FATAL ERROR: CHECK SCSI BUS - CABLES, "
"TERMINATION, DEVICE POWER etc.!\n", sym_name(np));
- spin_unlock_irqrestore(instance->host_lock, flags);
+ spin_unlock_irqrestore(shost->host_lock, flags);
attach_failed:
- if (!instance)
+ if (!shost)
return NULL;
printf_info("%s: giving up ...\n", sym_name(np));
if (np)
sym_free_resources(np, pdev);
- scsi_host_put(instance);
+ scsi_host_put(shost);
return NULL;
}
@@ -1558,7 +1433,6 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
static void __devinit sym_get_nvram(struct sym_device *devp, struct sym_nvram *nvp)
{
devp->nvram = nvp;
- devp->device_id = devp->chip.device_id;
nvp->type = 0;
sym_read_nvram(devp, nvp);
@@ -1573,7 +1447,6 @@ static int __devinit sym_check_supported(struct sym_device *device)
{
struct sym_chip *chip;
struct pci_dev *pdev = device->pdev;
- u_char revision;
unsigned long io_port = pci_resource_start(pdev, 0);
int i;
@@ -1593,14 +1466,12 @@ static int __devinit sym_check_supported(struct sym_device *device)
* to our device structure so we can make it match the actual device
* and options.
*/
- pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
- chip = sym_lookup_chip_table(pdev->device, revision);
+ chip = sym_lookup_chip_table(pdev->device, pdev->revision);
if (!chip) {
dev_info(&pdev->dev, "device not supported\n");
return -ENODEV;
}
memcpy(&device->chip, chip, sizeof(device->chip));
- device->chip.revision_id = revision;
return 0;
}
@@ -1641,7 +1512,7 @@ static int __devinit sym_set_workarounds(struct sym_device *device)
* We must ensure the chip will use WRITE AND INVALIDATE.
* The revision number limit is for now arbitrary.
*/
- if (pdev->device == PCI_DEVICE_ID_NCR_53C896 && chip->revision_id < 0x4) {
+ if (pdev->device == PCI_DEVICE_ID_NCR_53C896 && pdev->revision < 0x4) {
chip->features |= (FE_WRIE | FE_CLSE);
}
@@ -1769,8 +1640,9 @@ static void sym_config_pqs(struct pci_dev *pdev, struct sym_device *sym_dev)
* Detach the host.
* We have to free resources and halt the NCR chip.
*/
-static int sym_detach(struct sym_hcb *np, struct pci_dev *pdev)
+static int sym_detach(struct Scsi_Host *shost, struct pci_dev *pdev)
{
+ struct sym_hcb *np = sym_get_hcb(shost);
printk("%s: detaching ...\n", sym_name(np));
del_timer_sync(&np->s.timer);
@@ -1808,6 +1680,7 @@ static struct scsi_host_template sym2_template = {
.eh_host_reset_handler = sym53c8xx_eh_host_reset_handler,
.this_id = 7,
.use_clustering = ENABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
.max_sectors = 0xFFFF,
#ifdef SYM_LINUX_PROC_INFO_SUPPORT
.proc_info = sym53c8xx_proc_info,
@@ -1822,7 +1695,7 @@ static int __devinit sym2_probe(struct pci_dev *pdev,
{
struct sym_device sym_dev;
struct sym_nvram nvram;
- struct Scsi_Host *instance;
+ struct Scsi_Host *shost;
memset(&sym_dev, 0, sizeof(sym_dev));
memset(&nvram, 0, sizeof(nvram));
@@ -1849,13 +1722,13 @@ static int __devinit sym2_probe(struct pci_dev *pdev,
sym_get_nvram(&sym_dev, &nvram);
- instance = sym_attach(&sym2_template, attach_count, &sym_dev);
- if (!instance)
+ shost = sym_attach(&sym2_template, attach_count, &sym_dev);
+ if (!shost)
goto free;
- if (scsi_add_host(instance, &pdev->dev))
+ if (scsi_add_host(shost, &pdev->dev))
goto detach;
- scsi_scan_host(instance);
+ scsi_scan_host(shost);
attach_count++;
@@ -1873,20 +1746,143 @@ static int __devinit sym2_probe(struct pci_dev *pdev,
static void __devexit sym2_remove(struct pci_dev *pdev)
{
- struct sym_hcb *np = pci_get_drvdata(pdev);
- struct Scsi_Host *host = np->s.host;
-
- scsi_remove_host(host);
- scsi_host_put(host);
-
- sym_detach(np, pdev);
+ struct Scsi_Host *shost = pci_get_drvdata(pdev);
+ scsi_remove_host(shost);
+ scsi_host_put(shost);
+ sym_detach(shost, pdev);
pci_release_regions(pdev);
pci_disable_device(pdev);
attach_count--;
}
+/**
+ * sym2_io_error_detected() - called when PCI error is detected
+ * @pdev: pointer to PCI device
+ * @state: current state of the PCI slot
+ */
+static pci_ers_result_t sym2_io_error_detected(struct pci_dev *pdev,
+ enum pci_channel_state state)
+{
+ /* If slot is permanently frozen, turn everything off */
+ if (state == pci_channel_io_perm_failure) {
+ sym2_remove(pdev);
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+
+ disable_irq(pdev->irq);
+ pci_disable_device(pdev);
+
+ /* Request that MMIO be enabled, so register dump can be taken. */
+ return PCI_ERS_RESULT_CAN_RECOVER;
+}
+
+/**
+ * sym2_io_slot_dump - Enable MMIO and dump debug registers
+ * @pdev: pointer to PCI device
+ */
+static pci_ers_result_t sym2_io_slot_dump(struct pci_dev *pdev)
+{
+ struct Scsi_Host *shost = pci_get_drvdata(pdev);
+
+ sym_dump_registers(shost);
+
+ /* Request a slot reset. */
+ return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/**
+ * sym2_reset_workarounds - hardware-specific work-arounds
+ *
+ * This routine is similar to sym_set_workarounds(), except
+ * that, at this point, we already know that the device was
+ * succesfully intialized at least once before, and so most
+ * of the steps taken there are un-needed here.
+ */
+static void sym2_reset_workarounds(struct pci_dev *pdev)
+{
+ u_short status_reg;
+ struct sym_chip *chip;
+
+ chip = sym_lookup_chip_table(pdev->device, pdev->revision);
+
+ /* Work around for errant bit in 895A, in a fashion
+ * similar to what is done in sym_set_workarounds().
+ */
+ pci_read_config_word(pdev, PCI_STATUS, &status_reg);
+ if (!(chip->features & FE_66MHZ) && (status_reg & PCI_STATUS_66MHZ)) {
+ status_reg = PCI_STATUS_66MHZ;
+ pci_write_config_word(pdev, PCI_STATUS, status_reg);
+ pci_read_config_word(pdev, PCI_STATUS, &status_reg);
+ }
+}
+
+/**
+ * sym2_io_slot_reset() - called when the pci bus has been reset.
+ * @pdev: pointer to PCI device
+ *
+ * Restart the card from scratch.
+ */
+static pci_ers_result_t sym2_io_slot_reset(struct pci_dev *pdev)
+{
+ struct Scsi_Host *shost = pci_get_drvdata(pdev);
+ struct sym_hcb *np = sym_get_hcb(shost);
+
+ printk(KERN_INFO "%s: recovering from a PCI slot reset\n",
+ sym_name(np));
+
+ if (pci_enable_device(pdev)) {
+ printk(KERN_ERR "%s: Unable to enable after PCI reset\n",
+ sym_name(np));
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+
+ pci_set_master(pdev);
+ enable_irq(pdev->irq);
+
+ /* If the chip can do Memory Write Invalidate, enable it */
+ if (np->features & FE_WRIE) {
+ if (pci_set_mwi(pdev))
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+
+ /* Perform work-arounds, analogous to sym_set_workarounds() */
+ sym2_reset_workarounds(pdev);
+
+ /* Perform host reset only on one instance of the card */
+ if (PCI_FUNC(pdev->devfn) == 0) {
+ if (sym_reset_scsi_bus(np, 0)) {
+ printk(KERN_ERR "%s: Unable to reset scsi host\n",
+ sym_name(np));
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+ sym_start_up(shost, 1);
+ }
+
+ return PCI_ERS_RESULT_RECOVERED;
+}
+
+/**
+ * sym2_io_resume() - resume normal ops after PCI reset
+ * @pdev: pointer to PCI device
+ *
+ * Called when the error recovery driver tells us that its
+ * OK to resume normal operation. Use completion to allow
+ * halted scsi ops to resume.
+ */
+static void sym2_io_resume(struct pci_dev *pdev)
+{
+ struct Scsi_Host *shost = pci_get_drvdata(pdev);
+ struct sym_data *sym_data = shost_priv(shost);
+
+ spin_lock_irq(shost->host_lock);
+ if (sym_data->io_reset)
+ complete_all(sym_data->io_reset);
+ sym_data->io_reset = NULL;
+ spin_unlock_irq(shost->host_lock);
+}
+
static void sym2_get_signalling(struct Scsi_Host *shost)
{
struct sym_hcb *np = sym_get_hcb(shost);
@@ -2049,11 +2045,19 @@ static struct pci_device_id sym2_id_table[] __devinitdata = {
MODULE_DEVICE_TABLE(pci, sym2_id_table);
+static struct pci_error_handlers sym2_err_handler = {
+ .error_detected = sym2_io_error_detected,
+ .mmio_enabled = sym2_io_slot_dump,
+ .slot_reset = sym2_io_slot_reset,
+ .resume = sym2_io_resume,
+};
+
static struct pci_driver sym2_driver = {
.name = NAME53C8XX,
.id_table = sym2_id_table,
.probe = sym2_probe,
.remove = __devexit_p(sym2_remove),
+ .err_handler = &sym2_err_handler,
};
static int __init sym2_init(void)
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h
index 0f097ba4f712..567fbe0b4f09 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.h
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.h
@@ -40,7 +40,9 @@
#ifndef SYM_GLUE_H
#define SYM_GLUE_H
+#include <linux/completion.h>
#include <linux/delay.h>
+#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/string.h>
@@ -177,14 +179,11 @@ struct sym_shcb {
int unit;
char inst_name[16];
char chip_name[8];
- struct pci_dev *device;
struct Scsi_Host *host;
void __iomem * ioaddr; /* MMIO kernel io address */
void __iomem * ramaddr; /* RAM kernel io address */
- u_short io_ws; /* IO window size */
- int irq; /* IRQ number */
struct timer_list timer; /* Timer handler link header */
u_long lasttime;
@@ -212,20 +211,21 @@ struct sym_device {
} s;
struct sym_chip chip;
struct sym_nvram *nvram;
- u_short device_id;
u_char host_id;
};
/*
* Driver host data structure.
*/
-struct host_data {
+struct sym_data {
struct sym_hcb *ncb;
+ struct completion *io_reset; /* PCI error handling */
+ struct pci_dev *pdev;
};
static inline struct sym_hcb * sym_get_hcb(struct Scsi_Host *host)
{
- return ((struct host_data *)host->hostdata)->ncb;
+ return ((struct sym_data *)host->hostdata)->ncb;
}
#include "sym_fw.h"
@@ -263,8 +263,8 @@ void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid)
void sym_xpt_done(struct sym_hcb *np, struct scsi_cmnd *ccb);
#define sym_print_addr(cmd, arg...) dev_info(&cmd->device->sdev_gendev , ## arg)
void sym_xpt_async_bus_reset(struct sym_hcb *np);
-void sym_xpt_async_sent_bdr(struct sym_hcb *np, int target);
int sym_setup_data_and_start (struct sym_hcb *np, struct scsi_cmnd *csio, struct sym_ccb *cp);
-void sym_log_bus_error(struct sym_hcb *np);
+void sym_log_bus_error(struct Scsi_Host *);
+void sym_dump_registers(struct Scsi_Host *);
#endif /* SYM_GLUE_H */
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
index 21cd4c7f5289..463f119f20e9 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c
@@ -52,7 +52,7 @@
* Needed function prototypes.
*/
static void sym_int_ma (struct sym_hcb *np);
-static void sym_int_sir (struct sym_hcb *np);
+static void sym_int_sir(struct sym_hcb *);
static struct sym_ccb *sym_alloc_ccb(struct sym_hcb *np);
static struct sym_ccb *sym_ccb_from_dsa(struct sym_hcb *np, u32 dsa);
static void sym_alloc_lcb_tags (struct sym_hcb *np, u_char tn, u_char ln);
@@ -684,6 +684,8 @@ static void sym_set_bus_mode(struct sym_hcb *np, struct sym_nvram *nvram)
*/
static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, struct sym_nvram *nvram)
{
+ struct sym_data *sym_data = shost_priv(shost);
+ struct pci_dev *pdev = sym_data->pdev;
u_char burst_max;
u32 period;
int i;
@@ -778,19 +780,12 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru
* 64 bit addressing (895A/896/1010) ?
*/
if (np->features & FE_DAC) {
-#if SYM_CONF_DMA_ADDRESSING_MODE == 0
- np->rv_ccntl1 |= (DDAC);
-#elif SYM_CONF_DMA_ADDRESSING_MODE == 1
- if (!np->use_dac)
- np->rv_ccntl1 |= (DDAC);
- else
- np->rv_ccntl1 |= (XTIMOD | EXTIBMV);
-#elif SYM_CONF_DMA_ADDRESSING_MODE == 2
- if (!np->use_dac)
- np->rv_ccntl1 |= (DDAC);
- else
- np->rv_ccntl1 |= (0 | EXTIBMV);
-#endif
+ if (!use_dac(np))
+ np->rv_ccntl1 |= (DDAC);
+ else if (SYM_CONF_DMA_ADDRESSING_MODE == 1)
+ np->rv_ccntl1 |= (XTIMOD | EXTIBMV);
+ else if (SYM_CONF_DMA_ADDRESSING_MODE == 2)
+ np->rv_ccntl1 |= (0 | EXTIBMV);
}
/*
@@ -804,8 +799,8 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru
* In dual channel mode, contention occurs if internal cycles
* are used. Disable internal cycles.
*/
- if (np->device_id == PCI_DEVICE_ID_LSI_53C1010_33 &&
- np->revision_id < 0x1)
+ if (pdev->device == PCI_DEVICE_ID_LSI_53C1010_33 &&
+ pdev->revision < 0x1)
np->rv_ccntl0 |= DILS;
/*
@@ -828,10 +823,10 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru
* this driver. The generic ncr driver that does not use
* LOAD/STORE instructions does not need this work-around.
*/
- if ((np->device_id == PCI_DEVICE_ID_NCR_53C810 &&
- np->revision_id >= 0x10 && np->revision_id <= 0x11) ||
- (np->device_id == PCI_DEVICE_ID_NCR_53C860 &&
- np->revision_id <= 0x1))
+ if ((pdev->device == PCI_DEVICE_ID_NCR_53C810 &&
+ pdev->revision >= 0x10 && pdev->revision <= 0x11) ||
+ (pdev->device == PCI_DEVICE_ID_NCR_53C860 &&
+ pdev->revision <= 0x1))
np->features &= ~(FE_WRIE|FE_ERL|FE_ERMP);
/*
@@ -897,7 +892,7 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru
if ((SYM_SETUP_SCSI_LED ||
(nvram->type == SYM_SYMBIOS_NVRAM ||
(nvram->type == SYM_TEKRAM_NVRAM &&
- np->device_id == PCI_DEVICE_ID_NCR_53C895))) &&
+ pdev->device == PCI_DEVICE_ID_NCR_53C895))) &&
!(np->features & FE_LEDC) && !(np->sv_gpcntl & 0x01))
np->features |= FE_LED0;
@@ -1135,8 +1130,9 @@ restart_test:
* First 24 register of the chip:
* r0..rf
*/
-static void sym_log_hard_error(struct sym_hcb *np, u_short sist, u_char dstat)
+static void sym_log_hard_error(struct Scsi_Host *shost, u_short sist, u_char dstat)
{
+ struct sym_hcb *np = sym_get_hcb(shost);
u32 dsp;
int script_ofs;
int script_size;
@@ -1180,16 +1176,27 @@ static void sym_log_hard_error(struct sym_hcb *np, u_short sist, u_char dstat)
scr_to_cpu((int) *(u32 *)(script_base + script_ofs)));
}
- printf ("%s: regdump:", sym_name(np));
- for (i=0; i<24;i++)
- printf (" %02x", (unsigned)INB_OFF(np, i));
- printf (".\n");
+ printf("%s: regdump:", sym_name(np));
+ for (i = 0; i < 24; i++)
+ printf(" %02x", (unsigned)INB_OFF(np, i));
+ printf(".\n");
/*
* PCI BUS error.
*/
if (dstat & (MDPE|BF))
- sym_log_bus_error(np);
+ sym_log_bus_error(shost);
+}
+
+void sym_dump_registers(struct Scsi_Host *shost)
+{
+ struct sym_hcb *np = sym_get_hcb(shost);
+ u_short sist;
+ u_char dstat;
+
+ sist = INW(np, nc_sist);
+ dstat = INB(np, nc_dstat);
+ sym_log_hard_error(shost, sist, dstat);
}
static struct sym_chip sym_dev_table[] = {
@@ -1312,7 +1319,7 @@ int sym_lookup_dmap(struct sym_hcb *np, u32 h, int s)
{
int i;
- if (!np->use_dac)
+ if (!use_dac(np))
goto weird;
/* Look up existing mappings */
@@ -1519,7 +1526,8 @@ void sym_put_start_queue(struct sym_hcb *np, struct sym_ccb *cp)
np->squeueput = qidx;
if (DEBUG_FLAGS & DEBUG_QUEUE)
- printf ("%s: queuepos=%d.\n", sym_name (np), np->squeueput);
+ scmd_printk(KERN_DEBUG, cp->cmd, "queuepos=%d\n",
+ np->squeueput);
/*
* Script processor may be waiting for reselect.
@@ -1696,8 +1704,11 @@ static void sym_flush_busy_queue (struct sym_hcb *np, int cam_status)
* 1: SCSI BUS RESET delivered or received.
* 2: SCSI BUS MODE changed.
*/
-void sym_start_up (struct sym_hcb *np, int reason)
+void sym_start_up(struct Scsi_Host *shost, int reason)
{
+ struct sym_data *sym_data = shost_priv(shost);
+ struct pci_dev *pdev = sym_data->pdev;
+ struct sym_hcb *np = sym_data->ncb;
int i;
u32 phys;
@@ -1746,7 +1757,7 @@ void sym_start_up (struct sym_hcb *np, int reason)
* This also let point to first position the start
* and done queue pointers used from SCRIPTS.
*/
- np->fw_patch(np);
+ np->fw_patch(shost);
/*
* Wakeup all pending jobs.
@@ -1788,7 +1799,7 @@ void sym_start_up (struct sym_hcb *np, int reason)
/*
* For now, disable AIP generation on C1010-66.
*/
- if (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)
+ if (pdev->device == PCI_DEVICE_ID_LSI_53C1010_66)
OUTB(np, nc_aipcntl1, DISAIP);
/*
@@ -1798,8 +1809,8 @@ void sym_start_up (struct sym_hcb *np, int reason)
* that from SCRIPTS for each selection/reselection, but
* I just don't want. :)
*/
- if (np->device_id == PCI_DEVICE_ID_LSI_53C1010_33 &&
- np->revision_id < 1)
+ if (pdev->device == PCI_DEVICE_ID_LSI_53C1010_33 &&
+ pdev->revision < 1)
OUTB(np, nc_stest1, INB(np, nc_stest1) | 0x30);
/*
@@ -1807,9 +1818,9 @@ void sym_start_up (struct sym_hcb *np, int reason)
* Disable overlapped arbitration for some dual function devices,
* regardless revision id (kind of post-chip-design feature. ;-))
*/
- if (np->device_id == PCI_DEVICE_ID_NCR_53C875)
+ if (pdev->device == PCI_DEVICE_ID_NCR_53C875)
OUTB(np, nc_ctest0, (1<<5));
- else if (np->device_id == PCI_DEVICE_ID_NCR_53C896)
+ else if (pdev->device == PCI_DEVICE_ID_NCR_53C896)
np->rv_ccntl0 |= DPR;
/*
@@ -1827,7 +1838,7 @@ void sym_start_up (struct sym_hcb *np, int reason)
* Set up scratch C and DRS IO registers to map the 32 bit
* DMA address range our data structures are located in.
*/
- if (np->use_dac) {
+ if (use_dac(np)) {
np->dmap_bah[0] = 0; /* ??? */
OUTL(np, nc_scrx[0], np->dmap_bah[0]);
OUTL(np, nc_drs, np->dmap_bah[0]);
@@ -1900,7 +1911,7 @@ void sym_start_up (struct sym_hcb *np, int reason)
if (sym_verbose >= 2)
printf("%s: Downloading SCSI SCRIPTS.\n", sym_name(np));
memcpy_toio(np->s.ramaddr, np->scripta0, np->scripta_sz);
- if (np->ram_ws == 8192) {
+ if (np->features & FE_RAM8K) {
memcpy_toio(np->s.ramaddr + 4096, np->scriptb0, np->scriptb_sz);
phys = scr_to_cpu(np->scr_ram_seg);
OUTL(np, nc_mmws, phys);
@@ -2214,8 +2225,9 @@ static void sym_int_udc (struct sym_hcb *np)
* mode to eight bit asynchronous, etc...
* So, just reinitializing all except chip should be enough.
*/
-static void sym_int_sbmc (struct sym_hcb *np)
+static void sym_int_sbmc(struct Scsi_Host *shost)
{
+ struct sym_hcb *np = sym_get_hcb(shost);
u_char scsi_mode = INB(np, nc_stest4) & SMODE;
/*
@@ -2228,7 +2240,7 @@ static void sym_int_sbmc (struct sym_hcb *np)
* Should suspend command processing for a few seconds and
* reinitialize all except the chip.
*/
- sym_start_up (np, 2);
+ sym_start_up(shost, 2);
}
/*
@@ -2756,8 +2768,11 @@ reset_all:
* Use at your own decision and risk.
*/
-void sym_interrupt (struct sym_hcb *np)
+irqreturn_t sym_interrupt(struct Scsi_Host *shost)
{
+ struct sym_data *sym_data = shost_priv(shost);
+ struct sym_hcb *np = sym_data->ncb;
+ struct pci_dev *pdev = sym_data->pdev;
u_char istat, istatc;
u_char dstat;
u_short sist;
@@ -2782,7 +2797,7 @@ void sym_interrupt (struct sym_hcb *np)
}
if (!(istat & (SIP|DIP)))
- return;
+ return (istat & INTF) ? IRQ_HANDLED : IRQ_NONE;
#if 0 /* We should never get this one */
if (istat & CABRT)
@@ -2809,6 +2824,13 @@ void sym_interrupt (struct sym_hcb *np)
dstat |= INB(np, nc_dstat);
istatc = INB(np, nc_istat);
istat |= istatc;
+
+ /* Prevent deadlock waiting on a condition that may
+ * never clear. */
+ if (unlikely(sist == 0xffff && dstat == 0xff)) {
+ if (pci_channel_offline(pdev))
+ return IRQ_NONE;
+ }
} while (istatc & (SIP|DIP));
if (DEBUG_FLAGS & DEBUG_TINY)
@@ -2842,10 +2864,10 @@ void sym_interrupt (struct sym_hcb *np)
!(dstat & (MDPE|BF|ABRT|IID))) {
if (sist & PAR) sym_int_par (np, sist);
else if (sist & MA) sym_int_ma (np);
- else if (dstat & SIR) sym_int_sir (np);
+ else if (dstat & SIR) sym_int_sir(np);
else if (dstat & SSI) OUTONB_STD();
else goto unknown_int;
- return;
+ return IRQ_HANDLED;
}
/*
@@ -2861,8 +2883,8 @@ void sym_interrupt (struct sym_hcb *np)
*/
if (sist & RST) {
printf("%s: SCSI BUS reset detected.\n", sym_name(np));
- sym_start_up (np, 1);
- return;
+ sym_start_up(shost, 1);
+ return IRQ_HANDLED;
}
OUTB(np, nc_ctest3, np->rv_ctest3 | CLF); /* clear dma fifo */
@@ -2870,11 +2892,11 @@ void sym_interrupt (struct sym_hcb *np)
if (!(sist & (GEN|HTH|SGE)) &&
!(dstat & (MDPE|BF|ABRT|IID))) {
- if (sist & SBMC) sym_int_sbmc (np);
+ if (sist & SBMC) sym_int_sbmc(shost);
else if (sist & STO) sym_int_sto (np);
else if (sist & UDC) sym_int_udc (np);
else goto unknown_int;
- return;
+ return IRQ_HANDLED;
}
/*
@@ -2884,12 +2906,12 @@ void sym_interrupt (struct sym_hcb *np)
* Reset everything.
*/
- sym_log_hard_error(np, sist, dstat);
+ sym_log_hard_error(shost, sist, dstat);
if ((sist & (GEN|HTH|SGE)) ||
(dstat & (MDPE|BF|ABRT|IID))) {
sym_start_reset(np);
- return;
+ return IRQ_HANDLED;
}
unknown_int:
@@ -2900,6 +2922,7 @@ unknown_int:
printf( "%s: unknown interrupt(s) ignored, "
"ISTAT=0x%x DSTAT=0x%x SIST=0x%x\n",
sym_name(np), istat, dstat, sist);
+ return IRQ_NONE;
}
/*
@@ -3520,7 +3543,8 @@ static void sym_sir_task_recovery(struct sym_hcb *np, int num)
* If we sent a BDR, make upper layer aware of that.
*/
if (np->abrt_msg[0] == M_RESET)
- sym_xpt_async_sent_bdr(np, target);
+ starget_printk(KERN_NOTICE, starget,
+ "has been reset\n");
break;
}
@@ -4304,7 +4328,7 @@ static void sym_nego_rejected(struct sym_hcb *np, struct sym_tcb *tp, struct sym
/*
* chip exception handler for programmed interrupts.
*/
-static void sym_int_sir (struct sym_hcb *np)
+static void sym_int_sir(struct sym_hcb *np)
{
u_char num = INB(np, nc_dsps);
u32 dsa = INL(np, nc_dsa);
@@ -4343,31 +4367,30 @@ static void sym_int_sir (struct sym_hcb *np)
return;
/*
* The device didn't go to MSG OUT phase after having
- * been selected with ATN. We donnot want to handle
- * that.
+ * been selected with ATN. We do not want to handle that.
*/
case SIR_SEL_ATN_NO_MSG_OUT:
- printf ("%s:%d: No MSG OUT phase after selection with ATN.\n",
- sym_name (np), target);
+ scmd_printk(KERN_WARNING, cp->cmd,
+ "No MSG OUT phase after selection with ATN\n");
goto out_stuck;
/*
* The device didn't switch to MSG IN phase after
- * having reseleted the initiator.
+ * having reselected the initiator.
*/
case SIR_RESEL_NO_MSG_IN:
- printf ("%s:%d: No MSG IN phase after reselection.\n",
- sym_name (np), target);
+ scmd_printk(KERN_WARNING, cp->cmd,
+ "No MSG IN phase after reselection\n");
goto out_stuck;
/*
* After reselection, the device sent a message that wasn't
* an IDENTIFY.
*/
case SIR_RESEL_NO_IDENTIFY:
- printf ("%s:%d: No IDENTIFY after reselection.\n",
- sym_name (np), target);
+ scmd_printk(KERN_WARNING, cp->cmd,
+ "No IDENTIFY after reselection\n");
goto out_stuck;
/*
- * The device reselected a LUN we donnot know about.
+ * The device reselected a LUN we do not know about.
*/
case SIR_RESEL_BAD_LUN:
np->msgout[0] = M_RESET;
@@ -4380,8 +4403,7 @@ static void sym_int_sir (struct sym_hcb *np)
np->msgout[0] = M_ABORT;
goto out;
/*
- * The device reselected for a tagged nexus that we donnot
- * have.
+ * The device reselected for a tagged nexus that we do not have.
*/
case SIR_RESEL_BAD_I_T_L_Q:
np->msgout[0] = M_ABORT_TAG;
@@ -4393,8 +4415,8 @@ static void sym_int_sir (struct sym_hcb *np)
case SIR_RESEL_ABORTED:
np->lastmsg = np->msgout[0];
np->msgout[0] = M_NOOP;
- printf ("%s:%d: message %x sent on bad reselection.\n",
- sym_name (np), target, np->lastmsg);
+ scmd_printk(KERN_WARNING, cp->cmd,
+ "message %x sent on bad reselection\n", np->lastmsg);
goto out;
/*
* The SCRIPTS let us know that a message has been
@@ -5578,16 +5600,13 @@ int sym_hcb_attach(struct Scsi_Host *shost, struct sym_fw *fw, struct sym_nvram
np->scriptz_ba = vtobus(np->scriptz0);
if (np->ram_ba) {
- np->scripta_ba = np->ram_ba;
+ np->scripta_ba = np->ram_ba;
if (np->features & FE_RAM8K) {
- np->ram_ws = 8192;
np->scriptb_ba = np->scripta_ba + 4096;
#if 0 /* May get useful for 64 BIT PCI addressing */
np->scr_ram_seg = cpu_to_scr(np->scripta_ba >> 32);
#endif
}
- else
- np->ram_ws = 4096;
}
/*
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h
index 79ab6a177039..ad078805e62b 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.h
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h
@@ -883,10 +883,7 @@ struct sym_hcb {
* Physical bus addresses of the chip.
*/
u32 mmio_ba; /* MMIO 32 bit BUS address */
- int mmio_ws; /* MMIO Window size */
-
u32 ram_ba; /* RAM 32 bit BUS address */
- int ram_ws; /* RAM window size */
/*
* SCRIPTS virtual and physical bus addresses.
@@ -912,14 +909,12 @@ struct sym_hcb {
struct sym_fwb_ba fwb_bas; /* Useful SCRIPTB bus addresses */
struct sym_fwz_ba fwz_bas; /* Useful SCRIPTZ bus addresses */
void (*fw_setup)(struct sym_hcb *np, struct sym_fw *fw);
- void (*fw_patch)(struct sym_hcb *np);
+ void (*fw_patch)(struct Scsi_Host *);
char *fw_name;
/*
* General controller parameters and configuration.
*/
- u_short device_id; /* PCI device id */
- u_char revision_id; /* PCI device revision id */
u_int features; /* Chip features map */
u_char myaddr; /* SCSI id of the adapter */
u_char maxburst; /* log base 2 of dwords burst */
@@ -1031,6 +1026,14 @@ struct sym_hcb {
#endif
};
+#if SYM_CONF_DMA_ADDRESSING_MODE == 0
+#define use_dac(np) 0
+#define set_dac(np) do { } while (0)
+#else
+#define use_dac(np) (np)->use_dac
+#define set_dac(np) (np)->use_dac = 1
+#endif
+
#define HCB_BA(np, lbl) (np->hcb_ba + offsetof(struct sym_hcb, lbl))
@@ -1052,8 +1055,8 @@ void sym_start_next_ccbs(struct sym_hcb *np, struct sym_lcb *lp, int maxn);
#else
void sym_put_start_queue(struct sym_hcb *np, struct sym_ccb *cp);
#endif
-void sym_start_up(struct sym_hcb *np, int reason);
-void sym_interrupt(struct sym_hcb *np);
+void sym_start_up(struct Scsi_Host *, int reason);
+irqreturn_t sym_interrupt(struct Scsi_Host *);
int sym_clear_tasks(struct sym_hcb *np, int cam_status, int target, int lun, int task);
struct sym_ccb *sym_get_ccb(struct sym_hcb *np, struct scsi_cmnd *cmd, u_char tag_order);
void sym_free_ccb(struct sym_hcb *np, struct sym_ccb *cp);
@@ -1073,18 +1076,21 @@ int sym_hcb_attach(struct Scsi_Host *shost, struct sym_fw *fw, struct sym_nvram
*/
#if SYM_CONF_DMA_ADDRESSING_MODE == 0
+#define DMA_DAC_MASK DMA_32BIT_MASK
#define sym_build_sge(np, data, badd, len) \
do { \
(data)->addr = cpu_to_scr(badd); \
(data)->size = cpu_to_scr(len); \
} while (0)
#elif SYM_CONF_DMA_ADDRESSING_MODE == 1
+#define DMA_DAC_MASK DMA_40BIT_MASK
#define sym_build_sge(np, data, badd, len) \
do { \
(data)->addr = cpu_to_scr(badd); \
(data)->size = cpu_to_scr((((badd) >> 8) & 0xff000000) + len); \
} while (0)
#elif SYM_CONF_DMA_ADDRESSING_MODE == 2
+#define DMA_DAC_MASK DMA_64BIT_MASK
int sym_lookup_dmap(struct sym_hcb *np, u32 h, int s);
static __inline void
sym_build_sge(struct sym_hcb *np, struct sym_tblmove *data, u64 badd, int len)
diff --git a/drivers/scsi/sym53c8xx_2/sym_nvram.c b/drivers/scsi/sym53c8xx_2/sym_nvram.c
index 15d69298ab6e..5662fbb3ff60 100644
--- a/drivers/scsi/sym53c8xx_2/sym_nvram.c
+++ b/drivers/scsi/sym53c8xx_2/sym_nvram.c
@@ -696,7 +696,7 @@ static int sym_read_Tekram_nvram (struct sym_device *np, Tekram_nvram *nvram)
u_short csum;
int x;
- switch (np->device_id) {
+ switch (np->pdev->device) {
case PCI_DEVICE_ID_NCR_53C885:
case PCI_DEVICE_ID_NCR_53C895:
case PCI_DEVICE_ID_NCR_53C896:
diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c
index 5c72ca31a47a..44193049c4ae 100644
--- a/drivers/scsi/tmscsim.c
+++ b/drivers/scsi/tmscsim.c
@@ -430,10 +430,7 @@ static __inline__ void dc390_Going_remove (struct dc390_dcb* pDCB, struct dc390_
static struct scatterlist* dc390_sg_build_single(struct scatterlist *sg, void *addr, unsigned int length)
{
- memset(sg, 0, sizeof(struct scatterlist));
- sg->page = virt_to_page(addr);
- sg->length = length;
- sg->offset = (unsigned long)addr & ~PAGE_MASK;
+ sg_init_one(sg, addr, length);
return sg;
}
diff --git a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c
index fc9f51818e8f..7edd6ceb13b2 100644
--- a/drivers/scsi/u14-34f.c
+++ b/drivers/scsi/u14-34f.c
@@ -450,7 +450,8 @@ static struct scsi_host_template driver_template = {
.slave_configure = u14_34f_slave_configure,
.this_id = 7,
.unchecked_isa_dma = 1,
- .use_clustering = ENABLE_CLUSTERING
+ .use_clustering = ENABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
};
#if !defined(__BIG_ENDIAN_BITFIELD) && !defined(__LITTLE_ENDIAN_BITFIELD)
diff --git a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c
index c08235d5afc9..6d1f0edd7985 100644
--- a/drivers/scsi/ultrastor.c
+++ b/drivers/scsi/ultrastor.c
@@ -681,7 +681,7 @@ static inline void build_sg_list(struct mscp *mscp, struct scsi_cmnd *SCpnt)
max = scsi_sg_count(SCpnt);
scsi_for_each_sg(SCpnt, sg, max, i) {
- mscp->sglist[i].address = isa_page_to_bus(sg->page) + sg->offset;
+ mscp->sglist[i].address = isa_page_to_bus(sg_page(sg)) + sg->offset;
mscp->sglist[i].num_bytes = sg->length;
transfer_length += sg->length;
}
@@ -1197,5 +1197,6 @@ static struct scsi_host_template driver_template = {
.cmd_per_lun = ULTRASTOR_MAX_CMDS_PER_LUN,
.unchecked_isa_dma = 1,
.use_clustering = ENABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
};
#include "scsi_module.c"
diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c
index 0e8e642fd3b0..fdbb92d1f722 100644
--- a/drivers/scsi/wd33c93.c
+++ b/drivers/scsi/wd33c93.c
@@ -410,8 +410,7 @@ wd33c93_queuecommand(struct scsi_cmnd *cmd,
if (cmd->use_sg) {
cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer;
cmd->SCp.buffers_residual = cmd->use_sg - 1;
- cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) +
- cmd->SCp.buffer->offset;
+ cmd->SCp.ptr = sg_virt(cmd->SCp.buffer);
cmd->SCp.this_residual = cmd->SCp.buffer->length;
} else {
cmd->SCp.buffer = NULL;
@@ -745,8 +744,7 @@ transfer_bytes(const wd33c93_regs regs, struct scsi_cmnd *cmd,
++cmd->SCp.buffer;
--cmd->SCp.buffers_residual;
cmd->SCp.this_residual = cmd->SCp.buffer->length;
- cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) +
- cmd->SCp.buffer->offset;
+ cmd->SCp.ptr = sg_virt(cmd->SCp.buffer);
}
if (!cmd->SCp.this_residual) /* avoid bogus setups */
return;
diff --git a/drivers/scsi/wd33c93.h b/drivers/scsi/wd33c93.h
index 61ffb860dacc..00123f2383d7 100644
--- a/drivers/scsi/wd33c93.h
+++ b/drivers/scsi/wd33c93.h
@@ -155,7 +155,7 @@
#define WD33C93_FS_12_15 OWNID_FS_12
#define WD33C93_FS_16_20 OWNID_FS_16
- /* pass input-clock explicitely. accepted mhz values are 8-10,12-20 */
+ /* pass input-clock explicitly. accepted mhz values are 8-10,12-20 */
#define WD33C93_FS_MHZ(mhz) (mhz)
/* Control register */
diff --git a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c
index d6fd4259c56b..03cd44f231df 100644
--- a/drivers/scsi/wd7000.c
+++ b/drivers/scsi/wd7000.c
@@ -1123,7 +1123,7 @@ static int wd7000_queuecommand(struct scsi_cmnd *SCpnt,
any2scsi(scb->maxlen, nseg * sizeof(Sgb));
scsi_for_each_sg(SCpnt, sg, nseg, i) {
- any2scsi(sgb[i].ptr, isa_page_to_bus(sg->page) + sg->offset);
+ any2scsi(sgb[i].ptr, isa_page_to_bus(sg_page(sg)) + sg->offset);
any2scsi(sgb[i].len, sg->length);
}
} else {
@@ -1671,6 +1671,7 @@ static struct scsi_host_template driver_template = {
.cmd_per_lun = 1,
.unchecked_isa_dma = 1,
.use_clustering = ENABLE_CLUSTERING,
+ .use_sg_chaining = ENABLE_SG_CHAINING,
};
#include "scsi_module.c"
diff --git a/drivers/serial/8250_early.c b/drivers/serial/8250_early.c
index 4d4c9f01be8d..1f16de719962 100644
--- a/drivers/serial/8250_early.c
+++ b/drivers/serial/8250_early.c
@@ -76,7 +76,7 @@ static void __init wait_for_xmitr(struct uart_port *port)
}
}
-static void __init putc(struct uart_port *port, int c)
+static void __init serial_putc(struct uart_port *port, int c)
{
wait_for_xmitr(port);
serial_out(port, UART_TX, c);
@@ -91,7 +91,7 @@ static void __init early_serial8250_write(struct console *console, const char *s
ier = serial_in(port, UART_IER);
serial_out(port, UART_IER, 0);
- uart_console_write(port, s, count, putc);
+ uart_console_write(port, s, count, serial_putc);
/* Wait for transmitter to become empty and restore the IER */
wait_for_xmitr(port);
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index 1ea1ed82c352..ceb03c9e749f 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -1036,6 +1036,7 @@ enum pci_board_num_t {
pbn_b0_2_115200,
pbn_b0_4_115200,
pbn_b0_5_115200,
+ pbn_b0_8_115200,
pbn_b0_1_921600,
pbn_b0_2_921600,
@@ -1172,6 +1173,12 @@ static struct pciserial_board pci_boards[] __devinitdata = {
.base_baud = 115200,
.uart_offset = 8,
},
+ [pbn_b0_8_115200] = {
+ .flags = FL_BASE0,
+ .num_ports = 8,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
[pbn_b0_1_921600] = {
.flags = FL_BASE0,
@@ -1979,6 +1986,7 @@ static int pciserial_suspend_one(struct pci_dev *dev, pm_message_t state)
static int pciserial_resume_one(struct pci_dev *dev)
{
+ int err;
struct serial_private *priv = pci_get_drvdata(dev);
pci_set_power_state(dev, PCI_D0);
@@ -1988,7 +1996,9 @@ static int pciserial_resume_one(struct pci_dev *dev)
/*
* The device may have been disabled. Re-enable it.
*/
- pci_enable_device(dev);
+ err = pci_enable_device(dev);
+ if (err)
+ return err;
pciserial_resume_ports(priv);
}
@@ -2566,6 +2576,119 @@ static struct pci_device_id serial_pci_tbl[] = {
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030,
PCI_SUBVENDOR_ID_PERLE, PCI_SUBDEVICE_ID_PCI_RAS8,
0, 0, pbn_b2_8_921600 },
+
+ /*
+ * Mainpine series cards: Fairly standard layout but fools
+ * parts of the autodetect in some cases and uses otherwise
+ * unmatched communications subclasses in the PCI Express case
+ */
+
+ { /* RockForceDUO */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x0200,
+ 0, 0, pbn_b0_2_115200 },
+ { /* RockForceQUATRO */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x0300,
+ 0, 0, pbn_b0_4_115200 },
+ { /* RockForceDUO+ */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x0400,
+ 0, 0, pbn_b0_2_115200 },
+ { /* RockForceQUATRO+ */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x0500,
+ 0, 0, pbn_b0_4_115200 },
+ { /* RockForce+ */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x0600,
+ 0, 0, pbn_b0_2_115200 },
+ { /* RockForce+ */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x0700,
+ 0, 0, pbn_b0_4_115200 },
+ { /* RockForceOCTO+ */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x0800,
+ 0, 0, pbn_b0_8_115200 },
+ { /* RockForceDUO+ */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x0C00,
+ 0, 0, pbn_b0_2_115200 },
+ { /* RockForceQUARTRO+ */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x0D00,
+ 0, 0, pbn_b0_4_115200 },
+ { /* RockForceOCTO+ */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x1D00,
+ 0, 0, pbn_b0_8_115200 },
+ { /* RockForceD1 */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x2000,
+ 0, 0, pbn_b0_1_115200 },
+ { /* RockForceF1 */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x2100,
+ 0, 0, pbn_b0_1_115200 },
+ { /* RockForceD2 */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x2200,
+ 0, 0, pbn_b0_2_115200 },
+ { /* RockForceF2 */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x2300,
+ 0, 0, pbn_b0_2_115200 },
+ { /* RockForceD4 */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x2400,
+ 0, 0, pbn_b0_4_115200 },
+ { /* RockForceF4 */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x2500,
+ 0, 0, pbn_b0_4_115200 },
+ { /* RockForceD8 */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x2600,
+ 0, 0, pbn_b0_8_115200 },
+ { /* RockForceF8 */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x2700,
+ 0, 0, pbn_b0_8_115200 },
+ { /* IQ Express D1 */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x3000,
+ 0, 0, pbn_b0_1_115200 },
+ { /* IQ Express F1 */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x3100,
+ 0, 0, pbn_b0_1_115200 },
+ { /* IQ Express D2 */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x3200,
+ 0, 0, pbn_b0_2_115200 },
+ { /* IQ Express F2 */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x3300,
+ 0, 0, pbn_b0_2_115200 },
+ { /* IQ Express D4 */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x3400,
+ 0, 0, pbn_b0_4_115200 },
+ { /* IQ Express F4 */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x3500,
+ 0, 0, pbn_b0_4_115200 },
+ { /* IQ Express D8 */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x3C00,
+ 0, 0, pbn_b0_8_115200 },
+ { /* IQ Express F8 */
+ PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE,
+ PCI_VENDOR_ID_MAINPINE, 0x3D00,
+ 0, 0, pbn_b0_8_115200 },
+
+
/*
* PA Semi PA6T-1682M on-chip UART
*/
diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c
index 301c8c0be9d7..1de098e75497 100644
--- a/drivers/serial/8250_pnp.c
+++ b/drivers/serial/8250_pnp.c
@@ -69,6 +69,8 @@ static const struct pnp_device_id pnp_dev_table[] = {
{ "CTL3001", 0 },
/* Creative Labs Modem Blaster 28.8 DSVD PnP Voice */
{ "CTL3011", 0 },
+ /* Davicom ISA 33.6K Modem */
+ { "DAV0336", 0 },
/* Creative */
/* Creative Modem Blaster Flash56 DI5601-1 */
{ "DMB1032", 0 },
@@ -327,6 +329,8 @@ static const struct pnp_device_id pnp_dev_table[] = {
{ "WACF004", 0 },
{ "WACF005", 0 },
{ "WACF006", 0 },
+ { "WACF007", 0 },
+ { "WACF008", 0 },
/* Compaq touchscreen */
{ "FPI2002", 0 },
/* Fujitsu Stylistic touchscreens */
@@ -343,6 +347,11 @@ static const struct pnp_device_id pnp_dev_table[] = {
/* Fujitsu Wacom Tablet PC devices */
{ "FUJ02E5", 0 },
{ "FUJ02E6", 0 },
+ /*
+ * LG C1 EXPRESS DUAL (C1-PB11A3) touch screen (actually a FUJ02E6 in
+ * disguise)
+ */
+ { "LTS0001", 0 },
/* Rockwell's (PORALiNK) 33600 INT PNP */
{ "WCI0003", 0 },
/* Unkown PnP modems */
@@ -430,7 +439,8 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
}
memset(&port, 0, sizeof(struct uart_port));
- port.irq = pnp_irq(dev, 0);
+ if (pnp_irq_valid(dev, 0))
+ port.irq = pnp_irq(dev, 0);
if (pnp_port_valid(dev, 0)) {
port.iobase = pnp_port_start(dev, 0);
port.iotype = UPIO_PORT;
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index d6ae38e55d01..ed438bc7e98d 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -62,11 +62,11 @@ config SERIAL_8250_CONSOLE
kernel will automatically use the first serial line, /dev/ttyS0, as
system console.
- you can set that using a kernel command line option such as
+ You can set that using a kernel command line option such as
"console=uart8250,io,0x3f8,9600n8"
"console=uart8250,mmio,0xff5e0000,115200n8".
- and it will switch to normal serial console when correponding port is
- ready.
+ and it will switch to normal serial console when the corresponding
+ port is ready.
"earlycon=uart8250,io,0x3f8,9600n8"
"earlycon=uart8250,mmio,0xff5e0000,115200n8".
it will not only setup early console.
@@ -624,7 +624,7 @@ choice
config SERIAL_BFIN_DMA
bool "DMA mode"
- depends on DMA_UNCACHED_1M && !KGDB_UART
+ depends on !DMA_UNCACHED_NONE && !KGDB_UART
help
This driver works under DMA mode. If this option is selected, the
blackfin simple dma driver is also enabled.
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
index 72229df9dc11..40604a092921 100644
--- a/drivers/serial/amba-pl011.c
+++ b/drivers/serial/amba-pl011.c
@@ -263,15 +263,15 @@ static unsigned int pl01x_get_mctrl(struct uart_port *port)
unsigned int result = 0;
unsigned int status = readw(uap->port.membase + UART01x_FR);
-#define BIT(uartbit, tiocmbit) \
+#define TIOCMBIT(uartbit, tiocmbit) \
if (status & uartbit) \
result |= tiocmbit
- BIT(UART01x_FR_DCD, TIOCM_CAR);
- BIT(UART01x_FR_DSR, TIOCM_DSR);
- BIT(UART01x_FR_CTS, TIOCM_CTS);
- BIT(UART011_FR_RI, TIOCM_RNG);
-#undef BIT
+ TIOCMBIT(UART01x_FR_DCD, TIOCM_CAR);
+ TIOCMBIT(UART01x_FR_DSR, TIOCM_DSR);
+ TIOCMBIT(UART01x_FR_CTS, TIOCM_CTS);
+ TIOCMBIT(UART011_FR_RI, TIOCM_RNG);
+#undef TIOCMBIT
return result;
}
@@ -282,18 +282,18 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl)
cr = readw(uap->port.membase + UART011_CR);
-#define BIT(tiocmbit, uartbit) \
+#define TIOCMBIT(tiocmbit, uartbit) \
if (mctrl & tiocmbit) \
cr |= uartbit; \
else \
cr &= ~uartbit
- BIT(TIOCM_RTS, UART011_CR_RTS);
- BIT(TIOCM_DTR, UART011_CR_DTR);
- BIT(TIOCM_OUT1, UART011_CR_OUT1);
- BIT(TIOCM_OUT2, UART011_CR_OUT2);
- BIT(TIOCM_LOOP, UART011_CR_LBE);
-#undef BIT
+ TIOCMBIT(TIOCM_RTS, UART011_CR_RTS);
+ TIOCMBIT(TIOCM_DTR, UART011_CR_DTR);
+ TIOCMBIT(TIOCM_OUT1, UART011_CR_OUT1);
+ TIOCMBIT(TIOCM_OUT2, UART011_CR_OUT2);
+ TIOCMBIT(TIOCM_LOOP, UART011_CR_LBE);
+#undef TIOCMBIT
writew(cr, uap->port.membase + UART011_CR);
}
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
index 4d6b3c56d20e..111da57f5334 100644
--- a/drivers/serial/atmel_serial.c
+++ b/drivers/serial/atmel_serial.c
@@ -204,8 +204,6 @@ static u_int atmel_get_mctrl(struct uart_port *port)
*/
static void atmel_stop_tx(struct uart_port *port)
{
- struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
-
UART_PUT_IDR(port, ATMEL_US_TXRDY);
}
@@ -214,8 +212,6 @@ static void atmel_stop_tx(struct uart_port *port)
*/
static void atmel_start_tx(struct uart_port *port)
{
- struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
-
UART_PUT_IER(port, ATMEL_US_TXRDY);
}
@@ -224,8 +220,6 @@ static void atmel_start_tx(struct uart_port *port)
*/
static void atmel_stop_rx(struct uart_port *port)
{
- struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
-
UART_PUT_IDR(port, ATMEL_US_RXRDY);
}
@@ -409,7 +403,6 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id)
*/
static int atmel_startup(struct uart_port *port)
{
- struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
int retval;
/*
@@ -456,8 +449,6 @@ static int atmel_startup(struct uart_port *port)
*/
static void atmel_shutdown(struct uart_port *port)
{
- struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
-
/*
* Disable all interrupts, port and break condition.
*/
diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c
index 312bef6bd583..a4e23cf47906 100644
--- a/drivers/serial/crisv10.c
+++ b/drivers/serial/crisv10.c
@@ -1,426 +1,10 @@
-/* $Id: serial.c,v 1.25 2004/09/29 10:33:49 starvik Exp $
- *
+/*
* Serial port driver for the ETRAX 100LX chip
*
- * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Axis Communications AB
+ * Copyright (C) 1998-2007 Axis Communications AB
*
* Many, many authors. Based once upon a time on serial.c for 16x50.
*
- * $Log: serial.c,v $
- * Revision 1.25 2004/09/29 10:33:49 starvik
- * Resolved a dealock when printing debug from kernel.
- *
- * Revision 1.24 2004/08/27 23:25:59 johana
- * rs_set_termios() must call change_speed() if c_iflag has changed or
- * automatic XOFF handling will be enabled and transmitter will stop
- * if 0x13 is received.
- *
- * Revision 1.23 2004/08/24 06:57:13 starvik
- * More whitespace cleanup
- *
- * Revision 1.22 2004/08/24 06:12:20 starvik
- * Whitespace cleanup
- *
- * Revision 1.20 2004/05/24 12:00:20 starvik
- * Big merge of stuff from Linux 2.4 (e.g. manual mode for the serial port).
- *
- * Revision 1.19 2004/05/17 13:12:15 starvik
- * Kernel console hook
- * Big merge from Linux 2.4 still pending.
- *
- * Revision 1.18 2003/10/28 07:18:30 starvik
- * Compiles with debug info
- *
- * Revision 1.17 2003/07/04 08:27:37 starvik
- * Merge of Linux 2.5.74
- *
- * Revision 1.16 2003/06/13 10:05:19 johana
- * Help the user to avoid trouble by:
- * Forcing mixed mode for status/control lines if not all pins are used.
- *
- * Revision 1.15 2003/06/13 09:43:01 johana
- * Merged in the following changes from os/linux/arch/cris/drivers/serial.c
- * + some minor changes to reduce diff.
- *
- * Revision 1.49 2003/05/30 11:31:54 johana
- * Merged in change-branch--serial9bit that adds CMSPAR support for sticky
- * parity (mark/space)
- *
- * Revision 1.48 2003/05/30 11:03:57 johana
- * Implemented rs_send_xchar() by disabling the DMA and writing manually.
- * Added e100_disable_txdma_channel() and e100_enable_txdma_channel().
- * Fixed rs_throttle() and rs_unthrottle() to properly call rs_send_xchar
- * instead of setting info->x_char and check the CRTSCTS flag before
- * controlling the rts pin.
- *
- * Revision 1.14 2003/04/09 08:12:44 pkj
- * Corrected typo changes made upstream.
- *
- * Revision 1.13 2003/04/09 05:20:47 starvik
- * Merge of Linux 2.5.67
- *
- * Revision 1.11 2003/01/22 06:48:37 starvik
- * Fixed warnings issued by GCC 3.2.1
- *
- * Revision 1.9 2002/12/13 09:07:47 starvik
- * Alert user that RX_TIMEOUT_TICKS==0 doesn't work
- *
- * Revision 1.8 2002/12/11 13:13:57 starvik
- * Added arch/ to v10 specific includes
- * Added fix from Linux 2.4 in serial.c (flush_to_flip_buffer)
- *
- * Revision 1.7 2002/12/06 07:13:57 starvik
- * Corrected work queue stuff
- * Removed CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST
- *
- * Revision 1.6 2002/11/21 07:17:46 starvik
- * Change static inline to extern inline where otherwise outlined with gcc-3.2
- *
- * Revision 1.5 2002/11/14 15:59:49 starvik
- * Linux 2.5 port of the latest serial driver from 2.4. The work queue stuff
- * probably doesn't work yet.
- *
- * Revision 1.42 2002/11/05 09:08:47 johana
- * Better implementation of rs_stop() and rs_start() that uses the XOFF
- * register to start/stop transmission.
- * change_speed() also initilises XOFF register correctly so that
- * auto_xoff is enabled when IXON flag is set by user.
- * This gives fast XOFF response times.
- *
- * Revision 1.41 2002/11/04 18:40:57 johana
- * Implemented rs_stop() and rs_start().
- * Simple tests using hwtestserial indicates that this should be enough
- * to make it work.
- *
- * Revision 1.40 2002/10/14 05:33:18 starvik
- * RS-485 uses fast timers even if SERIAL_FAST_TIMER is disabled
- *
- * Revision 1.39 2002/09/30 21:00:57 johana
- * Support for CONFIG_ETRAX_SERx_DTR_RI_DSR_CD_MIXED where the status and
- * control pins can be mixed between PA and PB.
- * If no serial port uses MIXED old solution is used
- * (saves a few bytes and cycles).
- * control_pins struct uses masks instead of bit numbers.
- * Corrected dummy values and polarity in line_info() so
- * /proc/tty/driver/serial is now correct.
- * (the E100_xxx_GET() macros is really active low - perhaps not obvious)
- *
- * Revision 1.38 2002/08/23 11:01:36 starvik
- * Check that serial port is enabled in all interrupt handlers to avoid
- * restarts of DMA channels not assigned to serial ports
- *
- * Revision 1.37 2002/08/13 13:02:37 bjornw
- * Removed some warnings because of unused code
- *
- * Revision 1.36 2002/08/08 12:50:01 starvik
- * Serial interrupt is shared with synchronous serial port driver
- *
- * Revision 1.35 2002/06/03 10:40:49 starvik
- * Increased RS-485 RTS toggle timer to 2 characters
- *
- * Revision 1.34 2002/05/28 18:59:36 johana
- * Whitespace and comment fixing to be more like etrax100ser.c 1.71.
- *
- * Revision 1.33 2002/05/28 17:55:43 johana
- * RS-485 uses FAST_TIMER if enabled, and starts a short (one char time)
- * timer from tranismit_chars (interrupt context).
- * The timer toggles RTS in interrupt context when expired giving minimum
- * latencies.
- *
- * Revision 1.32 2002/05/22 13:58:00 johana
- * Renamed rs_write() to raw_write() and made it inline.
- * New rs_write() handles RS-485 if configured and enabled
- * (moved code from e100_write_rs485()).
- * RS-485 ioctl's uses copy_from_user() instead of verify_area().
- *
- * Revision 1.31 2002/04/22 11:20:03 johana
- * Updated copyright years.
- *
- * Revision 1.30 2002/04/22 09:39:12 johana
- * RS-485 support compiles.
- *
- * Revision 1.29 2002/01/14 16:10:01 pkj
- * Allocate the receive buffers dynamically. The static 4kB buffer was
- * too small for the peaks. This means that we can get rid of the extra
- * buffer and the copying to it. It also means we require less memory
- * under normal operations, but can use more when needed (there is a
- * cap at 64kB for safety reasons). If there is no memory available
- * we panic(), and die a horrible death...
- *
- * Revision 1.28 2001/12/18 15:04:53 johana
- * Cleaned up write_rs485() - now it works correctly without padding extra
- * char.
- * Added sane default initialisation of rs485.
- * Added #ifdef around dummy variables.
- *
- * Revision 1.27 2001/11/29 17:00:41 pkj
- * 2kB seems to be too small a buffer when using 921600 bps,
- * so increase it to 4kB (this was already done for the elinux
- * version of the serial driver).
- *
- * Revision 1.26 2001/11/19 14:20:41 pkj
- * Minor changes to comments and unused code.
- *
- * Revision 1.25 2001/11/12 20:03:43 pkj
- * Fixed compiler warnings.
- *
- * Revision 1.24 2001/11/12 15:10:05 pkj
- * Total redesign of the receiving part of the serial driver.
- * Uses eight chained descriptors to write to a 4kB buffer.
- * This data is then serialised into a 2kB buffer. From there it
- * is copied into the TTY's flip buffers when they become available.
- * A lot of copying, and the sizes of the buffers might need to be
- * tweaked, but all in all it should work better than the previous
- * version, without the need to modify the TTY code in any way.
- * Also note that erroneous bytes are now correctly marked in the
- * flag buffers (instead of always marking the first byte).
- *
- * Revision 1.23 2001/10/30 17:53:26 pkj
- * * Set info->uses_dma to 0 when a port is closed.
- * * Mark the timer1 interrupt as a fast one (SA_INTERRUPT).
- * * Call start_flush_timer() in start_receive() if
- * CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST is defined.
- *
- * Revision 1.22 2001/10/30 17:44:03 pkj
- * Use %lu for received and transmitted counters in line_info().
- *
- * Revision 1.21 2001/10/30 17:40:34 pkj
- * Clean-up. The only change to functionality is that
- * CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS(=5) is used instead of
- * MAX_FLUSH_TIME(=8).
- *
- * Revision 1.20 2001/10/30 15:24:49 johana
- * Added char_time stuff from 2.0 driver.
- *
- * Revision 1.19 2001/10/30 15:23:03 johana
- * Merged with 1.13.2 branch + fixed indentation
- * and changed CONFIG_ETRAX100_XYS to CONFIG_ETRAX_XYZ
- *
- * Revision 1.18 2001/09/24 09:27:22 pkj
- * Completed ext_baud_table[] in cflag_to_baud() and cflag_to_etrax_baud().
- *
- * Revision 1.17 2001/08/24 11:32:49 ronny
- * More fixes for the CONFIG_ETRAX_SERIAL_PORT0 define.
- *
- * Revision 1.16 2001/08/24 07:56:22 ronny
- * Added config ifdefs around ser0 irq requests.
- *
- * Revision 1.15 2001/08/16 09:10:31 bjarne
- * serial.c - corrected the initialization of rs_table, the wrong defines
- * where used.
- * Corrected a test in timed_flush_handler.
- * Changed configured to enabled.
- * serial.h - Changed configured to enabled.
- *
- * Revision 1.14 2001/08/15 07:31:23 bjarne
- * Introduced two new members to the e100_serial struct.
- * configured - Will be set to 1 if the port has been configured in .config
- * uses_dma - Should be set to 1 if the port uses DMA. Currently it is set
- * to 1
- * when a port is opened. This is used to limit the DMA interrupt
- * routines to only manipulate DMA channels actually used by the
- * serial driver.
- *
- * Revision 1.13.2.2 2001/10/17 13:57:13 starvik
- * Receiver was broken by the break fixes
- *
- * Revision 1.13.2.1 2001/07/20 13:57:39 ronny
- * Merge with new stuff from etrax100ser.c. Works but haven't checked stuff
- * like break handling.
- *
- * Revision 1.13 2001/05/09 12:40:31 johana
- * Use DMA_NBR and IRQ_NBR defines from dma.h and irq.h
- *
- * Revision 1.12 2001/04/19 12:23:07 bjornw
- * CONFIG_RS485 -> CONFIG_ETRAX_RS485
- *
- * Revision 1.11 2001/04/05 14:29:48 markusl
- * Updated according to review remarks i.e.
- * -Use correct types in port structure to avoid compiler warnings
- * -Try to use IO_* macros whenever possible
- * -Open should never return -EBUSY
- *
- * Revision 1.10 2001/03/05 13:14:07 bjornw
- * Another spelling fix
- *
- * Revision 1.9 2001/02/23 13:46:38 bjornw
- * Spellling check
- *
- * Revision 1.8 2001/01/23 14:56:35 markusl
- * Made use of ser1 optional
- * Needed by USB
- *
- * Revision 1.7 2001/01/19 16:14:48 perf
- * Added kernel options for serial ports 234.
- * Changed option names from CONFIG_ETRAX100_XYZ to CONFIG_ETRAX_XYZ.
- *
- * Revision 1.6 2000/11/22 16:36:09 bjornw
- * Please marketing by using the correct case when spelling Etrax.
- *
- * Revision 1.5 2000/11/21 16:43:37 bjornw
- * Fixed so it compiles under CONFIG_SVINTO_SIM
- *
- * Revision 1.4 2000/11/15 17:34:12 bjornw
- * Added a timeout timer for flushing input channels. The interrupt-based
- * fast flush system should be easy to merge with this later (works the same
- * way, only with an irq instead of a system timer_list)
- *
- * Revision 1.3 2000/11/13 17:19:57 bjornw
- * * Incredibly, this almost complete rewrite of serial.c worked (at least
- * for output) the first time.
- *
- * Items worth noticing:
- *
- * No Etrax100 port 1 workarounds (does only compile on 2.4 anyway now)
- * RS485 is not ported (why can't it be done in userspace as on x86 ?)
- * Statistics done through async_icount - if any more stats are needed,
- * that's the place to put them or in an arch-dep version of it.
- * timeout_interrupt and the other fast timeout stuff not ported yet
- * There be dragons in this 3k+ line driver
- *
- * Revision 1.2 2000/11/10 16:50:28 bjornw
- * First shot at a 2.4 port, does not compile totally yet
- *
- * Revision 1.1 2000/11/10 16:47:32 bjornw
- * Added verbatim copy of rev 1.49 etrax100ser.c from elinux
- *
- * Revision 1.49 2000/10/30 15:47:14 tobiasa
- * Changed version number.
- *
- * Revision 1.48 2000/10/25 11:02:43 johana
- * Changed %ul to %lu in printf's
- *
- * Revision 1.47 2000/10/18 15:06:53 pkj
- * Compile correctly with CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST and
- * CONFIG_ETRAX_SERIAL_PROC_ENTRY together.
- * Some clean-up of the /proc/serial file.
- *
- * Revision 1.46 2000/10/16 12:59:40 johana
- * Added CONFIG_ETRAX_SERIAL_PROC_ENTRY for statistics and debug info.
- *
- * Revision 1.45 2000/10/13 17:10:59 pkj
- * Do not flush DMAs while flipping TTY buffers.
- *
- * Revision 1.44 2000/10/13 16:34:29 pkj
- * Added a delay in ser_interrupt() for 2.3ms when an error is detected.
- * We do not know why this delay is required yet, but without it the
- * irmaflash program does not work (this was the program that needed
- * the ser_interrupt() to be needed in the first place). This should not
- * affect normal use of the serial ports.
- *
- * Revision 1.43 2000/10/13 16:30:44 pkj
- * New version of the fast flush of serial buffers code. This time
- * it is localized to the serial driver and uses a fast timer to
- * do the work.
- *
- * Revision 1.42 2000/10/13 14:54:26 bennyo
- * Fix for switching RTS when using rs485
- *
- * Revision 1.41 2000/10/12 11:43:44 pkj
- * Cleaned up a number of comments.
- *
- * Revision 1.40 2000/10/10 11:58:39 johana
- * Made RS485 support generic for all ports.
- * Toggle rts in interrupt if no delay wanted.
- * WARNING: No true transmitter empty check??
- * Set d_wait bit when sending data so interrupt is delayed until
- * fifo flushed. (Fix tcdrain() problem)
- *
- * Revision 1.39 2000/10/04 16:08:02 bjornw
- * * Use virt_to_phys etc. for DMA addresses
- * * Removed CONFIG_FLUSH_DMA_FAST hacks
- * * Indentation fix
- *
- * Revision 1.38 2000/10/02 12:27:10 mattias
- * * added variable used when using fast flush on serial dma.
- * (CONFIG_FLUSH_DMA_FAST)
- *
- * Revision 1.37 2000/09/27 09:44:24 pkj
- * Uncomment definition of SERIAL_HANDLE_EARLY_ERRORS.
- *
- * Revision 1.36 2000/09/20 13:12:52 johana
- * Support for CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS:
- * Number of timer ticks between flush of receive fifo (1 tick = 10ms).
- * Try 0-3 for low latency applications. Approx 5 for high load
- * applications (e.g. PPP). Maybe this should be more adaptive some day...
- *
- * Revision 1.35 2000/09/20 10:36:08 johana
- * Typo in get_lsr_info()
- *
- * Revision 1.34 2000/09/20 10:29:59 johana
- * Let rs_chars_in_buffer() check fifo content as well.
- * get_lsr_info() might work now (not tested).
- * Easier to change the port to debug.
- *
- * Revision 1.33 2000/09/13 07:52:11 torbjore
- * Support RS485
- *
- * Revision 1.32 2000/08/31 14:45:37 bjornw
- * After sending a break we need to reset the transmit DMA channel
- *
- * Revision 1.31 2000/06/21 12:13:29 johana
- * Fixed wait for all chars sent when closing port.
- * (Used to always take 1 second!)
- * Added shadows for directions of status/ctrl signals.
- *
- * Revision 1.30 2000/05/29 16:27:55 bjornw
- * Simulator ifdef moved a bit
- *
- * Revision 1.29 2000/05/09 09:40:30 mattias
- * * Added description of dma registers used in timeout_interrupt
- * * Removed old code
- *
- * Revision 1.28 2000/05/08 16:38:58 mattias
- * * Bugfix for flushing fifo in timeout_interrupt
- * Problem occurs when bluetooth stack waits for a small number of bytes
- * containing an event acknowledging free buffers in bluetooth HW
- * As before, data was stuck in fifo until more data came on uart and
- * flushed it up to the stack.
- *
- * Revision 1.27 2000/05/02 09:52:28 jonasd
- * Added fix for peculiar etrax behaviour when eop is forced on an empty
- * fifo. This is used when flashing the IRMA chip. Disabled by default.
- *
- * Revision 1.26 2000/03/29 15:32:02 bjornw
- * 2.0.34 updates
- *
- * Revision 1.25 2000/02/16 16:59:36 bjornw
- * * Receive DMA directly into the flip-buffer, eliminating an intermediary
- * receive buffer and a memcpy. Will avoid some overruns.
- * * Error message on debug port if an overrun or flip buffer overrun occurs.
- * * Just use the first byte in the flag flip buffer for errors.
- * * Check for timeout on the serial ports only each 5/100 s, not 1/100.
- *
- * Revision 1.24 2000/02/09 18:02:28 bjornw
- * * Clear serial errors (overrun, framing, parity) correctly. Before, the
- * receiver would get stuck if an error occurred and we did not restart
- * the input DMA.
- * * Cosmetics (indentation, some code made into inlines)
- * * Some more debug options
- * * Actually shut down the serial port (DMA irq, DMA reset, receiver stop)
- * when the last open is closed. Corresponding fixes in startup().
- * * rs_close() "tx FIFO wait" code moved into right place, bug & -> && fixed
- * and make a special case out of port 1 (R_DMA_CHx_STATUS is broken for that)
- * * e100_disable_rx/enable_rx just disables/enables the receiver, not RTS
- *
- * Revision 1.23 2000/01/24 17:46:19 johana
- * Wait for flush of DMA/FIFO when closing port.
- *
- * Revision 1.22 2000/01/20 18:10:23 johana
- * Added TIOCMGET ioctl to return modem status.
- * Implemented modem status/control that works with the extra signals
- * (DTR, DSR, RI,CD) as well.
- * 3 different modes supported:
- * ser0 on PB (Bundy), ser1 on PB (Lisa) and ser2 on PA (Bundy)
- * Fixed DEF_TX value that caused the serial transmitter pin (txd) to go to 0 when
- * closing the last filehandle, NASTY!.
- * Added break generation, not tested though!
- * Use IRQF_SHARED when request_irq() for ser2 and ser3 (shared with) par0 and par1.
- * You can't use them at the same time (yet..), but you can hopefully switch
- * between ser2/par0, ser3/par1 with the same kernel config.
- * Replaced some magic constants with defines
- *
- *
*/
static char *serial_version = "$Revision: 1.25 $";
@@ -442,11 +26,12 @@ static char *serial_version = "$Revision: 1.25 $";
#include <asm/uaccess.h>
#include <linux/kernel.h>
#include <linux/mutex.h>
+#include <linux/bitops.h>
#include <asm/io.h>
#include <asm/irq.h>
+#include <asm/dma.h>
#include <asm/system.h>
-#include <asm/bitops.h>
#include <linux/delay.h>
#include <asm/arch/svinto.h>
@@ -454,8 +39,9 @@ static char *serial_version = "$Revision: 1.25 $";
/* non-arch dependent serial structures are in linux/serial.h */
#include <linux/serial.h>
/* while we keep our own stuff (struct e100_serial) in a local .h file */
-#include "serial.h"
+#include "crisv10.h"
#include <asm/fasttimer.h>
+#include <asm/arch/io_interface_mux.h>
#ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER
#ifndef CONFIG_ETRAX_FAST_TIMER
@@ -504,16 +90,6 @@ struct tty_driver *serial_driver;
from eLinux */
#define SERIAL_HANDLE_EARLY_ERRORS
-/* Defined and used in n_tty.c, but we need it here as well */
-#define TTY_THRESHOLD_THROTTLE 128
-
-/* Due to buffersizes and threshold values, our SERIAL_DESCR_BUF_SIZE
- * must not be to high or flow control won't work if we leave it to the tty
- * layer so we have our own throttling in flush_to_flip
- * TTY_FLIPBUF_SIZE=512,
- * TTY_THRESHOLD_THROTTLE/UNTHROTTLE=128
- * BUF_SIZE can't be > 128
- */
/* Currently 16 descriptors x 128 bytes = 2048 bytes */
#define SERIAL_DESCR_BUF_SIZE 256
@@ -586,13 +162,13 @@ unsigned long timer_data_to_ns(unsigned long timer_data);
static void change_speed(struct e100_serial *info);
static void rs_throttle(struct tty_struct * tty);
static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
-static int rs_write(struct tty_struct * tty, int from_user,
- const unsigned char *buf, int count);
+static int rs_write(struct tty_struct *tty,
+ const unsigned char *buf, int count);
#ifdef CONFIG_ETRAX_RS485
-static int e100_write_rs485(struct tty_struct * tty, int from_user,
- const unsigned char *buf, int count);
+static int e100_write_rs485(struct tty_struct *tty,
+ const unsigned char *buf, int count);
#endif
-static int get_lsr_info(struct e100_serial * info, unsigned int *value);
+static int get_lsr_info(struct e100_serial *info, unsigned int *value);
#define DEF_BAUD 115200 /* 115.2 kbit/s */
@@ -677,20 +253,39 @@ static struct e100_serial rs_table[] = {
.rx_ctrl = DEF_RX,
.tx_ctrl = DEF_TX,
.iseteop = 2,
+ .dma_owner = dma_ser0,
+ .io_if = if_serial_0,
#ifdef CONFIG_ETRAX_SERIAL_PORT0
.enabled = 1,
#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA6_OUT
.dma_out_enabled = 1,
+ .dma_out_nbr = SER0_TX_DMA_NBR,
+ .dma_out_irq_nbr = SER0_DMA_TX_IRQ_NBR,
+ .dma_out_irq_flags = IRQF_DISABLED,
+ .dma_out_irq_description = "serial 0 dma tr",
#else
.dma_out_enabled = 0,
+ .dma_out_nbr = UINT_MAX,
+ .dma_out_irq_nbr = 0,
+ .dma_out_irq_flags = 0,
+ .dma_out_irq_description = NULL,
#endif
#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA7_IN
.dma_in_enabled = 1,
+ .dma_in_nbr = SER0_RX_DMA_NBR,
+ .dma_in_irq_nbr = SER0_DMA_RX_IRQ_NBR,
+ .dma_in_irq_flags = IRQF_DISABLED,
+ .dma_in_irq_description = "serial 0 dma rec",
#else
- .dma_in_enabled = 0
+ .dma_in_enabled = 0,
+ .dma_in_nbr = UINT_MAX,
+ .dma_in_irq_nbr = 0,
+ .dma_in_irq_flags = 0,
+ .dma_in_irq_description = NULL,
#endif
#else
.enabled = 0,
+ .io_if_description = NULL,
.dma_out_enabled = 0,
.dma_in_enabled = 0
#endif
@@ -712,20 +307,42 @@ static struct e100_serial rs_table[] = {
.rx_ctrl = DEF_RX,
.tx_ctrl = DEF_TX,
.iseteop = 3,
+ .dma_owner = dma_ser1,
+ .io_if = if_serial_1,
#ifdef CONFIG_ETRAX_SERIAL_PORT1
.enabled = 1,
+ .io_if_description = "ser1",
#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA8_OUT
.dma_out_enabled = 1,
+ .dma_out_nbr = SER1_TX_DMA_NBR,
+ .dma_out_irq_nbr = SER1_DMA_TX_IRQ_NBR,
+ .dma_out_irq_flags = IRQF_DISABLED,
+ .dma_out_irq_description = "serial 1 dma tr",
#else
.dma_out_enabled = 0,
+ .dma_out_nbr = UINT_MAX,
+ .dma_out_irq_nbr = 0,
+ .dma_out_irq_flags = 0,
+ .dma_out_irq_description = NULL,
#endif
#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA9_IN
.dma_in_enabled = 1,
+ .dma_in_nbr = SER1_RX_DMA_NBR,
+ .dma_in_irq_nbr = SER1_DMA_RX_IRQ_NBR,
+ .dma_in_irq_flags = IRQF_DISABLED,
+ .dma_in_irq_description = "serial 1 dma rec",
#else
- .dma_in_enabled = 0
+ .dma_in_enabled = 0,
+ .dma_in_enabled = 0,
+ .dma_in_nbr = UINT_MAX,
+ .dma_in_irq_nbr = 0,
+ .dma_in_irq_flags = 0,
+ .dma_in_irq_description = NULL,
#endif
#else
.enabled = 0,
+ .io_if_description = NULL,
+ .dma_in_irq_nbr = 0,
.dma_out_enabled = 0,
.dma_in_enabled = 0
#endif
@@ -746,20 +363,40 @@ static struct e100_serial rs_table[] = {
.rx_ctrl = DEF_RX,
.tx_ctrl = DEF_TX,
.iseteop = 0,
+ .dma_owner = dma_ser2,
+ .io_if = if_serial_2,
#ifdef CONFIG_ETRAX_SERIAL_PORT2
.enabled = 1,
+ .io_if_description = "ser2",
#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA2_OUT
.dma_out_enabled = 1,
+ .dma_out_nbr = SER2_TX_DMA_NBR,
+ .dma_out_irq_nbr = SER2_DMA_TX_IRQ_NBR,
+ .dma_out_irq_flags = IRQF_DISABLED,
+ .dma_out_irq_description = "serial 2 dma tr",
#else
.dma_out_enabled = 0,
+ .dma_out_nbr = UINT_MAX,
+ .dma_out_irq_nbr = 0,
+ .dma_out_irq_flags = 0,
+ .dma_out_irq_description = NULL,
#endif
#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA3_IN
.dma_in_enabled = 1,
+ .dma_in_nbr = SER2_RX_DMA_NBR,
+ .dma_in_irq_nbr = SER2_DMA_RX_IRQ_NBR,
+ .dma_in_irq_flags = IRQF_DISABLED,
+ .dma_in_irq_description = "serial 2 dma rec",
#else
- .dma_in_enabled = 0
+ .dma_in_enabled = 0,
+ .dma_in_nbr = UINT_MAX,
+ .dma_in_irq_nbr = 0,
+ .dma_in_irq_flags = 0,
+ .dma_in_irq_description = NULL,
#endif
#else
.enabled = 0,
+ .io_if_description = NULL,
.dma_out_enabled = 0,
.dma_in_enabled = 0
#endif
@@ -780,20 +417,40 @@ static struct e100_serial rs_table[] = {
.rx_ctrl = DEF_RX,
.tx_ctrl = DEF_TX,
.iseteop = 1,
+ .dma_owner = dma_ser3,
+ .io_if = if_serial_3,
#ifdef CONFIG_ETRAX_SERIAL_PORT3
.enabled = 1,
+ .io_if_description = "ser3",
#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA4_OUT
.dma_out_enabled = 1,
+ .dma_out_nbr = SER3_TX_DMA_NBR,
+ .dma_out_irq_nbr = SER3_DMA_TX_IRQ_NBR,
+ .dma_out_irq_flags = IRQF_DISABLED,
+ .dma_out_irq_description = "serial 3 dma tr",
#else
.dma_out_enabled = 0,
+ .dma_out_nbr = UINT_MAX,
+ .dma_out_irq_nbr = 0,
+ .dma_out_irq_flags = 0,
+ .dma_out_irq_description = NULL,
#endif
#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA5_IN
.dma_in_enabled = 1,
+ .dma_in_nbr = SER3_RX_DMA_NBR,
+ .dma_in_irq_nbr = SER3_DMA_RX_IRQ_NBR,
+ .dma_in_irq_flags = IRQF_DISABLED,
+ .dma_in_irq_description = "serial 3 dma rec",
#else
- .dma_in_enabled = 0
+ .dma_in_enabled = 0,
+ .dma_in_nbr = UINT_MAX,
+ .dma_in_irq_nbr = 0,
+ .dma_in_irq_flags = 0,
+ .dma_in_irq_description = NULL
#endif
#else
.enabled = 0,
+ .io_if_description = NULL,
.dma_out_enabled = 0,
.dma_in_enabled = 0
#endif
@@ -1414,12 +1071,11 @@ e100_dtr(struct e100_serial *info, int set)
{
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
*e100_modem_pins[info->line].dtr_shadow &= ~mask;
*e100_modem_pins[info->line].dtr_shadow |= (set ? 0 : mask);
*e100_modem_pins[info->line].dtr_port = *e100_modem_pins[info->line].dtr_shadow;
- restore_flags(flags);
+ local_irq_restore(flags);
}
#ifdef SERIAL_DEBUG_IO
@@ -1438,12 +1094,11 @@ e100_rts(struct e100_serial *info, int set)
{
#ifndef CONFIG_SVINTO_SIM
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
info->rx_ctrl &= ~E100_RTS_MASK;
info->rx_ctrl |= (set ? 0 : E100_RTS_MASK); /* RTS is active low */
info->port[REG_REC_CTRL] = info->rx_ctrl;
- restore_flags(flags);
+ local_irq_restore(flags);
#ifdef SERIAL_DEBUG_IO
printk("ser%i rts %i\n", info->line, set);
#endif
@@ -1461,12 +1116,11 @@ e100_ri_out(struct e100_serial *info, int set)
unsigned char mask = e100_modem_pins[info->line].ri_mask;
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
*e100_modem_pins[info->line].ri_shadow &= ~mask;
*e100_modem_pins[info->line].ri_shadow |= (set ? 0 : mask);
*e100_modem_pins[info->line].ri_port = *e100_modem_pins[info->line].ri_shadow;
- restore_flags(flags);
+ local_irq_restore(flags);
}
#endif
}
@@ -1479,12 +1133,11 @@ e100_cd_out(struct e100_serial *info, int set)
unsigned char mask = e100_modem_pins[info->line].cd_mask;
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
*e100_modem_pins[info->line].cd_shadow &= ~mask;
*e100_modem_pins[info->line].cd_shadow |= (set ? 0 : mask);
*e100_modem_pins[info->line].cd_port = *e100_modem_pins[info->line].cd_shadow;
- restore_flags(flags);
+ local_irq_restore(flags);
}
#endif
}
@@ -1558,8 +1211,7 @@ static void e100_disable_txdma_channel(struct e100_serial *info)
/* Disable output DMA channel for the serial port in question
* ( set to something other then serialX)
*/
- save_flags(flags);
- cli();
+ local_irq_save(flags);
DFLOW(DEBUG_LOG(info->line, "disable_txdma_channel %i\n", info->line));
if (info->line == 0) {
if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma6)) ==
@@ -1587,7 +1239,7 @@ static void e100_disable_txdma_channel(struct e100_serial *info)
}
}
*R_GEN_CONFIG = genconfig_shadow;
- restore_flags(flags);
+ local_irq_restore(flags);
}
@@ -1595,8 +1247,7 @@ static void e100_enable_txdma_channel(struct e100_serial *info)
{
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
DFLOW(DEBUG_LOG(info->line, "enable_txdma_channel %i\n", info->line));
/* Enable output DMA channel for the serial port in question */
if (info->line == 0) {
@@ -1613,7 +1264,7 @@ static void e100_enable_txdma_channel(struct e100_serial *info)
genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma4, serial3);
}
*R_GEN_CONFIG = genconfig_shadow;
- restore_flags(flags);
+ local_irq_restore(flags);
}
static void e100_disable_rxdma_channel(struct e100_serial *info)
@@ -1623,8 +1274,7 @@ static void e100_disable_rxdma_channel(struct e100_serial *info)
/* Disable input DMA channel for the serial port in question
* ( set to something other then serialX)
*/
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if (info->line == 0) {
if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma7)) ==
IO_STATE(R_GEN_CONFIG, dma7, serial0)) {
@@ -1651,7 +1301,7 @@ static void e100_disable_rxdma_channel(struct e100_serial *info)
}
}
*R_GEN_CONFIG = genconfig_shadow;
- restore_flags(flags);
+ local_irq_restore(flags);
}
@@ -1659,8 +1309,7 @@ static void e100_enable_rxdma_channel(struct e100_serial *info)
{
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* Enable input DMA channel for the serial port in question */
if (info->line == 0) {
genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma7);
@@ -1676,7 +1325,7 @@ static void e100_enable_rxdma_channel(struct e100_serial *info)
genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma5, serial3);
}
*R_GEN_CONFIG = genconfig_shadow;
- restore_flags(flags);
+ local_irq_restore(flags);
}
#ifdef SERIAL_HANDLE_EARLY_ERRORS
@@ -1783,7 +1432,7 @@ e100_enable_rs485(struct tty_struct *tty,struct rs485_control *r)
}
static int
-e100_write_rs485(struct tty_struct *tty, int from_user,
+e100_write_rs485(struct tty_struct *tty,
const unsigned char *buf, int count)
{
struct e100_serial * info = (struct e100_serial *)tty->driver_data;
@@ -1796,7 +1445,7 @@ e100_write_rs485(struct tty_struct *tty, int from_user,
*/
info->rs485.enabled = 1;
/* rs_write now deals with RS485 if enabled */
- count = rs_write(tty, from_user, buf, count);
+ count = rs_write(tty, buf, count);
info->rs485.enabled = old_enabled;
return count;
}
@@ -1834,7 +1483,7 @@ rs_stop(struct tty_struct *tty)
unsigned long flags;
unsigned long xoff;
- save_flags(flags); cli();
+ local_irq_save(flags);
DFLOW(DEBUG_LOG(info->line, "XOFF rs_stop xmit %i\n",
CIRC_CNT(info->xmit.head,
info->xmit.tail,SERIAL_XMIT_SIZE)));
@@ -1846,7 +1495,7 @@ rs_stop(struct tty_struct *tty)
}
*((unsigned long *)&info->port[REG_XOFF]) = xoff;
- restore_flags(flags);
+ local_irq_restore(flags);
}
}
@@ -1858,7 +1507,7 @@ rs_start(struct tty_struct *tty)
unsigned long flags;
unsigned long xoff;
- save_flags(flags); cli();
+ local_irq_save(flags);
DFLOW(DEBUG_LOG(info->line, "XOFF rs_start xmit %i\n",
CIRC_CNT(info->xmit.head,
info->xmit.tail,SERIAL_XMIT_SIZE)));
@@ -1873,7 +1522,7 @@ rs_start(struct tty_struct *tty)
info->xmit.head != info->xmit.tail && info->xmit.buf)
e100_enable_serial_tx_ready_irq(info);
- restore_flags(flags);
+ local_irq_restore(flags);
}
}
@@ -2053,8 +1702,7 @@ static int serial_fast_timer_expired = 0;
static void flush_timeout_function(unsigned long data);
#define START_FLUSH_FAST_TIMER_TIME(info, string, usec) {\
unsigned long timer_flags; \
- save_flags(timer_flags); \
- cli(); \
+ local_irq_save(timer_flags); \
if (fast_timers[info->line].function == NULL) { \
serial_fast_timer_started++; \
TIMERD(DEBUG_LOG(info->line, "start_timer %i ", info->line)); \
@@ -2068,7 +1716,7 @@ static void flush_timeout_function(unsigned long data);
else { \
TIMERD(DEBUG_LOG(info->line, "timer %i already running\n", info->line)); \
} \
- restore_flags(timer_flags); \
+ local_irq_restore(timer_flags); \
}
#define START_FLUSH_FAST_TIMER(info, string) START_FLUSH_FAST_TIMER_TIME(info, string, info->flush_time_usec)
@@ -2097,8 +1745,7 @@ append_recv_buffer(struct e100_serial *info, struct etrax_recv_buffer *buffer)
{
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if (!info->first_recv_buffer)
info->first_recv_buffer = buffer;
@@ -2111,7 +1758,7 @@ append_recv_buffer(struct e100_serial *info, struct etrax_recv_buffer *buffer)
if (info->recv_cnt > info->max_recv_cnt)
info->max_recv_cnt = info->recv_cnt;
- restore_flags(flags);
+ local_irq_restore(flags);
}
static int
@@ -2131,11 +1778,7 @@ add_char_and_flag(struct e100_serial *info, unsigned char data, unsigned char fl
info->icount.rx++;
} else {
struct tty_struct *tty = info->tty;
- *tty->flip.char_buf_ptr = data;
- *tty->flip.flag_buf_ptr = flag;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
+ tty_insert_flip_char(tty, data, flag);
info->icount.rx++;
}
@@ -2320,7 +1963,6 @@ start_receive(struct e100_serial *info)
*/
return;
#endif
- info->tty->flip.count = 0;
if (info->uses_dma_in) {
/* reset the input dma channel to be sure it works */
@@ -2482,70 +2124,21 @@ static void flush_to_flip_buffer(struct e100_serial *info)
{
struct tty_struct *tty;
struct etrax_recv_buffer *buffer;
- unsigned int length;
unsigned long flags;
- int max_flip_size;
- if (!info->first_recv_buffer)
- return;
-
- save_flags(flags);
- cli();
+ local_irq_save(flags);
+ tty = info->tty;
- if (!(tty = info->tty)) {
- restore_flags(flags);
+ if (!tty) {
+ local_irq_restore(flags);
return;
}
- length = tty->flip.count;
- /* Don't flip more than the ldisc has room for.
- * The return value from ldisc.receive_room(tty) - might not be up to
- * date, the previous flip of up to TTY_FLIPBUF_SIZE might be on the
- * processed and not accounted for yet.
- * Since we use DMA, 1 SERIAL_DESCR_BUF_SIZE could be on the way.
- * Lets buffer data here and let flow control take care of it.
- * Since we normally flip large chunks, the ldisc don't react
- * with throttle until too late if we flip to much.
- */
- max_flip_size = tty->ldisc.receive_room(tty);
- if (max_flip_size < 0)
- max_flip_size = 0;
- if (max_flip_size <= (TTY_FLIPBUF_SIZE + /* Maybe not accounted for */
- length + info->recv_cnt + /* We have this queued */
- 2*SERIAL_DESCR_BUF_SIZE + /* This could be on the way */
- TTY_THRESHOLD_THROTTLE)) { /* Some slack */
- /* check TTY_THROTTLED first so it indicates our state */
- if (!test_and_set_bit(TTY_THROTTLED, &tty->flags)) {
- DFLOW(DEBUG_LOG(info->line,"flush_to_flip throttles room %lu\n", max_flip_size));
- rs_throttle(tty);
- }
-#if 0
- else if (max_flip_size <= (TTY_FLIPBUF_SIZE + /* Maybe not accounted for */
- length + info->recv_cnt + /* We have this queued */
- SERIAL_DESCR_BUF_SIZE + /* This could be on the way */
- TTY_THRESHOLD_THROTTLE)) { /* Some slack */
- DFLOW(DEBUG_LOG(info->line,"flush_to_flip throttles again! %lu\n", max_flip_size));
- rs_throttle(tty);
- }
-#endif
- }
-
- if (max_flip_size > TTY_FLIPBUF_SIZE)
- max_flip_size = TTY_FLIPBUF_SIZE;
-
- while ((buffer = info->first_recv_buffer) && length < max_flip_size) {
+ while ((buffer = info->first_recv_buffer) != NULL) {
unsigned int count = buffer->length;
- if (length + count > max_flip_size)
- count = max_flip_size - length;
-
- memcpy(tty->flip.char_buf_ptr + length, buffer->buffer, count);
- memset(tty->flip.flag_buf_ptr + length, TTY_NORMAL, count);
- tty->flip.flag_buf_ptr[length] = buffer->error;
-
- length += count;
+ tty_insert_flip_string(tty, buffer->buffer, count);
info->recv_cnt -= count;
- DFLIP(DEBUG_LOG(info->line,"flip: %i\n", length));
if (count == buffer->length) {
info->first_recv_buffer = buffer->next;
@@ -2560,26 +2153,9 @@ static void flush_to_flip_buffer(struct e100_serial *info)
if (!info->first_recv_buffer)
info->last_recv_buffer = NULL;
- tty->flip.count = length;
- DFLIP(if (tty->ldisc.chars_in_buffer(tty) > 3500) {
- DEBUG_LOG(info->line, "ldisc %lu\n",
- tty->ldisc.chars_in_buffer(tty));
- DEBUG_LOG(info->line, "flip.count %lu\n",
- tty->flip.count);
- }
- );
- restore_flags(flags);
-
- DFLIP(
- if (1) {
- DEBUG_LOG(info->line, "*** rxtot %i\n", info->icount.rx);
- DEBUG_LOG(info->line, "ldisc %lu\n", tty->ldisc.chars_in_buffer(tty));
- DEBUG_LOG(info->line, "room %lu\n", tty->ldisc.receive_room(tty));
- }
+ local_irq_restore(flags);
- );
-
- /* this includes a check for low-latency */
+ /* This includes a check for low-latency */
tty_flip_buffer_push(tty);
}
@@ -2722,21 +2298,7 @@ struct e100_serial * handle_ser_rx_interrupt_no_dma(struct e100_serial *info)
printk("!NO TTY!\n");
return info;
}
- if (tty->flip.count >= TTY_FLIPBUF_SIZE - TTY_THRESHOLD_THROTTLE) {
- /* check TTY_THROTTLED first so it indicates our state */
- if (!test_and_set_bit(TTY_THROTTLED, &tty->flags)) {
- DFLOW(DEBUG_LOG(info->line, "rs_throttle flip.count: %i\n", tty->flip.count));
- rs_throttle(tty);
- }
- }
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
- DEBUG_LOG(info->line, "force FLIP! %i\n", tty->flip.count);
- tty->flip.work.func((void *) tty);
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
- DEBUG_LOG(info->line, "FLIP FULL! %i\n", tty->flip.count);
- return info; /* if TTY_DONT_FLIP is set */
- }
- }
+
/* Read data and status at the same time */
data_read = *((unsigned long *)&info->port[REG_DATA_STATUS32]);
more_data:
@@ -2789,27 +2351,26 @@ more_data:
DEBUG_LOG(info->line, "EBRK %i\n", info->break_detected_cnt);
info->errorcode = ERRCODE_INSERT_BREAK;
} else {
+ unsigned char data = IO_EXTRACT(R_SERIAL0_READ,
+ data_in, data_read);
+ char flag = TTY_NORMAL;
if (info->errorcode == ERRCODE_INSERT_BREAK) {
- info->icount.brk++;
- *tty->flip.char_buf_ptr = 0;
- *tty->flip.flag_buf_ptr = TTY_BREAK;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
+ struct tty_struct *tty = info->tty;
+ tty_insert_flip_char(tty, 0, flag);
info->icount.rx++;
}
- *tty->flip.char_buf_ptr = IO_EXTRACT(R_SERIAL0_READ, data_in, data_read);
if (data_read & IO_MASK(R_SERIAL0_READ, par_err)) {
info->icount.parity++;
- *tty->flip.flag_buf_ptr = TTY_PARITY;
+ flag = TTY_PARITY;
} else if (data_read & IO_MASK(R_SERIAL0_READ, overrun)) {
info->icount.overrun++;
- *tty->flip.flag_buf_ptr = TTY_OVERRUN;
+ flag = TTY_OVERRUN;
} else if (data_read & IO_MASK(R_SERIAL0_READ, framing_err)) {
info->icount.frame++;
- *tty->flip.flag_buf_ptr = TTY_FRAME;
+ flag = TTY_FRAME;
}
+ tty_insert_flip_char(tty, data, flag);
info->errorcode = 0;
}
info->break_detected_cnt = 0;
@@ -2825,16 +2386,14 @@ more_data:
log_int(rdpc(), 0, 0);
}
);
- *tty->flip.char_buf_ptr = IO_EXTRACT(R_SERIAL0_READ, data_in, data_read);
- *tty->flip.flag_buf_ptr = 0;
+ tty_insert_flip_char(tty,
+ IO_EXTRACT(R_SERIAL0_READ, data_in, data_read),
+ TTY_NORMAL);
} else {
DEBUG_LOG(info->line, "ser_rx int but no data_avail %08lX\n", data_read);
}
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
info->icount.rx++;
data_read = *((unsigned long *)&info->port[REG_DATA_STATUS32]);
if (data_read & IO_MASK(R_SERIAL0_READ, data_avail)) {
@@ -2972,7 +2531,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info)
if (info->x_char) {
unsigned char rstat;
DFLOW(DEBUG_LOG(info->line, "tx_int: xchar 0x%02X\n", info->x_char));
- save_flags(flags); cli();
+ local_irq_save(flags);
rstat = info->port[REG_STATUS];
DFLOW(DEBUG_LOG(info->line, "stat %x\n", rstat));
@@ -2981,7 +2540,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info)
info->x_char = 0;
/* We must enable since it is disabled in ser_interrupt */
e100_enable_serial_tx_ready_irq(info);
- restore_flags(flags);
+ local_irq_restore(flags);
return;
}
if (info->uses_dma_out) {
@@ -2989,7 +2548,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info)
int i;
/* We only use normal tx interrupt when sending x_char */
DFLOW(DEBUG_LOG(info->line, "tx_int: xchar sent\n", 0));
- save_flags(flags); cli();
+ local_irq_save(flags);
rstat = info->port[REG_STATUS];
DFLOW(DEBUG_LOG(info->line, "stat %x\n", rstat));
e100_disable_serial_tx_ready_irq(info);
@@ -3002,7 +2561,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info)
nop();
*info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, continue);
- restore_flags(flags);
+ local_irq_restore(flags);
return;
}
/* Normal char-by-char interrupt */
@@ -3016,7 +2575,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info)
}
DINTR2(DEBUG_LOG(info->line, "tx_int %c\n", info->xmit.buf[info->xmit.tail]));
/* Send a byte, rs485 timing is critical so turn of ints */
- save_flags(flags); cli();
+ local_irq_save(flags);
info->port[REG_TR_DATA] = info->xmit.buf[info->xmit.tail];
info->xmit.tail = (info->xmit.tail + 1) & (SERIAL_XMIT_SIZE-1);
info->icount.tx++;
@@ -3040,7 +2599,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info)
/* We must enable since it is disabled in ser_interrupt */
e100_enable_serial_tx_ready_irq(info);
}
- restore_flags(flags);
+ local_irq_restore(flags);
if (CIRC_CNT(info->xmit.head,
info->xmit.tail,
@@ -3065,7 +2624,7 @@ ser_interrupt(int irq, void *dev_id)
int handled = 0;
static volatile unsigned long reentered_ready_mask = 0;
- save_flags(flags); cli();
+ local_irq_save(flags);
irq_mask1_rd = *R_IRQ_MASK1_RD;
/* First handle all rx interrupts with ints disabled */
info = rs_table;
@@ -3110,7 +2669,7 @@ ser_interrupt(int irq, void *dev_id)
/* Unblock the serial interrupt */
*R_VECT_MASK_SET = IO_STATE(R_VECT_MASK_SET, serial, set);
- sti();
+ local_irq_enable();
ready_mask = (1 << (8+1+2*0)); /* ser0 tr_ready */
info = rs_table;
for (i = 0; i < NR_PORTS; i++) {
@@ -3123,11 +2682,11 @@ ser_interrupt(int irq, void *dev_id)
ready_mask <<= 2;
}
/* handle_ser_tx_interrupt enables tr_ready interrupts */
- cli();
+ local_irq_disable();
/* Handle reentered TX interrupt */
irq_mask1_rd = reentered_ready_mask;
}
- cli();
+ local_irq_disable();
tx_started = 0;
} else {
unsigned long ready_mask;
@@ -3143,7 +2702,7 @@ ser_interrupt(int irq, void *dev_id)
}
}
- restore_flags(flags);
+ local_irq_restore(flags);
return IRQ_RETVAL(handled);
} /* ser_interrupt */
#endif
@@ -3164,11 +2723,13 @@ ser_interrupt(int irq, void *dev_id)
* them using rs_sched_event(), and they get done here.
*/
static void
-do_softint(void *private_)
+do_softint(struct work_struct *work)
{
- struct e100_serial *info = (struct e100_serial *) private_;
+ struct e100_serial *info;
struct tty_struct *tty;
+ info = container_of(work, struct e100_serial, work);
+
tty = info->tty;
if (!tty)
return;
@@ -3188,13 +2749,12 @@ startup(struct e100_serial * info)
if (!xmit_page)
return -ENOMEM;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* if it was already initialized, skip this */
if (info->flags & ASYNC_INITIALIZED) {
- restore_flags(flags);
+ local_irq_restore(flags);
free_page(xmit_page);
return 0;
}
@@ -3320,7 +2880,7 @@ startup(struct e100_serial * info)
info->flags |= ASYNC_INITIALIZED;
- restore_flags(flags);
+ local_irq_restore(flags);
return 0;
}
@@ -3371,8 +2931,7 @@ shutdown(struct e100_serial * info)
info->irq);
#endif
- save_flags(flags);
- cli(); /* Disable interrupts */
+ local_irq_save(flags);
if (info->xmit.buf) {
free_page((unsigned long)info->xmit.buf);
@@ -3396,7 +2955,7 @@ shutdown(struct e100_serial * info)
set_bit(TTY_IO_ERROR, &info->tty->flags);
info->flags &= ~ASYNC_INITIALIZED;
- restore_flags(flags);
+ local_irq_restore(flags);
}
@@ -3454,7 +3013,6 @@ change_speed(struct e100_serial *info)
DBAUD(printk("using external baudrate: %lu\n", CONFIG_ETRAX_EXTERN_PB6CLK_FREQ/8));
info->baud = CONFIG_ETRAX_EXTERN_PB6CLK_FREQ/8;
}
- }
#endif
else
{
@@ -3488,8 +3046,7 @@ change_speed(struct e100_serial *info)
#ifndef CONFIG_SVINTO_SIM
/* start with default settings and then fill in changes */
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* 8 bit, no/even parity */
info->rx_ctrl &= ~(IO_MASK(R_SERIAL0_REC_CTRL, rec_bitnr) |
IO_MASK(R_SERIAL0_REC_CTRL, rec_par_en) |
@@ -3553,7 +3110,7 @@ change_speed(struct e100_serial *info)
}
*((unsigned long *)&info->port[REG_XOFF]) = xoff;
- restore_flags(flags);
+ local_irq_restore(flags);
#endif /* !CONFIG_SVINTO_SIM */
update_char_time(info);
@@ -3581,13 +3138,12 @@ rs_flush_chars(struct tty_struct *tty)
/* this protection might not exactly be necessary here */
- save_flags(flags);
- cli();
+ local_irq_save(flags);
start_transmit(info);
- restore_flags(flags);
+ local_irq_restore(flags);
}
-static int rs_raw_write(struct tty_struct * tty, int from_user,
+static int rs_raw_write(struct tty_struct *tty,
const unsigned char *buf, int count)
{
int c, ret = 0;
@@ -3610,53 +3166,19 @@ static int rs_raw_write(struct tty_struct * tty, int from_user,
SIMCOUT(buf, count);
return count;
#endif
- save_flags(flags);
+ local_save_flags(flags);
DFLOW(DEBUG_LOG(info->line, "write count %i ", count));
DFLOW(DEBUG_LOG(info->line, "ldisc %i\n", tty->ldisc.chars_in_buffer(tty)));
- /* the cli/restore_flags pairs below are needed because the
- * DMA interrupt handler moves the info->xmit values. the memcpy
- * needs to be in the critical region unfortunately, because we
- * need to read xmit values, memcpy, write xmit values in one
- * atomic operation... this could perhaps be avoided by more clever
- * design.
+ /* The local_irq_disable/restore_flags pairs below are needed
+ * because the DMA interrupt handler moves the info->xmit values.
+ * the memcpy needs to be in the critical region unfortunately,
+ * because we need to read xmit values, memcpy, write xmit values
+ * in one atomic operation... this could perhaps be avoided by
+ * more clever design.
*/
- if (from_user) {
- mutex_lock(&tmp_buf_mutex);
- while (1) {
- int c1;
- c = CIRC_SPACE_TO_END(info->xmit.head,
- info->xmit.tail,
- SERIAL_XMIT_SIZE);
- if (count < c)
- c = count;
- if (c <= 0)
- break;
-
- c -= copy_from_user(tmp_buf, buf, c);
- if (!c) {
- if (!ret)
- ret = -EFAULT;
- break;
- }
- cli();
- c1 = CIRC_SPACE_TO_END(info->xmit.head,
- info->xmit.tail,
- SERIAL_XMIT_SIZE);
- if (c1 < c)
- c = c1;
- memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c);
- info->xmit.head = ((info->xmit.head + c) &
- (SERIAL_XMIT_SIZE-1));
- restore_flags(flags);
- buf += c;
- count -= c;
- ret += c;
- }
- mutex_unlock(&tmp_buf_mutex);
- } else {
- cli();
+ local_irq_disable();
while (count) {
c = CIRC_SPACE_TO_END(info->xmit.head,
info->xmit.tail,
@@ -3674,8 +3196,7 @@ static int rs_raw_write(struct tty_struct * tty, int from_user,
count -= c;
ret += c;
}
- restore_flags(flags);
- }
+ local_irq_restore(flags);
/* enable transmitter if not running, unless the tty is stopped
* this does not need IRQ protection since if tr_running == 0
@@ -3694,7 +3215,7 @@ static int rs_raw_write(struct tty_struct * tty, int from_user,
} /* raw_raw_write() */
static int
-rs_write(struct tty_struct * tty, int from_user,
+rs_write(struct tty_struct *tty,
const unsigned char *buf, int count)
{
#if defined(CONFIG_ETRAX_RS485)
@@ -3721,7 +3242,7 @@ rs_write(struct tty_struct * tty, int from_user,
}
#endif /* CONFIG_ETRAX_RS485 */
- count = rs_raw_write(tty, from_user, buf, count);
+ count = rs_raw_write(tty, buf, count);
#if defined(CONFIG_ETRAX_RS485)
if (info->rs485.enabled)
@@ -3789,10 +3310,9 @@ rs_flush_buffer(struct tty_struct *tty)
struct e100_serial *info = (struct e100_serial *)tty->driver_data;
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
info->xmit.head = info->xmit.tail = 0;
- restore_flags(flags);
+ local_irq_restore(flags);
tty_wakeup(tty);
}
@@ -3810,7 +3330,7 @@ static void rs_send_xchar(struct tty_struct *tty, char ch)
{
struct e100_serial *info = (struct e100_serial *)tty->driver_data;
unsigned long flags;
- save_flags(flags); cli();
+ local_irq_save(flags);
if (info->uses_dma_out) {
/* Put the DMA on hold and disable the channel */
*info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, hold);
@@ -3827,7 +3347,7 @@ static void rs_send_xchar(struct tty_struct *tty, char ch)
DFLOW(DEBUG_LOG(info->line, "rs_send_xchar 0x%02X\n", ch));
info->x_char = ch;
e100_enable_serial_tx_ready_irq(info);
- restore_flags(flags);
+ local_irq_restore(flags);
}
/*
@@ -4039,21 +3559,61 @@ char *get_control_state_str(int MLines, char *s)
}
#endif
+static void
+rs_break(struct tty_struct *tty, int break_state)
+{
+ struct e100_serial *info = (struct e100_serial *)tty->driver_data;
+ unsigned long flags;
+
+ if (!info->port)
+ return;
+
+ local_irq_save(flags);
+ if (break_state == -1) {
+ /* Go to manual mode and set the txd pin to 0 */
+ /* Clear bit 7 (txd) and 6 (tr_enable) */
+ info->tx_ctrl &= 0x3F;
+ } else {
+ /* Set bit 7 (txd) and 6 (tr_enable) */
+ info->tx_ctrl |= (0x80 | 0x40);
+ }
+ info->port[REG_TR_CTRL] = info->tx_ctrl;
+ local_irq_restore(flags);
+}
+
static int
-get_modem_info(struct e100_serial * info, unsigned int *value)
+rs_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
{
- unsigned int result;
- /* Polarity isn't verified */
-#if 0 /*def SERIAL_DEBUG_IO */
+ struct e100_serial *info = (struct e100_serial *)tty->driver_data;
- printk("get_modem_info: RTS: %i DTR: %i CD: %i RI: %i DSR: %i CTS: %i\n",
- E100_RTS_GET(info),
- E100_DTR_GET(info),
- E100_CD_GET(info),
- E100_RI_GET(info),
- E100_DSR_GET(info),
- E100_CTS_GET(info));
-#endif
+ if (clear & TIOCM_RTS)
+ e100_rts(info, 0);
+ if (clear & TIOCM_DTR)
+ e100_dtr(info, 0);
+ /* Handle FEMALE behaviour */
+ if (clear & TIOCM_RI)
+ e100_ri_out(info, 0);
+ if (clear & TIOCM_CD)
+ e100_cd_out(info, 0);
+
+ if (set & TIOCM_RTS)
+ e100_rts(info, 1);
+ if (set & TIOCM_DTR)
+ e100_dtr(info, 1);
+ /* Handle FEMALE behaviour */
+ if (set & TIOCM_RI)
+ e100_ri_out(info, 1);
+ if (set & TIOCM_CD)
+ e100_cd_out(info, 1);
+ return 0;
+}
+
+static int
+rs_tiocmget(struct tty_struct *tty, struct file *file)
+{
+ struct e100_serial *info = (struct e100_serial *)tty->driver_data;
+ unsigned int result;
result =
(!E100_RTS_GET(info) ? TIOCM_RTS : 0)
@@ -4064,95 +3624,20 @@ get_modem_info(struct e100_serial * info, unsigned int *value)
| (!E100_CTS_GET(info) ? TIOCM_CTS : 0);
#ifdef SERIAL_DEBUG_IO
- printk("e100ser: modem state: %i 0x%08X\n", result, result);
+ printk(KERN_DEBUG "ser%i: modem state: %i 0x%08X\n",
+ info->line, result, result);
{
char s[100];
get_control_state_str(result, s);
- printk("state: %s\n", s);
+ printk(KERN_DEBUG "state: %s\n", s);
}
#endif
- if (copy_to_user(value, &result, sizeof(int)))
- return -EFAULT;
- return 0;
-}
-
-
-static int
-set_modem_info(struct e100_serial * info, unsigned int cmd,
- unsigned int *value)
-{
- unsigned int arg;
+ return result;
- if (copy_from_user(&arg, value, sizeof(int)))
- return -EFAULT;
-
- switch (cmd) {
- case TIOCMBIS:
- if (arg & TIOCM_RTS) {
- e100_rts(info, 1);
- }
- if (arg & TIOCM_DTR) {
- e100_dtr(info, 1);
- }
- /* Handle FEMALE behaviour */
- if (arg & TIOCM_RI) {
- e100_ri_out(info, 1);
- }
- if (arg & TIOCM_CD) {
- e100_cd_out(info, 1);
- }
- break;
- case TIOCMBIC:
- if (arg & TIOCM_RTS) {
- e100_rts(info, 0);
- }
- if (arg & TIOCM_DTR) {
- e100_dtr(info, 0);
- }
- /* Handle FEMALE behaviour */
- if (arg & TIOCM_RI) {
- e100_ri_out(info, 0);
- }
- if (arg & TIOCM_CD) {
- e100_cd_out(info, 0);
- }
- break;
- case TIOCMSET:
- e100_rts(info, arg & TIOCM_RTS);
- e100_dtr(info, arg & TIOCM_DTR);
- /* Handle FEMALE behaviour */
- e100_ri_out(info, arg & TIOCM_RI);
- e100_cd_out(info, arg & TIOCM_CD);
- break;
- default:
- return -EINVAL;
- }
- return 0;
}
-static void
-rs_break(struct tty_struct *tty, int break_state)
-{
- struct e100_serial * info = (struct e100_serial *)tty->driver_data;
- unsigned long flags;
-
- if (!info->port)
- return;
-
- save_flags(flags);
- cli();
- if (break_state == -1) {
- /* Go to manual mode and set the txd pin to 0 */
- info->tx_ctrl &= 0x3F; /* Clear bit 7 (txd) and 6 (tr_enable) */
- } else {
- info->tx_ctrl |= (0x80 | 0x40); /* Set bit 7 (txd) and 6 (tr_enable) */
- }
- info->port[REG_TR_CTRL] = info->tx_ctrl;
- restore_flags(flags);
-}
-
static int
rs_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
@@ -4167,49 +3652,45 @@ rs_ioctl(struct tty_struct *tty, struct file * file,
}
switch (cmd) {
- case TIOCMGET:
- return get_modem_info(info, (unsigned int *) arg);
- case TIOCMBIS:
- case TIOCMBIC:
- case TIOCMSET:
- return set_modem_info(info, cmd, (unsigned int *) arg);
- case TIOCGSERIAL:
- return get_serial_info(info,
- (struct serial_struct *) arg);
- case TIOCSSERIAL:
- return set_serial_info(info,
- (struct serial_struct *) arg);
- case TIOCSERGETLSR: /* Get line status register */
- return get_lsr_info(info, (unsigned int *) arg);
-
- case TIOCSERGSTRUCT:
- if (copy_to_user((struct e100_serial *) arg,
- info, sizeof(struct e100_serial)))
- return -EFAULT;
- return 0;
+ case TIOCGSERIAL:
+ return get_serial_info(info,
+ (struct serial_struct *) arg);
+ case TIOCSSERIAL:
+ return set_serial_info(info,
+ (struct serial_struct *) arg);
+ case TIOCSERGETLSR: /* Get line status register */
+ return get_lsr_info(info, (unsigned int *) arg);
+
+ case TIOCSERGSTRUCT:
+ if (copy_to_user((struct e100_serial *) arg,
+ info, sizeof(struct e100_serial)))
+ return -EFAULT;
+ return 0;
#if defined(CONFIG_ETRAX_RS485)
- case TIOCSERSETRS485:
- {
- struct rs485_control rs485ctrl;
- if (copy_from_user(&rs485ctrl, (struct rs485_control*)arg, sizeof(rs485ctrl)))
- return -EFAULT;
+ case TIOCSERSETRS485:
+ {
+ struct rs485_control rs485ctrl;
+ if (copy_from_user(&rs485ctrl, (struct rs485_control *)arg,
+ sizeof(rs485ctrl)))
+ return -EFAULT;
- return e100_enable_rs485(tty, &rs485ctrl);
- }
+ return e100_enable_rs485(tty, &rs485ctrl);
+ }
- case TIOCSERWRRS485:
- {
- struct rs485_write rs485wr;
- if (copy_from_user(&rs485wr, (struct rs485_write*)arg, sizeof(rs485wr)))
- return -EFAULT;
+ case TIOCSERWRRS485:
+ {
+ struct rs485_write rs485wr;
+ if (copy_from_user(&rs485wr, (struct rs485_write *)arg,
+ sizeof(rs485wr)))
+ return -EFAULT;
- return e100_write_rs485(tty, 1, rs485wr.outc, rs485wr.outc_size);
- }
+ return e100_write_rs485(tty, rs485wr.outc, rs485wr.outc_size);
+ }
#endif
- default:
- return -ENOIOCTLCMD;
+ default:
+ return -ENOIOCTLCMD;
}
return 0;
}
@@ -4234,46 +3715,6 @@ rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
}
-/* In debugport.c - register a console write function that uses the normal
- * serial driver
- */
-typedef int (*debugport_write_function)(int i, const char *buf, unsigned int len);
-
-extern debugport_write_function debug_write_function;
-
-static int rs_debug_write_function(int i, const char *buf, unsigned int len)
-{
- int cnt;
- int written = 0;
- struct tty_struct *tty;
- static int recurse_cnt = 0;
-
- tty = rs_table[i].tty;
- if (tty) {
- unsigned long flags;
- if (recurse_cnt > 5) /* We skip this debug output */
- return 1;
-
- local_irq_save(flags);
- recurse_cnt++;
- local_irq_restore(flags);
- do {
- cnt = rs_write(tty, 0, buf + written, len);
- if (cnt >= 0) {
- written += cnt;
- buf += cnt;
- len -= cnt;
- } else
- len = cnt;
- } while(len > 0);
- local_irq_save(flags);
- recurse_cnt--;
- local_irq_restore(flags);
- return 1;
- }
- return 0;
-}
-
/*
* ------------------------------------------------------------
* rs_close()
@@ -4295,11 +3736,10 @@ rs_close(struct tty_struct *tty, struct file * filp)
/* interrupts are disabled for this entire function */
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if (tty_hung_up_p(filp)) {
- restore_flags(flags);
+ local_irq_restore(flags);
return;
}
@@ -4326,7 +3766,7 @@ rs_close(struct tty_struct *tty, struct file * filp)
info->count = 0;
}
if (info->count) {
- restore_flags(flags);
+ local_irq_restore(flags);
return;
}
info->flags |= ASYNC_CLOSING;
@@ -4380,7 +3820,7 @@ rs_close(struct tty_struct *tty, struct file * filp)
}
info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
wake_up_interruptible(&info->close_wait);
- restore_flags(flags);
+ local_irq_restore(flags);
/* port closed */
@@ -4402,6 +3842,28 @@ rs_close(struct tty_struct *tty, struct file * filp)
#endif
}
#endif
+
+ /*
+ * Release any allocated DMA irq's.
+ */
+ if (info->dma_in_enabled) {
+ free_irq(info->dma_in_irq_nbr, info);
+ cris_free_dma(info->dma_in_nbr, info->dma_in_irq_description);
+ info->uses_dma_in = 0;
+#ifdef SERIAL_DEBUG_OPEN
+ printk(KERN_DEBUG "DMA irq '%s' freed\n",
+ info->dma_in_irq_description);
+#endif
+ }
+ if (info->dma_out_enabled) {
+ free_irq(info->dma_out_irq_nbr, info);
+ cris_free_dma(info->dma_out_nbr, info->dma_out_irq_description);
+ info->uses_dma_out = 0;
+#ifdef SERIAL_DEBUG_OPEN
+ printk(KERN_DEBUG "DMA irq '%s' freed\n",
+ info->dma_out_irq_description);
+#endif
+ }
}
/*
@@ -4476,8 +3938,8 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
*/
if (tty_hung_up_p(filp) ||
(info->flags & ASYNC_CLOSING)) {
- if (info->flags & ASYNC_CLOSING)
- interruptible_sleep_on(&info->close_wait);
+ wait_event_interruptible(info->close_wait,
+ !(info->flags & ASYNC_CLOSING));
#ifdef SERIAL_DO_RESTART
if (info->flags & ASYNC_HUP_NOTIFY)
return -EAGAIN;
@@ -4515,21 +3977,19 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
printk("block_til_ready before block: ttyS%d, count = %d\n",
info->line, info->count);
#endif
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if (!tty_hung_up_p(filp)) {
extra_count++;
info->count--;
}
- restore_flags(flags);
+ local_irq_restore(flags);
info->blocked_open++;
while (1) {
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* assert RTS and DTR */
e100_rts(info, 1);
e100_dtr(info, 1);
- restore_flags(flags);
+ local_irq_restore(flags);
set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
!(info->flags & ASYNC_INITIALIZED)) {
@@ -4571,6 +4031,19 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
return 0;
}
+static void
+deinit_port(struct e100_serial *info)
+{
+ if (info->dma_out_enabled) {
+ cris_free_dma(info->dma_out_nbr, info->dma_out_irq_description);
+ free_irq(info->dma_out_irq_nbr, info);
+ }
+ if (info->dma_in_enabled) {
+ cris_free_dma(info->dma_in_nbr, info->dma_in_irq_description);
+ free_irq(info->dma_in_irq_nbr, info);
+ }
+}
+
/*
* This routine is called whenever a serial port is opened.
* It performs the serial-specific initialization for the tty structure.
@@ -4581,9 +4054,9 @@ rs_open(struct tty_struct *tty, struct file * filp)
struct e100_serial *info;
int retval, line;
unsigned long page;
+ int allocated_resources = 0;
/* find which port we want to open */
-
line = tty->index;
if (line < 0 || line >= NR_PORTS)
@@ -4623,8 +4096,8 @@ rs_open(struct tty_struct *tty, struct file * filp)
*/
if (tty_hung_up_p(filp) ||
(info->flags & ASYNC_CLOSING)) {
- if (info->flags & ASYNC_CLOSING)
- interruptible_sleep_on(&info->close_wait);
+ wait_event_interruptible(info->close_wait,
+ !(info->flags & ASYNC_CLOSING));
#ifdef SERIAL_DO_RESTART
return ((info->flags & ASYNC_HUP_NOTIFY) ?
-EAGAIN : -ERESTARTSYS);
@@ -4634,12 +4107,85 @@ rs_open(struct tty_struct *tty, struct file * filp)
}
/*
+ * If DMA is enabled try to allocate the irq's.
+ */
+ if (info->count == 1) {
+ allocated_resources = 1;
+ if (info->dma_in_enabled) {
+ if (request_irq(info->dma_in_irq_nbr,
+ rec_interrupt,
+ info->dma_in_irq_flags,
+ info->dma_in_irq_description,
+ info)) {
+ printk(KERN_WARNING "DMA irq '%s' busy; "
+ "falling back to non-DMA mode\n",
+ info->dma_in_irq_description);
+ /* Make sure we never try to use DMA in */
+ /* for the port again. */
+ info->dma_in_enabled = 0;
+ } else if (cris_request_dma(info->dma_in_nbr,
+ info->dma_in_irq_description,
+ DMA_VERBOSE_ON_ERROR,
+ info->dma_owner)) {
+ free_irq(info->dma_in_irq_nbr, info);
+ printk(KERN_WARNING "DMA '%s' busy; "
+ "falling back to non-DMA mode\n",
+ info->dma_in_irq_description);
+ /* Make sure we never try to use DMA in */
+ /* for the port again. */
+ info->dma_in_enabled = 0;
+ }
+#ifdef SERIAL_DEBUG_OPEN
+ else
+ printk(KERN_DEBUG "DMA irq '%s' allocated\n",
+ info->dma_in_irq_description);
+#endif
+ }
+ if (info->dma_out_enabled) {
+ if (request_irq(info->dma_out_irq_nbr,
+ tr_interrupt,
+ info->dma_out_irq_flags,
+ info->dma_out_irq_description,
+ info)) {
+ printk(KERN_WARNING "DMA irq '%s' busy; "
+ "falling back to non-DMA mode\n",
+ info->dma_out_irq_description);
+ /* Make sure we never try to use DMA out */
+ /* for the port again. */
+ info->dma_out_enabled = 0;
+ } else if (cris_request_dma(info->dma_out_nbr,
+ info->dma_out_irq_description,
+ DMA_VERBOSE_ON_ERROR,
+ info->dma_owner)) {
+ free_irq(info->dma_out_irq_nbr, info);
+ printk(KERN_WARNING "DMA '%s' busy; "
+ "falling back to non-DMA mode\n",
+ info->dma_out_irq_description);
+ /* Make sure we never try to use DMA out */
+ /* for the port again. */
+ info->dma_out_enabled = 0;
+ }
+#ifdef SERIAL_DEBUG_OPEN
+ else
+ printk(KERN_DEBUG "DMA irq '%s' allocated\n",
+ info->dma_out_irq_description);
+#endif
+ }
+ }
+
+ /*
* Start up the serial port
*/
retval = startup(info);
- if (retval)
+ if (retval) {
+ if (allocated_resources)
+ deinit_port(info);
+
+ /* FIXME Decrease count info->count here too? */
return retval;
+ }
+
retval = block_til_ready(tty, filp, info);
if (retval) {
@@ -4647,6 +4193,9 @@ rs_open(struct tty_struct *tty, struct file * filp)
printk("rs_open returning after block_til_ready with %d\n",
retval);
#endif
+ if (allocated_resources)
+ deinit_port(info);
+
return retval;
}
@@ -4836,6 +4385,8 @@ static const struct tty_operations rs_ops = {
.send_xchar = rs_send_xchar,
.wait_until_sent = rs_wait_until_sent,
.read_proc = rs_read_proc,
+ .tiocmget = rs_tiocmget,
+ .tiocmset = rs_tiocmset
};
static int __init
@@ -4853,9 +4404,27 @@ rs_init(void)
/* Setup the timed flush handler system */
#if !defined(CONFIG_ETRAX_SERIAL_FAST_TIMER)
- init_timer(&flush_timer);
- flush_timer.function = timed_flush_handler;
- mod_timer(&flush_timer, jiffies + CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS);
+ setup_timer(&flush_timer, timed_flush_handler, 0);
+ mod_timer(&flush_timer, jiffies + 5);
+#endif
+
+#if defined(CONFIG_ETRAX_RS485)
+#if defined(CONFIG_ETRAX_RS485_ON_PA)
+ if (cris_io_interface_allocate_pins(if_ser0, 'a', rs485_pa_bit,
+ rs485_pa_bit)) {
+ printk(KERN_CRIT "ETRAX100LX serial: Could not allocate "
+ "RS485 pin\n");
+ return -EBUSY;
+ }
+#endif
+#if defined(CONFIG_ETRAX_RS485_ON_PORT_G)
+ if (cris_io_interface_allocate_pins(if_ser0, 'g', rs485_pa_bit,
+ rs485_port_g_bit)) {
+ printk(KERN_CRIT "ETRAX100LX serial: Could not allocate "
+ "RS485 pin\n");
+ return -EBUSY;
+ }
+#endif
#endif
/* Initialize the tty_driver structure */
@@ -4882,6 +4451,16 @@ rs_init(void)
/* do some initializing for the separate ports */
for (i = 0, info = rs_table; i < NR_PORTS; i++,info++) {
+ if (info->enabled) {
+ if (cris_request_io_interface(info->io_if,
+ info->io_if_description)) {
+ printk(KERN_CRIT "ETRAX100LX async serial: "
+ "Could not allocate IO pins for "
+ "%s, port %d\n",
+ info->io_if_description, i);
+ info->enabled = 0;
+ }
+ }
info->uses_dma_in = 0;
info->uses_dma_out = 0;
info->line = i;
@@ -4915,7 +4494,7 @@ rs_init(void)
info->rs485.delay_rts_before_send = 0;
info->rs485.enabled = 0;
#endif
- INIT_WORK(&info->work, do_softint, info);
+ INIT_WORK(&info->work, do_softint);
if (info->enabled) {
printk(KERN_INFO "%s%d at 0x%x is a builtin UART with DMA\n",
@@ -4933,64 +4512,17 @@ rs_init(void)
#endif
#ifndef CONFIG_SVINTO_SIM
+#ifndef CONFIG_ETRAX_KGDB
/* Not needed in simulator. May only complicate stuff. */
/* hook the irq's for DMA channel 6 and 7, serial output and input, and some more... */
- if (request_irq(SERIAL_IRQ_NBR, ser_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial ", NULL))
- panic("irq8");
-
-#ifdef CONFIG_ETRAX_SERIAL_PORT0
-#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA6_OUT
- if (request_irq(SER0_DMA_TX_IRQ_NBR, tr_interrupt, IRQF_DISABLED, "serial 0 dma tr", NULL))
- panic("irq22");
-#endif
-#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA7_IN
- if (request_irq(SER0_DMA_RX_IRQ_NBR, rec_interrupt, IRQF_DISABLED, "serial 0 dma rec", NULL))
- panic("irq23");
-#endif
-#endif
-
-#ifdef CONFIG_ETRAX_SERIAL_PORT1
-#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA8_OUT
- if (request_irq(SER1_DMA_TX_IRQ_NBR, tr_interrupt, IRQF_DISABLED, "serial 1 dma tr", NULL))
- panic("irq24");
-#endif
-#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA9_IN
- if (request_irq(SER1_DMA_RX_IRQ_NBR, rec_interrupt, IRQF_DISABLED, "serial 1 dma rec", NULL))
- panic("irq25");
-#endif
-#endif
-#ifdef CONFIG_ETRAX_SERIAL_PORT2
- /* DMA Shared with par0 (and SCSI0 and ATA) */
-#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA2_OUT
- if (request_irq(SER2_DMA_TX_IRQ_NBR, tr_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial 2 dma tr", NULL))
- panic("irq18");
-#endif
-#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA3_IN
- if (request_irq(SER2_DMA_RX_IRQ_NBR, rec_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial 2 dma rec", NULL))
- panic("irq19");
-#endif
-#endif
-#ifdef CONFIG_ETRAX_SERIAL_PORT3
- /* DMA Shared with par1 (and SCSI1 and Extern DMA 0) */
-#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA4_OUT
- if (request_irq(SER3_DMA_TX_IRQ_NBR, tr_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial 3 dma tr", NULL))
- panic("irq20");
-#endif
-#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA5_IN
- if (request_irq(SER3_DMA_RX_IRQ_NBR, rec_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial 3 dma rec", NULL))
- panic("irq21");
-#endif
-#endif
+ if (request_irq(SERIAL_IRQ_NBR, ser_interrupt,
+ IRQF_SHARED | IRQF_DISABLED, "serial ", driver))
+ panic("%s: Failed to request irq8", __FUNCTION__);
-#ifdef CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST
- if (request_irq(TIMER1_IRQ_NBR, timeout_interrupt, IRQF_SHARED | IRQF_DISABLED,
- "fast serial dma timeout", NULL)) {
- printk(KERN_CRIT "err: timer1 irq\n");
- }
#endif
#endif /* CONFIG_SVINTO_SIM */
- debug_write_function = rs_debug_write_function;
+
return 0;
}
diff --git a/drivers/serial/crisv10.h b/drivers/serial/crisv10.h
new file mode 100644
index 000000000000..ccd0f32b7372
--- /dev/null
+++ b/drivers/serial/crisv10.h
@@ -0,0 +1,146 @@
+/*
+ * serial.h: Arch-dep definitions for the Etrax100 serial driver.
+ *
+ * Copyright (C) 1998-2007 Axis Communications AB
+ */
+
+#ifndef _ETRAX_SERIAL_H
+#define _ETRAX_SERIAL_H
+
+#include <linux/circ_buf.h>
+#include <asm/termios.h>
+#include <asm/dma.h>
+#include <asm/arch/io_interface_mux.h>
+
+/* Software state per channel */
+
+#ifdef __KERNEL__
+/*
+ * This is our internal structure for each serial port's state.
+ *
+ * Many fields are paralleled by the structure used by the serial_struct
+ * structure.
+ *
+ * For definitions of the flags field, see tty.h
+ */
+
+#define SERIAL_RECV_DESCRIPTORS 8
+
+struct etrax_recv_buffer {
+ struct etrax_recv_buffer *next;
+ unsigned short length;
+ unsigned char error;
+ unsigned char pad;
+
+ unsigned char buffer[0];
+};
+
+struct e100_serial {
+ int baud;
+ volatile u8 *port; /* R_SERIALx_CTRL */
+ u32 irq; /* bitnr in R_IRQ_MASK2 for dmaX_descr */
+
+ /* Output registers */
+ volatile u8 *oclrintradr; /* adr to R_DMA_CHx_CLR_INTR */
+ volatile u32 *ofirstadr; /* adr to R_DMA_CHx_FIRST */
+ volatile u8 *ocmdadr; /* adr to R_DMA_CHx_CMD */
+ const volatile u8 *ostatusadr; /* adr to R_DMA_CHx_STATUS */
+
+ /* Input registers */
+ volatile u8 *iclrintradr; /* adr to R_DMA_CHx_CLR_INTR */
+ volatile u32 *ifirstadr; /* adr to R_DMA_CHx_FIRST */
+ volatile u8 *icmdadr; /* adr to R_DMA_CHx_CMD */
+ volatile u32 *idescradr; /* adr to R_DMA_CHx_DESCR */
+
+ int flags; /* defined in tty.h */
+
+ u8 rx_ctrl; /* shadow for R_SERIALx_REC_CTRL */
+ u8 tx_ctrl; /* shadow for R_SERIALx_TR_CTRL */
+ u8 iseteop; /* bit number for R_SET_EOP for the input dma */
+ int enabled; /* Set to 1 if the port is enabled in HW config */
+
+ u8 dma_out_enabled; /* Set to 1 if DMA should be used */
+ u8 dma_in_enabled; /* Set to 1 if DMA should be used */
+
+ /* end of fields defined in rs_table[] in .c-file */
+ int dma_owner;
+ unsigned int dma_in_nbr;
+ unsigned int dma_out_nbr;
+ unsigned int dma_in_irq_nbr;
+ unsigned int dma_out_irq_nbr;
+ unsigned long dma_in_irq_flags;
+ unsigned long dma_out_irq_flags;
+ char *dma_in_irq_description;
+ char *dma_out_irq_description;
+
+ enum cris_io_interface io_if;
+ char *io_if_description;
+
+ u8 uses_dma_in; /* Set to 1 if DMA is used */
+ u8 uses_dma_out; /* Set to 1 if DMA is used */
+ u8 forced_eop; /* a fifo eop has been forced */
+ int baud_base; /* For special baudrates */
+ int custom_divisor; /* For special baudrates */
+ struct etrax_dma_descr tr_descr;
+ struct etrax_dma_descr rec_descr[SERIAL_RECV_DESCRIPTORS];
+ int cur_rec_descr;
+
+ volatile int tr_running; /* 1 if output is running */
+
+ struct tty_struct *tty;
+ int read_status_mask;
+ int ignore_status_mask;
+ int x_char; /* xon/xoff character */
+ int close_delay;
+ unsigned short closing_wait;
+ unsigned short closing_wait2;
+ unsigned long event;
+ unsigned long last_active;
+ int line;
+ int type; /* PORT_ETRAX */
+ int count; /* # of fd on device */
+ int blocked_open; /* # of blocked opens */
+ struct circ_buf xmit;
+ struct etrax_recv_buffer *first_recv_buffer;
+ struct etrax_recv_buffer *last_recv_buffer;
+ unsigned int recv_cnt;
+ unsigned int max_recv_cnt;
+
+ struct work_struct work;
+ struct async_icount icount; /* error-statistics etc.*/
+ struct ktermios normal_termios;
+ struct ktermios callout_termios;
+ wait_queue_head_t open_wait;
+ wait_queue_head_t close_wait;
+
+ unsigned long char_time_usec; /* The time for 1 char, in usecs */
+ unsigned long flush_time_usec; /* How often we should flush */
+ unsigned long last_tx_active_usec; /* Last tx usec in the jiffies */
+ unsigned long last_tx_active; /* Last tx time in jiffies */
+ unsigned long last_rx_active_usec; /* Last rx usec in the jiffies */
+ unsigned long last_rx_active; /* Last rx time in jiffies */
+
+ int break_detected_cnt;
+ int errorcode;
+
+#ifdef CONFIG_ETRAX_RS485
+ struct rs485_control rs485; /* RS-485 support */
+#endif
+};
+
+/* this PORT is not in the standard serial.h. it's not actually used for
+ * anything since we only have one type of async serial-port anyway in this
+ * system.
+ */
+
+#define PORT_ETRAX 1
+
+/*
+ * Events are used to schedule things to happen at timer-interrupt
+ * time, instead of at rs interrupt time.
+ */
+#define RS_EVENT_WRITE_WAKEUP 0
+
+#endif /* __KERNEL__ */
+
+#endif /* !_ETRAX_SERIAL_H */
diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c
index 281f23a371b2..94ec66372508 100644
--- a/drivers/serial/jsm/jsm_tty.c
+++ b/drivers/serial/jsm/jsm_tty.c
@@ -500,13 +500,11 @@ void jsm_input(struct jsm_channel *ch)
{
struct jsm_board *bd;
struct tty_struct *tp;
- struct tty_ldisc *ld;
u32 rmask;
u16 head;
u16 tail;
int data_len;
unsigned long lock_flags;
- int flip_len = 0;
int len = 0;
int n = 0;
int s = 0;
@@ -574,45 +572,13 @@ void jsm_input(struct jsm_channel *ch)
jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "start 2\n");
- /*
- * If the rxbuf is empty and we are not throttled, put as much
- * as we can directly into the linux TTY buffer.
- *
- */
- flip_len = TTY_FLIPBUF_SIZE;
-
- len = min(data_len, flip_len);
- len = min(len, (N_TTY_BUF_SIZE - 1) - tp->read_cnt);
- ld = tty_ldisc_ref(tp);
-
- /*
- * If we were unable to get a reference to the ld,
- * don't flush our buffer, and act like the ld doesn't
- * have any space to put the data right now.
- */
- if (!ld) {
- len = 0;
- } else {
- /*
- * If ld doesn't have a pointer to a receive_buf function,
- * flush the data, then act like the ld doesn't have any
- * space to put the data right now.
- */
- if (!ld->receive_buf) {
- ch->ch_r_head = ch->ch_r_tail;
- len = 0;
- }
- }
-
- if (len <= 0) {
+ if (data_len <= 0) {
spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "jsm_input 1\n");
- if (ld)
- tty_ldisc_deref(ld);
return;
}
- len = tty_buffer_request_room(tp, len);
+ len = tty_buffer_request_room(tp, data_len);
n = len;
/*
@@ -647,7 +613,7 @@ void jsm_input(struct jsm_channel *ch)
else if (*(ch->ch_equeue +tail +i) & UART_LSR_FE)
tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_FRAME);
else
- tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_NORMAL);
+ tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_NORMAL);
}
} else {
tty_insert_flip_string(tp, ch->ch_rqueue + tail, s) ;
@@ -666,9 +632,6 @@ void jsm_input(struct jsm_channel *ch)
/* Tell the tty layer its okay to "eat" the data now */
tty_flip_buffer_push(tp);
- if (ld)
- tty_ldisc_deref(ld);
-
jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "finish\n");
}
diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c
index 6e09c8b395e8..348ee2c19b58 100644
--- a/drivers/serial/m32r_sio.c
+++ b/drivers/serial/m32r_sio.c
@@ -539,7 +539,7 @@ static void serial_do_unlink(struct irq_info *i, struct uart_sio_port *up)
static int serial_link_irq_chain(struct uart_sio_port *up)
{
struct irq_info *i = irq_lists + up->port.irq;
- int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0;
+ int ret, irq_flags = 0;
spin_lock_irq(&i->lock);
diff --git a/drivers/serial/m32r_sio.h b/drivers/serial/m32r_sio.h
index 849f1b2c2531..e9b7e11793b1 100644
--- a/drivers/serial/m32r_sio.h
+++ b/drivers/serial/m32r_sio.h
@@ -46,9 +46,3 @@ struct old_serial_port {
#define PROBE_ANY (~0)
#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
-
-#ifdef CONFIG_SERIAL_SIO_SHARE_IRQ
-#define M32R_SIO_SHARE_IRQS 1
-#else
-#define M32R_SIO_SHARE_IRQS 0
-#endif
diff --git a/drivers/serial/mcf.c b/drivers/serial/mcf.c
new file mode 100644
index 000000000000..a7d4360ea7df
--- /dev/null
+++ b/drivers/serial/mcf.c
@@ -0,0 +1,653 @@
+/****************************************************************************/
+
+/*
+ * mcf.c -- Freescale ColdFire UART driver
+ *
+ * (C) Copyright 2003-2007, Greg Ungerer <gerg@snapgear.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+/****************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/console.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/io.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfuart.h>
+#include <asm/nettel.h>
+
+/****************************************************************************/
+
+/*
+ * Some boards implement the DTR/DCD lines using GPIO lines, most
+ * don't. Dummy out the access macros for those that don't. Those
+ * that do should define these macros somewhere in there board
+ * specific inlude files.
+ */
+#if !defined(mcf_getppdcd)
+#define mcf_getppdcd(p) (1)
+#endif
+#if !defined(mcf_getppdtr)
+#define mcf_getppdtr(p) (1)
+#endif
+#if !defined(mcf_setppdtr)
+#define mcf_setppdtr(p, v) do { } while (0)
+#endif
+
+/****************************************************************************/
+
+/*
+ * Local per-uart structure.
+ */
+struct mcf_uart {
+ struct uart_port port;
+ unsigned int sigs; /* Local copy of line sigs */
+ unsigned char imr; /* Local IMR mirror */
+};
+
+/****************************************************************************/
+
+static unsigned int mcf_tx_empty(struct uart_port *port)
+{
+ return (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXEMPTY) ?
+ TIOCSER_TEMT : 0;
+}
+
+/****************************************************************************/
+
+static unsigned int mcf_get_mctrl(struct uart_port *port)
+{
+ struct mcf_uart *pp = (struct mcf_uart *) port;
+ unsigned long flags;
+ unsigned int sigs;
+
+ spin_lock_irqsave(&port->lock, flags);
+ sigs = (readb(port->membase + MCFUART_UIPR) & MCFUART_UIPR_CTS) ?
+ 0 : TIOCM_CTS;
+ sigs |= (pp->sigs & TIOCM_RTS);
+ sigs |= (mcf_getppdcd(port->line) ? TIOCM_CD : 0);
+ sigs |= (mcf_getppdtr(port->line) ? TIOCM_DTR : 0);
+ spin_unlock_irqrestore(&port->lock, flags);
+ return sigs;
+}
+
+/****************************************************************************/
+
+static void mcf_set_mctrl(struct uart_port *port, unsigned int sigs)
+{
+ struct mcf_uart *pp = (struct mcf_uart *) port;
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->lock, flags);
+ pp->sigs = sigs;
+ mcf_setppdtr(port->line, (sigs & TIOCM_DTR));
+ if (sigs & TIOCM_RTS)
+ writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP1);
+ else
+ writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP0);
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/****************************************************************************/
+
+static void mcf_start_tx(struct uart_port *port)
+{
+ struct mcf_uart *pp = (struct mcf_uart *) port;
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->lock, flags);
+ pp->imr |= MCFUART_UIR_TXREADY;
+ writeb(pp->imr, port->membase + MCFUART_UIMR);
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/****************************************************************************/
+
+static void mcf_stop_tx(struct uart_port *port)
+{
+ struct mcf_uart *pp = (struct mcf_uart *) port;
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->lock, flags);
+ pp->imr &= ~MCFUART_UIR_TXREADY;
+ writeb(pp->imr, port->membase + MCFUART_UIMR);
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/****************************************************************************/
+
+static void mcf_stop_rx(struct uart_port *port)
+{
+ struct mcf_uart *pp = (struct mcf_uart *) port;
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->lock, flags);
+ pp->imr &= ~MCFUART_UIR_RXREADY;
+ writeb(pp->imr, port->membase + MCFUART_UIMR);
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/****************************************************************************/
+
+static void mcf_break_ctl(struct uart_port *port, int break_state)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->lock, flags);
+ if (break_state == -1)
+ writeb(MCFUART_UCR_CMDBREAKSTART, port->membase + MCFUART_UCR);
+ else
+ writeb(MCFUART_UCR_CMDBREAKSTOP, port->membase + MCFUART_UCR);
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/****************************************************************************/
+
+static void mcf_enable_ms(struct uart_port *port)
+{
+}
+
+/****************************************************************************/
+
+static int mcf_startup(struct uart_port *port)
+{
+ struct mcf_uart *pp = (struct mcf_uart *) port;
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ /* Reset UART, get it into known state... */
+ writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR);
+ writeb(MCFUART_UCR_CMDRESETTX, port->membase + MCFUART_UCR);
+
+ /* Enable the UART transmitter and receiver */
+ writeb(MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE,
+ port->membase + MCFUART_UCR);
+
+ /* Enable RX interrupts now */
+ pp->imr = MCFUART_UIR_RXREADY;
+ writeb(pp->imr, port->membase + MCFUART_UIMR);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ return 0;
+}
+
+/****************************************************************************/
+
+static void mcf_shutdown(struct uart_port *port)
+{
+ struct mcf_uart *pp = (struct mcf_uart *) port;
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ /* Disable all interrupts now */
+ pp->imr = 0;
+ writeb(pp->imr, port->membase + MCFUART_UIMR);
+
+ /* Disable UART transmitter and receiver */
+ writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR);
+ writeb(MCFUART_UCR_CMDRESETTX, port->membase + MCFUART_UCR);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/****************************************************************************/
+
+static void mcf_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
+{
+ unsigned long flags;
+ unsigned int baud, baudclk;
+ unsigned char mr1, mr2;
+
+ baud = uart_get_baud_rate(port, termios, old, 0, 230400);
+ baudclk = ((MCF_BUSCLK / baud) + 16) / 32;
+
+ mr1 = MCFUART_MR1_RXIRQRDY | MCFUART_MR1_RXERRCHAR;
+ mr2 = 0;
+
+ switch (termios->c_cflag & CSIZE) {
+ case CS5: mr1 |= MCFUART_MR1_CS5; break;
+ case CS6: mr1 |= MCFUART_MR1_CS6; break;
+ case CS7: mr1 |= MCFUART_MR1_CS7; break;
+ case CS8:
+ default: mr1 |= MCFUART_MR1_CS8; break;
+ }
+
+ if (termios->c_cflag & PARENB) {
+ if (termios->c_cflag & CMSPAR) {
+ if (termios->c_cflag & PARODD)
+ mr1 |= MCFUART_MR1_PARITYMARK;
+ else
+ mr1 |= MCFUART_MR1_PARITYSPACE;
+ } else {
+ if (termios->c_cflag & PARODD)
+ mr1 |= MCFUART_MR1_PARITYODD;
+ else
+ mr1 |= MCFUART_MR1_PARITYEVEN;
+ }
+ } else {
+ mr1 |= MCFUART_MR1_PARITYNONE;
+ }
+
+ if (termios->c_cflag & CSTOPB)
+ mr2 |= MCFUART_MR2_STOP2;
+ else
+ mr2 |= MCFUART_MR2_STOP1;
+
+ if (termios->c_cflag & CRTSCTS) {
+ mr1 |= MCFUART_MR1_RXRTS;
+ mr2 |= MCFUART_MR2_TXCTS;
+ }
+
+ spin_lock_irqsave(&port->lock, flags);
+ writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR);
+ writeb(MCFUART_UCR_CMDRESETTX, port->membase + MCFUART_UCR);
+ writeb(MCFUART_UCR_CMDRESETMRPTR, port->membase + MCFUART_UCR);
+ writeb(mr1, port->membase + MCFUART_UMR);
+ writeb(mr2, port->membase + MCFUART_UMR);
+ writeb((baudclk & 0xff00) >> 8, port->membase + MCFUART_UBG1);
+ writeb((baudclk & 0xff), port->membase + MCFUART_UBG2);
+ writeb(MCFUART_UCSR_RXCLKTIMER | MCFUART_UCSR_TXCLKTIMER,
+ port->membase + MCFUART_UCSR);
+ writeb(MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE,
+ port->membase + MCFUART_UCR);
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/****************************************************************************/
+
+static void mcf_rx_chars(struct mcf_uart *pp)
+{
+ struct uart_port *port = (struct uart_port *) pp;
+ unsigned char status, ch, flag;
+
+ while ((status = readb(port->membase + MCFUART_USR)) & MCFUART_USR_RXREADY) {
+ ch = readb(port->membase + MCFUART_URB);
+ flag = TTY_NORMAL;
+ port->icount.rx++;
+
+ if (status & MCFUART_USR_RXERR) {
+ writeb(MCFUART_UCR_CMDRESETERR,
+ port->membase + MCFUART_UCR);
+
+ if (status & MCFUART_USR_RXBREAK) {
+ port->icount.brk++;
+ if (uart_handle_break(port))
+ continue;
+ } else if (status & MCFUART_USR_RXPARITY) {
+ port->icount.parity++;
+ } else if (status & MCFUART_USR_RXOVERRUN) {
+ port->icount.overrun++;
+ } else if (status & MCFUART_USR_RXFRAMING) {
+ port->icount.frame++;
+ }
+
+ status &= port->read_status_mask;
+
+ if (status & MCFUART_USR_RXBREAK)
+ flag = TTY_BREAK;
+ else if (status & MCFUART_USR_RXPARITY)
+ flag = TTY_PARITY;
+ else if (status & MCFUART_USR_RXFRAMING)
+ flag = TTY_FRAME;
+ }
+
+ if (uart_handle_sysrq_char(port, ch))
+ continue;
+ uart_insert_char(port, status, MCFUART_USR_RXOVERRUN, ch, flag);
+ }
+
+ tty_flip_buffer_push(port->info->tty);
+}
+
+/****************************************************************************/
+
+static void mcf_tx_chars(struct mcf_uart *pp)
+{
+ struct uart_port *port = (struct uart_port *) pp;
+ struct circ_buf *xmit = &port->info->xmit;
+
+ if (port->x_char) {
+ /* Send special char - probably flow control */
+ writeb(port->x_char, port->membase + MCFUART_UTB);
+ port->x_char = 0;
+ port->icount.tx++;
+ return;
+ }
+
+ while (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXREADY) {
+ if (xmit->head == xmit->tail)
+ break;
+ writeb(xmit->buf[xmit->tail], port->membase + MCFUART_UTB);
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE -1);
+ port->icount.tx++;
+ }
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(port);
+
+ if (xmit->head == xmit->tail) {
+ pp->imr &= ~MCFUART_UIR_TXREADY;
+ writeb(pp->imr, port->membase + MCFUART_UIMR);
+ }
+}
+
+/****************************************************************************/
+
+static irqreturn_t mcf_interrupt(int irq, void *data)
+{
+ struct uart_port *port = data;
+ struct mcf_uart *pp = (struct mcf_uart *) port;
+ unsigned int isr;
+
+ isr = readb(port->membase + MCFUART_UISR) & pp->imr;
+ if (isr & MCFUART_UIR_RXREADY)
+ mcf_rx_chars(pp);
+ if (isr & MCFUART_UIR_TXREADY)
+ mcf_tx_chars(pp);
+ return IRQ_HANDLED;
+}
+
+/****************************************************************************/
+
+static void mcf_config_port(struct uart_port *port, int flags)
+{
+ port->type = PORT_MCF;
+
+ /* Clear mask, so no surprise interrupts. */
+ writeb(0, port->membase + MCFUART_UIMR);
+
+ if (request_irq(port->irq, mcf_interrupt, IRQF_DISABLED, "UART", port))
+ printk(KERN_ERR "MCF: unable to attach ColdFire UART %d "
+ "interrupt vector=%d\n", port->line, port->irq);
+}
+
+/****************************************************************************/
+
+static const char *mcf_type(struct uart_port *port)
+{
+ return (port->type == PORT_MCF) ? "ColdFire UART" : NULL;
+}
+
+/****************************************************************************/
+
+static int mcf_request_port(struct uart_port *port)
+{
+ /* UARTs always present */
+ return 0;
+}
+
+/****************************************************************************/
+
+static void mcf_release_port(struct uart_port *port)
+{
+ /* Nothing to release... */
+}
+
+/****************************************************************************/
+
+static int mcf_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+ if ((ser->type != PORT_UNKNOWN) && (ser->type != PORT_MCF))
+ return -EINVAL;
+ return 0;
+}
+
+/****************************************************************************/
+
+/*
+ * Define the basic serial functions we support.
+ */
+static struct uart_ops mcf_uart_ops = {
+ .tx_empty = mcf_tx_empty,
+ .get_mctrl = mcf_get_mctrl,
+ .set_mctrl = mcf_set_mctrl,
+ .start_tx = mcf_start_tx,
+ .stop_tx = mcf_stop_tx,
+ .stop_rx = mcf_stop_rx,
+ .enable_ms = mcf_enable_ms,
+ .break_ctl = mcf_break_ctl,
+ .startup = mcf_startup,
+ .shutdown = mcf_shutdown,
+ .set_termios = mcf_set_termios,
+ .type = mcf_type,
+ .request_port = mcf_request_port,
+ .release_port = mcf_release_port,
+ .config_port = mcf_config_port,
+ .verify_port = mcf_verify_port,
+};
+
+static struct mcf_uart mcf_ports[3];
+
+#define MCF_MAXPORTS (sizeof(mcf_ports) / sizeof(struct mcf_uart))
+
+/****************************************************************************/
+#if defined(CONFIG_SERIAL_MCF_CONSOLE)
+/****************************************************************************/
+
+int __init early_mcf_setup(struct mcf_platform_uart *platp)
+{
+ struct uart_port *port;
+ int i;
+
+ for (i = 0; ((i < MCF_MAXPORTS) && (platp[i].mapbase)); i++) {
+ port = &mcf_ports[i].port;
+
+ port->line = i;
+ port->type = PORT_MCF;
+ port->mapbase = platp[i].mapbase;
+ port->membase = (platp[i].membase) ? platp[i].membase :
+ (unsigned char __iomem *) port->mapbase;
+ port->iotype = SERIAL_IO_MEM;
+ port->irq = platp[i].irq;
+ port->uartclk = MCF_BUSCLK;
+ port->flags = ASYNC_BOOT_AUTOCONF;
+ port->ops = &mcf_uart_ops;
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+
+static void mcf_console_putc(struct console *co, const char c)
+{
+ struct uart_port *port = &(mcf_ports + co->index)->port;
+ int i;
+
+ for (i = 0; (i < 0x10000); i++) {
+ if (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXREADY)
+ break;
+ }
+ writeb(c, port->membase + MCFUART_UTB);
+ for (i = 0; (i < 0x10000); i++) {
+ if (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXREADY)
+ break;
+ }
+}
+
+/****************************************************************************/
+
+static void mcf_console_write(struct console *co, const char *s, unsigned int count)
+{
+ for (; (count); count--, s++) {
+ mcf_console_putc(co, *s);
+ if (*s == '\n')
+ mcf_console_putc(co, '\r');
+ }
+}
+
+/****************************************************************************/
+
+static int __init mcf_console_setup(struct console *co, char *options)
+{
+ struct uart_port *port;
+ int baud = CONFIG_SERIAL_MCF_BAUDRATE;
+ int bits = 8;
+ int parity = 'n';
+ int flow = 'n';
+
+ if ((co->index >= 0) && (co->index <= MCF_MAXPORTS))
+ co->index = 0;
+ port = &mcf_ports[co->index].port;
+ if (port->membase == 0)
+ return -ENODEV;
+
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+ return uart_set_options(port, co, baud, parity, bits, flow);
+}
+
+/****************************************************************************/
+
+static struct uart_driver mcf_driver;
+
+static struct console mcf_console = {
+ .name = "ttyS",
+ .write = mcf_console_write,
+ .device = uart_console_device,
+ .setup = mcf_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+ .data = &mcf_driver,
+};
+
+static int __init mcf_console_init(void)
+{
+ register_console(&mcf_console);
+ return 0;
+}
+
+console_initcall(mcf_console_init);
+
+#define MCF_CONSOLE &mcf_console
+
+/****************************************************************************/
+#else
+/****************************************************************************/
+
+#define MCF_CONSOLE NULL
+
+/****************************************************************************/
+#endif /* CONFIG_MCF_CONSOLE */
+/****************************************************************************/
+
+/*
+ * Define the mcf UART driver structure.
+ */
+static struct uart_driver mcf_driver = {
+ .owner = THIS_MODULE,
+ .driver_name = "mcf",
+ .dev_name = "ttyS",
+ .major = TTY_MAJOR,
+ .minor = 64,
+ .nr = MCF_MAXPORTS,
+ .cons = MCF_CONSOLE,
+};
+
+/****************************************************************************/
+
+static int __devinit mcf_probe(struct platform_device *pdev)
+{
+ struct mcf_platform_uart *platp = pdev->dev.platform_data;
+ struct uart_port *port;
+ int i;
+
+ for (i = 0; ((i < MCF_MAXPORTS) && (platp[i].mapbase)); i++) {
+ port = &mcf_ports[i].port;
+
+ port->line = i;
+ port->type = PORT_MCF;
+ port->mapbase = platp[i].mapbase;
+ port->membase = (platp[i].membase) ? platp[i].membase :
+ (unsigned char __iomem *) platp[i].mapbase;
+ port->iotype = SERIAL_IO_MEM;
+ port->irq = platp[i].irq;
+ port->uartclk = MCF_BUSCLK;
+ port->ops = &mcf_uart_ops;
+ port->flags = ASYNC_BOOT_AUTOCONF;
+
+ uart_add_one_port(&mcf_driver, port);
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+
+static int mcf_remove(struct platform_device *pdev)
+{
+ struct uart_port *port;
+ int i;
+
+ for (i = 0; (i < MCF_MAXPORTS); i++) {
+ port = &mcf_ports[i].port;
+ if (port)
+ uart_remove_one_port(&mcf_driver, port);
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+
+static struct platform_driver mcf_platform_driver = {
+ .probe = mcf_probe,
+ .remove = __devexit_p(mcf_remove),
+ .driver = {
+ .name = "mcfuart",
+ .owner = THIS_MODULE,
+ },
+};
+
+/****************************************************************************/
+
+static int __init mcf_init(void)
+{
+ int rc;
+
+ printk("ColdFire internal UART serial driver\n");
+
+ rc = uart_register_driver(&mcf_driver);
+ if (rc)
+ return rc;
+ rc = platform_driver_register(&mcf_platform_driver);
+ if (rc)
+ return rc;
+ return 0;
+}
+
+/****************************************************************************/
+
+static void __exit mcf_exit(void)
+{
+ platform_driver_unregister(&mcf_platform_driver);
+ uart_unregister_driver(&mcf_driver);
+}
+
+/****************************************************************************/
+
+module_init(mcf_init);
+module_exit(mcf_exit);
+
+MODULE_AUTHOR("Greg Ungerer <gerg@snapgear.com>");
+MODULE_DESCRIPTION("Freescale ColdFire UART driver");
+MODULE_LICENSE("GPL");
+
+/****************************************************************************/
diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c
index e9c6cb391a23..af3a011b2b24 100644
--- a/drivers/serial/pxa.c
+++ b/drivers/serial/pxa.c
@@ -42,6 +42,7 @@
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
+#include <linux/clk.h>
#include <asm/io.h>
#include <asm/hardware.h>
@@ -55,7 +56,7 @@ struct uart_pxa_port {
unsigned char lcr;
unsigned char mcr;
unsigned int lsr_break_flag;
- unsigned int cken;
+ struct clk *clk;
char *name;
};
@@ -351,6 +352,8 @@ static int serial_pxa_startup(struct uart_port *port)
else
up->mcr = 0;
+ up->port.uartclk = clk_get_rate(up->clk);
+
/*
* Allocate the IRQ
*/
@@ -546,9 +549,11 @@ serial_pxa_pm(struct uart_port *port, unsigned int state,
unsigned int oldstate)
{
struct uart_pxa_port *up = (struct uart_pxa_port *)port;
- pxa_set_cken(up->cken, !state);
+
if (!state)
- udelay(1);
+ clk_enable(up->clk);
+ else
+ clk_disable(up->clk);
}
static void serial_pxa_release_port(struct uart_port *port)
@@ -582,7 +587,7 @@ serial_pxa_type(struct uart_port *port)
#ifdef CONFIG_SERIAL_PXA_CONSOLE
-static struct uart_pxa_port serial_pxa_ports[];
+static struct uart_pxa_port *serial_pxa_ports[4];
static struct uart_driver serial_pxa_reg;
#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
@@ -632,9 +637,11 @@ static void serial_pxa_console_putchar(struct uart_port *port, int ch)
static void
serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
{
- struct uart_pxa_port *up = &serial_pxa_ports[co->index];
+ struct uart_pxa_port *up = serial_pxa_ports[co->index];
unsigned int ier;
+ clk_enable(up->clk);
+
/*
* First save the IER then disable the interrupts
*/
@@ -649,6 +656,8 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
*/
wait_for_xmitr(up);
serial_out(up, UART_IER, ier);
+
+ clk_disable(up->clk);
}
static int __init
@@ -662,7 +671,9 @@ serial_pxa_console_setup(struct console *co, char *options)
if (co->index == -1 || co->index >= serial_pxa_reg.nr)
co->index = 0;
- up = &serial_pxa_ports[co->index];
+ up = serial_pxa_ports[co->index];
+ if (!up)
+ return -ENODEV;
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
@@ -680,15 +691,6 @@ static struct console serial_pxa_console = {
.data = &serial_pxa_reg,
};
-static int __init
-serial_pxa_console_init(void)
-{
- register_console(&serial_pxa_console);
- return 0;
-}
-
-console_initcall(serial_pxa_console_init);
-
#define PXA_CONSOLE &serial_pxa_console
#else
#define PXA_CONSOLE NULL
@@ -714,73 +716,13 @@ struct uart_ops serial_pxa_pops = {
.verify_port = serial_pxa_verify_port,
};
-static struct uart_pxa_port serial_pxa_ports[] = {
- { /* FFUART */
- .name = "FFUART",
- .cken = CKEN_FFUART,
- .port = {
- .type = PORT_PXA,
- .iotype = UPIO_MEM,
- .membase = (void *)&FFUART,
- .mapbase = __PREG(FFUART),
- .irq = IRQ_FFUART,
- .uartclk = 921600 * 16,
- .fifosize = 64,
- .ops = &serial_pxa_pops,
- .line = 0,
- },
- }, { /* BTUART */
- .name = "BTUART",
- .cken = CKEN_BTUART,
- .port = {
- .type = PORT_PXA,
- .iotype = UPIO_MEM,
- .membase = (void *)&BTUART,
- .mapbase = __PREG(BTUART),
- .irq = IRQ_BTUART,
- .uartclk = 921600 * 16,
- .fifosize = 64,
- .ops = &serial_pxa_pops,
- .line = 1,
- },
- }, { /* STUART */
- .name = "STUART",
- .cken = CKEN_STUART,
- .port = {
- .type = PORT_PXA,
- .iotype = UPIO_MEM,
- .membase = (void *)&STUART,
- .mapbase = __PREG(STUART),
- .irq = IRQ_STUART,
- .uartclk = 921600 * 16,
- .fifosize = 64,
- .ops = &serial_pxa_pops,
- .line = 2,
- },
- }, { /* HWUART */
- .name = "HWUART",
- .cken = CKEN_HWUART,
- .port = {
- .type = PORT_PXA,
- .iotype = UPIO_MEM,
- .membase = (void *)&HWUART,
- .mapbase = __PREG(HWUART),
- .irq = IRQ_HWUART,
- .uartclk = 921600 * 16,
- .fifosize = 64,
- .ops = &serial_pxa_pops,
- .line = 3,
- },
- }
-};
-
static struct uart_driver serial_pxa_reg = {
.owner = THIS_MODULE,
.driver_name = "PXA serial",
.dev_name = "ttyS",
.major = TTY_MAJOR,
.minor = 64,
- .nr = ARRAY_SIZE(serial_pxa_ports),
+ .nr = 4,
.cons = PXA_CONSOLE,
};
@@ -806,10 +748,68 @@ static int serial_pxa_resume(struct platform_device *dev)
static int serial_pxa_probe(struct platform_device *dev)
{
- serial_pxa_ports[dev->id].port.dev = &dev->dev;
- uart_add_one_port(&serial_pxa_reg, &serial_pxa_ports[dev->id].port);
- platform_set_drvdata(dev, &serial_pxa_ports[dev->id]);
+ struct uart_pxa_port *sport;
+ struct resource *mmres, *irqres;
+ int ret;
+
+ mmres = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ irqres = platform_get_resource(dev, IORESOURCE_IRQ, 0);
+ if (!mmres || !irqres)
+ return -ENODEV;
+
+ sport = kzalloc(sizeof(struct uart_pxa_port), GFP_KERNEL);
+ if (!sport)
+ return -ENOMEM;
+
+ sport->clk = clk_get(&dev->dev, "UARTCLK");
+ if (IS_ERR(sport->clk)) {
+ ret = PTR_ERR(sport->clk);
+ goto err_free;
+ }
+
+ sport->port.type = PORT_PXA;
+ sport->port.iotype = UPIO_MEM;
+ sport->port.mapbase = mmres->start;
+ sport->port.irq = irqres->start;
+ sport->port.fifosize = 64;
+ sport->port.ops = &serial_pxa_pops;
+ sport->port.line = dev->id;
+ sport->port.dev = &dev->dev;
+ sport->port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
+ sport->port.uartclk = clk_get_rate(sport->clk);
+
+ /*
+ * Is it worth keeping this?
+ */
+ if (mmres->start == __PREG(FFUART))
+ sport->name = "FFUART";
+ else if (mmres->start == __PREG(BTUART))
+ sport->name = "BTUART";
+ else if (mmres->start == __PREG(STUART))
+ sport->name = "STUART";
+ else if (mmres->start == __PREG(HWUART))
+ sport->name = "HWUART";
+ else
+ sport->name = "???";
+
+ sport->port.membase = ioremap(mmres->start, mmres->end - mmres->start + 1);
+ if (!sport->port.membase) {
+ ret = -ENOMEM;
+ goto err_clk;
+ }
+
+ serial_pxa_ports[dev->id] = sport;
+
+ uart_add_one_port(&serial_pxa_reg, &sport->port);
+ platform_set_drvdata(dev, sport);
+
return 0;
+
+ err_clk:
+ clk_put(sport->clk);
+ err_free:
+ kfree(sport);
+ return ret;
}
static int serial_pxa_remove(struct platform_device *dev)
@@ -818,8 +818,9 @@ static int serial_pxa_remove(struct platform_device *dev)
platform_set_drvdata(dev, NULL);
- if (sport)
- uart_remove_one_port(&serial_pxa_reg, &sport->port);
+ uart_remove_one_port(&serial_pxa_reg, &sport->port);
+ clk_put(sport->clk);
+ kfree(sport);
return 0;
}
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
index 3f26c4b2f322..e773c8e14962 100644
--- a/drivers/serial/s3c2410.c
+++ b/drivers/serial/s3c2410.c
@@ -20,8 +20,8 @@
* - S3C2410 and S3C2440 serial support
* - Power Management support
* - Fix console via IrDA devices
- * - SysReq (Herbert Pötzl)
- * - Break character handling (Herbert Pötzl)
+ * - SysReq (Herbert Pötzl)
+ * - Break character handling (Herbert Pötzl)
* - spin-lock initialisation (Dimitry Andric)
* - added clock control
* - updated init code to use platform_device info
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index a055f58f342f..3bb5d241dd40 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -1875,6 +1875,7 @@ uart_set_options(struct uart_port *port, struct console *co,
int baud, int parity, int bits, int flow)
{
struct ktermios termios;
+ static struct ktermios dummy;
int i;
/*
@@ -1920,7 +1921,7 @@ uart_set_options(struct uart_port *port, struct console *co,
*/
port->mctrl |= TIOCM_DTR;
- port->ops->set_termios(port, &termios, NULL);
+ port->ops->set_termios(port, &termios, &dummy);
co->cflag = termios.c_cflag;
return 0;
@@ -1938,18 +1939,41 @@ static void uart_change_pm(struct uart_state *state, int pm_state)
}
}
+struct uart_match {
+ struct uart_port *port;
+ struct uart_driver *driver;
+};
+
+static int serial_match_port(struct device *dev, void *data)
+{
+ struct uart_match *match = data;
+ dev_t devt = MKDEV(match->driver->major, match->driver->minor) + match->port->line;
+
+ return dev->devt == devt; /* Actually, only one tty per port */
+}
+
int uart_suspend_port(struct uart_driver *drv, struct uart_port *port)
{
struct uart_state *state = drv->state + port->line;
+ struct device *tty_dev;
+ struct uart_match match = {port, drv};
mutex_lock(&state->mutex);
-#ifdef CONFIG_DISABLE_CONSOLE_SUSPEND
- if (uart_console(port)) {
+ if (!console_suspend_enabled && uart_console(port)) {
+ /* we're going to avoid suspending serial console */
mutex_unlock(&state->mutex);
return 0;
}
-#endif
+
+ tty_dev = device_find_child(port->dev, &match, serial_match_port);
+ if (device_may_wakeup(tty_dev)) {
+ enable_irq_wake(port->irq);
+ put_device(tty_dev);
+ mutex_unlock(&state->mutex);
+ return 0;
+ }
+ port->suspended = 1;
if (state->info && state->info->flags & UIF_INITIALIZED) {
const struct uart_ops *ops = port->ops;
@@ -1992,12 +2016,18 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
mutex_lock(&state->mutex);
-#ifdef CONFIG_DISABLE_CONSOLE_SUSPEND
- if (uart_console(port)) {
+ if (!console_suspend_enabled && uart_console(port)) {
+ /* no need to resume serial console, it wasn't suspended */
mutex_unlock(&state->mutex);
return 0;
}
-#endif
+
+ if (!port->suspended) {
+ disable_irq_wake(port->irq);
+ mutex_unlock(&state->mutex);
+ return 0;
+ }
+ port->suspended = 0;
uart_change_pm(state, 0);
@@ -2127,6 +2157,14 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
spin_unlock_irqrestore(&port->lock, flags);
/*
+ * If this driver supports console, and it hasn't been
+ * successfully registered yet, try to re-register it.
+ * It may be that the port was not available.
+ */
+ if (port->cons && !(port->cons->flags & CON_ENABLED))
+ register_console(port->cons);
+
+ /*
* Power down all ports by default, except the
* console if we have one.
*/
@@ -2270,6 +2308,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
{
struct uart_state *state;
int ret = 0;
+ struct device *tty_dev;
BUG_ON(in_interrupt());
@@ -2286,6 +2325,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
}
state->port = port;
+ state->pm_state = -1;
port->cons = drv->cons;
port->info = state->info;
@@ -2305,16 +2345,13 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
* Register the port whether it's detected or not. This allows
* setserial to be used to alter this ports parameters.
*/
- tty_register_device(drv->tty_driver, port->line, port->dev);
-
- /*
- * If this driver supports console, and it hasn't been
- * successfully registered yet, try to re-register it.
- * It may be that the port was not available.
- */
- if (port->type != PORT_UNKNOWN &&
- port->cons && !(port->cons->flags & CON_ENABLED))
- register_console(port->cons);
+ tty_dev = tty_register_device(drv->tty_driver, port->line, port->dev);
+ if (likely(!IS_ERR(tty_dev))) {
+ device_can_wakeup(tty_dev) = 1;
+ device_set_wakeup_enable(tty_dev, 0);
+ } else
+ printk(KERN_ERR "Cannot register tty device on line %d\n",
+ port->line);
/*
* Ensure UPF_DEAD is not set.
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 7c8d78fbbbfb..d8b660061c13 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -345,7 +345,7 @@ static int serial_probe(struct pcmcia_device *link)
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
link->io.NumPorts1 = 8;
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+ link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->conf.Attributes = CONF_ENABLE_IRQ;
if (do_sound) {
@@ -911,6 +911,7 @@ static struct pcmcia_device_id serial_ids[] = {
PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0175, 0x0000, "DP83903.cis"),
PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0035, "3CXEM556.cis"),
PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x003d, "3CXEM556.cis"),
+ PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC850", 0xd85f6206, 0x42a2c018, "SW_8xx_SER.cis"), /* Sierra Wireless AC850 3G Network Adapter R1 */
PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0x0710, "SW_7xx_SER.cis"), /* Sierra Wireless AC710/AC750 GPRS Network Adapter R1 */
PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- pre update */
PCMCIA_DEVICE_CIS_MANF_CARD(0x013f, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- post update */
diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c
index 0930e2a85514..7ad21925869a 100644
--- a/drivers/serial/serial_txx9.c
+++ b/drivers/serial/serial_txx9.c
@@ -25,19 +25,15 @@
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/console.h>
-#include <linux/sysrq.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/pci.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
-#include <linux/mutex.h>
#include <asm/io.h>
-static char *serial_version = "1.10";
+static char *serial_version = "1.11";
static char *serial_name = "TX39/49 Serial driver";
#define PASS_LIMIT 256
@@ -68,8 +64,6 @@ static char *serial_name = "TX39/49 Serial driver";
*/
#define UART_NR CONFIG_SERIAL_TXX9_NR_UARTS
-#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
-
struct uart_txx9_port {
struct uart_port port;
/* No additional info for now */
@@ -663,7 +657,15 @@ static void
serial_txx9_pm(struct uart_port *port, unsigned int state,
unsigned int oldstate)
{
- if (state == 0)
+ /*
+ * If oldstate was -1 this is called from
+ * uart_configure_port(). In this case do not initialize the
+ * port now, because the port was already initialized (for
+ * non-console port) or should not be initialized here (for
+ * console port). If we initialized the port here we lose
+ * serial console settings.
+ */
+ if (state == 0 && oldstate != -1)
serial_txx9_initialize(port);
}
@@ -756,21 +758,6 @@ static void serial_txx9_config_port(struct uart_port *port, int uflags)
serial_txx9_initialize(port);
}
-static int
-serial_txx9_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- unsigned long new_port = ser->port;
- if (HIGH_BITS_OFFSET)
- new_port += (unsigned long)ser->port_high << HIGH_BITS_OFFSET;
- if (ser->type != port->type ||
- ser->irq != port->irq ||
- ser->io_type != port->iotype ||
- new_port != port->iobase ||
- (unsigned long)ser->iomem_base != port->mapbase)
- return -EINVAL;
- return 0;
-}
-
static const char *
serial_txx9_type(struct uart_port *port)
{
@@ -794,7 +781,6 @@ static struct uart_ops serial_txx9_pops = {
.release_port = serial_txx9_release_port,
.request_port = serial_txx9_request_port,
.config_port = serial_txx9_config_port,
- .verify_port = serial_txx9_verify_port,
};
static struct uart_txx9_port serial_txx9_ports[UART_NR];
@@ -950,7 +936,8 @@ int __init early_serial_txx9_setup(struct uart_port *port)
serial_txx9_ports[port->line].port = *port;
serial_txx9_ports[port->line].port.ops = &serial_txx9_pops;
- serial_txx9_ports[port->line].port.flags |= UPF_BOOT_AUTOCONF;
+ serial_txx9_ports[port->line].port.flags |=
+ UPF_BOOT_AUTOCONF | UPF_FIXED_PORT;
return 0;
}
@@ -995,7 +982,8 @@ static int __devinit serial_txx9_register_port(struct uart_port *port)
uart->port.irq = port->irq;
uart->port.uartclk = port->uartclk;
uart->port.iotype = port->iotype;
- uart->port.flags = port->flags | UPF_BOOT_AUTOCONF;
+ uart->port.flags = port->flags
+ | UPF_BOOT_AUTOCONF | UPF_FIXED_PORT;
uart->port.mapbase = port->mapbase;
if (port->dev)
uart->port.dev = port->dev;
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h
index e89ae29645d6..d24621ce799a 100644
--- a/drivers/serial/sh-sci.h
+++ b/drivers/serial/sh-sci.h
@@ -77,7 +77,6 @@
# define SCIF_ONLY
#elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712)
# define SCSPTR0 0xA4400000 /* 16 bit SCIF */
-# define SCI_NPORTS 2
# define SCIF_ORER 0x0001 /* overrun error bit */
# define PACR 0xa4050100
# define PBCR 0xa4050102
@@ -102,12 +101,6 @@
# define SCIF_ORER 0x0001 /* overrun error bit */
# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
# define SCIF_ONLY
-#elif defined(CONFIG_CPU_SUBTYPE_ST40STB1)
-# define SCSPTR1 0xffe00020 /* 16 bit SCIF */
-# define SCSPTR2 0xffe80020 /* 16 bit SCIF */
-# define SCIF_ORER 0x0001 /* overrun error bit */
-# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
-# define SCIF_ONLY
#elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103)
# include <asm/hardware.h>
# define SCIF_BASE_ADDR 0x01030000
@@ -116,8 +109,7 @@
# define SCIF_LSR2_OFFS 0x0000024
# define SCSPTR2 ((port->mapbase)+SCIF_PTR2_OFFS) /* 16 bit SCIF */
# define SCLSR2 ((port->mapbase)+SCIF_LSR2_OFFS) /* 16 bit SCIF */
-# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,
- TE=1,RE=1,REIE=1 */
+# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0, TE=1,RE=1,REIE=1 */
# define SCIF_ONLY
#elif defined(CONFIG_H83007) || defined(CONFIG_H83068)
# define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */
@@ -577,15 +569,6 @@ static inline int sci_rxd_in(struct uart_port *port)
return ctrl_inb(SCPDR0) & 0x0001 ? 1 : 0; /* SCIF0 */
return 1;
}
-#elif defined(CONFIG_CPU_SUBTYPE_ST40STB1)
-static inline int sci_rxd_in(struct uart_port *port)
-{
- if (port->mapbase == 0xffe00000)
- return ctrl_inw(SCSPTR1)&0x0001 ? 1 : 0; /* SCIF */
- else
- return ctrl_inw(SCSPTR2)&0x0001 ? 1 : 0; /* SCIF */
-
-}
#elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103)
static inline int sci_rxd_in(struct uart_port *port)
{
diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c
index dfef83f14960..a85f2d31a686 100644
--- a/drivers/serial/uartlite.c
+++ b/drivers/serial/uartlite.c
@@ -329,12 +329,14 @@ static struct uart_ops ulite_ops = {
static void ulite_console_wait_tx(struct uart_port *port)
{
int i;
+ u8 val;
- /* wait up to 10ms for the character(s) to be sent */
- for (i = 0; i < 10000; i++) {
- if (readb(port->membase + ULITE_STATUS) & ULITE_STATUS_TXEMPTY)
+ /* Spin waiting for TX fifo to have space available */
+ for (i = 0; i < 100000; i++) {
+ val = readb(port->membase + ULITE_STATUS);
+ if ((val & ULITE_STATUS_TXFULL) == 0)
break;
- udelay(1);
+ cpu_relax();
}
}
diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c
index 161d1021b7eb..e52a6296ca46 100644
--- a/drivers/sh/maple/maple.c
+++ b/drivers/sh/maple/maple.c
@@ -601,8 +601,7 @@ static int match_maple_bus_driver(struct device *devptr,
return 0;
}
-static int maple_bus_uevent(struct device *dev, char **envp,
- int num_envp, char *buffer, int buffer_size)
+static int maple_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
{
return 0;
}
diff --git a/drivers/sh/superhyway/superhyway.c b/drivers/sh/superhyway/superhyway.c
index 7d873b3b0513..4d0282b821b5 100644
--- a/drivers/sh/superhyway/superhyway.c
+++ b/drivers/sh/superhyway/superhyway.c
@@ -107,16 +107,17 @@ int superhyway_add_devices(struct superhyway_bus *bus,
static int __init superhyway_init(void)
{
struct superhyway_bus *bus;
- int ret = 0;
+ int ret;
- device_register(&superhyway_bus_device);
+ ret = device_register(&superhyway_bus_device);
+ if (unlikely(ret))
+ return ret;
for (bus = superhyway_channels; bus->ops; bus++)
ret |= superhyway_scan_bus(bus);
return ret;
}
-
postcore_initcall(superhyway_init);
static const struct superhyway_device_id *
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index b91571122daa..a77ede598d34 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -124,16 +124,17 @@ config SPI_MPC52xx_PSC
Controller in master SPI mode.
config SPI_MPC83xx
- tristate "Freescale MPC83xx SPI controller"
- depends on SPI_MASTER && PPC_83xx && EXPERIMENTAL
+ tristate "Freescale MPC83xx/QUICC Engine SPI controller"
+ depends on SPI_MASTER && (PPC_83xx || QUICC_ENGINE) && EXPERIMENTAL
select SPI_BITBANG
help
- This enables using the Freescale MPC83xx SPI controller in master
- mode.
+ This enables using the Freescale MPC83xx and QUICC Engine SPI
+ controllers in master mode.
Note, this driver uniquely supports the SPI controller on the MPC83xx
- family of PowerPC processors. The MPC83xx uses a simple set of shift
- registers for data (opposed to the CPM based descriptor model).
+ family of PowerPC processors, plus processors with QUICC Engine
+ technology. This driver uses a simple set of shift registers for data
+ (opposed to the CPM based descriptor model).
config SPI_OMAP_UWIRE
tristate "OMAP1 MicroWire"
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
index b0469749310a..0d342dcdd302 100644
--- a/drivers/spi/atmel_spi.c
+++ b/drivers/spi/atmel_spi.c
@@ -211,7 +211,7 @@ static void atmel_spi_next_message(struct spi_master *master)
msg = list_entry(as->queue.next, struct spi_message, queue);
spi = msg->spi;
- dev_dbg(master->cdev.dev, "start message %p for %s\n",
+ dev_dbg(master->dev.parent, "start message %p for %s\n",
msg, spi->dev.bus_id);
/* select chip if it's not still active */
@@ -266,10 +266,10 @@ static void atmel_spi_dma_unmap_xfer(struct spi_master *master,
struct spi_transfer *xfer)
{
if (xfer->tx_dma != INVALID_DMA_ADDRESS)
- dma_unmap_single(master->cdev.dev, xfer->tx_dma,
+ dma_unmap_single(master->dev.parent, xfer->tx_dma,
xfer->len, DMA_TO_DEVICE);
if (xfer->rx_dma != INVALID_DMA_ADDRESS)
- dma_unmap_single(master->cdev.dev, xfer->rx_dma,
+ dma_unmap_single(master->dev.parent, xfer->rx_dma,
xfer->len, DMA_FROM_DEVICE);
}
@@ -285,7 +285,7 @@ atmel_spi_msg_done(struct spi_master *master, struct atmel_spi *as,
list_del(&msg->queue);
msg->status = status;
- dev_dbg(master->cdev.dev,
+ dev_dbg(master->dev.parent,
"xfer complete: %u bytes transferred\n",
msg->actual_length);
@@ -348,7 +348,7 @@ atmel_spi_interrupt(int irq, void *dev_id)
if (xfer->delay_usecs)
udelay(xfer->delay_usecs);
- dev_warn(master->cdev.dev, "fifo overrun (%u/%u remaining)\n",
+ dev_warn(master->dev.parent, "fifo overrun (%u/%u remaining)\n",
spi_readl(as, TCR), spi_readl(as, RCR));
/*
@@ -363,7 +363,7 @@ atmel_spi_interrupt(int irq, void *dev_id)
if (spi_readl(as, SR) & SPI_BIT(TXEMPTY))
break;
if (!timeout)
- dev_warn(master->cdev.dev,
+ dev_warn(master->dev.parent,
"timeout waiting for TXEMPTY");
while (spi_readl(as, SR) & SPI_BIT(RDRF))
spi_readl(as, RDR);
@@ -526,7 +526,7 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg)
struct atmel_spi *as;
struct spi_transfer *xfer;
unsigned long flags;
- struct device *controller = spi->master->cdev.dev;
+ struct device *controller = spi->master->dev.parent;
as = spi_master_get_devdata(spi->master);
diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_psc_spi.c
index d2a4b2bdb07b..7051e6c5edc3 100644
--- a/drivers/spi/mpc52xx_psc_spi.c
+++ b/drivers/spi/mpc52xx_psc_spi.c
@@ -181,7 +181,7 @@ static int mpc52xx_psc_spi_transfer_rxtx(struct spi_device *spi,
}
- /* enable interupts and wait for wake up
+ /* enable interrupts and wait for wake up
* if just one byte is expected the Rx FIFO genererates no
* FFULL interrupt, so activate the RxRDY interrupt
*/
@@ -503,7 +503,7 @@ static int __init mpc52xx_psc_spi_do_probe(struct device *dev, u32 regaddr,
INIT_LIST_HEAD(&mps->queue);
mps->workqueue = create_singlethread_workqueue(
- master->cdev.dev->bus_id);
+ master->dev.parent->bus_id);
if (mps->workqueue == NULL) {
ret = -EBUSY;
goto free_irq;
diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c
index 6b357cdb9ea3..3cdab131c4a9 100644
--- a/drivers/spi/omap2_mcspi.c
+++ b/drivers/spi/omap2_mcspi.c
@@ -645,7 +645,7 @@ static int omap2_mcspi_setup(struct spi_device *spi)
clk_enable(mcspi->ick);
clk_enable(mcspi->fck);
- ret = omap2_mcspi_setup_transfer(spi, NULL);
+ ret = omap2_mcspi_setup_transfer(spi, NULL);
clk_disable(mcspi->fck);
clk_disable(mcspi->ick);
@@ -693,7 +693,6 @@ static void omap2_mcspi_work(struct work_struct *work)
struct spi_device *spi;
struct spi_transfer *t = NULL;
int cs_active = 0;
- struct omap2_mcspi_device_config *conf;
struct omap2_mcspi_cs *cs;
int par_override = 0;
int status = 0;
@@ -706,7 +705,6 @@ static void omap2_mcspi_work(struct work_struct *work)
spin_unlock_irq(&mcspi->lock);
spi = m->spi;
- conf = spi->controller_data;
cs = spi->controller_state;
omap2_mcspi_set_enable(spi, 1);
diff --git a/drivers/spi/omap_uwire.c b/drivers/spi/omap_uwire.c
index d275c615a73e..8245b5153f30 100644
--- a/drivers/spi/omap_uwire.c
+++ b/drivers/spi/omap_uwire.c
@@ -481,7 +481,7 @@ static void uwire_off(struct uwire_spi *uwire)
spi_master_put(uwire->bitbang.master);
}
-static int uwire_probe(struct platform_device *pdev)
+static int __init uwire_probe(struct platform_device *pdev)
{
struct spi_master *master;
struct uwire_spi *uwire;
@@ -525,7 +525,7 @@ static int uwire_probe(struct platform_device *pdev)
return status;
}
-static int uwire_remove(struct platform_device *pdev)
+static int __exit uwire_remove(struct platform_device *pdev)
{
struct uwire_spi *uwire = dev_get_drvdata(&pdev->dev);
int status;
@@ -543,8 +543,7 @@ static struct platform_driver uwire_driver = {
.bus = &platform_bus_type,
.owner = THIS_MODULE,
},
- .probe = uwire_probe,
- .remove = uwire_remove,
+ .remove = __exit_p(uwire_remove),
// suspend ... unuse ck
// resume ... use ck
};
@@ -566,7 +565,7 @@ static int __init omap_uwire_init(void)
omap_writel(val | 0x00AAA000, OMAP730_IO_CONF_9);
}
- return platform_driver_register(&uwire_driver);
+ return platform_driver_probe(&uwire_driver, uwire_probe);
}
static void __exit omap_uwire_exit(void)
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
index e51311b2da0b..5f3d808cbc29 100644
--- a/drivers/spi/pxa2xx_spi.c
+++ b/drivers/spi/pxa2xx_spi.c
@@ -26,7 +26,6 @@
#include <linux/dma-mapping.h>
#include <linux/spi/spi.h>
#include <linux/workqueue.h>
-#include <linux/errno.h>
#include <linux/delay.h>
#include <asm/io.h>
@@ -1230,7 +1229,7 @@ static void cleanup(struct spi_device *spi)
kfree(chip);
}
-static int init_queue(struct driver_data *drv_data)
+static int __init init_queue(struct driver_data *drv_data)
{
INIT_LIST_HEAD(&drv_data->queue);
spin_lock_init(&drv_data->lock);
@@ -1243,7 +1242,7 @@ static int init_queue(struct driver_data *drv_data)
INIT_WORK(&drv_data->pump_messages, pump_messages);
drv_data->workqueue = create_singlethread_workqueue(
- drv_data->master->cdev.dev->bus_id);
+ drv_data->master->dev.parent->bus_id);
if (drv_data->workqueue == NULL)
return -EBUSY;
@@ -1318,7 +1317,7 @@ static int destroy_queue(struct driver_data *drv_data)
return 0;
}
-static int pxa2xx_spi_probe(struct platform_device *pdev)
+static int __init pxa2xx_spi_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct pxa2xx_spi_master *platform_info;
@@ -1622,8 +1621,7 @@ static struct platform_driver driver = {
.bus = &platform_bus_type,
.owner = THIS_MODULE,
},
- .probe = pxa2xx_spi_probe,
- .remove = __devexit_p(pxa2xx_spi_remove),
+ .remove = pxa2xx_spi_remove,
.shutdown = pxa2xx_spi_shutdown,
.suspend = pxa2xx_spi_suspend,
.resume = pxa2xx_spi_resume,
@@ -1631,9 +1629,7 @@ static struct platform_driver driver = {
static int __init pxa2xx_spi_init(void)
{
- platform_driver_register(&driver);
-
- return 0;
+ return platform_driver_probe(&driver, pxa2xx_spi_probe);
}
module_init(pxa2xx_spi_init);
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index bcb8dd5fb0b4..b31f4431849b 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -204,7 +204,7 @@ struct spi_device *spi_new_device(struct spi_master *master,
struct spi_board_info *chip)
{
struct spi_device *proxy;
- struct device *dev = master->cdev.dev;
+ struct device *dev = master->dev.parent;
int status;
/* NOTE: caller did any chip->bus_num checks necessary.
@@ -239,7 +239,7 @@ struct spi_device *spi_new_device(struct spi_master *master,
proxy->modalias = chip->modalias;
snprintf(proxy->dev.bus_id, sizeof proxy->dev.bus_id,
- "%s.%u", master->cdev.class_id,
+ "%s.%u", master->dev.bus_id,
chip->chip_select);
proxy->dev.parent = dev;
proxy->dev.bus = &spi_bus_type;
@@ -338,18 +338,18 @@ static void scan_boardinfo(struct spi_master *master)
/*-------------------------------------------------------------------------*/
-static void spi_master_release(struct class_device *cdev)
+static void spi_master_release(struct device *dev)
{
struct spi_master *master;
- master = container_of(cdev, struct spi_master, cdev);
+ master = container_of(dev, struct spi_master, dev);
kfree(master);
}
static struct class spi_master_class = {
.name = "spi_master",
.owner = THIS_MODULE,
- .release = spi_master_release,
+ .dev_release = spi_master_release,
};
@@ -357,7 +357,7 @@ static struct class spi_master_class = {
* spi_alloc_master - allocate SPI master controller
* @dev: the controller, possibly using the platform_bus
* @size: how much zeroed driver-private data to allocate; the pointer to this
- * memory is in the class_data field of the returned class_device,
+ * memory is in the driver_data field of the returned device,
* accessible with spi_master_get_devdata().
* Context: can sleep
*
@@ -383,9 +383,9 @@ struct spi_master *spi_alloc_master(struct device *dev, unsigned size)
if (!master)
return NULL;
- class_device_initialize(&master->cdev);
- master->cdev.class = &spi_master_class;
- master->cdev.dev = get_device(dev);
+ device_initialize(&master->dev);
+ master->dev.class = &spi_master_class;
+ master->dev.parent = get_device(dev);
spi_master_set_devdata(master, &master[1]);
return master;
@@ -415,7 +415,7 @@ EXPORT_SYMBOL_GPL(spi_alloc_master);
int spi_register_master(struct spi_master *master)
{
static atomic_t dyn_bus_id = ATOMIC_INIT((1<<15) - 1);
- struct device *dev = master->cdev.dev;
+ struct device *dev = master->dev.parent;
int status = -ENODEV;
int dynamic = 0;
@@ -440,12 +440,12 @@ int spi_register_master(struct spi_master *master)
/* register the device, then userspace will see it.
* registration fails if the bus ID is in use.
*/
- snprintf(master->cdev.class_id, sizeof master->cdev.class_id,
+ snprintf(master->dev.bus_id, sizeof master->dev.bus_id,
"spi%u", master->bus_num);
- status = class_device_add(&master->cdev);
+ status = device_add(&master->dev);
if (status < 0)
goto done;
- dev_dbg(dev, "registered master %s%s\n", master->cdev.class_id,
+ dev_dbg(dev, "registered master %s%s\n", master->dev.bus_id,
dynamic ? " (dynamic)" : "");
/* populate children from any spi device tables */
@@ -457,10 +457,11 @@ done:
EXPORT_SYMBOL_GPL(spi_register_master);
-static int __unregister(struct device *dev, void *unused)
+static int __unregister(struct device *dev, void *master_dev)
{
/* note: before about 2.6.14-rc1 this would corrupt memory: */
- spi_unregister_device(to_spi_device(dev));
+ if (dev != master_dev)
+ spi_unregister_device(to_spi_device(dev));
return 0;
}
@@ -478,8 +479,9 @@ void spi_unregister_master(struct spi_master *master)
{
int dummy;
- dummy = device_for_each_child(master->cdev.dev, NULL, __unregister);
- class_device_unregister(&master->cdev);
+ dummy = device_for_each_child(master->dev.parent, &master->dev,
+ __unregister);
+ device_unregister(&master->dev);
}
EXPORT_SYMBOL_GPL(spi_unregister_master);
@@ -495,13 +497,13 @@ EXPORT_SYMBOL_GPL(spi_unregister_master);
*/
struct spi_master *spi_busnum_to_master(u16 bus_num)
{
- struct class_device *cdev;
+ struct device *dev;
struct spi_master *master = NULL;
struct spi_master *m;
down(&spi_master_class.sem);
- list_for_each_entry(cdev, &spi_master_class.children, node) {
- m = container_of(cdev, struct spi_master, cdev);
+ list_for_each_entry(dev, &spi_master_class.children, node) {
+ m = container_of(dev, struct spi_master, dev);
if (m->bus_num == bus_num) {
master = spi_master_get(m);
break;
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index f540ed77a102..2ef11bb70b2e 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -39,7 +39,6 @@
#include <linux/dma-mapping.h>
#include <linux/spi/spi.h>
#include <linux/workqueue.h>
-#include <linux/errno.h>
#include <linux/delay.h>
#include <asm/io.h>
@@ -1071,7 +1070,7 @@ static int setup(struct spi_device *spi)
return -ENODEV;
}
- dev_dbg(&spi->dev, "setup spi chip %s, width is %d, dma is %d,",
+ dev_dbg(&spi->dev, "setup spi chip %s, width is %d, dma is %d\n",
spi->modalias, chip->width, chip->enable_dma);
dev_dbg(&spi->dev, "ctl_reg is 0x%x, flag_reg is 0x%x\n",
chip->ctl_reg, chip->flag);
@@ -1107,7 +1106,7 @@ static inline int init_queue(struct driver_data *drv_data)
/* init messages workqueue */
INIT_WORK(&drv_data->pump_messages, pump_messages);
drv_data->workqueue =
- create_singlethread_workqueue(drv_data->master->cdev.dev->bus_id);
+ create_singlethread_workqueue(drv_data->master->dev.parent->bus_id);
if (drv_data->workqueue == NULL)
return -EBUSY;
diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c
index 0c85c984ccb4..81639c6be1c7 100644
--- a/drivers/spi/spi_bitbang.c
+++ b/drivers/spi/spi_bitbang.c
@@ -472,7 +472,7 @@ int spi_bitbang_start(struct spi_bitbang *bitbang)
/* this task is the only thing to touch the SPI bits */
bitbang->busy = 0;
bitbang->workqueue = create_singlethread_workqueue(
- bitbang->master->cdev.dev->bus_id);
+ bitbang->master->dev.parent->bus_id);
if (bitbang->workqueue == NULL) {
status = -EBUSY;
goto err1;
diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c
index bd9177f51de9..7686ba34430f 100644
--- a/drivers/spi/spi_imx.c
+++ b/drivers/spi/spi_imx.c
@@ -1194,7 +1194,7 @@ static int setup(struct spi_device *spi)
chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
if (!chip) {
dev_err(&spi->dev,
- "setup - cannot allocate controller state");
+ "setup - cannot allocate controller state\n");
return -ENOMEM;
}
chip->control = SPI_DEFAULT_CONTROL;
@@ -1206,7 +1206,7 @@ static int setup(struct spi_device *spi)
if (!chip_info) {
dev_err(&spi->dev,
"setup - "
- "cannot allocate controller data");
+ "cannot allocate controller data\n");
status = -ENOMEM;
goto err_first_setup;
}
@@ -1361,7 +1361,7 @@ static void cleanup(struct spi_device *spi)
kfree(spi_get_ctldata(spi));
}
-static int init_queue(struct driver_data *drv_data)
+static int __init init_queue(struct driver_data *drv_data)
{
INIT_LIST_HEAD(&drv_data->queue);
spin_lock_init(&drv_data->lock);
@@ -1374,7 +1374,7 @@ static int init_queue(struct driver_data *drv_data)
INIT_WORK(&drv_data->work, pump_messages);
drv_data->workqueue = create_singlethread_workqueue(
- drv_data->master->cdev.dev->bus_id);
+ drv_data->master->dev.parent->bus_id);
if (drv_data->workqueue == NULL)
return -EBUSY;
@@ -1444,7 +1444,7 @@ static int destroy_queue(struct driver_data *drv_data)
return 0;
}
-static int spi_imx_probe(struct platform_device *pdev)
+static int __init spi_imx_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct spi_imx_master *platform_info;
@@ -1622,7 +1622,7 @@ err_no_mem:
return status;
}
-static int __devexit spi_imx_remove(struct platform_device *pdev)
+static int __exit spi_imx_remove(struct platform_device *pdev)
{
struct driver_data *drv_data = platform_get_drvdata(pdev);
int irq;
@@ -1739,8 +1739,7 @@ static struct platform_driver driver = {
.bus = &platform_bus_type,
.owner = THIS_MODULE,
},
- .probe = spi_imx_probe,
- .remove = __devexit_p(spi_imx_remove),
+ .remove = __exit_p(spi_imx_remove),
.shutdown = spi_imx_shutdown,
.suspend = spi_imx_suspend,
.resume = spi_imx_resume,
@@ -1748,7 +1747,7 @@ static struct platform_driver driver = {
static int __init spi_imx_init(void)
{
- return platform_driver_register(&driver);
+ return platform_driver_probe(&driver, spi_imx_probe);
}
module_init(spi_imx_init);
diff --git a/drivers/spi/spi_lm70llp.c b/drivers/spi/spi_lm70llp.c
index 4ea68ac16115..39d8d8ad65c0 100644
--- a/drivers/spi/spi_lm70llp.c
+++ b/drivers/spi/spi_lm70llp.c
@@ -82,7 +82,7 @@ struct spi_lm70llp {
struct pardevice *pd;
struct spi_device *spidev_lm70;
struct spi_board_info info;
- struct class_device *cdev;
+ //struct device *dev;
};
/* REVISIT : ugly global ; provides "exclusive open" facility */
diff --git a/drivers/spi/spi_mpc83xx.c b/drivers/spi/spi_mpc83xx.c
index 32cda77b31cd..4580b9cf625d 100644
--- a/drivers/spi/spi_mpc83xx.c
+++ b/drivers/spi/spi_mpc83xx.c
@@ -511,7 +511,7 @@ err:
return ret;
}
-static int __devexit mpc83xx_spi_remove(struct platform_device *dev)
+static int __exit mpc83xx_spi_remove(struct platform_device *dev)
{
struct mpc83xx_spi *mpc83xx_spi;
struct spi_master *master;
@@ -529,8 +529,7 @@ static int __devexit mpc83xx_spi_remove(struct platform_device *dev)
MODULE_ALIAS("mpc83xx_spi"); /* for platform bus hotplug */
static struct platform_driver mpc83xx_spi_driver = {
- .probe = mpc83xx_spi_probe,
- .remove = __devexit_p(mpc83xx_spi_remove),
+ .remove = __exit_p(mpc83xx_spi_remove),
.driver = {
.name = "mpc83xx_spi",
},
@@ -538,7 +537,7 @@ static struct platform_driver mpc83xx_spi_driver = {
static int __init mpc83xx_spi_init(void)
{
- return platform_driver_register(&mpc83xx_spi_driver);
+ return platform_driver_probe(&mpc83xx_spi_driver, mpc83xx_spi_probe);
}
static void __exit mpc83xx_spi_exit(void)
diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c
index e9b683f7d7b3..89d6685a5ca4 100644
--- a/drivers/spi/spi_s3c24xx.c
+++ b/drivers/spi/spi_s3c24xx.c
@@ -233,7 +233,7 @@ static irqreturn_t s3c24xx_spi_irq(int irq, void *dev)
return IRQ_HANDLED;
}
-static int s3c24xx_spi_probe(struct platform_device *pdev)
+static int __init s3c24xx_spi_probe(struct platform_device *pdev)
{
struct s3c24xx_spi *hw;
struct spi_master *master;
@@ -382,7 +382,7 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
return err;
}
-static int s3c24xx_spi_remove(struct platform_device *dev)
+static int __exit s3c24xx_spi_remove(struct platform_device *dev)
{
struct s3c24xx_spi *hw = platform_get_drvdata(dev);
@@ -429,8 +429,7 @@ static int s3c24xx_spi_resume(struct platform_device *pdev)
MODULE_ALIAS("s3c2410_spi"); /* for platform bus hotplug */
static struct platform_driver s3c24xx_spidrv = {
- .probe = s3c24xx_spi_probe,
- .remove = s3c24xx_spi_remove,
+ .remove = __exit_p(s3c24xx_spi_remove),
.suspend = s3c24xx_spi_suspend,
.resume = s3c24xx_spi_resume,
.driver = {
@@ -441,7 +440,7 @@ static struct platform_driver s3c24xx_spidrv = {
static int __init s3c24xx_spi_init(void)
{
- return platform_driver_register(&s3c24xx_spidrv);
+ return platform_driver_probe(&s3c24xx_spidrv, s3c24xx_spi_probe);
}
static void __exit s3c24xx_spi_exit(void)
diff --git a/drivers/spi/spi_txx9.c b/drivers/spi/spi_txx9.c
index b7f4bb239eaf..363ac8e68821 100644
--- a/drivers/spi/spi_txx9.c
+++ b/drivers/spi/spi_txx9.c
@@ -24,6 +24,7 @@
#include <linux/spi/spi.h>
#include <linux/err.h>
#include <linux/clk.h>
+#include <linux/io.h>
#include <asm/gpio.h>
@@ -74,7 +75,6 @@ struct txx9spi {
struct list_head queue;
wait_queue_head_t waitq;
void __iomem *membase;
- int irq;
int baseclk;
struct clk *clk;
u32 max_speed_hz, min_speed_hz;
@@ -350,12 +350,12 @@ static int __init txx9spi_probe(struct platform_device *dev)
struct resource *res;
int ret = -ENODEV;
u32 mcr;
+ int irq;
master = spi_alloc_master(&dev->dev, sizeof(*c));
if (!master)
return ret;
c = spi_master_get_devdata(master);
- c->irq = -1;
platform_set_drvdata(dev, master);
INIT_WORK(&c->work, txx9spi_work);
@@ -381,32 +381,36 @@ static int __init txx9spi_probe(struct platform_device *dev)
res = platform_get_resource(dev, IORESOURCE_MEM, 0);
if (!res)
- goto exit;
- c->membase = ioremap(res->start, res->end - res->start + 1);
+ goto exit_busy;
+ if (!devm_request_mem_region(&dev->dev,
+ res->start, res->end - res->start + 1,
+ "spi_txx9"))
+ goto exit_busy;
+ c->membase = devm_ioremap(&dev->dev,
+ res->start, res->end - res->start + 1);
if (!c->membase)
- goto exit;
+ goto exit_busy;
/* enter config mode */
mcr = txx9spi_rd(c, TXx9_SPMCR);
mcr &= ~(TXx9_SPMCR_OPMODE | TXx9_SPMCR_SPSTP | TXx9_SPMCR_BCLR);
txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR, TXx9_SPMCR);
- c->irq = platform_get_irq(dev, 0);
- if (c->irq < 0)
- goto exit;
- ret = request_irq(c->irq, txx9spi_interrupt, 0, dev->name, c);
- if (ret) {
- c->irq = -1;
+ irq = platform_get_irq(dev, 0);
+ if (irq < 0)
+ goto exit_busy;
+ ret = devm_request_irq(&dev->dev, irq, txx9spi_interrupt, 0,
+ "spi_txx9", c);
+ if (ret)
goto exit;
- }
- c->workqueue = create_singlethread_workqueue(master->cdev.dev->bus_id);
+ c->workqueue = create_singlethread_workqueue(master->dev.parent->bus_id);
if (!c->workqueue)
- goto exit;
+ goto exit_busy;
c->last_chipselect = -1;
dev_info(&dev->dev, "at %#llx, irq %d, %dMHz\n",
- (unsigned long long)res->start, c->irq,
+ (unsigned long long)res->start, irq,
(c->baseclk + 500000) / 1000000);
master->bus_num = dev->id;
@@ -418,13 +422,11 @@ static int __init txx9spi_probe(struct platform_device *dev)
if (ret)
goto exit;
return 0;
+exit_busy:
+ ret = -EBUSY;
exit:
if (c->workqueue)
destroy_workqueue(c->workqueue);
- if (c->irq >= 0)
- free_irq(c->irq, c);
- if (c->membase)
- iounmap(c->membase);
if (c->clk) {
clk_disable(c->clk);
clk_put(c->clk);
@@ -442,8 +444,6 @@ static int __exit txx9spi_remove(struct platform_device *dev)
spi_unregister_master(master);
platform_set_drvdata(dev, NULL);
destroy_workqueue(c->workqueue);
- free_irq(c->irq, c);
- iounmap(c->membase);
clk_disable(c->clk);
clk_put(c->clk);
spi_master_put(master);
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index c55459c592b8..b3518ca9f04e 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -184,14 +184,14 @@ static int spidev_message(struct spidev_data *spidev,
if (u_tmp->rx_buf) {
k_tmp->rx_buf = buf;
if (!access_ok(VERIFY_WRITE, (u8 __user *)
- (ptrdiff_t) u_tmp->rx_buf,
+ (uintptr_t) u_tmp->rx_buf,
u_tmp->len))
goto done;
}
if (u_tmp->tx_buf) {
k_tmp->tx_buf = buf;
if (copy_from_user(buf, (const u8 __user *)
- (ptrdiff_t) u_tmp->tx_buf,
+ (uintptr_t) u_tmp->tx_buf,
u_tmp->len))
goto done;
}
@@ -224,7 +224,7 @@ static int spidev_message(struct spidev_data *spidev,
for (n = n_xfers, u_tmp = u_xfers; n; n--, u_tmp++) {
if (u_tmp->rx_buf) {
if (__copy_to_user((u8 __user *)
- (ptrdiff_t) u_tmp->rx_buf, buf,
+ (uintptr_t) u_tmp->rx_buf, buf,
u_tmp->len)) {
status = -EFAULT;
goto done;
diff --git a/drivers/spi/tle62x0.c b/drivers/spi/tle62x0.c
index 6da58ca48b33..455991fbe28f 100644
--- a/drivers/spi/tle62x0.c
+++ b/drivers/spi/tle62x0.c
@@ -107,8 +107,11 @@ static ssize_t tle62x0_status_show(struct device *dev,
mutex_lock(&st->lock);
ret = tle62x0_read(st);
-
dev_dbg(dev, "tle62x0_read() returned %d\n", ret);
+ if (ret < 0) {
+ mutex_unlock(&st->lock);
+ return ret;
+ }
for (ptr = 0; ptr < (st->nr_gpio * 2)/8; ptr += 1) {
fault <<= 8;
diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig
index b4a5e5e9d9fc..d976660cb7f0 100644
--- a/drivers/ssb/Kconfig
+++ b/drivers/ssb/Kconfig
@@ -22,7 +22,7 @@ config SSB
config SSB_PCIHOST_POSSIBLE
bool
- depends on SSB && PCI
+ depends on SSB && (PCI = y || PCI = SSB)
default y
config SSB_PCIHOST
@@ -37,7 +37,7 @@ config SSB_PCIHOST
config SSB_PCMCIAHOST_POSSIBLE
bool
- depends on SSB && PCMCIA && EXPERIMENTAL
+ depends on SSB && (PCMCIA = y || PCMCIA = SSB) && EXPERIMENTAL
default y
config SSB_PCMCIAHOST
diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c
index ab8691a32580..3d3dd32bf3ab 100644
--- a/drivers/ssb/driver_mipscore.c
+++ b/drivers/ssb/driver_mipscore.c
@@ -173,7 +173,7 @@ u32 ssb_cpu_clock(struct ssb_mipscore *mcore)
void ssb_mipscore_init(struct ssb_mipscore *mcore)
{
- struct ssb_bus *bus = mcore->dev->bus;
+ struct ssb_bus *bus;
struct ssb_device *dev;
unsigned long hz, ns;
unsigned int irq, i;
@@ -183,6 +183,7 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore)
ssb_dprintk(KERN_INFO PFX "Initializing MIPS core...\n");
+ bus = mcore->dev->bus;
hz = ssb_clockspeed(bus);
if (!hz)
hz = 100000000;
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
index c12a741b5574..85a20546e827 100644
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -440,6 +440,7 @@ static int ssb_devices_register(struct ssb_bus *bus)
break;
case SSB_BUSTYPE_PCMCIA:
#ifdef CONFIG_SSB_PCMCIAHOST
+ sdev->irq = bus->host_pcmcia->irq.AssignedIRQ;
dev->parent = &bus->host_pcmcia->dev;
#endif
break;
@@ -1147,7 +1148,10 @@ static int __init ssb_modinit(void)
return err;
}
-subsys_initcall(ssb_modinit);
+/* ssb must be initialized after PCI but before the ssb drivers.
+ * That means we must use some initcall between subsys_initcall
+ * and device_initcall. */
+fs_initcall(ssb_modinit);
static void __exit ssb_modexit(void)
{
diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c
index b6abee846f02..bb44a76b3eb5 100644
--- a/drivers/ssb/pcmcia.c
+++ b/drivers/ssb/pcmcia.c
@@ -63,17 +63,17 @@ int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus,
err = pcmcia_access_configuration_register(pdev, &reg);
if (err != CS_SUCCESS)
goto error;
- read_addr |= (reg.Value & 0xF) << 12;
+ read_addr |= ((u32)(reg.Value & 0x0F)) << 12;
reg.Offset = 0x30;
err = pcmcia_access_configuration_register(pdev, &reg);
if (err != CS_SUCCESS)
goto error;
- read_addr |= reg.Value << 16;
+ read_addr |= ((u32)reg.Value) << 16;
reg.Offset = 0x32;
err = pcmcia_access_configuration_register(pdev, &reg);
if (err != CS_SUCCESS)
goto error;
- read_addr |= reg.Value << 24;
+ read_addr |= ((u32)reg.Value) << 24;
cur_core = (read_addr - SSB_ENUM_BASE) / SSB_CORE_SIZE;
if (cur_core == coreidx)
@@ -152,28 +152,29 @@ error:
goto out_unlock;
}
-/* These are the main device register access functions.
- * do_select_core is inline to have the likely hotpath inline.
- * All unlikely codepaths are out-of-line. */
-static inline int do_select_core(struct ssb_bus *bus,
- struct ssb_device *dev,
- u16 *offset)
+static int select_core_and_segment(struct ssb_device *dev,
+ u16 *offset)
{
+ struct ssb_bus *bus = dev->bus;
int err;
- u8 need_seg = (*offset >= 0x800) ? 1 : 0;
+ u8 need_segment;
+
+ if (*offset >= 0x800) {
+ *offset -= 0x800;
+ need_segment = 1;
+ } else
+ need_segment = 0;
if (unlikely(dev != bus->mapped_device)) {
err = ssb_pcmcia_switch_core(bus, dev);
if (unlikely(err))
return err;
}
- if (unlikely(need_seg != bus->mapped_pcmcia_seg)) {
- err = ssb_pcmcia_switch_segment(bus, need_seg);
+ if (unlikely(need_segment != bus->mapped_pcmcia_seg)) {
+ err = ssb_pcmcia_switch_segment(bus, need_segment);
if (unlikely(err))
return err;
}
- if (need_seg == 1)
- *offset -= 0x800;
return 0;
}
@@ -181,32 +182,31 @@ static inline int do_select_core(struct ssb_bus *bus,
static u16 ssb_pcmcia_read16(struct ssb_device *dev, u16 offset)
{
struct ssb_bus *bus = dev->bus;
- u16 x;
- if (unlikely(do_select_core(bus, dev, &offset)))
+ if (unlikely(select_core_and_segment(dev, &offset)))
return 0xFFFF;
- x = readw(bus->mmio + offset);
- return x;
+ return readw(bus->mmio + offset);
}
static u32 ssb_pcmcia_read32(struct ssb_device *dev, u16 offset)
{
struct ssb_bus *bus = dev->bus;
- u32 x;
+ u32 lo, hi;
- if (unlikely(do_select_core(bus, dev, &offset)))
+ if (unlikely(select_core_and_segment(dev, &offset)))
return 0xFFFFFFFF;
- x = readl(bus->mmio + offset);
+ lo = readw(bus->mmio + offset);
+ hi = readw(bus->mmio + offset + 2);
- return x;
+ return (lo | (hi << 16));
}
static void ssb_pcmcia_write16(struct ssb_device *dev, u16 offset, u16 value)
{
struct ssb_bus *bus = dev->bus;
- if (unlikely(do_select_core(bus, dev, &offset)))
+ if (unlikely(select_core_and_segment(dev, &offset)))
return;
writew(value, bus->mmio + offset);
}
@@ -215,12 +215,12 @@ static void ssb_pcmcia_write32(struct ssb_device *dev, u16 offset, u32 value)
{
struct ssb_bus *bus = dev->bus;
- if (unlikely(do_select_core(bus, dev, &offset)))
+ if (unlikely(select_core_and_segment(dev, &offset)))
return;
- readw(bus->mmio + offset);
- writew(value >> 16, bus->mmio + offset + 2);
- readw(bus->mmio + offset);
- writew(value, bus->mmio + offset);
+ writeb((value & 0xFF000000) >> 24, bus->mmio + offset + 3);
+ writeb((value & 0x00FF0000) >> 16, bus->mmio + offset + 2);
+ writeb((value & 0x0000FF00) >> 8, bus->mmio + offset + 1);
+ writeb((value & 0x000000FF) >> 0, bus->mmio + offset + 0);
}
/* Not "static", as it's used in main.c */
diff --git a/drivers/tc/.gitignore b/drivers/tc/.gitignore
deleted file mode 100644
index acc0e1e6a650..000000000000
--- a/drivers/tc/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-lk201-map.c
diff --git a/drivers/tc/Makefile b/drivers/tc/Makefile
index c899246bd362..623b21063228 100644
--- a/drivers/tc/Makefile
+++ b/drivers/tc/Makefile
@@ -5,18 +5,3 @@
# Object file lists.
obj-$(CONFIG_TC) += tc.o tc-driver.o
-obj-$(CONFIG_VT) += lk201.o lk201-map.o lk201-remap.o
-
-$(obj)/lk201-map.o: $(obj)/lk201-map.c
-
-# Uncomment if you're changing the keymap and have an appropriate
-# loadkeys version for the map. By default, we'll use the shipped
-# versions.
-# GENERATE_KEYMAP := 1
-
-ifdef GENERATE_KEYMAP
-
-$(obj)/lk201-map.c: $(obj)/%.c: $(src)/%.map
- loadkeys --mktable $< > $@
-
-endif
diff --git a/drivers/tc/lk201-map.c_shipped b/drivers/tc/lk201-map.c_shipped
deleted file mode 100644
index a9df8f5bf62b..000000000000
--- a/drivers/tc/lk201-map.c_shipped
+++ /dev/null
@@ -1,265 +0,0 @@
-
-/* Do not edit this file! It was automatically generated by */
-/* loadkeys --mktable defkeymap.map > defkeymap.c */
-
-#include <linux/types.h>
-#include <linux/keyboard.h>
-#include <linux/kd.h>
-
-u_short plain_map[NR_KEYS] = {
- 0xf200, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104, 0xf105, 0xf106,
- 0xf107, 0xf108, 0xf109, 0xf10a, 0xf10b, 0xf10c, 0xf10d, 0xf11b,
- 0xf11c, 0xf110, 0xf111, 0xf112, 0xf113, 0xf060, 0xf031, 0xf032,
- 0xf033, 0xf034, 0xf035, 0xf036, 0xf037, 0xf038, 0xf039, 0xf030,
- 0xf02d, 0xf03d, 0xf07f, 0xf114, 0xf115, 0xf116, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf009, 0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74,
- 0xfb79, 0xfb75, 0xfb69, 0xfb6f, 0xfb70, 0xf05b, 0xf05d, 0xf201,
- 0xf117, 0xf118, 0xf119, 0xf307, 0xf308, 0xf309, 0xf30b, 0xf702,
- 0xf207, 0xfb61, 0xfb73, 0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a,
- 0xfb6b, 0xfb6c, 0xf03b, 0xf027, 0xf05c, 0xf603, 0xf304, 0xf305,
- 0xf306, 0xf200, 0xf700, 0xf03e, 0xfb7a, 0xfb78, 0xfb63, 0xfb76,
- 0xfb62, 0xfb6e, 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf200, 0xf601,
- 0xf600, 0xf602, 0xf301, 0xf302, 0xf303, 0xf30e, 0xf200, 0xf703,
- 0xf020, 0xf200, 0xf200, 0xf300, 0xf310, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-};
-
-static u_short shift_map[NR_KEYS] = {
- 0xf200, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104, 0xf105, 0xf106,
- 0xf107, 0xf108, 0xf109, 0xf10a, 0xf10b, 0xf10c, 0xf10d, 0xf203,
- 0xf11c, 0xf110, 0xf111, 0xf112, 0xf113, 0xf07e, 0xf021, 0xf040,
- 0xf023, 0xf024, 0xf025, 0xf05e, 0xf026, 0xf02a, 0xf028, 0xf029,
- 0xf05f, 0xf02b, 0xf07f, 0xf114, 0xf115, 0xf116, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf009, 0xfb51, 0xfb57, 0xfb45, 0xfb52, 0xfb54,
- 0xfb59, 0xfb55, 0xfb49, 0xfb4f, 0xfb50, 0xf07b, 0xf07d, 0xf201,
- 0xf117, 0xf20b, 0xf20a, 0xf307, 0xf308, 0xf309, 0xf30b, 0xf702,
- 0xf207, 0xfb41, 0xfb53, 0xfb44, 0xfb46, 0xfb47, 0xfb48, 0xfb4a,
- 0xfb4b, 0xfb4c, 0xf03a, 0xf022, 0xf07c, 0xf603, 0xf304, 0xf305,
- 0xf306, 0xf200, 0xf700, 0xf03c, 0xfb5a, 0xfb58, 0xfb43, 0xfb56,
- 0xfb42, 0xfb4e, 0xfb4d, 0xf03c, 0xf03e, 0xf03f, 0xf200, 0xf601,
- 0xf600, 0xf602, 0xf301, 0xf302, 0xf303, 0xf30e, 0xf200, 0xf703,
- 0xf020, 0xf200, 0xf200, 0xf300, 0xf310, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-};
-
-static u_short altgr_map[NR_KEYS] = {
- 0xf200, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104, 0xf105, 0xf106,
- 0xf107, 0xf108, 0xf109, 0xf10a, 0xf10b, 0xf10c, 0xf10d, 0xf202,
- 0xf11c, 0xf110, 0xf111, 0xf112, 0xf113, 0xf200, 0xf200, 0xf040,
- 0xf200, 0xf024, 0xf200, 0xf200, 0xf07b, 0xf05b, 0xf05d, 0xf07d,
- 0xf05c, 0xf200, 0xf200, 0xf114, 0xf115, 0xf116, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xfb71, 0xfb77, 0xf918, 0xfb72, 0xfb74,
- 0xfb79, 0xfb75, 0xfb69, 0xfb6f, 0xfb70, 0xf200, 0xf07e, 0xf201,
- 0xf117, 0xf118, 0xf119, 0xf911, 0xf912, 0xf913, 0xf30b, 0xf702,
- 0xf207, 0xf914, 0xfb73, 0xf917, 0xf919, 0xfb67, 0xfb68, 0xfb6a,
- 0xfb6b, 0xfb6c, 0xf200, 0xf200, 0xf200, 0xf603, 0xf90e, 0xf90f,
- 0xf910, 0xf200, 0xf700, 0xf200, 0xfb7a, 0xfb78, 0xf916, 0xfb76,
- 0xf915, 0xfb6e, 0xfb6d, 0xf200, 0xf200, 0xf200, 0xf200, 0xf601,
- 0xf600, 0xf602, 0xf90b, 0xf90c, 0xf90d, 0xf30e, 0xf200, 0xf703,
- 0xf200, 0xf200, 0xf200, 0xf90a, 0xf310, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-};
-
-static u_short ctrl_map[NR_KEYS] = {
- 0xf200, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104, 0xf105, 0xf106,
- 0xf107, 0xf108, 0xf109, 0xf10a, 0xf10b, 0xf10c, 0xf10d, 0xf204,
- 0xf11c, 0xf110, 0xf111, 0xf112, 0xf113, 0xf81b, 0xf200, 0xf000,
- 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f, 0xf07f, 0xf200, 0xf200,
- 0xf01f, 0xf200, 0xf008, 0xf114, 0xf115, 0xf116, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf011, 0xf017, 0xf005, 0xf012, 0xf014,
- 0xf019, 0xf015, 0xf009, 0xf00f, 0xf010, 0xf01b, 0xf01d, 0xf201,
- 0xf117, 0xf118, 0xf119, 0xf307, 0xf308, 0xf309, 0xf30b, 0xf702,
- 0xf207, 0xf001, 0xf013, 0xf004, 0xf006, 0xf007, 0xf008, 0xf00a,
- 0xf00b, 0xf00c, 0xf200, 0xf007, 0xf01c, 0xf603, 0xf304, 0xf305,
- 0xf306, 0xf200, 0xf700, 0xf200, 0xf01a, 0xf018, 0xf003, 0xf016,
- 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf20e, 0xf07f, 0xf200, 0xf601,
- 0xf600, 0xf602, 0xf301, 0xf302, 0xf303, 0xf30e, 0xf200, 0xf703,
- 0xf000, 0xf200, 0xf200, 0xf300, 0xf310, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-};
-
-static u_short shift_ctrl_map[NR_KEYS] = {
- 0xf200, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104, 0xf105, 0xf106,
- 0xf107, 0xf108, 0xf109, 0xf10a, 0xf10b, 0xf10c, 0xf10d, 0xf200,
- 0xf11c, 0xf110, 0xf111, 0xf112, 0xf113, 0xf200, 0xf200, 0xf000,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
- 0xf01f, 0xf200, 0xf200, 0xf114, 0xf115, 0xf116, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf011, 0xf017, 0xf005, 0xf012, 0xf014,
- 0xf019, 0xf015, 0xf009, 0xf00f, 0xf010, 0xf200, 0xf200, 0xf201,
- 0xf117, 0xf118, 0xf119, 0xf307, 0xf308, 0xf309, 0xf30b, 0xf702,
- 0xf207, 0xf001, 0xf013, 0xf004, 0xf006, 0xf007, 0xf008, 0xf00a,
- 0xf00b, 0xf00c, 0xf200, 0xf200, 0xf200, 0xf603, 0xf304, 0xf305,
- 0xf306, 0xf200, 0xf700, 0xf200, 0xf01a, 0xf018, 0xf003, 0xf016,
- 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf200, 0xf200, 0xf200, 0xf601,
- 0xf600, 0xf602, 0xf301, 0xf302, 0xf303, 0xf30e, 0xf200, 0xf703,
- 0xf200, 0xf200, 0xf200, 0xf300, 0xf310, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-};
-
-static u_short alt_map[NR_KEYS] = {
- 0xf200, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504, 0xf505, 0xf506,
- 0xf507, 0xf508, 0xf509, 0xf50a, 0xf50b, 0xf50c, 0xf50d, 0xf200,
- 0xf11c, 0xf510, 0xf511, 0xf512, 0xf513, 0xf01b, 0xf831, 0xf832,
- 0xf833, 0xf834, 0xf835, 0xf836, 0xf837, 0xf838, 0xf839, 0xf830,
- 0xf82d, 0xf83d, 0xf87f, 0xf114, 0xf115, 0xf116, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf809, 0xf871, 0xf877, 0xf865, 0xf872, 0xf874,
- 0xf879, 0xf875, 0xf869, 0xf86f, 0xf870, 0xf85b, 0xf85d, 0xf80d,
- 0xf117, 0xf118, 0xf119, 0xf907, 0xf908, 0xf909, 0xf30b, 0xf702,
- 0xf207, 0xf861, 0xf873, 0xf864, 0xf866, 0xf867, 0xf868, 0xf86a,
- 0xf86b, 0xf86c, 0xf83b, 0xf827, 0xf85c, 0xf603, 0xf904, 0xf905,
- 0xf906, 0xf200, 0xf700, 0xf200, 0xf87a, 0xf878, 0xf863, 0xf876,
- 0xf862, 0xf86e, 0xf86d, 0xf82c, 0xf82e, 0xf82f, 0xf200, 0xf210,
- 0xf600, 0xf211, 0xf901, 0xf902, 0xf903, 0xf30e, 0xf200, 0xf703,
- 0xf820, 0xf200, 0xf200, 0xf900, 0xf310, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-};
-
-static u_short ctrl_alt_map[NR_KEYS] = {
- 0xf200, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504, 0xf505, 0xf506,
- 0xf507, 0xf508, 0xf509, 0xf50a, 0xf50b, 0xf50c, 0xf50d, 0xf200,
- 0xf11c, 0xf510, 0xf511, 0xf512, 0xf513, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf114, 0xf115, 0xf20c, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf811, 0xf817, 0xf805, 0xf812, 0xf814,
- 0xf819, 0xf815, 0xf809, 0xf80f, 0xf810, 0xf200, 0xf200, 0xf201,
- 0xf117, 0xf118, 0xf119, 0xf307, 0xf308, 0xf309, 0xf30b, 0xf702,
- 0xf207, 0xf801, 0xf813, 0xf804, 0xf806, 0xf807, 0xf808, 0xf80a,
- 0xf80b, 0xf80c, 0xf200, 0xf200, 0xf200, 0xf603, 0xf304, 0xf305,
- 0xf306, 0xf200, 0xf700, 0xf200, 0xf81a, 0xf818, 0xf803, 0xf816,
- 0xf802, 0xf80e, 0xf80d, 0xf200, 0xf200, 0xf200, 0xf200, 0xf601,
- 0xf600, 0xf602, 0xf301, 0xf302, 0xf303, 0xf30e, 0xf200, 0xf703,
- 0xf200, 0xf200, 0xf200, 0xf300, 0xf20c, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-};
-
-ushort *key_maps[MAX_NR_KEYMAPS] = {
- plain_map, shift_map, altgr_map, 0,
- ctrl_map, shift_ctrl_map, 0, 0,
- alt_map, 0, 0, 0,
- ctrl_alt_map, 0
-};
-
-unsigned int keymap_count = 7;
-
-
-/*
- * Philosophy: most people do not define more strings, but they who do
- * often want quite a lot of string space. So, we statically allocate
- * the default and allocate dynamically in chunks of 512 bytes.
- */
-
-char func_buf[] = {
- '\033', '[', '[', 'A', 0,
- '\033', '[', '[', 'B', 0,
- '\033', '[', '[', 'C', 0,
- '\033', '[', '[', 'D', 0,
- '\033', '[', '[', 'E', 0,
- '\033', '[', '1', '7', '~', 0,
- '\033', '[', '1', '8', '~', 0,
- '\033', '[', '1', '9', '~', 0,
- '\033', '[', '2', '0', '~', 0,
- '\033', '[', '2', '1', '~', 0,
- '\033', '[', '2', '3', '~', 0,
- '\033', '[', '2', '4', '~', 0,
- '\033', '[', '2', '5', '~', 0,
- '\033', '[', '2', '6', '~', 0,
- '\033', '[', '2', '8', '~', 0,
- '\033', '[', '2', '9', '~', 0,
- '\033', '[', '3', '1', '~', 0,
- '\033', '[', '3', '2', '~', 0,
- '\033', '[', '3', '3', '~', 0,
- '\033', '[', '3', '4', '~', 0,
- '\033', '[', '1', '~', 0,
- '\033', '[', '2', '~', 0,
- '\033', '[', '3', '~', 0,
- '\033', '[', '4', '~', 0,
- '\033', '[', '5', '~', 0,
- '\033', '[', '6', '~', 0,
- '\033', '[', 'M', 0,
- '\033', '[', 'P', 0,
-};
-
-
-char *funcbufptr = func_buf;
-int funcbufsize = sizeof(func_buf);
-int funcbufleft = 0; /* space left */
-
-char *func_table[MAX_NR_FUNC] = {
- func_buf + 0,
- func_buf + 5,
- func_buf + 10,
- func_buf + 15,
- func_buf + 20,
- func_buf + 25,
- func_buf + 31,
- func_buf + 37,
- func_buf + 43,
- func_buf + 49,
- func_buf + 55,
- func_buf + 61,
- func_buf + 67,
- func_buf + 73,
- func_buf + 79,
- func_buf + 85,
- func_buf + 91,
- func_buf + 97,
- func_buf + 103,
- func_buf + 109,
- func_buf + 115,
- func_buf + 120,
- func_buf + 125,
- func_buf + 130,
- func_buf + 135,
- func_buf + 140,
- func_buf + 145,
- 0,
- 0,
- func_buf + 149,
- 0,
-};
-
-struct kbdiacr accent_table[MAX_DIACR] = {
- {'`', 'A', 'À'}, {'`', 'a', 'à'},
- {'\'', 'A', 'Á'}, {'\'', 'a', 'á'},
- {'^', 'A', 'Â'}, {'^', 'a', 'â'},
- {'~', 'A', 'Ã'}, {'~', 'a', 'ã'},
- {'"', 'A', 'Ä'}, {'"', 'a', 'ä'},
- {'O', 'A', 'Å'}, {'o', 'a', 'å'},
- {'0', 'A', 'Å'}, {'0', 'a', 'å'},
- {'A', 'A', 'Å'}, {'a', 'a', 'å'},
- {'A', 'E', 'Æ'}, {'a', 'e', 'æ'},
- {',', 'C', 'Ç'}, {',', 'c', 'ç'},
- {'`', 'E', 'È'}, {'`', 'e', 'è'},
- {'\'', 'E', 'É'}, {'\'', 'e', 'é'},
- {'^', 'E', 'Ê'}, {'^', 'e', 'ê'},
- {'"', 'E', 'Ë'}, {'"', 'e', 'ë'},
- {'`', 'I', 'Ì'}, {'`', 'i', 'ì'},
- {'\'', 'I', 'Í'}, {'\'', 'i', 'í'},
- {'^', 'I', 'Î'}, {'^', 'i', 'î'},
- {'"', 'I', 'Ï'}, {'"', 'i', 'ï'},
- {'-', 'D', 'Ð'}, {'-', 'd', 'ð'},
- {'~', 'N', 'Ñ'}, {'~', 'n', 'ñ'},
- {'`', 'O', 'Ò'}, {'`', 'o', 'ò'},
- {'\'', 'O', 'Ó'}, {'\'', 'o', 'ó'},
- {'^', 'O', 'Ô'}, {'^', 'o', 'ô'},
- {'~', 'O', 'Õ'}, {'~', 'o', 'õ'},
- {'"', 'O', 'Ö'}, {'"', 'o', 'ö'},
- {'/', 'O', 'Ø'}, {'/', 'o', 'ø'},
- {'`', 'U', 'Ù'}, {'`', 'u', 'ù'},
- {'\'', 'U', 'Ú'}, {'\'', 'u', 'ú'},
- {'^', 'U', 'Û'}, {'^', 'u', 'û'},
- {'"', 'U', 'Ü'}, {'"', 'u', 'ü'},
- {'\'', 'Y', 'Ý'}, {'\'', 'y', 'ý'},
- {'T', 'H', 'Þ'}, {'t', 'h', 'þ'},
- {'s', 's', 'ß'}, {'"', 'y', 'ÿ'},
- {'s', 'z', 'ß'}, {'i', 'j', 'ÿ'},
-};
-
-unsigned int accent_table_size = 68;
diff --git a/drivers/tc/lk201-map.map b/drivers/tc/lk201-map.map
deleted file mode 100644
index 2c636b4b7823..000000000000
--- a/drivers/tc/lk201-map.map
+++ /dev/null
@@ -1,356 +0,0 @@
-# Default kernel keymap. This uses 7 modifier combinations.
-keymaps 0-2,4-5,8,12
-# Change the above line into
-# keymaps 0-2,4-6,8,12
-# in case you want the entries
-# altgr control keycode 83 = Boot
-# altgr control keycode 111 = Boot
-# below.
-#
-# In fact AltGr is used very little, and one more keymap can
-# be saved by mapping AltGr to Alt (and adapting a few entries):
-# keycode 100 = Alt
-#
-keycode 0x15 = grave tilde
- alt keycode 0x15 = Escape
- control keycode 0x15 = Meta_Escape
-keycode 0x16 = one exclam
- alt keycode 0x16 = Meta_one
-keycode 0x17 = two at at
- control keycode 0x17 = nul
- shift control keycode 0x17 = nul
- alt keycode 0x17 = Meta_two
-keycode 0x18 = three numbersign
- control keycode 0x18 = Escape
- alt keycode 0x18 = Meta_three
-keycode 0x19 = four dollar dollar
- control keycode 0x19 = Control_backslash
- alt keycode 0x19 = Meta_four
-keycode 0x1a = five percent
- control keycode 0x1a = Control_bracketright
- alt keycode 0x1a = Meta_five
-keycode 0x1b = six asciicircum
- control keycode 0x1b = Control_asciicircum
- alt keycode 0x1b = Meta_six
-keycode 0x1c = seven ampersand braceleft
- control keycode 0x1c = Control_underscore
- alt keycode 0x1c = Meta_seven
-keycode 0x1d = eight asterisk bracketleft
- control keycode 0x1d = Delete
- alt keycode 0x1d = Meta_eight
-keycode 0x1e = nine parenleft bracketright
- alt keycode 0x1e = Meta_nine
-keycode 0x1f = zero parenright braceright
- alt keycode 0x1f = Meta_zero
-keycode 0x20 = minus underscore backslash
- control keycode 0x20 = Control_underscore
- shift control keycode 0x20 = Control_underscore
- alt keycode 0x20 = Meta_minus
-keycode 0x21 = equal plus
- alt keycode 0x21 = Meta_equal
-keycode 0x22 = Delete Delete
- control keycode 0x22 = BackSpace
- alt keycode 0x22 = Meta_Delete
-keycode 0x2a = Tab Tab
- alt keycode 0x2a = Meta_Tab
-keycode 0x2b = q
-keycode 0x2c = w
-keycode 0x2d = e
- altgr keycode 0x2d = Hex_E
-keycode 0x2e = r
-keycode 0x2f = t
-keycode 0x30 = y
-keycode 0x31 = u
-keycode 0x32 = i
-keycode 0x33 = o
-keycode 0x34 = p
-keycode 0x35 = bracketleft braceleft
- control keycode 0x35 = Escape
- alt keycode 0x35 = Meta_bracketleft
-keycode 0x36 = bracketright braceright asciitilde
- control keycode 0x36 = Control_bracketright
- alt keycode 0x36 = Meta_bracketright
-keycode 0x37 = Return
- alt keycode 0x37 = Meta_Control_m
-keycode 0x3f = Control
-keycode 0x41 = a
- altgr keycode 0x41 = Hex_A
-keycode 0x42 = s
-keycode 0x43 = d
- altgr keycode 0x43 = Hex_D
-keycode 0x44 = f
- altgr keycode 0x44 = Hex_F
-keycode 0x45 = g
-keycode 0x46 = h
-keycode 0x47 = j
-keycode 0x48 = k
-keycode 0x49 = l
-keycode 0x4a = semicolon colon
- alt keycode 0x4a = Meta_semicolon
-keycode 0x4b = apostrophe quotedbl
- control keycode 0x4b = Control_g
- alt keycode 0x4b = Meta_apostrophe
-# keycode 41 = grave asciitilde
-# control keycode 41 = nul
-# alt keycode 41 = Meta_grave
-keycode 0x52 = Shift
-keycode 0x4c = backslash bar
- control keycode 0x4c = Control_backslash
- alt keycode 0x4c = Meta_backslash
-keycode 0x53 = greater less
-keycode 0x54 = z
-keycode 0x55 = x
-keycode 0x56 = c
- altgr keycode 0x56 = Hex_C
-keycode 0x57 = v
-keycode 0x58 = b
- altgr keycode 0x58 = Hex_B
-keycode 0x59 = n
-keycode 0x5a = m
-keycode 0x5b = comma less
- alt keycode 0x5b = Meta_comma
-keycode 0x5c = period greater
- control keycode 0x5c = Compose
- alt keycode 0x5c = Meta_period
-keycode 0x5d = slash question
- control keycode 0x5d = Delete
- alt keycode 0x5d = Meta_slash
-
-keycode 0x67 = Alt
-keycode 0x68 = space space
- control keycode 0x68 = nul
- alt keycode 0x68 = Meta_space
-keycode 0x40 = Caps_Lock
-keycode 0x01 = F1
- control keycode 0x01 = F1
- alt keycode 0x01 = Console_1
- control alt keycode 0x01 = Console_1
-keycode 0x02 = F2
- control keycode 0x02 = F2
- alt keycode 0x02 = Console_2
- control alt keycode 0x02 = Console_2
-keycode 0x03 = F3
- control keycode 0x03 = F3
- alt keycode 0x03 = Console_3
- control alt keycode 0x03 = Console_3
-keycode 0x04 = F4
- control keycode 0x04 = F4
- alt keycode 0x04 = Console_4
- control alt keycode 0x04 = Console_4
-keycode 0x05 = F5
- control keycode 0x05 = F5
- alt keycode 0x05 = Console_5
- control alt keycode 0x05 = Console_5
-keycode 0x06 = F6
- control keycode 0x06 = F6
- alt keycode 0x06 = Console_6
- control alt keycode 0x06 = Console_6
-keycode 0x07 = F7
- control keycode 0x07 = F7
- alt keycode 0x07 = Console_7
- control alt keycode 0x07 = Console_7
-keycode 0x08 = F8
- control keycode 0x08 = F8
- alt keycode 0x08 = Console_8
- control alt keycode 0x08 = Console_8
-keycode 0x09 = F9
- control keycode 0x09 = F9
- alt keycode 0x09 = Console_9
- control alt keycode 0x09 = Console_9
-keycode 0x0a = F10
- control keycode 0x0a = F10
- alt keycode 0x0a = Console_10
- control alt keycode 0x0a = Console_10
-keycode 0x0b = F11
- control keycode 0x0b = F11
- alt keycode 0x0b = Console_11
- control alt keycode 0x0b = Console_11
-keycode 0x0c = F12
- control keycode 0x0c = F12
- alt keycode 0x0c = Console_12
- control alt keycode 0x0c = Console_12
-keycode 0x0d = F13
- control keycode 0x0d = F13
- alt keycode 0x0d = Console_13
- control alt keycode 0x0d = Console_13
-keycode 0x0e = F14
- control keycode 0x0e = F14
- alt keycode 0x0e = Console_14
- control alt keycode 0x0e = Console_14
-
-keycode 0x11 = F17
- control keycode 0x11 = F17
- alt keycode 0x11 = Console_17
- control alt keycode 0x11 = Console_17
-keycode 0x12 = F18
- control keycode 0x12 = F18
- alt keycode 0x12 = Console_18
- control alt keycode 0x12 = Console_18
-keycode 0x13 = F19
- control keycode 0x13 = F19
- alt keycode 0x13 = Console_19
- control alt keycode 0x13 = Console_19
-keycode 0x14 = F20
- control keycode 0x14 = F20
- alt keycode 0x14 = Console_20
- control alt keycode 0x14 = Console_20
-
-
-keycode 0x3b = KP_7
- alt keycode 0x3b = Ascii_7
- altgr keycode 0x3b = Hex_7
-keycode 0x3c = KP_8
- alt keycode 0x3c = Ascii_8
- altgr keycode 0x3c = Hex_8
-keycode 0x3d = KP_9
- alt keycode 0x3d = Ascii_9
- altgr keycode 0x3d = Hex_9
-keycode 0x3e = KP_Subtract
-keycode 0x4e = KP_4
- alt keycode 0x4e = Ascii_4
- altgr keycode 0x4e = Hex_4
-keycode 0x4f = KP_5
- alt keycode 0x4f = Ascii_5
- altgr keycode 0x4f = Hex_5
-keycode 0x50 = KP_6
- alt keycode 0x50 = Ascii_6
- altgr keycode 0x50 = Hex_6
-keycode 0x62 = KP_1
- alt keycode 0x62 = Ascii_1
- altgr keycode 0x62 = Hex_1
-keycode 0x63 = KP_2
- alt keycode 0x63 = Ascii_2
- altgr keycode 0x63 = Hex_2
-keycode 0x64 = KP_3
- alt keycode 0x64 = Ascii_3
- altgr keycode 0x64 = Hex_3
-keycode 0x6b = KP_0
- alt keycode 0x6b = Ascii_0
- altgr keycode 0x6b = Hex_0
-keycode 0x6c = KP_Period
-# altgr control keycode 0x6c = Boot
- control alt keycode 0x6c = Boot
-keycode 0x65 = KP_Enter
-
-keycode 0x3f = Control
-
-# keycode 100 = AltGr
-
-keycode 0x23 = Find
-keycode 0x4d = Up
-keycode 0x39 = Prior
- shift keycode 0x39 = Scroll_Backward
-keycode 0x5f = Left
- alt keycode 0x5f = Decr_Console
-keycode 0x61 = Right
- alt keycode 0x61 = Incr_Console
-keycode 0x38 = Select
-keycode 0x60 = Down
-keycode 0x3a = Next
- shift keycode 0x3a = Scroll_Forward
-keycode 0x24 = Insert
-keycode 0x25 = Remove
-# altgr control keycode 0x25 = Boot
- control alt keycode 0x25 = Boot
-
-keycode 0x0f = Help Show_Memory Show_Registers
- control keycode 0x0f = Show_State
-
-keycode 0x10 = Do
-
-string F1 = "\033[[A"
-string F2 = "\033[[B"
-string F3 = "\033[[C"
-string F4 = "\033[[D"
-string F5 = "\033[[E"
-string F6 = "\033[17~"
-string F7 = "\033[18~"
-string F8 = "\033[19~"
-string F9 = "\033[20~"
-string F10 = "\033[21~"
-string F11 = "\033[23~"
-string F12 = "\033[24~"
-string F13 = "\033[25~"
-string F14 = "\033[26~"
-string F15 = "\033[28~"
-string F16 = "\033[29~"
-string F17 = "\033[31~"
-string F18 = "\033[32~"
-string F19 = "\033[33~"
-string F20 = "\033[34~"
-string Find = "\033[1~"
-string Insert = "\033[2~"
-string Remove = "\033[3~"
-string Select = "\033[4~"
-string Prior = "\033[5~"
-string Next = "\033[6~"
-string Macro = "\033[M"
-string Pause = "\033[P"
-compose '`' 'A' to 'À'
-compose '`' 'a' to 'à'
-compose '\'' 'A' to 'Á'
-compose '\'' 'a' to 'á'
-compose '^' 'A' to 'Â'
-compose '^' 'a' to 'â'
-compose '~' 'A' to 'Ã'
-compose '~' 'a' to 'ã'
-compose '"' 'A' to 'Ä'
-compose '"' 'a' to 'ä'
-compose 'O' 'A' to 'Å'
-compose 'o' 'a' to 'å'
-compose '0' 'A' to 'Å'
-compose '0' 'a' to 'å'
-compose 'A' 'A' to 'Å'
-compose 'a' 'a' to 'å'
-compose 'A' 'E' to 'Æ'
-compose 'a' 'e' to 'æ'
-compose ',' 'C' to 'Ç'
-compose ',' 'c' to 'ç'
-compose '`' 'E' to 'È'
-compose '`' 'e' to 'è'
-compose '\'' 'E' to 'É'
-compose '\'' 'e' to 'é'
-compose '^' 'E' to 'Ê'
-compose '^' 'e' to 'ê'
-compose '"' 'E' to 'Ë'
-compose '"' 'e' to 'ë'
-compose '`' 'I' to 'Ì'
-compose '`' 'i' to 'ì'
-compose '\'' 'I' to 'Í'
-compose '\'' 'i' to 'í'
-compose '^' 'I' to 'Î'
-compose '^' 'i' to 'î'
-compose '"' 'I' to 'Ï'
-compose '"' 'i' to 'ï'
-compose '-' 'D' to 'Ð'
-compose '-' 'd' to 'ð'
-compose '~' 'N' to 'Ñ'
-compose '~' 'n' to 'ñ'
-compose '`' 'O' to 'Ò'
-compose '`' 'o' to 'ò'
-compose '\'' 'O' to 'Ó'
-compose '\'' 'o' to 'ó'
-compose '^' 'O' to 'Ô'
-compose '^' 'o' to 'ô'
-compose '~' 'O' to 'Õ'
-compose '~' 'o' to 'õ'
-compose '"' 'O' to 'Ö'
-compose '"' 'o' to 'ö'
-compose '/' 'O' to 'Ø'
-compose '/' 'o' to 'ø'
-compose '`' 'U' to 'Ù'
-compose '`' 'u' to 'ù'
-compose '\'' 'U' to 'Ú'
-compose '\'' 'u' to 'ú'
-compose '^' 'U' to 'Û'
-compose '^' 'u' to 'û'
-compose '"' 'U' to 'Ü'
-compose '"' 'u' to 'ü'
-compose '\'' 'Y' to 'Ý'
-compose '\'' 'y' to 'ý'
-compose 'T' 'H' to 'Þ'
-compose 't' 'h' to 'þ'
-compose 's' 's' to 'ß'
-compose '"' 'y' to 'ÿ'
-compose 's' 'z' to 'ß'
-compose 'i' 'j' to 'ÿ'
diff --git a/drivers/tc/lk201-remap.c b/drivers/tc/lk201-remap.c
deleted file mode 100644
index d39098c2720e..000000000000
--- a/drivers/tc/lk201-remap.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Keyboard mappings for DEC LK201/401/501 keyboards
- *
- * 17.05.99 Michael Engel (engel@unix-ag.org)
- *
- * DEC US keyboards generate keycodes in the range 0x55 - 0xfb
- *
- * This conflicts with Linux scancode conventions which define
- * 0x00-0x7f as "normal" and 0x80-0xff as "shifted" scancodes, so we
- * have to remap the keycodes to 0x00-0x7f with the scancodeRemap
- * array. The generated scancode is simply the number of the key counted
- * from the left upper to the right lower corner of the keyboard ...
- *
- * These scancodes are then being remapped (I hope ;-)) with the
- * lk501*map[] arrays which define scancode -> Linux code mapping
- *
- * Oh man is this horrible ;-)
- *
- * Scancodes with dual labels exist for keyboards as follows:
- *
- * code: left label / right label
- *
- * 0x73: LKx01, LK421 / LK443, LK444
- * 0x74: LKx01, LK421 / LK443, LK444
- * 0x7c: LKx01, LK421 / LK443, LK444
- * 0x8a: LKx01, LK421 / LK443, LK444
- * 0x8b: LKx01, LK421 / LK443, LK444
- * 0x8c: LKx01, LK421 / LK443, LK444
- * 0x8d: LKx01, LK421 / LK443, LK444
- * 0x8e: LKx01, LK421 / LK443, LK444
- * 0x8f: LKx01, LK421 / LK443, LK444
- * 0x9c: LKx01, LK421 / LK443, LK444
- * 0xa1: LKx01, LK421 / LK443, LK444
- * 0xa2: LKx01, LK421 / LK443, LK444
- * 0xa3: LKx01, LK421 / LK443, LK444
- * 0xa4: LKx01, LK421 / LK443, LK444
- * 0xad: LK421 / LK443, LK444
- * 0xc9: LKx01, LK421, LK443 / LK444
- * 0xf7: LKx01, LK443 / LK444
- */
-
-unsigned char scancodeRemap[256] = {
-/* ----- */
-/* 0 */ 0, 0, 0, 0,
-/* ----- */
-/* 4 */ 0, 0, 0, 0,
-/* ----- */
-/* 8 */ 0, 0, 0, 0,
-/* ----- */
-/* c */ 0, 0, 0, 0,
-/* ----- */
-/* 10 */ 0, 0, 0, 0,
-/* ----- */
-/* 14 */ 0, 0, 0, 0,
-/* ----- */
-/* 18 */ 0, 0, 0, 0,
-/* ----- */
-/* 1c */ 0, 0, 0, 0,
-/* ----- */
-/* 20 */ 0, 0, 0, 0,
-/* ----- */
-/* 24 */ 0, 0, 0, 0,
-/* ----- */
-/* 28 */ 0, 0, 0, 0,
-/* ----- */
-/* 2c */ 0, 0, 0, 0,
-/* ----- */
-/* 30 */ 0, 0, 0, 0,
-/* ----- */
-/* 34 */ 0, 0, 0, 0,
-/* ----- */
-/* 38 */ 0, 0, 0, 0,
-/* ----- */
-/* 3c */ 0, 0, 0, 0,
-/* ----- */
-/* 40 */ 0, 0, 0, 0,
-/* ----- */
-/* 44 */ 0, 0, 0, 0,
-/* ----- */
-/* 48 */ 0, 0, 0, 0,
-/* ----- */
-/* 4c */ 0, 0, 0, 0,
-/* ----- */
-/* 50 */ 0, 0, 0, 0,
-/* ----- ESC F1 F2 */
-/* 54 */ 0, 0, 0x01, 0x02,
-/* ----- F3 F4 F5 */
-/* 58 */ 0x03, 0x04, 0x05, 0,
-/* ----- */
-/* 5c */ 0, 0, 0, 0,
-/* ----- */
-/* 60 */ 0, 0, 0, 0,
-/* ----- F6 F7 F8 F9 */
-/* 64 */ 0x06, 0x07, 0x08, 0x09,
-/* ----- F10 */
-/* 68 */ 0x0a, 0, 0, 0,
-/* ----- */
-/* 6c */ 0, 0, 0, 0,
-/* ----- F11 F12 F13/PRNT SCRN */
-/* 70 */ 0, 0x0b, 0x0c, 0x0d,
-/* ----- F14/SCRL LCK */
-/* 74 */ 0x0e, 0, 0, 0,
-/* ----- */
-/* 78 */ 0, 0, 0, 0,
-/* ----- HELP/PAUSE DO */
-/* 7c */ 0x0f, 0x10, 0, 0,
-/* ----- F17 F18 F19 F20 */
-/* 80 */ 0x11, 0x12, 0x13, 0x14,
-/* ----- */
-/* 84 */ 0, 0, 0, 0,
-/* ----- FIND/INSERT INSERT/HOME */
-/* 88 */ 0, 0, 0x23, 0x24,
-/* ----- REMOVE/PG UP SELECT/DELETE PREVIOUS/END NEXT/PG DN */
-/* 8c */ 0x25, 0x38, 0x39, 0x3a,
-/* ----- KP 0 */
-/* 90 */ 0, 0, 0x6b, 0,
-/* ----- KP . KP ENTER KP 1 KP 2 */
-/* 94 */ 0x6c, 0x65, 0x62, 0x63,
-/* ----- KP 3 KP 4 KP 5 KP 6 */
-/* 98 */ 0x64, 0x4e, 0x4f, 0x50,
-/* ----- KP ,/KP + KP 7 KP 8 KP 9 */
-/* 9c */ 0x51, 0x3b, 0x3c, 0x3d,
-/* ----- KP - KP F1/NUM LCK KP F2/KP / KP F3/KP * */
-/* a0 */ 0x3e, 0x26, 0x27, 0x28,
-/* ----- KP F4/KP - LEFT */
-/* a4 */ 0x29, 0, 0, 0x5f,
-/* ----- RIGHT DOWN UP SHIFT Rt */
-/* a8 */ 0x61, 0x60, 0x4d, 0x5e,
-/* ----- ALT COMP Rt/CTRL Rt SHIFT CONTROL */
-/* ac */ 0, 0, 0x52, 0x3f,
-/* ----- CAPS COMPOSE ALT Rt */
-/* b0 */ 0x40, 0x67, 0, 0,
-/* ----- */
-/* b4 */ 0, 0, 0, 0,
-/* ----- */
-/* b8 */ 0, 0, 0, 0,
-/* ----- BKSP RET TAB ` */
-/* bc */ 0x22, 0x37, 0x2a, 0x15,
-/* ----- 1 q a z */
-/* c0 */ 0x16, 0x2b, 0x41, 0x54,
-/* ----- 2 w s */
-/* c4 */ 0, 0x17, 0x2c, 0x42,
-/* ----- x </\\ 3 */
-/* c8 */ 0x55, 0x53, 0, 0x18,
-/* ----- e d c */
-/* cc */ 0x2d, 0x43, 0x56, 0,
-/* ----- 4 r f v */
-/* d0 */ 0x19, 0x2e, 0x44, 0x57,
-/* ----- SPACE 5 t */
-/* d4 */ 0x68, 0, 0x1a, 0x2f,
-/* ----- g b 6 */
-/* d8 */ 0x45, 0x58, 0, 0x1b,
-/* ----- y h n */
-/* dc */ 0x30, 0x46, 0x59, 0,
-/* ----- 7 u j m */
-/* e0 */ 0x1c, 0x31, 0x47, 0x5a,
-/* ----- 8 i k */
-/* e4 */ 0, 0x1d, 0x32, 0x48,
-/* ----- , 9 o */
-/* e8 */ 0x5b, 0, 0x1e, 0x33,
-/* ----- l . 0 */
-/* ec */ 0x49, 0x5c, 0, 0x1f,
-/* ----- p ; / */
-/* f0 */ 0x34, 0, 0x4a, 0x5d,
-/* ----- = ] \\/\' */
-/* f4 */ 0, 0x21, 0x36, 0x4c,
-/* ----- - [ \' */
-/* f8 */ 0, 0x20, 0x35, 0x4b,
-/* ----- */
-/* fc */ 0, 0, 0, 0,
-};
-
diff --git a/drivers/tc/lk201.c b/drivers/tc/lk201.c
deleted file mode 100644
index a90c255f079d..000000000000
--- a/drivers/tc/lk201.c
+++ /dev/null
@@ -1,439 +0,0 @@
-/*
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1999-2002 Harald Koerfgen <hkoerfg@web.de>
- * Copyright (C) 2001, 2002, 2003, 2004 Maciej W. Rozycki
- */
-
-
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/kbd_ll.h>
-#include <linux/kbd_kern.h>
-#include <linux/vt_kern.h>
-
-#include <asm/keyboard.h>
-#include <asm/dec/tc.h>
-#include <asm/dec/machtype.h>
-#include <asm/dec/serial.h>
-
-#include "lk201.h"
-
-/*
- * Only handle DECstations that have an LK201 interface.
- * Maxine uses LK501 at the Access.Bus and various DECsystems
- * have no keyboard interface at all.
- */
-#define LK_IFACE (mips_machtype == MACH_DS23100 || \
- mips_machtype == MACH_DS5000_200 || \
- mips_machtype == MACH_DS5000_1XX || \
- mips_machtype == MACH_DS5000_2X0)
-/*
- * These use the Z8530 SCC. Others use the DZ11.
- */
-#define LK_IFACE_ZS (mips_machtype == MACH_DS5000_1XX || \
- mips_machtype == MACH_DS5000_2X0)
-
-/* Simple translation table for the SysRq keys */
-
-#ifdef CONFIG_MAGIC_SYSRQ
-/*
- * Actually no translation at all, at least until we figure out
- * how to define SysRq for LK201 and friends. --macro
- */
-unsigned char lk201_sysrq_xlate[128];
-unsigned char *kbd_sysrq_xlate = lk201_sysrq_xlate;
-
-unsigned char kbd_sysrq_key = -1;
-#endif
-
-#define KEYB_LINE 3
-
-static int __init lk201_init(void *);
-static void __init lk201_info(void *);
-static void lk201_rx_char(unsigned char, unsigned char);
-
-static struct dec_serial_hook lk201_hook = {
- .init_channel = lk201_init,
- .init_info = lk201_info,
- .rx_char = NULL,
- .poll_rx_char = NULL,
- .poll_tx_char = NULL,
- .cflags = B4800 | CS8 | CSTOPB | CLOCAL,
-};
-
-/*
- * This is used during keyboard initialisation
- */
-static unsigned char lk201_reset_string[] = {
- LK_CMD_SET_DEFAULTS,
- LK_CMD_MODE(LK_MODE_RPT_DOWN, 1),
- LK_CMD_MODE(LK_MODE_RPT_DOWN, 2),
- LK_CMD_MODE(LK_MODE_RPT_DOWN, 3),
- LK_CMD_MODE(LK_MODE_RPT_DOWN, 4),
- LK_CMD_MODE(LK_MODE_DOWN_UP, 5),
- LK_CMD_MODE(LK_MODE_DOWN_UP, 6),
- LK_CMD_MODE(LK_MODE_RPT_DOWN, 7),
- LK_CMD_MODE(LK_MODE_RPT_DOWN, 8),
- LK_CMD_MODE(LK_MODE_RPT_DOWN, 9),
- LK_CMD_MODE(LK_MODE_RPT_DOWN, 10),
- LK_CMD_MODE(LK_MODE_RPT_DOWN, 11),
- LK_CMD_MODE(LK_MODE_RPT_DOWN, 12),
- LK_CMD_MODE(LK_MODE_DOWN, 13),
- LK_CMD_MODE(LK_MODE_RPT_DOWN, 14),
- LK_CMD_DIS_KEYCLK,
- LK_CMD_ENB_BELL, LK_PARAM_VOLUME(4),
-};
-
-static void *lk201_handle;
-
-static int lk201_send(unsigned char ch)
-{
- if (lk201_hook.poll_tx_char(lk201_handle, ch)) {
- printk(KERN_ERR "lk201: transmit timeout\n");
- return -EIO;
- }
- return 0;
-}
-
-static inline int lk201_get_id(void)
-{
- return lk201_send(LK_CMD_REQ_ID);
-}
-
-static int lk201_reset(void)
-{
- int i, r;
-
- for (i = 0; i < sizeof(lk201_reset_string); i++) {
- r = lk201_send(lk201_reset_string[i]);
- if (r < 0)
- return r;
- }
- return 0;
-}
-
-static void lk201_report(unsigned char id[6])
-{
- char *report = "lk201: keyboard attached, ";
-
- switch (id[2]) {
- case LK_STAT_PWRUP_OK:
- printk(KERN_INFO "%sself-test OK\n", report);
- break;
- case LK_STAT_PWRUP_KDOWN:
- /* The keyboard will resend the power-up ID
- after all keys are released, so we don't
- bother handling the error specially. Still
- there may be a short-circuit inside.
- */
- printk(KERN_ERR "%skey down (stuck?), code: 0x%02x\n",
- report, id[3]);
- break;
- case LK_STAT_PWRUP_ERROR:
- printk(KERN_ERR "%sself-test failure\n", report);
- break;
- default:
- printk(KERN_ERR "%sunknown error: 0x%02x\n",
- report, id[2]);
- }
-}
-
-static void lk201_id(unsigned char id[6])
-{
- /*
- * Report whether there is an LK201 or an LK401
- * The LK401 has ALT keys...
- */
- switch (id[4]) {
- case 1:
- printk(KERN_INFO "lk201: LK201 detected\n");
- break;
- case 2:
- printk(KERN_INFO "lk201: LK401 detected\n");
- break;
- case 3:
- printk(KERN_INFO "lk201: LK443 detected\n");
- break;
- case 4:
- printk(KERN_INFO "lk201: LK421 detected\n");
- break;
- default:
- printk(KERN_WARNING
- "lk201: unknown keyboard detected, ID %d\n", id[4]);
- printk(KERN_WARNING "lk201: ... please report to "
- "<linux-mips@linux-mips.org>\n");
- }
-}
-
-#define DEFAULT_KEYB_REP_DELAY (250/5) /* [5ms] */
-#define DEFAULT_KEYB_REP_RATE 30 /* [cps] */
-
-static struct kbd_repeat kbdrate = {
- DEFAULT_KEYB_REP_DELAY,
- DEFAULT_KEYB_REP_RATE
-};
-
-static void parse_kbd_rate(struct kbd_repeat *r)
-{
- if (r->delay <= 0)
- r->delay = kbdrate.delay;
- if (r->rate <= 0)
- r->rate = kbdrate.rate;
-
- if (r->delay < 5)
- r->delay = 5;
- if (r->delay > 630)
- r->delay = 630;
- if (r->rate < 12)
- r->rate = 12;
- if (r->rate > 127)
- r->rate = 127;
- if (r->rate == 125)
- r->rate = 124;
-}
-
-static int write_kbd_rate(struct kbd_repeat *rep)
-{
- int delay, rate;
- int i;
-
- delay = rep->delay / 5;
- rate = rep->rate;
- for (i = 0; i < 4; i++) {
- if (lk201_hook.poll_tx_char(lk201_handle,
- LK_CMD_RPT_RATE(i)))
- return 1;
- if (lk201_hook.poll_tx_char(lk201_handle,
- LK_PARAM_DELAY(delay)))
- return 1;
- if (lk201_hook.poll_tx_char(lk201_handle,
- LK_PARAM_RATE(rate)))
- return 1;
- }
- return 0;
-}
-
-static int lk201_kbd_rate(struct kbd_repeat *rep)
-{
- if (rep == NULL)
- return -EINVAL;
-
- parse_kbd_rate(rep);
-
- if (write_kbd_rate(rep)) {
- memcpy(rep, &kbdrate, sizeof(struct kbd_repeat));
- return -EIO;
- }
-
- memcpy(&kbdrate, rep, sizeof(struct kbd_repeat));
-
- return 0;
-}
-
-static void lk201_kd_mksound(unsigned int hz, unsigned int ticks)
-{
- if (!ticks)
- return;
-
- /*
- * Can't set frequency and we "approximate"
- * duration by volume. ;-)
- */
- ticks /= HZ / 32;
- if (ticks > 7)
- ticks = 7;
- ticks = 7 - ticks;
-
- if (lk201_hook.poll_tx_char(lk201_handle, LK_CMD_ENB_BELL))
- return;
- if (lk201_hook.poll_tx_char(lk201_handle, LK_PARAM_VOLUME(ticks)))
- return;
- if (lk201_hook.poll_tx_char(lk201_handle, LK_CMD_BELL))
- return;
-}
-
-void kbd_leds(unsigned char leds)
-{
- unsigned char l = 0;
-
- if (!lk201_handle) /* FIXME */
- return;
-
- /* FIXME -- Only Hold and Lock LEDs for now. --macro */
- if (leds & LED_SCR)
- l |= LK_LED_HOLD;
- if (leds & LED_CAP)
- l |= LK_LED_LOCK;
-
- if (lk201_hook.poll_tx_char(lk201_handle, LK_CMD_LEDS_ON))
- return;
- if (lk201_hook.poll_tx_char(lk201_handle, LK_PARAM_LED_MASK(l)))
- return;
- if (lk201_hook.poll_tx_char(lk201_handle, LK_CMD_LEDS_OFF))
- return;
- if (lk201_hook.poll_tx_char(lk201_handle, LK_PARAM_LED_MASK(~l)))
- return;
-}
-
-int kbd_setkeycode(unsigned int scancode, unsigned int keycode)
-{
- return -EINVAL;
-}
-
-int kbd_getkeycode(unsigned int scancode)
-{
- return -EINVAL;
-}
-
-int kbd_translate(unsigned char scancode, unsigned char *keycode,
- char raw_mode)
-{
- *keycode = scancode;
- return 1;
-}
-
-char kbd_unexpected_up(unsigned char keycode)
-{
- return 0x80;
-}
-
-static void lk201_rx_char(unsigned char ch, unsigned char fl)
-{
- static unsigned char id[6];
- static int id_i;
-
- static int shift_state = 0;
- static int prev_scancode;
- unsigned char c = scancodeRemap[ch];
-
- if (fl != TTY_NORMAL && fl != TTY_OVERRUN) {
- printk(KERN_ERR "lk201: keyboard receive error: 0x%02x\n", fl);
- return;
- }
-
- /* Assume this is a power-up ID. */
- if (ch == LK_STAT_PWRUP_ID && !id_i) {
- id[id_i++] = ch;
- return;
- }
-
- /* Handle the power-up sequence. */
- if (id_i) {
- id[id_i++] = ch;
- if (id_i == 4) {
- /* OK, the power-up concluded. */
- lk201_report(id);
- if (id[2] == LK_STAT_PWRUP_OK)
- lk201_get_id();
- else {
- id_i = 0;
- printk(KERN_ERR "lk201: keyboard power-up "
- "error, skipping initialization\n");
- }
- } else if (id_i == 6) {
- /* We got the ID; report it and start operation. */
- id_i = 0;
- lk201_id(id);
- lk201_reset();
- }
- return;
- }
-
- /* Everything else is a scancode/status response. */
- id_i = 0;
- switch (ch) {
- case LK_STAT_RESUME_ERR:
- case LK_STAT_ERROR:
- case LK_STAT_INHIBIT_ACK:
- case LK_STAT_TEST_ACK:
- case LK_STAT_MODE_KEYDOWN:
- case LK_STAT_MODE_ACK:
- break;
- case LK_KEY_LOCK:
- shift_state ^= LK_LOCK;
- handle_scancode(c, (shift_state & LK_LOCK) ? 1 : 0);
- break;
- case LK_KEY_SHIFT:
- shift_state ^= LK_SHIFT;
- handle_scancode(c, (shift_state & LK_SHIFT) ? 1 : 0);
- break;
- case LK_KEY_CTRL:
- shift_state ^= LK_CTRL;
- handle_scancode(c, (shift_state & LK_CTRL) ? 1 : 0);
- break;
- case LK_KEY_COMP:
- shift_state ^= LK_COMP;
- handle_scancode(c, (shift_state & LK_COMP) ? 1 : 0);
- break;
- case LK_KEY_RELEASE:
- if (shift_state & LK_SHIFT)
- handle_scancode(scancodeRemap[LK_KEY_SHIFT], 0);
- if (shift_state & LK_CTRL)
- handle_scancode(scancodeRemap[LK_KEY_CTRL], 0);
- if (shift_state & LK_COMP)
- handle_scancode(scancodeRemap[LK_KEY_COMP], 0);
- if (shift_state & LK_LOCK)
- handle_scancode(scancodeRemap[LK_KEY_LOCK], 0);
- shift_state = 0;
- break;
- case LK_KEY_REPEAT:
- handle_scancode(prev_scancode, 1);
- break;
- default:
- prev_scancode = c;
- handle_scancode(c, 1);
- break;
- }
- tasklet_schedule(&keyboard_tasklet);
-}
-
-static void __init lk201_info(void *handle)
-{
-}
-
-static int __init lk201_init(void *handle)
-{
- /* First install handlers. */
- lk201_handle = handle;
- kbd_rate = lk201_kbd_rate;
- kd_mksound = lk201_kd_mksound;
-
- lk201_hook.rx_char = lk201_rx_char;
-
- /* Then just issue a reset -- the handlers will do the rest. */
- lk201_send(LK_CMD_POWER_UP);
-
- return 0;
-}
-
-void __init kbd_init_hw(void)
-{
- /* Maxine uses LK501 at the Access.Bus. */
- if (!LK_IFACE)
- return;
-
- printk(KERN_INFO "lk201: DECstation LK keyboard driver v0.05.\n");
-
- if (LK_IFACE_ZS) {
- /*
- * kbd_init_hw() is being called before
- * rs_init() so just register the kbd hook
- * and let zs_init do the rest :-)
- */
- if (!register_dec_serial_hook(KEYB_LINE, &lk201_hook))
- unregister_dec_serial_hook(KEYB_LINE);
- } else {
- /*
- * TODO: modify dz.c to allow similar hooks
- * for LK201 handling on DS2100, DS3100, and DS5000/200
- */
- printk(KERN_ERR "lk201: support for DZ11 not yet ready.\n");
- }
-}
diff --git a/drivers/tc/lk201.h b/drivers/tc/lk201.h
deleted file mode 100644
index 99f3203c41b8..000000000000
--- a/drivers/tc/lk201.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Commands to the keyboard processor
- */
-
-#define LK_PARAM 0x80 /* start/end parameter list */
-
-#define LK_CMD_RESUME 0x8b /* resume transmission to the host */
-#define LK_CMD_INHIBIT 0x89 /* stop transmission to the host */
-#define LK_CMD_LEDS_ON 0x13 /* light LEDs */
- /* 1st param: led bitmask */
-#define LK_CMD_LEDS_OFF 0x11 /* turn off LEDs */
- /* 1st param: led bitmask */
-#define LK_CMD_DIS_KEYCLK 0x99 /* disable the keyclick */
-#define LK_CMD_ENB_KEYCLK 0x1b /* enable the keyclick */
- /* 1st param: volume */
-#define LK_CMD_DIS_CTLCLK 0xb9 /* disable the Ctrl keyclick */
-#define LK_CMD_ENB_CTLCLK 0xbb /* enable the Ctrl keyclick */
-#define LK_CMD_SOUND_CLK 0x9f /* emit a keyclick */
-#define LK_CMD_DIS_BELL 0xa1 /* disable the bell */
-#define LK_CMD_ENB_BELL 0x23 /* enable the bell */
- /* 1st param: volume */
-#define LK_CMD_BELL 0xa7 /* emit a bell */
-#define LK_CMD_TMP_NORPT 0xd1 /* disable typematic */
- /* for the currently pressed key */
-#define LK_CMD_ENB_RPT 0xe3 /* enable typematic */
- /* for RPT_DOWN groups */
-#define LK_CMD_DIS_RPT 0xe1 /* disable typematic */
- /* for RPT_DOWN groups */
-#define LK_CMD_RPT_TO_DOWN 0xd9 /* set RPT_DOWN groups to DOWN */
-#define LK_CMD_REQ_ID 0xab /* request the keyboard ID */
-#define LK_CMD_POWER_UP 0xfd /* init power-up sequence */
-#define LK_CMD_TEST_MODE 0xcb /* enter the factory test mode */
-#define LK_CMD_TEST_EXIT 0x80 /* exit the factory test mode */
-#define LK_CMD_SET_DEFAULTS 0xd3 /* set power-up defaults */
-
-#define LK_CMD_MODE(m,div) (LK_PARAM|(((div)&0xf)<<3)|(((m)&0x3)<<1))
- /* select the repeat mode */
- /* for the selected key group */
-#define LK_CMD_MODE_AR(m,div) ((((div)&0xf)<<3)|(((m)&0x3)<<1))
- /* select the repeat mode */
- /* and the repeat register */
- /* for the selected key group */
- /* 1st param: register number */
-#define LK_CMD_RPT_RATE(r) (0x78|(((r)&0x3)<<1))
- /* set the delay and repeat rate */
- /* for the selected repeat register */
- /* 1st param: initial delay */
- /* 2nd param: repeat rate */
-
-/* there are 4 leds, represent them in the low 4 bits of a byte */
-#define LK_PARAM_LED_MASK(ledbmap) (LK_PARAM|((ledbmap)&0xf))
-#define LK_LED_WAIT 0x1 /* Wait LED */
-#define LK_LED_COMP 0x2 /* Compose LED */
-#define LK_LED_LOCK 0x4 /* Lock LED */
-#define LK_LED_HOLD 0x8 /* Hold Screen LED */
-
-/* max volume is 0, lowest is 0x7 */
-#define LK_PARAM_VOLUME(v) (LK_PARAM|((v)&0x7))
-
-/* mode set command details, div is a key group number */
-#define LK_MODE_DOWN 0x0 /* make only */
-#define LK_MODE_RPT_DOWN 0x1 /* make and typematic */
-#define LK_MODE_DOWN_UP 0x3 /* make and release */
-
-/* there are 4 repeat registers */
-#define LK_PARAM_AR(r) (LK_PARAM|((v)&0x3))
-
-/*
- * Mappings between key groups and keycodes are as follows:
- *
- * 1: 0xbf - 0xff -- alphanumeric,
- * 2: 0x91 - 0xa5 -- numeric keypad,
- * 3: 0xbc -- Backspace,
- * 4: 0xbd - 0xbe -- Tab, Return,
- * 5: 0xb0 - 0xb2 -- Lock, Compose Character,
- * 6: 0xad - 0xaf -- Ctrl, Shift,
- * 7: 0xa6 - 0xa8 -- Left Arrow, Right Arrow,
- * 8: 0xa9 - 0xac -- Up Arrow, Down Arrow, Right Shift,
- * 9: 0x88 - 0x90 -- editor keypad,
- * 10: 0x56 - 0x62 -- F1 - F5,
- * 11: 0x63 - 0x6e -- F6 - F10,
- * 12: 0x6f - 0x7a -- F11 - F14,
- * 13: 0x7b - 0x7d -- Help, Do,
- * 14: 0x7e - 0x87 -- F17 - F20.
- *
- * Notes:
- * 1. Codes in the 0x00 - 0x40 range are reserved.
- * 2. The assignment of the 0x41 - 0x55 range is undiscovered, probably 10.
- */
-
-/* delay is 5 - 630 ms; 0x00 and 0x7f are reserved */
-#define LK_PARAM_DELAY(t) ((t)&0x7f)
-
-/* rate is 12 - 127 Hz; 0x00 - 0x0b and 0x7d (power-up!) are reserved */
-#define LK_PARAM_RATE(r) (LK_PARAM|((r)&0x7f))
-
-#define LK_SHIFT 1<<0
-#define LK_CTRL 1<<1
-#define LK_LOCK 1<<2
-#define LK_COMP 1<<3
-
-#define LK_KEY_SHIFT 0xae
-#define LK_KEY_CTRL 0xaf
-#define LK_KEY_LOCK 0xb0
-#define LK_KEY_COMP 0xb1
-
-#define LK_KEY_RELEASE 0xb3 /* all keys released */
-#define LK_KEY_REPEAT 0xb4 /* repeat the last key */
-
-/* status responses */
-#define LK_STAT_RESUME_ERR 0xb5 /* keystrokes lost while inhibited */
-#define LK_STAT_ERROR 0xb6 /* an invalid command received */
-#define LK_STAT_INHIBIT_ACK 0xb7 /* transmission inhibited */
-#define LK_STAT_TEST_ACK 0xb8 /* the factory test mode entered */
-#define LK_STAT_MODE_KEYDOWN 0xb9 /* a key is down on a change */
- /* to the DOWN_UP mode; */
- /* the keycode follows */
-#define LK_STAT_MODE_ACK 0xba /* the mode command succeeded */
-
-#define LK_STAT_PWRUP_ID 0x01 /* the power-up response start mark */
-#define LK_STAT_PWRUP_OK 0x00 /* the power-up self test OK */
-#define LK_STAT_PWRUP_KDOWN 0x3d /* a key was down during the test */
-#define LK_STAT_PWRUP_ERROR 0x3e /* keyboard self test failure */
-
-extern unsigned char scancodeRemap[256];
diff --git a/drivers/telephony/Kconfig b/drivers/telephony/Kconfig
index 5f98f673f1b6..b5f78b6ed2bd 100644
--- a/drivers/telephony/Kconfig
+++ b/drivers/telephony/Kconfig
@@ -19,7 +19,7 @@ if PHONE
config PHONE_IXJ
tristate "QuickNet Internet LineJack/PhoneJack support"
- depends ISA || PCI
+ depends on ISA || PCI
---help---
Say M if you have a telephony card manufactured by Quicknet
Technologies, Inc. These include the Internet PhoneJACK and
diff --git a/drivers/telephony/phonedev.c b/drivers/telephony/phonedev.c
index 4d8c2a5b3297..bcea8d9b718c 100644
--- a/drivers/telephony/phonedev.c
+++ b/drivers/telephony/phonedev.c
@@ -120,9 +120,8 @@ int phone_register_device(struct phone_device *p, int unit)
void phone_unregister_device(struct phone_device *pfd)
{
mutex_lock(&phone_lock);
- if (phone_device[pfd->minor] != pfd)
- panic("phone: bad unregister");
- phone_device[pfd->minor] = NULL;
+ if (likely(phone_device[pfd->minor] == pfd))
+ phone_device[pfd->minor] = NULL;
mutex_unlock(&phone_lock);
}
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index f51e22490edf..912d97aaf9bf 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -332,7 +332,7 @@ static void acm_read_bulk(struct urb *urb)
return;
if (status)
- dev_dbg(&acm->data->dev, "bulk rx status %d", status);
+ dev_dbg(&acm->data->dev, "bulk rx status %d\n", status);
buf = rcv->buffer;
buf->size = urb->actual_length;
@@ -831,13 +831,13 @@ static int acm_probe (struct usb_interface *intf,
/* normal probing*/
if (!buffer) {
- err("Wierd descriptor references\n");
+ err("Weird descriptor references\n");
return -EINVAL;
}
if (!buflen) {
if (intf->cur_altsetting->endpoint->extralen && intf->cur_altsetting->endpoint->extra) {
- dev_dbg(&intf->dev,"Seeking extra descriptors on endpoint");
+ dev_dbg(&intf->dev,"Seeking extra descriptors on endpoint\n");
buflen = intf->cur_altsetting->endpoint->extralen;
buffer = intf->cur_altsetting->endpoint->extra;
} else {
@@ -887,24 +887,24 @@ next_desc:
if (!union_header) {
if (call_interface_num > 0) {
- dev_dbg(&intf->dev,"No union descriptor, using call management descriptor");
+ dev_dbg(&intf->dev,"No union descriptor, using call management descriptor\n");
data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = call_interface_num));
control_interface = intf;
} else {
- dev_dbg(&intf->dev,"No union descriptor, giving up");
+ dev_dbg(&intf->dev,"No union descriptor, giving up\n");
return -ENODEV;
}
} else {
control_interface = usb_ifnum_to_if(usb_dev, union_header->bMasterInterface0);
data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = union_header->bSlaveInterface0));
if (!control_interface || !data_interface) {
- dev_dbg(&intf->dev,"no interfaces");
+ dev_dbg(&intf->dev,"no interfaces\n");
return -ENODEV;
}
}
if (data_interface_num != call_interface_num)
- dev_dbg(&intf->dev,"Seperate call control interface. That is not fully supported.");
+ dev_dbg(&intf->dev,"Seperate call control interface. That is not fully supported.\n");
skip_normal_probe:
@@ -912,7 +912,7 @@ skip_normal_probe:
if (data_interface->cur_altsetting->desc.bInterfaceClass != CDC_DATA_INTERFACE_TYPE) {
if (control_interface->cur_altsetting->desc.bInterfaceClass == CDC_DATA_INTERFACE_TYPE) {
struct usb_interface *t;
- dev_dbg(&intf->dev,"Your device has switched interfaces.");
+ dev_dbg(&intf->dev,"Your device has switched interfaces.\n");
t = control_interface;
control_interface = data_interface;
@@ -927,7 +927,7 @@ skip_normal_probe:
return -ENODEV;
if (usb_interface_claimed(data_interface)) { /* valid in this context */
- dev_dbg(&intf->dev,"The data interface isn't available");
+ dev_dbg(&intf->dev,"The data interface isn't available\n");
return -EBUSY;
}
@@ -944,7 +944,7 @@ skip_normal_probe:
if (!usb_endpoint_dir_in(epread)) {
/* descriptors are swapped */
struct usb_endpoint_descriptor *t;
- dev_dbg(&intf->dev,"The data interface has switched endpoints");
+ dev_dbg(&intf->dev,"The data interface has switched endpoints\n");
t = epread;
epread = epwrite;
@@ -959,7 +959,7 @@ skip_normal_probe:
}
if (!(acm = kzalloc(sizeof(struct acm), GFP_KERNEL))) {
- dev_dbg(&intf->dev, "out of memory (acm kzalloc)");
+ dev_dbg(&intf->dev, "out of memory (acm kzalloc)\n");
goto alloc_fail;
}
@@ -985,26 +985,26 @@ skip_normal_probe:
buf = usb_buffer_alloc(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma);
if (!buf) {
- dev_dbg(&intf->dev, "out of memory (ctrl buffer alloc)");
+ dev_dbg(&intf->dev, "out of memory (ctrl buffer alloc)\n");
goto alloc_fail2;
}
acm->ctrl_buffer = buf;
if (acm_write_buffers_alloc(acm) < 0) {
- dev_dbg(&intf->dev, "out of memory (write buffer alloc)");
+ dev_dbg(&intf->dev, "out of memory (write buffer alloc)\n");
goto alloc_fail4;
}
acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL);
if (!acm->ctrlurb) {
- dev_dbg(&intf->dev, "out of memory (ctrlurb kmalloc)");
+ dev_dbg(&intf->dev, "out of memory (ctrlurb kmalloc)\n");
goto alloc_fail5;
}
for (i = 0; i < num_rx_buf; i++) {
struct acm_ru *rcv = &(acm->ru[i]);
if (!(rcv->urb = usb_alloc_urb(0, GFP_KERNEL))) {
- dev_dbg(&intf->dev, "out of memory (read urbs usb_alloc_urb)");
+ dev_dbg(&intf->dev, "out of memory (read urbs usb_alloc_urb)\n");
goto alloc_fail7;
}
@@ -1015,13 +1015,13 @@ skip_normal_probe:
struct acm_rb *buf = &(acm->rb[i]);
if (!(buf->base = usb_buffer_alloc(acm->dev, readsize, GFP_KERNEL, &buf->dma))) {
- dev_dbg(&intf->dev, "out of memory (read bufs usb_buffer_alloc)");
+ dev_dbg(&intf->dev, "out of memory (read bufs usb_buffer_alloc)\n");
goto alloc_fail7;
}
}
acm->writeurb = usb_alloc_urb(0, GFP_KERNEL);
if (!acm->writeurb) {
- dev_dbg(&intf->dev, "out of memory (writeurb kmalloc)");
+ dev_dbg(&intf->dev, "out of memory (writeurb kmalloc)\n");
goto alloc_fail7;
}
diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c
index ead2475406b8..28d4972f7ad5 100644
--- a/drivers/usb/core/buffer.c
+++ b/drivers/usb/core/buffer.c
@@ -11,7 +11,6 @@
#include <linux/device.h>
#include <linux/mm.h>
#include <asm/io.h>
-#include <asm/scatterlist.h>
#include <linux/dma-mapping.h>
#include <linux/dmapool.h>
#include <linux/usb.h>
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index f013b4012c9a..1f4f6d02fe25 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -460,7 +460,7 @@ static int checkintf(struct dev_state *ps, unsigned int ifnum)
return 0;
/* if not yet claimed, claim it for the driver */
dev_warn(&ps->dev->dev, "usbfs: process %d (%s) did not claim interface %u before use\n",
- current->pid, current->comm, ifnum);
+ task_pid_nr(current), current->comm, ifnum);
return claimintf(ps, ifnum);
}
diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c
index 7dc123d6b2d0..99e5a68a3f12 100644
--- a/drivers/usb/core/endpoint.c
+++ b/drivers/usb/core/endpoint.c
@@ -291,7 +291,7 @@ int usb_create_ep_files(struct device *parent,
retval = endpoint_get_minor(ep_dev);
if (retval) {
- dev_err(parent, "can not allocate minor number for %s",
+ dev_err(parent, "can not allocate minor number for %s\n",
ep_dev->dev.bus_id);
goto error_register;
}
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 3dd997df8505..fea8256a18d6 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -30,7 +30,6 @@
#include <linux/utsname.h>
#include <linux/mm.h>
#include <asm/io.h>
-#include <asm/scatterlist.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/mutex.h>
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index d20cb545a6e4..036c3dea855e 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1407,7 +1407,11 @@ fail:
/**
- * Similar to usb_disconnect()
+ * usb_deauthorize_device - deauthorize a device (usbcore-internal)
+ * @usb_dev: USB device
+ *
+ * Move the USB device to a very basic state where interfaces are disabled
+ * and the device is in fact unconfigured and unusable.
*
* We share a lock (that we have) with device_del(), so we need to
* defer its call.
@@ -2866,10 +2870,9 @@ static int hub_thread(void *__unused)
set_freezable();
do {
hub_events();
- wait_event_interruptible(khubd_wait,
+ wait_event_freezable(khubd_wait,
!list_empty(&hub_event_list) ||
kthread_should_stop());
- try_to_freeze();
} while (!kthread_should_stop() || !list_empty(&hub_event_list));
pr_debug("%s: khubd exiting\n", usbcore_name);
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index c021af390372..316a746e0080 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -11,9 +11,9 @@
#include <linux/timer.h>
#include <linux/ctype.h>
#include <linux/device.h>
+#include <linux/scatterlist.h>
#include <linux/usb/quirks.h>
#include <asm/byteorder.h>
-#include <asm/scatterlist.h>
#include "hcd.h" /* for usbcore internals */
#include "usb.h"
@@ -434,16 +434,14 @@ int usb_sg_init (
if (dma) {
io->urbs [i]->transfer_dma = sg_dma_address (sg + i);
len = sg_dma_len (sg + i);
-#if defined(CONFIG_HIGHMEM) || defined(CONFIG_IOMMU)
+#if defined(CONFIG_HIGHMEM) || defined(CONFIG_GART_IOMMU)
io->urbs[i]->transfer_buffer = NULL;
#else
- io->urbs[i]->transfer_buffer =
- page_address(sg[i].page) + sg[i].offset;
+ io->urbs[i]->transfer_buffer = sg_virt(&sg[i]);
#endif
} else {
/* hc may use _only_ transfer_buffer */
- io->urbs [i]->transfer_buffer =
- page_address (sg [i].page) + sg [i].offset;
+ io->urbs [i]->transfer_buffer = sg_virt(&sg[i]);
len = sg [i].length;
}
@@ -1526,7 +1524,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
new_interfaces = kmalloc(nintf * sizeof(*new_interfaces),
GFP_KERNEL);
if (!new_interfaces) {
- dev_err(&dev->dev, "Out of memory");
+ dev_err(&dev->dev, "Out of memory\n");
return -ENOMEM;
}
@@ -1535,7 +1533,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
sizeof(struct usb_interface),
GFP_KERNEL);
if (!new_interfaces[n]) {
- dev_err(&dev->dev, "Out of memory");
+ dev_err(&dev->dev, "Out of memory\n");
ret = -ENOMEM;
free_interfaces:
while (--n >= 0)
@@ -1643,7 +1641,13 @@ free_interfaces:
intf->dev.bus_id, ret);
continue;
}
- usb_create_sysfs_intf_files (intf);
+
+ /* The driver's probe method can call usb_set_interface(),
+ * which would mean the interface's sysfs files are already
+ * created. Just in case, we'll remove them first.
+ */
+ usb_remove_sysfs_intf_files(intf);
+ usb_create_sysfs_intf_files(intf);
}
usb_autosuspend_device(dev);
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index c20c03aaf012..d05ead20081c 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -372,7 +372,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
/* enforce simple/standard policy */
allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP |
- URB_NO_INTERRUPT | URB_DIR_MASK);
+ URB_NO_INTERRUPT | URB_DIR_MASK | URB_FREE_BUFFER);
switch (xfertype) {
case USB_ENDPOINT_XFER_BULK:
if (is_out)
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index c99938d5f78e..c4a6f1095b8b 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -36,7 +36,7 @@
#include <linux/workqueue.h>
#include <asm/io.h>
-#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
#include <linux/mm.h>
#include <linux/dma-mapping.h>
@@ -982,7 +982,6 @@ EXPORT_SYMBOL(usb_altnum_to_altsetting);
EXPORT_SYMBOL(__usb_get_extra_descriptor);
-EXPORT_SYMBOL(usb_find_device);
EXPORT_SYMBOL(usb_get_current_frame_number);
EXPORT_SYMBOL(usb_buffer_alloc);
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
index 1c8040602525..c72e9620bf8d 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/drivers/usb/gadget/amd5536udc.c
@@ -3289,7 +3289,7 @@ static int udc_pci_probe(
dev->chiprev = pdev->revision;
pci_set_master(pdev);
- pci_set_mwi(pdev);
+ pci_try_set_mwi(pdev);
/* init dma pools */
if (use_dma) {
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index 73726c570a6e..1d174dcb3ac9 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -4006,7 +4006,7 @@ static int __init fsg_bind(struct usb_gadget *gadget)
DBG(fsg, "removable=%d, stall=%d, buflen=%u\n",
mod_data.removable, mod_data.can_stall,
mod_data.buflen);
- DBG(fsg, "I/O thread pid: %d\n", fsg->thread_task->pid);
+ DBG(fsg, "I/O thread pid: %d\n", task_pid_nr(fsg->thread_task));
set_bit(REGISTERED, &fsg->atomic_bitflags);
diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c
index e78c2ddc1f88..367b75c0b25b 100644
--- a/drivers/usb/gadget/lh7a40x_udc.c
+++ b/drivers/usb/gadget/lh7a40x_udc.c
@@ -1272,7 +1272,7 @@ static int lh7a40x_set_halt(struct usb_ep *_ep, int value)
/*
* Attempts to halt IN endpoints will fail (returning -EAGAIN)
* if any transfer requests are still queued, or if the controller
- * FIFO still holds bytes that the host hasn’t collected.
+ * FIFO still holds bytes that the host hasn't collected.
*/
spin_unlock_irqrestore(&ep->dev->lock, flags);
DEBUG
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
index 3e715082de36..3173b39f0bfd 100644
--- a/drivers/usb/gadget/pxa2xx_udc.c
+++ b/drivers/usb/gadget/pxa2xx_udc.c
@@ -43,6 +43,8 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/err.h>
#include <asm/byteorder.h>
#include <asm/dma.h>
@@ -1157,7 +1159,7 @@ static void udc_disable(struct pxa2xx_udc *dev)
#ifdef CONFIG_ARCH_PXA
/* Disable clock for USB device */
- pxa_set_cken(CKEN_USB, 0);
+ clk_disable(dev->clk);
#endif
ep0_idle (dev);
@@ -1202,8 +1204,7 @@ static void udc_enable (struct pxa2xx_udc *dev)
#ifdef CONFIG_ARCH_PXA
/* Enable clock for USB device */
- pxa_set_cken(CKEN_USB, 1);
- udelay(5);
+ clk_enable(dev->clk);
#endif
/* try to clear these bits before we enable the udc */
@@ -2137,6 +2138,14 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
if (irq < 0)
return -ENODEV;
+#ifdef CONFIG_ARCH_PXA
+ dev->clk = clk_get(&pdev->dev, "UDCCLK");
+ if (IS_ERR(dev->clk)) {
+ retval = PTR_ERR(dev->clk);
+ goto err_clk;
+ }
+#endif
+
pr_debug("%s: IRQ %d%s%s\n", driver_name, irq,
dev->has_cfr ? "" : " (!cfr)",
SIZE_STR "(pio)"
@@ -2152,11 +2161,10 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev,
"can't get vbus gpio %d, err: %d\n",
dev->mach->gpio_vbus, retval);
- return -EBUSY;
+ goto err_gpio_vbus;
}
gpio_direction_input(dev->mach->gpio_vbus);
vbus_irq = gpio_to_irq(dev->mach->gpio_vbus);
- set_irq_type(vbus_irq, IRQT_BOTHEDGE);
} else
vbus_irq = 0;
@@ -2166,9 +2174,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev,
"can't get pullup gpio %d, err: %d\n",
dev->mach->gpio_pullup, retval);
- if (dev->mach->gpio_vbus)
- gpio_free(dev->mach->gpio_vbus);
- return -EBUSY;
+ goto err_gpio_pullup;
}
gpio_direction_output(dev->mach->gpio_pullup, 0);
}
@@ -2195,11 +2201,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
if (retval != 0) {
printk(KERN_ERR "%s: can't get irq %d, err %d\n",
driver_name, irq, retval);
- if (dev->mach->gpio_pullup)
- gpio_free(dev->mach->gpio_pullup);
- if (dev->mach->gpio_vbus)
- gpio_free(dev->mach->gpio_vbus);
- return -EBUSY;
+ goto err_irq1;
}
dev->got_irq = 1;
@@ -2213,12 +2215,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
printk(KERN_ERR "%s: can't get irq %i, err %d\n",
driver_name, LUBBOCK_USB_DISC_IRQ, retval);
lubbock_fail0:
- free_irq(irq, dev);
- if (dev->mach->gpio_pullup)
- gpio_free(dev->mach->gpio_pullup);
- if (dev->mach->gpio_vbus)
- gpio_free(dev->mach->gpio_vbus);
- return -EBUSY;
+ goto err_irq_lub;
}
retval = request_irq(LUBBOCK_USB_IRQ,
lubbock_vbus_irq,
@@ -2234,22 +2231,37 @@ lubbock_fail0:
#endif
if (vbus_irq) {
retval = request_irq(vbus_irq, udc_vbus_irq,
- IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
+ IRQF_DISABLED | IRQF_SAMPLE_RANDOM |
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
driver_name, dev);
if (retval != 0) {
printk(KERN_ERR "%s: can't get irq %i, err %d\n",
driver_name, vbus_irq, retval);
- free_irq(irq, dev);
- if (dev->mach->gpio_pullup)
- gpio_free(dev->mach->gpio_pullup);
- if (dev->mach->gpio_vbus)
- gpio_free(dev->mach->gpio_vbus);
- return -EBUSY;
+ goto err_vbus_irq;
}
}
create_proc_files();
return 0;
+
+ err_vbus_irq:
+#ifdef CONFIG_ARCH_LUBBOCK
+ free_irq(LUBBOCK_USB_DISC_IRQ, dev);
+ err_irq_lub:
+#endif
+ free_irq(irq, dev);
+ err_irq1:
+ if (dev->mach->gpio_pullup)
+ gpio_free(dev->mach->gpio_pullup);
+ err_gpio_pullup:
+ if (dev->mach->gpio_vbus)
+ gpio_free(dev->mach->gpio_vbus);
+ err_gpio_vbus:
+#ifdef CONFIG_ARCH_PXA
+ clk_put(dev->clk);
+ err_clk:
+#endif
+ return retval;
}
static void pxa2xx_udc_shutdown(struct platform_device *_dev)
@@ -2284,6 +2296,10 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev)
if (dev->mach->gpio_pullup)
gpio_free(dev->mach->gpio_pullup);
+#ifdef CONFIG_ARCH_PXA
+ clk_put(dev->clk);
+#endif
+
platform_set_drvdata(pdev, NULL);
the_controller = NULL;
return 0;
diff --git a/drivers/usb/gadget/pxa2xx_udc.h b/drivers/usb/gadget/pxa2xx_udc.h
index 0e5d0e6fb0e2..1db46d705777 100644
--- a/drivers/usb/gadget/pxa2xx_udc.h
+++ b/drivers/usb/gadget/pxa2xx_udc.h
@@ -125,6 +125,7 @@ struct pxa2xx_udc {
struct timer_list timer;
struct device *dev;
+ struct clk *clk;
struct pxa2xx_udc_mach_info *mach;
u64 dma_mask;
struct pxa2xx_ep ep [PXA_UDC_NUM_ENDPOINTS];
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index c978d622fa8a..177e78ed241b 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -156,7 +156,7 @@ config USB_OHCI_HCD_PCI
config USB_OHCI_HCD_SSB
bool "OHCI support for Broadcom SSB OHCI core"
- depends on USB_OHCI_HCD && SSB && EXPERIMENTAL
+ depends on USB_OHCI_HCD && (SSB = y || SSB = CONFIG_USB_OHCI_HCD) && EXPERIMENTAL
default n
---help---
Support for the Sonics Silicon Backplane (SSB) attached
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 0dcb4164dc83..735db4aec831 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -451,7 +451,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
/* Some boards (mostly VIA?) report bogus overcurrent indications,
* causing massive log spam unless we completely ignore them. It
- * may be relevant that VIA VT8235 controlers, where PORT_POWER is
+ * may be relevant that VIA VT8235 controllers, where PORT_POWER is
* always set, seem to clear PORT_OCC and PORT_CSC when writing to
* PORT_POWER; that's surprising, but maybe within-spec.
*/
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 240c7f507541..704f33fdd2f1 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -80,7 +80,10 @@ static const char hcd_name [] = "ohci_hcd";
static void ohci_dump (struct ohci_hcd *ohci, int verbose);
static int ohci_init (struct ohci_hcd *ohci);
static void ohci_stop (struct usb_hcd *hcd);
+
+#if defined(CONFIG_PM) || defined(CONFIG_PCI)
static int ohci_restart (struct ohci_hcd *ohci);
+#endif
#include "ohci-hub.c"
#include "ohci-dbg.c"
@@ -396,7 +399,7 @@ static int check_ed(struct ohci_hcd *ohci, struct ed *ed)
*/
static void unlink_watchdog_func(unsigned long _ohci)
{
- long flags;
+ unsigned long flags;
unsigned max;
unsigned seen_count = 0;
unsigned i;
@@ -893,6 +896,8 @@ static void ohci_stop (struct usb_hcd *hcd)
/*-------------------------------------------------------------------------*/
+#if defined(CONFIG_PM) || defined(CONFIG_PCI)
+
/* must not be called from interrupt context */
static int ohci_restart (struct ohci_hcd *ohci)
{
@@ -954,6 +959,8 @@ static int ohci_restart (struct ohci_hcd *ohci)
return 0;
}
+#endif
+
/*-------------------------------------------------------------------------*/
#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
index 6829814b7aaf..44b79e8a6e25 100644
--- a/drivers/usb/host/ohci-s3c2410.c
+++ b/drivers/usb/host/ohci-s3c2410.c
@@ -358,7 +358,7 @@ static int usb_hcd_s3c2410_probe (const struct hc_driver *driver,
hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1;
if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
- dev_err(&dev->dev, "request_mem_region failed");
+ dev_err(&dev->dev, "request_mem_region failed\n");
retval = -EBUSY;
goto err_put;
}
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index 94d859aa73f8..ba370c56172c 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -1556,7 +1556,7 @@ sl811h_start(struct usb_hcd *hcd)
hcd->power_budget = sl811->board->power * 2;
}
- /* enable power and interupts */
+ /* enable power and interrupts */
port_power(sl811, 1);
return 0;
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index e5d60d5b105a..60379b17bbc1 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -1271,7 +1271,8 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
} else if (qh->period != urb->interval) {
return -EINVAL; /* Can't change the period */
- } else { /* Pick up where the last URB leaves off */
+ } else {
+ /* Find the next unused frame */
if (list_empty(&qh->queue)) {
frame = qh->iso_frame;
} else {
@@ -1283,10 +1284,18 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
lurb->number_of_packets *
lurb->interval;
}
- if (urb->transfer_flags & URB_ISO_ASAP)
- urb->start_frame = frame;
- else if (urb->start_frame != frame)
- return -EINVAL;
+ if (urb->transfer_flags & URB_ISO_ASAP) {
+ /* Skip some frames if necessary to insure
+ * the start frame is in the future.
+ */
+ uhci_get_current_frame_number(uhci);
+ if (uhci_frame_before_eq(frame, uhci->frame_number)) {
+ frame = uhci->frame_number + 1;
+ frame += ((qh->phase - frame) &
+ (qh->period - 1));
+ }
+ } /* Otherwise pick up where the last URB leaves off */
+ urb->start_frame = frame;
}
/* Make sure we won't have to go too far into the future */
diff --git a/drivers/usb/image/Kconfig b/drivers/usb/image/Kconfig
index 95ce703110d2..7595dfb38e3b 100644
--- a/drivers/usb/image/Kconfig
+++ b/drivers/usb/image/Kconfig
@@ -1,5 +1,5 @@
#
-# USB Imageing devices configuration
+# USB Imaging devices configuration
#
comment "USB Imaging devices"
depends on USB
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
index e7d982a71548..91e999c9f680 100644
--- a/drivers/usb/image/microtek.c
+++ b/drivers/usb/image/microtek.c
@@ -519,8 +519,7 @@ static void mts_do_sg (struct urb* transfer)
context->fragment++;
mts_int_submit_urb(transfer,
context->data_pipe,
- page_address(sg[context->fragment].page) +
- sg[context->fragment].offset,
+ sg_virt(&sg[context->fragment]),
sg[context->fragment].length,
context->fragment + 1 == scsi_sg_count(context->srb) ?
mts_data_done : mts_do_sg);
@@ -557,7 +556,7 @@ mts_build_transfer_context(struct scsi_cmnd *srb, struct mts_desc* desc)
return;
} else {
sg = scsi_sglist(srb);
- desc->context.data = page_address(sg[0].page) + sg[0].offset;
+ desc->context.data = sg_virt(&sg[0]);
desc->context.data_length = sg[0].length;
}
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c
index 5131cbfb2f52..c567aa7a41ea 100644
--- a/drivers/usb/misc/adutux.c
+++ b/drivers/usb/misc/adutux.c
@@ -805,7 +805,7 @@ static int adu_probe(struct usb_interface *interface,
dev->minor = interface->minor;
/* let the user know what node this device is now attached to */
- dev_info(&interface->dev, "ADU%d %s now attached to /dev/usb/adutux%d",
+ dev_info(&interface->dev, "ADU%d %s now attached to /dev/usb/adutux%d\n",
udev->descriptor.idProduct, dev->serial_number,
(dev->minor - ADU_MINOR_BASE));
exit:
@@ -851,7 +851,7 @@ static void adu_disconnect(struct usb_interface *interface)
mutex_unlock(&dev->mtx);
}
- dev_info(&interface->dev, "ADU device adutux%d now disconnected",
+ dev_info(&interface->dev, "ADU device adutux%d now disconnected\n",
(minor - ADU_MINOR_BASE));
dbg(2," %s : leave", __FUNCTION__);
diff --git a/drivers/usb/misc/cytherm.c b/drivers/usb/misc/cytherm.c
index 04e87acd6e46..1cd9e7eba93b 100644
--- a/drivers/usb/misc/cytherm.c
+++ b/drivers/usb/misc/cytherm.c
@@ -118,7 +118,7 @@ static ssize_t set_brightness(struct device *dev, struct device_attribute *attr,
cytherm->brightness, buffer, 8);
if (retval)
dev_dbg(&cytherm->udev->dev, "retval = %d\n", retval);
- /* Inform µC that we have changed the brightness setting */
+ /* Inform µC that we have changed the brightness setting */
retval = vendor_command(cytherm->udev, WRITE_RAM, BRIGHTNESS_SEM,
0x01, buffer, 8);
if (retval)
@@ -399,7 +399,6 @@ static void cytherm_disconnect(struct usb_interface *interface)
struct usb_cytherm *dev;
dev = usb_get_intfdata (interface);
- usb_set_intfdata (interface, NULL);
device_remove_file(&interface->dev, &dev_attr_brightness);
device_remove_file(&interface->dev, &dev_attr_temp);
@@ -407,6 +406,9 @@ static void cytherm_disconnect(struct usb_interface *interface)
device_remove_file(&interface->dev, &dev_attr_port0);
device_remove_file(&interface->dev, &dev_attr_port1);
+ /* first remove the files, then NULL the pointer */
+ usb_set_intfdata (interface, NULL);
+
usb_put_dev(dev->udev);
kfree(dev);
diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c
index 5c0a26cbd128..4a09b87bdd28 100644
--- a/drivers/usb/misc/emi26.c
+++ b/drivers/usb/misc/emi26.c
@@ -1,7 +1,7 @@
/*
* Emagic EMI 2|6 usb audio interface firmware loader.
* Copyright (C) 2002
- * Tapio Laxström (tapio.laxstrom@iptime.fi)
+ * Tapio Laxström (tapio.laxstrom@iptime.fi)
*
* 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
@@ -114,6 +114,10 @@ static int emi26_load_firmware (struct usb_device *dev)
/* De-assert reset (let the CPU run) */
err = emi26_set_reset(dev,0);
+ if (err < 0) {
+ err("%s - error loading firmware: error = %d", __FUNCTION__, err);
+ goto wraperr;
+ }
msleep(250); /* let device settle */
/* 2. We upload the FPGA firmware into the EMI
@@ -249,7 +253,7 @@ static void __exit emi26_exit (void)
module_init(emi26_init);
module_exit(emi26_exit);
-MODULE_AUTHOR("tapio laxström");
+MODULE_AUTHOR("Tapio Laxström");
MODULE_DESCRIPTION("Emagic EMI 2|6 firmware loader.");
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c
index 23153eac0dfa..d1362415922c 100644
--- a/drivers/usb/misc/emi62.c
+++ b/drivers/usb/misc/emi62.c
@@ -1,7 +1,7 @@
/*
* Emagic EMI 2|6 usb audio interface firmware loader.
* Copyright (C) 2002
- * Tapio Laxström (tapio.laxstrom@iptime.fi)
+ * Tapio Laxström (tapio.laxstrom@iptime.fi)
*
* 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
@@ -123,6 +123,10 @@ static int emi62_load_firmware (struct usb_device *dev)
/* De-assert reset (let the CPU run) */
err = emi62_set_reset(dev,0);
+ if (err < 0) {
+ err("%s - error loading firmware: error = %d", __FUNCTION__, err);
+ goto wraperr;
+ }
msleep(250); /* let device settle */
/* 2. We upload the FPGA firmware into the EMI
@@ -292,7 +296,7 @@ static void __exit emi62_exit (void)
module_init(emi62_init);
module_exit(emi62_exit);
-MODULE_AUTHOR("tapio laxström");
+MODULE_AUTHOR("Tapio Laxström");
MODULE_DESCRIPTION("Emagic EMI 6|2m firmware loader.");
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
index d3d8cd6ff103..148b7fe639b2 100644
--- a/drivers/usb/misc/ftdi-elan.c
+++ b/drivers/usb/misc/ftdi-elan.c
@@ -147,7 +147,7 @@ struct u132_target {
/* Structure to hold all of our device specific stuff*/
struct usb_ftdi {
struct list_head ftdi_list;
- struct semaphore u132_lock;
+ struct mutex u132_lock;
int command_next;
int command_head;
struct u132_command command[COMMAND_SIZE];
@@ -330,39 +330,39 @@ static int ftdi_elan_hcd_init(struct usb_ftdi *ftdi)
static void ftdi_elan_abandon_completions(struct usb_ftdi *ftdi)
{
- down(&ftdi->u132_lock);
+ mutex_lock(&ftdi->u132_lock);
while (ftdi->respond_next > ftdi->respond_head) {
struct u132_respond *respond = &ftdi->respond[RESPOND_MASK &
ftdi->respond_head++];
*respond->result = -ESHUTDOWN;
*respond->value = 0;
complete(&respond->wait_completion);
- } up(&ftdi->u132_lock);
+ } mutex_unlock(&ftdi->u132_lock);
}
static void ftdi_elan_abandon_targets(struct usb_ftdi *ftdi)
{
int ed_number = 4;
- down(&ftdi->u132_lock);
+ mutex_lock(&ftdi->u132_lock);
while (ed_number-- > 0) {
struct u132_target *target = &ftdi->target[ed_number];
if (target->active == 1) {
target->condition_code = TD_DEVNOTRESP;
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
ftdi_elan_do_callback(ftdi, target, NULL, 0);
- down(&ftdi->u132_lock);
+ mutex_lock(&ftdi->u132_lock);
}
}
ftdi->recieved = 0;
ftdi->expected = 4;
ftdi->ed_found = 0;
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
}
static void ftdi_elan_flush_targets(struct usb_ftdi *ftdi)
{
int ed_number = 4;
- down(&ftdi->u132_lock);
+ mutex_lock(&ftdi->u132_lock);
while (ed_number-- > 0) {
struct u132_target *target = &ftdi->target[ed_number];
target->abandoning = 1;
@@ -382,9 +382,9 @@ static void ftdi_elan_flush_targets(struct usb_ftdi *ftdi)
ftdi->command_next += 1;
ftdi_elan_kick_command_queue(ftdi);
} else {
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
msleep(100);
- down(&ftdi->u132_lock);
+ mutex_lock(&ftdi->u132_lock);
goto wait_1;
}
}
@@ -404,9 +404,9 @@ static void ftdi_elan_flush_targets(struct usb_ftdi *ftdi)
ftdi->command_next += 1;
ftdi_elan_kick_command_queue(ftdi);
} else {
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
msleep(100);
- down(&ftdi->u132_lock);
+ mutex_lock(&ftdi->u132_lock);
goto wait_2;
}
}
@@ -414,13 +414,13 @@ static void ftdi_elan_flush_targets(struct usb_ftdi *ftdi)
ftdi->recieved = 0;
ftdi->expected = 4;
ftdi->ed_found = 0;
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
}
static void ftdi_elan_cancel_targets(struct usb_ftdi *ftdi)
{
int ed_number = 4;
- down(&ftdi->u132_lock);
+ mutex_lock(&ftdi->u132_lock);
while (ed_number-- > 0) {
struct u132_target *target = &ftdi->target[ed_number];
target->abandoning = 1;
@@ -440,9 +440,9 @@ static void ftdi_elan_cancel_targets(struct usb_ftdi *ftdi)
ftdi->command_next += 1;
ftdi_elan_kick_command_queue(ftdi);
} else {
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
msleep(100);
- down(&ftdi->u132_lock);
+ mutex_lock(&ftdi->u132_lock);
goto wait;
}
}
@@ -450,7 +450,7 @@ static void ftdi_elan_cancel_targets(struct usb_ftdi *ftdi)
ftdi->recieved = 0;
ftdi->expected = 4;
ftdi->ed_found = 0;
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
}
static void ftdi_elan_kick_command_queue(struct usb_ftdi *ftdi)
@@ -886,14 +886,14 @@ static char *have_ed_set_response(struct usb_ftdi *ftdi,
char *b)
{
int payload = (ed_length >> 0) & 0x07FF;
- down(&ftdi->u132_lock);
+ mutex_lock(&ftdi->u132_lock);
target->actual = 0;
target->non_null = (ed_length >> 15) & 0x0001;
target->repeat_number = (ed_length >> 11) & 0x000F;
if (ed_type == 0x02) {
if (payload == 0 || target->abandoning > 0) {
target->abandoning = 0;
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,
payload);
ftdi->recieved = 0;
@@ -903,13 +903,13 @@ static char *have_ed_set_response(struct usb_ftdi *ftdi,
} else {
ftdi->expected = 4 + payload;
ftdi->ed_found = 1;
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
return b;
}
} else if (ed_type == 0x03) {
if (payload == 0 || target->abandoning > 0) {
target->abandoning = 0;
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,
payload);
ftdi->recieved = 0;
@@ -919,12 +919,12 @@ static char *have_ed_set_response(struct usb_ftdi *ftdi,
} else {
ftdi->expected = 4 + payload;
ftdi->ed_found = 1;
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
return b;
}
} else if (ed_type == 0x01) {
target->abandoning = 0;
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,
payload);
ftdi->recieved = 0;
@@ -933,7 +933,7 @@ static char *have_ed_set_response(struct usb_ftdi *ftdi,
return ftdi->response;
} else {
target->abandoning = 0;
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,
payload);
ftdi->recieved = 0;
@@ -947,12 +947,12 @@ static char *have_ed_get_response(struct usb_ftdi *ftdi,
struct u132_target *target, u16 ed_length, int ed_number, int ed_type,
char *b)
{
- down(&ftdi->u132_lock);
+ mutex_lock(&ftdi->u132_lock);
target->condition_code = TD_DEVNOTRESP;
target->actual = (ed_length >> 0) & 0x01FF;
target->non_null = (ed_length >> 15) & 0x0001;
target->repeat_number = (ed_length >> 11) & 0x000F;
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
if (target->active)
ftdi_elan_do_callback(ftdi, target, NULL, 0);
target->abandoning = 0;
@@ -1278,7 +1278,7 @@ static int ftdi_elan_write_reg(struct usb_ftdi *ftdi, u32 data)
return -ENODEV;
} else {
int command_size;
- down(&ftdi->u132_lock);
+ mutex_lock(&ftdi->u132_lock);
command_size = ftdi->command_next - ftdi->command_head;
if (command_size < COMMAND_SIZE) {
struct u132_command *command = &ftdi->command[
@@ -1292,10 +1292,10 @@ static int ftdi_elan_write_reg(struct usb_ftdi *ftdi, u32 data)
command->buffer = &command->value;
ftdi->command_next += 1;
ftdi_elan_kick_command_queue(ftdi);
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
return 0;
} else {
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
msleep(100);
goto wait;
}
@@ -1310,7 +1310,7 @@ static int ftdi_elan_write_config(struct usb_ftdi *ftdi, int config_offset,
return -ENODEV;
} else {
int command_size;
- down(&ftdi->u132_lock);
+ mutex_lock(&ftdi->u132_lock);
command_size = ftdi->command_next - ftdi->command_head;
if (command_size < COMMAND_SIZE) {
struct u132_command *command = &ftdi->command[
@@ -1324,10 +1324,10 @@ static int ftdi_elan_write_config(struct usb_ftdi *ftdi, int config_offset,
command->buffer = &command->value;
ftdi->command_next += 1;
ftdi_elan_kick_command_queue(ftdi);
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
return 0;
} else {
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
msleep(100);
goto wait;
}
@@ -1342,7 +1342,7 @@ static int ftdi_elan_write_pcimem(struct usb_ftdi *ftdi, int mem_offset,
return -ENODEV;
} else {
int command_size;
- down(&ftdi->u132_lock);
+ mutex_lock(&ftdi->u132_lock);
command_size = ftdi->command_next - ftdi->command_head;
if (command_size < COMMAND_SIZE) {
struct u132_command *command = &ftdi->command[
@@ -1356,10 +1356,10 @@ static int ftdi_elan_write_pcimem(struct usb_ftdi *ftdi, int mem_offset,
command->buffer = &command->value;
ftdi->command_next += 1;
ftdi_elan_kick_command_queue(ftdi);
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
return 0;
} else {
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
msleep(100);
goto wait;
}
@@ -1382,7 +1382,7 @@ static int ftdi_elan_read_reg(struct usb_ftdi *ftdi, u32 *data)
} else {
int command_size;
int respond_size;
- down(&ftdi->u132_lock);
+ mutex_lock(&ftdi->u132_lock);
command_size = ftdi->command_next - ftdi->command_head;
respond_size = ftdi->respond_next - ftdi->respond_head;
if (command_size < COMMAND_SIZE && respond_size < RESPOND_SIZE)
@@ -1405,11 +1405,11 @@ static int ftdi_elan_read_reg(struct usb_ftdi *ftdi, u32 *data)
ftdi->command_next += 1;
ftdi->respond_next += 1;
ftdi_elan_kick_command_queue(ftdi);
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
wait_for_completion(&respond->wait_completion);
return result;
} else {
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
msleep(100);
goto wait;
}
@@ -1425,7 +1425,7 @@ static int ftdi_elan_read_config(struct usb_ftdi *ftdi, int config_offset,
} else {
int command_size;
int respond_size;
- down(&ftdi->u132_lock);
+ mutex_lock(&ftdi->u132_lock);
command_size = ftdi->command_next - ftdi->command_head;
respond_size = ftdi->respond_next - ftdi->respond_head;
if (command_size < COMMAND_SIZE && respond_size < RESPOND_SIZE)
@@ -1449,11 +1449,11 @@ static int ftdi_elan_read_config(struct usb_ftdi *ftdi, int config_offset,
ftdi->command_next += 1;
ftdi->respond_next += 1;
ftdi_elan_kick_command_queue(ftdi);
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
wait_for_completion(&respond->wait_completion);
return result;
} else {
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
msleep(100);
goto wait;
}
@@ -1469,7 +1469,7 @@ static int ftdi_elan_read_pcimem(struct usb_ftdi *ftdi, int mem_offset,
} else {
int command_size;
int respond_size;
- down(&ftdi->u132_lock);
+ mutex_lock(&ftdi->u132_lock);
command_size = ftdi->command_next - ftdi->command_head;
respond_size = ftdi->respond_next - ftdi->respond_head;
if (command_size < COMMAND_SIZE && respond_size < RESPOND_SIZE)
@@ -1493,11 +1493,11 @@ static int ftdi_elan_read_pcimem(struct usb_ftdi *ftdi, int mem_offset,
ftdi->command_next += 1;
ftdi->respond_next += 1;
ftdi_elan_kick_command_queue(ftdi);
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
wait_for_completion(&respond->wait_completion);
return result;
} else {
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
msleep(100);
goto wait;
}
@@ -1529,7 +1529,7 @@ static int ftdi_elan_edset_setup(struct usb_ftdi *ftdi, u8 ed_number,
return -ENODEV;
} else {
int command_size;
- down(&ftdi->u132_lock);
+ mutex_lock(&ftdi->u132_lock);
command_size = ftdi->command_next - ftdi->command_head;
if (command_size < COMMAND_SIZE) {
struct u132_target *target = &ftdi->target[ed];
@@ -1550,10 +1550,10 @@ static int ftdi_elan_edset_setup(struct usb_ftdi *ftdi, u8 ed_number,
target->active = 1;
ftdi->command_next += 1;
ftdi_elan_kick_command_queue(ftdi);
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
return 0;
} else {
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
msleep(100);
goto wait;
}
@@ -1586,7 +1586,7 @@ static int ftdi_elan_edset_input(struct usb_ftdi *ftdi, u8 ed_number,
return -ENODEV;
} else {
int command_size;
- down(&ftdi->u132_lock);
+ mutex_lock(&ftdi->u132_lock);
command_size = ftdi->command_next - ftdi->command_head;
if (command_size < COMMAND_SIZE) {
struct u132_target *target = &ftdi->target[ed];
@@ -1615,10 +1615,10 @@ static int ftdi_elan_edset_input(struct usb_ftdi *ftdi, u8 ed_number,
target->active = 1;
ftdi->command_next += 1;
ftdi_elan_kick_command_queue(ftdi);
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
return 0;
} else {
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
msleep(100);
goto wait;
}
@@ -1651,7 +1651,7 @@ static int ftdi_elan_edset_empty(struct usb_ftdi *ftdi, u8 ed_number,
return -ENODEV;
} else {
int command_size;
- down(&ftdi->u132_lock);
+ mutex_lock(&ftdi->u132_lock);
command_size = ftdi->command_next - ftdi->command_head;
if (command_size < COMMAND_SIZE) {
struct u132_target *target = &ftdi->target[ed];
@@ -1672,10 +1672,10 @@ static int ftdi_elan_edset_empty(struct usb_ftdi *ftdi, u8 ed_number,
target->active = 1;
ftdi->command_next += 1;
ftdi_elan_kick_command_queue(ftdi);
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
return 0;
} else {
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
msleep(100);
goto wait;
}
@@ -1708,7 +1708,7 @@ static int ftdi_elan_edset_output(struct usb_ftdi *ftdi, u8 ed_number,
return -ENODEV;
} else {
int command_size;
- down(&ftdi->u132_lock);
+ mutex_lock(&ftdi->u132_lock);
command_size = ftdi->command_next - ftdi->command_head;
if (command_size < COMMAND_SIZE) {
u8 *b;
@@ -1751,10 +1751,10 @@ static int ftdi_elan_edset_output(struct usb_ftdi *ftdi, u8 ed_number,
target->active = 1;
ftdi->command_next += 1;
ftdi_elan_kick_command_queue(ftdi);
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
return 0;
} else {
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
msleep(100);
goto wait;
}
@@ -1787,7 +1787,7 @@ static int ftdi_elan_edset_single(struct usb_ftdi *ftdi, u8 ed_number,
return -ENODEV;
} else {
int command_size;
- down(&ftdi->u132_lock);
+ mutex_lock(&ftdi->u132_lock);
command_size = ftdi->command_next - ftdi->command_head;
if (command_size < COMMAND_SIZE) {
int remaining_length = urb->transfer_buffer_length -
@@ -1816,10 +1816,10 @@ static int ftdi_elan_edset_single(struct usb_ftdi *ftdi, u8 ed_number,
target->active = 1;
ftdi->command_next += 1;
ftdi_elan_kick_command_queue(ftdi);
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
return 0;
} else {
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
msleep(100);
goto wait;
}
@@ -1849,9 +1849,9 @@ static int ftdi_elan_edset_flush(struct usb_ftdi *ftdi, u8 ed_number,
return -ENODEV;
} else {
struct u132_target *target = &ftdi->target[ed];
- down(&ftdi->u132_lock);
+ mutex_lock(&ftdi->u132_lock);
if (target->abandoning > 0) {
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
return 0;
} else {
target->abandoning = 1;
@@ -1873,13 +1873,13 @@ static int ftdi_elan_edset_flush(struct usb_ftdi *ftdi, u8 ed_number,
ftdi->command_next += 1;
ftdi_elan_kick_command_queue(ftdi);
} else {
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
msleep(100);
- down(&ftdi->u132_lock);
+ mutex_lock(&ftdi->u132_lock);
goto wait_1;
}
}
- up(&ftdi->u132_lock);
+ mutex_unlock(&ftdi->u132_lock);
return 0;
}
}
@@ -2793,7 +2793,7 @@ static int ftdi_elan_probe(struct usb_interface *interface,
init_MUTEX(&ftdi->sw_lock);
ftdi->udev = usb_get_dev(interface_to_usbdev(interface));
ftdi->interface = interface;
- init_MUTEX(&ftdi->u132_lock);
+ mutex_init(&ftdi->u132_lock);
ftdi->expected = 4;
iface_desc = interface->cur_altsetting;
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c
index e6fd024024f5..4bcf7fb4e5da 100644
--- a/drivers/usb/misc/idmouse.c
+++ b/drivers/usb/misc/idmouse.c
@@ -66,6 +66,7 @@ static struct usb_device_id idmouse_table[] = {
USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, value, index, NULL, 0, 1000)
MODULE_DEVICE_TABLE(usb, idmouse_table);
+static DEFINE_MUTEX(open_disc_mutex);
/* structure to hold all of our device specific stuff */
struct usb_idmouse {
@@ -80,7 +81,7 @@ struct usb_idmouse {
int open; /* if the port is open or not */
int present; /* if the device is not disconnected */
- struct semaphore sem; /* locks this structure */
+ struct mutex lock; /* locks this structure */
};
@@ -213,13 +214,17 @@ static int idmouse_open(struct inode *inode, struct file *file)
if (!interface)
return -ENODEV;
+ mutex_lock(&open_disc_mutex);
/* get the device information block from the interface */
dev = usb_get_intfdata(interface);
- if (!dev)
+ if (!dev) {
+ mutex_unlock(&open_disc_mutex);
return -ENODEV;
+ }
/* lock this device */
- down(&dev->sem);
+ mutex_lock(&dev->lock);
+ mutex_unlock(&open_disc_mutex);
/* check if already open */
if (dev->open) {
@@ -245,7 +250,7 @@ static int idmouse_open(struct inode *inode, struct file *file)
error:
/* unlock this device */
- up(&dev->sem);
+ mutex_unlock(&dev->lock);
return result;
}
@@ -258,12 +263,14 @@ static int idmouse_release(struct inode *inode, struct file *file)
if (dev == NULL)
return -ENODEV;
+ mutex_lock(&open_disc_mutex);
/* lock our device */
- down(&dev->sem);
+ mutex_lock(&dev->lock);
/* are we really open? */
if (dev->open <= 0) {
- up(&dev->sem);
+ mutex_unlock(&dev->lock);
+ mutex_unlock(&open_disc_mutex);
return -ENODEV;
}
@@ -271,10 +278,12 @@ static int idmouse_release(struct inode *inode, struct file *file)
if (!dev->present) {
/* the device was unplugged before the file was released */
- up(&dev->sem);
+ mutex_unlock(&dev->lock);
+ mutex_unlock(&open_disc_mutex);
idmouse_delete(dev);
} else {
- up(&dev->sem);
+ mutex_unlock(&dev->lock);
+ mutex_unlock(&open_disc_mutex);
}
return 0;
}
@@ -286,18 +295,18 @@ static ssize_t idmouse_read(struct file *file, char __user *buffer, size_t count
int result;
/* lock this object */
- down(&dev->sem);
+ mutex_lock(&dev->lock);
/* verify that the device wasn't unplugged */
if (!dev->present) {
- up(&dev->sem);
+ mutex_unlock(&dev->lock);
return -ENODEV;
}
result = simple_read_from_buffer(buffer, count, ppos,
dev->bulk_in_buffer, IMGSIZE);
/* unlock the device */
- up(&dev->sem);
+ mutex_unlock(&dev->lock);
return result;
}
@@ -320,7 +329,7 @@ static int idmouse_probe(struct usb_interface *interface,
if (dev == NULL)
return -ENOMEM;
- init_MUTEX(&dev->sem);
+ mutex_init(&dev->lock);
dev->udev = udev;
dev->interface = interface;
@@ -372,24 +381,26 @@ static void idmouse_disconnect(struct usb_interface *interface)
/* get device structure */
dev = usb_get_intfdata(interface);
- usb_set_intfdata(interface, NULL);
/* give back our minor */
usb_deregister_dev(interface, &idmouse_class);
- /* lock it */
- down(&dev->sem);
+ mutex_lock(&open_disc_mutex);
+ usb_set_intfdata(interface, NULL);
+ /* lock the device */
+ mutex_lock(&dev->lock);
+ mutex_unlock(&open_disc_mutex);
/* prevent device read, write and ioctl */
dev->present = 0;
/* if the device is opened, idmouse_release will clean this up */
if (!dev->open) {
- up(&dev->sem);
+ mutex_unlock(&dev->lock);
idmouse_delete(dev);
} else {
/* unlock */
- up(&dev->sem);
+ mutex_unlock(&dev->lock);
}
info("%s disconnected", DRIVER_DESC);
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c
index 46d9f27ec173..764696ff1e8e 100644
--- a/drivers/usb/misc/iowarrior.c
+++ b/drivers/usb/misc/iowarrior.c
@@ -66,6 +66,7 @@ module_param(debug, bool, 0644);
MODULE_PARM_DESC(debug, "debug=1 enables debugging messages");
static struct usb_driver iowarrior_driver;
+static DEFINE_MUTEX(iowarrior_open_disc_lock);
/*--------------*/
/* data */
@@ -216,7 +217,7 @@ static void iowarrior_callback(struct urb *urb)
exit:
retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
- dev_err(&dev->interface->dev, "%s - usb_submit_urb failed with result %d",
+ dev_err(&dev->interface->dev, "%s - usb_submit_urb failed with result %d\n",
__FUNCTION__, retval);
}
@@ -351,7 +352,7 @@ static ssize_t iowarrior_write(struct file *file,
mutex_lock(&dev->mutex);
/* verify that the device wasn't unplugged */
- if (dev == NULL || !dev->present) {
+ if (!dev->present) {
retval = -ENODEV;
goto exit;
}
@@ -451,7 +452,7 @@ static ssize_t iowarrior_write(struct file *file,
break;
default:
/* what do we have here ? An unsupported Product-ID ? */
- dev_err(&dev->interface->dev, "%s - not supported for product=0x%x",
+ dev_err(&dev->interface->dev, "%s - not supported for product=0x%x\n",
__FUNCTION__, dev->product_id);
retval = -EFAULT;
goto exit;
@@ -526,7 +527,7 @@ static int iowarrior_ioctl(struct inode *inode, struct file *file,
} else {
retval = -EINVAL;
dev_err(&dev->interface->dev,
- "ioctl 'IOW_WRITE' is not supported for product=0x%x.",
+ "ioctl 'IOW_WRITE' is not supported for product=0x%x.\n",
dev->product_id);
}
break;
@@ -608,11 +609,15 @@ static int iowarrior_open(struct inode *inode, struct file *file)
return -ENODEV;
}
+ mutex_lock(&iowarrior_open_disc_lock);
dev = usb_get_intfdata(interface);
- if (!dev)
+ if (!dev) {
+ mutex_unlock(&iowarrior_open_disc_lock);
return -ENODEV;
+ }
mutex_lock(&dev->mutex);
+ mutex_unlock(&iowarrior_open_disc_lock);
/* Only one process can open each device, no sharing. */
if (dev->opened) {
@@ -752,7 +757,7 @@ static int iowarrior_probe(struct usb_interface *interface,
/* allocate memory for our device state and intialize it */
dev = kzalloc(sizeof(struct iowarrior), GFP_KERNEL);
if (dev == NULL) {
- dev_err(&interface->dev, "Out of memory");
+ dev_err(&interface->dev, "Out of memory\n");
return retval;
}
@@ -866,6 +871,7 @@ static void iowarrior_disconnect(struct usb_interface *interface)
int minor;
dev = usb_get_intfdata(interface);
+ mutex_lock(&iowarrior_open_disc_lock);
usb_set_intfdata(interface, NULL);
minor = dev->minor;
@@ -879,6 +885,7 @@ static void iowarrior_disconnect(struct usb_interface *interface)
dev->present = 0;
mutex_unlock(&dev->mutex);
+ mutex_unlock(&iowarrior_open_disc_lock);
if (dev->opened) {
/* There is a process that holds a filedescriptor to the device ,
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
index 561970b889a5..aab320085ebf 100644
--- a/drivers/usb/misc/legousbtower.c
+++ b/drivers/usb/misc/legousbtower.c
@@ -198,6 +198,7 @@ static struct usb_device_id tower_table [] = {
};
MODULE_DEVICE_TABLE (usb, tower_table);
+static DEFINE_MUTEX(open_disc_mutex);
#define LEGO_USB_TOWER_MINOR_BASE 160
@@ -350,25 +351,31 @@ static int tower_open (struct inode *inode, struct file *file)
goto exit;
}
+ mutex_lock(&open_disc_mutex);
dev = usb_get_intfdata(interface);
if (!dev) {
+ mutex_unlock(&open_disc_mutex);
retval = -ENODEV;
goto exit;
}
/* lock this device */
if (down_interruptible (&dev->sem)) {
+ mutex_unlock(&open_disc_mutex);
retval = -ERESTARTSYS;
goto exit;
}
+
/* allow opening only once */
if (dev->open_count) {
+ mutex_unlock(&open_disc_mutex);
retval = -EBUSY;
goto unlock_exit;
}
dev->open_count = 1;
+ mutex_unlock(&open_disc_mutex);
/* reset the tower */
result = usb_control_msg (dev->udev,
@@ -437,9 +444,10 @@ static int tower_release (struct inode *inode, struct file *file)
if (dev == NULL) {
dbg(1, "%s: object is NULL", __FUNCTION__);
retval = -ENODEV;
- goto exit;
+ goto exit_nolock;
}
+ mutex_lock(&open_disc_mutex);
if (down_interruptible (&dev->sem)) {
retval = -ERESTARTSYS;
goto exit;
@@ -468,6 +476,8 @@ unlock_exit:
up (&dev->sem);
exit:
+ mutex_unlock(&open_disc_mutex);
+exit_nolock:
dbg(2, "%s: leave, return value %d", __FUNCTION__, retval);
return retval;
}
@@ -989,6 +999,7 @@ static void tower_disconnect (struct usb_interface *interface)
dbg(2, "%s: enter", __FUNCTION__);
dev = usb_get_intfdata (interface);
+ mutex_lock(&open_disc_mutex);
usb_set_intfdata (interface, NULL);
minor = dev->minor;
@@ -997,6 +1008,7 @@ static void tower_disconnect (struct usb_interface *interface)
usb_deregister_dev (interface, &tower_class);
down (&dev->sem);
+ mutex_unlock(&open_disc_mutex);
/* if the device is not opened, then we clean up right now */
if (!dev->open_count) {
diff --git a/drivers/usb/misc/phidgetmotorcontrol.c b/drivers/usb/misc/phidgetmotorcontrol.c
index df0ebcdb9d6a..2ad09b1f4848 100644
--- a/drivers/usb/misc/phidgetmotorcontrol.c
+++ b/drivers/usb/misc/phidgetmotorcontrol.c
@@ -155,7 +155,7 @@ resubmit:
retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
dev_err(&mc->intf->dev,
- "can't resubmit intr, %s-%s/motorcontrol0, retval %d",
+ "can't resubmit intr, %s-%s/motorcontrol0, retval %d\n",
mc->udev->bus->bus_name,
mc->udev->devpath, retval);
}
diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c
index 88f6abe73624..330c18e390b8 100644
--- a/drivers/usb/misc/rio500.c
+++ b/drivers/usb/misc/rio500.c
@@ -118,10 +118,7 @@ ioctl_rio(struct inode *inode, struct file *file, unsigned int cmd,
mutex_lock(&(rio->lock));
/* Sanity check to make sure rio is connected, powered, etc */
- if ( rio == NULL ||
- rio->present == 0 ||
- rio->rio_dev == NULL )
- {
+ if (rio->present == 0 || rio->rio_dev == NULL) {
retval = -ENODEV;
goto err_out;
}
@@ -280,10 +277,7 @@ write_rio(struct file *file, const char __user *buffer,
if (intr)
return -EINTR;
/* Sanity check to make sure rio is connected, powered, etc */
- if ( rio == NULL ||
- rio->present == 0 ||
- rio->rio_dev == NULL )
- {
+ if (rio->present == 0 || rio->rio_dev == NULL) {
mutex_unlock(&(rio->lock));
return -ENODEV;
}
@@ -369,10 +363,7 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
if (intr)
return -EINTR;
/* Sanity check to make sure rio is connected, powered, etc */
- if ( rio == NULL ||
- rio->present == 0 ||
- rio->rio_dev == NULL )
- {
+ if (rio->present == 0 || rio->rio_dev == NULL) {
mutex_unlock(&(rio->lock));
return -ENODEV;
}
diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c
index 43722e5a49d1..b624320df903 100644
--- a/drivers/usb/misc/sisusbvga/sisusb_con.c
+++ b/drivers/usb/misc/sisusbvga/sisusb_con.c
@@ -1042,7 +1042,8 @@ sisusbcon_set_origin(struct vc_data *c)
/* Interface routine */
static int
-sisusbcon_resize(struct vc_data *c, unsigned int newcols, unsigned int newrows)
+sisusbcon_resize(struct vc_data *c, unsigned int newcols, unsigned int newrows,
+ unsigned int user)
{
struct sisusb_usb_data *sisusb;
int fh;
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
index 719842032712..20777d01db62 100644
--- a/drivers/usb/misc/usblcd.c
+++ b/drivers/usb/misc/usblcd.c
@@ -17,6 +17,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/errno.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
@@ -34,6 +35,8 @@ static struct usb_device_id id_table [] = {
};
MODULE_DEVICE_TABLE (usb, id_table);
+static DEFINE_MUTEX(open_disc_mutex);
+
struct usb_lcd {
struct usb_device * udev; /* init: probe_lcd */
@@ -79,12 +82,16 @@ static int lcd_open(struct inode *inode, struct file *file)
return -ENODEV;
}
+ mutex_lock(&open_disc_mutex);
dev = usb_get_intfdata(interface);
- if (!dev)
+ if (!dev) {
+ mutex_unlock(&open_disc_mutex);
return -ENODEV;
+ }
/* increment our usage count for the device */
kref_get(&dev->kref);
+ mutex_unlock(&open_disc_mutex);
/* grab a power reference */
r = usb_autopm_get_interface(interface);
@@ -393,8 +400,10 @@ static void lcd_disconnect(struct usb_interface *interface)
struct usb_lcd *dev;
int minor = interface->minor;
+ mutex_lock(&open_disc_mutex);
dev = usb_get_intfdata(interface);
usb_set_intfdata(interface, NULL);
+ mutex_unlock(&open_disc_mutex);
/* give back our minor */
usb_deregister_dev(interface, &lcd_class);
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index e901d31e051b..ea3162146481 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -360,9 +360,9 @@ static void free_sglist (struct scatterlist *sg, int nents)
if (!sg)
return;
for (i = 0; i < nents; i++) {
- if (!sg [i].page)
+ if (!sg_page(&sg[i]))
continue;
- kfree (page_address (sg [i].page) + sg [i].offset);
+ kfree (sg_virt(&sg[i]));
}
kfree (sg);
}
diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
index 2734fe2b9c43..f1255b0a182d 100644
--- a/drivers/usb/misc/uss720.c
+++ b/drivers/usb/misc/uss720.c
@@ -128,7 +128,7 @@ static void async_complete(struct urb *urb)
#endif
/* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */
if (rq->reg[2] & rq->reg[1] & 0x10 && pp)
- parport_generic_irq(0, pp);
+ parport_generic_irq(pp);
}
complete(&rq->compl);
kref_put(&rq->ref_count, destroy_async);
@@ -337,7 +337,7 @@ static int uss720_irq(int usbstatus, void *buffer, int len, void *dev_id)
memcpy(priv->reg, buffer, 4);
/* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */
if (priv->reg[2] & priv->reg[1] & 0x10)
- parport_generic_irq(0, pp);
+ parport_generic_irq(pp);
return 1;
}
#endif
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
index ebb04ac4857b..5e3e4e9b6c77 100644
--- a/drivers/usb/mon/mon_text.c
+++ b/drivers/usb/mon/mon_text.c
@@ -87,7 +87,7 @@ struct mon_reader_text {
static struct dentry *mon_dir; /* Usually /sys/kernel/debug/usbmon */
-static void mon_text_ctor(void *, struct kmem_cache *, unsigned long);
+static void mon_text_ctor(struct kmem_cache *, void *);
struct mon_text_ptr {
int cnt, limit;
@@ -720,7 +720,7 @@ void mon_text_del(struct mon_bus *mbus)
/*
* Slab interface: constructor.
*/
-static void mon_text_ctor(void *mem, struct kmem_cache *slab, unsigned long sflags)
+static void mon_text_ctor(struct kmem_cache *slab, void *mem)
{
/*
* Nothing to initialize. No, really!
diff --git a/drivers/usb/serial/ChangeLog.history b/drivers/usb/serial/ChangeLog.history
index 52c4f7bd7a80..c1b279939bbf 100644
--- a/drivers/usb/serial/ChangeLog.history
+++ b/drivers/usb/serial/ChangeLog.history
@@ -400,7 +400,7 @@ visor.c Change Log comments:
(11/11/2001) gkh
Added support for the m125 devices, and added check to prevent oopses
- for Clié devices that lie about the number of ports they have.
+ for Clié devices that lie about the number of ports they have.
(08/30/2001) gkh
Added support for the Clie devices, both the 3.5 and 4.0 os versions.
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 99fefed77919..4a86696e6c7d 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -527,7 +527,7 @@ config USB_SERIAL_CYBERJACK
depends on USB_SERIAL && EXPERIMENTAL
---help---
Say Y here if you want to use a cyberJack pinpad/e-com USB chipcard
- reader. This is an interface to ISO 7816 compatible contactbased
+ reader. This is an interface to ISO 7816 compatible contact-based
chipcards, e.g. GSM SIMs.
To compile this driver as a module, choose M here: the
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index 2a8e537cb046..ddfee918000d 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -161,7 +161,8 @@ static void ark3116_set_termios(struct usb_serial_port *port,
{
struct usb_serial *serial = port->serial;
struct ark3116_private *priv = usb_get_serial_port_data(port);
- unsigned int cflag = port->tty->termios->c_cflag;
+ struct ktermios *termios = port->tty->termios;
+ unsigned int cflag = termios->c_cflag;
unsigned long flags;
int baud;
int ark3116_baud;
@@ -177,11 +178,14 @@ static void ark3116_set_termios(struct usb_serial_port *port,
*(port->tty->termios) = tty_std_termios;
port->tty->termios->c_cflag = B9600 | CS8
| CREAD | HUPCL | CLOCAL;
+ termios->c_ispeed = 9600;
+ termios->c_ospeed = 9600;
priv->termios_initialized = 1;
}
spin_unlock_irqrestore(&priv->lock, flags);
- cflag = port->tty->termios->c_cflag;
+ cflag = termios->c_cflag;
+ termios->c_cflag &= ~(CMSPAR|CRTSCTS);
buf = kmalloc(1, GFP_KERNEL);
if (!buf) {
@@ -254,9 +258,13 @@ static void ark3116_set_termios(struct usb_serial_port *port,
case 115200:
case 230400:
case 460800:
+ /* Report the resulting rate back to the caller */
+ tty_encode_baud_rate(port->tty, baud, baud);
break;
/* set 9600 as default (if given baudrate is invalid for example) */
default:
+ tty_encode_baud_rate(port->tty, 9600, 9600);
+ case 0:
baud = 9600;
}
@@ -302,6 +310,7 @@ static void ark3116_set_termios(struct usb_serial_port *port,
/* TEST ARK3116_SND(154, 0xFE, 0x40, 0xFFFF, 0x0006); */
kfree(buf);
+
return;
}
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index 6b252ceb39a8..42582d49b69c 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -272,9 +272,6 @@ static void ch341_set_termios(struct usb_serial_port *port,
dbg("ch341_set_termios()");
- if (!tty || !tty->termios)
- return;
-
baud_rate = tty_get_baud_rate(tty);
switch (baud_rate) {
@@ -299,6 +296,11 @@ static void ch341_set_termios(struct usb_serial_port *port,
* (cflag & PARENB) : parity {NONE, EVEN, ODD}
* (cflag & CSTOPB) : stop bits [1, 2]
*/
+
+ /* Copy back the old hardware settings */
+ tty_termios_copy_hw(tty->termios, old_termios);
+ /* And re-encode with the new baud */
+ tty_encode_baud_rate(tty, baud_rate, baud_rate);
}
static struct usb_driver ch341_driver = {
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
index 9386e216d681..0362654d3b52 100644
--- a/drivers/usb/serial/console.c
+++ b/drivers/usb/serial/console.c
@@ -164,6 +164,7 @@ static int usb_console_setup(struct console *co, char *options)
}
if (serial->type->set_termios) {
+ struct ktermios dummy;
/* build up a fake tty structure so that the open call has something
* to look at to get the cflag value */
tty = kzalloc(sizeof(*tty), GFP_KERNEL);
@@ -177,12 +178,13 @@ static int usb_console_setup(struct console *co, char *options)
kfree (tty);
return -ENOMEM;
}
+ memset(&dummy, 0, sizeof(struct ktermios));
termios->c_cflag = cflag;
tty->termios = termios;
port->tty = tty;
/* set up the initial termios settings */
- serial->type->set_termios(port, NULL);
+ serial->type->set_termios(port, &dummy);
port->tty = NULL;
kfree (termios);
kfree (tty);
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
index eb7df1835c11..3a83cb4c4bc2 100644
--- a/drivers/usb/serial/cp2101.c
+++ b/drivers/usb/serial/cp2101.c
@@ -361,7 +361,6 @@ static void cp2101_get_termios (struct usb_serial_port *port)
dbg("%s - no tty structures", __FUNCTION__);
return;
}
- cflag = port->tty->termios->c_cflag;
cp2101_get_config(port, CP2101_BAUDRATE, &baud, 2);
/* Convert to baudrate */
@@ -369,40 +368,9 @@ static void cp2101_get_termios (struct usb_serial_port *port)
baud = BAUD_RATE_GEN_FREQ / baud;
dbg("%s - baud rate = %d", __FUNCTION__, baud);
- cflag &= ~CBAUD;
- switch (baud) {
- /*
- * The baud rates which are commented out below
- * appear to be supported by the device
- * but are non-standard
- */
- case 600: cflag |= B600; break;
- case 1200: cflag |= B1200; break;
- case 1800: cflag |= B1800; break;
- case 2400: cflag |= B2400; break;
- case 4800: cflag |= B4800; break;
- /*case 7200: cflag |= B7200; break;*/
- case 9600: cflag |= B9600; break;
- /*case 14400: cflag |= B14400; break;*/
- case 19200: cflag |= B19200; break;
- /*case 28800: cflag |= B28800; break;*/
- case 38400: cflag |= B38400; break;
- /*case 55854: cflag |= B55054; break;*/
- case 57600: cflag |= B57600; break;
- case 115200: cflag |= B115200; break;
- /*case 127117: cflag |= B127117; break;*/
- case 230400: cflag |= B230400; break;
- case 460800: cflag |= B460800; break;
- case 921600: cflag |= B921600; break;
- /*case 3686400: cflag |= B3686400; break;*/
- default:
- dbg("%s - Baud rate is not supported, "
- "using 9600 baud", __FUNCTION__);
- cflag |= B9600;
- cp2101_set_config_single(port, CP2101_BAUDRATE,
- (BAUD_RATE_GEN_FREQ/9600));
- break;
- }
+
+ tty_encode_baud_rate(port->tty, baud, baud);
+ cflag = port->tty->termios->c_cflag;
cp2101_get_config(port, CP2101_BITS, &bits, 2);
cflag &= ~CSIZE;
@@ -516,7 +484,7 @@ static void cp2101_get_termios (struct usb_serial_port *port)
static void cp2101_set_termios (struct usb_serial_port *port,
struct ktermios *old_termios)
{
- unsigned int cflag, old_cflag=0;
+ unsigned int cflag, old_cflag;
int baud=0, bits;
unsigned int modem_ctl[4];
@@ -526,6 +494,8 @@ static void cp2101_set_termios (struct usb_serial_port *port,
dbg("%s - no tty structures", __FUNCTION__);
return;
}
+ port->tty->termios->c_cflag &= ~CMSPAR;
+
cflag = port->tty->termios->c_cflag;
old_cflag = old_termios->c_cflag;
baud = tty_get_baud_rate(port->tty);
@@ -563,11 +533,15 @@ static void cp2101_set_termios (struct usb_serial_port *port,
dbg("%s - Setting baud rate to %d baud", __FUNCTION__,
baud);
if (cp2101_set_config_single(port, CP2101_BAUDRATE,
- (BAUD_RATE_GEN_FREQ / baud)))
+ (BAUD_RATE_GEN_FREQ / baud))) {
dev_err(&port->dev, "Baud rate requested not "
"supported by device\n");
+ baud = tty_termios_baud_rate(old_termios);
+ }
}
}
+ /* Report back the resulting baud rate */
+ tty_encode_baud_rate(port->tty, baud, baud);
/* If the number of data bits is to be updated */
if ((cflag & CSIZE) != (old_cflag & CSIZE)) {
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index dab2e66d111d..ae410c4678ea 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -973,6 +973,8 @@ static void digi_set_termios(struct usb_serial_port *port,
}
}
/* set parity */
+ tty->termios->c_cflag &= ~CMSPAR;
+
if ((cflag&(PARENB|PARODD)) != (old_cflag&(PARENB|PARODD))) {
if (cflag&PARENB) {
if (cflag&PARODD)
@@ -1054,15 +1056,15 @@ static void digi_set_termios(struct usb_serial_port *port,
}
/* set output flow control */
- if ((iflag&IXON) != (old_iflag&IXON)
- || (cflag&CRTSCTS) != (old_cflag&CRTSCTS)) {
+ if ((iflag & IXON) != (old_iflag & IXON)
+ || (cflag & CRTSCTS) != (old_cflag & CRTSCTS)) {
arg = 0;
- if (iflag&IXON)
+ if (iflag & IXON)
arg |= DIGI_OUTPUT_FLOW_CONTROL_XON_XOFF;
else
arg &= ~DIGI_OUTPUT_FLOW_CONTROL_XON_XOFF;
- if (cflag&CRTSCTS) {
+ if (cflag & CRTSCTS) {
arg |= DIGI_OUTPUT_FLOW_CONTROL_CTS;
} else {
arg &= ~DIGI_OUTPUT_FLOW_CONTROL_CTS;
@@ -1076,8 +1078,8 @@ static void digi_set_termios(struct usb_serial_port *port,
}
/* set receive enable/disable */
- if ((cflag&CREAD) != (old_cflag&CREAD)) {
- if (cflag&CREAD)
+ if ((cflag & CREAD) != (old_cflag & CREAD)) {
+ if (cflag & CREAD)
arg = DIGI_ENABLE;
else
arg = DIGI_DISABLE;
@@ -1089,7 +1091,7 @@ static void digi_set_termios(struct usb_serial_port *port,
}
if ((ret = digi_write_oob_command(port, buf, i, 1)) != 0)
dbg("digi_set_termios: write oob failed, ret=%d", ret);
-
+ tty_encode_baud_rate(tty, baud, baud);
}
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index 050fcc996f56..a5c8e1e17ea5 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -449,14 +449,9 @@ static int empeg_ioctl (struct usb_serial_port *port, struct file * file, unsign
static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
{
-
+ struct ktermios *termios = port->tty->termios;
dbg("%s - port %d", __FUNCTION__, port->number);
- if ((!port->tty) || (!port->tty->termios)) {
- dbg("%s - no tty structures", __FUNCTION__);
- return;
- }
-
/*
* The empeg-car player wants these particular tty settings.
* You could, for example, change the baud rate, however the
@@ -466,7 +461,7 @@ static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *ol
*
* The default requirements for this device are:
*/
- port->tty->termios->c_iflag
+ termios->c_iflag
&= ~(IGNBRK /* disable ignore break */
| BRKINT /* disable break causes interrupt */
| PARMRK /* disable mark parity errors */
@@ -476,24 +471,23 @@ static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *ol
| ICRNL /* disable translate CR to NL */
| IXON); /* disable enable XON/XOFF flow control */
- port->tty->termios->c_oflag
+ termios->c_oflag
&= ~OPOST; /* disable postprocess output characters */
- port->tty->termios->c_lflag
+ termios->c_lflag
&= ~(ECHO /* disable echo input characters */
| ECHONL /* disable echo new line */
| ICANON /* disable erase, kill, werase, and rprnt special characters */
| ISIG /* disable interrupt, quit, and suspend special characters */
| IEXTEN); /* disable non-POSIX special characters */
- port->tty->termios->c_cflag
+ termios->c_cflag
&= ~(CSIZE /* no size */
| PARENB /* disable parity bit */
| CBAUD); /* clear current baud rate */
- port->tty->termios->c_cflag
- |= (CS8 /* character size 8 bits */
- | B115200); /* baud rate 115200 */
+ termios->c_cflag
+ |= CS8; /* character size 8 bits */
/*
* Force low_latency on; otherwise the pushes are scheduled;
@@ -501,8 +495,7 @@ static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *ol
* on the floor. We don't want to drop bytes on the floor. :)
*/
port->tty->low_latency = 1;
-
- return;
+ tty_encode_baud_rate(port->tty, 115200, 115200);
}
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index e4c248c98e84..c40e77dccf8e 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -83,7 +83,7 @@
*
* (18/Jun/2003) Ian Abbott
* Added Device ID of the USB relais from Rudolf Gugler (backported from
- * Philipp Gühring's patch for 2.5.x kernel).
+ * Philipp Gühring's patch for 2.5.x kernel).
* Moved read transfer buffer reallocation into startup function.
* Free existing write urb and transfer buffer in startup function.
* Only use urbs in write urb pool that were successfully allocated.
@@ -294,7 +294,7 @@ struct ftdi_private {
__u16 interface; /* FT2232C port interface (0 for FT232/245) */
- int force_baud; /* if non-zero, force the baud rate to this value */
+ speed_t force_baud; /* if non-zero, force the baud rate to this value */
int force_rtscts; /* if non-zero, force RTS-CTS to always be enabled */
spinlock_t tx_lock; /* spinlock for transmit state */
@@ -878,6 +878,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
if (div_value == 0) {
dbg("%s - Baudrate (%d) requested is not supported", __FUNCTION__, baud);
div_value = ftdi_sio_b9600;
+ baud = 9600;
div_okay = 0;
}
break;
@@ -886,6 +887,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
div_value = ftdi_232am_baud_to_divisor(baud);
} else {
dbg("%s - Baud rate too high!", __FUNCTION__);
+ baud = 9600;
div_value = ftdi_232am_baud_to_divisor(9600);
div_okay = 0;
}
@@ -899,6 +901,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
dbg("%s - Baud rate too high!", __FUNCTION__);
div_value = ftdi_232bm_baud_to_divisor(9600);
div_okay = 0;
+ baud = 9600;
}
break;
} /* priv->chip_type */
@@ -909,6 +912,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
ftdi_chip_name[priv->chip_type]);
}
+ tty_encode_baud_rate(port->tty, baud, baud);
return(div_value);
}
@@ -1071,7 +1075,7 @@ static ssize_t show_latency_timer(struct device *dev, struct device_attribute *a
(char*) &latency, 1, WDR_TIMEOUT);
if (rv < 0) {
- dev_err(dev, "Unable to read latency timer: %i", rv);
+ dev_err(dev, "Unable to read latency timer: %i\n", rv);
return -EIO;
}
return sprintf(buf, "%i\n", latency);
@@ -1098,7 +1102,7 @@ static ssize_t store_latency_timer(struct device *dev, struct device_attribute *
buf, 0, WDR_TIMEOUT);
if (rv < 0) {
- dev_err(dev, "Unable to write latency timer: %i", rv);
+ dev_err(dev, "Unable to write latency timer: %i\n", rv);
return -EIO;
}
@@ -1263,7 +1267,7 @@ static void ftdi_USB_UIRT_setup (struct ftdi_private *priv)
priv->flags |= ASYNC_SPD_CUST;
priv->custom_divisor = 77;
- priv->force_baud = B38400;
+ priv->force_baud = 38400;
} /* ftdi_USB_UIRT_setup */
/* Setup for the HE-TIRA1 device, which requires hardwired
@@ -1274,7 +1278,7 @@ static void ftdi_HE_TIRA1_setup (struct ftdi_private *priv)
priv->flags |= ASYNC_SPD_CUST;
priv->custom_divisor = 240;
- priv->force_baud = B38400;
+ priv->force_baud = 38400;
priv->force_rtscts = 1;
} /* ftdi_HE_TIRA1_setup */
@@ -1363,7 +1367,7 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp)
/* ftdi_set_termios will send usb control messages */
if (port->tty)
- ftdi_set_termios(port, NULL);
+ ftdi_set_termios(port, port->tty->termios);
/* FIXME: Flow control might be enabled, so it should be checked -
we have no control of defaults! */
@@ -1933,32 +1937,33 @@ static void ftdi_break_ctl( struct usb_serial_port *port, int break_state )
static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
{ /* ftdi_termios */
struct usb_device *dev = port->serial->dev;
- unsigned int cflag = port->tty->termios->c_cflag;
struct ftdi_private *priv = usb_get_serial_port_data(port);
+ struct ktermios *termios = port->tty->termios;
+ unsigned int cflag = termios->c_cflag;
__u16 urb_value; /* will hold the new flags */
char buf[1]; /* Perhaps I should dynamically alloc this? */
// Added for xon/xoff support
- unsigned int iflag = port->tty->termios->c_iflag;
+ unsigned int iflag = termios->c_iflag;
unsigned char vstop;
unsigned char vstart;
dbg("%s", __FUNCTION__);
/* Force baud rate if this device requires it, unless it is set to B0. */
- if (priv->force_baud && ((port->tty->termios->c_cflag & CBAUD) != B0)) {
+ if (priv->force_baud && ((termios->c_cflag & CBAUD) != B0)) {
dbg("%s: forcing baud rate for this device", __FUNCTION__);
- port->tty->termios->c_cflag &= ~CBAUD;
- port->tty->termios->c_cflag |= priv->force_baud;
+ tty_encode_baud_rate(port->tty, priv->force_baud,
+ priv->force_baud);
}
/* Force RTS-CTS if this device requires it. */
if (priv->force_rtscts) {
dbg("%s: forcing rtscts for this device", __FUNCTION__);
- port->tty->termios->c_cflag |= CRTSCTS;
+ termios->c_cflag |= CRTSCTS;
}
- cflag = port->tty->termios->c_cflag;
+ cflag = termios->c_cflag;
/* FIXME -For this cut I don't care if the line is really changing or
not - so just do the change regardless - should be able to
@@ -1969,6 +1974,8 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
/* Set number of data bits, parity, stop bits */
+ termios->c_cflag &= ~CMSPAR;
+
urb_value = 0;
urb_value |= (cflag & CSTOPB ? FTDI_SIO_SET_DATA_STOP_BITS_2 :
FTDI_SIO_SET_DATA_STOP_BITS_1);
@@ -2048,8 +2055,8 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
// Set the vstart and vstop -- could have been done up above where
// a lot of other dereferencing is done but that would be very
// inefficient as vstart and vstop are not always needed
- vstart=port->tty->termios->c_cc[VSTART];
- vstop=port->tty->termios->c_cc[VSTOP];
+ vstart = termios->c_cc[VSTART];
+ vstop = termios->c_cc[VSTOP];
urb_value=(vstop << 8) | (vstart);
if (usb_control_msg(dev,
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index b57b90ae9f9d..b51cbb0eaa05 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -17,7 +17,7 @@
* Bill Ryder - bryder@sgi.com formerly of Silicon Graphics, Inc.- wrote the
* FTDI_SIO implementation.
*
- * Philipp Gühring - pg@futureware.at - added the Device ID of the USB relais
+ * Philipp Gühring - pg@futureware.at - added the Device ID of the USB relais
* from Rudolf Gugler
*
*/
@@ -44,7 +44,7 @@
#define FTDI_ACTZWAVE_PID 0xF2D0
-/* www.starting-point-systems.com µChameleon device */
+/* www.starting-point-systems.com µChameleon device */
#define FTDI_MICRO_CHAMELEON_PID 0xCAA0 /* Product Id */
/* www.irtrans.de device */
@@ -419,7 +419,7 @@
/*
* Teratronik product ids.
- * Submitted by O. Wölfelschneider.
+ * Submitted by O. Wölfelschneider.
*/
#define FTDI_TERATRONIK_VCP_PID 0xEC88 /* Teratronik device (preferring VCP driver on windows) */
#define FTDI_TERATRONIK_D2XX_PID 0xEC89 /* Teratronik device (preferring D2XX driver on windows) */
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 88a2c7dce335..9eb4a65ee4d9 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -208,14 +208,15 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *
/* only do something if we have a bulk out endpoint */
if (serial->num_bulk_out) {
- spin_lock_bh(&port->lock);
+ unsigned long flags;
+ spin_lock_irqsave(&port->lock, flags);
if (port->write_urb_busy) {
- spin_unlock_bh(&port->lock);
+ spin_unlock_irqrestore(&port->lock, flags);
dbg("%s - already writing", __FUNCTION__);
return 0;
}
port->write_urb_busy = 1;
- spin_unlock_bh(&port->lock);
+ spin_unlock_irqrestore(&port->lock, flags);
count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index 2ecb1d2a034d..a5d2e115e167 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -1503,22 +1503,16 @@ static void edge_unthrottle (struct usb_serial_port *port)
*****************************************************************************/
static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
{
+ /* FIXME: This function appears unused ?? */
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
struct tty_struct *tty = port->tty;
unsigned int cflag;
- if (!port->tty || !port->tty->termios) {
- dbg ("%s - no tty or termios", __FUNCTION__);
- return;
- }
-
cflag = tty->termios->c_cflag;
dbg("%s - clfag %08x iflag %08x", __FUNCTION__,
tty->termios->c_cflag, tty->termios->c_iflag);
- if (old_termios) {
- dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__,
- old_termios->c_cflag, old_termios->c_iflag);
- }
+ dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__,
+ old_termios->c_cflag, old_termios->c_iflag);
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -2653,7 +2647,11 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
dbg("%s - baud rate = %d", __FUNCTION__, baud);
status = send_cmd_write_baud_rate (edge_port, baud);
-
+ if (status == -1) {
+ /* Speed change was not possible - put back the old speed */
+ baud = tty_termios_baud_rate(old_termios);
+ tty_encode_baud_rate(tty, baud, baud);
+ }
return;
}
@@ -2882,7 +2880,7 @@ static int edge_startup (struct usb_serial *serial)
(edge_serial->product_info.NumPorts != serial->num_ports)) {
dev_warn(&serial->dev->dev, "Device Reported %d serial ports "
"vs. core thinking we have %d ports, email "
- "greg@kroah.com this information.",
+ "greg@kroah.com this information.\n",
edge_serial->product_info.NumPorts,
serial->num_ports);
}
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index e836ad07fdb9..9b38a08ac83a 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -306,7 +306,7 @@ static struct usb_device_id ipaq_id_table [] = {
{ USB_DEVICE(0x0930, 0x0705) }, /* TOSHIBA Pocket PC e310 */
{ USB_DEVICE(0x0930, 0x0706) }, /* TOSHIBA Pocket PC e740 */
{ USB_DEVICE(0x0930, 0x0707) }, /* TOSHIBA Pocket PC e330 Series */
- { USB_DEVICE(0x0930, 0x0708) }, /* TOSHIBA Pocket PC e350 Series */
+ { USB_DEVICE(0x0930, 0x0708) }, /* TOSHIBA Pocket PC e350 Series */
{ USB_DEVICE(0x0930, 0x0709) }, /* TOSHIBA Pocket PC e750 Series */
{ USB_DEVICE(0x0930, 0x070A) }, /* TOSHIBA Pocket PC e400 Series */
{ USB_DEVICE(0x0930, 0x070B) }, /* TOSHIBA Pocket PC e800 Series */
@@ -488,7 +488,7 @@ static struct usb_device_id ipaq_id_table [] = {
{ USB_DEVICE(0x0BF8, 0x1001) }, /* Fujitsu Siemens Computers USB Sync */
{ USB_DEVICE(0x0C44, 0x03A2) }, /* Motorola iDEN Smartphone */
{ USB_DEVICE(0x0C8E, 0x6000) }, /* Cesscom Luxian Series */
- { USB_DEVICE(0x0CAD, 0x9001) }, /* Motorola PowerPad Pocket PC Device */
+ { USB_DEVICE(0x0CAD, 0x9001) }, /* Motorola PowerPad Pocket PC Device */
{ USB_DEVICE(0x0F4E, 0x0200) }, /* Freedom Scientific USB Sync */
{ USB_DEVICE(0x0F98, 0x0201) }, /* Cyberbank USB Sync */
{ USB_DEVICE(0x0FB8, 0x3001) }, /* Wistron USB Sync */
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index 1b94daa61584..cbe5530f3db2 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -227,7 +227,7 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
0,
100000);
if (result < 0)
- dev_err(&port->dev, "Init of modem failed (error = %d)", result);
+ dev_err(&port->dev, "Init of modem failed (error = %d)\n", result);
/* reset the bulk pipes */
usb_clear_halt(dev, usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress));
@@ -255,7 +255,7 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
0,
100000);
if (result < 0)
- dev_err(&port->dev, "Enabling bulk RxRead failed (error = %d)", result);
+ dev_err(&port->dev, "Enabling bulk RxRead failed (error = %d)\n", result);
/*--4: setup the initial flowcontrol */
dbg("%s:setting init flowcontrol (%s)",__FUNCTION__,buf_flow_init);
@@ -268,7 +268,7 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
0x10,
200000);
if (result < 0)
- dev_err(&port->dev, "initial flowcontrol failed (error = %d)", result);
+ dev_err(&port->dev, "initial flowcontrol failed (error = %d)\n", result);
/*--5: raise the dtr */
@@ -282,7 +282,7 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
0,
200000);
if (result < 0)
- dev_err(&port->dev, "setting dtr failed (error = %d)", result);
+ dev_err(&port->dev, "setting dtr failed (error = %d)\n", result);
/*--6: raise the rts */
dbg("%s:raising rts",__FUNCTION__);
@@ -295,7 +295,7 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
0,
200000);
if (result < 0)
- dev_err(&port->dev, "setting dtr failed (error = %d)", result);
+ dev_err(&port->dev, "setting dtr failed (error = %d)\n", result);
kfree(buf_flow_init);
return 0;
@@ -322,7 +322,7 @@ static void ipw_close(struct usb_serial_port *port, struct file * filp)
0,
200000);
if (result < 0)
- dev_err(&port->dev, "dropping dtr failed (error = %d)", result);
+ dev_err(&port->dev, "dropping dtr failed (error = %d)\n", result);
/*--2: drop the rts */
dbg("%s:dropping rts",__FUNCTION__);
@@ -334,7 +334,7 @@ static void ipw_close(struct usb_serial_port *port, struct file * filp)
0,
200000);
if (result < 0)
- dev_err(&port->dev, "dropping rts failed (error = %d)", result);
+ dev_err(&port->dev, "dropping rts failed (error = %d)\n", result);
/*--3: purge */
@@ -347,7 +347,7 @@ static void ipw_close(struct usb_serial_port *port, struct file * filp)
0,
200000);
if (result < 0)
- dev_err(&port->dev, "purge failed (error = %d)", result);
+ dev_err(&port->dev, "purge failed (error = %d)\n", result);
/* send RXBULK_off (tell modem to stop transmitting bulk data on rx chan) */
@@ -361,7 +361,7 @@ static void ipw_close(struct usb_serial_port *port, struct file * filp)
100000);
if (result < 0)
- dev_err(&port->dev, "Disabling bulk RxRead failed (error = %d)", result);
+ dev_err(&port->dev, "Disabling bulk RxRead failed (error = %d)\n", result);
/* shutdown any in-flight urbs that we know about */
usb_kill_urb(port->read_urb);
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index 5ab6a0c5ac52..6b803ab98543 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -504,11 +504,6 @@ static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_t
dbg("%s - port %d", __FUNCTION__, port->number);
- if ((!port->tty) || (!port->tty->termios)) {
- dbg("%s - no tty structures", __FUNCTION__);
- return;
- }
-
baud = tty_get_baud_rate(port->tty);
/*
@@ -531,8 +526,6 @@ static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_t
default:
ir_baud = SPEED_9600;
baud = 9600;
- /* And once the new tty stuff is all done we need to
- call back to correct the baud bits */
}
if (xbof == -1)
@@ -562,6 +555,10 @@ static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_t
result = usb_submit_urb (port->write_urb, GFP_KERNEL);
if (result)
dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
+
+ /* Only speed changes are supported */
+ tty_termios_copy_hw(port->tty->termios, old_termios);
+ tty_encode_baud_rate(port->tty, baud, baud);
}
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index f2a6fce5de1e..1f7ab15df36d 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -278,29 +278,35 @@ static void keyspan_set_termios (struct usb_serial_port *port,
struct keyspan_port_private *p_priv;
const struct keyspan_device_details *d_details;
unsigned int cflag;
+ struct tty_struct *tty = port->tty;
dbg("%s", __FUNCTION__);
p_priv = usb_get_serial_port_data(port);
d_details = p_priv->device_details;
- cflag = port->tty->termios->c_cflag;
+ cflag = tty->termios->c_cflag;
device_port = port->number - port->serial->minor;
/* Baud rate calculation takes baud rate as an integer
so other rates can be generated if desired. */
- baud_rate = tty_get_baud_rate(port->tty);
+ baud_rate = tty_get_baud_rate(tty);
/* If no match or invalid, don't change */
- if (baud_rate >= 0
- && d_details->calculate_baud_rate(baud_rate, d_details->baudclk,
+ if (d_details->calculate_baud_rate(baud_rate, d_details->baudclk,
NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
/* FIXME - more to do here to ensure rate changes cleanly */
+ /* FIXME - calcuate exact rate from divisor ? */
p_priv->baud = baud_rate;
- }
+ } else
+ baud_rate = tty_termios_baud_rate(old_termios);
+ tty_encode_baud_rate(tty, baud_rate, baud_rate);
/* set CTS/RTS handshake etc. */
p_priv->cflag = cflag;
p_priv->flow_control = (cflag & CRTSCTS)? flow_cts: flow_none;
+ /* Mark/Space not supported */
+ tty->termios->c_cflag &= ~CMSPAR;
+
keyspan_send_setup(port, 0);
}
@@ -1209,20 +1215,18 @@ static int keyspan_chars_in_buffer (struct usb_serial_port *port)
static int keyspan_open (struct usb_serial_port *port, struct file *filp)
{
- struct keyspan_port_private *p_priv;
- struct keyspan_serial_private *s_priv;
- struct usb_serial *serial = port->serial;
+ struct keyspan_port_private *p_priv;
+ struct keyspan_serial_private *s_priv;
+ struct usb_serial *serial = port->serial;
const struct keyspan_device_details *d_details;
int i, err;
- int baud_rate, device_port;
struct urb *urb;
- unsigned int cflag;
s_priv = usb_get_serial_data(serial);
p_priv = usb_get_serial_port_data(port);
d_details = p_priv->device_details;
-
- dbg("%s - port%d.", __FUNCTION__, port->number);
+
+ dbg("%s - port%d.", __FUNCTION__, port->number);
/* Set some sane defaults */
p_priv->rts_state = 1;
@@ -1243,7 +1247,7 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp)
urb->dev = serial->dev;
/* make sure endpoint data toggle is synchronized with the device */
-
+
usb_clear_halt(urb->dev, urb->pipe);
if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
@@ -1259,30 +1263,6 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp)
/* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 0); */
}
- /* get the terminal config for the setup message now so we don't
- * need to send 2 of them */
-
- cflag = port->tty->termios->c_cflag;
- device_port = port->number - port->serial->minor;
-
- /* Baud rate calculation takes baud rate as an integer
- so other rates can be generated if desired. */
- baud_rate = tty_get_baud_rate(port->tty);
- /* If no match or invalid, leave as default */
- if (baud_rate >= 0
- && d_details->calculate_baud_rate(baud_rate, d_details->baudclk,
- NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
- p_priv->baud = baud_rate;
- }
-
- /* set CTS/RTS handshake etc. */
- p_priv->cflag = cflag;
- p_priv->flow_control = (cflag & CRTSCTS)? flow_cts: flow_none;
-
- keyspan_send_setup(port, 1);
- //mdelay(100);
- //keyspan_set_termios(port, NULL);
-
return (0);
}
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index 6f224195bd25..aee450246bfd 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -616,8 +616,9 @@ static void kobil_set_termios(struct usb_serial_port *port, struct ktermios *old
case 1200:
urb_val = SUSBCR_SBR_1200;
break;
- case 9600:
default:
+ speed = 9600;
+ case 9600:
urb_val = SUSBCR_SBR_9600;
break;
}
@@ -641,6 +642,8 @@ static void kobil_set_termios(struct usb_serial_port *port, struct ktermios *old
urb_val |= SUSBCR_SPASB_NoParity;
strcat(settings, "No Parity");
}
+ port->tty->termios->c_cflag &= ~CMSPAR;
+ tty_encode_baud_rate(port->tty, speed, speed);
result = usb_control_msg( port->serial->dev,
usb_rcvctrlpipe(port->serial->dev, 0 ),
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index 01e811becec4..e02c198016b0 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -478,7 +478,7 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp)
response = usb_submit_urb(port0->interrupt_in_urb, GFP_KERNEL);
if (response)
dev_err(&port->dev,
- "%s - Error %d submitting control urb",
+ "%s - Error %d submitting control urb\n",
__FUNCTION__, response);
}
@@ -492,7 +492,7 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp)
response = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (response)
dev_err(&port->dev,
- "%s - Error %d submitting read urb", __FUNCTION__, response);
+ "%s - Error %d submitting read urb\n", __FUNCTION__, response);
/* initialize our icount structure */
memset(&(mos7720_port->icount), 0x00, sizeof(mos7720_port->icount));
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index f76480f1455d..a5ced7e08cbf 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -1977,11 +1977,6 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
tty = mos7840_port->port->tty;
- if ((!tty) || (!tty->termios)) {
- dbg("%s - no tty structures", __FUNCTION__);
- return;
- }
-
dbg("%s", "Entering .......... \n");
lData = LCR_BITS_8;
@@ -2151,11 +2146,6 @@ static void mos7840_set_termios(struct usb_serial_port *port,
tty = port->tty;
- if (!port->tty || !port->tty->termios) {
- dbg("%s - no tty or termios", __FUNCTION__);
- return;
- }
-
if (!mos7840_port->open) {
dbg("%s - port not opened", __FUNCTION__);
return;
@@ -2165,19 +2155,10 @@ static void mos7840_set_termios(struct usb_serial_port *port,
cflag = tty->termios->c_cflag;
- if (!cflag) {
- dbg("%s %s\n", __FUNCTION__, "cflag is NULL");
- return;
- }
-
dbg("%s - clfag %08x iflag %08x", __FUNCTION__,
tty->termios->c_cflag, RELEVANT_IFLAG(tty->termios->c_iflag));
-
- if (old_termios) {
- dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__,
- old_termios->c_cflag, RELEVANT_IFLAG(old_termios->c_iflag));
- }
-
+ dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__,
+ old_termios->c_cflag, RELEVANT_IFLAG(old_termios->c_iflag));
dbg("%s - port %d", __FUNCTION__, port->number);
/* change the port settings to the new ones specified */
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index a18659e0700c..4590124cf888 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -172,6 +172,8 @@ static struct usb_device_id option_ids[] = {
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2110) }, /* Novatel Merlin ES620 / Merlin ES720 / Ovation U720 */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2130) }, /* Novatel Merlin ES620 SM Bus */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2410) }, /* Novatel EU740 */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x4100) }, /* Novatel U727 */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x4400) }, /* Novatel MC950 */
{ USB_DEVICE(DELL_VENDOR_ID, 0x8114) }, /* Dell Wireless 5700 Mobile Broadband CDMA/EVDO Mini-Card == Novatel Expedite EV620 CDMA/EV-DO */
{ USB_DEVICE(DELL_VENDOR_ID, 0x8115) }, /* Dell Wireless 5500 Mobile Broadband HSDPA Mini-Card == Novatel Expedite EU740 HSDPA/3G */
{ USB_DEVICE(DELL_VENDOR_ID, 0x8116) }, /* Dell Wireless 5505 Mobile Broadband HSDPA Mini-Card == Novatel Expedite EU740 HSDPA/3G */
@@ -311,7 +313,8 @@ static void option_set_termios(struct usb_serial_port *port,
struct ktermios *old_termios)
{
dbg("%s", __FUNCTION__);
-
+ /* Doesn't support option setting */
+ tty_termios_copy_hw(port->tty->termios, old_termios);
option_send_setup(port);
}
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
index d19861166b50..eea226ae37bd 100644
--- a/drivers/usb/serial/oti6858.c
+++ b/drivers/usb/serial/oti6858.c
@@ -256,7 +256,7 @@ static void setup_line(struct work_struct *work)
100);
if (result != OTI6858_CTRL_PKT_SIZE) {
- dev_err(&port->dev, "%s(): error reading status", __FUNCTION__);
+ dev_err(&port->dev, "%s(): error reading status\n", __FUNCTION__);
kfree(new_setup);
/* we will try again */
schedule_delayed_work(&priv->delayed_setup_work, msecs_to_jiffies(2));
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 1da57fd9ea23..2cd3f1d4b687 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -56,6 +56,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ3) },
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_PHAROS) },
{ USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) },
+ { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) },
{ USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) },
{ USB_DEVICE(ATEN_VENDOR_ID2, ATEN_PRODUCT_ID) },
{ USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) },
@@ -470,16 +471,13 @@ static void pl2303_set_termios(struct usb_serial_port *port,
dbg("%s - port %d", __FUNCTION__, port->number);
- if ((!port->tty) || (!port->tty->termios)) {
- dbg("%s - no tty structures", __FUNCTION__);
- return;
- }
-
spin_lock_irqsave(&priv->lock, flags);
if (!priv->termios_initialized) {
*(port->tty->termios) = tty_std_termios;
port->tty->termios->c_cflag = B9600 | CS8 | CREAD |
HUPCL | CLOCAL;
+ port->tty->termios->c_ispeed = 9600;
+ port->tty->termios->c_ospeed = 9600;
priv->termios_initialized = 1;
}
spin_unlock_irqrestore(&priv->lock, flags);
@@ -596,6 +594,10 @@ static void pl2303_set_termios(struct usb_serial_port *port,
dbg ("0x40:0x1:0x0:0x0 %d", i);
}
+ /* FIXME: Need to read back resulting baud rate */
+ if (baud)
+ tty_encode_baud_rate(port->tty, baud, baud);
+
kfree(buf);
}
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index c39bace5cbcc..ed603e3decd6 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -20,6 +20,7 @@
#define IODATA_VENDOR_ID 0x04bb
#define IODATA_PRODUCT_ID 0x0a03
+#define IODATA_PRODUCT_ID_RSAQ5 0x0a0e
#define ELCOM_VENDOR_ID 0x056e
#define ELCOM_PRODUCT_ID 0x5003
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index 0bb8de4cc524..833f6e1e3721 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -48,7 +48,7 @@ enum devicetype {
static int sierra_set_power_state(struct usb_device *udev, __u16 swiState)
{
int result;
- dev_dbg(&udev->dev, "%s", "SET POWER STATE");
+ dev_dbg(&udev->dev, "%s", "SET POWER STATE\n");
result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
0x00, /* __u8 request */
0x40, /* __u8 request type */
@@ -63,7 +63,7 @@ static int sierra_set_power_state(struct usb_device *udev, __u16 swiState)
static int sierra_set_ms_mode(struct usb_device *udev, __u16 eSocMode)
{
int result;
- dev_dbg(&udev->dev, "%s", "DEVICE MODE SWITCH");
+ dev_dbg(&udev->dev, "%s", "DEVICE MODE SWITCH\n");
result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
SWIMS_USB_REQUEST_SetMode, /* __u8 request */
SWIMS_USB_REQUEST_TYPE_SetMode, /* __u8 request type */
@@ -224,7 +224,7 @@ static void sierra_set_termios(struct usb_serial_port *port,
struct ktermios *old_termios)
{
dbg("%s", __FUNCTION__);
-
+ tty_termios_copy_hw(port->tty->termios, old_termios);
sierra_send_setup(port);
}
@@ -397,7 +397,7 @@ static void sierra_indat_callback(struct urb *urb)
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err)
dev_err(&port->dev, "resubmit read urb failed."
- "(%d)", err);
+ "(%d)\n", err);
}
}
return;
@@ -525,7 +525,7 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp)
result = usb_submit_urb(urb, GFP_KERNEL);
if (result) {
- dev_err(&port->dev, "submit urb %d failed (%d) %d",
+ dev_err(&port->dev, "submit urb %d failed (%d) %d\n",
i, result, urb->transfer_buffer_length);
}
}
@@ -538,7 +538,7 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp)
if (port->interrupt_in_urb) {
result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (result)
- dev_err(&port->dev, "submit irq_in urb failed %d",
+ dev_err(&port->dev, "submit irq_in urb failed %d\n",
result);
}
return 0;
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 4b1bd7def4a5..497e29a700ca 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -429,6 +429,8 @@ static void serial_set_termios (struct tty_struct *tty, struct ktermios * old)
/* pass on to the driver specific version of this function if it is available */
if (port->serial->type->set_termios)
port->serial->type->set_termios(port, old);
+ else
+ tty_termios_copy_hw(tty->termios, old);
}
static void serial_break (struct tty_struct *tty, int break_state)
@@ -1121,7 +1123,9 @@ int usb_serial_resume(struct usb_interface *intf)
{
struct usb_serial *serial = usb_get_intfdata(intf);
- return serial->type->resume(serial);
+ if (serial->type->resume)
+ return serial->type->resume(serial);
+ return 0;
}
EXPORT_SYMBOL(usb_serial_resume);
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index cc8b44c08712..ee5dd8b5a713 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -885,16 +885,7 @@ static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, un
static void whiteheat_set_termios(struct usb_serial_port *port, struct ktermios *old_termios)
{
dbg("%s -port %d", __FUNCTION__, port->number);
-
- if ((!port->tty) || (!port->tty->termios)) {
- dbg("%s - no tty structures", __FUNCTION__);
- goto exit;
- }
-
firm_setup_port(port);
-
-exit:
- return;
}
@@ -1244,6 +1235,8 @@ static int firm_setup_port(struct usb_serial_port *port) {
port_settings.baud = tty_get_baud_rate(port->tty);
dbg("%s - baud rate = %d", __FUNCTION__, port_settings.baud);
+ /* fixme: should set validated settings */
+ tty_encode_baud_rate(port->tty, port_settings.baud, port_settings.baud);
/* handle any settings that aren't specified in the tty structure */
port_settings.lloop = 0;
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
index fe2c4cd53f5a..7e53333be013 100644
--- a/drivers/usb/storage/Kconfig
+++ b/drivers/usb/storage/Kconfig
@@ -48,7 +48,6 @@ config USB_STORAGE_FREECOM
config USB_STORAGE_ISD200
bool "ISD-200 USB/ATA Bridge support"
depends on USB_STORAGE
- depends on BLK_DEV_IDE=y || BLK_DEV_IDE=USB_STORAGE
---help---
Say Y here if you want to use USB Mass Store devices based
on the In-Systems Design ISD-200 USB/ATA bridge.
diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c
index 4d3cbb12b713..8d3711a7ff06 100644
--- a/drivers/usb/storage/alauda.c
+++ b/drivers/usb/storage/alauda.c
@@ -798,12 +798,13 @@ static int alauda_read_data(struct us_data *us, unsigned long address,
{
unsigned char *buffer;
u16 lba, max_lba;
- unsigned int page, len, index, offset;
+ unsigned int page, len, offset;
unsigned int blockshift = MEDIA_INFO(us).blockshift;
unsigned int pageshift = MEDIA_INFO(us).pageshift;
unsigned int blocksize = MEDIA_INFO(us).blocksize;
unsigned int pagesize = MEDIA_INFO(us).pagesize;
unsigned int uzonesize = MEDIA_INFO(us).uzonesize;
+ struct scatterlist *sg;
int result;
/*
@@ -827,7 +828,8 @@ static int alauda_read_data(struct us_data *us, unsigned long address,
max_lba = MEDIA_INFO(us).capacity >> (blockshift + pageshift);
result = USB_STOR_TRANSPORT_GOOD;
- index = offset = 0;
+ offset = 0;
+ sg = NULL;
while (sectors > 0) {
unsigned int zone = lba / uzonesize; /* integer division */
@@ -873,7 +875,7 @@ static int alauda_read_data(struct us_data *us, unsigned long address,
/* Store the data in the transfer buffer */
usb_stor_access_xfer_buf(buffer, len, us->srb,
- &index, &offset, TO_XFER_BUF);
+ &sg, &offset, TO_XFER_BUF);
page = 0;
lba++;
@@ -891,11 +893,12 @@ static int alauda_write_data(struct us_data *us, unsigned long address,
unsigned int sectors)
{
unsigned char *buffer, *blockbuffer;
- unsigned int page, len, index, offset;
+ unsigned int page, len, offset;
unsigned int blockshift = MEDIA_INFO(us).blockshift;
unsigned int pageshift = MEDIA_INFO(us).pageshift;
unsigned int blocksize = MEDIA_INFO(us).blocksize;
unsigned int pagesize = MEDIA_INFO(us).pagesize;
+ struct scatterlist *sg;
u16 lba, max_lba;
int result;
@@ -929,7 +932,8 @@ static int alauda_write_data(struct us_data *us, unsigned long address,
max_lba = MEDIA_INFO(us).capacity >> (pageshift + blockshift);
result = USB_STOR_TRANSPORT_GOOD;
- index = offset = 0;
+ offset = 0;
+ sg = NULL;
while (sectors > 0) {
/* Write as many sectors as possible in this block */
@@ -946,7 +950,7 @@ static int alauda_write_data(struct us_data *us, unsigned long address,
/* Get the data from the transfer buffer */
usb_stor_access_xfer_buf(buffer, len, us->srb,
- &index, &offset, FROM_XFER_BUF);
+ &sg, &offset, FROM_XFER_BUF);
result = alauda_write_lba(us, lba, page, pages, buffer,
blockbuffer);
diff --git a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c
index c87ad1bae1d6..579e9f52053a 100644
--- a/drivers/usb/storage/datafab.c
+++ b/drivers/usb/storage/datafab.c
@@ -98,7 +98,8 @@ static int datafab_read_data(struct us_data *us,
unsigned char thistime;
unsigned int totallen, alloclen;
int len, result;
- unsigned int sg_idx = 0, sg_offset = 0;
+ unsigned int sg_offset = 0;
+ struct scatterlist *sg = NULL;
// we're working in LBA mode. according to the ATA spec,
// we can support up to 28-bit addressing. I don't know if Datafab
@@ -155,7 +156,7 @@ static int datafab_read_data(struct us_data *us,
// Store the data in the transfer buffer
usb_stor_access_xfer_buf(buffer, len, us->srb,
- &sg_idx, &sg_offset, TO_XFER_BUF);
+ &sg, &sg_offset, TO_XFER_BUF);
sector += thistime;
totallen -= len;
@@ -181,7 +182,8 @@ static int datafab_write_data(struct us_data *us,
unsigned char thistime;
unsigned int totallen, alloclen;
int len, result;
- unsigned int sg_idx = 0, sg_offset = 0;
+ unsigned int sg_offset = 0;
+ struct scatterlist *sg = NULL;
// we're working in LBA mode. according to the ATA spec,
// we can support up to 28-bit addressing. I don't know if Datafab
@@ -217,7 +219,7 @@ static int datafab_write_data(struct us_data *us,
// Get the data from the transfer buffer
usb_stor_access_xfer_buf(buffer, len, us->srb,
- &sg_idx, &sg_offset, FROM_XFER_BUF);
+ &sg, &sg_offset, FROM_XFER_BUF);
command[0] = 0;
command[1] = thistime;
diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
index 6831dca93c1b..49ba6c0ff1e8 100644
--- a/drivers/usb/storage/isd200.c
+++ b/drivers/usb/storage/isd200.c
@@ -3,7 +3,7 @@
* $Id: isd200.c,v 1.16 2002/04/22 03:39:43 mdharm Exp $
*
* Current development and maintenance:
- * (C) 2001-2002 Björn Stenberg (bjorn@haxx.se)
+ * (C) 2001-2002 Björn Stenberg (bjorn@haxx.se)
*
* Developed with the assistance of:
* (C) 2002 Alan Stern <stern@rowland.org>
@@ -977,6 +977,109 @@ static int isd200_manual_enum(struct us_data *us)
return(retStatus);
}
+/*
+ * We are the last non IDE user of the legacy IDE ident structures
+ * and we thus want to keep a private copy of this function so the
+ * driver can be used without the obsolete drivers/ide layer
+ */
+
+static void isd200_fix_driveid (struct hd_driveid *id)
+{
+#ifndef __LITTLE_ENDIAN
+# ifdef __BIG_ENDIAN
+ int i;
+ u16 *stringcast;
+
+ id->config = __le16_to_cpu(id->config);
+ id->cyls = __le16_to_cpu(id->cyls);
+ id->reserved2 = __le16_to_cpu(id->reserved2);
+ id->heads = __le16_to_cpu(id->heads);
+ id->track_bytes = __le16_to_cpu(id->track_bytes);
+ id->sector_bytes = __le16_to_cpu(id->sector_bytes);
+ id->sectors = __le16_to_cpu(id->sectors);
+ id->vendor0 = __le16_to_cpu(id->vendor0);
+ id->vendor1 = __le16_to_cpu(id->vendor1);
+ id->vendor2 = __le16_to_cpu(id->vendor2);
+ stringcast = (u16 *)&id->serial_no[0];
+ for (i = 0; i < (20/2); i++)
+ stringcast[i] = __le16_to_cpu(stringcast[i]);
+ id->buf_type = __le16_to_cpu(id->buf_type);
+ id->buf_size = __le16_to_cpu(id->buf_size);
+ id->ecc_bytes = __le16_to_cpu(id->ecc_bytes);
+ stringcast = (u16 *)&id->fw_rev[0];
+ for (i = 0; i < (8/2); i++)
+ stringcast[i] = __le16_to_cpu(stringcast[i]);
+ stringcast = (u16 *)&id->model[0];
+ for (i = 0; i < (40/2); i++)
+ stringcast[i] = __le16_to_cpu(stringcast[i]);
+ id->dword_io = __le16_to_cpu(id->dword_io);
+ id->reserved50 = __le16_to_cpu(id->reserved50);
+ id->field_valid = __le16_to_cpu(id->field_valid);
+ id->cur_cyls = __le16_to_cpu(id->cur_cyls);
+ id->cur_heads = __le16_to_cpu(id->cur_heads);
+ id->cur_sectors = __le16_to_cpu(id->cur_sectors);
+ id->cur_capacity0 = __le16_to_cpu(id->cur_capacity0);
+ id->cur_capacity1 = __le16_to_cpu(id->cur_capacity1);
+ id->lba_capacity = __le32_to_cpu(id->lba_capacity);
+ id->dma_1word = __le16_to_cpu(id->dma_1word);
+ id->dma_mword = __le16_to_cpu(id->dma_mword);
+ id->eide_pio_modes = __le16_to_cpu(id->eide_pio_modes);
+ id->eide_dma_min = __le16_to_cpu(id->eide_dma_min);
+ id->eide_dma_time = __le16_to_cpu(id->eide_dma_time);
+ id->eide_pio = __le16_to_cpu(id->eide_pio);
+ id->eide_pio_iordy = __le16_to_cpu(id->eide_pio_iordy);
+ for (i = 0; i < 2; ++i)
+ id->words69_70[i] = __le16_to_cpu(id->words69_70[i]);
+ for (i = 0; i < 4; ++i)
+ id->words71_74[i] = __le16_to_cpu(id->words71_74[i]);
+ id->queue_depth = __le16_to_cpu(id->queue_depth);
+ for (i = 0; i < 4; ++i)
+ id->words76_79[i] = __le16_to_cpu(id->words76_79[i]);
+ id->major_rev_num = __le16_to_cpu(id->major_rev_num);
+ id->minor_rev_num = __le16_to_cpu(id->minor_rev_num);
+ id->command_set_1 = __le16_to_cpu(id->command_set_1);
+ id->command_set_2 = __le16_to_cpu(id->command_set_2);
+ id->cfsse = __le16_to_cpu(id->cfsse);
+ id->cfs_enable_1 = __le16_to_cpu(id->cfs_enable_1);
+ id->cfs_enable_2 = __le16_to_cpu(id->cfs_enable_2);
+ id->csf_default = __le16_to_cpu(id->csf_default);
+ id->dma_ultra = __le16_to_cpu(id->dma_ultra);
+ id->trseuc = __le16_to_cpu(id->trseuc);
+ id->trsEuc = __le16_to_cpu(id->trsEuc);
+ id->CurAPMvalues = __le16_to_cpu(id->CurAPMvalues);
+ id->mprc = __le16_to_cpu(id->mprc);
+ id->hw_config = __le16_to_cpu(id->hw_config);
+ id->acoustic = __le16_to_cpu(id->acoustic);
+ id->msrqs = __le16_to_cpu(id->msrqs);
+ id->sxfert = __le16_to_cpu(id->sxfert);
+ id->sal = __le16_to_cpu(id->sal);
+ id->spg = __le32_to_cpu(id->spg);
+ id->lba_capacity_2 = __le64_to_cpu(id->lba_capacity_2);
+ for (i = 0; i < 22; i++)
+ id->words104_125[i] = __le16_to_cpu(id->words104_125[i]);
+ id->last_lun = __le16_to_cpu(id->last_lun);
+ id->word127 = __le16_to_cpu(id->word127);
+ id->dlf = __le16_to_cpu(id->dlf);
+ id->csfo = __le16_to_cpu(id->csfo);
+ for (i = 0; i < 26; i++)
+ id->words130_155[i] = __le16_to_cpu(id->words130_155[i]);
+ id->word156 = __le16_to_cpu(id->word156);
+ for (i = 0; i < 3; i++)
+ id->words157_159[i] = __le16_to_cpu(id->words157_159[i]);
+ id->cfa_power = __le16_to_cpu(id->cfa_power);
+ for (i = 0; i < 14; i++)
+ id->words161_175[i] = __le16_to_cpu(id->words161_175[i]);
+ for (i = 0; i < 31; i++)
+ id->words176_205[i] = __le16_to_cpu(id->words176_205[i]);
+ for (i = 0; i < 48; i++)
+ id->words206_254[i] = __le16_to_cpu(id->words206_254[i]);
+ id->integrity_word = __le16_to_cpu(id->integrity_word);
+# else
+# error "Please fix <asm/byteorder.h>"
+# endif
+#endif
+}
+
/**************************************************************************
* isd200_get_inquiry_data
@@ -1018,7 +1121,7 @@ static int isd200_get_inquiry_data( struct us_data *us )
int i;
__be16 *src;
__u16 *dest;
- ide_fix_driveid(id);
+ isd200_fix_driveid(id);
US_DEBUGP(" Identify Data Structure:\n");
US_DEBUGP(" config = 0x%x\n", id->config);
diff --git a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c
index 003fcf545888..61097cbb1585 100644
--- a/drivers/usb/storage/jumpshot.c
+++ b/drivers/usb/storage/jumpshot.c
@@ -119,7 +119,8 @@ static int jumpshot_read_data(struct us_data *us,
unsigned char thistime;
unsigned int totallen, alloclen;
int len, result;
- unsigned int sg_idx = 0, sg_offset = 0;
+ unsigned int sg_offset = 0;
+ struct scatterlist *sg = NULL;
// we're working in LBA mode. according to the ATA spec,
// we can support up to 28-bit addressing. I don't know if Jumpshot
@@ -170,7 +171,7 @@ static int jumpshot_read_data(struct us_data *us,
// Store the data in the transfer buffer
usb_stor_access_xfer_buf(buffer, len, us->srb,
- &sg_idx, &sg_offset, TO_XFER_BUF);
+ &sg, &sg_offset, TO_XFER_BUF);
sector += thistime;
totallen -= len;
@@ -195,7 +196,8 @@ static int jumpshot_write_data(struct us_data *us,
unsigned char thistime;
unsigned int totallen, alloclen;
int len, result, waitcount;
- unsigned int sg_idx = 0, sg_offset = 0;
+ unsigned int sg_offset = 0;
+ struct scatterlist *sg = NULL;
// we're working in LBA mode. according to the ATA spec,
// we can support up to 28-bit addressing. I don't know if Jumpshot
@@ -225,7 +227,7 @@ static int jumpshot_write_data(struct us_data *us,
// Get the data from the transfer buffer
usb_stor_access_xfer_buf(buffer, len, us->srb,
- &sg_idx, &sg_offset, FROM_XFER_BUF);
+ &sg, &sg_offset, FROM_XFER_BUF);
command[0] = 0;
command[1] = thistime;
diff --git a/drivers/usb/storage/libusual.c b/drivers/usb/storage/libusual.c
index 06d1107dbd47..55b952084f0c 100644
--- a/drivers/usb/storage/libusual.c
+++ b/drivers/usb/storage/libusual.c
@@ -30,7 +30,7 @@ static atomic_t usu_bias = ATOMIC_INIT(USB_US_DEFAULT_BIAS);
#define BIAS_NAME_SIZE (sizeof("usb-storage"))
static const char *bias_names[3] = { "none", "usb-storage", "ub" };
-static DECLARE_MUTEX_LOCKED(usu_init_notify);
+static struct semaphore usu_init_notify;
static DECLARE_COMPLETION(usu_end_notify);
static atomic_t total_threads = ATOMIC_INIT(0);
@@ -204,6 +204,8 @@ static int __init usb_usual_init(void)
{
int rc;
+ sema_init(&usu_init_notify, 0);
+
rc = usb_register(&usu_driver);
up(&usu_init_notify);
return rc;
diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c
index 9ad30428d2dd..889622baac20 100644
--- a/drivers/usb/storage/protocol.c
+++ b/drivers/usb/storage/protocol.c
@@ -157,7 +157,7 @@ void usb_stor_transparent_scsi_command(struct scsi_cmnd *srb,
* pick up from where this one left off. */
unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
- unsigned int buflen, struct scsi_cmnd *srb, unsigned int *index,
+ unsigned int buflen, struct scsi_cmnd *srb, struct scatterlist **sgptr,
unsigned int *offset, enum xfer_buf_dir dir)
{
unsigned int cnt;
@@ -184,17 +184,18 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
* located in high memory -- then kmap() will map it to a temporary
* position in the kernel's virtual address space. */
} else {
- struct scatterlist *sg =
- (struct scatterlist *) srb->request_buffer
- + *index;
+ struct scatterlist *sg = *sgptr;
+
+ if (!sg)
+ sg = (struct scatterlist *) srb->request_buffer;
/* This loop handles a single s-g list entry, which may
* include multiple pages. Find the initial page structure
* and the starting offset within the page, and update
* the *offset and *index values for the next loop. */
cnt = 0;
- while (cnt < buflen && *index < srb->use_sg) {
- struct page *page = sg->page +
+ while (cnt < buflen) {
+ struct page *page = sg_page(sg) +
((sg->offset + *offset) >> PAGE_SHIFT);
unsigned int poff =
(sg->offset + *offset) & (PAGE_SIZE-1);
@@ -209,8 +210,7 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
/* Transfer continues to next s-g entry */
*offset = 0;
- ++*index;
- ++sg;
+ sg = sg_next(sg);
}
/* Transfer the data for all the pages in this
@@ -234,6 +234,7 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
sglen -= plen;
}
}
+ *sgptr = sg;
}
/* Return the amount actually transferred */
@@ -245,9 +246,10 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
void usb_stor_set_xfer_buf(unsigned char *buffer,
unsigned int buflen, struct scsi_cmnd *srb)
{
- unsigned int index = 0, offset = 0;
+ unsigned int offset = 0;
+ struct scatterlist *sg = NULL;
- usb_stor_access_xfer_buf(buffer, buflen, srb, &index, &offset,
+ usb_stor_access_xfer_buf(buffer, buflen, srb, &sg, &offset,
TO_XFER_BUF);
if (buflen < srb->request_bufflen)
srb->resid = srb->request_bufflen - buflen;
diff --git a/drivers/usb/storage/protocol.h b/drivers/usb/storage/protocol.h
index 845bed4b8031..8737a36891ca 100644
--- a/drivers/usb/storage/protocol.h
+++ b/drivers/usb/storage/protocol.h
@@ -52,7 +52,7 @@ extern void usb_stor_transparent_scsi_command(struct scsi_cmnd*,
enum xfer_buf_dir {TO_XFER_BUF, FROM_XFER_BUF};
extern unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
- unsigned int buflen, struct scsi_cmnd *srb, unsigned int *index,
+ unsigned int buflen, struct scsi_cmnd *srb, struct scatterlist **,
unsigned int *offset, enum xfer_buf_dir dir);
extern void usb_stor_set_xfer_buf(unsigned char *buffer,
diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
index b2ed2a3e6fca..b12202c5da2d 100644
--- a/drivers/usb/storage/sddr09.c
+++ b/drivers/usb/storage/sddr09.c
@@ -705,7 +705,8 @@ sddr09_read_data(struct us_data *us,
unsigned char *buffer;
unsigned int lba, maxlba, pba;
unsigned int page, pages;
- unsigned int len, index, offset;
+ unsigned int len, offset;
+ struct scatterlist *sg;
int result;
// Figure out the initial LBA and page
@@ -730,7 +731,8 @@ sddr09_read_data(struct us_data *us,
// contiguous LBA's. Another exercise left to the student.
result = 0;
- index = offset = 0;
+ offset = 0;
+ sg = NULL;
while (sectors > 0) {
@@ -777,7 +779,7 @@ sddr09_read_data(struct us_data *us,
// Store the data in the transfer buffer
usb_stor_access_xfer_buf(buffer, len, us->srb,
- &index, &offset, TO_XFER_BUF);
+ &sg, &offset, TO_XFER_BUF);
page = 0;
lba++;
@@ -931,7 +933,8 @@ sddr09_write_data(struct us_data *us,
unsigned int pagelen, blocklen;
unsigned char *blockbuffer;
unsigned char *buffer;
- unsigned int len, index, offset;
+ unsigned int len, offset;
+ struct scatterlist *sg;
int result;
// Figure out the initial LBA and page
@@ -968,7 +971,8 @@ sddr09_write_data(struct us_data *us,
}
result = 0;
- index = offset = 0;
+ offset = 0;
+ sg = NULL;
while (sectors > 0) {
@@ -987,7 +991,7 @@ sddr09_write_data(struct us_data *us,
// Get the data from the transfer buffer
usb_stor_access_xfer_buf(buffer, len, us->srb,
- &index, &offset, FROM_XFER_BUF);
+ &sg, &offset, FROM_XFER_BUF);
result = sddr09_write_lba(us, lba, page, pages,
buffer, blockbuffer);
diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c
index 0b1b5b59ca7b..d43a3415e12f 100644
--- a/drivers/usb/storage/sddr55.c
+++ b/drivers/usb/storage/sddr55.c
@@ -167,7 +167,8 @@ static int sddr55_read_data(struct us_data *us,
unsigned long address;
unsigned short pages;
- unsigned int len, index, offset;
+ unsigned int len, offset;
+ struct scatterlist *sg;
// Since we only read in one block at a time, we have to create
// a bounce buffer and move the data a piece at a time between the
@@ -178,7 +179,8 @@ static int sddr55_read_data(struct us_data *us,
buffer = kmalloc(len, GFP_NOIO);
if (buffer == NULL)
return USB_STOR_TRANSPORT_ERROR; /* out of memory */
- index = offset = 0;
+ offset = 0;
+ sg = NULL;
while (sectors>0) {
@@ -255,7 +257,7 @@ static int sddr55_read_data(struct us_data *us,
// Store the data in the transfer buffer
usb_stor_access_xfer_buf(buffer, len, us->srb,
- &index, &offset, TO_XFER_BUF);
+ &sg, &offset, TO_XFER_BUF);
page = 0;
lba++;
@@ -287,7 +289,8 @@ static int sddr55_write_data(struct us_data *us,
unsigned short pages;
int i;
- unsigned int len, index, offset;
+ unsigned int len, offset;
+ struct scatterlist *sg;
/* check if we are allowed to write */
if (info->read_only || info->force_read_only) {
@@ -304,7 +307,8 @@ static int sddr55_write_data(struct us_data *us,
buffer = kmalloc(len, GFP_NOIO);
if (buffer == NULL)
return USB_STOR_TRANSPORT_ERROR;
- index = offset = 0;
+ offset = 0;
+ sg = NULL;
while (sectors > 0) {
@@ -322,7 +326,7 @@ static int sddr55_write_data(struct us_data *us,
// Get the data from the transfer buffer
usb_stor_access_xfer_buf(buffer, len, us->srb,
- &index, &offset, FROM_XFER_BUF);
+ &sg, &offset, FROM_XFER_BUF);
US_DEBUGP("Write %02X pages, to PBA %04X"
" (LBA %04X) page %02X\n",
diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
index 17ca4d73577b..cb22a9ad1694 100644
--- a/drivers/usb/storage/shuttle_usbat.c
+++ b/drivers/usb/storage/shuttle_usbat.c
@@ -993,7 +993,8 @@ static int usbat_flash_read_data(struct us_data *us,
unsigned char thistime;
unsigned int totallen, alloclen;
int len, result;
- unsigned int sg_idx = 0, sg_offset = 0;
+ unsigned int sg_offset = 0;
+ struct scatterlist *sg = NULL;
result = usbat_flash_check_media(us, info);
if (result != USB_STOR_TRANSPORT_GOOD)
@@ -1047,7 +1048,7 @@ static int usbat_flash_read_data(struct us_data *us,
/* Store the data in the transfer buffer */
usb_stor_access_xfer_buf(buffer, len, us->srb,
- &sg_idx, &sg_offset, TO_XFER_BUF);
+ &sg, &sg_offset, TO_XFER_BUF);
sector += thistime;
totallen -= len;
@@ -1083,7 +1084,8 @@ static int usbat_flash_write_data(struct us_data *us,
unsigned char thistime;
unsigned int totallen, alloclen;
int len, result;
- unsigned int sg_idx = 0, sg_offset = 0;
+ unsigned int sg_offset = 0;
+ struct scatterlist *sg = NULL;
result = usbat_flash_check_media(us, info);
if (result != USB_STOR_TRANSPORT_GOOD)
@@ -1122,7 +1124,7 @@ static int usbat_flash_write_data(struct us_data *us,
/* Get the data from the transfer buffer */
usb_stor_access_xfer_buf(buffer, len, us->srb,
- &sg_idx, &sg_offset, FROM_XFER_BUF);
+ &sg, &sg_offset, FROM_XFER_BUF);
/* ATA command 0x30 (WRITE SECTORS) */
usbat_pack_ata_sector_cmd(command, thistime, sector, 0x30);
@@ -1162,8 +1164,8 @@ static int usbat_hp8200e_handle_read10(struct us_data *us,
unsigned char *buffer;
unsigned int len;
unsigned int sector;
- unsigned int sg_segment = 0;
unsigned int sg_offset = 0;
+ struct scatterlist *sg = NULL;
US_DEBUGP("handle_read10: transfersize %d\n",
srb->transfersize);
@@ -1220,9 +1222,6 @@ static int usbat_hp8200e_handle_read10(struct us_data *us,
sector |= short_pack(data[7+5], data[7+4]);
transferred = 0;
- sg_segment = 0; /* for keeping track of where we are in */
- sg_offset = 0; /* the scatter/gather list */
-
while (transferred != srb->request_bufflen) {
if (len > srb->request_bufflen - transferred)
@@ -1255,7 +1254,7 @@ static int usbat_hp8200e_handle_read10(struct us_data *us,
/* Store the data in the transfer buffer */
usb_stor_access_xfer_buf(buffer, len, srb,
- &sg_segment, &sg_offset, TO_XFER_BUF);
+ &sg, &sg_offset, TO_XFER_BUF);
/* Update the amount transferred and the sector number */
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 9b656ec427d0..22ab2380367d 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -407,7 +407,7 @@ UNUSUAL_DEV( 0x04cb, 0x0100, 0x0000, 0x2210,
"FinePix 1400Zoom",
US_SC_UFI, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY | US_FL_SINGLE_LUN),
-/* Reported by Peter Wächtler <pwaechtler@loewe-komp.de>
+/* Reported by Peter Wächtler <pwaechtler@loewe-komp.de>
* The device needs the flags only.
*/
UNUSUAL_DEV( 0x04ce, 0x0002, 0x0074, 0x0074,
@@ -1551,7 +1551,7 @@ UNUSUAL_DEV( 0x2735, 0x100b, 0x0000, 0x9999,
US_FL_GO_SLOW ),
/*
- * David Härdeman <david@2gen.com>
+ * David Härdeman <david@2gen.com>
* The key makes the SCSI stack print confusing (but harmless) messages
*/
UNUSUAL_DEV( 0x4146, 0xba01, 0x0100, 0x0100,
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 3451e8d03ab0..ac6114eea0c3 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -907,12 +907,9 @@ static int usb_stor_scan_thread(void * __us)
if (delay_use > 0) {
printk(KERN_DEBUG "usb-storage: waiting for device "
"to settle before scanning\n");
-retry:
- wait_event_interruptible_timeout(us->delay_wait,
+ wait_event_freezable_timeout(us->delay_wait,
test_bit(US_FLIDX_DISCONNECTING, &us->flags),
delay_use * HZ);
- if (try_to_freeze())
- goto retry;
}
/* If the device is still connected, perform the scanning */
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 5216c11d4dec..7d86e9eae915 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -5,8 +5,9 @@
menu "Graphics support"
depends on HAS_IOMEM
-source "drivers/video/backlight/Kconfig"
-source "drivers/video/display/Kconfig"
+source "drivers/char/agp/Kconfig"
+
+source "drivers/char/drm/Kconfig"
config VGASTATE
tristate
@@ -14,12 +15,11 @@ config VGASTATE
config VIDEO_OUTPUT_CONTROL
tristate "Lowlevel video output switch controls"
- default m
help
This framework adds support for low-level control of the video
output switch.
-config FB
+menuconfig FB
tristate "Support for frame buffer devices"
---help---
The frame buffer device provides an abstraction for the graphics
@@ -103,6 +103,15 @@ config FB_CFB_IMAGEBLIT
blitting. This is used by drivers that don't provide their own
(accelerated) version.
+config FB_CFB_REV_PIXELS_IN_BYTE
+ bool
+ depends on FB
+ default n
+ ---help---
+ Allow generic frame-buffer functions to work on displays with 1, 2
+ and 4 bits per pixel depths which has opposite order of pixels in
+ byte order to bytes in long order.
+
config FB_SYS_FILLRECT
tristate
depends on FB
@@ -494,7 +503,7 @@ config FB_VALKYRIE
config FB_CT65550
bool "Chips 65550 display support"
- depends on (FB = y) && PPC32
+ depends on (FB = y) && PPC32 && PCI
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
@@ -535,6 +544,15 @@ config FB_VGA16
To compile this driver as a module, choose M here: the
module will be called vga16fb.
+config FB_BF54X_LQ043
+ tristate "SHARP LQ043 TFT LCD (BF548 EZKIT)"
+ depends on FB && (BF54x)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is the framebuffer device driver for a SHARP LQ043T1DG01 TFT LCD
+
config FB_STI
tristate "HP STI frame buffer device support"
depends on FB && PARISC
@@ -592,6 +610,24 @@ config FB_TGA
Say Y if you have one of those.
+config FB_UVESA
+ tristate "Userspace VESA VGA graphics support"
+ depends on FB && CONNECTOR
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_MODE_HELPERS
+ help
+ This is the frame buffer driver for generic VBE 2.0 compliant
+ graphic cards. It can also take advantage of VBE 3.0 features,
+ such as refresh rate adjustment.
+
+ This driver generally provides more features than vesafb but
+ requires a userspace helper application called 'v86d'. See
+ <file:Documentation/fb/uvesafb.txt> for more information.
+
+ If unsure, say N.
+
config FB_VESA
bool "VESA VGA graphics support"
depends on (FB = y) && X86
@@ -625,7 +661,7 @@ config FB_HECUBA
help
This enables support for the Hecuba board. This driver was tested
with an E-Ink 800x600 display and x86 SBCs through a 16 bit GPIO
- interface (8 bit data, 4 bit control). If you anticpate using
+ interface (8 bit data, 4 bit control). If you anticipate using
this driver, say Y or M; otherwise say N. You must specify the
GPIO IO address to be used for setting control and data.
@@ -779,7 +815,7 @@ config FB_XVR500
help
This is the framebuffer device for the Sun XVR-500 and similar
graphics cards based upon the 3DLABS Wildcat chipset. The driver
- only works on sparc64 systems where the system firwmare has
+ only works on sparc64 systems where the system firmware has
mostly initialized the card already. It is treated as a
completely dumb framebuffer device.
@@ -792,7 +828,7 @@ config FB_XVR2500
help
This is the framebuffer device for the Sun XVR-2500 and similar
graphics cards based upon the 3DLABS Wildcat chipset. The driver
- only works on sparc64 systems where the system firwmare has
+ only works on sparc64 systems where the system firmware has
mostly initialized the card already. It is treated as a
completely dumb framebuffer device.
@@ -1473,7 +1509,7 @@ config FB_VOODOO1
WARNING: Do not use any application that uses the 3D engine
(namely glide) while using this driver.
- Please read the <file:Documentation/fb/README-sstfb.txt> for supported
+ Please read the <file:Documentation/fb/sstfb.txt> for supported
options and other important info support.
config FB_VT8623
@@ -1625,7 +1661,7 @@ config FB_PMAG_BA
config FB_PMAGB_B
tristate "PMAGB-B TURBOchannel framebuffer support"
- depends on TC
+ depends on FB && TC
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
@@ -1771,7 +1807,7 @@ config FB_SM501
This driver is also available as a module ( = code which can be
inserted and removed from the running kernel whenever you want). The
module will be called sm501fb. If you want to compile it as a module,
- say M here and read <file:Documentation/modules.txt>.
+ say M here and read <file:Documentation/kbuild/modules.txt>.
If unsure, say N.
@@ -1793,7 +1829,7 @@ config FB_PNX4008_DUM_RGB
config FB_IBM_GXT4500
tristate "Framebuffer support for IBM GXT4500P adaptor"
- depends on PPC
+ depends on FB && PPC
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
@@ -1833,10 +1869,6 @@ config FB_XILINX
framebuffer. ML300 carries a 640*480 LCD display on the board,
ML403 uses a standard DB15 VGA connector.
-if ARCH_OMAP
- source "drivers/video/omap/Kconfig"
-endif
-
config FB_VIRTUAL
tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
depends on FB
@@ -1860,6 +1892,11 @@ config FB_VIRTUAL
If unsure, say N.
+source "drivers/video/omap/Kconfig"
+
+source "drivers/video/backlight/Kconfig"
+source "drivers/video/display/Kconfig"
+
if VT
source "drivers/video/console/Kconfig"
endif
@@ -1869,4 +1906,3 @@ if FB || SGI_NEWPORT_CONSOLE
endif
endmenu
-
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 06eec7b182b7..59d6c45a910d 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -115,10 +115,12 @@ obj-$(CONFIG_FB_XILINX) += xilinxfb.o
obj-$(CONFIG_FB_OMAP) += omap/
# Platform or fallback drivers go here
+obj-$(CONFIG_FB_UVESA) += uvesafb.o
obj-$(CONFIG_FB_VESA) += vesafb.o
obj-$(CONFIG_FB_IMAC) += imacfb.o
obj-$(CONFIG_FB_VGA16) += vga16fb.o
obj-$(CONFIG_FB_OF) += offb.o
+obj-$(CONFIG_FB_BF54X_LQ043) += bf54x-lq043fb.o
# the test framebuffer is last
obj-$(CONFIG_FB_VIRTUAL) += vfb.o
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index 1a849b870bcc..4c9ec3f58c52 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -52,7 +52,7 @@
#include <linux/init.h>
#include <linux/ioport.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/amigahw.h>
@@ -112,7 +112,7 @@
+----------+---------------------------------------------+----------+-------+
| | ^ | | |
| | |upper_margin | | |
- | | ¥ | | |
+ | | v | | |
+----------###############################################----------+-------+
| # ^ # | |
| # | # | |
@@ -133,15 +133,15 @@
| # | # | |
| # | # | |
| # | # | |
- | # ¥ # | |
+ | # v # | |
+----------###############################################----------+-------+
| | ^ | | |
| | |lower_margin | | |
- | | ¥ | | |
+ | | v | | |
+----------+---------------------------------------------+----------+-------+
| | ^ | | |
| | |vsync_len | | |
- | | ¥ | | |
+ | | v | | |
+----------+---------------------------------------------+----------+-------+
@@ -325,7 +325,7 @@
CCIR -> PAL
-----------
- - a scanline is 64 µs long, of which 52.48 µs are visible. This is about
+ - a scanline is 64 µs long, of which 52.48 µs are visible. This is about
736 visible 70 ns pixels per line.
- we have 625 scanlines, of which 575 are visible (interlaced); after
rounding this becomes 576.
@@ -333,7 +333,7 @@
RETMA -> NTSC
-------------
- - a scanline is 63.5 µs long, of which 53.5 µs are visible. This is about
+ - a scanline is 63.5 µs long, of which 53.5 µs are visible. This is about
736 visible 70 ns pixels per line.
- we have 525 scanlines, of which 485 are visible (interlaced); after
rounding this becomes 484.
@@ -802,7 +802,7 @@ static u_short ecs_palette[32];
static u_short do_vmode_full = 0; /* Change the Video Mode */
static u_short do_vmode_pan = 0; /* Update the Video Mode */
-static short do_blank = 0; /* (Un)Blank the Screen (±1) */
+static short do_blank = 0; /* (Un)Blank the Screen (±1) */
static u_short do_cursor = 0; /* Move the Cursor */
diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c
index db15baca3f7b..c3431691c9f2 100644
--- a/drivers/video/arcfb.c
+++ b/drivers/video/arcfb.c
@@ -48,7 +48,7 @@
#include <linux/arcfb.h>
#include <linux/platform_device.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#define floor8(a) (a&(~0x07))
#define floorXres(a,xres) (a&(~(xres - 1)))
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c
index 0038a0541c7e..5d4fbaa53a6c 100644
--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -58,7 +58,7 @@
#include <linux/interrupt.h>
#include <asm/setup.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <asm/pgtable.h>
#include <asm/irq.h>
#include <asm/io.h>
diff --git a/drivers/video/aty/ati_ids.h b/drivers/video/aty/ati_ids.h
index dca2eb8f2dde..3e9d28bcd9f8 100644
--- a/drivers/video/aty/ati_ids.h
+++ b/drivers/video/aty/ati_ids.h
@@ -188,6 +188,7 @@
#define PCI_CHIP_MACH64VT 0x5654
#define PCI_CHIP_MACH64VU 0x5655
#define PCI_CHIP_MACH64VV 0x5656
+#define PCI_CHIP_RC410_5A62 0x5A62
#define PCI_CHIP_RS300_5834 0x5834
#define PCI_CHIP_RS300_5835 0x5835
#define PCI_CHIP_RS300_5836 0x5836
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index cfcbe37d2d70..cbd3308b6690 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -56,7 +56,7 @@
#include <linux/vmalloc.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/pci.h>
diff --git a/drivers/video/aty/atyfb.h b/drivers/video/aty/atyfb.h
index dc62f8e282b4..7691e73823d3 100644
--- a/drivers/video/aty/atyfb.h
+++ b/drivers/video/aty/atyfb.h
@@ -126,6 +126,7 @@ union aty_pll {
*/
struct atyfb_par {
+ u32 pseudo_palette[16];
struct { u8 red, green, blue; } palette[256];
const struct aty_dac_ops *dac_ops;
const struct aty_pll_ops *pll_ops;
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index bc6f0096aa04..d775eb6590b6 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -26,7 +26,7 @@
* Anthony Tong <atong@uiuc.edu>
*
* Generic LCD support written by Daniel Mantione, ported from 2.4.20 by Alex Kern
- * Many Thanks to Ville Syrjälä for patches and fixing nasting 16 bit color bug.
+ * Many Thanks to Ville Syrjälä for patches and fixing nasting 16 bit color bug.
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
@@ -68,7 +68,7 @@
#include <linux/backlight.h>
#include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <video/mach64.h>
#include "atyfb.h"
@@ -541,8 +541,6 @@ static char ram_off[] __devinitdata = "OFF";
#endif /* CONFIG_FB_ATY_CT */
-static u32 pseudo_palette[16];
-
#ifdef CONFIG_FB_ATY_GX
static char *aty_gx_ram[8] __devinitdata = {
ram_dram, ram_vram, ram_vram, ram_dram,
@@ -2577,7 +2575,7 @@ static int __devinit aty_init(struct fb_info *info)
#endif
info->fbops = &atyfb_ops;
- info->pseudo_palette = pseudo_palette;
+ info->pseudo_palette = par->pseudo_palette;
info->flags = FBINFO_DEFAULT |
FBINFO_HWACCEL_IMAGEBLIT |
FBINFO_HWACCEL_FILLRECT |
diff --git a/drivers/video/aty/mach64_cursor.c b/drivers/video/aty/mach64_cursor.c
index fe2c6ad01a8d..faf95da8fcbc 100644
--- a/drivers/video/aty/mach64_cursor.c
+++ b/drivers/video/aty/mach64_cursor.c
@@ -8,7 +8,6 @@
#include <linux/string.h>
#include <asm/io.h>
-#include <asm/uaccess.h>
#ifdef __sparc__
#include <asm/fbio.h>
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 4b747bdaeea6..1e32b3d13f2e 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -69,7 +69,7 @@
#include <linux/device.h>
#include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#ifdef CONFIG_PPC_OF
@@ -145,6 +145,8 @@ static struct pci_device_id radeonfb_pci_table[] = {
/* 9000/Pro */
CHIP_DEF(PCI_CHIP_RV250_If, RV250, CHIP_HAS_CRTC2),
CHIP_DEF(PCI_CHIP_RV250_Ig, RV250, CHIP_HAS_CRTC2),
+
+ CHIP_DEF(PCI_CHIP_RC410_5A62, RC410, CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
/* Mobility 9100 IGP (U3) */
CHIP_DEF(PCI_CHIP_RS300_5835, RS300, CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
CHIP_DEF(PCI_CHIP_RS350_7835, RS300, CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
@@ -1999,6 +2001,7 @@ static void radeon_identify_vram(struct radeonfb_info *rinfo)
if ((rinfo->family == CHIP_FAMILY_RS100) ||
(rinfo->family == CHIP_FAMILY_RS200) ||
(rinfo->family == CHIP_FAMILY_RS300) ||
+ (rinfo->family == CHIP_FAMILY_RC410) ||
(rinfo->family == CHIP_FAMILY_RS480) ) {
u32 tom = INREG(NB_TOM);
tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024);
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
index be1d57bf9dc8..83ee3e75386c 100644
--- a/drivers/video/aty/radeon_pm.c
+++ b/drivers/video/aty/radeon_pm.c
@@ -27,8 +27,6 @@
#include "ati_ids.h"
-static void radeon_reinitialize_M10(struct radeonfb_info *rinfo);
-
/*
* Workarounds for bugs in PC laptops:
* - enable D2 sleep in some IBM Thinkpads
@@ -39,6 +37,8 @@ static void radeon_reinitialize_M10(struct radeonfb_info *rinfo);
*/
#if defined(CONFIG_PM) && defined(CONFIG_X86)
+static void radeon_reinitialize_M10(struct radeonfb_info *rinfo);
+
struct radeon_device_id {
const char *ident; /* (arbitrary) Name */
const unsigned short subsystem_vendor; /* Subsystem Vendor ID */
diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h
index 7c922c7b460b..5eac1ce52e72 100644
--- a/drivers/video/aty/radeonfb.h
+++ b/drivers/video/aty/radeonfb.h
@@ -48,6 +48,7 @@ enum radeon_family {
CHIP_FAMILY_RV350,
CHIP_FAMILY_RV380, /* RV370/RV380/M22/M24 */
CHIP_FAMILY_R420, /* R420/R423/M18 */
+ CHIP_FAMILY_RC410,
CHIP_FAMILY_RS480,
CHIP_FAMILY_LAST,
};
@@ -66,7 +67,8 @@ enum radeon_family {
((rinfo)->family == CHIP_FAMILY_R350) || \
((rinfo)->family == CHIP_FAMILY_RV380) || \
((rinfo)->family == CHIP_FAMILY_R420) || \
- ((rinfo)->family == CHIP_FAMILY_RS480) )
+ ((rinfo)->family == CHIP_FAMILY_RC410) || \
+ ((rinfo)->family == CHIP_FAMILY_RS480))
/*
* Chip flags
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
index 832e4613673a..62bd4441b5e0 100644
--- a/drivers/video/au1100fb.c
+++ b/drivers/video/au1100fb.c
@@ -457,7 +457,7 @@ static struct fb_ops au1100fb_ops =
/* AU1100 LCD controller device driver */
-int au1100fb_drv_probe(struct device *dev)
+static int __init au1100fb_drv_probe(struct device *dev)
{
struct au1100fb_device *fbdev = NULL;
struct resource *regs_res;
diff --git a/drivers/video/backlight/cr_bllcd.c b/drivers/video/backlight/cr_bllcd.c
index 92e201e81fbd..26add8898605 100644
--- a/drivers/video/backlight/cr_bllcd.c
+++ b/drivers/video/backlight/cr_bllcd.c
@@ -36,7 +36,6 @@
#include <linux/backlight.h>
#include <linux/lcd.h>
#include <linux/pci.h>
-#include <asm/uaccess.h>
/* The LVDS- and panel power controls sits on the
* GPIO port of the ISA bridge.
diff --git a/drivers/video/backlight/progear_bl.c b/drivers/video/backlight/progear_bl.c
index 836ab4df0ef2..15fb4d58b5bc 100644
--- a/drivers/video/backlight/progear_bl.c
+++ b/drivers/video/backlight/progear_bl.c
@@ -23,7 +23,6 @@
#include <linux/fb.h>
#include <linux/backlight.h>
#include <linux/pci.h>
-#include <asm/uaccess.h>
#define PMU_LPCR 0xB0
#define SB_MPS1 0x61
diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c
new file mode 100644
index 000000000000..74d11c318987
--- /dev/null
+++ b/drivers/video/bf54x-lq043fb.c
@@ -0,0 +1,786 @@
+/*
+ * File: drivers/video/bf54x-lq043.c
+ * Based on:
+ * Author: Michael Hennerich <hennerich@blackfin.uclinux.org>
+ *
+ * Created:
+ * Description: ADSP-BF54x Framebufer driver
+ *
+ *
+ * Modified:
+ * Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/device.h>
+#include <linux/backlight.h>
+#include <linux/lcd.h>
+#include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+
+#include <asm/blackfin.h>
+#include <asm/irq.h>
+#include <asm/dpmc.h>
+#include <asm/dma-mapping.h>
+#include <asm/dma.h>
+#include <asm/gpio.h>
+#include <asm/portmux.h>
+
+#include <asm/mach/bf54x-lq043.h>
+
+#define NO_BL_SUPPORT
+
+#define DRIVER_NAME "bf54x-lq043"
+static char driver_name[] = DRIVER_NAME;
+
+#define BFIN_LCD_NBR_PALETTE_ENTRIES 256
+
+#define EPPI0_18 {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2, P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3, \
+ P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7, P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, \
+ P_PPI0_D11, P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15, P_PPI0_D16, P_PPI0_D17, 0}
+
+#define EPPI0_24 {P_PPI0_D18, P_PPI0_D19, P_PPI0_D20, P_PPI0_D21, P_PPI0_D22, P_PPI0_D23, 0}
+
+struct bfin_bf54xfb_info {
+ struct fb_info *fb;
+ struct device *dev;
+
+ struct bfin_bf54xfb_mach_info *mach_info;
+
+ unsigned char *fb_buffer; /* RGB Buffer */
+
+ dma_addr_t dma_handle;
+ int lq043_mmap;
+ int lq043_open_cnt;
+ int irq;
+ spinlock_t lock; /* lock */
+};
+
+static int nocursor;
+module_param(nocursor, int, 0644);
+MODULE_PARM_DESC(nocursor, "cursor enable/disable");
+
+static int outp_rgb666;
+module_param(outp_rgb666, int, 0);
+MODULE_PARM_DESC(outp_rgb666, "Output 18-bit RGB666");
+
+#define LCD_X_RES 480 /*Horizontal Resolution */
+#define LCD_Y_RES 272 /* Vertical Resolution */
+
+#define LCD_BPP 24 /* Bit Per Pixel */
+#define DMA_BUS_SIZE 32
+
+/* -- Horizontal synchronizing --
+ *
+ * Timing characteristics taken from the SHARP LQ043T1DG01 datasheet
+ * (LCY-W-06602A Page 9 of 22)
+ *
+ * Clock Frequency 1/Tc Min 7.83 Typ 9.00 Max 9.26 MHz
+ *
+ * Period TH - 525 - Clock
+ * Pulse width THp - 41 - Clock
+ * Horizontal period THd - 480 - Clock
+ * Back porch THb - 2 - Clock
+ * Front porch THf - 2 - Clock
+ *
+ * -- Vertical synchronizing --
+ * Period TV - 286 - Line
+ * Pulse width TVp - 10 - Line
+ * Vertical period TVd - 272 - Line
+ * Back porch TVb - 2 - Line
+ * Front porch TVf - 2 - Line
+ */
+
+#define LCD_CLK (8*1000*1000) /* 8MHz */
+
+/* # active data to transfer after Horizontal Delay clock */
+#define EPPI_HCOUNT LCD_X_RES
+
+/* # active lines to transfer after Vertical Delay clock */
+#define EPPI_VCOUNT LCD_Y_RES
+
+/* Samples per Line = 480 (active data) + 45 (padding) */
+#define EPPI_LINE 525
+
+/* Lines per Frame = 272 (active data) + 14 (padding) */
+#define EPPI_FRAME 286
+
+/* FS1 (Hsync) Width (Typical)*/
+#define EPPI_FS1W_HBL 41
+
+/* FS1 (Hsync) Period (Typical) */
+#define EPPI_FS1P_AVPL EPPI_LINE
+
+/* Horizontal Delay clock after assertion of Hsync (Typical) */
+#define EPPI_HDELAY 43
+
+/* FS2 (Vsync) Width = FS1 (Hsync) Period * 10 */
+#define EPPI_FS2W_LVB (EPPI_LINE * 10)
+
+ /* FS2 (Vsync) Period = FS1 (Hsync) Period * Lines per Frame */
+#define EPPI_FS2P_LAVF (EPPI_LINE * EPPI_FRAME)
+
+/* Vertical Delay after assertion of Vsync (2 Lines) */
+#define EPPI_VDELAY 12
+
+#define EPPI_CLIP 0xFF00FF00
+
+/* EPPI Control register configuration value for RGB out
+ * - EPPI as Output
+ * GP 2 frame sync mode,
+ * Internal Clock generation disabled, Internal FS generation enabled,
+ * Receives samples on EPPI_CLK raising edge, Transmits samples on EPPI_CLK falling edge,
+ * FS1 & FS2 are active high,
+ * DLEN = 6 (24 bits for RGB888 out) or 5 (18 bits for RGB666 out)
+ * DMA Unpacking disabled when RGB Formating is enabled, otherwise DMA unpacking enabled
+ * Swapping Enabled,
+ * One (DMA) Channel Mode,
+ * RGB Formatting Enabled for RGB666 output, disabled for RGB888 output
+ * Regular watermark - when FIFO is 100% full,
+ * Urgent watermark - when FIFO is 75% full
+ */
+
+#define EPPI_CONTROL (0x20136E2E | SWAPEN)
+
+static inline u16 get_eppi_clkdiv(u32 target_ppi_clk)
+{
+ u32 sclk = get_sclk();
+
+ /* EPPI_CLK = (SCLK) / (2 * (EPPI_CLKDIV[15:0] + 1)) */
+
+ return (((sclk / target_ppi_clk) / 2) - 1);
+}
+
+static void config_ppi(struct bfin_bf54xfb_info *fbi)
+{
+
+ u16 eppi_clkdiv = get_eppi_clkdiv(LCD_CLK);
+
+ bfin_write_EPPI0_FS1W_HBL(EPPI_FS1W_HBL);
+ bfin_write_EPPI0_FS1P_AVPL(EPPI_FS1P_AVPL);
+ bfin_write_EPPI0_FS2W_LVB(EPPI_FS2W_LVB);
+ bfin_write_EPPI0_FS2P_LAVF(EPPI_FS2P_LAVF);
+ bfin_write_EPPI0_CLIP(EPPI_CLIP);
+
+ bfin_write_EPPI0_FRAME(EPPI_FRAME);
+ bfin_write_EPPI0_LINE(EPPI_LINE);
+
+ bfin_write_EPPI0_HCOUNT(EPPI_HCOUNT);
+ bfin_write_EPPI0_HDELAY(EPPI_HDELAY);
+ bfin_write_EPPI0_VCOUNT(EPPI_VCOUNT);
+ bfin_write_EPPI0_VDELAY(EPPI_VDELAY);
+
+ bfin_write_EPPI0_CLKDIV(eppi_clkdiv);
+
+/*
+ * DLEN = 6 (24 bits for RGB888 out) or 5 (18 bits for RGB666 out)
+ * RGB Formatting Enabled for RGB666 output, disabled for RGB888 output
+ */
+ if (outp_rgb666)
+ bfin_write_EPPI0_CONTROL((EPPI_CONTROL & ~DLENGTH) | DLEN_18 |
+ RGB_FMT_EN);
+ else
+ bfin_write_EPPI0_CONTROL(((EPPI_CONTROL & ~DLENGTH) | DLEN_24) &
+ ~RGB_FMT_EN);
+
+
+}
+
+static int config_dma(struct bfin_bf54xfb_info *fbi)
+{
+
+ set_dma_config(CH_EPPI0,
+ set_bfin_dma_config(DIR_READ, DMA_FLOW_AUTO,
+ INTR_DISABLE, DIMENSION_2D,
+ DATA_SIZE_32));
+ set_dma_x_count(CH_EPPI0, (LCD_X_RES * LCD_BPP) / DMA_BUS_SIZE);
+ set_dma_x_modify(CH_EPPI0, DMA_BUS_SIZE / 8);
+ set_dma_y_count(CH_EPPI0, LCD_Y_RES);
+ set_dma_y_modify(CH_EPPI0, DMA_BUS_SIZE / 8);
+ set_dma_start_addr(CH_EPPI0, (unsigned long)fbi->fb_buffer);
+
+ return 0;
+}
+
+static int request_ports(struct bfin_bf54xfb_info *fbi)
+{
+
+ u16 eppi_req_18[] = EPPI0_18;
+ u16 disp = fbi->mach_info->disp;
+
+ if (gpio_request(disp, NULL)) {
+ printk(KERN_ERR "Requesting GPIO %d faild\n", disp);
+ return -EFAULT;
+ }
+
+ if (peripheral_request_list(eppi_req_18, DRIVER_NAME)) {
+ printk(KERN_ERR "Requesting Peripherals faild\n");
+ gpio_free(disp);
+ return -EFAULT;
+ }
+
+ if (!outp_rgb666) {
+
+ u16 eppi_req_24[] = EPPI0_24;
+
+ if (peripheral_request_list(eppi_req_24, DRIVER_NAME)) {
+ printk(KERN_ERR "Requesting Peripherals faild\n");
+ peripheral_free_list(eppi_req_18);
+ gpio_free(disp);
+ return -EFAULT;
+ }
+ }
+
+ gpio_direction_output(disp);
+ gpio_set_value(disp, 1);
+
+ return 0;
+}
+
+static void free_ports(struct bfin_bf54xfb_info *fbi)
+{
+
+ u16 eppi_req_18[] = EPPI0_18;
+
+ gpio_free(fbi->mach_info->disp);
+
+ peripheral_free_list(eppi_req_18);
+
+ if (!outp_rgb666) {
+ u16 eppi_req_24[] = EPPI0_24;
+ peripheral_free_list(eppi_req_24);
+ }
+}
+
+static int bfin_bf54x_fb_open(struct fb_info *info, int user)
+{
+ struct bfin_bf54xfb_info *fbi = info->par;
+
+ spin_lock(&fbi->lock);
+ fbi->lq043_open_cnt++;
+
+ if (fbi->lq043_open_cnt <= 1) {
+
+ bfin_write_EPPI0_CONTROL(0);
+ SSYNC();
+
+ config_dma(fbi);
+ config_ppi(fbi);
+
+ /* start dma */
+ enable_dma(CH_EPPI0);
+ bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() | EPPI_EN);
+ }
+
+ spin_unlock(&fbi->lock);
+
+ return 0;
+}
+
+static int bfin_bf54x_fb_release(struct fb_info *info, int user)
+{
+ struct bfin_bf54xfb_info *fbi = info->par;
+
+ spin_lock(&fbi->lock);
+
+ fbi->lq043_open_cnt--;
+ fbi->lq043_mmap = 0;
+
+ if (fbi->lq043_open_cnt <= 0) {
+
+ bfin_write_EPPI0_CONTROL(0);
+ SSYNC();
+ disable_dma(CH_EPPI0);
+ memset(fbi->fb_buffer, 0, info->fix.smem_len);
+ }
+
+ spin_unlock(&fbi->lock);
+
+ return 0;
+}
+
+static int bfin_bf54x_fb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+
+ if (var->bits_per_pixel != LCD_BPP) {
+ pr_debug("%s: depth not supported: %u BPP\n", __FUNCTION__,
+ var->bits_per_pixel);
+ return -EINVAL;
+ }
+
+ if (info->var.xres != var->xres || info->var.yres != var->yres ||
+ info->var.xres_virtual != var->xres_virtual ||
+ info->var.yres_virtual != var->yres_virtual) {
+ pr_debug("%s: Resolution not supported: X%u x Y%u \n",
+ __FUNCTION__, var->xres, var->yres);
+ return -EINVAL;
+ }
+
+ /*
+ * Memory limit
+ */
+
+ if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) {
+ pr_debug("%s: Memory Limit requested yres_virtual = %u\n",
+ __FUNCTION__, var->yres_virtual);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static int bfin_bf54x_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+
+ struct bfin_bf54xfb_info *fbi = info->par;
+
+ if (fbi->lq043_mmap)
+ return -1;
+
+ spin_lock(&fbi->lock);
+ fbi->lq043_mmap = 1;
+ spin_unlock(&fbi->lock);
+
+ vma->vm_start = (unsigned long)(fbi->fb_buffer);
+
+ vma->vm_end = vma->vm_start + info->fix.smem_len;
+ /* For those who don't understand how mmap works, go read
+ * Documentation/nommu-mmap.txt.
+ * For those that do, you will know that the VM_MAYSHARE flag
+ * must be set in the vma->vm_flags structure on noMMU
+ * Other flags can be set, and are documented in
+ * include/linux/mm.h
+ */
+ vma->vm_flags |= VM_MAYSHARE;
+
+ return 0;
+}
+
+int bfin_bf54x_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+ if (nocursor)
+ return 0;
+ else
+ return -EINVAL; /* just to force soft_cursor() call */
+}
+
+static int bfin_bf54x_fb_setcolreg(u_int regno, u_int red, u_int green,
+ u_int blue, u_int transp,
+ struct fb_info *info)
+{
+ if (regno >= BFIN_LCD_NBR_PALETTE_ENTRIES)
+ return -EINVAL;
+
+ if (info->var.grayscale) {
+ /* grayscale = 0.30*R + 0.59*G + 0.11*B */
+ red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+ }
+
+ if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+
+ u32 value;
+ /* Place color in the pseudopalette */
+ if (regno > 16)
+ return -EINVAL;
+
+ red >>= (16 - info->var.red.length);
+ green >>= (16 - info->var.green.length);
+ blue >>= (16 - info->var.blue.length);
+
+ value = (red << info->var.red.offset) |
+ (green << info->var.green.offset) |
+ (blue << info->var.blue.offset);
+ value &= 0xFFFFFF;
+
+ ((u32 *) (info->pseudo_palette))[regno] = value;
+
+ }
+
+ return 0;
+}
+
+static struct fb_ops bfin_bf54x_fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_open = bfin_bf54x_fb_open,
+ .fb_release = bfin_bf54x_fb_release,
+ .fb_check_var = bfin_bf54x_fb_check_var,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+ .fb_mmap = bfin_bf54x_fb_mmap,
+ .fb_cursor = bfin_bf54x_fb_cursor,
+ .fb_setcolreg = bfin_bf54x_fb_setcolreg,
+};
+
+#ifndef NO_BL_SUPPORT
+static int bl_get_brightness(struct backlight_device *bd)
+{
+ return 0;
+}
+
+static struct backlight_ops bfin_lq043fb_bl_ops = {
+ .get_brightness = bl_get_brightness,
+};
+
+static struct backlight_device *bl_dev;
+
+static int bfin_lcd_get_power(struct lcd_device *dev)
+{
+ return 0;
+}
+
+static int bfin_lcd_set_power(struct lcd_device *dev, int power)
+{
+ return 0;
+}
+
+static int bfin_lcd_get_contrast(struct lcd_device *dev)
+{
+ return 0;
+}
+
+static int bfin_lcd_set_contrast(struct lcd_device *dev, int contrast)
+{
+
+ return 0;
+}
+
+static int bfin_lcd_check_fb(struct fb_info *fi)
+{
+ if (!fi || (fi == &bfin_bf54x_fb))
+ return 1;
+ return 0;
+}
+
+static struct lcd_ops bfin_lcd_ops = {
+ .get_power = bfin_lcd_get_power,
+ .set_power = bfin_lcd_set_power,
+ .get_contrast = bfin_lcd_get_contrast,
+ .set_contrast = bfin_lcd_set_contrast,
+ .check_fb = bfin_lcd_check_fb,
+};
+
+static struct lcd_device *lcd_dev;
+#endif
+
+static irqreturn_t bfin_bf54x_irq_error(int irq, void *dev_id)
+{
+
+ /*struct bfin_bf54xfb_info *info = (struct bfin_bf54xfb_info *)dev_id;*/
+
+ u16 status = bfin_read_EPPI0_STATUS();
+
+ bfin_write_EPPI0_STATUS(0xFFFF);
+
+ if (status) {
+ bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() & ~EPPI_EN);
+ disable_dma(CH_EPPI0);
+
+ /* start dma */
+ enable_dma(CH_EPPI0);
+ bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() | EPPI_EN);
+ bfin_write_EPPI0_STATUS(0xFFFF);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int __init bfin_bf54x_probe(struct platform_device *pdev)
+{
+ struct bfin_bf54xfb_info *info;
+ struct fb_info *fbinfo;
+ int ret;
+
+ printk(KERN_INFO DRIVER_NAME ": FrameBuffer initializing...\n");
+
+ if (request_dma(CH_EPPI0, "CH_EPPI0") < 0) {
+ printk(KERN_ERR DRIVER_NAME
+ ": couldn't request CH_EPPI0 DMA\n");
+ ret = -EFAULT;
+ goto out1;
+ }
+
+ fbinfo =
+ framebuffer_alloc(sizeof(struct bfin_bf54xfb_info), &pdev->dev);
+ if (!fbinfo) {
+ ret = -ENOMEM;
+ goto out2;
+ }
+
+ info = fbinfo->par;
+ info->fb = fbinfo;
+ info->dev = &pdev->dev;
+
+ platform_set_drvdata(pdev, fbinfo);
+
+ strcpy(fbinfo->fix.id, driver_name);
+
+ info->mach_info = pdev->dev.platform_data;
+
+ if (info->mach_info == NULL) {
+ dev_err(&pdev->dev,
+ "no platform data for lcd, cannot attach\n");
+ ret = -EINVAL;
+ goto out3;
+ }
+
+ fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
+ fbinfo->fix.type_aux = 0;
+ fbinfo->fix.xpanstep = 0;
+ fbinfo->fix.ypanstep = 0;
+ fbinfo->fix.ywrapstep = 0;
+ fbinfo->fix.accel = FB_ACCEL_NONE;
+ fbinfo->fix.visual = FB_VISUAL_TRUECOLOR;
+
+ fbinfo->var.nonstd = 0;
+ fbinfo->var.activate = FB_ACTIVATE_NOW;
+ fbinfo->var.height = info->mach_info->height;
+ fbinfo->var.width = info->mach_info->width;
+ fbinfo->var.accel_flags = 0;
+ fbinfo->var.vmode = FB_VMODE_NONINTERLACED;
+
+ fbinfo->fbops = &bfin_bf54x_fb_ops;
+ fbinfo->flags = FBINFO_FLAG_DEFAULT;
+
+ fbinfo->var.xres = info->mach_info->xres.defval;
+ fbinfo->var.xres_virtual = info->mach_info->xres.defval;
+ fbinfo->var.yres = info->mach_info->yres.defval;
+ fbinfo->var.yres_virtual = info->mach_info->yres.defval;
+ fbinfo->var.bits_per_pixel = info->mach_info->bpp.defval;
+
+ fbinfo->var.upper_margin = 0;
+ fbinfo->var.lower_margin = 0;
+ fbinfo->var.vsync_len = 0;
+
+ fbinfo->var.left_margin = 0;
+ fbinfo->var.right_margin = 0;
+ fbinfo->var.hsync_len = 0;
+
+ fbinfo->var.red.offset = 16;
+ fbinfo->var.green.offset = 8;
+ fbinfo->var.blue.offset = 0;
+ fbinfo->var.transp.offset = 0;
+ fbinfo->var.red.length = 8;
+ fbinfo->var.green.length = 8;
+ fbinfo->var.blue.length = 8;
+ fbinfo->var.transp.length = 0;
+ fbinfo->fix.smem_len = info->mach_info->xres.max *
+ info->mach_info->yres.max * info->mach_info->bpp.max / 8;
+
+ fbinfo->fix.line_length = fbinfo->var.xres_virtual *
+ fbinfo->var.bits_per_pixel / 8;
+
+ info->fb_buffer =
+ dma_alloc_coherent(NULL, fbinfo->fix.smem_len, &info->dma_handle,
+ GFP_KERNEL);
+
+ if (NULL == info->fb_buffer) {
+ printk(KERN_ERR DRIVER_NAME
+ ": couldn't allocate dma buffer.\n");
+ ret = -ENOMEM;
+ goto out3;
+ }
+
+ memset(info->fb_buffer, 0, fbinfo->fix.smem_len);
+
+ fbinfo->screen_base = (void *)info->fb_buffer;
+ fbinfo->fix.smem_start = (int)info->fb_buffer;
+
+ fbinfo->fbops = &bfin_bf54x_fb_ops;
+
+ fbinfo->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL);
+ if (!fbinfo->pseudo_palette) {
+ printk(KERN_ERR DRIVER_NAME
+ "Fail to allocate pseudo_palette\n");
+
+ ret = -ENOMEM;
+ goto out4;
+ }
+
+ memset(fbinfo->pseudo_palette, 0, sizeof(u32) * 16);
+
+ if (fb_alloc_cmap(&fbinfo->cmap, BFIN_LCD_NBR_PALETTE_ENTRIES, 0)
+ < 0) {
+ printk(KERN_ERR DRIVER_NAME
+ "Fail to allocate colormap (%d entries)\n",
+ BFIN_LCD_NBR_PALETTE_ENTRIES);
+ ret = -EFAULT;
+ goto out5;
+ }
+
+ if (request_ports(info)) {
+ printk(KERN_ERR DRIVER_NAME ": couldn't request gpio port.\n");
+ ret = -EFAULT;
+ goto out6;
+ }
+
+ info->irq = platform_get_irq(pdev, 0);
+ if (info->irq < 0) {
+ ret = -EINVAL;
+ goto out7;
+ }
+
+ if (request_irq(info->irq, (void *)bfin_bf54x_irq_error, IRQF_DISABLED,
+ "PPI ERROR", info) < 0) {
+ printk(KERN_ERR DRIVER_NAME
+ ": unable to request PPI ERROR IRQ\n");
+ ret = -EFAULT;
+ goto out7;
+ }
+
+ if (register_framebuffer(fbinfo) < 0) {
+ printk(KERN_ERR DRIVER_NAME
+ ": unable to register framebuffer.\n");
+ ret = -EINVAL;
+ goto out8;
+ }
+#ifndef NO_BL_SUPPORT
+ bl_dev =
+ backlight_device_register("bf54x-bl", NULL, NULL,
+ &bfin_lq043fb_bl_ops);
+ bl_dev->props.max_brightness = 255;
+
+ lcd_dev = lcd_device_register(DRIVER_NAME, NULL, &bfin_lcd_ops);
+ lcd_dev->props.max_contrast = 255, printk(KERN_INFO "Done.\n");
+#endif
+
+ return 0;
+
+out8:
+ free_irq(info->irq, info);
+out7:
+ free_ports(info);
+out6:
+ fb_dealloc_cmap(&fbinfo->cmap);
+out5:
+ kfree(fbinfo->pseudo_palette);
+out4:
+ dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
+ info->dma_handle);
+out3:
+ framebuffer_release(fbinfo);
+out2:
+ free_dma(CH_EPPI0);
+out1:
+ platform_set_drvdata(pdev, NULL);
+
+ return ret;
+}
+
+static int bfin_bf54x_remove(struct platform_device *pdev)
+{
+
+ struct fb_info *fbinfo = platform_get_drvdata(pdev);
+ struct bfin_bf54xfb_info *info = fbinfo->par;
+
+ free_dma(CH_EPPI0);
+ free_irq(info->irq, info);
+
+ if (info->fb_buffer != NULL)
+ dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
+ info->dma_handle);
+
+ kfree(fbinfo->pseudo_palette);
+ fb_dealloc_cmap(&fbinfo->cmap);
+
+#ifndef NO_BL_SUPPORT
+ lcd_device_unregister(lcd_dev);
+ backlight_device_unregister(bl_dev);
+#endif
+
+ unregister_framebuffer(fbinfo);
+
+ free_ports(info);
+
+ printk(KERN_INFO DRIVER_NAME ": Unregister LCD driver.\n");
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int bfin_bf54x_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct fb_info *fbinfo = platform_get_drvdata(pdev);
+ struct bfin_bf54xfb_info *info = fbinfo->par;
+
+ bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() & ~EPPI_EN);
+ disable_dma(CH_EPPI0);
+ bfin_write_EPPI0_STATUS(0xFFFF);
+
+ return 0;
+}
+
+static int bfin_bf54x_resume(struct platform_device *pdev)
+{
+ struct fb_info *fbinfo = platform_get_drvdata(pdev);
+ struct bfin_bf54xfb_info *info = fbinfo->par;
+
+ enable_dma(CH_EPPI0);
+ bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() | EPPI_EN);
+
+ return 0;
+}
+#else
+#define bfin_bf54x_suspend NULL
+#define bfin_bf54x_resume NULL
+#endif
+
+static struct platform_driver bfin_bf54x_driver = {
+ .probe = bfin_bf54x_probe,
+ .remove = bfin_bf54x_remove,
+ .suspend = bfin_bf54x_suspend,
+ .resume = bfin_bf54x_resume,
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __devinit bfin_bf54x_driver_init(void)
+{
+ return platform_driver_register(&bfin_bf54x_driver);
+}
+
+static void __exit bfin_bf54x_driver_cleanup(void)
+{
+ platform_driver_unregister(&bfin_bf54x_driver);
+}
+
+MODULE_DESCRIPTION("Blackfin BF54x TFT LCD Driver");
+MODULE_LICENSE("GPL");
+
+module_init(bfin_bf54x_driver_init);
+module_exit(bfin_bf54x_driver_cleanup);
diff --git a/drivers/video/cfbcopyarea.c b/drivers/video/cfbcopyarea.c
index 032210f45be3..b07e419b12d2 100644
--- a/drivers/video/cfbcopyarea.c
+++ b/drivers/video/cfbcopyarea.c
@@ -45,14 +45,14 @@
static void
bitcpy(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src,
- int src_idx, int bits, unsigned n)
+ int src_idx, int bits, unsigned n, u32 bswapmask)
{
unsigned long first, last;
int const shift = dst_idx-src_idx;
int left, right;
- first = FB_SHIFT_HIGH(~0UL, dst_idx);
- last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits));
+ first = fb_shifted_pixels_mask_long(dst_idx, bswapmask);
+ last = ~fb_shifted_pixels_mask_long((dst_idx+n) % bits, bswapmask);
if (!shift) {
// Same alignment for source and dest
@@ -94,29 +94,34 @@ bitcpy(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src
FB_WRITEL( comp( FB_READL(src), FB_READL(dst), last), dst);
}
} else {
+ /* Different alignment for source and dest */
unsigned long d0, d1;
int m;
- // Different alignment for source and dest
right = shift & (bits - 1);
left = -shift & (bits - 1);
+ bswapmask &= shift;
if (dst_idx+n <= bits) {
// Single destination word
if (last)
first &= last;
+ d0 = FB_READL(src);
+ d0 = fb_rev_pixels_in_long(d0, bswapmask);
if (shift > 0) {
// Single source word
- FB_WRITEL( comp( FB_READL(src) >> right, FB_READL(dst), first), dst);
+ d0 >>= right;
} else if (src_idx+n <= bits) {
// Single source word
- FB_WRITEL( comp(FB_READL(src) << left, FB_READL(dst), first), dst);
+ d0 <<= left;;
} else {
// 2 source words
- d0 = FB_READL(src++);
- d1 = FB_READL(src);
- FB_WRITEL( comp(d0<<left | d1>>right, FB_READL(dst), first), dst);
+ d1 = FB_READL(src + 1);
+ d1 = fb_rev_pixels_in_long(d1, bswapmask);
+ d0 = d0<<left | d1>>right;
}
+ d0 = fb_rev_pixels_in_long(d0, bswapmask);
+ FB_WRITEL(comp(d0, FB_READL(dst), first), dst);
} else {
// Multiple destination words
/** We must always remember the last value read, because in case
@@ -125,25 +130,31 @@ bitcpy(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src
overlap with the current long from SRC. We store this value in
'd0'. */
d0 = FB_READL(src++);
+ d0 = fb_rev_pixels_in_long(d0, bswapmask);
// Leading bits
if (shift > 0) {
// Single source word
- FB_WRITEL( comp(d0 >> right, FB_READL(dst), first), dst);
+ d1 = d0;
+ d0 >>= right;
dst++;
n -= bits - dst_idx;
} else {
// 2 source words
d1 = FB_READL(src++);
- FB_WRITEL( comp(d0<<left | d1>>right, FB_READL(dst), first), dst);
- d0 = d1;
+ d1 = fb_rev_pixels_in_long(d1, bswapmask);
+
+ d0 = d0<<left | d1>>right;
dst++;
n -= bits - dst_idx;
}
+ d0 = fb_rev_pixels_in_long(d0, bswapmask);
+ FB_WRITEL(comp(d0, FB_READL(dst), first), dst);
+ d0 = d1;
// Main chunk
m = n % bits;
n /= bits;
- while (n >= 4) {
+ while ((n >= 4) && !bswapmask) {
d1 = FB_READL(src++);
FB_WRITEL(d0 << left | d1 >> right, dst++);
d0 = d1;
@@ -160,7 +171,10 @@ bitcpy(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src
}
while (n--) {
d1 = FB_READL(src++);
- FB_WRITEL(d0 << left | d1 >> right, dst++);
+ d1 = fb_rev_pixels_in_long(d1, bswapmask);
+ d0 = d0 << left | d1 >> right;
+ d0 = fb_rev_pixels_in_long(d0, bswapmask);
+ FB_WRITEL(d0, dst++);
d0 = d1;
}
@@ -168,12 +182,16 @@ bitcpy(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src
if (last) {
if (m <= right) {
// Single source word
- FB_WRITEL( comp(d0 << left, FB_READL(dst), last), dst);
+ d0 <<= left;
} else {
// 2 source words
d1 = FB_READL(src);
- FB_WRITEL( comp(d0<<left | d1>>right, FB_READL(dst), last), dst);
+ d1 = fb_rev_pixels_in_long(d1,
+ bswapmask);
+ d0 = d0<<left | d1>>right;
}
+ d0 = fb_rev_pixels_in_long(d0, bswapmask);
+ FB_WRITEL(comp(d0, FB_READL(dst), last), dst);
}
}
}
@@ -185,7 +203,7 @@ bitcpy(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src
static void
bitcpy_rev(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src,
- int src_idx, int bits, unsigned n)
+ int src_idx, int bits, unsigned n, u32 bswapmask)
{
unsigned long first, last;
int shift;
@@ -203,8 +221,8 @@ bitcpy_rev(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem
shift = dst_idx-src_idx;
- first = FB_SHIFT_LOW(~0UL, bits - 1 - dst_idx);
- last = ~(FB_SHIFT_LOW(~0UL, bits - 1 - ((dst_idx-n) % bits)));
+ first = fb_shifted_pixels_mask_long(bits - 1 - dst_idx, bswapmask);
+ last = ~fb_shifted_pixels_mask_long(bits - 1 - ((dst_idx-n) % bits), bswapmask);
if (!shift) {
// Same alignment for source and dest
@@ -247,24 +265,32 @@ bitcpy_rev(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem
}
} else {
// Different alignment for source and dest
+ unsigned long d0, d1;
+ int m;
int const left = -shift & (bits-1);
int const right = shift & (bits-1);
+ bswapmask &= shift;
if ((unsigned long)dst_idx+1 >= n) {
// Single destination word
if (last)
first &= last;
+ d0 = FB_READL(src);
if (shift < 0) {
// Single source word
- FB_WRITEL( comp( FB_READL(src)<<left, FB_READL(dst), first), dst);
+ d0 <<= left;
} else if (1+(unsigned long)src_idx >= n) {
// Single source word
- FB_WRITEL( comp( FB_READL(src)>>right, FB_READL(dst), first), dst);
+ d0 >>= right;
} else {
// 2 source words
- FB_WRITEL( comp( (FB_READL(src)>>right | FB_READL(src-1)<<left), FB_READL(dst), first), dst);
+ d1 = FB_READL(src - 1);
+ d1 = fb_rev_pixels_in_long(d1, bswapmask);
+ d0 = d0>>right | d1<<left;
}
+ d0 = fb_rev_pixels_in_long(d0, bswapmask);
+ FB_WRITEL(comp(d0, FB_READL(dst), first), dst);
} else {
// Multiple destination words
/** We must always remember the last value read, because in case
@@ -272,27 +298,30 @@ bitcpy_rev(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem
1bpp), we always collect one full long for DST and that might
overlap with the current long from SRC. We store this value in
'd0'. */
- unsigned long d0, d1;
- int m;
d0 = FB_READL(src--);
+ d0 = fb_rev_pixels_in_long(d0, bswapmask);
// Leading bits
if (shift < 0) {
// Single source word
- FB_WRITEL( comp( (d0 << left), FB_READL(dst), first), dst);
+ d1 = d0;
+ d0 <<= left;
} else {
// 2 source words
d1 = FB_READL(src--);
- FB_WRITEL( comp( (d0>>right | d1<<left), FB_READL(dst), first), dst);
- d0 = d1;
+ d1 = fb_rev_pixels_in_long(d1, bswapmask);
+ d0 = d0>>right | d1<<left;
}
+ d0 = fb_rev_pixels_in_long(d0, bswapmask);
+ FB_WRITEL(comp(d0, FB_READL(dst), first), dst);
+ d0 = d1;
dst--;
n -= dst_idx+1;
// Main chunk
m = n % bits;
n /= bits;
- while (n >= 4) {
+ while ((n >= 4) && !bswapmask) {
d1 = FB_READL(src--);
FB_WRITEL(d0 >> right | d1 << left, dst--);
d0 = d1;
@@ -309,7 +338,10 @@ bitcpy_rev(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem
}
while (n--) {
d1 = FB_READL(src--);
- FB_WRITEL(d0 >> right | d1 << left, dst--);
+ d1 = fb_rev_pixels_in_long(d1, bswapmask);
+ d0 = d0 >> right | d1 << left;
+ d0 = fb_rev_pixels_in_long(d0, bswapmask);
+ FB_WRITEL(d0, dst--);
d0 = d1;
}
@@ -317,12 +349,16 @@ bitcpy_rev(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem
if (last) {
if (m <= left) {
// Single source word
- FB_WRITEL( comp(d0 >> right, FB_READL(dst), last), dst);
+ d0 >>= right;
} else {
// 2 source words
d1 = FB_READL(src);
- FB_WRITEL( comp(d0>>right | d1<<left, FB_READL(dst), last), dst);
+ d1 = fb_rev_pixels_in_long(d1,
+ bswapmask);
+ d0 = d0>>right | d1<<left;
}
+ d0 = fb_rev_pixels_in_long(d0, bswapmask);
+ FB_WRITEL(comp(d0, FB_READL(dst), last), dst);
}
}
}
@@ -336,6 +372,7 @@ void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
unsigned long __iomem *dst = NULL, *src = NULL;
int bits = BITS_PER_LONG, bytes = bits >> 3;
int dst_idx = 0, src_idx = 0, rev_copy = 0;
+ u32 bswapmask = fb_compute_bswapmask(p);
if (p->state != FBINFO_STATE_RUNNING)
return;
@@ -368,7 +405,7 @@ void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
src += src_idx >> (ffs(bits) - 1);
src_idx &= (bytes - 1);
bitcpy_rev(dst, dst_idx, src, src_idx, bits,
- width*p->var.bits_per_pixel);
+ width*p->var.bits_per_pixel, bswapmask);
}
} else {
while (height--) {
@@ -377,7 +414,7 @@ void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
src += src_idx >> (ffs(bits) - 1);
src_idx &= (bytes - 1);
bitcpy(dst, dst_idx, src, src_idx, bits,
- width*p->var.bits_per_pixel);
+ width*p->var.bits_per_pixel, bswapmask);
dst_idx += bits_per_line;
src_idx += bits_per_line;
}
diff --git a/drivers/video/cfbfillrect.c b/drivers/video/cfbfillrect.c
index 71623b4f8ca2..23d70a12e4da 100644
--- a/drivers/video/cfbfillrect.c
+++ b/drivers/video/cfbfillrect.c
@@ -36,15 +36,16 @@
*/
static void
-bitfill_aligned(unsigned long __iomem *dst, int dst_idx, unsigned long pat, unsigned n, int bits)
+bitfill_aligned(unsigned long __iomem *dst, int dst_idx, unsigned long pat,
+ unsigned n, int bits, u32 bswapmask)
{
unsigned long first, last;
if (!n)
return;
- first = FB_SHIFT_HIGH(~0UL, dst_idx);
- last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits));
+ first = fb_shifted_pixels_mask_long(dst_idx, bswapmask);
+ last = ~fb_shifted_pixels_mask_long((dst_idx+n) % bits, bswapmask);
if (dst_idx+n <= bits) {
// Single word
@@ -146,7 +147,8 @@ bitfill_unaligned(unsigned long __iomem *dst, int dst_idx, unsigned long pat,
* Aligned pattern invert using 32/64-bit memory accesses
*/
static void
-bitfill_aligned_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat, unsigned n, int bits)
+bitfill_aligned_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat,
+ unsigned n, int bits, u32 bswapmask)
{
unsigned long val = pat, dat;
unsigned long first, last;
@@ -154,8 +156,8 @@ bitfill_aligned_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat,
if (!n)
return;
- first = FB_SHIFT_HIGH(~0UL, dst_idx);
- last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits));
+ first = fb_shifted_pixels_mask_long(dst_idx, bswapmask);
+ last = ~fb_shifted_pixels_mask_long((dst_idx+n) % bits, bswapmask);
if (dst_idx+n <= bits) {
// Single word
@@ -303,8 +305,10 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
if (p->fbops->fb_sync)
p->fbops->fb_sync(p);
if (!left) {
+ u32 bswapmask = fb_compute_bswapmask(p);
void (*fill_op32)(unsigned long __iomem *dst, int dst_idx,
- unsigned long pat, unsigned n, int bits) = NULL;
+ unsigned long pat, unsigned n, int bits,
+ u32 bswapmask) = NULL;
switch (rect->rop) {
case ROP_XOR:
@@ -321,7 +325,7 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
while (height--) {
dst += dst_idx >> (ffs(bits) - 1);
dst_idx &= (bits - 1);
- fill_op32(dst, dst_idx, pat, width*bpp, bits);
+ fill_op32(dst, dst_idx, pat, width*bpp, bits, bswapmask);
dst_idx += p->fix.line_length*8;
}
} else {
diff --git a/drivers/video/cfbimgblt.c b/drivers/video/cfbimgblt.c
index 261004473c8e..f598907b42ad 100644
--- a/drivers/video/cfbimgblt.c
+++ b/drivers/video/cfbimgblt.c
@@ -33,6 +33,7 @@
#include <linux/string.h>
#include <linux/fb.h>
#include <asm/types.h>
+#include "fb_draw.h"
#define DEBUG
@@ -87,6 +88,7 @@ static inline void color_imageblit(const struct fb_image *image,
u32 null_bits = 32 - bpp;
u32 *palette = (u32 *) p->pseudo_palette;
const u8 *src = image->data;
+ u32 bswapmask = fb_compute_bswapmask(p);
dst2 = (u32 __iomem *) dst1;
for (i = image->height; i--; ) {
@@ -96,7 +98,7 @@ static inline void color_imageblit(const struct fb_image *image,
val = 0;
if (start_index) {
- u32 start_mask = ~(FB_SHIFT_HIGH(~(u32)0, start_index));
+ u32 start_mask = ~fb_shifted_pixels_mask_u32(start_index, bswapmask);
val = FB_READL(dst) & start_mask;
shift = start_index;
}
@@ -107,7 +109,7 @@ static inline void color_imageblit(const struct fb_image *image,
else
color = *src;
color <<= FB_LEFT_POS(bpp);
- val |= FB_SHIFT_HIGH(color, shift);
+ val |= FB_SHIFT_HIGH(color, shift ^ bswapmask);
if (shift >= null_bits) {
FB_WRITEL(val, dst++);
@@ -119,7 +121,7 @@ static inline void color_imageblit(const struct fb_image *image,
src++;
}
if (shift) {
- u32 end_mask = FB_SHIFT_HIGH(~(u32)0, shift);
+ u32 end_mask = fb_shifted_pixels_mask_u32(shift, bswapmask);
FB_WRITEL((FB_READL(dst) & end_mask) | val, dst);
}
@@ -147,7 +149,8 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info *
u32 spitch = (image->width+7)/8;
const u8 *src = image->data, *s;
u32 i, j, l;
-
+ u32 bswapmask = fb_compute_bswapmask(p);
+
dst2 = (u32 __iomem *) dst1;
fgcolor <<= FB_LEFT_POS(bpp);
bgcolor <<= FB_LEFT_POS(bpp);
@@ -161,7 +164,7 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info *
/* write leading bits */
if (start_index) {
- u32 start_mask = ~(FB_SHIFT_HIGH(~(u32)0,start_index));
+ u32 start_mask = ~fb_shifted_pixels_mask_u32(start_index, bswapmask);
val = FB_READL(dst) & start_mask;
shift = start_index;
}
@@ -169,7 +172,7 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info *
while (j--) {
l--;
color = (*s & (1 << l)) ? fgcolor : bgcolor;
- val |= FB_SHIFT_HIGH(color, shift);
+ val |= FB_SHIFT_HIGH(color, shift ^ bswapmask);
/* Did the bitshift spill bits to the next long? */
if (shift >= null_bits) {
@@ -184,7 +187,7 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info *
/* write trailing bits */
if (shift) {
- u32 end_mask = FB_SHIFT_HIGH(~(u32)0, shift);
+ u32 end_mask = fb_shifted_pixels_mask_u32(shift, bswapmask);
FB_WRITEL((FB_READL(dst) & end_mask) | val, dst);
}
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index 8269d704ab2a..f7e2d5add831 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -45,7 +45,6 @@
#include <linux/delay.h>
#include <linux/fb.h>
#include <linux/init.h>
-#include <linux/selection.h>
#include <asm/pgtable.h>
#ifdef CONFIG_ZORRO
@@ -59,14 +58,13 @@
#endif
#ifdef CONFIG_PPC_PREP
#include <asm/machdep.h>
-#define isPReP (machine_is(prep))
+#define isPReP machine_is(prep)
#else
#define isPReP 0
#endif
-#include "video/vga.h"
-#include "video/cirrus.h"
-
+#include <video/vga.h>
+#include <video/cirrus.h>
/*****************************************************************
*
@@ -82,7 +80,8 @@
/* debug output */
#ifdef CIRRUSFB_DEBUG
-#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
+#define DPRINTK(fmt, args...) \
+ printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
#else
#define DPRINTK(fmt, args...)
#endif
@@ -90,19 +89,15 @@
/* debugging assertions */
#ifndef CIRRUSFB_NDEBUG
#define assert(expr) \
- if(!(expr)) { \
- printk( "Assertion failed! %s,%s,%s,line=%d\n",\
- #expr,__FILE__,__FUNCTION__,__LINE__); \
- }
+ if (!(expr)) { \
+ printk("Assertion failed! %s,%s,%s,line=%d\n", \
+ #expr, __FILE__, __FUNCTION__, __LINE__); \
+ }
#else
#define assert(expr)
#endif
-#define MB_ (1024*1024)
-#define KB_ (1024)
-
-#define MAX_NUM_BOARDS 7
-
+#define MB_ (1024 * 1024)
/*****************************************************************
*
@@ -111,7 +106,7 @@
*/
/* board types */
-typedef enum {
+enum cirrus_board {
BT_NONE = 0,
BT_SD64,
BT_PICCOLO,
@@ -121,13 +116,12 @@ typedef enum {
BT_ALPINE, /* GD543x/4x */
BT_GD5480,
BT_LAGUNA, /* GD546x */
-} cirrusfb_board_t;
-
+};
/*
* per-board-type information, used for enumerating and abstracting
* chip-specific information
- * NOTE: MUST be in the same order as cirrusfb_board_t in order to
+ * NOTE: MUST be in the same order as enum cirrus_board in order to
* use direct indexing on this array
* NOTE: '__initdata' cannot be used as some of this info
* is required at runtime. Maybe separate into an init-only and
@@ -139,7 +133,8 @@ static const struct cirrusfb_board_info_rec {
/* for 1/4bpp, 8bpp 15/16bpp, 24bpp, 32bpp - numbers from xorg code */
bool init_sr07 : 1; /* init SR07 during init_vgachip() */
bool init_sr1f : 1; /* write SR1F during init_vgachip() */
- bool scrn_start_bit19 : 1; /* construct bit 19 of screen start address */
+ /* construct bit 19 of screen start address */
+ bool scrn_start_bit19 : 1;
/* initial SR07 value, then for each mode */
unsigned char sr07;
@@ -261,30 +256,28 @@ static const struct cirrusfb_board_info_rec {
}
};
-
#ifdef CONFIG_PCI
#define CHIP(id, btype) \
{ PCI_VENDOR_ID_CIRRUS, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (btype) }
static struct pci_device_id cirrusfb_pci_table[] = {
- CHIP( PCI_DEVICE_ID_CIRRUS_5436, BT_ALPINE ),
- CHIP( PCI_DEVICE_ID_CIRRUS_5434_8, BT_ALPINE ),
- CHIP( PCI_DEVICE_ID_CIRRUS_5434_4, BT_ALPINE ),
- CHIP( PCI_DEVICE_ID_CIRRUS_5430, BT_ALPINE ), /* GD-5440 is same id */
- CHIP( PCI_DEVICE_ID_CIRRUS_7543, BT_ALPINE ),
- CHIP( PCI_DEVICE_ID_CIRRUS_7548, BT_ALPINE ),
- CHIP( PCI_DEVICE_ID_CIRRUS_5480, BT_GD5480 ), /* MacPicasso likely */
- CHIP( PCI_DEVICE_ID_CIRRUS_5446, BT_PICASSO4 ), /* Picasso 4 is 5446 */
- CHIP( PCI_DEVICE_ID_CIRRUS_5462, BT_LAGUNA ), /* CL Laguna */
- CHIP( PCI_DEVICE_ID_CIRRUS_5464, BT_LAGUNA ), /* CL Laguna 3D */
- CHIP( PCI_DEVICE_ID_CIRRUS_5465, BT_LAGUNA ), /* CL Laguna 3DA*/
+ CHIP(PCI_DEVICE_ID_CIRRUS_5436, BT_ALPINE),
+ CHIP(PCI_DEVICE_ID_CIRRUS_5434_8, BT_ALPINE),
+ CHIP(PCI_DEVICE_ID_CIRRUS_5434_4, BT_ALPINE),
+ CHIP(PCI_DEVICE_ID_CIRRUS_5430, BT_ALPINE), /* GD-5440 is same id */
+ CHIP(PCI_DEVICE_ID_CIRRUS_7543, BT_ALPINE),
+ CHIP(PCI_DEVICE_ID_CIRRUS_7548, BT_ALPINE),
+ CHIP(PCI_DEVICE_ID_CIRRUS_5480, BT_GD5480), /* MacPicasso likely */
+ CHIP(PCI_DEVICE_ID_CIRRUS_5446, BT_PICASSO4), /* Picasso 4 is 5446 */
+ CHIP(PCI_DEVICE_ID_CIRRUS_5462, BT_LAGUNA), /* CL Laguna */
+ CHIP(PCI_DEVICE_ID_CIRRUS_5464, BT_LAGUNA), /* CL Laguna 3D */
+ CHIP(PCI_DEVICE_ID_CIRRUS_5465, BT_LAGUNA), /* CL Laguna 3DA*/
{ 0, }
};
MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table);
#undef CHIP
#endif /* CONFIG_PCI */
-
#ifdef CONFIG_ZORRO
static const struct zorro_device_id cirrusfb_zorro_table[] = {
{
@@ -294,7 +287,7 @@ static const struct zorro_device_id cirrusfb_zorro_table[] = {
.id = ZORRO_PROD_HELFRICH_PICCOLO_RAM,
.driver_data = BT_PICCOLO,
}, {
- .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
+ .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
.driver_data = BT_PICASSO,
}, {
.id = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
@@ -333,12 +326,7 @@ static const struct {
};
#endif /* CONFIG_ZORRO */
-
struct cirrusfb_regs {
- __u32 line_length; /* in BYTES! */
- __u32 visual;
- __u32 type;
-
long freq;
long nom;
long den;
@@ -364,37 +352,23 @@ struct cirrusfb_regs {
long VertBlankEnd;
};
-
-
#ifdef CIRRUSFB_DEBUG
-typedef enum {
- CRT,
- SEQ
-} cirrusfb_dbg_reg_class_t;
-#endif /* CIRRUSFB_DEBUG */
-
-
-
+enum cirrusfb_dbg_reg_class {
+ CRT,
+ SEQ
+};
+#endif /* CIRRUSFB_DEBUG */
/* info about board */
struct cirrusfb_info {
- struct fb_info *info;
-
- u8 __iomem *fbmem;
u8 __iomem *regbase;
- u8 __iomem *mem;
- unsigned long size;
- cirrusfb_board_t btype;
+ enum cirrus_board btype;
unsigned char SFR; /* Shadow of special function register */
- unsigned long fbmem_phys;
- unsigned long fbregs_phys;
-
struct cirrusfb_regs currentmode;
int blank_mode;
u32 pseudo_palette[16];
- struct { u8 red, green, blue, pad; } palette[256];
#ifdef CONFIG_ZORRO
struct zorro_dev *zdev;
@@ -402,12 +376,11 @@ struct cirrusfb_info {
#ifdef CONFIG_PCI
struct pci_dev *pdev;
#endif
- void (*unmap)(struct cirrusfb_info *cinfo);
+ void (*unmap)(struct fb_info *info);
};
-
static unsigned cirrusfb_def_mode = 1;
-static int noaccel = 0;
+static int noaccel;
/*
* Predefined Video Modes
@@ -441,7 +414,7 @@ static const struct {
.lower_margin = 8,
.hsync_len = 96,
.vsync_len = 4,
- .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
.vmode = FB_VMODE_NONINTERLACED
}
}, {
@@ -502,27 +475,29 @@ static const struct {
/****************************************************************************/
/**** BEGIN PROTOTYPES ******************************************************/
-
/*--- Interface used by the world ------------------------------------------*/
-static int cirrusfb_init (void);
+static int cirrusfb_init(void);
#ifndef MODULE
-static int cirrusfb_setup (char *options);
+static int cirrusfb_setup(char *options);
#endif
-static int cirrusfb_open (struct fb_info *info, int user);
-static int cirrusfb_release (struct fb_info *info, int user);
-static int cirrusfb_setcolreg (unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp,
- struct fb_info *info);
-static int cirrusfb_check_var (struct fb_var_screeninfo *var,
- struct fb_info *info);
-static int cirrusfb_set_par (struct fb_info *info);
-static int cirrusfb_pan_display (struct fb_var_screeninfo *var,
- struct fb_info *info);
-static int cirrusfb_blank (int blank_mode, struct fb_info *info);
-static void cirrusfb_fillrect (struct fb_info *info, const struct fb_fillrect *region);
-static void cirrusfb_copyarea(struct fb_info *info, const struct fb_copyarea *area);
-static void cirrusfb_imageblit(struct fb_info *info, const struct fb_image *image);
+static int cirrusfb_open(struct fb_info *info, int user);
+static int cirrusfb_release(struct fb_info *info, int user);
+static int cirrusfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *info);
+static int cirrusfb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info);
+static int cirrusfb_set_par(struct fb_info *info);
+static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info);
+static int cirrusfb_blank(int blank_mode, struct fb_info *info);
+static void cirrusfb_fillrect(struct fb_info *info,
+ const struct fb_fillrect *region);
+static void cirrusfb_copyarea(struct fb_info *info,
+ const struct fb_copyarea *area);
+static void cirrusfb_imageblit(struct fb_info *info,
+ const struct fb_image *image);
/* function table of the above functions */
static struct fb_ops cirrusfb_ops = {
@@ -540,68 +515,68 @@ static struct fb_ops cirrusfb_ops = {
};
/*--- Hardware Specific Routines -------------------------------------------*/
-static int cirrusfb_decode_var (const struct fb_var_screeninfo *var,
+static int cirrusfb_decode_var(const struct fb_var_screeninfo *var,
struct cirrusfb_regs *regs,
- const struct fb_info *info);
+ struct fb_info *info);
/*--- Internal routines ----------------------------------------------------*/
-static void init_vgachip (struct cirrusfb_info *cinfo);
-static void switch_monitor (struct cirrusfb_info *cinfo, int on);
-static void WGen (const struct cirrusfb_info *cinfo,
- int regnum, unsigned char val);
-static unsigned char RGen (const struct cirrusfb_info *cinfo, int regnum);
-static void AttrOn (const struct cirrusfb_info *cinfo);
-static void WHDR (const struct cirrusfb_info *cinfo, unsigned char val);
-static void WSFR (struct cirrusfb_info *cinfo, unsigned char val);
-static void WSFR2 (struct cirrusfb_info *cinfo, unsigned char val);
-static void WClut (struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char red,
- unsigned char green,
- unsigned char blue);
+static void init_vgachip(struct fb_info *info);
+static void switch_monitor(struct cirrusfb_info *cinfo, int on);
+static void WGen(const struct cirrusfb_info *cinfo,
+ int regnum, unsigned char val);
+static unsigned char RGen(const struct cirrusfb_info *cinfo, int regnum);
+static void AttrOn(const struct cirrusfb_info *cinfo);
+static void WHDR(const struct cirrusfb_info *cinfo, unsigned char val);
+static void WSFR(struct cirrusfb_info *cinfo, unsigned char val);
+static void WSFR2(struct cirrusfb_info *cinfo, unsigned char val);
+static void WClut(struct cirrusfb_info *cinfo, unsigned char regnum,
+ unsigned char red, unsigned char green, unsigned char blue);
#if 0
-static void RClut (struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char *red,
- unsigned char *green,
- unsigned char *blue);
+static void RClut(struct cirrusfb_info *cinfo, unsigned char regnum,
+ unsigned char *red, unsigned char *green,
+ unsigned char *blue);
#endif
-static void cirrusfb_WaitBLT (u8 __iomem *regbase);
-static void cirrusfb_BitBLT (u8 __iomem *regbase, int bits_per_pixel,
- u_short curx, u_short cury,
- u_short destx, u_short desty,
- u_short width, u_short height,
- u_short line_length);
-static void cirrusfb_RectFill (u8 __iomem *regbase, int bits_per_pixel,
- u_short x, u_short y,
- u_short width, u_short height,
- u_char color, u_short line_length);
-
-static void bestclock (long freq, long *best,
- long *nom, long *den,
- long *div, long maxfreq);
+static void cirrusfb_WaitBLT(u8 __iomem *regbase);
+static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel,
+ u_short curx, u_short cury,
+ u_short destx, u_short desty,
+ u_short width, u_short height,
+ u_short line_length);
+static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
+ u_short x, u_short y,
+ u_short width, u_short height,
+ u_char color, u_short line_length);
+
+static void bestclock(long freq, long *best,
+ long *nom, long *den,
+ long *div, long maxfreq);
#ifdef CIRRUSFB_DEBUG
-static void cirrusfb_dump (void);
-static void cirrusfb_dbg_reg_dump (caddr_t regbase);
-static void cirrusfb_dbg_print_regs (caddr_t regbase, cirrusfb_dbg_reg_class_t reg_class,...);
-static void cirrusfb_dbg_print_byte (const char *name, unsigned char val);
+static void cirrusfb_dump(void);
+static void cirrusfb_dbg_reg_dump(caddr_t regbase);
+static void cirrusfb_dbg_print_regs(caddr_t regbase,
+ enum cirrusfb_dbg_reg_class reg_class, ...);
+static void cirrusfb_dbg_print_byte(const char *name, unsigned char val);
#endif /* CIRRUSFB_DEBUG */
/*** END PROTOTYPES ********************************************************/
/*****************************************************************************/
/*** BEGIN Interface Used by the World ***************************************/
-static int opencount = 0;
+static int opencount;
/*--- Open /dev/fbx ---------------------------------------------------------*/
-static int cirrusfb_open (struct fb_info *info, int user)
+static int cirrusfb_open(struct fb_info *info, int user)
{
if (opencount++ == 0)
- switch_monitor (info->par, 1);
+ switch_monitor(info->par, 1);
return 0;
}
/*--- Close /dev/fbx --------------------------------------------------------*/
-static int cirrusfb_release (struct fb_info *info, int user)
+static int cirrusfb_release(struct fb_info *info, int user)
{
if (--opencount == 0)
- switch_monitor (info->par, 0);
+ switch_monitor(info->par, 0);
return 0;
}
@@ -610,11 +585,11 @@ static int cirrusfb_release (struct fb_info *info, int user)
/**** BEGIN Hardware specific Routines **************************************/
/* Get a good MCLK value */
-static long cirrusfb_get_mclk (long freq, int bpp, long *div)
+static long cirrusfb_get_mclk(long freq, int bpp, long *div)
{
long mclk;
- assert (div != NULL);
+ assert(div != NULL);
/* Calculate MCLK, in case VCLK is high enough to require > 50MHz.
* Assume a 64-bit data path for now. The formula is:
@@ -624,23 +599,23 @@ static long cirrusfb_get_mclk (long freq, int bpp, long *div)
mclk = (mclk * 12) / 10;
if (mclk < 50000)
mclk = 50000;
- DPRINTK ("Use MCLK of %ld kHz\n", mclk);
+ DPRINTK("Use MCLK of %ld kHz\n", mclk);
/* Calculate value for SR1F. Multiply by 2 so we can round up. */
mclk = ((mclk * 16) / 14318);
mclk = (mclk + 1) / 2;
- DPRINTK ("Set SR1F[5:0] to 0x%lx\n", mclk);
+ DPRINTK("Set SR1F[5:0] to 0x%lx\n", mclk);
/* Determine if we should use MCLK instead of VCLK, and if so, what we
* should divide it by to get VCLK */
switch (freq) {
case 24751 ... 25249:
*div = 2;
- DPRINTK ("Using VCLK = MCLK/2\n");
+ DPRINTK("Using VCLK = MCLK/2\n");
break;
case 49501 ... 50499:
*div = 1;
- DPRINTK ("Using VCLK = MCLK\n");
+ DPRINTK("Using VCLK = MCLK\n");
break;
default:
*div = 0;
@@ -653,7 +628,6 @@ static long cirrusfb_get_mclk (long freq, int bpp, long *div)
static int cirrusfb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
- struct cirrusfb_info *cinfo = info->par;
int nom, den; /* translyting from pixels->bytes */
int yres, i;
static struct { int xres, yres; } modes[] =
@@ -665,63 +639,55 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var,
{ -1, -1 } };
switch (var->bits_per_pixel) {
- case 0 ... 1:
- var->bits_per_pixel = 1;
+ case 1:
nom = 4;
den = 8;
break; /* 8 pixel per byte, only 1/4th of mem usable */
- case 2 ... 8:
- var->bits_per_pixel = 8;
- nom = 1;
+ case 8:
+ case 16:
+ case 24:
+ case 32:
+ nom = var->bits_per_pixel / 8;
den = 1;
break; /* 1 pixel == 1 byte */
- case 9 ... 16:
- var->bits_per_pixel = 16;
- nom = 2;
- den = 1;
- break; /* 2 bytes per pixel */
- case 17 ... 24:
- var->bits_per_pixel = 24;
- nom = 3;
- den = 1;
- break; /* 3 bytes per pixel */
- case 25 ... 32:
- var->bits_per_pixel = 32;
- nom = 4;
- den = 1;
- break; /* 4 bytes per pixel */
default:
- printk ("cirrusfb: mode %dx%dx%d rejected...color depth not supported.\n",
+ printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected..."
+ "color depth not supported.\n",
var->xres, var->yres, var->bits_per_pixel);
- DPRINTK ("EXIT - EINVAL error\n");
+ DPRINTK("EXIT - EINVAL error\n");
return -EINVAL;
}
- if (var->xres * nom / den * var->yres > cinfo->size) {
- printk ("cirrusfb: mode %dx%dx%d rejected...resolution too high to fit into video memory!\n",
+ if (var->xres * nom / den * var->yres > info->screen_size) {
+ printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected..."
+ "resolution too high to fit into video memory!\n",
var->xres, var->yres, var->bits_per_pixel);
- DPRINTK ("EXIT - EINVAL error\n");
+ DPRINTK("EXIT - EINVAL error\n");
return -EINVAL;
}
/* use highest possible virtual resolution */
if (var->xres_virtual == -1 &&
var->yres_virtual == -1) {
- printk ("cirrusfb: using maximum available virtual resolution\n");
+ printk(KERN_INFO
+ "cirrusfb: using maximum available virtual resolution\n");
for (i = 0; modes[i].xres != -1; i++) {
- if (modes[i].xres * nom / den * modes[i].yres < cinfo->size / 2)
+ int size = modes[i].xres * nom / den * modes[i].yres;
+ if (size < info->screen_size / 2)
break;
}
if (modes[i].xres == -1) {
- printk ("cirrusfb: could not find a virtual resolution that fits into video memory!!\n");
- DPRINTK ("EXIT - EINVAL error\n");
+ printk(KERN_ERR "cirrusfb: could not find a virtual "
+ "resolution that fits into video memory!!\n");
+ DPRINTK("EXIT - EINVAL error\n");
return -EINVAL;
}
var->xres_virtual = modes[i].xres;
var->yres_virtual = modes[i].yres;
- printk ("cirrusfb: virtual resolution set to maximum of %dx%d\n",
- var->xres_virtual, var->yres_virtual);
+ printk(KERN_INFO "cirrusfb: virtual resolution set to "
+ "maximum of %dx%d\n", var->xres_virtual,
+ var->yres_virtual);
}
if (var->xres_virtual < var->xres)
@@ -744,23 +710,19 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var,
case 1:
var->red.offset = 0;
var->red.length = 1;
- var->green.offset = 0;
- var->green.length = 1;
- var->blue.offset = 0;
- var->blue.length = 1;
+ var->green = var->red;
+ var->blue = var->red;
break;
case 8:
var->red.offset = 0;
var->red.length = 6;
- var->green.offset = 0;
- var->green.length = 6;
- var->blue.offset = 0;
- var->blue.length = 6;
+ var->green = var->red;
+ var->blue = var->red;
break;
case 16:
- if(isPReP) {
+ if (isPReP) {
var->red.offset = 2;
var->green.offset = -3;
var->blue.offset = 8;
@@ -775,22 +737,8 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var,
break;
case 24:
- if(isPReP) {
- var->red.offset = 8;
- var->green.offset = 16;
- var->blue.offset = 24;
- } else {
- var->red.offset = 16;
- var->green.offset = 8;
- var->blue.offset = 0;
- }
- var->red.length = 8;
- var->green.length = 8;
- var->blue.length = 8;
- break;
-
case 32:
- if(isPReP) {
+ if (isPReP) {
var->red.offset = 8;
var->green.offset = 16;
var->blue.offset = 24;
@@ -825,54 +773,42 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var,
yres = (yres + 1) / 2;
if (yres >= 1280) {
- printk (KERN_WARNING "cirrusfb: ERROR: VerticalTotal >= 1280; special treatment required! (TODO)\n");
- DPRINTK ("EXIT - EINVAL error\n");
+ printk(KERN_ERR "cirrusfb: ERROR: VerticalTotal >= 1280; "
+ "special treatment required! (TODO)\n");
+ DPRINTK("EXIT - EINVAL error\n");
return -EINVAL;
}
return 0;
}
-static int cirrusfb_decode_var (const struct fb_var_screeninfo *var,
+static int cirrusfb_decode_var(const struct fb_var_screeninfo *var,
struct cirrusfb_regs *regs,
- const struct fb_info *info)
+ struct fb_info *info)
{
long freq;
long maxclock;
- int maxclockidx = 0;
+ int maxclockidx = var->bits_per_pixel >> 3;
struct cirrusfb_info *cinfo = info->par;
int xres, hfront, hsync, hback;
int yres, vfront, vsync, vback;
- switch(var->bits_per_pixel) {
+ switch (var->bits_per_pixel) {
case 1:
- regs->line_length = var->xres_virtual / 8;
- regs->visual = FB_VISUAL_MONO10;
- maxclockidx = 0;
+ info->fix.line_length = var->xres_virtual / 8;
+ info->fix.visual = FB_VISUAL_MONO10;
break;
case 8:
- regs->line_length = var->xres_virtual;
- regs->visual = FB_VISUAL_PSEUDOCOLOR;
- maxclockidx = 1;
+ info->fix.line_length = var->xres_virtual;
+ info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
break;
case 16:
- regs->line_length = var->xres_virtual * 2;
- regs->visual = FB_VISUAL_DIRECTCOLOR;
- maxclockidx = 2;
- break;
-
case 24:
- regs->line_length = var->xres_virtual * 3;
- regs->visual = FB_VISUAL_DIRECTCOLOR;
- maxclockidx = 3;
- break;
-
case 32:
- regs->line_length = var->xres_virtual * 4;
- regs->visual = FB_VISUAL_DIRECTCOLOR;
- maxclockidx = 4;
+ info->fix.line_length = var->xres_virtual * maxclockidx;
+ info->fix.visual = FB_VISUAL_DIRECTCOLOR;
break;
default:
@@ -882,12 +818,12 @@ static int cirrusfb_decode_var (const struct fb_var_screeninfo *var,
break;
}
- regs->type = FB_TYPE_PACKED_PIXELS;
+ info->fix.type = FB_TYPE_PACKED_PIXELS;
/* convert from ps to kHz */
- freq = 1000000000 / var->pixclock;
+ freq = PICOS2KHZ(var->pixclock);
- DPRINTK ("desired pixclock: %ld kHz\n", freq);
+ DPRINTK("desired pixclock: %ld kHz\n", freq);
maxclock = cirrusfb_board_info[cinfo->btype].maxclock[maxclockidx];
regs->multiplexing = 0;
@@ -902,8 +838,9 @@ static int cirrusfb_decode_var (const struct fb_var_screeninfo *var,
break;
default:
- printk (KERN_WARNING "cirrusfb: ERROR: Frequency greater than maxclock (%ld kHz)\n", maxclock);
- DPRINTK ("EXIT - return -EINVAL\n");
+ printk(KERN_ERR "cirrusfb: Frequency greater "
+ "than maxclock (%ld kHz)\n", maxclock);
+ DPRINTK("EXIT - return -EINVAL\n");
return -EINVAL;
}
}
@@ -914,14 +851,16 @@ static int cirrusfb_decode_var (const struct fb_var_screeninfo *var,
case 16:
case 32:
if (regs->HorizRes <= 800)
- freq /= 2; /* Xbh has this type of clock for 32-bit */
+ /* Xbh has this type of clock for 32-bit */
+ freq /= 2;
break;
}
#endif
- bestclock (freq, &regs->freq, &regs->nom, &regs->den, &regs->div,
- maxclock);
- regs->mclk = cirrusfb_get_mclk (freq, var->bits_per_pixel, &regs->divMCLK);
+ bestclock(freq, &regs->freq, &regs->nom, &regs->den, &regs->div,
+ maxclock);
+ regs->mclk = cirrusfb_get_mclk(freq, var->bits_per_pixel,
+ &regs->divMCLK);
xres = var->xres;
hfront = var->right_margin;
@@ -948,7 +887,8 @@ static int cirrusfb_decode_var (const struct fb_var_screeninfo *var,
regs->HorizTotal = (xres + hfront + hsync + hback) / 8 - 5;
regs->HorizDispEnd = xres / 8 - 1;
regs->HorizBlankStart = xres / 8;
- regs->HorizBlankEnd = regs->HorizTotal + 5; /* does not count with "-5" */
+ /* does not count with "-5" */
+ regs->HorizBlankEnd = regs->HorizTotal + 5;
regs->HorizSyncStart = (xres + hfront) / 8 + 1;
regs->HorizSyncEnd = (xres + hfront + hsync) / 8 + 1;
@@ -976,23 +916,23 @@ static int cirrusfb_decode_var (const struct fb_var_screeninfo *var,
return 0;
}
-
-static void cirrusfb_set_mclk (const struct cirrusfb_info *cinfo, int val, int div)
+static void cirrusfb_set_mclk(const struct cirrusfb_info *cinfo, int val,
+ int div)
{
- assert (cinfo != NULL);
+ assert(cinfo != NULL);
if (div == 2) {
/* VCLK = MCLK/2 */
- unsigned char old = vga_rseq (cinfo->regbase, CL_SEQR1E);
- vga_wseq (cinfo->regbase, CL_SEQR1E, old | 0x1);
- vga_wseq (cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f));
+ unsigned char old = vga_rseq(cinfo->regbase, CL_SEQR1E);
+ vga_wseq(cinfo->regbase, CL_SEQR1E, old | 0x1);
+ vga_wseq(cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f));
} else if (div == 1) {
/* VCLK = MCLK */
- unsigned char old = vga_rseq (cinfo->regbase, CL_SEQR1E);
- vga_wseq (cinfo->regbase, CL_SEQR1E, old & ~0x1);
- vga_wseq (cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f));
+ unsigned char old = vga_rseq(cinfo->regbase, CL_SEQR1E);
+ vga_wseq(cinfo->regbase, CL_SEQR1E, old & ~0x1);
+ vga_wseq(cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f));
} else {
- vga_wseq (cinfo->regbase, CL_SEQR1F, val & 0x3f);
+ vga_wseq(cinfo->regbase, CL_SEQR1F, val & 0x3f);
}
}
@@ -1001,7 +941,7 @@ static void cirrusfb_set_mclk (const struct cirrusfb_info *cinfo, int val, int d
actually writes the values for a new video mode into the hardware,
**************************************************************************/
-static int cirrusfb_set_par_foo (struct fb_info *info)
+static int cirrusfb_set_par_foo(struct fb_info *info)
{
struct cirrusfb_info *cinfo = info->par;
struct fb_var_screeninfo *var = &info->var;
@@ -1011,15 +951,15 @@ static int cirrusfb_set_par_foo (struct fb_info *info)
int offset = 0, err;
const struct cirrusfb_board_info_rec *bi;
- DPRINTK ("ENTER\n");
- DPRINTK ("Requested mode: %dx%dx%d\n",
+ DPRINTK("ENTER\n");
+ DPRINTK("Requested mode: %dx%dx%d\n",
var->xres, var->yres, var->bits_per_pixel);
- DPRINTK ("pixclock: %d\n", var->pixclock);
+ DPRINTK("pixclock: %d\n", var->pixclock);
- init_vgachip (cinfo);
+ init_vgachip(info);
err = cirrusfb_decode_var(var, &regs, info);
- if(err) {
+ if (err) {
/* should never happen */
DPRINTK("mode change aborted. invalid var.\n");
return -EINVAL;
@@ -1027,34 +967,35 @@ static int cirrusfb_set_par_foo (struct fb_info *info)
bi = &cirrusfb_board_info[cinfo->btype];
-
/* unlock register VGA_CRTC_H_TOTAL..CRT7 */
- vga_wcrt (regbase, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */
+ vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */
/* if debugging is enabled, all parameters get output before writing */
- DPRINTK ("CRT0: %ld\n", regs.HorizTotal);
- vga_wcrt (regbase, VGA_CRTC_H_TOTAL, regs.HorizTotal);
+ DPRINTK("CRT0: %ld\n", regs.HorizTotal);
+ vga_wcrt(regbase, VGA_CRTC_H_TOTAL, regs.HorizTotal);
- DPRINTK ("CRT1: %ld\n", regs.HorizDispEnd);
- vga_wcrt (regbase, VGA_CRTC_H_DISP, regs.HorizDispEnd);
+ DPRINTK("CRT1: %ld\n", regs.HorizDispEnd);
+ vga_wcrt(regbase, VGA_CRTC_H_DISP, regs.HorizDispEnd);
- DPRINTK ("CRT2: %ld\n", regs.HorizBlankStart);
- vga_wcrt (regbase, VGA_CRTC_H_BLANK_START, regs.HorizBlankStart);
+ DPRINTK("CRT2: %ld\n", regs.HorizBlankStart);
+ vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, regs.HorizBlankStart);
- DPRINTK ("CRT3: 128+%ld\n", regs.HorizBlankEnd % 32); /* + 128: Compatible read */
- vga_wcrt (regbase, VGA_CRTC_H_BLANK_END, 128 + (regs.HorizBlankEnd % 32));
+ /* + 128: Compatible read */
+ DPRINTK("CRT3: 128+%ld\n", regs.HorizBlankEnd % 32);
+ vga_wcrt(regbase, VGA_CRTC_H_BLANK_END,
+ 128 + (regs.HorizBlankEnd % 32));
- DPRINTK ("CRT4: %ld\n", regs.HorizSyncStart);
- vga_wcrt (regbase, VGA_CRTC_H_SYNC_START, regs.HorizSyncStart);
+ DPRINTK("CRT4: %ld\n", regs.HorizSyncStart);
+ vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, regs.HorizSyncStart);
tmp = regs.HorizSyncEnd % 32;
if (regs.HorizBlankEnd & 32)
tmp += 128;
- DPRINTK ("CRT5: %d\n", tmp);
- vga_wcrt (regbase, VGA_CRTC_H_SYNC_END, tmp);
+ DPRINTK("CRT5: %d\n", tmp);
+ vga_wcrt(regbase, VGA_CRTC_H_SYNC_END, tmp);
- DPRINTK ("CRT6: %ld\n", regs.VertTotal & 0xff);
- vga_wcrt (regbase, VGA_CRTC_V_TOTAL, (regs.VertTotal & 0xff));
+ DPRINTK("CRT6: %ld\n", regs.VertTotal & 0xff);
+ vga_wcrt(regbase, VGA_CRTC_V_TOTAL, (regs.VertTotal & 0xff));
tmp = 16; /* LineCompare bit #9 */
if (regs.VertTotal & 256)
@@ -1071,34 +1012,34 @@ static int cirrusfb_set_par_foo (struct fb_info *info)
tmp |= 64;
if (regs.VertSyncStart & 512)
tmp |= 128;
- DPRINTK ("CRT7: %d\n", tmp);
- vga_wcrt (regbase, VGA_CRTC_OVERFLOW, tmp);
+ DPRINTK("CRT7: %d\n", tmp);
+ vga_wcrt(regbase, VGA_CRTC_OVERFLOW, tmp);
tmp = 0x40; /* LineCompare bit #8 */
if (regs.VertBlankStart & 512)
tmp |= 0x20;
if (var->vmode & FB_VMODE_DOUBLE)
tmp |= 0x80;
- DPRINTK ("CRT9: %d\n", tmp);
- vga_wcrt (regbase, VGA_CRTC_MAX_SCAN, tmp);
+ DPRINTK("CRT9: %d\n", tmp);
+ vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, tmp);
- DPRINTK ("CRT10: %ld\n", regs.VertSyncStart & 0xff);
- vga_wcrt (regbase, VGA_CRTC_V_SYNC_START, (regs.VertSyncStart & 0xff));
+ DPRINTK("CRT10: %ld\n", regs.VertSyncStart & 0xff);
+ vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, regs.VertSyncStart & 0xff);
- DPRINTK ("CRT11: 64+32+%ld\n", regs.VertSyncEnd % 16);
- vga_wcrt (regbase, VGA_CRTC_V_SYNC_END, (regs.VertSyncEnd % 16 + 64 + 32));
+ DPRINTK("CRT11: 64+32+%ld\n", regs.VertSyncEnd % 16);
+ vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, regs.VertSyncEnd % 16 + 64 + 32);
- DPRINTK ("CRT12: %ld\n", regs.VertDispEnd & 0xff);
- vga_wcrt (regbase, VGA_CRTC_V_DISP_END, (regs.VertDispEnd & 0xff));
+ DPRINTK("CRT12: %ld\n", regs.VertDispEnd & 0xff);
+ vga_wcrt(regbase, VGA_CRTC_V_DISP_END, regs.VertDispEnd & 0xff);
- DPRINTK ("CRT15: %ld\n", regs.VertBlankStart & 0xff);
- vga_wcrt (regbase, VGA_CRTC_V_BLANK_START, (regs.VertBlankStart & 0xff));
+ DPRINTK("CRT15: %ld\n", regs.VertBlankStart & 0xff);
+ vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, regs.VertBlankStart & 0xff);
- DPRINTK ("CRT16: %ld\n", regs.VertBlankEnd & 0xff);
- vga_wcrt (regbase, VGA_CRTC_V_BLANK_END, (regs.VertBlankEnd & 0xff));
+ DPRINTK("CRT16: %ld\n", regs.VertBlankEnd & 0xff);
+ vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, regs.VertBlankEnd & 0xff);
- DPRINTK ("CRT18: 0xff\n");
- vga_wcrt (regbase, VGA_CRTC_LINE_COMPARE, 0xff);
+ DPRINTK("CRT18: 0xff\n");
+ vga_wcrt(regbase, VGA_CRTC_LINE_COMPARE, 0xff);
tmp = 0;
if (var->vmode & FB_VMODE_INTERLACED)
@@ -1112,57 +1053,63 @@ static int cirrusfb_set_par_foo (struct fb_info *info)
if (regs.VertBlankEnd & 512)
tmp |= 128;
- DPRINTK ("CRT1a: %d\n", tmp);
- vga_wcrt (regbase, CL_CRT1A, tmp);
+ DPRINTK("CRT1a: %d\n", tmp);
+ vga_wcrt(regbase, CL_CRT1A, tmp);
/* set VCLK0 */
/* hardware RefClock: 14.31818 MHz */
/* formula: VClk = (OSC * N) / (D * (1+P)) */
/* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */
- vga_wseq (regbase, CL_SEQRB, regs.nom);
+ vga_wseq(regbase, CL_SEQRB, regs.nom);
tmp = regs.den << 1;
if (regs.div != 0)
tmp |= 1;
+ /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
if ((cinfo->btype == BT_SD64) ||
(cinfo->btype == BT_ALPINE) ||
(cinfo->btype == BT_GD5480))
- tmp |= 0x80; /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
+ tmp |= 0x80;
- DPRINTK ("CL_SEQR1B: %ld\n", (long) tmp);
- vga_wseq (regbase, CL_SEQR1B, tmp);
+ DPRINTK("CL_SEQR1B: %ld\n", (long) tmp);
+ vga_wseq(regbase, CL_SEQR1B, tmp);
if (regs.VertRes >= 1024)
/* 1280x1024 */
- vga_wcrt (regbase, VGA_CRTC_MODE, 0xc7);
+ vga_wcrt(regbase, VGA_CRTC_MODE, 0xc7);
else
/* mode control: VGA_CRTC_START_HI enable, ROTATE(?), 16bit
* address wrap, no compat. */
- vga_wcrt (regbase, VGA_CRTC_MODE, 0xc3);
+ vga_wcrt(regbase, VGA_CRTC_MODE, 0xc3);
-/* HAEH? vga_wcrt (regbase, VGA_CRTC_V_SYNC_END, 0x20); * previously: 0x00 unlock VGA_CRTC_H_TOTAL..CRT7 */
+/* HAEH? vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20);
+ * previously: 0x00 unlock VGA_CRTC_H_TOTAL..CRT7 */
/* don't know if it would hurt to also program this if no interlaced */
/* mode is used, but I feel better this way.. :-) */
if (var->vmode & FB_VMODE_INTERLACED)
- vga_wcrt (regbase, VGA_CRTC_REGS, regs.HorizTotal / 2);
+ vga_wcrt(regbase, VGA_CRTC_REGS, regs.HorizTotal / 2);
else
- vga_wcrt (regbase, VGA_CRTC_REGS, 0x00); /* interlace control */
+ vga_wcrt(regbase, VGA_CRTC_REGS, 0x00); /* interlace control */
- vga_wseq (regbase, VGA_SEQ_CHARACTER_MAP, 0);
+ vga_wseq(regbase, VGA_SEQ_CHARACTER_MAP, 0);
/* adjust horizontal/vertical sync type (low/high) */
- tmp = 0x03; /* enable display memory & CRTC I/O address for color mode */
+ /* enable display memory & CRTC I/O address for color mode */
+ tmp = 0x03;
if (var->sync & FB_SYNC_HOR_HIGH_ACT)
tmp |= 0x40;
if (var->sync & FB_SYNC_VERT_HIGH_ACT)
tmp |= 0x80;
- WGen (cinfo, VGA_MIS_W, tmp);
+ WGen(cinfo, VGA_MIS_W, tmp);
- vga_wcrt (regbase, VGA_CRTC_PRESET_ROW, 0); /* Screen A Preset Row-Scan register */
- vga_wcrt (regbase, VGA_CRTC_CURSOR_START, 0); /* text cursor on and start line */
- vga_wcrt (regbase, VGA_CRTC_CURSOR_END, 31); /* text cursor end line */
+ /* Screen A Preset Row-Scan register */
+ vga_wcrt(regbase, VGA_CRTC_PRESET_ROW, 0);
+ /* text cursor on and start line */
+ vga_wcrt(regbase, VGA_CRTC_CURSOR_START, 0);
+ /* text cursor end line */
+ vga_wcrt(regbase, VGA_CRTC_CURSOR_END, 31);
/******************************************************
*
@@ -1172,8 +1119,8 @@ static int cirrusfb_set_par_foo (struct fb_info *info)
/* programming for different color depths */
if (var->bits_per_pixel == 1) {
- DPRINTK ("cirrusfb: preparing for 1 bit deep display\n");
- vga_wgfx (regbase, VGA_GFX_MODE, 0); /* mode register */
+ DPRINTK("cirrusfb: preparing for 1 bit deep display\n");
+ vga_wgfx(regbase, VGA_GFX_MODE, 0); /* mode register */
/* SR07 */
switch (cinfo->btype) {
@@ -1184,71 +1131,77 @@ static int cirrusfb_set_par_foo (struct fb_info *info)
case BT_PICASSO4:
case BT_ALPINE:
case BT_GD5480:
- DPRINTK (" (for GD54xx)\n");
- vga_wseq (regbase, CL_SEQR7,
+ DPRINTK(" (for GD54xx)\n");
+ vga_wseq(regbase, CL_SEQR7,
regs.multiplexing ?
bi->sr07_1bpp_mux : bi->sr07_1bpp);
break;
case BT_LAGUNA:
- DPRINTK (" (for GD546x)\n");
- vga_wseq (regbase, CL_SEQR7,
- vga_rseq (regbase, CL_SEQR7) & ~0x01);
+ DPRINTK(" (for GD546x)\n");
+ vga_wseq(regbase, CL_SEQR7,
+ vga_rseq(regbase, CL_SEQR7) & ~0x01);
break;
default:
- printk (KERN_WARNING "cirrusfb: unknown Board\n");
+ printk(KERN_WARNING "cirrusfb: unknown Board\n");
break;
}
/* Extended Sequencer Mode */
switch (cinfo->btype) {
case BT_SD64:
- /* setting the SEQRF on SD64 is not necessary (only during init) */
- DPRINTK ("(for SD64)\n");
- vga_wseq (regbase, CL_SEQR1F, 0x1a); /* MCLK select */
+ /* setting the SEQRF on SD64 is not necessary
+ * (only during init)
+ */
+ DPRINTK("(for SD64)\n");
+ /* MCLK select */
+ vga_wseq(regbase, CL_SEQR1F, 0x1a);
break;
case BT_PICCOLO:
- DPRINTK ("(for Piccolo)\n");
-/* ### ueberall 0x22? */
- vga_wseq (regbase, CL_SEQR1F, 0x22); /* ##vorher 1c MCLK select */
- vga_wseq (regbase, CL_SEQRF, 0xb0); /* evtl d0 bei 1 bit? avoid FIFO underruns..? */
+ case BT_SPECTRUM:
+ DPRINTK("(for Piccolo/Spectrum)\n");
+ /* ### ueberall 0x22? */
+ /* ##vorher 1c MCLK select */
+ vga_wseq(regbase, CL_SEQR1F, 0x22);
+ /* evtl d0 bei 1 bit? avoid FIFO underruns..? */
+ vga_wseq(regbase, CL_SEQRF, 0xb0);
break;
case BT_PICASSO:
- DPRINTK ("(for Picasso)\n");
- vga_wseq (regbase, CL_SEQR1F, 0x22); /* ##vorher 22 MCLK select */
- vga_wseq (regbase, CL_SEQRF, 0xd0); /* ## vorher d0 avoid FIFO underruns..? */
- break;
-
- case BT_SPECTRUM:
- DPRINTK ("(for Spectrum)\n");
-/* ### ueberall 0x22? */
- vga_wseq (regbase, CL_SEQR1F, 0x22); /* ##vorher 1c MCLK select */
- vga_wseq (regbase, CL_SEQRF, 0xb0); /* evtl d0? avoid FIFO underruns..? */
+ DPRINTK("(for Picasso)\n");
+ /* ##vorher 22 MCLK select */
+ vga_wseq(regbase, CL_SEQR1F, 0x22);
+ /* ## vorher d0 avoid FIFO underruns..? */
+ vga_wseq(regbase, CL_SEQRF, 0xd0);
break;
case BT_PICASSO4:
case BT_ALPINE:
case BT_GD5480:
case BT_LAGUNA:
- DPRINTK (" (for GD54xx)\n");
+ DPRINTK(" (for GD54xx)\n");
/* do nothing */
break;
default:
- printk (KERN_WARNING "cirrusfb: unknown Board\n");
+ printk(KERN_WARNING "cirrusfb: unknown Board\n");
break;
}
- WGen (cinfo, VGA_PEL_MSK, 0x01); /* pixel mask: pass-through for first plane */
+ /* pixel mask: pass-through for first plane */
+ WGen(cinfo, VGA_PEL_MSK, 0x01);
if (regs.multiplexing)
- WHDR (cinfo, 0x4a); /* hidden dac reg: 1280x1024 */
+ /* hidden dac reg: 1280x1024 */
+ WHDR(cinfo, 0x4a);
else
- WHDR (cinfo, 0); /* hidden dac: nothing */
- vga_wseq (regbase, VGA_SEQ_MEMORY_MODE, 0x06); /* memory mode: odd/even, ext. memory */
- vga_wseq (regbase, VGA_SEQ_PLANE_WRITE, 0x01); /* plane mask: only write to first plane */
+ /* hidden dac: nothing */
+ WHDR(cinfo, 0);
+ /* memory mode: odd/even, ext. memory */
+ vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x06);
+ /* plane mask: only write to first plane */
+ vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0x01);
offset = var->xres_virtual / 16;
}
@@ -1259,7 +1212,7 @@ static int cirrusfb_set_par_foo (struct fb_info *info)
*/
else if (var->bits_per_pixel == 8) {
- DPRINTK ("cirrusfb: preparing for 8 bit deep display\n");
+ DPRINTK("cirrusfb: preparing for 8 bit deep display\n");
switch (cinfo->btype) {
case BT_SD64:
case BT_PICCOLO:
@@ -1268,75 +1221,77 @@ static int cirrusfb_set_par_foo (struct fb_info *info)
case BT_PICASSO4:
case BT_ALPINE:
case BT_GD5480:
- DPRINTK (" (for GD54xx)\n");
- vga_wseq (regbase, CL_SEQR7,
+ DPRINTK(" (for GD54xx)\n");
+ vga_wseq(regbase, CL_SEQR7,
regs.multiplexing ?
bi->sr07_8bpp_mux : bi->sr07_8bpp);
break;
case BT_LAGUNA:
- DPRINTK (" (for GD546x)\n");
- vga_wseq (regbase, CL_SEQR7,
- vga_rseq (regbase, CL_SEQR7) | 0x01);
+ DPRINTK(" (for GD546x)\n");
+ vga_wseq(regbase, CL_SEQR7,
+ vga_rseq(regbase, CL_SEQR7) | 0x01);
break;
default:
- printk (KERN_WARNING "cirrusfb: unknown Board\n");
+ printk(KERN_WARNING "cirrusfb: unknown Board\n");
break;
}
switch (cinfo->btype) {
case BT_SD64:
- vga_wseq (regbase, CL_SEQR1F, 0x1d); /* MCLK select */
+ /* MCLK select */
+ vga_wseq(regbase, CL_SEQR1F, 0x1d);
break;
case BT_PICCOLO:
- vga_wseq (regbase, CL_SEQR1F, 0x22); /* ### vorher 1c MCLK select */
- vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
- break;
-
case BT_PICASSO:
- vga_wseq (regbase, CL_SEQR1F, 0x22); /* ### vorher 1c MCLK select */
- vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
- break;
-
case BT_SPECTRUM:
- vga_wseq (regbase, CL_SEQR1F, 0x22); /* ### vorher 1c MCLK select */
- vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
+ /* ### vorher 1c MCLK select */
+ vga_wseq(regbase, CL_SEQR1F, 0x22);
+ /* Fast Page-Mode writes */
+ vga_wseq(regbase, CL_SEQRF, 0xb0);
break;
case BT_PICASSO4:
#ifdef CONFIG_ZORRO
- vga_wseq (regbase, CL_SEQRF, 0xb8); /* ### INCOMPLETE!! */
+ /* ### INCOMPLETE!! */
+ vga_wseq(regbase, CL_SEQRF, 0xb8);
#endif
-/* vga_wseq (regbase, CL_SEQR1F, 0x1c); */
+/* vga_wseq(regbase, CL_SEQR1F, 0x1c); */
break;
case BT_ALPINE:
- DPRINTK (" (for GD543x)\n");
- cirrusfb_set_mclk (cinfo, regs.mclk, regs.divMCLK);
+ DPRINTK(" (for GD543x)\n");
+ cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK);
/* We already set SRF and SR1F */
break;
case BT_GD5480:
case BT_LAGUNA:
- DPRINTK (" (for GD54xx)\n");
+ DPRINTK(" (for GD54xx)\n");
/* do nothing */
break;
default:
- printk (KERN_WARNING "cirrusfb: unknown Board\n");
+ printk(KERN_WARNING "cirrusfb: unknown Board\n");
break;
}
- vga_wgfx (regbase, VGA_GFX_MODE, 64); /* mode register: 256 color mode */
- WGen (cinfo, VGA_PEL_MSK, 0xff); /* pixel mask: pass-through all planes */
+ /* mode register: 256 color mode */
+ vga_wgfx(regbase, VGA_GFX_MODE, 64);
+ /* pixel mask: pass-through all planes */
+ WGen(cinfo, VGA_PEL_MSK, 0xff);
if (regs.multiplexing)
- WHDR (cinfo, 0x4a); /* hidden dac reg: 1280x1024 */
+ /* hidden dac reg: 1280x1024 */
+ WHDR(cinfo, 0x4a);
else
- WHDR (cinfo, 0); /* hidden dac: nothing */
- vga_wseq (regbase, VGA_SEQ_MEMORY_MODE, 0x0a); /* memory mode: chain4, ext. memory */
- vga_wseq (regbase, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: enable writing to all 4 planes */
+ /* hidden dac: nothing */
+ WHDR(cinfo, 0);
+ /* memory mode: chain4, ext. memory */
+ vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
+ /* plane mask: enable writing to all 4 planes */
+ vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff);
offset = var->xres_virtual / 8;
}
@@ -1347,72 +1302,77 @@ static int cirrusfb_set_par_foo (struct fb_info *info)
*/
else if (var->bits_per_pixel == 16) {
- DPRINTK ("cirrusfb: preparing for 16 bit deep display\n");
+ DPRINTK("cirrusfb: preparing for 16 bit deep display\n");
switch (cinfo->btype) {
case BT_SD64:
- vga_wseq (regbase, CL_SEQR7, 0xf7); /* Extended Sequencer Mode: 256c col. mode */
- vga_wseq (regbase, CL_SEQR1F, 0x1e); /* MCLK select */
+ /* Extended Sequencer Mode: 256c col. mode */
+ vga_wseq(regbase, CL_SEQR7, 0xf7);
+ /* MCLK select */
+ vga_wseq(regbase, CL_SEQR1F, 0x1e);
break;
case BT_PICCOLO:
- vga_wseq (regbase, CL_SEQR7, 0x87);
- vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
- vga_wseq (regbase, CL_SEQR1F, 0x22); /* MCLK select */
+ case BT_SPECTRUM:
+ vga_wseq(regbase, CL_SEQR7, 0x87);
+ /* Fast Page-Mode writes */
+ vga_wseq(regbase, CL_SEQRF, 0xb0);
+ /* MCLK select */
+ vga_wseq(regbase, CL_SEQR1F, 0x22);
break;
case BT_PICASSO:
- vga_wseq (regbase, CL_SEQR7, 0x27);
- vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
- vga_wseq (regbase, CL_SEQR1F, 0x22); /* MCLK select */
- break;
-
- case BT_SPECTRUM:
- vga_wseq (regbase, CL_SEQR7, 0x87);
- vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
- vga_wseq (regbase, CL_SEQR1F, 0x22); /* MCLK select */
+ vga_wseq(regbase, CL_SEQR7, 0x27);
+ /* Fast Page-Mode writes */
+ vga_wseq(regbase, CL_SEQRF, 0xb0);
+ /* MCLK select */
+ vga_wseq(regbase, CL_SEQR1F, 0x22);
break;
case BT_PICASSO4:
- vga_wseq (regbase, CL_SEQR7, 0x27);
-/* vga_wseq (regbase, CL_SEQR1F, 0x1c); */
+ vga_wseq(regbase, CL_SEQR7, 0x27);
+/* vga_wseq(regbase, CL_SEQR1F, 0x1c); */
break;
case BT_ALPINE:
- DPRINTK (" (for GD543x)\n");
+ DPRINTK(" (for GD543x)\n");
if (regs.HorizRes >= 1024)
- vga_wseq (regbase, CL_SEQR7, 0xa7);
+ vga_wseq(regbase, CL_SEQR7, 0xa7);
else
- vga_wseq (regbase, CL_SEQR7, 0xa3);
- cirrusfb_set_mclk (cinfo, regs.mclk, regs.divMCLK);
+ vga_wseq(regbase, CL_SEQR7, 0xa3);
+ cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK);
break;
case BT_GD5480:
- DPRINTK (" (for GD5480)\n");
- vga_wseq (regbase, CL_SEQR7, 0x17);
+ DPRINTK(" (for GD5480)\n");
+ vga_wseq(regbase, CL_SEQR7, 0x17);
/* We already set SRF and SR1F */
break;
case BT_LAGUNA:
- DPRINTK (" (for GD546x)\n");
- vga_wseq (regbase, CL_SEQR7,
- vga_rseq (regbase, CL_SEQR7) & ~0x01);
+ DPRINTK(" (for GD546x)\n");
+ vga_wseq(regbase, CL_SEQR7,
+ vga_rseq(regbase, CL_SEQR7) & ~0x01);
break;
default:
- printk (KERN_WARNING "CIRRUSFB: unknown Board\n");
+ printk(KERN_WARNING "CIRRUSFB: unknown Board\n");
break;
}
- vga_wgfx (regbase, VGA_GFX_MODE, 64); /* mode register: 256 color mode */
- WGen (cinfo, VGA_PEL_MSK, 0xff); /* pixel mask: pass-through all planes */
+ /* mode register: 256 color mode */
+ vga_wgfx(regbase, VGA_GFX_MODE, 64);
+ /* pixel mask: pass-through all planes */
+ WGen(cinfo, VGA_PEL_MSK, 0xff);
#ifdef CONFIG_PCI
- WHDR (cinfo, 0xc0); /* Copy Xbh */
+ WHDR(cinfo, 0xc0); /* Copy Xbh */
#elif defined(CONFIG_ZORRO)
/* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */
- WHDR (cinfo, 0xa0); /* hidden dac reg: nothing special */
+ WHDR(cinfo, 0xa0); /* hidden dac reg: nothing special */
#endif
- vga_wseq (regbase, VGA_SEQ_MEMORY_MODE, 0x0a); /* memory mode: chain4, ext. memory */
- vga_wseq (regbase, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: enable writing to all 4 planes */
+ /* memory mode: chain4, ext. memory */
+ vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
+ /* plane mask: enable writing to all 4 planes */
+ vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff);
offset = var->xres_virtual / 4;
}
@@ -1423,64 +1383,70 @@ static int cirrusfb_set_par_foo (struct fb_info *info)
*/
else if (var->bits_per_pixel == 32) {
- DPRINTK ("cirrusfb: preparing for 24/32 bit deep display\n");
+ DPRINTK("cirrusfb: preparing for 24/32 bit deep display\n");
switch (cinfo->btype) {
case BT_SD64:
- vga_wseq (regbase, CL_SEQR7, 0xf9); /* Extended Sequencer Mode: 256c col. mode */
- vga_wseq (regbase, CL_SEQR1F, 0x1e); /* MCLK select */
+ /* Extended Sequencer Mode: 256c col. mode */
+ vga_wseq(regbase, CL_SEQR7, 0xf9);
+ /* MCLK select */
+ vga_wseq(regbase, CL_SEQR1F, 0x1e);
break;
case BT_PICCOLO:
- vga_wseq (regbase, CL_SEQR7, 0x85);
- vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
- vga_wseq (regbase, CL_SEQR1F, 0x22); /* MCLK select */
+ case BT_SPECTRUM:
+ vga_wseq(regbase, CL_SEQR7, 0x85);
+ /* Fast Page-Mode writes */
+ vga_wseq(regbase, CL_SEQRF, 0xb0);
+ /* MCLK select */
+ vga_wseq(regbase, CL_SEQR1F, 0x22);
break;
case BT_PICASSO:
- vga_wseq (regbase, CL_SEQR7, 0x25);
- vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
- vga_wseq (regbase, CL_SEQR1F, 0x22); /* MCLK select */
- break;
-
- case BT_SPECTRUM:
- vga_wseq (regbase, CL_SEQR7, 0x85);
- vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
- vga_wseq (regbase, CL_SEQR1F, 0x22); /* MCLK select */
+ vga_wseq(regbase, CL_SEQR7, 0x25);
+ /* Fast Page-Mode writes */
+ vga_wseq(regbase, CL_SEQRF, 0xb0);
+ /* MCLK select */
+ vga_wseq(regbase, CL_SEQR1F, 0x22);
break;
case BT_PICASSO4:
- vga_wseq (regbase, CL_SEQR7, 0x25);
-/* vga_wseq (regbase, CL_SEQR1F, 0x1c); */
+ vga_wseq(regbase, CL_SEQR7, 0x25);
+/* vga_wseq(regbase, CL_SEQR1F, 0x1c); */
break;
case BT_ALPINE:
- DPRINTK (" (for GD543x)\n");
- vga_wseq (regbase, CL_SEQR7, 0xa9);
- cirrusfb_set_mclk (cinfo, regs.mclk, regs.divMCLK);
+ DPRINTK(" (for GD543x)\n");
+ vga_wseq(regbase, CL_SEQR7, 0xa9);
+ cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK);
break;
case BT_GD5480:
- DPRINTK (" (for GD5480)\n");
- vga_wseq (regbase, CL_SEQR7, 0x19);
+ DPRINTK(" (for GD5480)\n");
+ vga_wseq(regbase, CL_SEQR7, 0x19);
/* We already set SRF and SR1F */
break;
case BT_LAGUNA:
- DPRINTK (" (for GD546x)\n");
- vga_wseq (regbase, CL_SEQR7,
- vga_rseq (regbase, CL_SEQR7) & ~0x01);
+ DPRINTK(" (for GD546x)\n");
+ vga_wseq(regbase, CL_SEQR7,
+ vga_rseq(regbase, CL_SEQR7) & ~0x01);
break;
default:
- printk (KERN_WARNING "cirrusfb: unknown Board\n");
+ printk(KERN_WARNING "cirrusfb: unknown Board\n");
break;
}
- vga_wgfx (regbase, VGA_GFX_MODE, 64); /* mode register: 256 color mode */
- WGen (cinfo, VGA_PEL_MSK, 0xff); /* pixel mask: pass-through all planes */
- WHDR (cinfo, 0xc5); /* hidden dac reg: 8-8-8 mode (24 or 32) */
- vga_wseq (regbase, VGA_SEQ_MEMORY_MODE, 0x0a); /* memory mode: chain4, ext. memory */
- vga_wseq (regbase, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: enable writing to all 4 planes */
+ /* mode register: 256 color mode */
+ vga_wgfx(regbase, VGA_GFX_MODE, 64);
+ /* pixel mask: pass-through all planes */
+ WGen(cinfo, VGA_PEL_MSK, 0xff);
+ /* hidden dac reg: 8-8-8 mode (24 or 32) */
+ WHDR(cinfo, 0xc5);
+ /* memory mode: chain4, ext. memory */
+ vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
+ /* plane mask: enable writing to all 4 planes */
+ vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff);
offset = var->xres_virtual / 4;
}
@@ -1490,48 +1456,67 @@ static int cirrusfb_set_par_foo (struct fb_info *info)
*
*/
- else {
- printk (KERN_ERR "cirrusfb: What's this?? requested color depth == %d.\n",
+ else
+ printk(KERN_ERR "cirrusfb: What's this?? "
+ " requested color depth == %d.\n",
var->bits_per_pixel);
- }
- vga_wcrt (regbase, VGA_CRTC_OFFSET, offset & 0xff);
+ vga_wcrt(regbase, VGA_CRTC_OFFSET, offset & 0xff);
tmp = 0x22;
if (offset & 0x100)
tmp |= 0x10; /* offset overflow bit */
- vga_wcrt (regbase, CL_CRT1B, tmp); /* screen start addr #16-18, fastpagemode cycles */
+ /* screen start addr #16-18, fastpagemode cycles */
+ vga_wcrt(regbase, CL_CRT1B, tmp);
if (cinfo->btype == BT_SD64 ||
cinfo->btype == BT_PICASSO4 ||
cinfo->btype == BT_ALPINE ||
cinfo->btype == BT_GD5480)
- vga_wcrt (regbase, CL_CRT1D, 0x00); /* screen start address bit 19 */
-
- vga_wcrt (regbase, VGA_CRTC_CURSOR_HI, 0); /* text cursor location high */
- vga_wcrt (regbase, VGA_CRTC_CURSOR_LO, 0); /* text cursor location low */
- vga_wcrt (regbase, VGA_CRTC_UNDERLINE, 0); /* underline row scanline = at very bottom */
-
- vga_wattr (regbase, VGA_ATC_MODE, 1); /* controller mode */
- vga_wattr (regbase, VGA_ATC_OVERSCAN, 0); /* overscan (border) color */
- vga_wattr (regbase, VGA_ATC_PLANE_ENABLE, 15); /* color plane enable */
- vga_wattr (regbase, CL_AR33, 0); /* pixel panning */
- vga_wattr (regbase, VGA_ATC_COLOR_PAGE, 0); /* color select */
+ /* screen start address bit 19 */
+ vga_wcrt(regbase, CL_CRT1D, 0x00);
+
+ /* text cursor location high */
+ vga_wcrt(regbase, VGA_CRTC_CURSOR_HI, 0);
+ /* text cursor location low */
+ vga_wcrt(regbase, VGA_CRTC_CURSOR_LO, 0);
+ /* underline row scanline = at very bottom */
+ vga_wcrt(regbase, VGA_CRTC_UNDERLINE, 0);
+
+ /* controller mode */
+ vga_wattr(regbase, VGA_ATC_MODE, 1);
+ /* overscan (border) color */
+ vga_wattr(regbase, VGA_ATC_OVERSCAN, 0);
+ /* color plane enable */
+ vga_wattr(regbase, VGA_ATC_PLANE_ENABLE, 15);
+ /* pixel panning */
+ vga_wattr(regbase, CL_AR33, 0);
+ /* color select */
+ vga_wattr(regbase, VGA_ATC_COLOR_PAGE, 0);
/* [ EGS: SetOffset(); ] */
/* From SetOffset(): Turn on VideoEnable bit in Attribute controller */
- AttrOn (cinfo);
-
- vga_wgfx (regbase, VGA_GFX_SR_VALUE, 0); /* set/reset register */
- vga_wgfx (regbase, VGA_GFX_SR_ENABLE, 0); /* set/reset enable */
- vga_wgfx (regbase, VGA_GFX_COMPARE_VALUE, 0); /* color compare */
- vga_wgfx (regbase, VGA_GFX_DATA_ROTATE, 0); /* data rotate */
- vga_wgfx (regbase, VGA_GFX_PLANE_READ, 0); /* read map select */
- vga_wgfx (regbase, VGA_GFX_MISC, 1); /* miscellaneous register */
- vga_wgfx (regbase, VGA_GFX_COMPARE_MASK, 15); /* color don't care */
- vga_wgfx (regbase, VGA_GFX_BIT_MASK, 255); /* bit mask */
-
- vga_wseq (regbase, CL_SEQR12, 0x0); /* graphics cursor attributes: nothing special */
+ AttrOn(cinfo);
+
+ /* set/reset register */
+ vga_wgfx(regbase, VGA_GFX_SR_VALUE, 0);
+ /* set/reset enable */
+ vga_wgfx(regbase, VGA_GFX_SR_ENABLE, 0);
+ /* color compare */
+ vga_wgfx(regbase, VGA_GFX_COMPARE_VALUE, 0);
+ /* data rotate */
+ vga_wgfx(regbase, VGA_GFX_DATA_ROTATE, 0);
+ /* read map select */
+ vga_wgfx(regbase, VGA_GFX_PLANE_READ, 0);
+ /* miscellaneous register */
+ vga_wgfx(regbase, VGA_GFX_MISC, 1);
+ /* color don't care */
+ vga_wgfx(regbase, VGA_GFX_COMPARE_MASK, 15);
+ /* bit mask */
+ vga_wgfx(regbase, VGA_GFX_BIT_MASK, 255);
+
+ /* graphics cursor attributes: nothing special */
+ vga_wseq(regbase, CL_SEQR12, 0x0);
/* finally, turn on everything - turn off "FullBandwidth" bit */
/* also, set "DotClock%2" bit where requested */
@@ -1542,36 +1527,33 @@ static int cirrusfb_set_par_foo (struct fb_info *info)
tmp |= 0x08;
*/
- vga_wseq (regbase, VGA_SEQ_CLOCK_MODE, tmp);
- DPRINTK ("CL_SEQR1: %d\n", tmp);
+ vga_wseq(regbase, VGA_SEQ_CLOCK_MODE, tmp);
+ DPRINTK("CL_SEQR1: %d\n", tmp);
cinfo->currentmode = regs;
- info->fix.type = regs.type;
- info->fix.visual = regs.visual;
- info->fix.line_length = regs.line_length;
/* pan to requested offset */
- cirrusfb_pan_display (var, info);
+ cirrusfb_pan_display(var, info);
#ifdef CIRRUSFB_DEBUG
- cirrusfb_dump ();
+ cirrusfb_dump();
#endif
- DPRINTK ("EXIT\n");
+ DPRINTK("EXIT\n");
return 0;
}
/* for some reason incomprehensible to me, cirrusfb requires that you write
* the registers twice for the settings to take..grr. -dte */
-static int cirrusfb_set_par (struct fb_info *info)
+static int cirrusfb_set_par(struct fb_info *info)
{
- cirrusfb_set_par_foo (info);
- return cirrusfb_set_par_foo (info);
+ cirrusfb_set_par_foo(info);
+ return cirrusfb_set_par_foo(info);
}
-static int cirrusfb_setcolreg (unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp,
- struct fb_info *info)
+static int cirrusfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *info)
{
struct cirrusfb_info *cinfo = info->par;
@@ -1584,34 +1566,18 @@ static int cirrusfb_setcolreg (unsigned regno, unsigned red, unsigned green,
green >>= (16 - info->var.green.length);
blue >>= (16 - info->var.blue.length);
- if (regno>=16)
+ if (regno >= 16)
return 1;
v = (red << info->var.red.offset) |
(green << info->var.green.offset) |
(blue << info->var.blue.offset);
- switch (info->var.bits_per_pixel) {
- case 8:
- cinfo->pseudo_palette[regno] = v;
- break;
- case 16:
- cinfo->pseudo_palette[regno] = v;
- break;
- case 24:
- case 32:
- cinfo->pseudo_palette[regno] = v;
- break;
- }
+ cinfo->pseudo_palette[regno] = v;
return 0;
}
- cinfo->palette[regno].red = red;
- cinfo->palette[regno].green = green;
- cinfo->palette[regno].blue = blue;
-
- if (info->var.bits_per_pixel == 8) {
- WClut (cinfo, regno, red >> 10, green >> 10, blue >> 10);
- }
+ if (info->var.bits_per_pixel == 8)
+ WClut(cinfo, regno, red >> 10, green >> 10, blue >> 10);
return 0;
@@ -1622,8 +1588,8 @@ static int cirrusfb_setcolreg (unsigned regno, unsigned red, unsigned green,
performs display panning - provided hardware permits this
**************************************************************************/
-static int cirrusfb_pan_display (struct fb_var_screeninfo *var,
- struct fb_info *info)
+static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
{
int xoffset = 0;
int yoffset = 0;
@@ -1631,8 +1597,8 @@ static int cirrusfb_pan_display (struct fb_var_screeninfo *var,
unsigned char tmp = 0, tmp2 = 0, xpix;
struct cirrusfb_info *cinfo = info->par;
- DPRINTK ("ENTER\n");
- DPRINTK ("virtual offset: (%d,%d)\n", var->xoffset, var->yoffset);
+ DPRINTK("ENTER\n");
+ DPRINTK("virtual offset: (%d,%d)\n", var->xoffset, var->yoffset);
/* no range checks for xoffset and yoffset, */
/* as fb_pan_display has already done this */
@@ -1645,7 +1611,7 @@ static int cirrusfb_pan_display (struct fb_var_screeninfo *var,
xoffset = var->xoffset * info->var.bits_per_pixel / 8;
yoffset = var->yoffset;
- base = yoffset * cinfo->currentmode.line_length + xoffset;
+ base = yoffset * info->fix.line_length + xoffset;
if (info->var.bits_per_pixel == 1) {
/* base is already correct */
@@ -1655,11 +1621,13 @@ static int cirrusfb_pan_display (struct fb_var_screeninfo *var,
xpix = (unsigned char) ((xoffset % 4) * 2);
}
- cirrusfb_WaitBLT(cinfo->regbase); /* make sure all the BLT's are done */
+ cirrusfb_WaitBLT(cinfo->regbase); /* make sure all the BLT's are done */
/* lower 8 + 8 bits of screen start address */
- vga_wcrt (cinfo->regbase, VGA_CRTC_START_LO, (unsigned char) (base & 0xff));
- vga_wcrt (cinfo->regbase, VGA_CRTC_START_HI, (unsigned char) (base >> 8));
+ vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO,
+ (unsigned char) (base & 0xff));
+ vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI,
+ (unsigned char) (base >> 8));
/* construct bits 16, 17 and 18 of screen start address */
if (base & 0x10000)
@@ -1669,50 +1637,49 @@ static int cirrusfb_pan_display (struct fb_var_screeninfo *var,
if (base & 0x40000)
tmp |= 0x08;
- tmp2 = (vga_rcrt (cinfo->regbase, CL_CRT1B) & 0xf2) | tmp; /* 0xf2 is %11110010, exclude tmp bits */
- vga_wcrt (cinfo->regbase, CL_CRT1B, tmp2);
+ /* 0xf2 is %11110010, exclude tmp bits */
+ tmp2 = (vga_rcrt(cinfo->regbase, CL_CRT1B) & 0xf2) | tmp;
+ vga_wcrt(cinfo->regbase, CL_CRT1B, tmp2);
/* construct bit 19 of screen start address */
- if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19) {
- tmp2 = 0;
- if (base & 0x80000)
- tmp2 = 0x80;
- vga_wcrt (cinfo->regbase, CL_CRT1D, tmp2);
- }
+ if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19)
+ vga_wcrt(cinfo->regbase, CL_CRT1D, (base >> 12) & 0x80);
- /* write pixel panning value to AR33; this does not quite work in 8bpp */
- /* ### Piccolo..? Will this work? */
+ /* write pixel panning value to AR33; this does not quite work in 8bpp
+ *
+ * ### Piccolo..? Will this work?
+ */
if (info->var.bits_per_pixel == 1)
- vga_wattr (cinfo->regbase, CL_AR33, xpix);
+ vga_wattr(cinfo->regbase, CL_AR33, xpix);
- cirrusfb_WaitBLT (cinfo->regbase);
+ cirrusfb_WaitBLT(cinfo->regbase);
- DPRINTK ("EXIT\n");
- return (0);
+ DPRINTK("EXIT\n");
+ return 0;
}
-
-static int cirrusfb_blank (int blank_mode, struct fb_info *info)
+static int cirrusfb_blank(int blank_mode, struct fb_info *info)
{
/*
- * Blank the screen if blank_mode != 0, else unblank. If blank == NULL
- * then the caller blanks by setting the CLUT (Color Look Up Table) to all
- * black. Return 0 if blanking succeeded, != 0 if un-/blanking failed due
- * to e.g. a video mode which doesn't support it. Implements VESA suspend
- * and powerdown modes on hardware that supports disabling hsync/vsync:
- * blank_mode == 2: suspend vsync
- * blank_mode == 3: suspend hsync
- * blank_mode == 4: powerdown
+ * Blank the screen if blank_mode != 0, else unblank. If blank == NULL
+ * then the caller blanks by setting the CLUT (Color Look Up Table)
+ * to all black. Return 0 if blanking succeeded, != 0 if un-/blanking
+ * failed due to e.g. a video mode which doesn't support it.
+ * Implements VESA suspend and powerdown modes on hardware that
+ * supports disabling hsync/vsync:
+ * blank_mode == 2: suspend vsync
+ * blank_mode == 3: suspend hsync
+ * blank_mode == 4: powerdown
*/
unsigned char val;
struct cirrusfb_info *cinfo = info->par;
int current_mode = cinfo->blank_mode;
- DPRINTK ("ENTER, blank mode = %d\n", blank_mode);
+ DPRINTK("ENTER, blank mode = %d\n", blank_mode);
if (info->state != FBINFO_STATE_RUNNING ||
current_mode == blank_mode) {
- DPRINTK ("EXIT, returning 0\n");
+ DPRINTK("EXIT, returning 0\n");
return 0;
}
@@ -1720,17 +1687,19 @@ static int cirrusfb_blank (int blank_mode, struct fb_info *info)
if (current_mode == FB_BLANK_NORMAL ||
current_mode == FB_BLANK_UNBLANK) {
/* unblank the screen */
- val = vga_rseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE);
- vga_wseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE, val & 0xdf); /* clear "FullBandwidth" bit */
+ val = vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE);
+ /* clear "FullBandwidth" bit */
+ vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val & 0xdf);
/* and undo VESA suspend trickery */
- vga_wgfx (cinfo->regbase, CL_GRE, 0x00);
+ vga_wgfx(cinfo->regbase, CL_GRE, 0x00);
}
/* set new */
- if(blank_mode > FB_BLANK_NORMAL) {
+ if (blank_mode > FB_BLANK_NORMAL) {
/* blank the screen */
- val = vga_rseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE);
- vga_wseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE, val | 0x20); /* set "FullBandwidth" bit */
+ val = vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE);
+ /* set "FullBandwidth" bit */
+ vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val | 0x20);
}
switch (blank_mode) {
@@ -1738,21 +1707,21 @@ static int cirrusfb_blank (int blank_mode, struct fb_info *info)
case FB_BLANK_NORMAL:
break;
case FB_BLANK_VSYNC_SUSPEND:
- vga_wgfx (cinfo->regbase, CL_GRE, 0x04);
+ vga_wgfx(cinfo->regbase, CL_GRE, 0x04);
break;
case FB_BLANK_HSYNC_SUSPEND:
- vga_wgfx (cinfo->regbase, CL_GRE, 0x02);
+ vga_wgfx(cinfo->regbase, CL_GRE, 0x02);
break;
case FB_BLANK_POWERDOWN:
- vga_wgfx (cinfo->regbase, CL_GRE, 0x06);
+ vga_wgfx(cinfo->regbase, CL_GRE, 0x06);
break;
default:
- DPRINTK ("EXIT, returning 1\n");
+ DPRINTK("EXIT, returning 1\n");
return 1;
}
cinfo->blank_mode = blank_mode;
- DPRINTK ("EXIT, returning 0\n");
+ DPRINTK("EXIT, returning 0\n");
/* Let fbcon do a soft blank for us */
return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
@@ -1761,45 +1730,51 @@ static int cirrusfb_blank (int blank_mode, struct fb_info *info)
/****************************************************************************/
/**** BEGIN Internal Routines ***********************************************/
-static void init_vgachip (struct cirrusfb_info *cinfo)
+static void init_vgachip(struct fb_info *info)
{
+ struct cirrusfb_info *cinfo = info->par;
const struct cirrusfb_board_info_rec *bi;
- DPRINTK ("ENTER\n");
+ DPRINTK("ENTER\n");
- assert (cinfo != NULL);
+ assert(cinfo != NULL);
bi = &cirrusfb_board_info[cinfo->btype];
/* reset board globally */
switch (cinfo->btype) {
case BT_PICCOLO:
- WSFR (cinfo, 0x01);
- udelay (500);
- WSFR (cinfo, 0x51);
- udelay (500);
+ WSFR(cinfo, 0x01);
+ udelay(500);
+ WSFR(cinfo, 0x51);
+ udelay(500);
break;
case BT_PICASSO:
- WSFR2 (cinfo, 0xff);
- udelay (500);
+ WSFR2(cinfo, 0xff);
+ udelay(500);
break;
case BT_SD64:
case BT_SPECTRUM:
- WSFR (cinfo, 0x1f);
- udelay (500);
- WSFR (cinfo, 0x4f);
- udelay (500);
+ WSFR(cinfo, 0x1f);
+ udelay(500);
+ WSFR(cinfo, 0x4f);
+ udelay(500);
break;
case BT_PICASSO4:
- vga_wcrt (cinfo->regbase, CL_CRT51, 0x00); /* disable flickerfixer */
- mdelay (100);
- vga_wgfx (cinfo->regbase, CL_GR2F, 0x00); /* from Klaus' NetBSD driver: */
- vga_wgfx (cinfo->regbase, CL_GR33, 0x00); /* put blitter into 542x compat */
- vga_wgfx (cinfo->regbase, CL_GR31, 0x00); /* mode */
+ /* disable flickerfixer */
+ vga_wcrt(cinfo->regbase, CL_CRT51, 0x00);
+ mdelay(100);
+ /* from Klaus' NetBSD driver: */
+ vga_wgfx(cinfo->regbase, CL_GR2F, 0x00);
+ /* put blitter into 542x compat */
+ vga_wgfx(cinfo->regbase, CL_GR33, 0x00);
+ /* mode */
+ vga_wgfx(cinfo->regbase, CL_GR31, 0x00);
break;
case BT_GD5480:
- vga_wgfx (cinfo->regbase, CL_GR2F, 0x00); /* from Klaus' NetBSD driver: */
+ /* from Klaus' NetBSD driver: */
+ vga_wgfx(cinfo->regbase, CL_GR2F, 0x00);
break;
case BT_ALPINE:
@@ -1807,153 +1782,208 @@ static void init_vgachip (struct cirrusfb_info *cinfo)
break;
default:
- printk (KERN_ERR "cirrusfb: Warning: Unknown board type\n");
+ printk(KERN_ERR "cirrusfb: Warning: Unknown board type\n");
break;
}
- assert (cinfo->size > 0); /* make sure RAM size set by this point */
+ /* make sure RAM size set by this point */
+ assert(info->screen_size > 0);
/* the P4 is not fully initialized here; I rely on it having been */
/* inited under AmigaOS already, which seems to work just fine */
- /* (Klaus advised to do it this way) */
+ /* (Klaus advised to do it this way) */
if (cinfo->btype != BT_PICASSO4) {
- WGen (cinfo, CL_VSSM, 0x10); /* EGS: 0x16 */
- WGen (cinfo, CL_POS102, 0x01);
- WGen (cinfo, CL_VSSM, 0x08); /* EGS: 0x0e */
+ WGen(cinfo, CL_VSSM, 0x10); /* EGS: 0x16 */
+ WGen(cinfo, CL_POS102, 0x01);
+ WGen(cinfo, CL_VSSM, 0x08); /* EGS: 0x0e */
if (cinfo->btype != BT_SD64)
- WGen (cinfo, CL_VSSM2, 0x01);
+ WGen(cinfo, CL_VSSM2, 0x01);
- vga_wseq (cinfo->regbase, CL_SEQR0, 0x03); /* reset sequencer logic */
+ /* reset sequencer logic */
+ vga_wseq(cinfo->regbase, CL_SEQR0, 0x03);
- vga_wseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE, 0x21); /* FullBandwidth (video off) and 8/9 dot clock */
- WGen (cinfo, VGA_MIS_W, 0xc1); /* polarity (-/-), disable access to display memory, VGA_CRTC_START_HI base address: color */
+ /* FullBandwidth (video off) and 8/9 dot clock */
+ vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, 0x21);
+ /* polarity (-/-), disable access to display memory,
+ * VGA_CRTC_START_HI base address: color
+ */
+ WGen(cinfo, VGA_MIS_W, 0xc1);
-/* vga_wgfx (cinfo->regbase, CL_GRA, 0xce); "magic cookie" - doesn't make any sense to me.. */
- vga_wseq (cinfo->regbase, CL_SEQR6, 0x12); /* unlock all extension registers */
+ /* "magic cookie" - doesn't make any sense to me.. */
+/* vga_wgfx(cinfo->regbase, CL_GRA, 0xce); */
+ /* unlock all extension registers */
+ vga_wseq(cinfo->regbase, CL_SEQR6, 0x12);
- vga_wgfx (cinfo->regbase, CL_GR31, 0x04); /* reset blitter */
+ /* reset blitter */
+ vga_wgfx(cinfo->regbase, CL_GR31, 0x04);
switch (cinfo->btype) {
case BT_GD5480:
- vga_wseq (cinfo->regbase, CL_SEQRF, 0x98);
+ vga_wseq(cinfo->regbase, CL_SEQRF, 0x98);
break;
case BT_ALPINE:
break;
case BT_SD64:
- vga_wseq (cinfo->regbase, CL_SEQRF, 0xb8);
+ vga_wseq(cinfo->regbase, CL_SEQRF, 0xb8);
break;
default:
- vga_wseq (cinfo->regbase, CL_SEQR16, 0x0f);
- vga_wseq (cinfo->regbase, CL_SEQRF, 0xb0);
+ vga_wseq(cinfo->regbase, CL_SEQR16, 0x0f);
+ vga_wseq(cinfo->regbase, CL_SEQRF, 0xb0);
break;
}
}
- vga_wseq (cinfo->regbase, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: nothing */
- vga_wseq (cinfo->regbase, VGA_SEQ_CHARACTER_MAP, 0x00); /* character map select: doesn't even matter in gx mode */
- vga_wseq (cinfo->regbase, VGA_SEQ_MEMORY_MODE, 0x0e); /* memory mode: chain-4, no odd/even, ext. memory */
+ /* plane mask: nothing */
+ vga_wseq(cinfo->regbase, VGA_SEQ_PLANE_WRITE, 0xff);
+ /* character map select: doesn't even matter in gx mode */
+ vga_wseq(cinfo->regbase, VGA_SEQ_CHARACTER_MAP, 0x00);
+ /* memory mode: chain-4, no odd/even, ext. memory */
+ vga_wseq(cinfo->regbase, VGA_SEQ_MEMORY_MODE, 0x0e);
/* controller-internal base address of video memory */
if (bi->init_sr07)
- vga_wseq (cinfo->regbase, CL_SEQR7, bi->sr07);
+ vga_wseq(cinfo->regbase, CL_SEQR7, bi->sr07);
- /* vga_wseq (cinfo->regbase, CL_SEQR8, 0x00); *//* EEPROM control: shouldn't be necessary to write to this at all.. */
+ /* vga_wseq(cinfo->regbase, CL_SEQR8, 0x00); */
+ /* EEPROM control: shouldn't be necessary to write to this at all.. */
- vga_wseq (cinfo->regbase, CL_SEQR10, 0x00); /* graphics cursor X position (incomplete; position gives rem. 3 bits */
- vga_wseq (cinfo->regbase, CL_SEQR11, 0x00); /* graphics cursor Y position (..."... ) */
- vga_wseq (cinfo->regbase, CL_SEQR12, 0x00); /* graphics cursor attributes */
- vga_wseq (cinfo->regbase, CL_SEQR13, 0x00); /* graphics cursor pattern address */
+ /* graphics cursor X position (incomplete; position gives rem. 3 bits */
+ vga_wseq(cinfo->regbase, CL_SEQR10, 0x00);
+ /* graphics cursor Y position (..."... ) */
+ vga_wseq(cinfo->regbase, CL_SEQR11, 0x00);
+ /* graphics cursor attributes */
+ vga_wseq(cinfo->regbase, CL_SEQR12, 0x00);
+ /* graphics cursor pattern address */
+ vga_wseq(cinfo->regbase, CL_SEQR13, 0x00);
/* writing these on a P4 might give problems.. */
if (cinfo->btype != BT_PICASSO4) {
- vga_wseq (cinfo->regbase, CL_SEQR17, 0x00); /* configuration readback and ext. color */
- vga_wseq (cinfo->regbase, CL_SEQR18, 0x02); /* signature generator */
+ /* configuration readback and ext. color */
+ vga_wseq(cinfo->regbase, CL_SEQR17, 0x00);
+ /* signature generator */
+ vga_wseq(cinfo->regbase, CL_SEQR18, 0x02);
}
/* MCLK select etc. */
if (bi->init_sr1f)
- vga_wseq (cinfo->regbase, CL_SEQR1F, bi->sr1f);
-
- vga_wcrt (cinfo->regbase, VGA_CRTC_PRESET_ROW, 0x00); /* Screen A preset row scan: none */
- vga_wcrt (cinfo->regbase, VGA_CRTC_CURSOR_START, 0x20); /* Text cursor start: disable text cursor */
- vga_wcrt (cinfo->regbase, VGA_CRTC_CURSOR_END, 0x00); /* Text cursor end: - */
- vga_wcrt (cinfo->regbase, VGA_CRTC_START_HI, 0x00); /* Screen start address high: 0 */
- vga_wcrt (cinfo->regbase, VGA_CRTC_START_LO, 0x00); /* Screen start address low: 0 */
- vga_wcrt (cinfo->regbase, VGA_CRTC_CURSOR_HI, 0x00); /* text cursor location high: 0 */
- vga_wcrt (cinfo->regbase, VGA_CRTC_CURSOR_LO, 0x00); /* text cursor location low: 0 */
-
- vga_wcrt (cinfo->regbase, VGA_CRTC_UNDERLINE, 0x00); /* Underline Row scanline: - */
- vga_wcrt (cinfo->regbase, VGA_CRTC_MODE, 0xc3); /* mode control: timing enable, byte mode, no compat modes */
- vga_wcrt (cinfo->regbase, VGA_CRTC_LINE_COMPARE, 0x00); /* Line Compare: not needed */
+ vga_wseq(cinfo->regbase, CL_SEQR1F, bi->sr1f);
+
+ /* Screen A preset row scan: none */
+ vga_wcrt(cinfo->regbase, VGA_CRTC_PRESET_ROW, 0x00);
+ /* Text cursor start: disable text cursor */
+ vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_START, 0x20);
+ /* Text cursor end: - */
+ vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_END, 0x00);
+ /* Screen start address high: 0 */
+ vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI, 0x00);
+ /* Screen start address low: 0 */
+ vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO, 0x00);
+ /* text cursor location high: 0 */
+ vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_HI, 0x00);
+ /* text cursor location low: 0 */
+ vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_LO, 0x00);
+
+ /* Underline Row scanline: - */
+ vga_wcrt(cinfo->regbase, VGA_CRTC_UNDERLINE, 0x00);
+ /* mode control: timing enable, byte mode, no compat modes */
+ vga_wcrt(cinfo->regbase, VGA_CRTC_MODE, 0xc3);
+ /* Line Compare: not needed */
+ vga_wcrt(cinfo->regbase, VGA_CRTC_LINE_COMPARE, 0x00);
/* ### add 0x40 for text modes with > 30 MHz pixclock */
- vga_wcrt (cinfo->regbase, CL_CRT1B, 0x02); /* ext. display controls: ext.adr. wrap */
-
- vga_wgfx (cinfo->regbase, VGA_GFX_SR_VALUE, 0x00); /* Set/Reset registes: - */
- vga_wgfx (cinfo->regbase, VGA_GFX_SR_ENABLE, 0x00); /* Set/Reset enable: - */
- vga_wgfx (cinfo->regbase, VGA_GFX_COMPARE_VALUE, 0x00); /* Color Compare: - */
- vga_wgfx (cinfo->regbase, VGA_GFX_DATA_ROTATE, 0x00); /* Data Rotate: - */
- vga_wgfx (cinfo->regbase, VGA_GFX_PLANE_READ, 0x00); /* Read Map Select: - */
- vga_wgfx (cinfo->regbase, VGA_GFX_MODE, 0x00); /* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */
- vga_wgfx (cinfo->regbase, VGA_GFX_MISC, 0x01); /* Miscellaneous: memory map base address, graphics mode */
- vga_wgfx (cinfo->regbase, VGA_GFX_COMPARE_MASK, 0x0f); /* Color Don't care: involve all planes */
- vga_wgfx (cinfo->regbase, VGA_GFX_BIT_MASK, 0xff); /* Bit Mask: no mask at all */
+ /* ext. display controls: ext.adr. wrap */
+ vga_wcrt(cinfo->regbase, CL_CRT1B, 0x02);
+
+ /* Set/Reset registes: - */
+ vga_wgfx(cinfo->regbase, VGA_GFX_SR_VALUE, 0x00);
+ /* Set/Reset enable: - */
+ vga_wgfx(cinfo->regbase, VGA_GFX_SR_ENABLE, 0x00);
+ /* Color Compare: - */
+ vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_VALUE, 0x00);
+ /* Data Rotate: - */
+ vga_wgfx(cinfo->regbase, VGA_GFX_DATA_ROTATE, 0x00);
+ /* Read Map Select: - */
+ vga_wgfx(cinfo->regbase, VGA_GFX_PLANE_READ, 0x00);
+ /* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */
+ vga_wgfx(cinfo->regbase, VGA_GFX_MODE, 0x00);
+ /* Miscellaneous: memory map base address, graphics mode */
+ vga_wgfx(cinfo->regbase, VGA_GFX_MISC, 0x01);
+ /* Color Don't care: involve all planes */
+ vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_MASK, 0x0f);
+ /* Bit Mask: no mask at all */
+ vga_wgfx(cinfo->regbase, VGA_GFX_BIT_MASK, 0xff);
if (cinfo->btype == BT_ALPINE)
- vga_wgfx (cinfo->regbase, CL_GRB, 0x20); /* (5434 can't have bit 3 set for bitblt) */
+ /* (5434 can't have bit 3 set for bitblt) */
+ vga_wgfx(cinfo->regbase, CL_GRB, 0x20);
else
- vga_wgfx (cinfo->regbase, CL_GRB, 0x28); /* Graphics controller mode extensions: finer granularity, 8byte data latches */
-
- vga_wgfx (cinfo->regbase, CL_GRC, 0xff); /* Color Key compare: - */
- vga_wgfx (cinfo->regbase, CL_GRD, 0x00); /* Color Key compare mask: - */
- vga_wgfx (cinfo->regbase, CL_GRE, 0x00); /* Miscellaneous control: - */
- /* vga_wgfx (cinfo->regbase, CL_GR10, 0x00); *//* Background color byte 1: - */
-/* vga_wgfx (cinfo->regbase, CL_GR11, 0x00); */
-
- vga_wattr (cinfo->regbase, VGA_ATC_PALETTE0, 0x00); /* Attribute Controller palette registers: "identity mapping" */
- vga_wattr (cinfo->regbase, VGA_ATC_PALETTE1, 0x01);
- vga_wattr (cinfo->regbase, VGA_ATC_PALETTE2, 0x02);
- vga_wattr (cinfo->regbase, VGA_ATC_PALETTE3, 0x03);
- vga_wattr (cinfo->regbase, VGA_ATC_PALETTE4, 0x04);
- vga_wattr (cinfo->regbase, VGA_ATC_PALETTE5, 0x05);
- vga_wattr (cinfo->regbase, VGA_ATC_PALETTE6, 0x06);
- vga_wattr (cinfo->regbase, VGA_ATC_PALETTE7, 0x07);
- vga_wattr (cinfo->regbase, VGA_ATC_PALETTE8, 0x08);
- vga_wattr (cinfo->regbase, VGA_ATC_PALETTE9, 0x09);
- vga_wattr (cinfo->regbase, VGA_ATC_PALETTEA, 0x0a);
- vga_wattr (cinfo->regbase, VGA_ATC_PALETTEB, 0x0b);
- vga_wattr (cinfo->regbase, VGA_ATC_PALETTEC, 0x0c);
- vga_wattr (cinfo->regbase, VGA_ATC_PALETTED, 0x0d);
- vga_wattr (cinfo->regbase, VGA_ATC_PALETTEE, 0x0e);
- vga_wattr (cinfo->regbase, VGA_ATC_PALETTEF, 0x0f);
-
- vga_wattr (cinfo->regbase, VGA_ATC_MODE, 0x01); /* Attribute Controller mode: graphics mode */
- vga_wattr (cinfo->regbase, VGA_ATC_OVERSCAN, 0x00); /* Overscan color reg.: reg. 0 */
- vga_wattr (cinfo->regbase, VGA_ATC_PLANE_ENABLE, 0x0f); /* Color Plane enable: Enable all 4 planes */
-/* ### vga_wattr (cinfo->regbase, CL_AR33, 0x00); * Pixel Panning: - */
- vga_wattr (cinfo->regbase, VGA_ATC_COLOR_PAGE, 0x00); /* Color Select: - */
-
- WGen (cinfo, VGA_PEL_MSK, 0xff); /* Pixel mask: no mask */
+ /* Graphics controller mode extensions: finer granularity,
+ * 8byte data latches
+ */
+ vga_wgfx(cinfo->regbase, CL_GRB, 0x28);
+
+ vga_wgfx(cinfo->regbase, CL_GRC, 0xff); /* Color Key compare: - */
+ vga_wgfx(cinfo->regbase, CL_GRD, 0x00); /* Color Key compare mask: - */
+ vga_wgfx(cinfo->regbase, CL_GRE, 0x00); /* Miscellaneous control: - */
+ /* Background color byte 1: - */
+ /* vga_wgfx (cinfo->regbase, CL_GR10, 0x00); */
+ /* vga_wgfx (cinfo->regbase, CL_GR11, 0x00); */
+
+ /* Attribute Controller palette registers: "identity mapping" */
+ vga_wattr(cinfo->regbase, VGA_ATC_PALETTE0, 0x00);
+ vga_wattr(cinfo->regbase, VGA_ATC_PALETTE1, 0x01);
+ vga_wattr(cinfo->regbase, VGA_ATC_PALETTE2, 0x02);
+ vga_wattr(cinfo->regbase, VGA_ATC_PALETTE3, 0x03);
+ vga_wattr(cinfo->regbase, VGA_ATC_PALETTE4, 0x04);
+ vga_wattr(cinfo->regbase, VGA_ATC_PALETTE5, 0x05);
+ vga_wattr(cinfo->regbase, VGA_ATC_PALETTE6, 0x06);
+ vga_wattr(cinfo->regbase, VGA_ATC_PALETTE7, 0x07);
+ vga_wattr(cinfo->regbase, VGA_ATC_PALETTE8, 0x08);
+ vga_wattr(cinfo->regbase, VGA_ATC_PALETTE9, 0x09);
+ vga_wattr(cinfo->regbase, VGA_ATC_PALETTEA, 0x0a);
+ vga_wattr(cinfo->regbase, VGA_ATC_PALETTEB, 0x0b);
+ vga_wattr(cinfo->regbase, VGA_ATC_PALETTEC, 0x0c);
+ vga_wattr(cinfo->regbase, VGA_ATC_PALETTED, 0x0d);
+ vga_wattr(cinfo->regbase, VGA_ATC_PALETTEE, 0x0e);
+ vga_wattr(cinfo->regbase, VGA_ATC_PALETTEF, 0x0f);
+
+ /* Attribute Controller mode: graphics mode */
+ vga_wattr(cinfo->regbase, VGA_ATC_MODE, 0x01);
+ /* Overscan color reg.: reg. 0 */
+ vga_wattr(cinfo->regbase, VGA_ATC_OVERSCAN, 0x00);
+ /* Color Plane enable: Enable all 4 planes */
+ vga_wattr(cinfo->regbase, VGA_ATC_PLANE_ENABLE, 0x0f);
+/* ### vga_wattr(cinfo->regbase, CL_AR33, 0x00); * Pixel Panning: - */
+ /* Color Select: - */
+ vga_wattr(cinfo->regbase, VGA_ATC_COLOR_PAGE, 0x00);
+
+ WGen(cinfo, VGA_PEL_MSK, 0xff); /* Pixel mask: no mask */
if (cinfo->btype != BT_ALPINE && cinfo->btype != BT_GD5480)
- WGen (cinfo, VGA_MIS_W, 0xc3); /* polarity (-/-), enable display mem, VGA_CRTC_START_HI i/o base = color */
+ /* polarity (-/-), enable display mem,
+ * VGA_CRTC_START_HI i/o base = color
+ */
+ WGen(cinfo, VGA_MIS_W, 0xc3);
- vga_wgfx (cinfo->regbase, CL_GR31, 0x04); /* BLT Start/status: Blitter reset */
- vga_wgfx (cinfo->regbase, CL_GR31, 0x00); /* - " - : "end-of-reset" */
+ /* BLT Start/status: Blitter reset */
+ vga_wgfx(cinfo->regbase, CL_GR31, 0x04);
+ /* - " - : "end-of-reset" */
+ vga_wgfx(cinfo->regbase, CL_GR31, 0x00);
/* misc... */
- WHDR (cinfo, 0); /* Hidden DAC register: - */
+ WHDR(cinfo, 0); /* Hidden DAC register: - */
- printk (KERN_DEBUG "cirrusfb: This board has %ld bytes of DRAM memory\n", cinfo->size);
- DPRINTK ("EXIT\n");
+ printk(KERN_DEBUG "cirrusfb: This board has %ld bytes of DRAM memory\n",
+ info->screen_size);
+ DPRINTK("EXIT\n");
return;
}
-static void switch_monitor (struct cirrusfb_info *cinfo, int on)
+static void switch_monitor(struct cirrusfb_info *cinfo, int on)
{
#ifdef CONFIG_ZORRO /* only works on Zorro boards */
static int IsOn = 0; /* XXX not ok for multiple boards */
- DPRINTK ("ENTER\n");
+ DPRINTK("ENTER\n");
if (cinfo->btype == BT_PICASSO4)
return; /* nothing to switch */
@@ -1963,77 +1993,56 @@ static void switch_monitor (struct cirrusfb_info *cinfo, int on)
return; /* nothing to switch */
if (cinfo->btype == BT_PICASSO) {
if ((on && !IsOn) || (!on && IsOn))
- WSFR (cinfo, 0xff);
+ WSFR(cinfo, 0xff);
- DPRINTK ("EXIT\n");
+ DPRINTK("EXIT\n");
return;
}
if (on) {
switch (cinfo->btype) {
case BT_SD64:
- WSFR (cinfo, cinfo->SFR | 0x21);
+ WSFR(cinfo, cinfo->SFR | 0x21);
break;
case BT_PICCOLO:
- WSFR (cinfo, cinfo->SFR | 0x28);
+ WSFR(cinfo, cinfo->SFR | 0x28);
break;
case BT_SPECTRUM:
- WSFR (cinfo, 0x6f);
+ WSFR(cinfo, 0x6f);
break;
default: /* do nothing */ break;
}
} else {
switch (cinfo->btype) {
case BT_SD64:
- WSFR (cinfo, cinfo->SFR & 0xde);
+ WSFR(cinfo, cinfo->SFR & 0xde);
break;
case BT_PICCOLO:
- WSFR (cinfo, cinfo->SFR & 0xd7);
+ WSFR(cinfo, cinfo->SFR & 0xd7);
break;
case BT_SPECTRUM:
- WSFR (cinfo, 0x4f);
+ WSFR(cinfo, 0x4f);
break;
default: /* do nothing */ break;
}
}
- DPRINTK ("EXIT\n");
+ DPRINTK("EXIT\n");
#endif /* CONFIG_ZORRO */
}
-
/******************************************/
/* Linux 2.6-style accelerated functions */
/******************************************/
-static void cirrusfb_prim_fillrect(struct cirrusfb_info *cinfo,
- const struct fb_fillrect *region)
-{
- int m; /* bytes per pixel */
- u32 color = (cinfo->info->fix.visual == FB_VISUAL_TRUECOLOR) ?
- cinfo->pseudo_palette[region->color] : region->color;
-
- if(cinfo->info->var.bits_per_pixel == 1) {
- cirrusfb_RectFill(cinfo->regbase, cinfo->info->var.bits_per_pixel,
- region->dx / 8, region->dy,
- region->width / 8, region->height,
- color,
- cinfo->currentmode.line_length);
- } else {
- m = ( cinfo->info->var.bits_per_pixel + 7 ) / 8;
- cirrusfb_RectFill(cinfo->regbase, cinfo->info->var.bits_per_pixel,
- region->dx * m, region->dy,
- region->width * m, region->height,
- color,
- cinfo->currentmode.line_length);
- }
- return;
-}
-
-static void cirrusfb_fillrect (struct fb_info *info, const struct fb_fillrect *region)
+static void cirrusfb_fillrect(struct fb_info *info,
+ const struct fb_fillrect *region)
{
- struct cirrusfb_info *cinfo = info->par;
struct fb_fillrect modded;
int vxres, vyres;
+ struct cirrusfb_info *cinfo = info->par;
+ int m = info->var.bits_per_pixel;
+ u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
+ cinfo->pseudo_palette[region->color] : region->color;
if (info->state != FBINFO_STATE_RUNNING)
return;
@@ -2047,49 +2056,30 @@ static void cirrusfb_fillrect (struct fb_info *info, const struct fb_fillrect *r
memcpy(&modded, region, sizeof(struct fb_fillrect));
- if(!modded.width || !modded.height ||
+ if (!modded.width || !modded.height ||
modded.dx >= vxres || modded.dy >= vyres)
return;
- if(modded.dx + modded.width > vxres) modded.width = vxres - modded.dx;
- if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy;
-
- cirrusfb_prim_fillrect(cinfo, &modded);
-}
-
-static void cirrusfb_prim_copyarea(struct cirrusfb_info *cinfo,
- const struct fb_copyarea *area)
-{
- int m; /* bytes per pixel */
- if(cinfo->info->var.bits_per_pixel == 1) {
- cirrusfb_BitBLT(cinfo->regbase, cinfo->info->var.bits_per_pixel,
- area->sx / 8, area->sy,
- area->dx / 8, area->dy,
- area->width / 8, area->height,
- cinfo->currentmode.line_length);
- } else {
- m = ( cinfo->info->var.bits_per_pixel + 7 ) / 8;
- cirrusfb_BitBLT(cinfo->regbase, cinfo->info->var.bits_per_pixel,
- area->sx * m, area->sy,
- area->dx * m, area->dy,
- area->width * m, area->height,
- cinfo->currentmode.line_length);
- }
- return;
+ if (modded.dx + modded.width > vxres)
+ modded.width = vxres - modded.dx;
+ if (modded.dy + modded.height > vyres)
+ modded.height = vyres - modded.dy;
+
+ cirrusfb_RectFill(cinfo->regbase,
+ info->var.bits_per_pixel,
+ (region->dx * m) / 8, region->dy,
+ (region->width * m) / 8, region->height,
+ color,
+ info->fix.line_length);
}
-
-static void cirrusfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+static void cirrusfb_copyarea(struct fb_info *info,
+ const struct fb_copyarea *area)
{
- struct cirrusfb_info *cinfo = info->par;
struct fb_copyarea modded;
u32 vxres, vyres;
- modded.sx = area->sx;
- modded.sy = area->sy;
- modded.dx = area->dx;
- modded.dy = area->dy;
- modded.width = area->width;
- modded.height = area->height;
+ struct cirrusfb_info *cinfo = info->par;
+ int m = info->var.bits_per_pixel;
if (info->state != FBINFO_STATE_RUNNING)
return;
@@ -2100,90 +2090,106 @@ static void cirrusfb_copyarea(struct fb_info *info, const struct fb_copyarea *ar
vxres = info->var.xres_virtual;
vyres = info->var.yres_virtual;
+ memcpy(&modded, area, sizeof(struct fb_copyarea));
- if(!modded.width || !modded.height ||
+ if (!modded.width || !modded.height ||
modded.sx >= vxres || modded.sy >= vyres ||
modded.dx >= vxres || modded.dy >= vyres)
return;
- if(modded.sx + modded.width > vxres) modded.width = vxres - modded.sx;
- if(modded.dx + modded.width > vxres) modded.width = vxres - modded.dx;
- if(modded.sy + modded.height > vyres) modded.height = vyres - modded.sy;
- if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy;
+ if (modded.sx + modded.width > vxres)
+ modded.width = vxres - modded.sx;
+ if (modded.dx + modded.width > vxres)
+ modded.width = vxres - modded.dx;
+ if (modded.sy + modded.height > vyres)
+ modded.height = vyres - modded.sy;
+ if (modded.dy + modded.height > vyres)
+ modded.height = vyres - modded.dy;
+
+ cirrusfb_BitBLT(cinfo->regbase, info->var.bits_per_pixel,
+ (area->sx * m) / 8, area->sy,
+ (area->dx * m) / 8, area->dy,
+ (area->width * m) / 8, area->height,
+ info->fix.line_length);
- cirrusfb_prim_copyarea(cinfo, &modded);
}
-static void cirrusfb_imageblit(struct fb_info *info, const struct fb_image *image)
+static void cirrusfb_imageblit(struct fb_info *info,
+ const struct fb_image *image)
{
struct cirrusfb_info *cinfo = info->par;
- cirrusfb_WaitBLT(cinfo->regbase);
+ cirrusfb_WaitBLT(cinfo->regbase);
cfb_imageblit(info, image);
}
-
#ifdef CONFIG_PPC_PREP
#define PREP_VIDEO_BASE ((volatile unsigned long) 0xC0000000)
#define PREP_IO_BASE ((volatile unsigned char *) 0x80000000)
-static void get_prep_addrs (unsigned long *display, unsigned long *registers)
+static void get_prep_addrs(unsigned long *display, unsigned long *registers)
{
- DPRINTK ("ENTER\n");
+ DPRINTK("ENTER\n");
*display = PREP_VIDEO_BASE;
*registers = (unsigned long) PREP_IO_BASE;
- DPRINTK ("EXIT\n");
+ DPRINTK("EXIT\n");
}
#endif /* CONFIG_PPC_PREP */
-
#ifdef CONFIG_PCI
-static int release_io_ports = 0;
+static int release_io_ports;
/* Pulled the logic from XFree86 Cirrus driver to get the memory size,
* based on the DRAM bandwidth bit and DRAM bank switching bit. This
* works with 1MB, 2MB and 4MB configurations (which the Motorola boards
* seem to have. */
-static unsigned int cirrusfb_get_memsize (u8 __iomem *regbase)
+static unsigned int cirrusfb_get_memsize(u8 __iomem *regbase)
{
unsigned long mem;
unsigned char SRF;
- DPRINTK ("ENTER\n");
+ DPRINTK("ENTER\n");
- SRF = vga_rseq (regbase, CL_SEQRF);
+ SRF = vga_rseq(regbase, CL_SEQRF);
switch ((SRF & 0x18)) {
- case 0x08: mem = 512 * 1024; break;
- case 0x10: mem = 1024 * 1024; break;
- /* 64-bit DRAM data bus width; assume 2MB. Also indicates 2MB memory
- * on the 5430. */
- case 0x18: mem = 2048 * 1024; break;
- default: printk ("CLgenfb: Unknown memory size!\n");
+ case 0x08:
+ mem = 512 * 1024;
+ break;
+ case 0x10:
+ mem = 1024 * 1024;
+ break;
+ /* 64-bit DRAM data bus width; assume 2MB. Also indicates 2MB memory
+ * on the 5430.
+ */
+ case 0x18:
+ mem = 2048 * 1024;
+ break;
+ default:
+ printk(KERN_WARNING "CLgenfb: Unknown memory size!\n");
mem = 1024 * 1024;
}
- if (SRF & 0x80) {
- /* If DRAM bank switching is enabled, there must be twice as much
- * memory installed. (4MB on the 5434) */
+ if (SRF & 0x80)
+ /* If DRAM bank switching is enabled, there must be twice as much
+ * memory installed. (4MB on the 5434)
+ */
mem *= 2;
- }
+
/* TODO: Handling of GD5446/5480 (see XF86 sources ...) */
- DPRINTK ("EXIT\n");
+ DPRINTK("EXIT\n");
return mem;
}
-
-
-static void get_pci_addrs (const struct pci_dev *pdev,
- unsigned long *display, unsigned long *registers)
+static void get_pci_addrs(const struct pci_dev *pdev,
+ unsigned long *display, unsigned long *registers)
{
- assert (pdev != NULL);
- assert (display != NULL);
- assert (registers != NULL);
+ assert(pdev != NULL);
+ assert(display != NULL);
+ assert(registers != NULL);
- DPRINTK ("ENTER\n");
+ DPRINTK("ENTER\n");
*display = 0;
*registers = 0;
@@ -2198,51 +2204,48 @@ static void get_pci_addrs (const struct pci_dev *pdev,
*registers = pci_resource_start(pdev, 1);
}
- assert (*display != 0);
+ assert(*display != 0);
- DPRINTK ("EXIT\n");
+ DPRINTK("EXIT\n");
}
-
-static void cirrusfb_pci_unmap (struct cirrusfb_info *cinfo)
+static void cirrusfb_pci_unmap(struct fb_info *info)
{
+ struct cirrusfb_info *cinfo = info->par;
struct pci_dev *pdev = cinfo->pdev;
- iounmap(cinfo->fbmem);
+ iounmap(info->screen_base);
#if 0 /* if system didn't claim this region, we would... */
release_mem_region(0xA0000, 65535);
#endif
if (release_io_ports)
release_region(0x3C0, 32);
pci_release_regions(pdev);
- framebuffer_release(cinfo->info);
}
#endif /* CONFIG_PCI */
-
#ifdef CONFIG_ZORRO
-static void __devexit cirrusfb_zorro_unmap (struct cirrusfb_info *cinfo)
+static void __devexit cirrusfb_zorro_unmap(struct fb_info *info)
{
+ struct cirrusfb_info *cinfo = info->par;
zorro_release_device(cinfo->zdev);
if (cinfo->btype == BT_PICASSO4) {
cinfo->regbase -= 0x600000;
- iounmap ((void *)cinfo->regbase);
- iounmap ((void *)cinfo->fbmem);
+ iounmap((void *)cinfo->regbase);
+ iounmap(info->screen_base);
} else {
if (zorro_resource_start(cinfo->zdev) > 0x01000000)
- iounmap ((void *)cinfo->fbmem);
+ iounmap(info->screen_base);
}
- framebuffer_release(cinfo->info);
}
#endif /* CONFIG_ZORRO */
-static int cirrusfb_set_fbinfo(struct cirrusfb_info *cinfo)
+static int cirrusfb_set_fbinfo(struct fb_info *info)
{
- struct fb_info *info = cinfo->info;
+ struct cirrusfb_info *cinfo = info->par;
struct fb_var_screeninfo *var = &info->var;
- info->par = cinfo;
info->pseudo_palette = cinfo->pseudo_palette;
info->flags = FBINFO_DEFAULT
| FBINFO_HWACCEL_XPAN
@@ -2252,7 +2255,6 @@ static int cirrusfb_set_fbinfo(struct cirrusfb_info *cinfo)
if (noaccel)
info->flags |= FBINFO_HWACCEL_DISABLED;
info->fbops = &cirrusfb_ops;
- info->screen_base = cinfo->fbmem;
if (cinfo->btype == BT_GD5480) {
if (var->bits_per_pixel == 16)
info->screen_base += 1 * MB_;
@@ -2266,18 +2268,15 @@ static int cirrusfb_set_fbinfo(struct cirrusfb_info *cinfo)
/* monochrome: only 1 memory plane */
/* 8 bit and above: Use whole memory area */
- info->fix.smem_start = cinfo->fbmem_phys;
- info->fix.smem_len = (var->bits_per_pixel == 1) ? cinfo->size / 4 : cinfo->size;
- info->fix.type = cinfo->currentmode.type;
+ info->fix.smem_len = info->screen_size;
+ if (var->bits_per_pixel == 1)
+ info->fix.smem_len /= 4;
info->fix.type_aux = 0;
- info->fix.visual = cinfo->currentmode.visual;
info->fix.xpanstep = 1;
info->fix.ypanstep = 1;
info->fix.ywrapstep = 0;
- info->fix.line_length = cinfo->currentmode.line_length;
/* FIXME: map region at 0xB8000 if available, fill in here */
- info->fix.mmio_start = cinfo->fbregs_phys;
info->fix.mmio_len = 0;
info->fix.accel = FB_ACCEL_NONE;
@@ -2286,23 +2285,23 @@ static int cirrusfb_set_fbinfo(struct cirrusfb_info *cinfo)
return 0;
}
-static int cirrusfb_register(struct cirrusfb_info *cinfo)
+static int cirrusfb_register(struct fb_info *info)
{
- struct fb_info *info;
+ struct cirrusfb_info *cinfo = info->par;
int err;
- cirrusfb_board_t btype;
+ enum cirrus_board btype;
- DPRINTK ("ENTER\n");
+ DPRINTK("ENTER\n");
- printk (KERN_INFO "cirrusfb: Driver for Cirrus Logic based graphic boards, v" CIRRUSFB_VERSION "\n");
+ printk(KERN_INFO "cirrusfb: Driver for Cirrus Logic based "
+ "graphic boards, v" CIRRUSFB_VERSION "\n");
- info = cinfo->info;
btype = cinfo->btype;
/* sanity checks */
- assert (btype != BT_NONE);
+ assert(btype != BT_NONE);
- DPRINTK ("cirrusfb: (RAM start set to: 0x%p)\n", cinfo->fbmem);
+ DPRINTK("cirrusfb: (RAM start set to: 0x%p)\n", info->screen_base);
/* Make pretend we've set the var so our structures are in a "good" */
/* state, even though we haven't written the mode to the hw yet... */
@@ -2317,47 +2316,49 @@ static int cirrusfb_register(struct cirrusfb_info *cinfo)
}
/* set all the vital stuff */
- cirrusfb_set_fbinfo(cinfo);
+ cirrusfb_set_fbinfo(info);
err = register_framebuffer(info);
if (err < 0) {
- printk (KERN_ERR "cirrusfb: could not register fb device; err = %d!\n", err);
+ printk(KERN_ERR "cirrusfb: could not register "
+ "fb device; err = %d!\n", err);
goto err_dealloc_cmap;
}
- DPRINTK ("EXIT, returning 0\n");
+ DPRINTK("EXIT, returning 0\n");
return 0;
err_dealloc_cmap:
fb_dealloc_cmap(&info->cmap);
err_unmap_cirrusfb:
- cinfo->unmap(cinfo);
+ cinfo->unmap(info);
+ framebuffer_release(info);
return err;
}
-static void __devexit cirrusfb_cleanup (struct fb_info *info)
+static void __devexit cirrusfb_cleanup(struct fb_info *info)
{
struct cirrusfb_info *cinfo = info->par;
- DPRINTK ("ENTER\n");
+ DPRINTK("ENTER\n");
- switch_monitor (cinfo, 0);
+ switch_monitor(cinfo, 0);
- unregister_framebuffer (info);
- fb_dealloc_cmap (&info->cmap);
- printk ("Framebuffer unregistered\n");
- cinfo->unmap(cinfo);
+ unregister_framebuffer(info);
+ fb_dealloc_cmap(&info->cmap);
+ printk("Framebuffer unregistered\n");
+ cinfo->unmap(info);
+ framebuffer_release(info);
- DPRINTK ("EXIT\n");
+ DPRINTK("EXIT\n");
}
-
#ifdef CONFIG_PCI
-static int cirrusfb_pci_register (struct pci_dev *pdev,
+static int cirrusfb_pci_register(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct cirrusfb_info *cinfo;
struct fb_info *info;
- cirrusfb_board_t btype;
+ enum cirrus_board btype;
unsigned long board_addr, board_size;
int ret;
@@ -2375,35 +2376,37 @@ static int cirrusfb_pci_register (struct pci_dev *pdev,
}
cinfo = info->par;
- cinfo->info = info;
cinfo->pdev = pdev;
- cinfo->btype = btype = (cirrusfb_board_t) ent->driver_data;
+ cinfo->btype = btype = (enum cirrus_board) ent->driver_data;
- DPRINTK (" Found PCI device, base address 0 is 0x%lx, btype set to %d\n",
+ DPRINTK(" Found PCI device, base address 0 is 0x%x, btype set to %d\n",
pdev->resource[0].start, btype);
- DPRINTK (" base address 1 is 0x%lx\n", pdev->resource[1].start);
+ DPRINTK(" base address 1 is 0x%x\n", pdev->resource[1].start);
- if(isPReP) {
- pci_write_config_dword (pdev, PCI_BASE_ADDRESS_0, 0x00000000);
+ if (isPReP) {
+ pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, 0x00000000);
#ifdef CONFIG_PPC_PREP
- get_prep_addrs (&board_addr, &cinfo->fbregs_phys);
+ get_prep_addrs(&board_addr, &info->fix.mmio_start);
#endif
- /* PReP dies if we ioremap the IO registers, but it works w/out... */
- cinfo->regbase = (char __iomem *) cinfo->fbregs_phys;
+ /* PReP dies if we ioremap the IO registers, but it works w/out... */
+ cinfo->regbase = (char __iomem *) info->fix.mmio_start;
} else {
- DPRINTK ("Attempt to get PCI info for Cirrus Graphics Card\n");
- get_pci_addrs (pdev, &board_addr, &cinfo->fbregs_phys);
- cinfo->regbase = NULL; /* FIXME: this forces VGA. alternatives? */
+ DPRINTK("Attempt to get PCI info for Cirrus Graphics Card\n");
+ get_pci_addrs(pdev, &board_addr, &info->fix.mmio_start);
+ /* FIXME: this forces VGA. alternatives? */
+ cinfo->regbase = NULL;
}
- DPRINTK ("Board address: 0x%lx, register address: 0x%lx\n", board_addr, cinfo->fbregs_phys);
+ DPRINTK("Board address: 0x%lx, register address: 0x%lx\n",
+ board_addr, info->fix.mmio_start);
board_size = (btype == BT_GD5480) ?
- 32 * MB_ : cirrusfb_get_memsize (cinfo->regbase);
+ 32 * MB_ : cirrusfb_get_memsize(cinfo->regbase);
ret = pci_request_regions(pdev, "cirrusfb");
- if (ret <0) {
- printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, abort\n",
+ if (ret < 0) {
+ printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, "
+ "abort\n",
board_addr);
goto err_release_fb;
}
@@ -2419,23 +2422,24 @@ static int cirrusfb_pci_register (struct pci_dev *pdev,
if (request_region(0x3C0, 32, "cirrusfb"))
release_io_ports = 1;
- cinfo->fbmem = ioremap(board_addr, board_size);
- if (!cinfo->fbmem) {
+ info->screen_base = ioremap(board_addr, board_size);
+ if (!info->screen_base) {
ret = -EIO;
goto err_release_legacy;
}
- cinfo->fbmem_phys = board_addr;
- cinfo->size = board_size;
+ info->fix.smem_start = board_addr;
+ info->screen_size = board_size;
cinfo->unmap = cirrusfb_pci_unmap;
- printk (" RAM (%lu kB) at 0xx%lx, ", cinfo->size / KB_, board_addr);
- printk ("Cirrus Logic chipset on PCI bus\n");
+ printk(KERN_INFO " RAM (%lu kB) at 0xx%lx, ",
+ info->screen_size >> 10, board_addr);
+ printk(KERN_INFO "Cirrus Logic chipset on PCI bus\n");
pci_set_drvdata(pdev, info);
- ret = cirrusfb_register(cinfo);
+ ret = cirrusfb_register(info);
if (ret)
- iounmap(cinfo->fbmem);
+ iounmap(info->screen_base);
return ret;
err_release_legacy:
@@ -2453,14 +2457,14 @@ err_out:
return ret;
}
-static void __devexit cirrusfb_pci_unregister (struct pci_dev *pdev)
+static void __devexit cirrusfb_pci_unregister(struct pci_dev *pdev)
{
struct fb_info *info = pci_get_drvdata(pdev);
- DPRINTK ("ENTER\n");
+ DPRINTK("ENTER\n");
- cirrusfb_cleanup (info);
+ cirrusfb_cleanup(info);
- DPRINTK ("EXIT\n");
+ DPRINTK("EXIT\n");
}
static struct pci_driver cirrusfb_pci_driver = {
@@ -2477,14 +2481,13 @@ static struct pci_driver cirrusfb_pci_driver = {
};
#endif /* CONFIG_PCI */
-
#ifdef CONFIG_ZORRO
static int cirrusfb_zorro_register(struct zorro_dev *z,
const struct zorro_device_id *ent)
{
struct cirrusfb_info *cinfo;
struct fb_info *info;
- cirrusfb_board_t btype;
+ enum cirrus_board btype;
struct zorro_dev *z2 = NULL;
unsigned long board_addr, board_size, size;
int ret;
@@ -2498,83 +2501,85 @@ static int cirrusfb_zorro_register(struct zorro_dev *z,
info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev);
if (!info) {
- printk (KERN_ERR "cirrusfb: could not allocate memory\n");
+ printk(KERN_ERR "cirrusfb: could not allocate memory\n");
ret = -ENOMEM;
goto err_out;
}
cinfo = info->par;
- cinfo->info = info;
cinfo->btype = btype;
- assert (z > 0);
- assert (z2 >= 0);
- assert (btype != BT_NONE);
+ assert(z);
+ assert(btype != BT_NONE);
cinfo->zdev = z;
board_addr = zorro_resource_start(z);
board_size = zorro_resource_len(z);
- cinfo->size = size;
+ info->screen_size = size;
if (!zorro_request_device(z, "cirrusfb")) {
- printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, abort\n",
+ printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, "
+ "abort\n",
board_addr);
ret = -EBUSY;
goto err_release_fb;
}
- printk (" RAM (%lu MB) at $%lx, ", board_size / MB_, board_addr);
+ printk(" RAM (%lu MB) at $%lx, ", board_size / MB_, board_addr);
ret = -EIO;
if (btype == BT_PICASSO4) {
- printk (" REG at $%lx\n", board_addr + 0x600000);
+ printk(KERN_INFO " REG at $%lx\n", board_addr + 0x600000);
/* To be precise, for the P4 this is not the */
/* begin of the board, but the begin of RAM. */
/* for P4, map in its address space in 2 chunks (### TEST! ) */
/* (note the ugly hardcoded 16M number) */
- cinfo->regbase = ioremap (board_addr, 16777216);
+ cinfo->regbase = ioremap(board_addr, 16777216);
if (!cinfo->regbase)
goto err_release_region;
- DPRINTK ("cirrusfb: Virtual address for board set to: $%p\n", cinfo->regbase);
+ DPRINTK("cirrusfb: Virtual address for board set to: $%p\n",
+ cinfo->regbase);
cinfo->regbase += 0x600000;
- cinfo->fbregs_phys = board_addr + 0x600000;
+ info->fix.mmio_start = board_addr + 0x600000;
- cinfo->fbmem_phys = board_addr + 16777216;
- cinfo->fbmem = ioremap (cinfo->fbmem_phys, 16777216);
- if (!cinfo->fbmem)
+ info->fix.smem_start = board_addr + 16777216;
+ info->screen_base = ioremap(info->fix.smem_start, 16777216);
+ if (!info->screen_base)
goto err_unmap_regbase;
} else {
- printk (" REG at $%lx\n", (unsigned long) z2->resource.start);
+ printk(KERN_INFO " REG at $%lx\n",
+ (unsigned long) z2->resource.start);
- cinfo->fbmem_phys = board_addr;
+ info->fix.smem_start = board_addr;
if (board_addr > 0x01000000)
- cinfo->fbmem = ioremap (board_addr, board_size);
+ info->screen_base = ioremap(board_addr, board_size);
else
- cinfo->fbmem = (caddr_t) ZTWO_VADDR (board_addr);
- if (!cinfo->fbmem)
+ info->screen_base = (caddr_t) ZTWO_VADDR(board_addr);
+ if (!info->screen_base)
goto err_release_region;
/* set address for REG area of board */
- cinfo->regbase = (caddr_t) ZTWO_VADDR (z2->resource.start);
- cinfo->fbregs_phys = z2->resource.start;
+ cinfo->regbase = (caddr_t) ZTWO_VADDR(z2->resource.start);
+ info->fix.mmio_start = z2->resource.start;
- DPRINTK ("cirrusfb: Virtual address for board set to: $%p\n", cinfo->regbase);
+ DPRINTK("cirrusfb: Virtual address for board set to: $%p\n",
+ cinfo->regbase);
}
cinfo->unmap = cirrusfb_zorro_unmap;
- printk (KERN_INFO "Cirrus Logic chipset on Zorro bus\n");
+ printk(KERN_INFO "Cirrus Logic chipset on Zorro bus\n");
zorro_set_drvdata(z, info);
- ret = cirrusfb_register(cinfo);
+ ret = cirrusfb_register(info);
if (ret) {
if (btype == BT_PICASSO4) {
- iounmap(cinfo->fbmem);
+ iounmap(info->screen_base);
iounmap(cinfo->regbase - 0x600000);
} else if (board_addr > 0x01000000)
- iounmap(cinfo->fbmem);
+ iounmap(info->screen_base);
}
return ret;
@@ -2592,11 +2597,11 @@ err_out:
void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z)
{
struct fb_info *info = zorro_get_drvdata(z);
- DPRINTK ("ENTER\n");
+ DPRINTK("ENTER\n");
- cirrusfb_cleanup (info);
+ cirrusfb_cleanup(info);
- DPRINTK ("EXIT\n");
+ DPRINTK("EXIT\n");
}
static struct zorro_driver cirrusfb_zorro_driver = {
@@ -2628,26 +2633,24 @@ static int __init cirrusfb_init(void)
return error;
}
-
-
#ifndef MODULE
static int __init cirrusfb_setup(char *options) {
char *this_opt, s[32];
int i;
- DPRINTK ("ENTER\n");
+ DPRINTK("ENTER\n");
if (!options || !*options)
return 0;
- while ((this_opt = strsep (&options, ",")) != NULL) {
+ while ((this_opt = strsep(&options, ",")) != NULL) {
if (!*this_opt) continue;
DPRINTK("cirrusfb_setup: option '%s'\n", this_opt);
for (i = 0; i < NUM_TOTAL_MODES; i++) {
- sprintf (s, "mode:%s", cirrusfb_predefined[i].name);
- if (strcmp (this_opt, s) == 0)
+ sprintf(s, "mode:%s", cirrusfb_predefined[i].name);
+ if (strcmp(this_opt, s) == 0)
cirrusfb_def_mode = i;
}
if (!strcmp(this_opt, "noaccel"))
@@ -2657,7 +2660,6 @@ static int __init cirrusfb_setup(char *options) {
}
#endif
-
/*
* Modularization
*/
@@ -2666,7 +2668,7 @@ MODULE_AUTHOR("Copyright 1999,2000 Jeff Garzik <jgarzik@pobox.com>");
MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips");
MODULE_LICENSE("GPL");
-static void __exit cirrusfb_exit (void)
+static void __exit cirrusfb_exit(void)
{
#ifdef CONFIG_PCI
pci_unregister_driver(&cirrusfb_pci_driver);
@@ -2682,66 +2684,67 @@ module_init(cirrusfb_init);
module_exit(cirrusfb_exit);
#endif
-
/**********************************************************************/
/* about the following functions - I have used the same names for the */
/* functions as Markus Wild did in his Retina driver for NetBSD as */
/* they just made sense for this purpose. Apart from that, I wrote */
-/* these functions myself. */
+/* these functions myself. */
/**********************************************************************/
/*** WGen() - write into one of the external/general registers ***/
-static void WGen (const struct cirrusfb_info *cinfo,
+static void WGen(const struct cirrusfb_info *cinfo,
int regnum, unsigned char val)
{
unsigned long regofs = 0;
if (cinfo->btype == BT_PICASSO) {
/* Picasso II specific hack */
-/* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D || regnum == CL_VSSM2) */
+/* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
+ regnum == CL_VSSM2) */
if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
regofs = 0xfff;
}
- vga_w (cinfo->regbase, regofs + regnum, val);
+ vga_w(cinfo->regbase, regofs + regnum, val);
}
/*** RGen() - read out one of the external/general registers ***/
-static unsigned char RGen (const struct cirrusfb_info *cinfo, int regnum)
+static unsigned char RGen(const struct cirrusfb_info *cinfo, int regnum)
{
unsigned long regofs = 0;
if (cinfo->btype == BT_PICASSO) {
/* Picasso II specific hack */
-/* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D || regnum == CL_VSSM2) */
+/* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
+ regnum == CL_VSSM2) */
if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
regofs = 0xfff;
}
- return vga_r (cinfo->regbase, regofs + regnum);
+ return vga_r(cinfo->regbase, regofs + regnum);
}
/*** AttrOn() - turn on VideoEnable for Attribute controller ***/
-static void AttrOn (const struct cirrusfb_info *cinfo)
+static void AttrOn(const struct cirrusfb_info *cinfo)
{
- assert (cinfo != NULL);
+ assert(cinfo != NULL);
- DPRINTK ("ENTER\n");
+ DPRINTK("ENTER\n");
- if (vga_rcrt (cinfo->regbase, CL_CRT24) & 0x80) {
+ if (vga_rcrt(cinfo->regbase, CL_CRT24) & 0x80) {
/* if we're just in "write value" mode, write back the */
/* same value as before to not modify anything */
- vga_w (cinfo->regbase, VGA_ATT_IW,
- vga_r (cinfo->regbase, VGA_ATT_R));
+ vga_w(cinfo->regbase, VGA_ATT_IW,
+ vga_r(cinfo->regbase, VGA_ATT_R));
}
/* turn on video bit */
-/* vga_w (cinfo->regbase, VGA_ATT_IW, 0x20); */
- vga_w (cinfo->regbase, VGA_ATT_IW, 0x33);
+/* vga_w(cinfo->regbase, VGA_ATT_IW, 0x20); */
+ vga_w(cinfo->regbase, VGA_ATT_IW, 0x33);
/* dummy write on Reg0 to be on "write index" mode next time */
- vga_w (cinfo->regbase, VGA_ATT_IW, 0x00);
+ vga_w(cinfo->regbase, VGA_ATT_IW, 0x00);
- DPRINTK ("EXIT\n");
+ DPRINTK("EXIT\n");
}
/*** WHDR() - write into the Hidden DAC register ***/
@@ -2750,119 +2753,115 @@ static void AttrOn (const struct cirrusfb_info *cinfo)
* registers of their functional group) here is a specialized routine for
* accessing the HDR
*/
-static void WHDR (const struct cirrusfb_info *cinfo, unsigned char val)
+static void WHDR(const struct cirrusfb_info *cinfo, unsigned char val)
{
unsigned char dummy;
if (cinfo->btype == BT_PICASSO) {
/* Klaus' hint for correct access to HDR on some boards */
/* first write 0 to pixel mask (3c6) */
- WGen (cinfo, VGA_PEL_MSK, 0x00);
- udelay (200);
+ WGen(cinfo, VGA_PEL_MSK, 0x00);
+ udelay(200);
/* next read dummy from pixel address (3c8) */
- dummy = RGen (cinfo, VGA_PEL_IW);
- udelay (200);
+ dummy = RGen(cinfo, VGA_PEL_IW);
+ udelay(200);
}
/* now do the usual stuff to access the HDR */
- dummy = RGen (cinfo, VGA_PEL_MSK);
- udelay (200);
- dummy = RGen (cinfo, VGA_PEL_MSK);
- udelay (200);
- dummy = RGen (cinfo, VGA_PEL_MSK);
- udelay (200);
- dummy = RGen (cinfo, VGA_PEL_MSK);
- udelay (200);
+ dummy = RGen(cinfo, VGA_PEL_MSK);
+ udelay(200);
+ dummy = RGen(cinfo, VGA_PEL_MSK);
+ udelay(200);
+ dummy = RGen(cinfo, VGA_PEL_MSK);
+ udelay(200);
+ dummy = RGen(cinfo, VGA_PEL_MSK);
+ udelay(200);
- WGen (cinfo, VGA_PEL_MSK, val);
- udelay (200);
+ WGen(cinfo, VGA_PEL_MSK, val);
+ udelay(200);
if (cinfo->btype == BT_PICASSO) {
/* now first reset HDR access counter */
- dummy = RGen (cinfo, VGA_PEL_IW);
- udelay (200);
+ dummy = RGen(cinfo, VGA_PEL_IW);
+ udelay(200);
/* and at the end, restore the mask value */
/* ## is this mask always 0xff? */
- WGen (cinfo, VGA_PEL_MSK, 0xff);
- udelay (200);
+ WGen(cinfo, VGA_PEL_MSK, 0xff);
+ udelay(200);
}
}
-
/*** WSFR() - write to the "special function register" (SFR) ***/
-static void WSFR (struct cirrusfb_info *cinfo, unsigned char val)
+static void WSFR(struct cirrusfb_info *cinfo, unsigned char val)
{
#ifdef CONFIG_ZORRO
- assert (cinfo->regbase != NULL);
+ assert(cinfo->regbase != NULL);
cinfo->SFR = val;
- z_writeb (val, cinfo->regbase + 0x8000);
+ z_writeb(val, cinfo->regbase + 0x8000);
#endif
}
/* The Picasso has a second register for switching the monitor bit */
-static void WSFR2 (struct cirrusfb_info *cinfo, unsigned char val)
+static void WSFR2(struct cirrusfb_info *cinfo, unsigned char val)
{
#ifdef CONFIG_ZORRO
/* writing an arbitrary value to this one causes the monitor switcher */
/* to flip to Amiga display */
- assert (cinfo->regbase != NULL);
+ assert(cinfo->regbase != NULL);
cinfo->SFR = val;
- z_writeb (val, cinfo->regbase + 0x9000);
+ z_writeb(val, cinfo->regbase + 0x9000);
#endif
}
-
/*** WClut - set CLUT entry (range: 0..63) ***/
-static void WClut (struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char red,
+static void WClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char red,
unsigned char green, unsigned char blue)
{
unsigned int data = VGA_PEL_D;
/* address write mode register is not translated.. */
- vga_w (cinfo->regbase, VGA_PEL_IW, regnum);
+ vga_w(cinfo->regbase, VGA_PEL_IW, regnum);
if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) {
/* but DAC data register IS, at least for Picasso II */
if (cinfo->btype == BT_PICASSO)
data += 0xfff;
- vga_w (cinfo->regbase, data, red);
- vga_w (cinfo->regbase, data, green);
- vga_w (cinfo->regbase, data, blue);
+ vga_w(cinfo->regbase, data, red);
+ vga_w(cinfo->regbase, data, green);
+ vga_w(cinfo->regbase, data, blue);
} else {
- vga_w (cinfo->regbase, data, blue);
- vga_w (cinfo->regbase, data, green);
- vga_w (cinfo->regbase, data, red);
+ vga_w(cinfo->regbase, data, blue);
+ vga_w(cinfo->regbase, data, green);
+ vga_w(cinfo->regbase, data, red);
}
}
-
#if 0
/*** RClut - read CLUT entry (range 0..63) ***/
-static void RClut (struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char *red,
+static void RClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char *red,
unsigned char *green, unsigned char *blue)
{
unsigned int data = VGA_PEL_D;
- vga_w (cinfo->regbase, VGA_PEL_IR, regnum);
+ vga_w(cinfo->regbase, VGA_PEL_IR, regnum);
if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) {
if (cinfo->btype == BT_PICASSO)
data += 0xfff;
- *red = vga_r (cinfo->regbase, data);
- *green = vga_r (cinfo->regbase, data);
- *blue = vga_r (cinfo->regbase, data);
+ *red = vga_r(cinfo->regbase, data);
+ *green = vga_r(cinfo->regbase, data);
+ *blue = vga_r(cinfo->regbase, data);
} else {
- *blue = vga_r (cinfo->regbase, data);
- *green = vga_r (cinfo->regbase, data);
- *red = vga_r (cinfo->regbase, data);
+ *blue = vga_r(cinfo->regbase, data);
+ *green = vga_r(cinfo->regbase, data);
+ *red = vga_r(cinfo->regbase, data);
}
}
#endif
-
/*******************************************************************
cirrusfb_WaitBLT()
@@ -2870,10 +2869,10 @@ static void RClut (struct cirrusfb_info *cinfo, unsigned char regnum, unsigned c
*********************************************************************/
/* FIXME: use interrupts instead */
-static void cirrusfb_WaitBLT (u8 __iomem *regbase)
+static void cirrusfb_WaitBLT(u8 __iomem *regbase)
{
/* now busy-wait until we're done */
- while (vga_rgfx (regbase, CL_GR31) & 0x08)
+ while (vga_rgfx(regbase, CL_GR31) & 0x08)
/* do nothing */ ;
}
@@ -2883,15 +2882,17 @@ static void cirrusfb_WaitBLT (u8 __iomem *regbase)
perform accelerated "scrolling"
********************************************************************/
-static void cirrusfb_BitBLT (u8 __iomem *regbase, int bits_per_pixel,
- u_short curx, u_short cury, u_short destx, u_short desty,
- u_short width, u_short height, u_short line_length)
+static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel,
+ u_short curx, u_short cury,
+ u_short destx, u_short desty,
+ u_short width, u_short height,
+ u_short line_length)
{
u_short nwidth, nheight;
u_long nsrc, ndest;
u_char bltmode;
- DPRINTK ("ENTER\n");
+ DPRINTK("ENTER\n");
nwidth = width - 1;
nheight = height - 1;
@@ -2911,9 +2912,13 @@ static void cirrusfb_BitBLT (u8 __iomem *regbase, int bits_per_pixel,
nsrc = (cury * line_length) + curx;
ndest = (desty * line_length) + destx;
} else {
- /* this means start addresses are at the end, counting backwards */
- nsrc = cury * line_length + curx + nheight * line_length + nwidth;
- ndest = desty * line_length + destx + nheight * line_length + nwidth;
+ /* this means start addresses are at the end,
+ * counting backwards
+ */
+ nsrc = cury * line_length + curx +
+ nheight * line_length + nwidth;
+ ndest = desty * line_length + destx +
+ nheight * line_length + nwidth;
}
/*
@@ -2929,52 +2934,65 @@ static void cirrusfb_BitBLT (u8 __iomem *regbase, int bits_per_pixel,
start/stop
*/
- cirrusfb_WaitBLT(regbase);
+ cirrusfb_WaitBLT(regbase);
/* pitch: set to line_length */
- vga_wgfx (regbase, CL_GR24, line_length & 0xff); /* dest pitch low */
- vga_wgfx (regbase, CL_GR25, (line_length >> 8)); /* dest pitch hi */
- vga_wgfx (regbase, CL_GR26, line_length & 0xff); /* source pitch low */
- vga_wgfx (regbase, CL_GR27, (line_length >> 8)); /* source pitch hi */
+ /* dest pitch low */
+ vga_wgfx(regbase, CL_GR24, line_length & 0xff);
+ /* dest pitch hi */
+ vga_wgfx(regbase, CL_GR25, line_length >> 8);
+ /* source pitch low */
+ vga_wgfx(regbase, CL_GR26, line_length & 0xff);
+ /* source pitch hi */
+ vga_wgfx(regbase, CL_GR27, line_length >> 8);
/* BLT width: actual number of pixels - 1 */
- vga_wgfx (regbase, CL_GR20, nwidth & 0xff); /* BLT width low */
- vga_wgfx (regbase, CL_GR21, (nwidth >> 8)); /* BLT width hi */
+ /* BLT width low */
+ vga_wgfx(regbase, CL_GR20, nwidth & 0xff);
+ /* BLT width hi */
+ vga_wgfx(regbase, CL_GR21, nwidth >> 8);
/* BLT height: actual number of lines -1 */
- vga_wgfx (regbase, CL_GR22, nheight & 0xff); /* BLT height low */
- vga_wgfx (regbase, CL_GR23, (nheight >> 8)); /* BLT width hi */
+ /* BLT height low */
+ vga_wgfx(regbase, CL_GR22, nheight & 0xff);
+ /* BLT width hi */
+ vga_wgfx(regbase, CL_GR23, nheight >> 8);
/* BLT destination */
- vga_wgfx (regbase, CL_GR28, (u_char) (ndest & 0xff)); /* BLT dest low */
- vga_wgfx (regbase, CL_GR29, (u_char) (ndest >> 8)); /* BLT dest mid */
- vga_wgfx (regbase, CL_GR2A, (u_char) (ndest >> 16)); /* BLT dest hi */
+ /* BLT dest low */
+ vga_wgfx(regbase, CL_GR28, (u_char) (ndest & 0xff));
+ /* BLT dest mid */
+ vga_wgfx(regbase, CL_GR29, (u_char) (ndest >> 8));
+ /* BLT dest hi */
+ vga_wgfx(regbase, CL_GR2A, (u_char) (ndest >> 16));
/* BLT source */
- vga_wgfx (regbase, CL_GR2C, (u_char) (nsrc & 0xff)); /* BLT src low */
- vga_wgfx (regbase, CL_GR2D, (u_char) (nsrc >> 8)); /* BLT src mid */
- vga_wgfx (regbase, CL_GR2E, (u_char) (nsrc >> 16)); /* BLT src hi */
+ /* BLT src low */
+ vga_wgfx(regbase, CL_GR2C, (u_char) (nsrc & 0xff));
+ /* BLT src mid */
+ vga_wgfx(regbase, CL_GR2D, (u_char) (nsrc >> 8));
+ /* BLT src hi */
+ vga_wgfx(regbase, CL_GR2E, (u_char) (nsrc >> 16));
/* BLT mode */
- vga_wgfx (regbase, CL_GR30, bltmode); /* BLT mode */
+ vga_wgfx(regbase, CL_GR30, bltmode); /* BLT mode */
/* BLT ROP: SrcCopy */
- vga_wgfx (regbase, CL_GR32, 0x0d); /* BLT ROP */
+ vga_wgfx(regbase, CL_GR32, 0x0d); /* BLT ROP */
/* and finally: GO! */
- vga_wgfx (regbase, CL_GR31, 0x02); /* BLT Start/status */
+ vga_wgfx(regbase, CL_GR31, 0x02); /* BLT Start/status */
- DPRINTK ("EXIT\n");
+ DPRINTK("EXIT\n");
}
-
/*******************************************************************
cirrusfb_RectFill()
perform accelerated rectangle fill
********************************************************************/
-static void cirrusfb_RectFill (u8 __iomem *regbase, int bits_per_pixel,
+static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
u_short x, u_short y, u_short width, u_short height,
u_char color, u_short line_length)
{
@@ -2982,93 +3000,95 @@ static void cirrusfb_RectFill (u8 __iomem *regbase, int bits_per_pixel,
u_long ndest;
u_char op;
- DPRINTK ("ENTER\n");
+ DPRINTK("ENTER\n");
nwidth = width - 1;
nheight = height - 1;
ndest = (y * line_length) + x;
- cirrusfb_WaitBLT(regbase);
+ cirrusfb_WaitBLT(regbase);
/* pitch: set to line_length */
- vga_wgfx (regbase, CL_GR24, line_length & 0xff); /* dest pitch low */
- vga_wgfx (regbase, CL_GR25, (line_length >> 8)); /* dest pitch hi */
- vga_wgfx (regbase, CL_GR26, line_length & 0xff); /* source pitch low */
- vga_wgfx (regbase, CL_GR27, (line_length >> 8)); /* source pitch hi */
+ vga_wgfx(regbase, CL_GR24, line_length & 0xff); /* dest pitch low */
+ vga_wgfx(regbase, CL_GR25, line_length >> 8); /* dest pitch hi */
+ vga_wgfx(regbase, CL_GR26, line_length & 0xff); /* source pitch low */
+ vga_wgfx(regbase, CL_GR27, line_length >> 8); /* source pitch hi */
/* BLT width: actual number of pixels - 1 */
- vga_wgfx (regbase, CL_GR20, nwidth & 0xff); /* BLT width low */
- vga_wgfx (regbase, CL_GR21, (nwidth >> 8)); /* BLT width hi */
+ vga_wgfx(regbase, CL_GR20, nwidth & 0xff); /* BLT width low */
+ vga_wgfx(regbase, CL_GR21, nwidth >> 8); /* BLT width hi */
/* BLT height: actual number of lines -1 */
- vga_wgfx (regbase, CL_GR22, nheight & 0xff); /* BLT height low */
- vga_wgfx (regbase, CL_GR23, (nheight >> 8)); /* BLT width hi */
+ vga_wgfx(regbase, CL_GR22, nheight & 0xff); /* BLT height low */
+ vga_wgfx(regbase, CL_GR23, nheight >> 8); /* BLT width hi */
/* BLT destination */
- vga_wgfx (regbase, CL_GR28, (u_char) (ndest & 0xff)); /* BLT dest low */
- vga_wgfx (regbase, CL_GR29, (u_char) (ndest >> 8)); /* BLT dest mid */
- vga_wgfx (regbase, CL_GR2A, (u_char) (ndest >> 16)); /* BLT dest hi */
+ /* BLT dest low */
+ vga_wgfx(regbase, CL_GR28, (u_char) (ndest & 0xff));
+ /* BLT dest mid */
+ vga_wgfx(regbase, CL_GR29, (u_char) (ndest >> 8));
+ /* BLT dest hi */
+ vga_wgfx(regbase, CL_GR2A, (u_char) (ndest >> 16));
/* BLT source: set to 0 (is a dummy here anyway) */
- vga_wgfx (regbase, CL_GR2C, 0x00); /* BLT src low */
- vga_wgfx (regbase, CL_GR2D, 0x00); /* BLT src mid */
- vga_wgfx (regbase, CL_GR2E, 0x00); /* BLT src hi */
+ vga_wgfx(regbase, CL_GR2C, 0x00); /* BLT src low */
+ vga_wgfx(regbase, CL_GR2D, 0x00); /* BLT src mid */
+ vga_wgfx(regbase, CL_GR2E, 0x00); /* BLT src hi */
/* This is a ColorExpand Blt, using the */
/* same color for foreground and background */
- vga_wgfx (regbase, VGA_GFX_SR_VALUE, color); /* foreground color */
- vga_wgfx (regbase, VGA_GFX_SR_ENABLE, color); /* background color */
+ vga_wgfx(regbase, VGA_GFX_SR_VALUE, color); /* foreground color */
+ vga_wgfx(regbase, VGA_GFX_SR_ENABLE, color); /* background color */
op = 0xc0;
if (bits_per_pixel == 16) {
- vga_wgfx (regbase, CL_GR10, color); /* foreground color */
- vga_wgfx (regbase, CL_GR11, color); /* background color */
+ vga_wgfx(regbase, CL_GR10, color); /* foreground color */
+ vga_wgfx(regbase, CL_GR11, color); /* background color */
op = 0x50;
op = 0xd0;
} else if (bits_per_pixel == 32) {
- vga_wgfx (regbase, CL_GR10, color); /* foreground color */
- vga_wgfx (regbase, CL_GR11, color); /* background color */
- vga_wgfx (regbase, CL_GR12, color); /* foreground color */
- vga_wgfx (regbase, CL_GR13, color); /* background color */
- vga_wgfx (regbase, CL_GR14, 0); /* foreground color */
- vga_wgfx (regbase, CL_GR15, 0); /* background color */
+ vga_wgfx(regbase, CL_GR10, color); /* foreground color */
+ vga_wgfx(regbase, CL_GR11, color); /* background color */
+ vga_wgfx(regbase, CL_GR12, color); /* foreground color */
+ vga_wgfx(regbase, CL_GR13, color); /* background color */
+ vga_wgfx(regbase, CL_GR14, 0); /* foreground color */
+ vga_wgfx(regbase, CL_GR15, 0); /* background color */
op = 0x50;
op = 0xf0;
}
/* BLT mode: color expand, Enable 8x8 copy (faster?) */
- vga_wgfx (regbase, CL_GR30, op); /* BLT mode */
+ vga_wgfx(regbase, CL_GR30, op); /* BLT mode */
/* BLT ROP: SrcCopy */
- vga_wgfx (regbase, CL_GR32, 0x0d); /* BLT ROP */
+ vga_wgfx(regbase, CL_GR32, 0x0d); /* BLT ROP */
/* and finally: GO! */
- vga_wgfx (regbase, CL_GR31, 0x02); /* BLT Start/status */
+ vga_wgfx(regbase, CL_GR31, 0x02); /* BLT Start/status */
- DPRINTK ("EXIT\n");
+ DPRINTK("EXIT\n");
}
-
/**************************************************************************
* bestclock() - determine closest possible clock lower(?) than the
* desired pixel clock
**************************************************************************/
-static void bestclock (long freq, long *best, long *nom,
+static void bestclock(long freq, long *best, long *nom,
long *den, long *div, long maxfreq)
{
long n, h, d, f;
- assert (best != NULL);
- assert (nom != NULL);
- assert (den != NULL);
- assert (div != NULL);
- assert (maxfreq > 0);
+ assert(best != NULL);
+ assert(nom != NULL);
+ assert(den != NULL);
+ assert(div != NULL);
+ assert(maxfreq > 0);
*nom = 0;
*den = 0;
*div = 0;
- DPRINTK ("ENTER\n");
+ DPRINTK("ENTER\n");
if (freq < 8000)
freq = 8000;
@@ -3085,7 +3105,7 @@ static void bestclock (long freq, long *best, long *nom,
if (d > 31)
d = (d / 2) * 2;
h = (14318 * n) / d;
- if (abs (h - freq) < abs (*best - freq)) {
+ if (abs(h - freq) < abs(*best - freq)) {
*best = h;
*nom = n;
if (d < 32) {
@@ -3102,7 +3122,7 @@ static void bestclock (long freq, long *best, long *nom,
if (d > 31)
d = (d / 2) * 2;
h = (14318 * n) / d;
- if (abs (h - freq) < abs (*best - freq)) {
+ if (abs(h - freq) < abs(*best - freq)) {
*best = h;
*nom = n;
if (d < 32) {
@@ -3116,14 +3136,13 @@ static void bestclock (long freq, long *best, long *nom,
}
}
- DPRINTK ("Best possible values for given frequency:\n");
- DPRINTK (" best: %ld kHz nom: %ld den: %ld div: %ld\n",
- freq, *nom, *den, *div);
+ DPRINTK("Best possible values for given frequency:\n");
+ DPRINTK(" best: %ld kHz nom: %ld den: %ld div: %ld\n",
+ freq, *nom, *den, *div);
- DPRINTK ("EXIT\n");
+ DPRINTK("EXIT\n");
}
-
/* -------------------------------------------------------------------------
*
* debugging functions
@@ -3145,21 +3164,20 @@ static void bestclock (long freq, long *best, long *nom,
*/
static
-void cirrusfb_dbg_print_byte (const char *name, unsigned char val)
+void cirrusfb_dbg_print_byte(const char *name, unsigned char val)
{
- DPRINTK ("%8s = 0x%02X (bits 7-0: %c%c%c%c%c%c%c%c)\n",
- name, val,
- val & 0x80 ? '1' : '0',
- val & 0x40 ? '1' : '0',
- val & 0x20 ? '1' : '0',
- val & 0x10 ? '1' : '0',
- val & 0x08 ? '1' : '0',
- val & 0x04 ? '1' : '0',
- val & 0x02 ? '1' : '0',
- val & 0x01 ? '1' : '0');
+ DPRINTK("%8s = 0x%02X (bits 7-0: %c%c%c%c%c%c%c%c)\n",
+ name, val,
+ val & 0x80 ? '1' : '0',
+ val & 0x40 ? '1' : '0',
+ val & 0x20 ? '1' : '0',
+ val & 0x10 ? '1' : '0',
+ val & 0x08 ? '1' : '0',
+ val & 0x04 ? '1' : '0',
+ val & 0x02 ? '1' : '0',
+ val & 0x01 ? '1' : '0');
}
-
/**
* cirrusfb_dbg_print_regs
* @base: If using newmmio, the newmmio base address, otherwise %NULL
@@ -3172,25 +3190,26 @@ void cirrusfb_dbg_print_byte (const char *name, unsigned char val)
*/
static
-void cirrusfb_dbg_print_regs (caddr_t regbase, cirrusfb_dbg_reg_class_t reg_class,...)
+void cirrusfb_dbg_print_regs(caddr_t regbase,
+ enum cirrusfb_dbg_reg_class reg_class, ...)
{
va_list list;
unsigned char val = 0;
unsigned reg;
char *name;
- va_start (list, reg_class);
+ va_start(list, reg_class);
- name = va_arg (list, char *);
+ name = va_arg(list, char *);
while (name != NULL) {
- reg = va_arg (list, int);
+ reg = va_arg(list, int);
switch (reg_class) {
case CRT:
- val = vga_rcrt (regbase, (unsigned char) reg);
+ val = vga_rcrt(regbase, (unsigned char) reg);
break;
case SEQ:
- val = vga_rseq (regbase, (unsigned char) reg);
+ val = vga_rseq(regbase, (unsigned char) reg);
break;
default:
/* should never occur */
@@ -3198,15 +3217,14 @@ void cirrusfb_dbg_print_regs (caddr_t regbase, cirrusfb_dbg_reg_class_t reg_clas
break;
}
- cirrusfb_dbg_print_byte (name, val);
+ cirrusfb_dbg_print_byte(name, val);
- name = va_arg (list, char *);
+ name = va_arg(list, char *);
}
- va_end (list);
+ va_end(list);
}
-
/**
* cirrusfb_dump
* @cirrusfbinfo:
@@ -3214,13 +3232,11 @@ void cirrusfb_dbg_print_regs (caddr_t regbase, cirrusfb_dbg_reg_class_t reg_clas
* DESCRIPTION:
*/
-static
-void cirrusfb_dump (void)
+static void cirrusfb_dump(void)
{
- cirrusfb_dbg_reg_dump (NULL);
+ cirrusfb_dbg_reg_dump(NULL);
}
-
/**
* cirrusfb_dbg_reg_dump
* @base: If using newmmio, the newmmio base address, otherwise %NULL
@@ -3232,11 +3248,11 @@ void cirrusfb_dump (void)
*/
static
-void cirrusfb_dbg_reg_dump (caddr_t regbase)
+void cirrusfb_dbg_reg_dump(caddr_t regbase)
{
- DPRINTK ("CIRRUSFB VGA CRTC register dump:\n");
+ DPRINTK("CIRRUSFB VGA CRTC register dump:\n");
- cirrusfb_dbg_print_regs (regbase, CRT,
+ cirrusfb_dbg_print_regs(regbase, CRT,
"CR00", 0x00,
"CR01", 0x01,
"CR02", 0x02,
@@ -3286,11 +3302,11 @@ void cirrusfb_dbg_reg_dump (caddr_t regbase)
"CR3F", 0x3F,
NULL);
- DPRINTK ("\n");
+ DPRINTK("\n");
- DPRINTK ("CIRRUSFB VGA SEQ register dump:\n");
+ DPRINTK("CIRRUSFB VGA SEQ register dump:\n");
- cirrusfb_dbg_print_regs (regbase, SEQ,
+ cirrusfb_dbg_print_regs(regbase, SEQ,
"SR00", 0x00,
"SR01", 0x01,
"SR02", 0x02,
@@ -3319,7 +3335,7 @@ void cirrusfb_dbg_reg_dump (caddr_t regbase)
"SR1F", 0x1F,
NULL);
- DPRINTK ("\n");
+ DPRINTK("\n");
}
#endif /* CIRRUSFB_DEBUG */
diff --git a/drivers/video/clps711xfb.c b/drivers/video/clps711xfb.c
index dea6579941b7..17b5267f44d7 100644
--- a/drivers/video/clps711xfb.c
+++ b/drivers/video/clps711xfb.c
@@ -29,7 +29,7 @@
#include <asm/hardware.h>
#include <asm/mach-types.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <asm/hardware/clps7111.h>
#include <asm/arch/syspld.h>
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index a22ccf9485a4..267422f66255 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -27,7 +27,7 @@ config VGACON_SOFT_SCROLLBACK
The scrollback buffer of the standard VGA console is located in
the VGA RAM. The size of this RAM is fixed and is quite small.
If you require a larger scrollback buffer, this can be placed in
- System RAM which is dynamically allocated during intialization.
+ System RAM which is dynamically allocated during initialization.
Placing the scrollback buffer in System RAM will slightly slow
down the console.
diff --git a/drivers/video/console/dummycon.c b/drivers/video/console/dummycon.c
index d9315d99445f..b63860f7beab 100644
--- a/drivers/video/console/dummycon.c
+++ b/drivers/video/console/dummycon.c
@@ -18,8 +18,8 @@
*/
#if defined(__arm__)
-#define DUMMY_COLUMNS ORIG_VIDEO_COLS
-#define DUMMY_ROWS ORIG_VIDEO_LINES
+#define DUMMY_COLUMNS screen_info.orig_video_cols
+#define DUMMY_ROWS screen_info.orig_video_lines
#elif defined(__hppa__)
/* set by Kconfig. Use 80x25 for 640x480 and 160x64 for 1280x1024 */
#define DUMMY_COLUMNS CONFIG_DUMMY_CONSOLE_COLUMNS
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index e58c87b3e3a0..0f32f4a00b2d 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -78,7 +78,6 @@
#include <asm/fb.h>
#include <asm/irq.h>
#include <asm/system.h>
-#include <asm/uaccess.h>
#ifdef CONFIG_ATARI
#include <asm/atariints.h>
#endif
@@ -2169,7 +2168,7 @@ static __inline__ void updatescrollmode(struct display *p,
}
static int fbcon_resize(struct vc_data *vc, unsigned int width,
- unsigned int height)
+ unsigned int height, unsigned int user)
{
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
struct fbcon_ops *ops = info->fbcon_par;
@@ -2406,7 +2405,7 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
update_screen(vc);
}
- if (fbcon_is_inactive(vc, info) ||
+ if (mode_switch || fbcon_is_inactive(vc, info) ||
ops->blank_state != FB_BLANK_UNBLANK)
fbcon_del_cursor_timer(info);
else
diff --git a/drivers/video/console/font_10x18.c b/drivers/video/console/font_10x18.c
index e6aa0eab5bb6..6be72bb218ee 100644
--- a/drivers/video/console/font_10x18.c
+++ b/drivers/video/console/font_10x18.c
@@ -5133,14 +5133,14 @@ static const unsigned char fontdata_10x18[FONTDATAMAX] = {
const struct font_desc font_10x18 = {
- FONT10x18_IDX,
- "10x18",
- 10,
- 18,
- fontdata_10x18,
+ .idx = FONT10x18_IDX,
+ .name = "10x18",
+ .width = 10,
+ .height = 18,
+ .data = fontdata_10x18,
#ifdef __sparc__
- 5
+ .pref = 5,
#else
- -1
+ .pref = -1,
#endif
};
diff --git a/drivers/video/console/font_6x11.c b/drivers/video/console/font_6x11.c
index 89976cd97494..46e86e67aa6a 100644
--- a/drivers/video/console/font_6x11.c
+++ b/drivers/video/console/font_6x11.c
@@ -3342,10 +3342,11 @@ static const unsigned char fontdata_6x11[FONTDATAMAX] = {
const struct font_desc font_vga_6x11 = {
- VGA6x11_IDX,
- "ProFont6x11",
- 6,
- 11,
- fontdata_6x11,
- -2000 /* Try avoiding this font if possible unless on MAC */
+ .idx = VGA6x11_IDX,
+ .name = "ProFont6x11",
+ .width = 6,
+ .height = 11,
+ .data = fontdata_6x11,
+ /* Try avoiding this font if possible unless on MAC */
+ .pref = -2000,
};
diff --git a/drivers/video/console/font_7x14.c b/drivers/video/console/font_7x14.c
index bbf116647397..3b7dbf9c060b 100644
--- a/drivers/video/console/font_7x14.c
+++ b/drivers/video/console/font_7x14.c
@@ -4109,10 +4109,10 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
const struct font_desc font_7x14 = {
- FONT7x14_IDX,
- "7x14",
- 7,
- 14,
- fontdata_7x14,
- 0
+ .idx = FONT7x14_IDX,
+ .name = "7x14",
+ .width = 7,
+ .height = 14,
+ .data = fontdata_7x14,
+ .pref = 0,
};
diff --git a/drivers/video/console/font_8x16.c b/drivers/video/console/font_8x16.c
index 74fe86f28ff4..00a0c67a5c7d 100644
--- a/drivers/video/console/font_8x16.c
+++ b/drivers/video/console/font_8x16.c
@@ -5,6 +5,7 @@
/**********************************************/
#include <linux/font.h>
+#include <linux/module.h>
#define FONTDATAMAX 4096
@@ -4622,10 +4623,11 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
const struct font_desc font_vga_8x16 = {
- VGA8x16_IDX,
- "VGA8x16",
- 8,
- 16,
- fontdata_8x16,
- 0
+ .idx = VGA8x16_IDX,
+ .name = "VGA8x16",
+ .width = 8,
+ .height = 16,
+ .data = fontdata_8x16,
+ .pref = 0,
};
+EXPORT_SYMBOL(font_vga_8x16);
diff --git a/drivers/video/console/font_8x8.c b/drivers/video/console/font_8x8.c
index 26199f8ee908..9f56efe2cee7 100644
--- a/drivers/video/console/font_8x8.c
+++ b/drivers/video/console/font_8x8.c
@@ -2574,10 +2574,10 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
const struct font_desc font_vga_8x8 = {
- VGA8x8_IDX,
- "VGA8x8",
- 8,
- 8,
- fontdata_8x8,
- 0
+ .idx = VGA8x8_IDX,
+ .name = "VGA8x8",
+ .width = 8,
+ .height = 8,
+ .data = fontdata_8x8,
+ .pref = 0,
};
diff --git a/drivers/video/console/font_acorn_8x8.c b/drivers/video/console/font_acorn_8x8.c
index 40f3d4eeb198..639e31ae1100 100644
--- a/drivers/video/console/font_acorn_8x8.c
+++ b/drivers/video/console/font_acorn_8x8.c
@@ -262,14 +262,14 @@ static const unsigned char acorndata_8x8[] = {
};
const struct font_desc font_acorn_8x8 = {
- ACORN8x8_IDX,
- "Acorn8x8",
- 8,
- 8,
- acorndata_8x8,
+ .idx = ACORN8x8_IDX,
+ .name = "Acorn8x8",
+ .width = 8,
+ .height = 8,
+ .data = acorndata_8x8,
#ifdef CONFIG_ARCH_ACORN
- 20
+ .pref = 20,
#else
- 0
+ .pref = 0,
#endif
};
diff --git a/drivers/video/console/font_mini_4x6.c b/drivers/video/console/font_mini_4x6.c
index d818234fdf11..a19a7f33133e 100644
--- a/drivers/video/console/font_mini_4x6.c
+++ b/drivers/video/console/font_mini_4x6.c
@@ -2148,11 +2148,11 @@ static const unsigned char fontdata_mini_4x6[FONTDATAMAX] = {
};
const struct font_desc font_mini_4x6 = {
- MINI4x6_IDX,
- "MINI4x6",
- 4,
- 6,
- fontdata_mini_4x6,
- 3
+ .idx = MINI4x6_IDX,
+ .name = "MINI4x6",
+ .width = 4,
+ .height = 6,
+ .data = fontdata_mini_4x6,
+ .pref = 3,
};
diff --git a/drivers/video/console/font_pearl_8x8.c b/drivers/video/console/font_pearl_8x8.c
index e646c88f55c7..dc6ad539ca4e 100644
--- a/drivers/video/console/font_pearl_8x8.c
+++ b/drivers/video/console/font_pearl_8x8.c
@@ -2578,10 +2578,10 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
};
const struct font_desc font_pearl_8x8 = {
- PEARL8x8_IDX,
- "PEARL8x8",
- 8,
- 8,
- fontdata_pearl8x8,
- 2
+ .idx = PEARL8x8_IDX,
+ .name = "PEARL8x8",
+ .width = 8,
+ .height = 8,
+ .data = fontdata_pearl8x8,
+ .pref = 2,
};
diff --git a/drivers/video/console/font_sun12x22.c b/drivers/video/console/font_sun12x22.c
index ab5eb93407b4..d3643853c33a 100644
--- a/drivers/video/console/font_sun12x22.c
+++ b/drivers/video/console/font_sun12x22.c
@@ -6152,14 +6152,14 @@ static const unsigned char fontdata_sun12x22[FONTDATAMAX] = {
const struct font_desc font_sun_12x22 = {
- SUN12x22_IDX,
- "SUN12x22",
- 12,
- 22,
- fontdata_sun12x22,
+ .idx = SUN12x22_IDX,
+ .name = "SUN12x22",
+ .width = 12,
+ .height = 22,
+ .data = fontdata_sun12x22,
#ifdef __sparc__
- 5
+ .pref = 5,
#else
- -1
+ .pref = -1,
#endif
};
diff --git a/drivers/video/console/font_sun8x16.c b/drivers/video/console/font_sun8x16.c
index 41f910f5529c..5abf290c6eb7 100644
--- a/drivers/video/console/font_sun8x16.c
+++ b/drivers/video/console/font_sun8x16.c
@@ -262,14 +262,14 @@ static const unsigned char fontdata_sun8x16[FONTDATAMAX] = {
};
const struct font_desc font_sun_8x16 = {
- SUN8x16_IDX,
- "SUN8x16",
- 8,
- 16,
- fontdata_sun8x16,
+ .idx = SUN8x16_IDX,
+ .name = "SUN8x16",
+ .width = 8,
+ .height = 16,
+ .data = fontdata_sun8x16,
#ifdef __sparc__
- 10
+ .pref = 10,
#else
- -1
+ .pref = -1,
#endif
};
diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c
index dda0586ab3f3..d31b203bf654 100644
--- a/drivers/video/console/newport_con.c
+++ b/drivers/video/console/newport_con.c
@@ -98,14 +98,19 @@ static inline void newport_init_cmap(void)
}
}
-static void newport_show_logo(void)
+static const struct linux_logo *newport_show_logo(void)
{
#ifdef CONFIG_LOGO_SGI_CLUT224
const struct linux_logo *logo = fb_find_logo(8);
- const unsigned char *clut = logo->clut;
- const unsigned char *data = logo->data;
+ const unsigned char *clut;
+ const unsigned char *data;
unsigned long i;
+ if (!logo)
+ return NULL;
+ clut = logo->clut;
+ data = logo->data;
+
for (i = 0; i < logo->clutsize; i++) {
newport_bfwait(npregs);
newport_cmap_setaddr(npregs, i + 0x20);
@@ -123,6 +128,8 @@ static void newport_show_logo(void)
for (i = 0; i < logo->width*logo->height; i++)
npregs->go.hostrw0 = *data++ << 24;
+
+ return logo;
#endif /* CONFIG_LOGO_SGI_CLUT224 */
}
@@ -465,9 +472,10 @@ static int newport_switch(struct vc_data *vc)
npregs->cset.topscan = 0x3ff;
if (!logo_drawn) {
- newport_show_logo();
- logo_drawn = 1;
- logo_active = 1;
+ if (newport_show_logo()) {
+ logo_drawn = 1;
+ logo_active = 1;
+ }
}
return 1;
diff --git a/drivers/video/console/softcursor.c b/drivers/video/console/softcursor.c
index 03cfb7ac5733..25f835bf3d72 100644
--- a/drivers/video/console/softcursor.c
+++ b/drivers/video/console/softcursor.c
@@ -15,7 +15,6 @@
#include <linux/fb.h>
#include <linux/slab.h>
-#include <asm/uaccess.h>
#include <asm/io.h>
#include "fbcon.h"
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index d18b73aafa0d..f65bcd314d54 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -362,7 +362,7 @@ static const char *vgacon_startup(void)
u16 saved1, saved2;
volatile u16 *p;
- if (ORIG_VIDEO_ISVGA == VIDEO_TYPE_VLFB) {
+ if (screen_info.orig_video_isVGA == VIDEO_TYPE_VLFB) {
no_vga:
#ifdef CONFIG_DUMMY_CONSOLE
conswitchp = &dummy_con;
@@ -372,29 +372,30 @@ static const char *vgacon_startup(void)
#endif
}
- /* SCREEN_INFO initialized? */
- if ((ORIG_VIDEO_MODE == 0) &&
- (ORIG_VIDEO_LINES == 0) &&
- (ORIG_VIDEO_COLS == 0))
+ /* boot_params.screen_info initialized? */
+ if ((screen_info.orig_video_mode == 0) &&
+ (screen_info.orig_video_lines == 0) &&
+ (screen_info.orig_video_cols == 0))
goto no_vga;
/* VGA16 modes are not handled by VGACON */
- if ((ORIG_VIDEO_MODE == 0x0D) || /* 320x200/4 */
- (ORIG_VIDEO_MODE == 0x0E) || /* 640x200/4 */
- (ORIG_VIDEO_MODE == 0x10) || /* 640x350/4 */
- (ORIG_VIDEO_MODE == 0x12) || /* 640x480/4 */
- (ORIG_VIDEO_MODE == 0x6A)) /* 800x600/4, 0x6A is very common */
+ if ((screen_info.orig_video_mode == 0x0D) || /* 320x200/4 */
+ (screen_info.orig_video_mode == 0x0E) || /* 640x200/4 */
+ (screen_info.orig_video_mode == 0x10) || /* 640x350/4 */
+ (screen_info.orig_video_mode == 0x12) || /* 640x480/4 */
+ (screen_info.orig_video_mode == 0x6A)) /* 800x600/4 (VESA) */
goto no_vga;
- vga_video_num_lines = ORIG_VIDEO_LINES;
- vga_video_num_columns = ORIG_VIDEO_COLS;
+ vga_video_num_lines = screen_info.orig_video_lines;
+ vga_video_num_columns = screen_info.orig_video_cols;
state.vgabase = NULL;
- if (ORIG_VIDEO_MODE == 7) { /* Is this a monochrome display? */
+ if (screen_info.orig_video_mode == 7) {
+ /* Monochrome display */
vga_vram_base = 0xb0000;
vga_video_port_reg = VGA_CRT_IM;
vga_video_port_val = VGA_CRT_DM;
- if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10) {
+ if ((screen_info.orig_video_ega_bx & 0xff) != 0x10) {
static struct resource ega_console_resource =
{ .name = "ega", .start = 0x3B0, .end = 0x3BF };
vga_video_type = VIDEO_TYPE_EGAM;
@@ -422,12 +423,12 @@ static const char *vgacon_startup(void)
vga_vram_base = 0xb8000;
vga_video_port_reg = VGA_CRT_IC;
vga_video_port_val = VGA_CRT_DC;
- if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10) {
+ if ((screen_info.orig_video_ega_bx & 0xff) != 0x10) {
int i;
vga_vram_size = 0x8000;
- if (!ORIG_VIDEO_ISVGA) {
+ if (!screen_info.orig_video_isVGA) {
static struct resource ega_console_resource
= { .name = "ega", .start = 0x3C0, .end = 0x3DF };
vga_video_type = VIDEO_TYPE_EGAC;
@@ -521,14 +522,14 @@ static const char *vgacon_startup(void)
|| vga_video_type == VIDEO_TYPE_VGAC
|| vga_video_type == VIDEO_TYPE_EGAM) {
vga_hardscroll_enabled = vga_hardscroll_user_enable;
- vga_default_font_height = ORIG_VIDEO_POINTS;
- vga_video_font_height = ORIG_VIDEO_POINTS;
+ vga_default_font_height = screen_info.orig_video_points;
+ vga_video_font_height = screen_info.orig_video_points;
/* This may be suboptimal but is a safe bet - go with it */
vga_scan_lines =
vga_video_font_height * vga_video_num_lines;
}
- vgacon_xres = ORIG_VIDEO_COLS * VGA_FONTWIDTH;
+ vgacon_xres = screen_info.orig_video_cols * VGA_FONTWIDTH;
vgacon_yres = vga_scan_lines;
if (!vga_init_done) {
@@ -798,7 +799,7 @@ static int vgacon_switch(struct vc_data *c)
{
int x = c->vc_cols * VGA_FONTWIDTH;
int y = c->vc_rows * c->vc_font.height;
- int rows = ORIG_VIDEO_LINES * vga_default_font_height/
+ int rows = screen_info.orig_video_lines * vga_default_font_height/
c->vc_font.height;
/*
* We need to save screen size here as it's the only way
@@ -818,7 +819,7 @@ static int vgacon_switch(struct vc_data *c)
if ((vgacon_xres != x || vgacon_yres != y) &&
(!(vga_video_num_columns % 2) &&
- vga_video_num_columns <= ORIG_VIDEO_COLS &&
+ vga_video_num_columns <= screen_info.orig_video_cols &&
vga_video_num_lines <= rows))
vgacon_doresize(c, c->vc_cols, c->vc_rows);
}
@@ -1278,13 +1279,14 @@ static int vgacon_font_get(struct vc_data *c, struct console_font *font)
#endif
static int vgacon_resize(struct vc_data *c, unsigned int width,
- unsigned int height)
+ unsigned int height, unsigned int user)
{
- if (width % 2 || width > ORIG_VIDEO_COLS ||
- height > (ORIG_VIDEO_LINES * vga_default_font_height)/
+ if (width % 2 || width > screen_info.orig_video_cols ||
+ height > (screen_info.orig_video_lines * vga_default_font_height)/
c->vc_font.height)
- /* let svgatextmode tinker with video timings */
- return 0;
+ /* let svgatextmode tinker with video timings and
+ return success */
+ return (user) ? 0 : -EINVAL;
if (CON_IS_VISIBLE(c) && !vga_is_gfx) /* who knows */
vgacon_doresize(c, width, height);
@@ -1312,8 +1314,8 @@ static void vgacon_save_screen(struct vc_data *c)
* console initialization routines.
*/
vga_bootup_console = 1;
- c->vc_x = ORIG_X;
- c->vc_y = ORIG_Y;
+ c->vc_x = screen_info.orig_x;
+ c->vc_y = screen_info.orig_y;
}
/* We can't copy in more then the size of the video buffer,
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
index 30ede6e8830f..d0e4cb618269 100644
--- a/drivers/video/cyber2000fb.c
+++ b/drivers/video/cyber2000fb.c
@@ -50,7 +50,6 @@
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/system.h>
-#include <asm/uaccess.h>
#ifdef __arm__
#include <asm/mach-types.h>
@@ -63,7 +62,7 @@ struct cfb_info {
struct display_switch *dispsw;
struct display *display;
struct pci_dev *dev;
- unsigned char __iomem *region;
+ unsigned char __iomem *region;
unsigned char __iomem *regs;
u_int id;
int func_use_count;
@@ -98,11 +97,11 @@ MODULE_PARM_DESC(default_font, "Default font name");
/*
* Our access methods.
*/
-#define cyber2000fb_writel(val,reg,cfb) writel(val, (cfb)->regs + (reg))
-#define cyber2000fb_writew(val,reg,cfb) writew(val, (cfb)->regs + (reg))
-#define cyber2000fb_writeb(val,reg,cfb) writeb(val, (cfb)->regs + (reg))
+#define cyber2000fb_writel(val, reg, cfb) writel(val, (cfb)->regs + (reg))
+#define cyber2000fb_writew(val, reg, cfb) writew(val, (cfb)->regs + (reg))
+#define cyber2000fb_writeb(val, reg, cfb) writeb(val, (cfb)->regs + (reg))
-#define cyber2000fb_readb(reg,cfb) readb((cfb)->regs + (reg))
+#define cyber2000fb_readb(reg, cfb) readb((cfb)->regs + (reg))
static inline void
cyber2000_crtcw(unsigned int reg, unsigned int val, struct cfb_info *cfb)
@@ -222,12 +221,8 @@ cyber2000fb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
static void
cyber2000fb_imageblit(struct fb_info *info, const struct fb_image *image)
{
-// struct cfb_info *cfb = (struct cfb_info *)info;
-
-// if (!(cfb->fb.var.accel_flags & FB_ACCELF_TEXT)) {
- cfb_imageblit(info, image);
- return;
-// }
+ cfb_imageblit(info, image);
+ return;
}
static int cyber2000fb_sync(struct fb_info *info)
@@ -278,12 +273,12 @@ cyber2000fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
/*
* Pseudocolour:
- * 8 8
+ * 8 8
* pixel --/--+--/--> red lut --> red dac
- * | 8
- * +--/--> green lut --> green dac
- * | 8
- * +--/--> blue lut --> blue dac
+ * | 8
+ * +--/--> green lut --> green dac
+ * | 8
+ * +--/--> blue lut --> blue dac
*/
case FB_VISUAL_PSEUDOCOLOR:
if (regno >= NR_PALETTE)
@@ -293,9 +288,9 @@ cyber2000fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
green >>= 8;
blue >>= 8;
- cfb->palette[regno].red = red;
+ cfb->palette[regno].red = red;
cfb->palette[regno].green = green;
- cfb->palette[regno].blue = blue;
+ cfb->palette[regno].blue = blue;
cyber2000fb_writeb(regno, 0x3c8, cfb);
cyber2000fb_writeb(red, 0x3c9, cfb);
@@ -305,12 +300,12 @@ cyber2000fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
/*
* Direct colour:
- * n rl
- * pixel --/--+--/--> red lut --> red dac
- * | gl
- * +--/--> green lut --> green dac
- * | bl
- * +--/--> blue lut --> blue dac
+ * n rl
+ * pixel --/--+--/--> red lut --> red dac
+ * | gl
+ * +--/--> green lut --> green dac
+ * | bl
+ * +--/--> blue lut --> blue dac
* n = bpp, rl = red length, gl = green length, bl = blue length
*/
case FB_VISUAL_DIRECTCOLOR:
@@ -326,9 +321,11 @@ cyber2000fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
* to the high 6 bits of the LUT.
*/
cyber2000fb_writeb(regno << 2, 0x3c8, cfb);
- cyber2000fb_writeb(cfb->palette[regno >> 1].red, 0x3c9, cfb);
+ cyber2000fb_writeb(cfb->palette[regno >> 1].red,
+ 0x3c9, cfb);
cyber2000fb_writeb(green, 0x3c9, cfb);
- cyber2000fb_writeb(cfb->palette[regno >> 1].blue, 0x3c9, cfb);
+ cyber2000fb_writeb(cfb->palette[regno >> 1].blue,
+ 0x3c9, cfb);
green = cfb->palette[regno << 3].green;
@@ -336,9 +333,9 @@ cyber2000fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
}
if (var->green.length >= 5 && regno < 32) {
- cfb->palette[regno << 3].red = red;
+ cfb->palette[regno << 3].red = red;
cfb->palette[regno << 3].green = green;
- cfb->palette[regno << 3].blue = blue;
+ cfb->palette[regno << 3].blue = blue;
/*
* The 5 bits of each colour component are
@@ -352,9 +349,9 @@ cyber2000fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
}
if (var->green.length == 4 && regno < 16) {
- cfb->palette[regno << 4].red = red;
+ cfb->palette[regno << 4].red = red;
cfb->palette[regno << 4].green = green;
- cfb->palette[regno << 4].blue = blue;
+ cfb->palette[regno << 4].blue = blue;
/*
* The 5 bits of each colour component are
@@ -378,12 +375,12 @@ cyber2000fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
/*
* True colour:
- * n rl
- * pixel --/--+--/--> red dac
- * | gl
- * +--/--> green dac
- * | bl
- * +--/--> blue dac
+ * n rl
+ * pixel --/--+--/--> red dac
+ * | gl
+ * +--/--> green dac
+ * | bl
+ * +--/--> blue dac
* n = bpp, rl = red length, gl = green length, bl = blue length
*/
case FB_VISUAL_TRUECOLOR:
@@ -495,9 +492,9 @@ static void cyber2000fb_set_timing(struct cfb_info *cfb, struct par_info *hw)
/* PLL registers */
cyber2000_grphw(EXT_DCLK_MULT, hw->clock_mult, cfb);
- cyber2000_grphw(EXT_DCLK_DIV, hw->clock_div, cfb);
+ cyber2000_grphw(EXT_DCLK_DIV, hw->clock_div, cfb);
cyber2000_grphw(EXT_MCLK_MULT, cfb->mclk_mult, cfb);
- cyber2000_grphw(EXT_MCLK_DIV, cfb->mclk_div, cfb);
+ cyber2000_grphw(EXT_MCLK_DIV, cfb->mclk_div, cfb);
cyber2000_grphw(0x90, 0x01, cfb);
cyber2000_grphw(0xb9, 0x80, cfb);
cyber2000_grphw(0xb9, 0x00, cfb);
@@ -516,8 +513,8 @@ static void cyber2000fb_set_timing(struct cfb_info *cfb, struct par_info *hw)
/*
* Set up accelerator registers
*/
- cyber2000fb_writew(hw->width, CO_REG_SRC_WIDTH, cfb);
- cyber2000fb_writew(hw->width, CO_REG_DEST_WIDTH, cfb);
+ cyber2000fb_writew(hw->width, CO_REG_SRC_WIDTH, cfb);
+ cyber2000fb_writew(hw->width, CO_REG_DEST_WIDTH, cfb);
cyber2000fb_writeb(hw->co_pixfmt, CO_REG_PIXFMT, cfb);
}
@@ -550,15 +547,15 @@ cyber2000fb_decode_crtc(struct par_info *hw, struct cfb_info *cfb,
{
u_int Htotal, Hblankend, Hsyncend;
u_int Vtotal, Vdispend, Vblankstart, Vblankend, Vsyncstart, Vsyncend;
-#define BIT(v,b1,m,b2) (((v >> b1) & m) << b2)
+#define ENCODE_BIT(v, b1, m, b2) ((((v) >> (b1)) & (m)) << (b2))
hw->crtc[13] = hw->pitch;
hw->crtc[17] = 0xe3;
hw->crtc[14] = 0;
hw->crtc[8] = 0;
- Htotal = var->xres + var->right_margin +
- var->hsync_len + var->left_margin;
+ Htotal = var->xres + var->right_margin +
+ var->hsync_len + var->left_margin;
if (Htotal > 2080)
return -EINVAL;
@@ -568,15 +565,15 @@ cyber2000fb_decode_crtc(struct par_info *hw, struct cfb_info *cfb,
hw->crtc[2] = var->xres >> 3;
hw->crtc[4] = (var->xres + var->right_margin) >> 3;
- Hblankend = (Htotal - 4*8) >> 3;
+ Hblankend = (Htotal - 4 * 8) >> 3;
- hw->crtc[3] = BIT(Hblankend, 0, 0x1f, 0) |
- BIT(1, 0, 0x01, 7);
+ hw->crtc[3] = ENCODE_BIT(Hblankend, 0, 0x1f, 0) |
+ ENCODE_BIT(1, 0, 0x01, 7);
Hsyncend = (var->xres + var->right_margin + var->hsync_len) >> 3;
- hw->crtc[5] = BIT(Hsyncend, 0, 0x1f, 0) |
- BIT(Hblankend, 5, 0x01, 7);
+ hw->crtc[5] = ENCODE_BIT(Hsyncend, 0, 0x1f, 0) |
+ ENCODE_BIT(Hblankend, 5, 0x01, 7);
Vdispend = var->yres - 1;
Vsyncstart = var->yres + var->lower_margin;
@@ -591,20 +588,20 @@ cyber2000fb_decode_crtc(struct par_info *hw, struct cfb_info *cfb,
Vblankend = Vtotal - 10;
hw->crtc[6] = Vtotal;
- hw->crtc[7] = BIT(Vtotal, 8, 0x01, 0) |
- BIT(Vdispend, 8, 0x01, 1) |
- BIT(Vsyncstart, 8, 0x01, 2) |
- BIT(Vblankstart,8, 0x01, 3) |
- BIT(1, 0, 0x01, 4) |
- BIT(Vtotal, 9, 0x01, 5) |
- BIT(Vdispend, 9, 0x01, 6) |
- BIT(Vsyncstart, 9, 0x01, 7);
- hw->crtc[9] = BIT(0, 0, 0x1f, 0) |
- BIT(Vblankstart,9, 0x01, 5) |
- BIT(1, 0, 0x01, 6);
+ hw->crtc[7] = ENCODE_BIT(Vtotal, 8, 0x01, 0) |
+ ENCODE_BIT(Vdispend, 8, 0x01, 1) |
+ ENCODE_BIT(Vsyncstart, 8, 0x01, 2) |
+ ENCODE_BIT(Vblankstart, 8, 0x01, 3) |
+ ENCODE_BIT(1, 0, 0x01, 4) |
+ ENCODE_BIT(Vtotal, 9, 0x01, 5) |
+ ENCODE_BIT(Vdispend, 9, 0x01, 6) |
+ ENCODE_BIT(Vsyncstart, 9, 0x01, 7);
+ hw->crtc[9] = ENCODE_BIT(0, 0, 0x1f, 0) |
+ ENCODE_BIT(Vblankstart, 9, 0x01, 5) |
+ ENCODE_BIT(1, 0, 0x01, 6);
hw->crtc[10] = Vsyncstart;
- hw->crtc[11] = BIT(Vsyncend, 0, 0x0f, 0) |
- BIT(1, 0, 0x01, 7);
+ hw->crtc[11] = ENCODE_BIT(Vsyncend, 0, 0x0f, 0) |
+ ENCODE_BIT(1, 0, 0x01, 7);
hw->crtc[12] = Vdispend;
hw->crtc[15] = Vblankstart;
hw->crtc[16] = Vblankend;
@@ -616,10 +613,10 @@ cyber2000fb_decode_crtc(struct par_info *hw, struct cfb_info *cfb,
* 4=LINECOMP:10 5-IVIDEO 6=FIXCNT
*/
hw->crtc_ofl =
- BIT(Vtotal, 10, 0x01, 0) |
- BIT(Vdispend, 10, 0x01, 1) |
- BIT(Vsyncstart, 10, 0x01, 2) |
- BIT(Vblankstart,10, 0x01, 3) |
+ ENCODE_BIT(Vtotal, 10, 0x01, 0) |
+ ENCODE_BIT(Vdispend, 10, 0x01, 1) |
+ ENCODE_BIT(Vsyncstart, 10, 0x01, 2) |
+ ENCODE_BIT(Vblankstart, 10, 0x01, 3) |
EXT_CRT_VRTOFL_LINECOMP10;
/* woody: set the interlaced bit... */
@@ -751,11 +748,11 @@ cyber2000fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
var->red.msb_right = 0;
var->green.msb_right = 0;
var->blue.msb_right = 0;
+ var->transp.offset = 0;
+ var->transp.length = 0;
switch (var->bits_per_pixel) {
case 8: /* PSEUDOCOLOUR, 256 */
- var->transp.offset = 0;
- var->transp.length = 0;
var->red.offset = 0;
var->red.length = 8;
var->green.offset = 0;
@@ -767,8 +764,6 @@ cyber2000fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
case 16:/* DIRECTCOLOUR, 64k or 32k */
switch (var->green.length) {
case 6: /* RGB565, 64k */
- var->transp.offset = 0;
- var->transp.length = 0;
var->red.offset = 11;
var->red.length = 5;
var->green.offset = 5;
@@ -779,8 +774,6 @@ cyber2000fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
default:
case 5: /* RGB555, 32k */
- var->transp.offset = 0;
- var->transp.length = 0;
var->red.offset = 10;
var->red.length = 5;
var->green.offset = 5;
@@ -803,8 +796,6 @@ cyber2000fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
break;
case 24:/* TRUECOLOUR, 16m */
- var->transp.offset = 0;
- var->transp.length = 0;
var->red.offset = 16;
var->red.length = 8;
var->green.offset = 8;
@@ -831,7 +822,7 @@ cyber2000fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
mem = var->xres_virtual * var->yres_virtual * (var->bits_per_pixel / 8);
if (mem > cfb->fb.fix.smem_len)
var->yres_virtual = cfb->fb.fix.smem_len * 8 /
- (var->bits_per_pixel * var->xres_virtual);
+ (var->bits_per_pixel * var->xres_virtual);
if (var->yres > var->yres_virtual)
var->yres = var->yres_virtual;
@@ -883,6 +874,8 @@ static int cyber2000fb_set_par(struct fb_info *info)
default:
BUG();
}
+ break;
+
case 24:/* TRUECOLOUR, 16m */
hw.co_pixfmt = CO_PIXFMT_24BPP;
hw.width *= 3;
@@ -922,7 +915,7 @@ static int cyber2000fb_set_par(struct fb_info *info)
hw.fetch <<= 1;
hw.fetch += 1;
- cfb->fb.fix.line_length = var->xres_virtual * var->bits_per_pixel / 8;
+ cfb->fb.fix.line_length = var->xres_virtual * var->bits_per_pixel / 8;
/*
* Same here - if the size of the video mode exceeds the
@@ -953,7 +946,6 @@ static int cyber2000fb_set_par(struct fb_info *info)
return 0;
}
-
/*
* Pan or Wrap the Display
*/
@@ -1003,15 +995,15 @@ static int cyber2000fb_blank(int blank, struct fb_info *info)
switch (blank) {
case FB_BLANK_POWERDOWN: /* powerdown - both sync lines down */
sync = EXT_SYNC_CTL_VS_0 | EXT_SYNC_CTL_HS_0;
- break;
+ break;
case FB_BLANK_HSYNC_SUSPEND: /* hsync off */
sync = EXT_SYNC_CTL_VS_NORMAL | EXT_SYNC_CTL_HS_0;
- break;
+ break;
case FB_BLANK_VSYNC_SUSPEND: /* vsync off */
sync = EXT_SYNC_CTL_VS_0 | EXT_SYNC_CTL_HS_NORMAL;
break;
- case FB_BLANK_NORMAL: /* soft blank */
- default: /* unblank */
+ case FB_BLANK_NORMAL: /* soft blank */
+ default: /* unblank */
break;
}
@@ -1019,7 +1011,8 @@ static int cyber2000fb_blank(int blank, struct fb_info *info)
if (blank <= 1) {
/* turn on ramdacs */
- cfb->ramdac_powerdown &= ~(RAMDAC_DACPWRDN | RAMDAC_BYPASS | RAMDAC_RAMPWRDN);
+ cfb->ramdac_powerdown &= ~(RAMDAC_DACPWRDN | RAMDAC_BYPASS |
+ RAMDAC_RAMPWRDN);
cyber2000fb_write_ramdac_ctrl(cfb);
}
@@ -1044,7 +1037,8 @@ static int cyber2000fb_blank(int blank, struct fb_info *info)
if (blank >= 2) {
/* turn off ramdacs */
- cfb->ramdac_powerdown |= RAMDAC_DACPWRDN | RAMDAC_BYPASS | RAMDAC_RAMPWRDN;
+ cfb->ramdac_powerdown |= RAMDAC_DACPWRDN | RAMDAC_BYPASS |
+ RAMDAC_RAMPWRDN;
cyber2000fb_write_ramdac_ctrl(cfb);
}
@@ -1069,7 +1063,7 @@ static struct fb_ops cyber2000fb_ops = {
* of this driver. It is here solely at the moment to support the other
* CyberPro modules external to this driver.
*/
-static struct cfb_info *int_cfb_info;
+static struct cfb_info *int_cfb_info;
/*
* Enable access to the extended registers
@@ -1086,6 +1080,7 @@ void cyber2000fb_enable_extregs(struct cfb_info *cfb)
cyber2000_grphw(EXT_FUNC_CTL, old, cfb);
}
}
+EXPORT_SYMBOL(cyber2000fb_enable_extregs);
/*
* Disable access to the extended registers
@@ -1105,11 +1100,13 @@ void cyber2000fb_disable_extregs(struct cfb_info *cfb)
else
cfb->func_use_count -= 1;
}
+EXPORT_SYMBOL(cyber2000fb_disable_extregs);
void cyber2000fb_get_fb_var(struct cfb_info *cfb, struct fb_var_screeninfo *var)
{
memcpy(var, &cfb->fb.var, sizeof(struct fb_var_screeninfo));
}
+EXPORT_SYMBOL(cyber2000fb_get_fb_var);
/*
* Attach a capture/tv driver to the core CyberX0X0 driver.
@@ -1123,13 +1120,15 @@ int cyber2000fb_attach(struct cyberpro_info *info, int idx)
info->fb_size = int_cfb_info->fb.fix.smem_len;
info->enable_extregs = cyber2000fb_enable_extregs;
info->disable_extregs = cyber2000fb_disable_extregs;
- info->info = int_cfb_info;
+ info->info = int_cfb_info;
- strlcpy(info->dev_name, int_cfb_info->fb.fix.id, sizeof(info->dev_name));
+ strlcpy(info->dev_name, int_cfb_info->fb.fix.id,
+ sizeof(info->dev_name));
}
return int_cfb_info != NULL;
}
+EXPORT_SYMBOL(cyber2000fb_attach);
/*
* Detach a capture/tv driver from the core CyberX0X0 driver.
@@ -1137,12 +1136,7 @@ int cyber2000fb_attach(struct cyberpro_info *info, int idx)
void cyber2000fb_detach(int idx)
{
}
-
-EXPORT_SYMBOL(cyber2000fb_attach);
EXPORT_SYMBOL(cyber2000fb_detach);
-EXPORT_SYMBOL(cyber2000fb_enable_extregs);
-EXPORT_SYMBOL(cyber2000fb_disable_extregs);
-EXPORT_SYMBOL(cyber2000fb_get_fb_var);
/*
* These parameters give
@@ -1206,7 +1200,7 @@ static void cyberpro_init_hw(struct cfb_info *cfb)
int i;
for (i = 0; i < sizeof(igs_regs); i += 2)
- cyber2000_grphw(igs_regs[i], igs_regs[i+1], cfb);
+ cyber2000_grphw(igs_regs[i], igs_regs[i + 1], cfb);
if (cfb->id == ID_CYBERPRO_5000) {
unsigned char val;
@@ -1216,8 +1210,8 @@ static void cyberpro_init_hw(struct cfb_info *cfb)
}
}
-static struct cfb_info * __devinit
-cyberpro_alloc_fb_info(unsigned int id, char *name)
+static struct cfb_info __devinit *cyberpro_alloc_fb_info(unsigned int id,
+ char *name)
{
struct cfb_info *cfb;
@@ -1229,9 +1223,9 @@ cyberpro_alloc_fb_info(unsigned int id, char *name)
cfb->id = id;
if (id == ID_CYBERPRO_5000)
- cfb->ref_ps = 40690; // 24.576 MHz
+ cfb->ref_ps = 40690; /* 24.576 MHz */
else
- cfb->ref_ps = 69842; // 14.31818 MHz (69841?)
+ cfb->ref_ps = 69842; /* 14.31818 MHz (69841?) */
cfb->divisors[0] = 1;
cfb->divisors[1] = 2;
@@ -1283,8 +1277,7 @@ cyberpro_alloc_fb_info(unsigned int id, char *name)
return cfb;
}
-static void
-cyberpro_free_fb_info(struct cfb_info *cfb)
+static void cyberpro_free_fb_info(struct cfb_info *cfb)
{
if (cfb) {
/*
@@ -1301,8 +1294,7 @@ cyberpro_free_fb_info(struct cfb_info *cfb)
* video=cyber2000:font:fontname
*/
#ifndef MODULE
-static int
-cyber2000fb_setup(char *options)
+static int cyber2000fb_setup(char *options)
{
char *opt;
@@ -1316,7 +1308,8 @@ cyber2000fb_setup(char *options)
if (strncmp(opt, "font:", 5) == 0) {
static char default_font_storage[40];
- strlcpy(default_font_storage, opt + 5, sizeof(default_font_storage));
+ strlcpy(default_font_storage, opt + 5,
+ sizeof(default_font_storage));
default_font = default_font_storage;
continue;
}
@@ -1355,10 +1348,18 @@ static int __devinit cyberpro_common_probe(struct cfb_info *cfb)
* Determine the size of the memory.
*/
switch (cfb->mem_ctl2 & MEM_CTL2_SIZE_MASK) {
- case MEM_CTL2_SIZE_4MB: smem_size = 0x00400000; break;
- case MEM_CTL2_SIZE_2MB: smem_size = 0x00200000; break;
- case MEM_CTL2_SIZE_1MB: smem_size = 0x00100000; break;
- default: smem_size = 0x00100000; break;
+ case MEM_CTL2_SIZE_4MB:
+ smem_size = 0x00400000;
+ break;
+ case MEM_CTL2_SIZE_2MB:
+ smem_size = 0x00200000;
+ break;
+ case MEM_CTL2_SIZE_1MB:
+ smem_size = 0x00100000;
+ break;
+ default:
+ smem_size = 0x00100000;
+ break;
}
cfb->fb.fix.smem_len = smem_size;
@@ -1367,8 +1368,8 @@ static int __devinit cyberpro_common_probe(struct cfb_info *cfb)
err = -EINVAL;
if (!fb_find_mode(&cfb->fb.var, &cfb->fb, NULL, NULL, 0,
- &cyber2000fb_default_mode, 8)) {
- printk("%s: no valid mode found\n", cfb->fb.fix.id);
+ &cyber2000fb_default_mode, 8)) {
+ printk(KERN_ERR "%s: no valid mode found\n", cfb->fb.fix.id);
goto failed;
}
@@ -1378,7 +1379,7 @@ static int __devinit cyberpro_common_probe(struct cfb_info *cfb)
if (cfb->fb.var.yres_virtual < cfb->fb.var.yres)
cfb->fb.var.yres_virtual = cfb->fb.var.yres;
-// fb_set_var(&cfb->fb.var, -1, &cfb->fb);
+/* fb_set_var(&cfb->fb.var, -1, &cfb->fb); */
/*
* Calculate the hsync and vsync frequencies. Note that
@@ -1426,20 +1427,20 @@ static void cyberpro_common_resume(struct cfb_info *cfb)
#include <asm/arch/hardware.h>
-static int __devinit
-cyberpro_vl_probe(void)
+static int __devinit cyberpro_vl_probe(void)
{
struct cfb_info *cfb;
int err = -ENOMEM;
- if (!request_mem_region(FB_START,FB_SIZE,"CyberPro2010")) return err;
+ if (!request_mem_region(FB_START, FB_SIZE, "CyberPro2010"))
+ return err;
cfb = cyberpro_alloc_fb_info(ID_CYBERPRO_2010, "CyberPro2010");
if (!cfb)
goto failed_release;
cfb->dev = NULL;
- cfb->region = ioremap(FB_START,FB_SIZE);
+ cfb->region = ioremap(FB_START, FB_SIZE);
if (!cfb->region)
goto failed_ioremap;
@@ -1476,7 +1477,7 @@ failed:
failed_ioremap:
cyberpro_free_fb_info(cfb);
failed_release:
- release_mem_region(FB_START,FB_SIZE);
+ release_mem_region(FB_START, FB_SIZE);
return err;
}
@@ -1539,7 +1540,8 @@ static int cyberpro_pci_enable_mmio(struct cfb_info *cfb)
* Allow the CyberPro to accept PCI burst accesses
*/
if (cfb->id == ID_CYBERPRO_2010) {
- printk(KERN_INFO "%s: NOT enabling PCI bursts\n", cfb->fb.fix.id);
+ printk(KERN_INFO "%s: NOT enabling PCI bursts\n",
+ cfb->fb.fix.id);
} else {
val = cyber2000_grphr(EXT_BUS_CTL, cfb);
if (!(val & EXT_BUS_CTL_PCIBURST_WRITE)) {
@@ -1689,9 +1691,10 @@ static int cyberpro_pci_resume(struct pci_dev *dev)
}
static struct pci_device_id cyberpro_pci_table[] = {
-// Not yet
-// { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_1682,
-// PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_IGA_1682 },
+/* Not yet
+ * { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_1682,
+ * PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_IGA_1682 },
+ */
{ PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2000,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_2000 },
{ PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2010,
@@ -1701,7 +1704,7 @@ static struct pci_device_id cyberpro_pci_table[] = {
{ 0, }
};
-MODULE_DEVICE_TABLE(pci,cyberpro_pci_table);
+MODULE_DEVICE_TABLE(pci, cyberpro_pci_table);
static struct pci_driver cyberpro_driver = {
.name = "CyberPro",
diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c
index 33be46ccb54f..cc2810ef5de5 100644
--- a/drivers/video/epson1355fb.c
+++ b/drivers/video/epson1355fb.c
@@ -57,7 +57,7 @@
#include <asm/types.h>
#include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <video/epson1355.h>
diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c
index 1a8643f053d8..a0c5d9d90d74 100644
--- a/drivers/video/fb_defio.c
+++ b/drivers/video/fb_defio.c
@@ -19,7 +19,6 @@
#include <linux/interrupt.h>
#include <linux/fb.h>
#include <linux/list.h>
-#include <asm/uaccess.h>
/* to support deferred IO */
#include <linux/rmap.h>
diff --git a/drivers/video/fb_draw.h b/drivers/video/fb_draw.h
index c5c45203833b..cdafbe14ef1f 100644
--- a/drivers/video/fb_draw.h
+++ b/drivers/video/fb_draw.h
@@ -2,6 +2,7 @@
#define _FB_DRAW_H
#include <asm/types.h>
+#include <linux/fb.h>
/*
* Compose two values, using a bitmask as decision value
@@ -69,4 +70,97 @@ pixel_to_pat( u32 bpp, u32 pixel)
}
}
#endif
+
+#ifdef CONFIG_FB_CFB_REV_PIXELS_IN_BYTE
+#if BITS_PER_LONG == 64
+#define REV_PIXELS_MASK1 0x5555555555555555ul
+#define REV_PIXELS_MASK2 0x3333333333333333ul
+#define REV_PIXELS_MASK4 0x0f0f0f0f0f0f0f0ful
+#else
+#define REV_PIXELS_MASK1 0x55555555ul
+#define REV_PIXELS_MASK2 0x33333333ul
+#define REV_PIXELS_MASK4 0x0f0f0f0ful
+#endif
+
+static inline unsigned long fb_rev_pixels_in_long(unsigned long val,
+ u32 bswapmask)
+{
+ if (bswapmask & 1)
+ val = comp(val >> 1, val << 1, REV_PIXELS_MASK1);
+ if (bswapmask & 2)
+ val = comp(val >> 2, val << 2, REV_PIXELS_MASK2);
+ if (bswapmask & 3)
+ val = comp(val >> 4, val << 4, REV_PIXELS_MASK4);
+}
+
+static inline u32 fb_shifted_pixels_mask_u32(u32 index, u32 bswapmask)
+{
+ u32 mask;
+
+ if (!bswapmask) {
+ mask = FB_SHIFT_HIGH(~(u32)0, index);
+ } else {
+ mask = 0xff << FB_LEFT_POS(8);
+ mask = FB_SHIFT_LOW(mask, index & (bswapmask)) & mask;
+ mask = FB_SHIFT_HIGH(mask, index & ~(bswapmask));
+#if defined(__i386__) || defined(__x86_64__)
+ /* Shift argument is limited to 0 - 31 on x86 based CPU's */
+ if(index + bswapmask < 32)
+#endif
+ mask |= FB_SHIFT_HIGH(~(u32)0,
+ (index + bswapmask) & ~(bswapmask));
+ }
+ return mask;
+}
+
+static inline unsigned long fb_shifted_pixels_mask_long(u32 index, u32 bswapmask)
+{
+ unsigned long mask;
+
+ if (!bswapmask) {
+ mask = FB_SHIFT_HIGH(~0UL, index);
+ } else {
+ mask = 0xff << FB_LEFT_POS(8);
+ mask = FB_SHIFT_LOW(mask, index & (bswapmask)) & mask;
+ mask = FB_SHIFT_HIGH(mask, index & ~(bswapmask));
+#if defined(__i386__) || defined(__x86_64__)
+ /* Shift argument is limited to 0 - 31 on x86 based CPU's */
+ if(index + bswapmask < BITS_PER_LONG)
+#endif
+ mask |= FB_SHIFT_HIGH(~0UL,
+ (index + bswapmask) & ~(bswapmask));
+ }
+ return mask;
+}
+
+
+static inline u32 fb_compute_bswapmask(struct fb_info *info)
+{
+ u32 bswapmask = 0;
+ unsigned bpp = info->var.bits_per_pixel;
+
+ if ((bpp < 8) && (info->var.nonstd & FB_NONSTD_REV_PIX_IN_B)) {
+ /*
+ * Reversed order of pixel layout in bytes
+ * works only for 1, 2 and 4 bpp
+ */
+ bswapmask = 7 - bpp + 1;
+ }
+ return bswapmask;
+}
+
+#else /* CONFIG_FB_CFB_REV_PIXELS_IN_BYTE */
+
+static inline unsigned long fb_rev_pixels_in_long(unsigned long val,
+ u32 bswapmask)
+{
+ return val;
+}
+
+#define fb_shifted_pixels_mask_u32(i, b) FB_SHIFT_HIGH(~(u32)0, (i))
+#define fb_shifted_pixels_mask_long(i, b) FB_SHIFT_HIGH(~0UL, (i))
+#define fb_compute_bswapmask(...) 0
+
+#endif /* CONFIG_FB_CFB_REV_PIXELS_IN_BYTE */
+
#endif /* FB_DRAW_H */
diff --git a/drivers/video/fb_sys_fops.c b/drivers/video/fb_sys_fops.c
index cf2538d669cd..ff275d7f3eaf 100644
--- a/drivers/video/fb_sys_fops.c
+++ b/drivers/video/fb_sys_fops.c
@@ -11,7 +11,7 @@
*/
#include <linux/fb.h>
#include <linux/module.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
ssize_t fb_sys_read(struct fb_info *info, char __user *buf, size_t count,
loff_t *ppos)
diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c
index 148108afdd51..91b78e691505 100644
--- a/drivers/video/fbcmap.c
+++ b/drivers/video/fbcmap.c
@@ -15,8 +15,7 @@
#include <linux/module.h>
#include <linux/fb.h>
#include <linux/slab.h>
-
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
static u16 red2[] __read_mostly = {
0x0000, 0xaaaa
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 074027204702..1194f5e060ea 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1567,8 +1567,6 @@ int fb_new_modelist(struct fb_info *info)
static char *video_options[FB_MAX] __read_mostly;
static int ofonly __read_mostly;
-extern const char *global_mode_option;
-
/**
* fb_get_options - get kernel boot parameters
* @name: framebuffer name as it would appear in
@@ -1636,7 +1634,7 @@ static int __init video_setup(char *options)
}
if (!global && !strstr(options, "fb:")) {
- global_mode_option = options;
+ fb_mode_option = options;
global = 1;
}
@@ -1663,7 +1661,6 @@ EXPORT_SYMBOL(register_framebuffer);
EXPORT_SYMBOL(unregister_framebuffer);
EXPORT_SYMBOL(num_registered_fb);
EXPORT_SYMBOL(registered_fb);
-EXPORT_SYMBOL(fb_prepare_logo);
EXPORT_SYMBOL(fb_show_logo);
EXPORT_SYMBOL(fb_set_var);
EXPORT_SYMBOL(fb_blank);
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index 438b9411905c..4ba9c0894416 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -591,7 +591,7 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
{
struct fb_videomode *mode, *m;
unsigned char *block;
- int num = 0, i;
+ int num = 0, i, first = 1;
mode = kzalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL);
if (mode == NULL)
@@ -608,8 +608,6 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
DPRINTK(" Detailed Timings\n");
block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) {
- int first = 1;
-
if (!(block[0] == 0x00 && block[1] == 0x00)) {
get_detailed_timing(block, &mode[num]);
if (first) {
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c
index b9b572b293d4..2e552d5bbb5d 100644
--- a/drivers/video/gbefb.c
+++ b/drivers/video/gbefb.c
@@ -183,8 +183,8 @@ static struct fb_videomode default_mode_LCD __initdata = {
.vmode = FB_VMODE_NONINTERLACED,
};
-struct fb_videomode *default_mode = &default_mode_CRT;
-struct fb_var_screeninfo *default_var = &default_var_CRT;
+struct fb_videomode *default_mode __initdata = &default_mode_CRT;
+struct fb_var_screeninfo *default_var __initdata = &default_var_CRT;
static int flat_panel_enabled = 0;
diff --git a/drivers/video/geode/lxfb.h b/drivers/video/geode/lxfb.h
index 6c227f9592a5..ca13c48d19b0 100644
--- a/drivers/video/geode/lxfb.h
+++ b/drivers/video/geode/lxfb.h
@@ -33,7 +33,7 @@ void lx_set_palette_reg(struct fb_info *, unsigned int, unsigned int,
#define MSR_LX_GLD_CONFIG 0x48002001
#define MSR_LX_GLCP_DOTPLL 0x4c000015
-#define MSR_LX_DF_PADSEL 0x48000011
+#define MSR_LX_DF_PADSEL 0x48002011
#define MSR_LX_DC_SPARE 0x80000011
#define MSR_LX_DF_GLCONFIG 0x48002001
diff --git a/drivers/video/geode/lxfb_core.c b/drivers/video/geode/lxfb_core.c
index 5e30b40c8c0f..583185fd7c94 100644
--- a/drivers/video/geode/lxfb_core.c
+++ b/drivers/video/geode/lxfb_core.c
@@ -566,12 +566,7 @@ static int __init lxfb_setup(char *options)
if (!options || !*options)
return 0;
- while (1) {
- char *opt = strsep(&options, ",");
-
- if (opt == NULL)
- break;
-
+ while ((opt = strsep(&options, ",")) != NULL) {
if (!*opt)
continue;
diff --git a/drivers/video/geode/video_gx.c b/drivers/video/geode/video_gx.c
index 7f3f18d06718..febf09c63492 100644
--- a/drivers/video/geode/video_gx.c
+++ b/drivers/video/geode/video_gx.c
@@ -127,7 +127,7 @@ static void gx_set_dclk_frequency(struct fb_info *info)
int timeout = 1000;
/* Rev. 1 Geode GXs use a 14 MHz reference clock instead of 48 MHz. */
- if (cpu_data->x86_mask == 1) {
+ if (cpu_data(0).x86_mask == 1) {
pll_table = gx_pll_table_14MHz;
pll_table_len = ARRAY_SIZE(gx_pll_table_14MHz);
} else {
diff --git a/drivers/video/gxt4500.c b/drivers/video/gxt4500.c
index 23a6bcc3e3ce..e92337bef50d 100644
--- a/drivers/video/gxt4500.c
+++ b/drivers/video/gxt4500.c
@@ -636,7 +636,7 @@ static int __devinit gxt4500_probe(struct pci_dev *pdev,
info = framebuffer_alloc(sizeof(struct gxt4500_par), &pdev->dev);
if (!info) {
- dev_err(&pdev->dev, "gxt4500: cannot alloc FB info record");
+ dev_err(&pdev->dev, "gxt4500: cannot alloc FB info record\n");
goto err_free_fb;
}
par = info->par;
diff --git a/drivers/video/hecubafb.c b/drivers/video/hecubafb.c
index abfcb50364c8..94e0df8a6f60 100644
--- a/drivers/video/hecubafb.c
+++ b/drivers/video/hecubafb.c
@@ -45,7 +45,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/list.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
/* Apollo controller specific defines */
#define APOLLO_START_NEW_IMG 0xA0
diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c
index 94f4511023d8..3ab91bf21576 100644
--- a/drivers/video/imsttfb.c
+++ b/drivers/video/imsttfb.c
@@ -29,7 +29,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#if defined(CONFIG_PPC)
#include <linux/nvram.h>
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index a12589898597..11609552a387 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -34,7 +34,6 @@
#include <asm/hardware.h>
#include <asm/io.h>
-#include <asm/uaccess.h>
#include <asm/arch/imxfb.h>
/*
@@ -467,7 +466,7 @@ static int __init imxfb_init_fbinfo(struct device *dev)
info->var.vmode = FB_VMODE_NONINTERLACED;
info->fbops = &imxfb_ops;
- info->flags = FBINFO_FLAG_DEFAULT;
+ info->flags = FBINFO_FLAG_DEFAULT | FBINFO_READS_FAST;
fbi->rgb[RGB_16] = &def_rgb_16;
fbi->rgb[RGB_8] = &def_rgb_8;
@@ -480,6 +479,7 @@ static int __init imxfb_init_fbinfo(struct device *dev)
info->var.yres_virtual = inf->yres;
fbi->max_bpp = inf->bpp;
info->var.bits_per_pixel = inf->bpp;
+ info->var.nonstd = inf->nonstd;
info->var.pixclock = inf->pixclock;
info->var.hsync_len = inf->hsync_len;
info->var.left_margin = inf->left_margin;
diff --git a/drivers/video/intelfb/intelfb.h b/drivers/video/intelfb/intelfb.h
index 6148300fadd6..2fe3f7def530 100644
--- a/drivers/video/intelfb/intelfb.h
+++ b/drivers/video/intelfb/intelfb.h
@@ -231,8 +231,8 @@ struct intelfb_hwstate {
struct intelfb_heap_data {
u32 physical;
u8 __iomem *virtual;
- u32 offset; // in GATT pages
- u32 size; // in bytes
+ u32 offset; /* in GATT pages */
+ u32 size; /* in bytes */
};
#ifdef CONFIG_FB_INTEL_I2C
@@ -270,9 +270,9 @@ struct intelfb_info {
struct intelfb_hwstate save_state;
/* agpgart structs */
- struct agp_memory *gtt_fb_mem; // use all stolen memory or vram
- struct agp_memory *gtt_ring_mem; // ring buffer
- struct agp_memory *gtt_cursor_mem; // hw cursor
+ struct agp_memory *gtt_fb_mem; /* use all stolen memory or vram */
+ struct agp_memory *gtt_ring_mem; /* ring buffer */
+ struct agp_memory *gtt_cursor_mem; /* hw cursor */
/* use a gart reserved fb mem */
u8 fbmem_gart;
@@ -346,7 +346,7 @@ struct intelfb_info {
/* driver registered */
int registered;
-
+
/* index into plls */
int pll_index;
@@ -355,7 +355,10 @@ struct intelfb_info {
struct intelfb_output_rec output[MAX_OUTPUTS];
};
-#define IS_I9XX(dinfo) (((dinfo)->chipset == INTEL_915G)||(dinfo->chipset == INTEL_915GM)||((dinfo)->chipset == INTEL_945G)||(dinfo->chipset==INTEL_945GM))
+#define IS_I9XX(dinfo) (((dinfo)->chipset == INTEL_915G) || \
+ ((dinfo)->chipset == INTEL_915GM) || \
+ ((dinfo)->chipset == INTEL_945G) || \
+ ((dinfo)->chipset==INTEL_945GM))
#ifndef FBIO_WAITFORVSYNC
#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
diff --git a/drivers/video/intelfb/intelfb_i2c.c b/drivers/video/intelfb/intelfb_i2c.c
index 61e4c8759b23..94c08bb5acf1 100644
--- a/drivers/video/intelfb/intelfb_i2c.c
+++ b/drivers/video/intelfb/intelfb_i2c.c
@@ -58,7 +58,8 @@ static void intelfb_gpio_setscl(void *data, int state)
struct intelfb_info *dinfo = chan->dinfo;
u32 val;
- OUTREG(chan->reg, (state ? SCL_VAL_OUT : 0) | SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK);
+ OUTREG(chan->reg, (state ? SCL_VAL_OUT : 0) |
+ SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK);
val = INREG(chan->reg);
}
@@ -68,7 +69,8 @@ static void intelfb_gpio_setsda(void *data, int state)
struct intelfb_info *dinfo = chan->dinfo;
u32 val;
- OUTREG(chan->reg, (state ? SDA_VAL_OUT : 0) | SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK);
+ OUTREG(chan->reg, (state ? SDA_VAL_OUT : 0) |
+ SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK);
val = INREG(chan->reg);
}
@@ -97,26 +99,26 @@ static int intelfb_gpio_getsda(void *data)
}
static int intelfb_setup_i2c_bus(struct intelfb_info *dinfo,
- struct intelfb_i2c_chan *chan,
- const u32 reg, const char *name)
+ struct intelfb_i2c_chan *chan,
+ const u32 reg, const char *name)
{
int rc;
- chan->dinfo = dinfo;
- chan->reg = reg;
+ chan->dinfo = dinfo;
+ chan->reg = reg;
snprintf(chan->adapter.name, sizeof(chan->adapter.name),
"intelfb %s", name);
- chan->adapter.owner = THIS_MODULE;
- chan->adapter.id = I2C_HW_B_INTELFB;
+ chan->adapter.owner = THIS_MODULE;
+ chan->adapter.id = I2C_HW_B_INTELFB;
chan->adapter.algo_data = &chan->algo;
chan->adapter.dev.parent = &chan->dinfo->pdev->dev;
- chan->algo.setsda = intelfb_gpio_setsda;
- chan->algo.setscl = intelfb_gpio_setscl;
- chan->algo.getsda = intelfb_gpio_getsda;
- chan->algo.getscl = intelfb_gpio_getscl;
- chan->algo.udelay = 40;
- chan->algo.timeout = 20;
- chan->algo.data = chan;
+ chan->algo.setsda = intelfb_gpio_setsda;
+ chan->algo.setscl = intelfb_gpio_setscl;
+ chan->algo.getsda = intelfb_gpio_getsda;
+ chan->algo.getscl = intelfb_gpio_getscl;
+ chan->algo.udelay = 40;
+ chan->algo.timeout = 20;
+ chan->algo.data = chan;
i2c_set_adapdata(&chan->adapter, chan);
@@ -142,40 +144,44 @@ void intelfb_create_i2c_busses(struct intelfb_info *dinfo)
dinfo->output[i].type = INTELFB_OUTPUT_ANALOG;
/* setup the DDC bus for analog output */
- intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].ddc_bus, GPIOA, "CRTDDC_A");
+ intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].ddc_bus, GPIOA,
+ "CRTDDC_A");
i++;
- /* need to add the output busses for each device
- - this function is very incomplete
- - i915GM has LVDS and TVOUT for example
- */
- switch(dinfo->chipset) {
+ /* need to add the output busses for each device
+ - this function is very incomplete
+ - i915GM has LVDS and TVOUT for example
+ */
+ switch(dinfo->chipset) {
case INTEL_830M:
case INTEL_845G:
case INTEL_855GM:
case INTEL_865G:
dinfo->output[i].type = INTELFB_OUTPUT_DVO;
- intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].ddc_bus, GPIOD, "DVODDC_D");
- intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].i2c_bus, GPIOE, "DVOI2C_E");
+ intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].ddc_bus,
+ GPIOD, "DVODDC_D");
+ intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].i2c_bus,
+ GPIOE, "DVOI2C_E");
i++;
break;
case INTEL_915G:
case INTEL_915GM:
- /* has some LVDS + tv-out */
+ /* has some LVDS + tv-out */
case INTEL_945G:
case INTEL_945GM:
/* SDVO ports have a single control bus - 2 devices */
dinfo->output[i].type = INTELFB_OUTPUT_SDVO;
- intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].i2c_bus, GPIOE, "SDVOCTRL_E");
+ intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].i2c_bus,
+ GPIOE, "SDVOCTRL_E");
/* TODO: initialize the SDVO */
-// I830SDVOInit(pScrn, i, DVOB);
+ /* I830SDVOInit(pScrn, i, DVOB); */
i++;
/* set up SDVOC */
dinfo->output[i].type = INTELFB_OUTPUT_SDVO;
dinfo->output[i].i2c_bus = dinfo->output[i - 1].i2c_bus;
/* TODO: initialize the SDVO */
-// I830SDVOInit(pScrn, i, DVOC);
+ /* I830SDVOInit(pScrn, i, DVOC); */
i++;
break;
}
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
index b75eda84858f..481d58f7535d 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -4,7 +4,7 @@
* Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G/915GM/
* 945G/945GM integrated graphics chips.
*
- * Copyright © 2002, 2003 David Dawes <dawes@xfree86.org>
+ * Copyright © 2002, 2003 David Dawes <dawes@xfree86.org>
* 2004 Sylvain Meyer
* 2006 David Airlie
*
@@ -99,13 +99,6 @@
* Add vram option to reserve more memory than stolen by BIOS
* Fix intelfbhw_pan_display typo
* Add __initdata annotations
- *
- * TODO:
- *
- *
- * Wish List:
- *
- *
*/
#include <linux/module.h>
@@ -222,8 +215,8 @@ static struct pci_driver intelfb_driver = {
/* Module description/parameters */
MODULE_AUTHOR("David Dawes <dawes@tungstengraphics.com>, "
"Sylvain Meyer <sylvain.meyer@worldonline.fr>");
-MODULE_DESCRIPTION(
- "Framebuffer driver for Intel(R) " SUPPORTED_CHIPSETS " chipsets");
+MODULE_DESCRIPTION("Framebuffer driver for Intel(R) " SUPPORTED_CHIPSETS
+ " chipsets");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DEVICE_TABLE(pci, intelfb_pci_table);
@@ -271,8 +264,7 @@ MODULE_PARM_DESC(mode,
#define OPT_INTVAL(opt, name) simple_strtoul(opt + strlen(name) + 1, NULL, 0)
#define OPT_STRVAL(opt, name) (opt + strlen(name))
-static __inline__ char *
-get_opt_string(const char *this_opt, const char *name)
+static __inline__ char * get_opt_string(const char *this_opt, const char *name)
{
const char *p;
int i;
@@ -290,8 +282,8 @@ get_opt_string(const char *this_opt, const char *name)
return ret;
}
-static __inline__ int
-get_opt_int(const char *this_opt, const char *name, int *ret)
+static __inline__ int get_opt_int(const char *this_opt, const char *name,
+ int *ret)
{
if (!ret)
return 0;
@@ -303,8 +295,8 @@ get_opt_int(const char *this_opt, const char *name, int *ret)
return 1;
}
-static __inline__ int
-get_opt_bool(const char *this_opt, const char *name, int *ret)
+static __inline__ int get_opt_bool(const char *this_opt, const char *name,
+ int *ret)
{
if (!ret)
return 0;
@@ -324,8 +316,7 @@ get_opt_bool(const char *this_opt, const char *name, int *ret)
return 1;
}
-static int __init
-intelfb_setup(char *options)
+static int __init intelfb_setup(char *options)
{
char *this_opt;
@@ -355,7 +346,7 @@ intelfb_setup(char *options)
continue;
if (get_opt_bool(this_opt, "accel", &accel))
;
- else if (get_opt_int(this_opt, "vram", &vram))
+ else if (get_opt_int(this_opt, "vram", &vram))
;
else if (get_opt_bool(this_opt, "hwcursor", &hwcursor))
;
@@ -376,8 +367,7 @@ intelfb_setup(char *options)
#endif
-static int __init
-intelfb_init(void)
+static int __init intelfb_init(void)
{
#ifndef MODULE
char *option = NULL;
@@ -401,8 +391,7 @@ intelfb_init(void)
return pci_register_driver(&intelfb_driver);
}
-static void __exit
-intelfb_exit(void)
+static void __exit intelfb_exit(void)
{
DBG_MSG("intelfb_exit\n");
pci_unregister_driver(&intelfb_driver);
@@ -428,8 +417,8 @@ static inline void __devinit set_mtrr(struct intelfb_info *dinfo)
}
static inline void unset_mtrr(struct intelfb_info *dinfo)
{
- if (dinfo->has_mtrr)
- mtrr_del(dinfo->mtrr_reg, dinfo->aperture.physical,
+ if (dinfo->has_mtrr)
+ mtrr_del(dinfo->mtrr_reg, dinfo->aperture.physical,
dinfo->aperture.size);
}
#else
@@ -442,8 +431,7 @@ static inline void unset_mtrr(struct intelfb_info *dinfo)
* driver init / cleanup *
***************************************************************/
-static void
-cleanup(struct intelfb_info *dinfo)
+static void cleanup(struct intelfb_info *dinfo)
{
DBG_MSG("cleanup\n");
@@ -499,8 +487,8 @@ cleanup(struct intelfb_info *dinfo)
} while (0)
-static int __devinit
-intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int __devinit intelfb_pci_register(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
struct fb_info *info;
struct intelfb_info *dinfo;
@@ -510,8 +498,8 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
int agp_memtype;
const char *s;
struct agp_bridge_data *bridge;
- int aperture_bar = 0;
- int mmio_bar = 1;
+ int aperture_bar = 0;
+ int mmio_bar = 1;
int offset;
DBG_MSG("intelfb_pci_register\n");
@@ -637,9 +625,8 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
dinfo->ring.size = RINGBUFFER_SIZE;
dinfo->ring_tail_mask = dinfo->ring.size - 1;
}
- if (dinfo->hwcursor) {
+ if (dinfo->hwcursor)
dinfo->cursor.size = HW_CURSOR_SIZE;
- }
/* Use agpgart to manage the GATT */
if (!(bridge = agp_backend_acquire(pdev))) {
@@ -662,18 +649,15 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
offset = ROUND_UP_TO_PAGE(MB(voffset))/GTT_PAGE_SIZE;
/* set the mem offsets - set them after the already used pages */
- if (dinfo->accel) {
+ if (dinfo->accel)
dinfo->ring.offset = offset + gtt_info.current_memory;
- }
- if (dinfo->hwcursor) {
+ if (dinfo->hwcursor)
dinfo->cursor.offset = offset +
+ gtt_info.current_memory + (dinfo->ring.size >> 12);
- }
- if (dinfo->fbmem_gart) {
+ if (dinfo->fbmem_gart)
dinfo->fb.offset = offset +
+ gtt_info.current_memory + (dinfo->ring.size >> 12)
+ (dinfo->cursor.size >> 12);
- }
/* Allocate memories (which aren't stolen) */
/* Map the fb and MMIO regions */
@@ -689,7 +673,7 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
dinfo->mmio_base =
(u8 __iomem *)ioremap_nocache(dinfo->mmio_base_phys,
- INTEL_REG_SIZE);
+ INTEL_REG_SIZE);
if (!dinfo->mmio_base) {
ERR_MSG("Cannot remap MMIO region.\n");
cleanup(dinfo);
@@ -820,7 +804,8 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
if (bailearly == 1)
bailout(dinfo);
- if (FIXED_MODE(dinfo) && ORIG_VIDEO_ISVGA != VIDEO_TYPE_VLFB) {
+ if (FIXED_MODE(dinfo) &&
+ screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) {
ERR_MSG("Video mode must be programmed at boot time.\n");
cleanup(dinfo);
return -ENODEV;
@@ -831,16 +816,14 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Initialise dinfo and related data. */
/* If an initial mode was programmed at boot time, get its details. */
- if (ORIG_VIDEO_ISVGA == VIDEO_TYPE_VLFB)
+ if (screen_info.orig_video_isVGA == VIDEO_TYPE_VLFB)
get_initial_mode(dinfo);
if (bailearly == 3)
bailout(dinfo);
- if (FIXED_MODE(dinfo)) {
- /* remap fb address */
+ if (FIXED_MODE(dinfo)) /* remap fb address */
update_dinfo(dinfo, &dinfo->initial_var);
- }
if (bailearly == 4)
bailout(dinfo);
@@ -939,8 +922,7 @@ intelfb_pci_unregister(struct pci_dev *pdev)
* helper functions *
***************************************************************/
-int __inline__
-intelfb_var_to_depth(const struct fb_var_screeninfo *var)
+int __inline__ intelfb_var_to_depth(const struct fb_var_screeninfo *var)
{
DBG_MSG("intelfb_var_to_depth: bpp: %d, green.length is %d\n",
var->bits_per_pixel, var->green.length);
@@ -956,8 +938,7 @@ intelfb_var_to_depth(const struct fb_var_screeninfo *var)
}
-static __inline__ int
-var_to_refresh(const struct fb_var_screeninfo *var)
+static __inline__ int var_to_refresh(const struct fb_var_screeninfo *var)
{
int xtot = var->xres + var->left_margin + var->right_margin +
var->hsync_len;
@@ -971,8 +952,7 @@ var_to_refresh(const struct fb_var_screeninfo *var)
* Various intialisation functions *
***************************************************************/
-static void __devinit
-get_initial_mode(struct intelfb_info *dinfo)
+static void __devinit get_initial_mode(struct intelfb_info *dinfo)
{
struct fb_var_screeninfo *var;
int xtot, ytot;
@@ -1039,8 +1019,7 @@ get_initial_mode(struct intelfb_info *dinfo)
}
}
-static int __devinit
-intelfb_init_var(struct intelfb_info *dinfo)
+static int __devinit intelfb_init_var(struct intelfb_info *dinfo)
{
struct fb_var_screeninfo *var;
int msrc = 0;
@@ -1087,10 +1066,9 @@ intelfb_init_var(struct intelfb_info *dinfo)
}
- if (!msrc) {
+ if (!msrc)
msrc = fb_find_mode(var, dinfo->info, PREFERRED_MODE,
NULL, 0, NULL, 0);
- }
}
if (!msrc) {
@@ -1122,8 +1100,7 @@ intelfb_init_var(struct intelfb_info *dinfo)
return 0;
}
-static int __devinit
-intelfb_set_fbinfo(struct intelfb_info *dinfo)
+static int __devinit intelfb_set_fbinfo(struct intelfb_info *dinfo)
{
struct fb_info *info = dinfo->info;
@@ -1159,8 +1136,8 @@ intelfb_set_fbinfo(struct intelfb_info *dinfo)
}
/* Update dinfo to match the active video mode. */
-static void
-update_dinfo(struct intelfb_info *dinfo, struct fb_var_screeninfo *var)
+static void update_dinfo(struct intelfb_info *dinfo,
+ struct fb_var_screeninfo *var)
{
DBG_MSG("update_dinfo\n");
@@ -1208,36 +1185,32 @@ update_dinfo(struct intelfb_info *dinfo, struct fb_var_screeninfo *var)
* fbdev interface *
***************************************************************/
-static int
-intelfb_open(struct fb_info *info, int user)
+static int intelfb_open(struct fb_info *info, int user)
{
struct intelfb_info *dinfo = GET_DINFO(info);
- if (user) {
+ if (user)
dinfo->open++;
- }
return 0;
}
-static int
-intelfb_release(struct fb_info *info, int user)
+static int intelfb_release(struct fb_info *info, int user)
{
struct intelfb_info *dinfo = GET_DINFO(info);
if (user) {
dinfo->open--;
msleep(1);
- if (!dinfo->open) {
+ if (!dinfo->open)
intelfbhw_disable_irq(dinfo);
- }
}
return 0;
}
-static int
-intelfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+static int intelfb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
{
int change_var = 0;
struct fb_var_screeninfo v;
@@ -1271,15 +1244,15 @@ intelfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
}
/* Check for a supported bpp. */
- if (v.bits_per_pixel <= 8) {
+ if (v.bits_per_pixel <= 8)
v.bits_per_pixel = 8;
- } else if (v.bits_per_pixel <= 16) {
+ else if (v.bits_per_pixel <= 16) {
if (v.bits_per_pixel == 16)
v.green.length = 6;
v.bits_per_pixel = 16;
- } else if (v.bits_per_pixel <= 32) {
+ } else if (v.bits_per_pixel <= 32)
v.bits_per_pixel = 32;
- } else
+ else
return -EINVAL;
change_var = ((info->var.xres != var->xres) ||
@@ -1361,10 +1334,9 @@ intelfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
return 0;
}
-static int
-intelfb_set_par(struct fb_info *info)
+static int intelfb_set_par(struct fb_info *info)
{
- struct intelfb_hwstate *hw;
+ struct intelfb_hwstate *hw;
struct intelfb_info *dinfo = GET_DINFO(info);
if (FIXED_MODE(dinfo)) {
@@ -1372,9 +1344,9 @@ intelfb_set_par(struct fb_info *info)
return -EINVAL;
}
- hw = kmalloc(sizeof(*hw), GFP_ATOMIC);
- if (!hw)
- return -ENOMEM;
+ hw = kmalloc(sizeof(*hw), GFP_ATOMIC);
+ if (!hw)
+ return -ENOMEM;
DBG_MSG("intelfb_set_par (%dx%d-%d)\n", info->var.xres,
info->var.yres, info->var.bits_per_pixel);
@@ -1384,15 +1356,15 @@ intelfb_set_par(struct fb_info *info)
if (ACCEL(dinfo, info))
intelfbhw_2d_stop(dinfo);
- memcpy(hw, &dinfo->save_state, sizeof(*hw));
- if (intelfbhw_mode_to_hw(dinfo, hw, &info->var))
- goto invalid_mode;
- if (intelfbhw_program_mode(dinfo, hw, 0))
- goto invalid_mode;
+ memcpy(hw, &dinfo->save_state, sizeof(*hw));
+ if (intelfbhw_mode_to_hw(dinfo, hw, &info->var))
+ goto invalid_mode;
+ if (intelfbhw_program_mode(dinfo, hw, 0))
+ goto invalid_mode;
#if REGDUMP > 0
- intelfbhw_read_hw_state(dinfo, hw, 0);
- intelfbhw_print_hw_state(dinfo, hw);
+ intelfbhw_read_hw_state(dinfo, hw, 0);
+ intelfbhw_print_hw_state(dinfo, hw);
#endif
update_dinfo(dinfo, &info->var);
@@ -1408,9 +1380,9 @@ intelfb_set_par(struct fb_info *info)
info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
FBINFO_HWACCEL_IMAGEBLIT;
- } else {
+ } else
info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
- }
+
kfree(hw);
return 0;
invalid_mode:
@@ -1418,9 +1390,9 @@ invalid_mode:
return -EINVAL;
}
-static int
-intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp, struct fb_info *info)
+static int intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *info)
{
struct intelfb_info *dinfo = GET_DINFO(info);
@@ -1463,23 +1435,22 @@ intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
return 0;
}
-static int
-intelfb_blank(int blank, struct fb_info *info)
+static int intelfb_blank(int blank, struct fb_info *info)
{
intelfbhw_do_blank(blank, info);
return 0;
}
-static int
-intelfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+static int intelfb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
{
intelfbhw_pan_display(var, info);
return 0;
}
/* When/if we have our own ioctls. */
-static int
-intelfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
+static int intelfb_ioctl(struct fb_info *info, unsigned int cmd,
+ unsigned long arg)
{
int retval = 0;
struct intelfb_info *dinfo = GET_DINFO(info);
@@ -1499,8 +1470,8 @@ intelfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
return retval;
}
-static void
-intelfb_fillrect (struct fb_info *info, const struct fb_fillrect *rect)
+static void intelfb_fillrect (struct fb_info *info,
+ const struct fb_fillrect *rect)
{
struct intelfb_info *dinfo = GET_DINFO(info);
u32 rop, color;
@@ -1514,7 +1485,7 @@ intelfb_fillrect (struct fb_info *info, const struct fb_fillrect *rect)
if (rect->rop == ROP_COPY)
rop = PAT_ROP_GXCOPY;
- else // ROP_XOR
+ else /* ROP_XOR */
rop = PAT_ROP_GXXOR;
if (dinfo->depth != 8)
@@ -1528,8 +1499,8 @@ intelfb_fillrect (struct fb_info *info, const struct fb_fillrect *rect)
rop);
}
-static void
-intelfb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
+static void intelfb_copyarea(struct fb_info *info,
+ const struct fb_copyarea *region)
{
struct intelfb_info *dinfo = GET_DINFO(info);
@@ -1545,8 +1516,8 @@ intelfb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
dinfo->pitch, info->var.bits_per_pixel);
}
-static void
-intelfb_imageblit(struct fb_info *info, const struct fb_image *image)
+static void intelfb_imageblit(struct fb_info *info,
+ const struct fb_image *image)
{
struct intelfb_info *dinfo = GET_DINFO(info);
u32 fgcolor, bgcolor;
@@ -1574,8 +1545,7 @@ intelfb_imageblit(struct fb_info *info, const struct fb_image *image)
return cfb_imageblit(info, image);
}
-static int
-intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+static int intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
struct intelfb_info *dinfo = GET_DINFO(info);
u32 physical;
@@ -1689,8 +1659,7 @@ intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
return 0;
}
-static int
-intelfb_sync(struct fb_info *info)
+static int intelfb_sync(struct fb_info *info)
{
struct intelfb_info *dinfo = GET_DINFO(info);
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c
index 6a47682d8614..5f6fb7d2c408 100644
--- a/drivers/video/intelfb/intelfbhw.c
+++ b/drivers/video/intelfb/intelfbhw.c
@@ -3,7 +3,7 @@
*
* Linux framebuffer driver for Intel(R) 865G integrated graphics chips.
*
- * Copyright © 2002, 2003 David Dawes <dawes@xfree86.org>
+ * Copyright © 2002, 2003 David Dawes <dawes@xfree86.org>
* 2004 Sylvain Meyer
*
* This driver consists of two parts. The first part (intelfbdrv.c) provides
@@ -56,17 +56,16 @@ static struct pll_min_max plls[PLLS_MAX] = {
6, 16, 3, 16,
4, 128, 0, 31,
930000, 1400000, 165000, 48000,
- 4, 2 }, //I8xx
+ 4, 2 }, /* I8xx */
{ 75, 120, 10, 20,
5, 9, 4, 7,
5, 80, 1, 8,
1400000, 2800000, 200000, 96000,
- 10, 5 } //I9xx
+ 10, 5 } /* I9xx */
};
-int
-intelfbhw_get_chipset(struct pci_dev *pdev, struct intelfb_info *dinfo)
+int intelfbhw_get_chipset(struct pci_dev *pdev, struct intelfb_info *dinfo)
{
u32 tmp;
if (!pdev || !dinfo)
@@ -149,9 +148,8 @@ intelfbhw_get_chipset(struct pci_dev *pdev, struct intelfb_info *dinfo)
}
}
-int
-intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size,
- int *stolen_size)
+int intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size,
+ int *stolen_size)
{
struct pci_dev *bridge_dev;
u16 tmp;
@@ -254,8 +252,7 @@ intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size,
}
}
-int
-intelfbhw_check_non_crt(struct intelfb_info *dinfo)
+int intelfbhw_check_non_crt(struct intelfb_info *dinfo)
{
int dvo = 0;
@@ -271,8 +268,7 @@ intelfbhw_check_non_crt(struct intelfb_info *dinfo)
return dvo;
}
-const char *
-intelfbhw_dvo_to_string(int dvo)
+const char * intelfbhw_dvo_to_string(int dvo)
{
if (dvo & DVOA_PORT)
return "DVO port A";
@@ -287,9 +283,8 @@ intelfbhw_dvo_to_string(int dvo)
}
-int
-intelfbhw_validate_mode(struct intelfb_info *dinfo,
- struct fb_var_screeninfo *var)
+int intelfbhw_validate_mode(struct intelfb_info *dinfo,
+ struct fb_var_screeninfo *var)
{
int bytes_per_pixel;
int tmp;
@@ -322,17 +317,26 @@ intelfbhw_validate_mode(struct intelfb_info *dinfo,
var->yres, VACTIVE_MASK + 1);
return 1;
}
-
- /* Check for interlaced/doublescan modes. */
- if (var->vmode & FB_VMODE_INTERLACED) {
- WRN_MSG("Mode is interlaced.\n");
+ if (var->xres < 4) {
+ WRN_MSG("X resolution too small (%d vs 4).\n", var->xres);
+ return 1;
+ }
+ if (var->yres < 4) {
+ WRN_MSG("Y resolution too small (%d vs 4).\n", var->yres);
return 1;
}
+
+ /* Check for doublescan modes. */
if (var->vmode & FB_VMODE_DOUBLE) {
WRN_MSG("Mode is double-scan.\n");
return 1;
}
+ if ((var->vmode & FB_VMODE_INTERLACED) && (var->yres & 1)) {
+ WRN_MSG("Odd number of lines in interlaced mode\n");
+ return 1;
+ }
+
/* Check if clock is OK. */
tmp = 1000000000 / var->pixclock;
if (tmp < MIN_CLOCK) {
@@ -349,8 +353,7 @@ intelfbhw_validate_mode(struct intelfb_info *dinfo,
return 0;
}
-int
-intelfbhw_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+int intelfbhw_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
{
struct intelfb_info *dinfo = GET_DINFO(info);
u32 offset, xoffset, yoffset;
@@ -372,9 +375,10 @@ intelfbhw_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
offset += dinfo->fb.offset << 12;
dinfo->vsync.pan_offset = offset;
- if ((var->activate & FB_ACTIVATE_VBL) && !intelfbhw_enable_irq(dinfo, 0)) {
+ if ((var->activate & FB_ACTIVATE_VBL) &&
+ !intelfbhw_enable_irq(dinfo))
dinfo->vsync.pan_display = 1;
- } else {
+ else {
dinfo->vsync.pan_display = 0;
OUTREG(DSPABASE, offset);
}
@@ -383,8 +387,7 @@ intelfbhw_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
}
/* Blank the screen. */
-void
-intelfbhw_do_blank(int blank, struct fb_info *info)
+void intelfbhw_do_blank(int blank, struct fb_info *info)
{
struct intelfb_info *dinfo = GET_DINFO(info);
u32 tmp;
@@ -409,11 +412,10 @@ intelfbhw_do_blank(int blank, struct fb_info *info)
DBG_MSG("cursor_on is %d\n", dinfo->cursor_on);
#endif
if (dinfo->cursor_on) {
- if (blank) {
+ if (blank)
intelfbhw_cursor_hide(dinfo);
- } else {
+ else
intelfbhw_cursor_show(dinfo);
- }
dinfo->cursor_on = 1;
}
dinfo->cursor_blanked = blank;
@@ -441,19 +443,18 @@ intelfbhw_do_blank(int blank, struct fb_info *info)
}
-void
-intelfbhw_setcolreg(struct intelfb_info *dinfo, unsigned regno,
- unsigned red, unsigned green, unsigned blue,
- unsigned transp)
+void intelfbhw_setcolreg(struct intelfb_info *dinfo, unsigned regno,
+ unsigned red, unsigned green, unsigned blue,
+ unsigned transp)
{
+ u32 palette_reg = (dinfo->pipe == PIPE_A) ?
+ PALETTE_A : PALETTE_B;
+
#if VERBOSE > 0
DBG_MSG("intelfbhw_setcolreg: %d: (%d, %d, %d)\n",
regno, red, green, blue);
#endif
- u32 palette_reg = (dinfo->pipe == PIPE_A) ?
- PALETTE_A : PALETTE_B;
-
OUTREG(palette_reg + (regno << 2),
(red << PALETTE_8_RED_SHIFT) |
(green << PALETTE_8_GREEN_SHIFT) |
@@ -461,9 +462,8 @@ intelfbhw_setcolreg(struct intelfb_info *dinfo, unsigned regno,
}
-int
-intelfbhw_read_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw,
- int flag)
+int intelfbhw_read_hw_state(struct intelfb_info *dinfo,
+ struct intelfb_hwstate *hw, int flag)
{
int i;
@@ -610,7 +610,8 @@ static int calc_vclock3(int index, int m, int n, int p)
return plls[index].ref_clk * m / n / p;
}
-static int calc_vclock(int index, int m1, int m2, int n, int p1, int p2, int lvds)
+static int calc_vclock(int index, int m1, int m2, int n, int p1, int p2,
+ int lvds)
{
struct pll_min_max *pll = &plls[index];
u32 m, vco, p;
@@ -619,17 +620,16 @@ static int calc_vclock(int index, int m1, int m2, int n, int p1, int p2, int lvd
n += 2;
vco = pll->ref_clk * m / n;
- if (index == PLLS_I8xx) {
+ if (index == PLLS_I8xx)
p = ((p1 + 2) * (1 << (p2 + 1)));
- } else {
+ else
p = ((p1) * (p2 ? 5 : 10));
- }
return vco / p;
}
#if REGDUMP
-static void
-intelfbhw_get_p1p2(struct intelfb_info *dinfo, int dpll, int *o_p1, int *o_p2)
+static void intelfbhw_get_p1p2(struct intelfb_info *dinfo, int dpll,
+ int *o_p1, int *o_p2)
{
int p1, p2;
@@ -638,7 +638,7 @@ intelfbhw_get_p1p2(struct intelfb_info *dinfo, int dpll, int *o_p1, int *o_p2)
p1 = 1;
else
p1 = (dpll >> DPLL_P1_SHIFT) & 0xff;
-
+
p1 = ffs(p1);
p2 = (dpll >> DPLL_I9XX_P2_SHIFT) & DPLL_P2_MASK;
@@ -656,8 +656,8 @@ intelfbhw_get_p1p2(struct intelfb_info *dinfo, int dpll, int *o_p1, int *o_p2)
#endif
-void
-intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw)
+void intelfbhw_print_hw_state(struct intelfb_info *dinfo,
+ struct intelfb_hwstate *hw)
{
#if REGDUMP
int i, m1, m2, n, p1, p2;
@@ -670,7 +670,7 @@ intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw)
printk("hw state dump start\n");
printk(" VGA0_DIVISOR: 0x%08x\n", hw->vga0_divisor);
printk(" VGA1_DIVISOR: 0x%08x\n", hw->vga1_divisor);
- printk(" VGAPD: 0x%08x\n", hw->vga_pd);
+ printk(" VGAPD: 0x%08x\n", hw->vga_pd);
n = (hw->vga0_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
m1 = (hw->vga0_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
m2 = (hw->vga0_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
@@ -689,7 +689,8 @@ intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw)
intelfbhw_get_p1p2(dinfo, hw->vga_pd, &p1, &p2);
printk(" VGA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
m1, m2, n, p1, p2);
- printk(" VGA1: clock is %d\n", calc_vclock(index, m1, m2, n, p1, p2, 0));
+ printk(" VGA1: clock is %d\n",
+ calc_vclock(index, m1, m2, n, p1, p2, 0));
printk(" DPLL_A: 0x%08x\n", hw->dpll_a);
printk(" DPLL_B: 0x%08x\n", hw->dpll_b);
@@ -706,7 +707,8 @@ intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw)
printk(" PLLA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
m1, m2, n, p1, p2);
- printk(" PLLA0: clock is %d\n", calc_vclock(index, m1, m2, n, p1, p2, 0));
+ printk(" PLLA0: clock is %d\n",
+ calc_vclock(index, m1, m2, n, p1, p2, 0));
n = (hw->fpa1 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
m1 = (hw->fpa1 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
@@ -716,7 +718,8 @@ intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw)
printk(" PLLA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
m1, m2, n, p1, p2);
- printk(" PLLA1: clock is %d\n", calc_vclock(index, m1, m2, n, p1, p2, 0));
+ printk(" PLLA1: clock is %d\n",
+ calc_vclock(index, m1, m2, n, p1, p2, 0));
#if 0
printk(" PALETTE_A:\n");
@@ -821,8 +824,8 @@ intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw)
/* Split the M parameter into M1 and M2. */
-static int
-splitm(int index, unsigned int m, unsigned int *retm1, unsigned int *retm2)
+static int splitm(int index, unsigned int m, unsigned int *retm1,
+ unsigned int *retm2)
{
int m1, m2;
int testm;
@@ -843,8 +846,8 @@ splitm(int index, unsigned int m, unsigned int *retm1, unsigned int *retm2)
}
/* Split the P parameter into P1 and P2. */
-static int
-splitp(int index, unsigned int p, unsigned int *retp1, unsigned int *retp2)
+static int splitp(int index, unsigned int p, unsigned int *retp1,
+ unsigned int *retp2)
{
int p1, p2;
struct pll_min_max *pll = &plls[index];
@@ -878,9 +881,8 @@ splitp(int index, unsigned int p, unsigned int *retp1, unsigned int *retp2)
}
}
-static int
-calc_pll_params(int index, int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *retp1,
- u32 *retp2, u32 *retclock)
+static int calc_pll_params(int index, int clock, u32 *retm1, u32 *retm2,
+ u32 *retn, u32 *retp1, u32 *retp2, u32 *retclock)
{
u32 m1, m2, n, p1, p2, n1, testm;
u32 f_vco, p, p_best = 0, m, f_out = 0;
@@ -975,8 +977,8 @@ calc_pll_params(int index, int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *re
return 0;
}
-static __inline__ int
-check_overflow(u32 value, u32 limit, const char *description)
+static __inline__ int check_overflow(u32 value, u32 limit,
+ const char *description)
{
if (value > limit) {
WRN_MSG("%s value %d exceeds limit %d\n",
@@ -987,9 +989,9 @@ check_overflow(u32 value, u32 limit, const char *description)
}
/* It is assumed that hw is filled in with the initial state information. */
-int
-intelfbhw_mode_to_hw(struct intelfb_info *dinfo, struct intelfb_hwstate *hw,
- struct fb_var_screeninfo *var)
+int intelfbhw_mode_to_hw(struct intelfb_info *dinfo,
+ struct intelfb_hwstate *hw,
+ struct fb_var_screeninfo *var)
{
int pipe = PIPE_A;
u32 *dpll, *fp0, *fp1;
@@ -1093,9 +1095,8 @@ intelfbhw_mode_to_hw(struct intelfb_info *dinfo, struct intelfb_hwstate *hw,
if (IS_I9XX(dinfo)) {
*dpll |= (p2 << DPLL_I9XX_P2_SHIFT);
*dpll |= (1 << (p1 - 1)) << DPLL_P1_SHIFT;
- } else {
+ } else
*dpll |= (p2 << DPLL_P2_SHIFT) | (p1 << DPLL_P1_SHIFT);
- }
*fp0 = (n << FP_N_DIVISOR_SHIFT) |
(m1 << FP_M1_DIVISOR_SHIFT) |
@@ -1139,6 +1140,8 @@ intelfbhw_mode_to_hw(struct intelfb_info *dinfo, struct intelfb_hwstate *hw,
hblank_end);
vactive = var->yres;
+ if (var->vmode & FB_VMODE_INTERLACED)
+ vactive--; /* the chip adds 2 halflines automatically */
vsync_start = vactive + var->lower_margin;
vsync_end = vsync_start + var->vsync_len;
vtotal = vsync_end + var->upper_margin;
@@ -1220,19 +1223,24 @@ intelfbhw_mode_to_hw(struct intelfb_info *dinfo, struct intelfb_hwstate *hw,
/* Set the palette to 8-bit mode. */
*pipe_conf &= ~PIPECONF_GAMMA;
+
+ if (var->vmode & FB_VMODE_INTERLACED)
+ *pipe_conf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
+ else
+ *pipe_conf &= ~PIPECONF_INTERLACE_MASK;
+
return 0;
}
/* Program a (non-VGA) video mode. */
-int
-intelfbhw_program_mode(struct intelfb_info *dinfo,
- const struct intelfb_hwstate *hw, int blank)
+int intelfbhw_program_mode(struct intelfb_info *dinfo,
+ const struct intelfb_hwstate *hw, int blank)
{
int pipe = PIPE_A;
u32 tmp;
const u32 *dpll, *fp0, *fp1, *pipe_conf;
const u32 *hs, *ht, *hb, *vs, *vt, *vb, *ss;
- u32 dpll_reg, fp0_reg, fp1_reg, pipe_conf_reg;
+ u32 dpll_reg, fp0_reg, fp1_reg, pipe_conf_reg, pipe_stat_reg;
u32 hsync_reg, htotal_reg, hblank_reg;
u32 vsync_reg, vtotal_reg, vblank_reg;
u32 src_size_reg;
@@ -1273,6 +1281,7 @@ intelfbhw_program_mode(struct intelfb_info *dinfo,
fp0_reg = FPB0;
fp1_reg = FPB1;
pipe_conf_reg = PIPEBCONF;
+ pipe_stat_reg = PIPEBSTAT;
hsync_reg = HSYNC_B;
htotal_reg = HTOTAL_B;
hblank_reg = HBLANK_B;
@@ -1296,6 +1305,7 @@ intelfbhw_program_mode(struct intelfb_info *dinfo,
fp0_reg = FPA0;
fp1_reg = FPA1;
pipe_conf_reg = PIPEACONF;
+ pipe_stat_reg = PIPEASTAT;
hsync_reg = HSYNC_A;
htotal_reg = HTOTAL_A;
hblank_reg = HBLANK_A;
@@ -1312,8 +1322,8 @@ intelfbhw_program_mode(struct intelfb_info *dinfo,
count = 0;
do {
- tmp_val[count%3] = INREG(0x70000);
- if ((tmp_val[0] == tmp_val[1]) && (tmp_val[1]==tmp_val[2]))
+ tmp_val[count % 3] = INREG(PIPEA_DSL);
+ if ((tmp_val[0] == tmp_val[1]) && (tmp_val[1] == tmp_val[2]))
break;
count++;
udelay(1);
@@ -1322,7 +1332,7 @@ intelfbhw_program_mode(struct intelfb_info *dinfo,
tmp &= ~PIPECONF_ENABLE;
OUTREG(pipe_conf_reg, tmp);
}
- } while(count < 2000);
+ } while (count < 2000);
OUTREG(ADPA, INREG(ADPA) & ~ADPA_DAC_ENABLE);
@@ -1382,6 +1392,17 @@ intelfbhw_program_mode(struct intelfb_info *dinfo,
OUTREG(vtotal_reg, *vt);
OUTREG(src_size_reg, *ss);
+ switch (dinfo->info->var.vmode & (FB_VMODE_INTERLACED |
+ FB_VMODE_ODD_FLD_FIRST)) {
+ case FB_VMODE_INTERLACED | FB_VMODE_ODD_FLD_FIRST:
+ OUTREG(pipe_stat_reg, 0xFFFF | PIPESTAT_FLD_EVT_ODD_EN);
+ break;
+ case FB_VMODE_INTERLACED: /* even lines first */
+ OUTREG(pipe_stat_reg, 0xFFFF | PIPESTAT_FLD_EVT_EVEN_EN);
+ break;
+ default: /* non-interlaced */
+ OUTREG(pipe_stat_reg, 0xFFFF); /* clear all status bits only */
+ }
/* Enable pipe */
OUTREG(pipe_conf_reg, *pipe_conf | PIPECONF_ENABLE);
@@ -1446,8 +1467,7 @@ static u32 get_ring_space(struct intelfb_info *dinfo)
return ring_space;
}
-static int
-wait_ring(struct intelfb_info *dinfo, int n)
+static int wait_ring(struct intelfb_info *dinfo, int n)
{
int i = 0;
unsigned long end;
@@ -1489,16 +1509,15 @@ wait_ring(struct intelfb_info *dinfo, int n)
return i;
}
-static void
-do_flush(struct intelfb_info *dinfo) {
+static void do_flush(struct intelfb_info *dinfo)
+{
START_RING(2);
OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
OUT_RING(MI_NOOP);
ADVANCE_RING();
}
-void
-intelfbhw_do_sync(struct intelfb_info *dinfo)
+void intelfbhw_do_sync(struct intelfb_info *dinfo)
{
#if VERBOSE > 0
DBG_MSG("intelfbhw_do_sync\n");
@@ -1517,8 +1536,7 @@ intelfbhw_do_sync(struct intelfb_info *dinfo)
dinfo->ring_space = dinfo->ring.size - RING_MIN_FREE;
}
-static void
-refresh_ring(struct intelfb_info *dinfo)
+static void refresh_ring(struct intelfb_info *dinfo)
{
#if VERBOSE > 0
DBG_MSG("refresh_ring\n");
@@ -1529,8 +1547,7 @@ refresh_ring(struct intelfb_info *dinfo)
dinfo->ring_space = get_ring_space(dinfo);
}
-static void
-reset_state(struct intelfb_info *dinfo)
+static void reset_state(struct intelfb_info *dinfo)
{
int i;
u32 tmp;
@@ -1560,12 +1577,11 @@ reset_state(struct intelfb_info *dinfo)
}
/* Stop the 2D engine, and turn off the ring buffer. */
-void
-intelfbhw_2d_stop(struct intelfb_info *dinfo)
+void intelfbhw_2d_stop(struct intelfb_info *dinfo)
{
#if VERBOSE > 0
- DBG_MSG("intelfbhw_2d_stop: accel: %d, ring_active: %d\n", dinfo->accel,
- dinfo->ring_active);
+ DBG_MSG("intelfbhw_2d_stop: accel: %d, ring_active: %d\n",
+ dinfo->accel, dinfo->ring_active);
#endif
if (!dinfo->accel)
@@ -1580,8 +1596,7 @@ intelfbhw_2d_stop(struct intelfb_info *dinfo)
* It is assumed that the graphics engine has been stopped by previously
* calling intelfb_2d_stop().
*/
-void
-intelfbhw_2d_start(struct intelfb_info *dinfo)
+void intelfbhw_2d_start(struct intelfb_info *dinfo)
{
#if VERBOSE > 0
DBG_MSG("intelfbhw_2d_start: accel: %d, ring_active: %d\n",
@@ -1605,9 +1620,8 @@ intelfbhw_2d_start(struct intelfb_info *dinfo)
}
/* 2D fillrect (solid fill or invert) */
-void
-intelfbhw_do_fillrect(struct intelfb_info *dinfo, u32 x, u32 y, u32 w, u32 h,
- u32 color, u32 pitch, u32 bpp, u32 rop)
+void intelfbhw_do_fillrect(struct intelfb_info *dinfo, u32 x, u32 y, u32 w,
+ u32 h, u32 color, u32 pitch, u32 bpp, u32 rop)
{
u32 br00, br09, br13, br14, br16;
@@ -1696,9 +1710,9 @@ intelfbhw_do_bitblt(struct intelfb_info *dinfo, u32 curx, u32 cury,
ADVANCE_RING();
}
-int
-intelfbhw_do_drawglyph(struct intelfb_info *dinfo, u32 fg, u32 bg, u32 w,
- u32 h, const u8* cdat, u32 x, u32 y, u32 pitch, u32 bpp)
+int intelfbhw_do_drawglyph(struct intelfb_info *dinfo, u32 fg, u32 bg, u32 w,
+ u32 h, const u8* cdat, u32 x, u32 y, u32 pitch,
+ u32 bpp)
{
int nbytes, ndwords, pad, tmp;
u32 br00, br09, br13, br18, br19, br22, br23;
@@ -1785,8 +1799,7 @@ intelfbhw_do_drawglyph(struct intelfb_info *dinfo, u32 fg, u32 bg, u32 w,
}
/* HW cursor functions. */
-void
-intelfbhw_cursor_init(struct intelfb_info *dinfo)
+void intelfbhw_cursor_init(struct intelfb_info *dinfo)
{
u32 tmp;
@@ -1817,8 +1830,7 @@ intelfbhw_cursor_init(struct intelfb_info *dinfo)
}
}
-void
-intelfbhw_cursor_hide(struct intelfb_info *dinfo)
+void intelfbhw_cursor_hide(struct intelfb_info *dinfo)
{
u32 tmp;
@@ -1843,8 +1855,7 @@ intelfbhw_cursor_hide(struct intelfb_info *dinfo)
}
}
-void
-intelfbhw_cursor_show(struct intelfb_info *dinfo)
+void intelfbhw_cursor_show(struct intelfb_info *dinfo)
{
u32 tmp;
@@ -1873,8 +1884,7 @@ intelfbhw_cursor_show(struct intelfb_info *dinfo)
}
}
-void
-intelfbhw_cursor_setpos(struct intelfb_info *dinfo, int x, int y)
+void intelfbhw_cursor_setpos(struct intelfb_info *dinfo, int x, int y)
{
u32 tmp;
@@ -1892,13 +1902,11 @@ intelfbhw_cursor_setpos(struct intelfb_info *dinfo, int x, int y)
((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
OUTREG(CURSOR_A_POSITION, tmp);
- if (IS_I9XX(dinfo)) {
+ if (IS_I9XX(dinfo))
OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);
- }
}
-void
-intelfbhw_cursor_setcolor(struct intelfb_info *dinfo, u32 bg, u32 fg)
+void intelfbhw_cursor_setcolor(struct intelfb_info *dinfo, u32 bg, u32 fg)
{
#if VERBOSE > 0
DBG_MSG("intelfbhw_cursor_setcolor\n");
@@ -1910,9 +1918,8 @@ intelfbhw_cursor_setcolor(struct intelfb_info *dinfo, u32 bg, u32 fg)
OUTREG(CURSOR_A_PALETTE3, bg & CURSOR_PALETTE_MASK);
}
-void
-intelfbhw_cursor_load(struct intelfb_info *dinfo, int width, int height,
- u8 *data)
+void intelfbhw_cursor_load(struct intelfb_info *dinfo, int width, int height,
+ u8 *data)
{
u8 __iomem *addr = (u8 __iomem *)dinfo->cursor.virtual;
int i, j, w = width / 8;
@@ -1940,8 +1947,8 @@ intelfbhw_cursor_load(struct intelfb_info *dinfo, int width, int height,
}
}
-void
-intelfbhw_cursor_reset(struct intelfb_info *dinfo) {
+void intelfbhw_cursor_reset(struct intelfb_info *dinfo)
+{
u8 __iomem *addr = (u8 __iomem *)dinfo->cursor.virtual;
int i, j;
@@ -1961,72 +1968,72 @@ intelfbhw_cursor_reset(struct intelfb_info *dinfo) {
}
}
-static irqreturn_t
-intelfbhw_irq(int irq, void *dev_id) {
- int handled = 0;
+static irqreturn_t intelfbhw_irq(int irq, void *dev_id)
+{
u16 tmp;
struct intelfb_info *dinfo = (struct intelfb_info *)dev_id;
spin_lock(&dinfo->int_lock);
tmp = INREG16(IIR);
- tmp &= VSYNC_PIPE_A_INTERRUPT;
+ if (dinfo->info->var.vmode & FB_VMODE_INTERLACED)
+ tmp &= PIPE_A_EVENT_INTERRUPT;
+ else
+ tmp &= VSYNC_PIPE_A_INTERRUPT; /* non-interlaced */
if (tmp == 0) {
spin_unlock(&dinfo->int_lock);
- return IRQ_RETVAL(handled);
+ return IRQ_RETVAL(0); /* not us */
}
- OUTREG16(IIR, tmp);
+ /* clear status bits 0-15 ASAP and don't touch bits 16-31 */
+ OUTREG(PIPEASTAT, INREG(PIPEASTAT));
- if (tmp & VSYNC_PIPE_A_INTERRUPT) {
- dinfo->vsync.count++;
- if (dinfo->vsync.pan_display) {
- dinfo->vsync.pan_display = 0;
- OUTREG(DSPABASE, dinfo->vsync.pan_offset);
- }
- wake_up_interruptible(&dinfo->vsync.wait);
- handled = 1;
+ OUTREG16(IIR, tmp);
+ if (dinfo->vsync.pan_display) {
+ dinfo->vsync.pan_display = 0;
+ OUTREG(DSPABASE, dinfo->vsync.pan_offset);
}
+ dinfo->vsync.count++;
+ wake_up_interruptible(&dinfo->vsync.wait);
+
spin_unlock(&dinfo->int_lock);
- return IRQ_RETVAL(handled);
+ return IRQ_RETVAL(1);
}
-int
-intelfbhw_enable_irq(struct intelfb_info *dinfo, int reenable) {
-
+int intelfbhw_enable_irq(struct intelfb_info *dinfo)
+{
+ u16 tmp;
if (!test_and_set_bit(0, &dinfo->irq_flags)) {
if (request_irq(dinfo->pdev->irq, intelfbhw_irq, IRQF_SHARED,
- "intelfb", dinfo)) {
+ "intelfb", dinfo)) {
clear_bit(0, &dinfo->irq_flags);
return -EINVAL;
}
spin_lock_irq(&dinfo->int_lock);
- OUTREG16(HWSTAM, 0xfffe);
- OUTREG16(IMR, 0x0);
- OUTREG16(IER, VSYNC_PIPE_A_INTERRUPT);
- spin_unlock_irq(&dinfo->int_lock);
- } else if (reenable) {
- u16 ier;
-
+ OUTREG16(HWSTAM, 0xfffe); /* i830 DRM uses ffff */
+ OUTREG16(IMR, 0);
+ } else
spin_lock_irq(&dinfo->int_lock);
- ier = INREG16(IER);
- if ((ier & VSYNC_PIPE_A_INTERRUPT)) {
- DBG_MSG("someone disabled the IRQ [%08X]\n", ier);
- OUTREG(IER, VSYNC_PIPE_A_INTERRUPT);
- }
- spin_unlock_irq(&dinfo->int_lock);
+
+ if (dinfo->info->var.vmode & FB_VMODE_INTERLACED)
+ tmp = PIPE_A_EVENT_INTERRUPT;
+ else
+ tmp = VSYNC_PIPE_A_INTERRUPT; /* non-interlaced */
+ if (tmp != INREG16(IER)) {
+ DBG_MSG("changing IER to 0x%X\n", tmp);
+ OUTREG16(IER, tmp);
}
+
+ spin_unlock_irq(&dinfo->int_lock);
return 0;
}
-void
-intelfbhw_disable_irq(struct intelfb_info *dinfo) {
- u16 tmp;
-
+void intelfbhw_disable_irq(struct intelfb_info *dinfo)
+{
if (test_and_clear_bit(0, &dinfo->irq_flags)) {
if (dinfo->vsync.pan_display) {
dinfo->vsync.pan_display = 0;
@@ -2037,16 +2044,15 @@ intelfbhw_disable_irq(struct intelfb_info *dinfo) {
OUTREG16(IMR, 0xffff);
OUTREG16(IER, 0x0);
- tmp = INREG16(IIR);
- OUTREG16(IIR, tmp);
+ OUTREG16(IIR, INREG16(IIR)); /* clear IRQ requests */
spin_unlock_irq(&dinfo->int_lock);
free_irq(dinfo->pdev->irq, dinfo);
}
}
-int
-intelfbhw_wait_for_vsync(struct intelfb_info *dinfo, u32 pipe) {
+int intelfbhw_wait_for_vsync(struct intelfb_info *dinfo, u32 pipe)
+{
struct intelfb_vsync *vsync;
unsigned int count;
int ret;
@@ -2059,18 +2065,16 @@ intelfbhw_wait_for_vsync(struct intelfb_info *dinfo, u32 pipe) {
return -ENODEV;
}
- ret = intelfbhw_enable_irq(dinfo, 0);
- if (ret) {
+ ret = intelfbhw_enable_irq(dinfo);
+ if (ret)
return ret;
- }
count = vsync->count;
- ret = wait_event_interruptible_timeout(vsync->wait, count != vsync->count, HZ/10);
- if (ret < 0) {
+ ret = wait_event_interruptible_timeout(vsync->wait,
+ count != vsync->count, HZ / 10);
+ if (ret < 0)
return ret;
- }
if (ret == 0) {
- intelfbhw_enable_irq(dinfo, 1);
DBG_MSG("wait_for_vsync timed out!\n");
return -ETIMEDOUT;
}
diff --git a/drivers/video/intelfb/intelfbhw.h b/drivers/video/intelfb/intelfbhw.h
index 8c54ba8fbdda..0b076bac321b 100644
--- a/drivers/video/intelfb/intelfbhw.h
+++ b/drivers/video/intelfb/intelfbhw.h
@@ -83,7 +83,7 @@
*/
#define RING_MIN_FREE 64
-#define IPEHR 0x2088
+#define IPEHR 0x2088
#define INSTDONE 0x2090
#define PRI_RING_EMPTY 1
@@ -93,7 +93,7 @@
#define IIR 0x20A4
#define IMR 0x20A8
#define VSYNC_PIPE_A_INTERRUPT (1 << 7)
-#define PIPE_A_EVENT_INTERRUPT (1 << 4)
+#define PIPE_A_EVENT_INTERRUPT (1 << 6)
#define VSYNC_PIPE_B_INTERRUPT (1 << 5)
#define PIPE_B_EVENT_INTERRUPT (1 << 4)
#define HOST_PORT_EVENT_INTERRUPT (1 << 3)
@@ -128,9 +128,9 @@
#define GPIOA 0x5010
#define GPIOB 0x5014
-#define GPIOC 0x5018 // this may be external DDC on i830
-#define GPIOD 0x501C // this is DVO DDC
-#define GPIOE 0x5020 // this is DVO i2C
+#define GPIOC 0x5018 /* this may be external DDC on i830 */
+#define GPIOD 0x501C /* this is DVO DDC */
+#define GPIOE 0x5020 /* this is DVO i2C */
#define GPIOF 0x5024
/* PLL registers */
@@ -269,15 +269,20 @@
#define PORT_ENABLE (1 << 31)
#define PORT_PIPE_SELECT_SHIFT 30
#define PORT_TV_FLAGS_MASK 0xFF
-#define PORT_TV_FLAGS 0xC4 // ripped from my BIOS
- // to understand and correct
+#define PORT_TV_FLAGS 0xC4 /* ripped from my BIOS
+ to understand and correct */
#define DVOA_SRCDIM 0x61124
#define DVOB_SRCDIM 0x61144
#define DVOC_SRCDIM 0x61164
+#define PIPEA_DSL 0x70000
+#define PIPEB_DSL 0x71000
#define PIPEACONF 0x70008
#define PIPEBCONF 0x71008
+#define PIPEASTAT 0x70024 /* bits 0-15 are "write 1 to clear" */
+#define PIPEBSTAT 0x71024
+
#define PIPECONF_ENABLE (1 << 31)
#define PIPECONF_DISABLE 0
#define PIPECONF_DOUBLE_WIDE (1 << 30)
@@ -286,6 +291,35 @@
#define PIPECONF_UNLOCKED 0
#define PIPECONF_GAMMA (1 << 24)
#define PIPECONF_PALETTE 0
+#define PIPECONF_PROGRESSIVE (0 << 21)
+#define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21)
+#define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21)
+#define PIPECONF_INTERLACE_MASK (7 << 21)
+
+/* enable bits, write 1 to enable */
+#define PIPESTAT_FIFO_UNDERRUN (1 << 31)
+#define PIPESTAT_CRC_ERROR_EN (1 << 29)
+#define PIPESTAT_CRC_DONE_EN (1 << 28)
+#define PIPESTAT_HOTPLUG_EN (1 << 26)
+#define PIPESTAT_VERTICAL_SYNC_EN (1 << 25)
+#define PIPESTAT_DISPLINE_COMP_EN (1 << 24)
+#define PIPESTAT_FLD_EVT_ODD_EN (1 << 21)
+#define PIPESTAT_FLD_EVT_EVEN_EN (1 << 20)
+#define PIPESTAT_TV_HOTPLUG_EN (1 << 18)
+#define PIPESTAT_VBLANK_EN (1 << 17)
+#define PIPESTAT_OVL_UPDATE_EN (1 << 16)
+/* status bits, write 1 to clear */
+#define PIPESTAT_HOTPLUG_STATE (1 << 15)
+#define PIPESTAT_CRC_ERROR (1 << 13)
+#define PIPESTAT_CRC_DONE (1 << 12)
+#define PIPESTAT_HOTPLUG (1 << 10)
+#define PIPESTAT_VSYNC (1 << 9)
+#define PIPESTAT_DISPLINE_COMP (1 << 8)
+#define PIPESTAT_FLD_EVT_ODD (1 << 5)
+#define PIPESTAT_FLD_EVT_EVEN (1 << 4)
+#define PIPESTAT_TV_HOTPLUG (1 << 2)
+#define PIPESTAT_VBLANK (1 << 1)
+#define PIPESTAT_OVL_UPDATE (1 << 0)
#define DISPARB 0x70030
#define DISPARB_AEND_MASK 0x1ff
@@ -365,7 +399,7 @@
#define DISPPLANE_8BPP (0x2<<26)
#define DISPPLANE_15_16BPP (0x4<<26)
#define DISPPLANE_16BPP (0x5<<26)
-#define DISPPLANE_32BPP_NO_ALPHA (0x6<<26)
+#define DISPPLANE_32BPP_NO_ALPHA (0x6<<26)
#define DISPPLANE_32BPP (0x7<<26)
#define DISPPLANE_STEREO_ENABLE (1<<25)
#define DISPPLANE_STEREO_DISABLE 0
@@ -567,7 +601,7 @@ extern void intelfbhw_cursor_setcolor(struct intelfb_info *dinfo, u32 bg,
extern void intelfbhw_cursor_load(struct intelfb_info *dinfo, int width,
int height, u8 *data);
extern void intelfbhw_cursor_reset(struct intelfb_info *dinfo);
-extern int intelfbhw_enable_irq(struct intelfb_info *dinfo, int reenable);
+extern int intelfbhw_enable_irq(struct intelfb_info *dinfo);
extern void intelfbhw_disable_irq(struct intelfb_info *dinfo);
extern int intelfbhw_wait_for_vsync(struct intelfb_info *dinfo, u32 pipe);
diff --git a/drivers/video/kyro/fbdev.c b/drivers/video/kyro/fbdev.c
index 1c5579907397..acb9370fdb14 100644
--- a/drivers/video/kyro/fbdev.c
+++ b/drivers/video/kyro/fbdev.c
@@ -21,7 +21,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#ifdef CONFIG_MTRR
#include <asm/mtrr.h>
#endif
diff --git a/drivers/video/logo/logo.c b/drivers/video/logo/logo.c
index 2b0f799aa8da..fc72684aae5a 100644
--- a/drivers/video/logo/logo.c
+++ b/drivers/video/logo/logo.c
@@ -34,6 +34,10 @@ extern const struct linux_logo logo_superh_vga16;
extern const struct linux_logo logo_superh_clut224;
extern const struct linux_logo logo_m32r_clut224;
+static int nologo;
+module_param(nologo, bool, 0);
+MODULE_PARM_DESC(nologo, "Disables startup logo");
+
/* logo's are marked __initdata. Use __init_refok to tell
* modpost that it is intended that this function uses data
* marked __initdata.
@@ -42,6 +46,9 @@ const struct linux_logo * __init_refok fb_find_logo(int depth)
{
const struct linux_logo *logo = NULL;
+ if (nologo)
+ return NULL;
+
if (depth >= 1) {
#ifdef CONFIG_LOGO_LINUX_MONO
/* Generic Linux logo */
@@ -71,10 +78,7 @@ const struct linux_logo * __init_refok fb_find_logo(int depth)
#endif
#ifdef CONFIG_LOGO_DEC_CLUT224
/* DEC Linux logo on MIPS/MIPS64 or ALPHA */
-#ifndef CONFIG_ALPHA
- if (mips_machgroup == MACH_GROUP_DEC)
-#endif
- logo = &logo_dec_clut224;
+ logo = &logo_dec_clut224;
#endif
#ifdef CONFIG_LOGO_MAC_CLUT224
/* Macintosh Linux logo on m68k */
@@ -87,10 +91,7 @@ const struct linux_logo * __init_refok fb_find_logo(int depth)
#endif
#ifdef CONFIG_LOGO_SGI_CLUT224
/* SGI Linux logo on MIPS/MIPS64 and VISWS */
-#ifndef CONFIG_X86_VISWS
- if (mips_machgroup == MACH_GROUP_SGI)
-#endif
- logo = &logo_sgi_clut224;
+ logo = &logo_sgi_clut224;
#endif
#ifdef CONFIG_LOGO_SUN_CLUT224
/* Sun Linux logo */
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index 86ca7b179000..b25972ac6eeb 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -113,7 +113,7 @@
#include "matroxfb_g450.h"
#include <linux/matroxfb.h>
#include <linux/interrupt.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#ifdef CONFIG_PPC_PMAC
#include <asm/machdep.h>
diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c
index 4b3344e03695..a6ab5b6a58d0 100644
--- a/drivers/video/matrox/matroxfb_crtc2.c
+++ b/drivers/video/matrox/matroxfb_crtc2.c
@@ -15,7 +15,7 @@
#include "matroxfb_misc.h"
#include "matroxfb_DAC1064.h"
#include <linux/matroxfb.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
/* **************************************************** */
diff --git a/drivers/video/matrox/matroxfb_g450.c b/drivers/video/matrox/matroxfb_g450.c
index 4d610b405d45..6209a761f674 100644
--- a/drivers/video/matrox/matroxfb_g450.c
+++ b/drivers/video/matrox/matroxfb_g450.c
@@ -17,7 +17,6 @@
#include "matroxfb_DAC1064.h"
#include "g450_pll.h"
#include <linux/matroxfb.h>
-#include <asm/uaccess.h>
#include <asm/div64.h>
#include "matroxfb_g450.h"
diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c
index de0d755f9019..49cd53e46c0a 100644
--- a/drivers/video/matrox/matroxfb_maven.c
+++ b/drivers/video/matrox/matroxfb_maven.c
@@ -18,7 +18,6 @@
#include <linux/i2c.h>
#include <linux/matroxfb.h>
#include <asm/div64.h>
-#include <asm/uaccess.h>
#define MAVEN_I2CID (0x1B)
diff --git a/drivers/video/mbx/mbxfb.c b/drivers/video/mbx/mbxfb.c
index 980d5f623902..80cd117ca65c 100644
--- a/drivers/video/mbx/mbxfb.c
+++ b/drivers/video/mbx/mbxfb.c
@@ -1,7 +1,7 @@
/*
* linux/drivers/video/mbx/mbxfb.c
*
- * Copyright (C) 2006 8D Technologies inc
+ * Copyright (C) 2006-2007 8D Technologies inc
* Raphael Assenat <raph@8d.com>
* - Added video overlay support
* - Various improvements
@@ -334,8 +334,8 @@ static int mbxfb_blank(int blank, struct fb_info *info)
static int mbxfb_setupOverlay(struct mbxfb_overlaySetup *set)
{
- u32 vsctrl, vbbase, vscadr, vsadr;
- u32 sssize, spoctrl, svctrl, shctrl;
+ u32 vsctrl, vscadr, vsadr;
+ u32 sssize, spoctrl, shctrl;
u32 vubase, vvbase;
u32 vovrclk;
@@ -349,13 +349,11 @@ static int mbxfb_setupOverlay(struct mbxfb_overlaySetup *set)
vscadr = readl(VSCADR);
vubase = readl(VUBASE);
vvbase = readl(VVBASE);
+ shctrl = readl(SHCTRL);
spoctrl = readl(SPOCTRL);
sssize = readl(SSSIZE);
-
- vbbase = Vbbase_Glalpha(set->alpha);
-
vsctrl &= ~( FMsk(VSCTRL_VSWIDTH) |
FMsk(VSCTRL_VSHEIGHT) |
FMsk(VSCTRL_VPIXFMT) |
@@ -364,38 +362,41 @@ static int mbxfb_setupOverlay(struct mbxfb_overlaySetup *set)
vsctrl |= Vsctrl_Width(set->width) | Vsctrl_Height(set->height) |
VSCTRL_CSC_EN;
- vscadr &= ~(VSCADR_STR_EN | VSCADR_COLKEY_EN | VSCADR_COLKEYSRC |
- FMsk(VSCADR_BLEND_M) | FMsk(VSCADR_BLEND_POS) |
- FMsk(VSCADR_VBASE_ADR) );
+ vscadr &= ~(VSCADR_STR_EN | FMsk(VSCADR_VBASE_ADR) );
vubase &= ~(VUBASE_UVHALFSTR | FMsk(VUBASE_UBASE_ADR));
vvbase &= ~(FMsk(VVBASE_VBASE_ADR));
- switch (set->fmt)
- {
- case MBXFB_FMT_YUV12:
- vsctrl |= VSCTRL_VPIXFMT_YUV12;
+ switch (set->fmt) {
+ case MBXFB_FMT_YUV16:
+ vsctrl |= VSCTRL_VPIXFMT_YUV12;
- set->Y_stride = ((set->width) + 0xf ) & ~0xf;
+ set->Y_stride = ((set->width) + 0xf ) & ~0xf;
+ break;
+ case MBXFB_FMT_YUV12:
+ vsctrl |= VSCTRL_VPIXFMT_YUV12;
+ set->Y_stride = ((set->width) + 0xf ) & ~0xf;
+ vubase |= VUBASE_UVHALFSTR;
+
+ break;
+ case MBXFB_FMT_UY0VY1:
+ vsctrl |= VSCTRL_VPIXFMT_UY0VY1;
+ set->Y_stride = (set->width*2 + 0xf ) & ~0xf;
+ break;
+ case MBXFB_FMT_VY0UY1:
+ vsctrl |= VSCTRL_VPIXFMT_VY0UY1;
+ set->Y_stride = (set->width*2 + 0xf ) & ~0xf;
+ break;
+ case MBXFB_FMT_Y0UY1V:
+ vsctrl |= VSCTRL_VPIXFMT_Y0UY1V;
+ set->Y_stride = (set->width*2 + 0xf ) & ~0xf;
+ break;
+ case MBXFB_FMT_Y0VY1U:
+ vsctrl |= VSCTRL_VPIXFMT_Y0VY1U;
+ set->Y_stride = (set->width*2 + 0xf ) & ~0xf;
break;
- case MBXFB_FMT_UY0VY1:
- vsctrl |= VSCTRL_VPIXFMT_UY0VY1;
- set->Y_stride = (set->width*2 + 0xf ) & ~0xf;
- break;
- case MBXFB_FMT_VY0UY1:
- vsctrl |= VSCTRL_VPIXFMT_VY0UY1;
- set->Y_stride = (set->width*2 + 0xf ) & ~0xf;
- break;
- case MBXFB_FMT_Y0UY1V:
- vsctrl |= VSCTRL_VPIXFMT_Y0UY1V;
- set->Y_stride = (set->width*2 + 0xf ) & ~0xf;
- break;
- case MBXFB_FMT_Y0VY1U:
- vsctrl |= VSCTRL_VPIXFMT_Y0VY1U;
- set->Y_stride = (set->width*2 + 0xf ) & ~0xf;
- break;
- default:
- return -EINVAL;
+ default:
+ return -EINVAL;
}
/* VSCTRL has the bits which sets the Video Pixel Format.
@@ -417,8 +418,7 @@ static int mbxfb_setupOverlay(struct mbxfb_overlaySetup *set)
(0x60000 + set->mem_offset + set->V_offset)>>3);
- vscadr |= VSCADR_BLEND_VID | VSCADR_BLEND_GLOB |
- Vscadr_Vbase_Adr((0x60000 + set->mem_offset)>>4);
+ vscadr |= Vscadr_Vbase_Adr((0x60000 + set->mem_offset)>>4);
if (set->enable)
vscadr |= VSCADR_STR_EN;
@@ -433,9 +433,8 @@ static int mbxfb_setupOverlay(struct mbxfb_overlaySetup *set)
spoctrl &= ~(SPOCTRL_H_SC_BP | SPOCTRL_V_SC_BP |
SPOCTRL_HV_SC_OR | SPOCTRL_VS_UR_C |
- FMsk(SPOCTRL_VORDER) | FMsk(SPOCTRL_VPITCH));
- spoctrl = Spoctrl_Vpitch((set->height<<11)/set->scaled_height)
- | SPOCTRL_VORDER_2TAP;
+ FMsk(SPOCTRL_VPITCH));
+ spoctrl |= Spoctrl_Vpitch((set->height<<11)/set->scaled_height);
/* Bypass horiz/vert scaler when same size */
if (set->scaled_width == set->width)
@@ -443,14 +442,11 @@ static int mbxfb_setupOverlay(struct mbxfb_overlaySetup *set)
if (set->scaled_height == set->height)
spoctrl |= SPOCTRL_V_SC_BP;
- svctrl = Svctrl_Initial1(1<<10) | Svctrl_Initial2(1<<10);
-
- shctrl = Shctrl_Hinitial(4<<11)
- | Shctrl_Hpitch((set->width<<11)/set->scaled_width);
+ shctrl &= ~(FMsk(SHCTRL_HPITCH) | SHCTRL_HDECIM);
+ shctrl |= Shctrl_Hpitch((set->width<<11)/set->scaled_width);
/* Video plane registers */
write_reg(vsctrl, VSCTRL);
- write_reg(vbbase, VBBASE);
write_reg(vscadr, VSCADR);
write_reg(vubase, VUBASE);
write_reg(vvbase, VVBASE);
@@ -459,28 +455,8 @@ static int mbxfb_setupOverlay(struct mbxfb_overlaySetup *set)
/* Video scaler registers */
write_reg(sssize, SSSIZE);
write_reg(spoctrl, SPOCTRL);
- write_reg(svctrl, SVCTRL);
write_reg(shctrl, SHCTRL);
- /* RAPH: Using those coefficients, the scaled
- * image is quite blurry. I dont know how
- * to improve them ; The chip documentation
- * was not helpful.. */
- write_reg(0x21212121, VSCOEFF0);
- write_reg(0x21212121, VSCOEFF1);
- write_reg(0x21212121, VSCOEFF2);
- write_reg(0x21212121, VSCOEFF3);
- write_reg(0x21212121, VSCOEFF4);
- write_reg(0x00000000, HSCOEFF0);
- write_reg(0x00000000, HSCOEFF1);
- write_reg(0x00000000, HSCOEFF2);
- write_reg(0x03020201, HSCOEFF3);
- write_reg(0x09070604, HSCOEFF4);
- write_reg(0x0f0e0c0a, HSCOEFF5);
- write_reg(0x15141211, HSCOEFF6);
- write_reg(0x19181716, HSCOEFF7);
- write_reg(0x00000019, HSCOEFF8);
-
/* Clock */
if (set->enable)
vovrclk |= 1;
@@ -492,27 +468,206 @@ static int mbxfb_setupOverlay(struct mbxfb_overlaySetup *set)
return 0;
}
+static int mbxfb_ioctl_planeorder(struct mbxfb_planeorder *porder)
+{
+ unsigned long gscadr, vscadr;
+
+ if (porder->bottom == porder->top)
+ return -EINVAL;
+
+ gscadr = readl(GSCADR);
+ vscadr = readl(VSCADR);
+
+ gscadr &= ~(FMsk(GSCADR_BLEND_POS));
+ vscadr &= ~(FMsk(VSCADR_BLEND_POS));
+
+ switch (porder->bottom) {
+ case MBXFB_PLANE_GRAPHICS:
+ gscadr |= GSCADR_BLEND_GFX;
+ break;
+ case MBXFB_PLANE_VIDEO:
+ vscadr |= VSCADR_BLEND_GFX;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (porder->top) {
+ case MBXFB_PLANE_GRAPHICS:
+ gscadr |= GSCADR_BLEND_VID;
+ break;
+ case MBXFB_PLANE_VIDEO:
+ vscadr |= GSCADR_BLEND_VID;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ write_reg_dly(vscadr, VSCADR);
+ write_reg_dly(gscadr, GSCADR);
+
+ return 0;
+
+}
+
+static int mbxfb_ioctl_alphactl(struct mbxfb_alphaCtl *alpha)
+{
+ unsigned long vscadr, vbbase, vcmsk;
+ unsigned long gscadr, gbbase, gdrctrl;
+
+ vbbase = Vbbase_Glalpha(alpha->overlay_global_alpha) |
+ Vbbase_Colkey(alpha->overlay_colorkey);
+
+ gbbase = Gbbase_Glalpha(alpha->graphics_global_alpha) |
+ Gbbase_Colkey(alpha->graphics_colorkey);
+
+ vcmsk = readl(VCMSK);
+ vcmsk &= ~(FMsk(VCMSK_COLKEY_M));
+ vcmsk |= Vcmsk_colkey_m(alpha->overlay_colorkey_mask);
+
+ gdrctrl = readl(GDRCTRL);
+ gdrctrl &= ~(FMsk(GDRCTRL_COLKEYM));
+ gdrctrl |= Gdrctrl_Colkeym(alpha->graphics_colorkey_mask);
+
+ vscadr = readl(VSCADR);
+ vscadr &= ~(FMsk(VSCADR_BLEND_M) | VSCADR_COLKEYSRC | VSCADR_COLKEY_EN);
+
+ gscadr = readl(GSCADR);
+ gscadr &= ~(FMsk(GSCADR_BLEND_M) | GSCADR_COLKEY_EN | GSCADR_COLKEYSRC);
+
+ switch (alpha->overlay_colorkey_mode) {
+ case MBXFB_COLORKEY_DISABLED:
+ break;
+ case MBXFB_COLORKEY_PREVIOUS:
+ vscadr |= VSCADR_COLKEY_EN;
+ break;
+ case MBXFB_COLORKEY_CURRENT:
+ vscadr |= VSCADR_COLKEY_EN | VSCADR_COLKEYSRC;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (alpha->overlay_blend_mode) {
+ case MBXFB_ALPHABLEND_NONE:
+ vscadr |= VSCADR_BLEND_NONE;
+ break;
+ case MBXFB_ALPHABLEND_GLOBAL:
+ vscadr |= VSCADR_BLEND_GLOB;
+ break;
+ case MBXFB_ALPHABLEND_PIXEL:
+ vscadr |= VSCADR_BLEND_PIX;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (alpha->graphics_colorkey_mode) {
+ case MBXFB_COLORKEY_DISABLED:
+ break;
+ case MBXFB_COLORKEY_PREVIOUS:
+ gscadr |= GSCADR_COLKEY_EN;
+ break;
+ case MBXFB_COLORKEY_CURRENT:
+ gscadr |= GSCADR_COLKEY_EN | GSCADR_COLKEYSRC;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (alpha->graphics_blend_mode) {
+ case MBXFB_ALPHABLEND_NONE:
+ gscadr |= GSCADR_BLEND_NONE;
+ break;
+ case MBXFB_ALPHABLEND_GLOBAL:
+ gscadr |= GSCADR_BLEND_GLOB;
+ break;
+ case MBXFB_ALPHABLEND_PIXEL:
+ gscadr |= GSCADR_BLEND_PIX;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ write_reg_dly(vbbase, VBBASE);
+ write_reg_dly(gbbase, GBBASE);
+ write_reg_dly(vcmsk, VCMSK);
+ write_reg_dly(gdrctrl, GDRCTRL);
+ write_reg_dly(gscadr, GSCADR);
+ write_reg_dly(vscadr, VSCADR);
+
+ return 0;
+}
+
static int mbxfb_ioctl(struct fb_info *info, unsigned int cmd,
unsigned long arg)
{
- struct mbxfb_overlaySetup setup;
+ struct mbxfb_overlaySetup setup;
+ struct mbxfb_planeorder porder;
+ struct mbxfb_alphaCtl alpha;
+ struct mbxfb_reg reg;
int res;
+ __u32 tmp;
- if (cmd == MBXFB_IOCX_OVERLAY)
+ switch (cmd)
{
- if (copy_from_user(&setup, (void __user*)arg,
- sizeof(struct mbxfb_overlaySetup)))
+ case MBXFB_IOCX_OVERLAY:
+ if (copy_from_user(&setup, (void __user*)arg,
+ sizeof(struct mbxfb_overlaySetup)))
+ return -EFAULT;
+
+ res = mbxfb_setupOverlay(&setup);
+ if (res)
+ return res;
+
+ if (copy_to_user((void __user*)arg, &setup,
+ sizeof(struct mbxfb_overlaySetup)))
+ return -EFAULT;
+
+ return 0;
+
+ case MBXFB_IOCS_PLANEORDER:
+ if (copy_from_user(&porder, (void __user*)arg,
+ sizeof(struct mbxfb_planeorder)))
return -EFAULT;
- res = mbxfb_setupOverlay(&setup);
- if (res)
- return res;
+ return mbxfb_ioctl_planeorder(&porder);
- if (copy_to_user((void __user*)arg, &setup,
- sizeof(struct mbxfb_overlaySetup)))
+ case MBXFB_IOCS_ALPHA:
+ if (copy_from_user(&alpha, (void __user*)arg,
+ sizeof(struct mbxfb_alphaCtl)))
return -EFAULT;
- return 0;
+ return mbxfb_ioctl_alphactl(&alpha);
+
+ case MBXFB_IOCS_REG:
+ if (copy_from_user(&reg, (void __user*)arg,
+ sizeof(struct mbxfb_reg)))
+ return -EFAULT;
+
+ if (reg.addr >= 0x10000) /* regs are from 0x3fe0000 to 0x3feffff */
+ return -EINVAL;
+
+ tmp = readl(virt_base_2700 + reg.addr);
+ tmp &= ~reg.mask;
+ tmp |= reg.val & reg.mask;
+ writel(tmp, virt_base_2700 + reg.addr);
+
+ return 0;
+ case MBXFB_IOCX_REG:
+ if (copy_from_user(&reg, (void __user*)arg,
+ sizeof(struct mbxfb_reg)))
+ return -EFAULT;
+
+ if (reg.addr >= 0x10000) /* regs are from 0x3fe0000 to 0x3feffff */
+ return -EINVAL;
+ reg.val = readl(virt_base_2700 + reg.addr);
+
+ if (copy_to_user((void __user*)arg, &reg,
+ sizeof(struct mbxfb_reg)))
+ return -EFAULT;
+
+ return 0;
}
return -EINVAL;
}
@@ -558,7 +713,6 @@ static void __devinit setup_memc(struct fb_info *fbi)
LMTYPE);
/* enable memory controller */
write_reg_dly(LMPWR_MC_PWR_ACT, LMPWR);
-
/* perform dummy reads */
for ( i = 0; i < 16; i++ ) {
tmp = readl(fbi->screen_base);
@@ -588,8 +742,8 @@ static void enable_clocks(struct fb_info *fbi)
write_reg_dly(0x00000000, VOVRCLK);
write_reg_dly(PIXCLK_EN, PIXCLK);
write_reg_dly(MEMCLK_EN, MEMCLK);
- write_reg_dly(0x00000006, M24CLK);
- write_reg_dly(0x00000006, MBXCLK);
+ write_reg_dly(0x00000001, M24CLK);
+ write_reg_dly(0x00000001, MBXCLK);
write_reg_dly(SDCLK_EN, SDCLK);
write_reg_dly(0x00000001, PIXCLKDIV);
}
@@ -597,6 +751,7 @@ static void enable_clocks(struct fb_info *fbi)
static void __devinit setup_graphics(struct fb_info *fbi)
{
unsigned long gsctrl;
+ unsigned long vscadr;
gsctrl = GSCTRL_GAMMA_EN | Gsctrl_Width(fbi->var.xres) |
Gsctrl_Height(fbi->var.yres);
@@ -620,6 +775,11 @@ static void __devinit setup_graphics(struct fb_info *fbi)
write_reg_dly(0x00ffffff, GDRCTRL);
write_reg_dly((GSCADR_STR_EN | Gscadr_Gbase_Adr(0x6000)), GSCADR);
write_reg_dly(0x00000000, GPLUT);
+
+ vscadr = readl(VSCADR);
+ vscadr &= ~(FMsk(VSCADR_BLEND_POS) | FMsk(VSCADR_BLEND_M));
+ vscadr |= VSCADR_BLEND_VID | VSCADR_BLEND_NONE;
+ write_reg_dly(vscadr, VSCADR);
}
static void __devinit setup_display(struct fb_info *fbi)
@@ -638,13 +798,47 @@ static void __devinit setup_display(struct fb_info *fbi)
static void __devinit enable_controller(struct fb_info *fbi)
{
+ u32 svctrl, shctrl;
+
write_reg_dly(SYSRST_RST, SYSRST);
+ /* setup a timeout, raise drive strength */
+ write_reg_dly(0xffffff0c, SYSCFG);
enable_clocks(fbi);
setup_memc(fbi);
setup_graphics(fbi);
setup_display(fbi);
+
+ shctrl = readl(SHCTRL);
+ shctrl &= ~(FMsk(SHCTRL_HINITIAL));
+ shctrl |= Shctrl_Hinitial(4<<11);
+ writel(shctrl, SHCTRL);
+
+ svctrl = Svctrl_Initial1(1<<10) | Svctrl_Initial2(1<<10);
+ writel(svctrl, SVCTRL);
+
+ writel(SPOCTRL_H_SC_BP | SPOCTRL_V_SC_BP | SPOCTRL_VORDER_4TAP
+ , SPOCTRL);
+
+ /* Those coefficients are good for scaling up. For scaling
+ * down, the application has to calculate them. */
+ write_reg(0xff000100, VSCOEFF0);
+ write_reg(0xfdfcfdfe, VSCOEFF1);
+ write_reg(0x170d0500, VSCOEFF2);
+ write_reg(0x3d372d22, VSCOEFF3);
+ write_reg(0x00000040, VSCOEFF4);
+
+ write_reg(0xff010100, HSCOEFF0);
+ write_reg(0x00000000, HSCOEFF1);
+ write_reg(0x02010000, HSCOEFF2);
+ write_reg(0x01020302, HSCOEFF3);
+ write_reg(0xf9fbfe00, HSCOEFF4);
+ write_reg(0xfbf7f6f7, HSCOEFF5);
+ write_reg(0x1c110700, HSCOEFF6);
+ write_reg(0x3e393127, HSCOEFF7);
+ write_reg(0x00000040, HSCOEFF8);
+
}
#ifdef CONFIG_PM
diff --git a/drivers/video/mbx/reg_bits.h b/drivers/video/mbx/reg_bits.h
index 9a24fb0c7d48..5f14b4befd71 100644
--- a/drivers/video/mbx/reg_bits.h
+++ b/drivers/video/mbx/reg_bits.h
@@ -215,7 +215,7 @@
/* GSCADR graphics stream control address register fields */
#define GSCADR_STR_EN (1 << 31)
#define GSCADR_COLKEY_EN (1 << 30)
-#define GSCADR_COLKEYSCR (1 << 29)
+#define GSCADR_COLKEYSRC (1 << 29)
#define GSCADR_BLEND_M Fld(2,27)
#define GSCADR_BLEND_NONE ((0x0) << FShft(GSCADR_BLEND_M))
#define GSCADR_BLEND_INV ((0x1) << FShft(GSCADR_BLEND_M))
@@ -303,6 +303,67 @@
#define VSADR_YSTART Fld(11,0)
#define Vsadr_Ystart(x) ((x) << FShft(VSADR_YSTART))
+/* VSCTRL - Video Surface Control Register */
+#define VSCTRL_VPIXFMT Fld(4,27)
+#define VSCTRL_VPIXFMT_YUV12 ((0x9) << FShft(VSCTRL_VPIXFMT))
+#define VSCTRL_VPIXFMT_UY0VY1 ((0xc) << FShft(VSCTRL_VPIXFMT))
+#define VSCTRL_VPIXFMT_VY0UY1 ((0xd) << FShft(VSCTRL_VPIXFMT))
+#define VSCTRL_VPIXFMT_Y0UY1V ((0xe) << FShft(VSCTRL_VPIXFMT))
+#define VSCTRL_VPIXFMT_Y0VY1U ((0xf) << FShft(VSCTRL_VPIXFMT))
+#define VSCTRL_GAMMA_EN (1 << 26)
+#define VSCTRL_CSC_EN (1 << 25)
+#define VSCTRL_COSITED (1 << 22)
+#define VSCTRL_VSWIDTH Fld(11,11)
+#define Vsctrl_Width(Pixels) /* Video Width [1-2048] */ \
+ (((Pixels) - 1) << FShft(VSCTRL_VSWIDTH))
+#define VSCTRL_VSHEIGHT Fld(11,0)
+#define Vsctrl_Height(Pixels) /* Video Height [1-2048] */ \
+ (((Pixels) - 1) << FShft(VSCTRL_VSHEIGHT))
+
+/* VBBASE - Video Blending Base Register */
+#define VBBASE_GLALPHA Fld(8,24)
+#define Vbbase_Glalpha(x) ((x) << FShft(VBBASE_GLALPHA))
+
+#define VBBASE_COLKEY Fld(24,0)
+#define Vbbase_Colkey(x) ((x) << FShft(VBBASE_COLKEY))
+
+/* VCMSK - Video Color Key Mask Register */
+#define VCMSK_COLKEY_M Fld(24,0)
+#define Vcmsk_colkey_m(x) ((x) << FShft(VCMSK_COLKEY_M))
+
+/* VSCADR - Video Stream Control Rddress Register */
+#define VSCADR_STR_EN (1 << 31)
+#define VSCADR_COLKEY_EN (1 << 30)
+#define VSCADR_COLKEYSRC (1 << 29)
+#define VSCADR_BLEND_M Fld(2,27)
+#define VSCADR_BLEND_NONE ((0x0) << FShft(VSCADR_BLEND_M))
+#define VSCADR_BLEND_INV ((0x1) << FShft(VSCADR_BLEND_M))
+#define VSCADR_BLEND_GLOB ((0x2) << FShft(VSCADR_BLEND_M))
+#define VSCADR_BLEND_PIX ((0x3) << FShft(VSCADR_BLEND_M))
+#define VSCADR_BLEND_POS Fld(2,24)
+#define VSCADR_BLEND_GFX ((0x0) << FShft(VSCADR_BLEND_POS))
+#define VSCADR_BLEND_VID ((0x1) << FShft(VSCADR_BLEND_POS))
+#define VSCADR_BLEND_CUR ((0x2) << FShft(VSCADR_BLEND_POS))
+#define VSCADR_VBASE_ADR Fld(23,0)
+#define Vscadr_Vbase_Adr(x) ((x) << FShft(VSCADR_VBASE_ADR))
+
+/* VUBASE - Video U Base Register */
+#define VUBASE_UVHALFSTR (1 << 31)
+#define VUBASE_UBASE_ADR Fld(24,0)
+#define Vubase_Ubase_Adr(x) ((x) << FShft(VUBASE_UBASE_ADR))
+
+/* VVBASE - Video V Base Register */
+#define VVBASE_VBASE_ADR Fld(24,0)
+#define Vvbase_Vbase_Adr(x) ((x) << FShft(VVBASE_VBASE_ADR))
+
+/* VSADR - Video Stride Address Register */
+#define VSADR_SRCSTRIDE Fld(10,22)
+#define Vsadr_Srcstride(x) ((x) << FShft(VSADR_SRCSTRIDE))
+#define VSADR_XSTART Fld(11,11)
+#define Vsadr_Xstart(x) ((x) << FShft(VSADR_XSTART))
+#define VSADR_YSTART Fld(11,0)
+#define Vsadr_Ystart(x) ((x) << FShft(VSADR_YSTART))
+
/* HCCTRL - Hardware Cursor Register fields */
#define HCCTRL_CUR_EN (1 << 31)
#define HCCTRL_COLKEY_EN (1 << 29)
@@ -479,6 +540,30 @@
#define DINTRE_HBLNK1_EN (1 << 1)
#define DINTRE_HBLNK0_EN (1 << 0)
+/* DINTRS - Display Interrupt Status Register */
+#define DINTRS_CUR_OR_S (1 << 18)
+#define DINTRS_STR2_OR_S (1 << 17)
+#define DINTRS_STR1_OR_S (1 << 16)
+#define DINTRS_CUR_UR_S (1 << 6)
+#define DINTRS_STR2_UR_S (1 << 5)
+#define DINTRS_STR1_UR_S (1 << 4)
+#define DINTRS_VEVENT1_S (1 << 3)
+#define DINTRS_VEVENT0_S (1 << 2)
+#define DINTRS_HBLNK1_S (1 << 1)
+#define DINTRS_HBLNK0_S (1 << 0)
+
+/* DINTRE - Display Interrupt Enable Register */
+#define DINTRE_CUR_OR_EN (1 << 18)
+#define DINTRE_STR2_OR_EN (1 << 17)
+#define DINTRE_STR1_OR_EN (1 << 16)
+#define DINTRE_CUR_UR_EN (1 << 6)
+#define DINTRE_STR2_UR_EN (1 << 5)
+#define DINTRE_STR1_UR_EN (1 << 4)
+#define DINTRE_VEVENT1_EN (1 << 3)
+#define DINTRE_VEVENT0_EN (1 << 2)
+#define DINTRE_HBLNK1_EN (1 << 1)
+#define DINTRE_HBLNK0_EN (1 << 0)
+
/* DLSTS - display load status register */
#define DLSTS_RLD_ADONE (1 << 23)
diff --git a/drivers/video/mbx/regs.h b/drivers/video/mbx/regs.h
index a7c63d865aad..063099d48839 100644
--- a/drivers/video/mbx/regs.h
+++ b/drivers/video/mbx/regs.h
@@ -30,7 +30,7 @@
#define VOVRCLK __REG_2700G(0x00000044)
#define PIXCLK __REG_2700G(0x00000048)
#define MEMCLK __REG_2700G(0x0000004c)
-#define M24CLK __REG_2700G(0x00000054)
+#define M24CLK __REG_2700G(0x00000050)
#define MBXCLK __REG_2700G(0x00000054)
#define SDCLK __REG_2700G(0x00000058)
#define PIXCLKDIV __REG_2700G(0x0000005c)
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
index 3741ad729401..8d81ef019c6c 100644
--- a/drivers/video/modedb.c
+++ b/drivers/video/modedb.c
@@ -27,7 +27,7 @@
#define DPRINTK(fmt, args...)
#endif
-const char *global_mode_option;
+const char *fb_mode_option;
/*
* Standard video mode definitions (taken from XFree86)
@@ -72,7 +72,7 @@ static const struct fb_videomode modedb[] = {
0, FB_VMODE_NONINTERLACED
}, {
/* 1152x864 @ 89 Hz interlaced, 44 kHz hsync */
- NULL, 69, 1152, 864, 15384, 96, 16, 110, 1, 216, 10,
+ NULL, 89, 1152, 864, 15384, 96, 16, 110, 1, 216, 10,
0, FB_VMODE_INTERLACED
}, {
/* 800x600 @ 72 Hz, 48.0 kHz hsync */
@@ -120,11 +120,11 @@ static const struct fb_videomode modedb[] = {
0, FB_VMODE_NONINTERLACED
}, {
/* 1400x1050 @ 60Hz, 63.9 kHz hsync */
- NULL, 68, 1400, 1050, 9259, 136, 40, 13, 1, 112, 3,
+ NULL, 60, 1400, 1050, 9259, 136, 40, 13, 1, 112, 3,
0, FB_VMODE_NONINTERLACED
}, {
/* 1400x1050 @ 75,107 Hz, 82,392 kHz +hsync +vsync*/
- NULL, 75, 1400, 1050, 9271, 120, 56, 13, 0, 112, 3,
+ NULL, 75, 1400, 1050, 7190, 120, 56, 23, 10, 112, 13,
FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
}, {
/* 1400x1050 @ 60 Hz, ? kHz +hsync +vsync*/
@@ -253,7 +253,7 @@ static const struct fb_videomode modedb[] = {
FB_VMODE_NONINTERLACED
}, {
/* 1152x768, 60 Hz, PowerBook G4 Titanium I and II */
- NULL, 60, 1152, 768, 15386, 158, 26, 29, 3, 136, 6,
+ NULL, 60, 1152, 768, 14047, 158, 26, 29, 3, 136, 6,
FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
}, {
/* 1366x768, 60 Hz, 47.403 kHz hsync, WXGA 16:9 aspect ratio */
@@ -306,7 +306,7 @@ const struct fb_videomode vesa_modes[] = {
FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
/* 12 1024x768i-43 VESA */
- { NULL, 53, 1024, 768, 22271, 56, 8, 41, 0, 176, 8,
+ { NULL, 43, 1024, 768, 22271, 56, 8, 41, 0, 176, 8,
FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
FB_VMODE_INTERLACED, FB_MODE_IS_VESA },
/* 13 1024x768-60 VESA */
@@ -383,7 +383,7 @@ const struct fb_videomode vesa_modes[] = {
{ NULL, 60, 1920, 1440, 4273, 344, 128, 56, 1, 200, 3,
FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
/* 33 1920x1440-75 VESA */
- { NULL, 60, 1920, 1440, 3367, 352, 144, 56, 1, 224, 3,
+ { NULL, 75, 1920, 1440, 3367, 352, 144, 56, 1, 224, 3,
FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
};
EXPORT_SYMBOL(vesa_modes);
@@ -510,7 +510,9 @@ int fb_find_mode(struct fb_var_screeninfo *var,
default_bpp = 8;
/* Did the user specify a video mode? */
- if (mode_option || (mode_option = global_mode_option)) {
+ if (!mode_option)
+ mode_option = fb_mode_option;
+ if (mode_option) {
const char *name = mode_option;
unsigned int namelen = strlen(name);
int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
@@ -606,26 +608,43 @@ done:
DPRINTK("Trying specified video mode%s %ix%i\n",
refresh_specified ? "" : " (ignoring refresh rate)", xres, yres);
- diff = refresh;
+ if (!refresh_specified) {
+ /*
+ * If the caller has provided a custom mode database and a
+ * valid monspecs structure, we look for the mode with the
+ * highest refresh rate. Otherwise we play it safe it and
+ * try to find a mode with a refresh rate closest to the
+ * standard 60 Hz.
+ */
+ if (db != modedb &&
+ info->monspecs.vfmin && info->monspecs.vfmax &&
+ info->monspecs.hfmin && info->monspecs.hfmax &&
+ info->monspecs.dclkmax) {
+ refresh = 1000;
+ } else {
+ refresh = 60;
+ }
+ }
+
+ diff = -1;
best = -1;
for (i = 0; i < dbsize; i++) {
- if (name_matches(db[i], name, namelen) ||
- (res_specified && res_matches(db[i], xres, yres))) {
- if(!fb_try_mode(var, info, &db[i], bpp)) {
- if(!refresh_specified || db[i].refresh == refresh)
- return 1;
- else {
- if(diff > abs(db[i].refresh - refresh)) {
- diff = abs(db[i].refresh - refresh);
- best = i;
- }
+ if ((name_matches(db[i], name, namelen) ||
+ (res_specified && res_matches(db[i], xres, yres))) &&
+ !fb_try_mode(var, info, &db[i], bpp)) {
+ if (refresh_specified && db[i].refresh == refresh) {
+ return 1;
+ } else {
+ if (abs(db[i].refresh - refresh) < diff) {
+ diff = abs(db[i].refresh - refresh);
+ best = i;
}
}
}
}
if (best != -1) {
fb_try_mode(var, info, &db[best], bpp);
- return 2;
+ return (refresh_specified) ? 2 : 1;
}
diff = xres + yres;
@@ -938,6 +957,7 @@ void fb_destroy_modelist(struct list_head *head)
kfree(pos);
}
}
+EXPORT_SYMBOL_GPL(fb_destroy_modelist);
/**
* fb_videomode_to_modelist: convert mode array to mode list
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c
index 731d7a5c5aa2..4b6a99b5be0d 100644
--- a/drivers/video/neofb.c
+++ b/drivers/video/neofb.c
@@ -72,7 +72,6 @@
#include <asm/irq.h>
#include <asm/pgtable.h>
#include <asm/system.h>
-#include <asm/uaccess.h>
#ifdef CONFIG_MTRR
#include <asm/mtrr.h>
diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c
index afe4567e1ff4..6fd7cb8f9b8e 100644
--- a/drivers/video/nvidia/nv_i2c.c
+++ b/drivers/video/nvidia/nv_i2c.c
@@ -125,11 +125,13 @@ void nvidia_create_i2c_busses(struct nvidia_par *par)
par->chan[1].par = par;
par->chan[2].par = par;
- par->chan[0].ddc_base = 0x36;
- nvidia_setup_i2c_bus(&par->chan[0], "nvidia #0", I2C_CLASS_HWMON);
+ par->chan[0].ddc_base = (par->reverse_i2c) ? 0x36 : 0x3e;
+ nvidia_setup_i2c_bus(&par->chan[0], "nvidia #0",
+ (par->reverse_i2c) ? I2C_CLASS_HWMON : 0);
- par->chan[1].ddc_base = 0x3e;
- nvidia_setup_i2c_bus(&par->chan[1], "nvidia #1", 0);
+ par->chan[1].ddc_base = (par->reverse_i2c) ? 0x3e : 0x36;
+ nvidia_setup_i2c_bus(&par->chan[1], "nvidia #1",
+ (par->reverse_i2c) ? 0 : I2C_CLASS_HWMON);
par->chan[2].ddc_base = 0x50;
nvidia_setup_i2c_bus(&par->chan[2], "nvidia #2", 0);
diff --git a/drivers/video/nvidia/nv_type.h b/drivers/video/nvidia/nv_type.h
index 2fdf77ec39fc..f132aab8c5de 100644
--- a/drivers/video/nvidia/nv_type.h
+++ b/drivers/video/nvidia/nv_type.h
@@ -135,6 +135,7 @@ struct nvidia_par {
int paneltweak;
int LVDS;
int pm_state;
+ int reverse_i2c;
u32 crtcSync_read;
u32 fpSyncs;
u32 dmaPut;
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index a7fe214f0f77..30e14eb1f51e 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -79,6 +79,7 @@ static int noscale __devinitdata = 0;
static int paneltweak __devinitdata = 0;
static int vram __devinitdata = 0;
static int bpp __devinitdata = 8;
+static int reverse_i2c __devinitdata;
#ifdef CONFIG_MTRR
static int nomtrr __devinitdata = 0;
#endif
@@ -1305,6 +1306,7 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd,
par->CRTCnumber = forceCRTC;
par->FpScale = (!noscale);
par->paneltweak = paneltweak;
+ par->reverse_i2c = reverse_i2c;
/* enable IO and mem if not already done */
pci_read_config_word(pd, PCI_COMMAND, &cmd);
@@ -1486,6 +1488,8 @@ static int __devinit nvidiafb_setup(char *options)
noaccel = 1;
} else if (!strncmp(this_opt, "noscale", 7)) {
noscale = 1;
+ } else if (!strncmp(this_opt, "reverse_i2c", 11)) {
+ reverse_i2c = 1;
} else if (!strncmp(this_opt, "paneltweak:", 11)) {
paneltweak = simple_strtoul(this_opt+11, NULL, 0);
} else if (!strncmp(this_opt, "vram:", 5)) {
@@ -1582,6 +1586,8 @@ MODULE_PARM_DESC(mode_option, "Specify initial video mode");
module_param(bpp, int, 0);
MODULE_PARM_DESC(bpp, "pixel width in bits"
"(default=8)");
+module_param(reverse_i2c, int, 0);
+MODULE_PARM_DESC(reverse_i2c, "reverse port assignment of the i2c bus");
#ifdef CONFIG_MTRR
module_param(nomtrr, bool, 0);
MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) "
diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig
index 7f4d25b8a184..44408850e2eb 100644
--- a/drivers/video/omap/Kconfig
+++ b/drivers/video/omap/Kconfig
@@ -1,6 +1,6 @@
config FB_OMAP
tristate "OMAP frame buffer support (EXPERIMENTAL)"
- depends on FB
+ depends on FB && ARCH_OMAP
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
@@ -8,7 +8,7 @@ config FB_OMAP
Frame buffer driver for OMAP based boards.
config FB_OMAP_BOOTLOADER_INIT
- bool "Check bootloader initializaion"
+ bool "Check bootloader initialization"
depends on FB_OMAP
help
Say Y here if you want to enable checking if the bootloader has
diff --git a/drivers/video/omap/blizzard.c b/drivers/video/omap/blizzard.c
index e682940a97a4..4d8ad9cd0e19 100644
--- a/drivers/video/omap/blizzard.c
+++ b/drivers/video/omap/blizzard.c
@@ -225,7 +225,7 @@ static void blizzard_restart_sdram(void)
while (!(blizzard_read_reg(BLIZZARD_MEM_BANK0_STATUS) & 0x01)) {
if (time_after(jiffies, tmo)) {
dev_err(blizzard.fbdev->dev,
- "s1d1374x: SDRAM not ready");
+ "s1d1374x: SDRAM not ready\n");
break;
}
msleep(1);
diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c
index f4c23434de6f..ab32ceb06178 100644
--- a/drivers/video/omap/dispc.c
+++ b/drivers/video/omap/dispc.c
@@ -880,19 +880,19 @@ static irqreturn_t omap_dispc_irq_handler(int irq, void *dev)
static int get_dss_clocks(void)
{
if (IS_ERR((dispc.dss_ick = clk_get(dispc.fbdev->dev, "dss_ick")))) {
- dev_err(dispc.fbdev->dev, "can't get dss_ick");
+ dev_err(dispc.fbdev->dev, "can't get dss_ick\n");
return PTR_ERR(dispc.dss_ick);
}
if (IS_ERR((dispc.dss1_fck = clk_get(dispc.fbdev->dev, "dss1_fck")))) {
- dev_err(dispc.fbdev->dev, "can't get dss1_fck");
+ dev_err(dispc.fbdev->dev, "can't get dss1_fck\n");
clk_put(dispc.dss_ick);
return PTR_ERR(dispc.dss1_fck);
}
if (IS_ERR((dispc.dss_54m_fck =
clk_get(dispc.fbdev->dev, "dss_54m_fck")))) {
- dev_err(dispc.fbdev->dev, "can't get dss_54m_fck");
+ dev_err(dispc.fbdev->dev, "can't get dss_54m_fck\n");
clk_put(dispc.dss_ick);
clk_put(dispc.dss1_fck);
return PTR_ERR(dispc.dss_54m_fck);
diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c
index dc48e02f215c..1e642b7a20fe 100644
--- a/drivers/video/omap/hwa742.c
+++ b/drivers/video/omap/hwa742.c
@@ -508,7 +508,7 @@ int hwa742_update_window_async(struct fb_info *fbi,
if (unlikely(win->format &
~(0x03 | OMAPFB_FORMAT_FLAG_DOUBLE |
OMAPFB_FORMAT_FLAG_TEARSYNC | OMAPFB_FORMAT_FLAG_FORCE_VSYNC))) {
- dev_dbg(hwa742.fbdev->dev, "invalid window flag");
+ dev_dbg(hwa742.fbdev->dev, "invalid window flag\n");
r = -EINVAL;
goto out;
}
diff --git a/drivers/video/omap/lcd_h3.c b/drivers/video/omap/lcd_h3.c
index 51807b4e26d1..c604d935c188 100644
--- a/drivers/video/omap/lcd_h3.c
+++ b/drivers/video/omap/lcd_h3.c
@@ -28,8 +28,6 @@
#define MODULE_NAME "omapfb-lcd_h3"
-#define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args)
-
static int h3_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
{
return 0;
@@ -48,7 +46,7 @@ static int h3_panel_enable(struct lcd_panel *panel)
if (!r)
r = tps65010_set_gpio_out_value(GPIO2, HIGH);
if (r)
- pr_err("Unable to turn on LCD panel\n");
+ pr_err(MODULE_NAME ": Unable to turn on LCD panel\n");
return r;
}
@@ -62,7 +60,7 @@ static void h3_panel_disable(struct lcd_panel *panel)
if (!r)
tps65010_set_gpio_out_value(GPIO2, LOW);
if (r)
- pr_err("Unable to turn off LCD panel\n");
+ pr_err(MODULE_NAME ": Unable to turn off LCD panel\n");
}
static unsigned long h3_panel_get_caps(struct lcd_panel *panel)
diff --git a/drivers/video/omap/lcd_inn1610.c b/drivers/video/omap/lcd_inn1610.c
index 95604ca43301..5ef119c813e0 100644
--- a/drivers/video/omap/lcd_inn1610.c
+++ b/drivers/video/omap/lcd_inn1610.c
@@ -27,20 +27,18 @@
#define MODULE_NAME "omapfb-lcd_h3"
-#define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args)
-
static int innovator1610_panel_init(struct lcd_panel *panel,
struct omapfb_device *fbdev)
{
int r = 0;
if (omap_request_gpio(14)) {
- pr_err("can't request GPIO 14\n");
+ pr_err(MODULE_NAME ": can't request GPIO 14\n");
r = -1;
goto exit;
}
if (omap_request_gpio(15)) {
- pr_err("can't request GPIO 15\n");
+ pr_err(MODULE_NAME ": can't request GPIO 15\n");
omap_free_gpio(14);
r = -1;
goto exit;
diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c
index 2b4269813b22..789cfd23c36b 100644
--- a/drivers/video/omap/rfbi.c
+++ b/drivers/video/omap/rfbi.c
@@ -84,12 +84,12 @@ static inline u32 rfbi_read_reg(int idx)
static int rfbi_get_clocks(void)
{
if (IS_ERR((rfbi.dss_ick = clk_get(rfbi.fbdev->dev, "dss_ick")))) {
- dev_err(rfbi.fbdev->dev, "can't get dss_ick");
+ dev_err(rfbi.fbdev->dev, "can't get dss_ick\n");
return PTR_ERR(rfbi.dss_ick);
}
if (IS_ERR((rfbi.dss1_fck = clk_get(rfbi.fbdev->dev, "dss1_fck")))) {
- dev_err(rfbi.fbdev->dev, "can't get dss1_fck");
+ dev_err(rfbi.fbdev->dev, "can't get dss1_fck\n");
clk_put(rfbi.dss_ick);
return PTR_ERR(rfbi.dss1_fck);
}
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
index 10c0cc6e93fc..5591dfb22b18 100644
--- a/drivers/video/pm2fb.c
+++ b/drivers/video/pm2fb.c
@@ -11,7 +11,7 @@
* and additional input from James Simmon's port of Hannu Mallat's tdfx
* driver.
*
- * I have a Creative Graphics Blaster Exxtreme card - pm2fb on x86. I
+ * I have a Creative Graphics Blaster Exxtreme card - pm2fb on x86. I
* have no access to other pm2fb implementations. Sparc (and thus
* hopefully other big-endian) devices now work, thanks to a lot of
* testing work by Ron Murray. I have no access to CVision hardware,
@@ -38,6 +38,9 @@
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/pci.h>
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
#include <video/permedia2.h>
#include <video/cvisionppc.h>
@@ -52,15 +55,19 @@
#undef PM2FB_MASTER_DEBUG
#ifdef PM2FB_MASTER_DEBUG
-#define DPRINTK(a,b...) printk(KERN_DEBUG "pm2fb: %s: " a, __FUNCTION__ , ## b)
+#define DPRINTK(a, b...) \
+ printk(KERN_DEBUG "pm2fb: %s: " a, __FUNCTION__ , ## b)
#else
-#define DPRINTK(a,b...)
+#define DPRINTK(a, b...)
#endif
+#define PM2_PIXMAP_SIZE (1600 * 4)
+
/*
* Driver data
*/
-static char *mode __devinitdata = NULL;
+static int hwcursor = 1;
+static char *mode __devinitdata;
/*
* The XFree GLINT driver will (I think to implement hardware cursor
@@ -73,6 +80,11 @@ static char *mode __devinitdata = NULL;
*/
static int lowhsync;
static int lowvsync;
+static int noaccel __devinitdata;
+/* mtrr option */
+#ifdef CONFIG_MTRR
+static int nomtrr __devinitdata;
+#endif
/*
* The hardware state of the graphics card that isn't part of the
@@ -88,6 +100,7 @@ struct pm2fb_par
u32 mem_control; /* MemControl reg at probe */
u32 boot_address; /* BootAddress reg at probe */
u32 palette[16];
+ int mtrr_handle;
};
/*
@@ -135,60 +148,39 @@ static struct fb_var_screeninfo pm2fb_var __devinitdata = {
* Utility functions
*/
-static inline u32 RD32(unsigned char __iomem *base, s32 off)
-{
- return fb_readl(base + off);
-}
-
-static inline void WR32(unsigned char __iomem *base, s32 off, u32 v)
+static inline u32 pm2_RD(struct pm2fb_par *p, s32 off)
{
- fb_writel(v, base + off);
+ return fb_readl(p->v_regs + off);
}
-static inline u32 pm2_RD(struct pm2fb_par* p, s32 off)
+static inline void pm2_WR(struct pm2fb_par *p, s32 off, u32 v)
{
- return RD32(p->v_regs, off);
+ fb_writel(v, p->v_regs + off);
}
-static inline void pm2_WR(struct pm2fb_par* p, s32 off, u32 v)
+static inline u32 pm2_RDAC_RD(struct pm2fb_par *p, s32 idx)
{
- WR32(p->v_regs, off, v);
+ pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx);
+ mb();
+ return pm2_RD(p, PM2R_RD_INDEXED_DATA);
}
-static inline u32 pm2_RDAC_RD(struct pm2fb_par* p, s32 idx)
+static inline u32 pm2v_RDAC_RD(struct pm2fb_par *p, s32 idx)
{
- int index = PM2R_RD_INDEXED_DATA;
- switch (p->type) {
- case PM2_TYPE_PERMEDIA2:
- pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx);
- break;
- case PM2_TYPE_PERMEDIA2V:
- pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff);
- index = PM2VR_RD_INDEXED_DATA;
- break;
- }
+ pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff);
mb();
- return pm2_RD(p, index);
+ return pm2_RD(p, PM2VR_RD_INDEXED_DATA);
}
-static inline void pm2_RDAC_WR(struct pm2fb_par* p, s32 idx, u32 v)
+static inline void pm2_RDAC_WR(struct pm2fb_par *p, s32 idx, u32 v)
{
- int index = PM2R_RD_INDEXED_DATA;
- switch (p->type) {
- case PM2_TYPE_PERMEDIA2:
- pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx);
- break;
- case PM2_TYPE_PERMEDIA2V:
- pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff);
- index = PM2VR_RD_INDEXED_DATA;
- break;
- }
+ pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx);
wmb();
- pm2_WR(p, index, v);
+ pm2_WR(p, PM2R_RD_INDEXED_DATA, v);
wmb();
}
-static inline void pm2v_RDAC_WR(struct pm2fb_par* p, s32 idx, u32 v)
+static inline void pm2v_RDAC_WR(struct pm2fb_par *p, s32 idx, u32 v)
{
pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff);
wmb();
@@ -199,10 +191,10 @@ static inline void pm2v_RDAC_WR(struct pm2fb_par* p, s32 idx, u32 v)
#ifdef CONFIG_FB_PM2_FIFO_DISCONNECT
#define WAIT_FIFO(p, a)
#else
-static inline void WAIT_FIFO(struct pm2fb_par* p, u32 a)
+static inline void WAIT_FIFO(struct pm2fb_par *p, u32 a)
{
- while( pm2_RD(p, PM2R_IN_FIFO_SPACE) < a );
- mb();
+ while (pm2_RD(p, PM2R_IN_FIFO_SPACE) < a)
+ cpu_relax();
}
#endif
@@ -238,7 +230,7 @@ static u32 partprod(u32 xres)
for (i = 0; pp_table[i].width && pp_table[i].width != xres; i++)
;
- if ( pp_table[i].width == 0 )
+ if (pp_table[i].width == 0)
DPRINTK("invalid width %u\n", xres);
return pp_table[i].pp;
}
@@ -246,25 +238,22 @@ static u32 partprod(u32 xres)
static u32 to3264(u32 timing, int bpp, int is64)
{
switch (bpp) {
+ case 24:
+ timing *= 3;
case 8:
- timing >>= 2 + is64;
- break;
+ timing >>= 1;
case 16:
- timing >>= 1 + is64;
- break;
- case 24:
- timing = (timing * 3) >> (2 + is64);
- break;
+ timing >>= 1;
case 32:
- if (is64)
- timing >>= 1;
break;
}
+ if (is64)
+ timing >>= 1;
return timing;
}
-static void pm2_mnp(u32 clk, unsigned char* mm, unsigned char* nn,
- unsigned char* pp)
+static void pm2_mnp(u32 clk, unsigned char *mm, unsigned char *nn,
+ unsigned char *pp)
{
unsigned char m;
unsigned char n;
@@ -278,13 +267,13 @@ static void pm2_mnp(u32 clk, unsigned char* mm, unsigned char* nn,
for (m = 2; m; m++) {
f = PM2_REFERENCE_CLOCK * m / n;
if (f >= 150000 && f <= 300000) {
- for ( p = 0; p < 5; p++, f >>= 1) {
- curr = ( clk > f ) ? clk - f : f - clk;
- if ( curr < delta ) {
- delta=curr;
- *mm=m;
- *nn=n;
- *pp=p;
+ for (p = 0; p < 5; p++, f >>= 1) {
+ curr = (clk > f) ? clk - f : f - clk;
+ if (curr < delta) {
+ delta = curr;
+ *mm = m;
+ *nn = n;
+ *pp = p;
}
}
}
@@ -292,8 +281,8 @@ static void pm2_mnp(u32 clk, unsigned char* mm, unsigned char* nn,
}
}
-static void pm2v_mnp(u32 clk, unsigned char* mm, unsigned char* nn,
- unsigned char* pp)
+static void pm2v_mnp(u32 clk, unsigned char *mm, unsigned char *nn,
+ unsigned char *pp)
{
unsigned char m;
unsigned char n;
@@ -302,23 +291,24 @@ static void pm2v_mnp(u32 clk, unsigned char* mm, unsigned char* nn,
s32 delta = 1000;
*mm = *nn = *pp = 0;
- for ( m = 1; m < 128; m++) {
+ for (m = 1; m < 128; m++) {
for (n = 2 * m + 1; n; n++) {
- for ( p = 0; p < 2; p++) {
- f = ( PM2_REFERENCE_CLOCK >> ( p + 1 )) * n / m;
- if ( clk > f - delta && clk < f + delta ) {
- delta = ( clk > f ) ? clk - f : f - clk;
- *mm=m;
- *nn=n;
- *pp=p;
+ for (p = 0; p < 2; p++) {
+ f = (PM2_REFERENCE_CLOCK >> (p + 1)) * n / m;
+ if (clk > f - delta && clk < f + delta) {
+ delta = (clk > f) ? clk - f : f - clk;
+ *mm = m;
+ *nn = n;
+ *pp = p;
}
}
}
}
}
-static void clear_palette(struct pm2fb_par* p) {
- int i=256;
+static void clear_palette(struct pm2fb_par *p)
+{
+ int i = 256;
WAIT_FIFO(p, 1);
pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, 0);
@@ -331,14 +321,14 @@ static void clear_palette(struct pm2fb_par* p) {
}
}
-static void reset_card(struct pm2fb_par* p)
+static void reset_card(struct pm2fb_par *p)
{
if (p->type == PM2_TYPE_PERMEDIA2V)
pm2_WR(p, PM2VR_RD_INDEX_HIGH, 0);
pm2_WR(p, PM2R_RESET_STATUS, 0);
mb();
while (pm2_RD(p, PM2R_RESET_STATUS) & PM2F_BEING_RESET)
- ;
+ cpu_relax();
mb();
#ifdef CONFIG_FB_PM2_FIFO_DISCONNECT
DPRINTK("FIFO disconnect enabled\n");
@@ -354,11 +344,11 @@ static void reset_card(struct pm2fb_par* p)
pm2_WR(p, PM2R_MEM_CONFIG, p->mem_config);
}
-static void reset_config(struct pm2fb_par* p)
+static void reset_config(struct pm2fb_par *p)
{
- WAIT_FIFO(p, 52);
+ WAIT_FIFO(p, 53);
pm2_WR(p, PM2R_CHIP_CONFIG, pm2_RD(p, PM2R_CHIP_CONFIG) &
- ~(PM2F_VGA_ENABLE|PM2F_VGA_FIXED));
+ ~(PM2F_VGA_ENABLE | PM2F_VGA_FIXED));
pm2_WR(p, PM2R_BYPASS_WRITE_MASK, ~(0L));
pm2_WR(p, PM2R_FRAMEBUFFER_WRITE_MASK, ~(0L));
pm2_WR(p, PM2R_FIFO_CONTROL, 0);
@@ -393,31 +383,32 @@ static void reset_config(struct pm2fb_par* p)
pm2_WR(p, PM2R_STATISTICS_MODE, 0);
pm2_WR(p, PM2R_SCISSOR_MODE, 0);
pm2_WR(p, PM2R_FILTER_MODE, PM2F_SYNCHRONIZATION);
+ pm2_WR(p, PM2R_RD_PIXEL_MASK, 0xff);
switch (p->type) {
case PM2_TYPE_PERMEDIA2:
pm2_RDAC_WR(p, PM2I_RD_MODE_CONTROL, 0); /* no overlay */
pm2_RDAC_WR(p, PM2I_RD_CURSOR_CONTROL, 0);
pm2_RDAC_WR(p, PM2I_RD_MISC_CONTROL, PM2F_RD_PALETTE_WIDTH_8);
+ pm2_RDAC_WR(p, PM2I_RD_COLOR_KEY_CONTROL, 0);
+ pm2_RDAC_WR(p, PM2I_RD_OVERLAY_KEY, 0);
+ pm2_RDAC_WR(p, PM2I_RD_RED_KEY, 0);
+ pm2_RDAC_WR(p, PM2I_RD_GREEN_KEY, 0);
+ pm2_RDAC_WR(p, PM2I_RD_BLUE_KEY, 0);
break;
case PM2_TYPE_PERMEDIA2V:
pm2v_RDAC_WR(p, PM2VI_RD_MISC_CONTROL, 1); /* 8bit */
break;
}
- pm2_RDAC_WR(p, PM2I_RD_COLOR_KEY_CONTROL, 0);
- pm2_RDAC_WR(p, PM2I_RD_OVERLAY_KEY, 0);
- pm2_RDAC_WR(p, PM2I_RD_RED_KEY, 0);
- pm2_RDAC_WR(p, PM2I_RD_GREEN_KEY, 0);
- pm2_RDAC_WR(p, PM2I_RD_BLUE_KEY, 0);
}
-static void set_aperture(struct pm2fb_par* p, u32 depth)
+static void set_aperture(struct pm2fb_par *p, u32 depth)
{
/*
* The hardware is little-endian. When used in big-endian
* hosts, the on-chip aperture settings are used where
* possible to translate from host to card byte order.
*/
- WAIT_FIFO(p, 4);
+ WAIT_FIFO(p, 2);
#ifdef __LITTLE_ENDIAN
pm2_WR(p, PM2R_APERTURE_ONE, PM2F_APERTURE_STANDARD);
#else
@@ -440,11 +431,11 @@ static void set_aperture(struct pm2fb_par* p, u32 depth)
}
#endif
- // We don't use aperture two, so this may be superflous
+ /* We don't use aperture two, so this may be superflous */
pm2_WR(p, PM2R_APERTURE_TWO, PM2F_APERTURE_STANDARD);
}
-static void set_color(struct pm2fb_par* p, unsigned char regno,
+static void set_color(struct pm2fb_par *p, unsigned char regno,
unsigned char r, unsigned char g, unsigned char b)
{
WAIT_FIFO(p, 4);
@@ -457,7 +448,7 @@ static void set_color(struct pm2fb_par* p, unsigned char regno,
pm2_WR(p, PM2R_RD_PALETTE_DATA, b);
}
-static void set_memclock(struct pm2fb_par* par, u32 clk)
+static void set_memclock(struct pm2fb_par *par, u32 clk)
{
int i;
unsigned char m, n, p;
@@ -465,7 +456,7 @@ static void set_memclock(struct pm2fb_par* par, u32 clk)
switch (par->type) {
case PM2_TYPE_PERMEDIA2V:
pm2v_mnp(clk/2, &m, &n, &p);
- WAIT_FIFO(par, 8);
+ WAIT_FIFO(par, 12);
pm2_WR(par, PM2VR_RD_INDEX_HIGH, PM2VI_RD_MCLK_CONTROL >> 8);
pm2v_RDAC_WR(par, PM2VI_RD_MCLK_CONTROL, 0);
pm2v_RDAC_WR(par, PM2VI_RD_MCLK_PRESCALE, m);
@@ -473,10 +464,9 @@ static void set_memclock(struct pm2fb_par* par, u32 clk)
pm2v_RDAC_WR(par, PM2VI_RD_MCLK_POSTSCALE, p);
pm2v_RDAC_WR(par, PM2VI_RD_MCLK_CONTROL, 1);
rmb();
- for (i = 256;
- i && !(pm2_RDAC_RD(par, PM2VI_RD_MCLK_CONTROL) & 2);
- i--)
- ;
+ for (i = 256; i; i--)
+ if (pm2v_RDAC_RD(par, PM2VI_RD_MCLK_CONTROL) & 2)
+ break;
pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0);
break;
case PM2_TYPE_PERMEDIA2:
@@ -488,15 +478,14 @@ static void set_memclock(struct pm2fb_par* par, u32 clk)
pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_3, 8|p);
pm2_RDAC_RD(par, PM2I_RD_MEMORY_CLOCK_STATUS);
rmb();
- for (i = 256;
- i && !(pm2_RD(par, PM2R_RD_INDEXED_DATA) & PM2F_PLL_LOCKED);
- i--)
- ;
+ for (i = 256; i; i--)
+ if (pm2_RD(par, PM2R_RD_INDEXED_DATA) & PM2F_PLL_LOCKED)
+ break;
break;
}
}
-static void set_pixclock(struct pm2fb_par* par, u32 clk)
+static void set_pixclock(struct pm2fb_par *par, u32 clk)
{
int i;
unsigned char m, n, p;
@@ -504,17 +493,16 @@ static void set_pixclock(struct pm2fb_par* par, u32 clk)
switch (par->type) {
case PM2_TYPE_PERMEDIA2:
pm2_mnp(clk, &m, &n, &p);
- WAIT_FIFO(par, 8);
+ WAIT_FIFO(par, 10);
pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A3, 0);
pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A1, m);
pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A2, n);
pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A3, 8|p);
pm2_RDAC_RD(par, PM2I_RD_PIXEL_CLOCK_STATUS);
rmb();
- for (i = 256;
- i && !(pm2_RD(par, PM2R_RD_INDEXED_DATA) & PM2F_PLL_LOCKED);
- i--)
- ;
+ for (i = 256; i; i--)
+ if (pm2_RD(par, PM2R_RD_INDEXED_DATA) & PM2F_PLL_LOCKED)
+ break;
break;
case PM2_TYPE_PERMEDIA2V:
pm2v_mnp(clk/2, &m, &n, &p);
@@ -528,11 +516,10 @@ static void set_pixclock(struct pm2fb_par* par, u32 clk)
}
}
-static void set_video(struct pm2fb_par* p, u32 video) {
+static void set_video(struct pm2fb_par *p, u32 video)
+{
u32 tmp;
- u32 vsync;
-
- vsync = video;
+ u32 vsync = video;
DPRINTK("video = 0x%x\n", video);
@@ -542,10 +529,10 @@ static void set_video(struct pm2fb_par* p, u32 video) {
* driver may well. So always set +hsync/+vsync and then set
* the RAMDAC to invert the sync if necessary.
*/
- vsync &= ~(PM2F_HSYNC_MASK|PM2F_VSYNC_MASK);
- vsync |= PM2F_HSYNC_ACT_HIGH|PM2F_VSYNC_ACT_HIGH;
+ vsync &= ~(PM2F_HSYNC_MASK | PM2F_VSYNC_MASK);
+ vsync |= PM2F_HSYNC_ACT_HIGH | PM2F_VSYNC_ACT_HIGH;
- WAIT_FIFO(p, 5);
+ WAIT_FIFO(p, 3);
pm2_WR(p, PM2R_VIDEO_CONTROL, vsync);
switch (p->type) {
@@ -564,16 +551,11 @@ static void set_video(struct pm2fb_par* p, u32 video) {
if ((video & PM2F_VSYNC_MASK) == PM2F_VSYNC_ACT_LOW)
tmp |= 4; /* invert vsync */
pm2v_RDAC_WR(p, PM2VI_RD_SYNC_CONTROL, tmp);
- pm2v_RDAC_WR(p, PM2VI_RD_MISC_CONTROL, 1);
break;
}
}
/*
- *
- */
-
-/**
* pm2fb_check_var - Optional function. Validates a var passed in.
* @var: frame buffer variable screen structure
* @info: frame buffer structure that represents a single frame buffer
@@ -594,15 +576,22 @@ static int pm2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
}
if (var->xres != var->xres_virtual) {
- DPRINTK("virtual x resolution != physical x resolution not supported\n");
+ DPRINTK("virtual x resolution != "
+ "physical x resolution not supported\n");
return -EINVAL;
}
if (var->yres > var->yres_virtual) {
- DPRINTK("virtual y resolution < physical y resolution not possible\n");
+ DPRINTK("virtual y resolution < "
+ "physical y resolution not possible\n");
return -EINVAL;
}
+ /* permedia cannot blit over 2048 */
+ if (var->yres_virtual > 2047) {
+ var->yres_virtual = 2047;
+ }
+
if (var->xoffset) {
DPRINTK("xoffset not supported\n");
return -EINVAL;
@@ -614,7 +603,7 @@ static int pm2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
}
var->xres = (var->xres + 15) & ~15; /* could sometimes be 8 */
- lpitch = var->xres * ((var->bits_per_pixel + 7)>>3);
+ lpitch = var->xres * ((var->bits_per_pixel + 7) >> 3);
if (var->xres < 320 || var->xres > 1600) {
DPRINTK("width not supported: %u\n", var->xres);
@@ -633,15 +622,18 @@ static int pm2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
}
if (PICOS2KHZ(var->pixclock) > PM2_MAX_PIXCLOCK) {
- DPRINTK("pixclock too high (%ldKHz)\n", PICOS2KHZ(var->pixclock));
+ DPRINTK("pixclock too high (%ldKHz)\n",
+ PICOS2KHZ(var->pixclock));
return -EINVAL;
}
var->transp.offset = 0;
var->transp.length = 0;
- switch(var->bits_per_pixel) {
+ switch (var->bits_per_pixel) {
case 8:
- var->red.length = var->green.length = var->blue.length = 8;
+ var->red.length = 8;
+ var->green.length = 8;
+ var->blue.length = 8;
break;
case 16:
var->red.offset = 11;
@@ -657,7 +649,9 @@ static int pm2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
var->red.offset = 16;
var->green.offset = 8;
var->blue.offset = 0;
- var->red.length = var->green.length = var->blue.length = 8;
+ var->red.length = 8;
+ var->green.length = 8;
+ var->blue.length = 8;
break;
case 24:
#ifdef __BIG_ENDIAN
@@ -668,10 +662,13 @@ static int pm2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
var->blue.offset = 0;
#endif
var->green.offset = 8;
- var->red.length = var->green.length = var->blue.length = 8;
+ var->red.length = 8;
+ var->green.length = 8;
+ var->blue.length = 8;
break;
}
- var->height = var->width = -1;
+ var->height = -1;
+ var->width = -1;
var->accel_flags = 0; /* Can't mmap if this is on */
@@ -691,7 +688,9 @@ static int pm2fb_set_par(struct fb_info *info)
{
struct pm2fb_par *par = info->par;
u32 pixclock;
- u32 width, height, depth;
+ u32 width = (info->var.xres_virtual + 7) & ~7;
+ u32 height = info->var.yres_virtual;
+ u32 depth = (info->var.bits_per_pixel + 7) & ~7;
u32 hsstart, hsend, hbend, htotal;
u32 vsstart, vsend, vbend, vtotal;
u32 stride;
@@ -701,22 +700,19 @@ static int pm2fb_set_par(struct fb_info *info)
u32 txtmap = 0;
u32 pixsize = 0;
u32 clrformat = 0;
- u32 xres;
+ u32 misc = 1; /* 8-bit DAC */
+ u32 xres = (info->var.xres + 31) & ~31;
int data64;
reset_card(par);
reset_config(par);
clear_palette(par);
- if ( par->memclock )
+ if (par->memclock)
set_memclock(par, par->memclock);
- width = (info->var.xres_virtual + 7) & ~7;
- height = info->var.yres_virtual;
- depth = (info->var.bits_per_pixel + 7) & ~7;
depth = (depth > 32) ? 32 : depth;
data64 = depth > 8 || par->type == PM2_TYPE_PERMEDIA2V;
- xres = (info->var.xres + 31) & ~31;
pixclock = PICOS2KHZ(info->var.pixclock);
if (pixclock > PM2_MAX_PIXCLOCK) {
DPRINTK("pixclock too high (%uKHz)\n", pixclock);
@@ -731,7 +727,8 @@ static int pm2fb_set_par(struct fb_info *info)
? info->var.lower_margin - 1
: 0; /* FIXME! */
vsend = info->var.lower_margin + info->var.vsync_len - 1;
- vbend = info->var.lower_margin + info->var.vsync_len + info->var.upper_margin;
+ vbend = info->var.lower_margin + info->var.vsync_len +
+ info->var.upper_margin;
vtotal = info->var.yres + vbend - 1;
stride = to3264(width, depth, 1);
base = to3264(info->var.yoffset * xres + info->var.xoffset, depth, 1);
@@ -744,25 +741,25 @@ static int pm2fb_set_par(struct fb_info *info)
video |= PM2F_HSYNC_ACT_LOW;
} else
video |= PM2F_HSYNC_ACT_HIGH;
- }
- else
+ } else
video |= PM2F_HSYNC_ACT_LOW;
+
if (info->var.sync & FB_SYNC_VERT_HIGH_ACT) {
if (lowvsync) {
DPRINTK("ignoring +vsync, using -vsync.\n");
video |= PM2F_VSYNC_ACT_LOW;
} else
video |= PM2F_VSYNC_ACT_HIGH;
- }
- else
+ } else
video |= PM2F_VSYNC_ACT_LOW;
- if ((info->var.vmode & FB_VMODE_MASK)==FB_VMODE_INTERLACED) {
+
+ if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
DPRINTK("interlaced not supported\n");
return -EINVAL;
}
- if ((info->var.vmode & FB_VMODE_MASK)==FB_VMODE_DOUBLE)
+ if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
video |= PM2F_LINE_DOUBLE;
- if ((info->var.activate & FB_ACTIVATE_MASK)==FB_ACTIVATE_NOW)
+ if ((info->var.activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW)
video |= PM2F_VIDEO_ENABLE;
par->video = video;
@@ -783,12 +780,10 @@ static int pm2fb_set_par(struct fb_info *info)
mb();
WAIT_FIFO(par, 19);
- pm2_RDAC_WR(par, PM2I_RD_COLOR_KEY_CONTROL,
- ( depth == 8 ) ? 0 : PM2F_COLOR_KEY_TEST_OFF);
switch (depth) {
case 8:
pm2_WR(par, PM2R_FB_READ_PIXEL, 0);
- clrformat = 0x0e;
+ clrformat = 0x2e;
break;
case 16:
pm2_WR(par, PM2R_FB_READ_PIXEL, 1);
@@ -796,6 +791,7 @@ static int pm2fb_set_par(struct fb_info *info)
txtmap = PM2F_TEXTEL_SIZE_16;
pixsize = 1;
clrformat = 0x70;
+ misc |= 8;
break;
case 32:
pm2_WR(par, PM2R_FB_READ_PIXEL, 2);
@@ -803,6 +799,7 @@ static int pm2fb_set_par(struct fb_info *info)
txtmap = PM2F_TEXTEL_SIZE_32;
pixsize = 2;
clrformat = 0x20;
+ misc |= 8;
break;
case 24:
pm2_WR(par, PM2R_FB_READ_PIXEL, 4);
@@ -810,6 +807,7 @@ static int pm2fb_set_par(struct fb_info *info)
txtmap = PM2F_TEXTEL_SIZE_24;
pixsize = 4;
clrformat = 0x20;
+ misc |= 8;
break;
}
pm2_WR(par, PM2R_FB_WRITE_MODE, PM2F_FB_WRITE_ENABLE);
@@ -834,14 +832,19 @@ static int pm2fb_set_par(struct fb_info *info)
pm2_WR(par, PM2R_SCREEN_BASE, base);
wmb();
set_video(par, video);
- WAIT_FIFO(par, 4);
+ WAIT_FIFO(par, 10);
switch (par->type) {
case PM2_TYPE_PERMEDIA2:
pm2_RDAC_WR(par, PM2I_RD_COLOR_MODE, clrmode);
+ pm2_RDAC_WR(par, PM2I_RD_COLOR_KEY_CONTROL,
+ (depth == 8) ? 0 : PM2F_COLOR_KEY_TEST_OFF);
break;
case PM2_TYPE_PERMEDIA2V:
+ pm2v_RDAC_WR(par, PM2VI_RD_DAC_CONTROL, 0);
pm2v_RDAC_WR(par, PM2VI_RD_PIXEL_SIZE, pixsize);
pm2v_RDAC_WR(par, PM2VI_RD_COLOR_FORMAT, clrformat);
+ pm2v_RDAC_WR(par, PM2VI_RD_MISC_CONTROL, misc);
+ pm2v_RDAC_WR(par, PM2VI_RD_OVERLAY_KEY, 0);
break;
}
set_pixclock(par, pixclock);
@@ -872,16 +875,15 @@ static int pm2fb_setcolreg(unsigned regno, unsigned red, unsigned green,
struct pm2fb_par *par = info->par;
if (regno >= info->cmap.len) /* no. of hw registers */
- return 1;
+ return -EINVAL;
/*
* Program hardware... do anything you want with transp
*/
/* grayscale works only partially under directcolor */
- if (info->var.grayscale) {
- /* grayscale = 0.30*R + 0.59*G + 0.11*B */
+ /* grayscale = 0.30*R + 0.59*G + 0.11*B */
+ if (info->var.grayscale)
red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
- }
/* Directcolor:
* var->{color}.offset contains start of bitfield
@@ -931,7 +933,7 @@ static int pm2fb_setcolreg(unsigned regno, unsigned red, unsigned green,
u32 v;
if (regno >= 16)
- return 1;
+ return -EINVAL;
v = (red << info->var.red.offset) |
(green << info->var.green.offset) |
@@ -948,8 +950,7 @@ static int pm2fb_setcolreg(unsigned regno, unsigned red, unsigned green,
break;
}
return 0;
- }
- else if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR)
+ } else if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR)
set_color(par, regno, red, green, blue);
return 0;
@@ -972,11 +973,9 @@ static int pm2fb_pan_display(struct fb_var_screeninfo *var,
{
struct pm2fb_par *p = info->par;
u32 base;
- u32 depth;
- u32 xres;
+ u32 depth = (var->bits_per_pixel + 7) & ~7;
+ u32 xres = (var->xres + 31) & ~31;
- xres = (var->xres + 31) & ~31;
- depth = (var->bits_per_pixel + 7) & ~7;
depth = (depth > 32) ? 32 : depth;
base = to3264(var->yoffset * xres + var->xoffset, depth, 1);
WAIT_FIFO(p, 1);
@@ -1018,15 +1017,15 @@ static int pm2fb_blank(int blank_mode, struct fb_info *info)
break;
case FB_BLANK_VSYNC_SUSPEND:
/* VSync: Off */
- video &= ~(PM2F_VSYNC_MASK | PM2F_BLANK_LOW );
+ video &= ~(PM2F_VSYNC_MASK | PM2F_BLANK_LOW);
break;
case FB_BLANK_HSYNC_SUSPEND:
/* HSync: Off */
- video &= ~(PM2F_HSYNC_MASK | PM2F_BLANK_LOW );
+ video &= ~(PM2F_HSYNC_MASK | PM2F_BLANK_LOW);
break;
case FB_BLANK_POWERDOWN:
/* HSync: Off, VSync: Off */
- video &= ~(PM2F_VSYNC_MASK | PM2F_HSYNC_MASK| PM2F_BLANK_LOW);
+ video &= ~(PM2F_VSYNC_MASK | PM2F_HSYNC_MASK | PM2F_BLANK_LOW);
break;
}
set_video(par, video);
@@ -1042,48 +1041,20 @@ static int pm2fb_sync(struct fb_info *info)
mb();
do {
while (pm2_RD(par, PM2R_OUT_FIFO_WORDS) == 0)
- udelay(10);
- rmb();
+ cpu_relax();
} while (pm2_RD(par, PM2R_OUT_FIFO) != PM2TAG(PM2R_SYNC));
return 0;
}
-/*
- * block operation. copy=0: rectangle fill, copy=1: rectangle copy.
- */
-static void pm2fb_block_op(struct fb_info* info, int copy,
- s32 xsrc, s32 ysrc,
- s32 x, s32 y, s32 w, s32 h,
- u32 color) {
- struct pm2fb_par *par = info->par;
-
- if (!w || !h)
- return;
- WAIT_FIFO(par, 5);
- pm2_WR(par, PM2R_CONFIG, PM2F_CONFIG_FB_WRITE_ENABLE |
- PM2F_CONFIG_FB_READ_SOURCE_ENABLE);
- if (copy)
- pm2_WR(par, PM2R_FB_SOURCE_DELTA,
- ((ysrc-y) & 0xfff) << 16 | ((xsrc-x) & 0xfff));
- else
- pm2_WR(par, PM2R_FB_BLOCK_COLOR, color);
- pm2_WR(par, PM2R_RECTANGLE_ORIGIN, (y << 16) | x);
- pm2_WR(par, PM2R_RECTANGLE_SIZE, (h << 16) | w);
- wmb();
- pm2_WR(par, PM2R_RENDER, PM2F_RENDER_RECTANGLE |
- (x<xsrc ? PM2F_INCREASE_X : 0) |
- (y<ysrc ? PM2F_INCREASE_Y : 0) |
- (copy ? 0 : PM2F_RENDER_FASTFILL));
-}
-
-static void pm2fb_fillrect (struct fb_info *info,
+static void pm2fb_fillrect(struct fb_info *info,
const struct fb_fillrect *region)
{
+ struct pm2fb_par *par = info->par;
struct fb_fillrect modded;
int vxres, vyres;
u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
- ((u32*)info->pseudo_palette)[region->color] : region->color;
+ ((u32 *)info->pseudo_palette)[region->color] : region->color;
if (info->state != FBINFO_STATE_RUNNING)
return;
@@ -1098,31 +1069,46 @@ static void pm2fb_fillrect (struct fb_info *info,
memcpy(&modded, region, sizeof(struct fb_fillrect));
- if(!modded.width || !modded.height ||
- modded.dx >= vxres || modded.dy >= vyres)
+ if (!modded.width || !modded.height ||
+ modded.dx >= vxres || modded.dy >= vyres)
return;
- if(modded.dx + modded.width > vxres)
+ if (modded.dx + modded.width > vxres)
modded.width = vxres - modded.dx;
- if(modded.dy + modded.height > vyres)
+ if (modded.dy + modded.height > vyres)
modded.height = vyres - modded.dy;
- if(info->var.bits_per_pixel == 8)
+ if (info->var.bits_per_pixel == 8)
color |= color << 8;
- if(info->var.bits_per_pixel <= 16)
+ if (info->var.bits_per_pixel <= 16)
color |= color << 16;
- if(info->var.bits_per_pixel != 24)
- pm2fb_block_op(info, 0, 0, 0,
- modded.dx, modded.dy,
- modded.width, modded.height, color);
- else
- cfb_fillrect(info, region);
+ WAIT_FIFO(par, 3);
+ pm2_WR(par, PM2R_CONFIG, PM2F_CONFIG_FB_WRITE_ENABLE);
+ pm2_WR(par, PM2R_RECTANGLE_ORIGIN, (modded.dy << 16) | modded.dx);
+ pm2_WR(par, PM2R_RECTANGLE_SIZE, (modded.height << 16) | modded.width);
+ if (info->var.bits_per_pixel != 24) {
+ WAIT_FIFO(par, 2);
+ pm2_WR(par, PM2R_FB_BLOCK_COLOR, color);
+ wmb();
+ pm2_WR(par, PM2R_RENDER,
+ PM2F_RENDER_RECTANGLE | PM2F_RENDER_FASTFILL);
+ } else {
+ WAIT_FIFO(par, 4);
+ pm2_WR(par, PM2R_COLOR_DDA_MODE, 1);
+ pm2_WR(par, PM2R_CONSTANT_COLOR, color);
+ wmb();
+ pm2_WR(par, PM2R_RENDER,
+ PM2F_RENDER_RECTANGLE |
+ PM2F_INCREASE_X | PM2F_INCREASE_Y );
+ pm2_WR(par, PM2R_COLOR_DDA_MODE, 0);
+ }
}
static void pm2fb_copyarea(struct fb_info *info,
const struct fb_copyarea *area)
{
+ struct pm2fb_par *par = info->par;
struct fb_copyarea modded;
u32 vxres, vyres;
@@ -1138,23 +1124,359 @@ static void pm2fb_copyarea(struct fb_info *info,
vxres = info->var.xres_virtual;
vyres = info->var.yres_virtual;
- if(!modded.width || !modded.height ||
- modded.sx >= vxres || modded.sy >= vyres ||
- modded.dx >= vxres || modded.dy >= vyres)
+ if (!modded.width || !modded.height ||
+ modded.sx >= vxres || modded.sy >= vyres ||
+ modded.dx >= vxres || modded.dy >= vyres)
return;
- if(modded.sx + modded.width > vxres)
+ if (modded.sx + modded.width > vxres)
modded.width = vxres - modded.sx;
- if(modded.dx + modded.width > vxres)
+ if (modded.dx + modded.width > vxres)
modded.width = vxres - modded.dx;
- if(modded.sy + modded.height > vyres)
+ if (modded.sy + modded.height > vyres)
modded.height = vyres - modded.sy;
- if(modded.dy + modded.height > vyres)
+ if (modded.dy + modded.height > vyres)
modded.height = vyres - modded.dy;
- pm2fb_block_op(info, 1, modded.sx, modded.sy,
- modded.dx, modded.dy,
- modded.width, modded.height, 0);
+ WAIT_FIFO(par, 5);
+ pm2_WR(par, PM2R_CONFIG, PM2F_CONFIG_FB_WRITE_ENABLE |
+ PM2F_CONFIG_FB_READ_SOURCE_ENABLE);
+ pm2_WR(par, PM2R_FB_SOURCE_DELTA,
+ ((modded.sy - modded.dy) & 0xfff) << 16 |
+ ((modded.sx - modded.dx) & 0xfff));
+ pm2_WR(par, PM2R_RECTANGLE_ORIGIN, (modded.dy << 16) | modded.dx);
+ pm2_WR(par, PM2R_RECTANGLE_SIZE, (modded.height << 16) | modded.width);
+ wmb();
+ pm2_WR(par, PM2R_RENDER, PM2F_RENDER_RECTANGLE |
+ (modded.dx < modded.sx ? PM2F_INCREASE_X : 0) |
+ (modded.dy < modded.sy ? PM2F_INCREASE_Y : 0));
+}
+
+static void pm2fb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+ struct pm2fb_par *par = info->par;
+ u32 height = image->height;
+ u32 fgx, bgx;
+ const u32 *src = (const u32 *)image->data;
+ u32 xres = (info->var.xres + 31) & ~31;
+
+ if (info->state != FBINFO_STATE_RUNNING)
+ return;
+ if (info->flags & FBINFO_HWACCEL_DISABLED || image->depth != 1) {
+ cfb_imageblit(info, image);
+ return;
+ }
+ switch (info->fix.visual) {
+ case FB_VISUAL_PSEUDOCOLOR:
+ fgx = image->fg_color;
+ bgx = image->bg_color;
+ break;
+ case FB_VISUAL_TRUECOLOR:
+ default:
+ fgx = par->palette[image->fg_color];
+ bgx = par->palette[image->bg_color];
+ break;
+ }
+ if (info->var.bits_per_pixel == 8) {
+ fgx |= fgx << 8;
+ bgx |= bgx << 8;
+ }
+ if (info->var.bits_per_pixel <= 16) {
+ fgx |= fgx << 16;
+ bgx |= bgx << 16;
+ }
+
+ WAIT_FIFO(par, 13);
+ pm2_WR(par, PM2R_FB_READ_MODE, partprod(xres));
+ pm2_WR(par, PM2R_SCISSOR_MIN_XY,
+ ((image->dy & 0xfff) << 16) | (image->dx & 0x0fff));
+ pm2_WR(par, PM2R_SCISSOR_MAX_XY,
+ (((image->dy + image->height) & 0x0fff) << 16) |
+ ((image->dx + image->width) & 0x0fff));
+ pm2_WR(par, PM2R_SCISSOR_MODE, 1);
+ /* GXcopy & UNIT_ENABLE */
+ pm2_WR(par, PM2R_LOGICAL_OP_MODE, (0x3 << 1) | 1);
+ pm2_WR(par, PM2R_RECTANGLE_ORIGIN,
+ ((image->dy & 0xfff) << 16) | (image->dx & 0x0fff));
+ pm2_WR(par, PM2R_RECTANGLE_SIZE,
+ ((image->height & 0x0fff) << 16) |
+ ((image->width) & 0x0fff));
+ if (info->var.bits_per_pixel == 24) {
+ pm2_WR(par, PM2R_COLOR_DDA_MODE, 1);
+ /* clear area */
+ pm2_WR(par, PM2R_CONSTANT_COLOR, bgx);
+ pm2_WR(par, PM2R_RENDER,
+ PM2F_RENDER_RECTANGLE |
+ PM2F_INCREASE_X | PM2F_INCREASE_Y);
+ /* BitMapPackEachScanline & invert bits and byte order*/
+ /* force background */
+ pm2_WR(par, PM2R_RASTERIZER_MODE, (1 << 9) | 1 | (3 << 7));
+ pm2_WR(par, PM2R_CONSTANT_COLOR, fgx);
+ pm2_WR(par, PM2R_RENDER,
+ PM2F_RENDER_RECTANGLE |
+ PM2F_INCREASE_X | PM2F_INCREASE_Y |
+ PM2F_RENDER_SYNC_ON_BIT_MASK);
+ } else {
+ pm2_WR(par, PM2R_COLOR_DDA_MODE, 0);
+ /* clear area */
+ pm2_WR(par, PM2R_FB_BLOCK_COLOR, bgx);
+ pm2_WR(par, PM2R_RENDER,
+ PM2F_RENDER_RECTANGLE |
+ PM2F_RENDER_FASTFILL |
+ PM2F_INCREASE_X | PM2F_INCREASE_Y);
+ /* invert bits and byte order*/
+ pm2_WR(par, PM2R_RASTERIZER_MODE, 1 | (3 << 7));
+ pm2_WR(par, PM2R_FB_BLOCK_COLOR, fgx);
+ pm2_WR(par, PM2R_RENDER,
+ PM2F_RENDER_RECTANGLE |
+ PM2F_INCREASE_X | PM2F_INCREASE_Y |
+ PM2F_RENDER_FASTFILL |
+ PM2F_RENDER_SYNC_ON_BIT_MASK);
+ }
+
+ while (height--) {
+ int width = ((image->width + 7) >> 3)
+ + info->pixmap.scan_align - 1;
+ width >>= 2;
+ WAIT_FIFO(par, width);
+ while (width--) {
+ pm2_WR(par, PM2R_BIT_MASK_PATTERN, *src);
+ src++;
+ }
+ }
+ WAIT_FIFO(par, 3);
+ pm2_WR(par, PM2R_RASTERIZER_MODE, 0);
+ pm2_WR(par, PM2R_COLOR_DDA_MODE, 0);
+ pm2_WR(par, PM2R_SCISSOR_MODE, 0);
+}
+
+/*
+ * Hardware cursor support.
+ */
+static const u8 cursor_bits_lookup[16] = {
+ 0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
+ 0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55
+};
+
+static int pm2vfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+ struct pm2fb_par *par = info->par;
+ u8 mode = PM2F_CURSORMODE_TYPE_X;
+ int x = cursor->image.dx - info->var.xoffset;
+ int y = cursor->image.dy - info->var.yoffset;
+
+ if (cursor->enable)
+ mode |= PM2F_CURSORMODE_CURSOR_ENABLE;
+
+ pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_MODE, mode);
+
+ if (!cursor->enable)
+ x = 2047; /* push it outside display */
+ pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_X_LOW, x & 0xff);
+ pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_X_HIGH, (x >> 8) & 0xf);
+ pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_Y_LOW, y & 0xff);
+ pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_Y_HIGH, (y >> 8) & 0xf);
+
+ /*
+ * If the cursor is not be changed this means either we want the
+ * current cursor state (if enable is set) or we want to query what
+ * we can do with the cursor (if enable is not set)
+ */
+ if (!cursor->set)
+ return 0;
+
+ if (cursor->set & FB_CUR_SETHOT) {
+ pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_X_HOT,
+ cursor->hot.x & 0x3f);
+ pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_Y_HOT,
+ cursor->hot.y & 0x3f);
+ }
+
+ if (cursor->set & FB_CUR_SETCMAP) {
+ u32 fg_idx = cursor->image.fg_color;
+ u32 bg_idx = cursor->image.bg_color;
+ struct fb_cmap cmap = info->cmap;
+
+ /* the X11 driver says one should use these color registers */
+ pm2_WR(par, PM2VR_RD_INDEX_HIGH, PM2VI_RD_CURSOR_PALETTE >> 8);
+ pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_PALETTE + 0,
+ cmap.red[bg_idx] >> 8 );
+ pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_PALETTE + 1,
+ cmap.green[bg_idx] >> 8 );
+ pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_PALETTE + 2,
+ cmap.blue[bg_idx] >> 8 );
+
+ pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_PALETTE + 3,
+ cmap.red[fg_idx] >> 8 );
+ pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_PALETTE + 4,
+ cmap.green[fg_idx] >> 8 );
+ pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_PALETTE + 5,
+ cmap.blue[fg_idx] >> 8 );
+ pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0);
+ }
+
+ if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
+ u8 *bitmap = (u8 *)cursor->image.data;
+ u8 *mask = (u8 *)cursor->mask;
+ int i;
+ int pos = PM2VI_RD_CURSOR_PATTERN;
+
+ for (i = 0; i < cursor->image.height; i++) {
+ int j = (cursor->image.width + 7) >> 3;
+ int k = 8 - j;
+
+ pm2_WR(par, PM2VR_RD_INDEX_HIGH, pos >> 8);
+
+ for (; j > 0; j--) {
+ u8 data = *bitmap ^ *mask;
+
+ if (cursor->rop == ROP_COPY)
+ data = *mask & *bitmap;
+ /* Upper 4 bits of bitmap data */
+ pm2v_RDAC_WR(par, pos++,
+ cursor_bits_lookup[data >> 4] |
+ (cursor_bits_lookup[*mask >> 4] << 1));
+ /* Lower 4 bits of bitmap */
+ pm2v_RDAC_WR(par, pos++,
+ cursor_bits_lookup[data & 0xf] |
+ (cursor_bits_lookup[*mask & 0xf] << 1));
+ bitmap++;
+ mask++;
+ }
+ for (; k > 0; k--) {
+ pm2v_RDAC_WR(par, pos++, 0);
+ pm2v_RDAC_WR(par, pos++, 0);
+ }
+ }
+
+ while (pos < (1024 + PM2VI_RD_CURSOR_PATTERN)) {
+ pm2_WR(par, PM2VR_RD_INDEX_HIGH, pos >> 8);
+ pm2v_RDAC_WR(par, pos++, 0);
+ }
+
+ pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0);
+ }
+ return 0;
+}
+
+static int pm2fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+ struct pm2fb_par *par = info->par;
+ u8 mode;
+
+ if (!hwcursor)
+ return -EINVAL; /* just to force soft_cursor() call */
+
+ /* Too large of a cursor or wrong bpp :-( */
+ if (cursor->image.width > 64 ||
+ cursor->image.height > 64 ||
+ cursor->image.depth > 1)
+ return -EINVAL;
+
+ if (par->type == PM2_TYPE_PERMEDIA2V)
+ return pm2vfb_cursor(info, cursor);
+
+ mode = 0x40;
+ if (cursor->enable)
+ mode = 0x43;
+
+ pm2_RDAC_WR(par, PM2I_RD_CURSOR_CONTROL, mode);
+
+ /*
+ * If the cursor is not be changed this means either we want the
+ * current cursor state (if enable is set) or we want to query what
+ * we can do with the cursor (if enable is not set)
+ */
+ if (!cursor->set)
+ return 0;
+
+ if (cursor->set & FB_CUR_SETPOS) {
+ int x = cursor->image.dx - info->var.xoffset + 63;
+ int y = cursor->image.dy - info->var.yoffset + 63;
+
+ WAIT_FIFO(par, 4);
+ pm2_WR(par, PM2R_RD_CURSOR_X_LSB, x & 0xff);
+ pm2_WR(par, PM2R_RD_CURSOR_X_MSB, (x >> 8) & 0x7);
+ pm2_WR(par, PM2R_RD_CURSOR_Y_LSB, y & 0xff);
+ pm2_WR(par, PM2R_RD_CURSOR_Y_MSB, (y >> 8) & 0x7);
+ }
+
+ if (cursor->set & FB_CUR_SETCMAP) {
+ u32 fg_idx = cursor->image.fg_color;
+ u32 bg_idx = cursor->image.bg_color;
+
+ WAIT_FIFO(par, 7);
+ pm2_WR(par, PM2R_RD_CURSOR_COLOR_ADDRESS, 1);
+ pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA,
+ info->cmap.red[bg_idx] >> 8);
+ pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA,
+ info->cmap.green[bg_idx] >> 8);
+ pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA,
+ info->cmap.blue[bg_idx] >> 8);
+
+ pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA,
+ info->cmap.red[fg_idx] >> 8);
+ pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA,
+ info->cmap.green[fg_idx] >> 8);
+ pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA,
+ info->cmap.blue[fg_idx] >> 8);
+ }
+
+ if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
+ u8 *bitmap = (u8 *)cursor->image.data;
+ u8 *mask = (u8 *)cursor->mask;
+ int i;
+
+ WAIT_FIFO(par, 1);
+ pm2_WR(par, PM2R_RD_PALETTE_WRITE_ADDRESS, 0);
+
+ for (i = 0; i < cursor->image.height; i++) {
+ int j = (cursor->image.width + 7) >> 3;
+ int k = 8 - j;
+
+ WAIT_FIFO(par, 8);
+ for (; j > 0; j--) {
+ u8 data = *bitmap ^ *mask;
+
+ if (cursor->rop == ROP_COPY)
+ data = *mask & *bitmap;
+ /* bitmap data */
+ pm2_WR(par, PM2R_RD_CURSOR_DATA, data);
+ bitmap++;
+ mask++;
+ }
+ for (; k > 0; k--)
+ pm2_WR(par, PM2R_RD_CURSOR_DATA, 0);
+ }
+ for (; i < 64; i++) {
+ int j = 8;
+ WAIT_FIFO(par, 8);
+ while (j-- > 0)
+ pm2_WR(par, PM2R_RD_CURSOR_DATA, 0);
+ }
+
+ mask = (u8 *)cursor->mask;
+ for (i = 0; i < cursor->image.height; i++) {
+ int j = (cursor->image.width + 7) >> 3;
+ int k = 8 - j;
+
+ WAIT_FIFO(par, 8);
+ for (; j > 0; j--) {
+ /* mask */
+ pm2_WR(par, PM2R_RD_CURSOR_DATA, *mask);
+ mask++;
+ }
+ for (; k > 0; k--)
+ pm2_WR(par, PM2R_RD_CURSOR_DATA, 0);
+ }
+ for (; i < 64; i++) {
+ int j = 8;
+ WAIT_FIFO(par, 8);
+ while (j-- > 0)
+ pm2_WR(par, PM2R_RD_CURSOR_DATA, 0);
+ }
+ }
+ return 0;
}
/* ------------ Hardware Independent Functions ------------ */
@@ -1172,8 +1494,9 @@ static struct fb_ops pm2fb_ops = {
.fb_pan_display = pm2fb_pan_display,
.fb_fillrect = pm2fb_fillrect,
.fb_copyarea = pm2fb_copyarea,
- .fb_imageblit = cfb_imageblit,
+ .fb_imageblit = pm2fb_imageblit,
.fb_sync = pm2fb_sync,
+ .fb_cursor = pm2fb_cursor,
};
/*
@@ -1194,16 +1517,17 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev,
{
struct pm2fb_par *default_par;
struct fb_info *info;
- int err, err_retval = -ENXIO;
+ int err;
+ int retval = -ENXIO;
err = pci_enable_device(pdev);
- if ( err ) {
+ if (err) {
printk(KERN_WARNING "pm2fb: Can't enable pdev: %d\n", err);
return err;
}
info = framebuffer_alloc(sizeof(struct pm2fb_par), &pdev->dev);
- if ( !info )
+ if (!info)
return -ENOMEM;
default_par = info->par;
@@ -1236,14 +1560,14 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev,
DPRINTK("Register base at 0x%lx\n", pm2fb_fix.mmio_start);
/* Registers - request region and map it. */
- if ( !request_mem_region(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len,
- "pm2fb regbase") ) {
+ if (!request_mem_region(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len,
+ "pm2fb regbase")) {
printk(KERN_WARNING "pm2fb: Can't reserve regbase.\n");
goto err_exit_neither;
}
default_par->v_regs =
ioremap_nocache(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len);
- if ( !default_par->v_regs ) {
+ if (!default_par->v_regs) {
printk(KERN_WARNING "pm2fb: Can't remap %s register area.\n",
pm2fb_fix.id);
release_mem_region(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len);
@@ -1258,72 +1582,101 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev,
default_par->mem_control, default_par->boot_address,
default_par->mem_config);
- if(default_par->mem_control == 0 &&
+ if (default_par->mem_control == 0 &&
default_par->boot_address == 0x31 &&
default_par->mem_config == 0x259fffff) {
default_par->memclock = CVPPC_MEMCLOCK;
- default_par->mem_control=0;
- default_par->boot_address=0x20;
- default_par->mem_config=0xe6002021;
+ default_par->mem_control = 0;
+ default_par->boot_address = 0x20;
+ default_par->mem_config = 0xe6002021;
if (pdev->subsystem_vendor == 0x1048 &&
pdev->subsystem_device == 0x0a31) {
- DPRINTK("subsystem_vendor: %04x, subsystem_device: %04x\n",
+ DPRINTK("subsystem_vendor: %04x, "
+ "subsystem_device: %04x\n",
pdev->subsystem_vendor, pdev->subsystem_device);
- DPRINTK("We have not been initialized by VGA BIOS "
- "and are running on an Elsa Winner 2000 Office\n");
+ DPRINTK("We have not been initialized by VGA BIOS and "
+ "are running on an Elsa Winner 2000 Office\n");
DPRINTK("Initializing card timings manually...\n");
- default_par->memclock=70000;
+ default_par->memclock = 100000;
}
if (pdev->subsystem_vendor == 0x3d3d &&
pdev->subsystem_device == 0x0100) {
- DPRINTK("subsystem_vendor: %04x, subsystem_device: %04x\n",
+ DPRINTK("subsystem_vendor: %04x, "
+ "subsystem_device: %04x\n",
pdev->subsystem_vendor, pdev->subsystem_device);
- DPRINTK("We have not been initialized by VGA BIOS "
- "and are running on an 3dlabs reference board\n");
+ DPRINTK("We have not been initialized by VGA BIOS and "
+ "are running on an 3dlabs reference board\n");
DPRINTK("Initializing card timings manually...\n");
- default_par->memclock=74894;
+ default_par->memclock = 74894;
}
}
/* Now work out how big lfb is going to be. */
- switch(default_par->mem_config & PM2F_MEM_CONFIG_RAM_MASK) {
+ switch (default_par->mem_config & PM2F_MEM_CONFIG_RAM_MASK) {
case PM2F_MEM_BANKS_1:
- pm2fb_fix.smem_len=0x200000;
+ pm2fb_fix.smem_len = 0x200000;
break;
case PM2F_MEM_BANKS_2:
- pm2fb_fix.smem_len=0x400000;
+ pm2fb_fix.smem_len = 0x400000;
break;
case PM2F_MEM_BANKS_3:
- pm2fb_fix.smem_len=0x600000;
+ pm2fb_fix.smem_len = 0x600000;
break;
case PM2F_MEM_BANKS_4:
- pm2fb_fix.smem_len=0x800000;
+ pm2fb_fix.smem_len = 0x800000;
break;
}
pm2fb_fix.smem_start = pci_resource_start(pdev, 1);
/* Linear frame buffer - request region and map it. */
- if ( !request_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len,
- "pm2fb smem") ) {
+ if (!request_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len,
+ "pm2fb smem")) {
printk(KERN_WARNING "pm2fb: Can't reserve smem.\n");
goto err_exit_mmio;
}
info->screen_base =
ioremap_nocache(pm2fb_fix.smem_start, pm2fb_fix.smem_len);
- if ( !info->screen_base ) {
+ if (!info->screen_base) {
printk(KERN_WARNING "pm2fb: Can't ioremap smem area.\n");
release_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len);
goto err_exit_mmio;
}
+#ifdef CONFIG_MTRR
+ default_par->mtrr_handle = -1;
+ if (!nomtrr)
+ default_par->mtrr_handle =
+ mtrr_add(pm2fb_fix.smem_start,
+ pm2fb_fix.smem_len,
+ MTRR_TYPE_WRCOMB, 1);
+#endif
+
info->fbops = &pm2fb_ops;
info->fix = pm2fb_fix;
info->pseudo_palette = default_par->palette;
info->flags = FBINFO_DEFAULT |
FBINFO_HWACCEL_YPAN |
FBINFO_HWACCEL_COPYAREA |
+ FBINFO_HWACCEL_IMAGEBLIT |
FBINFO_HWACCEL_FILLRECT;
+ info->pixmap.addr = kmalloc(PM2_PIXMAP_SIZE, GFP_KERNEL);
+ if (!info->pixmap.addr) {
+ retval = -ENOMEM;
+ goto err_exit_pixmap;
+ }
+ info->pixmap.size = PM2_PIXMAP_SIZE;
+ info->pixmap.buf_align = 4;
+ info->pixmap.scan_align = 4;
+ info->pixmap.access_align = 32;
+ info->pixmap.flags = FB_PIXMAP_SYSTEM;
+
+ if (noaccel) {
+ printk(KERN_DEBUG "disabling acceleration\n");
+ info->flags |= FBINFO_HWACCEL_DISABLED;
+ info->pixmap.scan_align = 1;
+ }
+
if (!mode)
mode = "640x480@60";
@@ -1350,6 +1703,8 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev,
err_exit_all:
fb_dealloc_cmap(&info->cmap);
err_exit_both:
+ kfree(info->pixmap.addr);
+ err_exit_pixmap:
iounmap(info->screen_base);
release_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len);
err_exit_mmio:
@@ -1357,7 +1712,7 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev,
release_mem_region(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len);
err_exit_neither:
framebuffer_release(info);
- return err_retval;
+ return retval;
}
/**
@@ -1369,34 +1724,34 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev,
*/
static void __devexit pm2fb_remove(struct pci_dev *pdev)
{
- struct fb_info* info = pci_get_drvdata(pdev);
- struct fb_fix_screeninfo* fix = &info->fix;
+ struct fb_info *info = pci_get_drvdata(pdev);
+ struct fb_fix_screeninfo *fix = &info->fix;
struct pm2fb_par *par = info->par;
unregister_framebuffer(info);
+#ifdef CONFIG_MTRR
+ if (par->mtrr_handle >= 0)
+ mtrr_del(par->mtrr_handle, info->fix.smem_start,
+ info->fix.smem_len);
+#endif /* CONFIG_MTRR */
iounmap(info->screen_base);
release_mem_region(fix->smem_start, fix->smem_len);
iounmap(par->v_regs);
release_mem_region(fix->mmio_start, fix->mmio_len);
pci_set_drvdata(pdev, NULL);
+ kfree(info->pixmap.addr);
kfree(info);
}
static struct pci_device_id pm2fb_id_table[] = {
{ PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TVP4020,
- PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
- 0xff0000, 0 },
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ PCI_VENDOR_ID_3DLABS, PCI_DEVICE_ID_3DLABS_PERMEDIA2,
- PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
- 0xff0000, 0 },
- { PCI_VENDOR_ID_3DLABS, PCI_DEVICE_ID_3DLABS_PERMEDIA2V,
- PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
- 0xff0000, 0 },
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ PCI_VENDOR_ID_3DLABS, PCI_DEVICE_ID_3DLABS_PERMEDIA2V,
- PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NOT_DEFINED_VGA << 8,
- 0xff00, 0 },
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ 0, }
};
@@ -1418,7 +1773,7 @@ MODULE_DEVICE_TABLE(pci, pm2fb_id_table);
*/
static int __init pm2fb_setup(char *options)
{
- char* this_opt;
+ char *this_opt;
if (!options || !*options)
return 0;
@@ -1426,13 +1781,20 @@ static int __init pm2fb_setup(char *options)
while ((this_opt = strsep(&options, ",")) != NULL) {
if (!*this_opt)
continue;
- if(!strcmp(this_opt, "lowhsync")) {
+ if (!strcmp(this_opt, "lowhsync"))
lowhsync = 1;
- } else if(!strcmp(this_opt, "lowvsync")) {
+ else if (!strcmp(this_opt, "lowvsync"))
lowvsync = 1;
- } else {
+ else if (!strncmp(this_opt, "hwcursor=", 9))
+ hwcursor = simple_strtoul(this_opt + 9, NULL, 0);
+#ifdef CONFIG_MTRR
+ else if (!strncmp(this_opt, "nomtrr", 6))
+ nomtrr = 1;
+#endif
+ else if (!strncmp(this_opt, "noaccel", 7))
+ noaccel = 1;
+ else
mode = this_opt;
- }
}
return 0;
}
@@ -1474,6 +1836,15 @@ module_param(lowhsync, bool, 0);
MODULE_PARM_DESC(lowhsync, "Force horizontal sync low regardless of mode");
module_param(lowvsync, bool, 0);
MODULE_PARM_DESC(lowvsync, "Force vertical sync low regardless of mode");
+module_param(noaccel, bool, 0);
+MODULE_PARM_DESC(noaccel, "Disable acceleration");
+module_param(hwcursor, int, 0644);
+MODULE_PARM_DESC(hwcursor, "Enable hardware cursor "
+ "(1=enable, 0=disable, default=1)");
+#ifdef CONFIG_MTRR
+module_param(nomtrr, bool, 0);
+MODULE_PARM_DESC(nomtrr, "Disable MTRR support (0 or 1=disabled) (default=0)");
+#endif
MODULE_AUTHOR("Jim Hague <jim.hague@acm.org>");
MODULE_DESCRIPTION("Permedia2 framebuffer device driver");
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c
index 5b3f54c0918e..070659992c18 100644
--- a/drivers/video/pm3fb.c
+++ b/drivers/video/pm3fb.c
@@ -32,6 +32,9 @@
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/pci.h>
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
#include <video/pm3fb.h>
@@ -41,15 +44,25 @@
#undef PM3FB_MASTER_DEBUG
#ifdef PM3FB_MASTER_DEBUG
-#define DPRINTK(a,b...) printk(KERN_DEBUG "pm3fb: %s: " a, __FUNCTION__ , ## b)
+#define DPRINTK(a, b...) \
+ printk(KERN_DEBUG "pm3fb: %s: " a, __FUNCTION__ , ## b)
#else
-#define DPRINTK(a,b...)
+#define DPRINTK(a, b...)
#endif
+#define PM3_PIXMAP_SIZE (2048 * 4)
+
/*
* Driver data
*/
+static int hwcursor = 1;
static char *mode_option __devinitdata;
+static int noaccel __devinitdata;
+
+/* mtrr option */
+#ifdef CONFIG_MTRR
+static int nomtrr __devinitdata;
+#endif
/*
* This structure defines the hardware state of the graphics card. Normally
@@ -61,8 +74,9 @@ static char *mode_option __devinitdata;
struct pm3_par {
unsigned char __iomem *v_regs;/* virtual address of p_regs */
u32 video; /* video flags before blanking */
- u32 base; /* screen base (xoffset+yoffset) in 128 bits unit */
+ u32 base; /* screen base in 128 bits unit */
u32 palette[16];
+ int mtrr_handle;
};
/*
@@ -96,7 +110,8 @@ static inline void PM3_WRITE_REG(struct pm3_par *par, s32 off, u32 v)
static inline void PM3_WAIT(struct pm3_par *par, u32 n)
{
- while (PM3_READ_REG(par, PM3InFIFOSpace) < n);
+ while (PM3_READ_REG(par, PM3InFIFOSpace) < n)
+ cpu_relax();
}
static inline void PM3_WRITE_DAC_REG(struct pm3_par *par, unsigned r, u8 v)
@@ -133,7 +148,7 @@ static void pm3fb_clear_colormap(struct pm3_par *par,
}
-/* Calculating various clock parameter */
+/* Calculating various clock parameters */
static void pm3fb_calculate_clock(unsigned long reqclock,
unsigned char *prescale,
unsigned char *feedback,
@@ -164,7 +179,7 @@ static void pm3fb_calculate_clock(unsigned long reqclock,
static inline int pm3fb_depth(const struct fb_var_screeninfo *var)
{
- if ( var->bits_per_pixel == 16 )
+ if (var->bits_per_pixel == 16)
return var->red.length + var->green.length
+ var->blue.length;
@@ -195,8 +210,8 @@ static int pm3fb_sync(struct fb_info *info)
PM3_WRITE_REG(par, PM3Sync, 0);
mb();
do {
- while ((PM3_READ_REG(par, PM3OutFIFOWords)) == 0);
- rmb();
+ while ((PM3_READ_REG(par, PM3OutFIFOWords)) == 0)
+ cpu_relax();
} while ((PM3_READ_REG(par, PM3OutputFifo)) != PM3Sync_Tag);
return 0;
@@ -276,15 +291,22 @@ static void pm3fb_init_engine(struct fb_info *info)
PM3_WAIT(par, 2);
{
- unsigned long rm = 1;
+ /* invert bits in bitmask */
+ unsigned long rm = 1 | (3 << 7);
switch (info->var.bits_per_pixel) {
case 8:
PM3_WRITE_REG(par, PM3PixelSize,
PM3PixelSize_GLOBAL_8BIT);
+#ifdef __BIG_ENDIAN
+ rm |= 3 << 15;
+#endif
break;
case 16:
PM3_WRITE_REG(par, PM3PixelSize,
PM3PixelSize_GLOBAL_16BIT);
+#ifdef __BIG_ENDIAN
+ rm |= 2 << 15;
+#endif
break;
case 32:
PM3_WRITE_REG(par, PM3PixelSize,
@@ -342,7 +364,7 @@ static void pm3fb_init_engine(struct fb_info *info)
PM3_WRITE_REG(par, PM3dXDom, 0x0);
PM3_WRITE_REG(par, PM3dXSub, 0x0);
- PM3_WRITE_REG(par, PM3dY, (1 << 16));
+ PM3_WRITE_REG(par, PM3dY, 1 << 16);
PM3_WRITE_REG(par, PM3StartXDom, 0x0);
PM3_WRITE_REG(par, PM3StartXSub, 0x0);
PM3_WRITE_REG(par, PM3StartY, 0x0);
@@ -357,71 +379,350 @@ static void pm3fb_init_engine(struct fb_info *info)
pm3fb_sync(info);
}
-static void pm3fb_fillrect (struct fb_info *info,
+static void pm3fb_fillrect(struct fb_info *info,
const struct fb_fillrect *region)
{
struct pm3_par *par = info->par;
struct fb_fillrect modded;
int vxres, vyres;
+ int rop;
u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
- ((u32*)info->pseudo_palette)[region->color] : region->color;
+ ((u32 *)info->pseudo_palette)[region->color] : region->color;
if (info->state != FBINFO_STATE_RUNNING)
return;
- if ((info->flags & FBINFO_HWACCEL_DISABLED) ||
- region->rop != ROP_COPY ) {
+ if (info->flags & FBINFO_HWACCEL_DISABLED) {
cfb_fillrect(info, region);
return;
}
+ if (region->rop == ROP_COPY )
+ rop = PM3Config2D_ForegroundROP(0x3); /* GXcopy */
+ else
+ rop = PM3Config2D_ForegroundROP(0x6) | /* GXxor */
+ PM3Config2D_FBDestReadEnable;
vxres = info->var.xres_virtual;
vyres = info->var.yres_virtual;
memcpy(&modded, region, sizeof(struct fb_fillrect));
- if(!modded.width || !modded.height ||
- modded.dx >= vxres || modded.dy >= vyres)
+ if (!modded.width || !modded.height ||
+ modded.dx >= vxres || modded.dy >= vyres)
return;
- if(modded.dx + modded.width > vxres)
+ if (modded.dx + modded.width > vxres)
modded.width = vxres - modded.dx;
- if(modded.dy + modded.height > vyres)
+ if (modded.dy + modded.height > vyres)
modded.height = vyres - modded.dy;
- if(info->var.bits_per_pixel == 8)
+ if (info->var.bits_per_pixel == 8)
color |= color << 8;
- if(info->var.bits_per_pixel <= 16)
+ if (info->var.bits_per_pixel <= 16)
color |= color << 16;
PM3_WAIT(par, 4);
-
+ /* ROP Ox3 is GXcopy */
PM3_WRITE_REG(par, PM3Config2D,
- PM3Config2D_UseConstantSource |
- PM3Config2D_ForegroundROPEnable |
- (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */
- PM3Config2D_FBWriteEnable);
+ PM3Config2D_UseConstantSource |
+ PM3Config2D_ForegroundROPEnable |
+ rop |
+ PM3Config2D_FBWriteEnable);
PM3_WRITE_REG(par, PM3ForegroundColor, color);
PM3_WRITE_REG(par, PM3RectanglePosition,
- (PM3RectanglePosition_XOffset(modded.dx)) |
- (PM3RectanglePosition_YOffset(modded.dy)));
+ PM3RectanglePosition_XOffset(modded.dx) |
+ PM3RectanglePosition_YOffset(modded.dy));
PM3_WRITE_REG(par, PM3Render2D,
PM3Render2D_XPositive |
PM3Render2D_YPositive |
PM3Render2D_Operation_Normal |
PM3Render2D_SpanOperation |
- (PM3Render2D_Width(modded.width)) |
- (PM3Render2D_Height(modded.height)));
+ PM3Render2D_Width(modded.width) |
+ PM3Render2D_Height(modded.height));
+}
+
+static void pm3fb_copyarea(struct fb_info *info,
+ const struct fb_copyarea *area)
+{
+ struct pm3_par *par = info->par;
+ struct fb_copyarea modded;
+ u32 vxres, vyres;
+ int x_align, o_x, o_y;
+
+ if (info->state != FBINFO_STATE_RUNNING)
+ return;
+ if (info->flags & FBINFO_HWACCEL_DISABLED) {
+ cfb_copyarea(info, area);
+ return;
+ }
+
+ memcpy(&modded, area, sizeof(struct fb_copyarea));
+
+ vxres = info->var.xres_virtual;
+ vyres = info->var.yres_virtual;
+
+ if (!modded.width || !modded.height ||
+ modded.sx >= vxres || modded.sy >= vyres ||
+ modded.dx >= vxres || modded.dy >= vyres)
+ return;
+
+ if (modded.sx + modded.width > vxres)
+ modded.width = vxres - modded.sx;
+ if (modded.dx + modded.width > vxres)
+ modded.width = vxres - modded.dx;
+ if (modded.sy + modded.height > vyres)
+ modded.height = vyres - modded.sy;
+ if (modded.dy + modded.height > vyres)
+ modded.height = vyres - modded.dy;
+
+ o_x = modded.sx - modded.dx; /*(sx > dx ) ? (sx - dx) : (dx - sx); */
+ o_y = modded.sy - modded.dy; /*(sy > dy ) ? (sy - dy) : (dy - sy); */
+
+ x_align = (modded.sx & 0x1f);
+
+ PM3_WAIT(par, 6);
+
+ PM3_WRITE_REG(par, PM3Config2D,
+ PM3Config2D_UserScissorEnable |
+ PM3Config2D_ForegroundROPEnable |
+ PM3Config2D_Blocking |
+ PM3Config2D_ForegroundROP(0x3) | /* Ox3 is GXcopy */
+ PM3Config2D_FBWriteEnable);
+
+ PM3_WRITE_REG(par, PM3ScissorMinXY,
+ ((modded.dy & 0x0fff) << 16) | (modded.dx & 0x0fff));
+ PM3_WRITE_REG(par, PM3ScissorMaxXY,
+ (((modded.dy + modded.height) & 0x0fff) << 16) |
+ ((modded.dx + modded.width) & 0x0fff));
+
+ PM3_WRITE_REG(par, PM3FBSourceReadBufferOffset,
+ PM3FBSourceReadBufferOffset_XOffset(o_x) |
+ PM3FBSourceReadBufferOffset_YOffset(o_y));
+
+ PM3_WRITE_REG(par, PM3RectanglePosition,
+ PM3RectanglePosition_XOffset(modded.dx - x_align) |
+ PM3RectanglePosition_YOffset(modded.dy));
+
+ PM3_WRITE_REG(par, PM3Render2D,
+ ((modded.sx > modded.dx) ? PM3Render2D_XPositive : 0) |
+ ((modded.sy > modded.dy) ? PM3Render2D_YPositive : 0) |
+ PM3Render2D_Operation_Normal |
+ PM3Render2D_SpanOperation |
+ PM3Render2D_FBSourceReadEnable |
+ PM3Render2D_Width(modded.width + x_align) |
+ PM3Render2D_Height(modded.height));
+}
+
+static void pm3fb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+ struct pm3_par *par = info->par;
+ u32 height = image->height;
+ u32 fgx, bgx;
+ const u32 *src = (const u32 *)image->data;
+
+ if (info->state != FBINFO_STATE_RUNNING)
+ return;
+ if (info->flags & FBINFO_HWACCEL_DISABLED) {
+ cfb_imageblit(info, image);
+ return;
+ }
+ switch (info->fix.visual) {
+ case FB_VISUAL_PSEUDOCOLOR:
+ fgx = image->fg_color;
+ bgx = image->bg_color;
+ break;
+ case FB_VISUAL_TRUECOLOR:
+ default:
+ fgx = par->palette[image->fg_color];
+ bgx = par->palette[image->bg_color];
+ break;
+ }
+ if (image->depth != 1)
+ return cfb_imageblit(info, image);
+
+ if (info->var.bits_per_pixel == 8) {
+ fgx |= fgx << 8;
+ bgx |= bgx << 8;
+ }
+ if (info->var.bits_per_pixel <= 16) {
+ fgx |= fgx << 16;
+ bgx |= bgx << 16;
+ }
+
+ PM3_WAIT(par, 7);
+
+ PM3_WRITE_REG(par, PM3ForegroundColor, fgx);
+ PM3_WRITE_REG(par, PM3BackgroundColor, bgx);
+
+ /* ROP Ox3 is GXcopy */
+ PM3_WRITE_REG(par, PM3Config2D,
+ PM3Config2D_UserScissorEnable |
+ PM3Config2D_UseConstantSource |
+ PM3Config2D_ForegroundROPEnable |
+ PM3Config2D_ForegroundROP(0x3) |
+ PM3Config2D_OpaqueSpan |
+ PM3Config2D_FBWriteEnable);
+ PM3_WRITE_REG(par, PM3ScissorMinXY,
+ ((image->dy & 0x0fff) << 16) | (image->dx & 0x0fff));
+ PM3_WRITE_REG(par, PM3ScissorMaxXY,
+ (((image->dy + image->height) & 0x0fff) << 16) |
+ ((image->dx + image->width) & 0x0fff));
+ PM3_WRITE_REG(par, PM3RectanglePosition,
+ PM3RectanglePosition_XOffset(image->dx) |
+ PM3RectanglePosition_YOffset(image->dy));
+ PM3_WRITE_REG(par, PM3Render2D,
+ PM3Render2D_XPositive |
+ PM3Render2D_YPositive |
+ PM3Render2D_Operation_SyncOnBitMask |
+ PM3Render2D_SpanOperation |
+ PM3Render2D_Width(image->width) |
+ PM3Render2D_Height(image->height));
+
+
+ while (height--) {
+ int width = ((image->width + 7) >> 3)
+ + info->pixmap.scan_align - 1;
+ width >>= 2;
+
+ while (width >= PM3_FIFO_SIZE) {
+ int i = PM3_FIFO_SIZE - 1;
+
+ PM3_WAIT(par, PM3_FIFO_SIZE);
+ while (i--) {
+ PM3_WRITE_REG(par, PM3BitMaskPattern, *src);
+ src++;
+ }
+ width -= PM3_FIFO_SIZE - 1;
+ }
+
+ PM3_WAIT(par, width + 1);
+ while (width--) {
+ PM3_WRITE_REG(par, PM3BitMaskPattern, *src);
+ src++;
+ }
+ }
}
/* end of acceleration functions */
+/*
+ * Hardware Cursor support.
+ */
+static const u8 cursor_bits_lookup[16] = {
+ 0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
+ 0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55
+};
+
+static int pm3fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+ struct pm3_par *par = info->par;
+ u8 mode;
+
+ if (!hwcursor)
+ return -EINVAL; /* just to force soft_cursor() call */
+
+ /* Too large of a cursor or wrong bpp :-( */
+ if (cursor->image.width > 64 ||
+ cursor->image.height > 64 ||
+ cursor->image.depth > 1)
+ return -EINVAL;
+
+ mode = PM3RD_CursorMode_TYPE_X;
+ if (cursor->enable)
+ mode |= PM3RD_CursorMode_CURSOR_ENABLE;
+
+ PM3_WRITE_DAC_REG(par, PM3RD_CursorMode, mode);
+
+ /*
+ * If the cursor is not be changed this means either we want the
+ * current cursor state (if enable is set) or we want to query what
+ * we can do with the cursor (if enable is not set)
+ */
+ if (!cursor->set)
+ return 0;
+
+ if (cursor->set & FB_CUR_SETPOS) {
+ int x = cursor->image.dx - info->var.xoffset;
+ int y = cursor->image.dy - info->var.yoffset;
+
+ PM3_WRITE_DAC_REG(par, PM3RD_CursorXLow, x & 0xff);
+ PM3_WRITE_DAC_REG(par, PM3RD_CursorXHigh, (x >> 8) & 0xf);
+ PM3_WRITE_DAC_REG(par, PM3RD_CursorYLow, y & 0xff);
+ PM3_WRITE_DAC_REG(par, PM3RD_CursorYHigh, (y >> 8) & 0xf);
+ }
+
+ if (cursor->set & FB_CUR_SETHOT) {
+ PM3_WRITE_DAC_REG(par, PM3RD_CursorHotSpotX,
+ cursor->hot.x & 0x3f);
+ PM3_WRITE_DAC_REG(par, PM3RD_CursorHotSpotY,
+ cursor->hot.y & 0x3f);
+ }
+
+ if (cursor->set & FB_CUR_SETCMAP) {
+ u32 fg_idx = cursor->image.fg_color;
+ u32 bg_idx = cursor->image.bg_color;
+ struct fb_cmap cmap = info->cmap;
+
+ /* the X11 driver says one should use these color registers */
+ PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(39),
+ cmap.red[fg_idx] >> 8 );
+ PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(40),
+ cmap.green[fg_idx] >> 8 );
+ PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(41),
+ cmap.blue[fg_idx] >> 8 );
+
+ PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(42),
+ cmap.red[bg_idx] >> 8 );
+ PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(43),
+ cmap.green[bg_idx] >> 8 );
+ PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(44),
+ cmap.blue[bg_idx] >> 8 );
+ }
+
+ if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
+ u8 *bitmap = (u8 *)cursor->image.data;
+ u8 *mask = (u8 *)cursor->mask;
+ int i;
+ int pos = PM3RD_CursorPattern(0);
+
+ for (i = 0; i < cursor->image.height; i++) {
+ int j = (cursor->image.width + 7) >> 3;
+ int k = 8 - j;
+
+ for (; j > 0; j--) {
+ u8 data = *bitmap ^ *mask;
+
+ if (cursor->rop == ROP_COPY)
+ data = *mask & *bitmap;
+ /* Upper 4 bits of bitmap data */
+ PM3_WRITE_DAC_REG(par, pos++,
+ cursor_bits_lookup[data >> 4] |
+ (cursor_bits_lookup[*mask >> 4] << 1));
+ /* Lower 4 bits of bitmap */
+ PM3_WRITE_DAC_REG(par, pos++,
+ cursor_bits_lookup[data & 0xf] |
+ (cursor_bits_lookup[*mask & 0xf] << 1));
+ bitmap++;
+ mask++;
+ }
+ for (; k > 0; k--) {
+ PM3_WRITE_DAC_REG(par, pos++, 0);
+ PM3_WRITE_DAC_REG(par, pos++, 0);
+ }
+ }
+ while (pos < PM3RD_CursorPattern(1024))
+ PM3_WRITE_DAC_REG(par, pos++, 0);
+ }
+ return 0;
+}
+
/* write the mode to registers */
static void pm3fb_write_mode(struct fb_info *info)
{
struct pm3_par *par = info->par;
- char tempsync = 0x00, tempmisc = 0x00;
+ char tempsync = 0x00;
+ char tempmisc = 0x00;
const u32 hsstart = info->var.right_margin;
const u32 hsend = hsstart + info->var.hsync_len;
const u32 hbend = hsend + info->var.left_margin;
@@ -618,47 +919,57 @@ static int pm3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
unsigned bpp = var->red.length + var->green.length
+ var->blue.length + var->transp.length;
- if ( bpp != var->bits_per_pixel ) {
+ if (bpp != var->bits_per_pixel) {
/* set predefined mode for bits_per_pixel settings */
- switch(var->bits_per_pixel) {
+ switch (var->bits_per_pixel) {
case 8:
- var->red.length = var->green.length = var->blue.length = 8;
- var->red.offset = var->green.offset = var->blue.offset = 0;
+ var->red.length = 8;
+ var->green.length = 8;
+ var->blue.length = 8;
+ var->red.offset = 0;
+ var->green.offset = 0;
+ var->blue.offset = 0;
var->transp.offset = 0;
var->transp.length = 0;
break;
case 16:
- var->red.length = var->blue.length = 5;
+ var->red.length = 5;
+ var->blue.length = 5;
var->green.length = 6;
var->transp.length = 0;
break;
case 32:
- var->red.length = var->green.length = var->blue.length = 8;
+ var->red.length = 8;
+ var->green.length = 8;
+ var->blue.length = 8;
var->transp.length = 8;
break;
default:
- DPRINTK("depth not supported: %u\n", var->bits_per_pixel);
+ DPRINTK("depth not supported: %u\n",
+ var->bits_per_pixel);
return -EINVAL;
}
}
/* it is assumed BGRA order */
- if (var->bits_per_pixel > 8 )
- {
+ if (var->bits_per_pixel > 8 ) {
var->blue.offset = 0;
var->green.offset = var->blue.length;
var->red.offset = var->green.offset + var->green.length;
var->transp.offset = var->red.offset + var->red.length;
}
- var->height = var->width = -1;
+ var->height = -1;
+ var->width = -1;
if (var->xres != var->xres_virtual) {
- DPRINTK("virtual x resolution != physical x resolution not supported\n");
+ DPRINTK("virtual x resolution != "
+ "physical x resolution not supported\n");
return -EINVAL;
}
if (var->yres > var->yres_virtual) {
- DPRINTK("virtual y resolution < physical y resolution not possible\n");
+ DPRINTK("virtual y resolution < "
+ "physical y resolution not possible\n");
return -EINVAL;
}
@@ -673,7 +984,7 @@ static int pm3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
}
var->xres = (var->xres + 31) & ~31; /* could sometimes be 8 */
- lpitch = var->xres * ((var->bits_per_pixel + 7)>>3);
+ lpitch = var->xres * ((var->bits_per_pixel + 7) >> 3);
if (var->xres < 200 || var->xres > 2048) {
DPRINTK("width not supported: %u\n", var->xres);
@@ -692,7 +1003,8 @@ static int pm3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
}
if (PICOS2KHZ(var->pixclock) > PM3_MAX_PIXCLOCK) {
- DPRINTK("pixclock too high (%ldKHz)\n", PICOS2KHZ(var->pixclock));
+ DPRINTK("pixclock too high (%ldKHz)\n",
+ PICOS2KHZ(var->pixclock));
return -EINVAL;
}
@@ -709,7 +1021,7 @@ static int pm3fb_set_par(struct fb_info *info)
const u32 xres = (info->var.xres + 31) & ~31;
const unsigned bpp = info->var.bits_per_pixel;
- par->base = pm3fb_shift_bpp(bpp,(info->var.yoffset * xres)
+ par->base = pm3fb_shift_bpp(bpp, (info->var.yoffset * xres)
+ info->var.xoffset);
par->video = 0;
@@ -725,15 +1037,12 @@ static int pm3fb_set_par(struct fb_info *info)
if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
par->video |= PM3VideoControl_LINE_DOUBLE_ON;
- else
- par->video |= PM3VideoControl_LINE_DOUBLE_OFF;
if ((info->var.activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW)
par->video |= PM3VideoControl_ENABLE;
- else {
- par->video |= PM3VideoControl_DISABLE;
+ else
DPRINTK("PM3Video disabled\n");
- }
+
switch (bpp) {
case 8:
par->video |= PM3VideoControl_PIXELSIZE_8BIT;
@@ -751,13 +1060,11 @@ static int pm3fb_set_par(struct fb_info *info)
info->fix.visual =
(bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
- info->fix.line_length = ((info->var.xres_virtual + 7) & ~7)
- * bpp / 8;
+ info->fix.line_length = ((info->var.xres_virtual + 7) >> 3) * bpp;
/* pm3fb_clear_memory(info, 0);*/
pm3fb_clear_colormap(par, 0, 0, 0);
- PM3_WRITE_DAC_REG(par, PM3RD_CursorMode,
- PM3RD_CursorMode_CURSOR_DISABLE);
+ PM3_WRITE_DAC_REG(par, PM3RD_CursorMode, 0);
pm3fb_init_engine(info);
pm3fb_write_mode(info);
return 0;
@@ -773,10 +1080,9 @@ static int pm3fb_setcolreg(unsigned regno, unsigned red, unsigned green,
return -EINVAL;
/* grayscale works only partially under directcolor */
- if (info->var.grayscale) {
- /* grayscale = 0.30*R + 0.59*G + 0.11*B */
+ /* grayscale = 0.30*R + 0.59*G + 0.11*B */
+ if (info->var.grayscale)
red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
- }
/* Directcolor:
* var->{color}.offset contains start of bitfield
@@ -790,8 +1096,8 @@ static int pm3fb_setcolreg(unsigned regno, unsigned red, unsigned green,
*
* Pseudocolor:
* var->{color}.offset is 0
- * var->{color}.length contains width of DAC or the number of unique
- * colors available (color depth)
+ * var->{color}.length contains width of DAC or the number
+ * of unique colors available (color depth)
* pseudo_palette is not used
* RAMDAC[X] is programmed to (red, green, blue)
* color depth = var->{color}.length
@@ -801,7 +1107,7 @@ static int pm3fb_setcolreg(unsigned regno, unsigned red, unsigned green,
* This is the point where the color is converted to something that
* is acceptable by the hardware.
*/
-#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
+#define CNVT_TOHW(val, width) ((((val) << (width)) + 0x7FFF - (val)) >> 16)
red = CNVT_TOHW(red, info->var.red.length);
green = CNVT_TOHW(green, info->var.green.length);
blue = CNVT_TOHW(blue, info->var.blue.length);
@@ -825,12 +1131,11 @@ static int pm3fb_setcolreg(unsigned regno, unsigned red, unsigned green,
break;
case 16:
case 32:
- ((u32*)(info->pseudo_palette))[regno] = v;
+ ((u32 *)(info->pseudo_palette))[regno] = v;
break;
}
return 0;
- }
- else if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR)
+ } else if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR)
pm3fb_set_color(par, regno, red, green, blue);
return 0;
@@ -871,7 +1176,7 @@ static int pm3fb_blank(int blank_mode, struct fb_info *info)
video |= PM3VideoControl_ENABLE;
break;
case FB_BLANK_NORMAL:
- video &= ~(PM3VideoControl_ENABLE);
+ video &= ~PM3VideoControl_ENABLE;
break;
case FB_BLANK_HSYNC_SUSPEND:
video &= ~(PM3VideoControl_HSYNC_MASK |
@@ -892,7 +1197,7 @@ static int pm3fb_blank(int blank_mode, struct fb_info *info)
}
PM3_WAIT(par, 1);
- PM3_WRITE_REG(par,PM3VideoControl, video);
+ PM3_WRITE_REG(par, PM3VideoControl, video);
return 0;
}
@@ -907,10 +1212,11 @@ static struct fb_ops pm3fb_ops = {
.fb_setcolreg = pm3fb_setcolreg,
.fb_pan_display = pm3fb_pan_display,
.fb_fillrect = pm3fb_fillrect,
- .fb_copyarea = cfb_copyarea,
- .fb_imageblit = cfb_imageblit,
+ .fb_copyarea = pm3fb_copyarea,
+ .fb_imageblit = pm3fb_imageblit,
.fb_blank = pm3fb_blank,
.fb_sync = pm3fb_sync,
+ .fb_cursor = pm3fb_cursor,
};
/* ------------------------------------------------------------------------- */
@@ -923,7 +1229,8 @@ static struct fb_ops pm3fb_ops = {
/* the pm3fb_fix.smem_start is also set */
static unsigned long pm3fb_size_memory(struct pm3_par *par)
{
- unsigned long memsize = 0, tempBypass, i, temp1, temp2;
+ unsigned long memsize = 0;
+ unsigned long tempBypass, i, temp1, temp2;
unsigned char __iomem *screen_mem;
pm3fb_fix.smem_len = 64 * 1024l * 1024; /* request full aperture size */
@@ -951,7 +1258,9 @@ static unsigned long pm3fb_size_memory(struct pm3_par *par)
PM3_WAIT(par, 1);
PM3_WRITE_REG(par, PM3MemBypassWriteMask, 0xFFFFFFFF);
- /* pm3 split up memory, replicates, and do a lot of nasty stuff IMHO ;-) */
+ /* pm3 split up memory, replicates, and do a lot of
+ * nasty stuff IMHO ;-)
+ */
for (i = 0; i < 32; i++) {
fb_writel(i * 0x00345678,
(screen_mem + (i * 1048576)));
@@ -1008,8 +1317,9 @@ static int __devinit pm3fb_probe(struct pci_dev *dev,
{
struct fb_info *info;
struct pm3_par *par;
- struct device* device = &dev->dev; /* for pci drivers */
- int err, retval = -ENXIO;
+ struct device *device = &dev->dev; /* for pci drivers */
+ int err;
+ int retval = -ENXIO;
err = pci_enable_device(dev);
if (err) {
@@ -1031,6 +1341,10 @@ static int __devinit pm3fb_probe(struct pci_dev *dev,
*/
pm3fb_fix.mmio_start = pci_resource_start(dev, 0);
pm3fb_fix.mmio_len = PM3_REGS_SIZE;
+#if defined(__BIG_ENDIAN)
+ pm3fb_fix.mmio_start += PM3_REGS_SIZE;
+ DPRINTK("Adjusting register base for big-endian.\n");
+#endif
/* Registers - request region and map it. */
if (!request_mem_region(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len,
@@ -1047,15 +1361,10 @@ static int __devinit pm3fb_probe(struct pci_dev *dev,
goto err_exit_neither;
}
-#if defined(__BIG_ENDIAN)
- pm3fb_fix.mmio_start += PM3_REGS_SIZE;
- DPRINTK("Adjusting register base for big-endian.\n");
-#endif
/* Linear frame buffer - request region and map it. */
pm3fb_fix.smem_start = pci_resource_start(dev, 1);
pm3fb_fix.smem_len = pm3fb_size_memory(par);
- if (!pm3fb_fix.smem_len)
- {
+ if (!pm3fb_fix.smem_len) {
printk(KERN_WARNING "pm3fb: Can't find memory on board.\n");
goto err_exit_mmio;
}
@@ -1073,6 +1382,12 @@ static int __devinit pm3fb_probe(struct pci_dev *dev,
}
info->screen_size = pm3fb_fix.smem_len;
+#ifdef CONFIG_MTRR
+ if (!nomtrr)
+ par->mtrr_handle = mtrr_add(pm3fb_fix.smem_start,
+ pm3fb_fix.smem_len,
+ MTRR_TYPE_WRCOMB, 1);
+#endif
info->fbops = &pm3fb_ops;
par->video = PM3_READ_REG(par, PM3VideoControl);
@@ -1080,7 +1395,26 @@ static int __devinit pm3fb_probe(struct pci_dev *dev,
info->fix = pm3fb_fix;
info->pseudo_palette = par->palette;
info->flags = FBINFO_DEFAULT |
- FBINFO_HWACCEL_FILLRECT;/* | FBINFO_HWACCEL_YPAN;*/
+ FBINFO_HWACCEL_XPAN |
+ FBINFO_HWACCEL_YPAN |
+ FBINFO_HWACCEL_COPYAREA |
+ FBINFO_HWACCEL_IMAGEBLIT |
+ FBINFO_HWACCEL_FILLRECT;
+
+ if (noaccel) {
+ printk(KERN_DEBUG "disabling acceleration\n");
+ info->flags |= FBINFO_HWACCEL_DISABLED;
+ }
+ info->pixmap.addr = kmalloc(PM3_PIXMAP_SIZE, GFP_KERNEL);
+ if (!info->pixmap.addr) {
+ retval = -ENOMEM;
+ goto err_exit_pixmap;
+ }
+ info->pixmap.size = PM3_PIXMAP_SIZE;
+ info->pixmap.buf_align = 4;
+ info->pixmap.scan_align = 4;
+ info->pixmap.access_align = 32;
+ info->pixmap.flags = FB_PIXMAP_SYSTEM;
/*
* This should give a reasonable default video mode. The following is
@@ -1118,6 +1452,8 @@ static int __devinit pm3fb_probe(struct pci_dev *dev,
err_exit_all:
fb_dealloc_cmap(&info->cmap);
err_exit_both:
+ kfree(info->pixmap.addr);
+ err_exit_pixmap:
iounmap(info->screen_base);
release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
err_exit_mmio:
@@ -1142,12 +1478,18 @@ static void __devexit pm3fb_remove(struct pci_dev *dev)
unregister_framebuffer(info);
fb_dealloc_cmap(&info->cmap);
+#ifdef CONFIG_MTRR
+ if (par->mtrr_handle >= 0)
+ mtrr_del(par->mtrr_handle, info->fix.smem_start,
+ info->fix.smem_len);
+#endif /* CONFIG_MTRR */
iounmap(info->screen_base);
release_mem_region(fix->smem_start, fix->smem_len);
iounmap(par->v_regs);
release_mem_region(fix->mmio_start, fix->mmio_len);
pci_set_drvdata(dev, NULL);
+ kfree(info->pixmap.addr);
framebuffer_release(info);
}
}
@@ -1168,21 +1510,76 @@ static struct pci_driver pm3fb_driver = {
MODULE_DEVICE_TABLE(pci, pm3fb_id_table);
+#ifndef MODULE
+ /*
+ * Setup
+ */
+
+/*
+ * Only necessary if your driver takes special options,
+ * otherwise we fall back on the generic fb_setup().
+ */
+static int __init pm3fb_setup(char *options)
+{
+ char *this_opt;
+
+ /* Parse user speficied options (`video=pm3fb:') */
+ if (!options || !*options)
+ return 0;
+
+ while ((this_opt = strsep(&options, ",")) != NULL) {
+ if (!*this_opt)
+ continue;
+ else if (!strncmp(this_opt, "noaccel", 7))
+ noaccel = 1;
+ else if (!strncmp(this_opt, "hwcursor=", 9))
+ hwcursor = simple_strtoul(this_opt + 9, NULL, 0);
+#ifdef CONFIG_MTRR
+ else if (!strncmp(this_opt, "nomtrr", 6))
+ nomtrr = 1;
+#endif
+ else
+ mode_option = this_opt;
+ }
+ return 0;
+}
+#endif /* MODULE */
+
static int __init pm3fb_init(void)
{
+ /*
+ * For kernel boot options (in 'video=pm3fb:<options>' format)
+ */
#ifndef MODULE
- if (fb_get_options("pm3fb", NULL))
+ char *option = NULL;
+
+ if (fb_get_options("pm3fb", &option))
return -ENODEV;
+ pm3fb_setup(option);
#endif
+
return pci_register_driver(&pm3fb_driver);
}
+#ifdef MODULE
static void __exit pm3fb_exit(void)
{
pci_unregister_driver(&pm3fb_driver);
}
-module_init(pm3fb_init);
module_exit(pm3fb_exit);
+#endif
+module_init(pm3fb_init);
+
+module_param(noaccel, bool, 0);
+MODULE_PARM_DESC(noaccel, "Disable acceleration");
+module_param(hwcursor, int, 0644);
+MODULE_PARM_DESC(hwcursor, "Enable hardware cursor "
+ "(1=enable, 0=disable, default=1)");
+#ifdef CONFIG_MTRR
+module_param(nomtrr, bool, 0);
+MODULE_PARM_DESC(nomtrr, "Disable MTRR support (0 or 1=disabled) (default=0)");
+#endif
+MODULE_DESCRIPTION("Permedia3 framebuffer device driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c
index 264d37243fad..3a3f80f65219 100644
--- a/drivers/video/pmag-ba-fb.c
+++ b/drivers/video/pmag-ba-fb.c
@@ -147,16 +147,23 @@ static int __init pmagbafb_probe(struct device *dev)
resource_size_t start, len;
struct fb_info *info;
struct pmagbafb_par *par;
+ int err;
info = framebuffer_alloc(sizeof(struct pmagbafb_par), dev);
- if (!info)
+ if (!info) {
+ printk(KERN_ERR "%s: Cannot allocate memory\n", dev->bus_id);
return -ENOMEM;
+ }
par = info->par;
dev_set_drvdata(dev, info);
- if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
+ if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
+ printk(KERN_ERR "%s: Cannot allocate color map\n",
+ dev->bus_id);
+ err = -ENOMEM;
goto err_alloc;
+ }
info->fbops = &pmagbafb_ops;
info->fix = pmagbafb_fix;
@@ -166,28 +173,41 @@ static int __init pmagbafb_probe(struct device *dev)
/* Request the I/O MEM resource. */
start = tdev->resource.start;
len = tdev->resource.end - start + 1;
- if (!request_mem_region(start, len, dev->bus_id))
+ if (!request_mem_region(start, len, dev->bus_id)) {
+ printk(KERN_ERR "%s: Cannot reserve FB region\n", dev->bus_id);
+ err = -EBUSY;
goto err_cmap;
+ }
/* MMIO mapping setup. */
info->fix.mmio_start = start;
par->mmio = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len);
- if (!par->mmio)
+ if (!par->mmio) {
+ printk(KERN_ERR "%s: Cannot map MMIO\n", dev->bus_id);
+ err = -ENOMEM;
goto err_resource;
+ }
par->dac = par->mmio + PMAG_BA_BT459;
/* Frame buffer mapping setup. */
info->fix.smem_start = start + PMAG_BA_FBMEM;
info->screen_base = ioremap_nocache(info->fix.smem_start,
info->fix.smem_len);
- if (!info->screen_base)
+ if (!info->screen_base) {
+ printk(KERN_ERR "%s: Cannot map FB\n", dev->bus_id);
+ err = -ENOMEM;
goto err_mmio_map;
+ }
info->screen_size = info->fix.smem_len;
pmagbafb_erase_cursor(info);
- if (register_framebuffer(info) < 0)
+ err = register_framebuffer(info);
+ if (err < 0) {
+ printk(KERN_ERR "%s: Cannot register framebuffer\n",
+ dev->bus_id);
goto err_smem_map;
+ }
get_device(dev);
@@ -211,7 +231,7 @@ err_cmap:
err_alloc:
framebuffer_release(info);
- return -ENXIO;
+ return err;
}
static int __exit pmagbafb_remove(struct device *dev)
diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c
index 7a0ce7d5af6b..9b80597241b0 100644
--- a/drivers/video/pmagb-b-fb.c
+++ b/drivers/video/pmagb-b-fb.c
@@ -254,16 +254,23 @@ static int __init pmagbbfb_probe(struct device *dev)
struct pmagbbfb_par *par;
char freq0[12], freq1[12];
u32 vid_base;
+ int err;
info = framebuffer_alloc(sizeof(struct pmagbbfb_par), dev);
- if (!info)
+ if (!info) {
+ printk(KERN_ERR "%s: Cannot allocate memory\n", dev->bus_id);
return -ENOMEM;
+ }
par = info->par;
dev_set_drvdata(dev, info);
- if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
+ if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
+ printk(KERN_ERR "%s: Cannot allocate color map\n",
+ dev->bus_id);
+ err = -ENOMEM;
goto err_alloc;
+ }
info->fbops = &pmagbbfb_ops;
info->fix = pmagbbfb_fix;
@@ -273,22 +280,31 @@ static int __init pmagbbfb_probe(struct device *dev)
/* Request the I/O MEM resource. */
start = tdev->resource.start;
len = tdev->resource.end - start + 1;
- if (!request_mem_region(start, len, dev->bus_id))
+ if (!request_mem_region(start, len, dev->bus_id)) {
+ printk(KERN_ERR "%s: Cannot reserve FB region\n", dev->bus_id);
+ err = -EBUSY;
goto err_cmap;
+ }
/* MMIO mapping setup. */
info->fix.mmio_start = start;
par->mmio = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len);
- if (!par->mmio)
+ if (!par->mmio) {
+ printk(KERN_ERR "%s: Cannot map MMIO\n", dev->bus_id);
+ err = -ENOMEM;
goto err_resource;
+ }
par->sfb = par->mmio + PMAGB_B_SFB;
par->dac = par->mmio + PMAGB_B_BT459;
/* Frame buffer mapping setup. */
info->fix.smem_start = start + PMAGB_B_FBMEM;
par->smem = ioremap_nocache(info->fix.smem_start, info->fix.smem_len);
- if (!par->smem)
+ if (!par->smem) {
+ printk(KERN_ERR "%s: Cannot map FB\n", dev->bus_id);
+ err = -ENOMEM;
goto err_mmio_map;
+ }
vid_base = sfb_read(par, SFB_REG_VID_BASE);
info->screen_base = (void __iomem *)par->smem + vid_base * 0x1000;
info->screen_size = info->fix.smem_len - 2 * vid_base * 0x1000;
@@ -297,8 +313,12 @@ static int __init pmagbbfb_probe(struct device *dev)
pmagbbfb_screen_setup(info);
pmagbbfb_osc_setup(info);
- if (register_framebuffer(info) < 0)
+ err = register_framebuffer(info);
+ if (err < 0) {
+ printk(KERN_ERR "%s: Cannot register framebuffer\n",
+ dev->bus_id);
goto err_smem_map;
+ }
get_device(dev);
@@ -330,7 +350,7 @@ err_cmap:
err_alloc:
framebuffer_release(info);
- return -ENXIO;
+ return err;
}
static int __exit pmagbbfb_remove(struct device *dev)
diff --git a/drivers/video/pnx4008/pnxrgbfb.c b/drivers/video/pnx4008/pnxrgbfb.c
index f29e66e2d774..685761a0732c 100644
--- a/drivers/video/pnx4008/pnxrgbfb.c
+++ b/drivers/video/pnx4008/pnxrgbfb.c
@@ -26,7 +26,6 @@
#include <linux/init.h>
#include <linux/platform_device.h>
-#include <asm/uaccess.h>
#include "sdum.h"
#include "fbcommon.h"
diff --git a/drivers/video/pnx4008/sdum.h b/drivers/video/pnx4008/sdum.h
index e8c5dcdd8813..189c3d641383 100644
--- a/drivers/video/pnx4008/sdum.h
+++ b/drivers/video/pnx4008/sdum.h
@@ -77,9 +77,6 @@
#define CONF_DIRTYDETECTION_OFF (0x600)
#define CONF_DIRTYDETECTION_ON (0x601)
-/* Set the corresponding bit. */
-#define BIT(n) (0x1U << (n))
-
struct dumchannel_uf {
int channelnr;
u32 *dirty;
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c
index 646ec823c168..75836aa83191 100644
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -22,22 +22,14 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/console.h>
#include <linux/ioctl.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
#include <linux/kthread.h>
#include <linux/freezer.h>
-
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/fb.h>
#include <linux/init.h>
-#include <asm/time.h>
#include <asm/abs_addr.h>
#include <asm/lv1call.h>
@@ -48,12 +40,6 @@
#define DEVICE_NAME "ps3fb"
-#ifdef PS3FB_DEBUG
-#define DPRINTK(fmt, args...) printk("%s: " fmt, __func__ , ##args)
-#else
-#define DPRINTK(fmt, args...)
-#endif
-
#define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC 0x101
#define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP 0x102
#define L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP 0x600
@@ -66,8 +52,10 @@
#define L1GPU_DISPLAY_SYNC_VSYNC 2
#define DDR_SIZE (0) /* used no ddr */
-#define GPU_OFFSET (64 * 1024)
+#define GPU_CMD_BUF_SIZE (64 * 1024)
#define GPU_IOIF (0x0d000000UL)
+#define GPU_ALIGN_UP(x) _ALIGN_UP((x), 64)
+#define GPU_MAX_LINE_LENGTH (65536 - 64)
#define PS3FB_FULL_MODE_BIT 0x80
@@ -131,13 +119,12 @@ struct ps3fb_priv {
u64 context_handle, memory_handle;
void *xdr_ea;
+ size_t xdr_size;
struct gpu_driver_info *dinfo;
- u32 res_index;
u64 vblank_count; /* frame count */
wait_queue_head_t wait_vsync;
- u32 num_frames; /* num of frame buffers */
atomic_t ext_flip; /* on/off flip with vsync */
atomic_t f_count; /* fb_open count */
int is_blanked;
@@ -146,6 +133,18 @@ struct ps3fb_priv {
};
static struct ps3fb_priv ps3fb;
+struct ps3fb_par {
+ u32 pseudo_palette[16];
+ int mode_id, new_mode_id;
+ int res_index;
+ unsigned int num_frames; /* num of frame buffers */
+ unsigned int width;
+ unsigned int height;
+ unsigned long full_offset; /* start of fullscreen DDR fb */
+ unsigned long fb_offset; /* start of actual DDR fb */
+ unsigned long pan_offset;
+};
+
struct ps3fb_res_table {
u32 xres;
u32 yres;
@@ -294,29 +293,31 @@ static const struct fb_videomode ps3fb_modedb[] = {
#define Y_OFF(i) (ps3fb_res[i].yoff) /* top/bottom margin (pixel) */
#define WIDTH(i) (ps3fb_res[i].xres) /* width of FB */
#define HEIGHT(i) (ps3fb_res[i].yres) /* height of FB */
-#define BPP 4 /* number of bytes per pixel */
-#define VP_OFF(i) (WIDTH(i) * Y_OFF(i) * BPP + X_OFF(i) * BPP)
-#define FB_OFF(i) (GPU_OFFSET - VP_OFF(i) % GPU_OFFSET)
+#define BPP 4 /* number of bytes per pixel */
+
+/* Start of the virtual frame buffer (relative to fullscreen ) */
+#define VP_OFF(i) ((WIDTH(i) * Y_OFF(i) + X_OFF(i)) * BPP)
+
static int ps3fb_mode;
module_param(ps3fb_mode, int, 0);
static char *mode_option __devinitdata;
-static int ps3fb_get_res_table(u32 xres, u32 yres)
+static int ps3fb_get_res_table(u32 xres, u32 yres, int mode)
{
int full_mode;
unsigned int i;
u32 x, y, f;
- full_mode = (ps3fb_mode & PS3FB_FULL_MODE_BIT) ? PS3FB_RES_FULL : 0;
+ full_mode = (mode & PS3FB_FULL_MODE_BIT) ? PS3FB_RES_FULL : 0;
for (i = 0;; i++) {
x = ps3fb_res[i].xres;
y = ps3fb_res[i].yres;
f = ps3fb_res[i].type;
if (!x) {
- DPRINTK("ERROR: ps3fb_get_res_table()\n");
+ pr_debug("ERROR: ps3fb_get_res_table()\n");
return -1;
}
@@ -335,7 +336,7 @@ static int ps3fb_get_res_table(u32 xres, u32 yres)
}
static unsigned int ps3fb_find_mode(const struct fb_var_screeninfo *var,
- u32 *line_length)
+ u32 *ddr_line_length, u32 *xdr_line_length)
{
unsigned int i, mode;
@@ -350,31 +351,41 @@ static unsigned int ps3fb_find_mode(const struct fb_var_screeninfo *var,
var->upper_margin == ps3fb_modedb[i].upper_margin &&
var->lower_margin == ps3fb_modedb[i].lower_margin &&
var->sync == ps3fb_modedb[i].sync &&
- (var->vmode & FB_VMODE_MASK) == ps3fb_modedb[i].vmode) {
- /* Cropped broadcast modes use the full line_length */
- *line_length =
- ps3fb_modedb[i < 10 ? i + 13 : i].xres * 4;
- /* Full broadcast modes have the full mode bit set */
- mode = i > 12 ? (i - 12) | PS3FB_FULL_MODE_BIT : i + 1;
-
- DPRINTK("ps3fb_find_mode: mode %u\n", mode);
- return mode;
- }
+ (var->vmode & FB_VMODE_MASK) == ps3fb_modedb[i].vmode)
+ goto found;
- DPRINTK("ps3fb_find_mode: mode not found\n");
+ pr_debug("ps3fb_find_mode: mode not found\n");
return 0;
+found:
+ /* Cropped broadcast modes use the full line length */
+ *ddr_line_length = ps3fb_modedb[i < 10 ? i + 13 : i].xres * BPP;
+
+ if (ps3_compare_firmware_version(1, 9, 0) >= 0) {
+ *xdr_line_length = GPU_ALIGN_UP(max(var->xres,
+ var->xres_virtual) * BPP);
+ if (*xdr_line_length > GPU_MAX_LINE_LENGTH)
+ *xdr_line_length = GPU_MAX_LINE_LENGTH;
+ } else
+ *xdr_line_length = *ddr_line_length;
+
+ /* Full broadcast modes have the full mode bit set */
+ mode = i > 12 ? (i - 12) | PS3FB_FULL_MODE_BIT : i + 1;
+
+ pr_debug("ps3fb_find_mode: mode %u\n", mode);
+
+ return mode;
}
-static const struct fb_videomode *ps3fb_default_mode(void)
+static const struct fb_videomode *ps3fb_default_mode(int id)
{
- u32 mode = ps3fb_mode & PS3AV_MODE_MASK;
+ u32 mode = id & PS3AV_MODE_MASK;
u32 flags;
if (mode < 1 || mode > 13)
return NULL;
- flags = ps3fb_mode & ~PS3AV_MODE_MASK;
+ flags = id & ~PS3AV_MODE_MASK;
if (mode <= 10 && flags & PS3FB_FULL_MODE_BIT) {
/* Full broadcast mode */
@@ -384,55 +395,77 @@ static const struct fb_videomode *ps3fb_default_mode(void)
return &ps3fb_modedb[mode - 1];
}
-static int ps3fb_sync(u32 frame)
+static void ps3fb_sync_image(struct device *dev, u64 frame_offset,
+ u64 dst_offset, u64 src_offset, u32 width,
+ u32 height, u32 dst_line_length,
+ u32 src_line_length)
{
- int i, status;
- u32 xres, yres;
- u64 fb_ioif, offset;
-
- i = ps3fb.res_index;
- xres = ps3fb_res[i].xres;
- yres = ps3fb_res[i].yres;
+ int status;
+ u64 line_length;
- if (frame > ps3fb.num_frames - 1) {
- printk(KERN_WARNING "%s: invalid frame number (%u)\n",
- __func__, frame);
- return -EINVAL;
- }
- offset = xres * yres * BPP * frame;
+ line_length = dst_line_length;
+ if (src_line_length != dst_line_length)
+ line_length |= (u64)src_line_length << 32;
- fb_ioif = GPU_IOIF + FB_OFF(i) + offset;
status = lv1_gpu_context_attribute(ps3fb.context_handle,
L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT,
- offset, fb_ioif,
+ dst_offset, GPU_IOIF + src_offset,
L1GPU_FB_BLIT_WAIT_FOR_COMPLETION |
- (xres << 16) | yres,
- xres * BPP); /* line_length */
+ (width << 16) | height,
+ line_length);
if (status)
- printk(KERN_ERR
- "%s: lv1_gpu_context_attribute FB_BLIT failed: %d\n",
- __func__, status);
+ dev_err(dev,
+ "%s: lv1_gpu_context_attribute FB_BLIT failed: %d\n",
+ __func__, status);
#ifdef HEAD_A
status = lv1_gpu_context_attribute(ps3fb.context_handle,
L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP,
- 0, offset, 0, 0);
+ 0, frame_offset, 0, 0);
if (status)
- printk(KERN_ERR
- "%s: lv1_gpu_context_attribute FLIP failed: %d\n",
- __func__, status);
+ dev_err(dev, "%s: lv1_gpu_context_attribute FLIP failed: %d\n",
+ __func__, status);
#endif
#ifdef HEAD_B
status = lv1_gpu_context_attribute(ps3fb.context_handle,
L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP,
- 1, offset, 0, 0);
+ 1, frame_offset, 0, 0);
if (status)
- printk(KERN_ERR
- "%s: lv1_gpu_context_attribute FLIP failed: %d\n",
- __func__, status);
+ dev_err(dev, "%s: lv1_gpu_context_attribute FLIP failed: %d\n",
+ __func__, status);
#endif
- return 0;
}
+static int ps3fb_sync(struct fb_info *info, u32 frame)
+{
+ struct ps3fb_par *par = info->par;
+ int i, error = 0;
+ u32 ddr_line_length, xdr_line_length;
+ u64 ddr_base, xdr_base;
+
+ acquire_console_sem();
+
+ if (frame > par->num_frames - 1) {
+ dev_dbg(info->device, "%s: invalid frame number (%u)\n",
+ __func__, frame);
+ error = -EINVAL;
+ goto out;
+ }
+
+ i = par->res_index;
+ xdr_line_length = info->fix.line_length;
+ ddr_line_length = ps3fb_res[i].xres * BPP;
+ xdr_base = frame * info->var.yres_virtual * xdr_line_length;
+ ddr_base = frame * ps3fb_res[i].yres * ddr_line_length;
+
+ ps3fb_sync_image(info->device, ddr_base + par->full_offset,
+ ddr_base + par->fb_offset, xdr_base + par->pan_offset,
+ par->width, par->height, ddr_line_length,
+ xdr_line_length);
+
+out:
+ release_console_sem();
+ return error;
+}
static int ps3fb_open(struct fb_info *info, int user)
{
@@ -445,7 +478,7 @@ static int ps3fb_release(struct fb_info *info, int user)
if (atomic_dec_and_test(&ps3fb.f_count)) {
if (atomic_read(&ps3fb.ext_flip)) {
atomic_set(&ps3fb.ext_flip, 0);
- ps3fb_sync(0); /* single buffer */
+ ps3fb_sync(info, 0); /* single buffer */
}
}
return 0;
@@ -461,39 +494,37 @@ static int ps3fb_release(struct fb_info *info, int user)
static int ps3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
- u32 line_length;
+ u32 xdr_line_length, ddr_line_length;
int mode;
- int i;
- DPRINTK("var->xres:%u info->var.xres:%u\n", var->xres, info->var.xres);
- DPRINTK("var->yres:%u info->var.yres:%u\n", var->yres, info->var.yres);
+ dev_dbg(info->device, "var->xres:%u info->var.xres:%u\n", var->xres,
+ info->var.xres);
+ dev_dbg(info->device, "var->yres:%u info->var.yres:%u\n", var->yres,
+ info->var.yres);
/* FIXME For now we do exact matches only */
- mode = ps3fb_find_mode(var, &line_length);
+ mode = ps3fb_find_mode(var, &ddr_line_length, &xdr_line_length);
if (!mode)
return -EINVAL;
- /*
- * FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
- * as FB_VMODE_SMOOTH_XPAN is only used internally
- */
+ /* Virtual screen */
+ if (var->xres_virtual < var->xres)
+ var->xres_virtual = var->xres;
+ if (var->yres_virtual < var->yres)
+ var->yres_virtual = var->yres;
- if (var->vmode & FB_VMODE_CONUPDATE) {
- var->vmode |= FB_VMODE_YWRAP;
- var->xoffset = info->var.xoffset;
- var->yoffset = info->var.yoffset;
+ if (var->xres_virtual > xdr_line_length / BPP) {
+ dev_dbg(info->device,
+ "Horizontal virtual screen size too large\n");
+ return -EINVAL;
}
- /* Virtual screen and panning are not supported */
- if (var->xres_virtual > var->xres || var->yres_virtual > var->yres ||
- var->xoffset || var->yoffset) {
- DPRINTK("Virtual screen and panning are not supported\n");
+ if (var->xoffset + var->xres > var->xres_virtual ||
+ var->yoffset + var->yres > var->yres_virtual) {
+ dev_dbg(info->device, "panning out-of-range\n");
return -EINVAL;
}
- var->xres_virtual = var->xres;
- var->yres_virtual = var->yres;
-
/* We support ARGB8888 only */
if (var->bits_per_pixel > 32 || var->grayscale ||
var->red.offset > 16 || var->green.offset > 8 ||
@@ -502,7 +533,7 @@ static int ps3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
var->blue.length > 8 || var->transp.length > 8 ||
var->red.msb_right || var->green.msb_right ||
var->blue.msb_right || var->transp.msb_right || var->nonstd) {
- DPRINTK("We support ARGB8888 only\n");
+ dev_dbg(info->device, "We support ARGB8888 only\n");
return -EINVAL;
}
@@ -522,14 +553,13 @@ static int ps3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
/* Rotation is not supported */
if (var->rotate) {
- DPRINTK("Rotation is not supported\n");
+ dev_dbg(info->device, "Rotation is not supported\n");
return -EINVAL;
}
/* Memory limit */
- i = ps3fb_get_res_table(var->xres, var->yres);
- if (ps3fb_res[i].xres*ps3fb_res[i].yres*BPP > ps3fb_videomemory.size) {
- DPRINTK("Not enough memory\n");
+ if (var->yres_virtual * xdr_line_length > ps3fb.xdr_size) {
+ dev_dbg(info->device, "Not enough memory\n");
return -ENOMEM;
}
@@ -545,36 +575,69 @@ static int ps3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
static int ps3fb_set_par(struct fb_info *info)
{
- unsigned int mode;
+ struct ps3fb_par *par = info->par;
+ unsigned int mode, ddr_line_length, xdr_line_length, lines, maxlines;
int i;
unsigned long offset;
- static int first = 1;
+ u64 dst;
- DPRINTK("xres:%d xv:%d yres:%d yv:%d clock:%d\n",
+ dev_dbg(info->device, "xres:%d xv:%d yres:%d yv:%d clock:%d\n",
info->var.xres, info->var.xres_virtual,
info->var.yres, info->var.yres_virtual, info->var.pixclock);
- i = ps3fb_get_res_table(info->var.xres, info->var.yres);
- ps3fb.res_index = i;
- mode = ps3fb_find_mode(&info->var, &info->fix.line_length);
+ mode = ps3fb_find_mode(&info->var, &ddr_line_length, &xdr_line_length);
if (!mode)
return -EINVAL;
- offset = FB_OFF(i) + VP_OFF(i);
- info->fix.smem_len = ps3fb_videomemory.size - offset;
- info->screen_base = (char __iomem *)ps3fb.xdr_ea + offset;
- memset(ps3fb.xdr_ea, 0, ps3fb_videomemory.size);
+ i = ps3fb_get_res_table(info->var.xres, info->var.yres, mode);
+ par->res_index = i;
+
+ info->fix.smem_start = virt_to_abs(ps3fb.xdr_ea);
+ info->fix.smem_len = ps3fb.xdr_size;
+ info->fix.xpanstep = info->var.xres_virtual > info->var.xres ? 1 : 0;
+ info->fix.ypanstep = info->var.yres_virtual > info->var.yres ? 1 : 0;
+ info->fix.line_length = xdr_line_length;
+
+ info->screen_base = (char __iomem *)ps3fb.xdr_ea;
- ps3fb.num_frames = ps3fb_videomemory.size/
- (ps3fb_res[i].xres*ps3fb_res[i].yres*BPP);
+ par->num_frames = ps3fb.xdr_size /
+ max(ps3fb_res[i].yres * ddr_line_length,
+ info->var.yres_virtual * xdr_line_length);
/* Keep the special bits we cannot set using fb_var_screeninfo */
- ps3fb_mode = (ps3fb_mode & ~PS3AV_MODE_MASK) | mode;
+ par->new_mode_id = (par->new_mode_id & ~PS3AV_MODE_MASK) | mode;
+
+ par->width = info->var.xres;
+ par->height = info->var.yres;
+ offset = VP_OFF(i);
+ par->fb_offset = GPU_ALIGN_UP(offset);
+ par->full_offset = par->fb_offset - offset;
+ par->pan_offset = info->var.yoffset * xdr_line_length +
+ info->var.xoffset * BPP;
+
+ if (par->new_mode_id != par->mode_id) {
+ if (ps3av_set_video_mode(par->new_mode_id)) {
+ par->new_mode_id = par->mode_id;
+ return -EINVAL;
+ }
+ par->mode_id = par->new_mode_id;
+ }
- if (ps3av_set_video_mode(ps3fb_mode, first))
- return -EINVAL;
+ /* Clear XDR frame buffer memory */
+ memset(ps3fb.xdr_ea, 0, ps3fb.xdr_size);
+
+ /* Clear DDR frame buffer memory */
+ lines = ps3fb_res[i].yres * par->num_frames;
+ if (par->full_offset)
+ lines++;
+ maxlines = ps3fb.xdr_size / ddr_line_length;
+ for (dst = 0; lines; dst += maxlines * ddr_line_length) {
+ unsigned int l = min(lines, maxlines);
+ ps3fb_sync_image(info->device, 0, dst, 0, ps3fb_res[i].xres, l,
+ ddr_line_length, ddr_line_length);
+ lines -= l;
+ }
- first = 0;
return 0;
}
@@ -601,6 +664,16 @@ static int ps3fb_setcolreg(unsigned int regno, unsigned int red,
return 0;
}
+static int ps3fb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct ps3fb_par *par = info->par;
+
+ par->pan_offset = var->yoffset * info->fix.line_length +
+ var->xoffset * BPP;
+ return 0;
+}
+
/*
* As we have a virtual frame buffer, we need our own mmap function
*/
@@ -608,24 +681,19 @@ static int ps3fb_setcolreg(unsigned int regno, unsigned int red,
static int ps3fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
unsigned long size, offset;
- int i;
-
- i = ps3fb_get_res_table(info->var.xres, info->var.yres);
- if (i == -1)
- return -EINVAL;
size = vma->vm_end - vma->vm_start;
offset = vma->vm_pgoff << PAGE_SHIFT;
if (offset + size > info->fix.smem_len)
return -EINVAL;
- offset += info->fix.smem_start + FB_OFF(i) + VP_OFF(i);
+ offset += info->fix.smem_start;
if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT,
size, vma->vm_page_prot))
return -EAGAIN;
- printk(KERN_DEBUG "ps3fb: mmap framebuffer P(%lx)->V(%lx)\n", offset,
- vma->vm_start);
+ dev_dbg(info->device, "ps3fb: mmap framebuffer P(%lx)->V(%lx)\n",
+ offset, vma->vm_start);
return 0;
}
@@ -637,7 +705,7 @@ static int ps3fb_blank(int blank, struct fb_info *info)
{
int retval;
- DPRINTK("%s: blank:%d\n", __func__, blank);
+ dev_dbg(info->device, "%s: blank:%d\n", __func__, blank);
switch (blank) {
case FB_BLANK_POWERDOWN:
case FB_BLANK_HSYNC_SUSPEND:
@@ -659,12 +727,12 @@ static int ps3fb_blank(int blank, struct fb_info *info)
static int ps3fb_get_vblank(struct fb_vblank *vblank)
{
- memset(vblank, 0, sizeof(&vblank));
+ memset(vblank, 0, sizeof(*vblank));
vblank->flags = FB_VBLANK_HAVE_VSYNC;
return 0;
}
-int ps3fb_wait_for_vsync(u32 crtc)
+static int ps3fb_wait_for_vsync(u32 crtc)
{
int ret;
u64 count;
@@ -679,9 +747,7 @@ int ps3fb_wait_for_vsync(u32 crtc)
return 0;
}
-EXPORT_SYMBOL_GPL(ps3fb_wait_for_vsync);
-
-void ps3fb_flip_ctl(int on, void *data)
+static void ps3fb_flip_ctl(int on, void *data)
{
struct ps3fb_priv *priv = data;
if (on)
@@ -699,14 +765,14 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd,
unsigned long arg)
{
void __user *argp = (void __user *)arg;
- u32 val, old_mode;
+ u32 val;
int retval = -EFAULT;
switch (cmd) {
case FBIOGET_VBLANK:
{
struct fb_vblank vblank;
- DPRINTK("FBIOGET_VBLANK:\n");
+ dev_dbg(info->device, "FBIOGET_VBLANK:\n");
retval = ps3fb_get_vblank(&vblank);
if (retval)
break;
@@ -719,7 +785,7 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd,
case FBIO_WAITFORVSYNC:
{
u32 crt;
- DPRINTK("FBIO_WAITFORVSYNC:\n");
+ dev_dbg(info->device, "FBIO_WAITFORVSYNC:\n");
if (get_user(crt, (u32 __user *) arg))
break;
@@ -729,6 +795,7 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd,
case PS3FB_IOCTL_SETMODE:
{
+ struct ps3fb_par *par = info->par;
const struct fb_videomode *mode;
struct fb_var_screeninfo var;
@@ -736,15 +803,13 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd,
break;
if (!(val & PS3AV_MODE_MASK)) {
- u32 id = ps3av_get_auto_mode(0);
+ u32 id = ps3av_get_auto_mode();
if (id > 0)
val = (val & ~PS3AV_MODE_MASK) | id;
}
- DPRINTK("PS3FB_IOCTL_SETMODE:%x\n", val);
+ dev_dbg(info->device, "PS3FB_IOCTL_SETMODE:%x\n", val);
retval = -EINVAL;
- old_mode = ps3fb_mode;
- ps3fb_mode = val;
- mode = ps3fb_default_mode();
+ mode = ps3fb_default_mode(val);
if (mode) {
var = info->var;
fb_videomode_to_var(&var, mode);
@@ -752,45 +817,44 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd,
info->flags |= FBINFO_MISC_USEREVENT;
/* Force, in case only special bits changed */
var.activate |= FB_ACTIVATE_FORCE;
+ par->new_mode_id = val;
retval = fb_set_var(info, &var);
info->flags &= ~FBINFO_MISC_USEREVENT;
release_console_sem();
}
- if (retval)
- ps3fb_mode = old_mode;
break;
}
case PS3FB_IOCTL_GETMODE:
val = ps3av_get_mode();
- DPRINTK("PS3FB_IOCTL_GETMODE:%x\n", val);
+ dev_dbg(info->device, "PS3FB_IOCTL_GETMODE:%x\n", val);
if (!copy_to_user(argp, &val, sizeof(val)))
retval = 0;
break;
case PS3FB_IOCTL_SCREENINFO:
{
+ struct ps3fb_par *par = info->par;
struct ps3fb_ioctl_res res;
- int i = ps3fb.res_index;
- DPRINTK("PS3FB_IOCTL_SCREENINFO:\n");
- res.xres = ps3fb_res[i].xres;
- res.yres = ps3fb_res[i].yres;
- res.xoff = ps3fb_res[i].xoff;
- res.yoff = ps3fb_res[i].yoff;
- res.num_frames = ps3fb.num_frames;
+ dev_dbg(info->device, "PS3FB_IOCTL_SCREENINFO:\n");
+ res.xres = info->fix.line_length / BPP;
+ res.yres = info->var.yres_virtual;
+ res.xoff = (res.xres - info->var.xres) / 2;
+ res.yoff = (res.yres - info->var.yres) / 2;
+ res.num_frames = par->num_frames;
if (!copy_to_user(argp, &res, sizeof(res)))
retval = 0;
break;
}
case PS3FB_IOCTL_ON:
- DPRINTK("PS3FB_IOCTL_ON:\n");
+ dev_dbg(info->device, "PS3FB_IOCTL_ON:\n");
atomic_inc(&ps3fb.ext_flip);
retval = 0;
break;
case PS3FB_IOCTL_OFF:
- DPRINTK("PS3FB_IOCTL_OFF:\n");
+ dev_dbg(info->device, "PS3FB_IOCTL_OFF:\n");
atomic_dec_if_positive(&ps3fb.ext_flip);
retval = 0;
break;
@@ -799,8 +863,8 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd,
if (copy_from_user(&val, argp, sizeof(val)))
break;
- DPRINTK("PS3FB_IOCTL_FSEL:%d\n", val);
- retval = ps3fb_sync(val);
+ dev_dbg(info->device, "PS3FB_IOCTL_FSEL:%d\n", val);
+ retval = ps3fb_sync(info, val);
break;
default:
@@ -812,13 +876,15 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd,
static int ps3fbd(void *arg)
{
+ struct fb_info *info = arg;
+
set_freezable();
while (!kthread_should_stop()) {
try_to_freeze();
set_current_state(TASK_INTERRUPTIBLE);
if (ps3fb.is_kicked) {
ps3fb.is_kicked = 0;
- ps3fb_sync(0); /* single buffer */
+ ps3fb_sync(info, 0); /* single buffer */
}
schedule();
}
@@ -827,14 +893,15 @@ static int ps3fbd(void *arg)
static irqreturn_t ps3fb_vsync_interrupt(int irq, void *ptr)
{
+ struct device *dev = ptr;
u64 v1;
int status;
struct display_head *head = &ps3fb.dinfo->display_head[1];
status = lv1_gpu_context_intr(ps3fb.context_handle, &v1);
if (status) {
- printk(KERN_ERR "%s: lv1_gpu_context_intr failed: %d\n",
- __func__, status);
+ dev_err(dev, "%s: lv1_gpu_context_intr failed: %d\n", __func__,
+ status);
return IRQ_NONE;
}
@@ -854,35 +921,35 @@ static irqreturn_t ps3fb_vsync_interrupt(int irq, void *ptr)
static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo,
- struct ps3_system_bus_device *dev)
+ struct device *dev)
{
int error;
- DPRINTK("version_driver:%x\n", dinfo->version_driver);
- DPRINTK("irq outlet:%x\n", dinfo->irq.irq_outlet);
- DPRINTK("version_gpu:%x memory_size:%x ch:%x core_freq:%d mem_freq:%d\n",
+ dev_dbg(dev, "version_driver:%x\n", dinfo->version_driver);
+ dev_dbg(dev, "irq outlet:%x\n", dinfo->irq.irq_outlet);
+ dev_dbg(dev,
+ "version_gpu: %x memory_size: %x ch: %x core_freq: %d "
+ "mem_freq:%d\n",
dinfo->version_gpu, dinfo->memory_size, dinfo->hardware_channel,
dinfo->nvcore_frequency/1000000, dinfo->memory_frequency/1000000);
if (dinfo->version_driver != GPU_DRIVER_INFO_VERSION) {
- printk(KERN_ERR "%s: version_driver err:%x\n", __func__,
- dinfo->version_driver);
+ dev_err(dev, "%s: version_driver err:%x\n", __func__,
+ dinfo->version_driver);
return -EINVAL;
}
error = ps3_irq_plug_setup(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet,
&ps3fb.irq_no);
if (error) {
- printk(KERN_ERR "%s: ps3_alloc_irq failed %d\n", __func__,
- error);
+ dev_err(dev, "%s: ps3_alloc_irq failed %d\n", __func__, error);
return error;
}
error = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt, IRQF_DISABLED,
DEVICE_NAME, dev);
if (error) {
- printk(KERN_ERR "%s: request_irq failed %d\n", __func__,
- error);
+ dev_err(dev, "%s: request_irq failed %d\n", __func__, error);
ps3_irq_plug_destroy(ps3fb.irq_no);
return error;
}
@@ -892,29 +959,31 @@ static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo,
return 0;
}
-static int ps3fb_xdr_settings(u64 xdr_lpar)
+static int ps3fb_xdr_settings(u64 xdr_lpar, struct device *dev)
{
int status;
status = lv1_gpu_context_iomap(ps3fb.context_handle, GPU_IOIF,
xdr_lpar, ps3fb_videomemory.size, 0);
if (status) {
- printk(KERN_ERR "%s: lv1_gpu_context_iomap failed: %d\n",
- __func__, status);
+ dev_err(dev, "%s: lv1_gpu_context_iomap failed: %d\n",
+ __func__, status);
return -ENXIO;
}
- DPRINTK("video:%p xdr_ea:%p ioif:%lx lpar:%lx phys:%lx size:%lx\n",
+ dev_dbg(dev,
+ "video:%p xdr_ea:%p ioif:%lx lpar:%lx phys:%lx size:%lx\n",
ps3fb_videomemory.address, ps3fb.xdr_ea, GPU_IOIF, xdr_lpar,
virt_to_abs(ps3fb.xdr_ea), ps3fb_videomemory.size);
status = lv1_gpu_context_attribute(ps3fb.context_handle,
L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP,
- xdr_lpar, ps3fb_videomemory.size,
- GPU_IOIF, 0);
+ xdr_lpar + ps3fb.xdr_size,
+ GPU_CMD_BUF_SIZE,
+ GPU_IOIF + ps3fb.xdr_size, 0);
if (status) {
- printk(KERN_ERR
- "%s: lv1_gpu_context_attribute FB_SETUP failed: %d\n",
- __func__, status);
+ dev_err(dev,
+ "%s: lv1_gpu_context_attribute FB_SETUP failed: %d\n",
+ __func__, status);
return -ENXIO;
}
return 0;
@@ -928,6 +997,7 @@ static struct fb_ops ps3fb_ops = {
.fb_check_var = ps3fb_check_var,
.fb_set_par = ps3fb_set_par,
.fb_setcolreg = ps3fb_setcolreg,
+ .fb_pan_display = ps3fb_pan_display,
.fb_fillrect = sys_fillrect,
.fb_copyarea = sys_copyarea,
.fb_imageblit = sys_imageblit,
@@ -944,7 +1014,7 @@ static struct fb_fix_screeninfo ps3fb_fix __initdata = {
.accel = FB_ACCEL_NONE,
};
-static int ps3fb_set_sync(void)
+static int ps3fb_set_sync(struct device *dev)
{
int status;
@@ -953,8 +1023,10 @@ static int ps3fb_set_sync(void)
L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
0, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
if (status) {
- printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_SYNC "
- "failed: %d\n", __func__, status);
+ dev_err(dev,
+ "%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: "
+ "%d\n",
+ __func__, status);
return -1;
}
#endif
@@ -964,8 +1036,10 @@ static int ps3fb_set_sync(void)
1, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
if (status) {
- printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_MODE "
- "failed: %d\n", __func__, status);
+ dev_err(dev,
+ "%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: "
+ "%d\n",
+ __func__, status);
return -1;
}
#endif
@@ -975,6 +1049,7 @@ static int ps3fb_set_sync(void)
static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
{
struct fb_info *info;
+ struct ps3fb_par *par;
int retval = -ENOMEM;
u32 xres, yres;
u64 ddr_lpar = 0;
@@ -983,98 +1058,106 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
u64 lpar_reports = 0;
u64 lpar_reports_size = 0;
u64 xdr_lpar;
- int status;
- unsigned long offset;
+ int status, res_index;
struct task_struct *task;
status = ps3_open_hv_device(dev);
if (status) {
- printk(KERN_ERR "%s: ps3_open_hv_device failed\n", __func__);
+ dev_err(&dev->core, "%s: ps3_open_hv_device failed\n",
+ __func__);
goto err;
}
if (!ps3fb_mode)
ps3fb_mode = ps3av_get_mode();
- DPRINTK("ps3av_mode:%d\n", ps3fb_mode);
+ dev_dbg(&dev->core, "ps3av_mode:%d\n", ps3fb_mode);
if (ps3fb_mode > 0 &&
!ps3av_video_mode2res(ps3fb_mode, &xres, &yres)) {
- ps3fb.res_index = ps3fb_get_res_table(xres, yres);
- DPRINTK("res_index:%d\n", ps3fb.res_index);
+ res_index = ps3fb_get_res_table(xres, yres, ps3fb_mode);
+ dev_dbg(&dev->core, "res_index:%d\n", res_index);
} else
- ps3fb.res_index = GPU_RES_INDEX;
+ res_index = GPU_RES_INDEX;
atomic_set(&ps3fb.f_count, -1); /* fbcon opens ps3fb */
atomic_set(&ps3fb.ext_flip, 0); /* for flip with vsync */
init_waitqueue_head(&ps3fb.wait_vsync);
- ps3fb.num_frames = 1;
- ps3fb_set_sync();
+ ps3fb_set_sync(&dev->core);
/* get gpu context handle */
status = lv1_gpu_memory_allocate(DDR_SIZE, 0, 0, 0, 0,
&ps3fb.memory_handle, &ddr_lpar);
if (status) {
- printk(KERN_ERR "%s: lv1_gpu_memory_allocate failed: %d\n",
- __func__, status);
+ dev_err(&dev->core, "%s: lv1_gpu_memory_allocate failed: %d\n",
+ __func__, status);
goto err;
}
- DPRINTK("ddr:lpar:0x%lx\n", ddr_lpar);
+ dev_dbg(&dev->core, "ddr:lpar:0x%lx\n", ddr_lpar);
status = lv1_gpu_context_allocate(ps3fb.memory_handle, 0,
&ps3fb.context_handle,
&lpar_dma_control, &lpar_driver_info,
&lpar_reports, &lpar_reports_size);
if (status) {
- printk(KERN_ERR "%s: lv1_gpu_context_attribute failed: %d\n",
- __func__, status);
+ dev_err(&dev->core,
+ "%s: lv1_gpu_context_attribute failed: %d\n", __func__,
+ status);
goto err_gpu_memory_free;
}
/* vsync interrupt */
ps3fb.dinfo = ioremap(lpar_driver_info, 128 * 1024);
if (!ps3fb.dinfo) {
- printk(KERN_ERR "%s: ioremap failed\n", __func__);
+ dev_err(&dev->core, "%s: ioremap failed\n", __func__);
goto err_gpu_context_free;
}
- retval = ps3fb_vsync_settings(ps3fb.dinfo, dev);
+ retval = ps3fb_vsync_settings(ps3fb.dinfo, &dev->core);
if (retval)
goto err_iounmap_dinfo;
- /* xdr frame buffer */
+ /* XDR frame buffer */
ps3fb.xdr_ea = ps3fb_videomemory.address;
xdr_lpar = ps3_mm_phys_to_lpar(__pa(ps3fb.xdr_ea));
- retval = ps3fb_xdr_settings(xdr_lpar);
+
+ /* Clear memory to prevent kernel info leakage into userspace */
+ memset(ps3fb.xdr_ea, 0, ps3fb_videomemory.size);
+
+ /* The GPU command buffer is at the end of video memory */
+ ps3fb.xdr_size = ps3fb_videomemory.size - GPU_CMD_BUF_SIZE;
+
+ retval = ps3fb_xdr_settings(xdr_lpar, &dev->core);
if (retval)
goto err_free_irq;
- /*
- * ps3fb must clear memory to prevent kernel info
- * leakage into userspace
- */
- memset(ps3fb.xdr_ea, 0, ps3fb_videomemory.size);
- info = framebuffer_alloc(sizeof(u32) * 16, &dev->core);
+ info = framebuffer_alloc(sizeof(struct ps3fb_par), &dev->core);
if (!info)
goto err_free_irq;
- offset = FB_OFF(ps3fb.res_index) + VP_OFF(ps3fb.res_index);
- info->screen_base = (char __iomem *)ps3fb.xdr_ea + offset;
+ par = info->par;
+ par->mode_id = ~ps3fb_mode; /* != ps3fb_mode, to trigger change */
+ par->new_mode_id = ps3fb_mode;
+ par->res_index = res_index;
+ par->num_frames = 1;
+
+ info->screen_base = (char __iomem *)ps3fb.xdr_ea;
info->fbops = &ps3fb_ops;
info->fix = ps3fb_fix;
info->fix.smem_start = virt_to_abs(ps3fb.xdr_ea);
- info->fix.smem_len = ps3fb_videomemory.size - offset;
- info->pseudo_palette = info->par;
- info->par = NULL;
- info->flags = FBINFO_DEFAULT | FBINFO_READS_FAST;
+ info->fix.smem_len = ps3fb.xdr_size;
+ info->pseudo_palette = par->pseudo_palette;
+ info->flags = FBINFO_DEFAULT | FBINFO_READS_FAST |
+ FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN;
retval = fb_alloc_cmap(&info->cmap, 256, 0);
if (retval < 0)
goto err_framebuffer_release;
if (!fb_find_mode(&info->var, info, mode_option, ps3fb_modedb,
- ARRAY_SIZE(ps3fb_modedb), ps3fb_default_mode(), 32)) {
+ ARRAY_SIZE(ps3fb_modedb),
+ ps3fb_default_mode(par->new_mode_id), 32)) {
retval = -EINVAL;
goto err_fb_dealloc;
}
@@ -1088,9 +1171,9 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
dev->core.driver_data = info;
- printk(KERN_INFO
- "fb%d: PS3 frame buffer device, using %ld KiB of video memory\n",
- info->node, ps3fb_videomemory.size >> 10);
+ dev_info(info->device, "%s %s, using %lu KiB of video memory\n",
+ dev_driver_string(info->dev), info->dev->bus_id,
+ ps3fb.xdr_size >> 10);
task = kthread_run(ps3fbd, info, DEVICE_NAME);
if (IS_ERR(task)) {
@@ -1127,7 +1210,7 @@ static int ps3fb_shutdown(struct ps3_system_bus_device *dev)
int status;
struct fb_info *info = dev->core.driver_data;
- DPRINTK(" -> %s:%d\n", __func__, __LINE__);
+ dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
ps3fb_flip_ctl(0, &ps3fb); /* flip off */
ps3fb.dinfo->irq.mask = 0;
@@ -1152,14 +1235,16 @@ static int ps3fb_shutdown(struct ps3_system_bus_device *dev)
status = lv1_gpu_context_free(ps3fb.context_handle);
if (status)
- DPRINTK("lv1_gpu_context_free failed: %d\n", status);
+ dev_dbg(&dev->core, "lv1_gpu_context_free failed: %d\n",
+ status);
status = lv1_gpu_memory_free(ps3fb.memory_handle);
if (status)
- DPRINTK("lv1_gpu_memory_free failed: %d\n", status);
+ dev_dbg(&dev->core, "lv1_gpu_memory_free failed: %d\n",
+ status);
ps3_close_hv_device(dev);
- DPRINTK(" <- %s:%d\n", __func__, __LINE__);
+ dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
return 0;
}
@@ -1212,9 +1297,9 @@ static int __init ps3fb_init(void)
static void __exit ps3fb_exit(void)
{
- DPRINTK(" -> %s:%d\n", __func__, __LINE__);
+ pr_debug(" -> %s:%d\n", __func__, __LINE__);
ps3_system_bus_driver_unregister(&ps3fb_driver);
- DPRINTK(" <- %s:%d\n", __func__, __LINE__);
+ pr_debug(" <- %s:%d\n", __func__, __LINE__);
}
module_init(ps3fb_init);
diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c
index 06805c9b237b..6a3d0b574897 100644
--- a/drivers/video/pvr2fb.c
+++ b/drivers/video/pvr2fb.c
@@ -72,7 +72,7 @@
#endif
#ifdef CONFIG_SH_STORE_QUEUES
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <asm/cpu/sq.h>
#endif
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index a280a52f8efe..10f912df2dad 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -37,11 +37,12 @@
#include <linux/cpufreq.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+#include <linux/err.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/irq.h>
-#include <asm/uaccess.h>
#include <asm/div64.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/bitfield.h>
@@ -106,20 +107,38 @@ pxafb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue,
u_int trans, struct fb_info *info)
{
struct pxafb_info *fbi = (struct pxafb_info *)info;
- u_int val, ret = 1;
+ u_int val;
- if (regno < fbi->palette_size) {
- if (fbi->fb.var.grayscale) {
- val = ((blue >> 8) & 0x00ff);
- } else {
- val = ((red >> 0) & 0xf800);
- val |= ((green >> 5) & 0x07e0);
- val |= ((blue >> 11) & 0x001f);
- }
+ if (regno >= fbi->palette_size)
+ return 1;
+
+ if (fbi->fb.var.grayscale) {
+ fbi->palette_cpu[regno] = ((blue >> 8) & 0x00ff);
+ return 0;
+ }
+
+ switch (fbi->lccr4 & LCCR4_PAL_FOR_MASK) {
+ case LCCR4_PAL_FOR_0:
+ val = ((red >> 0) & 0xf800);
+ val |= ((green >> 5) & 0x07e0);
+ val |= ((blue >> 11) & 0x001f);
fbi->palette_cpu[regno] = val;
- ret = 0;
+ break;
+ case LCCR4_PAL_FOR_1:
+ val = ((red << 8) & 0x00f80000);
+ val |= ((green >> 0) & 0x0000fc00);
+ val |= ((blue >> 8) & 0x000000f8);
+ ((u32*)(fbi->palette_cpu))[regno] = val;
+ break;
+ case LCCR4_PAL_FOR_2:
+ val = ((red << 8) & 0x00fc0000);
+ val |= ((green >> 0) & 0x0000fc00);
+ val |= ((blue >> 8) & 0x000000fc);
+ ((u32*)(fbi->palette_cpu))[regno] = val;
+ break;
}
- return ret;
+
+ return 0;
}
static int
@@ -361,7 +380,10 @@ static int pxafb_set_par(struct fb_info *info)
else
fbi->palette_size = var->bits_per_pixel == 1 ? 4 : 1 << var->bits_per_pixel;
- palette_mem_size = fbi->palette_size * sizeof(u16);
+ if ((fbi->lccr4 & LCCR4_PAL_FOR_MASK) == LCCR4_PAL_FOR_0)
+ palette_mem_size = fbi->palette_size * sizeof(u16);
+ else
+ palette_mem_size = fbi->palette_size * sizeof(u32);
pr_debug("pxafb: palette_mem_size = 0x%08lx\n", palette_mem_size);
@@ -506,15 +528,15 @@ static struct fb_ops pxafb_ops = {
*
* Factoring the 10^4 and 10^-12 out gives 10^-8 == 1 / 100000000 as used below.
*/
-static inline unsigned int get_pcd(unsigned int pixclock)
+static inline unsigned int get_pcd(struct pxafb_info *fbi, unsigned int pixclock)
{
unsigned long long pcd;
/* FIXME: Need to take into account Double Pixel Clock mode
- * (DPC) bit? or perhaps set it based on the various clock
- * speeds */
-
- pcd = (unsigned long long)get_lcdclk_frequency_10khz() * pixclock;
+ * (DPC) bit? or perhaps set it based on the various clock
+ * speeds */
+ pcd = (unsigned long long)(clk_get_rate(fbi->clk) / 10000);
+ pcd *= pixclock;
do_div(pcd, 100000000 * 2);
/* no need for this, since we should subtract 1 anyway. they cancel */
/* pcd += 1; */ /* make up for integer math truncations */
@@ -523,19 +545,21 @@ static inline unsigned int get_pcd(unsigned int pixclock)
/*
* Some touchscreens need hsync information from the video driver to
- * function correctly. We export it here.
+ * function correctly. We export it here. Note that 'hsync_time' and
+ * the value returned from pxafb_get_hsync_time() is the *reciprocal*
+ * of the hsync period in seconds.
*/
static inline void set_hsync_time(struct pxafb_info *fbi, unsigned int pcd)
{
- unsigned long long htime;
+ unsigned long htime;
if ((pcd == 0) || (fbi->fb.var.hsync_len == 0)) {
fbi->hsync_time=0;
return;
}
- htime = (unsigned long long)get_lcdclk_frequency_10khz() * 10000;
- do_div(htime, pcd * fbi->fb.var.hsync_len);
+ htime = clk_get_rate(fbi->clk) / (pcd * fbi->fb.var.hsync_len);
+
fbi->hsync_time = htime;
}
@@ -560,7 +584,7 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *
{
struct pxafb_lcd_reg new_regs;
u_long flags;
- u_int lines_per_panel, pcd = get_pcd(var->pixclock);
+ u_int lines_per_panel, pcd = get_pcd(fbi, var->pixclock);
pr_debug("pxafb: Configuring PXA LCD\n");
@@ -676,7 +700,13 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *
fbi->dmadesc_palette_cpu->fsadr = fbi->palette_dma;
fbi->dmadesc_palette_cpu->fidr = 0;
- fbi->dmadesc_palette_cpu->ldcmd = (fbi->palette_size * 2) | LDCMD_PAL;
+ if ((fbi->lccr4 & LCCR4_PAL_FOR_MASK) == LCCR4_PAL_FOR_0)
+ fbi->dmadesc_palette_cpu->ldcmd = fbi->palette_size *
+ sizeof(u16);
+ else
+ fbi->dmadesc_palette_cpu->ldcmd = fbi->palette_size *
+ sizeof(u32);
+ fbi->dmadesc_palette_cpu->ldcmd |= LDCMD_PAL;
if (var->bits_per_pixel == 16) {
/* palette shouldn't be loaded in true-color mode */
@@ -715,6 +745,8 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *
fbi->reg_lccr1 = new_regs.lccr1;
fbi->reg_lccr2 = new_regs.lccr2;
fbi->reg_lccr3 = new_regs.lccr3;
+ fbi->reg_lccr4 = LCCR4 & (~LCCR4_PAL_FOR_MASK);
+ fbi->reg_lccr4 |= (fbi->lccr4 & LCCR4_PAL_FOR_MASK);
set_hsync_time(fbi, pcd);
local_irq_restore(flags);
@@ -803,7 +835,7 @@ static void pxafb_enable_controller(struct pxafb_info *fbi)
pr_debug("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3);
/* enable LCD controller clock */
- pxa_set_cken(CKEN_LCD, 1);
+ clk_enable(fbi->clk);
/* Sequence from 11.7.10 */
LCCR3 = fbi->reg_lccr3;
@@ -821,6 +853,7 @@ static void pxafb_enable_controller(struct pxafb_info *fbi)
pr_debug("LCCR1 0x%08x\n", (unsigned int) LCCR1);
pr_debug("LCCR2 0x%08x\n", (unsigned int) LCCR2);
pr_debug("LCCR3 0x%08x\n", (unsigned int) LCCR3);
+ pr_debug("LCCR4 0x%08x\n", (unsigned int) LCCR4);
}
static void pxafb_disable_controller(struct pxafb_info *fbi)
@@ -840,7 +873,7 @@ static void pxafb_disable_controller(struct pxafb_info *fbi)
remove_wait_queue(&fbi->ctrlr_wait, &wait);
/* disable LCD controller clock */
- pxa_set_cken(CKEN_LCD, 0);
+ clk_disable(fbi->clk);
}
/*
@@ -994,7 +1027,7 @@ pxafb_freq_transition(struct notifier_block *nb, unsigned long val, void *data)
break;
case CPUFREQ_POSTCHANGE:
- pcd = get_pcd(fbi->fb.var.pixclock);
+ pcd = get_pcd(fbi, fbi->fb.var.pixclock);
set_hsync_time(fbi, pcd);
fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd);
set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE);
@@ -1090,10 +1123,13 @@ static int __init pxafb_map_video_memory(struct pxafb_info *fbi)
* dma_writecombine_mmap)
*/
fbi->fb.fix.smem_start = fbi->screen_dma;
-
fbi->palette_size = fbi->fb.var.bits_per_pixel == 8 ? 256 : 16;
- palette_mem_size = fbi->palette_size * sizeof(u16);
+ if ((fbi->lccr4 & LCCR4_PAL_FOR_MASK) == LCCR4_PAL_FOR_0)
+ palette_mem_size = fbi->palette_size * sizeof(u16);
+ else
+ palette_mem_size = fbi->palette_size * sizeof(u32);
+
pr_debug("pxafb: palette_mem_size = 0x%08lx\n", palette_mem_size);
fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size);
@@ -1119,6 +1155,12 @@ static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev)
memset(fbi, 0, sizeof(struct pxafb_info));
fbi->dev = dev;
+ fbi->clk = clk_get(dev, "LCDCLK");
+ if (IS_ERR(fbi->clk)) {
+ kfree(fbi);
+ return NULL;
+ }
+
strcpy(fbi->fb.fix.id, PXA_NAME);
fbi->fb.fix.type = FB_TYPE_PACKED_PIXELS;
@@ -1150,6 +1192,7 @@ static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev)
fbi->lccr0 = inf->lccr0;
fbi->lccr3 = inf->lccr3;
+ fbi->lccr4 = inf->lccr4;
fbi->state = C_STARTUP;
fbi->task_state = (u_char)-1;
diff --git a/drivers/video/pxafb.h b/drivers/video/pxafb.h
index 7499a1c4bf79..d920b8a14c35 100644
--- a/drivers/video/pxafb.h
+++ b/drivers/video/pxafb.h
@@ -40,6 +40,7 @@ struct pxafb_dma_descriptor {
struct pxafb_info {
struct fb_info fb;
struct device *dev;
+ struct clk *clk;
/*
* These are the addresses we mapped
@@ -70,6 +71,7 @@ struct pxafb_info {
u_int lccr0;
u_int lccr3;
+ u_int lccr4;
u_int cmap_inverse:1,
cmap_static:1,
unused:30;
@@ -78,6 +80,7 @@ struct pxafb_info {
u_int reg_lccr1;
u_int reg_lccr2;
u_int reg_lccr3;
+ u_int reg_lccr4;
unsigned long hsync_time;
diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c
index a5333c190789..b829dc7c5edf 100644
--- a/drivers/video/s1d13xxxfb.c
+++ b/drivers/video/s1d13xxxfb.c
@@ -540,7 +540,7 @@ s1d13xxxfb_probe(struct platform_device *pdev)
int ret = 0;
u8 revision;
- dbg("probe called: device is %p\n", dev);
+ dbg("probe called: device is %p\n", pdev);
printk(KERN_INFO "Epson S1D13XXX FB Driver\n");
@@ -753,8 +753,11 @@ static struct platform_driver s1d13xxxfb_driver = {
static int __init
s1d13xxxfb_init(void)
{
+
+#ifndef MODULE
if (fb_get_options("s1d13xxxfb", NULL))
return -ENODEV;
+#endif
return platform_driver_register(&s1d13xxxfb_driver);
}
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
index 8a4c6470d799..5857ccf5f6b1 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/s3c2410fb.c
@@ -20,7 +20,7 @@
*
* 2004-12-04: Arnaud Patard <arnaud.patard@rtp-net.org>
* - Added the possibility to set on or off the
- * debugging mesaages
+ * debugging messages
* - Replaced 0 and 1 by on or off when reading the
* /sys files
*
@@ -31,8 +31,8 @@
* - add pixel clock divisor control
*
* 2004-11-11: Arnaud Patard <arnaud.patard@rtp-net.org>
- * - Removed the use of currcon as it no more exist
- * - Added LCD power sysfs interface
+ * - Removed the use of currcon as it no more exists
+ * - Added LCD power sysfs interface
*
* 2004-11-03: Ben Dooks <ben-linux@fluff.org>
* - minor cleanups
@@ -49,14 +49,14 @@
* - Suppress command line options
*
* 2004-09-15: Arnaud Patard <arnaud.patard@rtp-net.org>
- * - code cleanup
+ * - code cleanup
*
* 2004-09-07: Arnaud Patard <arnaud.patard@rtp-net.org>
- * - Renamed from h1940fb.c to s3c2410fb.c
- * - Add support for different devices
- * - Backlight support
+ * - Renamed from h1940fb.c to s3c2410fb.c
+ * - Add support for different devices
+ * - Backlight support
*
- * 2004-09-05: Herbert Pötzl <herbert@13thfloor.at>
+ * 2004-09-05: Herbert Pötzl <herbert@13thfloor.at>
* - added clock (de-)allocation code
* - added fixem fbmem option
*
@@ -64,7 +64,7 @@
* - code cleanup
* - added a forgotten return in h1940fb_init
*
- * 2004-07-19: Herbert Pötzl <herbert@13thfloor.at>
+ * 2004-07-19: Herbert Pötzl <herbert@13thfloor.at>
* - code cleanup and extended debugging
*
* 2004-07-15: Arnaud Patard <arnaud.patard@rtp-net.org>
@@ -82,13 +82,10 @@
#include <linux/init.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
-#include <linux/workqueue.h>
-#include <linux/wait.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <asm/io.h>
-#include <asm/uaccess.h>
#include <asm/div64.h>
#include <asm/mach/map.h>
@@ -102,14 +99,11 @@
#include "s3c2410fb.h"
-
-static struct s3c2410fb_mach_info *mach_info;
-
/* Debugging stuff */
#ifdef CONFIG_FB_S3C2410_DEBUG
-static int debug = 1;
+static int debug = 1;
#else
-static int debug = 0;
+static int debug = 0;
#endif
#define dprintk(msg...) if (debug) { printk(KERN_DEBUG "s3c2410fb: " msg); }
@@ -119,48 +113,48 @@ static int debug = 0;
/* s3c2410fb_set_lcdaddr
*
* initialise lcd controller address pointers
-*/
-
-static void s3c2410fb_set_lcdaddr(struct s3c2410fb_info *fbi)
+ */
+static void s3c2410fb_set_lcdaddr(struct fb_info *info)
{
- struct fb_var_screeninfo *var = &fbi->fb->var;
unsigned long saddr1, saddr2, saddr3;
+ struct s3c2410fb_info *fbi = info->par;
+ void __iomem *regs = fbi->io;
- saddr1 = fbi->fb->fix.smem_start >> 1;
- saddr2 = fbi->fb->fix.smem_start;
- saddr2 += (var->xres * var->yres * var->bits_per_pixel)/8;
- saddr2>>= 1;
+ saddr1 = info->fix.smem_start >> 1;
+ saddr2 = info->fix.smem_start;
+ saddr2 += info->fix.line_length * info->var.yres;
+ saddr2 >>= 1;
- saddr3 = S3C2410_OFFSIZE(0) | S3C2410_PAGEWIDTH((var->xres * var->bits_per_pixel / 16) & 0x3ff);
+ saddr3 = S3C2410_OFFSIZE(0) |
+ S3C2410_PAGEWIDTH((info->fix.line_length / 2) & 0x3ff);
dprintk("LCDSADDR1 = 0x%08lx\n", saddr1);
dprintk("LCDSADDR2 = 0x%08lx\n", saddr2);
dprintk("LCDSADDR3 = 0x%08lx\n", saddr3);
- writel(saddr1, S3C2410_LCDSADDR1);
- writel(saddr2, S3C2410_LCDSADDR2);
- writel(saddr3, S3C2410_LCDSADDR3);
+ writel(saddr1, regs + S3C2410_LCDSADDR1);
+ writel(saddr2, regs + S3C2410_LCDSADDR2);
+ writel(saddr3, regs + S3C2410_LCDSADDR3);
}
/* s3c2410fb_calc_pixclk()
*
* calculate divisor for clk->pixclk
-*/
-
+ */
static unsigned int s3c2410fb_calc_pixclk(struct s3c2410fb_info *fbi,
unsigned long pixclk)
{
unsigned long clk = clk_get_rate(fbi->clk);
unsigned long long div;
- /* pixclk is in picoseoncds, our clock is in Hz
+ /* pixclk is in picoseconds, our clock is in Hz
*
* Hz -> picoseconds is / 10^-12
*/
div = (unsigned long long)clk * pixclk;
- do_div(div,1000000UL);
- do_div(div,1000000UL);
+ div >>= 12; /* div / 2^12 */
+ do_div(div, 625 * 625UL * 625); /* div / 5^12 */
dprintk("pixclk %ld, divisor is %ld\n", pixclk, (long)div);
return div;
@@ -176,246 +170,278 @@ static int s3c2410fb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
struct s3c2410fb_info *fbi = info->par;
+ struct s3c2410fb_mach_info *mach_info = fbi->dev->platform_data;
+ struct s3c2410fb_display *display = NULL;
+ struct s3c2410fb_display *default_display = mach_info->displays +
+ mach_info->default_display;
+ int type = default_display->type;
+ unsigned i;
dprintk("check_var(var=%p, info=%p)\n", var, info);
/* validate x/y resolution */
+ /* choose default mode if possible */
+ if (var->yres == default_display->yres &&
+ var->xres == default_display->xres &&
+ var->bits_per_pixel == default_display->bpp)
+ display = default_display;
+ else
+ for (i = 0; i < mach_info->num_displays; i++)
+ if (type == mach_info->displays[i].type &&
+ var->yres == mach_info->displays[i].yres &&
+ var->xres == mach_info->displays[i].xres &&
+ var->bits_per_pixel == mach_info->displays[i].bpp) {
+ display = mach_info->displays + i;
+ break;
+ }
- if (var->yres > fbi->mach_info->yres.max)
- var->yres = fbi->mach_info->yres.max;
- else if (var->yres < fbi->mach_info->yres.min)
- var->yres = fbi->mach_info->yres.min;
-
- if (var->xres > fbi->mach_info->xres.max)
- var->yres = fbi->mach_info->xres.max;
- else if (var->xres < fbi->mach_info->xres.min)
- var->xres = fbi->mach_info->xres.min;
-
- /* validate bpp */
-
- if (var->bits_per_pixel > fbi->mach_info->bpp.max)
- var->bits_per_pixel = fbi->mach_info->bpp.max;
- else if (var->bits_per_pixel < fbi->mach_info->bpp.min)
- var->bits_per_pixel = fbi->mach_info->bpp.min;
+ if (!display) {
+ dprintk("wrong resolution or depth %dx%d at %d bpp\n",
+ var->xres, var->yres, var->bits_per_pixel);
+ return -EINVAL;
+ }
+ /* it is always the size as the display */
+ var->xres_virtual = display->xres;
+ var->yres_virtual = display->yres;
+ var->height = display->height;
+ var->width = display->width;
+
+ /* copy lcd settings */
+ var->pixclock = display->pixclock;
+ var->left_margin = display->left_margin;
+ var->right_margin = display->right_margin;
+ var->upper_margin = display->upper_margin;
+ var->lower_margin = display->lower_margin;
+ var->vsync_len = display->vsync_len;
+ var->hsync_len = display->hsync_len;
+
+ fbi->regs.lcdcon5 = display->lcdcon5;
+ /* set display type */
+ fbi->regs.lcdcon1 = display->type;
+
+ var->transp.offset = 0;
+ var->transp.length = 0;
/* set r/g/b positions */
switch (var->bits_per_pixel) {
- case 1:
- case 2:
- case 4:
- var->red.offset = 0;
- var->red.length = var->bits_per_pixel;
- var->green = var->red;
- var->blue = var->red;
- var->transp.offset = 0;
- var->transp.length = 0;
- break;
- case 8:
- if ( fbi->mach_info->type != S3C2410_LCDCON1_TFT ) {
- /* 8 bpp 332 */
- var->red.length = 3;
- var->red.offset = 5;
- var->green.length = 3;
- var->green.offset = 2;
- var->blue.length = 2;
- var->blue.offset = 0;
- var->transp.length = 0;
- } else {
- var->red.offset = 0;
- var->red.length = var->bits_per_pixel;
- var->green = var->red;
- var->blue = var->red;
- var->transp.offset = 0;
- var->transp.length = 0;
- }
- break;
- case 12:
- /* 12 bpp 444 */
- var->red.length = 4;
- var->red.offset = 8;
- var->green.length = 4;
- var->green.offset = 4;
- var->blue.length = 4;
+ case 1:
+ case 2:
+ case 4:
+ var->red.offset = 0;
+ var->red.length = var->bits_per_pixel;
+ var->green = var->red;
+ var->blue = var->red;
+ break;
+ case 8:
+ if (display->type != S3C2410_LCDCON1_TFT) {
+ /* 8 bpp 332 */
+ var->red.length = 3;
+ var->red.offset = 5;
+ var->green.length = 3;
+ var->green.offset = 2;
+ var->blue.length = 2;
var->blue.offset = 0;
- var->transp.length = 0;
- break;
-
- default:
- case 16:
- if (fbi->regs.lcdcon5 & S3C2410_LCDCON5_FRM565 ) {
- /* 16 bpp, 565 format */
- var->red.offset = 11;
- var->green.offset = 5;
- var->blue.offset = 0;
- var->red.length = 5;
- var->green.length = 6;
- var->blue.length = 5;
- var->transp.length = 0;
- } else {
- /* 16 bpp, 5551 format */
- var->red.offset = 11;
- var->green.offset = 6;
- var->blue.offset = 1;
- var->red.length = 5;
- var->green.length = 5;
- var->blue.length = 5;
- var->transp.length = 0;
- }
- break;
- case 24:
- /* 24 bpp 888 */
+ } else {
+ var->red.offset = 0;
var->red.length = 8;
- var->red.offset = 16;
- var->green.length = 8;
- var->green.offset = 8;
- var->blue.length = 8;
- var->blue.offset = 0;
- var->transp.length = 0;
- break;
-
+ var->green = var->red;
+ var->blue = var->red;
+ }
+ break;
+ case 12:
+ /* 12 bpp 444 */
+ var->red.length = 4;
+ var->red.offset = 8;
+ var->green.length = 4;
+ var->green.offset = 4;
+ var->blue.length = 4;
+ var->blue.offset = 0;
+ break;
+ default:
+ case 16:
+ if (display->lcdcon5 & S3C2410_LCDCON5_FRM565) {
+ /* 16 bpp, 565 format */
+ var->red.offset = 11;
+ var->green.offset = 5;
+ var->blue.offset = 0;
+ var->red.length = 5;
+ var->green.length = 6;
+ var->blue.length = 5;
+ } else {
+ /* 16 bpp, 5551 format */
+ var->red.offset = 11;
+ var->green.offset = 6;
+ var->blue.offset = 1;
+ var->red.length = 5;
+ var->green.length = 5;
+ var->blue.length = 5;
+ }
+ break;
+ case 32:
+ /* 24 bpp 888 and 8 dummy */
+ var->red.length = 8;
+ var->red.offset = 16;
+ var->green.length = 8;
+ var->green.offset = 8;
+ var->blue.length = 8;
+ var->blue.offset = 0;
+ break;
}
return 0;
}
-
-/* s3c2410fb_activate_var
+/* s3c2410fb_calculate_stn_lcd_regs
*
- * activate (set) the controller from the given framebuffer
- * information
-*/
-
-static void s3c2410fb_activate_var(struct s3c2410fb_info *fbi,
- struct fb_var_screeninfo *var)
+ * calculate register values from var settings
+ */
+static void s3c2410fb_calculate_stn_lcd_regs(const struct fb_info *info,
+ struct s3c2410fb_hw *regs)
{
- int hs;
+ const struct s3c2410fb_info *fbi = info->par;
+ const struct fb_var_screeninfo *var = &info->var;
+ int type = regs->lcdcon1 & ~S3C2410_LCDCON1_TFT;
+ int hs = var->xres >> 2;
+ unsigned wdly = (var->left_margin >> 4) - 1;
+ unsigned wlh = (var->hsync_len >> 4) - 1;
- fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_MODEMASK;
- fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_TFT;
+ if (type != S3C2410_LCDCON1_STN4)
+ hs >>= 1;
- dprintk("%s: var->xres = %d\n", __FUNCTION__, var->xres);
- dprintk("%s: var->yres = %d\n", __FUNCTION__, var->yres);
- dprintk("%s: var->bpp = %d\n", __FUNCTION__, var->bits_per_pixel);
+ switch (var->bits_per_pixel) {
+ case 1:
+ regs->lcdcon1 |= S3C2410_LCDCON1_STN1BPP;
+ break;
+ case 2:
+ regs->lcdcon1 |= S3C2410_LCDCON1_STN2GREY;
+ break;
+ case 4:
+ regs->lcdcon1 |= S3C2410_LCDCON1_STN4GREY;
+ break;
+ case 8:
+ regs->lcdcon1 |= S3C2410_LCDCON1_STN8BPP;
+ hs *= 3;
+ break;
+ case 12:
+ regs->lcdcon1 |= S3C2410_LCDCON1_STN12BPP;
+ hs *= 3;
+ break;
- fbi->regs.lcdcon1 |= fbi->mach_info->type;
-
- if (fbi->mach_info->type == S3C2410_LCDCON1_TFT)
- switch (var->bits_per_pixel) {
- case 1:
- fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT1BPP;
- break;
- case 2:
- fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT2BPP;
- break;
- case 4:
- fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT4BPP;
- break;
- case 8:
- fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT8BPP;
- break;
- case 16:
- fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT16BPP;
- break;
-
- default:
- /* invalid pixel depth */
- dev_err(fbi->dev, "invalid bpp %d\n", var->bits_per_pixel);
- }
- else
- switch (var->bits_per_pixel) {
- case 1:
- fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN1BPP;
- break;
- case 2:
- fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN2GREY;
- break;
- case 4:
- fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN4GREY;
- break;
- case 8:
- fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN8BPP;
- break;
- case 12:
- fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN12BPP;
- break;
-
- default:
- /* invalid pixel depth */
- dev_err(fbi->dev, "invalid bpp %d\n", var->bits_per_pixel);
- }
+ default:
+ /* invalid pixel depth */
+ dev_err(fbi->dev, "invalid bpp %d\n",
+ var->bits_per_pixel);
+ }
+ /* update X/Y info */
+ dprintk("setting horz: lft=%d, rt=%d, sync=%d\n",
+ var->left_margin, var->right_margin, var->hsync_len);
- /* check to see if we need to update sync/borders */
+ regs->lcdcon2 = S3C2410_LCDCON2_LINEVAL(var->yres - 1);
- if (!fbi->mach_info->fixed_syncs) {
- dprintk("setting vert: up=%d, low=%d, sync=%d\n",
- var->upper_margin, var->lower_margin,
- var->vsync_len);
+ if (wdly > 3)
+ wdly = 3;
- dprintk("setting horz: lft=%d, rt=%d, sync=%d\n",
- var->left_margin, var->right_margin,
- var->hsync_len);
+ if (wlh > 3)
+ wlh = 3;
- fbi->regs.lcdcon2 =
- S3C2410_LCDCON2_VBPD(var->upper_margin - 1) |
- S3C2410_LCDCON2_VFPD(var->lower_margin - 1) |
- S3C2410_LCDCON2_VSPW(var->vsync_len - 1);
+ regs->lcdcon3 = S3C2410_LCDCON3_WDLY(wdly) |
+ S3C2410_LCDCON3_LINEBLANK(var->right_margin / 8) |
+ S3C2410_LCDCON3_HOZVAL(hs - 1);
- fbi->regs.lcdcon3 =
- S3C2410_LCDCON3_HBPD(var->right_margin - 1) |
- S3C2410_LCDCON3_HFPD(var->left_margin - 1);
+ regs->lcdcon4 = S3C2410_LCDCON4_WLH(wlh);
+}
- fbi->regs.lcdcon4 &= ~S3C2410_LCDCON4_HSPW(0xff);
- fbi->regs.lcdcon4 |= S3C2410_LCDCON4_HSPW(var->hsync_len - 1);
- }
+/* s3c2410fb_calculate_tft_lcd_regs
+ *
+ * calculate register values from var settings
+ */
+static void s3c2410fb_calculate_tft_lcd_regs(const struct fb_info *info,
+ struct s3c2410fb_hw *regs)
+{
+ const struct s3c2410fb_info *fbi = info->par;
+ const struct fb_var_screeninfo *var = &info->var;
+ switch (var->bits_per_pixel) {
+ case 1:
+ regs->lcdcon1 |= S3C2410_LCDCON1_TFT1BPP;
+ break;
+ case 2:
+ regs->lcdcon1 |= S3C2410_LCDCON1_TFT2BPP;
+ break;
+ case 4:
+ regs->lcdcon1 |= S3C2410_LCDCON1_TFT4BPP;
+ break;
+ case 8:
+ regs->lcdcon1 |= S3C2410_LCDCON1_TFT8BPP;
+ regs->lcdcon5 |= S3C2410_LCDCON5_BSWP |
+ S3C2410_LCDCON5_FRM565;
+ regs->lcdcon5 &= ~S3C2410_LCDCON5_HWSWP;
+ break;
+ case 16:
+ regs->lcdcon1 |= S3C2410_LCDCON1_TFT16BPP;
+ regs->lcdcon5 &= ~S3C2410_LCDCON5_BSWP;
+ regs->lcdcon5 |= S3C2410_LCDCON5_HWSWP;
+ break;
+ case 32:
+ regs->lcdcon1 |= S3C2410_LCDCON1_TFT24BPP;
+ regs->lcdcon5 &= ~(S3C2410_LCDCON5_BSWP |
+ S3C2410_LCDCON5_HWSWP |
+ S3C2410_LCDCON5_BPP24BL);
+ break;
+ default:
+ /* invalid pixel depth */
+ dev_err(fbi->dev, "invalid bpp %d\n",
+ var->bits_per_pixel);
+ }
/* update X/Y info */
+ dprintk("setting vert: up=%d, low=%d, sync=%d\n",
+ var->upper_margin, var->lower_margin, var->vsync_len);
- fbi->regs.lcdcon2 &= ~S3C2410_LCDCON2_LINEVAL(0x3ff);
- fbi->regs.lcdcon2 |= S3C2410_LCDCON2_LINEVAL(var->yres - 1);
-
- switch(fbi->mach_info->type) {
- case S3C2410_LCDCON1_DSCAN4:
- case S3C2410_LCDCON1_STN8:
- hs = var->xres / 8;
- break;
- case S3C2410_LCDCON1_STN4:
- hs = var->xres / 4;
- break;
- default:
- case S3C2410_LCDCON1_TFT:
- hs = var->xres;
- break;
-
- }
+ dprintk("setting horz: lft=%d, rt=%d, sync=%d\n",
+ var->left_margin, var->right_margin, var->hsync_len);
- /* Special cases : STN color displays */
- if ( ((fbi->regs.lcdcon1 & S3C2410_LCDCON1_MODEMASK) == S3C2410_LCDCON1_STN8BPP) \
- || ((fbi->regs.lcdcon1 & S3C2410_LCDCON1_MODEMASK) == S3C2410_LCDCON1_STN12BPP) ) {
- hs = hs * 3;
- }
+ regs->lcdcon2 = S3C2410_LCDCON2_LINEVAL(var->yres - 1) |
+ S3C2410_LCDCON2_VBPD(var->upper_margin - 1) |
+ S3C2410_LCDCON2_VFPD(var->lower_margin - 1) |
+ S3C2410_LCDCON2_VSPW(var->vsync_len - 1);
+ regs->lcdcon3 = S3C2410_LCDCON3_HBPD(var->right_margin - 1) |
+ S3C2410_LCDCON3_HFPD(var->left_margin - 1) |
+ S3C2410_LCDCON3_HOZVAL(var->xres - 1);
- fbi->regs.lcdcon3 &= ~S3C2410_LCDCON3_HOZVAL(0x7ff);
- fbi->regs.lcdcon3 |= S3C2410_LCDCON3_HOZVAL(hs - 1);
+ regs->lcdcon4 = S3C2410_LCDCON4_HSPW(var->hsync_len - 1);
+}
- if (var->pixclock > 0) {
- int clkdiv = s3c2410fb_calc_pixclk(fbi, var->pixclock);
+/* s3c2410fb_activate_var
+ *
+ * activate (set) the controller from the given framebuffer
+ * information
+ */
+static void s3c2410fb_activate_var(struct fb_info *info)
+{
+ struct s3c2410fb_info *fbi = info->par;
+ void __iomem *regs = fbi->io;
+ int type = fbi->regs.lcdcon1 & S3C2410_LCDCON1_TFT;
+ struct fb_var_screeninfo *var = &info->var;
+ int clkdiv = s3c2410fb_calc_pixclk(fbi, var->pixclock) / 2;
- if (fbi->mach_info->type == S3C2410_LCDCON1_TFT) {
- clkdiv = (clkdiv / 2) -1;
- if (clkdiv < 0)
- clkdiv = 0;
- }
- else {
- clkdiv = (clkdiv / 2);
- if (clkdiv < 2)
- clkdiv = 2;
- }
+ dprintk("%s: var->xres = %d\n", __FUNCTION__, var->xres);
+ dprintk("%s: var->yres = %d\n", __FUNCTION__, var->yres);
+ dprintk("%s: var->bpp = %d\n", __FUNCTION__, var->bits_per_pixel);
- fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_CLKVAL(0x3ff);
- fbi->regs.lcdcon1 |= S3C2410_LCDCON1_CLKVAL(clkdiv);
+ if (type == S3C2410_LCDCON1_TFT) {
+ s3c2410fb_calculate_tft_lcd_regs(info, &fbi->regs);
+ --clkdiv;
+ if (clkdiv < 0)
+ clkdiv = 0;
+ } else {
+ s3c2410fb_calculate_stn_lcd_regs(info, &fbi->regs);
+ if (clkdiv < 2)
+ clkdiv = 2;
}
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_CLKVAL(clkdiv);
+
/* write new registers */
dprintk("new register set:\n");
@@ -425,47 +451,48 @@ static void s3c2410fb_activate_var(struct s3c2410fb_info *fbi,
dprintk("lcdcon[4] = 0x%08lx\n", fbi->regs.lcdcon4);
dprintk("lcdcon[5] = 0x%08lx\n", fbi->regs.lcdcon5);
- writel(fbi->regs.lcdcon1 & ~S3C2410_LCDCON1_ENVID, S3C2410_LCDCON1);
- writel(fbi->regs.lcdcon2, S3C2410_LCDCON2);
- writel(fbi->regs.lcdcon3, S3C2410_LCDCON3);
- writel(fbi->regs.lcdcon4, S3C2410_LCDCON4);
- writel(fbi->regs.lcdcon5, S3C2410_LCDCON5);
+ writel(fbi->regs.lcdcon1 & ~S3C2410_LCDCON1_ENVID,
+ regs + S3C2410_LCDCON1);
+ writel(fbi->regs.lcdcon2, regs + S3C2410_LCDCON2);
+ writel(fbi->regs.lcdcon3, regs + S3C2410_LCDCON3);
+ writel(fbi->regs.lcdcon4, regs + S3C2410_LCDCON4);
+ writel(fbi->regs.lcdcon5, regs + S3C2410_LCDCON5);
/* set lcd address pointers */
- s3c2410fb_set_lcdaddr(fbi);
+ s3c2410fb_set_lcdaddr(info);
- writel(fbi->regs.lcdcon1, S3C2410_LCDCON1);
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_ENVID,
+ writel(fbi->regs.lcdcon1, regs + S3C2410_LCDCON1);
}
-
/*
- * s3c2410fb_set_par - Optional function. Alters the hardware state.
+ * s3c2410fb_set_par - Alters the hardware state.
* @info: frame buffer structure that represents a single frame buffer
*
*/
static int s3c2410fb_set_par(struct fb_info *info)
{
- struct s3c2410fb_info *fbi = info->par;
struct fb_var_screeninfo *var = &info->var;
- switch (var->bits_per_pixel)
- {
- case 16:
- fbi->fb->fix.visual = FB_VISUAL_TRUECOLOR;
- break;
- case 1:
- fbi->fb->fix.visual = FB_VISUAL_MONO01;
- break;
- default:
- fbi->fb->fix.visual = FB_VISUAL_PSEUDOCOLOR;
- break;
+ switch (var->bits_per_pixel) {
+ case 32:
+ case 16:
+ case 12:
+ info->fix.visual = FB_VISUAL_TRUECOLOR;
+ break;
+ case 1:
+ info->fix.visual = FB_VISUAL_MONO01;
+ break;
+ default:
+ info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+ break;
}
- fbi->fb->fix.line_length = (var->width*var->bits_per_pixel)/8;
+ info->fix.line_length = (var->width * var->bits_per_pixel) / 8;
/* activate this new configuration */
- s3c2410fb_activate_var(fbi, var);
+ s3c2410fb_activate_var(info);
return 0;
}
@@ -493,7 +520,8 @@ static void schedule_palette_update(struct s3c2410fb_info *fbi,
}
/* from pxafb.c */
-static inline unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf)
+static inline unsigned int chan_to_field(unsigned int chan,
+ struct fb_bitfield *bf)
{
chan &= 0xffff;
chan >>= 16 - bf->length;
@@ -505,20 +533,22 @@ static int s3c2410fb_setcolreg(unsigned regno,
unsigned transp, struct fb_info *info)
{
struct s3c2410fb_info *fbi = info->par;
+ void __iomem *regs = fbi->io;
unsigned int val;
- /* dprintk("setcol: regno=%d, rgb=%d,%d,%d\n", regno, red, green, blue); */
+ /* dprintk("setcol: regno=%d, rgb=%d,%d,%d\n",
+ regno, red, green, blue); */
- switch (fbi->fb->fix.visual) {
+ switch (info->fix.visual) {
case FB_VISUAL_TRUECOLOR:
- /* true-colour, use pseuo-palette */
+ /* true-colour, use pseudo-palette */
if (regno < 16) {
- u32 *pal = fbi->fb->pseudo_palette;
+ u32 *pal = info->pseudo_palette;
- val = chan_to_field(red, &fbi->fb->var.red);
- val |= chan_to_field(green, &fbi->fb->var.green);
- val |= chan_to_field(blue, &fbi->fb->var.blue);
+ val = chan_to_field(red, &info->var.red);
+ val |= chan_to_field(green, &info->var.green);
+ val |= chan_to_field(blue, &info->var.blue);
pal[regno] = val;
}
@@ -528,25 +558,24 @@ static int s3c2410fb_setcolreg(unsigned regno,
if (regno < 256) {
/* currently assume RGB 5-6-5 mode */
- val = ((red >> 0) & 0xf800);
- val |= ((green >> 5) & 0x07e0);
- val |= ((blue >> 11) & 0x001f);
+ val = (red >> 0) & 0xf800;
+ val |= (green >> 5) & 0x07e0;
+ val |= (blue >> 11) & 0x001f;
- writel(val, S3C2410_TFTPAL(regno));
+ writel(val, regs + S3C2410_TFTPAL(regno));
schedule_palette_update(fbi, regno, val);
}
break;
default:
- return 1; /* unknown type */
+ return 1; /* unknown type */
}
return 0;
}
-
-/**
+/*
* s3c2410fb_blank
* @blank_mode: the blank mode we want.
* @info: frame buffer structure that represents a single frame buffer
@@ -564,31 +593,31 @@ static int s3c2410fb_setcolreg(unsigned regno,
*/
static int s3c2410fb_blank(int blank_mode, struct fb_info *info)
{
- dprintk("blank(mode=%d, info=%p)\n", blank_mode, info);
+ struct s3c2410fb_info *fbi = info->par;
+ void __iomem *regs = fbi->io;
- if (mach_info == NULL)
- return -EINVAL;
+ dprintk("blank(mode=%d, info=%p)\n", blank_mode, info);
if (blank_mode == FB_BLANK_UNBLANK)
- writel(0x0, S3C2410_TPAL);
+ writel(0x0, regs + S3C2410_TPAL);
else {
dprintk("setting TPAL to output 0x000000\n");
- writel(S3C2410_TPAL_EN, S3C2410_TPAL);
+ writel(S3C2410_TPAL_EN, regs + S3C2410_TPAL);
}
return 0;
}
-static int s3c2410fb_debug_show(struct device *dev, struct device_attribute *attr, char *buf)
+static int s3c2410fb_debug_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
return snprintf(buf, PAGE_SIZE, "%s\n", debug ? "on" : "off");
}
-static int s3c2410fb_debug_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t len)
-{
- if (mach_info == NULL)
- return -EINVAL;
+static int s3c2410fb_debug_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
if (len < 1)
return -EINVAL;
@@ -607,10 +636,7 @@ static int s3c2410fb_debug_store(struct device *dev, struct device_attribute *at
return len;
}
-
-static DEVICE_ATTR(debug, 0666,
- s3c2410fb_debug_show,
- s3c2410fb_debug_store);
+static DEVICE_ATTR(debug, 0666, s3c2410fb_debug_show, s3c2410fb_debug_store);
static struct fb_ops s3c2410fb_ops = {
.owner = THIS_MODULE,
@@ -623,7 +649,6 @@ static struct fb_ops s3c2410fb_ops = {
.fb_imageblit = cfb_imageblit,
};
-
/*
* s3c2410fb_map_video_memory():
* Allocates the DRAM memory for the frame buffer. This buffer is
@@ -632,36 +657,38 @@ static struct fb_ops s3c2410fb_ops = {
* cache. Once this area is remapped, all virtual memory
* access to the video memory should occur at the new region.
*/
-static int __init s3c2410fb_map_video_memory(struct s3c2410fb_info *fbi)
+static int __init s3c2410fb_map_video_memory(struct fb_info *info)
{
- dprintk("map_video_memory(fbi=%p)\n", fbi);
+ struct s3c2410fb_info *fbi = info->par;
+ dma_addr_t map_dma;
+ unsigned map_size = PAGE_ALIGN(info->fix.smem_len);
- fbi->map_size = PAGE_ALIGN(fbi->fb->fix.smem_len + PAGE_SIZE);
- fbi->map_cpu = dma_alloc_writecombine(fbi->dev, fbi->map_size,
- &fbi->map_dma, GFP_KERNEL);
+ dprintk("map_video_memory(fbi=%p)\n", fbi);
- fbi->map_size = fbi->fb->fix.smem_len;
+ info->screen_base = dma_alloc_writecombine(fbi->dev, map_size,
+ &map_dma, GFP_KERNEL);
- if (fbi->map_cpu) {
+ if (info->screen_base) {
/* prevent initial garbage on screen */
dprintk("map_video_memory: clear %p:%08x\n",
- fbi->map_cpu, fbi->map_size);
- memset(fbi->map_cpu, 0xf0, fbi->map_size);
+ info->screen_base, map_size);
+ memset(info->screen_base, 0xf0, map_size);
- fbi->screen_dma = fbi->map_dma;
- fbi->fb->screen_base = fbi->map_cpu;
- fbi->fb->fix.smem_start = fbi->screen_dma;
+ info->fix.smem_start = map_dma;
- dprintk("map_video_memory: dma=%08x cpu=%p size=%08x\n",
- fbi->map_dma, fbi->map_cpu, fbi->fb->fix.smem_len);
+ dprintk("map_video_memory: dma=%08lx cpu=%p size=%08x\n",
+ info->fix.smem_start, info->screen_base, map_size);
}
- return fbi->map_cpu ? 0 : -ENOMEM;
+ return info->screen_base ? 0 : -ENOMEM;
}
-static inline void s3c2410fb_unmap_video_memory(struct s3c2410fb_info *fbi)
+static inline void s3c2410fb_unmap_video_memory(struct fb_info *info)
{
- dma_free_writecombine(fbi->dev,fbi->map_size,fbi->map_cpu, fbi->map_dma);
+ struct s3c2410fb_info *fbi = info->par;
+
+ dma_free_writecombine(fbi->dev, PAGE_ALIGN(info->fix.smem_len),
+ info->screen_base, info->fix.smem_start);
}
static inline void modify_gpio(void __iomem *reg,
@@ -673,13 +700,13 @@ static inline void modify_gpio(void __iomem *reg,
writel(tmp | set, reg);
}
-
/*
* s3c2410fb_init_registers - Initialise all LCD-related registers
*/
-
-static int s3c2410fb_init_registers(struct s3c2410fb_info *fbi)
+static int s3c2410fb_init_registers(struct fb_info *info)
{
+ struct s3c2410fb_info *fbi = info->par;
+ struct s3c2410fb_mach_info *mach_info = fbi->dev->platform_data;
unsigned long flags;
void __iomem *regs = fbi->io;
@@ -696,14 +723,6 @@ static int s3c2410fb_init_registers(struct s3c2410fb_info *fbi)
local_irq_restore(flags);
- writel(fbi->regs.lcdcon1, regs + S3C2410_LCDCON1);
- writel(fbi->regs.lcdcon2, regs + S3C2410_LCDCON2);
- writel(fbi->regs.lcdcon3, regs + S3C2410_LCDCON3);
- writel(fbi->regs.lcdcon4, regs + S3C2410_LCDCON4);
- writel(fbi->regs.lcdcon5, regs + S3C2410_LCDCON5);
-
- s3c2410fb_set_lcdaddr(fbi);
-
dprintk("LPCSEL = 0x%08lx\n", mach_info->lpcsel);
writel(mach_info->lpcsel, regs + S3C2410_LPCSEL);
@@ -712,22 +731,19 @@ static int s3c2410fb_init_registers(struct s3c2410fb_info *fbi)
/* ensure temporary palette disabled */
writel(0x00, regs + S3C2410_TPAL);
- /* Enable video by setting the ENVID bit to 1 */
- fbi->regs.lcdcon1 |= S3C2410_LCDCON1_ENVID;
- writel(fbi->regs.lcdcon1, regs + S3C2410_LCDCON1);
return 0;
}
static void s3c2410fb_write_palette(struct s3c2410fb_info *fbi)
{
unsigned int i;
- unsigned long ent;
void __iomem *regs = fbi->io;
fbi->palette_ready = 0;
for (i = 0; i < 256; i++) {
- if ((ent = fbi->palette_buffer[i]) == PALETTE_BUFF_CLEAR)
+ unsigned long ent = fbi->palette_buffer[i];
+ if (ent == PALETTE_BUFF_CLEAR)
continue;
writel(ent, regs + S3C2410_TFTPAL(i));
@@ -761,13 +777,14 @@ static irqreturn_t s3c2410fb_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static char driver_name[]="s3c2410fb";
+static char driver_name[] = "s3c2410fb";
static int __init s3c2410fb_probe(struct platform_device *pdev)
{
struct s3c2410fb_info *info;
- struct fb_info *fbinfo;
- struct s3c2410fb_hw *mregs;
+ struct s3c2410fb_display *display;
+ struct fb_info *fbinfo;
+ struct s3c2410fb_mach_info *mach_info;
struct resource *res;
int ret;
int irq;
@@ -777,11 +794,12 @@ static int __init s3c2410fb_probe(struct platform_device *pdev)
mach_info = pdev->dev.platform_data;
if (mach_info == NULL) {
- dev_err(&pdev->dev,"no platform data for lcd, cannot attach\n");
+ dev_err(&pdev->dev,
+ "no platform data for lcd, cannot attach\n");
return -EINVAL;
}
- mregs = &mach_info->regs;
+ display = mach_info->displays + mach_info->default_display;
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
@@ -790,22 +808,22 @@ static int __init s3c2410fb_probe(struct platform_device *pdev)
}
fbinfo = framebuffer_alloc(sizeof(struct s3c2410fb_info), &pdev->dev);
- if (!fbinfo) {
+ if (!fbinfo)
return -ENOMEM;
- }
+
+ platform_set_drvdata(pdev, fbinfo);
info = fbinfo->par;
- info->fb = fbinfo;
info->dev = &pdev->dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL) {
- dev_err(&pdev->dev, "failed to get memory registersn");
+ dev_err(&pdev->dev, "failed to get memory registers\n");
ret = -ENXIO;
goto dealloc_fb;
}
- size = (res->end - res->start)+1;
+ size = (res->end - res->start) + 1;
info->mem = request_mem_region(res->start, size, pdev->name);
if (info->mem == NULL) {
dev_err(&pdev->dev, "failed to get memory region\n");
@@ -820,21 +838,14 @@ static int __init s3c2410fb_probe(struct platform_device *pdev)
goto release_mem;
}
- platform_set_drvdata(pdev, fbinfo);
-
dprintk("devinit\n");
strcpy(fbinfo->fix.id, driver_name);
- memcpy(&info->regs, &mach_info->regs, sizeof(info->regs));
-
- /* Stop the video and unset ENVID if set */
- info->regs.lcdcon1 &= ~S3C2410_LCDCON1_ENVID;
+ /* Stop the video */
lcdcon1 = readl(info->io + S3C2410_LCDCON1);
writel(lcdcon1 & ~S3C2410_LCDCON1_ENVID, info->io + S3C2410_LCDCON1);
- info->mach_info = pdev->dev.platform_data;
-
fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
fbinfo->fix.type_aux = 0;
fbinfo->fix.xpanstep = 0;
@@ -844,8 +855,6 @@ static int __init s3c2410fb_probe(struct platform_device *pdev)
fbinfo->var.nonstd = 0;
fbinfo->var.activate = FB_ACTIVATE_NOW;
- fbinfo->var.height = mach_info->height;
- fbinfo->var.width = mach_info->width;
fbinfo->var.accel_flags = 0;
fbinfo->var.vmode = FB_VMODE_NONINTERLACED;
@@ -853,32 +862,6 @@ static int __init s3c2410fb_probe(struct platform_device *pdev)
fbinfo->flags = FBINFO_FLAG_DEFAULT;
fbinfo->pseudo_palette = &info->pseudo_pal;
- fbinfo->var.xres = mach_info->xres.defval;
- fbinfo->var.xres_virtual = mach_info->xres.defval;
- fbinfo->var.yres = mach_info->yres.defval;
- fbinfo->var.yres_virtual = mach_info->yres.defval;
- fbinfo->var.bits_per_pixel = mach_info->bpp.defval;
-
- fbinfo->var.upper_margin = S3C2410_LCDCON2_GET_VBPD(mregs->lcdcon2) + 1;
- fbinfo->var.lower_margin = S3C2410_LCDCON2_GET_VFPD(mregs->lcdcon2) + 1;
- fbinfo->var.vsync_len = S3C2410_LCDCON2_GET_VSPW(mregs->lcdcon2) + 1;
-
- fbinfo->var.left_margin = S3C2410_LCDCON3_GET_HFPD(mregs->lcdcon3) + 1;
- fbinfo->var.right_margin = S3C2410_LCDCON3_GET_HBPD(mregs->lcdcon3) + 1;
- fbinfo->var.hsync_len = S3C2410_LCDCON4_GET_HSPW(mregs->lcdcon4) + 1;
-
- fbinfo->var.red.offset = 11;
- fbinfo->var.green.offset = 5;
- fbinfo->var.blue.offset = 0;
- fbinfo->var.transp.offset = 0;
- fbinfo->var.red.length = 5;
- fbinfo->var.green.length = 6;
- fbinfo->var.blue.length = 5;
- fbinfo->var.transp.length = 0;
- fbinfo->fix.smem_len = mach_info->xres.max *
- mach_info->yres.max *
- mach_info->bpp.max / 8;
-
for (i = 0; i < 256; i++)
info->palette_buffer[i] = PALETTE_BUFF_CLEAR;
@@ -901,23 +884,39 @@ static int __init s3c2410fb_probe(struct platform_device *pdev)
msleep(1);
+ /* find maximum required memory size for display */
+ for (i = 0; i < mach_info->num_displays; i++) {
+ unsigned long smem_len = mach_info->displays[i].xres;
+
+ smem_len *= mach_info->displays[i].yres;
+ smem_len *= mach_info->displays[i].bpp;
+ smem_len >>= 3;
+ if (fbinfo->fix.smem_len < smem_len)
+ fbinfo->fix.smem_len = smem_len;
+ }
+
/* Initialize video memory */
- ret = s3c2410fb_map_video_memory(info);
+ ret = s3c2410fb_map_video_memory(fbinfo);
if (ret) {
- printk( KERN_ERR "Failed to allocate video RAM: %d\n", ret);
+ printk(KERN_ERR "Failed to allocate video RAM: %d\n", ret);
ret = -ENOMEM;
goto release_clock;
}
dprintk("got video memory\n");
- ret = s3c2410fb_init_registers(info);
+ fbinfo->var.xres = display->xres;
+ fbinfo->var.yres = display->yres;
+ fbinfo->var.bits_per_pixel = display->bpp;
+
+ s3c2410fb_init_registers(fbinfo);
- ret = s3c2410fb_check_var(&fbinfo->var, fbinfo);
+ s3c2410fb_check_var(&fbinfo->var, fbinfo);
ret = register_framebuffer(fbinfo);
if (ret < 0) {
- printk(KERN_ERR "Failed to register framebuffer device: %d\n", ret);
+ printk(KERN_ERR "Failed to register framebuffer device: %d\n",
+ ret);
goto free_video_memory;
}
@@ -930,18 +929,19 @@ static int __init s3c2410fb_probe(struct platform_device *pdev)
return 0;
free_video_memory:
- s3c2410fb_unmap_video_memory(info);
+ s3c2410fb_unmap_video_memory(fbinfo);
release_clock:
clk_disable(info->clk);
clk_put(info->clk);
release_irq:
- free_irq(irq,info);
+ free_irq(irq, info);
release_regs:
iounmap(info->io);
release_mem:
release_resource(info->mem);
kfree(info->mem);
dealloc_fb:
+ platform_set_drvdata(pdev, NULL);
framebuffer_release(fbinfo);
return ret;
}
@@ -949,8 +949,7 @@ dealloc_fb:
/* s3c2410fb_stop_lcd
*
* shutdown the lcd controller
-*/
-
+ */
static void s3c2410fb_stop_lcd(struct s3c2410fb_info *fbi)
{
unsigned long flags;
@@ -968,28 +967,33 @@ static void s3c2410fb_stop_lcd(struct s3c2410fb_info *fbi)
*/
static int s3c2410fb_remove(struct platform_device *pdev)
{
- struct fb_info *fbinfo = platform_get_drvdata(pdev);
+ struct fb_info *fbinfo = platform_get_drvdata(pdev);
struct s3c2410fb_info *info = fbinfo->par;
int irq;
+ unregister_framebuffer(fbinfo);
+
s3c2410fb_stop_lcd(info);
msleep(1);
- s3c2410fb_unmap_video_memory(info);
+ s3c2410fb_unmap_video_memory(fbinfo);
- if (info->clk) {
- clk_disable(info->clk);
- clk_put(info->clk);
- info->clk = NULL;
+ if (info->clk) {
+ clk_disable(info->clk);
+ clk_put(info->clk);
+ info->clk = NULL;
}
irq = platform_get_irq(pdev, 0);
- free_irq(irq,info);
+ free_irq(irq, info);
+
+ iounmap(info->io);
release_resource(info->mem);
kfree(info->mem);
- iounmap(info->io);
- unregister_framebuffer(fbinfo);
+
+ platform_set_drvdata(pdev, NULL);
+ framebuffer_release(fbinfo);
return 0;
}
@@ -997,7 +1001,6 @@ static int s3c2410fb_remove(struct platform_device *pdev)
#ifdef CONFIG_PM
/* suspend and resume support for the lcd controller */
-
static int s3c2410fb_suspend(struct platform_device *dev, pm_message_t state)
{
struct fb_info *fbinfo = platform_get_drvdata(dev);
@@ -1044,7 +1047,7 @@ static struct platform_driver s3c2410fb_driver = {
},
};
-int __devinit s3c2410fb_init(void)
+int __init s3c2410fb_init(void)
{
return platform_driver_register(&s3c2410fb_driver);
}
@@ -1054,10 +1057,10 @@ static void __exit s3c2410fb_cleanup(void)
platform_driver_unregister(&s3c2410fb_driver);
}
-
module_init(s3c2410fb_init);
module_exit(s3c2410fb_cleanup);
-MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>, Ben Dooks <ben-linux@fluff.org>");
+MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>, "
+ "Ben Dooks <ben-linux@fluff.org>");
MODULE_DESCRIPTION("Framebuffer driver for the s3c2410");
MODULE_LICENSE("GPL");
diff --git a/drivers/video/s3c2410fb.h b/drivers/video/s3c2410fb.h
index 17c7915b7acd..6ce5dc26c5f7 100644
--- a/drivers/video/s3c2410fb.h
+++ b/drivers/video/s3c2410fb.h
@@ -16,7 +16,7 @@
*
* 2004-09-07: Arnaud Patard <arnaud.patard@rtp-net.org>
* - Renamed from h1940fb.h to s3c2410fb.h
- * - Chenged h1940 to s3c2410
+ * - Changed h1940 to s3c2410
*
* 2004-07-15: Arnaud Patard <arnaud.patard@rtp-net.org>
* - First version
@@ -26,25 +26,14 @@
#define __S3C2410FB_H
struct s3c2410fb_info {
- struct fb_info *fb;
struct device *dev;
struct clk *clk;
struct resource *mem;
void __iomem *io;
- struct s3c2410fb_mach_info *mach_info;
-
- /* raw memory addresses */
- dma_addr_t map_dma; /* physical */
- u_char * map_cpu; /* virtual */
- u_int map_size;
-
struct s3c2410fb_hw regs;
- /* addresses of pieces placed in raw buffer */
- u_char * screen_cpu; /* virtual address of buffer */
- dma_addr_t screen_dma; /* physical address of buffer */
unsigned int palette_ready;
/* keep these registers in case we need to re-write palette */
diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c
index d11735895a01..7d53bc23b9c7 100644
--- a/drivers/video/s3fb.c
+++ b/drivers/video/s3fb.c
@@ -400,11 +400,17 @@ static int s3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
struct s3fb_info *par = info->par;
int rv, mem, step;
+ u16 m, n, r;
/* Find appropriate format */
rv = svga_match_format (s3fb_formats, var, NULL);
- if ((rv < 0) || ((par->chip == CHIP_988_VIRGE_VX) ? (rv == 7) : (rv == 6)))
- { /* 24bpp on VIRGE VX, 32bpp on others */
+
+ /* 32bpp mode is not supported on VIRGE VX,
+ 24bpp is not supported on others */
+ if ((par->chip == CHIP_988_VIRGE_VX) ? (rv == 7) : (rv == 6))
+ rv = -EINVAL;
+
+ if (rv < 0) {
printk(KERN_ERR "fb%d: unsupported mode requested\n", info->node);
return rv;
}
@@ -422,20 +428,26 @@ static int s3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
/* Check whether have enough memory */
mem = ((var->bits_per_pixel * var->xres_virtual) >> 3) * var->yres_virtual;
- if (mem > info->screen_size)
- {
+ if (mem > info->screen_size) {
printk(KERN_ERR "fb%d: not enough framebuffer memory (%d kB requested , %d kB available)\n",
info->node, mem >> 10, (unsigned int) (info->screen_size >> 10));
return -EINVAL;
}
rv = svga_check_timings (&s3_timing_regs, var, info->node);
- if (rv < 0)
- {
+ if (rv < 0) {
printk(KERN_ERR "fb%d: invalid timings requested\n", info->node);
return rv;
}
+ rv = svga_compute_pll(&s3_pll, PICOS2KHZ(var->pixclock), &m, &n, &r,
+ info->node);
+ if (rv < 0) {
+ printk(KERN_ERR "fb%d: invalid pixclock value requested\n",
+ info->node);
+ return rv;
+ }
+
return 0;
}
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index 5d2a4a4b731c..ab2b2110478b 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -178,7 +178,6 @@
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/mach-types.h>
-#include <asm/uaccess.h>
#include <asm/arch/assabet.h>
#include <asm/arch/shannon.h>
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
index b855f4a34afe..37b135d5d12e 100644
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -57,7 +57,6 @@
#include <asm/irq.h>
#include <asm/pgtable.h>
#include <asm/system.h>
-#include <asm/uaccess.h>
#ifdef CONFIG_MTRR
#include <asm/mtrr.h>
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index e8ccace01252..37bd24b8d83b 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -58,7 +58,7 @@
#include <linux/capability.h>
#include <linux/fs.h>
#include <linux/types.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <asm/io.h>
#ifdef CONFIG_MTRR
#include <asm/mtrr.h>
@@ -1248,7 +1248,6 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in
if(found_mode) {
ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
ivideo->sisfb_mode_idx, ivideo->currentvbflags);
- ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
} else {
ivideo->sisfb_mode_idx = -1;
}
@@ -1260,6 +1259,8 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in
return -EINVAL;
}
+ ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
+
if(sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx) == 0) {
ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
ivideo->refresh_rate = 60;
diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c
index 64779e70408f..62321458f71a 100644
--- a/drivers/video/skeletonfb.c
+++ b/drivers/video/skeletonfb.c
@@ -780,7 +780,7 @@ static int __devinit xxxfb_probe(struct pci_dev *dev,
*
* NOTE: This field is currently unused.
*/
- info->pixmap.scan_align = 32;
+ info->pixmap.access_align = 32;
/***************************** End optional stage ***************************/
/*
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
index c86df126f93a..1be95a68d696 100644
--- a/drivers/video/sm501fb.c
+++ b/drivers/video/sm501fb.c
@@ -28,6 +28,7 @@
#include <linux/wait.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/console.h>
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -62,6 +63,8 @@ struct sm501fb_info {
struct resource *regs_res; /* registers resource */
struct sm501_platdata_fb *pdata; /* our platform data */
+ unsigned long pm_crt_ctrl; /* pm: crt ctrl save */
+
int irq;
int swap_endian; /* set to swap rgb=>bgr */
void __iomem *regs; /* remapped registers */
@@ -774,6 +777,11 @@ static int sm501fb_set_par_pnl(struct fb_info *info)
writel(control, fbi->regs + SM501_DC_PANEL_CONTROL);
sm501fb_sync_regs(fbi);
+ /* ensure the panel interface is not tristated at this point */
+
+ sm501_modify_reg(fbi->dev->parent, SM501_SYSTEM_CONTROL,
+ 0, SM501_SYSCTRL_PANEL_TRISTATE);
+
/* power the panel up */
sm501fb_panel_power(fbi, 1);
return 0;
@@ -1687,19 +1695,25 @@ static int sm501fb_suspend_fb(struct sm501fb_info *info,
goto err_nocursor;
}
+ dev_dbg(info->dev, "suspending screen to %p\n", par->store_fb);
+ dev_dbg(info->dev, "suspending cursor to %p\n", par->store_cursor);
+
memcpy_fromio(par->store_fb, par->screen.k_addr, par->screen.size);
memcpy_fromio(par->store_cursor, par->cursor.k_addr, par->cursor.size);
-
/* blank the relevant interface to ensure unit power minimised */
(par->ops.fb_blank)(FB_BLANK_POWERDOWN, fbi);
+ acquire_console_sem();
+ fb_set_suspend(fbi, 1);
+ release_console_sem();
+
return 0;
err_nocursor:
vfree(par->store_fb);
+ par->store_fb = NULL;
return -ENOMEM;
-
}
static void sm501fb_resume_fb(struct sm501fb_info *info,
@@ -1717,8 +1731,20 @@ static void sm501fb_resume_fb(struct sm501fb_info *info,
/* restore the data */
- memcpy_toio(par->screen.k_addr, par->store_fb, par->screen.size);
- memcpy_toio(par->cursor.k_addr, par->store_cursor, par->cursor.size);
+ dev_dbg(info->dev, "restoring screen from %p\n", par->store_fb);
+ dev_dbg(info->dev, "restoring cursor from %p\n", par->store_cursor);
+
+ if (par->store_fb)
+ memcpy_toio(par->screen.k_addr, par->store_fb,
+ par->screen.size);
+
+ if (par->store_cursor)
+ memcpy_toio(par->cursor.k_addr, par->store_cursor,
+ par->cursor.size);
+
+ acquire_console_sem();
+ fb_set_suspend(fbi, 0);
+ release_console_sem();
vfree(par->store_fb);
vfree(par->store_cursor);
@@ -1731,6 +1757,9 @@ static int sm501fb_suspend(struct platform_device *pdev, pm_message_t state)
{
struct sm501fb_info *info = platform_get_drvdata(pdev);
+ /* store crt control to resume with */
+ info->pm_crt_ctrl = readl(info->regs + SM501_DC_CRT_CONTROL);
+
sm501fb_suspend_fb(info, HEAD_CRT);
sm501fb_suspend_fb(info, HEAD_PANEL);
@@ -1740,12 +1769,24 @@ static int sm501fb_suspend(struct platform_device *pdev, pm_message_t state)
return 0;
}
+#define SM501_CRT_CTRL_SAVE (SM501_DC_CRT_CONTROL_TVP | \
+ SM501_DC_CRT_CONTROL_SEL)
+
+
static int sm501fb_resume(struct platform_device *pdev)
{
struct sm501fb_info *info = platform_get_drvdata(pdev);
+ unsigned long crt_ctrl;
sm501_unit_power(info->dev->parent, SM501_GATE_DISPLAY, 1);
+ /* restore the items we want to be saved for crt control */
+
+ crt_ctrl = readl(info->regs + SM501_DC_CRT_CONTROL);
+ crt_ctrl &= ~SM501_CRT_CTRL_SAVE;
+ crt_ctrl |= info->pm_crt_ctrl & SM501_CRT_CTRL_SAVE;
+ writel(crt_ctrl, info->regs + SM501_DC_CRT_CONTROL);
+
sm501fb_resume_fb(info, HEAD_CRT);
sm501fb_resume_fb(info, HEAD_PANEL);
diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c
index 5eff28ce4f4d..97784f9c184d 100644
--- a/drivers/video/sstfb.c
+++ b/drivers/video/sstfb.c
@@ -88,7 +88,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <video/sstfb.h>
diff --git a/drivers/video/svgalib.c b/drivers/video/svgalib.c
index 25df928d37d8..9c7106701572 100644
--- a/drivers/video/svgalib.c
+++ b/drivers/video/svgalib.c
@@ -598,9 +598,11 @@ void svga_set_timings(const struct svga_timing_regs *tm, struct fb_var_screeninf
/* ------------------------------------------------------------------------- */
-int svga_match_format(const struct svga_fb_format *frm, struct fb_var_screeninfo *var, struct fb_fix_screeninfo *fix)
+static inline int match_format(const struct svga_fb_format *frm,
+ struct fb_var_screeninfo *var)
{
int i = 0;
+ int stored = -EINVAL;
while (frm->bits_per_pixel != SVGA_FORMAT_END_VAL)
{
@@ -609,25 +611,38 @@ int svga_match_format(const struct svga_fb_format *frm, struct fb_var_screeninfo
(var->green.length <= frm->green.length) &&
(var->blue.length <= frm->blue.length) &&
(var->transp.length <= frm->transp.length) &&
- (var->nonstd == frm->nonstd)) {
- var->bits_per_pixel = frm->bits_per_pixel;
- var->red = frm->red;
- var->green = frm->green;
- var->blue = frm->blue;
- var->transp = frm->transp;
- var->nonstd = frm->nonstd;
- if (fix != NULL) {
- fix->type = frm->type;
- fix->type_aux = frm->type_aux;
- fix->visual = frm->visual;
- fix->xpanstep = frm->xpanstep;
- }
+ (var->nonstd == frm->nonstd))
return i;
- }
+ if (var->bits_per_pixel == frm->bits_per_pixel)
+ stored = i;
i++;
frm++;
}
- return -EINVAL;
+ return stored;
+}
+
+int svga_match_format(const struct svga_fb_format *frm,
+ struct fb_var_screeninfo *var,
+ struct fb_fix_screeninfo *fix)
+{
+ int i = match_format(frm, var);
+
+ if (i >= 0) {
+ var->bits_per_pixel = frm[i].bits_per_pixel;
+ var->red = frm[i].red;
+ var->green = frm[i].green;
+ var->blue = frm[i].blue;
+ var->transp = frm[i].transp;
+ var->nonstd = frm[i].nonstd;
+ if (fix != NULL) {
+ fix->type = frm[i].type;
+ fix->type_aux = frm[i].type_aux;
+ fix->visual = frm[i].visual;
+ fix->xpanstep = frm[i].xpanstep;
+ }
+ }
+
+ return i;
}
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index 689ce0270b81..057bdd593800 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -4,13 +4,13 @@
*
* Author: Hannu Mallat <hmallat@cc.hut.fi>
*
- * Copyright © 1999 Hannu Mallat
+ * Copyright © 1999 Hannu Mallat
* All rights reserved
*
* Created : Thu Sep 23 18:17:43 1999, hmallat
* Last modified: Tue Nov 2 21:19:47 1999, hmallat
*
- * Lots of the information here comes from the Daryll Strauss' Banshee
+ * Lots of the information here comes from the Daryll Strauss' Banshee
* patches to the XF86 server, and the rest comes from the 3dfx
* Banshee specification. I'm very much indebted to Daryll for his
* work on the X server.
@@ -23,7 +23,7 @@
* behave very differently from the Voodoo3/4/5. For anyone wanting to
* use frame buffer on the Voodoo1/2, see the sstfb driver (which is
* located at http://www.sourceforge.net/projects/sstfb).
- *
+ *
* While I _am_ grateful to 3Dfx for releasing the specs for Banshee,
* I do wish the next version is a bit more complete. Without the XF86
* patches I couldn't have gotten even this far... for instance, the
@@ -33,9 +33,8 @@
*
* The structure of this driver comes pretty much from the Permedia
* driver by Ilario Nardinocchi, which in turn is based on skeletonfb.
- *
+ *
* TODO:
- * - support for 16/32 bpp needs fixing (funky bootup penguin)
* - multihead support (basically need to support an array of fb_infos)
* - support other architectures (PPC, Alpha); does the fact that the VGA
* core can be accessed only thru I/O (not memory mapped) complicate
@@ -43,18 +42,18 @@
*
* Version history:
*
- * 0.1.4 (released 2002-05-28) ported over to new fbdev api by James Simmons
+ * 0.1.4 (released 2002-05-28) ported over to new fbdev api by James Simmons
*
- * 0.1.3 (released 1999-11-02) added Attila's panning support, code
- * reorg, hwcursor address page size alignment
- * (for mmaping both frame buffer and regs),
- * and my changes to get rid of hardcoded
- * VGA i/o register locations (uses PCI
- * configuration info now)
- * 0.1.2 (released 1999-10-19) added Attila Kesmarki's bug fixes and
- * improvements
- * 0.1.1 (released 1999-10-07) added Voodoo3 support by Harold Oga.
- * 0.1.0 (released 1999-10-06) initial version
+ * 0.1.3 (released 1999-11-02) added Attila's panning support, code
+ * reorg, hwcursor address page size alignment
+ * (for mmaping both frame buffer and regs),
+ * and my changes to get rid of hardcoded
+ * VGA i/o register locations (uses PCI
+ * configuration info now)
+ * 0.1.2 (released 1999-10-19) added Attila Kesmarki's bug fixes and
+ * improvements
+ * 0.1.1 (released 1999-10-07) added Voodoo3 support by Harold Oga.
+ * 0.1.0 (released 1999-10-06) initial version
*
*/
@@ -64,24 +63,32 @@
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/pci.h>
-#include <linux/nvram.h>
#include <asm/io.h>
-#include <linux/timer.h>
-#include <linux/spinlock.h>
#include <video/tdfx.h>
-#undef TDFXFB_DEBUG
-#ifdef TDFXFB_DEBUG
-#define DPRINTK(a,b...) printk(KERN_DEBUG "fb: %s: " a, __FUNCTION__ , ## b)
+#define DPRINTK(a, b...) pr_debug("fb: %s: " a, __FUNCTION__ , ## b)
+
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
#else
-#define DPRINTK(a,b...)
-#endif
+/* duplicate asm/mtrr.h defines to work on archs without mtrr */
+#define MTRR_TYPE_WRCOMB 1
+
+static inline int mtrr_add(unsigned long base, unsigned long size,
+ unsigned int type, char increment)
+{
+ return -ENODEV;
+}
+static inline int mtrr_del(int reg, unsigned long base,
+ unsigned long size)
+{
+ return -ENODEV;
+}
+#endif
#define BANSHEE_MAX_PIXCLOCK 270000
#define VOODOO3_MAX_PIXCLOCK 300000
@@ -90,9 +97,9 @@
static struct fb_fix_screeninfo tdfx_fix __devinitdata = {
.id = "3Dfx",
.type = FB_TYPE_PACKED_PIXELS,
- .visual = FB_VISUAL_PSEUDOCOLOR,
+ .visual = FB_VISUAL_PSEUDOCOLOR,
.ypanstep = 1,
- .ywrapstep = 1,
+ .ywrapstep = 1,
.accel = FB_ACCEL_3DFX_BANSHEE
};
@@ -102,7 +109,7 @@ static struct fb_var_screeninfo tdfx_var __devinitdata = {
.yres = 480,
.xres_virtual = 640,
.yres_virtual = 1024,
- .bits_per_pixel =8,
+ .bits_per_pixel = 8,
.red = {0, 8, 0},
.blue = {0, 8, 0},
.green = {0, 8, 0},
@@ -142,103 +149,79 @@ static struct pci_device_id tdfxfb_id_table[] = {
static struct pci_driver tdfxfb_driver = {
.name = "tdfxfb",
- .id_table = tdfxfb_id_table,
- .probe = tdfxfb_probe,
- .remove = __devexit_p(tdfxfb_remove),
+ .id_table = tdfxfb_id_table,
+ .probe = tdfxfb_probe,
+ .remove = __devexit_p(tdfxfb_remove),
};
MODULE_DEVICE_TABLE(pci, tdfxfb_id_table);
/*
- * Frame buffer device API
+ * Driver data
*/
-static int tdfxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fb);
-static int tdfxfb_set_par(struct fb_info *info);
-static int tdfxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
- u_int transp, struct fb_info *info);
-static int tdfxfb_blank(int blank, struct fb_info *info);
-static int tdfxfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
-static int banshee_wait_idle(struct fb_info *info);
-#ifdef CONFIG_FB_3DFX_ACCEL
-static void tdfxfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
-static void tdfxfb_copyarea(struct fb_info *info, const struct fb_copyarea *area);
-static void tdfxfb_imageblit(struct fb_info *info, const struct fb_image *image);
-#endif /* CONFIG_FB_3DFX_ACCEL */
-
-static struct fb_ops tdfxfb_ops = {
- .owner = THIS_MODULE,
- .fb_check_var = tdfxfb_check_var,
- .fb_set_par = tdfxfb_set_par,
- .fb_setcolreg = tdfxfb_setcolreg,
- .fb_blank = tdfxfb_blank,
- .fb_pan_display = tdfxfb_pan_display,
- .fb_sync = banshee_wait_idle,
-#ifdef CONFIG_FB_3DFX_ACCEL
- .fb_fillrect = tdfxfb_fillrect,
- .fb_copyarea = tdfxfb_copyarea,
- .fb_imageblit = tdfxfb_imageblit,
-#else
- .fb_fillrect = cfb_fillrect,
- .fb_copyarea = cfb_copyarea,
- .fb_imageblit = cfb_imageblit,
-#endif
-};
-
-/*
- * do_xxx: Hardware-specific functions
- */
-static u32 do_calc_pll(int freq, int *freq_out);
-static void do_write_regs(struct fb_info *info, struct banshee_reg *reg);
-static unsigned long do_lfb_size(struct tdfx_par *par, unsigned short);
-
-/*
- * Driver data
- */
-static int nopan = 0;
-static int nowrap = 1; // not implemented (yet)
-static char *mode_option __devinitdata = NULL;
-
-/* -------------------------------------------------------------------------
- * Hardware-specific funcions
+static int nopan;
+static int nowrap = 1; /* not implemented (yet) */
+static int hwcursor = 1;
+static char *mode_option __devinitdata;
+/* mtrr option */
+static int nomtrr __devinitdata;
+
+/* -------------------------------------------------------------------------
+ * Hardware-specific funcions
* ------------------------------------------------------------------------- */
-#ifdef VGA_REG_IO
-static inline u8 vga_inb(struct tdfx_par *par, u32 reg) { return inb(reg); }
-
-static inline void vga_outb(struct tdfx_par *par, u32 reg, u8 val) { outb(val, reg); }
-#else
-static inline u8 vga_inb(struct tdfx_par *par, u32 reg) {
- return inb(par->iobase + reg - 0x300);
+static inline u8 vga_inb(struct tdfx_par *par, u32 reg)
+{
+ return inb(par->iobase + reg - 0x300);
}
-static inline void vga_outb(struct tdfx_par *par, u32 reg, u8 val) {
- outb(val, par->iobase + reg - 0x300);
+
+static inline void vga_outb(struct tdfx_par *par, u32 reg, u8 val)
+{
+ outb(val, par->iobase + reg - 0x300);
}
-#endif
-static inline void gra_outb(struct tdfx_par *par, u32 idx, u8 val) {
- vga_outb(par, GRA_I, idx); vga_outb(par, GRA_D, val);
+static inline void gra_outb(struct tdfx_par *par, u32 idx, u8 val)
+{
+ vga_outb(par, GRA_I, idx);
+ wmb();
+ vga_outb(par, GRA_D, val);
+ wmb();
}
-static inline void seq_outb(struct tdfx_par *par, u32 idx, u8 val) {
- vga_outb(par, SEQ_I, idx); vga_outb(par, SEQ_D, val);
+static inline void seq_outb(struct tdfx_par *par, u32 idx, u8 val)
+{
+ vga_outb(par, SEQ_I, idx);
+ wmb();
+ vga_outb(par, SEQ_D, val);
+ wmb();
}
-static inline u8 seq_inb(struct tdfx_par *par, u32 idx) {
- vga_outb(par, SEQ_I, idx); return vga_inb(par, SEQ_D);
+static inline u8 seq_inb(struct tdfx_par *par, u32 idx)
+{
+ vga_outb(par, SEQ_I, idx);
+ mb();
+ return vga_inb(par, SEQ_D);
}
-static inline void crt_outb(struct tdfx_par *par, u32 idx, u8 val) {
- vga_outb(par, CRT_I, idx); vga_outb(par, CRT_D, val);
+static inline void crt_outb(struct tdfx_par *par, u32 idx, u8 val)
+{
+ vga_outb(par, CRT_I, idx);
+ wmb();
+ vga_outb(par, CRT_D, val);
+ wmb();
}
-static inline u8 crt_inb(struct tdfx_par *par, u32 idx) {
- vga_outb(par, CRT_I, idx); return vga_inb(par, CRT_D);
+static inline u8 crt_inb(struct tdfx_par *par, u32 idx)
+{
+ vga_outb(par, CRT_I, idx);
+ mb();
+ return vga_inb(par, CRT_D);
}
-static inline void att_outb(struct tdfx_par *par, u32 idx, u8 val)
+static inline void att_outb(struct tdfx_par *par, u32 idx, u8 val)
{
unsigned char tmp;
-
+
tmp = vga_inb(par, IS1_R);
vga_outb(par, ATT_IW, idx);
vga_outb(par, ATT_IW, val);
@@ -267,10 +250,11 @@ static inline void vga_enable_video(struct tdfx_par *par)
static inline void vga_enable_palette(struct tdfx_par *par)
{
vga_inb(par, IS1_R);
+ mb();
vga_outb(par, ATT_IW, 0x20);
}
-static inline u32 tdfx_inl(struct tdfx_par *par, unsigned int reg)
+static inline u32 tdfx_inl(struct tdfx_par *par, unsigned int reg)
{
return readl(par->regbase_virt + reg);
}
@@ -284,9 +268,10 @@ static inline void banshee_make_room(struct tdfx_par *par, int size)
{
/* Note: The Voodoo3's onboard FIFO has 32 slots. This loop
* won't quit if you ask for more. */
- while((tdfx_inl(par, STATUS) & 0x1f) < size-1);
+ while ((tdfx_inl(par, STATUS) & 0x1f) < size - 1)
+ cpu_relax();
}
-
+
static int banshee_wait_idle(struct fb_info *info)
{
struct tdfx_par *par = info->par;
@@ -295,28 +280,31 @@ static int banshee_wait_idle(struct fb_info *info)
banshee_make_room(par, 1);
tdfx_outl(par, COMMAND_3D, COMMAND_3D_NOP);
- while(1) {
- i = (tdfx_inl(par, STATUS) & STATUS_BUSY) ? 0 : i + 1;
- if(i == 3) break;
- }
+ do {
+ if ((tdfx_inl(par, STATUS) & STATUS_BUSY) == 0)
+ i++;
+ } while (i < 3);
+
return 0;
}
/*
- * Set the color of a palette entry in 8bpp mode
+ * Set the color of a palette entry in 8bpp mode
*/
static inline void do_setpalentry(struct tdfx_par *par, unsigned regno, u32 c)
-{
+{
banshee_make_room(par, 2);
tdfx_outl(par, DACADDR, regno);
+ /* read after write makes it working */
+ tdfx_inl(par, DACADDR);
tdfx_outl(par, DACDATA, c);
}
-static u32 do_calc_pll(int freq, int* freq_out)
+static u32 do_calc_pll(int freq, int *freq_out)
{
int m, n, k, best_m, best_n, best_k, best_error;
int fref = 14318;
-
+
best_error = freq;
best_n = best_m = best_k = 0;
@@ -326,27 +314,28 @@ static u32 do_calc_pll(int freq, int* freq_out)
* Estimate value of n that produces target frequency
* with current m and k
*/
- int n_estimated = (freq * (m + 2) * (1 << k) / fref) - 2;
+ int n_estimated = ((freq * (m + 2) << k) / fref) - 2;
/* Search neighborhood of estimated n */
- for (n = max(0, n_estimated - 1);
- n <= min(255, n_estimated + 1); n++) {
+ for (n = max(0, n_estimated);
+ n <= min(255, n_estimated + 1);
+ n++) {
/*
* Calculate PLL freqency with current m, k and
* estimated n
*/
- int f = fref * (n + 2) / (m + 2) / (1 << k);
- int error = abs (f - freq);
+ int f = (fref * (n + 2) / (m + 2)) >> k;
+ int error = abs(f - freq);
/*
- * If this is the closest we've come to the
+ * If this is the closest we've come to the
* target frequency then remember n, m and k
*/
- if (error < best_error) {
+ if (error < best_error) {
best_error = error;
- best_n = n;
- best_m = m;
- best_k = k;
+ best_n = n;
+ best_m = m;
+ best_k = k;
}
}
}
@@ -355,12 +344,12 @@ static u32 do_calc_pll(int freq, int* freq_out)
n = best_n;
m = best_m;
k = best_k;
- *freq_out = fref*(n + 2)/(m + 2)/(1 << k);
+ *freq_out = (fref * (n + 2) / (m + 2)) >> k;
return (n << 8) | (m << 2) | k;
}
-static void do_write_regs(struct fb_info *info, struct banshee_reg* reg)
+static void do_write_regs(struct fb_info *info, struct banshee_reg *reg)
{
struct tdfx_par *par = info->par;
int i;
@@ -372,13 +361,13 @@ static void do_write_regs(struct fb_info *info, struct banshee_reg* reg)
crt_outb(par, 0x11, crt_inb(par, 0x11) & 0x7f); /* CRT unprotect */
banshee_make_room(par, 3);
- tdfx_outl(par, VGAINIT1, reg->vgainit1 & 0x001FFFFF);
- tdfx_outl(par, VIDPROCCFG, reg->vidcfg & ~0x00000001);
+ tdfx_outl(par, VGAINIT1, reg->vgainit1 & 0x001FFFFF);
+ tdfx_outl(par, VIDPROCCFG, reg->vidcfg & ~0x00000001);
#if 0
tdfx_outl(par, PLLCTRL1, reg->mempll);
tdfx_outl(par, PLLCTRL2, reg->gfxpll);
#endif
- tdfx_outl(par, PLLCTRL0, reg->vidpll);
+ tdfx_outl(par, PLLCTRL0, reg->vidpll);
vga_outb(par, MISC_W, reg->misc[0x00] | 0x01);
@@ -400,72 +389,65 @@ static void do_write_regs(struct fb_info *info, struct banshee_reg* reg)
vga_enable_palette(par);
vga_enable_video(par);
- banshee_make_room(par, 11);
- tdfx_outl(par, VGAINIT0, reg->vgainit0);
- tdfx_outl(par, DACMODE, reg->dacmode);
- tdfx_outl(par, VIDDESKSTRIDE, reg->stride);
- tdfx_outl(par, HWCURPATADDR, 0);
-
- tdfx_outl(par, VIDSCREENSIZE,reg->screensize);
- tdfx_outl(par, VIDDESKSTART, reg->startaddr);
- tdfx_outl(par, VIDPROCCFG, reg->vidcfg);
- tdfx_outl(par, VGAINIT1, reg->vgainit1);
- tdfx_outl(par, MISCINIT0, reg->miscinit0);
-
- banshee_make_room(par, 8);
- tdfx_outl(par, SRCBASE, reg->srcbase);
- tdfx_outl(par, DSTBASE, reg->dstbase);
- tdfx_outl(par, COMMANDEXTRA_2D, 0);
- tdfx_outl(par, CLIP0MIN, 0);
- tdfx_outl(par, CLIP0MAX, 0x0fff0fff);
- tdfx_outl(par, CLIP1MIN, 0);
- tdfx_outl(par, CLIP1MAX, 0x0fff0fff);
- tdfx_outl(par, SRCXY, 0);
+ banshee_make_room(par, 9);
+ tdfx_outl(par, VGAINIT0, reg->vgainit0);
+ tdfx_outl(par, DACMODE, reg->dacmode);
+ tdfx_outl(par, VIDDESKSTRIDE, reg->stride);
+ tdfx_outl(par, HWCURPATADDR, reg->curspataddr);
+
+ tdfx_outl(par, VIDSCREENSIZE, reg->screensize);
+ tdfx_outl(par, VIDDESKSTART, reg->startaddr);
+ tdfx_outl(par, VIDPROCCFG, reg->vidcfg);
+ tdfx_outl(par, VGAINIT1, reg->vgainit1);
+ tdfx_outl(par, MISCINIT0, reg->miscinit0);
+
+ banshee_make_room(par, 8);
+ tdfx_outl(par, SRCBASE, reg->startaddr);
+ tdfx_outl(par, DSTBASE, reg->startaddr);
+ tdfx_outl(par, COMMANDEXTRA_2D, 0);
+ tdfx_outl(par, CLIP0MIN, 0);
+ tdfx_outl(par, CLIP0MAX, 0x0fff0fff);
+ tdfx_outl(par, CLIP1MIN, 0);
+ tdfx_outl(par, CLIP1MAX, 0x0fff0fff);
+ tdfx_outl(par, SRCXY, 0);
banshee_wait_idle(info);
}
-static unsigned long do_lfb_size(struct tdfx_par *par, unsigned short dev_id)
+static unsigned long do_lfb_size(struct tdfx_par *par, unsigned short dev_id)
{
- u32 draminit0;
- u32 draminit1;
+ u32 draminit0 = tdfx_inl(par, DRAMINIT0);
+ u32 draminit1 = tdfx_inl(par, DRAMINIT1);
u32 miscinit1;
-
- int num_chips;
+ int num_chips = (draminit0 & DRAMINIT0_SGRAM_NUM) ? 8 : 4;
int chip_size; /* in MB */
- u32 lfbsize;
- int has_sgram;
+ int has_sgram = draminit1 & DRAMINIT1_MEM_SDRAM;
- draminit0 = tdfx_inl(par, DRAMINIT0);
- draminit1 = tdfx_inl(par, DRAMINIT1);
-
- num_chips = (draminit0 & DRAMINIT0_SGRAM_NUM) ? 8 : 4;
-
if (dev_id < PCI_DEVICE_ID_3DFX_VOODOO5) {
/* Banshee/Voodoo3 */
- has_sgram = draminit1 & DRAMINIT1_MEM_SDRAM;
- chip_size = has_sgram ? ((draminit0 & DRAMINIT0_SGRAM_TYPE) ? 2 : 1)
- : 2;
+ chip_size = 2;
+ if (has_sgram && (draminit0 & DRAMINIT0_SGRAM_TYPE))
+ chip_size = 1;
} else {
/* Voodoo4/5 */
has_sgram = 0;
- chip_size = 1 << ((draminit0 & DRAMINIT0_SGRAM_TYPE_MASK) >> DRAMINIT0_SGRAM_TYPE_SHIFT);
+ chip_size = draminit0 & DRAMINIT0_SGRAM_TYPE_MASK;
+ chip_size = 1 << (chip_size >> DRAMINIT0_SGRAM_TYPE_SHIFT);
}
- lfbsize = num_chips * chip_size * 1024 * 1024;
/* disable block writes for SDRAM */
miscinit1 = tdfx_inl(par, MISCINIT1);
miscinit1 |= has_sgram ? 0 : MISCINIT1_2DBLOCK_DIS;
miscinit1 |= MISCINIT1_CLUT_INV;
- banshee_make_room(par, 1);
+ banshee_make_room(par, 1);
tdfx_outl(par, MISCINIT1, miscinit1);
- return lfbsize;
+ return num_chips * chip_size * 1024l * 1024;
}
/* ------------------------------------------------------------------------- */
-static int tdfxfb_check_var(struct fb_var_screeninfo *var,struct fb_info *info)
+static int tdfxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
struct tdfx_par *par = info->par;
u32 lpitch;
@@ -486,103 +468,113 @@ static int tdfxfb_check_var(struct fb_var_screeninfo *var,struct fb_info *info)
DPRINTK("xoffset not supported\n");
return -EINVAL;
}
+ var->yoffset = 0;
- /* Banshee doesn't support interlace, but Voodoo4/5 and probably Voodoo3 do. */
- /* no direct information about device id now? use max_pixclock for this... */
+ /*
+ * Banshee doesn't support interlace, but Voodoo4/5 and probably
+ * Voodoo3 do.
+ * no direct information about device id now?
+ * use max_pixclock for this...
+ */
if (((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) &&
- (par->max_pixclock < VOODOO3_MAX_PIXCLOCK)) {
+ (par->max_pixclock < VOODOO3_MAX_PIXCLOCK)) {
DPRINTK("interlace not supported\n");
return -EINVAL;
}
var->xres = (var->xres + 15) & ~15; /* could sometimes be 8 */
- lpitch = var->xres * ((var->bits_per_pixel + 7)>>3);
-
+ lpitch = var->xres * ((var->bits_per_pixel + 7) >> 3);
+
if (var->xres < 320 || var->xres > 2048) {
DPRINTK("width not supported: %u\n", var->xres);
return -EINVAL;
}
-
+
if (var->yres < 200 || var->yres > 2048) {
DPRINTK("height not supported: %u\n", var->yres);
return -EINVAL;
}
-
+
if (lpitch * var->yres_virtual > info->fix.smem_len) {
- var->yres_virtual = info->fix.smem_len/lpitch;
+ var->yres_virtual = info->fix.smem_len / lpitch;
if (var->yres_virtual < var->yres) {
DPRINTK("no memory for screen (%ux%ux%u)\n",
- var->xres, var->yres_virtual, var->bits_per_pixel);
+ var->xres, var->yres_virtual,
+ var->bits_per_pixel);
return -EINVAL;
}
}
-
+
if (PICOS2KHZ(var->pixclock) > par->max_pixclock) {
- DPRINTK("pixclock too high (%ldKHz)\n",PICOS2KHZ(var->pixclock));
+ DPRINTK("pixclock too high (%ldKHz)\n",
+ PICOS2KHZ(var->pixclock));
return -EINVAL;
}
- switch(var->bits_per_pixel) {
- case 8:
- var->red.length = var->green.length = var->blue.length = 8;
- break;
- case 16:
- var->red.offset = 11;
- var->red.length = 5;
- var->green.offset = 5;
- var->green.length = 6;
- var->blue.offset = 0;
- var->blue.length = 5;
- break;
- case 24:
- var->red.offset=16;
- var->green.offset=8;
- var->blue.offset=0;
- var->red.length = var->green.length = var->blue.length = 8;
- case 32:
- var->red.offset = 16;
- var->green.offset = 8;
- var->blue.offset = 0;
- var->red.length = var->green.length = var->blue.length = 8;
- break;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ switch (var->bits_per_pixel) {
+ case 8:
+ var->red.length = 8;
+ var->red.offset = 0;
+ var->green = var->red;
+ var->blue = var->red;
+ break;
+ case 16:
+ var->red.offset = 11;
+ var->red.length = 5;
+ var->green.offset = 5;
+ var->green.length = 6;
+ var->blue.offset = 0;
+ var->blue.length = 5;
+ break;
+ case 32:
+ var->transp.offset = 24;
+ var->transp.length = 8;
+ case 24:
+ var->red.offset = 16;
+ var->green.offset = 8;
+ var->blue.offset = 0;
+ var->red.length = var->green.length = var->blue.length = 8;
+ break;
}
- var->height = var->width = -1;
-
+ var->width = -1;
+ var->height = -1;
+
var->accel_flags = FB_ACCELF_TEXT;
-
- DPRINTK("Checking graphics mode at %dx%d depth %d\n", var->xres, var->yres, var->bits_per_pixel);
+
+ DPRINTK("Checking graphics mode at %dx%d depth %d\n",
+ var->xres, var->yres, var->bits_per_pixel);
return 0;
}
static int tdfxfb_set_par(struct fb_info *info)
{
struct tdfx_par *par = info->par;
- u32 hdispend, hsyncsta, hsyncend, htotal;
+ u32 hdispend = info->var.xres;
+ u32 hsyncsta = hdispend + info->var.right_margin;
+ u32 hsyncend = hsyncsta + info->var.hsync_len;
+ u32 htotal = hsyncend + info->var.left_margin;
u32 hd, hs, he, ht, hbs, hbe;
u32 vd, vs, ve, vt, vbs, vbe;
struct banshee_reg reg;
int fout, freq;
- u32 wd, cpp;
-
- par->baseline = 0;
-
+ u32 wd;
+ u32 cpp = (info->var.bits_per_pixel + 7) >> 3;
+
memset(&reg, 0, sizeof(reg));
- cpp = (info->var.bits_per_pixel + 7)/8;
-
- reg.vidcfg = VIDCFG_VIDPROC_ENABLE | VIDCFG_DESK_ENABLE | VIDCFG_CURS_X11 | ((cpp - 1) << VIDCFG_PIXFMT_SHIFT) | (cpp != 1 ? VIDCFG_CLUT_BYPASS : 0);
+
+ reg.vidcfg = VIDCFG_VIDPROC_ENABLE | VIDCFG_DESK_ENABLE |
+ VIDCFG_CURS_X11 |
+ ((cpp - 1) << VIDCFG_PIXFMT_SHIFT) |
+ (cpp != 1 ? VIDCFG_CLUT_BYPASS : 0);
/* PLL settings */
freq = PICOS2KHZ(info->var.pixclock);
- reg.dacmode = 0;
- reg.vidcfg &= ~VIDCFG_2X;
-
- hdispend = info->var.xres;
- hsyncsta = hdispend + info->var.right_margin;
- hsyncend = hsyncsta + info->var.hsync_len;
- htotal = hsyncend + info->var.left_margin;
+ reg.vidcfg &= ~VIDCFG_2X;
- if (freq > par->max_pixclock/2) {
+ if (freq > par->max_pixclock / 2) {
freq = freq > par->max_pixclock ? par->max_pixclock : freq;
reg.dacmode |= DACMODE_2X;
reg.vidcfg |= VIDCFG_2X;
@@ -591,8 +583,9 @@ static int tdfxfb_set_par(struct fb_info *info)
hsyncend >>= 1;
htotal >>= 1;
}
-
- hd = wd = (hdispend >> 3) - 1;
+
+ wd = (hdispend >> 3) - 1;
+ hd = wd;
hs = (hsyncsta >> 3) - 1;
he = (hsyncend >> 3) - 1;
ht = (htotal >> 3) - 1;
@@ -600,28 +593,30 @@ static int tdfxfb_set_par(struct fb_info *info)
hbe = ht;
if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
- vbs = vd = (info->var.yres << 1) - 1;
+ vd = (info->var.yres << 1) - 1;
vs = vd + (info->var.lower_margin << 1);
ve = vs + (info->var.vsync_len << 1);
- vbe = vt = ve + (info->var.upper_margin << 1) - 1;
+ vt = ve + (info->var.upper_margin << 1) - 1;
+ reg.screensize = info->var.xres | (info->var.yres << 13);
+ reg.vidcfg |= VIDCFG_HALF_MODE;
+ reg.crt[0x09] = 0x80;
} else {
- vbs = vd = info->var.yres - 1;
+ vd = info->var.yres - 1;
vs = vd + info->var.lower_margin;
ve = vs + info->var.vsync_len;
- vbe = vt = ve + info->var.upper_margin - 1;
+ vt = ve + info->var.upper_margin - 1;
+ reg.screensize = info->var.xres | (info->var.yres << 12);
+ reg.vidcfg &= ~VIDCFG_HALF_MODE;
}
-
+ vbs = vd;
+ vbe = vt;
+
/* this is all pretty standard VGA register stuffing */
- reg.misc[0x00] = 0x0f |
+ reg.misc[0x00] = 0x0f |
(info->var.xres < 400 ? 0xa0 :
info->var.xres < 480 ? 0x60 :
info->var.xres < 768 ? 0xe0 : 0x20);
-
- reg.gra[0x00] = 0x00;
- reg.gra[0x01] = 0x00;
- reg.gra[0x02] = 0x00;
- reg.gra[0x03] = 0x00;
- reg.gra[0x04] = 0x00;
+
reg.gra[0x05] = 0x40;
reg.gra[0x06] = 0x05;
reg.gra[0x07] = 0x0f;
@@ -644,10 +639,7 @@ static int tdfxfb_set_par(struct fb_info *info)
reg.att[0x0e] = 0x0e;
reg.att[0x0f] = 0x0f;
reg.att[0x10] = 0x41;
- reg.att[0x11] = 0x00;
reg.att[0x12] = 0x0f;
- reg.att[0x13] = 0x00;
- reg.att[0x14] = 0x00;
reg.seq[0x00] = 0x03;
reg.seq[0x01] = 0x01; /* fixme: clkdiv2? */
@@ -660,146 +652,133 @@ static int tdfxfb_set_par(struct fb_info *info)
reg.crt[0x02] = hbs;
reg.crt[0x03] = 0x80 | (hbe & 0x1f);
reg.crt[0x04] = hs;
- reg.crt[0x05] = ((hbe & 0x20) << 2) | (he & 0x1f);
+ reg.crt[0x05] = ((hbe & 0x20) << 2) | (he & 0x1f);
reg.crt[0x06] = vt;
reg.crt[0x07] = ((vs & 0x200) >> 2) |
((vd & 0x200) >> 3) |
((vt & 0x200) >> 4) | 0x10 |
((vbs & 0x100) >> 5) |
- ((vs & 0x100) >> 6) |
- ((vd & 0x100) >> 7) |
- ((vt & 0x100) >> 8);
- reg.crt[0x08] = 0x00;
- reg.crt[0x09] = 0x40 | ((vbs & 0x200) >> 4);
- reg.crt[0x0a] = 0x00;
- reg.crt[0x0b] = 0x00;
- reg.crt[0x0c] = 0x00;
- reg.crt[0x0d] = 0x00;
- reg.crt[0x0e] = 0x00;
- reg.crt[0x0f] = 0x00;
+ ((vs & 0x100) >> 6) |
+ ((vd & 0x100) >> 7) |
+ ((vt & 0x100) >> 8);
+ reg.crt[0x09] |= 0x40 | ((vbs & 0x200) >> 4);
reg.crt[0x10] = vs;
- reg.crt[0x11] = (ve & 0x0f) | 0x20;
+ reg.crt[0x11] = (ve & 0x0f) | 0x20;
reg.crt[0x12] = vd;
reg.crt[0x13] = wd;
- reg.crt[0x14] = 0x00;
reg.crt[0x15] = vbs;
- reg.crt[0x16] = vbe + 1;
+ reg.crt[0x16] = vbe + 1;
reg.crt[0x17] = 0xc3;
reg.crt[0x18] = 0xff;
-
+
/* Banshee's nonvga stuff */
- reg.ext[0x00] = (((ht & 0x100) >> 8) |
- ((hd & 0x100) >> 6) |
+ reg.ext[0x00] = (((ht & 0x100) >> 8) |
+ ((hd & 0x100) >> 6) |
((hbs & 0x100) >> 4) |
- ((hbe & 0x40) >> 1) |
- ((hs & 0x100) >> 2) |
- ((he & 0x20) << 2));
- reg.ext[0x01] = (((vt & 0x400) >> 10) |
- ((vd & 0x400) >> 8) |
- ((vbs & 0x400) >> 6) |
- ((vbe & 0x400) >> 4));
-
- reg.vgainit0 = VGAINIT0_8BIT_DAC |
+ ((hbe & 0x40) >> 1) |
+ ((hs & 0x100) >> 2) |
+ ((he & 0x20) << 2));
+ reg.ext[0x01] = (((vt & 0x400) >> 10) |
+ ((vd & 0x400) >> 8) |
+ ((vbs & 0x400) >> 6) |
+ ((vbe & 0x400) >> 4));
+
+ reg.vgainit0 = VGAINIT0_8BIT_DAC |
VGAINIT0_EXT_ENABLE |
VGAINIT0_WAKEUP_3C3 |
VGAINIT0_ALT_READBACK |
VGAINIT0_EXTSHIFTOUT;
reg.vgainit1 = tdfx_inl(par, VGAINIT1) & 0x1fffff;
+ if (hwcursor)
+ reg.curspataddr = info->fix.smem_len;
+
reg.cursloc = 0;
-
- reg.cursc0 = 0;
+
+ reg.cursc0 = 0;
reg.cursc1 = 0xffffff;
-
- reg.stride = info->var.xres * cpp;
- reg.startaddr = par->baseline * reg.stride;
- reg.srcbase = reg.startaddr;
- reg.dstbase = reg.startaddr;
- /* PLL settings */
- freq = PICOS2KHZ(info->var.pixclock);
+ reg.stride = info->var.xres * cpp;
+ reg.startaddr = info->var.yoffset * reg.stride
+ + info->var.xoffset * cpp;
- reg.dacmode &= ~DACMODE_2X;
- reg.vidcfg &= ~VIDCFG_2X;
- if (freq > par->max_pixclock/2) {
- freq = freq > par->max_pixclock ? par->max_pixclock : freq;
- reg.dacmode |= DACMODE_2X;
- reg.vidcfg |= VIDCFG_2X;
- }
reg.vidpll = do_calc_pll(freq, &fout);
#if 0
reg.mempll = do_calc_pll(..., &fout);
reg.gfxpll = do_calc_pll(..., &fout);
#endif
- if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
- reg.screensize = info->var.xres | (info->var.yres << 13);
- reg.vidcfg |= VIDCFG_HALF_MODE;
- reg.crt[0x09] |= 0x80;
- } else {
- reg.screensize = info->var.xres | (info->var.yres << 12);
- reg.vidcfg &= ~VIDCFG_HALF_MODE;
- }
if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
reg.vidcfg |= VIDCFG_INTERLACE;
reg.miscinit0 = tdfx_inl(par, MISCINIT0);
#if defined(__BIG_ENDIAN)
switch (info->var.bits_per_pixel) {
- case 8:
- case 24:
- reg.miscinit0 &= ~(1 << 30);
- reg.miscinit0 &= ~(1 << 31);
- break;
- case 16:
- reg.miscinit0 |= (1 << 30);
- reg.miscinit0 |= (1 << 31);
- break;
- case 32:
- reg.miscinit0 |= (1 << 30);
- reg.miscinit0 &= ~(1 << 31);
- break;
+ case 8:
+ case 24:
+ reg.miscinit0 &= ~(1 << 30);
+ reg.miscinit0 &= ~(1 << 31);
+ break;
+ case 16:
+ reg.miscinit0 |= (1 << 30);
+ reg.miscinit0 |= (1 << 31);
+ break;
+ case 32:
+ reg.miscinit0 |= (1 << 30);
+ reg.miscinit0 &= ~(1 << 31);
+ break;
}
-#endif
+#endif
do_write_regs(info, &reg);
/* Now change fb_fix_screeninfo according to changes in par */
- info->fix.line_length = info->var.xres * ((info->var.bits_per_pixel + 7)>>3);
- info->fix.visual = (info->var.bits_per_pixel == 8)
+ info->fix.line_length = reg.stride;
+ info->fix.visual = (info->var.bits_per_pixel == 8)
? FB_VISUAL_PSEUDOCOLOR
: FB_VISUAL_TRUECOLOR;
- DPRINTK("Graphics mode is now set at %dx%d depth %d\n", info->var.xres, info->var.yres, info->var.bits_per_pixel);
- return 0;
+ DPRINTK("Graphics mode is now set at %dx%d depth %d\n",
+ info->var.xres, info->var.yres, info->var.bits_per_pixel);
+ return 0;
}
/* A handy macro shamelessly pinched from matroxfb */
-#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
+#define CNVT_TOHW(val, width) ((((val) << (width)) + 0x7FFF - (val)) >> 16)
-static int tdfxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
- unsigned blue,unsigned transp,struct fb_info *info)
+static int tdfxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *info)
{
struct tdfx_par *par = info->par;
u32 rgbcol;
-
- if (regno >= info->cmap.len || regno > 255) return 1;
-
+
+ if (regno >= info->cmap.len || regno > 255)
+ return 1;
+
+ /* grayscale works only partially under directcolor */
+ if (info->var.grayscale) {
+ /* grayscale = 0.30*R + 0.59*G + 0.11*B */
+ blue = (red * 77 + green * 151 + blue * 28) >> 8;
+ green = blue;
+ red = blue;
+ }
+
switch (info->fix.visual) {
case FB_VISUAL_PSEUDOCOLOR:
- rgbcol =(((u32)red & 0xff00) << 8) |
- (((u32)green & 0xff00) << 0) |
- (((u32)blue & 0xff00) >> 8);
+ rgbcol = (((u32)red & 0xff00) << 8) |
+ (((u32)green & 0xff00) << 0) |
+ (((u32)blue & 0xff00) >> 8);
do_setpalentry(par, regno, rgbcol);
break;
/* Truecolor has no hardware color palettes. */
case FB_VISUAL_TRUECOLOR:
if (regno < 16) {
- rgbcol = (CNVT_TOHW( red, info->var.red.length) <<
+ rgbcol = (CNVT_TOHW(red, info->var.red.length) <<
info->var.red.offset) |
- (CNVT_TOHW( green, info->var.green.length) <<
+ (CNVT_TOHW(green, info->var.green.length) <<
info->var.green.offset) |
- (CNVT_TOHW( blue, info->var.blue.length) <<
+ (CNVT_TOHW(blue, info->var.blue.length) <<
info->var.blue.offset) |
- (CNVT_TOHW( transp, info->var.transp.length) <<
+ (CNVT_TOHW(transp, info->var.transp.length) <<
info->var.transp.offset);
par->palette[regno] = rgbcol;
}
@@ -815,287 +794,325 @@ static int tdfxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
static int tdfxfb_blank(int blank, struct fb_info *info)
-{
+{
struct tdfx_par *par = info->par;
- u32 dacmode, state = 0, vgablank = 0;
+ int vgablank = 1;
+ u32 dacmode = tdfx_inl(par, DACMODE);
- dacmode = tdfx_inl(par, DACMODE);
+ dacmode &= ~(BIT(1) | BIT(3));
switch (blank) {
- case FB_BLANK_UNBLANK: /* Screen: On; HSync: On, VSync: On */
- state = 0;
- vgablank = 0;
- break;
- case FB_BLANK_NORMAL: /* Screen: Off; HSync: On, VSync: On */
- state = 0;
- vgablank = 1;
- break;
- case FB_BLANK_VSYNC_SUSPEND: /* Screen: Off; HSync: On, VSync: Off */
- state = BIT(3);
- vgablank = 1;
- break;
- case FB_BLANK_HSYNC_SUSPEND: /* Screen: Off; HSync: Off, VSync: On */
- state = BIT(1);
- vgablank = 1;
- break;
- case FB_BLANK_POWERDOWN: /* Screen: Off; HSync: Off, VSync: Off */
- state = BIT(1) | BIT(3);
- vgablank = 1;
- break;
+ case FB_BLANK_UNBLANK: /* Screen: On; HSync: On, VSync: On */
+ vgablank = 0;
+ break;
+ case FB_BLANK_NORMAL: /* Screen: Off; HSync: On, VSync: On */
+ break;
+ case FB_BLANK_VSYNC_SUSPEND: /* Screen: Off; HSync: On, VSync: Off */
+ dacmode |= BIT(3);
+ break;
+ case FB_BLANK_HSYNC_SUSPEND: /* Screen: Off; HSync: Off, VSync: On */
+ dacmode |= BIT(1);
+ break;
+ case FB_BLANK_POWERDOWN: /* Screen: Off; HSync: Off, VSync: Off */
+ dacmode |= BIT(1) | BIT(3);
+ break;
}
- dacmode &= ~(BIT(1) | BIT(3));
- dacmode |= state;
- banshee_make_room(par, 1);
+ banshee_make_room(par, 1);
tdfx_outl(par, DACMODE, dacmode);
- if (vgablank)
+ if (vgablank)
vga_disable_video(par);
else
vga_enable_video(par);
return 0;
}
-/*
+/*
* Set the starting position of the visible screen to var->yoffset
- */
+ */
static int tdfxfb_pan_display(struct fb_var_screeninfo *var,
- struct fb_info *info)
+ struct fb_info *info)
{
struct tdfx_par *par = info->par;
- u32 addr;
+ u32 addr = var->yoffset * info->fix.line_length;
if (nopan || var->xoffset || (var->yoffset > var->yres_virtual))
return -EINVAL;
if ((var->yoffset + var->yres > var->yres_virtual && nowrap))
return -EINVAL;
- addr = var->yoffset * info->fix.line_length;
banshee_make_room(par, 1);
tdfx_outl(par, VIDDESKSTART, addr);
-
+
info->var.xoffset = var->xoffset;
- info->var.yoffset = var->yoffset;
+ info->var.yoffset = var->yoffset;
return 0;
}
#ifdef CONFIG_FB_3DFX_ACCEL
/*
- * FillRect 2D command (solidfill or invert (via ROP_XOR))
+ * FillRect 2D command (solidfill or invert (via ROP_XOR))
*/
-static void tdfxfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+static void tdfxfb_fillrect(struct fb_info *info,
+ const struct fb_fillrect *rect)
{
struct tdfx_par *par = info->par;
u32 bpp = info->var.bits_per_pixel;
u32 stride = info->fix.line_length;
- u32 fmt= stride | ((bpp+((bpp==8) ? 0 : 8)) << 13);
+ u32 fmt = stride | ((bpp + ((bpp == 8) ? 0 : 8)) << 13);
int tdfx_rop;
-
- if (rect->rop == ROP_COPY)
+ u32 dx = rect->dx;
+ u32 dy = rect->dy;
+ u32 dstbase = 0;
+
+ if (rect->rop == ROP_COPY)
tdfx_rop = TDFX_ROP_COPY;
- else
+ else
tdfx_rop = TDFX_ROP_XOR;
- banshee_make_room(par, 5);
- tdfx_outl(par, DSTFORMAT, fmt);
+ /* asume always rect->height < 4096 */
+ if (dy + rect->height > 4095) {
+ dstbase = stride * dy;
+ dy = 0;
+ }
+ /* asume always rect->width < 4096 */
+ if (dx + rect->width > 4095) {
+ dstbase += dx * bpp >> 3;
+ dx = 0;
+ }
+ banshee_make_room(par, 6);
+ tdfx_outl(par, DSTFORMAT, fmt);
if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {
- tdfx_outl(par, COLORFORE, rect->color);
+ tdfx_outl(par, COLORFORE, rect->color);
} else { /* FB_VISUAL_TRUECOLOR */
tdfx_outl(par, COLORFORE, par->palette[rect->color]);
}
- tdfx_outl(par, COMMAND_2D, COMMAND_2D_FILLRECT | (tdfx_rop << 24));
- tdfx_outl(par, DSTSIZE, rect->width | (rect->height << 16));
- tdfx_outl(par, LAUNCH_2D, rect->dx | (rect->dy << 16));
+ tdfx_outl(par, COMMAND_2D, COMMAND_2D_FILLRECT | (tdfx_rop << 24));
+ tdfx_outl(par, DSTBASE, dstbase);
+ tdfx_outl(par, DSTSIZE, rect->width | (rect->height << 16));
+ tdfx_outl(par, LAUNCH_2D, dx | (dy << 16));
}
/*
- * Screen-to-Screen BitBlt 2D command (for the bmove fb op.)
+ * Screen-to-Screen BitBlt 2D command (for the bmove fb op.)
*/
-static void tdfxfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+static void tdfxfb_copyarea(struct fb_info *info,
+ const struct fb_copyarea *area)
{
struct tdfx_par *par = info->par;
- u32 sx = area->sx, sy = area->sy, dx = area->dx, dy = area->dy;
+ u32 sx = area->sx, sy = area->sy, dx = area->dx, dy = area->dy;
u32 bpp = info->var.bits_per_pixel;
u32 stride = info->fix.line_length;
u32 blitcmd = COMMAND_2D_S2S_BITBLT | (TDFX_ROP_COPY << 24);
- u32 fmt = stride | ((bpp+((bpp==8) ? 0 : 8)) << 13);
-
+ u32 fmt = stride | ((bpp + ((bpp == 8) ? 0 : 8)) << 13);
+ u32 dstbase = 0;
+ u32 srcbase = 0;
+
+ /* asume always area->height < 4096 */
+ if (sy + area->height > 4095) {
+ srcbase = stride * sy;
+ sy = 0;
+ }
+ /* asume always area->width < 4096 */
+ if (sx + area->width > 4095) {
+ srcbase += sx * bpp >> 3;
+ sx = 0;
+ }
+ /* asume always area->height < 4096 */
+ if (dy + area->height > 4095) {
+ dstbase = stride * dy;
+ dy = 0;
+ }
+ /* asume always area->width < 4096 */
+ if (dx + area->width > 4095) {
+ dstbase += dx * bpp >> 3;
+ dx = 0;
+ }
+
if (area->sx <= area->dx) {
- //-X
+ /* -X */
blitcmd |= BIT(14);
sx += area->width - 1;
dx += area->width - 1;
}
if (area->sy <= area->dy) {
- //-Y
+ /* -Y */
blitcmd |= BIT(15);
sy += area->height - 1;
dy += area->height - 1;
}
-
- banshee_make_room(par, 6);
- tdfx_outl(par, SRCFORMAT, fmt);
- tdfx_outl(par, DSTFORMAT, fmt);
- tdfx_outl(par, COMMAND_2D, blitcmd);
- tdfx_outl(par, DSTSIZE, area->width | (area->height << 16));
- tdfx_outl(par, DSTXY, dx | (dy << 16));
- tdfx_outl(par, LAUNCH_2D, sx | (sy << 16));
+ banshee_make_room(par, 8);
+
+ tdfx_outl(par, SRCFORMAT, fmt);
+ tdfx_outl(par, DSTFORMAT, fmt);
+ tdfx_outl(par, COMMAND_2D, blitcmd);
+ tdfx_outl(par, DSTSIZE, area->width | (area->height << 16));
+ tdfx_outl(par, DSTXY, dx | (dy << 16));
+ tdfx_outl(par, SRCBASE, srcbase);
+ tdfx_outl(par, DSTBASE, dstbase);
+ tdfx_outl(par, LAUNCH_2D, sx | (sy << 16));
}
-static void tdfxfb_imageblit(struct fb_info *info, const struct fb_image *image)
+static void tdfxfb_imageblit(struct fb_info *info, const struct fb_image *image)
{
struct tdfx_par *par = info->par;
- int size = image->height * ((image->width * image->depth + 7)>>3);
+ int size = image->height * ((image->width * image->depth + 7) >> 3);
int fifo_free;
int i, stride = info->fix.line_length;
u32 bpp = info->var.bits_per_pixel;
- u32 dstfmt = stride | ((bpp+((bpp==8) ? 0 : 8)) << 13);
+ u32 dstfmt = stride | ((bpp + ((bpp == 8) ? 0 : 8)) << 13);
u8 *chardata = (u8 *) image->data;
u32 srcfmt;
+ u32 dx = image->dx;
+ u32 dy = image->dy;
+ u32 dstbase = 0;
if (image->depth != 1) {
- //banshee_make_room(par, 6 + ((size + 3) >> 2));
- //srcfmt = stride | ((bpp+((bpp==8) ? 0 : 8)) << 13) | 0x400000;
+#ifdef BROKEN_CODE
+ banshee_make_room(par, 6 + ((size + 3) >> 2));
+ srcfmt = stride | ((bpp + ((bpp == 8) ? 0 : 8)) << 13) |
+ 0x400000;
+#else
cfb_imageblit(info, image);
+#endif
return;
- } else {
- banshee_make_room(par, 8);
- switch (info->fix.visual) {
- case FB_VISUAL_PSEUDOCOLOR:
+ }
+ banshee_make_room(par, 9);
+ switch (info->fix.visual) {
+ case FB_VISUAL_PSEUDOCOLOR:
tdfx_outl(par, COLORFORE, image->fg_color);
tdfx_outl(par, COLORBACK, image->bg_color);
- break;
- case FB_VISUAL_TRUECOLOR:
- default:
- tdfx_outl(par, COLORFORE,
- par->palette[image->fg_color]);
- tdfx_outl(par, COLORBACK,
- par->palette[image->bg_color]);
- }
+ break;
+ case FB_VISUAL_TRUECOLOR:
+ default:
+ tdfx_outl(par, COLORFORE,
+ par->palette[image->fg_color]);
+ tdfx_outl(par, COLORBACK,
+ par->palette[image->bg_color]);
+ }
#ifdef __BIG_ENDIAN
- srcfmt = 0x400000 | BIT(20);
+ srcfmt = 0x400000 | BIT(20);
#else
- srcfmt = 0x400000;
+ srcfmt = 0x400000;
#endif
- }
+ /* asume always image->height < 4096 */
+ if (dy + image->height > 4095) {
+ dstbase = stride * dy;
+ dy = 0;
+ }
+ /* asume always image->width < 4096 */
+ if (dx + image->width > 4095) {
+ dstbase += dx * bpp >> 3;
+ dx = 0;
+ }
- tdfx_outl(par, SRCXY, 0);
- tdfx_outl(par, DSTXY, image->dx | (image->dy << 16));
- tdfx_outl(par, COMMAND_2D, COMMAND_2D_H2S_BITBLT | (TDFX_ROP_COPY << 24));
- tdfx_outl(par, SRCFORMAT, srcfmt);
- tdfx_outl(par, DSTFORMAT, dstfmt);
- tdfx_outl(par, DSTSIZE, image->width | (image->height << 16));
+ tdfx_outl(par, DSTBASE, dstbase);
+ tdfx_outl(par, SRCXY, 0);
+ tdfx_outl(par, DSTXY, dx | (dy << 16));
+ tdfx_outl(par, COMMAND_2D,
+ COMMAND_2D_H2S_BITBLT | (TDFX_ROP_COPY << 24));
+ tdfx_outl(par, SRCFORMAT, srcfmt);
+ tdfx_outl(par, DSTFORMAT, dstfmt);
+ tdfx_outl(par, DSTSIZE, image->width | (image->height << 16));
/* A count of how many free FIFO entries we've requested.
* When this goes negative, we need to request more. */
fifo_free = 0;
- /* Send four bytes at a time of data */
- for (i = (size >> 2) ; i > 0; i--) {
- if(--fifo_free < 0) {
- fifo_free=31;
- banshee_make_room(par,fifo_free);
+ /* Send four bytes at a time of data */
+ for (i = (size >> 2); i > 0; i--) {
+ if (--fifo_free < 0) {
+ fifo_free = 31;
+ banshee_make_room(par, fifo_free);
}
- tdfx_outl(par, LAUNCH_2D,*(u32*)chardata);
- chardata += 4;
- }
-
- /* Send the leftovers now */
- banshee_make_room(par,3);
- i = size%4;
- switch (i) {
- case 0: break;
- case 1: tdfx_outl(par, LAUNCH_2D,*chardata); break;
- case 2: tdfx_outl(par, LAUNCH_2D,*(u16*)chardata); break;
- case 3: tdfx_outl(par, LAUNCH_2D,*(u16*)chardata | ((chardata[3]) << 24)); break;
+ tdfx_outl(par, LAUNCH_2D, *(u32 *)chardata);
+ chardata += 4;
+ }
+
+ /* Send the leftovers now */
+ banshee_make_room(par, 3);
+ switch (size % 4) {
+ case 0:
+ break;
+ case 1:
+ tdfx_outl(par, LAUNCH_2D, *chardata);
+ break;
+ case 2:
+ tdfx_outl(par, LAUNCH_2D, *(u16 *)chardata);
+ break;
+ case 3:
+ tdfx_outl(par, LAUNCH_2D,
+ *(u16 *)chardata | (chardata[3] << 24));
+ break;
}
}
#endif /* CONFIG_FB_3DFX_ACCEL */
-#ifdef TDFX_HARDWARE_CURSOR
static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
struct tdfx_par *par = info->par;
- unsigned long flags;
+ u32 vidcfg;
- /*
- * If the cursor is not be changed this means either we want the
- * current cursor state (if enable is set) or we want to query what
- * we can do with the cursor (if enable is not set)
- */
- if (!cursor->set) return 0;
+ if (!hwcursor)
+ return -EINVAL; /* just to force soft_cursor() call */
- /* Too large of a cursor :-( */
- if (cursor->image.width > 64 || cursor->image.height > 64)
- return -ENXIO;
+ /* Too large of a cursor or wrong bpp :-( */
+ if (cursor->image.width > 64 ||
+ cursor->image.height > 64 ||
+ cursor->image.depth > 1)
+ return -EINVAL;
- /*
- * If we are going to be changing things we should disable
- * the cursor first
- */
- if (info->cursor.enable) {
- spin_lock_irqsave(&par->DAClock, flags);
- info->cursor.enable = 0;
- del_timer(&(par->hwcursor.timer));
- tdfx_outl(par, VIDPROCCFG, par->hwcursor.disable);
- spin_unlock_irqrestore(&par->DAClock, flags);
- }
+ vidcfg = tdfx_inl(par, VIDPROCCFG);
+ if (cursor->enable)
+ tdfx_outl(par, VIDPROCCFG, vidcfg | VIDCFG_HWCURSOR_ENABLE);
+ else
+ tdfx_outl(par, VIDPROCCFG, vidcfg & ~VIDCFG_HWCURSOR_ENABLE);
- /* Disable the Cursor */
- if ((cursor->set && FB_CUR_SETCUR) && !cursor->enable)
+ /*
+ * If the cursor is not be changed this means either we want the
+ * current cursor state (if enable is set) or we want to query what
+ * we can do with the cursor (if enable is not set)
+ */
+ if (!cursor->set)
return 0;
/* fix cursor color - XFree86 forgets to restore it properly */
- if (cursor->set && FB_CUR_SETCMAP) {
- struct fb_cmap cmap = cursor->image.cmap;
+ if (cursor->set & FB_CUR_SETCMAP) {
+ struct fb_cmap cmap = info->cmap;
+ u32 bg_idx = cursor->image.bg_color;
+ u32 fg_idx = cursor->image.fg_color;
unsigned long bg_color, fg_color;
- cmap.len = 2; /* Voodoo 3+ only support 2 color cursors */
- fg_color = ((cmap.red[cmap.start] << 16) |
- (cmap.green[cmap.start] << 8) |
- (cmap.blue[cmap.start]));
- bg_color = ((cmap.red[cmap.start+1] << 16) |
- (cmap.green[cmap.start+1] << 8) |
- (cmap.blue[cmap.start+1]));
- fb_copy_cmap(&cmap, &info->cursor.image.cmap);
- spin_lock_irqsave(&par->DAClock, flags);
+ fg_color = (((u32)cmap.red[fg_idx] & 0xff00) << 8) |
+ (((u32)cmap.green[fg_idx] & 0xff00) << 0) |
+ (((u32)cmap.blue[fg_idx] & 0xff00) >> 8);
+ bg_color = (((u32)cmap.red[bg_idx] & 0xff00) << 8) |
+ (((u32)cmap.green[bg_idx] & 0xff00) << 0) |
+ (((u32)cmap.blue[bg_idx] & 0xff00) >> 8);
banshee_make_room(par, 2);
tdfx_outl(par, HWCURC0, bg_color);
tdfx_outl(par, HWCURC1, fg_color);
- spin_unlock_irqrestore(&par->DAClock, flags);
}
- if (cursor->set && FB_CUR_SETPOS) {
- int x, y;
+ if (cursor->set & FB_CUR_SETPOS) {
+ int x = cursor->image.dx;
+ int y = cursor->image.dy - info->var.yoffset;
- x = cursor->image.dx;
- y = cursor->image.dy;
- y -= info->var.yoffset;
- info->cursor.image.dx = x;
- info->cursor.image.dy = y;
x += 63;
y += 63;
- spin_lock_irqsave(&par->DAClock, flags);
banshee_make_room(par, 1);
tdfx_outl(par, HWCURLOC, (y << 16) + x);
- spin_unlock_irqrestore(&par->DAClock, flags);
}
-
- /* Not supported so we fake it */
- if (cursor->set && FB_CUR_SETHOT) {
- info->cursor.hot.x = cursor->hot.x;
- info->cursor.hot.y = cursor->hot.y;
- }
-
- if (cursor->set && FB_CUR_SETSHAPE) {
+ if (cursor->set & (FB_CUR_SETIMAGE | FB_CUR_SETSHAPE)) {
/*
- * Voodoo 3 and above cards use 2 monochrome cursor patterns.
+ * Voodoo 3 and above cards use 2 monochrome cursor patterns.
* The reason is so the card can fetch 8 words at a time
* and are stored on chip for use for the next 8 scanlines.
* This reduces the number of times for access to draw the
* cursor for each screen refresh.
* Each pattern is a bitmap of 64 bit wide and 64 bit high
- * (total of 8192 bits or 1024 Kbytes). The two patterns are
+ * (total of 8192 bits or 1024 bytes). The two patterns are
* stored in such a way that pattern 0 always resides in the
* lower half (least significant 64 bits) of a 128 bit word
* and pattern 1 the upper half. If you examine the data of
@@ -1106,50 +1123,54 @@ static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
* (128 bits) which is the maximum cursor width times two for
* the two monochrome patterns.
*/
- u8 *cursorbase = (u8 *) info->cursor.image.data;
- char *bitmap = (char *)cursor->image.data;
- char *mask = (char *) cursor->mask;
- int i, j, k, h = 0;
-
- for (i = 0; i < 64; i++) {
- if (i < cursor->image.height) {
- j = (cursor->image.width + 7) >> 3;
- k = 8 - j;
-
- for (;j > 0; j--) {
- /* Pattern 0. Copy the cursor bitmap to it */
- fb_writeb(*bitmap, cursorbase + h);
- bitmap++;
- /* Pattern 1. Copy the cursor mask to it */
- fb_writeb(*mask, cursorbase + h + 8);
- mask++;
- h++;
- }
- for (;k > 0; k--) {
- fb_writeb(0, cursorbase + h);
- fb_writeb(~0, cursorbase + h + 8);
- h++;
- }
- } else {
- fb_writel(0, cursorbase + h);
- fb_writel(0, cursorbase + h + 4);
- fb_writel(~0, cursorbase + h + 8);
- fb_writel(~0, cursorbase + h + 12);
- h += 16;
+ u8 __iomem *cursorbase = info->screen_base + info->fix.smem_len;
+ u8 *bitmap = (u8 *)cursor->image.data;
+ u8 *mask = (u8 *)cursor->mask;
+ int i;
+
+ fb_memset(cursorbase, 0, 1024);
+
+ for (i = 0; i < cursor->image.height; i++) {
+ int h = 0;
+ int j = (cursor->image.width + 7) >> 3;
+
+ for (; j > 0; j--) {
+ u8 data = *mask ^ *bitmap;
+ if (cursor->rop == ROP_COPY)
+ data = *mask & *bitmap;
+ /* Pattern 0. Copy the cursor mask to it */
+ fb_writeb(*mask, cursorbase + h);
+ mask++;
+ /* Pattern 1. Copy the cursor bitmap to it */
+ fb_writeb(data, cursorbase + h + 8);
+ bitmap++;
+ h++;
}
+ cursorbase += 16;
}
}
- /* Turn the cursor on */
- cursor->enable = 1;
- info->cursor = *cursor;
- mod_timer(&par->hwcursor.timer, jiffies+HZ/2);
- spin_lock_irqsave(&par->DAClock, flags);
- banshee_make_room(par, 1);
- tdfx_outl(par, VIDPROCCFG, par->hwcursor.enable);
- spin_unlock_irqrestore(&par->DAClock, flags);
return 0;
}
+
+static struct fb_ops tdfxfb_ops = {
+ .owner = THIS_MODULE,
+ .fb_check_var = tdfxfb_check_var,
+ .fb_set_par = tdfxfb_set_par,
+ .fb_setcolreg = tdfxfb_setcolreg,
+ .fb_blank = tdfxfb_blank,
+ .fb_pan_display = tdfxfb_pan_display,
+ .fb_sync = banshee_wait_idle,
+ .fb_cursor = tdfxfb_cursor,
+#ifdef CONFIG_FB_3DFX_ACCEL
+ .fb_fillrect = tdfxfb_fillrect,
+ .fb_copyarea = tdfxfb_copyarea,
+ .fb_imageblit = tdfxfb_imageblit,
+#else
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
#endif
+};
/**
* tdfxfb_probe - Device Initializiation
@@ -1161,14 +1182,15 @@ static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
*
*/
static int __devinit tdfxfb_probe(struct pci_dev *pdev,
- const struct pci_device_id *id)
+ const struct pci_device_id *id)
{
struct tdfx_par *default_par;
struct fb_info *info;
int err, lpitch;
- if ((err = pci_enable_device(pdev))) {
- printk(KERN_WARNING "tdfxfb: Can't enable pdev: %d\n", err);
+ err = pci_enable_device(pdev);
+ if (err) {
+ printk(KERN_ERR "tdfxfb: Can't enable pdev: %d\n", err);
return err;
}
@@ -1176,139 +1198,145 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
if (!info)
return -ENOMEM;
-
+
default_par = info->par;
-
+
/* Configure the default fb_fix_screeninfo first */
switch (pdev->device) {
- case PCI_DEVICE_ID_3DFX_BANSHEE:
- strcat(tdfx_fix.id, " Banshee");
- default_par->max_pixclock = BANSHEE_MAX_PIXCLOCK;
- break;
- case PCI_DEVICE_ID_3DFX_VOODOO3:
- strcat(tdfx_fix.id, " Voodoo3");
- default_par->max_pixclock = VOODOO3_MAX_PIXCLOCK;
- break;
- case PCI_DEVICE_ID_3DFX_VOODOO5:
- strcat(tdfx_fix.id, " Voodoo5");
- default_par->max_pixclock = VOODOO5_MAX_PIXCLOCK;
- break;
+ case PCI_DEVICE_ID_3DFX_BANSHEE:
+ strcat(tdfx_fix.id, " Banshee");
+ default_par->max_pixclock = BANSHEE_MAX_PIXCLOCK;
+ break;
+ case PCI_DEVICE_ID_3DFX_VOODOO3:
+ strcat(tdfx_fix.id, " Voodoo3");
+ default_par->max_pixclock = VOODOO3_MAX_PIXCLOCK;
+ break;
+ case PCI_DEVICE_ID_3DFX_VOODOO5:
+ strcat(tdfx_fix.id, " Voodoo5");
+ default_par->max_pixclock = VOODOO5_MAX_PIXCLOCK;
+ break;
}
tdfx_fix.mmio_start = pci_resource_start(pdev, 0);
tdfx_fix.mmio_len = pci_resource_len(pdev, 0);
- default_par->regbase_virt = ioremap_nocache(tdfx_fix.mmio_start, tdfx_fix.mmio_len);
- if (!default_par->regbase_virt) {
- printk("fb: Can't remap %s register area.\n", tdfx_fix.id);
+ if (!request_mem_region(tdfx_fix.mmio_start, tdfx_fix.mmio_len,
+ "tdfx regbase")) {
+ printk(KERN_ERR "tdfxfb: Can't reserve regbase\n");
goto out_err;
}
-
- if (!request_mem_region(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0), "tdfx regbase")) {
- printk(KERN_WARNING "tdfxfb: Can't reserve regbase\n");
- goto out_err;
- }
+
+ default_par->regbase_virt =
+ ioremap_nocache(tdfx_fix.mmio_start, tdfx_fix.mmio_len);
+ if (!default_par->regbase_virt) {
+ printk(KERN_ERR "fb: Can't remap %s register area.\n",
+ tdfx_fix.id);
+ goto out_err_regbase;
+ }
tdfx_fix.smem_start = pci_resource_start(pdev, 1);
- if (!(tdfx_fix.smem_len = do_lfb_size(default_par, pdev->device))) {
- printk("fb: Can't count %s memory.\n", tdfx_fix.id);
- release_mem_region(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
- goto out_err;
+ tdfx_fix.smem_len = do_lfb_size(default_par, pdev->device);
+ if (!tdfx_fix.smem_len) {
+ printk(KERN_ERR "fb: Can't count %s memory.\n", tdfx_fix.id);
+ goto out_err_regbase;
}
- if (!request_mem_region(pci_resource_start(pdev, 1),
- pci_resource_len(pdev, 1), "tdfx smem")) {
- printk(KERN_WARNING "tdfxfb: Can't reserve smem\n");
- release_mem_region(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
- goto out_err;
+ if (!request_mem_region(tdfx_fix.smem_start,
+ pci_resource_len(pdev, 1), "tdfx smem")) {
+ printk(KERN_ERR "tdfxfb: Can't reserve smem\n");
+ goto out_err_regbase;
}
- info->screen_base = ioremap_nocache(tdfx_fix.smem_start,
+ info->screen_base = ioremap_nocache(tdfx_fix.smem_start,
tdfx_fix.smem_len);
if (!info->screen_base) {
- printk("fb: Can't remap %s framebuffer.\n", tdfx_fix.id);
- release_mem_region(pci_resource_start(pdev, 1),
- pci_resource_len(pdev, 1));
- release_mem_region(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
- goto out_err;
+ printk(KERN_ERR "fb: Can't remap %s framebuffer.\n",
+ tdfx_fix.id);
+ goto out_err_screenbase;
}
default_par->iobase = pci_resource_start(pdev, 2);
-
+
if (!request_region(pci_resource_start(pdev, 2),
- pci_resource_len(pdev, 2), "tdfx iobase")) {
- printk(KERN_WARNING "tdfxfb: Can't reserve iobase\n");
- release_mem_region(pci_resource_start(pdev, 1),
- pci_resource_len(pdev, 1));
- release_mem_region(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
- goto out_err;
+ pci_resource_len(pdev, 2), "tdfx iobase")) {
+ printk(KERN_ERR "tdfxfb: Can't reserve iobase\n");
+ goto out_err_screenbase;
}
- printk("fb: %s memory = %dK\n", tdfx_fix.id, tdfx_fix.smem_len >> 10);
+ printk(KERN_INFO "fb: %s memory = %dK\n", tdfx_fix.id,
+ tdfx_fix.smem_len >> 10);
+
+ default_par->mtrr_handle = -1;
+ if (!nomtrr)
+ default_par->mtrr_handle =
+ mtrr_add(tdfx_fix.smem_start, tdfx_fix.smem_len,
+ MTRR_TYPE_WRCOMB, 1);
tdfx_fix.ypanstep = nopan ? 0 : 1;
tdfx_fix.ywrapstep = nowrap ? 0 : 1;
-
+
info->fbops = &tdfxfb_ops;
- info->fix = tdfx_fix;
+ info->fix = tdfx_fix;
info->pseudo_palette = default_par->palette;
info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
#ifdef CONFIG_FB_3DFX_ACCEL
- info->flags |= FBINFO_HWACCEL_FILLRECT |
- FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_IMAGEBLIT;
+ info->flags |= FBINFO_HWACCEL_FILLRECT |
+ FBINFO_HWACCEL_COPYAREA |
+ FBINFO_HWACCEL_IMAGEBLIT |
+ FBINFO_READS_FAST;
#endif
+ /* reserve 8192 bits for cursor */
+ /* the 2.4 driver says PAGE_MASK boundary is not enough for Voodoo4 */
+ if (hwcursor)
+ info->fix.smem_len = (info->fix.smem_len - 1024) &
+ (PAGE_MASK << 1);
if (!mode_option)
mode_option = "640x480@60";
-
- err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
+
+ err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
if (!err || err == 4)
info->var = tdfx_var;
/* maximize virtual vertical length */
lpitch = info->var.xres_virtual * ((info->var.bits_per_pixel + 7) >> 3);
- info->var.yres_virtual = info->fix.smem_len/lpitch;
+ info->var.yres_virtual = info->fix.smem_len / lpitch;
if (info->var.yres_virtual < info->var.yres)
- goto out_err;
-
-#ifdef CONFIG_FB_3DFX_ACCEL
- /*
- * FIXME: Limit var->yres_virtual to 4096 because of screen artifacts
- * during scrolling. This is only present if 2D acceleration is
- * enabled.
- */
- if (info->var.yres_virtual > 4096)
- info->var.yres_virtual = 4096;
-#endif /* CONFIG_FB_3DFX_ACCEL */
+ goto out_err_iobase;
if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
- printk(KERN_WARNING "tdfxfb: Can't allocate color map\n");
- goto out_err;
+ printk(KERN_ERR "tdfxfb: Can't allocate color map\n");
+ goto out_err_iobase;
}
if (register_framebuffer(info) < 0) {
- printk("tdfxfb: can't register framebuffer\n");
+ printk(KERN_ERR "tdfxfb: can't register framebuffer\n");
fb_dealloc_cmap(&info->cmap);
- goto out_err;
+ goto out_err_iobase;
}
/*
* Our driver data
*/
pci_set_drvdata(pdev, info);
- return 0;
+ return 0;
-out_err:
+out_err_iobase:
+ if (default_par->mtrr_handle >= 0)
+ mtrr_del(default_par->mtrr_handle, info->fix.smem_start,
+ info->fix.smem_len);
+ release_mem_region(pci_resource_start(pdev, 2),
+ pci_resource_len(pdev, 2));
+out_err_screenbase:
+ if (info->screen_base)
+ iounmap(info->screen_base);
+ release_mem_region(tdfx_fix.smem_start, pci_resource_len(pdev, 1));
+out_err_regbase:
/*
* Cleanup after anything that was remapped/allocated.
*/
if (default_par->regbase_virt)
iounmap(default_par->regbase_virt);
- if (info->screen_base)
- iounmap(info->screen_base);
+ release_mem_region(tdfx_fix.mmio_start, tdfx_fix.mmio_len);
+out_err:
framebuffer_release(info);
return -ENXIO;
}
@@ -1316,7 +1344,7 @@ out_err:
#ifndef MODULE
static void tdfxfb_setup(char *options)
{
- char* this_opt;
+ char *this_opt;
if (!options || !*options)
return;
@@ -1324,10 +1352,16 @@ static void tdfxfb_setup(char *options)
while ((this_opt = strsep(&options, ",")) != NULL) {
if (!*this_opt)
continue;
- if(!strcmp(this_opt, "nopan")) {
+ if (!strcmp(this_opt, "nopan")) {
nopan = 1;
- } else if(!strcmp(this_opt, "nowrap")) {
+ } else if (!strcmp(this_opt, "nowrap")) {
nowrap = 1;
+ } else if (!strncmp(this_opt, "hwcursor=", 9)) {
+ hwcursor = simple_strtoul(this_opt + 9, NULL, 0);
+#ifdef CONFIG_MTRR
+ } else if (!strncmp(this_opt, "nomtrr", 6)) {
+ nomtrr = 1;
+#endif
} else {
mode_option = this_opt;
}
@@ -1350,6 +1384,9 @@ static void __devexit tdfxfb_remove(struct pci_dev *pdev)
struct tdfx_par *par = info->par;
unregister_framebuffer(info);
+ if (par->mtrr_handle >= 0)
+ mtrr_del(par->mtrr_handle, info->fix.smem_start,
+ info->fix.smem_len);
iounmap(par->regbase_virt);
iounmap(info->screen_base);
@@ -1374,17 +1411,25 @@ static int __init tdfxfb_init(void)
tdfxfb_setup(option);
#endif
- return pci_register_driver(&tdfxfb_driver);
+ return pci_register_driver(&tdfxfb_driver);
}
static void __exit tdfxfb_exit(void)
{
- pci_unregister_driver(&tdfxfb_driver);
+ pci_unregister_driver(&tdfxfb_driver);
}
MODULE_AUTHOR("Hannu Mallat <hmallat@cc.hut.fi>");
MODULE_DESCRIPTION("3Dfx framebuffer device driver");
MODULE_LICENSE("GPL");
-
+
+module_param(hwcursor, int, 0644);
+MODULE_PARM_DESC(hwcursor, "Enable hardware cursor "
+ "(1=enable, 0=disable, default=1)");
+#ifdef CONFIG_MTRR
+module_param(nomtrr, bool, 0);
+MODULE_PARM_DESC(nomtrr, "Disable MTRR support (default: enabled)");
+#endif
+
module_init(tdfxfb_init);
module_exit(tdfxfb_exit);
diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c
index d292a37ec7d6..680642c089c9 100644
--- a/drivers/video/tgafb.c
+++ b/drivers/video/tgafb.c
@@ -5,7 +5,7 @@
* Copyright (C) 1997 Geert Uytterhoeven
* Copyright (C) 1999,2000 Martin Lucina, Tom Zerucha
* Copyright (C) 2002 Richard Henderson
- * Copyright (C) 2006 Maciej W. Rozycki
+ * Copyright (C) 2006, 2007 Maciej W. Rozycki
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
@@ -13,6 +13,7 @@
*/
#include <linux/bitrev.h>
+#include <linux/compiler.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/errno.h>
@@ -636,15 +637,6 @@ tgafb_mono_imageblit(struct fb_info *info, const struct fb_image *image)
is8bpp = info->var.bits_per_pixel == 8;
- /* For copies that aren't pixel expansion, there's little we
- can do better than the generic code. */
- /* ??? There is a DMA write mode; I wonder if that could be
- made to pull the data from the image buffer... */
- if (image->depth > 1) {
- cfb_imageblit(info, image);
- return;
- }
-
dx = image->dx;
dy = image->dy;
width = image->width;
@@ -654,6 +646,9 @@ tgafb_mono_imageblit(struct fb_info *info, const struct fb_image *image)
line_length = info->fix.line_length;
rincr = (width + 7) / 8;
+ /* A shift below cannot cope with. */
+ if (unlikely(width == 0))
+ return;
/* Crop the image to the screen. */
if (dx > vxres || dy > vyres)
return;
@@ -709,9 +704,10 @@ tgafb_mono_imageblit(struct fb_info *info, const struct fb_image *image)
unsigned long bwidth;
/* Handle common case of imaging a single character, in
- a font less than 32 pixels wide. */
+ a font less than or 32 pixels wide. */
- pixelmask = (1 << width) - 1;
+ /* Avoid a shift by 32; width > 0 implied. */
+ pixelmask = (2ul << (width - 1)) - 1;
pixelmask <<= shift;
__raw_writel(pixelmask, regs_base + TGA_PIXELMASK_REG);
wmb();
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c
index c699864b6f4a..70fb4ee2b421 100644
--- a/drivers/video/tridentfb.c
+++ b/drivers/video/tridentfb.c
@@ -1,18 +1,19 @@
/*
* Frame buffer driver for Trident Blade and Image series
*
- * Copyright 2001,2002 - Jani Monoses <jani@iv.ro>
+ * Copyright 2001, 2002 - Jani Monoses <jani@iv.ro>
*
*
* CREDITS:(in order of appearance)
- * skeletonfb.c by Geert Uytterhoeven and other fb code in drivers/video
- * Special thanks ;) to Mattia Crivellini <tia@mclink.it>
- * much inspired by the XFree86 4.x Trident driver sources by Alan Hourihane
- * the FreeVGA project
- * Francesco Salvestrini <salvestrini@users.sf.net> XP support,code,suggestions
+ * skeletonfb.c by Geert Uytterhoeven and other fb code in drivers/video
+ * Special thanks ;) to Mattia Crivellini <tia@mclink.it>
+ * much inspired by the XFree86 4.x Trident driver sources
+ * by Alan Hourihane the FreeVGA project
+ * Francesco Salvestrini <salvestrini@users.sf.net> XP support,
+ * code, suggestions
* TODO:
- * timing value tweaking so it looks good on every monitor in every mode
- * TGUI acceleration
+ * timing value tweaking so it looks good on every monitor in every mode
+ * TGUI acceleration
*/
#include <linux/module.h>
@@ -26,11 +27,11 @@
#define VERSION "0.7.8-NEWAPI"
struct tridentfb_par {
- int vclk; //in MHz
- void __iomem * io_virt; //iospace virtual memory address
+ int vclk; /* in MHz */
+ void __iomem *io_virt; /* iospace virtual memory address */
};
-static unsigned char eng_oper; //engine operation...
+static unsigned char eng_oper; /* engine operation... */
static struct fb_ops tridentfb_ops;
static struct tridentfb_par default_par;
@@ -39,11 +40,10 @@ static struct tridentfb_par default_par;
static struct fb_info fb_info;
static u32 pseudo_pal[16];
-
static struct fb_var_screeninfo default_var;
static struct fb_fix_screeninfo tridentfb_fix = {
- .id = "Trident",
+ .id = "Trident",
.type = FB_TYPE_PACKED_PIXELS,
.ypanstep = 1,
.visual = FB_VISUAL_PSEUDOCOLOR,
@@ -55,11 +55,10 @@ static int chip_id;
static int defaultaccel;
static int displaytype;
-
/* defaults which are normally overriden by user values */
/* video mode */
-static char * mode = "640x480";
+static char *mode = "640x480";
static int bpp = 8;
static int noaccel;
@@ -74,7 +73,6 @@ static int memsize;
static int memdiff;
static int nativex;
-
module_param(mode, charp, 0);
module_param(bpp, int, 0);
module_param(center, int, 0);
@@ -86,88 +84,85 @@ module_param(nativex, int, 0);
module_param(fp, int, 0);
module_param(crt, int, 0);
-
static int chip3D;
static int chipcyber;
static int is3Dchip(int id)
{
- return ((id == BLADE3D) || (id == CYBERBLADEE4) ||
- (id == CYBERBLADEi7) || (id == CYBERBLADEi7D) ||
- (id == CYBER9397) || (id == CYBER9397DVD) ||
- (id == CYBER9520) || (id == CYBER9525DVD) ||
- (id == IMAGE975) || (id == IMAGE985) ||
- (id == CYBERBLADEi1) || (id == CYBERBLADEi1D) ||
- (id == CYBERBLADEAi1) || (id == CYBERBLADEAi1D) ||
- (id == CYBERBLADEXPm8) || (id == CYBERBLADEXPm16) ||
- (id == CYBERBLADEXPAi1));
+ return ((id == BLADE3D) || (id == CYBERBLADEE4) ||
+ (id == CYBERBLADEi7) || (id == CYBERBLADEi7D) ||
+ (id == CYBER9397) || (id == CYBER9397DVD) ||
+ (id == CYBER9520) || (id == CYBER9525DVD) ||
+ (id == IMAGE975) || (id == IMAGE985) ||
+ (id == CYBERBLADEi1) || (id == CYBERBLADEi1D) ||
+ (id == CYBERBLADEAi1) || (id == CYBERBLADEAi1D) ||
+ (id == CYBERBLADEXPm8) || (id == CYBERBLADEXPm16) ||
+ (id == CYBERBLADEXPAi1));
}
static int iscyber(int id)
{
switch (id) {
- case CYBER9388:
- case CYBER9382:
- case CYBER9385:
- case CYBER9397:
- case CYBER9397DVD:
- case CYBER9520:
- case CYBER9525DVD:
- case CYBERBLADEE4:
- case CYBERBLADEi7D:
- case CYBERBLADEi1:
- case CYBERBLADEi1D:
- case CYBERBLADEAi1:
- case CYBERBLADEAi1D:
- case CYBERBLADEXPAi1:
- return 1;
-
- case CYBER9320:
- case TGUI9660:
- case IMAGE975:
- case IMAGE985:
- case BLADE3D:
- case CYBERBLADEi7: /* VIA MPV4 integrated version */
+ case CYBER9388:
+ case CYBER9382:
+ case CYBER9385:
+ case CYBER9397:
+ case CYBER9397DVD:
+ case CYBER9520:
+ case CYBER9525DVD:
+ case CYBERBLADEE4:
+ case CYBERBLADEi7D:
+ case CYBERBLADEi1:
+ case CYBERBLADEi1D:
+ case CYBERBLADEAi1:
+ case CYBERBLADEAi1D:
+ case CYBERBLADEXPAi1:
+ return 1;
- default:
- /* case CYBERBLDAEXPm8: Strange */
- /* case CYBERBLDAEXPm16: Strange */
- return 0;
+ case CYBER9320:
+ case TGUI9660:
+ case IMAGE975:
+ case IMAGE985:
+ case BLADE3D:
+ case CYBERBLADEi7: /* VIA MPV4 integrated version */
+
+ default:
+ /* case CYBERBLDAEXPm8: Strange */
+ /* case CYBERBLDAEXPm16: Strange */
+ return 0;
}
}
-#define CRT 0x3D0 //CRTC registers offset for color display
+#define CRT 0x3D0 /* CRTC registers offset for color display */
#ifndef TRIDENT_MMIO
#define TRIDENT_MMIO 1
#endif
#if TRIDENT_MMIO
- #define t_outb(val,reg) writeb(val,((struct tridentfb_par *)(fb_info.par))->io_virt + reg)
+ #define t_outb(val, reg) writeb(val,((struct tridentfb_par *)(fb_info.par))->io_virt + reg)
#define t_inb(reg) readb(((struct tridentfb_par*)(fb_info.par))->io_virt + reg)
#else
- #define t_outb(val,reg) outb(val,reg)
+ #define t_outb(val, reg) outb(val, reg)
#define t_inb(reg) inb(reg)
#endif
static struct accel_switch {
- void (*init_accel)(int,int);
- void (*wait_engine)(void);
- void (*fill_rect)(__u32,__u32,__u32,__u32,__u32,__u32);
- void (*copy_rect)(__u32,__u32,__u32,__u32,__u32,__u32);
+ void (*init_accel) (int, int);
+ void (*wait_engine) (void);
+ void (*fill_rect) (u32, u32, u32, u32, u32, u32);
+ void (*copy_rect) (u32, u32, u32, u32, u32, u32);
} *acc;
-#define writemmr(r,v) writel(v, ((struct tridentfb_par *)fb_info.par)->io_virt + r)
+#define writemmr(r, v) writel(v, ((struct tridentfb_par *)fb_info.par)->io_virt + r)
#define readmmr(r) readl(((struct tridentfb_par *)fb_info.par)->io_virt + r)
-
-
/*
* Blade specific acceleration.
*/
-#define point(x,y) ((y)<<16|(x))
+#define point(x, y) ((y) << 16 | (x))
#define STA 0x2120
#define CMD 0x2144
#define ROP 0x2148
@@ -179,64 +174,71 @@ static struct accel_switch {
#define ROP_S 0xCC
-static void blade_init_accel(int pitch,int bpp)
+static void blade_init_accel(int pitch, int bpp)
{
- int v1 = (pitch>>3)<<20;
- int tmp = 0,v2;
+ int v1 = (pitch >> 3) << 20;
+ int tmp = 0, v2;
switch (bpp) {
- case 8:tmp = 0;break;
- case 15:tmp = 5;break;
- case 16:tmp = 1;break;
- case 24:
- case 32:tmp = 2;break;
+ case 8:
+ tmp = 0;
+ break;
+ case 15:
+ tmp = 5;
+ break;
+ case 16:
+ tmp = 1;
+ break;
+ case 24:
+ case 32:
+ tmp = 2;
+ break;
}
- v2 = v1 | (tmp<<29);
- writemmr(0x21C0,v2);
- writemmr(0x21C4,v2);
- writemmr(0x21B8,v2);
- writemmr(0x21BC,v2);
- writemmr(0x21D0,v1);
- writemmr(0x21D4,v1);
- writemmr(0x21C8,v1);
- writemmr(0x21CC,v1);
- writemmr(0x216C,0);
+ v2 = v1 | (tmp << 29);
+ writemmr(0x21C0, v2);
+ writemmr(0x21C4, v2);
+ writemmr(0x21B8, v2);
+ writemmr(0x21BC, v2);
+ writemmr(0x21D0, v1);
+ writemmr(0x21D4, v1);
+ writemmr(0x21C8, v1);
+ writemmr(0x21CC, v1);
+ writemmr(0x216C, 0);
}
static void blade_wait_engine(void)
{
- while(readmmr(STA) & 0xFA800000);
+ while (readmmr(STA) & 0xFA800000) ;
}
-static void blade_fill_rect(__u32 x,__u32 y,__u32 w,__u32 h,__u32 c,__u32 rop)
+static void blade_fill_rect(u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
{
- writemmr(CLR,c);
- writemmr(ROP,rop ? 0x66:ROP_S);
- writemmr(CMD,0x20000000|1<<19|1<<4|2<<2);
+ writemmr(CLR, c);
+ writemmr(ROP, rop ? 0x66 : ROP_S);
+ writemmr(CMD, 0x20000000 | 1 << 19 | 1 << 4 | 2 << 2);
- writemmr(DR1,point(x,y));
- writemmr(DR2,point(x+w-1,y+h-1));
+ writemmr(DR1, point(x, y));
+ writemmr(DR2, point(x + w - 1, y + h - 1));
}
-static void blade_copy_rect(__u32 x1,__u32 y1,__u32 x2,__u32 y2,__u32 w,__u32 h)
+static void blade_copy_rect(u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
{
- __u32 s1,s2,d1,d2;
+ u32 s1, s2, d1, d2;
int direction = 2;
- s1 = point(x1,y1);
- s2 = point(x1+w-1,y1+h-1);
- d1 = point(x2,y2);
- d2 = point(x2+w-1,y2+h-1);
+ s1 = point(x1, y1);
+ s2 = point(x1 + w - 1, y1 + h - 1);
+ d1 = point(x2, y2);
+ d2 = point(x2 + w - 1, y2 + h - 1);
if ((y1 > y2) || ((y1 == y2) && (x1 > x2)))
- direction = 0;
-
+ direction = 0;
- writemmr(ROP,ROP_S);
- writemmr(CMD,0xE0000000|1<<19|1<<4|1<<2|direction);
+ writemmr(ROP, ROP_S);
+ writemmr(CMD, 0xE0000000 | 1 << 19 | 1 << 4 | 1 << 2 | direction);
- writemmr(SR1,direction?s2:s1);
- writemmr(SR2,direction?s1:s2);
- writemmr(DR1,direction?d2:d1);
- writemmr(DR2,direction?d1:d2);
+ writemmr(SR1, direction ? s2 : s1);
+ writemmr(SR2, direction ? s1 : s2);
+ writemmr(DR1, direction ? d2 : d1);
+ writemmr(DR2, direction ? d1 : d2);
}
static struct accel_switch accel_blade = {
@@ -246,51 +248,72 @@ static struct accel_switch accel_blade = {
blade_copy_rect,
};
-
/*
* BladeXP specific acceleration functions
*/
#define ROP_P 0xF0
-#define masked_point(x,y) ((y & 0xffff)<<16|(x & 0xffff))
+#define masked_point(x, y) ((y & 0xffff)<<16|(x & 0xffff))
-static void xp_init_accel(int pitch,int bpp)
+static void xp_init_accel(int pitch, int bpp)
{
- int tmp = 0,v1;
+ int tmp = 0, v1;
unsigned char x = 0;
switch (bpp) {
- case 8: x = 0; break;
- case 16: x = 1; break;
- case 24: x = 3; break;
- case 32: x = 2; break;
+ case 8:
+ x = 0;
+ break;
+ case 16:
+ x = 1;
+ break;
+ case 24:
+ x = 3;
+ break;
+ case 32:
+ x = 2;
+ break;
}
switch (pitch << (bpp >> 3)) {
- case 8192:
- case 512: x |= 0x00; break;
- case 1024: x |= 0x04; break;
- case 2048: x |= 0x08; break;
- case 4096: x |= 0x0C; break;
+ case 8192:
+ case 512:
+ x |= 0x00;
+ break;
+ case 1024:
+ x |= 0x04;
+ break;
+ case 2048:
+ x |= 0x08;
+ break;
+ case 4096:
+ x |= 0x0C;
+ break;
}
- t_outb(x,0x2125);
+ t_outb(x, 0x2125);
eng_oper = x | 0x40;
switch (bpp) {
- case 8: tmp = 18; break;
- case 15:
- case 16: tmp = 19; break;
- case 24:
- case 32: tmp = 20; break;
+ case 8:
+ tmp = 18;
+ break;
+ case 15:
+ case 16:
+ tmp = 19;
+ break;
+ case 24:
+ case 32:
+ tmp = 20;
+ break;
}
v1 = pitch << tmp;
- writemmr(0x2154,v1);
- writemmr(0x2150,v1);
- t_outb(3,0x2126);
+ writemmr(0x2154, v1);
+ writemmr(0x2150, v1);
+ t_outb(3, 0x2126);
}
static void xp_wait_engine(void)
@@ -318,24 +341,24 @@ static void xp_wait_engine(void)
}
}
-static void xp_fill_rect(__u32 x,__u32 y,__u32 w,__u32 h,__u32 c,__u32 rop)
+static void xp_fill_rect(u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
{
- writemmr(0x2127,ROP_P);
- writemmr(0x2158,c);
- writemmr(0x2128,0x4000);
- writemmr(0x2140,masked_point(h,w));
- writemmr(0x2138,masked_point(y,x));
- t_outb(0x01,0x2124);
- t_outb(eng_oper,0x2125);
+ writemmr(0x2127, ROP_P);
+ writemmr(0x2158, c);
+ writemmr(0x2128, 0x4000);
+ writemmr(0x2140, masked_point(h, w));
+ writemmr(0x2138, masked_point(y, x));
+ t_outb(0x01, 0x2124);
+ t_outb(eng_oper, 0x2125);
}
-static void xp_copy_rect(__u32 x1,__u32 y1,__u32 x2,__u32 y2,__u32 w,__u32 h)
+static void xp_copy_rect(u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
{
int direction;
- __u32 x1_tmp, x2_tmp, y1_tmp, y2_tmp;
+ u32 x1_tmp, x2_tmp, y1_tmp, y2_tmp;
direction = 0x0004;
-
+
if ((x1 < x2) && (y1 == y2)) {
direction |= 0x0200;
x1_tmp = x1 + w - 1;
@@ -344,53 +367,60 @@ static void xp_copy_rect(__u32 x1,__u32 y1,__u32 x2,__u32 y2,__u32 w,__u32 h)
x1_tmp = x1;
x2_tmp = x2;
}
-
+
if (y1 < y2) {
direction |= 0x0100;
y1_tmp = y1 + h - 1;
y2_tmp = y2 + h - 1;
- } else {
+ } else {
y1_tmp = y1;
y2_tmp = y2;
}
- writemmr(0x2128,direction);
- t_outb(ROP_S,0x2127);
- writemmr(0x213C,masked_point(y1_tmp,x1_tmp));
- writemmr(0x2138,masked_point(y2_tmp,x2_tmp));
- writemmr(0x2140,masked_point(h,w));
- t_outb(0x01,0x2124);
+ writemmr(0x2128, direction);
+ t_outb(ROP_S, 0x2127);
+ writemmr(0x213C, masked_point(y1_tmp, x1_tmp));
+ writemmr(0x2138, masked_point(y2_tmp, x2_tmp));
+ writemmr(0x2140, masked_point(h, w));
+ t_outb(0x01, 0x2124);
}
static struct accel_switch accel_xp = {
- xp_init_accel,
+ xp_init_accel,
xp_wait_engine,
xp_fill_rect,
xp_copy_rect,
};
-
/*
* Image specific acceleration functions
*/
-static void image_init_accel(int pitch,int bpp)
+static void image_init_accel(int pitch, int bpp)
{
int tmp = 0;
- switch (bpp) {
- case 8:tmp = 0;break;
- case 15:tmp = 5;break;
- case 16:tmp = 1;break;
- case 24:
- case 32:tmp = 2;break;
+ switch (bpp) {
+ case 8:
+ tmp = 0;
+ break;
+ case 15:
+ tmp = 5;
+ break;
+ case 16:
+ tmp = 1;
+ break;
+ case 24:
+ case 32:
+ tmp = 2;
+ break;
}
writemmr(0x2120, 0xF0000000);
- writemmr(0x2120, 0x40000000|tmp);
+ writemmr(0x2120, 0x40000000 | tmp);
writemmr(0x2120, 0x80000000);
writemmr(0x2144, 0x00000000);
writemmr(0x2148, 0x00000000);
writemmr(0x2150, 0x00000000);
writemmr(0x2154, 0x00000000);
- writemmr(0x2120, 0x60000000|(pitch<<16) |pitch);
+ writemmr(0x2120, 0x60000000 | (pitch << 16) | pitch);
writemmr(0x216C, 0x00000000);
writemmr(0x2170, 0x00000000);
writemmr(0x217C, 0x00000000);
@@ -400,44 +430,43 @@ static void image_init_accel(int pitch,int bpp)
static void image_wait_engine(void)
{
- while(readmmr(0x2164) & 0xF0000000);
+ while (readmmr(0x2164) & 0xF0000000) ;
}
-static void image_fill_rect(__u32 x, __u32 y, __u32 w, __u32 h, __u32 c, __u32 rop)
+static void image_fill_rect(u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
{
- writemmr(0x2120,0x80000000);
- writemmr(0x2120,0x90000000|ROP_S);
+ writemmr(0x2120, 0x80000000);
+ writemmr(0x2120, 0x90000000 | ROP_S);
- writemmr(0x2144,c);
+ writemmr(0x2144, c);
- writemmr(DR1,point(x,y));
- writemmr(DR2,point(x+w-1,y+h-1));
+ writemmr(DR1, point(x, y));
+ writemmr(DR2, point(x + w - 1, y + h - 1));
- writemmr(0x2124,0x80000000|3<<22|1<<10|1<<9);
+ writemmr(0x2124, 0x80000000 | 3 << 22 | 1 << 10 | 1 << 9);
}
-static void image_copy_rect(__u32 x1,__u32 y1,__u32 x2,__u32 y2,__u32 w,__u32 h)
+static void image_copy_rect(u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
{
- __u32 s1,s2,d1,d2;
+ u32 s1, s2, d1, d2;
int direction = 2;
- s1 = point(x1,y1);
- s2 = point(x1+w-1,y1+h-1);
- d1 = point(x2,y2);
- d2 = point(x2+w-1,y2+h-1);
-
- if ((y1 > y2) || ((y1 == y2) && (x1 >x2)))
- direction = 0;
-
- writemmr(0x2120,0x80000000);
- writemmr(0x2120,0x90000000|ROP_S);
-
- writemmr(SR1,direction?s2:s1);
- writemmr(SR2,direction?s1:s2);
- writemmr(DR1,direction?d2:d1);
- writemmr(DR2,direction?d1:d2);
- writemmr(0x2124,0x80000000|1<<22|1<<10|1<<7|direction);
-}
+ s1 = point(x1, y1);
+ s2 = point(x1 + w - 1, y1 + h - 1);
+ d1 = point(x2, y2);
+ d2 = point(x2 + w - 1, y2 + h - 1);
+ if ((y1 > y2) || ((y1 == y2) && (x1 > x2)))
+ direction = 0;
+
+ writemmr(0x2120, 0x80000000);
+ writemmr(0x2120, 0x90000000 | ROP_S);
+
+ writemmr(SR1, direction ? s2 : s1);
+ writemmr(SR2, direction ? s1 : s2);
+ writemmr(DR1, direction ? d2 : d1);
+ writemmr(DR2, direction ? d1 : d2);
+ writemmr(0x2124, 0x80000000 | 1 << 22 | 1 << 10 | 1 << 7 | direction);
+}
static struct accel_switch accel_image = {
image_init_accel,
@@ -450,30 +479,34 @@ static struct accel_switch accel_image = {
* Accel functions called by the upper layers
*/
#ifdef CONFIG_FB_TRIDENT_ACCEL
-static void tridentfb_fillrect(struct fb_info * info, const struct fb_fillrect *fr)
+static void tridentfb_fillrect(struct fb_info *info,
+ const struct fb_fillrect *fr)
{
int bpp = info->var.bits_per_pixel;
int col = 0;
-
+
switch (bpp) {
- default:
- case 8: col |= fr->color;
- col |= col << 8;
- col |= col << 16;
- break;
- case 16: col = ((u32 *)(info->pseudo_palette))[fr->color];
-
- break;
- case 32: col = ((u32 *)(info->pseudo_palette))[fr->color];
- break;
- }
-
+ default:
+ case 8:
+ col |= fr->color;
+ col |= col << 8;
+ col |= col << 16;
+ break;
+ case 16:
+ col = ((u32 *)(info->pseudo_palette))[fr->color];
+ break;
+ case 32:
+ col = ((u32 *)(info->pseudo_palette))[fr->color];
+ break;
+ }
+
acc->fill_rect(fr->dx, fr->dy, fr->width, fr->height, col, fr->rop);
acc->wait_engine();
}
-static void tridentfb_copyarea(struct fb_info *info, const struct fb_copyarea *ca)
+static void tridentfb_copyarea(struct fb_info *info,
+ const struct fb_copyarea *ca)
{
- acc->copy_rect(ca->sx,ca->sy,ca->dx,ca->dy,ca->width,ca->height);
+ acc->copy_rect(ca->sx, ca->sy, ca->dx, ca->dy, ca->width, ca->height);
acc->wait_engine();
}
#else /* !CONFIG_FB_TRIDENT_ACCEL */
@@ -488,14 +521,14 @@ static void tridentfb_copyarea(struct fb_info *info, const struct fb_copyarea *c
static inline unsigned char read3X4(int reg)
{
- struct tridentfb_par * par = (struct tridentfb_par *)fb_info.par;
+ struct tridentfb_par *par = (struct tridentfb_par *)fb_info.par;
writeb(reg, par->io_virt + CRT + 4);
- return readb( par->io_virt + CRT + 5);
+ return readb(par->io_virt + CRT + 5);
}
static inline void write3X4(int reg, unsigned char val)
{
- struct tridentfb_par * par = (struct tridentfb_par *)fb_info.par;
+ struct tridentfb_par *par = (struct tridentfb_par *)fb_info.par;
writeb(reg, par->io_virt + CRT + 4);
writeb(val, par->io_virt + CRT + 5);
}
@@ -520,7 +553,7 @@ static inline unsigned char read3CE(int reg)
static inline void writeAttr(int reg, unsigned char val)
{
- readb(((struct tridentfb_par *)fb_info.par)->io_virt + CRT + 0x0A); //flip-flop to index
+ readb(((struct tridentfb_par *)fb_info.par)->io_virt + CRT + 0x0A); /* flip-flop to index */
t_outb(reg, 0x3C0);
t_outb(val, 0x3C0);
}
@@ -540,32 +573,41 @@ static inline void enable_mmio(void)
/* Unprotect registers */
outb(NewMode1, 0x3C4);
outb(0x80, 0x3C5);
-
+
/* Enable MMIO */
- outb(PCIReg, 0x3D4);
+ outb(PCIReg, 0x3D4);
outb(inb(0x3D5) | 0x01, 0x3D5);
}
-
#define crtc_unlock() write3X4(CRTVSyncEnd, read3X4(CRTVSyncEnd) & 0x7F)
/* Return flat panel's maximum x resolution */
static int __devinit get_nativex(void)
{
- int x,y,tmp;
+ int x, y, tmp;
if (nativex)
return nativex;
- tmp = (read3CE(VertStretch) >> 4) & 3;
+ tmp = (read3CE(VertStretch) >> 4) & 3;
switch (tmp) {
- case 0: x = 1280; y = 1024; break;
- case 2: x = 1024; y = 768; break;
- case 3: x = 800; y = 600; break;
- case 4: x = 1400; y = 1050; break;
- case 1:
- default:x = 640; y = 480; break;
+ case 0:
+ x = 1280; y = 1024;
+ break;
+ case 2:
+ x = 1024; y = 768;
+ break;
+ case 3:
+ x = 800; y = 600;
+ break;
+ case 4:
+ x = 1400; y = 1050;
+ break;
+ case 1:
+ default:
+ x = 640; y = 480;
+ break;
}
output("%dx%d flat panel found\n", x, y);
@@ -576,25 +618,26 @@ static int __devinit get_nativex(void)
static void set_lwidth(int width)
{
write3X4(Offset, width & 0xFF);
- write3X4(AddColReg, (read3X4(AddColReg) & 0xCF) | ((width & 0x300) >>4));
+ write3X4(AddColReg,
+ (read3X4(AddColReg) & 0xCF) | ((width & 0x300) >> 4));
}
/* For resolutions smaller than FP resolution stretch */
static void screen_stretch(void)
{
- if (chip_id != CYBERBLADEXPAi1)
- write3CE(BiosReg,0);
- else
- write3CE(BiosReg,8);
- write3CE(VertStretch,(read3CE(VertStretch) & 0x7C) | 1);
- write3CE(HorStretch,(read3CE(HorStretch) & 0x7C) | 1);
+ if (chip_id != CYBERBLADEXPAi1)
+ write3CE(BiosReg, 0);
+ else
+ write3CE(BiosReg, 8);
+ write3CE(VertStretch, (read3CE(VertStretch) & 0x7C) | 1);
+ write3CE(HorStretch, (read3CE(HorStretch) & 0x7C) | 1);
}
/* For resolutions smaller than FP resolution center */
static void screen_center(void)
{
- write3CE(VertStretch,(read3CE(VertStretch) & 0x7C) | 0x80);
- write3CE(HorStretch,(read3CE(HorStretch) & 0x7C) | 0x80);
+ write3CE(VertStretch, (read3CE(VertStretch) & 0x7C) | 0x80);
+ write3CE(HorStretch, (read3CE(HorStretch) & 0x7C) | 0x80);
}
/* Address of first shown pixel in display memory */
@@ -602,40 +645,42 @@ static void set_screen_start(int base)
{
write3X4(StartAddrLow, base & 0xFF);
write3X4(StartAddrHigh, (base & 0xFF00) >> 8);
- write3X4(CRTCModuleTest, (read3X4(CRTCModuleTest) & 0xDF) | ((base & 0x10000) >> 11));
- write3X4(CRTHiOrd, (read3X4(CRTHiOrd) & 0xF8) | ((base & 0xE0000) >> 17));
+ write3X4(CRTCModuleTest,
+ (read3X4(CRTCModuleTest) & 0xDF) | ((base & 0x10000) >> 11));
+ write3X4(CRTHiOrd,
+ (read3X4(CRTHiOrd) & 0xF8) | ((base & 0xE0000) >> 17));
}
/* Use 20.12 fixed-point for NTSC value and frequency calculation */
-#define calc_freq(n,m,k) ( ((unsigned long)0xE517 * (n+8) / ((m+2)*(1<<k))) >> 12 )
+#define calc_freq(n, m, k) ( ((unsigned long)0xE517 * (n + 8) / ((m + 2) * (1 << k))) >> 12 )
/* Set dotclock frequency */
static void set_vclk(int freq)
{
- int m,n,k;
- int f,fi,d,di;
- unsigned char lo=0,hi=0;
+ int m, n, k;
+ int f, fi, d, di;
+ unsigned char lo = 0, hi = 0;
d = 20;
- for(k = 2;k>=0;k--)
- for(m = 0;m<63;m++)
- for(n = 0;n<128;n++) {
- fi = calc_freq(n,m,k);
- if ((di = abs(fi - freq)) < d) {
- d = di;
- f = fi;
- lo = n;
- hi = (k<<6) | m;
- }
- }
+ for (k = 2; k >= 0; k--)
+ for (m = 0; m < 63; m++)
+ for (n = 0; n < 128; n++) {
+ fi = calc_freq(n, m, k);
+ if ((di = abs(fi - freq)) < d) {
+ d = di;
+ f = fi;
+ lo = n;
+ hi = (k << 6) | m;
+ }
+ }
if (chip3D) {
- write3C4(ClockHigh,hi);
- write3C4(ClockLow,lo);
+ write3C4(ClockHigh, hi);
+ write3C4(ClockLow, lo);
} else {
- outb(lo,0x43C8);
- outb(hi,0x43C9);
+ outb(lo, 0x43C8);
+ outb(hi, 0x43C9);
}
- debug("VCLK = %X %X\n",hi,lo);
+ debug("VCLK = %X %X\n", hi, lo);
}
/* Set number of lines for flat panels*/
@@ -663,7 +708,7 @@ static unsigned int __devinit get_displaytype(void)
return DISPLAY_FP;
if (crt || !chipcyber)
return DISPLAY_CRT;
- return (read3CE(FPConfig) & 0x10)?DISPLAY_FP:DISPLAY_CRT;
+ return (read3CE(FPConfig) & 0x10) ? DISPLAY_FP : DISPLAY_CRT;
}
/* Try detecting the video memory size */
@@ -676,100 +721,136 @@ static unsigned int __devinit get_memsize(void)
if (memsize)
k = memsize * Kb;
else
- switch (chip_id) {
- case CYBER9525DVD: k = 2560 * Kb; break;
+ switch (chip_id) {
+ case CYBER9525DVD:
+ k = 2560 * Kb;
+ break;
default:
tmp = read3X4(SPR) & 0x0F;
switch (tmp) {
- case 0x01: k = 512; break;
- case 0x02: k = 6 * Mb; break; /* XP */
- case 0x03: k = 1 * Mb; break;
- case 0x04: k = 8 * Mb; break;
- case 0x06: k = 10 * Mb; break; /* XP */
- case 0x07: k = 2 * Mb; break;
- case 0x08: k = 12 * Mb; break; /* XP */
- case 0x0A: k = 14 * Mb; break; /* XP */
- case 0x0C: k = 16 * Mb; break; /* XP */
- case 0x0E: /* XP */
-
- tmp2 = read3C4(0xC1);
- switch (tmp2) {
- case 0x00: k = 20 * Mb; break;
- case 0x01: k = 24 * Mb; break;
- case 0x10: k = 28 * Mb; break;
- case 0x11: k = 32 * Mb; break;
- default: k = 1 * Mb; break;
- }
+ case 0x01:
+ k = 512;
+ break;
+ case 0x02:
+ k = 6 * Mb; /* XP */
+ break;
+ case 0x03:
+ k = 1 * Mb;
+ break;
+ case 0x04:
+ k = 8 * Mb;
+ break;
+ case 0x06:
+ k = 10 * Mb; /* XP */
+ break;
+ case 0x07:
+ k = 2 * Mb;
+ break;
+ case 0x08:
+ k = 12 * Mb; /* XP */
+ break;
+ case 0x0A:
+ k = 14 * Mb; /* XP */
+ break;
+ case 0x0C:
+ k = 16 * Mb; /* XP */
+ break;
+ case 0x0E: /* XP */
+
+ tmp2 = read3C4(0xC1);
+ switch (tmp2) {
+ case 0x00:
+ k = 20 * Mb;
+ break;
+ case 0x01:
+ k = 24 * Mb;
+ break;
+ case 0x10:
+ k = 28 * Mb;
+ break;
+ case 0x11:
+ k = 32 * Mb;
+ break;
+ default:
+ k = 1 * Mb;
+ break;
+ }
+ break;
+
+ case 0x0F:
+ k = 4 * Mb;
+ break;
+ default:
+ k = 1 * Mb;
break;
-
- case 0x0F: k = 4 * Mb; break;
- default: k = 1 * Mb;
}
- }
+ }
k -= memdiff * Kb;
- output("framebuffer size = %d Kb\n", k/Kb);
+ output("framebuffer size = %d Kb\n", k / Kb);
return k;
}
/* See if we can handle the video mode described in var */
-static int tridentfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+static int tridentfb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
{
int bpp = var->bits_per_pixel;
debug("enter\n");
/* check color depth */
- if (bpp == 24 )
+ if (bpp == 24)
bpp = var->bits_per_pixel = 32;
- /* check whether resolution fits on panel and in memory*/
+ /* check whether resolution fits on panel and in memory */
if (flatpanel && nativex && var->xres > nativex)
return -EINVAL;
- if (var->xres * var->yres_virtual * bpp/8 > info->fix.smem_len)
+ if (var->xres * var->yres_virtual * bpp / 8 > info->fix.smem_len)
return -EINVAL;
switch (bpp) {
- case 8:
- var->red.offset = 0;
- var->green.offset = 0;
- var->blue.offset = 0;
- var->red.length = 6;
- var->green.length = 6;
- var->blue.length = 6;
- break;
- case 16:
- var->red.offset = 11;
- var->green.offset = 5;
- var->blue.offset = 0;
- var->red.length = 5;
- var->green.length = 6;
- var->blue.length = 5;
- break;
- case 32:
- var->red.offset = 16;
- var->green.offset = 8;
- var->blue.offset = 0;
- var->red.length = 8;
- var->green.length = 8;
- var->blue.length = 8;
- break;
- default:
- return -EINVAL;
+ case 8:
+ var->red.offset = 0;
+ var->green.offset = 0;
+ var->blue.offset = 0;
+ var->red.length = 6;
+ var->green.length = 6;
+ var->blue.length = 6;
+ break;
+ case 16:
+ var->red.offset = 11;
+ var->green.offset = 5;
+ var->blue.offset = 0;
+ var->red.length = 5;
+ var->green.length = 6;
+ var->blue.length = 5;
+ break;
+ case 32:
+ var->red.offset = 16;
+ var->green.offset = 8;
+ var->blue.offset = 0;
+ var->red.length = 8;
+ var->green.length = 8;
+ var->blue.length = 8;
+ break;
+ default:
+ return -EINVAL;
}
debug("exit\n");
return 0;
}
+
/* Pan the display */
static int tridentfb_pan_display(struct fb_var_screeninfo *var,
- struct fb_info *info)
+ struct fb_info *info)
{
unsigned int offset;
debug("enter\n");
offset = (var->xoffset + (var->yoffset * var->xres))
- * var->bits_per_pixel/32;
+ * var->bits_per_pixel / 32;
info->var.xoffset = var->xoffset;
info->var.yoffset = var->yoffset;
set_screen_start(offset);
@@ -777,36 +858,38 @@ static int tridentfb_pan_display(struct fb_var_screeninfo *var,
return 0;
}
-#define shadowmode_on() write3CE(CyberControl,read3CE(CyberControl) | 0x81)
-#define shadowmode_off() write3CE(CyberControl,read3CE(CyberControl) & 0x7E)
+#define shadowmode_on() write3CE(CyberControl, read3CE(CyberControl) | 0x81)
+#define shadowmode_off() write3CE(CyberControl, read3CE(CyberControl) & 0x7E)
/* Set the hardware to the requested video mode */
static int tridentfb_set_par(struct fb_info *info)
{
- struct tridentfb_par * par = (struct tridentfb_par *)(info->par);
- u32 htotal,hdispend,hsyncstart,hsyncend,hblankstart,hblankend,
- vtotal,vdispend,vsyncstart,vsyncend,vblankstart,vblankend;
- struct fb_var_screeninfo *var = &info->var;
+ struct tridentfb_par *par = (struct tridentfb_par *)(info->par);
+ u32 htotal, hdispend, hsyncstart, hsyncend, hblankstart, hblankend;
+ u32 vtotal, vdispend, vsyncstart, vsyncend, vblankstart, vblankend;
+ struct fb_var_screeninfo *var = &info->var;
int bpp = var->bits_per_pixel;
unsigned char tmp;
debug("enter\n");
- htotal = (var->xres + var->left_margin + var->right_margin + var->hsync_len)/8 - 10;
- hdispend = var->xres/8 - 1;
- hsyncstart = (var->xres + var->right_margin)/8;
- hsyncend = var->hsync_len/8;
+ hdispend = var->xres / 8 - 1;
+ hsyncstart = (var->xres + var->right_margin) / 8;
+ hsyncend = var->hsync_len / 8;
+ htotal =
+ (var->xres + var->left_margin + var->right_margin +
+ var->hsync_len) / 8 - 10;
hblankstart = hdispend + 1;
hblankend = htotal + 5;
- vtotal = var->yres + var->upper_margin + var->lower_margin + var->vsync_len - 2;
vdispend = var->yres - 1;
vsyncstart = var->yres + var->lower_margin;
vsyncend = var->vsync_len;
+ vtotal = var->upper_margin + vsyncstart + vsyncend - 2;
vblankstart = var->yres;
vblankend = vtotal + 2;
enable_mmio();
crtc_unlock();
- write3CE(CyberControl,8);
+ write3CE(CyberControl, 8);
if (flatpanel && var->xres < nativex) {
/*
@@ -814,18 +897,18 @@ static int tridentfb_set_par(struct fb_info *info)
* than requested resolution decide whether
* we stretch or center
*/
- t_outb(0xEB,0x3C2);
+ t_outb(0xEB, 0x3C2);
shadowmode_on();
- if (center)
+ if (center)
screen_center();
else if (stretch)
screen_stretch();
} else {
- t_outb(0x2B,0x3C2);
- write3CE(CyberControl,8);
+ t_outb(0x2B, 0x3C2);
+ write3CE(CyberControl, 8);
}
/* vertical timing values */
@@ -834,15 +917,15 @@ static int tridentfb_set_par(struct fb_info *info)
write3X4(CRTVSyncStart, vsyncstart & 0xFF);
write3X4(CRTVSyncEnd, (vsyncend & 0x0F));
write3X4(CRTVBlankStart, vblankstart & 0xFF);
- write3X4(CRTVBlankEnd, 0/*p->vblankend & 0xFF*/);
+ write3X4(CRTVBlankEnd, 0 /* p->vblankend & 0xFF */ );
/* horizontal timing values */
write3X4(CRTHTotal, htotal & 0xFF);
write3X4(CRTHDispEnd, hdispend & 0xFF);
write3X4(CRTHSyncStart, hsyncstart & 0xFF);
- write3X4(CRTHSyncEnd, (hsyncend & 0x1F) | ((hblankend & 0x20)<<2));
+ write3X4(CRTHSyncEnd, (hsyncend & 0x1F) | ((hblankend & 0x20) << 2));
write3X4(CRTHBlankStart, hblankstart & 0xFF);
- write3X4(CRTHBlankEnd, 0/*(p->hblankend & 0x1F)*/);
+ write3X4(CRTHBlankEnd, 0 /* (p->hblankend & 0x1F) */ );
/* higher bits of vertical timing values */
tmp = 0x10;
@@ -856,7 +939,7 @@ static int tridentfb_set_par(struct fb_info *info)
if (vsyncstart & 0x200) tmp |= 0x80;
write3X4(CRTOverflow, tmp);
- tmp = read3X4(CRTHiOrd) | 0x08; //line compare bit 10
+ tmp = read3X4(CRTHiOrd) | 0x08; /* line compare bit 10 */
if (vtotal & 0x400) tmp |= 0x80;
if (vblankstart & 0x400) tmp |= 0x40;
if (vsyncstart & 0x400) tmp |= 0x20;
@@ -867,84 +950,100 @@ static int tridentfb_set_par(struct fb_info *info)
if (htotal & 0x800) tmp |= 0x800 >> 11;
if (hblankstart & 0x800) tmp |= 0x800 >> 7;
write3X4(HorizOverflow, tmp);
-
+
tmp = 0x40;
if (vblankstart & 0x200) tmp |= 0x20;
-//FIXME if (info->var.vmode & FB_VMODE_DOUBLE) tmp |= 0x80; //double scan for 200 line modes
+//FIXME if (info->var.vmode & FB_VMODE_DOUBLE) tmp |= 0x80; /* double scan for 200 line modes */
write3X4(CRTMaxScanLine, tmp);
- write3X4(CRTLineCompare,0xFF);
- write3X4(CRTPRowScan,0);
- write3X4(CRTModeControl,0xC3);
+ write3X4(CRTLineCompare, 0xFF);
+ write3X4(CRTPRowScan, 0);
+ write3X4(CRTModeControl, 0xC3);
- write3X4(LinearAddReg,0x20); //enable linear addressing
+ write3X4(LinearAddReg, 0x20); /* enable linear addressing */
- tmp = (info->var.vmode & FB_VMODE_INTERLACED) ? 0x84:0x80;
- write3X4(CRTCModuleTest,tmp); //enable access extended memory
+ tmp = (info->var.vmode & FB_VMODE_INTERLACED) ? 0x84 : 0x80;
+ write3X4(CRTCModuleTest, tmp); /* enable access extended memory */
- write3X4(GraphEngReg, 0x80); //enable GE for text acceleration
+ write3X4(GraphEngReg, 0x80); /* enable GE for text acceleration */
-#ifdef CONFIG_FB_TRIDENT_ACCEL
- acc->init_accel(info->var.xres,bpp);
+#ifdef CONFIG_FB_TRIDENT_ACCEL
+ acc->init_accel(info->var.xres, bpp);
#endif
-
+
switch (bpp) {
- case 8: tmp = 0x00; break;
- case 16: tmp = 0x05; break;
- case 24: tmp = 0x29; break;
- case 32: tmp = 0x09;
+ case 8:
+ tmp = 0x00;
+ break;
+ case 16:
+ tmp = 0x05;
+ break;
+ case 24:
+ tmp = 0x29;
+ break;
+ case 32:
+ tmp = 0x09;
+ break;
}
write3X4(PixelBusReg, tmp);
tmp = 0x10;
if (chipcyber)
- tmp |= 0x20;
- write3X4(DRAMControl, tmp); //both IO,linear enable
+ tmp |= 0x20;
+ write3X4(DRAMControl, tmp); /* both IO, linear enable */
write3X4(InterfaceSel, read3X4(InterfaceSel) | 0x40);
- write3X4(Performance,0x92);
- write3X4(PCIReg,0x07); //MMIO & PCI read and write burst enable
+ write3X4(Performance, 0x92);
+ write3X4(PCIReg, 0x07); /* MMIO & PCI read and write burst enable */
/* convert from picoseconds to MHz */
- par->vclk = 1000000/info->var.pixclock;
+ par->vclk = 1000000 / info->var.pixclock;
if (bpp == 32)
- par->vclk *=2;
+ par->vclk *= 2;
set_vclk(par->vclk);
- write3C4(0,3);
- write3C4(1,1); //set char clock 8 dots wide
- write3C4(2,0x0F); //enable 4 maps because needed in chain4 mode
- write3C4(3,0);
- write3C4(4,0x0E); //memory mode enable bitmaps ??
+ write3C4(0, 3);
+ write3C4(1, 1); /* set char clock 8 dots wide */
+ write3C4(2, 0x0F); /* enable 4 maps because needed in chain4 mode */
+ write3C4(3, 0);
+ write3C4(4, 0x0E); /* memory mode enable bitmaps ?? */
- write3CE(MiscExtFunc,(bpp==32)?0x1A:0x12); //divide clock by 2 if 32bpp
- //chain4 mode display and CPU path
- write3CE(0x5,0x40); //no CGA compat,allow 256 col
- write3CE(0x6,0x05); //graphics mode
- write3CE(0x7,0x0F); //planes?
+ write3CE(MiscExtFunc, (bpp == 32) ? 0x1A : 0x12); /* divide clock by 2 if 32bpp */
+ /* chain4 mode display and CPU path */
+ write3CE(0x5, 0x40); /* no CGA compat, allow 256 col */
+ write3CE(0x6, 0x05); /* graphics mode */
+ write3CE(0x7, 0x0F); /* planes? */
if (chip_id == CYBERBLADEXPAi1) {
/* This fixes snow-effect in 32 bpp */
- write3X4(CRTHSyncStart,0x84);
+ write3X4(CRTHSyncStart, 0x84);
}
- writeAttr(0x10,0x41); //graphics mode and support 256 color modes
- writeAttr(0x12,0x0F); //planes
- writeAttr(0x13,0); //horizontal pel panning
+ writeAttr(0x10, 0x41); /* graphics mode and support 256 color modes */
+ writeAttr(0x12, 0x0F); /* planes */
+ writeAttr(0x13, 0); /* horizontal pel panning */
- //colors
- for(tmp = 0;tmp < 0x10;tmp++)
- writeAttr(tmp,tmp);
- readb(par->io_virt + CRT + 0x0A); //flip-flop to index
- t_outb(0x20, 0x3C0); //enable attr
+ /* colors */
+ for (tmp = 0; tmp < 0x10; tmp++)
+ writeAttr(tmp, tmp);
+ readb(par->io_virt + CRT + 0x0A); /* flip-flop to index */
+ t_outb(0x20, 0x3C0); /* enable attr */
switch (bpp) {
- case 8: tmp = 0;break; //256 colors
- case 15: tmp = 0x10;break;
- case 16: tmp = 0x30;break; //hicolor
- case 24: //truecolor
- case 32: tmp = 0xD0;break;
+ case 8:
+ tmp = 0;
+ break;
+ case 15:
+ tmp = 0x10;
+ break;
+ case 16:
+ tmp = 0x30;
+ break;
+ case 24:
+ case 32:
+ tmp = 0xD0;
+ break;
}
t_inb(0x3C8);
@@ -952,37 +1051,36 @@ static int tridentfb_set_par(struct fb_info *info)
t_inb(0x3C6);
t_inb(0x3C6);
t_inb(0x3C6);
- t_outb(tmp,0x3C6);
+ t_outb(tmp, 0x3C6);
t_inb(0x3C8);
if (flatpanel)
set_number_of_lines(info->var.yres);
- set_lwidth(info->var.xres * bpp/(4*16));
+ set_lwidth(info->var.xres * bpp / (4 * 16));
info->fix.visual = (bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
- info->fix.line_length = info->var.xres * (bpp >> 3);
- info->cmap.len = (bpp == 8) ? 256: 16;
+ info->fix.line_length = info->var.xres * (bpp >> 3);
+ info->cmap.len = (bpp == 8) ? 256 : 16;
debug("exit\n");
return 0;
}
/* Set one color register */
static int tridentfb_setcolreg(unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp,
- struct fb_info *info)
+ unsigned blue, unsigned transp,
+ struct fb_info *info)
{
int bpp = info->var.bits_per_pixel;
if (regno >= info->cmap.len)
return 1;
-
if (bpp == 8) {
- t_outb(0xFF,0x3C6);
- t_outb(regno,0x3C8);
+ t_outb(0xFF, 0x3C6);
+ t_outb(regno, 0x3C8);
- t_outb(red>>10,0x3C9);
- t_outb(green>>10,0x3C9);
- t_outb(blue>>10,0x3C9);
+ t_outb(red >> 10, 0x3C9);
+ t_outb(green >> 10, 0x3C9);
+ t_outb(blue >> 10, 0x3C9);
} else if (regno < 16) {
if (bpp == 16) { /* RGB 565 */
@@ -994,29 +1092,28 @@ static int tridentfb_setcolreg(unsigned regno, unsigned red, unsigned green,
((u32 *)(info->pseudo_palette))[regno] = col;
} else if (bpp == 32) /* ARGB 8888 */
((u32*)info->pseudo_palette)[regno] =
- ((transp & 0xFF00) <<16) |
- ((red & 0xFF00) << 8) |
+ ((transp & 0xFF00) << 16) |
+ ((red & 0xFF00) << 8) |
((green & 0xFF00)) |
- ((blue & 0xFF00)>>8);
+ ((blue & 0xFF00) >> 8);
}
-// debug("exit\n");
+/* debug("exit\n"); */
return 0;
}
/* Try blanking the screen.For flat panels it does nothing */
static int tridentfb_blank(int blank_mode, struct fb_info *info)
{
- unsigned char PMCont,DPMSCont;
+ unsigned char PMCont, DPMSCont;
debug("enter\n");
if (flatpanel)
return 0;
- t_outb(0x04,0x83C8); /* Read DPMS Control */
+ t_outb(0x04, 0x83C8); /* Read DPMS Control */
PMCont = t_inb(0x83C6) & 0xFC;
DPMSCont = read3CE(PowerStatus) & 0xFC;
- switch (blank_mode)
- {
+ switch (blank_mode) {
case FB_BLANK_UNBLANK:
/* Screen: On, HSync: On, VSync: On */
case FB_BLANK_NORMAL:
@@ -1039,11 +1136,11 @@ static int tridentfb_blank(int blank_mode, struct fb_info *info)
PMCont |= 0x00;
DPMSCont |= 0x03;
break;
- }
+ }
- write3CE(PowerStatus,DPMSCont);
- t_outb(4,0x83C8);
- t_outb(PMCont,0x83C6);
+ write3CE(PowerStatus, DPMSCont);
+ t_outb(4, 0x83C8);
+ t_outb(PMCont, 0x83C6);
debug("exit\n");
@@ -1051,7 +1148,20 @@ static int tridentfb_blank(int blank_mode, struct fb_info *info)
return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
}
-static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_device_id * id)
+static struct fb_ops tridentfb_ops = {
+ .owner = THIS_MODULE,
+ .fb_setcolreg = tridentfb_setcolreg,
+ .fb_pan_display = tridentfb_pan_display,
+ .fb_blank = tridentfb_blank,
+ .fb_check_var = tridentfb_check_var,
+ .fb_set_par = tridentfb_set_par,
+ .fb_fillrect = tridentfb_fillrect,
+ .fb_copyarea = tridentfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+};
+
+static int __devinit trident_pci_probe(struct pci_dev * dev,
+ const struct pci_device_id * id)
{
int err;
unsigned char revision;
@@ -1062,31 +1172,42 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de
chip_id = id->device;
- if(chip_id == CYBERBLADEi1)
+ if (chip_id == CYBERBLADEi1)
output("*** Please do use cyblafb, Cyberblade/i1 support "
"will soon be removed from tridentfb!\n");
/* If PCI id is 0x9660 then further detect chip type */
-
+
if (chip_id == TGUI9660) {
- outb(RevisionID,0x3C4);
- revision = inb(0x3C5);
-
+ outb(RevisionID, 0x3C4);
+ revision = inb(0x3C5);
+
switch (revision) {
- case 0x22:
- case 0x23: chip_id = CYBER9397;break;
- case 0x2A: chip_id = CYBER9397DVD;break;
- case 0x30:
- case 0x33:
- case 0x34:
- case 0x35:
- case 0x38:
- case 0x3A:
- case 0xB3: chip_id = CYBER9385;break;
- case 0x40 ... 0x43: chip_id = CYBER9382;break;
- case 0x4A: chip_id = CYBER9388;break;
- default:break;
+ case 0x22:
+ case 0x23:
+ chip_id = CYBER9397;
+ break;
+ case 0x2A:
+ chip_id = CYBER9397DVD;
+ break;
+ case 0x30:
+ case 0x33:
+ case 0x34:
+ case 0x35:
+ case 0x38:
+ case 0x3A:
+ case 0xB3:
+ chip_id = CYBER9385;
+ break;
+ case 0x40 ... 0x43:
+ chip_id = CYBER9382;
+ break;
+ case 0x4A:
+ chip_id = CYBER9388;
+ break;
+ default:
+ break;
}
}
@@ -1095,8 +1216,7 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de
if (is_xp(chip_id)) {
acc = &accel_xp;
- } else
- if (is_blade(chip_id)) {
+ } else if (is_blade(chip_id)) {
acc = &accel_blade;
} else {
acc = &accel_image;
@@ -1108,8 +1228,8 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de
fb_info.par = &default_par;
/* setup MMIO region */
- tridentfb_fix.mmio_start = pci_resource_start(dev,1);
- tridentfb_fix.mmio_len = chip3D ? 0x20000:0x10000;
+ tridentfb_fix.mmio_start = pci_resource_start(dev, 1);
+ tridentfb_fix.mmio_len = chip3D ? 0x20000 : 0x10000;
if (!request_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len, "tridentfb")) {
debug("request_region failed!\n");
@@ -1125,11 +1245,11 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de
}
enable_mmio();
-
+
/* setup framebuffer memory */
- tridentfb_fix.smem_start = pci_resource_start(dev,0);
+ tridentfb_fix.smem_start = pci_resource_start(dev, 0);
tridentfb_fix.smem_len = get_memsize();
-
+
if (!request_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len, "tridentfb")) {
debug("request_mem_region failed!\n");
err = -1;
@@ -1137,7 +1257,7 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de
}
fb_info.screen_base = ioremap_nocache(tridentfb_fix.smem_start,
- tridentfb_fix.smem_len);
+ tridentfb_fix.smem_len);
if (!fb_info.screen_base) {
release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len);
@@ -1147,13 +1267,13 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de
}
output("%s board found\n", pci_name(dev));
-#if 0
- output("Trident board found : mem = %X,io = %X, mem_v = %X, io_v = %X\n",
+#if 0
+ output("Trident board found : mem = %X, io = %X, mem_v = %X, io_v = %X\n",
tridentfb_fix.smem_start, tridentfb_fix.mmio_start, fb_info.screen_base, default_par.io_virt);
#endif
displaytype = get_displaytype();
- if(flatpanel)
+ if (flatpanel)
nativex = get_nativex();
fb_info.fix = tridentfb_fix;
@@ -1166,11 +1286,11 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de
#endif
fb_info.pseudo_palette = pseudo_pal;
- if (!fb_find_mode(&default_var,&fb_info,mode,NULL,0,NULL,bpp)) {
+ if (!fb_find_mode(&default_var, &fb_info, mode, NULL, 0, NULL, bpp)) {
err = -EINVAL;
goto out_unmap;
}
- fb_alloc_cmap(&fb_info.cmap,256,0);
+ fb_alloc_cmap(&fb_info.cmap, 256, 0);
if (defaultaccel && acc)
default_var.accel_flags |= FB_ACCELF_TEXT;
else
@@ -1184,8 +1304,8 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de
goto out_unmap;
}
output("fb%d: %s frame buffer device %dx%d-%dbpp\n",
- fb_info.node, fb_info.fix.id,default_var.xres,
- default_var.yres,default_var.bits_per_pixel);
+ fb_info.node, fb_info.fix.id, default_var.xres,
+ default_var.yres, default_var.bits_per_pixel);
return 0;
out_unmap:
@@ -1196,7 +1316,7 @@ out_unmap:
return err;
}
-static void __devexit trident_pci_remove(struct pci_dev * dev)
+static void __devexit trident_pci_remove(struct pci_dev *dev)
{
struct tridentfb_par *par = (struct tridentfb_par*)fb_info.par;
unregister_framebuffer(&fb_info);
@@ -1208,69 +1328,70 @@ static void __devexit trident_pci_remove(struct pci_dev * dev)
/* List of boards that we are trying to support */
static struct pci_device_id trident_devices[] = {
- {PCI_VENDOR_ID_TRIDENT, BLADE3D, PCI_ANY_ID,PCI_ANY_ID,0,0,0},
- {PCI_VENDOR_ID_TRIDENT, CYBERBLADEi7, PCI_ANY_ID,PCI_ANY_ID,0,0,0},
- {PCI_VENDOR_ID_TRIDENT, CYBERBLADEi7D, PCI_ANY_ID,PCI_ANY_ID,0,0,0},
- {PCI_VENDOR_ID_TRIDENT, CYBERBLADEi1, PCI_ANY_ID,PCI_ANY_ID,0,0,0},
- {PCI_VENDOR_ID_TRIDENT, CYBERBLADEi1D, PCI_ANY_ID,PCI_ANY_ID,0,0,0},
- {PCI_VENDOR_ID_TRIDENT, CYBERBLADEAi1, PCI_ANY_ID,PCI_ANY_ID,0,0,0},
- {PCI_VENDOR_ID_TRIDENT, CYBERBLADEAi1D, PCI_ANY_ID,PCI_ANY_ID,0,0,0},
- {PCI_VENDOR_ID_TRIDENT, CYBERBLADEE4, PCI_ANY_ID,PCI_ANY_ID,0,0,0},
- {PCI_VENDOR_ID_TRIDENT, TGUI9660, PCI_ANY_ID,PCI_ANY_ID,0,0,0},
- {PCI_VENDOR_ID_TRIDENT, IMAGE975, PCI_ANY_ID,PCI_ANY_ID,0,0,0},
- {PCI_VENDOR_ID_TRIDENT, IMAGE985, PCI_ANY_ID,PCI_ANY_ID,0,0,0},
- {PCI_VENDOR_ID_TRIDENT, CYBER9320, PCI_ANY_ID,PCI_ANY_ID,0,0,0},
- {PCI_VENDOR_ID_TRIDENT, CYBER9388, PCI_ANY_ID,PCI_ANY_ID,0,0,0},
- {PCI_VENDOR_ID_TRIDENT, CYBER9520, PCI_ANY_ID,PCI_ANY_ID,0,0,0},
- {PCI_VENDOR_ID_TRIDENT, CYBER9525DVD, PCI_ANY_ID,PCI_ANY_ID,0,0,0},
- {PCI_VENDOR_ID_TRIDENT, CYBER9397, PCI_ANY_ID,PCI_ANY_ID,0,0,0},
- {PCI_VENDOR_ID_TRIDENT, CYBER9397DVD, PCI_ANY_ID,PCI_ANY_ID,0,0,0},
- {PCI_VENDOR_ID_TRIDENT, CYBERBLADEXPAi1, PCI_ANY_ID,PCI_ANY_ID,0,0,0},
- {PCI_VENDOR_ID_TRIDENT, CYBERBLADEXPm8, PCI_ANY_ID,PCI_ANY_ID,0,0,0},
- {PCI_VENDOR_ID_TRIDENT, CYBERBLADEXPm16, PCI_ANY_ID,PCI_ANY_ID,0,0,0},
+ {PCI_VENDOR_ID_TRIDENT, BLADE3D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_TRIDENT, CYBERBLADEi7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_TRIDENT, CYBERBLADEi7D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_TRIDENT, CYBERBLADEi1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_TRIDENT, CYBERBLADEi1D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_TRIDENT, CYBERBLADEAi1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_TRIDENT, CYBERBLADEAi1D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_TRIDENT, CYBERBLADEE4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_TRIDENT, TGUI9660, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_TRIDENT, IMAGE975, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_TRIDENT, IMAGE985, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_TRIDENT, CYBER9320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_TRIDENT, CYBER9388, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_TRIDENT, CYBER9520, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_TRIDENT, CYBER9525DVD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_TRIDENT, CYBER9397, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_TRIDENT, CYBER9397DVD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_TRIDENT, CYBERBLADEXPAi1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_TRIDENT, CYBERBLADEXPm8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_TRIDENT, CYBERBLADEXPm16, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0,}
-};
-
-MODULE_DEVICE_TABLE(pci,trident_devices);
+};
+
+MODULE_DEVICE_TABLE(pci, trident_devices);
static struct pci_driver tridentfb_pci_driver = {
- .name = "tridentfb",
- .id_table = trident_devices,
- .probe = trident_pci_probe,
- .remove = __devexit_p(trident_pci_remove)
+ .name = "tridentfb",
+ .id_table = trident_devices,
+ .probe = trident_pci_probe,
+ .remove = __devexit_p(trident_pci_remove)
};
/*
* Parse user specified options (`video=trident:')
* example:
- * video=trident:800x600,bpp=16,noaccel
+ * video=trident:800x600,bpp=16,noaccel
*/
#ifndef MODULE
static int tridentfb_setup(char *options)
{
- char * opt;
+ char *opt;
if (!options || !*options)
return 0;
- while((opt = strsep(&options,",")) != NULL ) {
- if (!*opt) continue;
- if (!strncmp(opt,"noaccel",7))
+ while ((opt = strsep(&options, ",")) != NULL) {
+ if (!*opt)
+ continue;
+ if (!strncmp(opt, "noaccel", 7))
noaccel = 1;
- else if (!strncmp(opt,"fp",2))
+ else if (!strncmp(opt, "fp", 2))
displaytype = DISPLAY_FP;
- else if (!strncmp(opt,"crt",3))
+ else if (!strncmp(opt, "crt", 3))
displaytype = DISPLAY_CRT;
- else if (!strncmp(opt,"bpp=",4))
- bpp = simple_strtoul(opt+4,NULL,0);
- else if (!strncmp(opt,"center",6))
+ else if (!strncmp(opt, "bpp=", 4))
+ bpp = simple_strtoul(opt + 4, NULL, 0);
+ else if (!strncmp(opt, "center", 6))
center = 1;
- else if (!strncmp(opt,"stretch",7))
+ else if (!strncmp(opt, "stretch", 7))
stretch = 1;
- else if (!strncmp(opt,"memsize=",8))
- memsize = simple_strtoul(opt+8,NULL,0);
- else if (!strncmp(opt,"memdiff=",8))
- memdiff = simple_strtoul(opt+8,NULL,0);
- else if (!strncmp(opt,"nativex=",8))
- nativex = simple_strtoul(opt+8,NULL,0);
+ else if (!strncmp(opt, "memsize=", 8))
+ memsize = simple_strtoul(opt + 8, NULL, 0);
+ else if (!strncmp(opt, "memdiff=", 8))
+ memdiff = simple_strtoul(opt + 8, NULL, 0);
+ else if (!strncmp(opt, "nativex=", 8))
+ nativex = simple_strtoul(opt + 8, NULL, 0);
else
mode = opt;
}
@@ -1296,18 +1417,6 @@ static void __exit tridentfb_exit(void)
pci_unregister_driver(&tridentfb_pci_driver);
}
-static struct fb_ops tridentfb_ops = {
- .owner = THIS_MODULE,
- .fb_setcolreg = tridentfb_setcolreg,
- .fb_pan_display = tridentfb_pan_display,
- .fb_blank = tridentfb_blank,
- .fb_check_var = tridentfb_check_var,
- .fb_set_par = tridentfb_set_par,
- .fb_fillrect = tridentfb_fillrect,
- .fb_copyarea= tridentfb_copyarea,
- .fb_imageblit = cfb_imageblit,
-};
-
module_init(tridentfb_init);
module_exit(tridentfb_exit);
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c
new file mode 100644
index 000000000000..d1d6c0facd54
--- /dev/null
+++ b/drivers/video/uvesafb.c
@@ -0,0 +1,2068 @@
+/*
+ * A framebuffer driver for VBE 2.0+ compliant video cards
+ *
+ * (c) 2007 Michal Januszewski <spock@gentoo.org>
+ * Loosely based upon the vesafb driver.
+ *
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/skbuff.h>
+#include <linux/timer.h>
+#include <linux/completion.h>
+#include <linux/connector.h>
+#include <linux/random.h>
+#include <linux/platform_device.h>
+#include <linux/limits.h>
+#include <linux/fb.h>
+#include <linux/io.h>
+#include <linux/mutex.h>
+#include <video/edid.h>
+#include <video/uvesafb.h>
+#ifdef CONFIG_X86
+#include <video/vga.h>
+#endif
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+#include "edid.h"
+
+static struct cb_id uvesafb_cn_id = {
+ .idx = CN_IDX_V86D,
+ .val = CN_VAL_V86D_UVESAFB
+};
+static char v86d_path[PATH_MAX] = "/sbin/v86d";
+static char v86d_started; /* has v86d been started by uvesafb? */
+
+static struct fb_fix_screeninfo uvesafb_fix __devinitdata = {
+ .id = "VESA VGA",
+ .type = FB_TYPE_PACKED_PIXELS,
+ .accel = FB_ACCEL_NONE,
+ .visual = FB_VISUAL_TRUECOLOR,
+};
+
+static int mtrr __devinitdata = 3; /* enable mtrr by default */
+static int blank __devinitdata = 1; /* enable blanking by default */
+static int ypan __devinitdata = 1; /* 0: scroll, 1: ypan, 2: ywrap */
+static int pmi_setpal __devinitdata = 1; /* use PMI for palette changes */
+static int nocrtc __devinitdata; /* ignore CRTC settings */
+static int noedid __devinitdata; /* don't try DDC transfers */
+static int vram_remap __devinitdata; /* set amt. of memory to be used */
+static int vram_total __devinitdata; /* set total amount of memory */
+static u16 maxclk __devinitdata; /* maximum pixel clock */
+static u16 maxvf __devinitdata; /* maximum vertical frequency */
+static u16 maxhf __devinitdata; /* maximum horizontal frequency */
+static u16 vbemode __devinitdata; /* force use of a specific VBE mode */
+static char *mode_option __devinitdata;
+
+static struct uvesafb_ktask *uvfb_tasks[UVESAFB_TASKS_MAX];
+static DEFINE_MUTEX(uvfb_lock);
+
+/*
+ * A handler for replies from userspace.
+ *
+ * Make sure each message passes consistency checks and if it does,
+ * find the kernel part of the task struct, copy the registers and
+ * the buffer contents and then complete the task.
+ */
+static void uvesafb_cn_callback(void *data)
+{
+ struct cn_msg *msg = data;
+ struct uvesafb_task *utask;
+ struct uvesafb_ktask *task;
+
+ if (msg->seq >= UVESAFB_TASKS_MAX)
+ return;
+
+ mutex_lock(&uvfb_lock);
+ task = uvfb_tasks[msg->seq];
+
+ if (!task || msg->ack != task->ack) {
+ mutex_unlock(&uvfb_lock);
+ return;
+ }
+
+ utask = (struct uvesafb_task *)msg->data;
+
+ /* Sanity checks for the buffer length. */
+ if (task->t.buf_len < utask->buf_len ||
+ utask->buf_len > msg->len - sizeof(*utask)) {
+ mutex_unlock(&uvfb_lock);
+ return;
+ }
+
+ uvfb_tasks[msg->seq] = NULL;
+ mutex_unlock(&uvfb_lock);
+
+ memcpy(&task->t, utask, sizeof(*utask));
+
+ if (task->t.buf_len && task->buf)
+ memcpy(task->buf, utask + 1, task->t.buf_len);
+
+ complete(task->done);
+ return;
+}
+
+static int uvesafb_helper_start(void)
+{
+ char *envp[] = {
+ "HOME=/",
+ "PATH=/sbin:/bin",
+ NULL,
+ };
+
+ char *argv[] = {
+ v86d_path,
+ NULL,
+ };
+
+ return call_usermodehelper(v86d_path, argv, envp, 1);
+}
+
+/*
+ * Execute a uvesafb task.
+ *
+ * Returns 0 if the task is executed successfully.
+ *
+ * A message sent to the userspace consists of the uvesafb_task
+ * struct and (optionally) a buffer. The uvesafb_task struct is
+ * a simplified version of uvesafb_ktask (its kernel counterpart)
+ * containing only the register values, flags and the length of
+ * the buffer.
+ *
+ * Each message is assigned a sequence number (increased linearly)
+ * and a random ack number. The sequence number is used as a key
+ * for the uvfb_tasks array which holds pointers to uvesafb_ktask
+ * structs for all requests.
+ */
+static int uvesafb_exec(struct uvesafb_ktask *task)
+{
+ static int seq;
+ struct cn_msg *m;
+ int err;
+ int len = sizeof(task->t) + task->t.buf_len;
+
+ /*
+ * Check whether the message isn't longer than the maximum
+ * allowed by connector.
+ */
+ if (sizeof(*m) + len > CONNECTOR_MAX_MSG_SIZE) {
+ printk(KERN_WARNING "uvesafb: message too long (%d), "
+ "can't execute task\n", (int)(sizeof(*m) + len));
+ return -E2BIG;
+ }
+
+ m = kzalloc(sizeof(*m) + len, GFP_KERNEL);
+ if (!m)
+ return -ENOMEM;
+
+ init_completion(task->done);
+
+ memcpy(&m->id, &uvesafb_cn_id, sizeof(m->id));
+ m->seq = seq;
+ m->len = len;
+ m->ack = random32();
+
+ /* uvesafb_task structure */
+ memcpy(m + 1, &task->t, sizeof(task->t));
+
+ /* Buffer */
+ memcpy((u8 *)(m + 1) + sizeof(task->t), task->buf, task->t.buf_len);
+
+ /*
+ * Save the message ack number so that we can find the kernel
+ * part of this task when a reply is received from userspace.
+ */
+ task->ack = m->ack;
+
+ mutex_lock(&uvfb_lock);
+
+ /* If all slots are taken -- bail out. */
+ if (uvfb_tasks[seq]) {
+ mutex_unlock(&uvfb_lock);
+ return -EBUSY;
+ }
+
+ /* Save a pointer to the kernel part of the task struct. */
+ uvfb_tasks[seq] = task;
+ mutex_unlock(&uvfb_lock);
+
+ err = cn_netlink_send(m, 0, gfp_any());
+ if (err == -ESRCH) {
+ /*
+ * Try to start the userspace helper if sending
+ * the request failed the first time.
+ */
+ err = uvesafb_helper_start();
+ if (err) {
+ printk(KERN_ERR "uvesafb: failed to execute %s\n",
+ v86d_path);
+ printk(KERN_ERR "uvesafb: make sure that the v86d "
+ "helper is installed and executable\n");
+ } else {
+ v86d_started = 1;
+ err = cn_netlink_send(m, 0, gfp_any());
+ }
+ }
+ kfree(m);
+
+ if (!err && !(task->t.flags & TF_EXIT))
+ err = !wait_for_completion_timeout(task->done,
+ msecs_to_jiffies(UVESAFB_TIMEOUT));
+
+ mutex_lock(&uvfb_lock);
+ uvfb_tasks[seq] = NULL;
+ mutex_unlock(&uvfb_lock);
+
+ seq++;
+ if (seq >= UVESAFB_TASKS_MAX)
+ seq = 0;
+
+ return err;
+}
+
+/*
+ * Free a uvesafb_ktask struct.
+ */
+static void uvesafb_free(struct uvesafb_ktask *task)
+{
+ if (task) {
+ if (task->done)
+ kfree(task->done);
+ kfree(task);
+ }
+}
+
+/*
+ * Prepare a uvesafb_ktask struct to be used again.
+ */
+static void uvesafb_reset(struct uvesafb_ktask *task)
+{
+ struct completion *cpl = task->done;
+
+ memset(task, 0, sizeof(*task));
+ task->done = cpl;
+}
+
+/*
+ * Allocate and prepare a uvesafb_ktask struct.
+ */
+static struct uvesafb_ktask *uvesafb_prep(void)
+{
+ struct uvesafb_ktask *task;
+
+ task = kzalloc(sizeof(*task), GFP_KERNEL);
+ if (task) {
+ task->done = kzalloc(sizeof(*task->done), GFP_KERNEL);
+ if (!task->done) {
+ kfree(task);
+ task = NULL;
+ }
+ }
+ return task;
+}
+
+static void uvesafb_setup_var(struct fb_var_screeninfo *var,
+ struct fb_info *info, struct vbe_mode_ib *mode)
+{
+ struct uvesafb_par *par = info->par;
+
+ var->vmode = FB_VMODE_NONINTERLACED;
+ var->sync = FB_SYNC_VERT_HIGH_ACT;
+
+ var->xres = mode->x_res;
+ var->yres = mode->y_res;
+ var->xres_virtual = mode->x_res;
+ var->yres_virtual = (par->ypan) ?
+ info->fix.smem_len / mode->bytes_per_scan_line :
+ mode->y_res;
+ var->xoffset = 0;
+ var->yoffset = 0;
+ var->bits_per_pixel = mode->bits_per_pixel;
+
+ if (var->bits_per_pixel == 15)
+ var->bits_per_pixel = 16;
+
+ if (var->bits_per_pixel > 8) {
+ var->red.offset = mode->red_off;
+ var->red.length = mode->red_len;
+ var->green.offset = mode->green_off;
+ var->green.length = mode->green_len;
+ var->blue.offset = mode->blue_off;
+ var->blue.length = mode->blue_len;
+ var->transp.offset = mode->rsvd_off;
+ var->transp.length = mode->rsvd_len;
+ } else {
+ var->red.offset = 0;
+ var->green.offset = 0;
+ var->blue.offset = 0;
+ var->transp.offset = 0;
+
+ /*
+ * We're assuming that we can switch the DAC to 8 bits. If
+ * this proves to be incorrect, we'll update the fields
+ * later in set_par().
+ */
+ if (par->vbe_ib.capabilities & VBE_CAP_CAN_SWITCH_DAC) {
+ var->red.length = 8;
+ var->green.length = 8;
+ var->blue.length = 8;
+ var->transp.length = 0;
+ } else {
+ var->red.length = 6;
+ var->green.length = 6;
+ var->blue.length = 6;
+ var->transp.length = 0;
+ }
+ }
+}
+
+static int uvesafb_vbe_find_mode(struct uvesafb_par *par,
+ int xres, int yres, int depth, unsigned char flags)
+{
+ int i, match = -1, h = 0, d = 0x7fffffff;
+
+ for (i = 0; i < par->vbe_modes_cnt; i++) {
+ h = abs(par->vbe_modes[i].x_res - xres) +
+ abs(par->vbe_modes[i].y_res - yres) +
+ abs(depth - par->vbe_modes[i].depth);
+
+ /*
+ * We have an exact match in terms of resolution
+ * and depth.
+ */
+ if (h == 0)
+ return i;
+
+ if (h < d || (h == d && par->vbe_modes[i].depth > depth)) {
+ d = h;
+ match = i;
+ }
+ }
+ i = 1;
+
+ if (flags & UVESAFB_EXACT_DEPTH &&
+ par->vbe_modes[match].depth != depth)
+ i = 0;
+
+ if (flags & UVESAFB_EXACT_RES && d > 24)
+ i = 0;
+
+ if (i != 0)
+ return match;
+ else
+ return -1;
+}
+
+static u8 *uvesafb_vbe_state_save(struct uvesafb_par *par)
+{
+ struct uvesafb_ktask *task;
+ u8 *state;
+ int err;
+
+ if (!par->vbe_state_size)
+ return NULL;
+
+ state = kmalloc(par->vbe_state_size, GFP_KERNEL);
+ if (!state)
+ return NULL;
+
+ task = uvesafb_prep();
+ if (!task) {
+ kfree(state);
+ return NULL;
+ }
+
+ task->t.regs.eax = 0x4f04;
+ task->t.regs.ecx = 0x000f;
+ task->t.regs.edx = 0x0001;
+ task->t.flags = TF_BUF_RET | TF_BUF_ESBX;
+ task->t.buf_len = par->vbe_state_size;
+ task->buf = state;
+ err = uvesafb_exec(task);
+
+ if (err || (task->t.regs.eax & 0xffff) != 0x004f) {
+ printk(KERN_WARNING "uvesafb: VBE get state call "
+ "failed (eax=0x%x, err=%d)\n",
+ task->t.regs.eax, err);
+ kfree(state);
+ state = NULL;
+ }
+
+ uvesafb_free(task);
+ return state;
+}
+
+static void uvesafb_vbe_state_restore(struct uvesafb_par *par, u8 *state_buf)
+{
+ struct uvesafb_ktask *task;
+ int err;
+
+ if (!state_buf)
+ return;
+
+ task = uvesafb_prep();
+ if (!task)
+ return;
+
+ task->t.regs.eax = 0x4f04;
+ task->t.regs.ecx = 0x000f;
+ task->t.regs.edx = 0x0002;
+ task->t.buf_len = par->vbe_state_size;
+ task->t.flags = TF_BUF_ESBX;
+ task->buf = state_buf;
+
+ err = uvesafb_exec(task);
+ if (err || (task->t.regs.eax & 0xffff) != 0x004f)
+ printk(KERN_WARNING "uvesafb: VBE state restore call "
+ "failed (eax=0x%x, err=%d)\n",
+ task->t.regs.eax, err);
+
+ uvesafb_free(task);
+}
+
+static int __devinit uvesafb_vbe_getinfo(struct uvesafb_ktask *task,
+ struct uvesafb_par *par)
+{
+ int err;
+
+ task->t.regs.eax = 0x4f00;
+ task->t.flags = TF_VBEIB;
+ task->t.buf_len = sizeof(struct vbe_ib);
+ task->buf = &par->vbe_ib;
+ strncpy(par->vbe_ib.vbe_signature, "VBE2", 4);
+
+ err = uvesafb_exec(task);
+ if (err || (task->t.regs.eax & 0xffff) != 0x004f) {
+ printk(KERN_ERR "uvesafb: Getting VBE info block failed "
+ "(eax=0x%x, err=%d)\n", (u32)task->t.regs.eax,
+ err);
+ return -EINVAL;
+ }
+
+ if (par->vbe_ib.vbe_version < 0x0200) {
+ printk(KERN_ERR "uvesafb: Sorry, pre-VBE 2.0 cards are "
+ "not supported.\n");
+ return -EINVAL;
+ }
+
+ if (!par->vbe_ib.mode_list_ptr) {
+ printk(KERN_ERR "uvesafb: Missing mode list!\n");
+ return -EINVAL;
+ }
+
+ printk(KERN_INFO "uvesafb: ");
+
+ /*
+ * Convert string pointers and the mode list pointer into
+ * usable addresses. Print informational messages about the
+ * video adapter and its vendor.
+ */
+ if (par->vbe_ib.oem_vendor_name_ptr)
+ printk("%s, ",
+ ((char *)task->buf) + par->vbe_ib.oem_vendor_name_ptr);
+
+ if (par->vbe_ib.oem_product_name_ptr)
+ printk("%s, ",
+ ((char *)task->buf) + par->vbe_ib.oem_product_name_ptr);
+
+ if (par->vbe_ib.oem_product_rev_ptr)
+ printk("%s, ",
+ ((char *)task->buf) + par->vbe_ib.oem_product_rev_ptr);
+
+ if (par->vbe_ib.oem_string_ptr)
+ printk("OEM: %s, ",
+ ((char *)task->buf) + par->vbe_ib.oem_string_ptr);
+
+ printk("VBE v%d.%d\n", ((par->vbe_ib.vbe_version & 0xff00) >> 8),
+ par->vbe_ib.vbe_version & 0xff);
+
+ return 0;
+}
+
+static int __devinit uvesafb_vbe_getmodes(struct uvesafb_ktask *task,
+ struct uvesafb_par *par)
+{
+ int off = 0, err;
+ u16 *mode;
+
+ par->vbe_modes_cnt = 0;
+
+ /* Count available modes. */
+ mode = (u16 *) (((u8 *)&par->vbe_ib) + par->vbe_ib.mode_list_ptr);
+ while (*mode != 0xffff) {
+ par->vbe_modes_cnt++;
+ mode++;
+ }
+
+ par->vbe_modes = kzalloc(sizeof(struct vbe_mode_ib) *
+ par->vbe_modes_cnt, GFP_KERNEL);
+ if (!par->vbe_modes)
+ return -ENOMEM;
+
+ /* Get info about all available modes. */
+ mode = (u16 *) (((u8 *)&par->vbe_ib) + par->vbe_ib.mode_list_ptr);
+ while (*mode != 0xffff) {
+ struct vbe_mode_ib *mib;
+
+ uvesafb_reset(task);
+ task->t.regs.eax = 0x4f01;
+ task->t.regs.ecx = (u32) *mode;
+ task->t.flags = TF_BUF_RET | TF_BUF_ESDI;
+ task->t.buf_len = sizeof(struct vbe_mode_ib);
+ task->buf = par->vbe_modes + off;
+
+ err = uvesafb_exec(task);
+ if (err || (task->t.regs.eax & 0xffff) != 0x004f) {
+ printk(KERN_ERR "uvesafb: Getting mode info block "
+ "for mode 0x%x failed (eax=0x%x, err=%d)\n",
+ *mode, (u32)task->t.regs.eax, err);
+ return -EINVAL;
+ }
+
+ mib = task->buf;
+ mib->mode_id = *mode;
+
+ /*
+ * We only want modes that are supported with the current
+ * hardware configuration, color, graphics and that have
+ * support for the LFB.
+ */
+ if ((mib->mode_attr & VBE_MODE_MASK) == VBE_MODE_MASK &&
+ mib->bits_per_pixel >= 8)
+ off++;
+ else
+ par->vbe_modes_cnt--;
+
+ mode++;
+ mib->depth = mib->red_len + mib->green_len + mib->blue_len;
+
+ /*
+ * Handle 8bpp modes and modes with broken color component
+ * lengths.
+ */
+ if (mib->depth == 0 || (mib->depth == 24 &&
+ mib->bits_per_pixel == 32))
+ mib->depth = mib->bits_per_pixel;
+ }
+
+ return 0;
+}
+
+/*
+ * The Protected Mode Interface is 32-bit x86 code, so we only run it on
+ * x86 and not x86_64.
+ */
+#ifdef CONFIG_X86_32
+static int __devinit uvesafb_vbe_getpmi(struct uvesafb_ktask *task,
+ struct uvesafb_par *par)
+{
+ int i, err;
+
+ uvesafb_reset(task);
+ task->t.regs.eax = 0x4f0a;
+ task->t.regs.ebx = 0x0;
+ err = uvesafb_exec(task);
+
+ if ((task->t.regs.eax & 0xffff) != 0x4f || task->t.regs.es < 0xc000) {
+ par->pmi_setpal = par->ypan = 0;
+ } else {
+ par->pmi_base = (u16 *)phys_to_virt(((u32)task->t.regs.es << 4)
+ + task->t.regs.edi);
+ par->pmi_start = (u8 *)par->pmi_base + par->pmi_base[1];
+ par->pmi_pal = (u8 *)par->pmi_base + par->pmi_base[2];
+ printk(KERN_INFO "uvesafb: protected mode interface info at "
+ "%04x:%04x\n",
+ (u16)task->t.regs.es, (u16)task->t.regs.edi);
+ printk(KERN_INFO "uvesafb: pmi: set display start = %p, "
+ "set palette = %p\n", par->pmi_start,
+ par->pmi_pal);
+
+ if (par->pmi_base[3]) {
+ printk(KERN_INFO "uvesafb: pmi: ports = ");
+ for (i = par->pmi_base[3]/2;
+ par->pmi_base[i] != 0xffff; i++)
+ printk("%x ", par->pmi_base[i]);
+ printk("\n");
+
+ if (par->pmi_base[i] != 0xffff) {
+ printk(KERN_INFO "uvesafb: can't handle memory"
+ " requests, pmi disabled\n");
+ par->ypan = par->pmi_setpal = 0;
+ }
+ }
+ }
+ return 0;
+}
+#endif /* CONFIG_X86_32 */
+
+/*
+ * Check whether a video mode is supported by the Video BIOS and is
+ * compatible with the monitor limits.
+ */
+static int __devinit uvesafb_is_valid_mode(struct fb_videomode *mode,
+ struct fb_info *info)
+{
+ if (info->monspecs.gtf) {
+ fb_videomode_to_var(&info->var, mode);
+ if (fb_validate_mode(&info->var, info))
+ return 0;
+ }
+
+ if (uvesafb_vbe_find_mode(info->par, mode->xres, mode->yres, 8,
+ UVESAFB_EXACT_RES) == -1)
+ return 0;
+
+ return 1;
+}
+
+static int __devinit uvesafb_vbe_getedid(struct uvesafb_ktask *task,
+ struct fb_info *info)
+{
+ struct uvesafb_par *par = info->par;
+ int err = 0;
+
+ if (noedid || par->vbe_ib.vbe_version < 0x0300)
+ return -EINVAL;
+
+ task->t.regs.eax = 0x4f15;
+ task->t.regs.ebx = 0;
+ task->t.regs.ecx = 0;
+ task->t.buf_len = 0;
+ task->t.flags = 0;
+
+ err = uvesafb_exec(task);
+
+ if ((task->t.regs.eax & 0xffff) != 0x004f || err)
+ return -EINVAL;
+
+ if ((task->t.regs.ebx & 0x3) == 3) {
+ printk(KERN_INFO "uvesafb: VBIOS/hardware supports both "
+ "DDC1 and DDC2 transfers\n");
+ } else if ((task->t.regs.ebx & 0x3) == 2) {
+ printk(KERN_INFO "uvesafb: VBIOS/hardware supports DDC2 "
+ "transfers\n");
+ } else if ((task->t.regs.ebx & 0x3) == 1) {
+ printk(KERN_INFO "uvesafb: VBIOS/hardware supports DDC1 "
+ "transfers\n");
+ } else {
+ printk(KERN_INFO "uvesafb: VBIOS/hardware doesn't support "
+ "DDC transfers\n");
+ return -EINVAL;
+ }
+
+ task->t.regs.eax = 0x4f15;
+ task->t.regs.ebx = 1;
+ task->t.regs.ecx = task->t.regs.edx = 0;
+ task->t.flags = TF_BUF_RET | TF_BUF_ESDI;
+ task->t.buf_len = EDID_LENGTH;
+ task->buf = kzalloc(EDID_LENGTH, GFP_KERNEL);
+
+ err = uvesafb_exec(task);
+
+ if ((task->t.regs.eax & 0xffff) == 0x004f && !err) {
+ fb_edid_to_monspecs(task->buf, &info->monspecs);
+
+ if (info->monspecs.vfmax && info->monspecs.hfmax) {
+ /*
+ * If the maximum pixel clock wasn't specified in
+ * the EDID block, set it to 300 MHz.
+ */
+ if (info->monspecs.dclkmax == 0)
+ info->monspecs.dclkmax = 300 * 1000000;
+ info->monspecs.gtf = 1;
+ }
+ } else {
+ err = -EINVAL;
+ }
+
+ kfree(task->buf);
+ return err;
+}
+
+static void __devinit uvesafb_vbe_getmonspecs(struct uvesafb_ktask *task,
+ struct fb_info *info)
+{
+ struct uvesafb_par *par = info->par;
+ int i;
+
+ memset(&info->monspecs, 0, sizeof(info->monspecs));
+
+ /*
+ * If we don't get all necessary data from the EDID block,
+ * mark it as incompatible with the GTF and set nocrtc so
+ * that we always use the default BIOS refresh rate.
+ */
+ if (uvesafb_vbe_getedid(task, info)) {
+ info->monspecs.gtf = 0;
+ par->nocrtc = 1;
+ }
+
+ /* Kernel command line overrides. */
+ if (maxclk)
+ info->monspecs.dclkmax = maxclk * 1000000;
+ if (maxvf)
+ info->monspecs.vfmax = maxvf;
+ if (maxhf)
+ info->monspecs.hfmax = maxhf * 1000;
+
+ /*
+ * In case DDC transfers are not supported, the user can provide
+ * monitor limits manually. Lower limits are set to "safe" values.
+ */
+ if (info->monspecs.gtf == 0 && maxclk && maxvf && maxhf) {
+ info->monspecs.dclkmin = 0;
+ info->monspecs.vfmin = 60;
+ info->monspecs.hfmin = 29000;
+ info->monspecs.gtf = 1;
+ par->nocrtc = 0;
+ }
+
+ if (info->monspecs.gtf)
+ printk(KERN_INFO
+ "uvesafb: monitor limits: vf = %d Hz, hf = %d kHz, "
+ "clk = %d MHz\n", info->monspecs.vfmax,
+ (int)(info->monspecs.hfmax / 1000),
+ (int)(info->monspecs.dclkmax / 1000000));
+ else
+ printk(KERN_INFO "uvesafb: no monitor limits have been set, "
+ "default refresh rate will be used\n");
+
+ /* Add VBE modes to the modelist. */
+ for (i = 0; i < par->vbe_modes_cnt; i++) {
+ struct fb_var_screeninfo var;
+ struct vbe_mode_ib *mode;
+ struct fb_videomode vmode;
+
+ mode = &par->vbe_modes[i];
+ memset(&var, 0, sizeof(var));
+
+ var.xres = mode->x_res;
+ var.yres = mode->y_res;
+
+ fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60, &var, info);
+ fb_var_to_videomode(&vmode, &var);
+ fb_add_videomode(&vmode, &info->modelist);
+ }
+
+ /* Add valid VESA modes to our modelist. */
+ for (i = 0; i < VESA_MODEDB_SIZE; i++) {
+ if (uvesafb_is_valid_mode((struct fb_videomode *)
+ &vesa_modes[i], info))
+ fb_add_videomode(&vesa_modes[i], &info->modelist);
+ }
+
+ for (i = 0; i < info->monspecs.modedb_len; i++) {
+ if (uvesafb_is_valid_mode(&info->monspecs.modedb[i], info))
+ fb_add_videomode(&info->monspecs.modedb[i],
+ &info->modelist);
+ }
+
+ return;
+}
+
+static void __devinit uvesafb_vbe_getstatesize(struct uvesafb_ktask *task,
+ struct uvesafb_par *par)
+{
+ int err;
+
+ uvesafb_reset(task);
+
+ /*
+ * Get the VBE state buffer size. We want all available
+ * hardware state data (CL = 0x0f).
+ */
+ task->t.regs.eax = 0x4f04;
+ task->t.regs.ecx = 0x000f;
+ task->t.regs.edx = 0x0000;
+ task->t.flags = 0;
+
+ err = uvesafb_exec(task);
+
+ if (err || (task->t.regs.eax & 0xffff) != 0x004f) {
+ printk(KERN_WARNING "uvesafb: VBE state buffer size "
+ "cannot be determined (eax=0x%x, err=%d)\n",
+ task->t.regs.eax, err);
+ par->vbe_state_size = 0;
+ return;
+ }
+
+ par->vbe_state_size = 64 * (task->t.regs.ebx & 0xffff);
+}
+
+static int __devinit uvesafb_vbe_init(struct fb_info *info)
+{
+ struct uvesafb_ktask *task = NULL;
+ struct uvesafb_par *par = info->par;
+ int err;
+
+ task = uvesafb_prep();
+ if (!task)
+ return -ENOMEM;
+
+ err = uvesafb_vbe_getinfo(task, par);
+ if (err)
+ goto out;
+
+ err = uvesafb_vbe_getmodes(task, par);
+ if (err)
+ goto out;
+
+ par->nocrtc = nocrtc;
+#ifdef CONFIG_X86_32
+ par->pmi_setpal = pmi_setpal;
+ par->ypan = ypan;
+
+ if (par->pmi_setpal || par->ypan)
+ uvesafb_vbe_getpmi(task, par);
+#else
+ /* The protected mode interface is not available on non-x86. */
+ par->pmi_setpal = par->ypan = 0;
+#endif
+
+ INIT_LIST_HEAD(&info->modelist);
+ uvesafb_vbe_getmonspecs(task, info);
+ uvesafb_vbe_getstatesize(task, par);
+
+out: uvesafb_free(task);
+ return err;
+}
+
+static int __devinit uvesafb_vbe_init_mode(struct fb_info *info)
+{
+ struct list_head *pos;
+ struct fb_modelist *modelist;
+ struct fb_videomode *mode;
+ struct uvesafb_par *par = info->par;
+ int i, modeid;
+
+ /* Has the user requested a specific VESA mode? */
+ if (vbemode) {
+ for (i = 0; i < par->vbe_modes_cnt; i++) {
+ if (par->vbe_modes[i].mode_id == vbemode) {
+ fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60,
+ &info->var, info);
+ /*
+ * With pixclock set to 0, the default BIOS
+ * timings will be used in set_par().
+ */
+ info->var.pixclock = 0;
+ modeid = i;
+ goto gotmode;
+ }
+ }
+ printk(KERN_INFO "uvesafb: requested VBE mode 0x%x is "
+ "unavailable\n", vbemode);
+ vbemode = 0;
+ }
+
+ /* Count the modes in the modelist */
+ i = 0;
+ list_for_each(pos, &info->modelist)
+ i++;
+
+ /*
+ * Convert the modelist into a modedb so that we can use it with
+ * fb_find_mode().
+ */
+ mode = kzalloc(i * sizeof(*mode), GFP_KERNEL);
+ if (mode) {
+ i = 0;
+ list_for_each(pos, &info->modelist) {
+ modelist = list_entry(pos, struct fb_modelist, list);
+ mode[i] = modelist->mode;
+ i++;
+ }
+
+ if (!mode_option)
+ mode_option = UVESAFB_DEFAULT_MODE;
+
+ i = fb_find_mode(&info->var, info, mode_option, mode, i,
+ NULL, 8);
+
+ kfree(mode);
+ }
+
+ /* fb_find_mode() failed */
+ if (i == 0 || i >= 3) {
+ info->var.xres = 640;
+ info->var.yres = 480;
+ mode = (struct fb_videomode *)
+ fb_find_best_mode(&info->var, &info->modelist);
+
+ if (mode) {
+ fb_videomode_to_var(&info->var, mode);
+ } else {
+ modeid = par->vbe_modes[0].mode_id;
+ fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60,
+ &info->var, info);
+ goto gotmode;
+ }
+ }
+
+ /* Look for a matching VBE mode. */
+ modeid = uvesafb_vbe_find_mode(par, info->var.xres, info->var.yres,
+ info->var.bits_per_pixel, UVESAFB_EXACT_RES);
+
+ if (modeid == -1)
+ return -EINVAL;
+
+gotmode:
+ uvesafb_setup_var(&info->var, info, &par->vbe_modes[modeid]);
+
+ /*
+ * If we are not VBE3.0+ compliant, we're done -- the BIOS will
+ * ignore our timings anyway.
+ */
+ if (par->vbe_ib.vbe_version < 0x0300 || par->nocrtc)
+ fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60,
+ &info->var, info);
+
+ return modeid;
+}
+
+static int uvesafb_setpalette(struct uvesafb_pal_entry *entries, int count,
+ int start, struct fb_info *info)
+{
+ struct uvesafb_ktask *task;
+#ifdef CONFIG_X86
+ struct uvesafb_par *par = info->par;
+ int i = par->mode_idx;
+#endif
+ int err = 0;
+
+ /*
+ * We support palette modifications for 8 bpp modes only, so
+ * there can never be more than 256 entries.
+ */
+ if (start + count > 256)
+ return -EINVAL;
+
+#ifdef CONFIG_X86
+ /* Use VGA registers if mode is VGA-compatible. */
+ if (i >= 0 && i < par->vbe_modes_cnt &&
+ par->vbe_modes[i].mode_attr & VBE_MODE_VGACOMPAT) {
+ for (i = 0; i < count; i++) {
+ outb_p(start + i, dac_reg);
+ outb_p(entries[i].red, dac_val);
+ outb_p(entries[i].green, dac_val);
+ outb_p(entries[i].blue, dac_val);
+ }
+ }
+#ifdef CONFIG_X86_32
+ else if (par->pmi_setpal) {
+ __asm__ __volatile__(
+ "call *(%%esi)"
+ : /* no return value */
+ : "a" (0x4f09), /* EAX */
+ "b" (0), /* EBX */
+ "c" (count), /* ECX */
+ "d" (start), /* EDX */
+ "D" (entries), /* EDI */
+ "S" (&par->pmi_pal)); /* ESI */
+ }
+#endif /* CONFIG_X86_32 */
+ else
+#endif /* CONFIG_X86 */
+ {
+ task = uvesafb_prep();
+ if (!task)
+ return -ENOMEM;
+
+ task->t.regs.eax = 0x4f09;
+ task->t.regs.ebx = 0x0;
+ task->t.regs.ecx = count;
+ task->t.regs.edx = start;
+ task->t.flags = TF_BUF_ESDI;
+ task->t.buf_len = sizeof(struct uvesafb_pal_entry) * count;
+ task->buf = entries;
+
+ err = uvesafb_exec(task);
+ if ((task->t.regs.eax & 0xffff) != 0x004f)
+ err = 1;
+
+ uvesafb_free(task);
+ }
+ return err;
+}
+
+static int uvesafb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *info)
+{
+ struct uvesafb_pal_entry entry;
+ int shift = 16 - info->var.green.length;
+ int err = 0;
+
+ if (regno >= info->cmap.len)
+ return -EINVAL;
+
+ if (info->var.bits_per_pixel == 8) {
+ entry.red = red >> shift;
+ entry.green = green >> shift;
+ entry.blue = blue >> shift;
+ entry.pad = 0;
+
+ err = uvesafb_setpalette(&entry, 1, regno, info);
+ } else if (regno < 16) {
+ switch (info->var.bits_per_pixel) {
+ case 16:
+ if (info->var.red.offset == 10) {
+ /* 1:5:5:5 */
+ ((u32 *) (info->pseudo_palette))[regno] =
+ ((red & 0xf800) >> 1) |
+ ((green & 0xf800) >> 6) |
+ ((blue & 0xf800) >> 11);
+ } else {
+ /* 0:5:6:5 */
+ ((u32 *) (info->pseudo_palette))[regno] =
+ ((red & 0xf800) ) |
+ ((green & 0xfc00) >> 5) |
+ ((blue & 0xf800) >> 11);
+ }
+ break;
+
+ case 24:
+ case 32:
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+ ((u32 *)(info->pseudo_palette))[regno] =
+ (red << info->var.red.offset) |
+ (green << info->var.green.offset) |
+ (blue << info->var.blue.offset);
+ break;
+ }
+ }
+ return err;
+}
+
+static int uvesafb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
+{
+ struct uvesafb_pal_entry *entries;
+ int shift = 16 - info->var.green.length;
+ int i, err = 0;
+
+ if (info->var.bits_per_pixel == 8) {
+ if (cmap->start + cmap->len > info->cmap.start +
+ info->cmap.len || cmap->start < info->cmap.start)
+ return -EINVAL;
+
+ entries = kmalloc(sizeof(*entries) * cmap->len, GFP_KERNEL);
+ if (!entries)
+ return -ENOMEM;
+
+ for (i = 0; i < cmap->len; i++) {
+ entries[i].red = cmap->red[i] >> shift;
+ entries[i].green = cmap->green[i] >> shift;
+ entries[i].blue = cmap->blue[i] >> shift;
+ entries[i].pad = 0;
+ }
+ err = uvesafb_setpalette(entries, cmap->len, cmap->start, info);
+ kfree(entries);
+ } else {
+ /*
+ * For modes with bpp > 8, we only set the pseudo palette in
+ * the fb_info struct. We rely on uvesafb_setcolreg to do all
+ * sanity checking.
+ */
+ for (i = 0; i < cmap->len; i++) {
+ err |= uvesafb_setcolreg(cmap->start + i, cmap->red[i],
+ cmap->green[i], cmap->blue[i],
+ 0, info);
+ }
+ }
+ return err;
+}
+
+static int uvesafb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+#ifdef CONFIG_X86_32
+ int offset;
+ struct uvesafb_par *par = info->par;
+
+ offset = (var->yoffset * info->fix.line_length + var->xoffset) / 4;
+
+ /*
+ * It turns out it's not the best idea to do panning via vm86,
+ * so we only allow it if we have a PMI.
+ */
+ if (par->pmi_start) {
+ __asm__ __volatile__(
+ "call *(%%edi)"
+ : /* no return value */
+ : "a" (0x4f07), /* EAX */
+ "b" (0), /* EBX */
+ "c" (offset), /* ECX */
+ "d" (offset >> 16), /* EDX */
+ "D" (&par->pmi_start)); /* EDI */
+ }
+#endif
+ return 0;
+}
+
+static int uvesafb_blank(int blank, struct fb_info *info)
+{
+ struct uvesafb_ktask *task;
+ int err = 1;
+#ifdef CONFIG_X86
+ struct uvesafb_par *par = info->par;
+
+ if (par->vbe_ib.capabilities & VBE_CAP_VGACOMPAT) {
+ int loop = 10000;
+ u8 seq = 0, crtc17 = 0;
+
+ if (blank == FB_BLANK_POWERDOWN) {
+ seq = 0x20;
+ crtc17 = 0x00;
+ err = 0;
+ } else {
+ seq = 0x00;
+ crtc17 = 0x80;
+ err = (blank == FB_BLANK_UNBLANK) ? 0 : -EINVAL;
+ }
+
+ vga_wseq(NULL, 0x00, 0x01);
+ seq |= vga_rseq(NULL, 0x01) & ~0x20;
+ vga_wseq(NULL, 0x00, seq);
+
+ crtc17 |= vga_rcrt(NULL, 0x17) & ~0x80;
+ while (loop--);
+ vga_wcrt(NULL, 0x17, crtc17);
+ vga_wseq(NULL, 0x00, 0x03);
+ } else
+#endif /* CONFIG_X86 */
+ {
+ task = uvesafb_prep();
+ if (!task)
+ return -ENOMEM;
+
+ task->t.regs.eax = 0x4f10;
+ switch (blank) {
+ case FB_BLANK_UNBLANK:
+ task->t.regs.ebx = 0x0001;
+ break;
+ case FB_BLANK_NORMAL:
+ task->t.regs.ebx = 0x0101; /* standby */
+ break;
+ case FB_BLANK_POWERDOWN:
+ task->t.regs.ebx = 0x0401; /* powerdown */
+ break;
+ default:
+ goto out;
+ }
+
+ err = uvesafb_exec(task);
+ if (err || (task->t.regs.eax & 0xffff) != 0x004f)
+ err = 1;
+out: uvesafb_free(task);
+ }
+ return err;
+}
+
+static int uvesafb_open(struct fb_info *info, int user)
+{
+ struct uvesafb_par *par = info->par;
+ int cnt = atomic_read(&par->ref_count);
+
+ if (!cnt && par->vbe_state_size)
+ par->vbe_state_orig = uvesafb_vbe_state_save(par);
+
+ atomic_inc(&par->ref_count);
+ return 0;
+}
+
+static int uvesafb_release(struct fb_info *info, int user)
+{
+ struct uvesafb_ktask *task = NULL;
+ struct uvesafb_par *par = info->par;
+ int cnt = atomic_read(&par->ref_count);
+
+ if (!cnt)
+ return -EINVAL;
+
+ if (cnt != 1)
+ goto out;
+
+ task = uvesafb_prep();
+ if (!task)
+ goto out;
+
+ /* First, try to set the standard 80x25 text mode. */
+ task->t.regs.eax = 0x0003;
+ uvesafb_exec(task);
+
+ /*
+ * Now try to restore whatever hardware state we might have
+ * saved when the fb device was first opened.
+ */
+ uvesafb_vbe_state_restore(par, par->vbe_state_orig);
+out:
+ atomic_dec(&par->ref_count);
+ if (task)
+ uvesafb_free(task);
+ return 0;
+}
+
+static int uvesafb_set_par(struct fb_info *info)
+{
+ struct uvesafb_par *par = info->par;
+ struct uvesafb_ktask *task = NULL;
+ struct vbe_crtc_ib *crtc = NULL;
+ struct vbe_mode_ib *mode = NULL;
+ int i, err = 0, depth = info->var.bits_per_pixel;
+
+ if (depth > 8 && depth != 32)
+ depth = info->var.red.length + info->var.green.length +
+ info->var.blue.length;
+
+ i = uvesafb_vbe_find_mode(par, info->var.xres, info->var.yres, depth,
+ UVESAFB_EXACT_RES | UVESAFB_EXACT_DEPTH);
+ if (i >= 0)
+ mode = &par->vbe_modes[i];
+ else
+ return -EINVAL;
+
+ task = uvesafb_prep();
+ if (!task)
+ return -ENOMEM;
+setmode:
+ task->t.regs.eax = 0x4f02;
+ task->t.regs.ebx = mode->mode_id | 0x4000; /* use LFB */
+
+ if (par->vbe_ib.vbe_version >= 0x0300 && !par->nocrtc &&
+ info->var.pixclock != 0) {
+ task->t.regs.ebx |= 0x0800; /* use CRTC data */
+ task->t.flags = TF_BUF_ESDI;
+ crtc = kzalloc(sizeof(struct vbe_crtc_ib), GFP_KERNEL);
+ if (!crtc) {
+ err = -ENOMEM;
+ goto out;
+ }
+ crtc->horiz_start = info->var.xres + info->var.right_margin;
+ crtc->horiz_end = crtc->horiz_start + info->var.hsync_len;
+ crtc->horiz_total = crtc->horiz_end + info->var.left_margin;
+
+ crtc->vert_start = info->var.yres + info->var.lower_margin;
+ crtc->vert_end = crtc->vert_start + info->var.vsync_len;
+ crtc->vert_total = crtc->vert_end + info->var.upper_margin;
+
+ crtc->pixel_clock = PICOS2KHZ(info->var.pixclock) * 1000;
+ crtc->refresh_rate = (u16)(100 * (crtc->pixel_clock /
+ (crtc->vert_total * crtc->horiz_total)));
+
+ if (info->var.vmode & FB_VMODE_DOUBLE)
+ crtc->flags |= 0x1;
+ if (info->var.vmode & FB_VMODE_INTERLACED)
+ crtc->flags |= 0x2;
+ if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
+ crtc->flags |= 0x4;
+ if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
+ crtc->flags |= 0x8;
+ memcpy(&par->crtc, crtc, sizeof(*crtc));
+ } else {
+ memset(&par->crtc, 0, sizeof(*crtc));
+ }
+
+ task->t.buf_len = sizeof(struct vbe_crtc_ib);
+ task->buf = &par->crtc;
+
+ err = uvesafb_exec(task);
+ if (err || (task->t.regs.eax & 0xffff) != 0x004f) {
+ /*
+ * The mode switch might have failed because we tried to
+ * use our own timings. Try again with the default timings.
+ */
+ if (crtc != NULL) {
+ printk(KERN_WARNING "uvesafb: mode switch failed "
+ "(eax=0x%x, err=%d). Trying again with "
+ "default timings.\n", task->t.regs.eax, err);
+ uvesafb_reset(task);
+ kfree(crtc);
+ crtc = NULL;
+ info->var.pixclock = 0;
+ goto setmode;
+ } else {
+ printk(KERN_ERR "uvesafb: mode switch failed (eax="
+ "0x%x, err=%d)\n", task->t.regs.eax, err);
+ err = -EINVAL;
+ goto out;
+ }
+ }
+ par->mode_idx = i;
+
+ /* For 8bpp modes, always try to set the DAC to 8 bits. */
+ if (par->vbe_ib.capabilities & VBE_CAP_CAN_SWITCH_DAC &&
+ mode->bits_per_pixel <= 8) {
+ uvesafb_reset(task);
+ task->t.regs.eax = 0x4f08;
+ task->t.regs.ebx = 0x0800;
+
+ err = uvesafb_exec(task);
+ if (err || (task->t.regs.eax & 0xffff) != 0x004f ||
+ ((task->t.regs.ebx & 0xff00) >> 8) != 8) {
+ /*
+ * We've failed to set the DAC palette format -
+ * time to correct var.
+ */
+ info->var.red.length = 6;
+ info->var.green.length = 6;
+ info->var.blue.length = 6;
+ }
+ }
+
+ info->fix.visual = (info->var.bits_per_pixel == 8) ?
+ FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+ info->fix.line_length = mode->bytes_per_scan_line;
+
+out: if (crtc != NULL)
+ kfree(crtc);
+ uvesafb_free(task);
+
+ return err;
+}
+
+static void uvesafb_check_limits(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ const struct fb_videomode *mode;
+ struct uvesafb_par *par = info->par;
+
+ /*
+ * If pixclock is set to 0, then we're using default BIOS timings
+ * and thus don't have to perform any checks here.
+ */
+ if (!var->pixclock)
+ return;
+
+ if (par->vbe_ib.vbe_version < 0x0300) {
+ fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60, var, info);
+ return;
+ }
+
+ if (!fb_validate_mode(var, info))
+ return;
+
+ mode = fb_find_best_mode(var, &info->modelist);
+ if (mode) {
+ if (mode->xres == var->xres && mode->yres == var->yres &&
+ !(mode->vmode & (FB_VMODE_INTERLACED | FB_VMODE_DOUBLE))) {
+ fb_videomode_to_var(var, mode);
+ return;
+ }
+ }
+
+ if (info->monspecs.gtf && !fb_get_mode(FB_MAXTIMINGS, 0, var, info))
+ return;
+ /* Use default refresh rate */
+ var->pixclock = 0;
+}
+
+static int uvesafb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct uvesafb_par *par = info->par;
+ struct vbe_mode_ib *mode = NULL;
+ int match = -1;
+ int depth = var->red.length + var->green.length + var->blue.length;
+
+ /*
+ * Various apps will use bits_per_pixel to set the color depth,
+ * which is theoretically incorrect, but which we'll try to handle
+ * here.
+ */
+ if (depth == 0 || abs(depth - var->bits_per_pixel) >= 8)
+ depth = var->bits_per_pixel;
+
+ match = uvesafb_vbe_find_mode(par, var->xres, var->yres, depth,
+ UVESAFB_EXACT_RES);
+ if (match == -1)
+ return -EINVAL;
+
+ mode = &par->vbe_modes[match];
+ uvesafb_setup_var(var, info, mode);
+
+ /*
+ * Check whether we have remapped enough memory for this mode.
+ * We might be called at an early stage, when we haven't remapped
+ * any memory yet, in which case we simply skip the check.
+ */
+ if (var->yres * mode->bytes_per_scan_line > info->fix.smem_len
+ && info->fix.smem_len)
+ return -EINVAL;
+
+ if ((var->vmode & FB_VMODE_DOUBLE) &&
+ !(par->vbe_modes[match].mode_attr & 0x100))
+ var->vmode &= ~FB_VMODE_DOUBLE;
+
+ if ((var->vmode & FB_VMODE_INTERLACED) &&
+ !(par->vbe_modes[match].mode_attr & 0x200))
+ var->vmode &= ~FB_VMODE_INTERLACED;
+
+ uvesafb_check_limits(var, info);
+
+ var->xres_virtual = var->xres;
+ var->yres_virtual = (par->ypan) ?
+ info->fix.smem_len / mode->bytes_per_scan_line :
+ var->yres;
+ return 0;
+}
+
+static void uvesafb_save_state(struct fb_info *info)
+{
+ struct uvesafb_par *par = info->par;
+
+ if (par->vbe_state_saved)
+ kfree(par->vbe_state_saved);
+
+ par->vbe_state_saved = uvesafb_vbe_state_save(par);
+}
+
+static void uvesafb_restore_state(struct fb_info *info)
+{
+ struct uvesafb_par *par = info->par;
+
+ uvesafb_vbe_state_restore(par, par->vbe_state_saved);
+}
+
+static struct fb_ops uvesafb_ops = {
+ .owner = THIS_MODULE,
+ .fb_open = uvesafb_open,
+ .fb_release = uvesafb_release,
+ .fb_setcolreg = uvesafb_setcolreg,
+ .fb_setcmap = uvesafb_setcmap,
+ .fb_pan_display = uvesafb_pan_display,
+ .fb_blank = uvesafb_blank,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+ .fb_check_var = uvesafb_check_var,
+ .fb_set_par = uvesafb_set_par,
+ .fb_save_state = uvesafb_save_state,
+ .fb_restore_state = uvesafb_restore_state,
+};
+
+static void __devinit uvesafb_init_info(struct fb_info *info,
+ struct vbe_mode_ib *mode)
+{
+ unsigned int size_vmode;
+ unsigned int size_remap;
+ unsigned int size_total;
+ struct uvesafb_par *par = info->par;
+ int i, h;
+
+ info->pseudo_palette = ((u8 *)info->par + sizeof(struct uvesafb_par));
+ info->fix = uvesafb_fix;
+ info->fix.ypanstep = par->ypan ? 1 : 0;
+ info->fix.ywrapstep = (par->ypan > 1) ? 1 : 0;
+
+ /*
+ * If we were unable to get the state buffer size, disable
+ * functions for saving and restoring the hardware state.
+ */
+ if (par->vbe_state_size == 0) {
+ info->fbops->fb_save_state = NULL;
+ info->fbops->fb_restore_state = NULL;
+ }
+
+ /* Disable blanking if the user requested so. */
+ if (!blank)
+ info->fbops->fb_blank = NULL;
+
+ /*
+ * Find out how much IO memory is required for the mode with
+ * the highest resolution.
+ */
+ size_remap = 0;
+ for (i = 0; i < par->vbe_modes_cnt; i++) {
+ h = par->vbe_modes[i].bytes_per_scan_line *
+ par->vbe_modes[i].y_res;
+ if (h > size_remap)
+ size_remap = h;
+ }
+ size_remap *= 2;
+
+ /*
+ * size_vmode -- that is the amount of memory needed for the
+ * used video mode, i.e. the minimum amount of
+ * memory we need.
+ */
+ if (mode != NULL) {
+ size_vmode = info->var.yres * mode->bytes_per_scan_line;
+ } else {
+ size_vmode = info->var.yres * info->var.xres *
+ ((info->var.bits_per_pixel + 7) >> 3);
+ }
+
+ /*
+ * size_total -- all video memory we have. Used for mtrr
+ * entries, resource allocation and bounds
+ * checking.
+ */
+ size_total = par->vbe_ib.total_memory * 65536;
+ if (vram_total)
+ size_total = vram_total * 1024 * 1024;
+ if (size_total < size_vmode)
+ size_total = size_vmode;
+
+ /*
+ * size_remap -- the amount of video memory we are going to
+ * use for vesafb. With modern cards it is no
+ * option to simply use size_total as th
+ * wastes plenty of kernel address space.
+ */
+ if (vram_remap)
+ size_remap = vram_remap * 1024 * 1024;
+ if (size_remap < size_vmode)
+ size_remap = size_vmode;
+ if (size_remap > size_total)
+ size_remap = size_total;
+
+ info->fix.smem_len = size_remap;
+ info->fix.smem_start = mode->phys_base_ptr;
+
+ /*
+ * We have to set yres_virtual here because when setup_var() was
+ * called, smem_len wasn't defined yet.
+ */
+ info->var.yres_virtual = info->fix.smem_len /
+ mode->bytes_per_scan_line;
+
+ if (par->ypan && info->var.yres_virtual > info->var.yres) {
+ printk(KERN_INFO "uvesafb: scrolling: %s "
+ "using protected mode interface, "
+ "yres_virtual=%d\n",
+ (par->ypan > 1) ? "ywrap" : "ypan",
+ info->var.yres_virtual);
+ } else {
+ printk(KERN_INFO "uvesafb: scrolling: redraw\n");
+ info->var.yres_virtual = info->var.yres;
+ par->ypan = 0;
+ }
+
+ info->flags = FBINFO_FLAG_DEFAULT |
+ (par->ypan) ? FBINFO_HWACCEL_YPAN : 0;
+
+ if (!par->ypan)
+ info->fbops->fb_pan_display = NULL;
+}
+
+static void uvesafb_init_mtrr(struct fb_info *info)
+{
+#ifdef CONFIG_MTRR
+ if (mtrr && !(info->fix.smem_start & (PAGE_SIZE - 1))) {
+ int temp_size = info->fix.smem_len;
+ unsigned int type = 0;
+
+ switch (mtrr) {
+ case 1:
+ type = MTRR_TYPE_UNCACHABLE;
+ break;
+ case 2:
+ type = MTRR_TYPE_WRBACK;
+ break;
+ case 3:
+ type = MTRR_TYPE_WRCOMB;
+ break;
+ case 4:
+ type = MTRR_TYPE_WRTHROUGH;
+ break;
+ default:
+ type = 0;
+ break;
+ }
+
+ if (type) {
+ int rc;
+
+ /* Find the largest power-of-two */
+ while (temp_size & (temp_size - 1))
+ temp_size &= (temp_size - 1);
+
+ /* Try and find a power of two to add */
+ do {
+ rc = mtrr_add(info->fix.smem_start,
+ temp_size, type, 1);
+ temp_size >>= 1;
+ } while (temp_size >= PAGE_SIZE && rc == -EINVAL);
+ }
+ }
+#endif /* CONFIG_MTRR */
+}
+
+
+static ssize_t uvesafb_show_vbe_ver(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
+ struct uvesafb_par *par = info->par;
+
+ return snprintf(buf, PAGE_SIZE, "%.4x\n", par->vbe_ib.vbe_version);
+}
+
+static DEVICE_ATTR(vbe_version, S_IRUGO, uvesafb_show_vbe_ver, NULL);
+
+static ssize_t uvesafb_show_vbe_modes(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
+ struct uvesafb_par *par = info->par;
+ int ret = 0, i;
+
+ for (i = 0; i < par->vbe_modes_cnt && ret < PAGE_SIZE; i++) {
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "%dx%d-%d, 0x%.4x\n",
+ par->vbe_modes[i].x_res, par->vbe_modes[i].y_res,
+ par->vbe_modes[i].depth, par->vbe_modes[i].mode_id);
+ }
+
+ return ret;
+}
+
+static DEVICE_ATTR(vbe_modes, S_IRUGO, uvesafb_show_vbe_modes, NULL);
+
+static ssize_t uvesafb_show_vendor(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
+ struct uvesafb_par *par = info->par;
+
+ if (par->vbe_ib.oem_vendor_name_ptr)
+ return snprintf(buf, PAGE_SIZE, "%s\n", (char *)
+ (&par->vbe_ib) + par->vbe_ib.oem_vendor_name_ptr);
+ else
+ return 0;
+}
+
+static DEVICE_ATTR(oem_vendor, S_IRUGO, uvesafb_show_vendor, NULL);
+
+static ssize_t uvesafb_show_product_name(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
+ struct uvesafb_par *par = info->par;
+
+ if (par->vbe_ib.oem_product_name_ptr)
+ return snprintf(buf, PAGE_SIZE, "%s\n", (char *)
+ (&par->vbe_ib) + par->vbe_ib.oem_product_name_ptr);
+ else
+ return 0;
+}
+
+static DEVICE_ATTR(oem_product_name, S_IRUGO, uvesafb_show_product_name, NULL);
+
+static ssize_t uvesafb_show_product_rev(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
+ struct uvesafb_par *par = info->par;
+
+ if (par->vbe_ib.oem_product_rev_ptr)
+ return snprintf(buf, PAGE_SIZE, "%s\n", (char *)
+ (&par->vbe_ib) + par->vbe_ib.oem_product_rev_ptr);
+ else
+ return 0;
+}
+
+static DEVICE_ATTR(oem_product_rev, S_IRUGO, uvesafb_show_product_rev, NULL);
+
+static ssize_t uvesafb_show_oem_string(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
+ struct uvesafb_par *par = info->par;
+
+ if (par->vbe_ib.oem_string_ptr)
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ (char *)(&par->vbe_ib) + par->vbe_ib.oem_string_ptr);
+ else
+ return 0;
+}
+
+static DEVICE_ATTR(oem_string, S_IRUGO, uvesafb_show_oem_string, NULL);
+
+static ssize_t uvesafb_show_nocrtc(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
+ struct uvesafb_par *par = info->par;
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", par->nocrtc);
+}
+
+static ssize_t uvesafb_store_nocrtc(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
+ struct uvesafb_par *par = info->par;
+
+ if (count > 0) {
+ if (buf[0] == '0')
+ par->nocrtc = 0;
+ else
+ par->nocrtc = 1;
+ }
+ return count;
+}
+
+static DEVICE_ATTR(nocrtc, S_IRUGO | S_IWUSR, uvesafb_show_nocrtc,
+ uvesafb_store_nocrtc);
+
+static struct attribute *uvesafb_dev_attrs[] = {
+ &dev_attr_vbe_version.attr,
+ &dev_attr_vbe_modes.attr,
+ &dev_attr_oem_vendor.attr,
+ &dev_attr_oem_product_name.attr,
+ &dev_attr_oem_product_rev.attr,
+ &dev_attr_oem_string.attr,
+ &dev_attr_nocrtc.attr,
+ NULL,
+};
+
+static struct attribute_group uvesafb_dev_attgrp = {
+ .name = NULL,
+ .attrs = uvesafb_dev_attrs,
+};
+
+static int __devinit uvesafb_probe(struct platform_device *dev)
+{
+ struct fb_info *info;
+ struct vbe_mode_ib *mode = NULL;
+ struct uvesafb_par *par;
+ int err = 0, i;
+
+ info = framebuffer_alloc(sizeof(*par) + sizeof(u32) * 256, &dev->dev);
+ if (!info)
+ return -ENOMEM;
+
+ par = info->par;
+
+ err = uvesafb_vbe_init(info);
+ if (err) {
+ printk(KERN_ERR "uvesafb: vbe_init() failed with %d\n", err);
+ goto out;
+ }
+
+ info->fbops = &uvesafb_ops;
+
+ i = uvesafb_vbe_init_mode(info);
+ if (i < 0) {
+ err = -EINVAL;
+ goto out;
+ } else {
+ mode = &par->vbe_modes[i];
+ }
+
+ if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
+ err = -ENXIO;
+ goto out;
+ }
+
+ uvesafb_init_info(info, mode);
+
+ if (!request_mem_region(info->fix.smem_start, info->fix.smem_len,
+ "uvesafb")) {
+ printk(KERN_ERR "uvesafb: cannot reserve video memory at "
+ "0x%lx\n", info->fix.smem_start);
+ err = -EIO;
+ goto out_mode;
+ }
+
+ info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
+
+ if (!info->screen_base) {
+ printk(KERN_ERR
+ "uvesafb: abort, cannot ioremap 0x%x bytes of video "
+ "memory at 0x%lx\n",
+ info->fix.smem_len, info->fix.smem_start);
+ err = -EIO;
+ goto out_mem;
+ }
+
+ if (!request_region(0x3c0, 32, "uvesafb")) {
+ printk(KERN_ERR "uvesafb: request region 0x3c0-0x3e0 failed\n");
+ err = -EIO;
+ goto out_unmap;
+ }
+
+ uvesafb_init_mtrr(info);
+ platform_set_drvdata(dev, info);
+
+ if (register_framebuffer(info) < 0) {
+ printk(KERN_ERR
+ "uvesafb: failed to register framebuffer device\n");
+ err = -EINVAL;
+ goto out_reg;
+ }
+
+ printk(KERN_INFO "uvesafb: framebuffer at 0x%lx, mapped to 0x%p, "
+ "using %dk, total %dk\n", info->fix.smem_start,
+ info->screen_base, info->fix.smem_len/1024,
+ par->vbe_ib.total_memory * 64);
+ printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
+ info->fix.id);
+
+ err = sysfs_create_group(&dev->dev.kobj, &uvesafb_dev_attgrp);
+ if (err != 0)
+ printk(KERN_WARNING "fb%d: failed to register attributes\n",
+ info->node);
+
+ return 0;
+
+out_reg:
+ release_region(0x3c0, 32);
+out_unmap:
+ iounmap(info->screen_base);
+out_mem:
+ release_mem_region(info->fix.smem_start, info->fix.smem_len);
+out_mode:
+ if (!list_empty(&info->modelist))
+ fb_destroy_modelist(&info->modelist);
+ fb_destroy_modedb(info->monspecs.modedb);
+ fb_dealloc_cmap(&info->cmap);
+out:
+ if (par->vbe_modes)
+ kfree(par->vbe_modes);
+
+ framebuffer_release(info);
+ return err;
+}
+
+static int uvesafb_remove(struct platform_device *dev)
+{
+ struct fb_info *info = platform_get_drvdata(dev);
+
+ if (info) {
+ struct uvesafb_par *par = info->par;
+
+ sysfs_remove_group(&dev->dev.kobj, &uvesafb_dev_attgrp);
+ unregister_framebuffer(info);
+ release_region(0x3c0, 32);
+ iounmap(info->screen_base);
+ release_mem_region(info->fix.smem_start, info->fix.smem_len);
+ fb_destroy_modedb(info->monspecs.modedb);
+ fb_dealloc_cmap(&info->cmap);
+
+ if (par) {
+ if (par->vbe_modes)
+ kfree(par->vbe_modes);
+ if (par->vbe_state_orig)
+ kfree(par->vbe_state_orig);
+ if (par->vbe_state_saved)
+ kfree(par->vbe_state_saved);
+ }
+
+ framebuffer_release(info);
+ }
+ return 0;
+}
+
+static struct platform_driver uvesafb_driver = {
+ .probe = uvesafb_probe,
+ .remove = uvesafb_remove,
+ .driver = {
+ .name = "uvesafb",
+ },
+};
+
+static struct platform_device *uvesafb_device;
+
+#ifndef MODULE
+static int __devinit uvesafb_setup(char *options)
+{
+ char *this_opt;
+
+ if (!options || !*options)
+ return 0;
+
+ while ((this_opt = strsep(&options, ",")) != NULL) {
+ if (!*this_opt) continue;
+
+ if (!strcmp(this_opt, "redraw"))
+ ypan = 0;
+ else if (!strcmp(this_opt, "ypan"))
+ ypan = 1;
+ else if (!strcmp(this_opt, "ywrap"))
+ ypan = 2;
+ else if (!strcmp(this_opt, "vgapal"))
+ pmi_setpal = 0;
+ else if (!strcmp(this_opt, "pmipal"))
+ pmi_setpal = 1;
+ else if (!strncmp(this_opt, "mtrr:", 5))
+ mtrr = simple_strtoul(this_opt+5, NULL, 0);
+ else if (!strcmp(this_opt, "nomtrr"))
+ mtrr = 0;
+ else if (!strcmp(this_opt, "nocrtc"))
+ nocrtc = 1;
+ else if (!strcmp(this_opt, "noedid"))
+ noedid = 1;
+ else if (!strcmp(this_opt, "noblank"))
+ blank = 0;
+ else if (!strncmp(this_opt, "vtotal:", 7))
+ vram_total = simple_strtoul(this_opt + 7, NULL, 0);
+ else if (!strncmp(this_opt, "vremap:", 7))
+ vram_remap = simple_strtoul(this_opt + 7, NULL, 0);
+ else if (!strncmp(this_opt, "maxhf:", 6))
+ maxhf = simple_strtoul(this_opt + 6, NULL, 0);
+ else if (!strncmp(this_opt, "maxvf:", 6))
+ maxvf = simple_strtoul(this_opt + 6, NULL, 0);
+ else if (!strncmp(this_opt, "maxclk:", 7))
+ maxclk = simple_strtoul(this_opt + 7, NULL, 0);
+ else if (!strncmp(this_opt, "vbemode:", 8))
+ vbemode = simple_strtoul(this_opt + 8, NULL, 0);
+ else if (this_opt[0] >= '0' && this_opt[0] <= '9') {
+ mode_option = this_opt;
+ } else {
+ printk(KERN_WARNING
+ "uvesafb: unrecognized option %s\n", this_opt);
+ }
+ }
+
+ return 0;
+}
+#endif /* !MODULE */
+
+static ssize_t show_v86d(struct device_driver *dev, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", v86d_path);
+}
+
+static ssize_t store_v86d(struct device_driver *dev, const char *buf,
+ size_t count)
+{
+ strncpy(v86d_path, buf, PATH_MAX);
+ return count;
+}
+
+static DRIVER_ATTR(v86d, S_IRUGO | S_IWUSR, show_v86d, store_v86d);
+
+static int __devinit uvesafb_init(void)
+{
+ int err;
+
+#ifndef MODULE
+ char *option = NULL;
+
+ if (fb_get_options("uvesafb", &option))
+ return -ENODEV;
+ uvesafb_setup(option);
+#endif
+ err = cn_add_callback(&uvesafb_cn_id, "uvesafb", uvesafb_cn_callback);
+ if (err)
+ return err;
+
+ err = platform_driver_register(&uvesafb_driver);
+
+ if (!err) {
+ uvesafb_device = platform_device_alloc("uvesafb", 0);
+ if (uvesafb_device)
+ err = platform_device_add(uvesafb_device);
+ else
+ err = -ENOMEM;
+
+ if (err) {
+ platform_device_put(uvesafb_device);
+ platform_driver_unregister(&uvesafb_driver);
+ cn_del_callback(&uvesafb_cn_id);
+ return err;
+ }
+
+ err = driver_create_file(&uvesafb_driver.driver,
+ &driver_attr_v86d);
+ if (err) {
+ printk(KERN_WARNING "uvesafb: failed to register "
+ "attributes\n");
+ err = 0;
+ }
+ }
+ return err;
+}
+
+module_init(uvesafb_init);
+
+static void __devexit uvesafb_exit(void)
+{
+ struct uvesafb_ktask *task;
+
+ if (v86d_started) {
+ task = uvesafb_prep();
+ if (task) {
+ task->t.flags = TF_EXIT;
+ uvesafb_exec(task);
+ uvesafb_free(task);
+ }
+ }
+
+ cn_del_callback(&uvesafb_cn_id);
+ driver_remove_file(&uvesafb_driver.driver, &driver_attr_v86d);
+ platform_device_unregister(uvesafb_device);
+ platform_driver_unregister(&uvesafb_driver);
+}
+
+module_exit(uvesafb_exit);
+
+static inline int param_get_scroll(char *buffer, struct kernel_param *kp)
+{
+ return 0;
+}
+
+static inline int param_set_scroll(const char *val, struct kernel_param *kp)
+{
+ ypan = 0;
+
+ if (!strcmp(val, "redraw"))
+ ypan = 0;
+ else if (!strcmp(val, "ypan"))
+ ypan = 1;
+ else if (!strcmp(val, "ywrap"))
+ ypan = 2;
+
+ return 0;
+}
+
+#define param_check_scroll(name, p) __param_check(name, p, void);
+
+module_param_named(scroll, ypan, scroll, 0);
+MODULE_PARM_DESC(scroll,
+ "Scrolling mode, set to 'redraw', ''ypan' or 'ywrap'");
+module_param_named(vgapal, pmi_setpal, invbool, 0);
+MODULE_PARM_DESC(vgapal, "Set palette using VGA registers");
+module_param_named(pmipal, pmi_setpal, bool, 0);
+MODULE_PARM_DESC(pmipal, "Set palette using PMI calls");
+module_param(mtrr, uint, 0);
+MODULE_PARM_DESC(mtrr,
+ "Memory Type Range Registers setting. Use 0 to disable.");
+module_param(blank, bool, 0);
+MODULE_PARM_DESC(blank, "Enable hardware blanking");
+module_param(nocrtc, bool, 0);
+MODULE_PARM_DESC(nocrtc, "Ignore CRTC timings when setting modes");
+module_param(noedid, bool, 0);
+MODULE_PARM_DESC(noedid,
+ "Ignore EDID-provided monitor limits when setting modes");
+module_param(vram_remap, uint, 0);
+MODULE_PARM_DESC(vram_remap, "Set amount of video memory to be used [MiB]");
+module_param(vram_total, uint, 0);
+MODULE_PARM_DESC(vram_total, "Set total amount of video memoery [MiB]");
+module_param(maxclk, ushort, 0);
+MODULE_PARM_DESC(maxclk, "Maximum pixelclock [MHz], overrides EDID data");
+module_param(maxhf, ushort, 0);
+MODULE_PARM_DESC(maxhf,
+ "Maximum horizontal frequency [kHz], overrides EDID data");
+module_param(maxvf, ushort, 0);
+MODULE_PARM_DESC(maxvf,
+ "Maximum vertical frequency [Hz], overrides EDID data");
+module_param_named(mode, mode_option, charp, 0);
+MODULE_PARM_DESC(mode,
+ "Specify initial video mode as \"<xres>x<yres>[-<bpp>][@<refresh>]\"");
+module_param(vbemode, ushort, 0);
+MODULE_PARM_DESC(vbemode,
+ "VBE mode number to set, overrides the 'mode' option");
+module_param_string(v86d, v86d_path, PATH_MAX, 0660);
+MODULE_PARM_DESC(v86d, "Path to the v86d userspace helper.");
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Michal Januszewski <spock@gentoo.org>");
+MODULE_DESCRIPTION("Framebuffer driver for VBE2.0+ compliant graphics boards");
+
diff --git a/drivers/video/vermilion/vermilion.c b/drivers/video/vermilion/vermilion.c
index de531c907718..c31f549ebea0 100644
--- a/drivers/video/vermilion/vermilion.c
+++ b/drivers/video/vermilion/vermilion.c
@@ -23,8 +23,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* Authors:
- * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
- * Michel Dänzer <michel-at-tungstengraphics-dot-com>
+ * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ * Michel Dänzer <michel-at-tungstengraphics-dot-com>
* Alan Hourihane <alanh-at-tungstengraphics-dot-com>
*/
@@ -39,7 +39,6 @@
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
#include <linux/mmzone.h>
-#include <asm/uaccess.h>
/* #define VERMILION_DEBUG */
diff --git a/drivers/video/vermilion/vermilion.h b/drivers/video/vermilion/vermilion.h
index 1fc6695a49d2..c4aba59d4809 100644
--- a/drivers/video/vermilion/vermilion.h
+++ b/drivers/video/vermilion/vermilion.h
@@ -23,7 +23,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* Authors:
- * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
*/
#ifndef _VERMILION_H_
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c
index 64ee78c3c12b..072638a9528a 100644
--- a/drivers/video/vfb.c
+++ b/drivers/video/vfb.c
@@ -21,7 +21,6 @@
#include <linux/interrupt.h>
#include <linux/platform_device.h>
-#include <asm/uaccess.h>
#include <linux/fb.h>
#include <linux/init.h>
@@ -38,6 +37,48 @@ static void *videomemory;
static u_long videomemorysize = VIDEOMEMSIZE;
module_param(videomemorysize, ulong, 0);
+/**********************************************************************
+ *
+ * Memory management
+ *
+ **********************************************************************/
+static void *rvmalloc(unsigned long size)
+{
+ void *mem;
+ unsigned long adr;
+
+ size = PAGE_ALIGN(size);
+ mem = vmalloc_32(size);
+ if (!mem)
+ return NULL;
+
+ memset(mem, 0, size); /* Clear the ram out, no junk to the user */
+ adr = (unsigned long) mem;
+ while (size > 0) {
+ SetPageReserved(vmalloc_to_page((void *)adr));
+ adr += PAGE_SIZE;
+ size -= PAGE_SIZE;
+ }
+
+ return mem;
+}
+
+static void rvfree(void *mem, unsigned long size)
+{
+ unsigned long adr;
+
+ if (!mem)
+ return;
+
+ adr = (unsigned long) mem;
+ while ((long) size > 0) {
+ ClearPageReserved(vmalloc_to_page((void *)adr));
+ adr += PAGE_SIZE;
+ size -= PAGE_SIZE;
+ }
+ vfree(mem);
+}
+
static struct fb_var_screeninfo vfb_default __initdata = {
.xres = 640,
.yres = 480,
@@ -372,7 +413,33 @@ static int vfb_pan_display(struct fb_var_screeninfo *var,
static int vfb_mmap(struct fb_info *info,
struct vm_area_struct *vma)
{
- return -EINVAL;
+ unsigned long start = vma->vm_start;
+ unsigned long size = vma->vm_end - vma->vm_start;
+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+ unsigned long page, pos;
+
+ if (offset + size > info->fix.smem_len) {
+ return -EINVAL;
+ }
+
+ pos = (unsigned long)info->fix.smem_start + offset;
+
+ while (size > 0) {
+ page = vmalloc_to_pfn((void *)pos);
+ if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
+ return -EAGAIN;
+ }
+ start += PAGE_SIZE;
+ pos += PAGE_SIZE;
+ if (size > PAGE_SIZE)
+ size -= PAGE_SIZE;
+ else
+ size = 0;
+ }
+
+ vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */
+ return 0;
+
}
#ifndef MODULE
@@ -407,7 +474,7 @@ static int __init vfb_probe(struct platform_device *dev)
/*
* For real video cards we use ioremap.
*/
- if (!(videomemory = vmalloc(videomemorysize)))
+ if (!(videomemory = rvmalloc(videomemorysize)))
return retval;
/*
@@ -430,6 +497,8 @@ static int __init vfb_probe(struct platform_device *dev)
if (!retval || (retval == 4))
info->var = vfb_default;
+ vfb_fix.smem_start = (unsigned long) videomemory;
+ vfb_fix.smem_len = videomemorysize;
info->fix = vfb_fix;
info->pseudo_palette = info->par;
info->par = NULL;
@@ -453,7 +522,7 @@ err2:
err1:
framebuffer_release(info);
err:
- vfree(videomemory);
+ rvfree(videomemory, videomemorysize);
return retval;
}
@@ -463,7 +532,7 @@ static int vfb_remove(struct platform_device *dev)
if (info) {
unregister_framebuffer(info);
- vfree(videomemory);
+ rvfree(videomemory, videomemorysize);
framebuffer_release(info);
}
return 0;
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
index 2a14d28c4163..9b3c5923365e 100644
--- a/drivers/video/vga16fb.c
+++ b/drivers/video/vga16fb.c
@@ -1364,7 +1364,7 @@ static int __init vga16fb_probe(struct platform_device *dev)
par = info->par;
mutex_init(&par->open_lock);
- par->isVGA = ORIG_VIDEO_ISVGA;
+ par->isVGA = screen_info.orig_video_isVGA;
par->palette_blanked = 0;
par->vesa_blanked = 0;
diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig
new file mode 100644
index 000000000000..9e33fc4da875
--- /dev/null
+++ b/drivers/virtio/Kconfig
@@ -0,0 +1,8 @@
+# Virtio always gets selected by whoever wants it.
+config VIRTIO
+ bool
+
+# Similarly the virtio ring implementation.
+config VIRTIO_RING
+ bool
+ depends on VIRTIO
diff --git a/drivers/virtio/Makefile b/drivers/virtio/Makefile
new file mode 100644
index 000000000000..f70e40971dd9
--- /dev/null
+++ b/drivers/virtio/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_VIRTIO) += virtio.o
+obj-$(CONFIG_VIRTIO_RING) += virtio_ring.o
diff --git a/drivers/virtio/config.c b/drivers/virtio/config.c
new file mode 100644
index 000000000000..983d482fba40
--- /dev/null
+++ b/drivers/virtio/config.c
@@ -0,0 +1,13 @@
+/* Configuration space parsing helpers for virtio.
+ *
+ * The configuration is [type][len][... len bytes ...] fields.
+ *
+ * Copyright 2007 Rusty Russell, IBM Corporation.
+ * GPL v2 or later.
+ */
+#include <linux/err.h>
+#include <linux/virtio.h>
+#include <linux/virtio_config.h>
+#include <linux/bug.h>
+#include <asm/system.h>
+
diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
new file mode 100644
index 000000000000..15d7787dea87
--- /dev/null
+++ b/drivers/virtio/virtio.c
@@ -0,0 +1,189 @@
+#include <linux/virtio.h>
+#include <linux/spinlock.h>
+#include <linux/virtio_config.h>
+
+static ssize_t device_show(struct device *_d,
+ struct device_attribute *attr, char *buf)
+{
+ struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
+ return sprintf(buf, "%hu", dev->id.device);
+}
+static ssize_t vendor_show(struct device *_d,
+ struct device_attribute *attr, char *buf)
+{
+ struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
+ return sprintf(buf, "%hu", dev->id.vendor);
+}
+static ssize_t status_show(struct device *_d,
+ struct device_attribute *attr, char *buf)
+{
+ struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
+ return sprintf(buf, "0x%08x", dev->config->get_status(dev));
+}
+static ssize_t modalias_show(struct device *_d,
+ struct device_attribute *attr, char *buf)
+{
+ struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
+
+ return sprintf(buf, "virtio:d%08Xv%08X\n",
+ dev->id.device, dev->id.vendor);
+}
+static struct device_attribute virtio_dev_attrs[] = {
+ __ATTR_RO(device),
+ __ATTR_RO(vendor),
+ __ATTR_RO(status),
+ __ATTR_RO(modalias),
+ __ATTR_NULL
+};
+
+static inline int virtio_id_match(const struct virtio_device *dev,
+ const struct virtio_device_id *id)
+{
+ if (id->device != dev->id.device)
+ return 0;
+
+ return id->vendor == VIRTIO_DEV_ANY_ID || id->vendor != dev->id.vendor;
+}
+
+/* This looks through all the IDs a driver claims to support. If any of them
+ * match, we return 1 and the kernel will call virtio_dev_probe(). */
+static int virtio_dev_match(struct device *_dv, struct device_driver *_dr)
+{
+ unsigned int i;
+ struct virtio_device *dev = container_of(_dv,struct virtio_device,dev);
+ const struct virtio_device_id *ids;
+
+ ids = container_of(_dr, struct virtio_driver, driver)->id_table;
+ for (i = 0; ids[i].device; i++)
+ if (virtio_id_match(dev, &ids[i]))
+ return 1;
+ return 0;
+}
+
+static int virtio_uevent(struct device *_dv, struct kobj_uevent_env *env)
+{
+ struct virtio_device *dev = container_of(_dv,struct virtio_device,dev);
+
+ return add_uevent_var(env, "MODALIAS=virtio:d%08Xv%08X",
+ dev->id.device, dev->id.vendor);
+}
+
+static struct bus_type virtio_bus = {
+ .name = "virtio",
+ .match = virtio_dev_match,
+ .dev_attrs = virtio_dev_attrs,
+ .uevent = virtio_uevent,
+};
+
+static void add_status(struct virtio_device *dev, unsigned status)
+{
+ dev->config->set_status(dev, dev->config->get_status(dev) | status);
+}
+
+static int virtio_dev_probe(struct device *_d)
+{
+ int err;
+ struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
+ struct virtio_driver *drv = container_of(dev->dev.driver,
+ struct virtio_driver, driver);
+
+ add_status(dev, VIRTIO_CONFIG_S_DRIVER);
+ err = drv->probe(dev);
+ if (err)
+ add_status(dev, VIRTIO_CONFIG_S_FAILED);
+ else
+ add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK);
+ return err;
+}
+
+int register_virtio_driver(struct virtio_driver *driver)
+{
+ driver->driver.bus = &virtio_bus;
+ driver->driver.probe = virtio_dev_probe;
+ return driver_register(&driver->driver);
+}
+EXPORT_SYMBOL_GPL(register_virtio_driver);
+
+void unregister_virtio_driver(struct virtio_driver *driver)
+{
+ driver_unregister(&driver->driver);
+}
+EXPORT_SYMBOL_GPL(unregister_virtio_driver);
+
+int register_virtio_device(struct virtio_device *dev)
+{
+ int err;
+
+ dev->dev.bus = &virtio_bus;
+ sprintf(dev->dev.bus_id, "%u", dev->index);
+
+ /* Acknowledge that we've seen the device. */
+ add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE);
+
+ /* device_register() causes the bus infrastructure to look for a
+ * matching driver. */
+ err = device_register(&dev->dev);
+ if (err)
+ add_status(dev, VIRTIO_CONFIG_S_FAILED);
+ return err;
+}
+EXPORT_SYMBOL_GPL(register_virtio_device);
+
+void unregister_virtio_device(struct virtio_device *dev)
+{
+ device_unregister(&dev->dev);
+}
+EXPORT_SYMBOL_GPL(unregister_virtio_device);
+
+int __virtio_config_val(struct virtio_device *vdev,
+ u8 type, void *val, size_t size)
+{
+ void *token;
+ unsigned int len;
+
+ token = vdev->config->find(vdev, type, &len);
+ if (!token)
+ return -ENOENT;
+
+ if (len != size)
+ return -EIO;
+
+ vdev->config->get(vdev, token, val, size);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(__virtio_config_val);
+
+int virtio_use_bit(struct virtio_device *vdev,
+ void *token, unsigned int len, unsigned int bitnum)
+{
+ unsigned long bits[16];
+
+ /* This makes it convenient to pass-through find() results. */
+ if (!token)
+ return 0;
+
+ /* bit not in range of this bitfield? */
+ if (bitnum * 8 >= len / 2)
+ return 0;
+
+ /* Giant feature bitfields are silly. */
+ BUG_ON(len > sizeof(bits));
+ vdev->config->get(vdev, token, bits, len);
+
+ if (!test_bit(bitnum, bits))
+ return 0;
+
+ /* Set acknowledge bit, and write it back. */
+ set_bit(bitnum + len * 8 / 2, bits);
+ vdev->config->set(vdev, token, bits, len);
+ return 1;
+}
+EXPORT_SYMBOL_GPL(virtio_use_bit);
+
+static int virtio_init(void)
+{
+ if (bus_register(&virtio_bus) != 0)
+ panic("virtio bus registration failed");
+ return 0;
+}
+core_initcall(virtio_init);
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
new file mode 100644
index 000000000000..1dc04b6684e6
--- /dev/null
+++ b/drivers/virtio/virtio_ring.c
@@ -0,0 +1,319 @@
+/* Virtio ring implementation.
+ *
+ * Copyright 2007 Rusty Russell IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <linux/virtio.h>
+#include <linux/virtio_ring.h>
+#include <linux/device.h>
+
+#ifdef DEBUG
+/* For development, we want to crash whenever the ring is screwed. */
+#define BAD_RING(vq, fmt...) \
+ do { dev_err(&vq->vq.vdev->dev, fmt); BUG(); } while(0)
+#define START_USE(vq) \
+ do { if ((vq)->in_use) panic("in_use = %i\n", (vq)->in_use); (vq)->in_use = __LINE__; mb(); } while(0)
+#define END_USE(vq) \
+ do { BUG_ON(!(vq)->in_use); (vq)->in_use = 0; mb(); } while(0)
+#else
+#define BAD_RING(vq, fmt...) \
+ do { dev_err(&vq->vq.vdev->dev, fmt); (vq)->broken = true; } while(0)
+#define START_USE(vq)
+#define END_USE(vq)
+#endif
+
+struct vring_virtqueue
+{
+ struct virtqueue vq;
+
+ /* Actual memory layout for this queue */
+ struct vring vring;
+
+ /* Other side has made a mess, don't try any more. */
+ bool broken;
+
+ /* Number of free buffers */
+ unsigned int num_free;
+ /* Head of free buffer list. */
+ unsigned int free_head;
+ /* Number we've added since last sync. */
+ unsigned int num_added;
+
+ /* Last used index we've seen. */
+ u16 last_used_idx;
+
+ /* How to notify other side. FIXME: commonalize hcalls! */
+ void (*notify)(struct virtqueue *vq);
+
+#ifdef DEBUG
+ /* They're supposed to lock for us. */
+ unsigned int in_use;
+#endif
+
+ /* Tokens for callbacks. */
+ void *data[];
+};
+
+#define to_vvq(_vq) container_of(_vq, struct vring_virtqueue, vq)
+
+static int vring_add_buf(struct virtqueue *_vq,
+ struct scatterlist sg[],
+ unsigned int out,
+ unsigned int in,
+ void *data)
+{
+ struct vring_virtqueue *vq = to_vvq(_vq);
+ unsigned int i, avail, head, uninitialized_var(prev);
+
+ BUG_ON(data == NULL);
+ BUG_ON(out + in > vq->vring.num);
+ BUG_ON(out + in == 0);
+
+ START_USE(vq);
+
+ if (vq->num_free < out + in) {
+ pr_debug("Can't add buf len %i - avail = %i\n",
+ out + in, vq->num_free);
+ END_USE(vq);
+ return -ENOSPC;
+ }
+
+ /* We're about to use some buffers from the free list. */
+ vq->num_free -= out + in;
+
+ head = vq->free_head;
+ for (i = vq->free_head; out; i = vq->vring.desc[i].next, out--) {
+ vq->vring.desc[i].flags = VRING_DESC_F_NEXT;
+ vq->vring.desc[i].addr = (page_to_pfn(sg_page(sg))<<PAGE_SHIFT)
+ + sg->offset;
+ vq->vring.desc[i].len = sg->length;
+ prev = i;
+ sg++;
+ }
+ for (; in; i = vq->vring.desc[i].next, in--) {
+ vq->vring.desc[i].flags = VRING_DESC_F_NEXT|VRING_DESC_F_WRITE;
+ vq->vring.desc[i].addr = (page_to_pfn(sg_page(sg))<<PAGE_SHIFT)
+ + sg->offset;
+ vq->vring.desc[i].len = sg->length;
+ prev = i;
+ sg++;
+ }
+ /* Last one doesn't continue. */
+ vq->vring.desc[prev].flags &= ~VRING_DESC_F_NEXT;
+
+ /* Update free pointer */
+ vq->free_head = i;
+
+ /* Set token. */
+ vq->data[head] = data;
+
+ /* Put entry in available array (but don't update avail->idx until they
+ * do sync). FIXME: avoid modulus here? */
+ avail = (vq->vring.avail->idx + vq->num_added++) % vq->vring.num;
+ vq->vring.avail->ring[avail] = head;
+
+ pr_debug("Added buffer head %i to %p\n", head, vq);
+ END_USE(vq);
+ return 0;
+}
+
+static void vring_kick(struct virtqueue *_vq)
+{
+ struct vring_virtqueue *vq = to_vvq(_vq);
+ START_USE(vq);
+ /* Descriptors and available array need to be set before we expose the
+ * new available array entries. */
+ wmb();
+
+ vq->vring.avail->idx += vq->num_added;
+ vq->num_added = 0;
+
+ /* Need to update avail index before checking if we should notify */
+ mb();
+
+ if (!(vq->vring.used->flags & VRING_USED_F_NO_NOTIFY))
+ /* Prod other side to tell it about changes. */
+ vq->notify(&vq->vq);
+
+ END_USE(vq);
+}
+
+static void detach_buf(struct vring_virtqueue *vq, unsigned int head)
+{
+ unsigned int i;
+
+ /* Clear data ptr. */
+ vq->data[head] = NULL;
+
+ /* Put back on free list: find end */
+ i = head;
+ while (vq->vring.desc[i].flags & VRING_DESC_F_NEXT) {
+ i = vq->vring.desc[i].next;
+ vq->num_free++;
+ }
+
+ vq->vring.desc[i].next = vq->free_head;
+ vq->free_head = head;
+ /* Plus final descriptor */
+ vq->num_free++;
+}
+
+/* FIXME: We need to tell other side about removal, to synchronize. */
+static void vring_shutdown(struct virtqueue *_vq)
+{
+ struct vring_virtqueue *vq = to_vvq(_vq);
+ unsigned int i;
+
+ for (i = 0; i < vq->vring.num; i++)
+ detach_buf(vq, i);
+}
+
+static inline bool more_used(const struct vring_virtqueue *vq)
+{
+ return vq->last_used_idx != vq->vring.used->idx;
+}
+
+static void *vring_get_buf(struct virtqueue *_vq, unsigned int *len)
+{
+ struct vring_virtqueue *vq = to_vvq(_vq);
+ void *ret;
+ unsigned int i;
+
+ START_USE(vq);
+
+ if (!more_used(vq)) {
+ pr_debug("No more buffers in queue\n");
+ END_USE(vq);
+ return NULL;
+ }
+
+ i = vq->vring.used->ring[vq->last_used_idx%vq->vring.num].id;
+ *len = vq->vring.used->ring[vq->last_used_idx%vq->vring.num].len;
+
+ if (unlikely(i >= vq->vring.num)) {
+ BAD_RING(vq, "id %u out of range\n", i);
+ return NULL;
+ }
+ if (unlikely(!vq->data[i])) {
+ BAD_RING(vq, "id %u is not a head!\n", i);
+ return NULL;
+ }
+
+ /* detach_buf clears data, so grab it now. */
+ ret = vq->data[i];
+ detach_buf(vq, i);
+ vq->last_used_idx++;
+ END_USE(vq);
+ return ret;
+}
+
+static bool vring_restart(struct virtqueue *_vq)
+{
+ struct vring_virtqueue *vq = to_vvq(_vq);
+
+ START_USE(vq);
+ BUG_ON(!(vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT));
+
+ /* We optimistically turn back on interrupts, then check if there was
+ * more to do. */
+ vq->vring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT;
+ mb();
+ if (unlikely(more_used(vq))) {
+ vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
+ END_USE(vq);
+ return false;
+ }
+
+ END_USE(vq);
+ return true;
+}
+
+irqreturn_t vring_interrupt(int irq, void *_vq)
+{
+ struct vring_virtqueue *vq = to_vvq(_vq);
+
+ if (!more_used(vq)) {
+ pr_debug("virtqueue interrupt with no work for %p\n", vq);
+ return IRQ_NONE;
+ }
+
+ if (unlikely(vq->broken))
+ return IRQ_HANDLED;
+
+ pr_debug("virtqueue callback for %p (%p)\n", vq, vq->vq.callback);
+ if (vq->vq.callback && !vq->vq.callback(&vq->vq))
+ vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
+
+ return IRQ_HANDLED;
+}
+
+static struct virtqueue_ops vring_vq_ops = {
+ .add_buf = vring_add_buf,
+ .get_buf = vring_get_buf,
+ .kick = vring_kick,
+ .restart = vring_restart,
+ .shutdown = vring_shutdown,
+};
+
+struct virtqueue *vring_new_virtqueue(unsigned int num,
+ struct virtio_device *vdev,
+ void *pages,
+ void (*notify)(struct virtqueue *),
+ bool (*callback)(struct virtqueue *))
+{
+ struct vring_virtqueue *vq;
+ unsigned int i;
+
+ /* We assume num is a power of 2. */
+ if (num & (num - 1)) {
+ dev_warn(&vdev->dev, "Bad virtqueue length %u\n", num);
+ return NULL;
+ }
+
+ vq = kmalloc(sizeof(*vq) + sizeof(void *)*num, GFP_KERNEL);
+ if (!vq)
+ return NULL;
+
+ vring_init(&vq->vring, num, pages, PAGE_SIZE);
+ vq->vq.callback = callback;
+ vq->vq.vdev = vdev;
+ vq->vq.vq_ops = &vring_vq_ops;
+ vq->notify = notify;
+ vq->broken = false;
+ vq->last_used_idx = 0;
+ vq->num_added = 0;
+#ifdef DEBUG
+ vq->in_use = false;
+#endif
+
+ /* No callback? Tell other side not to bother us. */
+ if (!callback)
+ vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
+
+ /* Put everything in free lists. */
+ vq->num_free = num;
+ vq->free_head = 0;
+ for (i = 0; i < num-1; i++)
+ vq->vring.desc[i].next = i+1;
+
+ return &vq->vq;
+}
+
+void vring_del_virtqueue(struct virtqueue *vq)
+{
+ kfree(to_vvq(vq));
+}
+
diff --git a/drivers/w1/Kconfig b/drivers/w1/Kconfig
index 6854fd6b9714..9adbb4f90479 100644
--- a/drivers/w1/Kconfig
+++ b/drivers/w1/Kconfig
@@ -17,7 +17,8 @@ config W1_CON
bool "Userspace communication over connector"
default y
--- help ---
- This allows to communicate with userspace using connector [Documentation/connector].
+ This allows to communicate with userspace using connector. For more
+ information see <file:Documentation/connector/connector.txt>.
There are three types of messages between w1 core and userspace:
1. Events. They are generated each time new master or slave device found
either due to automatic or requested search.
diff --git a/drivers/w1/masters/ds1wm.c b/drivers/w1/masters/ds1wm.c
index 4b696641ce33..5747997f8d7d 100644
--- a/drivers/w1/masters/ds1wm.c
+++ b/drivers/w1/masters/ds1wm.c
@@ -307,7 +307,7 @@ static void ds1wm_search(void *data, u8 search_type,
rom_id |= (unsigned long long) r << (i * 4);
}
- dev_dbg(&ds1wm_data->pdev->dev, "found 0x%08llX", rom_id);
+ dev_dbg(&ds1wm_data->pdev->dev, "found 0x%08llX\n", rom_id);
ds1wm_write_register(ds1wm_data, DS1WM_CMD, ~DS1WM_CMD_SRA);
ds1wm_reset(ds1wm_data);
diff --git a/drivers/w1/masters/ds2490.c b/drivers/w1/masters/ds2490.c
index 299e274d241a..b63b5e044a4c 100644
--- a/drivers/w1/masters/ds2490.c
+++ b/drivers/w1/masters/ds2490.c
@@ -233,7 +233,7 @@ static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st,
{
int count, err;
- memset(st, 0, sizeof(st));
+ memset(st, 0, sizeof(*st));
count = 0;
err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_STATUS]), buf, size, &count, 100);
diff --git a/drivers/w1/masters/matrox_w1.c b/drivers/w1/masters/matrox_w1.c
index d356da5709fc..1550431ccb6a 100644
--- a/drivers/w1/masters/matrox_w1.c
+++ b/drivers/w1/masters/matrox_w1.c
@@ -33,7 +33,6 @@
#include <linux/slab.h>
#include <linux/pci_ids.h>
#include <linux/pci.h>
-#include <linux/timer.h>
#include "../w1.h"
#include "../w1_int.h"
diff --git a/drivers/char/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 37bddc1802de..2792bc1a7269 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -15,8 +15,8 @@ menuconfig WATCHDOG
implementation entirely in software (which can sometimes fail to
reboot the machine) and a driver for hardware watchdog boards, which
are more robust and can also keep track of the temperature inside
- your computer. For details, read <file:Documentation/watchdog/watchdog.txt>
- in the kernel source.
+ your computer. For details, read
+ <file:Documentation/watchdog/watchdog-api.txt> in the kernel source.
The watchdog is usually used together with the watchdog daemon
which is available from
@@ -343,11 +343,12 @@ config IBMASR
module will be called ibmasr.
config WAFER_WDT
- tristate "ICP Wafer 5823 Single Board Computer Watchdog"
+ tristate "ICP Single Board Computer Watchdog Timer"
depends on X86
help
- This is a driver for the hardware watchdog on the ICP Wafer 5823
- Single Board Computer (and probably other similar models).
+ This is a driver for the hardware watchdog on the ICP Single
+ Board Computer. This driver is working on (at least) the following
+ IPC SBC's: Wafer 5823, Rocky 4783, Rocky 3703 and Rocky 3782.
To compile this driver as a module, choose M here: the
module will be called wafer5823wdt.
@@ -609,6 +610,12 @@ config WDT_RM9K_GPI
To compile this driver as a module, choose M here: the
module will be called rm9k_wdt.
+config AR7_WDT
+ tristate "TI AR7 Watchdog Timer"
+ depends on AR7
+ help
+ Hardware driver for the TI AR7 Watchdog Timer.
+
# PARISC Architecture
# POWERPC Architecture
diff --git a/drivers/char/watchdog/Makefile b/drivers/watchdog/Makefile
index 389f8b14ccc4..7d9e5734f8bb 100644
--- a/drivers/char/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -90,6 +90,7 @@ obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o
obj-$(CONFIG_INDYDOG) += indydog.o
obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o
obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o
+obj-$(CONFIG_AR7_WDT) += ar7_wdt.o
# PARISC Architecture
diff --git a/drivers/char/watchdog/acquirewdt.c b/drivers/watchdog/acquirewdt.c
index 85269c365a10..85269c365a10 100644
--- a/drivers/char/watchdog/acquirewdt.c
+++ b/drivers/watchdog/acquirewdt.c
diff --git a/drivers/char/watchdog/advantechwdt.c b/drivers/watchdog/advantechwdt.c
index 8121cc247343..8121cc247343 100644
--- a/drivers/char/watchdog/advantechwdt.c
+++ b/drivers/watchdog/advantechwdt.c
diff --git a/drivers/char/watchdog/alim1535_wdt.c b/drivers/watchdog/alim1535_wdt.c
index c404fc69e7e6..b481cc0e32e4 100644
--- a/drivers/char/watchdog/alim1535_wdt.c
+++ b/drivers/watchdog/alim1535_wdt.c
@@ -31,7 +31,7 @@ static unsigned long ali_is_open;
static char ali_expect_release;
static struct pci_dev *ali_pci;
static u32 ali_timeout_bits; /* stores the computed timeout */
-static spinlock_t ali_lock; /* Guards the hardware */
+static DEFINE_SPINLOCK(ali_lock); /* Guards the hardware */
/* module parameters */
static int timeout = WATCHDOG_TIMEOUT;
@@ -398,8 +398,6 @@ static int __init watchdog_init(void)
{
int ret;
- spin_lock_init(&ali_lock);
-
/* Check whether or not the hardware watchdog is there */
if (ali_find_watchdog() != 0) {
return -ENODEV;
diff --git a/drivers/char/watchdog/alim7101_wdt.c b/drivers/watchdog/alim7101_wdt.c
index 67aed9f8c362..67aed9f8c362 100644
--- a/drivers/char/watchdog/alim7101_wdt.c
+++ b/drivers/watchdog/alim7101_wdt.c
diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c
new file mode 100644
index 000000000000..cdaab8c3d3d0
--- /dev/null
+++ b/drivers/watchdog/ar7_wdt.c
@@ -0,0 +1,349 @@
+/*
+ * drivers/watchdog/ar7_wdt.c
+ *
+ * Copyright (C) 2007 Nicolas Thill <nico@openwrt.org>
+ * Copyright (c) 2005 Enrik Berkhan <Enrik.Berkhan@akk.org>
+ *
+ * Some code taken from:
+ * National Semiconductor SCx200 Watchdog support
+ * Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/fs.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+
+#include <asm/addrspace.h>
+#include <asm/ar7/ar7.h>
+
+#define DRVNAME "ar7_wdt"
+#define LONGNAME "TI AR7 Watchdog Timer"
+
+MODULE_AUTHOR("Nicolas Thill <nico@openwrt.org>");
+MODULE_DESCRIPTION(LONGNAME);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+
+static int margin = 60;
+module_param(margin, int, 0);
+MODULE_PARM_DESC(margin, "Watchdog margin in seconds");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
+
+#define READ_REG(x) readl((void __iomem *)&(x))
+#define WRITE_REG(x, v) writel((v), (void __iomem *)&(x))
+
+struct ar7_wdt {
+ u32 kick_lock;
+ u32 kick;
+ u32 change_lock;
+ u32 change;
+ u32 disable_lock;
+ u32 disable;
+ u32 prescale_lock;
+ u32 prescale;
+};
+
+static struct semaphore open_semaphore;
+static unsigned expect_close;
+
+/* XXX currently fixed, allows max margin ~68.72 secs */
+#define prescale_value 0xffff
+
+/* Offset of the WDT registers */
+static unsigned long ar7_regs_wdt;
+/* Pointer to the remapped WDT IO space */
+static struct ar7_wdt *ar7_wdt;
+static void ar7_wdt_get_regs(void)
+{
+ u16 chip_id = ar7_chip_id();
+ switch (chip_id) {
+ case AR7_CHIP_7100:
+ case AR7_CHIP_7200:
+ ar7_regs_wdt = AR7_REGS_WDT;
+ break;
+ default:
+ ar7_regs_wdt = UR8_REGS_WDT;
+ break;
+ }
+}
+
+
+static void ar7_wdt_kick(u32 value)
+{
+ WRITE_REG(ar7_wdt->kick_lock, 0x5555);
+ if ((READ_REG(ar7_wdt->kick_lock) & 3) == 1) {
+ WRITE_REG(ar7_wdt->kick_lock, 0xaaaa);
+ if ((READ_REG(ar7_wdt->kick_lock) & 3) == 3) {
+ WRITE_REG(ar7_wdt->kick, value);
+ return;
+ }
+ }
+ printk(KERN_ERR DRVNAME ": failed to unlock WDT kick reg\n");
+}
+
+static void ar7_wdt_prescale(u32 value)
+{
+ WRITE_REG(ar7_wdt->prescale_lock, 0x5a5a);
+ if ((READ_REG(ar7_wdt->prescale_lock) & 3) == 1) {
+ WRITE_REG(ar7_wdt->prescale_lock, 0xa5a5);
+ if ((READ_REG(ar7_wdt->prescale_lock) & 3) == 3) {
+ WRITE_REG(ar7_wdt->prescale, value);
+ return;
+ }
+ }
+ printk(KERN_ERR DRVNAME ": failed to unlock WDT prescale reg\n");
+}
+
+static void ar7_wdt_change(u32 value)
+{
+ WRITE_REG(ar7_wdt->change_lock, 0x6666);
+ if ((READ_REG(ar7_wdt->change_lock) & 3) == 1) {
+ WRITE_REG(ar7_wdt->change_lock, 0xbbbb);
+ if ((READ_REG(ar7_wdt->change_lock) & 3) == 3) {
+ WRITE_REG(ar7_wdt->change, value);
+ return;
+ }
+ }
+ printk(KERN_ERR DRVNAME ": failed to unlock WDT change reg\n");
+}
+
+static void ar7_wdt_disable(u32 value)
+{
+ WRITE_REG(ar7_wdt->disable_lock, 0x7777);
+ if ((READ_REG(ar7_wdt->disable_lock) & 3) == 1) {
+ WRITE_REG(ar7_wdt->disable_lock, 0xcccc);
+ if ((READ_REG(ar7_wdt->disable_lock) & 3) == 2) {
+ WRITE_REG(ar7_wdt->disable_lock, 0xdddd);
+ if ((READ_REG(ar7_wdt->disable_lock) & 3) == 3) {
+ WRITE_REG(ar7_wdt->disable, value);
+ return;
+ }
+ }
+ }
+ printk(KERN_ERR DRVNAME ": failed to unlock WDT disable reg\n");
+}
+
+static void ar7_wdt_update_margin(int new_margin)
+{
+ u32 change;
+
+ change = new_margin * (ar7_vbus_freq() / prescale_value);
+ if (change < 1) change = 1;
+ if (change > 0xffff) change = 0xffff;
+ ar7_wdt_change(change);
+ margin = change * prescale_value / ar7_vbus_freq();
+ printk(KERN_INFO DRVNAME
+ ": timer margin %d seconds (prescale %d, change %d, freq %d)\n",
+ margin, prescale_value, change, ar7_vbus_freq());
+}
+
+static void ar7_wdt_enable_wdt(void)
+{
+ printk(KERN_DEBUG DRVNAME ": enabling watchdog timer\n");
+ ar7_wdt_disable(1);
+ ar7_wdt_kick(1);
+}
+
+static void ar7_wdt_disable_wdt(void)
+{
+ printk(KERN_DEBUG DRVNAME ": disabling watchdog timer\n");
+ ar7_wdt_disable(0);
+}
+
+static int ar7_wdt_open(struct inode *inode, struct file *file)
+{
+ /* only allow one at a time */
+ if (down_trylock(&open_semaphore))
+ return -EBUSY;
+ ar7_wdt_enable_wdt();
+ expect_close = 0;
+
+ return nonseekable_open(inode, file);
+}
+
+static int ar7_wdt_release(struct inode *inode, struct file *file)
+{
+ if (!expect_close)
+ printk(KERN_WARNING DRVNAME
+ ": watchdog device closed unexpectedly,"
+ "will not disable the watchdog timer\n");
+ else if (!nowayout)
+ ar7_wdt_disable_wdt();
+
+ up(&open_semaphore);
+
+ return 0;
+}
+
+static int ar7_wdt_notify_sys(struct notifier_block *this,
+ unsigned long code, void *unused)
+{
+ if (code == SYS_HALT || code == SYS_POWER_OFF)
+ if (!nowayout)
+ ar7_wdt_disable_wdt();
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block ar7_wdt_notifier = {
+ .notifier_call = ar7_wdt_notify_sys
+};
+
+static ssize_t ar7_wdt_write(struct file *file, const char *data,
+ size_t len, loff_t *ppos)
+{
+ /* check for a magic close character */
+ if (len) {
+ size_t i;
+
+ ar7_wdt_kick(1);
+
+ expect_close = 0;
+ for (i = 0; i < len; ++i) {
+ char c;
+ if (get_user(c, data+i))
+ return -EFAULT;
+ if (c == 'V')
+ expect_close = 1;
+ }
+
+ }
+ return len;
+}
+
+static int ar7_wdt_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ static struct watchdog_info ident = {
+ .identity = LONGNAME,
+ .firmware_version = 1,
+ .options = (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING),
+ };
+ int new_margin;
+
+ switch (cmd) {
+ default:
+ return -ENOTTY;
+ case WDIOC_GETSUPPORT:
+ if (copy_to_user((struct watchdog_info *)arg, &ident,
+ sizeof(ident)))
+ return -EFAULT;
+ return 0;
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ if (put_user(0, (int *)arg))
+ return -EFAULT;
+ return 0;
+ case WDIOC_KEEPALIVE:
+ ar7_wdt_kick(1);
+ return 0;
+ case WDIOC_SETTIMEOUT:
+ if (get_user(new_margin, (int *)arg))
+ return -EFAULT;
+ if (new_margin < 1)
+ return -EINVAL;
+
+ ar7_wdt_update_margin(new_margin);
+ ar7_wdt_kick(1);
+
+ case WDIOC_GETTIMEOUT:
+ if (put_user(margin, (int *)arg))
+ return -EFAULT;
+ return 0;
+ }
+}
+
+static struct file_operations ar7_wdt_fops = {
+ .owner = THIS_MODULE,
+ .write = ar7_wdt_write,
+ .ioctl = ar7_wdt_ioctl,
+ .open = ar7_wdt_open,
+ .release = ar7_wdt_release,
+};
+
+static struct miscdevice ar7_wdt_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &ar7_wdt_fops,
+};
+
+static int __init ar7_wdt_init(void)
+{
+ int rc;
+
+ ar7_wdt_get_regs();
+
+ if (!request_mem_region(ar7_regs_wdt, sizeof(struct ar7_wdt),
+ LONGNAME)) {
+ printk(KERN_WARNING DRVNAME ": watchdog I/O region busy\n");
+ return -EBUSY;
+ }
+
+ ar7_wdt = (struct ar7_wdt *)
+ ioremap(ar7_regs_wdt, sizeof(struct ar7_wdt));
+
+ ar7_wdt_disable_wdt();
+ ar7_wdt_prescale(prescale_value);
+ ar7_wdt_update_margin(margin);
+
+ sema_init(&open_semaphore, 1);
+
+ rc = register_reboot_notifier(&ar7_wdt_notifier);
+ if (rc) {
+ printk(KERN_ERR DRVNAME
+ ": unable to register reboot notifier\n");
+ goto out_alloc;
+ }
+
+ rc = misc_register(&ar7_wdt_miscdev);
+ if (rc) {
+ printk(KERN_ERR DRVNAME ": unable to register misc device\n");
+ goto out_register;
+ }
+ goto out;
+
+out_register:
+ unregister_reboot_notifier(&ar7_wdt_notifier);
+out_alloc:
+ iounmap(ar7_wdt);
+ release_mem_region(ar7_regs_wdt, sizeof(struct ar7_wdt));
+out:
+ return rc;
+}
+
+static void __exit ar7_wdt_cleanup(void)
+{
+ misc_deregister(&ar7_wdt_miscdev);
+ unregister_reboot_notifier(&ar7_wdt_notifier);
+ iounmap(ar7_wdt);
+ release_mem_region(ar7_regs_wdt, sizeof(struct ar7_wdt));
+}
+
+module_init(ar7_wdt_init);
+module_exit(ar7_wdt_cleanup);
diff --git a/drivers/char/watchdog/at32ap700x_wdt.c b/drivers/watchdog/at32ap700x_wdt.c
index 54a516169d07..54a516169d07 100644
--- a/drivers/char/watchdog/at32ap700x_wdt.c
+++ b/drivers/watchdog/at32ap700x_wdt.c
diff --git a/drivers/char/watchdog/at91rm9200_wdt.c b/drivers/watchdog/at91rm9200_wdt.c
index 38bd37372599..a684b1e87372 100644
--- a/drivers/char/watchdog/at91rm9200_wdt.c
+++ b/drivers/watchdog/at91rm9200_wdt.c
@@ -9,6 +9,7 @@
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/bitops.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/init.h>
@@ -19,7 +20,6 @@
#include <linux/platform_device.h>
#include <linux/types.h>
#include <linux/watchdog.h>
-#include <asm/bitops.h>
#include <asm/uaccess.h>
#include <asm/arch/at91_st.h>
diff --git a/drivers/char/watchdog/bfin_wdt.c b/drivers/watchdog/bfin_wdt.c
index 309d27913fc1..309d27913fc1 100644
--- a/drivers/char/watchdog/bfin_wdt.c
+++ b/drivers/watchdog/bfin_wdt.c
diff --git a/drivers/char/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c
index d362f5bf658a..d362f5bf658a 100644
--- a/drivers/char/watchdog/booke_wdt.c
+++ b/drivers/watchdog/booke_wdt.c
diff --git a/drivers/char/watchdog/cpu5wdt.c b/drivers/watchdog/cpu5wdt.c
index 5941ca601a3a..5941ca601a3a 100644
--- a/drivers/char/watchdog/cpu5wdt.c
+++ b/drivers/watchdog/cpu5wdt.c
diff --git a/drivers/char/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c
index 19db5302ba6e..a61cbd48dc07 100644
--- a/drivers/char/watchdog/davinci_wdt.c
+++ b/drivers/watchdog/davinci_wdt.c
@@ -61,7 +61,7 @@
static int heartbeat = DEFAULT_HEARTBEAT;
-static spinlock_t io_lock;
+static DEFINE_SPINLOCK(io_lock);
static unsigned long wdt_status;
#define WDT_IN_USE 0
#define WDT_OK_TO_CLOSE 1
@@ -200,8 +200,6 @@ static int davinci_wdt_probe(struct platform_device *pdev)
int ret = 0, size;
struct resource *res;
- spin_lock_init(&io_lock);
-
if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT)
heartbeat = DEFAULT_HEARTBEAT;
@@ -262,7 +260,7 @@ static int __init davinci_wdt_init(void)
static void __exit davinci_wdt_exit(void)
{
- return platform_driver_unregister(&platform_wdt_driver);
+ platform_driver_unregister(&platform_wdt_driver);
}
module_init(davinci_wdt_init);
diff --git a/drivers/char/watchdog/ep93xx_wdt.c b/drivers/watchdog/ep93xx_wdt.c
index 0e4787a0bb87..0e4787a0bb87 100644
--- a/drivers/char/watchdog/ep93xx_wdt.c
+++ b/drivers/watchdog/ep93xx_wdt.c
diff --git a/drivers/char/watchdog/eurotechwdt.c b/drivers/watchdog/eurotechwdt.c
index b14e9d1f164d..b14e9d1f164d 100644
--- a/drivers/char/watchdog/eurotechwdt.c
+++ b/drivers/watchdog/eurotechwdt.c
diff --git a/drivers/char/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c
index c5982502c03d..ca44fd9b19bb 100644
--- a/drivers/char/watchdog/i6300esb.c
+++ b/drivers/watchdog/i6300esb.c
@@ -2,7 +2,7 @@
* i6300esb: Watchdog timer driver for Intel 6300ESB chipset
*
* (c) Copyright 2004 Google Inc.
- * (c) Copyright 2005 David Härdeman <david@2gen.com>
+ * (c) Copyright 2005 David Härdeman <david@2gen.com>
*
* 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 @@
* Initial version 0.01
* 2004YYZZ Ross Biro
* Version 0.02
- * 20050210 David Härdeman <david@2gen.com>
+ * 20050210 David Härdeman <david@2gen.com>
* Ported driver to kernel 2.6
*/
@@ -77,7 +77,7 @@
/* internal variables */
static void __iomem *BASEADDR;
-static spinlock_t esb_lock; /* Guards the hardware */
+static DEFINE_SPINLOCK(esb_lock); /* Guards the hardware */
static unsigned long timer_alive;
static struct pci_dev *esb_pci;
static unsigned short triggered; /* The status of the watchdog upon boot */
@@ -456,8 +456,6 @@ static int __init watchdog_init (void)
{
int ret;
- spin_lock_init(&esb_lock);
-
/* Check whether or not the hardware watchdog is there */
if (!esb_getdevice () || esb_pci == NULL)
return -ENODEV;
@@ -521,7 +519,7 @@ static void __exit watchdog_cleanup (void)
module_init(watchdog_init);
module_exit(watchdog_cleanup);
-MODULE_AUTHOR("Ross Biro and David Härdeman");
+MODULE_AUTHOR("Ross Biro and David Härdeman");
MODULE_DESCRIPTION("Watchdog driver for Intel 6300ESB chipsets");
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/iTCO_vendor_support.c b/drivers/watchdog/iTCO_vendor_support.c
index 415083990097..cafc465f2ae3 100644
--- a/drivers/char/watchdog/iTCO_vendor_support.c
+++ b/drivers/watchdog/iTCO_vendor_support.c
@@ -115,7 +115,7 @@ static void supermicro_old_pre_keepalive(unsigned long acpibase)
* For P4DPx:
* BIOS setup -> Advanced -> I/O Device Configuration -> Watch Dog
* This setting enables or disables Watchdog function. When enabled, the
- * default watchdog timer is set to be 5 minutes (about 4’35â€). It is
+ * default watchdog timer is set to be 5 minutes (about 4m35s). It is
* enough to load and run the OS. The application (service or driver) has
* to take over the control once OS is running up and before watchdog
* expires.
diff --git a/drivers/char/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c
index cd5a565bc3a0..a0e6809e369f 100644
--- a/drivers/char/watchdog/iTCO_wdt.c
+++ b/drivers/watchdog/iTCO_wdt.c
@@ -35,10 +35,12 @@
* 82801GDH (ICH7DH) : document number 307013-002, 307014-009,
* 82801GBM (ICH7-M) : document number 307013-002, 307014-009,
* 82801GHM (ICH7-M DH) : document number 307013-002, 307014-009,
- * 82801HB (ICH8) : document number 313056-002, 313057-004,
- * 82801HR (ICH8R) : document number 313056-002, 313057-004,
- * 82801HH (ICH8DH) : document number 313056-002, 313057-004,
- * 82801HO (ICH8DO) : document number 313056-002, 313057-004,
+ * 82801HB (ICH8) : document number 313056-003, 313057-009,
+ * 82801HR (ICH8R) : document number 313056-003, 313057-009,
+ * 82801HBM (ICH8M) : document number 313056-003, 313057-009,
+ * 82801HH (ICH8DH) : document number 313056-003, 313057-009,
+ * 82801HO (ICH8DO) : document number 313056-003, 313057-009,
+ * 82801HEM (ICH8M-E) : document number 313056-003, 313057-009,
* 82801IB (ICH9) : document number 316972-001, 316973-001,
* 82801IR (ICH9R) : document number 316972-001, 316973-001,
* 82801IH (ICH9DH) : document number 316972-001, 316973-001,
@@ -95,8 +97,10 @@ enum iTCO_chipsets {
TCO_ICH7M, /* ICH7-M */
TCO_ICH7MDH, /* ICH7-M DH */
TCO_ICH8, /* ICH8 & ICH8R */
+ TCO_ICH8ME, /* ICH8M-E */
TCO_ICH8DH, /* ICH8DH */
TCO_ICH8DO, /* ICH8DO */
+ TCO_ICH8M, /* ICH8M */
TCO_ICH9, /* ICH9 */
TCO_ICH9R, /* ICH9R */
TCO_ICH9DH, /* ICH9DH */
@@ -125,8 +129,10 @@ static struct {
{"ICH7-M", 2},
{"ICH7-M DH", 2},
{"ICH8 or ICH8R", 2},
+ {"ICH8M-E", 2},
{"ICH8DH", 2},
{"ICH8DO", 2},
+ {"ICH8M", 2},
{"ICH9", 2},
{"ICH9R", 2},
{"ICH9DH", 2},
@@ -134,6 +140,15 @@ static struct {
{NULL,0}
};
+#define ITCO_PCI_DEVICE(dev, data) \
+ .vendor = PCI_VENDOR_ID_INTEL, \
+ .device = dev, \
+ .subvendor = PCI_ANY_ID, \
+ .subdevice = PCI_ANY_ID, \
+ .class = 0, \
+ .class_mask = 0, \
+ .driver_data = data
+
/*
* This data only exists for exporting the supported PCI ids
* via MODULE_DEVICE_TABLE. We do not actually register a
@@ -141,45 +156,47 @@ static struct {
* functions that probably will be registered by other drivers.
*/
static struct pci_device_id iTCO_wdt_pci_tbl[] = {
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH0 },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH2 },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH2M },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH3 },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH3M },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH4 },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH4M },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_CICH },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH5 },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_6300ESB },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH6 },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH6M },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH6W },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7 },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7M },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7MDH },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8 },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8DH },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8DO },
- { PCI_VENDOR_ID_INTEL, 0x2918, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH9 },
- { PCI_VENDOR_ID_INTEL, 0x2916, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH9R },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH9DH },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
- { PCI_VENDOR_ID_INTEL, 0x2671, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
- { PCI_VENDOR_ID_INTEL, 0x2672, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
- { PCI_VENDOR_ID_INTEL, 0x2673, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
- { PCI_VENDOR_ID_INTEL, 0x2674, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
- { PCI_VENDOR_ID_INTEL, 0x2675, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
- { PCI_VENDOR_ID_INTEL, 0x2676, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
- { PCI_VENDOR_ID_INTEL, 0x2677, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
- { PCI_VENDOR_ID_INTEL, 0x2678, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
- { PCI_VENDOR_ID_INTEL, 0x2679, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
- { PCI_VENDOR_ID_INTEL, 0x267a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
- { PCI_VENDOR_ID_INTEL, 0x267b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
- { PCI_VENDOR_ID_INTEL, 0x267c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
- { PCI_VENDOR_ID_INTEL, 0x267d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
- { PCI_VENDOR_ID_INTEL, 0x267e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
- { PCI_VENDOR_ID_INTEL, 0x267f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801AA_0, TCO_ICH )},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801AB_0, TCO_ICH0 )},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801BA_0, TCO_ICH2 )},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801BA_10, TCO_ICH2M )},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801CA_0, TCO_ICH3 )},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801CA_12, TCO_ICH3M )},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801DB_0, TCO_ICH4 )},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801DB_12, TCO_ICH4M )},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801E_0, TCO_CICH )},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801EB_0, TCO_ICH5 )},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ESB_1, TCO_6300ESB)},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH6_0, TCO_ICH6 )},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH6_1, TCO_ICH6M )},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH6_2, TCO_ICH6W )},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_0, TCO_ICH7 )},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_1, TCO_ICH7M )},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_31, TCO_ICH7MDH)},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_0, TCO_ICH8 )},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_1, TCO_ICH8ME )},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_2, TCO_ICH8DH )},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_3, TCO_ICH8DO )},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_4, TCO_ICH8M )},
+ { ITCO_PCI_DEVICE(0x2918, TCO_ICH9 )},
+ { ITCO_PCI_DEVICE(0x2916, TCO_ICH9R )},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH9_2, TCO_ICH9DH )},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ESB2_0, TCO_631XESB)},
+ { ITCO_PCI_DEVICE(0x2671, TCO_631XESB)},
+ { ITCO_PCI_DEVICE(0x2672, TCO_631XESB)},
+ { ITCO_PCI_DEVICE(0x2673, TCO_631XESB)},
+ { ITCO_PCI_DEVICE(0x2674, TCO_631XESB)},
+ { ITCO_PCI_DEVICE(0x2675, TCO_631XESB)},
+ { ITCO_PCI_DEVICE(0x2676, TCO_631XESB)},
+ { ITCO_PCI_DEVICE(0x2677, TCO_631XESB)},
+ { ITCO_PCI_DEVICE(0x2678, TCO_631XESB)},
+ { ITCO_PCI_DEVICE(0x2679, TCO_631XESB)},
+ { ITCO_PCI_DEVICE(0x267a, TCO_631XESB)},
+ { ITCO_PCI_DEVICE(0x267b, TCO_631XESB)},
+ { ITCO_PCI_DEVICE(0x267c, TCO_631XESB)},
+ { ITCO_PCI_DEVICE(0x267d, TCO_631XESB)},
+ { ITCO_PCI_DEVICE(0x267e, TCO_631XESB)},
+ { ITCO_PCI_DEVICE(0x267f, TCO_631XESB)},
{ 0, }, /* End of list */
};
MODULE_DEVICE_TABLE (pci, iTCO_wdt_pci_tbl);
@@ -300,6 +317,7 @@ static int iTCO_wdt_start(void)
/* disable chipset's NO_REBOOT bit */
if (iTCO_wdt_unset_NO_REBOOT_bit()) {
+ spin_unlock(&iTCO_wdt_private.io_lock);
printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot disabled by hardware\n");
return -EIO;
}
@@ -590,7 +608,7 @@ static struct miscdevice iTCO_wdt_miscdev = {
* Init & exit routines
*/
-static int iTCO_wdt_init(struct pci_dev *pdev, const struct pci_device_id *ent, struct platform_device *dev)
+static int __devinit iTCO_wdt_init(struct pci_dev *pdev, const struct pci_device_id *ent, struct platform_device *dev)
{
int ret;
u32 base_address;
@@ -694,7 +712,7 @@ out:
return ret;
}
-static void iTCO_wdt_cleanup(void)
+static void __devexit iTCO_wdt_cleanup(void)
{
/* Stop the timer before we leave */
if (!nowayout)
@@ -709,7 +727,7 @@ static void iTCO_wdt_cleanup(void)
iTCO_wdt_private.ACPIBASE = 0;
}
-static int iTCO_wdt_probe(struct platform_device *dev)
+static int __devinit iTCO_wdt_probe(struct platform_device *dev)
{
int found = 0;
struct pci_dev *pdev = NULL;
@@ -735,7 +753,7 @@ static int iTCO_wdt_probe(struct platform_device *dev)
return 0;
}
-static int iTCO_wdt_remove(struct platform_device *dev)
+static int __devexit iTCO_wdt_remove(struct platform_device *dev)
{
if (iTCO_wdt_private.ACPIBASE)
iTCO_wdt_cleanup();
@@ -753,7 +771,7 @@ static void iTCO_wdt_shutdown(struct platform_device *dev)
static struct platform_driver iTCO_wdt_driver = {
.probe = iTCO_wdt_probe,
- .remove = iTCO_wdt_remove,
+ .remove = __devexit_p(iTCO_wdt_remove),
.shutdown = iTCO_wdt_shutdown,
.suspend = iTCO_wdt_suspend,
.resume = iTCO_wdt_resume,
diff --git a/drivers/char/watchdog/ib700wdt.c b/drivers/watchdog/ib700wdt.c
index c3a60f52ccb9..4b89f401691a 100644
--- a/drivers/char/watchdog/ib700wdt.c
+++ b/drivers/watchdog/ib700wdt.c
@@ -48,7 +48,7 @@
static struct platform_device *ibwdt_platform_device;
static unsigned long ibwdt_is_open;
-static spinlock_t ibwdt_lock;
+static DEFINE_SPINLOCK(ibwdt_lock);
static char expect_close;
/* Module information */
@@ -308,8 +308,6 @@ static int __devinit ibwdt_probe(struct platform_device *dev)
{
int res;
- spin_lock_init(&ibwdt_lock);
-
#if WDT_START != WDT_STOP
if (!request_region(WDT_STOP, 1, "IB700 WDT")) {
printk (KERN_ERR PFX "STOP method I/O %X is not available.\n", WDT_STOP);
diff --git a/drivers/char/watchdog/ibmasr.c b/drivers/watchdog/ibmasr.c
index 94155f6136c2..94155f6136c2 100644
--- a/drivers/char/watchdog/ibmasr.c
+++ b/drivers/watchdog/ibmasr.c
diff --git a/drivers/char/watchdog/indydog.c b/drivers/watchdog/indydog.c
index 788245bdaa7f..788245bdaa7f 100644
--- a/drivers/char/watchdog/indydog.c
+++ b/drivers/watchdog/indydog.c
diff --git a/drivers/char/watchdog/iop_wdt.c b/drivers/watchdog/iop_wdt.c
index bbbd91af754d..bbbd91af754d 100644
--- a/drivers/char/watchdog/iop_wdt.c
+++ b/drivers/watchdog/iop_wdt.c
diff --git a/drivers/char/watchdog/ixp2000_wdt.c b/drivers/watchdog/ixp2000_wdt.c
index dc7548dcaf35..dc7548dcaf35 100644
--- a/drivers/char/watchdog/ixp2000_wdt.c
+++ b/drivers/watchdog/ixp2000_wdt.c
diff --git a/drivers/char/watchdog/ixp4xx_wdt.c b/drivers/watchdog/ixp4xx_wdt.c
index 5864bb865cfe..5864bb865cfe 100644
--- a/drivers/char/watchdog/ixp4xx_wdt.c
+++ b/drivers/watchdog/ixp4xx_wdt.c
diff --git a/drivers/char/watchdog/ks8695_wdt.c b/drivers/watchdog/ks8695_wdt.c
index 7150fb945eaf..e3a29c302309 100644
--- a/drivers/char/watchdog/ks8695_wdt.c
+++ b/drivers/watchdog/ks8695_wdt.c
@@ -8,6 +8,7 @@
* published by the Free Software Foundation.
*/
+#include <linux/bitops.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/init.h>
@@ -18,7 +19,6 @@
#include <linux/platform_device.h>
#include <linux/types.h>
#include <linux/watchdog.h>
-#include <asm/bitops.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/arch/regs-timer.h>
diff --git a/drivers/char/watchdog/machzwd.c b/drivers/watchdog/machzwd.c
index 6d35bb112a5f..e6e07b4575eb 100644
--- a/drivers/char/watchdog/machzwd.c
+++ b/drivers/watchdog/machzwd.c
@@ -123,8 +123,8 @@ static void zf_ping(unsigned long data);
static int zf_action = GEN_RESET;
static unsigned long zf_is_open;
static char zf_expect_close;
-static spinlock_t zf_lock;
-static spinlock_t zf_port_lock;
+static DEFINE_SPINLOCK(zf_lock);
+static DEFINE_SPINLOCK(zf_port_lock);
static DEFINE_TIMER(zf_timer, zf_ping, 0, 0);
static unsigned long next_heartbeat = 0;
@@ -438,9 +438,6 @@ static int __init zf_init(void)
zf_show_action(action);
- spin_lock_init(&zf_lock);
- spin_lock_init(&zf_port_lock);
-
if(!request_region(ZF_IOBASE, 3, "MachZ ZFL WDT")){
printk(KERN_ERR "cannot reserve I/O ports at %d\n",
ZF_IOBASE);
diff --git a/drivers/char/watchdog/mixcomwd.c b/drivers/watchdog/mixcomwd.c
index 1adf1d56027d..1adf1d56027d 100644
--- a/drivers/char/watchdog/mixcomwd.c
+++ b/drivers/watchdog/mixcomwd.c
diff --git a/drivers/char/watchdog/mpc5200_wdt.c b/drivers/watchdog/mpc5200_wdt.c
index 9cfb97576623..11f6a111e75b 100644
--- a/drivers/char/watchdog/mpc5200_wdt.c
+++ b/drivers/watchdog/mpc5200_wdt.c
@@ -176,6 +176,8 @@ static int mpc5200_wdt_probe(struct of_device *op, const struct of_device_id *ma
has_wdt = of_get_property(op->node, "has-wdt", NULL);
if (!has_wdt)
+ has_wdt = of_get_property(op->node, "fsl,has-wdt", NULL);
+ if (!has_wdt)
return -ENODEV;
wdt = kzalloc(sizeof(*wdt), GFP_KERNEL);
@@ -254,6 +256,7 @@ static int mpc5200_wdt_shutdown(struct of_device *op)
static struct of_device_id mpc5200_wdt_match[] = {
{ .compatible = "mpc5200-gpt", },
+ { .compatible = "fsl,mpc5200-gpt", },
{},
};
static struct of_platform_driver mpc5200_wdt_driver = {
diff --git a/drivers/char/watchdog/mpc83xx_wdt.c b/drivers/watchdog/mpc83xx_wdt.c
index a0bf95fb9763..6369f569517f 100644
--- a/drivers/char/watchdog/mpc83xx_wdt.c
+++ b/drivers/watchdog/mpc83xx_wdt.c
@@ -56,7 +56,7 @@ static int prescale = 1;
static unsigned int timeout_sec;
static unsigned long wdt_is_open;
-static spinlock_t wdt_spinlock;
+static DEFINE_SPINLOCK(wdt_spinlock);
static void mpc83xx_wdt_keepalive(void)
{
@@ -185,9 +185,6 @@ static int __devinit mpc83xx_wdt_probe(struct platform_device *dev)
printk(KERN_INFO "WDT driver for MPC83xx initialized. "
"mode:%s timeout=%d (%d seconds)\n",
reset ? "reset":"interrupt", timeout, timeout_sec);
-
- spin_lock_init(&wdt_spinlock);
-
return 0;
err_unmap:
diff --git a/drivers/char/watchdog/mpc8xx_wdt.c b/drivers/watchdog/mpc8xx_wdt.c
index 85b5734403a5..85b5734403a5 100644
--- a/drivers/char/watchdog/mpc8xx_wdt.c
+++ b/drivers/watchdog/mpc8xx_wdt.c
diff --git a/drivers/char/watchdog/mpcore_wdt.c b/drivers/watchdog/mpcore_wdt.c
index 0d2b27735419..0d2b27735419 100644
--- a/drivers/char/watchdog/mpcore_wdt.c
+++ b/drivers/watchdog/mpcore_wdt.c
diff --git a/drivers/char/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c
index dcfd401a7ad7..dcfd401a7ad7 100644
--- a/drivers/char/watchdog/mtx-1_wdt.c
+++ b/drivers/watchdog/mtx-1_wdt.c
diff --git a/drivers/char/watchdog/mv64x60_wdt.c b/drivers/watchdog/mv64x60_wdt.c
index 0365c317f7e1..0365c317f7e1 100644
--- a/drivers/char/watchdog/mv64x60_wdt.c
+++ b/drivers/watchdog/mv64x60_wdt.c
diff --git a/drivers/char/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
index 719b066f73c4..635ca454f56b 100644
--- a/drivers/char/watchdog/omap_wdt.c
+++ b/drivers/watchdog/omap_wdt.c
@@ -39,11 +39,11 @@
#include <linux/platform_device.h>
#include <linux/moduleparam.h>
#include <linux/clk.h>
+#include <linux/bitops.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/hardware.h>
-#include <asm/bitops.h>
#include <asm/arch/prcm.h>
diff --git a/drivers/char/watchdog/omap_wdt.h b/drivers/watchdog/omap_wdt.h
index 52a532a5114a..52a532a5114a 100644
--- a/drivers/char/watchdog/omap_wdt.h
+++ b/drivers/watchdog/omap_wdt.h
diff --git a/drivers/char/watchdog/pc87413_wdt.c b/drivers/watchdog/pc87413_wdt.c
index 3d3deae0d64b..15e4f8887a9e 100644
--- a/drivers/char/watchdog/pc87413_wdt.c
+++ b/drivers/watchdog/pc87413_wdt.c
@@ -61,7 +61,7 @@ static unsigned long timer_enabled = 0; /* is the timer enabled? */
static char expect_close; /* is the close expected? */
-static spinlock_t io_lock; /* to guard the watchdog from io races */
+static DEFINE_SPINLOCK(io_lock);/* to guard the watchdog from io races */
static int nowayout = WATCHDOG_NOWAYOUT;
@@ -561,8 +561,6 @@ static int __init pc87413_init(void)
{
int ret;
- spin_lock_init(&io_lock);
-
printk(KERN_INFO PFX "Version " VERSION " at io 0x%X\n", WDT_INDEX_IO_PORT);
/* request_region(io, 2, "pc87413"); */
diff --git a/drivers/char/watchdog/pcwd.c b/drivers/watchdog/pcwd.c
index 7b41434fac8c..7b41434fac8c 100644
--- a/drivers/char/watchdog/pcwd.c
+++ b/drivers/watchdog/pcwd.c
diff --git a/drivers/char/watchdog/pcwd_pci.c b/drivers/watchdog/pcwd_pci.c
index 61a89e959642..61a89e959642 100644
--- a/drivers/char/watchdog/pcwd_pci.c
+++ b/drivers/watchdog/pcwd_pci.c
diff --git a/drivers/char/watchdog/pcwd_usb.c b/drivers/watchdog/pcwd_usb.c
index 0f3fd6c9c354..0f3fd6c9c354 100644
--- a/drivers/char/watchdog/pcwd_usb.c
+++ b/drivers/watchdog/pcwd_usb.c
diff --git a/drivers/char/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c
index 22f8873dd092..b04aa096a10a 100644
--- a/drivers/char/watchdog/pnx4008_wdt.c
+++ b/drivers/watchdog/pnx4008_wdt.c
@@ -80,7 +80,7 @@
static int nowayout = WATCHDOG_NOWAYOUT;
static int heartbeat = DEFAULT_HEARTBEAT;
-static spinlock_t io_lock;
+static DEFINE_SPINLOCK(io_lock);
static unsigned long wdt_status;
#define WDT_IN_USE 0
#define WDT_OK_TO_CLOSE 1
@@ -254,8 +254,6 @@ static int pnx4008_wdt_probe(struct platform_device *pdev)
int ret = 0, size;
struct resource *res;
- spin_lock_init(&io_lock);
-
if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT)
heartbeat = DEFAULT_HEARTBEAT;
@@ -335,7 +333,7 @@ static int __init pnx4008_wdt_init(void)
static void __exit pnx4008_wdt_exit(void)
{
- return platform_driver_unregister(&platform_wdt_driver);
+ platform_driver_unregister(&platform_wdt_driver);
}
module_init(pnx4008_wdt_init);
diff --git a/drivers/char/watchdog/rm9k_wdt.c b/drivers/watchdog/rm9k_wdt.c
index 5c921e471564..5c921e471564 100644
--- a/drivers/char/watchdog/rm9k_wdt.c
+++ b/drivers/watchdog/rm9k_wdt.c
diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c
index 5d1c15f83d23..5d1c15f83d23 100644
--- a/drivers/char/watchdog/s3c2410_wdt.c
+++ b/drivers/watchdog/s3c2410_wdt.c
diff --git a/drivers/char/watchdog/sa1100_wdt.c b/drivers/watchdog/sa1100_wdt.c
index 3475f47aaa45..34a2b3b81800 100644
--- a/drivers/char/watchdog/sa1100_wdt.c
+++ b/drivers/watchdog/sa1100_wdt.c
@@ -25,13 +25,13 @@
#include <linux/miscdevice.h>
#include <linux/watchdog.h>
#include <linux/init.h>
+#include <linux/bitops.h>
#ifdef CONFIG_ARCH_PXA
#include <asm/arch/pxa-regs.h>
#endif
#include <asm/hardware.h>
-#include <asm/bitops.h>
#include <asm/uaccess.h>
#define OSCR_FREQ CLOCK_TICK_RATE
diff --git a/drivers/char/watchdog/sbc60xxwdt.c b/drivers/watchdog/sbc60xxwdt.c
index e4f3cb6090bc..e4f3cb6090bc 100644
--- a/drivers/char/watchdog/sbc60xxwdt.c
+++ b/drivers/watchdog/sbc60xxwdt.c
diff --git a/drivers/char/watchdog/sbc8360.c b/drivers/watchdog/sbc8360.c
index 285d85289532..2ee2677f3648 100644
--- a/drivers/char/watchdog/sbc8360.c
+++ b/drivers/watchdog/sbc8360.c
@@ -54,7 +54,7 @@
#include <asm/system.h>
static unsigned long sbc8360_is_open;
-static spinlock_t sbc8360_lock;
+static DEFINE_SPINLOCK(sbc8360_lock);
static char expect_close;
#define PFX "sbc8360: "
@@ -359,7 +359,6 @@ static int __init sbc8360_init(void)
goto out_noreboot;
}
- spin_lock_init(&sbc8360_lock);
res = misc_register(&sbc8360_miscdev);
if (res) {
printk(KERN_ERR PFX "failed to register misc device\n");
diff --git a/drivers/char/watchdog/sbc_epx_c3.c b/drivers/watchdog/sbc_epx_c3.c
index 82cbd8809a69..82cbd8809a69 100644
--- a/drivers/char/watchdog/sbc_epx_c3.c
+++ b/drivers/watchdog/sbc_epx_c3.c
diff --git a/drivers/char/watchdog/sc1200wdt.c b/drivers/watchdog/sc1200wdt.c
index 9670d47190d0..32ccd7c89c7d 100644
--- a/drivers/char/watchdog/sc1200wdt.c
+++ b/drivers/watchdog/sc1200wdt.c
@@ -74,7 +74,7 @@ static int io = -1;
static int io_len = 2; /* for non plug and play */
static struct semaphore open_sem;
static char expect_close;
-static spinlock_t sc1200wdt_lock; /* io port access serialisation */
+static DEFINE_SPINLOCK(sc1200wdt_lock); /* io port access serialisation */
#if defined CONFIG_PNP
static int isapnp = 1;
@@ -375,7 +375,6 @@ static int __init sc1200wdt_init(void)
printk("%s\n", banner);
- spin_lock_init(&sc1200wdt_lock);
sema_init(&open_sem, 1);
#if defined CONFIG_PNP
diff --git a/drivers/char/watchdog/sc520_wdt.c b/drivers/watchdog/sc520_wdt.c
index e8594c64d1e6..2847324a2be2 100644
--- a/drivers/char/watchdog/sc520_wdt.c
+++ b/drivers/watchdog/sc520_wdt.c
@@ -125,7 +125,7 @@ static DEFINE_TIMER(timer, wdt_timer_ping, 0, 0);
static unsigned long next_heartbeat;
static unsigned long wdt_is_open;
static char wdt_expect_close;
-static spinlock_t wdt_spinlock;
+static DEFINE_SPINLOCK(wdt_spinlock);
/*
* Whack the dog
@@ -383,8 +383,6 @@ static int __init sc520_wdt_init(void)
{
int rc = -EBUSY;
- spin_lock_init(&wdt_spinlock);
-
/* Check that the timeout value is within it's range ; if not reset to the default */
if (wdt_set_heartbeat(timeout)) {
wdt_set_heartbeat(WATCHDOG_TIMEOUT);
diff --git a/drivers/char/watchdog/scx200_wdt.c b/drivers/watchdog/scx200_wdt.c
index d4fd0fa2f176..d4fd0fa2f176 100644
--- a/drivers/char/watchdog/scx200_wdt.c
+++ b/drivers/watchdog/scx200_wdt.c
diff --git a/drivers/char/watchdog/shwdt.c b/drivers/watchdog/shwdt.c
index cecbedd473a4..cecbedd473a4 100644
--- a/drivers/char/watchdog/shwdt.c
+++ b/drivers/watchdog/shwdt.c
diff --git a/drivers/char/watchdog/smsc37b787_wdt.c b/drivers/watchdog/smsc37b787_wdt.c
index d3cb0a766020..5d2b5ba61414 100644
--- a/drivers/char/watchdog/smsc37b787_wdt.c
+++ b/drivers/watchdog/smsc37b787_wdt.c
@@ -83,7 +83,7 @@ static unsigned long timer_enabled = 0; /* is the timer enabled? */
static char expect_close; /* is the close expected? */
-static spinlock_t io_lock; /* to guard the watchdog from io races */
+static DEFINE_SPINLOCK(io_lock);/* to guard the watchdog from io races */
static int nowayout = WATCHDOG_NOWAYOUT;
@@ -540,8 +540,6 @@ static int __init wb_smsc_wdt_init(void)
{
int ret;
- spin_lock_init(&io_lock);
-
printk("SMsC 37B787 watchdog component driver " VERSION " initialising...\n");
if (!request_region(IOPORT, IOPORT_SIZE, "SMsC 37B787 watchdog")) {
diff --git a/drivers/char/watchdog/softdog.c b/drivers/watchdog/softdog.c
index 9c3694909243..9c3694909243 100644
--- a/drivers/char/watchdog/softdog.c
+++ b/drivers/watchdog/softdog.c
diff --git a/drivers/char/watchdog/w83627hf_wdt.c b/drivers/watchdog/w83627hf_wdt.c
index df33b3b5a53c..386492821fc2 100644
--- a/drivers/char/watchdog/w83627hf_wdt.c
+++ b/drivers/watchdog/w83627hf_wdt.c
@@ -48,7 +48,7 @@
static unsigned long wdt_is_open;
static char expect_close;
-static spinlock_t io_lock;
+static DEFINE_SPINLOCK(io_lock);
/* You must set this - there is no sane way to probe for this board. */
static int wdt_io = 0x2E;
@@ -328,8 +328,6 @@ wdt_init(void)
{
int ret;
- spin_lock_init(&io_lock);
-
printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF/THF/HG Super I/O chip initialising.\n");
if (wdt_set_heartbeat(timeout)) {
diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/watchdog/w83697hf_wdt.c
index d9e821d08deb..c622a0e6c9ae 100644
--- a/drivers/char/watchdog/w83697hf_wdt.c
+++ b/drivers/watchdog/w83697hf_wdt.c
@@ -8,7 +8,7 @@
* which is based on wdt.c.
* Original copyright messages:
*
- * (c) Copyright 2003 Pádraig Brady <P@draigBrady.com>
+ * (c) Copyright 2003 Pádraig Brady <P@draigBrady.com>
*
* (c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl>
*
@@ -47,7 +47,7 @@
static unsigned long wdt_is_open;
static char expect_close;
-static spinlock_t io_lock;
+static DEFINE_SPINLOCK(io_lock);
/* You must set this - there is no sane way to probe for this board. */
static int wdt_io = 0x2e;
@@ -376,8 +376,6 @@ wdt_init(void)
{
int ret, i, found = 0;
- spin_lock_init(&io_lock);
-
printk (KERN_INFO PFX "WDT driver for W83697HF/HG initializing\n");
if (wdt_io == 0) {
diff --git a/drivers/char/watchdog/w83877f_wdt.c b/drivers/watchdog/w83877f_wdt.c
index 3c88fe18f4f4..bcc9d48955de 100644
--- a/drivers/char/watchdog/w83877f_wdt.c
+++ b/drivers/watchdog/w83877f_wdt.c
@@ -94,7 +94,7 @@ static DEFINE_TIMER(timer, wdt_timer_ping, 0, 0);
static unsigned long next_heartbeat;
static unsigned long wdt_is_open;
static char wdt_expect_close;
-static spinlock_t wdt_spinlock;
+static DEFINE_SPINLOCK(wdt_spinlock);
/*
* Whack the dog
@@ -350,8 +350,6 @@ static int __init w83877f_wdt_init(void)
{
int rc = -EBUSY;
- spin_lock_init(&wdt_spinlock);
-
if(timeout < 1 || timeout > 3600) /* arbitrary upper limit */
{
timeout = WATCHDOG_TIMEOUT;
diff --git a/drivers/char/watchdog/w83977f_wdt.c b/drivers/watchdog/w83977f_wdt.c
index 157968442891..b475529d2475 100644
--- a/drivers/char/watchdog/w83977f_wdt.c
+++ b/drivers/watchdog/w83977f_wdt.c
@@ -50,7 +50,7 @@ static int timeoutW; /* timeout in watchdog counter units */
static unsigned long timer_alive;
static int testmode;
static char expect_close;
-static spinlock_t spinlock;
+static DEFINE_SPINLOCK(spinlock);
module_param(timeout, int, 0);
MODULE_PARM_DESC(timeout,"Watchdog timeout in seconds (15..7635), default=" __MODULE_STRING(DEFAULT_TIMEOUT) ")");
@@ -476,8 +476,6 @@ static int __init w83977f_wdt_init(void)
printk(KERN_INFO PFX DRIVER_VERSION);
- spin_lock_init(&spinlock);
-
/*
* Check that the timeout value is within it's range ;
* if not reset to the default
diff --git a/drivers/char/watchdog/wafer5823wdt.c b/drivers/watchdog/wafer5823wdt.c
index 950905d3c39f..9e368091f799 100644
--- a/drivers/char/watchdog/wafer5823wdt.c
+++ b/drivers/watchdog/wafer5823wdt.c
@@ -45,7 +45,7 @@
static unsigned long wafwdt_is_open;
static char expect_close;
-static spinlock_t wafwdt_lock;
+static DEFINE_SPINLOCK(wafwdt_lock);
/*
* You must set these - there is no sane way to probe for this board.
@@ -252,8 +252,6 @@ static int __init wafwdt_init(void)
printk(KERN_INFO "WDT driver for Wafer 5823 single board computer initialising.\n");
- spin_lock_init(&wafwdt_lock);
-
if (timeout < 1 || timeout > 255) {
timeout = WD_TIMO;
printk (KERN_INFO PFX "timeout value must be 1<=x<=255, using %d\n",
diff --git a/drivers/char/watchdog/wd501p.h b/drivers/watchdog/wd501p.h
index a4504f40394d..a4504f40394d 100644
--- a/drivers/char/watchdog/wd501p.h
+++ b/drivers/watchdog/wd501p.h
diff --git a/drivers/char/watchdog/wdrtas.c b/drivers/watchdog/wdrtas.c
index 1d64e277567d..1d64e277567d 100644
--- a/drivers/char/watchdog/wdrtas.c
+++ b/drivers/watchdog/wdrtas.c
diff --git a/drivers/char/watchdog/wdt.c b/drivers/watchdog/wdt.c
index 0a3de6a02442..53d0bb410df8 100644
--- a/drivers/char/watchdog/wdt.c
+++ b/drivers/watchdog/wdt.c
@@ -253,7 +253,7 @@ static irqreturn_t wdt_interrupt(int irq, void *dev_id)
printk(KERN_CRIT "Possible fan fault.\n");
}
#endif /* CONFIG_WDT_501 */
- if (!(status & WDC_SR_WCCR))
+ if (!(status & WDC_SR_WCCR)) {
#ifdef SOFTWARE_REBOOT
#ifdef ONLY_TESTING
printk(KERN_CRIT "Would Reboot.\n");
@@ -264,6 +264,7 @@ static irqreturn_t wdt_interrupt(int irq, void *dev_id)
#else
printk(KERN_CRIT "Reset in 5ms.\n");
#endif
+ }
return IRQ_HANDLED;
}
diff --git a/drivers/char/watchdog/wdt285.c b/drivers/watchdog/wdt285.c
index e4cf661dc890..e4cf661dc890 100644
--- a/drivers/char/watchdog/wdt285.c
+++ b/drivers/watchdog/wdt285.c
diff --git a/drivers/char/watchdog/wdt977.c b/drivers/watchdog/wdt977.c
index 7d300ff7ab07..9b7f6b6edef6 100644
--- a/drivers/char/watchdog/wdt977.c
+++ b/drivers/watchdog/wdt977.c
@@ -59,7 +59,7 @@ static int timeoutM; /* timeout in minutes */
static unsigned long timer_alive;
static int testmode;
static char expect_close;
-static spinlock_t spinlock;
+static DEFINE_SPINLOCK(spinlock);
module_param(timeout, int, 0);
MODULE_PARM_DESC(timeout,"Watchdog timeout in seconds (60..15300), default=" __MODULE_STRING(DEFAULT_TIMEOUT) ")");
@@ -448,8 +448,6 @@ static int __init wd977_init(void)
printk(KERN_INFO PFX DRIVER_VERSION);
- spin_lock_init(&spinlock);
-
/* Check that the timeout value is within it's range ; if not reset to the default */
if (wdt977_set_timeout(timeout))
{
diff --git a/drivers/char/watchdog/wdt_pci.c b/drivers/watchdog/wdt_pci.c
index 6baf4ae42c9d..1355608683e4 100644
--- a/drivers/char/watchdog/wdt_pci.c
+++ b/drivers/watchdog/wdt_pci.c
@@ -74,7 +74,7 @@
static int dev_count;
static struct semaphore open_sem;
-static spinlock_t wdtpci_lock;
+static DEFINE_SPINLOCK(wdtpci_lock);
static char expect_close;
static int io;
@@ -298,7 +298,7 @@ static irqreturn_t wdtpci_interrupt(int irq, void *dev_id)
printk(KERN_CRIT PFX "Possible fan fault.\n");
}
#endif /* CONFIG_WDT_501_PCI */
- if (!(status&WDC_SR_WCCR))
+ if (!(status&WDC_SR_WCCR)) {
#ifdef SOFTWARE_REBOOT
#ifdef ONLY_TESTING
printk(KERN_CRIT PFX "Would Reboot.\n");
@@ -309,6 +309,7 @@ static irqreturn_t wdtpci_interrupt(int irq, void *dev_id)
#else
printk(KERN_CRIT PFX "Reset in 5ms.\n");
#endif
+ }
return IRQ_HANDLED;
}
@@ -606,7 +607,6 @@ static int __devinit wdtpci_init_one (struct pci_dev *dev,
}
sema_init(&open_sem, 1);
- spin_lock_init(&wdtpci_lock);
irq = dev->irq;
io = pci_resource_start (dev, 2);
diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c
index 0b769f7c4a48..4750de316ad3 100644
--- a/drivers/xen/xenbus/xenbus_probe.c
+++ b/drivers/xen/xenbus/xenbus_probe.c
@@ -185,13 +185,14 @@ static void otherend_changed(struct xenbus_watch *watch,
if (!dev->otherend ||
strncmp(dev->otherend, vec[XS_WATCH_PATH],
strlen(dev->otherend))) {
- dev_dbg(&dev->dev, "Ignoring watch at %s", vec[XS_WATCH_PATH]);
+ dev_dbg(&dev->dev, "Ignoring watch at %s\n",
+ vec[XS_WATCH_PATH]);
return;
}
state = xenbus_read_driver_state(dev->otherend);
- dev_dbg(&dev->dev, "state is %d, (%s), %s, %s",
+ dev_dbg(&dev->dev, "state is %d, (%s), %s, %s\n",
state, xenbus_strstate(state), dev->otherend_watch.node,
vec[XS_WATCH_PATH]);
diff --git a/drivers/zorro/zorro.ids b/drivers/zorro/zorro.ids
index 5bd4b05d4c45..560fef2a7b1c 100644
--- a/drivers/zorro/zorro.ids
+++ b/drivers/zorro/zorro.ids
@@ -295,7 +295,7 @@
0100 RH 800C [HD Controller]
0200 RH 800C [RAM Expansion]
0861 Kato
-# The Rainbow II and III are actually made by Ingenieurbüro Helfrich
+# The Rainbow II and III are actually made by Ingenieurbüro Helfrich
2000 Rainbow II [Graphics Card]
2100 Rainbow III [Graphics Card]
8000 Melody MPEG [Audio Card]
diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index 15e05a15b575..b364da70ff28 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -1,6 +1,7 @@
/*
* V9FS FID Management
*
+ * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
* Copyright (C) 2005, 2006 by Eric Van Hensbergen <ericvh@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -34,9 +35,9 @@
#include "fid.h"
/**
- * v9fs_fid_insert - add a fid to a dentry
+ * v9fs_fid_add - add a fid to a dentry
+ * @dentry: dentry that the fid is being added to
* @fid: fid to add
- * @dentry: dentry that it is being added to
*
*/
@@ -66,52 +67,144 @@ int v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid)
}
/**
- * v9fs_fid_lookup - return a locked fid from a dentry
+ * v9fs_fid_find - retrieve a fid that belongs to the specified uid
* @dentry: dentry to look for fid in
- *
- * find a fid in the dentry, obtain its semaphore and return a reference to it.
- * code calling lookup is responsible for releasing lock
- *
- * TODO: only match fids that have the same uid as current user
+ * @uid: return fid that belongs to the specified user
+ * @any: if non-zero, return any fid associated with the dentry
*
*/
-struct p9_fid *v9fs_fid_lookup(struct dentry *dentry)
+static struct p9_fid *v9fs_fid_find(struct dentry *dentry, u32 uid, int any)
{
struct v9fs_dentry *dent;
- struct p9_fid *fid;
-
- P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
- dent = dentry->d_fsdata;
- if (dent)
- fid = list_entry(dent->fidlist.next, struct p9_fid, dlist);
- else
- fid = ERR_PTR(-EBADF);
+ struct p9_fid *fid, *ret;
+
+ P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p) uid %d any %d\n",
+ dentry->d_iname, dentry, uid, any);
+ dent = (struct v9fs_dentry *) dentry->d_fsdata;
+ ret = NULL;
+ if (dent) {
+ spin_lock(&dent->lock);
+ list_for_each_entry(fid, &dent->fidlist, dlist) {
+ if (any || fid->uid == uid) {
+ ret = fid;
+ break;
+ }
+ }
+ spin_unlock(&dent->lock);
+ }
- P9_DPRINTK(P9_DEBUG_VFS, " fid: %p\n", fid);
- return fid;
+ return ret;
}
/**
- * v9fs_fid_clone - lookup the fid for a dentry, clone a private copy and
- * release it
+ * v9fs_fid_lookup - lookup for a fid, try to walk if not found
* @dentry: dentry to look for fid in
*
- * find a fid in the dentry and then clone to a new private fid
- *
- * TODO: only match fids that have the same uid as current user
- *
+ * Look for a fid in the specified dentry for the current user.
+ * If no fid is found, try to create one walking from a fid from the parent
+ * dentry (if it has one), or the root dentry. If the user haven't accessed
+ * the fs yet, attach now and walk from the root.
*/
-struct p9_fid *v9fs_fid_clone(struct dentry *dentry)
+struct p9_fid *v9fs_fid_lookup(struct dentry *dentry)
{
- struct p9_fid *ofid, *fid;
+ int i, n, l, clone, any, access;
+ u32 uid;
+ struct p9_fid *fid;
+ struct dentry *d, *ds;
+ struct v9fs_session_info *v9ses;
+ char **wnames, *uname;
+
+ v9ses = v9fs_inode2v9ses(dentry->d_inode);
+ access = v9ses->flags & V9FS_ACCESS_MASK;
+ switch (access) {
+ case V9FS_ACCESS_SINGLE:
+ case V9FS_ACCESS_USER:
+ uid = current->fsuid;
+ any = 0;
+ break;
+
+ case V9FS_ACCESS_ANY:
+ uid = v9ses->uid;
+ any = 1;
+ break;
+
+ default:
+ uid = ~0;
+ any = 0;
+ break;
+ }
- P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
- ofid = v9fs_fid_lookup(dentry);
- if (IS_ERR(ofid))
- return ofid;
+ fid = v9fs_fid_find(dentry, uid, any);
+ if (fid)
+ return fid;
+
+ ds = dentry->d_parent;
+ fid = v9fs_fid_find(ds, uid, any);
+ if (!fid) { /* walk from the root */
+ n = 0;
+ for (ds = dentry; !IS_ROOT(ds); ds = ds->d_parent)
+ n++;
+
+ fid = v9fs_fid_find(ds, uid, any);
+ if (!fid) { /* the user is not attached to the fs yet */
+ if (access == V9FS_ACCESS_SINGLE)
+ return ERR_PTR(-EPERM);
+
+ if (v9fs_extended(v9ses))
+ uname = NULL;
+ else
+ uname = v9ses->uname;
+
+ fid = p9_client_attach(v9ses->clnt, NULL, uname, uid,
+ v9ses->aname);
+
+ if (IS_ERR(fid))
+ return fid;
+
+ v9fs_fid_add(ds, fid);
+ }
+ } else /* walk from the parent */
+ n = 1;
+
+ if (ds == dentry)
+ return fid;
+
+ wnames = kmalloc(sizeof(char *) * n, GFP_KERNEL);
+ if (!wnames)
+ return ERR_PTR(-ENOMEM);
+
+ for (d = dentry, i = n; i >= 0; i--, d = d->d_parent)
+ wnames[i] = (char *) d->d_name.name;
+
+ clone = 1;
+ i = 0;
+ while (i < n) {
+ l = min(n - i, P9_MAXWELEM);
+ fid = p9_client_walk(fid, l, &wnames[i], clone);
+ if (!fid) {
+ kfree(wnames);
+ return fid;
+ }
+
+ i += l;
+ clone = 0;
+ }
- fid = p9_client_walk(ofid, 0, NULL, 1);
+ kfree(wnames);
+ v9fs_fid_add(dentry, fid);
return fid;
}
+
+struct p9_fid *v9fs_fid_clone(struct dentry *dentry)
+{
+ struct p9_fid *fid, *ret;
+
+ fid = v9fs_fid_lookup(dentry);
+ if (IS_ERR(fid))
+ return fid;
+
+ ret = p9_client_walk(fid, 0, NULL, 1);
+ return ret;
+}
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
index 0a7068e30ecb..fbb12dadba83 100644
--- a/fs/9p/v9fs.c
+++ b/fs/9p/v9fs.c
@@ -38,56 +38,41 @@
/*
* Option Parsing (code inspired by NFS code)
- *
+ * NOTE: each transport will parse its own options
*/
enum {
/* Options that take integer arguments */
- Opt_debug, Opt_port, Opt_msize, Opt_uid, Opt_gid, Opt_afid,
- Opt_rfdno, Opt_wfdno,
+ Opt_debug, Opt_msize, Opt_dfltuid, Opt_dfltgid, Opt_afid,
/* String options */
- Opt_uname, Opt_remotename,
+ Opt_uname, Opt_remotename, Opt_trans,
/* Options that take no arguments */
- Opt_legacy, Opt_nodevmap, Opt_unix, Opt_tcp, Opt_fd, Opt_pci,
+ Opt_legacy, Opt_nodevmap,
/* Cache options */
Opt_cache_loose,
+ /* Access options */
+ Opt_access,
/* Error token */
Opt_err
};
static match_table_t tokens = {
{Opt_debug, "debug=%x"},
- {Opt_port, "port=%u"},
{Opt_msize, "msize=%u"},
- {Opt_uid, "uid=%u"},
- {Opt_gid, "gid=%u"},
+ {Opt_dfltuid, "dfltuid=%u"},
+ {Opt_dfltgid, "dfltgid=%u"},
{Opt_afid, "afid=%u"},
- {Opt_rfdno, "rfdno=%u"},
- {Opt_wfdno, "wfdno=%u"},
{Opt_uname, "uname=%s"},
{Opt_remotename, "aname=%s"},
- {Opt_unix, "proto=unix"},
- {Opt_tcp, "proto=tcp"},
- {Opt_fd, "proto=fd"},
-#ifdef CONFIG_PCI_9P
- {Opt_pci, "proto=pci"},
-#endif
- {Opt_tcp, "tcp"},
- {Opt_unix, "unix"},
- {Opt_fd, "fd"},
+ {Opt_trans, "trans=%s"},
{Opt_legacy, "noextend"},
{Opt_nodevmap, "nodevmap"},
{Opt_cache_loose, "cache=loose"},
{Opt_cache_loose, "loose"},
+ {Opt_access, "access=%s"},
{Opt_err, NULL}
};
-extern struct p9_transport *p9pci_trans_create(void);
-
-/*
- * Parse option string.
- */
-
/**
* v9fs_parse_options - parse mount options into session structure
* @options: options string passed from mount
@@ -95,27 +80,26 @@ extern struct p9_transport *p9pci_trans_create(void);
*
*/
-static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses)
+static void v9fs_parse_options(struct v9fs_session_info *v9ses)
{
- char *p;
+ char *options;
substring_t args[MAX_OPT_ARGS];
+ char *p;
int option;
int ret;
+ char *s, *e;
/* setup defaults */
- v9ses->port = V9FS_PORT;
- v9ses->maxdata = 9000;
- v9ses->proto = PROTO_TCP;
- v9ses->extended = 1;
+ v9ses->maxdata = 8192;
v9ses->afid = ~0;
v9ses->debug = 0;
- v9ses->rfdno = ~0;
- v9ses->wfdno = ~0;
v9ses->cache = 0;
+ v9ses->trans = v9fs_default_trans();
- if (!options)
+ if (!v9ses->options)
return;
+ options = kstrdup(v9ses->options, GFP_KERNEL);
while ((p = strsep(&options, ",")) != NULL) {
int token;
if (!*p)
@@ -135,47 +119,29 @@ static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses)
p9_debug_level = option;
#endif
break;
- case Opt_port:
- v9ses->port = option;
- break;
case Opt_msize:
v9ses->maxdata = option;
break;
- case Opt_uid:
- v9ses->uid = option;
+ case Opt_dfltuid:
+ v9ses->dfltuid = option;
break;
- case Opt_gid:
- v9ses->gid = option;
+ case Opt_dfltgid:
+ v9ses->dfltgid = option;
break;
case Opt_afid:
v9ses->afid = option;
break;
- case Opt_rfdno:
- v9ses->rfdno = option;
- break;
- case Opt_wfdno:
- v9ses->wfdno = option;
- break;
- case Opt_tcp:
- v9ses->proto = PROTO_TCP;
- break;
- case Opt_unix:
- v9ses->proto = PROTO_UNIX;
- break;
- case Opt_pci:
- v9ses->proto = PROTO_PCI;
- break;
- case Opt_fd:
- v9ses->proto = PROTO_FD;
+ case Opt_trans:
+ v9ses->trans = v9fs_match_trans(&args[0]);
break;
case Opt_uname:
- match_strcpy(v9ses->name, &args[0]);
+ match_strcpy(v9ses->uname, &args[0]);
break;
case Opt_remotename:
- match_strcpy(v9ses->remotename, &args[0]);
+ match_strcpy(v9ses->aname, &args[0]);
break;
case Opt_legacy:
- v9ses->extended = 0;
+ v9ses->flags &= ~V9FS_EXTENDED;
break;
case Opt_nodevmap:
v9ses->nodev = 1;
@@ -183,10 +149,28 @@ static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses)
case Opt_cache_loose:
v9ses->cache = CACHE_LOOSE;
break;
+
+ case Opt_access:
+ s = match_strdup(&args[0]);
+ v9ses->flags &= ~V9FS_ACCESS_MASK;
+ if (strcmp(s, "user") == 0)
+ v9ses->flags |= V9FS_ACCESS_USER;
+ else if (strcmp(s, "any") == 0)
+ v9ses->flags |= V9FS_ACCESS_ANY;
+ else {
+ v9ses->flags |= V9FS_ACCESS_SINGLE;
+ v9ses->uid = simple_strtol(s, &e, 10);
+ if (*e != '\0')
+ v9ses->uid = ~0;
+ }
+ kfree(s);
+ break;
+
default:
continue;
}
}
+ kfree(options);
}
/**
@@ -201,56 +185,46 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
const char *dev_name, char *data)
{
int retval = -EINVAL;
- struct p9_transport *trans;
+ struct p9_trans *trans = NULL;
struct p9_fid *fid;
- v9ses->name = __getname();
- if (!v9ses->name)
+ v9ses->uname = __getname();
+ if (!v9ses->uname)
return ERR_PTR(-ENOMEM);
- v9ses->remotename = __getname();
- if (!v9ses->remotename) {
- __putname(v9ses->name);
+ v9ses->aname = __getname();
+ if (!v9ses->aname) {
+ __putname(v9ses->uname);
return ERR_PTR(-ENOMEM);
}
- strcpy(v9ses->name, V9FS_DEFUSER);
- strcpy(v9ses->remotename, V9FS_DEFANAME);
-
- v9fs_parse_options(data, v9ses);
-
- switch (v9ses->proto) {
- case PROTO_TCP:
- trans = p9_trans_create_tcp(dev_name, v9ses->port);
- break;
- case PROTO_UNIX:
- trans = p9_trans_create_unix(dev_name);
- *v9ses->remotename = 0;
- break;
- case PROTO_FD:
- trans = p9_trans_create_fd(v9ses->rfdno, v9ses->wfdno);
- *v9ses->remotename = 0;
- break;
-#ifdef CONFIG_PCI_9P
- case PROTO_PCI:
- trans = p9pci_trans_create();
- *v9ses->remotename = 0;
- break;
-#endif
- default:
- printk(KERN_ERR "v9fs: Bad mount protocol %d\n", v9ses->proto);
- retval = -ENOPROTOOPT;
+ v9ses->flags = V9FS_EXTENDED | V9FS_ACCESS_USER;
+ strcpy(v9ses->uname, V9FS_DEFUSER);
+ strcpy(v9ses->aname, V9FS_DEFANAME);
+ v9ses->uid = ~0;
+ v9ses->dfltuid = V9FS_DEFUID;
+ v9ses->dfltgid = V9FS_DEFGID;
+ v9ses->options = kstrdup(data, GFP_KERNEL);
+ v9fs_parse_options(v9ses);
+
+ if (v9ses->trans == NULL) {
+ retval = -EPROTONOSUPPORT;
+ P9_DPRINTK(P9_DEBUG_ERROR,
+ "No transport defined or default transport\n");
goto error;
- };
+ }
+ trans = v9ses->trans->create(dev_name, v9ses->options);
if (IS_ERR(trans)) {
retval = PTR_ERR(trans);
trans = NULL;
goto error;
}
+ if ((v9ses->maxdata+P9_IOHDRSZ) > v9ses->trans->maxsize)
+ v9ses->maxdata = v9ses->trans->maxsize-P9_IOHDRSZ;
- v9ses->clnt = p9_client_create(trans, v9ses->maxdata + P9_IOHDRSZ,
- v9ses->extended);
+ v9ses->clnt = p9_client_create(trans, v9ses->maxdata+P9_IOHDRSZ,
+ v9fs_extended(v9ses));
if (IS_ERR(v9ses->clnt)) {
retval = PTR_ERR(v9ses->clnt);
@@ -259,8 +233,20 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
goto error;
}
- fid = p9_client_attach(v9ses->clnt, NULL, v9ses->name,
- v9ses->remotename);
+ if (!v9ses->clnt->dotu)
+ v9ses->flags &= ~V9FS_EXTENDED;
+
+ /* for legacy mode, fall back to V9FS_ACCESS_ANY */
+ if (!v9fs_extended(v9ses) &&
+ ((v9ses->flags&V9FS_ACCESS_MASK) == V9FS_ACCESS_USER)) {
+
+ v9ses->flags &= ~V9FS_ACCESS_MASK;
+ v9ses->flags |= V9FS_ACCESS_ANY;
+ v9ses->uid = ~0;
+ }
+
+ fid = p9_client_attach(v9ses->clnt, NULL, v9ses->uname, ~0,
+ v9ses->aname);
if (IS_ERR(fid)) {
retval = PTR_ERR(fid);
fid = NULL;
@@ -268,6 +254,11 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
goto error;
}
+ if ((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_SINGLE)
+ fid->uid = v9ses->uid;
+ else
+ fid->uid = ~0;
+
return fid;
error:
@@ -288,8 +279,9 @@ void v9fs_session_close(struct v9fs_session_info *v9ses)
v9ses->clnt = NULL;
}
- __putname(v9ses->name);
- __putname(v9ses->remotename);
+ __putname(v9ses->uname);
+ __putname(v9ses->aname);
+ kfree(v9ses->options);
}
/**
@@ -311,7 +303,7 @@ extern int v9fs_error_init(void);
static int __init init_v9fs(void)
{
printk(KERN_INFO "Installing v9fs 9p2000 file system support\n");
-
+ /* TODO: Setup list of registered trasnport modules */
return register_filesystem(&v9fs_fs_type);
}
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h
index abc4b1668ace..db4b4193f2e2 100644
--- a/fs/9p/v9fs.h
+++ b/fs/9p/v9fs.h
@@ -29,31 +29,30 @@
struct v9fs_session_info {
/* options */
unsigned int maxdata;
- unsigned char extended; /* set to 1 if we are using UNIX extensions */
+ unsigned char flags; /* session flags */
unsigned char nodev; /* set to 1 if no disable device mapping */
- unsigned short port; /* port to connect to */
unsigned short debug; /* debug level */
- unsigned short proto; /* protocol to use */
unsigned int afid; /* authentication fid */
- unsigned int rfdno; /* read file descriptor number */
- unsigned int wfdno; /* write file descriptor number */
unsigned int cache; /* cache mode */
- char *name; /* user name to mount as */
- char *remotename; /* name of remote hierarchy being mounted */
- unsigned int uid; /* default uid/muid for legacy support */
- unsigned int gid; /* default gid for legacy support */
-
+ char *options; /* copy of mount options */
+ char *uname; /* user name to mount as */
+ char *aname; /* name of remote hierarchy being mounted */
+ unsigned int dfltuid; /* default uid/muid for legacy support */
+ unsigned int dfltgid; /* default gid for legacy support */
+ u32 uid; /* if ACCESS_SINGLE, the uid that has access */
+ struct p9_trans_module *trans; /* 9p transport */
struct p9_client *clnt; /* 9p client */
struct dentry *debugfs_dir;
};
-/* possible values of ->proto */
+/* session flags */
enum {
- PROTO_TCP,
- PROTO_UNIX,
- PROTO_FD,
- PROTO_PCI,
+ V9FS_EXTENDED = 0x01, /* 9P2000.u */
+ V9FS_ACCESS_MASK = 0x06, /* access mask */
+ V9FS_ACCESS_SINGLE = 0x02, /* only one user can access the files */
+ V9FS_ACCESS_USER = 0x04, /* attache per user */
+ V9FS_ACCESS_ANY = 0x06, /* use the same attach for all users */
};
/* possible values of ->cache */
@@ -73,11 +72,18 @@ void v9fs_session_cancel(struct v9fs_session_info *v9ses);
#define V9FS_MAGIC 0x01021997
/* other default globals */
-#define V9FS_PORT 564
+#define V9FS_PORT 564
#define V9FS_DEFUSER "nobody"
#define V9FS_DEFANAME ""
+#define V9FS_DEFUID (-2)
+#define V9FS_DEFGID (-2)
static inline struct v9fs_session_info *v9fs_inode2v9ses(struct inode *inode)
{
return (inode->i_sb->s_fs_info);
}
+
+static inline int v9fs_extended(struct v9fs_session_info *v9ses)
+{
+ return v9ses->flags & V9FS_EXTENDED;
+}
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index 2a40c2946d0a..ba4b1caa9c43 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -105,7 +105,7 @@ static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl)
P9_DPRINTK(P9_DEBUG_VFS, "filp: %p lock: %p\n", filp, fl);
/* No mandatory locks */
- if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
+ if (__mandatory_lock(inode))
return -ENOLCK;
if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) {
@@ -162,15 +162,17 @@ v9fs_file_write(struct file *filp, const char __user * data,
fid = filp->private_data;
ret = p9_client_uwrite(fid, data, *offset, count);
- if (ret > 0)
+ if (ret > 0) {
+ invalidate_inode_pages2_range(inode->i_mapping, *offset,
+ *offset+ret);
*offset += ret;
+ }
if (*offset > inode->i_size) {
inode->i_size = *offset;
inode->i_blocks = (inode->i_size + 512 - 1) >> 9;
}
- invalidate_inode_pages2(inode->i_mapping);
return ret;
}
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index e5c45eed58a9..23581bcb599b 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -59,7 +59,7 @@ static int unixmode2p9mode(struct v9fs_session_info *v9ses, int mode)
res = mode & 0777;
if (S_ISDIR(mode))
res |= P9_DMDIR;
- if (v9ses->extended) {
+ if (v9fs_extended(v9ses)) {
if (S_ISLNK(mode))
res |= P9_DMSYMLINK;
if (v9ses->nodev == 0) {
@@ -99,21 +99,21 @@ static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode)
if ((mode & P9_DMDIR) == P9_DMDIR)
res |= S_IFDIR;
- else if ((mode & P9_DMSYMLINK) && (v9ses->extended))
+ else if ((mode & P9_DMSYMLINK) && (v9fs_extended(v9ses)))
res |= S_IFLNK;
- else if ((mode & P9_DMSOCKET) && (v9ses->extended)
+ else if ((mode & P9_DMSOCKET) && (v9fs_extended(v9ses))
&& (v9ses->nodev == 0))
res |= S_IFSOCK;
- else if ((mode & P9_DMNAMEDPIPE) && (v9ses->extended)
+ else if ((mode & P9_DMNAMEDPIPE) && (v9fs_extended(v9ses))
&& (v9ses->nodev == 0))
res |= S_IFIFO;
- else if ((mode & P9_DMDEVICE) && (v9ses->extended)
+ else if ((mode & P9_DMDEVICE) && (v9fs_extended(v9ses))
&& (v9ses->nodev == 0))
res |= S_IFBLK;
else
res |= S_IFREG;
- if (v9ses->extended) {
+ if (v9fs_extended(v9ses)) {
if ((mode & P9_DMSETUID) == P9_DMSETUID)
res |= S_ISUID;
@@ -214,7 +214,7 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
case S_IFBLK:
case S_IFCHR:
case S_IFSOCK:
- if(!v9ses->extended) {
+ if (!v9fs_extended(v9ses)) {
P9_DPRINTK(P9_DEBUG_ERROR,
"special files without extended mode\n");
return ERR_PTR(-EINVAL);
@@ -227,7 +227,7 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
inode->i_fop = &v9fs_file_operations;
break;
case S_IFLNK:
- if(!v9ses->extended) {
+ if (!v9fs_extended(v9ses)) {
P9_DPRINTK(P9_DEBUG_ERROR,
"extended modes used w/o 9P2000.u\n");
return ERR_PTR(-EINVAL);
@@ -236,7 +236,7 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
break;
case S_IFDIR:
inc_nlink(inode);
- if(v9ses->extended)
+ if (v9fs_extended(v9ses))
inode->i_op = &v9fs_dir_inode_operations_ext;
else
inode->i_op = &v9fs_dir_inode_operations;
@@ -364,7 +364,7 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir)
file_inode = file->d_inode;
v9ses = v9fs_inode2v9ses(file_inode);
v9fid = v9fs_fid_clone(file);
- if(IS_ERR(v9fid))
+ if (IS_ERR(v9fid))
return PTR_ERR(v9fid);
return p9_client_remove(v9fid);
@@ -398,7 +398,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
fid = NULL;
name = (char *) dentry->d_name.name;
dfid = v9fs_fid_clone(dentry->d_parent);
- if(IS_ERR(dfid)) {
+ if (IS_ERR(dfid)) {
err = PTR_ERR(dfid);
dfid = NULL;
goto error;
@@ -432,7 +432,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
goto error;
}
- if(v9ses->cache)
+ if (v9ses->cache)
dentry->d_op = &v9fs_cached_dentry_operations;
else
dentry->d_op = &v9fs_dentry_operations;
@@ -593,7 +593,7 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
if (result < 0)
goto error;
- if((fid->qid.version)&&(v9ses->cache))
+ if ((fid->qid.version) && (v9ses->cache))
dentry->d_op = &v9fs_cached_dentry_operations;
else
dentry->d_op = &v9fs_dentry_operations;
@@ -658,17 +658,17 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
old_inode = old_dentry->d_inode;
v9ses = v9fs_inode2v9ses(old_inode);
oldfid = v9fs_fid_lookup(old_dentry);
- if(IS_ERR(oldfid))
+ if (IS_ERR(oldfid))
return PTR_ERR(oldfid);
olddirfid = v9fs_fid_clone(old_dentry->d_parent);
- if(IS_ERR(olddirfid)) {
+ if (IS_ERR(olddirfid)) {
retval = PTR_ERR(olddirfid);
goto done;
}
newdirfid = v9fs_fid_clone(new_dentry->d_parent);
- if(IS_ERR(newdirfid)) {
+ if (IS_ERR(newdirfid)) {
retval = PTR_ERR(newdirfid);
goto clunk_olddir;
}
@@ -682,15 +682,15 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
}
v9fs_blank_wstat(&wstat);
- wstat.muid = v9ses->name;
+ wstat.muid = v9ses->uname;
wstat.name = (char *) new_dentry->d_name.name;
retval = p9_client_wstat(oldfid, &wstat);
clunk_newdir:
- p9_client_clunk(olddirfid);
+ p9_client_clunk(newdirfid);
clunk_olddir:
- p9_client_clunk(newdirfid);
+ p9_client_clunk(olddirfid);
done:
return retval;
@@ -768,7 +768,7 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
if (iattr->ia_valid & ATTR_SIZE)
wstat.length = iattr->ia_size;
- if (v9ses->extended) {
+ if (v9fs_extended(v9ses)) {
if (iattr->ia_valid & ATTR_UID)
wstat.n_uid = iattr->ia_uid;
@@ -805,10 +805,10 @@ v9fs_stat2inode(struct p9_stat *stat, struct inode *inode,
inode->i_mtime.tv_sec = stat->mtime;
inode->i_ctime.tv_sec = stat->mtime;
- inode->i_uid = v9ses->uid;
- inode->i_gid = v9ses->gid;
+ inode->i_uid = v9ses->dfltuid;
+ inode->i_gid = v9ses->dfltgid;
- if (v9ses->extended) {
+ if (v9fs_extended(v9ses)) {
inode->i_uid = stat->n_uid;
inode->i_gid = stat->n_gid;
}
@@ -887,10 +887,10 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
retval = -EPERM;
v9ses = v9fs_inode2v9ses(dentry->d_inode);
fid = v9fs_fid_lookup(dentry);
- if(IS_ERR(fid))
+ if (IS_ERR(fid))
return PTR_ERR(fid);
- if (!v9ses->extended)
+ if (!v9fs_extended(v9ses))
return -EBADF;
st = p9_client_stat(fid);
@@ -1011,7 +1011,7 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
struct p9_fid *fid;
v9ses = v9fs_inode2v9ses(dir);
- if (!v9ses->extended) {
+ if (!v9fs_extended(v9ses)) {
P9_DPRINTK(P9_DEBUG_ERROR, "not extended\n");
return -EPERM;
}
@@ -1070,7 +1070,7 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
old_dentry->d_name.name);
oldfid = v9fs_fid_clone(old_dentry);
- if(IS_ERR(oldfid))
+ if (IS_ERR(oldfid))
return PTR_ERR(oldfid);
name = __getname();
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index ba904371218b..678c02f1ae23 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -119,6 +119,7 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
P9_DPRINTK(P9_DEBUG_VFS, " \n");
+ st = NULL;
v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL);
if (!v9ses)
return -ENOMEM;
@@ -164,10 +165,12 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
root->d_inode->i_ino = v9fs_qid2ino(&st->qid);
v9fs_stat2inode(st, root->d_inode, sb);
v9fs_fid_add(root, fid);
+ kfree(st);
return simple_set_mnt(mnt, sb);
error:
+ kfree(st);
if (fid)
p9_client_clunk(fid);
@@ -216,24 +219,7 @@ static int v9fs_show_options(struct seq_file *m, struct vfsmount *mnt)
{
struct v9fs_session_info *v9ses = mnt->mnt_sb->s_fs_info;
- if (v9ses->debug != 0)
- seq_printf(m, ",debug=%x", v9ses->debug);
- if (v9ses->port != V9FS_PORT)
- seq_printf(m, ",port=%u", v9ses->port);
- if (v9ses->maxdata != 9000)
- seq_printf(m, ",msize=%u", v9ses->maxdata);
- if (v9ses->afid != ~0)
- seq_printf(m, ",afid=%u", v9ses->afid);
- if (v9ses->proto == PROTO_UNIX)
- seq_puts(m, ",proto=unix");
- if (v9ses->extended == 0)
- seq_puts(m, ",noextend");
- if (v9ses->nodev == 1)
- seq_puts(m, ",nodevmap");
- seq_printf(m, ",name=%s", v9ses->name);
- seq_printf(m, ",aname=%s", v9ses->remotename);
- seq_printf(m, ",uid=%u", v9ses->uid);
- seq_printf(m, ",gid=%u", v9ses->gid);
+ seq_printf(m, "%s", v9ses->options);
return 0;
}
diff --git a/fs/Kconfig b/fs/Kconfig
index 815d201d8600..429a00228507 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -140,6 +140,7 @@ config EXT4DEV_FS
tristate "Ext4dev/ext4 extended fs support development (EXPERIMENTAL)"
depends on EXPERIMENTAL
select JBD2
+ select CRC16
help
Ext4dev is a predecessor filesystem of the next generation
extended fs ext4, based on ext3 filesystem code. It will be
@@ -219,7 +220,7 @@ config JBD
config JBD_DEBUG
bool "JBD (ext3) debugging support"
- depends on JBD
+ depends on JBD && DEBUG_FS
help
If you are using the ext3 journaled file system (or potentially any
other file system/device using JBD), this option allows you to
@@ -228,10 +229,10 @@ config JBD_DEBUG
debugging output will be turned off.
If you select Y here, then you will be able to turn on debugging
- with "echo N > /proc/sys/fs/jbd-debug", where N is a number between
- 1 and 5, the higher the number, the more debugging output is
- generated. To turn debugging off again, do
- "echo 0 > /proc/sys/fs/jbd-debug".
+ with "echo N > /sys/kernel/debug/jbd/jbd-debug", where N is a
+ number between 1 and 5, the higher the number, the more debugging
+ output is generated. To turn debugging off again, do
+ "echo 0 > /sys/kernel/debug/jbd/jbd-debug".
config JBD2
tristate
@@ -503,7 +504,7 @@ config INOTIFY
including multiple file events, one-shot support, and unmount
notification.
- For more information, see Documentation/filesystems/inotify.txt
+ For more information, see <file:Documentation/filesystems/inotify.txt>
If unsure, say Y.
@@ -517,7 +518,7 @@ config INOTIFY_USER
directories via a single open fd. Events are read from the file
descriptor, which is also select()- and poll()-able.
- For more information, see Documentation/filesystems/inotify.txt
+ For more information, see <file:Documentation/filesystems/inotify.txt>
If unsure, say Y.
@@ -534,6 +535,24 @@ config QUOTA
with the quota tools. Probably the quota support is only useful for
multi user systems. If unsure, say N.
+config QUOTA_NETLINK_INTERFACE
+ bool "Report quota messages through netlink interface"
+ depends on QUOTA && NET
+ help
+ If you say Y here, quota warnings (about exceeding softlimit, reaching
+ hardlimit, etc.) will be reported through netlink interface. If unsure,
+ say Y.
+
+config PRINT_QUOTA_WARNING
+ bool "Print quota warnings to console (OBSOLETE)"
+ depends on QUOTA
+ default y
+ help
+ If you say Y here, quota warnings (about exceeding softlimit, reaching
+ hardlimit, etc.) will be printed to the process' controlling terminal.
+ Note that this behavior is currently deprecated and may go away in
+ future. Please use notification via netlink socket instead.
+
config QFMT_V1
tristate "Old quota format support"
depends on QUOTA
@@ -555,7 +574,7 @@ config QUOTACTL
default y
config DNOTIFY
- bool "Dnotify support" if EMBEDDED
+ bool "Dnotify support"
default y
help
Dnotify is a directory-based per-fd file change notification system
@@ -563,7 +582,7 @@ config DNOTIFY
superior alternatives, but some applications may still rely on
dnotify.
- Because of this, if unsure, say Y.
+ If unsure, say Y.
config AUTOFS_FS
tristate "Kernel automounter support"
@@ -999,20 +1018,6 @@ config HUGETLBFS
config HUGETLB_PAGE
def_bool HUGETLBFS
-config RAMFS
- bool
- default y
- ---help---
- Ramfs is a file system which keeps all files in RAM. It allows
- read and write access.
-
- It is more of an programming example than a useable file system. If
- you need a file system which lives in RAM with limit checking use
- tmpfs.
-
- To compile this as a module, choose M here: the module will be called
- ramfs.
-
config CONFIGFS_FS
tristate "Userspace-driven configuration filesystem (EXPERIMENTAL)"
depends on SYSFS && EXPERIMENTAL
@@ -1084,7 +1089,7 @@ config ECRYPT_FS
depends on EXPERIMENTAL && KEYS && CRYPTO && NET
help
Encrypted filesystem that operates on the VFS layer. See
- <file:Documentation/ecryptfs.txt> to learn more about
+ <file:Documentation/filesystems/ecryptfs.txt> to learn more about
eCryptfs. Userspace components are required and can be
obtained from <http://ecryptfs.sf.net>.
@@ -1543,8 +1548,20 @@ config UFS_DEBUG
endmenu
-menu "Network File Systems"
+menuconfig NETWORK_FILESYSTEMS
+ bool "Network File Systems"
+ default y
depends on NET
+ ---help---
+ Say Y here to get to see options for network filesystems and
+ filesystem-related networking code, such as NFS daemon and
+ RPCSEC security modules.
+ This option alone does not add any kernel code.
+
+ If you say N, all options in this submenu will be skipped and
+ disabled; if unsure, say Y here.
+
+if NETWORK_FILESYSTEMS
config NFS_FS
tristate "NFS file system support"
@@ -1990,7 +2007,7 @@ config CIFS_EXPERIMENTAL
config CIFS_UPCALL
bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)"
depends on CIFS_EXPERIMENTAL
- depends on CONNECTOR
+ depends on KEYS
help
Enables an upcall mechanism for CIFS which will be used to contact
userspace helper utilities to provide SPNEGO packaged Kerberos
@@ -2090,7 +2107,7 @@ config 9P_FS
If unsure, say N.
-endmenu
+endif # NETWORK_FILESYSTEMS
if BLOCK
menu "Partition Types"
diff --git a/fs/Makefile b/fs/Makefile
index 720c29d57a62..500cf15cdb4b 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -72,7 +72,7 @@ obj-$(CONFIG_JBD) += jbd/
obj-$(CONFIG_JBD2) += jbd2/
obj-$(CONFIG_EXT2_FS) += ext2/
obj-$(CONFIG_CRAMFS) += cramfs/
-obj-$(CONFIG_RAMFS) += ramfs/
+obj-y += ramfs/
obj-$(CONFIG_HUGETLBFS) += hugetlbfs/
obj-$(CONFIG_CODA_FS) += coda/
obj-$(CONFIG_MINIX_FS) += minix/
diff --git a/fs/adfs/inode.c b/fs/adfs/inode.c
index 7e7a04be1278..e647200262a2 100644
--- a/fs/adfs/inode.c
+++ b/fs/adfs/inode.c
@@ -61,10 +61,14 @@ static int adfs_readpage(struct file *file, struct page *page)
return block_read_full_page(page, adfs_get_block);
}
-static int adfs_prepare_write(struct file *file, struct page *page, unsigned int from, unsigned int to)
+static int adfs_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
{
- return cont_prepare_write(page, from, to, adfs_get_block,
- &ADFS_I(page->mapping->host)->mmu_private);
+ *pagep = NULL;
+ return cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
+ adfs_get_block,
+ &ADFS_I(mapping->host)->mmu_private);
}
static sector_t _adfs_bmap(struct address_space *mapping, sector_t block)
@@ -76,8 +80,8 @@ static const struct address_space_operations adfs_aops = {
.readpage = adfs_readpage,
.writepage = adfs_writepage,
.sync_page = block_sync_page,
- .prepare_write = adfs_prepare_write,
- .commit_write = generic_commit_write,
+ .write_begin = adfs_write_begin,
+ .write_end = generic_write_end,
.bmap = _adfs_bmap
};
diff --git a/fs/adfs/super.c b/fs/adfs/super.c
index 1c9fd3029496..b36695ae5c2e 100644
--- a/fs/adfs/super.c
+++ b/fs/adfs/super.c
@@ -228,7 +228,7 @@ static void adfs_destroy_inode(struct inode *inode)
kmem_cache_free(adfs_inode_cachep, ADFS_I(inode));
}
-static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
+static void init_once(struct kmem_cache *cachep, void *foo)
{
struct adfs_inode_info *ei = (struct adfs_inode_info *) foo;
diff --git a/fs/affs/bitmap.c b/fs/affs/bitmap.c
index b330009fe42d..c4a5ad09ddf2 100644
--- a/fs/affs/bitmap.c
+++ b/fs/affs/bitmap.c
@@ -11,7 +11,7 @@
/* This is, of course, shamelessly stolen from fs/minix */
-static int nibblemap[] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 };
+static const int nibblemap[] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 };
static u32
affs_count_free_bits(u32 blocksize, const void *data)
diff --git a/fs/affs/file.c b/fs/affs/file.c
index c314a35f0918..6e0c9399200e 100644
--- a/fs/affs/file.c
+++ b/fs/affs/file.c
@@ -395,25 +395,33 @@ static int affs_writepage(struct page *page, struct writeback_control *wbc)
{
return block_write_full_page(page, affs_get_block, wbc);
}
+
static int affs_readpage(struct file *file, struct page *page)
{
return block_read_full_page(page, affs_get_block);
}
-static int affs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
+
+static int affs_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
{
- return cont_prepare_write(page, from, to, affs_get_block,
- &AFFS_I(page->mapping->host)->mmu_private);
+ *pagep = NULL;
+ return cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
+ affs_get_block,
+ &AFFS_I(mapping->host)->mmu_private);
}
+
static sector_t _affs_bmap(struct address_space *mapping, sector_t block)
{
return generic_block_bmap(mapping,block,affs_get_block);
}
+
const struct address_space_operations affs_aops = {
.readpage = affs_readpage,
.writepage = affs_writepage,
.sync_page = block_sync_page,
- .prepare_write = affs_prepare_write,
- .commit_write = generic_commit_write,
+ .write_begin = affs_write_begin,
+ .write_end = generic_write_end,
.bmap = _affs_bmap
};
@@ -603,54 +611,65 @@ affs_readpage_ofs(struct file *file, struct page *page)
return err;
}
-static int affs_prepare_write_ofs(struct file *file, struct page *page, unsigned from, unsigned to)
+static int affs_write_begin_ofs(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
{
- struct inode *inode = page->mapping->host;
- u32 size, offset;
- u32 tmp;
+ struct inode *inode = mapping->host;
+ struct page *page;
+ pgoff_t index;
int err = 0;
- pr_debug("AFFS: prepare_write(%u, %ld, %d, %d)\n", (u32)inode->i_ino, page->index, from, to);
- offset = page->index << PAGE_CACHE_SHIFT;
- if (offset + from > AFFS_I(inode)->mmu_private) {
- err = affs_extent_file_ofs(inode, offset + from);
+ pr_debug("AFFS: write_begin(%u, %llu, %llu)\n", (u32)inode->i_ino, (unsigned long long)pos, (unsigned long long)pos + len);
+ if (pos > AFFS_I(inode)->mmu_private) {
+ /* XXX: this probably leaves a too-big i_size in case of
+ * failure. Should really be updating i_size at write_end time
+ */
+ err = affs_extent_file_ofs(inode, pos);
if (err)
return err;
}
- size = inode->i_size;
+
+ index = pos >> PAGE_CACHE_SHIFT;
+ page = __grab_cache_page(mapping, index);
+ if (!page)
+ return -ENOMEM;
+ *pagep = page;
if (PageUptodate(page))
return 0;
- if (from) {
- err = affs_do_readpage_ofs(file, page, 0, from);
- if (err)
- return err;
- }
- if (to < PAGE_CACHE_SIZE) {
- zero_user_page(page, to, PAGE_CACHE_SIZE - to, KM_USER0);
- if (size > offset + to) {
- if (size < offset + PAGE_CACHE_SIZE)
- tmp = size & ~PAGE_CACHE_MASK;
- else
- tmp = PAGE_CACHE_SIZE;
- err = affs_do_readpage_ofs(file, page, to, tmp);
- }
+ /* XXX: inefficient but safe in the face of short writes */
+ err = affs_do_readpage_ofs(file, page, 0, PAGE_CACHE_SIZE);
+ if (err) {
+ unlock_page(page);
+ page_cache_release(page);
}
return err;
}
-static int affs_commit_write_ofs(struct file *file, struct page *page, unsigned from, unsigned to)
+static int affs_write_end_ofs(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata)
{
- struct inode *inode = page->mapping->host;
+ struct inode *inode = mapping->host;
struct super_block *sb = inode->i_sb;
struct buffer_head *bh, *prev_bh;
char *data;
u32 bidx, boff, bsize;
+ unsigned from, to;
u32 tmp;
int written;
- pr_debug("AFFS: commit_write(%u, %ld, %d, %d)\n", (u32)inode->i_ino, page->index, from, to);
+ from = pos & (PAGE_CACHE_SIZE - 1);
+ to = pos + len;
+ /*
+ * XXX: not sure if this can handle short copies (len < copied), but
+ * we don't have to, because the page should always be uptodate here,
+ * due to write_begin.
+ */
+
+ pr_debug("AFFS: write_begin(%u, %llu, %llu)\n", (u32)inode->i_ino, (unsigned long long)pos, (unsigned long long)pos + len);
bsize = AFFS_SB(sb)->s_data_blksize;
data = page_address(page);
@@ -748,6 +767,9 @@ done:
if (tmp > inode->i_size)
inode->i_size = AFFS_I(inode)->mmu_private = tmp;
+ unlock_page(page);
+ page_cache_release(page);
+
return written;
out:
@@ -761,8 +783,8 @@ const struct address_space_operations affs_aops_ofs = {
.readpage = affs_readpage_ofs,
//.writepage = affs_writepage_ofs,
//.sync_page = affs_sync_page_ofs,
- .prepare_write = affs_prepare_write_ofs,
- .commit_write = affs_commit_write_ofs
+ .write_begin = affs_write_begin_ofs,
+ .write_end = affs_write_end_ofs
};
/* Free any preallocated blocks. */
@@ -805,18 +827,13 @@ affs_truncate(struct inode *inode)
if (inode->i_size > AFFS_I(inode)->mmu_private) {
struct address_space *mapping = inode->i_mapping;
struct page *page;
- u32 size = inode->i_size - 1;
+ void *fsdata;
+ u32 size = inode->i_size;
int res;
- page = grab_cache_page(mapping, size >> PAGE_CACHE_SHIFT);
- if (!page)
- return;
- size = (size & (PAGE_CACHE_SIZE - 1)) + 1;
- res = mapping->a_ops->prepare_write(NULL, page, size, size);
+ res = mapping->a_ops->write_begin(NULL, mapping, size, 0, 0, &page, &fsdata);
if (!res)
- res = mapping->a_ops->commit_write(NULL, page, size, size);
- unlock_page(page);
- page_cache_release(page);
+ res = mapping->a_ops->write_end(NULL, mapping, size, 0, 0, page, fsdata);
mark_inode_dirty(inode);
return;
} else if (inode->i_size == AFFS_I(inode)->mmu_private)
diff --git a/fs/affs/super.c b/fs/affs/super.c
index c80191ae2059..b53e5d0ec65c 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -84,7 +84,7 @@ static void affs_destroy_inode(struct inode *inode)
kmem_cache_free(affs_inode_cachep, AFFS_I(inode));
}
-static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
+static void init_once(struct kmem_cache *cachep, void *foo)
{
struct affs_inode_info *ei = (struct affs_inode_info *) foo;
diff --git a/fs/afs/callback.c b/fs/afs/callback.c
index b8243945818d..a78d5b236bb1 100644
--- a/fs/afs/callback.c
+++ b/fs/afs/callback.c
@@ -20,7 +20,9 @@
#include <linux/sched.h>
#include "internal.h"
+#if 0
unsigned afs_vnode_update_timeout = 10;
+#endif /* 0 */
#define afs_breakring_space(server) \
CIRC_SPACE((server)->cb_break_head, (server)->cb_break_tail, \
diff --git a/fs/afs/cell.c b/fs/afs/cell.c
index 175a567db78c..970d38f30565 100644
--- a/fs/afs/cell.c
+++ b/fs/afs/cell.c
@@ -33,6 +33,7 @@ static struct afs_cell *afs_cell_root;
static struct afs_cell *afs_cell_alloc(const char *name, char *vllist)
{
struct afs_cell *cell;
+ struct key *key;
size_t namelen;
char keyname[4 + AFS_MAXCELLNAME + 1], *cp, *dp, *next;
int ret;
@@ -89,20 +90,14 @@ static struct afs_cell *afs_cell_alloc(const char *name, char *vllist)
do {
*dp++ = toupper(*cp);
} while (*cp++);
- cell->anonymous_key = key_alloc(&key_type_rxrpc, keyname, 0, 0, current,
- KEY_POS_SEARCH, KEY_ALLOC_NOT_IN_QUOTA);
- if (IS_ERR(cell->anonymous_key)) {
- _debug("no key");
- ret = PTR_ERR(cell->anonymous_key);
- goto error;
- }
- ret = key_instantiate_and_link(cell->anonymous_key, NULL, 0,
- NULL, NULL);
- if (ret < 0) {
- _debug("instantiate failed");
+ key = rxrpc_get_null_key(keyname);
+ if (IS_ERR(key)) {
+ _debug("no key");
+ ret = PTR_ERR(key);
goto error;
}
+ cell->anonymous_key = key;
_debug("anon key %p{%x}",
cell->anonymous_key, key_serial(cell->anonymous_key));
@@ -265,6 +260,7 @@ struct afs_cell *afs_cell_lookup(const char *name, unsigned namesz)
return cell;
}
+#if 0
/*
* try and get a cell record
*/
@@ -280,6 +276,7 @@ struct afs_cell *afs_get_cell_maybe(struct afs_cell *cell)
write_unlock(&afs_cells_lock);
return cell;
}
+#endif /* 0 */
/*
* destroy a cell record
diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c
index d5b2ad6575bc..47b71c8947f9 100644
--- a/fs/afs/cmservice.c
+++ b/fs/afs/cmservice.c
@@ -16,7 +16,9 @@
#include "internal.h"
#include "afs_cm.h"
+#if 0
struct workqueue_struct *afs_cm_workqueue;
+#endif /* 0 */
static int afs_deliver_cb_init_call_back_state(struct afs_call *,
struct sk_buff *, bool);
diff --git a/fs/afs/flock.c b/fs/afs/flock.c
index af6952e39a18..210acafe4a9b 100644
--- a/fs/afs/flock.c
+++ b/fs/afs/flock.c
@@ -524,8 +524,7 @@ int afs_lock(struct file *file, int cmd, struct file_lock *fl)
(long long) fl->fl_start, (long long) fl->fl_end);
/* AFS doesn't support mandatory locks */
- if ((vnode->vfs_inode.i_mode & (S_ISGID | S_IXGRP)) == S_ISGID &&
- fl->fl_type != F_UNLCK)
+ if (__mandatory_lock(&vnode->vfs_inode) && fl->fl_type != F_UNLCK)
return -ENOLCK;
if (IS_GETLK(cmd))
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index 6306438f331f..5ca3625cd39e 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -570,7 +570,6 @@ extern int afs_abort_to_error(u32);
*/
extern const struct inode_operations afs_mntpt_inode_operations;
extern const struct file_operations afs_mntpt_file_operations;
-extern unsigned long afs_mntpt_expiry_timeout;
extern int afs_mntpt_check_symlink(struct afs_vnode *, struct key *);
extern void afs_mntpt_kill_timer(void);
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c
index 6f8c96fb29eb..5ce43b63c60e 100644
--- a/fs/afs/mntpt.c
+++ b/fs/afs/mntpt.c
@@ -42,7 +42,7 @@ const struct inode_operations afs_mntpt_inode_operations = {
static LIST_HEAD(afs_vfsmounts);
static DECLARE_DELAYED_WORK(afs_mntpt_expiry_timer, afs_mntpt_expiry_timed_out);
-unsigned long afs_mntpt_expiry_timeout = 10 * 60;
+static unsigned long afs_mntpt_expiry_timeout = 10 * 60;
/*
* check a symbolic link to see whether it actually encodes a mountpoint
diff --git a/fs/afs/proc.c b/fs/afs/proc.c
index 6edb56683b9a..846c7615ac9e 100644
--- a/fs/afs/proc.c
+++ b/fs/afs/proc.c
@@ -513,7 +513,7 @@ static void afs_proc_cell_volumes_stop(struct seq_file *p, void *v)
up_read(&cell->vl_sem);
}
-const char afs_vlocation_states[][4] = {
+static const char afs_vlocation_states[][4] = {
[AFS_VL_NEW] = "New",
[AFS_VL_CREATING] = "Crt",
[AFS_VL_VALID] = "Val",
diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c
index 8ccee9ee1d9d..bde3f19c0995 100644
--- a/fs/afs/rxrpc.c
+++ b/fs/afs/rxrpc.c
@@ -239,7 +239,8 @@ void afs_flat_call_destructor(struct afs_call *call)
/*
* attach the data from a bunch of pages on an inode to a call
*/
-int afs_send_pages(struct afs_call *call, struct msghdr *msg, struct kvec *iov)
+static int afs_send_pages(struct afs_call *call, struct msghdr *msg,
+ struct kvec *iov)
{
struct page *pages[8];
unsigned count, n, loop, offset, to;
diff --git a/fs/afs/server.c b/fs/afs/server.c
index 231ae4150279..28f2451419e1 100644
--- a/fs/afs/server.c
+++ b/fs/afs/server.c
@@ -13,7 +13,7 @@
#include <linux/slab.h>
#include "internal.h"
-unsigned afs_server_timeout = 10; /* server timeout in seconds */
+static unsigned afs_server_timeout = 10; /* server timeout in seconds */
static void afs_reap_server(struct work_struct *);
diff --git a/fs/afs/super.c b/fs/afs/super.c
index b8808b40f82b..4b2558c42213 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -27,8 +27,7 @@
#define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */
-static void afs_i_init_once(void *foo, struct kmem_cache *cachep,
- unsigned long flags);
+static void afs_i_init_once(struct kmem_cache *cachep, void *foo);
static int afs_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name,
void *data, struct vfsmount *mnt);
@@ -446,8 +445,7 @@ static void afs_put_super(struct super_block *sb)
/*
* initialise an inode cache slab element prior to any use
*/
-static void afs_i_init_once(void *_vnode, struct kmem_cache *cachep,
- unsigned long flags)
+static void afs_i_init_once(struct kmem_cache *cachep, void *_vnode)
{
struct afs_vnode *vnode = _vnode;
diff --git a/fs/afs/vlocation.c b/fs/afs/vlocation.c
index 09e3ad0fc7cc..849fc3160cb5 100644
--- a/fs/afs/vlocation.c
+++ b/fs/afs/vlocation.c
@@ -15,8 +15,8 @@
#include <linux/sched.h>
#include "internal.h"
-unsigned afs_vlocation_timeout = 10; /* volume location timeout in seconds */
-unsigned afs_vlocation_update_timeout = 10 * 60;
+static unsigned afs_vlocation_timeout = 10; /* volume location timeout in seconds */
+static unsigned afs_vlocation_update_timeout = 10 * 60;
static void afs_vlocation_reaper(struct work_struct *);
static void afs_vlocation_updater(struct work_struct *);
@@ -335,7 +335,7 @@ static int afs_vlocation_fill_in_record(struct afs_vlocation *vl,
/*
* queue a vlocation record for updates
*/
-void afs_vlocation_queue_for_updates(struct afs_vlocation *vl)
+static void afs_vlocation_queue_for_updates(struct afs_vlocation *vl)
{
struct afs_vlocation *xvl;
@@ -382,7 +382,7 @@ struct afs_vlocation *afs_vlocation_lookup(struct afs_cell *cell,
cell->name, key_serial(key),
(int) namesz, (int) namesz, name, namesz);
- if (namesz > sizeof(vl->vldb.name)) {
+ if (namesz >= sizeof(vl->vldb.name)) {
_leave(" = -ENAMETOOLONG");
return ERR_PTR(-ENAMETOOLONG);
}
diff --git a/fs/afs/write.c b/fs/afs/write.c
index a03b92a0fe1d..9a849ad3c489 100644
--- a/fs/afs/write.c
+++ b/fs/afs/write.c
@@ -8,7 +8,7 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
-
+#include <linux/backing-dev.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/pagemap.h>
@@ -510,9 +510,9 @@ int afs_writepage(struct page *page, struct writeback_control *wbc)
/*
* write a region of pages back to the server
*/
-int afs_writepages_region(struct address_space *mapping,
- struct writeback_control *wbc,
- pgoff_t index, pgoff_t end, pgoff_t *_next)
+static int afs_writepages_region(struct address_space *mapping,
+ struct writeback_control *wbc,
+ pgoff_t index, pgoff_t end, pgoff_t *_next)
{
struct backing_dev_info *bdi = mapping->backing_dev_info;
struct afs_writeback *wb;
diff --git a/fs/aio.c b/fs/aio.c
index ea2e19820381..f12db415c0f6 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -303,7 +303,7 @@ static void wait_for_all_aios(struct kioctx *ctx)
set_task_state(tsk, TASK_UNINTERRUPTIBLE);
while (ctx->reqs_active) {
spin_unlock_irq(&ctx->ctx_lock);
- schedule();
+ io_schedule();
set_task_state(tsk, TASK_UNINTERRUPTIBLE);
spin_lock_irq(&ctx->ctx_lock);
}
@@ -323,7 +323,7 @@ ssize_t fastcall wait_on_sync_kiocb(struct kiocb *iocb)
set_current_state(TASK_UNINTERRUPTIBLE);
if (!iocb->ki_users)
break;
- schedule();
+ io_schedule();
}
__set_current_state(TASK_RUNNING);
return iocb->ki_user_data;
@@ -710,18 +710,9 @@ static ssize_t aio_run_iocb(struct kiocb *iocb)
/*
* Now we are all set to call the retry method in async
- * context. By setting this thread's io_wait context
- * to point to the wait queue entry inside the currently
- * running iocb for the duration of the retry, we ensure
- * that async notification wakeups are queued by the
- * operation instead of blocking waits, and when notified,
- * cause the iocb to be kicked for continuation (through
- * the aio_wake_function callback).
+ * context.
*/
- BUG_ON(current->io_wait != NULL);
- current->io_wait = &iocb->ki_wait;
ret = retry(iocb);
- current->io_wait = NULL;
if (ret != -EIOCBRETRY && ret != -EIOCBQUEUED) {
BUG_ON(!list_empty(&iocb->ki_wait.task_list));
@@ -1170,7 +1161,7 @@ retry:
ret = 0;
if (to.timed_out) /* Only check after read evt */
break;
- schedule();
+ io_schedule();
if (signal_pending(tsk)) {
ret = -EINTR;
break;
@@ -1508,10 +1499,7 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb)
* Simply triggers a retry of the operation via kick_iocb.
*
* This callback is specified in the wait queue entry in
- * a kiocb (current->io_wait points to this wait queue
- * entry when an aio operation executes; it is used
- * instead of a synchronous wait when an i/o blocking
- * condition is encountered during aio).
+ * a kiocb.
*
* Note:
* This routine is executed with the wait queue lock held.
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
index b4a75880f6fd..23321889d9b0 100644
--- a/fs/anon_inodes.c
+++ b/fs/anon_inodes.c
@@ -76,7 +76,6 @@ int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile,
{
struct qstr this;
struct dentry *dentry;
- struct inode *inode;
struct file *file;
int error, fd;
@@ -86,15 +85,9 @@ int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile,
if (!file)
return -ENFILE;
- inode = igrab(anon_inode_inode);
- if (IS_ERR(inode)) {
- error = PTR_ERR(inode);
- goto err_put_filp;
- }
-
error = get_unused_fd();
if (error < 0)
- goto err_iput;
+ goto err_put_filp;
fd = error;
/*
@@ -108,14 +101,22 @@ int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile,
dentry = d_alloc(anon_inode_mnt->mnt_sb->s_root, &this);
if (!dentry)
goto err_put_unused_fd;
+
+ /*
+ * We know the anon_inode inode count is always greater than zero,
+ * so we can avoid doing an igrab() and we can use an open-coded
+ * atomic_inc().
+ */
+ atomic_inc(&anon_inode_inode->i_count);
+
dentry->d_op = &anon_inodefs_dentry_operations;
/* Do not publish this dentry inside the global dentry hash table */
dentry->d_flags &= ~DCACHE_UNHASHED;
- d_instantiate(dentry, inode);
+ d_instantiate(dentry, anon_inode_inode);
file->f_path.mnt = mntget(anon_inode_mnt);
file->f_path.dentry = dentry;
- file->f_mapping = inode->i_mapping;
+ file->f_mapping = anon_inode_inode->i_mapping;
file->f_pos = 0;
file->f_flags = O_RDWR;
@@ -127,14 +128,12 @@ int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile,
fd_install(fd, file);
*pfd = fd;
- *pinode = inode;
+ *pinode = anon_inode_inode;
*pfile = file;
return 0;
err_put_unused_fd:
put_unused_fd(fd);
-err_iput:
- iput(inode);
err_put_filp:
put_filp(file);
return error;
diff --git a/fs/attr.c b/fs/attr.c
index f8dfc2269d85..966b73e25f82 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -103,12 +103,11 @@ EXPORT_SYMBOL(inode_setattr);
int notify_change(struct dentry * dentry, struct iattr * attr)
{
struct inode *inode = dentry->d_inode;
- mode_t mode;
+ mode_t mode = inode->i_mode;
int error;
struct timespec now;
unsigned int ia_valid = attr->ia_valid;
- mode = inode->i_mode;
now = current_fs_time(inode->i_sb);
attr->ia_ctime = now;
@@ -116,18 +115,34 @@ int notify_change(struct dentry * dentry, struct iattr * attr)
attr->ia_atime = now;
if (!(ia_valid & ATTR_MTIME_SET))
attr->ia_mtime = now;
+ if (ia_valid & ATTR_KILL_PRIV) {
+ attr->ia_valid &= ~ATTR_KILL_PRIV;
+ ia_valid &= ~ATTR_KILL_PRIV;
+ error = security_inode_need_killpriv(dentry);
+ if (error > 0)
+ error = security_inode_killpriv(dentry);
+ if (error)
+ return error;
+ }
+
+ /*
+ * We now pass ATTR_KILL_S*ID to the lower level setattr function so
+ * that the function has the ability to reinterpret a mode change
+ * that's due to these bits. This adds an implicit restriction that
+ * no function will ever call notify_change with both ATTR_MODE and
+ * ATTR_KILL_S*ID set.
+ */
+ if ((ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID)) &&
+ (ia_valid & ATTR_MODE))
+ BUG();
+
if (ia_valid & ATTR_KILL_SUID) {
- attr->ia_valid &= ~ATTR_KILL_SUID;
if (mode & S_ISUID) {
- if (!(ia_valid & ATTR_MODE)) {
- ia_valid = attr->ia_valid |= ATTR_MODE;
- attr->ia_mode = inode->i_mode;
- }
- attr->ia_mode &= ~S_ISUID;
+ ia_valid = attr->ia_valid |= ATTR_MODE;
+ attr->ia_mode = (inode->i_mode & ~S_ISUID);
}
}
if (ia_valid & ATTR_KILL_SGID) {
- attr->ia_valid &= ~ ATTR_KILL_SGID;
if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
if (!(ia_valid & ATTR_MODE)) {
ia_valid = attr->ia_valid |= ATTR_MODE;
@@ -136,7 +151,7 @@ int notify_change(struct dentry * dentry, struct iattr * attr)
attr->ia_mode &= ~S_ISGID;
}
}
- if (!attr->ia_valid)
+ if (!(attr->ia_valid & ~(ATTR_KILL_SUID | ATTR_KILL_SGID)))
return 0;
if (ia_valid & ATTR_SIZE)
diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c
index e7204d71acc9..45f5992a0957 100644
--- a/fs/autofs/inode.c
+++ b/fs/autofs/inode.c
@@ -80,7 +80,7 @@ static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid,
*uid = current->uid;
*gid = current->gid;
- *pgrp = process_group(current);
+ *pgrp = task_pgrp_nr(current);
*minproto = *maxproto = AUTOFS_PROTO_VERSION;
diff --git a/fs/autofs/root.c b/fs/autofs/root.c
index c1489533277a..5efff3c0d886 100644
--- a/fs/autofs/root.c
+++ b/fs/autofs/root.c
@@ -214,8 +214,8 @@ static struct dentry *autofs_root_lookup(struct inode *dir, struct dentry *dentr
oz_mode = autofs_oz_mode(sbi);
DPRINTK(("autofs_lookup: pid = %u, pgrp = %u, catatonic = %d, "
- "oz_mode = %d\n", pid_nr(task_pid(current)),
- process_group(current), sbi->catatonic,
+ "oz_mode = %d\n", task_pid_nr(current),
+ task_pgrp_nr(current), sbi->catatonic,
oz_mode));
/*
@@ -536,7 +536,7 @@ static int autofs_root_ioctl(struct inode *inode, struct file *filp,
struct autofs_sb_info *sbi = autofs_sbi(inode->i_sb);
void __user *argp = (void __user *)arg;
- DPRINTK(("autofs_ioctl: cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u\n",cmd,arg,sbi,process_group(current)));
+ DPRINTK(("autofs_ioctl: cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u\n",cmd,arg,sbi,task_pgrp_nr(current)));
if (_IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) ||
_IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT)
diff --git a/fs/autofs/waitq.c b/fs/autofs/waitq.c
index 19a9cafb5ddf..be46805972f0 100644
--- a/fs/autofs/waitq.c
+++ b/fs/autofs/waitq.c
@@ -182,7 +182,7 @@ int autofs_wait_release(struct autofs_sb_info *sbi, autofs_wqt_t wait_queue_toke
{
struct autofs_wait_queue *wq, **wql;
- for ( wql = &sbi->queues ; (wq = *wql) != 0 ; wql = &wq->next ) {
+ for (wql = &sbi->queues; (wq = *wql) != NULL; wql = &wq->next) {
if ( wq->wait_queue_token == wait_queue_token )
break;
}
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index d85f42fa9206..2d4ae40718d9 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -131,7 +131,7 @@ static inline struct autofs_info *autofs4_dentry_ino(struct dentry *dentry)
filesystem without "magic".) */
static inline int autofs4_oz_mode(struct autofs_sb_info *sbi) {
- return sbi->catatonic || process_group(current) == sbi->oz_pgrp;
+ return sbi->catatonic || task_pgrp_nr(current) == sbi->oz_pgrp;
}
/* Does a dentry have some pending activity? */
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index 692364e8ffc3..7f05d6ccdb13 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -226,7 +226,7 @@ static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid,
*uid = current->uid;
*gid = current->gid;
- *pgrp = process_group(current);
+ *pgrp = task_pgrp_nr(current);
*minproto = AUTOFS_MIN_PROTO_VERSION;
*maxproto = AUTOFS_MAX_PROTO_VERSION;
@@ -312,20 +312,18 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
struct autofs_sb_info *sbi;
struct autofs_info *ino;
- sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
+ sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
if (!sbi)
goto fail_unlock;
DPRINTK("starting up, sbi = %p",sbi);
- memset(sbi, 0, sizeof(*sbi));
-
s->s_fs_info = sbi;
sbi->magic = AUTOFS_SBI_MAGIC;
sbi->pipefd = -1;
sbi->pipe = NULL;
sbi->catatonic = 1;
sbi->exp_timeout = 0;
- sbi->oz_pgrp = process_group(current);
+ sbi->oz_pgrp = task_pgrp_nr(current);
sbi->sb = s;
sbi->version = 0;
sbi->sub_version = 0;
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 45ff3d63b758..2bbcc8151dc3 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -582,7 +582,7 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
oz_mode = autofs4_oz_mode(sbi);
DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d",
- current->pid, process_group(current), sbi->catatonic, oz_mode);
+ current->pid, task_pgrp_nr(current), sbi->catatonic, oz_mode);
unhashed = autofs4_lookup_unhashed(sbi, dentry->d_parent, &dentry->d_name);
if (!unhashed) {
@@ -976,7 +976,7 @@ static int autofs4_root_ioctl(struct inode *inode, struct file *filp,
void __user *p = (void __user *)arg;
DPRINTK("cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u",
- cmd,arg,sbi,process_group(current));
+ cmd,arg,sbi,task_pgrp_nr(current));
if (_IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) ||
_IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT)
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
index 0d041a9cb348..1fe28e4754c2 100644
--- a/fs/autofs4/waitq.c
+++ b/fs/autofs4/waitq.c
@@ -376,7 +376,7 @@ int autofs4_wait_release(struct autofs_sb_info *sbi, autofs_wqt_t wait_queue_tok
struct autofs_wait_queue *wq, **wql;
mutex_lock(&sbi->wq_mutex);
- for (wql = &sbi->queues ; (wq = *wql) != 0 ; wql = &wq->next) {
+ for (wql = &sbi->queues; (wq = *wql) != NULL; wql = &wq->next) {
if (wq->wait_queue_token == wait_queue_token)
break;
}
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
index a45141827681..b28a20e61b80 100644
--- a/fs/befs/linuxvfs.c
+++ b/fs/befs/linuxvfs.c
@@ -289,7 +289,7 @@ befs_destroy_inode(struct inode *inode)
kmem_cache_free(befs_inode_cachep, BEFS_I(inode));
}
-static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
+static void init_once(struct kmem_cache *cachep, void *foo)
{
struct befs_inode_info *bi = (struct befs_inode_info *) foo;
diff --git a/fs/bfs/bfs.h b/fs/bfs/bfs.h
index 130f6c66c5ba..ac7a8b1d6c3a 100644
--- a/fs/bfs/bfs.h
+++ b/fs/bfs/bfs.h
@@ -14,8 +14,6 @@ struct bfs_sb_info {
unsigned long si_blocks;
unsigned long si_freeb;
unsigned long si_freei;
- unsigned long si_lf_ioff;
- unsigned long si_lf_sblk;
unsigned long si_lf_eblk;
unsigned long si_lasti;
unsigned long * si_imap;
@@ -39,7 +37,7 @@ static inline struct bfs_sb_info *BFS_SB(struct super_block *sb)
static inline struct bfs_inode_info *BFS_I(struct inode *inode)
{
- return list_entry(inode, struct bfs_inode_info, vfs_inode);
+ return container_of(inode, struct bfs_inode_info, vfs_inode);
}
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c
index 097f1497f743..1fd056d0fc3d 100644
--- a/fs/bfs/dir.c
+++ b/fs/bfs/dir.c
@@ -21,29 +21,32 @@
#define dprintf(x...)
#endif
-static int bfs_add_entry(struct inode * dir, const unsigned char * name, int namelen, int ino);
-static struct buffer_head * bfs_find_entry(struct inode * dir,
- const unsigned char * name, int namelen, struct bfs_dirent ** res_dir);
+static int bfs_add_entry(struct inode *dir, const unsigned char *name,
+ int namelen, int ino);
+static struct buffer_head *bfs_find_entry(struct inode *dir,
+ const unsigned char *name, int namelen,
+ struct bfs_dirent **res_dir);
-static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir)
+static int bfs_readdir(struct file *f, void *dirent, filldir_t filldir)
{
- struct inode * dir = f->f_path.dentry->d_inode;
- struct buffer_head * bh;
- struct bfs_dirent * de;
+ struct inode *dir = f->f_path.dentry->d_inode;
+ struct buffer_head *bh;
+ struct bfs_dirent *de;
unsigned int offset;
int block;
lock_kernel();
- if (f->f_pos & (BFS_DIRENT_SIZE-1)) {
- printf("Bad f_pos=%08lx for %s:%08lx\n", (unsigned long)f->f_pos,
- dir->i_sb->s_id, dir->i_ino);
+ if (f->f_pos & (BFS_DIRENT_SIZE - 1)) {
+ printf("Bad f_pos=%08lx for %s:%08lx\n",
+ (unsigned long)f->f_pos,
+ dir->i_sb->s_id, dir->i_ino);
unlock_kernel();
return -EBADF;
}
while (f->f_pos < dir->i_size) {
- offset = f->f_pos & (BFS_BSIZE-1);
+ offset = f->f_pos & (BFS_BSIZE - 1);
block = BFS_I(dir)->i_sblock + (f->f_pos >> BFS_BSIZE_BITS);
bh = sb_bread(dir->i_sb, block);
if (!bh) {
@@ -54,7 +57,9 @@ static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir)
de = (struct bfs_dirent *)(bh->b_data + offset);
if (de->ino) {
int size = strnlen(de->name, BFS_NAMELEN);
- if (filldir(dirent, de->name, size, f->f_pos, le16_to_cpu(de->ino), DT_UNKNOWN) < 0) {
+ if (filldir(dirent, de->name, size, f->f_pos,
+ le16_to_cpu(de->ino),
+ DT_UNKNOWN) < 0) {
brelse(bh);
unlock_kernel();
return 0;
@@ -62,7 +67,7 @@ static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir)
}
offset += BFS_DIRENT_SIZE;
f->f_pos += BFS_DIRENT_SIZE;
- } while (offset < BFS_BSIZE && f->f_pos < dir->i_size);
+ } while ((offset < BFS_BSIZE) && (f->f_pos < dir->i_size));
brelse(bh);
}
@@ -78,13 +83,13 @@ const struct file_operations bfs_dir_operations = {
extern void dump_imap(const char *, struct super_block *);
-static int bfs_create(struct inode * dir, struct dentry * dentry, int mode,
- struct nameidata *nd)
+static int bfs_create(struct inode *dir, struct dentry *dentry, int mode,
+ struct nameidata *nd)
{
int err;
- struct inode * inode;
- struct super_block * s = dir->i_sb;
- struct bfs_sb_info * info = BFS_SB(s);
+ struct inode *inode;
+ struct super_block *s = dir->i_sb;
+ struct bfs_sb_info *info = BFS_SB(s);
unsigned long ino;
inode = new_inode(s);
@@ -97,7 +102,7 @@ static int bfs_create(struct inode * dir, struct dentry * dentry, int mode,
iput(inode);
return -ENOSPC;
}
- set_bit(ino, info->si_imap);
+ set_bit(ino, info->si_imap);
info->si_freei--;
inode->i_uid = current->fsuid;
inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
@@ -113,9 +118,10 @@ static int bfs_create(struct inode * dir, struct dentry * dentry, int mode,
BFS_I(inode)->i_eblock = 0;
insert_inode_hash(inode);
mark_inode_dirty(inode);
- dump_imap("create",s);
+ dump_imap("create", s);
- err = bfs_add_entry(dir, dentry->d_name.name, dentry->d_name.len, inode->i_ino);
+ err = bfs_add_entry(dir, dentry->d_name.name, dentry->d_name.len,
+ inode->i_ino);
if (err) {
inode_dec_link_count(inode);
iput(inode);
@@ -127,11 +133,12 @@ static int bfs_create(struct inode * dir, struct dentry * dentry, int mode,
return 0;
}
-static struct dentry * bfs_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
+static struct dentry *bfs_lookup(struct inode *dir, struct dentry *dentry,
+ struct nameidata *nd)
{
- struct inode * inode = NULL;
- struct buffer_head * bh;
- struct bfs_dirent * de;
+ struct inode *inode = NULL;
+ struct buffer_head *bh;
+ struct bfs_dirent *de;
if (dentry->d_name.len > BFS_NAMELEN)
return ERR_PTR(-ENAMETOOLONG);
@@ -152,13 +159,15 @@ static struct dentry * bfs_lookup(struct inode * dir, struct dentry * dentry, st
return NULL;
}
-static int bfs_link(struct dentry * old, struct inode * dir, struct dentry * new)
+static int bfs_link(struct dentry *old, struct inode *dir,
+ struct dentry *new)
{
- struct inode * inode = old->d_inode;
+ struct inode *inode = old->d_inode;
int err;
lock_kernel();
- err = bfs_add_entry(dir, new->d_name.name, new->d_name.len, inode->i_ino);
+ err = bfs_add_entry(dir, new->d_name.name, new->d_name.len,
+ inode->i_ino);
if (err) {
unlock_kernel();
return err;
@@ -172,23 +181,23 @@ static int bfs_link(struct dentry * old, struct inode * dir, struct dentry * new
return 0;
}
-
-static int bfs_unlink(struct inode * dir, struct dentry * dentry)
+static int bfs_unlink(struct inode *dir, struct dentry *dentry)
{
int error = -ENOENT;
- struct inode * inode;
- struct buffer_head * bh;
- struct bfs_dirent * de;
+ struct inode *inode;
+ struct buffer_head *bh;
+ struct bfs_dirent *de;
inode = dentry->d_inode;
lock_kernel();
bh = bfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);
- if (!bh || le16_to_cpu(de->ino) != inode->i_ino)
+ if (!bh || (le16_to_cpu(de->ino) != inode->i_ino))
goto out_brelse;
if (!inode->i_nlink) {
- printf("unlinking non-existent file %s:%lu (nlink=%d)\n", inode->i_sb->s_id,
- inode->i_ino, inode->i_nlink);
+ printf("unlinking non-existent file %s:%lu (nlink=%d)\n",
+ inode->i_sb->s_id, inode->i_ino,
+ inode->i_nlink);
inode->i_nlink = 1;
}
de->ino = 0;
@@ -205,12 +214,12 @@ out_brelse:
return error;
}
-static int bfs_rename(struct inode * old_dir, struct dentry * old_dentry,
- struct inode * new_dir, struct dentry * new_dentry)
+static int bfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry)
{
- struct inode * old_inode, * new_inode;
- struct buffer_head * old_bh, * new_bh;
- struct bfs_dirent * old_de, * new_de;
+ struct inode *old_inode, *new_inode;
+ struct buffer_head *old_bh, *new_bh;
+ struct bfs_dirent *old_de, *new_de;
int error = -ENOENT;
old_bh = new_bh = NULL;
@@ -223,7 +232,7 @@ static int bfs_rename(struct inode * old_dir, struct dentry * old_dentry,
old_dentry->d_name.name,
old_dentry->d_name.len, &old_de);
- if (!old_bh || le16_to_cpu(old_de->ino) != old_inode->i_ino)
+ if (!old_bh || (le16_to_cpu(old_de->ino) != old_inode->i_ino))
goto end_rename;
error = -EPERM;
@@ -239,7 +248,8 @@ static int bfs_rename(struct inode * old_dir, struct dentry * old_dentry,
if (!new_bh) {
error = bfs_add_entry(new_dir,
new_dentry->d_name.name,
- new_dentry->d_name.len, old_inode->i_ino);
+ new_dentry->d_name.len,
+ old_inode->i_ino);
if (error)
goto end_rename;
}
@@ -268,11 +278,12 @@ const struct inode_operations bfs_dir_inops = {
.rename = bfs_rename,
};
-static int bfs_add_entry(struct inode * dir, const unsigned char * name, int namelen, int ino)
+static int bfs_add_entry(struct inode *dir, const unsigned char *name,
+ int namelen, int ino)
{
- struct buffer_head * bh;
- struct bfs_dirent * de;
- int block, sblock, eblock, off, eoff;
+ struct buffer_head *bh;
+ struct bfs_dirent *de;
+ int block, sblock, eblock, off, pos;
int i;
dprintf("name=%s, namelen=%d\n", name, namelen);
@@ -284,27 +295,24 @@ static int bfs_add_entry(struct inode * dir, const unsigned char * name, int nam
sblock = BFS_I(dir)->i_sblock;
eblock = BFS_I(dir)->i_eblock;
- eoff = dir->i_size % BFS_BSIZE;
- for (block=sblock; block<=eblock; block++) {
+ for (block = sblock; block <= eblock; block++) {
bh = sb_bread(dir->i_sb, block);
- if(!bh)
+ if (!bh)
return -ENOSPC;
- for (off=0; off<BFS_BSIZE; off+=BFS_DIRENT_SIZE) {
+ for (off = 0; off < BFS_BSIZE; off += BFS_DIRENT_SIZE) {
de = (struct bfs_dirent *)(bh->b_data + off);
- if (block==eblock && off>=eoff) {
- /* Do not read/interpret the garbage in the end of eblock. */
- de->ino = 0;
- }
if (!de->ino) {
- if ((block-sblock)*BFS_BSIZE + off >= dir->i_size) {
+ pos = (block - sblock) * BFS_BSIZE + off;
+ if (pos >= dir->i_size) {
dir->i_size += BFS_DIRENT_SIZE;
dir->i_ctime = CURRENT_TIME_SEC;
}
dir->i_mtime = CURRENT_TIME_SEC;
mark_inode_dirty(dir);
de->ino = cpu_to_le16((u16)ino);
- for (i=0; i<BFS_NAMELEN; i++)
- de->name[i] = (i < namelen) ? name[i] : 0;
+ for (i = 0; i < BFS_NAMELEN; i++)
+ de->name[i] =
+ (i < namelen) ? name[i] : 0;
mark_buffer_dirty(bh);
brelse(bh);
return 0;
@@ -315,25 +323,26 @@ static int bfs_add_entry(struct inode * dir, const unsigned char * name, int nam
return -ENOSPC;
}
-static inline int bfs_namecmp(int len, const unsigned char * name, const char * buffer)
+static inline int bfs_namecmp(int len, const unsigned char *name,
+ const char *buffer)
{
- if (len < BFS_NAMELEN && buffer[len])
+ if ((len < BFS_NAMELEN) && buffer[len])
return 0;
return !memcmp(name, buffer, len);
}
-static struct buffer_head * bfs_find_entry(struct inode * dir,
- const unsigned char * name, int namelen, struct bfs_dirent ** res_dir)
+static struct buffer_head *bfs_find_entry(struct inode *dir,
+ const unsigned char *name, int namelen,
+ struct bfs_dirent **res_dir)
{
- unsigned long block, offset;
- struct buffer_head * bh;
- struct bfs_dirent * de;
+ unsigned long block = 0, offset = 0;
+ struct buffer_head *bh = NULL;
+ struct bfs_dirent *de;
*res_dir = NULL;
if (namelen > BFS_NAMELEN)
return NULL;
- bh = NULL;
- block = offset = 0;
+
while (block * BFS_BSIZE + offset < dir->i_size) {
if (!bh) {
bh = sb_bread(dir->i_sb, BFS_I(dir)->i_sblock + block);
@@ -344,7 +353,8 @@ static struct buffer_head * bfs_find_entry(struct inode * dir,
}
de = (struct bfs_dirent *)(bh->b_data + offset);
offset += BFS_DIRENT_SIZE;
- if (le16_to_cpu(de->ino) && bfs_namecmp(namelen, name, de->name)) {
+ if (le16_to_cpu(de->ino) &&
+ bfs_namecmp(namelen, name, de->name)) {
*res_dir = de;
return bh;
}
diff --git a/fs/bfs/file.c b/fs/bfs/file.c
index 24310e9ee05a..b11e63e8fbcd 100644
--- a/fs/bfs/file.c
+++ b/fs/bfs/file.c
@@ -2,6 +2,11 @@
* fs/bfs/file.c
* BFS file operations.
* Copyright (C) 1999,2000 Tigran Aivazian <tigran@veritas.com>
+ *
+ * Make the file block allocation algorithm understand the size
+ * of the underlying block device.
+ * Copyright (C) 2007 Dmitri Vorobiev <dmitri.vorobiev@gmail.com>
+ *
*/
#include <linux/fs.h>
@@ -27,7 +32,8 @@ const struct file_operations bfs_file_operations = {
.splice_read = generic_file_splice_read,
};
-static int bfs_move_block(unsigned long from, unsigned long to, struct super_block *sb)
+static int bfs_move_block(unsigned long from, unsigned long to,
+ struct super_block *sb)
{
struct buffer_head *bh, *new;
@@ -43,21 +49,22 @@ static int bfs_move_block(unsigned long from, unsigned long to, struct super_blo
}
static int bfs_move_blocks(struct super_block *sb, unsigned long start,
- unsigned long end, unsigned long where)
+ unsigned long end, unsigned long where)
{
unsigned long i;
dprintf("%08lx-%08lx->%08lx\n", start, end, where);
for (i = start; i <= end; i++)
if(bfs_move_block(i, where + i, sb)) {
- dprintf("failed to move block %08lx -> %08lx\n", i, where + i);
+ dprintf("failed to move block %08lx -> %08lx\n", i,
+ where + i);
return -EIO;
}
return 0;
}
-static int bfs_get_block(struct inode * inode, sector_t block,
- struct buffer_head * bh_result, int create)
+static int bfs_get_block(struct inode *inode, sector_t block,
+ struct buffer_head *bh_result, int create)
{
unsigned long phys;
int err;
@@ -66,9 +73,6 @@ static int bfs_get_block(struct inode * inode, sector_t block,
struct bfs_inode_info *bi = BFS_I(inode);
struct buffer_head *sbh = info->si_sbh;
- if (block > info->si_blocks)
- return -EIO;
-
phys = bi->i_sblock + block;
if (!create) {
if (phys <= bi->i_eblock) {
@@ -79,21 +83,29 @@ static int bfs_get_block(struct inode * inode, sector_t block,
return 0;
}
- /* if the file is not empty and the requested block is within the range
- of blocks allocated for this file, we can grant it */
- if (inode->i_size && phys <= bi->i_eblock) {
+ /*
+ * If the file is not empty and the requested block is within the
+ * range of blocks allocated for this file, we can grant it.
+ */
+ if (bi->i_sblock && (phys <= bi->i_eblock)) {
dprintf("c=%d, b=%08lx, phys=%08lx (interim block granted)\n",
create, (unsigned long)block, phys);
map_bh(bh_result, sb, phys);
return 0;
}
- /* the rest has to be protected against itself */
+ /* The file will be extended, so let's see if there is enough space. */
+ if (phys >= info->si_blocks)
+ return -ENOSPC;
+
+ /* The rest has to be protected against itself. */
lock_kernel();
- /* if the last data block for this file is the last allocated
- block, we can extend the file trivially, without moving it
- anywhere */
+ /*
+ * If the last data block for this file is the last allocated
+ * block, we can extend the file trivially, without moving it
+ * anywhere.
+ */
if (bi->i_eblock == info->si_lf_eblk) {
dprintf("c=%d, b=%08lx, phys=%08lx (simple extension)\n",
create, (unsigned long)block, phys);
@@ -106,13 +118,19 @@ static int bfs_get_block(struct inode * inode, sector_t block,
goto out;
}
- /* Ok, we have to move this entire file to the next free block */
+ /* Ok, we have to move this entire file to the next free block. */
phys = info->si_lf_eblk + 1;
- if (bi->i_sblock) { /* if data starts on block 0 then there is no data */
+ if (phys + block >= info->si_blocks) {
+ err = -ENOSPC;
+ goto out;
+ }
+
+ if (bi->i_sblock) {
err = bfs_move_blocks(inode->i_sb, bi->i_sblock,
- bi->i_eblock, phys);
+ bi->i_eblock, phys);
if (err) {
- dprintf("failed to move ino=%08lx -> fs corruption\n", inode->i_ino);
+ dprintf("failed to move ino=%08lx -> fs corruption\n",
+ inode->i_ino);
goto out;
}
} else
@@ -124,8 +142,10 @@ static int bfs_get_block(struct inode * inode, sector_t block,
phys += block;
info->si_lf_eblk = bi->i_eblock = phys;
- /* this assumes nothing can write the inode back while we are here
- * and thus update inode->i_blocks! (XXX)*/
+ /*
+ * This assumes nothing can write the inode back while we are here
+ * and thus update inode->i_blocks! (XXX)
+ */
info->si_freeb -= bi->i_eblock - bi->i_sblock + 1 - inode->i_blocks;
mark_inode_dirty(inode);
mark_buffer_dirty(sbh);
@@ -145,9 +165,13 @@ static int bfs_readpage(struct file *file, struct page *page)
return block_read_full_page(page, bfs_get_block);
}
-static int bfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
+static int bfs_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
{
- return block_prepare_write(page, from, to, bfs_get_block);
+ *pagep = NULL;
+ return block_write_begin(file, mapping, pos, len, flags,
+ pagep, fsdata, bfs_get_block);
}
static sector_t bfs_bmap(struct address_space *mapping, sector_t block)
@@ -159,8 +183,8 @@ const struct address_space_operations bfs_aops = {
.readpage = bfs_readpage,
.writepage = bfs_writepage,
.sync_page = block_sync_page,
- .prepare_write = bfs_prepare_write,
- .commit_write = generic_commit_write,
+ .write_begin = bfs_write_begin,
+ .write_end = generic_write_end,
.bmap = bfs_bmap,
};
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c
index f346eb14e86f..294c41baef6e 100644
--- a/fs/bfs/inode.c
+++ b/fs/bfs/inode.c
@@ -30,25 +30,26 @@ MODULE_LICENSE("GPL");
#define dprintf(x...)
#endif
-void dump_imap(const char *prefix, struct super_block * s);
+void dump_imap(const char *prefix, struct super_block *s);
-static void bfs_read_inode(struct inode * inode)
+static void bfs_read_inode(struct inode *inode)
{
unsigned long ino = inode->i_ino;
- struct bfs_inode * di;
- struct buffer_head * bh;
+ struct bfs_inode *di;
+ struct buffer_head *bh;
int block, off;
- if (ino < BFS_ROOT_INO || ino > BFS_SB(inode->i_sb)->si_lasti) {
+ if ((ino < BFS_ROOT_INO) || (ino > BFS_SB(inode->i_sb)->si_lasti)) {
printf("Bad inode number %s:%08lx\n", inode->i_sb->s_id, ino);
make_bad_inode(inode);
return;
}
- block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1;
+ block = (ino - BFS_ROOT_INO) / BFS_INODES_PER_BLOCK + 1;
bh = sb_bread(inode->i_sb, block);
if (!bh) {
- printf("Unable to read inode %s:%08lx\n", inode->i_sb->s_id, ino);
+ printf("Unable to read inode %s:%08lx\n", inode->i_sb->s_id,
+ ino);
make_bad_inode(inode);
return;
}
@@ -56,7 +57,7 @@ static void bfs_read_inode(struct inode * inode)
off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK;
di = (struct bfs_inode *)bh->b_data + off;
- inode->i_mode = 0x0000FFFF & le32_to_cpu(di->i_mode);
+ inode->i_mode = 0x0000FFFF & le32_to_cpu(di->i_mode);
if (le32_to_cpu(di->i_vtype) == BFS_VDIR) {
inode->i_mode |= S_IFDIR;
inode->i_op = &bfs_dir_inops;
@@ -70,48 +71,48 @@ static void bfs_read_inode(struct inode * inode)
BFS_I(inode)->i_sblock = le32_to_cpu(di->i_sblock);
BFS_I(inode)->i_eblock = le32_to_cpu(di->i_eblock);
+ BFS_I(inode)->i_dsk_ino = le16_to_cpu(di->i_ino);
inode->i_uid = le32_to_cpu(di->i_uid);
inode->i_gid = le32_to_cpu(di->i_gid);
inode->i_nlink = le32_to_cpu(di->i_nlink);
inode->i_size = BFS_FILESIZE(di);
inode->i_blocks = BFS_FILEBLOCKS(di);
- if (inode->i_size || inode->i_blocks) dprintf("Registered inode with %lld size, %ld blocks\n", inode->i_size, inode->i_blocks);
inode->i_atime.tv_sec = le32_to_cpu(di->i_atime);
inode->i_mtime.tv_sec = le32_to_cpu(di->i_mtime);
inode->i_ctime.tv_sec = le32_to_cpu(di->i_ctime);
inode->i_atime.tv_nsec = 0;
inode->i_mtime.tv_nsec = 0;
inode->i_ctime.tv_nsec = 0;
- BFS_I(inode)->i_dsk_ino = le16_to_cpu(di->i_ino); /* can be 0 so we store a copy */
brelse(bh);
}
-static int bfs_write_inode(struct inode * inode, int unused)
+static int bfs_write_inode(struct inode *inode, int unused)
{
unsigned int ino = (u16)inode->i_ino;
unsigned long i_sblock;
- struct bfs_inode * di;
- struct buffer_head * bh;
+ struct bfs_inode *di;
+ struct buffer_head *bh;
int block, off;
dprintf("ino=%08x\n", ino);
- if (ino < BFS_ROOT_INO || ino > BFS_SB(inode->i_sb)->si_lasti) {
+ if ((ino < BFS_ROOT_INO) || (ino > BFS_SB(inode->i_sb)->si_lasti)) {
printf("Bad inode number %s:%08x\n", inode->i_sb->s_id, ino);
return -EIO;
}
lock_kernel();
- block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1;
+ block = (ino - BFS_ROOT_INO) / BFS_INODES_PER_BLOCK + 1;
bh = sb_bread(inode->i_sb, block);
if (!bh) {
- printf("Unable to read inode %s:%08x\n", inode->i_sb->s_id, ino);
+ printf("Unable to read inode %s:%08x\n",
+ inode->i_sb->s_id, ino);
unlock_kernel();
return -EIO;
}
- off = (ino - BFS_ROOT_INO)%BFS_INODES_PER_BLOCK;
+ off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK;
di = (struct bfs_inode *)bh->b_data + off;
if (ino == BFS_ROOT_INO)
@@ -133,27 +134,26 @@ static int bfs_write_inode(struct inode * inode, int unused)
di->i_eoffset = cpu_to_le32(i_sblock * BFS_BSIZE + inode->i_size - 1);
mark_buffer_dirty(bh);
- dprintf("Written ino=%d into %d:%d\n",le16_to_cpu(di->i_ino),block,off);
brelse(bh);
unlock_kernel();
return 0;
}
-static void bfs_delete_inode(struct inode * inode)
+static void bfs_delete_inode(struct inode *inode)
{
unsigned long ino = inode->i_ino;
- struct bfs_inode * di;
- struct buffer_head * bh;
+ struct bfs_inode *di;
+ struct buffer_head *bh;
int block, off;
- struct super_block * s = inode->i_sb;
- struct bfs_sb_info * info = BFS_SB(s);
- struct bfs_inode_info * bi = BFS_I(inode);
+ struct super_block *s = inode->i_sb;
+ struct bfs_sb_info *info = BFS_SB(s);
+ struct bfs_inode_info *bi = BFS_I(inode);
dprintf("ino=%08lx\n", ino);
truncate_inode_pages(&inode->i_data, 0);
- if (ino < BFS_ROOT_INO || ino > info->si_lasti) {
+ if ((ino < BFS_ROOT_INO) || (ino > info->si_lasti)) {
printf("invalid ino=%08lx\n", ino);
return;
}
@@ -162,31 +162,35 @@ static void bfs_delete_inode(struct inode * inode)
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
lock_kernel();
mark_inode_dirty(inode);
- block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1;
+
+ block = (ino - BFS_ROOT_INO) / BFS_INODES_PER_BLOCK + 1;
bh = sb_bread(s, block);
if (!bh) {
- printf("Unable to read inode %s:%08lx\n", inode->i_sb->s_id, ino);
+ printf("Unable to read inode %s:%08lx\n",
+ inode->i_sb->s_id, ino);
unlock_kernel();
return;
}
- off = (ino - BFS_ROOT_INO)%BFS_INODES_PER_BLOCK;
- di = (struct bfs_inode *) bh->b_data + off;
+ off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK;
+ di = (struct bfs_inode *)bh->b_data + off;
+ memset((void *)di, 0, sizeof(struct bfs_inode));
+ mark_buffer_dirty(bh);
+ brelse(bh);
+
if (bi->i_dsk_ino) {
- info->si_freeb += 1 + bi->i_eblock - bi->i_sblock;
+ info->si_freeb += BFS_FILEBLOCKS(bi);
info->si_freei++;
clear_bit(ino, info->si_imap);
dump_imap("delete_inode", s);
}
- di->i_ino = 0;
- di->i_sblock = 0;
- mark_buffer_dirty(bh);
- brelse(bh);
- /* if this was the last file, make the previous
- block "last files last block" even if there is no real file there,
- saves us 1 gap */
- if (info->si_lf_eblk == BFS_I(inode)->i_eblock) {
- info->si_lf_eblk = BFS_I(inode)->i_sblock - 1;
+ /*
+ * If this was the last file, make the previous block
+ * "last block of the last file" even if there is no
+ * real file there, saves us 1 gap.
+ */
+ if (info->si_lf_eblk == bi->i_eblock) {
+ info->si_lf_eblk = bi->i_sblock - 1;
mark_buffer_dirty(info->si_sbh);
}
unlock_kernel();
@@ -228,7 +232,7 @@ static void bfs_write_super(struct super_block *s)
unlock_kernel();
}
-static struct kmem_cache * bfs_inode_cachep;
+static struct kmem_cache *bfs_inode_cachep;
static struct inode *bfs_alloc_inode(struct super_block *sb)
{
@@ -244,7 +248,7 @@ static void bfs_destroy_inode(struct inode *inode)
kmem_cache_free(bfs_inode_cachep, BFS_I(inode));
}
-static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
+static void init_once(struct kmem_cache *cachep, void *foo)
{
struct bfs_inode_info *bi = foo;
@@ -279,7 +283,7 @@ static const struct super_operations bfs_sops = {
.statfs = bfs_statfs,
};
-void dump_imap(const char *prefix, struct super_block * s)
+void dump_imap(const char *prefix, struct super_block *s)
{
#ifdef DEBUG
int i;
@@ -287,25 +291,26 @@ void dump_imap(const char *prefix, struct super_block * s)
if (!tmpbuf)
return;
- for (i=BFS_SB(s)->si_lasti; i>=0; i--) {
- if (i > PAGE_SIZE-100) break;
+ for (i = BFS_SB(s)->si_lasti; i >= 0; i--) {
+ if (i > PAGE_SIZE - 100) break;
if (test_bit(i, BFS_SB(s)->si_imap))
strcat(tmpbuf, "1");
else
strcat(tmpbuf, "0");
}
- printk(KERN_ERR "BFS-fs: %s: lasti=%08lx <%s>\n", prefix, BFS_SB(s)->si_lasti, tmpbuf);
+ printf("BFS-fs: %s: lasti=%08lx <%s>\n",
+ prefix, BFS_SB(s)->si_lasti, tmpbuf);
free_page((unsigned long)tmpbuf);
#endif
}
static int bfs_fill_super(struct super_block *s, void *data, int silent)
{
- struct buffer_head * bh;
- struct bfs_super_block * bfs_sb;
- struct inode * inode;
+ struct buffer_head *bh;
+ struct bfs_super_block *bfs_sb;
+ struct inode *inode;
unsigned i, imap_len;
- struct bfs_sb_info * info;
+ struct bfs_sb_info *info;
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
@@ -329,14 +334,14 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent)
s->s_magic = BFS_MAGIC;
info->si_sbh = bh;
- info->si_lasti = (le32_to_cpu(bfs_sb->s_start) - BFS_BSIZE)/sizeof(struct bfs_inode)
- + BFS_ROOT_INO - 1;
-
- imap_len = info->si_lasti/8 + 1;
+ info->si_lasti = (le32_to_cpu(bfs_sb->s_start) - BFS_BSIZE) /
+ sizeof(struct bfs_inode)
+ + BFS_ROOT_INO - 1;
+ imap_len = (info->si_lasti / 8) + 1;
info->si_imap = kzalloc(imap_len, GFP_KERNEL);
if (!info->si_imap)
goto out;
- for (i=0; i<BFS_ROOT_INO; i++)
+ for (i = 0; i < BFS_ROOT_INO; i++)
set_bit(i, info->si_imap);
s->s_op = &bfs_sops;
@@ -352,16 +357,15 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent)
goto out;
}
- info->si_blocks = (le32_to_cpu(bfs_sb->s_end) + 1)>>BFS_BSIZE_BITS; /* for statfs(2) */
- info->si_freeb = (le32_to_cpu(bfs_sb->s_end) + 1 - le32_to_cpu(bfs_sb->s_start))>>BFS_BSIZE_BITS;
+ info->si_blocks = (le32_to_cpu(bfs_sb->s_end) + 1) >> BFS_BSIZE_BITS;
+ info->si_freeb = (le32_to_cpu(bfs_sb->s_end) + 1
+ - le32_to_cpu(bfs_sb->s_start)) >> BFS_BSIZE_BITS;
info->si_freei = 0;
info->si_lf_eblk = 0;
- info->si_lf_sblk = 0;
- info->si_lf_ioff = 0;
bh = NULL;
- for (i=BFS_ROOT_INO; i<=info->si_lasti; i++) {
+ for (i = BFS_ROOT_INO; i <= info->si_lasti; i++) {
struct bfs_inode *di;
- int block = (i - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1;
+ int block = (i - BFS_ROOT_INO) / BFS_INODES_PER_BLOCK + 1;
int off = (i - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK;
unsigned long sblock, eblock;
@@ -384,11 +388,8 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent)
sblock = le32_to_cpu(di->i_sblock);
eblock = le32_to_cpu(di->i_eblock);
- if (eblock > info->si_lf_eblk) {
+ if (eblock > info->si_lf_eblk)
info->si_lf_eblk = eblock;
- info->si_lf_sblk = sblock;
- info->si_lf_ioff = BFS_INO2OFF(i);
- }
}
brelse(bh);
if (!(s->s_flags & MS_RDONLY)) {
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index 813a887cd2b3..e176d195e7e5 100644
--- a/fs/binfmt_aout.c
+++ b/fs/binfmt_aout.c
@@ -31,7 +31,7 @@
static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs);
static int load_aout_library(struct file*);
-static int aout_core_dump(long signr, struct pt_regs * regs, struct file *file);
+static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit);
static struct linux_binfmt aout_format = {
.module = THIS_MODULE,
@@ -88,7 +88,7 @@ if (file->f_op->llseek) { \
* dumping of the process results in another error..
*/
-static int aout_core_dump(long signr, struct pt_regs * regs, struct file *file)
+static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit)
{
mm_segment_t fs;
int has_dumped = 0;
@@ -123,23 +123,19 @@ static int aout_core_dump(long signr, struct pt_regs * regs, struct file *file)
/* If the size of the dump file exceeds the rlimit, then see what would happen
if we wrote the stack, but not the data area. */
#ifdef __sparc__
- if ((dump.u_dsize+dump.u_ssize) >
- current->signal->rlim[RLIMIT_CORE].rlim_cur)
+ if ((dump.u_dsize + dump.u_ssize) > limit)
dump.u_dsize = 0;
#else
- if ((dump.u_dsize+dump.u_ssize+1) * PAGE_SIZE >
- current->signal->rlim[RLIMIT_CORE].rlim_cur)
+ if ((dump.u_dsize + dump.u_ssize+1) * PAGE_SIZE > limit)
dump.u_dsize = 0;
#endif
/* Make sure we have enough room to write the stack and data areas. */
#ifdef __sparc__
- if ((dump.u_ssize) >
- current->signal->rlim[RLIMIT_CORE].rlim_cur)
+ if (dump.u_ssize > limit)
dump.u_ssize = 0;
#else
- if ((dump.u_ssize+1) * PAGE_SIZE >
- current->signal->rlim[RLIMIT_CORE].rlim_cur)
+ if ((dump.u_ssize + 1) * PAGE_SIZE > limit)
dump.u_ssize = 0;
#endif
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index b1013f34085d..ba8de7ca260b 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -52,7 +52,7 @@ static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, i
* don't even try.
*/
#if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE)
-static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file);
+static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit);
#else
#define elf_core_dump NULL
#endif
@@ -151,6 +151,14 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
struct vm_area_struct *vma;
/*
+ * In some cases (e.g. Hyper-Threading), we want to avoid L1
+ * evictions by the processes running on the same package. One
+ * thing we can do is to shuffle the initial stack for them.
+ */
+
+ p = arch_align_stack(p);
+
+ /*
* If this architecture has a platform capability string, copy it
* to userspace. In some cases (Sparc), this info is impossible
* for userspace to get any other way, in others (i386) it is
@@ -160,14 +168,6 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
if (k_platform) {
size_t len = strlen(k_platform) + 1;
- /*
- * In some cases (e.g. Hyper-Threading), we want to avoid L1
- * evictions by the processes running on the same package. One
- * thing we can do is to shuffle the initial stack for them.
- */
-
- p = arch_align_stack(p);
-
u_platform = (elf_addr_t __user *)STACK_ALLOC(p, len);
if (__copy_to_user(u_platform, k_platform, len))
return -EFAULT;
@@ -175,6 +175,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
/* Create the ELF interpreter info */
elf_info = (elf_addr_t *)current->mm->saved_auxv;
+ /* update AT_VECTOR_SIZE_BASE if the number of NEW_AUX_ENT() changes */
#define NEW_AUX_ENT(id, val) \
do { \
elf_info[ei_index++] = id; \
@@ -185,6 +186,8 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
/*
* ARCH_DLINFO must come first so PPC can do its special alignment of
* AUXV.
+ * update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT() in
+ * ARCH_DLINFO changes
*/
ARCH_DLINFO;
#endif
@@ -730,6 +733,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
/* Some simple consistency checks for the interpreter */
if (elf_interpreter) {
+ static int warn;
interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
/* Now figure out which format our binary is */
@@ -741,6 +745,13 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
if (memcmp(loc->interp_elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
interpreter_type &= ~INTERPRETER_ELF;
+ if (interpreter_type == INTERPRETER_AOUT && warn < 10) {
+ printk(KERN_WARNING "a.out ELF interpreter %s is "
+ "deprecated and will not be supported "
+ "after Linux 2.6.25\n", elf_interpreter);
+ warn++;
+ }
+
retval = -ELIBBAD;
if (!interpreter_type)
goto out_free_dentry;
@@ -1193,35 +1204,68 @@ static int dump_seek(struct file *file, loff_t off)
}
/*
- * Decide whether a segment is worth dumping; default is yes to be
- * sure (missing info is worse than too much; etc).
- * Personally I'd include everything, and use the coredump limit...
- *
- * I think we should skip something. But I am not sure how. H.J.
+ * Decide what to dump of a segment, part, all or none.
*/
-static int maydump(struct vm_area_struct *vma, unsigned long mm_flags)
+static unsigned long vma_dump_size(struct vm_area_struct *vma,
+ unsigned long mm_flags)
{
/* The vma can be set up to tell us the answer directly. */
if (vma->vm_flags & VM_ALWAYSDUMP)
- return 1;
+ goto whole;
/* Do not dump I/O mapped devices or special mappings */
if (vma->vm_flags & (VM_IO | VM_RESERVED))
return 0;
+#define FILTER(type) (mm_flags & (1UL << MMF_DUMP_##type))
+
/* By default, dump shared memory if mapped from an anonymous file. */
if (vma->vm_flags & VM_SHARED) {
- if (vma->vm_file->f_path.dentry->d_inode->i_nlink == 0)
- return test_bit(MMF_DUMP_ANON_SHARED, &mm_flags);
- else
- return test_bit(MMF_DUMP_MAPPED_SHARED, &mm_flags);
+ if (vma->vm_file->f_path.dentry->d_inode->i_nlink == 0 ?
+ FILTER(ANON_SHARED) : FILTER(MAPPED_SHARED))
+ goto whole;
+ return 0;
}
- /* By default, if it hasn't been written to, don't write it out. */
- if (!vma->anon_vma)
- return test_bit(MMF_DUMP_MAPPED_PRIVATE, &mm_flags);
+ /* Dump segments that have been written to. */
+ if (vma->anon_vma && FILTER(ANON_PRIVATE))
+ goto whole;
+ if (vma->vm_file == NULL)
+ return 0;
+
+ if (FILTER(MAPPED_PRIVATE))
+ goto whole;
- return test_bit(MMF_DUMP_ANON_PRIVATE, &mm_flags);
+ /*
+ * If this looks like the beginning of a DSO or executable mapping,
+ * check for an ELF header. If we find one, dump the first page to
+ * aid in determining what was mapped here.
+ */
+ if (FILTER(ELF_HEADERS) && vma->vm_file != NULL && vma->vm_pgoff == 0) {
+ u32 __user *header = (u32 __user *) vma->vm_start;
+ u32 word;
+ /*
+ * Doing it this way gets the constant folded by GCC.
+ */
+ union {
+ u32 cmp;
+ char elfmag[SELFMAG];
+ } magic;
+ BUILD_BUG_ON(SELFMAG != sizeof word);
+ magic.elfmag[EI_MAG0] = ELFMAG0;
+ magic.elfmag[EI_MAG1] = ELFMAG1;
+ magic.elfmag[EI_MAG2] = ELFMAG2;
+ magic.elfmag[EI_MAG3] = ELFMAG3;
+ if (get_user(word, header) == 0 && word == magic.cmp)
+ return PAGE_SIZE;
+ }
+
+#undef FILTER
+
+ return 0;
+
+whole:
+ return vma->vm_end - vma->vm_start;
}
/* An ELF note in memory */
@@ -1339,10 +1383,10 @@ static void fill_prstatus(struct elf_prstatus *prstatus,
prstatus->pr_info.si_signo = prstatus->pr_cursig = signr;
prstatus->pr_sigpend = p->pending.signal.sig[0];
prstatus->pr_sighold = p->blocked.sig[0];
- prstatus->pr_pid = p->pid;
- prstatus->pr_ppid = p->parent->pid;
- prstatus->pr_pgrp = process_group(p);
- prstatus->pr_sid = process_session(p);
+ prstatus->pr_pid = task_pid_vnr(p);
+ prstatus->pr_ppid = task_pid_vnr(p->parent);
+ prstatus->pr_pgrp = task_pgrp_vnr(p);
+ prstatus->pr_sid = task_session_vnr(p);
if (thread_group_leader(p)) {
/*
* This is the record for the group leader. Add in the
@@ -1385,10 +1429,10 @@ static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
psinfo->pr_psargs[i] = ' ';
psinfo->pr_psargs[len] = 0;
- psinfo->pr_pid = p->pid;
- psinfo->pr_ppid = p->parent->pid;
- psinfo->pr_pgrp = process_group(p);
- psinfo->pr_sid = process_session(p);
+ psinfo->pr_pid = task_pid_vnr(p);
+ psinfo->pr_ppid = task_pid_vnr(p->parent);
+ psinfo->pr_pgrp = task_pgrp_vnr(p);
+ psinfo->pr_sid = task_session_vnr(p);
i = p->state ? ffz(~p->state) + 1 : 0;
psinfo->pr_state = i;
@@ -1411,7 +1455,7 @@ struct elf_thread_status
elf_fpregset_t fpu; /* NT_PRFPREG */
struct task_struct *thread;
#ifdef ELF_CORE_COPY_XFPREGS
- elf_fpxregset_t xfpu; /* NT_PRXFPREG */
+ elf_fpxregset_t xfpu; /* ELF_CORE_XFPREG_TYPE */
#endif
struct memelfnote notes[3];
int num_notes;
@@ -1446,8 +1490,8 @@ static int elf_dump_thread_status(long signr, struct elf_thread_status *t)
#ifdef ELF_CORE_COPY_XFPREGS
if (elf_core_copy_task_xfpregs(p, &t->xfpu)) {
- fill_note(&t->notes[2], "LINUX", NT_PRXFPREG, sizeof(t->xfpu),
- &t->xfpu);
+ fill_note(&t->notes[2], "LINUX", ELF_CORE_XFPREG_TYPE,
+ sizeof(t->xfpu), &t->xfpu);
t->num_notes++;
sz += notesize(&t->notes[2]);
}
@@ -1488,7 +1532,7 @@ static struct vm_area_struct *next_vma(struct vm_area_struct *this_vma,
* and then they are actually written out. If we run out of core limit
* we just truncate.
*/
-static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
+static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit)
{
#define NUM_NOTES 6
int has_dumped = 0;
@@ -1499,7 +1543,6 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
struct vm_area_struct *vma, *gate_vma;
struct elfhdr *elf = NULL;
loff_t offset = 0, dataoff, foffset;
- unsigned long limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
int numnote;
struct memelfnote *notes = NULL;
struct elf_prstatus *prstatus = NULL; /* NT_PRSTATUS */
@@ -1621,7 +1664,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
#ifdef ELF_CORE_COPY_XFPREGS
if (elf_core_copy_task_xfpregs(current, xfpu))
fill_note(notes + numnote++,
- "LINUX", NT_PRXFPREG, sizeof(*xfpu), xfpu);
+ "LINUX", ELF_CORE_XFPREG_TYPE, sizeof(*xfpu), xfpu);
#endif
fs = get_fs();
@@ -1662,16 +1705,13 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
for (vma = first_vma(current, gate_vma); vma != NULL;
vma = next_vma(vma, gate_vma)) {
struct elf_phdr phdr;
- size_t sz;
-
- sz = vma->vm_end - vma->vm_start;
phdr.p_type = PT_LOAD;
phdr.p_offset = offset;
phdr.p_vaddr = vma->vm_start;
phdr.p_paddr = 0;
- phdr.p_filesz = maydump(vma, mm_flags) ? sz : 0;
- phdr.p_memsz = sz;
+ phdr.p_filesz = vma_dump_size(vma, mm_flags);
+ phdr.p_memsz = vma->vm_end - vma->vm_start;
offset += phdr.p_filesz;
phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0;
if (vma->vm_flags & VM_WRITE)
@@ -1711,13 +1751,11 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
for (vma = first_vma(current, gate_vma); vma != NULL;
vma = next_vma(vma, gate_vma)) {
unsigned long addr;
+ unsigned long end;
- if (!maydump(vma, mm_flags))
- continue;
+ end = vma->vm_start + vma_dump_size(vma, mm_flags);
- for (addr = vma->vm_start;
- addr < vma->vm_end;
- addr += PAGE_SIZE) {
+ for (addr = vma->vm_start; addr < end; addr += PAGE_SIZE) {
struct page *page;
struct vm_area_struct *vma;
@@ -1725,7 +1763,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
&page, &vma) <= 0) {
DUMP_SEEK(PAGE_SIZE);
} else {
- if (page == ZERO_PAGE(addr)) {
+ if (page == ZERO_PAGE(0)) {
if (!dump_seek(file, PAGE_SIZE)) {
page_cache_release(page);
goto end_coredump;
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index 2f5d8dbe676d..32649f2a1654 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -75,7 +75,7 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *,
struct file *, struct mm_struct *);
#if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE)
-static int elf_fdpic_core_dump(long, struct pt_regs *, struct file *);
+static int elf_fdpic_core_dump(long, struct pt_regs *, struct file *, unsigned long limit);
#endif
static struct linux_binfmt elf_fdpic_format = {
@@ -1342,10 +1342,10 @@ static void fill_prstatus(struct elf_prstatus *prstatus,
prstatus->pr_info.si_signo = prstatus->pr_cursig = signr;
prstatus->pr_sigpend = p->pending.signal.sig[0];
prstatus->pr_sighold = p->blocked.sig[0];
- prstatus->pr_pid = p->pid;
- prstatus->pr_ppid = p->parent->pid;
- prstatus->pr_pgrp = process_group(p);
- prstatus->pr_sid = process_session(p);
+ prstatus->pr_pid = task_pid_vnr(p);
+ prstatus->pr_ppid = task_pid_vnr(p->parent);
+ prstatus->pr_pgrp = task_pgrp_vnr(p);
+ prstatus->pr_sid = task_session_vnr(p);
if (thread_group_leader(p)) {
/*
* This is the record for the group leader. Add in the
@@ -1391,10 +1391,10 @@ static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
psinfo->pr_psargs[i] = ' ';
psinfo->pr_psargs[len] = 0;
- psinfo->pr_pid = p->pid;
- psinfo->pr_ppid = p->parent->pid;
- psinfo->pr_pgrp = process_group(p);
- psinfo->pr_sid = process_session(p);
+ psinfo->pr_pid = task_pid_vnr(p);
+ psinfo->pr_ppid = task_pid_vnr(p->parent);
+ psinfo->pr_pgrp = task_pgrp_vnr(p);
+ psinfo->pr_sid = task_session_vnr(p);
i = p->state ? ffz(~p->state) + 1 : 0;
psinfo->pr_state = i;
@@ -1417,7 +1417,7 @@ struct elf_thread_status
elf_fpregset_t fpu; /* NT_PRFPREG */
struct task_struct *thread;
#ifdef ELF_CORE_COPY_XFPREGS
- elf_fpxregset_t xfpu; /* NT_PRXFPREG */
+ elf_fpxregset_t xfpu; /* ELF_CORE_XFPREG_TYPE */
#endif
struct memelfnote notes[3];
int num_notes;
@@ -1453,8 +1453,8 @@ static int elf_dump_thread_status(long signr, struct elf_thread_status *t)
#ifdef ELF_CORE_COPY_XFPREGS
if (elf_core_copy_task_xfpregs(p, &t->xfpu)) {
- fill_note(&t->notes[2], "LINUX", NT_PRXFPREG, sizeof(t->xfpu),
- &t->xfpu);
+ fill_note(&t->notes[2], "LINUX", ELF_CORE_XFPREG_TYPE,
+ sizeof(t->xfpu), &t->xfpu);
t->num_notes++;
sz += notesize(&t->notes[2]);
}
@@ -1488,7 +1488,7 @@ static int elf_fdpic_dump_segments(struct file *file, size_t *size,
&page, &vma) <= 0) {
DUMP_SEEK(file->f_pos + PAGE_SIZE);
}
- else if (page == ZERO_PAGE(addr)) {
+ else if (page == ZERO_PAGE(0)) {
page_cache_release(page);
DUMP_SEEK(file->f_pos + PAGE_SIZE);
}
@@ -1552,7 +1552,7 @@ static int elf_fdpic_dump_segments(struct file *file, size_t *size,
* we just truncate.
*/
static int elf_fdpic_core_dump(long signr, struct pt_regs *regs,
- struct file *file)
+ struct file *file, unsigned long limit)
{
#define NUM_NOTES 6
int has_dumped = 0;
@@ -1563,7 +1563,6 @@ static int elf_fdpic_core_dump(long signr, struct pt_regs *regs,
struct vm_area_struct *vma;
struct elfhdr *elf = NULL;
loff_t offset = 0, dataoff;
- unsigned long limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
int numnote;
struct memelfnote *notes = NULL;
struct elf_prstatus *prstatus = NULL; /* NT_PRSTATUS */
@@ -1690,7 +1689,7 @@ static int elf_fdpic_core_dump(long signr, struct pt_regs *regs,
#ifdef ELF_CORE_COPY_XFPREGS
if (elf_core_copy_task_xfpregs(current, xfpu))
fill_note(notes + numnote++,
- "LINUX", NT_PRXFPREG, sizeof(*xfpu), xfpu);
+ "LINUX", ELF_CORE_XFPREG_TYPE, sizeof(*xfpu), xfpu);
#endif
fs = get_fs();
diff --git a/fs/binfmt_em86.c b/fs/binfmt_em86.c
index 576dd7de2278..f95ae9789c91 100644
--- a/fs/binfmt_em86.c
+++ b/fs/binfmt_em86.c
@@ -2,7 +2,7 @@
* linux/fs/binfmt_em86.c
*
* Based on linux/fs/binfmt_script.c
- * Copyright (C) 1996 Martin von Löwis
+ * Copyright (C) 1996 Martin von Löwis
* original #!-checking implemented by tytso.
*
* em86 changes Copyright (C) 1997 Jim Paradis
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index fcb3405bb14e..33764fd6db66 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -75,7 +75,7 @@ static int load_flat_shared_library(int id, struct lib_info *p);
#endif
static int load_flat_binary(struct linux_binprm *, struct pt_regs * regs);
-static int flat_core_dump(long signr, struct pt_regs * regs, struct file *file);
+static int flat_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit);
static struct linux_binfmt flat_format = {
.module = THIS_MODULE,
@@ -90,7 +90,7 @@ static struct linux_binfmt flat_format = {
* Currently only a stub-function.
*/
-static int flat_core_dump(long signr, struct pt_regs * regs, struct file *file)
+static int flat_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit)
{
printk("Process %s:%d received signr %d and should have core dumped\n",
current->comm, current->pid, (int) signr);
@@ -113,7 +113,7 @@ static unsigned long create_flat_tables(
char * p = (char*)pp;
int argc = bprm->argc;
int envc = bprm->envc;
- char dummy;
+ char uninitialized_var(dummy);
sp = (unsigned long *) ((-(unsigned long)sizeof(char *))&(unsigned long) p);
@@ -290,7 +290,6 @@ out_free_buf:
kfree(buf);
out_free:
kfree(strm.workspace);
-out:
return retval;
}
@@ -459,7 +458,9 @@ static int load_flat_file(struct linux_binprm * bprm,
printk("BINFMT_FLAT: Loading file: %s\n", bprm->filename);
if (rev != FLAT_VERSION && rev != OLD_FLAT_VERSION) {
- printk("BINFMT_FLAT: bad flat file version 0x%x (supported 0x%x and 0x%x)\n", rev, FLAT_VERSION, OLD_FLAT_VERSION);
+ printk("BINFMT_FLAT: bad flat file version 0x%x (supported "
+ "0x%lx and 0x%lx)\n",
+ rev, FLAT_VERSION, OLD_FLAT_VERSION);
ret = -ENOEXEC;
goto err;
}
@@ -515,7 +516,8 @@ static int load_flat_file(struct linux_binprm * bprm,
/*
* calculate the extra space we need to map in
*/
- extra = max(bss_len + stack_len, relocs * sizeof(unsigned long));
+ extra = max_t(unsigned long, bss_len + stack_len,
+ relocs * sizeof(unsigned long));
/*
* there are a couple of cases here, the separate code/data
@@ -546,7 +548,7 @@ static int load_flat_file(struct linux_binprm * bprm,
PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0);
/* Remap to use all availabe slack region space */
if (realdatastart && (realdatastart < (unsigned long)-4096)) {
- reallen = ksize(realdatastart);
+ reallen = ksize((void *)realdatastart);
if (reallen > len) {
realdatastart = do_mremap(realdatastart, len,
reallen, MREMAP_FIXED, realdatastart);
@@ -598,7 +600,7 @@ static int load_flat_file(struct linux_binprm * bprm,
PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);
/* Remap to use all availabe slack region space */
if (textpos && (textpos < (unsigned long) -4096)) {
- reallen = ksize(textpos);
+ reallen = ksize((void *)textpos);
if (reallen > len) {
textpos = do_mremap(textpos, len, reallen,
MREMAP_FIXED, textpos);
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index 42e94b3ab7be..b53c7e5f41bb 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -1,7 +1,7 @@
/*
* binfmt_misc.c
*
- * Copyright (C) 1997 Richard Günther
+ * Copyright (C) 1997 Richard Günther
*
* binfmt_misc detects binaries via a magic or filename extension and invokes
* a specified wrapper. This should obsolete binfmt_java, binfmt_em86 and
diff --git a/fs/binfmt_script.c b/fs/binfmt_script.c
index 4d0e0f6d3273..ab33939b12a7 100644
--- a/fs/binfmt_script.c
+++ b/fs/binfmt_script.c
@@ -1,7 +1,7 @@
/*
* linux/fs/binfmt_script.c
*
- * Copyright (C) 1996 Martin von Löwis
+ * Copyright (C) 1996 Martin von Löwis
* original #!-checking implemented by tytso.
*/
diff --git a/fs/binfmt_som.c b/fs/binfmt_som.c
index 5bcdaaf4eae0..9208c41209f9 100644
--- a/fs/binfmt_som.c
+++ b/fs/binfmt_som.c
@@ -44,7 +44,7 @@ static int load_som_library(struct file *);
* don't even try.
*/
#if 0
-static int som_core_dump(long signr, struct pt_regs * regs);
+static int som_core_dump(long signr, struct pt_regs *regs, unsigned long limit);
#else
#define som_core_dump NULL
#endif
diff --git a/fs/bio.c b/fs/bio.c
index 5f604f269dfa..d59ddbf79626 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -109,11 +109,14 @@ static inline struct bio_vec *bvec_alloc_bs(gfp_t gfp_mask, int nr, unsigned lon
void bio_free(struct bio *bio, struct bio_set *bio_set)
{
- const int pool_idx = BIO_POOL_IDX(bio);
+ if (bio->bi_io_vec) {
+ const int pool_idx = BIO_POOL_IDX(bio);
- BIO_BUG_ON(pool_idx >= BIOVEC_NR_POOLS);
+ BIO_BUG_ON(pool_idx >= BIOVEC_NR_POOLS);
+
+ mempool_free(bio->bi_io_vec, bio_set->bvec_pools[pool_idx]);
+ }
- mempool_free(bio->bi_io_vec, bio_set->bvec_pools[pool_idx]);
mempool_free(bio, bio_set->bio_pool);
}
@@ -127,21 +130,9 @@ static void bio_fs_destructor(struct bio *bio)
void bio_init(struct bio *bio)
{
- bio->bi_next = NULL;
- bio->bi_bdev = NULL;
+ memset(bio, 0, sizeof(*bio));
bio->bi_flags = 1 << BIO_UPTODATE;
- bio->bi_rw = 0;
- bio->bi_vcnt = 0;
- bio->bi_idx = 0;
- bio->bi_phys_segments = 0;
- bio->bi_hw_segments = 0;
- bio->bi_hw_front_size = 0;
- bio->bi_hw_back_size = 0;
- bio->bi_size = 0;
- bio->bi_max_vecs = 0;
- bio->bi_end_io = NULL;
atomic_set(&bio->bi_cnt, 1);
- bio->bi_private = NULL;
}
/**
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 6339a30879b7..993f78c55221 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -378,14 +378,26 @@ static int blkdev_readpage(struct file * file, struct page * page)
return block_read_full_page(page, blkdev_get_block);
}
-static int blkdev_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
+static int blkdev_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
{
- return block_prepare_write(page, from, to, blkdev_get_block);
+ *pagep = NULL;
+ return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
+ blkdev_get_block);
}
-static int blkdev_commit_write(struct file *file, struct page *page, unsigned from, unsigned to)
+static int blkdev_write_end(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata)
{
- return block_commit_write(page, from, to);
+ int ret;
+ ret = block_write_end(file, mapping, pos, len, copied, page, fsdata);
+
+ unlock_page(page);
+ page_cache_release(page);
+
+ return ret;
}
/*
@@ -453,7 +465,7 @@ static void bdev_destroy_inode(struct inode *inode)
kmem_cache_free(bdev_cachep, bdi);
}
-static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
+static void init_once(struct kmem_cache * cachep, void *foo)
{
struct bdev_inode *ei = (struct bdev_inode *) foo;
struct block_device *bdev = &ei->bdev;
@@ -1327,8 +1339,8 @@ const struct address_space_operations def_blk_aops = {
.readpage = blkdev_readpage,
.writepage = blkdev_writepage,
.sync_page = block_sync_page,
- .prepare_write = blkdev_prepare_write,
- .commit_write = blkdev_commit_write,
+ .write_begin = blkdev_write_begin,
+ .write_end = blkdev_write_end,
.writepages = generic_writepages,
.direct_IO = blkdev_direct_IO,
};
diff --git a/fs/buffer.c b/fs/buffer.c
index 75b51dfa5e03..7249e014819e 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -110,10 +110,14 @@ static void buffer_io_error(struct buffer_head *bh)
}
/*
- * Default synchronous end-of-IO handler.. Just mark it up-to-date and
- * unlock the buffer. This is what ll_rw_block uses too.
+ * End-of-IO handler helper function which does not touch the bh after
+ * unlocking it.
+ * Note: unlock_buffer() sort-of does touch the bh after unlocking it, but
+ * a race there is benign: unlock_buffer() only use the bh's address for
+ * hashing after unlocking the buffer, so it doesn't actually touch the bh
+ * itself.
*/
-void end_buffer_read_sync(struct buffer_head *bh, int uptodate)
+static void __end_buffer_read_notouch(struct buffer_head *bh, int uptodate)
{
if (uptodate) {
set_buffer_uptodate(bh);
@@ -122,6 +126,15 @@ void end_buffer_read_sync(struct buffer_head *bh, int uptodate)
clear_buffer_uptodate(bh);
}
unlock_buffer(bh);
+}
+
+/*
+ * Default synchronous end-of-IO handler.. Just mark it up-to-date and
+ * unlock the buffer. This is what ll_rw_block uses too.
+ */
+void end_buffer_read_sync(struct buffer_head *bh, int uptodate)
+{
+ __end_buffer_read_notouch(bh, uptodate);
put_bh(bh);
}
@@ -697,6 +710,8 @@ static int __set_page_dirty(struct page *page,
if (mapping_cap_account_dirty(mapping)) {
__inc_zone_page_state(page, NR_FILE_DIRTY);
+ __inc_bdi_stat(mapping->backing_dev_info,
+ BDI_RECLAIMABLE);
task_io_account_write(PAGE_CACHE_SIZE);
}
radix_tree_tag_set(&mapping->page_tree,
@@ -1715,7 +1730,6 @@ done:
* The page and buffer_heads can be released at any time from
* here on.
*/
- wbc->pages_skipped++; /* We didn't write this page */
}
return err;
@@ -1757,6 +1771,48 @@ recover:
goto done;
}
+/*
+ * If a page has any new buffers, zero them out here, and mark them uptodate
+ * and dirty so they'll be written out (in order to prevent uninitialised
+ * block data from leaking). And clear the new bit.
+ */
+void page_zero_new_buffers(struct page *page, unsigned from, unsigned to)
+{
+ unsigned int block_start, block_end;
+ struct buffer_head *head, *bh;
+
+ BUG_ON(!PageLocked(page));
+ if (!page_has_buffers(page))
+ return;
+
+ bh = head = page_buffers(page);
+ block_start = 0;
+ do {
+ block_end = block_start + bh->b_size;
+
+ if (buffer_new(bh)) {
+ if (block_end > from && block_start < to) {
+ if (!PageUptodate(page)) {
+ unsigned start, size;
+
+ start = max(from, block_start);
+ size = min(to, block_end) - start;
+
+ zero_user_page(page, start, size, KM_USER0);
+ set_buffer_uptodate(bh);
+ }
+
+ clear_buffer_new(bh);
+ mark_buffer_dirty(bh);
+ }
+ }
+
+ block_start = block_end;
+ bh = bh->b_this_page;
+ } while (bh != head);
+}
+EXPORT_SYMBOL(page_zero_new_buffers);
+
static int __block_prepare_write(struct inode *inode, struct page *page,
unsigned from, unsigned to, get_block_t *get_block)
{
@@ -1800,7 +1856,9 @@ static int __block_prepare_write(struct inode *inode, struct page *page,
unmap_underlying_metadata(bh->b_bdev,
bh->b_blocknr);
if (PageUptodate(page)) {
+ clear_buffer_new(bh);
set_buffer_uptodate(bh);
+ mark_buffer_dirty(bh);
continue;
}
if (block_end > to || block_start < from) {
@@ -1839,38 +1897,8 @@ static int __block_prepare_write(struct inode *inode, struct page *page,
if (!buffer_uptodate(*wait_bh))
err = -EIO;
}
- if (!err) {
- bh = head;
- do {
- if (buffer_new(bh))
- clear_buffer_new(bh);
- } while ((bh = bh->b_this_page) != head);
- return 0;
- }
- /* Error case: */
- /*
- * Zero out any newly allocated blocks to avoid exposing stale
- * data. If BH_New is set, we know that the block was newly
- * allocated in the above loop.
- */
- bh = head;
- block_start = 0;
- do {
- block_end = block_start+blocksize;
- if (block_end <= from)
- goto next_bh;
- if (block_start >= to)
- break;
- if (buffer_new(bh)) {
- clear_buffer_new(bh);
- zero_user_page(page, block_start, bh->b_size, KM_USER0);
- set_buffer_uptodate(bh);
- mark_buffer_dirty(bh);
- }
-next_bh:
- block_start = block_end;
- bh = bh->b_this_page;
- } while (bh != head);
+ if (unlikely(err))
+ page_zero_new_buffers(page, from, to);
return err;
}
@@ -1895,6 +1923,7 @@ static int __block_commit_write(struct inode *inode, struct page *page,
set_buffer_uptodate(bh);
mark_buffer_dirty(bh);
}
+ clear_buffer_new(bh);
}
/*
@@ -1909,6 +1938,130 @@ static int __block_commit_write(struct inode *inode, struct page *page,
}
/*
+ * block_write_begin takes care of the basic task of block allocation and
+ * bringing partial write blocks uptodate first.
+ *
+ * If *pagep is not NULL, then block_write_begin uses the locked page
+ * at *pagep rather than allocating its own. In this case, the page will
+ * not be unlocked or deallocated on failure.
+ */
+int block_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata,
+ get_block_t *get_block)
+{
+ struct inode *inode = mapping->host;
+ int status = 0;
+ struct page *page;
+ pgoff_t index;
+ unsigned start, end;
+ int ownpage = 0;
+
+ index = pos >> PAGE_CACHE_SHIFT;
+ start = pos & (PAGE_CACHE_SIZE - 1);
+ end = start + len;
+
+ page = *pagep;
+ if (page == NULL) {
+ ownpage = 1;
+ page = __grab_cache_page(mapping, index);
+ if (!page) {
+ status = -ENOMEM;
+ goto out;
+ }
+ *pagep = page;
+ } else
+ BUG_ON(!PageLocked(page));
+
+ status = __block_prepare_write(inode, page, start, end, get_block);
+ if (unlikely(status)) {
+ ClearPageUptodate(page);
+
+ if (ownpage) {
+ unlock_page(page);
+ page_cache_release(page);
+ *pagep = NULL;
+
+ /*
+ * prepare_write() may have instantiated a few blocks
+ * outside i_size. Trim these off again. Don't need
+ * i_size_read because we hold i_mutex.
+ */
+ if (pos + len > inode->i_size)
+ vmtruncate(inode, inode->i_size);
+ }
+ goto out;
+ }
+
+out:
+ return status;
+}
+EXPORT_SYMBOL(block_write_begin);
+
+int block_write_end(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata)
+{
+ struct inode *inode = mapping->host;
+ unsigned start;
+
+ start = pos & (PAGE_CACHE_SIZE - 1);
+
+ if (unlikely(copied < len)) {
+ /*
+ * The buffers that were written will now be uptodate, so we
+ * don't have to worry about a readpage reading them and
+ * overwriting a partial write. However if we have encountered
+ * a short write and only partially written into a buffer, it
+ * will not be marked uptodate, so a readpage might come in and
+ * destroy our partial write.
+ *
+ * Do the simplest thing, and just treat any short write to a
+ * non uptodate page as a zero-length write, and force the
+ * caller to redo the whole thing.
+ */
+ if (!PageUptodate(page))
+ copied = 0;
+
+ page_zero_new_buffers(page, start+copied, start+len);
+ }
+ flush_dcache_page(page);
+
+ /* This could be a short (even 0-length) commit */
+ __block_commit_write(inode, page, start, start+copied);
+
+ return copied;
+}
+EXPORT_SYMBOL(block_write_end);
+
+int generic_write_end(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata)
+{
+ struct inode *inode = mapping->host;
+
+ copied = block_write_end(file, mapping, pos, len, copied, page, fsdata);
+
+ /*
+ * No need to use i_size_read() here, the i_size
+ * cannot change under us because we hold i_mutex.
+ *
+ * But it's important to update i_size while still holding page lock:
+ * page writeout could otherwise come in and zero beyond i_size.
+ */
+ if (pos+copied > inode->i_size) {
+ i_size_write(inode, pos+copied);
+ mark_inode_dirty(inode);
+ }
+
+ unlock_page(page);
+ page_cache_release(page);
+
+ return copied;
+}
+EXPORT_SYMBOL(generic_write_end);
+
+/*
* Generic "read page" function for block devices that have the normal
* get_block functionality. This is most of the block device filesystems.
* Reads the page asynchronously --- the unlock_buffer() and
@@ -2004,14 +2157,14 @@ int block_read_full_page(struct page *page, get_block_t *get_block)
}
/* utility function for filesystems that need to do work on expanding
- * truncates. Uses prepare/commit_write to allow the filesystem to
+ * truncates. Uses filesystem pagecache writes to allow the filesystem to
* deal with the hole.
*/
-static int __generic_cont_expand(struct inode *inode, loff_t size,
- pgoff_t index, unsigned int offset)
+int generic_cont_expand_simple(struct inode *inode, loff_t size)
{
struct address_space *mapping = inode->i_mapping;
struct page *page;
+ void *fsdata;
unsigned long limit;
int err;
@@ -2024,140 +2177,115 @@ static int __generic_cont_expand(struct inode *inode, loff_t size,
if (size > inode->i_sb->s_maxbytes)
goto out;
- err = -ENOMEM;
- page = grab_cache_page(mapping, index);
- if (!page)
- goto out;
- err = mapping->a_ops->prepare_write(NULL, page, offset, offset);
- if (err) {
- /*
- * ->prepare_write() may have instantiated a few blocks
- * outside i_size. Trim these off again.
- */
- unlock_page(page);
- page_cache_release(page);
- vmtruncate(inode, inode->i_size);
+ err = pagecache_write_begin(NULL, mapping, size, 0,
+ AOP_FLAG_UNINTERRUPTIBLE|AOP_FLAG_CONT_EXPAND,
+ &page, &fsdata);
+ if (err)
goto out;
- }
- err = mapping->a_ops->commit_write(NULL, page, offset, offset);
+ err = pagecache_write_end(NULL, mapping, size, 0, 0, page, fsdata);
+ BUG_ON(err > 0);
- unlock_page(page);
- page_cache_release(page);
- if (err > 0)
- err = 0;
out:
return err;
}
-int generic_cont_expand(struct inode *inode, loff_t size)
+int cont_expand_zero(struct file *file, struct address_space *mapping,
+ loff_t pos, loff_t *bytes)
{
- pgoff_t index;
- unsigned int offset;
+ struct inode *inode = mapping->host;
+ unsigned blocksize = 1 << inode->i_blkbits;
+ struct page *page;
+ void *fsdata;
+ pgoff_t index, curidx;
+ loff_t curpos;
+ unsigned zerofrom, offset, len;
+ int err = 0;
- offset = (size & (PAGE_CACHE_SIZE - 1)); /* Within page */
+ index = pos >> PAGE_CACHE_SHIFT;
+ offset = pos & ~PAGE_CACHE_MASK;
- /* ugh. in prepare/commit_write, if from==to==start of block, we
- ** skip the prepare. make sure we never send an offset for the start
- ** of a block
- */
- if ((offset & (inode->i_sb->s_blocksize - 1)) == 0) {
- /* caller must handle this extra byte. */
- offset++;
- }
- index = size >> PAGE_CACHE_SHIFT;
+ while (index > (curidx = (curpos = *bytes)>>PAGE_CACHE_SHIFT)) {
+ zerofrom = curpos & ~PAGE_CACHE_MASK;
+ if (zerofrom & (blocksize-1)) {
+ *bytes |= (blocksize-1);
+ (*bytes)++;
+ }
+ len = PAGE_CACHE_SIZE - zerofrom;
- return __generic_cont_expand(inode, size, index, offset);
-}
+ err = pagecache_write_begin(file, mapping, curpos, len,
+ AOP_FLAG_UNINTERRUPTIBLE,
+ &page, &fsdata);
+ if (err)
+ goto out;
+ zero_user_page(page, zerofrom, len, KM_USER0);
+ err = pagecache_write_end(file, mapping, curpos, len, len,
+ page, fsdata);
+ if (err < 0)
+ goto out;
+ BUG_ON(err != len);
+ err = 0;
+ }
-int generic_cont_expand_simple(struct inode *inode, loff_t size)
-{
- loff_t pos = size - 1;
- pgoff_t index = pos >> PAGE_CACHE_SHIFT;
- unsigned int offset = (pos & (PAGE_CACHE_SIZE - 1)) + 1;
+ /* page covers the boundary, find the boundary offset */
+ if (index == curidx) {
+ zerofrom = curpos & ~PAGE_CACHE_MASK;
+ /* if we will expand the thing last block will be filled */
+ if (offset <= zerofrom) {
+ goto out;
+ }
+ if (zerofrom & (blocksize-1)) {
+ *bytes |= (blocksize-1);
+ (*bytes)++;
+ }
+ len = offset - zerofrom;
- /* prepare/commit_write can handle even if from==to==start of block. */
- return __generic_cont_expand(inode, size, index, offset);
+ err = pagecache_write_begin(file, mapping, curpos, len,
+ AOP_FLAG_UNINTERRUPTIBLE,
+ &page, &fsdata);
+ if (err)
+ goto out;
+ zero_user_page(page, zerofrom, len, KM_USER0);
+ err = pagecache_write_end(file, mapping, curpos, len, len,
+ page, fsdata);
+ if (err < 0)
+ goto out;
+ BUG_ON(err != len);
+ err = 0;
+ }
+out:
+ return err;
}
/*
* For moronic filesystems that do not allow holes in file.
* We may have to extend the file.
*/
-
-int cont_prepare_write(struct page *page, unsigned offset,
- unsigned to, get_block_t *get_block, loff_t *bytes)
+int cont_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata,
+ get_block_t *get_block, loff_t *bytes)
{
- struct address_space *mapping = page->mapping;
struct inode *inode = mapping->host;
- struct page *new_page;
- pgoff_t pgpos;
- long status;
- unsigned zerofrom;
unsigned blocksize = 1 << inode->i_blkbits;
+ unsigned zerofrom;
+ int err;
- while(page->index > (pgpos = *bytes>>PAGE_CACHE_SHIFT)) {
- status = -ENOMEM;
- new_page = grab_cache_page(mapping, pgpos);
- if (!new_page)
- goto out;
- /* we might sleep */
- if (*bytes>>PAGE_CACHE_SHIFT != pgpos) {
- unlock_page(new_page);
- page_cache_release(new_page);
- continue;
- }
- zerofrom = *bytes & ~PAGE_CACHE_MASK;
- if (zerofrom & (blocksize-1)) {
- *bytes |= (blocksize-1);
- (*bytes)++;
- }
- status = __block_prepare_write(inode, new_page, zerofrom,
- PAGE_CACHE_SIZE, get_block);
- if (status)
- goto out_unmap;
- zero_user_page(new_page, zerofrom, PAGE_CACHE_SIZE - zerofrom,
- KM_USER0);
- generic_commit_write(NULL, new_page, zerofrom, PAGE_CACHE_SIZE);
- unlock_page(new_page);
- page_cache_release(new_page);
- }
-
- if (page->index < pgpos) {
- /* completely inside the area */
- zerofrom = offset;
- } else {
- /* page covers the boundary, find the boundary offset */
- zerofrom = *bytes & ~PAGE_CACHE_MASK;
-
- /* if we will expand the thing last block will be filled */
- if (to > zerofrom && (zerofrom & (blocksize-1))) {
- *bytes |= (blocksize-1);
- (*bytes)++;
- }
+ err = cont_expand_zero(file, mapping, pos, bytes);
+ if (err)
+ goto out;
- /* starting below the boundary? Nothing to zero out */
- if (offset <= zerofrom)
- zerofrom = offset;
- }
- status = __block_prepare_write(inode, page, zerofrom, to, get_block);
- if (status)
- goto out1;
- if (zerofrom < offset) {
- zero_user_page(page, zerofrom, offset - zerofrom, KM_USER0);
- __block_commit_write(inode, page, zerofrom, offset);
+ zerofrom = *bytes & ~PAGE_CACHE_MASK;
+ if (pos+len > *bytes && zerofrom & (blocksize-1)) {
+ *bytes |= (blocksize-1);
+ (*bytes)++;
}
- return 0;
-out1:
- ClearPageUptodate(page);
- return status;
-out_unmap:
- ClearPageUptodate(new_page);
- unlock_page(new_page);
- page_cache_release(new_page);
+ *pagep = NULL;
+ err = block_write_begin(file, mapping, pos, len,
+ flags, pagep, fsdata, get_block);
out:
- return status;
+ return err;
}
int block_prepare_write(struct page *page, unsigned from, unsigned to,
@@ -2242,81 +2370,129 @@ out_unlock:
}
/*
- * nobh_prepare_write()'s prereads are special: the buffer_heads are freed
+ * nobh_write_begin()'s prereads are special: the buffer_heads are freed
* immediately, while under the page lock. So it needs a special end_io
* handler which does not touch the bh after unlocking it.
- *
- * Note: unlock_buffer() sort-of does touch the bh after unlocking it, but
- * a race there is benign: unlock_buffer() only use the bh's address for
- * hashing after unlocking the buffer, so it doesn't actually touch the bh
- * itself.
*/
static void end_buffer_read_nobh(struct buffer_head *bh, int uptodate)
{
- if (uptodate) {
- set_buffer_uptodate(bh);
- } else {
- /* This happens, due to failed READA attempts. */
- clear_buffer_uptodate(bh);
- }
- unlock_buffer(bh);
+ __end_buffer_read_notouch(bh, uptodate);
+}
+
+/*
+ * Attach the singly-linked list of buffers created by nobh_write_begin, to
+ * the page (converting it to circular linked list and taking care of page
+ * dirty races).
+ */
+static void attach_nobh_buffers(struct page *page, struct buffer_head *head)
+{
+ struct buffer_head *bh;
+
+ BUG_ON(!PageLocked(page));
+
+ spin_lock(&page->mapping->private_lock);
+ bh = head;
+ do {
+ if (PageDirty(page))
+ set_buffer_dirty(bh);
+ if (!bh->b_this_page)
+ bh->b_this_page = head;
+ bh = bh->b_this_page;
+ } while (bh != head);
+ attach_page_buffers(page, head);
+ spin_unlock(&page->mapping->private_lock);
}
/*
* On entry, the page is fully not uptodate.
* On exit the page is fully uptodate in the areas outside (from,to)
*/
-int nobh_prepare_write(struct page *page, unsigned from, unsigned to,
+int nobh_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata,
get_block_t *get_block)
{
- struct inode *inode = page->mapping->host;
+ struct inode *inode = mapping->host;
const unsigned blkbits = inode->i_blkbits;
const unsigned blocksize = 1 << blkbits;
- struct buffer_head map_bh;
- struct buffer_head *read_bh[MAX_BUF_PER_PAGE];
+ struct buffer_head *head, *bh;
+ struct page *page;
+ pgoff_t index;
+ unsigned from, to;
unsigned block_in_page;
- unsigned block_start;
+ unsigned block_start, block_end;
sector_t block_in_file;
char *kaddr;
int nr_reads = 0;
- int i;
int ret = 0;
int is_mapped_to_disk = 1;
+ index = pos >> PAGE_CACHE_SHIFT;
+ from = pos & (PAGE_CACHE_SIZE - 1);
+ to = from + len;
+
+ page = __grab_cache_page(mapping, index);
+ if (!page)
+ return -ENOMEM;
+ *pagep = page;
+ *fsdata = NULL;
+
+ if (page_has_buffers(page)) {
+ unlock_page(page);
+ page_cache_release(page);
+ *pagep = NULL;
+ return block_write_begin(file, mapping, pos, len, flags, pagep,
+ fsdata, get_block);
+ }
+
if (PageMappedToDisk(page))
return 0;
+ /*
+ * Allocate buffers so that we can keep track of state, and potentially
+ * attach them to the page if an error occurs. In the common case of
+ * no error, they will just be freed again without ever being attached
+ * to the page (which is all OK, because we're under the page lock).
+ *
+ * Be careful: the buffer linked list is a NULL terminated one, rather
+ * than the circular one we're used to.
+ */
+ head = alloc_page_buffers(page, blocksize, 0);
+ if (!head) {
+ ret = -ENOMEM;
+ goto out_release;
+ }
+
block_in_file = (sector_t)page->index << (PAGE_CACHE_SHIFT - blkbits);
- map_bh.b_page = page;
/*
* We loop across all blocks in the page, whether or not they are
* part of the affected region. This is so we can discover if the
* page is fully mapped-to-disk.
*/
- for (block_start = 0, block_in_page = 0;
+ for (block_start = 0, block_in_page = 0, bh = head;
block_start < PAGE_CACHE_SIZE;
- block_in_page++, block_start += blocksize) {
- unsigned block_end = block_start + blocksize;
+ block_in_page++, block_start += blocksize, bh = bh->b_this_page) {
int create;
- map_bh.b_state = 0;
+ block_end = block_start + blocksize;
+ bh->b_state = 0;
create = 1;
if (block_start >= to)
create = 0;
- map_bh.b_size = blocksize;
ret = get_block(inode, block_in_file + block_in_page,
- &map_bh, create);
+ bh, create);
if (ret)
goto failed;
- if (!buffer_mapped(&map_bh))
+ if (!buffer_mapped(bh))
is_mapped_to_disk = 0;
- if (buffer_new(&map_bh))
- unmap_underlying_metadata(map_bh.b_bdev,
- map_bh.b_blocknr);
- if (PageUptodate(page))
+ if (buffer_new(bh))
+ unmap_underlying_metadata(bh->b_bdev, bh->b_blocknr);
+ if (PageUptodate(page)) {
+ set_buffer_uptodate(bh);
continue;
- if (buffer_new(&map_bh) || !buffer_mapped(&map_bh)) {
+ }
+ if (buffer_new(bh) || !buffer_mapped(bh)) {
kaddr = kmap_atomic(page, KM_USER0);
if (block_start < from)
memset(kaddr+block_start, 0, from-block_start);
@@ -2326,49 +2502,26 @@ int nobh_prepare_write(struct page *page, unsigned from, unsigned to,
kunmap_atomic(kaddr, KM_USER0);
continue;
}
- if (buffer_uptodate(&map_bh))
+ if (buffer_uptodate(bh))
continue; /* reiserfs does this */
if (block_start < from || block_end > to) {
- struct buffer_head *bh = alloc_buffer_head(GFP_NOFS);
-
- if (!bh) {
- ret = -ENOMEM;
- goto failed;
- }
- bh->b_state = map_bh.b_state;
- atomic_set(&bh->b_count, 0);
- bh->b_this_page = NULL;
- bh->b_page = page;
- bh->b_blocknr = map_bh.b_blocknr;
- bh->b_size = blocksize;
- bh->b_data = (char *)(long)block_start;
- bh->b_bdev = map_bh.b_bdev;
- bh->b_private = NULL;
- read_bh[nr_reads++] = bh;
+ lock_buffer(bh);
+ bh->b_end_io = end_buffer_read_nobh;
+ submit_bh(READ, bh);
+ nr_reads++;
}
}
if (nr_reads) {
- struct buffer_head *bh;
-
/*
* The page is locked, so these buffers are protected from
* any VM or truncate activity. Hence we don't need to care
* for the buffer_head refcounts.
*/
- for (i = 0; i < nr_reads; i++) {
- bh = read_bh[i];
- lock_buffer(bh);
- bh->b_end_io = end_buffer_read_nobh;
- submit_bh(READ, bh);
- }
- for (i = 0; i < nr_reads; i++) {
- bh = read_bh[i];
+ for (bh = head; bh; bh = bh->b_this_page) {
wait_on_buffer(bh);
if (!buffer_uptodate(bh))
ret = -EIO;
- free_buffer_head(bh);
- read_bh[i] = NULL;
}
if (ret)
goto failed;
@@ -2377,44 +2530,69 @@ int nobh_prepare_write(struct page *page, unsigned from, unsigned to,
if (is_mapped_to_disk)
SetPageMappedToDisk(page);
+ *fsdata = head; /* to be released by nobh_write_end */
+
return 0;
failed:
- for (i = 0; i < nr_reads; i++) {
- if (read_bh[i])
- free_buffer_head(read_bh[i]);
- }
-
+ BUG_ON(!ret);
/*
- * Error recovery is pretty slack. Clear the page and mark it dirty
- * so we'll later zero out any blocks which _were_ allocated.
+ * Error recovery is a bit difficult. We need to zero out blocks that
+ * were newly allocated, and dirty them to ensure they get written out.
+ * Buffers need to be attached to the page at this point, otherwise
+ * the handling of potential IO errors during writeout would be hard
+ * (could try doing synchronous writeout, but what if that fails too?)
*/
- zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0);
- SetPageUptodate(page);
- set_page_dirty(page);
+ attach_nobh_buffers(page, head);
+ page_zero_new_buffers(page, from, to);
+
+out_release:
+ unlock_page(page);
+ page_cache_release(page);
+ *pagep = NULL;
+
+ if (pos + len > inode->i_size)
+ vmtruncate(inode, inode->i_size);
+
return ret;
}
-EXPORT_SYMBOL(nobh_prepare_write);
+EXPORT_SYMBOL(nobh_write_begin);
-/*
- * Make sure any changes to nobh_commit_write() are reflected in
- * nobh_truncate_page(), since it doesn't call commit_write().
- */
-int nobh_commit_write(struct file *file, struct page *page,
- unsigned from, unsigned to)
+int nobh_write_end(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata)
{
struct inode *inode = page->mapping->host;
- loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
+ struct buffer_head *head = fsdata;
+ struct buffer_head *bh;
+
+ if (!PageMappedToDisk(page)) {
+ if (unlikely(copied < len) && !page_has_buffers(page))
+ attach_nobh_buffers(page, head);
+ if (page_has_buffers(page))
+ return generic_write_end(file, mapping, pos, len,
+ copied, page, fsdata);
+ }
SetPageUptodate(page);
set_page_dirty(page);
- if (pos > inode->i_size) {
- i_size_write(inode, pos);
+ if (pos+copied > inode->i_size) {
+ i_size_write(inode, pos+copied);
mark_inode_dirty(inode);
}
- return 0;
+
+ unlock_page(page);
+ page_cache_release(page);
+
+ while (head) {
+ bh = head;
+ head = head->b_this_page;
+ free_buffer_head(bh);
+ }
+
+ return copied;
}
-EXPORT_SYMBOL(nobh_commit_write);
+EXPORT_SYMBOL(nobh_write_end);
/*
* nobh_writepage() - based on block_full_write_page() except
@@ -2467,44 +2645,79 @@ out:
}
EXPORT_SYMBOL(nobh_writepage);
-/*
- * This function assumes that ->prepare_write() uses nobh_prepare_write().
- */
-int nobh_truncate_page(struct address_space *mapping, loff_t from)
+int nobh_truncate_page(struct address_space *mapping,
+ loff_t from, get_block_t *get_block)
{
- struct inode *inode = mapping->host;
- unsigned blocksize = 1 << inode->i_blkbits;
pgoff_t index = from >> PAGE_CACHE_SHIFT;
unsigned offset = from & (PAGE_CACHE_SIZE-1);
- unsigned to;
+ unsigned blocksize;
+ sector_t iblock;
+ unsigned length, pos;
+ struct inode *inode = mapping->host;
struct page *page;
- const struct address_space_operations *a_ops = mapping->a_ops;
- int ret = 0;
+ struct buffer_head map_bh;
+ int err;
- if ((offset & (blocksize - 1)) == 0)
- goto out;
+ blocksize = 1 << inode->i_blkbits;
+ length = offset & (blocksize - 1);
+
+ /* Block boundary? Nothing to do */
+ if (!length)
+ return 0;
+
+ length = blocksize - length;
+ iblock = (sector_t)index << (PAGE_CACHE_SHIFT - inode->i_blkbits);
- ret = -ENOMEM;
page = grab_cache_page(mapping, index);
+ err = -ENOMEM;
if (!page)
goto out;
- to = (offset + blocksize) & ~(blocksize - 1);
- ret = a_ops->prepare_write(NULL, page, offset, to);
- if (ret == 0) {
- zero_user_page(page, offset, PAGE_CACHE_SIZE - offset,
- KM_USER0);
- /*
- * It would be more correct to call aops->commit_write()
- * here, but this is more efficient.
- */
- SetPageUptodate(page);
- set_page_dirty(page);
+ if (page_has_buffers(page)) {
+has_buffers:
+ unlock_page(page);
+ page_cache_release(page);
+ return block_truncate_page(mapping, from, get_block);
}
+
+ /* Find the buffer that contains "offset" */
+ pos = blocksize;
+ while (offset >= pos) {
+ iblock++;
+ pos += blocksize;
+ }
+
+ err = get_block(inode, iblock, &map_bh, 0);
+ if (err)
+ goto unlock;
+ /* unmapped? It's a hole - nothing to do */
+ if (!buffer_mapped(&map_bh))
+ goto unlock;
+
+ /* Ok, it's mapped. Make sure it's up-to-date */
+ if (!PageUptodate(page)) {
+ err = mapping->a_ops->readpage(NULL, page);
+ if (err) {
+ page_cache_release(page);
+ goto out;
+ }
+ lock_page(page);
+ if (!PageUptodate(page)) {
+ err = -EIO;
+ goto unlock;
+ }
+ if (page_has_buffers(page))
+ goto has_buffers;
+ }
+ zero_user_page(page, offset, length, KM_USER0);
+ set_page_dirty(page);
+ err = 0;
+
+unlock:
unlock_page(page);
page_cache_release(page);
out:
- return ret;
+ return err;
}
EXPORT_SYMBOL(nobh_truncate_page);
@@ -2956,7 +3169,8 @@ static void recalc_bh_state(void)
struct buffer_head *alloc_buffer_head(gfp_t gfp_flags)
{
- struct buffer_head *ret = kmem_cache_zalloc(bh_cachep, gfp_flags);
+ struct buffer_head *ret = kmem_cache_zalloc(bh_cachep,
+ set_migrateflags(gfp_flags, __GFP_RECLAIMABLE));
if (ret) {
INIT_LIST_HEAD(&ret->b_assoc_buffers);
get_cpu_var(bh_accounting).nr++;
@@ -3024,14 +3238,13 @@ EXPORT_SYMBOL(block_read_full_page);
EXPORT_SYMBOL(block_sync_page);
EXPORT_SYMBOL(block_truncate_page);
EXPORT_SYMBOL(block_write_full_page);
-EXPORT_SYMBOL(cont_prepare_write);
+EXPORT_SYMBOL(cont_write_begin);
EXPORT_SYMBOL(end_buffer_read_sync);
EXPORT_SYMBOL(end_buffer_write_sync);
EXPORT_SYMBOL(file_fsync);
EXPORT_SYMBOL(fsync_bdev);
EXPORT_SYMBOL(generic_block_bmap);
EXPORT_SYMBOL(generic_commit_write);
-EXPORT_SYMBOL(generic_cont_expand);
EXPORT_SYMBOL(generic_cont_expand_simple);
EXPORT_SYMBOL(init_buffer);
EXPORT_SYMBOL(invalidate_bdev);
diff --git a/fs/char_dev.c b/fs/char_dev.c
index bbbf07baa145..c3bfa76765c4 100644
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -545,6 +545,7 @@ static struct kobject *base_probe(dev_t dev, int *part, void *data)
void __init chrdev_init(void)
{
cdev_map = kobj_map_init(base_probe, &chrdevs_lock);
+ bdi_init(&directly_mappable_cdev_bdi);
}
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index bed6215c0794..64dd22239b21 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,3 +1,28 @@
+Version 1.52
+------------
+Fix oops on second mount to server when null auth is used.
+
+Version 1.51
+------------
+Fix memory leak in statfs when mounted to very old servers (e.g.
+Windows 9x). Add new feature "POSIX open" which allows servers
+which support the current POSIX Extensions to provide better semantics
+(e.g. delete for open files opened with posix open). Take into
+account umask on posix mkdir not just older style mkdir. Add
+ability to mount to IPC$ share (which allows CIFS named pipes to be
+opened, read and written as if they were files). When 1st tree
+connect fails (e.g. due to signing negotiation failure) fix
+leak that causes cifsd not to stop and rmmod to fail to cleanup
+cifs_request_buffers pool. Fix problem with POSIX Open/Mkdir on
+bigendian architectures. Fix possible memory corruption when
+EAGAIN returned on kern_recvmsg. Return better error if server
+requires packet signing but client has disabled it. When mounted
+with cifsacl mount option - mode bits are approximated based
+on the contents of the ACL of the file or directory. When cifs
+mount helper is missing convert make sure that UNC name
+has backslash (not forward slash) between ip address of server
+and the share name.
+
Version 1.50
------------
Fix NTLMv2 signing. NFS server mounted over cifs works (if cifs mount is
@@ -6,7 +31,10 @@ done with "serverino" mount option). Add support for POSIX Unlink
Samba supports newer POSIX CIFS Protocol Extensions). Add "nounix"
mount option to allow disabling the CIFS Unix Extensions for just
that mount. Fix hang on spinlock in find_writable_file (race when
-reopening file after session crash).
+reopening file after session crash). Byte range unlock request to
+windows server could unlock more bytes (on server copy of file)
+than intended if start of unlock request is well before start of
+a previous byte range lock that we issued.
Version 1.49
------------
diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile
index 6ecd9d6ba3f3..45e42fb97c19 100644
--- a/fs/cifs/Makefile
+++ b/fs/cifs/Makefile
@@ -3,4 +3,9 @@
#
obj-$(CONFIG_CIFS) += cifs.o
-cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o sess.o export.o
+cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \
+ link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o \
+ md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o \
+ readdir.o ioctl.o sess.o export.o cifsacl.o
+
+cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o
diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c
index f50a88d58f78..bcda2c6b6a04 100644
--- a/fs/cifs/asn1.c
+++ b/fs/cifs/asn1.c
@@ -77,8 +77,12 @@
#define SPNEGO_OID_LEN 7
#define NTLMSSP_OID_LEN 10
+#define KRB5_OID_LEN 7
+#define MSKRB5_OID_LEN 7
static unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 };
static unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 };
+static unsigned long KRB5_OID[7] = { 1, 2, 840, 113554, 1, 2, 2 };
+static unsigned long MSKRB5_OID[7] = { 1, 2, 840, 48018, 1, 2, 2 };
/*
* ASN.1 context.
@@ -385,10 +389,9 @@ asn1_oid_decode(struct asn1_ctx *ctx,
unsigned long *optr;
size = eoc - ctx->pointer + 1;
- *oid = kmalloc(size * sizeof (unsigned long), GFP_ATOMIC);
- if (*oid == NULL) {
+ *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC);
+ if (*oid == NULL)
return 0;
- }
optr = *oid;
@@ -458,6 +461,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
unsigned long *oid = NULL;
unsigned int cls, con, tag, oidlen, rc;
int use_ntlmssp = FALSE;
+ int use_kerberos = FALSE;
*secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default*/
@@ -546,18 +550,28 @@ decode_negTokenInit(unsigned char *security_blob, int length,
return 0;
}
if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
- rc = asn1_oid_decode(&ctx, end, &oid, &oidlen);
- if (rc) {
+ if (asn1_oid_decode(&ctx, end, &oid, &oidlen)) {
+
cFYI(1,
("OID len = %d oid = 0x%lx 0x%lx "
"0x%lx 0x%lx",
oidlen, *oid, *(oid + 1),
*(oid + 2), *(oid + 3)));
- rc = compare_oid(oid, oidlen,
- NTLMSSP_OID, NTLMSSP_OID_LEN);
- kfree(oid);
- if (rc)
+
+ if (compare_oid(oid, oidlen,
+ MSKRB5_OID,
+ MSKRB5_OID_LEN))
+ use_kerberos = TRUE;
+ else if (compare_oid(oid, oidlen,
+ KRB5_OID,
+ KRB5_OID_LEN))
+ use_kerberos = TRUE;
+ else if (compare_oid(oid, oidlen,
+ NTLMSSP_OID,
+ NTLMSSP_OID_LEN))
use_ntlmssp = TRUE;
+
+ kfree(oid);
}
} else {
cFYI(1, ("Should be an oid what is going on?"));
@@ -581,9 +595,8 @@ decode_negTokenInit(unsigned char *security_blob, int length,
return 0;
} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
|| (tag != ASN1_SEQ)) {
- cFYI(1,
- ("Exit 6 cls = %d con = %d tag = %d end = %p (%d)",
- cls, con, tag, end, *end));
+ cFYI(1, ("cls = %d con = %d tag = %d end = %p (%d)",
+ cls, con, tag, end, *end));
}
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
@@ -611,12 +624,10 @@ decode_negTokenInit(unsigned char *security_blob, int length,
ctx.pointer)); /* is this UTF-8 or ASCII? */
}
- /* if (use_kerberos)
- *secType = Kerberos
- else */
- if (use_ntlmssp) {
+ if (use_kerberos)
+ *secType = Kerberos;
+ else if (use_ntlmssp)
*secType = NTLMSSP;
- }
return 1;
}
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index 1bf8cf522ad6..73c4c419663c 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -209,13 +209,16 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
i++;
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
- length =
- sprintf(buf,
- "\n%d) %s Uses: %d Type: %s DevInfo: 0x%x "
- "Attributes: 0x%x\nPathComponentMax: %d Status: %d",
- i, tcon->treeName,
- atomic_read(&tcon->useCount),
- tcon->nativeFileSystem,
+ length = sprintf(buf, "\n%d) %s Uses: %d ", i,
+ tcon->treeName, atomic_read(&tcon->useCount));
+ buf += length;
+ if (tcon->nativeFileSystem) {
+ length = sprintf(buf, "Type: %s ",
+ tcon->nativeFileSystem);
+ buf += length;
+ }
+ length = sprintf(buf, "DevInfo: 0x%x Attributes: 0x%x"
+ "\nPathComponentMax: %d Status: %d",
le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics),
le32_to_cpu(tcon->fsAttrInfo.Attributes),
le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
@@ -876,11 +879,16 @@ security_flags_write(struct file *file, const char __user *buffer,
if (count < 3) {
/* single char or single char followed by null */
c = flags_string[0];
- if (c == '0' || c == 'n' || c == 'N')
+ if (c == '0' || c == 'n' || c == 'N') {
extended_security = CIFSSEC_DEF; /* default */
- else if (c == '1' || c == 'y' || c == 'Y')
+ return count;
+ } else if (c == '1' || c == 'y' || c == 'Y') {
extended_security = CIFSSEC_MAX;
- return count;
+ return count;
+ } else if (!isdigit(c)) {
+ cERROR(1, ("invalid flag %c", c));
+ return -EINVAL;
+ }
}
/* else we have a number */
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c
new file mode 100644
index 000000000000..ad54a3a6e434
--- /dev/null
+++ b/fs/cifs/cifs_spnego.c
@@ -0,0 +1,128 @@
+/*
+ * fs/cifs/cifs_spnego.c -- SPNEGO upcall management for CIFS
+ *
+ * Copyright (c) 2007 Red Hat, Inc.
+ * Author(s): Jeff Layton (jlayton@redhat.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/list.h>
+#include <linux/string.h>
+#include <keys/user-type.h>
+#include <linux/key-type.h>
+#include "cifsglob.h"
+#include "cifs_spnego.h"
+#include "cifs_debug.h"
+
+/* create a new cifs key */
+static int
+cifs_spnego_key_instantiate(struct key *key, const void *data, size_t datalen)
+{
+ char *payload;
+ int ret;
+
+ ret = -ENOMEM;
+ payload = kmalloc(datalen, GFP_KERNEL);
+ if (!payload)
+ goto error;
+
+ /* attach the data */
+ memcpy(payload, data, datalen);
+ rcu_assign_pointer(key->payload.data, payload);
+ ret = 0;
+
+error:
+ return ret;
+}
+
+static void
+cifs_spnego_key_destroy(struct key *key)
+{
+ kfree(key->payload.data);
+}
+
+
+/*
+ * keytype for CIFS spnego keys
+ */
+struct key_type cifs_spnego_key_type = {
+ .name = "cifs.spnego",
+ .instantiate = cifs_spnego_key_instantiate,
+ .match = user_match,
+ .destroy = cifs_spnego_key_destroy,
+ .describe = user_describe,
+};
+
+/* get a key struct with a SPNEGO security blob, suitable for session setup */
+struct key *
+cifs_get_spnego_key(struct cifsSesInfo *sesInfo, const char *hostname)
+{
+ struct TCP_Server_Info *server = sesInfo->server;
+ char *description, *dp;
+ size_t desc_len;
+ struct key *spnego_key;
+
+
+ /* version + ;ip{4|6}= + address + ;host=hostname +
+ ;sec= + ;uid= + NULL */
+ desc_len = 4 + 5 + 32 + 1 + 5 + strlen(hostname) +
+ strlen(";sec=krb5") + 7 + sizeof(uid_t)*2 + 1;
+ spnego_key = ERR_PTR(-ENOMEM);
+ description = kzalloc(desc_len, GFP_KERNEL);
+ if (description == NULL)
+ goto out;
+
+ dp = description;
+ /* start with version and hostname portion of UNC string */
+ spnego_key = ERR_PTR(-EINVAL);
+ sprintf(dp, "0x%2.2x;host=%s;", CIFS_SPNEGO_UPCALL_VERSION,
+ hostname);
+ dp = description + strlen(description);
+
+ /* add the server address */
+ if (server->addr.sockAddr.sin_family == AF_INET)
+ sprintf(dp, "ip4=" NIPQUAD_FMT,
+ NIPQUAD(server->addr.sockAddr.sin_addr));
+ else if (server->addr.sockAddr.sin_family == AF_INET6)
+ sprintf(dp, "ip6=" NIP6_SEQFMT,
+ NIP6(server->addr.sockAddr6.sin6_addr));
+ else
+ goto out;
+
+ dp = description + strlen(description);
+
+ /* for now, only sec=krb5 is valid */
+ if (server->secType == Kerberos)
+ sprintf(dp, ";sec=krb5");
+ else
+ goto out;
+
+ dp = description + strlen(description);
+ sprintf(dp, ";uid=0x%x", sesInfo->linux_uid);
+
+ cFYI(1, ("key description = %s", description));
+ spnego_key = request_key(&cifs_spnego_key_type, description, "");
+
+ if (cifsFYI && !IS_ERR(spnego_key)) {
+ struct cifs_spnego_msg *msg = spnego_key->payload.data;
+ cifs_dump_mem("SPNEGO reply blob:", msg->data,
+ msg->secblob_len + msg->sesskey_len);
+ }
+
+out:
+ kfree(description);
+ return spnego_key;
+}
diff --git a/fs/cifs/cifs_spnego.h b/fs/cifs/cifs_spnego.h
new file mode 100644
index 000000000000..f443f3b35134
--- /dev/null
+++ b/fs/cifs/cifs_spnego.h
@@ -0,0 +1,46 @@
+/*
+ * fs/cifs/cifs_spnego.h -- SPNEGO upcall management for CIFS
+ *
+ * Copyright (c) 2007 Red Hat, Inc.
+ * Author(s): Jeff Layton (jlayton@redhat.com)
+ * Steve French (sfrench@us.ibm.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _CIFS_SPNEGO_H
+#define _CIFS_SPNEGO_H
+
+#define CIFS_SPNEGO_UPCALL_VERSION 1
+
+/*
+ * The version field should always be set to CIFS_SPNEGO_UPCALL_VERSION.
+ * The flags field is for future use. The request-key callout should set
+ * sesskey_len and secblob_len, and then concatenate the SessKey+SecBlob
+ * and stuff it in the data field.
+ */
+struct cifs_spnego_msg {
+ uint32_t version;
+ uint32_t flags;
+ uint32_t sesskey_len;
+ uint32_t secblob_len;
+ uint8_t data[1];
+};
+
+#ifdef __KERNEL__
+extern struct key_type cifs_spnego_key_type;
+#endif /* KERNEL */
+
+#endif /* _CIFS_SPNEGO_H */
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
new file mode 100644
index 000000000000..dabbce00712b
--- /dev/null
+++ b/fs/cifs/cifsacl.c
@@ -0,0 +1,531 @@
+/*
+ * fs/cifs/cifsacl.c
+ *
+ * Copyright (C) International Business Machines Corp., 2007
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ * Contains the routines for mapping CIFS/NTFS ACLs
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/fs.h>
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsacl.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+
+
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+
+static struct cifs_wksid wksidarr[NUM_WK_SIDS] = {
+ {{1, 0, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} }, "null user"},
+ {{1, 1, {0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0} }, "nobody"},
+ {{1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(11), 0, 0, 0, 0} }, "net-users"},
+ {{1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(18), 0, 0, 0, 0} }, "sys"},
+ {{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(544), 0, 0, 0} }, "root"},
+ {{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(545), 0, 0, 0} }, "users"},
+ {{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(546), 0, 0, 0} }, "guest"} }
+;
+
+
+/* security id for everyone */
+static const struct cifs_sid sid_everyone = {
+ 1, 1, {0, 0, 0, 0, 0, 1}, {0} };
+/* group users */
+static const struct cifs_sid sid_user =
+ {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
+
+
+int match_sid(struct cifs_sid *ctsid)
+{
+ int i, j;
+ int num_subauth, num_sat, num_saw;
+ struct cifs_sid *cwsid;
+
+ if (!ctsid)
+ return (-1);
+
+ for (i = 0; i < NUM_WK_SIDS; ++i) {
+ cwsid = &(wksidarr[i].cifssid);
+
+ /* compare the revision */
+ if (ctsid->revision != cwsid->revision)
+ continue;
+
+ /* compare all of the six auth values */
+ for (j = 0; j < 6; ++j) {
+ if (ctsid->authority[j] != cwsid->authority[j])
+ break;
+ }
+ if (j < 6)
+ continue; /* all of the auth values did not match */
+
+ /* compare all of the subauth values if any */
+ num_sat = ctsid->num_subauth;
+ num_saw = cwsid->num_subauth;
+ num_subauth = num_sat < num_saw ? num_sat : num_saw;
+ if (num_subauth) {
+ for (j = 0; j < num_subauth; ++j) {
+ if (ctsid->sub_auth[j] != cwsid->sub_auth[j])
+ break;
+ }
+ if (j < num_subauth)
+ continue; /* all sub_auth values do not match */
+ }
+
+ cFYI(1, ("matching sid: %s\n", wksidarr[i].sidname));
+ return (0); /* sids compare/match */
+ }
+
+ cFYI(1, ("No matching sid"));
+ return (-1);
+}
+
+/* if the two SIDs (roughly equivalent to a UUID for a user or group) are
+ the same returns 1, if they do not match returns 0 */
+int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
+{
+ int i;
+ int num_subauth, num_sat, num_saw;
+
+ if ((!ctsid) || (!cwsid))
+ return (0);
+
+ /* compare the revision */
+ if (ctsid->revision != cwsid->revision)
+ return (0);
+
+ /* compare all of the six auth values */
+ for (i = 0; i < 6; ++i) {
+ if (ctsid->authority[i] != cwsid->authority[i])
+ return (0);
+ }
+
+ /* compare all of the subauth values if any */
+ num_sat = ctsid->num_subauth;
+ num_saw = cwsid->num_subauth;
+ num_subauth = num_sat < num_saw ? num_sat : num_saw;
+ if (num_subauth) {
+ for (i = 0; i < num_subauth; ++i) {
+ if (ctsid->sub_auth[i] != cwsid->sub_auth[i])
+ return (0);
+ }
+ }
+
+ return (1); /* sids compare/match */
+}
+
+/*
+ change posix mode to reflect permissions
+ pmode is the existing mode (we only want to overwrite part of this
+ bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
+*/
+static void access_flags_to_mode(__u32 ace_flags, int type, umode_t *pmode,
+ umode_t *pbits_to_set)
+{
+ /* the order of ACEs is important. The canonical order is to begin with
+ DENY entries followed by ALLOW, otherwise an allow entry could be
+ encountered first, making the subsequent deny entry like "dead code"
+ which would be superflous since Windows stops when a match is made
+ for the operation you are trying to perform for your user */
+
+ /* For deny ACEs we change the mask so that subsequent allow access
+ control entries do not turn on the bits we are denying */
+ if (type == ACCESS_DENIED) {
+ if (ace_flags & GENERIC_ALL) {
+ *pbits_to_set &= ~S_IRWXUGO;
+ }
+ if ((ace_flags & GENERIC_WRITE) ||
+ ((ace_flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
+ *pbits_to_set &= ~S_IWUGO;
+ if ((ace_flags & GENERIC_READ) ||
+ ((ace_flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
+ *pbits_to_set &= ~S_IRUGO;
+ if ((ace_flags & GENERIC_EXECUTE) ||
+ ((ace_flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
+ *pbits_to_set &= ~S_IXUGO;
+ return;
+ } else if (type != ACCESS_ALLOWED) {
+ cERROR(1, ("unknown access control type %d", type));
+ return;
+ }
+ /* else ACCESS_ALLOWED type */
+
+ if (ace_flags & GENERIC_ALL) {
+ *pmode |= (S_IRWXUGO & (*pbits_to_set));
+#ifdef CONFIG_CIFS_DEBUG2
+ cFYI(1, ("all perms"));
+#endif
+ return;
+ }
+ if ((ace_flags & GENERIC_WRITE) ||
+ ((ace_flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
+ *pmode |= (S_IWUGO & (*pbits_to_set));
+ if ((ace_flags & GENERIC_READ) ||
+ ((ace_flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
+ *pmode |= (S_IRUGO & (*pbits_to_set));
+ if ((ace_flags & GENERIC_EXECUTE) ||
+ ((ace_flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
+ *pmode |= (S_IXUGO & (*pbits_to_set));
+
+#ifdef CONFIG_CIFS_DEBUG2
+ cFYI(1, ("access flags 0x%x mode now 0x%x", ace_flags, *pmode));
+#endif
+ return;
+}
+
+/*
+ Generate access flags to reflect permissions mode is the existing mode.
+ This function is called for every ACE in the DACL whose SID matches
+ with either owner or group or everyone.
+*/
+
+static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
+ __u32 *pace_flags)
+{
+ /* reset access mask */
+ *pace_flags = 0x0;
+
+ /* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */
+ mode &= bits_to_use;
+
+ /* check for R/W/X UGO since we do not know whose flags
+ is this but we have cleared all the bits sans RWX for
+ either user or group or other as per bits_to_use */
+ if (mode & S_IRUGO)
+ *pace_flags |= SET_FILE_READ_RIGHTS;
+ if (mode & S_IWUGO)
+ *pace_flags |= SET_FILE_WRITE_RIGHTS;
+ if (mode & S_IXUGO)
+ *pace_flags |= SET_FILE_EXEC_RIGHTS;
+
+#ifdef CONFIG_CIFS_DEBUG2
+ cFYI(1, ("mode: 0x%x, access flags now 0x%x", mode, *pace_flags));
+#endif
+ return;
+}
+
+
+#ifdef CONFIG_CIFS_DEBUG2
+static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
+{
+ int num_subauth;
+
+ /* validate that we do not go past end of acl */
+
+ if (le16_to_cpu(pace->size) < 16) {
+ cERROR(1, ("ACE too small, %d", le16_to_cpu(pace->size)));
+ return;
+ }
+
+ if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
+ cERROR(1, ("ACL too small to parse ACE"));
+ return;
+ }
+
+ num_subauth = pace->sid.num_subauth;
+ if (num_subauth) {
+ int i;
+ cFYI(1, ("ACE revision %d num_auth %d type %d flags %d size %d",
+ pace->sid.revision, pace->sid.num_subauth, pace->type,
+ pace->flags, pace->size));
+ for (i = 0; i < num_subauth; ++i) {
+ cFYI(1, ("ACE sub_auth[%d]: 0x%x", i,
+ le32_to_cpu(pace->sid.sub_auth[i])));
+ }
+
+ /* BB add length check to make sure that we do not have huge
+ num auths and therefore go off the end */
+ }
+
+ return;
+}
+#endif
+
+
+static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
+ struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
+ struct inode *inode)
+{
+ int i;
+ int num_aces = 0;
+ int acl_size;
+ char *acl_base;
+ struct cifs_ace **ppace;
+
+ /* BB need to add parm so we can store the SID BB */
+
+ /* validate that we do not go past end of acl */
+ if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
+ cERROR(1, ("ACL too small to parse DACL"));
+ return;
+ }
+
+#ifdef CONFIG_CIFS_DEBUG2
+ cFYI(1, ("DACL revision %d size %d num aces %d",
+ le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
+ le32_to_cpu(pdacl->num_aces)));
+#endif
+
+ /* reset rwx permissions for user/group/other.
+ Also, if num_aces is 0 i.e. DACL has no ACEs,
+ user/group/other have no permissions */
+ inode->i_mode &= ~(S_IRWXUGO);
+
+ if (!pdacl) {
+ /* no DACL in the security descriptor, set
+ all the permissions for user/group/other */
+ inode->i_mode |= S_IRWXUGO;
+ return;
+ }
+ acl_base = (char *)pdacl;
+ acl_size = sizeof(struct cifs_acl);
+
+ num_aces = le32_to_cpu(pdacl->num_aces);
+ if (num_aces > 0) {
+ umode_t user_mask = S_IRWXU;
+ umode_t group_mask = S_IRWXG;
+ umode_t other_mask = S_IRWXO;
+
+ ppace = kmalloc(num_aces * sizeof(struct cifs_ace *),
+ GFP_KERNEL);
+
+/* cifscred->cecount = pdacl->num_aces;
+ cifscred->aces = kmalloc(num_aces *
+ sizeof(struct cifs_ace *), GFP_KERNEL);*/
+
+ for (i = 0; i < num_aces; ++i) {
+ ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
+#ifdef CONFIG_CIFS_DEBUG2
+ dump_ace(ppace[i], end_of_acl);
+#endif
+ if (compare_sids(&(ppace[i]->sid), pownersid))
+ access_flags_to_mode(ppace[i]->access_req,
+ ppace[i]->type,
+ &(inode->i_mode),
+ &user_mask);
+ if (compare_sids(&(ppace[i]->sid), pgrpsid))
+ access_flags_to_mode(ppace[i]->access_req,
+ ppace[i]->type,
+ &(inode->i_mode),
+ &group_mask);
+ if (compare_sids(&(ppace[i]->sid), &sid_everyone))
+ access_flags_to_mode(ppace[i]->access_req,
+ ppace[i]->type,
+ &(inode->i_mode),
+ &other_mask);
+
+/* memcpy((void *)(&(cifscred->aces[i])),
+ (void *)ppace[i],
+ sizeof(struct cifs_ace)); */
+
+ acl_base = (char *)ppace[i];
+ acl_size = le16_to_cpu(ppace[i]->size);
+ }
+
+ kfree(ppace);
+ }
+
+ return;
+}
+
+
+static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
+{
+ /* BB need to add parm so we can store the SID BB */
+
+ /* validate that we do not go past end of ACL - sid must be at least 8
+ bytes long (assuming no sub-auths - e.g. the null SID */
+ if (end_of_acl < (char *)psid + 8) {
+ cERROR(1, ("ACL too small to parse SID %p", psid));
+ return -EINVAL;
+ }
+
+ if (psid->num_subauth) {
+#ifdef CONFIG_CIFS_DEBUG2
+ int i;
+ cFYI(1, ("SID revision %d num_auth %d",
+ psid->revision, psid->num_subauth));
+
+ for (i = 0; i < psid->num_subauth; i++) {
+ cFYI(1, ("SID sub_auth[%d]: 0x%x ", i,
+ le32_to_cpu(psid->sub_auth[i])));
+ }
+
+ /* BB add length check to make sure that we do not have huge
+ num auths and therefore go off the end */
+ cFYI(1, ("RID 0x%x",
+ le32_to_cpu(psid->sub_auth[psid->num_subauth-1])));
+#endif
+ }
+
+ return 0;
+}
+
+
+/* Convert CIFS ACL to POSIX form */
+static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
+ struct inode *inode)
+{
+ int rc;
+ struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
+ struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
+ char *end_of_acl = ((char *)pntsd) + acl_len;
+ __u32 dacloffset;
+
+ if ((inode == NULL) || (pntsd == NULL))
+ return -EIO;
+
+ owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
+ le32_to_cpu(pntsd->osidoffset));
+ group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
+ le32_to_cpu(pntsd->gsidoffset));
+ dacloffset = le32_to_cpu(pntsd->dacloffset);
+ dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
+#ifdef CONFIG_CIFS_DEBUG2
+ cFYI(1, ("revision %d type 0x%x ooffset 0x%x goffset 0x%x "
+ "sacloffset 0x%x dacloffset 0x%x",
+ pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
+ le32_to_cpu(pntsd->gsidoffset),
+ le32_to_cpu(pntsd->sacloffset), dacloffset));
+#endif
+/* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */
+ rc = parse_sid(owner_sid_ptr, end_of_acl);
+ if (rc)
+ return rc;
+
+ rc = parse_sid(group_sid_ptr, end_of_acl);
+ if (rc)
+ return rc;
+
+ if (dacloffset)
+ parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
+ group_sid_ptr, inode);
+ else
+ cFYI(1, ("no ACL")); /* BB grant all or default perms? */
+
+/* cifscred->uid = owner_sid_ptr->rid;
+ cifscred->gid = group_sid_ptr->rid;
+ memcpy((void *)(&(cifscred->osid)), (void *)owner_sid_ptr,
+ sizeof(struct cifs_sid));
+ memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr,
+ sizeof(struct cifs_sid)); */
+
+
+ return (0);
+}
+
+
+/* Retrieve an ACL from the server */
+static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode,
+ const char *path)
+{
+ struct cifsFileInfo *open_file;
+ int unlock_file = FALSE;
+ int xid;
+ int rc = -EIO;
+ __u16 fid;
+ struct super_block *sb;
+ struct cifs_sb_info *cifs_sb;
+ struct cifs_ntsd *pntsd = NULL;
+
+ cFYI(1, ("get mode from ACL for %s", path));
+
+ if (inode == NULL)
+ return NULL;
+
+ xid = GetXid();
+ open_file = find_readable_file(CIFS_I(inode));
+ sb = inode->i_sb;
+ if (sb == NULL) {
+ FreeXid(xid);
+ return NULL;
+ }
+ cifs_sb = CIFS_SB(sb);
+
+ if (open_file) {
+ unlock_file = TRUE;
+ fid = open_file->netfid;
+ } else {
+ int oplock = FALSE;
+ /* open file */
+ rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN,
+ READ_CONTROL, 0, &fid, &oplock, NULL,
+ cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
+ CIFS_MOUNT_MAP_SPECIAL_CHR);
+ if (rc != 0) {
+ cERROR(1, ("Unable to open file to get ACL"));
+ FreeXid(xid);
+ return NULL;
+ }
+ }
+
+ rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen);
+ cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen));
+ if (unlock_file == TRUE)
+ atomic_dec(&open_file->wrtPending);
+ else
+ CIFSSMBClose(xid, cifs_sb->tcon, fid);
+
+ FreeXid(xid);
+ return pntsd;
+}
+
+/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
+void acl_to_uid_mode(struct inode *inode, const char *path)
+{
+ struct cifs_ntsd *pntsd = NULL;
+ u32 acllen = 0;
+ int rc = 0;
+
+#ifdef CONFIG_CIFS_DEBUG2
+ cFYI(1, ("converting ACL to mode for %s", path));
+#endif
+ pntsd = get_cifs_acl(&acllen, inode, path);
+
+ /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
+ if (pntsd)
+ rc = parse_sec_desc(pntsd, acllen, inode);
+ if (rc)
+ cFYI(1, ("parse sec desc failed rc = %d", rc));
+
+ kfree(pntsd);
+ return;
+}
+
+/* Convert mode bits to an ACL so we can update the ACL on the server */
+int mode_to_acl(struct inode *inode, const char *path)
+{
+ int rc = 0;
+ __u32 acllen = 0;
+ struct cifs_ntsd *pntsd = NULL;
+
+ cFYI(1, ("set ACL from mode for %s", path));
+
+ /* Get the security descriptor */
+ pntsd = get_cifs_acl(&acllen, inode, path);
+
+ /* Add/Modify the three ACEs for owner, group, everyone
+ while retaining the other ACEs */
+
+ /* Set the security descriptor */
+
+
+ kfree(pntsd);
+ return rc;
+}
+#endif /* CONFIG_CIFS_EXPERIMENTAL */
diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h
index 5eff35d6e564..93a7c3462ea2 100644
--- a/fs/cifs/cifsacl.h
+++ b/fs/cifs/cifsacl.h
@@ -1,7 +1,7 @@
/*
* fs/cifs/cifsacl.h
*
- * Copyright (c) International Business Machines Corp., 2005
+ * Copyright (c) International Business Machines Corp., 2007
* Author(s): Steve French (sfrench@us.ibm.com)
*
* This library is free software; you can redistribute it and/or modify
@@ -22,17 +22,62 @@
#ifndef _CIFSACL_H
#define _CIFSACL_H
+
+#define NUM_AUTHS 6 /* number of authority fields */
+#define NUM_SUBAUTHS 5 /* number of sub authority fields */
+#define NUM_WK_SIDS 7 /* number of well known sids */
+#define SIDNAMELENGTH 20 /* long enough for the ones we care about */
+
+#define READ_BIT 0x4
+#define WRITE_BIT 0x2
+#define EXEC_BIT 0x1
+
+#define UBITSHIFT 6
+#define GBITSHIFT 3
+
+#define ACCESS_ALLOWED 0
+#define ACCESS_DENIED 1
+
+struct cifs_ntsd {
+ __le16 revision; /* revision level */
+ __le16 type;
+ __le32 osidoffset;
+ __le32 gsidoffset;
+ __le32 sacloffset;
+ __le32 dacloffset;
+} __attribute__((packed));
+
struct cifs_sid {
__u8 revision; /* revision level */
- __u8 num_subauths;
+ __u8 num_subauth;
__u8 authority[6];
- __u32 sub_auth[4];
- /* next sub_auth if any ... */
+ __le32 sub_auth[5]; /* sub_auth[num_subauth] */
} __attribute__((packed));
-/* everyone */
-/* extern const struct cifs_sid sid_everyone;*/
-/* group users */
-/* extern const struct cifs_sid sid_user;*/
+struct cifs_acl {
+ __le16 revision; /* revision level */
+ __le16 size;
+ __le32 num_aces;
+} __attribute__((packed));
+
+struct cifs_ace {
+ __u8 type;
+ __u8 flags;
+ __le16 size;
+ __le32 access_req;
+ struct cifs_sid sid; /* ie UUID of user or group who gets these perms */
+} __attribute__((packed));
+
+struct cifs_wksid {
+ struct cifs_sid cifssid;
+ char sidname[SIDNAMELENGTH];
+} __attribute__((packed));
+
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+
+extern int match_sid(struct cifs_sid *);
+extern int compare_sids(const struct cifs_sid *, const struct cifs_sid *);
+
+#endif /* CONFIG_CIFS_EXPERIMENTAL */
#endif /* _CIFSACL_H */
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 36272293027d..4ff8939c6cc7 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -99,15 +99,16 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
MD5Init(&context);
MD5Update(&context, (char *)&key->data, key->len);
for (i = 0; i < n_vec; i++) {
+ if (iov[i].iov_len == 0)
+ continue;
if (iov[i].iov_base == NULL) {
cERROR(1, ("null iovec entry"));
return -EIO;
- } else if (iov[i].iov_len == 0)
- break; /* bail out if we are sent nothing to sign */
+ }
/* The first entry includes a length field (which does not get
signed that occupies the first 4 bytes before the header */
if (i == 0) {
- if (iov[0].iov_len <= 8 ) /* cmd field at offset 9 */
+ if (iov[0].iov_len <= 8) /* cmd field at offset 9 */
break; /* nothing to sign or corrupt header */
MD5Update(&context, iov[0].iov_base+4,
iov[0].iov_len-4);
@@ -122,7 +123,7 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
- __u32 * pexpected_response_sequence_number)
+ __u32 *pexpected_response_sequence_number)
{
int rc = 0;
char smb_signature[20];
@@ -345,7 +346,7 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
user = kmalloc(2 + (len * 2), GFP_KERNEL);
if (user == NULL)
goto calc_exit_2;
- len = cifs_strtoUCS(user, ses->userName, len, nls_cp);
+ len = cifs_strtoUCS((__le16 *)user, ses->userName, len, nls_cp);
UniStrupr(user);
hmac_md5_update((char *)user, 2*len, pctxt);
@@ -356,7 +357,8 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
domain = kmalloc(2 + (len * 2), GFP_KERNEL);
if (domain == NULL)
goto calc_exit_1;
- len = cifs_strtoUCS(domain, ses->domainName, len, nls_cp);
+ len = cifs_strtoUCS((__le16 *)domain, ses->domainName, len,
+ nls_cp);
/* the following line was removed since it didn't work well
with lower cased domain name that passed as an option.
Maybe converting the domain name earlier makes sense */
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index cabb6a55d7dd..416dc9fe8961 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -43,16 +43,14 @@
#include "cifs_debug.h"
#include "cifs_fs_sb.h"
#include <linux/mm.h>
+#include <linux/key-type.h>
+#include "cifs_spnego.h"
#define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */
#ifdef CONFIG_CIFS_QUOTA
static struct quotactl_ops cifs_quotactl_ops;
#endif /* QUOTA */
-#ifdef CONFIG_CIFS_EXPERIMENTAL
-extern struct export_operations cifs_export_ops;
-#endif /* EXPERIMENTAL */
-
int cifsFYI = 0;
int cifsERROR = 1;
int traceSMB = 0;
@@ -240,9 +238,9 @@ static int cifs_permission(struct inode *inode, int mask, struct nameidata *nd)
cifs_sb = CIFS_SB(inode->i_sb);
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) {
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
return 0;
- } else /* file mode might have been restricted at mount time
+ else /* file mode might have been restricted at mount time
on the client (above and beyond ACL on servers) for
servers which do not support setting and viewing mode bits,
so allowing client to check permissions is useful */
@@ -312,15 +310,15 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
seq_printf(s, ",domain=%s",
cifs_sb->tcon->ses->domainName);
}
+ if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) ||
+ !(cifs_sb->tcon->unix_ext))
+ seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
+ if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) ||
+ !(cifs_sb->tcon->unix_ext))
+ seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
}
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
seq_printf(s, ",posixpaths");
- if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) ||
- !(cifs_sb->tcon->unix_ext))
- seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
- if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) ||
- !(cifs_sb->tcon->unix_ext))
- seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
seq_printf(s, ",rsize=%d", cifs_sb->rsize);
seq_printf(s, ",wsize=%d", cifs_sb->wsize);
}
@@ -346,7 +344,7 @@ int cifs_xquota_set(struct super_block *sb, int quota_type, qid_t qid,
if (pTcon) {
cFYI(1, ("set type: 0x%x id: %d", quota_type, qid));
} else {
- return -EIO;
+ rc = -EIO;
}
FreeXid(xid);
@@ -704,7 +702,7 @@ const struct file_operations cifs_dir_ops = {
};
static void
-cifs_init_once(void *inode, struct kmem_cache *cachep, unsigned long flags)
+cifs_init_once(struct kmem_cache *cachep, void *inode)
{
struct cifsInodeInfo *cifsi = inode;
@@ -716,7 +714,7 @@ static int
cifs_init_inodecache(void)
{
cifs_inode_cachep = kmem_cache_create("cifs_inode_cache",
- sizeof (struct cifsInodeInfo),
+ sizeof(struct cifsInodeInfo),
0, (SLAB_RECLAIM_ACCOUNT|
SLAB_MEM_SPREAD),
cifs_init_once);
@@ -816,8 +814,8 @@ static int
cifs_init_mids(void)
{
cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids",
- sizeof (struct mid_q_entry), 0,
- SLAB_HWCACHE_ALIGN, NULL);
+ sizeof(struct mid_q_entry), 0,
+ SLAB_HWCACHE_ALIGN, NULL);
if (cifs_mid_cachep == NULL)
return -ENOMEM;
@@ -829,8 +827,8 @@ cifs_init_mids(void)
}
cifs_oplock_cachep = kmem_cache_create("cifs_oplock_structs",
- sizeof (struct oplock_q_entry), 0,
- SLAB_HWCACHE_ALIGN, NULL);
+ sizeof(struct oplock_q_entry), 0,
+ SLAB_HWCACHE_ALIGN, NULL);
if (cifs_oplock_cachep == NULL) {
mempool_destroy(cifs_mid_poolp);
kmem_cache_destroy(cifs_mid_cachep);
@@ -882,7 +880,8 @@ static int cifs_oplock_thread(void *dummyarg)
the call */
/* mutex_lock(&inode->i_mutex);*/
if (S_ISREG(inode->i_mode)) {
- rc = filemap_fdatawrite(inode->i_mapping);
+ rc =
+ filemap_fdatawrite(inode->i_mapping);
if (CIFS_I(inode)->clientCanCacheRead
== 0) {
filemap_fdatawait(inode->i_mapping);
@@ -907,8 +906,7 @@ static int cifs_oplock_thread(void *dummyarg)
0 /* len */ , 0 /* offset */, 0,
0, LOCKING_ANDX_OPLOCK_RELEASE,
0 /* wait flag */);
- cFYI(1,
- ("Oplock release rc = %d ", rc));
+ cFYI(1, ("Oplock release rc = %d", rc));
}
} else
spin_unlock(&GlobalMid_Lock);
@@ -1009,12 +1007,16 @@ init_cifs(void)
rc = register_filesystem(&cifs_fs_type);
if (rc)
goto out_destroy_request_bufs;
-
+#ifdef CONFIG_CIFS_UPCALL
+ rc = register_key_type(&cifs_spnego_key_type);
+ if (rc)
+ goto out_unregister_filesystem;
+#endif
oplockThread = kthread_run(cifs_oplock_thread, NULL, "cifsoplockd");
if (IS_ERR(oplockThread)) {
rc = PTR_ERR(oplockThread);
cERROR(1, ("error %d create oplock thread", rc));
- goto out_unregister_filesystem;
+ goto out_unregister_key_type;
}
dnotifyThread = kthread_run(cifs_dnotify_thread, NULL, "cifsdnotifyd");
@@ -1028,7 +1030,11 @@ init_cifs(void)
out_stop_oplock_thread:
kthread_stop(oplockThread);
+ out_unregister_key_type:
+#ifdef CONFIG_CIFS_UPCALL
+ unregister_key_type(&cifs_spnego_key_type);
out_unregister_filesystem:
+#endif
unregister_filesystem(&cifs_fs_type);
out_destroy_request_bufs:
cifs_destroy_request_bufs();
@@ -1050,6 +1056,9 @@ exit_cifs(void)
#ifdef CONFIG_PROC_FS
cifs_proc_clean();
#endif
+#ifdef CONFIG_CIFS_UPCALL
+ unregister_key_type(&cifs_spnego_key_type);
+#endif
unregister_filesystem(&cifs_fs_type);
cifs_destroy_inodecache();
cifs_destroy_mids();
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index a20de77a3856..2a21dc66f0de 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -1,7 +1,7 @@
/*
* fs/cifs/cifsfs.h
*
- * Copyright (c) International Business Machines Corp., 2002, 2005
+ * Copyright (c) International Business Machines Corp., 2002, 2007
* Author(s): Steve French (sfrench@us.ibm.com)
*
* This library is free software; you can redistribute it and/or modify
@@ -99,7 +99,12 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *,
size_t, int);
extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
-extern int cifs_ioctl (struct inode *inode, struct file *filep,
+extern int cifs_ioctl(struct inode *inode, struct file *filep,
unsigned int command, unsigned long arg);
-#define CIFS_VERSION "1.50"
+
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+extern const struct export_operations cifs_export_ops;
+#endif /* EXPERIMENTAL */
+
+#define CIFS_VERSION "1.52"
#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index b98742fc3b5a..87f51f23276f 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -19,6 +19,7 @@
#include <linux/in.h>
#include <linux/in6.h>
#include "cifs_fs_sb.h"
+#include "cifsacl.h"
/*
* The sizes of various internal tables and strings
*/
@@ -89,7 +90,8 @@ enum statusEnum {
};
enum securityEnum {
- LANMAN = 0, /* Legacy LANMAN auth */
+ PLAINTXT = 0, /* Legacy with Plaintext passwords */
+ LANMAN, /* Legacy LANMAN auth */
NTLM, /* Legacy NTLM012 auth with NTLM hash */
NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */
RawNTLMSSP, /* NTLMSSP without SPNEGO */
@@ -115,6 +117,17 @@ struct mac_key {
} data;
};
+struct cifs_cred {
+ int uid;
+ int gid;
+ int mode;
+ int cecount;
+ struct cifs_sid osid;
+ struct cifs_sid gsid;
+ struct cifs_ntace *ntaces;
+ struct cifs_ace *aces;
+};
+
/*
*****************************************************************
* Except the CIFS PDUs themselves all the
@@ -279,6 +292,7 @@ struct cifsTconInfo {
FILE_SYSTEM_DEVICE_INFO fsDevInfo;
FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if fs name truncated */
FILE_SYSTEM_UNIX_INFO fsUnixInfo;
+ unsigned ipc:1; /* set if connection to IPC$ eg for RPC/PIPES */
unsigned retry:1;
unsigned nocase:1;
unsigned unix_ext:1; /* if off disable Linux extensions to CIFS protocol
@@ -329,6 +343,7 @@ struct cifsFileInfo {
struct list_head llist; /* list of byte range locks we have. */
unsigned closePend:1; /* file is marked to close */
unsigned invalidHandle:1; /* file closed via session abend */
+ unsigned messageMode:1; /* for pipes: message vs byte mode */
atomic_t wrtPending; /* handle in use - defer close */
struct semaphore fh_sem; /* prevents reopen race after dead ses*/
char *search_resume_name; /* BB removeme BB */
@@ -464,6 +479,9 @@ struct dir_notify_req {
#ifdef CONFIG_CIFS_WEAK_PW_HASH
#define CIFSSEC_MAY_LANMAN 0x00010
#define CIFSSEC_MAY_PLNTXT 0x00020
+#else
+#define CIFSSEC_MAY_LANMAN 0
+#define CIFSSEC_MAY_PLNTXT 0
#endif /* weak passwords */
#define CIFSSEC_MAY_SEAL 0x00040 /* not supported yet */
@@ -477,14 +495,23 @@ require use of the stronger protocol */
#ifdef CONFIG_CIFS_WEAK_PW_HASH
#define CIFSSEC_MUST_LANMAN 0x10010
#define CIFSSEC_MUST_PLNTXT 0x20020
+#ifdef CONFIG_CIFS_UPCALL
+#define CIFSSEC_MASK 0x3F03F /* allows weak security but also krb5 */
+#else
#define CIFSSEC_MASK 0x37037 /* current flags supported if weak */
+#endif /* UPCALL */
+#else /* do not allow weak pw hash */
+#ifdef CONFIG_CIFS_UPCALL
+#define CIFSSEC_MASK 0x0F00F /* flags supported if no weak allowed */
#else
-#define CIFSSEC_MASK 0x07007 /* flags supported if no weak config */
+#define CIFSSEC_MASK 0x07007 /* flags supported if no weak allowed */
+#endif /* UPCALL */
#endif /* WEAK_PW_HASH */
#define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */
#define CIFSSEC_DEF CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2
#define CIFSSEC_MAX CIFSSEC_MUST_SIGN | CIFSSEC_MUST_NTLMV2
+#define CIFSSEC_AUTH_MASK (CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_LANMAN | CIFSSEC_MAY_PLNTXT | CIFSSEC_MAY_KRB5)
/*
*****************************************************************
* All constants go here
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index 6a2056e58ceb..dbe6b846f37f 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -215,6 +215,29 @@
/* file_execute, file_read_attributes*/
/* write_dac, and delete. */
+#define FILE_READ_RIGHTS (FILE_READ_DATA | FILE_READ_EA | FILE_READ_ATTRIBUTES)
+#define FILE_WRITE_RIGHTS (FILE_WRITE_DATA | FILE_APPEND_DATA \
+ | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES)
+#define FILE_EXEC_RIGHTS (FILE_EXECUTE)
+
+#define SET_FILE_READ_RIGHTS (FILE_READ_DATA | FILE_READ_EA | FILE_WRITE_EA \
+ | FILE_READ_ATTRIBUTES \
+ | FILE_WRITE_ATTRIBUTES \
+ | DELETE | READ_CONTROL | WRITE_DAC \
+ | WRITE_OWNER | SYNCHRONIZE)
+#define SET_FILE_WRITE_RIGHTS (FILE_WRITE_DATA | FILE_APPEND_DATA \
+ | FILE_READ_EA | FILE_WRITE_EA \
+ | FILE_DELETE_CHILD | FILE_READ_ATTRIBUTES \
+ | FILE_WRITE_ATTRIBUTES \
+ | DELETE | READ_CONTROL | WRITE_DAC \
+ | WRITE_OWNER | SYNCHRONIZE)
+#define SET_FILE_EXEC_RIGHTS (FILE_READ_EA | FILE_WRITE_EA | FILE_EXECUTE \
+ | FILE_READ_ATTRIBUTES \
+ | FILE_WRITE_ATTRIBUTES \
+ | DELETE | READ_CONTROL | WRITE_DAC \
+ | WRITE_OWNER | SYNCHRONIZE)
+
+
/*
* Invalid readdir handle
*/
@@ -360,10 +383,10 @@ struct smb_hdr {
__u8 WordCount;
} __attribute__((packed));
/* given a pointer to an smb_hdr retrieve the value of byte count */
-#define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) )
-#define BCC_LE(smb_var) ( *(__le16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) )
+#define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount)))
+#define BCC_LE(smb_var) ( *(__le16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount)))
/* given a pointer to an smb_hdr retrieve the pointer to the byte area */
-#define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) + 2 )
+#define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount) + 2)
/*
* Computer Name Length (since Netbios name was length 16 with last byte 0x20)
@@ -716,6 +739,14 @@ typedef struct smb_com_findclose_req {
#define REQ_OPENDIRONLY 0x00000008
#define REQ_EXTENDED_INFO 0x00000010
+/* File type */
+#define DISK_TYPE 0x0000
+#define BYTE_PIPE_TYPE 0x0001
+#define MESSAGE_PIPE_TYPE 0x0002
+#define PRINTER_TYPE 0x0003
+#define COMM_DEV_TYPE 0x0004
+#define UNKNOWN_TYPE 0xFFFF
+
typedef struct smb_com_open_req { /* also handles create */
struct smb_hdr hdr; /* wct = 24 */
__u8 AndXCommand;
@@ -1197,6 +1228,29 @@ typedef struct smb_com_transaction_qsec_req {
__le32 AclFlags;
} __attribute__((packed)) QUERY_SEC_DESC_REQ;
+
+typedef struct smb_com_transaction_ssec_req {
+ struct smb_hdr hdr; /* wct = 19 */
+ __u8 MaxSetupCount;
+ __u16 Reserved;
+ __le32 TotalParameterCount;
+ __le32 TotalDataCount;
+ __le32 MaxParameterCount;
+ __le32 MaxDataCount;
+ __le32 ParameterCount;
+ __le32 ParameterOffset;
+ __le32 DataCount;
+ __le32 DataOffset;
+ __u8 SetupCount; /* no setup words follow subcommand */
+ /* SNIA spec incorrectly included spurious pad here */
+ __le16 SubCommand; /* 3 = SET_SECURITY_DESC */
+ __le16 ByteCount; /* bcc = 3 + 8 */
+ __u8 Pad[3];
+ __u16 Fid;
+ __u16 Reserved2;
+ __le32 AclFlags;
+} __attribute__((packed)) SET_SEC_DESC_REQ;
+
typedef struct smb_com_transaction_change_notify_req {
struct smb_hdr hdr; /* wct = 23 */
__u8 MaxSetupCount;
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 04a69dafedba..dd1d7c200ee6 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -50,7 +50,8 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
int * /* bytes returned */ , const int long_op);
extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *,
struct kvec *, int /* nvec to send */,
- int * /* type of buf returned */ , const int long_op);
+ int * /* type of buf returned */ , const int long_op,
+ const int logError /* whether to log status code*/ );
extern int SendReceiveBlockingLock(const unsigned int /* xid */ ,
struct cifsTconInfo *,
struct smb_hdr * /* input */ ,
@@ -60,18 +61,23 @@ extern int checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length);
extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *);
extern int is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof);
extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *);
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *);
+#endif
extern unsigned int smbCalcSize(struct smb_hdr *ptr);
extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
extern int decode_negTokenInit(unsigned char *security_blob, int length,
enum securityEnum *secType);
extern int cifs_inet_pton(int, char *source, void *dst);
-extern int map_smb_to_linux_error(struct smb_hdr *smb);
+extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr);
extern void header_assemble(struct smb_hdr *, char /* command */ ,
const struct cifsTconInfo *, int /* length of
fixed section (word count) in two byte units */);
extern int small_smb_init_no_tc(const int smb_cmd, const int wct,
struct cifsSesInfo *ses,
void **request_buf);
+extern struct key *cifs_get_spnego_key(struct cifsSesInfo *sesInfo,
+ const char *hostname);
extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
const int stage,
const struct nls_table *nls_cp);
@@ -91,6 +97,8 @@ extern int cifs_get_inode_info(struct inode **pinode,
extern int cifs_get_inode_info_unix(struct inode **pinode,
const unsigned char *search_path,
struct super_block *sb, int xid);
+extern void acl_to_uid_mode(struct inode *inode, const char *search_path);
+extern int mode_to_acl(struct inode *inode, const char *path);
extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
const char *);
@@ -304,7 +312,7 @@ extern int cifs_calculate_mac_key(struct mac_key *key, const char *rn,
const char *pass);
extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *,
const struct nls_table *);
-extern void CalcNTLMv2_response(const struct cifsSesInfo *, char * );
+extern void CalcNTLMv2_response(const struct cifsSesInfo *, char *);
extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *,
const struct nls_table *);
#ifdef CONFIG_CIFS_WEAK_PW_HASH
@@ -334,8 +342,7 @@ extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon,
const void *ea_value, const __u16 ea_value_len,
const struct nls_table *nls_codepage, int remap_special_chars);
extern int CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon,
- __u16 fid, char *acl_inf, const int buflen,
- const int acl_type /* ACCESS vs. DEFAULT */);
+ __u16 fid, struct cifs_ntsd **acl_inf, __u32 *buflen);
extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName,
char *acl_inf, const int buflen, const int acl_type,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 8eb102f940d4..59d7b7c037ad 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -34,10 +34,10 @@
#include <asm/uaccess.h>
#include "cifspdu.h"
#include "cifsglob.h"
+#include "cifsacl.h"
#include "cifsproto.h"
#include "cifs_unicode.h"
#include "cifs_debug.h"
-#include "cifsacl.h"
#ifdef CONFIG_CIFS_POSIX
static struct {
@@ -94,9 +94,8 @@ static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
write_lock(&GlobalSMBSeslock);
list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
open_file = list_entry(tmp, struct cifsFileInfo, tlist);
- if (open_file) {
+ if (open_file)
open_file->invalidHandle = TRUE;
- }
}
write_unlock(&GlobalSMBSeslock);
/* BB Add call to invalidate_inodes(sb) for all superblocks mounted
@@ -439,8 +438,13 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
pSMB->hdr.Mid = GetNextMid(server);
pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
+
if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
+ else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
+ cFYI(1, ("Kerberos only mechanism, enable extended security"));
+ pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
+ }
count = 0;
for (i = 0; i < CIFS_NUM_PROT; i++) {
@@ -513,7 +517,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
(int)ts.tv_sec, (int)utc.tv_sec,
(int)(utc.tv_sec - ts.tv_sec)));
val = (int)(utc.tv_sec - ts.tv_sec);
- seconds = val < 0 ? -val : val;
+ seconds = abs(val);
result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
remain = seconds % MIN_TZ_ADJ;
if (remain >= (MIN_TZ_ADJ / 2))
@@ -574,7 +578,20 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
server->secType = NTLM;
else if (secFlags & CIFSSEC_MAY_NTLMV2)
server->secType = NTLMv2;
- /* else krb5 ... any others ... */
+ else if (secFlags & CIFSSEC_MAY_KRB5)
+ server->secType = Kerberos;
+ else if (secFlags & CIFSSEC_MAY_LANMAN)
+ server->secType = LANMAN;
+/* #ifdef CONFIG_CIFS_EXPERIMENTAL
+ else if (secFlags & CIFSSEC_MAY_PLNTXT)
+ server->secType = ??
+#endif */
+ else {
+ rc = -EOPNOTSUPP;
+ cERROR(1, ("Invalid security type"));
+ goto neg_err_exit;
+ }
+ /* else ... any others ...? */
/* one byte, so no need to convert this or EncryptionKeyLen from
little endian */
@@ -604,30 +621,33 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
(server->capabilities & CAP_EXTENDED_SECURITY)) {
count = pSMBr->ByteCount;
- if (count < 16)
+ if (count < 16) {
rc = -EIO;
- else if (count == 16) {
- server->secType = RawNTLMSSP;
- if (server->socketUseCount.counter > 1) {
- if (memcmp(server->server_GUID,
- pSMBr->u.extended_response.
- GUID, 16) != 0) {
- cFYI(1, ("server UID changed"));
- memcpy(server->server_GUID,
- pSMBr->u.extended_response.GUID,
- 16);
- }
- } else
+ goto neg_err_exit;
+ }
+
+ if (server->socketUseCount.counter > 1) {
+ if (memcmp(server->server_GUID,
+ pSMBr->u.extended_response.
+ GUID, 16) != 0) {
+ cFYI(1, ("server UID changed"));
memcpy(server->server_GUID,
- pSMBr->u.extended_response.GUID, 16);
+ pSMBr->u.extended_response.GUID,
+ 16);
+ }
+ } else
+ memcpy(server->server_GUID,
+ pSMBr->u.extended_response.GUID, 16);
+
+ if (count == 16) {
+ server->secType = RawNTLMSSP;
} else {
rc = decode_negTokenInit(pSMBr->u.extended_response.
SecurityBlob,
count - 16,
&server->secType);
if (rc == 1) {
- /* BB Need to fill struct for sessetup here */
- rc = -EOPNOTSUPP;
+ rc = 0;
} else {
rc = -EINVAL;
}
@@ -642,10 +662,12 @@ signing_check:
/* MUST_SIGN already includes the MAY_SIGN FLAG
so if this is zero it means that signing is disabled */
cFYI(1, ("Signing disabled"));
- if (server->secMode & SECMODE_SIGN_REQUIRED)
+ if (server->secMode & SECMODE_SIGN_REQUIRED) {
cERROR(1, ("Server requires "
- "/proc/fs/cifs/PacketSigningEnabled "
- "to be on"));
+ "packet signing to be enabled in "
+ "/proc/fs/cifs/SecurityFlags."));
+ rc = -EOPNOTSUPP;
+ }
server->secMode &=
~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
} else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
@@ -1052,7 +1074,7 @@ PsxCreat:
InformationLevel) - 4;
offset = param_offset + params;
pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
- pdata->Level = SMB_QUERY_FILE_UNIX_BASIC;
+ pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
pdata->Permissions = cpu_to_le64(mode);
pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
pdata->OpenFlags = cpu_to_le32(*pOplock);
@@ -1098,8 +1120,8 @@ PsxCreat:
if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
*pOplock |= CIFS_CREATE_ACTION;
/* check to make sure response data is there */
- if (psx_rsp->ReturnedLevel != SMB_QUERY_FILE_UNIX_BASIC) {
- pRetData->Type = -1; /* unknown */
+ if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
+ pRetData->Type = cpu_to_le32(-1); /* unknown */
#ifdef CONFIG_CIFS_DEBUG2
cFYI(1, ("unknown type"));
#endif
@@ -1107,12 +1129,12 @@ PsxCreat:
if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
+ sizeof(FILE_UNIX_BASIC_INFO)) {
cERROR(1, ("Open response data too small"));
- pRetData->Type = -1;
+ pRetData->Type = cpu_to_le32(-1);
goto psx_create_err;
}
memcpy((char *) pRetData,
(char *)psx_rsp + sizeof(OPEN_PSX_RSP),
- sizeof (FILE_UNIX_BASIC_INFO));
+ sizeof(FILE_UNIX_BASIC_INFO));
}
psx_create_err:
@@ -1193,9 +1215,9 @@ OldOpenRetry:
}
if (*pOplock & REQ_OPLOCK)
pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
- else if (*pOplock & REQ_BATCHOPLOCK) {
+ else if (*pOplock & REQ_BATCHOPLOCK)
pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
- }
+
pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
/* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
/* 0 = read
@@ -1310,9 +1332,8 @@ openRetry:
}
if (*pOplock & REQ_OPLOCK)
pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
- else if (*pOplock & REQ_BATCHOPLOCK) {
+ else if (*pOplock & REQ_BATCHOPLOCK)
pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
- }
pSMB->DesiredAccess = cpu_to_le32(access_flags);
pSMB->AllocationSize = 0;
/* set file as system file if special file such
@@ -1424,9 +1445,8 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
iov[0].iov_base = (char *)pSMB;
iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
- rc = SendReceive2(xid, tcon->ses, iov,
- 1 /* num iovecs */,
- &resp_buf_type, 0);
+ rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
+ &resp_buf_type, 0 /* not long op */, 1 /* log err */ );
cifs_stats_inc(&tcon->num_reads);
pSMBr = (READ_RSP *)iov[0].iov_base;
if (rc) {
@@ -1446,11 +1466,11 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
*nbytes = 0;
} else {
pReadData = (char *) (&pSMBr->hdr.Protocol) +
- le16_to_cpu(pSMBr->DataOffset);
-/* if (rc = copy_to_user(buf, pReadData, data_length)) {
+ le16_to_cpu(pSMBr->DataOffset);
+/* if (rc = copy_to_user(buf, pReadData, data_length)) {
cERROR(1,("Faulting on read rc = %d",rc));
rc = -EFAULT;
- }*/ /* can not use copy_to_user when using page cache*/
+ }*/ /* can not use copy_to_user when using page cache*/
if (*buf)
memcpy(*buf, pReadData, data_length);
}
@@ -1645,7 +1665,7 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
- long_op);
+ long_op, 0 /* do not log STATUS code */ );
cifs_stats_inc(&tcon->num_writes);
if (rc) {
cFYI(1, ("Send error Write2 = %d", rc));
@@ -2465,6 +2485,7 @@ querySymLinkRetry:
return rc;
}
+#ifdef CONFIG_CIFS_EXPERIMENTAL
/* Initialize NT TRANSACT SMB into small smb request buffer.
This assumes that all NT TRANSACTS that we init here have
total parm and data under about 400 bytes (to fit in small cifs
@@ -2473,7 +2494,7 @@ querySymLinkRetry:
MaxSetupCount (size of returned setup area) and
MaxParameterCount (returned parms size) must be set by caller */
static int
-smb_init_ntransact(const __u16 sub_command, const int setup_count,
+smb_init_nttransact(const __u16 sub_command, const int setup_count,
const int parm_len, struct cifsTconInfo *tcon,
void **ret_buf)
{
@@ -2504,12 +2525,15 @@ smb_init_ntransact(const __u16 sub_command, const int setup_count,
static int
validate_ntransact(char *buf, char **ppparm, char **ppdata,
- int *pdatalen, int *pparmlen)
+ __u32 *pparmlen, __u32 *pdatalen)
{
char *end_of_smb;
__u32 data_count, data_offset, parm_count, parm_offset;
struct smb_com_ntransact_rsp *pSMBr;
+ *pdatalen = 0;
+ *pparmlen = 0;
+
if (buf == NULL)
return -EINVAL;
@@ -2538,7 +2562,7 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata,
cFYI(1, ("data starts after end of smb"));
return -EINVAL;
} else if (data_count + *ppdata > end_of_smb) {
- cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p",
+ cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
*ppdata, data_count, (data_count + *ppdata),
end_of_smb, pSMBr));
return -EINVAL;
@@ -2546,8 +2570,11 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata,
cFYI(1, ("parm count and data count larger than SMB"));
return -EINVAL;
}
+ *pdatalen = data_count;
+ *pparmlen = parm_count;
return 0;
}
+#endif /* CIFS_EXPERIMENTAL */
int
CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
@@ -2615,7 +2642,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
reparse_buf->TargetNameOffset +
reparse_buf->TargetNameLen) >
end_of_smb) {
- cFYI(1,("reparse buf goes beyond SMB"));
+ cFYI(1, ("reparse buf beyond SMB"));
rc = -EIO;
goto qreparse_out;
}
@@ -3042,25 +3069,11 @@ GetExtAttrOut:
#endif /* CONFIG_POSIX */
-
-/* security id for everyone */
-static const struct cifs_sid sid_everyone =
- {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
-/* group users */
-static const struct cifs_sid sid_user =
- {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
-
-/* Convert CIFS ACL to POSIX form */
-static int parse_sec_desc(struct cifs_sid *psec_desc, int acl_len)
-{
- return 0;
-}
-
+#ifdef CONFIG_CIFS_EXPERIMENTAL
/* Get Security Descriptor (by handle) from remote server for a file or dir */
int
CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
- /* BB fix up return info */ char *acl_inf, const int buflen,
- const int acl_type /* ACCESS/DEFAULT not sure implication */)
+ struct cifs_ntsd **acl_inf, __u32 *pbuflen)
{
int rc = 0;
int buf_type = 0;
@@ -3069,7 +3082,10 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
cFYI(1, ("GetCifsACL"));
- rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
+ *pbuflen = 0;
+ *acl_inf = NULL;
+
+ rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
8 /* parm len */, tcon, (void **) &pSMB);
if (rc)
return rc;
@@ -3085,40 +3101,58 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
iov[0].iov_base = (char *)pSMB;
iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
- rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 0);
+ rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
+ 0 /* not long op */, 0 /* do not log STATUS codes */ );
cifs_stats_inc(&tcon->num_acl_get);
if (rc) {
cFYI(1, ("Send error in QuerySecDesc = %d", rc));
} else { /* decode response */
- struct cifs_sid *psec_desc;
__le32 * parm;
- int parm_len;
- int data_len;
- int acl_len;
+ __u32 parm_len;
+ __u32 acl_len;
struct smb_com_ntransact_rsp *pSMBr;
+ char *pdata;
/* validate_nttransact */
rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
- (char **)&psec_desc,
- &parm_len, &data_len);
+ &pdata, &parm_len, pbuflen);
if (rc)
goto qsec_out;
pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
- cERROR(1, ("smb %p parm %p data %p",
- pSMBr, parm, psec_desc)); /* BB removeme BB */
+ cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf));
if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
rc = -EIO; /* bad smb */
+ *pbuflen = 0;
goto qsec_out;
}
/* BB check that data area is minimum length and as big as acl_len */
- acl_len = le32_to_cpu(*(__le32 *)parm);
- /* BB check if (acl_len > bufsize) */
+ acl_len = le32_to_cpu(*parm);
+ if (acl_len != *pbuflen) {
+ cERROR(1, ("acl length %d does not match %d",
+ acl_len, *pbuflen));
+ if (*pbuflen > acl_len)
+ *pbuflen = acl_len;
+ }
- parse_sec_desc(psec_desc, acl_len);
+ /* check if buffer is big enough for the acl
+ header followed by the smallest SID */
+ if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
+ (*pbuflen >= 64 * 1024)) {
+ cERROR(1, ("bad acl length %d", *pbuflen));
+ rc = -EINVAL;
+ *pbuflen = 0;
+ } else {
+ *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
+ if (*acl_inf == NULL) {
+ *pbuflen = 0;
+ rc = -ENOMEM;
+ }
+ memcpy(*acl_inf, pdata, *pbuflen);
+ }
}
qsec_out:
if (buf_type == CIFS_SMALL_BUFFER)
@@ -3128,6 +3162,7 @@ qsec_out:
/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
return rc;
}
+#endif /* CONFIG_CIFS_EXPERIMENTAL */
/* Legacy Query Path Information call for lookup to old servers such
as Win9x/WinME */
@@ -3363,13 +3398,16 @@ UnixQPathInfoRetry:
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
+ cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
+ "Unix Extensions can be disabled on mount "
+ "by specifying the nosfu mount option."));
rc = -EIO; /* bad smb */
} else {
__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
memcpy((char *) pFindData,
(char *) &pSMBr->hdr.Protocol +
data_offset,
- sizeof (FILE_UNIX_BASIC_INFO));
+ sizeof(FILE_UNIX_BASIC_INFO));
}
}
cifs_buf_release(pSMB);
@@ -3637,7 +3675,7 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
pSMB->SearchHandle = searchHandle; /* always kept as le */
pSMB->SearchCount =
- cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
+ cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
pSMB->ResumeKey = psrch_inf->resume_key;
pSMB->SearchFlags =
@@ -3883,12 +3921,10 @@ getDFSRetry:
pSMB->hdr.Mid = GetNextMid(ses->server);
pSMB->hdr.Tid = ses->ipc_tid;
pSMB->hdr.Uid = ses->Suid;
- if (ses->capabilities & CAP_STATUS32) {
+ if (ses->capabilities & CAP_STATUS32)
pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
- }
- if (ses->capabilities & CAP_DFS) {
+ if (ses->capabilities & CAP_DFS)
pSMB->hdr.Flags2 |= SMBFLG2_DFS;
- }
if (ses->capabilities & CAP_UNICODE) {
pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
@@ -4060,10 +4096,6 @@ oldQFSInfoRetry:
(void **) &pSMBr);
if (rc)
return rc;
- rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
params = 2; /* level */
pSMB->TotalDataCount = 0;
@@ -4265,7 +4297,7 @@ QFSAttributeRetry:
*) (((char *) &pSMBr->hdr.Protocol) +
data_offset);
memcpy(&tcon->fsAttrInfo, response_data,
- sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
+ sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
}
}
cifs_buf_release(pSMB);
@@ -4325,7 +4357,7 @@ QFSDeviceRetry:
} else { /* decode response */
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
- if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
+ if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
rc = -EIO; /* bad smb */
else {
__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
@@ -4334,7 +4366,7 @@ QFSDeviceRetry:
(((char *) &pSMBr->hdr.Protocol) +
data_offset);
memcpy(&tcon->fsDevInfo, response_data,
- sizeof (FILE_SYSTEM_DEVICE_INFO));
+ sizeof(FILE_SYSTEM_DEVICE_INFO));
}
}
cifs_buf_release(pSMB);
@@ -4402,7 +4434,7 @@ QFSUnixRetry:
*) (((char *) &pSMBr->hdr.Protocol) +
data_offset);
memcpy(&tcon->fsUnixInfo, response_data,
- sizeof (FILE_SYSTEM_UNIX_INFO));
+ sizeof(FILE_SYSTEM_UNIX_INFO));
}
}
cifs_buf_release(pSMB);
@@ -4612,7 +4644,7 @@ SetEOFRetry:
strncpy(pSMB->FileName, fileName, name_len);
}
params = 6 + name_len;
- data_count = sizeof (struct file_end_of_file_info);
+ data_count = sizeof(struct file_end_of_file_info);
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(4100);
pSMB->MaxSetupCount = 0;
@@ -4800,7 +4832,7 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
- count = sizeof (FILE_BASIC_INFO);
+ count = sizeof(FILE_BASIC_INFO);
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
pSMB->SetupCount = 1;
@@ -4871,7 +4903,7 @@ SetTimesRetry:
}
params = 6 + name_len;
- count = sizeof (FILE_BASIC_INFO);
+ count = sizeof(FILE_BASIC_INFO);
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
pSMB->MaxSetupCount = 0;
@@ -4900,7 +4932,7 @@ SetTimesRetry:
pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
pSMB->Reserved4 = 0;
pSMB->hdr.smb_buf_length += byte_count;
- memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
+ memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
pSMB->ByteCount = cpu_to_le16(byte_count);
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
@@ -5003,7 +5035,7 @@ setPermsRetry:
}
params = 6 + name_len;
- count = sizeof (FILE_UNIX_BASIC_INFO);
+ count = sizeof(FILE_UNIX_BASIC_INFO);
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
pSMB->MaxSetupCount = 0;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 4af3588c1a96..c52a76ff4bb9 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -124,7 +124,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
struct mid_q_entry *mid_entry;
spin_lock(&GlobalMid_Lock);
- if ( kthread_should_stop() ) {
+ if (kthread_should_stop()) {
/* the demux thread will exit normally
next time through the loop */
spin_unlock(&GlobalMid_Lock);
@@ -151,9 +151,8 @@ cifs_reconnect(struct TCP_Server_Info *server)
}
list_for_each(tmp, &GlobalTreeConnectionList) {
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
- if ((tcon) && (tcon->ses) && (tcon->ses->server == server)) {
+ if ((tcon) && (tcon->ses) && (tcon->ses->server == server))
tcon->tidStatus = CifsNeedReconnect;
- }
}
read_unlock(&GlobalSMBSeslock);
/* do not want to be sending data on a socket we are freeing */
@@ -161,7 +160,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
if (server->ssocket) {
cFYI(1, ("State: 0x%x Flags: 0x%lx", server->ssocket->state,
server->ssocket->flags));
- server->ssocket->ops->shutdown(server->ssocket, SEND_SHUTDOWN);
+ kernel_sock_shutdown(server->ssocket, SHUT_WR);
cFYI(1, ("Post shutdown state: 0x%x Flags: 0x%lx",
server->ssocket->state,
server->ssocket->flags));
@@ -187,7 +186,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
spin_unlock(&GlobalMid_Lock);
up(&server->tcpSem);
- while ( (!kthread_should_stop()) && (server->tcpStatus != CifsGood)) {
+ while ((!kthread_should_stop()) && (server->tcpStatus != CifsGood)) {
try_to_freeze();
if (server->protocolType == IPV6) {
rc = ipv6_connect(&server->addr.sockAddr6,
@@ -204,7 +203,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
} else {
atomic_inc(&tcpSesReconnectCount);
spin_lock(&GlobalMid_Lock);
- if ( !kthread_should_stop() )
+ if (!kthread_should_stop())
server->tcpStatus = CifsGood;
server->sequence_number = 0;
spin_unlock(&GlobalMid_Lock);
@@ -352,17 +351,15 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
current->flags |= PF_MEMALLOC;
server->tsk = current; /* save process info to wake at shutdown */
- cFYI(1, ("Demultiplex PID: %d", current->pid));
+ cFYI(1, ("Demultiplex PID: %d", task_pid_nr(current)));
write_lock(&GlobalSMBSeslock);
atomic_inc(&tcpSesAllocCount);
length = tcpSesAllocCount.counter;
write_unlock(&GlobalSMBSeslock);
complete(&cifsd_complete);
- if (length > 1) {
- mempool_resize(cifs_req_poolp,
- length + cifs_min_rcv,
- GFP_KERNEL);
- }
+ if (length > 1)
+ mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
+ GFP_KERNEL);
set_freezable();
while (!kthread_should_stop()) {
@@ -378,7 +375,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
}
} else if (isLargeBuf) {
/* we are reusing a dirty large buf, clear its start */
- memset(bigbuf, 0, sizeof (struct smb_hdr));
+ memset(bigbuf, 0, sizeof(struct smb_hdr));
}
if (smallbuf == NULL) {
@@ -391,7 +388,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
}
/* beginning of smb buffer is cleared in our buf_get */
} else /* if existing small buf clear beginning */
- memset(smallbuf, 0, sizeof (struct smb_hdr));
+ memset(smallbuf, 0, sizeof(struct smb_hdr));
isLargeBuf = FALSE;
isMultiRsp = FALSE;
@@ -400,11 +397,13 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
iov.iov_len = 4;
smb_msg.msg_control = NULL;
smb_msg.msg_controllen = 0;
+ pdu_length = 4; /* enough to get RFC1001 header */
+incomplete_rcv:
length =
kernel_recvmsg(csocket, &smb_msg,
- &iov, 1, 4, 0 /* BB see socket.h flags */);
+ &iov, 1, pdu_length, 0 /* BB other flags? */);
- if ( kthread_should_stop() ) {
+ if (kthread_should_stop()) {
break;
} else if (server->tcpStatus == CifsNeedReconnect) {
cFYI(1, ("Reconnect after server stopped responding"));
@@ -416,7 +415,10 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
msleep(1); /* minimum sleep to prevent looping
allowing socket to clear and app threads to set
tcpStatus CifsNeedReconnect if server hung */
- continue;
+ if (pdu_length < 4)
+ goto incomplete_rcv;
+ else
+ continue;
} else if (length <= 0) {
if (server->tcpStatus == CifsNew) {
cFYI(1, ("tcp session abend after SMBnegprot"));
@@ -437,13 +439,11 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
wake_up(&server->response_q);
continue;
} else if (length < 4) {
- cFYI(1,
- ("Frame under four bytes received (%d bytes long)",
+ cFYI(1, ("less than four bytes received (%d bytes)",
length));
- cifs_reconnect(server);
- csocket = server->ssocket;
- wake_up(&server->response_q);
- continue;
+ pdu_length -= length;
+ msleep(1);
+ goto incomplete_rcv;
}
/* The right amount was read from socket - 4 bytes */
@@ -504,7 +504,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
/* else we have an SMB response */
if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
- (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
+ (pdu_length < sizeof(struct smb_hdr) - 1 - 4)) {
cERROR(1, ("Invalid size SMB length %d pdu_length %d",
length, pdu_length+4));
cifs_reconnect(server);
@@ -528,7 +528,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
total_read += length) {
length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
pdu_length - total_read, 0);
- if ( kthread_should_stop() ||
+ if (kthread_should_stop() ||
(length == -EINTR)) {
/* then will exit */
reconnect = 2;
@@ -546,6 +546,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
allowing socket to clear and app
threads to set tcpStatus
CifsNeedReconnect if server hung*/
+ length = 0;
continue;
} else if (length <= 0) {
cERROR(1, ("Received no data, expecting %d",
@@ -631,9 +632,9 @@ multi_t2_fnd:
/* Was previous buf put in mpx struct for multi-rsp? */
if (!isMultiRsp) {
/* smb buffer will be freed by user thread */
- if (isLargeBuf) {
+ if (isLargeBuf)
bigbuf = NULL;
- } else
+ else
smallbuf = NULL;
}
wake_up_process(task_to_wake);
@@ -676,9 +677,8 @@ multi_t2_fnd:
server->ssocket = NULL;
}
/* buffer usuallly freed in free_mid - need to free it here on exit */
- if (bigbuf != NULL)
- cifs_buf_release(bigbuf);
- if (smallbuf != NULL)
+ cifs_buf_release(bigbuf);
+ if (smallbuf) /* no sense logging a debug message if NULL */
cifs_small_buf_release(smallbuf);
read_lock(&GlobalSMBSeslock);
@@ -702,9 +702,8 @@ multi_t2_fnd:
list_for_each(tmp, &GlobalSMBSessionList) {
ses = list_entry(tmp, struct cifsSesInfo,
cifsSessionList);
- if (ses->server == server) {
+ if (ses->server == server)
ses->status = CifsExiting;
- }
}
spin_lock(&GlobalMid_Lock);
@@ -714,9 +713,8 @@ multi_t2_fnd:
cFYI(1, ("Clearing Mid 0x%x - waking up ",
mid_entry->mid));
task_to_wake = mid_entry->tsk;
- if (task_to_wake) {
+ if (task_to_wake)
wake_up_process(task_to_wake);
- }
}
}
spin_unlock(&GlobalMid_Lock);
@@ -749,18 +747,15 @@ multi_t2_fnd:
list_for_each(tmp, &GlobalSMBSessionList) {
ses = list_entry(tmp, struct cifsSesInfo,
cifsSessionList);
- if (ses->server == server) {
+ if (ses->server == server)
ses->server = NULL;
- }
}
write_unlock(&GlobalSMBSeslock);
kfree(server);
- if (length > 0) {
- mempool_resize(cifs_req_poolp,
- length + cifs_min_rcv,
- GFP_KERNEL);
- }
+ if (length > 0)
+ mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
+ GFP_KERNEL);
return 0;
}
@@ -798,7 +793,7 @@ cifs_parse_mount_options(char *options, const char *devname,
vol->linux_gid = current->gid;
vol->dir_mode = S_IRWXUGO;
/* 2767 perms indicate mandatory locking support */
- vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
+ vol->file_mode = (S_IRWXUGO | S_ISGID) & (~S_IXGRP);
/* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
vol->rw = TRUE;
@@ -1477,7 +1472,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
if (psin_server->sin_port) { /* user overrode default port */
rc = (*csocket)->ops->connect(*csocket,
(struct sockaddr *) psin_server,
- sizeof (struct sockaddr_in), 0);
+ sizeof(struct sockaddr_in), 0);
if (rc >= 0)
connected = 1;
}
@@ -1493,7 +1488,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
rc = (*csocket)->ops->connect(*csocket,
(struct sockaddr *) psin_server,
- sizeof (struct sockaddr_in), 0);
+ sizeof(struct sockaddr_in), 0);
if (rc >= 0)
connected = 1;
}
@@ -1502,7 +1497,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
psin_server->sin_port = htons(RFC1001_PORT);
rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
psin_server,
- sizeof (struct sockaddr_in), 0);
+ sizeof(struct sockaddr_in), 0);
if (rc >= 0)
connected = 1;
}
@@ -1610,7 +1605,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
if (psin_server->sin6_port) { /* user overrode default port */
rc = (*csocket)->ops->connect(*csocket,
(struct sockaddr *) psin_server,
- sizeof (struct sockaddr_in6), 0);
+ sizeof(struct sockaddr_in6), 0);
if (rc >= 0)
connected = 1;
}
@@ -1626,7 +1621,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
rc = (*csocket)->ops->connect(*csocket,
(struct sockaddr *) psin_server,
- sizeof (struct sockaddr_in6), 0);
+ sizeof(struct sockaddr_in6), 0);
if (rc >= 0)
connected = 1;
}
@@ -1634,7 +1629,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
if (!connected) {
psin_server->sin6_port = htons(RFC1001_PORT);
rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
- psin_server, sizeof (struct sockaddr_in6), 0);
+ psin_server, sizeof(struct sockaddr_in6), 0);
if (rc >= 0)
connected = 1;
}
@@ -1750,7 +1745,16 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
cFYI(1, ("very large write cap"));
#endif /* CIFS_DEBUG2 */
if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
- cFYI(1, ("setting capabilities failed"));
+ if (vol_info == NULL) {
+ cFYI(1, ("resetting capabilities failed"));
+ } else
+ cERROR(1, ("Negotiating Unix capabilities "
+ "with the server failed. Consider "
+ "mounting with the Unix Extensions\n"
+ "disabled, if problems are found, "
+ "by specifying the nounix mount "
+ "option."));
+
}
}
}
@@ -1786,7 +1790,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
if (volume_info.nullauth) {
cFYI(1, ("null user"));
- volume_info.username = NULL;
+ volume_info.username = "";
} else if (volume_info.username) {
/* BB fixme parse for domain name here */
cFYI(1, ("Username: %s", volume_info.username));
@@ -1909,8 +1913,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
return rc;
}
- srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
- if (srvTcp == NULL) {
+ srvTcp = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
+ if (!srvTcp) {
rc = -ENOMEM;
sock_release(csocket);
kfree(volume_info.UNC);
@@ -1919,9 +1923,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
FreeXid(xid);
return rc;
} else {
- memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
memcpy(&srvTcp->addr.sockAddr, &sin_server,
- sizeof (struct sockaddr_in));
+ sizeof(struct sockaddr_in));
atomic_set(&srvTcp->inFlight, 0);
/* BB Add code for ipv6 case too */
srvTcp->ssocket = csocket;
@@ -2173,8 +2176,18 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
if (tsk)
kthread_stop(tsk);
}
- } else
+ } else {
cFYI(1, ("No session or bad tcon"));
+ if ((pSesInfo->server) &&
+ (pSesInfo->server->tsk)) {
+ struct task_struct *tsk;
+ force_sig(SIGKILL,
+ pSesInfo->server->tsk);
+ tsk = pSesInfo->server->tsk;
+ if (tsk)
+ kthread_stop(tsk);
+ }
+ }
sesInfoFree(pSesInfo);
/* pSesInfo = NULL; */
}
@@ -2185,8 +2198,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
tcon->ses = pSesInfo;
/* do not care if following two calls succeed - informational */
- CIFSSMBQFSDeviceInfo(xid, tcon);
- CIFSSMBQFSAttributeInfo(xid, tcon);
+ if (!tcon->ipc) {
+ CIFSSMBQFSDeviceInfo(xid, tcon);
+ CIFSSMBQFSAttributeInfo(xid, tcon);
+ }
/* tell server which Unix caps we support */
if (tcon->ses->capabilities & CAP_UNIX)
@@ -2526,8 +2541,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
sesssetup_nomem: /* do not return an error on nomem for the info strings,
since that could make reconnection harder, and
reconnection might be needed to free memory */
- if (smb_buffer)
- cifs_buf_release(smb_buffer);
+ cifs_buf_release(smb_buffer);
return rc;
}
@@ -2547,7 +2561,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
int remaining_words = 0;
int bytes_returned = 0;
int len;
- int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
+ int SecurityBlobLength = sizeof(NEGOTIATE_MESSAGE);
PNEGOTIATE_MESSAGE SecurityBlob;
PCHALLENGE_MESSAGE SecurityBlob2;
__u32 negotiate_flags, capabilities;
@@ -2865,15 +2879,14 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
rc = -EIO;
}
- if (smb_buffer)
- cifs_buf_release(smb_buffer);
+ cifs_buf_release(smb_buffer);
return rc;
}
static int
CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
- char *ntlm_session_key, int ntlmv2_flag,
- const struct nls_table *nls_codepage)
+ char *ntlm_session_key, int ntlmv2_flag,
+ const struct nls_table *nls_codepage)
{
struct smb_hdr *smb_buffer;
struct smb_hdr *smb_buffer_response;
@@ -2886,7 +2899,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
int remaining_words = 0;
int bytes_returned = 0;
int len;
- int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
+ int SecurityBlobLength = sizeof(AUTHENTICATE_MESSAGE);
PAUTHENTICATE_MESSAGE SecurityBlob;
__u32 negotiate_flags, capabilities;
__u16 count;
@@ -2901,8 +2914,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
return -ENOMEM;
}
smb_buffer_response = smb_buffer;
- pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
- pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
+ pSMB = (SESSION_SETUP_ANDX *)smb_buffer;
+ pSMBr = (SESSION_SETUP_ANDX *)smb_buffer_response;
/* send SMBsessionSetup here */
header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
@@ -2921,7 +2934,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
- CAP_EXTENDED_SECURITY;
+ CAP_EXTENDED_SECURITY;
if (ses->capabilities & CAP_UNICODE) {
smb_buffer->Flags2 |= SMBFLG2_UNICODE;
capabilities |= CAP_UNICODE;
@@ -2936,15 +2949,14 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
}
pSMB->req.Capabilities = cpu_to_le32(capabilities);
- bcc_ptr = (char *) &pSMB->req.SecurityBlob;
- SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
+ bcc_ptr = (char *)&pSMB->req.SecurityBlob;
+ SecurityBlob = (PAUTHENTICATE_MESSAGE)bcc_ptr;
strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
SecurityBlob->MessageType = NtLmAuthenticate;
bcc_ptr += SecurityBlobLength;
- negotiate_flags =
- NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
- NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
- 0x80000000 | NTLMSSP_NEGOTIATE_128;
+ negotiate_flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
+ NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
+ 0x80000000 | NTLMSSP_NEGOTIATE_128;
if (sign_CIFS_PDUs)
negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
if (ntlmv2_flag)
@@ -2979,36 +2991,32 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
SecurityBlob->DomainName.Length = 0;
SecurityBlob->DomainName.MaximumLength = 0;
} else {
- __u16 len =
- cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
+ __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
nls_codepage);
- len *= 2;
+ ln *= 2;
SecurityBlob->DomainName.MaximumLength =
- cpu_to_le16(len);
+ cpu_to_le16(ln);
SecurityBlob->DomainName.Buffer =
cpu_to_le32(SecurityBlobLength);
- bcc_ptr += len;
- SecurityBlobLength += len;
- SecurityBlob->DomainName.Length =
- cpu_to_le16(len);
+ bcc_ptr += ln;
+ SecurityBlobLength += ln;
+ SecurityBlob->DomainName.Length = cpu_to_le16(ln);
}
if (user == NULL) {
SecurityBlob->UserName.Buffer = 0;
SecurityBlob->UserName.Length = 0;
SecurityBlob->UserName.MaximumLength = 0;
} else {
- __u16 len =
- cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
+ __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
nls_codepage);
- len *= 2;
+ ln *= 2;
SecurityBlob->UserName.MaximumLength =
- cpu_to_le16(len);
+ cpu_to_le16(ln);
SecurityBlob->UserName.Buffer =
cpu_to_le32(SecurityBlobLength);
- bcc_ptr += len;
- SecurityBlobLength += len;
- SecurityBlob->UserName.Length =
- cpu_to_le16(len);
+ bcc_ptr += ln;
+ SecurityBlobLength += ln;
+ SecurityBlob->UserName.Length = cpu_to_le16(ln);
}
/* SecurityBlob->WorkstationName.Length =
@@ -3052,33 +3060,32 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
SecurityBlob->DomainName.Length = 0;
SecurityBlob->DomainName.MaximumLength = 0;
} else {
- __u16 len;
+ __u16 ln;
negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
strncpy(bcc_ptr, domain, 63);
- len = strnlen(domain, 64);
+ ln = strnlen(domain, 64);
SecurityBlob->DomainName.MaximumLength =
- cpu_to_le16(len);
+ cpu_to_le16(ln);
SecurityBlob->DomainName.Buffer =
cpu_to_le32(SecurityBlobLength);
- bcc_ptr += len;
- SecurityBlobLength += len;
- SecurityBlob->DomainName.Length = cpu_to_le16(len);
+ bcc_ptr += ln;
+ SecurityBlobLength += ln;
+ SecurityBlob->DomainName.Length = cpu_to_le16(ln);
}
if (user == NULL) {
SecurityBlob->UserName.Buffer = 0;
SecurityBlob->UserName.Length = 0;
SecurityBlob->UserName.MaximumLength = 0;
} else {
- __u16 len;
+ __u16 ln;
strncpy(bcc_ptr, user, 63);
- len = strnlen(user, 64);
- SecurityBlob->UserName.MaximumLength =
- cpu_to_le16(len);
+ ln = strnlen(user, 64);
+ SecurityBlob->UserName.MaximumLength = cpu_to_le16(ln);
SecurityBlob->UserName.Buffer =
- cpu_to_le32(SecurityBlobLength);
- bcc_ptr += len;
- SecurityBlobLength += len;
- SecurityBlob->UserName.Length = cpu_to_le16(len);
+ cpu_to_le32(SecurityBlobLength);
+ bcc_ptr += ln;
+ SecurityBlobLength += ln;
+ SecurityBlob->UserName.Length = cpu_to_le16(ln);
}
/* BB fill in our workstation name if known BB */
@@ -3100,12 +3107,11 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
&bytes_returned, 1);
if (rc) {
-/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
- } else if ((smb_buffer_response->WordCount == 3)
- || (smb_buffer_response->WordCount == 4)) {
+/* rc = map_smb_to_linux_error(smb_buffer_response) done in SendReceive now */
+ } else if ((smb_buffer_response->WordCount == 3) ||
+ (smb_buffer_response->WordCount == 4)) {
__u16 action = le16_to_cpu(pSMBr->resp.Action);
- __u16 blob_len =
- le16_to_cpu(pSMBr->resp.SecurityBlobLength);
+ __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
if (action & GUEST_LOGIN)
cFYI(1, (" Guest login")); /* BB Should we set anything
in SesInfo struct ? */
@@ -3145,8 +3151,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
} else {
remaining_words = BCC(smb_buffer_response) / 2;
}
- len =
- UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
+ len = UniStrnlen((wchar_t *) bcc_ptr,
+ remaining_words - 1);
/* We look for obvious messed up bcc or strings in response so we do not go off
the end since (at least) WIN2K and Windows XP have a major bug in not null
terminating last Unicode string in response */
@@ -3230,7 +3236,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
<= BCC(smb_buffer_response)) {
if (ses->serverOS)
kfree(ses->serverOS);
- ses->serverOS = kzalloc(len + 1,GFP_KERNEL);
+ ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
strncpy(ses->serverOS,bcc_ptr, len);
bcc_ptr += len;
@@ -3259,28 +3265,24 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
bcc_ptr[0] = 0;
bcc_ptr++;
} else
- cFYI(1,
- ("field of length %d "
+ cFYI(1, ("field of length %d "
"extends beyond end of smb ",
len));
}
} else {
- cERROR(1,
- (" Security Blob extends beyond end "
+ cERROR(1, ("Security Blob extends beyond end "
"of SMB"));
}
} else {
cERROR(1, ("No session structure passed in."));
}
} else {
- cERROR(1,
- (" Invalid Word count %d: ",
+ cERROR(1, ("Invalid Word count %d: ",
smb_buffer_response->WordCount));
rc = -EIO;
}
- if (smb_buffer)
- cifs_buf_release(smb_buffer);
+ cifs_buf_release(smb_buffer);
return rc;
}
@@ -3389,6 +3391,18 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
bcc_ptr = pByteArea(smb_buffer_response);
length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
/* skip service field (NB: this field is always ASCII) */
+ if (length == 3) {
+ if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
+ (bcc_ptr[2] == 'C')) {
+ cFYI(1, ("IPC connection"));
+ tcon->ipc = 1;
+ }
+ } else if (length == 2) {
+ if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
+ /* the most common case */
+ cFYI(1, ("disk share connection"));
+ }
+ }
bcc_ptr += length + 1;
strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
@@ -3399,9 +3413,11 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
kfree(tcon->nativeFileSystem);
tcon->nativeFileSystem =
kzalloc(length + 2, GFP_KERNEL);
- cifs_strfromUCS_le(tcon->nativeFileSystem,
- (__le16 *) bcc_ptr,
- length, nls_codepage);
+ if (tcon->nativeFileSystem)
+ cifs_strfromUCS_le(
+ tcon->nativeFileSystem,
+ (__le16 *) bcc_ptr,
+ length, nls_codepage);
bcc_ptr += 2 * length;
bcc_ptr[0] = 0; /* null terminate the string */
bcc_ptr[1] = 0;
@@ -3416,8 +3432,9 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
kfree(tcon->nativeFileSystem);
tcon->nativeFileSystem =
kzalloc(length + 1, GFP_KERNEL);
- strncpy(tcon->nativeFileSystem, bcc_ptr,
- length);
+ if (tcon->nativeFileSystem)
+ strncpy(tcon->nativeFileSystem, bcc_ptr,
+ length);
}
/* else do not bother copying these information fields*/
}
@@ -3433,8 +3450,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
ses->ipc_tid = smb_buffer_response->Tid;
}
- if (smb_buffer)
- cifs_buf_release(smb_buffer);
+ cifs_buf_release(smb_buffer);
return rc;
}
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 4830acc86d74..37dc97af1487 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,2005
+ * Copyright (C) International Business Machines Corp., 2002,2007
* Author(s): Steve French (sfrench@us.ibm.com)
*
* This library is free software; you can redistribute it and/or modify
@@ -269,7 +269,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
CIFSSMBClose(xid, pTcon, fileHandle);
} else if (newinode) {
pCifsFile =
- kzalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
+ kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
if (pCifsFile == NULL)
goto cifs_create_out;
@@ -397,7 +397,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
/* BB Do not bother to decode buf since no
local inode yet to put timestamps in,
but we can reuse it safely */
- int bytes_written;
+ unsigned int bytes_written;
struct win_dev *pdev;
pdev = (struct win_dev *)buf;
if (S_ISCHR(mode)) {
@@ -450,8 +450,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
xid = GetXid();
- cFYI(1,
- (" parent inode = 0x%p name is: %s and dentry = 0x%p",
+ cFYI(1, (" parent inode = 0x%p name is: %s and dentry = 0x%p",
parent_dir_inode, direntry->d_name.name, direntry));
/* check whether path exists */
@@ -594,7 +593,7 @@ static int cifs_ci_compare(struct dentry *dentry, struct qstr *a,
* case take precedence. If a is not a negative dentry, this
* should have no side effects
*/
- memcpy((unsigned char *)a->name, b->name, a->len);
+ memcpy(a->name, b->name, a->len);
return 0;
}
return 1;
diff --git a/fs/cifs/export.c b/fs/cifs/export.c
index 893fd0aebff8..75949d6a5f1b 100644
--- a/fs/cifs/export.c
+++ b/fs/cifs/export.c
@@ -43,6 +43,7 @@
#include <linux/exportfs.h>
#include "cifsglob.h"
#include "cifs_debug.h"
+#include "cifsfs.h"
#ifdef CONFIG_CIFS_EXPERIMENTAL
static struct dentry *cifs_get_parent(struct dentry *dentry)
@@ -52,7 +53,7 @@ static struct dentry *cifs_get_parent(struct dentry *dentry)
return ERR_PTR(-EACCES);
}
-struct export_operations cifs_export_ops = {
+const struct export_operations cifs_export_ops = {
.get_parent = cifs_get_parent,
/* Following five export operations are unneeded so far and can default:
.get_dentry =
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 894b1f7b299d..68ad4ca0cfa3 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -467,7 +467,7 @@ reopen_error_exit:
int cifs_close(struct inode *inode, struct file *file)
{
int rc = 0;
- int xid;
+ int xid, timeout;
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
struct cifsFileInfo *pSMBFile =
@@ -485,9 +485,9 @@ int cifs_close(struct inode *inode, struct file *file)
/* no sense reconnecting to close a file that is
already closed */
if (pTcon->tidStatus != CifsNeedReconnect) {
- int timeout = 2;
+ timeout = 2;
while ((atomic_read(&pSMBFile->wrtPending) != 0)
- && (timeout < 1000) ) {
+ && (timeout <= 2048)) {
/* Give write a better chance to get to
server ahead of the close. We do not
want to add a wait_q here as it would
@@ -522,12 +522,30 @@ int cifs_close(struct inode *inode, struct file *file)
list_del(&pSMBFile->flist);
list_del(&pSMBFile->tlist);
write_unlock(&GlobalSMBSeslock);
+ timeout = 10;
+ /* We waited above to give the SMBWrite a chance to issue
+ on the wire (so we do not get SMBWrite returning EBADF
+ if writepages is racing with close. Note that writepages
+ does not specify a file handle, so it is possible for a file
+ to be opened twice, and the application close the "wrong"
+ file handle - in these cases we delay long enough to allow
+ the SMBWrite to get on the wire before the SMB Close.
+ We allow total wait here over 45 seconds, more than
+ oplock break time, and more than enough to allow any write
+ to complete on the server, or to time out on the client */
+ while ((atomic_read(&pSMBFile->wrtPending) != 0)
+ && (timeout <= 50000)) {
+ cERROR(1, ("writes pending, delay free of handle"));
+ msleep(timeout);
+ timeout *= 8;
+ }
kfree(pSMBFile->search_resume_name);
kfree(file->private_data);
file->private_data = NULL;
} else
rc = -EBADF;
+ read_lock(&GlobalSMBSeslock);
if (list_empty(&(CIFS_I(inode)->openFileList))) {
cFYI(1, ("closing last open instance for inode %p", inode));
/* if the file is not open we do not know if we can cache info
@@ -535,6 +553,7 @@ int cifs_close(struct inode *inode, struct file *file)
CIFS_I(inode)->clientCanCacheRead = FALSE;
CIFS_I(inode)->clientCanCacheAll = FALSE;
}
+ read_unlock(&GlobalSMBSeslock);
if ((rc == 0) && CIFS_I(inode)->write_behind_rc)
rc = CIFS_I(inode)->write_behind_rc;
FreeXid(xid);
@@ -767,7 +786,8 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
mutex_lock(&fid->lock_mutex);
list_for_each_entry_safe(li, tmp, &fid->llist, llist) {
if (pfLock->fl_start <= li->offset &&
- length >= li->length) {
+ (pfLock->fl_start + length) >=
+ (li->offset + li->length)) {
stored_rc = CIFSSMBLock(xid, pTcon,
netfid,
li->length, li->offset,
@@ -1006,6 +1026,37 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
return total_written;
}
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode)
+{
+ struct cifsFileInfo *open_file = NULL;
+
+ read_lock(&GlobalSMBSeslock);
+ /* we could simply get the first_list_entry since write-only entries
+ are always at the end of the list but since the first entry might
+ have a close pending, we go through the whole list */
+ list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
+ if (open_file->closePend)
+ continue;
+ if (open_file->pfile && ((open_file->pfile->f_flags & O_RDWR) ||
+ (open_file->pfile->f_flags & O_RDONLY))) {
+ if (!open_file->invalidHandle) {
+ /* found a good file */
+ /* lock it so it will not be closed on us */
+ atomic_inc(&open_file->wrtPending);
+ read_unlock(&GlobalSMBSeslock);
+ return open_file;
+ } /* else might as well continue, and look for
+ another, or simply have the caller reopen it
+ again rather than trying to fix this handle */
+ } else /* write only file */
+ break; /* write only files are last so must be done */
+ }
+ read_unlock(&GlobalSMBSeslock);
+ return NULL;
+}
+#endif
+
struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
{
struct cifsFileInfo *open_file;
@@ -1022,6 +1073,7 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
}
read_lock(&GlobalSMBSeslock);
+refind_writable:
list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
if (open_file->closePend)
continue;
@@ -1029,24 +1081,49 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
((open_file->pfile->f_flags & O_RDWR) ||
(open_file->pfile->f_flags & O_WRONLY))) {
atomic_inc(&open_file->wrtPending);
+
+ if (!open_file->invalidHandle) {
+ /* found a good writable file */
+ read_unlock(&GlobalSMBSeslock);
+ return open_file;
+ }
+
read_unlock(&GlobalSMBSeslock);
- if ((open_file->invalidHandle) &&
- (!open_file->closePend) /* BB fixme -since the second clause can not be true remove it BB */) {
- rc = cifs_reopen_file(open_file->pfile, FALSE);
- /* if it fails, try another handle - might be */
- /* dangerous to hold up writepages with retry */
- if (rc) {
- cFYI(1,
- ("failed on reopen file in wp"));
+ /* Had to unlock since following call can block */
+ rc = cifs_reopen_file(open_file->pfile, FALSE);
+ if (!rc) {
+ if (!open_file->closePend)
+ return open_file;
+ else { /* start over in case this was deleted */
+ /* since the list could be modified */
read_lock(&GlobalSMBSeslock);
- /* can not use this handle, no write
- pending on this one after all */
- atomic_dec
- (&open_file->wrtPending);
- continue;
+ atomic_dec(&open_file->wrtPending);
+ goto refind_writable;
}
}
- return open_file;
+
+ /* if it fails, try another handle if possible -
+ (we can not do this if closePending since
+ loop could be modified - in which case we
+ have to start at the beginning of the list
+ again. Note that it would be bad
+ to hold up writepages here (rather than
+ in caller) with continuous retries */
+ cFYI(1, ("wp failed on reopen file"));
+ read_lock(&GlobalSMBSeslock);
+ /* can not use this handle, no write
+ pending on this one after all */
+ atomic_dec(&open_file->wrtPending);
+
+ if (open_file->closePend) /* list could have changed */
+ goto refind_writable;
+ /* else we simply continue to the next entry. Thus
+ we do not loop on reopen errors. If we
+ can not reopen the file, for example if we
+ reconnected to a server with another client
+ racing to delete or lock the file we would not
+ make progress if we restarted before the beginning
+ of the loop here. */
}
}
read_unlock(&GlobalSMBSeslock);
@@ -1709,7 +1786,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
struct page *page;
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
- int bytes_read = 0;
+ unsigned int bytes_read = 0;
unsigned int read_size, i;
char *smb_read_data = NULL;
struct smb_com_read_rsp *pSMBr;
@@ -1803,7 +1880,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
i += bytes_read >> PAGE_CACHE_SHIFT;
cifs_stats_bytes_read(pTcon, bytes_read);
- if ((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
+ if ((bytes_read & PAGE_CACHE_MASK) != bytes_read) {
i++; /* account for partial page */
/* server copy of file can have smaller size
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index dd4167762a8e..7d907e84e032 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -115,7 +115,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
inode->i_mode = le64_to_cpu(findData.Permissions);
/* since we set the inode type below we need to mask off
to avoid strange results if bits set above */
- inode->i_mode &= ~S_IFMT;
+ inode->i_mode &= ~S_IFMT;
if (type == UNIX_FILE) {
inode->i_mode |= S_IFREG;
} else if (type == UNIX_SYMLINK) {
@@ -289,7 +289,7 @@ static int decode_sfu_inode(struct inode *inode, __u64 size,
#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
-static int get_sfu_uid_mode(struct inode *inode,
+static int get_sfu_mode(struct inode *inode,
const unsigned char *path,
struct cifs_sb_info *cifs_sb, int xid)
{
@@ -527,11 +527,16 @@ int cifs_get_inode_info(struct inode **pinode,
/* BB fill in uid and gid here? with help from winbind?
or retrieve from NTFS stream extended attribute */
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+ /* fill in 0777 bits from ACL */
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
+ cFYI(1, ("Getting mode bits from ACL"));
+ acl_to_uid_mode(inode, search_path);
+ }
+#endif
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
- /* fill in uid, gid, mode from server ACL */
- /* BB FIXME this should also take into account the
- * default uid specified on mount if present */
- get_sfu_uid_mode(inode, search_path, cifs_sb, xid);
+ /* fill in remaining high mode bits e.g. SUID, VTX */
+ get_sfu_mode(inode, search_path, cifs_sb, xid);
} else if (atomic_read(&cifsInfo->inUse) == 0) {
inode->i_uid = cifs_sb->mnt_uid;
inode->i_gid = cifs_sb->mnt_gid;
@@ -575,19 +580,33 @@ int cifs_get_inode_info(struct inode **pinode,
return rc;
}
+static const struct inode_operations cifs_ipc_inode_ops = {
+ .lookup = cifs_lookup,
+};
+
/* gets root inode */
void cifs_read_inode(struct inode *inode)
{
- int xid;
+ int xid, rc;
struct cifs_sb_info *cifs_sb;
cifs_sb = CIFS_SB(inode->i_sb);
xid = GetXid();
if (cifs_sb->tcon->unix_ext)
- cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid);
+ rc = cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid);
else
- cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid);
+ rc = cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid);
+ if (rc && cifs_sb->tcon->ipc) {
+ cFYI(1, ("ipc connection - fake read inode"));
+ inode->i_mode |= S_IFDIR;
+ inode->i_nlink = 2;
+ inode->i_op = &cifs_ipc_inode_ops;
+ inode->i_fop = &simple_dir_operations;
+ inode->i_uid = cifs_sb->mnt_uid;
+ inode->i_gid = cifs_sb->mnt_gid;
+ }
+
/* can not call macro FreeXid here since in a void func */
_FreeXid(xid);
}
@@ -919,18 +938,25 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
goto mkdir_out;
}
+ mode &= ~current->fs->umask;
rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT,
mode, NULL /* netfid */, pInfo, &oplock,
full_path, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
- if (rc) {
+ if (rc == -EOPNOTSUPP) {
+ kfree(pInfo);
+ goto mkdir_retry_old;
+ } else if (rc) {
cFYI(1, ("posix mkdir returned 0x%x", rc));
d_drop(direntry);
} else {
int obj_type;
- if (pInfo->Type == -1) /* no return info - go query */
+ if (pInfo->Type == cpu_to_le32(-1)) {
+ /* no return info, go query for it */
+ kfree(pInfo);
goto mkdir_get_info;
+ }
/*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need
to set uid/gid */
inc_nlink(inode);
@@ -940,8 +966,10 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
direntry->d_op = &cifs_dentry_ops;
newinode = new_inode(inode->i_sb);
- if (newinode == NULL)
+ 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? */
@@ -972,7 +1000,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
kfree(pInfo);
goto mkdir_out;
}
-
+mkdir_retry_old:
/* BB add setting the equivalent of mode via CreateX w/ACLs */
rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -1377,8 +1405,17 @@ static int cifs_vmtruncate(struct inode *inode, loff_t offset)
}
i_size_write(inode, offset);
spin_unlock(&inode->i_lock);
+ /*
+ * unmap_mapping_range is called twice, first simply for efficiency
+ * so that truncate_inode_pages does fewer single-page unmaps. However
+ * after this first call, and before truncate_inode_pages finishes,
+ * it is possible for private pages to be COWed, which remain after
+ * truncate_inode_pages finishes, hence the second unmap_mapping_range
+ * call must be made for correctness.
+ */
unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
truncate_inode_pages(mapping, offset);
+ unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
goto out_truncate;
do_expand:
@@ -1469,7 +1506,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
atomic_dec(&open_file->wrtPending);
cFYI(1, ("SetFSize for attrs rc = %d", rc));
if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
- int bytes_written;
+ unsigned int bytes_written;
rc = CIFSSMBWrite(xid, pTcon,
nfid, 0, attrs->ia_size,
&bytes_written, NULL, NULL,
@@ -1502,7 +1539,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc == 0) {
- int bytes_written;
+ unsigned int bytes_written;
rc = CIFSSMBWrite(xid, pTcon,
netfid, 0,
attrs->ia_size,
@@ -1538,6 +1575,11 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
}
time_buf.Attributes = 0;
+
+ /* skip mode change if it's just for clearing setuid/setgid */
+ if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
+ attrs->ia_valid &= ~ATTR_MODE;
+
if (attrs->ia_valid & ATTR_MODE) {
cFYI(1, ("Mode changed to 0x%x", attrs->ia_mode));
mode = attrs->ia_mode;
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 6a85ef7b8797..11f265726db7 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -237,7 +237,7 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
char *tmp_path = NULL;
char *tmpbuffer;
unsigned char *referrals = NULL;
- int num_referrals = 0;
+ unsigned int num_referrals = 0;
int len;
__u16 fid;
diff --git a/fs/cifs/md5.c b/fs/cifs/md5.c
index e5c3e1212697..f13f96d42fcf 100644
--- a/fs/cifs/md5.c
+++ b/fs/cifs/md5.c
@@ -276,8 +276,8 @@ hmac_md5_init_rfc2104(unsigned char *key, int key_len,
}
/* start out by storing key in pads */
- memset(ctx->k_ipad, 0, sizeof (ctx->k_ipad));
- memset(ctx->k_opad, 0, sizeof (ctx->k_opad));
+ memset(ctx->k_ipad, 0, sizeof(ctx->k_ipad));
+ memset(ctx->k_opad, 0, sizeof(ctx->k_opad));
memcpy(ctx->k_ipad, key, key_len);
memcpy(ctx->k_opad, key, key_len);
@@ -307,8 +307,8 @@ hmac_md5_init_limK_to_64(const unsigned char *key, int key_len,
}
/* start out by storing key in pads */
- memset(ctx->k_ipad, 0, sizeof (ctx->k_ipad));
- memset(ctx->k_opad, 0, sizeof (ctx->k_opad));
+ memset(ctx->k_ipad, 0, sizeof(ctx->k_ipad));
+ memset(ctx->k_opad, 0, sizeof(ctx->k_opad));
memcpy(ctx->k_ipad, key, key_len);
memcpy(ctx->k_opad, key, key_len);
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 0bcec0844bee..15546c2354c5 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -73,7 +73,7 @@ sesInfoAlloc(void)
{
struct cifsSesInfo *ret_buf;
- ret_buf = kzalloc(sizeof (struct cifsSesInfo), GFP_KERNEL);
+ ret_buf = kzalloc(sizeof(struct cifsSesInfo), GFP_KERNEL);
if (ret_buf) {
write_lock(&GlobalSMBSeslock);
atomic_inc(&sesInfoAllocCount);
@@ -109,7 +109,7 @@ struct cifsTconInfo *
tconInfoAlloc(void)
{
struct cifsTconInfo *ret_buf;
- ret_buf = kzalloc(sizeof (struct cifsTconInfo), GFP_KERNEL);
+ ret_buf = kzalloc(sizeof(struct cifsTconInfo), GFP_KERNEL);
if (ret_buf) {
write_lock(&GlobalSMBSeslock);
atomic_inc(&tconInfoAllocCount);
@@ -169,7 +169,6 @@ cifs_buf_get(void)
void
cifs_buf_release(void *buf_to_free)
{
-
if (buf_to_free == NULL) {
/* cFYI(1, ("Null buffer passed to cifs_buf_release"));*/
return;
@@ -299,7 +298,7 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
memset(temp, 0, 256); /* bigger than MAX_CIFS_HDR_SIZE */
buffer->smb_buf_length =
- (2 * word_count) + sizeof (struct smb_hdr) -
+ (2 * word_count) + sizeof(struct smb_hdr) -
4 /* RFC 1001 length field does not count */ +
2 /* for bcc field itself */ ;
/* Note that this is the only network field that has to be converted
@@ -423,8 +422,8 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length)
__u32 clc_len; /* calculated length */
cFYI(0, ("checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len));
- if (length < 2 + sizeof (struct smb_hdr)) {
- if ((length >= sizeof (struct smb_hdr) - 1)
+ if (length < 2 + sizeof(struct smb_hdr)) {
+ if ((length >= sizeof(struct smb_hdr) - 1)
&& (smb->Status.CifsError != 0)) {
smb->WordCount = 0;
/* some error cases do not return wct and bcc */
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index 2bfed3f45d0f..646e1f06941b 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -114,10 +114,16 @@ static const struct smb_to_posix_error mapping_table_ERRSRV[] = {
{ERRusempx, -EIO},
{ERRusestd, -EIO},
{ERR_NOTIFY_ENUM_DIR, -ENOBUFS},
- {ERRaccountexpired, -EACCES},
+ {ERRnoSuchUser, -EACCES},
+/* {ERRaccountexpired, -EACCES},
{ERRbadclient, -EACCES},
{ERRbadLogonTime, -EACCES},
- {ERRpasswordExpired, -EACCES},
+ {ERRpasswordExpired, -EACCES},*/
+ {ERRaccountexpired, -EKEYEXPIRED},
+ {ERRbadclient, -EACCES},
+ {ERRbadLogonTime, -EACCES},
+ {ERRpasswordExpired, -EKEYEXPIRED},
+
{ERRnosupport, -EINVAL},
{0, 0}
};
@@ -126,6 +132,34 @@ static const struct smb_to_posix_error mapping_table_ERRHRD[] = {
{0, 0}
};
+
+/* if the mount helper is missing we need to reverse the 1st slash
+ from '/' to backslash in order to format the UNC properly for
+ ip address parsing and for tree connect (unless the user
+ remembered to put the UNC name in properly). Fortunately we do
+ not have to call this twice (we check for IPv4 addresses
+ first, so it is already converted by the time we
+ try IPv6 addresses */
+static int canonicalize_unc(char *cp)
+{
+ int i;
+
+ for (i = 0; i <= 46 /* INET6_ADDRSTRLEN */ ; i++) {
+ if (cp[i] == 0)
+ break;
+ if (cp[i] == '\\')
+ break;
+ if (cp[i] == '/') {
+#ifdef CONFIG_CIFS_DEBUG2
+ cFYI(1, ("change slash to backslash in malformed UNC"));
+#endif
+ cp[i] = '\\';
+ return 1;
+ }
+ }
+ return 0;
+}
+
/* Convert string containing dotted ip address to binary form */
/* returns 0 if invalid address */
@@ -135,11 +169,13 @@ cifs_inet_pton(int address_family, char *cp, void *dst)
int ret = 0;
/* calculate length by finding first slash or NULL */
- /* BB Should we convert '/' slash to '\' here since it seems already
- * done before this */
- if ( address_family == AF_INET ) {
- ret = in4_pton(cp, -1 /* len */, dst , '\\', NULL);
- } else if ( address_family == AF_INET6 ) {
+ if (address_family == AF_INET) {
+ ret = in4_pton(cp, -1 /* len */, dst, '\\', NULL);
+ if (ret == 0) {
+ if (canonicalize_unc(cp))
+ ret = in4_pton(cp, -1, dst, '\\', NULL);
+ }
+ } else if (address_family == AF_INET6) {
ret = in6_pton(cp, -1 /* len */, dst , '\\', NULL);
}
#ifdef CONFIG_CIFS_DEBUG2
@@ -270,7 +306,7 @@ static const struct {
from NT_STATUS_NO_SUCH_USER to NT_STATUS_LOGON_FAILURE
during the session setup } */
{
- ERRDOS, ERRnoaccess, NT_STATUS_NO_SUCH_USER}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_NO_SUCH_USER}, { /* could map to 2238 */
ERRHRD, ERRgeneral, NT_STATUS_GROUP_EXISTS}, {
ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_GROUP}, {
ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_GROUP}, {
@@ -285,10 +321,10 @@ static const struct {
ERRHRD, ERRgeneral, NT_STATUS_PASSWORD_RESTRICTION}, {
ERRDOS, ERRnoaccess, NT_STATUS_LOGON_FAILURE}, {
ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, {
- ERRSRV, 2241, NT_STATUS_INVALID_LOGON_HOURS}, {
- ERRSRV, 2240, NT_STATUS_INVALID_WORKSTATION}, {
+ ERRSRV, ERRbadLogonTime, NT_STATUS_INVALID_LOGON_HOURS}, {
+ ERRSRV, ERRbadclient, NT_STATUS_INVALID_WORKSTATION}, {
ERRSRV, ERRpasswordExpired, NT_STATUS_PASSWORD_EXPIRED}, {
- ERRSRV, 2239, NT_STATUS_ACCOUNT_DISABLED}, {
+ ERRSRV, ERRaccountexpired, NT_STATUS_ACCOUNT_DISABLED}, {
ERRHRD, ERRgeneral, NT_STATUS_NONE_MAPPED}, {
ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, {
ERRHRD, ERRgeneral, NT_STATUS_LUIDS_EXHAUSTED}, {
@@ -585,7 +621,7 @@ static const struct {
ERRDOS, ERRnoaccess, NT_STATUS_TRUST_FAILURE}, {
ERRHRD, ERRgeneral, NT_STATUS_MUTANT_LIMIT_EXCEEDED}, {
ERRDOS, ERRnetlogonNotStarted, NT_STATUS_NETLOGON_NOT_STARTED}, {
- ERRSRV, 2239, NT_STATUS_ACCOUNT_EXPIRED}, {
+ ERRSRV, ERRaccountexpired, NT_STATUS_ACCOUNT_EXPIRED}, {
ERRHRD, ERRgeneral, NT_STATUS_POSSIBLE_DEADLOCK}, {
ERRHRD, ERRgeneral, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT}, {
ERRHRD, ERRgeneral, NT_STATUS_REMOTE_SESSION_LIMIT}, {
@@ -734,7 +770,7 @@ cifs_print_status(__u32 status_code)
static void
-ntstatus_to_dos(__u32 ntstatus, __u8 * eclass, __u16 * ecode)
+ntstatus_to_dos(__u32 ntstatus, __u8 *eclass, __u16 *ecode)
{
int i;
if (ntstatus == 0) {
@@ -754,7 +790,7 @@ ntstatus_to_dos(__u32 ntstatus, __u8 * eclass, __u16 * ecode)
}
int
-map_smb_to_linux_error(struct smb_hdr *smb)
+map_smb_to_linux_error(struct smb_hdr *smb, int logErr)
{
unsigned int i;
int rc = -EIO; /* if transport error smb error may not be set */
@@ -771,7 +807,9 @@ map_smb_to_linux_error(struct smb_hdr *smb)
/* translate the newer STATUS codes to old style SMB errors
* and then to POSIX errors */
__u32 err = le32_to_cpu(smb->Status.CifsError);
- if (cifsFYI & CIFS_RC)
+ if (logErr && (err != (NT_STATUS_MORE_PROCESSING_REQUIRED)))
+ cifs_print_status(err);
+ else if (cifsFYI & CIFS_RC)
cifs_print_status(err);
ntstatus_to_dos(err, &smberrclass, &smberrcode);
} else {
@@ -785,8 +823,8 @@ map_smb_to_linux_error(struct smb_hdr *smb)
if (smberrclass == ERRDOS) { /* 1 byte field no need to byte reverse */
for (i = 0;
i <
- sizeof (mapping_table_ERRDOS) /
- sizeof (struct smb_to_posix_error); i++) {
+ sizeof(mapping_table_ERRDOS) /
+ sizeof(struct smb_to_posix_error); i++) {
if (mapping_table_ERRDOS[i].smb_err == 0)
break;
else if (mapping_table_ERRDOS[i].smb_err ==
@@ -799,8 +837,8 @@ map_smb_to_linux_error(struct smb_hdr *smb)
} else if (smberrclass == ERRSRV) { /* server class of error codes */
for (i = 0;
i <
- sizeof (mapping_table_ERRSRV) /
- sizeof (struct smb_to_posix_error); i++) {
+ sizeof(mapping_table_ERRSRV) /
+ sizeof(struct smb_to_posix_error); i++) {
if (mapping_table_ERRSRV[i].smb_err == 0)
break;
else if (mapping_table_ERRSRV[i].smb_err ==
@@ -813,7 +851,7 @@ map_smb_to_linux_error(struct smb_hdr *smb)
}
/* else ERRHRD class errors or junk - return EIO */
- cFYI(1, (" !!Mapping smb error code %d to POSIX err %d !!",
+ cFYI(1, ("Mapping smb error code %d to POSIX err %d",
smberrcode, rc));
/* generic corrective action e.g. reconnect SMB session on
@@ -829,14 +867,14 @@ map_smb_to_linux_error(struct smb_hdr *smb)
unsigned int
smbCalcSize(struct smb_hdr *ptr)
{
- return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) +
+ return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) +
2 /* size of the bcc field */ + BCC(ptr));
}
unsigned int
smbCalcSize_LE(struct smb_hdr *ptr)
{
- return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) +
+ return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) +
2 /* size of the bcc field */ + le16_to_cpu(BCC_LE(ptr)));
}
@@ -899,8 +937,11 @@ struct timespec cnvrtDosUnixTm(__u16 date, __u16 time)
cERROR(1, ("illegal hours %d", st->Hours));
days = sd->Day;
month = sd->Month;
- if ((days > 31) || (month > 12))
+ if ((days > 31) || (month > 12)) {
cERROR(1, ("illegal date, month %d day: %d", month, days));
+ if (month > 12)
+ month = 12;
+ }
month -= 1;
days += total_days_of_prev_months[month];
days += 3652; /* account for difference in days between 1980 and 1970 */
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 916df9431336..0f22def4bdff 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -121,7 +121,7 @@ static void AdjustForTZ(struct cifsTconInfo *tcon, struct inode *inode)
static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
- char *buf, int *pobject_type, int isNewInode)
+ char *buf, unsigned int *pobject_type, int isNewInode)
{
loff_t local_size;
struct timespec local_mtime;
@@ -171,7 +171,13 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
/* Linux can not store file creation time unfortunately so ignore it */
cifsInfo->cifsAttrs = attr;
- cifsInfo->time = jiffies;
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
+ /* get more accurate mode via ACL - so force inode refresh */
+ cifsInfo->time = 0;
+ } else
+#endif /* CONFIG_CIFS_EXPERIMENTAL */
+ cifsInfo->time = jiffies;
/* treat dos attribute of read-only as read-only mode bit e.g. 555? */
/* 2767 perms - indicate mandatory locking */
@@ -294,7 +300,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
}
static void unix_fill_in_inode(struct inode *tmp_inode,
- FILE_UNIX_INFO *pfindData, int *pobject_type, int isNewInode)
+ FILE_UNIX_INFO *pfindData, unsigned int *pobject_type, int isNewInode)
{
loff_t local_size;
struct timespec local_mtime;
@@ -495,7 +501,7 @@ ffirst_retry:
static int cifs_unicode_bytelen(char *str)
{
int len;
- __le16 * ustr = (__le16 *)str;
+ __le16 *ustr = (__le16 *)str;
for (len = 0; len <= PATH_MAX; len++) {
if (ustr[len] == 0)
@@ -826,7 +832,7 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
int rc = 0;
struct qstr qstring;
struct cifsFileInfo *pCifsF;
- unsigned obj_type;
+ unsigned int obj_type;
ino_t inum;
struct cifs_sb_info *cifs_sb;
struct inode *tmp_inode;
@@ -1067,7 +1073,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
for (i = 0; (i < num_to_fill) && (rc == 0); i++) {
if (current_entry == NULL) {
/* evaluate whether this case is an error */
- cERROR(1,("past end of SMB num to fill %d i %d",
+ cERROR(1, ("past SMB end, num to fill %d i %d",
num_to_fill, i));
break;
}
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 892be9b4d1f3..899dc6078d9a 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -67,14 +67,59 @@ static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
pSMB->req.hdr.Flags2 |= SMBFLG2_DFS;
capabilities |= CAP_DFS;
}
- if (ses->capabilities & CAP_UNIX) {
+ if (ses->capabilities & CAP_UNIX)
capabilities |= CAP_UNIX;
- }
/* BB check whether to init vcnum BB */
return capabilities;
}
+static void
+unicode_oslm_strings(char **pbcc_area, const struct nls_table *nls_cp)
+{
+ char *bcc_ptr = *pbcc_area;
+ int bytes_ret = 0;
+
+ /* Copy OS version */
+ bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32,
+ nls_cp);
+ bcc_ptr += 2 * bytes_ret;
+ bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, init_utsname()->release,
+ 32, nls_cp);
+ bcc_ptr += 2 * bytes_ret;
+ bcc_ptr += 2; /* trailing null */
+
+ bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
+ 32, nls_cp);
+ bcc_ptr += 2 * bytes_ret;
+ bcc_ptr += 2; /* trailing null */
+
+ *pbcc_area = bcc_ptr;
+}
+
+static void unicode_domain_string(char **pbcc_area, struct cifsSesInfo *ses,
+ const struct nls_table *nls_cp)
+{
+ char *bcc_ptr = *pbcc_area;
+ int bytes_ret = 0;
+
+ /* copy domain */
+ if (ses->domainName == NULL) {
+ /* Sending null domain better than using a bogus domain name (as
+ we did briefly in 2.6.18) since server will use its default */
+ *bcc_ptr = 0;
+ *(bcc_ptr+1) = 0;
+ bytes_ret = 0;
+ } else
+ bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName,
+ 256, nls_cp);
+ bcc_ptr += 2 * bytes_ret;
+ bcc_ptr += 2; /* account for null terminator */
+
+ *pbcc_area = bcc_ptr;
+}
+
+
static void unicode_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses,
const struct nls_table *nls_cp)
{
@@ -100,32 +145,9 @@ static void unicode_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses,
}
bcc_ptr += 2 * bytes_ret;
bcc_ptr += 2; /* account for null termination */
- /* copy domain */
- if (ses->domainName == NULL) {
- /* Sending null domain better than using a bogus domain name (as
- we did briefly in 2.6.18) since server will use its default */
- *bcc_ptr = 0;
- *(bcc_ptr+1) = 0;
- bytes_ret = 0;
- } else
- bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName,
- 256, nls_cp);
- bcc_ptr += 2 * bytes_ret;
- bcc_ptr += 2; /* account for null terminator */
-
- /* Copy OS version */
- bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32,
- nls_cp);
- bcc_ptr += 2 * bytes_ret;
- bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, init_utsname()->release,
- 32, nls_cp);
- bcc_ptr += 2 * bytes_ret;
- bcc_ptr += 2; /* trailing null */
- bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
- 32, nls_cp);
- bcc_ptr += 2 * bytes_ret;
- bcc_ptr += 2; /* trailing null */
+ unicode_domain_string(&bcc_ptr, ses, nls_cp);
+ unicode_oslm_strings(&bcc_ptr, nls_cp);
*pbcc_area = bcc_ptr;
}
@@ -203,14 +225,11 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft,
if (len >= words_left)
return rc;
- if (ses->serverOS)
- kfree(ses->serverOS);
+ 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);
- if (ses->serverOS != NULL) {
- cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len,
- nls_cp);
- }
+ if (ses->serverOS != NULL)
+ cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, nls_cp);
data += 2 * (len + 1);
words_left -= len + 1;
@@ -220,8 +239,7 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft,
if (len >= words_left)
return rc;
- if (ses->serverNOS)
- kfree(ses->serverNOS);
+ kfree(ses->serverNOS);
ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */
if (ses->serverNOS != NULL) {
cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len,
@@ -240,8 +258,7 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft,
if (len > words_left)
return rc;
- if (ses->serverDomain)
- kfree(ses->serverDomain);
+ kfree(ses->serverDomain);
ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */
if (ses->serverDomain != NULL) {
cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len,
@@ -271,8 +288,7 @@ static int decode_ascii_ssetup(char **pbcc_area, int bleft,
if (len >= bleft)
return rc;
- if (ses->serverOS)
- kfree(ses->serverOS);
+ kfree(ses->serverOS);
ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
if (ses->serverOS)
@@ -289,8 +305,7 @@ static int decode_ascii_ssetup(char **pbcc_area, int bleft,
if (len >= bleft)
return rc;
- if (ses->serverNOS)
- kfree(ses->serverNOS);
+ kfree(ses->serverNOS);
ses->serverNOS = kzalloc(len + 1, GFP_KERNEL);
if (ses->serverNOS)
@@ -479,7 +494,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
if (ses->capabilities & CAP_UNICODE) {
if (iov[0].iov_len % 2) {
*bcc_ptr = 0;
- } bcc_ptr++;
+ bcc_ptr++;
+ }
unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
} else
ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
@@ -497,7 +513,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
iov[1].iov_base = str_area;
iov[1].iov_len = count;
- rc = SendReceive2(xid, ses, iov, 2 /* num_iovecs */, &resp_buf_type, 0);
+ rc = SendReceive2(xid, ses, iov, 2 /* num_iovecs */, &resp_buf_type,
+ 0 /* not long op */, 1 /* log NT STATUS if any */ );
/* SMB request buf freed in SendReceive2 */
cFYI(1, ("ssetup rc from sendrecv2 is %d", rc));
diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c
index 90542a39be17..58bbfd992cc0 100644
--- a/fs/cifs/smbencrypt.c
+++ b/fs/cifs/smbencrypt.c
@@ -80,7 +80,7 @@ SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
/* Routines for Windows NT MD4 Hash functions. */
static int
-_my_wcslen(__u16 * str)
+_my_wcslen(__u16 *str)
{
int len = 0;
while (*str++ != 0)
@@ -96,7 +96,7 @@ _my_wcslen(__u16 * str)
*/
static int
-_my_mbstowcs(__u16 * dst, const unsigned char *src, int len)
+_my_mbstowcs(__u16 *dst, const unsigned char *src, int len)
{ /* BB not a very good conversion routine - change/fix */
int i;
__u16 val;
@@ -125,9 +125,9 @@ E_md4hash(const unsigned char *passwd, unsigned char *p16)
/* Password cannot be longer than 128 characters */
if (passwd) {
len = strlen((char *) passwd);
- if (len > 128) {
+ if (len > 128)
len = 128;
- }
+
/* Password must be converted to NT unicode */
_my_mbstowcs(wpwd, passwd, len);
} else
@@ -135,7 +135,7 @@ E_md4hash(const unsigned char *passwd, unsigned char *p16)
wpwd[len] = 0; /* Ensure string is null terminated */
/* Calculate length in bytes */
- len = _my_wcslen(wpwd) * sizeof (__u16);
+ len = _my_wcslen(wpwd) * sizeof(__u16);
mdfour(p16, (unsigned char *) wpwd, len);
memset(wpwd, 0, 129 * 2);
@@ -167,7 +167,7 @@ nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16])
E_P16((unsigned char *) passwd, (unsigned char *) p16);
/* clear out local copy of user's password (just being paranoid). */
- memset(passwd, '\0', sizeof (passwd));
+ memset(passwd, '\0', sizeof(passwd));
}
#endif
@@ -189,8 +189,10 @@ ntv2_owf_gen(const unsigned char owf[16], const char *user_n,
return;
dom_u = user_u + 1024;
- /* push_ucs2(NULL, user_u, user_n, (user_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER);
- push_ucs2(NULL, dom_u, domain_n, (domain_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER); */
+ /* push_ucs2(NULL, user_u, user_n, (user_l+1)*2,
+ STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER);
+ push_ucs2(NULL, dom_u, domain_n, (domain_l+1)*2,
+ STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER); */
/* BB user and domain may need to be uppercased */
user_l = cifs_strtoUCS(user_u, user_n, 511, nls_codepage);
diff --git a/fs/cifs/smberr.h b/fs/cifs/smberr.h
index 2ef0be288820..7f50e8577c1c 100644
--- a/fs/cifs/smberr.h
+++ b/fs/cifs/smberr.h
@@ -173,9 +173,10 @@
#define ERRusestd 251 /* temporarily unable to use either raw
or mpx */
#define ERR_NOTIFY_ENUM_DIR 1024
+#define ERRnoSuchUser 2238 /* user account does not exist */
#define ERRaccountexpired 2239
-#define ERRbadclient 2240
-#define ERRbadLogonTime 2241
+#define ERRbadclient 2240 /* can not logon from this client */
+#define ERRbadLogonTime 2241 /* logon hours do not allow this */
#define ERRpasswordExpired 2242
#define ERRnetlogonNotStarted 2455
#define ERRnosupport 0xFFFF
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 746bc9405db1..7ed32b3cb781 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -55,7 +55,7 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
if (temp == NULL)
return temp;
else {
- memset(temp, 0, sizeof (struct mid_q_entry));
+ memset(temp, 0, sizeof(struct mid_q_entry));
temp->mid = smb_buffer->Mid; /* always LE */
temp->pid = current->pid;
temp->command = smb_buffer->Command;
@@ -158,7 +158,7 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
iov.iov_len = len;
smb_msg.msg_name = sin;
- smb_msg.msg_namelen = sizeof (struct sockaddr);
+ smb_msg.msg_namelen = sizeof(struct sockaddr);
smb_msg.msg_control = NULL;
smb_msg.msg_controllen = 0;
smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
@@ -228,7 +228,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
return -ENOTSOCK; /* BB eventually add reconnect code here */
smb_msg.msg_name = sin;
- smb_msg.msg_namelen = sizeof (struct sockaddr);
+ smb_msg.msg_namelen = sizeof(struct sockaddr);
smb_msg.msg_control = NULL;
smb_msg.msg_controllen = 0;
smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
@@ -363,9 +363,8 @@ static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
} /* else ok - we are setting up session */
}
*ppmidQ = AllocMidQEntry(in_buf, ses);
- if (*ppmidQ == NULL) {
+ if (*ppmidQ == NULL)
return -ENOMEM;
- }
return 0;
}
@@ -419,7 +418,7 @@ static int wait_for_response(struct cifsSesInfo *ses,
int
SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
- const int long_op)
+ const int long_op, const int logError)
{
int rc = 0;
unsigned int receive_len;
@@ -465,7 +464,6 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
wake_up(&ses->server->request_q);
return rc;
}
-
rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
midQ->midState = MID_REQUEST_SUBMITTED;
@@ -568,13 +566,11 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
}
/* BB special case reconnect tid and uid here? */
- /* BB special case Errbadpassword and pwdexpired here */
- rc = map_smb_to_linux_error(midQ->resp_buf);
+ rc = map_smb_to_linux_error(midQ->resp_buf, logError);
/* convert ByteCount if necessary */
- if (receive_len >=
- sizeof (struct smb_hdr) -
- 4 /* do not count RFC1001 header */ +
+ if (receive_len >= sizeof(struct smb_hdr) - 4
+ /* do not count RFC1001 header */ +
(2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
BCC(midQ->resp_buf) =
le16_to_cpu(BCC_LE(midQ->resp_buf));
@@ -749,12 +745,11 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
*pbytes_returned = out_buf->smb_buf_length;
/* BB special case reconnect tid and uid here? */
- rc = map_smb_to_linux_error(out_buf);
+ rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
/* convert ByteCount if necessary */
- if (receive_len >=
- sizeof (struct smb_hdr) -
- 4 /* do not count RFC1001 header */ +
+ if (receive_len >= sizeof(struct smb_hdr) - 4
+ /* do not count RFC1001 header */ +
(2 * out_buf->WordCount) + 2 /* bcc */ )
BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
} else {
@@ -993,12 +988,11 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
*pbytes_returned = out_buf->smb_buf_length;
/* BB special case reconnect tid and uid here? */
- rc = map_smb_to_linux_error(out_buf);
+ rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
/* convert ByteCount if necessary */
- if (receive_len >=
- sizeof (struct smb_hdr) -
- 4 /* do not count RFC1001 header */ +
+ if (receive_len >= sizeof(struct smb_hdr) - 4
+ /* do not count RFC1001 header */ +
(2 * out_buf->WordCount) + 2 /* bcc */ )
BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
} else {
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index f61e433d281c..54e8ef96cb79 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -261,21 +261,27 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
-/* else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+ else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
__u16 fid;
int oplock = FALSE;
- rc = CIFSSMBOpen(xid, pTcon, full_path,
- FILE_OPEN, GENERIC_READ, 0, &fid,
- &oplock, NULL, cifs_sb->local_nls,
- cifs_sb->mnt_cifs_flags &
- CIFS_MOUNT_MAP_SPECIAL_CHR);
- if(rc == 0) {
- rc = CIFSSMBGetCIFSACL(xid, pTcon, fid,
- ea_value, buf_size,
- ACL_TYPE_ACCESS);
+ struct cifs_ntsd *pacl = NULL;
+ __u32 buflen = 0;
+ if (experimEnabled)
+ rc = CIFSSMBOpen(xid, pTcon, full_path,
+ FILE_OPEN, GENERIC_READ, 0, &fid,
+ &oplock, NULL, cifs_sb->local_nls,
+ cifs_sb->mnt_cifs_flags &
+ CIFS_MOUNT_MAP_SPECIAL_CHR);
+ /* else rc is EOPNOTSUPP from above */
+
+ if (rc == 0) {
+ rc = CIFSSMBGetCIFSACL(xid, pTcon, fid, &pacl,
+ &buflen);
CIFSSMBClose(xid, pTcon, fid);
}
- } */ /* BB enable after fixing up return data */
+ }
+#endif /* EXPERIMENTAL */
#else
cFYI(1, ("query POSIX ACL not supported yet"));
#endif /* CONFIG_CIFS_POSIX */
diff --git a/fs/coda/inode.c b/fs/coda/inode.c
index 342f4e0d582e..2f58dfc70083 100644
--- a/fs/coda/inode.c
+++ b/fs/coda/inode.c
@@ -58,7 +58,7 @@ static void coda_destroy_inode(struct inode *inode)
kmem_cache_free(coda_inode_cachep, ITOC(inode));
}
-static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
+static void init_once(struct kmem_cache * cachep, void *foo)
{
struct coda_inode_info *ei = (struct coda_inode_info *) foo;
diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
index cdb4c07a7870..359e531094dd 100644
--- a/fs/coda/upcall.c
+++ b/fs/coda/upcall.c
@@ -51,7 +51,7 @@ static void *alloc_upcall(int opcode, int size)
inp->ih.opcode = opcode;
inp->ih.pid = current->pid;
- inp->ih.pgid = process_group(current);
+ inp->ih.pgid = task_pgrp_nr(current);
#ifdef CONFIG_CODA_FS_OLD_API
memset(&inp->ih.cred, 0, sizeof(struct coda_cred));
inp->ih.cred.cr_fsuid = current->fsuid;
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index 9c3fd07f35e0..bd26e4cbb994 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -108,7 +108,6 @@
#include <linux/dvb/dmx.h>
#include <linux/dvb/frontend.h>
#include <linux/dvb/video.h>
-#include <linux/lp.h>
#ifdef CONFIG_SPARC
#include <asm/fbio.h>
@@ -323,7 +322,7 @@ static int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg)
int err;
uifr = compat_alloc_user_space(sizeof(struct ifreq));
- if (copy_in_user(uifr, compat_ptr(arg), sizeof(struct ifreq32)));
+ if (copy_in_user(uifr, compat_ptr(arg), sizeof(struct ifreq32)))
return -EFAULT;
err = sys_ioctl(fd, SIOCGIFNAME, (unsigned long)uifr);
@@ -3002,7 +3001,7 @@ static int __init init_sys32_ioctl(void)
int i;
for (i = 0; i < ARRAY_SIZE(ioctl_start); i++) {
- if (ioctl_start[i].next != 0) {
+ if (ioctl_start[i].next) {
printk("ioctl translation %d bad\n",i);
return -1;
}
diff --git a/fs/configfs/configfs_internal.h b/fs/configfs/configfs_internal.h
index 3b0185fdf9a4..cca98609aa7f 100644
--- a/fs/configfs/configfs_internal.h
+++ b/fs/configfs/configfs_internal.h
@@ -56,6 +56,8 @@ extern int configfs_is_root(struct config_item *item);
extern struct inode * configfs_new_inode(mode_t mode, struct configfs_dirent *);
extern int configfs_create(struct dentry *, int mode, int (*init)(struct inode *));
+extern int configfs_inode_init(void);
+extern void configfs_inode_exit(void);
extern int configfs_create_file(struct config_item *, const struct configfs_attribute *);
extern int configfs_make_dirent(struct configfs_dirent *,
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index 2f436d4f1d6d..50ed691098bc 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -142,7 +142,7 @@ static int init_dir(struct inode * inode)
return 0;
}
-static int init_file(struct inode * inode)
+static int configfs_init_file(struct inode * inode)
{
inode->i_size = PAGE_SIZE;
inode->i_fop = &configfs_file_operations;
@@ -283,7 +283,8 @@ static int configfs_attach_attr(struct configfs_dirent * sd, struct dentry * den
dentry->d_fsdata = configfs_get(sd);
sd->s_dentry = dentry;
- error = configfs_create(dentry, (attr->ca_mode & S_IALLUGO) | S_IFREG, init_file);
+ error = configfs_create(dentry, (attr->ca_mode & S_IALLUGO) | S_IFREG,
+ configfs_init_file);
if (error) {
configfs_put(sd);
return error;
diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c
index ddc003a9d214..4c1ebff778ee 100644
--- a/fs/configfs/inode.c
+++ b/fs/configfs/inode.c
@@ -41,8 +41,8 @@ extern struct super_block * configfs_sb;
static const struct address_space_operations configfs_aops = {
.readpage = simple_readpage,
- .prepare_write = simple_prepare_write,
- .commit_write = simple_commit_write
+ .write_begin = simple_write_begin,
+ .write_end = simple_write_end,
};
static struct backing_dev_info configfs_backing_dev_info = {
@@ -256,4 +256,12 @@ void configfs_hash_and_remove(struct dentry * dir, const char * name)
mutex_unlock(&dir->d_inode->i_mutex);
}
+int __init configfs_inode_init(void)
+{
+ return bdi_init(&configfs_backing_dev_info);
+}
+void __exit configfs_inode_exit(void)
+{
+ bdi_destroy(&configfs_backing_dev_info);
+}
diff --git a/fs/configfs/mount.c b/fs/configfs/mount.c
index 871b0cb61839..3bf0278ea843 100644
--- a/fs/configfs/mount.c
+++ b/fs/configfs/mount.c
@@ -154,8 +154,16 @@ static int __init configfs_init(void)
subsystem_unregister(&config_subsys);
kmem_cache_destroy(configfs_dir_cachep);
configfs_dir_cachep = NULL;
+ goto out;
}
+ err = configfs_inode_init();
+ if (err) {
+ unregister_filesystem(&configfs_fs_type);
+ subsystem_unregister(&config_subsys);
+ kmem_cache_destroy(configfs_dir_cachep);
+ configfs_dir_cachep = NULL;
+ }
out:
return err;
}
@@ -166,6 +174,7 @@ static void __exit configfs_exit(void)
subsystem_unregister(&config_subsys);
kmem_cache_destroy(configfs_dir_cachep);
configfs_dir_cachep = NULL;
+ configfs_inode_exit();
}
MODULE_AUTHOR("Oracle");
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index 3d194a2be3f5..350680fd7da7 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -148,7 +148,7 @@ static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned i
{
struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping;
struct page *pages[BLKS_PER_BUF];
- unsigned i, blocknr, buffer, unread;
+ unsigned i, blocknr, buffer;
unsigned long devsize;
char *data;
@@ -175,7 +175,6 @@ static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned i
devsize = mapping->host->i_size >> PAGE_CACHE_SHIFT;
/* Ok, read in BLKS_PER_BUF pages completely first. */
- unread = 0;
for (i = 0; i < BLKS_PER_BUF; i++) {
struct page *page = NULL;
@@ -258,12 +257,21 @@ static int cramfs_fill_super(struct super_block *sb, void *data, int silent)
/* Do sanity checks on the superblock */
if (super.magic != CRAMFS_MAGIC) {
+ /* check for wrong endianess */
+ if (super.magic == CRAMFS_MAGIC_WEND) {
+ if (!silent)
+ printk(KERN_ERR "cramfs: wrong endianess\n");
+ goto out;
+ }
+
/* check at 512 byte offset */
mutex_lock(&read_mutex);
memcpy(&super, cramfs_read(sb, 512, sizeof(super)), sizeof(super));
mutex_unlock(&read_mutex);
if (super.magic != CRAMFS_MAGIC) {
- if (!silent)
+ if (super.magic == CRAMFS_MAGIC_WEND && !silent)
+ printk(KERN_ERR "cramfs: wrong endianess\n");
+ else if (!silent)
printk(KERN_ERR "cramfs: wrong magic\n");
goto out;
}
@@ -353,7 +361,7 @@ static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
if (offset & 3)
return -EINVAL;
- buf = kmalloc(256, GFP_KERNEL);
+ buf = kmalloc(CRAMFS_MAXPATHLEN, GFP_KERNEL);
if (!buf)
return -ENOMEM;
@@ -367,7 +375,7 @@ static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
int namelen, error;
mutex_lock(&read_mutex);
- de = cramfs_read(sb, OFFSET(inode) + offset, sizeof(*de)+256);
+ de = cramfs_read(sb, OFFSET(inode) + offset, sizeof(*de)+CRAMFS_MAXPATHLEN);
name = (char *)(de+1);
/*
@@ -417,7 +425,7 @@ static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, s
char *name;
int namelen, retval;
- de = cramfs_read(dir->i_sb, OFFSET(dir) + offset, sizeof(*de)+256);
+ de = cramfs_read(dir->i_sb, OFFSET(dir) + offset, sizeof(*de)+CRAMFS_MAXPATHLEN);
name = (char *)(de+1);
/* Try to take advantage of sorted directories */
diff --git a/fs/dcache.c b/fs/dcache.c
index 678d39deb607..d9ca1e5ceb92 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -38,7 +38,7 @@ int sysctl_vfs_cache_pressure __read_mostly = 100;
EXPORT_SYMBOL_GPL(sysctl_vfs_cache_pressure);
__cacheline_aligned_in_smp DEFINE_SPINLOCK(dcache_lock);
-static __cacheline_aligned_in_smp DEFINE_SEQLOCK(rename_lock);
+__cacheline_aligned_in_smp DEFINE_SEQLOCK(rename_lock);
EXPORT_SYMBOL(dcache_lock);
@@ -381,20 +381,17 @@ restart:
* Throw away a dentry - free the inode, dput the parent. This requires that
* the LRU list has already been removed.
*
- * If prune_parents is true, try to prune ancestors as well.
+ * Try to prune ancestors as well. This is necessary to prevent
+ * quadratic behavior of shrink_dcache_parent(), but is also expected
+ * to be beneficial in reducing dentry cache fragmentation.
*
* Called with dcache_lock, drops it and then regains.
* Called with dentry->d_lock held, drops it.
*/
-static void prune_one_dentry(struct dentry * dentry, int prune_parents)
+static void prune_one_dentry(struct dentry * dentry)
{
__d_drop(dentry);
dentry = d_kill(dentry);
- if (!prune_parents) {
- dput(dentry);
- spin_lock(&dcache_lock);
- return;
- }
/*
* Prune ancestors. Locking is simpler than in dput(),
@@ -422,7 +419,6 @@ static void prune_one_dentry(struct dentry * dentry, int prune_parents)
* @count: number of entries to try and free
* @sb: if given, ignore dentries for other superblocks
* which are being unmounted.
- * @prune_parents: if true, try to prune ancestors as well in one go
*
* Shrink the dcache. This is done when we need
* more memory, or simply when we need to unmount
@@ -433,7 +429,7 @@ static void prune_one_dentry(struct dentry * dentry, int prune_parents)
* all the dentries are in use.
*/
-static void prune_dcache(int count, struct super_block *sb, int prune_parents)
+static void prune_dcache(int count, struct super_block *sb)
{
spin_lock(&dcache_lock);
for (; count ; count--) {
@@ -493,7 +489,7 @@ static void prune_dcache(int count, struct super_block *sb, int prune_parents)
* without taking the s_umount lock (I already hold it).
*/
if (sb && dentry->d_sb == sb) {
- prune_one_dentry(dentry, prune_parents);
+ prune_one_dentry(dentry);
continue;
}
/*
@@ -508,7 +504,7 @@ static void prune_dcache(int count, struct super_block *sb, int prune_parents)
s_umount = &dentry->d_sb->s_umount;
if (down_read_trylock(s_umount)) {
if (dentry->d_sb->s_root != NULL) {
- prune_one_dentry(dentry, prune_parents);
+ prune_one_dentry(dentry);
up_read(s_umount);
continue;
}
@@ -557,18 +553,18 @@ void shrink_dcache_sb(struct super_block * sb)
* superblock to the most recent end of the unused list.
*/
spin_lock(&dcache_lock);
- list_for_each_safe(tmp, next, &dentry_unused) {
+ list_for_each_prev_safe(tmp, next, &dentry_unused) {
dentry = list_entry(tmp, struct dentry, d_lru);
if (dentry->d_sb != sb)
continue;
- list_move(tmp, &dentry_unused);
+ list_move_tail(tmp, &dentry_unused);
}
/*
* Pass two ... free the dentries for this superblock.
*/
repeat:
- list_for_each_safe(tmp, next, &dentry_unused) {
+ list_for_each_prev_safe(tmp, next, &dentry_unused) {
dentry = list_entry(tmp, struct dentry, d_lru);
if (dentry->d_sb != sb)
continue;
@@ -579,7 +575,7 @@ repeat:
spin_unlock(&dentry->d_lock);
continue;
}
- prune_one_dentry(dentry, 1);
+ prune_one_dentry(dentry);
cond_resched_lock(&dcache_lock);
goto repeat;
}
@@ -858,7 +854,7 @@ void shrink_dcache_parent(struct dentry * parent)
int found;
while ((found = select_parent(parent)) != 0)
- prune_dcache(found, parent->d_sb, 1);
+ prune_dcache(found, parent->d_sb);
}
/*
@@ -878,7 +874,7 @@ static int shrink_dcache_memory(int nr, gfp_t gfp_mask)
if (nr) {
if (!(gfp_mask & __GFP_FS))
return -1;
- prune_dcache(nr, NULL, 1);
+ prune_dcache(nr, NULL);
}
return (dentry_stat.nr_unused / 100) * sysctl_vfs_cache_pressure;
}
@@ -903,7 +899,7 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
struct dentry *dentry;
char *dname;
- dentry = kmem_cache_alloc(dentry_cache, GFP_KERNEL);
+ dentry = kmem_cache_alloc(dentry_cache, GFP_KERNEL);
if (!dentry)
return NULL;
@@ -1483,6 +1479,8 @@ static void switch_names(struct dentry *dentry, struct dentry *target)
* dentry:internal, target:external. Steal target's
* storage and make target internal.
*/
+ memcpy(target->d_iname, dentry->d_name.name,
+ dentry->d_name.len + 1);
dentry->d_name.name = target->d_name.name;
target->d_name.name = target->d_iname;
}
@@ -1514,8 +1512,8 @@ static void switch_names(struct dentry *dentry, struct dentry *target)
* This forceful removal will result in ugly /proc output if
* somebody holds a file open that got deleted due to a rename.
* We could be nicer about the deleted file, and let it show
- * up under the name it got deleted rather than the name that
- * deleted it.
+ * up under the name it had before it was deleted rather than
+ * under the original name of the file that was moved on top of it.
*/
/*
@@ -1546,7 +1544,7 @@ static void d_move_locked(struct dentry * dentry, struct dentry * target)
}
/* Move the dentry to the target hash queue, if on different bucket */
- if (dentry->d_flags & DCACHE_UNHASHED)
+ if (d_unhashed(dentry))
goto already_unhashed;
hlist_del_rcu(&dentry->d_hash);
@@ -2108,7 +2106,7 @@ static void __init dcache_init_early(void)
INIT_HLIST_HEAD(&dentry_hashtable[loop]);
}
-static void __init dcache_init(unsigned long mempages)
+static void __init dcache_init(void)
{
int loop;
@@ -2170,10 +2168,10 @@ void __init vfs_caches_init(unsigned long mempages)
filp_cachep = kmem_cache_create("filp", sizeof(struct file), 0,
SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
- dcache_init(mempages);
- inode_init(mempages);
+ dcache_init();
+ inode_init();
files_init(mempages);
- mnt_init(mempages);
+ mnt_init();
bdev_cache_init();
chrdev_init();
}
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index a9b99c0dc2e7..fa6b7f7ff914 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -227,15 +227,24 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_x16, debugfs_u16_get, debugfs_u16_set, "0x%04llx\n"
DEFINE_SIMPLE_ATTRIBUTE(fops_x32, debugfs_u32_get, debugfs_u32_set, "0x%08llx\n");
-/**
- * debugfs_create_x8 - create a debugfs file that is used to read and write an unsigned 8-bit value
- * debugfs_create_x16 - create a debugfs file that is used to read and write an unsigned 16-bit value
- * debugfs_create_x32 - create a debugfs file that is used to read and write an unsigned 32-bit value
+/*
+ * debugfs_create_x{8,16,32} - create a debugfs file that is used to read and write an unsigned {8,16,32}-bit value
*
- * These functions are exactly the same as the above functions, (but use a hex
- * output for the decimal challenged) for details look at the above unsigned
+ * These functions are exactly the same as the above functions (but use a hex
+ * output for the decimal challenged). For details look at the above unsigned
* decimal functions.
*/
+
+/**
+ * debugfs_create_x8 - create a debugfs file that is used to read and write an unsigned 8-bit value
+ * @name: a pointer to a string containing the name of the file to create.
+ * @mode: the permission that the file should have
+ * @parent: a pointer to the parent dentry for this file. This should be a
+ * directory dentry if set. If this parameter is %NULL, then the
+ * file will be created in the root of the debugfs filesystem.
+ * @value: a pointer to the variable that the file should read to and write
+ * from.
+ */
struct dentry *debugfs_create_x8(const char *name, mode_t mode,
struct dentry *parent, u8 *value)
{
@@ -243,6 +252,16 @@ struct dentry *debugfs_create_x8(const char *name, mode_t mode,
}
EXPORT_SYMBOL_GPL(debugfs_create_x8);
+/**
+ * debugfs_create_x16 - create a debugfs file that is used to read and write an unsigned 16-bit value
+ * @name: a pointer to a string containing the name of the file to create.
+ * @mode: the permission that the file should have
+ * @parent: a pointer to the parent dentry for this file. This should be a
+ * directory dentry if set. If this parameter is %NULL, then the
+ * file will be created in the root of the debugfs filesystem.
+ * @value: a pointer to the variable that the file should read to and write
+ * from.
+ */
struct dentry *debugfs_create_x16(const char *name, mode_t mode,
struct dentry *parent, u16 *value)
{
@@ -250,6 +269,16 @@ struct dentry *debugfs_create_x16(const char *name, mode_t mode,
}
EXPORT_SYMBOL_GPL(debugfs_create_x16);
+/**
+ * debugfs_create_x32 - create a debugfs file that is used to read and write an unsigned 32-bit value
+ * @name: a pointer to a string containing the name of the file to create.
+ * @mode: the permission that the file should have
+ * @parent: a pointer to the parent dentry for this file. This should be a
+ * directory dentry if set. If this parameter is %NULL, then the
+ * file will be created in the root of the debugfs filesystem.
+ * @value: a pointer to the variable that the file should read to and write
+ * from.
+ */
struct dentry *debugfs_create_x32(const char *name, mode_t mode,
struct dentry *parent, u32 *value)
{
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index 11be8a325e26..6a713b33992f 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -413,7 +413,7 @@ struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
d_move(old_dentry, dentry);
fsnotify_move(old_dir->d_inode, new_dir->d_inode, old_name,
old_dentry->d_name.name, S_ISDIR(old_dentry->d_inode->i_mode),
- NULL, old_dentry->d_inode);
+ NULL, old_dentry);
fsnotify_oldname_free(old_name);
unlock_rename(new_dir, old_dir);
dput(dentry);
diff --git a/fs/direct-io.c b/fs/direct-io.c
index b5928a7b6a5a..acf0da1bd257 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -163,7 +163,7 @@ static int dio_refill_pages(struct dio *dio)
up_read(&current->mm->mmap_sem);
if (ret < 0 && dio->blocks_available && (dio->rw & WRITE)) {
- struct page *page = ZERO_PAGE(dio->curr_user_address);
+ struct page *page = ZERO_PAGE(0);
/*
* A memory fault, but the filesystem has some outstanding
* mapped blocks. We need to use those blocks up to avoid
@@ -763,7 +763,7 @@ static void dio_zero_block(struct dio *dio, int end)
this_chunk_bytes = this_chunk_blocks << dio->blkbits;
- page = ZERO_PAGE(dio->curr_user_address);
+ page = ZERO_PAGE(0);
if (submit_page_section(dio, page, 0, this_chunk_bytes,
dio->next_block_for_io))
return;
diff --git a/fs/dlm/Kconfig b/fs/dlm/Kconfig
index 54bcc00ec8df..2dbb422e8116 100644
--- a/fs/dlm/Kconfig
+++ b/fs/dlm/Kconfig
@@ -1,8 +1,6 @@
-menu "Distributed Lock Manager"
- depends on EXPERIMENTAL && INET
-
-config DLM
+menuconfig DLM
tristate "Distributed Lock Manager (DLM)"
+ depends on EXPERIMENTAL && INET
depends on SYSFS && (IPV6 || IPV6=n)
select CONFIGFS_FS
select IP_SCTP
@@ -17,5 +15,3 @@ config DLM_DEBUG
Under the debugfs mount point, the name of each lockspace will
appear as a file in the "dlm" directory. The output is the
list of resource and locks the local node knows about.
-
-endmenu
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index 58bf3f5cdbe2..e9923ca9c2d9 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -1062,7 +1062,7 @@ static int sctp_listen_for_all(void)
subscribe.sctp_shutdown_event = 1;
subscribe.sctp_partial_delivery_event = 1;
- result = kernel_setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
+ result = kernel_setsockopt(sock, SOL_SOCKET, SO_RCVBUFFORCE,
(char *)&bufsize, sizeof(bufsize));
if (result)
log_print("Error increasing buffer space on socket %d", result);
@@ -1454,10 +1454,6 @@ int dlm_lowcomms_start(void)
if (!con_cache)
goto out;
- /* Set some sysctl minima */
- if (sysctl_rmem_max < NEEDED_RMEM)
- sysctl_rmem_max = NEEDED_RMEM;
-
/* Start listening */
if (dlm_config.ci_protocol == 0)
error = tcp_listen_for_all();
diff --git a/fs/dlm/user.c b/fs/dlm/user.c
index 6438941ab1f8..4f741546f4bb 100644
--- a/fs/dlm/user.c
+++ b/fs/dlm/user.c
@@ -456,7 +456,7 @@ static int check_version(struct dlm_write_request *req)
printk(KERN_DEBUG "dlm: process %s (%d) version mismatch "
"user (%d.%d.%d) kernel (%d.%d.%d)\n",
current->comm,
- current->pid,
+ task_pid_nr(current),
req->version[0],
req->version[1],
req->version[2],
diff --git a/fs/dquot.c b/fs/dquot.c
index de9a29f64ff3..2809768d9c41 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -79,6 +79,10 @@
#include <linux/capability.h>
#include <linux/quotaops.h>
#include <linux/writeback.h> /* for inode_lock, oddly enough.. */
+#ifdef CONFIG_QUOTA_NETLINK_INTERFACE
+#include <net/netlink.h>
+#include <net/genetlink.h>
+#endif
#include <asm/uaccess.h>
@@ -823,6 +827,7 @@ static inline void dquot_decr_space(struct dquot *dquot, qsize_t number)
clear_bit(DQ_BLKS_B, &dquot->dq_flags);
}
+#ifdef CONFIG_PRINT_QUOTA_WARNING
static int flag_print_warnings = 1;
static inline int need_print_warning(struct dquot *dquot)
@@ -839,22 +844,15 @@ static inline int need_print_warning(struct dquot *dquot)
return 0;
}
-/* Values of warnings */
-#define NOWARN 0
-#define IHARDWARN 1
-#define ISOFTLONGWARN 2
-#define ISOFTWARN 3
-#define BHARDWARN 4
-#define BSOFTLONGWARN 5
-#define BSOFTWARN 6
-
/* Print warning to user which exceeded quota */
static void print_warning(struct dquot *dquot, const char warntype)
{
char *msg = NULL;
struct tty_struct *tty;
- int flag = (warntype == BHARDWARN || warntype == BSOFTLONGWARN) ? DQ_BLKS_B :
- ((warntype == IHARDWARN || warntype == ISOFTLONGWARN) ? DQ_INODES_B : 0);
+ int flag = (warntype == QUOTA_NL_BHARDWARN ||
+ warntype == QUOTA_NL_BSOFTLONGWARN) ? DQ_BLKS_B :
+ ((warntype == QUOTA_NL_IHARDWARN ||
+ warntype == QUOTA_NL_ISOFTLONGWARN) ? DQ_INODES_B : 0);
if (!need_print_warning(dquot) || (flag && test_and_set_bit(flag, &dquot->dq_flags)))
return;
@@ -864,28 +862,28 @@ static void print_warning(struct dquot *dquot, const char warntype)
if (!tty)
goto out_lock;
tty_write_message(tty, dquot->dq_sb->s_id);
- if (warntype == ISOFTWARN || warntype == BSOFTWARN)
+ if (warntype == QUOTA_NL_ISOFTWARN || warntype == QUOTA_NL_BSOFTWARN)
tty_write_message(tty, ": warning, ");
else
tty_write_message(tty, ": write failed, ");
tty_write_message(tty, quotatypes[dquot->dq_type]);
switch (warntype) {
- case IHARDWARN:
+ case QUOTA_NL_IHARDWARN:
msg = " file limit reached.\r\n";
break;
- case ISOFTLONGWARN:
+ case QUOTA_NL_ISOFTLONGWARN:
msg = " file quota exceeded too long.\r\n";
break;
- case ISOFTWARN:
+ case QUOTA_NL_ISOFTWARN:
msg = " file quota exceeded.\r\n";
break;
- case BHARDWARN:
+ case QUOTA_NL_BHARDWARN:
msg = " block limit reached.\r\n";
break;
- case BSOFTLONGWARN:
+ case QUOTA_NL_BSOFTLONGWARN:
msg = " block quota exceeded too long.\r\n";
break;
- case BSOFTWARN:
+ case QUOTA_NL_BSOFTWARN:
msg = " block quota exceeded.\r\n";
break;
}
@@ -893,14 +891,93 @@ static void print_warning(struct dquot *dquot, const char warntype)
out_lock:
mutex_unlock(&tty_mutex);
}
+#endif
+
+#ifdef CONFIG_QUOTA_NETLINK_INTERFACE
+
+/* Size of quota netlink message - actually an upperbound for buffer size */
+#define QUOTA_NL_MSG_SIZE 32
+
+/* Netlink family structure for quota */
+static struct genl_family quota_genl_family = {
+ .id = GENL_ID_GENERATE,
+ .hdrsize = 0,
+ .name = "VFS_DQUOT",
+ .version = 1,
+ .maxattr = QUOTA_NL_A_MAX,
+};
+
+/* Send warning to userspace about user which exceeded quota */
+static void send_warning(const struct dquot *dquot, const char warntype)
+{
+ static atomic_t seq;
+ struct sk_buff *skb;
+ void *msg_head;
+ int ret;
+
+ /* We have to allocate using GFP_NOFS as we are called from a
+ * filesystem performing write and thus further recursion into
+ * the fs to free some data could cause deadlocks. */
+ skb = genlmsg_new(QUOTA_NL_MSG_SIZE, GFP_NOFS);
+ if (!skb) {
+ printk(KERN_ERR
+ "VFS: Not enough memory to send quota warning.\n");
+ return;
+ }
+ msg_head = genlmsg_put(skb, 0, atomic_add_return(1, &seq),
+ &quota_genl_family, 0, QUOTA_NL_C_WARNING);
+ if (!msg_head) {
+ printk(KERN_ERR
+ "VFS: Cannot store netlink header in quota warning.\n");
+ goto err_out;
+ }
+ ret = nla_put_u32(skb, QUOTA_NL_A_QTYPE, dquot->dq_type);
+ if (ret)
+ goto attr_err_out;
+ ret = nla_put_u64(skb, QUOTA_NL_A_EXCESS_ID, dquot->dq_id);
+ if (ret)
+ goto attr_err_out;
+ ret = nla_put_u32(skb, QUOTA_NL_A_WARNING, warntype);
+ if (ret)
+ goto attr_err_out;
+ ret = nla_put_u32(skb, QUOTA_NL_A_DEV_MAJOR,
+ MAJOR(dquot->dq_sb->s_dev));
+ if (ret)
+ goto attr_err_out;
+ ret = nla_put_u32(skb, QUOTA_NL_A_DEV_MINOR,
+ MINOR(dquot->dq_sb->s_dev));
+ if (ret)
+ goto attr_err_out;
+ ret = nla_put_u64(skb, QUOTA_NL_A_CAUSED_ID, current->user->uid);
+ if (ret)
+ goto attr_err_out;
+ genlmsg_end(skb, msg_head);
+
+ ret = genlmsg_multicast(skb, 0, quota_genl_family.id, GFP_NOFS);
+ if (ret < 0 && ret != -ESRCH)
+ printk(KERN_ERR
+ "VFS: Failed to send notification message: %d\n", ret);
+ return;
+attr_err_out:
+ printk(KERN_ERR "VFS: Failed to compose quota message: %d\n", ret);
+err_out:
+ kfree_skb(skb);
+}
+#endif
static inline void flush_warnings(struct dquot **dquots, char *warntype)
{
int i;
for (i = 0; i < MAXQUOTAS; i++)
- if (dquots[i] != NODQUOT && warntype[i] != NOWARN)
+ if (dquots[i] != NODQUOT && warntype[i] != QUOTA_NL_NOWARN) {
+#ifdef CONFIG_PRINT_QUOTA_WARNING
print_warning(dquots[i], warntype[i]);
+#endif
+#ifdef CONFIG_QUOTA_NETLINK_INTERFACE
+ send_warning(dquots[i], warntype[i]);
+#endif
+ }
}
static inline char ignore_hardlimit(struct dquot *dquot)
@@ -914,14 +991,14 @@ static inline char ignore_hardlimit(struct dquot *dquot)
/* needs dq_data_lock */
static int check_idq(struct dquot *dquot, ulong inodes, char *warntype)
{
- *warntype = NOWARN;
+ *warntype = QUOTA_NL_NOWARN;
if (inodes <= 0 || test_bit(DQ_FAKE_B, &dquot->dq_flags))
return QUOTA_OK;
if (dquot->dq_dqb.dqb_ihardlimit &&
(dquot->dq_dqb.dqb_curinodes + inodes) > dquot->dq_dqb.dqb_ihardlimit &&
!ignore_hardlimit(dquot)) {
- *warntype = IHARDWARN;
+ *warntype = QUOTA_NL_IHARDWARN;
return NO_QUOTA;
}
@@ -929,14 +1006,14 @@ static int check_idq(struct dquot *dquot, ulong inodes, char *warntype)
(dquot->dq_dqb.dqb_curinodes + inodes) > dquot->dq_dqb.dqb_isoftlimit &&
dquot->dq_dqb.dqb_itime && get_seconds() >= dquot->dq_dqb.dqb_itime &&
!ignore_hardlimit(dquot)) {
- *warntype = ISOFTLONGWARN;
+ *warntype = QUOTA_NL_ISOFTLONGWARN;
return NO_QUOTA;
}
if (dquot->dq_dqb.dqb_isoftlimit &&
(dquot->dq_dqb.dqb_curinodes + inodes) > dquot->dq_dqb.dqb_isoftlimit &&
dquot->dq_dqb.dqb_itime == 0) {
- *warntype = ISOFTWARN;
+ *warntype = QUOTA_NL_ISOFTWARN;
dquot->dq_dqb.dqb_itime = get_seconds() + sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_igrace;
}
@@ -946,7 +1023,7 @@ static int check_idq(struct dquot *dquot, ulong inodes, char *warntype)
/* needs dq_data_lock */
static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *warntype)
{
- *warntype = 0;
+ *warntype = QUOTA_NL_NOWARN;
if (space <= 0 || test_bit(DQ_FAKE_B, &dquot->dq_flags))
return QUOTA_OK;
@@ -954,7 +1031,7 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *war
toqb(dquot->dq_dqb.dqb_curspace + space) > dquot->dq_dqb.dqb_bhardlimit &&
!ignore_hardlimit(dquot)) {
if (!prealloc)
- *warntype = BHARDWARN;
+ *warntype = QUOTA_NL_BHARDWARN;
return NO_QUOTA;
}
@@ -963,7 +1040,7 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *war
dquot->dq_dqb.dqb_btime && get_seconds() >= dquot->dq_dqb.dqb_btime &&
!ignore_hardlimit(dquot)) {
if (!prealloc)
- *warntype = BSOFTLONGWARN;
+ *warntype = QUOTA_NL_BSOFTLONGWARN;
return NO_QUOTA;
}
@@ -971,7 +1048,7 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *war
toqb(dquot->dq_dqb.dqb_curspace + space) > dquot->dq_dqb.dqb_bsoftlimit &&
dquot->dq_dqb.dqb_btime == 0) {
if (!prealloc) {
- *warntype = BSOFTWARN;
+ *warntype = QUOTA_NL_BSOFTWARN;
dquot->dq_dqb.dqb_btime = get_seconds() + sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_bgrace;
}
else
@@ -1066,7 +1143,7 @@ out_add:
return QUOTA_OK;
}
for (cnt = 0; cnt < MAXQUOTAS; cnt++)
- warntype[cnt] = NOWARN;
+ warntype[cnt] = QUOTA_NL_NOWARN;
down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
if (IS_NOQUOTA(inode)) { /* Now we can do reliable test... */
@@ -1112,7 +1189,7 @@ int dquot_alloc_inode(const struct inode *inode, unsigned long number)
if (IS_NOQUOTA(inode))
return QUOTA_OK;
for (cnt = 0; cnt < MAXQUOTAS; cnt++)
- warntype[cnt] = NOWARN;
+ warntype[cnt] = QUOTA_NL_NOWARN;
down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
if (IS_NOQUOTA(inode)) {
up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
@@ -1234,7 +1311,7 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
/* Clear the arrays */
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
transfer_to[cnt] = transfer_from[cnt] = NODQUOT;
- warntype[cnt] = NOWARN;
+ warntype[cnt] = QUOTA_NL_NOWARN;
}
down_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
/* Now recheck reliably when holding dqptr_sem */
@@ -1808,6 +1885,7 @@ static ctl_table fs_dqstats_table[] = {
.mode = 0444,
.proc_handler = &proc_dointvec,
},
+#ifdef CONFIG_PRINT_QUOTA_WARNING
{
.ctl_name = FS_DQ_WARNINGS,
.procname = "warnings",
@@ -1816,6 +1894,7 @@ static ctl_table fs_dqstats_table[] = {
.mode = 0644,
.proc_handler = &proc_dointvec,
},
+#endif
{ .ctl_name = 0 },
};
@@ -1877,6 +1956,11 @@ static int __init dquot_init(void)
register_shrinker(&dqcache_shrinker);
+#ifdef CONFIG_QUOTA_NETLINK_INTERFACE
+ if (genl_register_family(&quota_genl_family) != 0)
+ printk(KERN_ERR "VFS: Failed to create quota netlink interface.\n");
+#endif
+
return 0;
}
module_init(dquot_init);
diff --git a/fs/ecryptfs/Makefile b/fs/ecryptfs/Makefile
index 1f1107237eab..768857015516 100644
--- a/fs/ecryptfs/Makefile
+++ b/fs/ecryptfs/Makefile
@@ -4,4 +4,4 @@
obj-$(CONFIG_ECRYPT_FS) += ecryptfs.o
-ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o crypto.o keystore.o messaging.o netlink.o debug.o
+ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o read_write.o crypto.o keystore.o messaging.o netlink.o debug.o
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 6ac630625b70..bbed2fd40fdc 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -115,17 +115,35 @@ static int ecryptfs_calculate_md5(char *dst,
}
crypt_stat->hash_tfm = desc.tfm;
}
- crypto_hash_init(&desc);
- crypto_hash_update(&desc, &sg, len);
- crypto_hash_final(&desc, dst);
- mutex_unlock(&crypt_stat->cs_hash_tfm_mutex);
+ rc = crypto_hash_init(&desc);
+ if (rc) {
+ printk(KERN_ERR
+ "%s: Error initializing crypto hash; rc = [%d]\n",
+ __FUNCTION__, rc);
+ goto out;
+ }
+ rc = crypto_hash_update(&desc, &sg, len);
+ if (rc) {
+ printk(KERN_ERR
+ "%s: Error updating crypto hash; rc = [%d]\n",
+ __FUNCTION__, rc);
+ goto out;
+ }
+ rc = crypto_hash_final(&desc, dst);
+ if (rc) {
+ printk(KERN_ERR
+ "%s: Error finalizing crypto hash; rc = [%d]\n",
+ __FUNCTION__, rc);
+ goto out;
+ }
out:
+ mutex_unlock(&crypt_stat->cs_hash_tfm_mutex);
return rc;
}
-int ecryptfs_crypto_api_algify_cipher_name(char **algified_name,
- char *cipher_name,
- char *chaining_modifier)
+static int ecryptfs_crypto_api_algify_cipher_name(char **algified_name,
+ char *cipher_name,
+ char *chaining_modifier)
{
int cipher_name_len = strlen(cipher_name);
int chaining_modifier_len = strlen(chaining_modifier);
@@ -149,7 +167,7 @@ out:
* ecryptfs_derive_iv
* @iv: destination for the derived iv vale
* @crypt_stat: Pointer to crypt_stat struct for the current inode
- * @offset: Offset of the page whose's iv we are to derive
+ * @offset: Offset of the extent whose IV we are to derive
*
* Generate the initialization vector from the given root IV and page
* offset.
@@ -157,7 +175,7 @@ out:
* Returns zero on success; non-zero on error.
*/
static int ecryptfs_derive_iv(char *iv, struct ecryptfs_crypt_stat *crypt_stat,
- pgoff_t offset)
+ loff_t offset)
{
int rc = 0;
char dst[MD5_DIGEST_SIZE];
@@ -173,7 +191,7 @@ static int ecryptfs_derive_iv(char *iv, struct ecryptfs_crypt_stat *crypt_stat,
* hashing business. -Halcrow */
memcpy(src, crypt_stat->root_iv, crypt_stat->iv_bytes);
memset((src + crypt_stat->iv_bytes), 0, 16);
- snprintf((src + crypt_stat->iv_bytes), 16, "%ld", offset);
+ snprintf((src + crypt_stat->iv_bytes), 16, "%lld", offset);
if (unlikely(ecryptfs_verbosity > 0)) {
ecryptfs_printk(KERN_DEBUG, "source:\n");
ecryptfs_dump_hex(src, (crypt_stat->iv_bytes + 16));
@@ -204,6 +222,8 @@ void
ecryptfs_init_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat)
{
memset((void *)crypt_stat, 0, sizeof(struct ecryptfs_crypt_stat));
+ INIT_LIST_HEAD(&crypt_stat->keysig_list);
+ mutex_init(&crypt_stat->keysig_list_mutex);
mutex_init(&crypt_stat->cs_mutex);
mutex_init(&crypt_stat->cs_tfm_mutex);
mutex_init(&crypt_stat->cs_hash_tfm_mutex);
@@ -211,27 +231,48 @@ ecryptfs_init_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat)
}
/**
- * ecryptfs_destruct_crypt_stat
+ * ecryptfs_destroy_crypt_stat
* @crypt_stat: Pointer to the crypt_stat struct to initialize.
*
* Releases all memory associated with a crypt_stat struct.
*/
-void ecryptfs_destruct_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat)
+void ecryptfs_destroy_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat)
{
+ struct ecryptfs_key_sig *key_sig, *key_sig_tmp;
+
if (crypt_stat->tfm)
crypto_free_blkcipher(crypt_stat->tfm);
if (crypt_stat->hash_tfm)
crypto_free_hash(crypt_stat->hash_tfm);
+ mutex_lock(&crypt_stat->keysig_list_mutex);
+ list_for_each_entry_safe(key_sig, key_sig_tmp,
+ &crypt_stat->keysig_list, crypt_stat_list) {
+ list_del(&key_sig->crypt_stat_list);
+ kmem_cache_free(ecryptfs_key_sig_cache, key_sig);
+ }
+ mutex_unlock(&crypt_stat->keysig_list_mutex);
memset(crypt_stat, 0, sizeof(struct ecryptfs_crypt_stat));
}
-void ecryptfs_destruct_mount_crypt_stat(
+void ecryptfs_destroy_mount_crypt_stat(
struct ecryptfs_mount_crypt_stat *mount_crypt_stat)
{
- if (mount_crypt_stat->global_auth_tok_key)
- key_put(mount_crypt_stat->global_auth_tok_key);
- if (mount_crypt_stat->global_key_tfm)
- crypto_free_blkcipher(mount_crypt_stat->global_key_tfm);
+ struct ecryptfs_global_auth_tok *auth_tok, *auth_tok_tmp;
+
+ if (!(mount_crypt_stat->flags & ECRYPTFS_MOUNT_CRYPT_STAT_INITIALIZED))
+ return;
+ mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex);
+ list_for_each_entry_safe(auth_tok, auth_tok_tmp,
+ &mount_crypt_stat->global_auth_tok_list,
+ mount_crypt_stat_list) {
+ list_del(&auth_tok->mount_crypt_stat_list);
+ mount_crypt_stat->num_global_auth_toks--;
+ if (auth_tok->global_auth_tok_key
+ && !(auth_tok->flags & ECRYPTFS_AUTH_TOK_INVALID))
+ key_put(auth_tok->global_auth_tok_key);
+ kmem_cache_free(ecryptfs_global_auth_tok_cache, auth_tok);
+ }
+ mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex);
memset(mount_crypt_stat, 0, sizeof(struct ecryptfs_mount_crypt_stat));
}
@@ -256,13 +297,13 @@ int virt_to_scatterlist(const void *addr, int size, struct scatterlist *sg,
int offset;
int remainder_of_page;
+ sg_init_table(sg, sg_size);
+
while (size > 0 && i < sg_size) {
pg = virt_to_page(addr);
offset = offset_in_page(addr);
- if (sg) {
- sg[i].page = pg;
- sg[i].offset = offset;
- }
+ if (sg)
+ sg_set_page(&sg[i], pg, 0, offset);
remainder_of_page = PAGE_CACHE_SIZE - offset;
if (size >= remainder_of_page) {
if (sg)
@@ -330,114 +371,82 @@ out:
return rc;
}
-static void
-ecryptfs_extent_to_lwr_pg_idx_and_offset(unsigned long *lower_page_idx,
- int *byte_offset,
- struct ecryptfs_crypt_stat *crypt_stat,
- unsigned long extent_num)
+/**
+ * ecryptfs_lower_offset_for_extent
+ *
+ * Convert an eCryptfs page index into a lower byte offset
+ */
+void ecryptfs_lower_offset_for_extent(loff_t *offset, loff_t extent_num,
+ struct ecryptfs_crypt_stat *crypt_stat)
{
- unsigned long lower_extent_num;
- int extents_occupied_by_headers_at_front;
- int bytes_occupied_by_headers_at_front;
- int extent_offset;
- int extents_per_page;
-
- bytes_occupied_by_headers_at_front =
- ( crypt_stat->header_extent_size
- * crypt_stat->num_header_extents_at_front );
- extents_occupied_by_headers_at_front =
- ( bytes_occupied_by_headers_at_front
- / crypt_stat->extent_size );
- lower_extent_num = extents_occupied_by_headers_at_front + extent_num;
- extents_per_page = PAGE_CACHE_SIZE / crypt_stat->extent_size;
- (*lower_page_idx) = lower_extent_num / extents_per_page;
- extent_offset = lower_extent_num % extents_per_page;
- (*byte_offset) = extent_offset * crypt_stat->extent_size;
- ecryptfs_printk(KERN_DEBUG, " * crypt_stat->header_extent_size = "
- "[%d]\n", crypt_stat->header_extent_size);
- ecryptfs_printk(KERN_DEBUG, " * crypt_stat->"
- "num_header_extents_at_front = [%d]\n",
- crypt_stat->num_header_extents_at_front);
- ecryptfs_printk(KERN_DEBUG, " * extents_occupied_by_headers_at_"
- "front = [%d]\n", extents_occupied_by_headers_at_front);
- ecryptfs_printk(KERN_DEBUG, " * lower_extent_num = [0x%.16x]\n",
- lower_extent_num);
- ecryptfs_printk(KERN_DEBUG, " * extents_per_page = [%d]\n",
- extents_per_page);
- ecryptfs_printk(KERN_DEBUG, " * (*lower_page_idx) = [0x%.16x]\n",
- (*lower_page_idx));
- ecryptfs_printk(KERN_DEBUG, " * extent_offset = [%d]\n",
- extent_offset);
- ecryptfs_printk(KERN_DEBUG, " * (*byte_offset) = [%d]\n",
- (*byte_offset));
+ (*offset) = ((crypt_stat->extent_size
+ * crypt_stat->num_header_extents_at_front)
+ + (crypt_stat->extent_size * extent_num));
}
-static int ecryptfs_write_out_page(struct ecryptfs_page_crypt_context *ctx,
- struct page *lower_page,
- struct inode *lower_inode,
- int byte_offset_in_page, int bytes_to_write)
+/**
+ * ecryptfs_encrypt_extent
+ * @enc_extent_page: Allocated page into which to encrypt the data in
+ * @page
+ * @crypt_stat: crypt_stat containing cryptographic context for the
+ * encryption operation
+ * @page: Page containing plaintext data extent to encrypt
+ * @extent_offset: Page extent offset for use in generating IV
+ *
+ * Encrypts one extent of data.
+ *
+ * Return zero on success; non-zero otherwise
+ */
+static int ecryptfs_encrypt_extent(struct page *enc_extent_page,
+ struct ecryptfs_crypt_stat *crypt_stat,
+ struct page *page,
+ unsigned long extent_offset)
{
- int rc = 0;
+ loff_t extent_base;
+ char extent_iv[ECRYPTFS_MAX_IV_BYTES];
+ int rc;
- if (ctx->mode == ECRYPTFS_PREPARE_COMMIT_MODE) {
- rc = ecryptfs_commit_lower_page(lower_page, lower_inode,
- ctx->param.lower_file,
- byte_offset_in_page,
- bytes_to_write);
- if (rc) {
- ecryptfs_printk(KERN_ERR, "Error calling lower "
- "commit; rc = [%d]\n", rc);
- goto out;
- }
- } else {
- rc = ecryptfs_writepage_and_release_lower_page(lower_page,
- lower_inode,
- ctx->param.wbc);
- if (rc) {
- ecryptfs_printk(KERN_ERR, "Error calling lower "
- "writepage(); rc = [%d]\n", rc);
- goto out;
- }
+ extent_base = (((loff_t)page->index)
+ * (PAGE_CACHE_SIZE / crypt_stat->extent_size));
+ rc = ecryptfs_derive_iv(extent_iv, crypt_stat,
+ (extent_base + extent_offset));
+ if (rc) {
+ ecryptfs_printk(KERN_ERR, "Error attempting to "
+ "derive IV for extent [0x%.16x]; "
+ "rc = [%d]\n", (extent_base + extent_offset),
+ rc);
+ goto out;
}
-out:
- return rc;
-}
-
-static int ecryptfs_read_in_page(struct ecryptfs_page_crypt_context *ctx,
- struct page **lower_page,
- struct inode *lower_inode,
- unsigned long lower_page_idx,
- int byte_offset_in_page)
-{
- int rc = 0;
-
- if (ctx->mode == ECRYPTFS_PREPARE_COMMIT_MODE) {
- /* TODO: Limit this to only the data extents that are
- * needed */
- rc = ecryptfs_get_lower_page(lower_page, lower_inode,
- ctx->param.lower_file,
- lower_page_idx,
- byte_offset_in_page,
- (PAGE_CACHE_SIZE
- - byte_offset_in_page));
- if (rc) {
- ecryptfs_printk(
- KERN_ERR, "Error attempting to grab, map, "
- "and prepare_write lower page with index "
- "[0x%.16x]; rc = [%d]\n", lower_page_idx, rc);
- goto out;
- }
- } else {
- *lower_page = grab_cache_page(lower_inode->i_mapping,
- lower_page_idx);
- if (!(*lower_page)) {
- rc = -EINVAL;
- ecryptfs_printk(
- KERN_ERR, "Error attempting to grab and map "
- "lower page with index [0x%.16x]; rc = [%d]\n",
- lower_page_idx, rc);
- goto out;
- }
+ if (unlikely(ecryptfs_verbosity > 0)) {
+ ecryptfs_printk(KERN_DEBUG, "Encrypting extent "
+ "with iv:\n");
+ ecryptfs_dump_hex(extent_iv, crypt_stat->iv_bytes);
+ ecryptfs_printk(KERN_DEBUG, "First 8 bytes before "
+ "encryption:\n");
+ ecryptfs_dump_hex((char *)
+ (page_address(page)
+ + (extent_offset * crypt_stat->extent_size)),
+ 8);
+ }
+ rc = ecryptfs_encrypt_page_offset(crypt_stat, enc_extent_page, 0,
+ page, (extent_offset
+ * crypt_stat->extent_size),
+ crypt_stat->extent_size, extent_iv);
+ if (rc < 0) {
+ printk(KERN_ERR "%s: Error attempting to encrypt page with "
+ "page->index = [%ld], extent_offset = [%ld]; "
+ "rc = [%d]\n", __FUNCTION__, page->index, extent_offset,
+ rc);
+ goto out;
+ }
+ rc = 0;
+ if (unlikely(ecryptfs_verbosity > 0)) {
+ ecryptfs_printk(KERN_DEBUG, "Encrypt extent [0x%.16x]; "
+ "rc = [%d]\n", (extent_base + extent_offset),
+ rc);
+ ecryptfs_printk(KERN_DEBUG, "First 8 bytes after "
+ "encryption:\n");
+ ecryptfs_dump_hex((char *)(page_address(enc_extent_page)), 8);
}
out:
return rc;
@@ -445,7 +454,9 @@ out:
/**
* ecryptfs_encrypt_page
- * @ctx: The context of the page
+ * @page: Page mapped from the eCryptfs inode for the file; contains
+ * decrypted content that needs to be encrypted (to a temporary
+ * page; not in place) and written out to the lower file
*
* Encrypt an eCryptfs page. This is done on a per-extent basis. Note
* that eCryptfs pages may straddle the lower pages -- for instance,
@@ -455,128 +466,121 @@ out:
* file, 24K of page 0 of the lower file will be read and decrypted,
* and then 8K of page 1 of the lower file will be read and decrypted.
*
- * The actual operations performed on each page depends on the
- * contents of the ecryptfs_page_crypt_context struct.
- *
* Returns zero on success; negative on error
*/
-int ecryptfs_encrypt_page(struct ecryptfs_page_crypt_context *ctx)
+int ecryptfs_encrypt_page(struct page *page)
{
- char extent_iv[ECRYPTFS_MAX_IV_BYTES];
- unsigned long base_extent;
- unsigned long extent_offset = 0;
- unsigned long lower_page_idx = 0;
- unsigned long prior_lower_page_idx = 0;
- struct page *lower_page;
- struct inode *lower_inode;
- struct ecryptfs_inode_info *inode_info;
+ struct inode *ecryptfs_inode;
struct ecryptfs_crypt_stat *crypt_stat;
+ char *enc_extent_virt = NULL;
+ struct page *enc_extent_page;
+ loff_t extent_offset;
int rc = 0;
- int lower_byte_offset = 0;
- int orig_byte_offset = 0;
- int num_extents_per_page;
-#define ECRYPTFS_PAGE_STATE_UNREAD 0
-#define ECRYPTFS_PAGE_STATE_READ 1
-#define ECRYPTFS_PAGE_STATE_MODIFIED 2
-#define ECRYPTFS_PAGE_STATE_WRITTEN 3
- int page_state;
-
- lower_inode = ecryptfs_inode_to_lower(ctx->page->mapping->host);
- inode_info = ecryptfs_inode_to_private(ctx->page->mapping->host);
- crypt_stat = &inode_info->crypt_stat;
+
+ ecryptfs_inode = page->mapping->host;
+ crypt_stat =
+ &(ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat);
if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
- rc = ecryptfs_copy_page_to_lower(ctx->page, lower_inode,
- ctx->param.lower_file);
+ rc = ecryptfs_write_lower_page_segment(ecryptfs_inode, page,
+ 0, PAGE_CACHE_SIZE);
if (rc)
- ecryptfs_printk(KERN_ERR, "Error attempting to copy "
- "page at index [0x%.16x]\n",
- ctx->page->index);
+ printk(KERN_ERR "%s: Error attempting to copy "
+ "page at index [%ld]\n", __FUNCTION__,
+ page->index);
goto out;
}
- num_extents_per_page = PAGE_CACHE_SIZE / crypt_stat->extent_size;
- base_extent = (ctx->page->index * num_extents_per_page);
- page_state = ECRYPTFS_PAGE_STATE_UNREAD;
- while (extent_offset < num_extents_per_page) {
- ecryptfs_extent_to_lwr_pg_idx_and_offset(
- &lower_page_idx, &lower_byte_offset, crypt_stat,
- (base_extent + extent_offset));
- if (prior_lower_page_idx != lower_page_idx
- && page_state == ECRYPTFS_PAGE_STATE_MODIFIED) {
- rc = ecryptfs_write_out_page(ctx, lower_page,
- lower_inode,
- orig_byte_offset,
- (PAGE_CACHE_SIZE
- - orig_byte_offset));
- if (rc) {
- ecryptfs_printk(KERN_ERR, "Error attempting "
- "to write out page; rc = [%d]"
- "\n", rc);
- goto out;
- }
- page_state = ECRYPTFS_PAGE_STATE_WRITTEN;
- }
- if (page_state == ECRYPTFS_PAGE_STATE_UNREAD
- || page_state == ECRYPTFS_PAGE_STATE_WRITTEN) {
- rc = ecryptfs_read_in_page(ctx, &lower_page,
- lower_inode, lower_page_idx,
- lower_byte_offset);
- if (rc) {
- ecryptfs_printk(KERN_ERR, "Error attempting "
- "to read in lower page with "
- "index [0x%.16x]; rc = [%d]\n",
- lower_page_idx, rc);
- goto out;
- }
- orig_byte_offset = lower_byte_offset;
- prior_lower_page_idx = lower_page_idx;
- page_state = ECRYPTFS_PAGE_STATE_READ;
- }
- BUG_ON(!(page_state == ECRYPTFS_PAGE_STATE_MODIFIED
- || page_state == ECRYPTFS_PAGE_STATE_READ));
- rc = ecryptfs_derive_iv(extent_iv, crypt_stat,
- (base_extent + extent_offset));
+ enc_extent_virt = kmalloc(PAGE_CACHE_SIZE, GFP_USER);
+ if (!enc_extent_virt) {
+ rc = -ENOMEM;
+ ecryptfs_printk(KERN_ERR, "Error allocating memory for "
+ "encrypted extent\n");
+ goto out;
+ }
+ enc_extent_page = virt_to_page(enc_extent_virt);
+ for (extent_offset = 0;
+ extent_offset < (PAGE_CACHE_SIZE / crypt_stat->extent_size);
+ extent_offset++) {
+ loff_t offset;
+
+ rc = ecryptfs_encrypt_extent(enc_extent_page, crypt_stat, page,
+ extent_offset);
if (rc) {
- ecryptfs_printk(KERN_ERR, "Error attempting to "
- "derive IV for extent [0x%.16x]; "
- "rc = [%d]\n",
- (base_extent + extent_offset), rc);
+ printk(KERN_ERR "%s: Error encrypting extent; "
+ "rc = [%d]\n", __FUNCTION__, rc);
goto out;
}
- if (unlikely(ecryptfs_verbosity > 0)) {
- ecryptfs_printk(KERN_DEBUG, "Encrypting extent "
- "with iv:\n");
- ecryptfs_dump_hex(extent_iv, crypt_stat->iv_bytes);
- ecryptfs_printk(KERN_DEBUG, "First 8 bytes before "
- "encryption:\n");
- ecryptfs_dump_hex((char *)
- (page_address(ctx->page)
- + (extent_offset
- * crypt_stat->extent_size)), 8);
- }
- rc = ecryptfs_encrypt_page_offset(
- crypt_stat, lower_page, lower_byte_offset, ctx->page,
- (extent_offset * crypt_stat->extent_size),
- crypt_stat->extent_size, extent_iv);
- ecryptfs_printk(KERN_DEBUG, "Encrypt extent [0x%.16x]; "
- "rc = [%d]\n",
- (base_extent + extent_offset), rc);
- if (unlikely(ecryptfs_verbosity > 0)) {
- ecryptfs_printk(KERN_DEBUG, "First 8 bytes after "
- "encryption:\n");
- ecryptfs_dump_hex((char *)(page_address(lower_page)
- + lower_byte_offset), 8);
+ ecryptfs_lower_offset_for_extent(
+ &offset, ((((loff_t)page->index)
+ * (PAGE_CACHE_SIZE
+ / crypt_stat->extent_size))
+ + extent_offset), crypt_stat);
+ rc = ecryptfs_write_lower(ecryptfs_inode, enc_extent_virt,
+ offset, crypt_stat->extent_size);
+ if (rc) {
+ ecryptfs_printk(KERN_ERR, "Error attempting "
+ "to write lower page; rc = [%d]"
+ "\n", rc);
+ goto out;
}
- page_state = ECRYPTFS_PAGE_STATE_MODIFIED;
- extent_offset++;
}
- BUG_ON(orig_byte_offset != 0);
- rc = ecryptfs_write_out_page(ctx, lower_page, lower_inode, 0,
- (lower_byte_offset
- + crypt_stat->extent_size));
+out:
+ kfree(enc_extent_virt);
+ return rc;
+}
+
+static int ecryptfs_decrypt_extent(struct page *page,
+ struct ecryptfs_crypt_stat *crypt_stat,
+ struct page *enc_extent_page,
+ unsigned long extent_offset)
+{
+ loff_t extent_base;
+ char extent_iv[ECRYPTFS_MAX_IV_BYTES];
+ int rc;
+
+ extent_base = (((loff_t)page->index)
+ * (PAGE_CACHE_SIZE / crypt_stat->extent_size));
+ rc = ecryptfs_derive_iv(extent_iv, crypt_stat,
+ (extent_base + extent_offset));
if (rc) {
- ecryptfs_printk(KERN_ERR, "Error attempting to write out "
- "page; rc = [%d]\n", rc);
- goto out;
+ ecryptfs_printk(KERN_ERR, "Error attempting to "
+ "derive IV for extent [0x%.16x]; "
+ "rc = [%d]\n", (extent_base + extent_offset),
+ rc);
+ goto out;
+ }
+ if (unlikely(ecryptfs_verbosity > 0)) {
+ ecryptfs_printk(KERN_DEBUG, "Decrypting extent "
+ "with iv:\n");
+ ecryptfs_dump_hex(extent_iv, crypt_stat->iv_bytes);
+ ecryptfs_printk(KERN_DEBUG, "First 8 bytes before "
+ "decryption:\n");
+ ecryptfs_dump_hex((char *)
+ (page_address(enc_extent_page)
+ + (extent_offset * crypt_stat->extent_size)),
+ 8);
+ }
+ rc = ecryptfs_decrypt_page_offset(crypt_stat, page,
+ (extent_offset
+ * crypt_stat->extent_size),
+ enc_extent_page, 0,
+ crypt_stat->extent_size, extent_iv);
+ if (rc < 0) {
+ printk(KERN_ERR "%s: Error attempting to decrypt to page with "
+ "page->index = [%ld], extent_offset = [%ld]; "
+ "rc = [%d]\n", __FUNCTION__, page->index, extent_offset,
+ rc);
+ goto out;
+ }
+ rc = 0;
+ if (unlikely(ecryptfs_verbosity > 0)) {
+ ecryptfs_printk(KERN_DEBUG, "Decrypt extent [0x%.16x]; "
+ "rc = [%d]\n", (extent_base + extent_offset),
+ rc);
+ ecryptfs_printk(KERN_DEBUG, "First 8 bytes after "
+ "decryption:\n");
+ ecryptfs_dump_hex((char *)(page_address(page)
+ + (extent_offset
+ * crypt_stat->extent_size)), 8);
}
out:
return rc;
@@ -584,8 +588,9 @@ out:
/**
* ecryptfs_decrypt_page
- * @file: The ecryptfs file
- * @page: The page in ecryptfs to decrypt
+ * @page: Page mapped from the eCryptfs inode for the file; data read
+ * and decrypted from the lower file will be written into this
+ * page
*
* Decrypt an eCryptfs page. This is done on a per-extent basis. Note
* that eCryptfs pages may straddle the lower pages -- for instance,
@@ -597,108 +602,74 @@ out:
*
* Returns zero on success; negative on error
*/
-int ecryptfs_decrypt_page(struct file *file, struct page *page)
+int ecryptfs_decrypt_page(struct page *page)
{
- char extent_iv[ECRYPTFS_MAX_IV_BYTES];
- unsigned long base_extent;
- unsigned long extent_offset = 0;
- unsigned long lower_page_idx = 0;
- unsigned long prior_lower_page_idx = 0;
- struct page *lower_page;
- char *lower_page_virt = NULL;
- struct inode *lower_inode;
+ struct inode *ecryptfs_inode;
struct ecryptfs_crypt_stat *crypt_stat;
+ char *enc_extent_virt = NULL;
+ struct page *enc_extent_page;
+ unsigned long extent_offset;
int rc = 0;
- int byte_offset;
- int num_extents_per_page;
- int page_state;
- crypt_stat = &(ecryptfs_inode_to_private(
- page->mapping->host)->crypt_stat);
- lower_inode = ecryptfs_inode_to_lower(page->mapping->host);
+ ecryptfs_inode = page->mapping->host;
+ crypt_stat =
+ &(ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat);
if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
- rc = ecryptfs_do_readpage(file, page, page->index);
+ rc = ecryptfs_read_lower_page_segment(page, page->index, 0,
+ PAGE_CACHE_SIZE,
+ ecryptfs_inode);
if (rc)
- ecryptfs_printk(KERN_ERR, "Error attempting to copy "
- "page at index [0x%.16x]\n",
- page->index);
+ printk(KERN_ERR "%s: Error attempting to copy "
+ "page at index [%ld]\n", __FUNCTION__,
+ page->index);
goto out;
}
- num_extents_per_page = PAGE_CACHE_SIZE / crypt_stat->extent_size;
- base_extent = (page->index * num_extents_per_page);
- lower_page_virt = kmem_cache_alloc(ecryptfs_lower_page_cache,
- GFP_KERNEL);
- if (!lower_page_virt) {
+ enc_extent_virt = kmalloc(PAGE_CACHE_SIZE, GFP_USER);
+ if (!enc_extent_virt) {
rc = -ENOMEM;
- ecryptfs_printk(KERN_ERR, "Error getting page for encrypted "
- "lower page(s)\n");
+ ecryptfs_printk(KERN_ERR, "Error allocating memory for "
+ "encrypted extent\n");
goto out;
}
- lower_page = virt_to_page(lower_page_virt);
- page_state = ECRYPTFS_PAGE_STATE_UNREAD;
- while (extent_offset < num_extents_per_page) {
- ecryptfs_extent_to_lwr_pg_idx_and_offset(
- &lower_page_idx, &byte_offset, crypt_stat,
- (base_extent + extent_offset));
- if (prior_lower_page_idx != lower_page_idx
- || page_state == ECRYPTFS_PAGE_STATE_UNREAD) {
- rc = ecryptfs_do_readpage(file, lower_page,
- lower_page_idx);
- if (rc) {
- ecryptfs_printk(KERN_ERR, "Error reading "
- "lower encrypted page; rc = "
- "[%d]\n", rc);
- goto out;
- }
- prior_lower_page_idx = lower_page_idx;
- page_state = ECRYPTFS_PAGE_STATE_READ;
- }
- rc = ecryptfs_derive_iv(extent_iv, crypt_stat,
- (base_extent + extent_offset));
+ enc_extent_page = virt_to_page(enc_extent_virt);
+ for (extent_offset = 0;
+ extent_offset < (PAGE_CACHE_SIZE / crypt_stat->extent_size);
+ extent_offset++) {
+ loff_t offset;
+
+ ecryptfs_lower_offset_for_extent(
+ &offset, ((page->index * (PAGE_CACHE_SIZE
+ / crypt_stat->extent_size))
+ + extent_offset), crypt_stat);
+ rc = ecryptfs_read_lower(enc_extent_virt, offset,
+ crypt_stat->extent_size,
+ ecryptfs_inode);
if (rc) {
- ecryptfs_printk(KERN_ERR, "Error attempting to "
- "derive IV for extent [0x%.16x]; rc = "
- "[%d]\n",
- (base_extent + extent_offset), rc);
+ ecryptfs_printk(KERN_ERR, "Error attempting "
+ "to read lower page; rc = [%d]"
+ "\n", rc);
goto out;
}
- if (unlikely(ecryptfs_verbosity > 0)) {
- ecryptfs_printk(KERN_DEBUG, "Decrypting extent "
- "with iv:\n");
- ecryptfs_dump_hex(extent_iv, crypt_stat->iv_bytes);
- ecryptfs_printk(KERN_DEBUG, "First 8 bytes before "
- "decryption:\n");
- ecryptfs_dump_hex((lower_page_virt + byte_offset), 8);
- }
- rc = ecryptfs_decrypt_page_offset(crypt_stat, page,
- (extent_offset
- * crypt_stat->extent_size),
- lower_page, byte_offset,
- crypt_stat->extent_size,
- extent_iv);
- if (rc != crypt_stat->extent_size) {
- ecryptfs_printk(KERN_ERR, "Error attempting to "
- "decrypt extent [0x%.16x]\n",
- (base_extent + extent_offset));
+ rc = ecryptfs_decrypt_extent(page, crypt_stat, enc_extent_page,
+ extent_offset);
+ if (rc) {
+ printk(KERN_ERR "%s: Error encrypting extent; "
+ "rc = [%d]\n", __FUNCTION__, rc);
goto out;
}
- rc = 0;
- if (unlikely(ecryptfs_verbosity > 0)) {
- ecryptfs_printk(KERN_DEBUG, "First 8 bytes after "
- "decryption:\n");
- ecryptfs_dump_hex((char *)(page_address(page)
- + byte_offset), 8);
- }
- extent_offset++;
}
out:
- if (lower_page_virt)
- kmem_cache_free(ecryptfs_lower_page_cache, lower_page_virt);
+ kfree(enc_extent_virt);
return rc;
}
/**
* decrypt_scatterlist
+ * @crypt_stat: Cryptographic context
+ * @dest_sg: The destination scatterlist to decrypt into
+ * @src_sg: The source scatterlist to decrypt from
+ * @size: The number of bytes to decrypt
+ * @iv: The initialization vector to use for the decryption
*
* Returns the number of bytes decrypted; negative value on error
*/
@@ -740,6 +711,13 @@ out:
/**
* ecryptfs_encrypt_page_offset
+ * @crypt_stat: The cryptographic context
+ * @dst_page: The page to encrypt into
+ * @dst_offset: The offset in the page to encrypt into
+ * @src_page: The page to encrypt from
+ * @src_offset: The offset in the page to encrypt from
+ * @size: The number of bytes to encrypt
+ * @iv: The initialization vector to use for the encryption
*
* Returns the number of bytes encrypted
*/
@@ -751,17 +729,23 @@ ecryptfs_encrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat,
{
struct scatterlist src_sg, dst_sg;
- src_sg.page = src_page;
- src_sg.offset = src_offset;
- src_sg.length = size;
- dst_sg.page = dst_page;
- dst_sg.offset = dst_offset;
- dst_sg.length = size;
+ sg_init_table(&src_sg, 1);
+ sg_init_table(&dst_sg, 1);
+
+ sg_set_page(&src_sg, src_page, size, src_offset);
+ sg_set_page(&dst_sg, dst_page, size, dst_offset);
return encrypt_scatterlist(crypt_stat, &dst_sg, &src_sg, size, iv);
}
/**
* ecryptfs_decrypt_page_offset
+ * @crypt_stat: The cryptographic context
+ * @dst_page: The page to decrypt into
+ * @dst_offset: The offset in the page to decrypt into
+ * @src_page: The page to decrypt from
+ * @src_offset: The offset in the page to decrypt from
+ * @size: The number of bytes to decrypt
+ * @iv: The initialization vector to use for the decryption
*
* Returns the number of bytes decrypted
*/
@@ -773,12 +757,12 @@ ecryptfs_decrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat,
{
struct scatterlist src_sg, dst_sg;
- src_sg.page = src_page;
- src_sg.offset = src_offset;
- src_sg.length = size;
- dst_sg.page = dst_page;
- dst_sg.offset = dst_offset;
- dst_sg.length = size;
+ sg_init_table(&src_sg, 1);
+ sg_set_page(&src_sg, src_page, size, src_offset);
+
+ sg_init_table(&dst_sg, 1);
+ sg_set_page(&dst_sg, dst_page, size, dst_offset);
+
return decrypt_scatterlist(crypt_stat, &dst_sg, &src_sg, size, iv);
}
@@ -857,15 +841,17 @@ void ecryptfs_set_default_sizes(struct ecryptfs_crypt_stat *crypt_stat)
crypt_stat->extent_size = ECRYPTFS_DEFAULT_EXTENT_SIZE;
set_extent_mask_and_shift(crypt_stat);
crypt_stat->iv_bytes = ECRYPTFS_DEFAULT_IV_BYTES;
- if (PAGE_CACHE_SIZE <= ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE) {
- crypt_stat->header_extent_size =
- ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE;
- } else
- crypt_stat->header_extent_size = PAGE_CACHE_SIZE;
if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
crypt_stat->num_header_extents_at_front = 0;
- else
- crypt_stat->num_header_extents_at_front = 1;
+ else {
+ if (PAGE_CACHE_SIZE <= ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE)
+ crypt_stat->num_header_extents_at_front =
+ (ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE
+ / crypt_stat->extent_size);
+ else
+ crypt_stat->num_header_extents_at_front =
+ (PAGE_CACHE_SIZE / crypt_stat->extent_size);
+ }
}
/**
@@ -917,6 +903,8 @@ static void ecryptfs_generate_new_key(struct ecryptfs_crypt_stat *crypt_stat)
/**
* ecryptfs_copy_mount_wide_flags_to_inode_flags
+ * @crypt_stat: The inode's cryptographic context
+ * @mount_crypt_stat: The mount point's cryptographic context
*
* This function propagates the mount-wide flags to individual inode
* flags.
@@ -931,9 +919,34 @@ static void ecryptfs_copy_mount_wide_flags_to_inode_flags(
crypt_stat->flags |= ECRYPTFS_VIEW_AS_ENCRYPTED;
}
+static int ecryptfs_copy_mount_wide_sigs_to_inode_sigs(
+ struct ecryptfs_crypt_stat *crypt_stat,
+ struct ecryptfs_mount_crypt_stat *mount_crypt_stat)
+{
+ struct ecryptfs_global_auth_tok *global_auth_tok;
+ int rc = 0;
+
+ mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex);
+ list_for_each_entry(global_auth_tok,
+ &mount_crypt_stat->global_auth_tok_list,
+ mount_crypt_stat_list) {
+ rc = ecryptfs_add_keysig(crypt_stat, global_auth_tok->sig);
+ if (rc) {
+ printk(KERN_ERR "Error adding keysig; rc = [%d]\n", rc);
+ mutex_unlock(
+ &mount_crypt_stat->global_auth_tok_list_mutex);
+ goto out;
+ }
+ }
+ mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex);
+out:
+ return rc;
+}
+
/**
* ecryptfs_set_default_crypt_stat_vals
- * @crypt_stat
+ * @crypt_stat: The inode's cryptographic context
+ * @mount_crypt_stat: The mount point's cryptographic context
*
* Default values in the event that policy does not override them.
*/
@@ -953,7 +966,7 @@ static void ecryptfs_set_default_crypt_stat_vals(
/**
* ecryptfs_new_file_context
- * @ecryptfs_dentry
+ * @ecryptfs_dentry: The eCryptfs dentry
*
* If the crypto context for the file has not yet been established,
* this is where we do that. Establishing a new crypto context
@@ -970,49 +983,42 @@ static void ecryptfs_set_default_crypt_stat_vals(
*
* Returns zero on success; non-zero otherwise
*/
-/* Associate an authentication token(s) with the file */
int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry)
{
- int rc = 0;
struct ecryptfs_crypt_stat *crypt_stat =
&ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat;
struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
&ecryptfs_superblock_to_private(
ecryptfs_dentry->d_sb)->mount_crypt_stat;
int cipher_name_len;
+ int rc = 0;
ecryptfs_set_default_crypt_stat_vals(crypt_stat, mount_crypt_stat);
- /* See if there are mount crypt options */
- if (mount_crypt_stat->global_auth_tok) {
- ecryptfs_printk(KERN_DEBUG, "Initializing context for new "
- "file using mount_crypt_stat\n");
- crypt_stat->flags |= ECRYPTFS_ENCRYPTED;
- crypt_stat->flags |= ECRYPTFS_KEY_VALID;
- ecryptfs_copy_mount_wide_flags_to_inode_flags(crypt_stat,
- mount_crypt_stat);
- memcpy(crypt_stat->keysigs[crypt_stat->num_keysigs++],
- mount_crypt_stat->global_auth_tok_sig,
- ECRYPTFS_SIG_SIZE_HEX);
- cipher_name_len =
- strlen(mount_crypt_stat->global_default_cipher_name);
- memcpy(crypt_stat->cipher,
- mount_crypt_stat->global_default_cipher_name,
- cipher_name_len);
- crypt_stat->cipher[cipher_name_len] = '\0';
- crypt_stat->key_size =
- mount_crypt_stat->global_default_cipher_key_size;
- ecryptfs_generate_new_key(crypt_stat);
- } else
- /* We should not encounter this scenario since we
- * should detect lack of global_auth_tok at mount time
- * TODO: Applies to 0.1 release only; remove in future
- * release */
- BUG();
+ crypt_stat->flags |= (ECRYPTFS_ENCRYPTED | ECRYPTFS_KEY_VALID);
+ ecryptfs_copy_mount_wide_flags_to_inode_flags(crypt_stat,
+ mount_crypt_stat);
+ rc = ecryptfs_copy_mount_wide_sigs_to_inode_sigs(crypt_stat,
+ mount_crypt_stat);
+ if (rc) {
+ printk(KERN_ERR "Error attempting to copy mount-wide key sigs "
+ "to the inode key sigs; rc = [%d]\n", rc);
+ goto out;
+ }
+ cipher_name_len =
+ strlen(mount_crypt_stat->global_default_cipher_name);
+ memcpy(crypt_stat->cipher,
+ mount_crypt_stat->global_default_cipher_name,
+ cipher_name_len);
+ crypt_stat->cipher[cipher_name_len] = '\0';
+ crypt_stat->key_size =
+ mount_crypt_stat->global_default_cipher_key_size;
+ ecryptfs_generate_new_key(crypt_stat);
rc = ecryptfs_init_crypt_ctx(crypt_stat);
if (rc)
ecryptfs_printk(KERN_ERR, "Error initializing cryptographic "
"context for cipher [%s]: rc = [%d]\n",
crypt_stat->cipher, rc);
+out:
return rc;
}
@@ -1054,7 +1060,7 @@ static struct ecryptfs_flag_map_elem ecryptfs_flag_map[] = {
/**
* ecryptfs_process_flags
- * @crypt_stat
+ * @crypt_stat: The cryptographic context
* @page_virt: Source data to be parsed
* @bytes_read: Updated with the number of bytes read
*
@@ -1142,7 +1148,7 @@ ecryptfs_cipher_code_str_map[] = {
/**
* ecryptfs_code_for_cipher_string
- * @str: The string representing the cipher name
+ * @crypt_stat: The cryptographic context
*
* Returns zero on no match, or the cipher code on match
*/
@@ -1198,59 +1204,28 @@ int ecryptfs_cipher_code_to_string(char *str, u16 cipher_code)
return rc;
}
-/**
- * ecryptfs_read_header_region
- * @data
- * @dentry
- * @nd
- *
- * Returns zero on success; non-zero otherwise
- */
-static int ecryptfs_read_header_region(char *data, struct dentry *dentry,
- struct vfsmount *mnt)
+int ecryptfs_read_and_validate_header_region(char *data,
+ struct inode *ecryptfs_inode)
{
- struct file *lower_file;
- mm_segment_t oldfs;
+ struct ecryptfs_crypt_stat *crypt_stat =
+ &(ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat);
int rc;
- if ((rc = ecryptfs_open_lower_file(&lower_file, dentry, mnt,
- O_RDONLY))) {
- printk(KERN_ERR
- "Error opening lower_file to read header region\n");
- goto out;
- }
- lower_file->f_pos = 0;
- oldfs = get_fs();
- set_fs(get_ds());
- /* For releases 0.1 and 0.2, all of the header information
- * fits in the first data extent-sized region. */
- rc = lower_file->f_op->read(lower_file, (char __user *)data,
- ECRYPTFS_DEFAULT_EXTENT_SIZE, &lower_file->f_pos);
- set_fs(oldfs);
- if ((rc = ecryptfs_close_lower_file(lower_file))) {
- printk(KERN_ERR "Error closing lower_file\n");
+ rc = ecryptfs_read_lower(data, 0, crypt_stat->extent_size,
+ ecryptfs_inode);
+ if (rc) {
+ printk(KERN_ERR "%s: Error reading header region; rc = [%d]\n",
+ __FUNCTION__, rc);
goto out;
}
- rc = 0;
-out:
- return rc;
-}
-
-int ecryptfs_read_and_validate_header_region(char *data, struct dentry *dentry,
- struct vfsmount *mnt)
-{
- int rc;
-
- rc = ecryptfs_read_header_region(data, dentry, mnt);
- if (rc)
- goto out;
- if (!contains_ecryptfs_marker(data + ECRYPTFS_FILE_SIZE_BYTES))
+ if (!contains_ecryptfs_marker(data + ECRYPTFS_FILE_SIZE_BYTES)) {
rc = -EINVAL;
+ ecryptfs_printk(KERN_DEBUG, "Valid marker not found\n");
+ }
out:
return rc;
}
-
void
ecryptfs_write_header_metadata(char *virt,
struct ecryptfs_crypt_stat *crypt_stat,
@@ -1259,7 +1234,7 @@ ecryptfs_write_header_metadata(char *virt,
u32 header_extent_size;
u16 num_header_extents_at_front;
- header_extent_size = (u32)crypt_stat->header_extent_size;
+ header_extent_size = (u32)crypt_stat->extent_size;
num_header_extents_at_front =
(u16)crypt_stat->num_header_extents_at_front;
header_extent_size = cpu_to_be32(header_extent_size);
@@ -1276,9 +1251,10 @@ struct kmem_cache *ecryptfs_header_cache_2;
/**
* ecryptfs_write_headers_virt
- * @page_virt
- * @crypt_stat
- * @ecryptfs_dentry
+ * @page_virt: The virtual address to write the headers to
+ * @size: Set to the number of bytes written by this function
+ * @crypt_stat: The cryptographic context
+ * @ecryptfs_dentry: The eCryptfs dentry
*
* Format version: 1
*
@@ -1332,53 +1308,50 @@ static int ecryptfs_write_headers_virt(char *page_virt, size_t *size,
return rc;
}
-static int ecryptfs_write_metadata_to_contents(struct ecryptfs_crypt_stat *crypt_stat,
- struct file *lower_file,
- char *page_virt)
+static int
+ecryptfs_write_metadata_to_contents(struct ecryptfs_crypt_stat *crypt_stat,
+ struct dentry *ecryptfs_dentry,
+ char *page_virt)
{
- mm_segment_t oldfs;
int current_header_page;
int header_pages;
- ssize_t size;
- int rc = 0;
+ int rc;
- lower_file->f_pos = 0;
- oldfs = get_fs();
- set_fs(get_ds());
- size = vfs_write(lower_file, (char __user *)page_virt, PAGE_CACHE_SIZE,
- &lower_file->f_pos);
- if (size < 0) {
- rc = (int)size;
- printk(KERN_ERR "Error attempting to write lower page; "
- "rc = [%d]\n", rc);
- set_fs(oldfs);
+ rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode, page_virt,
+ 0, PAGE_CACHE_SIZE);
+ if (rc) {
+ printk(KERN_ERR "%s: Error attempting to write header "
+ "information to lower file; rc = [%d]\n", __FUNCTION__,
+ rc);
goto out;
}
- header_pages = ((crypt_stat->header_extent_size
+ header_pages = ((crypt_stat->extent_size
* crypt_stat->num_header_extents_at_front)
/ PAGE_CACHE_SIZE);
memset(page_virt, 0, PAGE_CACHE_SIZE);
current_header_page = 1;
while (current_header_page < header_pages) {
- size = vfs_write(lower_file, (char __user *)page_virt,
- PAGE_CACHE_SIZE, &lower_file->f_pos);
- if (size < 0) {
- rc = (int)size;
- printk(KERN_ERR "Error attempting to write lower page; "
- "rc = [%d]\n", rc);
- set_fs(oldfs);
+ loff_t offset;
+
+ offset = (((loff_t)current_header_page) << PAGE_CACHE_SHIFT);
+ if ((rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode,
+ page_virt, offset,
+ PAGE_CACHE_SIZE))) {
+ printk(KERN_ERR "%s: Error attempting to write header "
+ "information to lower file; rc = [%d]\n",
+ __FUNCTION__, rc);
goto out;
}
current_header_page++;
}
- set_fs(oldfs);
out:
return rc;
}
-static int ecryptfs_write_metadata_to_xattr(struct dentry *ecryptfs_dentry,
- struct ecryptfs_crypt_stat *crypt_stat,
- char *page_virt, size_t size)
+static int
+ecryptfs_write_metadata_to_xattr(struct dentry *ecryptfs_dentry,
+ struct ecryptfs_crypt_stat *crypt_stat,
+ char *page_virt, size_t size)
{
int rc;
@@ -1389,7 +1362,7 @@ static int ecryptfs_write_metadata_to_xattr(struct dentry *ecryptfs_dentry,
/**
* ecryptfs_write_metadata
- * @lower_file: The lower file struct, which was returned from dentry_open
+ * @ecryptfs_dentry: The eCryptfs dentry
*
* Write the file headers out. This will likely involve a userspace
* callout, in which the session key is encrypted with one or more
@@ -1397,22 +1370,21 @@ static int ecryptfs_write_metadata_to_xattr(struct dentry *ecryptfs_dentry,
* retrieved via a prompt. Exactly what happens at this point should
* be policy-dependent.
*
+ * TODO: Support header information spanning multiple pages
+ *
* Returns zero on success; non-zero on error
*/
-int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry,
- struct file *lower_file)
+int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry)
{
- struct ecryptfs_crypt_stat *crypt_stat;
+ struct ecryptfs_crypt_stat *crypt_stat =
+ &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat;
char *page_virt;
- size_t size;
+ size_t size = 0;
int rc = 0;
- crypt_stat = &ecryptfs_inode_to_private(
- ecryptfs_dentry->d_inode)->crypt_stat;
if (likely(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
if (!(crypt_stat->flags & ECRYPTFS_KEY_VALID)) {
- ecryptfs_printk(KERN_DEBUG, "Key is "
- "invalid; bailing out\n");
+ printk(KERN_ERR "Key is invalid; bailing out\n");
rc = -EINVAL;
goto out;
}
@@ -1441,7 +1413,8 @@ int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry,
crypt_stat, page_virt,
size);
else
- rc = ecryptfs_write_metadata_to_contents(crypt_stat, lower_file,
+ rc = ecryptfs_write_metadata_to_contents(crypt_stat,
+ ecryptfs_dentry,
page_virt);
if (rc) {
printk(KERN_ERR "Error writing metadata out to lower file; "
@@ -1464,28 +1437,28 @@ static int parse_header_metadata(struct ecryptfs_crypt_stat *crypt_stat,
u32 header_extent_size;
u16 num_header_extents_at_front;
- memcpy(&header_extent_size, virt, 4);
+ memcpy(&header_extent_size, virt, sizeof(u32));
header_extent_size = be32_to_cpu(header_extent_size);
- virt += 4;
- memcpy(&num_header_extents_at_front, virt, 2);
+ virt += sizeof(u32);
+ memcpy(&num_header_extents_at_front, virt, sizeof(u16));
num_header_extents_at_front = be16_to_cpu(num_header_extents_at_front);
- crypt_stat->header_extent_size = (int)header_extent_size;
crypt_stat->num_header_extents_at_front =
(int)num_header_extents_at_front;
- (*bytes_read) = 6;
+ (*bytes_read) = (sizeof(u32) + sizeof(u16));
if ((validate_header_size == ECRYPTFS_VALIDATE_HEADER_SIZE)
- && ((crypt_stat->header_extent_size
+ && ((crypt_stat->extent_size
* crypt_stat->num_header_extents_at_front)
< ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE)) {
rc = -EINVAL;
- ecryptfs_printk(KERN_WARNING, "Invalid header extent size: "
- "[%d]\n", crypt_stat->header_extent_size);
+ printk(KERN_WARNING "Invalid number of header extents: [%zd]\n",
+ crypt_stat->num_header_extents_at_front);
}
return rc;
}
/**
* set_default_header_data
+ * @crypt_stat: The cryptographic context
*
* For version 0 file format; this function is only for backwards
* compatibility for files created with the prior versions of
@@ -1493,12 +1466,15 @@ static int parse_header_metadata(struct ecryptfs_crypt_stat *crypt_stat,
*/
static void set_default_header_data(struct ecryptfs_crypt_stat *crypt_stat)
{
- crypt_stat->header_extent_size = 4096;
- crypt_stat->num_header_extents_at_front = 1;
+ crypt_stat->num_header_extents_at_front = 2;
}
/**
* ecryptfs_read_headers_virt
+ * @page_virt: The virtual address into which to read the headers
+ * @crypt_stat: The cryptographic context
+ * @ecryptfs_dentry: The eCryptfs dentry
+ * @validate_header_size: Whether to validate the header size while reading
*
* Read/parse the header data. The header format is detailed in the
* comment block for the ecryptfs_write_headers_virt() function.
@@ -1558,19 +1534,25 @@ out:
/**
* ecryptfs_read_xattr_region
+ * @page_virt: The vitual address into which to read the xattr data
+ * @ecryptfs_inode: The eCryptfs inode
*
* Attempts to read the crypto metadata from the extended attribute
* region of the lower file.
+ *
+ * Returns zero on success; non-zero on error
*/
-int ecryptfs_read_xattr_region(char *page_virt, struct dentry *ecryptfs_dentry)
+int ecryptfs_read_xattr_region(char *page_virt, struct inode *ecryptfs_inode)
{
+ struct dentry *lower_dentry =
+ ecryptfs_inode_to_private(ecryptfs_inode)->lower_file->f_dentry;
ssize_t size;
int rc = 0;
- size = ecryptfs_getxattr(ecryptfs_dentry, ECRYPTFS_XATTR_NAME,
- page_virt, ECRYPTFS_DEFAULT_EXTENT_SIZE);
+ size = ecryptfs_getxattr_lower(lower_dentry, ECRYPTFS_XATTR_NAME,
+ page_virt, ECRYPTFS_DEFAULT_EXTENT_SIZE);
if (size < 0) {
- printk(KERN_DEBUG "Error attempting to read the [%s] "
+ printk(KERN_ERR "Error attempting to read the [%s] "
"xattr from the lower file; return value = [%zd]\n",
ECRYPTFS_XATTR_NAME, size);
rc = -EINVAL;
@@ -1585,7 +1567,7 @@ int ecryptfs_read_and_validate_xattr_region(char *page_virt,
{
int rc;
- rc = ecryptfs_read_xattr_region(page_virt, ecryptfs_dentry);
+ rc = ecryptfs_read_xattr_region(page_virt, ecryptfs_dentry->d_inode);
if (rc)
goto out;
if (!contains_ecryptfs_marker(page_virt + ECRYPTFS_FILE_SIZE_BYTES)) {
@@ -1609,15 +1591,13 @@ out:
*
* Returns zero if valid headers found and parsed; non-zero otherwise
*/
-int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry,
- struct file *lower_file)
+int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry)
{
int rc = 0;
char *page_virt = NULL;
- mm_segment_t oldfs;
- ssize_t bytes_read;
+ struct inode *ecryptfs_inode = ecryptfs_dentry->d_inode;
struct ecryptfs_crypt_stat *crypt_stat =
- &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat;
+ &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;
struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
&ecryptfs_superblock_to_private(
ecryptfs_dentry->d_sb)->mount_crypt_stat;
@@ -1628,27 +1608,18 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry,
page_virt = kmem_cache_alloc(ecryptfs_header_cache_1, GFP_USER);
if (!page_virt) {
rc = -ENOMEM;
- ecryptfs_printk(KERN_ERR, "Unable to allocate page_virt\n");
+ printk(KERN_ERR "%s: Unable to allocate page_virt\n",
+ __FUNCTION__);
goto out;
}
- lower_file->f_pos = 0;
- oldfs = get_fs();
- set_fs(get_ds());
- bytes_read = lower_file->f_op->read(lower_file,
- (char __user *)page_virt,
- ECRYPTFS_DEFAULT_EXTENT_SIZE,
- &lower_file->f_pos);
- set_fs(oldfs);
- if (bytes_read != ECRYPTFS_DEFAULT_EXTENT_SIZE) {
- rc = -EINVAL;
- goto out;
- }
- rc = ecryptfs_read_headers_virt(page_virt, crypt_stat,
- ecryptfs_dentry,
- ECRYPTFS_VALIDATE_HEADER_SIZE);
+ rc = ecryptfs_read_lower(page_virt, 0, crypt_stat->extent_size,
+ ecryptfs_inode);
+ if (!rc)
+ rc = ecryptfs_read_headers_virt(page_virt, crypt_stat,
+ ecryptfs_dentry,
+ ECRYPTFS_VALIDATE_HEADER_SIZE);
if (rc) {
- rc = ecryptfs_read_xattr_region(page_virt,
- ecryptfs_dentry);
+ rc = ecryptfs_read_xattr_region(page_virt, ecryptfs_inode);
if (rc) {
printk(KERN_DEBUG "Valid eCryptfs headers not found in "
"file header region or xattr region\n");
@@ -1776,7 +1747,7 @@ out:
}
/**
- * ecryptfs_process_cipher - Perform cipher initialization.
+ * ecryptfs_process_key_cipher - Perform key cipher initialization.
* @key_tfm: Crypto context for key material, set by this function
* @cipher_name: Name of the cipher
* @key_size: Size of the key in bytes
@@ -1785,9 +1756,9 @@ out:
* should be released by other functions, such as on a superblock put
* event, regardless of whether this function succeeds for fails.
*/
-int
-ecryptfs_process_cipher(struct crypto_blkcipher **key_tfm, char *cipher_name,
- size_t *key_size)
+static int
+ecryptfs_process_key_cipher(struct crypto_blkcipher **key_tfm,
+ char *cipher_name, size_t *key_size)
{
char dummy_key[ECRYPTFS_MAX_KEY_BYTES];
char *full_alg_name;
@@ -1829,3 +1800,100 @@ ecryptfs_process_cipher(struct crypto_blkcipher **key_tfm, char *cipher_name,
out:
return rc;
}
+
+struct kmem_cache *ecryptfs_key_tfm_cache;
+struct list_head key_tfm_list;
+struct mutex key_tfm_list_mutex;
+
+int ecryptfs_init_crypto(void)
+{
+ mutex_init(&key_tfm_list_mutex);
+ INIT_LIST_HEAD(&key_tfm_list);
+ return 0;
+}
+
+int ecryptfs_destroy_crypto(void)
+{
+ struct ecryptfs_key_tfm *key_tfm, *key_tfm_tmp;
+
+ mutex_lock(&key_tfm_list_mutex);
+ list_for_each_entry_safe(key_tfm, key_tfm_tmp, &key_tfm_list,
+ key_tfm_list) {
+ list_del(&key_tfm->key_tfm_list);
+ if (key_tfm->key_tfm)
+ crypto_free_blkcipher(key_tfm->key_tfm);
+ kmem_cache_free(ecryptfs_key_tfm_cache, key_tfm);
+ }
+ mutex_unlock(&key_tfm_list_mutex);
+ return 0;
+}
+
+int
+ecryptfs_add_new_key_tfm(struct ecryptfs_key_tfm **key_tfm, char *cipher_name,
+ size_t key_size)
+{
+ struct ecryptfs_key_tfm *tmp_tfm;
+ int rc = 0;
+
+ tmp_tfm = kmem_cache_alloc(ecryptfs_key_tfm_cache, GFP_KERNEL);
+ if (key_tfm != NULL)
+ (*key_tfm) = tmp_tfm;
+ if (!tmp_tfm) {
+ rc = -ENOMEM;
+ printk(KERN_ERR "Error attempting to allocate from "
+ "ecryptfs_key_tfm_cache\n");
+ goto out;
+ }
+ mutex_init(&tmp_tfm->key_tfm_mutex);
+ strncpy(tmp_tfm->cipher_name, cipher_name,
+ ECRYPTFS_MAX_CIPHER_NAME_SIZE);
+ tmp_tfm->key_size = key_size;
+ rc = ecryptfs_process_key_cipher(&tmp_tfm->key_tfm,
+ tmp_tfm->cipher_name,
+ &tmp_tfm->key_size);
+ if (rc) {
+ printk(KERN_ERR "Error attempting to initialize key TFM "
+ "cipher with name = [%s]; rc = [%d]\n",
+ tmp_tfm->cipher_name, rc);
+ kmem_cache_free(ecryptfs_key_tfm_cache, tmp_tfm);
+ if (key_tfm != NULL)
+ (*key_tfm) = NULL;
+ goto out;
+ }
+ mutex_lock(&key_tfm_list_mutex);
+ list_add(&tmp_tfm->key_tfm_list, &key_tfm_list);
+ mutex_unlock(&key_tfm_list_mutex);
+out:
+ return rc;
+}
+
+int ecryptfs_get_tfm_and_mutex_for_cipher_name(struct crypto_blkcipher **tfm,
+ struct mutex **tfm_mutex,
+ char *cipher_name)
+{
+ struct ecryptfs_key_tfm *key_tfm;
+ int rc = 0;
+
+ (*tfm) = NULL;
+ (*tfm_mutex) = NULL;
+ mutex_lock(&key_tfm_list_mutex);
+ list_for_each_entry(key_tfm, &key_tfm_list, key_tfm_list) {
+ if (strcmp(key_tfm->cipher_name, cipher_name) == 0) {
+ (*tfm) = key_tfm->key_tfm;
+ (*tfm_mutex) = &key_tfm->key_tfm_mutex;
+ mutex_unlock(&key_tfm_list_mutex);
+ goto out;
+ }
+ }
+ mutex_unlock(&key_tfm_list_mutex);
+ rc = ecryptfs_add_new_key_tfm(&key_tfm, cipher_name, 0);
+ if (rc) {
+ printk(KERN_ERR "Error adding new key_tfm to list; rc = [%d]\n",
+ rc);
+ goto out;
+ }
+ (*tfm) = key_tfm->key_tfm;
+ (*tfm_mutex) = &key_tfm->key_tfm_mutex;
+out:
+ return rc;
+}
diff --git a/fs/ecryptfs/debug.c b/fs/ecryptfs/debug.c
index 434c7efd80f8..3d2bdf546ec6 100644
--- a/fs/ecryptfs/debug.c
+++ b/fs/ecryptfs/debug.c
@@ -38,8 +38,6 @@ void ecryptfs_dump_auth_tok(struct ecryptfs_auth_tok *auth_tok)
auth_tok);
if (auth_tok->flags & ECRYPTFS_PRIVATE_KEY) {
ecryptfs_printk(KERN_DEBUG, " * private key type\n");
- ecryptfs_printk(KERN_DEBUG, " * (NO PRIVATE KEY SUPPORT "
- "IN ECRYPTFS VERSION 0.1)\n");
} else {
ecryptfs_printk(KERN_DEBUG, " * passphrase type\n");
ecryptfs_to_hex(salt, auth_tok->token.password.salt,
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index 1b9dd9a96f19..ce7a5d4aec36 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -38,7 +38,7 @@
/* Version verification for shared data structures w/ userspace */
#define ECRYPTFS_VERSION_MAJOR 0x00
#define ECRYPTFS_VERSION_MINOR 0x04
-#define ECRYPTFS_SUPPORTED_FILE_VERSION 0x02
+#define ECRYPTFS_SUPPORTED_FILE_VERSION 0x03
/* These flags indicate which features are supported by the kernel
* module; userspace tools such as the mount helper read
* ECRYPTFS_VERSIONING_MASK from a sysfs handle in order to determine
@@ -48,10 +48,12 @@
#define ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH 0x00000004
#define ECRYPTFS_VERSIONING_POLICY 0x00000008
#define ECRYPTFS_VERSIONING_XATTR 0x00000010
+#define ECRYPTFS_VERSIONING_MULTKEY 0x00000020
#define ECRYPTFS_VERSIONING_MASK (ECRYPTFS_VERSIONING_PASSPHRASE \
| ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH \
| ECRYPTFS_VERSIONING_PUBKEY \
- | ECRYPTFS_VERSIONING_XATTR)
+ | ECRYPTFS_VERSIONING_XATTR \
+ | ECRYPTFS_VERSIONING_MULTKEY)
#define ECRYPTFS_MAX_PASSWORD_LENGTH 64
#define ECRYPTFS_MAX_PASSPHRASE_BYTES ECRYPTFS_MAX_PASSWORD_LENGTH
#define ECRYPTFS_SALT_SIZE 8
@@ -65,8 +67,7 @@
#define ECRYPTFS_MAX_KEY_BYTES 64
#define ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES 512
#define ECRYPTFS_DEFAULT_IV_BYTES 16
-#define ECRYPTFS_FILE_VERSION 0x02
-#define ECRYPTFS_DEFAULT_HEADER_EXTENT_SIZE 8192
+#define ECRYPTFS_FILE_VERSION 0x03
#define ECRYPTFS_DEFAULT_EXTENT_SIZE 4096
#define ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE 8192
#define ECRYPTFS_DEFAULT_MSG_CTX_ELEMS 32
@@ -144,6 +145,7 @@ struct ecryptfs_private_key {
struct ecryptfs_auth_tok {
u16 version; /* 8-bit major and 8-bit minor */
u16 token_type;
+#define ECRYPTFS_ENCRYPT_ONLY 0x00000001
u32 flags;
struct ecryptfs_session_key session_key;
u8 reserved[32];
@@ -194,12 +196,11 @@ ecryptfs_get_key_payload_data(struct key *key)
#define ECRYPTFS_MAX_KEYSET_SIZE 1024
#define ECRYPTFS_MAX_CIPHER_NAME_SIZE 32
#define ECRYPTFS_MAX_NUM_ENC_KEYS 64
-#define ECRYPTFS_MAX_NUM_KEYSIGS 2 /* TODO: Make this a linked list */
#define ECRYPTFS_MAX_IV_BYTES 16 /* 128 bits */
#define ECRYPTFS_SALT_BYTES 2
#define MAGIC_ECRYPTFS_MARKER 0x3c81b7f5
#define MAGIC_ECRYPTFS_MARKER_SIZE_BYTES 8 /* 4*2 */
-#define ECRYPTFS_FILE_SIZE_BYTES 8
+#define ECRYPTFS_FILE_SIZE_BYTES (sizeof(u64))
#define ECRYPTFS_DEFAULT_CIPHER "aes"
#define ECRYPTFS_DEFAULT_KEY_BYTES 16
#define ECRYPTFS_DEFAULT_HASH "md5"
@@ -212,6 +213,11 @@ ecryptfs_get_key_payload_data(struct key *key)
#define ECRYPTFS_TAG_67_PACKET_TYPE 0x43
#define MD5_DIGEST_SIZE 16
+struct ecryptfs_key_sig {
+ struct list_head crypt_stat_list;
+ char keysig[ECRYPTFS_SIG_SIZE_HEX];
+};
+
/**
* This is the primary struct associated with each encrypted file.
*
@@ -231,8 +237,6 @@ struct ecryptfs_crypt_stat {
u32 flags;
unsigned int file_version;
size_t iv_bytes;
- size_t num_keysigs;
- size_t header_extent_size;
size_t num_header_extents_at_front;
size_t extent_size; /* Data extent size; default is 4096 */
size_t key_size;
@@ -245,7 +249,8 @@ struct ecryptfs_crypt_stat {
unsigned char cipher[ECRYPTFS_MAX_CIPHER_NAME_SIZE];
unsigned char key[ECRYPTFS_MAX_KEY_BYTES];
unsigned char root_iv[ECRYPTFS_MAX_IV_BYTES];
- unsigned char keysigs[ECRYPTFS_MAX_NUM_KEYSIGS][ECRYPTFS_SIG_SIZE_HEX];
+ struct list_head keysig_list;
+ struct mutex keysig_list_mutex;
struct mutex cs_tfm_mutex;
struct mutex cs_hash_tfm_mutex;
struct mutex cs_mutex;
@@ -255,6 +260,8 @@ struct ecryptfs_crypt_stat {
struct ecryptfs_inode_info {
struct inode vfs_inode;
struct inode *wii_inode;
+ struct file *lower_file;
+ struct mutex lower_file_mutex;
struct ecryptfs_crypt_stat crypt_stat;
};
@@ -266,6 +273,59 @@ struct ecryptfs_dentry_info {
};
/**
+ * ecryptfs_global_auth_tok - A key used to encrypt all new files under the mountpoint
+ * @flags: Status flags
+ * @mount_crypt_stat_list: These auth_toks hang off the mount-wide
+ * cryptographic context. Every time a new
+ * inode comes into existence, eCryptfs copies
+ * the auth_toks on that list to the set of
+ * auth_toks on the inode's crypt_stat
+ * @global_auth_tok_key: The key from the user's keyring for the sig
+ * @global_auth_tok: The key contents
+ * @sig: The key identifier
+ *
+ * ecryptfs_global_auth_tok structs refer to authentication token keys
+ * in the user keyring that apply to newly created files. A list of
+ * these objects hangs off of the mount_crypt_stat struct for any
+ * given eCryptfs mount. This struct maintains a reference to both the
+ * key contents and the key itself so that the key can be put on
+ * unmount.
+ */
+struct ecryptfs_global_auth_tok {
+#define ECRYPTFS_AUTH_TOK_INVALID 0x00000001
+ u32 flags;
+ struct list_head mount_crypt_stat_list;
+ struct key *global_auth_tok_key;
+ struct ecryptfs_auth_tok *global_auth_tok;
+ unsigned char sig[ECRYPTFS_SIG_SIZE_HEX + 1];
+};
+
+/**
+ * ecryptfs_key_tfm - Persistent key tfm
+ * @key_tfm: crypto API handle to the key
+ * @key_size: Key size in bytes
+ * @key_tfm_mutex: Mutex to ensure only one operation in eCryptfs is
+ * using the persistent TFM at any point in time
+ * @key_tfm_list: Handle to hang this off the module-wide TFM list
+ * @cipher_name: String name for the cipher for this TFM
+ *
+ * Typically, eCryptfs will use the same ciphers repeatedly throughout
+ * the course of its operations. In order to avoid unnecessarily
+ * destroying and initializing the same cipher repeatedly, eCryptfs
+ * keeps a list of crypto API contexts around to use when needed.
+ */
+struct ecryptfs_key_tfm {
+ struct crypto_blkcipher *key_tfm;
+ size_t key_size;
+ struct mutex key_tfm_mutex;
+ struct list_head key_tfm_list;
+ unsigned char cipher_name[ECRYPTFS_MAX_CIPHER_NAME_SIZE + 1];
+};
+
+extern struct list_head key_tfm_list;
+extern struct mutex key_tfm_list_mutex;
+
+/**
* This struct is to enable a mount-wide passphrase/salt combo. This
* is more or less a stopgap to provide similar functionality to other
* crypto filesystems like EncFS or CFS until full policy support is
@@ -276,15 +336,14 @@ struct ecryptfs_mount_crypt_stat {
#define ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED 0x00000001
#define ECRYPTFS_XATTR_METADATA_ENABLED 0x00000002
#define ECRYPTFS_ENCRYPTED_VIEW_ENABLED 0x00000004
+#define ECRYPTFS_MOUNT_CRYPT_STAT_INITIALIZED 0x00000008
u32 flags;
- struct ecryptfs_auth_tok *global_auth_tok;
- struct key *global_auth_tok_key;
+ struct list_head global_auth_tok_list;
+ struct mutex global_auth_tok_list_mutex;
+ size_t num_global_auth_toks;
size_t global_default_cipher_key_size;
- struct crypto_blkcipher *global_key_tfm;
- struct mutex global_key_tfm_mutex;
unsigned char global_default_cipher_name[ECRYPTFS_MAX_CIPHER_NAME_SIZE
+ 1];
- unsigned char global_auth_tok_sig[ECRYPTFS_SIG_SIZE_HEX + 1];
};
/* superblock private data. */
@@ -468,6 +527,9 @@ extern struct kmem_cache *ecryptfs_header_cache_2;
extern struct kmem_cache *ecryptfs_xattr_cache;
extern struct kmem_cache *ecryptfs_lower_page_cache;
extern struct kmem_cache *ecryptfs_key_record_cache;
+extern struct kmem_cache *ecryptfs_key_sig_cache;
+extern struct kmem_cache *ecryptfs_global_auth_tok_cache;
+extern struct kmem_cache *ecryptfs_key_tfm_cache;
int ecryptfs_interpose(struct dentry *hidden_dentry,
struct dentry *this_dentry, struct super_block *sb,
@@ -486,44 +548,18 @@ int virt_to_scatterlist(const void *addr, int size, struct scatterlist *sg,
int ecryptfs_compute_root_iv(struct ecryptfs_crypt_stat *crypt_stat);
void ecryptfs_rotate_iv(unsigned char *iv);
void ecryptfs_init_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat);
-void ecryptfs_destruct_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat);
-void ecryptfs_destruct_mount_crypt_stat(
+void ecryptfs_destroy_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat);
+void ecryptfs_destroy_mount_crypt_stat(
struct ecryptfs_mount_crypt_stat *mount_crypt_stat);
int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat);
-int ecryptfs_crypto_api_algify_cipher_name(char **algified_name,
- char *cipher_name,
- char *chaining_modifier);
-#define ECRYPTFS_LOWER_I_MUTEX_NOT_HELD 0
-#define ECRYPTFS_LOWER_I_MUTEX_HELD 1
-int ecryptfs_write_inode_size_to_metadata(struct file *lower_file,
- struct inode *lower_inode,
- struct inode *inode,
- struct dentry *ecryptfs_dentry,
- int lower_i_mutex_held);
-int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode,
- struct file *lower_file,
- unsigned long lower_page_index, int byte_offset,
- int region_bytes);
-int
-ecryptfs_commit_lower_page(struct page *lower_page, struct inode *lower_inode,
- struct file *lower_file, int byte_offset,
- int region_size);
-int ecryptfs_copy_page_to_lower(struct page *page, struct inode *lower_inode,
- struct file *lower_file);
-int ecryptfs_do_readpage(struct file *file, struct page *page,
- pgoff_t lower_page_index);
-int ecryptfs_writepage_and_release_lower_page(struct page *lower_page,
- struct inode *lower_inode,
- struct writeback_control *wbc);
-int ecryptfs_encrypt_page(struct ecryptfs_page_crypt_context *ctx);
-int ecryptfs_decrypt_page(struct file *file, struct page *page);
-int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry,
- struct file *lower_file);
-int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry,
- struct file *lower_file);
+int ecryptfs_write_inode_size_to_metadata(struct inode *ecryptfs_inode);
+int ecryptfs_encrypt_page(struct page *page);
+int ecryptfs_decrypt_page(struct page *page);
+int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry);
+int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry);
int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry);
-int ecryptfs_read_and_validate_header_region(char *data, struct dentry *dentry,
- struct vfsmount *mnt);
+int ecryptfs_read_and_validate_header_region(char *data,
+ struct inode *ecryptfs_inode);
int ecryptfs_read_and_validate_xattr_region(char *page_virt,
struct dentry *ecryptfs_dentry);
u16 ecryptfs_code_for_cipher_string(struct ecryptfs_crypt_stat *crypt_stat);
@@ -533,27 +569,22 @@ int ecryptfs_generate_key_packet_set(char *dest_base,
struct ecryptfs_crypt_stat *crypt_stat,
struct dentry *ecryptfs_dentry,
size_t *len, size_t max);
-int process_request_key_err(long err_code);
int
ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat,
unsigned char *src, struct dentry *ecryptfs_dentry);
int ecryptfs_truncate(struct dentry *dentry, loff_t new_length);
-int
-ecryptfs_process_cipher(struct crypto_blkcipher **key_tfm, char *cipher_name,
- size_t *key_size);
int ecryptfs_inode_test(struct inode *inode, void *candidate_lower_inode);
int ecryptfs_inode_set(struct inode *inode, void *lower_inode);
void ecryptfs_init_inode(struct inode *inode, struct inode *lower_inode);
-int ecryptfs_open_lower_file(struct file **lower_file,
- struct dentry *lower_dentry,
- struct vfsmount *lower_mnt, int flags);
-int ecryptfs_close_lower_file(struct file *lower_file);
ssize_t ecryptfs_getxattr(struct dentry *dentry, const char *name, void *value,
size_t size);
+ssize_t
+ecryptfs_getxattr_lower(struct dentry *lower_dentry, const char *name,
+ void *value, size_t size);
int
ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value,
size_t size, int flags);
-int ecryptfs_read_xattr_region(char *page_virt, struct dentry *ecryptfs_dentry);
+int ecryptfs_read_xattr_region(char *page_virt, struct inode *ecryptfs_inode);
int ecryptfs_process_helo(unsigned int transport, uid_t uid, pid_t pid);
int ecryptfs_process_quit(uid_t uid, pid_t pid);
int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t uid,
@@ -580,7 +611,43 @@ void
ecryptfs_write_header_metadata(char *virt,
struct ecryptfs_crypt_stat *crypt_stat,
size_t *written);
+int ecryptfs_add_keysig(struct ecryptfs_crypt_stat *crypt_stat, char *sig);
+int
+ecryptfs_add_global_auth_tok(struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
+ char *sig);
+int ecryptfs_get_global_auth_tok_for_sig(
+ struct ecryptfs_global_auth_tok **global_auth_tok,
+ struct ecryptfs_mount_crypt_stat *mount_crypt_stat, char *sig);
+int
+ecryptfs_add_new_key_tfm(struct ecryptfs_key_tfm **key_tfm, char *cipher_name,
+ size_t key_size);
+int ecryptfs_init_crypto(void);
+int ecryptfs_destroy_crypto(void);
+int ecryptfs_get_tfm_and_mutex_for_cipher_name(struct crypto_blkcipher **tfm,
+ struct mutex **tfm_mutex,
+ char *cipher_name);
+int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key,
+ struct ecryptfs_auth_tok **auth_tok,
+ char *sig);
int ecryptfs_write_zeros(struct file *file, pgoff_t index, int start,
int num_zeros);
+void ecryptfs_lower_offset_for_extent(loff_t *offset, loff_t extent_num,
+ struct ecryptfs_crypt_stat *crypt_stat);
+int ecryptfs_write_lower(struct inode *ecryptfs_inode, char *data,
+ loff_t offset, size_t size);
+int ecryptfs_write_lower_page_segment(struct inode *ecryptfs_inode,
+ struct page *page_for_lower,
+ size_t offset_in_page, size_t size);
+int ecryptfs_write(struct file *ecryptfs_file, char *data, loff_t offset,
+ size_t size);
+int ecryptfs_read_lower(char *data, loff_t offset, size_t size,
+ struct inode *ecryptfs_inode);
+int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs,
+ pgoff_t page_index,
+ size_t offset_in_page, size_t size,
+ struct inode *ecryptfs_inode);
+int ecryptfs_read(char *data, loff_t offset, size_t size,
+ struct file *ecryptfs_file);
+struct page *ecryptfs_get_locked_page(struct file *file, loff_t index);
#endif /* #ifndef ECRYPTFS_KERNEL_H */
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index 94f456fe4d9b..c98c4690a771 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -141,34 +141,6 @@ retry:
struct kmem_cache *ecryptfs_file_info_cache;
-int ecryptfs_open_lower_file(struct file **lower_file,
- struct dentry *lower_dentry,
- struct vfsmount *lower_mnt, int flags)
-{
- int rc = 0;
-
- flags |= O_LARGEFILE;
- dget(lower_dentry);
- mntget(lower_mnt);
- *lower_file = dentry_open(lower_dentry, lower_mnt, flags);
- if (IS_ERR(*lower_file)) {
- printk(KERN_ERR "Error opening lower file for lower_dentry "
- "[0x%p], lower_mnt [0x%p], and flags [0x%x]\n",
- lower_dentry, lower_mnt, flags);
- rc = PTR_ERR(*lower_file);
- *lower_file = NULL;
- goto out;
- }
-out:
- return rc;
-}
-
-int ecryptfs_close_lower_file(struct file *lower_file)
-{
- fput(lower_file);
- return 0;
-}
-
/**
* ecryptfs_open
* @inode: inode speciying file to open
@@ -187,11 +159,7 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
/* Private value of ecryptfs_dentry allocated in
* ecryptfs_lookup() */
struct dentry *lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
- struct inode *lower_inode = NULL;
- struct file *lower_file = NULL;
- struct vfsmount *lower_mnt;
struct ecryptfs_file_info *file_info;
- int lower_flags;
mount_crypt_stat = &ecryptfs_superblock_to_private(
ecryptfs_dentry->d_sb)->mount_crypt_stat;
@@ -219,25 +187,12 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)) {
ecryptfs_printk(KERN_DEBUG, "Setting flags for stat...\n");
/* Policy code enabled in future release */
- crypt_stat->flags |= ECRYPTFS_POLICY_APPLIED;
- crypt_stat->flags |= ECRYPTFS_ENCRYPTED;
+ crypt_stat->flags |= (ECRYPTFS_POLICY_APPLIED
+ | ECRYPTFS_ENCRYPTED);
}
mutex_unlock(&crypt_stat->cs_mutex);
- lower_flags = file->f_flags;
- if ((lower_flags & O_ACCMODE) == O_WRONLY)
- lower_flags = (lower_flags & O_ACCMODE) | O_RDWR;
- if (file->f_flags & O_APPEND)
- lower_flags &= ~O_APPEND;
- lower_mnt = ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry);
- /* Corresponding fput() in ecryptfs_release() */
- if ((rc = ecryptfs_open_lower_file(&lower_file, lower_dentry, lower_mnt,
- lower_flags))) {
- ecryptfs_printk(KERN_ERR, "Error opening lower file\n");
- goto out_puts;
- }
- ecryptfs_set_file_lower(file, lower_file);
- /* Isn't this check the same as the one in lookup? */
- lower_inode = lower_dentry->d_inode;
+ ecryptfs_set_file_lower(
+ file, ecryptfs_inode_to_private(inode)->lower_file);
if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
ecryptfs_printk(KERN_DEBUG, "This is a directory\n");
crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
@@ -247,7 +202,7 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
mutex_lock(&crypt_stat->cs_mutex);
if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)
|| !(crypt_stat->flags & ECRYPTFS_KEY_VALID)) {
- rc = ecryptfs_read_metadata(ecryptfs_dentry, lower_file);
+ rc = ecryptfs_read_metadata(ecryptfs_dentry);
if (rc) {
ecryptfs_printk(KERN_DEBUG,
"Valid headers not found\n");
@@ -259,7 +214,7 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
"and plaintext passthrough mode is not "
"enabled; returning -EIO\n");
mutex_unlock(&crypt_stat->cs_mutex);
- goto out_puts;
+ goto out_free;
}
rc = 0;
crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
@@ -271,11 +226,8 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
ecryptfs_printk(KERN_DEBUG, "inode w/ addr = [0x%p], i_ino = [0x%.16x] "
"size: [0x%.16x]\n", inode, inode->i_ino,
i_size_read(inode));
- ecryptfs_set_file_lower(file, lower_file);
goto out;
-out_puts:
- mntput(lower_mnt);
- dput(lower_dentry);
+out_free:
kmem_cache_free(ecryptfs_file_info_cache,
ecryptfs_file_to_private(file));
out:
@@ -295,19 +247,9 @@ static int ecryptfs_flush(struct file *file, fl_owner_t td)
static int ecryptfs_release(struct inode *inode, struct file *file)
{
- struct file *lower_file = ecryptfs_file_to_lower(file);
- struct ecryptfs_file_info *file_info = ecryptfs_file_to_private(file);
- struct inode *lower_inode = ecryptfs_inode_to_lower(inode);
- int rc;
-
- if ((rc = ecryptfs_close_lower_file(lower_file))) {
- printk(KERN_ERR "Error closing lower_file\n");
- goto out;
- }
- inode->i_blocks = lower_inode->i_blocks;
- kmem_cache_free(ecryptfs_file_info_cache, file_info);
-out:
- return rc;
+ kmem_cache_free(ecryptfs_file_info_cache,
+ ecryptfs_file_to_private(file));
+ return 0;
}
static int
@@ -338,21 +280,6 @@ static int ecryptfs_fasync(int fd, struct file *file, int flag)
return rc;
}
-static ssize_t ecryptfs_splice_read(struct file *file, loff_t * ppos,
- struct pipe_inode_info *pipe, size_t count,
- unsigned int flags)
-{
- struct file *lower_file = NULL;
- int rc = -EINVAL;
-
- lower_file = ecryptfs_file_to_lower(file);
- if (lower_file->f_op && lower_file->f_op->splice_read)
- rc = lower_file->f_op->splice_read(lower_file, ppos, pipe,
- count, flags);
-
- return rc;
-}
-
static int ecryptfs_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg);
@@ -365,7 +292,7 @@ const struct file_operations ecryptfs_dir_fops = {
.release = ecryptfs_release,
.fsync = ecryptfs_fsync,
.fasync = ecryptfs_fasync,
- .splice_read = ecryptfs_splice_read,
+ .splice_read = generic_file_splice_read,
};
const struct file_operations ecryptfs_main_fops = {
@@ -382,7 +309,7 @@ const struct file_operations ecryptfs_main_fops = {
.release = ecryptfs_release,
.fsync = ecryptfs_fsync,
.fasync = ecryptfs_fasync,
- .splice_read = ecryptfs_splice_read,
+ .splice_read = generic_file_splice_read,
};
static int
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 131954b3fb98..0b1ab016fa2e 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -119,10 +119,23 @@ ecryptfs_do_create(struct inode *directory_inode,
}
rc = ecryptfs_create_underlying_file(lower_dir_dentry->d_inode,
ecryptfs_dentry, mode, nd);
- if (unlikely(rc)) {
- ecryptfs_printk(KERN_ERR,
- "Failure to create underlying file\n");
- goto out_lock;
+ if (rc) {
+ struct inode *ecryptfs_inode = ecryptfs_dentry->d_inode;
+ struct ecryptfs_inode_info *inode_info =
+ ecryptfs_inode_to_private(ecryptfs_inode);
+
+ printk(KERN_WARNING "%s: Error creating underlying file; "
+ "rc = [%d]; checking for existing\n", __FUNCTION__, rc);
+ if (inode_info) {
+ mutex_lock(&inode_info->lower_file_mutex);
+ if (!inode_info->lower_file) {
+ mutex_unlock(&inode_info->lower_file_mutex);
+ printk(KERN_ERR "%s: Failure to set underlying "
+ "file; rc = [%d]\n", __FUNCTION__, rc);
+ goto out_lock;
+ }
+ mutex_unlock(&inode_info->lower_file_mutex);
+ }
}
rc = ecryptfs_interpose(lower_dentry, ecryptfs_dentry,
directory_inode->i_sb, 0);
@@ -140,39 +153,30 @@ out:
/**
* grow_file
- * @ecryptfs_dentry: the ecryptfs dentry
- * @lower_file: The lower file
- * @inode: The ecryptfs inode
- * @lower_inode: The lower inode
+ * @ecryptfs_dentry: the eCryptfs dentry
*
* This is the code which will grow the file to its correct size.
*/
-static int grow_file(struct dentry *ecryptfs_dentry, struct file *lower_file,
- struct inode *inode, struct inode *lower_inode)
+static int grow_file(struct dentry *ecryptfs_dentry)
{
- int rc = 0;
+ struct inode *ecryptfs_inode = ecryptfs_dentry->d_inode;
struct file fake_file;
struct ecryptfs_file_info tmp_file_info;
+ char zero_virt[] = { 0x00 };
+ int rc = 0;
memset(&fake_file, 0, sizeof(fake_file));
fake_file.f_path.dentry = ecryptfs_dentry;
memset(&tmp_file_info, 0, sizeof(tmp_file_info));
ecryptfs_set_file_private(&fake_file, &tmp_file_info);
- ecryptfs_set_file_lower(&fake_file, lower_file);
- rc = ecryptfs_fill_zeros(&fake_file, 1);
- if (rc) {
- ecryptfs_inode_to_private(inode)->crypt_stat.flags |=
- ECRYPTFS_SECURITY_WARNING;
- ecryptfs_printk(KERN_WARNING, "Error attempting to fill zeros "
- "in file; rc = [%d]\n", rc);
- goto out;
- }
- i_size_write(inode, 0);
- rc = ecryptfs_write_inode_size_to_metadata(lower_file, lower_inode,
- inode, ecryptfs_dentry,
- ECRYPTFS_LOWER_I_MUTEX_NOT_HELD);
- ecryptfs_inode_to_private(inode)->crypt_stat.flags |= ECRYPTFS_NEW_FILE;
-out:
+ ecryptfs_set_file_lower(
+ &fake_file,
+ ecryptfs_inode_to_private(ecryptfs_inode)->lower_file);
+ rc = ecryptfs_write(&fake_file, zero_virt, 0, 1);
+ i_size_write(ecryptfs_inode, 0);
+ rc = ecryptfs_write_inode_size_to_metadata(ecryptfs_inode);
+ ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat.flags |=
+ ECRYPTFS_NEW_FILE;
return rc;
}
@@ -186,51 +190,31 @@ out:
*/
static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry)
{
+ struct ecryptfs_crypt_stat *crypt_stat =
+ &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat;
int rc = 0;
- int lower_flags;
- struct ecryptfs_crypt_stat *crypt_stat;
- struct dentry *lower_dentry;
- struct file *lower_file;
- struct inode *inode, *lower_inode;
- struct vfsmount *lower_mnt;
- lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
- ecryptfs_printk(KERN_DEBUG, "lower_dentry->d_name.name = [%s]\n",
- lower_dentry->d_name.name);
- inode = ecryptfs_dentry->d_inode;
- crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
- lower_flags = ((O_CREAT | O_TRUNC) & O_ACCMODE) | O_RDWR;
- lower_mnt = ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry);
- /* Corresponding fput() at end of this function */
- if ((rc = ecryptfs_open_lower_file(&lower_file, lower_dentry, lower_mnt,
- lower_flags))) {
- ecryptfs_printk(KERN_ERR,
- "Error opening dentry; rc = [%i]\n", rc);
- goto out;
- }
- lower_inode = lower_dentry->d_inode;
if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
ecryptfs_printk(KERN_DEBUG, "This is a directory\n");
crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
- goto out_fput;
+ goto out;
}
crypt_stat->flags |= ECRYPTFS_NEW_FILE;
ecryptfs_printk(KERN_DEBUG, "Initializing crypto context\n");
rc = ecryptfs_new_file_context(ecryptfs_dentry);
if (rc) {
- ecryptfs_printk(KERN_DEBUG, "Error creating new file "
- "context\n");
- goto out_fput;
+ ecryptfs_printk(KERN_ERR, "Error creating new file "
+ "context; rc = [%d]\n", rc);
+ goto out;
}
- rc = ecryptfs_write_metadata(ecryptfs_dentry, lower_file);
+ rc = ecryptfs_write_metadata(ecryptfs_dentry);
if (rc) {
- ecryptfs_printk(KERN_DEBUG, "Error writing headers\n");
- goto out_fput;
+ printk(KERN_ERR "Error writing headers; rc = [%d]\n", rc);
+ goto out;
}
- rc = grow_file(ecryptfs_dentry, lower_file, inode, lower_inode);
-out_fput:
- if ((rc = ecryptfs_close_lower_file(lower_file)))
- printk(KERN_ERR "Error closing lower_file\n");
+ rc = grow_file(ecryptfs_dentry);
+ if (rc)
+ printk(KERN_ERR "Error growing file; rc = [%d]\n", rc);
out:
return rc;
}
@@ -252,6 +236,8 @@ ecryptfs_create(struct inode *directory_inode, struct dentry *ecryptfs_dentry,
{
int rc;
+ /* ecryptfs_do_create() calls ecryptfs_interpose(), which opens
+ * the crypt_stat->lower_file (persistent file) */
rc = ecryptfs_do_create(directory_inode, ecryptfs_dentry, mode, nd);
if (unlikely(rc)) {
ecryptfs_printk(KERN_WARNING, "Failed to create file in"
@@ -374,8 +360,8 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry,
crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat;
if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED))
ecryptfs_set_default_sizes(crypt_stat);
- rc = ecryptfs_read_and_validate_header_region(page_virt, lower_dentry,
- nd->mnt);
+ rc = ecryptfs_read_and_validate_header_region(page_virt,
+ dentry->d_inode);
if (rc) {
rc = ecryptfs_read_and_validate_xattr_region(page_virt, dentry);
if (rc) {
@@ -392,7 +378,8 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry,
dentry->d_sb)->mount_crypt_stat;
if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) {
if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
- file_size = (crypt_stat->header_extent_size
+ file_size = ((crypt_stat->extent_size
+ * crypt_stat->num_header_extents_at_front)
+ i_size_read(lower_dentry->d_inode));
else
file_size = i_size_read(lower_dentry->d_inode);
@@ -722,8 +709,8 @@ upper_size_to_lower_size(struct ecryptfs_crypt_stat *crypt_stat,
{
loff_t lower_size;
- lower_size = ( crypt_stat->header_extent_size
- * crypt_stat->num_header_extents_at_front );
+ lower_size = (crypt_stat->extent_size
+ * crypt_stat->num_header_extents_at_front);
if (upper_size != 0) {
loff_t num_extents;
@@ -752,8 +739,7 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)
int rc = 0;
struct inode *inode = dentry->d_inode;
struct dentry *lower_dentry;
- struct vfsmount *lower_mnt;
- struct file fake_ecryptfs_file, *lower_file = NULL;
+ struct file fake_ecryptfs_file;
struct ecryptfs_crypt_stat *crypt_stat;
loff_t i_size = i_size_read(inode);
loff_t lower_size_before_truncate;
@@ -776,62 +762,52 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)
goto out;
}
lower_dentry = ecryptfs_dentry_to_lower(dentry);
- /* This dget & mntget is released through fput at out_fput: */
- lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
- if ((rc = ecryptfs_open_lower_file(&lower_file, lower_dentry, lower_mnt,
- O_RDWR))) {
- ecryptfs_printk(KERN_ERR,
- "Error opening dentry; rc = [%i]\n", rc);
- goto out_free;
- }
- ecryptfs_set_file_lower(&fake_ecryptfs_file, lower_file);
+ ecryptfs_set_file_lower(
+ &fake_ecryptfs_file,
+ ecryptfs_inode_to_private(dentry->d_inode)->lower_file);
/* Switch on growing or shrinking file */
if (new_length > i_size) {
- rc = ecryptfs_fill_zeros(&fake_ecryptfs_file, new_length);
- if (rc) {
- ecryptfs_printk(KERN_ERR,
- "Problem with fill_zeros\n");
- goto out_fput;
- }
- i_size_write(inode, new_length);
- rc = ecryptfs_write_inode_size_to_metadata(
- lower_file, lower_dentry->d_inode, inode, dentry,
- ECRYPTFS_LOWER_I_MUTEX_NOT_HELD);
- if (rc) {
- printk(KERN_ERR "Problem with "
- "ecryptfs_write_inode_size_to_metadata; "
- "rc = [%d]\n", rc);
- goto out_fput;
- }
+ char zero[] = { 0x00 };
+
+ /* Write a single 0 at the last position of the file;
+ * this triggers code that will fill in 0's throughout
+ * the intermediate portion of the previous end of the
+ * file and the new and of the file */
+ rc = ecryptfs_write(&fake_ecryptfs_file, zero,
+ (new_length - 1), 1);
} else { /* new_length < i_size_read(inode) */
- pgoff_t index = 0;
- int end_pos_in_page = -1;
+ /* We're chopping off all the pages down do the page
+ * in which new_length is located. Fill in the end of
+ * that page from (new_length & ~PAGE_CACHE_MASK) to
+ * PAGE_CACHE_SIZE with zeros. */
+ size_t num_zeros = (PAGE_CACHE_SIZE
+ - (new_length & ~PAGE_CACHE_MASK));
- if (new_length != 0) {
- index = ((new_length - 1) >> PAGE_CACHE_SHIFT);
- end_pos_in_page = ((new_length - 1) & ~PAGE_CACHE_MASK);
- }
- if (end_pos_in_page != (PAGE_CACHE_SIZE - 1)) {
- if ((rc = ecryptfs_write_zeros(&fake_ecryptfs_file,
- index,
- (end_pos_in_page + 1),
- ((PAGE_CACHE_SIZE - 1)
- - end_pos_in_page)))) {
+ if (num_zeros) {
+ char *zeros_virt;
+
+ zeros_virt = kzalloc(num_zeros, GFP_KERNEL);
+ if (!zeros_virt) {
+ rc = -ENOMEM;
+ goto out_free;
+ }
+ rc = ecryptfs_write(&fake_ecryptfs_file, zeros_virt,
+ new_length, num_zeros);
+ kfree(zeros_virt);
+ if (rc) {
printk(KERN_ERR "Error attempting to zero out "
"the remainder of the end page on "
"reducing truncate; rc = [%d]\n", rc);
- goto out_fput;
+ goto out_free;
}
}
vmtruncate(inode, new_length);
- rc = ecryptfs_write_inode_size_to_metadata(
- lower_file, lower_dentry->d_inode, inode, dentry,
- ECRYPTFS_LOWER_I_MUTEX_NOT_HELD);
+ rc = ecryptfs_write_inode_size_to_metadata(inode);
if (rc) {
printk(KERN_ERR "Problem with "
"ecryptfs_write_inode_size_to_metadata; "
"rc = [%d]\n", rc);
- goto out_fput;
+ goto out_free;
}
/* We are reducing the size of the ecryptfs file, and need to
* know if we need to reduce the size of the lower file. */
@@ -843,13 +819,6 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)
vmtruncate(lower_dentry->d_inode,
lower_size_after_truncate);
}
- /* Update the access times */
- lower_dentry->d_inode->i_mtime = lower_dentry->d_inode->i_ctime
- = CURRENT_TIME;
- mark_inode_dirty_sync(inode);
-out_fput:
- if ((rc = ecryptfs_close_lower_file(lower_file)))
- printk(KERN_ERR "Error closing lower_file\n");
out_free:
if (ecryptfs_file_to_private(&fake_ecryptfs_file))
kmem_cache_free(ecryptfs_file_info_cache,
@@ -909,23 +878,12 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
else if (S_ISREG(dentry->d_inode->i_mode)
&& (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)
|| !(crypt_stat->flags & ECRYPTFS_KEY_VALID))) {
- struct vfsmount *lower_mnt;
- struct file *lower_file = NULL;
struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
- int lower_flags;
-
- lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
- lower_flags = O_RDONLY;
- if ((rc = ecryptfs_open_lower_file(&lower_file, lower_dentry,
- lower_mnt, lower_flags))) {
- printk(KERN_ERR
- "Error opening lower file; rc = [%d]\n", rc);
- mutex_unlock(&crypt_stat->cs_mutex);
- goto out;
- }
+
mount_crypt_stat = &ecryptfs_superblock_to_private(
dentry->d_sb)->mount_crypt_stat;
- if ((rc = ecryptfs_read_metadata(dentry, lower_file))) {
+ rc = ecryptfs_read_metadata(dentry);
+ if (rc) {
if (!(mount_crypt_stat->flags
& ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) {
rc = -EIO;
@@ -935,16 +893,13 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
"enabled; returning -EIO\n");
mutex_unlock(&crypt_stat->cs_mutex);
- fput(lower_file);
goto out;
}
rc = 0;
crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
mutex_unlock(&crypt_stat->cs_mutex);
- fput(lower_file);
goto out;
}
- fput(lower_file);
}
mutex_unlock(&crypt_stat->cs_mutex);
if (ia->ia_valid & ATTR_SIZE) {
@@ -959,6 +914,14 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
if (rc < 0)
goto out;
}
+
+ /*
+ * mode change is for clearing setuid/setgid bits. Allow lower fs
+ * to interpret this in its own way.
+ */
+ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
+ ia->ia_valid &= ~ATTR_MODE;
+
rc = notify_change(lower_dentry, ia);
out:
fsstack_copy_attr_all(inode, lower_inode, NULL);
@@ -986,13 +949,11 @@ out:
}
ssize_t
-ecryptfs_getxattr(struct dentry *dentry, const char *name, void *value,
- size_t size)
+ecryptfs_getxattr_lower(struct dentry *lower_dentry, const char *name,
+ void *value, size_t size)
{
int rc = 0;
- struct dentry *lower_dentry;
- lower_dentry = ecryptfs_dentry_to_lower(dentry);
if (!lower_dentry->d_inode->i_op->getxattr) {
rc = -ENOSYS;
goto out;
@@ -1005,6 +966,14 @@ out:
return rc;
}
+ssize_t
+ecryptfs_getxattr(struct dentry *dentry, const char *name, void *value,
+ size_t size)
+{
+ return ecryptfs_getxattr_lower(ecryptfs_dentry_to_lower(dentry), name,
+ value, size);
+}
+
static ssize_t
ecryptfs_listxattr(struct dentry *dentry, char *list, size_t size)
{
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c
index b550dea8eee6..263fed88c0ca 100644
--- a/fs/ecryptfs/keystore.c
+++ b/fs/ecryptfs/keystore.c
@@ -39,7 +39,7 @@
* determine the type of error, make appropriate log entries, and
* return an error code.
*/
-int process_request_key_err(long err_code)
+static int process_request_key_err(long err_code)
{
int rc = 0;
@@ -71,7 +71,7 @@ int process_request_key_err(long err_code)
* address; zero on error
* @length_size: The number of bytes occupied by the encoded length
*
- * Returns Zero on success
+ * Returns zero on success; non-zero on error
*/
static int parse_packet_length(unsigned char *data, size_t *size,
size_t *length_size)
@@ -106,11 +106,11 @@ out:
/**
* write_packet_length
- * @dest: The byte array target into which to write the
- * length. Must have at least 5 bytes allocated.
+ * @dest: The byte array target into which to write the length. Must
+ * have at least 5 bytes allocated.
* @size: The length to write.
- * @packet_size_length: The number of bytes used to encode the
- * packet length is written to this address.
+ * @packet_size_length: The number of bytes used to encode the packet
+ * length is written to this address.
*
* Returns zero on success; non-zero on error.
*/
@@ -396,26 +396,53 @@ out:
return rc;
}
+static int
+ecryptfs_get_auth_tok_sig(char **sig, struct ecryptfs_auth_tok *auth_tok)
+{
+ int rc = 0;
+
+ (*sig) = NULL;
+ switch (auth_tok->token_type) {
+ case ECRYPTFS_PASSWORD:
+ (*sig) = auth_tok->token.password.signature;
+ break;
+ case ECRYPTFS_PRIVATE_KEY:
+ (*sig) = auth_tok->token.private_key.signature;
+ break;
+ default:
+ printk(KERN_ERR "Cannot get sig for auth_tok of type [%d]\n",
+ auth_tok->token_type);
+ rc = -EINVAL;
+ }
+ return rc;
+}
+
/**
- * decrypt_pki_encrypted_session_key - Decrypt the session key with
- * the given auth_tok.
+ * decrypt_pki_encrypted_session_key - Decrypt the session key with the given auth_tok.
+ * @auth_tok: The key authentication token used to decrypt the session key
+ * @crypt_stat: The cryptographic context
*
- * Returns Zero on success; non-zero error otherwise.
+ * Returns zero on success; non-zero error otherwise.
*/
-static int decrypt_pki_encrypted_session_key(
- struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
- struct ecryptfs_auth_tok *auth_tok,
- struct ecryptfs_crypt_stat *crypt_stat)
+static int
+decrypt_pki_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,
+ struct ecryptfs_crypt_stat *crypt_stat)
{
u16 cipher_code = 0;
struct ecryptfs_msg_ctx *msg_ctx;
struct ecryptfs_message *msg = NULL;
+ char *auth_tok_sig;
char *netlink_message;
size_t netlink_message_length;
int rc;
- rc = write_tag_64_packet(mount_crypt_stat->global_auth_tok_sig,
- &(auth_tok->session_key),
+ rc = ecryptfs_get_auth_tok_sig(&auth_tok_sig, auth_tok);
+ if (rc) {
+ printk(KERN_ERR "Unrecognized auth tok type: [%d]\n",
+ auth_tok->token_type);
+ goto out;
+ }
+ rc = write_tag_64_packet(auth_tok_sig, &(auth_tok->session_key),
&netlink_message, &netlink_message_length);
if (rc) {
ecryptfs_printk(KERN_ERR, "Failed to write tag 64 packet");
@@ -465,40 +492,33 @@ out:
static void wipe_auth_tok_list(struct list_head *auth_tok_list_head)
{
- struct list_head *walker;
struct ecryptfs_auth_tok_list_item *auth_tok_list_item;
+ struct ecryptfs_auth_tok_list_item *auth_tok_list_item_tmp;
- walker = auth_tok_list_head->next;
- while (walker != auth_tok_list_head) {
- auth_tok_list_item =
- list_entry(walker, struct ecryptfs_auth_tok_list_item,
- list);
- walker = auth_tok_list_item->list.next;
- memset(auth_tok_list_item, 0,
- sizeof(struct ecryptfs_auth_tok_list_item));
+ list_for_each_entry_safe(auth_tok_list_item, auth_tok_list_item_tmp,
+ auth_tok_list_head, list) {
+ list_del(&auth_tok_list_item->list);
kmem_cache_free(ecryptfs_auth_tok_list_item_cache,
auth_tok_list_item);
}
- auth_tok_list_head->next = NULL;
}
struct kmem_cache *ecryptfs_auth_tok_list_item_cache;
-
/**
* parse_tag_1_packet
- * @crypt_stat: The cryptographic context to modify based on packet
- * contents.
+ * @crypt_stat: The cryptographic context to modify based on packet contents
* @data: The raw bytes of the packet.
* @auth_tok_list: eCryptfs parses packets into authentication tokens;
- * a new authentication token will be placed at the end
- * of this list for this packet.
+ * a new authentication token will be placed at the
+ * end of this list for this packet.
* @new_auth_tok: Pointer to a pointer to memory that this function
* allocates; sets the memory address of the pointer to
* NULL on error. This object is added to the
* auth_tok_list.
* @packet_size: This function writes the size of the parsed packet
* into this memory location; zero on error.
+ * @max_packet_size: The maximum allowable packet size
*
* Returns zero on success; non-zero on error.
*/
@@ -515,72 +535,65 @@ parse_tag_1_packet(struct ecryptfs_crypt_stat *crypt_stat,
(*packet_size) = 0;
(*new_auth_tok) = NULL;
-
- /* we check that:
- * one byte for the Tag 1 ID flag
- * two bytes for the body size
- * do not exceed the maximum_packet_size
+ /**
+ * This format is inspired by OpenPGP; see RFC 2440
+ * packet tag 1
+ *
+ * Tag 1 identifier (1 byte)
+ * Max Tag 1 packet size (max 3 bytes)
+ * Version (1 byte)
+ * Key identifier (8 bytes; ECRYPTFS_SIG_SIZE)
+ * Cipher identifier (1 byte)
+ * Encrypted key size (arbitrary)
+ *
+ * 12 bytes minimum packet size
*/
- if (unlikely((*packet_size) + 3 > max_packet_size)) {
- ecryptfs_printk(KERN_ERR, "Packet size exceeds max\n");
+ if (unlikely(max_packet_size < 12)) {
+ printk(KERN_ERR "Invalid max packet size; must be >=12\n");
rc = -EINVAL;
goto out;
}
- /* check for Tag 1 identifier - one byte */
if (data[(*packet_size)++] != ECRYPTFS_TAG_1_PACKET_TYPE) {
- ecryptfs_printk(KERN_ERR, "Enter w/ first byte != 0x%.2x\n",
- ECRYPTFS_TAG_1_PACKET_TYPE);
+ printk(KERN_ERR "Enter w/ first byte != 0x%.2x\n",
+ ECRYPTFS_TAG_1_PACKET_TYPE);
rc = -EINVAL;
goto out;
}
/* Released: wipe_auth_tok_list called in ecryptfs_parse_packet_set or
* at end of function upon failure */
auth_tok_list_item =
- kmem_cache_alloc(ecryptfs_auth_tok_list_item_cache,
- GFP_KERNEL);
+ kmem_cache_zalloc(ecryptfs_auth_tok_list_item_cache,
+ GFP_KERNEL);
if (!auth_tok_list_item) {
- ecryptfs_printk(KERN_ERR, "Unable to allocate memory\n");
+ printk(KERN_ERR "Unable to allocate memory\n");
rc = -ENOMEM;
goto out;
}
- memset(auth_tok_list_item, 0,
- sizeof(struct ecryptfs_auth_tok_list_item));
(*new_auth_tok) = &auth_tok_list_item->auth_tok;
- /* check for body size - one to two bytes
- *
- * ***** TAG 1 Packet Format *****
- * | version number | 1 byte |
- * | key ID | 8 bytes |
- * | public key algorithm | 1 byte |
- * | encrypted session key | arbitrary |
- */
rc = parse_packet_length(&data[(*packet_size)], &body_size,
&length_size);
if (rc) {
- ecryptfs_printk(KERN_WARNING, "Error parsing packet length; "
- "rc = [%d]\n", rc);
+ printk(KERN_WARNING "Error parsing packet length; "
+ "rc = [%d]\n", rc);
goto out_free;
}
- if (unlikely(body_size < (0x02 + ECRYPTFS_SIG_SIZE))) {
- ecryptfs_printk(KERN_WARNING, "Invalid body size ([%d])\n",
- body_size);
+ if (unlikely(body_size < (ECRYPTFS_SIG_SIZE + 2))) {
+ printk(KERN_WARNING "Invalid body size ([%td])\n", body_size);
rc = -EINVAL;
goto out_free;
}
(*packet_size) += length_size;
if (unlikely((*packet_size) + body_size > max_packet_size)) {
- ecryptfs_printk(KERN_ERR, "Packet size exceeds max\n");
+ printk(KERN_WARNING "Packet size exceeds max\n");
rc = -EINVAL;
goto out_free;
}
- /* Version 3 (from RFC2440) - one byte */
if (unlikely(data[(*packet_size)++] != 0x03)) {
- ecryptfs_printk(KERN_DEBUG, "Unknown version number "
- "[%d]\n", data[(*packet_size) - 1]);
+ printk(KERN_WARNING "Unknown version number [%d]\n",
+ data[(*packet_size) - 1]);
rc = -EINVAL;
goto out_free;
}
- /* Read Signature */
ecryptfs_to_hex((*new_auth_tok)->token.private_key.signature,
&data[(*packet_size)], ECRYPTFS_SIG_SIZE);
*packet_size += ECRYPTFS_SIG_SIZE;
@@ -588,27 +601,23 @@ parse_tag_1_packet(struct ecryptfs_crypt_stat *crypt_stat,
* know which public key encryption algorithm was used */
(*packet_size)++;
(*new_auth_tok)->session_key.encrypted_key_size =
- body_size - (0x02 + ECRYPTFS_SIG_SIZE);
+ body_size - (ECRYPTFS_SIG_SIZE + 2);
if ((*new_auth_tok)->session_key.encrypted_key_size
> ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) {
- ecryptfs_printk(KERN_ERR, "Tag 1 packet contains key larger "
- "than ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES");
+ printk(KERN_WARNING "Tag 1 packet contains key larger "
+ "than ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES");
rc = -EINVAL;
goto out;
}
- ecryptfs_printk(KERN_DEBUG, "Encrypted key size = [%d]\n",
- (*new_auth_tok)->session_key.encrypted_key_size);
memcpy((*new_auth_tok)->session_key.encrypted_key,
- &data[(*packet_size)], (body_size - 0x02 - ECRYPTFS_SIG_SIZE));
+ &data[(*packet_size)], (body_size - (ECRYPTFS_SIG_SIZE + 2)));
(*packet_size) += (*new_auth_tok)->session_key.encrypted_key_size;
(*new_auth_tok)->session_key.flags &=
~ECRYPTFS_CONTAINS_DECRYPTED_KEY;
(*new_auth_tok)->session_key.flags |=
ECRYPTFS_CONTAINS_ENCRYPTED_KEY;
(*new_auth_tok)->token_type = ECRYPTFS_PRIVATE_KEY;
- (*new_auth_tok)->flags |= ECRYPTFS_PRIVATE_KEY;
- /* TODO: Why are we setting this flag here? Don't we want the
- * userspace to decrypt the session key? */
+ (*new_auth_tok)->flags = 0;
(*new_auth_tok)->session_key.flags &=
~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT);
(*new_auth_tok)->session_key.flags &=
@@ -658,22 +667,30 @@ parse_tag_3_packet(struct ecryptfs_crypt_stat *crypt_stat,
(*packet_size) = 0;
(*new_auth_tok) = NULL;
-
- /* we check that:
- * one byte for the Tag 3 ID flag
- * two bytes for the body size
- * do not exceed the maximum_packet_size
+ /**
+ *This format is inspired by OpenPGP; see RFC 2440
+ * packet tag 3
+ *
+ * Tag 3 identifier (1 byte)
+ * Max Tag 3 packet size (max 3 bytes)
+ * Version (1 byte)
+ * Cipher code (1 byte)
+ * S2K specifier (1 byte)
+ * Hash identifier (1 byte)
+ * Salt (ECRYPTFS_SALT_SIZE)
+ * Hash iterations (1 byte)
+ * Encrypted key (arbitrary)
+ *
+ * (ECRYPTFS_SALT_SIZE + 7) minimum packet size
*/
- if (unlikely((*packet_size) + 3 > max_packet_size)) {
- ecryptfs_printk(KERN_ERR, "Packet size exceeds max\n");
+ if (max_packet_size < (ECRYPTFS_SALT_SIZE + 7)) {
+ printk(KERN_ERR "Max packet size too large\n");
rc = -EINVAL;
goto out;
}
-
- /* check for Tag 3 identifyer - one byte */
if (data[(*packet_size)++] != ECRYPTFS_TAG_3_PACKET_TYPE) {
- ecryptfs_printk(KERN_ERR, "Enter w/ first byte != 0x%.2x\n",
- ECRYPTFS_TAG_3_PACKET_TYPE);
+ printk(KERN_ERR "First byte != 0x%.2x; invalid packet\n",
+ ECRYPTFS_TAG_3_PACKET_TYPE);
rc = -EINVAL;
goto out;
}
@@ -682,56 +699,37 @@ parse_tag_3_packet(struct ecryptfs_crypt_stat *crypt_stat,
auth_tok_list_item =
kmem_cache_zalloc(ecryptfs_auth_tok_list_item_cache, GFP_KERNEL);
if (!auth_tok_list_item) {
- ecryptfs_printk(KERN_ERR, "Unable to allocate memory\n");
+ printk(KERN_ERR "Unable to allocate memory\n");
rc = -ENOMEM;
goto out;
}
(*new_auth_tok) = &auth_tok_list_item->auth_tok;
-
- /* check for body size - one to two bytes */
rc = parse_packet_length(&data[(*packet_size)], &body_size,
&length_size);
if (rc) {
- ecryptfs_printk(KERN_WARNING, "Error parsing packet length; "
- "rc = [%d]\n", rc);
+ printk(KERN_WARNING "Error parsing packet length; rc = [%d]\n",
+ rc);
goto out_free;
}
- if (unlikely(body_size < (0x05 + ECRYPTFS_SALT_SIZE))) {
- ecryptfs_printk(KERN_WARNING, "Invalid body size ([%d])\n",
- body_size);
+ if (unlikely(body_size < (ECRYPTFS_SALT_SIZE + 5))) {
+ printk(KERN_WARNING "Invalid body size ([%td])\n", body_size);
rc = -EINVAL;
goto out_free;
}
(*packet_size) += length_size;
-
- /* now we know the length of the remainting Tag 3 packet size:
- * 5 fix bytes for: version string, cipher, S2K ID, hash algo,
- * number of hash iterations
- * ECRYPTFS_SALT_SIZE bytes for salt
- * body_size bytes minus the stuff above is the encrypted key size
- */
if (unlikely((*packet_size) + body_size > max_packet_size)) {
- ecryptfs_printk(KERN_ERR, "Packet size exceeds max\n");
+ printk(KERN_ERR "Packet size exceeds max\n");
rc = -EINVAL;
goto out_free;
}
-
- /* There are 5 characters of additional information in the
- * packet */
(*new_auth_tok)->session_key.encrypted_key_size =
- body_size - (0x05 + ECRYPTFS_SALT_SIZE);
- ecryptfs_printk(KERN_DEBUG, "Encrypted key size = [%d]\n",
- (*new_auth_tok)->session_key.encrypted_key_size);
-
- /* Version 4 (from RFC2440) - one byte */
+ (body_size - (ECRYPTFS_SALT_SIZE + 5));
if (unlikely(data[(*packet_size)++] != 0x04)) {
- ecryptfs_printk(KERN_DEBUG, "Unknown version number "
- "[%d]\n", data[(*packet_size) - 1]);
+ printk(KERN_WARNING "Unknown version number [%d]\n",
+ data[(*packet_size) - 1]);
rc = -EINVAL;
goto out_free;
}
-
- /* cipher - one byte */
ecryptfs_cipher_code_to_string(crypt_stat->cipher,
(u16)data[(*packet_size)]);
/* A little extra work to differentiate among the AES key
@@ -745,33 +743,26 @@ parse_tag_3_packet(struct ecryptfs_crypt_stat *crypt_stat,
(*new_auth_tok)->session_key.encrypted_key_size;
}
ecryptfs_init_crypt_ctx(crypt_stat);
- /* S2K identifier 3 (from RFC2440) */
if (unlikely(data[(*packet_size)++] != 0x03)) {
- ecryptfs_printk(KERN_ERR, "Only S2K ID 3 is currently "
- "supported\n");
+ printk(KERN_WARNING "Only S2K ID 3 is currently supported\n");
rc = -ENOSYS;
goto out_free;
}
-
/* TODO: finish the hash mapping */
- /* hash algorithm - one byte */
switch (data[(*packet_size)++]) {
case 0x01: /* See RFC2440 for these numbers and their mappings */
/* Choose MD5 */
- /* salt - ECRYPTFS_SALT_SIZE bytes */
memcpy((*new_auth_tok)->token.password.salt,
&data[(*packet_size)], ECRYPTFS_SALT_SIZE);
(*packet_size) += ECRYPTFS_SALT_SIZE;
-
/* This conversion was taken straight from RFC2440 */
- /* number of hash iterations - one byte */
(*new_auth_tok)->token.password.hash_iterations =
((u32) 16 + (data[(*packet_size)] & 15))
<< ((data[(*packet_size)] >> 4) + 6);
(*packet_size)++;
-
- /* encrypted session key -
- * (body_size-5-ECRYPTFS_SALT_SIZE) bytes */
+ /* Friendly reminder:
+ * (*new_auth_tok)->session_key.encrypted_key_size =
+ * (body_size - (ECRYPTFS_SALT_SIZE + 5)); */
memcpy((*new_auth_tok)->session_key.encrypted_key,
&data[(*packet_size)],
(*new_auth_tok)->session_key.encrypted_key_size);
@@ -781,7 +772,7 @@ parse_tag_3_packet(struct ecryptfs_crypt_stat *crypt_stat,
~ECRYPTFS_CONTAINS_DECRYPTED_KEY;
(*new_auth_tok)->session_key.flags |=
ECRYPTFS_CONTAINS_ENCRYPTED_KEY;
- (*new_auth_tok)->token.password.hash_algo = 0x01;
+ (*new_auth_tok)->token.password.hash_algo = 0x01; /* MD5 */
break;
default:
ecryptfs_printk(KERN_ERR, "Unsupported hash algorithm: "
@@ -837,82 +828,61 @@ parse_tag_11_packet(unsigned char *data, unsigned char *contents,
(*packet_size) = 0;
(*tag_11_contents_size) = 0;
-
- /* check that:
- * one byte for the Tag 11 ID flag
- * two bytes for the Tag 11 length
- * do not exceed the maximum_packet_size
+ /* This format is inspired by OpenPGP; see RFC 2440
+ * packet tag 11
+ *
+ * Tag 11 identifier (1 byte)
+ * Max Tag 11 packet size (max 3 bytes)
+ * Binary format specifier (1 byte)
+ * Filename length (1 byte)
+ * Filename ("_CONSOLE") (8 bytes)
+ * Modification date (4 bytes)
+ * Literal data (arbitrary)
+ *
+ * We need at least 16 bytes of data for the packet to even be
+ * valid.
*/
- if (unlikely((*packet_size) + 3 > max_packet_size)) {
- ecryptfs_printk(KERN_ERR, "Packet size exceeds max\n");
+ if (max_packet_size < 16) {
+ printk(KERN_ERR "Maximum packet size too small\n");
rc = -EINVAL;
goto out;
}
-
- /* check for Tag 11 identifyer - one byte */
if (data[(*packet_size)++] != ECRYPTFS_TAG_11_PACKET_TYPE) {
- ecryptfs_printk(KERN_WARNING,
- "Invalid tag 11 packet format\n");
+ printk(KERN_WARNING "Invalid tag 11 packet format\n");
rc = -EINVAL;
goto out;
}
-
- /* get Tag 11 content length - one or two bytes */
rc = parse_packet_length(&data[(*packet_size)], &body_size,
&length_size);
if (rc) {
- ecryptfs_printk(KERN_WARNING,
- "Invalid tag 11 packet format\n");
+ printk(KERN_WARNING "Invalid tag 11 packet format\n");
goto out;
}
- (*packet_size) += length_size;
-
- if (body_size < 13) {
- ecryptfs_printk(KERN_WARNING, "Invalid body size ([%d])\n",
- body_size);
+ if (body_size < 14) {
+ printk(KERN_WARNING "Invalid body size ([%td])\n", body_size);
rc = -EINVAL;
goto out;
}
- /* We have 13 bytes of surrounding packet values */
- (*tag_11_contents_size) = (body_size - 13);
-
- /* now we know the length of the remainting Tag 11 packet size:
- * 14 fix bytes for: special flag one, special flag two,
- * 12 skipped bytes
- * body_size bytes minus the stuff above is the Tag 11 content
- */
- /* FIXME why is the body size one byte smaller than the actual
- * size of the body?
- * this seems to be an error here as well as in
- * write_tag_11_packet() */
+ (*packet_size) += length_size;
+ (*tag_11_contents_size) = (body_size - 14);
if (unlikely((*packet_size) + body_size + 1 > max_packet_size)) {
- ecryptfs_printk(KERN_ERR, "Packet size exceeds max\n");
+ printk(KERN_ERR "Packet size exceeds max\n");
rc = -EINVAL;
goto out;
}
-
- /* special flag one - one byte */
if (data[(*packet_size)++] != 0x62) {
- ecryptfs_printk(KERN_WARNING, "Unrecognizable packet\n");
+ printk(KERN_WARNING "Unrecognizable packet\n");
rc = -EINVAL;
goto out;
}
-
- /* special flag two - one byte */
if (data[(*packet_size)++] != 0x08) {
- ecryptfs_printk(KERN_WARNING, "Unrecognizable packet\n");
+ printk(KERN_WARNING "Unrecognizable packet\n");
rc = -EINVAL;
goto out;
}
-
- /* skip the next 12 bytes */
- (*packet_size) += 12; /* We don't care about the filename or
- * the timestamp */
-
- /* get the Tag 11 contents - tag_11_contents_size bytes */
+ (*packet_size) += 12; /* Ignore filename and modification date */
memcpy(contents, &data[(*packet_size)], (*tag_11_contents_size));
(*packet_size) += (*tag_11_contents_size);
-
out:
if (rc) {
(*packet_size) = 0;
@@ -921,130 +891,232 @@ out:
return rc;
}
+static int
+ecryptfs_find_global_auth_tok_for_sig(
+ struct ecryptfs_global_auth_tok **global_auth_tok,
+ struct ecryptfs_mount_crypt_stat *mount_crypt_stat, char *sig)
+{
+ struct ecryptfs_global_auth_tok *walker;
+ int rc = 0;
+
+ (*global_auth_tok) = NULL;
+ mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex);
+ list_for_each_entry(walker,
+ &mount_crypt_stat->global_auth_tok_list,
+ mount_crypt_stat_list) {
+ if (memcmp(walker->sig, sig, ECRYPTFS_SIG_SIZE_HEX) == 0) {
+ (*global_auth_tok) = walker;
+ goto out;
+ }
+ }
+ rc = -EINVAL;
+out:
+ mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex);
+ return rc;
+}
+
/**
- * decrypt_session_key - Decrypt the session key with the given auth_tok.
+ * ecryptfs_verify_version
+ * @version: The version number to confirm
*
- * Returns Zero on success; non-zero error otherwise.
+ * Returns zero on good version; non-zero otherwise
*/
-static int decrypt_session_key(struct ecryptfs_auth_tok *auth_tok,
- struct ecryptfs_crypt_stat *crypt_stat)
+static int ecryptfs_verify_version(u16 version)
{
- struct ecryptfs_password *password_s_ptr;
- struct scatterlist src_sg[2], dst_sg[2];
- struct mutex *tfm_mutex = NULL;
- char *encrypted_session_key;
- char *session_key;
+ int rc = 0;
+ unsigned char major;
+ unsigned char minor;
+
+ major = ((version >> 8) & 0xFF);
+ minor = (version & 0xFF);
+ if (major != ECRYPTFS_VERSION_MAJOR) {
+ ecryptfs_printk(KERN_ERR, "Major version number mismatch. "
+ "Expected [%d]; got [%d]\n",
+ ECRYPTFS_VERSION_MAJOR, major);
+ rc = -EINVAL;
+ goto out;
+ }
+ if (minor != ECRYPTFS_VERSION_MINOR) {
+ ecryptfs_printk(KERN_ERR, "Minor version number mismatch. "
+ "Expected [%d]; got [%d]\n",
+ ECRYPTFS_VERSION_MINOR, minor);
+ rc = -EINVAL;
+ goto out;
+ }
+out:
+ return rc;
+}
+
+int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key,
+ struct ecryptfs_auth_tok **auth_tok,
+ char *sig)
+{
+ int rc = 0;
+
+ (*auth_tok_key) = request_key(&key_type_user, sig, NULL);
+ if (!(*auth_tok_key) || IS_ERR(*auth_tok_key)) {
+ printk(KERN_ERR "Could not find key with description: [%s]\n",
+ sig);
+ process_request_key_err(PTR_ERR(*auth_tok_key));
+ rc = -EINVAL;
+ goto out;
+ }
+ (*auth_tok) = ecryptfs_get_key_payload_data(*auth_tok_key);
+ if (ecryptfs_verify_version((*auth_tok)->version)) {
+ printk(KERN_ERR
+ "Data structure version mismatch. "
+ "Userspace tools must match eCryptfs "
+ "kernel module with major version [%d] "
+ "and minor version [%d]\n",
+ ECRYPTFS_VERSION_MAJOR,
+ ECRYPTFS_VERSION_MINOR);
+ rc = -EINVAL;
+ goto out;
+ }
+ if ((*auth_tok)->token_type != ECRYPTFS_PASSWORD
+ && (*auth_tok)->token_type != ECRYPTFS_PRIVATE_KEY) {
+ printk(KERN_ERR "Invalid auth_tok structure "
+ "returned from key query\n");
+ rc = -EINVAL;
+ goto out;
+ }
+out:
+ return rc;
+}
+
+/**
+ * ecryptfs_find_auth_tok_for_sig
+ * @auth_tok: Set to the matching auth_tok; NULL if not found
+ * @crypt_stat: inode crypt_stat crypto context
+ * @sig: Sig of auth_tok to find
+ *
+ * For now, this function simply looks at the registered auth_tok's
+ * linked off the mount_crypt_stat, so all the auth_toks that can be
+ * used must be registered at mount time. This function could
+ * potentially try a lot harder to find auth_tok's (e.g., by calling
+ * out to ecryptfsd to dynamically retrieve an auth_tok object) so
+ * that static registration of auth_tok's will no longer be necessary.
+ *
+ * Returns zero on no error; non-zero on error
+ */
+static int
+ecryptfs_find_auth_tok_for_sig(
+ struct ecryptfs_auth_tok **auth_tok,
+ struct ecryptfs_crypt_stat *crypt_stat, char *sig)
+{
+ struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
+ crypt_stat->mount_crypt_stat;
+ struct ecryptfs_global_auth_tok *global_auth_tok;
+ int rc = 0;
+
+ (*auth_tok) = NULL;
+ if (ecryptfs_find_global_auth_tok_for_sig(&global_auth_tok,
+ mount_crypt_stat, sig)) {
+ struct key *auth_tok_key;
+
+ rc = ecryptfs_keyring_auth_tok_for_sig(&auth_tok_key, auth_tok,
+ sig);
+ } else
+ (*auth_tok) = global_auth_tok->global_auth_tok;
+ return rc;
+}
+
+/**
+ * decrypt_passphrase_encrypted_session_key - Decrypt the session key with the given auth_tok.
+ * @auth_tok: The passphrase authentication token to use to encrypt the FEK
+ * @crypt_stat: The cryptographic context
+ *
+ * Returns zero on success; non-zero error otherwise
+ */
+static int
+decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,
+ struct ecryptfs_crypt_stat *crypt_stat)
+{
+ struct scatterlist dst_sg;
+ struct scatterlist src_sg;
+ struct mutex *tfm_mutex;
struct blkcipher_desc desc = {
.flags = CRYPTO_TFM_REQ_MAY_SLEEP
};
int rc = 0;
- password_s_ptr = &auth_tok->token.password;
- if (password_s_ptr->flags & ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET)
- ecryptfs_printk(KERN_DEBUG, "Session key encryption key "
- "set; skipping key generation\n");
- ecryptfs_printk(KERN_DEBUG, "Session key encryption key (size [%d])"
- ":\n",
- password_s_ptr->session_key_encryption_key_bytes);
- if (ecryptfs_verbosity > 0)
- ecryptfs_dump_hex(password_s_ptr->session_key_encryption_key,
- password_s_ptr->
- session_key_encryption_key_bytes);
- if (!strcmp(crypt_stat->cipher,
- crypt_stat->mount_crypt_stat->global_default_cipher_name)
- && crypt_stat->mount_crypt_stat->global_key_tfm) {
- desc.tfm = crypt_stat->mount_crypt_stat->global_key_tfm;
- tfm_mutex = &crypt_stat->mount_crypt_stat->global_key_tfm_mutex;
- } else {
- char *full_alg_name;
+ sg_init_table(&dst_sg, 1);
+ sg_init_table(&src_sg, 1);
- rc = ecryptfs_crypto_api_algify_cipher_name(&full_alg_name,
- crypt_stat->cipher,
- "ecb");
- if (rc)
- goto out;
- desc.tfm = crypto_alloc_blkcipher(full_alg_name, 0,
- CRYPTO_ALG_ASYNC);
- kfree(full_alg_name);
- if (IS_ERR(desc.tfm)) {
- rc = PTR_ERR(desc.tfm);
- printk(KERN_ERR "Error allocating crypto context; "
- "rc = [%d]\n", rc);
- goto out;
- }
- crypto_blkcipher_set_flags(desc.tfm, CRYPTO_TFM_REQ_WEAK_KEY);
+ if (unlikely(ecryptfs_verbosity > 0)) {
+ ecryptfs_printk(
+ KERN_DEBUG, "Session key encryption key (size [%d]):\n",
+ auth_tok->token.password.session_key_encryption_key_bytes);
+ ecryptfs_dump_hex(
+ auth_tok->token.password.session_key_encryption_key,
+ auth_tok->token.password.session_key_encryption_key_bytes);
+ }
+ rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(&desc.tfm, &tfm_mutex,
+ crypt_stat->cipher);
+ if (unlikely(rc)) {
+ printk(KERN_ERR "Internal error whilst attempting to get "
+ "tfm and mutex for cipher name [%s]; rc = [%d]\n",
+ crypt_stat->cipher, rc);
+ goto out;
}
- if (tfm_mutex)
- mutex_lock(tfm_mutex);
- rc = crypto_blkcipher_setkey(desc.tfm,
- password_s_ptr->session_key_encryption_key,
- crypt_stat->key_size);
- if (rc < 0) {
+ rc = virt_to_scatterlist(auth_tok->session_key.encrypted_key,
+ auth_tok->session_key.encrypted_key_size,
+ &src_sg, 1);
+ if (rc != 1) {
+ printk(KERN_ERR "Internal error whilst attempting to convert "
+ "auth_tok->session_key.encrypted_key to scatterlist; "
+ "expected rc = 1; got rc = [%d]. "
+ "auth_tok->session_key.encrypted_key_size = [%d]\n", rc,
+ auth_tok->session_key.encrypted_key_size);
+ goto out;
+ }
+ auth_tok->session_key.decrypted_key_size =
+ auth_tok->session_key.encrypted_key_size;
+ rc = virt_to_scatterlist(auth_tok->session_key.decrypted_key,
+ auth_tok->session_key.decrypted_key_size,
+ &dst_sg, 1);
+ if (rc != 1) {
+ printk(KERN_ERR "Internal error whilst attempting to convert "
+ "auth_tok->session_key.decrypted_key to scatterlist; "
+ "expected rc = 1; got rc = [%d]\n", rc);
+ goto out;
+ }
+ mutex_lock(tfm_mutex);
+ rc = crypto_blkcipher_setkey(
+ desc.tfm, auth_tok->token.password.session_key_encryption_key,
+ crypt_stat->key_size);
+ if (unlikely(rc < 0)) {
+ mutex_unlock(tfm_mutex);
printk(KERN_ERR "Error setting key for crypto context\n");
rc = -EINVAL;
- goto out_free_tfm;
- }
- /* TODO: virt_to_scatterlist */
- encrypted_session_key = (char *)__get_free_page(GFP_KERNEL);
- if (!encrypted_session_key) {
- ecryptfs_printk(KERN_ERR, "Out of memory\n");
- rc = -ENOMEM;
- goto out_free_tfm;
+ goto out;
}
- session_key = (char *)__get_free_page(GFP_KERNEL);
- if (!session_key) {
- kfree(encrypted_session_key);
- ecryptfs_printk(KERN_ERR, "Out of memory\n");
- rc = -ENOMEM;
- goto out_free_tfm;
- }
- memcpy(encrypted_session_key, auth_tok->session_key.encrypted_key,
- auth_tok->session_key.encrypted_key_size);
- src_sg[0].page = virt_to_page(encrypted_session_key);
- src_sg[0].offset = 0;
- BUG_ON(auth_tok->session_key.encrypted_key_size > PAGE_CACHE_SIZE);
- src_sg[0].length = auth_tok->session_key.encrypted_key_size;
- dst_sg[0].page = virt_to_page(session_key);
- dst_sg[0].offset = 0;
- auth_tok->session_key.decrypted_key_size =
- auth_tok->session_key.encrypted_key_size;
- dst_sg[0].length = auth_tok->session_key.encrypted_key_size;
- rc = crypto_blkcipher_decrypt(&desc, dst_sg, src_sg,
+ rc = crypto_blkcipher_decrypt(&desc, &dst_sg, &src_sg,
auth_tok->session_key.encrypted_key_size);
- if (rc) {
+ mutex_unlock(tfm_mutex);
+ if (unlikely(rc)) {
printk(KERN_ERR "Error decrypting; rc = [%d]\n", rc);
- goto out_free_memory;
+ goto out;
}
- auth_tok->session_key.decrypted_key_size =
- auth_tok->session_key.encrypted_key_size;
- memcpy(auth_tok->session_key.decrypted_key, session_key,
- auth_tok->session_key.decrypted_key_size);
auth_tok->session_key.flags |= ECRYPTFS_CONTAINS_DECRYPTED_KEY;
memcpy(crypt_stat->key, auth_tok->session_key.decrypted_key,
auth_tok->session_key.decrypted_key_size);
crypt_stat->flags |= ECRYPTFS_KEY_VALID;
- ecryptfs_printk(KERN_DEBUG, "Decrypted session key:\n");
- if (ecryptfs_verbosity > 0)
+ if (unlikely(ecryptfs_verbosity > 0)) {
+ ecryptfs_printk(KERN_DEBUG, "FEK of size [%d]:\n",
+ crypt_stat->key_size);
ecryptfs_dump_hex(crypt_stat->key,
crypt_stat->key_size);
-out_free_memory:
- memset(encrypted_session_key, 0, PAGE_CACHE_SIZE);
- free_page((unsigned long)encrypted_session_key);
- memset(session_key, 0, PAGE_CACHE_SIZE);
- free_page((unsigned long)session_key);
-out_free_tfm:
- if (tfm_mutex)
- mutex_unlock(tfm_mutex);
- else
- crypto_free_blkcipher(desc.tfm);
+ }
out:
return rc;
}
/**
* ecryptfs_parse_packet_set
- * @dest: The header page in memory
- * @version: Version of file format, to guide parsing behavior
+ * @crypt_stat: The cryptographic context
+ * @src: Virtual address of region of memory containing the packets
+ * @ecryptfs_dentry: The eCryptfs dentry associated with the packet set
*
* Get crypt_stat to have the file's session key if the requisite key
* is available to decrypt the session key.
@@ -1058,25 +1130,22 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat,
struct dentry *ecryptfs_dentry)
{
size_t i = 0;
- size_t found_auth_tok = 0;
+ size_t found_auth_tok;
size_t next_packet_is_auth_tok_packet;
- char sig[ECRYPTFS_SIG_SIZE_HEX];
struct list_head auth_tok_list;
- struct list_head *walker;
- struct ecryptfs_auth_tok *chosen_auth_tok = NULL;
- struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
- &ecryptfs_superblock_to_private(
- ecryptfs_dentry->d_sb)->mount_crypt_stat;
- struct ecryptfs_auth_tok *candidate_auth_tok = NULL;
+ struct ecryptfs_auth_tok *matching_auth_tok;
+ struct ecryptfs_auth_tok *candidate_auth_tok;
+ char *candidate_auth_tok_sig;
size_t packet_size;
struct ecryptfs_auth_tok *new_auth_tok;
unsigned char sig_tmp_space[ECRYPTFS_SIG_SIZE];
+ struct ecryptfs_auth_tok_list_item *auth_tok_list_item;
size_t tag_11_contents_size;
size_t tag_11_packet_size;
int rc = 0;
INIT_LIST_HEAD(&auth_tok_list);
- /* Parse the header to find as many packets as we can, these will be
+ /* Parse the header to find as many packets as we can; these will be
* added the our &auth_tok_list */
next_packet_is_auth_tok_packet = 1;
while (next_packet_is_auth_tok_packet) {
@@ -1155,73 +1224,85 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat,
}
}
if (list_empty(&auth_tok_list)) {
- rc = -EINVAL; /* Do not support non-encrypted files in
- * the 0.1 release */
+ printk(KERN_ERR "The lower file appears to be a non-encrypted "
+ "eCryptfs file; this is not supported in this version "
+ "of the eCryptfs kernel module\n");
+ rc = -EINVAL;
goto out;
}
- /* If we have a global auth tok, then we should try to use
- * it */
- if (mount_crypt_stat->global_auth_tok) {
- memcpy(sig, mount_crypt_stat->global_auth_tok_sig,
- ECRYPTFS_SIG_SIZE_HEX);
- chosen_auth_tok = mount_crypt_stat->global_auth_tok;
- } else
- BUG(); /* We should always have a global auth tok in
- * the 0.1 release */
- /* Scan list to see if our chosen_auth_tok works */
- list_for_each(walker, &auth_tok_list) {
- struct ecryptfs_auth_tok_list_item *auth_tok_list_item;
- auth_tok_list_item =
- list_entry(walker, struct ecryptfs_auth_tok_list_item,
- list);
+ /* auth_tok_list contains the set of authentication tokens
+ * parsed from the metadata. We need to find a matching
+ * authentication token that has the secret component(s)
+ * necessary to decrypt the EFEK in the auth_tok parsed from
+ * the metadata. There may be several potential matches, but
+ * just one will be sufficient to decrypt to get the FEK. */
+find_next_matching_auth_tok:
+ found_auth_tok = 0;
+ list_for_each_entry(auth_tok_list_item, &auth_tok_list, list) {
candidate_auth_tok = &auth_tok_list_item->auth_tok;
if (unlikely(ecryptfs_verbosity > 0)) {
ecryptfs_printk(KERN_DEBUG,
"Considering cadidate auth tok:\n");
ecryptfs_dump_auth_tok(candidate_auth_tok);
}
- /* TODO: Replace ECRYPTFS_SIG_SIZE_HEX w/ dynamic value */
- if (candidate_auth_tok->token_type == ECRYPTFS_PASSWORD
- && !strncmp(candidate_auth_tok->token.password.signature,
- sig, ECRYPTFS_SIG_SIZE_HEX)) {
- found_auth_tok = 1;
- goto leave_list;
- /* TODO: Transfer the common salt into the
- * crypt_stat salt */
- } else if ((candidate_auth_tok->token_type
- == ECRYPTFS_PRIVATE_KEY)
- && !strncmp(candidate_auth_tok->token.private_key.signature,
- sig, ECRYPTFS_SIG_SIZE_HEX)) {
+ rc = ecryptfs_get_auth_tok_sig(&candidate_auth_tok_sig,
+ candidate_auth_tok);
+ if (rc) {
+ printk(KERN_ERR
+ "Unrecognized candidate auth tok type: [%d]\n",
+ candidate_auth_tok->token_type);
+ rc = -EINVAL;
+ goto out_wipe_list;
+ }
+ ecryptfs_find_auth_tok_for_sig(&matching_auth_tok, crypt_stat,
+ candidate_auth_tok_sig);
+ if (matching_auth_tok) {
found_auth_tok = 1;
- goto leave_list;
+ goto found_matching_auth_tok;
}
}
if (!found_auth_tok) {
- ecryptfs_printk(KERN_ERR, "Could not find authentication "
- "token on temporary list for sig [%.*s]\n",
- ECRYPTFS_SIG_SIZE_HEX, sig);
+ ecryptfs_printk(KERN_ERR, "Could not find a usable "
+ "authentication token\n");
rc = -EIO;
goto out_wipe_list;
}
-leave_list:
- rc = -ENOTSUPP;
+found_matching_auth_tok:
if (candidate_auth_tok->token_type == ECRYPTFS_PRIVATE_KEY) {
memcpy(&(candidate_auth_tok->token.private_key),
- &(chosen_auth_tok->token.private_key),
+ &(matching_auth_tok->token.private_key),
sizeof(struct ecryptfs_private_key));
- rc = decrypt_pki_encrypted_session_key(mount_crypt_stat,
- candidate_auth_tok,
+ rc = decrypt_pki_encrypted_session_key(candidate_auth_tok,
crypt_stat);
} else if (candidate_auth_tok->token_type == ECRYPTFS_PASSWORD) {
memcpy(&(candidate_auth_tok->token.password),
- &(chosen_auth_tok->token.password),
+ &(matching_auth_tok->token.password),
sizeof(struct ecryptfs_password));
- rc = decrypt_session_key(candidate_auth_tok, crypt_stat);
+ rc = decrypt_passphrase_encrypted_session_key(
+ candidate_auth_tok, crypt_stat);
}
if (rc) {
- ecryptfs_printk(KERN_ERR, "Error decrypting the "
- "session key; rc = [%d]\n", rc);
- goto out_wipe_list;
+ struct ecryptfs_auth_tok_list_item *auth_tok_list_item_tmp;
+
+ ecryptfs_printk(KERN_WARNING, "Error decrypting the "
+ "session key for authentication token with sig "
+ "[%.*s]; rc = [%d]. Removing auth tok "
+ "candidate from the list and searching for "
+ "the next match.\n", candidate_auth_tok_sig,
+ ECRYPTFS_SIG_SIZE_HEX, rc);
+ list_for_each_entry_safe(auth_tok_list_item,
+ auth_tok_list_item_tmp,
+ &auth_tok_list, list) {
+ if (candidate_auth_tok
+ == &auth_tok_list_item->auth_tok) {
+ list_del(&auth_tok_list_item->list);
+ kmem_cache_free(
+ ecryptfs_auth_tok_list_item_cache,
+ auth_tok_list_item);
+ goto find_next_matching_auth_tok;
+ }
+ }
+ BUG();
}
rc = ecryptfs_compute_root_iv(crypt_stat);
if (rc) {
@@ -1240,6 +1321,7 @@ out_wipe_list:
out:
return rc;
}
+
static int
pki_encrypt_session_key(struct ecryptfs_auth_tok *auth_tok,
struct ecryptfs_crypt_stat *crypt_stat,
@@ -1284,22 +1366,25 @@ out:
/**
* write_tag_1_packet - Write an RFC2440-compatible tag 1 (public key) packet
* @dest: Buffer into which to write the packet
- * @max: Maximum number of bytes that can be writtn
+ * @remaining_bytes: Maximum number of bytes that can be writtn
+ * @auth_tok: The authentication token used for generating the tag 1 packet
+ * @crypt_stat: The cryptographic context
+ * @key_rec: The key record struct for the tag 1 packet
* @packet_size: This function will write the number of bytes that end
* up constituting the packet; set to zero on error
*
* Returns zero on success; non-zero on error.
*/
static int
-write_tag_1_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok,
+write_tag_1_packet(char *dest, size_t *remaining_bytes,
+ struct ecryptfs_auth_tok *auth_tok,
struct ecryptfs_crypt_stat *crypt_stat,
- struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
struct ecryptfs_key_record *key_rec, size_t *packet_size)
{
size_t i;
size_t encrypted_session_key_valid = 0;
- size_t key_rec_size;
size_t packet_size_length;
+ size_t max_packet_size;
int rc = 0;
(*packet_size) = 0;
@@ -1329,37 +1414,23 @@ write_tag_1_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok,
ecryptfs_dump_hex(key_rec->enc_key, key_rec->enc_key_size);
}
encrypted_session_key_set:
- /* Now we have a valid key_rec. Append it to the
- * key_rec set. */
- key_rec_size = (sizeof(struct ecryptfs_key_record)
- - ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES
- + (key_rec->enc_key_size));
- /* TODO: Include a packet size limit as a parameter to this
- * function once we have multi-packet headers (for versions
- * later than 0.1 */
- if (key_rec_size >= ECRYPTFS_MAX_KEYSET_SIZE) {
- ecryptfs_printk(KERN_ERR, "Keyset too large\n");
- rc = -EINVAL;
- goto out;
- }
- /* ***** TAG 1 Packet Format *****
- * | version number | 1 byte |
- * | key ID | 8 bytes |
- * | public key algorithm | 1 byte |
- * | encrypted session key | arbitrary |
- */
- if ((0x02 + ECRYPTFS_SIG_SIZE + key_rec->enc_key_size) >= max) {
- ecryptfs_printk(KERN_ERR,
- "Authentication token is too large\n");
+ /* This format is inspired by OpenPGP; see RFC 2440
+ * packet tag 1 */
+ max_packet_size = (1 /* Tag 1 identifier */
+ + 3 /* Max Tag 1 packet size */
+ + 1 /* Version */
+ + ECRYPTFS_SIG_SIZE /* Key identifier */
+ + 1 /* Cipher identifier */
+ + key_rec->enc_key_size); /* Encrypted key size */
+ if (max_packet_size > (*remaining_bytes)) {
+ printk(KERN_ERR "Packet length larger than maximum allowable; "
+ "need up to [%td] bytes, but there are only [%td] "
+ "available\n", max_packet_size, (*remaining_bytes));
rc = -EINVAL;
goto out;
}
dest[(*packet_size)++] = ECRYPTFS_TAG_1_PACKET_TYPE;
- /* This format is inspired by OpenPGP; see RFC 2440
- * packet tag 1 */
- rc = write_packet_length(&dest[(*packet_size)],
- (0x02 + ECRYPTFS_SIG_SIZE +
- key_rec->enc_key_size),
+ rc = write_packet_length(&dest[(*packet_size)], (max_packet_size - 4),
&packet_size_length);
if (rc) {
ecryptfs_printk(KERN_ERR, "Error generating tag 1 packet "
@@ -1377,13 +1448,15 @@ encrypted_session_key_set:
out:
if (rc)
(*packet_size) = 0;
+ else
+ (*remaining_bytes) -= (*packet_size);
return rc;
}
/**
* write_tag_11_packet
* @dest: Target into which Tag 11 packet is to be written
- * @max: Maximum packet length
+ * @remaining_bytes: Maximum packet length
* @contents: Byte array of contents to copy in
* @contents_length: Number of bytes in contents
* @packet_length: Length of the Tag 11 packet written; zero on error
@@ -1391,54 +1464,59 @@ out:
* Returns zero on success; non-zero on error.
*/
static int
-write_tag_11_packet(char *dest, int max, char *contents, size_t contents_length,
- size_t *packet_length)
+write_tag_11_packet(char *dest, size_t *remaining_bytes, char *contents,
+ size_t contents_length, size_t *packet_length)
{
size_t packet_size_length;
+ size_t max_packet_size;
int rc = 0;
(*packet_length) = 0;
- if ((13 + contents_length) > max) {
+ /* This format is inspired by OpenPGP; see RFC 2440
+ * packet tag 11 */
+ max_packet_size = (1 /* Tag 11 identifier */
+ + 3 /* Max Tag 11 packet size */
+ + 1 /* Binary format specifier */
+ + 1 /* Filename length */
+ + 8 /* Filename ("_CONSOLE") */
+ + 4 /* Modification date */
+ + contents_length); /* Literal data */
+ if (max_packet_size > (*remaining_bytes)) {
+ printk(KERN_ERR "Packet length larger than maximum allowable; "
+ "need up to [%td] bytes, but there are only [%td] "
+ "available\n", max_packet_size, (*remaining_bytes));
rc = -EINVAL;
- ecryptfs_printk(KERN_ERR, "Packet length larger than "
- "maximum allowable\n");
goto out;
}
- /* General packet header */
- /* Packet tag */
dest[(*packet_length)++] = ECRYPTFS_TAG_11_PACKET_TYPE;
- /* Packet length */
rc = write_packet_length(&dest[(*packet_length)],
- (13 + contents_length), &packet_size_length);
+ (max_packet_size - 4), &packet_size_length);
if (rc) {
- ecryptfs_printk(KERN_ERR, "Error generating tag 11 packet "
- "header; cannot generate packet length\n");
+ printk(KERN_ERR "Error generating tag 11 packet header; cannot "
+ "generate packet length. rc = [%d]\n", rc);
goto out;
}
(*packet_length) += packet_size_length;
- /* Tag 11 specific */
- /* One-octet field that describes how the data is formatted */
- dest[(*packet_length)++] = 0x62; /* binary data */
- /* One-octet filename length followed by filename */
+ dest[(*packet_length)++] = 0x62; /* binary data format specifier */
dest[(*packet_length)++] = 8;
memcpy(&dest[(*packet_length)], "_CONSOLE", 8);
(*packet_length) += 8;
- /* Four-octet number indicating modification date */
memset(&dest[(*packet_length)], 0x00, 4);
(*packet_length) += 4;
- /* Remainder is literal data */
memcpy(&dest[(*packet_length)], contents, contents_length);
(*packet_length) += contents_length;
out:
if (rc)
(*packet_length) = 0;
+ else
+ (*remaining_bytes) -= (*packet_length);
return rc;
}
/**
* write_tag_3_packet
* @dest: Buffer into which to write the packet
- * @max: Maximum number of bytes that can be written
+ * @remaining_bytes: Maximum number of bytes that can be written
* @auth_tok: Authentication token
* @crypt_stat: The cryptographic context
* @key_rec: encrypted key
@@ -1448,19 +1526,22 @@ write_tag_11_packet(char *dest, int max, char *contents, size_t contents_length,
* Returns zero on success; non-zero on error.
*/
static int
-write_tag_3_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok,
+write_tag_3_packet(char *dest, size_t *remaining_bytes,
+ struct ecryptfs_auth_tok *auth_tok,
struct ecryptfs_crypt_stat *crypt_stat,
struct ecryptfs_key_record *key_rec, size_t *packet_size)
{
size_t i;
size_t encrypted_session_key_valid = 0;
char session_key_encryption_key[ECRYPTFS_MAX_KEY_BYTES];
- struct scatterlist dest_sg[2];
- struct scatterlist src_sg[2];
+ struct scatterlist dst_sg;
+ struct scatterlist src_sg;
struct mutex *tfm_mutex = NULL;
- size_t key_rec_size;
- size_t packet_size_length;
size_t cipher_code;
+ size_t packet_size_length;
+ size_t max_packet_size;
+ struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
+ crypt_stat->mount_crypt_stat;
struct blkcipher_desc desc = {
.tfm = NULL,
.flags = CRYPTO_TFM_REQ_MAY_SLEEP
@@ -1470,16 +1551,25 @@ write_tag_3_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok,
(*packet_size) = 0;
ecryptfs_from_hex(key_rec->sig, auth_tok->token.password.signature,
ECRYPTFS_SIG_SIZE);
- encrypted_session_key_valid = 0;
- for (i = 0; i < crypt_stat->key_size; i++)
- encrypted_session_key_valid |=
- auth_tok->session_key.encrypted_key[i];
- if (encrypted_session_key_valid) {
- memcpy(key_rec->enc_key,
- auth_tok->session_key.encrypted_key,
- auth_tok->session_key.encrypted_key_size);
- goto encrypted_session_key_set;
+ rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(&desc.tfm, &tfm_mutex,
+ crypt_stat->cipher);
+ if (unlikely(rc)) {
+ printk(KERN_ERR "Internal error whilst attempting to get "
+ "tfm and mutex for cipher name [%s]; rc = [%d]\n",
+ crypt_stat->cipher, rc);
+ goto out;
}
+ if (mount_crypt_stat->global_default_cipher_key_size == 0) {
+ struct blkcipher_alg *alg = crypto_blkcipher_alg(desc.tfm);
+
+ printk(KERN_WARNING "No key size specified at mount; "
+ "defaulting to [%d]\n", alg->max_keysize);
+ mount_crypt_stat->global_default_cipher_key_size =
+ alg->max_keysize;
+ }
+ if (crypt_stat->key_size == 0)
+ crypt_stat->key_size =
+ mount_crypt_stat->global_default_cipher_key_size;
if (auth_tok->session_key.encrypted_key_size == 0)
auth_tok->session_key.encrypted_key_size =
crypt_stat->key_size;
@@ -1487,9 +1577,24 @@ write_tag_3_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok,
&& strcmp("aes", crypt_stat->cipher) == 0) {
memset((crypt_stat->key + 24), 0, 8);
auth_tok->session_key.encrypted_key_size = 32;
- }
+ } else
+ auth_tok->session_key.encrypted_key_size = crypt_stat->key_size;
key_rec->enc_key_size =
auth_tok->session_key.encrypted_key_size;
+ encrypted_session_key_valid = 0;
+ for (i = 0; i < auth_tok->session_key.encrypted_key_size; i++)
+ encrypted_session_key_valid |=
+ auth_tok->session_key.encrypted_key[i];
+ if (encrypted_session_key_valid) {
+ ecryptfs_printk(KERN_DEBUG, "encrypted_session_key_valid != 0; "
+ "using auth_tok->session_key.encrypted_key, "
+ "where key_rec->enc_key_size = [%d]\n",
+ key_rec->enc_key_size);
+ memcpy(key_rec->enc_key,
+ auth_tok->session_key.encrypted_key,
+ key_rec->enc_key_size);
+ goto encrypted_session_key_set;
+ }
if (auth_tok->token.password.flags &
ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET) {
ecryptfs_printk(KERN_DEBUG, "Using previously generated "
@@ -1508,54 +1613,32 @@ write_tag_3_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok,
ecryptfs_printk(KERN_DEBUG, "Session key encryption key:\n");
ecryptfs_dump_hex(session_key_encryption_key, 16);
}
- rc = virt_to_scatterlist(crypt_stat->key,
- key_rec->enc_key_size, src_sg, 2);
- if (!rc) {
+ rc = virt_to_scatterlist(crypt_stat->key, key_rec->enc_key_size,
+ &src_sg, 1);
+ if (rc != 1) {
ecryptfs_printk(KERN_ERR, "Error generating scatterlist "
- "for crypt_stat session key\n");
+ "for crypt_stat session key; expected rc = 1; "
+ "got rc = [%d]. key_rec->enc_key_size = [%d]\n",
+ rc, key_rec->enc_key_size);
rc = -ENOMEM;
goto out;
}
- rc = virt_to_scatterlist(key_rec->enc_key,
- key_rec->enc_key_size, dest_sg, 2);
- if (!rc) {
+ rc = virt_to_scatterlist(key_rec->enc_key, key_rec->enc_key_size,
+ &dst_sg, 1);
+ if (rc != 1) {
ecryptfs_printk(KERN_ERR, "Error generating scatterlist "
- "for crypt_stat encrypted session key\n");
+ "for crypt_stat encrypted session key; "
+ "expected rc = 1; got rc = [%d]. "
+ "key_rec->enc_key_size = [%d]\n", rc,
+ key_rec->enc_key_size);
rc = -ENOMEM;
goto out;
}
- if (!strcmp(crypt_stat->cipher,
- crypt_stat->mount_crypt_stat->global_default_cipher_name)
- && crypt_stat->mount_crypt_stat->global_key_tfm) {
- desc.tfm = crypt_stat->mount_crypt_stat->global_key_tfm;
- tfm_mutex = &crypt_stat->mount_crypt_stat->global_key_tfm_mutex;
- } else {
- char *full_alg_name;
-
- rc = ecryptfs_crypto_api_algify_cipher_name(&full_alg_name,
- crypt_stat->cipher,
- "ecb");
- if (rc)
- goto out;
- desc.tfm = crypto_alloc_blkcipher(full_alg_name, 0,
- CRYPTO_ALG_ASYNC);
- kfree(full_alg_name);
- if (IS_ERR(desc.tfm)) {
- rc = PTR_ERR(desc.tfm);
- ecryptfs_printk(KERN_ERR, "Could not initialize crypto "
- "context for cipher [%s]; rc = [%d]\n",
- crypt_stat->cipher, rc);
- goto out;
- }
- crypto_blkcipher_set_flags(desc.tfm, CRYPTO_TFM_REQ_WEAK_KEY);
- }
- if (tfm_mutex)
- mutex_lock(tfm_mutex);
+ mutex_lock(tfm_mutex);
rc = crypto_blkcipher_setkey(desc.tfm, session_key_encryption_key,
crypt_stat->key_size);
if (rc < 0) {
- if (tfm_mutex)
- mutex_unlock(tfm_mutex);
+ mutex_unlock(tfm_mutex);
ecryptfs_printk(KERN_ERR, "Error setting key for crypto "
"context; rc = [%d]\n", rc);
goto out;
@@ -1563,56 +1646,53 @@ write_tag_3_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok,
rc = 0;
ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes of the key\n",
crypt_stat->key_size);
- rc = crypto_blkcipher_encrypt(&desc, dest_sg, src_sg,
+ rc = crypto_blkcipher_encrypt(&desc, &dst_sg, &src_sg,
(*key_rec).enc_key_size);
+ mutex_unlock(tfm_mutex);
if (rc) {
printk(KERN_ERR "Error encrypting; rc = [%d]\n", rc);
goto out;
}
- if (tfm_mutex)
- mutex_unlock(tfm_mutex);
ecryptfs_printk(KERN_DEBUG, "This should be the encrypted key:\n");
- if (ecryptfs_verbosity > 0)
+ if (ecryptfs_verbosity > 0) {
+ ecryptfs_printk(KERN_DEBUG, "EFEK of size [%d]:\n",
+ key_rec->enc_key_size);
ecryptfs_dump_hex(key_rec->enc_key,
key_rec->enc_key_size);
-encrypted_session_key_set:
- /* Now we have a valid key_rec. Append it to the
- * key_rec set. */
- key_rec_size = (sizeof(struct ecryptfs_key_record)
- - ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES
- + (key_rec->enc_key_size));
- /* TODO: Include a packet size limit as a parameter to this
- * function once we have multi-packet headers (for versions
- * later than 0.1 */
- if (key_rec_size >= ECRYPTFS_MAX_KEYSET_SIZE) {
- ecryptfs_printk(KERN_ERR, "Keyset too large\n");
- rc = -EINVAL;
- goto out;
}
- /* TODO: Packet size limit */
- /* We have 5 bytes of surrounding packet data */
- if ((0x05 + ECRYPTFS_SALT_SIZE
- + key_rec->enc_key_size) >= max) {
- ecryptfs_printk(KERN_ERR, "Authentication token is too "
- "large\n");
+encrypted_session_key_set:
+ /* This format is inspired by OpenPGP; see RFC 2440
+ * packet tag 3 */
+ max_packet_size = (1 /* Tag 3 identifier */
+ + 3 /* Max Tag 3 packet size */
+ + 1 /* Version */
+ + 1 /* Cipher code */
+ + 1 /* S2K specifier */
+ + 1 /* Hash identifier */
+ + ECRYPTFS_SALT_SIZE /* Salt */
+ + 1 /* Hash iterations */
+ + key_rec->enc_key_size); /* Encrypted key size */
+ if (max_packet_size > (*remaining_bytes)) {
+ printk(KERN_ERR "Packet too large; need up to [%td] bytes, but "
+ "there are only [%td] available\n", max_packet_size,
+ (*remaining_bytes));
rc = -EINVAL;
goto out;
}
- /* This format is inspired by OpenPGP; see RFC 2440
- * packet tag 3 */
dest[(*packet_size)++] = ECRYPTFS_TAG_3_PACKET_TYPE;
- /* ver+cipher+s2k+hash+salt+iter+enc_key */
- rc = write_packet_length(&dest[(*packet_size)],
- (0x05 + ECRYPTFS_SALT_SIZE
- + key_rec->enc_key_size),
+ /* Chop off the Tag 3 identifier(1) and Tag 3 packet size(3)
+ * to get the number of octets in the actual Tag 3 packet */
+ rc = write_packet_length(&dest[(*packet_size)], (max_packet_size - 4),
&packet_size_length);
if (rc) {
- ecryptfs_printk(KERN_ERR, "Error generating tag 3 packet "
- "header; cannot generate packet length\n");
+ printk(KERN_ERR "Error generating tag 3 packet header; cannot "
+ "generate packet length. rc = [%d]\n", rc);
goto out;
}
(*packet_size) += packet_size_length;
dest[(*packet_size)++] = 0x04; /* version 4 */
+ /* TODO: Break from RFC2440 so that arbitrary ciphers can be
+ * specified with strings */
cipher_code = ecryptfs_code_for_cipher_string(crypt_stat);
if (cipher_code == 0) {
ecryptfs_printk(KERN_WARNING, "Unable to generate code for "
@@ -1631,10 +1711,10 @@ encrypted_session_key_set:
key_rec->enc_key_size);
(*packet_size) += key_rec->enc_key_size;
out:
- if (desc.tfm && !tfm_mutex)
- crypto_free_blkcipher(desc.tfm);
if (rc)
(*packet_size) = 0;
+ else
+ (*remaining_bytes) -= (*packet_size);
return rc;
}
@@ -1642,7 +1722,7 @@ struct kmem_cache *ecryptfs_key_record_cache;
/**
* ecryptfs_generate_key_packet_set
- * @dest: Virtual address from which to write the key record set
+ * @dest_base: Virtual address from which to write the key record set
* @crypt_stat: The cryptographic context from which the
* authentication tokens will be retrieved
* @ecryptfs_dentry: The dentry, used to retrieve the mount crypt stat
@@ -1662,24 +1742,43 @@ ecryptfs_generate_key_packet_set(char *dest_base,
size_t max)
{
struct ecryptfs_auth_tok *auth_tok;
+ struct ecryptfs_global_auth_tok *global_auth_tok;
struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
&ecryptfs_superblock_to_private(
ecryptfs_dentry->d_sb)->mount_crypt_stat;
size_t written;
struct ecryptfs_key_record *key_rec;
+ struct ecryptfs_key_sig *key_sig;
int rc = 0;
(*len) = 0;
+ mutex_lock(&crypt_stat->keysig_list_mutex);
key_rec = kmem_cache_alloc(ecryptfs_key_record_cache, GFP_KERNEL);
if (!key_rec) {
rc = -ENOMEM;
goto out;
}
- if (mount_crypt_stat->global_auth_tok) {
- auth_tok = mount_crypt_stat->global_auth_tok;
+ list_for_each_entry(key_sig, &crypt_stat->keysig_list,
+ crypt_stat_list) {
+ memset(key_rec, 0, sizeof(*key_rec));
+ rc = ecryptfs_find_global_auth_tok_for_sig(&global_auth_tok,
+ mount_crypt_stat,
+ key_sig->keysig);
+ if (rc) {
+ printk(KERN_ERR "Error attempting to get the global "
+ "auth_tok; rc = [%d]\n", rc);
+ goto out_free;
+ }
+ if (global_auth_tok->flags & ECRYPTFS_AUTH_TOK_INVALID) {
+ printk(KERN_WARNING
+ "Skipping invalid auth tok with sig = [%s]\n",
+ global_auth_tok->sig);
+ continue;
+ }
+ auth_tok = global_auth_tok->global_auth_tok;
if (auth_tok->token_type == ECRYPTFS_PASSWORD) {
rc = write_tag_3_packet((dest_base + (*len)),
- max, auth_tok,
+ &max, auth_tok,
crypt_stat, key_rec,
&written);
if (rc) {
@@ -1689,10 +1788,9 @@ ecryptfs_generate_key_packet_set(char *dest_base,
}
(*len) += written;
/* Write auth tok signature packet */
- rc = write_tag_11_packet(
- (dest_base + (*len)),
- (max - (*len)),
- key_rec->sig, ECRYPTFS_SIG_SIZE, &written);
+ rc = write_tag_11_packet((dest_base + (*len)), &max,
+ key_rec->sig,
+ ECRYPTFS_SIG_SIZE, &written);
if (rc) {
ecryptfs_printk(KERN_ERR, "Error writing "
"auth tok signature packet\n");
@@ -1701,9 +1799,8 @@ ecryptfs_generate_key_packet_set(char *dest_base,
(*len) += written;
} else if (auth_tok->token_type == ECRYPTFS_PRIVATE_KEY) {
rc = write_tag_1_packet(dest_base + (*len),
- max, auth_tok,
- crypt_stat,mount_crypt_stat,
- key_rec, &written);
+ &max, auth_tok,
+ crypt_stat, key_rec, &written);
if (rc) {
ecryptfs_printk(KERN_WARNING, "Error "
"writing tag 1 packet\n");
@@ -1716,19 +1813,69 @@ ecryptfs_generate_key_packet_set(char *dest_base,
rc = -EINVAL;
goto out_free;
}
- } else
- BUG();
- if (likely((max - (*len)) > 0)) {
+ }
+ if (likely(max > 0)) {
dest_base[(*len)] = 0x00;
} else {
ecryptfs_printk(KERN_ERR, "Error writing boundary byte\n");
rc = -EIO;
}
-
out_free:
kmem_cache_free(ecryptfs_key_record_cache, key_rec);
out:
if (rc)
(*len) = 0;
+ mutex_unlock(&crypt_stat->keysig_list_mutex);
+ return rc;
+}
+
+struct kmem_cache *ecryptfs_key_sig_cache;
+
+int ecryptfs_add_keysig(struct ecryptfs_crypt_stat *crypt_stat, char *sig)
+{
+ struct ecryptfs_key_sig *new_key_sig;
+ int rc = 0;
+
+ new_key_sig = kmem_cache_alloc(ecryptfs_key_sig_cache, GFP_KERNEL);
+ if (!new_key_sig) {
+ rc = -ENOMEM;
+ printk(KERN_ERR
+ "Error allocating from ecryptfs_key_sig_cache\n");
+ goto out;
+ }
+ memcpy(new_key_sig->keysig, sig, ECRYPTFS_SIG_SIZE_HEX);
+ mutex_lock(&crypt_stat->keysig_list_mutex);
+ list_add(&new_key_sig->crypt_stat_list, &crypt_stat->keysig_list);
+ mutex_unlock(&crypt_stat->keysig_list_mutex);
+out:
+ return rc;
+}
+
+struct kmem_cache *ecryptfs_global_auth_tok_cache;
+
+int
+ecryptfs_add_global_auth_tok(struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
+ char *sig)
+{
+ struct ecryptfs_global_auth_tok *new_auth_tok;
+ int rc = 0;
+
+ new_auth_tok = kmem_cache_alloc(ecryptfs_global_auth_tok_cache,
+ GFP_KERNEL);
+ if (!new_auth_tok) {
+ rc = -ENOMEM;
+ printk(KERN_ERR "Error allocating from "
+ "ecryptfs_global_auth_tok_cache\n");
+ goto out;
+ }
+ memcpy(new_auth_tok->sig, sig, ECRYPTFS_SIG_SIZE_HEX);
+ new_auth_tok->sig[ECRYPTFS_SIG_SIZE_HEX] = '\0';
+ mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex);
+ list_add(&new_auth_tok->mount_crypt_stat_list,
+ &mount_crypt_stat->global_auth_tok_list);
+ mount_crypt_stat->num_global_auth_toks++;
+ mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex);
+out:
return rc;
}
+
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index a98497264fe8..b83a512b7e08 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -32,7 +32,6 @@
#include <linux/crypto.h>
#include <linux/netlink.h>
#include <linux/mount.h>
-#include <linux/dcache.h>
#include <linux/pagemap.h>
#include <linux/key.h>
#include <linux/parser.h>
@@ -99,6 +98,64 @@ void __ecryptfs_printk(const char *fmt, ...)
}
/**
+ * ecryptfs_init_persistent_file
+ * @ecryptfs_dentry: Fully initialized eCryptfs dentry object, with
+ * the lower dentry and the lower mount set
+ *
+ * eCryptfs only ever keeps a single open file for every lower
+ * inode. All I/O operations to the lower inode occur through that
+ * file. When the first eCryptfs dentry that interposes with the first
+ * lower dentry for that inode is created, this function creates the
+ * persistent file struct and associates it with the eCryptfs
+ * inode. When the eCryptfs inode is destroyed, the file is closed.
+ *
+ * The persistent file will be opened with read/write permissions, if
+ * possible. Otherwise, it is opened read-only.
+ *
+ * This function does nothing if a lower persistent file is already
+ * associated with the eCryptfs inode.
+ *
+ * Returns zero on success; non-zero otherwise
+ */
+int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
+{
+ struct ecryptfs_inode_info *inode_info =
+ ecryptfs_inode_to_private(ecryptfs_dentry->d_inode);
+ int rc = 0;
+
+ mutex_lock(&inode_info->lower_file_mutex);
+ if (!inode_info->lower_file) {
+ struct dentry *lower_dentry;
+ struct vfsmount *lower_mnt =
+ ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry);
+
+ lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
+ /* Corresponding dput() and mntput() are done when the
+ * persistent file is fput() when the eCryptfs inode
+ * is destroyed. */
+ dget(lower_dentry);
+ mntget(lower_mnt);
+ inode_info->lower_file = dentry_open(lower_dentry,
+ lower_mnt,
+ (O_RDWR | O_LARGEFILE));
+ if (IS_ERR(inode_info->lower_file))
+ inode_info->lower_file = dentry_open(lower_dentry,
+ lower_mnt,
+ (O_RDONLY
+ | O_LARGEFILE));
+ if (IS_ERR(inode_info->lower_file)) {
+ printk(KERN_ERR "Error opening lower persistent file "
+ "for lower_dentry [0x%p] and lower_mnt [0x%p]\n",
+ lower_dentry, lower_mnt);
+ rc = PTR_ERR(inode_info->lower_file);
+ inode_info->lower_file = NULL;
+ }
+ }
+ mutex_unlock(&inode_info->lower_file_mutex);
+ return rc;
+}
+
+/**
* ecryptfs_interpose
* @lower_dentry: Existing dentry in the lower filesystem
* @dentry: ecryptfs' dentry
@@ -155,6 +212,13 @@ int ecryptfs_interpose(struct dentry *lower_dentry, struct dentry *dentry,
/* This size will be overwritten for real files w/ headers and
* other metadata */
fsstack_copy_inode_size(inode, lower_inode);
+ rc = ecryptfs_init_persistent_file(dentry);
+ if (rc) {
+ printk(KERN_ERR "%s: Error attempting to initialize the "
+ "persistent file for the dentry with name [%s]; "
+ "rc = [%d]\n", __FUNCTION__, dentry->d_name.name, rc);
+ goto out;
+ }
out:
return rc;
}
@@ -179,38 +243,41 @@ static match_table_t tokens = {
{ecryptfs_opt_err, NULL}
};
-/**
- * ecryptfs_verify_version
- * @version: The version number to confirm
- *
- * Returns zero on good version; non-zero otherwise
- */
-static int ecryptfs_verify_version(u16 version)
+static int ecryptfs_init_global_auth_toks(
+ struct ecryptfs_mount_crypt_stat *mount_crypt_stat)
{
+ struct ecryptfs_global_auth_tok *global_auth_tok;
int rc = 0;
- unsigned char major;
- unsigned char minor;
-
- major = ((version >> 8) & 0xFF);
- minor = (version & 0xFF);
- if (major != ECRYPTFS_VERSION_MAJOR) {
- ecryptfs_printk(KERN_ERR, "Major version number mismatch. "
- "Expected [%d]; got [%d]\n",
- ECRYPTFS_VERSION_MAJOR, major);
- rc = -EINVAL;
- goto out;
- }
- if (minor != ECRYPTFS_VERSION_MINOR) {
- ecryptfs_printk(KERN_ERR, "Minor version number mismatch. "
- "Expected [%d]; got [%d]\n",
- ECRYPTFS_VERSION_MINOR, minor);
- rc = -EINVAL;
- goto out;
+
+ list_for_each_entry(global_auth_tok,
+ &mount_crypt_stat->global_auth_tok_list,
+ mount_crypt_stat_list) {
+ rc = ecryptfs_keyring_auth_tok_for_sig(
+ &global_auth_tok->global_auth_tok_key,
+ &global_auth_tok->global_auth_tok,
+ global_auth_tok->sig);
+ if (rc) {
+ printk(KERN_ERR "Could not find valid key in user "
+ "session keyring for sig specified in mount "
+ "option: [%s]\n", global_auth_tok->sig);
+ global_auth_tok->flags |= ECRYPTFS_AUTH_TOK_INVALID;
+ rc = 0;
+ } else
+ global_auth_tok->flags &= ~ECRYPTFS_AUTH_TOK_INVALID;
}
-out:
return rc;
}
+static void ecryptfs_init_mount_crypt_stat(
+ struct ecryptfs_mount_crypt_stat *mount_crypt_stat)
+{
+ memset((void *)mount_crypt_stat, 0,
+ sizeof(struct ecryptfs_mount_crypt_stat));
+ INIT_LIST_HEAD(&mount_crypt_stat->global_auth_tok_list);
+ mutex_init(&mount_crypt_stat->global_auth_tok_list_mutex);
+ mount_crypt_stat->flags |= ECRYPTFS_MOUNT_CRYPT_STAT_INITIALIZED;
+}
+
/**
* ecryptfs_parse_options
* @sb: The ecryptfs super block
@@ -238,14 +305,11 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options)
int cipher_name_set = 0;
int cipher_key_bytes;
int cipher_key_bytes_set = 0;
- struct key *auth_tok_key = NULL;
- struct ecryptfs_auth_tok *auth_tok = NULL;
struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
&ecryptfs_superblock_to_private(sb)->mount_crypt_stat;
substring_t args[MAX_OPT_ARGS];
int token;
char *sig_src;
- char *sig_dst;
char *debug_src;
char *cipher_name_dst;
char *cipher_name_src;
@@ -256,6 +320,7 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options)
rc = -EINVAL;
goto out;
}
+ ecryptfs_init_mount_crypt_stat(mount_crypt_stat);
while ((p = strsep(&options, ",")) != NULL) {
if (!*p)
continue;
@@ -264,14 +329,13 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options)
case ecryptfs_opt_sig:
case ecryptfs_opt_ecryptfs_sig:
sig_src = args[0].from;
- sig_dst =
- mount_crypt_stat->global_auth_tok_sig;
- memcpy(sig_dst, sig_src, ECRYPTFS_SIG_SIZE_HEX);
- sig_dst[ECRYPTFS_SIG_SIZE_HEX] = '\0';
- ecryptfs_printk(KERN_DEBUG,
- "The mount_crypt_stat "
- "global_auth_tok_sig set to: "
- "[%s]\n", sig_dst);
+ rc = ecryptfs_add_global_auth_tok(mount_crypt_stat,
+ sig_src);
+ if (rc) {
+ printk(KERN_ERR "Error attempting to register "
+ "global sig; rc = [%d]\n", rc);
+ goto out;
+ }
sig_set = 1;
break;
case ecryptfs_opt_debug:
@@ -333,12 +397,10 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options)
p);
}
}
- /* Do not support lack of mount-wide signature in 0.1
- * release */
if (!sig_set) {
rc = -EINVAL;
- ecryptfs_printk(KERN_ERR, "You must supply a valid "
- "passphrase auth tok signature as a mount "
+ ecryptfs_printk(KERN_ERR, "You must supply at least one valid "
+ "auth tok signature as a mount "
"parameter; see the eCryptfs README\n");
goto out;
}
@@ -358,55 +420,23 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options)
if (!cipher_key_bytes_set) {
mount_crypt_stat->global_default_cipher_key_size = 0;
}
- rc = ecryptfs_process_cipher(
- &mount_crypt_stat->global_key_tfm,
- mount_crypt_stat->global_default_cipher_name,
- &mount_crypt_stat->global_default_cipher_key_size);
+ rc = ecryptfs_add_new_key_tfm(
+ NULL, mount_crypt_stat->global_default_cipher_name,
+ mount_crypt_stat->global_default_cipher_key_size);
if (rc) {
- printk(KERN_ERR "Error attempting to initialize cipher [%s] "
- "with key size [%Zd] bytes; rc = [%d]\n",
+ printk(KERN_ERR "Error attempting to initialize cipher with "
+ "name = [%s] and key size = [%td]; rc = [%d]\n",
mount_crypt_stat->global_default_cipher_name,
mount_crypt_stat->global_default_cipher_key_size, rc);
- mount_crypt_stat->global_key_tfm = NULL;
- mount_crypt_stat->global_auth_tok_key = NULL;
rc = -EINVAL;
goto out;
}
- mutex_init(&mount_crypt_stat->global_key_tfm_mutex);
- ecryptfs_printk(KERN_DEBUG, "Requesting the key with description: "
- "[%s]\n", mount_crypt_stat->global_auth_tok_sig);
- /* The reference to this key is held until umount is done The
- * call to key_put is done in ecryptfs_put_super() */
- auth_tok_key = request_key(&key_type_user,
- mount_crypt_stat->global_auth_tok_sig,
- NULL);
- if (!auth_tok_key || IS_ERR(auth_tok_key)) {
- ecryptfs_printk(KERN_ERR, "Could not find key with "
- "description: [%s]\n",
- mount_crypt_stat->global_auth_tok_sig);
- process_request_key_err(PTR_ERR(auth_tok_key));
- rc = -EINVAL;
- goto out;
- }
- auth_tok = ecryptfs_get_key_payload_data(auth_tok_key);
- if (ecryptfs_verify_version(auth_tok->version)) {
- ecryptfs_printk(KERN_ERR, "Data structure version mismatch. "
- "Userspace tools must match eCryptfs kernel "
- "module with major version [%d] and minor "
- "version [%d]\n", ECRYPTFS_VERSION_MAJOR,
- ECRYPTFS_VERSION_MINOR);
- rc = -EINVAL;
- goto out;
- }
- if (auth_tok->token_type != ECRYPTFS_PASSWORD
- && auth_tok->token_type != ECRYPTFS_PRIVATE_KEY) {
- ecryptfs_printk(KERN_ERR, "Invalid auth_tok structure "
- "returned from key query\n");
- rc = -EINVAL;
- goto out;
+ rc = ecryptfs_init_global_auth_toks(mount_crypt_stat);
+ if (rc) {
+ printk(KERN_WARNING "One or more global auth toks could not "
+ "properly register; rc = [%d]\n", rc);
}
- mount_crypt_stat->global_auth_tok_key = auth_tok_key;
- mount_crypt_stat->global_auth_tok = auth_tok;
+ rc = 0;
out:
return rc;
}
@@ -495,7 +525,8 @@ static int ecryptfs_read_super(struct super_block *sb, const char *dev_name)
sb->s_maxbytes = lower_root->d_sb->s_maxbytes;
ecryptfs_set_dentry_lower(sb->s_root, lower_root);
ecryptfs_set_dentry_lower_mnt(sb->s_root, lower_mnt);
- if ((rc = ecryptfs_interpose(lower_root, sb->s_root, sb, 0)))
+ rc = ecryptfs_interpose(lower_root, sb->s_root, sb, 0);
+ if (rc)
goto out_free;
rc = 0;
goto out;
@@ -579,7 +610,7 @@ static struct file_system_type ecryptfs_fs_type = {
* Initializes the ecryptfs_inode_info_cache when it is created
*/
static void
-inode_info_init_once(void *vptr, struct kmem_cache *cachep, unsigned long flags)
+inode_info_init_once(struct kmem_cache *cachep, void *vptr)
{
struct ecryptfs_inode_info *ei = (struct ecryptfs_inode_info *)vptr;
@@ -590,7 +621,7 @@ static struct ecryptfs_cache_info {
struct kmem_cache **cache;
const char *name;
size_t size;
- void (*ctor)(void*, struct kmem_cache *, unsigned long);
+ void (*ctor)(struct kmem_cache *cache, void *obj);
} ecryptfs_cache_infos[] = {
{
.cache = &ecryptfs_auth_tok_list_item_cache,
@@ -639,15 +670,25 @@ static struct ecryptfs_cache_info {
.size = PAGE_CACHE_SIZE,
},
{
- .cache = &ecryptfs_lower_page_cache,
- .name = "ecryptfs_lower_page_cache",
- .size = PAGE_CACHE_SIZE,
- },
- {
.cache = &ecryptfs_key_record_cache,
.name = "ecryptfs_key_record_cache",
.size = sizeof(struct ecryptfs_key_record),
},
+ {
+ .cache = &ecryptfs_key_sig_cache,
+ .name = "ecryptfs_key_sig_cache",
+ .size = sizeof(struct ecryptfs_key_sig),
+ },
+ {
+ .cache = &ecryptfs_global_auth_tok_cache,
+ .name = "ecryptfs_global_auth_tok_cache",
+ .size = sizeof(struct ecryptfs_global_auth_tok),
+ },
+ {
+ .cache = &ecryptfs_key_tfm_cache,
+ .name = "ecryptfs_key_tfm_cache",
+ .size = sizeof(struct ecryptfs_key_tfm),
+ },
};
static void ecryptfs_free_kmem_caches(void)
@@ -750,7 +791,8 @@ static struct ecryptfs_version_str_map_elem {
{ECRYPTFS_VERSIONING_PUBKEY, "pubkey"},
{ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH, "plaintext passthrough"},
{ECRYPTFS_VERSIONING_POLICY, "policy"},
- {ECRYPTFS_VERSIONING_XATTR, "metadata in extended attribute"}
+ {ECRYPTFS_VERSIONING_XATTR, "metadata in extended attribute"},
+ {ECRYPTFS_VERSIONING_MULTKEY, "multiple keys per file"}
};
static ssize_t version_str_show(struct ecryptfs_obj *obj, char *buff)
@@ -786,7 +828,8 @@ static int do_sysfs_registration(void)
{
int rc;
- if ((rc = subsystem_register(&ecryptfs_subsys))) {
+ rc = subsystem_register(&ecryptfs_subsys);
+ if (rc) {
printk(KERN_ERR
"Unable to register ecryptfs sysfs subsystem\n");
goto out;
@@ -845,33 +888,49 @@ static int __init ecryptfs_init(void)
rc = register_filesystem(&ecryptfs_fs_type);
if (rc) {
printk(KERN_ERR "Failed to register filesystem\n");
- ecryptfs_free_kmem_caches();
- goto out;
+ goto out_free_kmem_caches;
}
kobj_set_kset_s(&ecryptfs_subsys, fs_subsys);
rc = do_sysfs_registration();
if (rc) {
printk(KERN_ERR "sysfs registration failed\n");
- unregister_filesystem(&ecryptfs_fs_type);
- ecryptfs_free_kmem_caches();
- goto out;
+ goto out_unregister_filesystem;
}
rc = ecryptfs_init_messaging(ecryptfs_transport);
if (rc) {
ecryptfs_printk(KERN_ERR, "Failure occured while attempting to "
"initialize the eCryptfs netlink socket\n");
- do_sysfs_unregistration();
- unregister_filesystem(&ecryptfs_fs_type);
- ecryptfs_free_kmem_caches();
+ goto out_do_sysfs_unregistration;
+ }
+ rc = ecryptfs_init_crypto();
+ if (rc) {
+ printk(KERN_ERR "Failure whilst attempting to init crypto; "
+ "rc = [%d]\n", rc);
+ goto out_release_messaging;
}
+ goto out;
+out_release_messaging:
+ ecryptfs_release_messaging(ecryptfs_transport);
+out_do_sysfs_unregistration:
+ do_sysfs_unregistration();
+out_unregister_filesystem:
+ unregister_filesystem(&ecryptfs_fs_type);
+out_free_kmem_caches:
+ ecryptfs_free_kmem_caches();
out:
return rc;
}
static void __exit ecryptfs_exit(void)
{
- do_sysfs_unregistration();
+ int rc;
+
+ rc = ecryptfs_destroy_crypto();
+ if (rc)
+ printk(KERN_ERR "Failure whilst attempting to destroy crypto; "
+ "rc = [%d]\n", rc);
ecryptfs_release_messaging(ecryptfs_transport);
+ do_sysfs_unregistration();
unregister_filesystem(&ecryptfs_fs_type);
ecryptfs_free_kmem_caches();
}
diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c
index a9d87c47f72d..a96d341d154d 100644
--- a/fs/ecryptfs/messaging.c
+++ b/fs/ecryptfs/messaging.c
@@ -419,8 +419,9 @@ int ecryptfs_init_messaging(unsigned int transport)
}
mutex_init(&ecryptfs_daemon_id_hash_mux);
mutex_lock(&ecryptfs_daemon_id_hash_mux);
- ecryptfs_hash_buckets = 0;
- while (ecryptfs_number_of_users >> ++ecryptfs_hash_buckets);
+ ecryptfs_hash_buckets = 1;
+ while (ecryptfs_number_of_users >> ecryptfs_hash_buckets)
+ ecryptfs_hash_buckets++;
ecryptfs_daemon_id_hash = kmalloc(sizeof(struct hlist_head)
* ecryptfs_hash_buckets, GFP_KERNEL);
if (!ecryptfs_daemon_id_hash) {
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index fd3f94d4a668..16a7a555f392 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -37,130 +37,27 @@
struct kmem_cache *ecryptfs_lower_page_cache;
/**
- * ecryptfs_get1page
+ * ecryptfs_get_locked_page
*
* Get one page from cache or lower f/s, return error otherwise.
*
- * Returns unlocked and up-to-date page (if ok), with increased
+ * Returns locked and up-to-date page (if ok), with increased
* refcnt.
*/
-static struct page *ecryptfs_get1page(struct file *file, int index)
+struct page *ecryptfs_get_locked_page(struct file *file, loff_t index)
{
struct dentry *dentry;
struct inode *inode;
struct address_space *mapping;
+ struct page *page;
dentry = file->f_path.dentry;
inode = dentry->d_inode;
mapping = inode->i_mapping;
- return read_mapping_page(mapping, index, (void *)file);
-}
-
-/**
- * ecryptfs_fill_zeros
- * @file: The ecryptfs file
- * @new_length: The new length of the data in the underlying file;
- * everything between the prior end of the file and the
- * new end of the file will be filled with zero's.
- * new_length must be greater than current length
- *
- * Function for handling lseek-ing past the end of the file.
- *
- * This function does not support shrinking, only growing a file.
- *
- * Returns zero on success; non-zero otherwise.
- */
-int ecryptfs_fill_zeros(struct file *file, loff_t new_length)
-{
- int rc = 0;
- struct dentry *dentry = file->f_path.dentry;
- struct inode *inode = dentry->d_inode;
- pgoff_t old_end_page_index = 0;
- pgoff_t index = old_end_page_index;
- int old_end_pos_in_page = -1;
- pgoff_t new_end_page_index;
- int new_end_pos_in_page;
- loff_t cur_length = i_size_read(inode);
-
- if (cur_length != 0) {
- index = old_end_page_index =
- ((cur_length - 1) >> PAGE_CACHE_SHIFT);
- old_end_pos_in_page = ((cur_length - 1) & ~PAGE_CACHE_MASK);
- }
- new_end_page_index = ((new_length - 1) >> PAGE_CACHE_SHIFT);
- new_end_pos_in_page = ((new_length - 1) & ~PAGE_CACHE_MASK);
- ecryptfs_printk(KERN_DEBUG, "old_end_page_index = [0x%.16x]; "
- "old_end_pos_in_page = [%d]; "
- "new_end_page_index = [0x%.16x]; "
- "new_end_pos_in_page = [%d]\n",
- old_end_page_index, old_end_pos_in_page,
- new_end_page_index, new_end_pos_in_page);
- if (old_end_page_index == new_end_page_index) {
- /* Start and end are in the same page; we just need to
- * set a portion of the existing page to zero's */
- rc = ecryptfs_write_zeros(file, index,
- (old_end_pos_in_page + 1),
- (new_end_pos_in_page
- - old_end_pos_in_page));
- if (rc)
- ecryptfs_printk(KERN_ERR, "ecryptfs_write_zeros("
- "file=[%p], "
- "index=[0x%.16x], "
- "old_end_pos_in_page=[d], "
- "(PAGE_CACHE_SIZE - new_end_pos_in_page"
- "=[%d]"
- ")=[d]) returned [%d]\n", file, index,
- old_end_pos_in_page,
- new_end_pos_in_page,
- (PAGE_CACHE_SIZE - new_end_pos_in_page),
- rc);
- goto out;
- }
- /* Fill the remainder of the previous last page with zeros */
- rc = ecryptfs_write_zeros(file, index, (old_end_pos_in_page + 1),
- ((PAGE_CACHE_SIZE - 1) - old_end_pos_in_page));
- if (rc) {
- ecryptfs_printk(KERN_ERR, "ecryptfs_write_zeros(file=[%p], "
- "index=[0x%.16x], old_end_pos_in_page=[d], "
- "(PAGE_CACHE_SIZE - old_end_pos_in_page)=[d]) "
- "returned [%d]\n", file, index,
- old_end_pos_in_page,
- (PAGE_CACHE_SIZE - old_end_pos_in_page), rc);
- goto out;
- }
- index++;
- while (index < new_end_page_index) {
- /* Fill all intermediate pages with zeros */
- rc = ecryptfs_write_zeros(file, index, 0, PAGE_CACHE_SIZE);
- if (rc) {
- ecryptfs_printk(KERN_ERR, "ecryptfs_write_zeros("
- "file=[%p], "
- "index=[0x%.16x], "
- "old_end_pos_in_page=[d], "
- "(PAGE_CACHE_SIZE - new_end_pos_in_page"
- "=[%d]"
- ")=[d]) returned [%d]\n", file, index,
- old_end_pos_in_page,
- new_end_pos_in_page,
- (PAGE_CACHE_SIZE - new_end_pos_in_page),
- rc);
- goto out;
- }
- index++;
- }
- /* Fill the portion at the beginning of the last new page with
- * zero's */
- rc = ecryptfs_write_zeros(file, index, 0, (new_end_pos_in_page + 1));
- if (rc) {
- ecryptfs_printk(KERN_ERR, "ecryptfs_write_zeros(file="
- "[%p], index=[0x%.16x], 0, "
- "new_end_pos_in_page=[%d]"
- "returned [%d]\n", file, index,
- new_end_pos_in_page, rc);
- goto out;
- }
-out:
- return rc;
+ page = read_mapping_page(mapping, index, (void *)file);
+ if (!IS_ERR(page))
+ lock_page(page);
+ return page;
}
/**
@@ -171,13 +68,9 @@ out:
*/
static int ecryptfs_writepage(struct page *page, struct writeback_control *wbc)
{
- struct ecryptfs_page_crypt_context ctx;
int rc;
- ctx.page = page;
- ctx.mode = ECRYPTFS_WRITEPAGE_MODE;
- ctx.param.wbc = wbc;
- rc = ecryptfs_encrypt_page(&ctx);
+ rc = ecryptfs_encrypt_page(page);
if (rc) {
ecryptfs_printk(KERN_WARNING, "Error encrypting "
"page (upper index [0x%.16x])\n", page->index);
@@ -191,58 +84,6 @@ out:
}
/**
- * Reads the data from the lower file file at index lower_page_index
- * and copies that data into page.
- *
- * @param page Page to fill
- * @param lower_page_index Index of the page in the lower file to get
- */
-int ecryptfs_do_readpage(struct file *file, struct page *page,
- pgoff_t lower_page_index)
-{
- int rc;
- struct dentry *dentry;
- struct file *lower_file;
- struct dentry *lower_dentry;
- struct inode *inode;
- struct inode *lower_inode;
- char *page_data;
- struct page *lower_page = NULL;
- char *lower_page_data;
- const struct address_space_operations *lower_a_ops;
-
- dentry = file->f_path.dentry;
- lower_file = ecryptfs_file_to_lower(file);
- lower_dentry = ecryptfs_dentry_to_lower(dentry);
- inode = dentry->d_inode;
- lower_inode = ecryptfs_inode_to_lower(inode);
- lower_a_ops = lower_inode->i_mapping->a_ops;
- lower_page = read_cache_page(lower_inode->i_mapping, lower_page_index,
- (filler_t *)lower_a_ops->readpage,
- (void *)lower_file);
- if (IS_ERR(lower_page)) {
- rc = PTR_ERR(lower_page);
- lower_page = NULL;
- ecryptfs_printk(KERN_ERR, "Error reading from page cache\n");
- goto out;
- }
- page_data = kmap_atomic(page, KM_USER0);
- lower_page_data = kmap_atomic(lower_page, KM_USER1);
- memcpy(page_data, lower_page_data, PAGE_CACHE_SIZE);
- kunmap_atomic(lower_page_data, KM_USER1);
- kunmap_atomic(page_data, KM_USER0);
- flush_dcache_page(page);
- rc = 0;
-out:
- if (likely(lower_page))
- page_cache_release(lower_page);
- if (rc == 0)
- SetPageUptodate(page);
- else
- ClearPageUptodate(page);
- return rc;
-}
-/**
* Header Extent:
* Octets 0-7: Unencrypted file size (big-endian)
* Octets 8-15: eCryptfs special marker
@@ -271,9 +112,77 @@ static void set_header_info(char *page_virt,
}
/**
+ * ecryptfs_copy_up_encrypted_with_header
+ * @page: Sort of a ``virtual'' representation of the encrypted lower
+ * file. The actual lower file does not have the metadata in
+ * the header. This is locked.
+ * @crypt_stat: The eCryptfs inode's cryptographic context
+ *
+ * The ``view'' is the version of the file that userspace winds up
+ * seeing, with the header information inserted.
+ */
+static int
+ecryptfs_copy_up_encrypted_with_header(struct page *page,
+ struct ecryptfs_crypt_stat *crypt_stat)
+{
+ loff_t extent_num_in_page = 0;
+ loff_t num_extents_per_page = (PAGE_CACHE_SIZE
+ / crypt_stat->extent_size);
+ int rc = 0;
+
+ while (extent_num_in_page < num_extents_per_page) {
+ loff_t view_extent_num = ((((loff_t)page->index)
+ * num_extents_per_page)
+ + extent_num_in_page);
+
+ if (view_extent_num < crypt_stat->num_header_extents_at_front) {
+ /* This is a header extent */
+ char *page_virt;
+
+ page_virt = kmap_atomic(page, KM_USER0);
+ memset(page_virt, 0, PAGE_CACHE_SIZE);
+ /* TODO: Support more than one header extent */
+ if (view_extent_num == 0) {
+ rc = ecryptfs_read_xattr_region(
+ page_virt, page->mapping->host);
+ set_header_info(page_virt, crypt_stat);
+ }
+ kunmap_atomic(page_virt, KM_USER0);
+ flush_dcache_page(page);
+ if (rc) {
+ printk(KERN_ERR "%s: Error reading xattr "
+ "region; rc = [%d]\n", __FUNCTION__, rc);
+ goto out;
+ }
+ } else {
+ /* This is an encrypted data extent */
+ loff_t lower_offset =
+ ((view_extent_num -
+ crypt_stat->num_header_extents_at_front)
+ * crypt_stat->extent_size);
+
+ rc = ecryptfs_read_lower_page_segment(
+ page, (lower_offset >> PAGE_CACHE_SHIFT),
+ (lower_offset & ~PAGE_CACHE_MASK),
+ crypt_stat->extent_size, page->mapping->host);
+ if (rc) {
+ printk(KERN_ERR "%s: Error attempting to read "
+ "extent at offset [%lld] in the lower "
+ "file; rc = [%d]\n", __FUNCTION__,
+ lower_offset, rc);
+ goto out;
+ }
+ }
+ extent_num_in_page++;
+ }
+out:
+ return rc;
+}
+
+/**
* ecryptfs_readpage
- * @file: This is an ecryptfs file
- * @page: ecryptfs associated page to stick the read data into
+ * @file: An eCryptfs file
+ * @page: Page from eCryptfs inode mapping into which to stick the read data
*
* Read in a page, decrypting if necessary.
*
@@ -281,59 +190,35 @@ static void set_header_info(char *page_virt,
*/
static int ecryptfs_readpage(struct file *file, struct page *page)
{
+ struct ecryptfs_crypt_stat *crypt_stat =
+ &ecryptfs_inode_to_private(file->f_path.dentry->d_inode)->crypt_stat;
int rc = 0;
- struct ecryptfs_crypt_stat *crypt_stat;
- BUG_ON(!(file && file->f_path.dentry && file->f_path.dentry->d_inode));
- crypt_stat = &ecryptfs_inode_to_private(file->f_path.dentry->d_inode)
- ->crypt_stat;
if (!crypt_stat
|| !(crypt_stat->flags & ECRYPTFS_ENCRYPTED)
|| (crypt_stat->flags & ECRYPTFS_NEW_FILE)) {
ecryptfs_printk(KERN_DEBUG,
"Passing through unencrypted page\n");
- rc = ecryptfs_do_readpage(file, page, page->index);
- if (rc) {
- ecryptfs_printk(KERN_ERR, "Error reading page; rc = "
- "[%d]\n", rc);
- goto out;
- }
+ rc = ecryptfs_read_lower_page_segment(page, page->index, 0,
+ PAGE_CACHE_SIZE,
+ page->mapping->host);
} else if (crypt_stat->flags & ECRYPTFS_VIEW_AS_ENCRYPTED) {
if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) {
- int num_pages_in_header_region =
- (crypt_stat->header_extent_size
- / PAGE_CACHE_SIZE);
-
- if (page->index < num_pages_in_header_region) {
- char *page_virt;
-
- page_virt = kmap_atomic(page, KM_USER0);
- memset(page_virt, 0, PAGE_CACHE_SIZE);
- if (page->index == 0) {
- rc = ecryptfs_read_xattr_region(
- page_virt, file->f_path.dentry);
- set_header_info(page_virt, crypt_stat);
- }
- kunmap_atomic(page_virt, KM_USER0);
- flush_dcache_page(page);
- if (rc) {
- printk(KERN_ERR "Error reading xattr "
- "region\n");
- goto out;
- }
- } else {
- rc = ecryptfs_do_readpage(
- file, page,
- (page->index
- - num_pages_in_header_region));
- if (rc) {
- printk(KERN_ERR "Error reading page; "
- "rc = [%d]\n", rc);
- goto out;
- }
+ rc = ecryptfs_copy_up_encrypted_with_header(page,
+ crypt_stat);
+ if (rc) {
+ printk(KERN_ERR "%s: Error attempting to copy "
+ "the encrypted content from the lower "
+ "file whilst inserting the metadata "
+ "from the xattr into the header; rc = "
+ "[%d]\n", __FUNCTION__, rc);
+ goto out;
}
+
} else {
- rc = ecryptfs_do_readpage(file, page, page->index);
+ rc = ecryptfs_read_lower_page_segment(
+ page, page->index, 0, PAGE_CACHE_SIZE,
+ page->mapping->host);
if (rc) {
printk(KERN_ERR "Error reading page; rc = "
"[%d]\n", rc);
@@ -341,17 +226,18 @@ static int ecryptfs_readpage(struct file *file, struct page *page)
}
}
} else {
- rc = ecryptfs_decrypt_page(file, page);
+ rc = ecryptfs_decrypt_page(page);
if (rc) {
ecryptfs_printk(KERN_ERR, "Error decrypting page; "
"rc = [%d]\n", rc);
goto out;
}
}
- SetPageUptodate(page);
out:
if (rc)
ClearPageUptodate(page);
+ else
+ SetPageUptodate(page);
ecryptfs_printk(KERN_DEBUG, "Unlocking page with index = [0x%.16x]\n",
page->index);
unlock_page(page);
@@ -377,27 +263,6 @@ out:
return 0;
}
-/**
- * eCryptfs does not currently support holes. When writing after a
- * seek past the end of the file, eCryptfs fills in 0's through to the
- * current location. The code to fill in the 0's to all the
- * intermediate pages calls ecryptfs_prepare_write_no_truncate().
- */
-static int
-ecryptfs_prepare_write_no_truncate(struct file *file, struct page *page,
- unsigned from, unsigned to)
-{
- int rc = 0;
-
- if (from == 0 && to == PAGE_CACHE_SIZE)
- goto out; /* If we are writing a full page, it will be
- up to date. */
- if (!PageUptodate(page))
- rc = ecryptfs_do_readpage(file, page, page->index);
-out:
- return rc;
-}
-
static int ecryptfs_prepare_write(struct file *file, struct page *page,
unsigned from, unsigned to)
{
@@ -406,10 +271,21 @@ static int ecryptfs_prepare_write(struct file *file, struct page *page,
if (from == 0 && to == PAGE_CACHE_SIZE)
goto out; /* If we are writing a full page, it will be
up to date. */
- if (!PageUptodate(page))
- rc = ecryptfs_do_readpage(file, page, page->index);
+ if (!PageUptodate(page)) {
+ rc = ecryptfs_read_lower_page_segment(page, page->index, 0,
+ PAGE_CACHE_SIZE,
+ page->mapping->host);
+ if (rc) {
+ printk(KERN_ERR "%s: Error attemping to read lower "
+ "page segment; rc = [%d]\n", __FUNCTION__, rc);
+ ClearPageUptodate(page);
+ goto out;
+ } else
+ SetPageUptodate(page);
+ }
if (page->index != 0) {
- loff_t end_of_prev_pg_pos = page_offset(page) - 1;
+ loff_t end_of_prev_pg_pos =
+ (((loff_t)page->index << PAGE_CACHE_SHIFT) - 1);
if (end_of_prev_pg_pos > i_size_read(page->mapping->host)) {
rc = ecryptfs_truncate(file->f_path.dentry,
@@ -428,32 +304,6 @@ out:
return rc;
}
-int ecryptfs_writepage_and_release_lower_page(struct page *lower_page,
- struct inode *lower_inode,
- struct writeback_control *wbc)
-{
- int rc = 0;
-
- rc = lower_inode->i_mapping->a_ops->writepage(lower_page, wbc);
- if (rc) {
- ecryptfs_printk(KERN_ERR, "Error calling lower writepage(); "
- "rc = [%d]\n", rc);
- goto out;
- }
- lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME;
- page_cache_release(lower_page);
-out:
- return rc;
-}
-
-static
-void ecryptfs_release_lower_page(struct page *lower_page, int page_locked)
-{
- if (page_locked)
- unlock_page(lower_page);
- page_cache_release(lower_page);
-}
-
/**
* ecryptfs_write_inode_size_to_header
*
@@ -461,67 +311,48 @@ void ecryptfs_release_lower_page(struct page *lower_page, int page_locked)
*
* Returns zero on success; non-zero on error.
*/
-static int ecryptfs_write_inode_size_to_header(struct file *lower_file,
- struct inode *lower_inode,
- struct inode *inode)
+static int ecryptfs_write_inode_size_to_header(struct inode *ecryptfs_inode)
{
- int rc = 0;
- struct page *header_page;
- char *header_virt;
- const struct address_space_operations *lower_a_ops;
u64 file_size;
+ char *file_size_virt;
+ int rc;
-retry:
- header_page = grab_cache_page(lower_inode->i_mapping, 0);
- if (!header_page) {
- ecryptfs_printk(KERN_ERR, "grab_cache_page for "
- "lower_page_index 0 failed\n");
- rc = -EINVAL;
- goto out;
- }
- lower_a_ops = lower_inode->i_mapping->a_ops;
- rc = lower_a_ops->prepare_write(lower_file, header_page, 0, 8);
- if (rc) {
- if (rc == AOP_TRUNCATED_PAGE) {
- ecryptfs_release_lower_page(header_page, 0);
- goto retry;
- } else
- ecryptfs_release_lower_page(header_page, 1);
+ file_size_virt = kmalloc(sizeof(u64), GFP_KERNEL);
+ if (!file_size_virt) {
+ rc = -ENOMEM;
goto out;
}
- file_size = (u64)i_size_read(inode);
- ecryptfs_printk(KERN_DEBUG, "Writing size: [0x%.16x]\n", file_size);
+ file_size = (u64)i_size_read(ecryptfs_inode);
file_size = cpu_to_be64(file_size);
- header_virt = kmap_atomic(header_page, KM_USER0);
- memcpy(header_virt, &file_size, sizeof(u64));
- kunmap_atomic(header_virt, KM_USER0);
- flush_dcache_page(header_page);
- rc = lower_a_ops->commit_write(lower_file, header_page, 0, 8);
- if (rc < 0)
- ecryptfs_printk(KERN_ERR, "Error commiting header page "
- "write\n");
- if (rc == AOP_TRUNCATED_PAGE) {
- ecryptfs_release_lower_page(header_page, 0);
- goto retry;
- } else
- ecryptfs_release_lower_page(header_page, 1);
- lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME;
- mark_inode_dirty_sync(inode);
+ memcpy(file_size_virt, &file_size, sizeof(u64));
+ rc = ecryptfs_write_lower(ecryptfs_inode, file_size_virt, 0,
+ sizeof(u64));
+ kfree(file_size_virt);
+ if (rc)
+ printk(KERN_ERR "%s: Error writing file size to header; "
+ "rc = [%d]\n", __FUNCTION__, rc);
out:
return rc;
}
-static int ecryptfs_write_inode_size_to_xattr(struct inode *lower_inode,
- struct inode *inode,
- struct dentry *ecryptfs_dentry,
- int lower_i_mutex_held)
+struct kmem_cache *ecryptfs_xattr_cache;
+
+static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode)
{
ssize_t size;
void *xattr_virt;
- struct dentry *lower_dentry;
+ struct dentry *lower_dentry =
+ ecryptfs_inode_to_private(ecryptfs_inode)->lower_file->f_dentry;
+ struct inode *lower_inode = lower_dentry->d_inode;
u64 file_size;
int rc;
+ if (!lower_inode->i_op->getxattr || !lower_inode->i_op->setxattr) {
+ printk(KERN_WARNING
+ "No support for setting xattr in lower filesystem\n");
+ rc = -ENOSYS;
+ goto out;
+ }
xattr_virt = kmem_cache_alloc(ecryptfs_xattr_cache, GFP_KERNEL);
if (!xattr_virt) {
printk(KERN_ERR "Out of memory whilst attempting to write "
@@ -529,35 +360,17 @@ static int ecryptfs_write_inode_size_to_xattr(struct inode *lower_inode,
rc = -ENOMEM;
goto out;
}
- lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
- if (!lower_dentry->d_inode->i_op->getxattr ||
- !lower_dentry->d_inode->i_op->setxattr) {
- printk(KERN_WARNING
- "No support for setting xattr in lower filesystem\n");
- rc = -ENOSYS;
- kmem_cache_free(ecryptfs_xattr_cache, xattr_virt);
- goto out;
- }
- if (!lower_i_mutex_held)
- mutex_lock(&lower_dentry->d_inode->i_mutex);
- size = lower_dentry->d_inode->i_op->getxattr(lower_dentry,
- ECRYPTFS_XATTR_NAME,
- xattr_virt,
- PAGE_CACHE_SIZE);
- if (!lower_i_mutex_held)
- mutex_unlock(&lower_dentry->d_inode->i_mutex);
+ mutex_lock(&lower_inode->i_mutex);
+ size = lower_inode->i_op->getxattr(lower_dentry, ECRYPTFS_XATTR_NAME,
+ xattr_virt, PAGE_CACHE_SIZE);
if (size < 0)
size = 8;
- file_size = (u64)i_size_read(inode);
+ file_size = (u64)i_size_read(ecryptfs_inode);
file_size = cpu_to_be64(file_size);
memcpy(xattr_virt, &file_size, sizeof(u64));
- if (!lower_i_mutex_held)
- mutex_lock(&lower_dentry->d_inode->i_mutex);
- rc = lower_dentry->d_inode->i_op->setxattr(lower_dentry,
- ECRYPTFS_XATTR_NAME,
- xattr_virt, size, 0);
- if (!lower_i_mutex_held)
- mutex_unlock(&lower_dentry->d_inode->i_mutex);
+ rc = lower_inode->i_op->setxattr(lower_dentry, ECRYPTFS_XATTR_NAME,
+ xattr_virt, size, 0);
+ mutex_unlock(&lower_inode->i_mutex);
if (rc)
printk(KERN_ERR "Error whilst attempting to write inode size "
"to lower file xattr; rc = [%d]\n", rc);
@@ -566,122 +379,18 @@ out:
return rc;
}
-int
-ecryptfs_write_inode_size_to_metadata(struct file *lower_file,
- struct inode *lower_inode,
- struct inode *inode,
- struct dentry *ecryptfs_dentry,
- int lower_i_mutex_held)
+int ecryptfs_write_inode_size_to_metadata(struct inode *ecryptfs_inode)
{
struct ecryptfs_crypt_stat *crypt_stat;
- crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
+ crypt_stat = &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;
if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
- return ecryptfs_write_inode_size_to_xattr(lower_inode, inode,
- ecryptfs_dentry,
- lower_i_mutex_held);
+ return ecryptfs_write_inode_size_to_xattr(ecryptfs_inode);
else
- return ecryptfs_write_inode_size_to_header(lower_file,
- lower_inode,
- inode);
-}
-
-int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode,
- struct file *lower_file,
- unsigned long lower_page_index, int byte_offset,
- int region_bytes)
-{
- int rc = 0;
-
-retry:
- *lower_page = grab_cache_page(lower_inode->i_mapping, lower_page_index);
- if (!(*lower_page)) {
- rc = -EINVAL;
- ecryptfs_printk(KERN_ERR, "Error attempting to grab "
- "lower page with index [0x%.16x]\n",
- lower_page_index);
- goto out;
- }
- rc = lower_inode->i_mapping->a_ops->prepare_write(lower_file,
- (*lower_page),
- byte_offset,
- region_bytes);
- if (rc) {
- if (rc == AOP_TRUNCATED_PAGE) {
- ecryptfs_release_lower_page(*lower_page, 0);
- goto retry;
- } else {
- ecryptfs_printk(KERN_ERR, "prepare_write for "
- "lower_page_index = [0x%.16x] failed; rc = "
- "[%d]\n", lower_page_index, rc);
- ecryptfs_release_lower_page(*lower_page, 1);
- (*lower_page) = NULL;
- }
- }
-out:
- return rc;
-}
-
-/**
- * ecryptfs_commit_lower_page
- *
- * Returns zero on success; non-zero on error
- */
-int
-ecryptfs_commit_lower_page(struct page *lower_page, struct inode *lower_inode,
- struct file *lower_file, int byte_offset,
- int region_size)
-{
- int page_locked = 1;
- int rc = 0;
-
- rc = lower_inode->i_mapping->a_ops->commit_write(
- lower_file, lower_page, byte_offset, region_size);
- if (rc == AOP_TRUNCATED_PAGE)
- page_locked = 0;
- if (rc < 0) {
- ecryptfs_printk(KERN_ERR,
- "Error committing write; rc = [%d]\n", rc);
- } else
- rc = 0;
- ecryptfs_release_lower_page(lower_page, page_locked);
- return rc;
+ return ecryptfs_write_inode_size_to_header(ecryptfs_inode);
}
/**
- * ecryptfs_copy_page_to_lower
- *
- * Used for plaintext pass-through; no page index interpolation
- * required.
- */
-int ecryptfs_copy_page_to_lower(struct page *page, struct inode *lower_inode,
- struct file *lower_file)
-{
- int rc = 0;
- struct page *lower_page;
-
- rc = ecryptfs_get_lower_page(&lower_page, lower_inode, lower_file,
- page->index, 0, PAGE_CACHE_SIZE);
- if (rc) {
- ecryptfs_printk(KERN_ERR, "Error attempting to get page "
- "at index [0x%.16x]\n", page->index);
- goto out;
- }
- /* TODO: aops */
- memcpy((char *)page_address(lower_page), page_address(page),
- PAGE_CACHE_SIZE);
- rc = ecryptfs_commit_lower_page(lower_page, lower_inode, lower_file,
- 0, PAGE_CACHE_SIZE);
- if (rc)
- ecryptfs_printk(KERN_ERR, "Error attempting to commit page "
- "at index [0x%.16x]\n", page->index);
-out:
- return rc;
-}
-
-struct kmem_cache *ecryptfs_xattr_cache;
-
-/**
* ecryptfs_commit_write
* @file: The eCryptfs file object
* @page: The eCryptfs page
@@ -695,20 +404,12 @@ struct kmem_cache *ecryptfs_xattr_cache;
static int ecryptfs_commit_write(struct file *file, struct page *page,
unsigned from, unsigned to)
{
- struct ecryptfs_page_crypt_context ctx;
loff_t pos;
- struct inode *inode;
- struct inode *lower_inode;
- struct file *lower_file;
- struct ecryptfs_crypt_stat *crypt_stat;
+ struct inode *ecryptfs_inode = page->mapping->host;
+ struct ecryptfs_crypt_stat *crypt_stat =
+ &ecryptfs_inode_to_private(file->f_path.dentry->d_inode)->crypt_stat;
int rc;
- inode = page->mapping->host;
- lower_inode = ecryptfs_inode_to_lower(inode);
- lower_file = ecryptfs_file_to_lower(file);
- mutex_lock(&lower_inode->i_mutex);
- crypt_stat = &ecryptfs_inode_to_private(file->f_path.dentry->d_inode)
- ->crypt_stat;
if (crypt_stat->flags & ECRYPTFS_NEW_FILE) {
ecryptfs_printk(KERN_DEBUG, "ECRYPTFS_NEW_FILE flag set in "
"crypt_stat at memory location [%p]\n", crypt_stat);
@@ -718,6 +419,7 @@ static int ecryptfs_commit_write(struct file *file, struct page *page,
ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page"
"(page w/ index = [0x%.16x], to = [%d])\n", page->index,
to);
+ /* Fills in zeros if 'to' goes beyond inode size */
rc = fill_zeros_to_end_of_page(page, to);
if (rc) {
ecryptfs_printk(KERN_WARNING, "Error attempting to fill "
@@ -725,82 +427,22 @@ static int ecryptfs_commit_write(struct file *file, struct page *page,
page->index);
goto out;
}
- ctx.page = page;
- ctx.mode = ECRYPTFS_PREPARE_COMMIT_MODE;
- ctx.param.lower_file = lower_file;
- rc = ecryptfs_encrypt_page(&ctx);
+ rc = ecryptfs_encrypt_page(page);
if (rc) {
ecryptfs_printk(KERN_WARNING, "Error encrypting page (upper "
"index [0x%.16x])\n", page->index);
goto out;
}
- inode->i_blocks = lower_inode->i_blocks;
- pos = page_offset(page) + to;
- if (pos > i_size_read(inode)) {
- i_size_write(inode, pos);
+ pos = (((loff_t)page->index) << PAGE_CACHE_SHIFT) + to;
+ if (pos > i_size_read(ecryptfs_inode)) {
+ i_size_write(ecryptfs_inode, pos);
ecryptfs_printk(KERN_DEBUG, "Expanded file size to "
- "[0x%.16x]\n", i_size_read(inode));
+ "[0x%.16x]\n", i_size_read(ecryptfs_inode));
}
- rc = ecryptfs_write_inode_size_to_metadata(lower_file, lower_inode,
- inode, file->f_dentry,
- ECRYPTFS_LOWER_I_MUTEX_HELD);
+ rc = ecryptfs_write_inode_size_to_metadata(ecryptfs_inode);
if (rc)
printk(KERN_ERR "Error writing inode size to metadata; "
"rc = [%d]\n", rc);
- lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME;
- mark_inode_dirty_sync(inode);
-out:
- if (rc < 0)
- ClearPageUptodate(page);
- else
- SetPageUptodate(page);
- mutex_unlock(&lower_inode->i_mutex);
- return rc;
-}
-
-/**
- * ecryptfs_write_zeros
- * @file: The ecryptfs file
- * @index: The index in which we are writing
- * @start: The position after the last block of data
- * @num_zeros: The number of zeros to write
- *
- * Write a specified number of zero's to a page.
- *
- * (start + num_zeros) must be less than or equal to PAGE_CACHE_SIZE
- */
-int
-ecryptfs_write_zeros(struct file *file, pgoff_t index, int start, int num_zeros)
-{
- int rc = 0;
- struct page *tmp_page;
-
- tmp_page = ecryptfs_get1page(file, index);
- if (IS_ERR(tmp_page)) {
- ecryptfs_printk(KERN_ERR, "Error getting page at index "
- "[0x%.16x]\n", index);
- rc = PTR_ERR(tmp_page);
- goto out;
- }
- if ((rc = ecryptfs_prepare_write_no_truncate(file, tmp_page, start,
- (start + num_zeros)))) {
- ecryptfs_printk(KERN_ERR, "Error preparing to write zero's "
- "to page at index [0x%.16x]\n",
- index);
- page_cache_release(tmp_page);
- goto out;
- }
- zero_user_page(tmp_page, start, num_zeros, KM_USER0);
- rc = ecryptfs_commit_write(file, tmp_page, start, start + num_zeros);
- if (rc < 0) {
- ecryptfs_printk(KERN_ERR, "Error attempting to write zero's "
- "to remainder of page at index [0x%.16x]\n",
- index);
- page_cache_release(tmp_page);
- goto out;
- }
- rc = 0;
- page_cache_release(tmp_page);
out:
return rc;
}
@@ -819,34 +461,10 @@ static sector_t ecryptfs_bmap(struct address_space *mapping, sector_t block)
return rc;
}
-static void ecryptfs_sync_page(struct page *page)
-{
- struct inode *inode;
- struct inode *lower_inode;
- struct page *lower_page;
-
- inode = page->mapping->host;
- lower_inode = ecryptfs_inode_to_lower(inode);
- /* NOTE: Recently swapped with grab_cache_page(), since
- * sync_page() just makes sure that pending I/O gets done. */
- lower_page = find_lock_page(lower_inode->i_mapping, page->index);
- if (!lower_page) {
- ecryptfs_printk(KERN_DEBUG, "find_lock_page failed\n");
- return;
- }
- if (lower_page->mapping->a_ops->sync_page)
- lower_page->mapping->a_ops->sync_page(lower_page);
- ecryptfs_printk(KERN_DEBUG, "Unlocking page with index = [0x%.16x]\n",
- lower_page->index);
- unlock_page(lower_page);
- page_cache_release(lower_page);
-}
-
struct address_space_operations ecryptfs_aops = {
.writepage = ecryptfs_writepage,
.readpage = ecryptfs_readpage,
.prepare_write = ecryptfs_prepare_write,
.commit_write = ecryptfs_commit_write,
.bmap = ecryptfs_bmap,
- .sync_page = ecryptfs_sync_page,
};
diff --git a/fs/ecryptfs/read_write.c b/fs/ecryptfs/read_write.c
new file mode 100644
index 000000000000..6b7474a4336a
--- /dev/null
+++ b/fs/ecryptfs/read_write.c
@@ -0,0 +1,358 @@
+/**
+ * eCryptfs: Linux filesystem encryption layer
+ *
+ * Copyright (C) 2007 International Business Machines Corp.
+ * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <linux/fs.h>
+#include <linux/pagemap.h>
+#include "ecryptfs_kernel.h"
+
+/**
+ * ecryptfs_write_lower
+ * @ecryptfs_inode: The eCryptfs inode
+ * @data: Data to write
+ * @offset: Byte offset in the lower file to which to write the data
+ * @size: Number of bytes from @data to write at @offset in the lower
+ * file
+ *
+ * Write data to the lower file.
+ *
+ * Returns zero on success; non-zero on error
+ */
+int ecryptfs_write_lower(struct inode *ecryptfs_inode, char *data,
+ loff_t offset, size_t size)
+{
+ struct ecryptfs_inode_info *inode_info;
+ ssize_t octets_written;
+ mm_segment_t fs_save;
+ int rc = 0;
+
+ inode_info = ecryptfs_inode_to_private(ecryptfs_inode);
+ mutex_lock(&inode_info->lower_file_mutex);
+ BUG_ON(!inode_info->lower_file);
+ inode_info->lower_file->f_pos = offset;
+ fs_save = get_fs();
+ set_fs(get_ds());
+ octets_written = vfs_write(inode_info->lower_file, data, size,
+ &inode_info->lower_file->f_pos);
+ set_fs(fs_save);
+ if (octets_written < 0) {
+ printk(KERN_ERR "%s: octets_written = [%td]; "
+ "expected [%td]\n", __FUNCTION__, octets_written, size);
+ rc = -EINVAL;
+ }
+ mutex_unlock(&inode_info->lower_file_mutex);
+ mark_inode_dirty_sync(ecryptfs_inode);
+ return rc;
+}
+
+/**
+ * ecryptfs_write_lower_page_segment
+ * @ecryptfs_inode: The eCryptfs inode
+ * @page_for_lower: The page containing the data to be written to the
+ * lower file
+ * @offset_in_page: The offset in the @page_for_lower from which to
+ * start writing the data
+ * @size: The amount of data from @page_for_lower to write to the
+ * lower file
+ *
+ * Determines the byte offset in the file for the given page and
+ * offset within the page, maps the page, and makes the call to write
+ * the contents of @page_for_lower to the lower inode.
+ *
+ * Returns zero on success; non-zero otherwise
+ */
+int ecryptfs_write_lower_page_segment(struct inode *ecryptfs_inode,
+ struct page *page_for_lower,
+ size_t offset_in_page, size_t size)
+{
+ char *virt;
+ loff_t offset;
+ int rc;
+
+ offset = ((((loff_t)page_for_lower->index) << PAGE_CACHE_SHIFT)
+ + offset_in_page);
+ virt = kmap(page_for_lower);
+ rc = ecryptfs_write_lower(ecryptfs_inode, virt, offset, size);
+ kunmap(page_for_lower);
+ return rc;
+}
+
+/**
+ * ecryptfs_write
+ * @ecryptfs_file: The eCryptfs file into which to write
+ * @data: Virtual address where data to write is located
+ * @offset: Offset in the eCryptfs file at which to begin writing the
+ * data from @data
+ * @size: The number of bytes to write from @data
+ *
+ * Write an arbitrary amount of data to an arbitrary location in the
+ * eCryptfs inode page cache. This is done on a page-by-page, and then
+ * by an extent-by-extent, basis; individual extents are encrypted and
+ * written to the lower page cache (via VFS writes). This function
+ * takes care of all the address translation to locations in the lower
+ * filesystem; it also handles truncate events, writing out zeros
+ * where necessary.
+ *
+ * Returns zero on success; non-zero otherwise
+ */
+int ecryptfs_write(struct file *ecryptfs_file, char *data, loff_t offset,
+ size_t size)
+{
+ struct page *ecryptfs_page;
+ char *ecryptfs_page_virt;
+ loff_t ecryptfs_file_size =
+ i_size_read(ecryptfs_file->f_dentry->d_inode);
+ loff_t data_offset = 0;
+ loff_t pos;
+ int rc = 0;
+
+ if (offset > ecryptfs_file_size)
+ pos = ecryptfs_file_size;
+ else
+ pos = offset;
+ while (pos < (offset + size)) {
+ pgoff_t ecryptfs_page_idx = (pos >> PAGE_CACHE_SHIFT);
+ size_t start_offset_in_page = (pos & ~PAGE_CACHE_MASK);
+ size_t num_bytes = (PAGE_CACHE_SIZE - start_offset_in_page);
+ size_t total_remaining_bytes = ((offset + size) - pos);
+
+ if (num_bytes > total_remaining_bytes)
+ num_bytes = total_remaining_bytes;
+ if (pos < offset) {
+ size_t total_remaining_zeros = (offset - pos);
+
+ if (num_bytes > total_remaining_zeros)
+ num_bytes = total_remaining_zeros;
+ }
+ ecryptfs_page = ecryptfs_get_locked_page(ecryptfs_file,
+ ecryptfs_page_idx);
+ if (IS_ERR(ecryptfs_page)) {
+ rc = PTR_ERR(ecryptfs_page);
+ printk(KERN_ERR "%s: Error getting page at "
+ "index [%ld] from eCryptfs inode "
+ "mapping; rc = [%d]\n", __FUNCTION__,
+ ecryptfs_page_idx, rc);
+ goto out;
+ }
+ if (start_offset_in_page) {
+ /* Read in the page from the lower
+ * into the eCryptfs inode page cache,
+ * decrypting */
+ rc = ecryptfs_decrypt_page(ecryptfs_page);
+ if (rc) {
+ printk(KERN_ERR "%s: Error decrypting "
+ "page; rc = [%d]\n",
+ __FUNCTION__, rc);
+ ClearPageUptodate(ecryptfs_page);
+ page_cache_release(ecryptfs_page);
+ goto out;
+ }
+ }
+ ecryptfs_page_virt = kmap_atomic(ecryptfs_page, KM_USER0);
+ if (pos >= offset) {
+ memcpy(((char *)ecryptfs_page_virt
+ + start_offset_in_page),
+ (data + data_offset), num_bytes);
+ data_offset += num_bytes;
+ } else {
+ /* We are extending past the previous end of the file.
+ * Fill in zero values up to the start of where we
+ * will be writing data. */
+ memset(((char *)ecryptfs_page_virt
+ + start_offset_in_page), 0, num_bytes);
+ }
+ kunmap_atomic(ecryptfs_page_virt, KM_USER0);
+ flush_dcache_page(ecryptfs_page);
+ SetPageUptodate(ecryptfs_page);
+ unlock_page(ecryptfs_page);
+ rc = ecryptfs_encrypt_page(ecryptfs_page);
+ page_cache_release(ecryptfs_page);
+ if (rc) {
+ printk(KERN_ERR "%s: Error encrypting "
+ "page; rc = [%d]\n", __FUNCTION__, rc);
+ goto out;
+ }
+ pos += num_bytes;
+ }
+ if ((offset + size) > ecryptfs_file_size) {
+ i_size_write(ecryptfs_file->f_dentry->d_inode, (offset + size));
+ rc = ecryptfs_write_inode_size_to_metadata(
+ ecryptfs_file->f_dentry->d_inode);
+ if (rc) {
+ printk(KERN_ERR "Problem with "
+ "ecryptfs_write_inode_size_to_metadata; "
+ "rc = [%d]\n", rc);
+ goto out;
+ }
+ }
+out:
+ return rc;
+}
+
+/**
+ * ecryptfs_read_lower
+ * @data: The read data is stored here by this function
+ * @offset: Byte offset in the lower file from which to read the data
+ * @size: Number of bytes to read from @offset of the lower file and
+ * store into @data
+ * @ecryptfs_inode: The eCryptfs inode
+ *
+ * Read @size bytes of data at byte offset @offset from the lower
+ * inode into memory location @data.
+ *
+ * Returns zero on success; non-zero on error
+ */
+int ecryptfs_read_lower(char *data, loff_t offset, size_t size,
+ struct inode *ecryptfs_inode)
+{
+ struct ecryptfs_inode_info *inode_info =
+ ecryptfs_inode_to_private(ecryptfs_inode);
+ ssize_t octets_read;
+ mm_segment_t fs_save;
+ int rc = 0;
+
+ mutex_lock(&inode_info->lower_file_mutex);
+ BUG_ON(!inode_info->lower_file);
+ inode_info->lower_file->f_pos = offset;
+ fs_save = get_fs();
+ set_fs(get_ds());
+ octets_read = vfs_read(inode_info->lower_file, data, size,
+ &inode_info->lower_file->f_pos);
+ set_fs(fs_save);
+ if (octets_read < 0) {
+ printk(KERN_ERR "%s: octets_read = [%td]; "
+ "expected [%td]\n", __FUNCTION__, octets_read, size);
+ rc = -EINVAL;
+ }
+ mutex_unlock(&inode_info->lower_file_mutex);
+ return rc;
+}
+
+/**
+ * ecryptfs_read_lower_page_segment
+ * @page_for_ecryptfs: The page into which data for eCryptfs will be
+ * written
+ * @offset_in_page: Offset in @page_for_ecryptfs from which to start
+ * writing
+ * @size: The number of bytes to write into @page_for_ecryptfs
+ * @ecryptfs_inode: The eCryptfs inode
+ *
+ * Determines the byte offset in the file for the given page and
+ * offset within the page, maps the page, and makes the call to read
+ * the contents of @page_for_ecryptfs from the lower inode.
+ *
+ * Returns zero on success; non-zero otherwise
+ */
+int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs,
+ pgoff_t page_index,
+ size_t offset_in_page, size_t size,
+ struct inode *ecryptfs_inode)
+{
+ char *virt;
+ loff_t offset;
+ int rc;
+
+ offset = ((((loff_t)page_index) << PAGE_CACHE_SHIFT) + offset_in_page);
+ virt = kmap(page_for_ecryptfs);
+ rc = ecryptfs_read_lower(virt, offset, size, ecryptfs_inode);
+ kunmap(page_for_ecryptfs);
+ flush_dcache_page(page_for_ecryptfs);
+ return rc;
+}
+
+/**
+ * ecryptfs_read
+ * @data: The virtual address into which to write the data read (and
+ * possibly decrypted) from the lower file
+ * @offset: The offset in the decrypted view of the file from which to
+ * read into @data
+ * @size: The number of bytes to read into @data
+ * @ecryptfs_file: The eCryptfs file from which to read
+ *
+ * Read an arbitrary amount of data from an arbitrary location in the
+ * eCryptfs page cache. This is done on an extent-by-extent basis;
+ * individual extents are decrypted and read from the lower page
+ * cache (via VFS reads). This function takes care of all the
+ * address translation to locations in the lower filesystem.
+ *
+ * Returns zero on success; non-zero otherwise
+ */
+int ecryptfs_read(char *data, loff_t offset, size_t size,
+ struct file *ecryptfs_file)
+{
+ struct page *ecryptfs_page;
+ char *ecryptfs_page_virt;
+ loff_t ecryptfs_file_size =
+ i_size_read(ecryptfs_file->f_dentry->d_inode);
+ loff_t data_offset = 0;
+ loff_t pos;
+ int rc = 0;
+
+ if ((offset + size) > ecryptfs_file_size) {
+ rc = -EINVAL;
+ printk(KERN_ERR "%s: Attempt to read data past the end of the "
+ "file; offset = [%lld]; size = [%td]; "
+ "ecryptfs_file_size = [%lld]\n",
+ __FUNCTION__, offset, size, ecryptfs_file_size);
+ goto out;
+ }
+ pos = offset;
+ while (pos < (offset + size)) {
+ pgoff_t ecryptfs_page_idx = (pos >> PAGE_CACHE_SHIFT);
+ size_t start_offset_in_page = (pos & ~PAGE_CACHE_MASK);
+ size_t num_bytes = (PAGE_CACHE_SIZE - start_offset_in_page);
+ size_t total_remaining_bytes = ((offset + size) - pos);
+
+ if (num_bytes > total_remaining_bytes)
+ num_bytes = total_remaining_bytes;
+ ecryptfs_page = ecryptfs_get_locked_page(ecryptfs_file,
+ ecryptfs_page_idx);
+ if (IS_ERR(ecryptfs_page)) {
+ rc = PTR_ERR(ecryptfs_page);
+ printk(KERN_ERR "%s: Error getting page at "
+ "index [%ld] from eCryptfs inode "
+ "mapping; rc = [%d]\n", __FUNCTION__,
+ ecryptfs_page_idx, rc);
+ goto out;
+ }
+ rc = ecryptfs_decrypt_page(ecryptfs_page);
+ if (rc) {
+ printk(KERN_ERR "%s: Error decrypting "
+ "page; rc = [%d]\n", __FUNCTION__, rc);
+ ClearPageUptodate(ecryptfs_page);
+ page_cache_release(ecryptfs_page);
+ goto out;
+ }
+ ecryptfs_page_virt = kmap_atomic(ecryptfs_page, KM_USER0);
+ memcpy((data + data_offset),
+ ((char *)ecryptfs_page_virt + start_offset_in_page),
+ num_bytes);
+ kunmap_atomic(ecryptfs_page_virt, KM_USER0);
+ flush_dcache_page(ecryptfs_page);
+ SetPageUptodate(ecryptfs_page);
+ unlock_page(ecryptfs_page);
+ page_cache_release(ecryptfs_page);
+ pos += num_bytes;
+ data_offset += num_bytes;
+ }
+out:
+ return rc;
+}
diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c
index 7b3f0cc09a6f..f8cdab2bee3d 100644
--- a/fs/ecryptfs/super.c
+++ b/fs/ecryptfs/super.c
@@ -27,6 +27,7 @@
#include <linux/mount.h>
#include <linux/key.h>
#include <linux/seq_file.h>
+#include <linux/file.h>
#include <linux/crypto.h>
#include "ecryptfs_kernel.h"
@@ -46,15 +47,16 @@ struct kmem_cache *ecryptfs_inode_info_cache;
*/
static struct inode *ecryptfs_alloc_inode(struct super_block *sb)
{
- struct ecryptfs_inode_info *ecryptfs_inode;
+ struct ecryptfs_inode_info *inode_info;
struct inode *inode = NULL;
- ecryptfs_inode = kmem_cache_alloc(ecryptfs_inode_info_cache,
- GFP_KERNEL);
- if (unlikely(!ecryptfs_inode))
+ inode_info = kmem_cache_alloc(ecryptfs_inode_info_cache, GFP_KERNEL);
+ if (unlikely(!inode_info))
goto out;
- ecryptfs_init_crypt_stat(&ecryptfs_inode->crypt_stat);
- inode = &ecryptfs_inode->vfs_inode;
+ ecryptfs_init_crypt_stat(&inode_info->crypt_stat);
+ mutex_init(&inode_info->lower_file_mutex);
+ inode_info->lower_file = NULL;
+ inode = &inode_info->vfs_inode;
out:
return inode;
}
@@ -63,9 +65,10 @@ out:
* ecryptfs_destroy_inode
* @inode: The ecryptfs inode
*
- * This is used during the final destruction of the inode.
- * All allocation of memory related to the inode, including allocated
- * memory in the crypt_stat struct, will be released here.
+ * This is used during the final destruction of the inode. All
+ * allocation of memory related to the inode, including allocated
+ * memory in the crypt_stat struct, will be released here. This
+ * function also fput()'s the persistent file for the lower inode.
* There should be no chance that this deallocation will be missed.
*/
static void ecryptfs_destroy_inode(struct inode *inode)
@@ -73,7 +76,21 @@ static void ecryptfs_destroy_inode(struct inode *inode)
struct ecryptfs_inode_info *inode_info;
inode_info = ecryptfs_inode_to_private(inode);
- ecryptfs_destruct_crypt_stat(&inode_info->crypt_stat);
+ mutex_lock(&inode_info->lower_file_mutex);
+ if (inode_info->lower_file) {
+ struct dentry *lower_dentry =
+ inode_info->lower_file->f_dentry;
+
+ BUG_ON(!lower_dentry);
+ if (lower_dentry->d_inode) {
+ fput(inode_info->lower_file);
+ inode_info->lower_file = NULL;
+ d_drop(lower_dentry);
+ d_delete(lower_dentry);
+ }
+ }
+ mutex_unlock(&inode_info->lower_file_mutex);
+ ecryptfs_destroy_crypt_stat(&inode_info->crypt_stat);
kmem_cache_free(ecryptfs_inode_info_cache, inode_info);
}
@@ -104,7 +121,7 @@ static void ecryptfs_put_super(struct super_block *sb)
{
struct ecryptfs_sb_info *sb_info = ecryptfs_superblock_to_private(sb);
- ecryptfs_destruct_mount_crypt_stat(&sb_info->mount_crypt_stat);
+ ecryptfs_destroy_mount_crypt_stat(&sb_info->mount_crypt_stat);
kmem_cache_free(ecryptfs_sb_info_cache, sb_info);
ecryptfs_set_superblock_private(sb, NULL);
}
diff --git a/fs/efs/namei.c b/fs/efs/namei.c
index 5276b19423c1..f7f407075be1 100644
--- a/fs/efs/namei.c
+++ b/fs/efs/namei.c
@@ -10,6 +10,8 @@
#include <linux/string.h>
#include <linux/efs_fs.h>
#include <linux/smp_lock.h>
+#include <linux/exportfs.h>
+
static efs_ino_t efs_find_entry(struct inode *inode, const char *name, int len) {
struct buffer_head *bh;
@@ -75,13 +77,10 @@ struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, struct namei
return NULL;
}
-struct dentry *efs_get_dentry(struct super_block *sb, void *vobjp)
+static struct inode *efs_nfs_get_inode(struct super_block *sb, u64 ino,
+ u32 generation)
{
- __u32 *objp = vobjp;
- unsigned long ino = objp[0];
- __u32 generation = objp[1];
struct inode *inode;
- struct dentry *result;
if (ino == 0)
return ERR_PTR(-ESTALE);
@@ -91,20 +90,25 @@ struct dentry *efs_get_dentry(struct super_block *sb, void *vobjp)
if (is_bad_inode(inode) ||
(generation && inode->i_generation != generation)) {
- result = ERR_PTR(-ESTALE);
- goto out_iput;
+ iput(inode);
+ return ERR_PTR(-ESTALE);
}
- result = d_alloc_anon(inode);
- if (!result) {
- result = ERR_PTR(-ENOMEM);
- goto out_iput;
- }
- return result;
+ return inode;
+}
- out_iput:
- iput(inode);
- return result;
+struct dentry *efs_fh_to_dentry(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type)
+{
+ return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
+ efs_nfs_get_inode);
+}
+
+struct dentry *efs_fh_to_parent(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type)
+{
+ return generic_fh_to_parent(sb, fid, fh_len, fh_type,
+ efs_nfs_get_inode);
}
struct dentry *efs_get_parent(struct dentry *child)
diff --git a/fs/efs/super.c b/fs/efs/super.c
index ce4acb8ff819..c79bc627f107 100644
--- a/fs/efs/super.c
+++ b/fs/efs/super.c
@@ -69,7 +69,7 @@ static void efs_destroy_inode(struct inode *inode)
kmem_cache_free(efs_inode_cachep, INODE_INFO(inode));
}
-static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
+static void init_once(struct kmem_cache *cachep, void *foo)
{
struct efs_inode_info *ei = (struct efs_inode_info *) foo;
@@ -113,8 +113,9 @@ static const struct super_operations efs_superblock_operations = {
.remount_fs = efs_remount,
};
-static struct export_operations efs_export_ops = {
- .get_dentry = efs_get_dentry,
+static const struct export_operations efs_export_ops = {
+ .fh_to_dentry = efs_fh_to_dentry,
+ .fh_to_parent = efs_fh_to_parent,
.get_parent = efs_get_parent,
};
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 77b9953624f4..34f68f3a069a 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -325,15 +325,14 @@ static void ep_poll_safewake(struct poll_safewake *psw, wait_queue_head_t *wq)
int wake_nests = 0;
unsigned long flags;
struct task_struct *this_task = current;
- struct list_head *lsthead = &psw->wake_task_list, *lnk;
+ struct list_head *lsthead = &psw->wake_task_list;
struct wake_task_node *tncur;
struct wake_task_node tnode;
spin_lock_irqsave(&psw->lock, flags);
/* Try to see if the current task is already inside this wakeup call */
- list_for_each(lnk, lsthead) {
- tncur = list_entry(lnk, struct wake_task_node, llink);
+ list_for_each_entry(tncur, lsthead, llink) {
if (tncur->wq == wq ||
(tncur->task == this_task && ++wake_nests > EP_MAX_POLLWAKE_NESTS)) {
@@ -463,7 +462,7 @@ static void ep_free(struct eventpoll *ep)
* holding "epmutex" we can be sure that no file cleanup code will hit
* us during this operation. So we can avoid the lock on "ep->lock".
*/
- while ((rbp = rb_first(&ep->rbr)) != 0) {
+ while ((rbp = rb_first(&ep->rbr)) != NULL) {
epi = rb_entry(rbp, struct epitem, rbn);
ep_remove(ep, epi);
}
diff --git a/fs/exec.c b/fs/exec.c
index 073b0b8c6d05..4ccaaa4b13b2 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -29,6 +29,7 @@
#include <linux/stat.h>
#include <linux/fcntl.h>
#include <linux/smp_lock.h>
+#include <linux/string.h>
#include <linux/init.h>
#include <linux/pagemap.h>
#include <linux/highmem.h>
@@ -63,52 +64,28 @@ int core_uses_pid;
char core_pattern[CORENAME_MAX_SIZE] = "core";
int suid_dumpable = 0;
-EXPORT_SYMBOL(suid_dumpable);
/* The maximal length of core_pattern is also specified in sysctl.c */
-static struct linux_binfmt *formats;
+static LIST_HEAD(formats);
static DEFINE_RWLOCK(binfmt_lock);
int register_binfmt(struct linux_binfmt * fmt)
{
- struct linux_binfmt ** tmp = &formats;
-
if (!fmt)
return -EINVAL;
- if (fmt->next)
- return -EBUSY;
write_lock(&binfmt_lock);
- while (*tmp) {
- if (fmt == *tmp) {
- write_unlock(&binfmt_lock);
- return -EBUSY;
- }
- tmp = &(*tmp)->next;
- }
- fmt->next = formats;
- formats = fmt;
+ list_add(&fmt->lh, &formats);
write_unlock(&binfmt_lock);
return 0;
}
EXPORT_SYMBOL(register_binfmt);
-int unregister_binfmt(struct linux_binfmt * fmt)
+void unregister_binfmt(struct linux_binfmt * fmt)
{
- struct linux_binfmt ** tmp = &formats;
-
write_lock(&binfmt_lock);
- while (*tmp) {
- if (fmt == *tmp) {
- *tmp = fmt->next;
- fmt->next = NULL;
- write_unlock(&binfmt_lock);
- return 0;
- }
- tmp = &(*tmp)->next;
- }
+ list_del(&fmt->lh);
write_unlock(&binfmt_lock);
- return -EINVAL;
}
EXPORT_SYMBOL(unregister_binfmt);
@@ -134,9 +111,6 @@ asmlinkage long sys_uselib(const char __user * library)
if (error)
goto out;
- error = -EACCES;
- if (nd.mnt->mnt_flags & MNT_NOEXEC)
- goto exit;
error = -EINVAL;
if (!S_ISREG(nd.dentry->d_inode->i_mode))
goto exit;
@@ -155,7 +129,7 @@ asmlinkage long sys_uselib(const char __user * library)
struct linux_binfmt * fmt;
read_lock(&binfmt_lock);
- for (fmt = formats ; fmt ; fmt = fmt->next) {
+ list_for_each_entry(fmt, &formats, lh) {
if (!fmt->load_shlib)
continue;
if (!try_module_get(fmt->module))
@@ -260,7 +234,7 @@ static int __bprm_mm_init(struct linux_binprm *bprm)
vma->vm_start = vma->vm_end - PAGE_SIZE;
vma->vm_flags = VM_STACK_FLAGS;
- vma->vm_page_prot = protection_map[vma->vm_flags & 0x7];
+ vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
err = insert_vm_struct(mm, vma);
if (err) {
up_write(&mm->mmap_sem);
@@ -680,8 +654,7 @@ struct file *open_exec(const char *name)
if (!err) {
struct inode *inode = nd.dentry->d_inode;
file = ERR_PTR(-EACCES);
- if (!(nd.mnt->mnt_flags & MNT_NOEXEC) &&
- S_ISREG(inode->i_mode)) {
+ if (S_ISREG(inode->i_mode)) {
int err = vfs_permission(&nd, MAY_EXEC);
file = ERR_PTR(err);
if (!err) {
@@ -773,24 +746,11 @@ static int exec_mmap(struct mm_struct *mm)
static int de_thread(struct task_struct *tsk)
{
struct signal_struct *sig = tsk->signal;
- struct sighand_struct *newsighand, *oldsighand = tsk->sighand;
+ struct sighand_struct *oldsighand = tsk->sighand;
spinlock_t *lock = &oldsighand->siglock;
struct task_struct *leader = NULL;
int count;
- /*
- * If we don't share sighandlers, then we aren't sharing anything
- * and we can just re-use it all.
- */
- if (atomic_read(&oldsighand->count) <= 1) {
- exit_itimers(sig);
- return 0;
- }
-
- newsighand = kmem_cache_alloc(sighand_cachep, GFP_KERNEL);
- if (!newsighand)
- return -ENOMEM;
-
if (thread_group_empty(tsk))
goto no_thread_group;
@@ -807,7 +767,6 @@ static int de_thread(struct task_struct *tsk)
*/
spin_unlock_irq(lock);
read_unlock(&tasklist_lock);
- kmem_cache_free(sighand_cachep, newsighand);
return -EAGAIN;
}
@@ -816,8 +775,8 @@ static int de_thread(struct task_struct *tsk)
* Reparenting needs write_lock on tasklist_lock,
* so it is safe to do it under read_lock.
*/
- if (unlikely(tsk->group_leader == child_reaper(tsk)))
- tsk->nsproxy->pid_ns->child_reaper = tsk;
+ if (unlikely(tsk->group_leader == task_child_reaper(tsk)))
+ task_active_pid_ns(tsk)->child_reaper = tsk;
zap_other_threads(tsk);
read_unlock(&tasklist_lock);
@@ -841,16 +800,15 @@ static int de_thread(struct task_struct *tsk)
hrtimer_restart(&sig->real_timer);
spin_lock_irq(lock);
}
+
+ sig->notify_count = count;
+ sig->group_exit_task = tsk;
while (atomic_read(&sig->count) > count) {
- sig->group_exit_task = tsk;
- sig->notify_count = count;
__set_current_state(TASK_UNINTERRUPTIBLE);
spin_unlock_irq(lock);
schedule();
spin_lock_irq(lock);
}
- sig->group_exit_task = NULL;
- sig->notify_count = 0;
spin_unlock_irq(lock);
/*
@@ -859,14 +817,17 @@ static int de_thread(struct task_struct *tsk)
* and to assume its PID:
*/
if (!thread_group_leader(tsk)) {
- /*
- * Wait for the thread group leader to be a zombie.
- * It should already be zombie at this point, most
- * of the time.
- */
leader = tsk->group_leader;
- while (leader->exit_state != EXIT_ZOMBIE)
- yield();
+
+ sig->notify_count = -1;
+ for (;;) {
+ write_lock_irq(&tasklist_lock);
+ if (likely(leader->exit_state))
+ break;
+ __set_current_state(TASK_UNINTERRUPTIBLE);
+ write_unlock_irq(&tasklist_lock);
+ schedule();
+ }
/*
* The only record we have of the real-time age of a
@@ -880,10 +841,8 @@ static int de_thread(struct task_struct *tsk)
*/
tsk->start_time = leader->start_time;
- write_lock_irq(&tasklist_lock);
-
- BUG_ON(leader->tgid != tsk->tgid);
- BUG_ON(tsk->pid == tsk->tgid);
+ BUG_ON(!same_thread_group(leader, tsk));
+ BUG_ON(has_group_leader_pid(tsk));
/*
* An exec() starts a new thread group with the
* TGID of the previous thread group. Rehash the
@@ -898,7 +857,7 @@ static int de_thread(struct task_struct *tsk)
*/
detach_pid(tsk, PIDTYPE_PID);
tsk->pid = leader->pid;
- attach_pid(tsk, PIDTYPE_PID, find_pid(tsk->pid));
+ attach_pid(tsk, PIDTYPE_PID, task_pid(leader));
transfer_pid(leader, tsk, PIDTYPE_PGID);
transfer_pid(leader, tsk, PIDTYPE_SID);
list_replace_rcu(&leader->tasks, &tsk->tasks);
@@ -914,6 +873,8 @@ static int de_thread(struct task_struct *tsk)
write_unlock_irq(&tasklist_lock);
}
+ sig->group_exit_task = NULL;
+ sig->notify_count = 0;
/*
* There may be one thread left which is just exiting,
* but it's safe to stop telling the group to kill themselves.
@@ -925,29 +886,23 @@ no_thread_group:
if (leader)
release_task(leader);
- if (atomic_read(&oldsighand->count) == 1) {
+ if (atomic_read(&oldsighand->count) != 1) {
+ struct sighand_struct *newsighand;
/*
- * Now that we nuked the rest of the thread group,
- * it turns out we are not sharing sighand any more either.
- * So we can just keep it.
- */
- kmem_cache_free(sighand_cachep, newsighand);
- } else {
- /*
- * Move our state over to newsighand and switch it in.
+ * This ->sighand is shared with the CLONE_SIGHAND
+ * but not CLONE_THREAD task, switch to the new one.
*/
+ newsighand = kmem_cache_alloc(sighand_cachep, GFP_KERNEL);
+ if (!newsighand)
+ return -ENOMEM;
+
atomic_set(&newsighand->count, 1);
memcpy(newsighand->action, oldsighand->action,
sizeof(newsighand->action));
write_lock_irq(&tasklist_lock);
spin_lock(&oldsighand->siglock);
- spin_lock_nested(&newsighand->siglock, SINGLE_DEPTH_NESTING);
-
rcu_assign_pointer(tsk->sighand, newsighand);
- recalc_sigpending();
-
- spin_unlock(&newsighand->siglock);
spin_unlock(&oldsighand->siglock);
write_unlock_irq(&tasklist_lock);
@@ -957,12 +912,11 @@ no_thread_group:
BUG_ON(!thread_group_leader(tsk));
return 0;
}
-
+
/*
* These functions flushes out all traces of the currently running executable
* so that a new one can be started
*/
-
static void flush_old_files(struct files_struct * files)
{
long j = -1;
@@ -1284,7 +1238,7 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
retval = -ENOENT;
for (try=0; try<2; try++) {
read_lock(&binfmt_lock);
- for (fmt = formats ; fmt ; fmt = fmt->next) {
+ list_for_each_entry(fmt, &formats, lh) {
int (*fn)(struct linux_binprm *, struct pt_regs *) = fmt->load_binary;
if (!fn)
continue;
@@ -1479,7 +1433,7 @@ static int format_corename(char *corename, const char *pattern, long signr)
case 'p':
pid_in_pattern = 1;
rc = snprintf(out_ptr, out_end - out_ptr,
- "%d", current->tgid);
+ "%d", task_tgid_vnr(current));
if (rc > out_end - out_ptr)
goto out;
out_ptr += rc;
@@ -1537,6 +1491,14 @@ static int format_corename(char *corename, const char *pattern, long signr)
goto out;
out_ptr += rc;
break;
+ /* core limit size */
+ case 'c':
+ rc = snprintf(out_ptr, out_end - out_ptr,
+ "%lu", current->signal->rlim[RLIMIT_CORE].rlim_cur);
+ if (rc > out_end - out_ptr)
+ goto out;
+ out_ptr += rc;
+ break;
default:
break;
}
@@ -1551,7 +1513,7 @@ static int format_corename(char *corename, const char *pattern, long signr)
if (!ispipe && !pid_in_pattern
&& (core_uses_pid || atomic_read(&current->mm->mm_users) != 1)) {
rc = snprintf(out_ptr, out_end - out_ptr,
- ".%d", current->tgid);
+ ".%d", task_tgid_vnr(current));
if (rc > out_end - out_ptr)
goto out;
out_ptr += rc;
@@ -1699,7 +1661,6 @@ void set_dumpable(struct mm_struct *mm, int value)
break;
}
}
-EXPORT_SYMBOL_GPL(set_dumpable);
int get_dumpable(struct mm_struct *mm)
{
@@ -1720,6 +1681,10 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
int fsuid = current->fsuid;
int flag = 0;
int ispipe = 0;
+ unsigned long core_limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
+ char **helper_argv = NULL;
+ int helper_argc = 0;
+ char *delimit;
audit_core_dumps(signr);
@@ -1727,7 +1692,10 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
if (!binfmt || !binfmt->core_dump)
goto fail;
down_write(&mm->mmap_sem);
- if (!get_dumpable(mm)) {
+ /*
+ * If another thread got here first, or we are not dumpable, bail out.
+ */
+ if (mm->core_waiters || !get_dumpable(mm)) {
up_write(&mm->mmap_sem);
goto fail;
}
@@ -1741,7 +1709,6 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
flag = O_EXCL; /* Stop rewrite attacks */
current->fsuid = 0; /* Dump root private */
}
- set_dumpable(mm, 0);
retval = coredump_wait(exit_code);
if (retval < 0)
@@ -1753,9 +1720,6 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
*/
clear_thread_flag(TIF_SIGPENDING);
- if (current->signal->rlim[RLIMIT_CORE].rlim_cur < binfmt->min_coredump)
- goto fail_unlock;
-
/*
* lock_kernel() because format_corename() is controlled by sysctl, which
* uses lock_kernel()
@@ -1763,9 +1727,39 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
lock_kernel();
ispipe = format_corename(corename, core_pattern, signr);
unlock_kernel();
+ /*
+ * Don't bother to check the RLIMIT_CORE value if core_pattern points
+ * to a pipe. Since we're not writing directly to the filesystem
+ * RLIMIT_CORE doesn't really apply, as no actual core file will be
+ * created unless the pipe reader choses to write out the core file
+ * at which point file size limits and permissions will be imposed
+ * as it does with any other process
+ */
+ if ((!ispipe) && (core_limit < binfmt->min_coredump))
+ goto fail_unlock;
+
if (ispipe) {
+ helper_argv = argv_split(GFP_KERNEL, corename+1, &helper_argc);
+ /* Terminate the string before the first option */
+ delimit = strchr(corename, ' ');
+ if (delimit)
+ *delimit = '\0';
+ delimit = strrchr(helper_argv[0], '/');
+ if (delimit)
+ delimit++;
+ else
+ delimit = helper_argv[0];
+ if (!strcmp(delimit, current->comm)) {
+ printk(KERN_NOTICE "Recursive core dump detected, "
+ "aborting\n");
+ goto fail_unlock;
+ }
+
+ core_limit = RLIM_INFINITY;
+
/* SIGPIPE can happen, but it's just never processed */
- if(call_usermodehelper_pipe(corename+1, NULL, NULL, &file)) {
+ if (call_usermodehelper_pipe(corename+1, helper_argv, NULL,
+ &file)) {
printk(KERN_INFO "Core dump to %s pipe failed\n",
corename);
goto fail_unlock;
@@ -1793,13 +1787,16 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
if (!ispipe && do_truncate(file->f_path.dentry, 0, 0, file) != 0)
goto close_fail;
- retval = binfmt->core_dump(signr, regs, file);
+ retval = binfmt->core_dump(signr, regs, file, core_limit);
if (retval)
current->signal->group_exit_code |= 0x80;
close_fail:
filp_close(file, NULL);
fail_unlock:
+ if (helper_argv)
+ argv_free(helper_argv);
+
current->fsuid = fsuid;
complete_all(&mm->core_done);
fail:
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
index 8adb32a9387a..109ab5e44eca 100644
--- a/fs/exportfs/expfs.c
+++ b/fs/exportfs/expfs.c
@@ -1,4 +1,13 @@
-
+/*
+ * Copyright (C) Neil Brown 2002
+ * Copyright (C) Christoph Hellwig 2007
+ *
+ * This file contains the code mapping from inodes to NFS file handles,
+ * and for mapping back from file handles to dentries.
+ *
+ * For details on why we do all the strange and hairy things in here
+ * take a look at Documentation/filesystems/Exporting.
+ */
#include <linux/exportfs.h>
#include <linux/fs.h>
#include <linux/file.h>
@@ -9,32 +18,19 @@
#define dprintk(fmt, args...) do{}while(0)
-static int get_name(struct dentry *dentry, char *name,
+static int get_name(struct vfsmount *mnt, struct dentry *dentry, char *name,
struct dentry *child);
-static struct dentry *exportfs_get_dentry(struct super_block *sb, void *obj)
+static int exportfs_get_name(struct vfsmount *mnt, struct dentry *dir,
+ char *name, struct dentry *child)
{
- struct dentry *result = ERR_PTR(-ESTALE);
-
- if (sb->s_export_op->get_dentry) {
- result = sb->s_export_op->get_dentry(sb, obj);
- if (!result)
- result = ERR_PTR(-ESTALE);
- }
-
- return result;
-}
-
-static int exportfs_get_name(struct dentry *dir, char *name,
- struct dentry *child)
-{
- struct export_operations *nop = dir->d_sb->s_export_op;
+ const struct export_operations *nop = dir->d_sb->s_export_op;
if (nop->get_name)
return nop->get_name(dir, name, child);
else
- return get_name(dir, name, child);
+ return get_name(mnt, dir, name, child);
}
/*
@@ -98,7 +94,7 @@ find_disconnected_root(struct dentry *dentry)
* It may already be, as the flag isn't always updated when connection happens.
*/
static int
-reconnect_path(struct super_block *sb, struct dentry *target_dir)
+reconnect_path(struct vfsmount *mnt, struct dentry *target_dir)
{
char nbuf[NAME_MAX+1];
int noprogress = 0;
@@ -121,7 +117,7 @@ reconnect_path(struct super_block *sb, struct dentry *target_dir)
pd->d_flags &= ~DCACHE_DISCONNECTED;
spin_unlock(&pd->d_lock);
noprogress = 0;
- } else if (pd == sb->s_root) {
+ } else if (pd == mnt->mnt_sb->s_root) {
printk(KERN_ERR "export: Eeek filesystem root is not connected, impossible\n");
spin_lock(&pd->d_lock);
pd->d_flags &= ~DCACHE_DISCONNECTED;
@@ -147,8 +143,8 @@ reconnect_path(struct super_block *sb, struct dentry *target_dir)
struct dentry *npd;
mutex_lock(&pd->d_inode->i_mutex);
- if (sb->s_export_op->get_parent)
- ppd = sb->s_export_op->get_parent(pd);
+ if (mnt->mnt_sb->s_export_op->get_parent)
+ ppd = mnt->mnt_sb->s_export_op->get_parent(pd);
mutex_unlock(&pd->d_inode->i_mutex);
if (IS_ERR(ppd)) {
@@ -161,7 +157,7 @@ reconnect_path(struct super_block *sb, struct dentry *target_dir)
dprintk("%s: find name of %lu in %lu\n", __FUNCTION__,
pd->d_inode->i_ino, ppd->d_inode->i_ino);
- err = exportfs_get_name(ppd, nbuf, pd);
+ err = exportfs_get_name(mnt, ppd, nbuf, pd);
if (err) {
dput(ppd);
dput(pd);
@@ -214,125 +210,6 @@ reconnect_path(struct super_block *sb, struct dentry *target_dir)
return 0;
}
-/**
- * find_exported_dentry - helper routine to implement export_operations->decode_fh
- * @sb: The &super_block identifying the filesystem
- * @obj: An opaque identifier of the object to be found - passed to
- * get_inode
- * @parent: An optional opqaue identifier of the parent of the object.
- * @acceptable: A function used to test possible &dentries to see if they are
- * acceptable
- * @context: A parameter to @acceptable so that it knows on what basis to
- * judge.
- *
- * find_exported_dentry is the central helper routine to enable file systems
- * to provide the decode_fh() export_operation. It's main task is to take
- * an &inode, find or create an appropriate &dentry structure, and possibly
- * splice this into the dcache in the correct place.
- *
- * The decode_fh() operation provided by the filesystem should call
- * find_exported_dentry() with the same parameters that it received except
- * that instead of the file handle fragment, pointers to opaque identifiers
- * for the object and optionally its parent are passed. The default decode_fh
- * routine passes one pointer to the start of the filehandle fragment, and
- * one 8 bytes into the fragment. It is expected that most filesystems will
- * take this approach, though the offset to the parent identifier may well be
- * different.
- *
- * find_exported_dentry() will call get_dentry to get an dentry pointer from
- * the file system. If any &dentry in the d_alias list is acceptable, it will
- * be returned. Otherwise find_exported_dentry() will attempt to splice a new
- * &dentry into the dcache using get_name() and get_parent() to find the
- * appropriate place.
- */
-
-struct dentry *
-find_exported_dentry(struct super_block *sb, void *obj, void *parent,
- int (*acceptable)(void *context, struct dentry *de),
- void *context)
-{
- struct dentry *result, *alias;
- int err = -ESTALE;
-
- /*
- * Attempt to find the inode.
- */
- result = exportfs_get_dentry(sb, obj);
- if (IS_ERR(result))
- return result;
-
- if (S_ISDIR(result->d_inode->i_mode)) {
- if (!(result->d_flags & DCACHE_DISCONNECTED)) {
- if (acceptable(context, result))
- return result;
- err = -EACCES;
- goto err_result;
- }
-
- err = reconnect_path(sb, result);
- if (err)
- goto err_result;
- } else {
- struct dentry *target_dir, *nresult;
- char nbuf[NAME_MAX+1];
-
- alias = find_acceptable_alias(result, acceptable, context);
- if (alias)
- return alias;
-
- if (parent == NULL)
- goto err_result;
-
- target_dir = exportfs_get_dentry(sb,parent);
- if (IS_ERR(target_dir)) {
- err = PTR_ERR(target_dir);
- goto err_result;
- }
-
- err = reconnect_path(sb, target_dir);
- if (err) {
- dput(target_dir);
- goto err_result;
- }
-
- /*
- * As we weren't after a directory, have one more step to go.
- */
- err = exportfs_get_name(target_dir, nbuf, result);
- if (!err) {
- mutex_lock(&target_dir->d_inode->i_mutex);
- nresult = lookup_one_len(nbuf, target_dir,
- strlen(nbuf));
- mutex_unlock(&target_dir->d_inode->i_mutex);
- if (!IS_ERR(nresult)) {
- if (nresult->d_inode) {
- dput(result);
- result = nresult;
- } else
- dput(nresult);
- }
- }
- dput(target_dir);
- }
-
- alias = find_acceptable_alias(result, acceptable, context);
- if (alias)
- return alias;
-
- /* drat - I just cannot find anything acceptable */
- dput(result);
- /* It might be justifiable to return ESTALE here,
- * but the filehandle at-least looks reasonable good
- * and it may just be a permission problem, so returning
- * -EACCESS is safer
- */
- return ERR_PTR(-EACCES);
-
- err_result:
- dput(result);
- return ERR_PTR(err);
-}
-
struct getdents_callback {
char *name; /* name that was found. It already points to a
buffer NAME_MAX+1 is size */
@@ -370,8 +247,8 @@ static int filldir_one(void * __buf, const char * name, int len,
* calls readdir on the parent until it finds an entry with
* the same inode number as the child, and returns that.
*/
-static int get_name(struct dentry *dentry, char *name,
- struct dentry *child)
+static int get_name(struct vfsmount *mnt, struct dentry *dentry,
+ char *name, struct dentry *child)
{
struct inode *dir = dentry->d_inode;
int error;
@@ -387,7 +264,7 @@ static int get_name(struct dentry *dentry, char *name,
/*
* Open the directory ...
*/
- file = dentry_open(dget(dentry), NULL, O_RDONLY);
+ file = dentry_open(dget(dentry), mntget(mnt), O_RDONLY);
error = PTR_ERR(file);
if (IS_ERR(file))
goto out;
@@ -434,100 +311,177 @@ out:
* can be used to check that it is still valid. It places them in the
* filehandle fragment where export_decode_fh expects to find them.
*/
-static int export_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
- int connectable)
+static int export_encode_fh(struct dentry *dentry, struct fid *fid,
+ int *max_len, int connectable)
{
struct inode * inode = dentry->d_inode;
int len = *max_len;
- int type = 1;
+ int type = FILEID_INO32_GEN;
if (len < 2 || (connectable && len < 4))
return 255;
len = 2;
- fh[0] = inode->i_ino;
- fh[1] = inode->i_generation;
+ fid->i32.ino = inode->i_ino;
+ fid->i32.gen = inode->i_generation;
if (connectable && !S_ISDIR(inode->i_mode)) {
struct inode *parent;
spin_lock(&dentry->d_lock);
parent = dentry->d_parent->d_inode;
- fh[2] = parent->i_ino;
- fh[3] = parent->i_generation;
+ fid->i32.parent_ino = parent->i_ino;
+ fid->i32.parent_gen = parent->i_generation;
spin_unlock(&dentry->d_lock);
len = 4;
- type = 2;
+ type = FILEID_INO32_GEN_PARENT;
}
*max_len = len;
return type;
}
-
-/**
- * export_decode_fh - default export_operations->decode_fh function
- * @sb: The superblock
- * @fh: pointer to the file handle fragment
- * @fh_len: length of file handle fragment
- * @acceptable: function for testing acceptability of dentrys
- * @context: context for @acceptable
- *
- * This is the default decode_fh() function.
- * a fileid_type of 1 indicates that the filehandlefragment
- * just contains an object identifier understood by get_dentry.
- * a fileid_type of 2 says that there is also a directory
- * identifier 8 bytes in to the filehandlefragement.
- */
-static struct dentry *export_decode_fh(struct super_block *sb, __u32 *fh, int fh_len,
- int fileid_type,
- int (*acceptable)(void *context, struct dentry *de),
- void *context)
-{
- __u32 parent[2];
- parent[0] = parent[1] = 0;
- if (fh_len < 2 || fileid_type > 2)
- return NULL;
- if (fileid_type == 2) {
- if (fh_len > 2) parent[0] = fh[2];
- if (fh_len > 3) parent[1] = fh[3];
- }
- return find_exported_dentry(sb, fh, parent,
- acceptable, context);
-}
-
-int exportfs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
+int exportfs_encode_fh(struct dentry *dentry, struct fid *fid, int *max_len,
int connectable)
{
- struct export_operations *nop = dentry->d_sb->s_export_op;
+ const struct export_operations *nop = dentry->d_sb->s_export_op;
int error;
if (nop->encode_fh)
- error = nop->encode_fh(dentry, fh, max_len, connectable);
+ error = nop->encode_fh(dentry, fid->raw, max_len, connectable);
else
- error = export_encode_fh(dentry, fh, max_len, connectable);
+ error = export_encode_fh(dentry, fid, max_len, connectable);
return error;
}
EXPORT_SYMBOL_GPL(exportfs_encode_fh);
-struct dentry *exportfs_decode_fh(struct vfsmount *mnt, __u32 *fh, int fh_len,
- int fileid_type, int (*acceptable)(void *, struct dentry *),
- void *context)
+struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid,
+ int fh_len, int fileid_type,
+ int (*acceptable)(void *, struct dentry *), void *context)
{
- struct export_operations *nop = mnt->mnt_sb->s_export_op;
- struct dentry *result;
+ const struct export_operations *nop = mnt->mnt_sb->s_export_op;
+ struct dentry *result, *alias;
+ int err;
- if (nop->decode_fh) {
- result = nop->decode_fh(mnt->mnt_sb, fh, fh_len, fileid_type,
- acceptable, context);
+ /*
+ * Try to get any dentry for the given file handle from the filesystem.
+ */
+ result = nop->fh_to_dentry(mnt->mnt_sb, fid, fh_len, fileid_type);
+ if (!result)
+ result = ERR_PTR(-ESTALE);
+ if (IS_ERR(result))
+ return result;
+
+ if (S_ISDIR(result->d_inode->i_mode)) {
+ /*
+ * This request is for a directory.
+ *
+ * On the positive side there is only one dentry for each
+ * directory inode. On the negative side this implies that we
+ * to ensure our dentry is connected all the way up to the
+ * filesystem root.
+ */
+ if (result->d_flags & DCACHE_DISCONNECTED) {
+ err = reconnect_path(mnt, result);
+ if (err)
+ goto err_result;
+ }
+
+ if (!acceptable(context, result)) {
+ err = -EACCES;
+ goto err_result;
+ }
+
+ return result;
} else {
- result = export_decode_fh(mnt->mnt_sb, fh, fh_len, fileid_type,
- acceptable, context);
+ /*
+ * It's not a directory. Life is a little more complicated.
+ */
+ struct dentry *target_dir, *nresult;
+ char nbuf[NAME_MAX+1];
+
+ /*
+ * See if either the dentry we just got from the filesystem
+ * or any alias for it is acceptable. This is always true
+ * if this filesystem is exported without the subtreecheck
+ * option. If the filesystem is exported with the subtree
+ * check option there's a fair chance we need to look at
+ * the parent directory in the file handle and make sure
+ * it's connected to the filesystem root.
+ */
+ alias = find_acceptable_alias(result, acceptable, context);
+ if (alias)
+ return alias;
+
+ /*
+ * Try to extract a dentry for the parent directory from the
+ * file handle. If this fails we'll have to give up.
+ */
+ err = -ESTALE;
+ if (!nop->fh_to_parent)
+ goto err_result;
+
+ target_dir = nop->fh_to_parent(mnt->mnt_sb, fid,
+ fh_len, fileid_type);
+ if (!target_dir)
+ goto err_result;
+ err = PTR_ERR(target_dir);
+ if (IS_ERR(target_dir))
+ goto err_result;
+
+ /*
+ * And as usual we need to make sure the parent directory is
+ * connected to the filesystem root. The VFS really doesn't
+ * like disconnected directories..
+ */
+ err = reconnect_path(mnt, target_dir);
+ if (err) {
+ dput(target_dir);
+ goto err_result;
+ }
+
+ /*
+ * Now that we've got both a well-connected parent and a
+ * dentry for the inode we're after, make sure that our
+ * inode is actually connected to the parent.
+ */
+ err = exportfs_get_name(mnt, target_dir, nbuf, result);
+ if (!err) {
+ mutex_lock(&target_dir->d_inode->i_mutex);
+ nresult = lookup_one_len(nbuf, target_dir,
+ strlen(nbuf));
+ mutex_unlock(&target_dir->d_inode->i_mutex);
+ if (!IS_ERR(nresult)) {
+ if (nresult->d_inode) {
+ dput(result);
+ result = nresult;
+ } else
+ dput(nresult);
+ }
+ }
+
+ /*
+ * At this point we are done with the parent, but it's pinned
+ * by the child dentry anyway.
+ */
+ dput(target_dir);
+
+ /*
+ * And finally make sure the dentry is actually acceptable
+ * to NFSD.
+ */
+ alias = find_acceptable_alias(result, acceptable, context);
+ if (!alias) {
+ err = -EACCES;
+ goto err_result;
+ }
+
+ return alias;
}
- return result;
+ err_result:
+ dput(result);
+ return ERR_PTR(err);
}
EXPORT_SYMBOL_GPL(exportfs_decode_fh);
-EXPORT_SYMBOL(find_exported_dentry);
-
MODULE_LICENSE("GPL");
diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c
index baf71dd721fa..377ad172d74b 100644
--- a/fs/ext2/balloc.c
+++ b/fs/ext2/balloc.c
@@ -94,70 +94,17 @@ error_out:
return bh;
}
-/*
- * Set sb->s_dirt here because the superblock was "logically" altered. We
- * need to recalculate its free blocks count and flush it out.
- */
-static int reserve_blocks(struct super_block *sb, int count)
-{
- struct ext2_sb_info *sbi = EXT2_SB(sb);
- struct ext2_super_block *es = sbi->s_es;
- unsigned free_blocks;
- unsigned root_blocks;
-
- free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
- root_blocks = le32_to_cpu(es->s_r_blocks_count);
-
- if (free_blocks < count)
- count = free_blocks;
-
- if (free_blocks < root_blocks + count && !capable(CAP_SYS_RESOURCE) &&
- sbi->s_resuid != current->fsuid &&
- (sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) {
- /*
- * We are too close to reserve and we are not privileged.
- * Can we allocate anything at all?
- */
- if (free_blocks > root_blocks)
- count = free_blocks - root_blocks;
- else
- return 0;
- }
-
- percpu_counter_mod(&sbi->s_freeblocks_counter, -count);
- sb->s_dirt = 1;
- return count;
-}
-
static void release_blocks(struct super_block *sb, int count)
{
if (count) {
struct ext2_sb_info *sbi = EXT2_SB(sb);
- percpu_counter_mod(&sbi->s_freeblocks_counter, count);
+ percpu_counter_add(&sbi->s_freeblocks_counter, count);
sb->s_dirt = 1;
}
}
-static int group_reserve_blocks(struct ext2_sb_info *sbi, int group_no,
- struct ext2_group_desc *desc, struct buffer_head *bh, int count)
-{
- unsigned free_blocks;
-
- if (!desc->bg_free_blocks_count)
- return 0;
-
- spin_lock(sb_bgl_lock(sbi, group_no));
- free_blocks = le16_to_cpu(desc->bg_free_blocks_count);
- if (free_blocks < count)
- count = free_blocks;
- desc->bg_free_blocks_count = cpu_to_le16(free_blocks - count);
- spin_unlock(sb_bgl_lock(sbi, group_no));
- mark_buffer_dirty(bh);
- return count;
-}
-
-static void group_release_blocks(struct super_block *sb, int group_no,
+static void group_adjust_blocks(struct super_block *sb, int group_no,
struct ext2_group_desc *desc, struct buffer_head *bh, int count)
{
if (count) {
@@ -173,7 +120,306 @@ static void group_release_blocks(struct super_block *sb, int group_no,
}
}
-/* Free given blocks, update quota and i_blocks field */
+/*
+ * The reservation window structure operations
+ * --------------------------------------------
+ * Operations include:
+ * dump, find, add, remove, is_empty, find_next_reservable_window, etc.
+ *
+ * We use a red-black tree to represent per-filesystem reservation
+ * windows.
+ *
+ */
+
+/**
+ * __rsv_window_dump() -- Dump the filesystem block allocation reservation map
+ * @rb_root: root of per-filesystem reservation rb tree
+ * @verbose: verbose mode
+ * @fn: function which wishes to dump the reservation map
+ *
+ * If verbose is turned on, it will print the whole block reservation
+ * windows(start, end). Otherwise, it will only print out the "bad" windows,
+ * those windows that overlap with their immediate neighbors.
+ */
+#if 1
+static void __rsv_window_dump(struct rb_root *root, int verbose,
+ const char *fn)
+{
+ struct rb_node *n;
+ struct ext2_reserve_window_node *rsv, *prev;
+ int bad;
+
+restart:
+ n = rb_first(root);
+ bad = 0;
+ prev = NULL;
+
+ printk("Block Allocation Reservation Windows Map (%s):\n", fn);
+ while (n) {
+ rsv = rb_entry(n, struct ext2_reserve_window_node, rsv_node);
+ if (verbose)
+ printk("reservation window 0x%p "
+ "start: %lu, end: %lu\n",
+ rsv, rsv->rsv_start, rsv->rsv_end);
+ if (rsv->rsv_start && rsv->rsv_start >= rsv->rsv_end) {
+ printk("Bad reservation %p (start >= end)\n",
+ rsv);
+ bad = 1;
+ }
+ if (prev && prev->rsv_end >= rsv->rsv_start) {
+ printk("Bad reservation %p (prev->end >= start)\n",
+ rsv);
+ bad = 1;
+ }
+ if (bad) {
+ if (!verbose) {
+ printk("Restarting reservation walk in verbose mode\n");
+ verbose = 1;
+ goto restart;
+ }
+ }
+ n = rb_next(n);
+ prev = rsv;
+ }
+ printk("Window map complete.\n");
+ if (bad)
+ BUG();
+}
+#define rsv_window_dump(root, verbose) \
+ __rsv_window_dump((root), (verbose), __FUNCTION__)
+#else
+#define rsv_window_dump(root, verbose) do {} while (0)
+#endif
+
+/**
+ * goal_in_my_reservation()
+ * @rsv: inode's reservation window
+ * @grp_goal: given goal block relative to the allocation block group
+ * @group: the current allocation block group
+ * @sb: filesystem super block
+ *
+ * Test if the given goal block (group relative) is within the file's
+ * own block reservation window range.
+ *
+ * If the reservation window is outside the goal allocation group, return 0;
+ * grp_goal (given goal block) could be -1, which means no specific
+ * goal block. In this case, always return 1.
+ * If the goal block is within the reservation window, return 1;
+ * otherwise, return 0;
+ */
+static int
+goal_in_my_reservation(struct ext2_reserve_window *rsv, ext2_grpblk_t grp_goal,
+ unsigned int group, struct super_block * sb)
+{
+ ext2_fsblk_t group_first_block, group_last_block;
+
+ group_first_block = ext2_group_first_block_no(sb, group);
+ group_last_block = group_first_block + EXT2_BLOCKS_PER_GROUP(sb) - 1;
+
+ if ((rsv->_rsv_start > group_last_block) ||
+ (rsv->_rsv_end < group_first_block))
+ return 0;
+ if ((grp_goal >= 0) && ((grp_goal + group_first_block < rsv->_rsv_start)
+ || (grp_goal + group_first_block > rsv->_rsv_end)))
+ return 0;
+ return 1;
+}
+
+/**
+ * search_reserve_window()
+ * @rb_root: root of reservation tree
+ * @goal: target allocation block
+ *
+ * Find the reserved window which includes the goal, or the previous one
+ * if the goal is not in any window.
+ * Returns NULL if there are no windows or if all windows start after the goal.
+ */
+static struct ext2_reserve_window_node *
+search_reserve_window(struct rb_root *root, ext2_fsblk_t goal)
+{
+ struct rb_node *n = root->rb_node;
+ struct ext2_reserve_window_node *rsv;
+
+ if (!n)
+ return NULL;
+
+ do {
+ rsv = rb_entry(n, struct ext2_reserve_window_node, rsv_node);
+
+ if (goal < rsv->rsv_start)
+ n = n->rb_left;
+ else if (goal > rsv->rsv_end)
+ n = n->rb_right;
+ else
+ return rsv;
+ } while (n);
+ /*
+ * We've fallen off the end of the tree: the goal wasn't inside
+ * any particular node. OK, the previous node must be to one
+ * side of the interval containing the goal. If it's the RHS,
+ * we need to back up one.
+ */
+ if (rsv->rsv_start > goal) {
+ n = rb_prev(&rsv->rsv_node);
+ rsv = rb_entry(n, struct ext2_reserve_window_node, rsv_node);
+ }
+ return rsv;
+}
+
+/*
+ * ext2_rsv_window_add() -- Insert a window to the block reservation rb tree.
+ * @sb: super block
+ * @rsv: reservation window to add
+ *
+ * Must be called with rsv_lock held.
+ */
+void ext2_rsv_window_add(struct super_block *sb,
+ struct ext2_reserve_window_node *rsv)
+{
+ struct rb_root *root = &EXT2_SB(sb)->s_rsv_window_root;
+ struct rb_node *node = &rsv->rsv_node;
+ ext2_fsblk_t start = rsv->rsv_start;
+
+ struct rb_node ** p = &root->rb_node;
+ struct rb_node * parent = NULL;
+ struct ext2_reserve_window_node *this;
+
+ while (*p)
+ {
+ parent = *p;
+ this = rb_entry(parent, struct ext2_reserve_window_node, rsv_node);
+
+ if (start < this->rsv_start)
+ p = &(*p)->rb_left;
+ else if (start > this->rsv_end)
+ p = &(*p)->rb_right;
+ else {
+ rsv_window_dump(root, 1);
+ BUG();
+ }
+ }
+
+ rb_link_node(node, parent, p);
+ rb_insert_color(node, root);
+}
+
+/**
+ * rsv_window_remove() -- unlink a window from the reservation rb tree
+ * @sb: super block
+ * @rsv: reservation window to remove
+ *
+ * Mark the block reservation window as not allocated, and unlink it
+ * from the filesystem reservation window rb tree. Must be called with
+ * rsv_lock held.
+ */
+static void rsv_window_remove(struct super_block *sb,
+ struct ext2_reserve_window_node *rsv)
+{
+ rsv->rsv_start = EXT2_RESERVE_WINDOW_NOT_ALLOCATED;
+ rsv->rsv_end = EXT2_RESERVE_WINDOW_NOT_ALLOCATED;
+ rsv->rsv_alloc_hit = 0;
+ rb_erase(&rsv->rsv_node, &EXT2_SB(sb)->s_rsv_window_root);
+}
+
+/*
+ * rsv_is_empty() -- Check if the reservation window is allocated.
+ * @rsv: given reservation window to check
+ *
+ * returns 1 if the end block is EXT2_RESERVE_WINDOW_NOT_ALLOCATED.
+ */
+static inline int rsv_is_empty(struct ext2_reserve_window *rsv)
+{
+ /* a valid reservation end block could not be 0 */
+ return (rsv->_rsv_end == EXT2_RESERVE_WINDOW_NOT_ALLOCATED);
+}
+
+/**
+ * ext2_init_block_alloc_info()
+ * @inode: file inode structure
+ *
+ * Allocate and initialize the reservation window structure, and
+ * link the window to the ext2 inode structure at last
+ *
+ * The reservation window structure is only dynamically allocated
+ * and linked to ext2 inode the first time the open file
+ * needs a new block. So, before every ext2_new_block(s) call, for
+ * regular files, we should check whether the reservation window
+ * structure exists or not. In the latter case, this function is called.
+ * Fail to do so will result in block reservation being turned off for that
+ * open file.
+ *
+ * This function is called from ext2_get_blocks_handle(), also called
+ * when setting the reservation window size through ioctl before the file
+ * is open for write (needs block allocation).
+ *
+ * Needs truncate_mutex protection prior to calling this function.
+ */
+void ext2_init_block_alloc_info(struct inode *inode)
+{
+ struct ext2_inode_info *ei = EXT2_I(inode);
+ struct ext2_block_alloc_info *block_i = ei->i_block_alloc_info;
+ struct super_block *sb = inode->i_sb;
+
+ block_i = kmalloc(sizeof(*block_i), GFP_NOFS);
+ if (block_i) {
+ struct ext2_reserve_window_node *rsv = &block_i->rsv_window_node;
+
+ rsv->rsv_start = EXT2_RESERVE_WINDOW_NOT_ALLOCATED;
+ rsv->rsv_end = EXT2_RESERVE_WINDOW_NOT_ALLOCATED;
+
+ /*
+ * if filesystem is mounted with NORESERVATION, the goal
+ * reservation window size is set to zero to indicate
+ * block reservation is off
+ */
+ if (!test_opt(sb, RESERVATION))
+ rsv->rsv_goal_size = 0;
+ else
+ rsv->rsv_goal_size = EXT2_DEFAULT_RESERVE_BLOCKS;
+ rsv->rsv_alloc_hit = 0;
+ block_i->last_alloc_logical_block = 0;
+ block_i->last_alloc_physical_block = 0;
+ }
+ ei->i_block_alloc_info = block_i;
+}
+
+/**
+ * ext2_discard_reservation()
+ * @inode: inode
+ *
+ * Discard(free) block reservation window on last file close, or truncate
+ * or at last iput().
+ *
+ * It is being called in three cases:
+ * ext2_release_file(): last writer closes the file
+ * ext2_clear_inode(): last iput(), when nobody links to this file.
+ * ext2_truncate(): when the block indirect map is about to change.
+ */
+void ext2_discard_reservation(struct inode *inode)
+{
+ struct ext2_inode_info *ei = EXT2_I(inode);
+ struct ext2_block_alloc_info *block_i = ei->i_block_alloc_info;
+ struct ext2_reserve_window_node *rsv;
+ spinlock_t *rsv_lock = &EXT2_SB(inode->i_sb)->s_rsv_window_lock;
+
+ if (!block_i)
+ return;
+
+ rsv = &block_i->rsv_window_node;
+ if (!rsv_is_empty(&rsv->rsv_window)) {
+ spin_lock(rsv_lock);
+ if (!rsv_is_empty(&rsv->rsv_window))
+ rsv_window_remove(inode->i_sb, rsv);
+ spin_unlock(rsv_lock);
+ }
+}
+
+/**
+ * ext2_free_blocks_sb() -- Free given blocks and update quota and i_blocks
+ * @inode: inode
+ * @block: start physcial block to free
+ * @count: number of blocks to free
+ */
void ext2_free_blocks (struct inode * inode, unsigned long block,
unsigned long count)
{
@@ -248,7 +494,7 @@ do_more:
if (sb->s_flags & MS_SYNCHRONOUS)
sync_dirty_buffer(bitmap_bh);
- group_release_blocks(sb, block_group, desc, bh2, group_freed);
+ group_adjust_blocks(sb, block_group, desc, bh2, group_freed);
freed += group_freed;
if (overflow) {
@@ -262,16 +508,46 @@ error_return:
DQUOT_FREE_BLOCK(inode, freed);
}
-static int grab_block(spinlock_t *lock, char *map, unsigned size, int goal)
+/**
+ * bitmap_search_next_usable_block()
+ * @start: the starting block (group relative) of the search
+ * @bh: bufferhead contains the block group bitmap
+ * @maxblocks: the ending block (group relative) of the reservation
+ *
+ * The bitmap search --- search forward through the actual bitmap on disk until
+ * we find a bit free.
+ */
+static ext2_grpblk_t
+bitmap_search_next_usable_block(ext2_grpblk_t start, struct buffer_head *bh,
+ ext2_grpblk_t maxblocks)
{
- int k;
- char *p, *r;
+ ext2_grpblk_t next;
- if (!ext2_test_bit(goal, map))
- goto got_it;
+ next = ext2_find_next_zero_bit(bh->b_data, maxblocks, start);
+ if (next >= maxblocks)
+ return -1;
+ return next;
+}
-repeat:
- if (goal) {
+/**
+ * find_next_usable_block()
+ * @start: the starting block (group relative) to find next
+ * allocatable block in bitmap.
+ * @bh: bufferhead contains the block group bitmap
+ * @maxblocks: the ending block (group relative) for the search
+ *
+ * Find an allocatable block in a bitmap. We perform the "most
+ * appropriate allocation" algorithm of looking for a free block near
+ * the initial goal; then for a free byte somewhere in the bitmap;
+ * then for any free bit in the bitmap.
+ */
+static ext2_grpblk_t
+find_next_usable_block(int start, struct buffer_head *bh, int maxblocks)
+{
+ ext2_grpblk_t here, next;
+ char *p, *r;
+
+ if (start > 0) {
/*
* The goal was occupied; search forward for a free
* block within the next XX blocks.
@@ -280,249 +556,812 @@ repeat:
* less than EXT2_BLOCKS_PER_GROUP. Aligning up to the
* next 64-bit boundary is simple..
*/
- k = (goal + 63) & ~63;
- goal = ext2_find_next_zero_bit(map, k, goal);
- if (goal < k)
- goto got_it;
+ ext2_grpblk_t end_goal = (start + 63) & ~63;
+ if (end_goal > maxblocks)
+ end_goal = maxblocks;
+ here = ext2_find_next_zero_bit(bh->b_data, end_goal, start);
+ if (here < end_goal)
+ return here;
+ ext2_debug("Bit not found near goal\n");
+ }
+
+ here = start;
+ if (here < 0)
+ here = 0;
+
+ p = ((char *)bh->b_data) + (here >> 3);
+ r = memscan(p, 0, ((maxblocks + 7) >> 3) - (here >> 3));
+ next = (r - ((char *)bh->b_data)) << 3;
+
+ if (next < maxblocks && next >= here)
+ return next;
+
+ here = bitmap_search_next_usable_block(here, bh, maxblocks);
+ return here;
+}
+
+/*
+ * ext2_try_to_allocate()
+ * @sb: superblock
+ * @handle: handle to this transaction
+ * @group: given allocation block group
+ * @bitmap_bh: bufferhead holds the block bitmap
+ * @grp_goal: given target block within the group
+ * @count: target number of blocks to allocate
+ * @my_rsv: reservation window
+ *
+ * Attempt to allocate blocks within a give range. Set the range of allocation
+ * first, then find the first free bit(s) from the bitmap (within the range),
+ * and at last, allocate the blocks by claiming the found free bit as allocated.
+ *
+ * To set the range of this allocation:
+ * if there is a reservation window, only try to allocate block(s)
+ * from the file's own reservation window;
+ * Otherwise, the allocation range starts from the give goal block,
+ * ends at the block group's last block.
+ *
+ * If we failed to allocate the desired block then we may end up crossing to a
+ * new bitmap.
+ */
+static int
+ext2_try_to_allocate(struct super_block *sb, int group,
+ struct buffer_head *bitmap_bh, ext2_grpblk_t grp_goal,
+ unsigned long *count,
+ struct ext2_reserve_window *my_rsv)
+{
+ ext2_fsblk_t group_first_block;
+ ext2_grpblk_t start, end;
+ unsigned long num = 0;
+
+ /* we do allocation within the reservation window if we have a window */
+ if (my_rsv) {
+ group_first_block = ext2_group_first_block_no(sb, group);
+ if (my_rsv->_rsv_start >= group_first_block)
+ start = my_rsv->_rsv_start - group_first_block;
+ else
+ /* reservation window cross group boundary */
+ start = 0;
+ end = my_rsv->_rsv_end - group_first_block + 1;
+ if (end > EXT2_BLOCKS_PER_GROUP(sb))
+ /* reservation window crosses group boundary */
+ end = EXT2_BLOCKS_PER_GROUP(sb);
+ if ((start <= grp_goal) && (grp_goal < end))
+ start = grp_goal;
+ else
+ grp_goal = -1;
+ } else {
+ if (grp_goal > 0)
+ start = grp_goal;
+ else
+ start = 0;
+ end = EXT2_BLOCKS_PER_GROUP(sb);
+ }
+
+ BUG_ON(start > EXT2_BLOCKS_PER_GROUP(sb));
+
+repeat:
+ if (grp_goal < 0) {
+ grp_goal = find_next_usable_block(start, bitmap_bh, end);
+ if (grp_goal < 0)
+ goto fail_access;
+ if (!my_rsv) {
+ int i;
+
+ for (i = 0; i < 7 && grp_goal > start &&
+ !ext2_test_bit(grp_goal - 1,
+ bitmap_bh->b_data);
+ i++, grp_goal--)
+ ;
+ }
+ }
+ start = grp_goal;
+
+ if (ext2_set_bit_atomic(sb_bgl_lock(EXT2_SB(sb), group), grp_goal,
+ bitmap_bh->b_data)) {
/*
- * Search in the remainder of the current group.
+ * The block was allocated by another thread, or it was
+ * allocated and then freed by another thread
*/
+ start++;
+ grp_goal++;
+ if (start >= end)
+ goto fail_access;
+ goto repeat;
}
+ num++;
+ grp_goal++;
+ while (num < *count && grp_goal < end
+ && !ext2_set_bit_atomic(sb_bgl_lock(EXT2_SB(sb), group),
+ grp_goal, bitmap_bh->b_data)) {
+ num++;
+ grp_goal++;
+ }
+ *count = num;
+ return grp_goal - num;
+fail_access:
+ *count = num;
+ return -1;
+}
- p = map + (goal >> 3);
- r = memscan(p, 0, (size - goal + 7) >> 3);
- k = (r - map) << 3;
- if (k < size) {
- /*
- * We have succeeded in finding a free byte in the block
- * bitmap. Now search backwards to find the start of this
- * group of free blocks - won't take more than 7 iterations.
+/**
+ * find_next_reservable_window():
+ * find a reservable space within the given range.
+ * It does not allocate the reservation window for now:
+ * alloc_new_reservation() will do the work later.
+ *
+ * @search_head: the head of the searching list;
+ * This is not necessarily the list head of the whole filesystem
+ *
+ * We have both head and start_block to assist the search
+ * for the reservable space. The list starts from head,
+ * but we will shift to the place where start_block is,
+ * then start from there, when looking for a reservable space.
+ *
+ * @size: the target new reservation window size
+ *
+ * @group_first_block: the first block we consider to start
+ * the real search from
+ *
+ * @last_block:
+ * the maximum block number that our goal reservable space
+ * could start from. This is normally the last block in this
+ * group. The search will end when we found the start of next
+ * possible reservable space is out of this boundary.
+ * This could handle the cross boundary reservation window
+ * request.
+ *
+ * basically we search from the given range, rather than the whole
+ * reservation double linked list, (start_block, last_block)
+ * to find a free region that is of my size and has not
+ * been reserved.
+ *
+ */
+static int find_next_reservable_window(
+ struct ext2_reserve_window_node *search_head,
+ struct ext2_reserve_window_node *my_rsv,
+ struct super_block * sb,
+ ext2_fsblk_t start_block,
+ ext2_fsblk_t last_block)
+{
+ struct rb_node *next;
+ struct ext2_reserve_window_node *rsv, *prev;
+ ext2_fsblk_t cur;
+ int size = my_rsv->rsv_goal_size;
+
+ /* TODO: make the start of the reservation window byte-aligned */
+ /* cur = *start_block & ~7;*/
+ cur = start_block;
+ rsv = search_head;
+ if (!rsv)
+ return -1;
+
+ while (1) {
+ if (cur <= rsv->rsv_end)
+ cur = rsv->rsv_end + 1;
+
+ /* TODO?
+ * in the case we could not find a reservable space
+ * that is what is expected, during the re-search, we could
+ * remember what's the largest reservable space we could have
+ * and return that one.
+ *
+ * For now it will fail if we could not find the reservable
+ * space with expected-size (or more)...
*/
- for (goal = k; goal && !ext2_test_bit (goal - 1, map); goal--)
- ;
- goto got_it;
+ if (cur > last_block)
+ return -1; /* fail */
+
+ prev = rsv;
+ next = rb_next(&rsv->rsv_node);
+ rsv = rb_entry(next,struct ext2_reserve_window_node,rsv_node);
+
+ /*
+ * Reached the last reservation, we can just append to the
+ * previous one.
+ */
+ if (!next)
+ break;
+
+ if (cur + size <= rsv->rsv_start) {
+ /*
+ * Found a reserveable space big enough. We could
+ * have a reservation across the group boundary here
+ */
+ break;
+ }
}
+ /*
+ * we come here either :
+ * when we reach the end of the whole list,
+ * and there is empty reservable space after last entry in the list.
+ * append it to the end of the list.
+ *
+ * or we found one reservable space in the middle of the list,
+ * return the reservation window that we could append to.
+ * succeed.
+ */
+
+ if ((prev != my_rsv) && (!rsv_is_empty(&my_rsv->rsv_window)))
+ rsv_window_remove(sb, my_rsv);
+
+ /*
+ * Let's book the whole avaliable window for now. We will check the
+ * disk bitmap later and then, if there are free blocks then we adjust
+ * the window size if it's larger than requested.
+ * Otherwise, we will remove this node from the tree next time
+ * call find_next_reservable_window.
+ */
+ my_rsv->rsv_start = cur;
+ my_rsv->rsv_end = cur + size - 1;
+ my_rsv->rsv_alloc_hit = 0;
+
+ if (prev != my_rsv)
+ ext2_rsv_window_add(sb, my_rsv);
+
+ return 0;
+}
- k = ext2_find_next_zero_bit ((u32 *)map, size, goal);
- if (k < size) {
- goal = k;
- goto got_it;
+/**
+ * alloc_new_reservation()--allocate a new reservation window
+ *
+ * To make a new reservation, we search part of the filesystem
+ * reservation list (the list that inside the group). We try to
+ * allocate a new reservation window near the allocation goal,
+ * or the beginning of the group, if there is no goal.
+ *
+ * We first find a reservable space after the goal, then from
+ * there, we check the bitmap for the first free block after
+ * it. If there is no free block until the end of group, then the
+ * whole group is full, we failed. Otherwise, check if the free
+ * block is inside the expected reservable space, if so, we
+ * succeed.
+ * If the first free block is outside the reservable space, then
+ * start from the first free block, we search for next available
+ * space, and go on.
+ *
+ * on succeed, a new reservation will be found and inserted into the list
+ * It contains at least one free block, and it does not overlap with other
+ * reservation windows.
+ *
+ * failed: we failed to find a reservation window in this group
+ *
+ * @rsv: the reservation
+ *
+ * @grp_goal: The goal (group-relative). It is where the search for a
+ * free reservable space should start from.
+ * if we have a goal(goal >0 ), then start from there,
+ * no goal(goal = -1), we start from the first block
+ * of the group.
+ *
+ * @sb: the super block
+ * @group: the group we are trying to allocate in
+ * @bitmap_bh: the block group block bitmap
+ *
+ */
+static int alloc_new_reservation(struct ext2_reserve_window_node *my_rsv,
+ ext2_grpblk_t grp_goal, struct super_block *sb,
+ unsigned int group, struct buffer_head *bitmap_bh)
+{
+ struct ext2_reserve_window_node *search_head;
+ ext2_fsblk_t group_first_block, group_end_block, start_block;
+ ext2_grpblk_t first_free_block;
+ struct rb_root *fs_rsv_root = &EXT2_SB(sb)->s_rsv_window_root;
+ unsigned long size;
+ int ret;
+ spinlock_t *rsv_lock = &EXT2_SB(sb)->s_rsv_window_lock;
+
+ group_first_block = ext2_group_first_block_no(sb, group);
+ group_end_block = group_first_block + (EXT2_BLOCKS_PER_GROUP(sb) - 1);
+
+ if (grp_goal < 0)
+ start_block = group_first_block;
+ else
+ start_block = grp_goal + group_first_block;
+
+ size = my_rsv->rsv_goal_size;
+
+ if (!rsv_is_empty(&my_rsv->rsv_window)) {
+ /*
+ * if the old reservation is cross group boundary
+ * and if the goal is inside the old reservation window,
+ * we will come here when we just failed to allocate from
+ * the first part of the window. We still have another part
+ * that belongs to the next group. In this case, there is no
+ * point to discard our window and try to allocate a new one
+ * in this group(which will fail). we should
+ * keep the reservation window, just simply move on.
+ *
+ * Maybe we could shift the start block of the reservation
+ * window to the first block of next group.
+ */
+
+ if ((my_rsv->rsv_start <= group_end_block) &&
+ (my_rsv->rsv_end > group_end_block) &&
+ (start_block >= my_rsv->rsv_start))
+ return -1;
+
+ if ((my_rsv->rsv_alloc_hit >
+ (my_rsv->rsv_end - my_rsv->rsv_start + 1) / 2)) {
+ /*
+ * if the previously allocation hit ratio is
+ * greater than 1/2, then we double the size of
+ * the reservation window the next time,
+ * otherwise we keep the same size window
+ */
+ size = size * 2;
+ if (size > EXT2_MAX_RESERVE_BLOCKS)
+ size = EXT2_MAX_RESERVE_BLOCKS;
+ my_rsv->rsv_goal_size= size;
+ }
}
- return -1;
-got_it:
- if (ext2_set_bit_atomic(lock, goal, (void *) map))
- goto repeat;
- return goal;
+
+ spin_lock(rsv_lock);
+ /*
+ * shift the search start to the window near the goal block
+ */
+ search_head = search_reserve_window(fs_rsv_root, start_block);
+
+ /*
+ * find_next_reservable_window() simply finds a reservable window
+ * inside the given range(start_block, group_end_block).
+ *
+ * To make sure the reservation window has a free bit inside it, we
+ * need to check the bitmap after we found a reservable window.
+ */
+retry:
+ ret = find_next_reservable_window(search_head, my_rsv, sb,
+ start_block, group_end_block);
+
+ if (ret == -1) {
+ if (!rsv_is_empty(&my_rsv->rsv_window))
+ rsv_window_remove(sb, my_rsv);
+ spin_unlock(rsv_lock);
+ return -1;
+ }
+
+ /*
+ * On success, find_next_reservable_window() returns the
+ * reservation window where there is a reservable space after it.
+ * Before we reserve this reservable space, we need
+ * to make sure there is at least a free block inside this region.
+ *
+ * Search the first free bit on the block bitmap. Search starts from
+ * the start block of the reservable space we just found.
+ */
+ spin_unlock(rsv_lock);
+ first_free_block = bitmap_search_next_usable_block(
+ my_rsv->rsv_start - group_first_block,
+ bitmap_bh, group_end_block - group_first_block + 1);
+
+ if (first_free_block < 0) {
+ /*
+ * no free block left on the bitmap, no point
+ * to reserve the space. return failed.
+ */
+ spin_lock(rsv_lock);
+ if (!rsv_is_empty(&my_rsv->rsv_window))
+ rsv_window_remove(sb, my_rsv);
+ spin_unlock(rsv_lock);
+ return -1; /* failed */
+ }
+
+ start_block = first_free_block + group_first_block;
+ /*
+ * check if the first free block is within the
+ * free space we just reserved
+ */
+ if (start_block >= my_rsv->rsv_start && start_block <= my_rsv->rsv_end)
+ return 0; /* success */
+ /*
+ * if the first free bit we found is out of the reservable space
+ * continue search for next reservable space,
+ * start from where the free block is,
+ * we also shift the list head to where we stopped last time
+ */
+ search_head = my_rsv;
+ spin_lock(rsv_lock);
+ goto retry;
+}
+
+/**
+ * try_to_extend_reservation()
+ * @my_rsv: given reservation window
+ * @sb: super block
+ * @size: the delta to extend
+ *
+ * Attempt to expand the reservation window large enough to have
+ * required number of free blocks
+ *
+ * Since ext2_try_to_allocate() will always allocate blocks within
+ * the reservation window range, if the window size is too small,
+ * multiple blocks allocation has to stop at the end of the reservation
+ * window. To make this more efficient, given the total number of
+ * blocks needed and the current size of the window, we try to
+ * expand the reservation window size if necessary on a best-effort
+ * basis before ext2_new_blocks() tries to allocate blocks.
+ */
+static void try_to_extend_reservation(struct ext2_reserve_window_node *my_rsv,
+ struct super_block *sb, int size)
+{
+ struct ext2_reserve_window_node *next_rsv;
+ struct rb_node *next;
+ spinlock_t *rsv_lock = &EXT2_SB(sb)->s_rsv_window_lock;
+
+ if (!spin_trylock(rsv_lock))
+ return;
+
+ next = rb_next(&my_rsv->rsv_node);
+
+ if (!next)
+ my_rsv->rsv_end += size;
+ else {
+ next_rsv = rb_entry(next, struct ext2_reserve_window_node, rsv_node);
+
+ if ((next_rsv->rsv_start - my_rsv->rsv_end - 1) >= size)
+ my_rsv->rsv_end += size;
+ else
+ my_rsv->rsv_end = next_rsv->rsv_start - 1;
+ }
+ spin_unlock(rsv_lock);
+}
+
+/**
+ * ext2_try_to_allocate_with_rsv()
+ * @sb: superblock
+ * @group: given allocation block group
+ * @bitmap_bh: bufferhead holds the block bitmap
+ * @grp_goal: given target block within the group
+ * @count: target number of blocks to allocate
+ * @my_rsv: reservation window
+ *
+ * This is the main function used to allocate a new block and its reservation
+ * window.
+ *
+ * Each time when a new block allocation is need, first try to allocate from
+ * its own reservation. If it does not have a reservation window, instead of
+ * looking for a free bit on bitmap first, then look up the reservation list to
+ * see if it is inside somebody else's reservation window, we try to allocate a
+ * reservation window for it starting from the goal first. Then do the block
+ * allocation within the reservation window.
+ *
+ * This will avoid keeping on searching the reservation list again and
+ * again when somebody is looking for a free block (without
+ * reservation), and there are lots of free blocks, but they are all
+ * being reserved.
+ *
+ * We use a red-black tree for the per-filesystem reservation list.
+ */
+static ext2_grpblk_t
+ext2_try_to_allocate_with_rsv(struct super_block *sb, unsigned int group,
+ struct buffer_head *bitmap_bh, ext2_grpblk_t grp_goal,
+ struct ext2_reserve_window_node * my_rsv,
+ unsigned long *count)
+{
+ ext2_fsblk_t group_first_block, group_last_block;
+ ext2_grpblk_t ret = 0;
+ unsigned long num = *count;
+
+ /*
+ * we don't deal with reservation when
+ * filesystem is mounted without reservation
+ * or the file is not a regular file
+ * or last attempt to allocate a block with reservation turned on failed
+ */
+ if (my_rsv == NULL) {
+ return ext2_try_to_allocate(sb, group, bitmap_bh,
+ grp_goal, count, NULL);
+ }
+ /*
+ * grp_goal is a group relative block number (if there is a goal)
+ * 0 <= grp_goal < EXT2_BLOCKS_PER_GROUP(sb)
+ * first block is a filesystem wide block number
+ * first block is the block number of the first block in this group
+ */
+ group_first_block = ext2_group_first_block_no(sb, group);
+ group_last_block = group_first_block + (EXT2_BLOCKS_PER_GROUP(sb) - 1);
+
+ /*
+ * Basically we will allocate a new block from inode's reservation
+ * window.
+ *
+ * We need to allocate a new reservation window, if:
+ * a) inode does not have a reservation window; or
+ * b) last attempt to allocate a block from existing reservation
+ * failed; or
+ * c) we come here with a goal and with a reservation window
+ *
+ * We do not need to allocate a new reservation window if we come here
+ * at the beginning with a goal and the goal is inside the window, or
+ * we don't have a goal but already have a reservation window.
+ * then we could go to allocate from the reservation window directly.
+ */
+ while (1) {
+ if (rsv_is_empty(&my_rsv->rsv_window) || (ret < 0) ||
+ !goal_in_my_reservation(&my_rsv->rsv_window,
+ grp_goal, group, sb)) {
+ if (my_rsv->rsv_goal_size < *count)
+ my_rsv->rsv_goal_size = *count;
+ ret = alloc_new_reservation(my_rsv, grp_goal, sb,
+ group, bitmap_bh);
+ if (ret < 0)
+ break; /* failed */
+
+ if (!goal_in_my_reservation(&my_rsv->rsv_window,
+ grp_goal, group, sb))
+ grp_goal = -1;
+ } else if (grp_goal >= 0) {
+ int curr = my_rsv->rsv_end -
+ (grp_goal + group_first_block) + 1;
+
+ if (curr < *count)
+ try_to_extend_reservation(my_rsv, sb,
+ *count - curr);
+ }
+
+ if ((my_rsv->rsv_start > group_last_block) ||
+ (my_rsv->rsv_end < group_first_block)) {
+ rsv_window_dump(&EXT2_SB(sb)->s_rsv_window_root, 1);
+ BUG();
+ }
+ ret = ext2_try_to_allocate(sb, group, bitmap_bh, grp_goal,
+ &num, &my_rsv->rsv_window);
+ if (ret >= 0) {
+ my_rsv->rsv_alloc_hit += num;
+ *count = num;
+ break; /* succeed */
+ }
+ num = *count;
+ }
+ return ret;
+}
+
+/**
+ * ext2_has_free_blocks()
+ * @sbi: in-core super block structure.
+ *
+ * Check if filesystem has at least 1 free block available for allocation.
+ */
+static int ext2_has_free_blocks(struct ext2_sb_info *sbi)
+{
+ ext2_fsblk_t free_blocks, root_blocks;
+
+ free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
+ root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count);
+ if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) &&
+ sbi->s_resuid != current->fsuid &&
+ (sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) {
+ return 0;
+ }
+ return 1;
}
/*
- * ext2_new_block uses a goal block to assist allocation. If the goal is
+ * ext2_new_blocks() -- core block(s) allocation function
+ * @inode: file inode
+ * @goal: given target block(filesystem wide)
+ * @count: target number of blocks to allocate
+ * @errp: error code
+ *
+ * ext2_new_blocks uses a goal block to assist allocation. If the goal is
* free, or there is a free block within 32 blocks of the goal, that block
* is allocated. Otherwise a forward search is made for a free block; within
* each block group the search first looks for an entire free byte in the block
* bitmap, and then for any free bit if that fails.
* This function also updates quota and i_blocks field.
*/
-int ext2_new_block(struct inode *inode, unsigned long goal,
- u32 *prealloc_count, u32 *prealloc_block, int *err)
+ext2_fsblk_t ext2_new_blocks(struct inode *inode, ext2_fsblk_t goal,
+ unsigned long *count, int *errp)
{
struct buffer_head *bitmap_bh = NULL;
- struct buffer_head *gdp_bh; /* bh2 */
- struct ext2_group_desc *desc;
- int group_no; /* i */
- int ret_block; /* j */
- int group_idx; /* k */
- int target_block; /* tmp */
- int block = 0;
- struct super_block *sb = inode->i_sb;
- struct ext2_sb_info *sbi = EXT2_SB(sb);
- struct ext2_super_block *es = sbi->s_es;
- unsigned group_size = EXT2_BLOCKS_PER_GROUP(sb);
- unsigned prealloc_goal = es->s_prealloc_blocks;
- unsigned group_alloc = 0, es_alloc, dq_alloc;
- int nr_scanned_groups;
-
- if (!prealloc_goal--)
- prealloc_goal = EXT2_DEFAULT_PREALLOC_BLOCKS - 1;
- if (!prealloc_count || *prealloc_count)
- prealloc_goal = 0;
-
- if (DQUOT_ALLOC_BLOCK(inode, 1)) {
- *err = -EDQUOT;
- goto out;
+ struct buffer_head *gdp_bh;
+ int group_no;
+ int goal_group;
+ ext2_grpblk_t grp_target_blk; /* blockgroup relative goal block */
+ ext2_grpblk_t grp_alloc_blk; /* blockgroup-relative allocated block*/
+ ext2_fsblk_t ret_block; /* filesyetem-wide allocated block */
+ int bgi; /* blockgroup iteration index */
+ int performed_allocation = 0;
+ ext2_grpblk_t free_blocks; /* number of free blocks in a group */
+ struct super_block *sb;
+ struct ext2_group_desc *gdp;
+ struct ext2_super_block *es;
+ struct ext2_sb_info *sbi;
+ struct ext2_reserve_window_node *my_rsv = NULL;
+ struct ext2_block_alloc_info *block_i;
+ unsigned short windowsz = 0;
+ unsigned long ngroups;
+ unsigned long num = *count;
+
+ *errp = -ENOSPC;
+ sb = inode->i_sb;
+ if (!sb) {
+ printk("ext2_new_blocks: nonexistent device");
+ return 0;
}
- while (prealloc_goal && DQUOT_PREALLOC_BLOCK(inode, prealloc_goal))
- prealloc_goal--;
+ /*
+ * Check quota for allocation of this block.
+ */
+ if (DQUOT_ALLOC_BLOCK(inode, num)) {
+ *errp = -EDQUOT;
+ return 0;
+ }
- dq_alloc = prealloc_goal + 1;
- es_alloc = reserve_blocks(sb, dq_alloc);
- if (!es_alloc) {
- *err = -ENOSPC;
- goto out_dquot;
+ sbi = EXT2_SB(sb);
+ es = EXT2_SB(sb)->s_es;
+ ext2_debug("goal=%lu.\n", goal);
+ /*
+ * Allocate a block from reservation only when
+ * filesystem is mounted with reservation(default,-o reservation), and
+ * it's a regular file, and
+ * the desired window size is greater than 0 (One could use ioctl
+ * command EXT2_IOC_SETRSVSZ to set the window size to 0 to turn off
+ * reservation on that particular file)
+ */
+ block_i = EXT2_I(inode)->i_block_alloc_info;
+ if (block_i) {
+ windowsz = block_i->rsv_window_node.rsv_goal_size;
+ if (windowsz > 0)
+ my_rsv = &block_i->rsv_window_node;
}
- ext2_debug ("goal=%lu.\n", goal);
+ if (!ext2_has_free_blocks(sbi)) {
+ *errp = -ENOSPC;
+ goto out;
+ }
+ /*
+ * First, test whether the goal block is free.
+ */
if (goal < le32_to_cpu(es->s_first_data_block) ||
goal >= le32_to_cpu(es->s_blocks_count))
goal = le32_to_cpu(es->s_first_data_block);
- group_no = (goal - le32_to_cpu(es->s_first_data_block)) / group_size;
- desc = ext2_get_group_desc (sb, group_no, &gdp_bh);
- if (!desc) {
- /*
- * gdp_bh may still be uninitialised. But group_release_blocks
- * will not touch it because group_alloc is zero.
- */
+ group_no = (goal - le32_to_cpu(es->s_first_data_block)) /
+ EXT2_BLOCKS_PER_GROUP(sb);
+ goal_group = group_no;
+retry_alloc:
+ gdp = ext2_get_group_desc(sb, group_no, &gdp_bh);
+ if (!gdp)
goto io_error;
- }
- group_alloc = group_reserve_blocks(sbi, group_no, desc,
- gdp_bh, es_alloc);
- if (group_alloc) {
- ret_block = ((goal - le32_to_cpu(es->s_first_data_block)) %
- group_size);
- brelse(bitmap_bh);
+ free_blocks = le16_to_cpu(gdp->bg_free_blocks_count);
+ /*
+ * if there is not enough free blocks to make a new resevation
+ * turn off reservation for this allocation
+ */
+ if (my_rsv && (free_blocks < windowsz)
+ && (rsv_is_empty(&my_rsv->rsv_window)))
+ my_rsv = NULL;
+
+ if (free_blocks > 0) {
+ grp_target_blk = ((goal - le32_to_cpu(es->s_first_data_block)) %
+ EXT2_BLOCKS_PER_GROUP(sb));
bitmap_bh = read_block_bitmap(sb, group_no);
if (!bitmap_bh)
goto io_error;
-
- ext2_debug("goal is at %d:%d.\n", group_no, ret_block);
-
- ret_block = grab_block(sb_bgl_lock(sbi, group_no),
- bitmap_bh->b_data, group_size, ret_block);
- if (ret_block >= 0)
- goto got_block;
- group_release_blocks(sb, group_no, desc, gdp_bh, group_alloc);
- group_alloc = 0;
+ grp_alloc_blk = ext2_try_to_allocate_with_rsv(sb, group_no,
+ bitmap_bh, grp_target_blk,
+ my_rsv, &num);
+ if (grp_alloc_blk >= 0)
+ goto allocated;
}
- ext2_debug ("Bit not found in block group %d.\n", group_no);
+ ngroups = EXT2_SB(sb)->s_groups_count;
+ smp_rmb();
/*
* Now search the rest of the groups. We assume that
- * i and desc correctly point to the last group visited.
+ * i and gdp correctly point to the last group visited.
*/
- nr_scanned_groups = 0;
-retry:
- for (group_idx = 0; !group_alloc &&
- group_idx < sbi->s_groups_count; group_idx++) {
+ for (bgi = 0; bgi < ngroups; bgi++) {
group_no++;
- if (group_no >= sbi->s_groups_count)
+ if (group_no >= ngroups)
group_no = 0;
- desc = ext2_get_group_desc(sb, group_no, &gdp_bh);
- if (!desc)
+ gdp = ext2_get_group_desc(sb, group_no, &gdp_bh);
+ if (!gdp)
goto io_error;
- group_alloc = group_reserve_blocks(sbi, group_no, desc,
- gdp_bh, es_alloc);
- }
- if (!group_alloc) {
- *err = -ENOSPC;
- goto out_release;
- }
- brelse(bitmap_bh);
- bitmap_bh = read_block_bitmap(sb, group_no);
- if (!bitmap_bh)
- goto io_error;
- ret_block = grab_block(sb_bgl_lock(sbi, group_no), bitmap_bh->b_data,
- group_size, 0);
- if (ret_block < 0) {
+ free_blocks = le16_to_cpu(gdp->bg_free_blocks_count);
/*
- * If a free block counter is corrupted we can loop inifintely.
- * Detect that here.
+ * skip this group if the number of
+ * free blocks is less than half of the reservation
+ * window size.
*/
- nr_scanned_groups++;
- if (nr_scanned_groups > 2 * sbi->s_groups_count) {
- ext2_error(sb, "ext2_new_block",
- "corrupted free blocks counters");
+ if (free_blocks <= (windowsz/2))
+ continue;
+
+ brelse(bitmap_bh);
+ bitmap_bh = read_block_bitmap(sb, group_no);
+ if (!bitmap_bh)
goto io_error;
- }
/*
- * Someone else grabbed the last free block in this blockgroup
- * before us. Retry the scan.
+ * try to allocate block(s) from this group, without a goal(-1).
*/
- group_release_blocks(sb, group_no, desc, gdp_bh, group_alloc);
- group_alloc = 0;
- goto retry;
+ grp_alloc_blk = ext2_try_to_allocate_with_rsv(sb, group_no,
+ bitmap_bh, -1, my_rsv, &num);
+ if (grp_alloc_blk >= 0)
+ goto allocated;
}
+ /*
+ * We may end up a bogus ealier ENOSPC error due to
+ * filesystem is "full" of reservations, but
+ * there maybe indeed free blocks avaliable on disk
+ * In this case, we just forget about the reservations
+ * just do block allocation as without reservations.
+ */
+ if (my_rsv) {
+ my_rsv = NULL;
+ windowsz = 0;
+ group_no = goal_group;
+ goto retry_alloc;
+ }
+ /* No space left on the device */
+ *errp = -ENOSPC;
+ goto out;
+
+allocated:
-got_block:
ext2_debug("using block group %d(%d)\n",
- group_no, desc->bg_free_blocks_count);
+ group_no, gdp->bg_free_blocks_count);
- target_block = ret_block + group_no * group_size +
- le32_to_cpu(es->s_first_data_block);
+ ret_block = grp_alloc_blk + ext2_group_first_block_no(sb, group_no);
- if (target_block == le32_to_cpu(desc->bg_block_bitmap) ||
- target_block == le32_to_cpu(desc->bg_inode_bitmap) ||
- in_range(target_block, le32_to_cpu(desc->bg_inode_table),
- sbi->s_itb_per_group))
- ext2_error (sb, "ext2_new_block",
+ if (in_range(le32_to_cpu(gdp->bg_block_bitmap), ret_block, num) ||
+ in_range(le32_to_cpu(gdp->bg_inode_bitmap), ret_block, num) ||
+ in_range(ret_block, le32_to_cpu(gdp->bg_inode_table),
+ EXT2_SB(sb)->s_itb_per_group) ||
+ in_range(ret_block + num - 1, le32_to_cpu(gdp->bg_inode_table),
+ EXT2_SB(sb)->s_itb_per_group))
+ ext2_error(sb, "ext2_new_blocks",
"Allocating block in system zone - "
- "block = %u", target_block);
+ "blocks from "E2FSBLK", length %lu",
+ ret_block, num);
- if (target_block >= le32_to_cpu(es->s_blocks_count)) {
- ext2_error (sb, "ext2_new_block",
- "block(%d) >= blocks count(%d) - "
+ performed_allocation = 1;
+
+ if (ret_block + num - 1 >= le32_to_cpu(es->s_blocks_count)) {
+ ext2_error(sb, "ext2_new_blocks",
+ "block("E2FSBLK") >= blocks count(%d) - "
"block_group = %d, es == %p ", ret_block,
le32_to_cpu(es->s_blocks_count), group_no, es);
- goto io_error;
+ goto out;
}
- block = target_block;
-
- /* OK, we _had_ allocated something */
- ext2_debug("found bit %d\n", ret_block);
-
- dq_alloc--;
- es_alloc--;
- group_alloc--;
- /*
- * Do block preallocation now if required.
- */
- write_lock(&EXT2_I(inode)->i_meta_lock);
- if (group_alloc && !*prealloc_count) {
- unsigned n;
-
- for (n = 0; n < group_alloc && ++ret_block < group_size; n++) {
- if (ext2_set_bit_atomic(sb_bgl_lock(sbi, group_no),
- ret_block,
- (void*) bitmap_bh->b_data))
- break;
- }
- *prealloc_block = block + 1;
- *prealloc_count = n;
- es_alloc -= n;
- dq_alloc -= n;
- group_alloc -= n;
- }
- write_unlock(&EXT2_I(inode)->i_meta_lock);
+ group_adjust_blocks(sb, group_no, gdp, gdp_bh, -num);
+ percpu_counter_sub(&sbi->s_freeblocks_counter, num);
mark_buffer_dirty(bitmap_bh);
if (sb->s_flags & MS_SYNCHRONOUS)
sync_dirty_buffer(bitmap_bh);
- ext2_debug ("allocating block %d. ", block);
+ *errp = 0;
+ brelse(bitmap_bh);
+ DQUOT_FREE_BLOCK(inode, *count-num);
+ *count = num;
+ return ret_block;
- *err = 0;
-out_release:
- group_release_blocks(sb, group_no, desc, gdp_bh, group_alloc);
- release_blocks(sb, es_alloc);
-out_dquot:
- DQUOT_FREE_BLOCK(inode, dq_alloc);
+io_error:
+ *errp = -EIO;
out:
+ /*
+ * Undo the block allocation
+ */
+ if (!performed_allocation)
+ DQUOT_FREE_BLOCK(inode, *count);
brelse(bitmap_bh);
- return block;
+ return 0;
+}
-io_error:
- *err = -EIO;
- goto out_release;
+ext2_fsblk_t ext2_new_block(struct inode *inode, unsigned long goal, int *errp)
+{
+ unsigned long count = 1;
+
+ return ext2_new_blocks(inode, goal, &count, errp);
}
#ifdef EXT2FS_DEBUG
-static int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
+static const int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
unsigned long ext2_count_free (struct buffer_head * map, unsigned int numchars)
{
@@ -583,14 +1422,6 @@ unsigned long ext2_count_free_blocks (struct super_block * sb)
#endif
}
-static inline int
-block_in_use(unsigned long block, struct super_block *sb, unsigned char *map)
-{
- return ext2_test_bit ((block -
- le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block)) %
- EXT2_BLOCKS_PER_GROUP(sb), map);
-}
-
static inline int test_root(int a, int b)
{
int num = b;
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c
index 2bf49d7ef841..d868e26c15eb 100644
--- a/fs/ext2/dir.c
+++ b/fs/ext2/dir.c
@@ -22,10 +22,30 @@
*/
#include "ext2.h"
+#include <linux/buffer_head.h>
#include <linux/pagemap.h>
+#include <linux/swap.h>
typedef struct ext2_dir_entry_2 ext2_dirent;
+static inline unsigned ext2_rec_len_from_disk(__le16 dlen)
+{
+ unsigned len = le16_to_cpu(dlen);
+
+ if (len == EXT2_MAX_REC_LEN)
+ return 1 << 16;
+ return len;
+}
+
+static inline __le16 ext2_rec_len_to_disk(unsigned len)
+{
+ if (len == (1 << 16))
+ return cpu_to_le16(EXT2_MAX_REC_LEN);
+ else if (len > (1 << 16))
+ BUG();
+ return cpu_to_le16(len);
+}
+
/*
* ext2 uses block-sized chunks. Arguably, sector-sized ones would be
* more robust, but we have what we have
@@ -61,16 +81,25 @@ ext2_last_byte(struct inode *inode, unsigned long page_nr)
return last_byte;
}
-static int ext2_commit_chunk(struct page *page, unsigned from, unsigned to)
+static int ext2_commit_chunk(struct page *page, loff_t pos, unsigned len)
{
- struct inode *dir = page->mapping->host;
+ struct address_space *mapping = page->mapping;
+ struct inode *dir = mapping->host;
int err = 0;
+
dir->i_version++;
- page->mapping->a_ops->commit_write(NULL, page, from, to);
+ block_write_end(NULL, mapping, pos, len, len, page, NULL);
+
+ if (pos+len > dir->i_size) {
+ i_size_write(dir, pos+len);
+ mark_inode_dirty(dir);
+ }
+
if (IS_DIRSYNC(dir))
err = write_one_page(page, 1);
else
unlock_page(page);
+
return err;
}
@@ -95,7 +124,7 @@ static void ext2_check_page(struct page *page)
}
for (offs = 0; offs <= limit - EXT2_DIR_REC_LEN(1); offs += rec_len) {
p = (ext2_dirent *)(kaddr + offs);
- rec_len = le16_to_cpu(p->rec_len);
+ rec_len = ext2_rec_len_from_disk(p->rec_len);
if (rec_len < EXT2_DIR_REC_LEN(1))
goto Eshort;
@@ -193,7 +222,8 @@ static inline int ext2_match (int len, const char * const name,
*/
static inline ext2_dirent *ext2_next_entry(ext2_dirent *p)
{
- return (ext2_dirent *)((char*)p + le16_to_cpu(p->rec_len));
+ return (ext2_dirent *)((char *)p +
+ ext2_rec_len_from_disk(p->rec_len));
}
static inline unsigned
@@ -305,7 +335,7 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
return 0;
}
}
- filp->f_pos += le16_to_cpu(de->rec_len);
+ filp->f_pos += ext2_rec_len_from_disk(de->rec_len);
}
ext2_put_page(page);
}
@@ -412,16 +442,18 @@ ino_t ext2_inode_by_name(struct inode * dir, struct dentry *dentry)
void ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de,
struct page *page, struct inode *inode)
{
- unsigned from = (char *) de - (char *) page_address(page);
- unsigned to = from + le16_to_cpu(de->rec_len);
+ loff_t pos = page_offset(page) +
+ (char *) de - (char *) page_address(page);
+ unsigned len = ext2_rec_len_from_disk(de->rec_len);
int err;
lock_page(page);
- err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
+ err = __ext2_write_begin(NULL, page->mapping, pos, len,
+ AOP_FLAG_UNINTERRUPTIBLE, &page, NULL);
BUG_ON(err);
de->inode = cpu_to_le32(inode->i_ino);
- ext2_set_de_type (de, inode);
- err = ext2_commit_chunk(page, from, to);
+ ext2_set_de_type(de, inode);
+ err = ext2_commit_chunk(page, pos, len);
ext2_put_page(page);
dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
EXT2_I(dir)->i_flags &= ~EXT2_BTREE_FL;
@@ -444,7 +476,7 @@ int ext2_add_link (struct dentry *dentry, struct inode *inode)
unsigned long npages = dir_pages(dir);
unsigned long n;
char *kaddr;
- unsigned from, to;
+ loff_t pos;
int err;
/*
@@ -469,7 +501,7 @@ int ext2_add_link (struct dentry *dentry, struct inode *inode)
/* We hit i_size */
name_len = 0;
rec_len = chunk_size;
- de->rec_len = cpu_to_le16(chunk_size);
+ de->rec_len = ext2_rec_len_to_disk(chunk_size);
de->inode = 0;
goto got_it;
}
@@ -483,7 +515,7 @@ int ext2_add_link (struct dentry *dentry, struct inode *inode)
if (ext2_match (namelen, name, de))
goto out_unlock;
name_len = EXT2_DIR_REC_LEN(de->name_len);
- rec_len = le16_to_cpu(de->rec_len);
+ rec_len = ext2_rec_len_from_disk(de->rec_len);
if (!de->inode && rec_len >= reclen)
goto got_it;
if (rec_len >= name_len + reclen)
@@ -497,22 +529,23 @@ int ext2_add_link (struct dentry *dentry, struct inode *inode)
return -EINVAL;
got_it:
- from = (char*)de - (char*)page_address(page);
- to = from + rec_len;
- err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
+ pos = page_offset(page) +
+ (char*)de - (char*)page_address(page);
+ err = __ext2_write_begin(NULL, page->mapping, pos, rec_len, 0,
+ &page, NULL);
if (err)
goto out_unlock;
if (de->inode) {
ext2_dirent *de1 = (ext2_dirent *) ((char *) de + name_len);
- de1->rec_len = cpu_to_le16(rec_len - name_len);
- de->rec_len = cpu_to_le16(name_len);
+ de1->rec_len = ext2_rec_len_to_disk(rec_len - name_len);
+ de->rec_len = ext2_rec_len_to_disk(name_len);
de = de1;
}
de->name_len = namelen;
- memcpy (de->name, name, namelen);
+ memcpy(de->name, name, namelen);
de->inode = cpu_to_le32(inode->i_ino);
ext2_set_de_type (de, inode);
- err = ext2_commit_chunk(page, from, to);
+ err = ext2_commit_chunk(page, pos, rec_len);
dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
EXT2_I(dir)->i_flags &= ~EXT2_BTREE_FL;
mark_inode_dirty(dir);
@@ -536,7 +569,9 @@ int ext2_delete_entry (struct ext2_dir_entry_2 * dir, struct page * page )
struct inode *inode = mapping->host;
char *kaddr = page_address(page);
unsigned from = ((char*)dir - kaddr) & ~(ext2_chunk_size(inode)-1);
- unsigned to = ((char*)dir - kaddr) + le16_to_cpu(dir->rec_len);
+ unsigned to = ((char *)dir - kaddr) +
+ ext2_rec_len_from_disk(dir->rec_len);
+ loff_t pos;
ext2_dirent * pde = NULL;
ext2_dirent * de = (ext2_dirent *) (kaddr + from);
int err;
@@ -553,13 +588,15 @@ int ext2_delete_entry (struct ext2_dir_entry_2 * dir, struct page * page )
}
if (pde)
from = (char*)pde - (char*)page_address(page);
+ pos = page_offset(page) + from;
lock_page(page);
- err = mapping->a_ops->prepare_write(NULL, page, from, to);
+ err = __ext2_write_begin(NULL, page->mapping, pos, to - from, 0,
+ &page, NULL);
BUG_ON(err);
if (pde)
- pde->rec_len = cpu_to_le16(to-from);
+ pde->rec_len = ext2_rec_len_to_disk(to - from);
dir->inode = 0;
- err = ext2_commit_chunk(page, from, to);
+ err = ext2_commit_chunk(page, pos, to - from);
inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
EXT2_I(inode)->i_flags &= ~EXT2_BTREE_FL;
mark_inode_dirty(inode);
@@ -582,7 +619,9 @@ int ext2_make_empty(struct inode *inode, struct inode *parent)
if (!page)
return -ENOMEM;
- err = mapping->a_ops->prepare_write(NULL, page, 0, chunk_size);
+
+ err = __ext2_write_begin(NULL, page->mapping, 0, chunk_size, 0,
+ &page, NULL);
if (err) {
unlock_page(page);
goto fail;
@@ -591,14 +630,14 @@ int ext2_make_empty(struct inode *inode, struct inode *parent)
memset(kaddr, 0, chunk_size);
de = (struct ext2_dir_entry_2 *)kaddr;
de->name_len = 1;
- de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(1));
+ de->rec_len = ext2_rec_len_to_disk(EXT2_DIR_REC_LEN(1));
memcpy (de->name, ".\0\0", 4);
de->inode = cpu_to_le32(inode->i_ino);
ext2_set_de_type (de, inode);
de = (struct ext2_dir_entry_2 *)(kaddr + EXT2_DIR_REC_LEN(1));
de->name_len = 2;
- de->rec_len = cpu_to_le16(chunk_size - EXT2_DIR_REC_LEN(1));
+ de->rec_len = ext2_rec_len_to_disk(chunk_size - EXT2_DIR_REC_LEN(1));
de->inode = cpu_to_le32(parent->i_ino);
memcpy (de->name, "..\0", 4);
ext2_set_de_type (de, inode);
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
index 9fd0ec5ba0d0..7730388c4931 100644
--- a/fs/ext2/ext2.h
+++ b/fs/ext2/ext2.h
@@ -33,22 +33,9 @@ struct ext2_inode_info {
*/
__u32 i_block_group;
- /*
- * i_next_alloc_block is the logical (file-relative) number of the
- * most-recently-allocated block in this file. Yes, it is misnamed.
- * We use this for detecting linearly ascending allocation requests.
- */
- __u32 i_next_alloc_block;
+ /* block reservation info */
+ struct ext2_block_alloc_info *i_block_alloc_info;
- /*
- * i_next_alloc_goal is the *physical* companion to i_next_alloc_block.
- * it the the physical block number of the block which was most-recently
- * allocated to this file. This give us the goal (target) for the next
- * allocation when we detect linearly ascending requests.
- */
- __u32 i_next_alloc_goal;
- __u32 i_prealloc_block;
- __u32 i_prealloc_count;
__u32 i_dir_start_lookup;
#ifdef CONFIG_EXT2_FS_XATTR
/*
@@ -65,7 +52,16 @@ struct ext2_inode_info {
struct posix_acl *i_default_acl;
#endif
rwlock_t i_meta_lock;
+
+ /*
+ * truncate_mutex is for serialising ext2_truncate() against
+ * ext2_getblock(). It also protects the internals of the inode's
+ * reservation data structures: ext2_reserve_window and
+ * ext2_reserve_window_node.
+ */
+ struct mutex truncate_mutex;
struct inode vfs_inode;
+ struct list_head i_orphan; /* unlinked but open inodes */
};
/*
@@ -91,8 +87,9 @@ static inline struct ext2_inode_info *EXT2_I(struct inode *inode)
/* balloc.c */
extern int ext2_bg_has_super(struct super_block *sb, int group);
extern unsigned long ext2_bg_num_gdb(struct super_block *sb, int group);
-extern int ext2_new_block (struct inode *, unsigned long,
- __u32 *, __u32 *, int *);
+extern ext2_fsblk_t ext2_new_block(struct inode *, unsigned long, int *);
+extern ext2_fsblk_t ext2_new_blocks(struct inode *, unsigned long,
+ unsigned long *, int *);
extern void ext2_free_blocks (struct inode *, unsigned long,
unsigned long);
extern unsigned long ext2_count_free_blocks (struct super_block *);
@@ -101,6 +98,10 @@ extern void ext2_check_blocks_bitmap (struct super_block *);
extern struct ext2_group_desc * ext2_get_group_desc(struct super_block * sb,
unsigned int block_group,
struct buffer_head ** bh);
+extern void ext2_discard_reservation (struct inode *);
+extern int ext2_should_retry_alloc(struct super_block *sb, int *retries);
+extern void ext2_init_block_alloc_info(struct inode *);
+extern void ext2_rsv_window_add(struct super_block *sb, struct ext2_reserve_window_node *rsv);
/* dir.c */
extern int ext2_add_link (struct dentry *, struct inode *);
@@ -128,12 +129,14 @@ extern int ext2_write_inode (struct inode *, int);
extern void ext2_put_inode (struct inode *);
extern void ext2_delete_inode (struct inode *);
extern int ext2_sync_inode (struct inode *);
-extern void ext2_discard_prealloc (struct inode *);
extern int ext2_get_block(struct inode *, sector_t, struct buffer_head *, int);
extern void ext2_truncate (struct inode *);
extern int ext2_setattr (struct dentry *, struct iattr *);
extern void ext2_set_inode_flags(struct inode *inode);
extern void ext2_get_inode_flags(struct ext2_inode_info *);
+int __ext2_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata);
/* ioctl.c */
extern int ext2_ioctl (struct inode *, struct file *, unsigned int,
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index ab7961260c49..c051798459a1 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -30,8 +30,11 @@
*/
static int ext2_release_file (struct inode * inode, struct file * filp)
{
- if (filp->f_mode & FMODE_WRITE)
- ext2_discard_prealloc (inode);
+ if (filp->f_mode & FMODE_WRITE) {
+ mutex_lock(&EXT2_I(inode)->truncate_mutex);
+ ext2_discard_reservation(inode);
+ mutex_unlock(&EXT2_I(inode)->truncate_mutex);
+ }
return 0;
}
diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
index 2cb545bf0f3c..5deb8b74e649 100644
--- a/fs/ext2/ialloc.c
+++ b/fs/ext2/ialloc.c
@@ -177,7 +177,6 @@ static void ext2_preread_inode(struct inode *inode)
unsigned long block_group;
unsigned long offset;
unsigned long block;
- struct buffer_head *bh;
struct ext2_group_desc * gdp;
struct backing_dev_info *bdi;
@@ -188,7 +187,7 @@ static void ext2_preread_inode(struct inode *inode)
return;
block_group = (inode->i_ino - 1) / EXT2_INODES_PER_GROUP(inode->i_sb);
- gdp = ext2_get_group_desc(inode->i_sb, block_group, &bh);
+ gdp = ext2_get_group_desc(inode->i_sb, block_group, NULL);
if (gdp == NULL)
return;
@@ -217,11 +216,10 @@ static int find_group_dir(struct super_block *sb, struct inode *parent)
int ngroups = EXT2_SB(sb)->s_groups_count;
int avefreei = ext2_count_free_inodes(sb) / ngroups;
struct ext2_group_desc *desc, *best_desc = NULL;
- struct buffer_head *bh, *best_bh = NULL;
int group, best_group = -1;
for (group = 0; group < ngroups; group++) {
- desc = ext2_get_group_desc (sb, group, &bh);
+ desc = ext2_get_group_desc (sb, group, NULL);
if (!desc || !desc->bg_free_inodes_count)
continue;
if (le16_to_cpu(desc->bg_free_inodes_count) < avefreei)
@@ -231,7 +229,6 @@ static int find_group_dir(struct super_block *sb, struct inode *parent)
le16_to_cpu(best_desc->bg_free_blocks_count))) {
best_group = group;
best_desc = desc;
- best_bh = bh;
}
}
if (!best_desc)
@@ -284,7 +281,6 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent)
int max_debt, max_dirs, min_blocks, min_inodes;
int group = -1, i;
struct ext2_group_desc *desc;
- struct buffer_head *bh;
freei = percpu_counter_read_positive(&sbi->s_freeinodes_counter);
avefreei = freei / ngroups;
@@ -295,7 +291,6 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent)
if ((parent == sb->s_root->d_inode) ||
(EXT2_I(parent)->i_flags & EXT2_TOPDIR_FL)) {
struct ext2_group_desc *best_desc = NULL;
- struct buffer_head *best_bh = NULL;
int best_ndir = inodes_per_group;
int best_group = -1;
@@ -303,7 +298,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent)
parent_group = (unsigned)group % ngroups;
for (i = 0; i < ngroups; i++) {
group = (parent_group + i) % ngroups;
- desc = ext2_get_group_desc (sb, group, &bh);
+ desc = ext2_get_group_desc (sb, group, NULL);
if (!desc || !desc->bg_free_inodes_count)
continue;
if (le16_to_cpu(desc->bg_used_dirs_count) >= best_ndir)
@@ -315,11 +310,9 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent)
best_group = group;
best_ndir = le16_to_cpu(desc->bg_used_dirs_count);
best_desc = desc;
- best_bh = bh;
}
if (best_group >= 0) {
desc = best_desc;
- bh = best_bh;
group = best_group;
goto found;
}
@@ -345,7 +338,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent)
for (i = 0; i < ngroups; i++) {
group = (parent_group + i) % ngroups;
- desc = ext2_get_group_desc (sb, group, &bh);
+ desc = ext2_get_group_desc (sb, group, NULL);
if (!desc || !desc->bg_free_inodes_count)
continue;
if (sbi->s_debts[group] >= max_debt)
@@ -362,7 +355,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent)
fallback:
for (i = 0; i < ngroups; i++) {
group = (parent_group + i) % ngroups;
- desc = ext2_get_group_desc (sb, group, &bh);
+ desc = ext2_get_group_desc (sb, group, NULL);
if (!desc || !desc->bg_free_inodes_count)
continue;
if (le16_to_cpu(desc->bg_free_inodes_count) >= avefreei)
@@ -389,14 +382,13 @@ static int find_group_other(struct super_block *sb, struct inode *parent)
int parent_group = EXT2_I(parent)->i_block_group;
int ngroups = EXT2_SB(sb)->s_groups_count;
struct ext2_group_desc *desc;
- struct buffer_head *bh;
int group, i;
/*
* Try to place the inode in its parent directory
*/
group = parent_group;
- desc = ext2_get_group_desc (sb, group, &bh);
+ desc = ext2_get_group_desc (sb, group, NULL);
if (desc && le16_to_cpu(desc->bg_free_inodes_count) &&
le16_to_cpu(desc->bg_free_blocks_count))
goto found;
@@ -420,7 +412,7 @@ static int find_group_other(struct super_block *sb, struct inode *parent)
group += i;
if (group >= ngroups)
group -= ngroups;
- desc = ext2_get_group_desc (sb, group, &bh);
+ desc = ext2_get_group_desc (sb, group, NULL);
if (desc && le16_to_cpu(desc->bg_free_inodes_count) &&
le16_to_cpu(desc->bg_free_blocks_count))
goto found;
@@ -434,7 +426,7 @@ static int find_group_other(struct super_block *sb, struct inode *parent)
for (i = 0; i < ngroups; i++) {
if (++group >= ngroups)
group = 0;
- desc = ext2_get_group_desc (sb, group, &bh);
+ desc = ext2_get_group_desc (sb, group, NULL);
if (desc && le16_to_cpu(desc->bg_free_inodes_count))
goto found;
}
@@ -542,7 +534,7 @@ got:
goto fail;
}
- percpu_counter_mod(&sbi->s_freeinodes_counter, -1);
+ percpu_counter_add(&sbi->s_freeinodes_counter, -1);
if (S_ISDIR(mode))
percpu_counter_inc(&sbi->s_dirs_counter);
@@ -589,11 +581,8 @@ got:
ei->i_file_acl = 0;
ei->i_dir_acl = 0;
ei->i_dtime = 0;
+ ei->i_block_alloc_info = NULL;
ei->i_block_group = group;
- ei->i_next_alloc_block = 0;
- ei->i_next_alloc_goal = 0;
- ei->i_prealloc_block = 0;
- ei->i_prealloc_count = 0;
ei->i_dir_start_lookup = 0;
ei->i_state = EXT2_STATE_NEW;
ext2_set_inode_flags(inode);
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index 0079b2cd5314..b1ab32ab5a77 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -54,19 +54,6 @@ static inline int ext2_inode_is_fast_symlink(struct inode *inode)
}
/*
- * Called at each iput().
- *
- * The inode may be "bad" if ext2_read_inode() saw an error from
- * ext2_get_inode(), so we need to check that to avoid freeing random disk
- * blocks.
- */
-void ext2_put_inode(struct inode *inode)
-{
- if (!is_bad_inode(inode))
- ext2_discard_prealloc(inode);
-}
-
-/*
* Called at the last iput() if i_nlink is zero.
*/
void ext2_delete_inode (struct inode * inode)
@@ -89,61 +76,6 @@ no_delete:
clear_inode(inode); /* We must guarantee clearing of inode... */
}
-void ext2_discard_prealloc (struct inode * inode)
-{
-#ifdef EXT2_PREALLOCATE
- struct ext2_inode_info *ei = EXT2_I(inode);
- write_lock(&ei->i_meta_lock);
- if (ei->i_prealloc_count) {
- unsigned short total = ei->i_prealloc_count;
- unsigned long block = ei->i_prealloc_block;
- ei->i_prealloc_count = 0;
- ei->i_prealloc_block = 0;
- write_unlock(&ei->i_meta_lock);
- ext2_free_blocks (inode, block, total);
- return;
- } else
- write_unlock(&ei->i_meta_lock);
-#endif
-}
-
-static int ext2_alloc_block (struct inode * inode, unsigned long goal, int *err)
-{
-#ifdef EXT2FS_DEBUG
- static unsigned long alloc_hits, alloc_attempts;
-#endif
- unsigned long result;
-
-
-#ifdef EXT2_PREALLOCATE
- struct ext2_inode_info *ei = EXT2_I(inode);
- write_lock(&ei->i_meta_lock);
- if (ei->i_prealloc_count &&
- (goal == ei->i_prealloc_block || goal + 1 == ei->i_prealloc_block))
- {
- result = ei->i_prealloc_block++;
- ei->i_prealloc_count--;
- write_unlock(&ei->i_meta_lock);
- ext2_debug ("preallocation hit (%lu/%lu).\n",
- ++alloc_hits, ++alloc_attempts);
- } else {
- write_unlock(&ei->i_meta_lock);
- ext2_discard_prealloc (inode);
- ext2_debug ("preallocation miss (%lu/%lu).\n",
- alloc_hits, ++alloc_attempts);
- if (S_ISREG(inode->i_mode))
- result = ext2_new_block (inode, goal,
- &ei->i_prealloc_count,
- &ei->i_prealloc_block, err);
- else
- result = ext2_new_block(inode, goal, NULL, NULL, err);
- }
-#else
- result = ext2_new_block (inode, goal, 0, 0, err);
-#endif
- return result;
-}
-
typedef struct {
__le32 *p;
__le32 key;
@@ -228,7 +160,8 @@ static int ext2_block_to_path(struct inode *inode,
ext2_warning (inode->i_sb, "ext2_block_to_path", "block > big");
}
if (boundary)
- *boundary = (i_block & (ptrs - 1)) == (final - 1);
+ *boundary = final - 1 - (i_block & (ptrs - 1));
+
return n;
}
@@ -355,39 +288,129 @@ static unsigned long ext2_find_near(struct inode *inode, Indirect *ind)
* @block: block we want
* @chain: chain of indirect blocks
* @partial: pointer to the last triple within a chain
- * @goal: place to store the result.
*
- * Normally this function find the prefered place for block allocation,
- * stores it in *@goal and returns zero. If the branch had been changed
- * under us we return -EAGAIN.
+ * Returns preferred place for a block (the goal).
*/
static inline int ext2_find_goal(struct inode *inode,
long block,
Indirect chain[4],
- Indirect *partial,
- unsigned long *goal)
+ Indirect *partial)
{
- struct ext2_inode_info *ei = EXT2_I(inode);
- write_lock(&ei->i_meta_lock);
- if ((block == ei->i_next_alloc_block + 1) && ei->i_next_alloc_goal) {
- ei->i_next_alloc_block++;
- ei->i_next_alloc_goal++;
- }
- if (verify_chain(chain, partial)) {
- /*
- * try the heuristic for sequential allocation,
- * failing that at least try to get decent locality.
- */
- if (block == ei->i_next_alloc_block)
- *goal = ei->i_next_alloc_goal;
- if (!*goal)
- *goal = ext2_find_near(inode, partial);
- write_unlock(&ei->i_meta_lock);
- return 0;
+ struct ext2_block_alloc_info *block_i;
+
+ block_i = EXT2_I(inode)->i_block_alloc_info;
+
+ /*
+ * try the heuristic for sequential allocation,
+ * failing that at least try to get decent locality.
+ */
+ if (block_i && (block == block_i->last_alloc_logical_block + 1)
+ && (block_i->last_alloc_physical_block != 0)) {
+ return block_i->last_alloc_physical_block + 1;
+ }
+
+ return ext2_find_near(inode, partial);
+}
+
+/**
+ * ext2_blks_to_allocate: Look up the block map and count the number
+ * of direct blocks need to be allocated for the given branch.
+ *
+ * @branch: chain of indirect blocks
+ * @k: number of blocks need for indirect blocks
+ * @blks: number of data blocks to be mapped.
+ * @blocks_to_boundary: the offset in the indirect block
+ *
+ * return the total number of blocks to be allocate, including the
+ * direct and indirect blocks.
+ */
+static int
+ext2_blks_to_allocate(Indirect * branch, int k, unsigned long blks,
+ int blocks_to_boundary)
+{
+ unsigned long count = 0;
+
+ /*
+ * Simple case, [t,d]Indirect block(s) has not allocated yet
+ * then it's clear blocks on that path have not allocated
+ */
+ if (k > 0) {
+ /* right now don't hanel cross boundary allocation */
+ if (blks < blocks_to_boundary + 1)
+ count += blks;
+ else
+ count += blocks_to_boundary + 1;
+ return count;
+ }
+
+ count++;
+ while (count < blks && count <= blocks_to_boundary
+ && le32_to_cpu(*(branch[0].p + count)) == 0) {
+ count++;
}
- write_unlock(&ei->i_meta_lock);
- return -EAGAIN;
+ return count;
+}
+
+/**
+ * ext2_alloc_blocks: multiple allocate blocks needed for a branch
+ * @indirect_blks: the number of blocks need to allocate for indirect
+ * blocks
+ *
+ * @new_blocks: on return it will store the new block numbers for
+ * the indirect blocks(if needed) and the first direct block,
+ * @blks: on return it will store the total number of allocated
+ * direct blocks
+ */
+static int ext2_alloc_blocks(struct inode *inode,
+ ext2_fsblk_t goal, int indirect_blks, int blks,
+ ext2_fsblk_t new_blocks[4], int *err)
+{
+ int target, i;
+ unsigned long count = 0;
+ int index = 0;
+ ext2_fsblk_t current_block = 0;
+ int ret = 0;
+
+ /*
+ * Here we try to allocate the requested multiple blocks at once,
+ * on a best-effort basis.
+ * To build a branch, we should allocate blocks for
+ * the indirect blocks(if not allocated yet), and at least
+ * the first direct block of this branch. That's the
+ * minimum number of blocks need to allocate(required)
+ */
+ target = blks + indirect_blks;
+
+ while (1) {
+ count = target;
+ /* allocating blocks for indirect blocks and direct blocks */
+ current_block = ext2_new_blocks(inode,goal,&count,err);
+ if (*err)
+ goto failed_out;
+
+ target -= count;
+ /* allocate blocks for indirect blocks */
+ while (index < indirect_blks && count) {
+ new_blocks[index++] = current_block++;
+ count--;
+ }
+
+ if (count > 0)
+ break;
+ }
+
+ /* save the new block number for the first direct block */
+ new_blocks[index] = current_block;
+
+ /* total number of blocks allocated for direct blocks */
+ ret = count;
+ *err = 0;
+ return ret;
+failed_out:
+ for (i = 0; i <index; i++)
+ ext2_free_blocks(inode, new_blocks[i], 1);
+ return ret;
}
/**
@@ -416,39 +439,49 @@ static inline int ext2_find_goal(struct inode *inode,
*/
static int ext2_alloc_branch(struct inode *inode,
- int num,
- unsigned long goal,
- int *offsets,
- Indirect *branch)
+ int indirect_blks, int *blks, ext2_fsblk_t goal,
+ int *offsets, Indirect *branch)
{
int blocksize = inode->i_sb->s_blocksize;
- int n = 0;
- int err;
- int i;
- int parent = ext2_alloc_block(inode, goal, &err);
-
- branch[0].key = cpu_to_le32(parent);
- if (parent) for (n = 1; n < num; n++) {
- struct buffer_head *bh;
- /* Allocate the next block */
- int nr = ext2_alloc_block(inode, parent, &err);
- if (!nr)
- break;
- branch[n].key = cpu_to_le32(nr);
+ int i, n = 0;
+ int err = 0;
+ struct buffer_head *bh;
+ int num;
+ ext2_fsblk_t new_blocks[4];
+ ext2_fsblk_t current_block;
+
+ num = ext2_alloc_blocks(inode, goal, indirect_blks,
+ *blks, new_blocks, &err);
+ if (err)
+ return err;
+
+ branch[0].key = cpu_to_le32(new_blocks[0]);
+ /*
+ * metadata blocks and data blocks are allocated.
+ */
+ for (n = 1; n <= indirect_blks; n++) {
/*
- * Get buffer_head for parent block, zero it out and set
- * the pointer to new one, then send parent to disk.
+ * Get buffer_head for parent block, zero it out
+ * and set the pointer to new one, then send
+ * parent to disk.
*/
- bh = sb_getblk(inode->i_sb, parent);
- if (!bh) {
- err = -EIO;
- break;
- }
+ bh = sb_getblk(inode->i_sb, new_blocks[n-1]);
+ branch[n].bh = bh;
lock_buffer(bh);
memset(bh->b_data, 0, blocksize);
- branch[n].bh = bh;
branch[n].p = (__le32 *) bh->b_data + offsets[n];
+ branch[n].key = cpu_to_le32(new_blocks[n]);
*branch[n].p = branch[n].key;
+ if ( n == indirect_blks) {
+ current_block = new_blocks[n];
+ /*
+ * End of chain, update the last new metablock of
+ * the chain to point to the new allocated
+ * data blocks numbers
+ */
+ for (i=1; i < num; i++)
+ *(branch[n].p + i) = cpu_to_le32(++current_block);
+ }
set_buffer_uptodate(bh);
unlock_buffer(bh);
mark_buffer_dirty_inode(bh, inode);
@@ -458,77 +491,68 @@ static int ext2_alloc_branch(struct inode *inode,
*/
if (S_ISDIR(inode->i_mode) && IS_DIRSYNC(inode))
sync_dirty_buffer(bh);
- parent = nr;
}
- if (n == num)
- return 0;
-
- /* Allocation failed, free what we already allocated */
- for (i = 1; i < n; i++)
- bforget(branch[i].bh);
- for (i = 0; i < n; i++)
- ext2_free_blocks(inode, le32_to_cpu(branch[i].key), 1);
+ *blks = num;
return err;
}
/**
- * ext2_splice_branch - splice the allocated branch onto inode.
- * @inode: owner
- * @block: (logical) number of block we are adding
- * @chain: chain of indirect blocks (with a missing link - see
- * ext2_alloc_branch)
- * @where: location of missing link
- * @num: number of blocks we are adding
+ * ext2_splice_branch - splice the allocated branch onto inode.
+ * @inode: owner
+ * @block: (logical) number of block we are adding
+ * @chain: chain of indirect blocks (with a missing link - see
+ * ext2_alloc_branch)
+ * @where: location of missing link
+ * @num: number of indirect blocks we are adding
+ * @blks: number of direct blocks we are adding
*
- * This function verifies that chain (up to the missing link) had not
- * changed, fills the missing link and does all housekeeping needed in
- * inode (->i_blocks, etc.). In case of success we end up with the full
- * chain to new block and return 0. Otherwise (== chain had been changed)
- * we free the new blocks (forgetting their buffer_heads, indeed) and
- * return -EAGAIN.
+ * This function fills the missing link and does all housekeeping needed in
+ * inode (->i_blocks, etc.). In case of success we end up with the full
+ * chain to new block and return 0.
*/
-
-static inline int ext2_splice_branch(struct inode *inode,
- long block,
- Indirect chain[4],
- Indirect *where,
- int num)
+static void ext2_splice_branch(struct inode *inode,
+ long block, Indirect *where, int num, int blks)
{
- struct ext2_inode_info *ei = EXT2_I(inode);
int i;
+ struct ext2_block_alloc_info *block_i;
+ ext2_fsblk_t current_block;
- /* Verify that place we are splicing to is still there and vacant */
-
- write_lock(&ei->i_meta_lock);
- if (!verify_chain(chain, where-1) || *where->p)
- goto changed;
+ block_i = EXT2_I(inode)->i_block_alloc_info;
+ /* XXX LOCKING probably should have i_meta_lock ?*/
/* That's it */
*where->p = where->key;
- ei->i_next_alloc_block = block;
- ei->i_next_alloc_goal = le32_to_cpu(where[num-1].key);
- write_unlock(&ei->i_meta_lock);
+ /*
+ * Update the host buffer_head or inode to point to more just allocated
+ * direct blocks blocks
+ */
+ if (num == 0 && blks > 1) {
+ current_block = le32_to_cpu(where->key) + 1;
+ for (i = 1; i < blks; i++)
+ *(where->p + i ) = cpu_to_le32(current_block++);
+ }
+
+ /*
+ * update the most recently allocated logical & physical block
+ * in i_block_alloc_info, to assist find the proper goal block for next
+ * allocation
+ */
+ if (block_i) {
+ block_i->last_alloc_logical_block = block + blks - 1;
+ block_i->last_alloc_physical_block =
+ le32_to_cpu(where[num].key) + blks - 1;
+ }
/* We are done with atomic stuff, now do the rest of housekeeping */
- inode->i_ctime = CURRENT_TIME_SEC;
-
/* had we spliced it onto indirect block? */
if (where->bh)
mark_buffer_dirty_inode(where->bh, inode);
+ inode->i_ctime = CURRENT_TIME_SEC;
mark_inode_dirty(inode);
- return 0;
-
-changed:
- write_unlock(&ei->i_meta_lock);
- for (i = 1; i < num; i++)
- bforget(where[i].bh);
- for (i = 0; i < num; i++)
- ext2_free_blocks(inode, le32_to_cpu(where[i].key), 1);
- return -EAGAIN;
}
/*
@@ -542,64 +566,99 @@ changed:
* That has a nice additional property: no special recovery from the failed
* allocations is needed - we simply release blocks and do not touch anything
* reachable from inode.
+ *
+ * `handle' can be NULL if create == 0.
+ *
+ * The BKL may not be held on entry here. Be sure to take it early.
+ * return > 0, # of blocks mapped or allocated.
+ * return = 0, if plain lookup failed.
+ * return < 0, error case.
*/
-
-int ext2_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create)
+static int ext2_get_blocks(struct inode *inode,
+ sector_t iblock, unsigned long maxblocks,
+ struct buffer_head *bh_result,
+ int create)
{
int err = -EIO;
int offsets[4];
Indirect chain[4];
Indirect *partial;
- unsigned long goal;
- int left;
- int boundary = 0;
- int depth = ext2_block_to_path(inode, iblock, offsets, &boundary);
+ ext2_fsblk_t goal;
+ int indirect_blks;
+ int blocks_to_boundary = 0;
+ int depth;
+ struct ext2_inode_info *ei = EXT2_I(inode);
+ int count = 0;
+ ext2_fsblk_t first_block = 0;
- if (depth == 0)
- goto out;
+ depth = ext2_block_to_path(inode,iblock,offsets,&blocks_to_boundary);
+ if (depth == 0)
+ return (err);
reread:
partial = ext2_get_branch(inode, depth, offsets, chain, &err);
/* Simplest case - block found, no allocation needed */
if (!partial) {
-got_it:
- map_bh(bh_result, inode->i_sb, le32_to_cpu(chain[depth-1].key));
- if (boundary)
- set_buffer_boundary(bh_result);
- /* Clean up and exit */
- partial = chain+depth-1; /* the whole chain */
- goto cleanup;
+ first_block = le32_to_cpu(chain[depth - 1].key);
+ clear_buffer_new(bh_result); /* What's this do? */
+ count++;
+ /*map more blocks*/
+ while (count < maxblocks && count <= blocks_to_boundary) {
+ ext2_fsblk_t blk;
+
+ if (!verify_chain(chain, partial)) {
+ /*
+ * Indirect block might be removed by
+ * truncate while we were reading it.
+ * Handling of that case: forget what we've
+ * got now, go to reread.
+ */
+ count = 0;
+ goto changed;
+ }
+ blk = le32_to_cpu(*(chain[depth-1].p + count));
+ if (blk == first_block + count)
+ count++;
+ else
+ break;
+ }
+ goto got_it;
}
/* Next simple case - plain lookup or failed read of indirect block */
- if (!create || err == -EIO) {
-cleanup:
- while (partial > chain) {
- brelse(partial->bh);
- partial--;
- }
-out:
- return err;
- }
+ if (!create || err == -EIO)
+ goto cleanup;
+
+ mutex_lock(&ei->truncate_mutex);
/*
- * Indirect block might be removed by truncate while we were
- * reading it. Handling of that case (forget what we've got and
- * reread) is taken out of the main path.
- */
- if (err == -EAGAIN)
- goto changed;
+ * Okay, we need to do block allocation. Lazily initialize the block
+ * allocation info here if necessary
+ */
+ if (S_ISREG(inode->i_mode) && (!ei->i_block_alloc_info))
+ ext2_init_block_alloc_info(inode);
- goal = 0;
- if (ext2_find_goal(inode, iblock, chain, partial, &goal) < 0)
- goto changed;
+ goal = ext2_find_goal(inode, iblock, chain, partial);
- left = (chain + depth) - partial;
- err = ext2_alloc_branch(inode, left, goal,
- offsets+(partial-chain), partial);
- if (err)
+ /* the number of blocks need to allocate for [d,t]indirect blocks */
+ indirect_blks = (chain + depth) - partial - 1;
+ /*
+ * Next look up the indirect map to count the totoal number of
+ * direct blocks to allocate for this branch.
+ */
+ count = ext2_blks_to_allocate(partial, indirect_blks,
+ maxblocks, blocks_to_boundary);
+ /*
+ * XXX ???? Block out ext2_truncate while we alter the tree
+ */
+ err = ext2_alloc_branch(inode, indirect_blks, &count, goal,
+ offsets + (partial - chain), partial);
+
+ if (err) {
+ mutex_unlock(&ei->truncate_mutex);
goto cleanup;
+ }
if (ext2_use_xip(inode->i_sb)) {
/*
@@ -607,16 +666,28 @@ out:
*/
err = ext2_clear_xip_target (inode,
le32_to_cpu(chain[depth-1].key));
- if (err)
+ if (err) {
+ mutex_unlock(&ei->truncate_mutex);
goto cleanup;
+ }
}
- if (ext2_splice_branch(inode, iblock, chain, partial, left) < 0)
- goto changed;
-
+ ext2_splice_branch(inode, iblock, partial, indirect_blks, count);
+ mutex_unlock(&ei->truncate_mutex);
set_buffer_new(bh_result);
- goto got_it;
-
+got_it:
+ map_bh(bh_result, inode->i_sb, le32_to_cpu(chain[depth-1].key));
+ if (count > blocks_to_boundary)
+ set_buffer_boundary(bh_result);
+ err = count;
+ /* Clean up and exit */
+ partial = chain + depth - 1; /* the whole chain */
+cleanup:
+ while (partial > chain) {
+ brelse(partial->bh);
+ partial--;
+ }
+ return err;
changed:
while (partial > chain) {
brelse(partial->bh);
@@ -625,6 +696,19 @@ changed:
goto reread;
}
+int ext2_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create)
+{
+ unsigned max_blocks = bh_result->b_size >> inode->i_blkbits;
+ int ret = ext2_get_blocks(inode, iblock, max_blocks,
+ bh_result, create);
+ if (ret > 0) {
+ bh_result->b_size = (ret << inode->i_blkbits);
+ ret = 0;
+ }
+ return ret;
+
+}
+
static int ext2_writepage(struct page *page, struct writeback_control *wbc)
{
return block_write_full_page(page, ext2_get_block, wbc);
@@ -642,18 +726,35 @@ ext2_readpages(struct file *file, struct address_space *mapping,
return mpage_readpages(mapping, pages, nr_pages, ext2_get_block);
}
+int __ext2_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
+{
+ return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
+ ext2_get_block);
+}
+
static int
-ext2_prepare_write(struct file *file, struct page *page,
- unsigned from, unsigned to)
+ext2_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
{
- return block_prepare_write(page,from,to,ext2_get_block);
+ *pagep = NULL;
+ return __ext2_write_begin(file, mapping, pos, len, flags, pagep,fsdata);
}
static int
-ext2_nobh_prepare_write(struct file *file, struct page *page,
- unsigned from, unsigned to)
+ext2_nobh_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
{
- return nobh_prepare_write(page,from,to,ext2_get_block);
+ /*
+ * Dir-in-pagecache still uses ext2_write_begin. Would have to rework
+ * directory handling code to pass around offsets rather than struct
+ * pages in order to make this work easily.
+ */
+ return nobh_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
+ ext2_get_block);
}
static int ext2_nobh_writepage(struct page *page,
@@ -689,8 +790,8 @@ const struct address_space_operations ext2_aops = {
.readpages = ext2_readpages,
.writepage = ext2_writepage,
.sync_page = block_sync_page,
- .prepare_write = ext2_prepare_write,
- .commit_write = generic_commit_write,
+ .write_begin = ext2_write_begin,
+ .write_end = generic_write_end,
.bmap = ext2_bmap,
.direct_IO = ext2_direct_IO,
.writepages = ext2_writepages,
@@ -707,8 +808,8 @@ const struct address_space_operations ext2_nobh_aops = {
.readpages = ext2_readpages,
.writepage = ext2_nobh_writepage,
.sync_page = block_sync_page,
- .prepare_write = ext2_nobh_prepare_write,
- .commit_write = nobh_commit_write,
+ .write_begin = ext2_nobh_write_begin,
+ .write_end = nobh_write_end,
.bmap = ext2_bmap,
.direct_IO = ext2_direct_IO,
.writepages = ext2_writepages,
@@ -896,9 +997,10 @@ static void ext2_free_branches(struct inode *inode, __le32 *p, __le32 *q, int de
ext2_free_data(inode, p, q);
}
-void ext2_truncate (struct inode * inode)
+void ext2_truncate(struct inode *inode)
{
__le32 *i_data = EXT2_I(inode)->i_data;
+ struct ext2_inode_info *ei = EXT2_I(inode);
int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
int offsets[4];
Indirect chain[4];
@@ -916,8 +1018,6 @@ void ext2_truncate (struct inode * inode)
if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
return;
- ext2_discard_prealloc(inode);
-
blocksize = inode->i_sb->s_blocksize;
iblock = (inode->i_size + blocksize-1)
>> EXT2_BLOCK_SIZE_BITS(inode->i_sb);
@@ -925,7 +1025,8 @@ void ext2_truncate (struct inode * inode)
if (mapping_is_xip(inode->i_mapping))
xip_truncate_page(inode->i_mapping, inode->i_size);
else if (test_opt(inode->i_sb, NOBH))
- nobh_truncate_page(inode->i_mapping, inode->i_size);
+ nobh_truncate_page(inode->i_mapping,
+ inode->i_size, ext2_get_block);
else
block_truncate_page(inode->i_mapping,
inode->i_size, ext2_get_block);
@@ -934,6 +1035,12 @@ void ext2_truncate (struct inode * inode)
if (n == 0)
return;
+ /*
+ * From here we block out all ext2_get_block() callers who want to
+ * modify the block allocation tree.
+ */
+ mutex_lock(&ei->truncate_mutex);
+
if (n == 1) {
ext2_free_data(inode, i_data+offsets[0],
i_data + EXT2_NDIR_BLOCKS);
@@ -986,6 +1093,10 @@ do_indirects:
case EXT2_TIND_BLOCK:
;
}
+
+ ext2_discard_reservation(inode);
+
+ mutex_unlock(&ei->truncate_mutex);
inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
if (inode_needs_sync(inode)) {
sync_mapping_buffers(inode->i_mapping);
@@ -1010,7 +1121,7 @@ static struct ext2_inode *ext2_get_inode(struct super_block *sb, ino_t ino,
goto Einval;
block_group = (ino - 1) / EXT2_INODES_PER_GROUP(sb);
- gdp = ext2_get_group_desc(sb, block_group, &bh);
+ gdp = ext2_get_group_desc(sb, block_group, NULL);
if (!gdp)
goto Egdp;
/*
@@ -1086,6 +1197,8 @@ void ext2_read_inode (struct inode * inode)
ei->i_acl = EXT2_ACL_NOT_CACHED;
ei->i_default_acl = EXT2_ACL_NOT_CACHED;
#endif
+ ei->i_block_alloc_info = NULL;
+
if (IS_ERR(raw_inode))
goto bad_inode;
@@ -1127,9 +1240,6 @@ void ext2_read_inode (struct inode * inode)
ei->i_dtime = 0;
inode->i_generation = le32_to_cpu(raw_inode->i_generation);
ei->i_state = 0;
- ei->i_next_alloc_block = 0;
- ei->i_next_alloc_goal = 0;
- ei->i_prealloc_count = 0;
ei->i_block_group = (ino - 1) / EXT2_INODES_PER_GROUP(inode->i_sb);
ei->i_dir_start_lookup = 0;
diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c
index 3bcd25422ee4..320b2cb3d4d2 100644
--- a/fs/ext2/ioctl.c
+++ b/fs/ext2/ioctl.c
@@ -22,6 +22,7 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
{
struct ext2_inode_info *ei = EXT2_I(inode);
unsigned int flags;
+ unsigned short rsv_window_size;
ext2_debug ("cmd = %u, arg = %lu\n", cmd, arg);
@@ -46,6 +47,11 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
flags &= ~EXT2_DIRSYNC_FL;
mutex_lock(&inode->i_mutex);
+ /* Is it quota file? Do not allow user to mess with it */
+ if (IS_NOQUOTA(inode)) {
+ mutex_unlock(&inode->i_mutex);
+ return -EPERM;
+ }
oldflags = ei->i_flags;
/*
@@ -83,6 +89,50 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
inode->i_ctime = CURRENT_TIME_SEC;
mark_inode_dirty(inode);
return 0;
+ case EXT2_IOC_GETRSVSZ:
+ if (test_opt(inode->i_sb, RESERVATION)
+ && S_ISREG(inode->i_mode)
+ && ei->i_block_alloc_info) {
+ rsv_window_size = ei->i_block_alloc_info->rsv_window_node.rsv_goal_size;
+ return put_user(rsv_window_size, (int __user *)arg);
+ }
+ return -ENOTTY;
+ case EXT2_IOC_SETRSVSZ: {
+
+ if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode))
+ return -ENOTTY;
+
+ if (IS_RDONLY(inode))
+ return -EROFS;
+
+ if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+ return -EACCES;
+
+ if (get_user(rsv_window_size, (int __user *)arg))
+ return -EFAULT;
+
+ if (rsv_window_size > EXT2_MAX_RESERVE_BLOCKS)
+ rsv_window_size = EXT2_MAX_RESERVE_BLOCKS;
+
+ /*
+ * need to allocate reservation structure for this inode
+ * before set the window size
+ */
+ /*
+ * XXX What lock should protect the rsv_goal_size?
+ * Accessed in ext2_get_block only. ext3 uses i_truncate.
+ */
+ mutex_lock(&ei->truncate_mutex);
+ if (!ei->i_block_alloc_info)
+ ext2_init_block_alloc_info(inode);
+
+ if (ei->i_block_alloc_info){
+ struct ext2_reserve_window_node *rsv = &ei->i_block_alloc_info->rsv_window_node;
+ rsv->rsv_goal_size = rsv_window_size;
+ }
+ mutex_unlock(&ei->truncate_mutex);
+ return 0;
+ }
default:
return -ENOTTY;
}
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 639a32c3c9c1..154e25f13d77 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -30,6 +30,7 @@
#include <linux/vfs.h>
#include <linux/seq_file.h>
#include <linux/mount.h>
+#include <linux/log2.h>
#include <asm/uaccess.h>
#include "ext2.h"
#include "xattr.h"
@@ -148,6 +149,7 @@ static struct inode *ext2_alloc_inode(struct super_block *sb)
ei->i_acl = EXT2_ACL_NOT_CACHED;
ei->i_default_acl = EXT2_ACL_NOT_CACHED;
#endif
+ ei->i_block_alloc_info = NULL;
ei->vfs_inode.i_version = 1;
return &ei->vfs_inode;
}
@@ -157,7 +159,7 @@ static void ext2_destroy_inode(struct inode *inode)
kmem_cache_free(ext2_inode_cachep, EXT2_I(inode));
}
-static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
+static void init_once(struct kmem_cache * cachep, void *foo)
{
struct ext2_inode_info *ei = (struct ext2_inode_info *) foo;
@@ -165,6 +167,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag
#ifdef CONFIG_EXT2_FS_XATTR
init_rwsem(&ei->xattr_sem);
#endif
+ mutex_init(&ei->truncate_mutex);
inode_init_once(&ei->vfs_inode);
}
@@ -187,6 +190,7 @@ static void destroy_inodecache(void)
static void ext2_clear_inode(struct inode *inode)
{
+ struct ext2_block_alloc_info *rsv = EXT2_I(inode)->i_block_alloc_info;
#ifdef CONFIG_EXT2_FS_POSIX_ACL
struct ext2_inode_info *ei = EXT2_I(inode);
@@ -199,14 +203,74 @@ static void ext2_clear_inode(struct inode *inode)
ei->i_default_acl = EXT2_ACL_NOT_CACHED;
}
#endif
+ ext2_discard_reservation(inode);
+ EXT2_I(inode)->i_block_alloc_info = NULL;
+ if (unlikely(rsv))
+ kfree(rsv);
}
static int ext2_show_options(struct seq_file *seq, struct vfsmount *vfs)
{
- struct ext2_sb_info *sbi = EXT2_SB(vfs->mnt_sb);
+ struct super_block *sb = vfs->mnt_sb;
+ struct ext2_sb_info *sbi = EXT2_SB(sb);
+ struct ext2_super_block *es = sbi->s_es;
+ unsigned long def_mount_opts;
+
+ def_mount_opts = le32_to_cpu(es->s_default_mount_opts);
- if (sbi->s_mount_opt & EXT2_MOUNT_GRPID)
+ if (sbi->s_sb_block != 1)
+ seq_printf(seq, ",sb=%lu", sbi->s_sb_block);
+ if (test_opt(sb, MINIX_DF))
+ seq_puts(seq, ",minixdf");
+ if (test_opt(sb, GRPID))
seq_puts(seq, ",grpid");
+ if (!test_opt(sb, GRPID) && (def_mount_opts & EXT2_DEFM_BSDGROUPS))
+ seq_puts(seq, ",nogrpid");
+ if (sbi->s_resuid != EXT2_DEF_RESUID ||
+ le16_to_cpu(es->s_def_resuid) != EXT2_DEF_RESUID) {
+ seq_printf(seq, ",resuid=%u", sbi->s_resuid);
+ }
+ if (sbi->s_resgid != EXT2_DEF_RESGID ||
+ le16_to_cpu(es->s_def_resgid) != EXT2_DEF_RESGID) {
+ seq_printf(seq, ",resgid=%u", sbi->s_resgid);
+ }
+ if (test_opt(sb, ERRORS_CONT)) {
+ int def_errors = le16_to_cpu(es->s_errors);
+
+ if (def_errors == EXT2_ERRORS_PANIC ||
+ def_errors == EXT2_ERRORS_RO) {
+ seq_puts(seq, ",errors=continue");
+ }
+ }
+ if (test_opt(sb, ERRORS_RO))
+ seq_puts(seq, ",errors=remount-ro");
+ if (test_opt(sb, ERRORS_PANIC))
+ seq_puts(seq, ",errors=panic");
+ if (test_opt(sb, NO_UID32))
+ seq_puts(seq, ",nouid32");
+ if (test_opt(sb, DEBUG))
+ seq_puts(seq, ",debug");
+ if (test_opt(sb, OLDALLOC))
+ seq_puts(seq, ",oldalloc");
+
+#ifdef CONFIG_EXT2_FS_XATTR
+ if (test_opt(sb, XATTR_USER))
+ seq_puts(seq, ",user_xattr");
+ if (!test_opt(sb, XATTR_USER) &&
+ (def_mount_opts & EXT2_DEFM_XATTR_USER)) {
+ seq_puts(seq, ",nouser_xattr");
+ }
+#endif
+
+#ifdef CONFIG_EXT2_FS_POSIX_ACL
+ if (test_opt(sb, POSIX_ACL))
+ seq_puts(seq, ",acl");
+ if (!test_opt(sb, POSIX_ACL) && (def_mount_opts & EXT2_DEFM_ACL))
+ seq_puts(seq, ",noacl");
+#endif
+
+ if (test_opt(sb, NOBH))
+ seq_puts(seq, ",nobh");
#if defined(CONFIG_QUOTA)
if (sbi->s_mount_opt & EXT2_MOUNT_USRQUOTA)
@@ -234,7 +298,6 @@ static const struct super_operations ext2_sops = {
.destroy_inode = ext2_destroy_inode,
.read_inode = ext2_read_inode,
.write_inode = ext2_write_inode,
- .put_inode = ext2_put_inode,
.delete_inode = ext2_delete_inode,
.put_super = ext2_put_super,
.write_super = ext2_write_super,
@@ -248,13 +311,10 @@ static const struct super_operations ext2_sops = {
#endif
};
-static struct dentry *ext2_get_dentry(struct super_block *sb, void *vobjp)
+static struct inode *ext2_nfs_get_inode(struct super_block *sb,
+ u64 ino, u32 generation)
{
- __u32 *objp = vobjp;
- unsigned long ino = objp[0];
- __u32 generation = objp[1];
struct inode *inode;
- struct dentry *result;
if (ino < EXT2_FIRST_INO(sb) && ino != EXT2_ROOT_INO)
return ERR_PTR(-ESTALE);
@@ -275,15 +335,21 @@ static struct dentry *ext2_get_dentry(struct super_block *sb, void *vobjp)
iput(inode);
return ERR_PTR(-ESTALE);
}
- /* now to find a dentry.
- * If possible, get a well-connected one
- */
- result = d_alloc_anon(inode);
- if (!result) {
- iput(inode);
- return ERR_PTR(-ENOMEM);
- }
- return result;
+ return inode;
+}
+
+static struct dentry *ext2_fh_to_dentry(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type)
+{
+ return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
+ ext2_nfs_get_inode);
+}
+
+static struct dentry *ext2_fh_to_parent(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type)
+{
+ return generic_fh_to_parent(sb, fid, fh_len, fh_type,
+ ext2_nfs_get_inode);
}
/* Yes, most of these are left as NULL!!
@@ -291,9 +357,10 @@ static struct dentry *ext2_get_dentry(struct super_block *sb, void *vobjp)
* systems, but can be improved upon.
* Currently only get_parent is required.
*/
-static struct export_operations ext2_export_ops = {
+static const struct export_operations ext2_export_ops = {
+ .fh_to_dentry = ext2_fh_to_dentry,
+ .fh_to_parent = ext2_fh_to_parent,
.get_parent = ext2_get_parent,
- .get_dentry = ext2_get_dentry,
};
static unsigned long get_sb_block(void **data)
@@ -322,7 +389,7 @@ enum {
Opt_err_ro, Opt_nouid32, Opt_nocheck, Opt_debug,
Opt_oldalloc, Opt_orlov, Opt_nobh, Opt_user_xattr, Opt_nouser_xattr,
Opt_acl, Opt_noacl, Opt_xip, Opt_ignore, Opt_err, Opt_quota,
- Opt_usrquota, Opt_grpquota
+ Opt_usrquota, Opt_grpquota, Opt_reservation, Opt_noreservation
};
static match_table_t tokens = {
@@ -354,6 +421,8 @@ static match_table_t tokens = {
{Opt_ignore, "noquota"},
{Opt_quota, "quota"},
{Opt_usrquota, "usrquota"},
+ {Opt_reservation, "reservation"},
+ {Opt_noreservation, "noreservation"},
{Opt_err, NULL}
};
@@ -486,6 +555,14 @@ static int parse_options (char * options,
break;
#endif
+ case Opt_reservation:
+ set_opt(sbi->s_mount_opt, RESERVATION);
+ printk("reservations ON\n");
+ break;
+ case Opt_noreservation:
+ clear_opt(sbi->s_mount_opt, RESERVATION);
+ printk("reservations OFF\n");
+ break;
case Opt_ignore:
break;
default:
@@ -653,11 +730,13 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
int db_count;
int i, j;
__le32 features;
+ int err;
sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
if (!sbi)
return -ENOMEM;
sb->s_fs_info = sbi;
+ sbi->s_sb_block = sb_block;
/*
* See what the current blocksize for the device is, and
@@ -725,6 +804,8 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
sbi->s_resuid = le16_to_cpu(es->s_def_resuid);
sbi->s_resgid = le16_to_cpu(es->s_def_resgid);
+ set_opt(sbi->s_mount_opt, RESERVATION);
+
if (!parse_options ((char *) data, sbi))
goto failed_mount;
@@ -804,7 +885,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
sbi->s_inode_size = le16_to_cpu(es->s_inode_size);
sbi->s_first_ino = le32_to_cpu(es->s_first_ino);
if ((sbi->s_inode_size < EXT2_GOOD_OLD_INODE_SIZE) ||
- (sbi->s_inode_size & (sbi->s_inode_size - 1)) ||
+ !is_power_of_2(sbi->s_inode_size) ||
(sbi->s_inode_size > blocksize)) {
printk ("EXT2-fs: unsupported inode size: %d\n",
sbi->s_inode_size);
@@ -906,12 +987,35 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
get_random_bytes(&sbi->s_next_generation, sizeof(u32));
spin_lock_init(&sbi->s_next_gen_lock);
- percpu_counter_init(&sbi->s_freeblocks_counter,
+ /* per fileystem reservation list head & lock */
+ spin_lock_init(&sbi->s_rsv_window_lock);
+ sbi->s_rsv_window_root = RB_ROOT;
+ /*
+ * Add a single, static dummy reservation to the start of the
+ * reservation window list --- it gives us a placeholder for
+ * append-at-start-of-list which makes the allocation logic
+ * _much_ simpler.
+ */
+ sbi->s_rsv_window_head.rsv_start = EXT2_RESERVE_WINDOW_NOT_ALLOCATED;
+ sbi->s_rsv_window_head.rsv_end = EXT2_RESERVE_WINDOW_NOT_ALLOCATED;
+ sbi->s_rsv_window_head.rsv_alloc_hit = 0;
+ sbi->s_rsv_window_head.rsv_goal_size = 0;
+ ext2_rsv_window_add(sb, &sbi->s_rsv_window_head);
+
+ err = percpu_counter_init(&sbi->s_freeblocks_counter,
ext2_count_free_blocks(sb));
- percpu_counter_init(&sbi->s_freeinodes_counter,
+ if (!err) {
+ err = percpu_counter_init(&sbi->s_freeinodes_counter,
ext2_count_free_inodes(sb));
- percpu_counter_init(&sbi->s_dirs_counter,
+ }
+ if (!err) {
+ err = percpu_counter_init(&sbi->s_dirs_counter,
ext2_count_dirs(sb));
+ }
+ if (err) {
+ printk(KERN_ERR "EXT2-fs: insufficient memory\n");
+ goto failed_mount3;
+ }
/*
* set up enough so that it can read an inode
*/
@@ -1193,7 +1297,7 @@ static ssize_t ext2_quota_read(struct super_block *sb, int type, char *data,
tmp_bh.b_state = 0;
err = ext2_get_block(inode, blk, &tmp_bh, 0);
- if (err)
+ if (err < 0)
return err;
if (!buffer_mapped(&tmp_bh)) /* A hole? */
memset(data, 0, tocopy);
@@ -1232,7 +1336,7 @@ static ssize_t ext2_quota_write(struct super_block *sb, int type,
tmp_bh.b_state = 0;
err = ext2_get_block(inode, blk, &tmp_bh, 1);
- if (err)
+ if (err < 0)
goto out;
if (offset || tocopy != EXT2_BLOCK_SIZE(sb))
bh = sb_bread(sb, tmp_bh.b_blocknr);
diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
index 247efd0b51d6..3e8683dbb13f 100644
--- a/fs/ext2/xattr.c
+++ b/fs/ext2/xattr.c
@@ -664,8 +664,7 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
s_first_data_block) +
EXT2_I(inode)->i_block_group *
EXT2_BLOCKS_PER_GROUP(sb);
- int block = ext2_new_block(inode, goal,
- NULL, NULL, &error);
+ int block = ext2_new_block(inode, goal, &error);
if (error)
goto cleanup;
ea_idebug(inode, "creating block %d", block);
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
index ca8aee6efe37..a8ba7e831278 100644
--- a/fs/ext3/balloc.c
+++ b/fs/ext3/balloc.c
@@ -570,7 +570,7 @@ do_more:
cpu_to_le16(le16_to_cpu(desc->bg_free_blocks_count) +
group_freed);
spin_unlock(sb_bgl_lock(sbi, block_group));
- percpu_counter_mod(&sbi->s_freeblocks_counter, count);
+ percpu_counter_add(&sbi->s_freeblocks_counter, count);
/* We dirtied the bitmap block */
BUFFER_TRACE(bitmap_bh, "dirtied bitmap block");
@@ -1633,7 +1633,7 @@ allocated:
gdp->bg_free_blocks_count =
cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count)-num);
spin_unlock(sb_bgl_lock(sbi, group_no));
- percpu_counter_mod(&sbi->s_freeblocks_counter, -num);
+ percpu_counter_sub(&sbi->s_freeblocks_counter, num);
BUFFER_TRACE(gdp_bh, "journal_dirty_metadata for group descriptor");
err = ext3_journal_dirty_metadata(handle, gdp_bh);
@@ -1733,14 +1733,6 @@ ext3_fsblk_t ext3_count_free_blocks(struct super_block *sb)
#endif
}
-static inline int
-block_in_use(ext3_fsblk_t block, struct super_block *sb, unsigned char *map)
-{
- return ext3_test_bit ((block -
- le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block)) %
- EXT3_BLOCKS_PER_GROUP(sb), map);
-}
-
static inline int test_root(int a, int b)
{
int num = b;
diff --git a/fs/ext3/bitmap.c b/fs/ext3/bitmap.c
index b9176eed98d1..6afc39d80253 100644
--- a/fs/ext3/bitmap.c
+++ b/fs/ext3/bitmap.c
@@ -13,7 +13,7 @@
#ifdef EXT3FS_DEBUG
-static int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
+static const int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
unsigned long ext3_count_free (struct buffer_head * map, unsigned int numchars)
{
diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c
index c00723a99f44..8ca3bfd72427 100644
--- a/fs/ext3/dir.c
+++ b/fs/ext3/dir.c
@@ -47,9 +47,7 @@ const struct file_operations ext3_dir_operations = {
.compat_ioctl = ext3_compat_ioctl,
#endif
.fsync = ext3_sync_file, /* BKL held */
-#ifdef CONFIG_EXT3_INDEX
.release = ext3_release_dir,
-#endif
};
@@ -69,7 +67,7 @@ int ext3_check_dir_entry (const char * function, struct inode * dir,
unsigned long offset)
{
const char * error_msg = NULL;
- const int rlen = le16_to_cpu(de->rec_len);
+ const int rlen = ext3_rec_len_from_disk(de->rec_len);
if (rlen < EXT3_DIR_REC_LEN(1))
error_msg = "rec_len is smaller than minimal";
@@ -107,7 +105,6 @@ static int ext3_readdir(struct file * filp,
sb = inode->i_sb;
-#ifdef CONFIG_EXT3_INDEX
if (EXT3_HAS_COMPAT_FEATURE(inode->i_sb,
EXT3_FEATURE_COMPAT_DIR_INDEX) &&
((EXT3_I(inode)->i_flags & EXT3_INDEX_FL) ||
@@ -123,7 +120,6 @@ static int ext3_readdir(struct file * filp,
*/
EXT3_I(filp->f_path.dentry->d_inode)->i_flags &= ~EXT3_INDEX_FL;
}
-#endif
stored = 0;
offset = filp->f_pos & (sb->s_blocksize - 1);
@@ -143,7 +139,7 @@ static int ext3_readdir(struct file * filp,
sb->s_bdev->bd_inode->i_mapping,
&filp->f_ra, filp,
index, 1);
- filp->f_ra.prev_index = index;
+ filp->f_ra.prev_pos = (loff_t)index << PAGE_CACHE_SHIFT;
bh = ext3_bread(NULL, inode, blk, 0, &err);
}
@@ -177,10 +173,10 @@ revalidate:
* least that it is non-zero. A
* failure will be detected in the
* dirent test below. */
- if (le16_to_cpu(de->rec_len) <
+ if (ext3_rec_len_from_disk(de->rec_len) <
EXT3_DIR_REC_LEN(1))
break;
- i += le16_to_cpu(de->rec_len);
+ i += ext3_rec_len_from_disk(de->rec_len);
}
offset = i;
filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1))
@@ -201,7 +197,7 @@ revalidate:
ret = stored;
goto out;
}
- offset += le16_to_cpu(de->rec_len);
+ offset += ext3_rec_len_from_disk(de->rec_len);
if (le32_to_cpu(de->inode)) {
/* We might block in the next section
* if the data destination is
@@ -210,7 +206,7 @@ revalidate:
* not the directory has been modified
* during the copy operation.
*/
- unsigned long version = filp->f_version;
+ u64 version = filp->f_version;
error = filldir(dirent, de->name,
de->name_len,
@@ -223,7 +219,7 @@ revalidate:
goto revalidate;
stored ++;
}
- filp->f_pos += le16_to_cpu(de->rec_len);
+ filp->f_pos += ext3_rec_len_from_disk(de->rec_len);
}
offset = 0;
brelse (bh);
@@ -232,7 +228,6 @@ out:
return ret;
}
-#ifdef CONFIG_EXT3_INDEX
/*
* These functions convert from the major/minor hash to an f_pos
* value.
@@ -518,5 +513,3 @@ static int ext3_release_dir (struct inode * inode, struct file * filp)
return 0;
}
-
-#endif
diff --git a/fs/ext3/fsync.c b/fs/ext3/fsync.c
index dd1fd3c0fc05..a588e23841d4 100644
--- a/fs/ext3/fsync.c
+++ b/fs/ext3/fsync.c
@@ -47,7 +47,7 @@ int ext3_sync_file(struct file * file, struct dentry *dentry, int datasync)
struct inode *inode = dentry->d_inode;
int ret = 0;
- J_ASSERT(ext3_journal_current_handle() == 0);
+ J_ASSERT(ext3_journal_current_handle() == NULL);
/*
* data=writeback:
diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
index e45dbd651736..1bc8cd89c51d 100644
--- a/fs/ext3/ialloc.c
+++ b/fs/ext3/ialloc.c
@@ -204,14 +204,13 @@ static int find_group_dir(struct super_block *sb, struct inode *parent)
int ngroups = EXT3_SB(sb)->s_groups_count;
unsigned int freei, avefreei;
struct ext3_group_desc *desc, *best_desc = NULL;
- struct buffer_head *bh;
int group, best_group = -1;
freei = percpu_counter_read_positive(&EXT3_SB(sb)->s_freeinodes_counter);
avefreei = freei / ngroups;
for (group = 0; group < ngroups; group++) {
- desc = ext3_get_group_desc (sb, group, &bh);
+ desc = ext3_get_group_desc (sb, group, NULL);
if (!desc || !desc->bg_free_inodes_count)
continue;
if (le16_to_cpu(desc->bg_free_inodes_count) < avefreei)
@@ -269,7 +268,6 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent)
ext3_grpblk_t min_blocks;
int group = -1, i;
struct ext3_group_desc *desc;
- struct buffer_head *bh;
freei = percpu_counter_read_positive(&sbi->s_freeinodes_counter);
avefreei = freei / ngroups;
@@ -286,7 +284,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent)
parent_group = (unsigned)group % ngroups;
for (i = 0; i < ngroups; i++) {
group = (parent_group + i) % ngroups;
- desc = ext3_get_group_desc (sb, group, &bh);
+ desc = ext3_get_group_desc (sb, group, NULL);
if (!desc || !desc->bg_free_inodes_count)
continue;
if (le16_to_cpu(desc->bg_used_dirs_count) >= best_ndir)
@@ -319,7 +317,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent)
for (i = 0; i < ngroups; i++) {
group = (parent_group + i) % ngroups;
- desc = ext3_get_group_desc (sb, group, &bh);
+ desc = ext3_get_group_desc (sb, group, NULL);
if (!desc || !desc->bg_free_inodes_count)
continue;
if (le16_to_cpu(desc->bg_used_dirs_count) >= max_dirs)
@@ -334,7 +332,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent)
fallback:
for (i = 0; i < ngroups; i++) {
group = (parent_group + i) % ngroups;
- desc = ext3_get_group_desc (sb, group, &bh);
+ desc = ext3_get_group_desc (sb, group, NULL);
if (!desc || !desc->bg_free_inodes_count)
continue;
if (le16_to_cpu(desc->bg_free_inodes_count) >= avefreei)
@@ -358,14 +356,13 @@ static int find_group_other(struct super_block *sb, struct inode *parent)
int parent_group = EXT3_I(parent)->i_block_group;
int ngroups = EXT3_SB(sb)->s_groups_count;
struct ext3_group_desc *desc;
- struct buffer_head *bh;
int group, i;
/*
* Try to place the inode in its parent directory
*/
group = parent_group;
- desc = ext3_get_group_desc (sb, group, &bh);
+ desc = ext3_get_group_desc (sb, group, NULL);
if (desc && le16_to_cpu(desc->bg_free_inodes_count) &&
le16_to_cpu(desc->bg_free_blocks_count))
return group;
@@ -389,7 +386,7 @@ static int find_group_other(struct super_block *sb, struct inode *parent)
group += i;
if (group >= ngroups)
group -= ngroups;
- desc = ext3_get_group_desc (sb, group, &bh);
+ desc = ext3_get_group_desc (sb, group, NULL);
if (desc && le16_to_cpu(desc->bg_free_inodes_count) &&
le16_to_cpu(desc->bg_free_blocks_count))
return group;
@@ -403,7 +400,7 @@ static int find_group_other(struct super_block *sb, struct inode *parent)
for (i = 0; i < ngroups; i++) {
if (++group >= ngroups)
group = 0;
- desc = ext3_get_group_desc (sb, group, &bh);
+ desc = ext3_get_group_desc (sb, group, NULL);
if (desc && le16_to_cpu(desc->bg_free_inodes_count))
return group;
}
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index de4e3161e479..9b162cd6c16c 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -1028,7 +1028,7 @@ struct buffer_head *ext3_getblk(handle_t *handle, struct inode *inode,
}
if (buffer_new(&dummy)) {
J_ASSERT(create != 0);
- J_ASSERT(handle != 0);
+ J_ASSERT(handle != NULL);
/*
* Now that we do not always journal data, we should
@@ -1147,51 +1147,68 @@ static int do_journal_get_write_access(handle_t *handle,
return ext3_journal_get_write_access(handle, bh);
}
-static int ext3_prepare_write(struct file *file, struct page *page,
- unsigned from, unsigned to)
+static int ext3_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
{
- struct inode *inode = page->mapping->host;
+ struct inode *inode = mapping->host;
int ret, needed_blocks = ext3_writepage_trans_blocks(inode);
handle_t *handle;
int retries = 0;
+ struct page *page;
+ pgoff_t index;
+ unsigned from, to;
+
+ index = pos >> PAGE_CACHE_SHIFT;
+ from = pos & (PAGE_CACHE_SIZE - 1);
+ to = from + len;
retry:
+ page = __grab_cache_page(mapping, index);
+ if (!page)
+ return -ENOMEM;
+ *pagep = page;
+
handle = ext3_journal_start(inode, needed_blocks);
if (IS_ERR(handle)) {
+ unlock_page(page);
+ page_cache_release(page);
ret = PTR_ERR(handle);
goto out;
}
- if (test_opt(inode->i_sb, NOBH) && ext3_should_writeback_data(inode))
- ret = nobh_prepare_write(page, from, to, ext3_get_block);
- else
- ret = block_prepare_write(page, from, to, ext3_get_block);
+ ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
+ ext3_get_block);
if (ret)
- goto prepare_write_failed;
+ goto write_begin_failed;
if (ext3_should_journal_data(inode)) {
ret = walk_page_buffers(handle, page_buffers(page),
from, to, NULL, do_journal_get_write_access);
}
-prepare_write_failed:
- if (ret)
+write_begin_failed:
+ if (ret) {
ext3_journal_stop(handle);
+ unlock_page(page);
+ page_cache_release(page);
+ }
if (ret == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries))
goto retry;
out:
return ret;
}
+
int ext3_journal_dirty_data(handle_t *handle, struct buffer_head *bh)
{
int err = journal_dirty_data(handle, bh);
if (err)
ext3_journal_abort_handle(__FUNCTION__, __FUNCTION__,
- bh, handle,err);
+ bh, handle, err);
return err;
}
-/* For commit_write() in data=journal mode */
-static int commit_write_fn(handle_t *handle, struct buffer_head *bh)
+/* For write_end() in data=journal mode */
+static int write_end_fn(handle_t *handle, struct buffer_head *bh)
{
if (!buffer_mapped(bh) || buffer_freed(bh))
return 0;
@@ -1200,84 +1217,130 @@ static int commit_write_fn(handle_t *handle, struct buffer_head *bh)
}
/*
+ * Generic write_end handler for ordered and writeback ext3 journal modes.
+ * We can't use generic_write_end, because that unlocks the page and we need to
+ * unlock the page after ext3_journal_stop, but ext3_journal_stop must run
+ * after block_write_end.
+ */
+static int ext3_generic_write_end(struct file *file,
+ struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata)
+{
+ struct inode *inode = file->f_mapping->host;
+
+ copied = block_write_end(file, mapping, pos, len, copied, page, fsdata);
+
+ if (pos+copied > inode->i_size) {
+ i_size_write(inode, pos+copied);
+ mark_inode_dirty(inode);
+ }
+
+ return copied;
+}
+
+/*
* We need to pick up the new inode size which generic_commit_write gave us
* `file' can be NULL - eg, when called from page_symlink().
*
* ext3 never places buffers on inode->i_mapping->private_list. metadata
* buffers are managed internally.
*/
-static int ext3_ordered_commit_write(struct file *file, struct page *page,
- unsigned from, unsigned to)
+static int ext3_ordered_write_end(struct file *file,
+ struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata)
{
handle_t *handle = ext3_journal_current_handle();
- struct inode *inode = page->mapping->host;
+ struct inode *inode = file->f_mapping->host;
+ unsigned from, to;
int ret = 0, ret2;
+ from = pos & (PAGE_CACHE_SIZE - 1);
+ to = from + len;
+
ret = walk_page_buffers(handle, page_buffers(page),
from, to, NULL, ext3_journal_dirty_data);
if (ret == 0) {
/*
- * generic_commit_write() will run mark_inode_dirty() if i_size
+ * generic_write_end() will run mark_inode_dirty() if i_size
* changes. So let's piggyback the i_disksize mark_inode_dirty
* into that.
*/
loff_t new_i_size;
- new_i_size = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
+ new_i_size = pos + copied;
if (new_i_size > EXT3_I(inode)->i_disksize)
EXT3_I(inode)->i_disksize = new_i_size;
- ret = generic_commit_write(file, page, from, to);
+ copied = ext3_generic_write_end(file, mapping, pos, len, copied,
+ page, fsdata);
+ if (copied < 0)
+ ret = copied;
}
ret2 = ext3_journal_stop(handle);
if (!ret)
ret = ret2;
- return ret;
+ unlock_page(page);
+ page_cache_release(page);
+
+ return ret ? ret : copied;
}
-static int ext3_writeback_commit_write(struct file *file, struct page *page,
- unsigned from, unsigned to)
+static int ext3_writeback_write_end(struct file *file,
+ struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata)
{
handle_t *handle = ext3_journal_current_handle();
- struct inode *inode = page->mapping->host;
+ struct inode *inode = file->f_mapping->host;
int ret = 0, ret2;
loff_t new_i_size;
- new_i_size = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
+ new_i_size = pos + copied;
if (new_i_size > EXT3_I(inode)->i_disksize)
EXT3_I(inode)->i_disksize = new_i_size;
- if (test_opt(inode->i_sb, NOBH) && ext3_should_writeback_data(inode))
- ret = nobh_commit_write(file, page, from, to);
- else
- ret = generic_commit_write(file, page, from, to);
+ copied = ext3_generic_write_end(file, mapping, pos, len, copied,
+ page, fsdata);
+ if (copied < 0)
+ ret = copied;
ret2 = ext3_journal_stop(handle);
if (!ret)
ret = ret2;
- return ret;
+ unlock_page(page);
+ page_cache_release(page);
+
+ return ret ? ret : copied;
}
-static int ext3_journalled_commit_write(struct file *file,
- struct page *page, unsigned from, unsigned to)
+static int ext3_journalled_write_end(struct file *file,
+ struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata)
{
handle_t *handle = ext3_journal_current_handle();
- struct inode *inode = page->mapping->host;
+ struct inode *inode = mapping->host;
int ret = 0, ret2;
int partial = 0;
- loff_t pos;
+ unsigned from, to;
- /*
- * Here we duplicate the generic_commit_write() functionality
- */
- pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
+ from = pos & (PAGE_CACHE_SIZE - 1);
+ to = from + len;
+
+ if (copied < len) {
+ if (!PageUptodate(page))
+ copied = 0;
+ page_zero_new_buffers(page, from+copied, to);
+ }
ret = walk_page_buffers(handle, page_buffers(page), from,
- to, &partial, commit_write_fn);
+ to, &partial, write_end_fn);
if (!partial)
SetPageUptodate(page);
- if (pos > inode->i_size)
- i_size_write(inode, pos);
+ if (pos+copied > inode->i_size)
+ i_size_write(inode, pos+copied);
EXT3_I(inode)->i_state |= EXT3_STATE_JDATA;
if (inode->i_size > EXT3_I(inode)->i_disksize) {
EXT3_I(inode)->i_disksize = inode->i_size;
@@ -1285,10 +1348,14 @@ static int ext3_journalled_commit_write(struct file *file,
if (!ret)
ret = ret2;
}
+
ret2 = ext3_journal_stop(handle);
if (!ret)
ret = ret2;
- return ret;
+ unlock_page(page);
+ page_cache_release(page);
+
+ return ret ? ret : copied;
}
/*
@@ -1546,7 +1613,7 @@ static int ext3_journalled_writepage(struct page *page,
PAGE_CACHE_SIZE, NULL, do_journal_get_write_access);
err = walk_page_buffers(handle, page_buffers(page), 0,
- PAGE_CACHE_SIZE, NULL, commit_write_fn);
+ PAGE_CACHE_SIZE, NULL, write_end_fn);
if (ret == 0)
ret = err;
EXT3_I(inode)->i_state |= EXT3_STATE_JDATA;
@@ -1706,8 +1773,8 @@ static const struct address_space_operations ext3_ordered_aops = {
.readpages = ext3_readpages,
.writepage = ext3_ordered_writepage,
.sync_page = block_sync_page,
- .prepare_write = ext3_prepare_write,
- .commit_write = ext3_ordered_commit_write,
+ .write_begin = ext3_write_begin,
+ .write_end = ext3_ordered_write_end,
.bmap = ext3_bmap,
.invalidatepage = ext3_invalidatepage,
.releasepage = ext3_releasepage,
@@ -1720,8 +1787,8 @@ static const struct address_space_operations ext3_writeback_aops = {
.readpages = ext3_readpages,
.writepage = ext3_writeback_writepage,
.sync_page = block_sync_page,
- .prepare_write = ext3_prepare_write,
- .commit_write = ext3_writeback_commit_write,
+ .write_begin = ext3_write_begin,
+ .write_end = ext3_writeback_write_end,
.bmap = ext3_bmap,
.invalidatepage = ext3_invalidatepage,
.releasepage = ext3_releasepage,
@@ -1734,8 +1801,8 @@ static const struct address_space_operations ext3_journalled_aops = {
.readpages = ext3_readpages,
.writepage = ext3_journalled_writepage,
.sync_page = block_sync_page,
- .prepare_write = ext3_prepare_write,
- .commit_write = ext3_journalled_commit_write,
+ .write_begin = ext3_write_begin,
+ .write_end = ext3_journalled_write_end,
.set_page_dirty = ext3_journalled_set_page_dirty,
.bmap = ext3_bmap,
.invalidatepage = ext3_invalidatepage,
@@ -2887,7 +2954,7 @@ int ext3_write_inode(struct inode *inode, int wait)
return 0;
if (ext3_journal_current_handle()) {
- jbd_debug(0, "called recursively, non-PF_MEMALLOC!\n");
+ jbd_debug(1, "called recursively, non-PF_MEMALLOC!\n");
dump_stack();
return -EIO;
}
diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c
index 4a2a02c95bf9..023a070f55f1 100644
--- a/fs/ext3/ioctl.c
+++ b/fs/ext3/ioctl.c
@@ -51,6 +51,11 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
flags &= ~EXT3_DIRSYNC_FL;
mutex_lock(&inode->i_mutex);
+ /* Is it quota file? Do not allow user to mess with it */
+ if (IS_NOQUOTA(inode)) {
+ mutex_unlock(&inode->i_mutex);
+ return -EPERM;
+ }
oldflags = ei->i_flags;
/* The JOURNAL_DATA flag is modifiable only by root */
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index c1fa1908dba0..4ab6f76e63d0 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -144,7 +144,6 @@ struct dx_map_entry
u16 size;
};
-#ifdef CONFIG_EXT3_INDEX
static inline unsigned dx_get_block (struct dx_entry *entry);
static void dx_set_block (struct dx_entry *entry, unsigned value);
static inline unsigned dx_get_hash (struct dx_entry *entry);
@@ -178,6 +177,16 @@ static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry,
struct inode *inode);
/*
+ * p is at least 6 bytes before the end of page
+ */
+static inline struct ext3_dir_entry_2 *
+ext3_next_entry(struct ext3_dir_entry_2 *p)
+{
+ return (struct ext3_dir_entry_2 *)((char *)p +
+ ext3_rec_len_from_disk(p->rec_len));
+}
+
+/*
* Future: use high four bits of block for coalesce-on-delete flags
* Mask them off for now.
*/
@@ -281,7 +290,7 @@ static struct stats dx_show_leaf(struct dx_hash_info *hinfo, struct ext3_dir_ent
space += EXT3_DIR_REC_LEN(de->name_len);
names++;
}
- de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
+ de = ext3_next_entry(de);
}
printk("(%i)\n", names);
return (struct stats) { names, space, 1 };
@@ -548,14 +557,6 @@ static int ext3_htree_next_block(struct inode *dir, __u32 hash,
/*
- * p is at least 6 bytes before the end of page
- */
-static inline struct ext3_dir_entry_2 *ext3_next_entry(struct ext3_dir_entry_2 *p)
-{
- return (struct ext3_dir_entry_2 *)((char*)p + le16_to_cpu(p->rec_len));
-}
-
-/*
* This function fills a red-black tree with information from a
* directory block. It returns the number directory entries loaded
* into the tree. If there is an error it is returned in err.
@@ -721,7 +722,7 @@ static int dx_make_map (struct ext3_dir_entry_2 *de, int size,
cond_resched();
}
/* XXX: do we need to check rec_len == 0 case? -Chris */
- de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
+ de = ext3_next_entry(de);
}
return count;
}
@@ -768,8 +769,6 @@ static void dx_insert_block(struct dx_frame *frame, u32 hash, u32 block)
dx_set_block(new, block);
dx_set_count(entries, count + 1);
}
-#endif
-
static void ext3_update_dx_flag(struct inode *inode)
{
@@ -825,7 +824,7 @@ static inline int search_dirblock(struct buffer_head * bh,
return 1;
}
/* prevent looping on a bad block */
- de_len = le16_to_cpu(de->rec_len);
+ de_len = ext3_rec_len_from_disk(de->rec_len);
if (de_len <= 0)
return -1;
offset += de_len;
@@ -871,7 +870,6 @@ static struct buffer_head * ext3_find_entry (struct dentry *dentry,
name = dentry->d_name.name;
if (namelen > EXT3_NAME_LEN)
return NULL;
-#ifdef CONFIG_EXT3_INDEX
if (is_dx(dir)) {
bh = ext3_dx_find_entry(dentry, res_dir, &err);
/*
@@ -883,7 +881,6 @@ static struct buffer_head * ext3_find_entry (struct dentry *dentry,
return bh;
dxtrace(printk("ext3_find_entry: dx failed, falling back\n"));
}
-#endif
nblocks = dir->i_size >> EXT3_BLOCK_SIZE_BITS(sb);
start = EXT3_I(dir)->i_dir_start_lookup;
if (start >= nblocks)
@@ -959,7 +956,6 @@ cleanup_and_exit:
return ret;
}
-#ifdef CONFIG_EXT3_INDEX
static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry,
struct ext3_dir_entry_2 **res_dir, int *err)
{
@@ -1027,7 +1023,6 @@ errout:
dx_release (frames);
return NULL;
}
-#endif
static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
{
@@ -1123,7 +1118,6 @@ static inline void ext3_set_de_type(struct super_block *sb,
de->file_type = ext3_type_by_mode[(mode & S_IFMT)>>S_SHIFT];
}
-#ifdef CONFIG_EXT3_INDEX
/*
* Move count entries from end of map between two memory locations.
* Returns pointer to last entry moved.
@@ -1138,7 +1132,7 @@ dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count)
rec_len = EXT3_DIR_REC_LEN(de->name_len);
memcpy (to, de, rec_len);
((struct ext3_dir_entry_2 *) to)->rec_len =
- cpu_to_le16(rec_len);
+ ext3_rec_len_to_disk(rec_len);
de->inode = 0;
map++;
to += rec_len;
@@ -1157,13 +1151,12 @@ static struct ext3_dir_entry_2* dx_pack_dirents(char *base, int size)
prev = to = de;
while ((char*)de < base + size) {
- next = (struct ext3_dir_entry_2 *) ((char *) de +
- le16_to_cpu(de->rec_len));
+ next = ext3_next_entry(de);
if (de->inode && de->name_len) {
rec_len = EXT3_DIR_REC_LEN(de->name_len);
if (de > to)
memmove(to, de, rec_len);
- to->rec_len = cpu_to_le16(rec_len);
+ to->rec_len = ext3_rec_len_to_disk(rec_len);
prev = to;
to = (struct ext3_dir_entry_2 *) (((char *) to) + rec_len);
}
@@ -1237,8 +1230,8 @@ static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
/* Fancy dance to stay within two buffers */
de2 = dx_move_dirents(data1, data2, map + split, count - split);
de = dx_pack_dirents(data1,blocksize);
- de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
- de2->rec_len = cpu_to_le16(data2 + blocksize - (char *) de2);
+ de->rec_len = ext3_rec_len_to_disk(data1 + blocksize - (char *) de);
+ de2->rec_len = ext3_rec_len_to_disk(data2 + blocksize - (char *) de2);
dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data1, blocksize, 1));
dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data2, blocksize, 1));
@@ -1268,7 +1261,6 @@ errout:
*error = err;
return NULL;
}
-#endif
/*
@@ -1309,7 +1301,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
return -EEXIST;
}
nlen = EXT3_DIR_REC_LEN(de->name_len);
- rlen = le16_to_cpu(de->rec_len);
+ rlen = ext3_rec_len_from_disk(de->rec_len);
if ((de->inode? rlen - nlen: rlen) >= reclen)
break;
de = (struct ext3_dir_entry_2 *)((char *)de + rlen);
@@ -1328,11 +1320,11 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
/* By now the buffer is marked for journaling */
nlen = EXT3_DIR_REC_LEN(de->name_len);
- rlen = le16_to_cpu(de->rec_len);
+ rlen = ext3_rec_len_from_disk(de->rec_len);
if (de->inode) {
struct ext3_dir_entry_2 *de1 = (struct ext3_dir_entry_2 *)((char *)de + nlen);
- de1->rec_len = cpu_to_le16(rlen - nlen);
- de->rec_len = cpu_to_le16(nlen);
+ de1->rec_len = ext3_rec_len_to_disk(rlen - nlen);
+ de->rec_len = ext3_rec_len_to_disk(nlen);
de = de1;
}
de->file_type = EXT3_FT_UNKNOWN;
@@ -1366,7 +1358,6 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
return 0;
}
-#ifdef CONFIG_EXT3_INDEX
/*
* This converts a one block unindexed directory to a 3 block indexed
* directory, and adds the dentry to the indexed directory.
@@ -1410,17 +1401,18 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
/* The 0th block becomes the root, move the dirents out */
fde = &root->dotdot;
- de = (struct ext3_dir_entry_2 *)((char *)fde + le16_to_cpu(fde->rec_len));
+ de = (struct ext3_dir_entry_2 *)((char *)fde +
+ ext3_rec_len_from_disk(fde->rec_len));
len = ((char *) root) + blocksize - (char *) de;
memcpy (data1, de, len);
de = (struct ext3_dir_entry_2 *) data1;
top = data1 + len;
- while ((char *)(de2=(void*)de+le16_to_cpu(de->rec_len)) < top)
+ while ((char *)(de2 = ext3_next_entry(de)) < top)
de = de2;
- de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
+ de->rec_len = ext3_rec_len_to_disk(data1 + blocksize - (char *) de);
/* Initialize the root; the dot dirents already exist */
de = (struct ext3_dir_entry_2 *) (&root->dotdot);
- de->rec_len = cpu_to_le16(blocksize - EXT3_DIR_REC_LEN(2));
+ de->rec_len = ext3_rec_len_to_disk(blocksize - EXT3_DIR_REC_LEN(2));
memset (&root->info, 0, sizeof(root->info));
root->info.info_length = sizeof(root->info);
root->info.hash_version = EXT3_SB(dir->i_sb)->s_def_hash_version;
@@ -1445,7 +1437,6 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
return add_dirent_to_buf(handle, dentry, inode, de, bh);
}
-#endif
/*
* ext3_add_entry()
@@ -1466,9 +1457,7 @@ static int ext3_add_entry (handle_t *handle, struct dentry *dentry,
struct ext3_dir_entry_2 *de;
struct super_block * sb;
int retval;
-#ifdef CONFIG_EXT3_INDEX
int dx_fallback=0;
-#endif
unsigned blocksize;
u32 block, blocks;
@@ -1476,7 +1465,6 @@ static int ext3_add_entry (handle_t *handle, struct dentry *dentry,
blocksize = sb->s_blocksize;
if (!dentry->d_name.len)
return -EINVAL;
-#ifdef CONFIG_EXT3_INDEX
if (is_dx(dir)) {
retval = ext3_dx_add_entry(handle, dentry, inode);
if (!retval || (retval != ERR_BAD_DX_DIR))
@@ -1485,7 +1473,6 @@ static int ext3_add_entry (handle_t *handle, struct dentry *dentry,
dx_fallback++;
ext3_mark_inode_dirty(handle, dir);
}
-#endif
blocks = dir->i_size >> sb->s_blocksize_bits;
for (block = 0, offset = 0; block < blocks; block++) {
bh = ext3_bread(handle, dir, block, 0, &retval);
@@ -1495,11 +1482,9 @@ static int ext3_add_entry (handle_t *handle, struct dentry *dentry,
if (retval != -ENOSPC)
return retval;
-#ifdef CONFIG_EXT3_INDEX
if (blocks == 1 && !dx_fallback &&
EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_DIR_INDEX))
return make_indexed_dir(handle, dentry, inode, bh);
-#endif
brelse(bh);
}
bh = ext3_append(handle, dir, &block, &retval);
@@ -1507,11 +1492,10 @@ static int ext3_add_entry (handle_t *handle, struct dentry *dentry,
return retval;
de = (struct ext3_dir_entry_2 *) bh->b_data;
de->inode = 0;
- de->rec_len = cpu_to_le16(blocksize);
+ de->rec_len = ext3_rec_len_to_disk(blocksize);
return add_dirent_to_buf(handle, dentry, inode, de, bh);
}
-#ifdef CONFIG_EXT3_INDEX
/*
* Returns 0 for success, or a negative error value
*/
@@ -1571,7 +1555,7 @@ static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry,
goto cleanup;
node2 = (struct dx_node *)(bh2->b_data);
entries2 = node2->entries;
- node2->fake.rec_len = cpu_to_le16(sb->s_blocksize);
+ node2->fake.rec_len = ext3_rec_len_to_disk(sb->s_blocksize);
node2->fake.inode = 0;
BUFFER_TRACE(frame->bh, "get_write_access");
err = ext3_journal_get_write_access(handle, frame->bh);
@@ -1646,7 +1630,6 @@ cleanup:
dx_release(frames);
return err;
}
-#endif
/*
* ext3_delete_entry deletes a directory entry by merging it with the
@@ -1670,9 +1653,9 @@ static int ext3_delete_entry (handle_t *handle,
BUFFER_TRACE(bh, "get_write_access");
ext3_journal_get_write_access(handle, bh);
if (pde)
- pde->rec_len =
- cpu_to_le16(le16_to_cpu(pde->rec_len) +
- le16_to_cpu(de->rec_len));
+ pde->rec_len = ext3_rec_len_to_disk(
+ ext3_rec_len_from_disk(pde->rec_len) +
+ ext3_rec_len_from_disk(de->rec_len));
else
de->inode = 0;
dir->i_version++;
@@ -1680,10 +1663,9 @@ static int ext3_delete_entry (handle_t *handle,
ext3_journal_dirty_metadata(handle, bh);
return 0;
}
- i += le16_to_cpu(de->rec_len);
+ i += ext3_rec_len_from_disk(de->rec_len);
pde = de;
- de = (struct ext3_dir_entry_2 *)
- ((char *) de + le16_to_cpu(de->rec_len));
+ de = ext3_next_entry(de);
}
return -ENOENT;
}
@@ -1817,13 +1799,13 @@ retry:
de = (struct ext3_dir_entry_2 *) dir_block->b_data;
de->inode = cpu_to_le32(inode->i_ino);
de->name_len = 1;
- de->rec_len = cpu_to_le16(EXT3_DIR_REC_LEN(de->name_len));
+ de->rec_len = ext3_rec_len_to_disk(EXT3_DIR_REC_LEN(de->name_len));
strcpy (de->name, ".");
ext3_set_de_type(dir->i_sb, de, S_IFDIR);
- de = (struct ext3_dir_entry_2 *)
- ((char *) de + le16_to_cpu(de->rec_len));
+ de = ext3_next_entry(de);
de->inode = cpu_to_le32(dir->i_ino);
- de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize-EXT3_DIR_REC_LEN(1));
+ de->rec_len = ext3_rec_len_to_disk(inode->i_sb->s_blocksize -
+ EXT3_DIR_REC_LEN(1));
de->name_len = 2;
strcpy (de->name, "..");
ext3_set_de_type(dir->i_sb, de, S_IFDIR);
@@ -1875,8 +1857,7 @@ static int empty_dir (struct inode * inode)
return 1;
}
de = (struct ext3_dir_entry_2 *) bh->b_data;
- de1 = (struct ext3_dir_entry_2 *)
- ((char *) de + le16_to_cpu(de->rec_len));
+ de1 = ext3_next_entry(de);
if (le32_to_cpu(de->inode) != inode->i_ino ||
!le32_to_cpu(de1->inode) ||
strcmp (".", de->name) ||
@@ -1887,9 +1868,9 @@ static int empty_dir (struct inode * inode)
brelse (bh);
return 1;
}
- offset = le16_to_cpu(de->rec_len) + le16_to_cpu(de1->rec_len);
- de = (struct ext3_dir_entry_2 *)
- ((char *) de1 + le16_to_cpu(de1->rec_len));
+ offset = ext3_rec_len_from_disk(de->rec_len) +
+ ext3_rec_len_from_disk(de1->rec_len);
+ de = ext3_next_entry(de1);
while (offset < inode->i_size ) {
if (!bh ||
(void *) de >= (void *) (bh->b_data+sb->s_blocksize)) {
@@ -1918,9 +1899,8 @@ static int empty_dir (struct inode * inode)
brelse (bh);
return 0;
}
- offset += le16_to_cpu(de->rec_len);
- de = (struct ext3_dir_entry_2 *)
- ((char *) de + le16_to_cpu(de->rec_len));
+ offset += ext3_rec_len_from_disk(de->rec_len);
+ de = ext3_next_entry(de);
}
brelse (bh);
return 1;
@@ -2274,8 +2254,7 @@ retry:
}
#define PARENT_INO(buffer) \
- ((struct ext3_dir_entry_2 *) ((char *) buffer + \
- le16_to_cpu(((struct ext3_dir_entry_2 *) buffer)->rec_len)))->inode
+ (ext3_next_entry((struct ext3_dir_entry_2 *)(buffer))->inode)
/*
* Anybody can rename anything with this: the permission checks are left to the
diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c
index 2c97e09c6c6b..44de1453c301 100644
--- a/fs/ext3/resize.c
+++ b/fs/ext3/resize.c
@@ -154,6 +154,34 @@ static void mark_bitmap_end(int start_bit, int end_bit, char *bitmap)
}
/*
+ * If we have fewer than thresh credits, extend by EXT3_MAX_TRANS_DATA.
+ * If that fails, restart the transaction & regain write access for the
+ * buffer head which is used for block_bitmap modifications.
+ */
+static int extend_or_restart_transaction(handle_t *handle, int thresh,
+ struct buffer_head *bh)
+{
+ int err;
+
+ if (handle->h_buffer_credits >= thresh)
+ return 0;
+
+ err = ext3_journal_extend(handle, EXT3_MAX_TRANS_DATA);
+ if (err < 0)
+ return err;
+ if (err) {
+ err = ext3_journal_restart(handle, EXT3_MAX_TRANS_DATA);
+ if (err)
+ return err;
+ err = ext3_journal_get_write_access(handle, bh);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+/*
* Set up the block and inode bitmaps, and the inode table for the new group.
* This doesn't need to be part of the main transaction, since we are only
* changing blocks outside the actual filesystem. We still do journaling to
@@ -175,8 +203,9 @@ static int setup_new_group_blocks(struct super_block *sb,
int i;
int err = 0, err2;
- handle = ext3_journal_start_sb(sb, reserved_gdb + gdblocks +
- 2 + sbi->s_itb_per_group);
+ /* This transaction may be extended/restarted along the way */
+ handle = ext3_journal_start_sb(sb, EXT3_MAX_TRANS_DATA);
+
if (IS_ERR(handle))
return PTR_ERR(handle);
@@ -203,6 +232,10 @@ static int setup_new_group_blocks(struct super_block *sb,
ext3_debug("update backup group %#04lx (+%d)\n", block, bit);
+ err = extend_or_restart_transaction(handle, 1, bh);
+ if (err)
+ goto exit_bh;
+
gdb = sb_getblk(sb, block);
if (!gdb) {
err = -EIO;
@@ -212,10 +245,10 @@ static int setup_new_group_blocks(struct super_block *sb,
brelse(gdb);
goto exit_bh;
}
- lock_buffer(bh);
- memcpy(gdb->b_data, sbi->s_group_desc[i]->b_data, bh->b_size);
+ lock_buffer(gdb);
+ memcpy(gdb->b_data, sbi->s_group_desc[i]->b_data, gdb->b_size);
set_buffer_uptodate(gdb);
- unlock_buffer(bh);
+ unlock_buffer(gdb);
ext3_journal_dirty_metadata(handle, gdb);
ext3_set_bit(bit, bh->b_data);
brelse(gdb);
@@ -228,6 +261,10 @@ static int setup_new_group_blocks(struct super_block *sb,
ext3_debug("clear reserved block %#04lx (+%d)\n", block, bit);
+ err = extend_or_restart_transaction(handle, 1, bh);
+ if (err)
+ goto exit_bh;
+
if (IS_ERR(gdb = bclean(handle, sb, block))) {
err = PTR_ERR(bh);
goto exit_bh;
@@ -249,6 +286,11 @@ static int setup_new_group_blocks(struct super_block *sb,
struct buffer_head *it;
ext3_debug("clear inode block %#04lx (+%d)\n", block, bit);
+
+ err = extend_or_restart_transaction(handle, 1, bh);
+ if (err)
+ goto exit_bh;
+
if (IS_ERR(it = bclean(handle, sb, block))) {
err = PTR_ERR(it);
goto exit_bh;
@@ -257,6 +299,11 @@ static int setup_new_group_blocks(struct super_block *sb,
brelse(it);
ext3_set_bit(bit, bh->b_data);
}
+
+ err = extend_or_restart_transaction(handle, 2, bh);
+ if (err)
+ goto exit_bh;
+
mark_bitmap_end(input->blocks_count, EXT3_BLOCKS_PER_GROUP(sb),
bh->b_data);
ext3_journal_dirty_metadata(handle, bh);
@@ -884,9 +931,9 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input)
input->reserved_blocks);
/* Update the free space counts */
- percpu_counter_mod(&sbi->s_freeblocks_counter,
+ percpu_counter_add(&sbi->s_freeblocks_counter,
input->free_blocks_count);
- percpu_counter_mod(&sbi->s_freeinodes_counter,
+ percpu_counter_add(&sbi->s_freeinodes_counter,
EXT3_INODES_PER_GROUP(sb));
ext3_journal_dirty_metadata(handle, sbi->s_sbh);
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 9537316a0714..de55da9e28ba 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -472,7 +472,7 @@ static void ext3_destroy_inode(struct inode *inode)
kmem_cache_free(ext3_inode_cachep, EXT3_I(inode));
}
-static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
+static void init_once(struct kmem_cache * cachep, void *foo)
{
struct ext3_inode_info *ei = (struct ext3_inode_info *) foo;
@@ -545,9 +545,78 @@ static inline void ext3_show_quota_options(struct seq_file *seq, struct super_bl
#endif
}
+/*
+ * Show an option if
+ * - it's set to a non-default value OR
+ * - if the per-sb default is different from the global default
+ */
static int ext3_show_options(struct seq_file *seq, struct vfsmount *vfs)
{
struct super_block *sb = vfs->mnt_sb;
+ struct ext3_sb_info *sbi = EXT3_SB(sb);
+ struct ext3_super_block *es = sbi->s_es;
+ unsigned long def_mount_opts;
+
+ def_mount_opts = le32_to_cpu(es->s_default_mount_opts);
+
+ if (sbi->s_sb_block != 1)
+ seq_printf(seq, ",sb=%lu", sbi->s_sb_block);
+ if (test_opt(sb, MINIX_DF))
+ seq_puts(seq, ",minixdf");
+ if (test_opt(sb, GRPID))
+ seq_puts(seq, ",grpid");
+ if (!test_opt(sb, GRPID) && (def_mount_opts & EXT3_DEFM_BSDGROUPS))
+ seq_puts(seq, ",nogrpid");
+ if (sbi->s_resuid != EXT3_DEF_RESUID ||
+ le16_to_cpu(es->s_def_resuid) != EXT3_DEF_RESUID) {
+ seq_printf(seq, ",resuid=%u", sbi->s_resuid);
+ }
+ if (sbi->s_resgid != EXT3_DEF_RESGID ||
+ le16_to_cpu(es->s_def_resgid) != EXT3_DEF_RESGID) {
+ seq_printf(seq, ",resgid=%u", sbi->s_resgid);
+ }
+ if (test_opt(sb, ERRORS_CONT)) {
+ int def_errors = le16_to_cpu(es->s_errors);
+
+ if (def_errors == EXT3_ERRORS_PANIC ||
+ def_errors == EXT3_ERRORS_RO) {
+ seq_puts(seq, ",errors=continue");
+ }
+ }
+ if (test_opt(sb, ERRORS_RO))
+ seq_puts(seq, ",errors=remount-ro");
+ if (test_opt(sb, ERRORS_PANIC))
+ seq_puts(seq, ",errors=panic");
+ if (test_opt(sb, NO_UID32))
+ seq_puts(seq, ",nouid32");
+ if (test_opt(sb, DEBUG))
+ seq_puts(seq, ",debug");
+ if (test_opt(sb, OLDALLOC))
+ seq_puts(seq, ",oldalloc");
+#ifdef CONFIG_EXT3_FS_XATTR
+ if (test_opt(sb, XATTR_USER))
+ seq_puts(seq, ",user_xattr");
+ if (!test_opt(sb, XATTR_USER) &&
+ (def_mount_opts & EXT3_DEFM_XATTR_USER)) {
+ seq_puts(seq, ",nouser_xattr");
+ }
+#endif
+#ifdef CONFIG_EXT3_FS_POSIX_ACL
+ if (test_opt(sb, POSIX_ACL))
+ seq_puts(seq, ",acl");
+ if (!test_opt(sb, POSIX_ACL) && (def_mount_opts & EXT3_DEFM_ACL))
+ seq_puts(seq, ",noacl");
+#endif
+ if (!test_opt(sb, RESERVATION))
+ seq_puts(seq, ",noreservation");
+ if (sbi->s_commit_interval) {
+ seq_printf(seq, ",commit=%u",
+ (unsigned) (sbi->s_commit_interval / HZ));
+ }
+ if (test_opt(sb, BARRIER))
+ seq_puts(seq, ",barrier=1");
+ if (test_opt(sb, NOBH))
+ seq_puts(seq, ",nobh");
if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_JOURNAL_DATA)
seq_puts(seq, ",data=journal");
@@ -562,13 +631,10 @@ static int ext3_show_options(struct seq_file *seq, struct vfsmount *vfs)
}
-static struct dentry *ext3_get_dentry(struct super_block *sb, void *vobjp)
+static struct inode *ext3_nfs_get_inode(struct super_block *sb,
+ u64 ino, u32 generation)
{
- __u32 *objp = vobjp;
- unsigned long ino = objp[0];
- __u32 generation = objp[1];
struct inode *inode;
- struct dentry *result;
if (ino < EXT3_FIRST_INO(sb) && ino != EXT3_ROOT_INO)
return ERR_PTR(-ESTALE);
@@ -591,15 +657,22 @@ static struct dentry *ext3_get_dentry(struct super_block *sb, void *vobjp)
iput(inode);
return ERR_PTR(-ESTALE);
}
- /* now to find a dentry.
- * If possible, get a well-connected one
- */
- result = d_alloc_anon(inode);
- if (!result) {
- iput(inode);
- return ERR_PTR(-ENOMEM);
- }
- return result;
+
+ return inode;
+}
+
+static struct dentry *ext3_fh_to_dentry(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type)
+{
+ return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
+ ext3_nfs_get_inode);
+}
+
+static struct dentry *ext3_fh_to_parent(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type)
+{
+ return generic_fh_to_parent(sb, fid, fh_len, fh_type,
+ ext3_nfs_get_inode);
}
#ifdef CONFIG_QUOTA
@@ -668,9 +741,10 @@ static const struct super_operations ext3_sops = {
#endif
};
-static struct export_operations ext3_export_ops = {
+static const struct export_operations ext3_export_ops = {
+ .fh_to_dentry = ext3_fh_to_dentry,
+ .fh_to_parent = ext3_fh_to_parent,
.get_parent = ext3_get_parent,
- .get_dentry = ext3_get_dentry,
};
enum {
@@ -1416,6 +1490,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
int i;
int needs_recovery;
__le32 features;
+ int err;
sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
if (!sbi)
@@ -1424,6 +1499,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
sbi->s_mount_opt = 0;
sbi->s_resuid = EXT3_DEF_RESUID;
sbi->s_resgid = EXT3_DEF_RESGID;
+ sbi->s_sb_block = sb_block;
unlock_kernel();
@@ -1549,7 +1625,11 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
}
brelse (bh);
- sb_set_blocksize(sb, blocksize);
+ if (!sb_set_blocksize(sb, blocksize)) {
+ printk(KERN_ERR "EXT3-fs: bad blocksize %d.\n",
+ blocksize);
+ goto out_fail;
+ }
logic_sb_block = (sb_block * EXT3_MIN_BLOCK_SIZE) / blocksize;
offset = (sb_block * EXT3_MIN_BLOCK_SIZE) % blocksize;
bh = sb_bread(sb, logic_sb_block);
@@ -1675,12 +1755,20 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
get_random_bytes(&sbi->s_next_generation, sizeof(u32));
spin_lock_init(&sbi->s_next_gen_lock);
- percpu_counter_init(&sbi->s_freeblocks_counter,
- ext3_count_free_blocks(sb));
- percpu_counter_init(&sbi->s_freeinodes_counter,
- ext3_count_free_inodes(sb));
- percpu_counter_init(&sbi->s_dirs_counter,
- ext3_count_dirs(sb));
+ err = percpu_counter_init(&sbi->s_freeblocks_counter,
+ ext3_count_free_blocks(sb));
+ if (!err) {
+ err = percpu_counter_init(&sbi->s_freeinodes_counter,
+ ext3_count_free_inodes(sb));
+ }
+ if (!err) {
+ err = percpu_counter_init(&sbi->s_dirs_counter,
+ ext3_count_dirs(sb));
+ }
+ if (err) {
+ printk(KERN_ERR "EXT3-fs: insufficient memory\n");
+ goto failed_mount3;
+ }
/* per fileystem reservation list head & lock */
spin_lock_init(&sbi->s_rsv_window_lock);
@@ -2472,13 +2560,13 @@ static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf)
buf->f_type = EXT3_SUPER_MAGIC;
buf->f_bsize = sb->s_blocksize;
buf->f_blocks = le32_to_cpu(es->s_blocks_count) - sbi->s_overhead_last;
- buf->f_bfree = percpu_counter_sum(&sbi->s_freeblocks_counter);
+ buf->f_bfree = percpu_counter_sum_positive(&sbi->s_freeblocks_counter);
es->s_free_blocks_count = cpu_to_le32(buf->f_bfree);
buf->f_bavail = buf->f_bfree - le32_to_cpu(es->s_r_blocks_count);
if (buf->f_bfree < le32_to_cpu(es->s_r_blocks_count))
buf->f_bavail = 0;
buf->f_files = le32_to_cpu(es->s_inodes_count);
- buf->f_ffree = percpu_counter_sum(&sbi->s_freeinodes_counter);
+ buf->f_ffree = percpu_counter_sum_positive(&sbi->s_freeinodes_counter);
es->s_free_inodes_count = cpu_to_le32(buf->f_ffree);
buf->f_namelen = EXT3_NAME_LEN;
fsid = le64_to_cpup((void *)es->s_uuid) ^
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c
index f58cbb26323e..408373819e34 100644
--- a/fs/ext3/xattr.c
+++ b/fs/ext3/xattr.c
@@ -741,12 +741,11 @@ ext3_xattr_block_set(handle_t *handle, struct inode *inode,
}
} else {
/* Allocate a buffer where we construct the new block. */
- s->base = kmalloc(sb->s_blocksize, GFP_KERNEL);
+ s->base = kzalloc(sb->s_blocksize, GFP_KERNEL);
/* assert(header == s->base) */
error = -ENOMEM;
if (s->base == NULL)
goto cleanup;
- memset(s->base, 0, sb->s_blocksize);
header(s->base)->h_magic = cpu_to_le32(EXT3_XATTR_MAGIC);
header(s->base)->h_blocks = cpu_to_le32(1);
header(s->base)->h_refcount = cpu_to_le32(1);
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index e53b4af52f11..71ee95e534fd 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -20,6 +20,7 @@
#include <linux/quotaops.h>
#include <linux/buffer_head.h>
+#include "group.h"
/*
* balloc.c contains the blocks allocation and deallocation routines
*/
@@ -42,6 +43,94 @@ void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
}
+/* Initializes an uninitialized block bitmap if given, and returns the
+ * number of blocks free in the group. */
+unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
+ int block_group, struct ext4_group_desc *gdp)
+{
+ unsigned long start;
+ int bit, bit_max;
+ unsigned free_blocks, group_blocks;
+ struct ext4_sb_info *sbi = EXT4_SB(sb);
+
+ if (bh) {
+ J_ASSERT_BH(bh, buffer_locked(bh));
+
+ /* If checksum is bad mark all blocks used to prevent allocation
+ * essentially implementing a per-group read-only flag. */
+ if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
+ ext4_error(sb, __FUNCTION__,
+ "Checksum bad for group %u\n", block_group);
+ gdp->bg_free_blocks_count = 0;
+ gdp->bg_free_inodes_count = 0;
+ gdp->bg_itable_unused = 0;
+ memset(bh->b_data, 0xff, sb->s_blocksize);
+ return 0;
+ }
+ memset(bh->b_data, 0, sb->s_blocksize);
+ }
+
+ /* Check for superblock and gdt backups in this group */
+ bit_max = ext4_bg_has_super(sb, block_group);
+
+ if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG) ||
+ block_group < le32_to_cpu(sbi->s_es->s_first_meta_bg) *
+ sbi->s_desc_per_block) {
+ if (bit_max) {
+ bit_max += ext4_bg_num_gdb(sb, block_group);
+ bit_max +=
+ le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks);
+ }
+ } else { /* For META_BG_BLOCK_GROUPS */
+ int group_rel = (block_group -
+ le32_to_cpu(sbi->s_es->s_first_meta_bg)) %
+ EXT4_DESC_PER_BLOCK(sb);
+ if (group_rel == 0 || group_rel == 1 ||
+ (group_rel == EXT4_DESC_PER_BLOCK(sb) - 1))
+ bit_max += 1;
+ }
+
+ if (block_group == sbi->s_groups_count - 1) {
+ /*
+ * Even though mke2fs always initialize first and last group
+ * if some other tool enabled the EXT4_BG_BLOCK_UNINIT we need
+ * to make sure we calculate the right free blocks
+ */
+ group_blocks = ext4_blocks_count(sbi->s_es) -
+ le32_to_cpu(sbi->s_es->s_first_data_block) -
+ (EXT4_BLOCKS_PER_GROUP(sb) * (sbi->s_groups_count -1));
+ } else {
+ group_blocks = EXT4_BLOCKS_PER_GROUP(sb);
+ }
+
+ free_blocks = group_blocks - bit_max;
+
+ if (bh) {
+ for (bit = 0; bit < bit_max; bit++)
+ ext4_set_bit(bit, bh->b_data);
+
+ start = block_group * EXT4_BLOCKS_PER_GROUP(sb) +
+ le32_to_cpu(sbi->s_es->s_first_data_block);
+
+ /* Set bits for block and inode bitmaps, and inode table */
+ ext4_set_bit(ext4_block_bitmap(sb, gdp) - start, bh->b_data);
+ ext4_set_bit(ext4_inode_bitmap(sb, gdp) - start, bh->b_data);
+ for (bit = (ext4_inode_table(sb, gdp) - start),
+ bit_max = bit + sbi->s_itb_per_group; bit < bit_max; bit++)
+ ext4_set_bit(bit, bh->b_data);
+
+ /*
+ * Also if the number of blocks within the group is
+ * less than the blocksize * 8 ( which is the size
+ * of bitmap ), set rest of the block bitmap to 1
+ */
+ mark_bitmap_end(group_blocks, sb->s_blocksize * 8, bh->b_data);
+ }
+
+ return free_blocks - sbi->s_itb_per_group - 2;
+}
+
+
/*
* The free blocks are managed by bitmaps. A file system contains several
* blocks groups. Each group contains 1 bitmap block for blocks, 1 bitmap
@@ -110,23 +199,36 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb,
*
* Return buffer_head on success or NULL in case of failure.
*/
-static struct buffer_head *
+struct buffer_head *
read_block_bitmap(struct super_block *sb, unsigned int block_group)
{
struct ext4_group_desc * desc;
struct buffer_head * bh = NULL;
+ ext4_fsblk_t bitmap_blk;
- desc = ext4_get_group_desc (sb, block_group, NULL);
+ desc = ext4_get_group_desc(sb, block_group, NULL);
if (!desc)
- goto error_out;
- bh = sb_bread(sb, ext4_block_bitmap(sb, desc));
+ return NULL;
+ bitmap_blk = ext4_block_bitmap(sb, desc);
+ if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
+ bh = sb_getblk(sb, bitmap_blk);
+ if (!buffer_uptodate(bh)) {
+ lock_buffer(bh);
+ if (!buffer_uptodate(bh)) {
+ ext4_init_block_bitmap(sb, bh, block_group,
+ desc);
+ set_buffer_uptodate(bh);
+ }
+ unlock_buffer(bh);
+ }
+ } else {
+ bh = sb_bread(sb, bitmap_blk);
+ }
if (!bh)
- ext4_error (sb, "read_block_bitmap",
+ ext4_error (sb, __FUNCTION__,
"Cannot read block bitmap - "
"block_group = %d, block_bitmap = %llu",
- block_group,
- ext4_block_bitmap(sb, desc));
-error_out:
+ block_group, bitmap_blk);
return bh;
}
/*
@@ -586,8 +688,9 @@ do_more:
desc->bg_free_blocks_count =
cpu_to_le16(le16_to_cpu(desc->bg_free_blocks_count) +
group_freed);
+ desc->bg_checksum = ext4_group_desc_csum(sbi, block_group, desc);
spin_unlock(sb_bgl_lock(sbi, block_group));
- percpu_counter_mod(&sbi->s_freeblocks_counter, count);
+ percpu_counter_add(&sbi->s_freeblocks_counter, count);
/* We dirtied the bitmap block */
BUFFER_TRACE(bitmap_bh, "dirtied bitmap block");
@@ -1644,10 +1747,13 @@ allocated:
ret_block, goal_hits, goal_attempts);
spin_lock(sb_bgl_lock(sbi, group_no));
+ if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))
+ gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
gdp->bg_free_blocks_count =
cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count)-num);
+ gdp->bg_checksum = ext4_group_desc_csum(sbi, group_no, gdp);
spin_unlock(sb_bgl_lock(sbi, group_no));
- percpu_counter_mod(&sbi->s_freeblocks_counter, -num);
+ percpu_counter_sub(&sbi->s_freeblocks_counter, num);
BUFFER_TRACE(gdp_bh, "journal_dirty_metadata for group descriptor");
err = ext4_journal_dirty_metadata(handle, gdp_bh);
@@ -1747,15 +1853,6 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
#endif
}
-static inline int
-block_in_use(ext4_fsblk_t block, struct super_block *sb, unsigned char *map)
-{
- ext4_grpblk_t offset;
-
- ext4_get_group_no_and_offset(sb, block, NULL, &offset);
- return ext4_test_bit (offset, map);
-}
-
static inline int test_root(int a, int b)
{
int num = b;
diff --git a/fs/ext4/bitmap.c b/fs/ext4/bitmap.c
index 11e93c169bcf..420554f8f79d 100644
--- a/fs/ext4/bitmap.c
+++ b/fs/ext4/bitmap.c
@@ -13,7 +13,7 @@
#ifdef EXT4FS_DEBUG
-static int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
+static const int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
unsigned long ext4_count_free (struct buffer_head * map, unsigned int numchars)
{
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
index 3ab01c04e00c..f612bef98315 100644
--- a/fs/ext4/dir.c
+++ b/fs/ext4/dir.c
@@ -47,9 +47,7 @@ const struct file_operations ext4_dir_operations = {
.compat_ioctl = ext4_compat_ioctl,
#endif
.fsync = ext4_sync_file, /* BKL held */
-#ifdef CONFIG_EXT4_INDEX
.release = ext4_release_dir,
-#endif
};
@@ -107,7 +105,6 @@ static int ext4_readdir(struct file * filp,
sb = inode->i_sb;
-#ifdef CONFIG_EXT4_INDEX
if (EXT4_HAS_COMPAT_FEATURE(inode->i_sb,
EXT4_FEATURE_COMPAT_DIR_INDEX) &&
((EXT4_I(inode)->i_flags & EXT4_INDEX_FL) ||
@@ -123,7 +120,6 @@ static int ext4_readdir(struct file * filp,
*/
EXT4_I(filp->f_path.dentry->d_inode)->i_flags &= ~EXT4_INDEX_FL;
}
-#endif
stored = 0;
offset = filp->f_pos & (sb->s_blocksize - 1);
@@ -142,7 +138,7 @@ static int ext4_readdir(struct file * filp,
sb->s_bdev->bd_inode->i_mapping,
&filp->f_ra, filp,
index, 1);
- filp->f_ra.prev_index = index;
+ filp->f_ra.prev_pos = (loff_t)index << PAGE_CACHE_SHIFT;
bh = ext4_bread(NULL, inode, blk, 0, &err);
}
@@ -210,7 +206,7 @@ revalidate:
* not the directory has been modified
* during the copy operation.
*/
- unsigned long version = filp->f_version;
+ u64 version = filp->f_version;
error = filldir(dirent, de->name,
de->name_len,
@@ -232,7 +228,6 @@ out:
return ret;
}
-#ifdef CONFIG_EXT4_INDEX
/*
* These functions convert from the major/minor hash to an f_pos
* value.
@@ -518,5 +513,3 @@ static int ext4_release_dir (struct inode * inode, struct file * filp)
return 0;
}
-
-#endif
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 78beb096f57d..85287742f2ae 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -33,7 +33,7 @@
#include <linux/fs.h>
#include <linux/time.h>
#include <linux/ext4_jbd2.h>
-#include <linux/jbd.h>
+#include <linux/jbd2.h>
#include <linux/highuid.h>
#include <linux/pagemap.h>
#include <linux/quotaops.h>
@@ -52,7 +52,7 @@ static ext4_fsblk_t ext_pblock(struct ext4_extent *ex)
{
ext4_fsblk_t block;
- block = le32_to_cpu(ex->ee_start);
+ block = le32_to_cpu(ex->ee_start_lo);
block |= ((ext4_fsblk_t) le16_to_cpu(ex->ee_start_hi) << 31) << 1;
return block;
}
@@ -65,7 +65,7 @@ static ext4_fsblk_t idx_pblock(struct ext4_extent_idx *ix)
{
ext4_fsblk_t block;
- block = le32_to_cpu(ix->ei_leaf);
+ block = le32_to_cpu(ix->ei_leaf_lo);
block |= ((ext4_fsblk_t) le16_to_cpu(ix->ei_leaf_hi) << 31) << 1;
return block;
}
@@ -77,7 +77,7 @@ static ext4_fsblk_t idx_pblock(struct ext4_extent_idx *ix)
*/
static void ext4_ext_store_pblock(struct ext4_extent *ex, ext4_fsblk_t pb)
{
- ex->ee_start = cpu_to_le32((unsigned long) (pb & 0xffffffff));
+ ex->ee_start_lo = cpu_to_le32((unsigned long) (pb & 0xffffffff));
ex->ee_start_hi = cpu_to_le16((unsigned long) ((pb >> 31) >> 1) & 0xffff);
}
@@ -88,7 +88,7 @@ static void ext4_ext_store_pblock(struct ext4_extent *ex, ext4_fsblk_t pb)
*/
static void ext4_idx_store_pblock(struct ext4_extent_idx *ix, ext4_fsblk_t pb)
{
- ix->ei_leaf = cpu_to_le32((unsigned long) (pb & 0xffffffff));
+ ix->ei_leaf_lo = cpu_to_le32((unsigned long) (pb & 0xffffffff));
ix->ei_leaf_hi = cpu_to_le16((unsigned long) ((pb >> 31) >> 1) & 0xffff);
}
@@ -1409,8 +1409,7 @@ has_space:
eh->eh_entries = cpu_to_le16(le16_to_cpu(eh->eh_entries)+1);
nearex = path[depth].p_ext;
nearex->ee_block = newext->ee_block;
- nearex->ee_start = newext->ee_start;
- nearex->ee_start_hi = newext->ee_start_hi;
+ ext4_ext_store_pblock(nearex, ext_pblock(newext));
nearex->ee_len = newext->ee_len;
merge:
@@ -2177,7 +2176,6 @@ int ext4_ext_convert_to_initialized(handle_t *handle, struct inode *inode,
}
/* ex2: iblock to iblock + maxblocks-1 : initialised */
ex2->ee_block = cpu_to_le32(iblock);
- ex2->ee_start = cpu_to_le32(newblock);
ext4_ext_store_pblock(ex2, newblock);
ex2->ee_len = cpu_to_le16(allocated);
if (ex2 != ex)
diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c
index 2a167d7131fa..8d50879d1c2c 100644
--- a/fs/ext4/fsync.c
+++ b/fs/ext4/fsync.c
@@ -47,7 +47,7 @@ int ext4_sync_file(struct file * file, struct dentry *dentry, int datasync)
struct inode *inode = dentry->d_inode;
int ret = 0;
- J_ASSERT(ext4_journal_current_handle() == 0);
+ J_ASSERT(ext4_journal_current_handle() == NULL);
/*
* data=writeback:
diff --git a/fs/ext4/group.h b/fs/ext4/group.h
new file mode 100644
index 000000000000..1577910bb58b
--- /dev/null
+++ b/fs/ext4/group.h
@@ -0,0 +1,27 @@
+/*
+ * linux/fs/ext4/group.h
+ *
+ * Copyright (C) 2007 Cluster File Systems, Inc
+ *
+ * Author: Andreas Dilger <adilger@clusterfs.com>
+ */
+
+#ifndef _LINUX_EXT4_GROUP_H
+#define _LINUX_EXT4_GROUP_H
+
+extern __le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 group,
+ struct ext4_group_desc *gdp);
+extern int ext4_group_desc_csum_verify(struct ext4_sb_info *sbi, __u32 group,
+ struct ext4_group_desc *gdp);
+struct buffer_head *read_block_bitmap(struct super_block *sb,
+ unsigned int block_group);
+extern unsigned ext4_init_block_bitmap(struct super_block *sb,
+ struct buffer_head *bh, int group,
+ struct ext4_group_desc *desc);
+#define ext4_free_blocks_after_init(sb, group, desc) \
+ ext4_init_block_bitmap(sb, NULL, group, desc)
+extern unsigned ext4_init_inode_bitmap(struct super_block *sb,
+ struct buffer_head *bh, int group,
+ struct ext4_group_desc *desc);
+extern void mark_bitmap_end(int start_bit, int end_bit, char *bitmap);
+#endif /* _LINUX_EXT4_GROUP_H */
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 427f83066a0d..c61f37fd3f05 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -28,6 +28,7 @@
#include "xattr.h"
#include "acl.h"
+#include "group.h"
/*
* ialloc.c contains the inodes allocation and deallocation routines
@@ -43,6 +44,52 @@
* the free blocks count in the block.
*/
+/*
+ * To avoid calling the atomic setbit hundreds or thousands of times, we only
+ * need to use it within a single byte (to ensure we get endianness right).
+ * We can use memset for the rest of the bitmap as there are no other users.
+ */
+void mark_bitmap_end(int start_bit, int end_bit, char *bitmap)
+{
+ int i;
+
+ if (start_bit >= end_bit)
+ return;
+
+ ext4_debug("mark end bits +%d through +%d used\n", start_bit, end_bit);
+ for (i = start_bit; i < ((start_bit + 7) & ~7UL); i++)
+ ext4_set_bit(i, bitmap);
+ if (i < end_bit)
+ memset(bitmap + (i >> 3), 0xff, (end_bit - i) >> 3);
+}
+
+/* Initializes an uninitialized inode bitmap */
+unsigned ext4_init_inode_bitmap(struct super_block *sb,
+ struct buffer_head *bh, int block_group,
+ struct ext4_group_desc *gdp)
+{
+ struct ext4_sb_info *sbi = EXT4_SB(sb);
+
+ J_ASSERT_BH(bh, buffer_locked(bh));
+
+ /* If checksum is bad mark all blocks and inodes use to prevent
+ * allocation, essentially implementing a per-group read-only flag. */
+ if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
+ ext4_error(sb, __FUNCTION__, "Checksum bad for group %u\n",
+ block_group);
+ gdp->bg_free_blocks_count = 0;
+ gdp->bg_free_inodes_count = 0;
+ gdp->bg_itable_unused = 0;
+ memset(bh->b_data, 0xff, sb->s_blocksize);
+ return 0;
+ }
+
+ memset(bh->b_data, 0, (EXT4_INODES_PER_GROUP(sb) + 7) / 8);
+ mark_bitmap_end(EXT4_INODES_PER_GROUP(sb), EXT4_BLOCKS_PER_GROUP(sb),
+ bh->b_data);
+
+ return EXT4_INODES_PER_GROUP(sb);
+}
/*
* Read the inode allocation bitmap for a given block_group, reading
@@ -59,8 +106,20 @@ read_inode_bitmap(struct super_block * sb, unsigned long block_group)
desc = ext4_get_group_desc(sb, block_group, NULL);
if (!desc)
goto error_out;
-
- bh = sb_bread(sb, ext4_inode_bitmap(sb, desc));
+ if (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) {
+ bh = sb_getblk(sb, ext4_inode_bitmap(sb, desc));
+ if (!buffer_uptodate(bh)) {
+ lock_buffer(bh);
+ if (!buffer_uptodate(bh)) {
+ ext4_init_inode_bitmap(sb, bh, block_group,
+ desc);
+ set_buffer_uptodate(bh);
+ }
+ unlock_buffer(bh);
+ }
+ } else {
+ bh = sb_bread(sb, ext4_inode_bitmap(sb, desc));
+ }
if (!bh)
ext4_error(sb, "read_inode_bitmap",
"Cannot read inode bitmap - "
@@ -169,6 +228,8 @@ void ext4_free_inode (handle_t *handle, struct inode * inode)
if (is_directory)
gdp->bg_used_dirs_count = cpu_to_le16(
le16_to_cpu(gdp->bg_used_dirs_count) - 1);
+ gdp->bg_checksum = ext4_group_desc_csum(sbi,
+ block_group, gdp);
spin_unlock(sb_bgl_lock(sbi, block_group));
percpu_counter_inc(&sbi->s_freeinodes_counter);
if (is_directory)
@@ -204,14 +265,13 @@ static int find_group_dir(struct super_block *sb, struct inode *parent)
int ngroups = EXT4_SB(sb)->s_groups_count;
unsigned int freei, avefreei;
struct ext4_group_desc *desc, *best_desc = NULL;
- struct buffer_head *bh;
int group, best_group = -1;
freei = percpu_counter_read_positive(&EXT4_SB(sb)->s_freeinodes_counter);
avefreei = freei / ngroups;
for (group = 0; group < ngroups; group++) {
- desc = ext4_get_group_desc (sb, group, &bh);
+ desc = ext4_get_group_desc (sb, group, NULL);
if (!desc || !desc->bg_free_inodes_count)
continue;
if (le16_to_cpu(desc->bg_free_inodes_count) < avefreei)
@@ -269,7 +329,6 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent)
ext4_grpblk_t min_blocks;
int group = -1, i;
struct ext4_group_desc *desc;
- struct buffer_head *bh;
freei = percpu_counter_read_positive(&sbi->s_freeinodes_counter);
avefreei = freei / ngroups;
@@ -287,7 +346,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent)
parent_group = (unsigned)group % ngroups;
for (i = 0; i < ngroups; i++) {
group = (parent_group + i) % ngroups;
- desc = ext4_get_group_desc (sb, group, &bh);
+ desc = ext4_get_group_desc (sb, group, NULL);
if (!desc || !desc->bg_free_inodes_count)
continue;
if (le16_to_cpu(desc->bg_used_dirs_count) >= best_ndir)
@@ -322,7 +381,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent)
for (i = 0; i < ngroups; i++) {
group = (parent_group + i) % ngroups;
- desc = ext4_get_group_desc (sb, group, &bh);
+ desc = ext4_get_group_desc (sb, group, NULL);
if (!desc || !desc->bg_free_inodes_count)
continue;
if (le16_to_cpu(desc->bg_used_dirs_count) >= max_dirs)
@@ -337,7 +396,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent)
fallback:
for (i = 0; i < ngroups; i++) {
group = (parent_group + i) % ngroups;
- desc = ext4_get_group_desc (sb, group, &bh);
+ desc = ext4_get_group_desc (sb, group, NULL);
if (!desc || !desc->bg_free_inodes_count)
continue;
if (le16_to_cpu(desc->bg_free_inodes_count) >= avefreei)
@@ -361,14 +420,13 @@ static int find_group_other(struct super_block *sb, struct inode *parent)
int parent_group = EXT4_I(parent)->i_block_group;
int ngroups = EXT4_SB(sb)->s_groups_count;
struct ext4_group_desc *desc;
- struct buffer_head *bh;
int group, i;
/*
* Try to place the inode in its parent directory
*/
group = parent_group;
- desc = ext4_get_group_desc (sb, group, &bh);
+ desc = ext4_get_group_desc (sb, group, NULL);
if (desc && le16_to_cpu(desc->bg_free_inodes_count) &&
le16_to_cpu(desc->bg_free_blocks_count))
return group;
@@ -392,7 +450,7 @@ static int find_group_other(struct super_block *sb, struct inode *parent)
group += i;
if (group >= ngroups)
group -= ngroups;
- desc = ext4_get_group_desc (sb, group, &bh);
+ desc = ext4_get_group_desc (sb, group, NULL);
if (desc && le16_to_cpu(desc->bg_free_inodes_count) &&
le16_to_cpu(desc->bg_free_blocks_count))
return group;
@@ -406,7 +464,7 @@ static int find_group_other(struct super_block *sb, struct inode *parent)
for (i = 0; i < ngroups; i++) {
if (++group >= ngroups)
group = 0;
- desc = ext4_get_group_desc (sb, group, &bh);
+ desc = ext4_get_group_desc (sb, group, NULL);
if (desc && le16_to_cpu(desc->bg_free_inodes_count))
return group;
}
@@ -438,7 +496,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode * dir, int mode)
struct ext4_sb_info *sbi;
int err = 0;
struct inode *ret;
- int i;
+ int i, free = 0;
/* Cannot create files in a deleted directory */
if (!dir || !dir->i_nlink)
@@ -520,11 +578,13 @@ repeat_in_this_group:
goto out;
got:
- ino += group * EXT4_INODES_PER_GROUP(sb) + 1;
- if (ino < EXT4_FIRST_INO(sb) || ino > le32_to_cpu(es->s_inodes_count)) {
- ext4_error (sb, "ext4_new_inode",
- "reserved inode or inode > inodes count - "
- "block_group = %d, inode=%lu", group, ino);
+ ino++;
+ if ((group == 0 && ino < EXT4_FIRST_INO(sb)) ||
+ ino > EXT4_INODES_PER_GROUP(sb)) {
+ ext4_error(sb, __FUNCTION__,
+ "reserved inode or inode > inodes count - "
+ "block_group = %d, inode=%lu", group,
+ ino + group * EXT4_INODES_PER_GROUP(sb));
err = -EIO;
goto fail;
}
@@ -532,13 +592,78 @@ got:
BUFFER_TRACE(bh2, "get_write_access");
err = ext4_journal_get_write_access(handle, bh2);
if (err) goto fail;
+
+ /* We may have to initialize the block bitmap if it isn't already */
+ if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_GDT_CSUM) &&
+ gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
+ struct buffer_head *block_bh = read_block_bitmap(sb, group);
+
+ BUFFER_TRACE(block_bh, "get block bitmap access");
+ err = ext4_journal_get_write_access(handle, block_bh);
+ if (err) {
+ brelse(block_bh);
+ goto fail;
+ }
+
+ free = 0;
+ spin_lock(sb_bgl_lock(sbi, group));
+ /* recheck and clear flag under lock if we still need to */
+ if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
+ gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
+ free = ext4_free_blocks_after_init(sb, group, gdp);
+ gdp->bg_free_blocks_count = cpu_to_le16(free);
+ }
+ spin_unlock(sb_bgl_lock(sbi, group));
+
+ /* Don't need to dirty bitmap block if we didn't change it */
+ if (free) {
+ BUFFER_TRACE(block_bh, "dirty block bitmap");
+ err = ext4_journal_dirty_metadata(handle, block_bh);
+ }
+
+ brelse(block_bh);
+ if (err)
+ goto fail;
+ }
+
spin_lock(sb_bgl_lock(sbi, group));
+ /* If we didn't allocate from within the initialized part of the inode
+ * table then we need to initialize up to this inode. */
+ if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
+ if (gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) {
+ gdp->bg_flags &= cpu_to_le16(~EXT4_BG_INODE_UNINIT);
+
+ /* When marking the block group with
+ * ~EXT4_BG_INODE_UNINIT we don't want to depend
+ * on the value of bg_itable_unsed even though
+ * mke2fs could have initialized the same for us.
+ * Instead we calculated the value below
+ */
+
+ free = 0;
+ } else {
+ free = EXT4_INODES_PER_GROUP(sb) -
+ le16_to_cpu(gdp->bg_itable_unused);
+ }
+
+ /*
+ * Check the relative inode number against the last used
+ * relative inode number in this group. if it is greater
+ * we need to update the bg_itable_unused count
+ *
+ */
+ if (ino > free)
+ gdp->bg_itable_unused =
+ cpu_to_le16(EXT4_INODES_PER_GROUP(sb) - ino);
+ }
+
gdp->bg_free_inodes_count =
cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) - 1);
if (S_ISDIR(mode)) {
gdp->bg_used_dirs_count =
cpu_to_le16(le16_to_cpu(gdp->bg_used_dirs_count) + 1);
}
+ gdp->bg_checksum = ext4_group_desc_csum(sbi, group, gdp);
spin_unlock(sb_bgl_lock(sbi, group));
BUFFER_TRACE(bh2, "call ext4_journal_dirty_metadata");
err = ext4_journal_dirty_metadata(handle, bh2);
@@ -560,7 +685,7 @@ got:
inode->i_gid = current->fsgid;
inode->i_mode = mode;
- inode->i_ino = ino;
+ inode->i_ino = ino + group * EXT4_INODES_PER_GROUP(sb);
/* This is the optimal IO size (for stat), not the fs block size */
inode->i_blocks = 0;
inode->i_mtime = inode->i_atime = inode->i_ctime = ei->i_crtime =
@@ -576,11 +701,6 @@ got:
/* dirsync only applies to directories */
if (!S_ISDIR(mode))
ei->i_flags &= ~EXT4_DIRSYNC_FL;
-#ifdef EXT4_FRAGMENTS
- ei->i_faddr = 0;
- ei->i_frag_no = 0;
- ei->i_frag_size = 0;
-#endif
ei->i_file_acl = 0;
ei->i_dir_acl = 0;
ei->i_dtime = 0;
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index a4848e04a5ed..5489703d9573 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1027,7 +1027,7 @@ struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode,
}
if (buffer_new(&dummy)) {
J_ASSERT(create != 0);
- J_ASSERT(handle != 0);
+ J_ASSERT(handle != NULL);
/*
* Now that we do not always journal data, we should
@@ -1146,34 +1146,50 @@ static int do_journal_get_write_access(handle_t *handle,
return ext4_journal_get_write_access(handle, bh);
}
-static int ext4_prepare_write(struct file *file, struct page *page,
- unsigned from, unsigned to)
+static int ext4_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
{
- struct inode *inode = page->mapping->host;
+ struct inode *inode = mapping->host;
int ret, needed_blocks = ext4_writepage_trans_blocks(inode);
handle_t *handle;
int retries = 0;
+ struct page *page;
+ pgoff_t index;
+ unsigned from, to;
+
+ index = pos >> PAGE_CACHE_SHIFT;
+ from = pos & (PAGE_CACHE_SIZE - 1);
+ to = from + len;
retry:
- handle = ext4_journal_start(inode, needed_blocks);
- if (IS_ERR(handle)) {
- ret = PTR_ERR(handle);
- goto out;
+ page = __grab_cache_page(mapping, index);
+ if (!page)
+ return -ENOMEM;
+ *pagep = page;
+
+ handle = ext4_journal_start(inode, needed_blocks);
+ if (IS_ERR(handle)) {
+ unlock_page(page);
+ page_cache_release(page);
+ ret = PTR_ERR(handle);
+ goto out;
}
- if (test_opt(inode->i_sb, NOBH) && ext4_should_writeback_data(inode))
- ret = nobh_prepare_write(page, from, to, ext4_get_block);
- else
- ret = block_prepare_write(page, from, to, ext4_get_block);
- if (ret)
- goto prepare_write_failed;
- if (ext4_should_journal_data(inode)) {
+ ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
+ ext4_get_block);
+
+ if (!ret && ext4_should_journal_data(inode)) {
ret = walk_page_buffers(handle, page_buffers(page),
from, to, NULL, do_journal_get_write_access);
}
-prepare_write_failed:
- if (ret)
+
+ if (ret) {
ext4_journal_stop(handle);
+ unlock_page(page);
+ page_cache_release(page);
+ }
+
if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
goto retry;
out:
@@ -1185,12 +1201,12 @@ int ext4_journal_dirty_data(handle_t *handle, struct buffer_head *bh)
int err = jbd2_journal_dirty_data(handle, bh);
if (err)
ext4_journal_abort_handle(__FUNCTION__, __FUNCTION__,
- bh, handle,err);
+ bh, handle, err);
return err;
}
-/* For commit_write() in data=journal mode */
-static int commit_write_fn(handle_t *handle, struct buffer_head *bh)
+/* For write_end() in data=journal mode */
+static int write_end_fn(handle_t *handle, struct buffer_head *bh)
{
if (!buffer_mapped(bh) || buffer_freed(bh))
return 0;
@@ -1199,84 +1215,130 @@ static int commit_write_fn(handle_t *handle, struct buffer_head *bh)
}
/*
+ * Generic write_end handler for ordered and writeback ext4 journal modes.
+ * We can't use generic_write_end, because that unlocks the page and we need to
+ * unlock the page after ext4_journal_stop, but ext4_journal_stop must run
+ * after block_write_end.
+ */
+static int ext4_generic_write_end(struct file *file,
+ struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata)
+{
+ struct inode *inode = file->f_mapping->host;
+
+ copied = block_write_end(file, mapping, pos, len, copied, page, fsdata);
+
+ if (pos+copied > inode->i_size) {
+ i_size_write(inode, pos+copied);
+ mark_inode_dirty(inode);
+ }
+
+ return copied;
+}
+
+/*
* We need to pick up the new inode size which generic_commit_write gave us
* `file' can be NULL - eg, when called from page_symlink().
*
* ext4 never places buffers on inode->i_mapping->private_list. metadata
* buffers are managed internally.
*/
-static int ext4_ordered_commit_write(struct file *file, struct page *page,
- unsigned from, unsigned to)
+static int ext4_ordered_write_end(struct file *file,
+ struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata)
{
handle_t *handle = ext4_journal_current_handle();
- struct inode *inode = page->mapping->host;
+ struct inode *inode = file->f_mapping->host;
+ unsigned from, to;
int ret = 0, ret2;
+ from = pos & (PAGE_CACHE_SIZE - 1);
+ to = from + len;
+
ret = walk_page_buffers(handle, page_buffers(page),
from, to, NULL, ext4_journal_dirty_data);
if (ret == 0) {
/*
- * generic_commit_write() will run mark_inode_dirty() if i_size
+ * generic_write_end() will run mark_inode_dirty() if i_size
* changes. So let's piggyback the i_disksize mark_inode_dirty
* into that.
*/
loff_t new_i_size;
- new_i_size = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
+ new_i_size = pos + copied;
if (new_i_size > EXT4_I(inode)->i_disksize)
EXT4_I(inode)->i_disksize = new_i_size;
- ret = generic_commit_write(file, page, from, to);
+ copied = ext4_generic_write_end(file, mapping, pos, len, copied,
+ page, fsdata);
+ if (copied < 0)
+ ret = copied;
}
ret2 = ext4_journal_stop(handle);
if (!ret)
ret = ret2;
- return ret;
+ unlock_page(page);
+ page_cache_release(page);
+
+ return ret ? ret : copied;
}
-static int ext4_writeback_commit_write(struct file *file, struct page *page,
- unsigned from, unsigned to)
+static int ext4_writeback_write_end(struct file *file,
+ struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata)
{
handle_t *handle = ext4_journal_current_handle();
- struct inode *inode = page->mapping->host;
+ struct inode *inode = file->f_mapping->host;
int ret = 0, ret2;
loff_t new_i_size;
- new_i_size = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
+ new_i_size = pos + copied;
if (new_i_size > EXT4_I(inode)->i_disksize)
EXT4_I(inode)->i_disksize = new_i_size;
- if (test_opt(inode->i_sb, NOBH) && ext4_should_writeback_data(inode))
- ret = nobh_commit_write(file, page, from, to);
- else
- ret = generic_commit_write(file, page, from, to);
+ copied = ext4_generic_write_end(file, mapping, pos, len, copied,
+ page, fsdata);
+ if (copied < 0)
+ ret = copied;
ret2 = ext4_journal_stop(handle);
if (!ret)
ret = ret2;
- return ret;
+ unlock_page(page);
+ page_cache_release(page);
+
+ return ret ? ret : copied;
}
-static int ext4_journalled_commit_write(struct file *file,
- struct page *page, unsigned from, unsigned to)
+static int ext4_journalled_write_end(struct file *file,
+ struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata)
{
handle_t *handle = ext4_journal_current_handle();
- struct inode *inode = page->mapping->host;
+ struct inode *inode = mapping->host;
int ret = 0, ret2;
int partial = 0;
- loff_t pos;
+ unsigned from, to;
- /*
- * Here we duplicate the generic_commit_write() functionality
- */
- pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
+ from = pos & (PAGE_CACHE_SIZE - 1);
+ to = from + len;
+
+ if (copied < len) {
+ if (!PageUptodate(page))
+ copied = 0;
+ page_zero_new_buffers(page, from+copied, to);
+ }
ret = walk_page_buffers(handle, page_buffers(page), from,
- to, &partial, commit_write_fn);
+ to, &partial, write_end_fn);
if (!partial)
SetPageUptodate(page);
- if (pos > inode->i_size)
- i_size_write(inode, pos);
+ if (pos+copied > inode->i_size)
+ i_size_write(inode, pos+copied);
EXT4_I(inode)->i_state |= EXT4_STATE_JDATA;
if (inode->i_size > EXT4_I(inode)->i_disksize) {
EXT4_I(inode)->i_disksize = inode->i_size;
@@ -1284,10 +1346,14 @@ static int ext4_journalled_commit_write(struct file *file,
if (!ret)
ret = ret2;
}
+
ret2 = ext4_journal_stop(handle);
if (!ret)
ret = ret2;
- return ret;
+ unlock_page(page);
+ page_cache_release(page);
+
+ return ret ? ret : copied;
}
/*
@@ -1545,7 +1611,7 @@ static int ext4_journalled_writepage(struct page *page,
PAGE_CACHE_SIZE, NULL, do_journal_get_write_access);
err = walk_page_buffers(handle, page_buffers(page), 0,
- PAGE_CACHE_SIZE, NULL, commit_write_fn);
+ PAGE_CACHE_SIZE, NULL, write_end_fn);
if (ret == 0)
ret = err;
EXT4_I(inode)->i_state |= EXT4_STATE_JDATA;
@@ -1705,8 +1771,8 @@ static const struct address_space_operations ext4_ordered_aops = {
.readpages = ext4_readpages,
.writepage = ext4_ordered_writepage,
.sync_page = block_sync_page,
- .prepare_write = ext4_prepare_write,
- .commit_write = ext4_ordered_commit_write,
+ .write_begin = ext4_write_begin,
+ .write_end = ext4_ordered_write_end,
.bmap = ext4_bmap,
.invalidatepage = ext4_invalidatepage,
.releasepage = ext4_releasepage,
@@ -1719,8 +1785,8 @@ static const struct address_space_operations ext4_writeback_aops = {
.readpages = ext4_readpages,
.writepage = ext4_writeback_writepage,
.sync_page = block_sync_page,
- .prepare_write = ext4_prepare_write,
- .commit_write = ext4_writeback_commit_write,
+ .write_begin = ext4_write_begin,
+ .write_end = ext4_writeback_write_end,
.bmap = ext4_bmap,
.invalidatepage = ext4_invalidatepage,
.releasepage = ext4_releasepage,
@@ -1733,8 +1799,8 @@ static const struct address_space_operations ext4_journalled_aops = {
.readpages = ext4_readpages,
.writepage = ext4_journalled_writepage,
.sync_page = block_sync_page,
- .prepare_write = ext4_prepare_write,
- .commit_write = ext4_journalled_commit_write,
+ .write_begin = ext4_write_begin,
+ .write_end = ext4_journalled_write_end,
.set_page_dirty = ext4_journalled_set_page_dirty,
.bmap = ext4_bmap,
.invalidatepage = ext4_invalidatepage,
@@ -2645,11 +2711,6 @@ void ext4_read_inode(struct inode * inode)
}
inode->i_blocks = le32_to_cpu(raw_inode->i_blocks);
ei->i_flags = le32_to_cpu(raw_inode->i_flags);
-#ifdef EXT4_FRAGMENTS
- ei->i_faddr = le32_to_cpu(raw_inode->i_faddr);
- ei->i_frag_no = raw_inode->i_frag;
- ei->i_frag_size = raw_inode->i_fsize;
-#endif
ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl);
if (EXT4_SB(inode->i_sb)->s_es->s_creator_os !=
cpu_to_le32(EXT4_OS_HURD))
@@ -2794,11 +2855,6 @@ static int ext4_do_update_inode(handle_t *handle,
raw_inode->i_blocks = cpu_to_le32(inode->i_blocks);
raw_inode->i_dtime = cpu_to_le32(ei->i_dtime);
raw_inode->i_flags = cpu_to_le32(ei->i_flags);
-#ifdef EXT4_FRAGMENTS
- raw_inode->i_faddr = cpu_to_le32(ei->i_faddr);
- raw_inode->i_frag = ei->i_frag_no;
- raw_inode->i_fsize = ei->i_frag_size;
-#endif
if (EXT4_SB(inode->i_sb)->s_es->s_creator_os !=
cpu_to_le32(EXT4_OS_HURD))
raw_inode->i_file_acl_high =
@@ -3177,12 +3233,14 @@ int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode)
iloc, handle);
if (ret) {
EXT4_I(inode)->i_state |= EXT4_STATE_NO_EXPAND;
- if (mnt_count != sbi->s_es->s_mnt_count) {
+ if (mnt_count !=
+ le16_to_cpu(sbi->s_es->s_mnt_count)) {
ext4_warning(inode->i_sb, __FUNCTION__,
"Unable to expand inode %lu. Delete"
" some EAs or run e2fsck.",
inode->i_ino);
- mnt_count = sbi->s_es->s_mnt_count;
+ mnt_count =
+ le16_to_cpu(sbi->s_es->s_mnt_count);
}
}
}
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index c04c7ccba9e3..e7f894bdb420 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -51,6 +51,11 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
flags &= ~EXT4_DIRSYNC_FL;
mutex_lock(&inode->i_mutex);
+ /* Is it quota file? Do not allow user to mess with it */
+ if (IS_NOQUOTA(inode)) {
+ mutex_unlock(&inode->i_mutex);
+ return -EPERM;
+ }
oldflags = ei->i_flags;
/* The JOURNAL_DATA flag is modifiable only by root */
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 5fdb862e71c4..94ee6f315dc1 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -144,7 +144,6 @@ struct dx_map_entry
u16 size;
};
-#ifdef CONFIG_EXT4_INDEX
static inline unsigned dx_get_block (struct dx_entry *entry);
static void dx_set_block (struct dx_entry *entry, unsigned value);
static inline unsigned dx_get_hash (struct dx_entry *entry);
@@ -766,8 +765,6 @@ static void dx_insert_block(struct dx_frame *frame, u32 hash, u32 block)
dx_set_block(new, block);
dx_set_count(entries, count + 1);
}
-#endif
-
static void ext4_update_dx_flag(struct inode *inode)
{
@@ -869,7 +866,6 @@ static struct buffer_head * ext4_find_entry (struct dentry *dentry,
name = dentry->d_name.name;
if (namelen > EXT4_NAME_LEN)
return NULL;
-#ifdef CONFIG_EXT4_INDEX
if (is_dx(dir)) {
bh = ext4_dx_find_entry(dentry, res_dir, &err);
/*
@@ -881,7 +877,6 @@ static struct buffer_head * ext4_find_entry (struct dentry *dentry,
return bh;
dxtrace(printk("ext4_find_entry: dx failed, falling back\n"));
}
-#endif
nblocks = dir->i_size >> EXT4_BLOCK_SIZE_BITS(sb);
start = EXT4_I(dir)->i_dir_start_lookup;
if (start >= nblocks)
@@ -957,7 +952,6 @@ cleanup_and_exit:
return ret;
}
-#ifdef CONFIG_EXT4_INDEX
static struct buffer_head * ext4_dx_find_entry(struct dentry *dentry,
struct ext4_dir_entry_2 **res_dir, int *err)
{
@@ -1025,7 +1019,6 @@ errout:
dx_release (frames);
return NULL;
}
-#endif
static struct dentry *ext4_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
{
@@ -1121,7 +1114,6 @@ static inline void ext4_set_de_type(struct super_block *sb,
de->file_type = ext4_type_by_mode[(mode & S_IFMT)>>S_SHIFT];
}
-#ifdef CONFIG_EXT4_INDEX
/*
* Move count entries from end of map between two memory locations.
* Returns pointer to last entry moved.
@@ -1266,8 +1258,6 @@ errout:
*error = err;
return NULL;
}
-#endif
-
/*
* Add a new entry into a directory (leaf) block. If de is non-NULL,
@@ -1364,7 +1354,6 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
return 0;
}
-#ifdef CONFIG_EXT4_INDEX
/*
* This converts a one block unindexed directory to a 3 block indexed
* directory, and adds the dentry to the indexed directory.
@@ -1443,7 +1432,6 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
return add_dirent_to_buf(handle, dentry, inode, de, bh);
}
-#endif
/*
* ext4_add_entry()
@@ -1464,9 +1452,7 @@ static int ext4_add_entry (handle_t *handle, struct dentry *dentry,
struct ext4_dir_entry_2 *de;
struct super_block * sb;
int retval;
-#ifdef CONFIG_EXT4_INDEX
int dx_fallback=0;
-#endif
unsigned blocksize;
u32 block, blocks;
@@ -1474,7 +1460,6 @@ static int ext4_add_entry (handle_t *handle, struct dentry *dentry,
blocksize = sb->s_blocksize;
if (!dentry->d_name.len)
return -EINVAL;
-#ifdef CONFIG_EXT4_INDEX
if (is_dx(dir)) {
retval = ext4_dx_add_entry(handle, dentry, inode);
if (!retval || (retval != ERR_BAD_DX_DIR))
@@ -1483,7 +1468,6 @@ static int ext4_add_entry (handle_t *handle, struct dentry *dentry,
dx_fallback++;
ext4_mark_inode_dirty(handle, dir);
}
-#endif
blocks = dir->i_size >> sb->s_blocksize_bits;
for (block = 0, offset = 0; block < blocks; block++) {
bh = ext4_bread(handle, dir, block, 0, &retval);
@@ -1493,11 +1477,9 @@ static int ext4_add_entry (handle_t *handle, struct dentry *dentry,
if (retval != -ENOSPC)
return retval;
-#ifdef CONFIG_EXT4_INDEX
if (blocks == 1 && !dx_fallback &&
EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX))
return make_indexed_dir(handle, dentry, inode, bh);
-#endif
brelse(bh);
}
bh = ext4_append(handle, dir, &block, &retval);
@@ -1509,7 +1491,6 @@ static int ext4_add_entry (handle_t *handle, struct dentry *dentry,
return add_dirent_to_buf(handle, dentry, inode, de, bh);
}
-#ifdef CONFIG_EXT4_INDEX
/*
* Returns 0 for success, or a negative error value
*/
@@ -1644,7 +1625,6 @@ cleanup:
dx_release(frames);
return err;
}
-#endif
/*
* ext4_delete_entry deletes a directory entry by merging it with the
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
index aa11d7dbe970..bd8a52bb3999 100644
--- a/fs/ext4/resize.c
+++ b/fs/ext4/resize.c
@@ -16,6 +16,7 @@
#include <linux/errno.h>
#include <linux/slab.h>
+#include "group.h"
#define outside(b, first, last) ((b) < (first) || (b) >= (last))
#define inside(b, first, last) ((b) >= (first) && (b) < (last))
@@ -140,22 +141,29 @@ static struct buffer_head *bclean(handle_t *handle, struct super_block *sb,
}
/*
- * To avoid calling the atomic setbit hundreds or thousands of times, we only
- * need to use it within a single byte (to ensure we get endianness right).
- * We can use memset for the rest of the bitmap as there are no other users.
+ * If we have fewer than thresh credits, extend by EXT4_MAX_TRANS_DATA.
+ * If that fails, restart the transaction & regain write access for the
+ * buffer head which is used for block_bitmap modifications.
*/
-static void mark_bitmap_end(int start_bit, int end_bit, char *bitmap)
+static int extend_or_restart_transaction(handle_t *handle, int thresh,
+ struct buffer_head *bh)
{
- int i;
+ int err;
+
+ if (handle->h_buffer_credits >= thresh)
+ return 0;
- if (start_bit >= end_bit)
- return;
+ err = ext4_journal_extend(handle, EXT4_MAX_TRANS_DATA);
+ if (err < 0)
+ return err;
+ if (err) {
+ if ((err = ext4_journal_restart(handle, EXT4_MAX_TRANS_DATA)))
+ return err;
+ if ((err = ext4_journal_get_write_access(handle, bh)))
+ return err;
+ }
- ext4_debug("mark end bits +%d through +%d used\n", start_bit, end_bit);
- for (i = start_bit; i < ((start_bit + 7) & ~7UL); i++)
- ext4_set_bit(i, bitmap);
- if (i < end_bit)
- memset(bitmap + (i >> 3), 0xff, (end_bit - i) >> 3);
+ return 0;
}
/*
@@ -180,8 +188,9 @@ static int setup_new_group_blocks(struct super_block *sb,
int i;
int err = 0, err2;
- handle = ext4_journal_start_sb(sb, reserved_gdb + gdblocks +
- 2 + sbi->s_itb_per_group);
+ /* This transaction may be extended/restarted along the way */
+ handle = ext4_journal_start_sb(sb, EXT4_MAX_TRANS_DATA);
+
if (IS_ERR(handle))
return PTR_ERR(handle);
@@ -208,6 +217,9 @@ static int setup_new_group_blocks(struct super_block *sb,
ext4_debug("update backup group %#04lx (+%d)\n", block, bit);
+ if ((err = extend_or_restart_transaction(handle, 1, bh)))
+ goto exit_bh;
+
gdb = sb_getblk(sb, block);
if (!gdb) {
err = -EIO;
@@ -217,10 +229,10 @@ static int setup_new_group_blocks(struct super_block *sb,
brelse(gdb);
goto exit_bh;
}
- lock_buffer(bh);
- memcpy(gdb->b_data, sbi->s_group_desc[i]->b_data, bh->b_size);
+ lock_buffer(gdb);
+ memcpy(gdb->b_data, sbi->s_group_desc[i]->b_data, gdb->b_size);
set_buffer_uptodate(gdb);
- unlock_buffer(bh);
+ unlock_buffer(gdb);
ext4_journal_dirty_metadata(handle, gdb);
ext4_set_bit(bit, bh->b_data);
brelse(gdb);
@@ -233,6 +245,9 @@ static int setup_new_group_blocks(struct super_block *sb,
ext4_debug("clear reserved block %#04lx (+%d)\n", block, bit);
+ if ((err = extend_or_restart_transaction(handle, 1, bh)))
+ goto exit_bh;
+
if (IS_ERR(gdb = bclean(handle, sb, block))) {
err = PTR_ERR(bh);
goto exit_bh;
@@ -254,6 +269,10 @@ static int setup_new_group_blocks(struct super_block *sb,
struct buffer_head *it;
ext4_debug("clear inode block %#04lx (+%d)\n", block, bit);
+
+ if ((err = extend_or_restart_transaction(handle, 1, bh)))
+ goto exit_bh;
+
if (IS_ERR(it = bclean(handle, sb, block))) {
err = PTR_ERR(it);
goto exit_bh;
@@ -262,6 +281,10 @@ static int setup_new_group_blocks(struct super_block *sb,
brelse(it);
ext4_set_bit(bit, bh->b_data);
}
+
+ if ((err = extend_or_restart_transaction(handle, 2, bh)))
+ goto exit_bh;
+
mark_bitmap_end(input->blocks_count, EXT4_BLOCKS_PER_GROUP(sb),
bh->b_data);
ext4_journal_dirty_metadata(handle, bh);
@@ -289,7 +312,6 @@ exit_journal:
return err;
}
-
/*
* Iterate through the groups which hold BACKUP superblock/GDT copies in an
* ext4 filesystem. The counters should be initialized to 1, 5, and 7 before
@@ -842,6 +864,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
ext4_inode_table_set(sb, gdp, input->inode_table); /* LV FIXME */
gdp->bg_free_blocks_count = cpu_to_le16(input->free_blocks_count);
gdp->bg_free_inodes_count = cpu_to_le16(EXT4_INODES_PER_GROUP(sb));
+ gdp->bg_checksum = ext4_group_desc_csum(sbi, input->group, gdp);
/*
* Make the new blocks and inodes valid next. We do this before
@@ -893,9 +916,9 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
input->reserved_blocks);
/* Update the free space counts */
- percpu_counter_mod(&sbi->s_freeblocks_counter,
+ percpu_counter_add(&sbi->s_freeblocks_counter,
input->free_blocks_count);
- percpu_counter_mod(&sbi->s_freeinodes_counter,
+ percpu_counter_add(&sbi->s_freeinodes_counter,
EXT4_INODES_PER_GROUP(sb));
ext4_journal_dirty_metadata(handle, sbi->s_sbh);
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 3c1397fa83df..8031dc0e24e5 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -37,12 +37,14 @@
#include <linux/quotaops.h>
#include <linux/seq_file.h>
#include <linux/log2.h>
+#include <linux/crc16.h>
#include <asm/uaccess.h>
#include "xattr.h"
#include "acl.h"
#include "namei.h"
+#include "group.h"
static int ext4_load_journal(struct super_block *, struct ext4_super_block *,
unsigned long journal_devnum);
@@ -68,31 +70,31 @@ static void ext4_write_super_lockfs(struct super_block *sb);
ext4_fsblk_t ext4_block_bitmap(struct super_block *sb,
struct ext4_group_desc *bg)
{
- return le32_to_cpu(bg->bg_block_bitmap) |
+ return le32_to_cpu(bg->bg_block_bitmap_lo) |
(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
- (ext4_fsblk_t)le32_to_cpu(bg->bg_block_bitmap_hi) << 32 : 0);
+ (ext4_fsblk_t)le32_to_cpu(bg->bg_block_bitmap_hi) << 32 : 0);
}
ext4_fsblk_t ext4_inode_bitmap(struct super_block *sb,
struct ext4_group_desc *bg)
{
- return le32_to_cpu(bg->bg_inode_bitmap) |
+ return le32_to_cpu(bg->bg_inode_bitmap_lo) |
(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
- (ext4_fsblk_t)le32_to_cpu(bg->bg_inode_bitmap_hi) << 32 : 0);
+ (ext4_fsblk_t)le32_to_cpu(bg->bg_inode_bitmap_hi) << 32 : 0);
}
ext4_fsblk_t ext4_inode_table(struct super_block *sb,
struct ext4_group_desc *bg)
{
- return le32_to_cpu(bg->bg_inode_table) |
+ return le32_to_cpu(bg->bg_inode_table_lo) |
(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
- (ext4_fsblk_t)le32_to_cpu(bg->bg_inode_table_hi) << 32 : 0);
+ (ext4_fsblk_t)le32_to_cpu(bg->bg_inode_table_hi) << 32 : 0);
}
void ext4_block_bitmap_set(struct super_block *sb,
struct ext4_group_desc *bg, ext4_fsblk_t blk)
{
- bg->bg_block_bitmap = cpu_to_le32((u32)blk);
+ bg->bg_block_bitmap_lo = cpu_to_le32((u32)blk);
if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
bg->bg_block_bitmap_hi = cpu_to_le32(blk >> 32);
}
@@ -100,7 +102,7 @@ void ext4_block_bitmap_set(struct super_block *sb,
void ext4_inode_bitmap_set(struct super_block *sb,
struct ext4_group_desc *bg, ext4_fsblk_t blk)
{
- bg->bg_inode_bitmap = cpu_to_le32((u32)blk);
+ bg->bg_inode_bitmap_lo = cpu_to_le32((u32)blk);
if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
bg->bg_inode_bitmap_hi = cpu_to_le32(blk >> 32);
}
@@ -108,7 +110,7 @@ void ext4_inode_bitmap_set(struct super_block *sb,
void ext4_inode_table_set(struct super_block *sb,
struct ext4_group_desc *bg, ext4_fsblk_t blk)
{
- bg->bg_inode_table = cpu_to_le32((u32)blk);
+ bg->bg_inode_table_lo = cpu_to_le32((u32)blk);
if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
bg->bg_inode_table_hi = cpu_to_le32(blk >> 32);
}
@@ -523,7 +525,7 @@ static void ext4_destroy_inode(struct inode *inode)
kmem_cache_free(ext4_inode_cachep, EXT4_I(inode));
}
-static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
+static void init_once(struct kmem_cache *cachep, void *foo)
{
struct ext4_inode_info *ei = (struct ext4_inode_info *) foo;
@@ -596,9 +598,80 @@ static inline void ext4_show_quota_options(struct seq_file *seq, struct super_bl
#endif
}
+/*
+ * Show an option if
+ * - it's set to a non-default value OR
+ * - if the per-sb default is different from the global default
+ */
static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
{
struct super_block *sb = vfs->mnt_sb;
+ struct ext4_sb_info *sbi = EXT4_SB(sb);
+ struct ext4_super_block *es = sbi->s_es;
+ unsigned long def_mount_opts;
+
+ def_mount_opts = le32_to_cpu(es->s_default_mount_opts);
+
+ if (sbi->s_sb_block != 1)
+ seq_printf(seq, ",sb=%llu", sbi->s_sb_block);
+ if (test_opt(sb, MINIX_DF))
+ seq_puts(seq, ",minixdf");
+ if (test_opt(sb, GRPID))
+ seq_puts(seq, ",grpid");
+ if (!test_opt(sb, GRPID) && (def_mount_opts & EXT4_DEFM_BSDGROUPS))
+ seq_puts(seq, ",nogrpid");
+ if (sbi->s_resuid != EXT4_DEF_RESUID ||
+ le16_to_cpu(es->s_def_resuid) != EXT4_DEF_RESUID) {
+ seq_printf(seq, ",resuid=%u", sbi->s_resuid);
+ }
+ if (sbi->s_resgid != EXT4_DEF_RESGID ||
+ le16_to_cpu(es->s_def_resgid) != EXT4_DEF_RESGID) {
+ seq_printf(seq, ",resgid=%u", sbi->s_resgid);
+ }
+ if (test_opt(sb, ERRORS_CONT)) {
+ int def_errors = le16_to_cpu(es->s_errors);
+
+ if (def_errors == EXT4_ERRORS_PANIC ||
+ def_errors == EXT4_ERRORS_RO) {
+ seq_puts(seq, ",errors=continue");
+ }
+ }
+ if (test_opt(sb, ERRORS_RO))
+ seq_puts(seq, ",errors=remount-ro");
+ if (test_opt(sb, ERRORS_PANIC))
+ seq_puts(seq, ",errors=panic");
+ if (test_opt(sb, NO_UID32))
+ seq_puts(seq, ",nouid32");
+ if (test_opt(sb, DEBUG))
+ seq_puts(seq, ",debug");
+ if (test_opt(sb, OLDALLOC))
+ seq_puts(seq, ",oldalloc");
+#ifdef CONFIG_EXT4_FS_XATTR
+ if (test_opt(sb, XATTR_USER))
+ seq_puts(seq, ",user_xattr");
+ if (!test_opt(sb, XATTR_USER) &&
+ (def_mount_opts & EXT4_DEFM_XATTR_USER)) {
+ seq_puts(seq, ",nouser_xattr");
+ }
+#endif
+#ifdef CONFIG_EXT4_FS_POSIX_ACL
+ if (test_opt(sb, POSIX_ACL))
+ seq_puts(seq, ",acl");
+ if (!test_opt(sb, POSIX_ACL) && (def_mount_opts & EXT4_DEFM_ACL))
+ seq_puts(seq, ",noacl");
+#endif
+ if (!test_opt(sb, RESERVATION))
+ seq_puts(seq, ",noreservation");
+ if (sbi->s_commit_interval) {
+ seq_printf(seq, ",commit=%u",
+ (unsigned) (sbi->s_commit_interval / HZ));
+ }
+ if (test_opt(sb, BARRIER))
+ seq_puts(seq, ",barrier=1");
+ if (test_opt(sb, NOBH))
+ seq_puts(seq, ",nobh");
+ if (!test_opt(sb, EXTENTS))
+ seq_puts(seq, ",noextents");
if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)
seq_puts(seq, ",data=journal");
@@ -613,13 +686,10 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
}
-static struct dentry *ext4_get_dentry(struct super_block *sb, void *vobjp)
+static struct inode *ext4_nfs_get_inode(struct super_block *sb,
+ u64 ino, u32 generation)
{
- __u32 *objp = vobjp;
- unsigned long ino = objp[0];
- __u32 generation = objp[1];
struct inode *inode;
- struct dentry *result;
if (ino < EXT4_FIRST_INO(sb) && ino != EXT4_ROOT_INO)
return ERR_PTR(-ESTALE);
@@ -642,15 +712,22 @@ static struct dentry *ext4_get_dentry(struct super_block *sb, void *vobjp)
iput(inode);
return ERR_PTR(-ESTALE);
}
- /* now to find a dentry.
- * If possible, get a well-connected one
- */
- result = d_alloc_anon(inode);
- if (!result) {
- iput(inode);
- return ERR_PTR(-ENOMEM);
- }
- return result;
+
+ return inode;
+}
+
+static struct dentry *ext4_fh_to_dentry(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type)
+{
+ return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
+ ext4_nfs_get_inode);
+}
+
+static struct dentry *ext4_fh_to_parent(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type)
+{
+ return generic_fh_to_parent(sb, fid, fh_len, fh_type,
+ ext4_nfs_get_inode);
}
#ifdef CONFIG_QUOTA
@@ -719,9 +796,10 @@ static const struct super_operations ext4_sops = {
#endif
};
-static struct export_operations ext4_export_ops = {
+static const struct export_operations ext4_export_ops = {
+ .fh_to_dentry = ext4_fh_to_dentry,
+ .fh_to_parent = ext4_fh_to_parent,
.get_parent = ext4_get_parent,
- .get_dentry = ext4_get_dentry,
};
enum {
@@ -966,7 +1044,7 @@ static int parse_options (char *options, struct super_block *sb,
if (option < 0)
return 0;
if (option == 0)
- option = JBD_DEFAULT_MAX_COMMIT_AGE;
+ option = JBD2_DEFAULT_MAX_COMMIT_AGE;
sbi->s_commit_interval = HZ * option;
break;
case Opt_data_journal:
@@ -1237,6 +1315,43 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
return res;
}
+__le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 block_group,
+ struct ext4_group_desc *gdp)
+{
+ __u16 crc = 0;
+
+ if (sbi->s_es->s_feature_ro_compat &
+ cpu_to_le32(EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
+ int offset = offsetof(struct ext4_group_desc, bg_checksum);
+ __le32 le_group = cpu_to_le32(block_group);
+
+ crc = crc16(~0, sbi->s_es->s_uuid, sizeof(sbi->s_es->s_uuid));
+ crc = crc16(crc, (__u8 *)&le_group, sizeof(le_group));
+ crc = crc16(crc, (__u8 *)gdp, offset);
+ offset += sizeof(gdp->bg_checksum); /* skip checksum */
+ /* for checksum of struct ext4_group_desc do the rest...*/
+ if ((sbi->s_es->s_feature_incompat &
+ cpu_to_le32(EXT4_FEATURE_INCOMPAT_64BIT)) &&
+ offset < le16_to_cpu(sbi->s_es->s_desc_size))
+ crc = crc16(crc, (__u8 *)gdp + offset,
+ le16_to_cpu(sbi->s_es->s_desc_size) -
+ offset);
+ }
+
+ return cpu_to_le16(crc);
+}
+
+int ext4_group_desc_csum_verify(struct ext4_sb_info *sbi, __u32 block_group,
+ struct ext4_group_desc *gdp)
+{
+ if ((sbi->s_es->s_feature_ro_compat &
+ cpu_to_le32(EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) &&
+ (gdp->bg_checksum != ext4_group_desc_csum(sbi, block_group, gdp)))
+ return 0;
+
+ return 1;
+}
+
/* Called at mount-time, super-block is locked */
static int ext4_check_descriptors (struct super_block * sb)
{
@@ -1248,13 +1363,17 @@ static int ext4_check_descriptors (struct super_block * sb)
ext4_fsblk_t inode_table;
struct ext4_group_desc * gdp = NULL;
int desc_block = 0;
+ int flexbg_flag = 0;
int i;
+ if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG))
+ flexbg_flag = 1;
+
ext4_debug ("Checking group descriptors");
for (i = 0; i < sbi->s_groups_count; i++)
{
- if (i == sbi->s_groups_count - 1)
+ if (i == sbi->s_groups_count - 1 || flexbg_flag)
last_block = ext4_blocks_count(sbi->s_es) - 1;
else
last_block = first_block +
@@ -1291,7 +1410,16 @@ static int ext4_check_descriptors (struct super_block * sb)
i, inode_table);
return 0;
}
- first_block += EXT4_BLOCKS_PER_GROUP(sb);
+ if (!ext4_group_desc_csum_verify(sbi, i, gdp)) {
+ ext4_error(sb, __FUNCTION__,
+ "Checksum for group %d failed (%u!=%u)\n", i,
+ le16_to_cpu(ext4_group_desc_csum(sbi, i,
+ gdp)),
+ le16_to_cpu(gdp->bg_checksum));
+ return 0;
+ }
+ if (!flexbg_flag)
+ first_block += EXT4_BLOCKS_PER_GROUP(sb);
gdp = (struct ext4_group_desc *)
((__u8 *)gdp + EXT4_DESC_SIZE(sb));
}
@@ -1415,8 +1543,6 @@ static void ext4_orphan_cleanup (struct super_block * sb,
sb->s_flags = s_flags; /* Restore MS_RDONLY status */
}
-#define log2(n) ffz(~(n))
-
/*
* Maximal file size. There is a direct, and {,double-,triple-}indirect
* block limit, and also a limit of (2^32 - 1) 512-byte sectors in i_blocks.
@@ -1479,6 +1605,7 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
int needs_recovery;
__le32 features;
__u64 blocks_count;
+ int err;
sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
if (!sbi)
@@ -1487,6 +1614,7 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
sbi->s_mount_opt = 0;
sbi->s_resuid = EXT4_DEF_RESUID;
sbi->s_resgid = EXT4_DEF_RESGID;
+ sbi->s_sb_block = sb_block;
unlock_kernel();
@@ -1655,19 +1783,11 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE)
sb->s_time_gran = 1 << (EXT4_EPOCH_BITS - 2);
}
- sbi->s_frag_size = EXT4_MIN_FRAG_SIZE <<
- le32_to_cpu(es->s_log_frag_size);
- if (blocksize != sbi->s_frag_size) {
- printk(KERN_ERR
- "EXT4-fs: fragsize %lu != blocksize %u (unsupported)\n",
- sbi->s_frag_size, blocksize);
- goto failed_mount;
- }
sbi->s_desc_size = le16_to_cpu(es->s_desc_size);
if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_64BIT)) {
if (sbi->s_desc_size < EXT4_MIN_DESC_SIZE_64BIT ||
sbi->s_desc_size > EXT4_MAX_DESC_SIZE ||
- sbi->s_desc_size & (sbi->s_desc_size - 1)) {
+ !is_power_of_2(sbi->s_desc_size)) {
printk(KERN_ERR
"EXT4-fs: unsupported descriptor size %lu\n",
sbi->s_desc_size);
@@ -1676,7 +1796,6 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
} else
sbi->s_desc_size = EXT4_MIN_DESC_SIZE;
sbi->s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group);
- sbi->s_frags_per_group = le32_to_cpu(es->s_frags_per_group);
sbi->s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group);
if (EXT4_INODE_SIZE(sb) == 0)
goto cantfind_ext4;
@@ -1688,8 +1807,8 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
sbi->s_desc_per_block = blocksize / EXT4_DESC_SIZE(sb);
sbi->s_sbh = bh;
sbi->s_mount_state = le16_to_cpu(es->s_state);
- sbi->s_addr_per_block_bits = log2(EXT4_ADDR_PER_BLOCK(sb));
- sbi->s_desc_per_block_bits = log2(EXT4_DESC_PER_BLOCK(sb));
+ sbi->s_addr_per_block_bits = ilog2(EXT4_ADDR_PER_BLOCK(sb));
+ sbi->s_desc_per_block_bits = ilog2(EXT4_DESC_PER_BLOCK(sb));
for (i=0; i < 4; i++)
sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]);
sbi->s_def_hash_version = es->s_def_hash_version;
@@ -1700,12 +1819,6 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
sbi->s_blocks_per_group);
goto failed_mount;
}
- if (sbi->s_frags_per_group > blocksize * 8) {
- printk (KERN_ERR
- "EXT4-fs: #fragments per group too big: %lu\n",
- sbi->s_frags_per_group);
- goto failed_mount;
- }
if (sbi->s_inodes_per_group > blocksize * 8) {
printk (KERN_ERR
"EXT4-fs: #inodes per group too big: %lu\n",
@@ -1759,12 +1872,20 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
get_random_bytes(&sbi->s_next_generation, sizeof(u32));
spin_lock_init(&sbi->s_next_gen_lock);
- percpu_counter_init(&sbi->s_freeblocks_counter,
- ext4_count_free_blocks(sb));
- percpu_counter_init(&sbi->s_freeinodes_counter,
- ext4_count_free_inodes(sb));
- percpu_counter_init(&sbi->s_dirs_counter,
- ext4_count_dirs(sb));
+ err = percpu_counter_init(&sbi->s_freeblocks_counter,
+ ext4_count_free_blocks(sb));
+ if (!err) {
+ err = percpu_counter_init(&sbi->s_freeinodes_counter,
+ ext4_count_free_inodes(sb));
+ }
+ if (!err) {
+ err = percpu_counter_init(&sbi->s_dirs_counter,
+ ext4_count_dirs(sb));
+ }
+ if (err) {
+ printk(KERN_ERR "EXT4-fs: insufficient memory\n");
+ goto failed_mount3;
+ }
/* per fileystem reservation list head & lock */
spin_lock_init(&sbi->s_rsv_window_lock);
@@ -2551,7 +2672,7 @@ static int ext4_statfs (struct dentry * dentry, struct kstatfs * buf)
if (test_opt(sb, MINIX_DF)) {
sbi->s_overhead_last = 0;
- } else if (sbi->s_blocks_last != le32_to_cpu(es->s_blocks_count)) {
+ } else if (sbi->s_blocks_last != ext4_blocks_count(es)) {
unsigned long ngroups = sbi->s_groups_count, i;
ext4_fsblk_t overhead = 0;
smp_rmb();
@@ -2586,19 +2707,19 @@ static int ext4_statfs (struct dentry * dentry, struct kstatfs * buf)
overhead += ngroups * (2 + sbi->s_itb_per_group);
sbi->s_overhead_last = overhead;
smp_wmb();
- sbi->s_blocks_last = le32_to_cpu(es->s_blocks_count);
+ sbi->s_blocks_last = ext4_blocks_count(es);
}
buf->f_type = EXT4_SUPER_MAGIC;
buf->f_bsize = sb->s_blocksize;
buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last;
- buf->f_bfree = percpu_counter_sum(&sbi->s_freeblocks_counter);
- es->s_free_blocks_count = cpu_to_le32(buf->f_bfree);
+ buf->f_bfree = percpu_counter_sum_positive(&sbi->s_freeblocks_counter);
+ ext4_free_blocks_count_set(es, buf->f_bfree);
buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es);
if (buf->f_bfree < ext4_r_blocks_count(es))
buf->f_bavail = 0;
buf->f_files = le32_to_cpu(es->s_inodes_count);
- buf->f_ffree = percpu_counter_sum(&sbi->s_freeinodes_counter);
+ buf->f_ffree = percpu_counter_sum_positive(&sbi->s_freeinodes_counter);
es->s_free_inodes_count = cpu_to_le32(buf->f_ffree);
buf->f_namelen = EXT4_NAME_LEN;
fsid = le64_to_cpup((void *)es->s_uuid) ^
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index b10d68fffb55..86387302c2a9 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -750,12 +750,11 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
}
} else {
/* Allocate a buffer where we construct the new block. */
- s->base = kmalloc(sb->s_blocksize, GFP_KERNEL);
+ s->base = kzalloc(sb->s_blocksize, GFP_KERNEL);
/* assert(header == s->base) */
error = -ENOMEM;
if (s->base == NULL)
goto cleanup;
- memset(s->base, 0, sb->s_blocksize);
header(s->base)->h_magic = cpu_to_le32(EXT4_XATTR_MAGIC);
header(s->base)->h_blocks = cpu_to_le32(1);
header(s->base)->h_refcount = cpu_to_le32(1);
@@ -1121,7 +1120,7 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
int total_ino, total_blk;
void *base, *start, *end;
int extra_isize = 0, error = 0, tried_min_extra_isize = 0;
- int s_min_extra_isize = EXT4_SB(inode->i_sb)->s_es->s_min_extra_isize;
+ int s_min_extra_isize = le16_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_min_extra_isize);
down_write(&EXT4_I(inode)->xattr_sem);
retry:
@@ -1293,7 +1292,7 @@ retry:
i.name = b_entry_name;
i.value = buffer;
- i.value_len = cpu_to_le32(size);
+ i.value_len = size;
error = ext4_xattr_block_find(inode, &i, bs);
if (error)
goto cleanup;
diff --git a/fs/fat/cache.c b/fs/fat/cache.c
index be6f89b152ca..639b3b4f86d1 100644
--- a/fs/fat/cache.c
+++ b/fs/fat/cache.c
@@ -36,7 +36,7 @@ static inline int fat_max_cache(struct inode *inode)
static struct kmem_cache *fat_cache_cachep;
-static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags)
+static void init_once(struct kmem_cache *cachep, void *foo)
{
struct fat_cache *cache = (struct fat_cache *)foo;
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 4baa5f205368..920a576e1c25 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -141,19 +141,24 @@ static int fat_readpages(struct file *file, struct address_space *mapping,
return mpage_readpages(mapping, pages, nr_pages, fat_get_block);
}
-static int fat_prepare_write(struct file *file, struct page *page,
- unsigned from, unsigned to)
+static int fat_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
{
- return cont_prepare_write(page, from, to, fat_get_block,
- &MSDOS_I(page->mapping->host)->mmu_private);
+ *pagep = NULL;
+ return cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
+ fat_get_block,
+ &MSDOS_I(mapping->host)->mmu_private);
}
-static int fat_commit_write(struct file *file, struct page *page,
- unsigned from, unsigned to)
+static int fat_write_end(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *pagep, void *fsdata)
{
- struct inode *inode = page->mapping->host;
- int err = generic_commit_write(file, page, from, to);
- if (!err && !(MSDOS_I(inode)->i_attrs & ATTR_ARCH)) {
+ struct inode *inode = mapping->host;
+ int err;
+ err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata);
+ if (!(err < 0) && !(MSDOS_I(inode)->i_attrs & ATTR_ARCH)) {
inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
mark_inode_dirty(inode);
@@ -202,8 +207,8 @@ static const struct address_space_operations fat_aops = {
.writepage = fat_writepage,
.writepages = fat_writepages,
.sync_page = block_sync_page,
- .prepare_write = fat_prepare_write,
- .commit_write = fat_commit_write,
+ .write_begin = fat_write_begin,
+ .write_end = fat_write_end,
.direct_IO = fat_direct_IO,
.bmap = _fat_bmap
};
@@ -496,7 +501,7 @@ static void fat_destroy_inode(struct inode *inode)
kmem_cache_free(fat_inode_cachep, MSDOS_I(inode));
}
-static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
+static void init_once(struct kmem_cache *cachep, void *foo)
{
struct msdos_inode_info *ei = (struct msdos_inode_info *)foo;
@@ -648,24 +653,15 @@ static const struct super_operations fat_sops = {
* of i_logstart is used to store the directory entry offset.
*/
-static struct dentry *
-fat_decode_fh(struct super_block *sb, __u32 *fh, int len, int fhtype,
- int (*acceptable)(void *context, struct dentry *de),
- void *context)
-{
- if (fhtype != 3)
- return ERR_PTR(-ESTALE);
- if (len < 5)
- return ERR_PTR(-ESTALE);
-
- return sb->s_export_op->find_exported_dentry(sb, fh, NULL, acceptable, context);
-}
-
-static struct dentry *fat_get_dentry(struct super_block *sb, void *inump)
+static struct dentry *fat_fh_to_dentry(struct super_block *sb,
+ struct fid *fid, int fh_len, int fh_type)
{
struct inode *inode = NULL;
struct dentry *result;
- __u32 *fh = inump;
+ u32 *fh = fid->raw;
+
+ if (fh_len < 5 || fh_type != 3)
+ return NULL;
inode = iget(sb, fh[0]);
if (!inode || is_bad_inode(inode) || inode->i_generation != fh[1]) {
@@ -778,10 +774,9 @@ out:
return parent;
}
-static struct export_operations fat_export_ops = {
- .decode_fh = fat_decode_fh,
+static const struct export_operations fat_export_ops = {
.encode_fh = fat_encode_fh,
- .get_dentry = fat_get_dentry,
+ .fh_to_dentry = fat_fh_to_dentry,
.get_parent = fat_get_parent,
};
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 78b2ff044054..8685263ccc4a 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -18,6 +18,7 @@
#include <linux/ptrace.h>
#include <linux/signal.h>
#include <linux/rcupdate.h>
+#include <linux/pid_namespace.h>
#include <asm/poll.h>
#include <asm/siginfo.h>
@@ -110,7 +111,7 @@ out:
return error;
}
-static int dupfd(struct file *file, unsigned int start)
+static int dupfd(struct file *file, unsigned int start, int cloexec)
{
struct files_struct * files = current->files;
struct fdtable *fdt;
@@ -122,7 +123,10 @@ static int dupfd(struct file *file, unsigned int start)
/* locate_fd() may have expanded fdtable, load the ptr */
fdt = files_fdtable(files);
FD_SET(fd, fdt->open_fds);
- FD_CLR(fd, fdt->close_on_exec);
+ if (cloexec)
+ FD_SET(fd, fdt->close_on_exec);
+ else
+ FD_CLR(fd, fdt->close_on_exec);
spin_unlock(&files->file_lock);
fd_install(fd, file);
} else {
@@ -195,7 +199,7 @@ asmlinkage long sys_dup(unsigned int fildes)
struct file * file = fget(fildes);
if (file)
- ret = dupfd(file, 0);
+ ret = dupfd(file, 0, 0);
return ret;
}
@@ -289,7 +293,7 @@ int f_setown(struct file *filp, unsigned long arg, int force)
who = -who;
}
rcu_read_lock();
- pid = find_pid(who);
+ pid = find_vpid(who);
result = __f_setown(filp, pid, type, force);
rcu_read_unlock();
return result;
@@ -305,7 +309,7 @@ pid_t f_getown(struct file *filp)
{
pid_t pid;
read_lock(&filp->f_owner.lock);
- pid = pid_nr(filp->f_owner.pid);
+ pid = pid_nr_ns(filp->f_owner.pid, current->nsproxy->pid_ns);
if (filp->f_owner.pid_type == PIDTYPE_PGID)
pid = -pid;
read_unlock(&filp->f_owner.lock);
@@ -319,8 +323,9 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg,
switch (cmd) {
case F_DUPFD:
+ case F_DUPFD_CLOEXEC:
get_file(filp);
- err = dupfd(filp, arg);
+ err = dupfd(filp, arg, cmd == F_DUPFD_CLOEXEC);
break;
case F_GETFD:
err = get_close_on_exec(fd) ? FD_CLOEXEC : 0;
diff --git a/fs/file_table.c b/fs/file_table.c
index d17fd691b832..664e3f2309b8 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -98,16 +98,15 @@ struct file *get_empty_filp(void)
* percpu_counters are inaccurate. Do an expensive check before
* we go and fail.
*/
- if (percpu_counter_sum(&nr_files) >= files_stat.max_files)
+ if (percpu_counter_sum_positive(&nr_files) >= files_stat.max_files)
goto over;
}
- f = kmem_cache_alloc(filp_cachep, GFP_KERNEL);
+ f = kmem_cache_zalloc(filp_cachep, GFP_KERNEL);
if (f == NULL)
goto fail;
percpu_counter_inc(&nr_files);
- memset(f, 0, sizeof(*f));
if (security_file_alloc(f))
goto fail_sec;
@@ -138,6 +137,66 @@ fail:
EXPORT_SYMBOL(get_empty_filp);
+/**
+ * alloc_file - allocate and initialize a 'struct file'
+ * @mnt: the vfsmount on which the file will reside
+ * @dentry: the dentry representing the new file
+ * @mode: the mode with which the new file will be opened
+ * @fop: the 'struct file_operations' for the new file
+ *
+ * Use this instead of get_empty_filp() to get a new
+ * 'struct file'. Do so because of the same initialization
+ * pitfalls reasons listed for init_file(). This is a
+ * preferred interface to using init_file().
+ *
+ * If all the callers of init_file() are eliminated, its
+ * code should be moved into this function.
+ */
+struct file *alloc_file(struct vfsmount *mnt, struct dentry *dentry,
+ mode_t mode, const struct file_operations *fop)
+{
+ struct file *file;
+ struct path;
+
+ file = get_empty_filp();
+ if (!file)
+ return NULL;
+
+ init_file(file, mnt, dentry, mode, fop);
+ return file;
+}
+EXPORT_SYMBOL(alloc_file);
+
+/**
+ * init_file - initialize a 'struct file'
+ * @file: the already allocated 'struct file' to initialized
+ * @mnt: the vfsmount on which the file resides
+ * @dentry: the dentry representing this file
+ * @mode: the mode the file is opened with
+ * @fop: the 'struct file_operations' for this file
+ *
+ * Use this instead of setting the members directly. Doing so
+ * avoids making mistakes like forgetting the mntget() or
+ * forgetting to take a write on the mnt.
+ *
+ * Note: This is a crappy interface. It is here to make
+ * merging with the existing users of get_empty_filp()
+ * who have complex failure logic easier. All users
+ * of this should be moving to alloc_file().
+ */
+int init_file(struct file *file, struct vfsmount *mnt, struct dentry *dentry,
+ mode_t mode, const struct file_operations *fop)
+{
+ int error = 0;
+ file->f_path.dentry = dentry;
+ file->f_path.mnt = mntget(mnt);
+ file->f_mapping = dentry->d_inode->i_mapping;
+ file->f_mode = mode;
+ file->f_op = fop;
+ return error;
+}
+EXPORT_SYMBOL(init_file);
+
void fastcall fput(struct file *file)
{
if (atomic_dec_and_test(&file->f_count))
@@ -264,12 +323,11 @@ void file_kill(struct file *file)
int fs_may_remount_ro(struct super_block *sb)
{
- struct list_head *p;
+ struct file *file;
/* Check that no files are currently opened for writing. */
file_list_lock();
- list_for_each(p, &sb->s_files) {
- struct file *file = list_entry(p, struct file, f_u.fu_list);
+ list_for_each_entry(file, &sb->s_files, f_u.fu_list) {
struct inode *inode = file->f_path.dentry->d_inode;
/* File with pending delete? */
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 8d23b0b38717..0fca82021d76 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -89,7 +89,7 @@ void __mark_inode_dirty(struct inode *inode, int flags)
if (inode->i_ino || strcmp(inode->i_sb->s_id, "bdev"))
printk(KERN_DEBUG
"%s(%d): dirtied inode %lu (%s) on %s\n",
- current->comm, current->pid, inode->i_ino,
+ current->comm, task_pid_nr(current), inode->i_ino,
name, inode->i_sb->s_id);
}
@@ -100,11 +100,11 @@ void __mark_inode_dirty(struct inode *inode, int flags)
inode->i_state |= flags;
/*
- * If the inode is locked, just update its dirty state.
+ * If the inode is being synced, just update its dirty state.
* The unlocker will place the inode on the appropriate
* superblock list, based upon its state.
*/
- if (inode->i_state & I_LOCK)
+ if (inode->i_state & I_SYNC)
goto out;
/*
@@ -119,7 +119,7 @@ void __mark_inode_dirty(struct inode *inode, int flags)
goto out;
/*
- * If the inode was already on s_dirty or s_io, don't
+ * If the inode was already on s_dirty/s_io/s_more_io, don't
* reposition it (that would break s_dirty time-ordering).
*/
if (!was_dirty) {
@@ -141,6 +141,82 @@ static int write_inode(struct inode *inode, int sync)
}
/*
+ * Redirty an inode: set its when-it-was dirtied timestamp and move it to the
+ * furthest end of its superblock's dirty-inode list.
+ *
+ * Before stamping the inode's ->dirtied_when, we check to see whether it is
+ * already the most-recently-dirtied inode on the s_dirty list. If that is
+ * the case then the inode must have been redirtied while it was being written
+ * out and we don't reset its dirtied_when.
+ */
+static void redirty_tail(struct inode *inode)
+{
+ struct super_block *sb = inode->i_sb;
+
+ if (!list_empty(&sb->s_dirty)) {
+ struct inode *tail_inode;
+
+ tail_inode = list_entry(sb->s_dirty.next, struct inode, i_list);
+ if (!time_after_eq(inode->dirtied_when,
+ tail_inode->dirtied_when))
+ inode->dirtied_when = jiffies;
+ }
+ list_move(&inode->i_list, &sb->s_dirty);
+}
+
+/*
+ * requeue inode for re-scanning after sb->s_io list is exhausted.
+ */
+static void requeue_io(struct inode *inode)
+{
+ list_move(&inode->i_list, &inode->i_sb->s_more_io);
+}
+
+static void inode_sync_complete(struct inode *inode)
+{
+ /*
+ * Prevent speculative execution through spin_unlock(&inode_lock);
+ */
+ smp_mb();
+ wake_up_bit(&inode->i_state, __I_SYNC);
+}
+
+/*
+ * Move expired dirty inodes from @delaying_queue to @dispatch_queue.
+ */
+static void move_expired_inodes(struct list_head *delaying_queue,
+ struct list_head *dispatch_queue,
+ unsigned long *older_than_this)
+{
+ while (!list_empty(delaying_queue)) {
+ struct inode *inode = list_entry(delaying_queue->prev,
+ struct inode, i_list);
+ if (older_than_this &&
+ time_after(inode->dirtied_when, *older_than_this))
+ break;
+ list_move(&inode->i_list, dispatch_queue);
+ }
+}
+
+/*
+ * Queue all expired dirty inodes for io, eldest first.
+ */
+static void queue_io(struct super_block *sb,
+ unsigned long *older_than_this)
+{
+ list_splice_init(&sb->s_more_io, sb->s_io.prev);
+ move_expired_inodes(&sb->s_dirty, &sb->s_io, older_than_this);
+}
+
+int sb_has_dirty_inodes(struct super_block *sb)
+{
+ return !list_empty(&sb->s_dirty) ||
+ !list_empty(&sb->s_io) ||
+ !list_empty(&sb->s_more_io);
+}
+EXPORT_SYMBOL(sb_has_dirty_inodes);
+
+/*
* Write a single inode's dirty pages and inode data out to disk.
* If `wait' is set, wait on the writeout.
*
@@ -155,15 +231,14 @@ __sync_single_inode(struct inode *inode, struct writeback_control *wbc)
{
unsigned dirty;
struct address_space *mapping = inode->i_mapping;
- struct super_block *sb = inode->i_sb;
int wait = wbc->sync_mode == WB_SYNC_ALL;
int ret;
- BUG_ON(inode->i_state & I_LOCK);
+ BUG_ON(inode->i_state & I_SYNC);
- /* Set I_LOCK, reset I_DIRTY */
+ /* Set I_SYNC, reset I_DIRTY */
dirty = inode->i_state & I_DIRTY;
- inode->i_state |= I_LOCK;
+ inode->i_state |= I_SYNC;
inode->i_state &= ~I_DIRTY;
spin_unlock(&inode_lock);
@@ -184,24 +259,32 @@ __sync_single_inode(struct inode *inode, struct writeback_control *wbc)
}
spin_lock(&inode_lock);
- inode->i_state &= ~I_LOCK;
+ inode->i_state &= ~I_SYNC;
if (!(inode->i_state & I_FREEING)) {
if (!(inode->i_state & I_DIRTY) &&
mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) {
/*
* We didn't write back all the pages. nfs_writepages()
* sometimes bales out without doing anything. Redirty
- * the inode. It is still on sb->s_io.
+ * the inode; Move it from s_io onto s_more_io/s_dirty.
+ */
+ /*
+ * akpm: if the caller was the kupdate function we put
+ * this inode at the head of s_dirty so it gets first
+ * consideration. Otherwise, move it to the tail, for
+ * the reasons described there. I'm not really sure
+ * how much sense this makes. Presumably I had a good
+ * reasons for doing it this way, and I'd rather not
+ * muck with it at present.
*/
if (wbc->for_kupdate) {
/*
- * For the kupdate function we leave the inode
- * at the head of sb_dirty so it will get more
- * writeout as soon as the queue becomes
- * uncongested.
+ * For the kupdate function we move the inode
+ * to s_more_io so it will get more writeout as
+ * soon as the queue becomes uncongested.
*/
inode->i_state |= I_DIRTY_PAGES;
- list_move_tail(&inode->i_list, &sb->s_dirty);
+ requeue_io(inode);
} else {
/*
* Otherwise fully redirty the inode so that
@@ -211,15 +294,14 @@ __sync_single_inode(struct inode *inode, struct writeback_control *wbc)
* all the other files.
*/
inode->i_state |= I_DIRTY_PAGES;
- inode->dirtied_when = jiffies;
- list_move(&inode->i_list, &sb->s_dirty);
+ redirty_tail(inode);
}
} else if (inode->i_state & I_DIRTY) {
/*
* Someone redirtied the inode while were writing back
* the pages.
*/
- list_move(&inode->i_list, &sb->s_dirty);
+ redirty_tail(inode);
} else if (atomic_read(&inode->i_count)) {
/*
* The inode is clean, inuse
@@ -232,7 +314,7 @@ __sync_single_inode(struct inode *inode, struct writeback_control *wbc)
list_move(&inode->i_list, &inode_unused);
}
}
- wake_up_inode(inode);
+ inode_sync_complete(inode);
return ret;
}
@@ -251,11 +333,18 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
else
WARN_ON(inode->i_state & I_WILL_FREE);
- if ((wbc->sync_mode != WB_SYNC_ALL) && (inode->i_state & I_LOCK)) {
+ if ((wbc->sync_mode != WB_SYNC_ALL) && (inode->i_state & I_SYNC)) {
struct address_space *mapping = inode->i_mapping;
int ret;
- list_move(&inode->i_list, &inode->i_sb->s_dirty);
+ /*
+ * We're skipping this inode because it's locked, and we're not
+ * doing writeback-for-data-integrity. Move it to s_more_io so
+ * that writeback can proceed with the other inodes on s_io.
+ * We'll have another go at writing back this inode when we
+ * completed a full scan of s_io.
+ */
+ requeue_io(inode);
/*
* Even if we don't actually write the inode itself here,
@@ -270,16 +359,16 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
/*
* It's a data-integrity sync. We must wait.
*/
- if (inode->i_state & I_LOCK) {
- DEFINE_WAIT_BIT(wq, &inode->i_state, __I_LOCK);
+ if (inode->i_state & I_SYNC) {
+ DEFINE_WAIT_BIT(wq, &inode->i_state, __I_SYNC);
- wqh = bit_waitqueue(&inode->i_state, __I_LOCK);
+ wqh = bit_waitqueue(&inode->i_state, __I_SYNC);
do {
spin_unlock(&inode_lock);
__wait_on_bit(wqh, &wq, inode_wait,
TASK_UNINTERRUPTIBLE);
spin_lock(&inode_lock);
- } while (inode->i_state & I_LOCK);
+ } while (inode->i_state & I_SYNC);
}
return __sync_single_inode(inode, wbc);
}
@@ -312,7 +401,7 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
* The inodes to be written are parked on sb->s_io. They are moved back onto
* sb->s_dirty as they are selected for writing. This way, none can be missed
* on the writer throttling path, and we get decent balancing between many
- * throttled threads: we don't want them all piling up on __wait_on_inode.
+ * throttled threads: we don't want them all piling up on inode_sync_wait.
*/
static void
sync_sb_inodes(struct super_block *sb, struct writeback_control *wbc)
@@ -320,7 +409,7 @@ sync_sb_inodes(struct super_block *sb, struct writeback_control *wbc)
const unsigned long start = jiffies; /* livelock avoidance */
if (!wbc->for_kupdate || list_empty(&sb->s_io))
- list_splice_init(&sb->s_dirty, &sb->s_io);
+ queue_io(sb, wbc->older_than_this);
while (!list_empty(&sb->s_io)) {
struct inode *inode = list_entry(sb->s_io.prev,
@@ -330,7 +419,7 @@ sync_sb_inodes(struct super_block *sb, struct writeback_control *wbc)
long pages_skipped;
if (!bdi_cap_writeback_dirty(bdi)) {
- list_move(&inode->i_list, &sb->s_dirty);
+ redirty_tail(inode);
if (sb_is_blkdev_sb(sb)) {
/*
* Dirty memory-backed blockdev: the ramdisk
@@ -350,14 +439,14 @@ sync_sb_inodes(struct super_block *sb, struct writeback_control *wbc)
wbc->encountered_congestion = 1;
if (!sb_is_blkdev_sb(sb))
break; /* Skip a congested fs */
- list_move(&inode->i_list, &sb->s_dirty);
+ requeue_io(inode);
continue; /* Skip a congested blockdev */
}
if (wbc->bdi && bdi != wbc->bdi) {
if (!sb_is_blkdev_sb(sb))
break; /* fs has the wrong queue */
- list_move(&inode->i_list, &sb->s_dirty);
+ requeue_io(inode);
continue; /* blockdev has wrong queue */
}
@@ -365,11 +454,6 @@ sync_sb_inodes(struct super_block *sb, struct writeback_control *wbc)
if (time_after(inode->dirtied_when, start))
break;
- /* Was this inode dirtied too recently? */
- if (wbc->older_than_this && time_after(inode->dirtied_when,
- *wbc->older_than_this))
- break;
-
/* Is another pdflush already flushing this queue? */
if (current_is_pdflush() && !writeback_acquire(bdi))
break;
@@ -389,7 +473,7 @@ sync_sb_inodes(struct super_block *sb, struct writeback_control *wbc)
* writeback is not making progress due to locked
* buffers. Skip this inode for now.
*/
- list_move(&inode->i_list, &sb->s_dirty);
+ redirty_tail(inode);
}
spin_unlock(&inode_lock);
iput(inode);
@@ -398,6 +482,8 @@ sync_sb_inodes(struct super_block *sb, struct writeback_control *wbc)
if (wbc->nr_to_write <= 0)
break;
}
+ if (!list_empty(&sb->s_more_io))
+ wbc->more_io = 1;
return; /* Leave any unwritten inodes on s_io */
}
@@ -407,7 +493,7 @@ sync_sb_inodes(struct super_block *sb, struct writeback_control *wbc)
* Note:
* We don't need to grab a reference to superblock here. If it has non-empty
* ->s_dirty it's hadn't been killed yet and kill_super() won't proceed
- * past sync_inodes_sb() until both the ->s_dirty and ->s_io lists are
+ * past sync_inodes_sb() until the ->s_dirty/s_io/s_more_io lists are all
* empty. Since __sync_single_inode() regains inode_lock before it finally moves
* inode from superblock lists we are OK.
*
@@ -430,7 +516,7 @@ writeback_inodes(struct writeback_control *wbc)
restart:
sb = sb_entry(super_blocks.prev);
for (; sb != sb_entry(&super_blocks); sb = sb_entry(sb->s_list.prev)) {
- if (!list_empty(&sb->s_dirty) || !list_empty(&sb->s_io)) {
+ if (sb_has_dirty_inodes(sb)) {
/* we're making our own get_super here */
sb->s_count++;
spin_unlock(&sb_lock);
@@ -584,7 +670,7 @@ int write_inode_now(struct inode *inode, int sync)
ret = __writeback_single_inode(inode, &wbc);
spin_unlock(&inode_lock);
if (sync)
- wait_on_inode(inode);
+ inode_sync_wait(inode);
return ret;
}
EXPORT_SYMBOL(write_inode_now);
@@ -659,7 +745,7 @@ int generic_osync_inode(struct inode *inode, struct address_space *mapping, int
err = err2;
}
else
- wait_on_inode(inode);
+ inode_sync_wait(inode);
return err;
}
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 3ad22beb24c2..db534bcde45f 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -129,7 +129,7 @@ static struct fuse_req *get_reserved_req(struct fuse_conn *fc,
struct fuse_file *ff = file->private_data;
do {
- wait_event(fc->blocked_waitq, ff->reserved_req);
+ wait_event(fc->reserved_req_waitq, ff->reserved_req);
spin_lock(&fc->lock);
if (ff->reserved_req) {
req = ff->reserved_req;
@@ -155,7 +155,7 @@ static void put_reserved_req(struct fuse_conn *fc, struct fuse_req *req)
fuse_request_init(req);
BUG_ON(ff->reserved_req);
ff->reserved_req = req;
- wake_up(&fc->blocked_waitq);
+ wake_up_all(&fc->reserved_req_waitq);
spin_unlock(&fc->lock);
fput(file);
}
@@ -224,13 +224,13 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req)
fc->blocked = 0;
wake_up_all(&fc->blocked_waitq);
}
+ if (fc->num_background == FUSE_CONGESTION_THRESHOLD) {
+ clear_bdi_congested(&fc->bdi, READ);
+ clear_bdi_congested(&fc->bdi, WRITE);
+ }
fc->num_background--;
}
spin_unlock(&fc->lock);
- dput(req->dentry);
- mntput(req->vfsmount);
- if (req->file)
- fput(req->file);
wake_up(&req->waitq);
if (end)
end(fc, req);
@@ -273,28 +273,41 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
queue_interrupt(fc, req);
}
- if (req->force) {
- spin_unlock(&fc->lock);
- wait_event(req->waitq, req->state == FUSE_REQ_FINISHED);
- spin_lock(&fc->lock);
- } else {
+ if (!req->force) {
sigset_t oldset;
/* Only fatal signals may interrupt this */
block_sigs(&oldset);
wait_answer_interruptible(fc, req);
restore_sigs(&oldset);
+
+ if (req->aborted)
+ goto aborted;
+ if (req->state == FUSE_REQ_FINISHED)
+ return;
+
+ /* Request is not yet in userspace, bail out */
+ if (req->state == FUSE_REQ_PENDING) {
+ list_del(&req->list);
+ __fuse_put_request(req);
+ req->out.h.error = -EINTR;
+ return;
+ }
}
- if (req->aborted)
- goto aborted;
- if (req->state == FUSE_REQ_FINISHED)
- return;
+ /*
+ * Either request is already in userspace, or it was forced.
+ * Wait it out.
+ */
+ spin_unlock(&fc->lock);
+ wait_event(req->waitq, req->state == FUSE_REQ_FINISHED);
+ spin_lock(&fc->lock);
- req->out.h.error = -EINTR;
- req->aborted = 1;
+ if (!req->aborted)
+ return;
aborted:
+ BUG_ON(req->state != FUSE_REQ_FINISHED);
if (req->locked) {
/* This is uninterruptible sleep, because data is
being copied to/from the buffers of req. During
@@ -305,14 +318,6 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
wait_event(req->waitq, !req->locked);
spin_lock(&fc->lock);
}
- if (req->state == FUSE_REQ_PENDING) {
- list_del(&req->list);
- __fuse_put_request(req);
- } else if (req->state == FUSE_REQ_SENT) {
- spin_unlock(&fc->lock);
- wait_event(req->waitq, req->state == FUSE_REQ_FINISHED);
- spin_lock(&fc->lock);
- }
}
static unsigned len_args(unsigned numargs, struct fuse_arg *args)
@@ -378,6 +383,10 @@ static void request_send_nowait(struct fuse_conn *fc, struct fuse_req *req)
fc->num_background++;
if (fc->num_background == FUSE_MAX_BACKGROUND)
fc->blocked = 1;
+ if (fc->num_background == FUSE_CONGESTION_THRESHOLD) {
+ set_bdi_congested(&fc->bdi, READ);
+ set_bdi_congested(&fc->bdi, WRITE);
+ }
queue_request(fc, req);
spin_unlock(&fc->lock);
@@ -738,11 +747,12 @@ static ssize_t fuse_dev_read(struct kiocb *iocb, const struct iovec *iov,
fuse_copy_finish(&cs);
spin_lock(&fc->lock);
req->locked = 0;
- if (!err && req->aborted)
- err = -ENOENT;
+ if (req->aborted) {
+ request_end(fc, req);
+ return -ENODEV;
+ }
if (err) {
- if (!req->aborted)
- req->out.h.error = -EIO;
+ req->out.h.error = -EIO;
request_end(fc, req);
return err;
}
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index bd5a772d8ccf..3763757f9fe7 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -63,13 +63,21 @@ static u64 time_to_jiffies(unsigned long sec, unsigned long nsec)
* Set dentry and possibly attribute timeouts from the lookup/mk*
* replies
*/
-static void fuse_change_timeout(struct dentry *entry, struct fuse_entry_out *o)
+static void fuse_change_entry_timeout(struct dentry *entry,
+ struct fuse_entry_out *o)
{
fuse_dentry_settime(entry,
time_to_jiffies(o->entry_valid, o->entry_valid_nsec));
- if (entry->d_inode)
- get_fuse_inode(entry->d_inode)->i_time =
- time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
+}
+
+static u64 attr_timeout(struct fuse_attr_out *o)
+{
+ return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
+}
+
+static u64 entry_attr_timeout(struct fuse_entry_out *o)
+{
+ return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
}
/*
@@ -108,13 +116,19 @@ static void fuse_lookup_init(struct fuse_req *req, struct inode *dir,
struct dentry *entry,
struct fuse_entry_out *outarg)
{
+ struct fuse_conn *fc = get_fuse_conn(dir);
+
+ memset(outarg, 0, sizeof(struct fuse_entry_out));
req->in.h.opcode = FUSE_LOOKUP;
req->in.h.nodeid = get_node_id(dir);
req->in.numargs = 1;
req->in.args[0].size = entry->d_name.len + 1;
req->in.args[0].value = entry->d_name.name;
req->out.numargs = 1;
- req->out.args[0].size = sizeof(struct fuse_entry_out);
+ if (fc->minor < 9)
+ req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
+ else
+ req->out.args[0].size = sizeof(struct fuse_entry_out);
req->out.args[0].value = outarg;
}
@@ -140,6 +154,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
struct fuse_req *req;
struct fuse_req *forget_req;
struct dentry *parent;
+ u64 attr_version;
/* For negative dentries, always do a fresh lookup */
if (!inode)
@@ -156,6 +171,10 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
return 0;
}
+ spin_lock(&fc->lock);
+ attr_version = fc->attr_version;
+ spin_unlock(&fc->lock);
+
parent = dget_parent(entry);
fuse_lookup_init(req, parent->d_inode, entry, &outarg);
request_send(fc, req);
@@ -180,8 +199,10 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
return 0;
- fuse_change_attributes(inode, &outarg.attr);
- fuse_change_timeout(entry, &outarg);
+ fuse_change_attributes(inode, &outarg.attr,
+ entry_attr_timeout(&outarg),
+ attr_version);
+ fuse_change_entry_timeout(entry, &outarg);
}
return 1;
}
@@ -228,6 +249,7 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
struct fuse_conn *fc = get_fuse_conn(dir);
struct fuse_req *req;
struct fuse_req *forget_req;
+ u64 attr_version;
if (entry->d_name.len > FUSE_NAME_MAX)
return ERR_PTR(-ENAMETOOLONG);
@@ -242,6 +264,10 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
return ERR_PTR(PTR_ERR(forget_req));
}
+ spin_lock(&fc->lock);
+ attr_version = fc->attr_version;
+ spin_unlock(&fc->lock);
+
fuse_lookup_init(req, dir, entry, &outarg);
request_send(fc, req);
err = req->out.h.error;
@@ -253,7 +279,8 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
err = -EIO;
if (!err && outarg.nodeid) {
inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
- &outarg.attr);
+ &outarg.attr, entry_attr_timeout(&outarg),
+ attr_version);
if (!inode) {
fuse_send_forget(fc, forget_req, outarg.nodeid, 1);
return ERR_PTR(-ENOMEM);
@@ -276,7 +303,7 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
entry->d_op = &fuse_dentry_operations;
if (!err)
- fuse_change_timeout(entry, &outarg);
+ fuse_change_entry_timeout(entry, &outarg);
else
fuse_invalidate_entry_cache(entry);
return NULL;
@@ -288,12 +315,11 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
static void fuse_sync_release(struct fuse_conn *fc, struct fuse_file *ff,
u64 nodeid, int flags)
{
- struct fuse_req *req;
-
- req = fuse_release_fill(ff, nodeid, flags, FUSE_RELEASE);
- req->force = 1;
- request_send(fc, req);
- fuse_put_request(fc, req);
+ fuse_release_fill(ff, nodeid, flags, FUSE_RELEASE);
+ ff->reserved_req->force = 1;
+ request_send(fc, ff->reserved_req);
+ fuse_put_request(fc, ff->reserved_req);
+ kfree(ff);
}
/*
@@ -336,6 +362,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
flags &= ~O_NOCTTY;
memset(&inarg, 0, sizeof(inarg));
+ memset(&outentry, 0, sizeof(outentry));
inarg.flags = flags;
inarg.mode = mode;
req->in.h.opcode = FUSE_CREATE;
@@ -346,7 +373,10 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
req->in.args[1].size = entry->d_name.len + 1;
req->in.args[1].value = entry->d_name.name;
req->out.numargs = 2;
- req->out.args[0].size = sizeof(outentry);
+ if (fc->minor < 9)
+ req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
+ else
+ req->out.args[0].size = sizeof(outentry);
req->out.args[0].value = &outentry;
req->out.args[1].size = sizeof(outopen);
req->out.args[1].value = &outopen;
@@ -364,7 +394,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
fuse_put_request(fc, req);
inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
- &outentry.attr);
+ &outentry.attr, entry_attr_timeout(&outentry), 0);
if (!inode) {
flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
ff->fh = outopen.fh;
@@ -374,7 +404,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
}
fuse_put_request(fc, forget_req);
d_instantiate(entry, inode);
- fuse_change_timeout(entry, &outentry);
+ fuse_change_entry_timeout(entry, &outentry);
file = lookup_instantiate_filp(nd, entry, generic_file_open);
if (IS_ERR(file)) {
ff->fh = outopen.fh;
@@ -411,9 +441,13 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
return PTR_ERR(forget_req);
}
+ memset(&outarg, 0, sizeof(outarg));
req->in.h.nodeid = get_node_id(dir);
req->out.numargs = 1;
- req->out.args[0].size = sizeof(outarg);
+ if (fc->minor < 9)
+ req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
+ else
+ req->out.args[0].size = sizeof(outarg);
req->out.args[0].value = &outarg;
request_send(fc, req);
err = req->out.h.error;
@@ -429,7 +463,7 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
goto out_put_forget_req;
inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
- &outarg.attr);
+ &outarg.attr, entry_attr_timeout(&outarg), 0);
if (!inode) {
fuse_send_forget(fc, forget_req, outarg.nodeid, 1);
return -ENOMEM;
@@ -452,7 +486,7 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
} else
d_instantiate(entry, inode);
- fuse_change_timeout(entry, &outarg);
+ fuse_change_entry_timeout(entry, &outarg);
fuse_invalidate_attr(dir);
return 0;
@@ -664,32 +698,78 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
return err;
}
-int fuse_do_getattr(struct inode *inode)
+static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
+ struct kstat *stat)
+{
+ stat->dev = inode->i_sb->s_dev;
+ stat->ino = attr->ino;
+ stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
+ stat->nlink = attr->nlink;
+ stat->uid = attr->uid;
+ stat->gid = attr->gid;
+ stat->rdev = inode->i_rdev;
+ stat->atime.tv_sec = attr->atime;
+ stat->atime.tv_nsec = attr->atimensec;
+ stat->mtime.tv_sec = attr->mtime;
+ stat->mtime.tv_nsec = attr->mtimensec;
+ stat->ctime.tv_sec = attr->ctime;
+ stat->ctime.tv_nsec = attr->ctimensec;
+ stat->size = attr->size;
+ stat->blocks = attr->blocks;
+ stat->blksize = (1 << inode->i_blkbits);
+}
+
+static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
+ struct file *file)
{
int err;
- struct fuse_attr_out arg;
+ struct fuse_getattr_in inarg;
+ struct fuse_attr_out outarg;
struct fuse_conn *fc = get_fuse_conn(inode);
- struct fuse_req *req = fuse_get_req(fc);
+ struct fuse_req *req;
+ u64 attr_version;
+
+ req = fuse_get_req(fc);
if (IS_ERR(req))
return PTR_ERR(req);
+ spin_lock(&fc->lock);
+ attr_version = fc->attr_version;
+ spin_unlock(&fc->lock);
+
+ memset(&inarg, 0, sizeof(inarg));
+ memset(&outarg, 0, sizeof(outarg));
+ /* Directories have separate file-handle space */
+ if (file && S_ISREG(inode->i_mode)) {
+ struct fuse_file *ff = file->private_data;
+
+ inarg.getattr_flags |= FUSE_GETATTR_FH;
+ inarg.fh = ff->fh;
+ }
req->in.h.opcode = FUSE_GETATTR;
req->in.h.nodeid = get_node_id(inode);
+ req->in.numargs = 1;
+ req->in.args[0].size = sizeof(inarg);
+ req->in.args[0].value = &inarg;
req->out.numargs = 1;
- req->out.args[0].size = sizeof(arg);
- req->out.args[0].value = &arg;
+ if (fc->minor < 9)
+ req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
+ else
+ req->out.args[0].size = sizeof(outarg);
+ req->out.args[0].value = &outarg;
request_send(fc, req);
err = req->out.h.error;
fuse_put_request(fc, req);
if (!err) {
- if ((inode->i_mode ^ arg.attr.mode) & S_IFMT) {
+ if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
make_bad_inode(inode);
err = -EIO;
} else {
- struct fuse_inode *fi = get_fuse_inode(inode);
- fuse_change_attributes(inode, &arg.attr);
- fi->i_time = time_to_jiffies(arg.attr_valid,
- arg.attr_valid_nsec);
+ fuse_change_attributes(inode, &outarg.attr,
+ attr_timeout(&outarg),
+ attr_version);
+ if (stat)
+ fuse_fillattr(inode, &outarg.attr, stat);
}
}
return err;
@@ -708,7 +788,7 @@ int fuse_do_getattr(struct inode *inode)
* for which the owner of the mount has ptrace privilege. This
* excludes processes started by other users, suid or sgid processes.
*/
-static int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task)
+int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task)
{
if (fc->flags & FUSE_ALLOW_OTHER)
return 1;
@@ -724,30 +804,6 @@ static int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task)
return 0;
}
-/*
- * Check whether the inode attributes are still valid
- *
- * If the attribute validity timeout has expired, then fetch the fresh
- * attributes with a 'getattr' request
- *
- * I'm not sure why cached attributes are never returned for the root
- * inode, this is probably being too cautious.
- */
-static int fuse_revalidate(struct dentry *entry)
-{
- struct inode *inode = entry->d_inode;
- struct fuse_inode *fi = get_fuse_inode(inode);
- struct fuse_conn *fc = get_fuse_conn(inode);
-
- if (!fuse_allow_task(fc, current))
- return -EACCES;
- if (get_node_id(inode) != FUSE_ROOT_ID &&
- fi->i_time >= get_jiffies_64())
- return 0;
-
- return fuse_do_getattr(inode);
-}
-
static int fuse_access(struct inode *inode, int mask)
{
struct fuse_conn *fc = get_fuse_conn(inode);
@@ -795,17 +851,35 @@ static int fuse_access(struct inode *inode, int mask)
static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
{
struct fuse_conn *fc = get_fuse_conn(inode);
+ bool refreshed = false;
+ int err = 0;
if (!fuse_allow_task(fc, current))
return -EACCES;
- else if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
+
+ /*
+ * If attributes are needed, refresh them before proceeding
+ */
+ if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) ||
+ ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
+ struct fuse_inode *fi = get_fuse_inode(inode);
+ if (fi->i_time < get_jiffies_64()) {
+ err = fuse_do_getattr(inode, NULL, NULL);
+ if (err)
+ return err;
+
+ refreshed = true;
+ }
+ }
+
+ if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
int err = generic_permission(inode, mask, NULL);
/* If permission is denied, try to refresh file
attributes. This is also needed, because the root
node will at first have no permissions */
- if (err == -EACCES) {
- err = fuse_do_getattr(inode);
+ if (err == -EACCES && !refreshed) {
+ err = fuse_do_getattr(inode, NULL, NULL);
if (!err)
err = generic_permission(inode, mask, NULL);
}
@@ -814,17 +888,19 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
exist. So if permissions are revoked this won't be
noticed immediately, only after the attribute
timeout has expired */
-
- return err;
- } else {
- int mode = inode->i_mode;
- if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO))
- return -EACCES;
-
- if (nd && (nd->flags & (LOOKUP_ACCESS | LOOKUP_CHDIR)))
- return fuse_access(inode, mask);
- return 0;
+ } else if (nd && (nd->flags & (LOOKUP_ACCESS | LOOKUP_CHDIR))) {
+ err = fuse_access(inode, mask);
+ } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
+ if (!(inode->i_mode & S_IXUGO)) {
+ if (refreshed)
+ return -EACCES;
+
+ err = fuse_do_getattr(inode, NULL, NULL);
+ if (!err && !(inode->i_mode & S_IXUGO))
+ return -EACCES;
+ }
}
+ return err;
}
static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
@@ -859,6 +935,7 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
struct page *page;
struct inode *inode = file->f_path.dentry->d_inode;
struct fuse_conn *fc = get_fuse_conn(inode);
+ struct fuse_file *ff = file->private_data;
struct fuse_req *req;
if (is_bad_inode(inode))
@@ -875,7 +952,7 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
}
req->num_pages = 1;
req->pages[0] = page;
- fuse_read_fill(req, file, inode, file->f_pos, PAGE_SIZE, FUSE_READDIR);
+ fuse_read_fill(req, ff, inode, file->f_pos, PAGE_SIZE, FUSE_READDIR);
request_send(fc, req);
nbytes = req->out.args[0].size;
err = req->out.h.error;
@@ -955,6 +1032,20 @@ static int fuse_dir_fsync(struct file *file, struct dentry *de, int datasync)
return file ? fuse_fsync_common(file, de, datasync, 1) : 0;
}
+static bool update_mtime(unsigned ivalid)
+{
+ /* Always update if mtime is explicitly set */
+ if (ivalid & ATTR_MTIME_SET)
+ return true;
+
+ /* If it's an open(O_TRUNC) or an ftruncate(), don't update */
+ if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
+ return false;
+
+ /* In all other cases update */
+ return true;
+}
+
static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
{
unsigned ivalid = iattr->ia_valid;
@@ -967,33 +1058,19 @@ static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
arg->valid |= FATTR_GID, arg->gid = iattr->ia_gid;
if (ivalid & ATTR_SIZE)
arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size;
- /* You can only _set_ these together (they may change by themselves) */
- if ((ivalid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME)) {
- arg->valid |= FATTR_ATIME | FATTR_MTIME;
+ if (ivalid & ATTR_ATIME) {
+ arg->valid |= FATTR_ATIME;
arg->atime = iattr->ia_atime.tv_sec;
- arg->mtime = iattr->ia_mtime.tv_sec;
+ arg->atimensec = iattr->ia_atime.tv_nsec;
+ if (!(ivalid & ATTR_ATIME_SET))
+ arg->valid |= FATTR_ATIME_NOW;
}
- if (ivalid & ATTR_FILE) {
- struct fuse_file *ff = iattr->ia_file->private_data;
- arg->valid |= FATTR_FH;
- arg->fh = ff->fh;
- }
-}
-
-static void fuse_vmtruncate(struct inode *inode, loff_t offset)
-{
- struct fuse_conn *fc = get_fuse_conn(inode);
- int need_trunc;
-
- spin_lock(&fc->lock);
- need_trunc = inode->i_size > offset;
- i_size_write(inode, offset);
- spin_unlock(&fc->lock);
-
- if (need_trunc) {
- struct address_space *mapping = inode->i_mapping;
- unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
- truncate_inode_pages(mapping, offset);
+ if ((ivalid & ATTR_MTIME) && update_mtime(ivalid)) {
+ arg->valid |= FATTR_MTIME;
+ arg->mtime = iattr->ia_mtime.tv_sec;
+ arg->mtimensec = iattr->ia_mtime.tv_nsec;
+ if (!(ivalid & ATTR_MTIME_SET))
+ arg->valid |= FATTR_MTIME_NOW;
}
}
@@ -1005,16 +1082,18 @@ static void fuse_vmtruncate(struct inode *inode, loff_t offset)
* vmtruncate() doesn't allow for this case, so do the rlimit checking
* and the actual truncation by hand.
*/
-static int fuse_setattr(struct dentry *entry, struct iattr *attr)
+static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
+ struct file *file)
{
struct inode *inode = entry->d_inode;
struct fuse_conn *fc = get_fuse_conn(inode);
- struct fuse_inode *fi = get_fuse_inode(inode);
struct fuse_req *req;
struct fuse_setattr_in inarg;
struct fuse_attr_out outarg;
int err;
- int is_truncate = 0;
+
+ if (!fuse_allow_task(fc, current))
+ return -EACCES;
if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
err = inode_change_ok(inode, attr);
@@ -1022,9 +1101,11 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr)
return err;
}
+ if ((attr->ia_valid & ATTR_OPEN) && fc->atomic_o_trunc)
+ return 0;
+
if (attr->ia_valid & ATTR_SIZE) {
unsigned long limit;
- is_truncate = 1;
if (IS_SWAPFILE(inode))
return -ETXTBSY;
limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
@@ -1039,42 +1120,73 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr)
return PTR_ERR(req);
memset(&inarg, 0, sizeof(inarg));
+ memset(&outarg, 0, sizeof(outarg));
iattr_to_fattr(attr, &inarg);
+ if (file) {
+ struct fuse_file *ff = file->private_data;
+ inarg.valid |= FATTR_FH;
+ inarg.fh = ff->fh;
+ }
+ if (attr->ia_valid & ATTR_SIZE) {
+ /* For mandatory locking in truncate */
+ inarg.valid |= FATTR_LOCKOWNER;
+ inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
+ }
req->in.h.opcode = FUSE_SETATTR;
req->in.h.nodeid = get_node_id(inode);
req->in.numargs = 1;
req->in.args[0].size = sizeof(inarg);
req->in.args[0].value = &inarg;
req->out.numargs = 1;
- req->out.args[0].size = sizeof(outarg);
+ if (fc->minor < 9)
+ req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
+ else
+ req->out.args[0].size = sizeof(outarg);
req->out.args[0].value = &outarg;
request_send(fc, req);
err = req->out.h.error;
fuse_put_request(fc, req);
- if (!err) {
- if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
- make_bad_inode(inode);
- err = -EIO;
- } else {
- if (is_truncate)
- fuse_vmtruncate(inode, outarg.attr.size);
- fuse_change_attributes(inode, &outarg.attr);
- fi->i_time = time_to_jiffies(outarg.attr_valid,
- outarg.attr_valid_nsec);
- }
- } else if (err == -EINTR)
- fuse_invalidate_attr(inode);
+ if (err) {
+ if (err == -EINTR)
+ fuse_invalidate_attr(inode);
+ return err;
+ }
- return err;
+ if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
+ make_bad_inode(inode);
+ return -EIO;
+ }
+
+ fuse_change_attributes(inode, &outarg.attr, attr_timeout(&outarg), 0);
+ return 0;
+}
+
+static int fuse_setattr(struct dentry *entry, struct iattr *attr)
+{
+ if (attr->ia_valid & ATTR_FILE)
+ return fuse_do_setattr(entry, attr, attr->ia_file);
+ else
+ return fuse_do_setattr(entry, attr, NULL);
}
static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
struct kstat *stat)
{
struct inode *inode = entry->d_inode;
- int err = fuse_revalidate(entry);
- if (!err)
+ struct fuse_inode *fi = get_fuse_inode(inode);
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ int err;
+
+ if (!fuse_allow_task(fc, current))
+ return -EACCES;
+
+ if (fi->i_time < get_jiffies_64())
+ err = fuse_do_getattr(inode, stat, NULL);
+ else {
+ err = 0;
generic_fillattr(inode, stat);
+ stat->mode = fi->orig_i_mode;
+ }
return err;
}
@@ -1176,6 +1288,9 @@ static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
struct fuse_getxattr_out outarg;
ssize_t ret;
+ if (!fuse_allow_task(fc, current))
+ return -EACCES;
+
if (fc->no_listxattr)
return -EOPNOTSUPP;
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index f79de7c8cdfa..535b37399009 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -28,7 +28,9 @@ static int fuse_send_open(struct inode *inode, struct file *file, int isdir,
return PTR_ERR(req);
memset(&inarg, 0, sizeof(inarg));
- inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
+ inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY);
+ if (!fc->atomic_o_trunc)
+ inarg.flags &= ~O_TRUNC;
req->in.h.opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN;
req->in.h.nodeid = get_node_id(inode);
req->in.numargs = 1;
@@ -53,6 +55,9 @@ struct fuse_file *fuse_file_alloc(void)
if (!ff->reserved_req) {
kfree(ff);
ff = NULL;
+ } else {
+ INIT_LIST_HEAD(&ff->write_entry);
+ atomic_set(&ff->count, 0);
}
}
return ff;
@@ -64,15 +69,39 @@ void fuse_file_free(struct fuse_file *ff)
kfree(ff);
}
+static struct fuse_file *fuse_file_get(struct fuse_file *ff)
+{
+ atomic_inc(&ff->count);
+ return ff;
+}
+
+static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req)
+{
+ dput(req->dentry);
+ mntput(req->vfsmount);
+ fuse_put_request(fc, req);
+}
+
+static void fuse_file_put(struct fuse_file *ff)
+{
+ if (atomic_dec_and_test(&ff->count)) {
+ struct fuse_req *req = ff->reserved_req;
+ struct fuse_conn *fc = get_fuse_conn(req->dentry->d_inode);
+ req->end = fuse_release_end;
+ request_send_background(fc, req);
+ kfree(ff);
+ }
+}
+
void fuse_finish_open(struct inode *inode, struct file *file,
struct fuse_file *ff, struct fuse_open_out *outarg)
{
if (outarg->open_flags & FOPEN_DIRECT_IO)
file->f_op = &fuse_direct_io_file_operations;
if (!(outarg->open_flags & FOPEN_KEEP_CACHE))
- invalidate_mapping_pages(inode->i_mapping, 0, -1);
+ invalidate_inode_pages2(inode->i_mapping);
ff->fh = outarg->fh;
- file->private_data = ff;
+ file->private_data = fuse_file_get(ff);
}
int fuse_open_common(struct inode *inode, struct file *file, int isdir)
@@ -89,14 +118,6 @@ int fuse_open_common(struct inode *inode, struct file *file, int isdir)
if (err)
return err;
- /* If opening the root node, no lookup has been performed on
- it, so the attributes must be refreshed */
- if (get_node_id(inode) == FUSE_ROOT_ID) {
- err = fuse_do_getattr(inode);
- if (err)
- return err;
- }
-
ff = fuse_file_alloc();
if (!ff)
return -ENOMEM;
@@ -113,8 +134,7 @@ int fuse_open_common(struct inode *inode, struct file *file, int isdir)
return err;
}
-struct fuse_req *fuse_release_fill(struct fuse_file *ff, u64 nodeid, int flags,
- int opcode)
+void fuse_release_fill(struct fuse_file *ff, u64 nodeid, int flags, int opcode)
{
struct fuse_req *req = ff->reserved_req;
struct fuse_release_in *inarg = &req->misc.release_in;
@@ -126,9 +146,6 @@ struct fuse_req *fuse_release_fill(struct fuse_file *ff, u64 nodeid, int flags,
req->in.numargs = 1;
req->in.args[0].size = sizeof(struct fuse_release_in);
req->in.args[0].value = inarg;
- kfree(ff);
-
- return req;
}
int fuse_release_common(struct inode *inode, struct file *file, int isdir)
@@ -136,15 +153,23 @@ int fuse_release_common(struct inode *inode, struct file *file, int isdir)
struct fuse_file *ff = file->private_data;
if (ff) {
struct fuse_conn *fc = get_fuse_conn(inode);
- struct fuse_req *req;
- req = fuse_release_fill(ff, get_node_id(inode), file->f_flags,
- isdir ? FUSE_RELEASEDIR : FUSE_RELEASE);
+ fuse_release_fill(ff, get_node_id(inode), file->f_flags,
+ isdir ? FUSE_RELEASEDIR : FUSE_RELEASE);
/* Hold vfsmount and dentry until release is finished */
- req->vfsmount = mntget(file->f_path.mnt);
- req->dentry = dget(file->f_path.dentry);
- request_send_background(fc, req);
+ ff->reserved_req->vfsmount = mntget(file->f_path.mnt);
+ ff->reserved_req->dentry = dget(file->f_path.dentry);
+
+ spin_lock(&fc->lock);
+ list_del(&ff->write_entry);
+ spin_unlock(&fc->lock);
+ /*
+ * Normally this will send the RELEASE request,
+ * however if some asynchronous READ or WRITE requests
+ * are outstanding, the sending will be delayed
+ */
+ fuse_file_put(ff);
}
/* Return value is ignored by VFS */
@@ -165,7 +190,7 @@ static int fuse_release(struct inode *inode, struct file *file)
* Scramble the ID space with XTEA, so that the value of the files_struct
* pointer is not exposed to userspace.
*/
-static u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id)
+u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id)
{
u32 *k = fc->scramble_key;
u64 v = (unsigned long) id;
@@ -264,10 +289,9 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync)
return fuse_fsync_common(file, de, datasync, 0);
}
-void fuse_read_fill(struct fuse_req *req, struct file *file,
+void fuse_read_fill(struct fuse_req *req, struct fuse_file *ff,
struct inode *inode, loff_t pos, size_t count, int opcode)
{
- struct fuse_file *ff = file->private_data;
struct fuse_read_in *inarg = &req->misc.read_in;
inarg->fh = ff->fh;
@@ -285,10 +309,19 @@ void fuse_read_fill(struct fuse_req *req, struct file *file,
}
static size_t fuse_send_read(struct fuse_req *req, struct file *file,
- struct inode *inode, loff_t pos, size_t count)
+ struct inode *inode, loff_t pos, size_t count,
+ fl_owner_t owner)
{
struct fuse_conn *fc = get_fuse_conn(inode);
- fuse_read_fill(req, file, inode, pos, count, FUSE_READ);
+ struct fuse_file *ff = file->private_data;
+
+ fuse_read_fill(req, ff, inode, pos, count, FUSE_READ);
+ if (owner != NULL) {
+ struct fuse_read_in *inarg = &req->misc.read_in;
+
+ inarg->read_flags |= FUSE_READ_LOCKOWNER;
+ inarg->lock_owner = fuse_lock_owner_id(fc, owner);
+ }
request_send(fc, req);
return req->out.args[0].size;
}
@@ -312,7 +345,8 @@ static int fuse_readpage(struct file *file, struct page *page)
req->out.page_zeroing = 1;
req->num_pages = 1;
req->pages[0] = page;
- fuse_send_read(req, file, inode, page_offset(page), PAGE_CACHE_SIZE);
+ fuse_send_read(req, file, inode, page_offset(page), PAGE_CACHE_SIZE,
+ NULL);
err = req->out.h.error;
fuse_put_request(fc, req);
if (!err)
@@ -337,20 +371,21 @@ static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_req *req)
SetPageError(page);
unlock_page(page);
}
+ if (req->ff)
+ fuse_file_put(req->ff);
fuse_put_request(fc, req);
}
-static void fuse_send_readpages(struct fuse_req *req, struct file *file,
+static void fuse_send_readpages(struct fuse_req *req, struct fuse_file *ff,
struct inode *inode)
{
struct fuse_conn *fc = get_fuse_conn(inode);
loff_t pos = page_offset(req->pages[0]);
size_t count = req->num_pages << PAGE_CACHE_SHIFT;
req->out.page_zeroing = 1;
- fuse_read_fill(req, file, inode, pos, count, FUSE_READ);
+ fuse_read_fill(req, ff, inode, pos, count, FUSE_READ);
if (fc->async_read) {
- get_file(file);
- req->file = file;
+ req->ff = fuse_file_get(ff);
req->end = fuse_readpages_end;
request_send_background(fc, req);
} else {
@@ -359,15 +394,15 @@ static void fuse_send_readpages(struct fuse_req *req, struct file *file,
}
}
-struct fuse_readpages_data {
+struct fuse_fill_data {
struct fuse_req *req;
- struct file *file;
+ struct fuse_file *ff;
struct inode *inode;
};
static int fuse_readpages_fill(void *_data, struct page *page)
{
- struct fuse_readpages_data *data = _data;
+ struct fuse_fill_data *data = _data;
struct fuse_req *req = data->req;
struct inode *inode = data->inode;
struct fuse_conn *fc = get_fuse_conn(inode);
@@ -376,7 +411,7 @@ static int fuse_readpages_fill(void *_data, struct page *page)
(req->num_pages == FUSE_MAX_PAGES_PER_REQ ||
(req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read ||
req->pages[req->num_pages - 1]->index + 1 != page->index)) {
- fuse_send_readpages(req, data->file, inode);
+ fuse_send_readpages(req, data->ff, inode);
data->req = req = fuse_get_req(fc);
if (IS_ERR(req)) {
unlock_page(page);
@@ -393,14 +428,14 @@ static int fuse_readpages(struct file *file, struct address_space *mapping,
{
struct inode *inode = mapping->host;
struct fuse_conn *fc = get_fuse_conn(inode);
- struct fuse_readpages_data data;
+ struct fuse_fill_data data;
int err;
err = -EIO;
if (is_bad_inode(inode))
goto out;
- data.file = file;
+ data.ff = file->private_data;
data.inode = inode;
data.req = fuse_get_req(fc);
err = PTR_ERR(data.req);
@@ -410,7 +445,7 @@ static int fuse_readpages(struct file *file, struct address_space *mapping,
err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data);
if (!err) {
if (data.req->num_pages)
- fuse_send_readpages(data.req, file, inode);
+ fuse_send_readpages(data.req, data.ff, inode);
else
fuse_put_request(fc, data.req);
}
@@ -418,48 +453,69 @@ out:
return err;
}
-static size_t fuse_send_write(struct fuse_req *req, struct file *file,
- struct inode *inode, loff_t pos, size_t count)
+static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff,
+ struct inode *inode, loff_t pos, size_t count,
+ int writepage)
{
struct fuse_conn *fc = get_fuse_conn(inode);
- struct fuse_file *ff = file->private_data;
- struct fuse_write_in inarg;
- struct fuse_write_out outarg;
+ struct fuse_write_in *inarg = &req->misc.write.in;
+ struct fuse_write_out *outarg = &req->misc.write.out;
- memset(&inarg, 0, sizeof(struct fuse_write_in));
- inarg.fh = ff->fh;
- inarg.offset = pos;
- inarg.size = count;
+ memset(inarg, 0, sizeof(struct fuse_write_in));
+ inarg->fh = ff->fh;
+ inarg->offset = pos;
+ inarg->size = count;
+ inarg->write_flags = writepage ? FUSE_WRITE_CACHE : 0;
req->in.h.opcode = FUSE_WRITE;
req->in.h.nodeid = get_node_id(inode);
req->in.argpages = 1;
req->in.numargs = 2;
- req->in.args[0].size = sizeof(struct fuse_write_in);
- req->in.args[0].value = &inarg;
+ if (fc->minor < 9)
+ req->in.args[0].size = FUSE_COMPAT_WRITE_IN_SIZE;
+ else
+ req->in.args[0].size = sizeof(struct fuse_write_in);
+ req->in.args[0].value = inarg;
req->in.args[1].size = count;
req->out.numargs = 1;
req->out.args[0].size = sizeof(struct fuse_write_out);
- req->out.args[0].value = &outarg;
+ req->out.args[0].value = outarg;
+}
+
+static size_t fuse_send_write(struct fuse_req *req, struct file *file,
+ struct inode *inode, loff_t pos, size_t count,
+ fl_owner_t owner)
+{
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ fuse_write_fill(req, file->private_data, inode, pos, count, 0);
+ if (owner != NULL) {
+ struct fuse_write_in *inarg = &req->misc.write.in;
+ inarg->write_flags |= FUSE_WRITE_LOCKOWNER;
+ inarg->lock_owner = fuse_lock_owner_id(fc, owner);
+ }
request_send(fc, req);
- return outarg.size;
+ return req->misc.write.out.size;
}
-static int fuse_prepare_write(struct file *file, struct page *page,
- unsigned offset, unsigned to)
+static int fuse_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
{
- /* No op */
+ pgoff_t index = pos >> PAGE_CACHE_SHIFT;
+
+ *pagep = __grab_cache_page(mapping, index);
+ if (!*pagep)
+ return -ENOMEM;
return 0;
}
-static int fuse_commit_write(struct file *file, struct page *page,
- unsigned offset, unsigned to)
+static int fuse_buffered_write(struct file *file, struct inode *inode,
+ loff_t pos, unsigned count, struct page *page)
{
int err;
size_t nres;
- unsigned count = to - offset;
- struct inode *inode = page->mapping->host;
struct fuse_conn *fc = get_fuse_conn(inode);
- loff_t pos = page_offset(page) + offset;
+ struct fuse_inode *fi = get_fuse_inode(inode);
+ unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
struct fuse_req *req;
if (is_bad_inode(inode))
@@ -472,23 +528,39 @@ static int fuse_commit_write(struct file *file, struct page *page,
req->num_pages = 1;
req->pages[0] = page;
req->page_offset = offset;
- nres = fuse_send_write(req, file, inode, pos, count);
+ nres = fuse_send_write(req, file, inode, pos, count, NULL);
err = req->out.h.error;
fuse_put_request(fc, req);
- if (!err && nres != count)
+ if (!err && !nres)
err = -EIO;
if (!err) {
- pos += count;
+ pos += nres;
spin_lock(&fc->lock);
+ fi->attr_version = ++fc->attr_version;
if (pos > inode->i_size)
i_size_write(inode, pos);
spin_unlock(&fc->lock);
- if (offset == 0 && to == PAGE_CACHE_SIZE)
+ if (count == PAGE_CACHE_SIZE)
SetPageUptodate(page);
}
fuse_invalidate_attr(inode);
- return err;
+ return err ? err : nres;
+}
+
+static int fuse_write_end(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata)
+{
+ struct inode *inode = mapping->host;
+ int res = 0;
+
+ if (copied)
+ res = fuse_buffered_write(file, inode, pos, copied, page);
+
+ unlock_page(page);
+ page_cache_release(page);
+ return res;
}
static void fuse_release_user_pages(struct fuse_req *req, int write)
@@ -557,9 +629,11 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf,
nbytes = (req->num_pages << PAGE_SHIFT) - req->page_offset;
nbytes = min(count, nbytes);
if (write)
- nres = fuse_send_write(req, file, inode, pos, nbytes);
+ nres = fuse_send_write(req, file, inode, pos, nbytes,
+ current->files);
else
- nres = fuse_send_read(req, file, inode, pos, nbytes);
+ nres = fuse_send_read(req, file, inode, pos, nbytes,
+ current->files);
fuse_release_user_pages(req, !write);
if (req->out.h.error) {
if (!res)
@@ -661,7 +735,8 @@ static int convert_fuse_file_lock(const struct fuse_file_lock *ffl,
}
static void fuse_lk_fill(struct fuse_req *req, struct file *file,
- const struct file_lock *fl, int opcode, pid_t pid)
+ const struct file_lock *fl, int opcode, pid_t pid,
+ int flock)
{
struct inode *inode = file->f_path.dentry->d_inode;
struct fuse_conn *fc = get_fuse_conn(inode);
@@ -674,6 +749,8 @@ static void fuse_lk_fill(struct fuse_req *req, struct file *file,
arg->lk.end = fl->fl_end;
arg->lk.type = fl->fl_type;
arg->lk.pid = pid;
+ if (flock)
+ arg->lk_flags |= FUSE_LK_FLOCK;
req->in.h.opcode = opcode;
req->in.h.nodeid = get_node_id(inode);
req->in.numargs = 1;
@@ -693,7 +770,7 @@ static int fuse_getlk(struct file *file, struct file_lock *fl)
if (IS_ERR(req))
return PTR_ERR(req);
- fuse_lk_fill(req, file, fl, FUSE_GETLK, 0);
+ fuse_lk_fill(req, file, fl, FUSE_GETLK, 0, 0);
req->out.numargs = 1;
req->out.args[0].size = sizeof(outarg);
req->out.args[0].value = &outarg;
@@ -706,7 +783,7 @@ static int fuse_getlk(struct file *file, struct file_lock *fl)
return err;
}
-static int fuse_setlk(struct file *file, struct file_lock *fl)
+static int fuse_setlk(struct file *file, struct file_lock *fl, int flock)
{
struct inode *inode = file->f_path.dentry->d_inode;
struct fuse_conn *fc = get_fuse_conn(inode);
@@ -723,7 +800,7 @@ static int fuse_setlk(struct file *file, struct file_lock *fl)
if (IS_ERR(req))
return PTR_ERR(req);
- fuse_lk_fill(req, file, fl, opcode, pid);
+ fuse_lk_fill(req, file, fl, opcode, pid, flock);
request_send(fc, req);
err = req->out.h.error;
/* locking is restartable */
@@ -749,8 +826,25 @@ static int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl)
if (fc->no_lock)
err = posix_lock_file_wait(file, fl);
else
- err = fuse_setlk(file, fl);
+ err = fuse_setlk(file, fl, 0);
+ }
+ return err;
+}
+
+static int fuse_file_flock(struct file *file, int cmd, struct file_lock *fl)
+{
+ struct inode *inode = file->f_path.dentry->d_inode;
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ int err;
+
+ if (fc->no_lock) {
+ err = flock_lock_file_wait(file, fl);
+ } else {
+ /* emulate flock with POSIX locks */
+ fl->fl_owner = (fl_owner_t) file;
+ err = fuse_setlk(file, fl, 1);
}
+
return err;
}
@@ -802,6 +896,7 @@ static const struct file_operations fuse_file_operations = {
.release = fuse_release,
.fsync = fuse_fsync,
.lock = fuse_file_lock,
+ .flock = fuse_file_flock,
.splice_read = generic_file_splice_read,
};
@@ -814,13 +909,14 @@ static const struct file_operations fuse_direct_io_file_operations = {
.release = fuse_release,
.fsync = fuse_fsync,
.lock = fuse_file_lock,
+ .flock = fuse_file_flock,
/* no mmap and splice_read */
};
static const struct address_space_operations fuse_file_aops = {
.readpage = fuse_readpage,
- .prepare_write = fuse_prepare_write,
- .commit_write = fuse_commit_write,
+ .write_begin = fuse_write_begin,
+ .write_end = fuse_write_end,
.readpages = fuse_readpages,
.set_page_dirty = fuse_set_page_dirty,
.bmap = fuse_bmap,
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 68ae87cbafab..6c5461de1a5f 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -20,7 +20,10 @@
#define FUSE_MAX_PAGES_PER_REQ 32
/** Maximum number of outstanding background requests */
-#define FUSE_MAX_BACKGROUND 10
+#define FUSE_MAX_BACKGROUND 12
+
+/** Congestion starts at 75% of maximum */
+#define FUSE_CONGESTION_THRESHOLD (FUSE_MAX_BACKGROUND * 75 / 100)
/** It could be as large as PATH_MAX, but would that have any uses? */
#define FUSE_NAME_MAX 1024
@@ -60,6 +63,16 @@ struct fuse_inode {
/** Time in jiffies until the file attributes are valid */
u64 i_time;
+
+ /** The sticky bit in inode->i_mode may have been removed, so
+ preserve the original mode */
+ mode_t orig_i_mode;
+
+ /** Version of last attribute change */
+ u64 attr_version;
+
+ /** Files usable in writepage. Protected by fc->lock */
+ struct list_head write_files;
};
/** FUSE specific file data */
@@ -69,6 +82,12 @@ struct fuse_file {
/** File handle used by userspace */
u64 fh;
+
+ /** Refcount */
+ atomic_t count;
+
+ /** Entry on inode's write_files list */
+ struct list_head write_entry;
};
/** One input argument of a request */
@@ -200,6 +219,10 @@ struct fuse_req {
struct fuse_init_in init_in;
struct fuse_init_out init_out;
struct fuse_read_in read_in;
+ struct {
+ struct fuse_write_in in;
+ struct fuse_write_out out;
+ } write;
struct fuse_lk_in lk_in;
} misc;
@@ -213,7 +236,7 @@ struct fuse_req {
unsigned page_offset;
/** File used in the request (or NULL) */
- struct file *file;
+ struct fuse_file *ff;
/** vfsmount used in release */
struct vfsmount *vfsmount;
@@ -286,6 +309,9 @@ struct fuse_conn {
/** waitq for blocked connection */
wait_queue_head_t blocked_waitq;
+ /** waitq for reserved requests */
+ wait_queue_head_t reserved_req_waitq;
+
/** The next unique request id */
u64 reqctr;
@@ -304,6 +330,9 @@ struct fuse_conn {
/** Do readpages asynchronously? Only set in INIT */
unsigned async_read : 1;
+ /** Do not send separate SETATTR request before open(O_TRUNC) */
+ unsigned atomic_o_trunc : 1;
+
/*
* The following bitfields are only for optimization purposes
* and hence races in setting them will not cause malfunction
@@ -374,6 +403,9 @@ struct fuse_conn {
/** Reserved request for the DESTROY message */
struct fuse_req *destroy_req;
+
+ /** Version counter for attribute changes */
+ u64 attr_version;
};
static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb)
@@ -403,7 +435,8 @@ extern const struct file_operations fuse_dev_operations;
* Get a filled in inode
*/
struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
- int generation, struct fuse_attr *attr);
+ int generation, struct fuse_attr *attr,
+ u64 attr_valid, u64 attr_version);
/**
* Send FORGET command
@@ -414,7 +447,7 @@ void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req,
/**
* Initialize READ or READDIR request
*/
-void fuse_read_fill(struct fuse_req *req, struct file *file,
+void fuse_read_fill(struct fuse_req *req, struct fuse_file *ff,
struct inode *inode, loff_t pos, size_t count, int opcode);
/**
@@ -427,9 +460,9 @@ void fuse_file_free(struct fuse_file *ff);
void fuse_finish_open(struct inode *inode, struct file *file,
struct fuse_file *ff, struct fuse_open_out *outarg);
-/** */
-struct fuse_req *fuse_release_fill(struct fuse_file *ff, u64 nodeid, int flags,
- int opcode);
+/** Fill in ff->reserved_req with a RELEASE request */
+void fuse_release_fill(struct fuse_file *ff, u64 nodeid, int flags, int opcode);
+
/**
* Send RELEASE or RELEASEDIR request
*/
@@ -464,7 +497,8 @@ void fuse_init_symlink(struct inode *inode);
/**
* Change attributes of an inode
*/
-void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr);
+void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
+ u64 attr_valid, u64 attr_version);
/**
* Initialize the client device
@@ -524,11 +558,6 @@ void request_send_background(struct fuse_conn *fc, struct fuse_req *req);
void fuse_abort_conn(struct fuse_conn *fc);
/**
- * Get the attributes of a file
- */
-int fuse_do_getattr(struct inode *inode);
-
-/**
* Invalidate inode attributes
*/
void fuse_invalidate_attr(struct inode *inode);
@@ -557,3 +586,10 @@ void fuse_ctl_remove_conn(struct fuse_conn *fc);
* Is file type valid?
*/
int fuse_valid_type(int m);
+
+/**
+ * Is task allowed to perform filesystem operation?
+ */
+int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task);
+
+u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id);
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 5448f625ab56..9a68d6970845 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -56,6 +56,7 @@ static struct inode *fuse_alloc_inode(struct super_block *sb)
fi->i_time = 0;
fi->nodeid = 0;
fi->nlookup = 0;
+ INIT_LIST_HEAD(&fi->write_files);
fi->forget_req = fuse_request_alloc();
if (!fi->forget_req) {
kmem_cache_free(fuse_inode_cachep, inode);
@@ -68,6 +69,7 @@ static struct inode *fuse_alloc_inode(struct super_block *sb)
static void fuse_destroy_inode(struct inode *inode)
{
struct fuse_inode *fi = get_fuse_inode(inode);
+ BUG_ON(!list_empty(&fi->write_files));
if (fi->forget_req)
fuse_request_free(fi->forget_req);
kmem_cache_free(fuse_inode_cachep, inode);
@@ -109,20 +111,35 @@ static int fuse_remount_fs(struct super_block *sb, int *flags, char *data)
return 0;
}
-void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr)
+static void fuse_truncate(struct address_space *mapping, loff_t offset)
+{
+ /* See vmtruncate() */
+ unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
+ truncate_inode_pages(mapping, offset);
+ unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
+}
+
+
+void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
+ u64 attr_valid, u64 attr_version)
{
struct fuse_conn *fc = get_fuse_conn(inode);
- if (S_ISREG(inode->i_mode) && i_size_read(inode) != attr->size)
- invalidate_mapping_pages(inode->i_mapping, 0, -1);
+ struct fuse_inode *fi = get_fuse_inode(inode);
+ loff_t oldsize;
+
+ spin_lock(&fc->lock);
+ if (attr_version != 0 && fi->attr_version > attr_version) {
+ spin_unlock(&fc->lock);
+ return;
+ }
+ fi->attr_version = ++fc->attr_version;
+ fi->i_time = attr_valid;
inode->i_ino = attr->ino;
- inode->i_mode = (inode->i_mode & S_IFMT) + (attr->mode & 07777);
+ inode->i_mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
inode->i_nlink = attr->nlink;
inode->i_uid = attr->uid;
inode->i_gid = attr->gid;
- spin_lock(&fc->lock);
- i_size_write(inode, attr->size);
- spin_unlock(&fc->lock);
inode->i_blocks = attr->blocks;
inode->i_atime.tv_sec = attr->atime;
inode->i_atime.tv_nsec = attr->atimensec;
@@ -130,6 +147,30 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr)
inode->i_mtime.tv_nsec = attr->mtimensec;
inode->i_ctime.tv_sec = attr->ctime;
inode->i_ctime.tv_nsec = attr->ctimensec;
+
+ if (attr->blksize != 0)
+ inode->i_blkbits = ilog2(attr->blksize);
+ else
+ inode->i_blkbits = inode->i_sb->s_blocksize_bits;
+
+ /*
+ * Don't set the sticky bit in i_mode, unless we want the VFS
+ * to check permissions. This prevents failures due to the
+ * check in may_delete().
+ */
+ fi->orig_i_mode = inode->i_mode;
+ if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
+ inode->i_mode &= ~S_ISVTX;
+
+ oldsize = inode->i_size;
+ i_size_write(inode, attr->size);
+ spin_unlock(&fc->lock);
+
+ if (S_ISREG(inode->i_mode) && oldsize != attr->size) {
+ if (attr->size < oldsize)
+ fuse_truncate(inode->i_mapping, attr->size);
+ invalidate_inode_pages2(inode->i_mapping);
+ }
}
static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr)
@@ -169,7 +210,8 @@ static int fuse_inode_set(struct inode *inode, void *_nodeidp)
}
struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
- int generation, struct fuse_attr *attr)
+ int generation, struct fuse_attr *attr,
+ u64 attr_valid, u64 attr_version)
{
struct inode *inode;
struct fuse_inode *fi;
@@ -197,7 +239,8 @@ struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
spin_lock(&fc->lock);
fi->nlookup ++;
spin_unlock(&fc->lock);
- fuse_change_attributes(inode, attr);
+ fuse_change_attributes(inode, attr, attr_valid, attr_version);
+
return inode;
}
@@ -232,6 +275,7 @@ static void fuse_put_super(struct super_block *sb)
kill_fasync(&fc->fasync, SIGIO, POLL_IN);
wake_up_all(&fc->waitq);
wake_up_all(&fc->blocked_waitq);
+ wake_up_all(&fc->reserved_req_waitq);
mutex_lock(&fuse_mutex);
list_del(&fc->entry);
fuse_ctl_remove_conn(fc);
@@ -261,6 +305,11 @@ static int fuse_statfs(struct dentry *dentry, struct kstatfs *buf)
struct fuse_statfs_out outarg;
int err;
+ if (!fuse_allow_task(fc, current)) {
+ buf->f_type = FUSE_SUPER_MAGIC;
+ return 0;
+ }
+
req = fuse_get_req(fc);
if (IS_ERR(req))
return PTR_ERR(req);
@@ -401,6 +450,7 @@ static int fuse_show_options(struct seq_file *m, struct vfsmount *mnt)
static struct fuse_conn *new_conn(void)
{
struct fuse_conn *fc;
+ int err;
fc = kzalloc(sizeof(*fc), GFP_KERNEL);
if (fc) {
@@ -409,6 +459,7 @@ static struct fuse_conn *new_conn(void)
atomic_set(&fc->count, 1);
init_waitqueue_head(&fc->waitq);
init_waitqueue_head(&fc->blocked_waitq);
+ init_waitqueue_head(&fc->reserved_req_waitq);
INIT_LIST_HEAD(&fc->pending);
INIT_LIST_HEAD(&fc->processing);
INIT_LIST_HEAD(&fc->io);
@@ -416,10 +467,18 @@ static struct fuse_conn *new_conn(void)
atomic_set(&fc->num_waiting, 0);
fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
fc->bdi.unplug_io_fn = default_unplug_io_fn;
+ err = bdi_init(&fc->bdi);
+ if (err) {
+ kfree(fc);
+ fc = NULL;
+ goto out;
+ }
fc->reqctr = 0;
fc->blocked = 1;
+ fc->attr_version = 1;
get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key));
}
+out:
return fc;
}
@@ -429,6 +488,7 @@ void fuse_conn_put(struct fuse_conn *fc)
if (fc->destroy_req)
fuse_request_free(fc->destroy_req);
mutex_destroy(&fc->inst_mutex);
+ bdi_destroy(&fc->bdi);
kfree(fc);
}
}
@@ -446,7 +506,8 @@ static struct inode *get_root_inode(struct super_block *sb, unsigned mode)
attr.mode = mode;
attr.ino = FUSE_ROOT_ID;
- return fuse_iget(sb, 1, 0, &attr);
+ attr.nlink = 1;
+ return fuse_iget(sb, 1, 0, &attr, 0, 0);
}
static const struct super_operations fuse_super_operations = {
@@ -477,6 +538,8 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
fc->async_read = 1;
if (!(arg->flags & FUSE_POSIX_LOCKS))
fc->no_lock = 1;
+ if (arg->flags & FUSE_ATOMIC_O_TRUNC)
+ fc->atomic_o_trunc = 1;
} else {
ra_pages = fc->max_read / PAGE_CACHE_SIZE;
fc->no_lock = 1;
@@ -499,7 +562,8 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req)
arg->major = FUSE_KERNEL_VERSION;
arg->minor = FUSE_KERNEL_MINOR_VERSION;
arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE;
- arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS;
+ arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_FILE_OPS |
+ FUSE_ATOMIC_O_TRUNC;
req->in.h.opcode = FUSE_INIT;
req->in.numargs = 1;
req->in.args[0].size = sizeof(*arg);
@@ -683,8 +747,7 @@ static inline void unregister_fuseblk(void)
static decl_subsys(fuse, NULL, NULL);
static decl_subsys(connections, NULL, NULL);
-static void fuse_inode_init_once(void *foo, struct kmem_cache *cachep,
- unsigned long flags)
+static void fuse_inode_init_once(struct kmem_cache *cachep, void *foo)
{
struct inode * inode = foo;
diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c
index 79c91fd8381b..7ecfe0d3a491 100644
--- a/fs/gfs2/main.c
+++ b/fs/gfs2/main.c
@@ -24,7 +24,7 @@
#include "util.h"
#include "glock.h"
-static void gfs2_init_inode_once(void *foo, struct kmem_cache *cachep, unsigned long flags)
+static void gfs2_init_inode_once(struct kmem_cache *cachep, void *foo)
{
struct gfs2_inode *ip = foo;
@@ -34,7 +34,7 @@ static void gfs2_init_inode_once(void *foo, struct kmem_cache *cachep, unsigned
memset(ip->i_cache, 0, sizeof(ip->i_cache));
}
-static void gfs2_init_glock_once(void *foo, struct kmem_cache *cachep, unsigned long flags)
+static void gfs2_init_glock_once(struct kmem_cache *cachep, void *foo)
{
struct gfs2_glock *gl = foo;
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c
index 873a511ef2be..9679f8b9870d 100644
--- a/fs/gfs2/ops_address.c
+++ b/fs/gfs2/ops_address.c
@@ -17,6 +17,7 @@
#include <linux/mpage.h>
#include <linux/fs.h>
#include <linux/writeback.h>
+#include <linux/swap.h>
#include <linux/gfs2_ondisk.h>
#include <linux/lm_interface.h>
@@ -349,45 +350,49 @@ out_unlock:
}
/**
- * gfs2_prepare_write - Prepare to write a page to a file
+ * gfs2_write_begin - Begin to write to a file
* @file: The file to write to
- * @page: The page which is to be prepared for writing
- * @from: From (byte range within page)
- * @to: To (byte range within page)
+ * @mapping: The mapping in which to write
+ * @pos: The file offset at which to start writing
+ * @len: Length of the write
+ * @flags: Various flags
+ * @pagep: Pointer to return the page
+ * @fsdata: Pointer to return fs data (unused by GFS2)
*
* Returns: errno
*/
-static int gfs2_prepare_write(struct file *file, struct page *page,
- unsigned from, unsigned to)
+static int gfs2_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
{
- struct gfs2_inode *ip = GFS2_I(page->mapping->host);
- struct gfs2_sbd *sdp = GFS2_SB(page->mapping->host);
+ struct gfs2_inode *ip = GFS2_I(mapping->host);
+ struct gfs2_sbd *sdp = GFS2_SB(mapping->host);
unsigned int data_blocks, ind_blocks, rblocks;
int alloc_required;
int error = 0;
- loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + from;
- loff_t end = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
struct gfs2_alloc *al;
- unsigned int write_len = to - from;
+ pgoff_t index = pos >> PAGE_CACHE_SHIFT;
+ unsigned from = pos & (PAGE_CACHE_SIZE - 1);
+ unsigned to = from + len;
+ struct page *page;
-
- gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_ATIME|LM_FLAG_TRY_1CB, &ip->i_gh);
+ gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_ATIME, &ip->i_gh);
error = gfs2_glock_nq_atime(&ip->i_gh);
- if (unlikely(error)) {
- if (error == GLR_TRYFAILED) {
- unlock_page(page);
- error = AOP_TRUNCATED_PAGE;
- yield();
- }
+ if (unlikely(error))
goto out_uninit;
- }
- gfs2_write_calc_reserv(ip, write_len, &data_blocks, &ind_blocks);
+ error = -ENOMEM;
+ page = __grab_cache_page(mapping, index);
+ *pagep = page;
+ if (!page)
+ goto out_unlock;
+
+ gfs2_write_calc_reserv(ip, len, &data_blocks, &ind_blocks);
- error = gfs2_write_alloc_required(ip, pos, write_len, &alloc_required);
+ error = gfs2_write_alloc_required(ip, pos, len, &alloc_required);
if (error)
- goto out_unlock;
+ goto out_putpage;
ip->i_alloc.al_requested = 0;
@@ -420,7 +425,7 @@ static int gfs2_prepare_write(struct file *file, struct page *page,
goto out_trans_fail;
if (gfs2_is_stuffed(ip)) {
- if (end > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) {
+ if (pos + len > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) {
error = gfs2_unstuff_dinode(ip, page);
if (error == 0)
goto prepare_write;
@@ -443,6 +448,10 @@ out_qunlock:
out_alloc_put:
gfs2_alloc_put(ip);
}
+out_putpage:
+ page_cache_release(page);
+ if (pos + len > ip->i_inode.i_size)
+ vmtruncate(&ip->i_inode, ip->i_inode.i_size);
out_unlock:
gfs2_glock_dq_m(1, &ip->i_gh);
out_uninit:
@@ -478,65 +487,117 @@ static void adjust_fs_space(struct inode *inode)
}
/**
- * gfs2_commit_write - Commit write to a file
+ * gfs2_stuffed_write_end - Write end for stuffed files
+ * @inode: The inode
+ * @dibh: The buffer_head containing the on-disk inode
+ * @pos: The file position
+ * @len: The length of the write
+ * @copied: How much was actually copied by the VFS
+ * @page: The page
+ *
+ * This copies the data from the page into the inode block after
+ * the inode data structure itself.
+ *
+ * Returns: errno
+ */
+static int gfs2_stuffed_write_end(struct inode *inode, struct buffer_head *dibh,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page)
+{
+ struct gfs2_inode *ip = GFS2_I(inode);
+ struct gfs2_sbd *sdp = GFS2_SB(inode);
+ u64 to = pos + copied;
+ void *kaddr;
+ unsigned char *buf = dibh->b_data + sizeof(struct gfs2_dinode);
+ struct gfs2_dinode *di = (struct gfs2_dinode *)dibh->b_data;
+
+ BUG_ON((pos + len) > (dibh->b_size - sizeof(struct gfs2_dinode)));
+ kaddr = kmap_atomic(page, KM_USER0);
+ memcpy(buf + pos, kaddr + pos, copied);
+ memset(kaddr + pos + copied, 0, len - copied);
+ flush_dcache_page(page);
+ kunmap_atomic(kaddr, KM_USER0);
+
+ if (!PageUptodate(page))
+ SetPageUptodate(page);
+ unlock_page(page);
+ page_cache_release(page);
+
+ if (inode->i_size < to) {
+ i_size_write(inode, to);
+ ip->i_di.di_size = inode->i_size;
+ di->di_size = cpu_to_be64(inode->i_size);
+ mark_inode_dirty(inode);
+ }
+
+ if (inode == sdp->sd_rindex)
+ adjust_fs_space(inode);
+
+ brelse(dibh);
+ gfs2_trans_end(sdp);
+ gfs2_glock_dq(&ip->i_gh);
+ gfs2_holder_uninit(&ip->i_gh);
+ return copied;
+}
+
+/**
+ * gfs2_write_end
* @file: The file to write to
- * @page: The page containing the data
- * @from: From (byte range within page)
- * @to: To (byte range within page)
+ * @mapping: The address space to write to
+ * @pos: The file position
+ * @len: The length of the data
+ * @copied:
+ * @page: The page that has been written
+ * @fsdata: The fsdata (unused in GFS2)
+ *
+ * The main write_end function for GFS2. We have a separate one for
+ * stuffed files as they are slightly different, otherwise we just
+ * put our locking around the VFS provided functions.
*
* Returns: errno
*/
-static int gfs2_commit_write(struct file *file, struct page *page,
- unsigned from, unsigned to)
+static int gfs2_write_end(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata)
{
struct inode *inode = page->mapping->host;
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_sbd *sdp = GFS2_SB(inode);
- int error = -EOPNOTSUPP;
struct buffer_head *dibh;
struct gfs2_alloc *al = &ip->i_alloc;
struct gfs2_dinode *di;
+ unsigned int from = pos & (PAGE_CACHE_SIZE - 1);
+ unsigned int to = from + len;
+ int ret;
- if (gfs2_assert_withdraw(sdp, gfs2_glock_is_locked_by_me(ip->i_gl)))
- goto fail_nounlock;
+ BUG_ON(gfs2_glock_is_locked_by_me(ip->i_gl) == 0);
- error = gfs2_meta_inode_buffer(ip, &dibh);
- if (error)
- goto fail_endtrans;
+ ret = gfs2_meta_inode_buffer(ip, &dibh);
+ if (unlikely(ret)) {
+ unlock_page(page);
+ page_cache_release(page);
+ goto failed;
+ }
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
- di = (struct gfs2_dinode *)dibh->b_data;
-
- if (gfs2_is_stuffed(ip)) {
- u64 file_size;
- void *kaddr;
- file_size = ((u64)page->index << PAGE_CACHE_SHIFT) + to;
+ if (gfs2_is_stuffed(ip))
+ return gfs2_stuffed_write_end(inode, dibh, pos, len, copied, page);
- kaddr = kmap_atomic(page, KM_USER0);
- memcpy(dibh->b_data + sizeof(struct gfs2_dinode) + from,
- kaddr + from, to - from);
- kunmap_atomic(kaddr, KM_USER0);
+ if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip))
+ gfs2_page_add_databufs(ip, page, from, to);
- SetPageUptodate(page);
+ ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
- if (inode->i_size < file_size) {
- i_size_write(inode, file_size);
+ if (likely(ret >= 0)) {
+ copied = ret;
+ if ((pos + copied) > inode->i_size) {
+ di = (struct gfs2_dinode *)dibh->b_data;
+ ip->i_di.di_size = inode->i_size;
+ di->di_size = cpu_to_be64(inode->i_size);
mark_inode_dirty(inode);
}
- } else {
- if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED ||
- gfs2_is_jdata(ip))
- gfs2_page_add_databufs(ip, page, from, to);
- error = generic_commit_write(file, page, from, to);
- if (error)
- goto fail;
- }
-
- if (ip->i_di.di_size < inode->i_size) {
- ip->i_di.di_size = inode->i_size;
- di->di_size = cpu_to_be64(inode->i_size);
}
if (inode == sdp->sd_rindex)
@@ -544,33 +605,15 @@ static int gfs2_commit_write(struct file *file, struct page *page,
brelse(dibh);
gfs2_trans_end(sdp);
+failed:
if (al->al_requested) {
gfs2_inplace_release(ip);
gfs2_quota_unlock(ip);
gfs2_alloc_put(ip);
}
- unlock_page(page);
- gfs2_glock_dq_m(1, &ip->i_gh);
- lock_page(page);
+ gfs2_glock_dq(&ip->i_gh);
gfs2_holder_uninit(&ip->i_gh);
- return 0;
-
-fail:
- brelse(dibh);
-fail_endtrans:
- gfs2_trans_end(sdp);
- if (al->al_requested) {
- gfs2_inplace_release(ip);
- gfs2_quota_unlock(ip);
- gfs2_alloc_put(ip);
- }
- unlock_page(page);
- gfs2_glock_dq_m(1, &ip->i_gh);
- lock_page(page);
- gfs2_holder_uninit(&ip->i_gh);
-fail_nounlock:
- ClearPageUptodate(page);
- return error;
+ return ret;
}
/**
@@ -799,8 +842,8 @@ const struct address_space_operations gfs2_file_aops = {
.readpage = gfs2_readpage,
.readpages = gfs2_readpages,
.sync_page = block_sync_page,
- .prepare_write = gfs2_prepare_write,
- .commit_write = gfs2_commit_write,
+ .write_begin = gfs2_write_begin,
+ .write_end = gfs2_write_end,
.set_page_dirty = gfs2_set_page_dirty,
.bmap = gfs2_bmap,
.invalidatepage = gfs2_invalidatepage,
diff --git a/fs/gfs2/ops_export.c b/fs/gfs2/ops_export.c
index e2d1347796a9..b9da62348a87 100644
--- a/fs/gfs2/ops_export.c
+++ b/fs/gfs2/ops_export.c
@@ -31,40 +31,6 @@
#define GFS2_LARGE_FH_SIZE 8
#define GFS2_OLD_FH_SIZE 10
-static struct dentry *gfs2_decode_fh(struct super_block *sb,
- __u32 *p,
- int fh_len,
- int fh_type,
- int (*acceptable)(void *context,
- struct dentry *dentry),
- void *context)
-{
- __be32 *fh = (__force __be32 *)p;
- struct gfs2_inum_host inum, parent;
-
- memset(&parent, 0, sizeof(struct gfs2_inum));
-
- switch (fh_len) {
- case GFS2_LARGE_FH_SIZE:
- case GFS2_OLD_FH_SIZE:
- parent.no_formal_ino = ((u64)be32_to_cpu(fh[4])) << 32;
- parent.no_formal_ino |= be32_to_cpu(fh[5]);
- parent.no_addr = ((u64)be32_to_cpu(fh[6])) << 32;
- parent.no_addr |= be32_to_cpu(fh[7]);
- case GFS2_SMALL_FH_SIZE:
- inum.no_formal_ino = ((u64)be32_to_cpu(fh[0])) << 32;
- inum.no_formal_ino |= be32_to_cpu(fh[1]);
- inum.no_addr = ((u64)be32_to_cpu(fh[2])) << 32;
- inum.no_addr |= be32_to_cpu(fh[3]);
- break;
- default:
- return NULL;
- }
-
- return gfs2_export_ops.find_exported_dentry(sb, &inum, &parent,
- acceptable, context);
-}
-
static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len,
int connectable)
{
@@ -189,10 +155,10 @@ static struct dentry *gfs2_get_parent(struct dentry *child)
return dentry;
}
-static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_obj)
+static struct dentry *gfs2_get_dentry(struct super_block *sb,
+ struct gfs2_inum_host *inum)
{
struct gfs2_sbd *sdp = sb->s_fs_info;
- struct gfs2_inum_host *inum = inum_obj;
struct gfs2_holder i_gh, ri_gh, rgd_gh;
struct gfs2_rgrpd *rgd;
struct inode *inode;
@@ -289,11 +255,50 @@ fail:
return ERR_PTR(error);
}
-struct export_operations gfs2_export_ops = {
- .decode_fh = gfs2_decode_fh,
+static struct dentry *gfs2_fh_to_dentry(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type)
+{
+ struct gfs2_inum_host this;
+ __be32 *fh = (__force __be32 *)fid->raw;
+
+ switch (fh_type) {
+ case GFS2_SMALL_FH_SIZE:
+ case GFS2_LARGE_FH_SIZE:
+ case GFS2_OLD_FH_SIZE:
+ this.no_formal_ino = ((u64)be32_to_cpu(fh[0])) << 32;
+ this.no_formal_ino |= be32_to_cpu(fh[1]);
+ this.no_addr = ((u64)be32_to_cpu(fh[2])) << 32;
+ this.no_addr |= be32_to_cpu(fh[3]);
+ return gfs2_get_dentry(sb, &this);
+ default:
+ return NULL;
+ }
+}
+
+static struct dentry *gfs2_fh_to_parent(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type)
+{
+ struct gfs2_inum_host parent;
+ __be32 *fh = (__force __be32 *)fid->raw;
+
+ switch (fh_type) {
+ case GFS2_LARGE_FH_SIZE:
+ case GFS2_OLD_FH_SIZE:
+ parent.no_formal_ino = ((u64)be32_to_cpu(fh[4])) << 32;
+ parent.no_formal_ino |= be32_to_cpu(fh[5]);
+ parent.no_addr = ((u64)be32_to_cpu(fh[6])) << 32;
+ parent.no_addr |= be32_to_cpu(fh[7]);
+ return gfs2_get_dentry(sb, &parent);
+ default:
+ return NULL;
+ }
+}
+
+const struct export_operations gfs2_export_ops = {
.encode_fh = gfs2_encode_fh,
+ .fh_to_dentry = gfs2_fh_to_dentry,
+ .fh_to_parent = gfs2_fh_to_parent,
.get_name = gfs2_get_name,
.get_parent = gfs2_get_parent,
- .get_dentry = gfs2_get_dentry,
};
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c
index 46a9e10ff17b..bb11fd6752d3 100644
--- a/fs/gfs2/ops_file.c
+++ b/fs/gfs2/ops_file.c
@@ -406,7 +406,7 @@ static int gfs2_open(struct inode *inode, struct file *file)
if (!(file->f_flags & O_LARGEFILE) &&
ip->i_di.di_size > MAX_NON_LFS) {
- error = -EFBIG;
+ error = -EOVERFLOW;
goto fail_gunlock;
}
@@ -535,7 +535,7 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl)
if (!(fl->fl_flags & FL_POSIX))
return -ENOLCK;
- if ((ip->i_inode.i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
+ if (__mandatory_lock(&ip->i_inode))
return -ENOLCK;
if (sdp->sd_args.ar_localflocks) {
@@ -636,7 +636,7 @@ static int gfs2_flock(struct file *file, int cmd, struct file_lock *fl)
if (!(fl->fl_flags & FL_FLOCK))
return -ENOLCK;
- if ((ip->i_inode.i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
+ if (__mandatory_lock(&ip->i_inode))
return -ENOLCK;
if (sdp->sd_args.ar_localflocks)
diff --git a/fs/gfs2/ops_fstype.h b/fs/gfs2/ops_fstype.h
index 407029b3b2b3..da8490511836 100644
--- a/fs/gfs2/ops_fstype.h
+++ b/fs/gfs2/ops_fstype.h
@@ -14,6 +14,6 @@
extern struct file_system_type gfs2_fs_type;
extern struct file_system_type gfs2meta_fs_type;
-extern struct export_operations gfs2_export_ops;
+extern const struct export_operations gfs2_export_ops;
#endif /* __OPS_FSTYPE_DOT_H__ */
diff --git a/fs/hfs/extent.c b/fs/hfs/extent.c
index 5ea6b3d45eaa..c176f67ba0a5 100644
--- a/fs/hfs/extent.c
+++ b/fs/hfs/extent.c
@@ -464,23 +464,20 @@ void hfs_file_truncate(struct inode *inode)
(long long)HFS_I(inode)->phys_size, inode->i_size);
if (inode->i_size > HFS_I(inode)->phys_size) {
struct address_space *mapping = inode->i_mapping;
+ void *fsdata;
struct page *page;
int res;
+ /* XXX: Can use generic_cont_expand? */
size = inode->i_size - 1;
- page = grab_cache_page(mapping, size >> PAGE_CACHE_SHIFT);
- if (!page)
- return;
- size &= PAGE_CACHE_SIZE - 1;
- size++;
- res = mapping->a_ops->prepare_write(NULL, page, size, size);
- if (!res)
- res = mapping->a_ops->commit_write(NULL, page, size, size);
+ res = pagecache_write_begin(NULL, mapping, size+1, 0,
+ AOP_FLAG_UNINTERRUPTIBLE, &page, &fsdata);
+ if (!res) {
+ res = pagecache_write_end(NULL, mapping, size+1, 0, 0,
+ page, fsdata);
+ }
if (res)
inode->i_size = HFS_I(inode)->phys_size;
- unlock_page(page);
- page_cache_release(page);
- mark_inode_dirty(inode);
return;
} else if (inode->i_size == HFS_I(inode)->phys_size)
return;
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index bc835f272a6e..97f8446c4ff4 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -35,10 +35,14 @@ static int hfs_readpage(struct file *file, struct page *page)
return block_read_full_page(page, hfs_get_block);
}
-static int hfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
+static int hfs_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
{
- return cont_prepare_write(page, from, to, hfs_get_block,
- &HFS_I(page->mapping->host)->phys_size);
+ *pagep = NULL;
+ return cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
+ hfs_get_block,
+ &HFS_I(mapping->host)->phys_size);
}
static sector_t hfs_bmap(struct address_space *mapping, sector_t block)
@@ -119,8 +123,8 @@ const struct address_space_operations hfs_btree_aops = {
.readpage = hfs_readpage,
.writepage = hfs_writepage,
.sync_page = block_sync_page,
- .prepare_write = hfs_prepare_write,
- .commit_write = generic_commit_write,
+ .write_begin = hfs_write_begin,
+ .write_end = generic_write_end,
.bmap = hfs_bmap,
.releasepage = hfs_releasepage,
};
@@ -129,8 +133,8 @@ const struct address_space_operations hfs_aops = {
.readpage = hfs_readpage,
.writepage = hfs_writepage,
.sync_page = block_sync_page,
- .prepare_write = hfs_prepare_write,
- .commit_write = generic_commit_write,
+ .write_begin = hfs_write_begin,
+ .write_end = generic_write_end,
.bmap = hfs_bmap,
.direct_IO = hfs_direct_IO,
.writepages = hfs_writepages,
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index 6c5f92dfb500..16cbd902f8b9 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -430,7 +430,7 @@ static struct file_system_type hfs_fs_type = {
.fs_flags = FS_REQUIRES_DEV,
};
-static void hfs_init_once(void *p, struct kmem_cache *cachep, unsigned long flags)
+static void hfs_init_once(struct kmem_cache *cachep, void *p)
{
struct hfs_inode_info *i = p;
diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c
index 1a7480089e82..12e899cd7886 100644
--- a/fs/hfsplus/extents.c
+++ b/fs/hfsplus/extents.c
@@ -443,21 +443,18 @@ void hfsplus_file_truncate(struct inode *inode)
if (inode->i_size > HFSPLUS_I(inode).phys_size) {
struct address_space *mapping = inode->i_mapping;
struct page *page;
- u32 size = inode->i_size - 1;
+ void *fsdata;
+ u32 size = inode->i_size;
int res;
- page = grab_cache_page(mapping, size >> PAGE_CACHE_SHIFT);
- if (!page)
- return;
- size &= PAGE_CACHE_SIZE - 1;
- size++;
- res = mapping->a_ops->prepare_write(NULL, page, size, size);
- if (!res)
- res = mapping->a_ops->commit_write(NULL, page, size, size);
+ res = pagecache_write_begin(NULL, mapping, size, 0,
+ AOP_FLAG_UNINTERRUPTIBLE,
+ &page, &fsdata);
if (res)
- inode->i_size = HFSPLUS_I(inode).phys_size;
- unlock_page(page);
- page_cache_release(page);
+ return;
+ res = pagecache_write_end(NULL, mapping, size, 0, 0, page, fsdata);
+ if (res < 0)
+ return;
mark_inode_dirty(inode);
return;
} else if (inode->i_size == HFSPLUS_I(inode).phys_size)
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 6f7c662174db..37744cf3706a 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -27,10 +27,14 @@ static int hfsplus_writepage(struct page *page, struct writeback_control *wbc)
return block_write_full_page(page, hfsplus_get_block, wbc);
}
-static int hfsplus_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
+static int hfsplus_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
{
- return cont_prepare_write(page, from, to, hfsplus_get_block,
- &HFSPLUS_I(page->mapping->host).phys_size);
+ *pagep = NULL;
+ return cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
+ hfsplus_get_block,
+ &HFSPLUS_I(mapping->host).phys_size);
}
static sector_t hfsplus_bmap(struct address_space *mapping, sector_t block)
@@ -114,8 +118,8 @@ const struct address_space_operations hfsplus_btree_aops = {
.readpage = hfsplus_readpage,
.writepage = hfsplus_writepage,
.sync_page = block_sync_page,
- .prepare_write = hfsplus_prepare_write,
- .commit_write = generic_commit_write,
+ .write_begin = hfsplus_write_begin,
+ .write_end = generic_write_end,
.bmap = hfsplus_bmap,
.releasepage = hfsplus_releasepage,
};
@@ -124,8 +128,8 @@ const struct address_space_operations hfsplus_aops = {
.readpage = hfsplus_readpage,
.writepage = hfsplus_writepage,
.sync_page = block_sync_page,
- .prepare_write = hfsplus_prepare_write,
- .commit_write = generic_commit_write,
+ .write_begin = hfsplus_write_begin,
+ .write_end = generic_write_end,
.bmap = hfsplus_bmap,
.direct_IO = hfsplus_direct_IO,
.writepages = hfsplus_writepages,
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index 7b0f2e5a44e2..ecf70dafb643 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -466,7 +466,7 @@ static struct file_system_type hfsplus_fs_type = {
.fs_flags = FS_REQUIRES_DEV,
};
-static void hfsplus_init_once(void *p, struct kmem_cache *cachep, unsigned long flags)
+static void hfsplus_init_once(struct kmem_cache *cachep, void *p)
{
struct hfsplus_inode_info *i = p;
diff --git a/fs/hostfs/hostfs.h b/fs/hostfs/hostfs.h
index 06e5930515fe..6ae9011b95eb 100644
--- a/fs/hostfs/hostfs.h
+++ b/fs/hostfs/hostfs.h
@@ -3,7 +3,8 @@
#include "os.h"
-/* These are exactly the same definitions as in fs.h, but the names are
+/*
+ * These are exactly the same definitions as in fs.h, but the names are
* changed so that this file can be included in both kernel and user files.
*/
@@ -21,7 +22,8 @@
#define HOSTFS_ATTR_FORCE 512 /* Not a change, but a change it */
#define HOSTFS_ATTR_ATTR_FLAG 1024
-/* If you are very careful, you'll notice that these two are missing:
+/*
+ * If you are very careful, you'll notice that these two are missing:
*
* #define ATTR_KILL_SUID 2048
* #define ATTR_KILL_SGID 4096
@@ -76,7 +78,8 @@ extern int make_symlink(const char *from, const char *to);
extern int unlink_file(const char *file);
extern int do_mkdir(const char *file, int mode);
extern int do_rmdir(const char *file);
-extern int do_mknod(const char *file, int mode, unsigned int major, unsigned int minor);
+extern int do_mknod(const char *file, int mode, unsigned int major,
+ unsigned int minor);
extern int link_file(const char *from, const char *to);
extern int do_readlink(char *file, char *buf, int size);
extern int rename_file(char *from, char *to);
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index c77862032e84..8966b050196e 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -6,21 +6,14 @@
* 2003-02-10 Petr Baudis <pasky@ucw.cz>
*/
-#include <linux/stddef.h>
#include <linux/fs.h>
#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
+#include <linux/mm.h>
#include <linux/pagemap.h>
-#include <linux/blkdev.h>
-#include <linux/list.h>
#include <linux/statfs.h>
-#include <linux/kdev_t.h>
-#include <asm/uaccess.h>
#include "hostfs.h"
-#include "kern_util.h"
-#include "kern.h"
#include "init.h"
+#include "kern.h"
struct hostfs_inode_info {
char *host_filename;
@@ -61,18 +54,18 @@ static int __init hostfs_args(char *options, int *add)
char *ptr;
ptr = strchr(options, ',');
- if(ptr != NULL)
+ if (ptr != NULL)
*ptr++ = '\0';
- if(*options != '\0')
+ if (*options != '\0')
root_ino = options;
options = ptr;
- while(options){
+ while (options) {
ptr = strchr(options, ',');
- if(ptr != NULL)
+ if (ptr != NULL)
*ptr++ = '\0';
- if(*options != '\0'){
- if(!strcmp(options, "append"))
+ if (*options != '\0') {
+ if (!strcmp(options, "append"))
append = 1;
else printf("hostfs_args - unsupported option - %s\n",
options);
@@ -102,7 +95,7 @@ static char *dentry_name(struct dentry *dentry, int extra)
len = 0;
parent = dentry;
- while(parent->d_parent != parent){
+ while (parent->d_parent != parent) {
len += parent->d_name.len + 1;
parent = parent->d_parent;
}
@@ -110,12 +103,12 @@ static char *dentry_name(struct dentry *dentry, int extra)
root = HOSTFS_I(parent->d_inode)->host_filename;
len += strlen(root);
name = kmalloc(len + extra + 1, GFP_KERNEL);
- if(name == NULL)
+ if (name == NULL)
return NULL;
name[len] = '\0';
parent = dentry;
- while(parent->d_parent != parent){
+ while (parent->d_parent != parent) {
len -= parent->d_name.len + 1;
name[len] = '/';
strncpy(&name[len + 1], parent->d_name.name,
@@ -136,7 +129,8 @@ static char *inode_name(struct inode *ino, int extra)
static int read_name(struct inode *ino, char *name)
{
- /* The non-int inode fields are copied into ints by stat_file and
+ /*
+ * The non-int inode fields are copied into ints by stat_file and
* then copied into the inode because passing the actual pointers
* in and having them treated as int * breaks on big-endian machines
*/
@@ -149,7 +143,7 @@ static int read_name(struct inode *ino, char *name)
err = stat_file(name, &i_ino, &i_mode, &i_nlink, &ino->i_uid,
&ino->i_gid, &i_size, &ino->i_atime, &ino->i_mtime,
&ino->i_ctime, &i_blksize, &i_blocks, -1);
- if(err)
+ if (err)
return err;
ino->i_ino = i_ino;
@@ -166,33 +160,33 @@ static char *follow_link(char *link)
char *name, *resolved, *end;
len = 64;
- while(1){
+ while (1) {
n = -ENOMEM;
name = kmalloc(len, GFP_KERNEL);
- if(name == NULL)
+ if (name == NULL)
goto out;
n = do_readlink(link, name, len);
- if(n < len)
+ if (n < len)
break;
len *= 2;
kfree(name);
}
- if(n < 0)
+ if (n < 0)
goto out_free;
- if(*name == '/')
+ if (*name == '/')
return name;
end = strrchr(link, '/');
- if(end == NULL)
+ if (end == NULL)
return name;
*(end + 1) = '\0';
len = strlen(link) + strlen(name) + 1;
resolved = kmalloc(len, GFP_KERNEL);
- if(resolved == NULL){
+ if (resolved == NULL) {
n = -ENOMEM;
goto out_free;
}
@@ -213,20 +207,21 @@ static int read_inode(struct inode *ino)
char *name;
int err = 0;
- /* Unfortunately, we are called from iget() when we don't have a dentry
+ /*
+ * Unfortunately, we are called from iget() when we don't have a dentry
* allocated yet.
*/
- if(list_empty(&ino->i_dentry))
+ if (list_empty(&ino->i_dentry))
goto out;
err = -ENOMEM;
name = inode_name(ino, 0);
- if(name == NULL)
+ if (name == NULL)
goto out;
- if(file_type(name, NULL, NULL) == OS_TYPE_SYMLINK){
+ if (file_type(name, NULL, NULL) == OS_TYPE_SYMLINK) {
name = follow_link(name);
- if(IS_ERR(name)){
+ if (IS_ERR(name)) {
err = PTR_ERR(name);
goto out;
}
@@ -240,7 +235,8 @@ static int read_inode(struct inode *ino)
int hostfs_statfs(struct dentry *dentry, struct kstatfs *sf)
{
- /* do_statfs uses struct statfs64 internally, but the linux kernel
+ /*
+ * do_statfs uses struct statfs64 internally, but the linux kernel
* struct statfs still has 32-bit versions for most of these fields,
* so we convert them here
*/
@@ -255,7 +251,7 @@ int hostfs_statfs(struct dentry *dentry, struct kstatfs *sf)
&sf->f_bsize, &f_blocks, &f_bfree, &f_bavail, &f_files,
&f_ffree, &sf->f_fsid, sizeof(sf->f_fsid),
&sf->f_namelen, sf->f_spare);
- if(err)
+ if (err)
return err;
sf->f_blocks = f_blocks;
sf->f_bfree = f_bfree;
@@ -271,7 +267,7 @@ static struct inode *hostfs_alloc_inode(struct super_block *sb)
struct hostfs_inode_info *hi;
hi = kmalloc(sizeof(*hi), GFP_KERNEL);
- if(hi == NULL)
+ if (hi == NULL)
return NULL;
*hi = ((struct hostfs_inode_info) { .host_filename = NULL,
@@ -284,7 +280,7 @@ static struct inode *hostfs_alloc_inode(struct super_block *sb)
static void hostfs_delete_inode(struct inode *inode)
{
truncate_inode_pages(&inode->i_data, 0);
- if(HOSTFS_I(inode)->fd != -1) {
+ if (HOSTFS_I(inode)->fd != -1) {
close_file(&HOSTFS_I(inode)->fd);
HOSTFS_I(inode)->fd = -1;
}
@@ -295,9 +291,11 @@ static void hostfs_destroy_inode(struct inode *inode)
{
kfree(HOSTFS_I(inode)->host_filename);
- /*XXX: This should not happen, probably. The check is here for
- * additional safety.*/
- if(HOSTFS_I(inode)->fd != -1) {
+ /*
+ * XXX: This should not happen, probably. The check is here for
+ * additional safety.
+ */
+ if (HOSTFS_I(inode)->fd != -1) {
close_file(&HOSTFS_I(inode)->fd);
printk(KERN_DEBUG "Closing host fd in .destroy_inode\n");
}
@@ -327,17 +325,17 @@ int hostfs_readdir(struct file *file, void *ent, filldir_t filldir)
int error, len;
name = dentry_name(file->f_path.dentry, 0);
- if(name == NULL)
+ if (name == NULL)
return -ENOMEM;
dir = open_dir(name, &error);
kfree(name);
- if(dir == NULL)
+ if (dir == NULL)
return -error;
next = file->f_pos;
- while((name = read_dir(dir, &next, &ino, &len)) != NULL){
+ while ((name = read_dir(dir, &next, &ino, &len)) != NULL) {
error = (*filldir)(ent, name, len, file->f_pos,
ino, DT_UNKNOWN);
- if(error) break;
+ if (error) break;
file->f_pos = next;
}
close_dir(dir);
@@ -350,32 +348,33 @@ int hostfs_file_open(struct inode *ino, struct file *file)
int mode = 0, r = 0, w = 0, fd;
mode = file->f_mode & (FMODE_READ | FMODE_WRITE);
- if((mode & HOSTFS_I(ino)->mode) == mode)
+ if ((mode & HOSTFS_I(ino)->mode) == mode)
return 0;
- /* The file may already have been opened, but with the wrong access,
+ /*
+ * The file may already have been opened, but with the wrong access,
* so this resets things and reopens the file with the new access.
*/
- if(HOSTFS_I(ino)->fd != -1){
+ if (HOSTFS_I(ino)->fd != -1) {
close_file(&HOSTFS_I(ino)->fd);
HOSTFS_I(ino)->fd = -1;
}
HOSTFS_I(ino)->mode |= mode;
- if(HOSTFS_I(ino)->mode & FMODE_READ)
+ if (HOSTFS_I(ino)->mode & FMODE_READ)
r = 1;
- if(HOSTFS_I(ino)->mode & FMODE_WRITE)
+ if (HOSTFS_I(ino)->mode & FMODE_WRITE)
w = 1;
- if(w)
+ if (w)
r = 1;
name = dentry_name(file->f_path.dentry, 0);
- if(name == NULL)
+ if (name == NULL)
return -ENOMEM;
fd = open_file(name, r, w, append);
kfree(name);
- if(fd < 0)
+ if (fd < 0)
return fd;
FILE_HOSTFS_I(file)->fd = fd;
@@ -423,7 +422,7 @@ int hostfs_writepage(struct page *page, struct writeback_control *wbc)
base = ((unsigned long long) page->index) << PAGE_CACHE_SHIFT;
err = write_file(HOSTFS_I(inode)->fd, &base, buffer, count);
- if(err != count){
+ if (err != count) {
ClearPageUptodate(page);
goto out;
}
@@ -452,7 +451,8 @@ int hostfs_readpage(struct file *file, struct page *page)
buffer = kmap(page);
err = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer,
PAGE_CACHE_SIZE);
- if(err < 0) goto out;
+ if (err < 0)
+ goto out;
memset(&buffer[err], 0, PAGE_CACHE_SIZE - err);
@@ -466,56 +466,43 @@ int hostfs_readpage(struct file *file, struct page *page)
return err;
}
-int hostfs_prepare_write(struct file *file, struct page *page,
- unsigned int from, unsigned int to)
+int hostfs_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
{
- char *buffer;
- long long start, tmp;
- int err;
+ pgoff_t index = pos >> PAGE_CACHE_SHIFT;
- start = (long long) page->index << PAGE_CACHE_SHIFT;
- buffer = kmap(page);
- if(from != 0){
- tmp = start;
- err = read_file(FILE_HOSTFS_I(file)->fd, &tmp, buffer,
- from);
- if(err < 0) goto out;
- }
- if(to != PAGE_CACHE_SIZE){
- start += to;
- err = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer + to,
- PAGE_CACHE_SIZE - to);
- if(err < 0) goto out;
- }
- err = 0;
- out:
- kunmap(page);
- return err;
+ *pagep = __grab_cache_page(mapping, index);
+ if (!*pagep)
+ return -ENOMEM;
+ return 0;
}
-int hostfs_commit_write(struct file *file, struct page *page, unsigned from,
- unsigned to)
+int hostfs_write_end(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata)
{
- struct address_space *mapping = page->mapping;
struct inode *inode = mapping->host;
- char *buffer;
- long long start;
- int err = 0;
+ void *buffer;
+ unsigned from = pos & (PAGE_CACHE_SIZE - 1);
+ int err;
- start = (((long long) page->index) << PAGE_CACHE_SHIFT) + from;
buffer = kmap(page);
- err = write_file(FILE_HOSTFS_I(file)->fd, &start, buffer + from,
- to - from);
- if(err > 0) err = 0;
+ err = write_file(FILE_HOSTFS_I(file)->fd, &pos, buffer + from, copied);
+ kunmap(page);
- /* Actually, if !err, write_file has added to-from to start, so, despite
- * the appearance, we are comparing i_size against the _last_ written
- * location, as we should. */
+ if (!PageUptodate(page) && err == PAGE_CACHE_SIZE)
+ SetPageUptodate(page);
- if(!err && (start > inode->i_size))
- inode->i_size = start;
+ /*
+ * If err > 0, write_file has added err to pos, so we are comparing
+ * i_size against the last byte written.
+ */
+ if (err > 0 && (pos > inode->i_size))
+ inode->i_size = pos;
+ unlock_page(page);
+ page_cache_release(page);
- kunmap(page);
return err;
}
@@ -523,8 +510,8 @@ static const struct address_space_operations hostfs_aops = {
.writepage = hostfs_writepage,
.readpage = hostfs_readpage,
.set_page_dirty = __set_page_dirty_nobuffers,
- .prepare_write = hostfs_prepare_write,
- .commit_write = hostfs_commit_write
+ .write_begin = hostfs_write_begin,
+ .write_end = hostfs_write_end,
};
static int init_inode(struct inode *inode, struct dentry *dentry)
@@ -534,28 +521,28 @@ static int init_inode(struct inode *inode, struct dentry *dentry)
int maj, min;
dev_t rdev = 0;
- if(dentry){
+ if (dentry) {
name = dentry_name(dentry, 0);
- if(name == NULL)
+ if (name == NULL)
goto out;
type = file_type(name, &maj, &min);
- /*Reencode maj and min with the kernel encoding.*/
+ /* Reencode maj and min with the kernel encoding.*/
rdev = MKDEV(maj, min);
kfree(name);
}
else type = OS_TYPE_DIR;
err = 0;
- if(type == OS_TYPE_SYMLINK)
+ if (type == OS_TYPE_SYMLINK)
inode->i_op = &page_symlink_inode_operations;
- else if(type == OS_TYPE_DIR)
+ else if (type == OS_TYPE_DIR)
inode->i_op = &hostfs_dir_iops;
else inode->i_op = &hostfs_iops;
- if(type == OS_TYPE_DIR) inode->i_fop = &hostfs_dir_fops;
+ if (type == OS_TYPE_DIR) inode->i_fop = &hostfs_dir_fops;
else inode->i_fop = &hostfs_file_fops;
- if(type == OS_TYPE_SYMLINK)
+ if (type == OS_TYPE_SYMLINK)
inode->i_mapping->a_ops = &hostfs_link_aops;
else inode->i_mapping->a_ops = &hostfs_aops;
@@ -578,7 +565,7 @@ static int init_inode(struct inode *inode, struct dentry *dentry)
}
int hostfs_create(struct inode *dir, struct dentry *dentry, int mode,
- struct nameidata *nd)
+ struct nameidata *nd)
{
struct inode *inode;
char *name;
@@ -586,27 +573,28 @@ int hostfs_create(struct inode *dir, struct dentry *dentry, int mode,
error = -ENOMEM;
inode = iget(dir->i_sb, 0);
- if(inode == NULL) goto out;
+ if (inode == NULL)
+ goto out;
error = init_inode(inode, dentry);
- if(error)
+ if (error)
goto out_put;
error = -ENOMEM;
name = dentry_name(dentry, 0);
- if(name == NULL)
+ if (name == NULL)
goto out_put;
fd = file_create(name,
mode & S_IRUSR, mode & S_IWUSR, mode & S_IXUSR,
mode & S_IRGRP, mode & S_IWGRP, mode & S_IXGRP,
mode & S_IROTH, mode & S_IWOTH, mode & S_IXOTH);
- if(fd < 0)
+ if (fd < 0)
error = fd;
else error = read_name(inode, name);
kfree(name);
- if(error)
+ if (error)
goto out_put;
HOSTFS_I(inode)->fd = fd;
@@ -629,25 +617,25 @@ struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry,
err = -ENOMEM;
inode = iget(ino->i_sb, 0);
- if(inode == NULL)
+ if (inode == NULL)
goto out;
err = init_inode(inode, dentry);
- if(err)
+ if (err)
goto out_put;
err = -ENOMEM;
name = dentry_name(dentry, 0);
- if(name == NULL)
+ if (name == NULL)
goto out_put;
err = read_name(inode, name);
kfree(name);
- if(err == -ENOENT){
+ if (err == -ENOENT) {
iput(inode);
inode = NULL;
}
- else if(err)
+ else if (err)
goto out_put;
d_add(dentry, inode);
@@ -666,7 +654,7 @@ static char *inode_dentry_name(struct inode *ino, struct dentry *dentry)
int len;
file = inode_name(ino, dentry->d_name.len + 1);
- if(file == NULL)
+ if (file == NULL)
return NULL;
strcat(file, "/");
len = strlen(file);
@@ -680,10 +668,10 @@ int hostfs_link(struct dentry *to, struct inode *ino, struct dentry *from)
char *from_name, *to_name;
int err;
- if((from_name = inode_dentry_name(ino, from)) == NULL)
+ if ((from_name = inode_dentry_name(ino, from)) == NULL)
return -ENOMEM;
to_name = dentry_name(to, 0);
- if(to_name == NULL){
+ if (to_name == NULL) {
kfree(from_name);
return -ENOMEM;
}
@@ -698,9 +686,9 @@ int hostfs_unlink(struct inode *ino, struct dentry *dentry)
char *file;
int err;
- if((file = inode_dentry_name(ino, dentry)) == NULL)
+ if ((file = inode_dentry_name(ino, dentry)) == NULL)
return -ENOMEM;
- if(append)
+ if (append)
return -EPERM;
err = unlink_file(file);
@@ -713,7 +701,7 @@ int hostfs_symlink(struct inode *ino, struct dentry *dentry, const char *to)
char *file;
int err;
- if((file = inode_dentry_name(ino, dentry)) == NULL)
+ if ((file = inode_dentry_name(ino, dentry)) == NULL)
return -ENOMEM;
err = make_symlink(file, to);
kfree(file);
@@ -725,7 +713,7 @@ int hostfs_mkdir(struct inode *ino, struct dentry *dentry, int mode)
char *file;
int err;
- if((file = inode_dentry_name(ino, dentry)) == NULL)
+ if ((file = inode_dentry_name(ino, dentry)) == NULL)
return -ENOMEM;
err = do_mkdir(file, mode);
kfree(file);
@@ -737,7 +725,7 @@ int hostfs_rmdir(struct inode *ino, struct dentry *dentry)
char *file;
int err;
- if((file = inode_dentry_name(ino, dentry)) == NULL)
+ if ((file = inode_dentry_name(ino, dentry)) == NULL)
return -ENOMEM;
err = do_rmdir(file);
kfree(file);
@@ -751,26 +739,26 @@ int hostfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
int err = -ENOMEM;
inode = iget(dir->i_sb, 0);
- if(inode == NULL)
+ if (inode == NULL)
goto out;
err = init_inode(inode, dentry);
- if(err)
+ if (err)
goto out_put;
err = -ENOMEM;
name = dentry_name(dentry, 0);
- if(name == NULL)
+ if (name == NULL)
goto out_put;
init_special_inode(inode, mode, dev);
err = do_mknod(name, mode, MAJOR(dev), MINOR(dev));
- if(err)
+ if (err)
goto out_free;
err = read_name(inode, name);
kfree(name);
- if(err)
+ if (err)
goto out_put;
d_instantiate(dentry, inode);
@@ -790,9 +778,9 @@ int hostfs_rename(struct inode *from_ino, struct dentry *from,
char *from_name, *to_name;
int err;
- if((from_name = inode_dentry_name(from_ino, from)) == NULL)
+ if ((from_name = inode_dentry_name(from_ino, from)) == NULL)
return -ENOMEM;
- if((to_name = inode_dentry_name(to_ino, to)) == NULL){
+ if ((to_name = inode_dentry_name(to_ino, to)) == NULL) {
kfree(from_name);
return -ENOMEM;
}
@@ -815,12 +803,12 @@ int hostfs_permission(struct inode *ino, int desired, struct nameidata *nd)
return -ENOMEM;
if (S_ISCHR(ino->i_mode) || S_ISBLK(ino->i_mode) ||
- S_ISFIFO(ino->i_mode) || S_ISSOCK(ino->i_mode))
+ S_ISFIFO(ino->i_mode) || S_ISSOCK(ino->i_mode))
err = 0;
else
err = access_file(name, r, w, x);
kfree(name);
- if(!err)
+ if (!err)
err = generic_permission(ino, desired, NULL);
return err;
}
@@ -837,62 +825,55 @@ int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
if (err)
return err;
- if(append)
+ if (append)
attr->ia_valid &= ~ATTR_SIZE;
attrs.ia_valid = 0;
- if(attr->ia_valid & ATTR_MODE){
+ if (attr->ia_valid & ATTR_MODE) {
attrs.ia_valid |= HOSTFS_ATTR_MODE;
attrs.ia_mode = attr->ia_mode;
}
- if(attr->ia_valid & ATTR_UID){
+ if (attr->ia_valid & ATTR_UID) {
attrs.ia_valid |= HOSTFS_ATTR_UID;
attrs.ia_uid = attr->ia_uid;
}
- if(attr->ia_valid & ATTR_GID){
+ if (attr->ia_valid & ATTR_GID) {
attrs.ia_valid |= HOSTFS_ATTR_GID;
attrs.ia_gid = attr->ia_gid;
}
- if(attr->ia_valid & ATTR_SIZE){
+ if (attr->ia_valid & ATTR_SIZE) {
attrs.ia_valid |= HOSTFS_ATTR_SIZE;
attrs.ia_size = attr->ia_size;
}
- if(attr->ia_valid & ATTR_ATIME){
+ if (attr->ia_valid & ATTR_ATIME) {
attrs.ia_valid |= HOSTFS_ATTR_ATIME;
attrs.ia_atime = attr->ia_atime;
}
- if(attr->ia_valid & ATTR_MTIME){
+ if (attr->ia_valid & ATTR_MTIME) {
attrs.ia_valid |= HOSTFS_ATTR_MTIME;
attrs.ia_mtime = attr->ia_mtime;
}
- if(attr->ia_valid & ATTR_CTIME){
+ if (attr->ia_valid & ATTR_CTIME) {
attrs.ia_valid |= HOSTFS_ATTR_CTIME;
attrs.ia_ctime = attr->ia_ctime;
}
- if(attr->ia_valid & ATTR_ATIME_SET){
+ if (attr->ia_valid & ATTR_ATIME_SET) {
attrs.ia_valid |= HOSTFS_ATTR_ATIME_SET;
}
- if(attr->ia_valid & ATTR_MTIME_SET){
+ if (attr->ia_valid & ATTR_MTIME_SET) {
attrs.ia_valid |= HOSTFS_ATTR_MTIME_SET;
}
name = dentry_name(dentry, 0);
- if(name == NULL)
+ if (name == NULL)
return -ENOMEM;
err = set_attr(name, &attrs, fd);
kfree(name);
- if(err)
+ if (err)
return err;
return inode_setattr(dentry->d_inode, attr);
}
-int hostfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
- struct kstat *stat)
-{
- generic_fillattr(dentry->d_inode, stat);
- return 0;
-}
-
static const struct inode_operations hostfs_iops = {
.create = hostfs_create,
.link = hostfs_link,
@@ -904,7 +885,6 @@ static const struct inode_operations hostfs_iops = {
.rename = hostfs_rename,
.permission = hostfs_permission,
.setattr = hostfs_setattr,
- .getattr = hostfs_getattr,
};
static const struct inode_operations hostfs_dir_iops = {
@@ -919,7 +899,6 @@ static const struct inode_operations hostfs_dir_iops = {
.rename = hostfs_rename,
.permission = hostfs_permission,
.setattr = hostfs_setattr,
- .getattr = hostfs_getattr,
};
int hostfs_link_readpage(struct file *file, struct page *page)
@@ -929,13 +908,13 @@ int hostfs_link_readpage(struct file *file, struct page *page)
buffer = kmap(page);
name = inode_name(page->mapping->host, 0);
- if(name == NULL)
+ if (name == NULL)
return -ENOMEM;
err = do_readlink(name, buffer, PAGE_CACHE_SIZE);
kfree(name);
- if(err == PAGE_CACHE_SIZE)
+ if (err == PAGE_CACHE_SIZE)
err = -E2BIG;
- else if(err > 0){
+ else if (err > 0) {
flush_dcache_page(page);
SetPageUptodate(page);
if (PageError(page)) ClearPageError(page);
@@ -968,31 +947,33 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)
err = -ENOMEM;
host_root_path = kmalloc(strlen(root_ino) + 1
+ strlen(req_root) + 1, GFP_KERNEL);
- if(host_root_path == NULL)
+ if (host_root_path == NULL)
goto out;
sprintf(host_root_path, "%s/%s", root_ino, req_root);
root_inode = iget(sb, 0);
- if(root_inode == NULL)
+ if (root_inode == NULL)
goto out_free;
err = init_inode(root_inode, NULL);
- if(err)
+ if (err)
goto out_put;
HOSTFS_I(root_inode)->host_filename = host_root_path;
- /* Avoid that in the error path, iput(root_inode) frees again
- * host_root_path through hostfs_destroy_inode! */
+ /*
+ * Avoid that in the error path, iput(root_inode) frees again
+ * host_root_path through hostfs_destroy_inode!
+ */
host_root_path = NULL;
err = -ENOMEM;
sb->s_root = d_alloc_root(root_inode);
- if(sb->s_root == NULL)
+ if (sb->s_root == NULL)
goto out_put;
err = read_inode(root_inode);
- if(err){
+ if (err) {
/* No iput in this case because the dput does that for us */
dput(sb->s_root);
sb->s_root = NULL;
diff --git a/fs/hostfs/hostfs_user.c b/fs/hostfs/hostfs_user.c
index 5625e2481dd3..35c1a9f33f47 100644
--- a/fs/hostfs/hostfs_user.c
+++ b/fs/hostfs/hostfs_user.c
@@ -3,19 +3,21 @@
* Licensed under the GPL
*/
-#include <unistd.h>
#include <stdio.h>
-#include <fcntl.h>
+#include <stddef.h>
+#include <unistd.h>
#include <dirent.h>
#include <errno.h>
-#include <utime.h>
+#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/time.h>
+#include <sys/types.h>
#include <sys/vfs.h>
#include "hostfs.h"
-#include "kern_util.h"
+#include "os.h"
#include "user.h"
+#include <utime.h>
int stat_file(const char *path, unsigned long long *inode_out, int *mode_out,
int *nlink_out, int *uid_out, int *gid_out,
@@ -25,33 +27,41 @@ int stat_file(const char *path, unsigned long long *inode_out, int *mode_out,
{
struct stat64 buf;
- if(fd >= 0) {
+ if (fd >= 0) {
if (fstat64(fd, &buf) < 0)
return -errno;
- } else if(lstat64(path, &buf) < 0) {
+ } else if (lstat64(path, &buf) < 0) {
return -errno;
}
- if(inode_out != NULL) *inode_out = buf.st_ino;
- if(mode_out != NULL) *mode_out = buf.st_mode;
- if(nlink_out != NULL) *nlink_out = buf.st_nlink;
- if(uid_out != NULL) *uid_out = buf.st_uid;
- if(gid_out != NULL) *gid_out = buf.st_gid;
- if(size_out != NULL) *size_out = buf.st_size;
- if(atime_out != NULL) {
+ if (inode_out != NULL)
+ *inode_out = buf.st_ino;
+ if (mode_out != NULL)
+ *mode_out = buf.st_mode;
+ if (nlink_out != NULL)
+ *nlink_out = buf.st_nlink;
+ if (uid_out != NULL)
+ *uid_out = buf.st_uid;
+ if (gid_out != NULL)
+ *gid_out = buf.st_gid;
+ if (size_out != NULL)
+ *size_out = buf.st_size;
+ if (atime_out != NULL) {
atime_out->tv_sec = buf.st_atime;
atime_out->tv_nsec = 0;
}
- if(mtime_out != NULL) {
+ if (mtime_out != NULL) {
mtime_out->tv_sec = buf.st_mtime;
mtime_out->tv_nsec = 0;
}
- if(ctime_out != NULL) {
+ if (ctime_out != NULL) {
ctime_out->tv_sec = buf.st_ctime;
ctime_out->tv_nsec = 0;
}
- if(blksize_out != NULL) *blksize_out = buf.st_blksize;
- if(blocks_out != NULL) *blocks_out = buf.st_blocks;
+ if (blksize_out != NULL)
+ *blksize_out = buf.st_blksize;
+ if (blocks_out != NULL)
+ *blocks_out = buf.st_blocks;
return 0;
}
@@ -59,21 +69,29 @@ int file_type(const char *path, int *maj, int *min)
{
struct stat64 buf;
- if(lstat64(path, &buf) < 0)
+ if (lstat64(path, &buf) < 0)
return -errno;
- /*We cannot pass rdev as is because glibc and the kernel disagree
- *about its definition.*/
- if(maj != NULL)
+ /*
+ * We cannot pass rdev as is because glibc and the kernel disagree
+ * about its definition.
+ */
+ if (maj != NULL)
*maj = major(buf.st_rdev);
- if(min != NULL)
+ if (min != NULL)
*min = minor(buf.st_rdev);
- if(S_ISDIR(buf.st_mode)) return OS_TYPE_DIR;
- else if(S_ISLNK(buf.st_mode)) return OS_TYPE_SYMLINK;
- else if(S_ISCHR(buf.st_mode)) return OS_TYPE_CHARDEV;
- else if(S_ISBLK(buf.st_mode)) return OS_TYPE_BLOCKDEV;
- else if(S_ISFIFO(buf.st_mode))return OS_TYPE_FIFO;
- else if(S_ISSOCK(buf.st_mode))return OS_TYPE_SOCK;
+ if (S_ISDIR(buf.st_mode))
+ return OS_TYPE_DIR;
+ else if (S_ISLNK(buf.st_mode))
+ return OS_TYPE_SYMLINK;
+ else if (S_ISCHR(buf.st_mode))
+ return OS_TYPE_CHARDEV;
+ else if (S_ISBLK(buf.st_mode))
+ return OS_TYPE_BLOCKDEV;
+ else if (S_ISFIFO(buf.st_mode))
+ return OS_TYPE_FIFO;
+ else if (S_ISSOCK(buf.st_mode))
+ return OS_TYPE_SOCK;
else return OS_TYPE_FILE;
}
@@ -81,10 +99,13 @@ int access_file(char *path, int r, int w, int x)
{
int mode = 0;
- if(r) mode = R_OK;
- if(w) mode |= W_OK;
- if(x) mode |= X_OK;
- if(access(path, mode) != 0)
+ if (r)
+ mode = R_OK;
+ if (w)
+ mode |= W_OK;
+ if (x)
+ mode |= X_OK;
+ if (access(path, mode) != 0)
return -errno;
else return 0;
}
@@ -93,18 +114,18 @@ int open_file(char *path, int r, int w, int append)
{
int mode = 0, fd;
- if(r && !w)
+ if (r && !w)
mode = O_RDONLY;
- else if(!r && w)
+ else if (!r && w)
mode = O_WRONLY;
- else if(r && w)
+ else if (r && w)
mode = O_RDWR;
else panic("Impossible mode in open_file");
- if(append)
+ if (append)
mode |= O_APPEND;
fd = open64(path, mode);
- if(fd < 0)
+ if (fd < 0)
return -errno;
else return fd;
}
@@ -115,7 +136,7 @@ void *open_dir(char *path, int *err_out)
dir = opendir(path);
*err_out = errno;
- if(dir == NULL)
+ if (dir == NULL)
return NULL;
return dir;
}
@@ -128,7 +149,7 @@ char *read_dir(void *stream, unsigned long long *pos,
seekdir(dir, *pos);
ent = readdir(dir);
- if(ent == NULL)
+ if (ent == NULL)
return NULL;
*len_out = strlen(ent->d_name);
*ino_out = ent->d_ino;
@@ -141,7 +162,7 @@ int read_file(int fd, unsigned long long *offset, char *buf, int len)
int n;
n = pread64(fd, buf, len, *offset);
- if(n < 0)
+ if (n < 0)
return -errno;
*offset += n;
return n;
@@ -152,7 +173,7 @@ int write_file(int fd, unsigned long long *offset, const char *buf, int len)
int n;
n = pwrite64(fd, buf, len, *offset);
- if(n < 0)
+ if (n < 0)
return -errno;
*offset += n;
return n;
@@ -163,7 +184,7 @@ int lseek_file(int fd, long long offset, int whence)
int ret;
ret = lseek64(fd, offset, whence);
- if(ret < 0)
+ if (ret < 0)
return -errno;
return 0;
}
@@ -207,7 +228,7 @@ int file_create(char *name, int ur, int uw, int ux, int gr,
mode |= ow ? S_IWOTH : 0;
mode |= ox ? S_IXOTH : 0;
fd = open64(name, O_CREAT | O_RDWR, mode);
- if(fd < 0)
+ if (fd < 0)
return -errno;
return fd;
}
@@ -230,7 +251,7 @@ int set_attr(const char *file, struct hostfs_iattr *attrs, int fd)
if (fd >= 0) {
if (fchown(fd, attrs->ia_uid, -1))
return -errno;
- } else if(chown(file, attrs->ia_uid, -1)) {
+ } else if (chown(file, attrs->ia_uid, -1)) {
return -errno;
}
}
@@ -251,9 +272,11 @@ int set_attr(const char *file, struct hostfs_iattr *attrs, int fd)
}
}
- /* Update accessed and/or modified time, in two parts: first set
+ /*
+ * Update accessed and/or modified time, in two parts: first set
* times according to the changes to perform, and then call futimes()
- * or utimes() to apply them. */
+ * or utimes() to apply them.
+ */
ma = (HOSTFS_ATTR_ATIME_SET | HOSTFS_ATTR_MTIME_SET);
if (attrs->ia_valid & ma) {
err = stat_file(file, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -283,12 +306,12 @@ int set_attr(const char *file, struct hostfs_iattr *attrs, int fd)
}
}
- if(attrs->ia_valid & HOSTFS_ATTR_CTIME) ;
- if(attrs->ia_valid & (HOSTFS_ATTR_ATIME | HOSTFS_ATTR_MTIME)){
+ /* Note: ctime is not handled */
+ if (attrs->ia_valid & (HOSTFS_ATTR_ATIME | HOSTFS_ATTR_MTIME)) {
err = stat_file(file, NULL, NULL, NULL, NULL, NULL, NULL,
&attrs->ia_atime, &attrs->ia_mtime, NULL,
NULL, NULL, fd);
- if(err != 0)
+ if (err != 0)
return err;
}
return 0;
@@ -299,7 +322,7 @@ int make_symlink(const char *from, const char *to)
int err;
err = symlink(to, from);
- if(err)
+ if (err)
return -errno;
return 0;
}
@@ -309,7 +332,7 @@ int unlink_file(const char *file)
int err;
err = unlink(file);
- if(err)
+ if (err)
return -errno;
return 0;
}
@@ -319,7 +342,7 @@ int do_mkdir(const char *file, int mode)
int err;
err = mkdir(file, mode);
- if(err)
+ if (err)
return -errno;
return 0;
}
@@ -329,7 +352,7 @@ int do_rmdir(const char *file)
int err;
err = rmdir(file);
- if(err)
+ if (err)
return -errno;
return 0;
}
@@ -339,7 +362,7 @@ int do_mknod(const char *file, int mode, unsigned int major, unsigned int minor)
int err;
err = mknod(file, mode, makedev(major, minor));
- if(err)
+ if (err)
return -errno;
return 0;
}
@@ -349,7 +372,7 @@ int link_file(const char *to, const char *from)
int err;
err = link(to, from);
- if(err)
+ if (err)
return -errno;
return 0;
}
@@ -359,9 +382,9 @@ int do_readlink(char *file, char *buf, int size)
int n;
n = readlink(file, buf, size);
- if(n < 0)
+ if (n < 0)
return -errno;
- if(n < size)
+ if (n < size)
buf[n] = '\0';
return n;
}
@@ -371,7 +394,7 @@ int rename_file(char *from, char *to)
int err;
err = rename(from, to);
- if(err < 0)
+ if (err < 0)
return -errno;
return 0;
}
@@ -386,7 +409,7 @@ int do_statfs(char *root, long *bsize_out, long long *blocks_out,
int err;
err = statfs64(root, &buf);
- if(err < 0)
+ if (err < 0)
return -errno;
*bsize_out = buf.f_bsize;
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c
index 5b53e5c5d8df..be8be5040e07 100644
--- a/fs/hpfs/file.c
+++ b/fs/hpfs/file.c
@@ -86,25 +86,33 @@ static int hpfs_writepage(struct page *page, struct writeback_control *wbc)
{
return block_write_full_page(page,hpfs_get_block, wbc);
}
+
static int hpfs_readpage(struct file *file, struct page *page)
{
return block_read_full_page(page,hpfs_get_block);
}
-static int hpfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
+
+static int hpfs_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
{
- return cont_prepare_write(page,from,to,hpfs_get_block,
- &hpfs_i(page->mapping->host)->mmu_private);
+ *pagep = NULL;
+ return cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
+ hpfs_get_block,
+ &hpfs_i(mapping->host)->mmu_private);
}
+
static sector_t _hpfs_bmap(struct address_space *mapping, sector_t block)
{
return generic_block_bmap(mapping,block,hpfs_get_block);
}
+
const struct address_space_operations hpfs_aops = {
.readpage = hpfs_readpage,
.writepage = hpfs_writepage,
.sync_page = block_sync_page,
- .prepare_write = hpfs_prepare_write,
- .commit_write = generic_commit_write,
+ .write_begin = hpfs_write_begin,
+ .write_end = generic_write_end,
.bmap = _hpfs_bmap
};
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c
index 89612ee7c80d..00971d999964 100644
--- a/fs/hpfs/super.c
+++ b/fs/hpfs/super.c
@@ -173,7 +173,7 @@ static void hpfs_destroy_inode(struct inode *inode)
kmem_cache_free(hpfs_inode_cachep, hpfs_i(inode));
}
-static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
+static void init_once(struct kmem_cache *cachep, void *foo)
{
struct hpfs_inode_info *ei = (struct hpfs_inode_info *) foo;
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 950c2fbb815b..09ee07f02663 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -179,6 +179,130 @@ full_search:
}
#endif
+static int
+hugetlbfs_read_actor(struct page *page, unsigned long offset,
+ char __user *buf, unsigned long count,
+ unsigned long size)
+{
+ char *kaddr;
+ unsigned long left, copied = 0;
+ int i, chunksize;
+
+ if (size > count)
+ size = count;
+
+ /* Find which 4k chunk and offset with in that chunk */
+ i = offset >> PAGE_CACHE_SHIFT;
+ offset = offset & ~PAGE_CACHE_MASK;
+
+ while (size) {
+ chunksize = PAGE_CACHE_SIZE;
+ if (offset)
+ chunksize -= offset;
+ if (chunksize > size)
+ chunksize = size;
+ kaddr = kmap(&page[i]);
+ left = __copy_to_user(buf, kaddr + offset, chunksize);
+ kunmap(&page[i]);
+ if (left) {
+ copied += (chunksize - left);
+ break;
+ }
+ offset = 0;
+ size -= chunksize;
+ buf += chunksize;
+ copied += chunksize;
+ i++;
+ }
+ return copied ? copied : -EFAULT;
+}
+
+/*
+ * Support for read() - Find the page attached to f_mapping and copy out the
+ * data. Its *very* similar to do_generic_mapping_read(), we can't use that
+ * since it has PAGE_CACHE_SIZE assumptions.
+ */
+static ssize_t hugetlbfs_read(struct file *filp, char __user *buf,
+ size_t len, loff_t *ppos)
+{
+ struct address_space *mapping = filp->f_mapping;
+ struct inode *inode = mapping->host;
+ unsigned long index = *ppos >> HPAGE_SHIFT;
+ unsigned long offset = *ppos & ~HPAGE_MASK;
+ unsigned long end_index;
+ loff_t isize;
+ ssize_t retval = 0;
+
+ mutex_lock(&inode->i_mutex);
+
+ /* validate length */
+ if (len == 0)
+ goto out;
+
+ isize = i_size_read(inode);
+ if (!isize)
+ goto out;
+
+ end_index = (isize - 1) >> HPAGE_SHIFT;
+ for (;;) {
+ struct page *page;
+ int nr, ret;
+
+ /* nr is the maximum number of bytes to copy from this page */
+ nr = HPAGE_SIZE;
+ if (index >= end_index) {
+ if (index > end_index)
+ goto out;
+ nr = ((isize - 1) & ~HPAGE_MASK) + 1;
+ if (nr <= offset) {
+ goto out;
+ }
+ }
+ nr = nr - offset;
+
+ /* Find the page */
+ page = find_get_page(mapping, index);
+ if (unlikely(page == NULL)) {
+ /*
+ * We have a HOLE, zero out the user-buffer for the
+ * length of the hole or request.
+ */
+ ret = len < nr ? len : nr;
+ if (clear_user(buf, ret))
+ ret = -EFAULT;
+ } else {
+ /*
+ * We have the page, copy it to user space buffer.
+ */
+ ret = hugetlbfs_read_actor(page, offset, buf, len, nr);
+ }
+ if (ret < 0) {
+ if (retval == 0)
+ retval = ret;
+ if (page)
+ page_cache_release(page);
+ goto out;
+ }
+
+ offset += ret;
+ retval += ret;
+ len -= ret;
+ index += offset >> HPAGE_SHIFT;
+ offset &= ~HPAGE_MASK;
+
+ if (page)
+ page_cache_release(page);
+
+ /* short read or no more work */
+ if ((ret != nr) || (len == 0))
+ break;
+ }
+out:
+ *ppos = ((loff_t)index << HPAGE_SHIFT) + offset;
+ mutex_unlock(&inode->i_mutex);
+ return retval;
+}
+
/*
* Read a page. Again trivial. If it didn't already exist
* in the page cache, it is zero-filled.
@@ -189,15 +313,19 @@ static int hugetlbfs_readpage(struct file *file, struct page * page)
return -EINVAL;
}
-static int hugetlbfs_prepare_write(struct file *file,
- struct page *page, unsigned offset, unsigned to)
+static int hugetlbfs_write_begin(struct file *file,
+ struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
{
return -EINVAL;
}
-static int hugetlbfs_commit_write(struct file *file,
- struct page *page, unsigned offset, unsigned to)
+static int hugetlbfs_write_end(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata)
{
+ BUG();
return -EINVAL;
}
@@ -236,7 +364,6 @@ static void truncate_hugepages(struct inode *inode, loff_t lstart)
++next;
truncate_huge_page(page);
unlock_page(page);
- hugetlb_put_quota(mapping);
freed++;
}
huge_pagevec_release(&pvec);
@@ -256,7 +383,7 @@ static void hugetlbfs_forget_inode(struct inode *inode) __releases(inode_lock)
struct super_block *sb = inode->i_sb;
if (!hlist_unhashed(&inode->i_hash)) {
- if (!(inode->i_state & (I_DIRTY|I_LOCK)))
+ if (!(inode->i_state & (I_DIRTY|I_SYNC)))
list_move(&inode->i_list, &inode_unused);
inodes_stat.nr_unused++;
if (!sb || (sb->s_flags & MS_ACTIVE)) {
@@ -318,21 +445,15 @@ hugetlb_vmtruncate_list(struct prio_tree_root *root, pgoff_t pgoff)
}
}
-/*
- * Expanding truncates are not allowed.
- */
static int hugetlb_vmtruncate(struct inode *inode, loff_t offset)
{
pgoff_t pgoff;
struct address_space *mapping = inode->i_mapping;
- if (offset > inode->i_size)
- return -EINVAL;
-
BUG_ON(offset & ~HPAGE_MASK);
pgoff = offset >> PAGE_SHIFT;
- inode->i_size = offset;
+ i_size_write(inode, offset);
spin_lock(&mapping->i_mmap_lock);
if (!prio_tree_empty(&mapping->i_mmap))
hugetlb_vmtruncate_list(&mapping->i_mmap, pgoff);
@@ -569,13 +690,13 @@ static void hugetlbfs_destroy_inode(struct inode *inode)
static const struct address_space_operations hugetlbfs_aops = {
.readpage = hugetlbfs_readpage,
- .prepare_write = hugetlbfs_prepare_write,
- .commit_write = hugetlbfs_commit_write,
+ .write_begin = hugetlbfs_write_begin,
+ .write_end = hugetlbfs_write_end,
.set_page_dirty = hugetlbfs_set_page_dirty,
};
-static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags)
+static void init_once(struct kmem_cache *cachep, void *foo)
{
struct hugetlbfs_inode_info *ei = (struct hugetlbfs_inode_info *)foo;
@@ -583,6 +704,7 @@ static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags)
}
const struct file_operations hugetlbfs_file_operations = {
+ .read = hugetlbfs_read,
.mmap = hugetlbfs_file_mmap,
.fsync = simple_sync_file,
.get_unmapped_area = hugetlb_get_unmapped_area,
@@ -736,15 +858,15 @@ out_free:
return -ENOMEM;
}
-int hugetlb_get_quota(struct address_space *mapping)
+int hugetlb_get_quota(struct address_space *mapping, long delta)
{
int ret = 0;
struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(mapping->host->i_sb);
if (sbinfo->free_blocks > -1) {
spin_lock(&sbinfo->stat_lock);
- if (sbinfo->free_blocks > 0)
- sbinfo->free_blocks--;
+ if (sbinfo->free_blocks - delta >= 0)
+ sbinfo->free_blocks -= delta;
else
ret = -ENOMEM;
spin_unlock(&sbinfo->stat_lock);
@@ -753,13 +875,13 @@ int hugetlb_get_quota(struct address_space *mapping)
return ret;
}
-void hugetlb_put_quota(struct address_space *mapping)
+void hugetlb_put_quota(struct address_space *mapping, long delta)
{
struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(mapping->host->i_sb);
if (sbinfo->free_blocks > -1) {
spin_lock(&sbinfo->stat_lock);
- sbinfo->free_blocks++;
+ sbinfo->free_blocks += delta;
spin_unlock(&sbinfo->stat_lock);
}
}
@@ -810,16 +932,11 @@ struct file *hugetlb_file_setup(const char *name, size_t size)
if (!dentry)
goto out_shm_unlock;
- error = -ENFILE;
- file = get_empty_filp();
- if (!file)
- goto out_dentry;
-
error = -ENOSPC;
inode = hugetlbfs_get_inode(root->d_sb, current->fsuid,
current->fsgid, S_IFREG | S_IRWXUGO, 0);
if (!inode)
- goto out_file;
+ goto out_dentry;
error = -ENOMEM;
if (hugetlb_reserve_pages(inode, 0, size >> HPAGE_SHIFT))
@@ -828,17 +945,18 @@ struct file *hugetlb_file_setup(const char *name, size_t size)
d_instantiate(dentry, inode);
inode->i_size = size;
inode->i_nlink = 0;
- file->f_path.mnt = mntget(hugetlbfs_vfsmount);
- file->f_path.dentry = dentry;
- file->f_mapping = inode->i_mapping;
- file->f_op = &hugetlbfs_file_operations;
- file->f_mode = FMODE_WRITE | FMODE_READ;
+
+ error = -ENFILE;
+ file = alloc_file(hugetlbfs_vfsmount, dentry,
+ FMODE_WRITE | FMODE_READ,
+ &hugetlbfs_file_operations);
+ if (!file)
+ goto out_inode;
+
return file;
out_inode:
iput(inode);
-out_file:
- put_filp(file);
out_dentry:
dput(dentry);
out_shm_unlock:
@@ -851,11 +969,15 @@ static int __init init_hugetlbfs_fs(void)
int error;
struct vfsmount *vfsmount;
+ error = bdi_init(&hugetlbfs_backing_dev_info);
+ if (error)
+ return error;
+
hugetlbfs_inode_cachep = kmem_cache_create("hugetlbfs_inode_cache",
sizeof(struct hugetlbfs_inode_info),
0, 0, init_once);
if (hugetlbfs_inode_cachep == NULL)
- return -ENOMEM;
+ goto out2;
error = register_filesystem(&hugetlbfs_fs_type);
if (error)
@@ -873,6 +995,8 @@ static int __init init_hugetlbfs_fs(void)
out:
if (error)
kmem_cache_destroy(hugetlbfs_inode_cachep);
+ out2:
+ bdi_destroy(&hugetlbfs_backing_dev_info);
return error;
}
@@ -880,6 +1004,7 @@ static void __exit exit_hugetlbfs_fs(void)
{
kmem_cache_destroy(hugetlbfs_inode_cachep);
unregister_filesystem(&hugetlbfs_fs_type);
+ bdi_destroy(&hugetlbfs_backing_dev_info);
}
module_init(init_hugetlbfs_fs)
diff --git a/fs/inode.c b/fs/inode.c
index f97de0aeb3b6..ed35383d0b6c 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -99,6 +99,15 @@ struct inodes_stat_t inodes_stat;
static struct kmem_cache * inode_cachep __read_mostly;
+static void wake_up_inode(struct inode *inode)
+{
+ /*
+ * Prevent speculative execution through spin_unlock(&inode_lock);
+ */
+ smp_mb();
+ wake_up_bit(&inode->i_state, __I_LOCK);
+}
+
static struct inode *alloc_inode(struct super_block *sb)
{
static const struct address_space_operations empty_aops;
@@ -215,7 +224,7 @@ void inode_init_once(struct inode *inode)
EXPORT_SYMBOL(inode_init_once);
-static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
+static void init_once(struct kmem_cache * cachep, void *foo)
{
struct inode * inode = (struct inode *) foo;
@@ -232,7 +241,7 @@ void __iget(struct inode * inode)
return;
}
atomic_inc(&inode->i_count);
- if (!(inode->i_state & (I_DIRTY|I_LOCK)))
+ if (!(inode->i_state & (I_DIRTY|I_SYNC)))
list_move(&inode->i_list, &inode_in_use);
inodes_stat.nr_unused--;
}
@@ -253,7 +262,7 @@ void clear_inode(struct inode *inode)
BUG_ON(inode->i_data.nrpages);
BUG_ON(!(inode->i_state & I_FREEING));
BUG_ON(inode->i_state & I_CLEAR);
- wait_on_inode(inode);
+ inode_sync_wait(inode);
DQUOT_DROP(inode);
if (inode->i_sb->s_op->clear_inode)
inode->i_sb->s_op->clear_inode(inode);
@@ -568,16 +577,16 @@ EXPORT_SYMBOL(new_inode);
void unlock_new_inode(struct inode *inode)
{
#ifdef CONFIG_DEBUG_LOCK_ALLOC
- struct file_system_type *type = inode->i_sb->s_type;
- /*
- * ensure nobody is actually holding i_mutex
- */
- mutex_destroy(&inode->i_mutex);
- mutex_init(&inode->i_mutex);
- if (inode->i_mode & S_IFDIR)
+ if (inode->i_mode & S_IFDIR) {
+ struct file_system_type *type = inode->i_sb->s_type;
+
+ /*
+ * ensure nobody is actually holding i_mutex
+ */
+ mutex_destroy(&inode->i_mutex);
+ mutex_init(&inode->i_mutex);
lockdep_set_class(&inode->i_mutex, &type->i_mutex_dir_key);
- else
- lockdep_set_class(&inode->i_mutex, &type->i_mutex_key);
+ }
#endif
/*
* This is special! We do not need the spinlock
@@ -1071,7 +1080,7 @@ static void generic_forget_inode(struct inode *inode)
struct super_block *sb = inode->i_sb;
if (!hlist_unhashed(&inode->i_hash)) {
- if (!(inode->i_state & (I_DIRTY|I_LOCK)))
+ if (!(inode->i_state & (I_DIRTY|I_SYNC)))
list_move(&inode->i_list, &inode_unused);
inodes_stat.nr_unused++;
if (sb->s_flags & MS_ACTIVE) {
@@ -1314,15 +1323,6 @@ static void __wait_on_freeing_inode(struct inode *inode)
spin_lock(&inode_lock);
}
-void wake_up_inode(struct inode *inode)
-{
- /*
- * Prevent speculative execution through spin_unlock(&inode_lock);
- */
- smp_mb();
- wake_up_bit(&inode->i_state, __I_LOCK);
-}
-
/*
* We rarely want to lock two inodes that do not have a parent/child
* relationship (such as directory, child inode) simultaneously. The
@@ -1396,7 +1396,7 @@ void __init inode_init_early(void)
INIT_HLIST_HEAD(&inode_hashtable[loop]);
}
-void __init inode_init(unsigned long mempages)
+void __init inode_init(void)
{
int loop;
diff --git a/fs/inotify.c b/fs/inotify.c
index 7457501b9565..2c5b92152876 100644
--- a/fs/inotify.c
+++ b/fs/inotify.c
@@ -667,6 +667,49 @@ out:
EXPORT_SYMBOL_GPL(inotify_add_watch);
/**
+ * inotify_clone_watch - put the watch next to existing one
+ * @old: already installed watch
+ * @new: new watch
+ *
+ * Caller must hold the inotify_mutex of inode we are dealing with;
+ * it is expected to remove the old watch before unlocking the inode.
+ */
+s32 inotify_clone_watch(struct inotify_watch *old, struct inotify_watch *new)
+{
+ struct inotify_handle *ih = old->ih;
+ int ret = 0;
+
+ new->mask = old->mask;
+ new->ih = ih;
+
+ mutex_lock(&ih->mutex);
+
+ /* Initialize a new watch */
+ ret = inotify_handle_get_wd(ih, new);
+ if (unlikely(ret))
+ goto out;
+ ret = new->wd;
+
+ get_inotify_handle(ih);
+
+ new->inode = igrab(old->inode);
+
+ list_add(&new->h_list, &ih->watches);
+ list_add(&new->i_list, &old->inode->inotify_watches);
+out:
+ mutex_unlock(&ih->mutex);
+ return ret;
+}
+
+void inotify_evict_watch(struct inotify_watch *watch)
+{
+ get_inotify_watch(watch);
+ mutex_lock(&watch->ih->mutex);
+ inotify_remove_watch_locked(watch->ih, watch);
+ mutex_unlock(&watch->ih->mutex);
+}
+
+/**
* inotify_rm_wd - remove a watch from an inotify instance
* @ih: inotify handle
* @wd: watch descriptor to remove
diff --git a/fs/inotify_user.c b/fs/inotify_user.c
index 9bf2f6c09df6..5e009331c01f 100644
--- a/fs/inotify_user.c
+++ b/fs/inotify_user.c
@@ -31,6 +31,7 @@
#include <linux/list.h>
#include <linux/inotify.h>
#include <linux/syscalls.h>
+#include <linux/magic.h>
#include <asm/ioctls.h>
@@ -684,7 +685,8 @@ static int
inotify_get_sb(struct file_system_type *fs_type, int flags,
const char *dev_name, void *data, struct vfsmount *mnt)
{
- return get_sb_pseudo(fs_type, "inotify", NULL, 0xBAD1DEA, mnt);
+ return get_sb_pseudo(fs_type, "inotify", NULL,
+ INOTIFYFS_SUPER_MAGIC, mnt);
}
static struct file_system_type inotify_fs_type = {
diff --git a/fs/ioprio.c b/fs/ioprio.c
index 10d2c211d18b..e4e01bc7f338 100644
--- a/fs/ioprio.c
+++ b/fs/ioprio.c
@@ -25,6 +25,7 @@
#include <linux/capability.h>
#include <linux/syscalls.h>
#include <linux/security.h>
+#include <linux/pid_namespace.h>
static int set_task_ioprio(struct task_struct *task, int ioprio)
{
@@ -77,6 +78,10 @@ asmlinkage long sys_ioprio_set(int which, int who, int ioprio)
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
break;
+ case IOPRIO_CLASS_NONE:
+ if (data)
+ return -EINVAL;
+ break;
default:
return -EINVAL;
}
@@ -93,7 +98,7 @@ asmlinkage long sys_ioprio_set(int which, int who, int ioprio)
if (!who)
p = current;
else
- p = find_task_by_pid(who);
+ p = find_task_by_vpid(who);
if (p)
ret = set_task_ioprio(p, ioprio);
break;
@@ -101,7 +106,7 @@ asmlinkage long sys_ioprio_set(int which, int who, int ioprio)
if (!who)
pgrp = task_pgrp(current);
else
- pgrp = find_pid(who);
+ pgrp = find_vpid(who);
do_each_pid_task(pgrp, PIDTYPE_PGID, p) {
ret = set_task_ioprio(p, ioprio);
if (ret)
@@ -180,7 +185,7 @@ asmlinkage long sys_ioprio_get(int which, int who)
if (!who)
p = current;
else
- p = find_task_by_pid(who);
+ p = find_task_by_vpid(who);
if (p)
ret = get_task_ioprio(p);
break;
@@ -188,7 +193,7 @@ asmlinkage long sys_ioprio_get(int which, int who)
if (!who)
pgrp = task_pgrp(current);
else
- pgrp = find_pid(who);
+ pgrp = find_vpid(who);
do_each_pid_task(pgrp, PIDTYPE_PGID, p) {
tmpio = get_task_ioprio(p);
if (tmpio < 0)
diff --git a/fs/isofs/compress.c b/fs/isofs/compress.c
index 6bbbdb53581d..37dbd6404787 100644
--- a/fs/isofs/compress.c
+++ b/fs/isofs/compress.c
@@ -33,7 +33,7 @@ static char zisofs_sink_page[PAGE_CACHE_SIZE];
* allocation; this avoids failures at block-decompression time.
*/
static void *zisofs_zlib_workspace;
-static struct semaphore zisofs_zlib_semaphore;
+static DEFINE_MUTEX(zisofs_zlib_lock);
/*
* When decompressing, we typically obtain more than one page
@@ -180,9 +180,9 @@ static int zisofs_readpage(struct file *file, struct page *page)
/* First block is special since it may be fractional.
We also wait for it before grabbing the zlib
- semaphore; odds are that the subsequent blocks are
+ mutex; odds are that the subsequent blocks are
going to come in in short order so we don't hold
- the zlib semaphore longer than necessary. */
+ the zlib mutex longer than necessary. */
if ( !bh || (wait_on_buffer(bh), !buffer_uptodate(bh)) ) {
printk(KERN_DEBUG "zisofs: Hit null buffer, fpage = %d, xpage = %d, csize = %ld\n",
@@ -194,7 +194,7 @@ static int zisofs_readpage(struct file *file, struct page *page)
csize -= stream.avail_in;
stream.workspace = zisofs_zlib_workspace;
- down(&zisofs_zlib_semaphore);
+ mutex_lock(&zisofs_zlib_lock);
zerr = zlib_inflateInit(&stream);
if ( zerr != Z_OK ) {
@@ -281,7 +281,7 @@ static int zisofs_readpage(struct file *file, struct page *page)
zlib_inflateEnd(&stream);
z_eio:
- up(&zisofs_zlib_semaphore);
+ mutex_unlock(&zisofs_zlib_lock);
b_eio:
for ( i = 0 ; i < haveblocks ; i++ ) {
@@ -317,31 +317,16 @@ const struct address_space_operations zisofs_aops = {
/* No bmap operation supported */
};
-static int initialized;
-
int __init zisofs_init(void)
{
- if ( initialized ) {
- printk("zisofs_init: called more than once\n");
- return 0;
- }
-
zisofs_zlib_workspace = vmalloc(zlib_inflate_workspacesize());
if ( !zisofs_zlib_workspace )
return -ENOMEM;
- init_MUTEX(&zisofs_zlib_semaphore);
- initialized = 1;
return 0;
}
void zisofs_cleanup(void)
{
- if ( !initialized ) {
- printk("zisofs_cleanup: called without initialization\n");
- return;
- }
-
vfree(zisofs_zlib_workspace);
- initialized = 0;
}
diff --git a/fs/isofs/export.c b/fs/isofs/export.c
index 4af856a7fda7..29f9753ae5e5 100644
--- a/fs/isofs/export.c
+++ b/fs/isofs/export.c
@@ -42,16 +42,6 @@ isofs_export_iget(struct super_block *sb,
return result;
}
-static struct dentry *
-isofs_export_get_dentry(struct super_block *sb, void *vobjp)
-{
- __u32 *objp = vobjp;
- unsigned long block = objp[0];
- unsigned long offset = objp[1];
- __u32 generation = objp[2];
- return isofs_export_iget(sb, block, offset, generation);
-}
-
/* This function is surprisingly simple. The trick is understanding
* that "child" is always a directory. So, to find its parent, you
* simply need to find its ".." entry, normalize its block and offset,
@@ -182,43 +172,44 @@ isofs_export_encode_fh(struct dentry *dentry,
return type;
}
+struct isofs_fid {
+ u32 block;
+ u16 offset;
+ u16 parent_offset;
+ u32 generation;
+ u32 parent_block;
+ u32 parent_generation;
+};
-static struct dentry *
-isofs_export_decode_fh(struct super_block *sb,
- __u32 *fh32,
- int fh_len,
- int fileid_type,
- int (*acceptable)(void *context, struct dentry *de),
- void *context)
+static struct dentry *isofs_fh_to_dentry(struct super_block *sb,
+ struct fid *fid, int fh_len, int fh_type)
{
- __u16 *fh16 = (__u16*)fh32;
- __u32 child[3]; /* The child is what triggered all this. */
- __u32 parent[3]; /* The parent is just along for the ride. */
+ struct isofs_fid *ifid = (struct isofs_fid *)fid;
- if (fh_len < 3 || fileid_type > 2)
+ if (fh_len < 3 || fh_type > 2)
return NULL;
- child[0] = fh32[0];
- child[1] = fh16[2]; /* fh16 [sic] */
- child[2] = fh32[2];
-
- parent[0] = 0;
- parent[1] = 0;
- parent[2] = 0;
- if (fileid_type == 2) {
- if (fh_len > 2) parent[0] = fh32[3];
- parent[1] = fh16[3]; /* fh16 [sic] */
- if (fh_len > 4) parent[2] = fh32[4];
- }
-
- return sb->s_export_op->find_exported_dentry(sb, child, parent,
- acceptable, context);
+ return isofs_export_iget(sb, ifid->block, ifid->offset,
+ ifid->generation);
}
+static struct dentry *isofs_fh_to_parent(struct super_block *sb,
+ struct fid *fid, int fh_len, int fh_type)
+{
+ struct isofs_fid *ifid = (struct isofs_fid *)fid;
+
+ if (fh_type != 2)
+ return NULL;
+
+ return isofs_export_iget(sb,
+ fh_len > 2 ? ifid->parent_block : 0,
+ ifid->parent_offset,
+ fh_len > 4 ? ifid->parent_generation : 0);
+}
-struct export_operations isofs_export_ops = {
- .decode_fh = isofs_export_decode_fh,
+const struct export_operations isofs_export_ops = {
.encode_fh = isofs_export_encode_fh,
- .get_dentry = isofs_export_get_dentry,
+ .fh_to_dentry = isofs_fh_to_dentry,
+ .fh_to_parent = isofs_fh_to_parent,
.get_parent = isofs_export_get_parent,
};
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index 043b470fd3b6..09e3d306e96f 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -3,7 +3,7 @@
*
* (C) 1991 Linus Torvalds - minix filesystem
* 1992, 1993, 1994 Eric Youngdale Modified for ISO 9660 filesystem.
- * 1994 Eberhard Moenkeberg - multi session handling.
+ * 1994 Eberhard Mönkeberg - multi session handling.
* 1995 Mark Dobie - allow mounting of some weird VideoCDs and PhotoCDs.
* 1997 Gordon Chaffee - Joliet CDs
* 1998 Eric Lammerts - ISO 9660 Level 3
@@ -73,7 +73,7 @@ static void isofs_destroy_inode(struct inode *inode)
kmem_cache_free(isofs_inode_cachep, ISOFS_I(inode));
}
-static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags)
+static void init_once(struct kmem_cache *cachep, void *foo)
{
struct iso_inode_info *ei = foo;
diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h
index a07e67b1ea7f..f3213f9f89af 100644
--- a/fs/isofs/isofs.h
+++ b/fs/isofs/isofs.h
@@ -178,4 +178,4 @@ isofs_normalize_block_and_offset(struct iso_directory_record* de,
extern const struct inode_operations isofs_dir_inode_operations;
extern const struct file_operations isofs_dir_operations;
extern const struct address_space_operations isofs_symlink_aops;
-extern struct export_operations isofs_export_ops;
+extern const struct export_operations isofs_export_ops;
diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c
index c8c7e5138a01..e2b4dad39ca9 100644
--- a/fs/isofs/namei.c
+++ b/fs/isofs/namei.c
@@ -158,7 +158,8 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry,
struct dentry *isofs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
int found;
- unsigned long block, offset;
+ unsigned long uninitialized_var(block);
+ unsigned long uninitialized_var(offset);
struct inode *inode;
struct page *page;
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
index a003d50edcdb..8f1f2aa5fb39 100644
--- a/fs/jbd/commit.c
+++ b/fs/jbd/commit.c
@@ -375,7 +375,7 @@ void journal_commit_transaction(journal_t *journal)
struct buffer_head *bh = jh2bh(jh);
jbd_lock_bh_state(bh);
- jbd_slab_free(jh->b_committed_data, bh->b_size);
+ jbd_free(jh->b_committed_data, bh->b_size);
jh->b_committed_data = NULL;
jbd_unlock_bh_state(bh);
}
@@ -466,7 +466,7 @@ void journal_commit_transaction(journal_t *journal)
spin_unlock(&journal->j_list_lock);
if (err)
- __journal_abort_hard(journal);
+ journal_abort(journal, err);
journal_write_revoke_records(journal, commit_transaction);
@@ -524,7 +524,7 @@ void journal_commit_transaction(journal_t *journal)
descriptor = journal_get_descriptor_buffer(journal);
if (!descriptor) {
- __journal_abort_hard(journal);
+ journal_abort(journal, -EIO);
continue;
}
@@ -557,7 +557,7 @@ void journal_commit_transaction(journal_t *journal)
and repeat this loop: we'll fall into the
refile-on-abort condition above. */
if (err) {
- __journal_abort_hard(journal);
+ journal_abort(journal, err);
continue;
}
@@ -748,7 +748,7 @@ wait_for_iobuf:
err = -EIO;
if (err)
- __journal_abort_hard(journal);
+ journal_abort(journal, err);
/* End of a transaction! Finally, we can do checkpoint
processing: any buffers committed as a result of this
@@ -792,14 +792,14 @@ restart_loop:
* Otherwise, we can just throw away the frozen data now.
*/
if (jh->b_committed_data) {
- jbd_slab_free(jh->b_committed_data, bh->b_size);
+ jbd_free(jh->b_committed_data, bh->b_size);
jh->b_committed_data = NULL;
if (jh->b_frozen_data) {
jh->b_committed_data = jh->b_frozen_data;
jh->b_frozen_data = NULL;
}
} else if (jh->b_frozen_data) {
- jbd_slab_free(jh->b_frozen_data, bh->b_size);
+ jbd_free(jh->b_frozen_data, bh->b_size);
jh->b_frozen_data = NULL;
}
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
index 06ab3c10b1b8..5d14243499d4 100644
--- a/fs/jbd/journal.c
+++ b/fs/jbd/journal.c
@@ -35,6 +35,7 @@
#include <linux/kthread.h>
#include <linux/poison.h>
#include <linux/proc_fs.h>
+#include <linux/debugfs.h>
#include <asm/uaccess.h>
#include <asm/page.h>
@@ -83,7 +84,6 @@ EXPORT_SYMBOL(journal_force_commit);
static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *);
static void __journal_abort_soft (journal_t *journal, int errno);
-static int journal_create_jbd_slab(size_t slab_size);
/*
* Helper function used to manage commit timeouts
@@ -218,7 +218,7 @@ static int journal_start_thread(journal_t *journal)
if (IS_ERR(t))
return PTR_ERR(t);
- wait_event(journal->j_wait_done_commit, journal->j_task != 0);
+ wait_event(journal->j_wait_done_commit, journal->j_task != NULL);
return 0;
}
@@ -230,7 +230,8 @@ static void journal_kill_thread(journal_t *journal)
while (journal->j_task) {
wake_up(&journal->j_wait_commit);
spin_unlock(&journal->j_state_lock);
- wait_event(journal->j_wait_done_commit, journal->j_task == 0);
+ wait_event(journal->j_wait_done_commit,
+ journal->j_task == NULL);
spin_lock(&journal->j_state_lock);
}
spin_unlock(&journal->j_state_lock);
@@ -334,10 +335,10 @@ repeat:
char *tmp;
jbd_unlock_bh_state(bh_in);
- tmp = jbd_slab_alloc(bh_in->b_size, GFP_NOFS);
+ tmp = jbd_alloc(bh_in->b_size, GFP_NOFS);
jbd_lock_bh_state(bh_in);
if (jh_in->b_frozen_data) {
- jbd_slab_free(tmp, bh_in->b_size);
+ jbd_free(tmp, bh_in->b_size);
goto repeat;
}
@@ -654,10 +655,9 @@ static journal_t * journal_init_common (void)
journal_t *journal;
int err;
- journal = jbd_kmalloc(sizeof(*journal), GFP_KERNEL);
+ journal = kzalloc(sizeof(*journal), GFP_KERNEL);
if (!journal)
goto fail;
- memset(journal, 0, sizeof(*journal));
init_waitqueue_head(&journal->j_wait_transaction_locked);
init_waitqueue_head(&journal->j_wait_logspace);
@@ -1095,13 +1095,6 @@ int journal_load(journal_t *journal)
}
}
- /*
- * Create a slab for this blocksize
- */
- err = journal_create_jbd_slab(be32_to_cpu(sb->s_blocksize));
- if (err)
- return err;
-
/* Let the recovery code check whether it needs to recover any
* data from the journal. */
if (journal_recover(journal))
@@ -1615,86 +1608,6 @@ int journal_blocks_per_page(struct inode *inode)
}
/*
- * Simple support for retrying memory allocations. Introduced to help to
- * debug different VM deadlock avoidance strategies.
- */
-void * __jbd_kmalloc (const char *where, size_t size, gfp_t flags, int retry)
-{
- return kmalloc(size, flags | (retry ? __GFP_NOFAIL : 0));
-}
-
-/*
- * jbd slab management: create 1k, 2k, 4k, 8k slabs as needed
- * and allocate frozen and commit buffers from these slabs.
- *
- * Reason for doing this is to avoid, SLAB_DEBUG - since it could
- * cause bh to cross page boundary.
- */
-
-#define JBD_MAX_SLABS 5
-#define JBD_SLAB_INDEX(size) (size >> 11)
-
-static struct kmem_cache *jbd_slab[JBD_MAX_SLABS];
-static const char *jbd_slab_names[JBD_MAX_SLABS] = {
- "jbd_1k", "jbd_2k", "jbd_4k", NULL, "jbd_8k"
-};
-
-static void journal_destroy_jbd_slabs(void)
-{
- int i;
-
- for (i = 0; i < JBD_MAX_SLABS; i++) {
- if (jbd_slab[i])
- kmem_cache_destroy(jbd_slab[i]);
- jbd_slab[i] = NULL;
- }
-}
-
-static int journal_create_jbd_slab(size_t slab_size)
-{
- int i = JBD_SLAB_INDEX(slab_size);
-
- BUG_ON(i >= JBD_MAX_SLABS);
-
- /*
- * Check if we already have a slab created for this size
- */
- if (jbd_slab[i])
- return 0;
-
- /*
- * Create a slab and force alignment to be same as slabsize -
- * this will make sure that allocations won't cross the page
- * boundary.
- */
- jbd_slab[i] = kmem_cache_create(jbd_slab_names[i],
- slab_size, slab_size, 0, NULL);
- if (!jbd_slab[i]) {
- printk(KERN_EMERG "JBD: no memory for jbd_slab cache\n");
- return -ENOMEM;
- }
- return 0;
-}
-
-void * jbd_slab_alloc(size_t size, gfp_t flags)
-{
- int idx;
-
- idx = JBD_SLAB_INDEX(size);
- BUG_ON(jbd_slab[idx] == NULL);
- return kmem_cache_alloc(jbd_slab[idx], flags | __GFP_NOFAIL);
-}
-
-void jbd_slab_free(void *ptr, size_t size)
-{
- int idx;
-
- idx = JBD_SLAB_INDEX(size);
- BUG_ON(jbd_slab[idx] == NULL);
- kmem_cache_free(jbd_slab[idx], ptr);
-}
-
-/*
* Journal_head storage management
*/
static struct kmem_cache *journal_head_cache;
@@ -1710,7 +1623,7 @@ static int journal_init_journal_head_cache(void)
journal_head_cache = kmem_cache_create("journal_head",
sizeof(struct journal_head),
0, /* offset */
- 0, /* flags */
+ SLAB_TEMPORARY, /* flags */
NULL); /* ctor */
retval = 0;
if (journal_head_cache == 0) {
@@ -1739,14 +1652,14 @@ static struct journal_head *journal_alloc_journal_head(void)
atomic_inc(&nr_journal_heads);
#endif
ret = kmem_cache_alloc(journal_head_cache, GFP_NOFS);
- if (ret == 0) {
+ if (ret == NULL) {
jbd_debug(1, "out of memory for journal_head\n");
if (time_after(jiffies, last_warning + 5*HZ)) {
printk(KERN_NOTICE "ENOMEM in %s, retrying.\n",
__FUNCTION__);
last_warning = jiffies;
}
- while (ret == 0) {
+ while (ret == NULL) {
yield();
ret = kmem_cache_alloc(journal_head_cache, GFP_NOFS);
}
@@ -1881,13 +1794,13 @@ static void __journal_remove_journal_head(struct buffer_head *bh)
printk(KERN_WARNING "%s: freeing "
"b_frozen_data\n",
__FUNCTION__);
- jbd_slab_free(jh->b_frozen_data, bh->b_size);
+ jbd_free(jh->b_frozen_data, bh->b_size);
}
if (jh->b_committed_data) {
printk(KERN_WARNING "%s: freeing "
"b_committed_data\n",
__FUNCTION__);
- jbd_slab_free(jh->b_committed_data, bh->b_size);
+ jbd_free(jh->b_committed_data, bh->b_size);
}
bh->b_private = NULL;
jh->b_bh = NULL; /* debug, really */
@@ -1939,64 +1852,41 @@ void journal_put_journal_head(struct journal_head *jh)
}
/*
- * /proc tunables
+ * debugfs tunables
*/
-#if defined(CONFIG_JBD_DEBUG)
-int journal_enable_debug;
-EXPORT_SYMBOL(journal_enable_debug);
-#endif
+#ifdef CONFIG_JBD_DEBUG
-#if defined(CONFIG_JBD_DEBUG) && defined(CONFIG_PROC_FS)
+u8 journal_enable_debug __read_mostly;
+EXPORT_SYMBOL(journal_enable_debug);
-static struct proc_dir_entry *proc_jbd_debug;
+static struct dentry *jbd_debugfs_dir;
+static struct dentry *jbd_debug;
-static int read_jbd_debug(char *page, char **start, off_t off,
- int count, int *eof, void *data)
+static void __init jbd_create_debugfs_entry(void)
{
- int ret;
-
- ret = sprintf(page + off, "%d\n", journal_enable_debug);
- *eof = 1;
- return ret;
+ jbd_debugfs_dir = debugfs_create_dir("jbd", NULL);
+ if (jbd_debugfs_dir)
+ jbd_debug = debugfs_create_u8("jbd-debug", S_IRUGO,
+ jbd_debugfs_dir,
+ &journal_enable_debug);
}
-static int write_jbd_debug(struct file *file, const char __user *buffer,
- unsigned long count, void *data)
+static void __exit jbd_remove_debugfs_entry(void)
{
- char buf[32];
-
- if (count > ARRAY_SIZE(buf) - 1)
- count = ARRAY_SIZE(buf) - 1;
- if (copy_from_user(buf, buffer, count))
- return -EFAULT;
- buf[ARRAY_SIZE(buf) - 1] = '\0';
- journal_enable_debug = simple_strtoul(buf, NULL, 10);
- return count;
+ debugfs_remove(jbd_debug);
+ debugfs_remove(jbd_debugfs_dir);
}
-#define JBD_PROC_NAME "sys/fs/jbd-debug"
+#else
-static void __init create_jbd_proc_entry(void)
+static inline void jbd_create_debugfs_entry(void)
{
- proc_jbd_debug = create_proc_entry(JBD_PROC_NAME, 0644, NULL);
- if (proc_jbd_debug) {
- /* Why is this so hard? */
- proc_jbd_debug->read_proc = read_jbd_debug;
- proc_jbd_debug->write_proc = write_jbd_debug;
- }
}
-static void __exit remove_jbd_proc_entry(void)
+static inline void jbd_remove_debugfs_entry(void)
{
- if (proc_jbd_debug)
- remove_proc_entry(JBD_PROC_NAME, NULL);
}
-#else
-
-#define create_jbd_proc_entry() do {} while (0)
-#define remove_jbd_proc_entry() do {} while (0)
-
#endif
struct kmem_cache *jbd_handle_cache;
@@ -2006,7 +1896,7 @@ static int __init journal_init_handle_cache(void)
jbd_handle_cache = kmem_cache_create("journal_handle",
sizeof(handle_t),
0, /* offset */
- 0, /* flags */
+ SLAB_TEMPORARY, /* flags */
NULL); /* ctor */
if (jbd_handle_cache == NULL) {
printk(KERN_EMERG "JBD: failed to create handle cache\n");
@@ -2042,7 +1932,6 @@ static void journal_destroy_caches(void)
journal_destroy_revoke_caches();
journal_destroy_journal_head_cache();
journal_destroy_handle_cache();
- journal_destroy_jbd_slabs();
}
static int __init journal_init(void)
@@ -2054,7 +1943,7 @@ static int __init journal_init(void)
ret = journal_init_caches();
if (ret != 0)
journal_destroy_caches();
- create_jbd_proc_entry();
+ jbd_create_debugfs_entry();
return ret;
}
@@ -2065,7 +1954,7 @@ static void __exit journal_exit(void)
if (n)
printk(KERN_EMERG "JBD: leaked %d journal_heads!\n", n);
#endif
- remove_jbd_proc_entry();
+ jbd_remove_debugfs_entry();
journal_destroy_caches();
}
diff --git a/fs/jbd/recovery.c b/fs/jbd/recovery.c
index 2a5f4b833e35..c5d9694b6a2f 100644
--- a/fs/jbd/recovery.c
+++ b/fs/jbd/recovery.c
@@ -250,10 +250,10 @@ int journal_recover(journal_t *journal)
if (!err)
err = do_one_pass(journal, &info, PASS_REPLAY);
- jbd_debug(0, "JBD: recovery, exit status %d, "
+ jbd_debug(1, "JBD: recovery, exit status %d, "
"recovered transactions %u to %u\n",
err, info.start_transaction, info.end_transaction);
- jbd_debug(0, "JBD: Replayed %d and revoked %d/%d blocks\n",
+ jbd_debug(1, "JBD: Replayed %d and revoked %d/%d blocks\n",
info.nr_replays, info.nr_revoke_hits, info.nr_revokes);
/* Restart the log at the next transaction ID, thus invalidating
@@ -297,7 +297,7 @@ int journal_skip_recovery(journal_t *journal)
#ifdef CONFIG_JBD_DEBUG
int dropped = info.end_transaction - be32_to_cpu(sb->s_sequence);
#endif
- jbd_debug(0,
+ jbd_debug(1,
"JBD: ignoring %d transaction%s from the journal.\n",
dropped, (dropped == 1) ? "" : "s");
journal->j_transaction_sequence = ++info.end_transaction;
diff --git a/fs/jbd/revoke.c b/fs/jbd/revoke.c
index 62e13c8db132..ad2eacf570c6 100644
--- a/fs/jbd/revoke.c
+++ b/fs/jbd/revoke.c
@@ -170,13 +170,15 @@ int __init journal_init_revoke_caches(void)
{
revoke_record_cache = kmem_cache_create("revoke_record",
sizeof(struct jbd_revoke_record_s),
- 0, SLAB_HWCACHE_ALIGN, NULL);
+ 0,
+ SLAB_HWCACHE_ALIGN|SLAB_TEMPORARY,
+ NULL);
if (revoke_record_cache == 0)
return -ENOMEM;
revoke_table_cache = kmem_cache_create("revoke_table",
sizeof(struct jbd_revoke_table_s),
- 0, 0, NULL);
+ 0, SLAB_TEMPORARY, NULL);
if (revoke_table_cache == 0) {
kmem_cache_destroy(revoke_record_cache);
revoke_record_cache = NULL;
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c
index 8df5bac0b7a5..08ff6c7028cc 100644
--- a/fs/jbd/transaction.c
+++ b/fs/jbd/transaction.c
@@ -96,13 +96,12 @@ static int start_this_handle(journal_t *journal, handle_t *handle)
alloc_transaction:
if (!journal->j_running_transaction) {
- new_transaction = jbd_kmalloc(sizeof(*new_transaction),
- GFP_NOFS);
+ new_transaction = kzalloc(sizeof(*new_transaction),
+ GFP_NOFS|__GFP_NOFAIL);
if (!new_transaction) {
ret = -ENOMEM;
goto out;
}
- memset(new_transaction, 0, sizeof(*new_transaction));
}
jbd_debug(3, "New handle %p going live.\n", handle);
@@ -675,7 +674,7 @@ repeat:
JBUFFER_TRACE(jh, "allocate memory for buffer");
jbd_unlock_bh_state(bh);
frozen_buffer =
- jbd_slab_alloc(jh2bh(jh)->b_size,
+ jbd_alloc(jh2bh(jh)->b_size,
GFP_NOFS);
if (!frozen_buffer) {
printk(KERN_EMERG
@@ -735,7 +734,7 @@ done:
out:
if (unlikely(frozen_buffer)) /* It's usually NULL */
- jbd_slab_free(frozen_buffer, bh->b_size);
+ jbd_free(frozen_buffer, bh->b_size);
JBUFFER_TRACE(jh, "exit");
return error;
@@ -888,7 +887,7 @@ int journal_get_undo_access(handle_t *handle, struct buffer_head *bh)
repeat:
if (!jh->b_committed_data) {
- committed_data = jbd_slab_alloc(jh2bh(jh)->b_size, GFP_NOFS);
+ committed_data = jbd_alloc(jh2bh(jh)->b_size, GFP_NOFS);
if (!committed_data) {
printk(KERN_EMERG "%s: No memory for committed data\n",
__FUNCTION__);
@@ -915,7 +914,7 @@ repeat:
out:
journal_put_journal_head(jh);
if (unlikely(committed_data))
- jbd_slab_free(committed_data, bh->b_size);
+ jbd_free(committed_data, bh->b_size);
return err;
}
@@ -1172,7 +1171,7 @@ int journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
}
/* That test should have eliminated the following case: */
- J_ASSERT_JH(jh, jh->b_frozen_data == 0);
+ J_ASSERT_JH(jh, jh->b_frozen_data == NULL);
JBUFFER_TRACE(jh, "file as BJ_Metadata");
spin_lock(&journal->j_list_lock);
@@ -1522,7 +1521,7 @@ static void __journal_temp_unlink_buffer(struct journal_head *jh)
J_ASSERT_JH(jh, jh->b_jlist < BJ_Types);
if (jh->b_jlist != BJ_None)
- J_ASSERT_JH(jh, transaction != 0);
+ J_ASSERT_JH(jh, transaction != NULL);
switch (jh->b_jlist) {
case BJ_None:
@@ -1591,11 +1590,11 @@ __journal_try_to_free_buffer(journal_t *journal, struct buffer_head *bh)
if (buffer_locked(bh) || buffer_dirty(bh))
goto out;
- if (jh->b_next_transaction != 0)
+ if (jh->b_next_transaction != NULL)
goto out;
spin_lock(&journal->j_list_lock);
- if (jh->b_transaction != 0 && jh->b_cp_transaction == 0) {
+ if (jh->b_transaction != NULL && jh->b_cp_transaction == NULL) {
if (jh->b_jlist == BJ_SyncData || jh->b_jlist == BJ_Locked) {
/* A written-back ordered data buffer */
JBUFFER_TRACE(jh, "release data");
@@ -1603,7 +1602,7 @@ __journal_try_to_free_buffer(journal_t *journal, struct buffer_head *bh)
journal_remove_journal_head(bh);
__brelse(bh);
}
- } else if (jh->b_cp_transaction != 0 && jh->b_transaction == 0) {
+ } else if (jh->b_cp_transaction != NULL && jh->b_transaction == NULL) {
/* written-back checkpointed metadata buffer */
if (jh->b_jlist == BJ_None) {
JBUFFER_TRACE(jh, "remove from checkpoint list");
@@ -1963,7 +1962,7 @@ void __journal_file_buffer(struct journal_head *jh,
J_ASSERT_JH(jh, jh->b_jlist < BJ_Types);
J_ASSERT_JH(jh, jh->b_transaction == transaction ||
- jh->b_transaction == 0);
+ jh->b_transaction == NULL);
if (jh->b_transaction && jh->b_jlist == jlist)
return;
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index c0f59d1b13dc..6986f334c643 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -278,7 +278,7 @@ static inline void write_tag_block(int tag_bytes, journal_block_tag_t *tag,
unsigned long long block)
{
tag->t_blocknr = cpu_to_be32(block & (u32)~0);
- if (tag_bytes > JBD_TAG_SIZE32)
+ if (tag_bytes > JBD2_TAG_SIZE32)
tag->t_blocknr_high = cpu_to_be32((block >> 31) >> 1);
}
@@ -384,7 +384,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
struct buffer_head *bh = jh2bh(jh);
jbd_lock_bh_state(bh);
- jbd2_slab_free(jh->b_committed_data, bh->b_size);
+ jbd2_free(jh->b_committed_data, bh->b_size);
jh->b_committed_data = NULL;
jbd_unlock_bh_state(bh);
}
@@ -475,7 +475,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
spin_unlock(&journal->j_list_lock);
if (err)
- __jbd2_journal_abort_hard(journal);
+ jbd2_journal_abort(journal, err);
jbd2_journal_write_revoke_records(journal, commit_transaction);
@@ -533,7 +533,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
descriptor = jbd2_journal_get_descriptor_buffer(journal);
if (!descriptor) {
- __jbd2_journal_abort_hard(journal);
+ jbd2_journal_abort(journal, -EIO);
continue;
}
@@ -566,7 +566,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
and repeat this loop: we'll fall into the
refile-on-abort condition above. */
if (err) {
- __jbd2_journal_abort_hard(journal);
+ jbd2_journal_abort(journal, err);
continue;
}
@@ -757,7 +757,7 @@ wait_for_iobuf:
err = -EIO;
if (err)
- __jbd2_journal_abort_hard(journal);
+ jbd2_journal_abort(journal, err);
/* End of a transaction! Finally, we can do checkpoint
processing: any buffers committed as a result of this
@@ -801,14 +801,14 @@ restart_loop:
* Otherwise, we can just throw away the frozen data now.
*/
if (jh->b_committed_data) {
- jbd2_slab_free(jh->b_committed_data, bh->b_size);
+ jbd2_free(jh->b_committed_data, bh->b_size);
jh->b_committed_data = NULL;
if (jh->b_frozen_data) {
jh->b_committed_data = jh->b_frozen_data;
jh->b_frozen_data = NULL;
}
} else if (jh->b_frozen_data) {
- jbd2_slab_free(jh->b_frozen_data, bh->b_size);
+ jbd2_free(jh->b_frozen_data, bh->b_size);
jh->b_frozen_data = NULL;
}
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index f37324aee817..6ddc5531587c 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -84,7 +84,6 @@ EXPORT_SYMBOL(jbd2_journal_force_commit);
static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *);
static void __journal_abort_soft (journal_t *journal, int errno);
-static int jbd2_journal_create_jbd_slab(size_t slab_size);
/*
* Helper function used to manage commit timeouts
@@ -335,10 +334,10 @@ repeat:
char *tmp;
jbd_unlock_bh_state(bh_in);
- tmp = jbd2_slab_alloc(bh_in->b_size, GFP_NOFS);
+ tmp = jbd2_alloc(bh_in->b_size, GFP_NOFS);
jbd_lock_bh_state(bh_in);
if (jh_in->b_frozen_data) {
- jbd2_slab_free(tmp, bh_in->b_size);
+ jbd2_free(tmp, bh_in->b_size);
goto repeat;
}
@@ -655,10 +654,9 @@ static journal_t * journal_init_common (void)
journal_t *journal;
int err;
- journal = jbd_kmalloc(sizeof(*journal), GFP_KERNEL);
+ journal = kzalloc(sizeof(*journal), GFP_KERNEL|__GFP_NOFAIL);
if (!journal)
goto fail;
- memset(journal, 0, sizeof(*journal));
init_waitqueue_head(&journal->j_wait_transaction_locked);
init_waitqueue_head(&journal->j_wait_logspace);
@@ -672,7 +670,7 @@ static journal_t * journal_init_common (void)
spin_lock_init(&journal->j_list_lock);
spin_lock_init(&journal->j_state_lock);
- journal->j_commit_interval = (HZ * JBD_DEFAULT_MAX_COMMIT_AGE);
+ journal->j_commit_interval = (HZ * JBD2_DEFAULT_MAX_COMMIT_AGE);
/* The journal is marked for error until we succeed with recovery! */
journal->j_flags = JBD2_ABORT;
@@ -1096,13 +1094,6 @@ int jbd2_journal_load(journal_t *journal)
}
}
- /*
- * Create a slab for this blocksize
- */
- err = jbd2_journal_create_jbd_slab(be32_to_cpu(sb->s_blocksize));
- if (err)
- return err;
-
/* Let the recovery code check whether it needs to recover any
* data from the journal. */
if (jbd2_journal_recover(journal))
@@ -1621,89 +1612,9 @@ int jbd2_journal_blocks_per_page(struct inode *inode)
size_t journal_tag_bytes(journal_t *journal)
{
if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT))
- return JBD_TAG_SIZE64;
+ return JBD2_TAG_SIZE64;
else
- return JBD_TAG_SIZE32;
-}
-
-/*
- * Simple support for retrying memory allocations. Introduced to help to
- * debug different VM deadlock avoidance strategies.
- */
-void * __jbd2_kmalloc (const char *where, size_t size, gfp_t flags, int retry)
-{
- return kmalloc(size, flags | (retry ? __GFP_NOFAIL : 0));
-}
-
-/*
- * jbd slab management: create 1k, 2k, 4k, 8k slabs as needed
- * and allocate frozen and commit buffers from these slabs.
- *
- * Reason for doing this is to avoid, SLAB_DEBUG - since it could
- * cause bh to cross page boundary.
- */
-
-#define JBD_MAX_SLABS 5
-#define JBD_SLAB_INDEX(size) (size >> 11)
-
-static struct kmem_cache *jbd_slab[JBD_MAX_SLABS];
-static const char *jbd_slab_names[JBD_MAX_SLABS] = {
- "jbd2_1k", "jbd2_2k", "jbd2_4k", NULL, "jbd2_8k"
-};
-
-static void jbd2_journal_destroy_jbd_slabs(void)
-{
- int i;
-
- for (i = 0; i < JBD_MAX_SLABS; i++) {
- if (jbd_slab[i])
- kmem_cache_destroy(jbd_slab[i]);
- jbd_slab[i] = NULL;
- }
-}
-
-static int jbd2_journal_create_jbd_slab(size_t slab_size)
-{
- int i = JBD_SLAB_INDEX(slab_size);
-
- BUG_ON(i >= JBD_MAX_SLABS);
-
- /*
- * Check if we already have a slab created for this size
- */
- if (jbd_slab[i])
- return 0;
-
- /*
- * Create a slab and force alignment to be same as slabsize -
- * this will make sure that allocations won't cross the page
- * boundary.
- */
- jbd_slab[i] = kmem_cache_create(jbd_slab_names[i],
- slab_size, slab_size, 0, NULL);
- if (!jbd_slab[i]) {
- printk(KERN_EMERG "JBD: no memory for jbd_slab cache\n");
- return -ENOMEM;
- }
- return 0;
-}
-
-void * jbd2_slab_alloc(size_t size, gfp_t flags)
-{
- int idx;
-
- idx = JBD_SLAB_INDEX(size);
- BUG_ON(jbd_slab[idx] == NULL);
- return kmem_cache_alloc(jbd_slab[idx], flags | __GFP_NOFAIL);
-}
-
-void jbd2_slab_free(void *ptr, size_t size)
-{
- int idx;
-
- idx = JBD_SLAB_INDEX(size);
- BUG_ON(jbd_slab[idx] == NULL);
- kmem_cache_free(jbd_slab[idx], ptr);
+ return JBD2_TAG_SIZE32;
}
/*
@@ -1770,7 +1681,7 @@ static void journal_free_journal_head(struct journal_head *jh)
{
#ifdef CONFIG_JBD2_DEBUG
atomic_dec(&nr_journal_heads);
- memset(jh, JBD_POISON_FREE, sizeof(*jh));
+ memset(jh, JBD2_POISON_FREE, sizeof(*jh));
#endif
kmem_cache_free(jbd2_journal_head_cache, jh);
}
@@ -1893,13 +1804,13 @@ static void __journal_remove_journal_head(struct buffer_head *bh)
printk(KERN_WARNING "%s: freeing "
"b_frozen_data\n",
__FUNCTION__);
- jbd2_slab_free(jh->b_frozen_data, bh->b_size);
+ jbd2_free(jh->b_frozen_data, bh->b_size);
}
if (jh->b_committed_data) {
printk(KERN_WARNING "%s: freeing "
"b_committed_data\n",
__FUNCTION__);
- jbd2_slab_free(jh->b_committed_data, bh->b_size);
+ jbd2_free(jh->b_committed_data, bh->b_size);
}
bh->b_private = NULL;
jh->b_bh = NULL; /* debug, really */
@@ -1953,16 +1864,14 @@ void jbd2_journal_put_journal_head(struct journal_head *jh)
/*
* debugfs tunables
*/
-#if defined(CONFIG_JBD2_DEBUG)
-u8 jbd2_journal_enable_debug;
+#ifdef CONFIG_JBD2_DEBUG
+u8 jbd2_journal_enable_debug __read_mostly;
EXPORT_SYMBOL(jbd2_journal_enable_debug);
-#endif
-
-#if defined(CONFIG_JBD2_DEBUG) && defined(CONFIG_DEBUG_FS)
#define JBD2_DEBUG_NAME "jbd2-debug"
-struct dentry *jbd2_debugfs_dir, *jbd2_debug;
+static struct dentry *jbd2_debugfs_dir;
+static struct dentry *jbd2_debug;
static void __init jbd2_create_debugfs_entry(void)
{
@@ -1975,24 +1884,18 @@ static void __init jbd2_create_debugfs_entry(void)
static void __exit jbd2_remove_debugfs_entry(void)
{
- if (jbd2_debug)
- debugfs_remove(jbd2_debug);
- if (jbd2_debugfs_dir)
- debugfs_remove(jbd2_debugfs_dir);
+ debugfs_remove(jbd2_debug);
+ debugfs_remove(jbd2_debugfs_dir);
}
#else
static void __init jbd2_create_debugfs_entry(void)
{
- do {
- } while (0);
}
static void __exit jbd2_remove_debugfs_entry(void)
{
- do {
- } while (0);
}
#endif
@@ -2040,7 +1943,6 @@ static void jbd2_journal_destroy_caches(void)
jbd2_journal_destroy_revoke_caches();
jbd2_journal_destroy_jbd2_journal_head_cache();
jbd2_journal_destroy_handle_cache();
- jbd2_journal_destroy_jbd_slabs();
}
static int __init journal_init(void)
diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c
index b50be8a044eb..d0ce627539ef 100644
--- a/fs/jbd2/recovery.c
+++ b/fs/jbd2/recovery.c
@@ -311,7 +311,7 @@ int jbd2_journal_skip_recovery(journal_t *journal)
static inline unsigned long long read_tag_block(int tag_bytes, journal_block_tag_t *tag)
{
unsigned long long block = be32_to_cpu(tag->t_blocknr);
- if (tag_bytes > JBD_TAG_SIZE32)
+ if (tag_bytes > JBD2_TAG_SIZE32)
block |= (u64)be32_to_cpu(tag->t_blocknr_high) << 32;
return block;
}
diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c
index 01d88975e0c5..3595fd432d5b 100644
--- a/fs/jbd2/revoke.c
+++ b/fs/jbd2/revoke.c
@@ -352,7 +352,7 @@ int jbd2_journal_revoke(handle_t *handle, unsigned long long blocknr,
if (bh)
BUFFER_TRACE(bh, "found on hash");
}
-#ifdef JBD_EXPENSIVE_CHECKING
+#ifdef JBD2_EXPENSIVE_CHECKING
else {
struct buffer_head *bh2;
@@ -453,7 +453,7 @@ int jbd2_journal_cancel_revoke(handle_t *handle, struct journal_head *jh)
}
}
-#ifdef JBD_EXPENSIVE_CHECKING
+#ifdef JBD2_EXPENSIVE_CHECKING
/* There better not be one left behind by now! */
record = find_revoke_record(journal, bh->b_blocknr);
J_ASSERT_JH(jh, record == NULL);
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
index 7946ff43fc40..b1fcf2b3dca3 100644
--- a/fs/jbd2/transaction.c
+++ b/fs/jbd2/transaction.c
@@ -96,13 +96,12 @@ static int start_this_handle(journal_t *journal, handle_t *handle)
alloc_transaction:
if (!journal->j_running_transaction) {
- new_transaction = jbd_kmalloc(sizeof(*new_transaction),
- GFP_NOFS);
+ new_transaction = kzalloc(sizeof(*new_transaction),
+ GFP_NOFS|__GFP_NOFAIL);
if (!new_transaction) {
ret = -ENOMEM;
goto out;
}
- memset(new_transaction, 0, sizeof(*new_transaction));
}
jbd_debug(3, "New handle %p going live.\n", handle);
@@ -236,7 +235,7 @@ out:
/* Allocate a new handle. This should probably be in a slab... */
static handle_t *new_handle(int nblocks)
{
- handle_t *handle = jbd_alloc_handle(GFP_NOFS);
+ handle_t *handle = jbd2_alloc_handle(GFP_NOFS);
if (!handle)
return NULL;
memset(handle, 0, sizeof(*handle));
@@ -282,7 +281,7 @@ handle_t *jbd2_journal_start(journal_t *journal, int nblocks)
err = start_this_handle(journal, handle);
if (err < 0) {
- jbd_free_handle(handle);
+ jbd2_free_handle(handle);
current->journal_info = NULL;
handle = ERR_PTR(err);
}
@@ -668,7 +667,7 @@ repeat:
JBUFFER_TRACE(jh, "allocate memory for buffer");
jbd_unlock_bh_state(bh);
frozen_buffer =
- jbd2_slab_alloc(jh2bh(jh)->b_size,
+ jbd2_alloc(jh2bh(jh)->b_size,
GFP_NOFS);
if (!frozen_buffer) {
printk(KERN_EMERG
@@ -728,7 +727,7 @@ done:
out:
if (unlikely(frozen_buffer)) /* It's usually NULL */
- jbd2_slab_free(frozen_buffer, bh->b_size);
+ jbd2_free(frozen_buffer, bh->b_size);
JBUFFER_TRACE(jh, "exit");
return error;
@@ -881,7 +880,7 @@ int jbd2_journal_get_undo_access(handle_t *handle, struct buffer_head *bh)
repeat:
if (!jh->b_committed_data) {
- committed_data = jbd2_slab_alloc(jh2bh(jh)->b_size, GFP_NOFS);
+ committed_data = jbd2_alloc(jh2bh(jh)->b_size, GFP_NOFS);
if (!committed_data) {
printk(KERN_EMERG "%s: No memory for committed data\n",
__FUNCTION__);
@@ -908,7 +907,7 @@ repeat:
out:
jbd2_journal_put_journal_head(jh);
if (unlikely(committed_data))
- jbd2_slab_free(committed_data, bh->b_size);
+ jbd2_free(committed_data, bh->b_size);
return err;
}
@@ -1411,7 +1410,7 @@ int jbd2_journal_stop(handle_t *handle)
spin_unlock(&journal->j_state_lock);
}
- jbd_free_handle(handle);
+ jbd2_free_handle(handle);
return err;
}
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c
index 8ec9323e830a..77fc5838609c 100644
--- a/fs/jffs2/acl.c
+++ b/fs/jffs2/acl.c
@@ -228,11 +228,28 @@ struct posix_acl *jffs2_get_acl(struct inode *inode, int type)
return acl;
}
+static int __jffs2_set_acl(struct inode *inode, int xprefix, struct posix_acl *acl)
+{
+ char *value = NULL;
+ size_t size = 0;
+ int rc;
+
+ if (acl) {
+ value = jffs2_acl_to_medium(acl, &size);
+ if (IS_ERR(value))
+ return PTR_ERR(value);
+ }
+ rc = do_jffs2_setxattr(inode, xprefix, "", value, size, 0);
+ if (!value && rc == -ENODATA)
+ rc = 0;
+ kfree(value);
+
+ return rc;
+}
+
static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
{
struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
- size_t size = 0;
- char *value = NULL;
int rc, xprefix;
if (S_ISLNK(inode->i_mode))
@@ -267,17 +284,7 @@ static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
default:
return -EINVAL;
}
- if (acl) {
- value = jffs2_acl_to_medium(acl, &size);
- if (IS_ERR(value))
- return PTR_ERR(value);
- }
-
- rc = do_jffs2_setxattr(inode, xprefix, "", value, size, 0);
- if (!value && rc == -ENODATA)
- rc = 0;
- if (value)
- kfree(value);
+ rc = __jffs2_set_acl(inode, xprefix, acl);
if (!rc) {
switch(type) {
case ACL_TYPE_ACCESS:
@@ -312,38 +319,60 @@ int jffs2_permission(struct inode *inode, int mask, struct nameidata *nd)
return generic_permission(inode, mask, jffs2_check_acl);
}
-int jffs2_init_acl(struct inode *inode, struct posix_acl *acl)
+int jffs2_init_acl_pre(struct inode *dir_i, struct inode *inode, int *i_mode)
{
struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
- struct posix_acl *clone;
- mode_t mode;
- int rc = 0;
+ struct posix_acl *acl, *clone;
+ int rc;
- f->i_acl_access = JFFS2_ACL_NOT_CACHED;
- f->i_acl_default = JFFS2_ACL_NOT_CACHED;
+ f->i_acl_default = NULL;
+ f->i_acl_access = NULL;
+
+ if (S_ISLNK(*i_mode))
+ return 0; /* Symlink always has no-ACL */
+
+ acl = jffs2_get_acl(dir_i, ACL_TYPE_DEFAULT);
+ if (IS_ERR(acl))
+ return PTR_ERR(acl);
+
+ if (!acl) {
+ *i_mode &= ~current->fs->umask;
+ } else {
+ if (S_ISDIR(*i_mode))
+ jffs2_iset_acl(inode, &f->i_acl_default, acl);
- if (acl) {
- if (S_ISDIR(inode->i_mode)) {
- rc = jffs2_set_acl(inode, ACL_TYPE_DEFAULT, acl);
- if (rc)
- goto cleanup;
- }
clone = posix_acl_clone(acl, GFP_KERNEL);
- rc = -ENOMEM;
if (!clone)
- goto cleanup;
- mode = inode->i_mode;
- rc = posix_acl_create_masq(clone, &mode);
- if (rc >= 0) {
- inode->i_mode = mode;
- if (rc > 0)
- rc = jffs2_set_acl(inode, ACL_TYPE_ACCESS, clone);
- }
+ return -ENOMEM;
+ rc = posix_acl_create_masq(clone, (mode_t *)i_mode);
+ if (rc < 0)
+ return rc;
+ if (rc > 0)
+ jffs2_iset_acl(inode, &f->i_acl_access, clone);
+
posix_acl_release(clone);
}
- cleanup:
- posix_acl_release(acl);
- return rc;
+ return 0;
+}
+
+int jffs2_init_acl_post(struct inode *inode)
+{
+ struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
+ int rc;
+
+ if (f->i_acl_default) {
+ rc = __jffs2_set_acl(inode, JFFS2_XPREFIX_ACL_DEFAULT, f->i_acl_default);
+ if (rc)
+ return rc;
+ }
+
+ if (f->i_acl_access) {
+ rc = __jffs2_set_acl(inode, JFFS2_XPREFIX_ACL_ACCESS, f->i_acl_access);
+ if (rc)
+ return rc;
+ }
+
+ return 0;
}
void jffs2_clear_acl(struct jffs2_inode_info *f)
diff --git a/fs/jffs2/acl.h b/fs/jffs2/acl.h
index 90a2dbf59051..76c6ebd1acd9 100644
--- a/fs/jffs2/acl.h
+++ b/fs/jffs2/acl.h
@@ -31,7 +31,8 @@ struct jffs2_acl_header {
extern struct posix_acl *jffs2_get_acl(struct inode *inode, int type);
extern int jffs2_permission(struct inode *, int, struct nameidata *);
extern int jffs2_acl_chmod(struct inode *);
-extern int jffs2_init_acl(struct inode *, struct posix_acl *);
+extern int jffs2_init_acl_pre(struct inode *, struct inode *, int *);
+extern int jffs2_init_acl_post(struct inode *);
extern void jffs2_clear_acl(struct jffs2_inode_info *);
extern struct xattr_handler jffs2_acl_access_xattr_handler;
@@ -39,10 +40,11 @@ extern struct xattr_handler jffs2_acl_default_xattr_handler;
#else
-#define jffs2_get_acl(inode, type) (NULL)
-#define jffs2_permission NULL
-#define jffs2_acl_chmod(inode) (0)
-#define jffs2_init_acl(inode,dir) (0)
+#define jffs2_get_acl(inode, type) (NULL)
+#define jffs2_permission (NULL)
+#define jffs2_acl_chmod(inode) (0)
+#define jffs2_init_acl_pre(dir_i,inode,mode) (0)
+#define jffs2_init_acl_post(inode) (0)
#define jffs2_clear_acl(f)
#endif /* CONFIG_JFFS2_FS_POSIX_ACL */
diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h
index 2a49f2c51a9f..4130adabd76e 100644
--- a/fs/jffs2/debug.h
+++ b/fs/jffs2/debug.h
@@ -80,28 +80,28 @@
#define JFFS2_ERROR(fmt, ...) \
do { \
printk(JFFS2_ERR_MSG_PREFIX \
- " (%d) %s: " fmt, current->pid, \
+ " (%d) %s: " fmt, task_pid_nr(current), \
__FUNCTION__ , ##__VA_ARGS__); \
} while(0)
#define JFFS2_WARNING(fmt, ...) \
do { \
printk(JFFS2_WARN_MSG_PREFIX \
- " (%d) %s: " fmt, current->pid, \
+ " (%d) %s: " fmt, task_pid_nr(current), \
__FUNCTION__ , ##__VA_ARGS__); \
} while(0)
#define JFFS2_NOTICE(fmt, ...) \
do { \
printk(JFFS2_NOTICE_MSG_PREFIX \
- " (%d) %s: " fmt, current->pid, \
+ " (%d) %s: " fmt, task_pid_nr(current), \
__FUNCTION__ , ##__VA_ARGS__); \
} while(0)
#define JFFS2_DEBUG(fmt, ...) \
do { \
printk(JFFS2_DBG_MSG_PREFIX \
- " (%d) %s: " fmt, current->pid, \
+ " (%d) %s: " fmt, task_pid_nr(current), \
__FUNCTION__ , ##__VA_ARGS__); \
} while(0)
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index 8353eb9c1799..787e392ffd41 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -182,7 +182,6 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode,
struct jffs2_inode_info *f, *dir_f;
struct jffs2_sb_info *c;
struct inode *inode;
- struct posix_acl *acl;
int ret;
ri = jffs2_alloc_raw_inode();
@@ -193,7 +192,7 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode,
D1(printk(KERN_DEBUG "jffs2_create()\n"));
- inode = jffs2_new_inode(dir_i, mode, ri, &acl);
+ inode = jffs2_new_inode(dir_i, mode, ri);
if (IS_ERR(inode)) {
D1(printk(KERN_DEBUG "jffs2_new_inode() failed\n"));
@@ -211,14 +210,6 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode,
ret = jffs2_do_create(c, dir_f, f, ri,
dentry->d_name.name, dentry->d_name.len);
-
- if (ret)
- goto fail_acl;
-
- ret = jffs2_init_security(inode, dir_i);
- if (ret)
- goto fail_acl;
- ret = jffs2_init_acl(inode, acl);
if (ret)
goto fail;
@@ -231,8 +222,6 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode,
inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->nlink, inode->i_mapping->nrpages));
return 0;
- fail_acl:
- posix_acl_release(acl);
fail:
make_bad_inode(inode);
iput(inode);
@@ -309,7 +298,6 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
struct jffs2_full_dirent *fd;
int namelen;
uint32_t alloclen;
- struct posix_acl *acl;
int ret, targetlen = strlen(target);
/* FIXME: If you care. We'd need to use frags for the target
@@ -336,7 +324,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
return ret;
}
- inode = jffs2_new_inode(dir_i, S_IFLNK | S_IRWXUGO, ri, &acl);
+ inode = jffs2_new_inode(dir_i, S_IFLNK | S_IRWXUGO, ri);
if (IS_ERR(inode)) {
jffs2_free_raw_inode(ri);
@@ -366,7 +354,6 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
up(&f->sem);
jffs2_complete_reservation(c);
jffs2_clear_inode(inode);
- posix_acl_release(acl);
return PTR_ERR(fn);
}
@@ -377,7 +364,6 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
up(&f->sem);
jffs2_complete_reservation(c);
jffs2_clear_inode(inode);
- posix_acl_release(acl);
return -ENOMEM;
}
@@ -395,10 +381,9 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
ret = jffs2_init_security(inode, dir_i);
if (ret) {
jffs2_clear_inode(inode);
- posix_acl_release(acl);
return ret;
}
- ret = jffs2_init_acl(inode, acl);
+ ret = jffs2_init_acl_post(inode);
if (ret) {
jffs2_clear_inode(inode);
return ret;
@@ -476,7 +461,6 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
struct jffs2_full_dirent *fd;
int namelen;
uint32_t alloclen;
- struct posix_acl *acl;
int ret;
mode |= S_IFDIR;
@@ -499,7 +483,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
return ret;
}
- inode = jffs2_new_inode(dir_i, mode, ri, &acl);
+ inode = jffs2_new_inode(dir_i, mode, ri);
if (IS_ERR(inode)) {
jffs2_free_raw_inode(ri);
@@ -526,7 +510,6 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
up(&f->sem);
jffs2_complete_reservation(c);
jffs2_clear_inode(inode);
- posix_acl_release(acl);
return PTR_ERR(fn);
}
/* No data here. Only a metadata node, which will be
@@ -540,10 +523,9 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
ret = jffs2_init_security(inode, dir_i);
if (ret) {
jffs2_clear_inode(inode);
- posix_acl_release(acl);
return ret;
}
- ret = jffs2_init_acl(inode, acl);
+ ret = jffs2_init_acl_post(inode);
if (ret) {
jffs2_clear_inode(inode);
return ret;
@@ -639,7 +621,6 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
union jffs2_device_node dev;
int devlen = 0;
uint32_t alloclen;
- struct posix_acl *acl;
int ret;
if (!new_valid_dev(rdev))
@@ -666,7 +647,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
return ret;
}
- inode = jffs2_new_inode(dir_i, mode, ri, &acl);
+ inode = jffs2_new_inode(dir_i, mode, ri);
if (IS_ERR(inode)) {
jffs2_free_raw_inode(ri);
@@ -695,7 +676,6 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
up(&f->sem);
jffs2_complete_reservation(c);
jffs2_clear_inode(inode);
- posix_acl_release(acl);
return PTR_ERR(fn);
}
/* No data here. Only a metadata node, which will be
@@ -709,10 +689,9 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
ret = jffs2_init_security(inode, dir_i);
if (ret) {
jffs2_clear_inode(inode);
- posix_acl_release(acl);
return ret;
}
- ret = jffs2_init_acl(inode, acl);
+ ret = jffs2_init_acl_post(inode);
if (ret) {
jffs2_clear_inode(inode);
return ret;
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index c2530197be0c..f9c5dd6f4b64 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -19,10 +19,12 @@
#include <linux/jffs2.h>
#include "nodelist.h"
-static int jffs2_commit_write (struct file *filp, struct page *pg,
- unsigned start, unsigned end);
-static int jffs2_prepare_write (struct file *filp, struct page *pg,
- unsigned start, unsigned end);
+static int jffs2_write_end(struct file *filp, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *pg, void *fsdata);
+static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata);
static int jffs2_readpage (struct file *filp, struct page *pg);
int jffs2_fsync(struct file *filp, struct dentry *dentry, int datasync)
@@ -65,8 +67,8 @@ const struct inode_operations jffs2_file_inode_operations =
const struct address_space_operations jffs2_file_address_operations =
{
.readpage = jffs2_readpage,
- .prepare_write =jffs2_prepare_write,
- .commit_write = jffs2_commit_write
+ .write_begin = jffs2_write_begin,
+ .write_end = jffs2_write_end,
};
static int jffs2_do_readpage_nolock (struct inode *inode, struct page *pg)
@@ -119,15 +121,23 @@ static int jffs2_readpage (struct file *filp, struct page *pg)
return ret;
}
-static int jffs2_prepare_write (struct file *filp, struct page *pg,
- unsigned start, unsigned end)
+static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
{
- struct inode *inode = pg->mapping->host;
+ struct page *pg;
+ struct inode *inode = mapping->host;
struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
- uint32_t pageofs = pg->index << PAGE_CACHE_SHIFT;
+ pgoff_t index = pos >> PAGE_CACHE_SHIFT;
+ uint32_t pageofs = pos & (PAGE_CACHE_SIZE - 1);
int ret = 0;
- D1(printk(KERN_DEBUG "jffs2_prepare_write()\n"));
+ pg = __grab_cache_page(mapping, index);
+ if (!pg)
+ return -ENOMEM;
+ *pagep = pg;
+
+ D1(printk(KERN_DEBUG "jffs2_write_begin()\n"));
if (pageofs > inode->i_size) {
/* Make new hole frag from old EOF to new page */
@@ -142,7 +152,7 @@ static int jffs2_prepare_write (struct file *filp, struct page *pg,
ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len,
ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
if (ret)
- return ret;
+ goto out_page;
down(&f->sem);
memset(&ri, 0, sizeof(ri));
@@ -172,7 +182,7 @@ static int jffs2_prepare_write (struct file *filp, struct page *pg,
ret = PTR_ERR(fn);
jffs2_complete_reservation(c);
up(&f->sem);
- return ret;
+ goto out_page;
}
ret = jffs2_add_full_dnode_to_inode(c, f, fn);
if (f->metadata) {
@@ -181,65 +191,79 @@ static int jffs2_prepare_write (struct file *filp, struct page *pg,
f->metadata = NULL;
}
if (ret) {
- D1(printk(KERN_DEBUG "Eep. add_full_dnode_to_inode() failed in prepare_write, returned %d\n", ret));
+ D1(printk(KERN_DEBUG "Eep. add_full_dnode_to_inode() failed in write_begin, returned %d\n", ret));
jffs2_mark_node_obsolete(c, fn->raw);
jffs2_free_full_dnode(fn);
jffs2_complete_reservation(c);
up(&f->sem);
- return ret;
+ goto out_page;
}
jffs2_complete_reservation(c);
inode->i_size = pageofs;
up(&f->sem);
}
- /* Read in the page if it wasn't already present, unless it's a whole page */
- if (!PageUptodate(pg) && (start || end < PAGE_CACHE_SIZE)) {
+ /*
+ * Read in the page if it wasn't already present. Cannot optimize away
+ * the whole page write case until jffs2_write_end can handle the
+ * case of a short-copy.
+ */
+ if (!PageUptodate(pg)) {
down(&f->sem);
ret = jffs2_do_readpage_nolock(inode, pg);
up(&f->sem);
+ if (ret)
+ goto out_page;
}
- D1(printk(KERN_DEBUG "end prepare_write(). pg->flags %lx\n", pg->flags));
+ D1(printk(KERN_DEBUG "end write_begin(). pg->flags %lx\n", pg->flags));
+ return ret;
+
+out_page:
+ unlock_page(pg);
+ page_cache_release(pg);
return ret;
}
-static int jffs2_commit_write (struct file *filp, struct page *pg,
- unsigned start, unsigned end)
+static int jffs2_write_end(struct file *filp, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *pg, void *fsdata)
{
/* Actually commit the write from the page cache page we're looking at.
* For now, we write the full page out each time. It sucks, but it's simple
*/
- struct inode *inode = pg->mapping->host;
+ struct inode *inode = mapping->host;
struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
struct jffs2_raw_inode *ri;
+ unsigned start = pos & (PAGE_CACHE_SIZE - 1);
+ unsigned end = start + copied;
unsigned aligned_start = start & ~3;
int ret = 0;
uint32_t writtenlen = 0;
- D1(printk(KERN_DEBUG "jffs2_commit_write(): ino #%lu, page at 0x%lx, range %d-%d, flags %lx\n",
+ D1(printk(KERN_DEBUG "jffs2_write_end(): ino #%lu, page at 0x%lx, range %d-%d, flags %lx\n",
inode->i_ino, pg->index << PAGE_CACHE_SHIFT, start, end, pg->flags));
+ /* We need to avoid deadlock with page_cache_read() in
+ jffs2_garbage_collect_pass(). So the page must be
+ up to date to prevent page_cache_read() from trying
+ to re-lock it. */
+ BUG_ON(!PageUptodate(pg));
+
if (end == PAGE_CACHE_SIZE) {
- if (!start) {
- /* We need to avoid deadlock with page_cache_read() in
- jffs2_garbage_collect_pass(). So we have to mark the
- page up to date, to prevent page_cache_read() from
- trying to re-lock it. */
- SetPageUptodate(pg);
- } else {
- /* When writing out the end of a page, write out the
- _whole_ page. This helps to reduce the number of
- nodes in files which have many short writes, like
- syslog files. */
- start = aligned_start = 0;
- }
+ /* When writing out the end of a page, write out the
+ _whole_ page. This helps to reduce the number of
+ nodes in files which have many short writes, like
+ syslog files. */
+ aligned_start = 0;
}
ri = jffs2_alloc_raw_inode();
if (!ri) {
- D1(printk(KERN_DEBUG "jffs2_commit_write(): Allocation of raw inode failed\n"));
+ D1(printk(KERN_DEBUG "jffs2_write_end(): Allocation of raw inode failed\n"));
+ unlock_page(pg);
+ page_cache_release(pg);
return -ENOMEM;
}
@@ -267,14 +291,11 @@ static int jffs2_commit_write (struct file *filp, struct page *pg,
}
/* Adjust writtenlen for the padding we did, so we don't confuse our caller */
- if (writtenlen < (start&3))
- writtenlen = 0;
- else
- writtenlen -= (start&3);
+ writtenlen -= min(writtenlen, (start - aligned_start));
if (writtenlen) {
- if (inode->i_size < (pg->index << PAGE_CACHE_SHIFT) + start + writtenlen) {
- inode->i_size = (pg->index << PAGE_CACHE_SHIFT) + start + writtenlen;
+ if (inode->i_size < pos + writtenlen) {
+ inode->i_size = pos + writtenlen;
inode->i_blocks = (inode->i_size + 511) >> 9;
inode->i_ctime = inode->i_mtime = ITIME(je32_to_cpu(ri->ctime));
@@ -287,11 +308,14 @@ static int jffs2_commit_write (struct file *filp, struct page *pg,
/* generic_file_write has written more to the page cache than we've
actually written to the medium. Mark the page !Uptodate so that
it gets reread */
- D1(printk(KERN_DEBUG "jffs2_commit_write(): Not all bytes written. Marking page !uptodate\n"));
+ D1(printk(KERN_DEBUG "jffs2_write_end(): Not all bytes written. Marking page !uptodate\n"));
SetPageError(pg);
ClearPageUptodate(pg);
}
- D1(printk(KERN_DEBUG "jffs2_commit_write() returning %d\n",start+writtenlen==end?0:ret));
- return start+writtenlen==end?0:ret;
+ D1(printk(KERN_DEBUG "jffs2_write_end() returning %d\n",
+ writtenlen > 0 ? writtenlen : ret));
+ unlock_page(pg);
+ page_cache_release(pg);
+ return writtenlen > 0 ? writtenlen : ret;
}
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index ed85f9afdbc8..d2e06f7ea96f 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -402,8 +402,7 @@ void jffs2_write_super (struct super_block *sb)
/* jffs2_new_inode: allocate a new inode and inocache, add it to the hash,
fill in the raw_inode while you're at it. */
-struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_inode *ri,
- struct posix_acl **acl)
+struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_inode *ri)
{
struct inode *inode;
struct super_block *sb = dir_i->i_sb;
@@ -438,19 +437,11 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i
/* POSIX ACLs have to be processed now, at least partly.
The umask is only applied if there's no default ACL */
- if (!S_ISLNK(mode)) {
- *acl = jffs2_get_acl(dir_i, ACL_TYPE_DEFAULT);
- if (IS_ERR(*acl)) {
- make_bad_inode(inode);
- iput(inode);
- inode = (void *)*acl;
- *acl = NULL;
- return inode;
- }
- if (!(*acl))
- mode &= ~current->fs->umask;
- } else {
- *acl = NULL;
+ ret = jffs2_init_acl_pre(dir_i, inode, &mode);
+ if (ret) {
+ make_bad_inode(inode);
+ iput(inode);
+ return ERR_PTR(ret);
}
ret = jffs2_do_new_inode (c, f, mode, ri);
if (ret) {
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
index f6743a915cf3..bf64686cf098 100644
--- a/fs/jffs2/os-linux.h
+++ b/fs/jffs2/os-linux.h
@@ -173,15 +173,13 @@ int jffs2_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
extern const struct inode_operations jffs2_symlink_inode_operations;
/* fs.c */
-struct posix_acl;
-
int jffs2_setattr (struct dentry *, struct iattr *);
int jffs2_do_setattr (struct inode *, struct iattr *);
void jffs2_read_inode (struct inode *);
void jffs2_clear_inode (struct inode *);
void jffs2_dirty_inode(struct inode *inode);
struct inode *jffs2_new_inode (struct inode *dir_i, int mode,
- struct jffs2_raw_inode *ri, struct posix_acl **acl);
+ struct jffs2_raw_inode *ri);
int jffs2_statfs (struct dentry *, struct kstatfs *);
void jffs2_write_super (struct super_block *);
int jffs2_remount_fs (struct super_block *, int *, char *);
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index be2b70c2ec16..ffa447511e6a 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -43,7 +43,7 @@ static void jffs2_destroy_inode(struct inode *inode)
kmem_cache_free(jffs2_inode_cachep, JFFS2_INODE_INFO(inode));
}
-static void jffs2_i_init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
+static void jffs2_i_init_once(struct kmem_cache *cachep, void *foo)
{
struct jffs2_inode_info *ei = (struct jffs2_inode_info *) foo;
diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c
index 2f5695446d0f..147e2cbee9e4 100644
--- a/fs/jffs2/write.c
+++ b/fs/jffs2/write.c
@@ -465,6 +465,14 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
up(&f->sem);
jffs2_complete_reservation(c);
+
+ ret = jffs2_init_security(&f->vfs_inode, &dir_f->vfs_inode);
+ if (ret)
+ return ret;
+ ret = jffs2_init_acl_post(&f->vfs_inode);
+ if (ret)
+ return ret;
+
ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c
index 3467dde27e5a..4672013802e1 100644
--- a/fs/jfs/inode.c
+++ b/fs/jfs/inode.c
@@ -255,7 +255,7 @@ int jfs_get_block(struct inode *ip, sector_t lblock,
static int jfs_writepage(struct page *page, struct writeback_control *wbc)
{
- return nobh_writepage(page, jfs_get_block, wbc);
+ return block_write_full_page(page, jfs_get_block, wbc);
}
static int jfs_writepages(struct address_space *mapping,
@@ -275,10 +275,12 @@ static int jfs_readpages(struct file *file, struct address_space *mapping,
return mpage_readpages(mapping, pages, nr_pages, jfs_get_block);
}
-static int jfs_prepare_write(struct file *file,
- struct page *page, unsigned from, unsigned to)
+static int jfs_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
{
- return nobh_prepare_write(page, from, to, jfs_get_block);
+ return nobh_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
+ jfs_get_block);
}
static sector_t jfs_bmap(struct address_space *mapping, sector_t block)
@@ -302,8 +304,8 @@ const struct address_space_operations jfs_aops = {
.writepage = jfs_writepage,
.writepages = jfs_writepages,
.sync_page = block_sync_page,
- .prepare_write = jfs_prepare_write,
- .commit_write = nobh_commit_write,
+ .write_begin = jfs_write_begin,
+ .write_end = nobh_write_end,
.bmap = jfs_bmap,
.direct_IO = jfs_direct_IO,
};
@@ -356,7 +358,7 @@ void jfs_truncate(struct inode *ip)
{
jfs_info("jfs_truncate: size = 0x%lx", (ulong) ip->i_size);
- nobh_truncate_page(ip->i_mapping, ip->i_size);
+ nobh_truncate_page(ip->i_mapping, ip->i_size, jfs_get_block);
IWRITE_LOCK(ip, RDWRLOCK_NORMAL);
jfs_truncate_nolock(ip, ip->i_size);
diff --git a/fs/jfs/ioctl.c b/fs/jfs/ioctl.c
index 3c8663bea98c..dfda12a073e1 100644
--- a/fs/jfs/ioctl.c
+++ b/fs/jfs/ioctl.c
@@ -79,6 +79,9 @@ int jfs_ioctl(struct inode * inode, struct file * filp, unsigned int cmd,
if (!S_ISDIR(inode->i_mode))
flags &= ~JFS_DIRSYNC_FL;
+ /* Is it quota file? Do not allow user to mess with it */
+ if (IS_NOQUOTA(inode))
+ return -EPERM;
jfs_get_inode_flags(jfs_inode);
oldflags = jfs_inode->mode2;
diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
index df0b8535de84..df25ecc418af 100644
--- a/fs/jfs/jfs_dtree.c
+++ b/fs/jfs/jfs_dtree.c
@@ -773,7 +773,7 @@ int dtSearch(struct inode *ip, struct component_name * key, ino_t * data,
getChild:
/* update max. number of pages to split */
if (BT_STACK_FULL(btstack)) {
- /* Something's corrupted, mark filesytem dirty so
+ /* Something's corrupted, mark filesystem dirty so
* chkdsk will fix it.
*/
jfs_error(sb, "stack overrun in dtSearch!");
diff --git a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h
index f0ec72b263f1..8e2cf2cde185 100644
--- a/fs/jfs/jfs_inode.h
+++ b/fs/jfs/jfs_inode.h
@@ -18,6 +18,8 @@
#ifndef _H_JFS_INODE
#define _H_JFS_INODE
+struct fid;
+
extern struct inode *ialloc(struct inode *, umode_t);
extern int jfs_fsync(struct file *, struct dentry *, int);
extern int jfs_ioctl(struct inode *, struct file *,
@@ -32,7 +34,10 @@ extern void jfs_truncate_nolock(struct inode *, loff_t);
extern void jfs_free_zero_link(struct inode *);
extern struct dentry *jfs_get_parent(struct dentry *dentry);
extern void jfs_get_inode_flags(struct jfs_inode_info *);
-extern struct dentry *jfs_get_dentry(struct super_block *sb, void *vobjp);
+extern struct dentry *jfs_fh_to_dentry(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type);
+extern struct dentry *jfs_fh_to_parent(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type);
extern void jfs_set_inode_flags(struct inode *);
extern int jfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
index 941369c1ac8d..f5cd8d38af7a 100644
--- a/fs/jfs/jfs_metapage.c
+++ b/fs/jfs/jfs_metapage.c
@@ -180,7 +180,7 @@ static inline void remove_metapage(struct page *page, struct metapage *mp)
#endif
-static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags)
+static void init_once(struct kmem_cache *cachep, void *foo)
{
struct metapage *mp = (struct metapage *)foo;
diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
index 7aa1f7004eaf..e7c60ae6b5b2 100644
--- a/fs/jfs/jfs_txnmgr.c
+++ b/fs/jfs/jfs_txnmgr.c
@@ -1289,7 +1289,14 @@ int txCommit(tid_t tid, /* transaction identifier */
* commit the transaction synchronously, so the last iput
* will be done by the calling thread (or later)
*/
- if (tblk->u.ip->i_state & I_LOCK)
+ /*
+ * I believe this code is no longer needed. Splitting I_LOCK
+ * into two bits, I_LOCK and I_SYNC should prevent this
+ * deadlock as well. But since I don't have a JFS testload
+ * to verify this, only a trivial s/I_LOCK/I_SYNC/ was done.
+ * Joern
+ */
+ if (tblk->u.ip->i_state & I_SYNC)
tblk->xflag &= ~COMMIT_LAZY;
}
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index 932797ba433b..4e0a8493cef6 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -20,6 +20,7 @@
#include <linux/fs.h>
#include <linux/ctype.h>
#include <linux/quotaops.h>
+#include <linux/exportfs.h>
#include "jfs_incore.h"
#include "jfs_superblock.h"
#include "jfs_inode.h"
@@ -1477,13 +1478,10 @@ static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry, struc
return dentry;
}
-struct dentry *jfs_get_dentry(struct super_block *sb, void *vobjp)
+static struct inode *jfs_nfs_get_inode(struct super_block *sb,
+ u64 ino, u32 generation)
{
- __u32 *objp = vobjp;
- unsigned long ino = objp[0];
- __u32 generation = objp[1];
struct inode *inode;
- struct dentry *result;
if (ino == 0)
return ERR_PTR(-ESTALE);
@@ -1493,20 +1491,25 @@ struct dentry *jfs_get_dentry(struct super_block *sb, void *vobjp)
if (is_bad_inode(inode) ||
(generation && inode->i_generation != generation)) {
- result = ERR_PTR(-ESTALE);
- goto out_iput;
+ iput(inode);
+ return ERR_PTR(-ESTALE);
}
- result = d_alloc_anon(inode);
- if (!result) {
- result = ERR_PTR(-ENOMEM);
- goto out_iput;
- }
- return result;
+ return inode;
+}
- out_iput:
- iput(inode);
- return result;
+struct dentry *jfs_fh_to_dentry(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type)
+{
+ return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
+ jfs_nfs_get_inode);
+}
+
+struct dentry *jfs_fh_to_parent(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type)
+{
+ return generic_fh_to_parent(sb, fid, fh_len, fh_type,
+ jfs_nfs_get_inode);
}
struct dentry *jfs_get_parent(struct dentry *dentry)
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 4b372f550652..314bb4ff1ba8 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -48,7 +48,7 @@ MODULE_LICENSE("GPL");
static struct kmem_cache * jfs_inode_cachep;
static const struct super_operations jfs_super_operations;
-static struct export_operations jfs_export_operations;
+static const struct export_operations jfs_export_operations;
static struct file_system_type jfs_fs_type;
#define MAX_COMMIT_THREADS 64
@@ -737,8 +737,9 @@ static const struct super_operations jfs_super_operations = {
#endif
};
-static struct export_operations jfs_export_operations = {
- .get_dentry = jfs_get_dentry,
+static const struct export_operations jfs_export_operations = {
+ .fh_to_dentry = jfs_fh_to_dentry,
+ .fh_to_parent = jfs_fh_to_parent,
.get_parent = jfs_get_parent,
};
@@ -750,7 +751,7 @@ static struct file_system_type jfs_fs_type = {
.fs_flags = FS_REQUIRES_DEV,
};
-static void init_once(void *foo, struct kmem_cache * cachep, unsigned long flags)
+static void init_once(struct kmem_cache *cachep, void *foo)
{
struct jfs_inode_info *jfs_ip = (struct jfs_inode_info *) foo;
diff --git a/fs/libfs.c b/fs/libfs.c
index 5294de1f40c4..6e68b700958d 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -8,6 +8,7 @@
#include <linux/mount.h>
#include <linux/vfs.h>
#include <linux/mutex.h>
+#include <linux/exportfs.h>
#include <asm/uaccess.h>
@@ -351,8 +352,28 @@ int simple_prepare_write(struct file *file, struct page *page,
return 0;
}
-int simple_commit_write(struct file *file, struct page *page,
- unsigned from, unsigned to)
+int simple_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
+{
+ struct page *page;
+ pgoff_t index;
+ unsigned from;
+
+ index = pos >> PAGE_CACHE_SHIFT;
+ from = pos & (PAGE_CACHE_SIZE - 1);
+
+ page = __grab_cache_page(mapping, index);
+ if (!page)
+ return -ENOMEM;
+
+ *pagep = page;
+
+ return simple_prepare_write(file, page, from, from+len);
+}
+
+static int simple_commit_write(struct file *file, struct page *page,
+ unsigned from, unsigned to)
{
struct inode *inode = page->mapping->host;
loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
@@ -369,6 +390,28 @@ int simple_commit_write(struct file *file, struct page *page,
return 0;
}
+int simple_write_end(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata)
+{
+ unsigned from = pos & (PAGE_CACHE_SIZE - 1);
+
+ /* zero the stale part of the page if we did a short copy */
+ if (copied < len) {
+ void *kaddr = kmap_atomic(page, KM_USER0);
+ memset(kaddr + from + copied, 0, len - copied);
+ flush_dcache_page(page);
+ kunmap_atomic(kaddr, KM_USER0);
+ }
+
+ simple_commit_write(file, page, from, from+copied);
+
+ unlock_page(page);
+ page_cache_release(page);
+
+ return copied;
+}
+
/*
* the inodes created here are not hashed. If you use iunique to generate
* unique inode values later for this filesystem, then you must take care
@@ -636,13 +679,101 @@ out:
return ret;
}
+/*
+ * This is what d_alloc_anon should have been. Once the exportfs
+ * argument transition has been finished I will update d_alloc_anon
+ * to this prototype and this wrapper will go away. --hch
+ */
+static struct dentry *exportfs_d_alloc(struct inode *inode)
+{
+ struct dentry *dentry;
+
+ if (!inode)
+ return NULL;
+ if (IS_ERR(inode))
+ return ERR_PTR(PTR_ERR(inode));
+
+ dentry = d_alloc_anon(inode);
+ if (!dentry) {
+ iput(inode);
+ dentry = ERR_PTR(-ENOMEM);
+ }
+ return dentry;
+}
+
+/**
+ * generic_fh_to_dentry - generic helper for the fh_to_dentry export operation
+ * @sb: filesystem to do the file handle conversion on
+ * @fid: file handle to convert
+ * @fh_len: length of the file handle in bytes
+ * @fh_type: type of file handle
+ * @get_inode: filesystem callback to retrieve inode
+ *
+ * This function decodes @fid as long as it has one of the well-known
+ * Linux filehandle types and calls @get_inode on it to retrieve the
+ * inode for the object specified in the file handle.
+ */
+struct dentry *generic_fh_to_dentry(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type, struct inode *(*get_inode)
+ (struct super_block *sb, u64 ino, u32 gen))
+{
+ struct inode *inode = NULL;
+
+ if (fh_len < 2)
+ return NULL;
+
+ switch (fh_type) {
+ case FILEID_INO32_GEN:
+ case FILEID_INO32_GEN_PARENT:
+ inode = get_inode(sb, fid->i32.ino, fid->i32.gen);
+ break;
+ }
+
+ return exportfs_d_alloc(inode);
+}
+EXPORT_SYMBOL_GPL(generic_fh_to_dentry);
+
+/**
+ * generic_fh_to_dentry - generic helper for the fh_to_parent export operation
+ * @sb: filesystem to do the file handle conversion on
+ * @fid: file handle to convert
+ * @fh_len: length of the file handle in bytes
+ * @fh_type: type of file handle
+ * @get_inode: filesystem callback to retrieve inode
+ *
+ * This function decodes @fid as long as it has one of the well-known
+ * Linux filehandle types and calls @get_inode on it to retrieve the
+ * inode for the _parent_ object specified in the file handle if it
+ * is specified in the file handle, or NULL otherwise.
+ */
+struct dentry *generic_fh_to_parent(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type, struct inode *(*get_inode)
+ (struct super_block *sb, u64 ino, u32 gen))
+{
+ struct inode *inode = NULL;
+
+ if (fh_len <= 2)
+ return NULL;
+
+ switch (fh_type) {
+ case FILEID_INO32_GEN_PARENT:
+ inode = get_inode(sb, fid->i32.parent_ino,
+ (fh_len > 3 ? fid->i32.parent_gen : 0));
+ break;
+ }
+
+ return exportfs_d_alloc(inode);
+}
+EXPORT_SYMBOL_GPL(generic_fh_to_parent);
+
EXPORT_SYMBOL(dcache_dir_close);
EXPORT_SYMBOL(dcache_dir_lseek);
EXPORT_SYMBOL(dcache_dir_open);
EXPORT_SYMBOL(dcache_readdir);
EXPORT_SYMBOL(generic_read_dir);
EXPORT_SYMBOL(get_sb_pseudo);
-EXPORT_SYMBOL(simple_commit_write);
+EXPORT_SYMBOL(simple_write_begin);
+EXPORT_SYMBOL(simple_write_end);
EXPORT_SYMBOL(simple_dir_inode_operations);
EXPORT_SYMBOL(simple_dir_operations);
EXPORT_SYMBOL(simple_empty);
diff --git a/fs/locks.c b/fs/locks.c
index c795eaaf6c4c..8b8388eca05e 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -199,7 +199,7 @@ EXPORT_SYMBOL(locks_init_lock);
* Initialises the fields of the file lock which are invariant for
* free file_locks.
*/
-static void init_once(void *foo, struct kmem_cache *cache, unsigned long flags)
+static void init_once(struct kmem_cache *cache, void *foo)
{
struct file_lock *lock = (struct file_lock *) foo;
@@ -534,7 +534,9 @@ static void locks_insert_block(struct file_lock *blocker,
static void locks_wake_up_blocks(struct file_lock *blocker)
{
while (!list_empty(&blocker->fl_block)) {
- struct file_lock *waiter = list_entry(blocker->fl_block.next,
+ struct file_lock *waiter;
+
+ waiter = list_first_entry(&blocker->fl_block,
struct file_lock, fl_block);
__locks_delete_block(waiter);
if (waiter->fl_lmops && waiter->fl_lmops->fl_notify)
@@ -668,7 +670,7 @@ posix_test_lock(struct file *filp, struct file_lock *fl)
for (cfl = filp->f_path.dentry->d_inode->i_flock; cfl; cfl = cfl->fl_next) {
if (!IS_POSIX(cfl))
continue;
- if (posix_locks_conflict(cfl, fl))
+ if (posix_locks_conflict(fl, cfl))
break;
}
if (cfl)
@@ -694,18 +696,28 @@ EXPORT_SYMBOL(posix_test_lock);
* Note: the above assumption may not be true when handling lock requests
* from a broken NFS client. But broken NFS clients have a lot more to
* worry about than proper deadlock detection anyway... --okir
+ *
+ * However, the failure of this assumption (also possible in the case of
+ * multiple tasks sharing the same open file table) also means there's no
+ * guarantee that the loop below will terminate. As a hack, we give up
+ * after a few iterations.
*/
+
+#define MAX_DEADLK_ITERATIONS 10
+
static int posix_locks_deadlock(struct file_lock *caller_fl,
struct file_lock *block_fl)
{
- struct list_head *tmp;
+ struct file_lock *fl;
+ int i = 0;
next_task:
if (posix_same_owner(caller_fl, block_fl))
return 1;
- list_for_each(tmp, &blocked_list) {
- struct file_lock *fl = list_entry(tmp, struct file_lock, fl_link);
+ list_for_each_entry(fl, &blocked_list, fl_link) {
if (posix_same_owner(fl, block_fl)) {
+ if (i++ > MAX_DEADLK_ITERATIONS)
+ return 0;
fl = fl->fl_next;
block_fl = fl;
goto next_task;
@@ -715,8 +727,7 @@ next_task:
}
/* Try to create a FLOCK lock on filp. We always insert new FLOCK locks
- * at the head of the list, but that's secret knowledge known only to
- * flock_lock_file and posix_lock_file.
+ * after any leases, but before any posix locks.
*
* Note that if called with an FL_EXISTS argument, the caller may determine
* whether or not a lock was successfully freed by testing the return
@@ -733,6 +744,15 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)
lock_kernel();
if (request->fl_flags & FL_ACCESS)
goto find_conflict;
+
+ if (request->fl_type != F_UNLCK) {
+ error = -ENOMEM;
+ new_fl = locks_alloc_lock();
+ if (new_fl == NULL)
+ goto out;
+ error = 0;
+ }
+
for_each_lock(inode, before) {
struct file_lock *fl = *before;
if (IS_POSIX(fl))
@@ -754,10 +774,6 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)
goto out;
}
- error = -ENOMEM;
- new_fl = locks_alloc_lock();
- if (new_fl == NULL)
- goto out;
/*
* If a higher-priority process was blocked on the old file lock,
* give it the opportunity to lock the file.
@@ -819,7 +835,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str
lock_kernel();
if (request->fl_type != F_UNLCK) {
for_each_lock(inode, before) {
- struct file_lock *fl = *before;
+ fl = *before;
if (!IS_POSIX(fl))
continue;
if (!posix_locks_conflict(request, fl))
@@ -1113,7 +1129,7 @@ int locks_mandatory_area(int read_write, struct inode *inode,
* If we've been sleeping someone might have
* changed the permissions behind our back.
*/
- if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
+ if (__mandatory_lock(inode))
continue;
}
@@ -1337,6 +1353,7 @@ int fcntl_getlease(struct file *filp)
int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
{
struct file_lock *fl, **before, **my_before = NULL, *lease;
+ struct file_lock *new_fl = NULL;
struct dentry *dentry = filp->f_path.dentry;
struct inode *inode = dentry->d_inode;
int error, rdlease_count = 0, wrlease_count = 0;
@@ -1363,6 +1380,11 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
|| (atomic_read(&inode->i_count) > 1)))
goto out;
+ error = -ENOMEM;
+ new_fl = locks_alloc_lock();
+ if (new_fl == NULL)
+ goto out;
+
/*
* At this point, we know that if there is an exclusive
* lease on this file, then we hold it on this filp
@@ -1405,18 +1427,15 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
if (!leases_enable)
goto out;
- error = -ENOMEM;
- fl = locks_alloc_lock();
- if (fl == NULL)
- goto out;
-
- locks_copy_lock(fl, lease);
+ locks_copy_lock(new_fl, lease);
+ locks_insert_lock(before, new_fl);
- locks_insert_lock(before, fl);
+ *flp = new_fl;
+ return 0;
- *flp = fl;
- error = 0;
out:
+ if (new_fl != NULL)
+ locks_free_lock(new_fl);
return error;
}
EXPORT_SYMBOL(generic_setlease);
@@ -1752,9 +1771,7 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
/* Don't allow mandatory locks on files that may be memory mapped
* and shared.
*/
- if (IS_MANDLOCK(inode) &&
- (inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID &&
- mapping_writably_mapped(filp->f_mapping)) {
+ if (mandatory_lock(inode) && mapping_writably_mapped(filp->f_mapping)) {
error = -EAGAIN;
goto out;
}
@@ -1878,9 +1895,7 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,
/* Don't allow mandatory locks on files that may be memory mapped
* and shared.
*/
- if (IS_MANDLOCK(inode) &&
- (inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID &&
- mapping_writably_mapped(filp->f_mapping)) {
+ if (mandatory_lock(inode) && mapping_writably_mapped(filp->f_mapping)) {
error = -EAGAIN;
goto out;
}
@@ -2062,138 +2077,114 @@ int vfs_cancel_lock(struct file *filp, struct file_lock *fl)
EXPORT_SYMBOL_GPL(vfs_cancel_lock);
-static void lock_get_status(char* out, struct file_lock *fl, int id, char *pfx)
+#ifdef CONFIG_PROC_FS
+#include <linux/seq_file.h>
+
+static void lock_get_status(struct seq_file *f, struct file_lock *fl,
+ int id, char *pfx)
{
struct inode *inode = NULL;
if (fl->fl_file != NULL)
inode = fl->fl_file->f_path.dentry->d_inode;
- out += sprintf(out, "%d:%s ", id, pfx);
+ seq_printf(f, "%d:%s ", id, pfx);
if (IS_POSIX(fl)) {
- out += sprintf(out, "%6s %s ",
+ seq_printf(f, "%6s %s ",
(fl->fl_flags & FL_ACCESS) ? "ACCESS" : "POSIX ",
(inode == NULL) ? "*NOINODE*" :
- (IS_MANDLOCK(inode) &&
- (inode->i_mode & (S_IXGRP | S_ISGID)) == S_ISGID) ?
- "MANDATORY" : "ADVISORY ");
+ mandatory_lock(inode) ? "MANDATORY" : "ADVISORY ");
} else if (IS_FLOCK(fl)) {
if (fl->fl_type & LOCK_MAND) {
- out += sprintf(out, "FLOCK MSNFS ");
+ seq_printf(f, "FLOCK MSNFS ");
} else {
- out += sprintf(out, "FLOCK ADVISORY ");
+ seq_printf(f, "FLOCK ADVISORY ");
}
} else if (IS_LEASE(fl)) {
- out += sprintf(out, "LEASE ");
+ seq_printf(f, "LEASE ");
if (fl->fl_type & F_INPROGRESS)
- out += sprintf(out, "BREAKING ");
+ seq_printf(f, "BREAKING ");
else if (fl->fl_file)
- out += sprintf(out, "ACTIVE ");
+ seq_printf(f, "ACTIVE ");
else
- out += sprintf(out, "BREAKER ");
+ seq_printf(f, "BREAKER ");
} else {
- out += sprintf(out, "UNKNOWN UNKNOWN ");
+ seq_printf(f, "UNKNOWN UNKNOWN ");
}
if (fl->fl_type & LOCK_MAND) {
- out += sprintf(out, "%s ",
+ seq_printf(f, "%s ",
(fl->fl_type & LOCK_READ)
? (fl->fl_type & LOCK_WRITE) ? "RW " : "READ "
: (fl->fl_type & LOCK_WRITE) ? "WRITE" : "NONE ");
} else {
- out += sprintf(out, "%s ",
+ seq_printf(f, "%s ",
(fl->fl_type & F_INPROGRESS)
? (fl->fl_type & F_UNLCK) ? "UNLCK" : "READ "
: (fl->fl_type & F_WRLCK) ? "WRITE" : "READ ");
}
if (inode) {
#ifdef WE_CAN_BREAK_LSLK_NOW
- out += sprintf(out, "%d %s:%ld ", fl->fl_pid,
+ seq_printf(f, "%d %s:%ld ", fl->fl_pid,
inode->i_sb->s_id, inode->i_ino);
#else
/* userspace relies on this representation of dev_t ;-( */
- out += sprintf(out, "%d %02x:%02x:%ld ", fl->fl_pid,
+ seq_printf(f, "%d %02x:%02x:%ld ", fl->fl_pid,
MAJOR(inode->i_sb->s_dev),
MINOR(inode->i_sb->s_dev), inode->i_ino);
#endif
} else {
- out += sprintf(out, "%d <none>:0 ", fl->fl_pid);
+ seq_printf(f, "%d <none>:0 ", fl->fl_pid);
}
if (IS_POSIX(fl)) {
if (fl->fl_end == OFFSET_MAX)
- out += sprintf(out, "%Ld EOF\n", fl->fl_start);
+ seq_printf(f, "%Ld EOF\n", fl->fl_start);
else
- out += sprintf(out, "%Ld %Ld\n", fl->fl_start,
- fl->fl_end);
+ seq_printf(f, "%Ld %Ld\n", fl->fl_start, fl->fl_end);
} else {
- out += sprintf(out, "0 EOF\n");
+ seq_printf(f, "0 EOF\n");
}
}
-static void move_lock_status(char **p, off_t* pos, off_t offset)
+static int locks_show(struct seq_file *f, void *v)
{
- int len;
- len = strlen(*p);
- if(*pos >= offset) {
- /* the complete line is valid */
- *p += len;
- *pos += len;
- return;
- }
- if(*pos+len > offset) {
- /* use the second part of the line */
- int i = offset-*pos;
- memmove(*p,*p+i,len-i);
- *p += len-i;
- *pos += len;
- return;
- }
- /* discard the complete line */
- *pos += len;
+ struct file_lock *fl, *bfl;
+
+ fl = list_entry(v, struct file_lock, fl_link);
+
+ lock_get_status(f, fl, (long)f->private, "");
+
+ list_for_each_entry(bfl, &fl->fl_block, fl_block)
+ lock_get_status(f, bfl, (long)f->private, " ->");
+
+ f->private++;
+ return 0;
}
-/**
- * get_locks_status - reports lock usage in /proc/locks
- * @buffer: address in userspace to write into
- * @start: ?
- * @offset: how far we are through the buffer
- * @length: how much to read
- */
+static void *locks_start(struct seq_file *f, loff_t *pos)
+{
+ lock_kernel();
+ f->private = (void *)1;
+ return seq_list_start(&file_lock_list, *pos);
+}
-int get_locks_status(char *buffer, char **start, off_t offset, int length)
+static void *locks_next(struct seq_file *f, void *v, loff_t *pos)
{
- struct list_head *tmp;
- char *q = buffer;
- off_t pos = 0;
- int i = 0;
+ return seq_list_next(v, &file_lock_list, pos);
+}
- lock_kernel();
- list_for_each(tmp, &file_lock_list) {
- struct list_head *btmp;
- struct file_lock *fl = list_entry(tmp, struct file_lock, fl_link);
- lock_get_status(q, fl, ++i, "");
- move_lock_status(&q, &pos, offset);
-
- if(pos >= offset+length)
- goto done;
-
- list_for_each(btmp, &fl->fl_block) {
- struct file_lock *bfl = list_entry(btmp,
- struct file_lock, fl_block);
- lock_get_status(q, bfl, i, " ->");
- move_lock_status(&q, &pos, offset);
-
- if(pos >= offset+length)
- goto done;
- }
- }
-done:
+static void locks_stop(struct seq_file *f, void *v)
+{
unlock_kernel();
- *start = buffer;
- if(q-buffer < length)
- return (q-buffer);
- return length;
}
+struct seq_operations locks_seq_operations = {
+ .start = locks_start,
+ .next = locks_next,
+ .stop = locks_stop,
+ .show = locks_show,
+};
+#endif
+
/**
* lock_may_read - checks that the region is free of locks
* @inode: the inode that is being read
diff --git a/fs/mbcache.c b/fs/mbcache.c
index 1046cbefbfbf..eb31b73e7d69 100644
--- a/fs/mbcache.c
+++ b/fs/mbcache.c
@@ -403,9 +403,9 @@ mb_cache_entry_alloc(struct mb_cache *cache)
{
struct mb_cache_entry *ce;
- atomic_inc(&cache->c_entry_count);
ce = kmem_cache_alloc(cache->c_entry_cache, GFP_KERNEL);
if (ce) {
+ atomic_inc(&cache->c_entry_count);
INIT_LIST_HEAD(&ce->e_lru_list);
INIT_LIST_HEAD(&ce->e_block_list);
ce->e_cache = cache;
diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c
index 99a12f127769..703cc35e04b9 100644
--- a/fs/minix/bitmap.c
+++ b/fs/minix/bitmap.c
@@ -17,7 +17,7 @@
#include <linux/bitops.h>
#include <linux/sched.h>
-static int nibblemap[] = { 4,3,3,2,3,2,2,1,3,2,2,1,2,1,1,0 };
+static const int nibblemap[] = { 4,3,3,2,3,2,2,1,3,2,2,1,2,1,1,0 };
static unsigned long count_free(struct buffer_head *map[], unsigned numblocks, __u32 numbits)
{
diff --git a/fs/minix/dir.c b/fs/minix/dir.c
index e207cbe70951..f70433816a38 100644
--- a/fs/minix/dir.c
+++ b/fs/minix/dir.c
@@ -9,8 +9,10 @@
*/
#include "minix.h"
+#include <linux/buffer_head.h>
#include <linux/highmem.h>
#include <linux/smp_lock.h>
+#include <linux/swap.h>
typedef struct minix_dir_entry minix_dirent;
typedef struct minix3_dir_entry minix3_dirent;
@@ -48,11 +50,17 @@ static inline unsigned long dir_pages(struct inode *inode)
return (inode->i_size+PAGE_CACHE_SIZE-1)>>PAGE_CACHE_SHIFT;
}
-static int dir_commit_chunk(struct page *page, unsigned from, unsigned to)
+static int dir_commit_chunk(struct page *page, loff_t pos, unsigned len)
{
- struct inode *dir = (struct inode *)page->mapping->host;
+ struct address_space *mapping = page->mapping;
+ struct inode *dir = mapping->host;
int err = 0;
- page->mapping->a_ops->commit_write(NULL, page, from, to);
+ block_write_end(NULL, mapping, pos, len, len, page, NULL);
+
+ if (pos+len > dir->i_size) {
+ i_size_write(dir, pos+len);
+ mark_inode_dirty(dir);
+ }
if (IS_DIRSYNC(dir))
err = write_one_page(page, 1);
else
@@ -220,7 +228,7 @@ int minix_add_link(struct dentry *dentry, struct inode *inode)
char *kaddr, *p;
minix_dirent *de;
minix3_dirent *de3;
- unsigned from, to;
+ loff_t pos;
int err;
char *namx = NULL;
__u32 inumber;
@@ -272,9 +280,9 @@ int minix_add_link(struct dentry *dentry, struct inode *inode)
return -EINVAL;
got_it:
- from = p - (char*)page_address(page);
- to = from + sbi->s_dirsize;
- err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
+ pos = (page->index >> PAGE_CACHE_SHIFT) + p - (char*)page_address(page);
+ err = __minix_write_begin(NULL, page->mapping, pos, sbi->s_dirsize,
+ AOP_FLAG_UNINTERRUPTIBLE, &page, NULL);
if (err)
goto out_unlock;
memcpy (namx, name, namelen);
@@ -285,7 +293,7 @@ got_it:
memset (namx + namelen, 0, sbi->s_dirsize - namelen - 2);
de->inode = inode->i_ino;
}
- err = dir_commit_chunk(page, from, to);
+ err = dir_commit_chunk(page, pos, sbi->s_dirsize);
dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
mark_inode_dirty(dir);
out_put:
@@ -302,15 +310,16 @@ int minix_delete_entry(struct minix_dir_entry *de, struct page *page)
struct address_space *mapping = page->mapping;
struct inode *inode = (struct inode*)mapping->host;
char *kaddr = page_address(page);
- unsigned from = (char*)de - kaddr;
- unsigned to = from + minix_sb(inode->i_sb)->s_dirsize;
+ loff_t pos = page_offset(page) + (char*)de - kaddr;
+ unsigned len = minix_sb(inode->i_sb)->s_dirsize;
int err;
lock_page(page);
- err = mapping->a_ops->prepare_write(NULL, page, from, to);
+ err = __minix_write_begin(NULL, mapping, pos, len,
+ AOP_FLAG_UNINTERRUPTIBLE, &page, NULL);
if (err == 0) {
de->inode = 0;
- err = dir_commit_chunk(page, from, to);
+ err = dir_commit_chunk(page, pos, len);
} else {
unlock_page(page);
}
@@ -330,7 +339,8 @@ int minix_make_empty(struct inode *inode, struct inode *dir)
if (!page)
return -ENOMEM;
- err = mapping->a_ops->prepare_write(NULL, page, 0, 2 * sbi->s_dirsize);
+ err = __minix_write_begin(NULL, mapping, 0, 2 * sbi->s_dirsize,
+ AOP_FLAG_UNINTERRUPTIBLE, &page, NULL);
if (err) {
unlock_page(page);
goto fail;
@@ -421,17 +431,20 @@ not_empty:
void minix_set_link(struct minix_dir_entry *de, struct page *page,
struct inode *inode)
{
- struct inode *dir = (struct inode*)page->mapping->host;
+ struct address_space *mapping = page->mapping;
+ struct inode *dir = mapping->host;
struct minix_sb_info *sbi = minix_sb(dir->i_sb);
- unsigned from = (char *)de-(char*)page_address(page);
- unsigned to = from + sbi->s_dirsize;
+ loff_t pos = page_offset(page) +
+ (char *)de-(char*)page_address(page);
int err;
lock_page(page);
- err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
+
+ err = __minix_write_begin(NULL, mapping, pos, sbi->s_dirsize,
+ AOP_FLAG_UNINTERRUPTIBLE, &page, NULL);
if (err == 0) {
de->inode = inode->i_ino;
- err = dir_commit_chunk(page, from, to);
+ err = dir_commit_chunk(page, pos, sbi->s_dirsize);
} else {
unlock_page(page);
}
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index 43668d7d668f..bf4cd316af81 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -69,7 +69,7 @@ static void minix_destroy_inode(struct inode *inode)
kmem_cache_free(minix_inode_cachep, minix_i(inode));
}
-static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
+static void init_once(struct kmem_cache * cachep, void *foo)
{
struct minix_inode_info *ei = (struct minix_inode_info *) foo;
@@ -346,24 +346,39 @@ static int minix_writepage(struct page *page, struct writeback_control *wbc)
{
return block_write_full_page(page, minix_get_block, wbc);
}
+
static int minix_readpage(struct file *file, struct page *page)
{
return block_read_full_page(page,minix_get_block);
}
-static int minix_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
+
+int __minix_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
{
- return block_prepare_write(page,from,to,minix_get_block);
+ return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
+ minix_get_block);
}
+
+static int minix_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
+{
+ *pagep = NULL;
+ return __minix_write_begin(file, mapping, pos, len, flags, pagep, fsdata);
+}
+
static sector_t minix_bmap(struct address_space *mapping, sector_t block)
{
return generic_block_bmap(mapping,block,minix_get_block);
}
+
static const struct address_space_operations minix_aops = {
.readpage = minix_readpage,
.writepage = minix_writepage,
.sync_page = block_sync_page,
- .prepare_write = minix_prepare_write,
- .commit_write = generic_commit_write,
+ .write_begin = minix_write_begin,
+ .write_end = generic_write_end,
.bmap = minix_bmap
};
diff --git a/fs/minix/itree_v1.c b/fs/minix/itree_v1.c
index 1a5f3bf0bcec..82d6554b02fe 100644
--- a/fs/minix/itree_v1.c
+++ b/fs/minix/itree_v1.c
@@ -23,11 +23,16 @@ static inline block_t *i_data(struct inode *inode)
static int block_to_path(struct inode * inode, long block, int offsets[DEPTH])
{
int n = 0;
+ char b[BDEVNAME_SIZE];
if (block < 0) {
- printk("minix_bmap: block<0\n");
+ printk("MINIX-fs: block_to_path: block %ld < 0 on dev %s\n",
+ block, bdevname(inode->i_sb->s_bdev, b));
} else if (block >= (minix_sb(inode->i_sb)->s_max_size/BLOCK_SIZE)) {
- printk("minix_bmap: block>big\n");
+ if (printk_ratelimit())
+ printk("MINIX-fs: block_to_path: "
+ "block %ld too big on dev %s\n",
+ block, bdevname(inode->i_sb->s_bdev, b));
} else if (block < 7) {
offsets[n++] = block;
} else if ((block -= 7) < 512) {
diff --git a/fs/minix/itree_v2.c b/fs/minix/itree_v2.c
index ad8f0dec4ef4..f23010969369 100644
--- a/fs/minix/itree_v2.c
+++ b/fs/minix/itree_v2.c
@@ -23,12 +23,17 @@ static inline block_t *i_data(struct inode *inode)
static int block_to_path(struct inode * inode, long block, int offsets[DEPTH])
{
int n = 0;
+ char b[BDEVNAME_SIZE];
struct super_block *sb = inode->i_sb;
if (block < 0) {
- printk("minix_bmap: block<0\n");
+ printk("MINIX-fs: block_to_path: block %ld < 0 on dev %s\n",
+ block, bdevname(sb->s_bdev, b));
} else if (block >= (minix_sb(inode->i_sb)->s_max_size/sb->s_blocksize)) {
- printk("minix_bmap: block>big\n");
+ if (printk_ratelimit())
+ printk("MINIX-fs: block_to_path: "
+ "block %ld too big on dev %s\n",
+ block, bdevname(sb->s_bdev, b));
} else if (block < 7) {
offsets[n++] = block;
} else if ((block -= 7) < 256) {
diff --git a/fs/minix/minix.h b/fs/minix/minix.h
index 73ef84f8fb0b..ac5d3a75cb0d 100644
--- a/fs/minix/minix.h
+++ b/fs/minix/minix.h
@@ -54,6 +54,9 @@ extern int minix_new_block(struct inode * inode);
extern void minix_free_block(struct inode *inode, unsigned long block);
extern unsigned long minix_count_free_blocks(struct minix_sb_info *sbi);
extern int minix_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+extern int __minix_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata);
extern void V1_minix_truncate(struct inode *);
extern void V2_minix_truncate(struct inode *);
diff --git a/fs/mpage.c b/fs/mpage.c
index b1c3e5890508..d54f8f897224 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -379,31 +379,25 @@ mpage_readpages(struct address_space *mapping, struct list_head *pages,
struct bio *bio = NULL;
unsigned page_idx;
sector_t last_block_in_bio = 0;
- struct pagevec lru_pvec;
struct buffer_head map_bh;
unsigned long first_logical_block = 0;
clear_buffer_mapped(&map_bh);
- pagevec_init(&lru_pvec, 0);
for (page_idx = 0; page_idx < nr_pages; page_idx++) {
struct page *page = list_entry(pages->prev, struct page, lru);
prefetchw(&page->flags);
list_del(&page->lru);
- if (!add_to_page_cache(page, mapping,
+ if (!add_to_page_cache_lru(page, mapping,
page->index, GFP_KERNEL)) {
bio = do_mpage_readpage(bio, page,
nr_pages - page_idx,
&last_block_in_bio, &map_bh,
&first_logical_block,
get_block);
- if (!pagevec_add(&lru_pvec, page))
- __pagevec_lru_add(&lru_pvec);
- } else {
- page_cache_release(page);
}
+ page_cache_release(page);
}
- pagevec_lru_add(&lru_pvec);
BUG_ON(!list_empty(pages));
if (bio)
mpage_bio_submit(READ, bio);
diff --git a/fs/namei.c b/fs/namei.c
index a83160acd748..3b993db26cee 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -30,7 +30,6 @@
#include <linux/capability.h>
#include <linux/file.h>
#include <linux/fcntl.h>
-#include <linux/namei.h>
#include <asm/namei.h>
#include <asm/uaccess.h>
@@ -228,10 +227,14 @@ int generic_permission(struct inode *inode, int mask,
int permission(struct inode *inode, int mask, struct nameidata *nd)
{
- umode_t mode = inode->i_mode;
int retval, submask;
+ struct vfsmount *mnt = NULL;
+
+ if (nd)
+ mnt = nd->mnt;
if (mask & MAY_WRITE) {
+ umode_t mode = inode->i_mode;
/*
* Nobody gets write access to a read-only fs.
@@ -247,22 +250,34 @@ int permission(struct inode *inode, int mask, struct nameidata *nd)
return -EACCES;
}
-
- /*
- * MAY_EXEC on regular files requires special handling: We override
- * filesystem execute permissions if the mode bits aren't set or
- * the fs is mounted with the "noexec" flag.
- */
- if ((mask & MAY_EXEC) && S_ISREG(mode) && (!(mode & S_IXUGO) ||
- (nd && nd->mnt && (nd->mnt->mnt_flags & MNT_NOEXEC))))
- return -EACCES;
+ if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
+ /*
+ * MAY_EXEC on regular files is denied if the fs is mounted
+ * with the "noexec" flag.
+ */
+ if (mnt && (mnt->mnt_flags & MNT_NOEXEC))
+ return -EACCES;
+ }
/* Ordinary permission routines do not understand MAY_APPEND. */
submask = mask & ~MAY_APPEND;
- if (inode->i_op && inode->i_op->permission)
+ if (inode->i_op && inode->i_op->permission) {
retval = inode->i_op->permission(inode, submask, nd);
- else
+ if (!retval) {
+ /*
+ * Exec permission on a regular file is denied if none
+ * of the execute bits are set.
+ *
+ * This check should be done by the ->permission()
+ * method.
+ */
+ if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode) &&
+ !(inode->i_mode & S_IXUGO))
+ return -EACCES;
+ }
+ } else {
retval = generic_permission(inode, submask, NULL);
+ }
if (retval)
return retval;
@@ -1159,7 +1174,7 @@ static int fastcall do_path_lookup(int dfd, const char *name,
out:
if (unlikely(!retval && !audit_dummy_context() && nd->dentry &&
nd->dentry->d_inode))
- audit_inode(name, nd->dentry->d_inode);
+ audit_inode(name, nd->dentry);
out_fail:
return retval;
@@ -1199,7 +1214,7 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt,
retval = path_walk(name, nd);
if (unlikely(!retval && !audit_dummy_context() && nd->dentry &&
nd->dentry->d_inode))
- audit_inode(name, nd->dentry->d_inode);
+ audit_inode(name, nd->dentry);
return retval;
@@ -1273,7 +1288,8 @@ int __user_path_lookup_open(const char __user *name, unsigned int lookup_flags,
return err;
}
-static inline struct dentry *__lookup_hash_kern(struct qstr *name, struct dentry *base, struct nameidata *nd)
+static struct dentry *__lookup_hash(struct qstr *name,
+ struct dentry *base, struct nameidata *nd)
{
struct dentry *dentry;
struct inode *inode;
@@ -1313,31 +1329,18 @@ out:
* needs parent already locked. Doesn't follow mounts.
* SMP-safe.
*/
-static inline struct dentry * __lookup_hash(struct qstr *name, struct dentry *base, struct nameidata *nd)
+static struct dentry *lookup_hash(struct nameidata *nd)
{
- struct dentry *dentry;
- struct inode *inode;
int err;
- inode = base->d_inode;
-
- err = permission(inode, MAY_EXEC, nd);
- dentry = ERR_PTR(err);
+ err = permission(nd->dentry->d_inode, MAY_EXEC, nd);
if (err)
- goto out;
-
- dentry = __lookup_hash_kern(name, base, nd);
-out:
- return dentry;
-}
-
-static struct dentry *lookup_hash(struct nameidata *nd)
-{
+ return ERR_PTR(err);
return __lookup_hash(&nd->last, nd->dentry, nd);
}
-/* SMP-safe */
-static inline int __lookup_one_len(const char *name, struct qstr *this, struct dentry *base, int len)
+static int __lookup_one_len(const char *name, struct qstr *this,
+ struct dentry *base, int len)
{
unsigned long hash;
unsigned int c;
@@ -1358,6 +1361,17 @@ static inline int __lookup_one_len(const char *name, struct qstr *this, struct d
return 0;
}
+/**
+ * lookup_one_len: filesystem helper to lookup single pathname component
+ * @name: pathname component to lookup
+ * @base: base directory to lookup from
+ * @len: maximum length @len should be interpreted to
+ *
+ * Note that this routine is purely a helper for filesystem useage and should
+ * not be called by generic code. Also note that by using this function to
+ * nameidata argument is passed to the filesystem methods and a filesystem
+ * using this helper needs to be prepared for that.
+ */
struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
{
int err;
@@ -1366,18 +1380,33 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
err = __lookup_one_len(name, &this, base, len);
if (err)
return ERR_PTR(err);
+
+ err = permission(base->d_inode, MAY_EXEC, NULL);
+ if (err)
+ return ERR_PTR(err);
return __lookup_hash(&this, base, NULL);
}
-struct dentry *lookup_one_len_kern(const char *name, struct dentry *base, int len)
+/**
+ * lookup_one_noperm - bad hack for sysfs
+ * @name: pathname component to lookup
+ * @base: base directory to lookup from
+ *
+ * This is a variant of lookup_one_len that doesn't perform any permission
+ * checks. It's a horrible hack to work around the braindead sysfs
+ * architecture and should not be used anywhere else.
+ *
+ * DON'T USE THIS FUNCTION EVER, thanks.
+ */
+struct dentry *lookup_one_noperm(const char *name, struct dentry *base)
{
int err;
struct qstr this;
- err = __lookup_one_len(name, &this, base, len);
+ err = __lookup_one_len(name, &this, base, strlen(name));
if (err)
return ERR_PTR(err);
- return __lookup_hash_kern(&this, base, NULL);
+ return __lookup_hash(&this, base, NULL);
}
int fastcall __user_walk_fd(int dfd, const char __user *name, unsigned flags,
@@ -1440,7 +1469,7 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir)
return -ENOENT;
BUG_ON(victim->d_parent->d_inode != dir);
- audit_inode_child(victim->d_name.name, victim->d_inode, dir);
+ audit_inode_child(victim->d_name.name, victim, dir);
error = permission(dir,MAY_WRITE | MAY_EXEC, NULL);
if (error)
@@ -1579,10 +1608,6 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
if (S_ISDIR(inode->i_mode) && (flag & FMODE_WRITE))
return -EISDIR;
- error = vfs_permission(nd, acc_mode);
- if (error)
- return error;
-
/*
* FIFO's, sockets and device files are special: they don't
* actually live on the filesystem itself, and as such you
@@ -1597,6 +1622,10 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
flag &= ~O_TRUNC;
} else if (IS_RDONLY(inode) && (flag & FMODE_WRITE))
return -EROFS;
+
+ error = vfs_permission(nd, acc_mode);
+ if (error)
+ return error;
/*
* An append-only file must be opened in append mode for writing.
*/
@@ -1630,8 +1659,10 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
error = locks_verify_locked(inode);
if (!error) {
DQUOT_INIT(inode);
-
- error = do_truncate(dentry, 0, ATTR_MTIME|ATTR_CTIME, NULL);
+
+ error = do_truncate(dentry, 0,
+ ATTR_MTIME|ATTR_CTIME|ATTR_OPEN,
+ NULL);
}
put_write_access(inode);
if (error)
@@ -1752,7 +1783,7 @@ do_last:
* It already exists.
*/
mutex_unlock(&dir->d_inode->i_mutex);
- audit_inode(pathname, path.dentry->d_inode);
+ audit_inode(pathname, path.dentry);
error = -EEXIST;
if (flag & O_EXCL)
@@ -2531,7 +2562,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
if (!error) {
const char *new_name = old_dentry->d_name.name;
fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir,
- new_dentry->d_inode, old_dentry->d_inode);
+ new_dentry->d_inode, old_dentry);
}
fsnotify_oldname_free(old_name);
@@ -2729,53 +2760,29 @@ int __page_symlink(struct inode *inode, const char *symname, int len,
{
struct address_space *mapping = inode->i_mapping;
struct page *page;
+ void *fsdata;
int err;
char *kaddr;
retry:
- err = -ENOMEM;
- page = find_or_create_page(mapping, 0, gfp_mask);
- if (!page)
- goto fail;
- err = mapping->a_ops->prepare_write(NULL, page, 0, len-1);
- if (err == AOP_TRUNCATED_PAGE) {
- page_cache_release(page);
- goto retry;
- }
+ err = pagecache_write_begin(NULL, mapping, 0, len-1,
+ AOP_FLAG_UNINTERRUPTIBLE, &page, &fsdata);
if (err)
- goto fail_map;
+ goto fail;
+
kaddr = kmap_atomic(page, KM_USER0);
memcpy(kaddr, symname, len-1);
kunmap_atomic(kaddr, KM_USER0);
- err = mapping->a_ops->commit_write(NULL, page, 0, len-1);
- if (err == AOP_TRUNCATED_PAGE) {
- page_cache_release(page);
- goto retry;
- }
- if (err)
- goto fail_map;
- /*
- * Notice that we are _not_ going to block here - end of page is
- * unmapped, so this will only try to map the rest of page, see
- * that it is unmapped (typically even will not look into inode -
- * ->i_size will be enough for everything) and zero it out.
- * OTOH it's obviously correct and should make the page up-to-date.
- */
- if (!PageUptodate(page)) {
- err = mapping->a_ops->readpage(NULL, page);
- if (err != AOP_TRUNCATED_PAGE)
- wait_on_page_locked(page);
- } else {
- unlock_page(page);
- }
- page_cache_release(page);
+
+ err = pagecache_write_end(NULL, mapping, 0, len-1, len-1,
+ page, fsdata);
if (err < 0)
goto fail;
+ if (err < len-1)
+ goto retry;
+
mark_inode_dirty(inode);
return 0;
-fail_map:
- unlock_page(page);
- page_cache_release(page);
fail:
return err;
}
diff --git a/fs/namespace.c b/fs/namespace.c
index ddbda13c2d31..06083885b21e 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -246,7 +246,7 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root,
list_add(&mnt->mnt_slave, &old->mnt_slave_list);
mnt->mnt_master = old;
CLEAR_MNT_SHARED(mnt);
- } else {
+ } else if (!(flag & CL_PRIVATE)) {
if ((flag & CL_PROPAGATION) || IS_MNT_SHARED(old))
list_add(&mnt->mnt_share, &old->mnt_share);
if (IS_MNT_SLAVE(old))
@@ -746,6 +746,26 @@ Enomem:
return NULL;
}
+struct vfsmount *collect_mounts(struct vfsmount *mnt, struct dentry *dentry)
+{
+ struct vfsmount *tree;
+ down_read(&namespace_sem);
+ tree = copy_tree(mnt, dentry, CL_COPY_ALL | CL_PRIVATE);
+ up_read(&namespace_sem);
+ return tree;
+}
+
+void drop_collected_mounts(struct vfsmount *mnt)
+{
+ LIST_HEAD(umount_list);
+ down_read(&namespace_sem);
+ spin_lock(&vfsmount_lock);
+ umount_tree(mnt, 0, &umount_list);
+ spin_unlock(&vfsmount_lock);
+ up_read(&namespace_sem);
+ release_mounts(&umount_list);
+}
+
/*
* @source_mnt : mount tree to be attached
* @nd : place the mount tree @source_mnt is attached
@@ -1411,7 +1431,7 @@ long do_mount(char *dev_name, char *dir_name, char *type_page,
mnt_flags |= MNT_RELATIME;
flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE |
- MS_NOATIME | MS_NODIRATIME | MS_RELATIME);
+ MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT);
/* ... and get the mountpoint */
retval = path_lookup(dir_name, LOOKUP_FOLLOW, &nd);
@@ -1791,7 +1811,7 @@ static void __init init_mount_tree(void)
set_fs_root(current->fs, ns->root, ns->root->mnt_root);
}
-void __init mnt_init(unsigned long mempages)
+void __init mnt_init(void)
{
struct list_head *d;
unsigned int nr_hash;
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
index 7f8536dbdedc..e1cb70c643f8 100644
--- a/fs/ncpfs/inode.c
+++ b/fs/ncpfs/inode.c
@@ -56,7 +56,7 @@ static void ncp_destroy_inode(struct inode *inode)
kmem_cache_free(ncp_inode_cachep, NCP_FINFO(inode));
}
-static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
+static void init_once(struct kmem_cache *cachep, void *foo)
{
struct ncp_inode_info *ei = (struct ncp_inode_info *) foo;
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index a532ee12740a..70587f383f10 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -627,6 +627,7 @@ static void nfs_server_set_fsinfo(struct nfs_server *server, struct nfs_fsinfo *
if (server->rsize > NFS_MAX_FILE_IO_SIZE)
server->rsize = NFS_MAX_FILE_IO_SIZE;
server->rpages = (server->rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+
server->backing_dev_info.ra_pages = server->rpages * NFS_MAX_READAHEAD;
if (server->wsize > max_rpc_payload)
@@ -677,6 +678,10 @@ static int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, str
goto out_error;
nfs_server_set_fsinfo(server, &fsinfo);
+ error = bdi_init(&server->backing_dev_info);
+ if (error)
+ goto out_error;
+
/* Get some general file system info */
if (server->namelen == 0) {
@@ -756,6 +761,7 @@ void nfs_free_server(struct nfs_server *server)
nfs_put_client(server->nfs_client);
nfs_free_iostats(server->io_stats);
+ bdi_destroy(&server->backing_dev_info);
kfree(server);
nfs_release_automount_timer();
dprintk("<-- nfs_free_server()\n");
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index af8b235d405d..11833f4caeaa 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -168,7 +168,8 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
spin_unlock(&inode->i_lock);
spin_unlock(&clp->cl_lock);
- kfree(delegation);
+ if (delegation != NULL)
+ nfs_free_delegation(delegation);
return status;
}
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 8ec7fbd8240c..35334539d947 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -562,6 +562,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
nfs_fattr_init(&fattr);
desc->entry = &my_entry;
+ nfs_block_sillyrename(dentry);
while(!desc->entry->eof) {
res = readdir_search_pagecache(desc);
@@ -592,6 +593,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
break;
}
}
+ nfs_unblock_sillyrename(dentry);
unlock_kernel();
if (res > 0)
res = 0;
@@ -866,6 +868,7 @@ struct dentry_operations nfs_dentry_operations = {
static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
{
struct dentry *res;
+ struct dentry *parent;
struct inode *inode = NULL;
int error;
struct nfs_fh fhandle;
@@ -894,26 +897,31 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
goto out_unlock;
}
+ parent = dentry->d_parent;
+ /* Protect against concurrent sillydeletes */
+ nfs_block_sillyrename(parent);
error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);
if (error == -ENOENT)
goto no_entry;
if (error < 0) {
res = ERR_PTR(error);
- goto out_unlock;
+ goto out_unblock_sillyrename;
}
inode = nfs_fhget(dentry->d_sb, &fhandle, &fattr);
res = (struct dentry *)inode;
if (IS_ERR(res))
- goto out_unlock;
+ goto out_unblock_sillyrename;
no_entry:
res = d_materialise_unique(dentry, inode);
if (res != NULL) {
if (IS_ERR(res))
- goto out_unlock;
+ goto out_unblock_sillyrename;
dentry = res;
}
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
+out_unblock_sillyrename:
+ nfs_unblock_sillyrename(parent);
out_unlock:
unlock_kernel();
out:
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 32fe97211eea..afcab007a22b 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -549,13 +549,13 @@ static void nfs_direct_write_result(struct rpc_task *task, void *calldata)
spin_lock(&dreq->lock);
- if (unlikely(dreq->error != 0))
- goto out_unlock;
if (unlikely(status < 0)) {
- /* An error has occured, so we should not commit */
+ /* An error has occurred, so we should not commit */
dreq->flags = 0;
dreq->error = status;
}
+ if (unlikely(dreq->error != 0))
+ goto out_unlock;
dreq->count += data->res.count;
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index c664bb921425..b3bb89f7d5d2 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -131,7 +131,7 @@ nfs_file_release(struct inode *inode, struct file *filp)
{
/* Ensure that dirty pages are flushed out with the right creds */
if (filp->f_mode & FMODE_WRITE)
- filemap_fdatawrite(filp->f_mapping);
+ nfs_wb_all(filp->f_path.dentry->d_inode);
nfs_inc_stats(inode, NFSIOS_VFSRELEASE);
return NFS_PROTO(inode)->file_release(inode, filp);
}
@@ -306,27 +306,50 @@ nfs_fsync(struct file *file, struct dentry *dentry, int datasync)
}
/*
- * This does the "real" work of the write. The generic routine has
- * allocated the page, locked it, done all the page alignment stuff
- * calculations etc. Now we should just copy the data from user
- * space and write it back to the real medium..
+ * This does the "real" work of the write. We must allocate and lock the
+ * page to be sent back to the generic routine, which then copies the
+ * data from user space.
*
* If the writer ends up delaying the write, the writer needs to
* increment the page use counts until he is done with the page.
*/
-static int nfs_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
+static int nfs_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
{
- return nfs_flush_incompatible(file, page);
+ int ret;
+ pgoff_t index;
+ struct page *page;
+ index = pos >> PAGE_CACHE_SHIFT;
+
+ page = __grab_cache_page(mapping, index);
+ if (!page)
+ return -ENOMEM;
+ *pagep = page;
+
+ ret = nfs_flush_incompatible(file, page);
+ if (ret) {
+ unlock_page(page);
+ page_cache_release(page);
+ }
+ return ret;
}
-static int nfs_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to)
+static int nfs_write_end(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata)
{
- long status;
+ unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
+ int status;
lock_kernel();
- status = nfs_updatepage(file, page, offset, to-offset);
+ status = nfs_updatepage(file, page, offset, copied);
unlock_kernel();
- return status;
+
+ unlock_page(page);
+ page_cache_release(page);
+
+ return status < 0 ? status : copied;
}
static void nfs_invalidate_page(struct page *page, unsigned long offset)
@@ -354,8 +377,8 @@ const struct address_space_operations nfs_file_aops = {
.set_page_dirty = __set_page_dirty_nobuffers,
.writepage = nfs_writepage,
.writepages = nfs_writepages,
- .prepare_write = nfs_prepare_write,
- .commit_write = nfs_commit_write,
+ .write_begin = nfs_write_begin,
+ .write_end = nfs_write_end,
.invalidatepage = nfs_invalidate_page,
.releasepage = nfs_release_page,
#ifdef CONFIG_NFS_DIRECTIO
@@ -369,18 +392,35 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct page *page)
struct file *filp = vma->vm_file;
unsigned pagelen;
int ret = -EINVAL;
+ void *fsdata;
+ struct address_space *mapping;
+ loff_t offset;
lock_page(page);
- if (page->mapping != vma->vm_file->f_path.dentry->d_inode->i_mapping)
- goto out_unlock;
+ mapping = page->mapping;
+ if (mapping != vma->vm_file->f_path.dentry->d_inode->i_mapping) {
+ unlock_page(page);
+ return -EINVAL;
+ }
pagelen = nfs_page_length(page);
- if (pagelen == 0)
- goto out_unlock;
- ret = nfs_prepare_write(filp, page, 0, pagelen);
- if (!ret)
- ret = nfs_commit_write(filp, page, 0, pagelen);
-out_unlock:
+ offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
unlock_page(page);
+
+ /*
+ * we can use mapping after releasing the page lock, because:
+ * we hold mmap_sem on the fault path, which should pin the vma
+ * which should pin the file, which pins the dentry which should
+ * hold a reference on inode.
+ */
+
+ if (pagelen) {
+ struct page *page2 = NULL;
+ ret = nfs_write_begin(filp, mapping, offset, pagelen,
+ 0, &page2, &fsdata);
+ if (!ret)
+ ret = nfs_write_end(filp, mapping, offset, pagelen,
+ pagelen, page2, fsdata);
+ }
return ret;
}
@@ -577,8 +617,7 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
nfs_inc_stats(inode, NFSIOS_VFSLOCK);
/* No mandatory locks over NFS */
- if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID &&
- fl->fl_type != F_UNLCK)
+ if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK)
return -ENOLCK;
if (IS_GETLK(cmd))
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 035c769b715e..db5d96dc6107 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -357,6 +357,10 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
nfs_inc_stats(inode, NFSIOS_VFSSETATTR);
+ /* skip mode change if it's just for clearing setuid/setgid */
+ if (attr->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
+ attr->ia_valid &= ~ATTR_MODE;
+
if (attr->ia_valid & ATTR_SIZE) {
if (!S_ISREG(inode->i_mode) || attr->ia_size == i_size_read(inode))
attr->ia_valid &= ~ATTR_SIZE;
@@ -510,7 +514,7 @@ struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
return ctx;
}
-void put_nfs_open_context(struct nfs_open_context *ctx)
+static void __put_nfs_open_context(struct nfs_open_context *ctx, int wait)
{
struct inode *inode = ctx->path.dentry->d_inode;
@@ -518,8 +522,12 @@ void put_nfs_open_context(struct nfs_open_context *ctx)
return;
list_del(&ctx->list);
spin_unlock(&inode->i_lock);
- if (ctx->state != NULL)
- nfs4_close_state(&ctx->path, ctx->state, ctx->mode);
+ if (ctx->state != NULL) {
+ if (wait)
+ nfs4_close_sync(&ctx->path, ctx->state, ctx->mode);
+ else
+ nfs4_close_state(&ctx->path, ctx->state, ctx->mode);
+ }
if (ctx->cred != NULL)
put_rpccred(ctx->cred);
dput(ctx->path.dentry);
@@ -527,6 +535,16 @@ void put_nfs_open_context(struct nfs_open_context *ctx)
kfree(ctx);
}
+void put_nfs_open_context(struct nfs_open_context *ctx)
+{
+ __put_nfs_open_context(ctx, 0);
+}
+
+static void put_nfs_open_context_sync(struct nfs_open_context *ctx)
+{
+ __put_nfs_open_context(ctx, 1);
+}
+
/*
* Ensure that mmap has a recent RPC credential for use when writing out
* shared pages
@@ -573,7 +591,7 @@ static void nfs_file_clear_open_context(struct file *filp)
spin_lock(&inode->i_lock);
list_move_tail(&ctx->list, &NFS_I(inode)->open_files);
spin_unlock(&inode->i_lock);
- put_nfs_open_context(ctx);
+ put_nfs_open_context_sync(ctx);
}
}
@@ -1154,7 +1172,7 @@ static inline void nfs4_init_once(struct nfs_inode *nfsi)
#endif
}
-static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
+static void init_once(struct kmem_cache * cachep, void *foo)
{
struct nfs_inode *nfsi = (struct nfs_inode *) foo;
@@ -1165,6 +1183,9 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag
INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC);
nfsi->ncommit = 0;
nfsi->npages = 0;
+ atomic_set(&nfsi->silly_count, 1);
+ INIT_HLIST_HEAD(&nfsi->silly_list);
+ init_waitqueue_head(&nfsi->waitqueue);
nfs4_init_once(nfsi);
}
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index d2802b1ca3b9..b35069a2aa9e 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -178,7 +178,7 @@ extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struc
extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct rpc_cred *);
extern int nfs4_proc_async_renew(struct nfs_client *, struct rpc_cred *);
extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *);
-extern int nfs4_do_close(struct path *path, struct nfs4_state *state);
+extern int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait);
extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *);
extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle);
@@ -209,6 +209,7 @@ extern void nfs4_drop_state_owner(struct nfs4_state_owner *);
extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *);
extern void nfs4_put_open_state(struct nfs4_state *);
extern void nfs4_close_state(struct path *, struct nfs4_state *, mode_t);
+extern void nfs4_close_sync(struct path *, struct nfs4_state *, mode_t);
extern void nfs4_state_set_mode_locked(struct nfs4_state *, mode_t);
extern void nfs4_schedule_state_recovery(struct nfs_client *);
extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp);
@@ -235,6 +236,7 @@ extern struct svc_version nfs4_callback_version1;
#else
#define nfs4_close_state(a, b, c) do { } while (0)
+#define nfs4_close_sync(a, b, c) do { } while (0)
#endif /* CONFIG_NFS_V4 */
#endif /* __LINUX_FS_NFS_NFS4_FS.H */
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index cb99fd90a9ac..f03d9d5f5ba4 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1305,7 +1305,7 @@ static const struct rpc_call_ops nfs4_close_ops = {
*
* NOTE: Caller must be holding the sp->so_owner semaphore!
*/
-int nfs4_do_close(struct path *path, struct nfs4_state *state)
+int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait)
{
struct nfs_server *server = NFS_SERVER(state->inode);
struct nfs4_closedata *calldata;
@@ -1333,8 +1333,11 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state)
task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_close_ops, calldata);
if (IS_ERR(task))
return PTR_ERR(task);
+ status = 0;
+ if (wait)
+ status = rpc_wait_for_completion_task(task);
rpc_put_task(task);
- return 0;
+ return status;
out_free_calldata:
kfree(calldata);
out:
@@ -1365,13 +1368,14 @@ static int nfs4_intent_set_file(struct nameidata *nd, struct path *path, struct
}
ret = PTR_ERR(filp);
out_close:
- nfs4_close_state(path, state, nd->intent.open.flags);
+ nfs4_close_sync(path, state, nd->intent.open.flags);
return ret;
}
struct dentry *
nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
+ struct dentry *parent;
struct path path = {
.mnt = nd->mnt,
.dentry = dentry,
@@ -1394,6 +1398,9 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0);
if (IS_ERR(cred))
return (struct dentry *)cred;
+ parent = dentry->d_parent;
+ /* Protect against concurrent sillydeletes */
+ nfs_block_sillyrename(parent);
state = nfs4_do_open(dir, &path, nd->intent.open.flags, &attr, cred);
put_rpccred(cred);
if (IS_ERR(state)) {
@@ -1401,12 +1408,14 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
d_add(dentry, NULL);
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
}
+ nfs_unblock_sillyrename(parent);
return (struct dentry *)state;
}
res = d_add_unique(dentry, igrab(state->inode));
if (res != NULL)
path.dentry = res;
nfs_set_verifier(path.dentry, nfs_save_change_attribute(dir));
+ nfs_unblock_sillyrename(parent);
nfs4_intent_set_file(nd, &path, state);
return res;
}
@@ -1444,7 +1453,7 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st
nfs4_intent_set_file(nd, &path, state);
return 1;
}
- nfs4_close_state(&path, state, openflags);
+ nfs4_close_sync(&path, state, openflags);
out_drop:
d_drop(dentry);
return 0;
@@ -1898,7 +1907,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0)
status = nfs4_intent_set_file(nd, &path, state);
else
- nfs4_close_state(&path, state, flags);
+ nfs4_close_sync(&path, state, flags);
out:
return status;
}
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index bfb36261cecb..23a9a36556bf 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -425,7 +425,7 @@ void nfs4_put_open_state(struct nfs4_state *state)
/*
* Close the current file.
*/
-void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode)
+static void __nfs4_close(struct path *path, struct nfs4_state *state, mode_t mode, int wait)
{
struct nfs4_state_owner *owner = state->owner;
int call_close = 0;
@@ -466,7 +466,17 @@ void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode)
nfs4_put_open_state(state);
nfs4_put_state_owner(owner);
} else
- nfs4_do_close(path, state);
+ nfs4_do_close(path, state, wait);
+}
+
+void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode)
+{
+ __nfs4_close(path, state, mode, 0);
+}
+
+void nfs4_close_sync(struct path *path, struct nfs4_state *state, mode_t mode)
+{
+ __nfs4_close(path, state, mode, 1);
}
/*
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c
index e87b44ee9ac9..4b0334590ee5 100644
--- a/fs/nfs/nfsroot.c
+++ b/fs/nfs/nfsroot.c
@@ -43,7 +43,7 @@
* from being used (thanks to Leo Spiekman)
* Andy Walker : Allow to specify the NFS server in nfs_root
* without giving a path name
- * Swen Thümmler : Allow to specify the NFS options in nfs_root
+ * Swen Thümmler : Allow to specify the NFS options in nfs_root
* without giving a path name. Fix BOOTP request
* for domainname (domainname is NIS domain, not
* DNS domain!). Skip dummy devices for BOOTP.
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 97669ed05500..4f80d88e9fee 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -211,6 +211,7 @@ nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
nfs_fattr_init(&fattr);
dprintk("NFS call create %s\n", dentry->d_name.name);
status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ nfs_mark_for_revalidate(dir);
if (status == 0)
status = nfs_instantiate(dentry, &fhandle, &fattr);
dprintk("NFS reply create: %d\n", status);
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index 1aed850d18f2..233ad38161f9 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -11,9 +11,11 @@
#include <linux/sunrpc/sched.h>
#include <linux/sunrpc/clnt.h>
#include <linux/nfs_fs.h>
-
+#include <linux/sched.h>
+#include <linux/wait.h>
struct nfs_unlinkdata {
+ struct hlist_node list;
struct nfs_removeargs args;
struct nfs_removeres res;
struct inode *dir;
@@ -52,6 +54,20 @@ static int nfs_copy_dname(struct dentry *dentry, struct nfs_unlinkdata *data)
return 0;
}
+static void nfs_free_dname(struct nfs_unlinkdata *data)
+{
+ kfree(data->args.name.name);
+ data->args.name.name = NULL;
+ data->args.name.len = 0;
+}
+
+static void nfs_dec_sillycount(struct inode *dir)
+{
+ struct nfs_inode *nfsi = NFS_I(dir);
+ if (atomic_dec_return(&nfsi->silly_count) == 1)
+ wake_up(&nfsi->waitqueue);
+}
+
/**
* nfs_async_unlink_init - Initialize the RPC info
* task: rpc_task of the sillydelete
@@ -95,6 +111,8 @@ static void nfs_async_unlink_done(struct rpc_task *task, void *calldata)
static void nfs_async_unlink_release(void *calldata)
{
struct nfs_unlinkdata *data = calldata;
+
+ nfs_dec_sillycount(data->dir);
nfs_free_unlinkdata(data);
}
@@ -104,33 +122,100 @@ static const struct rpc_call_ops nfs_unlink_ops = {
.rpc_release = nfs_async_unlink_release,
};
-static int nfs_call_unlink(struct dentry *dentry, struct nfs_unlinkdata *data)
+static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct nfs_unlinkdata *data)
{
struct rpc_task *task;
+ struct dentry *alias;
+
+ alias = d_lookup(parent, &data->args.name);
+ if (alias != NULL) {
+ int ret = 0;
+ /*
+ * Hey, we raced with lookup... See if we need to transfer
+ * the sillyrename information to the aliased dentry.
+ */
+ nfs_free_dname(data);
+ spin_lock(&alias->d_lock);
+ if (!(alias->d_flags & DCACHE_NFSFS_RENAMED)) {
+ alias->d_fsdata = data;
+ alias->d_flags ^= DCACHE_NFSFS_RENAMED;
+ ret = 1;
+ }
+ spin_unlock(&alias->d_lock);
+ nfs_dec_sillycount(dir);
+ dput(alias);
+ return ret;
+ }
+ data->dir = igrab(dir);
+ if (!data->dir) {
+ nfs_dec_sillycount(dir);
+ return 0;
+ }
+ data->args.fh = NFS_FH(dir);
+ nfs_fattr_init(&data->res.dir_attr);
+
+ task = rpc_run_task(NFS_CLIENT(dir), RPC_TASK_ASYNC, &nfs_unlink_ops, data);
+ if (!IS_ERR(task))
+ rpc_put_task(task);
+ return 1;
+}
+
+static int nfs_call_unlink(struct dentry *dentry, struct nfs_unlinkdata *data)
+{
struct dentry *parent;
struct inode *dir;
+ int ret = 0;
- if (nfs_copy_dname(dentry, data) < 0)
- goto out_free;
parent = dget_parent(dentry);
if (parent == NULL)
goto out_free;
- dir = igrab(parent->d_inode);
+ dir = parent->d_inode;
+ if (nfs_copy_dname(dentry, data) != 0)
+ goto out_dput;
+ /* Non-exclusive lock protects against concurrent lookup() calls */
+ spin_lock(&dir->i_lock);
+ if (atomic_inc_not_zero(&NFS_I(dir)->silly_count) == 0) {
+ /* Deferred delete */
+ hlist_add_head(&data->list, &NFS_I(dir)->silly_list);
+ spin_unlock(&dir->i_lock);
+ ret = 1;
+ goto out_dput;
+ }
+ spin_unlock(&dir->i_lock);
+ ret = nfs_do_call_unlink(parent, dir, data);
+out_dput:
dput(parent);
- if (dir == NULL)
- goto out_free;
+out_free:
+ return ret;
+}
- data->dir = dir;
- data->args.fh = NFS_FH(dir);
- nfs_fattr_init(&data->res.dir_attr);
+void nfs_block_sillyrename(struct dentry *dentry)
+{
+ struct nfs_inode *nfsi = NFS_I(dentry->d_inode);
- task = rpc_run_task(NFS_CLIENT(dir), RPC_TASK_ASYNC, &nfs_unlink_ops, data);
- if (!IS_ERR(task))
- rpc_put_task(task);
- return 1;
-out_free:
- return 0;
+ wait_event(nfsi->waitqueue, atomic_cmpxchg(&nfsi->silly_count, 1, 0) == 1);
+}
+
+void nfs_unblock_sillyrename(struct dentry *dentry)
+{
+ struct inode *dir = dentry->d_inode;
+ struct nfs_inode *nfsi = NFS_I(dir);
+ struct nfs_unlinkdata *data;
+
+ atomic_inc(&nfsi->silly_count);
+ spin_lock(&dir->i_lock);
+ while (!hlist_empty(&nfsi->silly_list)) {
+ if (!atomic_inc_not_zero(&nfsi->silly_count))
+ break;
+ data = hlist_entry(nfsi->silly_list.first, struct nfs_unlinkdata, list);
+ hlist_del(&data->list);
+ spin_unlock(&dir->i_lock);
+ if (nfs_do_call_unlink(dentry, dir, data) == 0)
+ nfs_free_unlinkdata(data);
+ spin_lock(&dir->i_lock);
+ }
+ spin_unlock(&dir->i_lock);
}
/**
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index e2bb66c34406..89527a487ed7 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -174,8 +174,6 @@ static void nfs_mark_uptodate(struct page *page, unsigned int base, unsigned int
return;
if (count != nfs_page_length(page))
return;
- if (count != PAGE_CACHE_SIZE)
- zero_user_page(page, count, PAGE_CACHE_SIZE - count, KM_USER0);
SetPageUptodate(page);
}
@@ -242,10 +240,8 @@ static void nfs_end_page_writeback(struct page *page)
struct nfs_server *nfss = NFS_SERVER(inode);
end_page_writeback(page);
- if (atomic_long_dec_return(&nfss->writeback) < NFS_CONGESTION_OFF_THRESH) {
+ if (atomic_long_dec_return(&nfss->writeback) < NFS_CONGESTION_OFF_THRESH)
clear_bdi_congested(&nfss->backing_dev_info, WRITE);
- congestion_end(WRITE);
- }
}
/*
@@ -449,6 +445,7 @@ nfs_mark_request_commit(struct nfs_page *req)
NFS_PAGE_TAG_COMMIT);
spin_unlock(&inode->i_lock);
inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
+ inc_bdi_stat(req->wb_page->mapping->backing_dev_info, BDI_RECLAIMABLE);
__mark_inode_dirty(inode, I_DIRTY_DATASYNC);
}
@@ -535,6 +532,8 @@ static void nfs_cancel_commit_list(struct list_head *head)
while(!list_empty(head)) {
req = nfs_list_entry(head->next);
dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
+ dec_bdi_stat(req->wb_page->mapping->backing_dev_info,
+ BDI_RECLAIMABLE);
nfs_list_remove_request(req);
clear_bit(PG_NEED_COMMIT, &(req)->wb_flags);
nfs_inode_remove_request(req);
@@ -626,7 +625,8 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx,
return ERR_PTR(error);
}
spin_unlock(&inode->i_lock);
- return new;
+ req = new;
+ goto zero_page;
}
spin_unlock(&inode->i_lock);
@@ -654,13 +654,23 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx,
if (offset < req->wb_offset) {
req->wb_offset = offset;
req->wb_pgbase = offset;
- req->wb_bytes = rqend - req->wb_offset;
+ req->wb_bytes = max(end, rqend) - req->wb_offset;
+ goto zero_page;
}
if (end > rqend)
req->wb_bytes = end - req->wb_offset;
return req;
+zero_page:
+ /* If this page might potentially be marked as up to date,
+ * then we need to zero any uninitalised data. */
+ if (req->wb_pgbase == 0 && req->wb_bytes != PAGE_CACHE_SIZE
+ && !PageUptodate(req->wb_page))
+ zero_user_page(req->wb_page, req->wb_bytes,
+ PAGE_CACHE_SIZE - req->wb_bytes,
+ KM_USER0);
+ return req;
}
int nfs_flush_incompatible(struct file *file, struct page *page)
@@ -1195,6 +1205,8 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how)
nfs_list_remove_request(req);
nfs_mark_request_commit(req);
dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
+ dec_bdi_stat(req->wb_page->mapping->backing_dev_info,
+ BDI_RECLAIMABLE);
nfs_clear_page_tag_locked(req);
}
return -ENOMEM;
@@ -1220,6 +1232,8 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata)
nfs_list_remove_request(req);
clear_bit(PG_NEED_COMMIT, &(req)->wb_flags);
dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
+ dec_bdi_stat(req->wb_page->mapping->backing_dev_info,
+ BDI_RECLAIMABLE);
dprintk("NFS: commit (%s/%Ld %d@%Ld)",
req->wb_context->path.dentry->d_inode->i_sb->s_id,
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index cba899a3494e..66d0aeb32a47 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -386,15 +386,13 @@ static int check_export(struct inode *inode, int flags, unsigned char *uuid)
dprintk("exp_export: export of non-dev fs without fsid\n");
return -EINVAL;
}
- if (!inode->i_sb->s_export_op) {
+
+ if (!inode->i_sb->s_export_op ||
+ !inode->i_sb->s_export_op->fh_to_dentry) {
dprintk("exp_export: export of invalid fs type.\n");
return -EINVAL;
}
- /* Ok, we can export it */;
- if (!inode->i_sb->s_export_op->find_exported_dentry)
- inode->i_sb->s_export_op->find_exported_dentry =
- find_exported_dentry;
return 0;
}
@@ -861,9 +859,9 @@ exp_get_fsid_key(svc_client *clp, int fsid)
return exp_find_key(clp, FSID_NUM, fsidv, NULL);
}
-svc_export *
-exp_get_by_name(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry,
- struct cache_req *reqp)
+static svc_export *exp_get_by_name(svc_client *clp, struct vfsmount *mnt,
+ struct dentry *dentry,
+ struct cache_req *reqp)
{
struct svc_export *exp, key;
int err;
@@ -887,9 +885,9 @@ exp_get_by_name(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry,
/*
* Find the export entry for a given dentry.
*/
-struct svc_export *
-exp_parent(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry,
- struct cache_req *reqp)
+static struct svc_export *exp_parent(svc_client *clp, struct vfsmount *mnt,
+ struct dentry *dentry,
+ struct cache_req *reqp)
{
svc_export *exp;
@@ -1214,9 +1212,8 @@ out:
return err;
}
-struct svc_export *
-exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv,
- struct cache_req *reqp)
+static struct svc_export *exp_find(struct auth_domain *clp, int fsid_type,
+ u32 *fsidv, struct cache_req *reqp)
{
struct svc_export *exp;
struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv, reqp);
diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
index b61742885011..0e5fa11e6b44 100644
--- a/fs/nfsd/nfs2acl.c
+++ b/fs/nfsd/nfs2acl.c
@@ -41,7 +41,7 @@ static __be32 nfsacld_proc_getacl(struct svc_rqst * rqstp,
fh = fh_copy(&resp->fh, &argp->fh);
if ((nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP)))
- RETURN_STATUS(nfserr_inval);
+ RETURN_STATUS(nfserr);
if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
RETURN_STATUS(nfserr_inval);
diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c
index 3e3f2de82c36..b647f2f872dc 100644
--- a/fs/nfsd/nfs3acl.c
+++ b/fs/nfsd/nfs3acl.c
@@ -37,7 +37,7 @@ static __be32 nfsd3_proc_getacl(struct svc_rqst * rqstp,
fh = fh_copy(&resp->fh, &argp->fh);
if ((nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP)))
- RETURN_STATUS(nfserr_inval);
+ RETURN_STATUS(nfserr);
if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
RETURN_STATUS(nfserr_inval);
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index ebd03cc07479..1602cd00dd45 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -43,7 +43,7 @@
#include <linux/file.h>
#include <linux/namei.h>
#include <asm/uaccess.h>
-#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
#include <linux/crypto.h>
#include <linux/sched.h>
@@ -88,7 +88,7 @@ nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname)
{
struct xdr_netobj cksum;
struct hash_desc desc;
- struct scatterlist sg[1];
+ struct scatterlist sg;
__be32 status = nfserr_resource;
dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n",
@@ -102,11 +102,9 @@ nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname)
if (cksum.data == NULL)
goto out;
- sg[0].page = virt_to_page(clname->data);
- sg[0].offset = offset_in_page(clname->data);
- sg[0].length = clname->len;
+ sg_init_one(&sg, clname->data, clname->len);
- if (crypto_hash_digest(&desc, sg, sg->length, cksum.data))
+ if (crypto_hash_digest(&desc, &sg, sg.length, cksum.data))
goto out;
md5_to_hex(dname, cksum.data);
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 6f182d25793d..31673cd251c3 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -2035,7 +2035,7 @@ static inline int
io_during_grace_disallowed(struct inode *inode, int flags)
{
return nfs4_in_grace() && (flags & (RD_STATE | WR_STATE))
- && MANDATORY_LOCK(inode);
+ && mandatory_lock(inode);
}
/*
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 7011d62acfc8..468f17a78441 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -95,6 +95,22 @@ nfsd_mode_check(struct svc_rqst *rqstp, umode_t mode, int type)
return 0;
}
+static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp,
+ struct svc_export *exp)
+{
+ /* Check if the request originated from a secure port. */
+ if (!rqstp->rq_secure && EX_SECURE(exp)) {
+ char buf[RPC_MAX_ADDRBUFLEN];
+ dprintk(KERN_WARNING
+ "nfsd: request from insecure port %s!\n",
+ svc_print_addr(rqstp, buf, sizeof(buf)));
+ return nfserr_perm;
+ }
+
+ /* Set user creds for this exportpoint */
+ return nfserrno(nfsd_setuser(rqstp, exp));
+}
+
/*
* Perform sanity checks on the dentry in a client's file handle.
*
@@ -115,8 +131,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp));
if (!fhp->fh_dentry) {
- __u32 *datap=NULL;
- __u32 tfh[3]; /* filehandle fragment for oldstyle filehandles */
+ struct fid *fid = NULL, sfid;
int fileid_type;
int data_left = fh->fh_size/4;
@@ -128,7 +143,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
if (fh->fh_version == 1) {
int len;
- datap = fh->fh_auth;
if (--data_left<0) goto out;
switch (fh->fh_auth_type) {
case 0: break;
@@ -144,9 +158,11 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
fh->fh_fsid[1] = fh->fh_fsid[2];
}
if ((data_left -= len)<0) goto out;
- exp = rqst_exp_find(rqstp, fh->fh_fsid_type, datap);
- datap += len;
+ exp = rqst_exp_find(rqstp, fh->fh_fsid_type,
+ fh->fh_auth);
+ fid = (struct fid *)(fh->fh_auth + len);
} else {
+ __u32 tfh[2];
dev_t xdev;
ino_t xino;
if (fh->fh_size != NFS_FHSIZE)
@@ -167,18 +183,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
goto out;
}
- /* Check if the request originated from a secure port. */
- error = nfserr_perm;
- if (!rqstp->rq_secure && EX_SECURE(exp)) {
- char buf[RPC_MAX_ADDRBUFLEN];
- printk(KERN_WARNING
- "nfsd: request from insecure port %s!\n",
- svc_print_addr(rqstp, buf, sizeof(buf)));
- goto out;
- }
-
- /* Set user creds for this exportpoint */
- error = nfserrno(nfsd_setuser(rqstp, exp));
+ error = nfsd_setuser_and_check_port(rqstp, exp);
if (error)
goto out;
@@ -190,22 +195,22 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
error = nfserr_badhandle;
if (fh->fh_version != 1) {
- tfh[0] = fh->ofh_ino;
- tfh[1] = fh->ofh_generation;
- tfh[2] = fh->ofh_dirino;
- datap = tfh;
+ sfid.i32.ino = fh->ofh_ino;
+ sfid.i32.gen = fh->ofh_generation;
+ sfid.i32.parent_ino = fh->ofh_dirino;
+ fid = &sfid;
data_left = 3;
if (fh->ofh_dirino == 0)
- fileid_type = 1;
+ fileid_type = FILEID_INO32_GEN;
else
- fileid_type = 2;
+ fileid_type = FILEID_INO32_GEN_PARENT;
} else
fileid_type = fh->fh_fileid_type;
- if (fileid_type == 0)
+ if (fileid_type == FILEID_ROOT)
dentry = dget(exp->ex_dentry);
else {
- dentry = exportfs_decode_fh(exp->ex_mnt, datap,
+ dentry = exportfs_decode_fh(exp->ex_mnt, fid,
data_left, fileid_type,
nfsd_acceptable, exp);
}
@@ -227,18 +232,22 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
fhp->fh_export = exp;
nfsd_nr_verified++;
} else {
- /* just rechecking permissions
- * (e.g. nfsproc_create calls fh_verify, then nfsd_create does as well)
+ /*
+ * just rechecking permissions
+ * (e.g. nfsproc_create calls fh_verify, then nfsd_create
+ * does as well)
*/
dprintk("nfsd: fh_verify - just checking\n");
dentry = fhp->fh_dentry;
exp = fhp->fh_export;
- /* Set user creds for this exportpoint; necessary even
+ /*
+ * Set user creds for this exportpoint; necessary even
* in the "just checking" case because this may be a
* filehandle that was created by fh_compose, and that
* is about to be used in another nfsv4 compound
- * operation */
- error = nfserrno(nfsd_setuser(rqstp, exp));
+ * operation.
+ */
+ error = nfsd_setuser_and_check_port(rqstp, exp);
if (error)
goto out;
}
@@ -286,16 +295,21 @@ out:
* an inode. In this case a call to fh_update should be made
* before the fh goes out on the wire ...
*/
-static inline int _fh_update(struct dentry *dentry, struct svc_export *exp,
- __u32 *datap, int *maxsize)
+static void _fh_update(struct svc_fh *fhp, struct svc_export *exp,
+ struct dentry *dentry)
{
- if (dentry == exp->ex_dentry) {
- *maxsize = 0;
- return 0;
- }
+ if (dentry != exp->ex_dentry) {
+ struct fid *fid = (struct fid *)
+ (fhp->fh_handle.fh_auth + fhp->fh_handle.fh_size/4 - 1);
+ int maxsize = (fhp->fh_maxsize - fhp->fh_handle.fh_size)/4;
+ int subtreecheck = !(exp->ex_flags & NFSEXP_NOSUBTREECHECK);
- return exportfs_encode_fh(dentry, datap, maxsize,
- !(exp->ex_flags & NFSEXP_NOSUBTREECHECK));
+ fhp->fh_handle.fh_fileid_type =
+ exportfs_encode_fh(dentry, fid, &maxsize, subtreecheck);
+ fhp->fh_handle.fh_size += maxsize * 4;
+ } else {
+ fhp->fh_handle.fh_fileid_type = FILEID_ROOT;
+ }
}
/*
@@ -457,12 +471,8 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
datap += len/4;
fhp->fh_handle.fh_size = 4 + len;
- if (inode) {
- int size = (fhp->fh_maxsize-len-4)/4;
- fhp->fh_handle.fh_fileid_type =
- _fh_update(dentry, exp, datap, &size);
- fhp->fh_handle.fh_size += size*4;
- }
+ if (inode)
+ _fh_update(fhp, exp, dentry);
if (fhp->fh_handle.fh_fileid_type == 255)
return nfserr_opnotsupp;
}
@@ -479,7 +489,6 @@ __be32
fh_update(struct svc_fh *fhp)
{
struct dentry *dentry;
- __u32 *datap;
if (!fhp->fh_dentry)
goto out_bad;
@@ -490,15 +499,10 @@ fh_update(struct svc_fh *fhp)
if (fhp->fh_handle.fh_version != 1) {
_fh_update_old(dentry, fhp->fh_export, &fhp->fh_handle);
} else {
- int size;
- if (fhp->fh_handle.fh_fileid_type != 0)
+ if (fhp->fh_handle.fh_fileid_type != FILEID_ROOT)
goto out;
- datap = fhp->fh_handle.fh_auth+
- fhp->fh_handle.fh_size/4 -1;
- size = (fhp->fh_maxsize - fhp->fh_handle.fh_size)/4;
- fhp->fh_handle.fh_fileid_type =
- _fh_update(dentry, fhp->fh_export, datap, &size);
- fhp->fh_handle.fh_size += size*4;
+
+ _fh_update(fhp, fhp->fh_export, dentry);
if (fhp->fh_handle.fh_fileid_type == 255)
return nfserr_opnotsupp;
}
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index cec78c82b1f9..d0199189924c 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -61,12 +61,6 @@
#define NFSDDBG_FACILITY NFSDDBG_FILEOP
-/* We must ignore files (but only files) which might have mandatory
- * locks on them because there is no way to know if the accesser has
- * the lock.
- */
-#define IS_ISMNDLK(i) (S_ISREG((i)->i_mode) && MANDATORY_LOCK(i))
-
/*
* This is a cache of readahead params that help us choose the proper
* readahead strategy. Initially, we set all readahead parameters to 0
@@ -370,14 +364,23 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
if (iap->ia_valid & ATTR_MODE) {
iap->ia_mode &= S_IALLUGO;
imode = iap->ia_mode |= (imode & ~S_IALLUGO);
+ /* if changing uid/gid revoke setuid/setgid in mode */
+ if ((iap->ia_valid & ATTR_UID) && iap->ia_uid != inode->i_uid) {
+ iap->ia_valid |= ATTR_KILL_PRIV;
+ iap->ia_mode &= ~S_ISUID;
+ }
+ if ((iap->ia_valid & ATTR_GID) && iap->ia_gid != inode->i_gid)
+ iap->ia_mode &= ~S_ISGID;
+ } else {
+ /*
+ * Revoke setuid/setgid bit on chown/chgrp
+ */
+ if ((iap->ia_valid & ATTR_UID) && iap->ia_uid != inode->i_uid)
+ iap->ia_valid |= ATTR_KILL_SUID | ATTR_KILL_PRIV;
+ if ((iap->ia_valid & ATTR_GID) && iap->ia_gid != inode->i_gid)
+ iap->ia_valid |= ATTR_KILL_SGID;
}
- /* Revoke setuid/setgid bit on chown/chgrp */
- if ((iap->ia_valid & ATTR_UID) && iap->ia_uid != inode->i_uid)
- iap->ia_valid |= ATTR_KILL_SUID;
- if ((iap->ia_valid & ATTR_GID) && iap->ia_gid != inode->i_gid)
- iap->ia_valid |= ATTR_KILL_SGID;
-
/* Change the attributes. */
iap->ia_valid |= ATTR_CTIME;
@@ -689,7 +692,12 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
err = nfserr_perm;
if (IS_APPEND(inode) && (access & MAY_WRITE))
goto out;
- if (IS_ISMNDLK(inode))
+ /*
+ * We must ignore files (but only files) which might have mandatory
+ * locks on them because there is no way to know if the accesser has
+ * the lock.
+ */
+ if (S_ISREG((inode)->i_mode) && mandatory_lock(inode))
goto out;
if (!inode->i_fop)
@@ -866,6 +874,15 @@ static int nfsd_direct_splice_actor(struct pipe_inode_info *pipe,
return __splice_from_pipe(pipe, sd, nfsd_splice_actor);
}
+static inline int svc_msnfs(struct svc_fh *ffhp)
+{
+#ifdef MSNFS
+ return (ffhp->fh_export->ex_flags & NFSEXP_MSNFS);
+#else
+ return 0;
+#endif
+}
+
static __be32
nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
loff_t offset, struct kvec *vec, int vlen, unsigned long *count)
@@ -878,11 +895,9 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
err = nfserr_perm;
inode = file->f_path.dentry->d_inode;
-#ifdef MSNFS
- if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
- (!lock_may_read(inode, offset, *count)))
+
+ if (svc_msnfs(fhp) && !lock_may_read(inode, offset, *count))
goto out;
-#endif
/* Get readahead parameters */
ra = nfsd_get_raparms(inode->i_sb->s_dev, inode->i_ino);
@@ -931,7 +946,7 @@ out:
static void kill_suid(struct dentry *dentry)
{
struct iattr ia;
- ia.ia_valid = ATTR_KILL_SUID | ATTR_KILL_SGID;
+ ia.ia_valid = ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
mutex_lock(&dentry->d_inode->i_mutex);
notify_change(dentry, &ia);
@@ -1014,13 +1029,13 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
if (EX_WGATHER(exp)) {
if (atomic_read(&inode->i_writecount) > 1
|| (last_ino == inode->i_ino && last_dev == inode->i_sb->s_dev)) {
- dprintk("nfsd: write defer %d\n", current->pid);
+ dprintk("nfsd: write defer %d\n", task_pid_nr(current));
msleep(10);
- dprintk("nfsd: write resume %d\n", current->pid);
+ dprintk("nfsd: write resume %d\n", task_pid_nr(current));
}
if (inode->i_state & I_DIRTY) {
- dprintk("nfsd: write sync %d\n", current->pid);
+ dprintk("nfsd: write sync %d\n", task_pid_nr(current));
host_err=nfsd_sync(file);
}
#if 0
diff --git a/fs/nls/Kconfig b/fs/nls/Kconfig
index 976ecccd6f56..a39edc41becc 100644
--- a/fs/nls/Kconfig
+++ b/fs/nls/Kconfig
@@ -2,10 +2,8 @@
# Native language support configuration
#
-menu "Native Language Support"
-
-config NLS
- tristate "Base native language support"
+menuconfig NLS
+ tristate "Native language support"
---help---
The base Native Language Support. A number of filesystems
depend on it (e.g. FAT, JOLIET, NT, BEOS filesystems), as well
@@ -17,9 +15,10 @@ config NLS
To compile this code as a module, choose M here: the module
will be called nls_base.
+if NLS
+
config NLS_DEFAULT
string "Default NLS Option"
- depends on NLS
default "iso8859-1"
---help---
The default NLS used when mounting file system. Note, that this is
@@ -39,7 +38,6 @@ config NLS_DEFAULT
config NLS_CODEPAGE_437
tristate "Codepage 437 (United States, Canada)"
- depends on NLS
help
The Microsoft FAT file system family can deal with filenames in
native language character sets. These character sets are stored
@@ -52,7 +50,6 @@ config NLS_CODEPAGE_437
config NLS_CODEPAGE_737
tristate "Codepage 737 (Greek)"
- depends on NLS
help
The Microsoft FAT file system family can deal with filenames in
native language character sets. These character sets are stored
@@ -65,7 +62,6 @@ config NLS_CODEPAGE_737
config NLS_CODEPAGE_775
tristate "Codepage 775 (Baltic Rim)"
- depends on NLS
help
The Microsoft FAT file system family can deal with filenames in
native language character sets. These character sets are stored
@@ -79,7 +75,6 @@ config NLS_CODEPAGE_775
config NLS_CODEPAGE_850
tristate "Codepage 850 (Europe)"
- depends on NLS
---help---
The Microsoft FAT file system family can deal with filenames in
native language character sets. These character sets are stored in
@@ -96,7 +91,6 @@ config NLS_CODEPAGE_850
config NLS_CODEPAGE_852
tristate "Codepage 852 (Central/Eastern Europe)"
- depends on NLS
---help---
The Microsoft FAT file system family can deal with filenames in
native language character sets. These character sets are stored in
@@ -112,7 +106,6 @@ config NLS_CODEPAGE_852
config NLS_CODEPAGE_855
tristate "Codepage 855 (Cyrillic)"
- depends on NLS
help
The Microsoft FAT file system family can deal with filenames in
native language character sets. These character sets are stored in
@@ -124,7 +117,6 @@ config NLS_CODEPAGE_855
config NLS_CODEPAGE_857
tristate "Codepage 857 (Turkish)"
- depends on NLS
help
The Microsoft FAT file system family can deal with filenames in
native language character sets. These character sets are stored in
@@ -136,7 +128,6 @@ config NLS_CODEPAGE_857
config NLS_CODEPAGE_860
tristate "Codepage 860 (Portuguese)"
- depends on NLS
help
The Microsoft FAT file system family can deal with filenames in
native language character sets. These character sets are stored in
@@ -148,7 +139,6 @@ config NLS_CODEPAGE_860
config NLS_CODEPAGE_861
tristate "Codepage 861 (Icelandic)"
- depends on NLS
help
The Microsoft FAT file system family can deal with filenames in
native language character sets. These character sets are stored in
@@ -160,7 +150,6 @@ config NLS_CODEPAGE_861
config NLS_CODEPAGE_862
tristate "Codepage 862 (Hebrew)"
- depends on NLS
help
The Microsoft FAT file system family can deal with filenames in
native language character sets. These character sets are stored in
@@ -172,7 +161,6 @@ config NLS_CODEPAGE_862
config NLS_CODEPAGE_863
tristate "Codepage 863 (Canadian French)"
- depends on NLS
help
The Microsoft FAT file system family can deal with filenames in
native language character sets. These character sets are stored in
@@ -185,7 +173,6 @@ config NLS_CODEPAGE_863
config NLS_CODEPAGE_864
tristate "Codepage 864 (Arabic)"
- depends on NLS
help
The Microsoft FAT file system family can deal with filenames in
native language character sets. These character sets are stored in
@@ -197,7 +184,6 @@ config NLS_CODEPAGE_864
config NLS_CODEPAGE_865
tristate "Codepage 865 (Norwegian, Danish)"
- depends on NLS
help
The Microsoft FAT file system family can deal with filenames in
native language character sets. These character sets are stored in
@@ -210,7 +196,6 @@ config NLS_CODEPAGE_865
config NLS_CODEPAGE_866
tristate "Codepage 866 (Cyrillic/Russian)"
- depends on NLS
help
The Microsoft FAT file system family can deal with filenames in
native language character sets. These character sets are stored in
@@ -223,7 +208,6 @@ config NLS_CODEPAGE_866
config NLS_CODEPAGE_869
tristate "Codepage 869 (Greek)"
- depends on NLS
help
The Microsoft FAT file system family can deal with filenames in
native language character sets. These character sets are stored in
@@ -235,7 +219,6 @@ config NLS_CODEPAGE_869
config NLS_CODEPAGE_936
tristate "Simplified Chinese charset (CP936, GB2312)"
- depends on NLS
help
The Microsoft FAT file system family can deal with filenames in
native language character sets. These character sets are stored in
@@ -248,7 +231,6 @@ config NLS_CODEPAGE_936
config NLS_CODEPAGE_950
tristate "Traditional Chinese charset (Big5)"
- depends on NLS
help
The Microsoft FAT file system family can deal with filenames in
native language character sets. These character sets are stored in
@@ -261,7 +243,6 @@ config NLS_CODEPAGE_950
config NLS_CODEPAGE_932
tristate "Japanese charsets (Shift-JIS, EUC-JP)"
- depends on NLS
help
The Microsoft FAT file system family can deal with filenames in
native language character sets. These character sets are stored in
@@ -275,7 +256,6 @@ config NLS_CODEPAGE_932
config NLS_CODEPAGE_949
tristate "Korean charset (CP949, EUC-KR)"
- depends on NLS
help
The Microsoft FAT file system family can deal with filenames in
native language character sets. These character sets are stored in
@@ -287,7 +267,6 @@ config NLS_CODEPAGE_949
config NLS_CODEPAGE_874
tristate "Thai charset (CP874, TIS-620)"
- depends on NLS
help
The Microsoft FAT file system family can deal with filenames in
native language character sets. These character sets are stored in
@@ -299,7 +278,6 @@ config NLS_CODEPAGE_874
config NLS_ISO8859_8
tristate "Hebrew charsets (ISO-8859-8, CP1255)"
- depends on NLS
help
If you want to display filenames with native language characters
from the Microsoft FAT file system family or from JOLIET CD-ROMs
@@ -309,7 +287,6 @@ config NLS_ISO8859_8
config NLS_CODEPAGE_1250
tristate "Windows CP1250 (Slavic/Central European Languages)"
- depends on NLS
help
If you want to display filenames with native language characters
from the Microsoft FAT file system family or from JOLIET CDROMs
@@ -321,7 +298,6 @@ config NLS_CODEPAGE_1250
config NLS_CODEPAGE_1251
tristate "Windows CP1251 (Bulgarian, Belarusian)"
- depends on NLS
help
The Microsoft FAT file system family can deal with filenames in
native language character sets. These character sets are stored in
@@ -334,7 +310,6 @@ config NLS_CODEPAGE_1251
config NLS_ASCII
tristate "ASCII (United States)"
- depends on NLS
help
An ASCII NLS module is needed if you want to override the
DEFAULT NLS with this very basic charset and don't want any
@@ -342,7 +317,6 @@ config NLS_ASCII
config NLS_ISO8859_1
tristate "NLS ISO 8859-1 (Latin 1; Western European Languages)"
- depends on NLS
help
If you want to display filenames with native language characters
from the Microsoft FAT file system family or from JOLIET CD-ROMs
@@ -355,7 +329,6 @@ config NLS_ISO8859_1
config NLS_ISO8859_2
tristate "NLS ISO 8859-2 (Latin 2; Slavic/Central European Languages)"
- depends on NLS
help
If you want to display filenames with native language characters
from the Microsoft FAT file system family or from JOLIET CD-ROMs
@@ -367,7 +340,6 @@ config NLS_ISO8859_2
config NLS_ISO8859_3
tristate "NLS ISO 8859-3 (Latin 3; Esperanto, Galician, Maltese, Turkish)"
- depends on NLS
help
If you want to display filenames with native language characters
from the Microsoft FAT file system family or from JOLIET CD-ROMs
@@ -378,7 +350,6 @@ config NLS_ISO8859_3
config NLS_ISO8859_4
tristate "NLS ISO 8859-4 (Latin 4; old Baltic charset)"
- depends on NLS
help
If you want to display filenames with native language characters
from the Microsoft FAT file system family or from JOLIET CD-ROMs
@@ -389,7 +360,6 @@ config NLS_ISO8859_4
config NLS_ISO8859_5
tristate "NLS ISO 8859-5 (Cyrillic)"
- depends on NLS
help
If you want to display filenames with native language characters
from the Microsoft FAT file system family or from JOLIET CD-ROMs
@@ -401,7 +371,6 @@ config NLS_ISO8859_5
config NLS_ISO8859_6
tristate "NLS ISO 8859-6 (Arabic)"
- depends on NLS
help
If you want to display filenames with native language characters
from the Microsoft FAT file system family or from JOLIET CD-ROMs
@@ -411,7 +380,6 @@ config NLS_ISO8859_6
config NLS_ISO8859_7
tristate "NLS ISO 8859-7 (Modern Greek)"
- depends on NLS
help
If you want to display filenames with native language characters
from the Microsoft FAT file system family or from JOLIET CD-ROMs
@@ -421,7 +389,6 @@ config NLS_ISO8859_7
config NLS_ISO8859_9
tristate "NLS ISO 8859-9 (Latin 5; Turkish)"
- depends on NLS
help
If you want to display filenames with native language characters
from the Microsoft FAT file system family or from JOLIET CD-ROMs
@@ -432,7 +399,6 @@ config NLS_ISO8859_9
config NLS_ISO8859_13
tristate "NLS ISO 8859-13 (Latin 7; Baltic)"
- depends on NLS
help
If you want to display filenames with native language characters
from the Microsoft FAT file system family or from JOLIET CD-ROMs
@@ -443,7 +409,6 @@ config NLS_ISO8859_13
config NLS_ISO8859_14
tristate "NLS ISO 8859-14 (Latin 8; Celtic)"
- depends on NLS
help
If you want to display filenames with native language characters
from the Microsoft FAT file system family or from JOLIET CD-ROMs
@@ -455,7 +420,6 @@ config NLS_ISO8859_14
config NLS_ISO8859_15
tristate "NLS ISO 8859-15 (Latin 9; Western European Languages with Euro)"
- depends on NLS
---help---
If you want to display filenames with native language characters
from the Microsoft FAT file system family or from JOLIET CD-ROMs
@@ -472,7 +436,6 @@ config NLS_ISO8859_15
config NLS_KOI8_R
tristate "NLS KOI8-R (Russian)"
- depends on NLS
help
If you want to display filenames with native language characters
from the Microsoft FAT file system family or from JOLIET CD-ROMs
@@ -482,7 +445,6 @@ config NLS_KOI8_R
config NLS_KOI8_U
tristate "NLS KOI8-U/RU (Ukrainian, Belarusian)"
- depends on NLS
help
If you want to display filenames with native language characters
from the Microsoft FAT file system family or from JOLIET CD-ROMs
@@ -492,7 +454,6 @@ config NLS_KOI8_U
config NLS_UTF8
tristate "NLS UTF-8"
- depends on NLS
help
If you want to display filenames with native language characters
from the Microsoft FAT file system family or from JOLIET CD-ROMs
@@ -500,5 +461,4 @@ config NLS_UTF8
input/output character sets. Say Y here for the UTF-8 encoding of
the Unicode/ISO9646 universal character set.
-endmenu
-
+endif # NLS
diff --git a/fs/nls/nls_ascii.c b/fs/nls/nls_ascii.c
index 6993faea28ac..7020e940f74e 100644
--- a/fs/nls/nls_ascii.c
+++ b/fs/nls/nls_ascii.c
@@ -13,7 +13,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -56,7 +56,7 @@ static wchar_t charset2uni[256] = {
0x007c, 0x007d, 0x007e, 0x007f,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -75,11 +75,11 @@ static unsigned char page00[256] = {
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00,
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -98,7 +98,7 @@ static unsigned char charset2lower[256] = {
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -119,7 +119,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/nls/nls_base.c b/fs/nls/nls_base.c
index 7dfdab98729b..64965e1c21c4 100644
--- a/fs/nls/nls_base.c
+++ b/fs/nls/nls_base.c
@@ -34,7 +34,7 @@ struct utf8_table {
long lval;
};
-static struct utf8_table utf8_table[] =
+static const struct utf8_table utf8_table[] =
{
{0x80, 0x00, 0*6, 0x7F, 0, /* 1 byte sequence */},
{0xE0, 0xC0, 1*6, 0x7FF, 0x80, /* 2 byte sequence */},
@@ -50,7 +50,7 @@ utf8_mbtowc(wchar_t *p, const __u8 *s, int n)
{
long l;
int c0, c, nc;
- struct utf8_table *t;
+ const struct utf8_table *t;
nc = 0;
c0 = *s;
@@ -109,9 +109,9 @@ utf8_wctomb(__u8 *s, wchar_t wc, int maxlen)
{
long l;
int c, nc;
- struct utf8_table *t;
+ const struct utf8_table *t;
- if (s == 0)
+ if (!s)
return 0;
l = wc;
@@ -240,7 +240,7 @@ void unload_nls(struct nls_table *nls)
module_put(nls->owner);
}
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -323,7 +323,7 @@ static wchar_t charset2uni[256] = {
0x00fc, 0x00fd, 0x00fe, 0x00ff,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -359,11 +359,11 @@ static unsigned char page00[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -399,7 +399,7 @@ static unsigned char charset2lower[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -438,7 +438,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/nls/nls_cp1250.c b/fs/nls/nls_cp1250.c
index 570aa69846a0..c8471fe78e4e 100644
--- a/fs/nls/nls_cp1250.c
+++ b/fs/nls/nls_cp1250.c
@@ -13,7 +13,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -96,7 +96,7 @@ static wchar_t charset2uni[256] = {
0x00fc, 0x00fd, 0x0163, 0x02d9,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -132,7 +132,7 @@ static unsigned char page00[256] = {
0x00, 0x00, 0xfa, 0x00, 0xfc, 0xfd, 0x00, 0x00, /* 0xf8-0xff */
};
-static unsigned char page01[256] = {
+static const unsigned char page01[256] = {
0x00, 0x00, 0xc3, 0xe3, 0xa5, 0xb9, 0xc6, 0xe6, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0xc8, 0xe8, 0xcf, 0xef, /* 0x08-0x0f */
0xd0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -152,7 +152,7 @@ static unsigned char page01[256] = {
};
-static unsigned char page02[256] = {
+static const unsigned char page02[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -184,7 +184,7 @@ static unsigned char page02[256] = {
0xa2, 0xff, 0x00, 0xb2, 0x00, 0xbd, 0x00, 0x00, /* 0xd8-0xdf */
};
-static unsigned char page20[256] = {
+static const unsigned char page20[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x96, 0x97, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -210,7 +210,7 @@ static unsigned char page20[256] = {
0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
};
-static unsigned char page21[256] = {
+static const unsigned char page21[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -218,7 +218,7 @@ static unsigned char page21[256] = {
0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00, page01, page02, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -226,7 +226,7 @@ static unsigned char *page_uni2charset[256] = {
page20, page21, NULL, NULL, NULL, NULL, NULL, NULL,
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -262,7 +262,7 @@ static unsigned char charset2lower[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -300,7 +300,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/nls/nls_cp1251.c b/fs/nls/nls_cp1251.c
index f114afa069db..1939b46e772f 100644
--- a/fs/nls/nls_cp1251.c
+++ b/fs/nls/nls_cp1251.c
@@ -13,7 +13,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -96,7 +96,7 @@ static wchar_t charset2uni[256] = {
0x044c, 0x044d, 0x044e, 0x044f,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -132,7 +132,7 @@ static unsigned char page00[256] = {
0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
};
-static unsigned char page04[256] = {
+static const unsigned char page04[256] = {
0x00, 0xa8, 0x80, 0x81, 0xaa, 0xbd, 0xb2, 0xaf, /* 0x00-0x07 */
0xa3, 0x8a, 0x8c, 0x8e, 0x8d, 0x00, 0xa1, 0x8f, /* 0x08-0x0f */
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0x10-0x17 */
@@ -155,7 +155,7 @@ static unsigned char page04[256] = {
0x00, 0xa5, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
};
-static unsigned char page20[256] = {
+static const unsigned char page20[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x96, 0x97, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -166,7 +166,7 @@ static unsigned char page20[256] = {
0x00, 0x8b, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
};
-static unsigned char page21[256] = {
+static const unsigned char page21[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb9, 0x00, /* 0x10-0x17 */
@@ -174,7 +174,7 @@ static unsigned char page21[256] = {
0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00, NULL, NULL, NULL, page04, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -182,7 +182,7 @@ static unsigned char *page_uni2charset[256] = {
page20, page21, NULL, NULL, NULL, NULL, NULL, NULL,
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -217,7 +217,7 @@ static unsigned char charset2lower[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -254,7 +254,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/nls/nls_cp1255.c b/fs/nls/nls_cp1255.c
index e57f2cbf5bc0..8120ae2e091a 100644
--- a/fs/nls/nls_cp1255.c
+++ b/fs/nls/nls_cp1255.c
@@ -11,7 +11,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -94,7 +94,7 @@ static wchar_t charset2uni[256] = {
0x0000, 0x0000, 0x0000, 0x0000,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -129,7 +129,7 @@ static unsigned char page00[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, /* 0xf0-0xf7 */
};
-static unsigned char page01[256] = {
+static const unsigned char page01[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -152,7 +152,7 @@ static unsigned char page01[256] = {
0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
};
-static unsigned char page02[256] = {
+static const unsigned char page02[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -184,7 +184,7 @@ static unsigned char page02[256] = {
0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
};
-static unsigned char page05[256] = {
+static const unsigned char page05[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -219,7 +219,7 @@ static unsigned char page05[256] = {
0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
};
-static unsigned char page20[256] = {
+static const unsigned char page20[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0xfe, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x96, 0x97, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -245,7 +245,7 @@ static unsigned char page20[256] = {
0x00, 0x00, 0xa4, 0x00, 0x80, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
};
-static unsigned char page21[256] = {
+static const unsigned char page21[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb9, 0x00, /* 0x10-0x17 */
@@ -253,7 +253,7 @@ static unsigned char page21[256] = {
0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00, page01, page02, NULL, NULL, page05, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -261,7 +261,7 @@ static unsigned char *page_uni2charset[256] = {
page20, page21, NULL, NULL, NULL, NULL, NULL, NULL,
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -297,7 +297,7 @@ static unsigned char charset2lower[256] = {
0xf8, 0xf9, 0xfa, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -335,7 +335,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/nls/nls_cp437.c b/fs/nls/nls_cp437.c
index d41930ce4a44..ff37a4628ce4 100644
--- a/fs/nls/nls_cp437.c
+++ b/fs/nls/nls_cp437.c
@@ -13,7 +13,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -96,7 +96,7 @@ static wchar_t charset2uni[256] = {
0x207f, 0x00b2, 0x25a0, 0x00a0,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -132,7 +132,7 @@ static unsigned char page00[256] = {
0x00, 0x97, 0xa3, 0x96, 0x81, 0x00, 0x00, 0x98, /* 0xf8-0xff */
};
-static unsigned char page01[256] = {
+static const unsigned char page01[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -155,7 +155,7 @@ static unsigned char page01[256] = {
0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
};
-static unsigned char page03[256] = {
+static const unsigned char page03[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -184,7 +184,7 @@ static unsigned char page03[256] = {
0xe3, 0x00, 0x00, 0xe5, 0xe7, 0x00, 0xed, 0x00, /* 0xc0-0xc7 */
};
-static unsigned char page20[256] = {
+static const unsigned char page20[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -209,7 +209,7 @@ static unsigned char page20[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, /* 0xa0-0xa7 */
};
-static unsigned char page22[256] = {
+static const unsigned char page22[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -225,7 +225,7 @@ static unsigned char page22[256] = {
0x00, 0xf0, 0x00, 0x00, 0xf3, 0xf2, 0x00, 0x00, /* 0x60-0x67 */
};
-static unsigned char page23[256] = {
+static const unsigned char page23[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0xa9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -233,7 +233,7 @@ static unsigned char page23[256] = {
0xf4, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
};
-static unsigned char page25[256] = {
+static const unsigned char page25[256] = {
0xc4, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0xbf, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -258,7 +258,7 @@ static unsigned char page25[256] = {
0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00, page01, NULL, page03, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -266,7 +266,7 @@ static unsigned char *page_uni2charset[256] = {
page20, NULL, page22, page23, NULL, page25, NULL, NULL,
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -302,7 +302,7 @@ static unsigned char charset2lower[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -340,7 +340,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/nls/nls_cp737.c b/fs/nls/nls_cp737.c
index d21f8790aa19..f5576b8be1b9 100644
--- a/fs/nls/nls_cp737.c
+++ b/fs/nls/nls_cp737.c
@@ -13,7 +13,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -96,7 +96,7 @@ static wchar_t charset2uni[256] = {
0x207f, 0x00b2, 0x25a0, 0x00a0,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -131,7 +131,7 @@ static unsigned char page00[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, /* 0xf0-0xf7 */
};
-static unsigned char page03[256] = {
+static const unsigned char page03[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -161,7 +161,7 @@ static unsigned char page03[256] = {
0xaf, 0xe0, 0xe4, 0xe8, 0xe6, 0xe7, 0xe9, 0x00, /* 0xc8-0xcf */
};
-static unsigned char page20[256] = {
+static const unsigned char page20[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -180,7 +180,7 @@ static unsigned char page20[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, /* 0x78-0x7f */
};
-static unsigned char page22[256] = {
+static const unsigned char page22[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -196,7 +196,7 @@ static unsigned char page22[256] = {
0x00, 0x00, 0x00, 0x00, 0xf3, 0xf2, 0x00, 0x00, /* 0x60-0x67 */
};
-static unsigned char page25[256] = {
+static const unsigned char page25[256] = {
0xc4, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0xbf, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -221,7 +221,7 @@ static unsigned char page25[256] = {
0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00, NULL, NULL, page03, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -229,7 +229,7 @@ static unsigned char *page_uni2charset[256] = {
page20, NULL, page22, NULL, NULL, page25, NULL, NULL,
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -265,7 +265,7 @@ static unsigned char charset2lower[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -303,7 +303,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/nls/nls_cp775.c b/fs/nls/nls_cp775.c
index c97714c38a90..4905635d1c00 100644
--- a/fs/nls/nls_cp775.c
+++ b/fs/nls/nls_cp775.c
@@ -13,7 +13,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -96,7 +96,7 @@ static wchar_t charset2uni[256] = {
0x00b3, 0x00b2, 0x25a0, 0x00a0,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -132,7 +132,7 @@ static unsigned char page00[256] = {
0x9b, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, /* 0xf8-0xff */
};
-static unsigned char page01[256] = {
+static const unsigned char page01[256] = {
0xa0, 0x83, 0x00, 0x00, 0xb5, 0xd0, 0x80, 0x87, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0xb6, 0xd1, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0xed, 0x89, 0x00, 0x00, 0xb8, 0xd3, /* 0x10-0x17 */
@@ -151,21 +151,21 @@ static unsigned char page01[256] = {
0x00, 0x8d, 0xa5, 0xa3, 0xa4, 0xcf, 0xd8, 0x00, /* 0x78-0x7f */
};
-static unsigned char page20[256] = {
+static const unsigned char page20[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
0x00, 0xef, 0x00, 0x00, 0xf2, 0xa6, 0xf7, 0x00, /* 0x18-0x1f */
};
-static unsigned char page22[256] = {
+static const unsigned char page22[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
};
-static unsigned char page25[256] = {
+static const unsigned char page25[256] = {
0xc4, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0xbf, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -190,7 +190,7 @@ static unsigned char page25[256] = {
0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00, page01, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -198,7 +198,7 @@ static unsigned char *page_uni2charset[256] = {
page20, NULL, page22, NULL, NULL, page25, NULL, NULL,
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -234,7 +234,7 @@ static unsigned char charset2lower[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -272,7 +272,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/nls/nls_cp850.c b/fs/nls/nls_cp850.c
index 843b7d975ba2..fe5bdad50e2b 100644
--- a/fs/nls/nls_cp850.c
+++ b/fs/nls/nls_cp850.c
@@ -13,7 +13,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -96,7 +96,7 @@ static wchar_t charset2uni[256] = {
0x00b3, 0x00b2, 0x25a0, 0x00a0,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -132,7 +132,7 @@ static unsigned char page00[256] = {
0x9b, 0x97, 0xa3, 0x96, 0x81, 0xec, 0xe7, 0x98, /* 0xf8-0xff */
};
-static unsigned char page01[256] = {
+static const unsigned char page01[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -155,13 +155,13 @@ static unsigned char page01[256] = {
0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
};
-static unsigned char page20[256] = {
+static const unsigned char page20[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, /* 0x10-0x17 */
};
-static unsigned char page25[256] = {
+static const unsigned char page25[256] = {
0xc4, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0xbf, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -186,7 +186,7 @@ static unsigned char page25[256] = {
0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00, page01, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -194,7 +194,7 @@ static unsigned char *page_uni2charset[256] = {
page20, NULL, NULL, NULL, NULL, page25, NULL, NULL,
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -230,7 +230,7 @@ static unsigned char charset2lower[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -268,7 +268,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/nls/nls_cp852.c b/fs/nls/nls_cp852.c
index 83cfd844d5ca..ceb1c0166dd8 100644
--- a/fs/nls/nls_cp852.c
+++ b/fs/nls/nls_cp852.c
@@ -13,7 +13,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -96,7 +96,7 @@ static wchar_t charset2uni[256] = {
0x0158, 0x0159, 0x25a0, 0x00a0,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -132,7 +132,7 @@ static unsigned char page00[256] = {
0x00, 0x00, 0xa3, 0x00, 0x81, 0xec, 0x00, 0x00, /* 0xf8-0xff */
};
-static unsigned char page01[256] = {
+static const unsigned char page01[256] = {
0x00, 0x00, 0xc6, 0xc7, 0xa4, 0xa5, 0x8f, 0x86, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0xac, 0x9f, 0xd2, 0xd4, /* 0x08-0x0f */
0xd1, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -151,7 +151,7 @@ static unsigned char page01[256] = {
0x00, 0x8d, 0xab, 0xbd, 0xbe, 0xa6, 0xa7, 0x00, /* 0x78-0x7f */
};
-static unsigned char page02[256] = {
+static const unsigned char page02[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -183,7 +183,7 @@ static unsigned char page02[256] = {
0xf4, 0xfa, 0x00, 0xf2, 0x00, 0xf1, 0x00, 0x00, /* 0xd8-0xdf */
};
-static unsigned char page25[256] = {
+static const unsigned char page25[256] = {
0xc4, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0xbf, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -208,7 +208,7 @@ static unsigned char page25[256] = {
0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00, page01, page02, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -216,7 +216,7 @@ static unsigned char *page_uni2charset[256] = {
NULL, NULL, NULL, NULL, NULL, page25, NULL, NULL,
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -252,7 +252,7 @@ static unsigned char charset2lower[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfd, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -290,7 +290,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/nls/nls_cp855.c b/fs/nls/nls_cp855.c
index 9190b7b574ff..cc7f5fb2e0c2 100644
--- a/fs/nls/nls_cp855.c
+++ b/fs/nls/nls_cp855.c
@@ -13,7 +13,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -96,7 +96,7 @@ static wchar_t charset2uni[256] = {
0x0427, 0x00a7, 0x25a0, 0x00a0,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -124,7 +124,7 @@ static unsigned char page00[256] = {
0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
};
-static unsigned char page04[256] = {
+static const unsigned char page04[256] = {
0x00, 0x85, 0x81, 0x83, 0x87, 0x89, 0x8b, 0x8d, /* 0x00-0x07 */
0x8f, 0x91, 0x93, 0x95, 0x97, 0x00, 0x99, 0x9b, /* 0x08-0x0f */
0xa1, 0xa3, 0xec, 0xad, 0xa7, 0xa9, 0xea, 0xf4, /* 0x10-0x17 */
@@ -139,13 +139,13 @@ static unsigned char page04[256] = {
0x8e, 0x90, 0x92, 0x94, 0x96, 0x00, 0x98, 0x9a, /* 0x58-0x5f */
};
-static unsigned char page21[256] = {
+static const unsigned char page21[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0x00, /* 0x10-0x17 */
};
-static unsigned char page25[256] = {
+static const unsigned char page25[256] = {
0xc4, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0xbf, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -170,7 +170,7 @@ static unsigned char page25[256] = {
0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00, NULL, NULL, NULL, page04, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -178,7 +178,7 @@ static unsigned char *page_uni2charset[256] = {
NULL, page21, NULL, NULL, NULL, page25, NULL, NULL,
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -214,7 +214,7 @@ static unsigned char charset2lower[256] = {
0xf7, 0xf9, 0xf9, 0xfb, 0xfb, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -252,7 +252,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/nls/nls_cp857.c b/fs/nls/nls_cp857.c
index ef3d36db8082..e418e198e8d8 100644
--- a/fs/nls/nls_cp857.c
+++ b/fs/nls/nls_cp857.c
@@ -13,7 +13,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -96,7 +96,7 @@ static wchar_t charset2uni[256] = {
0x00b3, 0x00b2, 0x25a0, 0x00a0,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -132,7 +132,7 @@ static unsigned char page00[256] = {
0x9b, 0x97, 0xa3, 0x96, 0x81, 0x00, 0x00, 0xed, /* 0xf8-0xff */
};
-static unsigned char page01[256] = {
+static const unsigned char page01[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -147,7 +147,7 @@ static unsigned char page01[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, 0x9f, /* 0x58-0x5f */
};
-static unsigned char page25[256] = {
+static const unsigned char page25[256] = {
0xc4, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0xbf, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -172,7 +172,7 @@ static unsigned char page25[256] = {
0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00, page01, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -180,7 +180,7 @@ static unsigned char *page_uni2charset[256] = {
NULL, NULL, NULL, NULL, NULL, page25, NULL, NULL,
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -216,7 +216,7 @@ static unsigned char charset2lower[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -254,7 +254,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/nls/nls_cp860.c b/fs/nls/nls_cp860.c
index 7e2fb6645893..a86c97d1aa34 100644
--- a/fs/nls/nls_cp860.c
+++ b/fs/nls/nls_cp860.c
@@ -13,7 +13,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -96,7 +96,7 @@ static wchar_t charset2uni[256] = {
0x207f, 0x00b2, 0x25a0, 0x00a0,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -132,7 +132,7 @@ static unsigned char page00[256] = {
0x00, 0x97, 0xa3, 0x00, 0x81, 0x00, 0x00, 0x00, /* 0xf8-0xff */
};
-static unsigned char page03[256] = {
+static const unsigned char page03[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -161,7 +161,7 @@ static unsigned char page03[256] = {
0xe3, 0x00, 0x00, 0xe5, 0xe7, 0x00, 0xed, 0x00, /* 0xc0-0xc7 */
};
-static unsigned char page20[256] = {
+static const unsigned char page20[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -186,7 +186,7 @@ static unsigned char page20[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, /* 0xa0-0xa7 */
};
-static unsigned char page22[256] = {
+static const unsigned char page22[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -202,7 +202,7 @@ static unsigned char page22[256] = {
0x00, 0xf0, 0x00, 0x00, 0xf3, 0xf2, 0x00, 0x00, /* 0x60-0x67 */
};
-static unsigned char page23[256] = {
+static const unsigned char page23[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -210,7 +210,7 @@ static unsigned char page23[256] = {
0xf4, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
};
-static unsigned char page25[256] = {
+static const unsigned char page25[256] = {
0xc4, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0xbf, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -235,7 +235,7 @@ static unsigned char page25[256] = {
0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00, NULL, NULL, page03, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -243,7 +243,7 @@ static unsigned char *page_uni2charset[256] = {
page20, NULL, page22, page23, NULL, page25, NULL, NULL,
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -279,7 +279,7 @@ static unsigned char charset2lower[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -317,7 +317,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/nls/nls_cp861.c b/fs/nls/nls_cp861.c
index 66d8d808ccf1..bd920227acdf 100644
--- a/fs/nls/nls_cp861.c
+++ b/fs/nls/nls_cp861.c
@@ -13,7 +13,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -96,7 +96,7 @@ static wchar_t charset2uni[256] = {
0x207f, 0x00b2, 0x25a0, 0x00a0,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -132,7 +132,7 @@ static unsigned char page00[256] = {
0x9b, 0x00, 0xa3, 0x96, 0x81, 0x98, 0x95, 0x00, /* 0xf8-0xff */
};
-static unsigned char page01[256] = {
+static const unsigned char page01[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -155,7 +155,7 @@ static unsigned char page01[256] = {
0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
};
-static unsigned char page03[256] = {
+static const unsigned char page03[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -184,7 +184,7 @@ static unsigned char page03[256] = {
0xe3, 0x00, 0x00, 0xe5, 0xe7, 0x00, 0xed, 0x00, /* 0xc0-0xc7 */
};
-static unsigned char page20[256] = {
+static const unsigned char page20[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -209,7 +209,7 @@ static unsigned char page20[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, /* 0xa0-0xa7 */
};
-static unsigned char page22[256] = {
+static const unsigned char page22[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -225,7 +225,7 @@ static unsigned char page22[256] = {
0x00, 0xf0, 0x00, 0x00, 0xf3, 0xf2, 0x00, 0x00, /* 0x60-0x67 */
};
-static unsigned char page23[256] = {
+static const unsigned char page23[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0xa9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -233,7 +233,7 @@ static unsigned char page23[256] = {
0xf4, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
};
-static unsigned char page25[256] = {
+static const unsigned char page25[256] = {
0xc4, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0xbf, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -258,7 +258,7 @@ static unsigned char page25[256] = {
0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00, page01, NULL, page03, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -266,7 +266,7 @@ static unsigned char *page_uni2charset[256] = {
page20, NULL, page22, page23, NULL, page25, NULL, NULL,
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -302,7 +302,7 @@ static unsigned char charset2lower[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -340,7 +340,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/nls/nls_cp862.c b/fs/nls/nls_cp862.c
index 360ba388485f..e9b68eb3daf0 100644
--- a/fs/nls/nls_cp862.c
+++ b/fs/nls/nls_cp862.c
@@ -13,7 +13,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -96,7 +96,7 @@ static wchar_t charset2uni[256] = {
0x207f, 0x00b2, 0x25a0, 0x00a0,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -132,7 +132,7 @@ static unsigned char page00[256] = {
0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
};
-static unsigned char page01[256] = {
+static const unsigned char page01[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -155,7 +155,7 @@ static unsigned char page01[256] = {
0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
};
-static unsigned char page03[256] = {
+static const unsigned char page03[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -184,7 +184,7 @@ static unsigned char page03[256] = {
0xe3, 0x00, 0x00, 0xe5, 0xe7, 0x00, 0xed, 0x00, /* 0xc0-0xc7 */
};
-static unsigned char page05[256] = {
+static const unsigned char page05[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -218,7 +218,7 @@ static unsigned char page05[256] = {
0x98, 0x99, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
};
-static unsigned char page20[256] = {
+static const unsigned char page20[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -243,7 +243,7 @@ static unsigned char page20[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, /* 0xa0-0xa7 */
};
-static unsigned char page22[256] = {
+static const unsigned char page22[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -259,7 +259,7 @@ static unsigned char page22[256] = {
0x00, 0xf0, 0x00, 0x00, 0xf3, 0xf2, 0x00, 0x00, /* 0x60-0x67 */
};
-static unsigned char page23[256] = {
+static const unsigned char page23[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0xa9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -267,7 +267,7 @@ static unsigned char page23[256] = {
0xf4, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
};
-static unsigned char page25[256] = {
+static const unsigned char page25[256] = {
0xc4, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0xbf, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -292,7 +292,7 @@ static unsigned char page25[256] = {
0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00, page01, NULL, page03, NULL, page05, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -300,7 +300,7 @@ static unsigned char *page_uni2charset[256] = {
page20, NULL, page22, page23, NULL, page25, NULL, NULL,
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -336,7 +336,7 @@ static unsigned char charset2lower[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -374,7 +374,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/nls/nls_cp863.c b/fs/nls/nls_cp863.c
index 656a93113e37..f8a9b07ab4e2 100644
--- a/fs/nls/nls_cp863.c
+++ b/fs/nls/nls_cp863.c
@@ -13,7 +13,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -96,7 +96,7 @@ static wchar_t charset2uni[256] = {
0x207f, 0x00b2, 0x25a0, 0x00a0,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -132,7 +132,7 @@ static unsigned char page00[256] = {
0x00, 0x97, 0xa3, 0x96, 0x81, 0x00, 0x00, 0x00, /* 0xf8-0xff */
};
-static unsigned char page01[256] = {
+static const unsigned char page01[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -155,7 +155,7 @@ static unsigned char page01[256] = {
0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
};
-static unsigned char page03[256] = {
+static const unsigned char page03[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -184,7 +184,7 @@ static unsigned char page03[256] = {
0xe3, 0x00, 0x00, 0xe5, 0xe7, 0x00, 0xed, 0x00, /* 0xc0-0xc7 */
};
-static unsigned char page20[256] = {
+static const unsigned char page20[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8d, /* 0x10-0x17 */
@@ -203,7 +203,7 @@ static unsigned char page20[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, /* 0x78-0x7f */
};
-static unsigned char page22[256] = {
+static const unsigned char page22[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -219,7 +219,7 @@ static unsigned char page22[256] = {
0x00, 0xf0, 0x00, 0x00, 0xf3, 0xf2, 0x00, 0x00, /* 0x60-0x67 */
};
-static unsigned char page23[256] = {
+static const unsigned char page23[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0xa9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -227,7 +227,7 @@ static unsigned char page23[256] = {
0xf4, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
};
-static unsigned char page25[256] = {
+static const unsigned char page25[256] = {
0xc4, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0xbf, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -252,7 +252,7 @@ static unsigned char page25[256] = {
0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00, page01, NULL, page03, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -260,7 +260,7 @@ static unsigned char *page_uni2charset[256] = {
page20, NULL, page22, page23, NULL, page25, NULL, NULL,
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -296,7 +296,7 @@ static unsigned char charset2lower[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -334,7 +334,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/nls/nls_cp864.c b/fs/nls/nls_cp864.c
index 01ca7309753e..8d31f435fc6f 100644
--- a/fs/nls/nls_cp864.c
+++ b/fs/nls/nls_cp864.c
@@ -13,7 +13,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -96,7 +96,7 @@ static wchar_t charset2uni[256] = {
0xfed9, 0xfef1, 0x25a0, 0x0000,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -131,7 +131,7 @@ static unsigned char page00[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdd, /* 0xf0-0xf7 */
};
-static unsigned char page03[256] = {
+static const unsigned char page03[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -160,7 +160,7 @@ static unsigned char page03[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x00, /* 0xc0-0xc7 */
};
-static unsigned char page06[256] = {
+static const unsigned char page06[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -177,7 +177,7 @@ static unsigned char page06[256] = {
0xb8, 0xb9, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
};
-static unsigned char page22[256] = {
+static const unsigned char page22[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -190,7 +190,7 @@ static unsigned char page22[256] = {
0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
};
-static unsigned char page25[256] = {
+static const unsigned char page25[256] = {
0x85, 0x00, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x8c, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -215,7 +215,7 @@ static unsigned char page25[256] = {
0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
};
-static unsigned char pagefe[256] = {
+static const unsigned char pagefe[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -251,7 +251,7 @@ static unsigned char pagefe[256] = {
0x9a, 0x00, 0x00, 0x9d, 0x9e, 0x00, 0x00, 0x00, /* 0xf8-0xff */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00, NULL, NULL, page03, NULL, NULL, page06, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -286,7 +286,7 @@ static unsigned char *page_uni2charset[256] = {
NULL, NULL, NULL, NULL, NULL, NULL, pagefe, NULL,
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -322,7 +322,7 @@ static unsigned char charset2lower[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0x00, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -360,7 +360,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/nls/nls_cp865.c b/fs/nls/nls_cp865.c
index 5ba6ee13e109..4bd902fe3ec9 100644
--- a/fs/nls/nls_cp865.c
+++ b/fs/nls/nls_cp865.c
@@ -13,7 +13,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -96,7 +96,7 @@ static wchar_t charset2uni[256] = {
0x207f, 0x00b2, 0x25a0, 0x00a0,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -132,7 +132,7 @@ static unsigned char page00[256] = {
0x9b, 0x97, 0xa3, 0x96, 0x81, 0x00, 0x00, 0x98, /* 0xf8-0xff */
};
-static unsigned char page01[256] = {
+static const unsigned char page01[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -155,7 +155,7 @@ static unsigned char page01[256] = {
0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
};
-static unsigned char page03[256] = {
+static const unsigned char page03[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -184,7 +184,7 @@ static unsigned char page03[256] = {
0xe3, 0x00, 0x00, 0xe5, 0xe7, 0x00, 0xed, 0x00, /* 0xc0-0xc7 */
};
-static unsigned char page20[256] = {
+static const unsigned char page20[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -209,7 +209,7 @@ static unsigned char page20[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, /* 0xa0-0xa7 */
};
-static unsigned char page22[256] = {
+static const unsigned char page22[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -225,7 +225,7 @@ static unsigned char page22[256] = {
0x00, 0xf0, 0x00, 0x00, 0xf3, 0xf2, 0x00, 0x00, /* 0x60-0x67 */
};
-static unsigned char page23[256] = {
+static const unsigned char page23[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0xa9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -233,7 +233,7 @@ static unsigned char page23[256] = {
0xf4, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
};
-static unsigned char page25[256] = {
+static const unsigned char page25[256] = {
0xc4, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0xbf, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -258,7 +258,7 @@ static unsigned char page25[256] = {
0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00, page01, NULL, page03, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -266,7 +266,7 @@ static unsigned char *page_uni2charset[256] = {
page20, NULL, page22, page23, NULL, page25, NULL, NULL,
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -302,7 +302,7 @@ static unsigned char charset2lower[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -340,7 +340,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/nls/nls_cp866.c b/fs/nls/nls_cp866.c
index c5f82221c9fe..bdc7cb391398 100644
--- a/fs/nls/nls_cp866.c
+++ b/fs/nls/nls_cp866.c
@@ -13,7 +13,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -96,7 +96,7 @@ static wchar_t charset2uni[256] = {
0x2116, 0x00a4, 0x25a0, 0x00a0,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -123,7 +123,7 @@ static unsigned char page00[256] = {
0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, /* 0xb0-0xb7 */
};
-static unsigned char page04[256] = {
+static const unsigned char page04[256] = {
0x00, 0xf0, 0x00, 0x00, 0xf2, 0x00, 0x00, 0xf4, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x00, /* 0x08-0x0f */
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x10-0x17 */
@@ -138,20 +138,20 @@ static unsigned char page04[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, 0x00, /* 0x58-0x5f */
};
-static unsigned char page21[256] = {
+static const unsigned char page21[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, /* 0x10-0x17 */
};
-static unsigned char page22[256] = {
+static const unsigned char page22[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
0x00, 0xf9, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
};
-static unsigned char page25[256] = {
+static const unsigned char page25[256] = {
0xc4, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0xbf, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -176,7 +176,7 @@ static unsigned char page25[256] = {
0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00, NULL, NULL, NULL, page04, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -184,7 +184,7 @@ static unsigned char *page_uni2charset[256] = {
NULL, page21, page22, NULL, NULL, page25, NULL, NULL,
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -220,7 +220,7 @@ static unsigned char charset2lower[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -258,7 +258,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/nls/nls_cp869.c b/fs/nls/nls_cp869.c
index 8d4015124d11..9f283a2b151a 100644
--- a/fs/nls/nls_cp869.c
+++ b/fs/nls/nls_cp869.c
@@ -13,7 +13,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -96,7 +96,7 @@ static wchar_t charset2uni[256] = {
0x03b0, 0x03ce, 0x25a0, 0x00a0,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -124,7 +124,7 @@ static unsigned char page00[256] = {
0x00, 0x00, 0x00, 0xaf, 0x00, 0xab, 0x00, 0x00, /* 0xb8-0xbf */
};
-static unsigned char page03[256] = {
+static const unsigned char page03[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -154,14 +154,14 @@ static unsigned char page03[256] = {
0xf6, 0xfa, 0xa0, 0xfb, 0xa2, 0xa3, 0xfd, 0x00, /* 0xc8-0xcf */
};
-static unsigned char page20[256] = {
+static const unsigned char page20[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, /* 0x10-0x17 */
0x8b, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
};
-static unsigned char page25[256] = {
+static const unsigned char page25[256] = {
0xc4, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0xbf, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -186,7 +186,7 @@ static unsigned char page25[256] = {
0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00, NULL, NULL, page03, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -194,7 +194,7 @@ static unsigned char *page_uni2charset[256] = {
page20, NULL, NULL, NULL, NULL, page25, NULL, NULL,
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -230,7 +230,7 @@ static unsigned char charset2lower[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -268,7 +268,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/nls/nls_cp874.c b/fs/nls/nls_cp874.c
index df042052c2db..0b3c4886f8c0 100644
--- a/fs/nls/nls_cp874.c
+++ b/fs/nls/nls_cp874.c
@@ -13,7 +13,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -96,7 +96,7 @@ static wchar_t charset2uni[256] = {
0x0000, 0x0000, 0x0000, 0x0000,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -121,7 +121,7 @@ static unsigned char page00[256] = {
0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
};
-static unsigned char page0e[256] = {
+static const unsigned char page0e[256] = {
0x00, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0x00-0x07 */
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0x08-0x0f */
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0x10-0x17 */
@@ -136,7 +136,7 @@ static unsigned char page0e[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
};
-static unsigned char page20[256] = {
+static const unsigned char page20[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x96, 0x97, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -144,7 +144,7 @@ static unsigned char page20[256] = {
0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x85, 0x00, /* 0x20-0x27 */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, page0e, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -152,7 +152,7 @@ static unsigned char *page_uni2charset[256] = {
page20, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -188,7 +188,7 @@ static unsigned char charset2lower[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -226,7 +226,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/nls/nls_cp932.c b/fs/nls/nls_cp932.c
index 2a9ccf3bc7ef..0ffed6f1cebb 100644
--- a/fs/nls/nls_cp932.c
+++ b/fs/nls/nls_cp932.c
@@ -13,7 +13,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t c2u_81[256] = {
+static const wchar_t c2u_81[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -49,7 +49,7 @@ static wchar_t c2u_81[256] = {
0x0000,0x0000,0x0000,0x0000,0x25EF,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_82[256] = {
+static const wchar_t c2u_82[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -84,7 +84,7 @@ static wchar_t c2u_82[256] = {
0x3092,0x3093,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0xF0-0xF7 */
};
-static wchar_t c2u_83[256] = {
+static const wchar_t c2u_83[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -115,7 +115,7 @@ static wchar_t c2u_83[256] = {
0x03C3,0x03C4,0x03C5,0x03C6,0x03C7,0x03C8,0x03C9,0x0000,/* 0xD0-0xD7 */
};
-static wchar_t c2u_84[256] = {
+static const wchar_t c2u_84[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -143,7 +143,7 @@ static wchar_t c2u_84[256] = {
0x2537,0x253F,0x251D,0x2530,0x2525,0x2538,0x2542,0x0000,/* 0xB8-0xBF */
};
-static wchar_t c2u_87[256] = {
+static const wchar_t c2u_87[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -167,7 +167,7 @@ static wchar_t c2u_87[256] = {
0x221F,0x22BF,0x2235,0x2229,0x222A,0x0000,0x0000,0x0000,/* 0x98-0x9F */
};
-static wchar_t c2u_88[256] = {
+static const wchar_t c2u_88[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -203,7 +203,7 @@ static wchar_t c2u_88[256] = {
0x5F15,0x98F2,0x6DEB,0x80E4,0x852D,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_89[256] = {
+static const wchar_t c2u_89[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -239,7 +239,7 @@ static wchar_t c2u_89[256] = {
0x6062,0x61D0,0x6212,0x62D0,0x6539,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_8A[256] = {
+static const wchar_t c2u_8A[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -275,7 +275,7 @@ static wchar_t c2u_8A[256] = {
0x65D7,0x65E2,0x671F,0x68CB,0x68C4,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_8B[256] = {
+static const wchar_t c2u_8B[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -311,7 +311,7 @@ static wchar_t c2u_8B[256] = {
0x4E32,0x6ADB,0x91E7,0x5C51,0x5C48,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_8C[256] = {
+static const wchar_t c2u_8C[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -347,7 +347,7 @@ static wchar_t c2u_8C[256] = {
0x52B9,0x52FE,0x539A,0x53E3,0x5411,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_8D[256] = {
+static const wchar_t c2u_8D[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -383,7 +383,7 @@ static wchar_t c2u_8D[256] = {
0x9BAD,0x7B39,0x5319,0x518A,0x5237,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_8E[256] = {
+static const wchar_t c2u_8E[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -419,7 +419,7 @@ static wchar_t c2u_8E[256] = {
0x7DAC,0x9700,0x56DA,0x53CE,0x5468,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_8F[256] = {
+static const wchar_t c2u_8F[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -455,7 +455,7 @@ static wchar_t c2u_8F[256] = {
0x91B8,0x9320,0x5631,0x57F4,0x98FE,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_90[256] = {
+static const wchar_t c2u_90[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -491,7 +491,7 @@ static wchar_t c2u_90[256] = {
0x717D,0x65CB,0x7A7F,0x7BAD,0x7DDA,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_91[256] = {
+static const wchar_t c2u_91[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -527,7 +527,7 @@ static wchar_t c2u_91[256] = {
0x8AFE,0x8338,0x51E7,0x86F8,0x53EA,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_92[256] = {
+static const wchar_t c2u_92[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -563,7 +563,7 @@ static wchar_t c2u_92[256] = {
0x8247,0x8A02,0x8AE6,0x8E44,0x9013,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_93[256] = {
+static const wchar_t c2u_93[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -599,7 +599,7 @@ static wchar_t c2u_93[256] = {
0x8679,0x5EFF,0x65E5,0x4E73,0x5165,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_94[256] = {
+static const wchar_t c2u_94[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -635,7 +635,7 @@ static wchar_t c2u_94[256] = {
0x6787,0x6BD8,0x7435,0x7709,0x7F8E,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_95[256] = {
+static const wchar_t c2u_95[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -671,7 +671,7 @@ static wchar_t c2u_95[256] = {
0x62B1,0x6367,0x653E,0x65B9,0x670B,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_96[256] = {
+static const wchar_t c2u_96[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -707,7 +707,7 @@ static wchar_t c2u_96[256] = {
0x9453,0x6109,0x6108,0x6CB9,0x7652,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_97[256] = {
+static const wchar_t c2u_97[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -743,7 +743,7 @@ static wchar_t c2u_97[256] = {
0x6F23,0x7149,0x7C3E,0x7DF4,0x806F,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_98[256] = {
+static const wchar_t c2u_98[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -779,7 +779,7 @@ static wchar_t c2u_98[256] = {
0x5080,0x509A,0x5085,0x50B4,0x50B2,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_99[256] = {
+static const wchar_t c2u_99[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -815,7 +815,7 @@ static wchar_t c2u_99[256] = {
0x54A5,0x54AC,0x54C4,0x54C8,0x54A8,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_9A[256] = {
+static const wchar_t c2u_9A[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -851,7 +851,7 @@ static wchar_t c2u_9A[256] = {
0x5962,0x5960,0x5967,0x596C,0x5969,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_9B[256] = {
+static const wchar_t c2u_9B[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -887,7 +887,7 @@ static wchar_t c2u_9B[256] = {
0x5EC1,0x5EC2,0x5EC8,0x5ED0,0x5ECF,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_9C[256] = {
+static const wchar_t c2u_9C[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -923,7 +923,7 @@ static wchar_t c2u_9C[256] = {
0x6209,0x620D,0x620C,0x6214,0x621B,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_9D[256] = {
+static const wchar_t c2u_9D[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -959,7 +959,7 @@ static wchar_t c2u_9D[256] = {
0x66C1,0x66B9,0x66C9,0x66BE,0x66BC,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_9E[256] = {
+static const wchar_t c2u_9E[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -995,7 +995,7 @@ static wchar_t c2u_9E[256] = {
0x6A8D,0x6AA0,0x6A84,0x6AA2,0x6AA3,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_9F[256] = {
+static const wchar_t c2u_9F[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1031,7 +1031,7 @@ static wchar_t c2u_9F[256] = {
0x6EF2,0x6F31,0x6EEF,0x6F32,0x6ECC,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E0[256] = {
+static const wchar_t c2u_E0[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1067,7 +1067,7 @@ static wchar_t c2u_E0[256] = {
0x74A7,0x74CA,0x74CF,0x74D4,0x73F1,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E1[256] = {
+static const wchar_t c2u_E1[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1103,7 +1103,7 @@ static wchar_t c2u_E1[256] = {
0x78BE,0x78BC,0x78C5,0x78CA,0x78EC,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E2[256] = {
+static const wchar_t c2u_E2[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1139,7 +1139,7 @@ static wchar_t c2u_E2[256] = {
0x7CF2,0x7CF4,0x7CF6,0x7CFA,0x7D06,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E3[256] = {
+static const wchar_t c2u_E3[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1175,7 +1175,7 @@ static wchar_t c2u_E3[256] = {
0x811B,0x8129,0x8123,0x812F,0x814B,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E4[256] = {
+static const wchar_t c2u_E4[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1211,7 +1211,7 @@ static wchar_t c2u_E4[256] = {
0x84FC,0x8540,0x8563,0x8558,0x8548,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E5[256] = {
+static const wchar_t c2u_E5[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1247,7 +1247,7 @@ static wchar_t c2u_E5[256] = {
0x8938,0x894C,0x891D,0x8960,0x895E,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E6[256] = {
+static const wchar_t c2u_E6[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1283,7 +1283,7 @@ static wchar_t c2u_E6[256] = {
0x8E42,0x8E35,0x8E30,0x8E34,0x8E4A,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E7[256] = {
+static const wchar_t c2u_E7[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1319,7 +1319,7 @@ static wchar_t c2u_E7[256] = {
0x92E9,0x930F,0x92FA,0x9344,0x932E,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E8[256] = {
+static const wchar_t c2u_E8[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1355,7 +1355,7 @@ static wchar_t c2u_E8[256] = {
0x984F,0x984B,0x986B,0x986F,0x9870,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E9[256] = {
+static const wchar_t c2u_E9[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1391,7 +1391,7 @@ static wchar_t c2u_E9[256] = {
0x9D41,0x9D3F,0x9D3E,0x9D46,0x9D48,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_EA[256] = {
+static const wchar_t c2u_EA[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1416,7 +1416,7 @@ static wchar_t c2u_EA[256] = {
0x69C7,0x9059,0x7464,0x51DC,0x7199,0x0000,0x0000,0x0000,/* 0xA0-0xA7 */
};
-static wchar_t c2u_ED[256] = {
+static const wchar_t c2u_ED[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1452,7 +1452,7 @@ static wchar_t c2u_ED[256] = {
0x7147,0xFA15,0x71C1,0x71FE,0x72B1,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_EE[256] = {
+static const wchar_t c2u_EE[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1488,7 +1488,7 @@ static wchar_t c2u_EE[256] = {
0x2179,0xFFE2,0xFFE4,0xFF07,0xFF02,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_FA[256] = {
+static const wchar_t c2u_FA[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1524,7 +1524,7 @@ static wchar_t c2u_FA[256] = {
0x6C6F,0x6CDA,0x6D04,0x6D87,0x6D6F,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_FB[256] = {
+static const wchar_t c2u_FB[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1560,7 +1560,7 @@ static wchar_t c2u_FB[256] = {
0x9927,0xFA2C,0x999E,0x9A4E,0x9AD9,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_FC[256] = {
+static const wchar_t c2u_FC[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1573,7 +1573,7 @@ static wchar_t c2u_FC[256] = {
0x9D6B,0xFA2D,0x9E19,0x9ED1,0x0000,0x0000,0x0000,0x0000,/* 0x48-0x4F */
};
-static wchar_t *page_charset2uni[256] = {
+static const wchar_t *page_charset2uni[256] = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -1608,7 +1608,7 @@ static wchar_t *page_charset2uni[256] = {
NULL, NULL, c2u_FA, c2u_FB, c2u_FC, NULL, NULL, NULL,
};
-static unsigned char u2c_00hi[256 - 0xA0][2] = {
+static const unsigned char u2c_00hi[256 - 0xA0][2] = {
{0x00, 0x00}, {0x00, 0x00}, {0x81, 0x91}, {0x81, 0x92},/* 0xA0-0xA3 */
{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x81, 0x98},/* 0xA4-0xA7 */
{0x81, 0x4E}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xA8-0xAB */
@@ -1635,7 +1635,7 @@ static unsigned char u2c_00hi[256 - 0xA0][2] = {
{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xFC-0xFF */
};
-static unsigned char u2c_03[512] = {
+static const unsigned char u2c_03[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -1690,7 +1690,7 @@ static unsigned char u2c_03[512] = {
0x83, 0xD5, 0x83, 0xD6, 0x00, 0x00, 0x00, 0x00, /* 0xC8-0xCB */
};
-static unsigned char u2c_04[512] = {
+static const unsigned char u2c_04[512] = {
0x00, 0x00, 0x84, 0x46, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -1714,7 +1714,7 @@ static unsigned char u2c_04[512] = {
0x00, 0x00, 0x84, 0x76, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x53 */
};
-static unsigned char u2c_20[512] = {
+static const unsigned char u2c_20[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -1732,7 +1732,7 @@ static unsigned char u2c_20[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xA6, /* 0x38-0x3B */
};
-static unsigned char u2c_21[512] = {
+static const unsigned char u2c_21[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x8E, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -1790,7 +1790,7 @@ static unsigned char u2c_21[512] = {
0x81, 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xD4-0xD7 */
};
-static unsigned char u2c_22[512] = {
+static const unsigned char u2c_22[512] = {
0x81, 0xCD, 0x00, 0x00, 0x81, 0xDD, 0x81, 0xCE, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xDE, /* 0x04-0x07 */
0x81, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x81, 0xB9, /* 0x08-0x0B */
@@ -1842,7 +1842,7 @@ static unsigned char u2c_22[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x99, /* 0xBC-0xBF */
};
-static unsigned char u2c_23[512] = {
+static const unsigned char u2c_23[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -1850,7 +1850,7 @@ static unsigned char u2c_23[512] = {
0x00, 0x00, 0x00, 0x00, 0x81, 0xDC, 0x00, 0x00, /* 0x10-0x13 */
};
-static unsigned char u2c_24[512] = {
+static const unsigned char u2c_24[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -1882,7 +1882,7 @@ static unsigned char u2c_24[512] = {
0x87, 0x50, 0x87, 0x51, 0x87, 0x52, 0x87, 0x53, /* 0x70-0x73 */
};
-static unsigned char u2c_25[512] = {
+static const unsigned char u2c_25[512] = {
0x84, 0x9F, 0x84, 0xAA, 0x84, 0xA0, 0x84, 0xAB, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -1946,7 +1946,7 @@ static unsigned char u2c_25[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xFC, /* 0xEC-0xEF */
};
-static unsigned char u2c_26[512] = {
+static const unsigned char u2c_26[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x81, 0x9A, 0x81, 0x99, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -1977,7 +1977,7 @@ static unsigned char u2c_26[512] = {
0x00, 0x00, 0x81, 0xF3, 0x00, 0x00, 0x81, 0xF2, /* 0x6C-0x6F */
};
-static unsigned char u2c_30[512] = {
+static const unsigned char u2c_30[512] = {
0x81, 0x40, 0x81, 0x41, 0x81, 0x42, 0x81, 0x56, /* 0x00-0x03 */
0x00, 0x00, 0x81, 0x58, 0x81, 0x59, 0x81, 0x5A, /* 0x04-0x07 */
0x81, 0x71, 0x81, 0x72, 0x81, 0x73, 0x81, 0x74, /* 0x08-0x0B */
@@ -2045,7 +2045,7 @@ static unsigned char u2c_30[512] = {
0x81, 0x5B, 0x81, 0x52, 0x81, 0x53, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_32[512] = {
+static const unsigned char u2c_32[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -2092,7 +2092,7 @@ static unsigned char u2c_32[512] = {
0x87, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xA8-0xAB */
};
-static unsigned char u2c_33[512] = {
+static const unsigned char u2c_33[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x65, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -2148,7 +2148,7 @@ static unsigned char u2c_33[512] = {
0x00, 0x00, 0x87, 0x83, 0x00, 0x00, 0x00, 0x00, /* 0xCC-0xCF */
};
-static unsigned char u2c_4E[512] = {
+static const unsigned char u2c_4E[512] = {
0x88, 0xEA, 0x92, 0x9A, 0x00, 0x00, 0x8E, 0xB5, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x9C, /* 0x04-0x07 */
0x8F, 0xE4, 0x8E, 0x4F, 0x8F, 0xE3, 0x89, 0xBA, /* 0x08-0x0B */
@@ -2216,7 +2216,7 @@ static unsigned char u2c_4E[512] = {
0xED, 0x4E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_4F[512] = {
+static const unsigned char u2c_4F[512] = {
0xED, 0x4F, 0x8A, 0xE9, 0x00, 0x00, 0xED, 0x50, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x98, 0xC2, 0x88, 0xC9, 0x00, 0x00, /* 0x08-0x0B */
@@ -2284,7 +2284,7 @@ static unsigned char u2c_4F[512] = {
0x00, 0x00, 0x00, 0x00, 0x98, 0xEA, 0xED, 0x5A, /* 0xFC-0xFF */
};
-static unsigned char u2c_50[512] = {
+static const unsigned char u2c_50[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x98, 0xE4, 0x98, 0xED, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x91, 0x71, 0x00, 0x00, 0x8C, 0xC2, /* 0x08-0x0B */
@@ -2351,7 +2351,7 @@ static unsigned char u2c_50[512] = {
0x00, 0x00, 0x99, 0x4A, 0x00, 0x00, 0x95, 0xC6, /* 0xF8-0xFB */
};
-static unsigned char u2c_51[512] = {
+static const unsigned char u2c_51[512] = {
0x8B, 0x56, 0x99, 0x4D, 0x99, 0x4E, 0x00, 0x00, /* 0x00-0x03 */
0x89, 0xAD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x99, 0x4C, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -2419,7 +2419,7 @@ static unsigned char u2c_51[512] = {
0x00, 0x00, 0x94, 0x9F, 0x99, 0x82, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_52[512] = {
+static const unsigned char u2c_52[512] = {
0x93, 0x81, 0x00, 0x00, 0x00, 0x00, 0x90, 0x6E, /* 0x00-0x03 */
0x99, 0x83, 0x00, 0x00, 0x95, 0xAA, 0x90, 0xD8, /* 0x04-0x07 */
0x8A, 0xA0, 0x00, 0x00, 0x8A, 0xA7, 0x99, 0x84, /* 0x08-0x0B */
@@ -2487,7 +2487,7 @@ static unsigned char u2c_52[512] = {
0x00, 0x00, 0x00, 0x00, 0x8C, 0xF9, 0x96, 0xDC, /* 0xFC-0xFF */
};
-static unsigned char u2c_53[512] = {
+static const unsigned char u2c_53[512] = {
0xED, 0x6C, 0x96, 0xE6, 0x93, 0xF5, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x95, 0xEF, 0x99, 0xB0, 0xED, 0x6D, /* 0x04-0x07 */
0x99, 0xB1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -2554,7 +2554,7 @@ static unsigned char u2c_53[512] = {
0x8E, 0x69, 0x00, 0x00, 0x99, 0xDB, 0x00, 0x00, /* 0xF8-0xFB */
};
-static unsigned char u2c_54[512] = {
+static const unsigned char u2c_54[512] = {
0x00, 0x00, 0x99, 0xDC, 0x00, 0x00, 0x8B, 0x68, /* 0x00-0x03 */
0x8A, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x8D, 0x87, 0x8B, 0x67, 0x92, 0xDD, 0x89, 0x44, /* 0x08-0x0B */
@@ -2622,7 +2622,7 @@ static unsigned char u2c_54[512] = {
0x00, 0x00, 0x9A, 0x4A, 0x00, 0x00, 0xED, 0x77, /* 0xFC-0xFF */
};
-static unsigned char u2c_55[512] = {
+static const unsigned char u2c_55[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x89, 0x53, 0x00, 0x00, 0x8D, 0xB4, 0x90, 0x4F, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -2690,7 +2690,7 @@ static unsigned char u2c_55[512] = {
0x00, 0x00, 0x9A, 0x75, 0x9A, 0x74, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_56[512] = {
+static const unsigned char u2c_56[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x92, 0x51, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x89, 0xC3, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -2758,7 +2758,7 @@ static unsigned char u2c_56[512] = {
0x00, 0x00, 0x8D, 0x91, 0x00, 0x00, 0x9A, 0x9C, /* 0xFC-0xFF */
};
-static unsigned char u2c_57[512] = {
+static const unsigned char u2c_57[512] = {
0x9A, 0x9B, 0x00, 0x00, 0x00, 0x00, 0x95, 0xDE, /* 0x00-0x03 */
0x9A, 0x9D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x9A, 0x9F, 0x9A, 0x9E, 0x00, 0x00, 0x9A, 0xA0, /* 0x08-0x0B */
@@ -2826,7 +2826,7 @@ static unsigned char u2c_57[512] = {
0x8D, 0xE9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_58[512] = {
+static const unsigned char u2c_58[512] = {
0x96, 0x78, 0x00, 0x00, 0x93, 0xB0, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x8C, 0x98, 0x91, 0xCD, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x9A, 0xBF, 0x9A, 0xC2, /* 0x08-0x0B */
@@ -2894,7 +2894,7 @@ static unsigned char u2c_58[512] = {
0x9A, 0xE5, 0x9A, 0xE6, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_59[512] = {
+static const unsigned char u2c_59[512] = {
0x00, 0x00, 0x00, 0x00, 0x9A, 0xE7, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x95, 0xCF, 0x9A, 0xE8, 0xED, 0x83, /* 0x08-0x0B */
@@ -2962,7 +2962,7 @@ static unsigned char u2c_59[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8E, 0x70, /* 0xFC-0xFF */
};
-static unsigned char u2c_5A[512] = {
+static const unsigned char u2c_5A[512] = {
0x00, 0x00, 0x88, 0xD0, 0x00, 0x00, 0x88, 0xA1, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x9B, 0x51, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -3029,7 +3029,7 @@ static unsigned char u2c_5A[512] = {
0x00, 0x00, 0x00, 0x00, 0x9B, 0x65, 0x9B, 0x66, /* 0xF8-0xFB */
};
-static unsigned char u2c_5B[512] = {
+static const unsigned char u2c_5B[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x8A, 0xF0, 0x00, 0x00, 0x9B, 0x68, /* 0x08-0x0B */
@@ -3097,7 +3097,7 @@ static unsigned char u2c_5B[512] = {
0x00, 0x00, 0x00, 0x00, 0x91, 0xCE, 0x8E, 0xF5, /* 0xFC-0xFF */
};
-static unsigned char u2c_5C[512] = {
+static const unsigned char u2c_5C[512] = {
0x00, 0x00, 0x95, 0x95, 0x90, 0xEA, 0x00, 0x00, /* 0x00-0x03 */
0x8E, 0xCB, 0x9B, 0x91, 0x8F, 0xAB, 0x9B, 0x92, /* 0x04-0x07 */
0x9B, 0x93, 0x88, 0xD1, 0x91, 0xB8, 0x90, 0x71, /* 0x08-0x0B */
@@ -3165,7 +3165,7 @@ static unsigned char u2c_5C[512] = {
0x00, 0x00, 0x9B, 0xB5, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_5D[512] = {
+static const unsigned char u2c_5D[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x92, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9B, 0xBA, /* 0x08-0x0B */
@@ -3233,7 +3233,7 @@ static unsigned char u2c_5D[512] = {
0x00, 0x00, 0x92, 0x46, 0x8B, 0xD0, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_5E[512] = {
+static const unsigned char u2c_5E[512] = {
0x00, 0x00, 0x00, 0x00, 0x8E, 0x73, 0x95, 0x7A, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x94, 0xBF, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9B, 0xE1, /* 0x08-0x0B */
@@ -3301,7 +3301,7 @@ static unsigned char u2c_5E[512] = {
0x94, 0x55, 0x00, 0x00, 0x9C, 0x4F, 0x93, 0xF9, /* 0xFC-0xFF */
};
-static unsigned char u2c_5F[512] = {
+static const unsigned char u2c_5F[512] = {
0x00, 0x00, 0x95, 0xD9, 0x00, 0x00, 0x9C, 0x50, /* 0x00-0x03 */
0x98, 0x4D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x9C, 0x51, 0x95, 0xBE, 0x9C, 0x54, /* 0x08-0x0B */
@@ -3369,7 +3369,7 @@ static unsigned char u2c_5F[512] = {
0x00, 0x00, 0x8D, 0x9A, 0x00, 0x00, 0x9C, 0x7C, /* 0xFC-0xFF */
};
-static unsigned char u2c_60[512] = {
+static const unsigned char u2c_60[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -3436,7 +3436,7 @@ static unsigned char u2c_60[512] = {
0x00, 0x00, 0x8E, 0xE4, 0x9C, 0xB7, 0x9C, 0xBA, /* 0xF8-0xFB */
};
-static unsigned char u2c_61[512] = {
+static const unsigned char u2c_61[512] = {
0x9C, 0xB5, 0x8F, 0x44, 0x00, 0x00, 0x9C, 0xB8, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x9C, 0xB2, 0x00, 0x00, /* 0x04-0x07 */
0x96, 0xFA, 0x96, 0xF9, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -3504,7 +3504,7 @@ static unsigned char u2c_61[512] = {
0x9C, 0xF4, 0x9C, 0xF3, 0x9C, 0xF5, 0x9C, 0xF2, /* 0xFC-0xFF */
};
-static unsigned char u2c_62[512] = {
+static const unsigned char u2c_62[512] = {
0x9C, 0xF6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x9C, 0xF7, 0x9C, 0xF8, 0x95, 0xE8, 0x00, 0x00, /* 0x08-0x0B */
@@ -3572,7 +3572,7 @@ static unsigned char u2c_62[512] = {
0x00, 0x00, 0x00, 0x00, 0x8F, 0x45, 0x9D, 0x5C, /* 0xFC-0xFF */
};
-static unsigned char u2c_63[512] = {
+static const unsigned char u2c_63[512] = {
0x00, 0x00, 0x8E, 0x9D, 0x9D, 0x6B, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8E, 0x77, /* 0x04-0x07 */
0x9D, 0x6C, 0x88, 0xC2, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -3639,7 +3639,7 @@ static unsigned char u2c_63[512] = {
0x00, 0x00, 0x00, 0x00, 0x97, 0x68, 0x00, 0x00, /* 0xF8-0xFB */
};
-static unsigned char u2c_64[512] = {
+static const unsigned char u2c_64[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x9D, 0x8C, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -3707,7 +3707,7 @@ static unsigned char u2c_64[512] = {
0x00, 0x00, 0x9D, 0xB4, 0x8F, 0xEF, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_65[512] = {
+static const unsigned char u2c_65[512] = {
0x9D, 0xB3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x9D, 0xB7, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -3774,7 +3774,7 @@ static unsigned char u2c_65[512] = {
0x00, 0x00, 0x00, 0x00, 0x89, 0xA0, 0x9D, 0xDF, /* 0xF8-0xFB */
};
-static unsigned char u2c_66[512] = {
+static const unsigned char u2c_66[512] = {
0xED, 0xB2, 0x00, 0x00, 0x8D, 0x56, 0x9D, 0xDE, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x8D, 0xA9, 0x8F, 0xB8, /* 0x04-0x07 */
0x00, 0x00, 0xED, 0xB5, 0x9D, 0xDD, 0x00, 0x00, /* 0x08-0x0B */
@@ -3842,7 +3842,7 @@ static unsigned char u2c_66[512] = {
0x99, 0xD6, 0x91, 0x5D, 0x91, 0x5C, 0x91, 0xD6, /* 0xFC-0xFF */
};
-static unsigned char u2c_67[512] = {
+static const unsigned char u2c_67[512] = {
0x8D, 0xC5, 0x00, 0x00, 0x00, 0x00, 0x98, 0xF0, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x8C, 0x8E, 0x97, 0x4C, 0x00, 0x00, 0x95, 0xFC, /* 0x08-0x0B */
@@ -3910,7 +3910,7 @@ static unsigned char u2c_67[512] = {
0x00, 0x00, 0x00, 0x00, 0x96, 0x8F, 0x8A, 0x60, /* 0xFC-0xFF */
};
-static unsigned char u2c_68[512] = {
+static const unsigned char u2c_68[512] = {
0x00, 0x00, 0xED, 0xC9, 0x92, 0xCC, 0x93, 0xC8, /* 0x00-0x03 */
0x89, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -3977,7 +3977,7 @@ static unsigned char u2c_68[512] = {
0x00, 0x00, 0x9E, 0xA8, 0x8A, 0xBB, 0x00, 0x00, /* 0xF8-0xFB */
};
-static unsigned char u2c_69[512] = {
+static const unsigned char u2c_69[512] = {
0x98, 0x6F, 0x9E, 0x96, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x9E, 0xA4, 0x88, 0xD6, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x9E, 0x98, 0x00, 0x00, 0x00, 0x00, 0x96, 0xB8, /* 0x08-0x0B */
@@ -4045,7 +4045,7 @@ static unsigned char u2c_69[512] = {
0x00, 0x00, 0x91, 0x85, 0x00, 0x00, 0x9E, 0xDB, /* 0xFC-0xFF */
};
-static unsigned char u2c_6A[512] = {
+static const unsigned char u2c_6A[512] = {
0x00, 0x00, 0x00, 0x00, 0x9E, 0xD9, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x9E, 0xE0, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x9E, 0xE6, 0x94, 0xF3, /* 0x08-0x0B */
@@ -4112,7 +4112,7 @@ static unsigned char u2c_6A[512] = {
0x00, 0x00, 0x00, 0x00, 0x9F, 0x51, 0x9F, 0x4E, /* 0xF8-0xFB */
};
-static unsigned char u2c_6B[512] = {
+static const unsigned char u2c_6B[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x97, 0x93, 0x9F, 0x4F, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x9E, 0xDC, 0x00, 0x00, /* 0x08-0x0B */
@@ -4177,7 +4177,7 @@ static unsigned char u2c_6B[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9F, 0x7D, /* 0xF0-0xF3 */
};
-static unsigned char u2c_6C[512] = {
+static const unsigned char u2c_6C[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x9F, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -4242,7 +4242,7 @@ static unsigned char u2c_6C[512] = {
0x91, 0xD7, 0x9F, 0x96, 0x00, 0x00, 0x89, 0x6A, /* 0xF0-0xF3 */
};
-static unsigned char u2c_6D[512] = {
+static const unsigned char u2c_6D[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0xED, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0x6D, /* 0x08-0x0B */
@@ -4310,7 +4310,7 @@ static unsigned char u2c_6D[512] = {
0xED, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_6E[512] = {
+static const unsigned char u2c_6E[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x90, 0xB4, 0x00, 0x00, 0x8A, 0x89, /* 0x04-0x07 */
0x8D, 0xCF, 0x8F, 0xC2, 0x9F, 0xBB, 0x8F, 0x61, /* 0x08-0x0B */
@@ -4378,7 +4378,7 @@ static unsigned char u2c_6E[512] = {
0x00, 0x00, 0x00, 0x00, 0x9F, 0xF6, 0x9F, 0xDE, /* 0xFC-0xFF */
};
-static unsigned char u2c_6F[512] = {
+static const unsigned char u2c_6F[512] = {
0x00, 0x00, 0x8B, 0x99, 0x95, 0x59, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x8E, 0xBD, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x8D, 0x97, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -4446,7 +4446,7 @@ static unsigned char u2c_6F[512] = {
0x00, 0x00, 0x00, 0x00, 0xE0, 0x68, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_70[512] = {
+static const unsigned char u2c_70[512] = {
0x00, 0x00, 0xE0, 0x66, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0xED, 0xEF, 0x00, 0x00, 0xED, 0xF0, /* 0x04-0x07 */
0x00, 0x00, 0xE0, 0x62, 0x00, 0x00, 0xE0, 0x63, /* 0x08-0x0B */
@@ -4514,7 +4514,7 @@ static unsigned char u2c_70[512] = {
0x00, 0x00, 0xE0, 0x82, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_71[512] = {
+static const unsigned char u2c_71[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0xED, 0xF5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0xE0, 0x81, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -4582,7 +4582,7 @@ static unsigned char u2c_71[512] = {
0xE0, 0x9E, 0x00, 0x00, 0xED, 0xFB, 0xE0, 0xA0, /* 0xFC-0xFF */
};
-static unsigned char u2c_72[512] = {
+static const unsigned char u2c_72[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x94, 0x9A, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -4650,7 +4650,7 @@ static unsigned char u2c_72[512] = {
0x98, 0x54, 0x94, 0x82, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_73[512] = {
+static const unsigned char u2c_73[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0xE0, 0xC7, 0x00, 0x00, /* 0x08-0x0B */
@@ -4718,7 +4718,7 @@ static unsigned char u2c_73[512] = {
0x00, 0x00, 0x00, 0x00, 0x8C, 0xBB, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_74[512] = {
+static const unsigned char u2c_74[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0x85, /* 0x00-0x03 */
0x00, 0x00, 0xE0, 0xE4, 0x97, 0x9D, 0xEE, 0x49, /* 0x04-0x07 */
0x00, 0x00, 0x97, 0xAE, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -4785,7 +4785,7 @@ static unsigned char u2c_74[512] = {
0xE1, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xF8-0xFB */
};
-static unsigned char u2c_75[512] = {
+static const unsigned char u2c_75[512] = {
0x00, 0x00, 0xEE, 0x52, 0x00, 0x00, 0xE1, 0x4B, /* 0x00-0x03 */
0xE1, 0x4A, 0xE1, 0x4C, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -4853,7 +4853,7 @@ static unsigned char u2c_75[512] = {
0xE1, 0x80, 0x00, 0x00, 0xE1, 0x7D, 0xE1, 0x7E, /* 0xFC-0xFF */
};
-static unsigned char u2c_76[512] = {
+static const unsigned char u2c_76[512] = {
0x00, 0x00, 0xE1, 0x81, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0xE1, 0x88, 0x00, 0x00, 0xE1, 0x86, /* 0x08-0x0B */
@@ -4921,7 +4921,7 @@ static unsigned char u2c_76[512] = {
0x00, 0x00, 0x00, 0x00, 0x8F, 0x82, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_77[512] = {
+static const unsigned char u2c_77[512] = {
0x00, 0x00, 0x8F, 0xC8, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0xE1, 0xBE, 0x00, 0x00, 0x00, 0x00, 0xE1, 0xBD, /* 0x04-0x07 */
0xE1, 0xBC, 0x94, 0xFB, 0x00, 0x00, 0x8A, 0xC5, /* 0x08-0x0B */
@@ -4989,7 +4989,7 @@ static unsigned char u2c_77[512] = {
0xE1, 0xE3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_78[512] = {
+static const unsigned char u2c_78[512] = {
0x00, 0x00, 0x00, 0x00, 0x8D, 0xBB, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -5057,7 +5057,7 @@ static unsigned char u2c_78[512] = {
0x00, 0x00, 0xE2, 0x42, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_79[512] = {
+static const unsigned char u2c_79[512] = {
0x00, 0x00, 0x8F, 0xCA, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE2, 0x44, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -5124,7 +5124,7 @@ static unsigned char u2c_79[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xDA, /* 0xF8-0xFB */
};
-static unsigned char u2c_7A[512] = {
+static const unsigned char u2c_7A[512] = {
0x8B, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0xE2, 0x62, 0x00, 0x00, 0x00, 0x00, 0x92, 0xF6, /* 0x08-0x0B */
@@ -5192,7 +5192,7 @@ static unsigned char u2c_7A[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8A, 0xC6, /* 0xFC-0xFF */
};
-static unsigned char u2c_7B[512] = {
+static const unsigned char u2c_7B[512] = {
0x00, 0x00, 0x00, 0x00, 0xE2, 0x93, 0x00, 0x00, /* 0x00-0x03 */
0xE2, 0xA0, 0x00, 0x00, 0xE2, 0x96, 0x00, 0x00, /* 0x04-0x07 */
0x8B, 0x88, 0x00, 0x00, 0xE2, 0x95, 0xE2, 0xA2, /* 0x08-0x0B */
@@ -5258,7 +5258,7 @@ static unsigned char u2c_7B[512] = {
0x00, 0x00, 0x00, 0x00, 0xE2, 0xCC, 0xE2, 0xC9, /* 0xF4-0xF7 */
};
-static unsigned char u2c_7C[512] = {
+static const unsigned char u2c_7C[512] = {
0xE2, 0xC5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE2, 0xC6, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -5326,7 +5326,7 @@ static unsigned char u2c_7C[512] = {
0x00, 0x00, 0x00, 0x00, 0x8B, 0x8A, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_7D[512] = {
+static const unsigned char u2c_7D[512] = {
0x8B, 0x49, 0x00, 0x00, 0xE3, 0x40, 0x00, 0x00, /* 0x00-0x03 */
0x96, 0xF1, 0x8D, 0x67, 0xE2, 0xFC, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0xE3, 0x43, 0x96, 0xE4, /* 0x08-0x0B */
@@ -5393,7 +5393,7 @@ static unsigned char u2c_7D[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE3, 0x6B, /* 0xF8-0xFB */
};
-static unsigned char u2c_7E[512] = {
+static const unsigned char u2c_7E[512] = {
0x00, 0x00, 0x89, 0x8F, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x93, 0xEA, 0xE3, 0x6E, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0xE3, 0x75, 0xE3, 0x6F, 0xE3, 0x76, /* 0x08-0x0B */
@@ -5437,7 +5437,7 @@ static unsigned char u2c_7E[512] = {
0xE3, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9C-0x9F */
};
-static unsigned char u2c_7F[512] = {
+static const unsigned char u2c_7F[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -5505,7 +5505,7 @@ static unsigned char u2c_7F[512] = {
0x97, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_80[512] = {
+static const unsigned char u2c_80[512] = {
0x97, 0x73, 0x98, 0x56, 0x00, 0x00, 0x8D, 0x6C, /* 0x00-0x03 */
0xE3, 0xCC, 0x8E, 0xD2, 0xE3, 0xCB, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE3, 0xCD, /* 0x08-0x0B */
@@ -5573,7 +5573,7 @@ static unsigned char u2c_80[512] = {
0xE4, 0x45, 0x94, 0x5C, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_81[512] = {
+static const unsigned char u2c_81[512] = {
0x00, 0x00, 0x00, 0x00, 0x8E, 0x89, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x8B, 0xBA, 0x90, 0xC6, 0x98, 0x65, /* 0x04-0x07 */
0x96, 0xAC, 0xE3, 0xF5, 0x90, 0xD2, 0x00, 0x00, /* 0x08-0x0B */
@@ -5641,7 +5641,7 @@ static unsigned char u2c_81[512] = {
0x89, 0x50, 0x00, 0x00, 0xE4, 0x6B, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_82[512] = {
+static const unsigned char u2c_82[512] = {
0x00, 0x00, 0xE4, 0x6C, 0xE4, 0x6D, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0xE4, 0x6E, 0x00, 0x00, 0xE4, 0x6F, /* 0x04-0x07 */
0x8B, 0xBB, 0x9D, 0xA8, 0xE4, 0x70, 0x00, 0x00, /* 0x08-0x0B */
@@ -5708,7 +5708,7 @@ static unsigned char u2c_82[512] = {
0x00, 0x00, 0xE4, 0x99, 0xE4, 0x95, 0xE4, 0x98, /* 0xF8-0xFB */
};
-static unsigned char u2c_83[512] = {
+static const unsigned char u2c_83[512] = {
0x00, 0x00, 0xEE, 0x76, 0x96, 0xCE, 0xE4, 0x97, /* 0x00-0x03 */
0x89, 0xD6, 0x8A, 0x9D, 0xE4, 0x9B, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0xE4, 0x9D, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -5776,7 +5776,7 @@ static unsigned char u2c_83[512] = {
0x00, 0x00, 0xE4, 0xC1, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_84[512] = {
+static const unsigned char u2c_84[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE4, 0xC2, /* 0x00-0x03 */
0x93, 0xB8, 0x00, 0x00, 0x00, 0x00, 0xE4, 0xC7, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE4, 0xC4, /* 0x08-0x0B */
@@ -5844,7 +5844,7 @@ static unsigned char u2c_84[512] = {
0xE4, 0xF8, 0x00, 0x00, 0x00, 0x00, 0xE4, 0xF0, /* 0xFC-0xFF */
};
-static unsigned char u2c_85[512] = {
+static const unsigned char u2c_85[512] = {
0x8E, 0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0xE4, 0xCF, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -5912,7 +5912,7 @@ static unsigned char u2c_85[512] = {
0x00, 0x00, 0x00, 0x00, 0xE5, 0x60, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_86[512] = {
+static const unsigned char u2c_86[512] = {
0x00, 0x00, 0x00, 0x00, 0xE5, 0x41, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0xE5, 0x62, 0x91, 0x68, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0xE5, 0x5D, 0xE5, 0x5F, /* 0x08-0x0B */
@@ -5980,7 +5980,7 @@ static unsigned char u2c_86[512] = {
0x00, 0x00, 0x00, 0x00, 0x89, 0xE9, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_87[512] = {
+static const unsigned char u2c_87[512] = {
0xE5, 0x86, 0x00, 0x00, 0x96, 0x49, 0xE5, 0x87, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0xE5, 0x84, 0x00, 0x00, /* 0x04-0x07 */
0xE5, 0x85, 0xE5, 0x8A, 0xE5, 0x8D, 0x00, 0x00, /* 0x08-0x0B */
@@ -6048,7 +6048,7 @@ static unsigned char u2c_87[512] = {
0x00, 0x00, 0x00, 0x00, 0xE5, 0xB7, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_88[512] = {
+static const unsigned char u2c_88[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0xE5, 0xA2, 0x00, 0x00, 0xEE, 0x85, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -6116,7 +6116,7 @@ static unsigned char u2c_88[512] = {
0xE5, 0xE7, 0x90, 0xBB, 0x90, 0x9E, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_89[512] = {
+static const unsigned char u2c_89[512] = {
0x00, 0x00, 0x00, 0x00, 0xE5, 0xE6, 0x00, 0x00, /* 0x00-0x03 */
0xE5, 0xEB, 0x00, 0x00, 0x00, 0x00, 0x95, 0xA1, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0xE5, 0xED, 0x00, 0x00, /* 0x08-0x0B */
@@ -6183,7 +6183,7 @@ static unsigned char u2c_89[512] = {
0xE6, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xF8-0xFB */
};
-static unsigned char u2c_8A[512] = {
+static const unsigned char u2c_8A[512] = {
0x8C, 0xBE, 0x00, 0x00, 0x92, 0xF9, 0xE6, 0x5D, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x8C, 0x76, 0x00, 0x00, 0x90, 0x75, 0x00, 0x00, /* 0x08-0x0B */
@@ -6251,7 +6251,7 @@ static unsigned char u2c_8A[512] = {
0x00, 0x00, 0x00, 0x00, 0x91, 0xF8, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_8B[512] = {
+static const unsigned char u2c_8B[512] = {
0x96, 0x64, 0x89, 0x79, 0x88, 0xE0, 0x00, 0x00, /* 0x00-0x03 */
0x93, 0xA3, 0x00, 0x00, 0x00, 0x00, 0xE6, 0x89, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -6294,7 +6294,7 @@ static unsigned char u2c_8B[512] = {
0x00, 0x00, 0xE6, 0xAA, 0xE6, 0xAB, 0x00, 0x00, /* 0x98-0x9B */
};
-static unsigned char u2c_8C[512] = {
+static const unsigned char u2c_8C[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -6362,7 +6362,7 @@ static unsigned char u2c_8C[512] = {
0x8D, 0x77, 0xE6, 0xCE, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_8D[512] = {
+static const unsigned char u2c_8D[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0xE6, 0xD1, 0xE6, 0xD2, 0x00, 0x00, 0xE6, 0xD4, /* 0x04-0x07 */
0x91, 0xA1, 0x00, 0x00, 0xE6, 0xD3, 0x8A, 0xE4, /* 0x08-0x0B */
@@ -6430,7 +6430,7 @@ static unsigned char u2c_8D[512] = {
0xE6, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xF3, /* 0xFC-0xFF */
};
-static unsigned char u2c_8E[512] = {
+static const unsigned char u2c_8E[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0xE6, 0xF1, 0xE6, 0xF2, 0x97, 0x78, 0x00, 0x00, /* 0x08-0x0B */
@@ -6498,7 +6498,7 @@ static unsigned char u2c_8E[512] = {
0xE7, 0x64, 0x8C, 0x79, 0xE7, 0x67, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_8F[512] = {
+static const unsigned char u2c_8F[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x72, /* 0x00-0x03 */
0x00, 0x00, 0xE7, 0x69, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x8D, 0xDA, 0xE7, 0x68, 0x00, 0x00, /* 0x08-0x0B */
@@ -6566,7 +6566,7 @@ static unsigned char u2c_8F[512] = {
0x00, 0x00, 0x92, 0xC7, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_90[512] = {
+static const unsigned char u2c_90[512] = {
0x91, 0xDE, 0x91, 0x97, 0x00, 0x00, 0x93, 0xA6, /* 0x00-0x03 */
0x00, 0x00, 0xE7, 0x90, 0x8B, 0x74, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE7, 0x99, /* 0x08-0x0B */
@@ -6634,7 +6634,7 @@ static unsigned char u2c_90[512] = {
0x00, 0x00, 0x93, 0x73, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_91[512] = {
+static const unsigned char u2c_91[512] = {
0x00, 0x00, 0x00, 0x00, 0xE7, 0xBD, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -6702,7 +6702,7 @@ static unsigned char u2c_91[512] = {
0xE7, 0xDD, 0x00, 0x00, 0x00, 0x00, 0xE7, 0xE1, /* 0xFC-0xFF */
};
-static unsigned char u2c_92[512] = {
+static const unsigned char u2c_92[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0xEE, 0xA5, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0xEE, 0xA7, 0x00, 0x00, /* 0x08-0x0B */
@@ -6770,7 +6770,7 @@ static unsigned char u2c_92[512] = {
0x8D, 0x7C, 0x00, 0x00, 0x00, 0x00, 0xEE, 0xC0, /* 0xFC-0xFF */
};
-static unsigned char u2c_93[512] = {
+static const unsigned char u2c_93[512] = {
0x00, 0x00, 0x00, 0x00, 0xEE, 0xC2, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x8E, 0x4B, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -6837,7 +6837,7 @@ static unsigned char u2c_93[512] = {
0xEE, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xF8-0xFB */
};
-static unsigned char u2c_94[512] = {
+static const unsigned char u2c_94[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE8, 0x5E, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE8, 0x5F, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -6874,7 +6874,7 @@ static unsigned char u2c_94[512] = {
0x00, 0x00, 0xE8, 0x76, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x83 */
};
-static unsigned char u2c_95[512] = {
+static const unsigned char u2c_95[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -6936,7 +6936,7 @@ static unsigned char u2c_95[512] = {
0x00, 0x00, 0xE8, 0x92, 0x00, 0x00, 0x00, 0x00, /* 0xE4-0xE7 */
};
-static unsigned char u2c_96[512] = {
+static const unsigned char u2c_96[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -7003,7 +7003,7 @@ static unsigned char u2c_96[512] = {
0x00, 0x00, 0xE8, 0xB9, 0x00, 0x00, 0x93, 0x64, /* 0xF8-0xFB */
};
-static unsigned char u2c_97[512] = {
+static const unsigned char u2c_97[512] = {
0x8E, 0xF9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0xE8, 0xBA, 0x00, 0x00, 0xE8, 0xBB, 0x90, 0x6B, /* 0x04-0x07 */
0xE8, 0xBC, 0x00, 0x00, 0x97, 0xEC, 0x00, 0x00, /* 0x08-0x0B */
@@ -7071,7 +7071,7 @@ static unsigned char u2c_97[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0xBF, /* 0xFC-0xFF */
};
-static unsigned char u2c_98[512] = {
+static const unsigned char u2c_98[512] = {
0x00, 0x00, 0x95, 0xC5, 0x92, 0xB8, 0x8D, 0xA0, /* 0x00-0x03 */
0x00, 0x00, 0x8D, 0x80, 0x8F, 0x87, 0x00, 0x00, /* 0x04-0x07 */
0x90, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -7139,7 +7139,7 @@ static unsigned char u2c_98[512] = {
0x8E, 0x94, 0x96, 0x4F, 0x8F, 0xFC, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_99[512] = {
+static const unsigned char u2c_99[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE9, 0x4C, /* 0x00-0x03 */
0x00, 0x00, 0x96, 0xDD, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0xE9, 0x4D, 0x97, 0x7B, 0x00, 0x00, /* 0x08-0x0B */
@@ -7207,7 +7207,7 @@ static unsigned char u2c_99[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8F, 0x78, /* 0xFC-0xFF */
};
-static unsigned char u2c_9A[512] = {
+static const unsigned char u2c_9A[512] = {
0x00, 0x00, 0xE9, 0x74, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0xE9, 0x76, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -7274,7 +7274,7 @@ static unsigned char u2c_9A[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE9, 0x9F, /* 0xF8-0xFB */
};
-static unsigned char u2c_9B[512] = {
+static const unsigned char u2c_9B[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0xE9, 0xA0, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -7340,7 +7340,7 @@ static unsigned char u2c_9B[512] = {
0x00, 0x00, 0x88, 0xB1, 0x00, 0x00, 0x00, 0x00, /* 0xF4-0xF7 */
};
-static unsigned char u2c_9C[512] = {
+static const unsigned char u2c_9C[512] = {
0xEE, 0xE7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0xE9, 0xD8, 0x00, 0x00, 0xE9, 0xD4, 0x00, 0x00, /* 0x04-0x07 */
0xE9, 0xD5, 0xE9, 0xD1, 0xE9, 0xD7, 0x00, 0x00, /* 0x08-0x0B */
@@ -7406,7 +7406,7 @@ static unsigned char u2c_9C[512] = {
0x96, 0xC2, 0x00, 0x00, 0x93, 0xCE, 0x00, 0x00, /* 0xF4-0xF7 */
};
-static unsigned char u2c_9D[512] = {
+static const unsigned char u2c_9D[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE9, 0xEE, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0xE9, 0xEF, 0x93, 0xBC, /* 0x04-0x07 */
0xE9, 0xEC, 0xE9, 0xEB, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -7474,7 +7474,7 @@ static unsigned char u2c_9D[512] = {
0x00, 0x00, 0xEA, 0x5E, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_9E[512] = {
+static const unsigned char u2c_9E[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -7542,7 +7542,7 @@ static unsigned char u2c_9E[512] = {
0xEA, 0x85, 0xEA, 0x86, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_9F[512] = {
+static const unsigned char u2c_9F[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEA, 0x87, /* 0x04-0x07 */
0xEA, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -7587,11 +7587,11 @@ static unsigned char u2c_9F[512] = {
0xEA, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xA0-0xA3 */
};
-static unsigned char u2c_DC[512] = {
+static const unsigned char u2c_DC[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
};
-static unsigned char u2c_F9[512] = {
+static const unsigned char u2c_F9[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -7651,7 +7651,7 @@ static unsigned char u2c_F9[512] = {
0xEE, 0xCD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xDC-0xDF */
};
-static unsigned char u2c_FA[512] = {
+static const unsigned char u2c_FA[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -7666,7 +7666,7 @@ static unsigned char u2c_FA[512] = {
0xEE, 0xDD, 0xEE, 0xEA, 0x00, 0x00, 0x00, 0x00, /* 0x2C-0x2F */
};
-static unsigned char u2c_FF[512] = {
+static const unsigned char u2c_FF[512] = {
0x00, 0x00, 0x81, 0x49, 0xEE, 0xFC, 0x81, 0x94, /* 0x00-0x03 */
0x81, 0x90, 0x81, 0x93, 0x81, 0x95, 0xEE, 0xFB, /* 0x04-0x07 */
0x81, 0x69, 0x81, 0x6A, 0x81, 0x96, 0x81, 0x7B, /* 0x08-0x0B */
@@ -7728,7 +7728,7 @@ static unsigned char u2c_FF[512] = {
0xEE, 0xFA, 0x81, 0x8F, 0x00, 0x00, 0x00, 0x00, /* 0xE4-0xE7 */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
NULL, NULL, NULL, u2c_03, u2c_04, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -7762,7 +7762,7 @@ static unsigned char *page_uni2charset[256] = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, u2c_F9, u2c_FA, NULL, NULL, NULL, NULL, u2c_FF, };
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -7798,7 +7798,7 @@ static unsigned char charset2lower[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -7837,7 +7837,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(const wchar_t uni,
unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni&0xFF;
unsigned char ch = (uni>>8)&0xFF;
@@ -7878,7 +7878,7 @@ static int char2uni(const unsigned char *rawstring, int boundlen,
wchar_t *uni)
{
unsigned char ch, cl;
- wchar_t *charset2uni;
+ const wchar_t *charset2uni;
if (boundlen <= 0)
return -ENAMETOOLONG;
diff --git a/fs/nls/nls_cp936.c b/fs/nls/nls_cp936.c
index 65e640c61c8b..82770301bc3d 100644
--- a/fs/nls/nls_cp936.c
+++ b/fs/nls/nls_cp936.c
@@ -13,7 +13,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t c2u_81[256] = {
+static const wchar_t c2u_81[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -49,7 +49,7 @@ static wchar_t c2u_81[256] = {
0x4F99,0x4F9A,0x4F9C,0x4F9E,0x4F9F,0x4FA1,0x4FA2,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_82[256] = {
+static const wchar_t c2u_82[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -85,7 +85,7 @@ static wchar_t c2u_82[256] = {
0x50B4,0x50B5,0x50B6,0x50B7,0x50B8,0x50B9,0x50BC,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_83[256] = {
+static const wchar_t c2u_83[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -121,7 +121,7 @@ static wchar_t c2u_83[256] = {
0x51D0,0x51D2,0x51D3,0x51D4,0x51D5,0x51D6,0x51D7,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_84[256] = {
+static const wchar_t c2u_84[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -157,7 +157,7 @@ static wchar_t c2u_84[256] = {
0x5304,0x5307,0x5309,0x530A,0x530B,0x530C,0x530E,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_85[256] = {
+static const wchar_t c2u_85[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -193,7 +193,7 @@ static wchar_t c2u_85[256] = {
0x5497,0x5498,0x549C,0x549E,0x549F,0x54A0,0x54A1,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_86[256] = {
+static const wchar_t c2u_86[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -229,7 +229,7 @@ static wchar_t c2u_86[256] = {
0x55FB,0x55FC,0x55FF,0x5602,0x5603,0x5604,0x5605,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_87[256] = {
+static const wchar_t c2u_87[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -265,7 +265,7 @@ static wchar_t c2u_87[256] = {
0x570B,0x570C,0x570D,0x570E,0x570F,0x5710,0x5711,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_88[256] = {
+static const wchar_t c2u_88[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -301,7 +301,7 @@ static wchar_t c2u_88[256] = {
0x5837,0x5838,0x5839,0x583A,0x583B,0x583C,0x583D,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_89[256] = {
+static const wchar_t c2u_89[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -337,7 +337,7 @@ static wchar_t c2u_89[256] = {
0x592C,0x5930,0x5932,0x5933,0x5935,0x5936,0x593B,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_8A[256] = {
+static const wchar_t c2u_8A[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -373,7 +373,7 @@ static wchar_t c2u_8A[256] = {
0x5A59,0x5A5B,0x5A5C,0x5A5D,0x5A5E,0x5A5F,0x5A60,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_8B[256] = {
+static const wchar_t c2u_8B[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -409,7 +409,7 @@ static wchar_t c2u_8B[256] = {
0x5B41,0x5B42,0x5B43,0x5B44,0x5B45,0x5B46,0x5B47,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_8C[256] = {
+static const wchar_t c2u_8C[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -445,7 +445,7 @@ static wchar_t c2u_8C[256] = {
0x5CA0,0x5CA1,0x5CA4,0x5CA5,0x5CA6,0x5CA7,0x5CA8,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_8D[256] = {
+static const wchar_t c2u_8D[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -481,7 +481,7 @@ static wchar_t c2u_8D[256] = {
0x5D98,0x5D9A,0x5D9B,0x5D9C,0x5D9E,0x5D9F,0x5DA0,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_8E[256] = {
+static const wchar_t c2u_8E[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -517,7 +517,7 @@ static wchar_t c2u_8E[256] = {
0x5EBF,0x5EC0,0x5EC1,0x5EC2,0x5EC3,0x5EC4,0x5EC5,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_8F[256] = {
+static const wchar_t c2u_8F[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -553,7 +553,7 @@ static wchar_t c2u_8F[256] = {
0x5FF4,0x5FF6,0x5FF7,0x5FF9,0x5FFA,0x5FFC,0x6007,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_90[256] = {
+static const wchar_t c2u_90[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -589,7 +589,7 @@ static wchar_t c2u_90[256] = {
0x6140,0x6141,0x6142,0x6143,0x6144,0x6145,0x6146,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_91[256] = {
+static const wchar_t c2u_91[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -625,7 +625,7 @@ static wchar_t c2u_91[256] = {
0x623B,0x623C,0x6242,0x6244,0x6245,0x6246,0x624A,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_92[256] = {
+static const wchar_t c2u_92[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -661,7 +661,7 @@ static wchar_t c2u_92[256] = {
0x63B5,0x63B6,0x63B9,0x63BB,0x63BD,0x63BF,0x63C0,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_93[256] = {
+static const wchar_t c2u_93[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -697,7 +697,7 @@ static wchar_t c2u_93[256] = {
0x64D1,0x64D3,0x64D4,0x64D5,0x64D6,0x64D9,0x64DA,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_94[256] = {
+static const wchar_t c2u_94[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -733,7 +733,7 @@ static wchar_t c2u_94[256] = {
0x65DE,0x65DF,0x65E1,0x65E3,0x65E4,0x65EA,0x65EB,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_95[256] = {
+static const wchar_t c2u_95[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -769,7 +769,7 @@ static wchar_t c2u_95[256] = {
0x66F8,0x66FA,0x66FB,0x66FD,0x6701,0x6702,0x6703,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_96[256] = {
+static const wchar_t c2u_96[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -805,7 +805,7 @@ static wchar_t c2u_96[256] = {
0x6852,0x6856,0x6857,0x6858,0x6859,0x685A,0x685B,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_97[256] = {
+static const wchar_t c2u_97[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -841,7 +841,7 @@ static wchar_t c2u_97[256] = {
0x6955,0x6956,0x6958,0x6959,0x695B,0x695C,0x695F,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_98[256] = {
+static const wchar_t c2u_98[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -877,7 +877,7 @@ static wchar_t c2u_98[256] = {
0x6A52,0x6A53,0x6A54,0x6A55,0x6A56,0x6A57,0x6A5A,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_99[256] = {
+static const wchar_t c2u_99[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -913,7 +913,7 @@ static wchar_t c2u_99[256] = {
0x6B28,0x6B29,0x6B2A,0x6B2B,0x6B2C,0x6B2D,0x6B2E,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_9A[256] = {
+static const wchar_t c2u_9A[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -949,7 +949,7 @@ static wchar_t c2u_9A[256] = {
0x6C4E,0x6C4F,0x6C51,0x6C52,0x6C53,0x6C56,0x6C58,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_9B[256] = {
+static const wchar_t c2u_9B[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -985,7 +985,7 @@ static wchar_t c2u_9B[256] = {
0x6DBE,0x6DC1,0x6DC2,0x6DC3,0x6DC8,0x6DC9,0x6DCA,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_9C[256] = {
+static const wchar_t c2u_9C[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1021,7 +1021,7 @@ static wchar_t c2u_9C[256] = {
0x6EE7,0x6EEA,0x6EEB,0x6EEC,0x6EED,0x6EEE,0x6EEF,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_9D[256] = {
+static const wchar_t c2u_9D[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1057,7 +1057,7 @@ static wchar_t c2u_9D[256] = {
0x6FDC,0x6FDD,0x6FDF,0x6FE2,0x6FE3,0x6FE4,0x6FE5,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_9E[256] = {
+static const wchar_t c2u_9E[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1093,7 +1093,7 @@ static wchar_t c2u_9E[256] = {
0x70D2,0x70D3,0x70D4,0x70D5,0x70D6,0x70D7,0x70DA,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_9F[256] = {
+static const wchar_t c2u_9F[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1129,7 +1129,7 @@ static wchar_t c2u_9F[256] = {
0x71CC,0x71CD,0x71CF,0x71D0,0x71D1,0x71D2,0x71D3,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_A0[256] = {
+static const wchar_t c2u_A0[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1165,7 +1165,7 @@ static wchar_t c2u_A0[256] = {
0x72D3,0x72D4,0x72D5,0x72D6,0x72D8,0x72DA,0x72DB,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_A1[256] = {
+static const wchar_t c2u_A1[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1201,7 +1201,7 @@ static wchar_t c2u_A1[256] = {
0x25B2,0x203B,0x2192,0x2190,0x2191,0x2193,0x3013,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_A2[256] = {
+static const wchar_t c2u_A2[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1237,7 +1237,7 @@ static wchar_t c2u_A2[256] = {
0x2167,0x2168,0x2169,0x216A,0x216B,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_A3[256] = {
+static const wchar_t c2u_A3[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1273,7 +1273,7 @@ static wchar_t c2u_A3[256] = {
0xFF58,0xFF59,0xFF5A,0xFF5B,0xFF5C,0xFF5D,0xFFE3,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_A4[256] = {
+static const wchar_t c2u_A4[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1308,7 +1308,7 @@ static wchar_t c2u_A4[256] = {
0x3090,0x3091,0x3092,0x3093,0x0000,0x0000,0x0000,0x0000,/* 0xF0-0xF7 */
};
-static wchar_t c2u_A5[256] = {
+static const wchar_t c2u_A5[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1343,7 +1343,7 @@ static wchar_t c2u_A5[256] = {
0x30F0,0x30F1,0x30F2,0x30F3,0x30F4,0x30F5,0x30F6,0x0000,/* 0xF0-0xF7 */
};
-static wchar_t c2u_A6[256] = {
+static const wchar_t c2u_A6[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1378,7 +1378,7 @@ static wchar_t c2u_A6[256] = {
0xFE37,0xFE38,0xFE31,0x0000,0xFE33,0xFE34,0x0000,0x0000,/* 0xF0-0xF7 */
};
-static wchar_t c2u_A7[256] = {
+static const wchar_t c2u_A7[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1413,7 +1413,7 @@ static wchar_t c2u_A7[256] = {
0x044E,0x044F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0xF0-0xF7 */
};
-static wchar_t c2u_A8[256] = {
+static const wchar_t c2u_A8[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1447,7 +1447,7 @@ static wchar_t c2u_A8[256] = {
0x3128,0x3129,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0xE8-0xEF */
};
-static wchar_t c2u_A9[256] = {
+static const wchar_t c2u_A9[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1481,7 +1481,7 @@ static wchar_t c2u_A9[256] = {
0x2544,0x2545,0x2546,0x2547,0x2548,0x2549,0x254A,0x254B,/* 0xE8-0xEF */
};
-static wchar_t c2u_AA[256] = {
+static const wchar_t c2u_AA[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1506,7 +1506,7 @@ static wchar_t c2u_AA[256] = {
0x7371,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0xA0-0xA7 */
};
-static wchar_t c2u_AB[256] = {
+static const wchar_t c2u_AB[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1531,7 +1531,7 @@ static wchar_t c2u_AB[256] = {
0x73F7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0xA0-0xA7 */
};
-static wchar_t c2u_AC[256] = {
+static const wchar_t c2u_AC[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1556,7 +1556,7 @@ static wchar_t c2u_AC[256] = {
0x747A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0xA0-0xA7 */
};
-static wchar_t c2u_AD[256] = {
+static const wchar_t c2u_AD[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1581,7 +1581,7 @@ static wchar_t c2u_AD[256] = {
0x74F2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0xA0-0xA7 */
};
-static wchar_t c2u_AE[256] = {
+static const wchar_t c2u_AE[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1606,7 +1606,7 @@ static wchar_t c2u_AE[256] = {
0x7587,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0xA0-0xA7 */
};
-static wchar_t c2u_AF[256] = {
+static const wchar_t c2u_AF[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1631,7 +1631,7 @@ static wchar_t c2u_AF[256] = {
0x7644,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0xA0-0xA7 */
};
-static wchar_t c2u_B0[256] = {
+static const wchar_t c2u_B0[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1667,7 +1667,7 @@ static wchar_t c2u_B0[256] = {
0x508D,0x8C24,0x82DE,0x80DE,0x5305,0x8912,0x5265,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_B1[256] = {
+static const wchar_t c2u_B1[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1703,7 +1703,7 @@ static wchar_t c2u_B1[256] = {
0x5175,0x51B0,0x67C4,0x4E19,0x79C9,0x997C,0x70B3,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_B2[256] = {
+static const wchar_t c2u_B2[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1739,7 +1739,7 @@ static wchar_t c2u_B2[256] = {
0x7F20,0x94F2,0x4EA7,0x9610,0x98A4,0x660C,0x7316,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_B3[256] = {
+static const wchar_t c2u_B3[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1775,7 +1775,7 @@ static wchar_t c2u_B3[256] = {
0x53A8,0x8E87,0x9504,0x96CF,0x6EC1,0x9664,0x695A,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_B4[256] = {
+static const wchar_t c2u_B4[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1811,7 +1811,7 @@ static wchar_t c2u_B4[256] = {
0x5E26,0x6B86,0x4EE3,0x8D37,0x888B,0x5F85,0x902E,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_B5[256] = {
+static const wchar_t c2u_B5[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1847,7 +1847,7 @@ static wchar_t c2u_B5[256] = {
0x8DCC,0x7239,0x789F,0x8776,0x8FED,0x8C0D,0x53E0,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_B6[256] = {
+static const wchar_t c2u_B6[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1883,7 +1883,7 @@ static wchar_t c2u_B6[256] = {
0x800C,0x513F,0x8033,0x5C14,0x9975,0x6D31,0x4E8C,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_B7[256] = {
+static const wchar_t c2u_B7[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1919,7 +1919,7 @@ static wchar_t c2u_B7[256] = {
0x8F90,0x5E45,0x6C1F,0x7B26,0x4F0F,0x4FD8,0x670D,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_B8[256] = {
+static const wchar_t c2u_B8[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1955,7 +1955,7 @@ static wchar_t c2u_B8[256] = {
0x7ED9,0x6839,0x8DDF,0x8015,0x66F4,0x5E9A,0x7FB9,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_B9[256] = {
+static const wchar_t c2u_B9[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1991,7 +1991,7 @@ static wchar_t c2u_B9[256] = {
0x9505,0x90ED,0x56FD,0x679C,0x88F9,0x8FC7,0x54C8,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_BA[256] = {
+static const wchar_t c2u_BA[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2027,7 +2027,7 @@ static wchar_t c2u_BA[256] = {
0x58F6,0x846B,0x80E1,0x8774,0x72D0,0x7CCA,0x6E56,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_BB[256] = {
+static const wchar_t c2u_BB[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2063,7 +2063,7 @@ static wchar_t c2u_BB[256] = {
0x573E,0x57FA,0x673A,0x7578,0x7A3D,0x79EF,0x7B95,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_BC[256] = {
+static const wchar_t c2u_BC[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2099,7 +2099,7 @@ static wchar_t c2u_BC[256] = {
0x9274,0x8DF5,0x8D31,0x89C1,0x952E,0x7BAD,0x4EF6,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_BD[256] = {
+static const wchar_t c2u_BD[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2135,7 +2135,7 @@ static wchar_t c2u_BD[256] = {
0x8FDB,0x9773,0x664B,0x7981,0x8FD1,0x70EC,0x6D78,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_BE[256] = {
+static const wchar_t c2u_BE[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2171,7 +2171,7 @@ static wchar_t c2u_BE[256] = {
0x7EDD,0x5747,0x83CC,0x94A7,0x519B,0x541B,0x5CFB,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_BF[256] = {
+static const wchar_t c2u_BF[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2207,7 +2207,7 @@ static wchar_t c2u_BF[256] = {
0x76D4,0x5CBF,0x7AA5,0x8475,0x594E,0x9B41,0x5080,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_C0[256] = {
+static const wchar_t c2u_C0[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2243,7 +2243,7 @@ static wchar_t c2u_C0[256] = {
0x52B1,0x783E,0x5386,0x5229,0x5088,0x4F8B,0x4FD0,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_C1[256] = {
+static const wchar_t c2u_C1[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2279,7 +2279,7 @@ static wchar_t c2u_C1[256] = {
0x67F3,0x516D,0x9F99,0x804B,0x5499,0x7B3C,0x7ABF,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_C2[256] = {
+static const wchar_t c2u_C2[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2315,7 +2315,7 @@ static wchar_t c2u_C2[256] = {
0x9992,0x86EE,0x6EE1,0x8513,0x66FC,0x6162,0x6F2B,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_C3[256] = {
+static const wchar_t c2u_C3[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2351,7 +2351,7 @@ static wchar_t c2u_C3[256] = {
0x879F,0x9E23,0x94ED,0x540D,0x547D,0x8C2C,0x6478,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_C4[256] = {
+static const wchar_t c2u_C4[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2387,7 +2387,7 @@ static wchar_t c2u_C4[256] = {
0x954D,0x6D85,0x60A8,0x67E0,0x72DE,0x51DD,0x5B81,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_C5[256] = {
+static const wchar_t c2u_C5[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2423,7 +2423,7 @@ static wchar_t c2u_C5[256] = {
0x7812,0x9739,0x6279,0x62AB,0x5288,0x7435,0x6BD7,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_C6[256] = {
+static const wchar_t c2u_C6[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2459,7 +2459,7 @@ static wchar_t c2u_C6[256] = {
0x6C14,0x8FC4,0x5F03,0x6C7D,0x6CE3,0x8BAB,0x6390,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_C7[256] = {
+static const wchar_t c2u_C7[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2495,7 +2495,7 @@ static wchar_t c2u_C7[256] = {
0x533A,0x86C6,0x66F2,0x8EAF,0x5C48,0x9A71,0x6E20,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_C8[256] = {
+static const wchar_t c2u_C8[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2531,7 +2531,7 @@ static wchar_t c2u_C8[256] = {
0x8428,0x816E,0x9CC3,0x585E,0x8D5B,0x4E09,0x53C1,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_C9[256] = {
+static const wchar_t c2u_C9[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2567,7 +2567,7 @@ static wchar_t c2u_C9[256] = {
0x6E17,0x58F0,0x751F,0x7525,0x7272,0x5347,0x7EF3,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_CA[256] = {
+static const wchar_t c2u_CA[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2603,7 +2603,7 @@ static wchar_t c2u_CA[256] = {
0x675F,0x620D,0x7AD6,0x5885,0x5EB6,0x6570,0x6F31,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_CB[256] = {
+static const wchar_t c2u_CB[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2639,7 +2639,7 @@ static wchar_t c2u_CB[256] = {
0x9501,0x6240,0x584C,0x4ED6,0x5B83,0x5979,0x5854,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_CC[256] = {
+static const wchar_t c2u_CC[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2675,7 +2675,7 @@ static wchar_t c2u_CC[256] = {
0x8DF3,0x8D34,0x94C1,0x5E16,0x5385,0x542C,0x70C3,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_CD[256] = {
+static const wchar_t c2u_CD[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2711,7 +2711,7 @@ static wchar_t c2u_CD[256] = {
0x7F51,0x5F80,0x65FA,0x671B,0x5FD8,0x5984,0x5A01,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_CE[256] = {
+static const wchar_t c2u_CE[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2747,7 +2747,7 @@ static wchar_t c2u_CE[256] = {
0x7852,0x77FD,0x6670,0x563B,0x5438,0x9521,0x727A,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_CF[256] = {
+static const wchar_t c2u_CF[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2783,7 +2783,7 @@ static wchar_t c2u_CF[256] = {
0x54EE,0x56A3,0x9500,0x6D88,0x5BB5,0x6DC6,0x6653,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_D0[256] = {
+static const wchar_t c2u_D0[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2819,7 +2819,7 @@ static wchar_t c2u_D0[256] = {
0x7EED,0x8F69,0x55A7,0x5BA3,0x60AC,0x65CB,0x7384,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_D1[256] = {
+static const wchar_t c2u_D1[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2855,7 +2855,7 @@ static wchar_t c2u_D1[256] = {
0x517B,0x6837,0x6F3E,0x9080,0x8170,0x5996,0x7476,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_D2[256] = {
+static const wchar_t c2u_D2[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2891,7 +2891,7 @@ static wchar_t c2u_D2[256] = {
0x94F6,0x6DEB,0x5BC5,0x996E,0x5C39,0x5F15,0x9690,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_D3[256] = {
+static const wchar_t c2u_D3[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2927,7 +2927,7 @@ static wchar_t c2u_D3[256] = {
0x5CEA,0x5FA1,0x6108,0x6B32,0x72F1,0x80B2,0x8A89,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_D4[256] = {
+static const wchar_t c2u_D4[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2963,7 +2963,7 @@ static wchar_t c2u_D4[256] = {
0x66FE,0x8D60,0x624E,0x55B3,0x6E23,0x672D,0x8F67,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_D5[256] = {
+static const wchar_t c2u_D5[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2999,7 +2999,7 @@ static wchar_t c2u_D5[256] = {
0x72F0,0x4E89,0x6014,0x6574,0x62EF,0x6B63,0x653F,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_D6[256] = {
+static const wchar_t c2u_D6[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3035,7 +3035,7 @@ static wchar_t c2u_D6[256] = {
0x8457,0x67F1,0x52A9,0x86C0,0x8D2E,0x94F8,0x7B51,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_D7[256] = {
+static const wchar_t c2u_D7[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3071,7 +3071,7 @@ static wchar_t c2u_D7[256] = {
0x5750,0x5EA7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_D8[256] = {
+static const wchar_t c2u_D8[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3107,7 +3107,7 @@ static wchar_t c2u_D8[256] = {
0x4F09,0x4F2B,0x4F5E,0x4F67,0x6538,0x4F5A,0x4F5D,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_D9[256] = {
+static const wchar_t c2u_D9[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3143,7 +3143,7 @@ static wchar_t c2u_D9[256] = {
0x5B34,0x8803,0x7FB8,0x51AB,0x51B1,0x51BD,0x51BC,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_DA[256] = {
+static const wchar_t c2u_DA[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3179,7 +3179,7 @@ static wchar_t c2u_DA[256] = {
0x9099,0x90AC,0x90A1,0x90B4,0x90B3,0x90B6,0x90BA,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_DB[256] = {
+static const wchar_t c2u_DB[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3215,7 +3215,7 @@ static wchar_t c2u_DB[256] = {
0x57D2,0x57B8,0x57F4,0x57EF,0x57F8,0x57E4,0x57DD,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_DC[256] = {
+static const wchar_t c2u_DC[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3251,7 +3251,7 @@ static wchar_t c2u_DC[256] = {
0x8317,0x8360,0x832D,0x833A,0x8333,0x8366,0x8365,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_DD[256] = {
+static const wchar_t c2u_DD[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3287,7 +3287,7 @@ static wchar_t c2u_DD[256] = {
0x850C,0x750D,0x8538,0x84F0,0x8539,0x851F,0x853A,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_DE[256] = {
+static const wchar_t c2u_DE[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3323,7 +3323,7 @@ static wchar_t c2u_DE[256] = {
0x640C,0x6426,0x6421,0x645E,0x6484,0x646D,0x6496,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_DF[256] = {
+static const wchar_t c2u_DF[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3359,7 +3359,7 @@ static wchar_t c2u_DF[256] = {
0x5549,0x556D,0x5541,0x5555,0x553F,0x5550,0x553C,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E0[256] = {
+static const wchar_t c2u_E0[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3395,7 +3395,7 @@ static wchar_t c2u_E0[256] = {
0x5E0F,0x5E19,0x5E14,0x5E11,0x5E31,0x5E3B,0x5E3C,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E1[256] = {
+static const wchar_t c2u_E1[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3431,7 +3431,7 @@ static wchar_t c2u_E1[256] = {
0x72F2,0x72F4,0x72F7,0x7301,0x72F3,0x7303,0x72FA,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E2[256] = {
+static const wchar_t c2u_E2[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3467,7 +3467,7 @@ static wchar_t c2u_E2[256] = {
0x603F,0x6021,0x6078,0x6079,0x607B,0x607A,0x6042,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E3[256] = {
+static const wchar_t c2u_E3[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3503,7 +3503,7 @@ static wchar_t c2u_E3[256] = {
0x6CFA,0x6CEB,0x6CEE,0x6CB1,0x6CD3,0x6CEF,0x6CFE,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E4[256] = {
+static const wchar_t c2u_E4[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3539,7 +3539,7 @@ static wchar_t c2u_E4[256] = {
0x6F8D,0x6F8C,0x6F78,0x6F72,0x6F7C,0x6F7A,0x6FD1,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E5[256] = {
+static const wchar_t c2u_E5[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3575,7 +3575,7 @@ static wchar_t c2u_E5[256] = {
0x5C6E,0x5981,0x5983,0x598D,0x59A9,0x59AA,0x59A3,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E6[256] = {
+static const wchar_t c2u_E6[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3611,7 +3611,7 @@ static wchar_t c2u_E6[256] = {
0x9AA7,0x7E9F,0x7EA1,0x7EA3,0x7EA5,0x7EA8,0x7EA9,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E7[256] = {
+static const wchar_t c2u_E7[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3647,7 +3647,7 @@ static wchar_t c2u_E7[256] = {
0x745B,0x7426,0x7425,0x7428,0x7430,0x742E,0x742C,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E8[256] = {
+static const wchar_t c2u_E8[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3683,7 +3683,7 @@ static wchar_t c2u_E8[256] = {
0x686B,0x68C2,0x696E,0x68FC,0x691F,0x6920,0x68F9,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E9[256] = {
+static const wchar_t c2u_E9[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3719,7 +3719,7 @@ static wchar_t c2u_E9[256] = {
0x8F7C,0x8F7E,0x8F81,0x8F82,0x8F84,0x8F87,0x8F8B,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_EA[256] = {
+static const wchar_t c2u_EA[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3755,7 +3755,7 @@ static wchar_t c2u_EA[256] = {
0x728B,0x728D,0x728F,0x7292,0x6308,0x6332,0x63B0,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_EB[256] = {
+static const wchar_t c2u_EB[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3791,7 +3791,7 @@ static wchar_t c2u_EB[256] = {
0x6ED5,0x81A3,0x81AA,0x81CC,0x6726,0x81CA,0x81BB,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_EC[256] = {
+static const wchar_t c2u_EC[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3827,7 +3827,7 @@ static wchar_t c2u_EC[256] = {
0x7985,0x798A,0x799A,0x79A7,0x79B3,0x5FD1,0x5FD0,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_ED[256] = {
+static const wchar_t c2u_ED[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3863,7 +3863,7 @@ static wchar_t c2u_ED[256] = {
0x7738,0x7750,0x7751,0x7747,0x7743,0x775A,0x7768,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_EE[256] = {
+static const wchar_t c2u_EE[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3899,7 +3899,7 @@ static wchar_t c2u_EE[256] = {
0x94E0,0x94E2,0x94E4,0x94E5,0x94E7,0x94E8,0x94EA,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_EF[256] = {
+static const wchar_t c2u_EF[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3935,7 +3935,7 @@ static wchar_t c2u_EF[256] = {
0x79EB,0x7A06,0x5D47,0x7A03,0x7A02,0x7A1E,0x7A14,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_F0[256] = {
+static const wchar_t c2u_F0[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3971,7 +3971,7 @@ static wchar_t c2u_F0[256] = {
0x760C,0x7617,0x760A,0x7625,0x7618,0x7615,0x7619,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_F1[256] = {
+static const wchar_t c2u_F1[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -4007,7 +4007,7 @@ static wchar_t c2u_F1[256] = {
0x8052,0x8069,0x8071,0x8983,0x9878,0x9880,0x9883,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_F2[256] = {
+static const wchar_t c2u_F2[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -4043,7 +4043,7 @@ static wchar_t c2u_F2[256] = {
0x8764,0x8759,0x8765,0x8793,0x87AF,0x87A8,0x87D2,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_F3[256] = {
+static const wchar_t c2u_F3[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -4079,7 +4079,7 @@ static wchar_t c2u_F3[256] = {
0x7BEA,0x7C0C,0x7BFE,0x7BFC,0x7C0F,0x7C16,0x7C0B,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_F4[256] = {
+static const wchar_t c2u_F4[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -4115,7 +4115,7 @@ static wchar_t c2u_F4[256] = {
0x8C47,0x8C49,0x914A,0x9150,0x914E,0x914F,0x9164,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_F5[256] = {
+static const wchar_t c2u_F5[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -4151,7 +4151,7 @@ static wchar_t c2u_F5[256] = {
0x8C98,0x8C94,0x659B,0x89D6,0x89DE,0x89DA,0x89DC,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_F6[256] = {
+static const wchar_t c2u_F6[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -4187,7 +4187,7 @@ static wchar_t c2u_F6[256] = {
0x9CBD,0x9CC4,0x9CC5,0x9CC6,0x9CC7,0x9CCA,0x9CCB,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_F7[256] = {
+static const wchar_t c2u_F7[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -4223,7 +4223,7 @@ static wchar_t c2u_F7[256] = {
0x9F2C,0x9F2F,0x9F39,0x9F37,0x9F3D,0x9F3E,0x9F44,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_F8[256] = {
+static const wchar_t c2u_F8[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -4248,7 +4248,7 @@ static wchar_t c2u_F8[256] = {
0x9D42,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0xA0-0xA7 */
};
-static wchar_t c2u_F9[256] = {
+static const wchar_t c2u_F9[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -4273,7 +4273,7 @@ static wchar_t c2u_F9[256] = {
0x9DA2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0xA0-0xA7 */
};
-static wchar_t c2u_FA[256] = {
+static const wchar_t c2u_FA[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -4298,7 +4298,7 @@ static wchar_t c2u_FA[256] = {
0x9E02,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0xA0-0xA7 */
};
-static wchar_t c2u_FB[256] = {
+static const wchar_t c2u_FB[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -4323,7 +4323,7 @@ static wchar_t c2u_FB[256] = {
0x9EAA,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0xA0-0xA7 */
};
-static wchar_t c2u_FC[256] = {
+static const wchar_t c2u_FC[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -4348,7 +4348,7 @@ static wchar_t c2u_FC[256] = {
0x9F31,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0xA0-0xA7 */
};
-static wchar_t c2u_FD[256] = {
+static const wchar_t c2u_FD[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -4373,7 +4373,7 @@ static wchar_t c2u_FD[256] = {
0xF9F1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0xA0-0xA7 */
};
-static wchar_t c2u_FE[256] = {
+static const wchar_t c2u_FE[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -4386,7 +4386,7 @@ static wchar_t c2u_FE[256] = {
0xFA1F,0xFA20,0xFA21,0xFA23,0xFA24,0xFA27,0xFA28,0xFA29,/* 0x48-0x4F */
};
-static wchar_t *page_charset2uni[256] = {
+static const wchar_t *page_charset2uni[256] = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -4421,7 +4421,7 @@ static wchar_t *page_charset2uni[256] = {
c2u_F8, c2u_F9, c2u_FA, c2u_FB, c2u_FC, c2u_FD, c2u_FE, NULL,
};
-static unsigned char u2c_00[512] = {
+static const unsigned char u2c_00[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -4488,7 +4488,7 @@ static unsigned char u2c_00[512] = {
0xA8, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_01[512] = {
+static const unsigned char u2c_01[512] = {
0xA8, 0xA1, 0xA8, 0xA1, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -4548,7 +4548,7 @@ static unsigned char u2c_01[512] = {
0xA8, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xDC-0xDF */
};
-static unsigned char u2c_02[512] = {
+static const unsigned char u2c_02[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -4607,7 +4607,7 @@ static unsigned char u2c_02[512] = {
0x00, 0x00, 0xA8, 0x42, 0x00, 0x00, 0x00, 0x00, /* 0xD8-0xDB */
};
-static unsigned char u2c_03[512] = {
+static const unsigned char u2c_03[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -4662,7 +4662,7 @@ static unsigned char u2c_03[512] = {
0xA6, 0xD7, 0xA6, 0xD8, 0x00, 0x00, 0x00, 0x00, /* 0xC8-0xCB */
};
-static unsigned char u2c_04[512] = {
+static const unsigned char u2c_04[512] = {
0x00, 0x00, 0xA7, 0xA7, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -4686,7 +4686,7 @@ static unsigned char u2c_04[512] = {
0x00, 0x00, 0xA7, 0xD7, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x53 */
};
-static unsigned char u2c_20[512] = {
+static const unsigned char u2c_20[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -4705,7 +4705,7 @@ static unsigned char u2c_20[512] = {
0x00, 0x00, 0x00, 0x00, 0xA3, 0xFE, 0x00, 0x00, /* 0x3C-0x3F */
};
-static unsigned char u2c_21[512] = {
+static const unsigned char u2c_21[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xE6, /* 0x00-0x03 */
0x00, 0x00, 0xA8, 0x47, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0xA8, 0x48, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -4748,7 +4748,7 @@ static unsigned char u2c_21[512] = {
0xA8, 0x4B, 0xA8, 0x4C, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9B */
};
-static unsigned char u2c_22[512] = {
+static const unsigned char u2c_22[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0xA1, 0xCA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -4800,7 +4800,7 @@ static unsigned char u2c_22[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0x53, /* 0xBC-0xBF */
};
-static unsigned char u2c_23[512] = {
+static const unsigned char u2c_23[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -4808,7 +4808,7 @@ static unsigned char u2c_23[512] = {
0x00, 0x00, 0x00, 0x00, 0xA1, 0xD0, 0x00, 0x00, /* 0x10-0x13 */
};
-static unsigned char u2c_24[512] = {
+static const unsigned char u2c_24[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -4851,7 +4851,7 @@ static unsigned char u2c_24[512] = {
0xA2, 0xC1, 0xA2, 0xC2, 0xA2, 0xC3, 0xA2, 0xC4, /* 0x98-0x9B */
};
-static unsigned char u2c_25[512] = {
+static const unsigned char u2c_25[512] = {
0xA9, 0xA4, 0xA9, 0xA5, 0xA9, 0xA6, 0xA9, 0xA7, /* 0x00-0x03 */
0xA9, 0xA8, 0xA9, 0xA9, 0xA9, 0xAA, 0xA9, 0xAB, /* 0x04-0x07 */
0xA9, 0xAC, 0xA9, 0xAD, 0xA9, 0xAE, 0xA9, 0xAF, /* 0x08-0x0B */
@@ -4919,7 +4919,7 @@ static unsigned char u2c_25[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_26[512] = {
+static const unsigned char u2c_26[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0xA1, 0xEF, 0xA1, 0xEE, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0xA8, 0x91, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -4939,7 +4939,7 @@ static unsigned char u2c_26[512] = {
0xA1, 0xE2, 0x00, 0x00, 0xA1, 0xE1, 0x00, 0x00, /* 0x40-0x43 */
};
-static unsigned char u2c_30[512] = {
+static const unsigned char u2c_30[512] = {
0xA1, 0xA1, 0xA1, 0xA2, 0xA1, 0xA3, 0xA1, 0xA8, /* 0x00-0x03 */
0x00, 0x00, 0xA1, 0xA9, 0xA9, 0x65, 0xA9, 0x96, /* 0x04-0x07 */
0xA1, 0xB4, 0xA1, 0xB5, 0xA1, 0xB6, 0xA1, 0xB7, /* 0x08-0x0B */
@@ -5007,7 +5007,7 @@ static unsigned char u2c_30[512] = {
0xA9, 0x60, 0xA9, 0x63, 0xA9, 0x64, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_31[512] = {
+static const unsigned char u2c_31[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0xA8, 0xC5, 0xA8, 0xC6, 0xA8, 0xC7, /* 0x04-0x07 */
0xA8, 0xC8, 0xA8, 0xC9, 0xA8, 0xCA, 0xA8, 0xCB, /* 0x08-0x0B */
@@ -5051,7 +5051,7 @@ static unsigned char u2c_31[512] = {
0xB6, 0xA1, 0xCC, 0xEC, 0xB5, 0xD8, 0xC8, 0xCB, /* 0x9C-0x9F */
};
-static unsigned char u2c_32[512] = {
+static const unsigned char u2c_32[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -5100,7 +5100,7 @@ static unsigned char u2c_32[512] = {
0xD2, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xB0-0xB3 */
};
-static unsigned char u2c_33[512] = {
+static const unsigned char u2c_33[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -5158,7 +5158,7 @@ static unsigned char u2c_33[512] = {
0x00, 0x00, 0xA9, 0x54, 0x00, 0x00, 0x00, 0x00, /* 0xD4-0xD7 */
};
-static unsigned char u2c_4E[512] = {
+static const unsigned char u2c_4E[512] = {
0xD2, 0xBB, 0xB6, 0xA1, 0x81, 0x40, 0xC6, 0xDF, /* 0x00-0x03 */
0x81, 0x41, 0x81, 0x42, 0x81, 0x43, 0xCD, 0xF2, /* 0x04-0x07 */
0xD5, 0xC9, 0xC8, 0xFD, 0xC9, 0xCF, 0xCF, 0xC2, /* 0x08-0x0B */
@@ -5226,7 +5226,7 @@ static unsigned char u2c_4E[512] = {
0x81, 0xA9, 0xB7, 0xDD, 0x81, 0xAA, 0xB7, 0xC2, /* 0xFC-0xFF */
};
-static unsigned char u2c_4F[512] = {
+static const unsigned char u2c_4F[512] = {
0x81, 0xAB, 0xC6, 0xF3, 0x81, 0xAC, 0x81, 0xAD, /* 0x00-0x03 */
0x81, 0xAE, 0x81, 0xAF, 0x81, 0xB0, 0x81, 0xB1, /* 0x04-0x07 */
0x81, 0xB2, 0xD8, 0xF8, 0xD2, 0xC1, 0x81, 0xB3, /* 0x08-0x0B */
@@ -5294,7 +5294,7 @@ static unsigned char u2c_4F[512] = {
0x82, 0x71, 0x82, 0x72, 0xD9, 0xC2, 0x82, 0x73, /* 0xFC-0xFF */
};
-static unsigned char u2c_50[512] = {
+static const unsigned char u2c_50[512] = {
0x82, 0x74, 0x82, 0x75, 0x82, 0x76, 0x82, 0x77, /* 0x00-0x03 */
0x82, 0x78, 0x82, 0x79, 0x82, 0x7A, 0x82, 0x7B, /* 0x04-0x07 */
0x82, 0x7C, 0x82, 0x7D, 0x82, 0x7E, 0x82, 0x80, /* 0x08-0x0B */
@@ -5362,7 +5362,7 @@ static unsigned char u2c_50[512] = {
0x83, 0x74, 0x83, 0x75, 0x83, 0x76, 0x83, 0x77, /* 0xFC-0xFF */
};
-static unsigned char u2c_51[512] = {
+static const unsigned char u2c_51[512] = {
0x83, 0x78, 0x83, 0x79, 0x83, 0x7A, 0x83, 0x7B, /* 0x00-0x03 */
0x83, 0x7C, 0x83, 0x7D, 0xD9, 0xD3, 0xD9, 0xD8, /* 0x04-0x07 */
0x83, 0x7E, 0x83, 0x80, 0x83, 0x81, 0xD9, 0xD9, /* 0x08-0x0B */
@@ -5430,7 +5430,7 @@ static unsigned char u2c_51[512] = {
0xDB, 0xCA, 0xBA, 0xAF, 0x84, 0x54, 0xD4, 0xE4, /* 0xFC-0xFF */
};
-static unsigned char u2c_52[512] = {
+static const unsigned char u2c_52[512] = {
0xB5, 0xB6, 0xB5, 0xF3, 0xD8, 0xD6, 0xC8, 0xD0, /* 0x00-0x03 */
0x84, 0x55, 0x84, 0x56, 0xB7, 0xD6, 0xC7, 0xD0, /* 0x04-0x07 */
0xD8, 0xD7, 0x84, 0x57, 0xBF, 0xAF, 0x84, 0x58, /* 0x08-0x0B */
@@ -5498,7 +5498,7 @@ static unsigned char u2c_52[512] = {
0x84, 0xF3, 0x84, 0xF4, 0xB9, 0xB4, 0xCE, 0xF0, /* 0xFC-0xFF */
};
-static unsigned char u2c_53[512] = {
+static const unsigned char u2c_53[512] = {
0xD4, 0xC8, 0x84, 0xF5, 0x84, 0xF6, 0x84, 0xF7, /* 0x00-0x03 */
0x84, 0xF8, 0xB0, 0xFC, 0xB4, 0xD2, 0x84, 0xF9, /* 0x04-0x07 */
0xD0, 0xD9, 0x84, 0xFA, 0x84, 0xFB, 0x84, 0xFC, /* 0x08-0x0B */
@@ -5566,7 +5566,7 @@ static unsigned char u2c_53[512] = {
0xB5, 0xF0, 0xDF, 0xB4, 0x85, 0xB6, 0x85, 0xB7, /* 0xFC-0xFF */
};
-static unsigned char u2c_54[512] = {
+static const unsigned char u2c_54[512] = {
0x85, 0xB8, 0xD3, 0xF5, 0x85, 0xB9, 0xB3, 0xD4, /* 0x00-0x03 */
0xB8, 0xF7, 0x85, 0xBA, 0xDF, 0xBA, 0x85, 0xBB, /* 0x04-0x07 */
0xBA, 0xCF, 0xBC, 0xAA, 0xB5, 0xF5, 0x85, 0xBC, /* 0x08-0x0B */
@@ -5634,7 +5634,7 @@ static unsigned char u2c_54[512] = {
0xBA, 0xDF, 0xDF, 0xEC, 0x86, 0x64, 0xDB, 0xC1, /* 0xFC-0xFF */
};
-static unsigned char u2c_55[512] = {
+static const unsigned char u2c_55[512] = {
0x86, 0x65, 0xD1, 0xE4, 0x86, 0x66, 0x86, 0x67, /* 0x00-0x03 */
0x86, 0x68, 0x86, 0x69, 0xCB, 0xF4, 0xB4, 0xBD, /* 0x04-0x07 */
0x86, 0x6A, 0xB0, 0xA6, 0x86, 0x6B, 0x86, 0x6C, /* 0x08-0x0B */
@@ -5702,7 +5702,7 @@ static unsigned char u2c_55[512] = {
0x86, 0xF9, 0xCB, 0xD4, 0xE0, 0xD5, 0x86, 0xFA, /* 0xFC-0xFF */
};
-static unsigned char u2c_56[512] = {
+static const unsigned char u2c_56[512] = {
0xE0, 0xD6, 0xE0, 0xD2, 0x86, 0xFB, 0x86, 0xFC, /* 0x00-0x03 */
0x86, 0xFD, 0x86, 0xFE, 0x87, 0x40, 0x87, 0x41, /* 0x04-0x07 */
0xE0, 0xD0, 0xBC, 0xCE, 0x87, 0x42, 0x87, 0x43, /* 0x08-0x0B */
@@ -5770,7 +5770,7 @@ static unsigned char u2c_56[512] = {
0x87, 0xF2, 0xB9, 0xFA, 0xCD, 0xBC, 0xE0, 0xF3, /* 0xFC-0xFF */
};
-static unsigned char u2c_57[512] = {
+static const unsigned char u2c_57[512] = {
0x87, 0xF3, 0x87, 0xF4, 0x87, 0xF5, 0xC6, 0xD4, /* 0x00-0x03 */
0xE0, 0xF4, 0x87, 0xF6, 0xD4, 0xB2, 0x87, 0xF7, /* 0x04-0x07 */
0xC8, 0xA6, 0xE0, 0xF6, 0xE0, 0xF5, 0x87, 0xF8, /* 0x08-0x0B */
@@ -5838,7 +5838,7 @@ static unsigned char u2c_57[512] = {
0x88, 0xCE, 0xDC, 0xA3, 0x88, 0xCF, 0x88, 0xD0, /* 0xFC-0xFF */
};
-static unsigned char u2c_58[512] = {
+static const unsigned char u2c_58[512] = {
0xDC, 0xA5, 0x88, 0xD1, 0xCC, 0xC3, 0x88, 0xD2, /* 0x00-0x03 */
0x88, 0xD3, 0x88, 0xD4, 0xB6, 0xD1, 0xDD, 0xC0, /* 0x04-0x07 */
0x88, 0xD5, 0x88, 0xD6, 0x88, 0xD7, 0xDC, 0xA1, /* 0x08-0x0B */
@@ -5906,7 +5906,7 @@ static unsigned char u2c_58[512] = {
0x89, 0xDA, 0x89, 0xDB, 0x89, 0xDC, 0x89, 0xDD, /* 0xFC-0xFF */
};
-static unsigned char u2c_59[512] = {
+static const unsigned char u2c_59[512] = {
0x89, 0xDE, 0x89, 0xDF, 0xE2, 0xBA, 0x89, 0xE0, /* 0x00-0x03 */
0xB4, 0xA6, 0x89, 0xE1, 0x89, 0xE2, 0xB1, 0xB8, /* 0x04-0x07 */
0x89, 0xE3, 0x89, 0xE4, 0x89, 0xE5, 0x89, 0xE6, /* 0x08-0x0B */
@@ -5974,7 +5974,7 @@ static unsigned char u2c_59[512] = {
0x8A, 0xB8, 0x8A, 0xB9, 0x8A, 0xBA, 0xD7, 0xCB, /* 0xFC-0xFF */
};
-static unsigned char u2c_5A[512] = {
+static const unsigned char u2c_5A[512] = {
0x8A, 0xBB, 0xCD, 0xFE, 0x8A, 0xBC, 0xCD, 0xDE, /* 0x00-0x03 */
0xC2, 0xA6, 0xE6, 0xAB, 0xE6, 0xAC, 0xBD, 0xBF, /* 0x04-0x07 */
0xE6, 0xAE, 0xE6, 0xB3, 0x8A, 0xBD, 0x8A, 0xBE, /* 0x08-0x0B */
@@ -6042,7 +6042,7 @@ static unsigned char u2c_5A[512] = {
0x8B, 0xBA, 0x8B, 0xBB, 0x8B, 0xBC, 0x8B, 0xBD, /* 0xFC-0xFF */
};
-static unsigned char u2c_5B[512] = {
+static const unsigned char u2c_5B[512] = {
0x8B, 0xBE, 0x8B, 0xBF, 0x8B, 0xC0, 0x8B, 0xC1, /* 0x00-0x03 */
0x8B, 0xC2, 0x8B, 0xC3, 0x8B, 0xC4, 0x8B, 0xC5, /* 0x04-0x07 */
0x8B, 0xC6, 0xE6, 0xD2, 0x8B, 0xC7, 0x8B, 0xC8, /* 0x08-0x0B */
@@ -6110,7 +6110,7 @@ static unsigned char u2c_5B[512] = {
0xB5, 0xBC, 0x8C, 0x9C, 0x8C, 0x9D, 0xCA, 0xD9, /* 0xFC-0xFF */
};
-static unsigned char u2c_5C[512] = {
+static const unsigned char u2c_5C[512] = {
0x8C, 0x9E, 0xB7, 0xE2, 0x8C, 0x9F, 0x8C, 0xA0, /* 0x00-0x03 */
0xC9, 0xE4, 0x8C, 0xA1, 0xBD, 0xAB, 0x8C, 0xA2, /* 0x04-0x07 */
0x8C, 0xA3, 0xCE, 0xBE, 0xD7, 0xF0, 0x8C, 0xA4, /* 0x08-0x0B */
@@ -6178,7 +6178,7 @@ static unsigned char u2c_5C[512] = {
0x8D, 0x7A, 0x8D, 0x7B, 0x8D, 0x7C, 0x8D, 0x7D, /* 0xFC-0xFF */
};
-static unsigned char u2c_5D[512] = {
+static const unsigned char u2c_5D[512] = {
0x8D, 0x7E, 0x8D, 0x80, 0xE1, 0xC0, 0xE1, 0xC1, /* 0x00-0x03 */
0x8D, 0x81, 0x8D, 0x82, 0xE1, 0xC7, 0xB3, 0xE7, /* 0x04-0x07 */
0x8D, 0x83, 0x8D, 0x84, 0x8D, 0x85, 0x8D, 0x86, /* 0x08-0x0B */
@@ -6246,7 +6246,7 @@ static unsigned char u2c_5D[512] = {
0x8E, 0x87, 0xD9, 0xE3, 0xBD, 0xED, 0x8E, 0x88, /* 0xFC-0xFF */
};
-static unsigned char u2c_5E[512] = {
+static const unsigned char u2c_5E[512] = {
0x8E, 0x89, 0xB1, 0xD2, 0xCA, 0xD0, 0xB2, 0xBC, /* 0x00-0x03 */
0x8E, 0x8A, 0xCB, 0xA7, 0xB7, 0xAB, 0x8E, 0x8B, /* 0x04-0x07 */
0xCA, 0xA6, 0x8E, 0x8C, 0x8E, 0x8D, 0x8E, 0x8E, /* 0x08-0x0B */
@@ -6314,7 +6314,7 @@ static unsigned char u2c_5E[512] = {
0x8F, 0x69, 0x8F, 0x6A, 0xDE, 0xC3, 0xD8, 0xA5, /* 0xFC-0xFF */
};
-static unsigned char u2c_5F[512] = {
+static const unsigned char u2c_5F[512] = {
0xBF, 0xAA, 0xDB, 0xCD, 0xD2, 0xEC, 0xC6, 0xFA, /* 0x00-0x03 */
0xC5, 0xAA, 0x8F, 0x6B, 0x8F, 0x6C, 0x8F, 0x6D, /* 0x04-0x07 */
0xDE, 0xC4, 0x8F, 0x6E, 0xB1, 0xD7, 0xDF, 0xAE, /* 0x08-0x0B */
@@ -6382,7 +6382,7 @@ static unsigned char u2c_5F[512] = {
0x8F, 0xFD, 0xBA, 0xF6, 0xE2, 0xE9, 0xB7, 0xDE, /* 0xFC-0xFF */
};
-static unsigned char u2c_60[512] = {
+static const unsigned char u2c_60[512] = {
0xBB, 0xB3, 0xCC, 0xAC, 0xCB, 0xCB, 0xE2, 0xE4, /* 0x00-0x03 */
0xE2, 0xE6, 0xE2, 0xEA, 0xE2, 0xEB, 0x8F, 0xFE, /* 0x04-0x07 */
0x90, 0x40, 0x90, 0x41, 0xE2, 0xF7, 0x90, 0x42, /* 0x08-0x0B */
@@ -6450,7 +6450,7 @@ static unsigned char u2c_60[512] = {
0x90, 0xC6, 0x90, 0xC7, 0x90, 0xC8, 0x90, 0xC9, /* 0xFC-0xFF */
};
-static unsigned char u2c_61[512] = {
+static const unsigned char u2c_61[512] = {
0xE3, 0xB8, 0xB3, 0xEE, 0x90, 0xCA, 0x90, 0xCB, /* 0x00-0x03 */
0x90, 0xCC, 0x90, 0xCD, 0xED, 0xA9, 0x90, 0xCE, /* 0x04-0x07 */
0xD3, 0xFA, 0xD3, 0xE4, 0x90, 0xCF, 0x90, 0xD0, /* 0x08-0x0B */
@@ -6518,7 +6518,7 @@ static unsigned char u2c_61[512] = {
0x91, 0xD6, 0x91, 0xD7, 0x91, 0xD8, 0xDC, 0xB2, /* 0xFC-0xFF */
};
-static unsigned char u2c_62[512] = {
+static const unsigned char u2c_62[512] = {
0x91, 0xD9, 0x91, 0xDA, 0x91, 0xDB, 0x91, 0xDC, /* 0x00-0x03 */
0x91, 0xDD, 0x91, 0xDE, 0xED, 0xB0, 0x91, 0xDF, /* 0x04-0x07 */
0xB8, 0xEA, 0x91, 0xE0, 0xCE, 0xEC, 0xEA, 0xA7, /* 0x08-0x0B */
@@ -6586,7 +6586,7 @@ static unsigned char u2c_62[512] = {
0xC6, 0xB4, 0xD7, 0xA7, 0xCA, 0xB0, 0xC4, 0xC3, /* 0xFC-0xFF */
};
-static unsigned char u2c_63[512] = {
+static const unsigned char u2c_63[512] = {
0x92, 0x93, 0xB3, 0xD6, 0xB9, 0xD2, 0x92, 0x94, /* 0x00-0x03 */
0x92, 0x95, 0x92, 0x96, 0x92, 0x97, 0xD6, 0xB8, /* 0x04-0x07 */
0xEA, 0xFC, 0xB0, 0xB4, 0x92, 0x98, 0x92, 0x99, /* 0x08-0x0B */
@@ -6654,7 +6654,7 @@ static unsigned char u2c_63[512] = {
0x93, 0x67, 0xC0, 0xBF, 0x93, 0x68, 0xDE, 0xEC, /* 0xFC-0xFF */
};
-static unsigned char u2c_64[512] = {
+static const unsigned char u2c_64[512] = {
0xB2, 0xF3, 0xB8, 0xE9, 0xC2, 0xA7, 0x93, 0x69, /* 0x00-0x03 */
0x93, 0x6A, 0xBD, 0xC1, 0x93, 0x6B, 0x93, 0x6C, /* 0x04-0x07 */
0x93, 0x6D, 0x93, 0x6E, 0x93, 0x6F, 0xDE, 0xF5, /* 0x08-0x0B */
@@ -6722,7 +6722,7 @@ static unsigned char u2c_64[512] = {
0x94, 0x5D, 0x94, 0x5E, 0x94, 0x5F, 0x94, 0x60, /* 0xFC-0xFF */
};
-static unsigned char u2c_65[512] = {
+static const unsigned char u2c_65[512] = {
0xC5, 0xCA, 0x94, 0x61, 0x94, 0x62, 0x94, 0x63, /* 0x00-0x03 */
0x94, 0x64, 0x94, 0x65, 0x94, 0x66, 0x94, 0x67, /* 0x04-0x07 */
0x94, 0x68, 0xDF, 0xAB, 0x94, 0x69, 0x94, 0x6A, /* 0x08-0x0B */
@@ -6790,7 +6790,7 @@ static unsigned char u2c_65[512] = {
0x95, 0x47, 0x95, 0x48, 0x95, 0x49, 0x95, 0x4A, /* 0xFC-0xFF */
};
-static unsigned char u2c_66[512] = {
+static const unsigned char u2c_66[512] = {
0xEA, 0xC0, 0x95, 0x4B, 0xB0, 0xBA, 0xEA, 0xBE, /* 0x00-0x03 */
0x95, 0x4C, 0x95, 0x4D, 0xC0, 0xA5, 0x95, 0x4E, /* 0x04-0x07 */
0x95, 0x4F, 0x95, 0x50, 0xEA, 0xBB, 0x95, 0x51, /* 0x08-0x0B */
@@ -6858,7 +6858,7 @@ static unsigned char u2c_66[512] = {
0xC2, 0xFC, 0x95, 0xFB, 0xD4, 0xF8, 0xCC, 0xE6, /* 0xFC-0xFF */
};
-static unsigned char u2c_67[512] = {
+static const unsigned char u2c_67[512] = {
0xD7, 0xEE, 0x95, 0xFC, 0x95, 0xFD, 0x95, 0xFE, /* 0x00-0x03 */
0x96, 0x40, 0x96, 0x41, 0x96, 0x42, 0x96, 0x43, /* 0x04-0x07 */
0xD4, 0xC2, 0xD3, 0xD0, 0xEB, 0xC3, 0xC5, 0xF3, /* 0x08-0x0B */
@@ -6926,7 +6926,7 @@ static unsigned char u2c_67[512] = {
0x96, 0xCC, 0xE8, 0xDF, 0x96, 0xCD, 0xCA, 0xC1, /* 0xFC-0xFF */
};
-static unsigned char u2c_68[512] = {
+static const unsigned char u2c_68[512] = {
0xE8, 0xD9, 0x96, 0xCE, 0x96, 0xCF, 0x96, 0xD0, /* 0x00-0x03 */
0x96, 0xD1, 0xD5, 0xA4, 0x96, 0xD2, 0xB1, 0xEA, /* 0x04-0x07 */
0xD5, 0xBB, 0xE8, 0xCE, 0xE8, 0xD0, 0xB6, 0xB0, /* 0x08-0x0B */
@@ -6994,7 +6994,7 @@ static unsigned char u2c_68[512] = {
0xE8, 0xFB, 0x97, 0xB2, 0x97, 0xB3, 0x97, 0xB4, /* 0xFC-0xFF */
};
-static unsigned char u2c_69[512] = {
+static const unsigned char u2c_69[512] = {
0x97, 0xB5, 0xE9, 0xA4, 0x97, 0xB6, 0x97, 0xB7, /* 0x00-0x03 */
0x97, 0xB8, 0xD2, 0xCE, 0x97, 0xB9, 0x97, 0xBA, /* 0x04-0x07 */
0x97, 0xBB, 0x97, 0xBC, 0x97, 0xBD, 0xE9, 0xA3, /* 0x08-0x0B */
@@ -7062,7 +7062,7 @@ static unsigned char u2c_69[512] = {
0x98, 0xB3, 0xB2, 0xDB, 0x98, 0xB4, 0xE9, 0xC8, /* 0xFC-0xFF */
};
-static unsigned char u2c_6A[512] = {
+static const unsigned char u2c_6A[512] = {
0x98, 0xB5, 0x98, 0xB6, 0x98, 0xB7, 0x98, 0xB8, /* 0x00-0x03 */
0x98, 0xB9, 0x98, 0xBA, 0x98, 0xBB, 0x98, 0xBC, /* 0x04-0x07 */
0x98, 0xBD, 0x98, 0xBE, 0xB7, 0xAE, 0x98, 0xBF, /* 0x08-0x0B */
@@ -7130,7 +7130,7 @@ static unsigned char u2c_6A[512] = {
0x99, 0xD2, 0x99, 0xD3, 0x99, 0xD4, 0x99, 0xD5, /* 0xFC-0xFF */
};
-static unsigned char u2c_6B[512] = {
+static const unsigned char u2c_6B[512] = {
0x99, 0xD6, 0x99, 0xD7, 0x99, 0xD8, 0x99, 0xD9, /* 0x00-0x03 */
0x99, 0xDA, 0x99, 0xDB, 0x99, 0xDC, 0x99, 0xDD, /* 0x04-0x07 */
0x99, 0xDE, 0x99, 0xDF, 0x99, 0xE0, 0x99, 0xE1, /* 0x08-0x0B */
@@ -7198,7 +7198,7 @@ static unsigned char u2c_6B[512] = {
0x9A, 0xCE, 0xEB, 0xA6, 0x9A, 0xCF, 0x9A, 0xD0, /* 0xFC-0xFF */
};
-static unsigned char u2c_6C[512] = {
+static const unsigned char u2c_6C[512] = {
0x9A, 0xD1, 0x9A, 0xD2, 0x9A, 0xD3, 0x9A, 0xD4, /* 0x00-0x03 */
0x9A, 0xD5, 0xEB, 0xA9, 0xEB, 0xAB, 0xEB, 0xAA, /* 0x04-0x07 */
0x9A, 0xD6, 0x9A, 0xD7, 0x9A, 0xD8, 0x9A, 0xD9, /* 0x08-0x0B */
@@ -7266,7 +7266,7 @@ static unsigned char u2c_6C[512] = {
0xC6, 0xC3, 0xD4, 0xF3, 0xE3, 0xFE, 0x9B, 0x8E, /* 0xFC-0xFF */
};
-static unsigned char u2c_6D[512] = {
+static const unsigned char u2c_6D[512] = {
0x9B, 0x8F, 0xBD, 0xE0, 0x9B, 0x90, 0x9B, 0x91, /* 0x00-0x03 */
0xE4, 0xA7, 0x9B, 0x92, 0x9B, 0x93, 0xE4, 0xA6, /* 0x04-0x07 */
0x9B, 0x94, 0x9B, 0x95, 0x9B, 0x96, 0xD1, 0xF3, /* 0x08-0x0B */
@@ -7334,7 +7334,7 @@ static unsigned char u2c_6D[512] = {
0xED, 0xB5, 0x9C, 0x5D, 0x9C, 0x5E, 0x9C, 0x5F, /* 0xFC-0xFF */
};
-static unsigned char u2c_6E[512] = {
+static const unsigned char u2c_6E[512] = {
0x9C, 0x60, 0x9C, 0x61, 0x9C, 0x62, 0x9C, 0x63, /* 0x00-0x03 */
0x9C, 0x64, 0xC7, 0xE5, 0x9C, 0x65, 0x9C, 0x66, /* 0x04-0x07 */
0x9C, 0x67, 0x9C, 0x68, 0xD4, 0xA8, 0x9C, 0x69, /* 0x08-0x0B */
@@ -7402,7 +7402,7 @@ static unsigned char u2c_6E[512] = {
0x9D, 0x4A, 0x9D, 0x4B, 0x9D, 0x4C, 0x9D, 0x4D, /* 0xFC-0xFF */
};
-static unsigned char u2c_6F[512] = {
+static const unsigned char u2c_6F[512] = {
0x9D, 0x4E, 0x9D, 0x4F, 0xC6, 0xAF, 0x9D, 0x50, /* 0x00-0x03 */
0x9D, 0x51, 0x9D, 0x52, 0xC6, 0xE1, 0x9D, 0x53, /* 0x04-0x07 */
0x9D, 0x54, 0xE4, 0xF5, 0x9D, 0x55, 0x9D, 0x56, /* 0x08-0x0B */
@@ -7470,7 +7470,7 @@ static unsigned char u2c_6F[512] = {
0x9E, 0x54, 0x9E, 0x55, 0x9E, 0x56, 0x9E, 0x57, /* 0xFC-0xFF */
};
-static unsigned char u2c_70[512] = {
+static const unsigned char u2c_70[512] = {
0x9E, 0x58, 0x9E, 0x59, 0x9E, 0x5A, 0x9E, 0x5B, /* 0x00-0x03 */
0x9E, 0x5C, 0x9E, 0x5D, 0x9E, 0x5E, 0x9E, 0x5F, /* 0x04-0x07 */
0x9E, 0x60, 0x9E, 0x61, 0x9E, 0x62, 0x9E, 0x63, /* 0x08-0x0B */
@@ -7538,7 +7538,7 @@ static unsigned char u2c_70[512] = {
0x9F, 0x54, 0xB7, 0xE9, 0x9F, 0x55, 0x9F, 0x56, /* 0xFC-0xFF */
};
-static unsigned char u2c_71[512] = {
+static const unsigned char u2c_71[512] = {
0x9F, 0x57, 0x9F, 0x58, 0x9F, 0x59, 0x9F, 0x5A, /* 0x00-0x03 */
0x9F, 0x5B, 0x9F, 0x5C, 0x9F, 0x5D, 0x9F, 0x5E, /* 0x04-0x07 */
0x9F, 0x5F, 0xD1, 0xC9, 0xBA, 0xB8, 0x9F, 0x60, /* 0x08-0x0B */
@@ -7606,7 +7606,7 @@ static unsigned char u2c_71[512] = {
0xA0, 0x61, 0xA0, 0x62, 0xA0, 0x63, 0xA0, 0x64, /* 0xFC-0xFF */
};
-static unsigned char u2c_72[512] = {
+static const unsigned char u2c_72[512] = {
0xA0, 0x65, 0xA0, 0x66, 0xA0, 0x67, 0xA0, 0x68, /* 0x00-0x03 */
0xA0, 0x69, 0xA0, 0x6A, 0xB1, 0xAC, 0xA0, 0x6B, /* 0x04-0x07 */
0xA0, 0x6C, 0xA0, 0x6D, 0xA0, 0x6E, 0xA0, 0x6F, /* 0x08-0x0B */
@@ -7674,7 +7674,7 @@ static unsigned char u2c_72[512] = {
0xC0, 0xC7, 0xAA, 0x4E, 0xAA, 0x4F, 0xAA, 0x50, /* 0xFC-0xFF */
};
-static unsigned char u2c_73[512] = {
+static const unsigned char u2c_73[512] = {
0xAA, 0x51, 0xE1, 0xFB, 0xAA, 0x52, 0xE1, 0xFD, /* 0x00-0x03 */
0xAA, 0x53, 0xAA, 0x54, 0xAA, 0x55, 0xAA, 0x56, /* 0x04-0x07 */
0xAA, 0x57, 0xAA, 0x58, 0xE2, 0xA5, 0xAA, 0x59, /* 0x08-0x0B */
@@ -7742,7 +7742,7 @@ static unsigned char u2c_73[512] = {
0xAC, 0x44, 0xAC, 0x45, 0xAC, 0x46, 0xAC, 0x47, /* 0xFC-0xFF */
};
-static unsigned char u2c_74[512] = {
+static const unsigned char u2c_74[512] = {
0xAC, 0x48, 0xAC, 0x49, 0xAC, 0x4A, 0xC7, 0xF2, /* 0x00-0x03 */
0xAC, 0x4B, 0xC0, 0xC5, 0xC0, 0xED, 0xAC, 0x4C, /* 0x04-0x07 */
0xAC, 0x4D, 0xC1, 0xF0, 0xE7, 0xF0, 0xAC, 0x4E, /* 0x08-0x0B */
@@ -7810,7 +7810,7 @@ static unsigned char u2c_74[512] = {
0xAE, 0x46, 0xAE, 0x47, 0xAE, 0x48, 0xEA, 0xB3, /* 0xFC-0xFF */
};
-static unsigned char u2c_75[512] = {
+static const unsigned char u2c_75[512] = {
0xAE, 0x49, 0xAE, 0x4A, 0xAE, 0x4B, 0xAE, 0x4C, /* 0x00-0x03 */
0xD5, 0xE7, 0xAE, 0x4D, 0xAE, 0x4E, 0xAE, 0x4F, /* 0x04-0x07 */
0xAE, 0x50, 0xAE, 0x51, 0xAE, 0x52, 0xAE, 0x53, /* 0x08-0x0B */
@@ -7878,7 +7878,7 @@ static unsigned char u2c_75[512] = {
0xF0, 0xF3, 0xAF, 0x79, 0xAF, 0x7A, 0xF0, 0xF4, /* 0xFC-0xFF */
};
-static unsigned char u2c_76[512] = {
+static const unsigned char u2c_76[512] = {
0xF0, 0xF6, 0xB4, 0xE1, 0xAF, 0x7B, 0xF0, 0xF1, /* 0x00-0x03 */
0xAF, 0x7C, 0xF0, 0xF7, 0xAF, 0x7D, 0xAF, 0x7E, /* 0x04-0x07 */
0xAF, 0x80, 0xAF, 0x81, 0xF0, 0xFA, 0xAF, 0x82, /* 0x08-0x0B */
@@ -7946,7 +7946,7 @@ static unsigned char u2c_76[512] = {
0xC5, 0xCE, 0xB1, 0x60, 0xB6, 0xDC, 0xB1, 0x61, /* 0xFC-0xFF */
};
-static unsigned char u2c_77[512] = {
+static const unsigned char u2c_77[512] = {
0xB1, 0x62, 0xCA, 0xA1, 0xB1, 0x63, 0xB1, 0x64, /* 0x00-0x03 */
0xED, 0xED, 0xB1, 0x65, 0xB1, 0x66, 0xED, 0xF0, /* 0x04-0x07 */
0xED, 0xF1, 0xC3, 0xBC, 0xB1, 0x67, 0xBF, 0xB4, /* 0x08-0x0B */
@@ -8014,7 +8014,7 @@ static unsigned char u2c_77[512] = {
0xB3, 0x4D, 0xCE, 0xF9, 0xB7, 0xAF, 0xBF, 0xF3, /* 0xFC-0xFF */
};
-static unsigned char u2c_78[512] = {
+static const unsigned char u2c_78[512] = {
0xED, 0xB8, 0xC2, 0xEB, 0xC9, 0xB0, 0xB3, 0x4E, /* 0x00-0x03 */
0xB3, 0x4F, 0xB3, 0x50, 0xB3, 0x51, 0xB3, 0x52, /* 0x04-0x07 */
0xB3, 0x53, 0xED, 0xB9, 0xB3, 0x54, 0xB3, 0x55, /* 0x08-0x0B */
@@ -8082,7 +8082,7 @@ static unsigned char u2c_78[512] = {
0xB4, 0x92, 0xB4, 0x93, 0xB4, 0x94, 0xB4, 0x95, /* 0xFC-0xFF */
};
-static unsigned char u2c_79[512] = {
+static const unsigned char u2c_79[512] = {
0xB4, 0x96, 0xBD, 0xB8, 0xB4, 0x97, 0xB4, 0x98, /* 0x00-0x03 */
0xB4, 0x99, 0xED, 0xE2, 0xB4, 0x9A, 0xB4, 0x9B, /* 0x04-0x07 */
0xB4, 0x9C, 0xB4, 0x9D, 0xB4, 0x9E, 0xB4, 0x9F, /* 0x08-0x0B */
@@ -8150,7 +8150,7 @@ static unsigned char u2c_79[512] = {
0xB6, 0x8B, 0xBB, 0xE0, 0xB6, 0x8C, 0xB6, 0x8D, /* 0xFC-0xFF */
};
-static unsigned char u2c_7A[512] = {
+static const unsigned char u2c_7A[512] = {
0xCF, 0xA1, 0xB6, 0x8E, 0xEF, 0xFC, 0xEF, 0xFB, /* 0x00-0x03 */
0xB6, 0x8F, 0xB6, 0x90, 0xEF, 0xF9, 0xB6, 0x91, /* 0x04-0x07 */
0xB6, 0x92, 0xB6, 0x93, 0xB6, 0x94, 0xB3, 0xCC, /* 0x08-0x0B */
@@ -8218,7 +8218,7 @@ static unsigned char u2c_7A[512] = {
0xB8, 0x86, 0xF3, 0xC4, 0xB8, 0x87, 0xB8, 0xCD, /* 0xFC-0xFF */
};
-static unsigned char u2c_7B[512] = {
+static const unsigned char u2c_7B[512] = {
0xB8, 0x88, 0xB8, 0x89, 0xB8, 0x8A, 0xF3, 0xC6, /* 0x00-0x03 */
0xF3, 0xC7, 0xB8, 0x8B, 0xB0, 0xCA, 0xB8, 0x8C, /* 0x04-0x07 */
0xF3, 0xC5, 0xB8, 0x8D, 0xF3, 0xC9, 0xCB, 0xF1, /* 0x08-0x0B */
@@ -8286,7 +8286,7 @@ static unsigned char u2c_7B[512] = {
0xF3, 0xFB, 0xBA, 0x68, 0xF3, 0xFA, 0xBA, 0x69, /* 0xFC-0xFF */
};
-static unsigned char u2c_7C[512] = {
+static const unsigned char u2c_7C[512] = {
0xBA, 0x6A, 0xBA, 0x6B, 0xBA, 0x6C, 0xBA, 0x6D, /* 0x00-0x03 */
0xBA, 0x6E, 0xBA, 0x6F, 0xBA, 0x70, 0xB4, 0xD8, /* 0x04-0x07 */
0xBA, 0x71, 0xBA, 0x72, 0xBA, 0x73, 0xF3, 0xFE, /* 0x08-0x0B */
@@ -8354,7 +8354,7 @@ static unsigned char u2c_7C[512] = {
0xBC, 0x6B, 0xBC, 0x6C, 0xBC, 0x6D, 0xBC, 0x6E, /* 0xFC-0xFF */
};
-static unsigned char u2c_7D[512] = {
+static const unsigned char u2c_7D[512] = {
0xBC, 0x6F, 0xBC, 0x70, 0xBC, 0x71, 0xBC, 0x72, /* 0x00-0x03 */
0xBC, 0x73, 0xBC, 0x74, 0xBC, 0x75, 0xBC, 0x76, /* 0x04-0x07 */
0xBC, 0x77, 0xBC, 0x78, 0xCE, 0xC9, 0xBC, 0x79, /* 0x08-0x0B */
@@ -8422,7 +8422,7 @@ static unsigned char u2c_7D[512] = {
0xBF, 0x41, 0xBF, 0x42, 0xBF, 0x43, 0xBF, 0x44, /* 0xFC-0xFF */
};
-static unsigned char u2c_7E[512] = {
+static const unsigned char u2c_7E[512] = {
0xBF, 0x45, 0xBF, 0x46, 0xBF, 0x47, 0xBF, 0x48, /* 0x00-0x03 */
0xBF, 0x49, 0xBF, 0x4A, 0xBF, 0x4B, 0xBF, 0x4C, /* 0x04-0x07 */
0xBF, 0x4D, 0xBF, 0x4E, 0xBF, 0x4F, 0xBF, 0x50, /* 0x08-0x0B */
@@ -8490,7 +8490,7 @@ static unsigned char u2c_7E[512] = {
0xD7, 0xDB, 0xD5, 0xC0, 0xE7, 0xBA, 0xC2, 0xCC, /* 0xFC-0xFF */
};
-static unsigned char u2c_7F[512] = {
+static const unsigned char u2c_7F[512] = {
0xD7, 0xBA, 0xE7, 0xBB, 0xE7, 0xBC, 0xE7, 0xBD, /* 0x00-0x03 */
0xBC, 0xEA, 0xC3, 0xE5, 0xC0, 0xC2, 0xE7, 0xBE, /* 0x04-0x07 */
0xE7, 0xBF, 0xBC, 0xA9, 0xC0, 0x88, 0xE7, 0xC0, /* 0x08-0x0B */
@@ -8558,7 +8558,7 @@ static unsigned char u2c_7F[512] = {
0xD2, 0xED, 0xC2, 0x50, 0xC2, 0x51, 0xC2, 0x52, /* 0xFC-0xFF */
};
-static unsigned char u2c_80[512] = {
+static const unsigned char u2c_80[512] = {
0xD2, 0xAB, 0xC0, 0xCF, 0xC2, 0x53, 0xBF, 0xBC, /* 0x00-0x03 */
0xEB, 0xA3, 0xD5, 0xDF, 0xEA, 0xC8, 0xC2, 0x54, /* 0x04-0x07 */
0xC2, 0x55, 0xC2, 0x56, 0xC2, 0x57, 0xF1, 0xF3, /* 0x08-0x0B */
@@ -8626,7 +8626,7 @@ static unsigned char u2c_80[512] = {
0xEB, 0xDD, 0xC4, 0xDC, 0xC3, 0x75, 0xC3, 0x76, /* 0xFC-0xFF */
};
-static unsigned char u2c_81[512] = {
+static const unsigned char u2c_81[512] = {
0xC3, 0x77, 0xC3, 0x78, 0xD6, 0xAC, 0xC3, 0x79, /* 0x00-0x03 */
0xC3, 0x7A, 0xC3, 0x7B, 0xB4, 0xE0, 0xC3, 0x7C, /* 0x04-0x07 */
0xC3, 0x7D, 0xC2, 0xF6, 0xBC, 0xB9, 0xC3, 0x7E, /* 0x08-0x0B */
@@ -8694,7 +8694,7 @@ static unsigned char u2c_81[512] = {
0xBE, 0xCA, 0xC5, 0x60, 0xF4, 0xA7, 0xC5, 0x61, /* 0xFC-0xFF */
};
-static unsigned char u2c_82[512] = {
+static const unsigned char u2c_82[512] = {
0xD2, 0xA8, 0xF4, 0xA8, 0xF4, 0xA9, 0xC5, 0x62, /* 0x00-0x03 */
0xF4, 0xAA, 0xBE, 0xCB, 0xD3, 0xDF, 0xC5, 0x63, /* 0x04-0x07 */
0xC5, 0x64, 0xC5, 0x65, 0xC5, 0x66, 0xC5, 0x67, /* 0x08-0x0B */
@@ -8762,7 +8762,7 @@ static unsigned char u2c_82[512] = {
0xC6, 0x81, 0xC6, 0x82, 0xC6, 0x83, 0xC6, 0x84, /* 0xFC-0xFF */
};
-static unsigned char u2c_83[512] = {
+static const unsigned char u2c_83[512] = {
0xC6, 0x85, 0xD7, 0xC2, 0xC3, 0xAF, 0xB7, 0xB6, /* 0x00-0x03 */
0xC7, 0xD1, 0xC3, 0xA9, 0xDC, 0xE2, 0xDC, 0xD8, /* 0x04-0x07 */
0xDC, 0xEB, 0xDC, 0xD4, 0xC6, 0x86, 0xC6, 0x87, /* 0x08-0x0B */
@@ -8830,7 +8830,7 @@ static unsigned char u2c_83[512] = {
0xC8, 0x49, 0xDD, 0xC4, 0xC8, 0x4A, 0xC8, 0x4B, /* 0xFC-0xFF */
};
-static unsigned char u2c_84[512] = {
+static const unsigned char u2c_84[512] = {
0xC8, 0x4C, 0xDD, 0xBD, 0xC8, 0x4D, 0xDD, 0xCD, /* 0x00-0x03 */
0xCC, 0xD1, 0xC8, 0x4E, 0xDD, 0xC9, 0xC8, 0x4F, /* 0x04-0x07 */
0xC8, 0x50, 0xC8, 0x51, 0xC8, 0x52, 0xDD, 0xC2, /* 0x08-0x0B */
@@ -8898,7 +8898,7 @@ static unsigned char u2c_84[512] = {
0xDE, 0xA4, 0xC9, 0x9C, 0xC9, 0x9D, 0xDE, 0xA3, /* 0xFC-0xFF */
};
-static unsigned char u2c_85[512] = {
+static const unsigned char u2c_85[512] = {
0xC9, 0x9E, 0xC9, 0x9F, 0xC9, 0xA0, 0xCA, 0x40, /* 0x00-0x03 */
0xCA, 0x41, 0xCA, 0x42, 0xCA, 0x43, 0xCA, 0x44, /* 0x04-0x07 */
0xCA, 0x45, 0xCA, 0x46, 0xCA, 0x47, 0xCA, 0x48, /* 0x08-0x0B */
@@ -8966,7 +8966,7 @@ static unsigned char u2c_85[512] = {
0xCC, 0x42, 0xCC, 0x43, 0xCC, 0x44, 0xDE, 0xBD, /* 0xFC-0xFF */
};
-static unsigned char u2c_86[512] = {
+static const unsigned char u2c_86[512] = {
0xCC, 0x45, 0xCC, 0x46, 0xCC, 0x47, 0xCC, 0x48, /* 0x00-0x03 */
0xCC, 0x49, 0xDE, 0xBF, 0xCC, 0x4A, 0xCC, 0x4B, /* 0x04-0x07 */
0xCC, 0x4C, 0xCC, 0x4D, 0xCC, 0x4E, 0xCC, 0x4F, /* 0x08-0x0B */
@@ -9034,7 +9034,7 @@ static unsigned char u2c_86[512] = {
0xCD, 0x92, 0xCD, 0x93, 0xB6, 0xEA, 0xCD, 0x94, /* 0xFC-0xFF */
};
-static unsigned char u2c_87[512] = {
+static const unsigned char u2c_87[512] = {
0xCA, 0xF1, 0xCD, 0x95, 0xB7, 0xE4, 0xF2, 0xD7, /* 0x00-0x03 */
0xCD, 0x96, 0xCD, 0x97, 0xCD, 0x98, 0xF2, 0xD8, /* 0x04-0x07 */
0xF2, 0xDA, 0xF2, 0xDD, 0xF2, 0xDB, 0xCD, 0x99, /* 0x08-0x0B */
@@ -9102,7 +9102,7 @@ static unsigned char u2c_87[512] = {
0xCF, 0x82, 0xCF, 0x83, 0xF3, 0xB8, 0xCF, 0x84, /* 0xFC-0xFF */
};
-static unsigned char u2c_88[512] = {
+static const unsigned char u2c_88[512] = {
0xCF, 0x85, 0xCF, 0x86, 0xCF, 0x87, 0xD9, 0xF9, /* 0x00-0x03 */
0xCF, 0x88, 0xCF, 0x89, 0xCF, 0x8A, 0xCF, 0x8B, /* 0x04-0x07 */
0xCF, 0x8C, 0xCF, 0x8D, 0xF3, 0xB9, 0xCF, 0x8E, /* 0x08-0x0B */
@@ -9170,7 +9170,7 @@ static unsigned char u2c_88[512] = {
0xF1, 0xD3, 0xD1, 0x75, 0xF1, 0xD5, 0xD1, 0x76, /* 0xFC-0xFF */
};
-static unsigned char u2c_89[512] = {
+static const unsigned char u2c_89[512] = {
0xD1, 0x77, 0xD1, 0x78, 0xB9, 0xD3, 0xD1, 0x79, /* 0x00-0x03 */
0xD1, 0x7A, 0xD1, 0x7B, 0xD1, 0x7C, 0xD1, 0x7D, /* 0x04-0x07 */
0xD1, 0x7E, 0xD1, 0x80, 0xF1, 0xDB, 0xD1, 0x81, /* 0x08-0x0B */
@@ -9238,7 +9238,7 @@ static unsigned char u2c_89[512] = {
0xD3, 0x81, 0xD3, 0x82, 0xD3, 0x83, 0xD3, 0x84, /* 0xFC-0xFF */
};
-static unsigned char u2c_8A[512] = {
+static const unsigned char u2c_8A[512] = {
0xD1, 0xD4, 0xD3, 0x85, 0xD3, 0x86, 0xD3, 0x87, /* 0x00-0x03 */
0xD3, 0x88, 0xD3, 0x89, 0xD3, 0x8A, 0xD9, 0xEA, /* 0x04-0x07 */
0xD3, 0x8B, 0xD3, 0x8C, 0xD3, 0x8D, 0xD3, 0x8E, /* 0x08-0x0B */
@@ -9306,7 +9306,7 @@ static unsigned char u2c_8A[512] = {
0xD6, 0x58, 0xD6, 0x59, 0xD6, 0x5A, 0xD6, 0x5B, /* 0xFC-0xFF */
};
-static unsigned char u2c_8B[512] = {
+static const unsigned char u2c_8B[512] = {
0xD6, 0x5C, 0xD6, 0x5D, 0xD6, 0x5E, 0xD6, 0x5F, /* 0x00-0x03 */
0xD6, 0x60, 0xD6, 0x61, 0xD6, 0x62, 0xE5, 0xC0, /* 0x04-0x07 */
0xD6, 0x63, 0xD6, 0x64, 0xD6, 0x65, 0xD6, 0x66, /* 0x08-0x0B */
@@ -9374,7 +9374,7 @@ static unsigned char u2c_8B[512] = {
0xDA, 0xC2, 0xB7, 0xCC, 0xBF, 0xCE, 0xDA, 0xC3, /* 0xFC-0xFF */
};
-static unsigned char u2c_8C[512] = {
+static const unsigned char u2c_8C[512] = {
0xDA, 0xC4, 0xCB, 0xAD, 0xDA, 0xC5, 0xB5, 0xF7, /* 0x00-0x03 */
0xDA, 0xC6, 0xC1, 0xC2, 0xD7, 0xBB, 0xDA, 0xC7, /* 0x04-0x07 */
0xCC, 0xB8, 0xD7, 0x9F, 0xD2, 0xEA, 0xC4, 0xB1, /* 0x08-0x0B */
@@ -9442,7 +9442,7 @@ static unsigned char u2c_8C[512] = {
0xD9, 0x8F, 0xD9, 0x90, 0xD9, 0x91, 0xD9, 0x92, /* 0xFC-0xFF */
};
-static unsigned char u2c_8D[512] = {
+static const unsigned char u2c_8D[512] = {
0xD9, 0x93, 0xD9, 0x94, 0xD9, 0x95, 0xD9, 0x96, /* 0x00-0x03 */
0xD9, 0x97, 0xD9, 0x98, 0xD9, 0x99, 0xD9, 0x9A, /* 0x04-0x07 */
0xD9, 0x9B, 0xD9, 0x9C, 0xD9, 0x9D, 0xD9, 0x9E, /* 0x08-0x0B */
@@ -9510,7 +9510,7 @@ static unsigned char u2c_8D[512] = {
0xDB, 0x52, 0xF5, 0xD5, 0xDB, 0x53, 0xDB, 0x54, /* 0xFC-0xFF */
};
-static unsigned char u2c_8E[512] = {
+static const unsigned char u2c_8E[512] = {
0xDB, 0x55, 0xDB, 0x56, 0xDB, 0x57, 0xDB, 0x58, /* 0x00-0x03 */
0xDB, 0x59, 0xF5, 0xBD, 0xDB, 0x5A, 0xDB, 0x5B, /* 0x04-0x07 */
0xDB, 0x5C, 0xF5, 0xD4, 0xD3, 0xBB, 0xDB, 0x5D, /* 0x08-0x0B */
@@ -9578,7 +9578,7 @@ static unsigned char u2c_8E[512] = {
0xDD, 0x57, 0xDD, 0x58, 0xDD, 0x59, 0xDD, 0x5A, /* 0xFC-0xFF */
};
-static unsigned char u2c_8F[512] = {
+static const unsigned char u2c_8F[512] = {
0xDD, 0x5B, 0xDD, 0x5C, 0xDD, 0x5D, 0xDD, 0x5E, /* 0x00-0x03 */
0xDD, 0x5F, 0xDD, 0x60, 0xDD, 0x61, 0xDD, 0x62, /* 0x04-0x07 */
0xDD, 0x63, 0xDD, 0x64, 0xDD, 0x65, 0xDD, 0x66, /* 0x08-0x0B */
@@ -9646,7 +9646,7 @@ static unsigned char u2c_8F[512] = {
0xDE, 0x97, 0xD7, 0xB7, 0xDE, 0x98, 0xDE, 0x99, /* 0xFC-0xFF */
};
-static unsigned char u2c_90[512] = {
+static const unsigned char u2c_90[512] = {
0xCD, 0xCB, 0xCB, 0xCD, 0xCA, 0xCA, 0xCC, 0xD3, /* 0x00-0x03 */
0xE5, 0xCC, 0xE5, 0xCB, 0xC4, 0xE6, 0xDE, 0x9A, /* 0x04-0x07 */
0xDE, 0x9B, 0xD1, 0xA1, 0xD1, 0xB7, 0xE5, 0xCD, /* 0x08-0x0B */
@@ -9714,7 +9714,7 @@ static unsigned char u2c_90[512] = {
0xE0, 0x63, 0xB6, 0xBC, 0xDB, 0xB1, 0xE0, 0x64, /* 0xFC-0xFF */
};
-static unsigned char u2c_91[512] = {
+static const unsigned char u2c_91[512] = {
0xE0, 0x65, 0xE0, 0x66, 0xB6, 0xF5, 0xE0, 0x67, /* 0x00-0x03 */
0xDB, 0xB2, 0xE0, 0x68, 0xE0, 0x69, 0xE0, 0x6A, /* 0x04-0x07 */
0xE0, 0x6B, 0xE0, 0x6C, 0xE0, 0x6D, 0xE0, 0x6E, /* 0x08-0x0B */
@@ -9782,7 +9782,7 @@ static unsigned char u2c_91[512] = {
0xE2, 0x56, 0xE2, 0x57, 0xE2, 0x58, 0xE2, 0x59, /* 0xFC-0xFF */
};
-static unsigned char u2c_92[512] = {
+static const unsigned char u2c_92[512] = {
0xE2, 0x5A, 0xE2, 0x5B, 0xE2, 0x5C, 0xE2, 0x5D, /* 0x00-0x03 */
0xE2, 0x5E, 0xE2, 0x5F, 0xE2, 0x60, 0xE2, 0x61, /* 0x04-0x07 */
0xE2, 0x62, 0xE2, 0x63, 0xE2, 0x64, 0xE2, 0x65, /* 0x08-0x0B */
@@ -9850,7 +9850,7 @@ static unsigned char u2c_92[512] = {
0xE4, 0x93, 0xE4, 0x94, 0xE4, 0x95, 0xE4, 0x96, /* 0xFC-0xFF */
};
-static unsigned char u2c_93[512] = {
+static const unsigned char u2c_93[512] = {
0xE4, 0x97, 0xE4, 0x98, 0xE4, 0x99, 0xE4, 0x9A, /* 0x00-0x03 */
0xE4, 0x9B, 0xE4, 0x9C, 0xE4, 0x9D, 0xE4, 0x9E, /* 0x04-0x07 */
0xE4, 0x9F, 0xE4, 0xA0, 0xE5, 0x40, 0xE5, 0x41, /* 0x08-0x0B */
@@ -9918,7 +9918,7 @@ static unsigned char u2c_93[512] = {
0xE7, 0x6D, 0xE7, 0x6E, 0xE7, 0x6F, 0xE7, 0x70, /* 0xFC-0xFF */
};
-static unsigned char u2c_94[512] = {
+static const unsigned char u2c_94[512] = {
0xE7, 0x71, 0xE7, 0x72, 0xE7, 0x73, 0xE7, 0x74, /* 0x00-0x03 */
0xE7, 0x75, 0xE7, 0x76, 0xE7, 0x77, 0xE7, 0x78, /* 0x04-0x07 */
0xE7, 0x79, 0xE7, 0x7A, 0xE7, 0x7B, 0xE7, 0x7C, /* 0x08-0x0B */
@@ -9986,7 +9986,7 @@ static unsigned char u2c_94[512] = {
0xEF, 0xAA, 0xEF, 0xAB, 0xC1, 0xB4, 0xEF, 0xAC, /* 0xFC-0xFF */
};
-static unsigned char u2c_95[512] = {
+static const unsigned char u2c_95[512] = {
0xCF, 0xFA, 0xCB, 0xF8, 0xEF, 0xAE, 0xEF, 0xAD, /* 0x00-0x03 */
0xB3, 0xFA, 0xB9, 0xF8, 0xEF, 0xAF, 0xEF, 0xB0, /* 0x04-0x07 */
0xD0, 0xE2, 0xEF, 0xB1, 0xEF, 0xB2, 0xB7, 0xE6, /* 0x08-0x0B */
@@ -10054,7 +10054,7 @@ static unsigned char u2c_95[512] = {
0xE3, 0xCB, 0xC3, 0xF6, 0xE3, 0xCC, 0xEA, 0x5D, /* 0xFC-0xFF */
};
-static unsigned char u2c_96[512] = {
+static const unsigned char u2c_96[512] = {
0xB7, 0xA7, 0xB8, 0xF3, 0xBA, 0xD2, 0xE3, 0xCD, /* 0x00-0x03 */
0xE3, 0xCE, 0xD4, 0xC4, 0xE3, 0xCF, 0xEA, 0x5E, /* 0x04-0x07 */
0xE3, 0xD0, 0xD1, 0xCB, 0xE3, 0xD1, 0xE3, 0xD2, /* 0x08-0x0B */
@@ -10122,7 +10122,7 @@ static unsigned char u2c_96[512] = {
0xEB, 0x8B, 0xEB, 0x8C, 0xCE, 0xED, 0xEB, 0x8D, /* 0xFC-0xFF */
};
-static unsigned char u2c_97[512] = {
+static const unsigned char u2c_97[512] = {
0xD0, 0xE8, 0xF6, 0xAB, 0xEB, 0x8E, 0xEB, 0x8F, /* 0x00-0x03 */
0xCF, 0xF6, 0xEB, 0x90, 0xF6, 0xAA, 0xD5, 0xF0, /* 0x04-0x07 */
0xF6, 0xAC, 0xC3, 0xB9, 0xEB, 0x91, 0xEB, 0x92, /* 0x08-0x0B */
@@ -10190,7 +10190,7 @@ static unsigned char u2c_97[512] = {
0xED, 0x8E, 0xED, 0x8F, 0xED, 0x90, 0xED, 0x91, /* 0xFC-0xFF */
};
-static unsigned char u2c_98[512] = {
+static const unsigned char u2c_98[512] = {
0xED, 0x92, 0xED, 0x93, 0xED, 0x94, 0xED, 0x95, /* 0x00-0x03 */
0xED, 0x96, 0xED, 0x97, 0xED, 0x98, 0xED, 0x99, /* 0x04-0x07 */
0xED, 0x9A, 0xED, 0x9B, 0xED, 0x9C, 0xED, 0x9D, /* 0x08-0x0B */
@@ -10258,7 +10258,7 @@ static unsigned char u2c_98[512] = {
0xEF, 0x95, 0xEF, 0x96, 0xEF, 0x97, 0xEF, 0x98, /* 0xFC-0xFF */
};
-static unsigned char u2c_99[512] = {
+static const unsigned char u2c_99[512] = {
0xEF, 0x99, 0xEF, 0x9A, 0xEF, 0x9B, 0xEF, 0x9C, /* 0x00-0x03 */
0xEF, 0x9D, 0xEF, 0x9E, 0xEF, 0x9F, 0xEF, 0xA0, /* 0x04-0x07 */
0xF0, 0x40, 0xF0, 0x41, 0xF0, 0x42, 0xF0, 0x43, /* 0x08-0x0B */
@@ -10326,7 +10326,7 @@ static unsigned char u2c_99[512] = {
0xF2, 0x42, 0xF2, 0x43, 0xF2, 0x44, 0xF2, 0x45, /* 0xFC-0xFF */
};
-static unsigned char u2c_9A[512] = {
+static const unsigned char u2c_9A[512] = {
0xF2, 0x46, 0xF2, 0x47, 0xF2, 0x48, 0xF2, 0x49, /* 0x00-0x03 */
0xF2, 0x4A, 0xF2, 0x4B, 0xF2, 0x4C, 0xF2, 0x4D, /* 0x04-0x07 */
0xF2, 0x4E, 0xF2, 0x4F, 0xF2, 0x50, 0xF2, 0x51, /* 0x08-0x0B */
@@ -10394,7 +10394,7 @@ static unsigned char u2c_9A[512] = {
0xF3, 0x97, 0xF3, 0x98, 0xF3, 0x99, 0xF3, 0x9A, /* 0xFC-0xFF */
};
-static unsigned char u2c_9B[512] = {
+static const unsigned char u2c_9B[512] = {
0xF3, 0x9B, 0xF3, 0x9C, 0xF3, 0x9D, 0xD7, 0xD7, /* 0x00-0x03 */
0xF3, 0x9E, 0xF3, 0x9F, 0xF3, 0xA0, 0xF4, 0x40, /* 0x04-0x07 */
0xF7, 0xDC, 0xF4, 0x41, 0xF4, 0x42, 0xF4, 0x43, /* 0x08-0x0B */
@@ -10462,7 +10462,7 @@ static unsigned char u2c_9B[512] = {
0xF6, 0x60, 0xF6, 0x61, 0xF6, 0x62, 0xF6, 0x63, /* 0xFC-0xFF */
};
-static unsigned char u2c_9C[512] = {
+static const unsigned char u2c_9C[512] = {
0xF6, 0x64, 0xF6, 0x65, 0xF6, 0x66, 0xF6, 0x67, /* 0x00-0x03 */
0xF6, 0x68, 0xF6, 0x69, 0xF6, 0x6A, 0xF6, 0x6B, /* 0x04-0x07 */
0xF6, 0x6C, 0xF6, 0x6D, 0xF6, 0x6E, 0xF6, 0x6F, /* 0x08-0x0B */
@@ -10530,7 +10530,7 @@ static unsigned char u2c_9C[512] = {
0xF8, 0x59, 0xF8, 0x5A, 0xF8, 0x5B, 0xF8, 0x5C, /* 0xFC-0xFF */
};
-static unsigned char u2c_9D[512] = {
+static const unsigned char u2c_9D[512] = {
0xF8, 0x5D, 0xF8, 0x5E, 0xF8, 0x5F, 0xF8, 0x60, /* 0x00-0x03 */
0xF8, 0x61, 0xF8, 0x62, 0xF8, 0x63, 0xF8, 0x64, /* 0x04-0x07 */
0xF8, 0x65, 0xF8, 0x66, 0xF8, 0x67, 0xF8, 0x68, /* 0x08-0x0B */
@@ -10598,7 +10598,7 @@ static unsigned char u2c_9D[512] = {
0xFA, 0x9A, 0xFA, 0x9B, 0xFA, 0x9C, 0xFA, 0x9D, /* 0xFC-0xFF */
};
-static unsigned char u2c_9E[512] = {
+static const unsigned char u2c_9E[512] = {
0xFA, 0x9E, 0xFA, 0x9F, 0xFA, 0xA0, 0xFB, 0x40, /* 0x00-0x03 */
0xFB, 0x41, 0xFB, 0x42, 0xFB, 0x43, 0xFB, 0x44, /* 0x04-0x07 */
0xFB, 0x45, 0xFB, 0x46, 0xFB, 0x47, 0xFB, 0x48, /* 0x08-0x0B */
@@ -10666,7 +10666,7 @@ static unsigned char u2c_9E[512] = {
0xED, 0xEB, 0xFC, 0x77, 0xF6, 0xBC, 0xFC, 0x78, /* 0xFC-0xFF */
};
-static unsigned char u2c_9F[512] = {
+static const unsigned char u2c_9F[512] = {
0xFC, 0x79, 0xFC, 0x7A, 0xFC, 0x7B, 0xFC, 0x7C, /* 0x00-0x03 */
0xFC, 0x7D, 0xFC, 0x7E, 0xFC, 0x80, 0xFC, 0x81, /* 0x04-0x07 */
0xFC, 0x82, 0xFC, 0x83, 0xFC, 0x84, 0xF6, 0xBD, /* 0x08-0x0B */
@@ -10712,11 +10712,11 @@ static unsigned char u2c_9F[512] = {
0xFD, 0x9A, 0xFD, 0x9B, 0x00, 0x00, 0x00, 0x00, /* 0xA4-0xA7 */
};
-static unsigned char u2c_DC[512] = {
+static const unsigned char u2c_DC[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
};
-static unsigned char u2c_F9[512] = {
+static const unsigned char u2c_F9[512] = {
0xD8, 0x4D, 0xB8, 0xFC, 0xDC, 0x87, 0xD9, 0x5A, /* 0x00-0x03 */
0xBB, 0xAC, 0xB4, 0xAE, 0xBE, 0xE4, 0xFD, 0x94, /* 0x04-0x07 */
0xFD, 0x94, 0xC6, 0xF5, 0xBD, 0xF0, 0xC0, 0xAE, /* 0x08-0x0B */
@@ -10784,7 +10784,7 @@ static unsigned char u2c_F9[512] = {
0xD7, 0x52, 0xCA, 0xB2, 0xB2, 0xE8, 0xB4, 0xCC, /* 0xFC-0xFF */
};
-static unsigned char u2c_FA[512] = {
+static const unsigned char u2c_FA[512] = {
0xC7, 0xD0, 0xB6, 0xC8, 0xCD, 0xD8, 0xCC, 0xC7, /* 0x00-0x03 */
0xD5, 0xAC, 0xB6, 0xB4, 0xB1, 0xA9, 0xDD, 0x97, /* 0x04-0x07 */
0xD0, 0xD0, 0xBD, 0xB5, 0xD2, 0x8A, 0xC0, 0xAA, /* 0x08-0x0B */
@@ -10799,7 +10799,7 @@ static unsigned char u2c_FA[512] = {
0xF0, 0x5E, 0xFA, 0x51, 0x00, 0x00, 0x00, 0x00, /* 0x2C-0x2F */
};
-static unsigned char u2c_FE[512] = {
+static const unsigned char u2c_FE[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -10829,7 +10829,7 @@ static unsigned char u2c_FE[512] = {
0xA9, 0x85, 0xA9, 0x86, 0xA9, 0x87, 0xA9, 0x88, /* 0x68-0x6B */
};
-static unsigned char u2c_FF[512] = {
+static const unsigned char u2c_FF[512] = {
0x00, 0x00, 0xA3, 0xA1, 0xA3, 0xA2, 0xA3, 0xA3, /* 0x00-0x03 */
0xA1, 0xE7, 0xA3, 0xA5, 0xA3, 0xA6, 0xA3, 0xA7, /* 0x04-0x07 */
0xA3, 0xA8, 0xA3, 0xA9, 0xA3, 0xAA, 0xA3, 0xAB, /* 0x08-0x0B */
@@ -10891,7 +10891,7 @@ static unsigned char u2c_FF[512] = {
0xA9, 0x57, 0xA3, 0xA4, 0x00, 0x00, 0x00, 0x00, /* 0xE4-0xE7 */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
u2c_00, u2c_01, u2c_02, u2c_03, u2c_04, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -10925,7 +10925,7 @@ static unsigned char *page_uni2charset[256] = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, u2c_F9, u2c_FA, NULL, NULL, NULL, u2c_FE, u2c_FF, };
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -10961,7 +10961,7 @@ static unsigned char charset2lower[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -11000,7 +11000,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(const wchar_t uni,
unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni&0xFF;
unsigned char ch = (uni>>8)&0xFF;
unsigned char out0,out1;
@@ -11050,7 +11050,7 @@ static int char2uni(const unsigned char *rawstring, int boundlen,
wchar_t *uni)
{
unsigned char ch, cl;
- wchar_t *charset2uni;
+ const wchar_t *charset2uni;
int n;
if (boundlen <= 0)
diff --git a/fs/nls/nls_cp949.c b/fs/nls/nls_cp949.c
index 92ae19372f0f..8a7a2fe85c65 100644
--- a/fs/nls/nls_cp949.c
+++ b/fs/nls/nls_cp949.c
@@ -13,7 +13,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t c2u_81[256] = {
+static const wchar_t c2u_81[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -49,7 +49,7 @@ static wchar_t c2u_81[256] = {
0xAD09,0xAD0A,0xAD0B,0xAD0E,0xAD10,0xAD12,0xAD13,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_82[256] = {
+static const wchar_t c2u_82[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -85,7 +85,7 @@ static wchar_t c2u_82[256] = {
0xADF1,0xADF2,0xADF3,0xADF4,0xADF5,0xADF6,0xADF7,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_83[256] = {
+static const wchar_t c2u_83[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -121,7 +121,7 @@ static wchar_t c2u_83[256] = {
0xAEDF,0xAEE0,0xAEE1,0xAEE2,0xAEE3,0xAEE4,0xAEE5,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_84[256] = {
+static const wchar_t c2u_84[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -157,7 +157,7 @@ static wchar_t c2u_84[256] = {
0xAFB5,0xAFB6,0xAFB7,0xAFBA,0xAFBB,0xAFBD,0xAFBE,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_85[256] = {
+static const wchar_t c2u_85[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -193,7 +193,7 @@ static wchar_t c2u_85[256] = {
0xB096,0xB097,0xB09B,0xB09D,0xB09E,0xB0A3,0xB0A4,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_86[256] = {
+static const wchar_t c2u_86[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -229,7 +229,7 @@ static wchar_t c2u_86[256] = {
0xB195,0xB196,0xB197,0xB199,0xB19A,0xB19B,0xB19D,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_87[256] = {
+static const wchar_t c2u_87[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -265,7 +265,7 @@ static wchar_t c2u_87[256] = {
0xB266,0xB267,0xB26A,0xB26B,0xB26C,0xB26D,0xB26E,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_88[256] = {
+static const wchar_t c2u_88[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -301,7 +301,7 @@ static wchar_t c2u_88[256] = {
0xB359,0xB35A,0xB35D,0xB360,0xB361,0xB362,0xB363,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_89[256] = {
+static const wchar_t c2u_89[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -337,7 +337,7 @@ static wchar_t c2u_89[256] = {
0xB43E,0xB43F,0xB440,0xB441,0xB442,0xB443,0xB444,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_8A[256] = {
+static const wchar_t c2u_8A[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -373,7 +373,7 @@ static wchar_t c2u_8A[256] = {
0xB512,0xB513,0xB516,0xB517,0xB519,0xB51A,0xB51D,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_8B[256] = {
+static const wchar_t c2u_8B[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -409,7 +409,7 @@ static wchar_t c2u_8B[256] = {
0xB5F9,0xB5FA,0xB5FB,0xB5FC,0xB5FD,0xB5FE,0xB5FF,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_8C[256] = {
+static const wchar_t c2u_8C[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -445,7 +445,7 @@ static wchar_t c2u_8C[256] = {
0xB6BC,0xB6BD,0xB6BE,0xB6BF,0xB6C0,0xB6C1,0xB6C2,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_8D[256] = {
+static const wchar_t c2u_8D[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -481,7 +481,7 @@ static wchar_t c2u_8D[256] = {
0xB793,0xB794,0xB795,0xB79A,0xB79B,0xB79D,0xB79E,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_8E[256] = {
+static const wchar_t c2u_8E[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -517,7 +517,7 @@ static wchar_t c2u_8E[256] = {
0xB87E,0xB87F,0xB880,0xB881,0xB882,0xB883,0xB884,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_8F[256] = {
+static const wchar_t c2u_8F[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -553,7 +553,7 @@ static wchar_t c2u_8F[256] = {
0xB950,0xB952,0xB953,0xB954,0xB955,0xB956,0xB957,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_90[256] = {
+static const wchar_t c2u_90[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -589,7 +589,7 @@ static wchar_t c2u_90[256] = {
0xBA3E,0xBA3F,0xBA41,0xBA43,0xBA44,0xBA45,0xBA46,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_91[256] = {
+static const wchar_t c2u_91[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -625,7 +625,7 @@ static wchar_t c2u_91[256] = {
0xBB21,0xBB22,0xBB23,0xBB24,0xBB25,0xBB26,0xBB27,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_92[256] = {
+static const wchar_t c2u_92[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -661,7 +661,7 @@ static wchar_t c2u_92[256] = {
0xBBF6,0xBBF7,0xBBFA,0xBBFB,0xBBFD,0xBBFE,0xBC01,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_93[256] = {
+static const wchar_t c2u_93[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -697,7 +697,7 @@ static wchar_t c2u_93[256] = {
0xBCF2,0xBCF3,0xBCF7,0xBCF9,0xBCFA,0xBCFB,0xBCFD,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_94[256] = {
+static const wchar_t c2u_94[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -733,7 +733,7 @@ static wchar_t c2u_94[256] = {
0xBDCB,0xBDCC,0xBDCD,0xBDCE,0xBDCF,0xBDD0,0xBDD1,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_95[256] = {
+static const wchar_t c2u_95[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -769,7 +769,7 @@ static wchar_t c2u_95[256] = {
0xBEB1,0xBEB2,0xBEB3,0xBEB4,0xBEB5,0xBEB6,0xBEB7,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_96[256] = {
+static const wchar_t c2u_96[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -805,7 +805,7 @@ static wchar_t c2u_96[256] = {
0xBF7C,0xBF7D,0xBF7E,0xBF7F,0xBF80,0xBF81,0xBF82,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_97[256] = {
+static const wchar_t c2u_97[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -841,7 +841,7 @@ static wchar_t c2u_97[256] = {
0xC038,0xC039,0xC03A,0xC03B,0xC03D,0xC03E,0xC03F,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_98[256] = {
+static const wchar_t c2u_98[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -877,7 +877,7 @@ static wchar_t c2u_98[256] = {
0xC122,0xC125,0xC128,0xC129,0xC12A,0xC12B,0xC12E,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_99[256] = {
+static const wchar_t c2u_99[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -913,7 +913,7 @@ static wchar_t c2u_99[256] = {
0xC21A,0xC21B,0xC21D,0xC21E,0xC221,0xC222,0xC223,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_9A[256] = {
+static const wchar_t c2u_9A[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -949,7 +949,7 @@ static wchar_t c2u_9A[256] = {
0xC305,0xC306,0xC307,0xC30A,0xC30B,0xC30E,0xC30F,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_9B[256] = {
+static const wchar_t c2u_9B[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -985,7 +985,7 @@ static wchar_t c2u_9B[256] = {
0xC3D2,0xC3D3,0xC3D4,0xC3D5,0xC3D6,0xC3D7,0xC3DA,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_9C[256] = {
+static const wchar_t c2u_9C[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1021,7 +1021,7 @@ static wchar_t c2u_9C[256] = {
0xC4A3,0xC4A4,0xC4A5,0xC4A6,0xC4A7,0xC4A8,0xC4A9,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_9D[256] = {
+static const wchar_t c2u_9D[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1057,7 +1057,7 @@ static wchar_t c2u_9D[256] = {
0xC58A,0xC58B,0xC58E,0xC590,0xC592,0xC593,0xC594,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_9E[256] = {
+static const wchar_t c2u_9E[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1093,7 +1093,7 @@ static wchar_t c2u_9E[256] = {
0xC69E,0xC69F,0xC6A0,0xC6A1,0xC6A2,0xC6A3,0xC6A6,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_9F[256] = {
+static const wchar_t c2u_9F[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1129,7 +1129,7 @@ static wchar_t c2u_9F[256] = {
0xC7AF,0xC7B1,0xC7B2,0xC7B3,0xC7B5,0xC7B6,0xC7B7,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_A0[256] = {
+static const wchar_t c2u_A0[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1165,7 +1165,7 @@ static wchar_t c2u_A0[256] = {
0xC89B,0xC89C,0xC89E,0xC8A0,0xC8A2,0xC8A3,0xC8A4,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_A1[256] = {
+static const wchar_t c2u_A1[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1201,7 +1201,7 @@ static wchar_t c2u_A1[256] = {
0x2282,0x2283,0x222A,0x2229,0x2227,0x2228,0xFFE2,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_A2[256] = {
+static const wchar_t c2u_A2[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1234,7 +1234,7 @@ static wchar_t c2u_A2[256] = {
0x2116,0x33C7,0x2122,0x33C2,0x33D8,0x2121,0x20AC,0x00AE,/* 0xE0-0xE7 */
};
-static wchar_t c2u_A3[256] = {
+static const wchar_t c2u_A3[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1270,7 +1270,7 @@ static wchar_t c2u_A3[256] = {
0xFF58,0xFF59,0xFF5A,0xFF5B,0xFF5C,0xFF5D,0xFFE3,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_A4[256] = {
+static const wchar_t c2u_A4[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1306,7 +1306,7 @@ static wchar_t c2u_A4[256] = {
0x3188,0x3189,0x318A,0x318B,0x318C,0x318D,0x318E,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_A5[256] = {
+static const wchar_t c2u_A5[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1342,7 +1342,7 @@ static wchar_t c2u_A5[256] = {
0x03C9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_A6[256] = {
+static const wchar_t c2u_A6[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1375,7 +1375,7 @@ static wchar_t c2u_A6[256] = {
0x2546,0x2547,0x2548,0x2549,0x254A,0x0000,0x0000,0x0000,/* 0xE0-0xE7 */
};
-static wchar_t c2u_A7[256] = {
+static const wchar_t c2u_A7[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1409,7 +1409,7 @@ static wchar_t c2u_A7[256] = {
0x33AC,0x33DD,0x33D0,0x33D3,0x33C3,0x33C9,0x33DC,0x33C6,/* 0xE8-0xEF */
};
-static wchar_t c2u_A8[256] = {
+static const wchar_t c2u_A8[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1445,7 +1445,7 @@ static wchar_t c2u_A8[256] = {
0x2154,0x00BC,0x00BE,0x215B,0x215C,0x215D,0x215E,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_A9[256] = {
+static const wchar_t c2u_A9[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1481,7 +1481,7 @@ static wchar_t c2u_A9[256] = {
0x00B3,0x2074,0x207F,0x2081,0x2082,0x2083,0x2084,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_AA[256] = {
+static const wchar_t c2u_AA[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1516,7 +1516,7 @@ static wchar_t c2u_AA[256] = {
0x3090,0x3091,0x3092,0x3093,0x0000,0x0000,0x0000,0x0000,/* 0xF0-0xF7 */
};
-static wchar_t c2u_AB[256] = {
+static const wchar_t c2u_AB[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1551,7 +1551,7 @@ static wchar_t c2u_AB[256] = {
0x30F0,0x30F1,0x30F2,0x30F3,0x30F4,0x30F5,0x30F6,0x0000,/* 0xF0-0xF7 */
};
-static wchar_t c2u_AC[256] = {
+static const wchar_t c2u_AC[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1586,7 +1586,7 @@ static wchar_t c2u_AC[256] = {
0x044E,0x044F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0xF0-0xF7 */
};
-static wchar_t c2u_AD[256] = {
+static const wchar_t c2u_AD[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1611,7 +1611,7 @@ static wchar_t c2u_AD[256] = {
0xCDC5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0xA0-0xA7 */
};
-static wchar_t c2u_AE[256] = {
+static const wchar_t c2u_AE[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1636,7 +1636,7 @@ static wchar_t c2u_AE[256] = {
0xCE2B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0xA0-0xA7 */
};
-static wchar_t c2u_AF[256] = {
+static const wchar_t c2u_AF[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1661,7 +1661,7 @@ static wchar_t c2u_AF[256] = {
0xCE99,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0xA0-0xA7 */
};
-static wchar_t c2u_B0[256] = {
+static const wchar_t c2u_B0[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1697,7 +1697,7 @@ static wchar_t c2u_B0[256] = {
0xACF5,0xACF6,0xACFC,0xACFD,0xAD00,0xAD04,0xAD06,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_B1[256] = {
+static const wchar_t c2u_B1[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1733,7 +1733,7 @@ static wchar_t c2u_B1[256] = {
0xAE61,0xAE65,0xAE68,0xAE69,0xAE6C,0xAE70,0xAE78,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_B2[256] = {
+static const wchar_t c2u_B2[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1769,7 +1769,7 @@ static wchar_t c2u_B2[256] = {
0xB04C,0xB04E,0xB053,0xB054,0xB055,0xB057,0xB059,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_B3[256] = {
+static const wchar_t c2u_B3[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1805,7 +1805,7 @@ static wchar_t c2u_B3[256] = {
0xB19C,0xB1A8,0xB1CC,0xB1D0,0xB1D4,0xB1DC,0xB1DD,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_B4[256] = {
+static const wchar_t c2u_B4[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1841,7 +1841,7 @@ static wchar_t c2u_B4[256] = {
0xB358,0xB35B,0xB35C,0xB35E,0xB35F,0xB364,0xB365,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_B5[256] = {
+static const wchar_t c2u_B5[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1877,7 +1877,7 @@ static wchar_t c2u_B5[256] = {
0xB528,0xB529,0xB52A,0xB530,0xB531,0xB534,0xB538,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_B6[256] = {
+static const wchar_t c2u_B6[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1913,7 +1913,7 @@ static wchar_t c2u_B6[256] = {
0xB78D,0xB78F,0xB790,0xB791,0xB792,0xB796,0xB797,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_B7[256] = {
+static const wchar_t c2u_B7[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1949,7 +1949,7 @@ static wchar_t c2u_B7[256] = {
0xB951,0xB958,0xB959,0xB95C,0xB960,0xB968,0xB969,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_B8[256] = {
+static const wchar_t c2u_B8[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1985,7 +1985,7 @@ static wchar_t c2u_B8[256] = {
0xBABB,0xBABD,0xBAC4,0xBAC8,0xBAD8,0xBAD9,0xBAFC,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_B9[256] = {
+static const wchar_t c2u_B9[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2021,7 +2021,7 @@ static wchar_t c2u_B9[256] = {
0xBC88,0xBC8B,0xBC8C,0xBC8E,0xBC94,0xBC95,0xBC97,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_BA[256] = {
+static const wchar_t c2u_BA[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2057,7 +2057,7 @@ static wchar_t c2u_BA[256] = {
0xBE57,0xBE59,0xBE5A,0xBE5B,0xBE60,0xBE61,0xBE64,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_BB[256] = {
+static const wchar_t c2u_BB[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2093,7 +2093,7 @@ static wchar_t c2u_BB[256] = {
0xC0D0,0xC0D8,0xC0D9,0xC0DB,0xC0DC,0xC0DD,0xC0E4,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_BC[256] = {
+static const wchar_t c2u_BC[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2129,7 +2129,7 @@ static wchar_t c2u_BC[256] = {
0xC21C,0xC21F,0xC220,0xC228,0xC229,0xC22B,0xC22D,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_BD[256] = {
+static const wchar_t c2u_BD[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2165,7 +2165,7 @@ static wchar_t c2u_BD[256] = {
0xC3F5,0xC3F8,0xC408,0xC410,0xC424,0xC42C,0xC430,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_BE[256] = {
+static const wchar_t c2u_BE[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2201,7 +2201,7 @@ static wchar_t c2u_BE[256] = {
0xC5C6,0xC5C7,0xC5C8,0xC5C9,0xC5CA,0xC5CC,0xC5CE,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_BF[256] = {
+static const wchar_t c2u_BF[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2237,7 +2237,7 @@ static wchar_t c2u_BF[256] = {
0xC6D0,0xC6D4,0xC6DC,0xC6DD,0xC6E0,0xC6E1,0xC6E8,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_C0[256] = {
+static const wchar_t c2u_C0[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2273,7 +2273,7 @@ static wchar_t c2u_C0[256] = {
0xC7E8,0xC7EC,0xC800,0xC801,0xC804,0xC808,0xC80A,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_C1[256] = {
+static const wchar_t c2u_C1[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2309,7 +2309,7 @@ static wchar_t c2u_C1[256] = {
0xC9C4,0xC9C7,0xC9C8,0xC9CA,0xC9D0,0xC9D1,0xC9D3,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_C2[256] = {
+static const wchar_t c2u_C2[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2345,7 +2345,7 @@ static wchar_t c2u_C2[256] = {
0xCC29,0xCC2C,0xCC2E,0xCC30,0xCC38,0xCC39,0xCC3B,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_C3[256] = {
+static const wchar_t c2u_C3[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2381,7 +2381,7 @@ static wchar_t c2u_C3[256] = {
0xCE21,0xCE24,0xCE28,0xCE30,0xCE31,0xCE33,0xCE35,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_C4[256] = {
+static const wchar_t c2u_C4[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2417,7 +2417,7 @@ static wchar_t c2u_C4[256] = {
0xD011,0xD018,0xD02D,0xD034,0xD035,0xD038,0xD03C,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_C5[256] = {
+static const wchar_t c2u_C5[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2453,7 +2453,7 @@ static wchar_t c2u_C5[256] = {
0xD234,0xD23C,0xD23D,0xD23F,0xD241,0xD248,0xD25C,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_C6[256] = {
+static const wchar_t c2u_C6[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2489,7 +2489,7 @@ static wchar_t c2u_C6[256] = {
0xD3ED,0xD3F0,0xD3F4,0xD3FC,0xD3FD,0xD3FF,0xD401,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_C7[256] = {
+static const wchar_t c2u_C7[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2525,7 +2525,7 @@ static wchar_t c2u_C7[256] = {
0xD610,0xD611,0xD613,0xD614,0xD615,0xD61C,0xD620,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_C8[256] = {
+static const wchar_t c2u_C8[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2561,7 +2561,7 @@ static wchar_t c2u_C8[256] = {
0xD789,0xD78C,0xD790,0xD798,0xD799,0xD79B,0xD79D,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_CA[256] = {
+static const wchar_t c2u_CA[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2597,7 +2597,7 @@ static wchar_t c2u_CA[256] = {
0x76E3,0x77B0,0x7D3A,0x90AF,0x9451,0x9452,0x9F95,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_CB[256] = {
+static const wchar_t c2u_CB[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2633,7 +2633,7 @@ static wchar_t c2u_CB[256] = {
0x5091,0x6770,0x6840,0x5109,0x528D,0x5292,0x6AA2,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_CC[256] = {
+static const wchar_t c2u_CC[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2669,7 +2669,7 @@ static wchar_t c2u_CC[256] = {
0x5951,0x5B63,0x5C46,0x60B8,0x6212,0x6842,0x68B0,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_CD[256] = {
+static const wchar_t c2u_CD[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2705,7 +2705,7 @@ static wchar_t c2u_CD[256] = {
0x8CA2,0x978F,0x4E32,0x5BE1,0x6208,0x679C,0x74DC,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_CE[256] = {
+static const wchar_t c2u_CE[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2741,7 +2741,7 @@ static wchar_t c2u_CE[256] = {
0x4E18,0x4E45,0x4E5D,0x4EC7,0x4FF1,0x5177,0x52FE,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_CF[256] = {
+static const wchar_t c2u_CF[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2777,7 +2777,7 @@ static wchar_t c2u_CF[256] = {
0x8A6D,0x8ECC,0x994B,0xF906,0x6677,0x6B78,0x8CB4,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_D0[256] = {
+static const wchar_t c2u_D0[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2813,7 +2813,7 @@ static wchar_t c2u_D0[256] = {
0x5D0E,0x5DF1,0x5E7E,0x5FCC,0x6280,0x65D7,0x65E3,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_D1[256] = {
+static const wchar_t c2u_D1[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2849,7 +2849,7 @@ static wchar_t c2u_D1[256] = {
0x6960,0x6E73,0xF922,0x7537,0xF923,0xF924,0xF925,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_D2[256] = {
+static const wchar_t c2u_D2[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2885,7 +2885,7 @@ static wchar_t c2u_D2[256] = {
0xF959,0x5C3C,0x6CE5,0x533F,0x6EBA,0x591A,0x8336,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_D3[256] = {
+static const wchar_t c2u_D3[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2921,7 +2921,7 @@ static wchar_t c2u_D3[256] = {
0x5EA6,0x5F92,0x60BC,0x6311,0x6389,0x6417,0x6843,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_D4[256] = {
+static const wchar_t c2u_D4[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2957,7 +2957,7 @@ static wchar_t c2u_D4[256] = {
0x9127,0x9A30,0x5587,0x61F6,0xF95B,0x7669,0x7F85,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_D5[256] = {
+static const wchar_t c2u_D5[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2993,7 +2993,7 @@ static wchar_t c2u_D5[256] = {
0x792B,0x8F62,0x9742,0x6190,0x6200,0x6523,0x6F23,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_D6[256] = {
+static const wchar_t c2u_D6[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3029,7 +3029,7 @@ static wchar_t c2u_D6[256] = {
0x5ED6,0x6599,0x71CE,0x7642,0x77AD,0x804A,0x84FC,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_D7[256] = {
+static const wchar_t c2u_D7[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3065,7 +3065,7 @@ static wchar_t c2u_D7[256] = {
0x9E9F,0x6797,0x6DCB,0x7433,0x81E8,0x9716,0x782C,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_D8[256] = {
+static const wchar_t c2u_D8[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3101,7 +3101,7 @@ static wchar_t c2u_D8[256] = {
0x7704,0x7720,0x7DBF,0x7DEC,0x9762,0x9EB5,0x6EC5,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_D9[256] = {
+static const wchar_t c2u_D9[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3137,7 +3137,7 @@ static wchar_t c2u_D9[256] = {
0x58A8,0x9ED8,0x5011,0x520E,0x543B,0x554F,0x6587,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_DA[256] = {
+static const wchar_t c2u_DA[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3173,7 +3173,7 @@ static wchar_t c2u_DA[256] = {
0x9812,0x98EF,0x52C3,0x62D4,0x64A5,0x6E24,0x6F51,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_DB[256] = {
+static const wchar_t c2u_DB[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3209,7 +3209,7 @@ static wchar_t c2u_DB[256] = {
0x50FB,0x5288,0x58C1,0x64D8,0x6A97,0x74A7,0x7656,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_DC[256] = {
+static const wchar_t c2u_DC[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3245,7 +3245,7 @@ static wchar_t c2u_DC[256] = {
0x5256,0x526F,0x5426,0x5490,0x57E0,0x592B,0x5A66,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_DD[256] = {
+static const wchar_t c2u_DD[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3281,7 +3281,7 @@ static wchar_t c2u_DD[256] = {
0x7891,0x79D5,0x79D8,0x7C83,0x7DCB,0x7FE1,0x80A5,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_DE[256] = {
+static const wchar_t c2u_DE[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3317,7 +3317,7 @@ static wchar_t c2u_DE[256] = {
0x98FC,0x99DF,0x9E9D,0x524A,0xF969,0x6714,0xF96A,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_DF[256] = {
+static const wchar_t c2u_DF[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3353,7 +3353,7 @@ static wchar_t c2u_DF[256] = {
0x68F2,0x7280,0x745E,0x7B6E,0x7D6E,0x7DD6,0x7F72,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E0[256] = {
+static const wchar_t c2u_E0[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3389,7 +3389,7 @@ static wchar_t c2u_E0[256] = {
0x661F,0x665F,0x7329,0x73F9,0x76DB,0x7701,0x7B6C,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E1[256] = {
+static const wchar_t c2u_E1[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3425,7 +3425,7 @@ static wchar_t c2u_E1[256] = {
0x58FD,0x5AC2,0x5B88,0x5CAB,0x5CC0,0x5E25,0x6101,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E2[256] = {
+static const wchar_t c2u_E2[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3461,7 +3461,7 @@ static wchar_t c2u_E2[256] = {
0x99B4,0x620C,0x8853,0x8FF0,0x9265,0x5D07,0x5D27,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E3[256] = {
+static const wchar_t c2u_E3[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3497,7 +3497,7 @@ static wchar_t c2u_E3[256] = {
0x5BA4,0x5BE6,0x6089,0x5BE9,0x5C0B,0x5FC3,0x6C81,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E4[256] = {
+static const wchar_t c2u_E4[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3533,7 +3533,7 @@ static wchar_t c2u_E4[256] = {
0x5384,0x627C,0x6396,0x6DB2,0x7E0A,0x814B,0x984D,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E5[256] = {
+static const wchar_t c2u_E5[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3569,7 +3569,7 @@ static wchar_t c2u_E5[256] = {
0x4E88,0x4F59,0xF97F,0xF980,0xF981,0x5982,0xF982,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E6[256] = {
+static const wchar_t c2u_E6[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3605,7 +3605,7 @@ static wchar_t c2u_E6[256] = {
0x67D3,0xF9A5,0x708E,0x7130,0x7430,0x8276,0x82D2,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E7[256] = {
+static const wchar_t c2u_E7[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3641,7 +3641,7 @@ static wchar_t c2u_E7[256] = {
0x61CA,0x6556,0x65FF,0x6664,0x68A7,0x6C5A,0x6FB3,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E8[256] = {
+static const wchar_t c2u_E8[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3677,7 +3677,7 @@ static wchar_t c2u_E8[256] = {
0x66DC,0xF9BF,0x6A48,0xF9C0,0x71FF,0x7464,0xF9C1,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E9[256] = {
+static const wchar_t c2u_E9[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3713,7 +3713,7 @@ static wchar_t c2u_E9[256] = {
0x6A52,0x6B9E,0x6F90,0x7189,0x8018,0x82B8,0x8553,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_EA[256] = {
+static const wchar_t c2u_EA[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3749,7 +3749,7 @@ static wchar_t c2u_EA[256] = {
0x6961,0x6962,0x6CB9,0x6D27,0xF9CA,0x6E38,0xF9CB,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_EB[256] = {
+static const wchar_t c2u_EB[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3785,7 +3785,7 @@ static wchar_t c2u_EB[256] = {
0x77E3,0x7FA9,0x8264,0x858F,0x87FB,0x8863,0x8ABC,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_EC[256] = {
+static const wchar_t c2u_EC[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3821,7 +3821,7 @@ static wchar_t c2u_EC[256] = {
0xF9F5,0x7A14,0xF9F6,0x834F,0x8CC3,0x5165,0x5344,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_ED[256] = {
+static const wchar_t c2u_ED[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3857,7 +3857,7 @@ static wchar_t c2u_ED[256] = {
0x8523,0x8594,0x85CF,0x88DD,0x8D13,0x91AC,0x9577,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_EE[256] = {
+static const wchar_t c2u_EE[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3893,7 +3893,7 @@ static wchar_t c2u_EE[256] = {
0x5EDB,0x609B,0x6230,0x6813,0x6BBF,0x6C08,0x6FB1,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_EF[256] = {
+static const wchar_t c2u_EF[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3929,7 +3929,7 @@ static wchar_t c2u_EF[256] = {
0x914A,0x91D8,0x9266,0x92CC,0x9320,0x9706,0x9756,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_F0[256] = {
+static const wchar_t c2u_F0[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3965,7 +3965,7 @@ static wchar_t c2u_F0[256] = {
0x6DD9,0x742E,0x7A2E,0x7D42,0x7D9C,0x7E31,0x816B,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_F1[256] = {
+static const wchar_t c2u_F1[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -4001,7 +4001,7 @@ static wchar_t c2u_F1[256] = {
0x75C7,0x7E52,0x84B8,0x8B49,0x8D08,0x4E4B,0x53EA,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_F2[256] = {
+static const wchar_t c2u_F2[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -4037,7 +4037,7 @@ static wchar_t c2u_F2[256] = {
0x659F,0x6715,0xF9FD,0x57F7,0x6F57,0x7DDD,0x8F2F,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_F3[256] = {
+static const wchar_t c2u_F3[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -4073,7 +4073,7 @@ static wchar_t c2u_F3[256] = {
0x83DC,0x8521,0x91C7,0x91F5,0x518A,0x67F5,0x7B56,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_F4[256] = {
+static const wchar_t c2u_F4[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -4109,7 +4109,7 @@ static wchar_t c2u_F4[256] = {
0x521D,0x527F,0x54E8,0x6194,0x6284,0x62DB,0x68A2,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_F5[256] = {
+static const wchar_t c2u_F5[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -4145,7 +4145,7 @@ static wchar_t c2u_F5[256] = {
0x6C96,0x87F2,0x885D,0x8877,0x60B4,0x81B5,0x8403,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_F6[256] = {
+static const wchar_t c2u_F6[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -4181,7 +4181,7 @@ static wchar_t c2u_F6[256] = {
0x666B,0x67DD,0x6FC1,0x6FEF,0x7422,0x7438,0x8A17,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_F7[256] = {
+static const wchar_t c2u_F7[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -4217,7 +4217,7 @@ static wchar_t c2u_F7[256] = {
0x5742,0x677F,0x7248,0x74E3,0x8CA9,0x8FA6,0x9211,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_F8[256] = {
+static const wchar_t c2u_F8[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -4253,7 +4253,7 @@ static wchar_t c2u_F8[256] = {
0x74E2,0x7968,0x8868,0x8C79,0x98C7,0x98C4,0x9A43,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_F9[256] = {
+static const wchar_t c2u_F9[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -4289,7 +4289,7 @@ static wchar_t c2u_F9[256] = {
0x676D,0x6841,0x6C86,0x6E2F,0x7F38,0x809B,0x822A,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_FA[256] = {
+static const wchar_t c2u_FA[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -4325,7 +4325,7 @@ static wchar_t c2u_FA[256] = {
0x83A2,0x92CF,0x9830,0x4EA8,0x5144,0x5211,0x578B,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_FB[256] = {
+static const wchar_t c2u_FB[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -4361,7 +4361,7 @@ static wchar_t c2u_FB[256] = {
0x9D3B,0x5316,0x548C,0x5B05,0x6A3A,0x706B,0x7575,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_FC[256] = {
+static const wchar_t c2u_FC[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -4397,7 +4397,7 @@ static wchar_t c2u_FC[256] = {
0x5B5D,0x6548,0x6585,0x66C9,0x689F,0x6D8D,0x6DC6,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_FD[256] = {
+static const wchar_t c2u_FD[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -4433,7 +4433,7 @@ static wchar_t c2u_FD[256] = {
0x71B9,0x71BA,0x72A7,0x79A7,0x7A00,0x7FB2,0x8A70,0x0000,/* 0xF8-0xFF */
};
-static wchar_t *page_charset2uni[256] = {
+static const wchar_t *page_charset2uni[256] = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -4468,7 +4468,7 @@ static wchar_t *page_charset2uni[256] = {
c2u_F8, c2u_F9, c2u_FA, c2u_FB, c2u_FC, c2u_FD, NULL, NULL,
};
-static unsigned char u2c_01[512] = {
+static const unsigned char u2c_01[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -4497,7 +4497,7 @@ static unsigned char u2c_01[512] = {
0x00, 0x00, 0x00, 0x00, 0xA8, 0xAE, 0xA9, 0xAE, /* 0x64-0x67 */
};
-static unsigned char u2c_02[512] = {
+static const unsigned char u2c_02[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -4557,7 +4557,7 @@ static unsigned char u2c_02[512] = {
0x00, 0x00, 0xA2, 0xA9, 0x00, 0x00, 0x00, 0x00, /* 0xDC-0xDF */
};
-static unsigned char u2c_03[512] = {
+static const unsigned char u2c_03[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -4612,7 +4612,7 @@ static unsigned char u2c_03[512] = {
0xA5, 0xF7, 0xA5, 0xF8, 0x00, 0x00, 0x00, 0x00, /* 0xC8-0xCB */
};
-static unsigned char u2c_04[512] = {
+static const unsigned char u2c_04[512] = {
0x00, 0x00, 0xAC, 0xA7, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -4636,7 +4636,7 @@ static unsigned char u2c_04[512] = {
0x00, 0x00, 0xAC, 0xD7, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x53 */
};
-static unsigned char u2c_11[512] = {
+static const unsigned char u2c_11[512] = {
0xA4, 0xA1, 0xA4, 0xA2, 0xA4, 0xA4, 0xA4, 0xA7, /* 0x00-0x03 */
0xA4, 0xA8, 0xA4, 0xA9, 0xA4, 0xB1, 0xA4, 0xB2, /* 0x04-0x07 */
0xA4, 0xB3, 0xA4, 0xB5, 0xA4, 0xB6, 0xA4, 0xB7, /* 0x08-0x0B */
@@ -4703,7 +4703,7 @@ static unsigned char u2c_11[512] = {
0x00, 0x00, 0xA4, 0xF6, 0x00, 0x00, 0x00, 0x00, /* 0xF8-0xFB */
};
-static unsigned char u2c_20[512] = {
+static const unsigned char u2c_20[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -4750,7 +4750,7 @@ static unsigned char u2c_20[512] = {
0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x00, /* 0xA8-0xAB */
};
-static unsigned char u2c_21[512] = {
+static const unsigned char u2c_21[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xC9, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0xA2, 0xB5, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -4808,7 +4808,7 @@ static unsigned char u2c_21[512] = {
0xA2, 0xA2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xD4-0xD7 */
};
-static unsigned char u2c_22[512] = {
+static const unsigned char u2c_22[512] = {
0xA2, 0xA3, 0x00, 0x00, 0xA1, 0xD3, 0xA2, 0xA4, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xD4, /* 0x04-0x07 */
0xA1, 0xF4, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xF5, /* 0x08-0x0B */
@@ -4854,7 +4854,7 @@ static unsigned char u2c_22[512] = {
0x00, 0x00, 0xA1, 0xD1, 0x00, 0x00, 0x00, 0x00, /* 0xA4-0xA7 */
};
-static unsigned char u2c_23[512] = {
+static const unsigned char u2c_23[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -4862,7 +4862,7 @@ static unsigned char u2c_23[512] = {
0x00, 0x00, 0x00, 0x00, 0xA1, 0xD2, 0x00, 0x00, /* 0x10-0x13 */
};
-static unsigned char u2c_24[512] = {
+static const unsigned char u2c_24[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -4925,7 +4925,7 @@ static unsigned char u2c_24[512] = {
0xA8, 0xE5, 0xA8, 0xE6, 0x00, 0x00, 0x00, 0x00, /* 0xE8-0xEB */
};
-static unsigned char u2c_25[512] = {
+static const unsigned char u2c_25[512] = {
0xA6, 0xA1, 0xA6, 0xAC, 0xA6, 0xA2, 0xA6, 0xAD, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -4982,7 +4982,7 @@ static unsigned char u2c_25[512] = {
0xA2, 0xC4, 0xA2, 0xC5, 0x00, 0x00, 0x00, 0x00, /* 0xD0-0xD3 */
};
-static unsigned char u2c_26[512] = {
+static const unsigned char u2c_26[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0xA1, 0xDA, 0xA1, 0xD9, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -5013,7 +5013,7 @@ static unsigned char u2c_26[512] = {
0xA2, 0xDD, 0xA2, 0xDA, 0x00, 0x00, 0x00, 0x00, /* 0x6C-0x6F */
};
-static unsigned char u2c_30[512] = {
+static const unsigned char u2c_30[512] = {
0xA1, 0xA1, 0xA1, 0xA2, 0xA1, 0xA3, 0xA1, 0xA8, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0xA1, 0xB4, 0xA1, 0xB5, 0xA1, 0xB6, 0xA1, 0xB7, /* 0x08-0x0B */
@@ -5079,7 +5079,7 @@ static unsigned char u2c_30[512] = {
0xAB, 0xF4, 0xAB, 0xF5, 0xAB, 0xF6, 0x00, 0x00, /* 0xF4-0xF7 */
};
-static unsigned char u2c_31[512] = {
+static const unsigned char u2c_31[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -5123,7 +5123,7 @@ static unsigned char u2c_31[512] = {
0xEF, 0xCB, 0xF4, 0xB8, 0xF2, 0xA2, 0xEC, 0xD1, /* 0x9C-0x9F */
};
-static unsigned char u2c_32[512] = {
+static const unsigned char u2c_32[512] = {
0xA9, 0xB1, 0xA9, 0xB2, 0xA9, 0xB3, 0xA9, 0xB4, /* 0x00-0x03 */
0xA9, 0xB5, 0xA9, 0xB6, 0xA9, 0xB7, 0xA9, 0xB8, /* 0x04-0x07 */
0xA9, 0xB9, 0xA9, 0xBA, 0xA9, 0xBB, 0xA9, 0xBC, /* 0x08-0x0B */
@@ -5172,7 +5172,7 @@ static unsigned char u2c_32[512] = {
0xE5, 0xA8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xB0-0xB3 */
};
-static unsigned char u2c_33[512] = {
+static const unsigned char u2c_33[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -5232,7 +5232,7 @@ static unsigned char u2c_33[512] = {
0xA7, 0xEE, 0xA7, 0xE9, 0x00, 0x00, 0x00, 0x00, /* 0xDC-0xDF */
};
-static unsigned char u2c_4E[512] = {
+static const unsigned char u2c_4E[512] = {
0xEC, 0xE9, 0xEF, 0xCB, 0x00, 0x00, 0xF6, 0xD2, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0xB2, /* 0x04-0x07 */
0xED, 0xDB, 0xDF, 0xB2, 0xDF, 0xBE, 0xF9, 0xBB, /* 0x08-0x0B */
@@ -5299,7 +5299,7 @@ static unsigned char u2c_4E[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0xF2, /* 0xF8-0xFB */
};
-static unsigned char u2c_4F[512] = {
+static const unsigned char u2c_4F[512] = {
0x00, 0x00, 0xD0, 0xEA, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0xF9, 0xF2, 0xEC, 0xA5, 0xD0, 0xDF, /* 0x08-0x0B */
@@ -5366,7 +5366,7 @@ static unsigned char u2c_4F[512] = {
0xDC, 0xE4, 0x00, 0x00, 0xE5, 0xEF, 0x00, 0x00, /* 0xF8-0xFB */
};
-static unsigned char u2c_50[512] = {
+static const unsigned char u2c_50[512] = {
0x00, 0x00, 0x00, 0x00, 0xDC, 0xB1, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0xD5, 0xD6, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0xF3, 0xDA, 0x00, 0x00, 0xCB, 0xC1, /* 0x08-0x0B */
@@ -5434,7 +5434,7 @@ static unsigned char u2c_50[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDE, 0xC7, /* 0xFC-0xFF */
};
-static unsigned char u2c_51[512] = {
+static const unsigned char u2c_51[512] = {
0xEB, 0xF0, 0xF1, 0xD6, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0xE5, 0xE2, 0x00, 0x00, 0xCC, 0xCC, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0xCB, 0xFB, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -5502,7 +5502,7 @@ static unsigned char u2c_51[512] = {
0x00, 0x00, 0xF9, 0xDE, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_52[512] = {
+static const unsigned char u2c_52[512] = {
0xD3, 0xEF, 0x00, 0x00, 0x00, 0x00, 0xEC, 0xD3, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0xDD, 0xC2, 0xEF, 0xB7, /* 0x04-0x07 */
0xE7, 0xD4, 0x00, 0x00, 0xCA, 0xCA, 0x00, 0x00, /* 0x08-0x0B */
@@ -5570,7 +5570,7 @@ static unsigned char u2c_52[512] = {
0x00, 0x00, 0x00, 0x00, 0xCE, 0xFE, 0xDA, 0xA8, /* 0xFC-0xFF */
};
-static unsigned char u2c_53[512] = {
+static const unsigned char u2c_53[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0xF8, 0xD0, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0xFD, 0xD6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -5637,7 +5637,7 @@ static unsigned char u2c_53[512] = {
0xDE, 0xC9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xF8-0xFB */
};
-static unsigned char u2c_54[512] = {
+static const unsigned char u2c_54[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xDE, /* 0x00-0x03 */
0xCA, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0xF9, 0xEA, 0xD1, 0xCE, 0xEE, 0xD4, 0x00, 0x00, /* 0x08-0x0B */
@@ -5704,7 +5704,7 @@ static unsigned char u2c_54[512] = {
0x00, 0x00, 0x00, 0x00, 0xF8, 0xD4, 0x00, 0x00, /* 0xF8-0xFB */
};
-static unsigned char u2c_55[512] = {
+static const unsigned char u2c_55[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0xF8, 0xA6, 0x00, 0x00, 0xDE, 0xCA, 0xF2, 0xC6, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -5772,7 +5772,7 @@ static unsigned char u2c_55[512] = {
0x00, 0x00, 0xE1, 0xF5, 0xF1, 0xB3, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_56[512] = {
+static const unsigned char u2c_56[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0xF7, 0xA3, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0xCA, 0xA9, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -5839,7 +5839,7 @@ static unsigned char u2c_56[512] = {
0x00, 0x00, 0xD6, 0xB7, 0xCD, 0xB3, 0x00, 0x00, /* 0xF8-0xFB */
};
-static unsigned char u2c_57[512] = {
+static const unsigned char u2c_57[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xD5, /* 0x00-0x03 */
0xE5, 0xD8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0xCF, 0xEA, 0x00, 0x00, 0x00, 0x00, 0xCF, 0xD0, /* 0x08-0x0B */
@@ -5907,7 +5907,7 @@ static unsigned char u2c_57[512] = {
0xD0, 0xF2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_58[512] = {
+static const unsigned char u2c_58[512] = {
0xCF, 0xDC, 0x00, 0x00, 0xD3, 0xD1, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0xCC, 0xB1, 0xF7, 0xD8, 0x00, 0x00, /* 0x04-0x07 */
0xCB, 0xA8, 0xEB, 0xBC, 0xE4, 0xBE, 0x00, 0x00, /* 0x08-0x0B */
@@ -5975,7 +5975,7 @@ static unsigned char u2c_58[512] = {
0x00, 0x00, 0xE1, 0xF8, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_59[512] = {
+static const unsigned char u2c_59[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -6043,7 +6043,7 @@ static unsigned char u2c_59[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xED, 0xAC, /* 0xFC-0xFF */
};
-static unsigned char u2c_5A[512] = {
+static const unsigned char u2c_5A[512] = {
0x00, 0x00, 0xEA, 0xCE, 0x00, 0x00, 0xE8, 0xDF, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -6106,7 +6106,7 @@ static unsigned char u2c_5A[512] = {
0x00, 0x00, 0xD2, 0xEC, 0x00, 0x00, 0x00, 0x00, /* 0xE8-0xEB */
};
-static unsigned char u2c_5B[512] = {
+static const unsigned char u2c_5B[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0xFB, 0xFB, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0xFD, 0xF0, 0x00, 0x00, 0xE0, 0xBD, /* 0x08-0x0B */
@@ -6173,7 +6173,7 @@ static unsigned char u2c_5B[512] = {
0xF5, 0xBB, 0x00, 0x00, 0xDE, 0xD1, 0x00, 0x00, /* 0xF8-0xFB */
};
-static unsigned char u2c_5C[512] = {
+static const unsigned char u2c_5C[512] = {
0x00, 0x00, 0xDC, 0xE6, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0xDE, 0xD2, 0x00, 0x00, 0x00, 0x00, 0xED, 0xE2, /* 0x04-0x07 */
0xEE, 0xF6, 0xEA, 0xCF, 0xF0, 0xEE, 0xE3, 0xFC, /* 0x08-0x0B */
@@ -6241,7 +6241,7 @@ static unsigned char u2c_5C[512] = {
0x00, 0x00, 0xFA, 0xF2, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_5D[512] = {
+static const unsigned char u2c_5D[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE2, 0xFD, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -6309,7 +6309,7 @@ static unsigned char u2c_5D[512] = {
0x00, 0x00, 0xE1, 0xDE, 0xCB, 0xEE, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_5E[512] = {
+static const unsigned char u2c_5E[512] = {
0x00, 0x00, 0x00, 0x00, 0xE3, 0xBC, 0xF8, 0xD6, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0xDB, 0xEE, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -6376,7 +6376,7 @@ static unsigned char u2c_5E[512] = {
0x00, 0x00, 0x00, 0x00, 0xCB, 0xEF, 0xFC, 0xDF, /* 0xF8-0xFB */
};
-static unsigned char u2c_5F[512] = {
+static const unsigned char u2c_5F[512] = {
0x00, 0x00, 0xDC, 0xA7, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0xD6, 0xE7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0xF8, 0xC9, 0x00, 0x00, /* 0x08-0x0B */
@@ -6444,7 +6444,7 @@ static unsigned char u2c_5F[512] = {
0x00, 0x00, 0xFB, 0xEC, 0x00, 0x00, 0xDD, 0xC8, /* 0xFC-0xFF */
};
-static unsigned char u2c_60[512] = {
+static const unsigned char u2c_60[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -6511,7 +6511,7 @@ static unsigned char u2c_60[512] = {
0x00, 0x00, 0xE5, 0xA9, 0xE0, 0xF6, 0xF6, 0xB3, /* 0xF8-0xFB */
};
-static unsigned char u2c_61[512] = {
+static const unsigned char u2c_61[512] = {
0x00, 0x00, 0xE1, 0xFE, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0xCB, 0xF0, 0x00, 0x00, /* 0x04-0x07 */
0xEA, 0xEF, 0xEA, 0xF0, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -6579,7 +6579,7 @@ static unsigned char u2c_61[512] = {
0xCF, 0xAB, 0x00, 0x00, 0x00, 0x00, 0xEB, 0xF3, /* 0xFC-0xFF */
};
-static unsigned char u2c_62[512] = {
+static const unsigned char u2c_62[512] = {
0xD5, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD3, 0xD4, /* 0x04-0x07 */
0xCD, 0xFC, 0x00, 0x00, 0xD9, 0xE6, 0x00, 0x00, /* 0x08-0x0B */
@@ -6647,7 +6647,7 @@ static unsigned char u2c_62[512] = {
0x00, 0x00, 0x00, 0x00, 0xE3, 0xA6, 0xD1, 0xDA, /* 0xFC-0xFF */
};
-static unsigned char u2c_63[512] = {
+static const unsigned char u2c_63[512] = {
0x00, 0x00, 0xF2, 0xA5, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF2, 0xA6, /* 0x04-0x07 */
0x00, 0x00, 0xE4, 0xCE, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -6713,7 +6713,7 @@ static unsigned char u2c_63[512] = {
0xEA, 0xB5, 0x00, 0x00, 0xE5, 0xAA, 0xDF, 0xBA, /* 0xF4-0xF7 */
};
-static unsigned char u2c_64[512] = {
+static const unsigned char u2c_64[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -6781,7 +6781,7 @@ static unsigned char u2c_64[512] = {
0x00, 0x00, 0x00, 0x00, 0xE8, 0xF6, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_65[512] = {
+static const unsigned char u2c_65[512] = {
0xDA, 0xE7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0xF7, 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -6849,7 +6849,7 @@ static unsigned char u2c_65[512] = {
0xDA, 0xC4, 0xD4, 0xC5, 0x00, 0x00, 0xE7, 0xFA, /* 0xFC-0xFF */
};
-static unsigned char u2c_66[512] = {
+static const unsigned char u2c_66[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0xCD, 0xE0, 0xE3, 0xB0, /* 0x04-0x07 */
0x00, 0x00, 0xDB, 0xB2, 0xFB, 0xC4, 0x00, 0x00, /* 0x08-0x0B */
@@ -6917,7 +6917,7 @@ static unsigned char u2c_66[512] = {
0xD8, 0xBA, 0x00, 0x00, 0xF1, 0xF4, 0xF4, 0xF0, /* 0xFC-0xFF */
};
-static unsigned char u2c_67[512] = {
+static const unsigned char u2c_67[512] = {
0xF5, 0xCC, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xE5, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0xEA, 0xC5, 0xEA, 0xF3, 0x00, 0x00, 0xDD, 0xDB, /* 0x08-0x0B */
@@ -6985,7 +6985,7 @@ static unsigned char u2c_67[512] = {
0x00, 0x00, 0x00, 0x00, 0xEF, 0xDE, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_68[512] = {
+static const unsigned char u2c_68[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -7052,7 +7052,7 @@ static unsigned char u2c_68[512] = {
0x00, 0x00, 0xD4, 0xA1, 0xCE, 0xB2, 0x00, 0x00, /* 0xF8-0xFB */
};
-static unsigned char u2c_69[512] = {
+static const unsigned char u2c_69[512] = {
0xE8, 0xCA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0xEB, 0xF5, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -7120,7 +7120,7 @@ static unsigned char u2c_69[512] = {
0x00, 0x00, 0xF0, 0xCB, 0x00, 0x00, 0xD0, 0xC7, /* 0xFC-0xFF */
};
-static unsigned char u2c_6A[512] = {
+static const unsigned char u2c_6A[512] = {
0x00, 0x00, 0x00, 0x00, 0xE4, 0xC5, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0xDB, 0xE0, 0x00, 0x00, /* 0x08-0x0B */
@@ -7187,7 +7187,7 @@ static unsigned char u2c_6A[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE5, 0xA1, /* 0xF8-0xFB */
};
-static unsigned char u2c_6B[512] = {
+static const unsigned char u2c_6B[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0xD5, 0xB1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0xCF, 0xED, 0x00, 0x00, /* 0x08-0x0B */
@@ -7251,7 +7251,7 @@ static unsigned char u2c_6B[512] = {
0xCF, 0xB3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xEC-0xEF */
};
-static unsigned char u2c_6C[512] = {
+static const unsigned char u2c_6C[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0xEE, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -7316,7 +7316,7 @@ static unsigned char u2c_6C[512] = {
0xF7, 0xC1, 0x00, 0x00, 0x00, 0x00, 0xE7, 0xB6, /* 0xF0-0xF3 */
};
-static unsigned char u2c_6D[512] = {
+static const unsigned char u2c_6D[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE5, 0xC7, /* 0x08-0x0B */
@@ -7383,7 +7383,7 @@ static unsigned char u2c_6D[512] = {
0xF4, 0xE8, 0xE5, 0xF4, 0xF4, 0xBC, 0xF4, 0xD5, /* 0xF8-0xFB */
};
-static unsigned char u2c_6E[512] = {
+static const unsigned char u2c_6E[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -7451,7 +7451,7 @@ static unsigned char u2c_6E[512] = {
0x00, 0x00, 0x00, 0x00, 0xCD, 0xE3, 0xD8, 0xBB, /* 0xFC-0xFF */
};
-static unsigned char u2c_6F[512] = {
+static const unsigned char u2c_6F[512] = {
0x00, 0x00, 0xE5, 0xDB, 0xF8, 0xF7, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0xF6, 0xD4, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -7519,7 +7519,7 @@ static unsigned char u2c_6F[512] = {
0x00, 0x00, 0x00, 0x00, 0xD5, 0xEB, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_70[512] = {
+static const unsigned char u2c_70[512] = {
0x00, 0x00, 0xE5, 0xC8, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0xFB, 0xA4, 0xD4, 0xB9, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0xDE, 0xE1, 0x00, 0x00, 0xE4, 0xA3, /* 0x08-0x0B */
@@ -7587,7 +7587,7 @@ static unsigned char u2c_70[512] = {
0x00, 0x00, 0xDC, 0xEB, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_71[512] = {
+static const unsigned char u2c_71[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0xFD, 0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0xE5, 0xEA, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -7655,7 +7655,7 @@ static unsigned char u2c_71[512] = {
0xE3, 0xE8, 0x00, 0x00, 0xD4, 0xA7, 0xE8, 0xFC, /* 0xFC-0xFF */
};
-static unsigned char u2c_72[512] = {
+static const unsigned char u2c_72[512] = {
0xFA, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0xF8, 0xEF, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -7723,7 +7723,7 @@ static unsigned char u2c_72[512] = {
0xD5, 0xC9, 0xF8, 0xAC, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_73[512] = {
+static const unsigned char u2c_73[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0xE7, 0xD9, 0x00, 0x00, /* 0x08-0x0B */
@@ -7791,7 +7791,7 @@ static unsigned char u2c_73[512] = {
0x00, 0x00, 0xEF, 0xEA, 0xFA, 0xDE, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_74[512] = {
+static const unsigned char u2c_74[512] = {
0x00, 0x00, 0xE0, 0xC4, 0x00, 0x00, 0xCF, 0xB9, /* 0x00-0x03 */
0x00, 0x00, 0xD5, 0xCA, 0xD7, 0xE2, 0xE2, 0xAF, /* 0x04-0x07 */
0x00, 0x00, 0xD7, 0xB8, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -7857,7 +7857,7 @@ static unsigned char u2c_74[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xED, 0xB6, /* 0xF4-0xF7 */
};
-static unsigned char u2c_75[512] = {
+static const unsigned char u2c_75[512] = {
0x00, 0x00, 0xDC, 0xBA, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0xCC, 0xB4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -7925,7 +7925,7 @@ static unsigned char u2c_75[512] = {
0xCD, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_76[512] = {
+static const unsigned char u2c_76[512] = {
0xE5, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -7993,7 +7993,7 @@ static unsigned char u2c_76[512] = {
0xDA, 0xF0, 0x00, 0x00, 0xE2, 0xEA, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_77[512] = {
+static const unsigned char u2c_77[512] = {
0x00, 0x00, 0xE0, 0xFD, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0xD8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0xF7, 0xAF, 0xDA, 0xB6, 0x00, 0x00, 0xCA, 0xD7, /* 0x08-0x0B */
@@ -8058,7 +8058,7 @@ static unsigned char u2c_77[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xB4, /* 0xF0-0xF3 */
};
-static unsigned char u2c_78[512] = {
+static const unsigned char u2c_78[512] = {
0x00, 0x00, 0x00, 0x00, 0xDE, 0xE3, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -8125,7 +8125,7 @@ static unsigned char u2c_78[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDA, 0xF2, /* 0xF8-0xFB */
};
-static unsigned char u2c_79[512] = {
+static const unsigned char u2c_79[512] = {
0x00, 0x00, 0xF5, 0xA7, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -8192,7 +8192,7 @@ static unsigned char u2c_79[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0xB9, /* 0xF8-0xFB */
};
-static unsigned char u2c_7A[512] = {
+static const unsigned char u2c_7A[512] = {
0xFD, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0xE1, 0xAA, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0xCA, 0xD9, 0x00, 0x00, 0x00, 0x00, 0xEF, 0xEF, /* 0x08-0x0B */
@@ -8260,7 +8260,7 @@ static unsigned char u2c_7A[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCA, 0xDA, /* 0xFC-0xFF */
};
-static unsigned char u2c_7B[512] = {
+static const unsigned char u2c_7B[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -8323,7 +8323,7 @@ static unsigned char u2c_7B[512] = {
0x00, 0x00, 0xDE, 0xE8, 0x00, 0x00, 0x00, 0x00, /* 0xE8-0xEB */
};
-static unsigned char u2c_7C[512] = {
+static const unsigned char u2c_7C[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xEA, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -8391,7 +8391,7 @@ static unsigned char u2c_7C[512] = {
0x00, 0x00, 0x00, 0x00, 0xD0, 0xAC, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_7D[512] = {
+static const unsigned char u2c_7D[512] = {
0xD1, 0xBA, 0x00, 0x00, 0xF1, 0xC4, 0x00, 0x00, /* 0x00-0x03 */
0xE5, 0xB3, 0xFB, 0xF5, 0xE9, 0xE1, 0xFD, 0xE0, /* 0x04-0x07 */
0xFC, 0xBC, 0x00, 0x00, 0xDA, 0xA2, 0xDA, 0xA3, /* 0x08-0x0B */
@@ -8458,7 +8458,7 @@ static unsigned char u2c_7D[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF6, 0xC6, /* 0xF8-0xFB */
};
-static unsigned char u2c_7E[512] = {
+static const unsigned char u2c_7E[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0xF2, 0xDB, 0xE4, 0xFC, 0x00, 0x00, /* 0x08-0x0B */
@@ -8502,7 +8502,7 @@ static unsigned char u2c_7E[512] = {
0xD5, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9C-0x9F */
};
-static unsigned char u2c_7F[512] = {
+static const unsigned char u2c_7F[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -8570,7 +8570,7 @@ static unsigned char u2c_7F[512] = {
0xEC, 0xCF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_80[512] = {
+static const unsigned char u2c_80[512] = {
0xE9, 0xA5, 0xD6, 0xD5, 0x00, 0x00, 0xCD, 0xC5, /* 0x00-0x03 */
0x00, 0x00, 0xED, 0xBA, 0xD1, 0xBD, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0xCF, 0xBE, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -8638,7 +8638,7 @@ static unsigned char u2c_80[512] = {
0x00, 0x00, 0xD2, 0xF6, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_81[512] = {
+static const unsigned char u2c_81[512] = {
0x00, 0x00, 0x00, 0x00, 0xF2, 0xB7, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0xFA, 0xF6, 0xF6, 0xAA, 0xFA, 0xF7, /* 0x04-0x07 */
0xD8, 0xE6, 0x00, 0x00, 0xF4, 0xB1, 0x00, 0x00, /* 0x08-0x0B */
@@ -8706,7 +8706,7 @@ static unsigned char u2c_81[512] = {
0xCF, 0xBF, 0x00, 0x00, 0xEB, 0xAC, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_82[512] = {
+static const unsigned char u2c_82[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0xCF, 0xC0, 0x00, 0x00, 0xE6, 0xA8, /* 0x04-0x07 */
0xFD, 0xE9, 0x00, 0x00, 0xCF, 0xC1, 0x00, 0x00, /* 0x08-0x0B */
@@ -8774,7 +8774,7 @@ static unsigned char u2c_82[512] = {
0x00, 0x00, 0xCD, 0xC9, 0xF9, 0xB7, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_83[512] = {
+static const unsigned char u2c_83[512] = {
0x00, 0x00, 0xF1, 0xE8, 0xD9, 0xF2, 0xDB, 0xF5, /* 0x00-0x03 */
0xCA, 0xB5, 0xD9, 0xC6, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0xD8, 0xC9, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -8842,7 +8842,7 @@ static unsigned char u2c_83[512] = {
0x00, 0x00, 0xE2, 0xDD, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_84[512] = {
+static const unsigned char u2c_84[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF5, 0xFE, /* 0x00-0x03 */
0xD4, 0xAC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0xD5, 0xD1, 0x00, 0x00, /* 0x08-0x0B */
@@ -8910,7 +8910,7 @@ static unsigned char u2c_84[512] = {
0xD6, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_85[512] = {
+static const unsigned char u2c_85[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -8978,7 +8978,7 @@ static unsigned char u2c_85[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE, 0xAB, /* 0xFC-0xFF */
};
-static unsigned char u2c_86[512] = {
+static const unsigned char u2c_86[512] = {
0x00, 0x00, 0x00, 0x00, 0xE7, 0xDE, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0xD6, 0xD6, 0xE1, 0xCC, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0xE8, 0xB3, 0x00, 0x00, /* 0x08-0x0B */
@@ -9046,7 +9046,7 @@ static unsigned char u2c_86[512] = {
0x00, 0x00, 0x00, 0x00, 0xE4, 0xB6, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_87[512] = {
+static const unsigned char u2c_87[512] = {
0xF5, 0xB9, 0x00, 0x00, 0xDC, 0xF0, 0xE3, 0xF1, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0xE8, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -9114,7 +9114,7 @@ static unsigned char u2c_87[512] = {
0x00, 0x00, 0x00, 0x00, 0xE0, 0xEA, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_88[512] = {
+static const unsigned char u2c_88[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0xE3, 0xB2, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -9182,7 +9182,7 @@ static unsigned char u2c_88[512] = {
0x00, 0x00, 0xF0, 0xB2, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_89[512] = {
+static const unsigned char u2c_89[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0xDC, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -9249,7 +9249,7 @@ static unsigned char u2c_89[512] = {
0xF5, 0xBA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xF8-0xFB */
};
-static unsigned char u2c_8A[512] = {
+static const unsigned char u2c_8A[512] = {
0xE5, 0xEB, 0x00, 0x00, 0xEF, 0xF4, 0xDD, 0xB5, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0xCD, 0xAA, 0x00, 0x00, 0xE3, 0xF2, 0x00, 0x00, /* 0x08-0x0B */
@@ -9317,7 +9317,7 @@ static unsigned char u2c_8A[512] = {
0x00, 0x00, 0x00, 0x00, 0xD1, 0xE7, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_8B[512] = {
+static const unsigned char u2c_8B[512] = {
0xD9, 0xC7, 0xE4, 0xD7, 0xEA, 0xDD, 0x00, 0x00, /* 0x00-0x03 */
0xD4, 0xF7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -9360,7 +9360,7 @@ static unsigned char u2c_8B[512] = {
0x00, 0x00, 0x00, 0x00, 0xF3, 0xC6, 0x00, 0x00, /* 0x98-0x9B */
};
-static unsigned char u2c_8C[512] = {
+static const unsigned char u2c_8C[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -9428,7 +9428,7 @@ static unsigned char u2c_8C[512] = {
0xCF, 0xC5, 0xDF, 0xDF, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_8D[512] = {
+static const unsigned char u2c_8D[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0xF2, 0xBE, 0xF6, 0xA1, 0x00, 0x00, 0xEB, 0xCB, /* 0x04-0x07 */
0xF1, 0xFC, 0x00, 0x00, 0xF3, 0xC7, 0x00, 0x00, /* 0x08-0x0B */
@@ -9493,7 +9493,7 @@ static unsigned char u2c_8D[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD4, 0xAF, /* 0xF0-0xF3 */
};
-static unsigned char u2c_8E[512] = {
+static const unsigned char u2c_8E[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0xE9, 0xC9, 0x00, 0x00, /* 0x08-0x0B */
@@ -9561,7 +9561,7 @@ static unsigned char u2c_8E[512] = {
0x00, 0x00, 0x00, 0x00, 0xE3, 0xDC, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_8F[512] = {
+static const unsigned char u2c_8F[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE, 0xF2, /* 0x00-0x03 */
0x00, 0x00, 0xD6, 0xD9, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0xEE, 0xB0, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -9629,7 +9629,7 @@ static unsigned char u2c_8F[512] = {
0x00, 0x00, 0xF5, 0xDA, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_90[512] = {
+static const unsigned char u2c_90[512] = {
0xF7, 0xDC, 0xE1, 0xEA, 0xCE, 0xC1, 0xD4, 0xB1, /* 0x00-0x03 */
0x00, 0x00, 0xFD, 0xB1, 0xE6, 0xBD, 0x00, 0x00, /* 0x04-0x07 */
0xFB, 0xAD, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xE7, /* 0x08-0x0B */
@@ -9697,7 +9697,7 @@ static unsigned char u2c_90[512] = {
0x00, 0x00, 0xD4, 0xB4, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_91[512] = {
+static const unsigned char u2c_91[512] = {
0x00, 0x00, 0x00, 0x00, 0xE4, 0xC7, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -9763,7 +9763,7 @@ static unsigned char u2c_91[512] = {
0x00, 0x00, 0xF3, 0xFB, 0x00, 0x00, 0x00, 0x00, /* 0xF4-0xF7 */
};
-static unsigned char u2c_92[512] = {
+static const unsigned char u2c_92[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -9831,7 +9831,7 @@ static unsigned char u2c_92[512] = {
0xCB, 0xBC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_93[512] = {
+static const unsigned char u2c_93[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0xD6, 0xE2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -9897,7 +9897,7 @@ static unsigned char u2c_93[512] = {
0x00, 0x00, 0x00, 0x00, 0xF3, 0xA1, 0x00, 0x00, /* 0xF4-0xF7 */
};
-static unsigned char u2c_94[512] = {
+static const unsigned char u2c_94[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0xFC, 0xF5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -9932,7 +9932,7 @@ static unsigned char u2c_94[512] = {
0x00, 0x00, 0xF3, 0xC8, 0x00, 0x00, 0xF3, 0xBA, /* 0x7C-0x7F */
};
-static unsigned char u2c_95[512] = {
+static const unsigned char u2c_95[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -9993,7 +9993,7 @@ static unsigned char u2c_95[512] = {
0x00, 0x00, 0xF4, 0xC5, 0xDC, 0xA3, 0x00, 0x00, /* 0xE0-0xE3 */
};
-static unsigned char u2c_96[512] = {
+static const unsigned char u2c_96[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -10060,7 +10060,7 @@ static unsigned char u2c_96[512] = {
0x00, 0x00, 0xDA, 0xDF, 0x00, 0x00, 0xEF, 0xB3, /* 0xF8-0xFB */
};
-static unsigned char u2c_97[512] = {
+static const unsigned char u2c_97[512] = {
0xE2, 0xCD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0xEF, 0xFD, 0xF2, 0xE8, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -10128,7 +10128,7 @@ static unsigned char u2c_97[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFA, 0xC2, /* 0xFC-0xFF */
};
-static unsigned char u2c_98[512] = {
+static const unsigned char u2c_98[512] = {
0xFB, 0xE1, 0xFA, 0xED, 0xF0, 0xA2, 0xCC, 0xF1, /* 0x00-0x03 */
0x00, 0x00, 0xFA, 0xA3, 0xE2, 0xF7, 0x00, 0x00, /* 0x04-0x07 */
0xE2, 0xCE, 0x00, 0x00, 0xE9, 0xF5, 0x00, 0x00, /* 0x08-0x0B */
@@ -10196,7 +10196,7 @@ static unsigned char u2c_98[512] = {
0xDE, 0xF8, 0xF8, 0xE9, 0xE3, 0xDE, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_99[512] = {
+static const unsigned char u2c_99[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE, 0xF5, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0xFA, 0xC3, 0xE5, 0xD7, 0x00, 0x00, /* 0x08-0x0B */
@@ -10264,7 +10264,7 @@ static unsigned char u2c_99[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF1, 0xE7, /* 0xFC-0xFF */
};
-static unsigned char u2c_9A[512] = {
+static const unsigned char u2c_9A[512] = {
0x00, 0x00, 0xDE, 0xBE, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0xDC, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -10328,7 +10328,7 @@ static unsigned char u2c_9A[512] = {
0x00, 0x00, 0x00, 0x00, 0xDB, 0xA5, 0x00, 0x00, /* 0xEC-0xEF */
};
-static unsigned char u2c_9B[512] = {
+static const unsigned char u2c_9B[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -10391,7 +10391,7 @@ static unsigned char u2c_9B[512] = {
0xCC, 0xF4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xE8-0xEB */
};
-static unsigned char u2c_9C[512] = {
+static const unsigned char u2c_9C[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -10457,7 +10457,7 @@ static unsigned char u2c_9C[512] = {
0xD9, 0xB0, 0x00, 0x00, 0xE6, 0xE9, 0x00, 0x00, /* 0xF4-0xF7 */
};
-static unsigned char u2c_9D[512] = {
+static const unsigned char u2c_9D[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0xE4, 0xBC, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -10524,7 +10524,7 @@ static unsigned char u2c_9D[512] = {
0xFD, 0xD3, 0xEB, 0xED, 0xD6, 0xDC, 0x00, 0x00, /* 0xF8-0xFB */
};
-static unsigned char u2c_9E[512] = {
+static const unsigned char u2c_9E[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -10590,7 +10590,7 @@ static unsigned char u2c_9E[512] = {
0xDA, 0xBD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xF4-0xF7 */
};
-static unsigned char u2c_9F[512] = {
+static const unsigned char u2c_9F[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE8, 0xA8, /* 0x04-0x07 */
0xDC, 0xAF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -10634,7 +10634,7 @@ static unsigned char u2c_9F[512] = {
0xCF, 0xCF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9C-0x9F */
};
-static unsigned char u2c_AC[512] = {
+static const unsigned char u2c_AC[512] = {
0xB0, 0xA1, 0xB0, 0xA2, 0x81, 0x41, 0x81, 0x42, /* 0x00-0x03 */
0xB0, 0xA3, 0x81, 0x43, 0x81, 0x44, 0xB0, 0xA4, /* 0x04-0x07 */
0xB0, 0xA5, 0xB0, 0xA6, 0xB0, 0xA7, 0x81, 0x45, /* 0x08-0x0B */
@@ -10702,7 +10702,7 @@ static unsigned char u2c_AC[512] = {
0xB0, 0xFA, 0xB0, 0xFB, 0x81, 0xF0, 0x81, 0xF1, /* 0xFC-0xFF */
};
-static unsigned char u2c_AD[512] = {
+static const unsigned char u2c_AD[512] = {
0xB0, 0xFC, 0x81, 0xF2, 0x81, 0xF3, 0x81, 0xF4, /* 0x00-0x03 */
0xB0, 0xFD, 0x81, 0xF5, 0xB0, 0xFE, 0x81, 0xF6, /* 0x04-0x07 */
0x81, 0xF7, 0x81, 0xF8, 0x81, 0xF9, 0x81, 0xFA, /* 0x08-0x0B */
@@ -10770,7 +10770,7 @@ static unsigned char u2c_AD[512] = {
0xB1, 0xD9, 0x83, 0x43, 0x83, 0x44, 0xB1, 0xDA, /* 0xFC-0xFF */
};
-static unsigned char u2c_AE[512] = {
+static const unsigned char u2c_AE[512] = {
0xB1, 0xDB, 0xB1, 0xDC, 0x83, 0x45, 0x83, 0x46, /* 0x00-0x03 */
0x83, 0x47, 0x83, 0x48, 0x83, 0x49, 0x83, 0x4A, /* 0x04-0x07 */
0xB1, 0xDD, 0xB1, 0xDE, 0x83, 0x4B, 0xB1, 0xDF, /* 0x08-0x0B */
@@ -10838,7 +10838,7 @@ static unsigned char u2c_AE[512] = {
0xB2, 0xBA, 0x84, 0x52, 0x84, 0x53, 0x84, 0x54, /* 0xFC-0xFF */
};
-static unsigned char u2c_AF[512] = {
+static const unsigned char u2c_AF[512] = {
0x84, 0x55, 0x84, 0x56, 0x84, 0x57, 0x84, 0x58, /* 0x00-0x03 */
0x84, 0x59, 0x84, 0x5A, 0x84, 0x61, 0xB2, 0xBB, /* 0x04-0x07 */
0xB2, 0xBC, 0x84, 0x62, 0x84, 0x63, 0x84, 0x64, /* 0x08-0x0B */
@@ -10906,7 +10906,7 @@ static unsigned char u2c_AF[512] = {
0x85, 0x75, 0x85, 0x76, 0x85, 0x77, 0x85, 0x78, /* 0xFC-0xFF */
};
-static unsigned char u2c_B0[512] = {
+static const unsigned char u2c_B0[512] = {
0xB2, 0xEB, 0xB2, 0xEC, 0x85, 0x79, 0x85, 0x7A, /* 0x00-0x03 */
0xB2, 0xED, 0x85, 0x81, 0x85, 0x82, 0x85, 0x83, /* 0x04-0x07 */
0x85, 0x84, 0x85, 0x85, 0x85, 0x86, 0x85, 0x87, /* 0x08-0x0B */
@@ -10974,7 +10974,7 @@ static unsigned char u2c_B0[512] = {
0x86, 0x8C, 0x86, 0x8D, 0x86, 0x8E, 0x86, 0x8F, /* 0xFC-0xFF */
};
-static unsigned char u2c_B1[512] = {
+static const unsigned char u2c_B1[512] = {
0x86, 0x90, 0x86, 0x91, 0x86, 0x92, 0x86, 0x93, /* 0x00-0x03 */
0x86, 0x94, 0x86, 0x95, 0x86, 0x96, 0x86, 0x97, /* 0x04-0x07 */
0xB3, 0xCA, 0xB3, 0xCB, 0x86, 0x98, 0xB3, 0xCC, /* 0x08-0x0B */
@@ -11042,7 +11042,7 @@ static unsigned char u2c_B1[512] = {
0x87, 0x9E, 0xB4, 0xA8, 0x87, 0x9F, 0x87, 0xA0, /* 0xFC-0xFF */
};
-static unsigned char u2c_B2[512] = {
+static const unsigned char u2c_B2[512] = {
0x87, 0xA1, 0x87, 0xA2, 0x87, 0xA3, 0x87, 0xA4, /* 0x00-0x03 */
0xB4, 0xA9, 0xB4, 0xAA, 0x87, 0xA5, 0x87, 0xA6, /* 0x04-0x07 */
0xB4, 0xAB, 0x87, 0xA7, 0x87, 0xA8, 0xB4, 0xAC, /* 0x08-0x0B */
@@ -11110,7 +11110,7 @@ static unsigned char u2c_B2[512] = {
0x88, 0xAA, 0x88, 0xAB, 0x88, 0xAC, 0xB4, 0xEA, /* 0xFC-0xFF */
};
-static unsigned char u2c_B3[512] = {
+static const unsigned char u2c_B3[512] = {
0xB4, 0xEB, 0xB4, 0xEC, 0x88, 0xAD, 0x88, 0xAE, /* 0x00-0x03 */
0xB4, 0xED, 0x88, 0xAF, 0x88, 0xB0, 0x88, 0xB1, /* 0x04-0x07 */
0xB4, 0xEE, 0x88, 0xB2, 0x88, 0xB3, 0x88, 0xB4, /* 0x08-0x0B */
@@ -11178,7 +11178,7 @@ static unsigned char u2c_B3[512] = {
0xB5, 0xC5, 0x89, 0xBF, 0x89, 0xC0, 0x89, 0xC1, /* 0xFC-0xFF */
};
-static unsigned char u2c_B4[512] = {
+static const unsigned char u2c_B4[512] = {
0x89, 0xC2, 0x89, 0xC3, 0x89, 0xC4, 0x89, 0xC5, /* 0x00-0x03 */
0x89, 0xC6, 0x89, 0xC7, 0x89, 0xC8, 0x89, 0xC9, /* 0x04-0x07 */
0x89, 0xCA, 0x89, 0xCB, 0x89, 0xCC, 0x89, 0xCD, /* 0x08-0x0B */
@@ -11246,7 +11246,7 @@ static unsigned char u2c_B4[512] = {
0x8A, 0xE2, 0x8A, 0xE3, 0x8A, 0xE4, 0x8A, 0xE5, /* 0xFC-0xFF */
};
-static unsigned char u2c_B5[512] = {
+static const unsigned char u2c_B5[512] = {
0x8A, 0xE6, 0x8A, 0xE7, 0x8A, 0xE8, 0x8A, 0xE9, /* 0x00-0x03 */
0x8A, 0xEA, 0x8A, 0xEB, 0x8A, 0xEC, 0x8A, 0xED, /* 0x04-0x07 */
0x8A, 0xEE, 0x8A, 0xEF, 0x8A, 0xF0, 0x8A, 0xF1, /* 0x08-0x0B */
@@ -11314,7 +11314,7 @@ static unsigned char u2c_B5[512] = {
0x8B, 0xFB, 0x8B, 0xFC, 0x8B, 0xFD, 0x8B, 0xFE, /* 0xFC-0xFF */
};
-static unsigned char u2c_B6[512] = {
+static const unsigned char u2c_B6[512] = {
0x8C, 0x41, 0x8C, 0x42, 0x8C, 0x43, 0x8C, 0x44, /* 0x00-0x03 */
0x8C, 0x45, 0x8C, 0x46, 0x8C, 0x47, 0x8C, 0x48, /* 0x04-0x07 */
0x8C, 0x49, 0x8C, 0x4A, 0x8C, 0x4B, 0x8C, 0x4C, /* 0x08-0x0B */
@@ -11382,7 +11382,7 @@ static unsigned char u2c_B6[512] = {
0x8D, 0x82, 0x8D, 0x83, 0x8D, 0x84, 0x8D, 0x85, /* 0xFC-0xFF */
};
-static unsigned char u2c_B7[512] = {
+static const unsigned char u2c_B7[512] = {
0xB6, 0xDC, 0xB6, 0xDD, 0x8D, 0x86, 0x8D, 0x87, /* 0x00-0x03 */
0x8D, 0x88, 0xB6, 0xDE, 0x8D, 0x89, 0x8D, 0x8A, /* 0x04-0x07 */
0x8D, 0x8B, 0x8D, 0x8C, 0x8D, 0x8D, 0x8D, 0x8E, /* 0x08-0x0B */
@@ -11450,7 +11450,7 @@ static unsigned char u2c_B7[512] = {
0xB7, 0xB3, 0xB7, 0xB4, 0x8E, 0x9B, 0xB7, 0xB5, /* 0xFC-0xFF */
};
-static unsigned char u2c_B8[512] = {
+static const unsigned char u2c_B8[512] = {
0xB7, 0xB6, 0xB7, 0xB7, 0x8E, 0x9C, 0x8E, 0x9D, /* 0x00-0x03 */
0x8E, 0x9E, 0x8E, 0x9F, 0x8E, 0xA0, 0xB7, 0xB8, /* 0x04-0x07 */
0xB7, 0xB9, 0xB7, 0xBA, 0x8E, 0xA1, 0x8E, 0xA2, /* 0x08-0x0B */
@@ -11518,7 +11518,7 @@ static unsigned char u2c_B8[512] = {
0x8F, 0xAE, 0xB7, 0xEE, 0x8F, 0xAF, 0x8F, 0xB0, /* 0xFC-0xFF */
};
-static unsigned char u2c_B9[512] = {
+static const unsigned char u2c_B9[512] = {
0x8F, 0xB1, 0x8F, 0xB2, 0x8F, 0xB3, 0x8F, 0xB4, /* 0x00-0x03 */
0xB7, 0xEF, 0x8F, 0xB5, 0x8F, 0xB6, 0x8F, 0xB7, /* 0x04-0x07 */
0x8F, 0xB8, 0x8F, 0xB9, 0x8F, 0xBA, 0x8F, 0xBB, /* 0x08-0x0B */
@@ -11586,7 +11586,7 @@ static unsigned char u2c_B9[512] = {
0x90, 0xBD, 0x90, 0xBE, 0x90, 0xBF, 0x90, 0xC0, /* 0xFC-0xFF */
};
-static unsigned char u2c_BA[512] = {
+static const unsigned char u2c_BA[512] = {
0xB8, 0xCF, 0xB8, 0xD0, 0x90, 0xC1, 0x90, 0xC2, /* 0x00-0x03 */
0x90, 0xC3, 0x90, 0xC4, 0x90, 0xC5, 0x90, 0xC6, /* 0x04-0x07 */
0xB8, 0xD1, 0x90, 0xC7, 0x90, 0xC8, 0x90, 0xC9, /* 0x08-0x0B */
@@ -11654,7 +11654,7 @@ static unsigned char u2c_BA[512] = {
0xB8, 0xFE, 0x91, 0xDC, 0x91, 0xDD, 0x91, 0xDE, /* 0xFC-0xFF */
};
-static unsigned char u2c_BB[512] = {
+static const unsigned char u2c_BB[512] = {
0xB9, 0xA1, 0x91, 0xDF, 0x91, 0xE0, 0x91, 0xE1, /* 0x00-0x03 */
0xB9, 0xA2, 0x91, 0xE2, 0x91, 0xE3, 0x91, 0xE4, /* 0x04-0x07 */
0x91, 0xE5, 0x91, 0xE6, 0x91, 0xE7, 0x91, 0xE8, /* 0x08-0x0B */
@@ -11722,7 +11722,7 @@ static unsigned char u2c_BB[512] = {
0xB9, 0xCE, 0x92, 0xFC, 0x92, 0xFD, 0xB9, 0xCF, /* 0xFC-0xFF */
};
-static unsigned char u2c_BC[512] = {
+static const unsigned char u2c_BC[512] = {
0xB9, 0xD0, 0x92, 0xFE, 0xB9, 0xD1, 0x93, 0x41, /* 0x00-0x03 */
0x93, 0x42, 0x93, 0x43, 0x93, 0x44, 0x93, 0x45, /* 0x04-0x07 */
0xB9, 0xD2, 0xB9, 0xD3, 0x93, 0x46, 0xB9, 0xD4, /* 0x08-0x0B */
@@ -11790,7 +11790,7 @@ static unsigned char u2c_BC[512] = {
0xBA, 0xBC, 0x93, 0xFE, 0x94, 0x41, 0x94, 0x42, /* 0xFC-0xFF */
};
-static unsigned char u2c_BD[512] = {
+static const unsigned char u2c_BD[512] = {
0x94, 0x43, 0x94, 0x44, 0x94, 0x45, 0x94, 0x46, /* 0x00-0x03 */
0xBA, 0xBD, 0xBA, 0xBE, 0x94, 0x47, 0xBA, 0xBF, /* 0x04-0x07 */
0x94, 0x48, 0xBA, 0xC0, 0x94, 0x49, 0x94, 0x4A, /* 0x08-0x0B */
@@ -11858,7 +11858,7 @@ static unsigned char u2c_BD[512] = {
0x95, 0x69, 0x95, 0x6A, 0x95, 0x6B, 0x95, 0x6C, /* 0xFC-0xFF */
};
-static unsigned char u2c_BE[512] = {
+static const unsigned char u2c_BE[512] = {
0xBA, 0xE7, 0x95, 0x6D, 0x95, 0x6E, 0xBA, 0xE8, /* 0x00-0x03 */
0x95, 0x6F, 0xBA, 0xE9, 0x95, 0x70, 0x95, 0x71, /* 0x04-0x07 */
0x95, 0x72, 0x95, 0x73, 0x95, 0x74, 0x95, 0x75, /* 0x08-0x0B */
@@ -11926,7 +11926,7 @@ static unsigned char u2c_BE[512] = {
0x96, 0x87, 0x96, 0x88, 0x96, 0x89, 0x96, 0x8A, /* 0xFC-0xFF */
};
-static unsigned char u2c_BF[512] = {
+static const unsigned char u2c_BF[512] = {
0x96, 0x8B, 0xBB, 0xBF, 0x96, 0x8C, 0x96, 0x8D, /* 0x00-0x03 */
0x96, 0x8E, 0x96, 0x8F, 0x96, 0x90, 0x96, 0x91, /* 0x04-0x07 */
0xBB, 0xC0, 0xBB, 0xC1, 0x96, 0x92, 0x96, 0x93, /* 0x08-0x0B */
@@ -11994,7 +11994,7 @@ static unsigned char u2c_BF[512] = {
0x97, 0xBC, 0x97, 0xBD, 0x97, 0xBE, 0x97, 0xBF, /* 0xFC-0xFF */
};
-static unsigned char u2c_C0[512] = {
+static const unsigned char u2c_C0[512] = {
0x97, 0xC0, 0x97, 0xC1, 0x97, 0xC2, 0x97, 0xC3, /* 0x00-0x03 */
0x97, 0xC4, 0x97, 0xC5, 0x97, 0xC6, 0x97, 0xC7, /* 0x04-0x07 */
0x97, 0xC8, 0x97, 0xC9, 0x97, 0xCA, 0x97, 0xCB, /* 0x08-0x0B */
@@ -12062,7 +12062,7 @@ static unsigned char u2c_C0[512] = {
0x98, 0xDC, 0x98, 0xDD, 0x98, 0xDE, 0x98, 0xDF, /* 0xFC-0xFF */
};
-static unsigned char u2c_C1[512] = {
+static const unsigned char u2c_C1[512] = {
0xBC, 0xA8, 0x98, 0xE0, 0x98, 0xE1, 0x98, 0xE2, /* 0x00-0x03 */
0xBC, 0xA9, 0x98, 0xE3, 0x98, 0xE4, 0x98, 0xE5, /* 0x04-0x07 */
0xBC, 0xAA, 0x98, 0xE6, 0x98, 0xE7, 0x98, 0xE8, /* 0x08-0x0B */
@@ -12130,7 +12130,7 @@ static unsigned char u2c_C1[512] = {
0xBC, 0xEE, 0xBC, 0xEF, 0x99, 0xE4, 0x99, 0xE5, /* 0xFC-0xFF */
};
-static unsigned char u2c_C2[512] = {
+static const unsigned char u2c_C2[512] = {
0xBC, 0xF0, 0x99, 0xE6, 0x99, 0xE7, 0x99, 0xE8, /* 0x00-0x03 */
0xBC, 0xF1, 0x99, 0xE9, 0x99, 0xEA, 0x99, 0xEB, /* 0x04-0x07 */
0x99, 0xEC, 0x99, 0xED, 0x99, 0xEE, 0x99, 0xEF, /* 0x08-0x0B */
@@ -12198,7 +12198,7 @@ static unsigned char u2c_C2[512] = {
0xBD, 0xD1, 0x9A, 0xF1, 0x9A, 0xF2, 0x9A, 0xF3, /* 0xFC-0xFF */
};
-static unsigned char u2c_C3[512] = {
+static const unsigned char u2c_C3[512] = {
0xBD, 0xD2, 0x9A, 0xF4, 0x9A, 0xF5, 0x9A, 0xF6, /* 0x00-0x03 */
0x9A, 0xF7, 0x9A, 0xF8, 0x9A, 0xF9, 0x9A, 0xFA, /* 0x04-0x07 */
0xBD, 0xD3, 0xBD, 0xD4, 0x9A, 0xFB, 0x9A, 0xFC, /* 0x08-0x0B */
@@ -12266,7 +12266,7 @@ static unsigned char u2c_C3[512] = {
0x9C, 0x58, 0x9C, 0x59, 0x9C, 0x5A, 0x9C, 0x61, /* 0xFC-0xFF */
};
-static unsigned char u2c_C4[512] = {
+static const unsigned char u2c_C4[512] = {
0x9C, 0x62, 0x9C, 0x63, 0x9C, 0x64, 0x9C, 0x65, /* 0x00-0x03 */
0x9C, 0x66, 0x9C, 0x67, 0x9C, 0x68, 0x9C, 0x69, /* 0x04-0x07 */
0xBD, 0xFA, 0x9C, 0x6A, 0x9C, 0x6B, 0x9C, 0x6C, /* 0x08-0x0B */
@@ -12334,7 +12334,7 @@ static unsigned char u2c_C4[512] = {
0x9D, 0x97, 0x9D, 0x98, 0x9D, 0x99, 0xBE, 0xB7, /* 0xFC-0xFF */
};
-static unsigned char u2c_C5[512] = {
+static const unsigned char u2c_C5[512] = {
0xBE, 0xB8, 0xBE, 0xB9, 0x9D, 0x9A, 0x9D, 0x9B, /* 0x00-0x03 */
0x9D, 0x9C, 0x9D, 0x9D, 0x9D, 0x9E, 0x9D, 0x9F, /* 0x04-0x07 */
0x9D, 0xA0, 0x9D, 0xA1, 0x9D, 0xA2, 0x9D, 0xA3, /* 0x08-0x0B */
@@ -12402,7 +12402,7 @@ static unsigned char u2c_C5[512] = {
0xBF, 0xB0, 0xBF, 0xB1, 0xBF, 0xB2, 0xBF, 0xB3, /* 0xFC-0xFF */
};
-static unsigned char u2c_C6[512] = {
+static const unsigned char u2c_C6[512] = {
0xBF, 0xB4, 0xBF, 0xB5, 0x9E, 0x8E, 0x9E, 0x8F, /* 0x00-0x03 */
0x9E, 0x90, 0xBF, 0xB6, 0xBF, 0xB7, 0xBF, 0xB8, /* 0x04-0x07 */
0xBF, 0xB9, 0x9E, 0x91, 0x9E, 0x92, 0x9E, 0x93, /* 0x08-0x0B */
@@ -12470,7 +12470,7 @@ static unsigned char u2c_C6[512] = {
0x9F, 0x88, 0xC0, 0xA6, 0x9F, 0x89, 0x9F, 0x8A, /* 0xFC-0xFF */
};
-static unsigned char u2c_C7[512] = {
+static const unsigned char u2c_C7[512] = {
0x9F, 0x8B, 0x9F, 0x8C, 0x9F, 0x8D, 0x9F, 0x8E, /* 0x00-0x03 */
0xC0, 0xA7, 0xC0, 0xA8, 0x9F, 0x8F, 0x9F, 0x90, /* 0x04-0x07 */
0xC0, 0xA9, 0x9F, 0x91, 0x9F, 0x92, 0x9F, 0x93, /* 0x08-0x0B */
@@ -12538,7 +12538,7 @@ static unsigned char u2c_C7[512] = {
0xA0, 0x82, 0xA0, 0x83, 0xA0, 0x84, 0xA0, 0x85, /* 0xFC-0xFF */
};
-static unsigned char u2c_C8[512] = {
+static const unsigned char u2c_C8[512] = {
0xC0, 0xFA, 0xC0, 0xFB, 0xA0, 0x86, 0xA0, 0x87, /* 0x00-0x03 */
0xC0, 0xFC, 0xA0, 0x88, 0xA0, 0x89, 0xA0, 0x8A, /* 0x04-0x07 */
0xC0, 0xFD, 0xA0, 0x8B, 0xC0, 0xFE, 0xA0, 0x8C, /* 0x08-0x0B */
@@ -12606,7 +12606,7 @@ static unsigned char u2c_C8[512] = {
0xC1, 0xD6, 0xC1, 0xD7, 0xA1, 0x96, 0xA1, 0x97, /* 0xFC-0xFF */
};
-static unsigned char u2c_C9[512] = {
+static const unsigned char u2c_C9[512] = {
0xC1, 0xD8, 0xA1, 0x98, 0xA1, 0x99, 0xA1, 0x9A, /* 0x00-0x03 */
0xC1, 0xD9, 0xC1, 0xDA, 0xC1, 0xDB, 0xA1, 0x9B, /* 0x04-0x07 */
0xA1, 0x9C, 0xA1, 0x9D, 0xA1, 0x9E, 0xA1, 0x9F, /* 0x08-0x0B */
@@ -12674,7 +12674,7 @@ static unsigned char u2c_C9[512] = {
0xC2, 0xB2, 0xA4, 0x54, 0xA4, 0x55, 0xA4, 0x56, /* 0xFC-0xFF */
};
-static unsigned char u2c_CA[512] = {
+static const unsigned char u2c_CA[512] = {
0xC2, 0xB3, 0xA4, 0x57, 0xA4, 0x58, 0xA4, 0x59, /* 0x00-0x03 */
0xA4, 0x5A, 0xA4, 0x61, 0xA4, 0x62, 0xA4, 0x63, /* 0x04-0x07 */
0xC2, 0xB4, 0xC2, 0xB5, 0xA4, 0x64, 0xC2, 0xB6, /* 0x08-0x0B */
@@ -12742,7 +12742,7 @@ static unsigned char u2c_CA[512] = {
0xA6, 0x93, 0xA6, 0x94, 0xA6, 0x95, 0xA6, 0x96, /* 0xFC-0xFF */
};
-static unsigned char u2c_CB[512] = {
+static const unsigned char u2c_CB[512] = {
0xA6, 0x97, 0xA6, 0x98, 0xA6, 0x99, 0xA6, 0x9A, /* 0x00-0x03 */
0xA6, 0x9B, 0xA6, 0x9C, 0xA6, 0x9D, 0xA6, 0x9E, /* 0x04-0x07 */
0xC2, 0xD7, 0xA6, 0x9F, 0xA6, 0xA0, 0xA7, 0x41, /* 0x08-0x0B */
@@ -12810,7 +12810,7 @@ static unsigned char u2c_CB[512] = {
0xA9, 0x7A, 0xA9, 0x81, 0xA9, 0x82, 0xA9, 0x83, /* 0xFC-0xFF */
};
-static unsigned char u2c_CC[512] = {
+static const unsigned char u2c_CC[512] = {
0xA9, 0x84, 0xA9, 0x85, 0xA9, 0x86, 0xA9, 0x87, /* 0x00-0x03 */
0xA9, 0x88, 0xA9, 0x89, 0xA9, 0x8A, 0xA9, 0x8B, /* 0x04-0x07 */
0xA9, 0x8C, 0xA9, 0x8D, 0xA9, 0x8E, 0xA9, 0x8F, /* 0x08-0x0B */
@@ -12878,7 +12878,7 @@ static unsigned char u2c_CC[512] = {
0xAB, 0x9F, 0xAB, 0xA0, 0xAC, 0x41, 0xAC, 0x42, /* 0xFC-0xFF */
};
-static unsigned char u2c_CD[512] = {
+static const unsigned char u2c_CD[512] = {
0xAC, 0x43, 0xC3, 0xC9, 0xAC, 0x44, 0xAC, 0x45, /* 0x00-0x03 */
0xAC, 0x46, 0xAC, 0x47, 0xAC, 0x48, 0xAC, 0x49, /* 0x04-0x07 */
0xC3, 0xCA, 0xC3, 0xCB, 0xAC, 0x4A, 0xAC, 0x4B, /* 0x08-0x0B */
@@ -12946,7 +12946,7 @@ static unsigned char u2c_CD[512] = {
0xAE, 0x75, 0xC3, 0xF1, 0xAE, 0x76, 0xAE, 0x77, /* 0xFC-0xFF */
};
-static unsigned char u2c_CE[512] = {
+static const unsigned char u2c_CE[512] = {
0xAE, 0x78, 0xAE, 0x79, 0xAE, 0x7A, 0xAE, 0x81, /* 0x00-0x03 */
0xC3, 0xF2, 0xAE, 0x82, 0xAE, 0x83, 0xAE, 0x84, /* 0x04-0x07 */
0xC3, 0xF3, 0xAE, 0x85, 0xAE, 0x86, 0xAE, 0x87, /* 0x08-0x0B */
@@ -13014,7 +13014,7 @@ static unsigned char u2c_CE[512] = {
0xB0, 0x9D, 0xB0, 0x9E, 0xB0, 0x9F, 0xB0, 0xA0, /* 0xFC-0xFF */
};
-static unsigned char u2c_CF[512] = {
+static const unsigned char u2c_CF[512] = {
0xC4, 0xC9, 0xC4, 0xCA, 0xB1, 0x41, 0xB1, 0x42, /* 0x00-0x03 */
0xC4, 0xCB, 0xB1, 0x43, 0xB1, 0x44, 0xB1, 0x45, /* 0x04-0x07 */
0xC4, 0xCC, 0xB1, 0x46, 0xB1, 0x47, 0xB1, 0x48, /* 0x08-0x0B */
@@ -13082,7 +13082,7 @@ static unsigned char u2c_CF[512] = {
0xC4, 0xF5, 0xB3, 0x6F, 0xB3, 0x70, 0xB3, 0x71, /* 0xFC-0xFF */
};
-static unsigned char u2c_D0[512] = {
+static const unsigned char u2c_D0[512] = {
0xC4, 0xF6, 0xB3, 0x72, 0xB3, 0x73, 0xB3, 0x74, /* 0x00-0x03 */
0xC4, 0xF7, 0xB3, 0x75, 0xB3, 0x76, 0xB3, 0x77, /* 0x04-0x07 */
0xB3, 0x78, 0xB3, 0x79, 0xB3, 0x7A, 0xB3, 0x81, /* 0x08-0x0B */
@@ -13150,7 +13150,7 @@ static unsigned char u2c_D0[512] = {
0xB5, 0x98, 0xB5, 0x99, 0xB5, 0x9A, 0xB5, 0x9B, /* 0xFC-0xFF */
};
-static unsigned char u2c_D1[512] = {
+static const unsigned char u2c_D1[512] = {
0xB5, 0x9C, 0xB5, 0x9D, 0xB5, 0x9E, 0xB5, 0x9F, /* 0x00-0x03 */
0xB5, 0xA0, 0xB6, 0x41, 0xB6, 0x42, 0xB6, 0x43, /* 0x04-0x07 */
0xB6, 0x44, 0xB6, 0x45, 0xB6, 0x46, 0xB6, 0x47, /* 0x08-0x0B */
@@ -13218,7 +13218,7 @@ static unsigned char u2c_D1[512] = {
0xB8, 0x70, 0xB8, 0x71, 0xB8, 0x72, 0xB8, 0x73, /* 0xFC-0xFF */
};
-static unsigned char u2c_D2[512] = {
+static const unsigned char u2c_D2[512] = {
0xB8, 0x74, 0xB8, 0x75, 0xB8, 0x76, 0xB8, 0x77, /* 0x00-0x03 */
0xB8, 0x78, 0xB8, 0x79, 0xB8, 0x7A, 0xC5, 0xF2, /* 0x04-0x07 */
0xB8, 0x81, 0xC5, 0xF3, 0xB8, 0x82, 0xB8, 0x83, /* 0x08-0x0B */
@@ -13286,7 +13286,7 @@ static unsigned char u2c_D2[512] = {
0xBB, 0x42, 0xBB, 0x43, 0xBB, 0x44, 0xBB, 0x45, /* 0xFC-0xFF */
};
-static unsigned char u2c_D3[512] = {
+static const unsigned char u2c_D3[512] = {
0xC6, 0xC0, 0xC6, 0xC1, 0xBB, 0x46, 0xC6, 0xC2, /* 0x00-0x03 */
0xBB, 0x47, 0xC6, 0xC3, 0xBB, 0x48, 0xBB, 0x49, /* 0x04-0x07 */
0xBB, 0x4A, 0xBB, 0x4B, 0xBB, 0x4C, 0xBB, 0x4D, /* 0x08-0x0B */
@@ -13354,7 +13354,7 @@ static unsigned char u2c_D3[512] = {
0xC6, 0xFB, 0xC6, 0xFC, 0xBD, 0x65, 0xC6, 0xFD, /* 0xFC-0xFF */
};
-static unsigned char u2c_D4[512] = {
+static const unsigned char u2c_D4[512] = {
0xBD, 0x66, 0xC6, 0xFE, 0xBD, 0x67, 0xBD, 0x68, /* 0x00-0x03 */
0xBD, 0x69, 0xBD, 0x6A, 0xBD, 0x6B, 0xBD, 0x6C, /* 0x04-0x07 */
0xC7, 0xA1, 0xBD, 0x6D, 0xBD, 0x6E, 0xBD, 0x6F, /* 0x08-0x0B */
@@ -13422,7 +13422,7 @@ static unsigned char u2c_D4[512] = {
0xBF, 0xA0, 0xC7, 0xC0, 0xC0, 0x41, 0xC0, 0x42, /* 0xFC-0xFF */
};
-static unsigned char u2c_D5[512] = {
+static const unsigned char u2c_D5[512] = {
0xC0, 0x43, 0xC0, 0x44, 0xC0, 0x45, 0xC0, 0x46, /* 0x00-0x03 */
0xC7, 0xC1, 0xC0, 0x47, 0xC0, 0x48, 0xC0, 0x49, /* 0x04-0x07 */
0xC7, 0xC2, 0xC0, 0x4A, 0xC0, 0x4B, 0xC0, 0x4C, /* 0x08-0x0B */
@@ -13490,7 +13490,7 @@ static unsigned char u2c_D5[512] = {
0xC2, 0x6A, 0xC2, 0x6B, 0xC2, 0x6C, 0xC2, 0x6D, /* 0xFC-0xFF */
};
-static unsigned char u2c_D6[512] = {
+static const unsigned char u2c_D6[512] = {
0xC7, 0xF4, 0xC7, 0xF5, 0xC2, 0x6E, 0xC2, 0x6F, /* 0x00-0x03 */
0xC7, 0xF6, 0xC2, 0x70, 0xC2, 0x71, 0xC2, 0x72, /* 0x04-0x07 */
0xC7, 0xF7, 0xC2, 0x73, 0xC2, 0x74, 0xC2, 0x75, /* 0x08-0x0B */
@@ -13558,7 +13558,7 @@ static unsigned char u2c_D6[512] = {
0xC8, 0xD1, 0xC8, 0xD2, 0xC4, 0x8D, 0xC4, 0x8E, /* 0xFC-0xFF */
};
-static unsigned char u2c_D7[512] = {
+static const unsigned char u2c_D7[512] = {
0xC8, 0xD3, 0xC4, 0x8F, 0xC4, 0x90, 0xC4, 0x91, /* 0x00-0x03 */
0xC8, 0xD4, 0xC4, 0x92, 0xC4, 0x93, 0xC4, 0x94, /* 0x04-0x07 */
0xC4, 0x95, 0xC4, 0x96, 0xC4, 0x97, 0xC4, 0x98, /* 0x08-0x0B */
@@ -13603,11 +13603,11 @@ static unsigned char u2c_D7[512] = {
0xC6, 0x4F, 0xC6, 0x50, 0xC6, 0x51, 0xC6, 0x52, /* 0xA0-0xA3 */
};
-static unsigned char u2c_DC[512] = {
+static const unsigned char u2c_DC[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
};
-static unsigned char u2c_F9[512] = {
+static const unsigned char u2c_F9[512] = {
0xCB, 0xD0, 0xCB, 0xD6, 0xCB, 0xE7, 0xCD, 0xCF, /* 0x00-0x03 */
0xCD, 0xE8, 0xCE, 0xAD, 0xCF, 0xFB, 0xD0, 0xA2, /* 0x04-0x07 */
0xD0, 0xB8, 0xD0, 0xD0, 0xD0, 0xDD, 0xD1, 0xD4, /* 0x08-0x0B */
@@ -13675,7 +13675,7 @@ static unsigned char u2c_F9[512] = {
0xF2, 0xBD, 0xF2, 0xFA, 0xF3, 0xB1, 0xF4, 0xA7, /* 0xFC-0xFF */
};
-static unsigned char u2c_FA[512] = {
+static const unsigned char u2c_FA[512] = {
0xF4, 0xEE, 0xF6, 0xF4, 0xF6, 0xF6, 0xF7, 0xB8, /* 0x00-0x03 */
0xF7, 0xC8, 0xF7, 0xD3, 0xF8, 0xDB, 0xF8, 0xF0, /* 0x04-0x07 */
0xFA, 0xA1, 0xFA, 0xA2, 0xFA, 0xE6, 0xFC, 0xA9, /* 0x08-0x0B */
@@ -13690,7 +13690,7 @@ static unsigned char u2c_FA[512] = {
0xCE, 0xBD, 0xF9, 0xCD, 0x00, 0x00, 0x00, 0x00, /* 0x2C-0x2F */
};
-static unsigned char u2c_FF[512] = {
+static const unsigned char u2c_FF[512] = {
0x00, 0x00, 0xA3, 0xA1, 0xA3, 0xA2, 0xA3, 0xA3, /* 0x00-0x03 */
0xA3, 0xA4, 0xA3, 0xA5, 0xA3, 0xA6, 0xA3, 0xA7, /* 0x04-0x07 */
0xA3, 0xA8, 0xA3, 0xA9, 0xA3, 0xAA, 0xA3, 0xAB, /* 0x08-0x0B */
@@ -13752,7 +13752,7 @@ static unsigned char u2c_FF[512] = {
0x00, 0x00, 0xA1, 0xCD, 0xA3, 0xDC, 0x00, 0x00, /* 0xE4-0xE7 */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
NULL, u2c_01, u2c_02, u2c_03, u2c_04, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, u2c_11, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -13786,7 +13786,7 @@ static unsigned char *page_uni2charset[256] = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, u2c_F9, u2c_FA, NULL, NULL, NULL, NULL, u2c_FF, };
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -13822,7 +13822,7 @@ static unsigned char charset2lower[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -13861,7 +13861,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(const wchar_t uni,
unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni&0xFF;
unsigned char ch = (uni>>8)&0xFF;
int n;
@@ -13893,7 +13893,7 @@ static int char2uni(const unsigned char *rawstring, int boundlen,
wchar_t *uni)
{
unsigned char ch, cl;
- wchar_t *charset2uni;
+ const wchar_t *charset2uni;
int n;
if (boundlen <= 0)
diff --git a/fs/nls/nls_cp950.c b/fs/nls/nls_cp950.c
index 5665945fb88c..ef2536829aa5 100644
--- a/fs/nls/nls_cp950.c
+++ b/fs/nls/nls_cp950.c
@@ -13,7 +13,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t c2u_A1[256] = {
+static const wchar_t c2u_A1[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -49,7 +49,7 @@ static wchar_t c2u_A1[256] = {
0x2196,0x2197,0x2199,0x2198,0x2225,0x2223,0xFF0F,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_A2[256] = {
+static const wchar_t c2u_A2[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -85,7 +85,7 @@ static wchar_t c2u_A2[256] = {
0xFF50,0xFF51,0xFF52,0xFF53,0xFF54,0xFF55,0xFF56,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_A3[256] = {
+static const wchar_t c2u_A3[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -118,7 +118,7 @@ static wchar_t c2u_A3[256] = {
0x0000,0x20AC,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0xE0-0xE7 */
};
-static wchar_t c2u_A4[256] = {
+static const wchar_t c2u_A4[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -154,7 +154,7 @@ static wchar_t c2u_A4[256] = {
0x723B,0x7247,0x7259,0x725B,0x72AC,0x738B,0x4E19,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_A5[256] = {
+static const wchar_t c2u_A5[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -190,7 +190,7 @@ static wchar_t c2u_A5[256] = {
0x4F01,0x4F0B,0x5149,0x5147,0x5146,0x5148,0x5168,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_A6[256] = {
+static const wchar_t c2u_A6[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -226,7 +226,7 @@ static wchar_t c2u_A6[256] = {
0x4F3A,0x4F38,0x4F43,0x4F54,0x4F3C,0x4F46,0x4F63,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_A7[256] = {
+static const wchar_t c2u_A7[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -262,7 +262,7 @@ static wchar_t c2u_A7[256] = {
0x6751,0x675C,0x6756,0x675E,0x6749,0x6746,0x6760,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_A8[256] = {
+static const wchar_t c2u_A8[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -298,7 +298,7 @@ static wchar_t c2u_A8[256] = {
0x5378,0x5379,0x53D6,0x53D4,0x53D7,0x5473,0x5475,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_A9[256] = {
+static const wchar_t c2u_A9[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -334,7 +334,7 @@ static wchar_t c2u_A9[256] = {
0x6606,0x6602,0x660E,0x6600,0x660F,0x6615,0x660A,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_AA[256] = {
+static const wchar_t c2u_AA[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -370,7 +370,7 @@ static wchar_t c2u_AA[256] = {
0x9577,0x9580,0x961C,0x9640,0x963F,0x963B,0x9644,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_AB[256] = {
+static const wchar_t c2u_AB[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -406,7 +406,7 @@ static wchar_t c2u_AB[256] = {
0x62ED,0x6301,0x62EE,0x62FD,0x6307,0x62F1,0x62F7,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_AC[256] = {
+static const wchar_t c2u_AC[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -442,7 +442,7 @@ static wchar_t c2u_AC[256] = {
0x7D07,0x7D04,0x7D06,0x7F38,0x7F8E,0x7FBF,0x8004,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_AD[256] = {
+static const wchar_t c2u_AD[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -478,7 +478,7 @@ static wchar_t c2u_AD[256] = {
0x5514,0x54E9,0x54ED,0x54E1,0x5509,0x54EE,0x54EA,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_AE[256] = {
+static const wchar_t c2u_AE[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -514,7 +514,7 @@ static wchar_t c2u_AE[256] = {
0x6D88,0x6D87,0x6D66,0x6D78,0x6D77,0x6D59,0x6D93,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_AF[256] = {
+static const wchar_t c2u_AF[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -550,7 +550,7 @@ static wchar_t c2u_AF[256] = {
0x8339,0x8336,0x8317,0x8340,0x8331,0x8328,0x8343,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_B0[256] = {
+static const wchar_t c2u_B0[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -586,7 +586,7 @@ static wchar_t c2u_B0[256] = {
0x5962,0x5A36,0x5A41,0x5A49,0x5A66,0x5A6A,0x5A40,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_B1[256] = {
+static const wchar_t c2u_B1[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -622,7 +622,7 @@ static wchar_t c2u_B1[256] = {
0x689D,0x68A8,0x689F,0x68A1,0x6882,0x6B32,0x6BBA,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_B2[256] = {
+static const wchar_t c2u_B2[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -658,7 +658,7 @@ static wchar_t c2u_B2[256] = {
0x838A,0x8393,0x8389,0x83A0,0x8377,0x837B,0x837C,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_B3[256] = {
+static const wchar_t c2u_B3[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -694,7 +694,7 @@ static wchar_t c2u_B3[256] = {
0x5831,0x5821,0x581D,0x5820,0x58F9,0x58FA,0x5960,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_B4[256] = {
+static const wchar_t c2u_B4[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -730,7 +730,7 @@ static wchar_t c2u_B4[256] = {
0x6E4D,0x6E3A,0x6E2C,0x6E43,0x6E1D,0x6E3E,0x6ECB,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_B5[256] = {
+static const wchar_t c2u_B5[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -766,7 +766,7 @@ static wchar_t c2u_B5[256] = {
0x8996,0x8A3B,0x8A60,0x8A55,0x8A5E,0x8A3C,0x8A41,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_B6[256] = {
+static const wchar_t c2u_B6[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -802,7 +802,7 @@ static wchar_t c2u_B6[256] = {
0x5967,0x5AC1,0x5AC9,0x5ACC,0x5ABE,0x5ABD,0x5ABC,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_B7[256] = {
+static const wchar_t c2u_B7[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -838,7 +838,7 @@ static wchar_t c2u_B7[256] = {
0x76DE,0x76DF,0x775B,0x776B,0x7766,0x775E,0x7763,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_B8[256] = {
+static const wchar_t c2u_B8[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -874,7 +874,7 @@ static wchar_t c2u_B8[256] = {
0x8DE4,0x8DE6,0x8EB2,0x8F03,0x8F09,0x8EFE,0x8F0A,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_B9[256] = {
+static const wchar_t c2u_B9[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -910,7 +910,7 @@ static wchar_t c2u_B9[256] = {
0x5ED3,0x5ED6,0x5F0A,0x5F46,0x5F70,0x5FB9,0x6147,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_BA[256] = {
+static const wchar_t c2u_BA[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -946,7 +946,7 @@ static wchar_t c2u_BA[256] = {
0x7DBF,0x7DB5,0x7DB8,0x7DAD,0x7DD2,0x7DC7,0x7DAC,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_BB[256] = {
+static const wchar_t c2u_BB[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -982,7 +982,7 @@ static wchar_t c2u_BB[256] = {
0x50F5,0x50F9,0x5102,0x5108,0x5109,0x5105,0x51DC,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_BC[256] = {
+static const wchar_t c2u_BC[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1018,7 +1018,7 @@ static wchar_t c2u_BC[256] = {
0x7256,0x729B,0x734E,0x7357,0x7469,0x748B,0x7483,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_BD[256] = {
+static const wchar_t c2u_BD[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1054,7 +1054,7 @@ static wchar_t c2u_BD[256] = {
0x8F1B,0x8F1F,0x8F29,0x8F26,0x8F2A,0x8F1C,0x8F1E,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_BE[256] = {
+static const wchar_t c2u_BE[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1090,7 +1090,7 @@ static wchar_t c2u_BE[256] = {
0x6A48,0x6B59,0x6B77,0x6C05,0x6FC2,0x6FB1,0x6FA1,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_BF[256] = {
+static const wchar_t c2u_BF[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1126,7 +1126,7 @@ static wchar_t c2u_BF[256] = {
0x9333,0x932F,0x9322,0x92FC,0x932B,0x9304,0x931A,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_C0[256] = {
+static const wchar_t c2u_C0[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1162,7 +1162,7 @@ static wchar_t c2u_C0[256] = {
0x7642,0x764C,0x76EA,0x77B3,0x77AA,0x77B0,0x77AC,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_C1[256] = {
+static const wchar_t c2u_C1[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1198,7 +1198,7 @@ static wchar_t c2u_C1[256] = {
0x971E,0x97A0,0x97D3,0x9846,0x98B6,0x9935,0x9A01,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_C2[256] = {
+static const wchar_t c2u_C2[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1234,7 +1234,7 @@ static wchar_t c2u_C2[256] = {
0x96DC,0x96D9,0x96DB,0x96DE,0x9724,0x97A3,0x97A6,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_C3[256] = {
+static const wchar_t c2u_C3[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1270,7 +1270,7 @@ static wchar_t c2u_C3[256] = {
0x96E3,0x972A,0x9727,0x9761,0x97DC,0x97FB,0x985E,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_C4[256] = {
+static const wchar_t c2u_C4[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1306,7 +1306,7 @@ static wchar_t c2u_C4[256] = {
0x8822,0x8821,0x881F,0x896A,0x896C,0x89BD,0x8B74,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_C5[256] = {
+static const wchar_t c2u_C5[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1342,7 +1342,7 @@ static wchar_t c2u_C5[256] = {
0x7F50,0x7F88,0x8836,0x8839,0x8862,0x8B93,0x8B92,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_C6[256] = {
+static const wchar_t c2u_C6[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1361,7 +1361,7 @@ static wchar_t c2u_C6[256] = {
0x9E1A,0x7228,0x9A6A,0x9B31,0x9E1B,0x9E1E,0x7C72,0x0000,/* 0x78-0x7F */
};
-static wchar_t c2u_C9[256] = {
+static const wchar_t c2u_C9[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1397,7 +1397,7 @@ static wchar_t c2u_C9[256] = {
0x6C46,0x6C52,0x6C5C,0x6C4F,0x6C4A,0x6C54,0x6C4B,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_CA[256] = {
+static const wchar_t c2u_CA[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1433,7 +1433,7 @@ static wchar_t c2u_CA[256] = {
0x65F0,0x65F4,0x65F3,0x65F2,0x65F5,0x6745,0x6747,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_CB[256] = {
+static const wchar_t c2u_CB[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1469,7 +1469,7 @@ static wchar_t c2u_CB[256] = {
0x5776,0x5780,0x5775,0x577B,0x5773,0x5774,0x5762,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_CC[256] = {
+static const wchar_t c2u_CC[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1505,7 +1505,7 @@ static wchar_t c2u_CC[256] = {
0x6CD0,0x6CC2,0x6CBA,0x6CC3,0x6CC6,0x6CED,0x6CF2,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_CD[256] = {
+static const wchar_t c2u_CD[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1541,7 +1541,7 @@ static wchar_t c2u_CD[256] = {
0x5399,0x5398,0x54BA,0x54A1,0x54AD,0x54A5,0x54CF,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_CE[256] = {
+static const wchar_t c2u_CE[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1577,7 +1577,7 @@ static wchar_t c2u_CE[256] = {
0x662E,0x670F,0x6710,0x67C1,0x67F2,0x67C8,0x67BA,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_CF[256] = {
+static const wchar_t c2u_CF[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1613,7 +1613,7 @@ static wchar_t c2u_CF[256] = {
0x7944,0x79D5,0x79CD,0x79CF,0x79D6,0x79CE,0x7A80,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_D0[256] = {
+static const wchar_t c2u_D0[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1649,7 +1649,7 @@ static wchar_t c2u_D0[256] = {
0x54FF,0x5504,0x5508,0x54EB,0x5511,0x5505,0x54F1,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_D1[256] = {
+static const wchar_t c2u_D1[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1685,7 +1685,7 @@ static wchar_t c2u_D1[256] = {
0x6B31,0x6B34,0x6B6D,0x8082,0x6B88,0x6BE6,0x6BE4,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_D2[256] = {
+static const wchar_t c2u_D2[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1721,7 +1721,7 @@ static wchar_t c2u_D2[256] = {
0x7A85,0x7A8B,0x7A8C,0x7A8A,0x7A87,0x7AD8,0x7B10,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_D3[256] = {
+static const wchar_t c2u_D3[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1757,7 +1757,7 @@ static wchar_t c2u_D3[256] = {
0x90E5,0x90D8,0x90DB,0x90D7,0x90DC,0x90E4,0x9150,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_D4[256] = {
+static const wchar_t c2u_D4[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1793,7 +1793,7 @@ static wchar_t c2u_D4[256] = {
0x5D20,0x5D0C,0x5D28,0x5D0D,0x5D26,0x5D25,0x5D0F,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_D5[256] = {
+static const wchar_t c2u_D5[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1829,7 +1829,7 @@ static wchar_t c2u_D5[256] = {
0x6DED,0x6DF0,0x6DBA,0x6DD5,0x6DC2,0x6DCF,0x6DC9,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_D6[256] = {
+static const wchar_t c2u_D6[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1865,7 +1865,7 @@ static wchar_t c2u_D6[256] = {
0x7FCD,0x7FD0,0x7FD1,0x7FC7,0x7FCF,0x7FC9,0x801F,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_D7[256] = {
+static const wchar_t c2u_D7[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1901,7 +1901,7 @@ static wchar_t c2u_D7[256] = {
0x91F4,0x91F1,0x91F3,0x91F8,0x91E4,0x91F9,0x91EA,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_D8[256] = {
+static const wchar_t c2u_D8[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1937,7 +1937,7 @@ static wchar_t c2u_D8[256] = {
0x60C9,0x60B9,0x60CC,0x60E2,0x60CE,0x60C4,0x6114,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_D9[256] = {
+static const wchar_t c2u_D9[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -1973,7 +1973,7 @@ static wchar_t c2u_D9[256] = {
0x6E4B,0x6E40,0x6E51,0x6E3B,0x6E03,0x6E2E,0x6E5E,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_DA[256] = {
+static const wchar_t c2u_DA[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2009,7 +2009,7 @@ static wchar_t c2u_DA[256] = {
0x7D69,0x7D51,0x7D5F,0x7D4E,0x7F3E,0x7F3F,0x7F65,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_DB[256] = {
+static const wchar_t c2u_DB[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2045,7 +2045,7 @@ static wchar_t c2u_DB[256] = {
0x8DD9,0x8DC8,0x8DD7,0x8DC5,0x8EEF,0x8EF7,0x8EFA,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_DC[256] = {
+static const wchar_t c2u_DC[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2081,7 +2081,7 @@ static wchar_t c2u_DC[256] = {
0x5AB1,0x5AB5,0x5AB0,0x5ABF,0x5AC8,0x5ABB,0x5AC6,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_DD[256] = {
+static const wchar_t c2u_DD[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2117,7 +2117,7 @@ static wchar_t c2u_DD[256] = {
0x6B42,0x6B48,0x6B41,0x6B9B,0xFA0D,0x6BFB,0x6BFC,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_DE[256] = {
+static const wchar_t c2u_DE[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2153,7 +2153,7 @@ static wchar_t c2u_DE[256] = {
0x7A18,0x7A19,0x7A12,0x7A17,0x7A15,0x7A22,0x7A13,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_DF[256] = {
+static const wchar_t c2u_DF[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2189,7 +2189,7 @@ static wchar_t c2u_DF[256] = {
0x88CC,0x88D0,0x8985,0x899B,0x89DF,0x89E5,0x89E4,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E0[256] = {
+static const wchar_t c2u_E0[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2225,7 +2225,7 @@ static wchar_t c2u_E0[256] = {
0x50E4,0x50D3,0x50EC,0x50F0,0x50EF,0x50E3,0x50E0,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E1[256] = {
+static const wchar_t c2u_E1[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2261,7 +2261,7 @@ static wchar_t c2u_E1[256] = {
0x669F,0x6705,0x6704,0x6722,0x69B1,0x69B6,0x69C9,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E2[256] = {
+static const wchar_t c2u_E2[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2297,7 +2297,7 @@ static wchar_t c2u_E2[256] = {
0x7998,0x798A,0x798B,0x7996,0x7995,0x7994,0x7993,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E3[256] = {
+static const wchar_t c2u_E3[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2333,7 +2333,7 @@ static wchar_t c2u_E3[256] = {
0x88F2,0x88FA,0x88FE,0x88EE,0x88FC,0x88F6,0x88FB,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E4[256] = {
+static const wchar_t c2u_E4[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2369,7 +2369,7 @@ static wchar_t c2u_E4[256] = {
0x564C,0x5635,0x5641,0x564A,0x5649,0x5646,0x5658,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E5[256] = {
+static const wchar_t c2u_E5[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2405,7 +2405,7 @@ static wchar_t c2u_E5[256] = {
0x6C02,0x6F41,0x6F26,0x6F7E,0x6F87,0x6FC6,0x6F92,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E6[256] = {
+static const wchar_t c2u_E6[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2441,7 +2441,7 @@ static wchar_t c2u_E6[256] = {
0x7FEC,0x7FE6,0x7FE8,0x8064,0x8067,0x81A3,0x819F,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E7[256] = {
+static const wchar_t c2u_E7[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2477,7 +2477,7 @@ static wchar_t c2u_E7[256] = {
0x8E15,0x8E1B,0x8E16,0x8E11,0x8E19,0x8E26,0x8E27,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E8[256] = {
+static const wchar_t c2u_E8[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2513,7 +2513,7 @@ static wchar_t c2u_E8[256] = {
0x5111,0x51DE,0x5334,0x53E1,0x5670,0x5660,0x566E,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_E9[256] = {
+static const wchar_t c2u_E9[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2549,7 +2549,7 @@ static wchar_t c2u_E9[256] = {
0x6FAE,0x6FBA,0x6FAC,0x6FAA,0x6FCF,0x6FBF,0x6FB8,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_EA[256] = {
+static const wchar_t c2u_EA[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2585,7 +2585,7 @@ static wchar_t c2u_EA[256] = {
0x8556,0x8545,0x856B,0x854D,0x8553,0x8561,0x8558,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_EB[256] = {
+static const wchar_t c2u_EB[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2621,7 +2621,7 @@ static wchar_t c2u_EB[256] = {
0x92FF,0x9329,0x9339,0x9335,0x932A,0x9314,0x930C,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_EC[256] = {
+static const wchar_t c2u_EC[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2657,7 +2657,7 @@ static wchar_t c2u_EC[256] = {
0x6A9F,0x6A9B,0x6AA1,0x6A9E,0x6A87,0x6A93,0x6A8E,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_ED[256] = {
+static const wchar_t c2u_ED[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2693,7 +2693,7 @@ static wchar_t c2u_ED[256] = {
0x85A0,0x858B,0x85A3,0x857B,0x85A4,0x859A,0x859E,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_EE[256] = {
+static const wchar_t c2u_EE[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2729,7 +2729,7 @@ static wchar_t c2u_EE[256] = {
0x971F,0x9718,0x971D,0x9719,0x979A,0x97A1,0x979C,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_EF[256] = {
+static const wchar_t c2u_EF[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2765,7 +2765,7 @@ static wchar_t c2u_EF[256] = {
0x700A,0x7201,0x71FF,0x71F9,0x7203,0x71FD,0x7376,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_F0[256] = {
+static const wchar_t c2u_F0[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2801,7 +2801,7 @@ static wchar_t c2u_F0[256] = {
0x8E62,0x8E60,0x8E57,0x8E56,0x8E5E,0x8E65,0x8E67,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_F1[256] = {
+static const wchar_t c2u_F1[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2837,7 +2837,7 @@ static wchar_t c2u_F1[256] = {
0x58DB,0x5912,0x5B3D,0x5B3E,0x5B3F,0x5DC3,0x5E70,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_F2[256] = {
+static const wchar_t c2u_F2[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2873,7 +2873,7 @@ static wchar_t c2u_F2[256] = {
0x8B4A,0x8B40,0x8B53,0x8B56,0x8B54,0x8B4B,0x8B55,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_F3[256] = {
+static const wchar_t c2u_F3[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2909,7 +2909,7 @@ static wchar_t c2u_F3[256] = {
0x9F41,0x9F4D,0x9F56,0x9F57,0x9F58,0x5337,0x56B2,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_F4[256] = {
+static const wchar_t c2u_F4[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2945,7 +2945,7 @@ static wchar_t c2u_F4[256] = {
0x9416,0x9412,0x93FA,0x9409,0x93F8,0x940A,0x93FF,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_F5[256] = {
+static const wchar_t c2u_F5[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -2981,7 +2981,7 @@ static wchar_t c2u_F5[256] = {
0x8627,0x862E,0x8621,0x8620,0x8629,0x861E,0x8625,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_F6[256] = {
+static const wchar_t c2u_F6[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3017,7 +3017,7 @@ static wchar_t c2u_F6[256] = {
0x7A70,0x7A71,0x7C57,0x7C5C,0x7C59,0x7C5B,0x7C5A,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_F7[256] = {
+static const wchar_t c2u_F7[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3053,7 +3053,7 @@ static wchar_t c2u_F7[256] = {
0x8832,0x882E,0x8833,0x8976,0x8974,0x8973,0x89FE,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_F8[256] = {
+static const wchar_t c2u_F8[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3089,7 +3089,7 @@ static wchar_t c2u_F8[256] = {
0x77D8,0x77D9,0x7939,0x7C69,0x7C6B,0x7CF6,0x7E9A,0x0000,/* 0xF8-0xFF */
};
-static wchar_t c2u_F9[256] = {
+static const wchar_t c2u_F9[256] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x00-0x07 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x08-0x0F */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,/* 0x10-0x17 */
@@ -3125,7 +3125,7 @@ static wchar_t c2u_F9[256] = {
0x2551,0x2550,0x256D,0x256E,0x2570,0x256F,0x2593,0x0000,/* 0xF8-0xFF */
};
-static wchar_t *page_charset2uni[256] = {
+static const wchar_t *page_charset2uni[256] = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -3160,7 +3160,7 @@ static wchar_t *page_charset2uni[256] = {
c2u_F8, c2u_F9, NULL, NULL, NULL, NULL, NULL, NULL,
};
-static unsigned char u2c_02[512] = {
+static const unsigned char u2c_02[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -3219,7 +3219,7 @@ static unsigned char u2c_02[512] = {
0x00, 0x00, 0xA3, 0xBB, 0x00, 0x00, 0x00, 0x00, /* 0xD8-0xDB */
};
-static unsigned char u2c_03[512] = {
+static const unsigned char u2c_03[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0xA1, 0xC2, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -3274,7 +3274,7 @@ static unsigned char u2c_03[512] = {
0xA3, 0x72, 0xA3, 0x73, 0x00, 0x00, 0x00, 0x00, /* 0xC8-0xCB */
};
-static unsigned char u2c_20[512] = {
+static const unsigned char u2c_20[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -3293,7 +3293,7 @@ static unsigned char u2c_20[512] = {
0x00, 0x00, 0x00, 0x00, 0xA1, 0xC3, 0x00, 0x00, /* 0x3C-0x3F */
};
-static unsigned char u2c_21[512] = {
+static const unsigned char u2c_21[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x4A, /* 0x00-0x03 */
0x00, 0x00, 0xA1, 0xC1, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0xA2, 0x4B, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -3336,7 +3336,7 @@ static unsigned char u2c_21[512] = {
0xA1, 0xFB, 0xA1, 0xFA, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9B */
};
-static unsigned char u2c_22[512] = {
+static const unsigned char u2c_22[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -3388,12 +3388,12 @@ static unsigned char u2c_22[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xE9, /* 0xBC-0xBF */
};
-static unsigned char u2c_23[512] = {
+static const unsigned char u2c_23[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0x5B, /* 0x04-0x07 */
};
-static unsigned char u2c_25[512] = {
+static const unsigned char u2c_25[512] = {
0xA2, 0x77, 0x00, 0x00, 0xA2, 0x78, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -3455,7 +3455,7 @@ static unsigned char u2c_25[512] = {
0xA2, 0xAB, 0xA2, 0xAA, 0x00, 0x00, 0x00, 0x00, /* 0xE4-0xE7 */
};
-static unsigned char u2c_26[512] = {
+static const unsigned char u2c_26[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0xA1, 0xB9, 0xA1, 0xB8, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0xA1, 0xF3, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -3475,7 +3475,7 @@ static unsigned char u2c_26[512] = {
0xA1, 0xF0, 0xA1, 0xF2, 0xA1, 0xF1, 0x00, 0x00, /* 0x40-0x43 */
};
-static unsigned char u2c_30[512] = {
+static const unsigned char u2c_30[512] = {
0xA1, 0x40, 0xA1, 0x42, 0xA1, 0x43, 0xA1, 0xB2, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0xA1, 0x71, 0xA1, 0x72, 0xA1, 0x6D, 0xA1, 0x6E, /* 0x08-0x0B */
@@ -3491,7 +3491,7 @@ static unsigned char u2c_30[512] = {
0xA1, 0xCA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x33 */
};
-static unsigned char u2c_31[512] = {
+static const unsigned char u2c_31[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0xA3, 0x74, 0xA3, 0x75, 0xA3, 0x76, /* 0x04-0x07 */
0xA3, 0x77, 0xA3, 0x78, 0xA3, 0x79, 0xA3, 0x7A, /* 0x08-0x0B */
@@ -3535,7 +3535,7 @@ static unsigned char u2c_31[512] = {
0xA4, 0x42, 0xA4, 0xD1, 0xA6, 0x61, 0xA4, 0x48, /* 0x9C-0x9F */
};
-static unsigned char u2c_32[512] = {
+static const unsigned char u2c_32[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -3584,7 +3584,7 @@ static unsigned char u2c_32[512] = {
0xA9, 0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xB0-0xB3 */
};
-static unsigned char u2c_33[512] = {
+static const unsigned char u2c_33[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -3642,7 +3642,7 @@ static unsigned char u2c_33[512] = {
0x00, 0x00, 0xA2, 0x4F, 0x00, 0x00, 0x00, 0x00, /* 0xD4-0xD7 */
};
-static unsigned char u2c_4E[512] = {
+static const unsigned char u2c_4E[512] = {
0xA4, 0x40, 0xA4, 0x42, 0x00, 0x00, 0xA4, 0x43, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC9, 0x45, /* 0x04-0x07 */
0xA4, 0x56, 0xA4, 0x54, 0xA4, 0x57, 0xA4, 0x55, /* 0x08-0x0B */
@@ -3710,7 +3710,7 @@ static unsigned char u2c_4E[512] = {
0x00, 0x00, 0xA5, 0xF7, 0x00, 0x00, 0xA5, 0xE9, /* 0xFC-0xFF */
};
-static unsigned char u2c_4F[512] = {
+static const unsigned char u2c_4F[512] = {
0xC9, 0xB1, 0xA5, 0xF8, 0xC9, 0xB5, 0x00, 0x00, /* 0x00-0x03 */
0xC9, 0xB9, 0xC9, 0xB6, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0xC9, 0xB3, 0xA5, 0xEA, 0xA5, 0xEC, 0xA5, 0xF9, /* 0x08-0x0B */
@@ -3778,7 +3778,7 @@ static unsigned char u2c_4F[512] = {
0x00, 0x00, 0x00, 0x00, 0xAD, 0xDA, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_50[512] = {
+static const unsigned char u2c_50[512] = {
0xAD, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0xD0, 0xC9, 0xAD, 0xC7, 0xD0, 0xCA, /* 0x04-0x07 */
0x00, 0x00, 0xAD, 0xDC, 0x00, 0x00, 0xAD, 0xD3, /* 0x08-0x0B */
@@ -3846,7 +3846,7 @@ static unsigned char u2c_50[512] = {
0x00, 0x00, 0xE4, 0xF0, 0xE4, 0xED, 0xE4, 0xE6, /* 0xFC-0xFF */
};
-static unsigned char u2c_51[512] = {
+static const unsigned char u2c_51[512] = {
0xBB, 0xF6, 0x00, 0x00, 0xBB, 0xFA, 0xE4, 0xE7, /* 0x00-0x03 */
0xBB, 0xF5, 0xBB, 0xFD, 0xE4, 0xEA, 0xE4, 0xEB, /* 0x04-0x07 */
0xBB, 0xFB, 0xBB, 0xFC, 0xE4, 0xF1, 0xE4, 0xEE, /* 0x08-0x0B */
@@ -3914,7 +3914,7 @@ static unsigned char u2c_51[512] = {
0x00, 0x00, 0xA8, 0xE7, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_52[512] = {
+static const unsigned char u2c_52[512] = {
0xA4, 0x4D, 0xA4, 0x4E, 0x00, 0x00, 0xA4, 0x62, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0xA4, 0xC0, 0xA4, 0xC1, /* 0x04-0x07 */
0xA4, 0xC2, 0xC9, 0xBE, 0xA5, 0x5A, 0x00, 0x00, /* 0x08-0x0B */
@@ -3982,7 +3982,7 @@ static unsigned char u2c_52[512] = {
0xC9, 0x56, 0x00, 0x00, 0xA4, 0xC4, 0xA4, 0xC5, /* 0xFC-0xFF */
};
-static unsigned char u2c_53[512] = {
+static const unsigned char u2c_53[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0xA5, 0x5D, 0xA5, 0x5E, 0x00, 0x00, /* 0x04-0x07 */
0xA6, 0x49, 0xCA, 0x71, 0xCB, 0xD6, 0xCB, 0xD7, /* 0x08-0x0B */
@@ -4050,7 +4050,7 @@ static unsigned char u2c_53[512] = {
0xA5, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_54[512] = {
+static const unsigned char u2c_54[512] = {
0x00, 0x00, 0xA6, 0x53, 0x00, 0x00, 0xA6, 0x59, /* 0x00-0x03 */
0xA6, 0x55, 0x00, 0x00, 0xA6, 0x5B, 0xC9, 0xC5, /* 0x04-0x07 */
0xA6, 0x58, 0xA6, 0x4E, 0xA6, 0x51, 0xA6, 0x54, /* 0x08-0x0B */
@@ -4118,7 +4118,7 @@ static unsigned char u2c_54[512] = {
0xAD, 0xF3, 0xAE, 0x43, 0x00, 0x00, 0xD0, 0xF8, /* 0xFC-0xFF */
};
-static unsigned char u2c_55[512] = {
+static const unsigned char u2c_55[512] = {
0x00, 0x00, 0xAD, 0xF1, 0x00, 0x00, 0xD1, 0x46, /* 0x00-0x03 */
0xD0, 0xF9, 0xD0, 0xFD, 0xAD, 0xF6, 0xAE, 0x42, /* 0x04-0x07 */
0xD0, 0xFA, 0xAD, 0xFC, 0xD1, 0x40, 0xD1, 0x47, /* 0x08-0x0B */
@@ -4186,7 +4186,7 @@ static unsigned char u2c_55[512] = {
0xE1, 0x4B, 0xB9, 0xC2, 0xB9, 0xBE, 0xE1, 0x54, /* 0xFC-0xFF */
};
-static unsigned char u2c_56[512] = {
+static const unsigned char u2c_56[512] = {
0xB9, 0xBF, 0xE1, 0x4E, 0xE1, 0x50, 0x00, 0x00, /* 0x00-0x03 */
0xE1, 0x53, 0x00, 0x00, 0xB9, 0xC4, 0x00, 0x00, /* 0x04-0x07 */
0xB9, 0xCB, 0xB9, 0xC5, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -4254,7 +4254,7 @@ static unsigned char u2c_56[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAB, 0xAA, /* 0xFC-0xFF */
};
-static unsigned char u2c_57[512] = {
+static const unsigned char u2c_57[512] = {
0x00, 0x00, 0xD1, 0x48, 0xD1, 0x49, 0xAE, 0x45, /* 0x00-0x03 */
0xAE, 0x46, 0x00, 0x00, 0x00, 0x00, 0xD4, 0xAC, /* 0x04-0x07 */
0xB0, 0xE9, 0xB0, 0xEB, 0xD4, 0xAB, 0xB0, 0xEA, /* 0x08-0x0B */
@@ -4322,7 +4322,7 @@ static unsigned char u2c_57[512] = {
0xD4, 0xC3, 0xD4, 0xB5, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_58[512] = {
+static const unsigned char u2c_58[512] = {
0xD4, 0xB3, 0xD4, 0xC6, 0xB0, 0xF3, 0x00, 0x00, /* 0x00-0x03 */
0xD4, 0xCC, 0xB0, 0xED, 0xB0, 0xEF, 0xD4, 0xBB, /* 0x04-0x07 */
0xD4, 0xB6, 0xAE, 0x4B, 0xB0, 0xEE, 0xD4, 0xB8, /* 0x08-0x0B */
@@ -4390,7 +4390,7 @@ static unsigned char u2c_58[512] = {
0xDC, 0xF2, 0xB9, 0xD8, 0xE1, 0x69, 0xE5, 0x53, /* 0xFC-0xFF */
};
-static unsigned char u2c_59[512] = {
+static const unsigned char u2c_59[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC9, 0x5A, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0xCA, 0xB0, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -4458,7 +4458,7 @@ static unsigned char u2c_59[512] = {
0xCE, 0x6A, 0xCE, 0x69, 0xCE, 0x74, 0xAB, 0xBA, /* 0xFC-0xFF */
};
-static unsigned char u2c_5A[512] = {
+static const unsigned char u2c_5A[512] = {
0xCE, 0x65, 0xAB, 0xC2, 0x00, 0x00, 0xAB, 0xBD, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0xAE, 0x5C, 0xD1, 0x62, 0x00, 0x00, /* 0x08-0x0B */
@@ -4526,7 +4526,7 @@ static unsigned char u2c_5A[512] = {
0x00, 0x00, 0xE5, 0x56, 0x00, 0x00, 0xE5, 0x54, /* 0xFC-0xFF */
};
-static unsigned char u2c_5B[512] = {
+static const unsigned char u2c_5B[512] = {
0x00, 0x00, 0xE5, 0x5D, 0xE5, 0x5B, 0xE5, 0x59, /* 0x00-0x03 */
0x00, 0x00, 0xE5, 0x5F, 0x00, 0x00, 0xE5, 0x5E, /* 0x04-0x07 */
0xBC, 0x63, 0xBC, 0x5E, 0x00, 0x00, 0xBC, 0x60, /* 0x08-0x0B */
@@ -4594,7 +4594,7 @@ static unsigned char u2c_5B[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_5C[512] = {
+static const unsigned char u2c_5C[512] = {
0x00, 0x00, 0xAB, 0xCA, 0x00, 0x00, 0xD1, 0x69, /* 0x00-0x03 */
0xAE, 0x67, 0x00, 0x00, 0x00, 0x00, 0xB1, 0x4E, /* 0x04-0x07 */
0xB1, 0x4D, 0xB1, 0x4C, 0xB4, 0x4C, 0xB4, 0x4D, /* 0x08-0x0B */
@@ -4662,7 +4662,7 @@ static unsigned char u2c_5C[512] = {
0x00, 0x00, 0xAE, 0x6C, 0x00, 0x00, 0xD1, 0x6D, /* 0xFC-0xFF */
};
-static unsigned char u2c_5D[512] = {
+static const unsigned char u2c_5D[512] = {
0xD1, 0x71, 0xAE, 0x72, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0xB1, 0x53, 0xB1, 0x52, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD4, 0xF5, /* 0x08-0x0B */
@@ -4730,7 +4730,7 @@ static unsigned char u2c_5D[512] = {
0x00, 0x00, 0xB4, 0x53, 0xA4, 0x79, 0xC9, 0x5D, /* 0xFC-0xFF */
};
-static unsigned char u2c_5E[512] = {
+static const unsigned char u2c_5E[512] = {
0x00, 0x00, 0x00, 0x00, 0xA5, 0xAB, 0xA5, 0xAC, /* 0x00-0x03 */
0xC9, 0x78, 0x00, 0x00, 0xA6, 0x7C, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0xCA, 0xCB, 0x00, 0x00, /* 0x08-0x0B */
@@ -4798,7 +4798,7 @@ static unsigned char u2c_5E[512] = {
0x00, 0x00, 0x00, 0x00, 0xA4, 0x7B, 0xA4, 0xDC, /* 0xFC-0xFF */
};
-static unsigned char u2c_5F[512] = {
+static const unsigned char u2c_5F[512] = {
0x00, 0x00, 0xA5, 0xAF, 0xC9, 0xDD, 0x00, 0x00, /* 0x00-0x03 */
0xA7, 0xCB, 0xCA, 0xD2, 0x00, 0x00, 0xCE, 0xBB, /* 0x04-0x07 */
0xAB, 0xD9, 0x00, 0x00, 0xB9, 0xFA, 0xA4, 0x7C, /* 0x08-0x0B */
@@ -4866,7 +4866,7 @@ static unsigned char u2c_5F[512] = {
0x00, 0x00, 0xA9, 0xBF, 0x00, 0x00, 0xA9, 0xC1, /* 0xFC-0xFF */
};
-static unsigned char u2c_60[512] = {
+static const unsigned char u2c_60[512] = {
0xCA, 0xE4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0xCC, 0xAF, 0xCC, 0xA2, 0xCC, 0x7E, /* 0x08-0x0B */
@@ -4934,7 +4934,7 @@ static unsigned char u2c_60[512] = {
0xD9, 0x47, 0x00, 0x00, 0xD9, 0x48, 0xD9, 0x4E, /* 0xFC-0xFF */
};
-static unsigned char u2c_61[512] = {
+static const unsigned char u2c_61[512] = {
0xB4, 0x73, 0xB7, 0x54, 0x00, 0x00, 0xD9, 0x4A, /* 0x00-0x03 */
0xD9, 0x4F, 0xD9, 0x43, 0xB7, 0x5E, 0x00, 0x00, /* 0x04-0x07 */
0xB7, 0x55, 0xB4, 0x72, 0xD9, 0x41, 0xD9, 0x50, /* 0x08-0x0B */
@@ -5002,7 +5002,7 @@ static unsigned char u2c_61[512] = {
0xC4, 0xDF, 0xF5, 0xCC, 0xC4, 0xE0, 0xC5, 0x74, /* 0xFC-0xFF */
};
-static unsigned char u2c_62[512] = {
+static const unsigned char u2c_62[512] = {
0xC5, 0xCA, 0xF7, 0xD9, 0x00, 0x00, 0xF7, 0xDA, /* 0x00-0x03 */
0xF7, 0xDB, 0x00, 0x00, 0x00, 0x00, 0xF9, 0xBA, /* 0x04-0x07 */
0xA4, 0xE0, 0xC9, 0x7C, 0xA5, 0xB3, 0x00, 0x00, /* 0x08-0x0B */
@@ -5070,7 +5070,7 @@ static unsigned char u2c_62[512] = {
0xAB, 0xF7, 0xAB, 0xFB, 0xAC, 0x42, 0xAE, 0xB3, /* 0xFC-0xFF */
};
-static unsigned char u2c_63[512] = {
+static const unsigned char u2c_63[512] = {
0xCE, 0xE0, 0xAB, 0xF9, 0xAC, 0x45, 0xCE, 0xD9, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAB, 0xFC, /* 0x04-0x07 */
0xAE, 0xB2, 0xAB, 0xF6, 0x00, 0x00, 0xCE, 0xD6, /* 0x08-0x0B */
@@ -5138,7 +5138,7 @@ static unsigned char u2c_63[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_64[512] = {
+static const unsigned char u2c_64[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0xB7, 0x70, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0xDD, 0x7C, 0xDD, 0xB1, 0xDD, 0xB6, /* 0x08-0x0B */
@@ -5206,7 +5206,7 @@ static unsigned char u2c_64[512] = {
0xEF, 0xD7, 0xEF, 0xD3, 0xC2, 0x5A, 0xEF, 0xD1, /* 0xFC-0xFF */
};
-static unsigned char u2c_65[512] = {
+static const unsigned char u2c_65[512] = {
0xC3, 0x6B, 0xEF, 0xD5, 0x00, 0x00, 0xEF, 0xD6, /* 0x00-0x03 */
0xEF, 0xD2, 0x00, 0x00, 0xC2, 0x5B, 0xF2, 0x42, /* 0x04-0x07 */
0x00, 0x00, 0xF2, 0x45, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -5274,7 +5274,7 @@ static unsigned char u2c_65[512] = {
0xCC, 0xC5, 0xCC, 0xCE, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_66[512] = {
+static const unsigned char u2c_66[512] = {
0xA9, 0xFB, 0x00, 0x00, 0xA9, 0xF9, 0xCC, 0xCA, /* 0x00-0x03 */
0xCC, 0xC6, 0xCC, 0xCD, 0xA9, 0xF8, 0xAA, 0x40, /* 0x04-0x07 */
0xCC, 0xC8, 0xCC, 0xC4, 0xA9, 0xFE, 0xCC, 0xCB, /* 0x08-0x0B */
@@ -5342,7 +5342,7 @@ static unsigned char u2c_66[512] = {
0xB0, 0xD2, 0x00, 0x00, 0xB4, 0xBF, 0xB4, 0xC0, /* 0xFC-0xFF */
};
-static unsigned char u2c_67[512] = {
+static const unsigned char u2c_67[512] = {
0xB3, 0xCC, 0xD9, 0xA9, 0x00, 0x00, 0xB7, 0x7C, /* 0x00-0x03 */
0xE1, 0xFA, 0xE1, 0xF9, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0xA4, 0xEB, 0xA6, 0xB3, 0xCC, 0xD2, 0xAA, 0x42, /* 0x08-0x0B */
@@ -5410,7 +5410,7 @@ static unsigned char u2c_67[512] = {
0xCF, 0x57, 0x00, 0x00, 0x00, 0x00, 0xAC, 0x55, /* 0xFC-0xFF */
};
-static unsigned char u2c_68[512] = {
+static const unsigned char u2c_68[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -5478,7 +5478,7 @@ static unsigned char u2c_68[512] = {
0xD9, 0xC8, 0xD9, 0xC7, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_69[512] = {
+static const unsigned char u2c_69[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0xD9, 0xAC, 0xB4, 0xC8, 0xD9, 0xD4, 0xD9, 0xBC, /* 0x04-0x07 */
0xD9, 0xBE, 0x00, 0x00, 0xD9, 0xCB, 0xD9, 0xCA, /* 0x08-0x0B */
@@ -5546,7 +5546,7 @@ static unsigned char u2c_69[512] = {
0xE5, 0xE4, 0xBC, 0xD1, 0xE5, 0xD8, 0xE5, 0xD3, /* 0xFC-0xFF */
};
-static unsigned char u2c_6A[512] = {
+static const unsigned char u2c_6A[512] = {
0xE5, 0xCA, 0xBC, 0xCE, 0xBC, 0xD6, 0x00, 0x00, /* 0x00-0x03 */
0xE5, 0xE7, 0xBC, 0xD7, 0xE5, 0xCB, 0xE5, 0xED, /* 0x04-0x07 */
0xE5, 0xE0, 0xE5, 0xE6, 0xBC, 0xD4, 0x00, 0x00, /* 0x08-0x0B */
@@ -5614,7 +5614,7 @@ static unsigned char u2c_6A[512] = {
0xF5, 0xCF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_6B[512] = {
+static const unsigned char u2c_6B[512] = {
0xF5, 0xD2, 0x00, 0x00, 0xF5, 0xCE, 0xF5, 0xD0, /* 0x00-0x03 */
0xC4, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0xF6, 0xE5, 0xF6, 0xE6, 0xC5, 0x76, 0xF6, 0xE4, /* 0x08-0x0B */
@@ -5682,7 +5682,7 @@ static unsigned char u2c_6B[512] = {
0xDD, 0xFE, 0xB7, 0xB7, 0xE2, 0x6B, 0xE5, 0xF7, /* 0xFC-0xFF */
};
-static unsigned char u2c_6C[512] = {
+static const unsigned char u2c_6C[512] = {
0xE5, 0xF6, 0xE5, 0xF5, 0xE5, 0xF8, 0xE9, 0xE7, /* 0x00-0x03 */
0xE9, 0xE6, 0xBE, 0xFB, 0xE9, 0xE8, 0x00, 0x00, /* 0x04-0x07 */
0xC0, 0xD6, 0xED, 0x4D, 0x00, 0x00, 0xEF, 0xEA, /* 0x08-0x0B */
@@ -5749,7 +5749,7 @@ static unsigned char u2c_6C[512] = {
0x00, 0x00, 0xCD, 0x4C, 0x00, 0x00, 0x00, 0x00, /* 0xF8-0xFB */
};
-static unsigned char u2c_6D[512] = {
+static const unsigned char u2c_6D[512] = {
0xCF, 0x7C, 0xCF, 0xA1, 0x00, 0x00, 0xCF, 0xA4, /* 0x00-0x03 */
0xCF, 0x77, 0x00, 0x00, 0x00, 0x00, 0xCF, 0xA7, /* 0x04-0x07 */
0xCF, 0xAA, 0xCF, 0xAC, 0xCF, 0x74, 0xAC, 0x76, /* 0x08-0x0B */
@@ -5817,7 +5817,7 @@ static unsigned char u2c_6D[512] = {
0xD9, 0xE7, 0xD6, 0x43, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_6E[512] = {
+static const unsigned char u2c_6E[512] = {
0xD5, 0xEB, 0x00, 0x00, 0x00, 0x00, 0xD9, 0xFC, /* 0x00-0x03 */
0x00, 0x00, 0xB2, 0x4D, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -5885,7 +5885,7 @@ static unsigned char u2c_6E[512] = {
0xE2, 0xB3, 0xE2, 0xAF, 0xBA, 0x75, 0xBA, 0xA1, /* 0xFC-0xFF */
};
-static unsigned char u2c_6F[512] = {
+static const unsigned char u2c_6F[512] = {
0xE6, 0x53, 0xBA, 0xAE, 0xBA, 0x7D, 0xE2, 0x6F, /* 0x00-0x03 */
0x00, 0x00, 0xE2, 0xAE, 0xBA, 0xA3, 0xE2, 0xAB, /* 0x04-0x07 */
0xE2, 0xB8, 0xE2, 0x75, 0xE2, 0x7E, 0x00, 0x00, /* 0x08-0x0B */
@@ -5953,7 +5953,7 @@ static unsigned char u2c_6F[512] = {
0xEF, 0xF6, 0x00, 0x00, 0xC2, 0x6F, 0xEF, 0xF2, /* 0xFC-0xFF */
};
-static unsigned char u2c_70[512] = {
+static const unsigned char u2c_70[512] = {
0xEF, 0xF3, 0xEF, 0xEE, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0xE9, 0xF6, 0xEF, 0xEF, 0xC2, 0x70, 0xEF, 0xEB, /* 0x04-0x07 */
0x00, 0x00, 0xC2, 0x6D, 0xEF, 0xF8, 0xC2, 0x6E, /* 0x08-0x0B */
@@ -6021,7 +6021,7 @@ static unsigned char u2c_70[512] = {
0xD6, 0x52, 0xB2, 0x6C, 0x00, 0x00, 0xD6, 0x53, /* 0xFC-0xFF */
};
-static unsigned char u2c_71[512] = {
+static const unsigned char u2c_71[512] = {
0xD6, 0x56, 0x00, 0x00, 0xD6, 0x5A, 0x00, 0x00, /* 0x00-0x03 */
0xD6, 0x4F, 0x00, 0x00, 0xD6, 0x54, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0xB2, 0x6A, 0xB2, 0x6B, 0xD6, 0x59, /* 0x08-0x0B */
@@ -6089,7 +6089,7 @@ static unsigned char u2c_71[512] = {
0xC2, 0x75, 0xEF, 0xFD, 0xC2, 0x76, 0xEF, 0xFA, /* 0xFC-0xFF */
};
-static unsigned char u2c_72[512] = {
+static const unsigned char u2c_72[512] = {
0x00, 0x00, 0xEF, 0xF9, 0xF2, 0x6C, 0xEF, 0xFC, /* 0x00-0x03 */
0x00, 0x00, 0xF2, 0x6D, 0xC3, 0x7A, 0xF2, 0x6B, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0xF2, 0x6A, 0x00, 0x00, /* 0x08-0x0B */
@@ -6157,7 +6157,7 @@ static unsigned char u2c_72[512] = {
0xAF, 0x54, 0xAF, 0x56, 0xD2, 0xA6, 0xD6, 0x67, /* 0xFC-0xFF */
};
-static unsigned char u2c_73[512] = {
+static const unsigned char u2c_73[512] = {
0xD2, 0xA3, 0xD2, 0xAA, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0x62, /* 0x04-0x07 */
0xD6, 0x66, 0x00, 0x00, 0xD6, 0x65, 0xDA, 0x6E, /* 0x08-0x0B */
@@ -6225,7 +6225,7 @@ static unsigned char u2c_73[512] = {
0xD6, 0x74, 0xD6, 0x70, 0xB2, 0x7B, 0xD6, 0x75, /* 0xFC-0xFF */
};
-static unsigned char u2c_74[512] = {
+static const unsigned char u2c_74[512] = {
0xD6, 0x72, 0xD6, 0x6F, 0x00, 0x00, 0xB2, 0x79, /* 0x00-0x03 */
0xD6, 0x6E, 0xB2, 0x77, 0xB2, 0x7A, 0xD6, 0x71, /* 0x04-0x07 */
0xD6, 0x79, 0xAF, 0x5B, 0xB2, 0x78, 0xD6, 0x77, /* 0x08-0x0B */
@@ -6293,7 +6293,7 @@ static unsigned char u2c_74[512] = {
0x00, 0x00, 0xDE, 0xC2, 0xDE, 0xC1, 0xDE, 0xC0, /* 0xFC-0xFF */
};
-static unsigned char u2c_75[512] = {
+static const unsigned char u2c_75[512] = {
0xE2, 0xD5, 0x00, 0x00, 0xE2, 0xD6, 0xE2, 0xD7, /* 0x00-0x03 */
0xBA, 0xC2, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xAD, /* 0x04-0x07 */
0xE6, 0xAC, 0x00, 0x00, 0x00, 0x00, 0xEA, 0x69, /* 0x08-0x0B */
@@ -6361,7 +6361,7 @@ static unsigned char u2c_75[512] = {
0xDE, 0xCC, 0xDE, 0xD4, 0xDE, 0xCB, 0xB7, 0xF5, /* 0xFC-0xFF */
};
-static unsigned char u2c_76[512] = {
+static const unsigned char u2c_76[512] = {
0xB7, 0xEF, 0xB7, 0xF1, 0x00, 0x00, 0xDE, 0xC9, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0xE2, 0xDB, 0xBA, 0xC7, 0xE2, 0xDF, 0xBA, 0xC6, /* 0x08-0x0B */
@@ -6429,7 +6429,7 @@ static unsigned char u2c_76[512] = {
0xAC, 0xDF, 0x00, 0x00, 0xAC, 0xDE, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_77[512] = {
+static const unsigned char u2c_77[512] = {
0x00, 0x00, 0xAC, 0xD9, 0x00, 0x00, 0xCF, 0xE1, /* 0x00-0x03 */
0xCF, 0xE2, 0xCF, 0xE3, 0x00, 0x00, 0xAC, 0xE0, /* 0x04-0x07 */
0xCF, 0xE0, 0xAC, 0xDC, 0xCF, 0xE4, 0xAC, 0xDD, /* 0x08-0x0B */
@@ -6497,7 +6497,7 @@ static unsigned char u2c_77[512] = {
0xCD, 0x7B, 0xAA, 0xBF, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_78[512] = {
+static const unsigned char u2c_78[512] = {
0x00, 0x00, 0x00, 0x00, 0xAC, 0xE2, 0xCF, 0xF2, /* 0x00-0x03 */
0x00, 0x00, 0xCF, 0xED, 0xCF, 0xEA, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0xCF, 0xF1, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -6565,7 +6565,7 @@ static unsigned char u2c_78[512] = {
0xED, 0xA9, 0xED, 0xA6, 0xED, 0xAD, 0xF0, 0x56, /* 0xFC-0xFF */
};
-static unsigned char u2c_79[512] = {
+static const unsigned char u2c_79[512] = {
0x00, 0x00, 0xC1, 0x47, 0xED, 0xA7, 0x00, 0x00, /* 0x00-0x03 */
0xED, 0xAE, 0xED, 0xAB, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0xF0, 0x5A, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -6633,7 +6633,7 @@ static unsigned char u2c_79[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_7A[512] = {
+static const unsigned char u2c_7A[512] = {
0xB5, 0x7D, 0x00, 0x00, 0xDA, 0xD6, 0xDA, 0xD8, /* 0x00-0x03 */
0xDA, 0xDA, 0xB5, 0x7C, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0xB5, 0x7A, 0x00, 0x00, 0xDA, 0xD7, 0xB5, 0x7B, /* 0x08-0x0B */
@@ -6701,7 +6701,7 @@ static unsigned char u2c_7A[512] = {
0x00, 0x00, 0xAC, 0xF2, 0x00, 0x00, 0xAC, 0xF1, /* 0xFC-0xFF */
};
-static unsigned char u2c_7B[512] = {
+static const unsigned char u2c_7B[512] = {
0xD0, 0x42, 0xD0, 0x43, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0xD3, 0x40, 0xD3, 0x42, 0xAF, 0xB9, 0x00, 0x00, /* 0x04-0x07 */
0xD3, 0x44, 0xD3, 0x47, 0xD3, 0x45, 0x00, 0x00, /* 0x08-0x0B */
@@ -6769,7 +6769,7 @@ static unsigned char u2c_7B[512] = {
0x00, 0x00, 0xED, 0xC9, 0xC1, 0x4E, 0xED, 0xBE, /* 0xFC-0xFF */
};
-static unsigned char u2c_7C[512] = {
+static const unsigned char u2c_7C[512] = {
0xED, 0xBD, 0xED, 0xC7, 0xED, 0xC4, 0xED, 0xC6, /* 0x00-0x03 */
0x00, 0x00, 0xED, 0xBA, 0xED, 0xCA, 0xC1, 0x4C, /* 0x04-0x07 */
0x00, 0x00, 0xED, 0xC5, 0xED, 0xCE, 0xED, 0xC2, /* 0x08-0x0B */
@@ -6837,7 +6837,7 @@ static unsigned char u2c_7C[512] = {
0x00, 0x00, 0xCD, 0xA9, 0xAA, 0xC8, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_7D[512] = {
+static const unsigned char u2c_7D[512] = {
0xAC, 0xF6, 0xD0, 0x4C, 0xAC, 0xF4, 0xD0, 0x4A, /* 0x00-0x03 */
0xAC, 0xF9, 0xAC, 0xF5, 0xAC, 0xFA, 0xAC, 0xF8, /* 0x04-0x07 */
0xD0, 0x4B, 0xAC, 0xF7, 0xAF, 0xBF, 0xAF, 0xBE, /* 0x08-0x0B */
@@ -6904,7 +6904,7 @@ static unsigned char u2c_7D[512] = {
0x00, 0x00, 0xBD, 0x7B, 0xE6, 0xEA, 0xBD, 0x6F, /* 0xF8-0xFB */
};
-static unsigned char u2c_7E[512] = {
+static const unsigned char u2c_7E[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xE9, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0xBF, 0xA2, 0xBF, 0xA7, 0xBF, 0x7E, 0xEA, 0xD8, /* 0x08-0x0B */
@@ -6948,7 +6948,7 @@ static unsigned char u2c_7E[512] = {
0xC6, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9C-0x9F */
};
-static unsigned char u2c_7F[512] = {
+static const unsigned char u2c_7F[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -7016,7 +7016,7 @@ static unsigned char u2c_7F[512] = {
0xC1, 0x6C, 0xF2, 0xBE, 0xF2, 0xBF, 0xF4, 0xB1, /* 0xFC-0xFF */
};
-static unsigned char u2c_80[512] = {
+static const unsigned char u2c_80[512] = {
0xC4, 0xA3, 0xA6, 0xD1, 0x00, 0x00, 0xA6, 0xD2, /* 0x00-0x03 */
0xAC, 0xFE, 0xAA, 0xCC, 0xAF, 0xCF, 0xD0, 0x51, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB5, 0xC0, /* 0x08-0x0B */
@@ -7084,7 +7084,7 @@ static unsigned char u2c_80[512] = {
0xAF, 0xE2, 0xAF, 0xE0, 0xDB, 0x48, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_81[512] = {
+static const unsigned char u2c_81[512] = {
0xD3, 0x6F, 0xD3, 0x6D, 0xAF, 0xD7, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0xAF, 0xD9, 0xAF, 0xDC, 0x00, 0x00, /* 0x04-0x07 */
0xAF, 0xDF, 0x00, 0x00, 0xAF, 0xE1, 0x00, 0x00, /* 0x08-0x0B */
@@ -7152,7 +7152,7 @@ static unsigned char u2c_81[512] = {
0xA6, 0xDD, 0x00, 0x00, 0xAA, 0xD8, 0xD0, 0x68, /* 0xFC-0xFF */
};
-static unsigned char u2c_82[512] = {
+static const unsigned char u2c_82[512] = {
0xAF, 0xE6, 0xD3, 0x70, 0xB2, 0xEA, 0x00, 0x00, /* 0x00-0x03 */
0xDB, 0x57, 0xB8, 0xA4, 0x00, 0x00, 0xBB, 0x50, /* 0x04-0x07 */
0xBF, 0xB3, 0xC1, 0x7C, 0xC2, 0xC2, 0xF4, 0xB5, /* 0x08-0x0B */
@@ -7220,7 +7220,7 @@ static unsigned char u2c_82[512] = {
0x00, 0x00, 0x00, 0x00, 0xD0, 0x6C, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_83[512] = {
+static const unsigned char u2c_83[512] = {
0xD0, 0x70, 0xAD, 0x5F, 0xAD, 0x5A, 0xAD, 0x53, /* 0x00-0x03 */
0xAD, 0x58, 0xAD, 0x54, 0xAD, 0x67, 0xD0, 0x6E, /* 0x04-0x07 */
0xD3, 0xA5, 0xAD, 0x5B, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -7288,7 +7288,7 @@ static unsigned char u2c_83[512] = {
0xDB, 0x65, 0xB5, 0xE0, 0xDB, 0xB0, 0xDB, 0x71, /* 0xFC-0xFF */
};
-static unsigned char u2c_84[512] = {
+static const unsigned char u2c_84[512] = {
0x00, 0x00, 0xDB, 0x6D, 0x00, 0x00, 0xB5, 0xD1, /* 0x00-0x03 */
0xB5, 0xE5, 0x00, 0x00, 0xDB, 0x7C, 0xB5, 0xE7, /* 0x04-0x07 */
0x00, 0x00, 0xDB, 0x78, 0xB5, 0xDC, 0xB5, 0xD6, /* 0x08-0x0B */
@@ -7356,7 +7356,7 @@ static unsigned char u2c_84[512] = {
0xE7, 0x64, 0xE7, 0x6E, 0xE7, 0x69, 0xBD, 0xB6, /* 0xFC-0xFF */
};
-static unsigned char u2c_85[512] = {
+static const unsigned char u2c_85[512] = {
0xE7, 0x4F, 0x00, 0x00, 0xE7, 0x6D, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0xBD, 0xB7, 0xDF, 0xBD, /* 0x04-0x07 */
0xE7, 0x5B, 0xE7, 0x52, 0xE7, 0x55, 0xE7, 0x7B, /* 0x08-0x0B */
@@ -7424,7 +7424,7 @@ static unsigned char u2c_85[512] = {
0x00, 0x00, 0xF4, 0xC3, 0xF4, 0xBB, 0xF4, 0xB9, /* 0xFC-0xFF */
};
-static unsigned char u2c_86[512] = {
+static const unsigned char u2c_86[512] = {
0xF4, 0xBD, 0xF4, 0xBA, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0xF4, 0xBF, 0xF4, 0xC1, 0xC4, 0xAA, 0xC4, 0xAC, /* 0x04-0x07 */
0x00, 0x00, 0xF4, 0xC0, 0xC4, 0xAD, 0xC4, 0xAB, /* 0x08-0x0B */
@@ -7492,7 +7492,7 @@ static unsigned char u2c_86[512] = {
0x00, 0x00, 0x00, 0x00, 0xB8, 0xBF, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_87[512] = {
+static const unsigned char u2c_87[512] = {
0xB8, 0xBE, 0xDF, 0xED, 0xB8, 0xC1, 0xB8, 0xC2, /* 0x00-0x03 */
0xDF, 0xE3, 0xDF, 0xF0, 0xB8, 0xC3, 0xB8, 0xBD, /* 0x04-0x07 */
0xB8, 0xBC, 0xDF, 0xEC, 0xB8, 0xC4, 0xDF, 0xE2, /* 0x08-0x0B */
@@ -7560,7 +7560,7 @@ static unsigned char u2c_87[512] = {
0xF2, 0xE4, 0x00, 0x00, 0xC3, 0xCA, 0xF2, 0xE6, /* 0xFC-0xFF */
};
-static unsigned char u2c_88[512] = {
+static const unsigned char u2c_88[512] = {
0xF2, 0xDB, 0xF0, 0xCE, 0xF2, 0xE8, 0xF2, 0xDD, /* 0x00-0x03 */
0x00, 0x00, 0xC3, 0xC7, 0xF2, 0xE3, 0x00, 0x00, /* 0x04-0x07 */
0xF2, 0xE5, 0xF2, 0xE0, 0xF2, 0xE7, 0xF2, 0xE2, /* 0x08-0x0B */
@@ -7628,7 +7628,7 @@ static unsigned char u2c_88[512] = {
0xE3, 0xFC, 0xBB, 0x73, 0xE3, 0xFA, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_89[512] = {
+static const unsigned char u2c_89[512] = {
0x00, 0x00, 0xDB, 0xCE, 0xBB, 0x6F, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0xE7, 0xC2, 0xE7, 0xC9, 0xBD, 0xC6, /* 0x04-0x07 */
0x00, 0x00, 0xE7, 0xCD, 0xBD, 0xCA, 0xE7, 0xC5, /* 0x08-0x0B */
@@ -7696,7 +7696,7 @@ static unsigned char u2c_89[512] = {
0xC5, 0xA9, 0x00, 0x00, 0xF7, 0xFE, 0xF9, 0x4C, /* 0xFC-0xFF */
};
-static unsigned char u2c_8A[512] = {
+static const unsigned char u2c_8A[512] = {
0xA8, 0xA5, 0x00, 0x00, 0xAD, 0x71, 0xAD, 0x72, /* 0x00-0x03 */
0xD0, 0xB0, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xB1, /* 0x04-0x07 */
0xAD, 0x70, 0x00, 0x00, 0xB0, 0x54, 0x00, 0x00, /* 0x08-0x0B */
@@ -7764,7 +7764,7 @@ static unsigned char u2c_8A[512] = {
0xBF, 0xDC, 0x00, 0x00, 0xBF, 0xD5, 0xEB, 0xAE, /* 0xFC-0xFF */
};
-static unsigned char u2c_8B[512] = {
+static const unsigned char u2c_8B[512] = {
0xBF, 0xD1, 0xBF, 0xD6, 0xBF, 0xD7, 0x00, 0x00, /* 0x00-0x03 */
0xC1, 0xC3, 0xEE, 0xA4, 0xEE, 0xAD, 0xEE, 0xAA, /* 0x04-0x07 */
0xEE, 0xAC, 0x00, 0x00, 0xC1, 0xC0, 0xEE, 0xA5, /* 0x08-0x0B */
@@ -7808,7 +7808,7 @@ static unsigned char u2c_8B[512] = {
0xC6, 0x6D, 0x00, 0x00, 0xF9, 0xA9, 0xF9, 0xC8, /* 0x9C-0x9F */
};
-static unsigned char u2c_8C[512] = {
+static const unsigned char u2c_8C[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -7876,7 +7876,7 @@ static unsigned char u2c_8C[512] = {
0xC1, 0xCA, 0xC1, 0xC9, 0xF0, 0xF3, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_8D[512] = {
+static const unsigned char u2c_8D[512] = {
0xF0, 0xF6, 0x00, 0x00, 0xF0, 0xF5, 0x00, 0x00, /* 0x00-0x03 */
0xF0, 0xF4, 0xC2, 0xD8, 0xF3, 0x48, 0xF3, 0x49, /* 0x04-0x07 */
0xC3, 0xD8, 0xF3, 0x4A, 0xC3, 0xD9, 0x00, 0x00, /* 0x08-0x0B */
@@ -7944,7 +7944,7 @@ static unsigned char u2c_8D[512] = {
0xBB, 0xB1, 0xE4, 0x5B, 0xE4, 0x61, 0xE4, 0x59, /* 0xFC-0xFF */
};
-static unsigned char u2c_8E[512] = {
+static const unsigned char u2c_8E[512] = {
0xE4, 0x62, 0x00, 0x00, 0xE4, 0x58, 0xE4, 0x5D, /* 0x00-0x03 */
0xE4, 0x63, 0xE4, 0x60, 0xE4, 0x5F, 0xE4, 0x5E, /* 0x04-0x07 */
0x00, 0x00, 0xE4, 0x57, 0xE4, 0x5C, 0x00, 0x00, /* 0x08-0x0B */
@@ -8012,7 +8012,7 @@ static unsigned char u2c_8E[512] = {
0xB6, 0x63, 0x00, 0x00, 0xB8, 0xFD, 0xE0, 0x75, /* 0xFC-0xFF */
};
-static unsigned char u2c_8F[512] = {
+static const unsigned char u2c_8F[512] = {
0xE0, 0x77, 0xE0, 0x76, 0xE0, 0x7B, 0xB8, 0xFB, /* 0x00-0x03 */
0x00, 0x00, 0xE0, 0x78, 0xE0, 0x74, 0xE0, 0x79, /* 0x04-0x07 */
0xE0, 0x7A, 0xB8, 0xFC, 0xB8, 0xFE, 0xE0, 0x7C, /* 0x08-0x0B */
@@ -8080,7 +8080,7 @@ static unsigned char u2c_8F[512] = {
0xD3, 0xF0, 0xB0, 0x6C, 0xD3, 0xEA, 0xD3, 0xED, /* 0xFC-0xFF */
};
-static unsigned char u2c_90[512] = {
+static const unsigned char u2c_90[512] = {
0xB0, 0x68, 0xB0, 0x65, 0xD3, 0xEC, 0xB0, 0x6B, /* 0x00-0x03 */
0xD3, 0xEF, 0xB0, 0x6D, 0xB0, 0x66, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD7, 0xE3, /* 0x08-0x0B */
@@ -8148,7 +8148,7 @@ static unsigned char u2c_90[512] = {
0xDC, 0x54, 0xB3, 0xA3, 0xB6, 0x6E, 0xDC, 0x53, /* 0xFC-0xFF */
};
-static unsigned char u2c_91[512] = {
+static const unsigned char u2c_91[512] = {
0xDC, 0x59, 0xDC, 0x58, 0xB6, 0x6B, 0xDC, 0x5C, /* 0x00-0x03 */
0xDC, 0x52, 0xDC, 0x5B, 0xDC, 0x50, 0xDC, 0x5A, /* 0x04-0x07 */
0xDC, 0x55, 0xB6, 0x6D, 0x00, 0x00, 0xE0, 0xAA, /* 0x08-0x0B */
@@ -8216,7 +8216,7 @@ static unsigned char u2c_91[512] = {
0x00, 0x00, 0xDC, 0x6D, 0x00, 0x00, 0xDC, 0x6C, /* 0xFC-0xFF */
};
-static unsigned char u2c_92[512] = {
+static const unsigned char u2c_92[512] = {
0xDC, 0x6A, 0xDC, 0x62, 0xDC, 0x71, 0xDC, 0x65, /* 0x00-0x03 */
0xDC, 0x6F, 0xDC, 0x76, 0xDC, 0x6E, 0xB6, 0x79, /* 0x04-0x07 */
0x00, 0x00, 0xB6, 0x75, 0xDC, 0x63, 0x00, 0x00, /* 0x08-0x0B */
@@ -8284,7 +8284,7 @@ static unsigned char u2c_92[512] = {
0xBF, 0xFB, 0x00, 0x00, 0xEC, 0x41, 0xEB, 0xF8, /* 0xFC-0xFF */
};
-static unsigned char u2c_93[512] = {
+static const unsigned char u2c_93[512] = {
0xEC, 0x43, 0xEB, 0xE9, 0xEB, 0xF6, 0x00, 0x00, /* 0x00-0x03 */
0xBF, 0xFD, 0x00, 0x00, 0xEB, 0xE1, 0x00, 0x00, /* 0x04-0x07 */
0xEB, 0xDF, 0xEC, 0x42, 0x00, 0x00, 0xEC, 0x40, /* 0x08-0x0B */
@@ -8352,7 +8352,7 @@ static unsigned char u2c_93[512] = {
0xF5, 0x40, 0xC4, 0xC3, 0xF4, 0xED, 0xF4, 0xFE, /* 0xFC-0xFF */
};
-static unsigned char u2c_94[512] = {
+static const unsigned char u2c_94[512] = {
0xF4, 0xF4, 0x00, 0x00, 0x00, 0x00, 0xC4, 0xC2, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0xF5, 0x44, 0xF4, 0xF6, /* 0x04-0x07 */
0x00, 0x00, 0xF4, 0xFB, 0xF4, 0xFD, 0xF4, 0xE7, /* 0x08-0x0B */
@@ -8389,7 +8389,7 @@ static unsigned char u2c_94[512] = {
0xF9, 0xC0, 0xF9, 0xC1, 0xF9, 0xBF, 0xF9, 0xC9, /* 0x80-0x83 */
};
-static unsigned char u2c_95[512] = {
+static const unsigned char u2c_95[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -8451,7 +8451,7 @@ static unsigned char u2c_95[512] = {
0xF6, 0x6C, 0xF6, 0x6B, 0x00, 0x00, 0x00, 0x00, /* 0xE4-0xE7 */
};
-static unsigned char u2c_96[512] = {
+static const unsigned char u2c_96[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -8519,7 +8519,7 @@ static unsigned char u2c_96[512] = {
0x00, 0x00, 0xE0, 0xD7, 0x00, 0x00, 0xE4, 0xBD, /* 0xFC-0xFF */
};
-static unsigned char u2c_97[512] = {
+static const unsigned char u2c_97[512] = {
0xBB, 0xDD, 0x00, 0x00, 0xE8, 0xAF, 0x00, 0x00, /* 0x00-0x03 */
0xBE, 0x5D, 0xE8, 0xAD, 0xBE, 0x5E, 0xBE, 0x5F, /* 0x04-0x07 */
0xE8, 0xAE, 0xBE, 0x60, 0x00, 0x00, 0xEC, 0x51, /* 0x08-0x0B */
@@ -8587,7 +8587,7 @@ static unsigned char u2c_97[512] = {
0x00, 0x00, 0xF5, 0x4C, 0xF5, 0x4D, 0xC5, 0x54, /* 0xFC-0xFF */
};
-static unsigned char u2c_98[512] = {
+static const unsigned char u2c_98[512] = {
0xF8, 0x51, 0xAD, 0xB6, 0xB3, 0xBB, 0xB3, 0xBC, /* 0x00-0x03 */
0xD8, 0x4E, 0xB6, 0xB5, 0xB6, 0xB6, 0xDC, 0xAC, /* 0x04-0x07 */
0xB6, 0xB7, 0x00, 0x00, 0xB9, 0x7A, 0x00, 0x00, /* 0x08-0x0B */
@@ -8655,7 +8655,7 @@ static unsigned char u2c_98[512] = {
0xB9, 0x7D, 0xB9, 0xA1, 0xB9, 0xA2, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_99[512] = {
+static const unsigned char u2c_99[512] = {
0xE4, 0xCF, 0x00, 0x00, 0xE4, 0xCE, 0xBB, 0xE5, /* 0x00-0x03 */
0x00, 0x00, 0xBB, 0xE6, 0x00, 0x00, 0xE4, 0xD0, /* 0x04-0x07 */
0xE8, 0xBF, 0xBB, 0xE8, 0xBE, 0x69, 0x00, 0x00, /* 0x08-0x0B */
@@ -8723,7 +8723,7 @@ static unsigned char u2c_99[512] = {
0xEF, 0x62, 0xEF, 0x60, 0xEF, 0x61, 0xC2, 0x40, /* 0xFC-0xFF */
};
-static unsigned char u2c_9A[512] = {
+static const unsigned char u2c_9A[512] = {
0x00, 0x00, 0xC1, 0xFE, 0xEF, 0x58, 0xEF, 0x63, /* 0x00-0x03 */
0xF1, 0xB3, 0xF1, 0xB6, 0xF1, 0xB8, 0xF1, 0xB7, /* 0x04-0x07 */
0x00, 0x00, 0xF1, 0xB1, 0xF1, 0xB5, 0xF1, 0xB0, /* 0x08-0x0B */
@@ -8791,7 +8791,7 @@ static unsigned char u2c_9A[512] = {
0xEF, 0x68, 0xEF, 0x66, 0xEF, 0x65, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_9B[512] = {
+static const unsigned char u2c_9B[512] = {
0x00, 0x00, 0xEF, 0x67, 0x00, 0x00, 0xC3, 0x4F, /* 0x00-0x03 */
0xF1, 0xBC, 0xF1, 0xBD, 0xC3, 0x50, 0x00, 0x00, /* 0x04-0x07 */
0xF1, 0xBB, 0x00, 0x00, 0xF3, 0xC3, 0xF3, 0xC2, /* 0x08-0x0B */
@@ -8859,7 +8859,7 @@ static unsigned char u2c_9B[512] = {
0x00, 0x00, 0xC3, 0x56, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
};
-static unsigned char u2c_9C[512] = {
+static const unsigned char u2c_9C[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0xF5, 0x6D, 0xF5, 0x73, 0xF5, 0x71, /* 0x04-0x07 */
0xF5, 0x6B, 0xF5, 0x76, 0x00, 0x00, 0xF5, 0x6A, /* 0x08-0x0B */
@@ -8927,7 +8927,7 @@ static unsigned char u2c_9C[512] = {
0xE8, 0xE4, 0xE8, 0xE6, 0x00, 0x00, 0xE8, 0xE7, /* 0xFC-0xFF */
};
-static unsigned char u2c_9D[512] = {
+static const unsigned char u2c_9D[512] = {
0xE8, 0xEA, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xA1, /* 0x00-0x03 */
0xE8, 0xEF, 0xE8, 0xEE, 0xBE, 0x7D, 0xE8, 0xE9, /* 0x04-0x07 */
0xE8, 0xED, 0xBE, 0x7E, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -8995,7 +8995,7 @@ static unsigned char u2c_9D[512] = {
0x00, 0x00, 0xF8, 0xE6, 0xF8, 0xDD, 0xF8, 0xE5, /* 0xFC-0xFF */
};
-static unsigned char u2c_9E[512] = {
+static const unsigned char u2c_9E[512] = {
0xF8, 0xE2, 0xF8, 0xE3, 0xF8, 0xDC, 0xF8, 0xDF, /* 0x00-0x03 */
0xF8, 0xE7, 0xF8, 0xE1, 0xF8, 0xE0, 0xF8, 0xDE, /* 0x04-0x07 */
0x00, 0x00, 0xF8, 0xE4, 0x00, 0x00, 0xF9, 0x5D, /* 0x08-0x0B */
@@ -9063,7 +9063,7 @@ static unsigned char u2c_9E[512] = {
0xF3, 0xF5, 0xE0, 0xEF, 0x00, 0x00, 0xEF, 0xB1, /* 0xFC-0xFF */
};
-static unsigned char u2c_9F[512] = {
+static const unsigned char u2c_9F[512] = {
0xF1, 0xE2, 0xF1, 0xE1, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0xF8, 0x78, 0xC6, 0x52, /* 0x04-0x07 */
0x00, 0x00, 0xF9, 0x65, 0xF9, 0x7E, 0x00, 0x00, /* 0x08-0x0B */
@@ -9109,11 +9109,11 @@ static unsigned char u2c_9F[512] = {
0xF9, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xA4-0xA7 */
};
-static unsigned char u2c_DC[512] = {
+static const unsigned char u2c_DC[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
};
-static unsigned char u2c_F9[512] = {
+static const unsigned char u2c_F9[512] = {
0xB0, 0x5A, 0xA7, 0xF3, 0xA8, 0xAE, 0xB8, 0xEB, /* 0x00-0x03 */
0xB7, 0xC6, 0xA6, 0xEA, 0xA5, 0x79, 0xC0, 0x74, /* 0x04-0x07 */
0xC0, 0x74, 0xAB, 0xB4, 0xAA, 0xF7, 0xB3, 0xE2, /* 0x08-0x0B */
@@ -9181,7 +9181,7 @@ static unsigned char u2c_F9[512] = {
0xC3, 0xD1, 0xA4, 0xB0, 0xAF, 0xF9, 0xA8, 0xEB, /* 0xFC-0xFF */
};
-static unsigned char u2c_FA[512] = {
+static const unsigned char u2c_FA[512] = {
0xA4, 0xC1, 0xAB, 0xD7, 0xA9, 0xDD, 0xBF, 0x7D, /* 0x00-0x03 */
0xA6, 0x76, 0xAC, 0x7D, 0xBC, 0xC9, 0xBF, 0xE7, /* 0x04-0x07 */
0xA6, 0xE6, 0xAD, 0xB0, 0xA8, 0xA3, 0xB9, 0xF8, /* 0x08-0x0B */
@@ -9196,7 +9196,7 @@ static unsigned char u2c_FA[512] = {
0xC0, 0x5D, 0xC5, 0x62, 0x00, 0x00, 0x00, 0x00, /* 0x2C-0x2F */
};
-static unsigned char u2c_FE[512] = {
+static const unsigned char u2c_FE[512] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
@@ -9226,7 +9226,7 @@ static unsigned char u2c_FE[512] = {
0xA2, 0x42, 0xA2, 0x4C, 0xA2, 0x4D, 0xA2, 0x4E, /* 0x68-0x6B */
};
-static unsigned char u2c_FF[512] = {
+static const unsigned char u2c_FF[512] = {
0x00, 0x00, 0xA1, 0x49, 0xA1, 0xA8, 0xA1, 0xAD, /* 0x00-0x03 */
0xA2, 0x43, 0xA2, 0x48, 0xA1, 0xAE, 0xA1, 0xA6, /* 0x04-0x07 */
0xA1, 0x5D, 0xA1, 0x5E, 0xA1, 0xAF, 0xA1, 0xCF, /* 0x08-0x0B */
@@ -9288,7 +9288,7 @@ static unsigned char u2c_FF[512] = {
0x00, 0x00, 0xA2, 0x44, 0x00, 0x00, 0x00, 0x00, /* 0xE4-0xE7 */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
NULL, NULL, u2c_02, u2c_03, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -9322,7 +9322,7 @@ static unsigned char *page_uni2charset[256] = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, u2c_F9, u2c_FA, NULL, NULL, NULL, u2c_FE, u2c_FF, };
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -9358,7 +9358,7 @@ static unsigned char charset2lower[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -9397,7 +9397,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(const wchar_t uni,
unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni&0xFF;
unsigned char ch = (uni>>8)&0xFF;
int n;
@@ -9429,7 +9429,7 @@ static int char2uni(const unsigned char *rawstring, int boundlen,
wchar_t *uni)
{
unsigned char ch, cl;
- wchar_t *charset2uni;
+ const wchar_t *charset2uni;
int n;
if (boundlen <= 0)
diff --git a/fs/nls/nls_euc-jp.c b/fs/nls/nls_euc-jp.c
index 73293511578b..7424929a278b 100644
--- a/fs/nls/nls_euc-jp.c
+++ b/fs/nls/nls_euc-jp.c
@@ -57,7 +57,7 @@ static struct nls_table *p_nls;
} while(0)
/* SJIS IBM extended characters to EUC map */
-static unsigned char sjisibm2euc_map[][2] = {
+static const unsigned char sjisibm2euc_map[][2] = {
{0xF3, 0xF3}, {0xF3, 0xF4}, {0xF3, 0xF5}, {0xF3, 0xF6}, {0xF3, 0xF7},
{0xF3, 0xF8}, {0xF3, 0xF9}, {0xF3, 0xFA}, {0xF3, 0xFB}, {0xF3, 0xFC},
{0xF3, 0xFD}, {0xF3, 0xFE}, {0xF4, 0xA1}, {0xF4, 0xA2}, {0xF4, 0xA3},
@@ -243,7 +243,7 @@ static struct {
};
/* EUC to SJIS IBM extended characters map (G3 Upper block) */
-static unsigned char euc2sjisibm_g3upper_map[][2] = {
+static const unsigned char euc2sjisibm_g3upper_map[][2] = {
{0xFA, 0x40}, {0xFA, 0x41}, {0xFA, 0x42}, {0xFA, 0x43}, {0xFA, 0x44},
{0xFA, 0x45}, {0xFA, 0x46}, {0xFA, 0x47}, {0xFA, 0x48}, {0xFA, 0x49},
{0xFA, 0x4A}, {0xFA, 0x4B}, {0xFA, 0x4C}, {0xFA, 0x4D}, {0xFA, 0x4E},
diff --git a/fs/nls/nls_iso8859-1.c b/fs/nls/nls_iso8859-1.c
index 2483c3c6c1c1..7b951bb5849c 100644
--- a/fs/nls/nls_iso8859-1.c
+++ b/fs/nls/nls_iso8859-1.c
@@ -13,7 +13,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -96,7 +96,7 @@ static wchar_t charset2uni[256] = {
0x00fc, 0x00fd, 0x00fe, 0x00ff,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -132,11 +132,11 @@ static unsigned char page00[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -172,7 +172,7 @@ static unsigned char charset2lower[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -210,7 +210,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/nls/nls_iso8859-13.c b/fs/nls/nls_iso8859-13.c
index 7b8721d74368..c4d52ea9f092 100644
--- a/fs/nls/nls_iso8859-13.c
+++ b/fs/nls/nls_iso8859-13.c
@@ -11,7 +11,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -94,7 +94,7 @@ static wchar_t charset2uni[256] = {
0x00fc, 0x017c, 0x017e, 0x2019,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -130,7 +130,7 @@ static unsigned char page00[256] = {
0xb8, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, /* 0xf8-0xff */
};
-static unsigned char page01[256] = {
+static const unsigned char page01[256] = {
0xc2, 0xe2, 0x00, 0x00, 0xc0, 0xe0, 0xc3, 0xe3, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0xc8, 0xe8, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0xc7, 0xe7, 0x00, 0x00, 0xcb, 0xeb, /* 0x10-0x17 */
@@ -149,14 +149,14 @@ static unsigned char page01[256] = {
0x00, 0xca, 0xea, 0xdd, 0xfd, 0xde, 0xfe, 0x00, /* 0x78-0x7f */
};
-static unsigned char page20[256] = {
+static const unsigned char page20[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
0x00, 0xff, 0x00, 0x00, 0xb4, 0xa1, 0xa5, 0x00, /* 0x18-0x1f */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00, page01, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -164,7 +164,7 @@ static unsigned char *page_uni2charset[256] = {
page20, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -200,7 +200,7 @@ static unsigned char charset2lower[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -238,7 +238,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/nls/nls_iso8859-14.c b/fs/nls/nls_iso8859-14.c
index 2e895e638dba..dc02600c7fe1 100644
--- a/fs/nls/nls_iso8859-14.c
+++ b/fs/nls/nls_iso8859-14.c
@@ -18,7 +18,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -101,7 +101,7 @@ static wchar_t charset2uni[256] = {
0x00fc, 0x00fd, 0x0177, 0x00ff,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -137,7 +137,7 @@ static unsigned char page00[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0x00, 0xff, /* 0xf8-0xff */
};
-static unsigned char page01[256] = {
+static const unsigned char page01[256] = {
0x00, 0x00, 0xa1, 0xa2, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0xa6, 0xab, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -173,7 +173,7 @@ static unsigned char page01[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
};
-static unsigned char page1e[256] = {
+static const unsigned char page1e[256] = {
0x00, 0x00, 0xa1, 0xa2, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0xa6, 0xab, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -209,7 +209,7 @@ static unsigned char page1e[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00, page01, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -220,7 +220,7 @@ static unsigned char *page_uni2charset[256] = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -256,7 +256,7 @@ static unsigned char charset2lower[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -294,7 +294,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/nls/nls_iso8859-15.c b/fs/nls/nls_iso8859-15.c
index 5c91592779fe..3c7dfc832ef1 100644
--- a/fs/nls/nls_iso8859-15.c
+++ b/fs/nls/nls_iso8859-15.c
@@ -11,7 +11,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -94,7 +94,7 @@ static wchar_t charset2uni[256] = {
0x00fc, 0x00fd, 0x00fe, 0x00ff,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -130,7 +130,7 @@ static unsigned char page00[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-static unsigned char page01[256] = {
+static const unsigned char page01[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -149,7 +149,7 @@ static unsigned char page01[256] = {
0xbe, 0x00, 0x00, 0x00, 0x00, 0xb4, 0xb8, 0x00, /* 0x78-0x7f */
};
-static unsigned char page20[256] = {
+static const unsigned char page20[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -175,7 +175,7 @@ static unsigned char page20[256] = {
0x00, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00, page01, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -186,7 +186,7 @@ static unsigned char *page_uni2charset[256] = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -222,7 +222,7 @@ static unsigned char charset2lower[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -260,7 +260,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/nls/nls_iso8859-2.c b/fs/nls/nls_iso8859-2.c
index 892d38fe9530..a2d2197e4c77 100644
--- a/fs/nls/nls_iso8859-2.c
+++ b/fs/nls/nls_iso8859-2.c
@@ -13,7 +13,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -96,7 +96,7 @@ static wchar_t charset2uni[256] = {
0x00fc, 0x00fd, 0x0163, 0x02d9,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -132,7 +132,7 @@ static unsigned char page00[256] = {
0x00, 0x00, 0xfa, 0x00, 0xfc, 0xfd, 0x00, 0x00, /* 0xf8-0xff */
};
-static unsigned char page01[256] = {
+static const unsigned char page01[256] = {
0x00, 0x00, 0xc3, 0xe3, 0xa1, 0xb1, 0xc6, 0xe6, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0xc8, 0xe8, 0xcf, 0xef, /* 0x08-0x0f */
0xd0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -151,7 +151,7 @@ static unsigned char page01[256] = {
0x00, 0xac, 0xbc, 0xaf, 0xbf, 0xae, 0xbe, 0x00, /* 0x78-0x7f */
};
-static unsigned char page02[256] = {
+static const unsigned char page02[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -183,11 +183,11 @@ static unsigned char page02[256] = {
0xa2, 0xff, 0x00, 0xb2, 0x00, 0xbd, 0x00, 0x00, /* 0xd8-0xdf */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00, page01, page02, NULL, NULL, NULL, NULL, NULL,
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -223,7 +223,7 @@ static unsigned char charset2lower[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -261,7 +261,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/nls/nls_iso8859-3.c b/fs/nls/nls_iso8859-3.c
index 49317bcdb4be..a61e0daa3a86 100644
--- a/fs/nls/nls_iso8859-3.c
+++ b/fs/nls/nls_iso8859-3.c
@@ -13,7 +13,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -96,7 +96,7 @@ static wchar_t charset2uni[256] = {
0x00fc, 0x016d, 0x015d, 0x02d9,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -132,7 +132,7 @@ static unsigned char page00[256] = {
0x00, 0xf9, 0xfa, 0xfb, 0xfc, 0x00, 0x00, 0x00, /* 0xf8-0xff */
};
-static unsigned char page01[256] = {
+static const unsigned char page01[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0xc6, 0xe6, 0xc5, 0xe5, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -151,7 +151,7 @@ static unsigned char page01[256] = {
0x00, 0x00, 0x00, 0xaf, 0xbf, 0x00, 0x00, 0x00, /* 0x78-0x7f */
};
-static unsigned char page02[256] = {
+static const unsigned char page02[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -183,11 +183,11 @@ static unsigned char page02[256] = {
0xa2, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00, page01, page02, NULL, NULL, NULL, NULL, NULL,
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -223,7 +223,7 @@ static unsigned char charset2lower[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -261,7 +261,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/nls/nls_iso8859-4.c b/fs/nls/nls_iso8859-4.c
index 9f3b9368c2cf..e8ff555483b6 100644
--- a/fs/nls/nls_iso8859-4.c
+++ b/fs/nls/nls_iso8859-4.c
@@ -13,7 +13,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -96,7 +96,7 @@ static wchar_t charset2uni[256] = {
0x00fc, 0x0169, 0x016b, 0x02d9,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -132,7 +132,7 @@ static unsigned char page00[256] = {
0xf8, 0x00, 0xfa, 0xfb, 0xfc, 0x00, 0x00, 0x00, /* 0xf8-0xff */
};
-static unsigned char page01[256] = {
+static const unsigned char page01[256] = {
0xc0, 0xe0, 0x00, 0x00, 0xa1, 0xb1, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0xc8, 0xe8, 0x00, 0x00, /* 0x08-0x0f */
0xd0, 0xf0, 0xaa, 0xba, 0x00, 0x00, 0xcc, 0xec, /* 0x10-0x17 */
@@ -151,7 +151,7 @@ static unsigned char page01[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0xbe, 0x00, /* 0x78-0x7f */
};
-static unsigned char page02[256] = {
+static const unsigned char page02[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -183,11 +183,11 @@ static unsigned char page02[256] = {
0x00, 0xff, 0x00, 0xb2, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00, page01, page02, NULL, NULL, NULL, NULL, NULL,
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -223,7 +223,7 @@ static unsigned char charset2lower[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -261,7 +261,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/nls/nls_iso8859-5.c b/fs/nls/nls_iso8859-5.c
index 001a2bb132ce..4721e8930124 100644
--- a/fs/nls/nls_iso8859-5.c
+++ b/fs/nls/nls_iso8859-5.c
@@ -13,7 +13,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -96,7 +96,7 @@ static wchar_t charset2uni[256] = {
0x045c, 0x00a7, 0x045e, 0x045f,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -122,7 +122,7 @@ static unsigned char page00[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, /* 0xa8-0xaf */
};
-static unsigned char page04[256] = {
+static const unsigned char page04[256] = {
0x00, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0x00-0x07 */
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0x00, 0xae, 0xaf, /* 0x08-0x0f */
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0x10-0x17 */
@@ -137,13 +137,13 @@ static unsigned char page04[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0x00, 0xfe, 0xff, /* 0x58-0x5f */
};
-static unsigned char page21[256] = {
+static const unsigned char page21[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, /* 0x10-0x17 */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00, NULL, NULL, NULL, page04, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -151,7 +151,7 @@ static unsigned char *page_uni2charset[256] = {
NULL, page21, NULL, NULL, NULL, NULL, NULL, NULL,
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -187,7 +187,7 @@ static unsigned char charset2lower[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -225,7 +225,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/nls/nls_iso8859-6.c b/fs/nls/nls_iso8859-6.c
index 8cec03d66088..01a517d6d306 100644
--- a/fs/nls/nls_iso8859-6.c
+++ b/fs/nls/nls_iso8859-6.c
@@ -13,7 +13,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -96,7 +96,7 @@ static wchar_t charset2uni[256] = {
0x0000, 0x0000, 0x0000, 0x0000,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -122,7 +122,7 @@ static unsigned char page00[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, /* 0xa8-0xaf */
};
-static unsigned char page06[256] = {
+static const unsigned char page06[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -139,11 +139,11 @@ static unsigned char page06[256] = {
0x38, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00, NULL, NULL, NULL, NULL, NULL, page06, NULL,
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -179,7 +179,7 @@ static unsigned char charset2lower[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -216,7 +216,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/nls/nls_iso8859-7.c b/fs/nls/nls_iso8859-7.c
index 1be707d5ac31..2d27b93ef19e 100644
--- a/fs/nls/nls_iso8859-7.c
+++ b/fs/nls/nls_iso8859-7.c
@@ -13,7 +13,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -96,7 +96,7 @@ static wchar_t charset2uni[256] = {
0x03cc, 0x03cd, 0x03ce, 0x0000,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -124,7 +124,7 @@ static unsigned char page00[256] = {
0x00, 0x00, 0x00, 0xbb, 0x00, 0xbd, 0x00, 0x00, /* 0xb8-0xbf */
};
-static unsigned char page02[256] = {
+static const unsigned char page02[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -152,7 +152,7 @@ static unsigned char page02[256] = {
0x00, 0x00, 0x00, 0x00, 0xa2, 0xa1, 0x00, 0x00, /* 0xb8-0xbf */
};
-static unsigned char page03[256] = {
+static const unsigned char page03[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -182,13 +182,13 @@ static unsigned char page03[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0x00, /* 0xc8-0xcf */
};
-static unsigned char page20[256] = {
+static const unsigned char page20[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, /* 0x10-0x17 */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00, NULL, page02, page03, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -196,7 +196,7 @@ static unsigned char *page_uni2charset[256] = {
page20, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -232,7 +232,7 @@ static unsigned char charset2lower[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0x00, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -270,7 +270,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/nls/nls_iso8859-9.c b/fs/nls/nls_iso8859-9.c
index 8c0146f73834..694bf070c721 100644
--- a/fs/nls/nls_iso8859-9.c
+++ b/fs/nls/nls_iso8859-9.c
@@ -13,7 +13,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -96,7 +96,7 @@ static wchar_t charset2uni[256] = {
0x00fc, 0x0131, 0x015f, 0x00ff,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -132,7 +132,7 @@ static unsigned char page00[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0x00, 0x00, 0xff, /* 0xf8-0xff */
};
-static unsigned char page01[256] = {
+static const unsigned char page01[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -147,11 +147,11 @@ static unsigned char page01[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0xfe, /* 0x58-0x5f */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00, page01, NULL, NULL, NULL, NULL, NULL, NULL,
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -187,7 +187,7 @@ static unsigned char charset2lower[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -225,7 +225,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/nls/nls_koi8-r.c b/fs/nls/nls_koi8-r.c
index fefbe0807265..43875310540d 100644
--- a/fs/nls/nls_koi8-r.c
+++ b/fs/nls/nls_koi8-r.c
@@ -13,7 +13,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -96,7 +96,7 @@ static wchar_t charset2uni[256] = {
0x042d, 0x0429, 0x0427, 0x042a,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -131,7 +131,7 @@ static unsigned char page00[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, /* 0xf0-0xf7 */
};
-static unsigned char page04[256] = {
+static const unsigned char page04[256] = {
0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0xe1, 0xe2, 0xf7, 0xe7, 0xe4, 0xe5, 0xf6, 0xfa, /* 0x10-0x17 */
@@ -145,7 +145,7 @@ static unsigned char page04[256] = {
0x00, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
};
-static unsigned char page22[256] = {
+static const unsigned char page22[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -161,7 +161,7 @@ static unsigned char page22[256] = {
0x00, 0x00, 0x00, 0x00, 0x98, 0x99, 0x00, 0x00, /* 0x60-0x67 */
};
-static unsigned char page23[256] = {
+static const unsigned char page23[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -169,7 +169,7 @@ static unsigned char page23[256] = {
0x93, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
};
-static unsigned char page25[256] = {
+static const unsigned char page25[256] = {
0x80, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x83, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -194,7 +194,7 @@ static unsigned char page25[256] = {
0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00, NULL, NULL, NULL, page04, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -202,7 +202,7 @@ static unsigned char *page_uni2charset[256] = {
NULL, NULL, page22, page23, NULL, page25, NULL, NULL,
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -238,7 +238,7 @@ static unsigned char charset2lower[256] = {
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -276,7 +276,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/nls/nls_koi8-u.c b/fs/nls/nls_koi8-u.c
index 015070211f22..8c9f0292b5ae 100644
--- a/fs/nls/nls_koi8-u.c
+++ b/fs/nls/nls_koi8-u.c
@@ -11,7 +11,7 @@
#include <linux/nls.h>
#include <linux/errno.h>
-static wchar_t charset2uni[256] = {
+static const wchar_t charset2uni[256] = {
/* 0x00*/
0x0000, 0x0001, 0x0002, 0x0003,
0x0004, 0x0005, 0x0006, 0x0007,
@@ -94,7 +94,7 @@ static wchar_t charset2uni[256] = {
0x042d, 0x0429, 0x0427, 0x042a,
};
-static unsigned char page00[256] = {
+static const unsigned char page00[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -129,7 +129,7 @@ static unsigned char page00[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, /* 0xf0-0xf7 */
};
-static unsigned char page04[256] = {
+static const unsigned char page04[256] = {
0x00, 0xb3, 0x00, 0x00, 0xb4, 0x00, 0xb6, 0xb7, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0xe1, 0xe2, 0xf7, 0xe7, 0xe4, 0xe5, 0xf6, 0xfa, /* 0x10-0x17 */
@@ -152,7 +152,7 @@ static unsigned char page04[256] = {
0xbd, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
};
-static unsigned char page22[256] = {
+static const unsigned char page22[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -168,7 +168,7 @@ static unsigned char page22[256] = {
0x00, 0x00, 0x00, 0x00, 0x98, 0x99, 0x00, 0x00, /* 0x60-0x67 */
};
-static unsigned char page23[256] = {
+static const unsigned char page23[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -176,7 +176,7 @@ static unsigned char page23[256] = {
0x93, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
};
-static unsigned char page25[256] = {
+static const unsigned char page25[256] = {
0x80, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x83, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, /* 0x10-0x17 */
@@ -201,7 +201,7 @@ static unsigned char page25[256] = {
0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
};
-static unsigned char *page_uni2charset[256] = {
+static const unsigned char *const page_uni2charset[256] = {
page00, NULL, NULL, NULL, page04, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -209,7 +209,7 @@ static unsigned char *page_uni2charset[256] = {
NULL, NULL, page22, page23, NULL, page25, NULL, NULL,
};
-static unsigned char charset2lower[256] = {
+static const unsigned char charset2lower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -245,7 +245,7 @@ static unsigned char charset2lower[256] = {
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xf8-0xff */
};
-static unsigned char charset2upper[256] = {
+static const unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
@@ -283,7 +283,7 @@ static unsigned char charset2upper[256] = {
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
{
- unsigned char *uni2charset;
+ const unsigned char *uni2charset;
unsigned char cl = uni & 0x00ff;
unsigned char ch = (uni & 0xff00) >> 8;
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog
index 345798ebd366..37c11e194372 100644
--- a/fs/ntfs/ChangeLog
+++ b/fs/ntfs/ChangeLog
@@ -382,7 +382,7 @@ ToDo/Notes:
own locking so it does not matter if the vfs inode is locked.
- Fix bug in mft record writing where we forgot to set the device in
the buffers when mapping them after the VM had discarded them.
- Thanks to Martin MOKREJÅ  for the bug report.
+ Thanks to Martin MOKREJÃ… for the bug report.
2.1.22 - Many bug and race fixes and error handling improvements.
@@ -1585,7 +1585,7 @@ tng-0.0.4 - Big changes, getting in line with Al Viro's comments.
for reading $MFT (ntfs_mft_readpage). In the process create dedicated
address space operations (ntfs_mft_aops) for $MFT inode mapping. Also
removed the now superfluous exports from the kernel core patch.
- - Fix a bug where kfree() was used insted of ntfs_free().
+ - Fix a bug where kfree() was used instead of ntfs_free().
- Change map_mft_record() to take ntfs_inode as argument instead of
vfs inode. Dito for unmap_mft_record(). Adapt all callers.
- Add pointer to ntfs_volume to ntfs_inode.
diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c
index cfdc7900d271..ad87cb01299b 100644
--- a/fs/ntfs/aops.c
+++ b/fs/ntfs/aops.c
@@ -405,6 +405,15 @@ static int ntfs_readpage(struct file *file, struct page *page)
retry_readpage:
BUG_ON(!PageLocked(page));
+ vi = page->mapping->host;
+ i_size = i_size_read(vi);
+ /* Is the page fully outside i_size? (truncate in progress) */
+ if (unlikely(page->index >= (i_size + PAGE_CACHE_SIZE - 1) >>
+ PAGE_CACHE_SHIFT)) {
+ zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0);
+ ntfs_debug("Read outside i_size - truncated?");
+ goto done;
+ }
/*
* This can potentially happen because we clear PageUptodate() during
* ntfs_writepage() of MstProtected() attributes.
@@ -413,7 +422,6 @@ retry_readpage:
unlock_page(page);
return 0;
}
- vi = page->mapping->host;
ni = NTFS_I(vi);
/*
* Only $DATA attributes can be encrypted and only unnamed $DATA
diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c
index 92dabdcf2b80..50d3b0c258e3 100644
--- a/fs/ntfs/attrib.c
+++ b/fs/ntfs/attrib.c
@@ -179,10 +179,7 @@ int ntfs_map_runlist_nolock(ntfs_inode *ni, VCN vcn, ntfs_attr_search_ctx *ctx)
* ntfs_mapping_pairs_decompress() fails.
*/
end_vcn = sle64_to_cpu(a->data.non_resident.highest_vcn) + 1;
- if (!a->data.non_resident.lowest_vcn && end_vcn == 1)
- end_vcn = sle64_to_cpu(a->data.non_resident.allocated_size) >>
- ni->vol->cluster_size_bits;
- if (unlikely(vcn >= end_vcn)) {
+ if (unlikely(vcn && vcn >= end_vcn)) {
err = -ENOENT;
goto err_out;
}
diff --git a/fs/ntfs/compress.c b/fs/ntfs/compress.c
index d98daf59e0b6..d1619d05eb23 100644
--- a/fs/ntfs/compress.c
+++ b/fs/ntfs/compress.c
@@ -561,6 +561,16 @@ int ntfs_read_compressed_block(struct page *page)
read_unlock_irqrestore(&ni->size_lock, flags);
max_page = ((i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT) -
offset;
+ /* Is the page fully outside i_size? (truncate in progress) */
+ if (xpage >= max_page) {
+ kfree(bhs);
+ kfree(pages);
+ zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0);
+ ntfs_debug("Compressed read outside i_size - truncated?");
+ SetPageUptodate(page);
+ unlock_page(page);
+ return 0;
+ }
if (nr_pages < max_page)
max_page = nr_pages;
for (i = 0; i < max_page; i++, offset++) {
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
index c814204d4ea0..6cd08dfdc2ed 100644
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -61,7 +61,7 @@ static int ntfs_file_open(struct inode *vi, struct file *filp)
{
if (sizeof(unsigned long) < 8) {
if (i_size_read(vi) > MAX_LFS_FILESIZE)
- return -EFBIG;
+ return -EOVERFLOW;
}
return generic_file_open(vi, filp);
}
diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c
index e93c6142b23c..e1781c8b1650 100644
--- a/fs/ntfs/namei.c
+++ b/fs/ntfs/namei.c
@@ -450,58 +450,40 @@ try_next:
return parent_dent;
}
-/**
- * ntfs_get_dentry - find a dentry for the inode from a file handle sub-fragment
- * @sb: super block identifying the mounted ntfs volume
- * @fh: the file handle sub-fragment
- *
- * Find a dentry for the inode given a file handle sub-fragment. This function
- * is called from fs/exportfs/expfs.c::find_exported_dentry() which in turn is
- * called from the default ->decode_fh() which is export_decode_fh() in the
- * same file. The code is closely based on the default ->get_dentry() helper
- * fs/exportfs/expfs.c::get_object().
- *
- * The @fh contains two 32-bit unsigned values, the first one is the inode
- * number and the second one is the inode generation.
- *
- * Return the dentry on success or the error code on error (IS_ERR() is true).
- */
-static struct dentry *ntfs_get_dentry(struct super_block *sb, void *fh)
+static struct inode *ntfs_nfs_get_inode(struct super_block *sb,
+ u64 ino, u32 generation)
{
- struct inode *vi;
- struct dentry *dent;
- unsigned long ino = ((u32 *)fh)[0];
- u32 gen = ((u32 *)fh)[1];
+ struct inode *inode;
- ntfs_debug("Entering for inode 0x%lx, generation 0x%x.", ino, gen);
- vi = ntfs_iget(sb, ino);
- if (IS_ERR(vi)) {
- ntfs_error(sb, "Failed to get inode 0x%lx.", ino);
- return (struct dentry *)vi;
- }
- if (unlikely(is_bad_inode(vi) || vi->i_generation != gen)) {
- /* We didn't find the right inode. */
- ntfs_error(sb, "Inode 0x%lx, bad count: %d %d or version 0x%x "
- "0x%x.", vi->i_ino, vi->i_nlink,
- atomic_read(&vi->i_count), vi->i_generation,
- gen);
- iput(vi);
- return ERR_PTR(-ESTALE);
- }
- /* Now find a dentry. If possible, get a well-connected one. */
- dent = d_alloc_anon(vi);
- if (unlikely(!dent)) {
- iput(vi);
- return ERR_PTR(-ENOMEM);
+ inode = ntfs_iget(sb, ino);
+ if (!IS_ERR(inode)) {
+ if (is_bad_inode(inode) || inode->i_generation != generation) {
+ iput(inode);
+ inode = ERR_PTR(-ESTALE);
+ }
}
- ntfs_debug("Done for inode 0x%lx, generation 0x%x.", ino, gen);
- return dent;
+
+ return inode;
+}
+
+static struct dentry *ntfs_fh_to_dentry(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type)
+{
+ return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
+ ntfs_nfs_get_inode);
+}
+
+static struct dentry *ntfs_fh_to_parent(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type)
+{
+ return generic_fh_to_parent(sb, fid, fh_len, fh_type,
+ ntfs_nfs_get_inode);
}
/**
* Export operations allowing NFS exporting of mounted NTFS partitions.
*
- * We use the default ->decode_fh() and ->encode_fh() for now. Note that they
+ * We use the default ->encode_fh() for now. Note that they
* use 32 bits to store the inode number which is an unsigned long so on 64-bit
* architectures is usually 64 bits so it would all fail horribly on huge
* volumes. I guess we need to define our own encode and decode fh functions
@@ -517,10 +499,9 @@ static struct dentry *ntfs_get_dentry(struct super_block *sb, void *fh)
* allowing the inode number 0 which is used in NTFS for the system file $MFT
* and due to using iget() whereas NTFS needs ntfs_iget().
*/
-struct export_operations ntfs_export_ops = {
+const struct export_operations ntfs_export_ops = {
.get_parent = ntfs_get_parent, /* Find the parent of a given
directory. */
- .get_dentry = ntfs_get_dentry, /* Find a dentry for the inode
- given a file handle
- sub-fragment. */
+ .fh_to_dentry = ntfs_fh_to_dentry,
+ .fh_to_parent = ntfs_fh_to_parent,
};
diff --git a/fs/ntfs/ntfs.h b/fs/ntfs/ntfs.h
index d73f5a9ac341..d6a340bf80fc 100644
--- a/fs/ntfs/ntfs.h
+++ b/fs/ntfs/ntfs.h
@@ -69,7 +69,7 @@ extern const struct inode_operations ntfs_dir_inode_ops;
extern const struct file_operations ntfs_empty_file_ops;
extern const struct inode_operations ntfs_empty_inode_ops;
-extern struct export_operations ntfs_export_ops;
+extern const struct export_operations ntfs_export_ops;
/**
* NTFS_SB - return the ntfs volume given a vfs super block
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
index 90c4e3a29706..3e76f3b216bc 100644
--- a/fs/ntfs/super.c
+++ b/fs/ntfs/super.c
@@ -2381,14 +2381,14 @@ static void ntfs_put_super(struct super_block *sb)
*/
ntfs_commit_inode(vol->mft_ino);
write_inode_now(vol->mft_ino, 1);
- if (!list_empty(&sb->s_dirty)) {
+ if (sb_has_dirty_inodes(sb)) {
const char *s1, *s2;
mutex_lock(&vol->mft_ino->i_mutex);
truncate_inode_pages(vol->mft_ino->i_mapping, 0);
mutex_unlock(&vol->mft_ino->i_mutex);
write_inode_now(vol->mft_ino, 1);
- if (!list_empty(&sb->s_dirty)) {
+ if (sb_has_dirty_inodes(sb)) {
static const char *_s1 = "inodes";
static const char *_s2 = "";
s1 = _s1;
@@ -3080,8 +3080,7 @@ struct kmem_cache *ntfs_inode_cache;
struct kmem_cache *ntfs_big_inode_cache;
/* Init once constructor for the inode slab cache. */
-static void ntfs_big_inode_init_once(void *foo, struct kmem_cache *cachep,
- unsigned long flags)
+static void ntfs_big_inode_init_once(struct kmem_cache *cachep, void *foo)
{
ntfs_inode *ni = (ntfs_inode *)foo;
diff --git a/fs/ntfs/sysctl.c b/fs/ntfs/sysctl.c
index 4847fbfb0107..9ef85e628fe1 100644
--- a/fs/ntfs/sysctl.c
+++ b/fs/ntfs/sysctl.c
@@ -1,7 +1,7 @@
/*
* sysctl.c - Code for sysctl handling in NTFS Linux kernel driver. Part of
* the Linux-NTFS project. Adapted from the old NTFS driver,
- * Copyright (C) 1997 Martin von Löwis, Régis Duchesne
+ * Copyright (C) 1997 Martin von Löwis, Régis Duchesne
*
* Copyright (c) 2002-2005 Anton Altaparmakov
*
diff --git a/fs/ntfs/sysctl.h b/fs/ntfs/sysctl.h
index beda5bf96405..d4f8ce920d95 100644
--- a/fs/ntfs/sysctl.h
+++ b/fs/ntfs/sysctl.h
@@ -1,7 +1,7 @@
/*
* sysctl.h - Defines for sysctl handling in NTFS Linux kernel driver. Part of
* the Linux-NTFS project. Adapted from the old NTFS driver,
- * Copyright (C) 1997 Martin von Löwis, Régis Duchesne
+ * Copyright (C) 1997 Martin von Löwis, Régis Duchesne
*
* Copyright (c) 2002-2004 Anton Altaparmakov
*
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index 4ba7f0bdc248..ce62c152823d 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -3946,7 +3946,7 @@ static int __ocfs2_mark_extent_written(struct inode *inode,
struct ocfs2_merge_ctxt ctxt;
struct ocfs2_extent_list *rightmost_el;
- if (!rec->e_flags & OCFS2_EXT_UNWRITTEN) {
+ if (!(rec->e_flags & OCFS2_EXT_UNWRITTEN)) {
ret = -EIO;
mlog_errno(ret);
goto out;
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index 34d10452c56d..556e34ccb005 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -729,6 +729,27 @@ static void ocfs2_clear_page_regions(struct page *page,
}
/*
+ * Nonsparse file systems fully allocate before we get to the write
+ * code. This prevents ocfs2_write() from tagging the write as an
+ * allocating one, which means ocfs2_map_page_blocks() might try to
+ * read-in the blocks at the tail of our file. Avoid reading them by
+ * testing i_size against each block offset.
+ */
+static int ocfs2_should_read_blk(struct inode *inode, struct page *page,
+ unsigned int block_start)
+{
+ u64 offset = page_offset(page) + block_start;
+
+ if (ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb)))
+ return 1;
+
+ if (i_size_read(inode) > offset)
+ return 1;
+
+ return 0;
+}
+
+/*
* Some of this taken from block_prepare_write(). We already have our
* mapping by now though, and the entire write will be allocating or
* it won't, so not much need to use BH_New.
@@ -781,6 +802,7 @@ int ocfs2_map_page_blocks(struct page *page, u64 *p_blkno,
set_buffer_uptodate(bh);
} else if (!buffer_uptodate(bh) && !buffer_delay(bh) &&
!buffer_new(bh) &&
+ ocfs2_should_read_blk(inode, page, block_start) &&
(block_start < from || block_end > to)) {
ll_rw_block(READ, 1, &bh);
*wait_bh++=bh;
@@ -1724,9 +1746,9 @@ out:
return ret;
}
-int ocfs2_write_begin(struct file *file, struct address_space *mapping,
- loff_t pos, unsigned len, unsigned flags,
- struct page **pagep, void **fsdata)
+static int ocfs2_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
{
int ret;
struct buffer_head *di_bh = NULL;
@@ -1877,9 +1899,9 @@ out_write_size:
return copied;
}
-int ocfs2_write_end(struct file *file, struct address_space *mapping,
- loff_t pos, unsigned len, unsigned copied,
- struct page *page, void *fsdata)
+static int ocfs2_write_end(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata)
{
int ret;
struct inode *inode = mapping->host;
@@ -1896,6 +1918,8 @@ int ocfs2_write_end(struct file *file, struct address_space *mapping,
const struct address_space_operations ocfs2_aops = {
.readpage = ocfs2_readpage,
.writepage = ocfs2_writepage,
+ .write_begin = ocfs2_write_begin,
+ .write_end = ocfs2_write_end,
.bmap = ocfs2_bmap,
.sync_page = block_sync_page,
.direct_IO = ocfs2_direct_IO,
diff --git a/fs/ocfs2/aops.h b/fs/ocfs2/aops.h
index 113560877dbb..503e49232e11 100644
--- a/fs/ocfs2/aops.h
+++ b/fs/ocfs2/aops.h
@@ -44,14 +44,6 @@ int walk_page_buffers( handle_t *handle,
int (*fn)( handle_t *handle,
struct buffer_head *bh));
-int ocfs2_write_begin(struct file *file, struct address_space *mapping,
- loff_t pos, unsigned len, unsigned flags,
- struct page **pagep, void **fsdata);
-
-int ocfs2_write_end(struct file *file, struct address_space *mapping,
- loff_t pos, unsigned len, unsigned copied,
- struct page *page, void *fsdata);
-
int ocfs2_write_end_nolock(struct address_space *mapping,
loff_t pos, unsigned len, unsigned copied,
struct page *page, void *fsdata);
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c
index f14b541fab95..f02ccb34604d 100644
--- a/fs/ocfs2/cluster/heartbeat.c
+++ b/fs/ocfs2/cluster/heartbeat.c
@@ -267,7 +267,7 @@ static struct bio *o2hb_setup_one_bio(struct o2hb_region *reg,
current_page = cs / spp;
page = reg->hr_slot_data[current_page];
- vec_len = min(PAGE_CACHE_SIZE,
+ vec_len = min(PAGE_CACHE_SIZE - vec_start,
(max_slots-cs) * (PAGE_CACHE_SIZE/spp) );
mlog(ML_HB_BIO, "page %d, vec_len = %u, vec_start = %u\n",
@@ -1372,7 +1372,7 @@ static ssize_t o2hb_region_pid_read(struct o2hb_region *reg,
spin_lock(&o2hb_live_lock);
if (reg->hr_task)
- pid = reg->hr_task->pid;
+ pid = task_pid_nr(reg->hr_task);
spin_unlock(&o2hb_live_lock);
if (!pid)
diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h
index 75cd877f6d42..cd046060114e 100644
--- a/fs/ocfs2/cluster/masklog.h
+++ b/fs/ocfs2/cluster/masklog.h
@@ -192,7 +192,7 @@ extern struct mlog_bits mlog_and_bits, mlog_not_bits;
* previous token if args expands to nothing.
*/
#define __mlog_printk(level, fmt, args...) \
- printk(level "(%u,%lu):%s:%d " fmt, current->pid, \
+ printk(level "(%u,%lu):%s:%d " fmt, task_pid_nr(current), \
__mlog_cpu_guess, __PRETTY_FUNCTION__, __LINE__ , \
##args)
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c
index 685c18065c82..d84bd155997b 100644
--- a/fs/ocfs2/cluster/tcp.c
+++ b/fs/ocfs2/cluster/tcp.c
@@ -58,6 +58,7 @@
#include <linux/slab.h>
#include <linux/idr.h>
#include <linux/kref.h>
+#include <linux/net.h>
#include <net/tcp.h>
#include <asm/uaccess.h>
@@ -616,8 +617,7 @@ static void o2net_shutdown_sc(struct work_struct *work)
del_timer_sync(&sc->sc_idle_timeout);
o2net_sc_cancel_delayed_work(sc, &sc->sc_keepalive_work);
sc_put(sc);
- sc->sc_sock->ops->shutdown(sc->sc_sock,
- RCV_SHUTDOWN|SEND_SHUTDOWN);
+ kernel_sock_shutdown(sc->sc_sock, SHUT_RDWR);
}
/* not fatal so failed connects before the other guy has our
diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c
index 014e73978dac..1957a5ed219e 100644
--- a/fs/ocfs2/dcache.c
+++ b/fs/ocfs2/dcache.c
@@ -318,9 +318,9 @@ out_attach:
static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb,
struct ocfs2_dentry_lock *dl)
{
+ iput(dl->dl_inode);
ocfs2_simple_drop_lockres(osb, &dl->dl_lockres);
ocfs2_lock_res_free(&dl->dl_lockres);
- iput(dl->dl_inode);
kfree(dl);
}
@@ -376,7 +376,7 @@ out:
* directory locks. The dentries have already been deleted on other
* nodes via ocfs2_remote_dentry_delete().
*
- * Normally, the VFS handles the d_move() for the file sytem, after
+ * Normally, the VFS handles the d_move() for the file system, after
* the ->rename() callback. OCFS2 wants to handle this internally, so
* the new lock can be created atomically with respect to the cluster.
*/
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c
index 7453b70c1a19..63b28fdceb4a 100644
--- a/fs/ocfs2/dir.c
+++ b/fs/ocfs2/dir.c
@@ -208,9 +208,9 @@ out:
return NULL;
}
-struct buffer_head *ocfs2_find_entry_el(const char *name, int namelen,
- struct inode *dir,
- struct ocfs2_dir_entry **res_dir)
+static struct buffer_head *ocfs2_find_entry_el(const char *name, int namelen,
+ struct inode *dir,
+ struct ocfs2_dir_entry **res_dir)
{
struct super_block *sb;
struct buffer_head *bh_use[NAMEI_RA_SIZE];
@@ -586,7 +586,7 @@ bail:
}
static int ocfs2_dir_foreach_blk_id(struct inode *inode,
- unsigned long *f_version,
+ u64 *f_version,
loff_t *f_pos, void *priv,
filldir_t filldir, int *filldir_err)
{
@@ -648,7 +648,7 @@ revalidate:
* not the directory has been modified
* during the copy operation.
*/
- unsigned long version = *f_version;
+ u64 version = *f_version;
unsigned char d_type = DT_UNKNOWN;
if (de->file_type < OCFS2_FT_MAX)
@@ -677,7 +677,7 @@ out:
}
static int ocfs2_dir_foreach_blk_el(struct inode *inode,
- unsigned long *f_version,
+ u64 *f_version,
loff_t *f_pos, void *priv,
filldir_t filldir, int *filldir_err)
{
@@ -798,7 +798,7 @@ out:
return stored;
}
-static int ocfs2_dir_foreach_blk(struct inode *inode, unsigned long *f_version,
+static int ocfs2_dir_foreach_blk(struct inode *inode, u64 *f_version,
loff_t *f_pos, void *priv, filldir_t filldir,
int *filldir_err)
{
@@ -818,7 +818,7 @@ int ocfs2_dir_foreach(struct inode *inode, loff_t *f_pos, void *priv,
filldir_t filldir)
{
int ret = 0, filldir_err = 0;
- unsigned long version = inode->i_version;
+ u64 version = inode->i_version;
while (*f_pos < i_size_read(inode)) {
ret = ocfs2_dir_foreach_blk(inode, &version, f_pos, priv,
diff --git a/fs/ocfs2/dlm/dlmfs.c b/fs/ocfs2/dlm/dlmfs.c
index 7418dc83de1c..6639baab0798 100644
--- a/fs/ocfs2/dlm/dlmfs.c
+++ b/fs/ocfs2/dlm/dlmfs.c
@@ -255,9 +255,8 @@ static ssize_t dlmfs_file_write(struct file *filp,
return writelen;
}
-static void dlmfs_init_once(void *foo,
- struct kmem_cache *cachep,
- unsigned long flags)
+static void dlmfs_init_once(struct kmem_cache *cachep,
+ void *foo)
{
struct dlmfs_inode_private *ip =
(struct dlmfs_inode_private *) foo;
@@ -588,13 +587,17 @@ static int __init init_dlmfs_fs(void)
dlmfs_print_version();
+ status = bdi_init(&dlmfs_backing_dev_info);
+ if (status)
+ return status;
+
dlmfs_inode_cache = kmem_cache_create("dlmfs_inode_cache",
sizeof(struct dlmfs_inode_private),
0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
SLAB_MEM_SPREAD),
dlmfs_init_once);
if (!dlmfs_inode_cache)
- return -ENOMEM;
+ goto bail;
cleanup_inode = 1;
user_dlm_worker = create_singlethread_workqueue("user_dlm");
@@ -611,6 +614,7 @@ bail:
kmem_cache_destroy(dlmfs_inode_cache);
if (cleanup_worker)
destroy_workqueue(user_dlm_worker);
+ bdi_destroy(&dlmfs_backing_dev_info);
} else
printk("OCFS2 User DLM kernel interface loaded\n");
return status;
@@ -624,6 +628,8 @@ static void __exit exit_dlmfs_fs(void)
destroy_workqueue(user_dlm_worker);
kmem_cache_destroy(dlmfs_inode_cache);
+
+ bdi_destroy(&dlmfs_backing_dev_info);
}
MODULE_AUTHOR("Oracle");
diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c
index a2c33160bfd6..2fde7bf91434 100644
--- a/fs/ocfs2/dlm/dlmrecovery.c
+++ b/fs/ocfs2/dlm/dlmrecovery.c
@@ -259,7 +259,7 @@ static void dlm_print_reco_node_status(struct dlm_ctxt *dlm)
struct dlm_lock_resource *res;
mlog(ML_NOTICE, "%s(%d): recovery info, state=%s, dead=%u, master=%u\n",
- dlm->name, dlm->dlm_reco_thread_task->pid,
+ dlm->name, task_pid_nr(dlm->dlm_reco_thread_task),
dlm->reco.state & DLM_RECO_STATE_ACTIVE ? "ACTIVE" : "inactive",
dlm->reco.dead_node, dlm->reco.new_master);
@@ -420,7 +420,7 @@ void dlm_wait_for_recovery(struct dlm_ctxt *dlm)
if (dlm_in_recovery(dlm)) {
mlog(0, "%s: reco thread %d in recovery: "
"state=%d, master=%u, dead=%u\n",
- dlm->name, dlm->dlm_reco_thread_task->pid,
+ dlm->name, task_pid_nr(dlm->dlm_reco_thread_task),
dlm->reco.state, dlm->reco.new_master,
dlm->reco.dead_node);
}
@@ -483,7 +483,7 @@ static int dlm_do_recovery(struct dlm_ctxt *dlm)
return 0;
}
mlog(0, "%s(%d):recovery thread found node %u in the recovery map!\n",
- dlm->name, dlm->dlm_reco_thread_task->pid,
+ dlm->name, task_pid_nr(dlm->dlm_reco_thread_task),
dlm->reco.dead_node);
spin_unlock(&dlm->spinlock);
@@ -507,7 +507,7 @@ static int dlm_do_recovery(struct dlm_ctxt *dlm)
mlog(0, "another node will master this recovery session.\n");
}
mlog(0, "dlm=%s (%d), new_master=%u, this node=%u, dead_node=%u\n",
- dlm->name, dlm->dlm_reco_thread_task->pid, dlm->reco.new_master,
+ dlm->name, task_pid_nr(dlm->dlm_reco_thread_task), dlm->reco.new_master,
dlm->node_num, dlm->reco.dead_node);
/* it is safe to start everything back up here
@@ -520,7 +520,7 @@ static int dlm_do_recovery(struct dlm_ctxt *dlm)
master_here:
mlog(0, "(%d) mastering recovery of %s:%u here(this=%u)!\n",
- dlm->dlm_reco_thread_task->pid,
+ task_pid_nr(dlm->dlm_reco_thread_task),
dlm->name, dlm->reco.dead_node, dlm->node_num);
status = dlm_remaster_locks(dlm, dlm->reco.dead_node);
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index 41c76ff2fcfb..4e97dcceaf8f 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -670,7 +670,7 @@ static inline void ocfs2_generic_handle_attach_action(struct ocfs2_lock_res *loc
{
mlog_entry_void();
- BUG_ON((!lockres->l_flags & OCFS2_LOCK_BUSY));
+ BUG_ON((!(lockres->l_flags & OCFS2_LOCK_BUSY)));
BUG_ON(lockres->l_flags & OCFS2_LOCK_ATTACHED);
if (lockres->l_requested > LKM_NLMODE &&
@@ -980,18 +980,6 @@ again:
goto unlock;
}
- if (!(lockres->l_flags & OCFS2_LOCK_ATTACHED)) {
- /* lock has not been created yet. */
- spin_unlock_irqrestore(&lockres->l_lock, flags);
-
- ret = ocfs2_lock_create(osb, lockres, LKM_NLMODE, 0);
- if (ret < 0) {
- mlog_errno(ret);
- goto out;
- }
- goto again;
- }
-
if (lockres->l_flags & OCFS2_LOCK_BLOCKED &&
!ocfs2_may_continue_on_blocked_lock(lockres, level)) {
/* is the lock is currently blocked on behalf of
@@ -1006,7 +994,14 @@ again:
mlog(ML_ERROR, "lockres %s has action %u pending\n",
lockres->l_name, lockres->l_action);
- lockres->l_action = OCFS2_AST_CONVERT;
+ if (!(lockres->l_flags & OCFS2_LOCK_ATTACHED)) {
+ lockres->l_action = OCFS2_AST_ATTACH;
+ lkm_flags &= ~LKM_CONVERT;
+ } else {
+ lockres->l_action = OCFS2_AST_CONVERT;
+ lkm_flags |= LKM_CONVERT;
+ }
+
lockres->l_requested = level;
lockres_or_flags(lockres, OCFS2_LOCK_BUSY);
spin_unlock_irqrestore(&lockres->l_lock, flags);
@@ -1021,7 +1016,7 @@ again:
status = dlmlock(osb->dlm,
level,
&lockres->l_lksb,
- lkm_flags|LKM_CONVERT,
+ lkm_flags,
lockres->l_name,
OCFS2_LOCK_ID_MAX_LEN - 1,
ocfs2_locking_ast,
diff --git a/fs/ocfs2/export.c b/fs/ocfs2/export.c
index c3bbc198f9ce..535bfa9568a4 100644
--- a/fs/ocfs2/export.c
+++ b/fs/ocfs2/export.c
@@ -45,9 +45,9 @@ struct ocfs2_inode_handle
u32 ih_generation;
};
-static struct dentry *ocfs2_get_dentry(struct super_block *sb, void *vobjp)
+static struct dentry *ocfs2_get_dentry(struct super_block *sb,
+ struct ocfs2_inode_handle *handle)
{
- struct ocfs2_inode_handle *handle = vobjp;
struct inode *inode;
struct dentry *result;
@@ -194,54 +194,37 @@ bail:
return type;
}
-static struct dentry *ocfs2_decode_fh(struct super_block *sb, u32 *fh_in,
- int fh_len, int fileid_type,
- int (*acceptable)(void *context,
- struct dentry *de),
- void *context)
+static struct dentry *ocfs2_fh_to_dentry(struct super_block *sb,
+ struct fid *fid, int fh_len, int fh_type)
{
- struct ocfs2_inode_handle handle, parent;
- struct dentry *ret = NULL;
- __le32 *fh = (__force __le32 *) fh_in;
-
- mlog_entry("(0x%p, 0x%p, %d, %d, 0x%p, 0x%p)\n",
- sb, fh, fh_len, fileid_type, acceptable, context);
-
- if (fh_len < 3 || fileid_type > 2)
- goto bail;
-
- if (fileid_type == 2) {
- if (fh_len < 6)
- goto bail;
-
- parent.ih_blkno = (u64)le32_to_cpu(fh[3]) << 32;
- parent.ih_blkno |= (u64)le32_to_cpu(fh[4]);
- parent.ih_generation = le32_to_cpu(fh[5]);
+ struct ocfs2_inode_handle handle;
- mlog(0, "Decoding parent: blkno: %llu, generation: %u\n",
- (unsigned long long)parent.ih_blkno,
- parent.ih_generation);
- }
+ if (fh_len < 3 || fh_type > 2)
+ return NULL;
- handle.ih_blkno = (u64)le32_to_cpu(fh[0]) << 32;
- handle.ih_blkno |= (u64)le32_to_cpu(fh[1]);
- handle.ih_generation = le32_to_cpu(fh[2]);
+ handle.ih_blkno = (u64)le32_to_cpu(fid->raw[0]) << 32;
+ handle.ih_blkno |= (u64)le32_to_cpu(fid->raw[1]);
+ handle.ih_generation = le32_to_cpu(fid->raw[2]);
+ return ocfs2_get_dentry(sb, &handle);
+}
- mlog(0, "Encoding fh: blkno: %llu, generation: %u\n",
- (unsigned long long)handle.ih_blkno, handle.ih_generation);
+static struct dentry *ocfs2_fh_to_parent(struct super_block *sb,
+ struct fid *fid, int fh_len, int fh_type)
+{
+ struct ocfs2_inode_handle parent;
- ret = ocfs2_export_ops.find_exported_dentry(sb, &handle, &parent,
- acceptable, context);
+ if (fh_type != 2 || fh_len < 6)
+ return NULL;
-bail:
- mlog_exit_ptr(ret);
- return ret;
+ parent.ih_blkno = (u64)le32_to_cpu(fid->raw[3]) << 32;
+ parent.ih_blkno |= (u64)le32_to_cpu(fid->raw[4]);
+ parent.ih_generation = le32_to_cpu(fid->raw[5]);
+ return ocfs2_get_dentry(sb, &parent);
}
-struct export_operations ocfs2_export_ops = {
- .decode_fh = ocfs2_decode_fh,
+const struct export_operations ocfs2_export_ops = {
.encode_fh = ocfs2_encode_fh,
-
+ .fh_to_dentry = ocfs2_fh_to_dentry,
+ .fh_to_parent = ocfs2_fh_to_parent,
.get_parent = ocfs2_get_parent,
- .get_dentry = ocfs2_get_dentry,
};
diff --git a/fs/ocfs2/export.h b/fs/ocfs2/export.h
index e08bed9e45a0..41a738678c37 100644
--- a/fs/ocfs2/export.h
+++ b/fs/ocfs2/export.h
@@ -28,6 +28,6 @@
#include <linux/exportfs.h>
-extern struct export_operations ocfs2_export_ops;
+extern const struct export_operations ocfs2_export_ops;
#endif /* OCFS2_EXPORT_H */
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index a62b14eb4065..bbac7cd33e0b 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -1881,149 +1881,21 @@ out:
return ret;
}
-static inline void
-ocfs2_set_next_iovec(const struct iovec **iovp, size_t *basep, size_t bytes)
-{
- const struct iovec *iov = *iovp;
- size_t base = *basep;
-
- do {
- int copy = min(bytes, iov->iov_len - base);
-
- bytes -= copy;
- base += copy;
- if (iov->iov_len == base) {
- iov++;
- base = 0;
- }
- } while (bytes);
- *iovp = iov;
- *basep = base;
-}
-
-static struct page * ocfs2_get_write_source(char **ret_src_buf,
- const struct iovec *cur_iov,
- size_t iov_offset)
-{
- int ret;
- char *buf = cur_iov->iov_base + iov_offset;
- struct page *src_page = NULL;
- unsigned long off;
-
- off = (unsigned long)(buf) & ~PAGE_CACHE_MASK;
-
- if (!segment_eq(get_fs(), KERNEL_DS)) {
- /*
- * Pull in the user page. We want to do this outside
- * of the meta data locks in order to preserve locking
- * order in case of page fault.
- */
- ret = get_user_pages(current, current->mm,
- (unsigned long)buf & PAGE_CACHE_MASK, 1,
- 0, 0, &src_page, NULL);
- if (ret == 1)
- *ret_src_buf = kmap(src_page) + off;
- else
- src_page = ERR_PTR(-EFAULT);
- } else {
- *ret_src_buf = buf;
- }
-
- return src_page;
-}
-
-static void ocfs2_put_write_source(struct page *page)
-{
- if (page) {
- kunmap(page);
- page_cache_release(page);
- }
-}
-
-static ssize_t ocfs2_file_buffered_write(struct file *file, loff_t *ppos,
- const struct iovec *iov,
- unsigned long nr_segs,
- size_t count,
- ssize_t o_direct_written)
-{
- int ret = 0;
- ssize_t copied, total = 0;
- size_t iov_offset = 0, bytes;
- loff_t pos;
- const struct iovec *cur_iov = iov;
- struct page *user_page, *page;
- char * uninitialized_var(buf);
- char *dst;
- void *fsdata;
-
- /*
- * handle partial DIO write. Adjust cur_iov if needed.
- */
- ocfs2_set_next_iovec(&cur_iov, &iov_offset, o_direct_written);
-
- do {
- pos = *ppos;
-
- user_page = ocfs2_get_write_source(&buf, cur_iov, iov_offset);
- if (IS_ERR(user_page)) {
- ret = PTR_ERR(user_page);
- goto out;
- }
-
- /* Stay within our page boundaries */
- bytes = min((PAGE_CACHE_SIZE - ((unsigned long)pos & ~PAGE_CACHE_MASK)),
- (PAGE_CACHE_SIZE - ((unsigned long)buf & ~PAGE_CACHE_MASK)));
- /* Stay within the vector boundary */
- bytes = min_t(size_t, bytes, cur_iov->iov_len - iov_offset);
- /* Stay within count */
- bytes = min(bytes, count);
-
- page = NULL;
- ret = ocfs2_write_begin(file, file->f_mapping, pos, bytes, 0,
- &page, &fsdata);
- if (ret) {
- mlog_errno(ret);
- goto out;
- }
-
- dst = kmap_atomic(page, KM_USER0);
- memcpy(dst + (pos & (loff_t)(PAGE_CACHE_SIZE - 1)), buf, bytes);
- kunmap_atomic(dst, KM_USER0);
- flush_dcache_page(page);
- ocfs2_put_write_source(user_page);
-
- copied = ocfs2_write_end(file, file->f_mapping, pos, bytes,
- bytes, page, fsdata);
- if (copied < 0) {
- mlog_errno(copied);
- ret = copied;
- goto out;
- }
-
- total += copied;
- *ppos = pos + copied;
- count -= copied;
-
- ocfs2_set_next_iovec(&cur_iov, &iov_offset, copied);
- } while(count);
-
-out:
- return total ? total : ret;
-}
-
static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
const struct iovec *iov,
unsigned long nr_segs,
loff_t pos)
{
int ret, direct_io, appending, rw_level, have_alloc_sem = 0;
- int can_do_direct, sync = 0;
+ int can_do_direct;
ssize_t written = 0;
size_t ocount; /* original count */
size_t count; /* after file limit checks */
- loff_t *ppos = &iocb->ki_pos;
+ loff_t old_size, *ppos = &iocb->ki_pos;
+ u32 old_clusters;
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_path.dentry->d_inode;
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
mlog_entry("(0x%p, %u, '%.*s')\n", file,
(unsigned int)nr_segs,
@@ -2033,12 +1905,6 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
if (iocb->ki_left == 0)
return 0;
- ret = generic_segment_checks(iov, &nr_segs, &ocount, VERIFY_READ);
- if (ret)
- return ret;
-
- count = ocount;
-
vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE);
appending = file->f_flags & O_APPEND ? 1 : 0;
@@ -2082,33 +1948,30 @@ relock:
rw_level = -1;
direct_io = 0;
- sync = 1;
goto relock;
}
- if (!sync && ((file->f_flags & O_SYNC) || IS_SYNC(inode)))
- sync = 1;
-
/*
- * XXX: Is it ok to execute these checks a second time?
+ * To later detect whether a journal commit for sync writes is
+ * necessary, we sample i_size, and cluster count here.
*/
- ret = generic_write_checks(file, ppos, &count, S_ISBLK(inode->i_mode));
- if (ret)
- goto out;
-
- /*
- * Set pos so that sync_page_range_nolock() below understands
- * where to start from. We might've moved it around via the
- * calls above. The range we want to actually sync starts from
- * *ppos here.
- *
- */
- pos = *ppos;
+ old_size = i_size_read(inode);
+ old_clusters = OCFS2_I(inode)->ip_clusters;
/* communicate with ocfs2_dio_end_io */
ocfs2_iocb_set_rw_locked(iocb, rw_level);
if (direct_io) {
+ ret = generic_segment_checks(iov, &nr_segs, &ocount,
+ VERIFY_READ);
+ if (ret)
+ goto out_dio;
+
+ ret = generic_write_checks(file, ppos, &count,
+ S_ISBLK(inode->i_mode));
+ if (ret)
+ goto out_dio;
+
written = generic_file_direct_write(iocb, iov, &nr_segs, *ppos,
ppos, count, ocount);
if (written < 0) {
@@ -2116,20 +1979,29 @@ relock:
goto out_dio;
}
} else {
- written = ocfs2_file_buffered_write(file, ppos, iov, nr_segs,
- count, written);
- if (written < 0) {
- ret = written;
- if (ret != -EFAULT || ret != -ENOSPC)
- mlog_errno(ret);
- goto out;
- }
+ written = generic_file_aio_write_nolock(iocb, iov, nr_segs,
+ *ppos);
}
out_dio:
/* buffered aio wouldn't have proper lock coverage today */
BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT));
+ if ((file->f_flags & O_SYNC && !direct_io) || IS_SYNC(inode)) {
+ /*
+ * The generic write paths have handled getting data
+ * to disk, but since we don't make use of the dirty
+ * inode list, a manual journal commit is necessary
+ * here.
+ */
+ if (old_size != i_size_read(inode) ||
+ old_clusters != OCFS2_I(inode)->ip_clusters) {
+ ret = journal_force_commit(osb->journal->j_journal);
+ if (ret < 0)
+ written = ret;
+ }
+ }
+
/*
* deep in g_f_a_w_n()->ocfs2_direct_IO we pass in a ocfs2_dio_end_io
* function pointer which is called when o_direct io completes so that
@@ -2153,97 +2025,12 @@ out_sems:
if (have_alloc_sem)
up_read(&inode->i_alloc_sem);
- if (written > 0 && sync) {
- ssize_t err;
-
- err = sync_page_range_nolock(inode, file->f_mapping, pos, count);
- if (err < 0)
- written = err;
- }
-
mutex_unlock(&inode->i_mutex);
mlog_exit(ret);
return written ? written : ret;
}
-static int ocfs2_splice_write_actor(struct pipe_inode_info *pipe,
- struct pipe_buffer *buf,
- struct splice_desc *sd)
-{
- int ret, count;
- ssize_t copied = 0;
- struct file *file = sd->u.file;
- unsigned int offset;
- struct page *page = NULL;
- void *fsdata;
- char *src, *dst;
-
- ret = buf->ops->confirm(pipe, buf);
- if (ret)
- goto out;
-
- offset = sd->pos & ~PAGE_CACHE_MASK;
- count = sd->len;
- if (count + offset > PAGE_CACHE_SIZE)
- count = PAGE_CACHE_SIZE - offset;
-
- ret = ocfs2_write_begin(file, file->f_mapping, sd->pos, count, 0,
- &page, &fsdata);
- if (ret) {
- mlog_errno(ret);
- goto out;
- }
-
- src = buf->ops->map(pipe, buf, 1);
- dst = kmap_atomic(page, KM_USER1);
- memcpy(dst + offset, src + buf->offset, count);
- kunmap_atomic(dst, KM_USER1);
- buf->ops->unmap(pipe, buf, src);
-
- copied = ocfs2_write_end(file, file->f_mapping, sd->pos, count, count,
- page, fsdata);
- if (copied < 0) {
- mlog_errno(copied);
- ret = copied;
- goto out;
- }
-out:
-
- return copied ? copied : ret;
-}
-
-static ssize_t __ocfs2_file_splice_write(struct pipe_inode_info *pipe,
- struct file *out,
- loff_t *ppos,
- size_t len,
- unsigned int flags)
-{
- int ret, err;
- struct address_space *mapping = out->f_mapping;
- struct inode *inode = mapping->host;
- struct splice_desc sd = {
- .total_len = len,
- .flags = flags,
- .pos = *ppos,
- .u.file = out,
- };
-
- ret = __splice_from_pipe(pipe, &sd, ocfs2_splice_write_actor);
- if (ret > 0) {
- *ppos += ret;
-
- if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) {
- err = generic_osync_inode(inode, mapping,
- OSYNC_METADATA|OSYNC_DATA);
- if (err)
- ret = err;
- }
- }
-
- return ret;
-}
-
static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe,
struct file *out,
loff_t *ppos,
@@ -2273,8 +2060,7 @@ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe,
goto out_unlock;
}
- /* ok, we're done with i_size and alloc work */
- ret = __ocfs2_file_splice_write(pipe, out, ppos, len, flags);
+ ret = generic_file_splice_write_nolock(pipe, out, ppos, len, flags);
out_unlock:
ocfs2_rw_unlock(inode, 1);
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 729259016c18..989ac2718587 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -1105,9 +1105,16 @@ static int ocfs2_rename(struct inode *old_dir,
goto bail;
}
- if (!new_de && new_inode)
- mlog(ML_ERROR, "inode %lu does not exist in it's parent "
- "directory!", new_inode->i_ino);
+ if (!new_de && new_inode) {
+ /*
+ * Target was unlinked by another node while we were
+ * waiting to get to ocfs2_rename(). There isn't
+ * anything we can do here to help the situation, so
+ * bubble up the appropriate error.
+ */
+ status = -ENOENT;
+ goto bail;
+ }
/* In case we need to overwrite an existing file, we blow it
* away first */
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 0e2a1b45bf92..be562ac3e89c 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -1000,9 +1000,7 @@ bail:
return status;
}
-static void ocfs2_inode_init_once(void *data,
- struct kmem_cache *cachep,
- unsigned long flags)
+static void ocfs2_inode_init_once(struct kmem_cache *cachep, void *data)
{
struct ocfs2_inode_info *oi = data;
diff --git a/fs/open.c b/fs/open.c
index 1d9e5e98bf4e..4932b4d1da05 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -569,7 +569,7 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
dentry = file->f_path.dentry;
inode = dentry->d_inode;
- audit_inode(NULL, inode);
+ audit_inode(NULL, dentry);
err = -EROFS;
if (IS_RDONLY(inode))
@@ -658,7 +658,8 @@ static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
newattrs.ia_gid = group;
}
if (!S_ISDIR(inode->i_mode))
- newattrs.ia_valid |= ATTR_KILL_SUID|ATTR_KILL_SGID;
+ newattrs.ia_valid |=
+ ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
mutex_lock(&inode->i_mutex);
error = notify_change(dentry, &newattrs);
mutex_unlock(&inode->i_mutex);
@@ -726,7 +727,7 @@ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group)
goto out;
dentry = file->f_path.dentry;
- audit_inode(NULL, dentry->d_inode);
+ audit_inode(NULL, dentry);
error = chown_common(dentry, user, group);
fput(file);
out:
@@ -757,6 +758,10 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
f->f_op = fops_get(inode->i_fop);
file_move(f, &inode->i_sb->s_files);
+ error = security_dentry_open(f);
+ if (error)
+ goto cleanup_all;
+
if (!open && f->f_op)
open = f->f_op->open;
if (open) {
@@ -1056,7 +1061,7 @@ asmlinkage long sys_open(const char __user *filename, int flags, int mode)
prevent_tail_call(ret);
return ret;
}
-EXPORT_SYMBOL_GPL(sys_open);
+EXPORT_UNUSED_SYMBOL_GPL(sys_open); /* To be deleted for 2.6.25 */
asmlinkage long sys_openat(int dfd, const char __user *filename, int flags,
int mode)
@@ -1173,7 +1178,7 @@ asmlinkage long sys_vhangup(void)
int generic_file_open(struct inode * inode, struct file * filp)
{
if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
- return -EFBIG;
+ return -EOVERFLOW;
return 0;
}
diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c
index dd86be2aa6c9..d88173840082 100644
--- a/fs/openpromfs/inode.c
+++ b/fs/openpromfs/inode.c
@@ -415,7 +415,7 @@ static struct file_system_type openprom_fs_type = {
.kill_sb = kill_anon_super,
};
-static void op_inode_init_once(void *data, struct kmem_cache * cachep, unsigned long flags)
+static void op_inode_init_once(struct kmem_cache * cachep, void *data)
{
struct op_inode_info *oi = (struct op_inode_info *) data;
diff --git a/fs/pnode.h b/fs/pnode.h
index d45bd8ec36bf..f249be2fee7a 100644
--- a/fs/pnode.h
+++ b/fs/pnode.h
@@ -22,6 +22,7 @@
#define CL_COPY_ALL 0x04
#define CL_MAKE_SHARED 0x08
#define CL_PROPAGATION 0x10
+#define CL_PRIVATE 0x20
static inline void set_mnt_shared(struct vfsmount *mnt)
{
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 27b59f5f3bd1..eba339ecba27 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -77,6 +77,7 @@
#include <linux/cpuset.h>
#include <linux/rcupdate.h>
#include <linux/delayacct.h>
+#include <linux/pid_namespace.h>
#include <asm/pgtable.h>
#include <asm/processor.h>
@@ -145,8 +146,7 @@ static inline const char *get_task_state(struct task_struct *tsk)
TASK_UNINTERRUPTIBLE |
TASK_STOPPED |
TASK_TRACED)) |
- (tsk->exit_state & (EXIT_ZOMBIE |
- EXIT_DEAD));
+ tsk->exit_state;
const char **p = &task_state_array[0];
while (state) {
@@ -161,8 +161,15 @@ static inline char *task_state(struct task_struct *p, char *buffer)
struct group_info *group_info;
int g;
struct fdtable *fdt = NULL;
+ struct pid_namespace *ns;
+ pid_t ppid, tpid;
+ ns = current->nsproxy->pid_ns;
rcu_read_lock();
+ ppid = pid_alive(p) ?
+ task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0;
+ tpid = pid_alive(p) && p->ptrace ?
+ task_ppid_nr_ns(rcu_dereference(p->parent), ns) : 0;
buffer += sprintf(buffer,
"State:\t%s\n"
"Tgid:\t%d\n"
@@ -172,9 +179,9 @@ static inline char *task_state(struct task_struct *p, char *buffer)
"Uid:\t%d\t%d\t%d\t%d\n"
"Gid:\t%d\t%d\t%d\t%d\n",
get_task_state(p),
- p->tgid, p->pid,
- pid_alive(p) ? rcu_dereference(p->real_parent)->tgid : 0,
- pid_alive(p) && p->ptrace ? rcu_dereference(p->parent)->pid : 0,
+ task_tgid_nr_ns(p, ns),
+ task_pid_nr_ns(p, ns),
+ ppid, tpid,
p->uid, p->euid, p->suid, p->fsuid,
p->gid, p->egid, p->sgid, p->fsgid);
@@ -351,7 +358,8 @@ static cputime_t task_utime(struct task_struct *p)
}
utime = (clock_t)temp;
- return clock_t_to_cputime(utime);
+ p->prev_utime = max(p->prev_utime, clock_t_to_cputime(utime));
+ return p->prev_utime;
}
static cputime_t task_stime(struct task_struct *p)
@@ -366,7 +374,8 @@ static cputime_t task_stime(struct task_struct *p)
stime = nsec_to_clock_t(p->se.sum_exec_runtime) -
cputime_to_clock_t(task_utime(p));
- return clock_t_to_cputime(stime);
+ p->prev_stime = max(p->prev_stime, clock_t_to_cputime(stime));
+ return p->prev_stime;
}
#endif
@@ -394,6 +403,9 @@ static int do_task_stat(struct task_struct *task, char *buffer, int whole)
unsigned long rsslim = 0;
char tcomm[sizeof(task->comm)];
unsigned long flags;
+ struct pid_namespace *ns;
+
+ ns = current->nsproxy->pid_ns;
state = *get_task_state(task);
vsize = eip = esp = 0;
@@ -416,7 +428,7 @@ static int do_task_stat(struct task_struct *task, char *buffer, int whole)
struct signal_struct *sig = task->signal;
if (sig->tty) {
- tty_pgrp = pid_nr(sig->tty->pgrp);
+ tty_pgrp = pid_nr_ns(sig->tty->pgrp, ns);
tty_nr = new_encode_dev(tty_devnum(sig->tty));
}
@@ -446,12 +458,12 @@ static int do_task_stat(struct task_struct *task, char *buffer, int whole)
maj_flt += sig->maj_flt;
utime = cputime_add(utime, sig->utime);
stime = cputime_add(stime, sig->stime);
- gtime += cputime_add(gtime, sig->gtime);
+ gtime = cputime_add(gtime, sig->gtime);
}
- sid = signal_session(sig);
- pgid = process_group(task);
- ppid = rcu_dereference(task->real_parent)->tgid;
+ sid = task_session_nr_ns(task, ns);
+ pgid = task_pgrp_nr_ns(task, ns);
+ ppid = task_ppid_nr_ns(task, ns);
unlock_task_sighand(task, &flags);
}
@@ -483,7 +495,7 @@ static int do_task_stat(struct task_struct *task, char *buffer, int whole)
res = sprintf(buffer, "%d (%s) %c %d %d %d %d %d %u %lu \
%lu %lu %lu %lu %lu %ld %ld %ld %ld %d 0 %llu %lu %ld %lu %lu %lu %lu %lu \
%lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu %lu %ld\n",
- task->pid,
+ task_pid_nr_ns(task, ns),
tcomm,
state,
ppid,
diff --git a/fs/proc/base.c b/fs/proc/base.c
index e5d0953d4db1..a17c26859074 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -63,16 +63,19 @@
#include <linux/mm.h>
#include <linux/rcupdate.h>
#include <linux/kallsyms.h>
+#include <linux/resource.h>
#include <linux/module.h>
#include <linux/mount.h>
#include <linux/security.h>
#include <linux/ptrace.h>
+#include <linux/cgroup.h>
#include <linux/cpuset.h>
#include <linux/audit.h>
#include <linux/poll.h>
#include <linux/nsproxy.h>
#include <linux/oom.h>
#include <linux/elf.h>
+#include <linux/pid_namespace.h>
#include "internal.h"
/* NOTE:
@@ -199,27 +202,6 @@ static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vf
(task->state == TASK_STOPPED || task->state == TASK_TRACED) && \
security_ptrace(current,task) == 0))
-static int proc_pid_environ(struct task_struct *task, char * buffer)
-{
- int res = 0;
- struct mm_struct *mm = get_task_mm(task);
- if (mm) {
- unsigned int len;
-
- res = -ESRCH;
- if (!ptrace_may_attach(task))
- goto out;
-
- len = mm->env_end - mm->env_start;
- if (len > PAGE_SIZE)
- len = PAGE_SIZE;
- res = access_process_vm(task, mm->env_start, buffer, len, 0);
-out:
- mmput(mm);
- }
- return res;
-}
-
static int proc_pid_cmdline(struct task_struct *task, char * buffer)
{
int res = 0;
@@ -322,6 +304,78 @@ static int proc_oom_score(struct task_struct *task, char *buffer)
return sprintf(buffer, "%lu\n", points);
}
+struct limit_names {
+ char *name;
+ char *unit;
+};
+
+static const struct limit_names lnames[RLIM_NLIMITS] = {
+ [RLIMIT_CPU] = {"Max cpu time", "ms"},
+ [RLIMIT_FSIZE] = {"Max file size", "bytes"},
+ [RLIMIT_DATA] = {"Max data size", "bytes"},
+ [RLIMIT_STACK] = {"Max stack size", "bytes"},
+ [RLIMIT_CORE] = {"Max core file size", "bytes"},
+ [RLIMIT_RSS] = {"Max resident set", "bytes"},
+ [RLIMIT_NPROC] = {"Max processes", "processes"},
+ [RLIMIT_NOFILE] = {"Max open files", "files"},
+ [RLIMIT_MEMLOCK] = {"Max locked memory", "bytes"},
+ [RLIMIT_AS] = {"Max address space", "bytes"},
+ [RLIMIT_LOCKS] = {"Max file locks", "locks"},
+ [RLIMIT_SIGPENDING] = {"Max pending signals", "signals"},
+ [RLIMIT_MSGQUEUE] = {"Max msgqueue size", "bytes"},
+ [RLIMIT_NICE] = {"Max nice priority", NULL},
+ [RLIMIT_RTPRIO] = {"Max realtime priority", NULL},
+};
+
+/* Display limits for a process */
+static int proc_pid_limits(struct task_struct *task, char *buffer)
+{
+ unsigned int i;
+ int count = 0;
+ unsigned long flags;
+ char *bufptr = buffer;
+
+ struct rlimit rlim[RLIM_NLIMITS];
+
+ rcu_read_lock();
+ if (!lock_task_sighand(task,&flags)) {
+ rcu_read_unlock();
+ return 0;
+ }
+ memcpy(rlim, task->signal->rlim, sizeof(struct rlimit) * RLIM_NLIMITS);
+ unlock_task_sighand(task, &flags);
+ rcu_read_unlock();
+
+ /*
+ * print the file header
+ */
+ count += sprintf(&bufptr[count], "%-25s %-20s %-20s %-10s\n",
+ "Limit", "Soft Limit", "Hard Limit", "Units");
+
+ for (i = 0; i < RLIM_NLIMITS; i++) {
+ if (rlim[i].rlim_cur == RLIM_INFINITY)
+ count += sprintf(&bufptr[count], "%-25s %-20s ",
+ lnames[i].name, "unlimited");
+ else
+ count += sprintf(&bufptr[count], "%-25s %-20lu ",
+ lnames[i].name, rlim[i].rlim_cur);
+
+ if (rlim[i].rlim_max == RLIM_INFINITY)
+ count += sprintf(&bufptr[count], "%-20s ", "unlimited");
+ else
+ count += sprintf(&bufptr[count], "%-20lu ",
+ rlim[i].rlim_max);
+
+ if (lnames[i].unit)
+ count += sprintf(&bufptr[count], "%-10s\n",
+ lnames[i].unit);
+ else
+ count += sprintf(&bufptr[count], "\n");
+ }
+
+ return count;
+}
+
/************************************************************************/
/* Here the fs part begins */
/************************************************************************/
@@ -370,18 +424,21 @@ struct proc_mounts {
static int mounts_open(struct inode *inode, struct file *file)
{
struct task_struct *task = get_proc_task(inode);
+ struct nsproxy *nsp;
struct mnt_namespace *ns = NULL;
struct proc_mounts *p;
int ret = -EINVAL;
if (task) {
- task_lock(task);
- if (task->nsproxy) {
- ns = task->nsproxy->mnt_ns;
+ rcu_read_lock();
+ nsp = task_nsproxy(task);
+ if (nsp) {
+ ns = nsp->mnt_ns;
if (ns)
get_mnt_ns(ns);
}
- task_unlock(task);
+ rcu_read_unlock();
+
put_task_struct(task);
}
@@ -444,16 +501,20 @@ static int mountstats_open(struct inode *inode, struct file *file)
if (!ret) {
struct seq_file *m = file->private_data;
+ struct nsproxy *nsp;
struct mnt_namespace *mnt_ns = NULL;
struct task_struct *task = get_proc_task(inode);
if (task) {
- task_lock(task);
- if (task->nsproxy)
- mnt_ns = task->nsproxy->mnt_ns;
- if (mnt_ns)
- get_mnt_ns(mnt_ns);
- task_unlock(task);
+ rcu_read_lock();
+ nsp = task_nsproxy(task);
+ if (nsp) {
+ mnt_ns = nsp->mnt_ns;
+ if (mnt_ns)
+ get_mnt_ns(mnt_ns);
+ }
+ rcu_read_unlock();
+
put_task_struct(task);
}
@@ -492,7 +553,7 @@ static ssize_t proc_info_read(struct file * file, char __user * buf,
count = PROC_BLOCK_SIZE;
length = -ENOMEM;
- if (!(page = __get_free_page(GFP_KERNEL)))
+ if (!(page = __get_free_page(GFP_TEMPORARY)))
goto out;
length = PROC_I(inode)->op.proc_read(task, (char*)page);
@@ -532,7 +593,7 @@ static ssize_t mem_read(struct file * file, char __user * buf,
goto out;
ret = -ENOMEM;
- page = (char *)__get_free_page(GFP_USER);
+ page = (char *)__get_free_page(GFP_TEMPORARY);
if (!page)
goto out;
@@ -602,7 +663,7 @@ static ssize_t mem_write(struct file * file, const char __user *buf,
goto out;
copied = -ENOMEM;
- page = (char *)__get_free_page(GFP_USER);
+ page = (char *)__get_free_page(GFP_TEMPORARY);
if (!page)
goto out;
@@ -658,6 +719,76 @@ static const struct file_operations proc_mem_operations = {
.open = mem_open,
};
+static ssize_t environ_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
+ char *page;
+ unsigned long src = *ppos;
+ int ret = -ESRCH;
+ struct mm_struct *mm;
+
+ if (!task)
+ goto out_no_task;
+
+ if (!ptrace_may_attach(task))
+ goto out;
+
+ ret = -ENOMEM;
+ page = (char *)__get_free_page(GFP_TEMPORARY);
+ if (!page)
+ goto out;
+
+ ret = 0;
+
+ mm = get_task_mm(task);
+ if (!mm)
+ goto out_free;
+
+ while (count > 0) {
+ int this_len, retval, max_len;
+
+ this_len = mm->env_end - (mm->env_start + src);
+
+ if (this_len <= 0)
+ break;
+
+ max_len = (count > PAGE_SIZE) ? PAGE_SIZE : count;
+ this_len = (this_len > max_len) ? max_len : this_len;
+
+ retval = access_process_vm(task, (mm->env_start + src),
+ page, this_len, 0);
+
+ if (retval <= 0) {
+ ret = retval;
+ break;
+ }
+
+ if (copy_to_user(buf, page, retval)) {
+ ret = -EFAULT;
+ break;
+ }
+
+ ret += retval;
+ src += retval;
+ buf += retval;
+ count -= retval;
+ }
+ *ppos = src;
+
+ mmput(mm);
+out_free:
+ free_page((unsigned long) page);
+out:
+ put_task_struct(task);
+out_no_task:
+ return ret;
+}
+
+static const struct file_operations proc_environ_operations = {
+ .read = environ_read,
+};
+
static ssize_t oom_adjust_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
@@ -788,7 +919,7 @@ static ssize_t proc_loginuid_write(struct file * file, const char __user * buf,
/* No partial writes. */
return -EINVAL;
}
- page = (char*)__get_free_page(GFP_USER);
+ page = (char*)__get_free_page(GFP_TEMPORARY);
if (!page)
return -ENOMEM;
length = -EFAULT;
@@ -954,7 +1085,8 @@ static int do_proc_readlink(struct dentry *dentry, struct vfsmount *mnt,
char __user *buffer, int buflen)
{
struct inode * inode;
- char *tmp = (char*)__get_free_page(GFP_KERNEL), *path;
+ char *tmp = (char*)__get_free_page(GFP_TEMPORARY);
+ char *path;
int len;
if (!tmp)
@@ -1387,7 +1519,7 @@ static int proc_readfd_common(struct file * filp, void * dirent,
struct dentry *dentry = filp->f_path.dentry;
struct inode *inode = dentry->d_inode;
struct task_struct *p = get_proc_task(inode);
- unsigned int fd, tid, ino;
+ unsigned int fd, ino;
int retval;
struct files_struct * files;
struct fdtable *fdt;
@@ -1396,7 +1528,6 @@ static int proc_readfd_common(struct file * filp, void * dirent,
if (!p)
goto out_no_task;
retval = 0;
- tid = p->pid;
fd = filp->f_pos;
switch (fd) {
@@ -1631,7 +1762,6 @@ static int proc_pident_readdir(struct file *filp,
const struct pid_entry *ents, unsigned int nents)
{
int i;
- int pid;
struct dentry *dentry = filp->f_path.dentry;
struct inode *inode = dentry->d_inode;
struct task_struct *task = get_proc_task(inode);
@@ -1644,7 +1774,6 @@ static int proc_pident_readdir(struct file *filp,
goto out_no_task;
ret = 0;
- pid = task->pid;
i = filp->f_pos;
switch (i) {
case 0:
@@ -1726,7 +1855,7 @@ static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
goto out;
length = -ENOMEM;
- page = (char*)__get_free_page(GFP_USER);
+ page = (char*)__get_free_page(GFP_TEMPORARY);
if (!page)
goto out;
@@ -1878,14 +2007,14 @@ static int proc_self_readlink(struct dentry *dentry, char __user *buffer,
int buflen)
{
char tmp[PROC_NUMBUF];
- sprintf(tmp, "%d", current->tgid);
+ sprintf(tmp, "%d", task_tgid_vnr(current));
return vfs_readlink(dentry,buffer,buflen,tmp);
}
static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
{
char tmp[PROC_NUMBUF];
- sprintf(tmp, "%d", current->tgid);
+ sprintf(tmp, "%d", task_tgid_vnr(current));
return ERR_PTR(vfs_follow_link(nd,tmp));
}
@@ -2048,9 +2177,10 @@ static const struct pid_entry tgid_base_stuff[] = {
DIR("task", S_IRUGO|S_IXUGO, task),
DIR("fd", S_IRUSR|S_IXUSR, fd),
DIR("fdinfo", S_IRUSR|S_IXUSR, fdinfo),
- INF("environ", S_IRUSR, pid_environ),
+ REG("environ", S_IRUSR, environ),
INF("auxv", S_IRUSR, pid_auxv),
INF("status", S_IRUGO, pid_status),
+ INF("limits", S_IRUSR, pid_limits),
#ifdef CONFIG_SCHED_DEBUG
REG("sched", S_IRUGO|S_IWUSR, pid_sched),
#endif
@@ -2080,9 +2210,12 @@ static const struct pid_entry tgid_base_stuff[] = {
#ifdef CONFIG_SCHEDSTATS
INF("schedstat", S_IRUGO, pid_schedstat),
#endif
-#ifdef CONFIG_CPUSETS
+#ifdef CONFIG_PROC_PID_CPUSET
REG("cpuset", S_IRUGO, cpuset),
#endif
+#ifdef CONFIG_CGROUPS
+ REG("cgroup", S_IRUGO, cgroup),
+#endif
INF("oom_score", S_IRUGO, oom_score),
REG("oom_adj", S_IRUGO|S_IWUSR, oom_adjust),
#ifdef CONFIG_AUDITSYSCALL
@@ -2122,48 +2255,27 @@ static const struct inode_operations proc_tgid_base_inode_operations = {
.setattr = proc_setattr,
};
-/**
- * proc_flush_task - Remove dcache entries for @task from the /proc dcache.
- *
- * @task: task that should be flushed.
- *
- * Looks in the dcache for
- * /proc/@pid
- * /proc/@tgid/task/@pid
- * if either directory is present flushes it and all of it'ts children
- * from the dcache.
- *
- * It is safe and reasonable to cache /proc entries for a task until
- * that task exits. After that they just clog up the dcache with
- * useless entries, possibly causing useful dcache entries to be
- * flushed instead. This routine is proved to flush those useless
- * dcache entries at process exit time.
- *
- * NOTE: This routine is just an optimization so it does not guarantee
- * that no dcache entries will exist at process exit time it
- * just makes it very unlikely that any will persist.
- */
-void proc_flush_task(struct task_struct *task)
+static void proc_flush_task_mnt(struct vfsmount *mnt, pid_t pid, pid_t tgid)
{
struct dentry *dentry, *leader, *dir;
char buf[PROC_NUMBUF];
struct qstr name;
name.name = buf;
- name.len = snprintf(buf, sizeof(buf), "%d", task->pid);
- dentry = d_hash_and_lookup(proc_mnt->mnt_root, &name);
+ name.len = snprintf(buf, sizeof(buf), "%d", pid);
+ dentry = d_hash_and_lookup(mnt->mnt_root, &name);
if (dentry) {
shrink_dcache_parent(dentry);
d_drop(dentry);
dput(dentry);
}
- if (thread_group_leader(task))
+ if (tgid == 0)
goto out;
name.name = buf;
- name.len = snprintf(buf, sizeof(buf), "%d", task->tgid);
- leader = d_hash_and_lookup(proc_mnt->mnt_root, &name);
+ name.len = snprintf(buf, sizeof(buf), "%d", tgid);
+ leader = d_hash_and_lookup(mnt->mnt_root, &name);
if (!leader)
goto out;
@@ -2174,7 +2286,7 @@ void proc_flush_task(struct task_struct *task)
goto out_put_leader;
name.name = buf;
- name.len = snprintf(buf, sizeof(buf), "%d", task->pid);
+ name.len = snprintf(buf, sizeof(buf), "%d", pid);
dentry = d_hash_and_lookup(dir, &name);
if (dentry) {
shrink_dcache_parent(dentry);
@@ -2189,6 +2301,52 @@ out:
return;
}
+/**
+ * proc_flush_task - Remove dcache entries for @task from the /proc dcache.
+ * @task: task that should be flushed.
+ *
+ * When flushing dentries from proc, one needs to flush them from global
+ * proc (proc_mnt) and from all the namespaces' procs this task was seen
+ * in. This call is supposed to do all of this job.
+ *
+ * Looks in the dcache for
+ * /proc/@pid
+ * /proc/@tgid/task/@pid
+ * if either directory is present flushes it and all of it'ts children
+ * from the dcache.
+ *
+ * It is safe and reasonable to cache /proc entries for a task until
+ * that task exits. After that they just clog up the dcache with
+ * useless entries, possibly causing useful dcache entries to be
+ * flushed instead. This routine is proved to flush those useless
+ * dcache entries at process exit time.
+ *
+ * NOTE: This routine is just an optimization so it does not guarantee
+ * that no dcache entries will exist at process exit time it
+ * just makes it very unlikely that any will persist.
+ */
+
+void proc_flush_task(struct task_struct *task)
+{
+ int i;
+ struct pid *pid, *tgid = NULL;
+ struct upid *upid;
+
+ pid = task_pid(task);
+ if (thread_group_leader(task))
+ tgid = task_tgid(task);
+
+ for (i = 0; i <= pid->level; i++) {
+ upid = &pid->numbers[i];
+ proc_flush_task_mnt(upid->ns->proc_mnt, upid->nr,
+ tgid ? tgid->numbers[i].nr : 0);
+ }
+
+ upid = &pid->numbers[pid->level];
+ if (upid->nr == 1)
+ pid_ns_release_proc(upid->ns);
+}
+
static struct dentry *proc_pid_instantiate(struct inode *dir,
struct dentry * dentry,
struct task_struct *task, const void *ptr)
@@ -2224,6 +2382,7 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct
struct dentry *result = ERR_PTR(-ENOENT);
struct task_struct *task;
unsigned tgid;
+ struct pid_namespace *ns;
result = proc_base_lookup(dir, dentry);
if (!IS_ERR(result) || PTR_ERR(result) != -ENOENT)
@@ -2233,8 +2392,9 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct
if (tgid == ~0U)
goto out;
+ ns = dentry->d_sb->s_fs_info;
rcu_read_lock();
- task = find_task_by_pid(tgid);
+ task = find_task_by_pid_ns(tgid, ns);
if (task)
get_task_struct(task);
rcu_read_unlock();
@@ -2251,7 +2411,8 @@ out:
* Find the first task with tgid >= tgid
*
*/
-static struct task_struct *next_tgid(unsigned int tgid)
+static struct task_struct *next_tgid(unsigned int tgid,
+ struct pid_namespace *ns)
{
struct task_struct *task;
struct pid *pid;
@@ -2259,9 +2420,9 @@ static struct task_struct *next_tgid(unsigned int tgid)
rcu_read_lock();
retry:
task = NULL;
- pid = find_ge_pid(tgid);
+ pid = find_ge_pid(tgid, ns);
if (pid) {
- tgid = pid->nr + 1;
+ tgid = pid_nr_ns(pid, ns) + 1;
task = pid_task(pid, PIDTYPE_PID);
/* What we to know is if the pid we have find is the
* pid of a thread_group_leader. Testing for task
@@ -2301,6 +2462,7 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
struct task_struct *reaper = get_proc_task(filp->f_path.dentry->d_inode);
struct task_struct *task;
int tgid;
+ struct pid_namespace *ns;
if (!reaper)
goto out_no_task;
@@ -2311,11 +2473,12 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
goto out;
}
+ ns = filp->f_dentry->d_sb->s_fs_info;
tgid = filp->f_pos - TGID_OFFSET;
- for (task = next_tgid(tgid);
+ for (task = next_tgid(tgid, ns);
task;
- put_task_struct(task), task = next_tgid(tgid + 1)) {
- tgid = task->pid;
+ put_task_struct(task), task = next_tgid(tgid + 1, ns)) {
+ tgid = task_pid_nr_ns(task, ns);
filp->f_pos = tgid + TGID_OFFSET;
if (proc_pid_fill_cache(filp, dirent, filldir, task, tgid) < 0) {
put_task_struct(task);
@@ -2335,9 +2498,10 @@ out_no_task:
static const struct pid_entry tid_base_stuff[] = {
DIR("fd", S_IRUSR|S_IXUSR, fd),
DIR("fdinfo", S_IRUSR|S_IXUSR, fdinfo),
- INF("environ", S_IRUSR, pid_environ),
+ REG("environ", S_IRUSR, environ),
INF("auxv", S_IRUSR, pid_auxv),
INF("status", S_IRUGO, pid_status),
+ INF("limits", S_IRUSR, pid_limits),
#ifdef CONFIG_SCHED_DEBUG
REG("sched", S_IRUGO|S_IWUSR, pid_sched),
#endif
@@ -2366,9 +2530,12 @@ static const struct pid_entry tid_base_stuff[] = {
#ifdef CONFIG_SCHEDSTATS
INF("schedstat", S_IRUGO, pid_schedstat),
#endif
-#ifdef CONFIG_CPUSETS
+#ifdef CONFIG_PROC_PID_CPUSET
REG("cpuset", S_IRUGO, cpuset),
#endif
+#ifdef CONFIG_CGROUPS
+ REG("cgroup", S_IRUGO, cgroup),
+#endif
INF("oom_score", S_IRUGO, oom_score),
REG("oom_adj", S_IRUGO|S_IWUSR, oom_adjust),
#ifdef CONFIG_AUDITSYSCALL
@@ -2436,6 +2603,7 @@ static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry
struct task_struct *task;
struct task_struct *leader = get_proc_task(dir);
unsigned tid;
+ struct pid_namespace *ns;
if (!leader)
goto out_no_task;
@@ -2444,14 +2612,15 @@ static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry
if (tid == ~0U)
goto out;
+ ns = dentry->d_sb->s_fs_info;
rcu_read_lock();
- task = find_task_by_pid(tid);
+ task = find_task_by_pid_ns(tid, ns);
if (task)
get_task_struct(task);
rcu_read_unlock();
if (!task)
goto out;
- if (leader->tgid != task->tgid)
+ if (!same_thread_group(leader, task))
goto out_drop_task;
result = proc_task_instantiate(dir, dentry, task, NULL);
@@ -2476,14 +2645,14 @@ out_no_task:
* threads past it.
*/
static struct task_struct *first_tid(struct task_struct *leader,
- int tid, int nr)
+ int tid, int nr, struct pid_namespace *ns)
{
struct task_struct *pos;
rcu_read_lock();
/* Attempt to start with the pid of a thread */
if (tid && (nr > 0)) {
- pos = find_task_by_pid(tid);
+ pos = find_task_by_pid_ns(tid, ns);
if (pos && (pos->group_leader == leader))
goto found;
}
@@ -2552,6 +2721,7 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi
ino_t ino;
int tid;
unsigned long pos = filp->f_pos; /* avoiding "long long" filp->f_pos */
+ struct pid_namespace *ns;
task = get_proc_task(inode);
if (!task)
@@ -2585,16 +2755,17 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi
/* f_version caches the tgid value that the last readdir call couldn't
* return. lseek aka telldir automagically resets f_version to 0.
*/
- tid = filp->f_version;
+ ns = filp->f_dentry->d_sb->s_fs_info;
+ tid = (int)filp->f_version;
filp->f_version = 0;
- for (task = first_tid(leader, tid, pos - 2);
+ for (task = first_tid(leader, tid, pos - 2, ns);
task;
task = next_tid(task), pos++) {
- tid = task->pid;
+ tid = task_pid_nr_ns(task, ns);
if (proc_task_fill_cache(filp, dirent, filldir, task, tid) < 0) {
/* returning this tgid failed, save it as the first
* pid for the next readir call */
- filp->f_version = tid;
+ filp->f_version = (u64)tid;
put_task_struct(task);
break;
}
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index b5e7155d30d8..a9806bc21ec3 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -74,7 +74,7 @@ proc_file_read(struct file *file, char __user *buf, size_t nbytes,
nbytes = MAX_NON_LFS - pos;
dp = PDE(inode);
- if (!(page = (char*) __get_free_page(GFP_KERNEL)))
+ if (!(page = (char*) __get_free_page(GFP_TEMPORARY)))
return -ENOMEM;
while ((nbytes > 0) && !eof) {
@@ -561,28 +561,33 @@ static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp
static void proc_kill_inodes(struct proc_dir_entry *de)
{
struct list_head *p;
- struct super_block *sb = proc_mnt->mnt_sb;
+ struct super_block *sb;
/*
* Actually it's a partial revoke().
*/
- file_list_lock();
- list_for_each(p, &sb->s_files) {
- struct file * filp = list_entry(p, struct file, f_u.fu_list);
- struct dentry * dentry = filp->f_path.dentry;
- struct inode * inode;
- const struct file_operations *fops;
-
- if (dentry->d_op != &proc_dentry_operations)
- continue;
- inode = dentry->d_inode;
- if (PDE(inode) != de)
- continue;
- fops = filp->f_op;
- filp->f_op = NULL;
- fops_put(fops);
+ spin_lock(&sb_lock);
+ list_for_each_entry(sb, &proc_fs_type.fs_supers, s_instances) {
+ file_list_lock();
+ list_for_each(p, &sb->s_files) {
+ struct file *filp = list_entry(p, struct file,
+ f_u.fu_list);
+ struct dentry *dentry = filp->f_path.dentry;
+ struct inode *inode;
+ const struct file_operations *fops;
+
+ if (dentry->d_op != &proc_dentry_operations)
+ continue;
+ inode = dentry->d_inode;
+ if (PDE(inode) != de)
+ continue;
+ fops = filp->f_op;
+ filp->f_op = NULL;
+ fops_put(fops);
+ }
+ file_list_unlock();
}
- file_list_unlock();
+ spin_unlock(&sb_lock);
}
static struct proc_dir_entry *proc_create(struct proc_dir_entry **parent,
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 0e4d37c93eea..abe6a3f04368 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -107,7 +107,7 @@ static void proc_destroy_inode(struct inode *inode)
kmem_cache_free(proc_inode_cachep, PROC_I(inode));
}
-static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
+static void init_once(struct kmem_cache * cachep, void *foo)
{
struct proc_inode *ei = (struct proc_inode *) foo;
@@ -119,10 +119,8 @@ int __init proc_init_inodecache(void)
proc_inode_cachep = kmem_cache_create("proc_inode_cache",
sizeof(struct proc_inode),
0, (SLAB_RECLAIM_ACCOUNT|
- SLAB_MEM_SPREAD),
+ SLAB_MEM_SPREAD|SLAB_PANIC),
init_once);
- if (proc_inode_cachep == NULL)
- return -ENOMEM;
return 0;
}
@@ -450,7 +448,7 @@ out_mod:
return NULL;
}
-int proc_fill_super(struct super_block *s, void *data, int silent)
+int proc_fill_super(struct super_block *s)
{
struct inode * root_inode;
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 1820eb2ef762..1b2b6c6bb475 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -78,3 +78,5 @@ static inline int proc_fd(struct inode *inode)
{
return PROC_I(inode)->fd;
}
+
+extern struct file_system_type proc_fs_type;
diff --git a/fs/proc/mmu.c b/fs/proc/mmu.c
index 25d2d9c6e329..8ae221dfd010 100644
--- a/fs/proc/mmu.c
+++ b/fs/proc/mmu.c
@@ -8,27 +8,10 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/time.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/mman.h>
-#include <linux/proc_fs.h>
-#include <linux/mm.h>
-#include <linux/mmzone.h>
-#include <linux/pagemap.h>
-#include <linux/swap.h>
-#include <linux/slab.h>
-#include <linux/smp.h>
-#include <linux/seq_file.h>
-#include <linux/hugetlb.h>
+#include <linux/spinlock.h>
#include <linux/vmalloc.h>
-#include <asm/uaccess.h>
+#include <linux/highmem.h>
#include <asm/pgtable.h>
-#include <asm/tlb.h>
-#include <asm/div64.h>
#include "internal.h"
void get_vmalloc_info(struct vmalloc_info *vmi)
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index b872a01ad3af..e0d064e9764e 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -66,7 +66,6 @@ extern int get_stram_list(char *);
extern int get_filesystem_list(char *);
extern int get_exec_domain_list(char *);
extern int get_dma_list(char *);
-extern int get_locks_status (char *, char **, off_t, int);
static int proc_calc_metrics(char *page, char **start, off_t off,
int count, int *eof, int len)
@@ -92,7 +91,8 @@ static int loadavg_read_proc(char *page, char **start, off_t off,
LOAD_INT(a), LOAD_FRAC(a),
LOAD_INT(b), LOAD_FRAC(b),
LOAD_INT(c), LOAD_FRAC(c),
- nr_running(), nr_threads, current->nsproxy->pid_ns->last_pid);
+ nr_running(), nr_threads,
+ task_active_pid_ns(current)->last_pid);
return proc_calc_metrics(page, start, off, count, eof, len);
}
@@ -230,6 +230,19 @@ static const struct file_operations fragmentation_file_operations = {
.release = seq_release,
};
+extern struct seq_operations pagetypeinfo_op;
+static int pagetypeinfo_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &pagetypeinfo_op);
+}
+
+static const struct file_operations pagetypeinfo_file_ops = {
+ .open = pagetypeinfo_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
extern struct seq_operations zoneinfo_op;
static int zoneinfo_open(struct inode *inode, struct file *file)
{
@@ -514,11 +527,8 @@ static int show_stat(struct seq_file *p, void *v)
}
seq_printf(p, "intr %llu", (unsigned long long)sum);
-#ifndef CONFIG_SMP
- /* Touches too many cache lines on SMP setups */
for (i = 0; i < NR_IRQS; i++)
seq_printf(p, " %u", per_irq_sum[i]);
-#endif
seq_printf(p,
"\nctxt %llu\n"
@@ -624,16 +634,18 @@ static int cmdline_read_proc(char *page, char **start, off_t off,
return proc_calc_metrics(page, start, off, count, eof, len);
}
-static int locks_read_proc(char *page, char **start, off_t off,
- int count, int *eof, void *data)
+static int locks_open(struct inode *inode, struct file *filp)
{
- int len = get_locks_status(page, start, off, count);
-
- if (len < count)
- *eof = 1;
- return len;
+ return seq_open(filp, &locks_seq_operations);
}
+static const struct file_operations proc_locks_operations = {
+ .open = locks_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
static int execdomains_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
@@ -691,7 +703,6 @@ void __init proc_misc_init(void)
#endif
{"filesystems", filesystems_read_proc},
{"cmdline", cmdline_read_proc},
- {"locks", locks_read_proc},
{"execdomains", execdomains_read_proc},
{NULL,}
};
@@ -709,6 +720,7 @@ void __init proc_misc_init(void)
entry->proc_fops = &proc_kmsg_operations;
}
#endif
+ create_seq_entry("locks", 0, &proc_locks_operations);
create_seq_entry("devices", 0, &proc_devinfo_operations);
create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations);
#ifdef CONFIG_BLOCK
@@ -723,6 +735,7 @@ void __init proc_misc_init(void)
#endif
#endif
create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations);
+ create_seq_entry("pagetypeinfo", S_IRUGO, &pagetypeinfo_file_ops);
create_seq_entry("vmstat",S_IRUGO, &proc_vmstat_file_operations);
create_seq_entry("zoneinfo",S_IRUGO, &proc_zoneinfo_file_operations);
#ifdef CONFIG_BLOCK
diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c
index 2e91fb756e9a..131f9c68be5f 100644
--- a/fs/proc/proc_net.c
+++ b/fs/proc/proc_net.c
@@ -26,13 +26,6 @@
#include "internal.h"
-struct proc_dir_entry *proc_net_create(struct net *net,
- const char *name, mode_t mode, get_info_t *get_info)
-{
- return create_proc_info_entry(name,mode, net->proc_net, get_info);
-}
-EXPORT_SYMBOL_GPL(proc_net_create);
-
struct proc_dir_entry *proc_net_fops_create(struct net *net,
const char *name, mode_t mode, const struct file_operations *fops)
{
@@ -185,7 +178,7 @@ static __net_exit void proc_net_ns_exit(struct net *net)
kfree(net->proc_net_root);
}
-struct pernet_operations __net_initdata proc_net_ns_ops = {
+static struct pernet_operations __net_initdata proc_net_ns_ops = {
.init = proc_net_ns_init,
.exit = proc_net_ns_exit,
};
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index 680c429bfa22..4e57fcf85982 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -171,7 +171,8 @@ static ssize_t proc_sys_read(struct file *filp, char __user *buf,
struct dentry *dentry = filp->f_dentry;
struct ctl_table_header *head;
struct ctl_table *table;
- ssize_t error, res;
+ ssize_t error;
+ size_t res;
table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head);
/* Has the sysctl entry disappeared on us? */
@@ -209,7 +210,8 @@ static ssize_t proc_sys_write(struct file *filp, const char __user *buf,
struct dentry *dentry = filp->f_dentry;
struct ctl_table_header *head;
struct ctl_table *table;
- ssize_t error, res;
+ ssize_t error;
+ size_t res;
table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head);
/* Has the sysctl entry disappeared on us? */
diff --git a/fs/proc/root.c b/fs/proc/root.c
index cf3046638b09..1f86bb860e04 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -18,32 +18,90 @@
#include <linux/bitops.h>
#include <linux/smp_lock.h>
#include <linux/mount.h>
+#include <linux/pid_namespace.h>
#include "internal.h"
struct proc_dir_entry *proc_bus, *proc_root_fs, *proc_root_driver;
+static int proc_test_super(struct super_block *sb, void *data)
+{
+ return sb->s_fs_info == data;
+}
+
+static int proc_set_super(struct super_block *sb, void *data)
+{
+ struct pid_namespace *ns;
+
+ ns = (struct pid_namespace *)data;
+ sb->s_fs_info = get_pid_ns(ns);
+ return set_anon_super(sb, NULL);
+}
+
static int proc_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data, struct vfsmount *mnt)
{
+ int err;
+ struct super_block *sb;
+ struct pid_namespace *ns;
+ struct proc_inode *ei;
+
if (proc_mnt) {
/* Seed the root directory with a pid so it doesn't need
* to be special in base.c. I would do this earlier but
* the only task alive when /proc is mounted the first time
* is the init_task and it doesn't have any pids.
*/
- struct proc_inode *ei;
ei = PROC_I(proc_mnt->mnt_sb->s_root->d_inode);
if (!ei->pid)
ei->pid = find_get_pid(1);
}
- return get_sb_single(fs_type, flags, data, proc_fill_super, mnt);
+
+ if (flags & MS_KERNMOUNT)
+ ns = (struct pid_namespace *)data;
+ else
+ ns = current->nsproxy->pid_ns;
+
+ sb = sget(fs_type, proc_test_super, proc_set_super, ns);
+ if (IS_ERR(sb))
+ return PTR_ERR(sb);
+
+ if (!sb->s_root) {
+ sb->s_flags = flags;
+ err = proc_fill_super(sb);
+ if (err) {
+ up_write(&sb->s_umount);
+ deactivate_super(sb);
+ return err;
+ }
+
+ ei = PROC_I(sb->s_root->d_inode);
+ if (!ei->pid) {
+ rcu_read_lock();
+ ei->pid = get_pid(find_pid_ns(1, ns));
+ rcu_read_unlock();
+ }
+
+ sb->s_flags |= MS_ACTIVE;
+ ns->proc_mnt = mnt;
+ }
+
+ return simple_set_mnt(mnt, sb);
}
-static struct file_system_type proc_fs_type = {
+static void proc_kill_sb(struct super_block *sb)
+{
+ struct pid_namespace *ns;
+
+ ns = (struct pid_namespace *)sb->s_fs_info;
+ kill_anon_super(sb);
+ put_pid_ns(ns);
+}
+
+struct file_system_type proc_fs_type = {
.name = "proc",
.get_sb = proc_get_sb,
- .kill_sb = kill_anon_super,
+ .kill_sb = proc_kill_sb,
};
void __init proc_root_init(void)
@@ -54,12 +112,13 @@ void __init proc_root_init(void)
err = register_filesystem(&proc_fs_type);
if (err)
return;
- proc_mnt = kern_mount(&proc_fs_type);
+ proc_mnt = kern_mount_data(&proc_fs_type, &init_pid_ns);
err = PTR_ERR(proc_mnt);
if (IS_ERR(proc_mnt)) {
unregister_filesystem(&proc_fs_type);
return;
}
+
proc_misc_init();
proc_net_init();
@@ -153,6 +212,22 @@ struct proc_dir_entry proc_root = {
.parent = &proc_root,
};
+int pid_ns_prepare_proc(struct pid_namespace *ns)
+{
+ struct vfsmount *mnt;
+
+ mnt = kern_mount_data(&proc_fs_type, ns);
+ if (IS_ERR(mnt))
+ return PTR_ERR(mnt);
+
+ return 0;
+}
+
+void pid_ns_release_proc(struct pid_namespace *ns)
+{
+ mntput(ns->proc_mnt);
+}
+
EXPORT_SYMBOL(proc_symlink);
EXPORT_SYMBOL(proc_mkdir);
EXPORT_SYMBOL(create_proc_entry);
diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c
index 1bc8d873a9e1..638bdb963213 100644
--- a/fs/qnx4/inode.c
+++ b/fs/qnx4/inode.c
@@ -433,16 +433,21 @@ static int qnx4_writepage(struct page *page, struct writeback_control *wbc)
{
return block_write_full_page(page,qnx4_get_block, wbc);
}
+
static int qnx4_readpage(struct file *file, struct page *page)
{
return block_read_full_page(page,qnx4_get_block);
}
-static int qnx4_prepare_write(struct file *file, struct page *page,
- unsigned from, unsigned to)
+
+static int qnx4_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
{
- struct qnx4_inode_info *qnx4_inode = qnx4_i(page->mapping->host);
- return cont_prepare_write(page, from, to, qnx4_get_block,
- &qnx4_inode->mmu_private);
+ struct qnx4_inode_info *qnx4_inode = qnx4_i(mapping->host);
+ *pagep = NULL;
+ return cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
+ qnx4_get_block,
+ &qnx4_inode->mmu_private);
}
static sector_t qnx4_bmap(struct address_space *mapping, sector_t block)
{
@@ -452,8 +457,8 @@ static const struct address_space_operations qnx4_aops = {
.readpage = qnx4_readpage,
.writepage = qnx4_writepage,
.sync_page = block_sync_page,
- .prepare_write = qnx4_prepare_write,
- .commit_write = generic_commit_write,
+ .write_begin = qnx4_write_begin,
+ .write_end = generic_write_end,
.bmap = qnx4_bmap
};
@@ -531,8 +536,7 @@ static void qnx4_destroy_inode(struct inode *inode)
kmem_cache_free(qnx4_inode_cachep, qnx4_i(inode));
}
-static void init_once(void *foo, struct kmem_cache * cachep,
- unsigned long flags)
+static void init_once(struct kmem_cache *cachep, void *foo)
{
struct qnx4_inode_info *ei = (struct qnx4_inode_info *) foo;
diff --git a/fs/ramfs/Makefile b/fs/ramfs/Makefile
index 5a0236e02ee1..c71e65dcad25 100644
--- a/fs/ramfs/Makefile
+++ b/fs/ramfs/Makefile
@@ -2,7 +2,7 @@
# Makefile for the linux ramfs routines.
#
-obj-$(CONFIG_RAMFS) += ramfs.o
+obj-y += ramfs.o
file-mmu-y := file-nommu.o
file-mmu-$(CONFIG_MMU) := file-mmu.o
diff --git a/fs/ramfs/file-mmu.c b/fs/ramfs/file-mmu.c
index 97bdc0b2f9d2..b41a514b0976 100644
--- a/fs/ramfs/file-mmu.c
+++ b/fs/ramfs/file-mmu.c
@@ -29,8 +29,8 @@
const struct address_space_operations ramfs_aops = {
.readpage = simple_readpage,
- .prepare_write = simple_prepare_write,
- .commit_write = simple_commit_write,
+ .write_begin = simple_write_begin,
+ .write_end = simple_write_end,
.set_page_dirty = __set_page_dirty_no_writeback,
};
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c
index 237fe8b8e819..0989bc2c2f69 100644
--- a/fs/ramfs/file-nommu.c
+++ b/fs/ramfs/file-nommu.c
@@ -29,8 +29,8 @@ static int ramfs_nommu_setattr(struct dentry *, struct iattr *);
const struct address_space_operations ramfs_aops = {
.readpage = simple_readpage,
- .prepare_write = simple_prepare_write,
- .commit_write = simple_commit_write,
+ .write_begin = simple_write_begin,
+ .write_end = simple_write_end,
.set_page_dirty = __set_page_dirty_no_writeback,
};
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index ef2b46d099ff..8428d5b2711d 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -223,7 +223,17 @@ module_exit(exit_ramfs_fs)
int __init init_rootfs(void)
{
- return register_filesystem(&rootfs_fs_type);
+ int err;
+
+ err = bdi_init(&ramfs_backing_dev_info);
+ if (err)
+ return err;
+
+ err = register_filesystem(&rootfs_fs_type);
+ if (err)
+ bdi_destroy(&ramfs_backing_dev_info);
+
+ return err;
}
MODULE_LICENSE("GPL");
diff --git a/fs/read_write.c b/fs/read_write.c
index 507ddff48a9a..ea1f94cc722e 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -205,7 +205,7 @@ int rw_verify_area(int read_write, struct file *file, loff_t *ppos, size_t count
if (unlikely((pos < 0) || (loff_t) (pos + count) < 0))
goto Einval;
- if (unlikely(inode->i_flock && MANDATORY_LOCK(inode))) {
+ if (unlikely(inode->i_flock && mandatory_lock(inode))) {
int retval = locks_mandatory_area(
read_write == READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE,
inode, file, pos, count);
@@ -370,7 +370,7 @@ asmlinkage ssize_t sys_read(unsigned int fd, char __user * buf, size_t count)
return ret;
}
-EXPORT_SYMBOL_GPL(sys_read);
+EXPORT_UNUSED_SYMBOL_GPL(sys_read); /* to be deleted for 2.6.25 */
asmlinkage ssize_t sys_write(unsigned int fd, const char __user * buf, size_t count)
{
diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c
index b286ccb08587..16b331dd9913 100644
--- a/fs/reiserfs/bitmap.c
+++ b/fs/reiserfs/bitmap.c
@@ -47,7 +47,9 @@
test_bit(_ALLOC_ ## optname , &SB_ALLOC_OPTS(s))
static inline void get_bit_address(struct super_block *s,
- b_blocknr_t block, int *bmap_nr, int *offset)
+ b_blocknr_t block,
+ unsigned int *bmap_nr,
+ unsigned int *offset)
{
/* It is in the bitmap block number equal to the block
* number divided by the number of bits in a block. */
@@ -56,10 +58,10 @@ static inline void get_bit_address(struct super_block *s,
*offset = block & ((s->s_blocksize << 3) - 1);
}
-#ifdef CONFIG_REISERFS_CHECK
int is_reusable(struct super_block *s, b_blocknr_t block, int bit_value)
{
- int bmap, offset;
+ unsigned int bmap, offset;
+ unsigned int bmap_count = reiserfs_bmap_count(s);
if (block == 0 || block >= SB_BLOCK_COUNT(s)) {
reiserfs_warning(s,
@@ -75,25 +77,26 @@ int is_reusable(struct super_block *s, b_blocknr_t block, int bit_value)
if (unlikely(test_bit(REISERFS_OLD_FORMAT,
&(REISERFS_SB(s)->s_properties)))) {
b_blocknr_t bmap1 = REISERFS_SB(s)->s_sbh->b_blocknr + 1;
- if (block >= bmap1 && block <= bmap1 + SB_BMAP_NR(s)) {
+ if (block >= bmap1 &&
+ block <= bmap1 + bmap_count) {
reiserfs_warning(s, "vs: 4019: is_reusable: "
"bitmap block %lu(%u) can't be freed or reused",
- block, SB_BMAP_NR(s));
+ block, bmap_count);
return 0;
}
} else {
if (offset == 0) {
reiserfs_warning(s, "vs: 4020: is_reusable: "
"bitmap block %lu(%u) can't be freed or reused",
- block, SB_BMAP_NR(s));
+ block, bmap_count);
return 0;
}
}
- if (bmap >= SB_BMAP_NR(s)) {
+ if (bmap >= bmap_count) {
reiserfs_warning(s,
"vs-4030: is_reusable: there is no so many bitmap blocks: "
- "block=%lu, bitmap_nr=%d", block, bmap);
+ "block=%lu, bitmap_nr=%u", block, bmap);
return 0;
}
@@ -106,12 +109,11 @@ int is_reusable(struct super_block *s, b_blocknr_t block, int bit_value)
return 1;
}
-#endif /* CONFIG_REISERFS_CHECK */
/* searches in journal structures for a given block number (bmap, off). If block
is found in reiserfs journal it suggests next free block candidate to test. */
-static inline int is_block_in_journal(struct super_block *s, int bmap, int
- off, int *next)
+static inline int is_block_in_journal(struct super_block *s, unsigned int bmap,
+ int off, int *next)
{
b_blocknr_t tmp;
@@ -132,8 +134,8 @@ static inline int is_block_in_journal(struct super_block *s, int bmap, int
/* it searches for a window of zero bits with given minimum and maximum lengths in one bitmap
* block; */
static int scan_bitmap_block(struct reiserfs_transaction_handle *th,
- int bmap_n, int *beg, int boundary, int min,
- int max, int unfm)
+ unsigned int bmap_n, int *beg, int boundary,
+ int min, int max, int unfm)
{
struct super_block *s = th->t_super;
struct reiserfs_bitmap_info *bi = &SB_AP_BITMAP(s)[bmap_n];
@@ -143,8 +145,8 @@ static int scan_bitmap_block(struct reiserfs_transaction_handle *th,
BUG_ON(!th->t_trans_id);
- RFALSE(bmap_n >= SB_BMAP_NR(s), "Bitmap %d is out of range (0..%d)",
- bmap_n, SB_BMAP_NR(s) - 1);
+ RFALSE(bmap_n >= reiserfs_bmap_count(s), "Bitmap %u is out of "
+ "range (0..%u)", bmap_n, reiserfs_bmap_count(s) - 1);
PROC_INFO_INC(s, scan_bitmap.bmap);
/* this is unclear and lacks comments, explain how journal bitmaps
work here for the reader. Convey a sense of the design here. What
@@ -249,12 +251,12 @@ static int bmap_hash_id(struct super_block *s, u32 id)
} else {
hash_in = (char *)(&id);
hash = keyed_hash(hash_in, 4);
- bm = hash % SB_BMAP_NR(s);
+ bm = hash % reiserfs_bmap_count(s);
if (!bm)
bm = 1;
}
/* this can only be true when SB_BMAP_NR = 1 */
- if (bm >= SB_BMAP_NR(s))
+ if (bm >= reiserfs_bmap_count(s))
bm = 0;
return bm;
}
@@ -273,7 +275,7 @@ static inline int block_group_used(struct super_block *s, u32 id)
* to make a better decision. This favors long-term performace gain
* with a better on-disk layout vs. a short term gain of skipping the
* read and potentially having a bad placement. */
- if (info->first_zero_hint == 0) {
+ if (info->free_count == UINT_MAX) {
struct buffer_head *bh = reiserfs_read_bitmap_block(s, bm);
brelse(bh);
}
@@ -309,16 +311,16 @@ __le32 reiserfs_choose_packing(struct inode * dir)
* bitmap and place new blocks there. Returns number of allocated blocks. */
static int scan_bitmap(struct reiserfs_transaction_handle *th,
b_blocknr_t * start, b_blocknr_t finish,
- int min, int max, int unfm, unsigned long file_block)
+ int min, int max, int unfm, sector_t file_block)
{
int nr_allocated = 0;
struct super_block *s = th->t_super;
/* find every bm and bmap and bmap_nr in this file, and change them all to bitmap_blocknr
* - Hans, it is not a block number - Zam. */
- int bm, off;
- int end_bm, end_off;
- int off_max = s->s_blocksize << 3;
+ unsigned int bm, off;
+ unsigned int end_bm, end_off;
+ unsigned int off_max = s->s_blocksize << 3;
BUG_ON(!th->t_trans_id);
@@ -328,10 +330,10 @@ static int scan_bitmap(struct reiserfs_transaction_handle *th,
get_bit_address(s, *start, &bm, &off);
get_bit_address(s, finish, &end_bm, &end_off);
- if (bm > SB_BMAP_NR(s))
+ if (bm > reiserfs_bmap_count(s))
return 0;
- if (end_bm > SB_BMAP_NR(s))
- end_bm = SB_BMAP_NR(s);
+ if (end_bm > reiserfs_bmap_count(s))
+ end_bm = reiserfs_bmap_count(s);
/* When the bitmap is more than 10% free, anyone can allocate.
* When it's less than 10% free, only files that already use the
@@ -385,7 +387,7 @@ static void _reiserfs_free_block(struct reiserfs_transaction_handle *th,
struct reiserfs_super_block *rs;
struct buffer_head *sbh, *bmbh;
struct reiserfs_bitmap_info *apbi;
- int nr, offset;
+ unsigned int nr, offset;
BUG_ON(!th->t_trans_id);
@@ -397,10 +399,12 @@ static void _reiserfs_free_block(struct reiserfs_transaction_handle *th,
get_bit_address(s, block, &nr, &offset);
- if (nr >= sb_bmap_nr(rs)) {
+ if (nr >= reiserfs_bmap_count(s)) {
reiserfs_warning(s, "vs-4075: reiserfs_free_block: "
- "block %lu is out of range on %s",
- block, reiserfs_bdevname(s));
+ "block %lu is out of range on %s "
+ "(nr=%u,max=%u)", block,
+ reiserfs_bdevname(s), nr,
+ reiserfs_bmap_count(s));
return;
}
@@ -434,12 +438,19 @@ void reiserfs_free_block(struct reiserfs_transaction_handle *th,
int for_unformatted)
{
struct super_block *s = th->t_super;
-
BUG_ON(!th->t_trans_id);
RFALSE(!s, "vs-4061: trying to free block on nonexistent device");
- RFALSE(is_reusable(s, block, 1) == 0,
- "vs-4071: can not free such block");
+ if (!is_reusable(s, block, 1))
+ return;
+
+ if (block > sb_block_count(REISERFS_SB(s)->s_rs)) {
+ reiserfs_panic(th->t_super, "bitmap-4072",
+ "Trying to free block outside file system "
+ "boundaries (%lu > %lu)",
+ block, sb_block_count(REISERFS_SB(s)->s_rs));
+ return;
+ }
/* mark it before we clear it, just in case */
journal_mark_freed(th, s, block);
_reiserfs_free_block(th, inode, block, for_unformatted);
@@ -449,11 +460,11 @@ void reiserfs_free_block(struct reiserfs_transaction_handle *th,
static void reiserfs_free_prealloc_block(struct reiserfs_transaction_handle *th,
struct inode *inode, b_blocknr_t block)
{
+ BUG_ON(!th->t_trans_id);
RFALSE(!th->t_super,
"vs-4060: trying to free block on nonexistent device");
- RFALSE(is_reusable(th->t_super, block, 1) == 0,
- "vs-4070: can not free such block");
- BUG_ON(!th->t_trans_id);
+ if (!is_reusable(th->t_super, block, 1))
+ return;
_reiserfs_free_block(th, inode, block, 1);
}
@@ -1201,90 +1212,28 @@ int reiserfs_allocate_blocknrs(reiserfs_blocknr_hint_t * hint, b_blocknr_t * new
return ret;
}
-/* These 2 functions are here to provide blocks reservation to the rest of kernel */
-/* Reserve @blocks amount of blocks in fs pointed by @sb. Caller must make sure
- there are actually this much blocks on the FS available */
-void reiserfs_claim_blocks_to_be_allocated(struct super_block *sb, /* super block of
- filesystem where
- blocks should be
- reserved */
- int blocks /* How much to reserve */
- )
-{
-
- /* Fast case, if reservation is zero - exit immediately. */
- if (!blocks)
- return;
-
- spin_lock(&REISERFS_SB(sb)->bitmap_lock);
- REISERFS_SB(sb)->reserved_blocks += blocks;
- spin_unlock(&REISERFS_SB(sb)->bitmap_lock);
-}
-
-/* Unreserve @blocks amount of blocks in fs pointed by @sb */
-void reiserfs_release_claimed_blocks(struct super_block *sb, /* super block of
- filesystem where
- blocks should be
- reserved */
- int blocks /* How much to unreserve */
- )
-{
-
- /* Fast case, if unreservation is zero - exit immediately. */
- if (!blocks)
- return;
-
- spin_lock(&REISERFS_SB(sb)->bitmap_lock);
- REISERFS_SB(sb)->reserved_blocks -= blocks;
- spin_unlock(&REISERFS_SB(sb)->bitmap_lock);
- RFALSE(REISERFS_SB(sb)->reserved_blocks < 0,
- "amount of blocks reserved became zero?");
-}
-
-/* This function estimates how much pages we will be able to write to FS
- used for reiserfs_file_write() purposes for now. */
-int reiserfs_can_fit_pages(struct super_block *sb /* superblock of filesystem
- to estimate space */ )
-{
- int space;
-
- spin_lock(&REISERFS_SB(sb)->bitmap_lock);
- space =
- (SB_FREE_BLOCKS(sb) -
- REISERFS_SB(sb)->reserved_blocks) >> (PAGE_CACHE_SHIFT -
- sb->s_blocksize_bits);
- spin_unlock(&REISERFS_SB(sb)->bitmap_lock);
-
- return space > 0 ? space : 0;
-}
-
void reiserfs_cache_bitmap_metadata(struct super_block *sb,
struct buffer_head *bh,
struct reiserfs_bitmap_info *info)
{
unsigned long *cur = (unsigned long *)(bh->b_data + bh->b_size);
- info->first_zero_hint = 1 << (sb->s_blocksize_bits + 3);
+ /* The first bit must ALWAYS be 1 */
+ BUG_ON(!reiserfs_test_le_bit(0, (unsigned long *)bh->b_data));
+
+ info->free_count = 0;
while (--cur >= (unsigned long *)bh->b_data) {
- int base = ((char *)cur - bh->b_data) << 3;
+ int i;
/* 0 and ~0 are special, we can optimize for them */
- if (*cur == 0) {
- info->first_zero_hint = base;
+ if (*cur == 0)
info->free_count += BITS_PER_LONG;
- } else if (*cur != ~0L) { /* A mix, investigate */
- int b;
- for (b = BITS_PER_LONG - 1; b >= 0; b--) {
- if (!reiserfs_test_le_bit(b, cur)) {
- info->first_zero_hint = base + b;
+ else if (*cur != ~0L) /* A mix, investigate */
+ for (i = BITS_PER_LONG - 1; i >= 0; i--)
+ if (!reiserfs_test_le_bit(i, cur))
info->free_count++;
- }
- }
- }
}
- /* The first bit must ALWAYS be 1 */
- BUG_ON(info->first_zero_hint == 0);
}
struct buffer_head *reiserfs_read_bitmap_block(struct super_block *sb,
@@ -1314,7 +1263,7 @@ struct buffer_head *reiserfs_read_bitmap_block(struct super_block *sb,
BUG_ON(!buffer_uptodate(bh));
BUG_ON(atomic_read(&bh->b_count) == 0);
- if (info->first_zero_hint == 0)
+ if (info->free_count == UINT_MAX)
reiserfs_cache_bitmap_metadata(sb, bh, info);
}
@@ -1324,12 +1273,13 @@ struct buffer_head *reiserfs_read_bitmap_block(struct super_block *sb,
int reiserfs_init_bitmap_cache(struct super_block *sb)
{
struct reiserfs_bitmap_info *bitmap;
+ unsigned int bmap_nr = reiserfs_bmap_count(sb);
- bitmap = vmalloc(sizeof (*bitmap) * SB_BMAP_NR(sb));
+ bitmap = vmalloc(sizeof(*bitmap) * bmap_nr);
if (bitmap == NULL)
return -ENOMEM;
- memset(bitmap, 0, sizeof (*bitmap) * SB_BMAP_NR(sb));
+ memset(bitmap, 0xff, sizeof(*bitmap) * bmap_nr);
SB_AP_BITMAP(sb) = bitmap;
diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c
index ffbfc2caaf20..e6b03d2020c1 100644
--- a/fs/reiserfs/dir.c
+++ b/fs/reiserfs/dir.c
@@ -121,6 +121,16 @@ static int reiserfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
continue;
d_reclen = entry_length(bh, ih, entry_num);
d_name = B_I_DEH_ENTRY_FILE_NAME(bh, ih, deh);
+
+ if (d_reclen <= 0 ||
+ d_name + d_reclen > bh->b_data + bh->b_size) {
+ /* There is corrupted data in entry,
+ * We'd better stop here */
+ pathrelse(&path_to_entry);
+ ret = -EIO;
+ goto out;
+ }
+
if (!d_name[d_reclen - 1])
d_reclen = strlen(d_name);
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 2070aeee2a52..a804903d31d1 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -153,608 +153,6 @@ static int reiserfs_sync_file(struct file *p_s_filp,
return (n_err < 0) ? -EIO : 0;
}
-/* I really do not want to play with memory shortage right now, so
- to simplify the code, we are not going to write more than this much pages at
- a time. This still should considerably improve performance compared to 4k
- at a time case. This is 32 pages of 4k size. */
-#define REISERFS_WRITE_PAGES_AT_A_TIME (128 * 1024) / PAGE_CACHE_SIZE
-
-/* Allocates blocks for a file to fulfil write request.
- Maps all unmapped but prepared pages from the list.
- Updates metadata with newly allocated blocknumbers as needed */
-static int reiserfs_allocate_blocks_for_region(struct reiserfs_transaction_handle *th, struct inode *inode, /* Inode we work with */
- loff_t pos, /* Writing position */
- int num_pages, /* number of pages write going
- to touch */
- int write_bytes, /* amount of bytes to write */
- struct page **prepared_pages, /* array of
- prepared pages
- */
- int blocks_to_allocate /* Amount of blocks we
- need to allocate to
- fit the data into file
- */
- )
-{
- struct cpu_key key; // cpu key of item that we are going to deal with
- struct item_head *ih; // pointer to item head that we are going to deal with
- struct buffer_head *bh; // Buffer head that contains items that we are going to deal with
- __le32 *item; // pointer to item we are going to deal with
- INITIALIZE_PATH(path); // path to item, that we are going to deal with.
- b_blocknr_t *allocated_blocks; // Pointer to a place where allocated blocknumbers would be stored.
- reiserfs_blocknr_hint_t hint; // hint structure for block allocator.
- size_t res; // return value of various functions that we call.
- int curr_block; // current block used to keep track of unmapped blocks.
- int i; // loop counter
- int itempos; // position in item
- unsigned int from = (pos & (PAGE_CACHE_SIZE - 1)); // writing position in
- // first page
- unsigned int to = ((pos + write_bytes - 1) & (PAGE_CACHE_SIZE - 1)) + 1; /* last modified byte offset in last page */
- __u64 hole_size; // amount of blocks for a file hole, if it needed to be created.
- int modifying_this_item = 0; // Flag for items traversal code to keep track
- // of the fact that we already prepared
- // current block for journal
- int will_prealloc = 0;
- RFALSE(!blocks_to_allocate,
- "green-9004: tried to allocate zero blocks?");
-
- /* only preallocate if this is a small write */
- if (REISERFS_I(inode)->i_prealloc_count ||
- (!(write_bytes & (inode->i_sb->s_blocksize - 1)) &&
- blocks_to_allocate <
- REISERFS_SB(inode->i_sb)->s_alloc_options.preallocsize))
- will_prealloc =
- REISERFS_SB(inode->i_sb)->s_alloc_options.preallocsize;
-
- allocated_blocks = kmalloc((blocks_to_allocate + will_prealloc) *
- sizeof(b_blocknr_t), GFP_NOFS);
- if (!allocated_blocks)
- return -ENOMEM;
-
- /* First we compose a key to point at the writing position, we want to do
- that outside of any locking region. */
- make_cpu_key(&key, inode, pos + 1, TYPE_ANY, 3 /*key length */ );
-
- /* If we came here, it means we absolutely need to open a transaction,
- since we need to allocate some blocks */
- reiserfs_write_lock(inode->i_sb); // Journaling stuff and we need that.
- res = journal_begin(th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb)); // Wish I know if this number enough
- if (res)
- goto error_exit;
- reiserfs_update_inode_transaction(inode);
-
- /* Look for the in-tree position of our write, need path for block allocator */
- res = search_for_position_by_key(inode->i_sb, &key, &path);
- if (res == IO_ERROR) {
- res = -EIO;
- goto error_exit;
- }
-
- /* Allocate blocks */
- /* First fill in "hint" structure for block allocator */
- hint.th = th; // transaction handle.
- hint.path = &path; // Path, so that block allocator can determine packing locality or whatever it needs to determine.
- hint.inode = inode; // Inode is needed by block allocator too.
- hint.search_start = 0; // We have no hint on where to search free blocks for block allocator.
- hint.key = key.on_disk_key; // on disk key of file.
- hint.block = inode->i_blocks >> (inode->i_sb->s_blocksize_bits - 9); // Number of disk blocks this file occupies already.
- hint.formatted_node = 0; // We are allocating blocks for unformatted node.
- hint.preallocate = will_prealloc;
-
- /* Call block allocator to allocate blocks */
- res =
- reiserfs_allocate_blocknrs(&hint, allocated_blocks,
- blocks_to_allocate, blocks_to_allocate);
- if (res != CARRY_ON) {
- if (res == NO_DISK_SPACE) {
- /* We flush the transaction in case of no space. This way some
- blocks might become free */
- SB_JOURNAL(inode->i_sb)->j_must_wait = 1;
- res = restart_transaction(th, inode, &path);
- if (res)
- goto error_exit;
-
- /* We might have scheduled, so search again */
- res =
- search_for_position_by_key(inode->i_sb, &key,
- &path);
- if (res == IO_ERROR) {
- res = -EIO;
- goto error_exit;
- }
-
- /* update changed info for hint structure. */
- res =
- reiserfs_allocate_blocknrs(&hint, allocated_blocks,
- blocks_to_allocate,
- blocks_to_allocate);
- if (res != CARRY_ON) {
- res = res == QUOTA_EXCEEDED ? -EDQUOT : -ENOSPC;
- pathrelse(&path);
- goto error_exit;
- }
- } else {
- res = res == QUOTA_EXCEEDED ? -EDQUOT : -ENOSPC;
- pathrelse(&path);
- goto error_exit;
- }
- }
-#ifdef __BIG_ENDIAN
- // Too bad, I have not found any way to convert a given region from
- // cpu format to little endian format
- {
- int i;
- for (i = 0; i < blocks_to_allocate; i++)
- allocated_blocks[i] = cpu_to_le32(allocated_blocks[i]);
- }
-#endif
-
- /* Blocks allocating well might have scheduled and tree might have changed,
- let's search the tree again */
- /* find where in the tree our write should go */
- res = search_for_position_by_key(inode->i_sb, &key, &path);
- if (res == IO_ERROR) {
- res = -EIO;
- goto error_exit_free_blocks;
- }
-
- bh = get_last_bh(&path); // Get a bufferhead for last element in path.
- ih = get_ih(&path); // Get a pointer to last item head in path.
- item = get_item(&path); // Get a pointer to last item in path
-
- /* Let's see what we have found */
- if (res != POSITION_FOUND) { /* position not found, this means that we
- might need to append file with holes
- first */
- // Since we are writing past the file's end, we need to find out if
- // there is a hole that needs to be inserted before our writing
- // position, and how many blocks it is going to cover (we need to
- // populate pointers to file blocks representing the hole with zeros)
-
- {
- int item_offset = 1;
- /*
- * if ih is stat data, its offset is 0 and we don't want to
- * add 1 to pos in the hole_size calculation
- */
- if (is_statdata_le_ih(ih))
- item_offset = 0;
- hole_size = (pos + item_offset -
- (le_key_k_offset
- (get_inode_item_key_version(inode),
- &(ih->ih_key)) + op_bytes_number(ih,
- inode->
- i_sb->
- s_blocksize)))
- >> inode->i_sb->s_blocksize_bits;
- }
-
- if (hole_size > 0) {
- int to_paste = min_t(__u64, hole_size, MAX_ITEM_LEN(inode->i_sb->s_blocksize) / UNFM_P_SIZE); // How much data to insert first time.
- /* area filled with zeroes, to supply as list of zero blocknumbers
- We allocate it outside of loop just in case loop would spin for
- several iterations. */
- char *zeros = kzalloc(to_paste * UNFM_P_SIZE, GFP_ATOMIC); // We cannot insert more than MAX_ITEM_LEN bytes anyway.
- if (!zeros) {
- res = -ENOMEM;
- goto error_exit_free_blocks;
- }
- do {
- to_paste =
- min_t(__u64, hole_size,
- MAX_ITEM_LEN(inode->i_sb->
- s_blocksize) /
- UNFM_P_SIZE);
- if (is_indirect_le_ih(ih)) {
- /* Ok, there is existing indirect item already. Need to append it */
- /* Calculate position past inserted item */
- make_cpu_key(&key, inode,
- le_key_k_offset
- (get_inode_item_key_version
- (inode),
- &(ih->ih_key)) +
- op_bytes_number(ih,
- inode->
- i_sb->
- s_blocksize),
- TYPE_INDIRECT, 3);
- res =
- reiserfs_paste_into_item(th, &path,
- &key,
- inode,
- (char *)
- zeros,
- UNFM_P_SIZE
- *
- to_paste);
- if (res) {
- kfree(zeros);
- goto error_exit_free_blocks;
- }
- } else if (is_statdata_le_ih(ih)) {
- /* No existing item, create it */
- /* item head for new item */
- struct item_head ins_ih;
-
- /* create a key for our new item */
- make_cpu_key(&key, inode, 1,
- TYPE_INDIRECT, 3);
-
- /* Create new item head for our new item */
- make_le_item_head(&ins_ih, &key,
- key.version, 1,
- TYPE_INDIRECT,
- to_paste *
- UNFM_P_SIZE,
- 0 /* free space */ );
-
- /* Find where such item should live in the tree */
- res =
- search_item(inode->i_sb, &key,
- &path);
- if (res != ITEM_NOT_FOUND) {
- /* item should not exist, otherwise we have error */
- if (res != -ENOSPC) {
- reiserfs_warning(inode->
- i_sb,
- "green-9008: search_by_key (%K) returned %d",
- &key,
- res);
- }
- res = -EIO;
- kfree(zeros);
- goto error_exit_free_blocks;
- }
- res =
- reiserfs_insert_item(th, &path,
- &key, &ins_ih,
- inode,
- (char *)zeros);
- } else {
- reiserfs_panic(inode->i_sb,
- "green-9011: Unexpected key type %K\n",
- &key);
- }
- if (res) {
- kfree(zeros);
- goto error_exit_free_blocks;
- }
- /* Now we want to check if transaction is too full, and if it is
- we restart it. This will also free the path. */
- if (journal_transaction_should_end
- (th, th->t_blocks_allocated)) {
- inode->i_size = cpu_key_k_offset(&key) +
- (to_paste << inode->i_blkbits);
- res =
- restart_transaction(th, inode,
- &path);
- if (res) {
- pathrelse(&path);
- kfree(zeros);
- goto error_exit;
- }
- }
-
- /* Well, need to recalculate path and stuff */
- set_cpu_key_k_offset(&key,
- cpu_key_k_offset(&key) +
- (to_paste << inode->
- i_blkbits));
- res =
- search_for_position_by_key(inode->i_sb,
- &key, &path);
- if (res == IO_ERROR) {
- res = -EIO;
- kfree(zeros);
- goto error_exit_free_blocks;
- }
- bh = get_last_bh(&path);
- ih = get_ih(&path);
- item = get_item(&path);
- hole_size -= to_paste;
- } while (hole_size);
- kfree(zeros);
- }
- }
- // Go through existing indirect items first
- // replace all zeroes with blocknumbers from list
- // Note that if no corresponding item was found, by previous search,
- // it means there are no existing in-tree representation for file area
- // we are going to overwrite, so there is nothing to scan through for holes.
- for (curr_block = 0, itempos = path.pos_in_item;
- curr_block < blocks_to_allocate && res == POSITION_FOUND;) {
- retry:
-
- if (itempos >= ih_item_len(ih) / UNFM_P_SIZE) {
- /* We run out of data in this indirect item, let's look for another
- one. */
- /* First if we are already modifying current item, log it */
- if (modifying_this_item) {
- journal_mark_dirty(th, inode->i_sb, bh);
- modifying_this_item = 0;
- }
- /* Then set the key to look for a new indirect item (offset of old
- item is added to old item length */
- set_cpu_key_k_offset(&key,
- le_key_k_offset
- (get_inode_item_key_version(inode),
- &(ih->ih_key)) +
- op_bytes_number(ih,
- inode->i_sb->
- s_blocksize));
- /* Search ofor position of new key in the tree. */
- res =
- search_for_position_by_key(inode->i_sb, &key,
- &path);
- if (res == IO_ERROR) {
- res = -EIO;
- goto error_exit_free_blocks;
- }
- bh = get_last_bh(&path);
- ih = get_ih(&path);
- item = get_item(&path);
- itempos = path.pos_in_item;
- continue; // loop to check all kinds of conditions and so on.
- }
- /* Ok, we have correct position in item now, so let's see if it is
- representing file hole (blocknumber is zero) and fill it if needed */
- if (!item[itempos]) {
- /* Ok, a hole. Now we need to check if we already prepared this
- block to be journaled */
- while (!modifying_this_item) { // loop until succeed
- /* Well, this item is not journaled yet, so we must prepare
- it for journal first, before we can change it */
- struct item_head tmp_ih; // We copy item head of found item,
- // here to detect if fs changed under
- // us while we were preparing for
- // journal.
- int fs_gen; // We store fs generation here to find if someone
- // changes fs under our feet
-
- copy_item_head(&tmp_ih, ih); // Remember itemhead
- fs_gen = get_generation(inode->i_sb); // remember fs generation
- reiserfs_prepare_for_journal(inode->i_sb, bh, 1); // Prepare a buffer within which indirect item is stored for changing.
- if (fs_changed(fs_gen, inode->i_sb)
- && item_moved(&tmp_ih, &path)) {
- // Sigh, fs was changed under us, we need to look for new
- // location of item we are working with
-
- /* unmark prepaerd area as journaled and search for it's
- new position */
- reiserfs_restore_prepared_buffer(inode->
- i_sb,
- bh);
- res =
- search_for_position_by_key(inode->
- i_sb,
- &key,
- &path);
- if (res == IO_ERROR) {
- res = -EIO;
- goto error_exit_free_blocks;
- }
- bh = get_last_bh(&path);
- ih = get_ih(&path);
- item = get_item(&path);
- itempos = path.pos_in_item;
- goto retry;
- }
- modifying_this_item = 1;
- }
- item[itempos] = allocated_blocks[curr_block]; // Assign new block
- curr_block++;
- }
- itempos++;
- }
-
- if (modifying_this_item) { // We need to log last-accessed block, if it
- // was modified, but not logged yet.
- journal_mark_dirty(th, inode->i_sb, bh);
- }
-
- if (curr_block < blocks_to_allocate) {
- // Oh, well need to append to indirect item, or to create indirect item
- // if there weren't any
- if (is_indirect_le_ih(ih)) {
- // Existing indirect item - append. First calculate key for append
- // position. We do not need to recalculate path as it should
- // already point to correct place.
- make_cpu_key(&key, inode,
- le_key_k_offset(get_inode_item_key_version
- (inode),
- &(ih->ih_key)) +
- op_bytes_number(ih,
- inode->i_sb->s_blocksize),
- TYPE_INDIRECT, 3);
- res =
- reiserfs_paste_into_item(th, &path, &key, inode,
- (char *)(allocated_blocks +
- curr_block),
- UNFM_P_SIZE *
- (blocks_to_allocate -
- curr_block));
- if (res) {
- goto error_exit_free_blocks;
- }
- } else if (is_statdata_le_ih(ih)) {
- // Last found item was statdata. That means we need to create indirect item.
- struct item_head ins_ih; /* itemhead for new item */
-
- /* create a key for our new item */
- make_cpu_key(&key, inode, 1, TYPE_INDIRECT, 3); // Position one,
- // because that's
- // where first
- // indirect item
- // begins
- /* Create new item head for our new item */
- make_le_item_head(&ins_ih, &key, key.version, 1,
- TYPE_INDIRECT,
- (blocks_to_allocate -
- curr_block) * UNFM_P_SIZE,
- 0 /* free space */ );
- /* Find where such item should live in the tree */
- res = search_item(inode->i_sb, &key, &path);
- if (res != ITEM_NOT_FOUND) {
- /* Well, if we have found such item already, or some error
- occured, we need to warn user and return error */
- if (res != -ENOSPC) {
- reiserfs_warning(inode->i_sb,
- "green-9009: search_by_key (%K) "
- "returned %d", &key,
- res);
- }
- res = -EIO;
- goto error_exit_free_blocks;
- }
- /* Insert item into the tree with the data as its body */
- res =
- reiserfs_insert_item(th, &path, &key, &ins_ih,
- inode,
- (char *)(allocated_blocks +
- curr_block));
- } else {
- reiserfs_panic(inode->i_sb,
- "green-9010: unexpected item type for key %K\n",
- &key);
- }
- }
- // the caller is responsible for closing the transaction
- // unless we return an error, they are also responsible for logging
- // the inode.
- //
- pathrelse(&path);
- /*
- * cleanup prellocation from previous writes
- * if this is a partial block write
- */
- if (write_bytes & (inode->i_sb->s_blocksize - 1))
- reiserfs_discard_prealloc(th, inode);
- reiserfs_write_unlock(inode->i_sb);
-
- // go through all the pages/buffers and map the buffers to newly allocated
- // blocks (so that system knows where to write these pages later).
- curr_block = 0;
- for (i = 0; i < num_pages; i++) {
- struct page *page = prepared_pages[i]; //current page
- struct buffer_head *head = page_buffers(page); // first buffer for a page
- int block_start, block_end; // in-page offsets for buffers.
-
- if (!page_buffers(page))
- reiserfs_panic(inode->i_sb,
- "green-9005: No buffers for prepared page???");
-
- /* For each buffer in page */
- for (bh = head, block_start = 0; bh != head || !block_start;
- block_start = block_end, bh = bh->b_this_page) {
- if (!bh)
- reiserfs_panic(inode->i_sb,
- "green-9006: Allocated but absent buffer for a page?");
- block_end = block_start + inode->i_sb->s_blocksize;
- if (i == 0 && block_end <= from)
- /* if this buffer is before requested data to map, skip it */
- continue;
- if (i == num_pages - 1 && block_start >= to)
- /* If this buffer is after requested data to map, abort
- processing of current page */
- break;
-
- if (!buffer_mapped(bh)) { // Ok, unmapped buffer, need to map it
- map_bh(bh, inode->i_sb,
- le32_to_cpu(allocated_blocks
- [curr_block]));
- curr_block++;
- set_buffer_new(bh);
- }
- }
- }
-
- RFALSE(curr_block > blocks_to_allocate,
- "green-9007: Used too many blocks? weird");
-
- kfree(allocated_blocks);
- return 0;
-
-// Need to deal with transaction here.
- error_exit_free_blocks:
- pathrelse(&path);
- // free blocks
- for (i = 0; i < blocks_to_allocate; i++)
- reiserfs_free_block(th, inode, le32_to_cpu(allocated_blocks[i]),
- 1);
-
- error_exit:
- if (th->t_trans_id) {
- int err;
- // update any changes we made to blk count
- mark_inode_dirty(inode);
- err =
- journal_end(th, inode->i_sb,
- JOURNAL_PER_BALANCE_CNT * 3 + 1 +
- 2 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb));
- if (err)
- res = err;
- }
- reiserfs_write_unlock(inode->i_sb);
- kfree(allocated_blocks);
-
- return res;
-}
-
-/* Unlock pages prepared by reiserfs_prepare_file_region_for_write */
-static void reiserfs_unprepare_pages(struct page **prepared_pages, /* list of locked pages */
- size_t num_pages /* amount of pages */ )
-{
- int i; // loop counter
-
- for (i = 0; i < num_pages; i++) {
- struct page *page = prepared_pages[i];
-
- try_to_free_buffers(page);
- unlock_page(page);
- page_cache_release(page);
- }
-}
-
-/* This function will copy data from userspace to specified pages within
- supplied byte range */
-static int reiserfs_copy_from_user_to_file_region(loff_t pos, /* In-file position */
- int num_pages, /* Number of pages affected */
- int write_bytes, /* Amount of bytes to write */
- struct page **prepared_pages, /* pointer to
- array to
- prepared pages
- */
- const char __user * buf /* Pointer to user-supplied
- data */
- )
-{
- long page_fault = 0; // status of copy_from_user.
- int i; // loop counter.
- int offset; // offset in page
-
- for (i = 0, offset = (pos & (PAGE_CACHE_SIZE - 1)); i < num_pages;
- i++, offset = 0) {
- size_t count = min_t(size_t, PAGE_CACHE_SIZE - offset, write_bytes); // How much of bytes to write to this page
- struct page *page = prepared_pages[i]; // Current page we process.
-
- fault_in_pages_readable(buf, count);
-
- /* Copy data from userspace to the current page */
- kmap(page);
- page_fault = __copy_from_user(page_address(page) + offset, buf, count); // Copy the data.
- /* Flush processor's dcache for this page */
- flush_dcache_page(page);
- kunmap(page);
- buf += count;
- write_bytes -= count;
-
- if (page_fault)
- break; // Was there a fault? abort.
- }
-
- return page_fault ? -EFAULT : 0;
-}
-
/* taken fs/buffer.c:__block_commit_write */
int reiserfs_commit_page(struct inode *inode, struct page *page,
unsigned from, unsigned to)
@@ -824,432 +222,6 @@ int reiserfs_commit_page(struct inode *inode, struct page *page,
return ret;
}
-/* Submit pages for write. This was separated from actual file copying
- because we might want to allocate block numbers in-between.
- This function assumes that caller will adjust file size to correct value. */
-static int reiserfs_submit_file_region_for_write(struct reiserfs_transaction_handle *th, struct inode *inode, loff_t pos, /* Writing position offset */
- size_t num_pages, /* Number of pages to write */
- size_t write_bytes, /* number of bytes to write */
- struct page **prepared_pages /* list of pages */
- )
-{
- int status; // return status of block_commit_write.
- int retval = 0; // Return value we are going to return.
- int i; // loop counter
- int offset; // Writing offset in page.
- int orig_write_bytes = write_bytes;
- int sd_update = 0;
-
- for (i = 0, offset = (pos & (PAGE_CACHE_SIZE - 1)); i < num_pages;
- i++, offset = 0) {
- int count = min_t(int, PAGE_CACHE_SIZE - offset, write_bytes); // How much of bytes to write to this page
- struct page *page = prepared_pages[i]; // Current page we process.
-
- status =
- reiserfs_commit_page(inode, page, offset, offset + count);
- if (status)
- retval = status; // To not overcomplicate matters We are going to
- // submit all the pages even if there was error.
- // we only remember error status to report it on
- // exit.
- write_bytes -= count;
- }
- /* now that we've gotten all the ordered buffers marked dirty,
- * we can safely update i_size and close any running transaction
- */
- if (pos + orig_write_bytes > inode->i_size) {
- inode->i_size = pos + orig_write_bytes; // Set new size
- /* If the file have grown so much that tail packing is no
- * longer possible, reset "need to pack" flag */
- if ((have_large_tails(inode->i_sb) &&
- inode->i_size > i_block_size(inode) * 4) ||
- (have_small_tails(inode->i_sb) &&
- inode->i_size > i_block_size(inode)))
- REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask;
- else if ((have_large_tails(inode->i_sb) &&
- inode->i_size < i_block_size(inode) * 4) ||
- (have_small_tails(inode->i_sb) &&
- inode->i_size < i_block_size(inode)))
- REISERFS_I(inode)->i_flags |= i_pack_on_close_mask;
-
- if (th->t_trans_id) {
- reiserfs_write_lock(inode->i_sb);
- // this sets the proper flags for O_SYNC to trigger a commit
- mark_inode_dirty(inode);
- reiserfs_write_unlock(inode->i_sb);
- } else {
- reiserfs_write_lock(inode->i_sb);
- reiserfs_update_inode_transaction(inode);
- mark_inode_dirty(inode);
- reiserfs_write_unlock(inode->i_sb);
- }
-
- sd_update = 1;
- }
- if (th->t_trans_id) {
- reiserfs_write_lock(inode->i_sb);
- if (!sd_update)
- mark_inode_dirty(inode);
- status = journal_end(th, th->t_super, th->t_blocks_allocated);
- if (status)
- retval = status;
- reiserfs_write_unlock(inode->i_sb);
- }
- th->t_trans_id = 0;
-
- /*
- * we have to unlock the pages after updating i_size, otherwise
- * we race with writepage
- */
- for (i = 0; i < num_pages; i++) {
- struct page *page = prepared_pages[i];
- unlock_page(page);
- mark_page_accessed(page);
- page_cache_release(page);
- }
- return retval;
-}
-
-/* Look if passed writing region is going to touch file's tail
- (if it is present). And if it is, convert the tail to unformatted node */
-static int reiserfs_check_for_tail_and_convert(struct inode *inode, /* inode to deal with */
- loff_t pos, /* Writing position */
- int write_bytes /* amount of bytes to write */
- )
-{
- INITIALIZE_PATH(path); // needed for search_for_position
- struct cpu_key key; // Key that would represent last touched writing byte.
- struct item_head *ih; // item header of found block;
- int res; // Return value of various functions we call.
- int cont_expand_offset; // We will put offset for generic_cont_expand here
- // This can be int just because tails are created
- // only for small files.
-
-/* this embodies a dependency on a particular tail policy */
- if (inode->i_size >= inode->i_sb->s_blocksize * 4) {
- /* such a big files do not have tails, so we won't bother ourselves
- to look for tails, simply return */
- return 0;
- }
-
- reiserfs_write_lock(inode->i_sb);
- /* find the item containing the last byte to be written, or if
- * writing past the end of the file then the last item of the
- * file (and then we check its type). */
- make_cpu_key(&key, inode, pos + write_bytes + 1, TYPE_ANY,
- 3 /*key length */ );
- res = search_for_position_by_key(inode->i_sb, &key, &path);
- if (res == IO_ERROR) {
- reiserfs_write_unlock(inode->i_sb);
- return -EIO;
- }
- ih = get_ih(&path);
- res = 0;
- if (is_direct_le_ih(ih)) {
- /* Ok, closest item is file tail (tails are stored in "direct"
- * items), so we need to unpack it. */
- /* To not overcomplicate matters, we just call generic_cont_expand
- which will in turn call other stuff and finally will boil down to
- reiserfs_get_block() that would do necessary conversion. */
- cont_expand_offset =
- le_key_k_offset(get_inode_item_key_version(inode),
- &(ih->ih_key));
- pathrelse(&path);
- res = generic_cont_expand(inode, cont_expand_offset);
- } else
- pathrelse(&path);
-
- reiserfs_write_unlock(inode->i_sb);
- return res;
-}
-
-/* This function locks pages starting from @pos for @inode.
- @num_pages pages are locked and stored in
- @prepared_pages array. Also buffers are allocated for these pages.
- First and last page of the region is read if it is overwritten only
- partially. If last page did not exist before write (file hole or file
- append), it is zeroed, then.
- Returns number of unallocated blocks that should be allocated to cover
- new file data.*/
-static int reiserfs_prepare_file_region_for_write(struct inode *inode
- /* Inode of the file */ ,
- loff_t pos, /* position in the file */
- size_t num_pages, /* number of pages to
- prepare */
- size_t write_bytes, /* Amount of bytes to be
- overwritten from
- @pos */
- struct page **prepared_pages /* pointer to array
- where to store
- prepared pages */
- )
-{
- int res = 0; // Return values of different functions we call.
- unsigned long index = pos >> PAGE_CACHE_SHIFT; // Offset in file in pages.
- int from = (pos & (PAGE_CACHE_SIZE - 1)); // Writing offset in first page
- int to = ((pos + write_bytes - 1) & (PAGE_CACHE_SIZE - 1)) + 1;
- /* offset of last modified byte in last
- page */
- struct address_space *mapping = inode->i_mapping; // Pages are mapped here.
- int i; // Simple counter
- int blocks = 0; /* Return value (blocks that should be allocated) */
- struct buffer_head *bh, *head; // Current bufferhead and first bufferhead
- // of a page.
- unsigned block_start, block_end; // Starting and ending offsets of current
- // buffer in the page.
- struct buffer_head *wait[2], **wait_bh = wait; // Buffers for page, if
- // Page appeared to be not up
- // to date. Note how we have
- // at most 2 buffers, this is
- // because we at most may
- // partially overwrite two
- // buffers for one page. One at // the beginning of write area
- // and one at the end.
- // Everything inthe middle gets // overwritten totally.
-
- struct cpu_key key; // cpu key of item that we are going to deal with
- struct item_head *ih = NULL; // pointer to item head that we are going to deal with
- struct buffer_head *itembuf = NULL; // Buffer head that contains items that we are going to deal with
- INITIALIZE_PATH(path); // path to item, that we are going to deal with.
- __le32 *item = NULL; // pointer to item we are going to deal with
- int item_pos = -1; /* Position in indirect item */
-
- if (num_pages < 1) {
- reiserfs_warning(inode->i_sb,
- "green-9001: reiserfs_prepare_file_region_for_write "
- "called with zero number of pages to process");
- return -EFAULT;
- }
-
- /* We have 2 loops for pages. In first loop we grab and lock the pages, so
- that nobody would touch these until we release the pages. Then
- we'd start to deal with mapping buffers to blocks. */
- for (i = 0; i < num_pages; i++) {
- prepared_pages[i] = grab_cache_page(mapping, index + i); // locks the page
- if (!prepared_pages[i]) {
- res = -ENOMEM;
- goto failed_page_grabbing;
- }
- if (!page_has_buffers(prepared_pages[i]))
- create_empty_buffers(prepared_pages[i],
- inode->i_sb->s_blocksize, 0);
- }
-
- /* Let's count amount of blocks for a case where all the blocks
- overwritten are new (we will substract already allocated blocks later) */
- if (num_pages > 2)
- /* These are full-overwritten pages so we count all the blocks in
- these pages are counted as needed to be allocated */
- blocks =
- (num_pages - 2) << (PAGE_CACHE_SHIFT - inode->i_blkbits);
-
- /* count blocks needed for first page (possibly partially written) */
- blocks += ((PAGE_CACHE_SIZE - from) >> inode->i_blkbits) + !!(from & (inode->i_sb->s_blocksize - 1)); /* roundup */
-
- /* Now we account for last page. If last page == first page (we
- overwrite only one page), we substract all the blocks past the
- last writing position in a page out of already calculated number
- of blocks */
- blocks += ((num_pages > 1) << (PAGE_CACHE_SHIFT - inode->i_blkbits)) -
- ((PAGE_CACHE_SIZE - to) >> inode->i_blkbits);
- /* Note how we do not roundup here since partial blocks still
- should be allocated */
-
- /* Now if all the write area lies past the file end, no point in
- maping blocks, since there is none, so we just zero out remaining
- parts of first and last pages in write area (if needed) */
- if ((pos & ~((loff_t) PAGE_CACHE_SIZE - 1)) > inode->i_size) {
- if (from != 0) /* First page needs to be partially zeroed */
- zero_user_page(prepared_pages[0], 0, from, KM_USER0);
-
- if (to != PAGE_CACHE_SIZE) /* Last page needs to be partially zeroed */
- zero_user_page(prepared_pages[num_pages-1], to,
- PAGE_CACHE_SIZE - to, KM_USER0);
-
- /* Since all blocks are new - use already calculated value */
- return blocks;
- }
-
- /* Well, since we write somewhere into the middle of a file, there is
- possibility we are writing over some already allocated blocks, so
- let's map these blocks and substract number of such blocks out of blocks
- we need to allocate (calculated above) */
- /* Mask write position to start on blocksize, we do it out of the
- loop for performance reasons */
- pos &= ~((loff_t) inode->i_sb->s_blocksize - 1);
- /* Set cpu key to the starting position in a file (on left block boundary) */
- make_cpu_key(&key, inode,
- 1 + ((pos) & ~((loff_t) inode->i_sb->s_blocksize - 1)),
- TYPE_ANY, 3 /*key length */ );
-
- reiserfs_write_lock(inode->i_sb); // We need that for at least search_by_key()
- for (i = 0; i < num_pages; i++) {
-
- head = page_buffers(prepared_pages[i]);
- /* For each buffer in the page */
- for (bh = head, block_start = 0; bh != head || !block_start;
- block_start = block_end, bh = bh->b_this_page) {
- if (!bh)
- reiserfs_panic(inode->i_sb,
- "green-9002: Allocated but absent buffer for a page?");
- /* Find where this buffer ends */
- block_end = block_start + inode->i_sb->s_blocksize;
- if (i == 0 && block_end <= from)
- /* if this buffer is before requested data to map, skip it */
- continue;
-
- if (i == num_pages - 1 && block_start >= to) {
- /* If this buffer is after requested data to map, abort
- processing of current page */
- break;
- }
-
- if (buffer_mapped(bh) && bh->b_blocknr != 0) {
- /* This is optimisation for a case where buffer is mapped
- and have blocknumber assigned. In case significant amount
- of such buffers are present, we may avoid some amount
- of search_by_key calls.
- Probably it would be possible to move parts of this code
- out of BKL, but I afraid that would overcomplicate code
- without any noticeable benefit.
- */
- item_pos++;
- /* Update the key */
- set_cpu_key_k_offset(&key,
- cpu_key_k_offset(&key) +
- inode->i_sb->s_blocksize);
- blocks--; // Decrease the amount of blocks that need to be
- // allocated
- continue; // Go to the next buffer
- }
-
- if (!itembuf || /* if first iteration */
- item_pos >= ih_item_len(ih) / UNFM_P_SIZE) { /* or if we progressed past the
- current unformatted_item */
- /* Try to find next item */
- res =
- search_for_position_by_key(inode->i_sb,
- &key, &path);
- /* Abort if no more items */
- if (res != POSITION_FOUND) {
- /* make sure later loops don't use this item */
- itembuf = NULL;
- item = NULL;
- break;
- }
-
- /* Update information about current indirect item */
- itembuf = get_last_bh(&path);
- ih = get_ih(&path);
- item = get_item(&path);
- item_pos = path.pos_in_item;
-
- RFALSE(!is_indirect_le_ih(ih),
- "green-9003: indirect item expected");
- }
-
- /* See if there is some block associated with the file
- at that position, map the buffer to this block */
- if (get_block_num(item, item_pos)) {
- map_bh(bh, inode->i_sb,
- get_block_num(item, item_pos));
- blocks--; // Decrease the amount of blocks that need to be
- // allocated
- }
- item_pos++;
- /* Update the key */
- set_cpu_key_k_offset(&key,
- cpu_key_k_offset(&key) +
- inode->i_sb->s_blocksize);
- }
- }
- pathrelse(&path); // Free the path
- reiserfs_write_unlock(inode->i_sb);
-
- /* Now zero out unmappend buffers for the first and last pages of
- write area or issue read requests if page is mapped. */
- /* First page, see if it is not uptodate */
- if (!PageUptodate(prepared_pages[0])) {
- head = page_buffers(prepared_pages[0]);
-
- /* For each buffer in page */
- for (bh = head, block_start = 0; bh != head || !block_start;
- block_start = block_end, bh = bh->b_this_page) {
-
- if (!bh)
- reiserfs_panic(inode->i_sb,
- "green-9002: Allocated but absent buffer for a page?");
- /* Find where this buffer ends */
- block_end = block_start + inode->i_sb->s_blocksize;
- if (block_end <= from)
- /* if this buffer is before requested data to map, skip it */
- continue;
- if (block_start < from) { /* Aha, our partial buffer */
- if (buffer_mapped(bh)) { /* If it is mapped, we need to
- issue READ request for it to
- not loose data */
- ll_rw_block(READ, 1, &bh);
- *wait_bh++ = bh;
- } else { /* Not mapped, zero it */
- zero_user_page(prepared_pages[0],
- block_start,
- from - block_start, KM_USER0);
- set_buffer_uptodate(bh);
- }
- }
- }
- }
-
- /* Last page, see if it is not uptodate, or if the last page is past the end of the file. */
- if (!PageUptodate(prepared_pages[num_pages - 1]) ||
- ((pos + write_bytes) >> PAGE_CACHE_SHIFT) >
- (inode->i_size >> PAGE_CACHE_SHIFT)) {
- head = page_buffers(prepared_pages[num_pages - 1]);
-
- /* for each buffer in page */
- for (bh = head, block_start = 0; bh != head || !block_start;
- block_start = block_end, bh = bh->b_this_page) {
-
- if (!bh)
- reiserfs_panic(inode->i_sb,
- "green-9002: Allocated but absent buffer for a page?");
- /* Find where this buffer ends */
- block_end = block_start + inode->i_sb->s_blocksize;
- if (block_start >= to)
- /* if this buffer is after requested data to map, skip it */
- break;
- if (block_end > to) { /* Aha, our partial buffer */
- if (buffer_mapped(bh)) { /* If it is mapped, we need to
- issue READ request for it to
- not loose data */
- ll_rw_block(READ, 1, &bh);
- *wait_bh++ = bh;
- } else { /* Not mapped, zero it */
- zero_user_page(prepared_pages[num_pages-1],
- to, block_end - to, KM_USER0);
- set_buffer_uptodate(bh);
- }
- }
- }
- }
-
- /* Wait for read requests we made to happen, if necessary */
- while (wait_bh > wait) {
- wait_on_buffer(*--wait_bh);
- if (!buffer_uptodate(*wait_bh)) {
- res = -EIO;
- goto failed_read;
- }
- }
-
- return blocks;
- failed_page_grabbing:
- num_pages = i;
- failed_read:
- reiserfs_unprepare_pages(prepared_pages, num_pages);
- return res;
-}
-
/* Write @count bytes at position @ppos in a file indicated by @file
from the buffer @buf.
@@ -1284,14 +256,9 @@ static ssize_t reiserfs_file_write(struct file *file, /* the file we are going t
* new current position before returning. */
)
{
- size_t already_written = 0; // Number of bytes already written to the file.
- loff_t pos; // Current position in the file.
- ssize_t res; // return value of various functions that we call.
- int err = 0;
struct inode *inode = file->f_path.dentry->d_inode; // Inode of the file that we are writing to.
/* To simplify coding at this time, we store
locked pages in array for now */
- struct page *prepared_pages[REISERFS_WRITE_PAGES_AT_A_TIME];
struct reiserfs_transaction_handle th;
th.t_trans_id = 0;
@@ -1311,212 +278,7 @@ static ssize_t reiserfs_file_write(struct file *file, /* the file we are going t
count = MAX_NON_LFS - (unsigned long)*ppos;
}
- if (file->f_flags & O_DIRECT)
- return do_sync_write(file, buf, count, ppos);
-
- if (unlikely((ssize_t) count < 0))
- return -EINVAL;
-
- if (unlikely(!access_ok(VERIFY_READ, buf, count)))
- return -EFAULT;
-
- mutex_lock(&inode->i_mutex); // locks the entire file for just us
-
- pos = *ppos;
-
- /* Check if we can write to specified region of file, file
- is not overly big and this kind of stuff. Adjust pos and
- count, if needed */
- res = generic_write_checks(file, &pos, &count, 0);
- if (res)
- goto out;
-
- if (count == 0)
- goto out;
-
- res = remove_suid(file->f_path.dentry);
- if (res)
- goto out;
-
- file_update_time(file);
-
- // Ok, we are done with all the checks.
-
- // Now we should start real work
-
- /* If we are going to write past the file's packed tail or if we are going
- to overwrite part of the tail, we need that tail to be converted into
- unformatted node */
- res = reiserfs_check_for_tail_and_convert(inode, pos, count);
- if (res)
- goto out;
-
- while (count > 0) {
- /* This is the main loop in which we running until some error occures
- or until we write all of the data. */
- size_t num_pages; /* amount of pages we are going to write this iteration */
- size_t write_bytes; /* amount of bytes to write during this iteration */
- size_t blocks_to_allocate; /* how much blocks we need to allocate for this iteration */
-
- /* (pos & (PAGE_CACHE_SIZE-1)) is an idiom for offset into a page of pos */
- num_pages = !!((pos + count) & (PAGE_CACHE_SIZE - 1)) + /* round up partial
- pages */
- ((count +
- (pos & (PAGE_CACHE_SIZE - 1))) >> PAGE_CACHE_SHIFT);
- /* convert size to amount of
- pages */
- reiserfs_write_lock(inode->i_sb);
- if (num_pages > REISERFS_WRITE_PAGES_AT_A_TIME
- || num_pages > reiserfs_can_fit_pages(inode->i_sb)) {
- /* If we were asked to write more data than we want to or if there
- is not that much space, then we shorten amount of data to write
- for this iteration. */
- num_pages =
- min_t(size_t, REISERFS_WRITE_PAGES_AT_A_TIME,
- reiserfs_can_fit_pages(inode->i_sb));
- /* Also we should not forget to set size in bytes accordingly */
- write_bytes = (num_pages << PAGE_CACHE_SHIFT) -
- (pos & (PAGE_CACHE_SIZE - 1));
- /* If position is not on the
- start of the page, we need
- to substract the offset
- within page */
- } else
- write_bytes = count;
-
- /* reserve the blocks to be allocated later, so that later on
- we still have the space to write the blocks to */
- reiserfs_claim_blocks_to_be_allocated(inode->i_sb,
- num_pages <<
- (PAGE_CACHE_SHIFT -
- inode->i_blkbits));
- reiserfs_write_unlock(inode->i_sb);
-
- if (!num_pages) { /* If we do not have enough space even for a single page... */
- if (pos >
- inode->i_size + inode->i_sb->s_blocksize -
- (pos & (inode->i_sb->s_blocksize - 1))) {
- res = -ENOSPC;
- break; // In case we are writing past the end of the last file block, break.
- }
- // Otherwise we are possibly overwriting the file, so
- // let's set write size to be equal or less than blocksize.
- // This way we get it correctly for file holes.
- // But overwriting files on absolutelly full volumes would not
- // be very efficient. Well, people are not supposed to fill
- // 100% of disk space anyway.
- write_bytes =
- min_t(size_t, count,
- inode->i_sb->s_blocksize -
- (pos & (inode->i_sb->s_blocksize - 1)));
- num_pages = 1;
- // No blocks were claimed before, so do it now.
- reiserfs_claim_blocks_to_be_allocated(inode->i_sb,
- 1 <<
- (PAGE_CACHE_SHIFT
- -
- inode->
- i_blkbits));
- }
-
- /* Prepare for writing into the region, read in all the
- partially overwritten pages, if needed. And lock the pages,
- so that nobody else can access these until we are done.
- We get number of actual blocks needed as a result. */
- res = reiserfs_prepare_file_region_for_write(inode, pos,
- num_pages,
- write_bytes,
- prepared_pages);
- if (res < 0) {
- reiserfs_release_claimed_blocks(inode->i_sb,
- num_pages <<
- (PAGE_CACHE_SHIFT -
- inode->i_blkbits));
- break;
- }
-
- blocks_to_allocate = res;
-
- /* First we correct our estimate of how many blocks we need */
- reiserfs_release_claimed_blocks(inode->i_sb,
- (num_pages <<
- (PAGE_CACHE_SHIFT -
- inode->i_sb->
- s_blocksize_bits)) -
- blocks_to_allocate);
-
- if (blocks_to_allocate > 0) { /*We only allocate blocks if we need to */
- /* Fill in all the possible holes and append the file if needed */
- res =
- reiserfs_allocate_blocks_for_region(&th, inode, pos,
- num_pages,
- write_bytes,
- prepared_pages,
- blocks_to_allocate);
- }
-
- /* well, we have allocated the blocks, so it is time to free
- the reservation we made earlier. */
- reiserfs_release_claimed_blocks(inode->i_sb,
- blocks_to_allocate);
- if (res) {
- reiserfs_unprepare_pages(prepared_pages, num_pages);
- break;
- }
-
-/* NOTE that allocating blocks and filling blocks can be done in reverse order
- and probably we would do that just to get rid of garbage in files after a
- crash */
-
- /* Copy data from user-supplied buffer to file's pages */
- res =
- reiserfs_copy_from_user_to_file_region(pos, num_pages,
- write_bytes,
- prepared_pages, buf);
- if (res) {
- reiserfs_unprepare_pages(prepared_pages, num_pages);
- break;
- }
-
- /* Send the pages to disk and unlock them. */
- res =
- reiserfs_submit_file_region_for_write(&th, inode, pos,
- num_pages,
- write_bytes,
- prepared_pages);
- if (res)
- break;
-
- already_written += write_bytes;
- buf += write_bytes;
- *ppos = pos += write_bytes;
- count -= write_bytes;
- balance_dirty_pages_ratelimited_nr(inode->i_mapping, num_pages);
- }
-
- /* this is only true on error */
- if (th.t_trans_id) {
- reiserfs_write_lock(inode->i_sb);
- err = journal_end(&th, th.t_super, th.t_blocks_allocated);
- reiserfs_write_unlock(inode->i_sb);
- if (err) {
- res = err;
- goto out;
- }
- }
-
- if (likely(res >= 0) &&
- (unlikely((file->f_flags & O_SYNC) || IS_SYNC(inode))))
- res = generic_osync_inode(inode, file->f_mapping,
- OSYNC_METADATA | OSYNC_DATA);
-
- mutex_unlock(&inode->i_mutex);
- reiserfs_async_progress_wait(inode->i_sb);
- return (already_written != 0) ? already_written : res;
-
- out:
- mutex_unlock(&inode->i_mutex); // unlock the file on exit.
- return res;
+ return do_sync_write(file, buf, count, ppos);
}
const struct file_operations reiserfs_file_operations = {
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index ddde489f1cb2..231fd5ccadc5 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -17,11 +17,12 @@
#include <linux/mpage.h>
#include <linux/writeback.h>
#include <linux/quotaops.h>
+#include <linux/swap.h>
-static int reiserfs_commit_write(struct file *f, struct page *page,
- unsigned from, unsigned to);
-static int reiserfs_prepare_write(struct file *f, struct page *page,
- unsigned from, unsigned to);
+int reiserfs_commit_write(struct file *f, struct page *page,
+ unsigned from, unsigned to);
+int reiserfs_prepare_write(struct file *f, struct page *page,
+ unsigned from, unsigned to);
void reiserfs_delete_inode(struct inode *inode)
{
@@ -198,7 +199,7 @@ static inline void set_block_dev_mapped(struct buffer_head *bh,
// files which were created in the earlier version can not be longer,
// than 2 gb
//
-static int file_capable(struct inode *inode, long block)
+static int file_capable(struct inode *inode, sector_t block)
{
if (get_inode_item_key_version(inode) != KEY_FORMAT_3_5 || // it is new file.
block < (1 << (31 - inode->i_sb->s_blocksize_bits))) // old file, but 'block' is inside of 2gb
@@ -207,8 +208,8 @@ static int file_capable(struct inode *inode, long block)
return 0;
}
-/*static*/ int restart_transaction(struct reiserfs_transaction_handle *th,
- struct inode *inode, struct treepath *path)
+static int restart_transaction(struct reiserfs_transaction_handle *th,
+ struct inode *inode, struct treepath *path)
{
struct super_block *s = th->t_super;
int len = th->t_blocks_allocated;
@@ -241,7 +242,7 @@ static int file_capable(struct inode *inode, long block)
// Please improve the english/clarity in the comment above, as it is
// hard to understand.
-static int _get_block_create_0(struct inode *inode, long block,
+static int _get_block_create_0(struct inode *inode, sector_t block,
struct buffer_head *bh_result, int args)
{
INITIALIZE_PATH(path);
@@ -249,7 +250,7 @@ static int _get_block_create_0(struct inode *inode, long block,
struct buffer_head *bh;
struct item_head *ih, tmp_ih;
int fs_gen;
- int blocknr;
+ b_blocknr_t blocknr;
char *p = NULL;
int chars;
int ret;
@@ -568,7 +569,7 @@ static int convert_tail_for_hole(struct inode *inode,
}
static inline int _allocate_block(struct reiserfs_transaction_handle *th,
- long block,
+ sector_t block,
struct inode *inode,
b_blocknr_t * allocated_block_nr,
struct treepath *path, int flags)
@@ -1514,19 +1515,20 @@ struct inode *reiserfs_iget(struct super_block *s, const struct cpu_key *key)
return inode;
}
-struct dentry *reiserfs_get_dentry(struct super_block *sb, void *vobjp)
+static struct dentry *reiserfs_get_dentry(struct super_block *sb,
+ u32 objectid, u32 dir_id, u32 generation)
+
{
- __u32 *data = vobjp;
struct cpu_key key;
struct dentry *result;
struct inode *inode;
- key.on_disk_key.k_objectid = data[0];
- key.on_disk_key.k_dir_id = data[1];
+ key.on_disk_key.k_objectid = objectid;
+ key.on_disk_key.k_dir_id = dir_id;
reiserfs_write_lock(sb);
inode = reiserfs_iget(sb, &key);
- if (inode && !IS_ERR(inode) && data[2] != 0 &&
- data[2] != inode->i_generation) {
+ if (inode && !IS_ERR(inode) && generation != 0 &&
+ generation != inode->i_generation) {
iput(inode);
inode = NULL;
}
@@ -1543,14 +1545,9 @@ struct dentry *reiserfs_get_dentry(struct super_block *sb, void *vobjp)
return result;
}
-struct dentry *reiserfs_decode_fh(struct super_block *sb, __u32 * data,
- int len, int fhtype,
- int (*acceptable) (void *contect,
- struct dentry * de),
- void *context)
+struct dentry *reiserfs_fh_to_dentry(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type)
{
- __u32 obj[3], parent[3];
-
/* fhtype happens to reflect the number of u32s encoded.
* due to a bug in earlier code, fhtype might indicate there
* are more u32s then actually fitted.
@@ -1563,32 +1560,28 @@ struct dentry *reiserfs_decode_fh(struct super_block *sb, __u32 * data,
* 6 - as above plus generation of directory
* 6 does not fit in NFSv2 handles
*/
- if (fhtype > len) {
- if (fhtype != 6 || len != 5)
+ if (fh_type > fh_len) {
+ if (fh_type != 6 || fh_len != 5)
reiserfs_warning(sb,
- "nfsd/reiserfs, fhtype=%d, len=%d - odd",
- fhtype, len);
- fhtype = 5;
+ "nfsd/reiserfs, fhtype=%d, len=%d - odd",
+ fh_type, fh_len);
+ fh_type = 5;
}
- obj[0] = data[0];
- obj[1] = data[1];
- if (fhtype == 3 || fhtype >= 5)
- obj[2] = data[2];
- else
- obj[2] = 0; /* generation number */
+ return reiserfs_get_dentry(sb, fid->raw[0], fid->raw[1],
+ (fh_type == 3 || fh_type >= 5) ? fid->raw[2] : 0);
+}
- if (fhtype >= 4) {
- parent[0] = data[fhtype >= 5 ? 3 : 2];
- parent[1] = data[fhtype >= 5 ? 4 : 3];
- if (fhtype == 6)
- parent[2] = data[5];
- else
- parent[2] = 0;
- }
- return sb->s_export_op->find_exported_dentry(sb, obj,
- fhtype < 4 ? NULL : parent,
- acceptable, context);
+struct dentry *reiserfs_fh_to_parent(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type)
+{
+ if (fh_type < 4)
+ return NULL;
+
+ return reiserfs_get_dentry(sb,
+ (fh_type >= 5) ? fid->raw[3] : fid->raw[2],
+ (fh_type >= 5) ? fid->raw[4] : fid->raw[3],
+ (fh_type == 6) ? fid->raw[5] : 0);
}
int reiserfs_encode_fh(struct dentry *dentry, __u32 * data, int *lenp,
@@ -2550,8 +2543,78 @@ static int reiserfs_writepage(struct page *page, struct writeback_control *wbc)
return reiserfs_write_full_page(page, wbc);
}
-static int reiserfs_prepare_write(struct file *f, struct page *page,
- unsigned from, unsigned to)
+static int reiserfs_write_begin(struct file *file,
+ struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
+{
+ struct inode *inode;
+ struct page *page;
+ pgoff_t index;
+ int ret;
+ int old_ref = 0;
+
+ inode = mapping->host;
+ *fsdata = 0;
+ if (flags & AOP_FLAG_CONT_EXPAND &&
+ (pos & (inode->i_sb->s_blocksize - 1)) == 0) {
+ pos ++;
+ *fsdata = (void *)(unsigned long)flags;
+ }
+
+ index = pos >> PAGE_CACHE_SHIFT;
+ page = __grab_cache_page(mapping, index);
+ if (!page)
+ return -ENOMEM;
+ *pagep = page;
+
+ reiserfs_wait_on_write_block(inode->i_sb);
+ fix_tail_page_for_writing(page);
+ if (reiserfs_transaction_running(inode->i_sb)) {
+ struct reiserfs_transaction_handle *th;
+ th = (struct reiserfs_transaction_handle *)current->
+ journal_info;
+ BUG_ON(!th->t_refcount);
+ BUG_ON(!th->t_trans_id);
+ old_ref = th->t_refcount;
+ th->t_refcount++;
+ }
+ ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
+ reiserfs_get_block);
+ if (ret && reiserfs_transaction_running(inode->i_sb)) {
+ struct reiserfs_transaction_handle *th = current->journal_info;
+ /* this gets a little ugly. If reiserfs_get_block returned an
+ * error and left a transacstion running, we've got to close it,
+ * and we've got to free handle if it was a persistent transaction.
+ *
+ * But, if we had nested into an existing transaction, we need
+ * to just drop the ref count on the handle.
+ *
+ * If old_ref == 0, the transaction is from reiserfs_get_block,
+ * and it was a persistent trans. Otherwise, it was nested above.
+ */
+ if (th->t_refcount > old_ref) {
+ if (old_ref)
+ th->t_refcount--;
+ else {
+ int err;
+ reiserfs_write_lock(inode->i_sb);
+ err = reiserfs_end_persistent_transaction(th);
+ reiserfs_write_unlock(inode->i_sb);
+ if (err)
+ ret = err;
+ }
+ }
+ }
+ if (ret) {
+ unlock_page(page);
+ page_cache_release(page);
+ }
+ return ret;
+}
+
+int reiserfs_prepare_write(struct file *f, struct page *page,
+ unsigned from, unsigned to)
{
struct inode *inode = page->mapping->host;
int ret;
@@ -2604,8 +2667,102 @@ static sector_t reiserfs_aop_bmap(struct address_space *as, sector_t block)
return generic_block_bmap(as, block, reiserfs_bmap);
}
-static int reiserfs_commit_write(struct file *f, struct page *page,
- unsigned from, unsigned to)
+static int reiserfs_write_end(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata)
+{
+ struct inode *inode = page->mapping->host;
+ int ret = 0;
+ int update_sd = 0;
+ struct reiserfs_transaction_handle *th;
+ unsigned start;
+
+ if ((unsigned long)fsdata & AOP_FLAG_CONT_EXPAND)
+ pos ++;
+
+ reiserfs_wait_on_write_block(inode->i_sb);
+ if (reiserfs_transaction_running(inode->i_sb))
+ th = current->journal_info;
+ else
+ th = NULL;
+
+ start = pos & (PAGE_CACHE_SIZE - 1);
+ if (unlikely(copied < len)) {
+ if (!PageUptodate(page))
+ copied = 0;
+
+ page_zero_new_buffers(page, start + copied, start + len);
+ }
+ flush_dcache_page(page);
+
+ reiserfs_commit_page(inode, page, start, start + copied);
+
+ /* generic_commit_write does this for us, but does not update the
+ ** transaction tracking stuff when the size changes. So, we have
+ ** to do the i_size updates here.
+ */
+ pos += copied;
+ if (pos > inode->i_size) {
+ struct reiserfs_transaction_handle myth;
+ reiserfs_write_lock(inode->i_sb);
+ /* If the file have grown beyond the border where it
+ can have a tail, unmark it as needing a tail
+ packing */
+ if ((have_large_tails(inode->i_sb)
+ && inode->i_size > i_block_size(inode) * 4)
+ || (have_small_tails(inode->i_sb)
+ && inode->i_size > i_block_size(inode)))
+ REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask;
+
+ ret = journal_begin(&myth, inode->i_sb, 1);
+ if (ret) {
+ reiserfs_write_unlock(inode->i_sb);
+ goto journal_error;
+ }
+ reiserfs_update_inode_transaction(inode);
+ inode->i_size = pos;
+ /*
+ * this will just nest into our transaction. It's important
+ * to use mark_inode_dirty so the inode gets pushed around on the
+ * dirty lists, and so that O_SYNC works as expected
+ */
+ mark_inode_dirty(inode);
+ reiserfs_update_sd(&myth, inode);
+ update_sd = 1;
+ ret = journal_end(&myth, inode->i_sb, 1);
+ reiserfs_write_unlock(inode->i_sb);
+ if (ret)
+ goto journal_error;
+ }
+ if (th) {
+ reiserfs_write_lock(inode->i_sb);
+ if (!update_sd)
+ mark_inode_dirty(inode);
+ ret = reiserfs_end_persistent_transaction(th);
+ reiserfs_write_unlock(inode->i_sb);
+ if (ret)
+ goto out;
+ }
+
+ out:
+ unlock_page(page);
+ page_cache_release(page);
+ return ret == 0 ? copied : ret;
+
+ journal_error:
+ if (th) {
+ reiserfs_write_lock(inode->i_sb);
+ if (!update_sd)
+ reiserfs_update_sd(th, inode);
+ ret = reiserfs_end_persistent_transaction(th);
+ reiserfs_write_unlock(inode->i_sb);
+ }
+
+ goto out;
+}
+
+int reiserfs_commit_write(struct file *f, struct page *page,
+ unsigned from, unsigned to)
{
struct inode *inode = page->mapping->host;
loff_t pos = ((loff_t) page->index << PAGE_CACHE_SHIFT) + to;
@@ -2896,7 +3053,11 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
{
struct inode *inode = dentry->d_inode;
int error;
- unsigned int ia_valid = attr->ia_valid;
+ unsigned int ia_valid;
+
+ /* must be turned off for recursive notify_change calls */
+ ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID);
+
reiserfs_write_lock(inode->i_sb);
if (attr->ia_valid & ATTR_SIZE) {
/* version 2 items will be caught by the s_maxbytes check
@@ -2909,7 +3070,7 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
}
/* fill in hole pointers in the expanding truncate case. */
if (attr->ia_size > inode->i_size) {
- error = generic_cont_expand(inode, attr->ia_size);
+ error = generic_cont_expand_simple(inode, attr->ia_size);
if (REISERFS_I(inode)->i_prealloc_count > 0) {
int err;
struct reiserfs_transaction_handle th;
@@ -2999,8 +3160,8 @@ const struct address_space_operations reiserfs_address_space_operations = {
.releasepage = reiserfs_releasepage,
.invalidatepage = reiserfs_invalidatepage,
.sync_page = block_sync_page,
- .prepare_write = reiserfs_prepare_write,
- .commit_write = reiserfs_commit_write,
+ .write_begin = reiserfs_write_begin,
+ .write_end = reiserfs_write_end,
.bmap = reiserfs_aop_bmap,
.direct_IO = reiserfs_direct_IO,
.set_page_dirty = reiserfs_set_page_dirty,
diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c
index 11a0fcc2d402..e0f0f098a523 100644
--- a/fs/reiserfs/ioctl.c
+++ b/fs/reiserfs/ioctl.c
@@ -57,6 +57,9 @@ int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
if (get_user(flags, (int __user *)arg))
return -EFAULT;
+ /* Is it quota file? Do not allow user to mess with it. */
+ if (IS_NOQUOTA(inode))
+ return -EPERM;
if (((flags ^ REISERFS_I(inode)->
i_attrs) & (REISERFS_IMMUTABLE_FL |
REISERFS_APPEND_FL))
@@ -128,6 +131,10 @@ long reiserfs_compat_ioctl(struct file *file, unsigned int cmd,
}
#endif
+int reiserfs_commit_write(struct file *f, struct page *page,
+ unsigned from, unsigned to);
+int reiserfs_prepare_write(struct file *f, struct page *page,
+ unsigned from, unsigned to);
/*
** reiserfs_unpack
** Function try to convert tail from direct item into indirect.
@@ -175,15 +182,13 @@ static int reiserfs_unpack(struct inode *inode, struct file *filp)
if (!page) {
goto out;
}
- retval =
- mapping->a_ops->prepare_write(NULL, page, write_from, write_from);
+ retval = reiserfs_prepare_write(NULL, page, write_from, write_from);
if (retval)
goto out_unlock;
/* conversion can change page contents, must flush */
flush_dcache_page(page);
- retval =
- mapping->a_ops->commit_write(NULL, page, write_from, write_from);
+ retval = reiserfs_commit_write(NULL, page, write_from, write_from);
REISERFS_I(inode)->i_flags |= i_nopack_mask;
out_unlock:
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index f25086aeef5f..bb05a3e51b93 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -219,11 +219,12 @@ static void allocate_bitmap_nodes(struct super_block *p_s_sb)
}
}
-static int set_bit_in_list_bitmap(struct super_block *p_s_sb, int block,
+static int set_bit_in_list_bitmap(struct super_block *p_s_sb,
+ b_blocknr_t block,
struct reiserfs_list_bitmap *jb)
{
- int bmap_nr = block / (p_s_sb->s_blocksize << 3);
- int bit_nr = block % (p_s_sb->s_blocksize << 3);
+ unsigned int bmap_nr = block / (p_s_sb->s_blocksize << 3);
+ unsigned int bit_nr = block % (p_s_sb->s_blocksize << 3);
if (!jb->bitmaps[bmap_nr]) {
jb->bitmaps[bmap_nr] = get_bitmap_node(p_s_sb);
@@ -239,7 +240,7 @@ static void cleanup_bitmap_list(struct super_block *p_s_sb,
if (jb->bitmaps == NULL)
return;
- for (i = 0; i < SB_BMAP_NR(p_s_sb); i++) {
+ for (i = 0; i < reiserfs_bmap_count(p_s_sb); i++) {
if (jb->bitmaps[i]) {
free_bitmap_node(p_s_sb, jb->bitmaps[i]);
jb->bitmaps[i] = NULL;
@@ -289,7 +290,7 @@ static int free_bitmap_nodes(struct super_block *p_s_sb)
*/
int reiserfs_allocate_list_bitmaps(struct super_block *p_s_sb,
struct reiserfs_list_bitmap *jb_array,
- int bmap_nr)
+ unsigned int bmap_nr)
{
int i;
int failed = 0;
@@ -483,7 +484,7 @@ static inline struct reiserfs_journal_cnode *get_journal_hash_dev(struct
**
*/
int reiserfs_in_journal(struct super_block *p_s_sb,
- int bmap_nr, int bit_nr, int search_all,
+ unsigned int bmap_nr, int bit_nr, int search_all,
b_blocknr_t * next_zero_bit)
{
struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb);
@@ -615,6 +616,31 @@ static int journal_list_still_alive(struct super_block *s,
return 0;
}
+/*
+ * If page->mapping was null, we failed to truncate this page for
+ * some reason. Most likely because it was truncated after being
+ * logged via data=journal.
+ *
+ * This does a check to see if the buffer belongs to one of these
+ * lost pages before doing the final put_bh. If page->mapping was
+ * null, it tries to free buffers on the page, which should make the
+ * final page_cache_release drop the page from the lru.
+ */
+static void release_buffer_page(struct buffer_head *bh)
+{
+ struct page *page = bh->b_page;
+ if (!page->mapping && !TestSetPageLocked(page)) {
+ page_cache_get(page);
+ put_bh(bh);
+ if (!page->mapping)
+ try_to_free_buffers(page);
+ unlock_page(page);
+ page_cache_release(page);
+ } else {
+ put_bh(bh);
+ }
+}
+
static void reiserfs_end_buffer_io_sync(struct buffer_head *bh, int uptodate)
{
char b[BDEVNAME_SIZE];
@@ -628,8 +654,9 @@ static void reiserfs_end_buffer_io_sync(struct buffer_head *bh, int uptodate)
set_buffer_uptodate(bh);
else
clear_buffer_uptodate(bh);
+
unlock_buffer(bh);
- put_bh(bh);
+ release_buffer_page(bh);
}
static void reiserfs_end_ordered_io(struct buffer_head *bh, int uptodate)
@@ -966,7 +993,8 @@ static int flush_older_commits(struct super_block *s,
}
return 0;
}
-int reiserfs_async_progress_wait(struct super_block *s)
+
+static int reiserfs_async_progress_wait(struct super_block *s)
{
DEFINE_WAIT(wait);
struct reiserfs_journal *j = SB_JOURNAL(s);
@@ -986,7 +1014,7 @@ static int flush_commit_list(struct super_block *s,
struct reiserfs_journal_list *jl, int flushall)
{
int i;
- int bn;
+ b_blocknr_t bn;
struct buffer_head *tbh = NULL;
unsigned long trans_id = jl->j_trans_id;
struct reiserfs_journal *journal = SB_JOURNAL(s);
@@ -1546,9 +1574,10 @@ static int flush_journal_list(struct super_block *s,
BUG_ON(!test_clear_buffer_journal_dirty
(cn->bh));
- /* undo the inc from journal_mark_dirty */
+ /* drop one ref for us */
put_bh(cn->bh);
- brelse(cn->bh);
+ /* drop one ref for journal_mark_dirty */
+ release_buffer_page(cn->bh);
}
cn = cn->next;
}
@@ -2279,8 +2308,9 @@ static int journal_read_transaction(struct super_block *p_s_sb,
Right now it is only used from journal code. But later we might use it
from other places.
Note: Do not use journal_getblk/sb_getblk functions here! */
-static struct buffer_head *reiserfs_breada(struct block_device *dev, int block,
- int bufsize, unsigned int max_block)
+static struct buffer_head *reiserfs_breada(struct block_device *dev,
+ b_blocknr_t block, int bufsize,
+ b_blocknr_t max_block)
{
struct buffer_head *bhlist[BUFNR];
unsigned int blocks = BUFNR;
@@ -2621,6 +2651,61 @@ static int journal_init_dev(struct super_block *super,
return result;
}
+/**
+ * When creating/tuning a file system user can assign some
+ * journal params within boundaries which depend on the ratio
+ * blocksize/standard_blocksize.
+ *
+ * For blocks >= standard_blocksize transaction size should
+ * be not less then JOURNAL_TRANS_MIN_DEFAULT, and not more
+ * then JOURNAL_TRANS_MAX_DEFAULT.
+ *
+ * For blocks < standard_blocksize these boundaries should be
+ * decreased proportionally.
+ */
+#define REISERFS_STANDARD_BLKSIZE (4096)
+
+static int check_advise_trans_params(struct super_block *p_s_sb,
+ struct reiserfs_journal *journal)
+{
+ if (journal->j_trans_max) {
+ /* Non-default journal params.
+ Do sanity check for them. */
+ int ratio = 1;
+ if (p_s_sb->s_blocksize < REISERFS_STANDARD_BLKSIZE)
+ ratio = REISERFS_STANDARD_BLKSIZE / p_s_sb->s_blocksize;
+
+ if (journal->j_trans_max > JOURNAL_TRANS_MAX_DEFAULT / ratio ||
+ journal->j_trans_max < JOURNAL_TRANS_MIN_DEFAULT / ratio ||
+ SB_ONDISK_JOURNAL_SIZE(p_s_sb) / journal->j_trans_max <
+ JOURNAL_MIN_RATIO) {
+ reiserfs_warning(p_s_sb,
+ "sh-462: bad transaction max size (%u). FSCK?",
+ journal->j_trans_max);
+ return 1;
+ }
+ if (journal->j_max_batch != (journal->j_trans_max) *
+ JOURNAL_MAX_BATCH_DEFAULT/JOURNAL_TRANS_MAX_DEFAULT) {
+ reiserfs_warning(p_s_sb,
+ "sh-463: bad transaction max batch (%u). FSCK?",
+ journal->j_max_batch);
+ return 1;
+ }
+ } else {
+ /* Default journal params.
+ The file system was created by old version
+ of mkreiserfs, so some fields contain zeros,
+ and we need to advise proper values for them */
+ if (p_s_sb->s_blocksize != REISERFS_STANDARD_BLKSIZE)
+ reiserfs_panic(p_s_sb, "sh-464: bad blocksize (%u)",
+ p_s_sb->s_blocksize);
+ journal->j_trans_max = JOURNAL_TRANS_MAX_DEFAULT;
+ journal->j_max_batch = JOURNAL_MAX_BATCH_DEFAULT;
+ journal->j_max_commit_age = JOURNAL_MAX_COMMIT_AGE;
+ }
+ return 0;
+}
+
/*
** must be called once on fs mount. calls journal_read for you
*/
@@ -2649,7 +2734,7 @@ int journal_init(struct super_block *p_s_sb, const char *j_dev_name,
journal->j_persistent_trans = 0;
if (reiserfs_allocate_list_bitmaps(p_s_sb,
journal->j_list_bitmap,
- SB_BMAP_NR(p_s_sb)))
+ reiserfs_bmap_count(p_s_sb)))
goto free_and_return;
allocate_bitmap_nodes(p_s_sb);
@@ -2657,7 +2742,7 @@ int journal_init(struct super_block *p_s_sb, const char *j_dev_name,
SB_JOURNAL_1st_RESERVED_BLOCK(p_s_sb) = (old_format ?
REISERFS_OLD_DISK_OFFSET_IN_BYTES
/ p_s_sb->s_blocksize +
- SB_BMAP_NR(p_s_sb) +
+ reiserfs_bmap_count(p_s_sb) +
1 :
REISERFS_DISK_OFFSET_IN_BYTES /
p_s_sb->s_blocksize + 2);
@@ -2716,49 +2801,8 @@ int journal_init(struct super_block *p_s_sb, const char *j_dev_name,
le32_to_cpu(jh->jh_journal.jp_journal_max_commit_age);
journal->j_max_trans_age = JOURNAL_MAX_TRANS_AGE;
- if (journal->j_trans_max) {
- /* make sure these parameters are available, assign it if they are not */
- __u32 initial = journal->j_trans_max;
- __u32 ratio = 1;
-
- if (p_s_sb->s_blocksize < 4096)
- ratio = 4096 / p_s_sb->s_blocksize;
-
- if (SB_ONDISK_JOURNAL_SIZE(p_s_sb) / journal->j_trans_max <
- JOURNAL_MIN_RATIO)
- journal->j_trans_max =
- SB_ONDISK_JOURNAL_SIZE(p_s_sb) / JOURNAL_MIN_RATIO;
- if (journal->j_trans_max > JOURNAL_TRANS_MAX_DEFAULT / ratio)
- journal->j_trans_max =
- JOURNAL_TRANS_MAX_DEFAULT / ratio;
- if (journal->j_trans_max < JOURNAL_TRANS_MIN_DEFAULT / ratio)
- journal->j_trans_max =
- JOURNAL_TRANS_MIN_DEFAULT / ratio;
-
- if (journal->j_trans_max != initial)
- reiserfs_warning(p_s_sb,
- "sh-461: journal_init: wrong transaction max size (%u). Changed to %u",
- initial, journal->j_trans_max);
-
- journal->j_max_batch = journal->j_trans_max *
- JOURNAL_MAX_BATCH_DEFAULT / JOURNAL_TRANS_MAX_DEFAULT;
- }
-
- if (!journal->j_trans_max) {
- /*we have the file system was created by old version of mkreiserfs
- so this field contains zero value */
- journal->j_trans_max = JOURNAL_TRANS_MAX_DEFAULT;
- journal->j_max_batch = JOURNAL_MAX_BATCH_DEFAULT;
- journal->j_max_commit_age = JOURNAL_MAX_COMMIT_AGE;
-
- /* for blocksize >= 4096 - max transaction size is 1024. For block size < 4096
- trans max size is decreased proportionally */
- if (p_s_sb->s_blocksize < 4096) {
- journal->j_trans_max /= (4096 / p_s_sb->s_blocksize);
- journal->j_max_batch = (journal->j_trans_max) * 9 / 10;
- }
- }
-
+ if (check_advise_trans_params(p_s_sb, journal) != 0)
+ goto free_and_return;
journal->j_default_max_commit_age = journal->j_max_commit_age;
if (commit_max_age != 0) {
@@ -3708,13 +3752,8 @@ int journal_mark_freed(struct reiserfs_transaction_handle *th,
}
}
- if (bh) {
- put_bh(bh); /* get_hash grabs the buffer */
- if (atomic_read(&(bh->b_count)) < 0) {
- reiserfs_warning(p_s_sb,
- "journal-2165: bh->b_count < 0");
- }
- }
+ if (bh)
+ release_buffer_page(bh); /* get_hash grabs the buffer */
return 0;
}
diff --git a/fs/reiserfs/prints.c b/fs/reiserfs/prints.c
index bc808a91eeaa..5e7388b32d02 100644
--- a/fs/reiserfs/prints.c
+++ b/fs/reiserfs/prints.c
@@ -356,13 +356,11 @@ extern struct tree_balance *cur_tb;
void reiserfs_panic(struct super_block *sb, const char *fmt, ...)
{
do_reiserfs_warning(fmt);
- printk(KERN_EMERG "REISERFS: panic (device %s): %s\n",
- reiserfs_bdevname(sb), error_buf);
- BUG();
- /* this is not actually called, but makes reiserfs_panic() "noreturn" */
- panic("REISERFS: panic (device %s): %s\n",
- reiserfs_bdevname(sb), error_buf);
+ dump_stack();
+
+ panic(KERN_EMERG "REISERFS: panic (device %s): %s\n",
+ reiserfs_bdevname(sb), error_buf);
}
void reiserfs_abort(struct super_block *sb, int errno, const char *fmt, ...)
diff --git a/fs/reiserfs/resize.c b/fs/reiserfs/resize.c
index 976cc7887a0d..f71c3948edef 100644
--- a/fs/reiserfs/resize.c
+++ b/fs/reiserfs/resize.c
@@ -61,7 +61,8 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new)
}
/* count used bits in last bitmap block */
- block_r = SB_BLOCK_COUNT(s) - (SB_BMAP_NR(s) - 1) * s->s_blocksize * 8;
+ block_r = SB_BLOCK_COUNT(s) -
+ (reiserfs_bmap_count(s) - 1) * s->s_blocksize * 8;
/* count bitmap blocks in new fs */
bmap_nr_new = block_count_new / (s->s_blocksize * 8);
@@ -73,7 +74,7 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new)
/* save old values */
block_count = SB_BLOCK_COUNT(s);
- bmap_nr = SB_BMAP_NR(s);
+ bmap_nr = reiserfs_bmap_count(s);
/* resizing of reiserfs bitmaps (journal and real), if needed */
if (bmap_nr_new > bmap_nr) {
@@ -119,7 +120,7 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new)
return -ENOMEM;
}
memset(bitmap, 0,
- sizeof(struct reiserfs_bitmap_info) * SB_BMAP_NR(s));
+ sizeof(struct reiserfs_bitmap_info) * bmap_nr_new);
for (i = 0; i < bmap_nr; i++)
bitmap[i] = old_bitmap[i];
@@ -143,7 +144,6 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new)
mark_buffer_dirty(bh);
sync_dirty_buffer(bh);
// update bitmap_info stuff
- bitmap[i].first_zero_hint = 1;
bitmap[i].free_count = sb_blocksize(sb) * 8 - 1;
brelse(bh);
}
@@ -173,8 +173,6 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new)
for (i = block_r; i < s->s_blocksize * 8; i++)
reiserfs_test_and_clear_le_bit(i, bh->b_data);
info->free_count += s->s_blocksize * 8 - block_r;
- if (!info->first_zero_hint)
- info->first_zero_hint = block_r;
journal_mark_dirty(&th, s, bh);
brelse(bh);
@@ -196,9 +194,6 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new)
brelse(bh);
info->free_count -= s->s_blocksize * 8 - block_r_new;
- /* Extreme case where last bitmap is the only valid block in itself. */
- if (!info->free_count)
- info->first_zero_hint = 0;
/* update super */
reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
free_blocks = SB_FREE_BLOCKS(s);
@@ -206,7 +201,7 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new)
free_blocks + (block_count_new - block_count -
(bmap_nr_new - bmap_nr)));
PUT_SB_BLOCK_COUNT(s, block_count_new);
- PUT_SB_BMAP_NR(s, bmap_nr_new);
+ PUT_SB_BMAP_NR(s, bmap_would_wrap(bmap_nr_new) ? : bmap_nr_new);
s->s_dirt = 1;
journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s));
diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c
index 981027d1187b..d2db2417b2bd 100644
--- a/fs/reiserfs/stree.c
+++ b/fs/reiserfs/stree.c
@@ -559,7 +559,7 @@ static int is_tree_node(struct buffer_head *bh, int level)
/* The function is NOT SCHEDULE-SAFE! */
static void search_by_key_reada(struct super_block *s,
struct buffer_head **bh,
- unsigned long *b, int num)
+ b_blocknr_t *b, int num)
{
int i, j;
@@ -611,7 +611,7 @@ int search_by_key(struct super_block *p_s_sb, const struct cpu_key *p_s_key, /*
DISK_LEAF_NODE_LEVEL */
)
{
- int n_block_number;
+ b_blocknr_t n_block_number;
int expected_level;
struct buffer_head *p_s_bh;
struct path_element *p_s_last_element;
@@ -619,7 +619,7 @@ int search_by_key(struct super_block *p_s_sb, const struct cpu_key *p_s_key, /*
int right_neighbor_of_leaf_node;
int fs_gen;
struct buffer_head *reada_bh[SEARCH_BY_KEY_READA];
- unsigned long reada_blocks[SEARCH_BY_KEY_READA];
+ b_blocknr_t reada_blocks[SEARCH_BY_KEY_READA];
int reada_count = 0;
#ifdef CONFIG_REISERFS_CHECK
@@ -1458,9 +1458,6 @@ static void unmap_buffers(struct page *page, loff_t pos)
}
bh = next;
} while (bh != head);
- if (PAGE_SIZE == bh->b_size) {
- cancel_dirty_page(page, PAGE_CACHE_SIZE);
- }
}
}
}
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index a005451930b7..5cd85fe5df5d 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -145,7 +145,7 @@ static int finish_unfinished(struct super_block *s)
{
INITIALIZE_PATH(path);
struct cpu_key max_cpu_key, obj_key;
- struct reiserfs_key save_link_key;
+ struct reiserfs_key save_link_key, last_inode_key;
int retval = 0;
struct item_head *ih;
struct buffer_head *bh;
@@ -166,6 +166,8 @@ static int finish_unfinished(struct super_block *s)
set_cpu_key_k_offset(&max_cpu_key, ~0U);
max_cpu_key.key_length = 3;
+ memset(&last_inode_key, 0, sizeof(last_inode_key));
+
#ifdef CONFIG_QUOTA
/* Needed for iput() to work correctly and not trash data */
if (s->s_flags & MS_ACTIVE) {
@@ -278,8 +280,18 @@ static int finish_unfinished(struct super_block *s)
REISERFS_I(inode)->i_flags |= i_link_saved_unlink_mask;
/* not completed unlink (rmdir) found */
reiserfs_info(s, "Removing %k..", INODE_PKEY(inode));
- /* removal gets completed in iput */
- retval = 0;
+ if (memcmp(&last_inode_key, INODE_PKEY(inode),
+ sizeof(last_inode_key))){
+ last_inode_key = *INODE_PKEY(inode);
+ /* removal gets completed in iput */
+ retval = 0;
+ } else {
+ reiserfs_warning(s, "Dead loop in "
+ "finish_unfinished detected, "
+ "just remove save link\n");
+ retval = remove_save_link_only(s,
+ &save_link_key, 0);
+ }
}
iput(inode);
@@ -307,7 +319,7 @@ static int finish_unfinished(struct super_block *s)
/* to protect file being unlinked from getting lost we "safe" link files
being unlinked. This link will be deleted in the same transaction with last
- item of file. mounting the filesytem we scan all these links and remove
+ item of file. mounting the filesystem we scan all these links and remove
files which almost got lost */
void add_save_link(struct reiserfs_transaction_handle *th,
struct inode *inode, int truncate)
@@ -508,7 +520,7 @@ static void reiserfs_destroy_inode(struct inode *inode)
kmem_cache_free(reiserfs_inode_cachep, REISERFS_I(inode));
}
-static void init_once(void *foo, struct kmem_cache * cachep, unsigned long flags)
+static void init_once(struct kmem_cache * cachep, void *foo)
{
struct reiserfs_inode_info *ei = (struct reiserfs_inode_info *)foo;
@@ -649,11 +661,11 @@ static struct quotactl_ops reiserfs_qctl_operations = {
};
#endif
-static struct export_operations reiserfs_export_ops = {
+static const struct export_operations reiserfs_export_ops = {
.encode_fh = reiserfs_encode_fh,
- .decode_fh = reiserfs_decode_fh,
+ .fh_to_dentry = reiserfs_fh_to_dentry,
+ .fh_to_parent = reiserfs_fh_to_parent,
.get_parent = reiserfs_get_parent,
- .get_dentry = reiserfs_get_dentry,
};
/* this struct is used in reiserfs_getopt () for containing the value for those
@@ -1713,6 +1725,21 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
set_sb_umount_state(rs, REISERFS_ERROR_FS);
set_sb_fs_state(rs, 0);
+ /* Clear out s_bmap_nr if it would wrap. We can handle this
+ * case, but older revisions can't. This will cause the
+ * file system to fail mount on those older implementations,
+ * avoiding corruption. -jeffm */
+ if (bmap_would_wrap(reiserfs_bmap_count(s)) &&
+ sb_bmap_nr(rs) != 0) {
+ reiserfs_warning(s, "super-2030: This file system "
+ "claims to use %u bitmap blocks in "
+ "its super block, but requires %u. "
+ "Clearing to zero.", sb_bmap_nr(rs),
+ reiserfs_bmap_count(s));
+
+ set_sb_bmap_nr(rs, 0);
+ }
+
if (old_format_only(s)) {
/* filesystem of format 3.5 either with standard or non-standard
journal */
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index bf6e58214538..1597f6b649e0 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -426,6 +426,12 @@ static inline __u32 xattr_hash(const char *msg, int len)
return csum_partial(msg, len, 0);
}
+int reiserfs_commit_write(struct file *f, struct page *page,
+ unsigned from, unsigned to);
+int reiserfs_prepare_write(struct file *f, struct page *page,
+ unsigned from, unsigned to);
+
+
/* Generic extended attribute operations that can be used by xa plugins */
/*
@@ -478,7 +484,7 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer,
/* Resize it so we're ok to write there */
newattrs.ia_size = buffer_size;
newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
- mutex_lock(&xinode->i_mutex);
+ mutex_lock_nested(&xinode->i_mutex, I_MUTEX_XATTR);
err = notify_change(fp->f_path.dentry, &newattrs);
if (err)
goto out_filp;
@@ -512,15 +518,15 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer,
rxh->h_hash = cpu_to_le32(xahash);
}
- err = mapping->a_ops->prepare_write(fp, page, page_offset,
- page_offset + chunk + skip);
+ err = reiserfs_prepare_write(fp, page, page_offset,
+ page_offset + chunk + skip);
if (!err) {
if (buffer)
memcpy(data + skip, buffer + buffer_pos, chunk);
err =
- mapping->a_ops->commit_write(fp, page, page_offset,
- page_offset + chunk +
- skip);
+ reiserfs_commit_write(fp, page, page_offset,
+ page_offset + chunk +
+ skip);
}
unlock_page(page);
reiserfs_put_page(page);
@@ -1217,7 +1223,8 @@ int reiserfs_xattr_init(struct super_block *s, int mount_flags)
if (!IS_ERR(dentry)) {
if (!(mount_flags & MS_RDONLY) && !dentry->d_inode) {
struct inode *inode = dentry->d_parent->d_inode;
- mutex_lock(&inode->i_mutex);
+ mutex_lock_nested(&inode->i_mutex,
+ I_MUTEX_XATTR);
err = inode->i_op->mkdir(inode, dentry, 0700);
mutex_unlock(&inode->i_mutex);
if (err) {
diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c
index dae7945f90e4..a49cf5b9a195 100644
--- a/fs/romfs/inode.c
+++ b/fs/romfs/inode.c
@@ -92,7 +92,7 @@ static inline unsigned long romfs_maxsize(struct super_block *sb)
static inline struct romfs_inode_info *ROMFS_I(struct inode *inode)
{
- return list_entry(inode, struct romfs_inode_info, vfs_inode);
+ return container_of(inode, struct romfs_inode_info, vfs_inode);
}
static __u32
@@ -555,7 +555,7 @@ static struct kmem_cache * romfs_inode_cachep;
static struct inode *romfs_alloc_inode(struct super_block *sb)
{
struct romfs_inode_info *ei;
- ei = (struct romfs_inode_info *)kmem_cache_alloc(romfs_inode_cachep, GFP_KERNEL);
+ ei = kmem_cache_alloc(romfs_inode_cachep, GFP_KERNEL);
if (!ei)
return NULL;
return &ei->vfs_inode;
@@ -566,7 +566,7 @@ static void romfs_destroy_inode(struct inode *inode)
kmem_cache_free(romfs_inode_cachep, ROMFS_I(inode));
}
-static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags)
+static void init_once(struct kmem_cache *cachep, void *foo)
{
struct romfs_inode_info *ei = foo;
diff --git a/fs/select.c b/fs/select.c
index 46dca31c607a..47f47925aea2 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -177,11 +177,6 @@ get_max:
return max;
}
-#define BIT(i) (1UL << ((i)&(__NFDBITS-1)))
-#define MEM(i,m) ((m)+(unsigned)(i)/__NFDBITS)
-#define ISSET(i,m) (((i)&*(m)) != 0)
-#define SET(i,m) (*(m) |= (i))
-
#define POLLIN_SET (POLLRDNORM | POLLRDBAND | POLLIN | POLLHUP | POLLERR)
#define POLLOUT_SET (POLLWRBAND | POLLWRNORM | POLLOUT | POLLERR)
#define POLLEX_SET (POLLPRI)
@@ -586,7 +581,7 @@ static int do_poll(unsigned int nfds, struct poll_list *list,
/* Optimise the no-wait case */
if (!(*timeout))
pt = NULL;
-
+
for (;;) {
struct poll_list *walk;
long __timeout;
@@ -616,10 +611,12 @@ static int do_poll(unsigned int nfds, struct poll_list *list,
* a poll_table to them on the next loop iteration.
*/
pt = NULL;
- if (count || !*timeout || signal_pending(current))
- break;
- count = wait->error;
- if (count)
+ if (!count) {
+ count = wait->error;
+ if (signal_pending(current))
+ count = -EINTR;
+ }
+ if (count || !*timeout)
break;
if (*timeout < 0) {
@@ -651,93 +648,89 @@ static int do_poll(unsigned int nfds, struct poll_list *list,
int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, s64 *timeout)
{
struct poll_wqueues table;
- int fdcount, err;
- unsigned int i;
- struct poll_list *head;
- struct poll_list *walk;
+ int err = -EFAULT, fdcount, len, size;
/* Allocate small arguments on the stack to save memory and be
faster - use long to make sure the buffer is aligned properly
on 64 bit archs to avoid unaligned access */
long stack_pps[POLL_STACK_ALLOC/sizeof(long)];
- struct poll_list *stack_pp = NULL;
+ struct poll_list *const head = (struct poll_list *)stack_pps;
+ struct poll_list *walk = head;
+ unsigned long todo = nfds;
- /* Do a sanity check on nfds ... */
if (nfds > current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
return -EINVAL;
- poll_initwait(&table);
+ len = min_t(unsigned int, nfds, N_STACK_PPS);
+ for (;;) {
+ walk->next = NULL;
+ walk->len = len;
+ if (!len)
+ break;
- head = NULL;
- walk = NULL;
- i = nfds;
- err = -ENOMEM;
- while(i!=0) {
- struct poll_list *pp;
- int num, size;
- if (stack_pp == NULL)
- num = N_STACK_PPS;
- else
- num = POLLFD_PER_PAGE;
- if (num > i)
- num = i;
- size = sizeof(struct poll_list) + sizeof(struct pollfd)*num;
- if (!stack_pp)
- stack_pp = pp = (struct poll_list *)stack_pps;
- else {
- pp = kmalloc(size, GFP_KERNEL);
- if (!pp)
- goto out_fds;
- }
- pp->next=NULL;
- pp->len = num;
- if (head == NULL)
- head = pp;
- else
- walk->next = pp;
+ if (copy_from_user(walk->entries, ufds + nfds-todo,
+ sizeof(struct pollfd) * walk->len))
+ goto out_fds;
- walk = pp;
- if (copy_from_user(pp->entries, ufds + nfds-i,
- sizeof(struct pollfd)*num)) {
- err = -EFAULT;
+ todo -= walk->len;
+ if (!todo)
+ break;
+
+ len = min(todo, POLLFD_PER_PAGE);
+ size = sizeof(struct poll_list) + sizeof(struct pollfd) * len;
+ walk = walk->next = kmalloc(size, GFP_KERNEL);
+ if (!walk) {
+ err = -ENOMEM;
goto out_fds;
}
- i -= pp->len;
}
+ poll_initwait(&table);
fdcount = do_poll(nfds, head, &table, timeout);
+ poll_freewait(&table);
- /* OK, now copy the revents fields back to user space. */
- walk = head;
- err = -EFAULT;
- while(walk != NULL) {
+ for (walk = head; walk; walk = walk->next) {
struct pollfd *fds = walk->entries;
int j;
- for (j=0; j < walk->len; j++, ufds++) {
- if(__put_user(fds[j].revents, &ufds->revents))
+ for (j = 0; j < walk->len; j++, ufds++)
+ if (__put_user(fds[j].revents, &ufds->revents))
goto out_fds;
- }
- walk = walk->next;
}
+
err = fdcount;
- if (!fdcount && signal_pending(current))
- err = -EINTR;
out_fds:
- walk = head;
- while(walk!=NULL) {
- struct poll_list *pp = walk->next;
- if (walk != stack_pp)
- kfree(walk);
- walk = pp;
+ walk = head->next;
+ while (walk) {
+ struct poll_list *pos = walk;
+ walk = walk->next;
+ kfree(pos);
}
- poll_freewait(&table);
+
return err;
}
+static long do_restart_poll(struct restart_block *restart_block)
+{
+ struct pollfd __user *ufds = (struct pollfd __user*)restart_block->arg0;
+ int nfds = restart_block->arg1;
+ s64 timeout = ((s64)restart_block->arg3<<32) | (s64)restart_block->arg2;
+ int ret;
+
+ ret = do_sys_poll(ufds, nfds, &timeout);
+ if (ret == -EINTR) {
+ restart_block->fn = do_restart_poll;
+ restart_block->arg2 = timeout & 0xFFFFFFFF;
+ restart_block->arg3 = (u64)timeout >> 32;
+ ret = -ERESTART_RESTARTBLOCK;
+ }
+ return ret;
+}
+
asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds,
long timeout_msecs)
{
s64 timeout_jiffies;
+ int ret;
if (timeout_msecs > 0) {
#if HZ > 1000
@@ -752,7 +745,18 @@ asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds,
timeout_jiffies = timeout_msecs;
}
- return do_sys_poll(ufds, nfds, &timeout_jiffies);
+ ret = do_sys_poll(ufds, nfds, &timeout_jiffies);
+ if (ret == -EINTR) {
+ struct restart_block *restart_block;
+ restart_block = &current_thread_info()->restart_block;
+ restart_block->fn = do_restart_poll;
+ restart_block->arg0 = (unsigned long)ufds;
+ restart_block->arg1 = nfds;
+ restart_block->arg2 = timeout_jiffies & 0xFFFFFFFF;
+ restart_block->arg3 = (u64)timeout_jiffies >> 32;
+ ret = -ERESTART_RESTARTBLOCK;
+ }
+ return ret;
}
#ifdef TIF_RESTORE_SIGMASK
diff --git a/fs/signalfd.c b/fs/signalfd.c
index aefb0be07942..fb7f7e8034df 100644
--- a/fs/signalfd.c
+++ b/fs/signalfd.c
@@ -74,45 +74,45 @@ static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo,
* If you change siginfo_t structure, please be sure
* this code is fixed accordingly.
*/
- err |= __put_user(kinfo->si_signo, &uinfo->signo);
- err |= __put_user(kinfo->si_errno, &uinfo->err);
- err |= __put_user((short)kinfo->si_code, &uinfo->code);
+ err |= __put_user(kinfo->si_signo, &uinfo->ssi_signo);
+ err |= __put_user(kinfo->si_errno, &uinfo->ssi_errno);
+ err |= __put_user((short) kinfo->si_code, &uinfo->ssi_code);
switch (kinfo->si_code & __SI_MASK) {
case __SI_KILL:
- err |= __put_user(kinfo->si_pid, &uinfo->pid);
- err |= __put_user(kinfo->si_uid, &uinfo->uid);
+ err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid);
+ err |= __put_user(kinfo->si_uid, &uinfo->ssi_uid);
break;
case __SI_TIMER:
- err |= __put_user(kinfo->si_tid, &uinfo->tid);
- err |= __put_user(kinfo->si_overrun, &uinfo->overrun);
- err |= __put_user((long)kinfo->si_ptr, &uinfo->svptr);
+ err |= __put_user(kinfo->si_tid, &uinfo->ssi_tid);
+ err |= __put_user(kinfo->si_overrun, &uinfo->ssi_overrun);
+ err |= __put_user((long) kinfo->si_ptr, &uinfo->ssi_ptr);
break;
case __SI_POLL:
- err |= __put_user(kinfo->si_band, &uinfo->band);
- err |= __put_user(kinfo->si_fd, &uinfo->fd);
+ err |= __put_user(kinfo->si_band, &uinfo->ssi_band);
+ err |= __put_user(kinfo->si_fd, &uinfo->ssi_fd);
break;
case __SI_FAULT:
- err |= __put_user((long)kinfo->si_addr, &uinfo->addr);
+ err |= __put_user((long) kinfo->si_addr, &uinfo->ssi_addr);
#ifdef __ARCH_SI_TRAPNO
- err |= __put_user(kinfo->si_trapno, &uinfo->trapno);
+ err |= __put_user(kinfo->si_trapno, &uinfo->ssi_trapno);
#endif
break;
case __SI_CHLD:
- err |= __put_user(kinfo->si_pid, &uinfo->pid);
- err |= __put_user(kinfo->si_uid, &uinfo->uid);
- err |= __put_user(kinfo->si_status, &uinfo->status);
- err |= __put_user(kinfo->si_utime, &uinfo->utime);
- err |= __put_user(kinfo->si_stime, &uinfo->stime);
+ err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid);
+ err |= __put_user(kinfo->si_uid, &uinfo->ssi_uid);
+ err |= __put_user(kinfo->si_status, &uinfo->ssi_status);
+ err |= __put_user(kinfo->si_utime, &uinfo->ssi_utime);
+ err |= __put_user(kinfo->si_stime, &uinfo->ssi_stime);
break;
case __SI_RT: /* This is not generated by the kernel as of now. */
case __SI_MESGQ: /* But this is */
- err |= __put_user(kinfo->si_pid, &uinfo->pid);
- err |= __put_user(kinfo->si_uid, &uinfo->uid);
- err |= __put_user((long)kinfo->si_ptr, &uinfo->svptr);
+ err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid);
+ err |= __put_user(kinfo->si_uid, &uinfo->ssi_uid);
+ err |= __put_user((long) kinfo->si_ptr, &uinfo->ssi_ptr);
break;
default: /* this is just in case for now ... */
- err |= __put_user(kinfo->si_pid, &uinfo->pid);
- err |= __put_user(kinfo->si_uid, &uinfo->uid);
+ err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid);
+ err |= __put_user(kinfo->si_uid, &uinfo->ssi_uid);
break;
}
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c
index c5d78a7e492b..efbe29af3d7a 100644
--- a/fs/smbfs/file.c
+++ b/fs/smbfs/file.c
@@ -234,7 +234,7 @@ smb_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
VERBOSE("before read, size=%ld, flags=%x, atime=%ld\n",
(long)dentry->d_inode->i_size,
- dentry->d_inode->i_flags, dentry->d_inode->i_atime);
+ dentry->d_inode->i_flags, dentry->d_inode->i_atime.tv_sec);
status = generic_file_aio_read(iocb, iov, nr_segs, pos);
out:
@@ -269,7 +269,7 @@ smb_file_splice_read(struct file *file, loff_t *ppos,
struct dentry *dentry = file->f_path.dentry;
ssize_t status;
- VERBOSE("file %s/%s, pos=%Ld, count=%d\n",
+ VERBOSE("file %s/%s, pos=%Ld, count=%lu\n",
DENTRY_PATH(dentry), *ppos, count);
status = smb_revalidate_inode(dentry);
@@ -292,29 +292,45 @@ out:
* If the writer ends up delaying the write, the writer needs to
* increment the page use counts until he is done with the page.
*/
-static int smb_prepare_write(struct file *file, struct page *page,
- unsigned offset, unsigned to)
+static int smb_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
{
+ pgoff_t index = pos >> PAGE_CACHE_SHIFT;
+ *pagep = __grab_cache_page(mapping, index);
+ if (!*pagep)
+ return -ENOMEM;
return 0;
}
-static int smb_commit_write(struct file *file, struct page *page,
- unsigned offset, unsigned to)
+static int smb_write_end(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata)
{
int status;
+ unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
- status = -EFAULT;
lock_kernel();
- status = smb_updatepage(file, page, offset, to-offset);
+ status = smb_updatepage(file, page, offset, copied);
unlock_kernel();
+
+ if (!status) {
+ if (!PageUptodate(page) && copied == PAGE_CACHE_SIZE)
+ SetPageUptodate(page);
+ status = copied;
+ }
+
+ unlock_page(page);
+ page_cache_release(page);
+
return status;
}
const struct address_space_operations smb_file_aops = {
.readpage = smb_readpage,
.writepage = smb_writepage,
- .prepare_write = smb_prepare_write,
- .commit_write = smb_commit_write
+ .write_begin = smb_write_begin,
+ .write_end = smb_write_end,
};
/*
@@ -347,7 +363,8 @@ smb_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
result = generic_file_aio_write(iocb, iov, nr_segs, pos);
VERBOSE("pos=%ld, size=%ld, mtime=%ld, atime=%ld\n",
(long) file->f_pos, (long) dentry->d_inode->i_size,
- dentry->d_inode->i_mtime, dentry->d_inode->i_atime);
+ dentry->d_inode->i_mtime.tv_sec,
+ dentry->d_inode->i_atime.tv_sec);
}
out:
return result;
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c
index 73d1450a95d4..9416ead0c7aa 100644
--- a/fs/smbfs/inode.c
+++ b/fs/smbfs/inode.c
@@ -67,7 +67,7 @@ static void smb_destroy_inode(struct inode *inode)
kmem_cache_free(smb_inode_cachep, SMB_I(inode));
}
-static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
+static void init_once(struct kmem_cache *cachep, void *foo)
{
struct smb_inode_info *ei = (struct smb_inode_info *) foo;
@@ -536,7 +536,7 @@ static int smb_fill_super(struct super_block *sb, void *raw_data, int silent)
/* Allocate the global temp buffer and some superblock helper structs */
/* FIXME: move these to the smb_sb_info struct */
- VERBOSE("alloc chunk = %d\n", sizeof(struct smb_ops) +
+ VERBOSE("alloc chunk = %lu\n", sizeof(struct smb_ops) +
sizeof(struct smb_mount_data_kernel));
mem = kmalloc(sizeof(struct smb_ops) +
sizeof(struct smb_mount_data_kernel), GFP_KERNEL);
diff --git a/fs/smbfs/proc.c b/fs/smbfs/proc.c
index feac46050619..d517a27b7f4b 100644
--- a/fs/smbfs/proc.c
+++ b/fs/smbfs/proc.c
@@ -2593,7 +2593,7 @@ smb_proc_getattr_ff(struct smb_sb_info *server, struct dentry *dentry,
fattr->f_mtime.tv_sec = date_dos2unix(server, date, time);
fattr->f_mtime.tv_nsec = 0;
VERBOSE("name=%s, date=%x, time=%x, mtime=%ld\n",
- mask, date, time, fattr->f_mtime);
+ mask, date, time, fattr->f_mtime.tv_sec);
fattr->f_size = DVAL(req->rq_data, 12);
/* ULONG allocation size */
fattr->attr = WVAL(req->rq_data, 20);
diff --git a/fs/smbfs/smbiod.c b/fs/smbfs/smbiod.c
index 283c5720c9de..fae8e85af0ed 100644
--- a/fs/smbfs/smbiod.c
+++ b/fs/smbfs/smbiod.c
@@ -227,7 +227,7 @@ int smbiod_retry(struct smb_sb_info *server)
printk(KERN_ERR "smb_retry: signal failed [%d]\n", result);
goto out;
}
- VERBOSE("signalled pid %d\n", pid);
+ VERBOSE("signalled pid %d\n", pid_nr(pid));
/* FIXME: The retried requests should perhaps get a "time boost". */
diff --git a/fs/splice.c b/fs/splice.c
index e95a36228863..6bdcb6107bc3 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -447,7 +447,7 @@ fill_it:
*/
while (page_nr < nr_pages)
page_cache_release(pages[page_nr++]);
- in->f_ra.prev_index = index;
+ in->f_ra.prev_pos = (loff_t)index << PAGE_CACHE_SHIFT;
if (spd.nr_pages)
return splice_to_pipe(pipe, &spd);
@@ -563,7 +563,7 @@ static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
struct address_space *mapping = file->f_mapping;
unsigned int offset, this_len;
struct page *page;
- pgoff_t index;
+ void *fsdata;
int ret;
/*
@@ -573,49 +573,16 @@ static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
if (unlikely(ret))
return ret;
- index = sd->pos >> PAGE_CACHE_SHIFT;
offset = sd->pos & ~PAGE_CACHE_MASK;
this_len = sd->len;
if (this_len + offset > PAGE_CACHE_SIZE)
this_len = PAGE_CACHE_SIZE - offset;
-find_page:
- page = find_lock_page(mapping, index);
- if (!page) {
- ret = -ENOMEM;
- page = page_cache_alloc_cold(mapping);
- if (unlikely(!page))
- goto out_ret;
-
- /*
- * This will also lock the page
- */
- ret = add_to_page_cache_lru(page, mapping, index,
- GFP_KERNEL);
- if (unlikely(ret))
- goto out_release;
- }
-
- ret = mapping->a_ops->prepare_write(file, page, offset, offset+this_len);
- if (unlikely(ret)) {
- loff_t isize = i_size_read(mapping->host);
-
- if (ret != AOP_TRUNCATED_PAGE)
- unlock_page(page);
- page_cache_release(page);
- if (ret == AOP_TRUNCATED_PAGE)
- goto find_page;
-
- /*
- * prepare_write() may have instantiated a few blocks
- * outside i_size. Trim these off again.
- */
- if (sd->pos + this_len > isize)
- vmtruncate(mapping->host, isize);
-
- goto out_ret;
- }
+ ret = pagecache_write_begin(file, mapping, sd->pos, this_len,
+ AOP_FLAG_UNINTERRUPTIBLE, &page, &fsdata);
+ if (unlikely(ret))
+ goto out;
if (buf->page != page) {
/*
@@ -629,31 +596,9 @@ find_page:
kunmap_atomic(dst, KM_USER1);
buf->ops->unmap(pipe, buf, src);
}
-
- ret = mapping->a_ops->commit_write(file, page, offset, offset+this_len);
- if (ret) {
- if (ret == AOP_TRUNCATED_PAGE) {
- page_cache_release(page);
- goto find_page;
- }
- if (ret < 0)
- goto out;
- /*
- * Partial write has happened, so 'ret' already initialized by
- * number of bytes written, Where is nothing we have to do here.
- */
- } else
- ret = this_len;
- /*
- * Return the number of bytes written and mark page as
- * accessed, we are now done!
- */
- mark_page_accessed(page);
+ ret = pagecache_write_end(file, mapping, sd->pos, this_len, this_len,
+ page, fsdata);
out:
- unlock_page(page);
-out_release:
- page_cache_release(page);
-out_ret:
return ret;
}
@@ -879,13 +824,18 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
{
struct address_space *mapping = out->f_mapping;
struct inode *inode = mapping->host;
+ int killsuid, killpriv;
ssize_t ret;
- int err;
+ int err = 0;
- err = should_remove_suid(out->f_path.dentry);
- if (unlikely(err)) {
+ killpriv = security_inode_need_killpriv(out->f_path.dentry);
+ killsuid = should_remove_suid(out->f_path.dentry);
+ if (unlikely(killsuid || killpriv)) {
mutex_lock(&inode->i_mutex);
- err = __remove_suid(out->f_path.dentry, err);
+ if (killpriv)
+ err = security_inode_killpriv(out->f_path.dentry);
+ if (!err && killsuid)
+ err = __remove_suid(out->f_path.dentry, killsuid);
mutex_unlock(&inode->i_mutex);
if (err)
return err;
@@ -1390,10 +1340,10 @@ static int pipe_to_user(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
if (copy_to_user(sd->u.userptr, src + buf->offset, sd->len))
ret = -EFAULT;
+ buf->ops->unmap(pipe, buf, src);
out:
if (ret > 0)
sd->u.userptr += ret;
- buf->ops->unmap(pipe, buf, src);
return ret;
}
diff --git a/fs/super.c b/fs/super.c
index fc8ebedc6bed..ceaf2e3d594c 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -15,7 +15,7 @@
* Added kerneld support: Jacques Gelinas and Bjorn Ekwall
* Added change_root: Werner Almesberger & Hans Lermen, Feb '96
* Added options to /proc/mounts:
- * Torbjörn Lindh (torbjorn.lindh@gopta.se), April 14, 1996.
+ * Torbjörn Lindh (torbjorn.lindh@gopta.se), April 14, 1996.
* Added devfs support: Richard Gooch <rgooch@atnf.csiro.au>, 13-JAN-1998
* Heavily rewritten for 'one fs - one tree' dcache architecture. AV, Mar 2000
*/
@@ -40,10 +40,6 @@
#include <asm/uaccess.h>
-void get_filesystem(struct file_system_type *fs);
-void put_filesystem(struct file_system_type *fs);
-struct file_system_type *get_fs_type(const char *name);
-
LIST_HEAD(super_blocks);
DEFINE_SPINLOCK(sb_lock);
@@ -67,6 +63,7 @@ static struct super_block *alloc_super(struct file_system_type *type)
}
INIT_LIST_HEAD(&s->s_dirty);
INIT_LIST_HEAD(&s->s_io);
+ INIT_LIST_HEAD(&s->s_more_io);
INIT_LIST_HEAD(&s->s_files);
INIT_LIST_HEAD(&s->s_instances);
INIT_HLIST_HEAD(&s->s_anon);
@@ -335,21 +332,21 @@ struct super_block *sget(struct file_system_type *type,
void *data)
{
struct super_block *s = NULL;
- struct list_head *p;
+ struct super_block *old;
int err;
retry:
spin_lock(&sb_lock);
- if (test) list_for_each(p, &type->fs_supers) {
- struct super_block *old;
- old = list_entry(p, struct super_block, s_instances);
- if (!test(old, data))
- continue;
- if (!grab_super(old))
- goto retry;
- if (s)
- destroy_super(s);
- return old;
+ if (test) {
+ list_for_each_entry(old, &type->fs_supers, s_instances) {
+ if (!test(old, data))
+ continue;
+ if (!grab_super(old))
+ goto retry;
+ if (s)
+ destroy_super(s);
+ return old;
+ }
}
if (!s) {
spin_unlock(&sb_lock);
@@ -420,7 +417,7 @@ restart:
}
/*
- * Call the ->sync_fs super_op against all filesytems which are r/w and
+ * Call the ->sync_fs super_op against all filesystems which are r/w and
* which implement it.
*
* This operation is careful to avoid the livelock which could easily happen
@@ -428,7 +425,7 @@ restart:
* is used only here. We set it against all filesystems and then clear it as
* we sync them. So redirtied filesystems are skipped.
*
- * But if process A is currently running sync_filesytems and then process B
+ * But if process A is currently running sync_filesystems and then process B
* calls sync_filesystems as well, process B will set all the s_need_sync_fs
* flags again, which will cause process A to resync everything. Fix that with
* a local mutex.
@@ -947,9 +944,9 @@ do_kern_mount(const char *fstype, int flags, const char *name, void *data)
return mnt;
}
-struct vfsmount *kern_mount(struct file_system_type *type)
+struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
{
- return vfs_kern_mount(type, 0, type->name, NULL);
+ return vfs_kern_mount(type, MS_KERNMOUNT, type->name, data);
}
-EXPORT_SYMBOL(kern_mount);
+EXPORT_SYMBOL_GPL(kern_mount_data);
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 9161db4d6b5c..337162935d21 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -24,9 +24,9 @@
DEFINE_MUTEX(sysfs_mutex);
DEFINE_MUTEX(sysfs_rename_mutex);
-spinlock_t sysfs_assoc_lock = SPIN_LOCK_UNLOCKED;
+DEFINE_SPINLOCK(sysfs_assoc_lock);
-static spinlock_t sysfs_ino_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(sysfs_ino_lock);
static DEFINE_IDA(sysfs_ino_ida);
/**
@@ -112,8 +112,7 @@ struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd)
/* look it up */
parent = dentry;
mutex_lock(&parent->d_inode->i_mutex);
- dentry = lookup_one_len_kern(cur->s_name, parent,
- strlen(cur->s_name));
+ dentry = lookup_one_noperm(cur->s_name, parent);
mutex_unlock(&parent->d_inode->i_mutex);
dput(parent);
@@ -133,7 +132,7 @@ struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd)
* RETURNS:
* Pointer to @sd on success, NULL on failure.
*/
-struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd)
+static struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd)
{
if (unlikely(!sd))
return NULL;
@@ -162,7 +161,7 @@ struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd)
* Put an active reference to @sd. This function is noop if @sd
* is NULL.
*/
-void sysfs_put_active(struct sysfs_dirent *sd)
+static void sysfs_put_active(struct sysfs_dirent *sd)
{
struct completion *cmpl;
int v;
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index d3be1e7fb48b..27d1785b7644 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -540,7 +540,7 @@ int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr,
/**
* sysfs_create_file - create an attribute file for an object.
* @kobj: object we're creating for.
- * @attr: atrribute descriptor.
+ * @attr: attribute descriptor.
*/
int sysfs_create_file(struct kobject * kobj, const struct attribute * attr)
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 9236635111f4..d9262f74f94e 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -24,8 +24,8 @@ extern struct super_block * sysfs_sb;
static const struct address_space_operations sysfs_aops = {
.readpage = simple_readpage,
- .prepare_write = simple_prepare_write,
- .commit_write = simple_commit_write
+ .write_begin = simple_write_begin,
+ .write_end = simple_write_end,
};
static struct backing_dev_info sysfs_backing_dev_info = {
@@ -37,6 +37,11 @@ static const struct inode_operations sysfs_inode_operations ={
.setattr = sysfs_setattr,
};
+int __init sysfs_inode_init(void)
+{
+ return bdi_init(&sysfs_backing_dev_info);
+}
+
int sysfs_setattr(struct dentry * dentry, struct iattr * iattr)
{
struct inode * inode = dentry->d_inode;
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index c76c540be3c8..74168266cd59 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -92,6 +92,10 @@ int __init sysfs_init(void)
if (!sysfs_dir_cachep)
goto out;
+ err = sysfs_inode_init();
+ if (err)
+ goto out_err;
+
err = register_filesystem(&sysfs_fs_type);
if (!err) {
sysfs_mount = kern_mount(&sysfs_fs_type);
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index f0326f281d1c..ff17f8da9b43 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -103,8 +103,6 @@ extern const struct file_operations sysfs_dir_operations;
extern const struct inode_operations sysfs_dir_inode_operations;
struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd);
-struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd);
-void sysfs_put_active(struct sysfs_dirent *sd);
struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd);
void sysfs_put_active_two(struct sysfs_dirent *sd);
void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
@@ -146,6 +144,7 @@ static inline void sysfs_put(struct sysfs_dirent *sd)
struct inode *sysfs_get_inode(struct sysfs_dirent *sd);
int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name);
+int sysfs_inode_init(void);
/*
* file.c
diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c
index e566b387fcf9..56f655254bfe 100644
--- a/fs/sysv/dir.c
+++ b/fs/sysv/dir.c
@@ -16,6 +16,7 @@
#include <linux/pagemap.h>
#include <linux/highmem.h>
#include <linux/smp_lock.h>
+#include <linux/swap.h>
#include "sysv.h"
static int sysv_readdir(struct file *, void *, filldir_t);
@@ -37,12 +38,17 @@ static inline unsigned long dir_pages(struct inode *inode)
return (inode->i_size+PAGE_CACHE_SIZE-1)>>PAGE_CACHE_SHIFT;
}
-static int dir_commit_chunk(struct page *page, unsigned from, unsigned to)
+static int dir_commit_chunk(struct page *page, loff_t pos, unsigned len)
{
- struct inode *dir = (struct inode *)page->mapping->host;
+ struct address_space *mapping = page->mapping;
+ struct inode *dir = mapping->host;
int err = 0;
- page->mapping->a_ops->commit_write(NULL, page, from, to);
+ block_write_end(NULL, mapping, pos, len, len, page, NULL);
+ if (pos+len > dir->i_size) {
+ i_size_write(dir, pos+len);
+ mark_inode_dirty(dir);
+ }
if (IS_DIRSYNC(dir))
err = write_one_page(page, 1);
else
@@ -186,7 +192,7 @@ int sysv_add_link(struct dentry *dentry, struct inode *inode)
unsigned long npages = dir_pages(dir);
unsigned long n;
char *kaddr;
- unsigned from, to;
+ loff_t pos;
int err;
/* We take care of directory expansion in the same loop */
@@ -212,16 +218,17 @@ int sysv_add_link(struct dentry *dentry, struct inode *inode)
return -EINVAL;
got_it:
- from = (char*)de - (char*)page_address(page);
- to = from + SYSV_DIRSIZE;
+ pos = page_offset(page) +
+ (char*)de - (char*)page_address(page);
lock_page(page);
- err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
+ err = __sysv_write_begin(NULL, page->mapping, pos, SYSV_DIRSIZE,
+ AOP_FLAG_UNINTERRUPTIBLE, &page, NULL);
if (err)
goto out_unlock;
memcpy (de->name, name, namelen);
memset (de->name + namelen, 0, SYSV_DIRSIZE - namelen - 2);
de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino);
- err = dir_commit_chunk(page, from, to);
+ err = dir_commit_chunk(page, pos, SYSV_DIRSIZE);
dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
mark_inode_dirty(dir);
out_page:
@@ -238,15 +245,15 @@ int sysv_delete_entry(struct sysv_dir_entry *de, struct page *page)
struct address_space *mapping = page->mapping;
struct inode *inode = (struct inode*)mapping->host;
char *kaddr = (char*)page_address(page);
- unsigned from = (char*)de - kaddr;
- unsigned to = from + SYSV_DIRSIZE;
+ loff_t pos = page_offset(page) + (char *)de - kaddr;
int err;
lock_page(page);
- err = mapping->a_ops->prepare_write(NULL, page, from, to);
+ err = __sysv_write_begin(NULL, mapping, pos, SYSV_DIRSIZE,
+ AOP_FLAG_UNINTERRUPTIBLE, &page, NULL);
BUG_ON(err);
de->inode = 0;
- err = dir_commit_chunk(page, from, to);
+ err = dir_commit_chunk(page, pos, SYSV_DIRSIZE);
dir_put_page(page);
inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
mark_inode_dirty(inode);
@@ -263,12 +270,13 @@ int sysv_make_empty(struct inode *inode, struct inode *dir)
if (!page)
return -ENOMEM;
- kmap(page);
- err = mapping->a_ops->prepare_write(NULL, page, 0, 2 * SYSV_DIRSIZE);
+ err = __sysv_write_begin(NULL, mapping, 0, 2 * SYSV_DIRSIZE,
+ AOP_FLAG_UNINTERRUPTIBLE, &page, NULL);
if (err) {
unlock_page(page);
goto fail;
}
+ kmap(page);
base = (char*)page_address(page);
memset(base, 0, PAGE_CACHE_SIZE);
@@ -280,9 +288,9 @@ int sysv_make_empty(struct inode *inode, struct inode *dir)
de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), dir->i_ino);
strcpy(de->name,"..");
+ kunmap(page);
err = dir_commit_chunk(page, 0, 2 * SYSV_DIRSIZE);
fail:
- kunmap(page);
page_cache_release(page);
return err;
}
@@ -336,16 +344,18 @@ not_empty:
void sysv_set_link(struct sysv_dir_entry *de, struct page *page,
struct inode *inode)
{
- struct inode *dir = (struct inode*)page->mapping->host;
- unsigned from = (char *)de-(char*)page_address(page);
- unsigned to = from + SYSV_DIRSIZE;
+ struct address_space *mapping = page->mapping;
+ struct inode *dir = mapping->host;
+ loff_t pos = page_offset(page) +
+ (char *)de-(char*)page_address(page);
int err;
lock_page(page);
- err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
+ err = __sysv_write_begin(NULL, mapping, pos, SYSV_DIRSIZE,
+ AOP_FLAG_UNINTERRUPTIBLE, &page, NULL);
BUG_ON(err);
de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino);
- err = dir_commit_chunk(page, from, to);
+ err = dir_commit_chunk(page, pos, SYSV_DIRSIZE);
dir_put_page(page);
dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
mark_inode_dirty(dir);
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c
index 7c4e5d302abb..81ec6c548c07 100644
--- a/fs/sysv/inode.c
+++ b/fs/sysv/inode.c
@@ -318,7 +318,7 @@ static void sysv_destroy_inode(struct inode *inode)
kmem_cache_free(sysv_inode_cachep, SYSV_I(inode));
}
-static void init_once(void *p, struct kmem_cache *cachep, unsigned long flags)
+static void init_once(struct kmem_cache *cachep, void *p)
{
struct sysv_inode_info *si = (struct sysv_inode_info *)p;
diff --git a/fs/sysv/itree.c b/fs/sysv/itree.c
index f2bcccd1d6fc..f042eec464c2 100644
--- a/fs/sysv/itree.c
+++ b/fs/sysv/itree.c
@@ -453,23 +453,38 @@ static int sysv_writepage(struct page *page, struct writeback_control *wbc)
{
return block_write_full_page(page,get_block,wbc);
}
+
static int sysv_readpage(struct file *file, struct page *page)
{
return block_read_full_page(page,get_block);
}
-static int sysv_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
+
+int __sysv_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
{
- return block_prepare_write(page,from,to,get_block);
+ return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
+ get_block);
}
+
+static int sysv_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
+{
+ *pagep = NULL;
+ return __sysv_write_begin(file, mapping, pos, len, flags, pagep, fsdata);
+}
+
static sector_t sysv_bmap(struct address_space *mapping, sector_t block)
{
return generic_block_bmap(mapping,block,get_block);
}
+
const struct address_space_operations sysv_aops = {
.readpage = sysv_readpage,
.writepage = sysv_writepage,
.sync_page = block_sync_page,
- .prepare_write = sysv_prepare_write,
- .commit_write = generic_commit_write,
+ .write_begin = sysv_write_begin,
+ .write_end = generic_write_end,
.bmap = sysv_bmap
};
diff --git a/fs/sysv/sysv.h b/fs/sysv/sysv.h
index 5b4fedf17cc4..64c03bdf06a5 100644
--- a/fs/sysv/sysv.h
+++ b/fs/sysv/sysv.h
@@ -136,6 +136,9 @@ extern unsigned long sysv_count_free_blocks(struct super_block *);
/* itree.c */
extern void sysv_truncate(struct inode *);
+extern int __sysv_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata);
/* inode.c */
extern int sysv_write_inode(struct inode *, int);
diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c
index 87e87dcd3f9c..ab26176f6b91 100644
--- a/fs/udf/balloc.c
+++ b/fs/udf/balloc.c
@@ -689,7 +689,7 @@ static int udf_table_new_block(struct super_block *sb,
uint32_t spread = 0xFFFFFFFF, nspread = 0xFFFFFFFF;
uint32_t newblock = 0, adsize;
uint32_t elen, goal_elen = 0;
- kernel_lb_addr eloc, goal_eloc;
+ kernel_lb_addr eloc, uninitialized_var(goal_eloc);
struct extent_position epos, goal_epos;
int8_t etype;
diff --git a/fs/udf/file.c b/fs/udf/file.c
index 5d7a4ea27753..7c7a1b39d56c 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -76,36 +76,29 @@ static int udf_adinicb_writepage(struct page *page, struct writeback_control *wb
return 0;
}
-static int udf_adinicb_prepare_write(struct file *file, struct page *page,
- unsigned offset, unsigned to)
+static int udf_adinicb_write_end(struct file *file,
+ struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata)
{
- kmap(page);
- return 0;
-}
-
-static int udf_adinicb_commit_write(struct file *file, struct page *page,
- unsigned offset, unsigned to)
-{
- struct inode *inode = page->mapping->host;
- char *kaddr = page_address(page);
+ struct inode *inode = mapping->host;
+ unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
+ char *kaddr;
+ kaddr = kmap_atomic(page, KM_USER0);
memcpy(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode) + offset,
- kaddr + offset, to - offset);
- mark_inode_dirty(inode);
- SetPageUptodate(page);
- kunmap(page);
- /* only one page here */
- if (to > inode->i_size)
- inode->i_size = to;
- return 0;
+ kaddr + offset, copied);
+ kunmap_atomic(kaddr, KM_USER0);
+
+ return simple_write_end(file, mapping, pos, len, copied, page, fsdata);
}
const struct address_space_operations udf_adinicb_aops = {
.readpage = udf_adinicb_readpage,
.writepage = udf_adinicb_writepage,
.sync_page = block_sync_page,
- .prepare_write = udf_adinicb_prepare_write,
- .commit_write = udf_adinicb_commit_write,
+ .write_begin = simple_write_begin,
+ .write_end = udf_adinicb_write_end,
};
static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 1652b2c665bb..6ff8151984cf 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -133,10 +133,13 @@ static int udf_readpage(struct file *file, struct page *page)
return block_read_full_page(page, udf_get_block);
}
-static int udf_prepare_write(struct file *file, struct page *page,
- unsigned from, unsigned to)
+static int udf_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
{
- return block_prepare_write(page, from, to, udf_get_block);
+ *pagep = NULL;
+ return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
+ udf_get_block);
}
static sector_t udf_bmap(struct address_space *mapping, sector_t block)
@@ -148,8 +151,8 @@ const struct address_space_operations udf_aops = {
.readpage = udf_readpage,
.writepage = udf_writepage,
.sync_page = block_sync_page,
- .prepare_write = udf_prepare_write,
- .commit_write = generic_commit_write,
+ .write_begin = udf_write_begin,
+ .write_end = generic_write_end,
.bmap = udf_bmap,
};
diff --git a/fs/udf/super.c b/fs/udf/super.c
index c68a6e730b97..4360c7a05743 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -134,7 +134,7 @@ static void udf_destroy_inode(struct inode *inode)
kmem_cache_free(udf_inode_cachep, UDF_I(inode));
}
-static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags)
+static void init_once(struct kmem_cache *cachep, void *foo)
{
struct udf_inode_info *ei = (struct udf_inode_info *)foo;
@@ -913,8 +913,7 @@ static int udf_load_partdesc(struct super_block *sb, struct buffer_head *bh)
UDF_SB_PARTMAPS(sb)[i].s_uspace.s_table =
udf_iget(sb, loc);
if (!UDF_SB_PARTMAPS(sb)[i].s_uspace.s_table) {
- udf_debug("cannot load unallocSpaceTable (part %d)\n",
- i);
+ udf_debug("cannot load unallocSpaceTable (part %d)\n", i);
return 1;
}
UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_UNALLOC_TABLE;
@@ -944,8 +943,7 @@ static int udf_load_partdesc(struct super_block *sb, struct buffer_head *bh)
UDF_SB_PARTMAPS(sb)[i].s_fspace.s_table =
udf_iget(sb, loc);
if (!UDF_SB_PARTMAPS(sb)[i].s_fspace.s_table) {
- udf_debug("cannot load freedSpaceTable (part %d)\n",
- i);
+ udf_debug("cannot load freedSpaceTable (part %d)\n", i);
return 1;
}
UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_FREED_TABLE;
@@ -1293,19 +1291,16 @@ static int udf_load_partition(struct super_block *sb, kernel_lb_addr *fileset)
if (!UDF_SB_LASTBLOCK(sb)) {
udf_debug("Unable to determine Lastblock (For "
- "Virtual Partition)\n");
+ "Virtual Partition)\n");
return 1;
}
for (j = 0; j < UDF_SB_NUMPARTS(sb); j++) {
- if (j != i && UDF_SB_PARTVSN(sb, i) ==
- UDF_SB_PARTVSN(sb, j) &&
- UDF_SB_PARTNUM(sb, i) ==
- UDF_SB_PARTNUM(sb, j)) {
+ if (j != i &&
+ UDF_SB_PARTVSN(sb, i) == UDF_SB_PARTVSN(sb, j) &&
+ UDF_SB_PARTNUM(sb, i) == UDF_SB_PARTNUM(sb, j)) {
ino.partitionReferenceNum = j;
- ino.logicalBlockNum =
- UDF_SB_LASTBLOCK(sb) -
- UDF_SB_PARTROOT(sb, j);
+ ino.logicalBlockNum = UDF_SB_LASTBLOCK(sb) - UDF_SB_PARTROOT(sb, j);
break;
}
}
@@ -1318,9 +1313,9 @@ static int udf_load_partition(struct super_block *sb, kernel_lb_addr *fileset)
if (UDF_SB_PARTTYPE(sb, i) == UDF_VIRTUAL_MAP15) {
UDF_SB_TYPEVIRT(sb, i).s_start_offset =
- udf_ext0_offset(UDF_SB_VAT(sb));
+ udf_ext0_offset(UDF_SB_VAT(sb));
UDF_SB_TYPEVIRT(sb, i).s_num_entries =
- (UDF_SB_VAT(sb)->i_size - 36) >> 2;
+ (UDF_SB_VAT(sb)->i_size - 36) >> 2;
} else if (UDF_SB_PARTTYPE(sb, i) == UDF_VIRTUAL_MAP20) {
struct buffer_head *bh = NULL;
uint32_t pos;
@@ -1330,19 +1325,15 @@ static int udf_load_partition(struct super_block *sb, kernel_lb_addr *fileset)
if (!bh)
return 1;
UDF_SB_TYPEVIRT(sb, i).s_start_offset =
- le16_to_cpu(((struct
- virtualAllocationTable20 *)bh->b_data +
- udf_ext0_offset(UDF_SB_VAT(sb)))->
- lengthHeader) +
- udf_ext0_offset(UDF_SB_VAT(sb));
- UDF_SB_TYPEVIRT(sb, i).s_num_entries =
- (UDF_SB_VAT(sb)->i_size -
- UDF_SB_TYPEVIRT(sb, i).s_start_offset) >> 2;
+ le16_to_cpu(((struct virtualAllocationTable20 *)bh->b_data +
+ udf_ext0_offset(UDF_SB_VAT(sb)))->lengthHeader) +
+ udf_ext0_offset(UDF_SB_VAT(sb));
+ UDF_SB_TYPEVIRT(sb, i).s_num_entries = (UDF_SB_VAT(sb)->i_size -
+ UDF_SB_TYPEVIRT(sb, i).s_start_offset) >> 2;
brelse(bh);
}
UDF_SB_PARTROOT(sb, i) = udf_get_pblock(sb, 0, i, 0);
- UDF_SB_PARTLEN(sb, i) = UDF_SB_PARTLEN(sb,
- ino.partitionReferenceNum);
+ UDF_SB_PARTLEN(sb, i) = UDF_SB_PARTLEN(sb, ino.partitionReferenceNum);
}
}
return 0;
@@ -1357,21 +1348,17 @@ static void udf_open_lvid(struct super_block *sb)
UDF_SB_LVIDIU(sb)->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
UDF_SB_LVIDIU(sb)->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
if (udf_time_to_stamp(&cpu_time, CURRENT_TIME))
- UDF_SB_LVID(sb)->recordingDateAndTime =
- cpu_to_lets(cpu_time);
+ UDF_SB_LVID(sb)->recordingDateAndTime = cpu_to_lets(cpu_time);
UDF_SB_LVID(sb)->integrityType = LVID_INTEGRITY_TYPE_OPEN;
- UDF_SB_LVID(sb)->descTag.descCRC =
- cpu_to_le16(udf_crc((char *)UDF_SB_LVID(sb) + sizeof(tag),
- le16_to_cpu(UDF_SB_LVID(sb)->descTag.
- descCRCLength), 0));
+ UDF_SB_LVID(sb)->descTag.descCRC = cpu_to_le16(udf_crc((char *)UDF_SB_LVID(sb) + sizeof(tag),
+ le16_to_cpu(UDF_SB_LVID(sb)->descTag.descCRCLength), 0));
UDF_SB_LVID(sb)->descTag.tagChecksum = 0;
for (i = 0; i < 16; i++)
if (i != 4)
UDF_SB_LVID(sb)->descTag.tagChecksum +=
- ((uint8_t *) &
- (UDF_SB_LVID(sb)->descTag))[i];
+ ((uint8_t *) &(UDF_SB_LVID(sb)->descTag))[i];
mark_buffer_dirty(UDF_SB_LVIDBH(sb));
}
diff --git a/fs/udf/udftime.c b/fs/udf/udftime.c
index 3fd80eb66af3..adcb87c2da7e 100644
--- a/fs/udf/udftime.c
+++ b/fs/udf/udftime.c
@@ -108,10 +108,10 @@ time_t *udf_stamp_to_time(time_t *dest, long *dest_usec, kernel_timestamp src)
*dest = year_seconds[src.year - EPOCH_YEAR];
*dest -= offset * 60;
- yday = ((__mon_yday[__isleap (src.year)]
- [src.month - 1]) + (src.day - 1));
- *dest += ( ( (yday * 24) + src.hour ) * 60 + src.minute ) * 60 + src.second;
- *dest_usec = src.centiseconds * 10000 + src.hundredsOfMicroseconds * 100 + src.microseconds;
+ yday = ((__mon_yday[__isleap(src.year)][src.month - 1]) + src.day - 1);
+ *dest += (((yday * 24) + src.hour) * 60 + src.minute) * 60 + src.second;
+ *dest_usec = src.centiseconds * 10000 +
+ src.hundredsOfMicroseconds * 100 + src.microseconds;
return dest;
}
diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c
index 841ac25fd950..f63a09ce8683 100644
--- a/fs/ufs/balloc.c
+++ b/fs/ufs/balloc.c
@@ -19,6 +19,7 @@
#include <linux/bitops.h>
#include <asm/byteorder.h>
+#include "ufs.h"
#include "swab.h"
#include "util.h"
diff --git a/fs/ufs/cylinder.c b/fs/ufs/cylinder.c
index 09c39e5e6386..2a815665644f 100644
--- a/fs/ufs/cylinder.c
+++ b/fs/ufs/cylinder.c
@@ -17,6 +17,7 @@
#include <asm/byteorder.h>
+#include "ufs.h"
#include "swab.h"
#include "util.h"
diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c
index 154452172f43..30f8c2bb0c3e 100644
--- a/fs/ufs/dir.c
+++ b/fs/ufs/dir.c
@@ -19,7 +19,9 @@
#include <linux/time.h>
#include <linux/fs.h>
#include <linux/ufs_fs.h>
+#include <linux/swap.h>
+#include "ufs.h"
#include "swab.h"
#include "util.h"
@@ -38,12 +40,18 @@ static inline int ufs_match(struct super_block *sb, int len,
return !memcmp(name, de->d_name, len);
}
-static int ufs_commit_chunk(struct page *page, unsigned from, unsigned to)
+static int ufs_commit_chunk(struct page *page, loff_t pos, unsigned len)
{
- struct inode *dir = page->mapping->host;
+ struct address_space *mapping = page->mapping;
+ struct inode *dir = mapping->host;
int err = 0;
+
dir->i_version++;
- page->mapping->a_ops->commit_write(NULL, page, from, to);
+ block_write_end(NULL, mapping, pos, len, len, page, NULL);
+ if (pos+len > dir->i_size) {
+ i_size_write(dir, pos+len);
+ mark_inode_dirty(dir);
+ }
if (IS_DIRSYNC(dir))
err = write_one_page(page, 1);
else
@@ -81,16 +89,20 @@ ino_t ufs_inode_by_name(struct inode *dir, struct dentry *dentry)
void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de,
struct page *page, struct inode *inode)
{
- unsigned from = (char *) de - (char *) page_address(page);
- unsigned to = from + fs16_to_cpu(dir->i_sb, de->d_reclen);
+ loff_t pos = page_offset(page) +
+ (char *) de - (char *) page_address(page);
+ unsigned len = fs16_to_cpu(dir->i_sb, de->d_reclen);
int err;
lock_page(page);
- err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
+ err = __ufs_write_begin(NULL, page->mapping, pos, len,
+ AOP_FLAG_UNINTERRUPTIBLE, &page, NULL);
BUG_ON(err);
+
de->d_ino = cpu_to_fs32(dir->i_sb, inode->i_ino);
ufs_set_de_type(dir->i_sb, de, inode->i_mode);
- err = ufs_commit_chunk(page, from, to);
+
+ err = ufs_commit_chunk(page, pos, len);
ufs_put_page(page);
dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
mark_inode_dirty(dir);
@@ -312,7 +324,7 @@ int ufs_add_link(struct dentry *dentry, struct inode *inode)
unsigned long npages = ufs_dir_pages(dir);
unsigned long n;
char *kaddr;
- unsigned from, to;
+ loff_t pos;
int err;
UFSD("ENTER, name %s, namelen %u\n", name, namelen);
@@ -367,9 +379,10 @@ int ufs_add_link(struct dentry *dentry, struct inode *inode)
return -EINVAL;
got_it:
- from = (char*)de - (char*)page_address(page);
- to = from + rec_len;
- err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
+ pos = page_offset(page) +
+ (char*)de - (char*)page_address(page);
+ err = __ufs_write_begin(NULL, page->mapping, pos, rec_len,
+ AOP_FLAG_UNINTERRUPTIBLE, &page, NULL);
if (err)
goto out_unlock;
if (de->d_ino) {
@@ -386,7 +399,7 @@ got_it:
de->d_ino = cpu_to_fs32(sb, inode->i_ino);
ufs_set_de_type(sb, de, inode->i_mode);
- err = ufs_commit_chunk(page, from, to);
+ err = ufs_commit_chunk(page, pos, rec_len);
dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
mark_inode_dirty(dir);
@@ -509,6 +522,7 @@ int ufs_delete_entry(struct inode *inode, struct ufs_dir_entry *dir,
char *kaddr = page_address(page);
unsigned from = ((char*)dir - kaddr) & ~(UFS_SB(sb)->s_uspi->s_dirblksize - 1);
unsigned to = ((char*)dir - kaddr) + fs16_to_cpu(sb, dir->d_reclen);
+ loff_t pos;
struct ufs_dir_entry *pde = NULL;
struct ufs_dir_entry *de = (struct ufs_dir_entry *) (kaddr + from);
int err;
@@ -532,13 +546,16 @@ int ufs_delete_entry(struct inode *inode, struct ufs_dir_entry *dir,
}
if (pde)
from = (char*)pde - (char*)page_address(page);
+
+ pos = page_offset(page) + from;
lock_page(page);
- err = mapping->a_ops->prepare_write(NULL, page, from, to);
+ err = __ufs_write_begin(NULL, mapping, pos, to - from,
+ AOP_FLAG_UNINTERRUPTIBLE, &page, NULL);
BUG_ON(err);
if (pde)
- pde->d_reclen = cpu_to_fs16(sb, to-from);
+ pde->d_reclen = cpu_to_fs16(sb, to - from);
dir->d_ino = 0;
- err = ufs_commit_chunk(page, from, to);
+ err = ufs_commit_chunk(page, pos, to - from);
inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
mark_inode_dirty(inode);
out:
@@ -559,14 +576,15 @@ int ufs_make_empty(struct inode * inode, struct inode *dir)
if (!page)
return -ENOMEM;
- kmap(page);
- err = mapping->a_ops->prepare_write(NULL, page, 0, chunk_size);
+
+ err = __ufs_write_begin(NULL, mapping, 0, chunk_size,
+ AOP_FLAG_UNINTERRUPTIBLE, &page, NULL);
if (err) {
unlock_page(page);
goto fail;
}
-
+ kmap(page);
base = (char*)page_address(page);
memset(base, 0, PAGE_CACHE_SIZE);
@@ -584,10 +602,10 @@ int ufs_make_empty(struct inode * inode, struct inode *dir)
de->d_reclen = cpu_to_fs16(sb, chunk_size - UFS_DIR_REC_LEN(1));
ufs_set_de_namlen(sb, de, 2);
strcpy (de->d_name, "..");
+ kunmap(page);
err = ufs_commit_chunk(page, 0, chunk_size);
fail:
- kunmap(page);
page_cache_release(page);
return err;
}
diff --git a/fs/ufs/file.c b/fs/ufs/file.c
index 6705d74c6d2d..a46c97bf023f 100644
--- a/fs/ufs/file.c
+++ b/fs/ufs/file.c
@@ -27,6 +27,9 @@
#include <linux/ufs_fs.h>
#include <linux/buffer_head.h> /* for sync_mapping_buffers() */
+#include "ufs.h"
+
+
static int ufs_sync_file(struct file *file, struct dentry *dentry, int datasync)
{
struct inode *inode = dentry->d_inode;
diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c
index c28a8b6f2feb..7e260bc0d94f 100644
--- a/fs/ufs/ialloc.c
+++ b/fs/ufs/ialloc.c
@@ -34,6 +34,7 @@
#include <linux/bitops.h>
#include <asm/byteorder.h>
+#include "ufs.h"
#include "swab.h"
#include "util.h"
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
index f18b79122fa3..4320782761ae 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -38,6 +38,7 @@
#include <linux/smp_lock.h>
#include <linux/buffer_head.h>
+#include "ufs.h"
#include "swab.h"
#include "util.h"
@@ -558,24 +559,39 @@ static int ufs_writepage(struct page *page, struct writeback_control *wbc)
{
return block_write_full_page(page,ufs_getfrag_block,wbc);
}
+
static int ufs_readpage(struct file *file, struct page *page)
{
return block_read_full_page(page,ufs_getfrag_block);
}
-static int ufs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
+
+int __ufs_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
{
- return block_prepare_write(page,from,to,ufs_getfrag_block);
+ return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
+ ufs_getfrag_block);
}
+
+static int ufs_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
+{
+ *pagep = NULL;
+ return __ufs_write_begin(file, mapping, pos, len, flags, pagep, fsdata);
+}
+
static sector_t ufs_bmap(struct address_space *mapping, sector_t block)
{
return generic_block_bmap(mapping,block,ufs_getfrag_block);
}
+
const struct address_space_operations ufs_aops = {
.readpage = ufs_readpage,
.writepage = ufs_writepage,
.sync_page = block_sync_page,
- .prepare_write = ufs_prepare_write,
- .commit_write = generic_commit_write,
+ .write_begin = ufs_write_begin,
+ .write_end = generic_write_end,
.bmap = ufs_bmap
};
diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c
index a059ccd064ea..d8bfbee2fe2b 100644
--- a/fs/ufs/namei.c
+++ b/fs/ufs/namei.c
@@ -31,7 +31,7 @@
#include <linux/fs.h>
#include <linux/ufs_fs.h>
#include <linux/smp_lock.h>
-#include "swab.h" /* will go away - see comment in mknod() */
+#include "ufs.h"
#include "util.h"
static inline int ufs_add_nondir(struct dentry *dentry, struct inode *inode)
@@ -110,7 +110,6 @@ static int ufs_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_t
err = PTR_ERR(inode);
if (!IS_ERR(inode)) {
init_special_inode(inode, mode, rdev);
- /* NOTE: that'll go when we get wide dev_t */
ufs_set_inode_dev(inode->i_sb, UFS_I(inode), rdev);
mark_inode_dirty(inode);
lock_kernel();
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index 38eb0b7a1f3d..c78c04fd993f 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -88,7 +88,10 @@
#include <linux/buffer_head.h>
#include <linux/vfs.h>
#include <linux/log2.h>
+#include <linux/mount.h>
+#include <linux/seq_file.h>
+#include "ufs.h"
#include "swab.h"
#include "util.h"
@@ -286,16 +289,28 @@ void ufs_warning (struct super_block * sb, const char * function,
}
enum {
- Opt_type_old, Opt_type_sunx86, Opt_type_sun, Opt_type_44bsd,
- Opt_type_ufs2, Opt_type_hp, Opt_type_nextstepcd, Opt_type_nextstep,
- Opt_type_openstep, Opt_onerror_panic, Opt_onerror_lock,
- Opt_onerror_umount, Opt_onerror_repair, Opt_err
+ Opt_type_old = UFS_MOUNT_UFSTYPE_OLD,
+ Opt_type_sunx86 = UFS_MOUNT_UFSTYPE_SUNx86,
+ Opt_type_sun = UFS_MOUNT_UFSTYPE_SUN,
+ Opt_type_sunos = UFS_MOUNT_UFSTYPE_SUNOS,
+ Opt_type_44bsd = UFS_MOUNT_UFSTYPE_44BSD,
+ Opt_type_ufs2 = UFS_MOUNT_UFSTYPE_UFS2,
+ Opt_type_hp = UFS_MOUNT_UFSTYPE_HP,
+ Opt_type_nextstepcd = UFS_MOUNT_UFSTYPE_NEXTSTEP_CD,
+ Opt_type_nextstep = UFS_MOUNT_UFSTYPE_NEXTSTEP,
+ Opt_type_openstep = UFS_MOUNT_UFSTYPE_OPENSTEP,
+ Opt_onerror_panic = UFS_MOUNT_ONERROR_PANIC,
+ Opt_onerror_lock = UFS_MOUNT_ONERROR_LOCK,
+ Opt_onerror_umount = UFS_MOUNT_ONERROR_UMOUNT,
+ Opt_onerror_repair = UFS_MOUNT_ONERROR_REPAIR,
+ Opt_err
};
static match_table_t tokens = {
{Opt_type_old, "ufstype=old"},
{Opt_type_sunx86, "ufstype=sunx86"},
{Opt_type_sun, "ufstype=sun"},
+ {Opt_type_sunos, "ufstype=sunos"},
{Opt_type_44bsd, "ufstype=44bsd"},
{Opt_type_ufs2, "ufstype=ufs2"},
{Opt_type_ufs2, "ufstype=5xbsd"},
@@ -303,6 +318,7 @@ static match_table_t tokens = {
{Opt_type_nextstepcd, "ufstype=nextstep-cd"},
{Opt_type_nextstep, "ufstype=nextstep"},
{Opt_type_openstep, "ufstype=openstep"},
+/*end of possible ufs types */
{Opt_onerror_panic, "onerror=panic"},
{Opt_onerror_lock, "onerror=lock"},
{Opt_onerror_umount, "onerror=umount"},
@@ -339,6 +355,10 @@ static int ufs_parse_options (char * options, unsigned * mount_options)
ufs_clear_opt (*mount_options, UFSTYPE);
ufs_set_opt (*mount_options, UFSTYPE_SUN);
break;
+ case Opt_type_sunos:
+ ufs_clear_opt(*mount_options, UFSTYPE);
+ ufs_set_opt(*mount_options, UFSTYPE_SUNOS);
+ break;
case Opt_type_44bsd:
ufs_clear_opt (*mount_options, UFSTYPE);
ufs_set_opt (*mount_options, UFSTYPE_44BSD);
@@ -654,8 +674,8 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
ufs_set_opt (sbi->s_mount_opt, UFSTYPE_OLD);
}
- sbi->s_uspi = uspi =
- kmalloc (sizeof(struct ufs_sb_private_info), GFP_KERNEL);
+ uspi = kzalloc(sizeof(struct ufs_sb_private_info), GFP_KERNEL);
+ sbi->s_uspi = uspi;
if (!uspi)
goto failed;
uspi->s_dirblksize = UFS_SECTOR_SIZE;
@@ -692,10 +712,22 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
uspi->s_fshift = 10;
uspi->s_sbsize = super_block_size = 2048;
uspi->s_sbbase = 0;
- uspi->s_maxsymlinklen = 56;
+ uspi->s_maxsymlinklen = 0; /* Not supported on disk */
flags |= UFS_DE_OLD | UFS_UID_EFT | UFS_ST_SUN | UFS_CG_SUN;
break;
+ case UFS_MOUNT_UFSTYPE_SUNOS:
+ UFSD(("ufstype=sunos\n"))
+ uspi->s_fsize = block_size = 1024;
+ uspi->s_fmask = ~(1024 - 1);
+ uspi->s_fshift = 10;
+ uspi->s_sbsize = 2048;
+ super_block_size = 2048;
+ uspi->s_sbbase = 0;
+ uspi->s_maxsymlinklen = 0; /* Not supported on disk */
+ flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_SUNOS | UFS_CG_SUN;
+ break;
+
case UFS_MOUNT_UFSTYPE_SUNx86:
UFSD("ufstype=sunx86\n");
uspi->s_fsize = block_size = 1024;
@@ -703,7 +735,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
uspi->s_fshift = 10;
uspi->s_sbsize = super_block_size = 2048;
uspi->s_sbbase = 0;
- uspi->s_maxsymlinklen = 56;
+ uspi->s_maxsymlinklen = 0; /* Not supported on disk */
flags |= UFS_DE_OLD | UFS_UID_EFT | UFS_ST_SUNx86 | UFS_CG_SUN;
break;
@@ -805,11 +837,18 @@ again:
if (!ubh)
goto failed;
-
usb1 = ubh_get_usb_first(uspi);
usb2 = ubh_get_usb_second(uspi);
usb3 = ubh_get_usb_third(uspi);
+ /* Sort out mod used on SunOS 4.1.3 for fs_state */
+ uspi->s_postblformat = fs32_to_cpu(sb, usb3->fs_postblformat);
+ if (((flags & UFS_ST_MASK) == UFS_ST_SUNOS) &&
+ (uspi->s_postblformat != UFS_42POSTBLFMT)) {
+ flags &= ~UFS_ST_MASK;
+ flags |= UFS_ST_SUN;
+ }
+
/*
* Check ufs magic number
*/
@@ -903,8 +942,9 @@ magic_found:
*/
if (((flags & UFS_ST_MASK) == UFS_ST_44BSD) ||
((flags & UFS_ST_MASK) == UFS_ST_OLD) ||
- (((flags & UFS_ST_MASK) == UFS_ST_SUN ||
- (flags & UFS_ST_MASK) == UFS_ST_SUNx86) &&
+ (((flags & UFS_ST_MASK) == UFS_ST_SUN ||
+ (flags & UFS_ST_MASK) == UFS_ST_SUNOS ||
+ (flags & UFS_ST_MASK) == UFS_ST_SUNx86) &&
(ufs_get_fs_state(sb, usb1, usb3) == (UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time))))) {
switch(usb1->fs_clean) {
case UFS_FSCLEAN:
@@ -995,7 +1035,6 @@ magic_found:
uspi->s_contigsumsize = fs32_to_cpu(sb, usb3->fs_un2.fs_44.fs_contigsumsize);
uspi->s_qbmask = ufs_get_fs_qbmask(sb, usb3);
uspi->s_qfmask = ufs_get_fs_qfmask(sb, usb3);
- uspi->s_postblformat = fs32_to_cpu(sb, usb3->fs_postblformat);
uspi->s_nrpos = fs32_to_cpu(sb, usb3->fs_nrpos);
uspi->s_postbloff = fs32_to_cpu(sb, usb3->fs_postbloff);
uspi->s_rotbloff = fs32_to_cpu(sb, usb3->fs_rotbloff);
@@ -1077,6 +1116,7 @@ static void ufs_write_super(struct super_block *sb)
if (!(sb->s_flags & MS_RDONLY)) {
usb1->fs_time = cpu_to_fs32(sb, get_seconds());
if ((flags & UFS_ST_MASK) == UFS_ST_SUN
+ || (flags & UFS_ST_MASK) == UFS_ST_SUNOS
|| (flags & UFS_ST_MASK) == UFS_ST_SUNx86)
ufs_set_fs_state(sb, usb1, usb3,
UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time));
@@ -1146,6 +1186,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
ufs_put_super_internal(sb);
usb1->fs_time = cpu_to_fs32(sb, get_seconds());
if ((flags & UFS_ST_MASK) == UFS_ST_SUN
+ || (flags & UFS_ST_MASK) == UFS_ST_SUNOS
|| (flags & UFS_ST_MASK) == UFS_ST_SUNx86)
ufs_set_fs_state(sb, usb1, usb3,
UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time));
@@ -1162,6 +1203,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
return -EINVAL;
#else
if (ufstype != UFS_MOUNT_UFSTYPE_SUN &&
+ ufstype != UFS_MOUNT_UFSTYPE_SUNOS &&
ufstype != UFS_MOUNT_UFSTYPE_44BSD &&
ufstype != UFS_MOUNT_UFSTYPE_SUNx86 &&
ufstype != UFS_MOUNT_UFSTYPE_UFS2) {
@@ -1179,6 +1221,26 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
return 0;
}
+static int ufs_show_options(struct seq_file *seq, struct vfsmount *vfs)
+{
+ struct ufs_sb_info *sbi = UFS_SB(vfs->mnt_sb);
+ unsigned mval = sbi->s_mount_opt & UFS_MOUNT_UFSTYPE;
+ struct match_token *tp = tokens;
+
+ while (tp->token != Opt_onerror_panic && tp->token != mval)
+ ++tp;
+ BUG_ON(tp->token == Opt_onerror_panic);
+ seq_printf(seq, ",%s", tp->pattern);
+
+ mval = sbi->s_mount_opt & UFS_MOUNT_ONERROR;
+ while (tp->token != Opt_err && tp->token != mval)
+ ++tp;
+ BUG_ON(tp->token == Opt_err);
+ seq_printf(seq, ",%s", tp->pattern);
+
+ return 0;
+}
+
static int ufs_statfs(struct dentry *dentry, struct kstatfs *buf)
{
struct super_block *sb = dentry->d_sb;
@@ -1232,7 +1294,7 @@ static void ufs_destroy_inode(struct inode *inode)
kmem_cache_free(ufs_inode_cachep, UFS_I(inode));
}
-static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
+static void init_once(struct kmem_cache * cachep, void *foo)
{
struct ufs_inode_info *ei = (struct ufs_inode_info *) foo;
@@ -1271,6 +1333,7 @@ static const struct super_operations ufs_super_ops = {
.write_super = ufs_write_super,
.statfs = ufs_statfs,
.remount_fs = ufs_remount,
+ .show_options = ufs_show_options,
#ifdef CONFIG_QUOTA
.quota_read = ufs_quota_read,
.quota_write = ufs_quota_write,
diff --git a/fs/ufs/symlink.c b/fs/ufs/symlink.c
index d8549f807e80..43ac10e75a4a 100644
--- a/fs/ufs/symlink.c
+++ b/fs/ufs/symlink.c
@@ -28,6 +28,8 @@
#include <linux/fs.h>
#include <linux/namei.h>
#include <linux/ufs_fs.h>
+#include "ufs.h"
+
static void *ufs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c
index 79c54c85fb58..311ded34c2b2 100644
--- a/fs/ufs/truncate.c
+++ b/fs/ufs/truncate.c
@@ -46,6 +46,7 @@
#include <linux/blkdev.h>
#include <linux/sched.h>
+#include "ufs.h"
#include "swab.h"
#include "util.h"
diff --git a/fs/ufs/ufs.h b/fs/ufs/ufs.h
new file mode 100644
index 000000000000..7faa4cd71a27
--- /dev/null
+++ b/fs/ufs/ufs.h
@@ -0,0 +1,157 @@
+#ifndef _UFS_UFS_H
+#define _UFS_UFS_H 1
+
+#define UFS_MAX_GROUP_LOADED 8
+#define UFS_CGNO_EMPTY ((unsigned)-1)
+
+struct ufs_sb_private_info;
+struct ufs_cg_private_info;
+struct ufs_csum;
+
+struct ufs_sb_info {
+ struct ufs_sb_private_info * s_uspi;
+ struct ufs_csum * s_csp;
+ unsigned s_bytesex;
+ unsigned s_flags;
+ struct buffer_head ** s_ucg;
+ struct ufs_cg_private_info * s_ucpi[UFS_MAX_GROUP_LOADED];
+ unsigned s_cgno[UFS_MAX_GROUP_LOADED];
+ unsigned short s_cg_loaded;
+ unsigned s_mount_opt;
+};
+
+struct ufs_inode_info {
+ union {
+ __fs32 i_data[15];
+ __u8 i_symlink[4*15];
+ __fs64 u2_i_data[15];
+ } i_u1;
+ __u32 i_flags;
+ __u32 i_shadow;
+ __u32 i_unused1;
+ __u32 i_unused2;
+ __u32 i_oeftflag;
+ __u16 i_osync;
+ __u64 i_lastfrag;
+ __u32 i_dir_start_lookup;
+ struct inode vfs_inode;
+};
+
+/* mount options */
+#define UFS_MOUNT_ONERROR 0x0000000F
+#define UFS_MOUNT_ONERROR_PANIC 0x00000001
+#define UFS_MOUNT_ONERROR_LOCK 0x00000002
+#define UFS_MOUNT_ONERROR_UMOUNT 0x00000004
+#define UFS_MOUNT_ONERROR_REPAIR 0x00000008
+
+#define UFS_MOUNT_UFSTYPE 0x0000FFF0
+#define UFS_MOUNT_UFSTYPE_OLD 0x00000010
+#define UFS_MOUNT_UFSTYPE_44BSD 0x00000020
+#define UFS_MOUNT_UFSTYPE_SUN 0x00000040
+#define UFS_MOUNT_UFSTYPE_NEXTSTEP 0x00000080
+#define UFS_MOUNT_UFSTYPE_NEXTSTEP_CD 0x00000100
+#define UFS_MOUNT_UFSTYPE_OPENSTEP 0x00000200
+#define UFS_MOUNT_UFSTYPE_SUNx86 0x00000400
+#define UFS_MOUNT_UFSTYPE_HP 0x00000800
+#define UFS_MOUNT_UFSTYPE_UFS2 0x00001000
+#define UFS_MOUNT_UFSTYPE_SUNOS 0x00002000
+
+#define ufs_clear_opt(o,opt) o &= ~UFS_MOUNT_##opt
+#define ufs_set_opt(o,opt) o |= UFS_MOUNT_##opt
+#define ufs_test_opt(o,opt) ((o) & UFS_MOUNT_##opt)
+
+/*
+ * Debug code
+ */
+#ifdef CONFIG_UFS_DEBUG
+# define UFSD(f, a...) { \
+ printk ("UFSD (%s, %d): %s:", \
+ __FILE__, __LINE__, __FUNCTION__); \
+ printk (f, ## a); \
+ }
+#else
+# define UFSD(f, a...) /**/
+#endif
+
+/* balloc.c */
+extern void ufs_free_fragments (struct inode *, u64, unsigned);
+extern void ufs_free_blocks (struct inode *, u64, unsigned);
+extern u64 ufs_new_fragments(struct inode *, void *, u64, u64,
+ unsigned, int *, struct page *);
+
+/* cylinder.c */
+extern struct ufs_cg_private_info * ufs_load_cylinder (struct super_block *, unsigned);
+extern void ufs_put_cylinder (struct super_block *, unsigned);
+
+/* dir.c */
+extern const struct inode_operations ufs_dir_inode_operations;
+extern int ufs_add_link (struct dentry *, struct inode *);
+extern ino_t ufs_inode_by_name(struct inode *, struct dentry *);
+extern int ufs_make_empty(struct inode *, struct inode *);
+extern struct ufs_dir_entry *ufs_find_entry(struct inode *, struct dentry *, struct page **);
+extern int ufs_delete_entry(struct inode *, struct ufs_dir_entry *, struct page *);
+extern int ufs_empty_dir (struct inode *);
+extern struct ufs_dir_entry *ufs_dotdot(struct inode *, struct page **);
+extern void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de,
+ struct page *page, struct inode *inode);
+
+/* file.c */
+extern const struct inode_operations ufs_file_inode_operations;
+extern const struct file_operations ufs_file_operations;
+
+extern const struct address_space_operations ufs_aops;
+
+/* ialloc.c */
+extern void ufs_free_inode (struct inode *inode);
+extern struct inode * ufs_new_inode (struct inode *, int);
+
+/* inode.c */
+extern void ufs_read_inode (struct inode *);
+extern void ufs_put_inode (struct inode *);
+extern int ufs_write_inode (struct inode *, int);
+extern int ufs_sync_inode (struct inode *);
+extern void ufs_delete_inode (struct inode *);
+extern struct buffer_head * ufs_bread (struct inode *, unsigned, int, int *);
+extern int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create);
+
+/* namei.c */
+extern const struct file_operations ufs_dir_operations;
+
+/* super.c */
+extern void ufs_warning (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
+extern void ufs_error (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
+extern void ufs_panic (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
+
+/* symlink.c */
+extern const struct inode_operations ufs_fast_symlink_inode_operations;
+
+/* truncate.c */
+extern int ufs_truncate (struct inode *, loff_t);
+
+static inline struct ufs_sb_info *UFS_SB(struct super_block *sb)
+{
+ return sb->s_fs_info;
+}
+
+static inline struct ufs_inode_info *UFS_I(struct inode *inode)
+{
+ return container_of(inode, struct ufs_inode_info, vfs_inode);
+}
+
+/*
+ * Give cylinder group number for a file system block.
+ * Give cylinder group block number for a file system block.
+ */
+/* #define ufs_dtog(d) ((d) / uspi->s_fpg) */
+static inline u64 ufs_dtog(struct ufs_sb_private_info * uspi, u64 b)
+{
+ do_div(b, uspi->s_fpg);
+ return b;
+}
+/* #define ufs_dtogd(d) ((d) % uspi->s_fpg) */
+static inline u32 ufs_dtogd(struct ufs_sb_private_info * uspi, u64 b)
+{
+ return do_div(b, uspi->s_fpg);
+}
+
+#endif /* _UFS_UFS_H */
diff --git a/fs/ufs/util.c b/fs/ufs/util.c
index 84357f1ff0ec..410084dae389 100644
--- a/fs/ufs/util.c
+++ b/fs/ufs/util.c
@@ -11,6 +11,7 @@
#include <linux/ufs_fs.h>
#include <linux/buffer_head.h>
+#include "ufs.h"
#include "swab.h"
#include "util.h"
diff --git a/fs/ufs/util.h b/fs/ufs/util.h
index 06d344839c42..b26fc4dec1e7 100644
--- a/fs/ufs/util.h
+++ b/fs/ufs/util.h
@@ -38,6 +38,10 @@ ufs_get_fs_state(struct super_block *sb, struct ufs_super_block_first *usb1,
struct ufs_super_block_third *usb3)
{
switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
+ case UFS_ST_SUNOS:
+ if (fs32_to_cpu(sb, usb3->fs_postblformat) == UFS_42POSTBLFMT)
+ return fs32_to_cpu(sb, usb1->fs_u0.fs_sun.fs_state);
+ /* Fall Through to UFS_ST_SUN */
case UFS_ST_SUN:
return fs32_to_cpu(sb, usb3->fs_un2.fs_sun.fs_state);
case UFS_ST_SUNx86:
@@ -53,6 +57,12 @@ ufs_set_fs_state(struct super_block *sb, struct ufs_super_block_first *usb1,
struct ufs_super_block_third *usb3, s32 value)
{
switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
+ case UFS_ST_SUNOS:
+ if (fs32_to_cpu(sb, usb3->fs_postblformat == UFS_42POSTBLFMT)) {
+ usb1->fs_u0.fs_sun.fs_state = cpu_to_fs32(sb, value);
+ break;
+ }
+ /* Fall Through to UFS_ST_SUN */
case UFS_ST_SUN:
usb3->fs_un2.fs_sun.fs_state = cpu_to_fs32(sb, value);
break;
@@ -81,6 +91,7 @@ ufs_get_fs_qbmask(struct super_block *sb, struct ufs_super_block_third *usb3)
__fs64 tmp;
switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
+ case UFS_ST_SUNOS:
case UFS_ST_SUN:
((__fs32 *)&tmp)[0] = usb3->fs_un2.fs_sun.fs_qbmask[0];
((__fs32 *)&tmp)[1] = usb3->fs_un2.fs_sun.fs_qbmask[1];
@@ -104,6 +115,7 @@ ufs_get_fs_qfmask(struct super_block *sb, struct ufs_super_block_third *usb3)
__fs64 tmp;
switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
+ case UFS_ST_SUNOS:
case UFS_ST_SUN:
((__fs32 *)&tmp)[0] = usb3->fs_un2.fs_sun.fs_qfmask[0];
((__fs32 *)&tmp)[1] = usb3->fs_un2.fs_sun.fs_qfmask[1];
@@ -179,10 +191,12 @@ static inline u32
ufs_get_inode_uid(struct super_block *sb, struct ufs_inode *inode)
{
switch (UFS_SB(sb)->s_flags & UFS_UID_MASK) {
- case UFS_UID_EFT:
- return fs32_to_cpu(sb, inode->ui_u3.ui_sun.ui_uid);
case UFS_UID_44BSD:
return fs32_to_cpu(sb, inode->ui_u3.ui_44.ui_uid);
+ case UFS_UID_EFT:
+ if (inode->ui_u1.oldids.ui_suid == 0xFFFF)
+ return fs32_to_cpu(sb, inode->ui_u3.ui_sun.ui_uid);
+ /* Fall through */
default:
return fs16_to_cpu(sb, inode->ui_u1.oldids.ui_suid);
}
@@ -192,24 +206,31 @@ static inline void
ufs_set_inode_uid(struct super_block *sb, struct ufs_inode *inode, u32 value)
{
switch (UFS_SB(sb)->s_flags & UFS_UID_MASK) {
- case UFS_UID_EFT:
- inode->ui_u3.ui_sun.ui_uid = cpu_to_fs32(sb, value);
- break;
case UFS_UID_44BSD:
inode->ui_u3.ui_44.ui_uid = cpu_to_fs32(sb, value);
+ inode->ui_u1.oldids.ui_suid = cpu_to_fs16(sb, value);
+ break;
+ case UFS_UID_EFT:
+ inode->ui_u3.ui_sun.ui_uid = cpu_to_fs32(sb, value);
+ if (value > 0xFFFF)
+ value = 0xFFFF;
+ /* Fall through */
+ default:
+ inode->ui_u1.oldids.ui_suid = cpu_to_fs16(sb, value);
break;
}
- inode->ui_u1.oldids.ui_suid = cpu_to_fs16(sb, value);
}
static inline u32
ufs_get_inode_gid(struct super_block *sb, struct ufs_inode *inode)
{
switch (UFS_SB(sb)->s_flags & UFS_UID_MASK) {
- case UFS_UID_EFT:
- return fs32_to_cpu(sb, inode->ui_u3.ui_sun.ui_gid);
case UFS_UID_44BSD:
return fs32_to_cpu(sb, inode->ui_u3.ui_44.ui_gid);
+ case UFS_UID_EFT:
+ if (inode->ui_u1.oldids.ui_suid == 0xFFFF)
+ return fs32_to_cpu(sb, inode->ui_u3.ui_sun.ui_gid);
+ /* Fall through */
default:
return fs16_to_cpu(sb, inode->ui_u1.oldids.ui_sgid);
}
@@ -219,18 +240,26 @@ static inline void
ufs_set_inode_gid(struct super_block *sb, struct ufs_inode *inode, u32 value)
{
switch (UFS_SB(sb)->s_flags & UFS_UID_MASK) {
- case UFS_UID_EFT:
- inode->ui_u3.ui_sun.ui_gid = cpu_to_fs32(sb, value);
- break;
case UFS_UID_44BSD:
inode->ui_u3.ui_44.ui_gid = cpu_to_fs32(sb, value);
+ inode->ui_u1.oldids.ui_sgid = cpu_to_fs16(sb, value);
+ break;
+ case UFS_UID_EFT:
+ inode->ui_u3.ui_sun.ui_gid = cpu_to_fs32(sb, value);
+ if (value > 0xFFFF)
+ value = 0xFFFF;
+ /* Fall through */
+ default:
+ inode->ui_u1.oldids.ui_sgid = cpu_to_fs16(sb, value);
break;
}
- inode->ui_u1.oldids.ui_sgid = cpu_to_fs16(sb, value);
}
extern dev_t ufs_get_inode_dev(struct super_block *, struct ufs_inode_info *);
extern void ufs_set_inode_dev(struct super_block *, struct ufs_inode_info *, dev_t);
+extern int __ufs_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata);
/*
* These functions manipulate ufs buffers
diff --git a/fs/utimes.c b/fs/utimes.c
index 682eb63b20ad..b9912ecbee24 100644
--- a/fs/utimes.c
+++ b/fs/utimes.c
@@ -38,6 +38,14 @@ asmlinkage long sys_utime(char __user *filename, struct utimbuf __user *times)
#endif
+static bool nsec_valid(long nsec)
+{
+ if (nsec == UTIME_OMIT || nsec == UTIME_NOW)
+ return true;
+
+ return nsec >= 0 && nsec <= 999999999;
+}
+
/* If times==NULL, set access and modification to current time,
* must be owner or have write permission.
* Else, update from *times, must be owner or super user.
@@ -52,6 +60,11 @@ long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags
struct file *f = NULL;
error = -EINVAL;
+ if (times && (!nsec_valid(times[0].tv_nsec) ||
+ !nsec_valid(times[1].tv_nsec))) {
+ goto out;
+ }
+
if (flags & ~AT_SYMLINK_NOFOLLOW)
goto out;
diff --git a/fs/xattr.c b/fs/xattr.c
index a44fd92caca3..6645b7313b33 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -267,7 +267,7 @@ sys_fsetxattr(int fd, char __user *name, void __user *value,
if (!f)
return error;
dentry = f->f_path.dentry;
- audit_inode(NULL, dentry->d_inode);
+ audit_inode(NULL, dentry);
error = setxattr(dentry, name, value, size, flags);
fput(f);
return error;
@@ -349,7 +349,7 @@ sys_fgetxattr(int fd, char __user *name, void __user *value, size_t size)
f = fget(fd);
if (!f)
return error;
- audit_inode(NULL, f->f_path.dentry->d_inode);
+ audit_inode(NULL, f->f_path.dentry);
error = getxattr(f->f_path.dentry, name, value, size);
fput(f);
return error;
@@ -422,7 +422,7 @@ sys_flistxattr(int fd, char __user *list, size_t size)
f = fget(fd);
if (!f)
return error;
- audit_inode(NULL, f->f_path.dentry->d_inode);
+ audit_inode(NULL, f->f_path.dentry);
error = listxattr(f->f_path.dentry, list, size);
fput(f);
return error;
@@ -485,7 +485,7 @@ sys_fremovexattr(int fd, char __user *name)
if (!f)
return error;
dentry = f->f_path.dentry;
- audit_inode(NULL, dentry->d_inode);
+ audit_inode(NULL, dentry);
error = removexattr(dentry, name);
fput(f);
return error;
diff --git a/fs/xfs/Makefile-linux-2.6 b/fs/xfs/Makefile-linux-2.6
index e7a9a83f0087..d1491aa7a0e2 100644
--- a/fs/xfs/Makefile-linux-2.6
+++ b/fs/xfs/Makefile-linux-2.6
@@ -49,7 +49,6 @@ xfs-y += xfs_alloc.o \
xfs_alloc_btree.o \
xfs_attr.o \
xfs_attr_leaf.o \
- xfs_behavior.o \
xfs_bit.o \
xfs_bmap.o \
xfs_bmap_btree.o \
@@ -108,13 +107,11 @@ xfs-y += $(addprefix $(XFS_LINUX)/, \
xfs_iops.o \
xfs_lrw.o \
xfs_super.o \
- xfs_vfs.o \
xfs_vnode.o)
# Objects in support/
xfs-y += $(addprefix support/, \
debug.o \
- move.o \
uuid.o)
xfs-$(CONFIG_XFS_TRACE) += support/ktrace.o
diff --git a/fs/xfs/linux-2.6/kmem.h b/fs/xfs/linux-2.6/kmem.h
index e6ea293f303c..5e9564902976 100644
--- a/fs/xfs/linux-2.6/kmem.h
+++ b/fs/xfs/linux-2.6/kmem.h
@@ -79,7 +79,7 @@ kmem_zone_init(int size, char *zone_name)
static inline kmem_zone_t *
kmem_zone_init_flags(int size, char *zone_name, unsigned long flags,
- void (*construct)(void *, kmem_zone_t *, unsigned long))
+ void (*construct)(kmem_zone_t *, void *))
{
return kmem_cache_create(zone_name, size, 0, flags, construct);
}
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 6f4c29e9c3d9..2e34b104107c 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -37,6 +37,7 @@
#include "xfs_error.h"
#include "xfs_rw.h"
#include "xfs_iomap.h"
+#include "xfs_vnodeops.h"
#include <linux/mpage.h>
#include <linux/pagevec.h>
#include <linux/writeback.h>
@@ -139,9 +140,11 @@ xfs_destroy_ioend(
next = bh->b_private;
bh->b_end_io(bh, !ioend->io_error);
}
- if (unlikely(ioend->io_error))
- vn_ioerror(ioend->io_vnode, ioend->io_error, __FILE__,__LINE__);
- vn_iowake(ioend->io_vnode);
+ if (unlikely(ioend->io_error)) {
+ vn_ioerror(XFS_I(ioend->io_inode), ioend->io_error,
+ __FILE__,__LINE__);
+ }
+ vn_iowake(XFS_I(ioend->io_inode));
mempool_free(ioend, xfs_ioend_pool);
}
@@ -156,14 +159,10 @@ STATIC void
xfs_setfilesize(
xfs_ioend_t *ioend)
{
- xfs_inode_t *ip;
+ xfs_inode_t *ip = XFS_I(ioend->io_inode);
xfs_fsize_t isize;
xfs_fsize_t bsize;
- ip = xfs_vtoi(ioend->io_vnode);
- if (!ip)
- return;
-
ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFREG);
ASSERT(ioend->io_type != IOMAP_READ);
@@ -181,7 +180,7 @@ xfs_setfilesize(
ip->i_d.di_size = isize;
ip->i_update_core = 1;
ip->i_update_size = 1;
- mark_inode_dirty_sync(vn_to_inode(ioend->io_vnode));
+ mark_inode_dirty_sync(ioend->io_inode);
}
xfs_iunlock(ip, XFS_ILOCK_EXCL);
@@ -227,12 +226,12 @@ xfs_end_bio_unwritten(
{
xfs_ioend_t *ioend =
container_of(work, xfs_ioend_t, io_work);
- bhv_vnode_t *vp = ioend->io_vnode;
xfs_off_t offset = ioend->io_offset;
size_t size = ioend->io_size;
if (likely(!ioend->io_error)) {
- bhv_vop_bmap(vp, offset, size, BMAPI_UNWRITTEN, NULL, NULL);
+ xfs_bmap(XFS_I(ioend->io_inode), offset, size,
+ BMAPI_UNWRITTEN, NULL, NULL);
xfs_setfilesize(ioend);
}
xfs_destroy_ioend(ioend);
@@ -275,10 +274,10 @@ xfs_alloc_ioend(
ioend->io_error = 0;
ioend->io_list = NULL;
ioend->io_type = type;
- ioend->io_vnode = vn_from_inode(inode);
+ ioend->io_inode = inode;
ioend->io_buffer_head = NULL;
ioend->io_buffer_tail = NULL;
- atomic_inc(&ioend->io_vnode->v_iocount);
+ atomic_inc(&XFS_I(ioend->io_inode)->i_iocount);
ioend->io_offset = 0;
ioend->io_size = 0;
@@ -302,12 +301,13 @@ xfs_map_blocks(
xfs_iomap_t *mapp,
int flags)
{
- bhv_vnode_t *vp = vn_from_inode(inode);
+ xfs_inode_t *ip = XFS_I(inode);
int error, nmaps = 1;
- error = bhv_vop_bmap(vp, offset, count, flags, mapp, &nmaps);
+ error = xfs_bmap(ip, offset, count,
+ flags, mapp, &nmaps);
if (!error && (flags & (BMAPI_WRITE|BMAPI_ALLOCATE)))
- VMODIFY(vp);
+ xfs_iflags_set(ip, XFS_IMODIFIED);
return -error;
}
@@ -402,10 +402,9 @@ xfs_start_page_writeback(
clear_page_dirty_for_io(page);
set_page_writeback(page);
unlock_page(page);
- if (!buffers) {
+ /* If no buffers on the page are to be written, finish it here */
+ if (!buffers)
end_page_writeback(page);
- wbc->pages_skipped++; /* We didn't write this page */
- }
}
static inline int bio_add_buffer(struct bio *bio, struct buffer_head *bh)
@@ -498,7 +497,7 @@ xfs_cancel_ioend(
unlock_buffer(bh);
} while ((bh = next_bh) != NULL);
- vn_iowake(ioend->io_vnode);
+ vn_iowake(XFS_I(ioend->io_inode));
mempool_free(ioend, xfs_ioend_pool);
} while ((ioend = next) != NULL);
}
@@ -1238,10 +1237,7 @@ xfs_vm_writepages(
struct address_space *mapping,
struct writeback_control *wbc)
{
- struct bhv_vnode *vp = vn_from_inode(mapping->host);
-
- if (VN_TRUNC(vp))
- VUNTRUNCATE(vp);
+ xfs_iflags_clear(XFS_I(mapping->host), XFS_ITRUNCATED);
return generic_writepages(mapping, wbc);
}
@@ -1318,7 +1314,6 @@ __xfs_get_blocks(
int direct,
bmapi_flags_t flags)
{
- bhv_vnode_t *vp = vn_from_inode(inode);
xfs_iomap_t iomap;
xfs_off_t offset;
ssize_t size;
@@ -1328,7 +1323,7 @@ __xfs_get_blocks(
offset = (xfs_off_t)iblock << inode->i_blkbits;
ASSERT(bh_result->b_size >= (1 << inode->i_blkbits));
size = bh_result->b_size;
- error = bhv_vop_bmap(vp, offset, size,
+ error = xfs_bmap(XFS_I(inode), offset, size,
create ? flags : BMAPI_READ, &iomap, &niomap);
if (error)
return -error;
@@ -1476,13 +1471,13 @@ xfs_vm_direct_IO(
{
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_mapping->host;
- bhv_vnode_t *vp = vn_from_inode(inode);
xfs_iomap_t iomap;
int maps = 1;
int error;
ssize_t ret;
- error = bhv_vop_bmap(vp, offset, 0, BMAPI_DEVICE, &iomap, &maps);
+ error = xfs_bmap(XFS_I(inode), offset, 0,
+ BMAPI_DEVICE, &iomap, &maps);
if (error)
return -error;
@@ -1508,13 +1503,18 @@ xfs_vm_direct_IO(
}
STATIC int
-xfs_vm_prepare_write(
+xfs_vm_write_begin(
struct file *file,
- struct page *page,
- unsigned int from,
- unsigned int to)
+ struct address_space *mapping,
+ loff_t pos,
+ unsigned len,
+ unsigned flags,
+ struct page **pagep,
+ void **fsdata)
{
- return block_prepare_write(page, from, to, xfs_get_blocks);
+ *pagep = NULL;
+ return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
+ xfs_get_blocks);
}
STATIC sector_t
@@ -1523,12 +1523,13 @@ xfs_vm_bmap(
sector_t block)
{
struct inode *inode = (struct inode *)mapping->host;
- bhv_vnode_t *vp = vn_from_inode(inode);
+ struct xfs_inode *ip = XFS_I(inode);
- vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
- bhv_vop_rwlock(vp, VRWLOCK_READ);
- bhv_vop_flush_pages(vp, (xfs_off_t)0, -1, 0, FI_REMAPF);
- bhv_vop_rwunlock(vp, VRWLOCK_READ);
+ vn_trace_entry(XFS_I(inode), __FUNCTION__,
+ (inst_t *)__return_address);
+ xfs_rwlock(ip, VRWLOCK_READ);
+ xfs_flush_pages(ip, (xfs_off_t)0, -1, 0, FI_REMAPF);
+ xfs_rwunlock(ip, VRWLOCK_READ);
return generic_block_bmap(mapping, block, xfs_get_blocks);
}
@@ -1568,8 +1569,8 @@ const struct address_space_operations xfs_address_space_operations = {
.sync_page = block_sync_page,
.releasepage = xfs_vm_releasepage,
.invalidatepage = xfs_vm_invalidatepage,
- .prepare_write = xfs_vm_prepare_write,
- .commit_write = generic_commit_write,
+ .write_begin = xfs_vm_write_begin,
+ .write_end = generic_write_end,
.bmap = xfs_vm_bmap,
.direct_IO = xfs_vm_direct_IO,
.migratepage = buffer_migrate_page,
diff --git a/fs/xfs/linux-2.6/xfs_aops.h b/fs/xfs/linux-2.6/xfs_aops.h
index 2244e516b66a..3ba0631a3818 100644
--- a/fs/xfs/linux-2.6/xfs_aops.h
+++ b/fs/xfs/linux-2.6/xfs_aops.h
@@ -32,7 +32,7 @@ typedef struct xfs_ioend {
unsigned int io_type; /* delalloc / unwritten */
int io_error; /* I/O error code */
atomic_t io_remaining; /* hold count */
- struct bhv_vnode *io_vnode; /* file being written to */
+ struct inode *io_inode; /* file being written to */
struct buffer_head *io_buffer_head;/* buffer linked list head */
struct buffer_head *io_buffer_tail;/* buffer linked list tail */
size_t io_size; /* size of the extent */
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index 39f44ee572e8..b9c8589e05c2 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -187,6 +187,19 @@ free_address(
{
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);
@@ -997,7 +1010,18 @@ xfs_buf_iodone_work(
xfs_buf_t *bp =
container_of(work, xfs_buf_t, b_iodone_work);
- if (bp->b_iodone)
+ /*
+ * We can get an EOPNOTSUPP to ordered writes. Here we clear the
+ * ordered flag and reissue them. Because we can't tell the higher
+ * layers directly that they should not issue ordered I/O anymore, they
+ * need to check if the ordered flag was cleared during I/O completion.
+ */
+ if ((bp->b_error == EOPNOTSUPP) &&
+ (bp->b_flags & (XBF_ORDERED|XBF_ASYNC)) == (XBF_ORDERED|XBF_ASYNC)) {
+ XB_TRACE(bp, "ordered_retry", bp->b_iodone);
+ bp->b_flags &= ~XBF_ORDERED;
+ xfs_buf_iorequest(bp);
+ } else if (bp->b_iodone)
(*(bp->b_iodone))(bp);
else if (bp->b_flags & XBF_ASYNC)
xfs_buf_relse(bp);
diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c
index e3a5fedac1ba..15bd4948832c 100644
--- a/fs/xfs/linux-2.6/xfs_export.c
+++ b/fs/xfs/linux-2.6/xfs_export.c
@@ -17,72 +17,41 @@
*/
#include "xfs.h"
#include "xfs_types.h"
-#include "xfs_dmapi.h"
+#include "xfs_inum.h"
#include "xfs_log.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
+#include "xfs_ag.h"
+#include "xfs_dmapi.h"
#include "xfs_mount.h"
#include "xfs_export.h"
+#include "xfs_vnodeops.h"
+#include "xfs_bmap_btree.h"
+#include "xfs_inode.h"
+#include "xfs_vfsops.h"
static struct dentry dotdot = { .d_name.name = "..", .d_name.len = 2, };
/*
- * XFS encodes and decodes the fileid portion of NFS filehandles
- * itself instead of letting the generic NFS code do it. This
- * allows filesystems with 64 bit inode numbers to be exported.
- *
- * Note that a side effect is that xfs_vget() won't be passed a
- * zero inode/generation pair under normal circumstances. As
- * however a malicious client could send us such data, the check
- * remains in that code.
+ * Note that we only accept fileids which are long enough rather than allow
+ * the parent generation number to default to zero. XFS considers zero a
+ * valid generation number not an invalid/wildcard value.
*/
-
-STATIC struct dentry *
-xfs_fs_decode_fh(
- struct super_block *sb,
- __u32 *fh,
- int fh_len,
- int fileid_type,
- int (*acceptable)(
- void *context,
- struct dentry *de),
- void *context)
+static int xfs_fileid_length(int fileid_type)
{
- xfs_fid2_t ifid;
- xfs_fid2_t pfid;
- void *parent = NULL;
- int is64 = 0;
- __u32 *p = fh;
-
-#if XFS_BIG_INUMS
- is64 = (fileid_type & XFS_FILEID_TYPE_64FLAG);
- fileid_type &= ~XFS_FILEID_TYPE_64FLAG;
-#endif
-
- /*
- * Note that we only accept fileids which are long enough
- * rather than allow the parent generation number to default
- * to zero. XFS considers zero a valid generation number not
- * an invalid/wildcard value. There's little point printk'ing
- * a warning here as we don't have the client information
- * which would make such a warning useful.
- */
- if (fileid_type > 2 ||
- fh_len < xfs_fileid_length((fileid_type == 2), is64))
- return NULL;
-
- p = xfs_fileid_decode_fid2(p, &ifid, is64);
-
- if (fileid_type == 2) {
- p = xfs_fileid_decode_fid2(p, &pfid, is64);
- parent = &pfid;
+ switch (fileid_type) {
+ case FILEID_INO32_GEN:
+ return 2;
+ case FILEID_INO32_GEN_PARENT:
+ return 4;
+ case FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG:
+ return 3;
+ case FILEID_INO32_GEN_PARENT | XFS_FILEID_TYPE_64FLAG:
+ return 6;
}
-
- fh = (__u32 *)&ifid;
- return sb->s_export_op->find_exported_dentry(sb, fh, parent, acceptable, context);
+ return 255; /* invalid */
}
-
STATIC int
xfs_fs_encode_fh(
struct dentry *dentry,
@@ -90,23 +59,21 @@ xfs_fs_encode_fh(
int *max_len,
int connectable)
{
+ struct fid *fid = (struct fid *)fh;
+ struct xfs_fid64 *fid64 = (struct xfs_fid64 *)fh;
struct inode *inode = dentry->d_inode;
- int type = 1;
- __u32 *p = fh;
+ int fileid_type;
int len;
- int is64 = 0;
-#if XFS_BIG_INUMS
- bhv_vfs_t *vfs = vfs_from_sb(inode->i_sb);
-
- if (!(vfs->vfs_flag & VFS_32BITINODES)) {
- /* filesystem may contain 64bit inode numbers */
- is64 = XFS_FILEID_TYPE_64FLAG;
- }
-#endif
/* Directories don't need their parent encoded, they have ".." */
if (S_ISDIR(inode->i_mode))
- connectable = 0;
+ fileid_type = FILEID_INO32_GEN;
+ else
+ fileid_type = FILEID_INO32_GEN_PARENT;
+
+ /* filesystem may contain 64bit inode numbers */
+ if (!(XFS_M(inode->i_sb)->m_flags & XFS_MOUNT_SMALL_INUMS))
+ fileid_type |= XFS_FILEID_TYPE_64FLAG;
/*
* Only encode if there is enough space given. In practice
@@ -114,40 +81,118 @@ xfs_fs_encode_fh(
* over NFSv2 with the subtree_check export option; the other
* seven combinations work. The real answer is "don't use v2".
*/
- len = xfs_fileid_length(connectable, is64);
+ len = xfs_fileid_length(fileid_type);
if (*max_len < len)
return 255;
*max_len = len;
- p = xfs_fileid_encode_inode(p, inode, is64);
- if (connectable) {
+ switch (fileid_type) {
+ case FILEID_INO32_GEN_PARENT:
spin_lock(&dentry->d_lock);
- p = xfs_fileid_encode_inode(p, dentry->d_parent->d_inode, is64);
+ fid->i32.parent_ino = dentry->d_parent->d_inode->i_ino;
+ fid->i32.parent_gen = dentry->d_parent->d_inode->i_generation;
spin_unlock(&dentry->d_lock);
- type = 2;
+ /*FALLTHRU*/
+ case FILEID_INO32_GEN:
+ fid->i32.ino = inode->i_ino;
+ fid->i32.gen = inode->i_generation;
+ break;
+ case FILEID_INO32_GEN_PARENT | XFS_FILEID_TYPE_64FLAG:
+ spin_lock(&dentry->d_lock);
+ fid64->parent_ino = dentry->d_parent->d_inode->i_ino;
+ fid64->parent_gen = dentry->d_parent->d_inode->i_generation;
+ spin_unlock(&dentry->d_lock);
+ /*FALLTHRU*/
+ case FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG:
+ fid64->ino = inode->i_ino;
+ fid64->gen = inode->i_generation;
+ break;
}
- BUG_ON((p - fh) != len);
- return type | is64;
+
+ return fileid_type;
}
-STATIC struct dentry *
-xfs_fs_get_dentry(
+STATIC struct inode *
+xfs_nfs_get_inode(
struct super_block *sb,
- void *data)
-{
+ u64 ino,
+ u32 generation)
+ {
+ xfs_fid_t xfid;
bhv_vnode_t *vp;
- struct inode *inode;
- struct dentry *result;
- bhv_vfs_t *vfsp = vfs_from_sb(sb);
int error;
- error = bhv_vfs_vget(vfsp, &vp, (fid_t *)data);
- if (error || vp == NULL)
- return ERR_PTR(-ESTALE) ;
+ xfid.fid_len = sizeof(xfs_fid_t) - sizeof(xfid.fid_len);
+ xfid.fid_pad = 0;
+ xfid.fid_ino = ino;
+ xfid.fid_gen = generation;
+
+ error = xfs_vget(XFS_M(sb), &vp, &xfid);
+ if (error)
+ return ERR_PTR(-error);
+
+ return vp ? vn_to_inode(vp) : NULL;
+}
+
+STATIC struct dentry *
+xfs_fs_fh_to_dentry(struct super_block *sb, struct fid *fid,
+ int fh_len, int fileid_type)
+{
+ struct xfs_fid64 *fid64 = (struct xfs_fid64 *)fid;
+ struct inode *inode = NULL;
+ struct dentry *result;
+
+ if (fh_len < xfs_fileid_length(fileid_type))
+ return NULL;
+
+ switch (fileid_type) {
+ case FILEID_INO32_GEN_PARENT:
+ case FILEID_INO32_GEN:
+ inode = xfs_nfs_get_inode(sb, fid->i32.ino, fid->i32.gen);
+ break;
+ case FILEID_INO32_GEN_PARENT | XFS_FILEID_TYPE_64FLAG:
+ case FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG:
+ inode = xfs_nfs_get_inode(sb, fid64->ino, fid64->gen);
+ break;
+ }
+
+ if (!inode)
+ return NULL;
+ if (IS_ERR(inode))
+ return ERR_PTR(PTR_ERR(inode));
+ result = d_alloc_anon(inode);
+ if (!result) {
+ iput(inode);
+ return ERR_PTR(-ENOMEM);
+ }
+ return result;
+}
- inode = vn_to_inode(vp);
+STATIC struct dentry *
+xfs_fs_fh_to_parent(struct super_block *sb, struct fid *fid,
+ int fh_len, int fileid_type)
+{
+ struct xfs_fid64 *fid64 = (struct xfs_fid64 *)fid;
+ struct inode *inode = NULL;
+ struct dentry *result;
+
+ switch (fileid_type) {
+ case FILEID_INO32_GEN_PARENT:
+ inode = xfs_nfs_get_inode(sb, fid->i32.parent_ino,
+ fid->i32.parent_gen);
+ break;
+ case FILEID_INO32_GEN_PARENT | XFS_FILEID_TYPE_64FLAG:
+ inode = xfs_nfs_get_inode(sb, fid64->parent_ino,
+ fid64->parent_gen);
+ break;
+ }
+
+ if (!inode)
+ return NULL;
+ if (IS_ERR(inode))
+ return ERR_PTR(PTR_ERR(inode));
result = d_alloc_anon(inode);
- if (!result) {
+ if (!result) {
iput(inode);
return ERR_PTR(-ENOMEM);
}
@@ -159,12 +204,11 @@ xfs_fs_get_parent(
struct dentry *child)
{
int error;
- bhv_vnode_t *vp, *cvp;
+ bhv_vnode_t *cvp;
struct dentry *parent;
cvp = NULL;
- vp = vn_from_inode(child->d_inode);
- error = bhv_vop_lookup(vp, &dotdot, &cvp, 0, NULL, NULL);
+ error = xfs_lookup(XFS_I(child->d_inode), &dotdot, &cvp);
if (unlikely(error))
return ERR_PTR(-error);
@@ -176,9 +220,9 @@ xfs_fs_get_parent(
return parent;
}
-struct export_operations xfs_export_operations = {
- .decode_fh = xfs_fs_decode_fh,
+const struct export_operations xfs_export_operations = {
.encode_fh = xfs_fs_encode_fh,
+ .fh_to_dentry = xfs_fs_fh_to_dentry,
+ .fh_to_parent = xfs_fs_fh_to_parent,
.get_parent = xfs_fs_get_parent,
- .get_dentry = xfs_fs_get_dentry,
};
diff --git a/fs/xfs/linux-2.6/xfs_export.h b/fs/xfs/linux-2.6/xfs_export.h
index e794ca4efc76..3272b6ae7a35 100644
--- a/fs/xfs/linux-2.6/xfs_export.h
+++ b/fs/xfs/linux-2.6/xfs_export.h
@@ -59,50 +59,14 @@
* a subdirectory) or use the "fsid" export option.
*/
+struct xfs_fid64 {
+ u64 ino;
+ u32 gen;
+ u64 parent_ino;
+ u32 parent_gen;
+} __attribute__((packed));
+
/* This flag goes on the wire. Don't play with it. */
#define XFS_FILEID_TYPE_64FLAG 0x80 /* NFS fileid has 64bit inodes */
-/* Calculate the length in u32 units of the fileid data */
-static inline int
-xfs_fileid_length(int hasparent, int is64)
-{
- return hasparent ? (is64 ? 6 : 4) : (is64 ? 3 : 2);
-}
-
-/*
- * Decode encoded inode information (either for the inode itself
- * or the parent) into an xfs_fid2_t structure. Advances and
- * returns the new data pointer
- */
-static inline __u32 *
-xfs_fileid_decode_fid2(__u32 *p, xfs_fid2_t *fid, int is64)
-{
- fid->fid_len = sizeof(xfs_fid2_t) - sizeof(fid->fid_len);
- fid->fid_pad = 0;
- fid->fid_ino = *p++;
-#if XFS_BIG_INUMS
- if (is64)
- fid->fid_ino |= (((__u64)(*p++)) << 32);
-#endif
- fid->fid_gen = *p++;
- return p;
-}
-
-/*
- * Encode inode information (either for the inode itself or the
- * parent) into a fileid buffer. Advances and returns the new
- * data pointer.
- */
-static inline __u32 *
-xfs_fileid_encode_inode(__u32 *p, struct inode *inode, int is64)
-{
- *p++ = (__u32)inode->i_ino;
-#if XFS_BIG_INUMS
- if (is64)
- *p++ = (__u32)(inode->i_ino >> 32);
-#endif
- *p++ = inode->i_generation;
- return p;
-}
-
#endif /* __XFS_EXPORT_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index 0d4001eafd16..fb8dd34041eb 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -37,6 +37,7 @@
#include "xfs_error.h"
#include "xfs_rw.h"
#include "xfs_ioctl32.h"
+#include "xfs_vnodeops.h"
#include <linux/dcache.h>
#include <linux/smp_lock.h>
@@ -55,13 +56,12 @@ __xfs_file_read(
loff_t pos)
{
struct file *file = iocb->ki_filp;
- bhv_vnode_t *vp = vn_from_inode(file->f_path.dentry->d_inode);
BUG_ON(iocb->ki_pos != pos);
if (unlikely(file->f_flags & O_DIRECT))
ioflags |= IO_ISDIRECT;
- return bhv_vop_read(vp, iocb, iov, nr_segs, &iocb->ki_pos,
- ioflags, NULL);
+ return xfs_read(XFS_I(file->f_path.dentry->d_inode), iocb, iov,
+ nr_segs, &iocb->ki_pos, ioflags);
}
STATIC ssize_t
@@ -93,14 +93,12 @@ __xfs_file_write(
loff_t pos)
{
struct file *file = iocb->ki_filp;
- struct inode *inode = file->f_mapping->host;
- bhv_vnode_t *vp = vn_from_inode(inode);
BUG_ON(iocb->ki_pos != pos);
if (unlikely(file->f_flags & O_DIRECT))
ioflags |= IO_ISDIRECT;
- return bhv_vop_write(vp, iocb, iov, nr_segs, &iocb->ki_pos,
- ioflags, NULL);
+ return xfs_write(XFS_I(file->f_mapping->host), iocb, iov, nr_segs,
+ &iocb->ki_pos, ioflags);
}
STATIC ssize_t
@@ -131,8 +129,8 @@ xfs_file_splice_read(
size_t len,
unsigned int flags)
{
- return bhv_vop_splice_read(vn_from_inode(infilp->f_path.dentry->d_inode),
- infilp, ppos, pipe, len, flags, 0, NULL);
+ return xfs_splice_read(XFS_I(infilp->f_path.dentry->d_inode),
+ infilp, ppos, pipe, len, flags, 0);
}
STATIC ssize_t
@@ -143,9 +141,8 @@ xfs_file_splice_read_invis(
size_t len,
unsigned int flags)
{
- return bhv_vop_splice_read(vn_from_inode(infilp->f_path.dentry->d_inode),
- infilp, ppos, pipe, len, flags, IO_INVIS,
- NULL);
+ return xfs_splice_read(XFS_I(infilp->f_path.dentry->d_inode),
+ infilp, ppos, pipe, len, flags, IO_INVIS);
}
STATIC ssize_t
@@ -156,8 +153,8 @@ xfs_file_splice_write(
size_t len,
unsigned int flags)
{
- return bhv_vop_splice_write(vn_from_inode(outfilp->f_path.dentry->d_inode),
- pipe, outfilp, ppos, len, flags, 0, NULL);
+ return xfs_splice_write(XFS_I(outfilp->f_path.dentry->d_inode),
+ pipe, outfilp, ppos, len, flags, 0);
}
STATIC ssize_t
@@ -168,9 +165,8 @@ xfs_file_splice_write_invis(
size_t len,
unsigned int flags)
{
- return bhv_vop_splice_write(vn_from_inode(outfilp->f_path.dentry->d_inode),
- pipe, outfilp, ppos, len, flags, IO_INVIS,
- NULL);
+ return xfs_splice_write(XFS_I(outfilp->f_path.dentry->d_inode),
+ pipe, outfilp, ppos, len, flags, IO_INVIS);
}
STATIC int
@@ -180,7 +176,7 @@ xfs_file_open(
{
if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
return -EFBIG;
- return -bhv_vop_open(vn_from_inode(inode), NULL);
+ return -xfs_open(XFS_I(inode));
}
STATIC int
@@ -188,11 +184,7 @@ xfs_file_release(
struct inode *inode,
struct file *filp)
{
- bhv_vnode_t *vp = vn_from_inode(inode);
-
- if (vp)
- return -bhv_vop_release(vp);
- return 0;
+ return -xfs_release(XFS_I(inode));
}
STATIC int
@@ -201,14 +193,13 @@ xfs_file_fsync(
struct dentry *dentry,
int datasync)
{
- bhv_vnode_t *vp = vn_from_inode(dentry->d_inode);
int flags = FSYNC_WAIT;
if (datasync)
flags |= FSYNC_DATA;
- if (VN_TRUNC(vp))
- VUNTRUNCATE(vp);
- return -bhv_vop_fsync(vp, flags, NULL, (xfs_off_t)0, (xfs_off_t)-1);
+ xfs_iflags_clear(XFS_I(dentry->d_inode), XFS_ITRUNCATED);
+ return -xfs_fsync(XFS_I(dentry->d_inode), flags,
+ (xfs_off_t)0, (xfs_off_t)-1);
}
#ifdef CONFIG_XFS_DMAPI
@@ -233,74 +224,30 @@ xfs_file_readdir(
void *dirent,
filldir_t filldir)
{
- int error = 0;
- bhv_vnode_t *vp = vn_from_inode(filp->f_path.dentry->d_inode);
- uio_t uio;
- iovec_t iov;
- int eof = 0;
- caddr_t read_buf;
- int namelen, size = 0;
- size_t rlen = PAGE_CACHE_SIZE;
- xfs_off_t start_offset, curr_offset;
- xfs_dirent_t *dbp = NULL;
-
- /* Try fairly hard to get memory */
- do {
- if ((read_buf = kmalloc(rlen, GFP_KERNEL)))
- break;
- rlen >>= 1;
- } while (rlen >= 1024);
-
- if (read_buf == NULL)
- return -ENOMEM;
-
- uio.uio_iov = &iov;
- uio.uio_segflg = UIO_SYSSPACE;
- curr_offset = filp->f_pos;
- if (filp->f_pos != 0x7fffffff)
- uio.uio_offset = filp->f_pos;
- else
- uio.uio_offset = 0xffffffff;
-
- while (!eof) {
- uio.uio_resid = iov.iov_len = rlen;
- iov.iov_base = read_buf;
- uio.uio_iovcnt = 1;
-
- start_offset = uio.uio_offset;
-
- error = bhv_vop_readdir(vp, &uio, NULL, &eof);
- if ((uio.uio_offset == start_offset) || error) {
- size = 0;
- break;
- }
-
- size = rlen - uio.uio_resid;
- dbp = (xfs_dirent_t *)read_buf;
- while (size > 0) {
- namelen = strlen(dbp->d_name);
-
- if (filldir(dirent, dbp->d_name, namelen,
- (loff_t) curr_offset & 0x7fffffff,
- (ino_t) dbp->d_ino,
- DT_UNKNOWN)) {
- goto done;
- }
- size -= dbp->d_reclen;
- curr_offset = (loff_t)dbp->d_off /* & 0x7fffffff */;
- dbp = (xfs_dirent_t *)((char *)dbp + dbp->d_reclen);
- }
- }
-done:
- if (!error) {
- if (size == 0)
- filp->f_pos = uio.uio_offset & 0x7fffffff;
- else if (dbp)
- filp->f_pos = curr_offset;
- }
+ struct inode *inode = filp->f_path.dentry->d_inode;
+ xfs_inode_t *ip = XFS_I(inode);
+ int error;
+ size_t bufsize;
+
+ /*
+ * The Linux API doesn't pass down the total size of the buffer
+ * we read into down to the filesystem. With the filldir concept
+ * it's not needed for correct information, but the XFS dir2 leaf
+ * code wants an estimate of the buffer size to calculate it's
+ * readahead window and size the buffers used for mapping to
+ * physical blocks.
+ *
+ * Try to give it an estimate that's good enough, maybe at some
+ * point we can change the ->readdir prototype to include the
+ * buffer size.
+ */
+ bufsize = (size_t)min_t(loff_t, PAGE_SIZE, inode->i_size);
- kfree(read_buf);
- return -error;
+ error = xfs_readdir(ip, dirent, bufsize,
+ (xfs_off_t *)&filp->f_pos, filldir);
+ if (error)
+ return -error;
+ return 0;
}
STATIC int
@@ -312,7 +259,7 @@ xfs_file_mmap(
vma->vm_flags |= VM_CAN_NONLINEAR;
#ifdef CONFIG_XFS_DMAPI
- if (vn_from_inode(filp->f_path.dentry->d_inode)->v_vfsp->vfs_flag & VFS_DMI)
+ if (XFS_M(filp->f_path.dentry->d_inode->i_sb)->m_flags & XFS_MOUNT_DMAPI)
vma->vm_ops = &xfs_dmapi_file_vm_ops;
#endif /* CONFIG_XFS_DMAPI */
@@ -328,10 +275,9 @@ xfs_file_ioctl(
{
int error;
struct inode *inode = filp->f_path.dentry->d_inode;
- bhv_vnode_t *vp = vn_from_inode(inode);
- error = bhv_vop_ioctl(vp, inode, filp, 0, cmd, (void __user *)p);
- VMODIFY(vp);
+ error = xfs_ioctl(XFS_I(inode), filp, 0, cmd, (void __user *)p);
+ xfs_iflags_set(XFS_I(inode), XFS_IMODIFIED);
/* NOTE: some of the ioctl's return positive #'s as a
* byte count indicating success, such as
@@ -350,10 +296,9 @@ xfs_file_ioctl_invis(
{
int error;
struct inode *inode = filp->f_path.dentry->d_inode;
- bhv_vnode_t *vp = vn_from_inode(inode);
- error = bhv_vop_ioctl(vp, inode, filp, IO_INVIS, cmd, (void __user *)p);
- VMODIFY(vp);
+ error = xfs_ioctl(XFS_I(inode), filp, IO_INVIS, cmd, (void __user *)p);
+ xfs_iflags_set(XFS_I(inode), XFS_IMODIFIED);
/* NOTE: some of the ioctl's return positive #'s as a
* byte count indicating success, such as
@@ -371,16 +316,14 @@ xfs_vm_mprotect(
struct vm_area_struct *vma,
unsigned int newflags)
{
- bhv_vnode_t *vp = vn_from_inode(vma->vm_file->f_path.dentry->d_inode);
+ struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
+ struct xfs_mount *mp = XFS_M(inode->i_sb);
int error = 0;
- if (vp->v_vfsp->vfs_flag & VFS_DMI) {
+ if (mp->m_flags & XFS_MOUNT_DMAPI) {
if ((vma->vm_flags & VM_MAYSHARE) &&
- (newflags & VM_WRITE) && !(vma->vm_flags & VM_WRITE)) {
- xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp);
-
+ (newflags & VM_WRITE) && !(vma->vm_flags & VM_WRITE))
error = XFS_SEND_MMAP(mp, vma, VM_WRITE);
- }
}
return error;
}
@@ -397,18 +340,17 @@ STATIC int
xfs_file_open_exec(
struct inode *inode)
{
- bhv_vnode_t *vp = vn_from_inode(inode);
+ struct xfs_mount *mp = XFS_M(inode->i_sb);
- if (unlikely(vp->v_vfsp->vfs_flag & VFS_DMI)) {
- xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp);
- xfs_inode_t *ip = xfs_vtoi(vp);
+ if (unlikely(mp->m_flags & XFS_MOUNT_DMAPI)) {
+ if (DM_EVENT_ENABLED(XFS_I(inode), DM_EVENT_READ)) {
+ bhv_vnode_t *vp = vn_from_inode(inode);
- if (!ip)
- return -EINVAL;
- if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ))
- return -XFS_SEND_DATA(mp, DM_EVENT_READ, vp,
- 0, 0, 0, NULL);
+ return -XFS_SEND_DATA(mp, DM_EVENT_READ,
+ vp, 0, 0, 0, NULL);
+ }
}
+
return 0;
}
#endif /* HAVE_FOP_OPEN_EXEC */
diff --git a/fs/xfs/linux-2.6/xfs_fs_subr.c b/fs/xfs/linux-2.6/xfs_fs_subr.c
index 2eb87cd082af..ac6d34cc355d 100644
--- a/fs/xfs/linux-2.6/xfs_fs_subr.c
+++ b/fs/xfs/linux-2.6/xfs_fs_subr.c
@@ -16,66 +16,78 @@
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
+#include "xfs_vnodeops.h"
+
+/*
+ * The following six includes are needed so that we can include
+ * xfs_inode.h. What a mess..
+ */
+#include "xfs_bmap_btree.h"
+#include "xfs_inum.h"
+#include "xfs_dir2.h"
+#include "xfs_dir2_sf.h"
+#include "xfs_attr_sf.h"
+#include "xfs_dinode.h"
+
+#include "xfs_inode.h"
int fs_noerr(void) { return 0; }
int fs_nosys(void) { return ENOSYS; }
void fs_noval(void) { return; }
void
-fs_tosspages(
- bhv_desc_t *bdp,
+xfs_tosspages(
+ xfs_inode_t *ip,
xfs_off_t first,
xfs_off_t last,
int fiopt)
{
- bhv_vnode_t *vp = BHV_TO_VNODE(bdp);
- struct inode *ip = vn_to_inode(vp);
+ bhv_vnode_t *vp = XFS_ITOV(ip);
+ struct inode *inode = vn_to_inode(vp);
if (VN_CACHED(vp))
- truncate_inode_pages(ip->i_mapping, first);
+ truncate_inode_pages(inode->i_mapping, first);
}
int
-fs_flushinval_pages(
- bhv_desc_t *bdp,
+xfs_flushinval_pages(
+ xfs_inode_t *ip,
xfs_off_t first,
xfs_off_t last,
int fiopt)
{
- bhv_vnode_t *vp = BHV_TO_VNODE(bdp);
- struct inode *ip = vn_to_inode(vp);
+ bhv_vnode_t *vp = XFS_ITOV(ip);
+ struct inode *inode = vn_to_inode(vp);
int ret = 0;
if (VN_CACHED(vp)) {
- if (VN_TRUNC(vp))
- VUNTRUNCATE(vp);
- ret = filemap_write_and_wait(ip->i_mapping);
+ xfs_iflags_clear(ip, XFS_ITRUNCATED);
+ ret = filemap_write_and_wait(inode->i_mapping);
if (!ret)
- truncate_inode_pages(ip->i_mapping, first);
+ truncate_inode_pages(inode->i_mapping, first);
}
return ret;
}
int
-fs_flush_pages(
- bhv_desc_t *bdp,
+xfs_flush_pages(
+ xfs_inode_t *ip,
xfs_off_t first,
xfs_off_t last,
uint64_t flags,
int fiopt)
{
- bhv_vnode_t *vp = BHV_TO_VNODE(bdp);
- struct inode *ip = vn_to_inode(vp);
+ bhv_vnode_t *vp = XFS_ITOV(ip);
+ struct inode *inode = vn_to_inode(vp);
int ret = 0;
int ret2;
if (VN_DIRTY(vp)) {
- if (VN_TRUNC(vp))
- VUNTRUNCATE(vp);
- ret = filemap_fdatawrite(ip->i_mapping);
+ xfs_iflags_clear(ip, XFS_ITRUNCATED);
+ ret = filemap_fdatawrite(inode->i_mapping);
if (flags & XFS_B_ASYNC)
return ret;
- ret2 = filemap_fdatawait(ip->i_mapping);
+ ret2 = filemap_fdatawait(inode->i_mapping);
if (!ret)
ret = ret2;
}
diff --git a/fs/xfs/linux-2.6/xfs_fs_subr.h b/fs/xfs/linux-2.6/xfs_fs_subr.h
index c1b53118a303..82bb19b2599e 100644
--- a/fs/xfs/linux-2.6/xfs_fs_subr.h
+++ b/fs/xfs/linux-2.6/xfs_fs_subr.h
@@ -18,12 +18,8 @@
#ifndef __XFS_FS_SUBR_H__
#define __XFS_FS_SUBR_H__
-struct cred;
extern int fs_noerr(void);
extern int fs_nosys(void);
extern void fs_noval(void);
-extern void fs_tosspages(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
-extern int fs_flushinval_pages(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
-extern int fs_flush_pages(bhv_desc_t *, xfs_off_t, xfs_off_t, uint64_t, int);
#endif /* __XFS_FS_SUBR_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_globals.c b/fs/xfs/linux-2.6/xfs_globals.c
index 81565dea9af7..9febf9dc999d 100644
--- a/fs/xfs/linux-2.6/xfs_globals.c
+++ b/fs/xfs/linux-2.6/xfs_globals.c
@@ -20,11 +20,6 @@
#include "xfs_sysctl.h"
/*
- * System memory size - used to scale certain data structures in XFS.
- */
-unsigned long xfs_physmem;
-
-/*
* Tunable XFS parameters. xfs_params is required even when CONFIG_SYSCTL=n,
* other XFS code uses these values. Times are measured in centisecs (i.e.
* 100ths of a second).
diff --git a/fs/xfs/linux-2.6/xfs_globals.h b/fs/xfs/linux-2.6/xfs_globals.h
index e1a22bfcf865..2770b0085ee8 100644
--- a/fs/xfs/linux-2.6/xfs_globals.h
+++ b/fs/xfs/linux-2.6/xfs_globals.h
@@ -19,7 +19,6 @@
#define __XFS_GLOBALS_H__
extern uint64_t xfs_panic_mask; /* set to cause more panics */
-extern unsigned long xfs_physmem;
extern struct cred *sys_cred;
#endif /* __XFS_GLOBALS_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index 5917808abbd6..2b34bad48b07 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -47,6 +47,7 @@
#include "xfs_utils.h"
#include "xfs_dfrag.h"
#include "xfs_fsops.h"
+#include "xfs_vnodeops.h"
#include <linux/capability.h>
#include <linux/dcache.h>
@@ -137,7 +138,8 @@ xfs_find_handle(
vp = vn_from_inode(inode);
/* now we can grab the fsid */
- memcpy(&handle.ha_fsid, vp->v_vfsp->vfs_altfsid, sizeof(xfs_fsid_t));
+ memcpy(&handle.ha_fsid, XFS_I(inode)->i_mount->m_fixedfsid,
+ sizeof(xfs_fsid_t));
hsize = sizeof(xfs_fsid_t);
if (cmd != XFS_IOC_PATH_TO_FSHANDLE) {
@@ -150,11 +152,11 @@ xfs_find_handle(
lock_mode = xfs_ilock_map_shared(ip);
/* fill in fid section of handle from inode */
- handle.ha_fid.xfs_fid_len = sizeof(xfs_fid_t) -
- sizeof(handle.ha_fid.xfs_fid_len);
- handle.ha_fid.xfs_fid_pad = 0;
- handle.ha_fid.xfs_fid_gen = ip->i_d.di_gen;
- handle.ha_fid.xfs_fid_ino = ip->i_ino;
+ handle.ha_fid.fid_len = sizeof(xfs_fid_t) -
+ sizeof(handle.ha_fid.fid_len);
+ handle.ha_fid.fid_pad = 0;
+ handle.ha_fid.fid_gen = ip->i_d.di_gen;
+ handle.ha_fid.fid_ino = ip->i_ino;
xfs_iunlock_map_shared(ip, lock_mode);
@@ -220,10 +222,10 @@ xfs_vget_fsop_handlereq(
if (hlen < sizeof(*handlep))
memset(((char *)handlep) + hlen, 0, sizeof(*handlep) - hlen);
if (hlen > sizeof(handlep->ha_fsid)) {
- if (handlep->ha_fid.xfs_fid_len !=
- (hlen - sizeof(handlep->ha_fsid)
- - sizeof(handlep->ha_fid.xfs_fid_len))
- || handlep->ha_fid.xfs_fid_pad)
+ if (handlep->ha_fid.fid_len !=
+ (hlen - sizeof(handlep->ha_fsid) -
+ sizeof(handlep->ha_fid.fid_len)) ||
+ handlep->ha_fid.fid_pad)
return XFS_ERROR(EINVAL);
}
@@ -231,9 +233,9 @@ xfs_vget_fsop_handlereq(
* Crack the handle, obtain the inode # & generation #
*/
xfid = (struct xfs_fid *)&handlep->ha_fid;
- if (xfid->xfs_fid_len == sizeof(*xfid) - sizeof(xfid->xfs_fid_len)) {
- ino = xfid->xfs_fid_ino;
- igen = xfid->xfs_fid_gen;
+ if (xfid->fid_len == sizeof(*xfid) - sizeof(xfid->fid_len)) {
+ ino = xfid->fid_ino;
+ igen = xfid->fid_gen;
} else {
return XFS_ERROR(EINVAL);
}
@@ -349,19 +351,44 @@ xfs_open_by_handle(
return new_fd;
}
+/*
+ * This is a copy from fs/namei.c:vfs_readlink(), except for removing it's
+ * unused first argument.
+ */
+STATIC int
+do_readlink(
+ char __user *buffer,
+ int buflen,
+ const char *link)
+{
+ int len;
+
+ len = PTR_ERR(link);
+ if (IS_ERR(link))
+ goto out;
+
+ len = strlen(link);
+ if (len > (unsigned) buflen)
+ len = buflen;
+ if (copy_to_user(buffer, link, len))
+ len = -EFAULT;
+ out:
+ return len;
+}
+
+
STATIC int
xfs_readlink_by_handle(
xfs_mount_t *mp,
void __user *arg,
struct inode *parinode)
{
- int error;
- struct iovec aiov;
- struct uio auio;
struct inode *inode;
xfs_fsop_handlereq_t hreq;
bhv_vnode_t *vp;
__u32 olen;
+ void *link;
+ int error;
if (!capable(CAP_SYS_ADMIN))
return -XFS_ERROR(EPERM);
@@ -374,29 +401,31 @@ xfs_readlink_by_handle(
/* Restrict this handle operation to symlinks only. */
if (!S_ISLNK(inode->i_mode)) {
- VN_RELE(vp);
- return -XFS_ERROR(EINVAL);
+ error = -XFS_ERROR(EINVAL);
+ goto out_iput;
}
if (copy_from_user(&olen, hreq.ohandlen, sizeof(__u32))) {
- VN_RELE(vp);
- return -XFS_ERROR(EFAULT);
+ error = -XFS_ERROR(EFAULT);
+ goto out_iput;
}
- aiov.iov_len = olen;
- aiov.iov_base = hreq.ohandle;
- auio.uio_iov = (struct kvec *)&aiov;
- auio.uio_iovcnt = 1;
- auio.uio_offset = 0;
- auio.uio_segflg = UIO_USERSPACE;
- auio.uio_resid = olen;
+ link = kmalloc(MAXPATHLEN+1, GFP_KERNEL);
+ if (!link)
+ goto out_iput;
- error = bhv_vop_readlink(vp, &auio, IO_INVIS, NULL);
- VN_RELE(vp);
+ error = -xfs_readlink(XFS_I(inode), link);
if (error)
- return -error;
+ goto out_kfree;
+ error = do_readlink(hreq.ohandle, olen, link);
+ if (error)
+ goto out_kfree;
- return (olen - auio.uio_resid);
+ out_kfree:
+ kfree(link);
+ out_iput:
+ iput(inode);
+ return error;
}
STATIC int
@@ -409,7 +438,6 @@ xfs_fssetdm_by_handle(
struct fsdmidata fsd;
xfs_fsop_setdm_handlereq_t dmhreq;
struct inode *inode;
- bhv_desc_t *bdp;
bhv_vnode_t *vp;
if (!capable(CAP_MKNOD))
@@ -431,8 +459,8 @@ xfs_fssetdm_by_handle(
return -XFS_ERROR(EFAULT);
}
- bdp = bhv_base_unlocked(VN_BHV_HEAD(vp));
- error = xfs_set_dmattrs(bdp, fsd.fsd_dmevmask, fsd.fsd_dmstate, NULL);
+ error = xfs_set_dmattrs(xfs_vtoi(vp),
+ fsd.fsd_dmevmask, fsd.fsd_dmstate);
VN_RELE(vp);
if (error)
@@ -470,8 +498,8 @@ xfs_attrlist_by_handle(
goto out_vn_rele;
cursor = (attrlist_cursor_kern_t *)&al_hreq.pos;
- error = bhv_vop_attr_list(vp, kbuf, al_hreq.buflen, al_hreq.flags,
- cursor, NULL);
+ error = xfs_attr_list(XFS_I(inode), kbuf, al_hreq.buflen,
+ al_hreq.flags, cursor);
if (error)
goto out_kfree;
@@ -488,7 +516,7 @@ xfs_attrlist_by_handle(
STATIC int
xfs_attrmulti_attr_get(
- bhv_vnode_t *vp,
+ struct inode *inode,
char *name,
char __user *ubuf,
__uint32_t *len,
@@ -503,7 +531,7 @@ xfs_attrmulti_attr_get(
if (!kbuf)
return ENOMEM;
- error = bhv_vop_attr_get(vp, name, kbuf, len, flags, NULL);
+ error = xfs_attr_get(XFS_I(inode), name, kbuf, len, flags, NULL);
if (error)
goto out_kfree;
@@ -517,7 +545,7 @@ xfs_attrmulti_attr_get(
STATIC int
xfs_attrmulti_attr_set(
- bhv_vnode_t *vp,
+ struct inode *inode,
char *name,
const char __user *ubuf,
__uint32_t len,
@@ -526,9 +554,9 @@ xfs_attrmulti_attr_set(
char *kbuf;
int error = EFAULT;
- if (IS_RDONLY(&vp->v_inode))
+ if (IS_RDONLY(inode))
return -EROFS;
- if (IS_IMMUTABLE(&vp->v_inode) || IS_APPEND(&vp->v_inode))
+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
return EPERM;
if (len > XATTR_SIZE_MAX)
return EINVAL;
@@ -540,7 +568,7 @@ xfs_attrmulti_attr_set(
if (copy_from_user(kbuf, ubuf, len))
goto out_kfree;
- error = bhv_vop_attr_set(vp, name, kbuf, len, flags, NULL);
+ error = xfs_attr_set(XFS_I(inode), name, kbuf, len, flags);
out_kfree:
kfree(kbuf);
@@ -549,15 +577,15 @@ xfs_attrmulti_attr_set(
STATIC int
xfs_attrmulti_attr_remove(
- bhv_vnode_t *vp,
+ struct inode *inode,
char *name,
__uint32_t flags)
{
- if (IS_RDONLY(&vp->v_inode))
+ if (IS_RDONLY(inode))
return -EROFS;
- if (IS_IMMUTABLE(&vp->v_inode) || IS_APPEND(&vp->v_inode))
+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
return EPERM;
- return bhv_vop_attr_remove(vp, name, flags, NULL);
+ return xfs_attr_remove(XFS_I(inode), name, flags);
}
STATIC int
@@ -613,17 +641,17 @@ xfs_attrmulti_by_handle(
switch (ops[i].am_opcode) {
case ATTR_OP_GET:
- ops[i].am_error = xfs_attrmulti_attr_get(vp,
+ ops[i].am_error = xfs_attrmulti_attr_get(inode,
attr_name, ops[i].am_attrvalue,
&ops[i].am_length, ops[i].am_flags);
break;
case ATTR_OP_SET:
- ops[i].am_error = xfs_attrmulti_attr_set(vp,
+ ops[i].am_error = xfs_attrmulti_attr_set(inode,
attr_name, ops[i].am_attrvalue,
ops[i].am_length, ops[i].am_flags);
break;
case ATTR_OP_REMOVE:
- ops[i].am_error = xfs_attrmulti_attr_remove(vp,
+ ops[i].am_error = xfs_attrmulti_attr_remove(inode,
attr_name, ops[i].am_flags);
break;
default:
@@ -649,7 +677,7 @@ xfs_attrmulti_by_handle(
STATIC int
xfs_ioc_space(
- bhv_desc_t *bdp,
+ struct xfs_inode *ip,
struct inode *inode,
struct file *filp,
int flags,
@@ -681,37 +709,37 @@ xfs_ioc_xattr(
void __user *arg);
STATIC int
+xfs_ioc_fsgetxattr(
+ xfs_inode_t *ip,
+ int attr,
+ void __user *arg);
+
+STATIC int
xfs_ioc_getbmap(
- bhv_desc_t *bdp,
+ struct xfs_inode *ip,
int flags,
unsigned int cmd,
void __user *arg);
STATIC int
xfs_ioc_getbmapx(
- bhv_desc_t *bdp,
+ struct xfs_inode *ip,
void __user *arg);
int
xfs_ioctl(
- bhv_desc_t *bdp,
- struct inode *inode,
+ xfs_inode_t *ip,
struct file *filp,
int ioflags,
unsigned int cmd,
void __user *arg)
{
+ struct inode *inode = filp->f_path.dentry->d_inode;
+ bhv_vnode_t *vp = vn_from_inode(inode);
+ xfs_mount_t *mp = ip->i_mount;
int error;
- bhv_vnode_t *vp;
- xfs_inode_t *ip;
- xfs_mount_t *mp;
- vp = vn_from_inode(inode);
-
- vn_trace_entry(vp, "xfs_ioctl", (inst_t *)__return_address);
-
- ip = XFS_BHVTOI(bdp);
- mp = ip->i_mount;
+ vn_trace_entry(XFS_I(inode), "xfs_ioctl", (inst_t *)__return_address);
switch (cmd) {
@@ -731,7 +759,7 @@ xfs_ioctl(
!capable(CAP_SYS_ADMIN))
return -EPERM;
- return xfs_ioc_space(bdp, inode, filp, ioflags, cmd, arg);
+ return xfs_ioc_space(ip, inode, filp, ioflags, cmd, arg);
case XFS_IOC_DIOINFO: {
struct dioattr da;
@@ -761,11 +789,13 @@ xfs_ioctl(
case XFS_IOC_GETVERSION:
return put_user(inode->i_generation, (int __user *)arg);
+ case XFS_IOC_FSGETXATTR:
+ return xfs_ioc_fsgetxattr(ip, 0, arg);
+ case XFS_IOC_FSGETXATTRA:
+ return xfs_ioc_fsgetxattr(ip, 1, arg);
case XFS_IOC_GETXFLAGS:
case XFS_IOC_SETXFLAGS:
- case XFS_IOC_FSGETXATTR:
case XFS_IOC_FSSETXATTR:
- case XFS_IOC_FSGETXATTRA:
return xfs_ioc_xattr(vp, ip, filp, cmd, arg);
case XFS_IOC_FSSETDM: {
@@ -774,17 +804,17 @@ xfs_ioctl(
if (copy_from_user(&dmi, arg, sizeof(dmi)))
return -XFS_ERROR(EFAULT);
- error = xfs_set_dmattrs(bdp, dmi.fsd_dmevmask, dmi.fsd_dmstate,
- NULL);
+ error = xfs_set_dmattrs(ip, dmi.fsd_dmevmask,
+ dmi.fsd_dmstate);
return -error;
}
case XFS_IOC_GETBMAP:
case XFS_IOC_GETBMAPA:
- return xfs_ioc_getbmap(bdp, ioflags, cmd, arg);
+ return xfs_ioc_getbmap(ip, ioflags, cmd, arg);
case XFS_IOC_GETBMAPX:
- return xfs_ioc_getbmapx(bdp, arg);
+ return xfs_ioc_getbmapx(ip, arg);
case XFS_IOC_FD_TO_HANDLE:
case XFS_IOC_PATH_TO_HANDLE:
@@ -944,7 +974,7 @@ xfs_ioctl(
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- error = xfs_errortag_clearall(mp);
+ error = xfs_errortag_clearall(mp, 1);
return -error;
default:
@@ -954,7 +984,7 @@ xfs_ioctl(
STATIC int
xfs_ioc_space(
- bhv_desc_t *bdp,
+ struct xfs_inode *ip,
struct inode *inode,
struct file *filp,
int ioflags,
@@ -982,7 +1012,7 @@ xfs_ioc_space(
if (ioflags & IO_INVIS)
attr_flags |= ATTR_DMI;
- error = xfs_change_file_space(bdp, cmd, &bf, filp->f_pos,
+ error = xfs_change_file_space(ip, cmd, &bf, filp->f_pos,
NULL, attr_flags);
return -error;
}
@@ -1140,6 +1170,42 @@ xfs_di2lxflags(
}
STATIC int
+xfs_ioc_fsgetxattr(
+ xfs_inode_t *ip,
+ int attr,
+ void __user *arg)
+{
+ struct fsxattr fa;
+
+ xfs_ilock(ip, XFS_ILOCK_SHARED);
+ fa.fsx_xflags = xfs_ip2xflags(ip);
+ fa.fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog;
+ fa.fsx_projid = ip->i_d.di_projid;
+
+ if (attr) {
+ if (ip->i_afp) {
+ if (ip->i_afp->if_flags & XFS_IFEXTENTS)
+ fa.fsx_nextents = ip->i_afp->if_bytes /
+ sizeof(xfs_bmbt_rec_t);
+ else
+ fa.fsx_nextents = ip->i_d.di_anextents;
+ } else
+ fa.fsx_nextents = 0;
+ } else {
+ if (ip->i_df.if_flags & XFS_IFEXTENTS)
+ fa.fsx_nextents = ip->i_df.if_bytes /
+ sizeof(xfs_bmbt_rec_t);
+ else
+ fa.fsx_nextents = ip->i_d.di_nextents;
+ }
+ xfs_iunlock(ip, XFS_ILOCK_SHARED);
+
+ if (copy_to_user(arg, &fa, sizeof(fa)))
+ return -EFAULT;
+ return 0;
+}
+
+STATIC int
xfs_ioc_xattr(
bhv_vnode_t *vp,
xfs_inode_t *ip,
@@ -1158,27 +1224,6 @@ xfs_ioc_xattr(
return -ENOMEM;
switch (cmd) {
- case XFS_IOC_FSGETXATTR: {
- vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \
- XFS_AT_NEXTENTS | XFS_AT_PROJID;
- error = bhv_vop_getattr(vp, vattr, 0, NULL);
- if (unlikely(error)) {
- error = -error;
- break;
- }
-
- fa.fsx_xflags = vattr->va_xflags;
- fa.fsx_extsize = vattr->va_extsize;
- fa.fsx_nextents = vattr->va_nextents;
- fa.fsx_projid = vattr->va_projid;
-
- if (copy_to_user(arg, &fa, sizeof(fa))) {
- error = -EFAULT;
- break;
- }
- break;
- }
-
case XFS_IOC_FSSETXATTR: {
if (copy_from_user(&fa, arg, sizeof(fa))) {
error = -EFAULT;
@@ -1194,34 +1239,13 @@ xfs_ioc_xattr(
vattr->va_extsize = fa.fsx_extsize;
vattr->va_projid = fa.fsx_projid;
- error = bhv_vop_setattr(vp, vattr, attr_flags, NULL);
+ error = xfs_setattr(ip, vattr, attr_flags, NULL);
if (likely(!error))
__vn_revalidate(vp, vattr); /* update flags */
error = -error;
break;
}
- case XFS_IOC_FSGETXATTRA: {
- vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \
- XFS_AT_ANEXTENTS | XFS_AT_PROJID;
- error = bhv_vop_getattr(vp, vattr, 0, NULL);
- if (unlikely(error)) {
- error = -error;
- break;
- }
-
- fa.fsx_xflags = vattr->va_xflags;
- fa.fsx_extsize = vattr->va_extsize;
- fa.fsx_nextents = vattr->va_anextents;
- fa.fsx_projid = vattr->va_projid;
-
- if (copy_to_user(arg, &fa, sizeof(fa))) {
- error = -EFAULT;
- break;
- }
- break;
- }
-
case XFS_IOC_GETXFLAGS: {
flags = xfs_di2lxflags(ip->i_d.di_flags);
if (copy_to_user(arg, &flags, sizeof(flags)))
@@ -1250,7 +1274,7 @@ xfs_ioc_xattr(
vattr->va_xflags = xfs_merge_ioc_xflags(flags,
xfs_ip2xflags(ip));
- error = bhv_vop_setattr(vp, vattr, attr_flags, NULL);
+ error = xfs_setattr(ip, vattr, attr_flags, NULL);
if (likely(!error))
__vn_revalidate(vp, vattr); /* update flags */
error = -error;
@@ -1268,7 +1292,7 @@ xfs_ioc_xattr(
STATIC int
xfs_ioc_getbmap(
- bhv_desc_t *bdp,
+ struct xfs_inode *ip,
int ioflags,
unsigned int cmd,
void __user *arg)
@@ -1287,7 +1311,7 @@ xfs_ioc_getbmap(
if (ioflags & IO_INVIS)
iflags |= BMV_IF_NO_DMAPI_READ;
- error = xfs_getbmap(bdp, &bm, (struct getbmap __user *)arg+1, iflags);
+ error = xfs_getbmap(ip, &bm, (struct getbmap __user *)arg+1, iflags);
if (error)
return -error;
@@ -1298,7 +1322,7 @@ xfs_ioc_getbmap(
STATIC int
xfs_ioc_getbmapx(
- bhv_desc_t *bdp,
+ struct xfs_inode *ip,
void __user *arg)
{
struct getbmapx bmx;
@@ -1325,7 +1349,7 @@ xfs_ioc_getbmapx(
iflags |= BMV_IF_EXTENDED;
- error = xfs_getbmap(bdp, &bm, (struct getbmapx __user *)arg+1, iflags);
+ error = xfs_getbmap(ip, &bm, (struct getbmapx __user *)arg+1, iflags);
if (error)
return -error;
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c
index 42319d75aaab..0046bdd5b7f1 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl32.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl32.c
@@ -43,6 +43,7 @@
#include "xfs_itable.h"
#include "xfs_error.h"
#include "xfs_dfrag.h"
+#include "xfs_vnodeops.h"
#define _NATIVE_IOC(cmd, type) \
_IOC(_IOC_DIR(cmd), _IOC_TYPE(cmd), _IOC_NR(cmd), sizeof(type))
@@ -370,7 +371,6 @@ xfs_compat_ioctl(
unsigned long arg)
{
struct inode *inode = file->f_path.dentry->d_inode;
- bhv_vnode_t *vp = vn_from_inode(inode);
int error;
switch (cmd) {
@@ -443,7 +443,7 @@ xfs_compat_ioctl(
case XFS_IOC_FSBULKSTAT_SINGLE_32:
case XFS_IOC_FSINUMBERS_32:
cmd = _NATIVE_IOC(cmd, struct xfs_fsop_bulkreq);
- return xfs_ioc_bulkstat_compat(XFS_BHVTOI(VNHEAD(vp))->i_mount,
+ return xfs_ioc_bulkstat_compat(XFS_I(inode)->i_mount,
cmd, (void __user*)arg);
case XFS_IOC_FD_TO_HANDLE_32:
case XFS_IOC_PATH_TO_HANDLE_32:
@@ -457,8 +457,8 @@ xfs_compat_ioctl(
return -ENOIOCTLCMD;
}
- error = bhv_vop_ioctl(vp, inode, file, mode, cmd, (void __user *)arg);
- VMODIFY(vp);
+ error = xfs_ioctl(XFS_I(inode), file, mode, cmd, (void __user *)arg);
+ xfs_iflags_set(XFS_I(inode), XFS_IMODIFIED);
return error;
}
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index 0b5fa124bef2..ac50f8a37582 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -46,6 +46,7 @@
#include "xfs_attr.h"
#include "xfs_buf_item.h"
#include "xfs_utils.h"
+#include "xfs_vnodeops.h"
#include <linux/capability.h>
#include <linux/xattr.h>
@@ -53,22 +54,6 @@
#include <linux/security.h>
/*
- * Get a XFS inode from a given vnode.
- */
-xfs_inode_t *
-xfs_vtoi(
- bhv_vnode_t *vp)
-{
- bhv_desc_t *bdp;
-
- bdp = bhv_lookup_range(VN_BHV_HEAD(vp),
- VNODE_POSITION_XFS, VNODE_POSITION_XFS);
- if (unlikely(bdp == NULL))
- return NULL;
- return XFS_BHVTOI(bdp);
-}
-
-/*
* Bring the atime in the XFS inode uptodate.
* Used before logging the inode to disk or when the Linux inode goes away.
*/
@@ -80,9 +65,8 @@ xfs_synchronize_atime(
vp = XFS_ITOV_NULL(ip);
if (vp) {
- struct inode *inode = &vp->v_inode;
- ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec;
- ip->i_d.di_atime.t_nsec = (__int32_t)inode->i_atime.tv_nsec;
+ ip->i_d.di_atime.t_sec = (__int32_t)vp->i_atime.tv_sec;
+ ip->i_d.di_atime.t_nsec = (__int32_t)vp->i_atime.tv_nsec;
}
}
@@ -133,7 +117,7 @@ xfs_ichgtime(
*/
SYNCHRONIZE();
ip->i_update_core = 1;
- if (!(inode->i_state & I_LOCK))
+ if (!(inode->i_state & I_SYNC))
mark_inode_dirty_sync(inode);
}
@@ -185,7 +169,7 @@ xfs_ichgtime_fast(
*/
SYNCHRONIZE();
ip->i_update_core = 1;
- if (!(inode->i_state & I_LOCK))
+ if (!(inode->i_state & I_SYNC))
mark_inode_dirty_sync(inode);
}
@@ -195,18 +179,19 @@ xfs_ichgtime_fast(
*/
STATIC void
xfs_validate_fields(
- struct inode *ip,
- bhv_vattr_t *vattr)
+ struct inode *inode)
{
- vattr->va_mask = XFS_AT_NLINK|XFS_AT_SIZE|XFS_AT_NBLOCKS;
- if (!bhv_vop_getattr(vn_from_inode(ip), vattr, ATTR_LAZY, NULL)) {
- ip->i_nlink = vattr->va_nlink;
- ip->i_blocks = vattr->va_nblocks;
-
- /* we're under i_sem so i_size can't change under us */
- if (i_size_read(ip) != vattr->va_size)
- i_size_write(ip, vattr->va_size);
- }
+ struct xfs_inode *ip = XFS_I(inode);
+ loff_t size;
+
+ inode->i_nlink = ip->i_d.di_nlink;
+ inode->i_blocks =
+ XFS_FSB_TO_BB(ip->i_mount, ip->i_d.di_nblocks +
+ ip->i_delayed_blks);
+ /* we're under i_sem so i_size can't change under us */
+ size = XFS_ISIZE(ip);
+ if (i_size_read(inode) != size)
+ i_size_write(inode, size);
}
/*
@@ -233,9 +218,10 @@ xfs_init_security(
return -error;
}
- error = bhv_vop_attr_set(vp, name, value, length, ATTR_SECURE, NULL);
+ error = xfs_attr_set(XFS_I(ip), name, value,
+ length, ATTR_SECURE);
if (!error)
- VMODIFY(vp);
+ xfs_iflags_set(XFS_I(ip), XFS_IMODIFIED);
kfree(name);
kfree(value);
@@ -256,7 +242,7 @@ xfs_has_fs_struct(struct task_struct *task)
STATIC void
xfs_cleanup_inode(
- bhv_vnode_t *dvp,
+ struct inode *dir,
bhv_vnode_t *vp,
struct dentry *dentry,
int mode)
@@ -272,9 +258,9 @@ xfs_cleanup_inode(
teardown.d_name = dentry->d_name;
if (S_ISDIR(mode))
- bhv_vop_rmdir(dvp, &teardown, NULL);
+ xfs_rmdir(XFS_I(dir), &teardown);
else
- bhv_vop_remove(dvp, &teardown, NULL);
+ xfs_remove(XFS_I(dir), &teardown);
VN_RELE(vp);
}
@@ -286,7 +272,6 @@ xfs_vn_mknod(
dev_t rdev)
{
struct inode *ip;
- bhv_vattr_t vattr = { 0 };
bhv_vnode_t *vp = NULL, *dvp = vn_from_inode(dir);
xfs_acl_t *default_acl = NULL;
attrexists_t test_default_acl = _ACL_DEFAULT_EXISTS;
@@ -312,19 +297,14 @@ xfs_vn_mknod(
if (IS_POSIXACL(dir) && !default_acl && xfs_has_fs_struct(current))
mode &= ~current->fs->umask;
- vattr.va_mask = XFS_AT_TYPE|XFS_AT_MODE;
- vattr.va_mode = mode;
-
switch (mode & S_IFMT) {
case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK:
- vattr.va_rdev = sysv_encode_dev(rdev);
- vattr.va_mask |= XFS_AT_RDEV;
- /*FALLTHROUGH*/
+ rdev = sysv_encode_dev(rdev);
case S_IFREG:
- error = bhv_vop_create(dvp, dentry, &vattr, &vp, NULL);
+ error = xfs_create(XFS_I(dir), dentry, mode, rdev, &vp, NULL);
break;
case S_IFDIR:
- error = bhv_vop_mkdir(dvp, dentry, &vattr, &vp, NULL);
+ error = xfs_mkdir(XFS_I(dir), dentry, mode, &vp, NULL);
break;
default:
error = EINVAL;
@@ -334,16 +314,16 @@ xfs_vn_mknod(
if (unlikely(!error)) {
error = xfs_init_security(vp, dir);
if (error)
- xfs_cleanup_inode(dvp, vp, dentry, mode);
+ xfs_cleanup_inode(dir, vp, dentry, mode);
}
if (unlikely(default_acl)) {
if (!error) {
- error = _ACL_INHERIT(vp, &vattr, default_acl);
+ error = _ACL_INHERIT(vp, mode, default_acl);
if (!error)
- VMODIFY(vp);
+ xfs_iflags_set(XFS_I(vp), XFS_IMODIFIED);
else
- xfs_cleanup_inode(dvp, vp, dentry, mode);
+ xfs_cleanup_inode(dir, vp, dentry, mode);
}
_ACL_FREE(default_acl);
}
@@ -355,9 +335,9 @@ xfs_vn_mknod(
if (S_ISCHR(mode) || S_ISBLK(mode))
ip->i_rdev = rdev;
else if (S_ISDIR(mode))
- xfs_validate_fields(ip, &vattr);
+ xfs_validate_fields(ip);
d_instantiate(dentry, ip);
- xfs_validate_fields(dir, &vattr);
+ xfs_validate_fields(dir);
}
return -error;
}
@@ -387,13 +367,13 @@ xfs_vn_lookup(
struct dentry *dentry,
struct nameidata *nd)
{
- bhv_vnode_t *vp = vn_from_inode(dir), *cvp;
+ bhv_vnode_t *cvp;
int error;
if (dentry->d_name.len >= MAXNAMELEN)
return ERR_PTR(-ENAMETOOLONG);
- error = bhv_vop_lookup(vp, dentry, &cvp, 0, NULL, NULL);
+ error = xfs_lookup(XFS_I(dir), dentry, &cvp);
if (unlikely(error)) {
if (unlikely(error != ENOENT))
return ERR_PTR(-error);
@@ -411,22 +391,19 @@ xfs_vn_link(
struct dentry *dentry)
{
struct inode *ip; /* inode of guy being linked to */
- bhv_vnode_t *tdvp; /* target directory for new name/link */
bhv_vnode_t *vp; /* vp of name being linked */
- bhv_vattr_t vattr;
int error;
ip = old_dentry->d_inode; /* inode being linked to */
- tdvp = vn_from_inode(dir);
vp = vn_from_inode(ip);
VN_HOLD(vp);
- error = bhv_vop_link(tdvp, vp, dentry, NULL);
+ error = xfs_link(XFS_I(dir), vp, dentry);
if (unlikely(error)) {
VN_RELE(vp);
} else {
- VMODIFY(tdvp);
- xfs_validate_fields(ip, &vattr);
+ xfs_iflags_set(XFS_I(dir), XFS_IMODIFIED);
+ xfs_validate_fields(ip);
d_instantiate(dentry, ip);
}
return -error;
@@ -438,17 +415,14 @@ xfs_vn_unlink(
struct dentry *dentry)
{
struct inode *inode;
- bhv_vnode_t *dvp; /* directory containing name to remove */
- bhv_vattr_t vattr;
int error;
inode = dentry->d_inode;
- dvp = vn_from_inode(dir);
- error = bhv_vop_remove(dvp, dentry, NULL);
+ error = xfs_remove(XFS_I(dir), dentry);
if (likely(!error)) {
- xfs_validate_fields(dir, &vattr); /* size needs update */
- xfs_validate_fields(inode, &vattr);
+ xfs_validate_fields(dir); /* size needs update */
+ xfs_validate_fields(inode);
}
return -error;
}
@@ -460,28 +434,26 @@ xfs_vn_symlink(
const char *symname)
{
struct inode *ip;
- bhv_vattr_t va = { 0 };
- bhv_vnode_t *dvp; /* directory containing name of symlink */
bhv_vnode_t *cvp; /* used to lookup symlink to put in dentry */
int error;
+ mode_t mode;
- dvp = vn_from_inode(dir);
cvp = NULL;
- va.va_mode = S_IFLNK |
+ mode = S_IFLNK |
(irix_symlink_mode ? 0777 & ~current->fs->umask : S_IRWXUGO);
- va.va_mask = XFS_AT_TYPE|XFS_AT_MODE;
- error = bhv_vop_symlink(dvp, dentry, &va, (char *)symname, &cvp, NULL);
+ error = xfs_symlink(XFS_I(dir), dentry, (char *)symname, mode,
+ &cvp, NULL);
if (likely(!error && cvp)) {
error = xfs_init_security(cvp, dir);
if (likely(!error)) {
ip = vn_to_inode(cvp);
d_instantiate(dentry, ip);
- xfs_validate_fields(dir, &va);
- xfs_validate_fields(ip, &va);
+ xfs_validate_fields(dir);
+ xfs_validate_fields(ip);
} else {
- xfs_cleanup_inode(dvp, cvp, dentry, 0);
+ xfs_cleanup_inode(dir, cvp, dentry, 0);
}
}
return -error;
@@ -493,14 +465,12 @@ xfs_vn_rmdir(
struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
- bhv_vnode_t *dvp = vn_from_inode(dir);
- bhv_vattr_t vattr;
int error;
- error = bhv_vop_rmdir(dvp, dentry, NULL);
+ error = xfs_rmdir(XFS_I(dir), dentry);
if (likely(!error)) {
- xfs_validate_fields(inode, &vattr);
- xfs_validate_fields(dir, &vattr);
+ xfs_validate_fields(inode);
+ xfs_validate_fields(dir);
}
return -error;
}
@@ -513,21 +483,18 @@ xfs_vn_rename(
struct dentry *ndentry)
{
struct inode *new_inode = ndentry->d_inode;
- bhv_vnode_t *fvp; /* from directory */
bhv_vnode_t *tvp; /* target directory */
- bhv_vattr_t vattr;
int error;
- fvp = vn_from_inode(odir);
tvp = vn_from_inode(ndir);
- error = bhv_vop_rename(fvp, odentry, tvp, ndentry, NULL);
+ error = xfs_rename(XFS_I(odir), odentry, tvp, ndentry);
if (likely(!error)) {
if (new_inode)
- xfs_validate_fields(new_inode, &vattr);
- xfs_validate_fields(odir, &vattr);
+ xfs_validate_fields(new_inode);
+ xfs_validate_fields(odir);
if (ndir != odir)
- xfs_validate_fields(ndir, &vattr);
+ xfs_validate_fields(ndir);
}
return -error;
}
@@ -542,50 +509,25 @@ xfs_vn_follow_link(
struct dentry *dentry,
struct nameidata *nd)
{
- bhv_vnode_t *vp;
- uio_t *uio;
- iovec_t iov;
- int error;
char *link;
-
- ASSERT(dentry);
- ASSERT(nd);
+ int error = -ENOMEM;
link = kmalloc(MAXPATHLEN+1, GFP_KERNEL);
- if (!link) {
- nd_set_link(nd, ERR_PTR(-ENOMEM));
- return NULL;
- }
-
- uio = kmalloc(sizeof(uio_t), GFP_KERNEL);
- if (!uio) {
- kfree(link);
- nd_set_link(nd, ERR_PTR(-ENOMEM));
- return NULL;
- }
-
- vp = vn_from_inode(dentry->d_inode);
-
- iov.iov_base = link;
- iov.iov_len = MAXPATHLEN;
+ if (!link)
+ goto out_err;
- uio->uio_iov = &iov;
- uio->uio_offset = 0;
- uio->uio_segflg = UIO_SYSSPACE;
- uio->uio_resid = MAXPATHLEN;
- uio->uio_iovcnt = 1;
-
- error = bhv_vop_readlink(vp, uio, 0, NULL);
- if (unlikely(error)) {
- kfree(link);
- link = ERR_PTR(-error);
- } else {
- link[MAXPATHLEN - uio->uio_resid] = '\0';
- }
- kfree(uio);
+ error = -xfs_readlink(XFS_I(dentry->d_inode), link);
+ if (unlikely(error))
+ goto out_kfree;
nd_set_link(nd, link);
return NULL;
+
+ out_kfree:
+ kfree(link);
+ out_err:
+ nd_set_link(nd, ERR_PTR(error));
+ return NULL;
}
STATIC void
@@ -607,7 +549,7 @@ xfs_vn_permission(
int mode,
struct nameidata *nd)
{
- return -bhv_vop_access(vn_from_inode(inode), mode << 6, NULL);
+ return -xfs_access(XFS_I(inode), mode << 6, NULL);
}
#else
#define xfs_vn_permission NULL
@@ -620,11 +562,10 @@ xfs_vn_getattr(
struct kstat *stat)
{
struct inode *inode = dentry->d_inode;
- bhv_vnode_t *vp = vn_from_inode(inode);
bhv_vattr_t vattr = { .va_mask = XFS_AT_STAT };
int error;
- error = bhv_vop_getattr(vp, &vattr, ATTR_LAZY, NULL);
+ error = xfs_getattr(XFS_I(inode), &vattr, ATTR_LAZY);
if (likely(!error)) {
stat->size = i_size_read(inode);
stat->dev = inode->i_sb->s_dev;
@@ -652,7 +593,6 @@ xfs_vn_setattr(
{
struct inode *inode = dentry->d_inode;
unsigned int ia_valid = attr->ia_valid;
- bhv_vnode_t *vp = vn_from_inode(inode);
bhv_vattr_t vattr = { 0 };
int flags = 0;
int error;
@@ -696,9 +636,9 @@ xfs_vn_setattr(
flags |= ATTR_NONBLOCK;
#endif
- error = bhv_vop_setattr(vp, &vattr, flags, NULL);
+ error = xfs_setattr(XFS_I(inode), &vattr, flags, NULL);
if (likely(!error))
- __vn_revalidate(vp, &vattr);
+ __vn_revalidate(vn_from_inode(inode), &vattr);
return -error;
}
diff --git a/fs/xfs/linux-2.6/xfs_iops.h b/fs/xfs/linux-2.6/xfs_iops.h
index 95a69398fce0..14d0deb7afff 100644
--- a/fs/xfs/linux-2.6/xfs_iops.h
+++ b/fs/xfs/linux-2.6/xfs_iops.h
@@ -26,11 +26,15 @@ extern const struct file_operations xfs_file_operations;
extern const struct file_operations xfs_dir_file_operations;
extern const struct file_operations xfs_invis_file_operations;
-extern int xfs_ioctl(struct bhv_desc *, struct inode *, struct file *,
- int, unsigned int, void __user *);
struct xfs_inode;
extern void xfs_ichgtime(struct xfs_inode *, int);
extern void xfs_ichgtime_fast(struct xfs_inode *, struct inode *, int);
+#define xfs_vtoi(vp) \
+ ((struct xfs_inode *)vn_to_inode(vp)->i_private)
+
+#define XFS_I(inode) \
+ ((struct xfs_inode *)(inode)->i_private)
+
#endif /* __XFS_IOPS_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index 330c4ba9d404..dc3752de22da 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -51,7 +51,6 @@
#include <support/ktrace.h>
#include <support/debug.h>
-#include <support/move.h>
#include <support/uuid.h>
#include <linux/mm.h>
@@ -75,6 +74,7 @@
#include <linux/cpu.h>
#include <linux/notifier.h>
#include <linux/delay.h>
+#include <linux/log2.h>
#include <asm/page.h>
#include <asm/div64.h>
@@ -83,7 +83,6 @@
#include <asm/byteorder.h>
#include <asm/unaligned.h>
-#include <xfs_behavior.h>
#include <xfs_vfs.h>
#include <xfs_cred.h>
#include <xfs_vnode.h>
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index 765ec16a6e39..d6a8dddb2268 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -48,6 +48,7 @@
#include "xfs_buf_item.h"
#include "xfs_utils.h"
#include "xfs_iomap.h"
+#include "xfs_vnodeops.h"
#include <linux/capability.h>
#include <linux/writeback.h>
@@ -134,45 +135,34 @@ xfs_iozero(
loff_t pos, /* offset in file */
size_t count) /* size of data to zero */
{
- unsigned bytes;
struct page *page;
struct address_space *mapping;
int status;
mapping = ip->i_mapping;
do {
- unsigned long index, offset;
+ unsigned offset, bytes;
+ void *fsdata;
offset = (pos & (PAGE_CACHE_SIZE -1)); /* Within page */
- index = pos >> PAGE_CACHE_SHIFT;
bytes = PAGE_CACHE_SIZE - offset;
if (bytes > count)
bytes = count;
- status = -ENOMEM;
- page = grab_cache_page(mapping, index);
- if (!page)
- break;
-
- status = mapping->a_ops->prepare_write(NULL, page, offset,
- offset + bytes);
+ status = pagecache_write_begin(NULL, mapping, pos, bytes,
+ AOP_FLAG_UNINTERRUPTIBLE,
+ &page, &fsdata);
if (status)
- goto unlock;
+ break;
zero_user_page(page, offset, bytes, KM_USER0);
- status = mapping->a_ops->commit_write(NULL, page, offset,
- offset + bytes);
- if (!status) {
- pos += bytes;
- count -= bytes;
- }
-
-unlock:
- unlock_page(page);
- page_cache_release(page);
- if (status)
- break;
+ status = pagecache_write_end(NULL, mapping, pos, bytes, bytes,
+ page, fsdata);
+ WARN_ON(status <= 0); /* can't return less than zero! */
+ pos += bytes;
+ count -= bytes;
+ status = 0;
} while (count);
return (-status);
@@ -180,27 +170,22 @@ unlock:
ssize_t /* bytes read, or (-) error */
xfs_read(
- bhv_desc_t *bdp,
+ xfs_inode_t *ip,
struct kiocb *iocb,
const struct iovec *iovp,
unsigned int segs,
loff_t *offset,
- int ioflags,
- cred_t *credp)
+ int ioflags)
{
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_mapping->host;
+ bhv_vnode_t *vp = XFS_ITOV(ip);
+ xfs_mount_t *mp = ip->i_mount;
size_t size = 0;
ssize_t ret = 0;
xfs_fsize_t n;
- xfs_inode_t *ip;
- xfs_mount_t *mp;
- bhv_vnode_t *vp;
unsigned long seg;
- ip = XFS_BHVTOI(bdp);
- vp = BHV_TO_VNODE(bdp);
- mp = ip->i_mount;
XFS_STATS_INC(xs_read_calls);
@@ -245,13 +230,11 @@ xfs_read(
mutex_lock(&inode->i_mutex);
xfs_ilock(ip, XFS_IOLOCK_SHARED);
- if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) &&
- !(ioflags & IO_INVIS)) {
+ if (DM_EVENT_ENABLED(ip, DM_EVENT_READ) && !(ioflags & IO_INVIS)) {
bhv_vrwlock_t locktype = VRWLOCK_READ;
int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags);
- ret = -XFS_SEND_DATA(mp, DM_EVENT_READ,
- BHV_TO_VNODE(bdp), *offset, size,
+ ret = -XFS_SEND_DATA(mp, DM_EVENT_READ, vp, *offset, size,
dmflags, &locktype);
if (ret) {
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
@@ -263,8 +246,9 @@ xfs_read(
if (unlikely(ioflags & IO_ISDIRECT)) {
if (VN_CACHED(vp))
- ret = bhv_vop_flushinval_pages(vp, ctooff(offtoct(*offset)),
- -1, FI_REMAPF_LOCKED);
+ ret = xfs_flushinval_pages(ip,
+ ctooff(offtoct(*offset)),
+ -1, FI_REMAPF_LOCKED);
mutex_unlock(&inode->i_mutex);
if (ret) {
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
@@ -288,16 +272,15 @@ xfs_read(
ssize_t
xfs_splice_read(
- bhv_desc_t *bdp,
+ xfs_inode_t *ip,
struct file *infilp,
loff_t *ppos,
struct pipe_inode_info *pipe,
size_t count,
int flags,
- int ioflags,
- cred_t *credp)
+ int ioflags)
{
- xfs_inode_t *ip = XFS_BHVTOI(bdp);
+ bhv_vnode_t *vp = XFS_ITOV(ip);
xfs_mount_t *mp = ip->i_mount;
ssize_t ret;
@@ -307,13 +290,11 @@ xfs_splice_read(
xfs_ilock(ip, XFS_IOLOCK_SHARED);
- if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) &&
- (!(ioflags & IO_INVIS))) {
+ if (DM_EVENT_ENABLED(ip, DM_EVENT_READ) && !(ioflags & IO_INVIS)) {
bhv_vrwlock_t locktype = VRWLOCK_READ;
int error;
- error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp),
- *ppos, count,
+ error = XFS_SEND_DATA(mp, DM_EVENT_READ, vp, *ppos, count,
FILP_DELAY_FLAG(infilp), &locktype);
if (error) {
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
@@ -332,16 +313,15 @@ xfs_splice_read(
ssize_t
xfs_splice_write(
- bhv_desc_t *bdp,
+ xfs_inode_t *ip,
struct pipe_inode_info *pipe,
struct file *outfilp,
loff_t *ppos,
size_t count,
int flags,
- int ioflags,
- cred_t *credp)
+ int ioflags)
{
- xfs_inode_t *ip = XFS_BHVTOI(bdp);
+ bhv_vnode_t *vp = XFS_ITOV(ip);
xfs_mount_t *mp = ip->i_mount;
xfs_iocore_t *io = &ip->i_iocore;
ssize_t ret;
@@ -354,13 +334,11 @@ xfs_splice_write(
xfs_ilock(ip, XFS_IOLOCK_EXCL);
- if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_WRITE) &&
- (!(ioflags & IO_INVIS))) {
+ if (DM_EVENT_ENABLED(ip, DM_EVENT_WRITE) && !(ioflags & IO_INVIS)) {
bhv_vrwlock_t locktype = VRWLOCK_WRITE;
int error;
- error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, BHV_TO_VNODE(bdp),
- *ppos, count,
+ error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, vp, *ppos, count,
FILP_DELAY_FLAG(outfilp), &locktype);
if (error) {
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
@@ -594,24 +572,22 @@ out_lock:
ssize_t /* bytes written, or (-) error */
xfs_write(
- bhv_desc_t *bdp,
+ struct xfs_inode *xip,
struct kiocb *iocb,
const struct iovec *iovp,
unsigned int nsegs,
loff_t *offset,
- int ioflags,
- cred_t *credp)
+ int ioflags)
{
struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping;
struct inode *inode = mapping->host;
+ bhv_vnode_t *vp = XFS_ITOV(xip);
unsigned long segs = nsegs;
- xfs_inode_t *xip;
xfs_mount_t *mp;
ssize_t ret = 0, error = 0;
xfs_fsize_t isize, new_size;
xfs_iocore_t *io;
- bhv_vnode_t *vp;
int iolock;
int eventsent = 0;
bhv_vrwlock_t locktype;
@@ -621,9 +597,6 @@ xfs_write(
XFS_STATS_INC(xs_write_calls);
- vp = BHV_TO_VNODE(bdp);
- xip = XFS_BHVTOI(bdp);
-
error = generic_segment_checks(iovp, &segs, &ocount, VERIFY_READ);
if (error)
return error;
@@ -637,7 +610,7 @@ xfs_write(
io = &xip->i_iocore;
mp = io->io_mount;
- vfs_wait_for_freeze(vp->v_vfsp, SB_FREEZE_WRITE);
+ xfs_wait_for_freeze(mp, SB_FREEZE_WRITE);
if (XFS_FORCED_SHUTDOWN(mp))
return -EIO;
@@ -664,7 +637,7 @@ start:
goto out_unlock_mutex;
}
- if ((DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_WRITE) &&
+ if ((DM_EVENT_ENABLED(xip, DM_EVENT_WRITE) &&
!(ioflags & IO_INVIS) && !eventsent)) {
int dmflags = FILP_DELAY_FLAG(file);
@@ -733,7 +706,7 @@ start:
*/
if (pos > xip->i_size) {
- error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, pos, xip->i_size);
+ error = xfs_zero_eof(vp, io, pos, xip->i_size);
if (error) {
xfs_iunlock(xip, XFS_ILOCK_EXCL);
goto out_unlock_internal;
@@ -769,7 +742,8 @@ retry:
WARN_ON(need_i_mutex == 0);
xfs_inval_cached_trace(io, pos, -1,
ctooff(offtoct(pos)), -1);
- error = bhv_vop_flushinval_pages(vp, ctooff(offtoct(pos)),
+ error = xfs_flushinval_pages(xip,
+ ctooff(offtoct(pos)),
-1, FI_REMAPF_LOCKED);
if (error)
goto out_unlock_internal;
@@ -816,11 +790,9 @@ retry:
if (ret == -EIOCBQUEUED && !(ioflags & IO_ISAIO))
ret = wait_on_sync_kiocb(iocb);
- if ((ret == -ENOSPC) &&
- DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_NOSPACE) &&
- !(ioflags & IO_INVIS)) {
-
- xfs_rwunlock(bdp, locktype);
+ if (ret == -ENOSPC &&
+ DM_EVENT_ENABLED(xip, DM_EVENT_NOSPACE) && !(ioflags & IO_INVIS)) {
+ xfs_rwunlock(xip, locktype);
if (need_i_mutex)
mutex_unlock(&inode->i_mutex);
error = XFS_SEND_NAMESP(xip->i_mount, DM_EVENT_NOSPACE, vp,
@@ -828,7 +800,7 @@ retry:
0, 0, 0); /* Delay flag intentionally unused */
if (need_i_mutex)
mutex_lock(&inode->i_mutex);
- xfs_rwlock(bdp, locktype);
+ xfs_rwlock(xip, locktype);
if (error)
goto out_unlock_internal;
pos = xip->i_size;
@@ -855,20 +827,19 @@ retry:
/* Handle various SYNC-type writes */
if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) {
- error = xfs_write_sync_logforce(mp, xip);
- if (error)
- goto out_unlock_internal;
-
- xfs_rwunlock(bdp, locktype);
+ int error2;
+ xfs_rwunlock(xip, locktype);
if (need_i_mutex)
mutex_unlock(&inode->i_mutex);
-
- error = sync_page_range(inode, mapping, pos, ret);
+ error2 = sync_page_range(inode, mapping, pos, ret);
if (!error)
- error = -ret;
+ error = error2;
if (need_i_mutex)
mutex_lock(&inode->i_mutex);
- xfs_rwlock(bdp, locktype);
+ xfs_rwlock(xip, locktype);
+ error2 = xfs_write_sync_logforce(mp, xip);
+ if (!error)
+ error = error2;
}
out_unlock_internal:
@@ -886,7 +857,7 @@ retry:
xip->i_d.di_size = xip->i_size;
xfs_iunlock(xip, XFS_ILOCK_EXCL);
}
- xfs_rwunlock(bdp, locktype);
+ xfs_rwunlock(xip, locktype);
out_unlock_mutex:
if (need_i_mutex)
mutex_unlock(&inode->i_mutex);
@@ -925,14 +896,14 @@ xfs_bdstrat_cb(struct xfs_buf *bp)
int
-xfs_bmap(bhv_desc_t *bdp,
+xfs_bmap(
+ xfs_inode_t *ip,
xfs_off_t offset,
ssize_t count,
int flags,
xfs_iomap_t *iomapp,
int *niomaps)
{
- xfs_inode_t *ip = XFS_BHVTOI(bdp);
xfs_iocore_t *io = &ip->i_iocore;
ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFREG);
diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h
index 7c60a1eed88b..4b7747a828d9 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.h
+++ b/fs/xfs/linux-2.6/xfs_lrw.h
@@ -18,8 +18,6 @@
#ifndef __XFS_LRW_H__
#define __XFS_LRW_H__
-struct bhv_desc;
-struct bhv_vnode;
struct xfs_mount;
struct xfs_iocore;
struct xfs_inode;
@@ -71,30 +69,11 @@ extern void xfs_inval_cached_trace(struct xfs_iocore *,
#define xfs_inval_cached_trace(io, offset, len, first, last)
#endif
-/*
- * Maximum count of bmaps used by read and write paths.
- */
-#define XFS_MAX_RW_NBMAPS 4
-
-extern int xfs_bmap(struct bhv_desc *, xfs_off_t, ssize_t, int,
- struct xfs_iomap *, int *);
extern int xfsbdstrat(struct xfs_mount *, struct xfs_buf *);
extern int xfs_bdstrat_cb(struct xfs_buf *);
extern int xfs_dev_is_read_only(struct xfs_mount *, char *);
-extern int xfs_zero_eof(struct bhv_vnode *, struct xfs_iocore *, xfs_off_t,
+extern int xfs_zero_eof(struct inode *, struct xfs_iocore *, xfs_off_t,
xfs_fsize_t);
-extern ssize_t xfs_read(struct bhv_desc *, struct kiocb *,
- const struct iovec *, unsigned int,
- loff_t *, int, struct cred *);
-extern ssize_t xfs_write(struct bhv_desc *, struct kiocb *,
- const struct iovec *, unsigned int,
- loff_t *, int, struct cred *);
-extern ssize_t xfs_splice_read(struct bhv_desc *, struct file *, loff_t *,
- struct pipe_inode_info *, size_t, int, int,
- struct cred *);
-extern ssize_t xfs_splice_write(struct bhv_desc *, struct pipe_inode_info *,
- struct file *, loff_t *, size_t, int, int,
- struct cred *);
#endif /* __XFS_LRW_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 491d1f4f202d..8cb63c60c048 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -46,6 +46,8 @@
#include "xfs_attr.h"
#include "xfs_buf_item.h"
#include "xfs_utils.h"
+#include "xfs_vnodeops.h"
+#include "xfs_vfsops.h"
#include "xfs_version.h"
#include <linux/namei.h>
@@ -196,23 +198,20 @@ xfs_revalidate_inode(
inode->i_flags |= S_NOATIME;
else
inode->i_flags &= ~S_NOATIME;
- vp->v_flag &= ~VMODIFIED;
+ xfs_iflags_clear(ip, XFS_IMODIFIED);
}
void
xfs_initialize_vnode(
- bhv_desc_t *bdp,
+ struct xfs_mount *mp,
bhv_vnode_t *vp,
- bhv_desc_t *inode_bhv,
- int unlock)
+ struct xfs_inode *ip)
{
- xfs_inode_t *ip = XFS_BHVTOI(inode_bhv);
struct inode *inode = vn_to_inode(vp);
- if (!inode_bhv->bd_vobj) {
- vp->v_vfsp = bhvtovfs(bdp);
- bhv_desc_init(inode_bhv, ip, vp, &xfs_vnodeops);
- bhv_insert(VN_BHV_HEAD(vp), inode_bhv);
+ if (!ip->i_vnode) {
+ ip->i_vnode = vp;
+ inode->i_private = ip;
}
/*
@@ -222,8 +221,8 @@ xfs_initialize_vnode(
* second time once the inode is properly set up, and then we can
* finish our work.
*/
- if (ip->i_d.di_mode != 0 && unlock && (inode->i_state & I_NEW)) {
- xfs_revalidate_inode(XFS_BHVTOM(bdp), vp, ip);
+ if (ip->i_d.di_mode != 0 && (inode->i_state & I_NEW)) {
+ xfs_revalidate_inode(mp, vp, ip);
xfs_set_inodeops(inode);
xfs_iflags_clear(ip, XFS_INEW);
@@ -356,9 +355,8 @@ xfs_fs_destroy_inode(
STATIC void
xfs_fs_inode_init_once(
- void *vnode,
kmem_zone_t *zonep,
- unsigned long flags)
+ void *vnode)
{
inode_init_once(vn_to_inode((bhv_vnode_t *)vnode));
}
@@ -410,19 +408,22 @@ xfs_fs_write_inode(
struct inode *inode,
int sync)
{
- bhv_vnode_t *vp = vn_from_inode(inode);
int error = 0, flags = FLUSH_INODE;
- if (vp) {
- vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
- if (sync) {
- filemap_fdatawait(inode->i_mapping);
- flags |= FLUSH_SYNC;
- }
- error = bhv_vop_iflush(vp, flags);
- if (error == EAGAIN)
- error = sync? bhv_vop_iflush(vp, flags | FLUSH_LOG) : 0;
+ vn_trace_entry(XFS_I(inode), __FUNCTION__,
+ (inst_t *)__return_address);
+ if (sync) {
+ filemap_fdatawait(inode->i_mapping);
+ flags |= FLUSH_SYNC;
}
+ error = xfs_inode_flush(XFS_I(inode), flags);
+ /*
+ * if we failed to write out the inode then mark
+ * it dirty again so we'll try again later.
+ */
+ if (error)
+ mark_inode_dirty_sync(inode);
+
return -error;
}
@@ -430,35 +431,27 @@ STATIC void
xfs_fs_clear_inode(
struct inode *inode)
{
- bhv_vnode_t *vp = vn_from_inode(inode);
-
- vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
-
- XFS_STATS_INC(vn_rele);
- XFS_STATS_INC(vn_remove);
- XFS_STATS_INC(vn_reclaim);
- XFS_STATS_DEC(vn_active);
+ xfs_inode_t *ip = XFS_I(inode);
/*
- * This can happen because xfs_iget_core calls xfs_idestroy if we
+ * ip can be null when xfs_iget_core calls xfs_idestroy if we
* find an inode with di_mode == 0 but without IGET_CREATE set.
*/
- if (VNHEAD(vp))
- bhv_vop_inactive(vp, NULL);
-
- VN_LOCK(vp);
- vp->v_flag &= ~VMODIFIED;
- VN_UNLOCK(vp, 0);
-
- if (VNHEAD(vp))
- if (bhv_vop_reclaim(vp))
- panic("%s: cannot reclaim 0x%p\n", __FUNCTION__, vp);
-
- ASSERT(VNHEAD(vp) == NULL);
+ if (ip) {
+ vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address);
+
+ XFS_STATS_INC(vn_rele);
+ XFS_STATS_INC(vn_remove);
+ XFS_STATS_INC(vn_reclaim);
+ XFS_STATS_DEC(vn_active);
+
+ xfs_inactive(ip);
+ xfs_iflags_clear(ip, XFS_IMODIFIED);
+ if (xfs_reclaim(ip))
+ panic("%s: cannot reclaim 0x%p\n", __FUNCTION__, inode);
+ }
-#ifdef XFS_VNODE_TRACE
- ktrace_free(vp->v_trace);
-#endif
+ ASSERT(XFS_I(inode) == NULL);
}
/*
@@ -470,9 +463,9 @@ xfs_fs_clear_inode(
*/
STATIC void
xfs_syncd_queue_work(
- struct bhv_vfs *vfs,
+ struct xfs_mount *mp,
void *data,
- void (*syncer)(bhv_vfs_t *, void *))
+ void (*syncer)(struct xfs_mount *, void *))
{
struct bhv_vfs_sync_work *work;
@@ -480,11 +473,11 @@ xfs_syncd_queue_work(
INIT_LIST_HEAD(&work->w_list);
work->w_syncer = syncer;
work->w_data = data;
- work->w_vfs = vfs;
- spin_lock(&vfs->vfs_sync_lock);
- list_add_tail(&work->w_list, &vfs->vfs_sync_list);
- spin_unlock(&vfs->vfs_sync_lock);
- wake_up_process(vfs->vfs_sync_task);
+ work->w_mount = mp;
+ spin_lock(&mp->m_sync_lock);
+ list_add_tail(&work->w_list, &mp->m_sync_list);
+ spin_unlock(&mp->m_sync_lock);
+ wake_up_process(mp->m_sync_task);
}
/*
@@ -495,22 +488,22 @@ xfs_syncd_queue_work(
*/
STATIC void
xfs_flush_inode_work(
- bhv_vfs_t *vfs,
- void *inode)
+ struct xfs_mount *mp,
+ void *arg)
{
- filemap_flush(((struct inode *)inode)->i_mapping);
- iput((struct inode *)inode);
+ struct inode *inode = arg;
+ filemap_flush(inode->i_mapping);
+ iput(inode);
}
void
xfs_flush_inode(
xfs_inode_t *ip)
{
- struct inode *inode = vn_to_inode(XFS_ITOV(ip));
- struct bhv_vfs *vfs = XFS_MTOVFS(ip->i_mount);
+ struct inode *inode = ip->i_vnode;
igrab(inode);
- xfs_syncd_queue_work(vfs, inode, xfs_flush_inode_work);
+ xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_inode_work);
delay(msecs_to_jiffies(500));
}
@@ -520,11 +513,12 @@ xfs_flush_inode(
*/
STATIC void
xfs_flush_device_work(
- bhv_vfs_t *vfs,
- void *inode)
+ struct xfs_mount *mp,
+ void *arg)
{
- sync_blockdev(vfs->vfs_super->s_bdev);
- iput((struct inode *)inode);
+ struct inode *inode = arg;
+ sync_blockdev(mp->m_super->s_bdev);
+ iput(inode);
}
void
@@ -532,35 +526,33 @@ xfs_flush_device(
xfs_inode_t *ip)
{
struct inode *inode = vn_to_inode(XFS_ITOV(ip));
- struct bhv_vfs *vfs = XFS_MTOVFS(ip->i_mount);
igrab(inode);
- xfs_syncd_queue_work(vfs, inode, xfs_flush_device_work);
+ xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_device_work);
delay(msecs_to_jiffies(500));
xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC);
}
STATIC void
-vfs_sync_worker(
- bhv_vfs_t *vfsp,
+xfs_sync_worker(
+ struct xfs_mount *mp,
void *unused)
{
int error;
- if (!(vfsp->vfs_flag & VFS_RDONLY))
- error = bhv_vfs_sync(vfsp, SYNC_FSDATA | SYNC_BDFLUSH | \
- SYNC_ATTR | SYNC_REFCACHE | SYNC_SUPER,
- NULL);
- vfsp->vfs_sync_seq++;
- wake_up(&vfsp->vfs_wait_single_sync_task);
+ if (!(mp->m_flags & XFS_MOUNT_RDONLY))
+ error = xfs_sync(mp, SYNC_FSDATA | SYNC_BDFLUSH | SYNC_ATTR |
+ SYNC_REFCACHE | SYNC_SUPER);
+ mp->m_sync_seq++;
+ wake_up(&mp->m_wait_single_sync_task);
}
STATIC int
xfssyncd(
void *arg)
{
+ struct xfs_mount *mp = arg;
long timeleft;
- bhv_vfs_t *vfsp = (bhv_vfs_t *) arg;
bhv_vfs_sync_work_t *work, *n;
LIST_HEAD (tmp);
@@ -570,31 +562,31 @@ xfssyncd(
timeleft = schedule_timeout_interruptible(timeleft);
/* swsusp */
try_to_freeze();
- if (kthread_should_stop() && list_empty(&vfsp->vfs_sync_list))
+ if (kthread_should_stop() && list_empty(&mp->m_sync_list))
break;
- spin_lock(&vfsp->vfs_sync_lock);
+ spin_lock(&mp->m_sync_lock);
/*
* We can get woken by laptop mode, to do a sync -
* that's the (only!) case where the list would be
* empty with time remaining.
*/
- if (!timeleft || list_empty(&vfsp->vfs_sync_list)) {
+ if (!timeleft || list_empty(&mp->m_sync_list)) {
if (!timeleft)
timeleft = xfs_syncd_centisecs *
msecs_to_jiffies(10);
- INIT_LIST_HEAD(&vfsp->vfs_sync_work.w_list);
- list_add_tail(&vfsp->vfs_sync_work.w_list,
- &vfsp->vfs_sync_list);
+ INIT_LIST_HEAD(&mp->m_sync_work.w_list);
+ list_add_tail(&mp->m_sync_work.w_list,
+ &mp->m_sync_list);
}
- list_for_each_entry_safe(work, n, &vfsp->vfs_sync_list, w_list)
+ list_for_each_entry_safe(work, n, &mp->m_sync_list, w_list)
list_move(&work->w_list, &tmp);
- spin_unlock(&vfsp->vfs_sync_lock);
+ spin_unlock(&mp->m_sync_lock);
list_for_each_entry_safe(work, n, &tmp, w_list) {
- (*work->w_syncer)(vfsp, work->w_data);
+ (*work->w_syncer)(mp, work->w_data);
list_del(&work->w_list);
- if (work == &vfsp->vfs_sync_work)
+ if (work == &mp->m_sync_work)
continue;
kmem_free(work, sizeof(struct bhv_vfs_sync_work));
}
@@ -603,41 +595,19 @@ xfssyncd(
return 0;
}
-STATIC int
-xfs_fs_start_syncd(
- bhv_vfs_t *vfsp)
-{
- vfsp->vfs_sync_work.w_syncer = vfs_sync_worker;
- vfsp->vfs_sync_work.w_vfs = vfsp;
- vfsp->vfs_sync_task = kthread_run(xfssyncd, vfsp, "xfssyncd");
- if (IS_ERR(vfsp->vfs_sync_task))
- return -PTR_ERR(vfsp->vfs_sync_task);
- return 0;
-}
-
-STATIC void
-xfs_fs_stop_syncd(
- bhv_vfs_t *vfsp)
-{
- kthread_stop(vfsp->vfs_sync_task);
-}
-
STATIC void
xfs_fs_put_super(
struct super_block *sb)
{
- bhv_vfs_t *vfsp = vfs_from_sb(sb);
+ struct xfs_mount *mp = XFS_M(sb);
int error;
- xfs_fs_stop_syncd(vfsp);
- bhv_vfs_sync(vfsp, SYNC_ATTR | SYNC_DELWRI, NULL);
- error = bhv_vfs_unmount(vfsp, 0, NULL);
- if (error) {
+ kthread_stop(mp->m_sync_task);
+
+ xfs_sync(mp, SYNC_ATTR | SYNC_DELWRI);
+ error = xfs_unmount(mp, 0, NULL);
+ if (error)
printk("XFS: unmount got error=%d\n", error);
- printk("%s: vfs=0x%p left dangling!\n", __FUNCTION__, vfsp);
- } else {
- vfs_deallocate(vfsp);
- }
}
STATIC void
@@ -645,7 +615,7 @@ xfs_fs_write_super(
struct super_block *sb)
{
if (!(sb->s_flags & MS_RDONLY))
- bhv_vfs_sync(vfs_from_sb(sb), SYNC_FSDATA, NULL);
+ xfs_sync(XFS_M(sb), SYNC_FSDATA);
sb->s_dirt = 0;
}
@@ -654,11 +624,23 @@ xfs_fs_sync_super(
struct super_block *sb,
int wait)
{
- bhv_vfs_t *vfsp = vfs_from_sb(sb);
+ struct xfs_mount *mp = XFS_M(sb);
int error;
int flags;
- if (unlikely(sb->s_frozen == SB_FREEZE_WRITE)) {
+ /*
+ * Treat a sync operation like a freeze. This is to work
+ * around a race in sync_inodes() which works in two phases
+ * - an asynchronous flush, which can write out an inode
+ * without waiting for file size updates to complete, and a
+ * synchronous flush, which wont do anything because the
+ * async flush removed the inode's dirty flag. Also
+ * sync_inodes() will not see any files that just have
+ * outstanding transactions to be flushed because we don't
+ * dirty the Linux inode until after the transaction I/O
+ * completes.
+ */
+ if (wait || unlikely(sb->s_frozen == SB_FREEZE_WRITE)) {
/*
* First stage of freeze - no more writers will make progress
* now we are here, so we flush delwri and delalloc buffers
@@ -669,28 +651,28 @@ xfs_fs_sync_super(
*/
flags = SYNC_DATA_QUIESCE;
} else
- flags = SYNC_FSDATA | (wait ? SYNC_WAIT : 0);
+ flags = SYNC_FSDATA;
- error = bhv_vfs_sync(vfsp, flags, NULL);
+ error = xfs_sync(mp, flags);
sb->s_dirt = 0;
if (unlikely(laptop_mode)) {
- int prev_sync_seq = vfsp->vfs_sync_seq;
+ int prev_sync_seq = mp->m_sync_seq;
/*
* The disk must be active because we're syncing.
* We schedule xfssyncd now (now that the disk is
* active) instead of later (when it might not be).
*/
- wake_up_process(vfsp->vfs_sync_task);
+ wake_up_process(mp->m_sync_task);
/*
* We have to wait for the sync iteration to complete.
* If we don't, the disk activity caused by the sync
* will come after the sync is completed, and that
* triggers another sync from laptop mode.
*/
- wait_event(vfsp->vfs_wait_single_sync_task,
- vfsp->vfs_sync_seq != prev_sync_seq);
+ wait_event(mp->m_wait_single_sync_task,
+ mp->m_sync_seq != prev_sync_seq);
}
return -error;
@@ -701,7 +683,7 @@ xfs_fs_statfs(
struct dentry *dentry,
struct kstatfs *statp)
{
- return -bhv_vfs_statvfs(vfs_from_sb(dentry->d_sb), statp,
+ return -xfs_statvfs(XFS_M(dentry->d_sb), statp,
vn_from_inode(dentry->d_inode));
}
@@ -711,13 +693,13 @@ xfs_fs_remount(
int *flags,
char *options)
{
- bhv_vfs_t *vfsp = vfs_from_sb(sb);
+ struct xfs_mount *mp = XFS_M(sb);
struct xfs_mount_args *args = xfs_args_allocate(sb, 0);
int error;
- error = bhv_vfs_parseargs(vfsp, options, args, 1);
+ error = xfs_parseargs(mp, options, args, 1);
if (!error)
- error = bhv_vfs_mntupdate(vfsp, flags, args);
+ error = xfs_mntupdate(mp, flags, args);
kmem_free(args, sizeof(*args));
return -error;
}
@@ -726,7 +708,7 @@ STATIC void
xfs_fs_lockfs(
struct super_block *sb)
{
- bhv_vfs_freeze(vfs_from_sb(sb));
+ xfs_freeze(XFS_M(sb));
}
STATIC int
@@ -734,7 +716,7 @@ xfs_fs_show_options(
struct seq_file *m,
struct vfsmount *mnt)
{
- return -bhv_vfs_showargs(vfs_from_sb(mnt->mnt_sb), m);
+ return -xfs_showargs(XFS_M(mnt->mnt_sb), m);
}
STATIC int
@@ -742,7 +724,7 @@ xfs_fs_quotasync(
struct super_block *sb,
int type)
{
- return -bhv_vfs_quotactl(vfs_from_sb(sb), Q_XQUOTASYNC, 0, NULL);
+ return -XFS_QM_QUOTACTL(XFS_M(sb), Q_XQUOTASYNC, 0, NULL);
}
STATIC int
@@ -750,7 +732,7 @@ xfs_fs_getxstate(
struct super_block *sb,
struct fs_quota_stat *fqs)
{
- return -bhv_vfs_quotactl(vfs_from_sb(sb), Q_XGETQSTAT, 0, (caddr_t)fqs);
+ return -XFS_QM_QUOTACTL(XFS_M(sb), Q_XGETQSTAT, 0, (caddr_t)fqs);
}
STATIC int
@@ -759,7 +741,7 @@ xfs_fs_setxstate(
unsigned int flags,
int op)
{
- return -bhv_vfs_quotactl(vfs_from_sb(sb), op, 0, (caddr_t)&flags);
+ return -XFS_QM_QUOTACTL(XFS_M(sb), op, 0, (caddr_t)&flags);
}
STATIC int
@@ -769,7 +751,7 @@ xfs_fs_getxquota(
qid_t id,
struct fs_disk_quota *fdq)
{
- return -bhv_vfs_quotactl(vfs_from_sb(sb),
+ return -XFS_QM_QUOTACTL(XFS_M(sb),
(type == USRQUOTA) ? Q_XGETQUOTA :
((type == GRPQUOTA) ? Q_XGETGQUOTA :
Q_XGETPQUOTA), id, (caddr_t)fdq);
@@ -782,7 +764,7 @@ xfs_fs_setxquota(
qid_t id,
struct fs_disk_quota *fdq)
{
- return -bhv_vfs_quotactl(vfs_from_sb(sb),
+ return -XFS_QM_QUOTACTL(XFS_M(sb),
(type == USRQUOTA) ? Q_XSETQLIM :
((type == GRPQUOTA) ? Q_XSETGQLIM :
Q_XSETPQLIM), id, (caddr_t)fdq);
@@ -794,32 +776,38 @@ xfs_fs_fill_super(
void *data,
int silent)
{
- struct bhv_vnode *rootvp;
- struct bhv_vfs *vfsp = vfs_allocate(sb);
+ struct inode *rootvp;
+ struct xfs_mount *mp = NULL;
struct xfs_mount_args *args = xfs_args_allocate(sb, silent);
struct kstatfs statvfs;
int error;
- bhv_insert_all_vfsops(vfsp);
+ mp = xfs_mount_init();
- error = bhv_vfs_parseargs(vfsp, (char *)data, args, 0);
- if (error) {
- bhv_remove_all_vfsops(vfsp, 1);
+ INIT_LIST_HEAD(&mp->m_sync_list);
+ spin_lock_init(&mp->m_sync_lock);
+ init_waitqueue_head(&mp->m_wait_single_sync_task);
+
+ mp->m_super = sb;
+ sb->s_fs_info = mp;
+
+ if (sb->s_flags & MS_RDONLY)
+ mp->m_flags |= XFS_MOUNT_RDONLY;
+
+ error = xfs_parseargs(mp, (char *)data, args, 0);
+ if (error)
goto fail_vfsop;
- }
sb_min_blocksize(sb, BBSIZE);
sb->s_export_op = &xfs_export_operations;
sb->s_qcop = &xfs_quotactl_operations;
sb->s_op = &xfs_super_operations;
- error = bhv_vfs_mount(vfsp, args, NULL);
- if (error) {
- bhv_remove_all_vfsops(vfsp, 1);
+ error = xfs_mount(mp, args, NULL);
+ if (error)
goto fail_vfsop;
- }
- error = bhv_vfs_statvfs(vfsp, &statvfs, NULL);
+ error = xfs_statvfs(mp, &statvfs, NULL);
if (error)
goto fail_unmount;
@@ -831,7 +819,7 @@ xfs_fs_fill_super(
sb->s_time_gran = 1;
set_posix_acl_flag(sb);
- error = bhv_vfs_root(vfsp, &rootvp);
+ error = xfs_root(mp, &rootvp);
if (error)
goto fail_unmount;
@@ -844,9 +832,17 @@ xfs_fs_fill_super(
error = EINVAL;
goto fail_vnrele;
}
- if ((error = xfs_fs_start_syncd(vfsp)))
+
+ mp->m_sync_work.w_syncer = xfs_sync_worker;
+ mp->m_sync_work.w_mount = mp;
+ mp->m_sync_task = kthread_run(xfssyncd, mp, "xfssyncd");
+ if (IS_ERR(mp->m_sync_task)) {
+ error = -PTR_ERR(mp->m_sync_task);
goto fail_vnrele;
- vn_trace_exit(rootvp, __FUNCTION__, (inst_t *)__return_address);
+ }
+
+ vn_trace_exit(XFS_I(sb->s_root->d_inode), __FUNCTION__,
+ (inst_t *)__return_address);
kmem_free(args, sizeof(*args));
return 0;
@@ -860,10 +856,9 @@ fail_vnrele:
}
fail_unmount:
- bhv_vfs_unmount(vfsp, 0, NULL);
+ xfs_unmount(mp, 0, NULL);
fail_vfsop:
- vfs_deallocate(vfsp);
kmem_free(args, sizeof(*args));
return -error;
}
@@ -915,15 +910,11 @@ STATIC int __init
init_xfs_fs( void )
{
int error;
- struct sysinfo si;
static char message[] __initdata = KERN_INFO \
XFS_VERSION_STRING " with " XFS_BUILD_OPTIONS " enabled\n";
printk(message);
- si_meminfo(&si);
- xfs_physmem = si.totalram;
-
ktrace_init(64);
error = xfs_init_zones();
diff --git a/fs/xfs/linux-2.6/xfs_super.h b/fs/xfs/linux-2.6/xfs_super.h
index 201cc3273c84..3efcf45b14ab 100644
--- a/fs/xfs/linux-2.6/xfs_super.h
+++ b/fs/xfs/linux-2.6/xfs_super.h
@@ -107,7 +107,8 @@ struct block_device;
extern __uint64_t xfs_max_file_offset(unsigned int);
-extern void xfs_initialize_vnode(bhv_desc_t *, bhv_vnode_t *, bhv_desc_t *, int);
+extern void xfs_initialize_vnode(struct xfs_mount *mp, bhv_vnode_t *vp,
+ struct xfs_inode *ip);
extern void xfs_flush_inode(struct xfs_inode *);
extern void xfs_flush_device(struct xfs_inode *);
@@ -117,6 +118,8 @@ extern int xfs_blkdev_get(struct xfs_mount *, const char *,
extern void xfs_blkdev_put(struct block_device *);
extern void xfs_blkdev_issue_flush(struct xfs_buftarg *);
-extern struct export_operations xfs_export_operations;
+extern const struct export_operations xfs_export_operations;
+
+#define XFS_M(sb) ((struct xfs_mount *)((sb)->s_fs_info))
#endif /* __XFS_SUPER_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_vfs.c b/fs/xfs/linux-2.6/xfs_vfs.c
deleted file mode 100644
index 6145e8bd0be2..000000000000
--- a/fs/xfs/linux-2.6/xfs_vfs.c
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * Copyright (c) 2000-2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-#include "xfs.h"
-#include "xfs_fs.h"
-#include "xfs_inum.h"
-#include "xfs_log.h"
-#include "xfs_clnt.h"
-#include "xfs_trans.h"
-#include "xfs_sb.h"
-#include "xfs_ag.h"
-#include "xfs_dir2.h"
-#include "xfs_imap.h"
-#include "xfs_alloc.h"
-#include "xfs_dmapi.h"
-#include "xfs_mount.h"
-#include "xfs_quota.h"
-
-int
-vfs_mount(
- struct bhv_desc *bdp,
- struct xfs_mount_args *args,
- struct cred *cr)
-{
- struct bhv_desc *next = bdp;
-
- ASSERT(next);
- while (! (bhvtovfsops(next))->vfs_mount)
- next = BHV_NEXT(next);
- return ((*bhvtovfsops(next)->vfs_mount)(next, args, cr));
-}
-
-int
-vfs_parseargs(
- struct bhv_desc *bdp,
- char *s,
- struct xfs_mount_args *args,
- int f)
-{
- struct bhv_desc *next = bdp;
-
- ASSERT(next);
- while (! (bhvtovfsops(next))->vfs_parseargs)
- next = BHV_NEXT(next);
- return ((*bhvtovfsops(next)->vfs_parseargs)(next, s, args, f));
-}
-
-int
-vfs_showargs(
- struct bhv_desc *bdp,
- struct seq_file *m)
-{
- struct bhv_desc *next = bdp;
-
- ASSERT(next);
- while (! (bhvtovfsops(next))->vfs_showargs)
- next = BHV_NEXT(next);
- return ((*bhvtovfsops(next)->vfs_showargs)(next, m));
-}
-
-int
-vfs_unmount(
- struct bhv_desc *bdp,
- int fl,
- struct cred *cr)
-{
- struct bhv_desc *next = bdp;
-
- ASSERT(next);
- while (! (bhvtovfsops(next))->vfs_unmount)
- next = BHV_NEXT(next);
- return ((*bhvtovfsops(next)->vfs_unmount)(next, fl, cr));
-}
-
-int
-vfs_mntupdate(
- struct bhv_desc *bdp,
- int *fl,
- struct xfs_mount_args *args)
-{
- struct bhv_desc *next = bdp;
-
- ASSERT(next);
- while (! (bhvtovfsops(next))->vfs_mntupdate)
- next = BHV_NEXT(next);
- return ((*bhvtovfsops(next)->vfs_mntupdate)(next, fl, args));
-}
-
-int
-vfs_root(
- struct bhv_desc *bdp,
- struct bhv_vnode **vpp)
-{
- struct bhv_desc *next = bdp;
-
- ASSERT(next);
- while (! (bhvtovfsops(next))->vfs_root)
- next = BHV_NEXT(next);
- return ((*bhvtovfsops(next)->vfs_root)(next, vpp));
-}
-
-int
-vfs_statvfs(
- struct bhv_desc *bdp,
- bhv_statvfs_t *statp,
- struct bhv_vnode *vp)
-{
- struct bhv_desc *next = bdp;
-
- ASSERT(next);
- while (! (bhvtovfsops(next))->vfs_statvfs)
- next = BHV_NEXT(next);
- return ((*bhvtovfsops(next)->vfs_statvfs)(next, statp, vp));
-}
-
-int
-vfs_sync(
- struct bhv_desc *bdp,
- int fl,
- struct cred *cr)
-{
- struct bhv_desc *next = bdp;
-
- ASSERT(next);
- while (! (bhvtovfsops(next))->vfs_sync)
- next = BHV_NEXT(next);
- return ((*bhvtovfsops(next)->vfs_sync)(next, fl, cr));
-}
-
-int
-vfs_vget(
- struct bhv_desc *bdp,
- struct bhv_vnode **vpp,
- struct fid *fidp)
-{
- struct bhv_desc *next = bdp;
-
- ASSERT(next);
- while (! (bhvtovfsops(next))->vfs_vget)
- next = BHV_NEXT(next);
- return ((*bhvtovfsops(next)->vfs_vget)(next, vpp, fidp));
-}
-
-int
-vfs_dmapiops(
- struct bhv_desc *bdp,
- caddr_t addr)
-{
- struct bhv_desc *next = bdp;
-
- ASSERT(next);
- while (! (bhvtovfsops(next))->vfs_dmapiops)
- next = BHV_NEXT(next);
- return ((*bhvtovfsops(next)->vfs_dmapiops)(next, addr));
-}
-
-int
-vfs_quotactl(
- struct bhv_desc *bdp,
- int cmd,
- int id,
- caddr_t addr)
-{
- struct bhv_desc *next = bdp;
-
- ASSERT(next);
- while (! (bhvtovfsops(next))->vfs_quotactl)
- next = BHV_NEXT(next);
- return ((*bhvtovfsops(next)->vfs_quotactl)(next, cmd, id, addr));
-}
-
-void
-vfs_init_vnode(
- struct bhv_desc *bdp,
- struct bhv_vnode *vp,
- struct bhv_desc *bp,
- int unlock)
-{
- struct bhv_desc *next = bdp;
-
- ASSERT(next);
- while (! (bhvtovfsops(next))->vfs_init_vnode)
- next = BHV_NEXT(next);
- ((*bhvtovfsops(next)->vfs_init_vnode)(next, vp, bp, unlock));
-}
-
-void
-vfs_force_shutdown(
- struct bhv_desc *bdp,
- int fl,
- char *file,
- int line)
-{
- struct bhv_desc *next = bdp;
-
- ASSERT(next);
- while (! (bhvtovfsops(next))->vfs_force_shutdown)
- next = BHV_NEXT(next);
- ((*bhvtovfsops(next)->vfs_force_shutdown)(next, fl, file, line));
-}
-
-void
-vfs_freeze(
- struct bhv_desc *bdp)
-{
- struct bhv_desc *next = bdp;
-
- ASSERT(next);
- while (! (bhvtovfsops(next))->vfs_freeze)
- next = BHV_NEXT(next);
- ((*bhvtovfsops(next)->vfs_freeze)(next));
-}
-
-bhv_vfs_t *
-vfs_allocate(
- struct super_block *sb)
-{
- struct bhv_vfs *vfsp;
-
- vfsp = kmem_zalloc(sizeof(bhv_vfs_t), KM_SLEEP);
- bhv_head_init(VFS_BHVHEAD(vfsp), "vfs");
- INIT_LIST_HEAD(&vfsp->vfs_sync_list);
- spin_lock_init(&vfsp->vfs_sync_lock);
- init_waitqueue_head(&vfsp->vfs_wait_single_sync_task);
-
- vfsp->vfs_super = sb;
- sb->s_fs_info = vfsp;
-
- if (sb->s_flags & MS_RDONLY)
- vfsp->vfs_flag |= VFS_RDONLY;
-
- return vfsp;
-}
-
-bhv_vfs_t *
-vfs_from_sb(
- struct super_block *sb)
-{
- return (bhv_vfs_t *)sb->s_fs_info;
-}
-
-void
-vfs_deallocate(
- struct bhv_vfs *vfsp)
-{
- bhv_head_destroy(VFS_BHVHEAD(vfsp));
- kmem_free(vfsp, sizeof(bhv_vfs_t));
-}
-
-void
-vfs_insertops(
- struct bhv_vfs *vfsp,
- struct bhv_module_vfsops *vfsops)
-{
- struct bhv_desc *bdp;
-
- bdp = kmem_alloc(sizeof(struct bhv_desc), KM_SLEEP);
- bhv_desc_init(bdp, NULL, vfsp, vfsops);
- bhv_insert(&vfsp->vfs_bh, bdp);
-}
-
-void
-vfs_insertbhv(
- struct bhv_vfs *vfsp,
- struct bhv_desc *bdp,
- struct bhv_vfsops *vfsops,
- void *mount)
-{
- bhv_desc_init(bdp, mount, vfsp, vfsops);
- bhv_insert_initial(&vfsp->vfs_bh, bdp);
-}
-
-void
-bhv_remove_vfsops(
- struct bhv_vfs *vfsp,
- int pos)
-{
- struct bhv_desc *bhv;
-
- bhv = bhv_lookup_range(&vfsp->vfs_bh, pos, pos);
- if (!bhv)
- return;
- bhv_remove(&vfsp->vfs_bh, bhv);
- kmem_free(bhv, sizeof(*bhv));
-}
-
-void
-bhv_remove_all_vfsops(
- struct bhv_vfs *vfsp,
- int freebase)
-{
- struct xfs_mount *mp;
-
- bhv_remove_vfsops(vfsp, VFS_POSITION_QM);
- bhv_remove_vfsops(vfsp, VFS_POSITION_DM);
- if (!freebase)
- return;
- mp = XFS_VFSTOM(vfsp);
- VFS_REMOVEBHV(vfsp, &mp->m_bhv);
- xfs_mount_free(mp, 0);
-}
-
-void
-bhv_insert_all_vfsops(
- struct bhv_vfs *vfsp)
-{
- struct xfs_mount *mp;
-
- mp = xfs_mount_init();
- vfs_insertbhv(vfsp, &mp->m_bhv, &xfs_vfsops, mp);
- vfs_insertdmapi(vfsp);
- vfs_insertquota(vfsp);
-}
diff --git a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h
index dca3481aaafa..4da03a4e3520 100644
--- a/fs/xfs/linux-2.6/xfs_vfs.h
+++ b/fs/xfs/linux-2.6/xfs_vfs.h
@@ -21,68 +21,25 @@
#include <linux/vfs.h>
#include "xfs_fs.h"
-struct bhv_vfs;
-struct bhv_vnode;
+struct inode;
struct fid;
struct cred;
struct seq_file;
struct super_block;
+struct xfs_inode;
+struct xfs_mount;
struct xfs_mount_args;
typedef struct kstatfs bhv_statvfs_t;
typedef struct bhv_vfs_sync_work {
struct list_head w_list;
- struct bhv_vfs *w_vfs;
+ struct xfs_mount *w_mount;
void *w_data; /* syncer routine argument */
- void (*w_syncer)(struct bhv_vfs *, void *);
+ void (*w_syncer)(struct xfs_mount *, void *);
} bhv_vfs_sync_work_t;
-typedef struct bhv_vfs {
- u_int vfs_flag; /* flags */
- xfs_fsid_t vfs_fsid; /* file system ID */
- xfs_fsid_t *vfs_altfsid; /* An ID fixed for life of FS */
- bhv_head_t vfs_bh; /* head of vfs behavior chain */
- struct super_block *vfs_super; /* generic superblock pointer */
- struct task_struct *vfs_sync_task; /* generalised sync thread */
- bhv_vfs_sync_work_t vfs_sync_work; /* work item for VFS_SYNC */
- struct list_head vfs_sync_list; /* sync thread work item list */
- spinlock_t vfs_sync_lock; /* work item list lock */
- int vfs_sync_seq; /* sync thread generation no. */
- wait_queue_head_t vfs_wait_single_sync_task;
-} bhv_vfs_t;
-
-#define bhvtovfs(bdp) ( (struct bhv_vfs *)BHV_VOBJ(bdp) )
-#define bhvtovfsops(bdp) ( (struct bhv_vfsops *)BHV_OPS(bdp) )
-#define VFS_BHVHEAD(vfs) ( &(vfs)->vfs_bh )
-#define VFS_REMOVEBHV(vfs, bdp) ( bhv_remove(VFS_BHVHEAD(vfs), bdp) )
-
-#define VFS_POSITION_BASE BHV_POSITION_BASE /* chain bottom */
-#define VFS_POSITION_TOP BHV_POSITION_TOP /* chain top */
-#define VFS_POSITION_INVALID BHV_POSITION_INVALID /* invalid pos. num */
-
-typedef enum {
- VFS_BHV_UNKNOWN, /* not specified */
- VFS_BHV_XFS, /* xfs */
- VFS_BHV_DM, /* data migration */
- VFS_BHV_QM, /* quota manager */
- VFS_BHV_IO, /* IO path */
- VFS_BHV_END /* housekeeping end-of-range */
-} bhv_vfs_type_t;
-
-#define VFS_POSITION_XFS (BHV_POSITION_BASE)
-#define VFS_POSITION_DM (VFS_POSITION_BASE+10)
-#define VFS_POSITION_QM (VFS_POSITION_BASE+20)
-#define VFS_POSITION_IO (VFS_POSITION_BASE+30)
-
-#define VFS_RDONLY 0x0001 /* read-only vfs */
-#define VFS_GRPID 0x0002 /* group-ID assigned from directory */
-#define VFS_DMI 0x0004 /* filesystem has the DMI enabled */
-/* ---- VFS_UMOUNT ---- 0x0008 -- unneeded, fixed via kthread APIs */
-#define VFS_32BITINODES 0x0010 /* do not use inums above 32 bits */
-#define VFS_END 0x0010 /* max flag */
-
#define SYNC_ATTR 0x0001 /* sync attributes */
#define SYNC_CLOSE 0x0002 /* close file system down */
#define SYNC_DELWRI 0x0004 /* look at delayed writes */
@@ -115,118 +72,7 @@ typedef enum {
#define SHUTDOWN_REMOTE_REQ 0x0010 /* shutdown came from remote cell */
#define SHUTDOWN_DEVICE_REQ 0x0020 /* failed all paths to the device */
-typedef int (*vfs_mount_t)(bhv_desc_t *,
- struct xfs_mount_args *, struct cred *);
-typedef int (*vfs_parseargs_t)(bhv_desc_t *, char *,
- struct xfs_mount_args *, int);
-typedef int (*vfs_showargs_t)(bhv_desc_t *, struct seq_file *);
-typedef int (*vfs_unmount_t)(bhv_desc_t *, int, struct cred *);
-typedef int (*vfs_mntupdate_t)(bhv_desc_t *, int *,
- struct xfs_mount_args *);
-typedef int (*vfs_root_t)(bhv_desc_t *, struct bhv_vnode **);
-typedef int (*vfs_statvfs_t)(bhv_desc_t *, bhv_statvfs_t *,
- struct bhv_vnode *);
-typedef int (*vfs_sync_t)(bhv_desc_t *, int, struct cred *);
-typedef int (*vfs_vget_t)(bhv_desc_t *, struct bhv_vnode **, struct fid *);
-typedef int (*vfs_dmapiops_t)(bhv_desc_t *, caddr_t);
-typedef int (*vfs_quotactl_t)(bhv_desc_t *, int, int, caddr_t);
-typedef void (*vfs_init_vnode_t)(bhv_desc_t *,
- struct bhv_vnode *, bhv_desc_t *, int);
-typedef void (*vfs_force_shutdown_t)(bhv_desc_t *, int, char *, int);
-typedef void (*vfs_freeze_t)(bhv_desc_t *);
-
-typedef struct bhv_vfsops {
- bhv_position_t vf_position; /* behavior chain position */
- vfs_mount_t vfs_mount; /* mount file system */
- vfs_parseargs_t vfs_parseargs; /* parse mount options */
- vfs_showargs_t vfs_showargs; /* unparse mount options */
- vfs_unmount_t vfs_unmount; /* unmount file system */
- vfs_mntupdate_t vfs_mntupdate; /* update file system options */
- vfs_root_t vfs_root; /* get root vnode */
- vfs_statvfs_t vfs_statvfs; /* file system statistics */
- vfs_sync_t vfs_sync; /* flush files */
- vfs_vget_t vfs_vget; /* get vnode from fid */
- vfs_dmapiops_t vfs_dmapiops; /* data migration */
- vfs_quotactl_t vfs_quotactl; /* disk quota */
- vfs_init_vnode_t vfs_init_vnode; /* initialize a new vnode */
- vfs_force_shutdown_t vfs_force_shutdown; /* crash and burn */
- vfs_freeze_t vfs_freeze; /* freeze fs for snapshot */
-} bhv_vfsops_t;
-
-/*
- * Virtual filesystem operations, operating from head bhv.
- */
-#define VFSHEAD(v) ((v)->vfs_bh.bh_first)
-#define bhv_vfs_mount(v, ma,cr) vfs_mount(VFSHEAD(v), ma,cr)
-#define bhv_vfs_parseargs(v, o,ma,f) vfs_parseargs(VFSHEAD(v), o,ma,f)
-#define bhv_vfs_showargs(v, m) vfs_showargs(VFSHEAD(v), m)
-#define bhv_vfs_unmount(v, f,cr) vfs_unmount(VFSHEAD(v), f,cr)
-#define bhv_vfs_mntupdate(v, fl,args) vfs_mntupdate(VFSHEAD(v), fl,args)
-#define bhv_vfs_root(v, vpp) vfs_root(VFSHEAD(v), vpp)
-#define bhv_vfs_statvfs(v, sp,vp) vfs_statvfs(VFSHEAD(v), sp,vp)
-#define bhv_vfs_sync(v, flag,cr) vfs_sync(VFSHEAD(v), flag,cr)
-#define bhv_vfs_vget(v, vpp,fidp) vfs_vget(VFSHEAD(v), vpp,fidp)
-#define bhv_vfs_dmapiops(v, p) vfs_dmapiops(VFSHEAD(v), p)
-#define bhv_vfs_quotactl(v, c,id,p) vfs_quotactl(VFSHEAD(v), c,id,p)
-#define bhv_vfs_init_vnode(v, vp,b,ul) vfs_init_vnode(VFSHEAD(v), vp,b,ul)
-#define bhv_vfs_force_shutdown(v,u,f,l) vfs_force_shutdown(VFSHEAD(v), u,f,l)
-#define bhv_vfs_freeze(v) vfs_freeze(VFSHEAD(v))
-
-/*
- * Virtual filesystem operations, operating from next bhv.
- */
-#define bhv_next_vfs_mount(b, ma,cr) vfs_mount(b, ma,cr)
-#define bhv_next_vfs_parseargs(b, o,ma,f) vfs_parseargs(b, o,ma,f)
-#define bhv_next_vfs_showargs(b, m) vfs_showargs(b, m)
-#define bhv_next_vfs_unmount(b, f,cr) vfs_unmount(b, f,cr)
-#define bhv_next_vfs_mntupdate(b, fl,args) vfs_mntupdate(b, fl, args)
-#define bhv_next_vfs_root(b, vpp) vfs_root(b, vpp)
-#define bhv_next_vfs_statvfs(b, sp,vp) vfs_statvfs(b, sp,vp)
-#define bhv_next_vfs_sync(b, flag,cr) vfs_sync(b, flag,cr)
-#define bhv_next_vfs_vget(b, vpp,fidp) vfs_vget(b, vpp,fidp)
-#define bhv_next_vfs_dmapiops(b, p) vfs_dmapiops(b, p)
-#define bhv_next_vfs_quotactl(b, c,id,p) vfs_quotactl(b, c,id,p)
-#define bhv_next_vfs_init_vnode(b, vp,b2,ul) vfs_init_vnode(b, vp,b2,ul)
-#define bhv_next_force_shutdown(b, fl,f,l) vfs_force_shutdown(b, fl,f,l)
-#define bhv_next_vfs_freeze(b) vfs_freeze(b)
-
-extern int vfs_mount(bhv_desc_t *, struct xfs_mount_args *, struct cred *);
-extern int vfs_parseargs(bhv_desc_t *, char *, struct xfs_mount_args *, int);
-extern int vfs_showargs(bhv_desc_t *, struct seq_file *);
-extern int vfs_unmount(bhv_desc_t *, int, struct cred *);
-extern int vfs_mntupdate(bhv_desc_t *, int *, struct xfs_mount_args *);
-extern int vfs_root(bhv_desc_t *, struct bhv_vnode **);
-extern int vfs_statvfs(bhv_desc_t *, bhv_statvfs_t *, struct bhv_vnode *);
-extern int vfs_sync(bhv_desc_t *, int, struct cred *);
-extern int vfs_vget(bhv_desc_t *, struct bhv_vnode **, struct fid *);
-extern int vfs_dmapiops(bhv_desc_t *, caddr_t);
-extern int vfs_quotactl(bhv_desc_t *, int, int, caddr_t);
-extern void vfs_init_vnode(bhv_desc_t *, struct bhv_vnode *, bhv_desc_t *, int);
-extern void vfs_force_shutdown(bhv_desc_t *, int, char *, int);
-extern void vfs_freeze(bhv_desc_t *);
-
-#define vfs_test_for_freeze(vfs) ((vfs)->vfs_super->s_frozen)
-#define vfs_wait_for_freeze(vfs,l) vfs_check_frozen((vfs)->vfs_super, (l))
-
-typedef struct bhv_module_vfsops {
- struct bhv_vfsops bhv_common;
- void * bhv_custom;
-} bhv_module_vfsops_t;
-
-#define vfs_bhv_lookup(v, id) (bhv_lookup_range(&(v)->vfs_bh, (id), (id)))
-#define vfs_bhv_custom(b) (((bhv_module_vfsops_t*)BHV_OPS(b))->bhv_custom)
-#define vfs_bhv_set_custom(b,o) ((b)->bhv_custom = (void *)(o))
-#define vfs_bhv_clr_custom(b) ((b)->bhv_custom = NULL)
-
-extern bhv_vfs_t *vfs_allocate(struct super_block *);
-extern bhv_vfs_t *vfs_from_sb(struct super_block *);
-extern void vfs_deallocate(bhv_vfs_t *);
-extern void vfs_insertbhv(bhv_vfs_t *, bhv_desc_t *, bhv_vfsops_t *, void *);
-
-extern void vfs_insertops(bhv_vfs_t *, bhv_module_vfsops_t *);
-
-extern void bhv_insert_all_vfsops(struct bhv_vfs *);
-extern void bhv_remove_all_vfsops(struct bhv_vfs *, int);
-extern void bhv_remove_vfsops(struct bhv_vfs *, int);
+#define xfs_test_for_freeze(mp) ((mp)->m_super->s_frozen)
+#define xfs_wait_for_freeze(mp,l) vfs_check_frozen((mp)->m_super, (l))
#endif /* __XFS_VFS_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c
index ada24baf88de..814169fd7e1e 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.c
+++ b/fs/xfs/linux-2.6/xfs_vnode.c
@@ -16,9 +16,21 @@
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
+#include "xfs_vnodeops.h"
+#include "xfs_bmap_btree.h"
+#include "xfs_inode.h"
+
+/*
+ * And this gunk is needed for xfs_mount.h"
+ */
+#include "xfs_log.h"
+#include "xfs_trans.h"
+#include "xfs_sb.h"
+#include "xfs_dmapi.h"
+#include "xfs_inum.h"
+#include "xfs_ag.h"
+#include "xfs_mount.h"
-uint64_t vn_generation; /* vnode generation number */
-DEFINE_SPINLOCK(vnumber_lock);
/*
* Dedicated vnode inactive/reclaim sync semaphores.
@@ -39,19 +51,19 @@ vn_init(void)
void
vn_iowait(
- bhv_vnode_t *vp)
+ xfs_inode_t *ip)
{
- wait_queue_head_t *wq = vptosync(vp);
+ wait_queue_head_t *wq = vptosync(ip);
- wait_event(*wq, (atomic_read(&vp->v_iocount) == 0));
+ wait_event(*wq, (atomic_read(&ip->i_iocount) == 0));
}
void
vn_iowake(
- bhv_vnode_t *vp)
+ xfs_inode_t *ip)
{
- if (atomic_dec_and_test(&vp->v_iocount))
- wake_up(vptosync(vp));
+ if (atomic_dec_and_test(&ip->i_iocount))
+ wake_up(vptosync(ip));
}
/*
@@ -61,13 +73,13 @@ vn_iowake(
*/
void
vn_ioerror(
- bhv_vnode_t *vp,
+ xfs_inode_t *ip,
int error,
char *f,
int l)
{
if (unlikely(error == -ENODEV))
- bhv_vfs_force_shutdown(vp->v_vfsp, SHUTDOWN_DEVICE_REQ, f, l);
+ xfs_do_force_shutdown(ip->i_mount, SHUTDOWN_DEVICE_REQ, f, l);
}
bhv_vnode_t *
@@ -79,27 +91,8 @@ vn_initialize(
XFS_STATS_INC(vn_active);
XFS_STATS_INC(vn_alloc);
- vp->v_flag = VMODIFIED;
- spinlock_init(&vp->v_lock, "v_lock");
-
- spin_lock(&vnumber_lock);
- if (!++vn_generation) /* v_number shouldn't be zero */
- vn_generation++;
- vp->v_number = vn_generation;
- spin_unlock(&vnumber_lock);
-
ASSERT(VN_CACHED(vp) == 0);
- /* Initialize the first behavior and the behavior chain head. */
- vn_bhv_head_init(VN_BHV_HEAD(vp), "vnode");
-
- atomic_set(&vp->v_iocount, 0);
-
-#ifdef XFS_VNODE_TRACE
- vp->v_trace = ktrace_alloc(VNODE_TRACE_SIZE, KM_SLEEP);
-#endif /* XFS_VNODE_TRACE */
-
- vn_trace_exit(vp, __FUNCTION__, (inst_t *)__return_address);
return vp;
}
@@ -150,12 +143,12 @@ __vn_revalidate(
{
int error;
- vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
+ vn_trace_entry(xfs_vtoi(vp), __FUNCTION__, (inst_t *)__return_address);
vattr->va_mask = XFS_AT_STAT | XFS_AT_XFLAGS;
- error = bhv_vop_getattr(vp, vattr, 0, NULL);
+ error = xfs_getattr(xfs_vtoi(vp), vattr, 0);
if (likely(!error)) {
vn_revalidate_core(vp, vattr);
- VUNMODIFY(vp);
+ xfs_iflags_clear(xfs_vtoi(vp), XFS_IMODIFIED);
}
return -error;
}
@@ -180,24 +173,35 @@ vn_hold(
XFS_STATS_INC(vn_hold);
- VN_LOCK(vp);
inode = igrab(vn_to_inode(vp));
ASSERT(inode);
- VN_UNLOCK(vp, 0);
return vp;
}
#ifdef XFS_VNODE_TRACE
-#define KTRACE_ENTER(vp, vk, s, line, ra) \
- ktrace_enter( (vp)->v_trace, \
+/*
+ * Reference count of Linux inode if present, -1 if the xfs_inode
+ * has no associated Linux inode.
+ */
+static inline int xfs_icount(struct xfs_inode *ip)
+{
+ bhv_vnode_t *vp = XFS_ITOV_NULL(ip);
+
+ if (vp)
+ return vn_count(vp);
+ return -1;
+}
+
+#define KTRACE_ENTER(ip, vk, s, line, ra) \
+ ktrace_enter( (ip)->i_trace, \
/* 0 */ (void *)(__psint_t)(vk), \
/* 1 */ (void *)(s), \
/* 2 */ (void *)(__psint_t) line, \
-/* 3 */ (void *)(__psint_t)(vn_count(vp)), \
+/* 3 */ (void *)(__psint_t)xfs_icount(ip), \
/* 4 */ (void *)(ra), \
-/* 5 */ (void *)(__psunsigned_t)(vp)->v_flag, \
+/* 5 */ NULL, \
/* 6 */ (void *)(__psint_t)current_cpu(), \
/* 7 */ (void *)(__psint_t)current_pid(), \
/* 8 */ (void *)__return_address, \
@@ -207,32 +211,32 @@ vn_hold(
* Vnode tracing code.
*/
void
-vn_trace_entry(bhv_vnode_t *vp, const char *func, inst_t *ra)
+vn_trace_entry(xfs_inode_t *ip, const char *func, inst_t *ra)
{
- KTRACE_ENTER(vp, VNODE_KTRACE_ENTRY, func, 0, ra);
+ KTRACE_ENTER(ip, VNODE_KTRACE_ENTRY, func, 0, ra);
}
void
-vn_trace_exit(bhv_vnode_t *vp, const char *func, inst_t *ra)
+vn_trace_exit(xfs_inode_t *ip, const char *func, inst_t *ra)
{
- KTRACE_ENTER(vp, VNODE_KTRACE_EXIT, func, 0, ra);
+ KTRACE_ENTER(ip, VNODE_KTRACE_EXIT, func, 0, ra);
}
void
-vn_trace_hold(bhv_vnode_t *vp, char *file, int line, inst_t *ra)
+vn_trace_hold(xfs_inode_t *ip, char *file, int line, inst_t *ra)
{
- KTRACE_ENTER(vp, VNODE_KTRACE_HOLD, file, line, ra);
+ KTRACE_ENTER(ip, VNODE_KTRACE_HOLD, file, line, ra);
}
void
-vn_trace_ref(bhv_vnode_t *vp, char *file, int line, inst_t *ra)
+vn_trace_ref(xfs_inode_t *ip, char *file, int line, inst_t *ra)
{
- KTRACE_ENTER(vp, VNODE_KTRACE_REF, file, line, ra);
+ KTRACE_ENTER(ip, VNODE_KTRACE_REF, file, line, ra);
}
void
-vn_trace_rele(bhv_vnode_t *vp, char *file, int line, inst_t *ra)
+vn_trace_rele(xfs_inode_t *ip, char *file, int line, inst_t *ra)
{
- KTRACE_ENTER(vp, VNODE_KTRACE_RELE, file, line, ra);
+ KTRACE_ENTER(ip, VNODE_KTRACE_RELE, file, line, ra);
}
#endif /* XFS_VNODE_TRACE */
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h
index 5742d65f0785..55fb46948589 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.h
+++ b/fs/xfs/linux-2.6/xfs_vnode.h
@@ -18,84 +18,31 @@
#ifndef __XFS_VNODE_H__
#define __XFS_VNODE_H__
-struct uio;
struct file;
-struct bhv_vfs;
struct bhv_vattr;
struct xfs_iomap;
struct attrlist_cursor_kern;
typedef struct dentry bhv_vname_t;
typedef __u64 bhv_vnumber_t;
+typedef struct inode bhv_vnode_t;
-typedef enum bhv_vflags {
- VMODIFIED = 0x08, /* XFS inode state possibly differs */
- /* to the Linux inode state. */
- VTRUNCATED = 0x40, /* truncated down so flush-on-close */
-} bhv_vflags_t;
-
-/*
- * MP locking protocols:
- * v_flag, v_vfsp VN_LOCK/VN_UNLOCK
- */
-typedef struct bhv_vnode {
- bhv_vflags_t v_flag; /* vnode flags (see above) */
- bhv_vfs_t *v_vfsp; /* ptr to containing VFS */
- bhv_vnumber_t v_number; /* in-core vnode number */
- bhv_head_t v_bh; /* behavior head */
- spinlock_t v_lock; /* VN_LOCK/VN_UNLOCK */
- atomic_t v_iocount; /* outstanding I/O count */
-#ifdef XFS_VNODE_TRACE
- struct ktrace *v_trace; /* trace header structure */
-#endif
- struct inode v_inode; /* Linux inode */
- /* inode MUST be last */
-} bhv_vnode_t;
-
-#define VN_ISLNK(vp) S_ISLNK((vp)->v_inode.i_mode)
-#define VN_ISREG(vp) S_ISREG((vp)->v_inode.i_mode)
-#define VN_ISDIR(vp) S_ISDIR((vp)->v_inode.i_mode)
-#define VN_ISCHR(vp) S_ISCHR((vp)->v_inode.i_mode)
-#define VN_ISBLK(vp) S_ISBLK((vp)->v_inode.i_mode)
-
-#define VNODE_POSITION_BASE BHV_POSITION_BASE /* chain bottom */
-#define VNODE_POSITION_TOP BHV_POSITION_TOP /* chain top */
-#define VNODE_POSITION_INVALID BHV_POSITION_INVALID /* invalid pos. num */
-
-typedef enum {
- VN_BHV_UNKNOWN, /* not specified */
- VN_BHV_XFS, /* xfs */
- VN_BHV_DM, /* data migration */
- VN_BHV_QM, /* quota manager */
- VN_BHV_IO, /* IO path */
- VN_BHV_END /* housekeeping end-of-range */
-} vn_bhv_t;
-
-#define VNODE_POSITION_XFS (VNODE_POSITION_BASE)
-#define VNODE_POSITION_DM (VNODE_POSITION_BASE+10)
-#define VNODE_POSITION_QM (VNODE_POSITION_BASE+20)
-#define VNODE_POSITION_IO (VNODE_POSITION_BASE+30)
-
-/*
- * Macros for dealing with the behavior descriptor inside of the vnode.
- */
-#define BHV_TO_VNODE(bdp) ((bhv_vnode_t *)BHV_VOBJ(bdp))
-#define BHV_TO_VNODE_NULL(bdp) ((bhv_vnode_t *)BHV_VOBJNULL(bdp))
-
-#define VN_BHV_HEAD(vp) ((bhv_head_t *)(&((vp)->v_bh)))
-#define vn_bhv_head_init(bhp,name) bhv_head_init(bhp,name)
-#define vn_bhv_remove(bhp,bdp) bhv_remove(bhp,bdp)
+#define VN_ISLNK(vp) S_ISLNK((vp)->i_mode)
+#define VN_ISREG(vp) S_ISREG((vp)->i_mode)
+#define VN_ISDIR(vp) S_ISDIR((vp)->i_mode)
+#define VN_ISCHR(vp) S_ISCHR((vp)->i_mode)
+#define VN_ISBLK(vp) S_ISBLK((vp)->i_mode)
/*
* Vnode to Linux inode mapping.
*/
-static inline struct bhv_vnode *vn_from_inode(struct inode *inode)
+static inline bhv_vnode_t *vn_from_inode(struct inode *inode)
{
- return container_of(inode, bhv_vnode_t, v_inode);
+ return inode;
}
-static inline struct inode *vn_to_inode(struct bhv_vnode *vnode)
+static inline struct inode *vn_to_inode(bhv_vnode_t *vnode)
{
- return &vnode->v_inode;
+ return vnode;
}
/*
@@ -111,7 +58,7 @@ typedef enum bhv_vrwlock {
} bhv_vrwlock_t;
/*
- * Return values for bhv_vop_inactive. A return value of
+ * Return values for xfs_inactive. A return value of
* VN_INACTIVE_NOCACHE implies that the file system behavior
* has disassociated its state and bhv_desc_t from the vnode.
*/
@@ -119,193 +66,6 @@ typedef enum bhv_vrwlock {
#define VN_INACTIVE_NOCACHE 1
/*
- * Values for the cmd code given to vop_vnode_change.
- */
-typedef enum bhv_vchange {
- VCHANGE_FLAGS_FRLOCKS = 0,
- VCHANGE_FLAGS_ENF_LOCKING = 1,
- VCHANGE_FLAGS_TRUNCATED = 2,
- VCHANGE_FLAGS_PAGE_DIRTY = 3,
- VCHANGE_FLAGS_IOEXCL_COUNT = 4
-} bhv_vchange_t;
-
-typedef int (*vop_open_t)(bhv_desc_t *, struct cred *);
-typedef ssize_t (*vop_read_t)(bhv_desc_t *, struct kiocb *,
- const struct iovec *, unsigned int,
- loff_t *, int, struct cred *);
-typedef ssize_t (*vop_write_t)(bhv_desc_t *, struct kiocb *,
- const struct iovec *, unsigned int,
- loff_t *, int, struct cred *);
-typedef ssize_t (*vop_splice_read_t)(bhv_desc_t *, struct file *, loff_t *,
- struct pipe_inode_info *, size_t, int, int,
- struct cred *);
-typedef ssize_t (*vop_splice_write_t)(bhv_desc_t *, struct pipe_inode_info *,
- struct file *, loff_t *, size_t, int, int,
- struct cred *);
-typedef int (*vop_ioctl_t)(bhv_desc_t *, struct inode *, struct file *,
- int, unsigned int, void __user *);
-typedef int (*vop_getattr_t)(bhv_desc_t *, struct bhv_vattr *, int,
- struct cred *);
-typedef int (*vop_setattr_t)(bhv_desc_t *, struct bhv_vattr *, int,
- struct cred *);
-typedef int (*vop_access_t)(bhv_desc_t *, int, struct cred *);
-typedef int (*vop_lookup_t)(bhv_desc_t *, bhv_vname_t *, bhv_vnode_t **,
- int, bhv_vnode_t *, struct cred *);
-typedef int (*vop_create_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr *,
- bhv_vnode_t **, struct cred *);
-typedef int (*vop_remove_t)(bhv_desc_t *, bhv_vname_t *, struct cred *);
-typedef int (*vop_link_t)(bhv_desc_t *, bhv_vnode_t *, bhv_vname_t *,
- struct cred *);
-typedef int (*vop_rename_t)(bhv_desc_t *, bhv_vname_t *, bhv_vnode_t *,
- bhv_vname_t *, struct cred *);
-typedef int (*vop_mkdir_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr *,
- bhv_vnode_t **, struct cred *);
-typedef int (*vop_rmdir_t)(bhv_desc_t *, bhv_vname_t *, struct cred *);
-typedef int (*vop_readdir_t)(bhv_desc_t *, struct uio *, struct cred *,
- int *);
-typedef int (*vop_symlink_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr*,
- char *, bhv_vnode_t **, struct cred *);
-typedef int (*vop_readlink_t)(bhv_desc_t *, struct uio *, int,
- struct cred *);
-typedef int (*vop_fsync_t)(bhv_desc_t *, int, struct cred *,
- xfs_off_t, xfs_off_t);
-typedef int (*vop_inactive_t)(bhv_desc_t *, struct cred *);
-typedef int (*vop_fid2_t)(bhv_desc_t *, struct fid *);
-typedef int (*vop_release_t)(bhv_desc_t *);
-typedef int (*vop_rwlock_t)(bhv_desc_t *, bhv_vrwlock_t);
-typedef void (*vop_rwunlock_t)(bhv_desc_t *, bhv_vrwlock_t);
-typedef int (*vop_bmap_t)(bhv_desc_t *, xfs_off_t, ssize_t, int,
- struct xfs_iomap *, int *);
-typedef int (*vop_reclaim_t)(bhv_desc_t *);
-typedef int (*vop_attr_get_t)(bhv_desc_t *, const char *, char *, int *,
- int, struct cred *);
-typedef int (*vop_attr_set_t)(bhv_desc_t *, const char *, char *, int,
- int, struct cred *);
-typedef int (*vop_attr_remove_t)(bhv_desc_t *, const char *,
- int, struct cred *);
-typedef int (*vop_attr_list_t)(bhv_desc_t *, char *, int, int,
- struct attrlist_cursor_kern *, struct cred *);
-typedef void (*vop_link_removed_t)(bhv_desc_t *, bhv_vnode_t *, int);
-typedef void (*vop_vnode_change_t)(bhv_desc_t *, bhv_vchange_t, __psint_t);
-typedef void (*vop_ptossvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
-typedef int (*vop_pflushinvalvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
-typedef int (*vop_pflushvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t,
- uint64_t, int);
-typedef int (*vop_iflush_t)(bhv_desc_t *, int);
-
-
-typedef struct bhv_vnodeops {
- bhv_position_t vn_position; /* position within behavior chain */
- vop_open_t vop_open;
- vop_read_t vop_read;
- vop_write_t vop_write;
- vop_splice_read_t vop_splice_read;
- vop_splice_write_t vop_splice_write;
- vop_ioctl_t vop_ioctl;
- vop_getattr_t vop_getattr;
- vop_setattr_t vop_setattr;
- vop_access_t vop_access;
- vop_lookup_t vop_lookup;
- vop_create_t vop_create;
- vop_remove_t vop_remove;
- vop_link_t vop_link;
- vop_rename_t vop_rename;
- vop_mkdir_t vop_mkdir;
- vop_rmdir_t vop_rmdir;
- vop_readdir_t vop_readdir;
- vop_symlink_t vop_symlink;
- vop_readlink_t vop_readlink;
- vop_fsync_t vop_fsync;
- vop_inactive_t vop_inactive;
- vop_fid2_t vop_fid2;
- vop_rwlock_t vop_rwlock;
- vop_rwunlock_t vop_rwunlock;
- vop_bmap_t vop_bmap;
- vop_reclaim_t vop_reclaim;
- vop_attr_get_t vop_attr_get;
- vop_attr_set_t vop_attr_set;
- vop_attr_remove_t vop_attr_remove;
- vop_attr_list_t vop_attr_list;
- vop_link_removed_t vop_link_removed;
- vop_vnode_change_t vop_vnode_change;
- vop_ptossvp_t vop_tosspages;
- vop_pflushinvalvp_t vop_flushinval_pages;
- vop_pflushvp_t vop_flush_pages;
- vop_release_t vop_release;
- vop_iflush_t vop_iflush;
-} bhv_vnodeops_t;
-
-/*
- * Virtual node operations, operating from head bhv.
- */
-#define VNHEAD(vp) ((vp)->v_bh.bh_first)
-#define VOP(op, vp) (*((bhv_vnodeops_t *)VNHEAD(vp)->bd_ops)->op)
-#define bhv_vop_open(vp, cr) VOP(vop_open, vp)(VNHEAD(vp),cr)
-#define bhv_vop_read(vp,file,iov,segs,offset,ioflags,cr) \
- VOP(vop_read, vp)(VNHEAD(vp),file,iov,segs,offset,ioflags,cr)
-#define bhv_vop_write(vp,file,iov,segs,offset,ioflags,cr) \
- VOP(vop_write, vp)(VNHEAD(vp),file,iov,segs,offset,ioflags,cr)
-#define bhv_vop_splice_read(vp,f,o,pipe,cnt,fl,iofl,cr) \
- VOP(vop_splice_read, vp)(VNHEAD(vp),f,o,pipe,cnt,fl,iofl,cr)
-#define bhv_vop_splice_write(vp,f,o,pipe,cnt,fl,iofl,cr) \
- VOP(vop_splice_write, vp)(VNHEAD(vp),f,o,pipe,cnt,fl,iofl,cr)
-#define bhv_vop_bmap(vp,of,sz,rw,b,n) \
- VOP(vop_bmap, vp)(VNHEAD(vp),of,sz,rw,b,n)
-#define bhv_vop_getattr(vp, vap,f,cr) \
- VOP(vop_getattr, vp)(VNHEAD(vp), vap,f,cr)
-#define bhv_vop_setattr(vp, vap,f,cr) \
- VOP(vop_setattr, vp)(VNHEAD(vp), vap,f,cr)
-#define bhv_vop_access(vp, mode,cr) VOP(vop_access, vp)(VNHEAD(vp), mode,cr)
-#define bhv_vop_lookup(vp,d,vpp,f,rdir,cr) \
- VOP(vop_lookup, vp)(VNHEAD(vp),d,vpp,f,rdir,cr)
-#define bhv_vop_create(dvp,d,vap,vpp,cr) \
- VOP(vop_create, dvp)(VNHEAD(dvp),d,vap,vpp,cr)
-#define bhv_vop_remove(dvp,d,cr) VOP(vop_remove, dvp)(VNHEAD(dvp),d,cr)
-#define bhv_vop_link(dvp,fvp,d,cr) VOP(vop_link, dvp)(VNHEAD(dvp),fvp,d,cr)
-#define bhv_vop_rename(fvp,fnm,tdvp,tnm,cr) \
- VOP(vop_rename, fvp)(VNHEAD(fvp),fnm,tdvp,tnm,cr)
-#define bhv_vop_mkdir(dp,d,vap,vpp,cr) \
- VOP(vop_mkdir, dp)(VNHEAD(dp),d,vap,vpp,cr)
-#define bhv_vop_rmdir(dp,d,cr) VOP(vop_rmdir, dp)(VNHEAD(dp),d,cr)
-#define bhv_vop_readdir(vp,uiop,cr,eofp) \
- VOP(vop_readdir, vp)(VNHEAD(vp),uiop,cr,eofp)
-#define bhv_vop_symlink(dvp,d,vap,tnm,vpp,cr) \
- VOP(vop_symlink, dvp)(VNHEAD(dvp),d,vap,tnm,vpp,cr)
-#define bhv_vop_readlink(vp,uiop,fl,cr) \
- VOP(vop_readlink, vp)(VNHEAD(vp),uiop,fl,cr)
-#define bhv_vop_fsync(vp,f,cr,b,e) VOP(vop_fsync, vp)(VNHEAD(vp),f,cr,b,e)
-#define bhv_vop_inactive(vp,cr) VOP(vop_inactive, vp)(VNHEAD(vp),cr)
-#define bhv_vop_release(vp) VOP(vop_release, vp)(VNHEAD(vp))
-#define bhv_vop_fid2(vp,fidp) VOP(vop_fid2, vp)(VNHEAD(vp),fidp)
-#define bhv_vop_rwlock(vp,i) VOP(vop_rwlock, vp)(VNHEAD(vp),i)
-#define bhv_vop_rwlock_try(vp,i) VOP(vop_rwlock, vp)(VNHEAD(vp),i)
-#define bhv_vop_rwunlock(vp,i) VOP(vop_rwunlock, vp)(VNHEAD(vp),i)
-#define bhv_vop_frlock(vp,c,fl,flags,offset,fr) \
- VOP(vop_frlock, vp)(VNHEAD(vp),c,fl,flags,offset,fr)
-#define bhv_vop_reclaim(vp) VOP(vop_reclaim, vp)(VNHEAD(vp))
-#define bhv_vop_attr_get(vp, name, val, vallenp, fl, cred) \
- VOP(vop_attr_get, vp)(VNHEAD(vp),name,val,vallenp,fl,cred)
-#define bhv_vop_attr_set(vp, name, val, vallen, fl, cred) \
- VOP(vop_attr_set, vp)(VNHEAD(vp),name,val,vallen,fl,cred)
-#define bhv_vop_attr_remove(vp, name, flags, cred) \
- VOP(vop_attr_remove, vp)(VNHEAD(vp),name,flags,cred)
-#define bhv_vop_attr_list(vp, buf, buflen, fl, cursor, cred) \
- VOP(vop_attr_list, vp)(VNHEAD(vp),buf,buflen,fl,cursor,cred)
-#define bhv_vop_link_removed(vp, dvp, linkzero) \
- VOP(vop_link_removed, vp)(VNHEAD(vp), dvp, linkzero)
-#define bhv_vop_vnode_change(vp, cmd, val) \
- VOP(vop_vnode_change, vp)(VNHEAD(vp), cmd, val)
-#define bhv_vop_toss_pages(vp, first, last, fiopt) \
- VOP(vop_tosspages, vp)(VNHEAD(vp), first, last, fiopt)
-#define bhv_vop_flushinval_pages(vp, first, last, fiopt) \
- VOP(vop_flushinval_pages, vp)(VNHEAD(vp),first,last,fiopt)
-#define bhv_vop_flush_pages(vp, first, last, flags, fiopt) \
- VOP(vop_flush_pages, vp)(VNHEAD(vp),first,last,flags,fiopt)
-#define bhv_vop_ioctl(vp, inode, filp, fl, cmd, arg) \
- VOP(vop_ioctl, vp)(VNHEAD(vp),inode,filp,fl,cmd,arg)
-#define bhv_vop_iflush(vp, flags) VOP(vop_iflush, vp)(VNHEAD(vp), flags)
-
-/*
* Flags for read/write calls - same values as IRIX
*/
#define IO_ISAIO 0x00001 /* don't wait for completion */
@@ -428,16 +188,19 @@ typedef struct bhv_vattr {
extern void vn_init(void);
extern bhv_vnode_t *vn_initialize(struct inode *);
-extern int vn_revalidate(struct bhv_vnode *);
-extern int __vn_revalidate(struct bhv_vnode *, bhv_vattr_t *);
-extern void vn_revalidate_core(struct bhv_vnode *, bhv_vattr_t *);
-
-extern void vn_iowait(struct bhv_vnode *vp);
-extern void vn_iowake(struct bhv_vnode *vp);
+extern int vn_revalidate(bhv_vnode_t *);
+extern int __vn_revalidate(bhv_vnode_t *, bhv_vattr_t *);
+extern void vn_revalidate_core(bhv_vnode_t *, bhv_vattr_t *);
-extern void vn_ioerror(struct bhv_vnode *vp, int error, char *f, int l);
+/*
+ * Yeah, these don't take vnode anymore at all, all this should be
+ * cleaned up at some point.
+ */
+extern void vn_iowait(struct xfs_inode *ip);
+extern void vn_iowake(struct xfs_inode *ip);
+extern void vn_ioerror(struct xfs_inode *ip, int error, char *f, int l);
-static inline int vn_count(struct bhv_vnode *vp)
+static inline int vn_count(bhv_vnode_t *vp)
{
return atomic_read(&vn_to_inode(vp)->i_count);
}
@@ -445,21 +208,21 @@ static inline int vn_count(struct bhv_vnode *vp)
/*
* Vnode reference counting functions (and macros for compatibility).
*/
-extern bhv_vnode_t *vn_hold(struct bhv_vnode *);
+extern bhv_vnode_t *vn_hold(bhv_vnode_t *);
#if defined(XFS_VNODE_TRACE)
#define VN_HOLD(vp) \
((void)vn_hold(vp), \
- vn_trace_hold(vp, __FILE__, __LINE__, (inst_t *)__return_address))
+ vn_trace_hold(xfs_vtoi(vp), __FILE__, __LINE__, (inst_t *)__return_address))
#define VN_RELE(vp) \
- (vn_trace_rele(vp, __FILE__, __LINE__, (inst_t *)__return_address), \
+ (vn_trace_rele(xfs_vtoi(vp), __FILE__, __LINE__, (inst_t *)__return_address), \
iput(vn_to_inode(vp)))
#else
#define VN_HOLD(vp) ((void)vn_hold(vp))
#define VN_RELE(vp) (iput(vn_to_inode(vp)))
#endif
-static inline struct bhv_vnode *vn_grab(struct bhv_vnode *vp)
+static inline bhv_vnode_t *vn_grab(bhv_vnode_t *vp)
{
struct inode *inode = igrab(vn_to_inode(vp));
return inode ? vn_from_inode(inode) : NULL;
@@ -473,43 +236,14 @@ static inline struct bhv_vnode *vn_grab(struct bhv_vnode *vp)
#define VNAME_TO_VNODE(dentry) (vn_from_inode((dentry)->d_inode))
/*
- * Vnode spinlock manipulation.
- */
-#define VN_LOCK(vp) mutex_spinlock(&(vp)->v_lock)
-#define VN_UNLOCK(vp, s) mutex_spinunlock(&(vp)->v_lock, s)
-
-STATIC_INLINE void vn_flagset(struct bhv_vnode *vp, uint flag)
-{
- spin_lock(&vp->v_lock);
- vp->v_flag |= flag;
- spin_unlock(&vp->v_lock);
-}
-
-STATIC_INLINE uint vn_flagclr(struct bhv_vnode *vp, uint flag)
-{
- uint cleared;
-
- spin_lock(&vp->v_lock);
- cleared = (vp->v_flag & flag);
- vp->v_flag &= ~flag;
- spin_unlock(&vp->v_lock);
- return cleared;
-}
-
-#define VMODIFY(vp) vn_flagset(vp, VMODIFIED)
-#define VUNMODIFY(vp) vn_flagclr(vp, VMODIFIED)
-#define VTRUNCATE(vp) vn_flagset(vp, VTRUNCATED)
-#define VUNTRUNCATE(vp) vn_flagclr(vp, VTRUNCATED)
-
-/*
* Dealing with bad inodes
*/
-static inline void vn_mark_bad(struct bhv_vnode *vp)
+static inline void vn_mark_bad(bhv_vnode_t *vp)
{
make_bad_inode(vn_to_inode(vp));
}
-static inline int VN_BAD(struct bhv_vnode *vp)
+static inline int VN_BAD(bhv_vnode_t *vp)
{
return is_bad_inode(vn_to_inode(vp));
}
@@ -519,18 +253,18 @@ static inline int VN_BAD(struct bhv_vnode *vp)
*/
static inline void vn_atime_to_bstime(bhv_vnode_t *vp, xfs_bstime_t *bs_atime)
{
- bs_atime->tv_sec = vp->v_inode.i_atime.tv_sec;
- bs_atime->tv_nsec = vp->v_inode.i_atime.tv_nsec;
+ bs_atime->tv_sec = vp->i_atime.tv_sec;
+ bs_atime->tv_nsec = vp->i_atime.tv_nsec;
}
static inline void vn_atime_to_timespec(bhv_vnode_t *vp, struct timespec *ts)
{
- *ts = vp->v_inode.i_atime;
+ *ts = vp->i_atime;
}
static inline void vn_atime_to_time_t(bhv_vnode_t *vp, time_t *tt)
{
- *tt = vp->v_inode.i_atime.tv_sec;
+ *tt = vp->i_atime.tv_sec;
}
/*
@@ -540,7 +274,6 @@ static inline void vn_atime_to_time_t(bhv_vnode_t *vp, time_t *tt)
#define VN_CACHED(vp) (vn_to_inode(vp)->i_mapping->nrpages)
#define VN_DIRTY(vp) mapping_tagged(vn_to_inode(vp)->i_mapping, \
PAGECACHE_TAG_DIRTY)
-#define VN_TRUNC(vp) ((vp)->v_flag & VTRUNCATED)
/*
* Flags to vop_setattr/getattr.
@@ -572,21 +305,17 @@ static inline void vn_atime_to_time_t(bhv_vnode_t *vp, time_t *tt)
#define VNODE_KTRACE_REF 4
#define VNODE_KTRACE_RELE 5
-extern void vn_trace_entry(struct bhv_vnode *, const char *, inst_t *);
-extern void vn_trace_exit(struct bhv_vnode *, const char *, inst_t *);
-extern void vn_trace_hold(struct bhv_vnode *, char *, int, inst_t *);
-extern void vn_trace_ref(struct bhv_vnode *, char *, int, inst_t *);
-extern void vn_trace_rele(struct bhv_vnode *, char *, int, inst_t *);
-
-#define VN_TRACE(vp) \
- vn_trace_ref(vp, __FILE__, __LINE__, (inst_t *)__return_address)
+extern void vn_trace_entry(struct xfs_inode *, const char *, inst_t *);
+extern void vn_trace_exit(struct xfs_inode *, const char *, inst_t *);
+extern void vn_trace_hold(struct xfs_inode *, char *, int, inst_t *);
+extern void vn_trace_ref(struct xfs_inode *, char *, int, inst_t *);
+extern void vn_trace_rele(struct xfs_inode *, char *, int, inst_t *);
#else
#define vn_trace_entry(a,b,c)
#define vn_trace_exit(a,b,c)
#define vn_trace_hold(a,b,c,d)
#define vn_trace_ref(a,b,c,d)
#define vn_trace_rele(a,b,c,d)
-#define VN_TRACE(vp)
#endif
#endif /* __XFS_VNODE_H__ */
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index 6ff0f4de1630..b5f91281b707 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -288,45 +288,6 @@ xfs_qm_rele_quotafs_ref(
}
/*
- * This is called at mount time from xfs_mountfs to initialize the quotainfo
- * structure and start the global quota manager (xfs_Gqm) if it hasn't done
- * so already. Note that the superblock has not been read in yet.
- */
-void
-xfs_qm_mount_quotainit(
- xfs_mount_t *mp,
- uint flags)
-{
- /*
- * User, projects or group quotas has to be on.
- */
- ASSERT(flags & (XFSMNT_UQUOTA | XFSMNT_PQUOTA | XFSMNT_GQUOTA));
-
- /*
- * Initialize the flags in the mount structure. From this point
- * onwards we look at m_qflags to figure out if quotas's ON/OFF, etc.
- * Note that we enforce nothing if accounting is off.
- * ie. XFSMNT_*QUOTA must be ON for XFSMNT_*QUOTAENF.
- * It isn't necessary to take the quotaoff lock to do this; this is
- * called from mount.
- */
- if (flags & XFSMNT_UQUOTA) {
- mp->m_qflags |= (XFS_UQUOTA_ACCT | XFS_UQUOTA_ACTIVE);
- if (flags & XFSMNT_UQUOTAENF)
- mp->m_qflags |= XFS_UQUOTA_ENFD;
- }
- if (flags & XFSMNT_GQUOTA) {
- mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE);
- if (flags & XFSMNT_GQUOTAENF)
- mp->m_qflags |= XFS_OQUOTA_ENFD;
- } else if (flags & XFSMNT_PQUOTA) {
- mp->m_qflags |= (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE);
- if (flags & XFSMNT_PQUOTAENF)
- mp->m_qflags |= XFS_OQUOTA_ENFD;
- }
-}
-
-/*
* Just destroy the quotainfo structure.
*/
void
@@ -1039,7 +1000,7 @@ xfs_qm_dqdetach(
int
xfs_qm_sync(
xfs_mount_t *mp,
- short flags)
+ int flags)
{
int recl, restarts;
xfs_dquot_t *dqp;
@@ -1717,7 +1678,6 @@ xfs_qm_get_rtblks(
xfs_extnum_t idx; /* extent record index */
xfs_ifork_t *ifp; /* inode fork pointer */
xfs_extnum_t nextents; /* number of extent entries */
- xfs_bmbt_rec_t *ep; /* pointer to an extent entry */
int error;
ASSERT(XFS_IS_REALTIME_INODE(ip));
@@ -1728,10 +1688,8 @@ xfs_qm_get_rtblks(
}
rtblks = 0;
nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
- for (idx = 0; idx < nextents; idx++) {
- ep = xfs_iext_get_ext(ifp, idx);
- rtblks += xfs_bmbt_get_blockcount(ep);
- }
+ for (idx = 0; idx < nextents; idx++)
+ rtblks += xfs_bmbt_get_blockcount(xfs_iext_get_ext(ifp, idx));
*O_rtblks = (xfs_qcnt_t)rtblks;
return 0;
}
@@ -2459,8 +2417,7 @@ xfs_qm_vop_dqalloc(
lockflags = XFS_ILOCK_EXCL;
xfs_ilock(ip, lockflags);
- if ((flags & XFS_QMOPT_INHERIT) &&
- XFS_INHERIT_GID(ip, XFS_MTOVFS(mp)))
+ if ((flags & XFS_QMOPT_INHERIT) && XFS_INHERIT_GID(ip))
gid = ip->i_d.di_gid;
/*
diff --git a/fs/xfs/quota/xfs_qm.h b/fs/xfs/quota/xfs_qm.h
index 689407de0a20..23ccaa5fceaf 100644
--- a/fs/xfs/quota/xfs_qm.h
+++ b/fs/xfs/quota/xfs_qm.h
@@ -166,12 +166,11 @@ typedef struct xfs_dquot_acct {
extern void xfs_qm_destroy_quotainfo(xfs_mount_t *);
extern int xfs_qm_mount_quotas(xfs_mount_t *, int);
-extern void xfs_qm_mount_quotainit(xfs_mount_t *, uint);
extern int xfs_qm_quotacheck(xfs_mount_t *);
extern void xfs_qm_unmount_quotadestroy(xfs_mount_t *);
extern int xfs_qm_unmount_quotas(xfs_mount_t *);
extern int xfs_qm_write_sb_changes(xfs_mount_t *, __int64_t);
-extern int xfs_qm_sync(xfs_mount_t *, short);
+extern int xfs_qm_sync(xfs_mount_t *, int);
/* dquot stuff */
extern boolean_t xfs_qm_dqalloc_incore(xfs_dquot_t **);
@@ -199,7 +198,8 @@ extern void xfs_qm_freelist_unlink(xfs_dquot_t *);
extern int xfs_qm_freelist_lock_nowait(xfs_qm_t *);
/* system call interface */
-extern int xfs_qm_quotactl(bhv_desc_t *, int, int, xfs_caddr_t);
+extern int xfs_qm_quotactl(struct xfs_mount *, int, int,
+ xfs_caddr_t);
#ifdef DEBUG
extern int xfs_qm_internalqcheck(xfs_mount_t *);
diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c
index d2cdb8a2aad6..97bb32937585 100644
--- a/fs/xfs/quota/xfs_qm_bhv.c
+++ b/fs/xfs/quota/xfs_qm_bhv.c
@@ -48,172 +48,13 @@
#include "xfs_buf_item.h"
#include "xfs_qm.h"
-#define MNTOPT_QUOTA "quota" /* disk quotas (user) */
-#define MNTOPT_NOQUOTA "noquota" /* no quotas */
-#define MNTOPT_USRQUOTA "usrquota" /* user quota enabled */
-#define MNTOPT_GRPQUOTA "grpquota" /* group quota enabled */
-#define MNTOPT_PRJQUOTA "prjquota" /* project quota enabled */
-#define MNTOPT_UQUOTA "uquota" /* user quota (IRIX variant) */
-#define MNTOPT_GQUOTA "gquota" /* group quota (IRIX variant) */
-#define MNTOPT_PQUOTA "pquota" /* project quota (IRIX variant) */
-#define MNTOPT_UQUOTANOENF "uqnoenforce"/* user quota limit enforcement */
-#define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */
-#define MNTOPT_PQUOTANOENF "pqnoenforce"/* project quota limit enforcement */
-#define MNTOPT_QUOTANOENF "qnoenforce" /* same as uqnoenforce */
-STATIC int
-xfs_qm_parseargs(
- struct bhv_desc *bhv,
- char *options,
- struct xfs_mount_args *args,
- int update)
-{
- size_t length;
- char *local_options = options;
- char *this_char;
- int error;
- int referenced = update;
-
- while ((this_char = strsep(&local_options, ",")) != NULL) {
- length = strlen(this_char);
- if (local_options)
- length++;
-
- if (!strcmp(this_char, MNTOPT_NOQUOTA)) {
- args->flags &= ~(XFSMNT_UQUOTAENF|XFSMNT_UQUOTA);
- args->flags &= ~(XFSMNT_GQUOTAENF|XFSMNT_GQUOTA);
- referenced = update;
- } else if (!strcmp(this_char, MNTOPT_QUOTA) ||
- !strcmp(this_char, MNTOPT_UQUOTA) ||
- !strcmp(this_char, MNTOPT_USRQUOTA)) {
- args->flags |= XFSMNT_UQUOTA | XFSMNT_UQUOTAENF;
- referenced = 1;
- } else if (!strcmp(this_char, MNTOPT_QUOTANOENF) ||
- !strcmp(this_char, MNTOPT_UQUOTANOENF)) {
- args->flags |= XFSMNT_UQUOTA;
- args->flags &= ~XFSMNT_UQUOTAENF;
- referenced = 1;
- } else if (!strcmp(this_char, MNTOPT_PQUOTA) ||
- !strcmp(this_char, MNTOPT_PRJQUOTA)) {
- args->flags |= XFSMNT_PQUOTA | XFSMNT_PQUOTAENF;
- referenced = 1;
- } else if (!strcmp(this_char, MNTOPT_PQUOTANOENF)) {
- args->flags |= XFSMNT_PQUOTA;
- args->flags &= ~XFSMNT_PQUOTAENF;
- referenced = 1;
- } else if (!strcmp(this_char, MNTOPT_GQUOTA) ||
- !strcmp(this_char, MNTOPT_GRPQUOTA)) {
- args->flags |= XFSMNT_GQUOTA | XFSMNT_GQUOTAENF;
- referenced = 1;
- } else if (!strcmp(this_char, MNTOPT_GQUOTANOENF)) {
- args->flags |= XFSMNT_GQUOTA;
- args->flags &= ~XFSMNT_GQUOTAENF;
- referenced = 1;
- } else {
- if (local_options)
- *(local_options-1) = ',';
- continue;
- }
-
- while (length--)
- *this_char++ = ',';
- }
-
- if ((args->flags & XFSMNT_GQUOTA) && (args->flags & XFSMNT_PQUOTA)) {
- cmn_err(CE_WARN,
- "XFS: cannot mount with both project and group quota");
- return XFS_ERROR(EINVAL);
- }
-
- error = bhv_next_vfs_parseargs(BHV_NEXT(bhv), options, args, update);
- if (!error && !referenced)
- bhv_remove_vfsops(bhvtovfs(bhv), VFS_POSITION_QM);
- return error;
-}
-
-STATIC int
-xfs_qm_showargs(
- struct bhv_desc *bhv,
- struct seq_file *m)
-{
- struct bhv_vfs *vfsp = bhvtovfs(bhv);
- struct xfs_mount *mp = XFS_VFSTOM(vfsp);
-
- if (mp->m_qflags & XFS_UQUOTA_ACCT) {
- (mp->m_qflags & XFS_UQUOTA_ENFD) ?
- seq_puts(m, "," MNTOPT_USRQUOTA) :
- seq_puts(m, "," MNTOPT_UQUOTANOENF);
- }
-
- if (mp->m_qflags & XFS_PQUOTA_ACCT) {
- (mp->m_qflags & XFS_OQUOTA_ENFD) ?
- seq_puts(m, "," MNTOPT_PRJQUOTA) :
- seq_puts(m, "," MNTOPT_PQUOTANOENF);
- }
-
- if (mp->m_qflags & XFS_GQUOTA_ACCT) {
- (mp->m_qflags & XFS_OQUOTA_ENFD) ?
- seq_puts(m, "," MNTOPT_GRPQUOTA) :
- seq_puts(m, "," MNTOPT_GQUOTANOENF);
- }
-
- if (!(mp->m_qflags & XFS_ALL_QUOTA_ACCT))
- seq_puts(m, "," MNTOPT_NOQUOTA);
-
- return bhv_next_vfs_showargs(BHV_NEXT(bhv), m);
-}
-
-STATIC int
-xfs_qm_mount(
- struct bhv_desc *bhv,
- struct xfs_mount_args *args,
- struct cred *cr)
-{
- struct bhv_vfs *vfsp = bhvtovfs(bhv);
- struct xfs_mount *mp = XFS_VFSTOM(vfsp);
-
- if (args->flags & (XFSMNT_UQUOTA | XFSMNT_GQUOTA | XFSMNT_PQUOTA))
- xfs_qm_mount_quotainit(mp, args->flags);
- return bhv_next_vfs_mount(BHV_NEXT(bhv), args, cr);
-}
-
-/*
- * Directory tree accounting is implemented using project quotas, where
- * the project identifier is inherited from parent directories.
- * A statvfs (df, etc.) of a directory that is using project quota should
- * return a statvfs of the project, not the entire filesystem.
- * This makes such trees appear as if they are filesystems in themselves.
- */
-STATIC int
-xfs_qm_statvfs(
- struct bhv_desc *bhv,
+STATIC void
+xfs_fill_statvfs_from_dquot(
bhv_statvfs_t *statp,
- struct bhv_vnode *vnode)
+ xfs_disk_dquot_t *dp)
{
- xfs_mount_t *mp;
- xfs_inode_t *ip;
- xfs_dquot_t *dqp;
- xfs_disk_dquot_t *dp;
__uint64_t limit;
- int error;
-
- error = bhv_next_vfs_statvfs(BHV_NEXT(bhv), statp, vnode);
- if (error || !vnode)
- return error;
-
- mp = xfs_vfstom(bhvtovfs(bhv));
- ip = xfs_vtoi(vnode);
-
- if (!(ip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT))
- return 0;
- if (!(mp->m_qflags & XFS_PQUOTA_ACCT))
- return 0;
- if (!(mp->m_qflags & XFS_OQUOTA_ENFD))
- return 0;
-
- if (xfs_qm_dqget(mp, NULL, ip->i_d.di_projid, XFS_DQ_PROJ, 0, &dqp))
- return 0;
- dp = &dqp->q_core;
limit = dp->d_blk_softlimit ?
be64_to_cpu(dp->d_blk_softlimit) :
@@ -234,37 +75,35 @@ xfs_qm_statvfs(
(statp->f_files > be64_to_cpu(dp->d_icount)) ?
(statp->f_ffree - be64_to_cpu(dp->d_icount)) : 0;
}
-
- xfs_qm_dqput(dqp);
- return 0;
}
-STATIC int
-xfs_qm_syncall(
- struct bhv_desc *bhv,
- int flags,
- cred_t *credp)
+
+/*
+ * Directory tree accounting is implemented using project quotas, where
+ * the project identifier is inherited from parent directories.
+ * A statvfs (df, etc.) of a directory that is using project quota should
+ * return a statvfs of the project, not the entire filesystem.
+ * This makes such trees appear as if they are filesystems in themselves.
+ */
+STATIC void
+xfs_qm_statvfs(
+ xfs_inode_t *ip,
+ bhv_statvfs_t *statp)
{
- struct bhv_vfs *vfsp = bhvtovfs(bhv);
- struct xfs_mount *mp = XFS_VFSTOM(vfsp);
- int error;
+ xfs_mount_t *mp = ip->i_mount;
+ xfs_dquot_t *dqp;
- /*
- * Get the Quota Manager to flush the dquots.
- */
- if (XFS_IS_QUOTA_ON(mp)) {
- if ((error = xfs_qm_sync(mp, flags))) {
- /*
- * If we got an IO error, we will be shutting down.
- * So, there's nothing more for us to do here.
- */
- ASSERT(error != EIO || XFS_FORCED_SHUTDOWN(mp));
- if (XFS_FORCED_SHUTDOWN(mp)) {
- return XFS_ERROR(error);
- }
- }
+ if (!(ip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) ||
+ !((mp->m_qflags & (XFS_PQUOTA_ACCT|XFS_OQUOTA_ENFD))) ==
+ (XFS_PQUOTA_ACCT|XFS_OQUOTA_ENFD))
+ return;
+
+ if (!xfs_qm_dqget(mp, NULL, ip->i_d.di_projid, XFS_DQ_PROJ, 0, &dqp)) {
+ xfs_disk_dquot_t *dp = &dqp->q_core;
+
+ xfs_fill_statvfs_from_dquot(statp, dp);
+ xfs_qm_dqput(dqp);
}
- return bhv_next_vfs_sync(BHV_NEXT(bhv), flags, credp);
}
STATIC int
@@ -382,7 +221,7 @@ xfs_qm_dqrele_null(
}
-static struct xfs_qmops xfs_qmcore_xfs = {
+struct xfs_qmops xfs_qmcore_xfs = {
.xfs_qminit = xfs_qm_newmount,
.xfs_qmdone = xfs_qm_unmount_quotadestroy,
.xfs_qmmount = xfs_qm_endmount,
@@ -396,36 +235,24 @@ static struct xfs_qmops xfs_qmcore_xfs = {
.xfs_dqvoprename = xfs_qm_vop_rename_dqattach,
.xfs_dqvopchown = xfs_qm_vop_chown,
.xfs_dqvopchownresv = xfs_qm_vop_chown_reserve,
+ .xfs_dqstatvfs = xfs_qm_statvfs,
+ .xfs_dqsync = xfs_qm_sync,
+ .xfs_quotactl = xfs_qm_quotactl,
.xfs_dqtrxops = &xfs_trans_dquot_ops,
};
-
-struct bhv_module_vfsops xfs_qmops = { {
- BHV_IDENTITY_INIT(VFS_BHV_QM, VFS_POSITION_QM),
- .vfs_parseargs = xfs_qm_parseargs,
- .vfs_showargs = xfs_qm_showargs,
- .vfs_mount = xfs_qm_mount,
- .vfs_statvfs = xfs_qm_statvfs,
- .vfs_sync = xfs_qm_syncall,
- .vfs_quotactl = xfs_qm_quotactl, },
-};
-
+EXPORT_SYMBOL(xfs_qmcore_xfs);
void __init
xfs_qm_init(void)
{
- static char message[] __initdata =
- KERN_INFO "SGI XFS Quota Management subsystem\n";
-
- printk(message);
+ printk(KERN_INFO "SGI XFS Quota Management subsystem\n");
mutex_init(&xfs_Gqm_lock);
- vfs_bhv_set_custom(&xfs_qmops, &xfs_qmcore_xfs);
xfs_qm_init_procfs();
}
void __exit
xfs_qm_exit(void)
{
- vfs_bhv_clr_custom(&xfs_qmops);
xfs_qm_cleanup_procfs();
if (qm_dqzone)
kmem_zone_destroy(qm_dqzone);
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c
index 2df67fd913e5..ad5579d4eac4 100644
--- a/fs/xfs/quota/xfs_qm_syscalls.c
+++ b/fs/xfs/quota/xfs_qm_syscalls.c
@@ -81,18 +81,13 @@ STATIC void xfs_qm_export_dquot(xfs_mount_t *, xfs_disk_dquot_t *,
*/
int
xfs_qm_quotactl(
- struct bhv_desc *bdp,
+ xfs_mount_t *mp,
int cmd,
int id,
xfs_caddr_t addr)
{
- xfs_mount_t *mp;
- bhv_vfs_t *vfsp;
int error;
- vfsp = bhvtovfs(bdp);
- mp = XFS_VFSTOM(vfsp);
-
ASSERT(addr != NULL || cmd == Q_XQUOTASYNC);
/*
@@ -105,7 +100,7 @@ xfs_qm_quotactl(
*/
if (XFS_IS_QUOTA_ON(mp))
return XFS_ERROR(EINVAL);
- if (vfsp->vfs_flag & VFS_RDONLY)
+ if (mp->m_flags & XFS_MOUNT_RDONLY)
return XFS_ERROR(EROFS);
return (xfs_qm_scall_trunc_qfiles(mp,
xfs_qm_import_qtype_flags(*(uint *)addr)));
@@ -121,13 +116,13 @@ xfs_qm_quotactl(
* QUOTAON - enabling quota enforcement.
* Quota accounting must be turned on at mount time.
*/
- if (vfsp->vfs_flag & VFS_RDONLY)
+ if (mp->m_flags & XFS_MOUNT_RDONLY)
return XFS_ERROR(EROFS);
return (xfs_qm_scall_quotaon(mp,
xfs_qm_import_flags(*(uint *)addr)));
case Q_XQUOTAOFF:
- if (vfsp->vfs_flag & VFS_RDONLY)
+ if (mp->m_flags & XFS_MOUNT_RDONLY)
return XFS_ERROR(EROFS);
break;
@@ -143,7 +138,7 @@ xfs_qm_quotactl(
switch (cmd) {
case Q_XQUOTAOFF:
- if (vfsp->vfs_flag & VFS_RDONLY)
+ if (mp->m_flags & XFS_MOUNT_RDONLY)
return XFS_ERROR(EROFS);
error = xfs_qm_scall_quotaoff(mp,
xfs_qm_import_flags(*(uint *)addr),
@@ -164,19 +159,19 @@ xfs_qm_quotactl(
break;
case Q_XSETQLIM:
- if (vfsp->vfs_flag & VFS_RDONLY)
+ if (mp->m_flags & XFS_MOUNT_RDONLY)
return XFS_ERROR(EROFS);
error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_USER,
(fs_disk_quota_t *)addr);
break;
case Q_XSETGQLIM:
- if (vfsp->vfs_flag & VFS_RDONLY)
+ if (mp->m_flags & XFS_MOUNT_RDONLY)
return XFS_ERROR(EROFS);
error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_GROUP,
(fs_disk_quota_t *)addr);
break;
case Q_XSETPQLIM:
- if (vfsp->vfs_flag & VFS_RDONLY)
+ if (mp->m_flags & XFS_MOUNT_RDONLY)
return XFS_ERROR(EROFS);
error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_PROJ,
(fs_disk_quota_t *)addr);
diff --git a/fs/xfs/support/move.c b/fs/xfs/support/move.c
deleted file mode 100644
index ac8617ca3909..000000000000
--- a/fs/xfs/support/move.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-#include <xfs.h>
-
-/* Read from kernel buffer at src to user/kernel buffer defined
- * by the uio structure. Advance the pointer in the uio struct
- * as we go.
- */
-int
-xfs_uio_read(caddr_t src, size_t len, struct uio *uio)
-{
- size_t count;
-
- if (!len || !uio->uio_resid)
- return 0;
-
- count = uio->uio_iov->iov_len;
- if (!count)
- return 0;
- if (count > len)
- count = len;
-
- if (uio->uio_segflg == UIO_USERSPACE) {
- if (copy_to_user(uio->uio_iov->iov_base, src, count))
- return EFAULT;
- } else {
- ASSERT(uio->uio_segflg == UIO_SYSSPACE);
- memcpy(uio->uio_iov->iov_base, src, count);
- }
-
- uio->uio_iov->iov_base = (void*)((char*)uio->uio_iov->iov_base + count);
- uio->uio_iov->iov_len -= count;
- uio->uio_offset += count;
- uio->uio_resid -= count;
- return 0;
-}
diff --git a/fs/xfs/support/move.h b/fs/xfs/support/move.h
deleted file mode 100644
index 324e413deadd..000000000000
--- a/fs/xfs/support/move.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Portions Copyright (c) 1982, 1986, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#ifndef __XFS_SUPPORT_MOVE_H__
-#define __XFS_SUPPORT_MOVE_H__
-
-#include <linux/uio.h>
-#include <asm/uaccess.h>
-
-/* Segment flag values. */
-enum uio_seg {
- UIO_USERSPACE, /* from user data space */
- UIO_SYSSPACE, /* from system space */
-};
-
-struct uio {
- struct kvec *uio_iov; /* pointer to array of iovecs */
- int uio_iovcnt; /* number of iovecs in array */
- xfs_off_t uio_offset; /* offset in file this uio corresponds to */
- int uio_resid; /* residual i/o count */
- enum uio_seg uio_segflg; /* see above */
-};
-
-typedef struct uio uio_t;
-typedef struct kvec iovec_t;
-
-extern int xfs_uio_read (caddr_t, size_t, uio_t *);
-
-#endif /* __XFS_SUPPORT_MOVE_H__ */
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index 4ca4beb7bb54..5bfb66f33caf 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -32,6 +32,7 @@
#include "xfs_btree.h"
#include "xfs_acl.h"
#include "xfs_attr.h"
+#include "xfs_vnodeops.h"
#include <linux/capability.h>
#include <linux/posix_acl_xattr.h>
@@ -241,7 +242,7 @@ xfs_acl_vget(
bhv_vattr_t va;
va.va_mask = XFS_AT_MODE;
- error = bhv_vop_getattr(vp, &va, 0, sys_cred);
+ error = xfs_getattr(xfs_vtoi(vp), &va, 0);
if (error)
goto out;
xfs_acl_sync_mode(va.va_mode, xfs_acl);
@@ -265,9 +266,10 @@ xfs_acl_vremove(
VN_HOLD(vp);
error = xfs_acl_allow_set(vp, kind);
if (!error) {
- error = bhv_vop_attr_remove(vp, kind == _ACL_TYPE_DEFAULT?
+ error = xfs_attr_remove(xfs_vtoi(vp),
+ kind == _ACL_TYPE_DEFAULT?
SGI_ACL_DEFAULT: SGI_ACL_FILE,
- ATTR_ROOT, sys_cred);
+ ATTR_ROOT);
if (error == ENOATTR)
error = 0; /* 'scool */
}
@@ -370,17 +372,18 @@ xfs_acl_allow_set(
bhv_vnode_t *vp,
int kind)
{
+ xfs_inode_t *ip = xfs_vtoi(vp);
bhv_vattr_t va;
int error;
- if (vp->v_inode.i_flags & (S_IMMUTABLE|S_APPEND))
+ if (vp->i_flags & (S_IMMUTABLE|S_APPEND))
return EPERM;
if (kind == _ACL_TYPE_DEFAULT && !VN_ISDIR(vp))
return ENOTDIR;
- if (vp->v_vfsp->vfs_flag & VFS_RDONLY)
+ if (vp->i_sb->s_flags & MS_RDONLY)
return EROFS;
va.va_mask = XFS_AT_UID;
- error = bhv_vop_getattr(vp, &va, 0, NULL);
+ error = xfs_getattr(ip, &va, 0);
if (error)
return error;
if (va.va_uid != current->fsuid && !capable(CAP_FOWNER))
@@ -613,7 +616,8 @@ xfs_acl_get_attr(
ASSERT((flags & ATTR_KERNOVAL) ? (aclp == NULL) : 1);
flags |= ATTR_ROOT;
- *error = bhv_vop_attr_get(vp, kind == _ACL_TYPE_ACCESS ?
+ *error = xfs_attr_get(xfs_vtoi(vp),
+ kind == _ACL_TYPE_ACCESS ?
SGI_ACL_FILE : SGI_ACL_DEFAULT,
(char *)aclp, &len, flags, sys_cred);
if (*error || (flags & ATTR_KERNOVAL))
@@ -651,9 +655,10 @@ xfs_acl_set_attr(
INT_SET(newace->ae_perm, ARCH_CONVERT, ace->ae_perm);
}
INT_SET(newacl->acl_cnt, ARCH_CONVERT, aclp->acl_cnt);
- *error = bhv_vop_attr_set(vp, kind == _ACL_TYPE_ACCESS ?
+ *error = xfs_attr_set(xfs_vtoi(vp),
+ kind == _ACL_TYPE_ACCESS ?
SGI_ACL_FILE: SGI_ACL_DEFAULT,
- (char *)newacl, len, ATTR_ROOT, sys_cred);
+ (char *)newacl, len, ATTR_ROOT);
_ACL_FREE(newacl);
}
@@ -675,7 +680,7 @@ xfs_acl_vtoacl(
if (!error) {
/* Got the ACL, need the mode... */
va.va_mask = XFS_AT_MODE;
- error = bhv_vop_getattr(vp, &va, 0, sys_cred);
+ error = xfs_getattr(xfs_vtoi(vp), &va, 0);
}
if (error)
@@ -699,7 +704,7 @@ xfs_acl_vtoacl(
int
xfs_acl_inherit(
bhv_vnode_t *vp,
- bhv_vattr_t *vap,
+ mode_t mode,
xfs_acl_t *pdaclp)
{
xfs_acl_t *cacl;
@@ -727,7 +732,7 @@ xfs_acl_inherit(
return ENOMEM;
memcpy(cacl, pdaclp, sizeof(xfs_acl_t));
- xfs_acl_filter_mode(vap->va_mode, cacl);
+ xfs_acl_filter_mode(mode, cacl);
xfs_acl_setmode(vp, cacl, &basicperms);
/*
@@ -773,7 +778,7 @@ xfs_acl_setmode(
* mode. The m:: bits take precedence over the g:: bits.
*/
va.va_mask = XFS_AT_MODE;
- error = bhv_vop_getattr(vp, &va, 0, sys_cred);
+ error = xfs_getattr(xfs_vtoi(vp), &va, 0);
if (error)
return error;
@@ -807,7 +812,7 @@ xfs_acl_setmode(
if (gap && nomask)
va.va_mode |= gap->ae_perm << 3;
- return bhv_vop_setattr(vp, &va, 0, sys_cred);
+ return xfs_setattr(xfs_vtoi(vp), &va, 0, sys_cred);
}
/*
diff --git a/fs/xfs/xfs_acl.h b/fs/xfs/xfs_acl.h
index f853cf1a6270..34b7d3391299 100644
--- a/fs/xfs/xfs_acl.h
+++ b/fs/xfs/xfs_acl.h
@@ -50,7 +50,6 @@ typedef struct xfs_acl {
#ifdef CONFIG_XFS_POSIX_ACL
struct vattr;
-struct bhv_vnode;
struct xfs_inode;
extern struct kmem_zone *xfs_acl_zone;
@@ -58,20 +57,20 @@ extern struct kmem_zone *xfs_acl_zone;
(zone) = kmem_zone_init(sizeof(xfs_acl_t), (name))
#define xfs_acl_zone_destroy(zone) kmem_zone_destroy(zone)
-extern int xfs_acl_inherit(struct bhv_vnode *, struct bhv_vattr *, xfs_acl_t *);
+extern int xfs_acl_inherit(bhv_vnode_t *, mode_t mode, xfs_acl_t *);
extern int xfs_acl_iaccess(struct xfs_inode *, mode_t, cred_t *);
-extern int xfs_acl_vtoacl(struct bhv_vnode *, xfs_acl_t *, xfs_acl_t *);
-extern int xfs_acl_vhasacl_access(struct bhv_vnode *);
-extern int xfs_acl_vhasacl_default(struct bhv_vnode *);
-extern int xfs_acl_vset(struct bhv_vnode *, void *, size_t, int);
-extern int xfs_acl_vget(struct bhv_vnode *, void *, size_t, int);
-extern int xfs_acl_vremove(struct bhv_vnode *, int);
+extern int xfs_acl_vtoacl(bhv_vnode_t *, xfs_acl_t *, xfs_acl_t *);
+extern int xfs_acl_vhasacl_access(bhv_vnode_t *);
+extern int xfs_acl_vhasacl_default(bhv_vnode_t *);
+extern int xfs_acl_vset(bhv_vnode_t *, void *, size_t, int);
+extern int xfs_acl_vget(bhv_vnode_t *, void *, size_t, int);
+extern int xfs_acl_vremove(bhv_vnode_t *, int);
#define _ACL_TYPE_ACCESS 1
#define _ACL_TYPE_DEFAULT 2
#define _ACL_PERM_INVALID(perm) ((perm) & ~(ACL_READ|ACL_WRITE|ACL_EXECUTE))
-#define _ACL_INHERIT(c,v,d) (xfs_acl_inherit(c,v,d))
+#define _ACL_INHERIT(c,m,d) (xfs_acl_inherit(c,m,d))
#define _ACL_GET_ACCESS(pv,pa) (xfs_acl_vtoacl(pv,pa,NULL) == 0)
#define _ACL_GET_DEFAULT(pv,pd) (xfs_acl_vtoacl(pv,NULL,pd) == 0)
#define _ACL_ACCESS_EXISTS xfs_acl_vhasacl_access
@@ -91,7 +90,7 @@ extern int xfs_acl_vremove(struct bhv_vnode *, int);
#define xfs_acl_vhasacl_default(v) (0)
#define _ACL_ALLOC(a) (1) /* successfully allocate nothing */
#define _ACL_FREE(a) ((void)0)
-#define _ACL_INHERIT(c,v,d) (0)
+#define _ACL_INHERIT(c,m,d) (0)
#define _ACL_GET_ACCESS(pv,pa) (0)
#define _ACL_GET_DEFAULT(pv,pd) (0)
#define _ACL_ACCESS_EXISTS (NULL)
diff --git a/fs/xfs/xfs_ag.h b/fs/xfs/xfs_ag.h
index 51c09c114a20..9381b0360c4b 100644
--- a/fs/xfs/xfs_ag.h
+++ b/fs/xfs/xfs_ag.h
@@ -197,6 +197,10 @@ typedef struct xfs_perag
#endif
xfs_perag_busy_t *pagb_list; /* unstable blocks */
atomic_t pagf_fstrms; /* # of filestreams active in this AG */
+
+ int pag_ici_init; /* incore inode cache initialised */
+ rwlock_t pag_ici_lock; /* incore inode lock */
+ struct radix_tree_root pag_ici_root; /* incore inode cache root */
} xfs_perag_t;
#define XFS_AG_MAXLEVELS(mp) ((mp)->m_ag_maxlevels)
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
index 7ce44a7b88a2..93fa64dd1be6 100644
--- a/fs/xfs/xfs_attr.c
+++ b/fs/xfs/xfs_attr.c
@@ -49,6 +49,7 @@
#include "xfs_trans_space.h"
#include "xfs_acl.h"
#include "xfs_rw.h"
+#include "xfs_vnodeops.h"
/*
* xfs_attr.c
@@ -156,10 +157,14 @@ xfs_attr_fetch(xfs_inode_t *ip, const char *name, int namelen,
}
int
-xfs_attr_get(bhv_desc_t *bdp, const char *name, char *value, int *valuelenp,
- int flags, struct cred *cred)
+xfs_attr_get(
+ xfs_inode_t *ip,
+ const char *name,
+ char *value,
+ int *valuelenp,
+ int flags,
+ cred_t *cred)
{
- xfs_inode_t *ip = XFS_BHVTOI(bdp);
int error, namelen;
XFS_STATS_INC(xs_attr_get);
@@ -417,10 +422,13 @@ out:
}
int
-xfs_attr_set(bhv_desc_t *bdp, const char *name, char *value, int valuelen, int flags,
- struct cred *cred)
+xfs_attr_set(
+ xfs_inode_t *dp,
+ const char *name,
+ char *value,
+ int valuelen,
+ int flags)
{
- xfs_inode_t *dp;
int namelen;
namelen = strlen(name);
@@ -429,7 +437,6 @@ xfs_attr_set(bhv_desc_t *bdp, const char *name, char *value, int valuelen, int f
XFS_STATS_INC(xs_attr_set);
- dp = XFS_BHVTOI(bdp);
if (XFS_FORCED_SHUTDOWN(dp->i_mount))
return (EIO);
@@ -563,10 +570,12 @@ out:
}
int
-xfs_attr_remove(bhv_desc_t *bdp, const char *name, int flags, struct cred *cred)
+xfs_attr_remove(
+ xfs_inode_t *dp,
+ const char *name,
+ int flags)
{
- xfs_inode_t *dp;
- int namelen;
+ int namelen;
namelen = strlen(name);
if (namelen >= MAXNAMELEN)
@@ -574,7 +583,6 @@ xfs_attr_remove(bhv_desc_t *bdp, const char *name, int flags, struct cred *cred)
XFS_STATS_INC(xs_attr_remove);
- dp = XFS_BHVTOI(bdp);
if (XFS_FORCED_SHUTDOWN(dp->i_mount))
return (EIO);
@@ -702,11 +710,14 @@ xfs_attr_kern_list_sizes(xfs_attr_list_context_t *context, attrnames_t *namesp,
* success.
*/
int
-xfs_attr_list(bhv_desc_t *bdp, char *buffer, int bufsize, int flags,
- attrlist_cursor_kern_t *cursor, struct cred *cred)
+xfs_attr_list(
+ xfs_inode_t *dp,
+ char *buffer,
+ int bufsize,
+ int flags,
+ attrlist_cursor_kern_t *cursor)
{
xfs_attr_list_context_t context;
- xfs_inode_t *dp;
int error;
XFS_STATS_INC(xs_attr_list);
@@ -731,7 +742,7 @@ xfs_attr_list(bhv_desc_t *bdp, char *buffer, int bufsize, int flags,
/*
* Initialize the output buffer.
*/
- context.dp = dp = XFS_BHVTOI(bdp);
+ context.dp = dp;
context.cursor = cursor;
context.count = 0;
context.dupcnt = 0;
@@ -2502,7 +2513,7 @@ STATIC int
attr_generic_set(
bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
{
- return -bhv_vop_attr_set(vp, name, data, size, xflags, NULL);
+ return -xfs_attr_set(xfs_vtoi(vp), name, data, size, xflags);
}
STATIC int
@@ -2511,7 +2522,8 @@ attr_generic_get(
{
int error, asize = size;
- error = bhv_vop_attr_get(vp, name, data, &asize, xflags, NULL);
+ error = xfs_attr_get(xfs_vtoi(vp), name, data,
+ &asize, xflags, NULL);
if (!error)
return asize;
return -error;
@@ -2521,7 +2533,7 @@ STATIC int
attr_generic_remove(
bhv_vnode_t *vp, char *name, int xflags)
{
- return -bhv_vop_attr_remove(vp, name, xflags, NULL);
+ return -xfs_attr_remove(xfs_vtoi(vp), name, xflags);
}
STATIC int
@@ -2576,7 +2588,7 @@ attr_generic_list(
attrlist_cursor_kern_t cursor = { 0 };
int error;
- error = bhv_vop_attr_list(vp, data, size, xflags, &cursor, NULL);
+ error = xfs_attr_list(xfs_vtoi(vp), data, size, xflags, &cursor);
if (error > 0)
return -error;
*result = -error;
diff --git a/fs/xfs/xfs_attr.h b/fs/xfs/xfs_attr.h
index 783977d3ea71..786eba3121c4 100644
--- a/fs/xfs/xfs_attr.h
+++ b/fs/xfs/xfs_attr.h
@@ -36,14 +36,13 @@
*========================================================================*/
struct cred;
-struct bhv_vnode;
struct xfs_attr_list_context;
-typedef int (*attrset_t)(struct bhv_vnode *, char *, void *, size_t, int);
-typedef int (*attrget_t)(struct bhv_vnode *, char *, void *, size_t, int);
-typedef int (*attrremove_t)(struct bhv_vnode *, char *, int);
-typedef int (*attrexists_t)(struct bhv_vnode *);
-typedef int (*attrcapable_t)(struct bhv_vnode *, struct cred *);
+typedef int (*attrset_t)(bhv_vnode_t *, char *, void *, size_t, int);
+typedef int (*attrget_t)(bhv_vnode_t *, char *, void *, size_t, int);
+typedef int (*attrremove_t)(bhv_vnode_t *, char *, int);
+typedef int (*attrexists_t)(bhv_vnode_t *);
+typedef int (*attrcapable_t)(bhv_vnode_t *, struct cred *);
typedef struct attrnames {
char * attr_name;
@@ -64,7 +63,7 @@ extern struct attrnames attr_trusted;
extern struct attrnames *attr_namespaces[ATTR_NAMECOUNT];
extern attrnames_t *attr_lookup_namespace(char *, attrnames_t **, int);
-extern int attr_generic_list(struct bhv_vnode *, void *, size_t, int, ssize_t *);
+extern int attr_generic_list(bhv_vnode_t *, void *, size_t, int, ssize_t *);
#define ATTR_DONTFOLLOW 0x0001 /* -- unused, from IRIX -- */
#define ATTR_ROOT 0x0002 /* use attrs in root (trusted) namespace */
@@ -159,12 +158,8 @@ struct xfs_da_args;
/*
* Overall external interface routines.
*/
-int xfs_attr_get(bhv_desc_t *, const char *, char *, int *, int, struct cred *);
-int xfs_attr_set(bhv_desc_t *, const char *, char *, int, int, struct cred *);
int xfs_attr_set_int(struct xfs_inode *, const char *, int, char *, int, int);
-int xfs_attr_remove(bhv_desc_t *, const char *, int, struct cred *);
int xfs_attr_remove_int(struct xfs_inode *, const char *, int, int);
-int xfs_attr_list(bhv_desc_t *, char *, int, int, struct attrlist_cursor_kern *, struct cred *);
int xfs_attr_list_int(struct xfs_attr_list_context *);
int xfs_attr_inactive(struct xfs_inode *dp);
diff --git a/fs/xfs/xfs_behavior.c b/fs/xfs/xfs_behavior.c
deleted file mode 100644
index 0dc17219d412..000000000000
--- a/fs/xfs/xfs_behavior.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-#include "xfs.h"
-
-/*
- * Source file used to associate/disassociate behaviors with virtualized
- * objects. See xfs_behavior.h for more information about behaviors, etc.
- *
- * The implementation is split between functions in this file and macros
- * in xfs_behavior.h.
- */
-
-/*
- * Insert a new behavior descriptor into a behavior chain.
- *
- * The behavior chain is ordered based on the 'position' number which
- * lives in the first field of the ops vector (higher numbers first).
- *
- * Attempts to insert duplicate ops result in an EINVAL return code.
- * Otherwise, return 0 to indicate success.
- */
-int
-bhv_insert(bhv_head_t *bhp, bhv_desc_t *bdp)
-{
- bhv_desc_t *curdesc, *prev;
- int position;
-
- /*
- * Validate the position value of the new behavior.
- */
- position = BHV_POSITION(bdp);
- ASSERT(position >= BHV_POSITION_BASE && position <= BHV_POSITION_TOP);
-
- /*
- * Find location to insert behavior. Check for duplicates.
- */
- prev = NULL;
- for (curdesc = bhp->bh_first;
- curdesc != NULL;
- curdesc = curdesc->bd_next) {
-
- /* Check for duplication. */
- if (curdesc->bd_ops == bdp->bd_ops) {
- ASSERT(0);
- return EINVAL;
- }
-
- /* Find correct position */
- if (position >= BHV_POSITION(curdesc)) {
- ASSERT(position != BHV_POSITION(curdesc));
- break; /* found it */
- }
-
- prev = curdesc;
- }
-
- if (prev == NULL) {
- /* insert at front of chain */
- bdp->bd_next = bhp->bh_first;
- bhp->bh_first = bdp;
- } else {
- /* insert after prev */
- bdp->bd_next = prev->bd_next;
- prev->bd_next = bdp;
- }
-
- return 0;
-}
-
-/*
- * Remove a behavior descriptor from a position in a behavior chain;
- * the position is guaranteed not to be the first position.
- * Should only be called by the bhv_remove() macro.
- */
-void
-bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp)
-{
- bhv_desc_t *curdesc, *prev;
-
- ASSERT(bhp->bh_first != NULL);
- ASSERT(bhp->bh_first->bd_next != NULL);
-
- prev = bhp->bh_first;
- for (curdesc = bhp->bh_first->bd_next;
- curdesc != NULL;
- curdesc = curdesc->bd_next) {
-
- if (curdesc == bdp)
- break; /* found it */
- prev = curdesc;
- }
-
- ASSERT(curdesc == bdp);
- prev->bd_next = bdp->bd_next; /* remove from after prev */
-}
-
-/*
- * Looks for the first behavior within a specified range of positions.
- * Return the associated behavior descriptor. Or NULL, if none found.
- */
-bhv_desc_t *
-bhv_lookup_range(bhv_head_t *bhp, int low, int high)
-{
- bhv_desc_t *curdesc;
-
- for (curdesc = bhp->bh_first;
- curdesc != NULL;
- curdesc = curdesc->bd_next) {
-
- int position = BHV_POSITION(curdesc);
-
- if (position <= high) {
- if (position >= low)
- return curdesc;
- return NULL;
- }
- }
-
- return NULL;
-}
-
-/*
- * Return the base behavior in the chain, or NULL if the chain
- * is empty.
- *
- * The caller has not read locked the behavior chain, so acquire the
- * lock before traversing the chain.
- */
-bhv_desc_t *
-bhv_base(bhv_head_t *bhp)
-{
- bhv_desc_t *curdesc;
-
- for (curdesc = bhp->bh_first;
- curdesc != NULL;
- curdesc = curdesc->bd_next) {
-
- if (curdesc->bd_next == NULL) {
- return curdesc;
- }
- }
-
- return NULL;
-}
-
-void
-bhv_head_init(
- bhv_head_t *bhp,
- char *name)
-{
- bhp->bh_first = NULL;
-}
-
-void
-bhv_insert_initial(
- bhv_head_t *bhp,
- bhv_desc_t *bdp)
-{
- ASSERT(bhp->bh_first == NULL);
- (bhp)->bh_first = bdp;
-}
-
-void
-bhv_head_destroy(
- bhv_head_t *bhp)
-{
- ASSERT(bhp->bh_first == NULL);
-}
diff --git a/fs/xfs/xfs_behavior.h b/fs/xfs/xfs_behavior.h
deleted file mode 100644
index e7ca1fed955a..000000000000
--- a/fs/xfs/xfs_behavior.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-#ifndef __XFS_BEHAVIOR_H__
-#define __XFS_BEHAVIOR_H__
-
-/*
- * Header file used to associate behaviors with virtualized objects.
- *
- * A virtualized object is an internal, virtualized representation of
- * OS entities such as persistent files, processes, or sockets. Examples
- * of virtualized objects include vnodes, vprocs, and vsockets. Often
- * a virtualized object is referred to simply as an "object."
- *
- * A behavior is essentially an implementation layer associated with
- * an object. Multiple behaviors for an object are chained together,
- * the order of chaining determining the order of invocation. Each
- * behavior of a given object implements the same set of interfaces
- * (e.g., the VOP interfaces).
- *
- * Behaviors may be dynamically inserted into an object's behavior chain,
- * such that the addition is transparent to consumers that already have
- * references to the object. Typically, a given behavior will be inserted
- * at a particular location in the behavior chain. Insertion of new
- * behaviors is synchronized with operations-in-progress (oip's) so that
- * the oip's always see a consistent view of the chain.
- *
- * The term "interposition" is used to refer to the act of inserting
- * a behavior such that it interposes on (i.e., is inserted in front
- * of) a particular other behavior. A key example of this is when a
- * system implementing distributed single system image wishes to
- * interpose a distribution layer (providing distributed coherency)
- * in front of an object that is otherwise only accessed locally.
- *
- * Note that the traditional vnode/inode combination is simply a virtualized
- * object that has exactly one associated behavior.
- *
- * Behavior synchronization is logic which is necessary under certain
- * circumstances that there is no conflict between ongoing operations
- * traversing the behavior chain and those dynamically modifying the
- * behavior chain. Because behavior synchronization adds extra overhead
- * to virtual operation invocation, we want to restrict, as much as
- * we can, the requirement for this extra code, to those situations
- * in which it is truly necessary.
- *
- * Behavior synchronization is needed whenever there's at least one class
- * of object in the system for which:
- * 1) multiple behaviors for a given object are supported,
- * -- AND --
- * 2a) insertion of a new behavior can happen dynamically at any time during
- * the life of an active object,
- * -- AND --
- * 3a) insertion of a new behavior needs to synchronize with existing
- * ops-in-progress.
- * -- OR --
- * 3b) multiple different behaviors can be dynamically inserted at
- * any time during the life of an active object
- * -- OR --
- * 3c) removal of a behavior can occur at any time during the life of
- * an active object.
- * -- OR --
- * 2b) removal of a behavior can occur at any time during the life of an
- * active object
- *
- */
-
-/*
- * Behavior head. Head of the chain of behaviors.
- * Contained within each virtualized object data structure.
- */
-typedef struct bhv_head {
- struct bhv_desc *bh_first; /* first behavior in chain */
-} bhv_head_t;
-
-/*
- * Behavior descriptor. Descriptor associated with each behavior.
- * Contained within the behavior's private data structure.
- */
-typedef struct bhv_desc {
- void *bd_pdata; /* private data for this behavior */
- void *bd_vobj; /* virtual object associated with */
- void *bd_ops; /* ops for this behavior */
- struct bhv_desc *bd_next; /* next behavior in chain */
-} bhv_desc_t;
-
-/*
- * Behavior identity field. A behavior's identity determines the position
- * where it lives within a behavior chain, and it's always the first field
- * of the behavior's ops vector. The optional id field further identifies the
- * subsystem responsible for the behavior.
- */
-typedef struct bhv_identity {
- __u16 bi_id; /* owning subsystem id */
- __u16 bi_position; /* position in chain */
-} bhv_identity_t;
-
-typedef bhv_identity_t bhv_position_t;
-
-#define BHV_IDENTITY_INIT(id,pos) {id, pos}
-#define BHV_IDENTITY_INIT_POSITION(pos) BHV_IDENTITY_INIT(0, pos)
-
-/*
- * Define boundaries of position values.
- */
-#define BHV_POSITION_INVALID 0 /* invalid position number */
-#define BHV_POSITION_BASE 1 /* base (last) implementation layer */
-#define BHV_POSITION_TOP 63 /* top (first) implementation layer */
-
-/*
- * Plumbing macros.
- */
-#define BHV_HEAD_FIRST(bhp) (ASSERT((bhp)->bh_first), (bhp)->bh_first)
-#define BHV_NEXT(bdp) (ASSERT((bdp)->bd_next), (bdp)->bd_next)
-#define BHV_NEXTNULL(bdp) ((bdp)->bd_next)
-#define BHV_VOBJ(bdp) (ASSERT((bdp)->bd_vobj), (bdp)->bd_vobj)
-#define BHV_VOBJNULL(bdp) ((bdp)->bd_vobj)
-#define BHV_PDATA(bdp) (bdp)->bd_pdata
-#define BHV_OPS(bdp) (bdp)->bd_ops
-#define BHV_IDENTITY(bdp) ((bhv_identity_t *)(bdp)->bd_ops)
-#define BHV_POSITION(bdp) (BHV_IDENTITY(bdp)->bi_position)
-
-extern void bhv_head_init(bhv_head_t *, char *);
-extern void bhv_head_destroy(bhv_head_t *);
-extern int bhv_insert(bhv_head_t *, bhv_desc_t *);
-extern void bhv_insert_initial(bhv_head_t *, bhv_desc_t *);
-
-/*
- * Initialize a new behavior descriptor.
- * Arguments:
- * bdp - pointer to behavior descriptor
- * pdata - pointer to behavior's private data
- * vobj - pointer to associated virtual object
- * ops - pointer to ops for this behavior
- */
-#define bhv_desc_init(bdp, pdata, vobj, ops) \
- { \
- (bdp)->bd_pdata = pdata; \
- (bdp)->bd_vobj = vobj; \
- (bdp)->bd_ops = ops; \
- (bdp)->bd_next = NULL; \
- }
-
-/*
- * Remove a behavior descriptor from a behavior chain.
- */
-#define bhv_remove(bhp, bdp) \
- { \
- if ((bhp)->bh_first == (bdp)) { \
- /* \
- * Remove from front of chain. \
- * Atomic wrt oip's. \
- */ \
- (bhp)->bh_first = (bdp)->bd_next; \
- } else { \
- /* remove from non-front of chain */ \
- bhv_remove_not_first(bhp, bdp); \
- } \
- (bdp)->bd_vobj = NULL; \
- }
-
-/*
- * Behavior module prototypes.
- */
-extern void bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp);
-extern bhv_desc_t * bhv_lookup_range(bhv_head_t *bhp, int low, int high);
-extern bhv_desc_t * bhv_base(bhv_head_t *bhp);
-
-/* No bhv locking on Linux */
-#define bhv_base_unlocked bhv_base
-
-#endif /* __XFS_BEHAVIOR_H__ */
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index 94b5c5fe2681..2e9b34b7344b 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -53,6 +53,7 @@
#include "xfs_trans_space.h"
#include "xfs_buf_item.h"
#include "xfs_filestream.h"
+#include "xfs_vnodeops.h"
#ifdef DEBUG
@@ -248,7 +249,7 @@ xfs_bmap_local_to_extents(
* Else, *lastxp will be set to the index of the found
* entry; *gotp will contain the entry.
*/
-STATIC xfs_bmbt_rec_t * /* pointer to found extent entry */
+STATIC xfs_bmbt_rec_host_t * /* pointer to found extent entry */
xfs_bmap_search_extents(
xfs_inode_t *ip, /* incore inode pointer */
xfs_fileoff_t bno, /* block number searched for */
@@ -273,21 +274,6 @@ xfs_bmap_isaeof(
#ifdef XFS_BMAP_TRACE
/*
- * Add a bmap trace buffer entry. Base routine for the others.
- */
-STATIC void
-xfs_bmap_trace_addentry(
- int opcode, /* operation */
- const char *fname, /* function name */
- char *desc, /* operation description */
- xfs_inode_t *ip, /* incore inode pointer */
- xfs_extnum_t idx, /* index of entry(ies) */
- xfs_extnum_t cnt, /* count of entries, 1 or 2 */
- xfs_bmbt_rec_t *r1, /* first record */
- xfs_bmbt_rec_t *r2, /* second record or null */
- int whichfork); /* data or attr fork */
-
-/*
* Add bmap trace entry prior to a call to xfs_iext_remove.
*/
STATIC void
@@ -714,7 +700,7 @@ xfs_bmap_add_extent_delay_real(
{
xfs_btree_cur_t *cur; /* btree cursor */
int diff; /* temp value */
- xfs_bmbt_rec_t *ep; /* extent entry for idx */
+ xfs_bmbt_rec_host_t *ep; /* extent entry for idx */
int error; /* error return value */
int i; /* temp state */
xfs_ifork_t *ifp; /* inode fork pointer */
@@ -1270,7 +1256,7 @@ xfs_bmap_add_extent_unwritten_real(
xfs_extdelta_t *delta) /* Change made to incore extents */
{
xfs_btree_cur_t *cur; /* btree cursor */
- xfs_bmbt_rec_t *ep; /* extent entry for idx */
+ xfs_bmbt_rec_host_t *ep; /* extent entry for idx */
int error; /* error return value */
int i; /* temp state */
xfs_ifork_t *ifp; /* inode fork pointer */
@@ -1823,7 +1809,7 @@ xfs_bmap_add_extent_hole_delay(
xfs_extdelta_t *delta, /* Change made to incore extents */
int rsvd) /* OK to allocate reserved blocks */
{
- xfs_bmbt_rec_t *ep; /* extent record for idx */
+ xfs_bmbt_rec_host_t *ep; /* extent record for idx */
xfs_ifork_t *ifp; /* inode fork pointer */
xfs_bmbt_irec_t left; /* left neighbor extent entry */
xfs_filblks_t newlen=0; /* new indirect size */
@@ -2012,7 +1998,7 @@ xfs_bmap_add_extent_hole_real(
xfs_extdelta_t *delta, /* Change made to incore extents */
int whichfork) /* data or attr fork */
{
- xfs_bmbt_rec_t *ep; /* pointer to extent entry ins. point */
+ xfs_bmbt_rec_host_t *ep; /* pointer to extent entry ins. point */
int error; /* error return value */
int i; /* temp state */
xfs_ifork_t *ifp; /* inode fork pointer */
@@ -3070,7 +3056,7 @@ xfs_bmap_del_extent(
xfs_fileoff_t del_endoff; /* first offset past del */
int delay; /* current block is delayed allocated */
int do_fx; /* free extent at end of routine */
- xfs_bmbt_rec_t *ep; /* current extent entry pointer */
+ xfs_bmbt_rec_host_t *ep; /* current extent entry pointer */
int error; /* error return value */
int flags; /* inode logging flags */
xfs_bmbt_irec_t got; /* current extent entry */
@@ -3418,7 +3404,7 @@ xfs_bmap_extents_to_btree(
xfs_bmbt_rec_t *arp; /* child record pointer */
xfs_bmbt_block_t *block; /* btree root block */
xfs_btree_cur_t *cur; /* bmap btree cursor */
- xfs_bmbt_rec_t *ep; /* extent record pointer */
+ xfs_bmbt_rec_host_t *ep; /* extent record pointer */
int error; /* error return value */
xfs_extnum_t i, cnt; /* extent record index */
xfs_ifork_t *ifp; /* inode fork pointer */
@@ -3507,8 +3493,8 @@ xfs_bmap_extents_to_btree(
for (cnt = i = 0; i < nextents; i++) {
ep = xfs_iext_get_ext(ifp, i);
if (!ISNULLSTARTBLOCK(xfs_bmbt_get_startblock(ep))) {
- arp->l0 = INT_GET(ep->l0, ARCH_CONVERT);
- arp->l1 = INT_GET(ep->l1, ARCH_CONVERT);
+ arp->l0 = cpu_to_be64(ep->l0);
+ arp->l1 = cpu_to_be64(ep->l1);
arp++; cnt++;
}
}
@@ -3590,7 +3576,7 @@ xfs_bmap_local_to_extents(
if (ifp->if_bytes) {
xfs_alloc_arg_t args; /* allocation arguments */
xfs_buf_t *bp; /* buffer for extent block */
- xfs_bmbt_rec_t *ep; /* extent record pointer */
+ xfs_bmbt_rec_host_t *ep;/* extent record pointer */
args.tp = tp;
args.mp = ip->i_mount;
@@ -3655,7 +3641,7 @@ done:
* entry (null if none). Else, *lastxp will be set to the index
* of the found entry; *gotp will contain the entry.
*/
-xfs_bmbt_rec_t * /* pointer to found extent entry */
+xfs_bmbt_rec_host_t * /* pointer to found extent entry */
xfs_bmap_search_multi_extents(
xfs_ifork_t *ifp, /* inode fork pointer */
xfs_fileoff_t bno, /* block number searched for */
@@ -3664,7 +3650,7 @@ xfs_bmap_search_multi_extents(
xfs_bmbt_irec_t *gotp, /* out: extent entry found */
xfs_bmbt_irec_t *prevp) /* out: previous extent entry found */
{
- xfs_bmbt_rec_t *ep; /* extent record pointer */
+ xfs_bmbt_rec_host_t *ep; /* extent record pointer */
xfs_extnum_t lastx; /* last extent index */
/*
@@ -3706,7 +3692,7 @@ xfs_bmap_search_multi_extents(
* Else, *lastxp will be set to the index of the found
* entry; *gotp will contain the entry.
*/
-STATIC xfs_bmbt_rec_t * /* pointer to found extent entry */
+STATIC xfs_bmbt_rec_host_t * /* pointer to found extent entry */
xfs_bmap_search_extents(
xfs_inode_t *ip, /* incore inode pointer */
xfs_fileoff_t bno, /* block number searched for */
@@ -3717,7 +3703,7 @@ xfs_bmap_search_extents(
xfs_bmbt_irec_t *prevp) /* out: previous extent entry found */
{
xfs_ifork_t *ifp; /* inode fork pointer */
- xfs_bmbt_rec_t *ep; /* extent record pointer */
+ xfs_bmbt_rec_host_t *ep; /* extent record pointer */
XFS_STATS_INC(xs_look_exlist);
ifp = XFS_IFORK_PTR(ip, fork);
@@ -3757,11 +3743,11 @@ xfs_bmap_trace_addentry(
xfs_inode_t *ip, /* incore inode pointer */
xfs_extnum_t idx, /* index of entry(ies) */
xfs_extnum_t cnt, /* count of entries, 1 or 2 */
- xfs_bmbt_rec_t *r1, /* first record */
- xfs_bmbt_rec_t *r2, /* second record or null */
+ xfs_bmbt_rec_host_t *r1, /* first record */
+ xfs_bmbt_rec_host_t *r2, /* second record or null */
int whichfork) /* data or attr fork */
{
- xfs_bmbt_rec_t tr2;
+ xfs_bmbt_rec_host_t tr2;
ASSERT(cnt == 1 || cnt == 2);
ASSERT(r1 != NULL);
@@ -3842,8 +3828,8 @@ xfs_bmap_trace_insert(
xfs_bmbt_irec_t *r2, /* inserted record 2 or null */
int whichfork) /* data or attr fork */
{
- xfs_bmbt_rec_t tr1; /* compressed record 1 */
- xfs_bmbt_rec_t tr2; /* compressed record 2 if needed */
+ xfs_bmbt_rec_host_t tr1; /* compressed record 1 */
+ xfs_bmbt_rec_host_t tr2; /* compressed record 2 if needed */
xfs_bmbt_set_all(&tr1, r1);
if (cnt == 2) {
@@ -4316,7 +4302,6 @@ xfs_bmap_first_unused(
xfs_fileoff_t *first_unused, /* unused block */
int whichfork) /* data or attr fork */
{
- xfs_bmbt_rec_t *ep; /* pointer to an extent entry */
int error; /* error return value */
int idx; /* extent record index */
xfs_ifork_t *ifp; /* inode fork pointer */
@@ -4340,7 +4325,7 @@ xfs_bmap_first_unused(
lowest = *first_unused;
nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
for (idx = 0, lastaddr = 0, max = lowest; idx < nextents; idx++) {
- ep = xfs_iext_get_ext(ifp, idx);
+ xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, idx);
off = xfs_bmbt_get_startoff(ep);
/*
* See if the hole before this extent will work.
@@ -4371,7 +4356,7 @@ xfs_bmap_last_before(
{
xfs_fileoff_t bno; /* input file offset */
int eof; /* hit end of file */
- xfs_bmbt_rec_t *ep; /* pointer to last extent */
+ xfs_bmbt_rec_host_t *ep; /* pointer to last extent */
int error; /* error return value */
xfs_bmbt_irec_t got; /* current extent value */
xfs_ifork_t *ifp; /* inode fork pointer */
@@ -4417,7 +4402,7 @@ xfs_bmap_last_offset(
xfs_fileoff_t *last_block, /* last block */
int whichfork) /* data or attr fork */
{
- xfs_bmbt_rec_t *ep; /* pointer to last extent */
+ xfs_bmbt_rec_host_t *ep; /* pointer to last extent */
int error; /* error return value */
xfs_ifork_t *ifp; /* inode fork pointer */
xfs_extnum_t nextents; /* number of extent entries */
@@ -4454,7 +4439,7 @@ xfs_bmap_one_block(
xfs_inode_t *ip, /* incore inode */
int whichfork) /* data or attr fork */
{
- xfs_bmbt_rec_t *ep; /* ptr to fork's extent */
+ xfs_bmbt_rec_host_t *ep; /* ptr to fork's extent */
xfs_ifork_t *ifp; /* inode fork pointer */
int rval; /* return value */
xfs_bmbt_irec_t s; /* internal version of extent */
@@ -4549,7 +4534,7 @@ xfs_bmap_read_extents(
* Loop over all leaf nodes. Copy information to the extent records.
*/
for (;;) {
- xfs_bmbt_rec_t *frp, *trp;
+ xfs_bmbt_rec_t *frp;
xfs_fsblock_t nextbno;
xfs_extnum_t num_recs;
xfs_extnum_t start;
@@ -4581,9 +4566,9 @@ xfs_bmap_read_extents(
frp = XFS_BTREE_REC_ADDR(xfs_bmbt, block, 1);
start = i;
for (j = 0; j < num_recs; j++, i++, frp++) {
- trp = xfs_iext_get_ext(ifp, i);
- trp->l0 = INT_GET(frp->l0, ARCH_CONVERT);
- trp->l1 = INT_GET(frp->l1, ARCH_CONVERT);
+ xfs_bmbt_rec_host_t *trp = xfs_iext_get_ext(ifp, i);
+ trp->l0 = be64_to_cpu(frp->l0);
+ trp->l1 = be64_to_cpu(frp->l1);
}
if (exntf == XFS_EXTFMT_NOSTATE) {
/*
@@ -4631,7 +4616,7 @@ xfs_bmap_trace_exlist(
xfs_extnum_t cnt, /* count of entries in the list */
int whichfork) /* data or attr fork */
{
- xfs_bmbt_rec_t *ep; /* current extent record */
+ xfs_bmbt_rec_host_t *ep; /* current extent record */
xfs_extnum_t idx; /* extent record index */
xfs_ifork_t *ifp; /* inode fork pointer */
xfs_bmbt_irec_t s; /* file extent record */
@@ -4727,7 +4712,7 @@ xfs_bmapi(
xfs_btree_cur_t *cur; /* bmap btree cursor */
xfs_fileoff_t end; /* end of mapped file region */
int eof; /* we've hit the end of extents */
- xfs_bmbt_rec_t *ep; /* extent record pointer */
+ xfs_bmbt_rec_host_t *ep; /* extent record pointer */
int error; /* error return */
xfs_bmbt_irec_t got; /* current file extent record */
xfs_ifork_t *ifp; /* inode fork pointer */
@@ -5378,7 +5363,7 @@ xfs_bunmapi(
xfs_btree_cur_t *cur; /* bmap btree cursor */
xfs_bmbt_irec_t del; /* extent being deleted */
int eof; /* is deleting at eof */
- xfs_bmbt_rec_t *ep; /* extent record pointer */
+ xfs_bmbt_rec_host_t *ep; /* extent record pointer */
int error; /* error return value */
xfs_extnum_t extno; /* extent number in list */
xfs_bmbt_irec_t got; /* current extent record */
@@ -5743,11 +5728,44 @@ error0:
}
/*
+ * returns 1 for success, 0 if we failed to map the extent.
+ */
+STATIC int
+xfs_getbmapx_fix_eof_hole(
+ xfs_inode_t *ip, /* xfs incore inode pointer */
+ struct getbmap *out, /* output structure */
+ int prealloced, /* this is a file with
+ * preallocated data space */
+ __int64_t end, /* last block requested */
+ xfs_fsblock_t startblock)
+{
+ __int64_t fixlen;
+ xfs_mount_t *mp; /* file system mount point */
+
+ if (startblock == HOLESTARTBLOCK) {
+ mp = ip->i_mount;
+ out->bmv_block = -1;
+ fixlen = XFS_FSB_TO_BB(mp, XFS_B_TO_FSB(mp, ip->i_size));
+ fixlen -= out->bmv_offset;
+ if (prealloced && out->bmv_offset + out->bmv_length == end) {
+ /* Came to hole at EOF. Trim it. */
+ if (fixlen <= 0)
+ return 0;
+ out->bmv_length = fixlen;
+ }
+ } else {
+ out->bmv_block = XFS_FSB_TO_DB(ip, startblock);
+ }
+
+ return 1;
+}
+
+/*
* Fcntl interface to xfs_bmapi.
*/
int /* error code */
xfs_getbmap(
- bhv_desc_t *bdp, /* XFS behavior descriptor*/
+ xfs_inode_t *ip,
struct getbmap *bmv, /* user bmap structure */
void __user *ap, /* pointer to user's array */
int interface) /* interface flags */
@@ -5756,7 +5774,6 @@ xfs_getbmap(
int error; /* return value */
__int64_t fixlen; /* length for -1 case */
int i; /* extent number */
- xfs_inode_t *ip; /* xfs incore inode pointer */
bhv_vnode_t *vp; /* corresponding vnode */
int lock; /* lock state */
xfs_bmbt_irec_t *map; /* buffer for user's data */
@@ -5774,8 +5791,7 @@ xfs_getbmap(
int bmapi_flags; /* flags for xfs_bmapi */
__int32_t oflags; /* getbmapx bmv_oflags field */
- vp = BHV_TO_VNODE(bdp);
- ip = XFS_BHVTOI(bdp);
+ vp = XFS_ITOV(ip);
mp = ip->i_mount;
whichfork = interface & BMV_IF_ATTRFORK ? XFS_ATTR_FORK : XFS_DATA_FORK;
@@ -5794,10 +5810,9 @@ xfs_getbmap(
* could misinterpret holes in a DMAPI file as true holes,
* when in fact they may represent offline user data.
*/
- if ( (interface & BMV_IF_NO_DMAPI_READ) == 0
- && DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ)
- && whichfork == XFS_DATA_FORK) {
-
+ if ((interface & BMV_IF_NO_DMAPI_READ) == 0 &&
+ DM_EVENT_ENABLED(ip, DM_EVENT_READ) &&
+ whichfork == XFS_DATA_FORK) {
error = XFS_SEND_DATA(mp, DM_EVENT_READ, vp, 0, 0, 0, NULL);
if (error)
return XFS_ERROR(error);
@@ -5854,7 +5869,8 @@ xfs_getbmap(
if (whichfork == XFS_DATA_FORK &&
(ip->i_delayed_blks || ip->i_size > ip->i_d.di_size)) {
/* xfs_fsize_t last_byte = xfs_file_last_byte(ip); */
- error = bhv_vop_flush_pages(vp, (xfs_off_t)0, -1, 0, FI_REMAPF);
+ error = xfs_flush_pages(ip, (xfs_off_t)0,
+ -1, 0, FI_REMAPF);
}
ASSERT(whichfork == XFS_ATTR_FORK || ip->i_delayed_blks == 0);
@@ -5904,18 +5920,15 @@ xfs_getbmap(
out.bmv_length = XFS_FSB_TO_BB(mp, map[i].br_blockcount);
ASSERT(map[i].br_startblock != DELAYSTARTBLOCK);
if (map[i].br_startblock == HOLESTARTBLOCK &&
- ((prealloced && out.bmv_offset + out.bmv_length == bmvend) ||
- whichfork == XFS_ATTR_FORK )) {
- /*
- * came to hole at end of file or the end of
- attribute fork
- */
+ whichfork == XFS_ATTR_FORK) {
+ /* came to the end of attribute fork */
goto unlock_and_return;
} else {
- out.bmv_block =
- (map[i].br_startblock == HOLESTARTBLOCK) ?
- -1 :
- XFS_FSB_TO_DB(ip, map[i].br_startblock);
+ if (!xfs_getbmapx_fix_eof_hole(ip, &out,
+ prealloced, bmvend,
+ map[i].br_startblock)) {
+ goto unlock_and_return;
+ }
/* return either getbmap/getbmapx structure. */
if (interface & BMV_IF_EXTENDED) {
@@ -5974,7 +5987,7 @@ xfs_bmap_isaeof(
{
int error; /* error return value */
xfs_ifork_t *ifp; /* inode fork pointer */
- xfs_bmbt_rec_t *lastrec; /* extent record pointer */
+ xfs_bmbt_rec_host_t *lastrec; /* extent record pointer */
xfs_extnum_t nextents; /* number of file extents */
xfs_bmbt_irec_t s; /* expanded extent record */
@@ -6018,7 +6031,7 @@ xfs_bmap_eof(
xfs_fsblock_t blockcount; /* extent block count */
int error; /* error return value */
xfs_ifork_t *ifp; /* inode fork pointer */
- xfs_bmbt_rec_t *lastrec; /* extent record pointer */
+ xfs_bmbt_rec_host_t *lastrec; /* extent record pointer */
xfs_extnum_t nextents; /* number of file extents */
xfs_fileoff_t startoff; /* extent starting file offset */
@@ -6465,10 +6478,9 @@ xfs_bmap_count_leaves(
int *count)
{
int b;
- xfs_bmbt_rec_t *frp;
for (b = 0; b < numrecs; b++) {
- frp = xfs_iext_get_ext(ifp, idx + b);
+ xfs_bmbt_rec_host_t *frp = xfs_iext_get_ext(ifp, idx + b);
*count += xfs_bmbt_get_blockcount(frp);
}
return 0;
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h
index 524b1c9d5246..68267d75ff19 100644
--- a/fs/xfs/xfs_bmap.h
+++ b/fs/xfs/xfs_bmap.h
@@ -335,7 +335,7 @@ xfs_bunmapi(
*/
int /* error code */
xfs_getbmap(
- bhv_desc_t *bdp, /* XFS behavior descriptor*/
+ xfs_inode_t *ip,
struct getbmap *bmv, /* user bmap structure */
void __user *ap, /* pointer to user's array */
int iflags); /* interface flags */
@@ -378,7 +378,7 @@ xfs_check_nostate_extents(
* entry (null if none). Else, *lastxp will be set to the index
* of the found entry; *gotp will contain the entry.
*/
-xfs_bmbt_rec_t *
+xfs_bmbt_rec_host_t *
xfs_bmap_search_multi_extents(struct xfs_ifork *, xfs_fileoff_t, int *,
xfs_extnum_t *, xfs_bmbt_irec_t *, xfs_bmbt_irec_t *);
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c
index 89b891f51cfb..32b49ec00fb5 100644
--- a/fs/xfs/xfs_bmap_btree.c
+++ b/fs/xfs/xfs_bmap_btree.c
@@ -260,13 +260,14 @@ xfs_bmbt_trace_cursor(
char *s,
int line)
{
- xfs_bmbt_rec_t r;
+ xfs_bmbt_rec_host_t r;
xfs_bmbt_set_all(&r, &cur->bc_rec.b);
xfs_bmbt_trace_enter(func, cur, s, XFS_BMBT_KTRACE_CUR, line,
(cur->bc_nlevels << 24) | (cur->bc_private.b.flags << 16) |
cur->bc_private.b.allocated,
- INT_GET(r.l0, ARCH_CONVERT) >> 32, (int)INT_GET(r.l0, ARCH_CONVERT), INT_GET(r.l1, ARCH_CONVERT) >> 32, (int)INT_GET(r.l1, ARCH_CONVERT),
+ r.l0 >> 32, (int)r.l0,
+ r.l1 >> 32, (int)r.l1,
(unsigned long)cur->bc_bufs[0], (unsigned long)cur->bc_bufs[1],
(unsigned long)cur->bc_bufs[2], (unsigned long)cur->bc_bufs[3],
(cur->bc_ptrs[0] << 16) | cur->bc_ptrs[1],
@@ -383,7 +384,7 @@ xfs_bmbt_delrec(
if (ptr < numrecs) {
memmove(&kp[ptr - 1], &kp[ptr],
(numrecs - ptr) * sizeof(*kp));
- memmove(&pp[ptr - 1], &pp[ptr], /* INT_: direct copy */
+ memmove(&pp[ptr - 1], &pp[ptr],
(numrecs - ptr) * sizeof(*pp));
xfs_bmbt_log_ptrs(cur, bp, ptr, numrecs - 1);
xfs_bmbt_log_keys(cur, bp, ptr, numrecs - 1);
@@ -815,7 +816,7 @@ xfs_bmbt_insrec(
#endif
memmove(&kp[ptr], &kp[ptr - 1],
(numrecs - ptr + 1) * sizeof(*kp));
- memmove(&pp[ptr], &pp[ptr - 1], /* INT_: direct copy */
+ memmove(&pp[ptr], &pp[ptr - 1],
(numrecs - ptr + 1) * sizeof(*pp));
#ifdef DEBUG
if ((error = xfs_btree_check_lptr(cur, *bnop, level))) {
@@ -1250,7 +1251,7 @@ xfs_bmbt_lshift(
return error;
}
#endif
- *lpp = *rpp; /* INT_: direct copy */
+ *lpp = *rpp;
xfs_bmbt_log_ptrs(cur, lbp, lrecs, lrecs);
} else {
lrp = XFS_BMAP_REC_IADDR(left, lrecs, cur);
@@ -1388,7 +1389,7 @@ xfs_bmbt_rshift(
}
#endif
*rkp = *lkp;
- *rpp = *lpp; /* INT_: direct copy */
+ *rpp = *lpp;
xfs_bmbt_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
xfs_bmbt_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
} else {
@@ -1826,7 +1827,7 @@ __xfs_bmbt_get_all(
void
xfs_bmbt_get_all(
- xfs_bmbt_rec_t *r,
+ xfs_bmbt_rec_host_t *r,
xfs_bmbt_irec_t *s)
{
__xfs_bmbt_get_all(r->l0, r->l1, s);
@@ -1862,7 +1863,7 @@ xfs_bmbt_get_block(
*/
xfs_filblks_t
xfs_bmbt_get_blockcount(
- xfs_bmbt_rec_t *r)
+ xfs_bmbt_rec_host_t *r)
{
return (xfs_filblks_t)(r->l1 & XFS_MASK64LO(21));
}
@@ -1872,7 +1873,7 @@ xfs_bmbt_get_blockcount(
*/
xfs_fsblock_t
xfs_bmbt_get_startblock(
- xfs_bmbt_rec_t *r)
+ xfs_bmbt_rec_host_t *r)
{
#if XFS_BIG_BLKNOS
return (((xfs_fsblock_t)r->l0 & XFS_MASK64LO(9)) << 43) |
@@ -1896,7 +1897,7 @@ xfs_bmbt_get_startblock(
*/
xfs_fileoff_t
xfs_bmbt_get_startoff(
- xfs_bmbt_rec_t *r)
+ xfs_bmbt_rec_host_t *r)
{
return ((xfs_fileoff_t)r->l0 &
XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
@@ -1904,7 +1905,7 @@ xfs_bmbt_get_startoff(
xfs_exntst_t
xfs_bmbt_get_state(
- xfs_bmbt_rec_t *r)
+ xfs_bmbt_rec_host_t *r)
{
int ext_flag;
@@ -1913,19 +1914,13 @@ xfs_bmbt_get_state(
ext_flag);
}
-#ifndef XFS_NATIVE_HOST
/* Endian flipping versions of the bmbt extraction functions */
void
xfs_bmbt_disk_get_all(
xfs_bmbt_rec_t *r,
xfs_bmbt_irec_t *s)
{
- __uint64_t l0, l1;
-
- l0 = INT_GET(r->l0, ARCH_CONVERT);
- l1 = INT_GET(r->l1, ARCH_CONVERT);
-
- __xfs_bmbt_get_all(l0, l1, s);
+ __xfs_bmbt_get_all(be64_to_cpu(r->l0), be64_to_cpu(r->l1), s);
}
/*
@@ -1935,7 +1930,7 @@ xfs_filblks_t
xfs_bmbt_disk_get_blockcount(
xfs_bmbt_rec_t *r)
{
- return (xfs_filblks_t)(INT_GET(r->l1, ARCH_CONVERT) & XFS_MASK64LO(21));
+ return (xfs_filblks_t)(be64_to_cpu(r->l1) & XFS_MASK64LO(21));
}
/*
@@ -1945,11 +1940,9 @@ xfs_fileoff_t
xfs_bmbt_disk_get_startoff(
xfs_bmbt_rec_t *r)
{
- return ((xfs_fileoff_t)INT_GET(r->l0, ARCH_CONVERT) &
+ return ((xfs_fileoff_t)be64_to_cpu(r->l0) &
XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
}
-#endif /* XFS_NATIVE_HOST */
-
/*
* Increment cursor by one record at the level.
@@ -2290,185 +2283,131 @@ xfs_bmbt_newroot(
}
/*
- * Set all the fields in a bmap extent record from the uncompressed form.
- */
-void
-xfs_bmbt_set_all(
- xfs_bmbt_rec_t *r,
- xfs_bmbt_irec_t *s)
-{
- int extent_flag;
-
- ASSERT((s->br_state == XFS_EXT_NORM) ||
- (s->br_state == XFS_EXT_UNWRITTEN));
- extent_flag = (s->br_state == XFS_EXT_NORM) ? 0 : 1;
- ASSERT((s->br_startoff & XFS_MASK64HI(9)) == 0);
- ASSERT((s->br_blockcount & XFS_MASK64HI(43)) == 0);
-#if XFS_BIG_BLKNOS
- ASSERT((s->br_startblock & XFS_MASK64HI(12)) == 0);
- r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
- ((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
- ((xfs_bmbt_rec_base_t)s->br_startblock >> 43);
- r->l1 = ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
- ((xfs_bmbt_rec_base_t)s->br_blockcount &
- (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
-#else /* !XFS_BIG_BLKNOS */
- if (ISNULLSTARTBLOCK(s->br_startblock)) {
- r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
- ((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
- (xfs_bmbt_rec_base_t)XFS_MASK64LO(9);
- r->l1 = XFS_MASK64HI(11) |
- ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
- ((xfs_bmbt_rec_base_t)s->br_blockcount &
- (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
- } else {
- r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
- ((xfs_bmbt_rec_base_t)s->br_startoff << 9);
- r->l1 = ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
- ((xfs_bmbt_rec_base_t)s->br_blockcount &
- (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
- }
-#endif /* XFS_BIG_BLKNOS */
-}
-
-/*
* Set all the fields in a bmap extent record from the arguments.
*/
void
xfs_bmbt_set_allf(
- xfs_bmbt_rec_t *r,
- xfs_fileoff_t o,
- xfs_fsblock_t b,
- xfs_filblks_t c,
- xfs_exntst_t v)
+ xfs_bmbt_rec_host_t *r,
+ xfs_fileoff_t startoff,
+ xfs_fsblock_t startblock,
+ xfs_filblks_t blockcount,
+ xfs_exntst_t state)
{
- int extent_flag;
+ int extent_flag = (state == XFS_EXT_NORM) ? 0 : 1;
+
+ ASSERT(state == XFS_EXT_NORM || state == XFS_EXT_UNWRITTEN);
+ ASSERT((startoff & XFS_MASK64HI(64-BMBT_STARTOFF_BITLEN)) == 0);
+ ASSERT((blockcount & XFS_MASK64HI(64-BMBT_BLOCKCOUNT_BITLEN)) == 0);
- ASSERT((v == XFS_EXT_NORM) || (v == XFS_EXT_UNWRITTEN));
- extent_flag = (v == XFS_EXT_NORM) ? 0 : 1;
- ASSERT((o & XFS_MASK64HI(64-BMBT_STARTOFF_BITLEN)) == 0);
- ASSERT((c & XFS_MASK64HI(64-BMBT_BLOCKCOUNT_BITLEN)) == 0);
#if XFS_BIG_BLKNOS
- ASSERT((b & XFS_MASK64HI(64-BMBT_STARTBLOCK_BITLEN)) == 0);
+ ASSERT((startblock & XFS_MASK64HI(64-BMBT_STARTBLOCK_BITLEN)) == 0);
+
r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
- ((xfs_bmbt_rec_base_t)o << 9) |
- ((xfs_bmbt_rec_base_t)b >> 43);
- r->l1 = ((xfs_bmbt_rec_base_t)b << 21) |
- ((xfs_bmbt_rec_base_t)c &
+ ((xfs_bmbt_rec_base_t)startoff << 9) |
+ ((xfs_bmbt_rec_base_t)startblock >> 43);
+ r->l1 = ((xfs_bmbt_rec_base_t)startblock << 21) |
+ ((xfs_bmbt_rec_base_t)blockcount &
(xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
#else /* !XFS_BIG_BLKNOS */
- if (ISNULLSTARTBLOCK(b)) {
+ if (ISNULLSTARTBLOCK(startblock)) {
r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
- ((xfs_bmbt_rec_base_t)o << 9) |
+ ((xfs_bmbt_rec_base_t)startoff << 9) |
(xfs_bmbt_rec_base_t)XFS_MASK64LO(9);
r->l1 = XFS_MASK64HI(11) |
- ((xfs_bmbt_rec_base_t)b << 21) |
- ((xfs_bmbt_rec_base_t)c &
+ ((xfs_bmbt_rec_base_t)startblock << 21) |
+ ((xfs_bmbt_rec_base_t)blockcount &
(xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
} else {
r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
- ((xfs_bmbt_rec_base_t)o << 9);
- r->l1 = ((xfs_bmbt_rec_base_t)b << 21) |
- ((xfs_bmbt_rec_base_t)c &
+ ((xfs_bmbt_rec_base_t)startoff << 9);
+ r->l1 = ((xfs_bmbt_rec_base_t)startblock << 21) |
+ ((xfs_bmbt_rec_base_t)blockcount &
(xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
}
#endif /* XFS_BIG_BLKNOS */
}
-#ifndef XFS_NATIVE_HOST
/*
* Set all the fields in a bmap extent record from the uncompressed form.
*/
void
-xfs_bmbt_disk_set_all(
- xfs_bmbt_rec_t *r,
- xfs_bmbt_irec_t *s)
+xfs_bmbt_set_all(
+ xfs_bmbt_rec_host_t *r,
+ xfs_bmbt_irec_t *s)
{
- int extent_flag;
-
- ASSERT((s->br_state == XFS_EXT_NORM) ||
- (s->br_state == XFS_EXT_UNWRITTEN));
- extent_flag = (s->br_state == XFS_EXT_NORM) ? 0 : 1;
- ASSERT((s->br_startoff & XFS_MASK64HI(9)) == 0);
- ASSERT((s->br_blockcount & XFS_MASK64HI(43)) == 0);
-#if XFS_BIG_BLKNOS
- ASSERT((s->br_startblock & XFS_MASK64HI(12)) == 0);
- INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
- ((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
- ((xfs_bmbt_rec_base_t)s->br_startblock >> 43));
- INT_SET(r->l1, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
- ((xfs_bmbt_rec_base_t)s->br_blockcount &
- (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
-#else /* !XFS_BIG_BLKNOS */
- if (ISNULLSTARTBLOCK(s->br_startblock)) {
- INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
- ((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
- (xfs_bmbt_rec_base_t)XFS_MASK64LO(9));
- INT_SET(r->l1, ARCH_CONVERT, XFS_MASK64HI(11) |
- ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
- ((xfs_bmbt_rec_base_t)s->br_blockcount &
- (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
- } else {
- INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
- ((xfs_bmbt_rec_base_t)s->br_startoff << 9));
- INT_SET(r->l1, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
- ((xfs_bmbt_rec_base_t)s->br_blockcount &
- (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
- }
-#endif /* XFS_BIG_BLKNOS */
+ xfs_bmbt_set_allf(r, s->br_startoff, s->br_startblock,
+ s->br_blockcount, s->br_state);
}
+
/*
* Set all the fields in a disk format bmap extent record from the arguments.
*/
void
xfs_bmbt_disk_set_allf(
- xfs_bmbt_rec_t *r,
- xfs_fileoff_t o,
- xfs_fsblock_t b,
- xfs_filblks_t c,
- xfs_exntst_t v)
+ xfs_bmbt_rec_t *r,
+ xfs_fileoff_t startoff,
+ xfs_fsblock_t startblock,
+ xfs_filblks_t blockcount,
+ xfs_exntst_t state)
{
- int extent_flag;
+ int extent_flag = (state == XFS_EXT_NORM) ? 0 : 1;
+
+ ASSERT(state == XFS_EXT_NORM || state == XFS_EXT_UNWRITTEN);
+ ASSERT((startoff & XFS_MASK64HI(64-BMBT_STARTOFF_BITLEN)) == 0);
+ ASSERT((blockcount & XFS_MASK64HI(64-BMBT_BLOCKCOUNT_BITLEN)) == 0);
- ASSERT((v == XFS_EXT_NORM) || (v == XFS_EXT_UNWRITTEN));
- extent_flag = (v == XFS_EXT_NORM) ? 0 : 1;
- ASSERT((o & XFS_MASK64HI(64-BMBT_STARTOFF_BITLEN)) == 0);
- ASSERT((c & XFS_MASK64HI(64-BMBT_BLOCKCOUNT_BITLEN)) == 0);
#if XFS_BIG_BLKNOS
- ASSERT((b & XFS_MASK64HI(64-BMBT_STARTBLOCK_BITLEN)) == 0);
- INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
- ((xfs_bmbt_rec_base_t)o << 9) |
- ((xfs_bmbt_rec_base_t)b >> 43));
- INT_SET(r->l1, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)b << 21) |
- ((xfs_bmbt_rec_base_t)c &
- (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
+ ASSERT((startblock & XFS_MASK64HI(64-BMBT_STARTBLOCK_BITLEN)) == 0);
+
+ r->l0 = cpu_to_be64(
+ ((xfs_bmbt_rec_base_t)extent_flag << 63) |
+ ((xfs_bmbt_rec_base_t)startoff << 9) |
+ ((xfs_bmbt_rec_base_t)startblock >> 43));
+ r->l1 = cpu_to_be64(
+ ((xfs_bmbt_rec_base_t)startblock << 21) |
+ ((xfs_bmbt_rec_base_t)blockcount &
+ (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
#else /* !XFS_BIG_BLKNOS */
- if (ISNULLSTARTBLOCK(b)) {
- INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
- ((xfs_bmbt_rec_base_t)o << 9) |
- (xfs_bmbt_rec_base_t)XFS_MASK64LO(9));
- INT_SET(r->l1, ARCH_CONVERT, XFS_MASK64HI(11) |
- ((xfs_bmbt_rec_base_t)b << 21) |
- ((xfs_bmbt_rec_base_t)c &
+ if (ISNULLSTARTBLOCK(startblock)) {
+ r->l0 = cpu_to_be64(
+ ((xfs_bmbt_rec_base_t)extent_flag << 63) |
+ ((xfs_bmbt_rec_base_t)startoff << 9) |
+ (xfs_bmbt_rec_base_t)XFS_MASK64LO(9));
+ r->l1 = cpu_to_be64(XFS_MASK64HI(11) |
+ ((xfs_bmbt_rec_base_t)startblock << 21) |
+ ((xfs_bmbt_rec_base_t)blockcount &
(xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
} else {
- INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
- ((xfs_bmbt_rec_base_t)o << 9));
- INT_SET(r->l1, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)b << 21) |
- ((xfs_bmbt_rec_base_t)c &
- (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
+ r->l0 = cpu_to_be64(
+ ((xfs_bmbt_rec_base_t)extent_flag << 63) |
+ ((xfs_bmbt_rec_base_t)startoff << 9));
+ r->l1 = cpu_to_be64(
+ ((xfs_bmbt_rec_base_t)startblock << 21) |
+ ((xfs_bmbt_rec_base_t)blockcount &
+ (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
}
#endif /* XFS_BIG_BLKNOS */
}
-#endif /* XFS_NATIVE_HOST */
+
+/*
+ * Set all the fields in a bmap extent record from the uncompressed form.
+ */
+void
+xfs_bmbt_disk_set_all(
+ xfs_bmbt_rec_t *r,
+ xfs_bmbt_irec_t *s)
+{
+ xfs_bmbt_disk_set_allf(r, s->br_startoff, s->br_startblock,
+ s->br_blockcount, s->br_state);
+}
/*
* Set the blockcount field in a bmap extent record.
*/
void
xfs_bmbt_set_blockcount(
- xfs_bmbt_rec_t *r,
+ xfs_bmbt_rec_host_t *r,
xfs_filblks_t v)
{
ASSERT((v & XFS_MASK64HI(43)) == 0);
@@ -2481,7 +2420,7 @@ xfs_bmbt_set_blockcount(
*/
void
xfs_bmbt_set_startblock(
- xfs_bmbt_rec_t *r,
+ xfs_bmbt_rec_host_t *r,
xfs_fsblock_t v)
{
#if XFS_BIG_BLKNOS
@@ -2509,7 +2448,7 @@ xfs_bmbt_set_startblock(
*/
void
xfs_bmbt_set_startoff(
- xfs_bmbt_rec_t *r,
+ xfs_bmbt_rec_host_t *r,
xfs_fileoff_t v)
{
ASSERT((v & XFS_MASK64HI(9)) == 0);
@@ -2523,7 +2462,7 @@ xfs_bmbt_set_startoff(
*/
void
xfs_bmbt_set_state(
- xfs_bmbt_rec_t *r,
+ xfs_bmbt_rec_host_t *r,
xfs_exntst_t v)
{
ASSERT(v == XFS_EXT_NORM || v == XFS_EXT_UNWRITTEN);
@@ -2624,10 +2563,8 @@ xfs_check_nostate_extents(
xfs_extnum_t idx,
xfs_extnum_t num)
{
- xfs_bmbt_rec_t *ep;
-
for (; num > 0; num--, idx++) {
- ep = xfs_iext_get_ext(ifp, idx);
+ xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, idx);
if ((ep->l0 >>
(64 - BMBT_EXNTFLAG_BITLEN)) != 0) {
ASSERT(0);
diff --git a/fs/xfs/xfs_bmap_btree.h b/fs/xfs/xfs_bmap_btree.h
index a77b1b753d0c..2d950e975918 100644
--- a/fs/xfs/xfs_bmap_btree.h
+++ b/fs/xfs/xfs_bmap_btree.h
@@ -35,45 +35,16 @@ typedef struct xfs_bmdr_block {
/*
* Bmap btree record and extent descriptor.
- * For 32-bit kernels,
- * l0:31 is an extent flag (value 1 indicates non-normal).
- * l0:0-30 and l1:9-31 are startoff.
- * l1:0-8, l2:0-31, and l3:21-31 are startblock.
- * l3:0-20 are blockcount.
- * For 64-bit kernels,
* l0:63 is an extent flag (value 1 indicates non-normal).
* l0:9-62 are startoff.
* l0:0-8 and l1:21-63 are startblock.
* l1:0-20 are blockcount.
*/
-
-#ifndef XFS_NATIVE_HOST
-
-#define BMBT_TOTAL_BITLEN 128 /* 128 bits, 16 bytes */
-#define BMBT_EXNTFLAG_BITOFF 0
#define BMBT_EXNTFLAG_BITLEN 1
-#define BMBT_STARTOFF_BITOFF (BMBT_EXNTFLAG_BITOFF + BMBT_EXNTFLAG_BITLEN)
#define BMBT_STARTOFF_BITLEN 54
-#define BMBT_STARTBLOCK_BITOFF (BMBT_STARTOFF_BITOFF + BMBT_STARTOFF_BITLEN)
#define BMBT_STARTBLOCK_BITLEN 52
-#define BMBT_BLOCKCOUNT_BITOFF \
- (BMBT_STARTBLOCK_BITOFF + BMBT_STARTBLOCK_BITLEN)
-#define BMBT_BLOCKCOUNT_BITLEN (BMBT_TOTAL_BITLEN - BMBT_BLOCKCOUNT_BITOFF)
-
-#else
-
-#define BMBT_TOTAL_BITLEN 128 /* 128 bits, 16 bytes */
-#define BMBT_EXNTFLAG_BITOFF 63
-#define BMBT_EXNTFLAG_BITLEN 1
-#define BMBT_STARTOFF_BITOFF (BMBT_EXNTFLAG_BITOFF - BMBT_STARTOFF_BITLEN)
-#define BMBT_STARTOFF_BITLEN 54
-#define BMBT_STARTBLOCK_BITOFF 85 /* 128 - 43 (other 9 is in first word) */
-#define BMBT_STARTBLOCK_BITLEN 52
-#define BMBT_BLOCKCOUNT_BITOFF 64 /* Start of second 64 bit container */
#define BMBT_BLOCKCOUNT_BITLEN 21
-#endif /* XFS_NATIVE_HOST */
-
#define BMBT_USE_64 1
@@ -83,12 +54,16 @@ typedef struct xfs_bmbt_rec_32
} xfs_bmbt_rec_32_t;
typedef struct xfs_bmbt_rec_64
{
- __uint64_t l0, l1;
+ __be64 l0, l1;
} xfs_bmbt_rec_64_t;
typedef __uint64_t xfs_bmbt_rec_base_t; /* use this for casts */
typedef xfs_bmbt_rec_64_t xfs_bmbt_rec_t, xfs_bmdr_rec_t;
+typedef struct xfs_bmbt_rec_host {
+ __uint64_t l0, l1;
+} xfs_bmbt_rec_host_t;
+
/*
* Values and macros for delayed-allocation startblock fields.
*/
@@ -281,23 +256,17 @@ extern ktrace_t *xfs_bmbt_trace_buf;
extern void xfs_bmdr_to_bmbt(xfs_bmdr_block_t *, int, xfs_bmbt_block_t *, int);
extern int xfs_bmbt_decrement(struct xfs_btree_cur *, int, int *);
extern int xfs_bmbt_delete(struct xfs_btree_cur *, int *);
-extern void xfs_bmbt_get_all(xfs_bmbt_rec_t *r, xfs_bmbt_irec_t *s);
+extern void xfs_bmbt_get_all(xfs_bmbt_rec_host_t *r, xfs_bmbt_irec_t *s);
extern xfs_bmbt_block_t *xfs_bmbt_get_block(struct xfs_btree_cur *cur,
int, struct xfs_buf **bpp);
-extern xfs_filblks_t xfs_bmbt_get_blockcount(xfs_bmbt_rec_t *r);
-extern xfs_fsblock_t xfs_bmbt_get_startblock(xfs_bmbt_rec_t *r);
-extern xfs_fileoff_t xfs_bmbt_get_startoff(xfs_bmbt_rec_t *r);
-extern xfs_exntst_t xfs_bmbt_get_state(xfs_bmbt_rec_t *r);
+extern xfs_filblks_t xfs_bmbt_get_blockcount(xfs_bmbt_rec_host_t *r);
+extern xfs_fsblock_t xfs_bmbt_get_startblock(xfs_bmbt_rec_host_t *r);
+extern xfs_fileoff_t xfs_bmbt_get_startoff(xfs_bmbt_rec_host_t *r);
+extern xfs_exntst_t xfs_bmbt_get_state(xfs_bmbt_rec_host_t *r);
-#ifndef XFS_NATIVE_HOST
extern void xfs_bmbt_disk_get_all(xfs_bmbt_rec_t *r, xfs_bmbt_irec_t *s);
extern xfs_filblks_t xfs_bmbt_disk_get_blockcount(xfs_bmbt_rec_t *r);
extern xfs_fileoff_t xfs_bmbt_disk_get_startoff(xfs_bmbt_rec_t *r);
-#else
-#define xfs_bmbt_disk_get_all(r, s) xfs_bmbt_get_all(r, s)
-#define xfs_bmbt_disk_get_blockcount(r) xfs_bmbt_get_blockcount(r)
-#define xfs_bmbt_disk_get_startoff(r) xfs_bmbt_get_startoff(r)
-#endif /* XFS_NATIVE_HOST */
extern int xfs_bmbt_increment(struct xfs_btree_cur *, int, int *);
extern int xfs_bmbt_insert(struct xfs_btree_cur *, int *);
@@ -315,22 +284,17 @@ extern int xfs_bmbt_lookup_ge(struct xfs_btree_cur *, xfs_fileoff_t,
*/
extern int xfs_bmbt_newroot(struct xfs_btree_cur *cur, int *lflags, int *stat);
-extern void xfs_bmbt_set_all(xfs_bmbt_rec_t *r, xfs_bmbt_irec_t *s);
-extern void xfs_bmbt_set_allf(xfs_bmbt_rec_t *r, xfs_fileoff_t o,
+extern void xfs_bmbt_set_all(xfs_bmbt_rec_host_t *r, xfs_bmbt_irec_t *s);
+extern void xfs_bmbt_set_allf(xfs_bmbt_rec_host_t *r, xfs_fileoff_t o,
xfs_fsblock_t b, xfs_filblks_t c, xfs_exntst_t v);
-extern void xfs_bmbt_set_blockcount(xfs_bmbt_rec_t *r, xfs_filblks_t v);
-extern void xfs_bmbt_set_startblock(xfs_bmbt_rec_t *r, xfs_fsblock_t v);
-extern void xfs_bmbt_set_startoff(xfs_bmbt_rec_t *r, xfs_fileoff_t v);
-extern void xfs_bmbt_set_state(xfs_bmbt_rec_t *r, xfs_exntst_t v);
+extern void xfs_bmbt_set_blockcount(xfs_bmbt_rec_host_t *r, xfs_filblks_t v);
+extern void xfs_bmbt_set_startblock(xfs_bmbt_rec_host_t *r, xfs_fsblock_t v);
+extern void xfs_bmbt_set_startoff(xfs_bmbt_rec_host_t *r, xfs_fileoff_t v);
+extern void xfs_bmbt_set_state(xfs_bmbt_rec_host_t *r, xfs_exntst_t v);
-#ifndef XFS_NATIVE_HOST
extern void xfs_bmbt_disk_set_all(xfs_bmbt_rec_t *r, xfs_bmbt_irec_t *s);
extern void xfs_bmbt_disk_set_allf(xfs_bmbt_rec_t *r, xfs_fileoff_t o,
xfs_fsblock_t b, xfs_filblks_t c, xfs_exntst_t v);
-#else
-#define xfs_bmbt_disk_set_all(r, s) xfs_bmbt_set_all(r, s)
-#define xfs_bmbt_disk_set_allf(r, o, b, c, v) xfs_bmbt_set_allf(r, o, b, c, v)
-#endif /* XFS_NATIVE_HOST */
extern void xfs_bmbt_to_bmdr(xfs_bmbt_block_t *, int, xfs_bmdr_block_t *, int);
extern int xfs_bmbt_update(struct xfs_btree_cur *, xfs_fileoff_t,
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index b0667cb27d66..c8f2c2886fe4 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -23,6 +23,7 @@
#include "xfs_inum.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
+#include "xfs_ag.h"
#include "xfs_dmapi.h"
#include "xfs_mount.h"
#include "xfs_buf_item.h"
diff --git a/fs/xfs/xfs_clnt.h b/fs/xfs/xfs_clnt.h
index f89196cb08d2..d16c1b971074 100644
--- a/fs/xfs/xfs_clnt.h
+++ b/fs/xfs/xfs_clnt.h
@@ -89,7 +89,6 @@ struct xfs_mount_args {
#define XFSMNT_IDELETE 0x08000000 /* inode cluster delete */
#define XFSMNT_SWALLOC 0x10000000 /* turn on stripe width
* allocation */
-#define XFSMNT_IHASHSIZE 0x20000000 /* inode hash table size */
#define XFSMNT_DIRSYNC 0x40000000 /* sync creat,link,unlink,rename
* symlink,mkdir,rmdir,mknod */
#define XFSMNT_FLAGS2 0x80000000 /* more flags set in flags2 */
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c
index de35d18cc002..584f1ae85cd9 100644
--- a/fs/xfs/xfs_dfrag.c
+++ b/fs/xfs/xfs_dfrag.c
@@ -42,6 +42,7 @@
#include "xfs_dfrag.h"
#include "xfs_error.h"
#include "xfs_rw.h"
+#include "xfs_vnodeops.h"
/*
* Syssgi interface for swapext
@@ -199,7 +200,8 @@ xfs_swap_extents(
if (VN_CACHED(tvp) != 0) {
xfs_inval_cached_trace(&tip->i_iocore, 0, -1, 0, -1);
- error = bhv_vop_flushinval_pages(tvp, 0, -1, FI_REMAPF_LOCKED);
+ error = xfs_flushinval_pages(tip, 0, -1,
+ FI_REMAPF_LOCKED);
if (error)
goto error0;
}
@@ -265,7 +267,7 @@ xfs_swap_extents(
* fields change.
*/
- bhv_vop_toss_pages(vp, 0, -1, FI_REMAPF);
+ xfs_tosspages(ip, 0, -1, FI_REMAPF);
tp = xfs_trans_alloc(mp, XFS_TRANS_SWAPEXT);
if ((error = xfs_trans_reserve(tp, 0,
diff --git a/fs/xfs/xfs_dinode.h b/fs/xfs/xfs_dinode.h
index fefd0116bac9..dedd713574e1 100644
--- a/fs/xfs/xfs_dinode.h
+++ b/fs/xfs/xfs_dinode.h
@@ -34,41 +34,41 @@ struct xfs_mount;
* because we only need the core part in the in-core inode.
*/
typedef struct xfs_timestamp {
- __int32_t t_sec; /* timestamp seconds */
- __int32_t t_nsec; /* timestamp nanoseconds */
+ __be32 t_sec; /* timestamp seconds */
+ __be32 t_nsec; /* timestamp nanoseconds */
} xfs_timestamp_t;
/*
* Note: Coordinate changes to this structure with the XFS_DI_* #defines
- * below and the offsets table in xfs_ialloc_log_di().
+ * below, the offsets table in xfs_ialloc_log_di() and struct xfs_icdinode
+ * in xfs_inode.h.
*/
-typedef struct xfs_dinode_core
-{
- __uint16_t di_magic; /* inode magic # = XFS_DINODE_MAGIC */
- __uint16_t di_mode; /* mode and type of file */
- __int8_t di_version; /* inode version */
- __int8_t di_format; /* format of di_c data */
- __uint16_t di_onlink; /* old number of links to file */
- __uint32_t di_uid; /* owner's user id */
- __uint32_t di_gid; /* owner's group id */
- __uint32_t di_nlink; /* number of links to file */
- __uint16_t di_projid; /* owner's project id */
- __uint8_t di_pad[8]; /* unused, zeroed space */
- __uint16_t di_flushiter; /* incremented on flush */
+typedef struct xfs_dinode_core {
+ __be16 di_magic; /* inode magic # = XFS_DINODE_MAGIC */
+ __be16 di_mode; /* mode and type of file */
+ __u8 di_version; /* inode version */
+ __u8 di_format; /* format of di_c data */
+ __be16 di_onlink; /* old number of links to file */
+ __be32 di_uid; /* owner's user id */
+ __be32 di_gid; /* owner's group id */
+ __be32 di_nlink; /* number of links to file */
+ __be16 di_projid; /* owner's project id */
+ __u8 di_pad[8]; /* unused, zeroed space */
+ __be16 di_flushiter; /* incremented on flush */
xfs_timestamp_t di_atime; /* time last accessed */
xfs_timestamp_t di_mtime; /* time last modified */
xfs_timestamp_t di_ctime; /* time created/inode modified */
- xfs_fsize_t di_size; /* number of bytes in file */
- xfs_drfsbno_t di_nblocks; /* # of direct & btree blocks used */
- xfs_extlen_t di_extsize; /* basic/minimum extent size for file */
- xfs_extnum_t di_nextents; /* number of extents in data fork */
- xfs_aextnum_t di_anextents; /* number of extents in attribute fork*/
- __uint8_t di_forkoff; /* attr fork offs, <<3 for 64b align */
- __int8_t di_aformat; /* format of attr fork's data */
- __uint32_t di_dmevmask; /* DMIG event mask */
- __uint16_t di_dmstate; /* DMIG state info */
- __uint16_t di_flags; /* random flags, XFS_DIFLAG_... */
- __uint32_t di_gen; /* generation number */
+ __be64 di_size; /* number of bytes in file */
+ __be64 di_nblocks; /* # of direct & btree blocks used */
+ __be32 di_extsize; /* basic/minimum extent size for file */
+ __be32 di_nextents; /* number of extents in data fork */
+ __be16 di_anextents; /* number of extents in attribute fork*/
+ __u8 di_forkoff; /* attr fork offs, <<3 for 64b align */
+ __s8 di_aformat; /* format of attr fork's data */
+ __be32 di_dmevmask; /* DMIG event mask */
+ __be16 di_dmstate; /* DMIG state info */
+ __be16 di_flags; /* random flags, XFS_DIFLAG_... */
+ __be32 di_gen; /* generation number */
} xfs_dinode_core_t;
#define DI_MAX_FLUSH 0xffff
@@ -81,13 +81,13 @@ typedef struct xfs_dinode
* sure to update the macros like XFS_LITINO below and
* XFS_BMAP_RBLOCK_DSIZE in xfs_bmap_btree.h.
*/
- xfs_agino_t di_next_unlinked;/* agi unlinked list ptr */
+ __be32 di_next_unlinked;/* agi unlinked list ptr */
union {
xfs_bmdr_block_t di_bmbt; /* btree root block */
xfs_bmbt_rec_32_t di_bmx[1]; /* extent list */
xfs_dir2_sf_t di_dir2sf; /* shortform directory v2 */
char di_c[1]; /* local contents */
- xfs_dev_t di_dev; /* device for S_IFCHR/S_IFBLK */
+ __be32 di_dev; /* device for S_IFCHR/S_IFBLK */
uuid_t di_muuid; /* mount point value */
char di_symlink[1]; /* local symbolic link */
} di_u;
@@ -175,8 +175,7 @@ typedef enum xfs_dinode_fmt
#define XFS_CFORK_Q_DISK(dcp) ((dcp)->di_forkoff != 0)
#define XFS_CFORK_BOFF(dcp) ((int)((dcp)->di_forkoff << 3))
-#define XFS_CFORK_BOFF_DISK(dcp) \
- ((int)(INT_GET((dcp)->di_forkoff, ARCH_CONVERT) << 3))
+#define XFS_CFORK_BOFF_DISK(dcp) ((int)((dcp)->di_forkoff << 3))
#define XFS_CFORK_DSIZE_DISK(dcp,mp) \
(XFS_CFORK_Q_DISK(dcp) ? XFS_CFORK_BOFF_DISK(dcp) : XFS_LITINO(mp))
@@ -225,8 +224,8 @@ typedef enum xfs_dinode_fmt
#define XFS_CFORK_NEXTENTS_DISK(dcp,w) \
((w) == XFS_DATA_FORK ? \
- INT_GET((dcp)->di_nextents, ARCH_CONVERT) : \
- INT_GET((dcp)->di_anextents, ARCH_CONVERT))
+ be32_to_cpu((dcp)->di_nextents) : \
+ be16_to_cpu((dcp)->di_anextents))
#define XFS_CFORK_NEXTENTS(dcp,w) \
((w) == XFS_DATA_FORK ? (dcp)->di_nextents : (dcp)->di_anextents)
#define XFS_DFORK_NEXTENTS(dip,w) XFS_CFORK_NEXTENTS_DISK(&(dip)->di_core, w)
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c
index 29e091914df4..b0f1ee8fcb90 100644
--- a/fs/xfs/xfs_dir2.c
+++ b/fs/xfs/xfs_dir2.c
@@ -43,8 +43,6 @@
#include "xfs_dir2_trace.h"
#include "xfs_error.h"
-static int xfs_dir2_put_dirent64_direct(xfs_dir2_put_args_t *pa);
-static int xfs_dir2_put_dirent64_uio(xfs_dir2_put_args_t *pa);
void
xfs_dir_mount(
@@ -293,47 +291,33 @@ xfs_dir_removename(
* Read a directory.
*/
int
-xfs_dir_getdents(
- xfs_trans_t *tp,
+xfs_readdir(
xfs_inode_t *dp,
- uio_t *uio, /* caller's buffer control */
- int *eofp) /* out: eof reached */
+ void *dirent,
+ size_t bufsize,
+ xfs_off_t *offset,
+ filldir_t filldir)
{
- int alignment; /* alignment required for ABI */
- xfs_dirent_t *dbp; /* malloc'ed buffer */
- xfs_dir2_put_t put; /* entry formatting routine */
int rval; /* return value */
int v; /* type-checking value */
+ vn_trace_entry(dp, __FUNCTION__, (inst_t *)__return_address);
+
+ if (XFS_FORCED_SHUTDOWN(dp->i_mount))
+ return XFS_ERROR(EIO);
+
ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
XFS_STATS_INC(xs_dir_getdents);
- /*
- * If our caller has given us a single contiguous aligned memory buffer,
- * just work directly within that buffer. If it's in user memory,
- * lock it down first.
- */
- alignment = sizeof(xfs_off_t) - 1;
- if ((uio->uio_iovcnt == 1) &&
- (((__psint_t)uio->uio_iov[0].iov_base & alignment) == 0) &&
- ((uio->uio_iov[0].iov_len & alignment) == 0)) {
- dbp = NULL;
- put = xfs_dir2_put_dirent64_direct;
- } else {
- dbp = kmem_alloc(sizeof(*dbp) + MAXNAMELEN, KM_SLEEP);
- put = xfs_dir2_put_dirent64_uio;
- }
- *eofp = 0;
if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
- rval = xfs_dir2_sf_getdents(dp, uio, eofp, dbp, put);
- else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
+ rval = xfs_dir2_sf_getdents(dp, dirent, offset, filldir);
+ else if ((rval = xfs_dir2_isblock(NULL, dp, &v)))
;
else if (v)
- rval = xfs_dir2_block_getdents(tp, dp, uio, eofp, dbp, put);
+ rval = xfs_dir2_block_getdents(dp, dirent, offset, filldir);
else
- rval = xfs_dir2_leaf_getdents(tp, dp, uio, eofp, dbp, put);
- if (dbp != NULL)
- kmem_free(dbp, sizeof(*dbp) + MAXNAMELEN);
+ rval = xfs_dir2_leaf_getdents(dp, dirent, bufsize, offset,
+ filldir);
return rval;
}
@@ -613,77 +597,6 @@ xfs_dir2_isleaf(
}
/*
- * Getdents put routine for 64-bit ABI, direct form.
- */
-static int
-xfs_dir2_put_dirent64_direct(
- xfs_dir2_put_args_t *pa)
-{
- xfs_dirent_t *idbp; /* dirent pointer */
- iovec_t *iovp; /* io vector */
- int namelen; /* entry name length */
- int reclen; /* entry total length */
- uio_t *uio; /* I/O control */
-
- namelen = pa->namelen;
- reclen = DIRENTSIZE(namelen);
- uio = pa->uio;
- /*
- * Won't fit in the remaining space.
- */
- if (reclen > uio->uio_resid) {
- pa->done = 0;
- return 0;
- }
- iovp = uio->uio_iov;
- idbp = (xfs_dirent_t *)iovp->iov_base;
- iovp->iov_base = (char *)idbp + reclen;
- iovp->iov_len -= reclen;
- uio->uio_resid -= reclen;
- idbp->d_reclen = reclen;
- idbp->d_ino = pa->ino;
- idbp->d_off = pa->cook;
- idbp->d_name[namelen] = '\0';
- pa->done = 1;
- memcpy(idbp->d_name, pa->name, namelen);
- return 0;
-}
-
-/*
- * Getdents put routine for 64-bit ABI, uio form.
- */
-static int
-xfs_dir2_put_dirent64_uio(
- xfs_dir2_put_args_t *pa)
-{
- xfs_dirent_t *idbp; /* dirent pointer */
- int namelen; /* entry name length */
- int reclen; /* entry total length */
- int rval; /* return value */
- uio_t *uio; /* I/O control */
-
- namelen = pa->namelen;
- reclen = DIRENTSIZE(namelen);
- uio = pa->uio;
- /*
- * Won't fit in the remaining space.
- */
- if (reclen > uio->uio_resid) {
- pa->done = 0;
- return 0;
- }
- idbp = pa->dbp;
- idbp->d_reclen = reclen;
- idbp->d_ino = pa->ino;
- idbp->d_off = pa->cook;
- idbp->d_name[namelen] = '\0';
- memcpy(idbp->d_name, pa->name, namelen);
- rval = xfs_uio_read((caddr_t)idbp, reclen, uio);
- pa->done = (rval == 0);
- return rval;
-}
-
-/*
* Remove the given block from the directory.
* This routine is used for data and free blocks, leaf/node are done
* by xfs_da_shrink_inode.
diff --git a/fs/xfs/xfs_dir2.h b/fs/xfs/xfs_dir2.h
index 86560b6f794c..b265197e74cf 100644
--- a/fs/xfs/xfs_dir2.h
+++ b/fs/xfs/xfs_dir2.h
@@ -60,21 +60,6 @@ typedef __uint32_t xfs_dir2_db_t;
typedef xfs_off_t xfs_dir2_off_t;
/*
- * For getdents, argument struct for put routines.
- */
-typedef int (*xfs_dir2_put_t)(struct xfs_dir2_put_args *pa);
-typedef struct xfs_dir2_put_args {
- xfs_off_t cook; /* cookie of (next) entry */
- xfs_intino_t ino; /* inode number */
- xfs_dirent_t *dbp; /* buffer pointer */
- char *name; /* directory entry name */
- int namelen; /* length of name */
- int done; /* output: set if value was stored */
- xfs_dir2_put_t put; /* put function ptr (i/o) */
- struct uio *uio; /* uio control structure */
-} xfs_dir2_put_args_t;
-
-/*
* Generic directory interface routines
*/
extern void xfs_dir_startup(void);
@@ -92,8 +77,6 @@ extern int xfs_dir_removename(struct xfs_trans *tp, struct xfs_inode *dp,
char *name, int namelen, xfs_ino_t ino,
xfs_fsblock_t *first,
struct xfs_bmap_free *flist, xfs_extlen_t tot);
-extern int xfs_dir_getdents(struct xfs_trans *tp, struct xfs_inode *dp,
- uio_t *uio, int *eofp);
extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp,
char *name, int namelen, xfs_ino_t inum,
xfs_fsblock_t *first,
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c
index e4df1aaae2a2..c171767e242a 100644
--- a/fs/xfs/xfs_dir2_block.c
+++ b/fs/xfs/xfs_dir2_block.c
@@ -22,6 +22,7 @@
#include "xfs_inum.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
+#include "xfs_ag.h"
#include "xfs_dir2.h"
#include "xfs_dmapi.h"
#include "xfs_mount.h"
@@ -432,12 +433,10 @@ xfs_dir2_block_addname(
*/
int /* error */
xfs_dir2_block_getdents(
- xfs_trans_t *tp, /* transaction (NULL) */
xfs_inode_t *dp, /* incore inode */
- uio_t *uio, /* caller's buffer control */
- int *eofp, /* eof reached? (out) */
- xfs_dirent_t *dbp, /* caller's buffer */
- xfs_dir2_put_t put) /* abi's formatting function */
+ void *dirent,
+ xfs_off_t *offset,
+ filldir_t filldir)
{
xfs_dir2_block_t *block; /* directory block structure */
xfs_dabuf_t *bp; /* buffer for block */
@@ -447,31 +446,32 @@ xfs_dir2_block_getdents(
char *endptr; /* end of the data entries */
int error; /* error return value */
xfs_mount_t *mp; /* filesystem mount point */
- xfs_dir2_put_args_t p; /* arg package for put rtn */
char *ptr; /* current data entry */
int wantoff; /* starting block offset */
+ xfs_ino_t ino;
+ xfs_off_t cook;
mp = dp->i_mount;
/*
* If the block number in the offset is out of range, we're done.
*/
- if (xfs_dir2_dataptr_to_db(mp, uio->uio_offset) > mp->m_dirdatablk) {
- *eofp = 1;
+ if (xfs_dir2_dataptr_to_db(mp, *offset) > mp->m_dirdatablk) {
return 0;
}
/*
* Can't read the block, give up, else get dabuf in bp.
*/
- if ((error =
- xfs_da_read_buf(tp, dp, mp->m_dirdatablk, -1, &bp, XFS_DATA_FORK))) {
+ error = xfs_da_read_buf(NULL, dp, mp->m_dirdatablk, -1,
+ &bp, XFS_DATA_FORK);
+ if (error)
return error;
- }
+
ASSERT(bp != NULL);
/*
* Extract the byte offset we start at from the seek pointer.
* We'll skip entries before this.
*/
- wantoff = xfs_dir2_dataptr_to_off(mp, uio->uio_offset);
+ wantoff = xfs_dir2_dataptr_to_off(mp, *offset);
block = bp->data;
xfs_dir2_data_check(dp, bp);
/*
@@ -480,9 +480,7 @@ xfs_dir2_block_getdents(
btp = xfs_dir2_block_tail_p(mp, block);
ptr = (char *)block->u;
endptr = (char *)xfs_dir2_block_leaf_p(btp);
- p.dbp = dbp;
- p.put = put;
- p.uio = uio;
+
/*
* Loop over the data portion of the block.
* Each object is a real entry (dep) or an unused one (dup).
@@ -508,33 +506,24 @@ xfs_dir2_block_getdents(
*/
if ((char *)dep - (char *)block < wantoff)
continue;
- /*
- * Set up argument structure for put routine.
- */
- p.namelen = dep->namelen;
- p.cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
+ cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
ptr - (char *)block);
- p.ino = be64_to_cpu(dep->inumber);
+ ino = be64_to_cpu(dep->inumber);
#if XFS_BIG_INUMS
- p.ino += mp->m_inoadd;
+ ino += mp->m_inoadd;
#endif
- p.name = (char *)dep->name;
-
- /*
- * Put the entry in the caller's buffer.
- */
- error = p.put(&p);
/*
* If it didn't fit, set the final offset to here & return.
*/
- if (!p.done) {
- uio->uio_offset =
- xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
+ if (filldir(dirent, dep->name, dep->namelen, cook,
+ ino, DT_UNKNOWN)) {
+ *offset = xfs_dir2_db_off_to_dataptr(mp,
+ mp->m_dirdatablk,
(char *)dep - (char *)block);
- xfs_da_brelse(tp, bp);
- return error;
+ xfs_da_brelse(NULL, bp);
+ return 0;
}
}
@@ -542,13 +531,8 @@ xfs_dir2_block_getdents(
* Reached the end of the block.
* Set the offset to a non-existent block 1 and return.
*/
- *eofp = 1;
-
- uio->uio_offset =
- xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0);
-
- xfs_da_brelse(tp, bp);
-
+ *offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0);
+ xfs_da_brelse(NULL, bp);
return 0;
}
diff --git a/fs/xfs/xfs_dir2_block.h b/fs/xfs/xfs_dir2_block.h
index e7c2606161e9..10e689676382 100644
--- a/fs/xfs/xfs_dir2_block.h
+++ b/fs/xfs/xfs_dir2_block.h
@@ -80,9 +80,8 @@ xfs_dir2_block_leaf_p(xfs_dir2_block_tail_t *btp)
* Function declarations.
*/
extern int xfs_dir2_block_addname(struct xfs_da_args *args);
-extern int xfs_dir2_block_getdents(struct xfs_trans *tp, struct xfs_inode *dp,
- struct uio *uio, int *eofp,
- struct xfs_dirent *dbp, xfs_dir2_put_t put);
+extern int xfs_dir2_block_getdents(struct xfs_inode *dp, void *dirent,
+ xfs_off_t *offset, filldir_t filldir);
extern int xfs_dir2_block_lookup(struct xfs_da_args *args);
extern int xfs_dir2_block_removename(struct xfs_da_args *args);
extern int xfs_dir2_block_replace(struct xfs_da_args *args);
diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c
index 7ebe295bd6d3..d2452699e9b1 100644
--- a/fs/xfs/xfs_dir2_data.c
+++ b/fs/xfs/xfs_dir2_data.c
@@ -22,6 +22,7 @@
#include "xfs_inum.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
+#include "xfs_ag.h"
#include "xfs_dir2.h"
#include "xfs_dmapi.h"
#include "xfs_mount.h"
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c
index 1b73c9ad646a..e7c12fa1303e 100644
--- a/fs/xfs/xfs_dir2_leaf.c
+++ b/fs/xfs/xfs_dir2_leaf.c
@@ -749,12 +749,11 @@ xfs_dir2_leaf_compact_x1(
*/
int /* error */
xfs_dir2_leaf_getdents(
- xfs_trans_t *tp, /* transaction pointer */
xfs_inode_t *dp, /* incore directory inode */
- uio_t *uio, /* I/O control & vectors */
- int *eofp, /* out: reached end of dir */
- xfs_dirent_t *dbp, /* caller's buffer */
- xfs_dir2_put_t put) /* ABI formatting routine */
+ void *dirent,
+ size_t bufsize,
+ xfs_off_t *offset,
+ filldir_t filldir)
{
xfs_dabuf_t *bp; /* data block buffer */
int byteoff; /* offset in current block */
@@ -763,7 +762,6 @@ xfs_dir2_leaf_getdents(
xfs_dir2_data_t *data; /* data block structure */
xfs_dir2_data_entry_t *dep; /* data entry */
xfs_dir2_data_unused_t *dup; /* unused entry */
- int eof; /* reached end of directory */
int error = 0; /* error return value */
int i; /* temporary loop index */
int j; /* temporary loop index */
@@ -776,46 +774,38 @@ xfs_dir2_leaf_getdents(
xfs_mount_t *mp; /* filesystem mount point */
xfs_dir2_off_t newoff; /* new curoff after new blk */
int nmap; /* mappings to ask xfs_bmapi */
- xfs_dir2_put_args_t *p; /* formatting arg bundle */
char *ptr = NULL; /* pointer to current data */
int ra_current; /* number of read-ahead blks */
int ra_index; /* *map index for read-ahead */
int ra_offset; /* map entry offset for ra */
int ra_want; /* readahead count wanted */
+ xfs_ino_t ino;
/*
* If the offset is at or past the largest allowed value,
- * give up right away, return eof.
+ * give up right away.
*/
- if (uio->uio_offset >= XFS_DIR2_MAX_DATAPTR) {
- *eofp = 1;
+ if (*offset >= XFS_DIR2_MAX_DATAPTR)
return 0;
- }
+
mp = dp->i_mount;
- /*
- * Setup formatting arguments.
- */
- p = kmem_alloc(sizeof(*p), KM_SLEEP);
- p->dbp = dbp;
- p->put = put;
- p->uio = uio;
+
/*
* Set up to bmap a number of blocks based on the caller's
* buffer size, the directory block size, and the filesystem
* block size.
*/
- map_size =
- howmany(uio->uio_resid + mp->m_dirblksize,
- mp->m_sb.sb_blocksize);
+ map_size = howmany(bufsize + mp->m_dirblksize, mp->m_sb.sb_blocksize);
map = kmem_alloc(map_size * sizeof(*map), KM_SLEEP);
map_valid = ra_index = ra_offset = ra_current = map_blocks = 0;
bp = NULL;
- eof = 1;
+
/*
* Inside the loop we keep the main offset value as a byte offset
* in the directory file.
*/
- curoff = xfs_dir2_dataptr_to_byte(mp, uio->uio_offset);
+ curoff = xfs_dir2_dataptr_to_byte(mp, *offset);
+
/*
* Force this conversion through db so we truncate the offset
* down to get the start of the data block.
@@ -836,7 +826,7 @@ xfs_dir2_leaf_getdents(
* take it out of the mapping.
*/
if (bp) {
- xfs_da_brelse(tp, bp);
+ xfs_da_brelse(NULL, bp);
bp = NULL;
map_blocks -= mp->m_dirblkfsbs;
/*
@@ -862,8 +852,9 @@ xfs_dir2_leaf_getdents(
/*
* Recalculate the readahead blocks wanted.
*/
- ra_want = howmany(uio->uio_resid + mp->m_dirblksize,
+ ra_want = howmany(bufsize + mp->m_dirblksize,
mp->m_sb.sb_blocksize) - 1;
+
/*
* If we don't have as many as we want, and we haven't
* run out of data blocks, get some more mappings.
@@ -876,7 +867,7 @@ xfs_dir2_leaf_getdents(
* we already have in the table.
*/
nmap = map_size - map_valid;
- error = xfs_bmapi(tp, dp,
+ error = xfs_bmapi(NULL, dp,
map_off,
xfs_dir2_byte_to_da(mp,
XFS_DIR2_LEAF_OFFSET) - map_off,
@@ -939,7 +930,7 @@ xfs_dir2_leaf_getdents(
* mapping.
*/
curdb = xfs_dir2_da_to_db(mp, map->br_startoff);
- error = xfs_da_read_buf(tp, dp, map->br_startoff,
+ error = xfs_da_read_buf(NULL, dp, map->br_startoff,
map->br_blockcount >= mp->m_dirblkfsbs ?
XFS_FSB_TO_DADDR(mp, map->br_startblock) :
-1,
@@ -982,7 +973,7 @@ xfs_dir2_leaf_getdents(
* is a very rare case.
*/
else if (i > ra_current) {
- (void)xfs_da_reada_buf(tp, dp,
+ (void)xfs_da_reada_buf(NULL, dp,
map[ra_index].br_startoff +
ra_offset, XFS_DATA_FORK);
ra_current = i;
@@ -1089,46 +1080,39 @@ xfs_dir2_leaf_getdents(
*/
dep = (xfs_dir2_data_entry_t *)ptr;
- p->namelen = dep->namelen;
-
- length = xfs_dir2_data_entsize(p->namelen);
-
- p->cook = xfs_dir2_byte_to_dataptr(mp, curoff + length);
+ length = xfs_dir2_data_entsize(dep->namelen);
- p->ino = be64_to_cpu(dep->inumber);
+ ino = be64_to_cpu(dep->inumber);
#if XFS_BIG_INUMS
- p->ino += mp->m_inoadd;
+ ino += mp->m_inoadd;
#endif
- p->name = (char *)dep->name;
-
- error = p->put(p);
/*
* Won't fit. Return to caller.
*/
- if (!p->done) {
- eof = 0;
+ if (filldir(dirent, dep->name, dep->namelen,
+ xfs_dir2_byte_to_dataptr(mp, curoff + length),
+ ino, DT_UNKNOWN))
break;
- }
+
/*
* Advance to next entry in the block.
*/
ptr += length;
curoff += length;
+ bufsize -= length;
}
/*
* All done. Set output offset value to current offset.
*/
- *eofp = eof;
if (curoff > xfs_dir2_dataptr_to_byte(mp, XFS_DIR2_MAX_DATAPTR))
- uio->uio_offset = XFS_DIR2_MAX_DATAPTR;
+ *offset = XFS_DIR2_MAX_DATAPTR;
else
- uio->uio_offset = xfs_dir2_byte_to_dataptr(mp, curoff);
+ *offset = xfs_dir2_byte_to_dataptr(mp, curoff);
kmem_free(map, map_size * sizeof(*map));
- kmem_free(p, sizeof(*p));
if (bp)
- xfs_da_brelse(tp, bp);
+ xfs_da_brelse(NULL, bp);
return error;
}
diff --git a/fs/xfs/xfs_dir2_leaf.h b/fs/xfs/xfs_dir2_leaf.h
index 70c97f3f815e..6c9539f06987 100644
--- a/fs/xfs/xfs_dir2_leaf.h
+++ b/fs/xfs/xfs_dir2_leaf.h
@@ -232,9 +232,9 @@ extern void xfs_dir2_leaf_compact(struct xfs_da_args *args,
extern void xfs_dir2_leaf_compact_x1(struct xfs_dabuf *bp, int *indexp,
int *lowstalep, int *highstalep,
int *lowlogp, int *highlogp);
-extern int xfs_dir2_leaf_getdents(struct xfs_trans *tp, struct xfs_inode *dp,
- struct uio *uio, int *eofp,
- struct xfs_dirent *dbp, xfs_dir2_put_t put);
+extern int xfs_dir2_leaf_getdents(struct xfs_inode *dp, void *dirent,
+ size_t bufsize, xfs_off_t *offset,
+ filldir_t filldir);
extern int xfs_dir2_leaf_init(struct xfs_da_args *args, xfs_dir2_db_t bno,
struct xfs_dabuf **bpp, int magic);
extern void xfs_dir2_leaf_log_ents(struct xfs_trans *tp, struct xfs_dabuf *bp,
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c
index 91c61d9632c8..eb18e399e836 100644
--- a/fs/xfs/xfs_dir2_node.c
+++ b/fs/xfs/xfs_dir2_node.c
@@ -22,6 +22,7 @@
#include "xfs_inum.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
+#include "xfs_ag.h"
#include "xfs_dir2.h"
#include "xfs_dmapi.h"
#include "xfs_mount.h"
diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c
index 38fc4f22b76d..182c70315ad1 100644
--- a/fs/xfs/xfs_dir2_sf.c
+++ b/fs/xfs/xfs_dir2_sf.c
@@ -22,6 +22,7 @@
#include "xfs_inum.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
+#include "xfs_ag.h"
#include "xfs_dir2.h"
#include "xfs_dmapi.h"
#include "xfs_mount.h"
@@ -695,19 +696,18 @@ xfs_dir2_sf_create(
int /* error */
xfs_dir2_sf_getdents(
xfs_inode_t *dp, /* incore directory inode */
- uio_t *uio, /* caller's buffer control */
- int *eofp, /* eof reached? (out) */
- xfs_dirent_t *dbp, /* caller's buffer */
- xfs_dir2_put_t put) /* abi's formatting function */
+ void *dirent,
+ xfs_off_t *offset,
+ filldir_t filldir)
{
- int error; /* error return value */
int i; /* shortform entry number */
xfs_mount_t *mp; /* filesystem mount point */
xfs_dir2_dataptr_t off; /* current entry's offset */
- xfs_dir2_put_args_t p; /* arg package for put rtn */
xfs_dir2_sf_entry_t *sfep; /* shortform directory entry */
xfs_dir2_sf_t *sfp; /* shortform structure */
- xfs_off_t dir_offset;
+ xfs_dir2_dataptr_t dot_offset;
+ xfs_dir2_dataptr_t dotdot_offset;
+ xfs_ino_t ino;
mp = dp->i_mount;
@@ -720,8 +720,6 @@ xfs_dir2_sf_getdents(
return XFS_ERROR(EIO);
}
- dir_offset = uio->uio_offset;
-
ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
ASSERT(dp->i_df.if_u1.if_data != NULL);
@@ -732,108 +730,78 @@ xfs_dir2_sf_getdents(
/*
* If the block number in the offset is out of range, we're done.
*/
- if (xfs_dir2_dataptr_to_db(mp, dir_offset) > mp->m_dirdatablk) {
- *eofp = 1;
+ if (xfs_dir2_dataptr_to_db(mp, *offset) > mp->m_dirdatablk)
return 0;
- }
/*
- * Set up putargs structure.
+ * Precalculate offsets for . and .. as we will always need them.
+ *
+ * XXX(hch): the second argument is sometimes 0 and sometimes
+ * mp->m_dirdatablk.
*/
- p.dbp = dbp;
- p.put = put;
- p.uio = uio;
+ dot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
+ XFS_DIR2_DATA_DOT_OFFSET);
+ dotdot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
+ XFS_DIR2_DATA_DOTDOT_OFFSET);
+
/*
* Put . entry unless we're starting past it.
*/
- if (dir_offset <=
- xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
- XFS_DIR2_DATA_DOT_OFFSET)) {
- p.cook = xfs_dir2_db_off_to_dataptr(mp, 0,
- XFS_DIR2_DATA_DOTDOT_OFFSET);
- p.ino = dp->i_ino;
+ if (*offset <= dot_offset) {
+ ino = dp->i_ino;
#if XFS_BIG_INUMS
- p.ino += mp->m_inoadd;
+ ino += mp->m_inoadd;
#endif
- p.name = ".";
- p.namelen = 1;
-
- error = p.put(&p);
-
- if (!p.done) {
- uio->uio_offset =
- xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
- XFS_DIR2_DATA_DOT_OFFSET);
- return error;
+ if (filldir(dirent, ".", 1, dotdot_offset, ino, DT_DIR)) {
+ *offset = dot_offset;
+ return 0;
}
}
/*
* Put .. entry unless we're starting past it.
*/
- if (dir_offset <=
- xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
- XFS_DIR2_DATA_DOTDOT_OFFSET)) {
- p.cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
- XFS_DIR2_DATA_FIRST_OFFSET);
- p.ino = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent);
+ if (*offset <= dotdot_offset) {
+ off = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
+ XFS_DIR2_DATA_FIRST_OFFSET);
+ ino = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent);
#if XFS_BIG_INUMS
- p.ino += mp->m_inoadd;
+ ino += mp->m_inoadd;
#endif
- p.name = "..";
- p.namelen = 2;
-
- error = p.put(&p);
-
- if (!p.done) {
- uio->uio_offset =
- xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
- XFS_DIR2_DATA_DOTDOT_OFFSET);
- return error;
+ if (filldir(dirent, "..", 2, off, ino, DT_DIR)) {
+ *offset = dotdot_offset;
+ return 0;
}
}
/*
* Loop while there are more entries and put'ing works.
*/
- for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp);
- i < sfp->hdr.count;
- i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) {
-
+ sfep = xfs_dir2_sf_firstentry(sfp);
+ for (i = 0; i < sfp->hdr.count; i++) {
off = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
xfs_dir2_sf_get_offset(sfep));
- if (dir_offset > off)
+ if (*offset > off) {
+ sfep = xfs_dir2_sf_nextentry(sfp, sfep);
continue;
+ }
- p.namelen = sfep->namelen;
-
- p.cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
- xfs_dir2_sf_get_offset(sfep) +
- xfs_dir2_data_entsize(p.namelen));
-
- p.ino = xfs_dir2_sf_get_inumber(sfp, xfs_dir2_sf_inumberp(sfep));
+ ino = xfs_dir2_sf_get_inumber(sfp, xfs_dir2_sf_inumberp(sfep));
#if XFS_BIG_INUMS
- p.ino += mp->m_inoadd;
+ ino += mp->m_inoadd;
#endif
- p.name = (char *)sfep->name;
-
- error = p.put(&p);
- if (!p.done) {
- uio->uio_offset = off;
- return error;
+ if (filldir(dirent, sfep->name, sfep->namelen,
+ off + xfs_dir2_data_entsize(sfep->namelen),
+ ino, DT_UNKNOWN)) {
+ *offset = off;
+ return 0;
}
+ sfep = xfs_dir2_sf_nextentry(sfp, sfep);
}
- /*
- * They all fit.
- */
- *eofp = 1;
-
- uio->uio_offset =
- xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0);
-
+ *offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0);
return 0;
}
diff --git a/fs/xfs/xfs_dir2_sf.h b/fs/xfs/xfs_dir2_sf.h
index 11e503209afa..005629d702d2 100644
--- a/fs/xfs/xfs_dir2_sf.h
+++ b/fs/xfs/xfs_dir2_sf.h
@@ -169,9 +169,8 @@ extern int xfs_dir2_block_to_sf(struct xfs_da_args *args, struct xfs_dabuf *bp,
int size, xfs_dir2_sf_hdr_t *sfhp);
extern int xfs_dir2_sf_addname(struct xfs_da_args *args);
extern int xfs_dir2_sf_create(struct xfs_da_args *args, xfs_ino_t pino);
-extern int xfs_dir2_sf_getdents(struct xfs_inode *dp, struct uio *uio,
- int *eofp, struct xfs_dirent *dbp,
- xfs_dir2_put_t put);
+extern int xfs_dir2_sf_getdents(struct xfs_inode *dp, void *dirent,
+ xfs_off_t *offset, filldir_t filldir);
extern int xfs_dir2_sf_lookup(struct xfs_da_args *args);
extern int xfs_dir2_sf_removename(struct xfs_da_args *args);
extern int xfs_dir2_sf_replace(struct xfs_da_args *args);
diff --git a/fs/xfs/xfs_dmapi.h b/fs/xfs/xfs_dmapi.h
index adc3d251240d..f71784ab6a60 100644
--- a/fs/xfs/xfs_dmapi.h
+++ b/fs/xfs/xfs_dmapi.h
@@ -67,17 +67,15 @@ typedef enum {
#define HAVE_DM_RIGHT_T
/* Defines for determining if an event message should be sent. */
-#define DM_EVENT_ENABLED(vfsp, ip, event) ( \
- unlikely ((vfsp)->vfs_flag & VFS_DMI) && \
+#ifdef HAVE_DMAPI
+#define DM_EVENT_ENABLED(ip, event) ( \
+ unlikely ((ip)->i_mount->m_flags & XFS_MOUNT_DMAPI) && \
( ((ip)->i_d.di_dmevmask & (1 << event)) || \
((ip)->i_mount->m_dmevmask & (1 << event)) ) \
)
-
-#define DM_EVENT_ENABLED_IO(vfsp, io, event) ( \
- unlikely ((vfsp)->vfs_flag & VFS_DMI) && \
- ( ((io)->io_dmevmask & (1 << event)) || \
- ((io)->io_mount->m_dmevmask & (1 << event)) ) \
- )
+#else
+#define DM_EVENT_ENABLED(ip, event) (0)
+#endif
#define DM_XFS_VALID_FS_EVENTS ( \
(1 << DM_EVENT_PREUNMOUNT) | \
@@ -170,7 +168,4 @@ typedef enum {
DM_FLAGS_NDELAY : 0)
#define AT_DELAY_FLAG(f) ((f&ATTR_NONBLOCK) ? DM_FLAGS_NDELAY : 0)
-
-extern struct bhv_module_vfsops xfs_dmops;
-
#endif /* __XFS_DMAPI_H__ */
diff --git a/fs/xfs/xfs_dmops.c b/fs/xfs/xfs_dmops.c
index 1e4a35ddf7f9..a1e55fb9d5dd 100644
--- a/fs/xfs/xfs_dmops.c
+++ b/fs/xfs/xfs_dmops.c
@@ -19,18 +19,38 @@
#include "xfs_fs.h"
#include "xfs_types.h"
#include "xfs_log.h"
-#include "xfs_inum.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
-#include "xfs_ag.h"
-#include "xfs_dir2.h"
#include "xfs_dmapi.h"
+#include "xfs_inum.h"
+#include "xfs_ag.h"
#include "xfs_mount.h"
+#include "xfs_clnt.h"
-xfs_dmops_t xfs_dmcore_stub = {
+
+static struct xfs_dmops xfs_dmcore_stub = {
.xfs_send_data = (xfs_send_data_t)fs_nosys,
.xfs_send_mmap = (xfs_send_mmap_t)fs_noerr,
.xfs_send_destroy = (xfs_send_destroy_t)fs_nosys,
.xfs_send_namesp = (xfs_send_namesp_t)fs_nosys,
- .xfs_send_unmount = (xfs_send_unmount_t)fs_noval,
+ .xfs_send_mount = (xfs_send_mount_t)fs_nosys,
+ .xfs_send_unmount = (xfs_send_unmount_t)fs_noerr,
};
+
+int
+xfs_dmops_get(struct xfs_mount *mp, struct xfs_mount_args *args)
+{
+ if (args->flags & XFSMNT_DMAPI) {
+ cmn_err(CE_WARN,
+ "XFS: dmapi support not available in this kernel.");
+ return EINVAL;
+ }
+
+ mp->m_dm_ops = &xfs_dmcore_stub;
+ return 0;
+}
+
+void
+xfs_dmops_put(struct xfs_mount *mp)
+{
+}
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c
index 8c4331631337..a4634d94e561 100644
--- a/fs/xfs/xfs_error.c
+++ b/fs/xfs/xfs_error.c
@@ -22,6 +22,7 @@
#include "xfs_inum.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
+#include "xfs_ag.h"
#include "xfs_dir2.h"
#include "xfs_dmapi.h"
#include "xfs_mount.h"
@@ -132,10 +133,14 @@ xfs_errortag_add(int error_tag, xfs_mount_t *mp)
}
int
-xfs_errortag_clearall_umount(int64_t fsid, char *fsname, int loud)
+xfs_errortag_clearall(xfs_mount_t *mp, int loud)
{
- int i;
+ int64_t fsid;
int cleared = 0;
+ int i;
+
+ memcpy(&fsid, mp->m_fixedfsid, sizeof(xfs_fsid_t));
+
for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) {
if ((fsid == 0LL || xfs_etest_fsid[i] == fsid) &&
@@ -154,20 +159,10 @@ xfs_errortag_clearall_umount(int64_t fsid, char *fsname, int loud)
if (loud || cleared)
cmn_err(CE_WARN,
"Cleared all XFS error tags for filesystem \"%s\"",
- fsname);
+ mp->m_fsname);
return 0;
}
-
-int
-xfs_errortag_clearall(xfs_mount_t *mp)
-{
- int64_t fsid;
-
- memcpy(&fsid, mp->m_fixedfsid, sizeof(xfs_fsid_t));
-
- return xfs_errortag_clearall_umount(fsid, mp->m_fsname, 1);
-}
#endif /* DEBUG || INDUCE_IO_ERROR */
static void
diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h
index 5599ada456a1..10e9d9619ae5 100644
--- a/fs/xfs/xfs_error.h
+++ b/fs/xfs/xfs_error.h
@@ -144,12 +144,11 @@ extern void xfs_error_test_init(void);
#endif /* __ANSI_CPP__ */
extern int xfs_errortag_add(int error_tag, xfs_mount_t *mp);
-extern int xfs_errortag_clearall(xfs_mount_t *mp);
-extern int xfs_errortag_clearall_umount(int64_t fsid, char *fsname, int loud);
+extern int xfs_errortag_clearall(xfs_mount_t *mp, int loud);
#else
#define XFS_TEST_ERROR(expr, mp, tag, rf) (expr)
#define xfs_errortag_add(tag, mp) (ENOSYS)
-#define xfs_errortag_clearall(mp) (ENOSYS)
+#define xfs_errortag_clearall(mp, loud) (ENOSYS)
#endif /* (DEBUG || INDUCE_IO_ERROR) */
/*
diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c
index 3b14427ee123..f938a51be81b 100644
--- a/fs/xfs/xfs_extfree_item.c
+++ b/fs/xfs/xfs_extfree_item.c
@@ -23,6 +23,7 @@
#include "xfs_trans.h"
#include "xfs_buf_item.h"
#include "xfs_sb.h"
+#include "xfs_ag.h"
#include "xfs_dmapi.h"
#include "xfs_mount.h"
#include "xfs_trans_priv.h"
diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h
index ec3c9c27e0de..aab966276517 100644
--- a/fs/xfs/xfs_fs.h
+++ b/fs/xfs/xfs_fs.h
@@ -389,30 +389,13 @@ typedef struct xfs_fsop_attrmulti_handlereq {
*/
typedef struct { __u32 val[2]; } xfs_fsid_t; /* file system id type */
-
-#ifndef HAVE_FID
-#define MAXFIDSZ 46
-
-typedef struct fid {
- __u16 fid_len; /* length of data in bytes */
- unsigned char fid_data[MAXFIDSZ]; /* data (fid_len worth) */
-} fid_t;
-#endif
-
typedef struct xfs_fid {
- __u16 xfs_fid_len; /* length of remainder */
- __u16 xfs_fid_pad;
- __u32 xfs_fid_gen; /* generation number */
- __u64 xfs_fid_ino; /* 64 bits inode number */
+ __u16 fid_len; /* length of remainder */
+ __u16 fid_pad;
+ __u32 fid_gen; /* generation number */
+ __u64 fid_ino; /* 64 bits inode number */
} xfs_fid_t;
-typedef struct xfs_fid2 {
- __u16 fid_len; /* length of remainder */
- __u16 fid_pad; /* padding, must be zero */
- __u32 fid_gen; /* generation number */
- __u64 fid_ino; /* inode number */
-} xfs_fid2_t;
-
typedef struct xfs_handle {
union {
__s64 align; /* force alignment of ha_fid */
@@ -422,9 +405,9 @@ typedef struct xfs_handle {
} xfs_handle_t;
#define ha_fsid ha_u._ha_fsid
-#define XFS_HSIZE(handle) (((char *) &(handle).ha_fid.xfs_fid_pad \
+#define XFS_HSIZE(handle) (((char *) &(handle).ha_fid.fid_pad \
- (char *) &(handle)) \
- + (handle).ha_fid.xfs_fid_len)
+ + (handle).ha_fid.fid_len)
/*
* Flags for going down operation
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index 432e82347ed6..c92d5b821029 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -136,7 +136,6 @@ xfs_growfs_data_private(
xfs_rfsblock_t nfree;
xfs_agnumber_t oagcount;
int pct;
- xfs_sb_t *sbp;
xfs_trans_t *tp;
nb = in->newblocks;
@@ -175,7 +174,7 @@ xfs_growfs_data_private(
memset(&mp->m_perag[oagcount], 0,
(nagcount - oagcount) * sizeof(xfs_perag_t));
mp->m_flags |= XFS_MOUNT_32BITINODES;
- nagimax = xfs_initialize_perag(XFS_MTOVFS(mp), mp, nagcount);
+ nagimax = xfs_initialize_perag(mp, nagcount);
up_write(&mp->m_peraglock);
}
tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFS);
@@ -377,8 +376,7 @@ xfs_growfs_data_private(
error, agno);
break;
}
- sbp = XFS_BUF_TO_SBP(bp);
- xfs_xlatesb(sbp, &mp->m_sb, -1, XFS_SB_ALL_BITS);
+ xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb, XFS_SB_ALL_BITS);
/*
* If we get an error writing out the alternate superblocks,
* just issue a warning and continue. The real work is
@@ -435,10 +433,10 @@ xfs_growfs_data(
xfs_growfs_data_t *in)
{
int error;
- if (!cpsema(&mp->m_growlock))
+ if (!mutex_trylock(&mp->m_growlock))
return XFS_ERROR(EWOULDBLOCK);
error = xfs_growfs_data_private(mp, in);
- vsema(&mp->m_growlock);
+ mutex_unlock(&mp->m_growlock);
return error;
}
@@ -448,10 +446,10 @@ xfs_growfs_log(
xfs_growfs_log_t *in)
{
int error;
- if (!cpsema(&mp->m_growlock))
+ if (!mutex_trylock(&mp->m_growlock))
return XFS_ERROR(EWOULDBLOCK);
error = xfs_growfs_log_private(mp, in);
- vsema(&mp->m_growlock);
+ mutex_unlock(&mp->m_growlock);
return error;
}
@@ -628,8 +626,7 @@ xfs_fs_goingdown(
{
switch (inflags) {
case XFS_FSOP_GOING_FLAGS_DEFAULT: {
- struct bhv_vfs *vfsp = XFS_MTOVFS(mp);
- struct super_block *sb = freeze_bdev(vfsp->vfs_super->s_bdev);
+ struct super_block *sb = freeze_bdev(mp->m_super->s_bdev);
if (sb && !IS_ERR(sb)) {
xfs_force_shutdown(mp, SHUTDOWN_FORCE_UMOUNT);
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
index f943368c9b93..1409c2d61c11 100644
--- a/fs/xfs/xfs_ialloc.c
+++ b/fs/xfs/xfs_ialloc.c
@@ -293,9 +293,9 @@ xfs_ialloc_ag_alloc(
xfs_biozero(fbuf, 0, ninodes << args.mp->m_sb.sb_inodelog);
for (i = 0; i < ninodes; i++) {
free = XFS_MAKE_IPTR(args.mp, fbuf, i);
- INT_SET(free->di_core.di_magic, ARCH_CONVERT, XFS_DINODE_MAGIC);
- INT_SET(free->di_core.di_version, ARCH_CONVERT, version);
- INT_SET(free->di_next_unlinked, ARCH_CONVERT, NULLAGINO);
+ free->di_core.di_magic = cpu_to_be16(XFS_DINODE_MAGIC);
+ free->di_core.di_version = version;
+ free->di_next_unlinked = cpu_to_be32(NULLAGINO);
xfs_ialloc_log_di(tp, fbuf, i,
XFS_DI_CORE_BITS | XFS_DI_NEXT_UNLINKED);
}
diff --git a/fs/xfs/xfs_ialloc.h b/fs/xfs/xfs_ialloc.h
index 97f4040931ca..4e30ec1d13bc 100644
--- a/fs/xfs/xfs_ialloc.h
+++ b/fs/xfs/xfs_ialloc.h
@@ -30,14 +30,9 @@ struct xfs_trans;
#define XFS_IALLOC_BLOCKS(mp) (mp)->m_ialloc_blks
/*
- * For small block file systems, move inodes in clusters of this size.
- * When we don't have a lot of memory, however, we go a bit smaller
- * to reduce the number of AGI and ialloc btree blocks we need to keep
- * around for xfs_dilocate(). We choose which one to use in
- * xfs_mount_int().
+ * Move inodes in clusters of this size.
*/
#define XFS_INODE_BIG_CLUSTER_SIZE 8192
-#define XFS_INODE_SMALL_CLUSTER_SIZE 4096
#define XFS_INODE_CLUSTER_SIZE(mp) (mp)->m_inode_cluster_size
/*
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index 114433a22baa..488836e204a3 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -40,131 +40,13 @@
#include "xfs_utils.h"
/*
- * Initialize the inode hash table for the newly mounted file system.
- * Choose an initial table size based on user specified value, else
- * use a simple algorithm using the maximum number of inodes as an
- * indicator for table size, and clamp it between one and some large
- * number of pages.
- */
-void
-xfs_ihash_init(xfs_mount_t *mp)
-{
- __uint64_t icount;
- uint i;
-
- if (!mp->m_ihsize) {
- icount = mp->m_maxicount ? mp->m_maxicount :
- (mp->m_sb.sb_dblocks << mp->m_sb.sb_inopblog);
- mp->m_ihsize = 1 << max_t(uint, 8,
- (xfs_highbit64(icount) + 1) / 2);
- mp->m_ihsize = min_t(uint, mp->m_ihsize,
- (64 * NBPP) / sizeof(xfs_ihash_t));
- }
-
- mp->m_ihash = kmem_zalloc_greedy(&mp->m_ihsize,
- NBPC * sizeof(xfs_ihash_t),
- mp->m_ihsize * sizeof(xfs_ihash_t),
- KM_SLEEP | KM_MAYFAIL | KM_LARGE);
- mp->m_ihsize /= sizeof(xfs_ihash_t);
- for (i = 0; i < mp->m_ihsize; i++)
- rwlock_init(&(mp->m_ihash[i].ih_lock));
-}
-
-/*
- * Free up structures allocated by xfs_ihash_init, at unmount time.
- */
-void
-xfs_ihash_free(xfs_mount_t *mp)
-{
- kmem_free(mp->m_ihash, mp->m_ihsize * sizeof(xfs_ihash_t));
- mp->m_ihash = NULL;
-}
-
-/*
- * Initialize the inode cluster hash table for the newly mounted file system.
- * Its size is derived from the ihash table size.
- */
-void
-xfs_chash_init(xfs_mount_t *mp)
-{
- uint i;
-
- mp->m_chsize = max_t(uint, 1, mp->m_ihsize /
- (XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog));
- mp->m_chsize = min_t(uint, mp->m_chsize, mp->m_ihsize);
- mp->m_chash = (xfs_chash_t *)kmem_zalloc(mp->m_chsize
- * sizeof(xfs_chash_t),
- KM_SLEEP | KM_LARGE);
- for (i = 0; i < mp->m_chsize; i++) {
- spinlock_init(&mp->m_chash[i].ch_lock,"xfshash");
- }
-}
-
-/*
- * Free up structures allocated by xfs_chash_init, at unmount time.
- */
-void
-xfs_chash_free(xfs_mount_t *mp)
-{
- int i;
-
- for (i = 0; i < mp->m_chsize; i++) {
- spinlock_destroy(&mp->m_chash[i].ch_lock);
- }
-
- kmem_free(mp->m_chash, mp->m_chsize*sizeof(xfs_chash_t));
- mp->m_chash = NULL;
-}
-
-/*
- * Try to move an inode to the front of its hash list if possible
- * (and if its not there already). Called right after obtaining
- * the list version number and then dropping the read_lock on the
- * hash list in question (which is done right after looking up the
- * inode in question...).
- */
-STATIC void
-xfs_ihash_promote(
- xfs_ihash_t *ih,
- xfs_inode_t *ip,
- ulong version)
-{
- xfs_inode_t *iq;
-
- if ((ip->i_prevp != &ih->ih_next) && write_trylock(&ih->ih_lock)) {
- if (likely(version == ih->ih_version)) {
- /* remove from list */
- if ((iq = ip->i_next)) {
- iq->i_prevp = ip->i_prevp;
- }
- *ip->i_prevp = iq;
-
- /* insert at list head */
- iq = ih->ih_next;
- iq->i_prevp = &ip->i_next;
- ip->i_next = iq;
- ip->i_prevp = &ih->ih_next;
- ih->ih_next = ip;
- }
- write_unlock(&ih->ih_lock);
- }
-}
-
-/*
* Look up an inode by number in the given file system.
- * The inode is looked up in the hash table for the file system
- * represented by the mount point parameter mp. Each bucket of
- * the hash table is guarded by an individual semaphore.
- *
- * If the inode is found in the hash table, its corresponding vnode
- * is obtained with a call to vn_get(). This call takes care of
- * coordination with the reclamation of the inode and vnode. Note
- * that the vmap structure is filled in while holding the hash lock.
- * This gives us the state of the inode/vnode when we found it and
- * is used for coordination in vn_get().
+ * The inode is looked up in the cache held in each AG.
+ * If the inode is found in the cache, attach it to the provided
+ * vnode.
*
- * If it is not in core, read it in from the file system's device and
- * add the inode into the hash table.
+ * If it is not in core, read it in from the file system's device,
+ * add it to the cache and attach the provided vnode.
*
* The inode is locked according to the value of the lock_flags parameter.
* This flag parameter indicates how and if the inode's IO lock and inode lock
@@ -192,274 +74,241 @@ xfs_iget_core(
xfs_inode_t **ipp,
xfs_daddr_t bno)
{
- xfs_ihash_t *ih;
xfs_inode_t *ip;
xfs_inode_t *iq;
bhv_vnode_t *inode_vp;
- ulong version;
int error;
- /* REFERENCED */
- xfs_chash_t *ch;
- xfs_chashlist_t *chl, *chlnew;
- SPLDECL(s);
+ xfs_icluster_t *icl, *new_icl = NULL;
+ unsigned long first_index, mask;
+ xfs_perag_t *pag;
+ xfs_agino_t agino;
+
+ /* the radix tree exists only in inode capable AGs */
+ if (XFS_INO_TO_AGNO(mp, ino) >= mp->m_maxagi)
+ return EINVAL;
+
+ /* get the perag structure and ensure that it's inode capable */
+ pag = xfs_get_perag(mp, ino);
+ if (!pag->pagi_inodeok)
+ return EINVAL;
+ ASSERT(pag->pag_ici_init);
+ agino = XFS_INO_TO_AGINO(mp, ino);
+again:
+ read_lock(&pag->pag_ici_lock);
+ ip = radix_tree_lookup(&pag->pag_ici_root, agino);
- ih = XFS_IHASH(mp, ino);
+ if (ip != NULL) {
+ /*
+ * If INEW is set this inode is being set up
+ * we need to pause and try again.
+ */
+ if (xfs_iflags_test(ip, XFS_INEW)) {
+ read_unlock(&pag->pag_ici_lock);
+ delay(1);
+ XFS_STATS_INC(xs_ig_frecycle);
-again:
- read_lock(&ih->ih_lock);
+ goto again;
+ }
- for (ip = ih->ih_next; ip != NULL; ip = ip->i_next) {
- if (ip->i_ino == ino) {
+ inode_vp = XFS_ITOV_NULL(ip);
+ if (inode_vp == NULL) {
/*
- * If INEW is set this inode is being set up
+ * If IRECLAIM is set this inode is
+ * on its way out of the system,
* we need to pause and try again.
*/
- if (xfs_iflags_test(ip, XFS_INEW)) {
- read_unlock(&ih->ih_lock);
+ if (xfs_iflags_test(ip, XFS_IRECLAIM)) {
+ read_unlock(&pag->pag_ici_lock);
delay(1);
XFS_STATS_INC(xs_ig_frecycle);
goto again;
}
+ ASSERT(xfs_iflags_test(ip, XFS_IRECLAIMABLE));
- inode_vp = XFS_ITOV_NULL(ip);
- if (inode_vp == NULL) {
- /*
- * If IRECLAIM is set this inode is
- * on its way out of the system,
- * we need to pause and try again.
- */
- if (xfs_iflags_test(ip, XFS_IRECLAIM)) {
- read_unlock(&ih->ih_lock);
- delay(1);
- XFS_STATS_INC(xs_ig_frecycle);
-
- goto again;
- }
- ASSERT(xfs_iflags_test(ip, XFS_IRECLAIMABLE));
-
- /*
- * If lookup is racing with unlink, then we
- * should return an error immediately so we
- * don't remove it from the reclaim list and
- * potentially leak the inode.
- */
- if ((ip->i_d.di_mode == 0) &&
- !(flags & XFS_IGET_CREATE)) {
- read_unlock(&ih->ih_lock);
- return ENOENT;
- }
-
- /*
- * There may be transactions sitting in the
- * incore log buffers or being flushed to disk
- * at this time. We can't clear the
- * XFS_IRECLAIMABLE flag until these
- * transactions have hit the disk, otherwise we
- * will void the guarantee the flag provides
- * xfs_iunpin()
- */
- if (xfs_ipincount(ip)) {
- read_unlock(&ih->ih_lock);
- xfs_log_force(mp, 0,
- XFS_LOG_FORCE|XFS_LOG_SYNC);
- XFS_STATS_INC(xs_ig_frecycle);
- goto again;
- }
-
- vn_trace_exit(vp, "xfs_iget.alloc",
- (inst_t *)__return_address);
+ /*
+ * If lookup is racing with unlink, then we
+ * should return an error immediately so we
+ * don't remove it from the reclaim list and
+ * potentially leak the inode.
+ */
+ if ((ip->i_d.di_mode == 0) &&
+ !(flags & XFS_IGET_CREATE)) {
+ read_unlock(&pag->pag_ici_lock);
+ xfs_put_perag(mp, pag);
+ return ENOENT;
+ }
+
+ /*
+ * There may be transactions sitting in the
+ * incore log buffers or being flushed to disk
+ * at this time. We can't clear the
+ * XFS_IRECLAIMABLE flag until these
+ * transactions have hit the disk, otherwise we
+ * will void the guarantee the flag provides
+ * xfs_iunpin()
+ */
+ if (xfs_ipincount(ip)) {
+ read_unlock(&pag->pag_ici_lock);
+ xfs_log_force(mp, 0,
+ XFS_LOG_FORCE|XFS_LOG_SYNC);
+ XFS_STATS_INC(xs_ig_frecycle);
+ goto again;
+ }
- XFS_STATS_INC(xs_ig_found);
+ vn_trace_exit(ip, "xfs_iget.alloc",
+ (inst_t *)__return_address);
- xfs_iflags_clear(ip, XFS_IRECLAIMABLE);
- version = ih->ih_version;
- read_unlock(&ih->ih_lock);
- xfs_ihash_promote(ih, ip, version);
+ XFS_STATS_INC(xs_ig_found);
- XFS_MOUNT_ILOCK(mp);
- list_del_init(&ip->i_reclaim);
- XFS_MOUNT_IUNLOCK(mp);
+ xfs_iflags_clear(ip, XFS_IRECLAIMABLE);
+ read_unlock(&pag->pag_ici_lock);
- goto finish_inode;
+ XFS_MOUNT_ILOCK(mp);
+ list_del_init(&ip->i_reclaim);
+ XFS_MOUNT_IUNLOCK(mp);
- } else if (vp != inode_vp) {
- struct inode *inode = vn_to_inode(inode_vp);
+ goto finish_inode;
- /* The inode is being torn down, pause and
- * try again.
- */
- if (inode->i_state & (I_FREEING | I_CLEAR)) {
- read_unlock(&ih->ih_lock);
- delay(1);
- XFS_STATS_INC(xs_ig_frecycle);
+ } else if (vp != inode_vp) {
+ struct inode *inode = vn_to_inode(inode_vp);
- goto again;
- }
-/* Chances are the other vnode (the one in the inode) is being torn
- * down right now, and we landed on top of it. Question is, what do
- * we do? Unhook the old inode and hook up the new one?
- */
- cmn_err(CE_PANIC,
- "xfs_iget_core: ambiguous vns: vp/0x%p, invp/0x%p",
- inode_vp, vp);
+ /* The inode is being torn down, pause and
+ * try again.
+ */
+ if (inode->i_state & (I_FREEING | I_CLEAR)) {
+ read_unlock(&pag->pag_ici_lock);
+ delay(1);
+ XFS_STATS_INC(xs_ig_frecycle);
+
+ goto again;
}
+/* Chances are the other vnode (the one in the inode) is being torn
+* down right now, and we landed on top of it. Question is, what do
+* we do? Unhook the old inode and hook up the new one?
+*/
+ cmn_err(CE_PANIC,
+ "xfs_iget_core: ambiguous vns: vp/0x%p, invp/0x%p",
+ inode_vp, vp);
+ }
- /*
- * Inode cache hit: if ip is not at the front of
- * its hash chain, move it there now.
- * Do this with the lock held for update, but
- * do statistics after releasing the lock.
- */
- version = ih->ih_version;
- read_unlock(&ih->ih_lock);
- xfs_ihash_promote(ih, ip, version);
- XFS_STATS_INC(xs_ig_found);
+ /*
+ * Inode cache hit
+ */
+ read_unlock(&pag->pag_ici_lock);
+ XFS_STATS_INC(xs_ig_found);
finish_inode:
- if (ip->i_d.di_mode == 0) {
- if (!(flags & XFS_IGET_CREATE))
- return ENOENT;
- xfs_iocore_inode_reinit(ip);
+ if (ip->i_d.di_mode == 0) {
+ if (!(flags & XFS_IGET_CREATE)) {
+ xfs_put_perag(mp, pag);
+ return ENOENT;
}
+ xfs_iocore_inode_reinit(ip);
+ }
- if (lock_flags != 0)
- xfs_ilock(ip, lock_flags);
+ if (lock_flags != 0)
+ xfs_ilock(ip, lock_flags);
- xfs_iflags_clear(ip, XFS_ISTALE);
- vn_trace_exit(vp, "xfs_iget.found",
- (inst_t *)__return_address);
- goto return_ip;
- }
+ xfs_iflags_clear(ip, XFS_ISTALE);
+ vn_trace_exit(ip, "xfs_iget.found",
+ (inst_t *)__return_address);
+ goto return_ip;
}
/*
- * Inode cache miss: save the hash chain version stamp and unlock
- * the chain, so we don't deadlock in vn_alloc.
+ * Inode cache miss
*/
+ read_unlock(&pag->pag_ici_lock);
XFS_STATS_INC(xs_ig_missed);
- version = ih->ih_version;
-
- read_unlock(&ih->ih_lock);
-
/*
* Read the disk inode attributes into a new inode structure and get
* a new vnode for it. This should also initialize i_ino and i_mount.
*/
error = xfs_iread(mp, tp, ino, &ip, bno,
(flags & XFS_IGET_BULKSTAT) ? XFS_IMAP_BULKSTAT : 0);
- if (error)
+ if (error) {
+ xfs_put_perag(mp, pag);
return error;
+ }
- vn_trace_exit(vp, "xfs_iget.alloc", (inst_t *)__return_address);
+ vn_trace_exit(ip, "xfs_iget.alloc", (inst_t *)__return_address);
xfs_inode_lock_init(ip, vp);
xfs_iocore_inode_init(ip);
-
if (lock_flags)
xfs_ilock(ip, lock_flags);
if ((ip->i_d.di_mode == 0) && !(flags & XFS_IGET_CREATE)) {
xfs_idestroy(ip);
+ xfs_put_perag(mp, pag);
return ENOENT;
}
/*
- * Put ip on its hash chain, unless someone else hashed a duplicate
- * after we released the hash lock.
+ * This is a bit messy - we preallocate everything we _might_
+ * need before we pick up the ici lock. That way we don't have to
+ * juggle locks and go all the way back to the start.
*/
- write_lock(&ih->ih_lock);
+ new_icl = kmem_zone_alloc(xfs_icluster_zone, KM_SLEEP);
+ if (radix_tree_preload(GFP_KERNEL)) {
+ delay(1);
+ goto again;
+ }
+ mask = ~(((XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog)) - 1);
+ first_index = agino & mask;
+ write_lock(&pag->pag_ici_lock);
- if (ih->ih_version != version) {
- for (iq = ih->ih_next; iq != NULL; iq = iq->i_next) {
- if (iq->i_ino == ino) {
- write_unlock(&ih->ih_lock);
- xfs_idestroy(ip);
+ /*
+ * Find the cluster if it exists
+ */
+ icl = NULL;
+ if (radix_tree_gang_lookup(&pag->pag_ici_root, (void**)&iq,
+ first_index, 1)) {
+ if ((iq->i_ino & mask) == first_index)
+ icl = iq->i_cluster;
+ }
- XFS_STATS_INC(xs_ig_dup);
- goto again;
- }
- }
+ /*
+ * insert the new inode
+ */
+ error = radix_tree_insert(&pag->pag_ici_root, agino, ip);
+ if (unlikely(error)) {
+ BUG_ON(error != -EEXIST);
+ write_unlock(&pag->pag_ici_lock);
+ radix_tree_preload_end();
+ xfs_idestroy(ip);
+ XFS_STATS_INC(xs_ig_dup);
+ goto again;
}
/*
* These values _must_ be set before releasing ihlock!
*/
- ip->i_hash = ih;
- if ((iq = ih->ih_next)) {
- iq->i_prevp = &ip->i_next;
- }
- ip->i_next = iq;
- ip->i_prevp = &ih->ih_next;
- ih->ih_next = ip;
ip->i_udquot = ip->i_gdquot = NULL;
- ih->ih_version++;
xfs_iflags_set(ip, XFS_INEW);
- write_unlock(&ih->ih_lock);
- /*
- * put ip on its cluster's hash chain
- */
- ASSERT(ip->i_chash == NULL && ip->i_cprev == NULL &&
- ip->i_cnext == NULL);
-
- chlnew = NULL;
- ch = XFS_CHASH(mp, ip->i_blkno);
- chlredo:
- s = mutex_spinlock(&ch->ch_lock);
- for (chl = ch->ch_list; chl != NULL; chl = chl->chl_next) {
- if (chl->chl_blkno == ip->i_blkno) {
-
- /* insert this inode into the doubly-linked list
- * where chl points */
- if ((iq = chl->chl_ip)) {
- ip->i_cprev = iq->i_cprev;
- iq->i_cprev->i_cnext = ip;
- iq->i_cprev = ip;
- ip->i_cnext = iq;
- } else {
- ip->i_cnext = ip;
- ip->i_cprev = ip;
- }
- chl->chl_ip = ip;
- ip->i_chash = chl;
- break;
- }
- }
+ ASSERT(ip->i_cluster == NULL);
- /* no hash list found for this block; add a new hash list */
- if (chl == NULL) {
- if (chlnew == NULL) {
- mutex_spinunlock(&ch->ch_lock, s);
- ASSERT(xfs_chashlist_zone != NULL);
- chlnew = (xfs_chashlist_t *)
- kmem_zone_alloc(xfs_chashlist_zone,
- KM_SLEEP);
- ASSERT(chlnew != NULL);
- goto chlredo;
- } else {
- ip->i_cnext = ip;
- ip->i_cprev = ip;
- ip->i_chash = chlnew;
- chlnew->chl_ip = ip;
- chlnew->chl_blkno = ip->i_blkno;
- if (ch->ch_list)
- ch->ch_list->chl_prev = chlnew;
- chlnew->chl_next = ch->ch_list;
- chlnew->chl_prev = NULL;
- ch->ch_list = chlnew;
- chlnew = NULL;
- }
+ if (!icl) {
+ spin_lock_init(&new_icl->icl_lock);
+ INIT_HLIST_HEAD(&new_icl->icl_inodes);
+ icl = new_icl;
+ new_icl = NULL;
} else {
- if (chlnew != NULL) {
- kmem_zone_free(xfs_chashlist_zone, chlnew);
- }
+ ASSERT(!hlist_empty(&icl->icl_inodes));
}
+ spin_lock(&icl->icl_lock);
+ hlist_add_head(&ip->i_cnode, &icl->icl_inodes);
+ ip->i_cluster = icl;
+ spin_unlock(&icl->icl_lock);
- mutex_spinunlock(&ch->ch_lock, s);
-
+ write_unlock(&pag->pag_ici_lock);
+ radix_tree_preload_end();
+ if (new_icl)
+ kmem_zone_free(xfs_icluster_zone, new_icl);
/*
* Link ip to its mount and thread it on the mount's inode list.
@@ -478,6 +327,7 @@ finish_inode:
mp->m_inodes = ip;
XFS_MOUNT_IUNLOCK(mp);
+ xfs_put_perag(mp, pag);
return_ip:
ASSERT(ip->i_df.if_ext_max ==
@@ -486,14 +336,14 @@ finish_inode:
ASSERT(((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) != 0) ==
((ip->i_iocore.io_flags & XFS_IOCORE_RT) != 0));
+ xfs_iflags_set(ip, XFS_IMODIFIED);
*ipp = ip;
/*
* If we have a real type for an on-disk inode, we can set ops(&unlock)
* now. If it's a new inode being created, xfs_ialloc will handle it.
*/
- bhv_vfs_init_vnode(XFS_MTOVFS(mp), vp, XFS_ITOBHV(ip), 1);
-
+ xfs_initialize_vnode(mp, vp, ip);
return 0;
}
@@ -519,7 +369,8 @@ xfs_iget(
XFS_STATS_INC(xs_ig_attempts);
retry:
- if ((inode = iget_locked(XFS_MTOVFS(mp)->vfs_super, ino))) {
+ inode = iget_locked(mp->m_super, ino);
+ if (inode) {
xfs_inode_t *ip;
vp = vn_from_inode(inode);
@@ -570,8 +421,8 @@ xfs_inode_lock_init(
bhv_vnode_t *vp)
{
mrlock_init(&ip->i_lock, MRLOCK_ALLOW_EQUAL_PRI|MRLOCK_BARRIER,
- "xfsino", (long)vp->v_number);
- mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", vp->v_number);
+ "xfsino", ip->i_ino);
+ mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino);
init_waitqueue_head(&ip->i_ipin_wait);
atomic_set(&ip->i_pincount, 0);
initnsema(&ip->i_flock, 1, "xfsfino");
@@ -587,32 +438,19 @@ xfs_inode_incore(xfs_mount_t *mp,
xfs_ino_t ino,
xfs_trans_t *tp)
{
- xfs_ihash_t *ih;
xfs_inode_t *ip;
- ulong version;
-
- ih = XFS_IHASH(mp, ino);
- read_lock(&ih->ih_lock);
- for (ip = ih->ih_next; ip != NULL; ip = ip->i_next) {
- if (ip->i_ino == ino) {
- /*
- * If we find it and tp matches, return it.
- * Also move it to the front of the hash list
- * if we find it and it is not already there.
- * Otherwise break from the loop and return
- * NULL.
- */
- if (ip->i_transp == tp) {
- version = ih->ih_version;
- read_unlock(&ih->ih_lock);
- xfs_ihash_promote(ih, ip, version);
- return (ip);
- }
- break;
- }
- }
- read_unlock(&ih->ih_lock);
- return (NULL);
+ xfs_perag_t *pag;
+
+ pag = xfs_get_perag(mp, ino);
+ read_lock(&pag->pag_ici_lock);
+ ip = radix_tree_lookup(&pag->pag_ici_root, XFS_INO_TO_AGINO(mp, ino));
+ read_unlock(&pag->pag_ici_lock);
+ xfs_put_perag(mp, pag);
+
+ /* the returned inode must match the transaction */
+ if (ip && (ip->i_transp != tp))
+ return NULL;
+ return ip;
}
/*
@@ -629,7 +467,7 @@ xfs_iput(xfs_inode_t *ip,
{
bhv_vnode_t *vp = XFS_ITOV(ip);
- vn_trace_entry(vp, "xfs_iput", (inst_t *)__return_address);
+ vn_trace_entry(ip, "xfs_iput", (inst_t *)__return_address);
xfs_iunlock(ip, lock_flags);
VN_RELE(vp);
}
@@ -644,7 +482,7 @@ xfs_iput_new(xfs_inode_t *ip,
bhv_vnode_t *vp = XFS_ITOV(ip);
struct inode *inode = vn_to_inode(vp);
- vn_trace_entry(vp, "xfs_iput_new", (inst_t *)__return_address);
+ vn_trace_entry(ip, "xfs_iput_new", (inst_t *)__return_address);
if ((ip->i_d.di_mode == 0)) {
ASSERT(!xfs_iflags_test(ip, XFS_IRECLAIMABLE));
@@ -699,7 +537,8 @@ xfs_ireclaim(xfs_inode_t *ip)
*/
vp = XFS_ITOV_NULL(ip);
if (vp) {
- vn_bhv_remove(VN_BHV_HEAD(vp), XFS_ITOBHV(ip));
+ vn_to_inode(vp)->i_private = NULL;
+ ip->i_vnode = NULL;
}
/*
@@ -718,58 +557,26 @@ void
xfs_iextract(
xfs_inode_t *ip)
{
- xfs_ihash_t *ih;
+ xfs_mount_t *mp = ip->i_mount;
+ xfs_perag_t *pag = xfs_get_perag(mp, ip->i_ino);
xfs_inode_t *iq;
- xfs_mount_t *mp;
- xfs_chash_t *ch;
- xfs_chashlist_t *chl, *chm;
- SPLDECL(s);
-
- ih = ip->i_hash;
- write_lock(&ih->ih_lock);
- if ((iq = ip->i_next)) {
- iq->i_prevp = ip->i_prevp;
- }
- *ip->i_prevp = iq;
- ih->ih_version++;
- write_unlock(&ih->ih_lock);
+
+ write_lock(&pag->pag_ici_lock);
+ radix_tree_delete(&pag->pag_ici_root, XFS_INO_TO_AGINO(mp, ip->i_ino));
+ write_unlock(&pag->pag_ici_lock);
+ xfs_put_perag(mp, pag);
/*
- * Remove from cluster hash list
- * 1) delete the chashlist if this is the last inode on the chashlist
- * 2) unchain from list of inodes
- * 3) point chashlist->chl_ip to 'chl_next' if to this inode.
+ * Remove from cluster list
*/
mp = ip->i_mount;
- ch = XFS_CHASH(mp, ip->i_blkno);
- s = mutex_spinlock(&ch->ch_lock);
-
- if (ip->i_cnext == ip) {
- /* Last inode on chashlist */
- ASSERT(ip->i_cnext == ip && ip->i_cprev == ip);
- ASSERT(ip->i_chash != NULL);
- chm=NULL;
- chl = ip->i_chash;
- if (chl->chl_prev)
- chl->chl_prev->chl_next = chl->chl_next;
- else
- ch->ch_list = chl->chl_next;
- if (chl->chl_next)
- chl->chl_next->chl_prev = chl->chl_prev;
- kmem_zone_free(xfs_chashlist_zone, chl);
- } else {
- /* delete one inode from a non-empty list */
- iq = ip->i_cnext;
- iq->i_cprev = ip->i_cprev;
- ip->i_cprev->i_cnext = iq;
- if (ip->i_chash->chl_ip == ip) {
- ip->i_chash->chl_ip = iq;
- }
- ip->i_chash = __return_address;
- ip->i_cprev = __return_address;
- ip->i_cnext = __return_address;
- }
- mutex_spinunlock(&ch->ch_lock, s);
+ spin_lock(&ip->i_cluster->icl_lock);
+ hlist_del(&ip->i_cnode);
+ spin_unlock(&ip->i_cluster->icl_lock);
+
+ /* was last inode in cluster? */
+ if (hlist_empty(&ip->i_cluster->icl_inodes))
+ kmem_zone_free(xfs_icluster_zone, ip->i_cluster);
/*
* Remove from mount's inode list.
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index cdc4c28926d0..abf509a88915 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -49,12 +49,11 @@
#include "xfs_quota.h"
#include "xfs_acl.h"
#include "xfs_filestream.h"
-
-#include <linux/log2.h>
+#include "xfs_vnodeops.h"
kmem_zone_t *xfs_ifork_zone;
kmem_zone_t *xfs_inode_zone;
-kmem_zone_t *xfs_chashlist_zone;
+kmem_zone_t *xfs_icluster_zone;
/*
* Used in xfs_itruncate(). This is the maximum number of extents
@@ -67,7 +66,6 @@ STATIC int xfs_iformat_local(xfs_inode_t *, xfs_dinode_t *, int, int);
STATIC int xfs_iformat_extents(xfs_inode_t *, xfs_dinode_t *, int);
STATIC int xfs_iformat_btree(xfs_inode_t *, xfs_dinode_t *, int);
-
#ifdef DEBUG
/*
* Make sure that the extents in the given memory buffer
@@ -77,28 +75,23 @@ STATIC void
xfs_validate_extents(
xfs_ifork_t *ifp,
int nrecs,
- int disk,
xfs_exntfmt_t fmt)
{
- xfs_bmbt_rec_t *ep;
xfs_bmbt_irec_t irec;
- xfs_bmbt_rec_t rec;
+ xfs_bmbt_rec_host_t rec;
int i;
for (i = 0; i < nrecs; i++) {
- ep = xfs_iext_get_ext(ifp, i);
- rec.l0 = get_unaligned((__uint64_t*)&ep->l0);
- rec.l1 = get_unaligned((__uint64_t*)&ep->l1);
- if (disk)
- xfs_bmbt_disk_get_all(&rec, &irec);
- else
- xfs_bmbt_get_all(&rec, &irec);
+ xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, i);
+ rec.l0 = get_unaligned(&ep->l0);
+ rec.l1 = get_unaligned(&ep->l1);
+ xfs_bmbt_get_all(&rec, &irec);
if (fmt == XFS_EXTFMT_NOSTATE)
ASSERT(irec.br_state == XFS_EXT_NORM);
}
}
#else /* DEBUG */
-#define xfs_validate_extents(ifp, nrecs, disk, fmt)
+#define xfs_validate_extents(ifp, nrecs, fmt)
#endif /* DEBUG */
/*
@@ -201,8 +194,8 @@ xfs_inotobp(
}
dip = (xfs_dinode_t *)xfs_buf_offset(bp, 0);
di_ok =
- INT_GET(dip->di_core.di_magic, ARCH_CONVERT) == XFS_DINODE_MAGIC &&
- XFS_DINODE_GOOD_VERSION(INT_GET(dip->di_core.di_version, ARCH_CONVERT));
+ be16_to_cpu(dip->di_core.di_magic) == XFS_DINODE_MAGIC &&
+ XFS_DINODE_GOOD_VERSION(dip->di_core.di_version);
if (unlikely(XFS_TEST_ERROR(!di_ok, mp, XFS_ERRTAG_ITOBP_INOTOBP,
XFS_RANDOM_ITOBP_INOTOBP))) {
XFS_CORRUPTION_ERROR("xfs_inotobp", XFS_ERRLEVEL_LOW, mp, dip);
@@ -346,8 +339,8 @@ xfs_itobp(
dip = (xfs_dinode_t *)xfs_buf_offset(bp,
(i << mp->m_sb.sb_inodelog));
- di_ok = INT_GET(dip->di_core.di_magic, ARCH_CONVERT) == XFS_DINODE_MAGIC &&
- XFS_DINODE_GOOD_VERSION(INT_GET(dip->di_core.di_version, ARCH_CONVERT));
+ di_ok = be16_to_cpu(dip->di_core.di_magic) == XFS_DINODE_MAGIC &&
+ XFS_DINODE_GOOD_VERSION(dip->di_core.di_version);
if (unlikely(XFS_TEST_ERROR(!di_ok, mp,
XFS_ERRTAG_ITOBP_INOTOBP,
XFS_RANDOM_ITOBP_INOTOBP))) {
@@ -361,7 +354,7 @@ xfs_itobp(
"daddr %lld #%d (magic=%x)",
XFS_BUFTARG_NAME(mp->m_ddev_targp),
(unsigned long long)imap.im_blkno, i,
- INT_GET(dip->di_core.di_magic, ARCH_CONVERT));
+ be16_to_cpu(dip->di_core.di_magic));
#endif
XFS_CORRUPTION_ERROR("xfs_itobp", XFS_ERRLEVEL_HIGH,
mp, dip);
@@ -407,27 +400,26 @@ xfs_iformat(
XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
error = 0;
- if (unlikely(
- INT_GET(dip->di_core.di_nextents, ARCH_CONVERT) +
- INT_GET(dip->di_core.di_anextents, ARCH_CONVERT) >
- INT_GET(dip->di_core.di_nblocks, ARCH_CONVERT))) {
+ if (unlikely(be32_to_cpu(dip->di_core.di_nextents) +
+ be16_to_cpu(dip->di_core.di_anextents) >
+ be64_to_cpu(dip->di_core.di_nblocks))) {
xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
"corrupt dinode %Lu, extent total = %d, nblocks = %Lu.",
(unsigned long long)ip->i_ino,
- (int)(INT_GET(dip->di_core.di_nextents, ARCH_CONVERT)
- + INT_GET(dip->di_core.di_anextents, ARCH_CONVERT)),
+ (int)(be32_to_cpu(dip->di_core.di_nextents) +
+ be16_to_cpu(dip->di_core.di_anextents)),
(unsigned long long)
- INT_GET(dip->di_core.di_nblocks, ARCH_CONVERT));
+ be64_to_cpu(dip->di_core.di_nblocks));
XFS_CORRUPTION_ERROR("xfs_iformat(1)", XFS_ERRLEVEL_LOW,
ip->i_mount, dip);
return XFS_ERROR(EFSCORRUPTED);
}
- if (unlikely(INT_GET(dip->di_core.di_forkoff, ARCH_CONVERT) > ip->i_mount->m_sb.sb_inodesize)) {
+ if (unlikely(dip->di_core.di_forkoff > ip->i_mount->m_sb.sb_inodesize)) {
xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
"corrupt dinode %Lu, forkoff = 0x%x.",
(unsigned long long)ip->i_ino,
- (int)(INT_GET(dip->di_core.di_forkoff, ARCH_CONVERT)));
+ dip->di_core.di_forkoff);
XFS_CORRUPTION_ERROR("xfs_iformat(2)", XFS_ERRLEVEL_LOW,
ip->i_mount, dip);
return XFS_ERROR(EFSCORRUPTED);
@@ -438,25 +430,25 @@ xfs_iformat(
case S_IFCHR:
case S_IFBLK:
case S_IFSOCK:
- if (unlikely(INT_GET(dip->di_core.di_format, ARCH_CONVERT) != XFS_DINODE_FMT_DEV)) {
+ if (unlikely(dip->di_core.di_format != XFS_DINODE_FMT_DEV)) {
XFS_CORRUPTION_ERROR("xfs_iformat(3)", XFS_ERRLEVEL_LOW,
ip->i_mount, dip);
return XFS_ERROR(EFSCORRUPTED);
}
ip->i_d.di_size = 0;
ip->i_size = 0;
- ip->i_df.if_u2.if_rdev = INT_GET(dip->di_u.di_dev, ARCH_CONVERT);
+ ip->i_df.if_u2.if_rdev = be32_to_cpu(dip->di_u.di_dev);
break;
case S_IFREG:
case S_IFLNK:
case S_IFDIR:
- switch (INT_GET(dip->di_core.di_format, ARCH_CONVERT)) {
+ switch (dip->di_core.di_format) {
case XFS_DINODE_FMT_LOCAL:
/*
* no local regular files yet
*/
- if (unlikely((INT_GET(dip->di_core.di_mode, ARCH_CONVERT) & S_IFMT) == S_IFREG)) {
+ if (unlikely((be16_to_cpu(dip->di_core.di_mode) & S_IFMT) == S_IFREG)) {
xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
"corrupt inode %Lu "
"(local format for regular file).",
@@ -467,7 +459,7 @@ xfs_iformat(
return XFS_ERROR(EFSCORRUPTED);
}
- di_size = INT_GET(dip->di_core.di_size, ARCH_CONVERT);
+ di_size = be64_to_cpu(dip->di_core.di_size);
if (unlikely(di_size > XFS_DFORK_DSIZE(dip, ip->i_mount))) {
xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
"corrupt inode %Lu "
@@ -509,7 +501,7 @@ xfs_iformat(
ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_SLEEP);
ip->i_afp->if_ext_max =
XFS_IFORK_ASIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
- switch (INT_GET(dip->di_core.di_aformat, ARCH_CONVERT)) {
+ switch (dip->di_core.di_aformat) {
case XFS_DINODE_FMT_LOCAL:
atp = (xfs_attr_shortform_t *)XFS_DFORK_APTR(dip);
size = be16_to_cpu(atp->hdr.totsize);
@@ -602,7 +594,7 @@ xfs_iformat_extents(
xfs_dinode_t *dip,
int whichfork)
{
- xfs_bmbt_rec_t *ep, *dp;
+ xfs_bmbt_rec_t *dp;
xfs_ifork_t *ifp;
int nex;
int size;
@@ -637,13 +629,11 @@ xfs_iformat_extents(
ifp->if_bytes = size;
if (size) {
dp = (xfs_bmbt_rec_t *) XFS_DFORK_PTR(dip, whichfork);
- xfs_validate_extents(ifp, nex, 1, XFS_EXTFMT_INODE(ip));
+ xfs_validate_extents(ifp, nex, XFS_EXTFMT_INODE(ip));
for (i = 0; i < nex; i++, dp++) {
- ep = xfs_iext_get_ext(ifp, i);
- ep->l0 = INT_GET(get_unaligned((__uint64_t*)&dp->l0),
- ARCH_CONVERT);
- ep->l1 = INT_GET(get_unaligned((__uint64_t*)&dp->l1),
- ARCH_CONVERT);
+ xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, i);
+ ep->l0 = be64_to_cpu(get_unaligned(&dp->l0));
+ ep->l1 = be64_to_cpu(get_unaligned(&dp->l1));
}
XFS_BMAP_TRACE_EXLIST(ip, nex, whichfork);
if (whichfork != XFS_DATA_FORK ||
@@ -719,70 +709,74 @@ xfs_iformat_btree(
return 0;
}
-/*
- * xfs_xlate_dinode_core - translate an xfs_inode_core_t between ondisk
- * and native format
- *
- * buf = on-disk representation
- * dip = native representation
- * dir = direction - +ve -> disk to native
- * -ve -> native to disk
- */
void
-xfs_xlate_dinode_core(
- xfs_caddr_t buf,
- xfs_dinode_core_t *dip,
- int dir)
+xfs_dinode_from_disk(
+ xfs_icdinode_t *to,
+ xfs_dinode_core_t *from)
{
- xfs_dinode_core_t *buf_core = (xfs_dinode_core_t *)buf;
- xfs_dinode_core_t *mem_core = (xfs_dinode_core_t *)dip;
- xfs_arch_t arch = ARCH_CONVERT;
-
- ASSERT(dir);
-
- INT_XLATE(buf_core->di_magic, mem_core->di_magic, dir, arch);
- INT_XLATE(buf_core->di_mode, mem_core->di_mode, dir, arch);
- INT_XLATE(buf_core->di_version, mem_core->di_version, dir, arch);
- INT_XLATE(buf_core->di_format, mem_core->di_format, dir, arch);
- INT_XLATE(buf_core->di_onlink, mem_core->di_onlink, dir, arch);
- INT_XLATE(buf_core->di_uid, mem_core->di_uid, dir, arch);
- INT_XLATE(buf_core->di_gid, mem_core->di_gid, dir, arch);
- INT_XLATE(buf_core->di_nlink, mem_core->di_nlink, dir, arch);
- INT_XLATE(buf_core->di_projid, mem_core->di_projid, dir, arch);
-
- if (dir > 0) {
- memcpy(mem_core->di_pad, buf_core->di_pad,
- sizeof(buf_core->di_pad));
- } else {
- memcpy(buf_core->di_pad, mem_core->di_pad,
- sizeof(buf_core->di_pad));
- }
-
- INT_XLATE(buf_core->di_flushiter, mem_core->di_flushiter, dir, arch);
-
- INT_XLATE(buf_core->di_atime.t_sec, mem_core->di_atime.t_sec,
- dir, arch);
- INT_XLATE(buf_core->di_atime.t_nsec, mem_core->di_atime.t_nsec,
- dir, arch);
- INT_XLATE(buf_core->di_mtime.t_sec, mem_core->di_mtime.t_sec,
- dir, arch);
- INT_XLATE(buf_core->di_mtime.t_nsec, mem_core->di_mtime.t_nsec,
- dir, arch);
- INT_XLATE(buf_core->di_ctime.t_sec, mem_core->di_ctime.t_sec,
- dir, arch);
- INT_XLATE(buf_core->di_ctime.t_nsec, mem_core->di_ctime.t_nsec,
- dir, arch);
- INT_XLATE(buf_core->di_size, mem_core->di_size, dir, arch);
- INT_XLATE(buf_core->di_nblocks, mem_core->di_nblocks, dir, arch);
- INT_XLATE(buf_core->di_extsize, mem_core->di_extsize, dir, arch);
- INT_XLATE(buf_core->di_nextents, mem_core->di_nextents, dir, arch);
- INT_XLATE(buf_core->di_anextents, mem_core->di_anextents, dir, arch);
- INT_XLATE(buf_core->di_forkoff, mem_core->di_forkoff, dir, arch);
- INT_XLATE(buf_core->di_aformat, mem_core->di_aformat, dir, arch);
- INT_XLATE(buf_core->di_dmevmask, mem_core->di_dmevmask, dir, arch);
- INT_XLATE(buf_core->di_dmstate, mem_core->di_dmstate, dir, arch);
- INT_XLATE(buf_core->di_flags, mem_core->di_flags, dir, arch);
- INT_XLATE(buf_core->di_gen, mem_core->di_gen, dir, arch);
+ to->di_magic = be16_to_cpu(from->di_magic);
+ to->di_mode = be16_to_cpu(from->di_mode);
+ to->di_version = from ->di_version;
+ to->di_format = from->di_format;
+ to->di_onlink = be16_to_cpu(from->di_onlink);
+ to->di_uid = be32_to_cpu(from->di_uid);
+ to->di_gid = be32_to_cpu(from->di_gid);
+ to->di_nlink = be32_to_cpu(from->di_nlink);
+ to->di_projid = be16_to_cpu(from->di_projid);
+ memcpy(to->di_pad, from->di_pad, sizeof(to->di_pad));
+ to->di_flushiter = be16_to_cpu(from->di_flushiter);
+ to->di_atime.t_sec = be32_to_cpu(from->di_atime.t_sec);
+ to->di_atime.t_nsec = be32_to_cpu(from->di_atime.t_nsec);
+ to->di_mtime.t_sec = be32_to_cpu(from->di_mtime.t_sec);
+ to->di_mtime.t_nsec = be32_to_cpu(from->di_mtime.t_nsec);
+ to->di_ctime.t_sec = be32_to_cpu(from->di_ctime.t_sec);
+ to->di_ctime.t_nsec = be32_to_cpu(from->di_ctime.t_nsec);
+ to->di_size = be64_to_cpu(from->di_size);
+ to->di_nblocks = be64_to_cpu(from->di_nblocks);
+ to->di_extsize = be32_to_cpu(from->di_extsize);
+ to->di_nextents = be32_to_cpu(from->di_nextents);
+ to->di_anextents = be16_to_cpu(from->di_anextents);
+ to->di_forkoff = from->di_forkoff;
+ to->di_aformat = from->di_aformat;
+ to->di_dmevmask = be32_to_cpu(from->di_dmevmask);
+ to->di_dmstate = be16_to_cpu(from->di_dmstate);
+ to->di_flags = be16_to_cpu(from->di_flags);
+ to->di_gen = be32_to_cpu(from->di_gen);
+}
+
+void
+xfs_dinode_to_disk(
+ xfs_dinode_core_t *to,
+ xfs_icdinode_t *from)
+{
+ to->di_magic = cpu_to_be16(from->di_magic);
+ to->di_mode = cpu_to_be16(from->di_mode);
+ to->di_version = from ->di_version;
+ to->di_format = from->di_format;
+ to->di_onlink = cpu_to_be16(from->di_onlink);
+ to->di_uid = cpu_to_be32(from->di_uid);
+ to->di_gid = cpu_to_be32(from->di_gid);
+ to->di_nlink = cpu_to_be32(from->di_nlink);
+ to->di_projid = cpu_to_be16(from->di_projid);
+ memcpy(to->di_pad, from->di_pad, sizeof(to->di_pad));
+ to->di_flushiter = cpu_to_be16(from->di_flushiter);
+ to->di_atime.t_sec = cpu_to_be32(from->di_atime.t_sec);
+ to->di_atime.t_nsec = cpu_to_be32(from->di_atime.t_nsec);
+ to->di_mtime.t_sec = cpu_to_be32(from->di_mtime.t_sec);
+ to->di_mtime.t_nsec = cpu_to_be32(from->di_mtime.t_nsec);
+ to->di_ctime.t_sec = cpu_to_be32(from->di_ctime.t_sec);
+ to->di_ctime.t_nsec = cpu_to_be32(from->di_ctime.t_nsec);
+ to->di_size = cpu_to_be64(from->di_size);
+ to->di_nblocks = cpu_to_be64(from->di_nblocks);
+ to->di_extsize = cpu_to_be32(from->di_extsize);
+ to->di_nextents = cpu_to_be32(from->di_nextents);
+ to->di_anextents = cpu_to_be16(from->di_anextents);
+ to->di_forkoff = from->di_forkoff;
+ to->di_aformat = from->di_aformat;
+ to->di_dmevmask = cpu_to_be32(from->di_dmevmask);
+ to->di_dmstate = cpu_to_be16(from->di_dmstate);
+ to->di_flags = cpu_to_be16(from->di_flags);
+ to->di_gen = cpu_to_be32(from->di_gen);
}
STATIC uint
@@ -829,7 +823,7 @@ uint
xfs_ip2xflags(
xfs_inode_t *ip)
{
- xfs_dinode_core_t *dic = &ip->i_d;
+ xfs_icdinode_t *dic = &ip->i_d;
return _xfs_dic2xflags(dic->di_flags) |
(XFS_CFORK_Q(dic) ? XFS_XFLAG_HASATTR : 0);
@@ -839,7 +833,7 @@ uint
xfs_dic2xflags(
xfs_dinode_core_t *dic)
{
- return _xfs_dic2xflags(INT_GET(dic->di_flags, ARCH_CONVERT)) |
+ return _xfs_dic2xflags(be16_to_cpu(dic->di_flags)) |
(XFS_CFORK_Q_DISK(dic) ? XFS_XFLAG_HASATTR : 0);
}
@@ -870,6 +864,7 @@ xfs_iread(
ip = kmem_zone_zalloc(xfs_inode_zone, KM_SLEEP);
ip->i_ino = ino;
ip->i_mount = mp;
+ atomic_set(&ip->i_iocount, 0);
spin_lock_init(&ip->i_flags_lock);
/*
@@ -889,6 +884,9 @@ xfs_iread(
* Initialize inode's trace buffers.
* Do this before xfs_iformat in case it adds entries.
*/
+#ifdef XFS_VNODE_TRACE
+ ip->i_trace = ktrace_alloc(VNODE_TRACE_SIZE, KM_SLEEP);
+#endif
#ifdef XFS_BMAP_TRACE
ip->i_xtrace = ktrace_alloc(XFS_BMAP_KTRACE_SIZE, KM_SLEEP);
#endif
@@ -909,14 +907,14 @@ xfs_iread(
* If we got something that isn't an inode it means someone
* (nfs or dmi) has a stale handle.
*/
- if (INT_GET(dip->di_core.di_magic, ARCH_CONVERT) != XFS_DINODE_MAGIC) {
+ if (be16_to_cpu(dip->di_core.di_magic) != XFS_DINODE_MAGIC) {
kmem_zone_free(xfs_inode_zone, ip);
xfs_trans_brelse(tp, bp);
#ifdef DEBUG
xfs_fs_cmn_err(CE_ALERT, mp, "xfs_iread: "
"dip->di_core.di_magic (0x%x) != "
"XFS_DINODE_MAGIC (0x%x)",
- INT_GET(dip->di_core.di_magic, ARCH_CONVERT),
+ be16_to_cpu(dip->di_core.di_magic),
XFS_DINODE_MAGIC);
#endif /* DEBUG */
return XFS_ERROR(EINVAL);
@@ -930,8 +928,7 @@ xfs_iread(
* Otherwise, just get the truly permanent information.
*/
if (dip->di_core.di_mode) {
- xfs_xlate_dinode_core((xfs_caddr_t)&dip->di_core,
- &(ip->i_d), 1);
+ xfs_dinode_from_disk(&ip->i_d, &dip->di_core);
error = xfs_iformat(ip, dip);
if (error) {
kmem_zone_free(xfs_inode_zone, ip);
@@ -944,10 +941,10 @@ xfs_iread(
return error;
}
} else {
- ip->i_d.di_magic = INT_GET(dip->di_core.di_magic, ARCH_CONVERT);
- ip->i_d.di_version = INT_GET(dip->di_core.di_version, ARCH_CONVERT);
- ip->i_d.di_gen = INT_GET(dip->di_core.di_gen, ARCH_CONVERT);
- ip->i_d.di_flushiter = INT_GET(dip->di_core.di_flushiter, ARCH_CONVERT);
+ ip->i_d.di_magic = be16_to_cpu(dip->di_core.di_magic);
+ ip->i_d.di_version = dip->di_core.di_version;
+ ip->i_d.di_gen = be32_to_cpu(dip->di_core.di_gen);
+ ip->i_d.di_flushiter = be16_to_cpu(dip->di_core.di_flushiter);
/*
* Make sure to pull in the mode here as well in
* case the inode is released without being used.
@@ -1048,7 +1045,7 @@ xfs_iread_extents(
ifp->if_flags &= ~XFS_IFEXTENTS;
return error;
}
- xfs_validate_extents(ifp, nextents, 0, XFS_EXTFMT_INODE(ip));
+ xfs_validate_extents(ifp, nextents, XFS_EXTFMT_INODE(ip));
return 0;
}
@@ -1161,7 +1158,7 @@ xfs_ialloc(
if ((prid != 0) && (ip->i_d.di_version == XFS_DINODE_VERSION_1))
xfs_bump_ino_vers2(tp, ip);
- if (pip && XFS_INHERIT_GID(pip, vp->v_vfsp)) {
+ if (pip && XFS_INHERIT_GID(pip)) {
ip->i_d.di_gid = pip->i_d.di_gid;
if ((pip->i_d.di_mode & S_ISGID) && (mode & S_IFMT) == S_IFDIR) {
ip->i_d.di_mode |= S_ISGID;
@@ -1275,7 +1272,7 @@ xfs_ialloc(
xfs_trans_log_inode(tp, ip, flags);
/* now that we have an i_mode we can setup inode ops and unlock */
- bhv_vfs_init_vnode(XFS_MTOVFS(tp->t_mountp), vp, XFS_ITOBHV(ip), 1);
+ xfs_initialize_vnode(tp->t_mountp, vp, ip);
*ipp = ip;
return 0;
@@ -1462,7 +1459,7 @@ xfs_itruncate_start(
mp = ip->i_mount;
vp = XFS_ITOV(ip);
- vn_iowait(vp); /* wait for the completion of any pending DIOs */
+ vn_iowait(ip); /* wait for the completion of any pending DIOs */
/*
* Call toss_pages or flushinval_pages to get rid of pages
@@ -1497,9 +1494,11 @@ xfs_itruncate_start(
last_byte);
if (last_byte > toss_start) {
if (flags & XFS_ITRUNC_DEFINITE) {
- bhv_vop_toss_pages(vp, toss_start, -1, FI_REMAPF_LOCKED);
+ xfs_tosspages(ip, toss_start,
+ -1, FI_REMAPF_LOCKED);
} else {
- error = bhv_vop_flushinval_pages(vp, toss_start, -1, FI_REMAPF_LOCKED);
+ error = xfs_flushinval_pages(ip, toss_start,
+ -1, FI_REMAPF_LOCKED);
}
}
@@ -1932,9 +1931,9 @@ xfs_iunlink(
*/
error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, agdaddr,
XFS_FSS_TO_BB(mp, 1), 0, &agibp);
- if (error) {
+ if (error)
return error;
- }
+
/*
* Validate the magic number of the agi block.
*/
@@ -1958,6 +1957,24 @@ xfs_iunlink(
ASSERT(agi->agi_unlinked[bucket_index]);
ASSERT(be32_to_cpu(agi->agi_unlinked[bucket_index]) != agino);
+ error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0);
+ if (error)
+ return error;
+
+ /*
+ * Clear the on-disk di_nlink. This is to prevent xfs_bulkstat
+ * from picking up this inode when it is reclaimed (its incore state
+ * initialzed but not flushed to disk yet). The in-core di_nlink is
+ * already cleared in xfs_droplink() and a corresponding transaction
+ * logged. The hack here just synchronizes the in-core to on-disk
+ * di_nlink value in advance before the actual inode sync to disk.
+ * This is OK because the inode is already unlinked and would never
+ * change its di_nlink again for this inode generation.
+ * This is a temporary hack that would require a proper fix
+ * in the future.
+ */
+ dip->di_core.di_nlink = 0;
+
if (be32_to_cpu(agi->agi_unlinked[bucket_index]) != NULLAGINO) {
/*
* There is already another inode in the bucket we need
@@ -1965,12 +1982,7 @@ xfs_iunlink(
* Here we put the head pointer into our next pointer,
* and then we fall through to point the head at us.
*/
- error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0);
- if (error) {
- return error;
- }
- ASSERT(INT_GET(dip->di_next_unlinked, ARCH_CONVERT) == NULLAGINO);
- ASSERT(dip->di_next_unlinked);
+ ASSERT(be32_to_cpu(dip->di_next_unlinked) == NULLAGINO);
/* both on-disk, don't endian flip twice */
dip->di_next_unlinked = agi->agi_unlinked[bucket_index];
offset = ip->i_boffset +
@@ -2081,10 +2093,10 @@ xfs_iunlink_remove(
error, mp->m_fsname);
return error;
}
- next_agino = INT_GET(dip->di_next_unlinked, ARCH_CONVERT);
+ next_agino = be32_to_cpu(dip->di_next_unlinked);
ASSERT(next_agino != 0);
if (next_agino != NULLAGINO) {
- INT_SET(dip->di_next_unlinked, ARCH_CONVERT, NULLAGINO);
+ dip->di_next_unlinked = cpu_to_be32(NULLAGINO);
offset = ip->i_boffset +
offsetof(xfs_dinode_t, di_next_unlinked);
xfs_trans_inode_buf(tp, ibp);
@@ -2128,7 +2140,7 @@ xfs_iunlink_remove(
error, mp->m_fsname);
return error;
}
- next_agino = INT_GET(last_dip->di_next_unlinked, ARCH_CONVERT);
+ next_agino = be32_to_cpu(last_dip->di_next_unlinked);
ASSERT(next_agino != NULLAGINO);
ASSERT(next_agino != 0);
}
@@ -2143,11 +2155,11 @@ xfs_iunlink_remove(
error, mp->m_fsname);
return error;
}
- next_agino = INT_GET(dip->di_next_unlinked, ARCH_CONVERT);
+ next_agino = be32_to_cpu(dip->di_next_unlinked);
ASSERT(next_agino != 0);
ASSERT(next_agino != agino);
if (next_agino != NULLAGINO) {
- INT_SET(dip->di_next_unlinked, ARCH_CONVERT, NULLAGINO);
+ dip->di_next_unlinked = cpu_to_be32(NULLAGINO);
offset = ip->i_boffset +
offsetof(xfs_dinode_t, di_next_unlinked);
xfs_trans_inode_buf(tp, ibp);
@@ -2160,7 +2172,7 @@ xfs_iunlink_remove(
/*
* Point the previous inode on the list to the next inode.
*/
- INT_SET(last_dip->di_next_unlinked, ARCH_CONVERT, next_agino);
+ last_dip->di_next_unlinked = cpu_to_be32(next_agino);
ASSERT(next_agino != 0);
offset = last_offset + offsetof(xfs_dinode_t, di_next_unlinked);
xfs_trans_inode_buf(tp, last_ibp);
@@ -2191,10 +2203,10 @@ xfs_ifree_cluster(
int i, j, found, pre_flushed;
xfs_daddr_t blkno;
xfs_buf_t *bp;
- xfs_ihash_t *ih;
xfs_inode_t *ip, **ip_found;
xfs_inode_log_item_t *iip;
xfs_log_item_t *lip;
+ xfs_perag_t *pag = xfs_get_perag(mp, inum);
SPLDECL(s);
if (mp->m_sb.sb_blocksize >= XFS_INODE_CLUSTER_SIZE(mp)) {
@@ -2229,23 +2241,20 @@ xfs_ifree_cluster(
*/
found = 0;
for (i = 0; i < ninodes; i++) {
- ih = XFS_IHASH(mp, inum + i);
- read_lock(&ih->ih_lock);
- for (ip = ih->ih_next; ip != NULL; ip = ip->i_next) {
- if (ip->i_ino == inum + i)
- break;
- }
+ read_lock(&pag->pag_ici_lock);
+ ip = radix_tree_lookup(&pag->pag_ici_root,
+ XFS_INO_TO_AGINO(mp, (inum + i)));
/* Inode not in memory or we found it already,
* nothing to do
*/
if (!ip || xfs_iflags_test(ip, XFS_ISTALE)) {
- read_unlock(&ih->ih_lock);
+ read_unlock(&pag->pag_ici_lock);
continue;
}
if (xfs_inode_clean(ip)) {
- read_unlock(&ih->ih_lock);
+ read_unlock(&pag->pag_ici_lock);
continue;
}
@@ -2268,7 +2277,7 @@ xfs_ifree_cluster(
ip_found[found++] = ip;
}
}
- read_unlock(&ih->ih_lock);
+ read_unlock(&pag->pag_ici_lock);
continue;
}
@@ -2286,8 +2295,7 @@ xfs_ifree_cluster(
xfs_iunlock(ip, XFS_ILOCK_EXCL);
}
}
-
- read_unlock(&ih->ih_lock);
+ read_unlock(&pag->pag_ici_lock);
}
bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, blkno,
@@ -2342,6 +2350,7 @@ xfs_ifree_cluster(
}
kmem_free(ip_found, ninodes * sizeof(xfs_inode_t *));
+ xfs_put_perag(mp, pag);
}
/*
@@ -2737,6 +2746,10 @@ xfs_idestroy(
mrfree(&ip->i_lock);
mrfree(&ip->i_iolock);
freesema(&ip->i_flock);
+
+#ifdef XFS_VNODE_TRACE
+ ktrace_free(ip->i_trace);
+#endif
#ifdef XFS_BMAP_TRACE
ktrace_free(ip->i_xtrace);
#endif
@@ -2887,12 +2900,10 @@ xfs_iunpin_wait(
int
xfs_iextents_copy(
xfs_inode_t *ip,
- xfs_bmbt_rec_t *buffer,
+ xfs_bmbt_rec_t *dp,
int whichfork)
{
int copied;
- xfs_bmbt_rec_t *dest_ep;
- xfs_bmbt_rec_t *ep;
int i;
xfs_ifork_t *ifp;
int nrecs;
@@ -2912,10 +2923,9 @@ xfs_iextents_copy(
* the delayed ones. There must be at least one
* non-delayed extent.
*/
- dest_ep = buffer;
copied = 0;
for (i = 0; i < nrecs; i++) {
- ep = xfs_iext_get_ext(ifp, i);
+ xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, i);
start_block = xfs_bmbt_get_startblock(ep);
if (ISNULLSTARTBLOCK(start_block)) {
/*
@@ -2925,15 +2935,13 @@ xfs_iextents_copy(
}
/* Translate to on disk format */
- put_unaligned(INT_GET(ep->l0, ARCH_CONVERT),
- (__uint64_t*)&dest_ep->l0);
- put_unaligned(INT_GET(ep->l1, ARCH_CONVERT),
- (__uint64_t*)&dest_ep->l1);
- dest_ep++;
+ put_unaligned(cpu_to_be64(ep->l0), &dp->l0);
+ put_unaligned(cpu_to_be64(ep->l1), &dp->l1);
+ dp++;
copied++;
}
ASSERT(copied != 0);
- xfs_validate_extents(ifp, copied, 1, XFS_EXTFMT_INODE(ip));
+ xfs_validate_extents(ifp, copied, XFS_EXTFMT_INODE(ip));
return (copied * (uint)sizeof(xfs_bmbt_rec_t));
}
@@ -3024,7 +3032,7 @@ xfs_iflush_fork(
case XFS_DINODE_FMT_DEV:
if (iip->ili_format.ilf_fields & XFS_ILOG_DEV) {
ASSERT(whichfork == XFS_DATA_FORK);
- INT_SET(dip->di_u.di_dev, ARCH_CONVERT, ip->i_df.if_u2.if_rdev);
+ dip->di_u.di_dev = cpu_to_be32(ip->i_df.if_u2.if_rdev);
}
break;
@@ -3064,12 +3072,11 @@ xfs_iflush(
xfs_mount_t *mp;
int error;
/* REFERENCED */
- xfs_chash_t *ch;
xfs_inode_t *iq;
int clcount; /* count of inodes clustered */
int bufwasdelwri;
+ struct hlist_node *entry;
enum { INT_DELWRI = (1 << 0), INT_ASYNC = (1 << 1) };
- SPLDECL(s);
XFS_STATS_INC(xs_iflush_count);
@@ -3183,14 +3190,14 @@ xfs_iflush(
* inode clustering:
* see if other inodes can be gathered into this write
*/
-
- ip->i_chash->chl_buf = bp;
-
- ch = XFS_CHASH(mp, ip->i_blkno);
- s = mutex_spinlock(&ch->ch_lock);
+ spin_lock(&ip->i_cluster->icl_lock);
+ ip->i_cluster->icl_buf = bp;
clcount = 0;
- for (iq = ip->i_cnext; iq != ip; iq = iq->i_cnext) {
+ hlist_for_each_entry(iq, entry, &ip->i_cluster->icl_inodes, i_cnode) {
+ if (iq == ip)
+ continue;
+
/*
* Do an un-protected check to see if the inode is dirty and
* is a candidate for flushing. These checks will be repeated
@@ -3241,7 +3248,7 @@ xfs_iflush(
xfs_iunlock(iq, XFS_ILOCK_SHARED);
}
}
- mutex_spinunlock(&ch->ch_lock, s);
+ spin_unlock(&ip->i_cluster->icl_lock);
if (clcount) {
XFS_STATS_INC(xs_icluster_flushcnt);
@@ -3278,7 +3285,7 @@ cluster_corrupt_out:
/* Corruption detected in the clustering loop. Invalidate the
* inode buffer and shut down the filesystem.
*/
- mutex_spinunlock(&ch->ch_lock, s);
+ spin_unlock(&ip->i_cluster->icl_lock);
/*
* Clean up the buffer. If it was B_DELWRI, just release it --
@@ -3373,11 +3380,11 @@ xfs_iflush_int(
*/
xfs_synchronize_atime(ip);
- if (XFS_TEST_ERROR(INT_GET(dip->di_core.di_magic,ARCH_CONVERT) != XFS_DINODE_MAGIC,
+ if (XFS_TEST_ERROR(be16_to_cpu(dip->di_core.di_magic) != XFS_DINODE_MAGIC,
mp, XFS_ERRTAG_IFLUSH_1, XFS_RANDOM_IFLUSH_1)) {
xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp,
"xfs_iflush: Bad inode %Lu magic number 0x%x, ptr 0x%p",
- ip->i_ino, (int) INT_GET(dip->di_core.di_magic, ARCH_CONVERT), dip);
+ ip->i_ino, be16_to_cpu(dip->di_core.di_magic), dip);
goto corrupt_out;
}
if (XFS_TEST_ERROR(ip->i_d.di_magic != XFS_DINODE_MAGIC,
@@ -3440,7 +3447,7 @@ xfs_iflush_int(
* because if the inode is dirty at all the core must
* be.
*/
- xfs_xlate_dinode_core((xfs_caddr_t)&(dip->di_core), &(ip->i_d), -1);
+ xfs_dinode_to_disk(&dip->di_core, &ip->i_d);
/* Wrap, we never let the log put out DI_MAX_FLUSH */
if (ip->i_d.di_flushiter == DI_MAX_FLUSH)
@@ -3460,7 +3467,7 @@ xfs_iflush_int(
* Convert it back.
*/
ASSERT(ip->i_d.di_nlink <= XFS_MAXLINK_1);
- INT_SET(dip->di_core.di_onlink, ARCH_CONVERT, ip->i_d.di_nlink);
+ dip->di_core.di_onlink = cpu_to_be16(ip->i_d.di_nlink);
} else {
/*
* The superblock version has already been bumped,
@@ -3468,7 +3475,7 @@ xfs_iflush_int(
* format permanent.
*/
ip->i_d.di_version = XFS_DINODE_VERSION_2;
- INT_SET(dip->di_core.di_version, ARCH_CONVERT, XFS_DINODE_VERSION_2);
+ dip->di_core.di_version = XFS_DINODE_VERSION_2;
ip->i_d.di_onlink = 0;
dip->di_core.di_onlink = 0;
memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
@@ -3711,7 +3718,7 @@ xfs_ilock_trace(xfs_inode_t *ip, int lock, unsigned int lockflags, inst_t *ra)
/*
* Return a pointer to the extent record at file index idx.
*/
-xfs_bmbt_rec_t *
+xfs_bmbt_rec_host_t *
xfs_iext_get_ext(
xfs_ifork_t *ifp, /* inode fork pointer */
xfs_extnum_t idx) /* index of target extent */
@@ -3744,15 +3751,12 @@ xfs_iext_insert(
xfs_extnum_t count, /* number of inserted items */
xfs_bmbt_irec_t *new) /* items to insert */
{
- xfs_bmbt_rec_t *ep; /* extent record pointer */
xfs_extnum_t i; /* extent record index */
ASSERT(ifp->if_flags & XFS_IFEXTENTS);
xfs_iext_add(ifp, idx, count);
- for (i = idx; i < idx + count; i++, new++) {
- ep = xfs_iext_get_ext(ifp, i);
- xfs_bmbt_set_all(ep, new);
- }
+ for (i = idx; i < idx + count; i++, new++)
+ xfs_bmbt_set_all(xfs_iext_get_ext(ifp, i), new);
}
/*
@@ -4203,7 +4207,7 @@ xfs_iext_realloc_direct(
rnew_size = xfs_iroundup(new_size);
}
if (rnew_size != ifp->if_real_bytes) {
- ifp->if_u1.if_extents = (xfs_bmbt_rec_t *)
+ ifp->if_u1.if_extents =
kmem_realloc(ifp->if_u1.if_extents,
rnew_size,
ifp->if_real_bytes,
@@ -4266,8 +4270,7 @@ xfs_iext_inline_to_direct(
xfs_ifork_t *ifp, /* inode fork pointer */
int new_size) /* number of extents in file */
{
- ifp->if_u1.if_extents = (xfs_bmbt_rec_t *)
- kmem_alloc(new_size, KM_SLEEP);
+ ifp->if_u1.if_extents = kmem_alloc(new_size, KM_SLEEP);
memset(ifp->if_u1.if_extents, 0, new_size);
if (ifp->if_bytes) {
memcpy(ifp->if_u1.if_extents, ifp->if_u2.if_inline_ext,
@@ -4310,7 +4313,7 @@ void
xfs_iext_indirect_to_direct(
xfs_ifork_t *ifp) /* inode fork pointer */
{
- xfs_bmbt_rec_t *ep; /* extent record pointer */
+ xfs_bmbt_rec_host_t *ep; /* extent record pointer */
xfs_extnum_t nextents; /* number of extents in file */
int size; /* size of file extents */
@@ -4362,15 +4365,15 @@ xfs_iext_destroy(
/*
* Return a pointer to the extent record for file system block bno.
*/
-xfs_bmbt_rec_t * /* pointer to found extent record */
+xfs_bmbt_rec_host_t * /* pointer to found extent record */
xfs_iext_bno_to_ext(
xfs_ifork_t *ifp, /* inode fork pointer */
xfs_fileoff_t bno, /* block number to search for */
xfs_extnum_t *idxp) /* index of target extent */
{
- xfs_bmbt_rec_t *base; /* pointer to first extent */
+ xfs_bmbt_rec_host_t *base; /* pointer to first extent */
xfs_filblks_t blockcount = 0; /* number of blocks in extent */
- xfs_bmbt_rec_t *ep = NULL; /* pointer to target extent */
+ xfs_bmbt_rec_host_t *ep = NULL; /* pointer to target extent */
xfs_ext_irec_t *erp = NULL; /* indirection array pointer */
int high; /* upper boundary in search */
xfs_extnum_t idx = 0; /* index of target extent */
@@ -4545,8 +4548,7 @@ xfs_iext_irec_init(
kmem_alloc(sizeof(xfs_ext_irec_t), KM_SLEEP);
if (nextents == 0) {
- ifp->if_u1.if_extents = (xfs_bmbt_rec_t *)
- kmem_alloc(XFS_IEXT_BUFSZ, KM_SLEEP);
+ ifp->if_u1.if_extents = kmem_alloc(XFS_IEXT_BUFSZ, KM_SLEEP);
} else if (!ifp->if_real_bytes) {
xfs_iext_inline_to_direct(ifp, XFS_IEXT_BUFSZ);
} else if (ifp->if_real_bytes < XFS_IEXT_BUFSZ) {
@@ -4594,8 +4596,7 @@ xfs_iext_irec_new(
/* Initialize new extent record */
erp = ifp->if_u1.if_ext_irec;
- erp[erp_idx].er_extbuf = (xfs_bmbt_rec_t *)
- kmem_alloc(XFS_IEXT_BUFSZ, KM_SLEEP);
+ erp[erp_idx].er_extbuf = kmem_alloc(XFS_IEXT_BUFSZ, KM_SLEEP);
ifp->if_real_bytes = nlists * XFS_IEXT_BUFSZ;
memset(erp[erp_idx].er_extbuf, 0, XFS_IEXT_BUFSZ);
erp[erp_idx].er_extcount = 0;
@@ -4727,7 +4728,7 @@ void
xfs_iext_irec_compact_full(
xfs_ifork_t *ifp) /* inode fork pointer */
{
- xfs_bmbt_rec_t *ep, *ep_next; /* extent record pointers */
+ xfs_bmbt_rec_host_t *ep, *ep_next; /* extent record pointers */
xfs_ext_irec_t *erp, *erp_next; /* extent irec pointers */
int erp_idx = 0; /* extent irec index */
int ext_avail; /* empty entries in ex list */
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 012dfd4a958c..e5aff929cc65 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -18,6 +18,10 @@
#ifndef __XFS_INODE_H__
#define __XFS_INODE_H__
+struct xfs_dinode;
+struct xfs_dinode_core;
+
+
/*
* Fork identifiers.
*/
@@ -44,7 +48,7 @@
* it is possible that a third level of indirection may be required.
*/
typedef struct xfs_ext_irec {
- xfs_bmbt_rec_t *er_extbuf; /* block of extent records */
+ xfs_bmbt_rec_host_t *er_extbuf; /* block of extent records */
xfs_extnum_t er_extoff; /* extent offset in file */
xfs_extnum_t er_extcount; /* number of extents in page/block */
} xfs_ext_irec_t;
@@ -65,12 +69,12 @@ typedef struct xfs_ifork {
unsigned char if_ext_max; /* max # of extent records */
xfs_extnum_t if_lastex; /* last if_extents used */
union {
- xfs_bmbt_rec_t *if_extents; /* linear map file exts */
+ xfs_bmbt_rec_host_t *if_extents;/* linear map file exts */
xfs_ext_irec_t *if_ext_irec; /* irec map file exts */
char *if_data; /* inline file data */
} if_u1;
union {
- xfs_bmbt_rec_t if_inline_ext[XFS_INLINE_EXTS];
+ xfs_bmbt_rec_host_t if_inline_ext[XFS_INLINE_EXTS];
/* very small file extents */
char if_inline_data[XFS_INLINE_DATA];
/* very small file data */
@@ -102,7 +106,6 @@ typedef struct xfs_ifork {
#ifdef __KERNEL__
struct bhv_desc;
-struct bhv_vnode;
struct cred;
struct ktrace;
struct xfs_buf;
@@ -168,41 +171,18 @@ typedef struct xfs_iocore {
extern void xfs_iocore_inode_init(struct xfs_inode *);
extern void xfs_iocore_inode_reinit(struct xfs_inode *);
-
-/*
- * This is the type used in the xfs inode hash table.
- * An array of these is allocated for each mounted
- * file system to hash the inodes for that file system.
- */
-typedef struct xfs_ihash {
- struct xfs_inode *ih_next;
- rwlock_t ih_lock;
- uint ih_version;
-} xfs_ihash_t;
-
-#define XFS_IHASH(mp,ino) ((mp)->m_ihash + (((uint)(ino)) % (mp)->m_ihsize))
-
/*
- * This is the xfs inode cluster hash. This hash is used by xfs_iflush to
- * find inodes that share a cluster and can be flushed to disk at the same
- * time.
+ * This is the xfs inode cluster structure. This structure is used by
+ * xfs_iflush to find inodes that share a cluster and can be flushed to disk at
+ * the same time.
*/
-typedef struct xfs_chashlist {
- struct xfs_chashlist *chl_next;
- struct xfs_chashlist *chl_prev;
- struct xfs_inode *chl_ip;
- xfs_daddr_t chl_blkno; /* starting block number of
+typedef struct xfs_icluster {
+ struct hlist_head icl_inodes; /* list of inodes on cluster */
+ xfs_daddr_t icl_blkno; /* starting block number of
* the cluster */
- struct xfs_buf *chl_buf; /* the inode buffer */
-} xfs_chashlist_t;
-
-typedef struct xfs_chash {
- xfs_chashlist_t *ch_list;
- lock_t ch_lock;
-} xfs_chash_t;
-
-#define XFS_CHASH(mp,blk) ((mp)->m_chash + (((uint)blk) % (mp)->m_chsize))
-
+ struct xfs_buf *icl_buf; /* the inode buffer */
+ lock_t icl_lock; /* inode list lock */
+} xfs_icluster_t;
/*
* This is the xfs in-core inode structure.
@@ -227,25 +207,56 @@ typedef struct xfs_chash {
* chain off the mount structure by xfs_sync calls.
*/
+typedef struct xfs_ictimestamp {
+ __int32_t t_sec; /* timestamp seconds */
+ __int32_t t_nsec; /* timestamp nanoseconds */
+} xfs_ictimestamp_t;
+
+/*
+ * NOTE: This structure must be kept identical to struct xfs_dinode_core
+ * in xfs_dinode.h except for the endianess annotations.
+ */
+typedef struct xfs_icdinode {
+ __uint16_t di_magic; /* inode magic # = XFS_DINODE_MAGIC */
+ __uint16_t di_mode; /* mode and type of file */
+ __int8_t di_version; /* inode version */
+ __int8_t di_format; /* format of di_c data */
+ __uint16_t di_onlink; /* old number of links to file */
+ __uint32_t di_uid; /* owner's user id */
+ __uint32_t di_gid; /* owner's group id */
+ __uint32_t di_nlink; /* number of links to file */
+ __uint16_t di_projid; /* owner's project id */
+ __uint8_t di_pad[8]; /* unused, zeroed space */
+ __uint16_t di_flushiter; /* incremented on flush */
+ xfs_ictimestamp_t di_atime; /* time last accessed */
+ xfs_ictimestamp_t di_mtime; /* time last modified */
+ xfs_ictimestamp_t di_ctime; /* time created/inode modified */
+ xfs_fsize_t di_size; /* number of bytes in file */
+ xfs_drfsbno_t di_nblocks; /* # of direct & btree blocks used */
+ xfs_extlen_t di_extsize; /* basic/minimum extent size for file */
+ xfs_extnum_t di_nextents; /* number of extents in data fork */
+ xfs_aextnum_t di_anextents; /* number of extents in attribute fork*/
+ __uint8_t di_forkoff; /* attr fork offs, <<3 for 64b align */
+ __int8_t di_aformat; /* format of attr fork's data */
+ __uint32_t di_dmevmask; /* DMIG event mask */
+ __uint16_t di_dmstate; /* DMIG state info */
+ __uint16_t di_flags; /* random flags, XFS_DIFLAG_... */
+ __uint32_t di_gen; /* generation number */
+} xfs_icdinode_t;
+
typedef struct {
- struct xfs_ihash *ip_hash; /* pointer to hash header */
- struct xfs_inode *ip_next; /* inode hash link forw */
struct xfs_inode *ip_mnext; /* next inode in mount list */
struct xfs_inode *ip_mprev; /* ptr to prev inode */
- struct xfs_inode **ip_prevp; /* ptr to prev i_next */
struct xfs_mount *ip_mount; /* fs mount struct ptr */
} xfs_iptr_t;
typedef struct xfs_inode {
/* Inode linking and identification information. */
- struct xfs_ihash *i_hash; /* pointer to hash header */
- struct xfs_inode *i_next; /* inode hash link forw */
struct xfs_inode *i_mnext; /* next inode in mount list */
struct xfs_inode *i_mprev; /* ptr to prev inode */
- struct xfs_inode **i_prevp; /* ptr to prev i_next */
struct xfs_mount *i_mount; /* fs mount struct ptr */
struct list_head i_reclaim; /* reclaim list */
- struct bhv_desc i_bhv_desc; /* inode behavior descriptor*/
+ bhv_vnode_t *i_vnode; /* vnode backpointer */
struct xfs_dquot *i_udquot; /* user dquot */
struct xfs_dquot *i_gdquot; /* group dquot */
@@ -282,13 +293,16 @@ typedef struct xfs_inode {
unsigned int i_gen; /* generation count */
unsigned int i_delayed_blks; /* count of delay alloc blks */
- xfs_dinode_core_t i_d; /* most of ondisk inode */
- xfs_chashlist_t *i_chash; /* cluster hash list header */
- struct xfs_inode *i_cnext; /* cluster hash link forward */
- struct xfs_inode *i_cprev; /* cluster hash link backward */
+ xfs_icdinode_t i_d; /* most of ondisk inode */
+ xfs_icluster_t *i_cluster; /* cluster list header */
+ struct hlist_node i_cnode; /* cluster link node */
xfs_fsize_t i_size; /* in-memory size */
+ atomic_t i_iocount; /* outstanding I/O count */
/* Trace buffers per inode. */
+#ifdef XFS_VNODE_TRACE
+ struct ktrace *i_trace; /* general inode trace */
+#endif
#ifdef XFS_BMAP_TRACE
struct ktrace *i_xtrace; /* inode extent list trace */
#endif
@@ -349,6 +363,19 @@ xfs_iflags_test(xfs_inode_t *ip, unsigned short flags)
spin_unlock(&ip->i_flags_lock);
return ret;
}
+
+static inline int
+xfs_iflags_test_and_clear(xfs_inode_t *ip, unsigned short flags)
+{
+ int ret;
+
+ spin_lock(&ip->i_flags_lock);
+ ret = ip->i_flags & flags;
+ if (ret)
+ ip->i_flags &= ~flags;
+ spin_unlock(&ip->i_flags_lock);
+ return ret;
+}
#endif /* __KERNEL__ */
@@ -380,6 +407,9 @@ xfs_iflags_test(xfs_inode_t *ip, unsigned short flags)
#define XFS_IRECLAIMABLE 0x0020 /* inode can be reclaimed */
#define XFS_INEW 0x0040
#define XFS_IFILESTREAM 0x0080 /* inode is in a filestream directory */
+#define XFS_IMODIFIED 0x0100 /* XFS inode state possibly differs */
+ /* to the Linux inode state. */
+#define XFS_ITRUNCATED 0x0200 /* truncated down so flush-on-close */
/*
* Flags for inode locking.
@@ -454,20 +484,17 @@ xfs_iflags_test(xfs_inode_t *ip, unsigned short flags)
#define XFS_ITRUNC_DEFINITE 0x1
#define XFS_ITRUNC_MAYBE 0x2
-#define XFS_ITOV(ip) BHV_TO_VNODE(XFS_ITOBHV(ip))
-#define XFS_ITOV_NULL(ip) BHV_TO_VNODE_NULL(XFS_ITOBHV(ip))
-#define XFS_ITOBHV(ip) ((struct bhv_desc *)(&((ip)->i_bhv_desc)))
-#define XFS_BHVTOI(bhvp) ((xfs_inode_t *)((char *)(bhvp) - \
- (char *)&(((xfs_inode_t *)0)->i_bhv_desc)))
-#define BHV_IS_XFS(bdp) (BHV_OPS(bdp) == &xfs_vnodeops)
+#define XFS_ITOV(ip) ((ip)->i_vnode)
+#define XFS_ITOV_NULL(ip) ((ip)->i_vnode)
/*
* For multiple groups support: if S_ISGID bit is set in the parent
* directory, group of new file is set to that of the parent, and
* new subdirectory gets S_ISGID bit from parent.
*/
-#define XFS_INHERIT_GID(pip, vfsp) \
- (((vfsp)->vfs_flag & VFS_GRPID) || ((pip)->i_d.di_mode & S_ISGID))
+#define XFS_INHERIT_GID(pip) \
+ (((pip)->i_mount->m_flags & XFS_MOUNT_GRPID) || \
+ ((pip)->i_d.di_mode & S_ISGID))
/*
* Flags for xfs_iget()
@@ -480,11 +507,9 @@ xfs_iflags_test(xfs_inode_t *ip, unsigned short flags)
*/
void xfs_ihash_init(struct xfs_mount *);
void xfs_ihash_free(struct xfs_mount *);
-void xfs_chash_init(struct xfs_mount *);
-void xfs_chash_free(struct xfs_mount *);
xfs_inode_t *xfs_inode_incore(struct xfs_mount *, xfs_ino_t,
struct xfs_trans *);
-void xfs_inode_lock_init(xfs_inode_t *, struct bhv_vnode *);
+void xfs_inode_lock_init(xfs_inode_t *, bhv_vnode_t *);
int xfs_iget(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
uint, uint, xfs_inode_t **, xfs_daddr_t);
void xfs_iput(xfs_inode_t *, uint);
@@ -506,7 +531,7 @@ int xfs_finish_reclaim_all(struct xfs_mount *, int);
* xfs_inode.c prototypes.
*/
int xfs_itobp(struct xfs_mount *, struct xfs_trans *,
- xfs_inode_t *, xfs_dinode_t **, struct xfs_buf **,
+ xfs_inode_t *, struct xfs_dinode **, struct xfs_buf **,
xfs_daddr_t, uint);
int xfs_iread(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
xfs_inode_t **, xfs_daddr_t, uint);
@@ -514,8 +539,11 @@ int xfs_iread_extents(struct xfs_trans *, xfs_inode_t *, int);
int xfs_ialloc(struct xfs_trans *, xfs_inode_t *, mode_t,
xfs_nlink_t, xfs_dev_t, struct cred *, xfs_prid_t,
int, struct xfs_buf **, boolean_t *, xfs_inode_t **);
-void xfs_xlate_dinode_core(xfs_caddr_t, struct xfs_dinode_core *,
- int);
+void xfs_dinode_from_disk(struct xfs_icdinode *,
+ struct xfs_dinode_core *);
+void xfs_dinode_to_disk(struct xfs_dinode_core *,
+ struct xfs_icdinode *);
+
uint xfs_ip2xflags(struct xfs_inode *);
uint xfs_dic2xflags(struct xfs_dinode_core *);
int xfs_ifree(struct xfs_trans *, xfs_inode_t *,
@@ -545,11 +573,9 @@ void xfs_ichgtime(xfs_inode_t *, int);
xfs_fsize_t xfs_file_last_byte(xfs_inode_t *);
void xfs_lock_inodes(xfs_inode_t **, int, int, uint);
-xfs_inode_t *xfs_vtoi(struct bhv_vnode *vp);
-
void xfs_synchronize_atime(xfs_inode_t *);
-xfs_bmbt_rec_t *xfs_iext_get_ext(xfs_ifork_t *, xfs_extnum_t);
+xfs_bmbt_rec_host_t *xfs_iext_get_ext(xfs_ifork_t *, xfs_extnum_t);
void xfs_iext_insert(xfs_ifork_t *, xfs_extnum_t, xfs_extnum_t,
xfs_bmbt_irec_t *);
void xfs_iext_add(xfs_ifork_t *, xfs_extnum_t, int);
@@ -564,7 +590,7 @@ void xfs_iext_indirect_to_direct(xfs_ifork_t *);
void xfs_iext_direct_to_inline(xfs_ifork_t *, xfs_extnum_t);
void xfs_iext_inline_to_direct(xfs_ifork_t *, int);
void xfs_iext_destroy(xfs_ifork_t *);
-xfs_bmbt_rec_t *xfs_iext_bno_to_ext(xfs_ifork_t *, xfs_fileoff_t, int *);
+xfs_bmbt_rec_host_t *xfs_iext_bno_to_ext(xfs_ifork_t *, xfs_fileoff_t, int *);
xfs_ext_irec_t *xfs_iext_bno_to_irec(xfs_ifork_t *, xfs_fileoff_t, int *);
xfs_ext_irec_t *xfs_iext_idx_to_irec(xfs_ifork_t *, xfs_extnum_t *, int *, int);
void xfs_iext_irec_init(xfs_ifork_t *);
@@ -589,7 +615,7 @@ void xfs_inobp_check(struct xfs_mount *, struct xfs_buf *);
#define xfs_inobp_check(mp, bp)
#endif /* DEBUG */
-extern struct kmem_zone *xfs_chashlist_zone;
+extern struct kmem_zone *xfs_icluster_zone;
extern struct kmem_zone *xfs_ifork_zone;
extern struct kmem_zone *xfs_inode_zone;
extern struct kmem_zone *xfs_ili_zone;
diff --git a/fs/xfs/xfs_iocore.c b/fs/xfs/xfs_iocore.c
index 81548ec72ba6..b27b5d5be841 100644
--- a/fs/xfs/xfs_iocore.c
+++ b/fs/xfs/xfs_iocore.c
@@ -57,11 +57,11 @@ xfs_size_fn(
STATIC int
xfs_ioinit(
- struct bhv_vfs *vfsp,
+ struct xfs_mount *mp,
struct xfs_mount_args *mntargs,
int flags)
{
- return xfs_mountfs(vfsp, XFS_VFSTOM(vfsp), flags);
+ return xfs_mountfs(mp, flags);
}
xfs_ioops_t xfs_iocore_xfs = {
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index bf57b75acb90..72786e356d56 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -135,14 +135,10 @@ xfs_imap_to_bmap(
int flags)
{
xfs_mount_t *mp;
- xfs_fsize_t nisize;
int pbm;
xfs_fsblock_t start_block;
mp = io->io_mount;
- nisize = XFS_SIZE(mp, io);
- if (io->io_new_size > nisize)
- nisize = io->io_new_size;
for (pbm = 0; imaps && pbm < iomaps; imaps--, iomapp++, imap++, pbm++) {
iomapp->iomap_offset = XFS_FSB_TO_B(mp, imap->br_startoff);
@@ -169,10 +165,6 @@ xfs_imap_to_bmap(
iomapp->iomap_flags |= IOMAP_UNWRITTEN;
}
- if ((iomapp->iomap_offset + iomapp->iomap_bsize) >= nisize) {
- iomapp->iomap_flags |= IOMAP_EOF;
- }
-
offset += iomapp->iomap_bsize - iomapp->iomap_delta;
}
return pbm; /* Return the number filled */
diff --git a/fs/xfs/xfs_iomap.h b/fs/xfs/xfs_iomap.h
index df441ee936b2..f5c09887fe93 100644
--- a/fs/xfs/xfs_iomap.h
+++ b/fs/xfs/xfs_iomap.h
@@ -23,7 +23,6 @@
typedef enum { /* iomap_flags values */
IOMAP_READ = 0, /* mapping for a read */
- IOMAP_EOF = 0x01, /* mapping contains EOF */
IOMAP_HOLE = 0x02, /* mapping covers a hole */
IOMAP_DELAY = 0x04, /* mapping covers delalloc region */
IOMAP_REALTIME = 0x10, /* mapping on the realtime device */
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 4c2454bcc714..9972992fd3c3 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -57,7 +57,7 @@ xfs_bulkstat_one_iget(
xfs_bstat_t *buf, /* return buffer */
int *stat) /* BULKSTAT_RV_... */
{
- xfs_dinode_core_t *dic; /* dinode core info pointer */
+ xfs_icdinode_t *dic; /* dinode core info pointer */
xfs_inode_t *ip; /* incore inode pointer */
bhv_vnode_t *vp;
int error;
@@ -151,37 +151,37 @@ xfs_bulkstat_one_dinode(
* the new format. We don't change the version number so that we
* can distinguish this from a real new format inode.
*/
- if (INT_GET(dic->di_version, ARCH_CONVERT) == XFS_DINODE_VERSION_1) {
- buf->bs_nlink = INT_GET(dic->di_onlink, ARCH_CONVERT);
+ if (dic->di_version == XFS_DINODE_VERSION_1) {
+ buf->bs_nlink = be16_to_cpu(dic->di_onlink);
buf->bs_projid = 0;
} else {
- buf->bs_nlink = INT_GET(dic->di_nlink, ARCH_CONVERT);
- buf->bs_projid = INT_GET(dic->di_projid, ARCH_CONVERT);
+ buf->bs_nlink = be32_to_cpu(dic->di_nlink);
+ buf->bs_projid = be16_to_cpu(dic->di_projid);
}
buf->bs_ino = ino;
- buf->bs_mode = INT_GET(dic->di_mode, ARCH_CONVERT);
- buf->bs_uid = INT_GET(dic->di_uid, ARCH_CONVERT);
- buf->bs_gid = INT_GET(dic->di_gid, ARCH_CONVERT);
- buf->bs_size = INT_GET(dic->di_size, ARCH_CONVERT);
- buf->bs_atime.tv_sec = INT_GET(dic->di_atime.t_sec, ARCH_CONVERT);
- buf->bs_atime.tv_nsec = INT_GET(dic->di_atime.t_nsec, ARCH_CONVERT);
- buf->bs_mtime.tv_sec = INT_GET(dic->di_mtime.t_sec, ARCH_CONVERT);
- buf->bs_mtime.tv_nsec = INT_GET(dic->di_mtime.t_nsec, ARCH_CONVERT);
- buf->bs_ctime.tv_sec = INT_GET(dic->di_ctime.t_sec, ARCH_CONVERT);
- buf->bs_ctime.tv_nsec = INT_GET(dic->di_ctime.t_nsec, ARCH_CONVERT);
+ buf->bs_mode = be16_to_cpu(dic->di_mode);
+ buf->bs_uid = be32_to_cpu(dic->di_uid);
+ buf->bs_gid = be32_to_cpu(dic->di_gid);
+ buf->bs_size = be64_to_cpu(dic->di_size);
+ buf->bs_atime.tv_sec = be32_to_cpu(dic->di_atime.t_sec);
+ buf->bs_atime.tv_nsec = be32_to_cpu(dic->di_atime.t_nsec);
+ buf->bs_mtime.tv_sec = be32_to_cpu(dic->di_mtime.t_sec);
+ buf->bs_mtime.tv_nsec = be32_to_cpu(dic->di_mtime.t_nsec);
+ buf->bs_ctime.tv_sec = be32_to_cpu(dic->di_ctime.t_sec);
+ buf->bs_ctime.tv_nsec = be32_to_cpu(dic->di_ctime.t_nsec);
buf->bs_xflags = xfs_dic2xflags(dic);
- buf->bs_extsize = INT_GET(dic->di_extsize, ARCH_CONVERT) << mp->m_sb.sb_blocklog;
- buf->bs_extents = INT_GET(dic->di_nextents, ARCH_CONVERT);
- buf->bs_gen = INT_GET(dic->di_gen, ARCH_CONVERT);
+ buf->bs_extsize = be32_to_cpu(dic->di_extsize) << mp->m_sb.sb_blocklog;
+ buf->bs_extents = be32_to_cpu(dic->di_nextents);
+ buf->bs_gen = be32_to_cpu(dic->di_gen);
memset(buf->bs_pad, 0, sizeof(buf->bs_pad));
- buf->bs_dmevmask = INT_GET(dic->di_dmevmask, ARCH_CONVERT);
- buf->bs_dmstate = INT_GET(dic->di_dmstate, ARCH_CONVERT);
- buf->bs_aextents = INT_GET(dic->di_anextents, ARCH_CONVERT);
+ buf->bs_dmevmask = be32_to_cpu(dic->di_dmevmask);
+ buf->bs_dmstate = be16_to_cpu(dic->di_dmstate);
+ buf->bs_aextents = be16_to_cpu(dic->di_anextents);
- switch (INT_GET(dic->di_format, ARCH_CONVERT)) {
+ switch (dic->di_format) {
case XFS_DINODE_FMT_DEV:
- buf->bs_rdev = INT_GET(dip->di_u.di_dev, ARCH_CONVERT);
+ buf->bs_rdev = be32_to_cpu(dip->di_u.di_dev);
buf->bs_blksize = BLKDEV_IOSIZE;
buf->bs_blocks = 0;
break;
@@ -195,7 +195,7 @@ xfs_bulkstat_one_dinode(
case XFS_DINODE_FMT_BTREE:
buf->bs_rdev = 0;
buf->bs_blksize = mp->m_sb.sb_blocksize;
- buf->bs_blocks = INT_GET(dic->di_nblocks, ARCH_CONVERT);
+ buf->bs_blocks = be64_to_cpu(dic->di_nblocks);
break;
}
@@ -290,16 +290,23 @@ xfs_bulkstat_use_dinode(
return 1;
dip = (xfs_dinode_t *)
xfs_buf_offset(bp, clustidx << mp->m_sb.sb_inodelog);
- if (INT_GET(dip->di_core.di_magic, ARCH_CONVERT) != XFS_DINODE_MAGIC ||
- !XFS_DINODE_GOOD_VERSION(
- INT_GET(dip->di_core.di_version, ARCH_CONVERT)))
+ /*
+ * Check the buffer containing the on-disk inode for di_nlink == 0.
+ * This is to prevent xfs_bulkstat from picking up just reclaimed
+ * inodes that have their in-core state initialized but not flushed
+ * to disk yet. This is a temporary hack that would require a proper
+ * fix in the future.
+ */
+ if (be16_to_cpu(dip->di_core.di_magic) != XFS_DINODE_MAGIC ||
+ !XFS_DINODE_GOOD_VERSION(dip->di_core.di_version) ||
+ !dip->di_core.di_nlink)
return 0;
if (flags & BULKSTAT_FG_QUICK) {
*dipp = dip;
return 1;
}
/* BULKSTAT_FG_INLINE: if attr fork is local, or not there, use it */
- aformat = INT_GET(dip->di_core.di_aformat, ARCH_CONVERT);
+ aformat = dip->di_core.di_aformat;
if ((XFS_CFORK_Q(&dip->di_core) == 0) ||
(aformat == XFS_DINODE_FMT_LOCAL) ||
(aformat == XFS_DINODE_FMT_EXTENTS && !dip->di_core.di_anextents)) {
@@ -612,21 +619,25 @@ xfs_bulkstat(
}
}
}
+ ino = XFS_AGINO_TO_INO(mp, agno, agino);
+ bno = XFS_AGB_TO_DADDR(mp, agno, agbno);
/*
* Skip if this inode is free.
*/
- if (XFS_INOBT_MASK(chunkidx) & irbp->ir_free)
+ if (XFS_INOBT_MASK(chunkidx) & irbp->ir_free) {
+ lastino = ino;
continue;
+ }
/*
* Count used inodes as free so we can tell
* when the chunk is used up.
*/
irbp->ir_freecount++;
- ino = XFS_AGINO_TO_INO(mp, agno, agino);
- bno = XFS_AGB_TO_DADDR(mp, agno, agbno);
if (!xfs_bulkstat_use_dinode(mp, flags, bp,
- clustidx, &dip))
+ clustidx, &dip)) {
+ lastino = ino;
continue;
+ }
/*
* If we need to do an iget, cannot hold bp.
* Drop it, until starting the next cluster.
@@ -687,8 +698,7 @@ xfs_bulkstat(
if (end_of_ag) {
agno++;
agino = 0;
- } else
- agino = XFS_INO_TO_AGINO(mp, lastino);
+ }
} else
break;
}
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 9bfb69e1e885..77c12715a7d0 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -252,6 +252,29 @@ xlog_grant_add_space(struct log *log, int bytes)
xlog_grant_add_space_reserve(log, bytes);
}
+static void
+xlog_tic_reset_res(xlog_ticket_t *tic)
+{
+ tic->t_res_num = 0;
+ tic->t_res_arr_sum = 0;
+ tic->t_res_num_ophdrs = 0;
+}
+
+static void
+xlog_tic_add_region(xlog_ticket_t *tic, uint len, uint type)
+{
+ if (tic->t_res_num == XLOG_TIC_LEN_MAX) {
+ /* add to overflow and start again */
+ tic->t_res_o_flow += tic->t_res_arr_sum;
+ tic->t_res_num = 0;
+ tic->t_res_arr_sum = 0;
+ }
+
+ tic->t_res_arr[tic->t_res_num].r_len = len;
+ tic->t_res_arr[tic->t_res_num].r_type = type;
+ tic->t_res_arr_sum += len;
+ tic->t_res_num++;
+}
/*
* NOTES:
@@ -486,7 +509,7 @@ xfs_log_mount(xfs_mount_t *mp,
cmn_err(CE_NOTE,
"!Mounting filesystem \"%s\" in no-recovery mode. Filesystem will be inconsistent.",
mp->m_fsname);
- ASSERT(XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY);
+ ASSERT(mp->m_flags & XFS_MOUNT_RDONLY);
}
mp->m_log = xlog_alloc_log(mp, log_target, blk_offset, num_bblks);
@@ -496,16 +519,15 @@ xfs_log_mount(xfs_mount_t *mp,
* just worked.
*/
if (!(mp->m_flags & XFS_MOUNT_NORECOVERY)) {
- bhv_vfs_t *vfsp = XFS_MTOVFS(mp);
- int error, readonly = (vfsp->vfs_flag & VFS_RDONLY);
+ int error, readonly = (mp->m_flags & XFS_MOUNT_RDONLY);
if (readonly)
- vfsp->vfs_flag &= ~VFS_RDONLY;
+ mp->m_flags &= ~XFS_MOUNT_RDONLY;
error = xlog_recover(mp->m_log);
if (readonly)
- vfsp->vfs_flag |= VFS_RDONLY;
+ mp->m_flags |= XFS_MOUNT_RDONLY;
if (error) {
cmn_err(CE_WARN, "XFS: log mount/recovery failed: error %d", error);
xlog_dealloc_log(mp->m_log);
@@ -537,7 +559,7 @@ xfs_log_mount_finish(xfs_mount_t *mp, int mfsi_flags)
error = xlog_recover_finish(mp->m_log, mfsi_flags);
else {
error = 0;
- ASSERT(XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY);
+ ASSERT(mp->m_flags & XFS_MOUNT_RDONLY);
}
return error;
@@ -597,7 +619,7 @@ xfs_log_unmount_write(xfs_mount_t *mp)
* Don't write out unmount record on read-only mounts.
* Or, if we are doing a forced umount (typically because of IO errors).
*/
- if (XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY)
+ if (mp->m_flags & XFS_MOUNT_RDONLY)
return 0;
xfs_log_force(mp, 0, XFS_LOG_FORCE|XFS_LOG_SYNC);
@@ -949,6 +971,19 @@ xlog_iodone(xfs_buf_t *bp)
l = iclog->ic_log;
/*
+ * If the ordered flag has been removed by a lower
+ * layer, it means the underlyin device no longer supports
+ * barrier I/O. Warn loudly and turn off barriers.
+ */
+ if ((l->l_mp->m_flags & XFS_MOUNT_BARRIER) && !XFS_BUF_ORDERED(bp)) {
+ l->l_mp->m_flags &= ~XFS_MOUNT_BARRIER;
+ xfs_fs_cmn_err(CE_WARN, l->l_mp,
+ "xlog_iodone: Barriers are no longer supported"
+ " by device. Disabling barriers\n");
+ xfs_buftrace("XLOG_IODONE BARRIERS OFF", bp);
+ }
+
+ /*
* Race to shutdown the filesystem if we see an error.
*/
if (XFS_TEST_ERROR((XFS_BUF_GETERROR(bp)), l->l_mp,
@@ -1012,10 +1047,7 @@ xlog_bdstrat_cb(struct xfs_buf *bp)
/*
* Return size of each in-core log record buffer.
*
- * Low memory machines only get 2 16KB buffers. We don't want to waste
- * memory here. However, all other machines get at least 2 32KB buffers.
- * The number is hard coded because we don't care about the minimum
- * memory size, just 32MB systems.
+ * All machines get 8 x 32KB buffers by default, unless tuned otherwise.
*
* If the filesystem blocksize is too large, we may need to choose a
* larger size since the directory code currently logs entire blocks.
@@ -1028,17 +1060,10 @@ xlog_get_iclog_buffer_size(xfs_mount_t *mp,
int size;
int xhdrs;
- if (mp->m_logbufs <= 0) {
- if (xfs_physmem <= btoc(128*1024*1024)) {
- log->l_iclog_bufs = XLOG_MIN_ICLOGS;
- } else if (xfs_physmem <= btoc(400*1024*1024)) {
- log->l_iclog_bufs = XLOG_MED_ICLOGS;
- } else { /* 256K with 32K bufs */
- log->l_iclog_bufs = XLOG_MAX_ICLOGS;
- }
- } else {
+ if (mp->m_logbufs <= 0)
+ log->l_iclog_bufs = XLOG_MAX_ICLOGS;
+ else
log->l_iclog_bufs = mp->m_logbufs;
- }
/*
* Buffer size passed in from mount system call.
@@ -1069,18 +1094,9 @@ xlog_get_iclog_buffer_size(xfs_mount_t *mp,
goto done;
}
- /*
- * Special case machines that have less than 32MB of memory.
- * All machines with more memory use 32KB buffers.
- */
- if (xfs_physmem <= btoc(32*1024*1024)) {
- /* Don't change; min configuration */
- log->l_iclog_size = XLOG_RECORD_BSIZE; /* 16k */
- log->l_iclog_size_log = XLOG_RECORD_BSHIFT;
- } else {
- log->l_iclog_size = XLOG_BIG_RECORD_BSIZE; /* 32k */
- log->l_iclog_size_log = XLOG_BIG_RECORD_BSHIFT;
- }
+ /* All machines use 32KB buffers by default. */
+ log->l_iclog_size = XLOG_BIG_RECORD_BSIZE;
+ log->l_iclog_size_log = XLOG_BIG_RECORD_BSHIFT;
/* the default log size is 16k or 32k which is one header sector */
log->l_iclog_hsize = BBSIZE;
@@ -1771,14 +1787,14 @@ xlog_write(xfs_mount_t * mp,
len = 0;
if (ticket->t_flags & XLOG_TIC_INITED) { /* acct for start rec of xact */
len += sizeof(xlog_op_header_t);
- XLOG_TIC_ADD_OPHDR(ticket);
+ ticket->t_res_num_ophdrs++;
}
for (index = 0; index < nentries; index++) {
len += sizeof(xlog_op_header_t); /* each region gets >= 1 */
- XLOG_TIC_ADD_OPHDR(ticket);
+ ticket->t_res_num_ophdrs++;
len += reg[index].i_len;
- XLOG_TIC_ADD_REGION(ticket, reg[index].i_len, reg[index].i_type);
+ xlog_tic_add_region(ticket, reg[index].i_len, reg[index].i_type);
}
contwr = *start_lsn = 0;
@@ -1887,7 +1903,7 @@ xlog_write(xfs_mount_t * mp,
len += sizeof(xlog_op_header_t); /* from splitting of region */
/* account for new log op header */
ticket->t_curr_res -= sizeof(xlog_op_header_t);
- XLOG_TIC_ADD_OPHDR(ticket);
+ ticket->t_res_num_ophdrs++;
}
xlog_verify_dest_ptr(log, ptr);
@@ -2385,7 +2401,7 @@ restart:
*/
if (log_offset == 0) {
ticket->t_curr_res -= log->l_iclog_hsize;
- XLOG_TIC_ADD_REGION(ticket,
+ xlog_tic_add_region(ticket,
log->l_iclog_hsize,
XLOG_REG_TYPE_LRHEADER);
INT_SET(head->h_cycle, ARCH_CONVERT, log->l_curr_cycle);
@@ -2573,7 +2589,7 @@ xlog_regrant_write_log_space(xlog_t *log,
#endif
tic->t_curr_res = tic->t_unit_res;
- XLOG_TIC_RESET_RES(tic);
+ xlog_tic_reset_res(tic);
if (tic->t_cnt > 0)
return 0;
@@ -2714,7 +2730,7 @@ xlog_regrant_reserve_log_space(xlog_t *log,
s = GRANT_LOCK(log);
xlog_grant_sub_space(log, ticket->t_curr_res);
ticket->t_curr_res = ticket->t_unit_res;
- XLOG_TIC_RESET_RES(ticket);
+ xlog_tic_reset_res(ticket);
xlog_trace_loggrant(log, ticket,
"xlog_regrant_reserve_log_space: sub current res");
xlog_verify_grant_head(log, 1);
@@ -2731,7 +2747,7 @@ xlog_regrant_reserve_log_space(xlog_t *log,
xlog_verify_grant_head(log, 0);
GRANT_UNLOCK(log, s);
ticket->t_curr_res = ticket->t_unit_res;
- XLOG_TIC_RESET_RES(ticket);
+ xlog_tic_reset_res(ticket);
} /* xlog_regrant_reserve_log_space */
@@ -3354,7 +3370,7 @@ xlog_ticket_get(xlog_t *log,
tic->t_flags |= XLOG_TIC_PERM_RESERV;
sv_init(&(tic->t_sema), SV_DEFAULT, "logtick");
- XLOG_TIC_RESET_RES(tic);
+ xlog_tic_reset_res(tic);
return tic;
} /* xlog_ticket_get */
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
index 9bd3cdf11a87..752f964b3699 100644
--- a/fs/xfs/xfs_log_priv.h
+++ b/fs/xfs/xfs_log_priv.h
@@ -30,17 +30,16 @@ struct xfs_mount;
*/
#define XLOG_MIN_ICLOGS 2
-#define XLOG_MED_ICLOGS 4
#define XLOG_MAX_ICLOGS 8
#define XLOG_HEADER_MAGIC_NUM 0xFEEDbabe /* Invalid cycle number */
#define XLOG_VERSION_1 1
#define XLOG_VERSION_2 2 /* Large IClogs, Log sunit */
#define XLOG_VERSION_OKBITS (XLOG_VERSION_1 | XLOG_VERSION_2)
-#define XLOG_RECORD_BSIZE (16*1024) /* eventually 32k */
+#define XLOG_MIN_RECORD_BSIZE (16*1024) /* eventually 32k */
#define XLOG_BIG_RECORD_BSIZE (32*1024) /* 32k buffers */
#define XLOG_MAX_RECORD_BSIZE (256*1024)
#define XLOG_HEADER_CYCLE_SIZE (32*1024) /* cycle data in header */
-#define XLOG_RECORD_BSHIFT 14 /* 16384 == 1 << 14 */
+#define XLOG_MIN_RECORD_BSHIFT 14 /* 16384 == 1 << 14 */
#define XLOG_BIG_RECORD_BSHIFT 15 /* 32k == 1 << 15 */
#define XLOG_MAX_RECORD_BSHIFT 18 /* 256k == 1 << 18 */
#define XLOG_BTOLSUNIT(log, b) (((b)+(log)->l_mp->m_sb.sb_logsunit-1) / \
@@ -250,22 +249,6 @@ typedef __uint32_t xlog_tid_t;
/* Ticket reservation region accounting */
#define XLOG_TIC_LEN_MAX 15
-#define XLOG_TIC_RESET_RES(t) ((t)->t_res_num = \
- (t)->t_res_arr_sum = (t)->t_res_num_ophdrs = 0)
-#define XLOG_TIC_ADD_OPHDR(t) ((t)->t_res_num_ophdrs++)
-#define XLOG_TIC_ADD_REGION(t, len, type) \
- do { \
- if ((t)->t_res_num == XLOG_TIC_LEN_MAX) { \
- /* add to overflow and start again */ \
- (t)->t_res_o_flow += (t)->t_res_arr_sum; \
- (t)->t_res_num = 0; \
- (t)->t_res_arr_sum = 0; \
- } \
- (t)->t_res_arr[(t)->t_res_num].r_len = (len); \
- (t)->t_res_arr[(t)->t_res_num].r_type = (type); \
- (t)->t_res_arr_sum += (len); \
- (t)->t_res_num++; \
- } while (0)
/*
* Reservation region
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 8ae6e8e5f3db..851eca8a7150 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -2245,7 +2245,7 @@ xlog_recover_do_inode_trans(
int error;
int attr_index;
uint fields;
- xfs_dinode_core_t *dicp;
+ xfs_icdinode_t *dicp;
int need_free = 0;
if (pass == XLOG_RECOVER_PASS1) {
@@ -2309,7 +2309,7 @@ xlog_recover_do_inode_trans(
* Make sure the place we're flushing out to really looks
* like an inode!
*/
- if (unlikely(INT_GET(dip->di_core.di_magic, ARCH_CONVERT) != XFS_DINODE_MAGIC)) {
+ if (unlikely(be16_to_cpu(dip->di_core.di_magic) != XFS_DINODE_MAGIC)) {
xfs_buf_relse(bp);
xfs_fs_cmn_err(CE_ALERT, mp,
"xfs_inode_recover: Bad inode magic number, dino ptr = 0x%p, dino bp = 0x%p, ino = %Ld",
@@ -2319,7 +2319,7 @@ xlog_recover_do_inode_trans(
error = EFSCORRUPTED;
goto error;
}
- dicp = (xfs_dinode_core_t*)(item->ri_buf[1].i_addr);
+ dicp = (xfs_icdinode_t *)(item->ri_buf[1].i_addr);
if (unlikely(dicp->di_magic != XFS_DINODE_MAGIC)) {
xfs_buf_relse(bp);
xfs_fs_cmn_err(CE_ALERT, mp,
@@ -2332,15 +2332,13 @@ xlog_recover_do_inode_trans(
}
/* Skip replay when the on disk inode is newer than the log one */
- if (dicp->di_flushiter <
- INT_GET(dip->di_core.di_flushiter, ARCH_CONVERT)) {
+ if (dicp->di_flushiter < be16_to_cpu(dip->di_core.di_flushiter)) {
/*
* Deal with the wrap case, DI_MAX_FLUSH is less
* than smaller numbers
*/
- if ((INT_GET(dip->di_core.di_flushiter, ARCH_CONVERT)
- == DI_MAX_FLUSH) &&
- (dicp->di_flushiter < (DI_MAX_FLUSH>>1))) {
+ if (be16_to_cpu(dip->di_core.di_flushiter) == DI_MAX_FLUSH &&
+ dicp->di_flushiter < (DI_MAX_FLUSH >> 1)) {
/* do nothing */
} else {
xfs_buf_relse(bp);
@@ -2411,8 +2409,8 @@ xlog_recover_do_inode_trans(
}
/* The core is in in-core format */
- xfs_xlate_dinode_core((xfs_caddr_t)&dip->di_core,
- (xfs_dinode_core_t*)item->ri_buf[1].i_addr, -1);
+ xfs_dinode_to_disk(&dip->di_core,
+ (xfs_icdinode_t *)item->ri_buf[1].i_addr);
/* the rest is in on-disk format */
if (item->ri_buf[1].i_len > sizeof(xfs_dinode_core_t)) {
@@ -2424,8 +2422,7 @@ xlog_recover_do_inode_trans(
fields = in_f->ilf_fields;
switch (fields & (XFS_ILOG_DEV | XFS_ILOG_UUID)) {
case XFS_ILOG_DEV:
- INT_SET(dip->di_u.di_dev, ARCH_CONVERT, in_f->ilf_u.ilfu_rdev);
-
+ dip->di_u.di_dev = cpu_to_be32(in_f->ilf_u.ilfu_rdev);
break;
case XFS_ILOG_UUID:
dip->di_u.di_muuid = in_f->ilf_u.ilfu_uuid;
@@ -3234,8 +3231,8 @@ xlog_recover_process_iunlinks(
ASSERT(ip->i_d.di_nlink == 0);
/* setup for the next pass */
- agino = INT_GET(dip->di_next_unlinked,
- ARCH_CONVERT);
+ agino = be32_to_cpu(
+ dip->di_next_unlinked);
xfs_buf_relse(ibp);
/*
* Prevent any DMAPI event from
@@ -3837,7 +3834,10 @@ xlog_do_recover(
*/
bp = xfs_getsb(log->l_mp, 0);
XFS_BUF_UNDONE(bp);
+ ASSERT(!(XFS_BUF_ISWRITE(bp)));
+ ASSERT(!(XFS_BUF_ISDELAYWRITE(bp)));
XFS_BUF_READ(bp);
+ XFS_BUF_UNASYNC(bp);
xfsbdstrat(log->l_mp, bp);
if ((error = xfs_iowait(bp))) {
xfs_ioerror_alert("xlog_do_recover",
@@ -3849,7 +3849,7 @@ xlog_do_recover(
/* Convert superblock from on-disk format */
sbp = &log->l_mp->m_sb;
- xfs_xlatesb(XFS_BUF_TO_SBP(bp), sbp, 1, XFS_SB_ALL_BITS);
+ xfs_sb_from_disk(sbp, XFS_BUF_TO_SBP(bp));
ASSERT(sbp->sb_magicnum == XFS_SB_MAGIC);
ASSERT(XFS_SB_GOOD_VERSION(sbp));
xfs_buf_relse(bp);
@@ -4027,7 +4027,7 @@ xlog_recover_check_summary(
sbbp = xfs_getsb(mp, 0);
#ifdef XFS_LOUD_RECOVERY
sbp = &mp->m_sb;
- xfs_xlatesb(XFS_BUF_TO_SBP(sbbp), sbp, 1, XFS_SB_ALL_BITS);
+ xfs_sb_from_disk(sbp, XFS_BUF_TO_SBP(sbbp));
cmn_err(CE_NOTE,
"xlog_recover_check_summary: sb_icount %Lu itotal %Lu",
sbp->sb_icount, itotal);
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index a66b39805176..ebdb76da527c 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -139,7 +139,7 @@ xfs_mount_init(void)
AIL_LOCKINIT(&mp->m_ail_lock, "xfs_ail");
spinlock_init(&mp->m_sb_lock, "xfs_sb");
mutex_init(&mp->m_ilock);
- initnsema(&mp->m_growlock, 1, "xfs_grow");
+ mutex_init(&mp->m_growlock);
/*
* Initialize the AIL.
*/
@@ -157,14 +157,8 @@ xfs_mount_init(void)
*/
void
xfs_mount_free(
- xfs_mount_t *mp,
- int remove_bhv)
+ xfs_mount_t *mp)
{
- if (mp->m_ihash)
- xfs_ihash_free(mp);
- if (mp->m_chash)
- xfs_chash_free(mp);
-
if (mp->m_perag) {
int agno;
@@ -180,7 +174,7 @@ xfs_mount_free(
AIL_LOCK_DESTROY(&mp->m_ail_lock);
spinlock_destroy(&mp->m_sb_lock);
mutex_destroy(&mp->m_ilock);
- freesema(&mp->m_growlock);
+ mutex_destroy(&mp->m_growlock);
if (mp->m_quotainfo)
XFS_QM_DONE(mp);
@@ -191,15 +185,7 @@ xfs_mount_free(
if (mp->m_logname != NULL)
kmem_free(mp->m_logname, strlen(mp->m_logname) + 1);
- if (remove_bhv) {
- struct bhv_vfs *vfsp = XFS_MTOVFS(mp);
-
- bhv_remove_all_vfsops(vfsp, 0);
- VFS_REMOVEBHV(vfsp, &mp->m_bhv);
- }
-
xfs_icsb_destroy_counters(mp);
- kmem_free(mp, sizeof(xfs_mount_t));
}
/*
@@ -342,9 +328,19 @@ xfs_mount_validate_sb(
return 0;
}
+STATIC void
+xfs_initialize_perag_icache(
+ xfs_perag_t *pag)
+{
+ if (!pag->pag_ici_init) {
+ rwlock_init(&pag->pag_ici_lock);
+ INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC);
+ pag->pag_ici_init = 1;
+ }
+}
+
xfs_agnumber_t
xfs_initialize_perag(
- bhv_vfs_t *vfs,
xfs_mount_t *mp,
xfs_agnumber_t agcount)
{
@@ -362,7 +358,7 @@ xfs_initialize_perag(
/* Clear the mount flag if no inode can overflow 32 bits
* on this filesystem, or if specifically requested..
*/
- if ((vfs->vfs_flag & VFS_32BITINODES) && ino > max_inum) {
+ if ((mp->m_flags & XFS_MOUNT_SMALL_INUMS) && ino > max_inum) {
mp->m_flags |= XFS_MOUNT_32BITINODES;
} else {
mp->m_flags &= ~XFS_MOUNT_32BITINODES;
@@ -396,48 +392,92 @@ xfs_initialize_perag(
pag->pagi_inodeok = 1;
if (index < max_metadata)
pag->pagf_metadata = 1;
+ xfs_initialize_perag_icache(pag);
}
} else {
/* Setup default behavior for smaller filesystems */
for (index = 0; index < agcount; index++) {
pag = &mp->m_perag[index];
pag->pagi_inodeok = 1;
+ xfs_initialize_perag_icache(pag);
}
}
return index;
}
+void
+xfs_sb_from_disk(
+ xfs_sb_t *to,
+ xfs_dsb_t *from)
+{
+ to->sb_magicnum = be32_to_cpu(from->sb_magicnum);
+ to->sb_blocksize = be32_to_cpu(from->sb_blocksize);
+ to->sb_dblocks = be64_to_cpu(from->sb_dblocks);
+ to->sb_rblocks = be64_to_cpu(from->sb_rblocks);
+ to->sb_rextents = be64_to_cpu(from->sb_rextents);
+ memcpy(&to->sb_uuid, &from->sb_uuid, sizeof(to->sb_uuid));
+ to->sb_logstart = be64_to_cpu(from->sb_logstart);
+ to->sb_rootino = be64_to_cpu(from->sb_rootino);
+ to->sb_rbmino = be64_to_cpu(from->sb_rbmino);
+ to->sb_rsumino = be64_to_cpu(from->sb_rsumino);
+ to->sb_rextsize = be32_to_cpu(from->sb_rextsize);
+ to->sb_agblocks = be32_to_cpu(from->sb_agblocks);
+ to->sb_agcount = be32_to_cpu(from->sb_agcount);
+ to->sb_rbmblocks = be32_to_cpu(from->sb_rbmblocks);
+ to->sb_logblocks = be32_to_cpu(from->sb_logblocks);
+ to->sb_versionnum = be16_to_cpu(from->sb_versionnum);
+ to->sb_sectsize = be16_to_cpu(from->sb_sectsize);
+ to->sb_inodesize = be16_to_cpu(from->sb_inodesize);
+ to->sb_inopblock = be16_to_cpu(from->sb_inopblock);
+ memcpy(&to->sb_fname, &from->sb_fname, sizeof(to->sb_fname));
+ to->sb_blocklog = from->sb_blocklog;
+ to->sb_sectlog = from->sb_sectlog;
+ to->sb_inodelog = from->sb_inodelog;
+ to->sb_inopblog = from->sb_inopblog;
+ to->sb_agblklog = from->sb_agblklog;
+ to->sb_rextslog = from->sb_rextslog;
+ to->sb_inprogress = from->sb_inprogress;
+ to->sb_imax_pct = from->sb_imax_pct;
+ to->sb_icount = be64_to_cpu(from->sb_icount);
+ to->sb_ifree = be64_to_cpu(from->sb_ifree);
+ to->sb_fdblocks = be64_to_cpu(from->sb_fdblocks);
+ to->sb_frextents = be64_to_cpu(from->sb_frextents);
+ to->sb_uquotino = be64_to_cpu(from->sb_uquotino);
+ to->sb_gquotino = be64_to_cpu(from->sb_gquotino);
+ to->sb_qflags = be16_to_cpu(from->sb_qflags);
+ to->sb_flags = from->sb_flags;
+ to->sb_shared_vn = from->sb_shared_vn;
+ to->sb_inoalignmt = be32_to_cpu(from->sb_inoalignmt);
+ to->sb_unit = be32_to_cpu(from->sb_unit);
+ to->sb_width = be32_to_cpu(from->sb_width);
+ to->sb_dirblklog = from->sb_dirblklog;
+ to->sb_logsectlog = from->sb_logsectlog;
+ to->sb_logsectsize = be16_to_cpu(from->sb_logsectsize);
+ to->sb_logsunit = be32_to_cpu(from->sb_logsunit);
+ to->sb_features2 = be32_to_cpu(from->sb_features2);
+}
+
/*
- * xfs_xlatesb
+ * Copy in core superblock to ondisk one.
*
- * data - on disk version of sb
- * sb - a superblock
- * dir - conversion direction: <0 - convert sb to buf
- * >0 - convert buf to sb
- * fields - which fields to copy (bitmask)
+ * The fields argument is mask of superblock fields to copy.
*/
void
-xfs_xlatesb(
- void *data,
- xfs_sb_t *sb,
- int dir,
+xfs_sb_to_disk(
+ xfs_dsb_t *to,
+ xfs_sb_t *from,
__int64_t fields)
{
- xfs_caddr_t buf_ptr;
- xfs_caddr_t mem_ptr;
+ xfs_caddr_t to_ptr = (xfs_caddr_t)to;
+ xfs_caddr_t from_ptr = (xfs_caddr_t)from;
xfs_sb_field_t f;
int first;
int size;
- ASSERT(dir);
ASSERT(fields);
-
if (!fields)
return;
- buf_ptr = (xfs_caddr_t)data;
- mem_ptr = (xfs_caddr_t)sb;
-
while (fields) {
f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields);
first = xfs_sb_info[f].offset;
@@ -446,26 +486,20 @@ xfs_xlatesb(
ASSERT(xfs_sb_info[f].type == 0 || xfs_sb_info[f].type == 1);
if (size == 1 || xfs_sb_info[f].type == 1) {
- if (dir > 0) {
- memcpy(mem_ptr + first, buf_ptr + first, size);
- } else {
- memcpy(buf_ptr + first, mem_ptr + first, size);
- }
+ memcpy(to_ptr + first, from_ptr + first, size);
} else {
switch (size) {
case 2:
- INT_XLATE(*(__uint16_t*)(buf_ptr+first),
- *(__uint16_t*)(mem_ptr+first),
- dir, ARCH_CONVERT);
+ *(__be16 *)(to_ptr + first) =
+ cpu_to_be16(*(__u16 *)(from_ptr + first));
break;
case 4:
- INT_XLATE(*(__uint32_t*)(buf_ptr+first),
- *(__uint32_t*)(mem_ptr+first),
- dir, ARCH_CONVERT);
+ *(__be32 *)(to_ptr + first) =
+ cpu_to_be32(*(__u32 *)(from_ptr + first));
break;
case 8:
- INT_XLATE(*(__uint64_t*)(buf_ptr+first),
- *(__uint64_t*)(mem_ptr+first), dir, ARCH_CONVERT);
+ *(__be64 *)(to_ptr + first) =
+ cpu_to_be64(*(__u64 *)(from_ptr + first));
break;
default:
ASSERT(0);
@@ -487,7 +521,6 @@ xfs_readsb(xfs_mount_t *mp, int flags)
unsigned int sector_size;
unsigned int extra_flags;
xfs_buf_t *bp;
- xfs_sb_t *sbp;
int error;
ASSERT(mp->m_sb_bp == NULL);
@@ -515,8 +548,7 @@ xfs_readsb(xfs_mount_t *mp, int flags)
* Initialize the mount structure from the superblock.
* But first do some basic consistency checking.
*/
- sbp = XFS_BUF_TO_SBP(bp);
- xfs_xlatesb(XFS_BUF_PTR(bp), &(mp->m_sb), 1, XFS_SB_ALL_BITS);
+ xfs_sb_from_disk(&mp->m_sb, XFS_BUF_TO_SBP(bp));
error = xfs_mount_validate_sb(mp, &(mp->m_sb), flags);
if (error) {
@@ -715,7 +747,6 @@ xfs_initialize_perag_data(xfs_mount_t *mp, xfs_agnumber_t agcount)
*/
int
xfs_mountfs(
- bhv_vfs_t *vfsp,
xfs_mount_t *mp,
int mfsi_flags)
{
@@ -842,14 +873,11 @@ xfs_mountfs(
*/
if ((mfsi_flags & XFS_MFSI_SECOND) == 0 &&
(mp->m_flags & XFS_MOUNT_NOUUID) == 0) {
- __uint64_t ret64;
if (xfs_uuid_mount(mp)) {
error = XFS_ERROR(EINVAL);
goto error1;
}
uuid_mounted=1;
- ret64 = uuid_hash64(&sbp->sb_uuid);
- memcpy(&vfsp->vfs_fsid, &ret64, sizeof(ret64));
}
/*
@@ -871,16 +899,6 @@ xfs_mountfs(
writeio_log = mp->m_writeio_log;
}
- /*
- * Set the number of readahead buffers to use based on
- * physical memory size.
- */
- if (xfs_physmem <= 4096) /* <= 16MB */
- mp->m_nreadaheads = XFS_RW_NREADAHEAD_16MB;
- else if (xfs_physmem <= 8192) /* <= 32MB */
- mp->m_nreadaheads = XFS_RW_NREADAHEAD_32MB;
- else
- mp->m_nreadaheads = XFS_RW_NREADAHEAD_K32;
if (sbp->sb_blocklog > readio_log) {
mp->m_readio_log = sbp->sb_blocklog;
} else {
@@ -895,15 +913,12 @@ xfs_mountfs(
mp->m_writeio_blocks = 1 << (mp->m_writeio_log - sbp->sb_blocklog);
/*
- * Set the inode cluster size based on the physical memory
- * size. This may still be overridden by the file system
+ * Set the inode cluster size.
+ * This may still be overridden by the file system
* block size if it is larger than the chosen cluster size.
*/
- if (xfs_physmem <= btoc(32 * 1024 * 1024)) { /* <= 32 MB */
- mp->m_inode_cluster_size = XFS_INODE_SMALL_CLUSTER_SIZE;
- } else {
- mp->m_inode_cluster_size = XFS_INODE_BIG_CLUSTER_SIZE;
- }
+ mp->m_inode_cluster_size = XFS_INODE_BIG_CLUSTER_SIZE;
+
/*
* Set whether we're using inode alignment.
*/
@@ -987,16 +1002,6 @@ xfs_mountfs(
*/
uuid_getnodeuniq(&sbp->sb_uuid, mp->m_fixedfsid);
- /*
- * The vfs structure needs to have a file system independent
- * way of checking for the invariant file system ID. Since it
- * can't look at mount structures it has a pointer to the data
- * in the mount structure.
- *
- * File systems that don't support user level file handles (i.e.
- * all of them except for XFS) will leave vfs_altfsid as NULL.
- */
- vfsp->vfs_altfsid = (xfs_fsid_t *)mp->m_fixedfsid;
mp->m_dmevmask = 0; /* not persistent; set after each mount */
xfs_dir_mount(mp);
@@ -1012,20 +1017,13 @@ xfs_mountfs(
xfs_trans_init(mp);
/*
- * Allocate and initialize the inode hash table for this
- * file system.
- */
- xfs_ihash_init(mp);
- xfs_chash_init(mp);
-
- /*
* Allocate and initialize the per-ag data.
*/
init_rwsem(&mp->m_peraglock);
mp->m_perag =
kmem_zalloc(sbp->sb_agcount * sizeof(xfs_perag_t), KM_SLEEP);
- mp->m_maxagi = xfs_initialize_perag(vfsp, mp, sbp->sb_agcount);
+ mp->m_maxagi = xfs_initialize_perag(mp, sbp->sb_agcount);
/*
* log's mount-time initialization. Perform 1st part recovery if needed
@@ -1116,7 +1114,7 @@ xfs_mountfs(
* If fs is not mounted readonly, then update the superblock
* unit and width changes.
*/
- if (update_flags && !(vfsp->vfs_flag & VFS_RDONLY))
+ if (update_flags && !(mp->m_flags & XFS_MOUNT_RDONLY))
xfs_mount_log_sbunit(mp, update_flags);
/*
@@ -1169,8 +1167,6 @@ xfs_mountfs(
error3:
xfs_log_unmount_dealloc(mp);
error2:
- xfs_ihash_free(mp);
- xfs_chash_free(mp);
for (agno = 0; agno < sbp->sb_agcount; agno++)
if (mp->m_perag[agno].pagb_list)
kmem_free(mp->m_perag[agno].pagb_list,
@@ -1194,10 +1190,6 @@ xfs_mountfs(
int
xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
{
- struct bhv_vfs *vfsp = XFS_MTOVFS(mp);
-#if defined(DEBUG) || defined(INDUCE_IO_ERROR)
- int64_t fsid;
-#endif
__uint64_t resblks;
/*
@@ -1261,21 +1253,17 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
xfs_uuid_unmount(mp);
#if defined(DEBUG) || defined(INDUCE_IO_ERROR)
- /*
- * clear all error tags on this filesystem
- */
- memcpy(&fsid, &vfsp->vfs_fsid, sizeof(int64_t));
- xfs_errortag_clearall_umount(fsid, mp->m_fsname, 0);
+ xfs_errortag_clearall(mp, 0);
#endif
- XFS_IODONE(vfsp);
- xfs_mount_free(mp, 1);
+ XFS_IODONE(mp);
+ xfs_mount_free(mp);
return 0;
}
void
xfs_unmountfs_close(xfs_mount_t *mp, struct cred *cr)
{
- if (mp->m_logdev_targp != mp->m_ddev_targp)
+ if (mp->m_logdev_targp && mp->m_logdev_targp != mp->m_ddev_targp)
xfs_free_buftarg(mp->m_logdev_targp, 1);
if (mp->m_rtdev_targp)
xfs_free_buftarg(mp->m_rtdev_targp, 1);
@@ -1295,10 +1283,8 @@ xfs_unmountfs_wait(xfs_mount_t *mp)
int
xfs_fs_writable(xfs_mount_t *mp)
{
- bhv_vfs_t *vfsp = XFS_MTOVFS(mp);
-
- return !(vfs_test_for_freeze(vfsp) || XFS_FORCED_SHUTDOWN(mp) ||
- (vfsp->vfs_flag & VFS_RDONLY));
+ return !(xfs_test_for_freeze(mp) || XFS_FORCED_SHUTDOWN(mp) ||
+ (mp->m_flags & XFS_MOUNT_RDONLY));
}
/*
@@ -1348,34 +1334,44 @@ xfs_log_sbcount(
return 0;
}
+STATIC void
+xfs_mark_shared_ro(
+ xfs_mount_t *mp,
+ xfs_buf_t *bp)
+{
+ xfs_dsb_t *sb = XFS_BUF_TO_SBP(bp);
+ __uint16_t version;
+
+ if (!(sb->sb_flags & XFS_SBF_READONLY))
+ sb->sb_flags |= XFS_SBF_READONLY;
+
+ version = be16_to_cpu(sb->sb_versionnum);
+ if ((version & XFS_SB_VERSION_NUMBITS) != XFS_SB_VERSION_4 ||
+ !(version & XFS_SB_VERSION_SHAREDBIT))
+ version |= XFS_SB_VERSION_SHAREDBIT;
+ sb->sb_versionnum = cpu_to_be16(version);
+}
+
int
xfs_unmountfs_writesb(xfs_mount_t *mp)
{
xfs_buf_t *sbp;
- xfs_sb_t *sb;
int error = 0;
/*
* skip superblock write if fs is read-only, or
* if we are doing a forced umount.
*/
- if (!(XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY ||
+ if (!((mp->m_flags & XFS_MOUNT_RDONLY) ||
XFS_FORCED_SHUTDOWN(mp))) {
sbp = xfs_getsb(mp, 0);
- sb = XFS_BUF_TO_SBP(sbp);
/*
* mark shared-readonly if desired
*/
- if (mp->m_mk_sharedro) {
- if (!(sb->sb_flags & XFS_SBF_READONLY))
- sb->sb_flags |= XFS_SBF_READONLY;
- if (!XFS_SB_VERSION_HASSHARED(sb))
- XFS_SB_VERSION_ADDSHARED(sb);
- xfs_fs_cmn_err(CE_NOTE, mp,
- "Unmounting, marking shared read-only");
- }
+ if (mp->m_mk_sharedro)
+ xfs_mark_shared_ro(mp, sbp);
XFS_BUF_UNDONE(sbp);
XFS_BUF_UNREAD(sbp);
@@ -1410,7 +1406,6 @@ xfs_mod_sb(xfs_trans_t *tp, __int64_t fields)
int first;
int last;
xfs_mount_t *mp;
- xfs_sb_t *sbp;
xfs_sb_field_t f;
ASSERT(fields);
@@ -1418,13 +1413,12 @@ xfs_mod_sb(xfs_trans_t *tp, __int64_t fields)
return;
mp = tp->t_mountp;
bp = xfs_trans_getsb(tp, mp, 0);
- sbp = XFS_BUF_TO_SBP(bp);
first = sizeof(xfs_sb_t);
last = 0;
/* translate/copy */
- xfs_xlatesb(XFS_BUF_PTR(bp), &(mp->m_sb), -1, fields);
+ xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb, fields);
/* find modified range */
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 76ad74758696..c618f7cb5f0e 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -54,13 +54,8 @@ typedef struct xfs_trans_reservations {
#else
struct cred;
struct log;
-struct bhv_vfs;
-struct bhv_vnode;
struct xfs_mount_args;
-struct xfs_ihash;
-struct xfs_chash;
struct xfs_inode;
-struct xfs_perag;
struct xfs_iocore;
struct xfs_bmbt_irec;
struct xfs_bmap_free;
@@ -68,9 +63,6 @@ struct xfs_extdelta;
struct xfs_swapext;
struct xfs_mru_cache;
-extern struct bhv_vfsops xfs_vfsops;
-extern struct bhv_vnodeops xfs_vnodeops;
-
#define AIL_LOCK_T lock_t
#define AIL_LOCKINIT(x,y) spinlock_init(x,y)
#define AIL_LOCK_DESTROY(x) spinlock_destroy(x)
@@ -82,15 +74,17 @@ extern struct bhv_vnodeops xfs_vnodeops;
* Prototypes and functions for the Data Migration subsystem.
*/
-typedef int (*xfs_send_data_t)(int, struct bhv_vnode *,
+typedef int (*xfs_send_data_t)(int, bhv_vnode_t *,
xfs_off_t, size_t, int, bhv_vrwlock_t *);
typedef int (*xfs_send_mmap_t)(struct vm_area_struct *, uint);
-typedef int (*xfs_send_destroy_t)(struct bhv_vnode *, dm_right_t);
-typedef int (*xfs_send_namesp_t)(dm_eventtype_t, struct bhv_vfs *,
- struct bhv_vnode *,
- dm_right_t, struct bhv_vnode *, dm_right_t,
+typedef int (*xfs_send_destroy_t)(bhv_vnode_t *, dm_right_t);
+typedef int (*xfs_send_namesp_t)(dm_eventtype_t, struct xfs_mount *,
+ bhv_vnode_t *,
+ dm_right_t, bhv_vnode_t *, dm_right_t,
char *, char *, mode_t, int, int);
-typedef void (*xfs_send_unmount_t)(struct bhv_vfs *, struct bhv_vnode *,
+typedef int (*xfs_send_mount_t)(struct xfs_mount *, dm_right_t,
+ char *, char *);
+typedef void (*xfs_send_unmount_t)(struct xfs_mount *, bhv_vnode_t *,
dm_right_t, mode_t, int, int);
typedef struct xfs_dmops {
@@ -98,21 +92,24 @@ typedef struct xfs_dmops {
xfs_send_mmap_t xfs_send_mmap;
xfs_send_destroy_t xfs_send_destroy;
xfs_send_namesp_t xfs_send_namesp;
+ xfs_send_mount_t xfs_send_mount;
xfs_send_unmount_t xfs_send_unmount;
} xfs_dmops_t;
#define XFS_SEND_DATA(mp, ev,vp,off,len,fl,lock) \
- (*(mp)->m_dm_ops.xfs_send_data)(ev,vp,off,len,fl,lock)
+ (*(mp)->m_dm_ops->xfs_send_data)(ev,vp,off,len,fl,lock)
#define XFS_SEND_MMAP(mp, vma,fl) \
- (*(mp)->m_dm_ops.xfs_send_mmap)(vma,fl)
+ (*(mp)->m_dm_ops->xfs_send_mmap)(vma,fl)
#define XFS_SEND_DESTROY(mp, vp,right) \
- (*(mp)->m_dm_ops.xfs_send_destroy)(vp,right)
+ (*(mp)->m_dm_ops->xfs_send_destroy)(vp,right)
#define XFS_SEND_NAMESP(mp, ev,b1,r1,b2,r2,n1,n2,mode,rval,fl) \
- (*(mp)->m_dm_ops.xfs_send_namesp)(ev,NULL,b1,r1,b2,r2,n1,n2,mode,rval,fl)
-#define XFS_SEND_PREUNMOUNT(mp, vfs,b1,r1,b2,r2,n1,n2,mode,rval,fl) \
- (*(mp)->m_dm_ops.xfs_send_namesp)(DM_EVENT_PREUNMOUNT,vfs,b1,r1,b2,r2,n1,n2,mode,rval,fl)
-#define XFS_SEND_UNMOUNT(mp, vfsp,vp,right,mode,rval,fl) \
- (*(mp)->m_dm_ops.xfs_send_unmount)(vfsp,vp,right,mode,rval,fl)
+ (*(mp)->m_dm_ops->xfs_send_namesp)(ev,NULL,b1,r1,b2,r2,n1,n2,mode,rval,fl)
+#define XFS_SEND_PREUNMOUNT(mp,b1,r1,b2,r2,n1,n2,mode,rval,fl) \
+ (*(mp)->m_dm_ops->xfs_send_namesp)(DM_EVENT_PREUNMOUNT,mp,b1,r1,b2,r2,n1,n2,mode,rval,fl)
+#define XFS_SEND_MOUNT(mp,right,path,name) \
+ (*(mp)->m_dm_ops->xfs_send_mount)(mp,right,path,name)
+#define XFS_SEND_UNMOUNT(mp, vp,right,mode,rval,fl) \
+ (*(mp)->m_dm_ops->xfs_send_unmount)(mp,vp,right,mode,rval,fl)
/*
@@ -142,6 +139,9 @@ typedef struct xfs_dquot * (*xfs_dqvopchown_t)(
struct xfs_dquot **, struct xfs_dquot *);
typedef int (*xfs_dqvopchownresv_t)(struct xfs_trans *, struct xfs_inode *,
struct xfs_dquot *, struct xfs_dquot *, uint);
+typedef void (*xfs_dqstatvfs_t)(struct xfs_inode *, bhv_statvfs_t *);
+typedef int (*xfs_dqsync_t)(struct xfs_mount *, int flags);
+typedef int (*xfs_quotactl_t)(struct xfs_mount *, int, int, xfs_caddr_t);
typedef struct xfs_qmops {
xfs_qminit_t xfs_qminit;
@@ -157,42 +157,51 @@ typedef struct xfs_qmops {
xfs_dqvoprename_t xfs_dqvoprename;
xfs_dqvopchown_t xfs_dqvopchown;
xfs_dqvopchownresv_t xfs_dqvopchownresv;
+ xfs_dqstatvfs_t xfs_dqstatvfs;
+ xfs_dqsync_t xfs_dqsync;
+ xfs_quotactl_t xfs_quotactl;
struct xfs_dqtrxops *xfs_dqtrxops;
} xfs_qmops_t;
#define XFS_QM_INIT(mp, mnt, fl) \
- (*(mp)->m_qm_ops.xfs_qminit)(mp, mnt, fl)
+ (*(mp)->m_qm_ops->xfs_qminit)(mp, mnt, fl)
#define XFS_QM_MOUNT(mp, mnt, fl, mfsi_flags) \
- (*(mp)->m_qm_ops.xfs_qmmount)(mp, mnt, fl, mfsi_flags)
+ (*(mp)->m_qm_ops->xfs_qmmount)(mp, mnt, fl, mfsi_flags)
#define XFS_QM_UNMOUNT(mp) \
- (*(mp)->m_qm_ops.xfs_qmunmount)(mp)
+ (*(mp)->m_qm_ops->xfs_qmunmount)(mp)
#define XFS_QM_DONE(mp) \
- (*(mp)->m_qm_ops.xfs_qmdone)(mp)
+ (*(mp)->m_qm_ops->xfs_qmdone)(mp)
#define XFS_QM_DQRELE(mp, dq) \
- (*(mp)->m_qm_ops.xfs_dqrele)(dq)
+ (*(mp)->m_qm_ops->xfs_dqrele)(dq)
#define XFS_QM_DQATTACH(mp, ip, fl) \
- (*(mp)->m_qm_ops.xfs_dqattach)(ip, fl)
+ (*(mp)->m_qm_ops->xfs_dqattach)(ip, fl)
#define XFS_QM_DQDETACH(mp, ip) \
- (*(mp)->m_qm_ops.xfs_dqdetach)(ip)
+ (*(mp)->m_qm_ops->xfs_dqdetach)(ip)
#define XFS_QM_DQPURGEALL(mp, fl) \
- (*(mp)->m_qm_ops.xfs_dqpurgeall)(mp, fl)
+ (*(mp)->m_qm_ops->xfs_dqpurgeall)(mp, fl)
#define XFS_QM_DQVOPALLOC(mp, ip, uid, gid, prid, fl, dq1, dq2) \
- (*(mp)->m_qm_ops.xfs_dqvopalloc)(mp, ip, uid, gid, prid, fl, dq1, dq2)
+ (*(mp)->m_qm_ops->xfs_dqvopalloc)(mp, ip, uid, gid, prid, fl, dq1, dq2)
#define XFS_QM_DQVOPCREATE(mp, tp, ip, dq1, dq2) \
- (*(mp)->m_qm_ops.xfs_dqvopcreate)(tp, ip, dq1, dq2)
+ (*(mp)->m_qm_ops->xfs_dqvopcreate)(tp, ip, dq1, dq2)
#define XFS_QM_DQVOPRENAME(mp, ip) \
- (*(mp)->m_qm_ops.xfs_dqvoprename)(ip)
+ (*(mp)->m_qm_ops->xfs_dqvoprename)(ip)
#define XFS_QM_DQVOPCHOWN(mp, tp, ip, dqp, dq) \
- (*(mp)->m_qm_ops.xfs_dqvopchown)(tp, ip, dqp, dq)
+ (*(mp)->m_qm_ops->xfs_dqvopchown)(tp, ip, dqp, dq)
#define XFS_QM_DQVOPCHOWNRESV(mp, tp, ip, dq1, dq2, fl) \
- (*(mp)->m_qm_ops.xfs_dqvopchownresv)(tp, ip, dq1, dq2, fl)
+ (*(mp)->m_qm_ops->xfs_dqvopchownresv)(tp, ip, dq1, dq2, fl)
+#define XFS_QM_DQSTATVFS(ip, statp) \
+ (*(ip)->i_mount->m_qm_ops->xfs_dqstatvfs)(ip, statp)
+#define XFS_QM_DQSYNC(mp, flags) \
+ (*(mp)->m_qm_ops->xfs_dqsync)(mp, flags)
+#define XFS_QM_QUOTACTL(mp, cmd, id, addr) \
+ (*(mp)->m_qm_ops->xfs_quotactl)(mp, cmd, id, addr)
/*
* Prototypes and functions for I/O core modularization.
*/
-typedef int (*xfs_ioinit_t)(struct bhv_vfs *,
+typedef int (*xfs_ioinit_t)(struct xfs_mount *,
struct xfs_mount_args *, int);
typedef int (*xfs_bmapi_t)(struct xfs_trans *, void *,
xfs_fileoff_t, xfs_filblks_t, int,
@@ -222,7 +231,7 @@ typedef void (*xfs_lock_demote_t)(void *, uint);
typedef int (*xfs_lock_nowait_t)(void *, uint);
typedef void (*xfs_unlk_t)(void *, unsigned int);
typedef xfs_fsize_t (*xfs_size_t)(void *);
-typedef xfs_fsize_t (*xfs_iodone_t)(struct bhv_vfs *);
+typedef xfs_fsize_t (*xfs_iodone_t)(struct xfs_mount *);
typedef int (*xfs_swap_extents_t)(void *, void *,
struct xfs_swapext*);
@@ -245,8 +254,8 @@ typedef struct xfs_ioops {
xfs_swap_extents_t xfs_swap_extents_func;
} xfs_ioops_t;
-#define XFS_IOINIT(vfsp, args, flags) \
- (*(mp)->m_io_ops.xfs_ioinit)(vfsp, args, flags)
+#define XFS_IOINIT(mp, args, flags) \
+ (*(mp)->m_io_ops.xfs_ioinit)(mp, args, flags)
#define XFS_BMAPI(mp, trans,io,bno,len,f,first,tot,mval,nmap,flist,delta) \
(*(mp)->m_io_ops.xfs_bmapi_func) \
(trans,(io)->io_obj,bno,len,f,first,tot,mval,nmap,flist,delta)
@@ -280,8 +289,8 @@ typedef struct xfs_ioops {
(*(mp)->m_io_ops.xfs_ilock_demote)((io)->io_obj, mode)
#define XFS_SIZE(mp, io) \
(*(mp)->m_io_ops.xfs_size_func)((io)->io_obj)
-#define XFS_IODONE(vfsp) \
- (*(mp)->m_io_ops.xfs_iodone)(vfsp)
+#define XFS_IODONE(mp) \
+ (*(mp)->m_io_ops.xfs_iodone)(mp)
#define XFS_SWAP_EXTENTS(mp, io, tio, sxp) \
(*(mp)->m_io_ops.xfs_swap_extents_func) \
((io)->io_obj, (tio)->io_obj, sxp)
@@ -318,7 +327,7 @@ extern void xfs_icsb_sync_counters_flags(struct xfs_mount *, int);
#endif
typedef struct xfs_mount {
- bhv_desc_t m_bhv; /* vfs xfs behavior */
+ struct super_block *m_super;
xfs_tid_t m_tid; /* next unused tid for fs */
AIL_LOCK_T m_ail_lock; /* fs AIL mutex */
xfs_ail_entry_t m_ail; /* fs active log item list */
@@ -335,8 +344,6 @@ typedef struct xfs_mount {
xfs_agnumber_t m_agirotor; /* last ag dir inode alloced */
lock_t m_agirotor_lock;/* .. and lock protecting it */
xfs_agnumber_t m_maxagi; /* highest inode alloc group */
- size_t m_ihsize; /* size of next field */
- struct xfs_ihash *m_ihash; /* fs private inode hash table*/
struct xfs_inode *m_inodes; /* active inode list */
struct list_head m_del_inodes; /* inodes to reclaim */
mutex_t m_ilock; /* inode list mutex */
@@ -362,7 +369,6 @@ typedef struct xfs_mount {
__uint8_t m_blkbb_log; /* blocklog - BBSHIFT */
__uint8_t m_agno_log; /* log #ag's */
__uint8_t m_agino_log; /* #bits for agino in inum */
- __uint8_t m_nreadaheads; /* #readahead buffers */
__uint16_t m_inode_cluster_size;/* min inode buf size */
uint m_blockmask; /* sb_blocksize-1 */
uint m_blockwsize; /* sb_blocksize in words */
@@ -378,7 +384,7 @@ typedef struct xfs_mount {
uint m_in_maxlevels; /* XFS_IN_MAXLEVELS */
struct xfs_perag *m_perag; /* per-ag accounting info */
struct rw_semaphore m_peraglock; /* lock for m_perag (pointer) */
- sema_t m_growlock; /* growfs mutex */
+ struct mutex m_growlock; /* growfs mutex */
int m_fixedfsid[2]; /* unchanged for life of FS */
uint m_dmevmask; /* DMI events for this FS */
__uint64_t m_flags; /* global mount flags */
@@ -415,8 +421,8 @@ typedef struct xfs_mount {
uint m_chsize; /* size of next field */
struct xfs_chash *m_chash; /* fs private inode per-cluster
* hash table */
- struct xfs_dmops m_dm_ops; /* vector of DMI ops */
- struct xfs_qmops m_qm_ops; /* vector of XQM ops */
+ struct xfs_dmops *m_dm_ops; /* vector of DMI ops */
+ struct xfs_qmops *m_qm_ops; /* vector of XQM ops */
struct xfs_ioops m_io_ops; /* vector of I/O ops */
atomic_t m_active_trans; /* number trans frozen */
#ifdef HAVE_PERCPU_SB
@@ -426,6 +432,12 @@ typedef struct xfs_mount {
struct mutex m_icsb_mutex; /* balancer sync lock */
#endif
struct xfs_mru_cache *m_filestream; /* per-mount filestream data */
+ struct task_struct *m_sync_task; /* generalised sync thread */
+ bhv_vfs_sync_work_t m_sync_work; /* work item for VFS_SYNC */
+ struct list_head m_sync_list; /* sync thread work item list */
+ spinlock_t m_sync_lock; /* work item list lock */
+ int m_sync_seq; /* sync thread generation no. */
+ wait_queue_head_t m_wait_single_sync_task;
} xfs_mount_t;
/*
@@ -435,7 +447,7 @@ typedef struct xfs_mount {
must be synchronous except
for space allocations */
#define XFS_MOUNT_INO64 (1ULL << 1)
- /* (1ULL << 2) -- currently unused */
+#define XFS_MOUNT_DMAPI (1ULL << 2) /* dmapi is enabled */
#define XFS_MOUNT_WAS_CLEAN (1ULL << 3)
#define XFS_MOUNT_FS_SHUTDOWN (1ULL << 4) /* atomic stop of all filesystem
operations, typically for
@@ -445,7 +457,7 @@ typedef struct xfs_mount {
#define XFS_MOUNT_NOALIGN (1ULL << 7) /* turn off stripe alignment
allocations */
#define XFS_MOUNT_ATTR2 (1ULL << 8) /* allow use of attr2 format */
- /* (1ULL << 9) -- currently unused */
+#define XFS_MOUNT_GRPID (1ULL << 9) /* group-ID assigned from directory */
#define XFS_MOUNT_NORECOVERY (1ULL << 10) /* no recovery - dirty fs */
#define XFS_MOUNT_SHARED (1ULL << 11) /* shared mount */
#define XFS_MOUNT_DFLT_IOSIZE (1ULL << 12) /* set default i/o size */
@@ -453,13 +465,13 @@ typedef struct xfs_mount {
/* osyncisdsync is now default*/
#define XFS_MOUNT_32BITINODES (1ULL << 14) /* do not create inodes above
* 32 bits in size */
- /* (1ULL << 15) -- currently unused */
+#define XFS_MOUNT_SMALL_INUMS (1ULL << 15) /* users wants 32bit inodes */
#define XFS_MOUNT_NOUUID (1ULL << 16) /* ignore uuid during mount */
#define XFS_MOUNT_BARRIER (1ULL << 17)
#define XFS_MOUNT_IDELETE (1ULL << 18) /* delete empty inode clusters*/
#define XFS_MOUNT_SWALLOC (1ULL << 19) /* turn on stripe width
* allocation */
-#define XFS_MOUNT_IHASHSIZE (1ULL << 20) /* inode hash table size */
+#define XFS_MOUNT_RDONLY (1ULL << 20) /* read-only fs */
#define XFS_MOUNT_DIRSYNC (1ULL << 21) /* synchronous directory ops */
#define XFS_MOUNT_COMPAT_IOSIZE (1ULL << 22) /* don't report large preferred
* I/O size in stat() */
@@ -518,8 +530,10 @@ xfs_preferred_iosize(xfs_mount_t *mp)
#define XFS_LAST_UNMOUNT_WAS_CLEAN(mp) \
((mp)->m_flags & XFS_MOUNT_WAS_CLEAN)
#define XFS_FORCED_SHUTDOWN(mp) ((mp)->m_flags & XFS_MOUNT_FS_SHUTDOWN)
+void xfs_do_force_shutdown(struct xfs_mount *mp, int flags, char *fname,
+ int lnnum);
#define xfs_force_shutdown(m,f) \
- bhv_vfs_force_shutdown((XFS_MTOVFS(m)), f, __FILE__, __LINE__)
+ xfs_do_force_shutdown(m, f, __FILE__, __LINE__)
/*
* Flags for xfs_mountfs
@@ -533,28 +547,6 @@ xfs_preferred_iosize(xfs_mount_t *mp)
/* XFS_MFSI_CONVERT_SUNIT */
#define XFS_MFSI_QUIET 0x40 /* Be silent if mount errors found */
-/*
- * Macros for getting from mount to vfs and back.
- */
-#define XFS_MTOVFS(mp) xfs_mtovfs(mp)
-static inline struct bhv_vfs *xfs_mtovfs(xfs_mount_t *mp)
-{
- return bhvtovfs(&mp->m_bhv);
-}
-
-#define XFS_BHVTOM(bdp) xfs_bhvtom(bdp)
-static inline xfs_mount_t *xfs_bhvtom(bhv_desc_t *bdp)
-{
- return (xfs_mount_t *)BHV_PDATA(bdp);
-}
-
-#define XFS_VFSTOM(vfs) xfs_vfstom(vfs)
-static inline xfs_mount_t *xfs_vfstom(bhv_vfs_t *vfs)
-{
- return XFS_BHVTOM(bhv_lookup_range(VFS_BHVHEAD(vfs),
- VFS_POSITION_XFS, VFS_POSITION_XFS));
-}
-
#define XFS_DADDR_TO_AGNO(mp,d) xfs_daddr_to_agno(mp,d)
static inline xfs_agnumber_t
xfs_daddr_to_agno(struct xfs_mount *mp, xfs_daddr_t d)
@@ -573,6 +565,21 @@ xfs_daddr_to_agbno(struct xfs_mount *mp, xfs_daddr_t d)
}
/*
+ * perag get/put wrappers for eventual ref counting
+ */
+static inline xfs_perag_t *
+xfs_get_perag(struct xfs_mount *mp, xfs_ino_t ino)
+{
+ return &mp->m_perag[XFS_INO_TO_AGNO(mp, ino)];
+}
+
+static inline void
+xfs_put_perag(struct xfs_mount *mp, xfs_perag_t *pag)
+{
+ /* nothing to see here, move along */
+}
+
+/*
* Per-cpu superblock locking functions
*/
#ifdef HAVE_PERCPU_SB
@@ -609,8 +616,8 @@ typedef struct xfs_mod_sb {
extern xfs_mount_t *xfs_mount_init(void);
extern void xfs_mod_sb(xfs_trans_t *, __int64_t);
extern int xfs_log_sbcount(xfs_mount_t *, uint);
-extern void xfs_mount_free(xfs_mount_t *mp, int remove_bhv);
-extern int xfs_mountfs(struct bhv_vfs *, xfs_mount_t *mp, int);
+extern void xfs_mount_free(xfs_mount_t *mp);
+extern int xfs_mountfs(xfs_mount_t *mp, int);
extern void xfs_mountfs_check_barriers(xfs_mount_t *mp);
extern int xfs_unmountfs(xfs_mount_t *, struct cred *);
@@ -626,16 +633,19 @@ extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int);
extern int xfs_readsb(xfs_mount_t *, int);
extern void xfs_freesb(xfs_mount_t *);
extern int xfs_fs_writable(xfs_mount_t *);
-extern void xfs_do_force_shutdown(bhv_desc_t *, int, char *, int);
extern int xfs_syncsub(xfs_mount_t *, int, int *);
extern int xfs_sync_inodes(xfs_mount_t *, int, int *);
-extern xfs_agnumber_t xfs_initialize_perag(struct bhv_vfs *, xfs_mount_t *,
- xfs_agnumber_t);
-extern void xfs_xlatesb(void *, struct xfs_sb *, int, __int64_t);
+extern xfs_agnumber_t xfs_initialize_perag(xfs_mount_t *, xfs_agnumber_t);
+extern void xfs_sb_from_disk(struct xfs_sb *, struct xfs_dsb *);
+extern void xfs_sb_to_disk(struct xfs_dsb *, struct xfs_sb *, __int64_t);
extern int xfs_sb_validate_fsb_count(struct xfs_sb *, __uint64_t);
-extern struct xfs_dmops xfs_dmcore_stub;
-extern struct xfs_qmops xfs_qmcore_stub;
+extern int xfs_dmops_get(struct xfs_mount *, struct xfs_mount_args *);
+extern void xfs_dmops_put(struct xfs_mount *);
+extern int xfs_qmops_get(struct xfs_mount *, struct xfs_mount_args *);
+extern void xfs_qmops_put(struct xfs_mount *);
+
+extern struct xfs_dmops xfs_dmcore_xfs;
extern struct xfs_ioops xfs_iocore_xfs;
extern int xfs_init(void);
diff --git a/fs/xfs/xfs_qmops.c b/fs/xfs/xfs_qmops.c
index 0d594ed7efef..2ec1d8a27352 100644
--- a/fs/xfs/xfs_qmops.c
+++ b/fs/xfs/xfs_qmops.c
@@ -28,6 +28,8 @@
#include "xfs_mount.h"
#include "xfs_quota.h"
#include "xfs_error.h"
+#include "xfs_clnt.h"
+
STATIC struct xfs_dquot *
xfs_dqvopchown_default(
@@ -64,7 +66,7 @@ xfs_mount_reset_sbqflags(xfs_mount_t *mp)
* if the fs is readonly, let the incore superblock run
* with quotas off but don't flush the update out to disk
*/
- if (XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY)
+ if (mp->m_flags & XFS_MOUNT_RDONLY)
return 0;
#ifdef QUOTADEBUG
xfs_fs_cmn_err(CE_NOTE, mp, "Writing superblock quota changes");
@@ -110,7 +112,7 @@ xfs_noquota_init(
return error;
}
-xfs_qmops_t xfs_qmcore_stub = {
+static struct xfs_qmops xfs_qmcore_stub = {
.xfs_qminit = (xfs_qminit_t) xfs_noquota_init,
.xfs_qmdone = (xfs_qmdone_t) fs_noerr,
.xfs_qmmount = (xfs_qmmount_t) fs_noerr,
@@ -124,4 +126,30 @@ xfs_qmops_t xfs_qmcore_stub = {
.xfs_dqvoprename = (xfs_dqvoprename_t) fs_noerr,
.xfs_dqvopchown = xfs_dqvopchown_default,
.xfs_dqvopchownresv = (xfs_dqvopchownresv_t) fs_noerr,
+ .xfs_dqstatvfs = (xfs_dqstatvfs_t) fs_noval,
+ .xfs_dqsync = (xfs_dqsync_t) fs_noerr,
+ .xfs_quotactl = (xfs_quotactl_t) fs_nosys,
};
+
+int
+xfs_qmops_get(struct xfs_mount *mp, struct xfs_mount_args *args)
+{
+ if (args->flags & (XFSMNT_UQUOTA | XFSMNT_PQUOTA | XFSMNT_GQUOTA)) {
+#ifdef CONFIG_XFS_QUOTA
+ mp->m_qm_ops = &xfs_qmcore_xfs;
+#else
+ cmn_err(CE_WARN,
+ "XFS: qouta support not available in this kernel.");
+ return EINVAL;
+#endif
+ } else {
+ mp->m_qm_ops = &xfs_qmcore_stub;
+ }
+
+ return 0;
+}
+
+void
+xfs_qmops_put(struct xfs_mount *mp)
+{
+}
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index 6f14df976f73..12c4ec775af8 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -330,12 +330,12 @@ typedef struct xfs_dqtrxops {
} xfs_dqtrxops_t;
#define XFS_DQTRXOP(mp, tp, op, args...) \
- ((mp)->m_qm_ops.xfs_dqtrxops ? \
- ((mp)->m_qm_ops.xfs_dqtrxops->op)(tp, ## args) : 0)
+ ((mp)->m_qm_ops->xfs_dqtrxops ? \
+ ((mp)->m_qm_ops->xfs_dqtrxops->op)(tp, ## args) : 0)
#define XFS_DQTRXOP_VOID(mp, tp, op, args...) \
- ((mp)->m_qm_ops.xfs_dqtrxops ? \
- ((mp)->m_qm_ops.xfs_dqtrxops->op)(tp, ## args) : (void)0)
+ ((mp)->m_qm_ops->xfs_dqtrxops ? \
+ ((mp)->m_qm_ops->xfs_dqtrxops->op)(tp, ## args) : (void)0)
#define XFS_TRANS_DUP_DQINFO(mp, otp, ntp) \
XFS_DQTRXOP_VOID(mp, otp, qo_dup_dqinfo, ntp)
@@ -364,7 +364,7 @@ typedef struct xfs_dqtrxops {
extern int xfs_qm_dqcheck(xfs_disk_dquot_t *, xfs_dqid_t, uint, uint, char *);
extern int xfs_mount_reset_sbqflags(struct xfs_mount *);
-extern struct bhv_module_vfsops xfs_qmops;
+extern struct xfs_qmops xfs_qmcore_xfs;
#endif /* __KERNEL__ */
diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c
index 7679d7a7022d..44ea0ba36476 100644
--- a/fs/xfs/xfs_rename.c
+++ b/fs/xfs/xfs_rename.c
@@ -22,6 +22,7 @@
#include "xfs_inum.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
+#include "xfs_ag.h"
#include "xfs_dir2.h"
#include "xfs_dmapi.h"
#include "xfs_mount.h"
@@ -128,8 +129,7 @@ xfs_lock_for_rename(
lock_mode = xfs_ilock_map_shared(dp2);
}
- error = xfs_dir_lookup_int(XFS_ITOBHV(dp2), lock_mode,
- vname2, &inum2, &ip2);
+ error = xfs_dir_lookup_int(dp2, lock_mode, vname2, &inum2, &ip2);
if (error == ENOENT) { /* target does not need to exist. */
inum2 = 0;
} else if (error) {
@@ -221,15 +221,15 @@ xfs_lock_for_rename(
*/
int
xfs_rename(
- bhv_desc_t *src_dir_bdp,
+ xfs_inode_t *src_dp,
bhv_vname_t *src_vname,
bhv_vnode_t *target_dir_vp,
- bhv_vname_t *target_vname,
- cred_t *credp)
+ bhv_vname_t *target_vname)
{
+ bhv_vnode_t *src_dir_vp = XFS_ITOV(src_dp);
xfs_trans_t *tp;
- xfs_inode_t *src_dp, *target_dp, *src_ip, *target_ip;
- xfs_mount_t *mp;
+ xfs_inode_t *target_dp, *src_ip, *target_ip;
+ xfs_mount_t *mp = src_dp->i_mount;
int new_parent; /* moving to a new dir */
int src_is_directory; /* src_name is a directory */
int error;
@@ -239,7 +239,6 @@ xfs_rename(
int committed;
xfs_inode_t *inodes[4];
int target_ip_dropped = 0; /* dropped target_ip link? */
- bhv_vnode_t *src_dir_vp;
int spaceres;
int target_link_zero = 0;
int num_inodes;
@@ -248,9 +247,8 @@ xfs_rename(
int src_namelen = VNAMELEN(src_vname);
int target_namelen = VNAMELEN(target_vname);
- src_dir_vp = BHV_TO_VNODE(src_dir_bdp);
- vn_trace_entry(src_dir_vp, "xfs_rename", (inst_t *)__return_address);
- vn_trace_entry(target_dir_vp, "xfs_rename", (inst_t *)__return_address);
+ vn_trace_entry(src_dp, "xfs_rename", (inst_t *)__return_address);
+ vn_trace_entry(xfs_vtoi(target_dir_vp), "xfs_rename", (inst_t *)__return_address);
/*
* Find the XFS behavior descriptor for the target directory
@@ -261,12 +259,8 @@ xfs_rename(
return XFS_ERROR(EXDEV);
}
- src_dp = XFS_BHVTOI(src_dir_bdp);
- mp = src_dp->i_mount;
-
- if (DM_EVENT_ENABLED(src_dir_vp->v_vfsp, src_dp, DM_EVENT_RENAME) ||
- DM_EVENT_ENABLED(target_dir_vp->v_vfsp,
- target_dp, DM_EVENT_RENAME)) {
+ if (DM_EVENT_ENABLED(src_dp, DM_EVENT_RENAME) ||
+ DM_EVENT_ENABLED(target_dp, DM_EVENT_RENAME)) {
error = XFS_SEND_NAMESP(mp, DM_EVENT_RENAME,
src_dir_vp, DM_RIGHT_NULL,
target_dir_vp, DM_RIGHT_NULL,
@@ -592,20 +586,16 @@ xfs_rename(
/*
* Let interposed file systems know about removed links.
*/
- if (target_ip_dropped) {
- bhv_vop_link_removed(XFS_ITOV(target_ip), target_dir_vp,
- target_link_zero);
+ if (target_ip_dropped)
IRELE(target_ip);
- }
IRELE(src_ip);
/* Fall through to std_return with error = 0 or errno from
* xfs_trans_commit */
std_return:
- if (DM_EVENT_ENABLED(src_dir_vp->v_vfsp, src_dp, DM_EVENT_POSTRENAME) ||
- DM_EVENT_ENABLED(target_dir_vp->v_vfsp,
- target_dp, DM_EVENT_POSTRENAME)) {
+ if (DM_EVENT_ENABLED(src_dp, DM_EVENT_POSTRENAME) ||
+ DM_EVENT_ENABLED(target_dp, DM_EVENT_POSTRENAME)) {
(void) XFS_SEND_NAMESP (mp, DM_EVENT_POSTRENAME,
src_dir_vp, DM_RIGHT_NULL,
target_dir_vp, DM_RIGHT_NULL,
diff --git a/fs/xfs/xfs_rw.c b/fs/xfs/xfs_rw.c
index 905d1c008be7..cd3ece6cc918 100644
--- a/fs/xfs/xfs_rw.c
+++ b/fs/xfs/xfs_rw.c
@@ -178,18 +178,15 @@ xfs_write_sync_logforce(
* the shop, make sure that absolutely nothing persistent happens to
* this filesystem after this point.
*/
-
void
xfs_do_force_shutdown(
- bhv_desc_t *bdp,
+ xfs_mount_t *mp,
int flags,
char *fname,
int lnnum)
{
int logerror;
- xfs_mount_t *mp;
- mp = XFS_BHVTOM(bdp);
logerror = flags & SHUTDOWN_LOG_IO_ERROR;
if (!(flags & SHUTDOWN_FORCE_UMOUNT)) {
diff --git a/fs/xfs/xfs_rw.h b/fs/xfs/xfs_rw.h
index fcf28dbded7c..49875e1d129f 100644
--- a/fs/xfs/xfs_rw.h
+++ b/fs/xfs/xfs_rw.h
@@ -23,32 +23,6 @@ struct xfs_inode;
struct xfs_mount;
/*
- * Maximum count of bmaps used by read and write paths.
- */
-#define XFS_MAX_RW_NBMAPS 4
-
-/*
- * Counts of readahead buffers to use based on physical memory size.
- * None of these should be more than XFS_MAX_RW_NBMAPS.
- */
-#define XFS_RW_NREADAHEAD_16MB 2
-#define XFS_RW_NREADAHEAD_32MB 3
-#define XFS_RW_NREADAHEAD_K32 4
-#define XFS_RW_NREADAHEAD_K64 4
-
-/*
- * Maximum size of a buffer that we\'ll map. Making this
- * too big will degrade performance due to the number of
- * pages which need to be gathered. Making it too small
- * will prevent us from doing large I/O\'s to hardware that
- * needs it.
- *
- * This is currently set to 512 KB.
- */
-#define XFS_MAX_BMAP_LEN_BB 1024
-#define XFS_MAX_BMAP_LEN_BYTES 524288
-
-/*
* Convert the given file system block to a disk block.
* We have to treat it differently based on whether the
* file is a real time file or not, because the bmap code
@@ -116,14 +90,6 @@ extern void xfs_ioerror_alert(char *func, struct xfs_mount *mp,
/*
* Prototypes for functions in xfs_vnodeops.c.
*/
-extern int xfs_rwlock(bhv_desc_t *bdp, bhv_vrwlock_t write_lock);
-extern void xfs_rwunlock(bhv_desc_t *bdp, bhv_vrwlock_t write_lock);
-extern int xfs_setattr(bhv_desc_t *, bhv_vattr_t *vap, int flags,
- cred_t *credp);
-extern int xfs_change_file_space(bhv_desc_t *bdp, int cmd, xfs_flock64_t *bf,
- xfs_off_t offset, cred_t *credp, int flags);
-extern int xfs_set_dmattrs(bhv_desc_t *bdp, u_int evmask, u_int16_t state,
- cred_t *credp);
extern int xfs_free_eofblocks(struct xfs_mount *mp, struct xfs_inode *ip,
int flags);
diff --git a/fs/xfs/xfs_sb.h b/fs/xfs/xfs_sb.h
index ef42537a607a..94660b1a6ccc 100644
--- a/fs/xfs/xfs_sb.h
+++ b/fs/xfs/xfs_sb.h
@@ -87,8 +87,10 @@ struct xfs_mount;
(XFS_SB_VERSION2_OKREALFBITS | \
XFS_SB_VERSION2_OKSASHFBITS )
-typedef struct xfs_sb
-{
+/*
+ * Superblock - in core version. Must match the ondisk version below.
+ */
+typedef struct xfs_sb {
__uint32_t sb_magicnum; /* magic number == XFS_SB_MAGIC */
__uint32_t sb_blocksize; /* logical block size, bytes */
xfs_drfsbno_t sb_dblocks; /* number of data blocks */
@@ -146,6 +148,66 @@ typedef struct xfs_sb
} xfs_sb_t;
/*
+ * Superblock - on disk version. Must match the in core version below.
+ */
+typedef struct xfs_dsb {
+ __be32 sb_magicnum; /* magic number == XFS_SB_MAGIC */
+ __be32 sb_blocksize; /* logical block size, bytes */
+ __be64 sb_dblocks; /* number of data blocks */
+ __be64 sb_rblocks; /* number of realtime blocks */
+ __be64 sb_rextents; /* number of realtime extents */
+ uuid_t sb_uuid; /* file system unique id */
+ __be64 sb_logstart; /* starting block of log if internal */
+ __be64 sb_rootino; /* root inode number */
+ __be64 sb_rbmino; /* bitmap inode for realtime extents */
+ __be64 sb_rsumino; /* summary inode for rt bitmap */
+ __be32 sb_rextsize; /* realtime extent size, blocks */
+ __be32 sb_agblocks; /* size of an allocation group */
+ __be32 sb_agcount; /* number of allocation groups */
+ __be32 sb_rbmblocks; /* number of rt bitmap blocks */
+ __be32 sb_logblocks; /* number of log blocks */
+ __be16 sb_versionnum; /* header version == XFS_SB_VERSION */
+ __be16 sb_sectsize; /* volume sector size, bytes */
+ __be16 sb_inodesize; /* inode size, bytes */
+ __be16 sb_inopblock; /* inodes per block */
+ char sb_fname[12]; /* file system name */
+ __u8 sb_blocklog; /* log2 of sb_blocksize */
+ __u8 sb_sectlog; /* log2 of sb_sectsize */
+ __u8 sb_inodelog; /* log2 of sb_inodesize */
+ __u8 sb_inopblog; /* log2 of sb_inopblock */
+ __u8 sb_agblklog; /* log2 of sb_agblocks (rounded up) */
+ __u8 sb_rextslog; /* log2 of sb_rextents */
+ __u8 sb_inprogress; /* mkfs is in progress, don't mount */
+ __u8 sb_imax_pct; /* max % of fs for inode space */
+ /* statistics */
+ /*
+ * These fields must remain contiguous. If you really
+ * want to change their layout, make sure you fix the
+ * code in xfs_trans_apply_sb_deltas().
+ */
+ __be64 sb_icount; /* allocated inodes */
+ __be64 sb_ifree; /* free inodes */
+ __be64 sb_fdblocks; /* free data blocks */
+ __be64 sb_frextents; /* free realtime extents */
+ /*
+ * End contiguous fields.
+ */
+ __be64 sb_uquotino; /* user quota inode */
+ __be64 sb_gquotino; /* group quota inode */
+ __be16 sb_qflags; /* quota flags */
+ __u8 sb_flags; /* misc. flags */
+ __u8 sb_shared_vn; /* shared version number */
+ __be32 sb_inoalignmt; /* inode chunk alignment, fsblocks */
+ __be32 sb_unit; /* stripe or raid unit */
+ __be32 sb_width; /* stripe or raid width */
+ __u8 sb_dirblklog; /* log2 of dir block size (fsbs) */
+ __u8 sb_logsectlog; /* log2 of the log sector size */
+ __be16 sb_logsectsize; /* sector size for the log, bytes */
+ __be32 sb_logsunit; /* stripe unit size for the log */
+ __be32 sb_features2; /* additional feature bits */
+} xfs_dsb_t;
+
+/*
* Sequence number values for the fields.
*/
typedef enum {
@@ -446,7 +508,7 @@ static inline void xfs_sb_version_addattr2(xfs_sb_t *sbp)
#define XFS_SB_DADDR ((xfs_daddr_t)0) /* daddr in filesystem/ag */
#define XFS_SB_BLOCK(mp) XFS_HDR_BLOCK(mp, XFS_SB_DADDR)
-#define XFS_BUF_TO_SBP(bp) ((xfs_sb_t *)XFS_BUF_PTR(bp))
+#define XFS_BUF_TO_SBP(bp) ((xfs_dsb_t *)XFS_BUF_PTR(bp))
#define XFS_HDR_BLOCK(mp,d) ((xfs_agblock_t)XFS_BB_TO_FSBT(mp,d))
#define XFS_DADDR_TO_FSB(mp,d) XFS_AGB_TO_FSB(mp, \
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 356d6627f581..8878322ee793 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -234,7 +234,7 @@ xfs_trans_alloc(
xfs_mount_t *mp,
uint type)
{
- vfs_wait_for_freeze(XFS_MTOVFS(mp), SB_FREEZE_TRANS);
+ xfs_wait_for_freeze(mp, SB_FREEZE_TRANS);
return _xfs_trans_alloc(mp, type);
}
@@ -548,7 +548,7 @@ STATIC void
xfs_trans_apply_sb_deltas(
xfs_trans_t *tp)
{
- xfs_sb_t *sbp;
+ xfs_dsb_t *sbp;
xfs_buf_t *bp;
int whole = 0;
@@ -566,57 +566,51 @@ xfs_trans_apply_sb_deltas(
* Only update the superblock counters if we are logging them
*/
if (!xfs_sb_version_haslazysbcount(&(tp->t_mountp->m_sb))) {
- if (tp->t_icount_delta != 0) {
- INT_MOD(sbp->sb_icount, ARCH_CONVERT, tp->t_icount_delta);
- }
- if (tp->t_ifree_delta != 0) {
- INT_MOD(sbp->sb_ifree, ARCH_CONVERT, tp->t_ifree_delta);
- }
-
- if (tp->t_fdblocks_delta != 0) {
- INT_MOD(sbp->sb_fdblocks, ARCH_CONVERT, tp->t_fdblocks_delta);
- }
- if (tp->t_res_fdblocks_delta != 0) {
- INT_MOD(sbp->sb_fdblocks, ARCH_CONVERT, tp->t_res_fdblocks_delta);
- }
+ if (tp->t_icount_delta)
+ be64_add(&sbp->sb_icount, tp->t_icount_delta);
+ if (tp->t_ifree_delta)
+ be64_add(&sbp->sb_ifree, tp->t_ifree_delta);
+ if (tp->t_fdblocks_delta)
+ be64_add(&sbp->sb_fdblocks, tp->t_fdblocks_delta);
+ if (tp->t_res_fdblocks_delta)
+ be64_add(&sbp->sb_fdblocks, tp->t_res_fdblocks_delta);
}
- if (tp->t_frextents_delta != 0) {
- INT_MOD(sbp->sb_frextents, ARCH_CONVERT, tp->t_frextents_delta);
- }
- if (tp->t_res_frextents_delta != 0) {
- INT_MOD(sbp->sb_frextents, ARCH_CONVERT, tp->t_res_frextents_delta);
- }
- if (tp->t_dblocks_delta != 0) {
- INT_MOD(sbp->sb_dblocks, ARCH_CONVERT, tp->t_dblocks_delta);
+ if (tp->t_frextents_delta)
+ be64_add(&sbp->sb_frextents, tp->t_frextents_delta);
+ if (tp->t_res_frextents_delta)
+ be64_add(&sbp->sb_frextents, tp->t_res_frextents_delta);
+
+ if (tp->t_dblocks_delta) {
+ be64_add(&sbp->sb_dblocks, tp->t_dblocks_delta);
whole = 1;
}
- if (tp->t_agcount_delta != 0) {
- INT_MOD(sbp->sb_agcount, ARCH_CONVERT, tp->t_agcount_delta);
+ if (tp->t_agcount_delta) {
+ be32_add(&sbp->sb_agcount, tp->t_agcount_delta);
whole = 1;
}
- if (tp->t_imaxpct_delta != 0) {
- INT_MOD(sbp->sb_imax_pct, ARCH_CONVERT, tp->t_imaxpct_delta);
+ if (tp->t_imaxpct_delta) {
+ sbp->sb_imax_pct += tp->t_imaxpct_delta;
whole = 1;
}
- if (tp->t_rextsize_delta != 0) {
- INT_MOD(sbp->sb_rextsize, ARCH_CONVERT, tp->t_rextsize_delta);
+ if (tp->t_rextsize_delta) {
+ be32_add(&sbp->sb_rextsize, tp->t_rextsize_delta);
whole = 1;
}
- if (tp->t_rbmblocks_delta != 0) {
- INT_MOD(sbp->sb_rbmblocks, ARCH_CONVERT, tp->t_rbmblocks_delta);
+ if (tp->t_rbmblocks_delta) {
+ be32_add(&sbp->sb_rbmblocks, tp->t_rbmblocks_delta);
whole = 1;
}
- if (tp->t_rblocks_delta != 0) {
- INT_MOD(sbp->sb_rblocks, ARCH_CONVERT, tp->t_rblocks_delta);
+ if (tp->t_rblocks_delta) {
+ be64_add(&sbp->sb_rblocks, tp->t_rblocks_delta);
whole = 1;
}
- if (tp->t_rextents_delta != 0) {
- INT_MOD(sbp->sb_rextents, ARCH_CONVERT, tp->t_rextents_delta);
+ if (tp->t_rextents_delta) {
+ be64_add(&sbp->sb_rextents, tp->t_rextents_delta);
whole = 1;
}
- if (tp->t_rextslog_delta != 0) {
- INT_MOD(sbp->sb_rextslog, ARCH_CONVERT, tp->t_rextslog_delta);
+ if (tp->t_rextslog_delta) {
+ sbp->sb_rextslog += tp->t_rextslog_delta;
whole = 1;
}
@@ -624,17 +618,17 @@ xfs_trans_apply_sb_deltas(
/*
* Log the whole thing, the fields are noncontiguous.
*/
- xfs_trans_log_buf(tp, bp, 0, sizeof(xfs_sb_t) - 1);
+ xfs_trans_log_buf(tp, bp, 0, sizeof(xfs_dsb_t) - 1);
else
/*
* Since all the modifiable fields are contiguous, we
* can get away with this.
*/
- xfs_trans_log_buf(tp, bp, offsetof(xfs_sb_t, sb_icount),
- offsetof(xfs_sb_t, sb_frextents) +
+ xfs_trans_log_buf(tp, bp, offsetof(xfs_dsb_t, sb_icount),
+ offsetof(xfs_dsb_t, sb_frextents) +
sizeof(sbp->sb_frextents) - 1);
- XFS_MTOVFS(tp->t_mountp)->vfs_super->s_dirt = 1;
+ tp->t_mountp->m_super->s_dirt = 1;
}
/*
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
index ceb4f6e99960..5b2ff59f19cf 100644
--- a/fs/xfs/xfs_trans_ail.c
+++ b/fs/xfs/xfs_trans_ail.c
@@ -22,6 +22,7 @@
#include "xfs_inum.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
+#include "xfs_ag.h"
#include "xfs_dmapi.h"
#include "xfs_mount.h"
#include "xfs_trans_priv.h"
diff --git a/fs/xfs/xfs_trans_extfree.c b/fs/xfs/xfs_trans_extfree.c
index b290270dd4a6..27cce2a9c7e9 100644
--- a/fs/xfs/xfs_trans_extfree.c
+++ b/fs/xfs/xfs_trans_extfree.c
@@ -22,6 +22,7 @@
#include "xfs_inum.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
+#include "xfs_ag.h"
#include "xfs_dmapi.h"
#include "xfs_mount.h"
#include "xfs_trans_priv.h"
diff --git a/fs/xfs/xfs_types.h b/fs/xfs/xfs_types.h
index 104f64a98790..5c89be475464 100644
--- a/fs/xfs/xfs_types.h
+++ b/fs/xfs/xfs_types.h
@@ -151,18 +151,6 @@ typedef __uint8_t xfs_arch_t; /* architecture of an xfs fs */
*/
#define MAXNAMELEN 256
-typedef struct xfs_dirent { /* data from readdir() */
- xfs_ino_t d_ino; /* inode number of entry */
- xfs_off_t d_off; /* offset of disk directory entry */
- unsigned short d_reclen; /* length of this record */
- char d_name[1]; /* name of file */
-} xfs_dirent_t;
-
-#define DIRENTBASESIZE (((xfs_dirent_t *)0)->d_name - (char *)0)
-#define DIRENTSIZE(namelen) \
- ((DIRENTBASESIZE + (namelen) + \
- sizeof(xfs_off_t)) & ~(sizeof(xfs_off_t) - 1))
-
typedef enum {
XFS_LOOKUP_EQi, XFS_LOOKUP_LEi, XFS_LOOKUP_GEi
} xfs_lookup_t;
diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c
index 20ffec308e1e..673b405eaa31 100644
--- a/fs/xfs/xfs_utils.c
+++ b/fs/xfs/xfs_utils.c
@@ -65,20 +65,15 @@ xfs_get_dir_entry(
int
xfs_dir_lookup_int(
- bhv_desc_t *dir_bdp,
+ xfs_inode_t *dp,
uint lock_mode,
bhv_vname_t *dentry,
xfs_ino_t *inum,
xfs_inode_t **ipp)
{
- bhv_vnode_t *dir_vp;
- xfs_inode_t *dp;
int error;
- dir_vp = BHV_TO_VNODE(dir_bdp);
- vn_trace_entry(dir_vp, __FUNCTION__, (inst_t *)__return_address);
-
- dp = XFS_BHVTOI(dir_bdp);
+ vn_trace_entry(dp, __FUNCTION__, (inst_t *)__return_address);
error = xfs_dir_lookup(NULL, dp, VNAME(dentry), VNAMELEN(dentry), inum);
if (!error) {
diff --git a/fs/xfs/xfs_utils.h b/fs/xfs/xfs_utils.h
index fe953e98afa7..a00b26d8840e 100644
--- a/fs/xfs/xfs_utils.h
+++ b/fs/xfs/xfs_utils.h
@@ -20,13 +20,11 @@
#define IRELE(ip) VN_RELE(XFS_ITOV(ip))
#define IHOLD(ip) VN_HOLD(XFS_ITOV(ip))
-#define ITRACE(ip) vn_trace_ref(XFS_ITOV(ip), __FILE__, __LINE__, \
+#define ITRACE(ip) vn_trace_ref(ip, __FILE__, __LINE__, \
(inst_t *)__return_address)
-extern int xfs_rename (bhv_desc_t *, bhv_vname_t *, bhv_vnode_t *,
- bhv_vname_t *, cred_t *);
extern int xfs_get_dir_entry (bhv_vname_t *, xfs_inode_t **);
-extern int xfs_dir_lookup_int (bhv_desc_t *, uint, bhv_vname_t *, xfs_ino_t *,
+extern int xfs_dir_lookup_int (xfs_inode_t *, uint, bhv_vname_t *, xfs_ino_t *,
xfs_inode_t **);
extern int xfs_truncate_file (xfs_mount_t *, xfs_inode_t *);
extern int xfs_dir_ialloc (xfs_trans_t **, xfs_inode_t *, mode_t, xfs_nlink_t,
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index 11f5ea29a038..a1544597bcd3 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -54,8 +54,9 @@
#include "xfs_mru_cache.h"
#include "xfs_filestream.h"
#include "xfs_fsops.h"
+#include "xfs_vnodeops.h"
+#include "xfs_vfsops.h"
-STATIC int xfs_sync(bhv_desc_t *, int, cred_t *);
int
xfs_init(void)
@@ -117,8 +118,8 @@ xfs_init(void)
xfs_ili_zone =
kmem_zone_init_flags(sizeof(xfs_inode_log_item_t), "xfs_ili",
KM_ZONE_SPREAD, NULL);
- xfs_chashlist_zone =
- kmem_zone_init_flags(sizeof(xfs_chashlist_t), "xfs_chashlist",
+ xfs_icluster_zone =
+ kmem_zone_init_flags(sizeof(xfs_icluster_t), "xfs_icluster",
KM_ZONE_SPREAD, NULL);
/*
@@ -163,7 +164,7 @@ xfs_cleanup(void)
extern kmem_zone_t *xfs_efd_zone;
extern kmem_zone_t *xfs_efi_zone;
extern kmem_zone_t *xfs_buf_item_zone;
- extern kmem_zone_t *xfs_chashlist_zone;
+ extern kmem_zone_t *xfs_icluster_zone;
xfs_cleanup_procfs();
xfs_sysctl_unregister();
@@ -199,7 +200,7 @@ xfs_cleanup(void)
kmem_zone_destroy(xfs_efi_zone);
kmem_zone_destroy(xfs_ifork_zone);
kmem_zone_destroy(xfs_ili_zone);
- kmem_zone_destroy(xfs_chashlist_zone);
+ kmem_zone_destroy(xfs_icluster_zone);
}
/*
@@ -210,7 +211,6 @@ xfs_cleanup(void)
*/
STATIC int
xfs_start_flags(
- struct bhv_vfs *vfs,
struct xfs_mount_args *ap,
struct xfs_mount *mp)
{
@@ -238,17 +238,14 @@ xfs_start_flags(
mp->m_logbufs = ap->logbufs;
if (ap->logbufsize != -1 &&
ap->logbufsize != 0 &&
- ap->logbufsize != 16 * 1024 &&
- ap->logbufsize != 32 * 1024 &&
- ap->logbufsize != 64 * 1024 &&
- ap->logbufsize != 128 * 1024 &&
- ap->logbufsize != 256 * 1024) {
+ (ap->logbufsize < XLOG_MIN_RECORD_BSIZE ||
+ ap->logbufsize > XLOG_MAX_RECORD_BSIZE ||
+ !is_power_of_2(ap->logbufsize))) {
cmn_err(CE_WARN,
"XFS: invalid logbufsize: %d [not 16k,32k,64k,128k or 256k]",
ap->logbufsize);
return XFS_ERROR(EINVAL);
}
- mp->m_ihsize = ap->ihashsize;
mp->m_logbsize = ap->logbufsize;
mp->m_fsname_len = strlen(ap->fsname) + 1;
mp->m_fsname = kmem_alloc(mp->m_fsname_len, KM_SLEEP);
@@ -295,8 +292,6 @@ xfs_start_flags(
mp->m_readio_log = mp->m_writeio_log = ap->iosizelog;
}
- if (ap->flags & XFSMNT_IHASHSIZE)
- mp->m_flags |= XFS_MOUNT_IHASHSIZE;
if (ap->flags & XFSMNT_IDELETE)
mp->m_flags |= XFS_MOUNT_IDELETE;
if (ap->flags & XFSMNT_DIRSYNC)
@@ -311,7 +306,7 @@ xfs_start_flags(
* no recovery flag requires a read-only mount
*/
if (ap->flags & XFSMNT_NORECOVERY) {
- if (!(vfs->vfs_flag & VFS_RDONLY)) {
+ if (!(mp->m_flags & XFS_MOUNT_RDONLY)) {
cmn_err(CE_WARN,
"XFS: tried to mount a FS read-write without recovery!");
return XFS_ERROR(EINVAL);
@@ -329,6 +324,8 @@ xfs_start_flags(
if (ap->flags2 & XFSMNT2_FILESTREAMS)
mp->m_flags |= XFS_MOUNT_FILESTREAMS;
+ if (ap->flags & XFSMNT_DMAPI)
+ mp->m_flags |= XFS_MOUNT_DMAPI;
return 0;
}
@@ -338,11 +335,10 @@ xfs_start_flags(
*/
STATIC int
xfs_finish_flags(
- struct bhv_vfs *vfs,
struct xfs_mount_args *ap,
struct xfs_mount *mp)
{
- int ronly = (vfs->vfs_flag & VFS_RDONLY);
+ int ronly = (mp->m_flags & XFS_MOUNT_RDONLY);
/* Fail a mount where the logbuf is smaller then the log stripe */
if (XFS_SB_VERSION_HASLOGV2(&mp->m_sb)) {
@@ -403,6 +399,22 @@ xfs_finish_flags(
return XFS_ERROR(EINVAL);
}
+ if (ap->flags & XFSMNT_UQUOTA) {
+ mp->m_qflags |= (XFS_UQUOTA_ACCT | XFS_UQUOTA_ACTIVE);
+ if (ap->flags & XFSMNT_UQUOTAENF)
+ mp->m_qflags |= XFS_UQUOTA_ENFD;
+ }
+
+ if (ap->flags & XFSMNT_GQUOTA) {
+ mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE);
+ if (ap->flags & XFSMNT_GQUOTAENF)
+ mp->m_qflags |= XFS_OQUOTA_ENFD;
+ } else if (ap->flags & XFSMNT_PQUOTA) {
+ mp->m_qflags |= (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE);
+ if (ap->flags & XFSMNT_PQUOTAENF)
+ mp->m_qflags |= XFS_OQUOTA_ENFD;
+ }
+
return 0;
}
@@ -418,30 +430,26 @@ xfs_finish_flags(
* they are present. The data subvolume has already been opened by
* get_sb_bdev() and is stored in vfsp->vfs_super->s_bdev.
*/
-STATIC int
+int
xfs_mount(
- struct bhv_desc *bhvp,
+ struct xfs_mount *mp,
struct xfs_mount_args *args,
cred_t *credp)
{
- struct bhv_vfs *vfsp = bhvtovfs(bhvp);
- struct bhv_desc *p;
- struct xfs_mount *mp = XFS_BHVTOM(bhvp);
struct block_device *ddev, *logdev, *rtdev;
int flags = 0, error;
- ddev = vfsp->vfs_super->s_bdev;
+ ddev = mp->m_super->s_bdev;
logdev = rtdev = NULL;
- /*
- * Setup xfs_mount function vectors from available behaviors
- */
- p = vfs_bhv_lookup(vfsp, VFS_POSITION_DM);
- mp->m_dm_ops = p ? *(xfs_dmops_t *) vfs_bhv_custom(p) : xfs_dmcore_stub;
- p = vfs_bhv_lookup(vfsp, VFS_POSITION_QM);
- mp->m_qm_ops = p ? *(xfs_qmops_t *) vfs_bhv_custom(p) : xfs_qmcore_stub;
- p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO);
- mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs;
+ error = xfs_dmops_get(mp, args);
+ if (error)
+ return error;
+ error = xfs_qmops_get(mp, args);
+ if (error)
+ return error;
+
+ mp->m_io_ops = xfs_iocore_xfs;
if (args->flags & XFSMNT_QUIET)
flags |= XFS_MFSI_QUIET;
@@ -482,24 +490,30 @@ xfs_mount(
}
if (rtdev) {
mp->m_rtdev_targp = xfs_alloc_buftarg(rtdev, 1);
- if (!mp->m_rtdev_targp)
+ if (!mp->m_rtdev_targp) {
+ xfs_blkdev_put(logdev);
+ xfs_blkdev_put(rtdev);
goto error0;
+ }
}
mp->m_logdev_targp = (logdev && logdev != ddev) ?
xfs_alloc_buftarg(logdev, 1) : mp->m_ddev_targp;
- if (!mp->m_logdev_targp)
+ if (!mp->m_logdev_targp) {
+ xfs_blkdev_put(logdev);
+ xfs_blkdev_put(rtdev);
goto error0;
+ }
/*
* Setup flags based on mount(2) options and then the superblock
*/
- error = xfs_start_flags(vfsp, args, mp);
+ error = xfs_start_flags(args, mp);
if (error)
goto error1;
error = xfs_readsb(mp, flags);
if (error)
goto error1;
- error = xfs_finish_flags(vfsp, args, mp);
+ error = xfs_finish_flags(args, mp);
if (error)
goto error2;
@@ -530,10 +544,12 @@ xfs_mount(
if ((error = xfs_filestream_mount(mp)))
goto error2;
- error = XFS_IOINIT(vfsp, args, flags);
+ error = XFS_IOINIT(mp, args, flags);
if (error)
goto error2;
+ XFS_SEND_MOUNT(mp, DM_RIGHT_NULL, args->mtpt, args->fsname);
+
return 0;
error2:
@@ -547,17 +563,17 @@ error1:
xfs_binval(mp->m_rtdev_targp);
error0:
xfs_unmountfs_close(mp, credp);
+ xfs_qmops_put(mp);
+ xfs_dmops_put(mp);
return error;
}
-STATIC int
+int
xfs_unmount(
- bhv_desc_t *bdp,
+ xfs_mount_t *mp,
int flags,
cred_t *credp)
{
- bhv_vfs_t *vfsp = bhvtovfs(bdp);
- xfs_mount_t *mp = XFS_BHVTOM(bdp);
xfs_inode_t *rip;
bhv_vnode_t *rvp;
int unmount_event_wanted = 0;
@@ -568,8 +584,9 @@ xfs_unmount(
rip = mp->m_rootip;
rvp = XFS_ITOV(rip);
- if (vfsp->vfs_flag & VFS_DMI) {
- error = XFS_SEND_PREUNMOUNT(mp, vfsp,
+#ifdef HAVE_DMAPI
+ if (mp->m_flags & XFS_MOUNT_DMAPI) {
+ error = XFS_SEND_PREUNMOUNT(mp,
rvp, DM_RIGHT_NULL, rvp, DM_RIGHT_NULL,
NULL, NULL, 0, 0,
(mp->m_dmevmask & (1<<DM_EVENT_PREUNMOUNT))?
@@ -580,7 +597,7 @@ xfs_unmount(
unmount_event_flags = (mp->m_dmevmask & (1<<DM_EVENT_UNMOUNT))?
0 : DM_FLAGS_UNWANTED;
}
-
+#endif
/*
* First blow any referenced inode from this file system
* out of the reference cache, and delete the timer.
@@ -612,8 +629,7 @@ xfs_unmount(
* referenced vnodes as well.
*/
if (XFS_FORCED_SHUTDOWN(mp)) {
- error = xfs_sync(&mp->m_bhv,
- (SYNC_WAIT | SYNC_CLOSE), credp);
+ error = xfs_sync(mp, SYNC_WAIT | SYNC_CLOSE);
ASSERT(error != EFSCORRUPTED);
}
xfs_unmountfs_needed = 1;
@@ -627,7 +643,7 @@ out:
/* Note: mp structure must still exist for
* XFS_SEND_UNMOUNT() call.
*/
- XFS_SEND_UNMOUNT(mp, vfsp, error == 0 ? rvp : NULL,
+ XFS_SEND_UNMOUNT(mp, error == 0 ? rvp : NULL,
DM_RIGHT_NULL, 0, error, unmount_event_flags);
}
if (xfs_unmountfs_needed) {
@@ -636,6 +652,9 @@ out:
* and free the super block buffer & mount structures.
*/
xfs_unmountfs(mp, credp);
+ xfs_qmops_put(mp);
+ xfs_dmops_put(mp);
+ kmem_free(mp, sizeof(xfs_mount_t));
}
return XFS_ERROR(error);
@@ -694,29 +713,26 @@ xfs_attr_quiesce(
xfs_unmountfs_writesb(mp);
}
-STATIC int
+int
xfs_mntupdate(
- bhv_desc_t *bdp,
+ struct xfs_mount *mp,
int *flags,
struct xfs_mount_args *args)
{
- bhv_vfs_t *vfsp = bhvtovfs(bdp);
- xfs_mount_t *mp = XFS_BHVTOM(bdp);
-
if (!(*flags & MS_RDONLY)) { /* rw/ro -> rw */
- if (vfsp->vfs_flag & VFS_RDONLY)
- vfsp->vfs_flag &= ~VFS_RDONLY;
+ if (mp->m_flags & XFS_MOUNT_RDONLY)
+ mp->m_flags &= ~XFS_MOUNT_RDONLY;
if (args->flags & XFSMNT_BARRIER) {
mp->m_flags |= XFS_MOUNT_BARRIER;
xfs_mountfs_check_barriers(mp);
} else {
mp->m_flags &= ~XFS_MOUNT_BARRIER;
}
- } else if (!(vfsp->vfs_flag & VFS_RDONLY)) { /* rw -> ro */
+ } else if (!(mp->m_flags & XFS_MOUNT_RDONLY)) { /* rw -> ro */
xfs_filestream_flush(mp);
- bhv_vfs_sync(vfsp, SYNC_DATA_QUIESCE, NULL);
+ xfs_sync(mp, SYNC_DATA_QUIESCE);
xfs_attr_quiesce(mp);
- vfsp->vfs_flag |= VFS_RDONLY;
+ mp->m_flags |= XFS_MOUNT_RDONLY;
}
return 0;
}
@@ -811,14 +827,14 @@ fscorrupt_out2:
* vpp -- address of the caller's vnode pointer which should be
* set to the desired fs root vnode
*/
-STATIC int
+int
xfs_root(
- bhv_desc_t *bdp,
+ xfs_mount_t *mp,
bhv_vnode_t **vpp)
{
bhv_vnode_t *vp;
- vp = XFS_ITOV((XFS_BHVTOM(bdp))->m_rootip);
+ vp = XFS_ITOV(mp->m_rootip);
VN_HOLD(vp);
*vpp = vp;
return 0;
@@ -831,19 +847,17 @@ xfs_root(
* the superblock lock in the mount structure to ensure a consistent
* snapshot of the counters returned.
*/
-STATIC int
+int
xfs_statvfs(
- bhv_desc_t *bdp,
+ xfs_mount_t *mp,
bhv_statvfs_t *statp,
bhv_vnode_t *vp)
{
__uint64_t fakeinos;
xfs_extlen_t lsize;
- xfs_mount_t *mp;
xfs_sb_t *sbp;
unsigned long s;
- mp = XFS_BHVTOM(bdp);
sbp = &(mp->m_sb);
statp->f_type = XFS_SB_MAGIC;
@@ -874,6 +888,8 @@ xfs_statvfs(
xfs_statvfs_fsid(statp, mp);
statp->f_namelen = MAXNAMELEN - 1;
+ if (vp)
+ XFS_QM_DQSTATVFS(xfs_vtoi(vp), statp);
return 0;
}
@@ -920,14 +936,30 @@ xfs_statvfs(
* filesystem.
*
*/
-/*ARGSUSED*/
-STATIC int
+int
xfs_sync(
- bhv_desc_t *bdp,
- int flags,
- cred_t *credp)
+ xfs_mount_t *mp,
+ int flags)
{
- xfs_mount_t *mp = XFS_BHVTOM(bdp);
+ int error;
+
+ /*
+ * Get the Quota Manager to flush the dquots.
+ *
+ * If XFS quota support is not enabled or this filesystem
+ * instance does not use quotas XFS_QM_DQSYNC will always
+ * return zero.
+ */
+ error = XFS_QM_DQSYNC(mp, flags);
+ if (error) {
+ /*
+ * If we got an IO error, we will be shutting down.
+ * So, there's nothing more for us to do here.
+ */
+ ASSERT(error != EIO || XFS_FORCED_SHUTDOWN(mp));
+ if (XFS_FORCED_SHUTDOWN(mp))
+ return XFS_ERROR(error);
+ }
if (flags & SYNC_IOWAIT)
xfs_filestream_flush(mp);
@@ -1015,7 +1047,7 @@ xfs_sync_inodes(
if (bypassed)
*bypassed = 0;
- if (XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY)
+ if (mp->m_flags & XFS_MOUNT_RDONLY)
return 0;
error = 0;
last_error = 0;
@@ -1189,12 +1221,13 @@ xfs_sync_inodes(
if (flags & SYNC_CLOSE) {
/* Shutdown case. Flush and invalidate. */
if (XFS_FORCED_SHUTDOWN(mp))
- bhv_vop_toss_pages(vp, 0, -1, FI_REMAPF);
+ xfs_tosspages(ip, 0, -1,
+ FI_REMAPF);
else
- error = bhv_vop_flushinval_pages(vp, 0,
- -1, FI_REMAPF);
+ error = xfs_flushinval_pages(ip,
+ 0, -1, FI_REMAPF);
} else if ((flags & SYNC_DELWRI) && VN_DIRTY(vp)) {
- error = bhv_vop_flush_pages(vp, (xfs_off_t)0,
+ error = xfs_flush_pages(ip, 0,
-1, fflag, FI_NONE);
}
@@ -1204,7 +1237,7 @@ xfs_sync_inodes(
* place after this point
*/
if (flags & SYNC_IOWAIT)
- vn_iowait(vp);
+ vn_iowait(ip);
xfs_ilock(ip, XFS_ILOCK_SHARED);
}
@@ -1598,14 +1631,12 @@ xfs_syncsub(
/*
* xfs_vget - called by DMAPI and NFSD to get vnode from file handle
*/
-STATIC int
+int
xfs_vget(
- bhv_desc_t *bdp,
+ xfs_mount_t *mp,
bhv_vnode_t **vpp,
- fid_t *fidp)
+ xfs_fid_t *xfid)
{
- xfs_mount_t *mp = XFS_BHVTOM(bdp);
- xfs_fid_t *xfid = (struct xfs_fid *)fidp;
xfs_inode_t *ip;
int error;
xfs_ino_t ino;
@@ -1615,11 +1646,11 @@ xfs_vget(
* Invalid. Since handles can be created in user space and passed in
* via gethandle(), this is not cause for a panic.
*/
- if (xfid->xfs_fid_len != sizeof(*xfid) - sizeof(xfid->xfs_fid_len))
+ if (xfid->fid_len != sizeof(*xfid) - sizeof(xfid->fid_len))
return XFS_ERROR(EINVAL);
- ino = xfid->xfs_fid_ino;
- igen = xfid->xfs_fid_gen;
+ ino = xfid->fid_ino;
+ igen = xfid->fid_gen;
/*
* NFS can sometimes send requests for ino 0. Fail them gracefully.
@@ -1668,7 +1699,6 @@ xfs_vget(
#define MNTOPT_BSDGROUPS "bsdgroups" /* group-ID from parent directory */
#define MNTOPT_SYSVGROUPS "sysvgroups" /* group-ID from current process */
#define MNTOPT_ALLOCSIZE "allocsize" /* preferred allocation size */
-#define MNTOPT_IHASHSIZE "ihashsize" /* size of inode hash table */
#define MNTOPT_NORECOVERY "norecovery" /* don't run XFS recovery */
#define MNTOPT_BARRIER "barrier" /* use writer barriers for log write and
* unwritten extent conversion */
@@ -1683,6 +1713,21 @@ xfs_vget(
#define MNTOPT_ATTR2 "attr2" /* do use attr2 attribute format */
#define MNTOPT_NOATTR2 "noattr2" /* do not use attr2 attribute format */
#define MNTOPT_FILESTREAM "filestreams" /* use filestreams allocator */
+#define MNTOPT_QUOTA "quota" /* disk quotas (user) */
+#define MNTOPT_NOQUOTA "noquota" /* no quotas */
+#define MNTOPT_USRQUOTA "usrquota" /* user quota enabled */
+#define MNTOPT_GRPQUOTA "grpquota" /* group quota enabled */
+#define MNTOPT_PRJQUOTA "prjquota" /* project quota enabled */
+#define MNTOPT_UQUOTA "uquota" /* user quota (IRIX variant) */
+#define MNTOPT_GQUOTA "gquota" /* group quota (IRIX variant) */
+#define MNTOPT_PQUOTA "pquota" /* project quota (IRIX variant) */
+#define MNTOPT_UQUOTANOENF "uqnoenforce"/* user quota limit enforcement */
+#define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */
+#define MNTOPT_PQUOTANOENF "pqnoenforce"/* project quota limit enforcement */
+#define MNTOPT_QUOTANOENF "qnoenforce" /* same as uqnoenforce */
+#define MNTOPT_DMAPI "dmapi" /* DMI enabled (DMAPI / XDSM) */
+#define MNTOPT_XDSM "xdsm" /* DMI enabled (DMAPI / XDSM) */
+#define MNTOPT_DMI "dmi" /* DMI enabled (DMAPI / XDSM) */
STATIC unsigned long
suffix_strtoul(char *s, char **endp, unsigned int base)
@@ -1707,19 +1752,18 @@ suffix_strtoul(char *s, char **endp, unsigned int base)
return simple_strtoul((const char *)s, endp, base) << shift_left_factor;
}
-STATIC int
+int
xfs_parseargs(
- struct bhv_desc *bhv,
+ struct xfs_mount *mp,
char *options,
struct xfs_mount_args *args,
int update)
{
- bhv_vfs_t *vfsp = bhvtovfs(bhv);
char *this_char, *value, *eov;
int dsunit, dswidth, vol_dsunit, vol_dswidth;
int iosize;
+ int ikeep = 0;
- args->flags |= XFSMNT_IDELETE;
args->flags |= XFSMNT_BARRIER;
args->flags2 |= XFSMNT2_COMPAT_IOSIZE;
@@ -1794,21 +1838,12 @@ xfs_parseargs(
iosize = suffix_strtoul(value, &eov, 10);
args->flags |= XFSMNT_IOSIZE;
args->iosizelog = ffs(iosize) - 1;
- } else if (!strcmp(this_char, MNTOPT_IHASHSIZE)) {
- if (!value || !*value) {
- cmn_err(CE_WARN,
- "XFS: %s option requires an argument",
- this_char);
- return EINVAL;
- }
- args->flags |= XFSMNT_IHASHSIZE;
- args->ihashsize = simple_strtoul(value, &eov, 10);
} else if (!strcmp(this_char, MNTOPT_GRPID) ||
!strcmp(this_char, MNTOPT_BSDGROUPS)) {
- vfsp->vfs_flag |= VFS_GRPID;
+ mp->m_flags |= XFS_MOUNT_GRPID;
} else if (!strcmp(this_char, MNTOPT_NOGRPID) ||
!strcmp(this_char, MNTOPT_SYSVGROUPS)) {
- vfsp->vfs_flag &= ~VFS_GRPID;
+ mp->m_flags &= ~XFS_MOUNT_GRPID;
} else if (!strcmp(this_char, MNTOPT_WSYNC)) {
args->flags |= XFSMNT_WSYNC;
} else if (!strcmp(this_char, MNTOPT_OSYNCISOSYNC)) {
@@ -1858,6 +1893,7 @@ xfs_parseargs(
} else if (!strcmp(this_char, MNTOPT_NOBARRIER)) {
args->flags &= ~XFSMNT_BARRIER;
} else if (!strcmp(this_char, MNTOPT_IKEEP)) {
+ ikeep = 1;
args->flags &= ~XFSMNT_IDELETE;
} else if (!strcmp(this_char, MNTOPT_NOIKEEP)) {
args->flags |= XFSMNT_IDELETE;
@@ -1871,6 +1907,38 @@ xfs_parseargs(
args->flags &= ~XFSMNT_ATTR2;
} else if (!strcmp(this_char, MNTOPT_FILESTREAM)) {
args->flags2 |= XFSMNT2_FILESTREAMS;
+ } else if (!strcmp(this_char, MNTOPT_NOQUOTA)) {
+ args->flags &= ~(XFSMNT_UQUOTAENF|XFSMNT_UQUOTA);
+ args->flags &= ~(XFSMNT_GQUOTAENF|XFSMNT_GQUOTA);
+ } else if (!strcmp(this_char, MNTOPT_QUOTA) ||
+ !strcmp(this_char, MNTOPT_UQUOTA) ||
+ !strcmp(this_char, MNTOPT_USRQUOTA)) {
+ args->flags |= XFSMNT_UQUOTA | XFSMNT_UQUOTAENF;
+ } else if (!strcmp(this_char, MNTOPT_QUOTANOENF) ||
+ !strcmp(this_char, MNTOPT_UQUOTANOENF)) {
+ args->flags |= XFSMNT_UQUOTA;
+ args->flags &= ~XFSMNT_UQUOTAENF;
+ } else if (!strcmp(this_char, MNTOPT_PQUOTA) ||
+ !strcmp(this_char, MNTOPT_PRJQUOTA)) {
+ args->flags |= XFSMNT_PQUOTA | XFSMNT_PQUOTAENF;
+ } else if (!strcmp(this_char, MNTOPT_PQUOTANOENF)) {
+ args->flags |= XFSMNT_PQUOTA;
+ args->flags &= ~XFSMNT_PQUOTAENF;
+ } else if (!strcmp(this_char, MNTOPT_GQUOTA) ||
+ !strcmp(this_char, MNTOPT_GRPQUOTA)) {
+ args->flags |= XFSMNT_GQUOTA | XFSMNT_GQUOTAENF;
+ } else if (!strcmp(this_char, MNTOPT_GQUOTANOENF)) {
+ args->flags |= XFSMNT_GQUOTA;
+ args->flags &= ~XFSMNT_GQUOTAENF;
+ } else if (!strcmp(this_char, MNTOPT_DMAPI)) {
+ args->flags |= XFSMNT_DMAPI;
+ } else if (!strcmp(this_char, MNTOPT_XDSM)) {
+ args->flags |= XFSMNT_DMAPI;
+ } else if (!strcmp(this_char, MNTOPT_DMI)) {
+ args->flags |= XFSMNT_DMAPI;
+ } else if (!strcmp(this_char, "ihashsize")) {
+ cmn_err(CE_WARN,
+ "XFS: ihashsize no longer used, option is deprecated.");
} else if (!strcmp(this_char, "osyncisdsync")) {
/* no-op, this is now the default */
cmn_err(CE_WARN,
@@ -1886,7 +1954,7 @@ xfs_parseargs(
}
if (args->flags & XFSMNT_NORECOVERY) {
- if ((vfsp->vfs_flag & VFS_RDONLY) == 0) {
+ if ((mp->m_flags & XFS_MOUNT_RDONLY) == 0) {
cmn_err(CE_WARN,
"XFS: no-recovery mounts must be read-only.");
return EINVAL;
@@ -1899,6 +1967,18 @@ xfs_parseargs(
return EINVAL;
}
+ if ((args->flags & XFSMNT_GQUOTA) && (args->flags & XFSMNT_PQUOTA)) {
+ cmn_err(CE_WARN,
+ "XFS: cannot mount with both project and group quota");
+ return EINVAL;
+ }
+
+ if ((args->flags & XFSMNT_DMAPI) && *args->mtpt == '\0') {
+ printk("XFS: %s option needs the mount point option as well\n",
+ MNTOPT_DMAPI);
+ return EINVAL;
+ }
+
if ((dsunit && !dswidth) || (!dsunit && dswidth)) {
cmn_err(CE_WARN,
"XFS: sunit and swidth must be specified together");
@@ -1912,6 +1992,18 @@ xfs_parseargs(
return EINVAL;
}
+ /*
+ * Applications using DMI filesystems often expect the
+ * inode generation number to be monotonically increasing.
+ * If we delete inode chunks we break this assumption, so
+ * keep unused inode chunks on disk for DMI filesystems
+ * until we come up with a better solution.
+ * Note that if "ikeep" or "noikeep" mount options are
+ * supplied, then they are honored.
+ */
+ if (!(args->flags & XFSMNT_DMAPI) && !ikeep)
+ args->flags |= XFSMNT_IDELETE;
+
if ((args->flags & XFSMNT_NOALIGN) != XFSMNT_NOALIGN) {
if (dsunit) {
args->sunit = dsunit;
@@ -1927,15 +2019,15 @@ xfs_parseargs(
done:
if (args->flags & XFSMNT_32BITINODES)
- vfsp->vfs_flag |= VFS_32BITINODES;
+ mp->m_flags |= XFS_MOUNT_SMALL_INUMS;
if (args->flags2)
args->flags |= XFSMNT_FLAGS2;
return 0;
}
-STATIC int
+int
xfs_showargs(
- struct bhv_desc *bhv,
+ struct xfs_mount *mp,
struct seq_file *m)
{
static struct proc_xfs_info {
@@ -1953,17 +2045,12 @@ xfs_showargs(
{ 0, NULL }
};
struct proc_xfs_info *xfs_infop;
- struct xfs_mount *mp = XFS_BHVTOM(bhv);
- struct bhv_vfs *vfsp = XFS_MTOVFS(mp);
for (xfs_infop = xfs_info; xfs_infop->flag; xfs_infop++) {
if (mp->m_flags & xfs_infop->flag)
seq_puts(m, xfs_infop->str);
}
- if (mp->m_flags & XFS_MOUNT_IHASHSIZE)
- seq_printf(m, "," MNTOPT_IHASHSIZE "=%d", (int)mp->m_ihsize);
-
if (mp->m_flags & XFS_MOUNT_DFLT_IOSIZE)
seq_printf(m, "," MNTOPT_ALLOCSIZE "=%dk",
(int)(1 << mp->m_writeio_log) >> 10);
@@ -1990,11 +2077,37 @@ xfs_showargs(
if (!(mp->m_flags & XFS_MOUNT_COMPAT_IOSIZE))
seq_printf(m, "," MNTOPT_LARGEIO);
- if (!(vfsp->vfs_flag & VFS_32BITINODES))
+ if (!(mp->m_flags & XFS_MOUNT_SMALL_INUMS))
seq_printf(m, "," MNTOPT_64BITINODE);
- if (vfsp->vfs_flag & VFS_GRPID)
+ if (mp->m_flags & XFS_MOUNT_GRPID)
seq_printf(m, "," MNTOPT_GRPID);
+ if (mp->m_qflags & XFS_UQUOTA_ACCT) {
+ if (mp->m_qflags & XFS_UQUOTA_ENFD)
+ seq_puts(m, "," MNTOPT_USRQUOTA);
+ else
+ seq_puts(m, "," MNTOPT_UQUOTANOENF);
+ }
+
+ if (mp->m_qflags & XFS_PQUOTA_ACCT) {
+ if (mp->m_qflags & XFS_OQUOTA_ENFD)
+ seq_puts(m, "," MNTOPT_PRJQUOTA);
+ else
+ seq_puts(m, "," MNTOPT_PQUOTANOENF);
+ }
+
+ if (mp->m_qflags & XFS_GQUOTA_ACCT) {
+ if (mp->m_qflags & XFS_OQUOTA_ENFD)
+ seq_puts(m, "," MNTOPT_GRPQUOTA);
+ else
+ seq_puts(m, "," MNTOPT_GQUOTANOENF);
+ }
+
+ if (!(mp->m_qflags & XFS_ALL_QUOTA_ACCT))
+ seq_puts(m, "," MNTOPT_NOQUOTA);
+
+ if (mp->m_flags & XFS_MOUNT_DMAPI)
+ seq_puts(m, "," MNTOPT_DMAPI);
return 0;
}
@@ -2003,31 +2116,10 @@ xfs_showargs(
* need to take care of themetadata. Once that's done write a dummy
* record to dirty the log in case of a crash while frozen.
*/
-STATIC void
+void
xfs_freeze(
- bhv_desc_t *bdp)
+ xfs_mount_t *mp)
{
- xfs_mount_t *mp = XFS_BHVTOM(bdp);
-
xfs_attr_quiesce(mp);
xfs_fs_log_dummy(mp);
}
-
-
-bhv_vfsops_t xfs_vfsops = {
- BHV_IDENTITY_INIT(VFS_BHV_XFS,VFS_POSITION_XFS),
- .vfs_parseargs = xfs_parseargs,
- .vfs_showargs = xfs_showargs,
- .vfs_mount = xfs_mount,
- .vfs_unmount = xfs_unmount,
- .vfs_mntupdate = xfs_mntupdate,
- .vfs_root = xfs_root,
- .vfs_statvfs = xfs_statvfs,
- .vfs_sync = xfs_sync,
- .vfs_vget = xfs_vget,
- .vfs_dmapiops = (vfs_dmapiops_t)fs_nosys,
- .vfs_quotactl = (vfs_quotactl_t)fs_nosys,
- .vfs_init_vnode = xfs_initialize_vnode,
- .vfs_force_shutdown = xfs_do_force_shutdown,
- .vfs_freeze = xfs_freeze,
-};
diff --git a/fs/xfs/xfs_vfsops.h b/fs/xfs/xfs_vfsops.h
new file mode 100644
index 000000000000..a592fe02a339
--- /dev/null
+++ b/fs/xfs/xfs_vfsops.h
@@ -0,0 +1,28 @@
+#ifndef _XFS_VFSOPS_H
+#define _XFS_VFSOPS_H 1
+
+struct cred;
+struct xfs_fid;
+struct inode;
+struct kstatfs;
+struct xfs_mount;
+struct xfs_mount_args;
+
+int xfs_mount(struct xfs_mount *mp, struct xfs_mount_args *args,
+ struct cred *credp);
+int xfs_unmount(struct xfs_mount *mp, int flags, struct cred *credp);
+int xfs_mntupdate(struct xfs_mount *mp, int *flags,
+ struct xfs_mount_args *args);
+int xfs_root(struct xfs_mount *mp, bhv_vnode_t **vpp);
+int xfs_statvfs(struct xfs_mount *mp, struct kstatfs *statp,
+ bhv_vnode_t *vp);
+int xfs_sync(struct xfs_mount *mp, int flags);
+int xfs_vget(struct xfs_mount *mp, bhv_vnode_t **vpp, struct xfs_fid *xfid);
+int xfs_parseargs(struct xfs_mount *mp, char *options,
+ struct xfs_mount_args *args, int update);
+int xfs_showargs(struct xfs_mount *mp, struct seq_file *m);
+void xfs_freeze(struct xfs_mount *mp);
+void xfs_do_force_shutdown(struct xfs_mount *mp, int flags, char *fname,
+ int lnnum);
+
+#endif /* _XFS_VFSOPS_H */
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 603459229904..efd5aff9eaf6 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -52,15 +52,13 @@
#include "xfs_trans_space.h"
#include "xfs_log_priv.h"
#include "xfs_filestream.h"
+#include "xfs_vnodeops.h"
-STATIC int
+int
xfs_open(
- bhv_desc_t *bdp,
- cred_t *credp)
+ xfs_inode_t *ip)
{
int mode;
- bhv_vnode_t *vp = BHV_TO_VNODE(bdp);
- xfs_inode_t *ip = XFS_BHVTOI(bdp);
if (XFS_FORCED_SHUTDOWN(ip->i_mount))
return XFS_ERROR(EIO);
@@ -69,7 +67,7 @@ xfs_open(
* If it's a directory with any blocks, read-ahead block 0
* as we're almost certain to have the next operation be a read there.
*/
- if (VN_ISDIR(vp) && ip->i_d.di_nextents > 0) {
+ if (S_ISDIR(ip->i_d.di_mode) && ip->i_d.di_nextents > 0) {
mode = xfs_ilock_map_shared(ip);
if (ip->i_d.di_nextents > 0)
(void)xfs_da_reada_buf(NULL, ip, 0, XFS_DATA_FORK);
@@ -81,22 +79,16 @@ xfs_open(
/*
* xfs_getattr
*/
-STATIC int
+int
xfs_getattr(
- bhv_desc_t *bdp,
+ xfs_inode_t *ip,
bhv_vattr_t *vap,
- int flags,
- cred_t *credp)
+ int flags)
{
- xfs_inode_t *ip;
- xfs_mount_t *mp;
- bhv_vnode_t *vp;
-
- vp = BHV_TO_VNODE(bdp);
- vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
+ bhv_vnode_t *vp = XFS_ITOV(ip);
+ xfs_mount_t *mp = ip->i_mount;
- ip = XFS_BHVTOI(bdp);
- mp = ip->i_mount;
+ vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address);
if (XFS_FORCED_SHUTDOWN(mp))
return XFS_ERROR(EIO);
@@ -215,14 +207,14 @@ xfs_getattr(
*/
int
xfs_setattr(
- bhv_desc_t *bdp,
+ xfs_inode_t *ip,
bhv_vattr_t *vap,
int flags,
cred_t *credp)
{
- xfs_inode_t *ip;
+ bhv_vnode_t *vp = XFS_ITOV(ip);
+ xfs_mount_t *mp = ip->i_mount;
xfs_trans_t *tp;
- xfs_mount_t *mp;
int mask;
int code;
uint lock_flags;
@@ -230,17 +222,15 @@ xfs_setattr(
uid_t uid=0, iuid=0;
gid_t gid=0, igid=0;
int timeflags = 0;
- bhv_vnode_t *vp;
xfs_prid_t projid=0, iprojid=0;
int mandlock_before, mandlock_after;
struct xfs_dquot *udqp, *gdqp, *olddquot1, *olddquot2;
int file_owner;
int need_iolock = 1;
- vp = BHV_TO_VNODE(bdp);
- vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
+ vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address);
- if (vp->v_vfsp->vfs_flag & VFS_RDONLY)
+ if (mp->m_flags & XFS_MOUNT_RDONLY)
return XFS_ERROR(EROFS);
/*
@@ -251,9 +241,6 @@ xfs_setattr(
return XFS_ERROR(EINVAL);
}
- ip = XFS_BHVTOI(bdp);
- mp = ip->i_mount;
-
if (XFS_FORCED_SHUTDOWN(mp))
return XFS_ERROR(EIO);
@@ -337,7 +324,7 @@ xfs_setattr(
}
}
} else {
- if (DM_EVENT_ENABLED (vp->v_vfsp, ip, DM_EVENT_TRUNCATE) &&
+ if (DM_EVENT_ENABLED(ip, DM_EVENT_TRUNCATE) &&
!(flags & ATTR_DMI)) {
int dmflags = AT_DELAY_FLAG(flags) | DM_SEM_FLAG_WR;
code = XFS_SEND_DATA(mp, DM_EVENT_TRUNCATE, vp,
@@ -605,13 +592,13 @@ xfs_setattr(
if (!code &&
(ip->i_size != ip->i_d.di_size) &&
(vap->va_size > ip->i_d.di_size)) {
- code = bhv_vop_flush_pages(XFS_ITOV(ip),
+ code = xfs_flush_pages(ip,
ip->i_d.di_size, vap->va_size,
XFS_B_ASYNC, FI_NONE);
}
/* wait for all I/O to complete */
- vn_iowait(vp);
+ vn_iowait(ip);
if (!code)
code = xfs_itruncate_data(ip, vap->va_size);
@@ -673,7 +660,7 @@ xfs_setattr(
* vnode and flush it when the file is closed, and
* do not wait the usual (long) time for writeout.
*/
- VTRUNCATE(vp);
+ xfs_iflags_set(ip, XFS_ITRUNCATED);
}
/*
* Have to do this even if the file's size doesn't change.
@@ -877,10 +864,6 @@ xfs_setattr(
* racing calls to vop_vnode_change.
*/
mandlock_after = MANDLOCK(vp, ip->i_d.di_mode);
- if (mandlock_before != mandlock_after) {
- bhv_vop_vnode_change(vp, VCHANGE_FLAGS_ENF_LOCKING,
- mandlock_after);
- }
xfs_iunlock(ip, lock_flags);
@@ -896,7 +879,7 @@ xfs_setattr(
return code;
}
- if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_ATTRIBUTE) &&
+ if (DM_EVENT_ENABLED(ip, DM_EVENT_ATTRIBUTE) &&
!(flags & ATTR_DMI)) {
(void) XFS_SEND_NAMESP(mp, DM_EVENT_ATTRIBUTE, vp, DM_RIGHT_NULL,
NULL, DM_RIGHT_NULL, NULL, NULL,
@@ -924,19 +907,16 @@ xfs_setattr(
* xfs_access
* Null conversion from vnode mode bits to inode mode bits, as in efs.
*/
-STATIC int
+int
xfs_access(
- bhv_desc_t *bdp,
+ xfs_inode_t *ip,
int mode,
cred_t *credp)
{
- xfs_inode_t *ip;
int error;
- vn_trace_entry(BHV_TO_VNODE(bdp), __FUNCTION__,
- (inst_t *)__return_address);
+ vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address);
- ip = XFS_BHVTOI(bdp);
xfs_ilock(ip, XFS_ILOCK_SHARED);
error = xfs_iaccess(ip, mode, credp);
xfs_iunlock(ip, XFS_ILOCK_SHARED);
@@ -951,105 +931,88 @@ xfs_access(
*/
#define SYMLINK_MAPS 2
-/*
- * xfs_readlink
- *
- */
STATIC int
-xfs_readlink(
- bhv_desc_t *bdp,
- uio_t *uiop,
- int ioflags,
- cred_t *credp)
+xfs_readlink_bmap(
+ xfs_inode_t *ip,
+ char *link)
{
- xfs_inode_t *ip;
- int count;
- xfs_off_t offset;
- int pathlen;
- bhv_vnode_t *vp;
- int error = 0;
- xfs_mount_t *mp;
- int nmaps;
+ xfs_mount_t *mp = ip->i_mount;
+ int pathlen = ip->i_d.di_size;
+ int nmaps = SYMLINK_MAPS;
xfs_bmbt_irec_t mval[SYMLINK_MAPS];
xfs_daddr_t d;
int byte_cnt;
int n;
xfs_buf_t *bp;
+ int error = 0;
- vp = BHV_TO_VNODE(bdp);
- vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
-
- ip = XFS_BHVTOI(bdp);
- mp = ip->i_mount;
+ error = xfs_bmapi(NULL, ip, 0, XFS_B_TO_FSB(mp, pathlen), 0, NULL, 0,
+ mval, &nmaps, NULL, NULL);
+ if (error)
+ goto out;
- if (XFS_FORCED_SHUTDOWN(mp))
- return XFS_ERROR(EIO);
+ for (n = 0; n < nmaps; n++) {
+ d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
+ byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
- xfs_ilock(ip, XFS_ILOCK_SHARED);
+ bp = xfs_buf_read(mp->m_ddev_targp, d, BTOBB(byte_cnt), 0);
+ error = XFS_BUF_GETERROR(bp);
+ if (error) {
+ xfs_ioerror_alert("xfs_readlink",
+ ip->i_mount, bp, XFS_BUF_ADDR(bp));
+ xfs_buf_relse(bp);
+ goto out;
+ }
+ if (pathlen < byte_cnt)
+ byte_cnt = pathlen;
+ pathlen -= byte_cnt;
- ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFLNK);
+ memcpy(link, XFS_BUF_PTR(bp), byte_cnt);
+ xfs_buf_relse(bp);
+ }
- offset = uiop->uio_offset;
- count = uiop->uio_resid;
+ link[ip->i_d.di_size] = '\0';
+ error = 0;
- if (offset < 0) {
- error = XFS_ERROR(EINVAL);
- goto error_return;
- }
- if (count <= 0) {
- error = 0;
- goto error_return;
- }
+ out:
+ return error;
+}
- /*
- * See if the symlink is stored inline.
- */
- pathlen = (int)ip->i_d.di_size;
+int
+xfs_readlink(
+ xfs_inode_t *ip,
+ char *link)
+{
+ xfs_mount_t *mp = ip->i_mount;
+ int pathlen;
+ int error = 0;
- if (ip->i_df.if_flags & XFS_IFINLINE) {
- error = xfs_uio_read(ip->i_df.if_u1.if_data, pathlen, uiop);
- }
- else {
- /*
- * Symlink not inline. Call bmap to get it in.
- */
- nmaps = SYMLINK_MAPS;
+ vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address);
- error = xfs_bmapi(NULL, ip, 0, XFS_B_TO_FSB(mp, pathlen),
- 0, NULL, 0, mval, &nmaps, NULL, NULL);
+ if (XFS_FORCED_SHUTDOWN(mp))
+ return XFS_ERROR(EIO);
- if (error) {
- goto error_return;
- }
+ xfs_ilock(ip, XFS_ILOCK_SHARED);
- for (n = 0; n < nmaps; n++) {
- d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
- byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
- bp = xfs_buf_read(mp->m_ddev_targp, d,
- BTOBB(byte_cnt), 0);
- error = XFS_BUF_GETERROR(bp);
- if (error) {
- xfs_ioerror_alert("xfs_readlink",
- ip->i_mount, bp, XFS_BUF_ADDR(bp));
- xfs_buf_relse(bp);
- goto error_return;
- }
- if (pathlen < byte_cnt)
- byte_cnt = pathlen;
- pathlen -= byte_cnt;
+ ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFLNK);
+ ASSERT(ip->i_d.di_size <= MAXPATHLEN);
- error = xfs_uio_read(XFS_BUF_PTR(bp), byte_cnt, uiop);
- xfs_buf_relse (bp);
- }
+ pathlen = ip->i_d.di_size;
+ if (!pathlen)
+ goto out;
+ if (ip->i_df.if_flags & XFS_IFINLINE) {
+ memcpy(link, ip->i_df.if_u1.if_data, pathlen);
+ link[pathlen] = '\0';
+ } else {
+ error = xfs_readlink_bmap(ip, link);
}
-error_return:
+ out:
xfs_iunlock(ip, XFS_ILOCK_SHARED);
return error;
}
-
/*
* xfs_fsync
*
@@ -1059,23 +1022,18 @@ error_return:
* be held while flushing the data, so acquire after we're done
* with that.
*/
-STATIC int
+int
xfs_fsync(
- bhv_desc_t *bdp,
+ xfs_inode_t *ip,
int flag,
- cred_t *credp,
xfs_off_t start,
xfs_off_t stop)
{
- xfs_inode_t *ip;
xfs_trans_t *tp;
int error;
int log_flushed = 0, changed = 1;
- vn_trace_entry(BHV_TO_VNODE(bdp),
- __FUNCTION__, (inst_t *)__return_address);
-
- ip = XFS_BHVTOI(bdp);
+ vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address);
ASSERT(start >= 0 && stop >= -1);
@@ -1545,27 +1503,24 @@ xfs_inactive_attrs(
return 0;
}
-STATIC int
+int
xfs_release(
- bhv_desc_t *bdp)
+ xfs_inode_t *ip)
{
- xfs_inode_t *ip;
- bhv_vnode_t *vp;
- xfs_mount_t *mp;
+ bhv_vnode_t *vp = XFS_ITOV(ip);
+ xfs_mount_t *mp = ip->i_mount;
int error;
- vp = BHV_TO_VNODE(bdp);
- ip = XFS_BHVTOI(bdp);
- mp = ip->i_mount;
-
if (!VN_ISREG(vp) || (ip->i_d.di_mode == 0))
return 0;
/* If this is a read-only mount, don't do this (would generate I/O) */
- if (vp->v_vfsp->vfs_flag & VFS_RDONLY)
+ if (mp->m_flags & XFS_MOUNT_RDONLY)
return 0;
if (!XFS_FORCED_SHUTDOWN(mp)) {
+ int truncated;
+
/*
* If we are using filestreams, and we have an unlinked
* file that we are processing the last close on, then nothing
@@ -1586,8 +1541,9 @@ xfs_release(
* significantly reducing the time window where we'd otherwise
* be exposed to that problem.
*/
- if (VUNTRUNCATE(vp) && VN_DIRTY(vp) && ip->i_delayed_blks > 0)
- bhv_vop_flush_pages(vp, 0, -1, XFS_B_ASYNC, FI_NONE);
+ truncated = xfs_iflags_test_and_clear(ip, XFS_ITRUNCATED);
+ if (truncated && VN_DIRTY(vp) && ip->i_delayed_blks > 0)
+ xfs_flush_pages(ip, 0, -1, XFS_B_ASYNC, FI_NONE);
}
#ifdef HAVE_REFCACHE
@@ -1623,13 +1579,11 @@ xfs_release(
* now be truncated. Also, we clear all of the read-ahead state
* kept for the inode here since the file is now closed.
*/
-STATIC int
+int
xfs_inactive(
- bhv_desc_t *bdp,
- cred_t *credp)
+ xfs_inode_t *ip)
{
- xfs_inode_t *ip;
- bhv_vnode_t *vp;
+ bhv_vnode_t *vp = XFS_ITOV(ip);
xfs_bmap_free_t free_list;
xfs_fsblock_t first_block;
int committed;
@@ -1638,10 +1592,7 @@ xfs_inactive(
int error;
int truncate;
- vp = BHV_TO_VNODE(bdp);
- vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
-
- ip = XFS_BHVTOI(bdp);
+ vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address);
/*
* If the inode is already free, then there can be nothing
@@ -1666,15 +1617,14 @@ xfs_inactive(
mp = ip->i_mount;
- if (ip->i_d.di_nlink == 0 &&
- DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_DESTROY)) {
+ if (ip->i_d.di_nlink == 0 && DM_EVENT_ENABLED(ip, DM_EVENT_DESTROY)) {
(void) XFS_SEND_DESTROY(mp, vp, DM_RIGHT_NULL);
}
error = 0;
/* If this is a read-only mount, don't do this (would generate I/O) */
- if (vp->v_vfsp->vfs_flag & VFS_RDONLY)
+ if (mp->m_flags & XFS_MOUNT_RDONLY)
goto out;
if (ip->i_d.di_nlink != 0) {
@@ -1844,34 +1794,24 @@ xfs_inactive(
}
-/*
- * xfs_lookup
- */
-STATIC int
+int
xfs_lookup(
- bhv_desc_t *dir_bdp,
+ xfs_inode_t *dp,
bhv_vname_t *dentry,
- bhv_vnode_t **vpp,
- int flags,
- bhv_vnode_t *rdir,
- cred_t *credp)
+ bhv_vnode_t **vpp)
{
- xfs_inode_t *dp, *ip;
+ xfs_inode_t *ip;
xfs_ino_t e_inum;
int error;
uint lock_mode;
- bhv_vnode_t *dir_vp;
- dir_vp = BHV_TO_VNODE(dir_bdp);
- vn_trace_entry(dir_vp, __FUNCTION__, (inst_t *)__return_address);
-
- dp = XFS_BHVTOI(dir_bdp);
+ vn_trace_entry(dp, __FUNCTION__, (inst_t *)__return_address);
if (XFS_FORCED_SHUTDOWN(dp->i_mount))
return XFS_ERROR(EIO);
lock_mode = xfs_ilock_map_shared(dp);
- error = xfs_dir_lookup_int(dir_bdp, lock_mode, dentry, &e_inum, &ip);
+ error = xfs_dir_lookup_int(dp, lock_mode, dentry, &e_inum, &ip);
if (!error) {
*vpp = XFS_ITOV(ip);
ITRACE(ip);
@@ -1880,53 +1820,43 @@ xfs_lookup(
return error;
}
-
-/*
- * xfs_create (create a new file).
- */
-STATIC int
+int
xfs_create(
- bhv_desc_t *dir_bdp,
+ xfs_inode_t *dp,
bhv_vname_t *dentry,
- bhv_vattr_t *vap,
+ mode_t mode,
+ xfs_dev_t rdev,
bhv_vnode_t **vpp,
cred_t *credp)
{
char *name = VNAME(dentry);
- bhv_vnode_t *dir_vp;
- xfs_inode_t *dp, *ip;
+ xfs_mount_t *mp = dp->i_mount;
+ bhv_vnode_t *dir_vp = XFS_ITOV(dp);
+ xfs_inode_t *ip;
bhv_vnode_t *vp = NULL;
xfs_trans_t *tp;
- xfs_mount_t *mp;
- xfs_dev_t rdev;
int error;
xfs_bmap_free_t free_list;
xfs_fsblock_t first_block;
- boolean_t dp_joined_to_trans;
+ boolean_t unlock_dp_on_error = B_FALSE;
int dm_event_sent = 0;
uint cancel_flags;
int committed;
xfs_prid_t prid;
struct xfs_dquot *udqp, *gdqp;
uint resblks;
- int dm_di_mode;
int namelen;
ASSERT(!*vpp);
- dir_vp = BHV_TO_VNODE(dir_bdp);
- vn_trace_entry(dir_vp, __FUNCTION__, (inst_t *)__return_address);
+ vn_trace_entry(dp, __FUNCTION__, (inst_t *)__return_address);
- dp = XFS_BHVTOI(dir_bdp);
- mp = dp->i_mount;
-
- dm_di_mode = vap->va_mode;
namelen = VNAMELEN(dentry);
- if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_CREATE)) {
+ if (DM_EVENT_ENABLED(dp, DM_EVENT_CREATE)) {
error = XFS_SEND_NAMESP(mp, DM_EVENT_CREATE,
dir_vp, DM_RIGHT_NULL, NULL,
DM_RIGHT_NULL, name, NULL,
- dm_di_mode, 0, 0);
+ mode, 0, 0);
if (error)
return error;
@@ -1941,8 +1871,6 @@ xfs_create(
udqp = gdqp = NULL;
if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
prid = dp->i_d.di_projid;
- else if (vap->va_mask & XFS_AT_PROJID)
- prid = (xfs_prid_t)vap->va_projid;
else
prid = (xfs_prid_t)dfltprid;
@@ -1956,7 +1884,6 @@ xfs_create(
goto std_return;
ip = NULL;
- dp_joined_to_trans = B_FALSE;
tp = xfs_trans_alloc(mp, XFS_TRANS_CREATE);
cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
@@ -1976,11 +1903,11 @@ xfs_create(
}
if (error) {
cancel_flags = 0;
- dp = NULL;
goto error_return;
}
xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
+ unlock_dp_on_error = B_TRUE;
XFS_BMAP_INIT(&free_list, &first_block);
@@ -1995,8 +1922,7 @@ xfs_create(
if (resblks == 0 && (error = xfs_dir_canenter(tp, dp, name, namelen)))
goto error_return;
- rdev = (vap->va_mask & XFS_AT_RDEV) ? vap->va_rdev : 0;
- error = xfs_dir_ialloc(&tp, dp, vap->va_mode, 1,
+ error = xfs_dir_ialloc(&tp, dp, mode, 1,
rdev, credp, prid, resblks > 0,
&ip, &committed);
if (error) {
@@ -2014,15 +1940,15 @@ xfs_create(
ASSERT(ismrlocked (&ip->i_lock, MR_UPDATE));
/*
- * Now we join the directory inode to the transaction.
- * We do not do it earlier because xfs_dir_ialloc
- * might commit the previous transaction (and release
- * all the locks).
+ * Now we join the directory inode to the transaction. We do not do it
+ * earlier because xfs_dir_ialloc might commit the previous transaction
+ * (and release all the locks). An error from here on will result in
+ * the transaction cancel unlocking dp so don't do it explicitly in the
+ * error path.
*/
-
VN_HOLD(dir_vp);
xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
- dp_joined_to_trans = B_TRUE;
+ unlock_dp_on_error = B_FALSE;
error = xfs_dir_createname(tp, dp, name, namelen, ip->i_ino,
&first_block, &free_list, resblks ?
@@ -2076,25 +2002,18 @@ xfs_create(
XFS_QM_DQRELE(mp, udqp);
XFS_QM_DQRELE(mp, gdqp);
- /*
- * Propagate the fact that the vnode changed after the
- * xfs_inode locks have been released.
- */
- bhv_vop_vnode_change(vp, VCHANGE_FLAGS_TRUNCATED, 3);
-
*vpp = vp;
/* Fallthrough to std_return with error = 0 */
std_return:
- if ( (*vpp || (error != 0 && dm_event_sent != 0)) &&
- DM_EVENT_ENABLED(dir_vp->v_vfsp, XFS_BHVTOI(dir_bdp),
- DM_EVENT_POSTCREATE)) {
+ if ((*vpp || (error != 0 && dm_event_sent != 0)) &&
+ DM_EVENT_ENABLED(dp, DM_EVENT_POSTCREATE)) {
(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTCREATE,
dir_vp, DM_RIGHT_NULL,
*vpp ? vp:NULL,
DM_RIGHT_NULL, name, NULL,
- dm_di_mode, error, 0);
+ mode, error, 0);
}
return error;
@@ -2106,11 +2025,12 @@ std_return:
if (tp != NULL)
xfs_trans_cancel(tp, cancel_flags);
- if (!dp_joined_to_trans && (dp != NULL))
- xfs_iunlock(dp, XFS_ILOCK_EXCL);
XFS_QM_DQRELE(mp, udqp);
XFS_QM_DQRELE(mp, gdqp);
+ if (unlock_dp_on_error)
+ xfs_iunlock(dp, XFS_ILOCK_EXCL);
+
goto std_return;
abort_rele:
@@ -2381,22 +2301,16 @@ int remove_which_error_return = 0;
#define REMOVE_DEBUG_TRACE(x)
#endif /* ! DEBUG */
-
-/*
- * xfs_remove
- *
- */
-STATIC int
+int
xfs_remove(
- bhv_desc_t *dir_bdp,
- bhv_vname_t *dentry,
- cred_t *credp)
+ xfs_inode_t *dp,
+ bhv_vname_t *dentry)
{
- bhv_vnode_t *dir_vp;
+ bhv_vnode_t *dir_vp = XFS_ITOV(dp);
char *name = VNAME(dentry);
- xfs_inode_t *dp, *ip;
+ xfs_mount_t *mp = dp->i_mount;
+ xfs_inode_t *ip;
xfs_trans_t *tp = NULL;
- xfs_mount_t *mp;
int error = 0;
xfs_bmap_free_t free_list;
xfs_fsblock_t first_block;
@@ -2407,11 +2321,7 @@ xfs_remove(
uint resblks;
int namelen;
- dir_vp = BHV_TO_VNODE(dir_bdp);
- vn_trace_entry(dir_vp, __FUNCTION__, (inst_t *)__return_address);
-
- dp = XFS_BHVTOI(dir_bdp);
- mp = dp->i_mount;
+ vn_trace_entry(dp, __FUNCTION__, (inst_t *)__return_address);
if (XFS_FORCED_SHUTDOWN(mp))
return XFS_ERROR(EIO);
@@ -2423,7 +2333,7 @@ xfs_remove(
IRELE(ip);
}
- if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_REMOVE)) {
+ if (DM_EVENT_ENABLED(dp, DM_EVENT_REMOVE)) {
error = XFS_SEND_NAMESP(mp, DM_EVENT_REMOVE, dir_vp,
DM_RIGHT_NULL, NULL, DM_RIGHT_NULL,
name, NULL, dm_di_mode, 0, 0);
@@ -2454,7 +2364,7 @@ xfs_remove(
dm_di_mode = ip->i_d.di_mode;
- vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address);
+ vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address);
ITRACE(ip);
@@ -2588,19 +2498,13 @@ xfs_remove(
if (link_zero && xfs_inode_is_filestream(ip))
xfs_filestream_deassociate(ip);
- vn_trace_exit(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address);
-
- /*
- * Let interposed file systems know about removed links.
- */
- bhv_vop_link_removed(XFS_ITOV(ip), dir_vp, link_zero);
+ vn_trace_exit(ip, __FUNCTION__, (inst_t *)__return_address);
IRELE(ip);
/* Fall through to std_return with error = 0 */
std_return:
- if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp,
- DM_EVENT_POSTREMOVE)) {
+ if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTREMOVE)) {
(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE,
dir_vp, DM_RIGHT_NULL,
NULL, DM_RIGHT_NULL,
@@ -2638,46 +2542,36 @@ xfs_remove(
goto std_return;
}
-
-/*
- * xfs_link
- *
- */
-STATIC int
+int
xfs_link(
- bhv_desc_t *target_dir_bdp,
+ xfs_inode_t *tdp,
bhv_vnode_t *src_vp,
- bhv_vname_t *dentry,
- cred_t *credp)
+ bhv_vname_t *dentry)
{
- xfs_inode_t *tdp, *sip;
+ bhv_vnode_t *target_dir_vp = XFS_ITOV(tdp);
+ xfs_mount_t *mp = tdp->i_mount;
+ xfs_inode_t *sip = xfs_vtoi(src_vp);
xfs_trans_t *tp;
- xfs_mount_t *mp;
xfs_inode_t *ips[2];
int error;
xfs_bmap_free_t free_list;
xfs_fsblock_t first_block;
int cancel_flags;
int committed;
- bhv_vnode_t *target_dir_vp;
int resblks;
char *target_name = VNAME(dentry);
int target_namelen;
- target_dir_vp = BHV_TO_VNODE(target_dir_bdp);
- vn_trace_entry(target_dir_vp, __FUNCTION__, (inst_t *)__return_address);
- vn_trace_entry(src_vp, __FUNCTION__, (inst_t *)__return_address);
+ vn_trace_entry(tdp, __FUNCTION__, (inst_t *)__return_address);
+ vn_trace_entry(xfs_vtoi(src_vp), __FUNCTION__, (inst_t *)__return_address);
target_namelen = VNAMELEN(dentry);
ASSERT(!VN_ISDIR(src_vp));
- sip = xfs_vtoi(src_vp);
- tdp = XFS_BHVTOI(target_dir_bdp);
- mp = tdp->i_mount;
if (XFS_FORCED_SHUTDOWN(mp))
return XFS_ERROR(EIO);
- if (DM_EVENT_ENABLED(src_vp->v_vfsp, tdp, DM_EVENT_LINK)) {
+ if (DM_EVENT_ENABLED(tdp, DM_EVENT_LINK)) {
error = XFS_SEND_NAMESP(mp, DM_EVENT_LINK,
target_dir_vp, DM_RIGHT_NULL,
src_vp, DM_RIGHT_NULL,
@@ -2788,8 +2682,7 @@ xfs_link(
/* Fall through to std_return with error = 0. */
std_return:
- if (DM_EVENT_ENABLED(src_vp->v_vfsp, sip,
- DM_EVENT_POSTLINK)) {
+ if (DM_EVENT_ENABLED(sip, DM_EVENT_POSTLINK)) {
(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTLINK,
target_dir_vp, DM_RIGHT_NULL,
src_vp, DM_RIGHT_NULL,
@@ -2807,57 +2700,43 @@ std_return:
}
-/*
- * xfs_mkdir
- *
- */
-STATIC int
+int
xfs_mkdir(
- bhv_desc_t *dir_bdp,
+ xfs_inode_t *dp,
bhv_vname_t *dentry,
- bhv_vattr_t *vap,
+ mode_t mode,
bhv_vnode_t **vpp,
cred_t *credp)
{
+ bhv_vnode_t *dir_vp = XFS_ITOV(dp);
char *dir_name = VNAME(dentry);
- xfs_inode_t *dp;
+ int dir_namelen = VNAMELEN(dentry);
+ xfs_mount_t *mp = dp->i_mount;
xfs_inode_t *cdp; /* inode of created dir */
bhv_vnode_t *cvp; /* vnode of created dir */
xfs_trans_t *tp;
- xfs_mount_t *mp;
int cancel_flags;
int error;
int committed;
xfs_bmap_free_t free_list;
xfs_fsblock_t first_block;
- bhv_vnode_t *dir_vp;
- boolean_t dp_joined_to_trans;
+ boolean_t unlock_dp_on_error = B_FALSE;
boolean_t created = B_FALSE;
int dm_event_sent = 0;
xfs_prid_t prid;
struct xfs_dquot *udqp, *gdqp;
uint resblks;
- int dm_di_mode;
- int dir_namelen;
-
- dir_vp = BHV_TO_VNODE(dir_bdp);
- dp = XFS_BHVTOI(dir_bdp);
- mp = dp->i_mount;
if (XFS_FORCED_SHUTDOWN(mp))
return XFS_ERROR(EIO);
- dir_namelen = VNAMELEN(dentry);
-
tp = NULL;
- dp_joined_to_trans = B_FALSE;
- dm_di_mode = vap->va_mode;
- if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_CREATE)) {
+ if (DM_EVENT_ENABLED(dp, DM_EVENT_CREATE)) {
error = XFS_SEND_NAMESP(mp, DM_EVENT_CREATE,
dir_vp, DM_RIGHT_NULL, NULL,
DM_RIGHT_NULL, dir_name, NULL,
- dm_di_mode, 0, 0);
+ mode, 0, 0);
if (error)
return error;
dm_event_sent = 1;
@@ -2865,14 +2744,12 @@ xfs_mkdir(
/* Return through std_return after this point. */
- vn_trace_entry(dir_vp, __FUNCTION__, (inst_t *)__return_address);
+ vn_trace_entry(dp, __FUNCTION__, (inst_t *)__return_address);
mp = dp->i_mount;
udqp = gdqp = NULL;
if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
prid = dp->i_d.di_projid;
- else if (vap->va_mask & XFS_AT_PROJID)
- prid = (xfs_prid_t)vap->va_projid;
else
prid = (xfs_prid_t)dfltprid;
@@ -2898,11 +2775,11 @@ xfs_mkdir(
}
if (error) {
cancel_flags = 0;
- dp = NULL;
goto error_return;
}
xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
+ unlock_dp_on_error = B_TRUE;
/*
* Check for directory link count overflow.
@@ -2925,7 +2802,7 @@ xfs_mkdir(
/*
* create the directory inode.
*/
- error = xfs_dir_ialloc(&tp, dp, vap->va_mode, 2,
+ error = xfs_dir_ialloc(&tp, dp, mode, 2,
0, credp, prid, resblks > 0,
&cdp, NULL);
if (error) {
@@ -2939,11 +2816,13 @@ xfs_mkdir(
* Now we add the directory inode to the transaction.
* We waited until now since xfs_dir_ialloc might start
* a new transaction. Had we joined the transaction
- * earlier, the locks might have gotten released.
+ * earlier, the locks might have gotten released. An error
+ * from here on will result in the transaction cancel
+ * unlocking dp so don't do it explicitly in the error path.
*/
VN_HOLD(dir_vp);
xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
- dp_joined_to_trans = B_TRUE;
+ unlock_dp_on_error = B_FALSE;
XFS_BMAP_INIT(&free_list, &first_block);
@@ -3010,15 +2889,14 @@ xfs_mkdir(
* xfs_trans_commit. */
std_return:
- if ( (created || (error != 0 && dm_event_sent != 0)) &&
- DM_EVENT_ENABLED(dir_vp->v_vfsp, XFS_BHVTOI(dir_bdp),
- DM_EVENT_POSTCREATE)) {
+ if ((created || (error != 0 && dm_event_sent != 0)) &&
+ DM_EVENT_ENABLED(dp, DM_EVENT_POSTCREATE)) {
(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTCREATE,
dir_vp, DM_RIGHT_NULL,
created ? XFS_ITOV(cdp):NULL,
DM_RIGHT_NULL,
dir_name, NULL,
- dm_di_mode, error, 0);
+ mode, error, 0);
}
return error;
@@ -3032,56 +2910,43 @@ std_return:
XFS_QM_DQRELE(mp, udqp);
XFS_QM_DQRELE(mp, gdqp);
- if (!dp_joined_to_trans && (dp != NULL)) {
+ if (unlock_dp_on_error)
xfs_iunlock(dp, XFS_ILOCK_EXCL);
- }
goto std_return;
}
-
-/*
- * xfs_rmdir
- *
- */
-STATIC int
+int
xfs_rmdir(
- bhv_desc_t *dir_bdp,
- bhv_vname_t *dentry,
- cred_t *credp)
+ xfs_inode_t *dp,
+ bhv_vname_t *dentry)
{
+ bhv_vnode_t *dir_vp = XFS_ITOV(dp);
char *name = VNAME(dentry);
- xfs_inode_t *dp;
- xfs_inode_t *cdp; /* child directory */
+ int namelen = VNAMELEN(dentry);
+ xfs_mount_t *mp = dp->i_mount;
+ xfs_inode_t *cdp; /* child directory */
xfs_trans_t *tp;
- xfs_mount_t *mp;
int error;
xfs_bmap_free_t free_list;
xfs_fsblock_t first_block;
int cancel_flags;
int committed;
- bhv_vnode_t *dir_vp;
int dm_di_mode = S_IFDIR;
int last_cdp_link;
- int namelen;
uint resblks;
- dir_vp = BHV_TO_VNODE(dir_bdp);
- dp = XFS_BHVTOI(dir_bdp);
- mp = dp->i_mount;
-
- vn_trace_entry(dir_vp, __FUNCTION__, (inst_t *)__return_address);
+ vn_trace_entry(dp, __FUNCTION__, (inst_t *)__return_address);
- if (XFS_FORCED_SHUTDOWN(XFS_BHVTOI(dir_bdp)->i_mount))
+ if (XFS_FORCED_SHUTDOWN(mp))
return XFS_ERROR(EIO);
- namelen = VNAMELEN(dentry);
if (!xfs_get_dir_entry(dentry, &cdp)) {
dm_di_mode = cdp->i_d.di_mode;
IRELE(cdp);
}
- if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_REMOVE)) {
+ if (DM_EVENT_ENABLED(dp, DM_EVENT_REMOVE)) {
error = XFS_SEND_NAMESP(mp, DM_EVENT_REMOVE,
dir_vp, DM_RIGHT_NULL,
NULL, DM_RIGHT_NULL,
@@ -3260,17 +3125,12 @@ xfs_rmdir(
}
- /*
- * Let interposed file systems know about removed links.
- */
- bhv_vop_link_removed(XFS_ITOV(cdp), dir_vp, last_cdp_link);
-
IRELE(cdp);
/* Fall through to std_return with error = 0 or the errno
* from xfs_trans_commit. */
std_return:
- if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_POSTREMOVE)) {
+ if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTREMOVE)) {
(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE,
dir_vp, DM_RIGHT_NULL,
NULL, DM_RIGHT_NULL,
@@ -3289,56 +3149,24 @@ xfs_rmdir(
goto std_return;
}
-
-/*
- * Read dp's entries starting at uiop->uio_offset and translate them into
- * bufsize bytes worth of struct dirents starting at bufbase.
- */
-STATIC int
-xfs_readdir(
- bhv_desc_t *dir_bdp,
- uio_t *uiop,
- cred_t *credp,
- int *eofp)
-{
- xfs_inode_t *dp;
- xfs_trans_t *tp = NULL;
- int error = 0;
- uint lock_mode;
-
- vn_trace_entry(BHV_TO_VNODE(dir_bdp), __FUNCTION__,
- (inst_t *)__return_address);
- dp = XFS_BHVTOI(dir_bdp);
-
- if (XFS_FORCED_SHUTDOWN(dp->i_mount))
- return XFS_ERROR(EIO);
-
- lock_mode = xfs_ilock_map_shared(dp);
- error = xfs_dir_getdents(tp, dp, uiop, eofp);
- xfs_iunlock_map_shared(dp, lock_mode);
- return error;
-}
-
-
-STATIC int
+int
xfs_symlink(
- bhv_desc_t *dir_bdp,
+ xfs_inode_t *dp,
bhv_vname_t *dentry,
- bhv_vattr_t *vap,
char *target_path,
+ mode_t mode,
bhv_vnode_t **vpp,
cred_t *credp)
{
+ bhv_vnode_t *dir_vp = XFS_ITOV(dp);
+ xfs_mount_t *mp = dp->i_mount;
xfs_trans_t *tp;
- xfs_mount_t *mp;
- xfs_inode_t *dp;
xfs_inode_t *ip;
int error;
int pathlen;
xfs_bmap_free_t free_list;
xfs_fsblock_t first_block;
- boolean_t dp_joined_to_trans;
- bhv_vnode_t *dir_vp;
+ boolean_t unlock_dp_on_error = B_FALSE;
uint cancel_flags;
int committed;
xfs_fileoff_t first_fsb;
@@ -3357,16 +3185,12 @@ xfs_symlink(
int link_namelen;
*vpp = NULL;
- dir_vp = BHV_TO_VNODE(dir_bdp);
- dp = XFS_BHVTOI(dir_bdp);
- dp_joined_to_trans = B_FALSE;
error = 0;
ip = NULL;
tp = NULL;
- vn_trace_entry(dir_vp, __FUNCTION__, (inst_t *)__return_address);
+ vn_trace_entry(dp, __FUNCTION__, (inst_t *)__return_address);
- mp = dp->i_mount;
if (XFS_FORCED_SHUTDOWN(mp))
return XFS_ERROR(EIO);
@@ -3405,7 +3229,7 @@ xfs_symlink(
}
}
- if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_SYMLINK)) {
+ if (DM_EVENT_ENABLED(dp, DM_EVENT_SYMLINK)) {
error = XFS_SEND_NAMESP(mp, DM_EVENT_SYMLINK, dir_vp,
DM_RIGHT_NULL, NULL, DM_RIGHT_NULL,
link_name, target_path, 0, 0, 0);
@@ -3418,8 +3242,6 @@ xfs_symlink(
udqp = gdqp = NULL;
if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
prid = dp->i_d.di_projid;
- else if (vap->va_mask & XFS_AT_PROJID)
- prid = (xfs_prid_t)vap->va_projid;
else
prid = (xfs_prid_t)dfltprid;
@@ -3452,11 +3274,11 @@ xfs_symlink(
}
if (error) {
cancel_flags = 0;
- dp = NULL;
goto error_return;
}
xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
+ unlock_dp_on_error = B_TRUE;
/*
* Check whether the directory allows new symlinks or not.
@@ -3488,7 +3310,7 @@ xfs_symlink(
/*
* Allocate an inode for the symlink.
*/
- error = xfs_dir_ialloc(&tp, dp, S_IFLNK | (vap->va_mode&~S_IFMT),
+ error = xfs_dir_ialloc(&tp, dp, S_IFLNK | (mode & ~S_IFMT),
1, 0, credp, prid, resblks > 0, &ip, NULL);
if (error) {
if (error == ENOSPC)
@@ -3497,9 +3319,14 @@ xfs_symlink(
}
ITRACE(ip);
+ /*
+ * An error after we've joined dp to the transaction will result in the
+ * transaction cancel unlocking dp so don't do it explicitly in the
+ * error path.
+ */
VN_HOLD(dir_vp);
xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
- dp_joined_to_trans = B_TRUE;
+ unlock_dp_on_error = B_FALSE;
/*
* Also attach the dquot(s) to it, if applicable.
@@ -3605,8 +3432,7 @@ xfs_symlink(
/* Fall through to std_return with error = 0 or errno from
* xfs_trans_commit */
std_return:
- if (DM_EVENT_ENABLED(dir_vp->v_vfsp, XFS_BHVTOI(dir_bdp),
- DM_EVENT_POSTSYMLINK)) {
+ if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTSYMLINK)) {
(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTSYMLINK,
dir_vp, DM_RIGHT_NULL,
error ? NULL : XFS_ITOV(ip),
@@ -3633,35 +3459,21 @@ std_return:
XFS_QM_DQRELE(mp, udqp);
XFS_QM_DQRELE(mp, gdqp);
- if (!dp_joined_to_trans && (dp != NULL)) {
+ if (unlock_dp_on_error)
xfs_iunlock(dp, XFS_ILOCK_EXCL);
- }
goto std_return;
}
-/*
- * xfs_fid2
- *
- * A fid routine that takes a pointer to a previously allocated
- * fid structure (like xfs_fast_fid) but uses a 64 bit inode number.
- */
-STATIC int
+int
xfs_fid2(
- bhv_desc_t *bdp,
- fid_t *fidp)
+ xfs_inode_t *ip,
+ xfs_fid_t *xfid)
{
- xfs_inode_t *ip;
- xfs_fid2_t *xfid;
-
- vn_trace_entry(BHV_TO_VNODE(bdp), __FUNCTION__,
- (inst_t *)__return_address);
- ASSERT(sizeof(fid_t) >= sizeof(xfs_fid2_t));
+ vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address);
- xfid = (xfs_fid2_t *)fidp;
- ip = XFS_BHVTOI(bdp);
- xfid->fid_len = sizeof(xfs_fid2_t) - sizeof(xfid->fid_len);
+ xfid->fid_len = sizeof(xfs_fid_t) - sizeof(xfid->fid_len);
xfid->fid_pad = 0;
/*
* use memcpy because the inode is a long long and there's no
@@ -3674,21 +3486,13 @@ xfs_fid2(
}
-/*
- * xfs_rwlock
- */
int
xfs_rwlock(
- bhv_desc_t *bdp,
+ xfs_inode_t *ip,
bhv_vrwlock_t locktype)
{
- xfs_inode_t *ip;
- bhv_vnode_t *vp;
-
- vp = BHV_TO_VNODE(bdp);
- if (VN_ISDIR(vp))
+ if (S_ISDIR(ip->i_d.di_mode))
return 1;
- ip = XFS_BHVTOI(bdp);
if (locktype == VRWLOCK_WRITE) {
xfs_ilock(ip, XFS_IOLOCK_EXCL);
} else if (locktype == VRWLOCK_TRY_READ) {
@@ -3705,21 +3509,13 @@ xfs_rwlock(
}
-/*
- * xfs_rwunlock
- */
void
xfs_rwunlock(
- bhv_desc_t *bdp,
+ xfs_inode_t *ip,
bhv_vrwlock_t locktype)
{
- xfs_inode_t *ip;
- bhv_vnode_t *vp;
-
- vp = BHV_TO_VNODE(bdp);
- if (VN_ISDIR(vp))
- return;
- ip = XFS_BHVTOI(bdp);
+ if (S_ISDIR(ip->i_d.di_mode))
+ return;
if (locktype == VRWLOCK_WRITE) {
/*
* In the write case, we may have added a new entry to
@@ -3737,20 +3533,16 @@ xfs_rwunlock(
return;
}
-STATIC int
+
+int
xfs_inode_flush(
- bhv_desc_t *bdp,
+ xfs_inode_t *ip,
int flags)
{
- xfs_inode_t *ip;
- xfs_mount_t *mp;
- xfs_inode_log_item_t *iip;
+ xfs_mount_t *mp = ip->i_mount;
+ xfs_inode_log_item_t *iip = ip->i_itemp;
int error = 0;
- ip = XFS_BHVTOI(bdp);
- mp = ip->i_mount;
- iip = ip->i_itemp;
-
if (XFS_FORCED_SHUTDOWN(mp))
return XFS_ERROR(EIO);
@@ -3819,24 +3611,20 @@ xfs_inode_flush(
return error;
}
+
int
-xfs_set_dmattrs (
- bhv_desc_t *bdp,
+xfs_set_dmattrs(
+ xfs_inode_t *ip,
u_int evmask,
- u_int16_t state,
- cred_t *credp)
+ u_int16_t state)
{
- xfs_inode_t *ip;
+ xfs_mount_t *mp = ip->i_mount;
xfs_trans_t *tp;
- xfs_mount_t *mp;
int error;
if (!capable(CAP_SYS_ADMIN))
return XFS_ERROR(EPERM);
- ip = XFS_BHVTOI(bdp);
- mp = ip->i_mount;
-
if (XFS_FORCED_SHUTDOWN(mp))
return XFS_ERROR(EIO);
@@ -3859,17 +3647,13 @@ xfs_set_dmattrs (
return error;
}
-STATIC int
+int
xfs_reclaim(
- bhv_desc_t *bdp)
+ xfs_inode_t *ip)
{
- xfs_inode_t *ip;
- bhv_vnode_t *vp;
-
- vp = BHV_TO_VNODE(bdp);
- ip = XFS_BHVTOI(bdp);
+ bhv_vnode_t *vp = XFS_ITOV(ip);
- vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
+ vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address);
ASSERT(!VN_MAPPED(vp));
@@ -3879,7 +3663,7 @@ xfs_reclaim(
return 0;
}
- vn_iowait(vp);
+ vn_iowait(ip);
ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0);
@@ -3911,7 +3695,8 @@ xfs_reclaim(
XFS_MOUNT_ILOCK(mp);
spin_lock(&ip->i_flags_lock);
__xfs_iflags_set(ip, XFS_IRECLAIMABLE);
- vn_bhv_remove(VN_BHV_HEAD(vp), XFS_ITOBHV(ip));
+ vn_to_inode(vp)->i_private = NULL;
+ ip->i_vnode = NULL;
spin_unlock(&ip->i_flags_lock);
list_add_tail(&ip->i_reclaim, &mp->m_del_inodes);
XFS_MOUNT_IUNLOCK(mp);
@@ -3925,7 +3710,7 @@ xfs_finish_reclaim(
int locked,
int sync_mode)
{
- xfs_ihash_t *ih = ip->i_hash;
+ xfs_perag_t *pag = xfs_get_perag(ip->i_mount, ip->i_ino);
bhv_vnode_t *vp = XFS_ITOV_NULL(ip);
int error;
@@ -3937,12 +3722,12 @@ xfs_finish_reclaim(
* Once we have the XFS_IRECLAIM flag set it will not touch
* us.
*/
- write_lock(&ih->ih_lock);
+ write_lock(&pag->pag_ici_lock);
spin_lock(&ip->i_flags_lock);
if (__xfs_iflags_test(ip, XFS_IRECLAIM) ||
(!__xfs_iflags_test(ip, XFS_IRECLAIMABLE) && vp == NULL)) {
spin_unlock(&ip->i_flags_lock);
- write_unlock(&ih->ih_lock);
+ write_unlock(&pag->pag_ici_lock);
if (locked) {
xfs_ifunlock(ip);
xfs_iunlock(ip, XFS_ILOCK_EXCL);
@@ -3951,7 +3736,8 @@ xfs_finish_reclaim(
}
__xfs_iflags_set(ip, XFS_IRECLAIM);
spin_unlock(&ip->i_flags_lock);
- write_unlock(&ih->ih_lock);
+ write_unlock(&pag->pag_ici_lock);
+ xfs_put_perag(ip->i_mount, pag);
/*
* If the inode is still dirty, then flush it out. If the inode
@@ -4085,7 +3871,7 @@ xfs_alloc_file_space(
int committed;
int error;
- vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address);
+ vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address);
if (XFS_FORCED_SHUTDOWN(mp))
return XFS_ERROR(EIO);
@@ -4109,7 +3895,7 @@ xfs_alloc_file_space(
/* Generate a DMAPI event if needed. */
if (alloc_type != 0 && offset < ip->i_size &&
(attr_flags&ATTR_DMI) == 0 &&
- DM_EVENT_ENABLED(XFS_MTOVFS(mp), ip, DM_EVENT_WRITE)) {
+ DM_EVENT_ENABLED(ip, DM_EVENT_WRITE)) {
xfs_off_t end_dmi_offset;
end_dmi_offset = offset+len;
@@ -4223,9 +4009,8 @@ retry:
allocatesize_fsb -= allocated_fsb;
}
dmapi_enospc_check:
- if (error == ENOSPC && (attr_flags&ATTR_DMI) == 0 &&
- DM_EVENT_ENABLED(XFS_MTOVFS(mp), ip, DM_EVENT_NOSPACE)) {
-
+ if (error == ENOSPC && (attr_flags & ATTR_DMI) == 0 &&
+ DM_EVENT_ENABLED(ip, DM_EVENT_NOSPACE)) {
error = XFS_SEND_NAMESP(mp, DM_EVENT_NOSPACE,
XFS_ITOV(ip), DM_RIGHT_NULL,
XFS_ITOV(ip), DM_RIGHT_NULL,
@@ -4356,7 +4141,7 @@ xfs_free_file_space(
vp = XFS_ITOV(ip);
mp = ip->i_mount;
- vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
+ vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address);
if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
return error;
@@ -4369,9 +4154,8 @@ xfs_free_file_space(
end_dmi_offset = offset + len;
endoffset_fsb = XFS_B_TO_FSBT(mp, end_dmi_offset);
- if (offset < ip->i_size &&
- (attr_flags & ATTR_DMI) == 0 &&
- DM_EVENT_ENABLED(XFS_MTOVFS(mp), ip, DM_EVENT_WRITE)) {
+ if (offset < ip->i_size && (attr_flags & ATTR_DMI) == 0 &&
+ DM_EVENT_ENABLED(ip, DM_EVENT_WRITE)) {
if (end_dmi_offset > ip->i_size)
end_dmi_offset = ip->i_size;
error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, vp,
@@ -4385,7 +4169,7 @@ xfs_free_file_space(
need_iolock = 0;
if (need_iolock) {
xfs_ilock(ip, XFS_IOLOCK_EXCL);
- vn_iowait(vp); /* wait for the completion of any pending DIOs */
+ vn_iowait(ip); /* wait for the completion of any pending DIOs */
}
rounding = max_t(uint, 1 << mp->m_sb.sb_blocklog, NBPP);
@@ -4394,7 +4178,8 @@ xfs_free_file_space(
if (VN_CACHED(vp) != 0) {
xfs_inval_cached_trace(&ip->i_iocore, ioffset, -1,
ctooff(offtoct(ioffset)), -1);
- error = bhv_vop_flushinval_pages(vp, ctooff(offtoct(ioffset)),
+ error = xfs_flushinval_pages(ip,
+ ctooff(offtoct(ioffset)),
-1, FI_REMAPF_LOCKED);
if (error)
goto out_unlock_iolock;
@@ -4545,35 +4330,29 @@ xfs_free_file_space(
*/
int
xfs_change_file_space(
- bhv_desc_t *bdp,
+ xfs_inode_t *ip,
int cmd,
xfs_flock64_t *bf,
xfs_off_t offset,
cred_t *credp,
int attr_flags)
{
+ xfs_mount_t *mp = ip->i_mount;
int clrprealloc;
int error;
xfs_fsize_t fsize;
- xfs_inode_t *ip;
- xfs_mount_t *mp;
int setprealloc;
xfs_off_t startoffset;
xfs_off_t llen;
xfs_trans_t *tp;
bhv_vattr_t va;
- bhv_vnode_t *vp;
- vp = BHV_TO_VNODE(bdp);
- vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
-
- ip = XFS_BHVTOI(bdp);
- mp = ip->i_mount;
+ vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address);
/*
* must be a regular file and have write permission
*/
- if (!VN_ISREG(vp))
+ if (!S_ISREG(ip->i_d.di_mode))
return XFS_ERROR(EINVAL);
xfs_ilock(ip, XFS_ILOCK_SHARED);
@@ -4655,7 +4434,7 @@ xfs_change_file_space(
va.va_mask = XFS_AT_SIZE;
va.va_size = startoffset;
- error = xfs_setattr(bdp, &va, attr_flags, credp);
+ error = xfs_setattr(ip, &va, attr_flags, credp);
if (error)
return error;
@@ -4714,46 +4493,3 @@ xfs_change_file_space(
return error;
}
-
-bhv_vnodeops_t xfs_vnodeops = {
- BHV_IDENTITY_INIT(VN_BHV_XFS,VNODE_POSITION_XFS),
- .vop_open = xfs_open,
- .vop_read = xfs_read,
-#ifdef HAVE_SPLICE
- .vop_splice_read = xfs_splice_read,
- .vop_splice_write = xfs_splice_write,
-#endif
- .vop_write = xfs_write,
- .vop_ioctl = xfs_ioctl,
- .vop_getattr = xfs_getattr,
- .vop_setattr = xfs_setattr,
- .vop_access = xfs_access,
- .vop_lookup = xfs_lookup,
- .vop_create = xfs_create,
- .vop_remove = xfs_remove,
- .vop_link = xfs_link,
- .vop_rename = xfs_rename,
- .vop_mkdir = xfs_mkdir,
- .vop_rmdir = xfs_rmdir,
- .vop_readdir = xfs_readdir,
- .vop_symlink = xfs_symlink,
- .vop_readlink = xfs_readlink,
- .vop_fsync = xfs_fsync,
- .vop_inactive = xfs_inactive,
- .vop_fid2 = xfs_fid2,
- .vop_rwlock = xfs_rwlock,
- .vop_rwunlock = xfs_rwunlock,
- .vop_bmap = xfs_bmap,
- .vop_reclaim = xfs_reclaim,
- .vop_attr_get = xfs_attr_get,
- .vop_attr_set = xfs_attr_set,
- .vop_attr_remove = xfs_attr_remove,
- .vop_attr_list = xfs_attr_list,
- .vop_link_removed = (vop_link_removed_t)fs_noval,
- .vop_vnode_change = (vop_vnode_change_t)fs_noval,
- .vop_tosspages = fs_tosspages,
- .vop_flushinval_pages = fs_flushinval_pages,
- .vop_flush_pages = fs_flush_pages,
- .vop_release = xfs_release,
- .vop_iflush = xfs_inode_flush,
-};
diff --git a/fs/xfs/xfs_vnodeops.h b/fs/xfs/xfs_vnodeops.h
new file mode 100644
index 000000000000..b7e461c40cfb
--- /dev/null
+++ b/fs/xfs/xfs_vnodeops.h
@@ -0,0 +1,86 @@
+#ifndef _XFS_VNODEOPS_H
+#define _XFS_VNODEOPS_H 1
+
+struct attrlist_cursor_kern;
+struct bhv_vattr;
+struct cred;
+struct file;
+struct inode;
+struct iovec;
+struct kiocb;
+struct pipe_inode_info;
+struct uio;
+struct xfs_inode;
+struct xfs_iomap;
+
+
+int xfs_open(struct xfs_inode *ip);
+int xfs_getattr(struct xfs_inode *ip, struct bhv_vattr *vap, int flags);
+int xfs_setattr(struct xfs_inode *ip, struct bhv_vattr *vap, int flags,
+ struct cred *credp);
+int xfs_access(struct xfs_inode *ip, int mode, struct cred *credp);
+int xfs_readlink(struct xfs_inode *ip, char *link);
+int xfs_fsync(struct xfs_inode *ip, int flag, xfs_off_t start,
+ xfs_off_t stop);
+int xfs_release(struct xfs_inode *ip);
+int xfs_inactive(struct xfs_inode *ip);
+int xfs_lookup(struct xfs_inode *dp, bhv_vname_t *dentry,
+ bhv_vnode_t **vpp);
+int xfs_create(struct xfs_inode *dp, bhv_vname_t *dentry, mode_t mode,
+ xfs_dev_t rdev, bhv_vnode_t **vpp, struct cred *credp);
+int xfs_remove(struct xfs_inode *dp, bhv_vname_t *dentry);
+int xfs_link(struct xfs_inode *tdp, bhv_vnode_t *src_vp,
+ bhv_vname_t *dentry);
+int xfs_mkdir(struct xfs_inode *dp, bhv_vname_t *dentry,
+ mode_t mode, bhv_vnode_t **vpp, struct cred *credp);
+int xfs_rmdir(struct xfs_inode *dp, bhv_vname_t *dentry);
+int xfs_readdir(struct xfs_inode *dp, void *dirent, size_t bufsize,
+ xfs_off_t *offset, filldir_t filldir);
+int xfs_symlink(struct xfs_inode *dp, bhv_vname_t *dentry,
+ char *target_path, mode_t mode, bhv_vnode_t **vpp,
+ struct cred *credp);
+int xfs_fid2(struct xfs_inode *ip, struct xfs_fid *xfid);
+int xfs_rwlock(struct xfs_inode *ip, bhv_vrwlock_t locktype);
+void xfs_rwunlock(struct xfs_inode *ip, bhv_vrwlock_t locktype);
+int xfs_inode_flush(struct xfs_inode *ip, int flags);
+int xfs_set_dmattrs(struct xfs_inode *ip, u_int evmask, u_int16_t state);
+int xfs_reclaim(struct xfs_inode *ip);
+int xfs_change_file_space(struct xfs_inode *ip, int cmd,
+ xfs_flock64_t *bf, xfs_off_t offset,
+ struct cred *credp, int attr_flags);
+int xfs_rename(struct xfs_inode *src_dp, bhv_vname_t *src_vname,
+ bhv_vnode_t *target_dir_vp, bhv_vname_t *target_vname);
+int xfs_attr_get(struct xfs_inode *ip, const char *name, char *value,
+ int *valuelenp, int flags, cred_t *cred);
+int xfs_attr_set(struct xfs_inode *dp, const char *name, char *value,
+ int valuelen, int flags);
+int xfs_attr_remove(struct xfs_inode *dp, const char *name, int flags);
+int xfs_attr_list(struct xfs_inode *dp, char *buffer, int bufsize,
+ int flags, struct attrlist_cursor_kern *cursor);
+int xfs_ioctl(struct xfs_inode *ip, struct file *filp,
+ int ioflags, unsigned int cmd, void __user *arg);
+ssize_t xfs_read(struct xfs_inode *ip, struct kiocb *iocb,
+ const struct iovec *iovp, unsigned int segs,
+ loff_t *offset, int ioflags);
+ssize_t xfs_sendfile(struct xfs_inode *ip, struct file *filp,
+ loff_t *offset, int ioflags, size_t count,
+ read_actor_t actor, void *target);
+ssize_t xfs_splice_read(struct xfs_inode *ip, struct file *infilp,
+ loff_t *ppos, struct pipe_inode_info *pipe, size_t count,
+ int flags, int ioflags);
+ssize_t xfs_splice_write(struct xfs_inode *ip,
+ struct pipe_inode_info *pipe, struct file *outfilp,
+ loff_t *ppos, size_t count, int flags, int ioflags);
+ssize_t xfs_write(struct xfs_inode *xip, struct kiocb *iocb,
+ const struct iovec *iovp, unsigned int nsegs,
+ loff_t *offset, int ioflags);
+int xfs_bmap(struct xfs_inode *ip, xfs_off_t offset, ssize_t count,
+ int flags, struct xfs_iomap *iomapp, int *niomaps);
+void xfs_tosspages(struct xfs_inode *inode, xfs_off_t first,
+ xfs_off_t last, int fiopt);
+int xfs_flushinval_pages(struct xfs_inode *ip, xfs_off_t first,
+ xfs_off_t last, int fiopt);
+int xfs_flush_pages(struct xfs_inode *ip, xfs_off_t first,
+ xfs_off_t last, uint64_t flags, int fiopt);
+
+#endif /* _XFS_VNODEOPS_H */
diff --git a/include/Kbuild b/include/Kbuild
index 2d03f995865f..b52288774345 100644
--- a/include/Kbuild
+++ b/include/Kbuild
@@ -1,6 +1,5 @@
header-y += asm-generic/
header-y += linux/
-header-y += scsi/
header-y += sound/
header-y += mtd/
header-y += rdma/
diff --git a/include/acpi/achware.h b/include/acpi/achware.h
index 9df275cf7bc1..4053df943453 100644
--- a/include/acpi/achware.h
+++ b/include/acpi/achware.h
@@ -71,9 +71,9 @@ u32 acpi_hw_get_mode(void);
struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id);
acpi_status
-acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value);
+acpi_hw_register_read(u32 register_id, u32 * return_value);
-acpi_status acpi_hw_register_write(u8 use_lock, u32 register_id, u32 value);
+acpi_status acpi_hw_register_write(u32 register_id, u32 value);
acpi_status
acpi_hw_low_level_read(u32 width,
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 86aea44ce6d4..19c3ead2a90b 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -168,8 +168,7 @@ struct acpi_device_flags {
u32 power_manageable:1;
u32 performance_manageable:1;
u32 wake_capable:1; /* Wakeup(_PRW) supported? */
- u32 force_power_state:1;
- u32 reserved:19;
+ u32 reserved:20;
};
/* File System */
@@ -264,7 +263,6 @@ struct acpi_device_wakeup_flags {
struct acpi_device_wakeup_state {
u8 enabled:1;
- u8 active:1;
};
struct acpi_device_wakeup {
@@ -333,6 +331,7 @@ int acpi_bus_get_power(acpi_handle handle, int *state);
int acpi_bus_set_power(acpi_handle handle, int state);
#ifdef CONFIG_ACPI_PROC_EVENT
int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data);
+int acpi_bus_generate_proc_event4(const char *class, const char *bid, u8 type, int data);
int acpi_bus_receive_event(struct acpi_bus_event *event);
#else
static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index 3d7ab9e0c9fe..9512f0456ad1 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -314,6 +314,8 @@ acpi_resource_to_address64(struct acpi_resource *resource,
*/
acpi_status acpi_get_register(u32 register_id, u32 * return_value);
+acpi_status acpi_get_register_unlocked(u32 register_id, u32 *return_value);
+
acpi_status acpi_set_register(u32 register_id, u32 value);
acpi_status
diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h
index 4e5d3ca53a8e..a1b1b2ee3e51 100644
--- a/include/acpi/actbl1.h
+++ b/include/acpi/actbl1.h
@@ -257,7 +257,8 @@ struct acpi_table_dbgp {
struct acpi_table_dmar {
struct acpi_table_header header; /* Common ACPI table header */
u8 width; /* Host Address Width */
- u8 reserved[11];
+ u8 flags;
+ u8 reserved[10];
};
/* DMAR subtable header */
@@ -265,8 +266,6 @@ struct acpi_table_dmar {
struct acpi_dmar_header {
u16 type;
u16 length;
- u8 flags;
- u8 reserved[3];
};
/* Values for subtable type in struct acpi_dmar_header */
@@ -274,13 +273,15 @@ struct acpi_dmar_header {
enum acpi_dmar_type {
ACPI_DMAR_TYPE_HARDWARE_UNIT = 0,
ACPI_DMAR_TYPE_RESERVED_MEMORY = 1,
- ACPI_DMAR_TYPE_RESERVED = 2 /* 2 and greater are reserved */
+ ACPI_DMAR_TYPE_ATSR = 2,
+ ACPI_DMAR_TYPE_RESERVED = 3 /* 3 and greater are reserved */
};
struct acpi_dmar_device_scope {
u8 entry_type;
u8 length;
- u8 segment;
+ u16 reserved;
+ u8 enumeration_id;
u8 bus;
};
@@ -290,7 +291,14 @@ enum acpi_dmar_scope_type {
ACPI_DMAR_SCOPE_TYPE_NOT_USED = 0,
ACPI_DMAR_SCOPE_TYPE_ENDPOINT = 1,
ACPI_DMAR_SCOPE_TYPE_BRIDGE = 2,
- ACPI_DMAR_SCOPE_TYPE_RESERVED = 3 /* 3 and greater are reserved */
+ ACPI_DMAR_SCOPE_TYPE_IOAPIC = 3,
+ ACPI_DMAR_SCOPE_TYPE_HPET = 4,
+ ACPI_DMAR_SCOPE_TYPE_RESERVED = 5 /* 5 and greater are reserved */
+};
+
+struct acpi_dmar_pci_path {
+ u8 dev;
+ u8 fn;
};
/*
@@ -301,6 +309,9 @@ enum acpi_dmar_scope_type {
struct acpi_dmar_hardware_unit {
struct acpi_dmar_header header;
+ u8 flags;
+ u8 reserved;
+ u16 segment;
u64 address; /* Register Base Address */
};
@@ -312,7 +323,9 @@ struct acpi_dmar_hardware_unit {
struct acpi_dmar_reserved_memory {
struct acpi_dmar_header header;
- u64 address; /* 4_k aligned base address */
+ u16 reserved;
+ u16 segment;
+ u64 base_address; /* 4_k aligned base address */
u64 end_address; /* 4_k aligned limit address */
};
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
index 99934a999e66..26d79f6db8a0 100644
--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -3,6 +3,7 @@
#include <linux/kernel.h>
#include <linux/cpu.h>
+#include <linux/cpuidle.h>
#include <asm/acpi.h>
@@ -75,7 +76,9 @@ struct acpi_processor_cx {
};
struct acpi_processor_power {
+ struct cpuidle_device dev;
struct acpi_processor_cx *state;
+ struct acpi_processor_cx *bm_state;
unsigned long bm_check_timestamp;
u32 default_state;
u32 bm_activity;
@@ -199,6 +202,7 @@ struct acpi_processor_flags {
u8 bm_check:1;
u8 has_cst:1;
u8 power_setup_done:1;
+ u8 bm_rld_set:1;
};
struct acpi_processor {
@@ -322,6 +326,7 @@ int acpi_processor_power_exit(struct acpi_processor *pr,
struct acpi_device *device);
int acpi_processor_suspend(struct acpi_device * device, pm_message_t state);
int acpi_processor_resume(struct acpi_device * device);
+extern struct cpuidle_driver acpi_idle_driver;
/* in processor_thermal.c */
int acpi_processor_get_limit_info(struct acpi_processor *pr);
diff --git a/include/asm-alpha/bitops.h b/include/asm-alpha/bitops.h
index 9e71201000d5..9e19a704d484 100644
--- a/include/asm-alpha/bitops.h
+++ b/include/asm-alpha/bitops.h
@@ -1,7 +1,12 @@
#ifndef _ALPHA_BITOPS_H
#define _ALPHA_BITOPS_H
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
#include <asm/compiler.h>
+#include <asm/barrier.h>
/*
* Copyright 1994, Linus Torvalds.
@@ -69,6 +74,13 @@ clear_bit(unsigned long nr, volatile void * addr)
:"Ir" (1UL << (nr & 31)), "m" (*m));
}
+static inline void
+clear_bit_unlock(unsigned long nr, volatile void * addr)
+{
+ smp_mb();
+ clear_bit(nr, addr);
+}
+
/*
* WARNING: non atomic version.
*/
@@ -81,6 +93,13 @@ __clear_bit(unsigned long nr, volatile void * addr)
}
static inline void
+__clear_bit_unlock(unsigned long nr, volatile void * addr)
+{
+ smp_mb();
+ __clear_bit(nr, addr);
+}
+
+static inline void
change_bit(unsigned long nr, volatile void * addr)
{
unsigned long temp;
@@ -117,6 +136,36 @@ test_and_set_bit(unsigned long nr, volatile void *addr)
int *m = ((int *) addr) + (nr >> 5);
__asm__ __volatile__(
+#ifdef CONFIG_SMP
+ " mb\n"
+#endif
+ "1: ldl_l %0,%4\n"
+ " and %0,%3,%2\n"
+ " bne %2,2f\n"
+ " xor %0,%3,%0\n"
+ " stl_c %0,%1\n"
+ " beq %0,3f\n"
+ "2:\n"
+#ifdef CONFIG_SMP
+ " mb\n"
+#endif
+ ".subsection 2\n"
+ "3: br 1b\n"
+ ".previous"
+ :"=&r" (temp), "=m" (*m), "=&r" (oldbit)
+ :"Ir" (1UL << (nr & 31)), "m" (*m) : "memory");
+
+ return oldbit != 0;
+}
+
+static inline int
+test_and_set_bit_lock(unsigned long nr, volatile void *addr)
+{
+ unsigned long oldbit;
+ unsigned long temp;
+ int *m = ((int *) addr) + (nr >> 5);
+
+ __asm__ __volatile__(
"1: ldl_l %0,%4\n"
" and %0,%3,%2\n"
" bne %2,2f\n"
@@ -158,6 +207,9 @@ test_and_clear_bit(unsigned long nr, volatile void * addr)
int *m = ((int *) addr) + (nr >> 5);
__asm__ __volatile__(
+#ifdef CONFIG_SMP
+ " mb\n"
+#endif
"1: ldl_l %0,%4\n"
" and %0,%3,%2\n"
" beq %2,2f\n"
@@ -199,6 +251,9 @@ test_and_change_bit(unsigned long nr, volatile void * addr)
int *m = ((int *) addr) + (nr >> 5);
__asm__ __volatile__(
+#ifdef CONFIG_SMP
+ " mb\n"
+#endif
"1: ldl_l %0,%4\n"
" and %0,%3,%2\n"
" xor %0,%3,%0\n"
diff --git a/include/asm-alpha/elf.h b/include/asm-alpha/elf.h
index 6c2d78fba264..4b518e3b952c 100644
--- a/include/asm-alpha/elf.h
+++ b/include/asm-alpha/elf.h
@@ -155,6 +155,7 @@ extern int alpha_l1d_cacheshape;
extern int alpha_l2_cacheshape;
extern int alpha_l3_cacheshape;
+/* update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT entries changes */
#define ARCH_DLINFO \
do { \
NEW_AUX_ENT(AT_L1I_CACHESHAPE, alpha_l1i_cacheshape); \
diff --git a/include/asm-alpha/floppy.h b/include/asm-alpha/floppy.h
index 6a9f02af9529..0be50413b2b5 100644
--- a/include/asm-alpha/floppy.h
+++ b/include/asm-alpha/floppy.h
@@ -91,8 +91,6 @@ static int FDC2 = -1;
#define N_FDC 2
#define N_DRIVE 8
-#define FLOPPY_MOTOR_MASK 0xf0
-
/*
* Most Alphas have no problems with floppy DMA crossing 64k borders,
* except for certain ones, like XL and RUFFIAN.
diff --git a/include/asm-alpha/ide.h b/include/asm-alpha/ide.h
index 2a5cc0b367ab..b7bf68d0407b 100644
--- a/include/asm-alpha/ide.h
+++ b/include/asm-alpha/ide.h
@@ -40,7 +40,6 @@ static inline unsigned long ide_default_io_base(int index)
}
}
-#define IDE_ARCH_OBSOLETE_INIT
#define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */
#ifdef CONFIG_PCI
diff --git a/include/asm-alpha/io.h b/include/asm-alpha/io.h
index ab5b60dcef19..38f18cf18c9d 100644
--- a/include/asm-alpha/io.h
+++ b/include/asm-alpha/io.h
@@ -551,12 +551,6 @@ extern void outsl (unsigned long port, const void *src, unsigned long count);
#endif
#define RTC_ALWAYS_BCD 0
-/* Nothing to do */
-
-#define dma_cache_inv(_start,_size) do { } while (0)
-#define dma_cache_wback(_start,_size) do { } while (0)
-#define dma_cache_wback_inv(_start,_size) do { } while (0)
-
/*
* Some mucking forons use if[n]def writeq to check if platform has it.
* It's a bloody bad idea and we probably want ARCH_HAS_WRITEQ for them
diff --git a/include/asm-alpha/page.h b/include/asm-alpha/page.h
index bae7f05716d4..8cc97bfd3789 100644
--- a/include/asm-alpha/page.h
+++ b/include/asm-alpha/page.h
@@ -3,11 +3,12 @@
#ifdef __KERNEL__
+#include <linux/const.h>
#include <asm/pal.h>
/* PAGE_SHIFT determines the page size */
#define PAGE_SHIFT 13
-#define PAGE_SIZE (1UL << PAGE_SHIFT)
+#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
#ifndef __ASSEMBLY__
diff --git a/include/asm-alpha/ptrace.h b/include/asm-alpha/ptrace.h
index 9933b8b3612e..32c7a5cddd59 100644
--- a/include/asm-alpha/ptrace.h
+++ b/include/asm-alpha/ptrace.h
@@ -68,8 +68,6 @@ struct switch_stack {
#ifdef __KERNEL__
-#define __ARCH_SYS_PTRACE 1
-
#define user_mode(regs) (((regs)->ps & 8) != 0)
#define instruction_pointer(regs) ((regs)->pc)
#define profile_pc(regs) instruction_pointer(regs)
diff --git a/include/asm-alpha/scatterlist.h b/include/asm-alpha/scatterlist.h
index 917365405e83..440747ca6349 100644
--- a/include/asm-alpha/scatterlist.h
+++ b/include/asm-alpha/scatterlist.h
@@ -5,7 +5,10 @@
#include <asm/types.h>
struct scatterlist {
- struct page *page;
+#ifdef CONFIG_DEBUG_SG
+ unsigned long sg_magic;
+#endif
+ unsigned long page_link;
unsigned int offset;
unsigned int length;
diff --git a/include/asm-alpha/semaphore.h b/include/asm-alpha/semaphore.h
index 1a6295f2c2d4..f1e9278a9fe2 100644
--- a/include/asm-alpha/semaphore.h
+++ b/include/asm-alpha/semaphore.h
@@ -30,7 +30,6 @@ struct semaphore {
struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
-#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
static inline void sema_init(struct semaphore *sem, int val)
{
diff --git a/include/asm-alpha/system.h b/include/asm-alpha/system.h
index 620c4d86cbf4..fd9dc889f36c 100644
--- a/include/asm-alpha/system.h
+++ b/include/asm-alpha/system.h
@@ -48,6 +48,7 @@
#ifndef __ASSEMBLY__
#include <linux/kernel.h>
+#define AT_VECTOR_SIZE_ARCH 4 /* entries in ARCH_DLINFO */
/*
* This is the logout header that should be common to all platforms
diff --git a/include/asm-alpha/tlbflush.h b/include/asm-alpha/tlbflush.h
index 1ca3ed3bd6d3..eefab3fb51ae 100644
--- a/include/asm-alpha/tlbflush.h
+++ b/include/asm-alpha/tlbflush.h
@@ -92,17 +92,6 @@ flush_tlb_other(struct mm_struct *mm)
if (*mmc) *mmc = 0;
}
-/* Flush a specified range of user mapping page tables from TLB.
- Although Alpha uses VPTE caches, this can be a nop, as Alpha does
- not have finegrained tlb flushing, so it will flush VPTE stuff
- during next flush_tlb_range. */
-
-static inline void
-flush_tlb_pgtables(struct mm_struct *mm, unsigned long start,
- unsigned long end)
-{
-}
-
#ifndef CONFIG_SMP
/* Flush everything (kernel mapping may also have changed
due to vmalloc/vfree). */
diff --git a/include/asm-arm/arch-aaec2000/aaec2000.h b/include/asm-arm/arch-aaec2000/aaec2000.h
index 002227924b9f..a6d1ee0980f2 100644
--- a/include/asm-arm/arch-aaec2000/aaec2000.h
+++ b/include/asm-arm/arch-aaec2000/aaec2000.h
@@ -140,11 +140,11 @@
#define TIMER3_CLEAR __REG(0x80000e0c) /* Timer 3 Clear Register */
/* Timer Control register bits */
-#define TIMER_CTRL_ENABLE (1 << 7) /* Enable (Start° Timer */
+#define TIMER_CTRL_ENABLE (1 << 7) /* Enable (Start Timer) */
#define TIMER_CTRL_PERIODIC (1 << 6) /* Periodic Running Mode */
#define TIMER_CTRL_FREE_RUNNING (0 << 6) /* Normal Running Mode */
#define TIMER_CTRL_CLKSEL_508K (1 << 3) /* 508KHz Clock select (Timer 1, 2) */
-#define TIMER_CTRL_CLKSEL_2K (0 << 3) /* 2KHz Clock Select (Timer 1, 2)*/
+#define TIMER_CTRL_CLKSEL_2K (0 << 3) /* 2KHz Clock Select (Timer 1, 2) */
/* Power and State Control */
#define POWER_BASE __REG(0x80000400)
diff --git a/include/asm-arm/arch-at91/board.h b/include/asm-arm/arch-at91/board.h
index d96b10fd449f..c0d7075982c1 100644
--- a/include/asm-arm/arch-at91/board.h
+++ b/include/asm-arm/arch-at91/board.h
@@ -130,4 +130,7 @@ extern u8 at91_leds_cpu;
extern u8 at91_leds_timer;
extern void __init at91_init_leds(u8 cpu_led, u8 timer_led);
+/* FIXME: this needs a better location, but gets stuff building again */
+extern int at91_suspend_entering_slow_clock(void);
+
#endif
diff --git a/include/asm-arm/arch-davinci/gpio.h b/include/asm-arm/arch-davinci/gpio.h
index ea24a0e0bfd6..ff8de30b2fb3 100644
--- a/include/asm-arm/arch-davinci/gpio.h
+++ b/include/asm-arm/arch-davinci/gpio.h
@@ -13,6 +13,9 @@
#ifndef __DAVINCI_GPIO_H
#define __DAVINCI_GPIO_H
+#include <linux/io.h>
+#include <asm/hardware.h>
+
/*
* basic gpio routines
*
diff --git a/include/asm-arm/arch-imx/imxfb.h b/include/asm-arm/arch-imx/imxfb.h
index 7dbc7bbba65d..3ed9ec8b9f00 100644
--- a/include/asm-arm/arch-imx/imxfb.h
+++ b/include/asm-arm/arch-imx/imxfb.h
@@ -7,6 +7,7 @@ struct imxfb_mach_info {
u_short xres;
u_short yres;
+ u_int nonstd;
u_char bpp;
u_char hsync_len;
u_char left_margin;
diff --git a/include/asm-arm/arch-ixp23xx/platform.h b/include/asm-arm/arch-ixp23xx/platform.h
index 56e16d66645a..db8aa304c93d 100644
--- a/include/asm-arm/arch-ixp23xx/platform.h
+++ b/include/asm-arm/arch-ixp23xx/platform.h
@@ -14,17 +14,17 @@
#ifndef __ASSEMBLY__
-extern inline unsigned long ixp2000_reg_read(volatile void *reg)
+static inline unsigned long ixp2000_reg_read(volatile void *reg)
{
return *((volatile unsigned long *)reg);
}
-extern inline void ixp2000_reg_write(volatile void *reg, unsigned long val)
+static inline void ixp2000_reg_write(volatile void *reg, unsigned long val)
{
*((volatile unsigned long *)reg) = val;
}
-extern inline void ixp2000_reg_wrb(volatile void *reg, unsigned long val)
+static inline void ixp2000_reg_wrb(volatile void *reg, unsigned long val)
{
*((volatile unsigned long *)reg) = val;
}
diff --git a/include/asm-arm/arch-ixp4xx/io.h b/include/asm-arm/arch-ixp4xx/io.h
index c72f9d79417c..eeeea90cd5a9 100644
--- a/include/asm-arm/arch-ixp4xx/io.h
+++ b/include/asm-arm/arch-ixp4xx/io.h
@@ -17,9 +17,6 @@
#define IO_SPACE_LIMIT 0xffff0000
-#define BIT(x) ((1)<<(x))
-
-
extern int (*ixp4xx_pci_read)(u32 addr, u32 cmd, u32* data);
extern int ixp4xx_pci_write(u32 addr, u32 cmd, u32 data);
diff --git a/include/asm-arm/arch-ns9xxx/clock.h b/include/asm-arm/arch-ns9xxx/clock.h
index bf30cbdcc2bf..b943d3a92a1d 100644
--- a/include/asm-arm/arch-ns9xxx/clock.h
+++ b/include/asm-arm/arch-ns9xxx/clock.h
@@ -19,7 +19,7 @@
static inline u32 ns9xxx_systemclock(void) __attribute__((const));
static inline u32 ns9xxx_systemclock(void)
{
- u32 pll = SYS_PLL;
+ u32 pll = __raw_readl(SYS_PLL);
/*
* The system clock should be a multiple of HZ * TIMERCLOCKSELECT (in
@@ -46,8 +46,8 @@ static inline u32 ns9xxx_systemclock(void)
*
* Fine.
*/
- return CRYSTAL * (REGGET(pll, SYS_PLL, ND) + 1)
- >> REGGET(pll, SYS_PLL, FS);
+ return CRYSTAL * (REGGETIM(pll, SYS_PLL, ND) + 1)
+ >> REGGETIM(pll, SYS_PLL, FS);
}
static inline u32 ns9xxx_cpuclock(void) __attribute__((const));
diff --git a/include/asm-arm/arch-ns9xxx/gpio.h b/include/asm-arm/arch-ns9xxx/gpio.h
new file mode 100644
index 000000000000..adbca08583c0
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/gpio.h
@@ -0,0 +1,47 @@
+/*
+ * include/asm-arm/arch-ns9xxx/gpio.h
+ *
+ * Copyright (C) 2007 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+*/
+#ifndef __ASM_ARCH_GPIO_H
+#define __ASM_ARCH_GPIO_H
+
+#include <asm/errno.h>
+
+int gpio_request(unsigned gpio, const char *label);
+
+void gpio_free(unsigned gpio);
+
+int ns9xxx_gpio_configure(unsigned gpio, int inv, int func);
+
+int gpio_direction_input(unsigned gpio);
+
+int gpio_direction_output(unsigned gpio, int value);
+
+int gpio_get_value(unsigned gpio);
+
+void gpio_set_value(unsigned gpio, int value);
+
+/*
+ * ns9xxx can use gpio pins to trigger an irq, but it's not generic
+ * enough to be supported by the gpio_to_irq/irq_to_gpio interface
+ */
+static inline int gpio_to_irq(unsigned gpio)
+{
+ return -EINVAL;
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+ return -EINVAL;
+}
+
+/* get the cansleep() stubs */
+#include <asm-generic/gpio.h>
+
+#endif /* ifndef __ASM_ARCH_GPIO_H */
diff --git a/include/asm-arm/arch-ns9xxx/hardware.h b/include/asm-arm/arch-ns9xxx/hardware.h
index 25600554c4fe..0b7b34603f1c 100644
--- a/include/asm-arm/arch-ns9xxx/hardware.h
+++ b/include/asm-arm/arch-ns9xxx/hardware.h
@@ -27,42 +27,53 @@
#define io_v2p(x) ((((x) & 0x0f000000) << 4) \
+ ((x) & 0x00ffffff))
+#define __REGSHIFT(mask) ((mask) & (-(mask)))
+
#define __REGBIT(bit) ((u32)1 << (bit))
#define __REGBITS(hbit, lbit) ((((u32)1 << ((hbit) - (lbit) + 1)) - 1) << (lbit))
-#define __REGVAL(mask, value) (((value) * ((mask) & (-(mask))) & (mask)))
+#define __REGVAL(mask, value) (((value) * __REGSHIFT(mask)) & (mask))
#ifndef __ASSEMBLY__
-# define __REG(x) (*((volatile u32 *)io_p2v((x))))
-# define __REG2(x, y) (*((volatile u32 *)io_p2v((x)) + (y)))
+# define __REG(x) ((void __iomem __force *)io_p2v((x)))
+# define __REG2(x, y) ((void __iomem __force *)(io_p2v((x)) + 4 * (y)))
-# define __REGB(x) (*((volatile u8 *)io_p2v((x))))
-# define __REGB2(x) (*((volatile u8 *)io_p2v((x)) + (y)))
+# define __REGSET(var, field, value) \
+ ((var) = (((var) & ~((field) & ~(value))) | (value)))
# define REGSET(var, reg, field, value) \
- ((var) = (((var) \
- & ~(reg ## _ ## field & \
- ~ reg ## _ ## field ## _ ## value)) \
- | (reg ## _ ## field ## _ ## value)))
+ __REGSET(var, reg ## _ ## field, reg ## _ ## field ## _ ## value)
+
+# define REGSET_IDX(var, reg, field, idx, value) \
+ __REGSET(var, reg ## _ ## field((idx)), reg ## _ ## field ## _ ## value((idx)))
# define REGSETIM(var, reg, field, value) \
- ((var) = (((var) \
- & ~(reg ## _ ## field & \
- ~(__REGVAL(reg ## _ ## field, value)))) \
- | (__REGVAL(reg ## _ ## field, value))))
+ __REGSET(var, reg ## _ ## field, __REGVAL(reg ## _ ## field, (value)))
+
+# define REGSETIM_IDX(var, reg, field, idx, value) \
+ __REGSET(var, reg ## _ ## field((idx)), __REGVAL(reg ## _ ## field((idx)), (value)))
+
+# define __REGGET(var, field) \
+ (((var) & (field)))
# define REGGET(var, reg, field) \
- ((var & (reg ## _ ## field)) / \
- ((reg ## _ ## field) & (-(reg ## _ ## field))))
+ __REGGET(var, reg ## _ ## field)
+
+# define REGGET_IDX(var, reg, field, idx) \
+ __REGGET(var, reg ## _ ## field((idx)))
+
+# define REGGETIM(var, reg, field) \
+ __REGGET(var, reg ## _ ## field) / __REGSHIFT(reg ## _ ## field)
+
+# define REGGETIM_IDX(var, reg, field, idx) \
+ __REGGET(var, reg ## _ ## field((idx))) / \
+ __REGSHIFT(reg ## _ ## field((idx)))
#else
# define __REG(x) io_p2v(x)
# define __REG2(x, y) io_p2v((x) + (y))
-# define __REGB(x) __REG((x))
-# define __REGB2(x, y) __REG2((x), (y))
-
#endif
#endif /* ifndef __ASM_ARCH_HARDWARE_H */
diff --git a/include/asm-arm/arch-ns9xxx/regs-board-a9m9750dev.h b/include/asm-arm/arch-ns9xxx/regs-board-a9m9750dev.h
index c3dc532dd20c..afa3a9db3e1d 100644
--- a/include/asm-arm/arch-ns9xxx/regs-board-a9m9750dev.h
+++ b/include/asm-arm/arch-ns9xxx/regs-board-a9m9750dev.h
@@ -18,7 +18,7 @@
#define FPGA_UARTC_BASE io_p2v(NS9XXX_CSxSTAT_PHYS(0) + 0x10)
#define FPGA_UARTD_BASE io_p2v(NS9XXX_CSxSTAT_PHYS(0) + 0x18)
-#define FPGA_IER __REGB(NS9XXX_CSxSTAT_PHYS(0) + 0x50)
-#define FPGA_ISR __REGB(NS9XXX_CSxSTAT_PHYS(0) + 0x60)
+#define FPGA_IER __REG(NS9XXX_CSxSTAT_PHYS(0) + 0x50)
+#define FPGA_ISR __REG(NS9XXX_CSxSTAT_PHYS(0) + 0x60)
#endif /* ifndef __ASM_ARCH_REGSBOARDA9M9750_H */
diff --git a/include/asm-arm/arch-ns9xxx/system.h b/include/asm-arm/arch-ns9xxx/system.h
index e3cd4d31b3f3..c1082bd8977c 100644
--- a/include/asm-arm/arch-ns9xxx/system.h
+++ b/include/asm-arm/arch-ns9xxx/system.h
@@ -24,9 +24,9 @@ static inline void arch_reset(char mode)
{
u32 reg;
- reg = SYS_PLL >> 16;
+ reg = __raw_readl(SYS_PLL) >> 16;
REGSET(reg, SYS_PLL, SWC, YES);
- SYS_PLL = reg;
+ __raw_writel(reg, SYS_PLL);
BUG();
}
diff --git a/include/asm-arm/arch-omap/blizzard.h b/include/asm-arm/arch-omap/blizzard.h
new file mode 100644
index 000000000000..8d160f171372
--- /dev/null
+++ b/include/asm-arm/arch-omap/blizzard.h
@@ -0,0 +1,12 @@
+#ifndef _BLIZZARD_H
+#define _BLIZZARD_H
+
+struct blizzard_platform_data {
+ void (*power_up)(struct device *dev);
+ void (*power_down)(struct device *dev);
+ unsigned long (*get_clock_rate)(struct device *dev);
+
+ unsigned te_connected : 1;
+};
+
+#endif
diff --git a/include/asm-arm/arch-omap/board-2430sdp.h b/include/asm-arm/arch-omap/board-2430sdp.h
new file mode 100644
index 000000000000..e9c65ce3cb12
--- /dev/null
+++ b/include/asm-arm/arch-omap/board-2430sdp.h
@@ -0,0 +1,44 @@
+/*
+ * linux/include/asm-arm/arch-omap/board-2430sdp.h
+ *
+ * Hardware definitions for TI OMAP2430 SDP board.
+ *
+ * Based on board-h4.h by Dirk Behme <dirk.behme@de.bosch.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __ASM_ARCH_OMAP_2430SDP_H
+#define __ASM_ARCH_OMAP_2430SDP_H
+
+/* Placeholder for 2430SDP specific defines */
+#define OMAP24XX_ETHR_START 0x08000300
+#define OMAP24XX_ETHR_GPIO_IRQ 149
+#define SDP2430_CS0_BASE 0x04000000
+
+#define TWL4030_IRQNUM INT_24XX_SYS_NIRQ
+
+/* TWL4030 Primary Interrupt Handler (PIH) interrupts */
+#define IH_TWL4030_BASE IH_BOARD_BASE
+#define IH_TWL4030_END (IH_TWL4030_BASE+8)
+#define NR_IRQS (IH_TWL4030_END)
+
+#endif /* __ASM_ARCH_OMAP_2430SDP_H */
diff --git a/include/asm-arm/arch-omap/board-palmte.h b/include/asm-arm/arch-omap/board-palmte.h
new file mode 100644
index 000000000000..cd22035a7160
--- /dev/null
+++ b/include/asm-arm/arch-omap/board-palmte.h
@@ -0,0 +1,34 @@
+/*
+ * linux/include/asm-arm/arch-omap/board-palmte.h
+ *
+ * Hardware definitions for the Palm Tungsten E device.
+ *
+ * Maintainters : http://palmtelinux.sf.net
+ * palmtelinux-developpers@lists.sf.net
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __OMAP_BOARD_PALMTE_H
+#define __OMAP_BOARD_PALMTE_H
+
+#include <asm/arch/gpio.h>
+
+#define PALMTE_USBDETECT_GPIO 0
+#define PALMTE_USB_OR_DC_GPIO 1
+#define PALMTE_TSC_GPIO 4
+#define PALMTE_PINTDAV_GPIO 6
+#define PALMTE_MMC_WP_GPIO 8
+#define PALMTE_MMC_POWER_GPIO 9
+#define PALMTE_HDQ_GPIO 11
+#define PALMTE_HEADPHONES_GPIO 14
+#define PALMTE_SPEAKER_GPIO 15
+#define PALMTE_DC_GPIO OMAP_MPUIO(2)
+#define PALMTE_MMC_SWITCH_GPIO OMAP_MPUIO(4)
+#define PALMTE_MMC1_GPIO OMAP_MPUIO(6)
+#define PALMTE_MMC2_GPIO OMAP_MPUIO(7)
+#define PALMTE_MMC3_GPIO OMAP_MPUIO(11)
+
+#endif /* __OMAP_BOARD_PALMTE_H */
diff --git a/include/asm-arm/arch-omap/board-palmtt.h b/include/asm-arm/arch-omap/board-palmtt.h
new file mode 100644
index 000000000000..d9590b0ec90e
--- /dev/null
+++ b/include/asm-arm/arch-omap/board-palmtt.h
@@ -0,0 +1,23 @@
+/*
+ * linux/include/asm-arm/arch-omap/board-palmte.h
+ *
+ * Hardware definitions for the Palm Tungsten|T device.
+ *
+ * Maintainters : Marek Vasut <marek.vasut@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __OMAP_BOARD_PALMTT_H
+#define __OMAP_BOARD_PALMTT_H
+
+#define PALMTT_USBDETECT_GPIO 0
+#define PALMTT_CABLE_GPIO 1
+#define PALMTT_LED_GPIO 3
+#define PALMTT_PENIRQ_GPIO 6
+#define PALMTT_MMC_WP_GPIO 8
+#define PALMTT_HDQ_GPIO 11
+
+#endif /* __OMAP_BOARD_PALMTT_H */
diff --git a/include/asm-arm/arch-omap/board-palmz71.h b/include/asm-arm/arch-omap/board-palmz71.h
new file mode 100644
index 000000000000..1252a859787d
--- /dev/null
+++ b/include/asm-arm/arch-omap/board-palmz71.h
@@ -0,0 +1,26 @@
+/*
+ * linux/include/asm-arm/arch-omap/board-palmz71.h
+ *
+ * Hardware definitions for the Palm Zire71 device.
+ *
+ * Maintainters : Marek Vasut <marek.vasut@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __OMAP_BOARD_PALMZ71_H
+#define __OMAP_BOARD_PALMZ71_H
+
+#define PALMZ71_USBDETECT_GPIO 0
+#define PALMZ71_PENIRQ_GPIO 6
+#define PALMZ71_MMC_WP_GPIO 8
+#define PALMZ71_HDQ_GPIO 11
+
+#define PALMZ71_HOTSYNC_GPIO OMAP_MPUIO(1)
+#define PALMZ71_CABLE_GPIO OMAP_MPUIO(2)
+#define PALMZ71_SLIDER_GPIO OMAP_MPUIO(3)
+#define PALMZ71_MMC_IN_GPIO OMAP_MPUIO(4)
+
+#endif /* __OMAP_BOARD_PALMZ71_H */
diff --git a/include/asm-arm/arch-omap/board-sx1.h b/include/asm-arm/arch-omap/board-sx1.h
new file mode 100644
index 000000000000..2bb8dd6e2d14
--- /dev/null
+++ b/include/asm-arm/arch-omap/board-sx1.h
@@ -0,0 +1,46 @@
+/*
+ * Siemens SX1 board definitions
+ *
+ * Copyright: Vovan888 at gmail com
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef __ASM_ARCH_SX1_I2C_CHIPS_H
+#define __ASM_ARCH_SX1_I2C_CHIPS_H
+
+#define SOFIA_MAX_LIGHT_VAL 0x2B
+
+#define SOFIA_I2C_ADDR 0x32
+/* Sofia reg 3 bits masks */
+#define SOFIA_POWER1_REG 0x03
+
+#define SOFIA_USB_POWER 0x01
+#define SOFIA_MMC_POWER 0x04
+#define SOFIA_BLUETOOTH_POWER 0x08
+#define SOFIA_MMILIGHT_POWER 0x20
+
+#define SOFIA_POWER2_REG 0x04
+#define SOFIA_BACKLIGHT_REG 0x06
+#define SOFIA_KEYLIGHT_REG 0x07
+#define SOFIA_DIMMING_REG 0x09
+
+
+/* Function Prototypes for SX1 devices control on I2C bus */
+
+int sx1_setbacklight(u8 backlight);
+int sx1_getbacklight(u8 *backlight);
+int sx1_setkeylight(u8 keylight);
+int sx1_getkeylight(u8 *keylight);
+
+int sx1_setmmipower(u8 onoff);
+int sx1_setusbpower(u8 onoff);
+int sx1_setmmcpower(u8 onoff);
+
+#endif /* __ASM_ARCH_SX1_I2C_CHIPS_H */
diff --git a/include/asm-arm/arch-omap/board.h b/include/asm-arm/arch-omap/board.h
index 031672c56377..db44c5d1f1a0 100644
--- a/include/asm-arm/arch-omap/board.h
+++ b/include/asm-arm/arch-omap/board.h
@@ -179,4 +179,8 @@ extern const void *omap_get_var_config(u16 tag, size_t *len);
extern struct omap_board_config_kernel *omap_board_config;
extern int omap_board_config_size;
+
+/* for TI reference platforms sharing the same debug card */
+extern int debug_card_init(u32 addr, unsigned gpio);
+
#endif
diff --git a/include/asm-arm/arch-omap/dma.h b/include/asm-arm/arch-omap/dma.h
index f7774192a41e..f33b467fddb7 100644
--- a/include/asm-arm/arch-omap/dma.h
+++ b/include/asm-arm/arch-omap/dma.h
@@ -417,7 +417,6 @@ extern void omap_free_lcd_dma(void);
extern void omap_setup_lcd_dma(void);
extern void omap_enable_lcd_dma(void);
extern void omap_stop_lcd_dma(void);
-extern int omap_lcd_dma_ext_running(void);
extern void omap_set_lcd_dma_ext_controller(int external);
extern void omap_set_lcd_dma_single_transfer(int single);
extern void omap_set_lcd_dma_b1(unsigned long addr, u16 fb_xres, u16 fb_yres,
diff --git a/include/asm-arm/arch-omap/eac.h b/include/asm-arm/arch-omap/eac.h
new file mode 100644
index 000000000000..6662cb02bafc
--- /dev/null
+++ b/include/asm-arm/arch-omap/eac.h
@@ -0,0 +1,101 @@
+/*
+ * linux/include/asm-arm/arch-omap2/eac.h
+ *
+ * Defines for Enhanced Audio Controller
+ *
+ * Contact: Jarkko Nikula <jarkko.nikula@nokia.com>
+ *
+ * Copyright (C) 2006 Nokia Corporation
+ * Copyright (C) 2004 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __ASM_ARM_ARCH_OMAP2_EAC_H
+#define __ASM_ARM_ARCH_OMAP2_EAC_H
+
+#include <asm/arch/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/irq.h>
+
+#include <sound/driver.h>
+#include <sound/core.h>
+
+/* master codec clock source */
+#define EAC_MCLK_EXT_MASK 0x100
+enum eac_mclk_src {
+ EAC_MCLK_INT_11290000, /* internal 96 MHz / 8.5 = 11.29 Mhz */
+ EAC_MCLK_EXT_11289600 = EAC_MCLK_EXT_MASK,
+ EAC_MCLK_EXT_12288000,
+ EAC_MCLK_EXT_2x11289600,
+ EAC_MCLK_EXT_2x12288000,
+};
+
+/* codec port interface mode */
+enum eac_codec_mode {
+ EAC_CODEC_PCM,
+ EAC_CODEC_AC97,
+ EAC_CODEC_I2S_MASTER, /* codec port, I.e. EAC is the master */
+ EAC_CODEC_I2S_SLAVE,
+};
+
+/* configuration structure for I2S mode */
+struct eac_i2s_conf {
+ /* if enabled, then first data slot (left channel) is signaled as
+ * positive level of frame sync EAC.AC_FS */
+ unsigned polarity_changed_mode:1;
+ /* if enabled, then serial data starts one clock cycle after the
+ * of EAC.AC_FS for first audio slot */
+ unsigned sync_delay_enable:1;
+};
+
+/* configuration structure for EAC codec port */
+struct eac_codec {
+ enum eac_mclk_src mclk_src;
+
+ enum eac_codec_mode codec_mode;
+ union {
+ struct eac_i2s_conf i2s;
+ } codec_conf;
+
+ int default_rate; /* audio sampling rate */
+
+ int (* set_power)(void *private_data, int dac, int adc);
+ int (* register_controls)(void *private_data,
+ struct snd_card *card);
+ const char *short_name;
+
+ void *private_data;
+};
+
+/* structure for passing platform dependent data to the EAC driver */
+struct eac_platform_data {
+ int (* init)(struct device *eac_dev);
+ void (* cleanup)(struct device *eac_dev);
+ /* these callbacks are used to configure & control external MCLK
+ * source. NULL if not used */
+ int (* enable_ext_clocks)(struct device *eac_dev);
+ void (* disable_ext_clocks)(struct device *eac_dev);
+};
+
+extern void omap_init_eac(struct eac_platform_data *pdata);
+
+extern int eac_register_codec(struct device *eac_dev, struct eac_codec *codec);
+extern void eac_unregister_codec(struct device *eac_dev);
+
+extern int eac_set_mode(struct device *eac_dev, int play, int rec);
+
+#endif /* __ASM_ARM_ARCH_OMAP2_EAC_H */
diff --git a/include/asm-arm/arch-omap/gpmc.h b/include/asm-arm/arch-omap/gpmc.h
index 995cc83482eb..6a8e07ffc2d0 100644
--- a/include/asm-arm/arch-omap/gpmc.h
+++ b/include/asm-arm/arch-omap/gpmc.h
@@ -23,9 +23,10 @@
#define GPMC_CS_NAND_DATA 0x24
#define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31)
-#define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 20)
+#define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30)
#define GPMC_CONFIG1_READTYPE_ASYNC (0 << 29)
#define GPMC_CONFIG1_READTYPE_SYNC (1 << 29)
+#define GPMC_CONFIG1_WRITEMULTIPLE_SUPP (1 << 28)
#define GPMC_CONFIG1_WRITETYPE_ASYNC (0 << 27)
#define GPMC_CONFIG1_WRITETYPE_SYNC (1 << 27)
#define GPMC_CONFIG1_CLKACTIVATIONTIME(val) ((val & 3) << 25)
@@ -80,6 +81,8 @@ struct gpmc_timings {
};
extern unsigned int gpmc_ns_to_ticks(unsigned int time_ns);
+extern unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns);
+extern unsigned long gpmc_get_fclk_period(void);
extern void gpmc_cs_write_reg(int cs, int idx, u32 val);
extern u32 gpmc_cs_read_reg(int cs, int idx);
diff --git a/include/asm-arm/arch-omap/hardware.h b/include/asm-arm/arch-omap/hardware.h
index e225f4f39b34..da572092e255 100644
--- a/include/asm-arm/arch-omap/hardware.h
+++ b/include/asm-arm/arch-omap/hardware.h
@@ -318,6 +318,10 @@
#include "board-h4.h"
#endif
+#ifdef CONFIG_MACH_OMAP_2430SDP
+#include "board-2430sdp.h"
+#endif
+
#ifdef CONFIG_MACH_OMAP_APOLLON
#include "board-apollon.h"
#endif
@@ -330,6 +334,22 @@
#include "board-voiceblue.h"
#endif
+#ifdef CONFIG_MACH_OMAP_PALMTE
+#include "board-palmte.h"
+#endif
+
+#ifdef CONFIG_MACH_OMAP_PALMZ71
+#include "board-palmz71.h"
+#endif
+
+#ifdef CONFIG_MACH_OMAP_PALMTT
+#include "board-palmtt.h"
+#endif
+
+#ifdef CONFIG_MACH_SX1
+#include "board-sx1.h"
+#endif
+
#endif /* !__ASSEMBLER__ */
#endif /* __ASM_ARCH_OMAP_HARDWARE_H */
diff --git a/include/asm-arm/arch-omap/io.h b/include/asm-arm/arch-omap/io.h
index 4aca7e3d7566..289082d07f14 100644
--- a/include/asm-arm/arch-omap/io.h
+++ b/include/asm-arm/arch-omap/io.h
@@ -72,6 +72,16 @@
#define L4_24XX_PHYS L4_24XX_BASE /* 0x48000000 */
#define L4_24XX_VIRT 0xd8000000
#define L4_24XX_SIZE SZ_1M /* 1MB of 128MB used, want 1MB sect */
+
+#ifdef CONFIG_ARCH_OMAP2430
+#define L4_WK_243X_PHYS L4_WK_243X_BASE /* 0x49000000 */
+#define L4_WK_243X_VIRT 0xd9000000
+#define L4_WK_243X_SIZE SZ_1M
+#define OMAP243X_GPMC_PHYS OMAP243X_GPMC_BASE /* 0x49000000 */
+#define OMAP243X_GPMC_VIRT 0xFE000000
+#define OMAP243X_GPMC_SIZE SZ_1M
+#endif
+
#define IO_OFFSET 0x90000000
#define IO_ADDRESS(pa) ((pa) + IO_OFFSET) /* Works for L3 and L4 */
#define io_p2v(pa) ((pa) + IO_OFFSET) /* Works for L3 and L4 */
diff --git a/include/asm-arm/arch-omap/menelaus.h b/include/asm-arm/arch-omap/menelaus.h
index 82d276a6bd95..69ed7ee40179 100644
--- a/include/asm-arm/arch-omap/menelaus.h
+++ b/include/asm-arm/arch-omap/menelaus.h
@@ -7,6 +7,12 @@
#ifndef __ASM_ARCH_MENELAUS_H
#define __ASM_ARCH_MENELAUS_H
+struct device;
+
+struct menelaus_platform_data {
+ int (* late_init)(struct device *dev);
+};
+
extern int menelaus_register_mmc_callback(void (*callback)(void *data, u8 card_mask),
void *data);
extern void menelaus_unregister_mmc_callback(void);
@@ -20,6 +26,19 @@ extern int menelaus_set_vaux(unsigned int mV);
extern int menelaus_set_vdcdc(int dcdc, unsigned int mV);
extern int menelaus_set_slot_sel(int enable);
extern int menelaus_get_slot_pin_states(void);
+extern int menelaus_set_vcore_sw(unsigned int mV);
+extern int menelaus_set_vcore_hw(unsigned int roof_mV, unsigned int floor_mV);
+
+#define EN_VPLL_SLEEP (1 << 7)
+#define EN_VMMC_SLEEP (1 << 6)
+#define EN_VAUX_SLEEP (1 << 5)
+#define EN_VIO_SLEEP (1 << 4)
+#define EN_VMEM_SLEEP (1 << 3)
+#define EN_DC3_SLEEP (1 << 2)
+#define EN_DC2_SLEEP (1 << 1)
+#define EN_VC_SLEEP (1 << 0)
+
+extern int menelaus_set_regulator_sleep(int enable, u32 val);
#if defined(CONFIG_ARCH_OMAP24XX) && defined(CONFIG_MENELAUS)
#define omap_has_menelaus() 1
@@ -28,4 +47,3 @@ extern int menelaus_get_slot_pin_states(void);
#endif
#endif
-
diff --git a/include/asm-arm/arch-omap/mmc.h b/include/asm-arm/arch-omap/mmc.h
new file mode 100644
index 000000000000..b70e37b61242
--- /dev/null
+++ b/include/asm-arm/arch-omap/mmc.h
@@ -0,0 +1,66 @@
+/*
+ * MMC definitions for OMAP2
+ *
+ * Copyright (C) 2006 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __OMAP2_MMC_H
+#define __OMAP2_MMC_H
+
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/mmc/host.h>
+
+#define OMAP_MMC_MAX_SLOTS 2
+
+struct omap_mmc_platform_data {
+ unsigned enabled:1;
+ /* number of slots on board */
+ unsigned nr_slots:2;
+ /* nomux means "standard" muxing is wrong on this board, and that
+ * board-specific code handled it before common init logic.
+ */
+ unsigned nomux:1;
+ /* 4 wire signaling is optional, and is only used for SD/SDIO and
+ * MMCv4 */
+ unsigned wire4:1;
+ /* set if your board has components or wiring that limits the
+ * maximum frequency on the MMC bus */
+ unsigned int max_freq;
+
+ /* switch the bus to a new slot */
+ int (* switch_slot)(struct device *dev, int slot);
+ /* initialize board-specific MMC functionality, can be NULL if
+ * not supported */
+ int (* init)(struct device *dev);
+ void (* cleanup)(struct device *dev);
+
+ struct omap_mmc_slot_data {
+ int (* set_bus_mode)(struct device *dev, int slot, int bus_mode);
+ int (* set_power)(struct device *dev, int slot, int power_on, int vdd);
+ int (* get_ro)(struct device *dev, int slot);
+
+ /* return MMC cover switch state, can be NULL if not supported.
+ *
+ * possible return values:
+ * 0 - open
+ * 1 - closed
+ */
+ int (* get_cover_state)(struct device *dev, int slot);
+
+ const char *name;
+ u32 ocr_mask;
+ } slots[OMAP_MMC_MAX_SLOTS];
+};
+
+extern void omap_set_mmc_info(int host, const struct omap_mmc_platform_data *info);
+
+/* called from board-specific card detection service routine */
+extern void omap_mmc_notify_card_detect(struct device *dev, int slot, int detected);
+extern void omap_mmc_notify_cover_event(struct device *dev, int slot, int is_closed);
+
+#endif
diff --git a/include/asm-arm/arch-omap/mux.h b/include/asm-arm/arch-omap/mux.h
index f1ec2edd4040..b8fff50e6a87 100644
--- a/include/asm-arm/arch-omap/mux.h
+++ b/include/asm-arm/arch-omap/mux.h
@@ -406,6 +406,29 @@ enum omap1xxx_index {
V10_1610_CF_IREQ,
W10_1610_CF_RESET,
W11_1610_CF_CD1,
+
+ /* parallel camera */
+ J15_1610_CAM_LCLK,
+ J18_1610_CAM_D7,
+ J19_1610_CAM_D6,
+ J14_1610_CAM_D5,
+ K18_1610_CAM_D4,
+ K19_1610_CAM_D3,
+ K15_1610_CAM_D2,
+ K14_1610_CAM_D1,
+ L19_1610_CAM_D0,
+ L18_1610_CAM_VS,
+ L15_1610_CAM_HS,
+ M19_1610_CAM_RSTZ,
+ Y15_1610_CAM_OUTCLK,
+
+ /* serial camera */
+ H19_1610_CAM_EXCLK,
+ Y12_1610_CCP_CLKP,
+ W13_1610_CCP_CLKM,
+ W14_1610_CCP_DATAP,
+ Y14_1610_CCP_DATAM,
+
};
enum omap24xx_index {
diff --git a/include/asm-arm/arch-omap/omap24xx.h b/include/asm-arm/arch-omap/omap24xx.h
index 708b2fac77f2..14c0f9496579 100644
--- a/include/asm-arm/arch-omap/omap24xx.h
+++ b/include/asm-arm/arch-omap/omap24xx.h
@@ -8,6 +8,7 @@
*/
#define L4_24XX_BASE 0x48000000
+#define L4_WK_243X_BASE 0x49000000
#define L3_24XX_BASE 0x68000000
/* interrupt controller */
@@ -16,9 +17,20 @@
#define OMAP24XX_IVA_INTC_BASE 0x40000000
#define IRQ_SIR_IRQ 0x0040
+#ifdef CONFIG_ARCH_OMAP2420
#define OMAP24XX_32KSYNCT_BASE (L4_24XX_BASE + 0x4000)
#define OMAP24XX_PRCM_BASE (L4_24XX_BASE + 0x8000)
#define OMAP24XX_SDRC_BASE (L3_24XX_BASE + 0x9000)
+#define OMAP242X_CONTROL_STATUS (L4_24XX_BASE + 0x2f8)
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2430
+#define OMAP24XX_32KSYNCT_BASE (L4_WK_243X_BASE + 0x20000)
+#define OMAP24XX_PRCM_BASE (L4_WK_243X_BASE + 0x6000)
+#define OMAP24XX_SDRC_BASE (0x6D000000)
+#define OMAP242X_CONTROL_STATUS (L4_24XX_BASE + 0x2f8)
+#define OMAP243X_GPMC_BASE 0x6E000000
+#endif
/* DSP SS */
#define OMAP24XX_DSP_BASE 0x58000000
diff --git a/include/asm-arm/arch-omap/onenand.h b/include/asm-arm/arch-omap/onenand.h
new file mode 100644
index 000000000000..6c959d0ce470
--- /dev/null
+++ b/include/asm-arm/arch-omap/onenand.h
@@ -0,0 +1,21 @@
+/*
+ * include/asm-arm/arch-omap/onenand.h
+ *
+ * Copyright (C) 2006 Nokia Corporation
+ * Author: Juha Yrjola
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/mtd/partitions.h>
+
+struct omap_onenand_platform_data {
+ int cs;
+ int gpio_irq;
+ struct mtd_partition *parts;
+ int nr_parts;
+ int (*onenand_setup)(void __iomem *);
+ int dma_channel;
+};
diff --git a/include/asm-arm/arch-pxa/cm-x270.h b/include/asm-arm/arch-pxa/cm-x270.h
new file mode 100644
index 000000000000..f8fac9e18009
--- /dev/null
+++ b/include/asm-arm/arch-pxa/cm-x270.h
@@ -0,0 +1,50 @@
+/*
+ * linux/include/asm/arch-pxa/cm-x270.h
+ *
+ * Copyright Compulab Ltd., 2003, 2007
+ * Mike Rapoport <mike@compulab.co.il>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+
+/* CM-x270 device physical addresses */
+#define CMX270_CS1_PHYS (PXA_CS1_PHYS)
+#define MARATHON_PHYS (PXA_CS2_PHYS)
+#define CMX270_IDE104_PHYS (PXA_CS3_PHYS)
+#define CMX270_IT8152_PHYS (PXA_CS4_PHYS)
+
+/* Statically mapped regions */
+#define CMX270_VIRT_BASE (0xe8000000)
+#define CMX270_IT8152_VIRT (CMX270_VIRT_BASE)
+#define CMX270_IDE104_VIRT (CMX270_IT8152_VIRT + SZ_64M)
+
+/* GPIO related definitions */
+#define GPIO_IT8152_IRQ (22)
+
+#define IRQ_GPIO_IT8152_IRQ IRQ_GPIO(GPIO_IT8152_IRQ)
+#define PME_IRQ IRQ_GPIO(0)
+#define CMX270_IDE_IRQ IRQ_GPIO(100)
+#define CMX270_GPIRQ1 IRQ_GPIO(101)
+#define CMX270_TOUCHIRQ IRQ_GPIO(96)
+#define CMX270_ETHIRQ IRQ_GPIO(10)
+#define CMX270_GFXIRQ IRQ_GPIO(95)
+#define CMX270_NANDIRQ IRQ_GPIO(89)
+#define CMX270_MMC_IRQ IRQ_GPIO(83)
+
+/* PCMCIA related definitions */
+#define PCC_DETECT(x) (GPLR(84 - (x)) & GPIO_bit(84 - (x)))
+#define PCC_READY(x) (GPLR(82 - (x)) & GPIO_bit(82 - (x)))
+
+#define PCMCIA_S0_CD_VALID IRQ_GPIO(84)
+#define PCMCIA_S0_CD_VALID_EDGE GPIO_BOTH_EDGES
+
+#define PCMCIA_S1_CD_VALID IRQ_GPIO(83)
+#define PCMCIA_S1_CD_VALID_EDGE GPIO_BOTH_EDGES
+
+#define PCMCIA_S0_RDYINT IRQ_GPIO(82)
+#define PCMCIA_S1_RDYINT IRQ_GPIO(81)
+
+#define PCMCIA_RESET_GPIO 53
diff --git a/include/asm-arm/arch-pxa/dma.h b/include/asm-arm/arch-pxa/dma.h
index 3280ee2ddfa5..dbe110ee2666 100644
--- a/include/asm-arm/arch-pxa/dma.h
+++ b/include/asm-arm/arch-pxa/dma.h
@@ -30,6 +30,10 @@ typedef enum {
DMA_PRIO_LOW = 2
} pxa_dma_prio;
+#if defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI)
+#define HAVE_ARCH_PCI_SET_DMA_MASK 1
+#endif
+
/*
* DMA registration
*/
diff --git a/include/asm-arm/arch-pxa/gpio.h b/include/asm-arm/arch-pxa/gpio.h
index 9e99241f3edf..9dbc2dc794f7 100644
--- a/include/asm-arm/arch-pxa/gpio.h
+++ b/include/asm-arm/arch-pxa/gpio.h
@@ -38,16 +38,8 @@ static inline void gpio_free(unsigned gpio)
return;
}
-static inline int gpio_direction_input(unsigned gpio)
-{
- return pxa_gpio_mode(gpio | GPIO_IN);
-}
-
-static inline int gpio_direction_output(unsigned gpio, int value)
-{
- return pxa_gpio_mode(gpio | GPIO_OUT |
- (value ? GPIO_DFLT_HIGH : GPIO_DFLT_LOW));
-}
+extern int gpio_direction_input(unsigned gpio);
+extern int gpio_direction_output(unsigned gpio, int value);
static inline int __gpio_get_value(unsigned gpio)
{
diff --git a/include/asm-arm/arch-pxa/hardware.h b/include/asm-arm/arch-pxa/hardware.h
index 386121746417..ab2d963e742a 100644
--- a/include/asm-arm/arch-pxa/hardware.h
+++ b/include/asm-arm/arch-pxa/hardware.h
@@ -62,6 +62,7 @@
#ifndef __ASSEMBLY__
+#ifdef CONFIG_PXA25x
#define __cpu_is_pxa21x(id) \
({ \
unsigned int _id = (id) >> 4 & 0xf3f; \
@@ -73,12 +74,50 @@
unsigned int _id = (id) >> 4 & 0xfff; \
_id == 0x2d0 || _id == 0x290; \
})
+#else
+#define __cpu_is_pxa21x(id) (0)
+#define __cpu_is_pxa25x(id) (0)
+#endif
+#ifdef CONFIG_PXA27x
#define __cpu_is_pxa27x(id) \
({ \
unsigned int _id = (id) >> 4 & 0xfff; \
_id == 0x411; \
})
+#else
+#define __cpu_is_pxa27x(id) (0)
+#endif
+
+#ifdef CONFIG_CPU_PXA300
+#define __cpu_is_pxa300(id) \
+ ({ \
+ unsigned int _id = (id) >> 4 & 0xfff; \
+ _id == 0x688; \
+ })
+#else
+#define __cpu_is_pxa300(id) (0)
+#endif
+
+#ifdef CONFIG_CPU_PXA310
+#define __cpu_is_pxa310(id) \
+ ({ \
+ unsigned int _id = (id) >> 4 & 0xfff; \
+ _id == 0x689; \
+ })
+#else
+#define __cpu_is_pxa310(id) (0)
+#endif
+
+#ifdef CONFIG_CPU_PXA320
+#define __cpu_is_pxa320(id) \
+ ({ \
+ unsigned int _id = (id) >> 4 & 0xfff; \
+ _id == 0x603 || _id == 0x682; \
+ })
+#else
+#define __cpu_is_pxa320(id) (0)
+#endif
#define cpu_is_pxa21x() \
({ \
@@ -98,6 +137,53 @@
__cpu_is_pxa27x(id); \
})
+#define cpu_is_pxa300() \
+ ({ \
+ unsigned int id = read_cpuid(CPUID_ID); \
+ __cpu_is_pxa300(id); \
+ })
+
+#define cpu_is_pxa310() \
+ ({ \
+ unsigned int id = read_cpuid(CPUID_ID); \
+ __cpu_is_pxa310(id); \
+ })
+
+#define cpu_is_pxa320() \
+ ({ \
+ unsigned int id = read_cpuid(CPUID_ID); \
+ __cpu_is_pxa320(id); \
+ })
+
+/*
+ * CPUID Core Generation Bit
+ * <= 0x2 for pxa21x/pxa25x/pxa26x/pxa27x
+ * == 0x3 for pxa300/pxa310/pxa320
+ */
+#define __cpu_is_pxa2xx(id) \
+ ({ \
+ unsigned int _id = (id) >> 13 & 0x7; \
+ _id <= 0x2; \
+ })
+
+#define __cpu_is_pxa3xx(id) \
+ ({ \
+ unsigned int _id = (id) >> 13 & 0x7; \
+ _id == 0x3; \
+ })
+
+#define cpu_is_pxa2xx() \
+ ({ \
+ unsigned int id = read_cpuid(CPUID_ID); \
+ __cpu_is_pxa2xx(id); \
+ })
+
+#define cpu_is_pxa3xx() \
+ ({ \
+ unsigned int id = read_cpuid(CPUID_ID); \
+ __cpu_is_pxa3xx(id); \
+ })
+
/*
* Handy routine to set GPIO alternate functions
*/
@@ -116,14 +202,23 @@ extern void pxa_gpio_set_value(unsigned gpio, int value);
/*
* Routine to enable or disable CKEN
*/
-extern void pxa_set_cken(int clock, int enable);
+static inline void __deprecated pxa_set_cken(int clock, int enable)
+{
+ extern void __pxa_set_cken(int clock, int enable);
+ __pxa_set_cken(clock, enable);
+}
/*
* return current memory and LCD clock frequency in units of 10kHz
*/
extern unsigned int get_memclk_frequency_10khz(void);
-extern unsigned int get_lcdclk_frequency_10khz(void);
#endif
+#if defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI)
+#define PCIBIOS_MIN_IO 0
+#define PCIBIOS_MIN_MEM 0
+#define pcibios_assign_all_busses() 1
+#endif
+
#endif /* _ASM_ARCH_HARDWARE_H */
diff --git a/include/asm-arm/arch-pxa/irqs.h b/include/asm-arm/arch-pxa/irqs.h
index a07fe0f928cd..6238dbf7a236 100644
--- a/include/asm-arm/arch-pxa/irqs.h
+++ b/include/asm-arm/arch-pxa/irqs.h
@@ -66,12 +66,6 @@
#define IRQ_TO_GPIO_2_x(i) ((i) - PXA_GPIO_IRQ_BASE)
#define IRQ_TO_GPIO(i) (((i) < IRQ_GPIO(2)) ? ((i) - IRQ_GPIO0) : IRQ_TO_GPIO_2_x(i))
-#if defined(CONFIG_PXA25x)
-#define PXA_LAST_GPIO 84
-#elif defined(CONFIG_PXA27x)
-#define PXA_LAST_GPIO 127
-#endif
-
/*
* The next 16 interrupts are for board specific purposes. Since
* the kernel can only run on one machine at a time, we can re-use
@@ -216,3 +210,24 @@
#define IRQ_LOCOMO_GPIO_BASE (IRQ_BOARD_START + 1)
#define IRQ_LOCOMO_LT_BASE (IRQ_BOARD_START + 2)
#define IRQ_LOCOMO_SPI_BASE (IRQ_BOARD_START + 3)
+
+/* ITE8152 irqs */
+/* add IT8152 IRQs beyond BOARD_END */
+#ifdef CONFIG_PCI_HOST_ITE8152
+#define IT8152_IRQ(x) (IRQ_GPIO(IRQ_BOARD_END) + 1 + (x))
+
+/* IRQ-sources in 3 groups - local devices, LPC (serial), and external PCI */
+#define IT8152_LD_IRQ_COUNT 9
+#define IT8152_LP_IRQ_COUNT 16
+#define IT8152_PD_IRQ_COUNT 15
+
+/* Priorities: */
+#define IT8152_PD_IRQ(i) IT8152_IRQ(i)
+#define IT8152_LP_IRQ(i) (IT8152_IRQ(i) + IT8152_PD_IRQ_COUNT)
+#define IT8152_LD_IRQ(i) (IT8152_IRQ(i) + IT8152_PD_IRQ_COUNT + IT8152_LP_IRQ_COUNT)
+
+#define IT8152_LAST_IRQ IT8152_LD_IRQ(IT8152_LD_IRQ_COUNT - 1)
+
+#undef NR_IRQS
+#define NR_IRQS (IT8152_LAST_IRQ+1)
+#endif
diff --git a/include/asm-arm/arch-pxa/memory.h b/include/asm-arm/arch-pxa/memory.h
index e17f9881faf0..bee81d66c184 100644
--- a/include/asm-arm/arch-pxa/memory.h
+++ b/include/asm-arm/arch-pxa/memory.h
@@ -39,4 +39,14 @@
*/
#define NODE_MEM_SIZE_BITS 26
+#if !defined(__ASSEMBLY__) && defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI)
+void cmx270_pci_adjust_zones(int node, unsigned long *size,
+ unsigned long *holes);
+
+#define arch_adjust_zones(node, size, holes) \
+ cmx270_pci_adjust_zones(node, size, holes)
+
+#define ISA_DMA_THRESHOLD (PHYS_OFFSET + SZ_64M - 1)
+#endif
+
#endif
diff --git a/include/asm-arm/arch-pxa/mfp-pxa300.h b/include/asm-arm/arch-pxa/mfp-pxa300.h
new file mode 100644
index 000000000000..822a27cd7864
--- /dev/null
+++ b/include/asm-arm/arch-pxa/mfp-pxa300.h
@@ -0,0 +1,574 @@
+/*
+ * linux/include/asm-arm/arch-pxa/mfp-pxa300.h
+ *
+ * PXA300/PXA310 specific MFP configuration definitions
+ *
+ * Copyright (C) 2007 Marvell International Ltd.
+ * 2007-08-21: eric miao <eric.miao@marvell.com>
+ * initial version
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_MFP_PXA300_H
+#define __ASM_ARCH_MFP_PXA300_H
+
+#include <asm/arch/mfp.h>
+
+/* GPIO */
+#define GPIO46_GPIO MFP_CFG(GPIO46, AF1)
+#define GPIO49_GPIO MFP_CFG(GPIO49, AF3)
+#define GPIO50_GPIO MFP_CFG(GPIO50, AF2)
+#define GPIO51_GPIO MFP_CFG(GPIO51, AF3)
+#define GPIO52_GPIO MFP_CFG(GPIO52, AF3)
+#define GPIO56_GPIO MFP_CFG(GPIO56, AF0)
+#define GPIO58_GPIO MFP_CFG(GPIO58, AF0)
+#define GPIO59_GPIO MFP_CFG(GPIO59, AF0)
+#define GPIO60_GPIO MFP_CFG(GPIO60, AF0)
+#define GPIO61_GPIO MFP_CFG(GPIO61, AF0)
+#define GPIO62_GPIO MFP_CFG(GPIO62, AF0)
+
+#ifdef CONFIG_CPU_PXA310
+#define GPIO7_2_GPIO MFP_CFG(GPIO7_2, AF0)
+#define GPIO8_2_GPIO MFP_CFG(GPIO8_2, AF0)
+#define GPIO9_2_GPIO MFP_CFG(GPIO9_2, AF0)
+#define GPIO10_2_GPIO MFP_CFG(GPIO10_2, AF0)
+#define GPIO11_2_GPIO MFP_CFG(GPIO11_2, AF0)
+#define GPIO12_2_GPIO MFP_CFG(GPIO12_2, AF0)
+#endif
+
+/* Chip Select */
+#define GPIO2_nCS3 MFP_CFG(GPIO2, AF1)
+
+/* AC97 */
+#define GPIO23_AC97_nACRESET MFP_CFG(GPIO23, AF1)
+#define GPIO24_AC97_SYSCLK MFP_CFG(GPIO24, AF1)
+#define GPIO29_AC97_BITCLK MFP_CFG(GPIO29, AF1)
+#define GPIO25_AC97_SDATA_IN_0 MFP_CFG(GPIO25, AF1)
+#define GPIO26_AC97_SDATA_IN_1 MFP_CFG(GPIO26, AF1)
+#define GPIO17_AC97_SDATA_IN_2 MFP_CFG(GPIO17, AF3)
+#define GPIO21_AC97_SDATA_IN_2 MFP_CFG(GPIO21, AF2)
+#define GPIO18_AC97_SDATA_IN_3 MFP_CFG(GPIO18, AF3)
+#define GPIO22_AC97_SDATA_IN_3 MFP_CFG(GPIO22, AF2)
+#define GPIO27_AC97_SDATA_OUT MFP_CFG(GPIO27, AF1)
+#define GPIO28_AC97_SYNC MFP_CFG(GPIO28, AF1)
+
+/* I2C */
+#define GPIO21_I2C_SCL MFP_CFG_LPM(GPIO21, AF1, PULL_HIGH)
+#define GPIO22_I2C_SDA MFP_CFG_LPM(GPIO22, AF1, PULL_HIGH)
+
+/* QCI */
+#define GPIO39_CI_DD_0 MFP_CFG_DRV(GPIO39, AF1, DS04X)
+#define GPIO40_CI_DD_1 MFP_CFG_DRV(GPIO40, AF1, DS04X)
+#define GPIO41_CI_DD_2 MFP_CFG_DRV(GPIO41, AF1, DS04X)
+#define GPIO42_CI_DD_3 MFP_CFG_DRV(GPIO42, AF1, DS04X)
+#define GPIO43_CI_DD_4 MFP_CFG_DRV(GPIO43, AF1, DS04X)
+#define GPIO44_CI_DD_5 MFP_CFG_DRV(GPIO44, AF1, DS04X)
+#define GPIO45_CI_DD_6 MFP_CFG_DRV(GPIO45, AF1, DS04X)
+#define GPIO46_CI_DD_7 MFP_CFG_DRV(GPIO46, AF0, DS04X)
+#define GPIO47_CI_DD_8 MFP_CFG_DRV(GPIO47, AF1, DS04X)
+#define GPIO48_CI_DD_9 MFP_CFG_DRV(GPIO48, AF1, DS04X)
+#define GPIO52_CI_HSYNC MFP_CFG_DRV(GPIO52, AF0, DS04X)
+#define GPIO51_CI_VSYNC MFP_CFG_DRV(GPIO51, AF0, DS04X)
+#define GPIO49_CI_MCLK MFP_CFG_DRV(GPIO49, AF0, DS04X)
+#define GPIO50_CI_PCLK MFP_CFG_DRV(GPIO50, AF0, DS04X)
+
+/* KEYPAD */
+#define GPIO3_KP_DKIN_6 MFP_CFG_LPM(GPIO3, AF2, FLOAT)
+#define GPIO4_KP_DKIN_7 MFP_CFG_LPM(GPIO4, AF2, FLOAT)
+#define GPIO16_KP_DKIN_6 MFP_CFG_LPM(GPIO16, AF6, FLOAT)
+#define GPIO83_KP_DKIN_2 MFP_CFG_LPM(GPIO83, AF5, FLOAT)
+#define GPIO84_KP_DKIN_1 MFP_CFG_LPM(GPIO84, AF5, FLOAT)
+#define GPIO85_KP_DKIN_0 MFP_CFG_LPM(GPIO85, AF3, FLOAT)
+#define GPIO86_KP_DKIN_1 MFP_CFG_LPM(GPIO86, AF3, FLOAT)
+#define GPIO87_KP_DKIN_2 MFP_CFG_LPM(GPIO87, AF3, FLOAT)
+#define GPIO88_KP_DKIN_3 MFP_CFG_LPM(GPIO88, AF3, FLOAT)
+#define GPIO89_KP_DKIN_3 MFP_CFG_LPM(GPIO89, AF3, FLOAT)
+#define GPIO107_KP_DKIN_0 MFP_CFG_LPM(GPIO107, AF2, FLOAT)
+#define GPIO108_KP_DKIN_1 MFP_CFG_LPM(GPIO108, AF2, FLOAT)
+#define GPIO109_KP_DKIN_2 MFP_CFG_LPM(GPIO109, AF2, FLOAT)
+#define GPIO110_KP_DKIN_3 MFP_CFG_LPM(GPIO110, AF2, FLOAT)
+#define GPIO111_KP_DKIN_4 MFP_CFG_LPM(GPIO111, AF2, FLOAT)
+#define GPIO112_KP_DKIN_5 MFP_CFG_LPM(GPIO112, AF2, FLOAT)
+#define GPIO113_KP_DKIN_6 MFP_CFG_LPM(GPIO113, AF2, FLOAT)
+#define GPIO114_KP_DKIN_7 MFP_CFG_LPM(GPIO114, AF2, FLOAT)
+#define GPIO115_KP_DKIN_0 MFP_CFG_LPM(GPIO115, AF2, FLOAT)
+#define GPIO116_KP_DKIN_1 MFP_CFG_LPM(GPIO116, AF2, FLOAT)
+#define GPIO117_KP_DKIN_2 MFP_CFG_LPM(GPIO117, AF2, FLOAT)
+#define GPIO118_KP_DKIN_3 MFP_CFG_LPM(GPIO118, AF2, FLOAT)
+#define GPIO119_KP_DKIN_4 MFP_CFG_LPM(GPIO119, AF2, FLOAT)
+#define GPIO120_KP_DKIN_5 MFP_CFG_LPM(GPIO120, AF2, FLOAT)
+#define GPIO121_KP_DKIN_6 MFP_CFG_LPM(GPIO121, AF2, FLOAT)
+#define GPIO122_KP_DKIN_5 MFP_CFG_LPM(GPIO122, AF2, FLOAT)
+#define GPIO123_KP_DKIN_4 MFP_CFG_LPM(GPIO123, AF2, FLOAT)
+#define GPIO124_KP_DKIN_3 MFP_CFG_LPM(GPIO124, AF2, FLOAT)
+#define GPIO127_KP_DKIN_0 MFP_CFG_LPM(GPIO127, AF5, FLOAT)
+#define GPIO0_2_KP_DKIN_0 MFP_CFG_LPM(GPIO0_2, AF2, FLOAT)
+#define GPIO1_2_KP_DKIN_1 MFP_CFG_LPM(GPIO1_2, AF2, FLOAT)
+#define GPIO2_2_KP_DKIN_6 MFP_CFG_LPM(GPIO2_2, AF2, FLOAT)
+#define GPIO3_2_KP_DKIN_7 MFP_CFG_LPM(GPIO3_2, AF2, FLOAT)
+#define GPIO4_2_KP_DKIN_1 MFP_CFG_LPM(GPIO4_2, AF2, FLOAT)
+#define GPIO5_2_KP_DKIN_0 MFP_CFG_LPM(GPIO5_2, AF2, FLOAT)
+
+#define GPIO5_KP_MKIN_0 MFP_CFG_LPM(GPIO5, AF2, FLOAT)
+#define GPIO6_KP_MKIN_1 MFP_CFG_LPM(GPIO6, AF2, FLOAT)
+#define GPIO9_KP_MKIN_6 MFP_CFG_LPM(GPIO9, AF3, FLOAT)
+#define GPIO10_KP_MKIN_7 MFP_CFG_LPM(GPIO10, AF3, FLOAT)
+#define GPIO70_KP_MKIN_6 MFP_CFG_LPM(GPIO70, AF3, FLOAT)
+#define GPIO71_KP_MKIN_7 MFP_CFG_LPM(GPIO71, AF3, FLOAT)
+#define GPIO100_KP_MKIN_6 MFP_CFG_LPM(GPIO100, AF7, FLOAT)
+#define GPIO101_KP_MKIN_7 MFP_CFG_LPM(GPIO101, AF7, FLOAT)
+#define GPIO112_KP_MKIN_6 MFP_CFG_LPM(GPIO112, AF4, FLOAT)
+#define GPIO113_KP_MKIN_7 MFP_CFG_LPM(GPIO113, AF4, FLOAT)
+#define GPIO115_KP_MKIN_0 MFP_CFG_LPM(GPIO115, AF1, FLOAT)
+#define GPIO116_KP_MKIN_1 MFP_CFG_LPM(GPIO116, AF1, FLOAT)
+#define GPIO117_KP_MKIN_2 MFP_CFG_LPM(GPIO117, AF1, FLOAT)
+#define GPIO118_KP_MKIN_3 MFP_CFG_LPM(GPIO118, AF1, FLOAT)
+#define GPIO119_KP_MKIN_4 MFP_CFG_LPM(GPIO119, AF1, FLOAT)
+#define GPIO120_KP_MKIN_5 MFP_CFG_LPM(GPIO120, AF1, FLOAT)
+#define GPIO125_KP_MKIN_2 MFP_CFG_LPM(GPIO125, AF2, FLOAT)
+#define GPIO2_2_KP_MKIN_6 MFP_CFG_LPM(GPIO2_2, AF1, FLOAT)
+#define GPIO3_2_KP_MKIN_7 MFP_CFG_LPM(GPIO3_2, AF1, FLOAT)
+
+#define GPIO7_KP_MKOUT_5 MFP_CFG_LPM(GPIO7, AF1, DRIVE_HIGH)
+#define GPIO11_KP_MKOUT_5 MFP_CFG_LPM(GPIO11, AF3, DRIVE_HIGH)
+#define GPIO12_KP_MKOUT_6 MFP_CFG_LPM(GPIO12, AF3, DRIVE_HIGH)
+#define GPIO13_KP_MKOUT_7 MFP_CFG_LPM(GPIO13, AF3, DRIVE_HIGH)
+#define GPIO19_KP_MKOUT_4 MFP_CFG_LPM(GPIO19, AF3, DRIVE_HIGH)
+#define GPIO20_KP_MKOUT_5 MFP_CFG_LPM(GPIO20, AF3, DRIVE_HIGH)
+#define GPIO38_KP_MKOUT_5 MFP_CFG_LPM(GPIO38, AF5, DRIVE_HIGH)
+#define GPIO53_KP_MKOUT_6 MFP_CFG_LPM(GPIO53, AF5, DRIVE_HIGH)
+#define GPIO78_KP_MKOUT_7 MFP_CFG_LPM(GPIO78, AF5, DRIVE_HIGH)
+#define GPIO85_KP_MKOUT_0 MFP_CFG_LPM(GPIO85, AF2, DRIVE_HIGH)
+#define GPIO86_KP_MKOUT_1 MFP_CFG_LPM(GPIO86, AF2, DRIVE_HIGH)
+#define GPIO87_KP_MKOUT_2 MFP_CFG_LPM(GPIO87, AF2, DRIVE_HIGH)
+#define GPIO88_KP_MKOUT_3 MFP_CFG_LPM(GPIO88, AF2, DRIVE_HIGH)
+#define GPIO104_KP_MKOUT_6 MFP_CFG_LPM(GPIO104, AF5, DRIVE_HIGH)
+#define GPIO105_KP_MKOUT_7 MFP_CFG_LPM(GPIO105, AF5, DRIVE_HIGH)
+#define GPIO121_KP_MKOUT_0 MFP_CFG_LPM(GPIO121, AF1, DRIVE_HIGH)
+#define GPIO122_KP_MKOUT_1 MFP_CFG_LPM(GPIO122, AF1, DRIVE_HIGH)
+#define GPIO123_KP_MKOUT_2 MFP_CFG_LPM(GPIO123, AF1, DRIVE_HIGH)
+#define GPIO124_KP_MKOUT_3 MFP_CFG_LPM(GPIO124, AF1, DRIVE_HIGH)
+#define GPIO125_KP_MKOUT_4 MFP_CFG_LPM(GPIO125, AF1, DRIVE_HIGH)
+#define GPIO126_KP_MKOUT_7 MFP_CFG_LPM(GPIO126, AF4, DRIVE_HIGH)
+#define GPIO5_2_KP_MKOUT_6 MFP_CFG_LPM(GPIO5_2, AF1, DRIVE_HIGH)
+#define GPIO4_2_KP_MKOUT_5 MFP_CFG_LPM(GPIO4_2, AF1, DRIVE_HIGH)
+#define GPIO6_2_KP_MKOUT_7 MFP_CFG_LPM(GPIO6_2, AF1, DRIVE_HIGH)
+
+/* LCD */
+#define GPIO54_LCD_LDD_0 MFP_CFG_DRV(GPIO54, AF1, DS01X)
+#define GPIO55_LCD_LDD_1 MFP_CFG_DRV(GPIO55, AF1, DS01X)
+#define GPIO56_LCD_LDD_2 MFP_CFG_DRV(GPIO56, AF1, DS01X)
+#define GPIO57_LCD_LDD_3 MFP_CFG_DRV(GPIO57, AF1, DS01X)
+#define GPIO58_LCD_LDD_4 MFP_CFG_DRV(GPIO58, AF1, DS01X)
+#define GPIO59_LCD_LDD_5 MFP_CFG_DRV(GPIO59, AF1, DS01X)
+#define GPIO60_LCD_LDD_6 MFP_CFG_DRV(GPIO60, AF1, DS01X)
+#define GPIO61_LCD_LDD_7 MFP_CFG_DRV(GPIO61, AF1, DS01X)
+#define GPIO62_LCD_LDD_8 MFP_CFG_DRV(GPIO62, AF1, DS01X)
+#define GPIO63_LCD_LDD_9 MFP_CFG_DRV(GPIO63, AF1, DS01X)
+#define GPIO64_LCD_LDD_10 MFP_CFG_DRV(GPIO64, AF1, DS01X)
+#define GPIO65_LCD_LDD_11 MFP_CFG_DRV(GPIO65, AF1, DS01X)
+#define GPIO66_LCD_LDD_12 MFP_CFG_DRV(GPIO66, AF1, DS01X)
+#define GPIO67_LCD_LDD_13 MFP_CFG_DRV(GPIO67, AF1, DS01X)
+#define GPIO68_LCD_LDD_14 MFP_CFG_DRV(GPIO68, AF1, DS01X)
+#define GPIO69_LCD_LDD_15 MFP_CFG_DRV(GPIO69, AF1, DS01X)
+#define GPIO70_LCD_LDD_16 MFP_CFG_DRV(GPIO70, AF1, DS01X)
+#define GPIO71_LCD_LDD_17 MFP_CFG_DRV(GPIO71, AF1, DS01X)
+#define GPIO62_LCD_CS_N MFP_CFG_DRV(GPIO62, AF2, DS01X)
+#define GPIO72_LCD_FCLK MFP_CFG_DRV(GPIO72, AF1, DS01X)
+#define GPIO73_LCD_LCLK MFP_CFG_DRV(GPIO73, AF1, DS01X)
+#define GPIO74_LCD_PCLK MFP_CFG_DRV(GPIO74, AF1, DS01X)
+#define GPIO75_LCD_BIAS MFP_CFG_DRV(GPIO75, AF1, DS01X)
+#define GPIO76_LCD_VSYNC MFP_CFG_DRV(GPIO76, AF2, DS01X)
+
+#define GPIO15_LCD_CS_N MFP_CFG_DRV(GPIO15, AF2, DS01X)
+#define GPIO127_LCD_CS_N MFP_CFG_DRV(GPIO127, AF1, DS01X)
+#define GPIO63_LCD_VSYNC MFP_CFG_DRV(GPIO63, AF2, DS01X)
+
+/* Mini-LCD */
+#define GPIO72_MLCD_FCLK MFP_CFG_DRV(GPIO72, AF7, DS08X)
+#define GPIO73_MLCD_LCLK MFP_CFG_DRV(GPIO73, AF7, DS08X)
+#define GPIO54_MLCD_LDD_0 MFP_CFG_DRV(GPIO54, AF7, DS08X)
+#define GPIO55_MLCD_LDD_1 MFP_CFG_DRV(GPIO55, AF7, DS08X)
+#define GPIO56_MLCD_LDD_2 MFP_CFG_DRV(GPIO56, AF7, DS08X)
+#define GPIO57_MLCD_LDD_3 MFP_CFG_DRV(GPIO57, AF7, DS08X)
+#define GPIO58_MLCD_LDD_4 MFP_CFG_DRV(GPIO58, AF7, DS08X)
+#define GPIO59_MLCD_LDD_5 MFP_CFG_DRV(GPIO59, AF7, DS08X)
+#define GPIO60_MLCD_LDD_6 MFP_CFG_DRV(GPIO60, AF7, DS08X)
+#define GPIO61_MLCD_LDD_7 MFP_CFG_DRV(GPIO61, AF7, DS08X)
+#define GPIO62_MLCD_LDD_8 MFP_CFG_DRV(GPIO62, AF7, DS08X)
+#define GPIO63_MLCD_LDD_9 MFP_CFG_DRV(GPIO63, AF7, DS08X)
+#define GPIO64_MLCD_LDD_10 MFP_CFG_DRV(GPIO64, AF7, DS08X)
+#define GPIO65_MLCD_LDD_11 MFP_CFG_DRV(GPIO65, AF7, DS08X)
+#define GPIO66_MLCD_LDD_12 MFP_CFG_DRV(GPIO66, AF7, DS08X)
+#define GPIO67_MLCD_LDD_13 MFP_CFG_DRV(GPIO67, AF7, DS08X)
+#define GPIO68_MLCD_LDD_14 MFP_CFG_DRV(GPIO68, AF7, DS08X)
+#define GPIO69_MLCD_LDD_15 MFP_CFG_DRV(GPIO69, AF7, DS08X)
+#define GPIO74_MLCD_PCLK MFP_CFG_DRV(GPIO74, AF7, DS08X)
+#define GPIO75_MLCD_BIAS MFP_CFG_DRV(GPIO75, AF2, DS08X)
+
+/* MMC1 */
+#define GPIO7_MMC1_CLK MFP_CFG_LPM(GPIO7, AF4, DRIVE_HIGH)
+#define GPIO8_MMC1_CMD MFP_CFG_LPM(GPIO8, AF4, DRIVE_HIGH)
+#define GPIO14_MMC1_CMD MFP_CFG_LPM(GPIO14, AF5, DRIVE_HIGH)
+#define GPIO15_MMC1_CMD MFP_CFG_LPM(GPIO15, AF5, DRIVE_HIGH)
+#define GPIO3_MMC1_DAT0 MFP_CFG_LPM(GPIO3, AF4, DRIVE_HIGH)
+#define GPIO4_MMC1_DAT1 MFP_CFG_LPM(GPIO4, AF4, DRIVE_HIGH)
+#define GPIO5_MMC1_DAT2 MFP_CFG_LPM(GPIO5, AF4, DRIVE_HIGH)
+#define GPIO6_MMC1_DAT3 MFP_CFG_LPM(GPIO6, AF4, DRIVE_HIGH)
+
+/* MMC2 */
+#define GPIO9_MMC2_DAT0 MFP_CFG_LPM(GPIO9, AF4, PULL_HIGH)
+#define GPIO10_MMC2_DAT1 MFP_CFG_LPM(GPIO10, AF4, PULL_HIGH)
+#define GPIO11_MMC2_DAT2 MFP_CFG_LPM(GPIO11, AF4, PULL_HIGH)
+#define GPIO12_MMC2_DAT3 MFP_CFG_LPM(GPIO12, AF4, PULL_HIGH)
+#define GPIO13_MMC2_CLK MFP_CFG_LPM(GPIO13, AF4, PULL_HIGH)
+#define GPIO14_MMC2_CMD MFP_CFG_LPM(GPIO14, AF4, PULL_HIGH)
+#define GPIO77_MMC2_DAT0 MFP_CFG_LPM(GPIO77, AF4, PULL_HIGH)
+#define GPIO78_MMC2_DAT1 MFP_CFG_LPM(GPIO78, AF4, PULL_HIGH)
+#define GPIO79_MMC2_DAT2 MFP_CFG_LPM(GPIO79, AF4, PULL_HIGH)
+#define GPIO80_MMC2_DAT3 MFP_CFG_LPM(GPIO80, AF4, PULL_HIGH)
+#define GPIO81_MMC2_CLK MFP_CFG_LPM(GPIO81, AF4, PULL_HIGH)
+#define GPIO82_MMC2_CMD MFP_CFG_LPM(GPIO82, AF4, PULL_HIGH)
+
+/* SSP1 */
+#define GPIO89_SSP1_EXTCLK MFP_CFG(GPIO89, AF1)
+#define GPIO90_SSP1_SYSCLK MFP_CFG(GPIO90, AF1)
+#define GPIO15_SSP1_SCLK MFP_CFG(GPIO15, AF6)
+#define GPIO16_SSP1_FRM MFP_CFG(GPIO16, AF2)
+#define GPIO33_SSP1_SCLK MFP_CFG(GPIO33, AF5)
+#define GPIO34_SSP1_FRM MFP_CFG(GPIO34, AF5)
+#define GPIO85_SSP1_SCLK MFP_CFG(GPIO85, AF1)
+#define GPIO86_SSP1_FRM MFP_CFG(GPIO86, AF1)
+#define GPIO18_SSP1_TXD MFP_CFG(GPIO18, AF7)
+#define GPIO18_SSP1_RXD MFP_CFG(GPIO18, AF2)
+#define GPIO20_SSP1_TXD MFP_CFG(GPIO20, AF2)
+#define GPIO20_SSP1_RXD MFP_CFG(GPIO20, AF7)
+#define GPIO35_SSP1_TXD MFP_CFG(GPIO35, AF5)
+#define GPIO35_SSP1_RXD MFP_CFG(GPIO35, AF4)
+#define GPIO36_SSP1_TXD MFP_CFG(GPIO36, AF5)
+#define GPIO36_SSP1_RXD MFP_CFG(GPIO36, AF6)
+#define GPIO87_SSP1_TXD MFP_CFG(GPIO87, AF1)
+#define GPIO87_SSP1_RXD MFP_CFG(GPIO87, AF6)
+#define GPIO88_SSP1_TXD MFP_CFG(GPIO88, AF6)
+#define GPIO88_SSP1_RXD MFP_CFG(GPIO88, AF1)
+
+/* SSP2 */
+#define GPIO29_SSP2_EXTCLK MFP_CFG(GPIO29, AF2)
+#define GPIO23_SSP2_SCLK MFP_CFG(GPIO23, AF2)
+#define GPIO17_SSP2_FRM MFP_CFG(GPIO17, AF2)
+#define GPIO25_SSP2_SCLK MFP_CFG(GPIO25, AF2)
+#define GPIO26_SSP2_FRM MFP_CFG(GPIO26, AF2)
+#define GPIO33_SSP2_SCLK MFP_CFG(GPIO33, AF6)
+#define GPIO34_SSP2_FRM MFP_CFG(GPIO34, AF6)
+#define GPIO64_SSP2_SCLK MFP_CFG(GPIO64, AF2)
+#define GPIO65_SSP2_FRM MFP_CFG(GPIO65, AF2)
+#define GPIO19_SSP2_TXD MFP_CFG(GPIO19, AF2)
+#define GPIO19_SSP2_RXD MFP_CFG(GPIO19, AF7)
+#define GPIO24_SSP2_TXD MFP_CFG(GPIO24, AF5)
+#define GPIO24_SSP2_RXD MFP_CFG(GPIO24, AF4)
+#define GPIO27_SSP2_TXD MFP_CFG(GPIO27, AF2)
+#define GPIO27_SSP2_RXD MFP_CFG(GPIO27, AF5)
+#define GPIO28_SSP2_TXD MFP_CFG(GPIO28, AF5)
+#define GPIO28_SSP2_RXD MFP_CFG(GPIO28, AF2)
+#define GPIO35_SSP2_TXD MFP_CFG(GPIO35, AF7)
+#define GPIO35_SSP2_RXD MFP_CFG(GPIO35, AF6)
+#define GPIO66_SSP2_TXD MFP_CFG(GPIO66, AF4)
+#define GPIO66_SSP2_RXD MFP_CFG(GPIO66, AF2)
+#define GPIO67_SSP2_TXD MFP_CFG(GPIO67, AF2)
+#define GPIO67_SSP2_RXD MFP_CFG(GPIO67, AF4)
+#define GPIO36_SSP2_TXD MFP_CFG(GPIO36, AF7)
+
+/* SSP3 */
+#define GPIO69_SSP3_FRM MFP_CFG_X(GPIO69, AF2, DS08X, DRIVE_LOW)
+#define GPIO68_SSP3_SCLK MFP_CFG_X(GPIO68, AF2, DS08X, FLOAT)
+#define GPIO92_SSP3_FRM MFP_CFG_X(GPIO92, AF1, DS08X, DRIVE_LOW)
+#define GPIO91_SSP3_SCLK MFP_CFG_X(GPIO91, AF1, DS08X, FLOAT)
+#define GPIO70_SSP3_TXD MFP_CFG_X(GPIO70, AF2, DS08X, DRIVE_LOW)
+#define GPIO70_SSP3_RXD MFP_CFG_X(GPIO70, AF5, DS08X, FLOAT)
+#define GPIO71_SSP3_TXD MFP_CFG_X(GPIO71, AF5, DS08X, DRIVE_LOW)
+#define GPIO71_SSP3_RXD MFP_CFG_X(GPIO71, AF2, DS08X, FLOAT)
+#define GPIO93_SSP3_TXD MFP_CFG_X(GPIO93, AF1, DS08X, DRIVE_LOW)
+#define GPIO93_SSP3_RXD MFP_CFG_X(GPIO93, AF5, DS08X, FLOAT)
+#define GPIO94_SSP3_TXD MFP_CFG_X(GPIO94, AF5, DS08X, DRIVE_LOW)
+#define GPIO94_SSP3_RXD MFP_CFG_X(GPIO94, AF1, DS08X, FLOAT)
+
+/* SSP4 */
+#define GPIO95_SSP4_SCLK MFP_CFG_LPM(GPIO95, AF1, PULL_HIGH)
+#define GPIO96_SSP4_FRM MFP_CFG_LPM(GPIO96, AF1, PULL_HIGH)
+#define GPIO97_SSP4_TXD MFP_CFG_LPM(GPIO97, AF1, PULL_HIGH)
+#define GPIO97_SSP4_RXD MFP_CFG_LPM(GPIO97, AF5, PULL_HIGH)
+#define GPIO98_SSP4_TXD MFP_CFG_LPM(GPIO98, AF5, PULL_HIGH)
+#define GPIO98_SSP4_RXD MFP_CFG_LPM(GPIO98, AF1, PULL_HIGH)
+
+/* UART1 */
+#define GPIO32_UART1_CTS MFP_CFG_LPM(GPIO32, AF2, FLOAT)
+#define GPIO37_UART1_CTS MFP_CFG_LPM(GPIO37, AF4, FLOAT)
+#define GPIO79_UART1_CTS MFP_CFG_LPM(GPIO79, AF1, FLOAT)
+#define GPIO84_UART1_CTS MFP_CFG_LPM(GPIO84, AF3, FLOAT)
+#define GPIO101_UART1_CTS MFP_CFG_LPM(GPIO101, AF1, FLOAT)
+#define GPIO106_UART1_CTS MFP_CFG_LPM(GPIO106, AF6, FLOAT)
+
+#define GPIO32_UART1_RTS MFP_CFG_LPM(GPIO32, AF4, FLOAT)
+#define GPIO37_UART1_RTS MFP_CFG_LPM(GPIO37, AF2, FLOAT)
+#define GPIO79_UART1_RTS MFP_CFG_LPM(GPIO79, AF3, FLOAT)
+#define GPIO84_UART1_RTS MFP_CFG_LPM(GPIO84, AF1, FLOAT)
+#define GPIO101_UART1_RTS MFP_CFG_LPM(GPIO101, AF6, FLOAT)
+#define GPIO106_UART1_RTS MFP_CFG_LPM(GPIO106, AF1, FLOAT)
+
+#define GPIO34_UART1_DSR MFP_CFG_LPM(GPIO34, AF2, FLOAT)
+#define GPIO36_UART1_DSR MFP_CFG_LPM(GPIO36, AF4, FLOAT)
+#define GPIO81_UART1_DSR MFP_CFG_LPM(GPIO81, AF1, FLOAT)
+#define GPIO83_UART1_DSR MFP_CFG_LPM(GPIO83, AF3, FLOAT)
+#define GPIO103_UART1_DSR MFP_CFG_LPM(GPIO103, AF1, FLOAT)
+#define GPIO105_UART1_DSR MFP_CFG_LPM(GPIO105, AF6, FLOAT)
+
+#define GPIO34_UART1_DTR MFP_CFG_LPM(GPIO34, AF4, FLOAT)
+#define GPIO36_UART1_DTR MFP_CFG_LPM(GPIO36, AF2, FLOAT)
+#define GPIO81_UART1_DTR MFP_CFG_LPM(GPIO81, AF3, FLOAT)
+#define GPIO83_UART1_DTR MFP_CFG_LPM(GPIO83, AF1, FLOAT)
+#define GPIO103_UART1_DTR MFP_CFG_LPM(GPIO103, AF6, FLOAT)
+#define GPIO105_UART1_DTR MFP_CFG_LPM(GPIO105, AF1, FLOAT)
+
+#define GPIO35_UART1_RI MFP_CFG_LPM(GPIO35, AF2, FLOAT)
+#define GPIO82_UART1_RI MFP_CFG_LPM(GPIO82, AF1, FLOAT)
+#define GPIO104_UART1_RI MFP_CFG_LPM(GPIO104, AF1, FLOAT)
+
+#define GPIO33_UART1_DCD MFP_CFG_LPM(GPIO33, AF2, FLOAT)
+#define GPIO80_UART1_DCD MFP_CFG_LPM(GPIO80, AF1, FLOAT)
+#define GPIO102_UART1_DCD MFP_CFG_LPM(GPIO102, AF1, FLOAT)
+
+#define GPIO30_UART1_RXD MFP_CFG_LPM(GPIO30, AF2, FLOAT)
+#define GPIO31_UART1_RXD MFP_CFG_LPM(GPIO31, AF4, FLOAT)
+#define GPIO77_UART1_RXD MFP_CFG_LPM(GPIO77, AF1, FLOAT)
+#define GPIO78_UART1_RXD MFP_CFG_LPM(GPIO78, AF3, FLOAT)
+#define GPIO99_UART1_RXD MFP_CFG_LPM(GPIO99, AF1, FLOAT)
+#define GPIO100_UART1_RXD MFP_CFG_LPM(GPIO100, AF6, FLOAT)
+#define GPIO102_UART1_RXD MFP_CFG_LPM(GPIO102, AF6, FLOAT)
+#define GPIO104_UART1_RXD MFP_CFG_LPM(GPIO104, AF4, FLOAT)
+
+#define GPIO30_UART1_TXD MFP_CFG_LPM(GPIO30, AF4, FLOAT)
+#define GPIO31_UART1_TXD MFP_CFG_LPM(GPIO31, AF2, FLOAT)
+#define GPIO77_UART1_TXD MFP_CFG_LPM(GPIO77, AF3, FLOAT)
+#define GPIO78_UART1_TXD MFP_CFG_LPM(GPIO78, AF1, FLOAT)
+#define GPIO99_UART1_TXD MFP_CFG_LPM(GPIO99, AF6, FLOAT)
+#define GPIO100_UART1_TXD MFP_CFG_LPM(GPIO100, AF1, FLOAT)
+#define GPIO102_UART1_TXD MFP_CFG_LPM(GPIO102, AF4, FLOAT)
+
+/* UART2 */
+#define GPIO15_UART2_CTS MFP_CFG_LPM(GPIO15, AF3, FLOAT)
+#define GPIO16_UART2_CTS MFP_CFG_LPM(GPIO16, AF5, FLOAT)
+#define GPIO111_UART2_CTS MFP_CFG_LPM(GPIO111, AF3, FLOAT)
+#define GPIO114_UART2_CTS MFP_CFG_LPM(GPIO114, AF1, FLOAT)
+
+#define GPIO15_UART2_RTS MFP_CFG_LPM(GPIO15, AF4, FLOAT)
+#define GPIO16_UART2_RTS MFP_CFG_LPM(GPIO16, AF4, FLOAT)
+#define GPIO114_UART2_RTS MFP_CFG_LPM(GPIO114, AF3, FLOAT)
+#define GPIO111_UART2_RTS MFP_CFG_LPM(GPIO111, AF1, FLOAT)
+
+#define GPIO18_UART2_RXD MFP_CFG_LPM(GPIO18, AF5, FLOAT)
+#define GPIO19_UART2_RXD MFP_CFG_LPM(GPIO19, AF4, FLOAT)
+#define GPIO112_UART2_RXD MFP_CFG_LPM(GPIO112, AF1, FLOAT)
+#define GPIO113_UART2_RXD MFP_CFG_LPM(GPIO113, AF3, FLOAT)
+
+#define GPIO18_UART2_TXD MFP_CFG_LPM(GPIO18, AF4, FLOAT)
+#define GPIO19_UART2_TXD MFP_CFG_LPM(GPIO19, AF5, FLOAT)
+#define GPIO112_UART2_TXD MFP_CFG_LPM(GPIO112, AF3, FLOAT)
+#define GPIO113_UART2_TXD MFP_CFG_LPM(GPIO113, AF1, FLOAT)
+
+/* UART3 */
+#define GPIO91_UART3_CTS MFP_CFG_LPM(GPIO91, AF2, FLOAT)
+#define GPIO92_UART3_CTS MFP_CFG_LPM(GPIO92, AF4, FLOAT)
+#define GPIO107_UART3_CTS MFP_CFG_LPM(GPIO107, AF1, FLOAT)
+#define GPIO108_UART3_CTS MFP_CFG_LPM(GPIO108, AF3, FLOAT)
+
+#define GPIO91_UART3_RTS MFP_CFG_LPM(GPIO91, AF4, FLOAT)
+#define GPIO92_UART3_RTS MFP_CFG_LPM(GPIO92, AF2, FLOAT)
+#define GPIO107_UART3_RTS MFP_CFG_LPM(GPIO107, AF3, FLOAT)
+#define GPIO108_UART3_RTS MFP_CFG_LPM(GPIO108, AF1, FLOAT)
+
+#define GPIO7_UART3_RXD MFP_CFG_LPM(GPIO7, AF2, FLOAT)
+#define GPIO8_UART3_RXD MFP_CFG_LPM(GPIO8, AF6, FLOAT)
+#define GPIO93_UART3_RXD MFP_CFG_LPM(GPIO93, AF4, FLOAT)
+#define GPIO94_UART3_RXD MFP_CFG_LPM(GPIO94, AF2, FLOAT)
+#define GPIO109_UART3_RXD MFP_CFG_LPM(GPIO109, AF3, FLOAT)
+#define GPIO110_UART3_RXD MFP_CFG_LPM(GPIO110, AF1, FLOAT)
+
+#define GPIO7_UART3_TXD MFP_CFG_LPM(GPIO7, AF6, FLOAT)
+#define GPIO8_UART3_TXD MFP_CFG_LPM(GPIO8, AF2, FLOAT)
+#define GPIO93_UART3_TXD MFP_CFG_LPM(GPIO93, AF2, FLOAT)
+#define GPIO94_UART3_TXD MFP_CFG_LPM(GPIO94, AF4, FLOAT)
+#define GPIO109_UART3_TXD MFP_CFG_LPM(GPIO109, AF1, FLOAT)
+#define GPIO110_UART3_TXD MFP_CFG_LPM(GPIO110, AF3, FLOAT)
+
+/* USB Host */
+#define GPIO0_2_USBH_PEN MFP_CFG(GPIO0_2, AF1)
+#define GPIO1_2_USBH_PWR MFP_CFG(GPIO1_2, AF1)
+
+/* USB P3 */
+#define GPIO77_USB_P3_1 MFP_CFG(GPIO77, AF2)
+#define GPIO78_USB_P3_2 MFP_CFG(GPIO78, AF2)
+#define GPIO79_USB_P3_3 MFP_CFG(GPIO79, AF2)
+#define GPIO80_USB_P3_4 MFP_CFG(GPIO80, AF2)
+#define GPIO81_USB_P3_5 MFP_CFG(GPIO81, AF2)
+#define GPIO82_USB_P3_6 MFP_CFG(GPIO82, AF2)
+
+/* PWM */
+#define GPIO17_PWM0_OUT MFP_CFG(GPIO17, AF1)
+#define GPIO18_PWM1_OUT MFP_CFG(GPIO18, AF1)
+#define GPIO19_PWM2_OUT MFP_CFG(GPIO19, AF1)
+#define GPIO20_PWM3_OUT MFP_CFG(GPIO20, AF1)
+
+/* CIR */
+#define GPIO8_CIR_OUT MFP_CFG(GPIO8, AF5)
+#define GPIO16_CIR_OUT MFP_CFG(GPIO16, AF3)
+
+#define GPIO20_OW_DQ_IN MFP_CFG(GPIO20, AF5)
+#define GPIO126_OW_DQ MFP_CFG(GPIO126, AF2)
+
+#define GPIO0_DF_RDY MFP_CFG(GPIO0, AF1)
+#define GPIO7_CLK_BYPASS_XSC MFP_CFG(GPIO7, AF7)
+#define GPIO17_EXT_SYNC_MVT_0 MFP_CFG(GPIO17, AF6)
+#define GPIO18_EXT_SYNC_MVT_1 MFP_CFG(GPIO18, AF6)
+#define GPIO19_OST_CHOUT_MVT_0 MFP_CFG(GPIO19, AF6)
+#define GPIO20_OST_CHOUT_MVT_1 MFP_CFG(GPIO20, AF6)
+#define GPIO49_48M_CLK MFP_CFG(GPIO49, AF2)
+#define GPIO126_EXT_CLK MFP_CFG(GPIO126, AF3)
+#define GPIO127_CLK_BYPASS_GB MFP_CFG(GPIO127, AF7)
+#define GPIO71_EXT_MATCH_MVT MFP_CFG(GPIO71, AF6)
+
+#define GPIO3_uIO_IN MFP_CFG(GPIO3, AF1)
+
+#define GPIO4_uSIM_CARD_STATE MFP_CFG(GPIO4, AF1)
+#define GPIO5_uSIM_uCLK MFP_CFG(GPIO5, AF1)
+#define GPIO6_uSIM_uRST MFP_CFG(GPIO6, AF1)
+#define GPIO16_uSIM_UVS_0 MFP_CFG(GPIO16, AF1)
+
+#define GPIO9_SCIO MFP_CFG(GPIO9, AF1)
+#define GPIO20_RTC_MVT MFP_CFG(GPIO20, AF4)
+#define GPIO126_RTC_MVT MFP_CFG(GPIO126, AF1)
+
+/*
+ * PXA300 specific MFP configurations
+ */
+#ifdef CONFIG_CPU_PXA300
+#define GPIO99_USB_P2_2 MFP_CFG(GPIO99, AF2)
+#define GPIO99_USB_P2_5 MFP_CFG(GPIO99, AF3)
+#define GPIO99_USB_P2_6 MFP_CFG(GPIO99, AF4)
+#define GPIO100_USB_P2_2 MFP_CFG(GPIO100, AF4)
+#define GPIO100_USB_P2_5 MFP_CFG(GPIO100, AF5)
+#define GPIO101_USB_P2_1 MFP_CFG(GPIO101, AF2)
+#define GPIO102_USB_P2_4 MFP_CFG(GPIO102, AF2)
+#define GPIO104_USB_P2_3 MFP_CFG(GPIO104, AF2)
+#define GPIO105_USB_P2_5 MFP_CFG(GPIO105, AF2)
+#define GPIO100_USB_P2_6 MFP_CFG(GPIO100, AF2)
+#define GPIO106_USB_P2_7 MFP_CFG(GPIO106, AF2)
+#define GPIO103_USB_P2_8 MFP_CFG(GPIO103, AF2)
+
+/* U2D UTMI */
+#define GPIO38_UTM_CLK MFP_CFG(GPIO38, AF1)
+#define GPIO26_U2D_RXERROR MFP_CFG(GPIO26, AF3)
+#define GPIO50_U2D_RXERROR MFP_CFG(GPIO50, AF1)
+#define GPIO89_U2D_RXERROR MFP_CFG(GPIO89, AF5)
+#define GPIO24_UTM_RXVALID MFP_CFG(GPIO24, AF3)
+#define GPIO48_UTM_RXVALID MFP_CFG(GPIO48, AF2)
+#define GPIO87_UTM_RXVALID MFP_CFG(GPIO87, AF5)
+#define GPIO25_UTM_RXACTIVE MFP_CFG(GPIO25, AF3)
+#define GPIO47_UTM_RXACTIVE MFP_CFG(GPIO47, AF2)
+#define GPIO49_UTM_RXACTIVE MFP_CFG(GPIO49, AF1)
+#define GPIO88_UTM_RXACTIVE MFP_CFG(GPIO88, AF5)
+#define GPIO53_UTM_TXREADY MFP_CFG(GPIO53, AF1)
+#define GPIO67_UTM_LINESTATE_0 MFP_CFG(GPIO67, AF3)
+#define GPIO92_UTM_LINESTATE_0 MFP_CFG(GPIO92, AF3)
+#define GPIO104_UTM_LINESTATE_0 MFP_CFG(GPIO104, AF3)
+#define GPIO109_UTM_LINESTATE_0 MFP_CFG(GPIO109, AF4)
+#define GPIO68_UTM_LINESTATE_1 MFP_CFG(GPIO68, AF3)
+#define GPIO93_UTM_LINESTATE_1 MFP_CFG(GPIO93, AF3)
+#define GPIO105_UTM_LINESTATE_1 MFP_CFG(GPIO105, AF3)
+#define GPIO27_U2D_OPMODE_0 MFP_CFG(GPIO27, AF4)
+#define GPIO51_U2D_OPMODE_0 MFP_CFG(GPIO51, AF2)
+#define GPIO90_U2D_OPMODE_0 MFP_CFG(GPIO90, AF7)
+#define GPIO28_U2D_OPMODE_1 MFP_CFG(GPIO28, AF4)
+#define GPIO52_U2D_OPMODE_1 MFP_CFG(GPIO52, AF2)
+#define GPIO106_U2D_OPMODE_1 MFP_CFG(GPIO106, AF3)
+#define GPIO110_U2D_OPMODE_1 MFP_CFG(GPIO110, AF5)
+#define GPIO76_U2D_RESET MFP_CFG(GPIO76, AF1)
+#define GPIO95_U2D_RESET MFP_CFG(GPIO95, AF2)
+#define GPIO100_U2D_RESET MFP_CFG(GPIO100, AF3)
+#define GPIO66_U2D_SUSPEND MFP_CFG(GPIO66, AF3)
+#define GPIO98_U2D_SUSPEND MFP_CFG(GPIO98, AF2)
+#define GPIO103_U2D_SUSPEND MFP_CFG(GPIO103, AF3)
+#define GPIO65_U2D_TERM_SEL MFP_CFG(GPIO65, AF5)
+#define GPIO97_U2D_TERM_SEL MFP_CFG(GPIO97, AF3)
+#define GPIO102_U2D_TERM_SEL MFP_CFG(GPIO102, AF5)
+#define GPIO29_U2D_TXVALID MFP_CFG(GPIO29, AF3)
+#define GPIO52_U2D_TXVALID MFP_CFG(GPIO52, AF4)
+#define GPIO69_U2D_TXVALID MFP_CFG(GPIO69, AF3)
+#define GPIO85_U2D_TXVALID MFP_CFG(GPIO85, AF7)
+#define GPIO64_U2D_XCVR_SEL MFP_CFG(GPIO64, AF5)
+#define GPIO96_U2D_XCVR_SEL MFP_CFG(GPIO96, AF3)
+#define GPIO101_U2D_XCVR_SEL MFP_CFG(GPIO101, AF5)
+#define GPIO30_UTM_PHYDATA_0 MFP_CFG(GPIO30, AF3)
+#define GPIO31_UTM_PHYDATA_1 MFP_CFG(GPIO31, AF3)
+#define GPIO32_UTM_PHYDATA_2 MFP_CFG(GPIO32, AF3)
+#define GPIO33_UTM_PHYDATA_3 MFP_CFG(GPIO33, AF3)
+#define GPIO34_UTM_PHYDATA_4 MFP_CFG(GPIO34, AF3)
+#define GPIO35_UTM_PHYDATA_5 MFP_CFG(GPIO35, AF3)
+#define GPIO36_UTM_PHYDATA_6 MFP_CFG(GPIO36, AF3)
+#define GPIO37_UTM_PHYDATA_7 MFP_CFG(GPIO37, AF3)
+#define GPIO39_UTM_PHYDATA_0 MFP_CFG(GPIO39, AF3)
+#define GPIO40_UTM_PHYDATA_1 MFP_CFG(GPIO40, AF3)
+#define GPIO41_UTM_PHYDATA_2 MFP_CFG(GPIO41, AF3)
+#define GPIO42_UTM_PHYDATA_3 MFP_CFG(GPIO42, AF3)
+#define GPIO43_UTM_PHYDATA_4 MFP_CFG(GPIO43, AF3)
+#define GPIO44_UTM_PHYDATA_5 MFP_CFG(GPIO44, AF3)
+#define GPIO45_UTM_PHYDATA_6 MFP_CFG(GPIO45, AF3)
+#define GPIO46_UTM_PHYDATA_7 MFP_CFG(GPIO46, AF3)
+#endif /* CONFIG_CPU_PXA300 */
+
+/*
+ * PXA310 specific MFP configurations
+ */
+#ifdef CONFIG_CPU_PXA310
+/* USB P2 */
+#define GPIO36_USB_P2_1 MFP_CFG(GPIO36, AF1)
+#define GPIO30_USB_P2_2 MFP_CFG(GPIO30, AF1)
+#define GPIO35_USB_P2_3 MFP_CFG(GPIO35, AF1)
+#define GPIO32_USB_P2_4 MFP_CFG(GPIO32, AF1)
+#define GPIO34_USB_P2_5 MFP_CFG(GPIO34, AF1)
+#define GPIO31_USB_P2_6 MFP_CFG(GPIO31, AF1)
+
+/* MMC1 */
+#define GPIO24_MMC1_CMD MFP_CFG(GPIO24, AF3)
+#define GPIO29_MMC1_DAT0 MFP_CFG(GPIO29, AF3)
+
+/* MMC3 */
+#define GPIO103_MMC3_CLK MFP_CFG(GPIO103, AF2)
+#define GPIO105_MMC3_CMD MFP_CFG(GPIO105, AF2)
+#define GPIO11_2_MMC3_CLK MFP_CFG(GPIO11_2, AF1)
+#define GPIO12_2_MMC3_CMD MFP_CFG(GPIO12_2, AF1)
+#define GPIO7_2_MMC3_DAT0 MFP_CFG(GPIO7_2, AF1)
+#define GPIO8_2_MMC3_DAT1 MFP_CFG(GPIO8_2, AF1)
+#define GPIO9_2_MMC3_DAT2 MFP_CFG(GPIO9_2, AF1)
+#define GPIO10_2_MMC3_DAT3 MFP_CFG(GPIO10_2, AF1)
+
+/* ULPI */
+#define GPIO38_ULPI_CLK MFP_CFG(GPIO38, AF1)
+#define GPIO30_ULPI_DATA_OUT_0 MFP_CFG(GPIO30, AF3)
+#define GPIO31_ULPI_DATA_OUT_1 MFP_CFG(GPIO31, AF3)
+#define GPIO32_ULPI_DATA_OUT_2 MFP_CFG(GPIO32, AF3)
+#define GPIO33_ULPI_DATA_OUT_3 MFP_CFG(GPIO33, AF3)
+#define GPIO34_ULPI_DATA_OUT_4 MFP_CFG(GPIO34, AF3)
+#define GPIO35_ULPI_DATA_OUT_5 MFP_CFG(GPIO35, AF3)
+#define GPIO36_ULPI_DATA_OUT_6 MFP_CFG(GPIO36, AF3)
+#define GPIO37_ULPI_DATA_OUT_7 MFP_CFG(GPIO37, AF3)
+#define GPIO33_ULPI_OTG_INTR MFP_CFG(GPIO33, AF1)
+
+#define ULPI_DIR MFP_CFG_DRV(ULPI_DIR, MFP_AF0, MFP_DS01X)
+#define ULPI_NXT MFP_CFG_DRV(ULPI_NXT, MFP_AF0, MFP_DS01X)
+#define ULPI_STP MFP_CFG_DRV(ULPI_STP, MFP_AF0, MFP_DS01X)
+#endif /* CONFIG_CPU_PXA310 */
+
+#endif /* __ASM_ARCH_MFP_PXA300_H */
diff --git a/include/asm-arm/arch-pxa/mfp-pxa320.h b/include/asm-arm/arch-pxa/mfp-pxa320.h
new file mode 100644
index 000000000000..488a5bbc49e9
--- /dev/null
+++ b/include/asm-arm/arch-pxa/mfp-pxa320.h
@@ -0,0 +1,446 @@
+/*
+ * linux/include/asm-arm/arch-pxa/mfp-pxa320.h
+ *
+ * PXA320 specific MFP configuration definitions
+ *
+ * Copyright (C) 2007 Marvell International Ltd.
+ * 2007-08-21: eric miao <eric.miao@marvell.com>
+ * initial version
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_MFP_PXA320_H
+#define __ASM_ARCH_MFP_PXA320_H
+
+#include <asm/arch/mfp.h>
+
+/* GPIO */
+#define GPIO46_GPIO MFP_CFG(GPIO6, AF0)
+#define GPIO49_GPIO MFP_CFG(GPIO49, AF0)
+#define GPIO50_GPIO MFP_CFG(GPIO50, AF0)
+#define GPIO51_GPIO MFP_CFG(GPIO51, AF0)
+#define GPIO52_GPIO MFP_CFG(GPIO52, AF0)
+
+#define GPIO7_2_GPIO MFP_CFG(GPIO7_2, AF0)
+#define GPIO8_2_GPIO MFP_CFG(GPIO8_2, AF0)
+#define GPIO9_2_GPIO MFP_CFG(GPIO9_2, AF0)
+#define GPIO10_2_GPIO MFP_CFG(GPIO10_2, AF0)
+#define GPIO11_2_GPIO MFP_CFG(GPIO11_2, AF0)
+#define GPIO12_2_GPIO MFP_CFG(GPIO12_2, AF0)
+#define GPIO13_2_GPIO MFP_CFG(GPIO13_2, AF0)
+#define GPIO14_2_GPIO MFP_CFG(GPIO14_2, AF0)
+#define GPIO15_2_GPIO MFP_CFG(GPIO15_2, AF0)
+#define GPIO16_2_GPIO MFP_CFG(GPIO16_2, AF0)
+#define GPIO17_2_GPIO MFP_CFG(GPIO17_2, AF0)
+
+/* Chip Select */
+#define GPIO4_nCS3 MFP_CFG(GPIO4, AF1)
+
+/* AC97 */
+#define GPIO34_AC97_SYSCLK MFP_CFG(GPIO34, AF1)
+#define GPIO39_AC97_BITCLK MFP_CFG(GPIO39, AF1)
+#define GPIO40_AC97_nACRESET MFP_CFG(GPIO40, AF1)
+#define GPIO35_AC97_SDATA_IN_0 MFP_CFG(GPIO35, AF1)
+#define GPIO36_AC97_SDATA_IN_1 MFP_CFG(GPIO36, AF1)
+#define GPIO32_AC97_SDATA_IN_2 MFP_CFG(GPIO32, AF2)
+#define GPIO33_AC97_SDATA_IN_3 MFP_CFG(GPIO33, AF2)
+#define GPIO11_AC97_SDATA_IN_2 MFP_CFG(GPIO11, AF3)
+#define GPIO12_AC97_SDATA_IN_3 MFP_CFG(GPIO12, AF3)
+#define GPIO37_AC97_SDATA_OUT MFP_CFG(GPIO37, AF1)
+#define GPIO38_AC97_SYNC MFP_CFG(GPIO38, AF1)
+
+/* I2C */
+#define GPIO32_I2C_SCL MFP_CFG_LPM(GPIO32, AF1, PULL_HIGH)
+#define GPIO33_I2C_SDA MFP_CFG_LPM(GPIO33, AF1, PULL_HIGH)
+
+/* QCI */
+#define GPIO49_CI_DD_0 MFP_CFG_DRV(GPIO49, AF1, DS04X)
+#define GPIO50_CI_DD_1 MFP_CFG_DRV(GPIO50, AF1, DS04X)
+#define GPIO51_CI_DD_2 MFP_CFG_DRV(GPIO51, AF1, DS04X)
+#define GPIO52_CI_DD_3 MFP_CFG_DRV(GPIO52, AF1, DS04X)
+#define GPIO53_CI_DD_4 MFP_CFG_DRV(GPIO53, AF1, DS04X)
+#define GPIO54_CI_DD_5 MFP_CFG_DRV(GPIO54, AF1, DS04X)
+#define GPIO55_CI_DD_6 MFP_CFG_DRV(GPIO55, AF1, DS04X)
+#define GPIO56_CI_DD_7 MFP_CFG_DRV(GPIO56, AF0, DS04X)
+#define GPIO57_CI_DD_8 MFP_CFG_DRV(GPIO57, AF1, DS04X)
+#define GPIO58_CI_DD_9 MFP_CFG_DRV(GPIO58, AF1, DS04X)
+#define GPIO59_CI_MCLK MFP_CFG_DRV(GPIO59, AF0, DS04X)
+#define GPIO60_CI_PCLK MFP_CFG_DRV(GPIO60, AF0, DS04X)
+#define GPIO61_CI_HSYNC MFP_CFG_DRV(GPIO61, AF0, DS04X)
+#define GPIO62_CI_VSYNC MFP_CFG_DRV(GPIO62, AF0, DS04X)
+
+#define GPIO31_CIR_OUT MFP_CFG(GPIO31, AF5)
+
+#define GPIO0_2_CLK_EXT MFP_CFG(GPIO0_2, AF3)
+#define GPIO0_DRQ MFP_CFG(GPIO0, AF2)
+#define GPIO11_EXT_SYNC0 MFP_CFG(GPIO11, AF5)
+#define GPIO12_EXT_SYNC1 MFP_CFG(GPIO12, AF6)
+#define GPIO0_2_HZ_CLK MFP_CFG(GPIO0_2, AF1)
+#define GPIO14_HZ_CLK MFP_CFG(GPIO14, AF4)
+#define GPIO30_ICP_RXD MFP_CFG(GPIO30, AF1)
+#define GPIO31_ICP_TXD MFP_CFG(GPIO31, AF1)
+
+#define GPIO83_KP_DKIN_0 MFP_CFG_LPM(GPIO83, AF3, FLOAT)
+#define GPIO84_KP_DKIN_1 MFP_CFG_LPM(GPIO84, AF3, FLOAT)
+#define GPIO85_KP_DKIN_2 MFP_CFG_LPM(GPIO85, AF3, FLOAT)
+#define GPIO86_KP_DKIN_3 MFP_CFG_LPM(GPIO86, AF3, FLOAT)
+
+#define GPIO105_KP_DKIN_0 MFP_CFG_LPM(GPIO105, AF2, FLOAT)
+#define GPIO106_KP_DKIN_1 MFP_CFG_LPM(GPIO106, AF2, FLOAT)
+#define GPIO107_KP_DKIN_2 MFP_CFG_LPM(GPIO107, AF2, FLOAT)
+#define GPIO108_KP_DKIN_3 MFP_CFG_LPM(GPIO108, AF2, FLOAT)
+#define GPIO109_KP_DKIN_4 MFP_CFG_LPM(GPIO109, AF2, FLOAT)
+#define GPIO110_KP_DKIN_5 MFP_CFG_LPM(GPIO110, AF2, FLOAT)
+#define GPIO111_KP_DKIN_6 MFP_CFG_LPM(GPIO111, AF2, FLOAT)
+#define GPIO112_KP_DKIN_7 MFP_CFG_LPM(GPIO112, AF2, FLOAT)
+
+#define GPIO113_KP_DKIN_0 MFP_CFG_LPM(GPIO113, AF2, FLOAT)
+#define GPIO114_KP_DKIN_1 MFP_CFG_LPM(GPIO114, AF2, FLOAT)
+#define GPIO115_KP_DKIN_2 MFP_CFG_LPM(GPIO115, AF2, FLOAT)
+#define GPIO116_KP_DKIN_3 MFP_CFG_LPM(GPIO116, AF2, FLOAT)
+#define GPIO117_KP_DKIN_4 MFP_CFG_LPM(GPIO117, AF2, FLOAT)
+#define GPIO118_KP_DKIN_5 MFP_CFG_LPM(GPIO118, AF2, FLOAT)
+#define GPIO119_KP_DKIN_6 MFP_CFG_LPM(GPIO119, AF2, FLOAT)
+#define GPIO120_KP_DKIN_7 MFP_CFG_LPM(GPIO120, AF2, FLOAT)
+
+#define GPIO127_KP_DKIN_0 MFP_CFG_LPM(GPIO127, AF2, FLOAT)
+#define GPIO126_KP_DKIN_1 MFP_CFG_LPM(GPIO126, AF2, FLOAT)
+
+#define GPIO2_2_KP_DKIN_0 MFP_CFG_LPM(GPIO2_2, AF2, FLOAT)
+#define GPIO3_2_KP_DKIN_1 MFP_CFG_LPM(GPIO3_2, AF2, FLOAT)
+#define GPIO125_KP_DKIN_2 MFP_CFG_LPM(GPIO125, AF2, FLOAT)
+#define GPIO124_KP_DKIN_3 MFP_CFG_LPM(GPIO124, AF2, FLOAT)
+#define GPIO123_KP_DKIN_4 MFP_CFG_LPM(GPIO123, AF2, FLOAT)
+#define GPIO122_KP_DKIN_5 MFP_CFG_LPM(GPIO122, AF2, FLOAT)
+#define GPIO121_KP_DKIN_6 MFP_CFG_LPM(GPIO121, AF2, FLOAT)
+#define GPIO4_2_KP_DKIN_7 MFP_CFG_LPM(GPIO4_2, AF2, FLOAT)
+
+#define GPIO113_KP_MKIN_0 MFP_CFG_LPM(GPIO113, AF1, FLOAT)
+#define GPIO114_KP_MKIN_1 MFP_CFG_LPM(GPIO114, AF1, FLOAT)
+#define GPIO115_KP_MKIN_2 MFP_CFG_LPM(GPIO115, AF1, FLOAT)
+#define GPIO116_KP_MKIN_3 MFP_CFG_LPM(GPIO116, AF1, FLOAT)
+#define GPIO117_KP_MKIN_4 MFP_CFG_LPM(GPIO117, AF1, FLOAT)
+#define GPIO118_KP_MKIN_5 MFP_CFG_LPM(GPIO118, AF1, FLOAT)
+#define GPIO119_KP_MKIN_6 MFP_CFG_LPM(GPIO119, AF1, FLOAT)
+#define GPIO120_KP_MKIN_7 MFP_CFG_LPM(GPIO120, AF1, FLOAT)
+
+#define GPIO83_KP_MKOUT_0 MFP_CFG_LPM(GPIO83, AF2, DRIVE_HIGH)
+#define GPIO84_KP_MKOUT_1 MFP_CFG_LPM(GPIO84, AF2, DRIVE_HIGH)
+#define GPIO85_KP_MKOUT_2 MFP_CFG_LPM(GPIO85, AF2, DRIVE_HIGH)
+#define GPIO86_KP_MKOUT_3 MFP_CFG_LPM(GPIO86, AF2, DRIVE_HIGH)
+#define GPIO13_KP_MKOUT_4 MFP_CFG_LPM(GPIO13, AF3, DRIVE_HIGH)
+#define GPIO14_KP_MKOUT_5 MFP_CFG_LPM(GPIO14, AF3, DRIVE_HIGH)
+
+#define GPIO121_KP_MKOUT_0 MFP_CFG_LPM(GPIO121, AF1, DRIVE_HIGH)
+#define GPIO122_KP_MKOUT_1 MFP_CFG_LPM(GPIO122, AF1, DRIVE_HIGH)
+#define GPIO123_KP_MKOUT_2 MFP_CFG_LPM(GPIO123, AF1, DRIVE_HIGH)
+#define GPIO124_KP_MKOUT_3 MFP_CFG_LPM(GPIO124, AF1, DRIVE_HIGH)
+#define GPIO125_KP_MKOUT_4 MFP_CFG_LPM(GPIO125, AF1, DRIVE_HIGH)
+#define GPIO126_KP_MKOUT_5 MFP_CFG_LPM(GPIO126, AF1, DRIVE_HIGH)
+#define GPIO127_KP_MKOUT_6 MFP_CFG_LPM(GPIO127, AF1, DRIVE_HIGH)
+#define GPIO5_2_KP_MKOUT_7 MFP_CFG_LPM(GPIO5_2, AF1, DRIVE_HIGH)
+
+/* LCD */
+#define GPIO6_2_LCD_LDD_0 MFP_CFG_DRV(GPIO6_2, AF1, DS01X)
+#define GPIO7_2_LCD_LDD_1 MFP_CFG_DRV(GPIO7_2, AF1, DS01X)
+#define GPIO8_2_LCD_LDD_2 MFP_CFG_DRV(GPIO8_2, AF1, DS01X)
+#define GPIO9_2_LCD_LDD_3 MFP_CFG_DRV(GPIO9_2, AF1, DS01X)
+#define GPIO10_2_LCD_LDD_4 MFP_CFG_DRV(GPIO10_2, AF1, DS01X)
+#define GPIO11_2_LCD_LDD_5 MFP_CFG_DRV(GPIO11_2, AF1, DS01X)
+#define GPIO12_2_LCD_LDD_6 MFP_CFG_DRV(GPIO12_2, AF1, DS01X)
+#define GPIO13_2_LCD_LDD_7 MFP_CFG_DRV(GPIO13_2, AF1, DS01X)
+#define GPIO63_LCD_LDD_8 MFP_CFG_DRV(GPIO63, AF1, DS01X)
+#define GPIO64_LCD_LDD_9 MFP_CFG_DRV(GPIO64, AF1, DS01X)
+#define GPIO65_LCD_LDD_10 MFP_CFG_DRV(GPIO65, AF1, DS01X)
+#define GPIO66_LCD_LDD_11 MFP_CFG_DRV(GPIO66, AF1, DS01X)
+#define GPIO67_LCD_LDD_12 MFP_CFG_DRV(GPIO67, AF1, DS01X)
+#define GPIO68_LCD_LDD_13 MFP_CFG_DRV(GPIO68, AF1, DS01X)
+#define GPIO69_LCD_LDD_14 MFP_CFG_DRV(GPIO69, AF1, DS01X)
+#define GPIO70_LCD_LDD_15 MFP_CFG_DRV(GPIO70, AF1, DS01X)
+#define GPIO71_LCD_LDD_16 MFP_CFG_DRV(GPIO71, AF1, DS01X)
+#define GPIO72_LCD_LDD_17 MFP_CFG_DRV(GPIO72, AF1, DS01X)
+#define GPIO73_LCD_CS_N MFP_CFG_DRV(GPIO73, AF2, DS01X)
+#define GPIO74_LCD_VSYNC MFP_CFG_DRV(GPIO74, AF2, DS01X)
+#define GPIO14_2_LCD_FCLK MFP_CFG_DRV(GPIO14_2, AF1, DS01X)
+#define GPIO15_2_LCD_LCLK MFP_CFG_DRV(GPIO15_2, AF1, DS01X)
+#define GPIO16_2_LCD_PCLK MFP_CFG_DRV(GPIO16_2, AF1, DS01X)
+#define GPIO17_2_LCD_BIAS MFP_CFG_DRV(GPIO17_2, AF1, DS01X)
+#define GPIO64_LCD_VSYNC MFP_CFG_DRV(GPIO64, AF2, DS01X)
+#define GPIO63_LCD_CS_N MFP_CFG_DRV(GPIO63, AF2, DS01X)
+
+#define GPIO6_2_MLCD_DD_0 MFP_CFG_DRV(GPIO6_2, AF7, DS08X)
+#define GPIO7_2_MLCD_DD_1 MFP_CFG_DRV(GPIO7_2, AF7, DS08X)
+#define GPIO8_2_MLCD_DD_2 MFP_CFG_DRV(GPIO8_2, AF7, DS08X)
+#define GPIO9_2_MLCD_DD_3 MFP_CFG_DRV(GPIO9_2, AF7, DS08X)
+#define GPIO10_2_MLCD_DD_4 MFP_CFG_DRV(GPIO10_2, AF7, DS08X)
+#define GPIO11_2_MLCD_DD_5 MFP_CFG_DRV(GPIO11_2, AF7, DS08X)
+#define GPIO12_2_MLCD_DD_6 MFP_CFG_DRV(GPIO12_2, AF7, DS08X)
+#define GPIO13_2_MLCD_DD_7 MFP_CFG_DRV(GPIO13_2, AF7, DS08X)
+#define GPIO63_MLCD_DD_8 MFP_CFG_DRV(GPIO63, AF7, DS08X)
+#define GPIO64_MLCD_DD_9 MFP_CFG_DRV(GPIO64, AF7, DS08X)
+#define GPIO65_MLCD_DD_10 MFP_CFG_DRV(GPIO65, AF7, DS08X)
+#define GPIO66_MLCD_DD_11 MFP_CFG_DRV(GPIO66, AF7, DS08X)
+#define GPIO67_MLCD_DD_12 MFP_CFG_DRV(GPIO67, AF7, DS08X)
+#define GPIO68_MLCD_DD_13 MFP_CFG_DRV(GPIO68, AF7, DS08X)
+#define GPIO69_MLCD_DD_14 MFP_CFG_DRV(GPIO69, AF7, DS08X)
+#define GPIO70_MLCD_DD_15 MFP_CFG_DRV(GPIO70, AF7, DS08X)
+#define GPIO71_MLCD_DD_16 MFP_CFG_DRV(GPIO71, AF7, DS08X)
+#define GPIO72_MLCD_DD_17 MFP_CFG_DRV(GPIO72, AF7, DS08X)
+#define GPIO73_MLCD_CS MFP_CFG_DRV(GPIO73, AF7, DS08X)
+#define GPIO74_MLCD_VSYNC MFP_CFG_DRV(GPIO74, AF7, DS08X)
+#define GPIO14_2_MLCD_FCLK MFP_CFG_DRV(GPIO14_2, AF7, DS08X)
+#define GPIO15_2_MLCD_LCLK MFP_CFG_DRV(GPIO15_2, AF7, DS08X)
+#define GPIO16_2_MLCD_PCLK MFP_CFG_DRV(GPIO16_2, AF7, DS08X)
+#define GPIO17_2_MLCD_BIAS MFP_CFG_DRV(GPIO17_2, AF7, DS08X)
+
+/* MMC1 */
+#define GPIO9_MMC1_CMD MFP_CFG_LPM(GPIO9, AF4, DRIVE_HIGH)
+#define GPIO22_MMC1_CLK MFP_CFG_LPM(GPIO22, AF4, DRIVE_HIGH)
+#define GPIO23_MMC1_CMD MFP_CFG_LPM(GPIO23, AF4, DRIVE_HIGH)
+#define GPIO30_MMC1_CLK MFP_CFG_LPM(GPIO30, AF4, DRIVE_HIGH)
+#define GPIO31_MMC1_CMD MFP_CFG_LPM(GPIO31, AF4, DRIVE_HIGH)
+#define GPIO5_MMC1_DAT0 MFP_CFG_LPM(GPIO5, AF4, DRIVE_HIGH)
+#define GPIO6_MMC1_DAT1 MFP_CFG_LPM(GPIO6, AF4, DRIVE_HIGH)
+#define GPIO7_MMC1_DAT2 MFP_CFG_LPM(GPIO7, AF4, DRIVE_HIGH)
+#define GPIO8_MMC1_DAT3 MFP_CFG_LPM(GPIO8, AF4, DRIVE_HIGH)
+#define GPIO18_MMC1_DAT0 MFP_CFG_LPM(GPIO18, AF4, DRIVE_HIGH)
+#define GPIO19_MMC1_DAT1 MFP_CFG_LPM(GPIO19, AF4, DRIVE_HIGH)
+#define GPIO20_MMC1_DAT2 MFP_CFG_LPM(GPIO20, AF4, DRIVE_HIGH)
+#define GPIO21_MMC1_DAT3 MFP_CFG_LPM(GPIO21, AF4, DRIVE_HIGH)
+
+#define GPIO28_MMC2_CLK MFP_CFG_LPM(GPIO28, AF4, PULL_HIGH)
+#define GPIO29_MMC2_CMD MFP_CFG_LPM(GPIO29, AF4, PULL_HIGH)
+#define GPIO30_MMC2_CLK MFP_CFG_LPM(GPIO30, AF3, PULL_HIGH)
+#define GPIO31_MMC2_CMD MFP_CFG_LPM(GPIO31, AF3, PULL_HIGH)
+#define GPIO79_MMC2_CLK MFP_CFG_LPM(GPIO79, AF4, PULL_HIGH)
+#define GPIO80_MMC2_CMD MFP_CFG_LPM(GPIO80, AF4, PULL_HIGH)
+
+#define GPIO5_MMC2_DAT0 MFP_CFG_LPM(GPIO5, AF2, PULL_HIGH)
+#define GPIO6_MMC2_DAT1 MFP_CFG_LPM(GPIO6, AF2, PULL_HIGH)
+#define GPIO7_MMC2_DAT2 MFP_CFG_LPM(GPIO7, AF2, PULL_HIGH)
+#define GPIO8_MMC2_DAT3 MFP_CFG_LPM(GPIO8, AF2, PULL_HIGH)
+#define GPIO24_MMC2_DAT0 MFP_CFG_LPM(GPIO24, AF4, PULL_HIGH)
+#define GPIO75_MMC2_DAT0 MFP_CFG_LPM(GPIO75, AF4, PULL_HIGH)
+#define GPIO25_MMC2_DAT1 MFP_CFG_LPM(GPIO25, AF4, PULL_HIGH)
+#define GPIO76_MMC2_DAT1 MFP_CFG_LPM(GPIO76, AF4, PULL_HIGH)
+#define GPIO26_MMC2_DAT2 MFP_CFG_LPM(GPIO26, AF4, PULL_HIGH)
+#define GPIO77_MMC2_DAT2 MFP_CFG_LPM(GPIO77, AF4, PULL_HIGH)
+#define GPIO27_MMC2_DAT3 MFP_CFG_LPM(GPIO27, AF4, PULL_HIGH)
+#define GPIO78_MMC2_DAT3 MFP_CFG_LPM(GPIO78, AF4, PULL_HIGH)
+
+/* 1-Wire */
+#define GPIO14_ONE_WIRE MFP_CFG_LPM(GPIO14, AF5, FLOAT)
+#define GPIO0_2_ONE_WIRE MFP_CFG_LPM(GPIO0_2, AF2, FLOAT)
+
+/* SSP1 */
+#define GPIO87_SSP1_EXTCLK MFP_CFG(GPIO87, AF1)
+#define GPIO88_SSP1_SYSCLK MFP_CFG(GPIO88, AF1)
+#define GPIO83_SSP1_SCLK MFP_CFG(GPIO83, AF1)
+#define GPIO84_SSP1_SFRM MFP_CFG(GPIO84, AF1)
+#define GPIO85_SSP1_RXD MFP_CFG(GPIO85, AF6)
+#define GPIO85_SSP1_TXD MFP_CFG(GPIO85, AF1)
+#define GPIO86_SSP1_RXD MFP_CFG(GPIO86, AF1)
+#define GPIO86_SSP1_TXD MFP_CFG(GPIO86, AF6)
+
+/* SSP2 */
+#define GPIO39_SSP2_EXTCLK MFP_CFG(GPIO39, AF2)
+#define GPIO40_SSP2_SYSCLK MFP_CFG(GPIO40, AF2)
+#define GPIO12_SSP2_SCLK MFP_CFG(GPIO12, AF2)
+#define GPIO35_SSP2_SCLK MFP_CFG(GPIO35, AF2)
+#define GPIO36_SSP2_SFRM MFP_CFG(GPIO36, AF2)
+#define GPIO37_SSP2_RXD MFP_CFG(GPIO37, AF5)
+#define GPIO37_SSP2_TXD MFP_CFG(GPIO37, AF2)
+#define GPIO38_SSP2_RXD MFP_CFG(GPIO38, AF2)
+#define GPIO38_SSP2_TXD MFP_CFG(GPIO38, AF5)
+
+#define GPIO69_SSP3_SCLK MFP_CFG(GPIO69, AF2, DS08X, FLOAT)
+#define GPIO70_SSP3_FRM MFP_CFG(GPIO70, AF2, DS08X, DRIVE_LOW)
+#define GPIO89_SSP3_SCLK MFP_CFG(GPIO89, AF1, DS08X, FLOAT)
+#define GPIO90_SSP3_FRM MFP_CFG(GPIO90, AF1, DS08X, DRIVE_LOW)
+#define GPIO71_SSP3_RXD MFP_CFG_X(GPIO71, AF5, DS08X, FLOAT)
+#define GPIO71_SSP3_TXD MFP_CFG_X(GPIO71, AF2, DS08X, DRIVE_LOW)
+#define GPIO72_SSP3_RXD MFP_CFG_X(GPIO72, AF2, DS08X, FLOAT)
+#define GPIO72_SSP3_TXD MFP_CFG_X(GPIO72, AF5, DS08X, DRIVE_LOW)
+#define GPIO91_SSP3_RXD MFP_CFG_X(GPIO91, AF5, DS08X, FLOAT)
+#define GPIO91_SSP3_TXD MFP_CFG_X(GPIO91, AF1, DS08X, DRIVE_LOW)
+#define GPIO92_SSP3_RXD MFP_CFG_X(GPIO92, AF1, DS08X, FLOAT)
+#define GPIO92_SSP3_TXD MFP_CFG_X(GPIO92, AF5, DS08X, DRIVE_LOW)
+
+#define GPIO93_SSP4_SCLK MFP_CFG_LPM(GPIO93, AF1, PULL_HIGH)
+#define GPIO94_SSP4_FRM MFP_CFG_LPM(GPIO94, AF1, PULL_HIGH)
+#define GPIO94_SSP4_RXD MFP_CFG_LPM(GPIO94, AF5, PULL_HIGH)
+#define GPIO95_SSP4_RXD MFP_CFG_LPM(GPIO95, AF5, PULL_HIGH)
+#define GPIO95_SSP4_TXD MFP_CFG_LPM(GPIO95, AF1, PULL_HIGH)
+#define GPIO96_SSP4_RXD MFP_CFG_LPM(GPIO96, AF1, PULL_HIGH)
+#define GPIO96_SSP4_TXD MFP_CFG_LPM(GPIO96, AF5, PULL_HIGH)
+
+/* UART1 */
+#define GPIO41_UART1_RXD MFP_CFG_LPM(GPIO41, AF2, FLOAT)
+#define GPIO41_UART1_TXD MFP_CFG_LPM(GPIO41, AF4, FLOAT)
+#define GPIO42_UART1_RXD MFP_CFG_LPM(GPIO42, AF4, FLOAT)
+#define GPIO42_UART1_TXD MFP_CFG_LPM(GPIO42, AF2, FLOAT)
+#define GPIO97_UART1_RXD MFP_CFG_LPM(GPIO97, AF1, FLOAT)
+#define GPIO97_UART1_TXD MFP_CFG_LPM(GPIO97, AF6, FLOAT)
+#define GPIO98_UART1_RXD MFP_CFG_LPM(GPIO98, AF6, FLOAT)
+#define GPIO98_UART1_TXD MFP_CFG_LPM(GPIO98, AF1, FLOAT)
+#define GPIO43_UART1_CTS MFP_CFG_LPM(GPIO43, AF2, FLOAT)
+#define GPIO43_UART1_RTS MFP_CFG_LPM(GPIO43, AF4, FLOAT)
+#define GPIO48_UART1_CTS MFP_CFG_LPM(GPIO48, AF4, FLOAT)
+#define GPIO48_UART1_RTS MFP_CFG_LPM(GPIO48, AF2, FLOAT)
+#define GPIO99_UART1_CTS MFP_CFG_LPM(GPIO99, AF1, FLOAT)
+#define GPIO99_UART1_RTS MFP_CFG_LPM(GPIO99, AF6, FLOAT)
+#define GPIO104_UART1_CTS MFP_CFG_LPM(GPIO104, AF6, FLOAT)
+#define GPIO104_UART1_RTS MFP_CFG_LPM(GPIO104, AF1, FLOAT)
+#define GPIO45_UART1_DTR MFP_CFG_LPM(GPIO45, AF4, FLOAT)
+#define GPIO45_UART1_DSR MFP_CFG_LPM(GPIO45, AF2, FLOAT)
+#define GPIO47_UART1_DTR MFP_CFG_LPM(GPIO47, AF2, FLOAT)
+#define GPIO47_UART1_DSR MFP_CFG_LPM(GPIO47, AF4, FLOAT)
+#define GPIO101_UART1_DTR MFP_CFG_LPM(GPIO101, AF6, FLOAT)
+#define GPIO101_UART1_DSR MFP_CFG_LPM(GPIO101, AF1, FLOAT)
+#define GPIO103_UART1_DTR MFP_CFG_LPM(GPIO103, AF1, FLOAT)
+#define GPIO103_UART1_DSR MFP_CFG_LPM(GPIO103, AF6, FLOAT)
+#define GPIO44_UART1_DCD MFP_CFG_LPM(GPIO44, AF2, FLOAT)
+#define GPIO100_UART1_DCD MFP_CFG_LPM(GPIO100, AF1, FLOAT)
+#define GPIO46_UART1_RI MFP_CFG_LPM(GPIO46, AF2, FLOAT)
+#define GPIO102_UART1_RI MFP_CFG_LPM(GPIO102, AF1, FLOAT)
+
+/* UART2 */
+#define GPIO109_UART2_CTS MFP_CFG_LPM(GPIO109, AF3, FLOAT)
+#define GPIO109_UART2_RTS MFP_CFG_LPM(GPIO109, AF1, FLOAT)
+#define GPIO112_UART2_CTS MFP_CFG_LPM(GPIO112, AF1, FLOAT)
+#define GPIO112_UART2_RTS MFP_CFG_LPM(GPIO112, AF3, FLOAT)
+#define GPIO110_UART2_RXD MFP_CFG_LPM(GPIO110, AF1, FLOAT)
+#define GPIO110_UART2_TXD MFP_CFG_LPM(GPIO110, AF3, FLOAT)
+#define GPIO111_UART2_RXD MFP_CFG_LPM(GPIO111, AF3, FLOAT)
+#define GPIO111_UART2_TXD MFP_CFG_LPM(GPIO111, AF1, FLOAT)
+
+/* UART3 */
+#define GPIO89_UART3_CTS MFP_CFG_LPM(GPIO89, AF2, FLOAT)
+#define GPIO89_UART3_RTS MFP_CFG_LPM(GPIO89, AF4, FLOAT)
+#define GPIO90_UART3_CTS MFP_CFG_LPM(GPIO90, AF4, FLOAT)
+#define GPIO90_UART3_RTS MFP_CFG_LPM(GPIO90, AF2, FLOAT)
+#define GPIO105_UART3_CTS MFP_CFG_LPM(GPIO105, AF1, FLOAT)
+#define GPIO105_UART3_RTS MFP_CFG_LPM(GPIO105, AF3, FLOAT)
+#define GPIO106_UART3_CTS MFP_CFG_LPM(GPIO106, AF3, FLOAT)
+#define GPIO106_UART3_RTS MFP_CFG_LPM(GPIO106, AF1, FLOAT)
+#define GPIO30_UART3_RXD MFP_CFG_LPM(GPIO30, AF2, FLOAT)
+#define GPIO30_UART3_TXD MFP_CFG_LPM(GPIO30, AF6, FLOAT)
+#define GPIO31_UART3_RXD MFP_CFG_LPM(GPIO31, AF6, FLOAT)
+#define GPIO31_UART3_TXD MFP_CFG_LPM(GPIO31, AF2, FLOAT)
+#define GPIO91_UART3_RXD MFP_CFG_LPM(GPIO91, AF4, FLOAT)
+#define GPIO91_UART3_TXD MFP_CFG_LPM(GPIO91, AF2, FLOAT)
+#define GPIO92_UART3_RXD MFP_CFG_LPM(GPIO92, AF2, FLOAT)
+#define GPIO92_UART3_TXD MFP_CFG_LPM(GPIO92, AF4, FLOAT)
+#define GPIO107_UART3_RXD MFP_CFG_LPM(GPIO107, AF3, FLOAT)
+#define GPIO107_UART3_TXD MFP_CFG_LPM(GPIO107, AF1, FLOAT)
+#define GPIO108_UART3_RXD MFP_CFG_LPM(GPIO108, AF1, FLOAT)
+#define GPIO108_UART3_TXD MFP_CFG_LPM(GPIO108, AF3, FLOAT)
+
+
+/* USB 2.0 UTMI */
+#define GPIO10_UTM_CLK MFP_CFG(GPIO10, AF1)
+#define GPIO36_U2D_RXERROR MFP_CFG(GPIO36, AF3)
+#define GPIO60_U2D_RXERROR MFP_CFG(GPIO60, AF1)
+#define GPIO87_U2D_RXERROR MFP_CFG(GPIO87, AF5)
+#define GPIO34_UTM_RXVALID MFP_CFG(GPIO34, AF3)
+#define GPIO58_UTM_RXVALID MFP_CFG(GPIO58, AF2)
+#define GPIO85_UTM_RXVALID MFP_CFG(GPIO85, AF5)
+#define GPIO35_UTM_RXACTIVE MFP_CFG(GPIO35, AF3)
+#define GPIO59_UTM_RXACTIVE MFP_CFG(GPIO59, AF1)
+#define GPIO86_UTM_RXACTIVE MFP_CFG(GPIO86, AF5)
+#define GPIO73_UTM_TXREADY MFP_CFG(GPIO73, AF1)
+#define GPIO68_UTM_LINESTATE_0 MFP_CFG(GPIO68, AF3)
+#define GPIO90_UTM_LINESTATE_0 MFP_CFG(GPIO90, AF3)
+#define GPIO102_UTM_LINESTATE_0 MFP_CFG(GPIO102, AF3)
+#define GPIO107_UTM_LINESTATE_0 MFP_CFG(GPIO107, AF4)
+#define GPIO69_UTM_LINESTATE_1 MFP_CFG(GPIO69, AF3)
+#define GPIO91_UTM_LINESTATE_1 MFP_CFG(GPIO91, AF3)
+#define GPIO103_UTM_LINESTATE_1 MFP_CFG(GPIO103, AF3)
+
+#define GPIO41_U2D_PHYDATA_0 MFP_CFG(GPIO41, AF3)
+#define GPIO42_U2D_PHYDATA_1 MFP_CFG(GPIO42, AF3)
+#define GPIO43_U2D_PHYDATA_2 MFP_CFG(GPIO43, AF3)
+#define GPIO44_U2D_PHYDATA_3 MFP_CFG(GPIO44, AF3)
+#define GPIO45_U2D_PHYDATA_4 MFP_CFG(GPIO45, AF3)
+#define GPIO46_U2D_PHYDATA_5 MFP_CFG(GPIO46, AF3)
+#define GPIO47_U2D_PHYDATA_6 MFP_CFG(GPIO47, AF3)
+#define GPIO48_U2D_PHYDATA_7 MFP_CFG(GPIO48, AF3)
+
+#define GPIO49_U2D_PHYDATA_0 MFP_CFG(GPIO49, AF3)
+#define GPIO50_U2D_PHYDATA_1 MFP_CFG(GPIO50, AF3)
+#define GPIO51_U2D_PHYDATA_2 MFP_CFG(GPIO51, AF3)
+#define GPIO52_U2D_PHYDATA_3 MFP_CFG(GPIO52, AF3)
+#define GPIO53_U2D_PHYDATA_4 MFP_CFG(GPIO53, AF3)
+#define GPIO54_U2D_PHYDATA_5 MFP_CFG(GPIO54, AF3)
+#define GPIO55_U2D_PHYDATA_6 MFP_CFG(GPIO55, AF3)
+#define GPIO56_U2D_PHYDATA_7 MFP_CFG(GPIO56, AF3)
+
+#define GPIO37_U2D_OPMODE0 MFP_CFG(GPIO37, AF4)
+#define GPIO61_U2D_OPMODE0 MFP_CFG(GPIO61, AF2)
+#define GPIO88_U2D_OPMODE0 MFP_CFG(GPIO88, AF7)
+
+#define GPIO38_U2D_OPMODE1 MFP_CFG(GPIO38, AF4)
+#define GPIO62_U2D_OPMODE1 MFP_CFG(GPIO62, AF2)
+#define GPIO104_U2D_OPMODE1 MFP_CFG(GPIO104, AF4)
+#define GPIO108_U2D_OPMODE1 MFP_CFG(GPIO108, AF5)
+
+#define GPIO74_U2D_RESET MFP_CFG(GPIO74, AF1)
+#define GPIO93_U2D_RESET MFP_CFG(GPIO93, AF2)
+#define GPIO98_U2D_RESET MFP_CFG(GPIO98, AF3)
+
+#define GPIO67_U2D_SUSPEND MFP_CFG(GPIO67, AF3)
+#define GPIO96_U2D_SUSPEND MFP_CFG(GPIO96, AF2)
+#define GPIO101_U2D_SUSPEND MFP_CFG(GPIO101, AF3)
+
+#define GPIO66_U2D_TERM_SEL MFP_CFG(GPIO66, AF5)
+#define GPIO95_U2D_TERM_SEL MFP_CFG(GPIO95, AF3)
+#define GPIO97_U2D_TERM_SEL MFP_CFG(GPIO97, AF7)
+#define GPIO100_U2D_TERM_SEL MFP_CFG(GPIO100, AF5)
+
+#define GPIO39_U2D_TXVALID MFP_CFG(GPIO39, AF4)
+#define GPIO70_U2D_TXVALID MFP_CFG(GPIO70, AF5)
+#define GPIO83_U2D_TXVALID MFP_CFG(GPIO83, AF7)
+
+#define GPIO65_U2D_XCVR_SEL MFP_CFG(GPIO65, AF5)
+#define GPIO94_U2D_XCVR_SEL MFP_CFG(GPIO94, AF3)
+#define GPIO99_U2D_XCVR_SEL MFP_CFG(GPIO99, AF5)
+
+/* USB Host 1.1 */
+#define GPIO2_2_USBH_PEN MFP_CFG(GPIO2_2, AF1)
+#define GPIO3_2_USBH_PWR MFP_CFG(GPIO3_2, AF1)
+
+/* USB P2 */
+#define GPIO97_USB_P2_2 MFP_CFG(GPIO97, AF2)
+#define GPIO97_USB_P2_6 MFP_CFG(GPIO97, AF4)
+#define GPIO98_USB_P2_2 MFP_CFG(GPIO98, AF4)
+#define GPIO98_USB_P2_6 MFP_CFG(GPIO98, AF2)
+#define GPIO99_USB_P2_1 MFP_CFG(GPIO99, AF2)
+#define GPIO100_USB_P2_4 MFP_CFG(GPIO100, AF2)
+#define GPIO101_USB_P2_8 MFP_CFG(GPIO101, AF2)
+#define GPIO102_USB_P2_3 MFP_CFG(GPIO102, AF2)
+#define GPIO103_USB_P2_5 MFP_CFG(GPIO103, AF2)
+#define GPIO104_USB_P2_7 MFP_CFG(GPIO104, AF2)
+
+/* USB P3 */
+#define GPIO75_USB_P3_1 MFP_CFG(GPIO75, AF2)
+#define GPIO76_USB_P3_2 MFP_CFG(GPIO76, AF2)
+#define GPIO77_USB_P3_3 MFP_CFG(GPIO77, AF2)
+#define GPIO78_USB_P3_4 MFP_CFG(GPIO78, AF2)
+#define GPIO79_USB_P3_5 MFP_CFG(GPIO79, AF2)
+#define GPIO80_USB_P3_6 MFP_CFG(GPIO80, AF2)
+
+#define GPIO13_CHOUT0 MFP_CFG(GPIO13, AF6)
+#define GPIO14_CHOUT1 MFP_CFG(GPIO14, AF6)
+
+#define GPIO2_RDY MFP_CFG(GPIO2, AF1)
+#define GPIO5_NPIOR MFP_CFG(GPIO5, AF3)
+
+#define GPIO11_PWM0_OUT MFP_CFG(GPIO11, AF1)
+#define GPIO12_PWM1_OUT MFP_CFG(GPIO12, AF1)
+#define GPIO13_PWM2_OUT MFP_CFG(GPIO13, AF1)
+#define GPIO14_PWM3_OUT MFP_CFG(GPIO14, AF1)
+
+#endif /* __ASM_ARCH_MFP_PXA320_H */
diff --git a/include/asm-arm/arch-pxa/mfp.h b/include/asm-arm/arch-pxa/mfp.h
new file mode 100644
index 000000000000..ac4157af5a8e
--- /dev/null
+++ b/include/asm-arm/arch-pxa/mfp.h
@@ -0,0 +1,576 @@
+/*
+ * linux/include/asm-arm/arch-pxa/mfp.h
+ *
+ * Multi-Function Pin Definitions
+ *
+ * Copyright (C) 2007 Marvell International Ltd.
+ *
+ * 2007-8-21: eric miao <eric.miao@marvell.com>
+ * initial version
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_MFP_H
+#define __ASM_ARCH_MFP_H
+
+#define MFPR_BASE (0x40e10000)
+#define MFPR_SIZE (PAGE_SIZE)
+
+#define mfp_to_gpio(m) ((m) % 128)
+
+/* list of all the configurable MFP pins */
+enum {
+ MFP_PIN_INVALID = -1,
+
+ MFP_PIN_GPIO0 = 0,
+ MFP_PIN_GPIO1,
+ MFP_PIN_GPIO2,
+ MFP_PIN_GPIO3,
+ MFP_PIN_GPIO4,
+ MFP_PIN_GPIO5,
+ MFP_PIN_GPIO6,
+ MFP_PIN_GPIO7,
+ MFP_PIN_GPIO8,
+ MFP_PIN_GPIO9,
+ MFP_PIN_GPIO10,
+ MFP_PIN_GPIO11,
+ MFP_PIN_GPIO12,
+ MFP_PIN_GPIO13,
+ MFP_PIN_GPIO14,
+ MFP_PIN_GPIO15,
+ MFP_PIN_GPIO16,
+ MFP_PIN_GPIO17,
+ MFP_PIN_GPIO18,
+ MFP_PIN_GPIO19,
+ MFP_PIN_GPIO20,
+ MFP_PIN_GPIO21,
+ MFP_PIN_GPIO22,
+ MFP_PIN_GPIO23,
+ MFP_PIN_GPIO24,
+ MFP_PIN_GPIO25,
+ MFP_PIN_GPIO26,
+ MFP_PIN_GPIO27,
+ MFP_PIN_GPIO28,
+ MFP_PIN_GPIO29,
+ MFP_PIN_GPIO30,
+ MFP_PIN_GPIO31,
+ MFP_PIN_GPIO32,
+ MFP_PIN_GPIO33,
+ MFP_PIN_GPIO34,
+ MFP_PIN_GPIO35,
+ MFP_PIN_GPIO36,
+ MFP_PIN_GPIO37,
+ MFP_PIN_GPIO38,
+ MFP_PIN_GPIO39,
+ MFP_PIN_GPIO40,
+ MFP_PIN_GPIO41,
+ MFP_PIN_GPIO42,
+ MFP_PIN_GPIO43,
+ MFP_PIN_GPIO44,
+ MFP_PIN_GPIO45,
+ MFP_PIN_GPIO46,
+ MFP_PIN_GPIO47,
+ MFP_PIN_GPIO48,
+ MFP_PIN_GPIO49,
+ MFP_PIN_GPIO50,
+ MFP_PIN_GPIO51,
+ MFP_PIN_GPIO52,
+ MFP_PIN_GPIO53,
+ MFP_PIN_GPIO54,
+ MFP_PIN_GPIO55,
+ MFP_PIN_GPIO56,
+ MFP_PIN_GPIO57,
+ MFP_PIN_GPIO58,
+ MFP_PIN_GPIO59,
+ MFP_PIN_GPIO60,
+ MFP_PIN_GPIO61,
+ MFP_PIN_GPIO62,
+ MFP_PIN_GPIO63,
+ MFP_PIN_GPIO64,
+ MFP_PIN_GPIO65,
+ MFP_PIN_GPIO66,
+ MFP_PIN_GPIO67,
+ MFP_PIN_GPIO68,
+ MFP_PIN_GPIO69,
+ MFP_PIN_GPIO70,
+ MFP_PIN_GPIO71,
+ MFP_PIN_GPIO72,
+ MFP_PIN_GPIO73,
+ MFP_PIN_GPIO74,
+ MFP_PIN_GPIO75,
+ MFP_PIN_GPIO76,
+ MFP_PIN_GPIO77,
+ MFP_PIN_GPIO78,
+ MFP_PIN_GPIO79,
+ MFP_PIN_GPIO80,
+ MFP_PIN_GPIO81,
+ MFP_PIN_GPIO82,
+ MFP_PIN_GPIO83,
+ MFP_PIN_GPIO84,
+ MFP_PIN_GPIO85,
+ MFP_PIN_GPIO86,
+ MFP_PIN_GPIO87,
+ MFP_PIN_GPIO88,
+ MFP_PIN_GPIO89,
+ MFP_PIN_GPIO90,
+ MFP_PIN_GPIO91,
+ MFP_PIN_GPIO92,
+ MFP_PIN_GPIO93,
+ MFP_PIN_GPIO94,
+ MFP_PIN_GPIO95,
+ MFP_PIN_GPIO96,
+ MFP_PIN_GPIO97,
+ MFP_PIN_GPIO98,
+ MFP_PIN_GPIO99,
+ MFP_PIN_GPIO100,
+ MFP_PIN_GPIO101,
+ MFP_PIN_GPIO102,
+ MFP_PIN_GPIO103,
+ MFP_PIN_GPIO104,
+ MFP_PIN_GPIO105,
+ MFP_PIN_GPIO106,
+ MFP_PIN_GPIO107,
+ MFP_PIN_GPIO108,
+ MFP_PIN_GPIO109,
+ MFP_PIN_GPIO110,
+ MFP_PIN_GPIO111,
+ MFP_PIN_GPIO112,
+ MFP_PIN_GPIO113,
+ MFP_PIN_GPIO114,
+ MFP_PIN_GPIO115,
+ MFP_PIN_GPIO116,
+ MFP_PIN_GPIO117,
+ MFP_PIN_GPIO118,
+ MFP_PIN_GPIO119,
+ MFP_PIN_GPIO120,
+ MFP_PIN_GPIO121,
+ MFP_PIN_GPIO122,
+ MFP_PIN_GPIO123,
+ MFP_PIN_GPIO124,
+ MFP_PIN_GPIO125,
+ MFP_PIN_GPIO126,
+ MFP_PIN_GPIO127,
+ MFP_PIN_GPIO0_2,
+ MFP_PIN_GPIO1_2,
+ MFP_PIN_GPIO2_2,
+ MFP_PIN_GPIO3_2,
+ MFP_PIN_GPIO4_2,
+ MFP_PIN_GPIO5_2,
+ MFP_PIN_GPIO6_2,
+ MFP_PIN_GPIO7_2,
+ MFP_PIN_GPIO8_2,
+ MFP_PIN_GPIO9_2,
+ MFP_PIN_GPIO10_2,
+ MFP_PIN_GPIO11_2,
+ MFP_PIN_GPIO12_2,
+ MFP_PIN_GPIO13_2,
+ MFP_PIN_GPIO14_2,
+ MFP_PIN_GPIO15_2,
+ MFP_PIN_GPIO16_2,
+ MFP_PIN_GPIO17_2,
+
+ MFP_PIN_ULPI_STP,
+ MFP_PIN_ULPI_NXT,
+ MFP_PIN_ULPI_DIR,
+
+ MFP_PIN_nXCVREN,
+ MFP_PIN_DF_CLE_nOE,
+ MFP_PIN_DF_nADV1_ALE,
+ MFP_PIN_DF_SCLK_E,
+ MFP_PIN_DF_SCLK_S,
+ MFP_PIN_nBE0,
+ MFP_PIN_nBE1,
+ MFP_PIN_DF_nADV2_ALE,
+ MFP_PIN_DF_INT_RnB,
+ MFP_PIN_DF_nCS0,
+ MFP_PIN_DF_nCS1,
+ MFP_PIN_nLUA,
+ MFP_PIN_nLLA,
+ MFP_PIN_DF_nWE,
+ MFP_PIN_DF_ALE_nWE,
+ MFP_PIN_DF_nRE_nOE,
+ MFP_PIN_DF_ADDR0,
+ MFP_PIN_DF_ADDR1,
+ MFP_PIN_DF_ADDR2,
+ MFP_PIN_DF_ADDR3,
+ MFP_PIN_DF_IO0,
+ MFP_PIN_DF_IO1,
+ MFP_PIN_DF_IO2,
+ MFP_PIN_DF_IO3,
+ MFP_PIN_DF_IO4,
+ MFP_PIN_DF_IO5,
+ MFP_PIN_DF_IO6,
+ MFP_PIN_DF_IO7,
+ MFP_PIN_DF_IO8,
+ MFP_PIN_DF_IO9,
+ MFP_PIN_DF_IO10,
+ MFP_PIN_DF_IO11,
+ MFP_PIN_DF_IO12,
+ MFP_PIN_DF_IO13,
+ MFP_PIN_DF_IO14,
+ MFP_PIN_DF_IO15,
+
+ MFP_PIN_MAX,
+};
+
+/*
+ * Table that determines the low power modes outputs, with actual settings
+ * used in parentheses for don't-care values. Except for the float output,
+ * the configured driven and pulled levels match, so if there is a need for
+ * non-LPM pulled output, the same configuration could probably be used.
+ *
+ * Output value sleep_oe_n sleep_data pullup_en pulldown_en pull_sel
+ * (bit 7) (bit 8) (bit 14d) (bit 13d)
+ *
+ * Drive 0 0 0 0 X (1) 0
+ * Drive 1 0 1 X (1) 0 0
+ * Pull hi (1) 1 X(1) 1 0 0
+ * Pull lo (0) 1 X(0) 0 1 0
+ * Z (float) 1 X(0) 0 0 0
+ */
+#define MFP_LPM_DRIVE_LOW 0x8
+#define MFP_LPM_DRIVE_HIGH 0x6
+#define MFP_LPM_PULL_HIGH 0x7
+#define MFP_LPM_PULL_LOW 0x9
+#define MFP_LPM_FLOAT 0x1
+#define MFP_LPM_PULL_NEITHER 0x0
+
+/*
+ * The pullup and pulldown state of the MFP pin is by default determined by
+ * selected alternate function. In case some buggy devices need to override
+ * this default behavior, pxa3xx_mfp_set_pull() can be invoked with one of
+ * the following definition as the parameter.
+ *
+ * Definition pull_sel pullup_en pulldown_en
+ * MFP_PULL_HIGH 1 1 0
+ * MFP_PULL_LOW 1 0 1
+ * MFP_PULL_BOTH 1 1 1
+ * MFP_PULL_NONE 1 0 0
+ * MFP_PULL_DEFAULT 0 X X
+ *
+ * NOTE: pxa3xx_mfp_set_pull() will modify the PULLUP_EN and PULLDOWN_EN
+ * bits, which will cause potential conflicts with the low power mode
+ * setting, device drivers should take care of this
+ */
+#define MFP_PULL_BOTH (0x7u)
+#define MFP_PULL_HIGH (0x6u)
+#define MFP_PULL_LOW (0x5u)
+#define MFP_PULL_NONE (0x4u)
+#define MFP_PULL_DEFAULT (0x0u)
+
+#define MFP_AF0 (0)
+#define MFP_AF1 (1)
+#define MFP_AF2 (2)
+#define MFP_AF3 (3)
+#define MFP_AF4 (4)
+#define MFP_AF5 (5)
+#define MFP_AF6 (6)
+#define MFP_AF7 (7)
+
+#define MFP_DS01X (0)
+#define MFP_DS02X (1)
+#define MFP_DS03X (2)
+#define MFP_DS04X (3)
+#define MFP_DS06X (4)
+#define MFP_DS08X (5)
+#define MFP_DS10X (6)
+#define MFP_DS12X (7)
+
+#define MFP_EDGE_BOTH 0x3
+#define MFP_EDGE_RISE 0x2
+#define MFP_EDGE_FALL 0x1
+#define MFP_EDGE_NONE 0x0
+
+#define MFPR_AF_MASK 0x0007
+#define MFPR_DRV_MASK 0x1c00
+#define MFPR_RDH_MASK 0x0200
+#define MFPR_LPM_MASK 0xe180
+#define MFPR_PULL_MASK 0xe000
+#define MFPR_EDGE_MASK 0x0070
+
+#define MFPR_ALT_OFFSET 0
+#define MFPR_ERE_OFFSET 4
+#define MFPR_EFE_OFFSET 5
+#define MFPR_EC_OFFSET 6
+#define MFPR_SON_OFFSET 7
+#define MFPR_SD_OFFSET 8
+#define MFPR_SS_OFFSET 9
+#define MFPR_DRV_OFFSET 10
+#define MFPR_PD_OFFSET 13
+#define MFPR_PU_OFFSET 14
+#define MFPR_PS_OFFSET 15
+
+#define MFPR(af, drv, rdh, lpm, edge) \
+ (((af) & 0x7) | (((drv) & 0x7) << 10) |\
+ (((rdh) & 0x1) << 9) |\
+ (((lpm) & 0x3) << 7) |\
+ (((lpm) & 0x4) << 12)|\
+ (((lpm) & 0x8) << 10)|\
+ ((!(edge)) << 6) |\
+ (((edge) & 0x1) << 5) |\
+ (((edge) & 0x2) << 3))
+
+/*
+ * a possible MFP configuration is represented by a 32-bit integer
+ * bit 0..15 - MFPR value (16-bit)
+ * bit 16..31 - mfp pin index (used to obtain the MFPR offset)
+ *
+ * to facilitate the definition, the following macros are provided
+ *
+ * MFPR_DEFAULT - default MFPR value, with
+ * alternate function = 0,
+ * drive strength = fast 1mA (MFP_DS01X)
+ * low power mode = default
+ * release dalay hold = false (RDH bit)
+ * edge detection = none
+ *
+ * MFP_CFG - default MFPR value with alternate function
+ * MFP_CFG_DRV - default MFPR value with alternate function and
+ * pin drive strength
+ * MFP_CFG_LPM - default MFPR value with alternate function and
+ * low power mode
+ * MFP_CFG_X - default MFPR value with alternate function,
+ * pin drive strength and low power mode
+ *
+ * use
+ *
+ * MFP_CFG_PIN - to get the MFP pin index
+ * MFP_CFG_VAL - to get the corresponding MFPR value
+ */
+
+typedef uint32_t mfp_cfg_t;
+
+#define MFP_CFG_PIN(mfp_cfg) (((mfp_cfg) >> 16) & 0xffff)
+#define MFP_CFG_VAL(mfp_cfg) ((mfp_cfg) & 0xffff)
+
+#define MFPR_DEFAULT (0x0000)
+
+#define MFP_CFG(pin, af) \
+ ((MFP_PIN_##pin << 16) | MFPR_DEFAULT | (MFP_##af))
+
+#define MFP_CFG_DRV(pin, af, drv) \
+ ((MFP_PIN_##pin << 16) | MFPR_DEFAULT |\
+ ((MFP_##drv) << 10) | (MFP_##af))
+
+#define MFP_CFG_LPM(pin, af, lpm) \
+ ((MFP_PIN_##pin << 16) | MFPR_DEFAULT | (MFP_##af) |\
+ (((MFP_LPM_##lpm) & 0x3) << 7) |\
+ (((MFP_LPM_##lpm) & 0x4) << 12) |\
+ (((MFP_LPM_##lpm) & 0x8) << 10))
+
+#define MFP_CFG_X(pin, af, drv, lpm) \
+ ((MFP_PIN_##pin << 16) | MFPR_DEFAULT |\
+ ((MFP_##drv) << 10) | (MFP_##af) |\
+ (((MFP_LPM_##lpm) & 0x3) << 7) |\
+ (((MFP_LPM_##lpm) & 0x4) << 12) |\
+ (((MFP_LPM_##lpm) & 0x8) << 10))
+
+/* common MFP configurations - processor specific ones defined
+ * in mfp-pxa3xx.h
+ */
+#define GPIO0_GPIO MFP_CFG(GPIO0, AF0)
+#define GPIO1_GPIO MFP_CFG(GPIO1, AF0)
+#define GPIO2_GPIO MFP_CFG(GPIO2, AF0)
+#define GPIO3_GPIO MFP_CFG(GPIO3, AF0)
+#define GPIO4_GPIO MFP_CFG(GPIO4, AF0)
+#define GPIO5_GPIO MFP_CFG(GPIO5, AF0)
+#define GPIO6_GPIO MFP_CFG(GPIO6, AF0)
+#define GPIO7_GPIO MFP_CFG(GPIO7, AF0)
+#define GPIO8_GPIO MFP_CFG(GPIO8, AF0)
+#define GPIO9_GPIO MFP_CFG(GPIO9, AF0)
+#define GPIO10_GPIO MFP_CFG(GPIO10, AF0)
+#define GPIO11_GPIO MFP_CFG(GPIO11, AF0)
+#define GPIO12_GPIO MFP_CFG(GPIO12, AF0)
+#define GPIO13_GPIO MFP_CFG(GPIO13, AF0)
+#define GPIO14_GPIO MFP_CFG(GPIO14, AF0)
+#define GPIO15_GPIO MFP_CFG(GPIO15, AF0)
+#define GPIO16_GPIO MFP_CFG(GPIO16, AF0)
+#define GPIO17_GPIO MFP_CFG(GPIO17, AF0)
+#define GPIO18_GPIO MFP_CFG(GPIO18, AF0)
+#define GPIO19_GPIO MFP_CFG(GPIO19, AF0)
+#define GPIO20_GPIO MFP_CFG(GPIO20, AF0)
+#define GPIO21_GPIO MFP_CFG(GPIO21, AF0)
+#define GPIO22_GPIO MFP_CFG(GPIO22, AF0)
+#define GPIO23_GPIO MFP_CFG(GPIO23, AF0)
+#define GPIO24_GPIO MFP_CFG(GPIO24, AF0)
+#define GPIO25_GPIO MFP_CFG(GPIO25, AF0)
+#define GPIO26_GPIO MFP_CFG(GPIO26, AF0)
+#define GPIO27_GPIO MFP_CFG(GPIO27, AF0)
+#define GPIO28_GPIO MFP_CFG(GPIO28, AF0)
+#define GPIO29_GPIO MFP_CFG(GPIO29, AF0)
+#define GPIO30_GPIO MFP_CFG(GPIO30, AF0)
+#define GPIO31_GPIO MFP_CFG(GPIO31, AF0)
+#define GPIO32_GPIO MFP_CFG(GPIO32, AF0)
+#define GPIO33_GPIO MFP_CFG(GPIO33, AF0)
+#define GPIO34_GPIO MFP_CFG(GPIO34, AF0)
+#define GPIO35_GPIO MFP_CFG(GPIO35, AF0)
+#define GPIO36_GPIO MFP_CFG(GPIO36, AF0)
+#define GPIO37_GPIO MFP_CFG(GPIO37, AF0)
+#define GPIO38_GPIO MFP_CFG(GPIO38, AF0)
+#define GPIO39_GPIO MFP_CFG(GPIO39, AF0)
+#define GPIO40_GPIO MFP_CFG(GPIO40, AF0)
+#define GPIO41_GPIO MFP_CFG(GPIO41, AF0)
+#define GPIO42_GPIO MFP_CFG(GPIO42, AF0)
+#define GPIO43_GPIO MFP_CFG(GPIO43, AF0)
+#define GPIO44_GPIO MFP_CFG(GPIO44, AF0)
+#define GPIO45_GPIO MFP_CFG(GPIO45, AF0)
+
+#define GPIO47_GPIO MFP_CFG(GPIO47, AF0)
+#define GPIO48_GPIO MFP_CFG(GPIO48, AF0)
+
+#define GPIO53_GPIO MFP_CFG(GPIO53, AF0)
+#define GPIO54_GPIO MFP_CFG(GPIO54, AF0)
+#define GPIO55_GPIO MFP_CFG(GPIO55, AF0)
+
+#define GPIO57_GPIO MFP_CFG(GPIO57, AF0)
+
+#define GPIO63_GPIO MFP_CFG(GPIO63, AF0)
+#define GPIO64_GPIO MFP_CFG(GPIO64, AF0)
+#define GPIO65_GPIO MFP_CFG(GPIO65, AF0)
+#define GPIO66_GPIO MFP_CFG(GPIO66, AF0)
+#define GPIO67_GPIO MFP_CFG(GPIO67, AF0)
+#define GPIO68_GPIO MFP_CFG(GPIO68, AF0)
+#define GPIO69_GPIO MFP_CFG(GPIO69, AF0)
+#define GPIO70_GPIO MFP_CFG(GPIO70, AF0)
+#define GPIO71_GPIO MFP_CFG(GPIO71, AF0)
+#define GPIO72_GPIO MFP_CFG(GPIO72, AF0)
+#define GPIO73_GPIO MFP_CFG(GPIO73, AF0)
+#define GPIO74_GPIO MFP_CFG(GPIO74, AF0)
+#define GPIO75_GPIO MFP_CFG(GPIO75, AF0)
+#define GPIO76_GPIO MFP_CFG(GPIO76, AF0)
+#define GPIO77_GPIO MFP_CFG(GPIO77, AF0)
+#define GPIO78_GPIO MFP_CFG(GPIO78, AF0)
+#define GPIO79_GPIO MFP_CFG(GPIO79, AF0)
+#define GPIO80_GPIO MFP_CFG(GPIO80, AF0)
+#define GPIO81_GPIO MFP_CFG(GPIO81, AF0)
+#define GPIO82_GPIO MFP_CFG(GPIO82, AF0)
+#define GPIO83_GPIO MFP_CFG(GPIO83, AF0)
+#define GPIO84_GPIO MFP_CFG(GPIO84, AF0)
+#define GPIO85_GPIO MFP_CFG(GPIO85, AF0)
+#define GPIO86_GPIO MFP_CFG(GPIO86, AF0)
+#define GPIO87_GPIO MFP_CFG(GPIO87, AF0)
+#define GPIO88_GPIO MFP_CFG(GPIO88, AF0)
+#define GPIO89_GPIO MFP_CFG(GPIO89, AF0)
+#define GPIO90_GPIO MFP_CFG(GPIO90, AF0)
+#define GPIO91_GPIO MFP_CFG(GPIO91, AF0)
+#define GPIO92_GPIO MFP_CFG(GPIO92, AF0)
+#define GPIO93_GPIO MFP_CFG(GPIO93, AF0)
+#define GPIO94_GPIO MFP_CFG(GPIO94, AF0)
+#define GPIO95_GPIO MFP_CFG(GPIO95, AF0)
+#define GPIO96_GPIO MFP_CFG(GPIO96, AF0)
+#define GPIO97_GPIO MFP_CFG(GPIO97, AF0)
+#define GPIO98_GPIO MFP_CFG(GPIO98, AF0)
+#define GPIO99_GPIO MFP_CFG(GPIO99, AF0)
+#define GPIO100_GPIO MFP_CFG(GPIO100, AF0)
+#define GPIO101_GPIO MFP_CFG(GPIO101, AF0)
+#define GPIO102_GPIO MFP_CFG(GPIO102, AF0)
+#define GPIO103_GPIO MFP_CFG(GPIO103, AF0)
+#define GPIO104_GPIO MFP_CFG(GPIO104, AF0)
+#define GPIO105_GPIO MFP_CFG(GPIO105, AF0)
+#define GPIO106_GPIO MFP_CFG(GPIO106, AF0)
+#define GPIO107_GPIO MFP_CFG(GPIO107, AF0)
+#define GPIO108_GPIO MFP_CFG(GPIO108, AF0)
+#define GPIO109_GPIO MFP_CFG(GPIO109, AF0)
+#define GPIO110_GPIO MFP_CFG(GPIO110, AF0)
+#define GPIO111_GPIO MFP_CFG(GPIO111, AF0)
+#define GPIO112_GPIO MFP_CFG(GPIO112, AF0)
+#define GPIO113_GPIO MFP_CFG(GPIO113, AF0)
+#define GPIO114_GPIO MFP_CFG(GPIO114, AF0)
+#define GPIO115_GPIO MFP_CFG(GPIO115, AF0)
+#define GPIO116_GPIO MFP_CFG(GPIO116, AF0)
+#define GPIO117_GPIO MFP_CFG(GPIO117, AF0)
+#define GPIO118_GPIO MFP_CFG(GPIO118, AF0)
+#define GPIO119_GPIO MFP_CFG(GPIO119, AF0)
+#define GPIO120_GPIO MFP_CFG(GPIO120, AF0)
+#define GPIO121_GPIO MFP_CFG(GPIO121, AF0)
+#define GPIO122_GPIO MFP_CFG(GPIO122, AF0)
+#define GPIO123_GPIO MFP_CFG(GPIO123, AF0)
+#define GPIO124_GPIO MFP_CFG(GPIO124, AF0)
+#define GPIO125_GPIO MFP_CFG(GPIO125, AF0)
+#define GPIO126_GPIO MFP_CFG(GPIO126, AF0)
+#define GPIO127_GPIO MFP_CFG(GPIO127, AF0)
+
+#define GPIO0_2_GPIO MFP_CFG(GPIO0_2, AF0)
+#define GPIO1_2_GPIO MFP_CFG(GPIO1_2, AF0)
+#define GPIO2_2_GPIO MFP_CFG(GPIO2_2, AF0)
+#define GPIO3_2_GPIO MFP_CFG(GPIO3_2, AF0)
+#define GPIO4_2_GPIO MFP_CFG(GPIO4_2, AF0)
+#define GPIO5_2_GPIO MFP_CFG(GPIO5_2, AF0)
+#define GPIO6_2_GPIO MFP_CFG(GPIO6_2, AF0)
+
+/*
+ * each MFP pin will have a MFPR register, since the offset of the
+ * register varies between processors, the processor specific code
+ * should initialize the pin offsets by pxa3xx_mfp_init_addr()
+ *
+ * pxa3xx_mfp_init_addr - accepts a table of "pxa3xx_mfp_addr_map"
+ * structure, which represents a range of MFP pins from "start" to
+ * "end", with the offset begining at "offset", to define a single
+ * pin, let "end" = -1
+ *
+ * use
+ *
+ * MFP_ADDR_X() to define a range of pins
+ * MFP_ADDR() to define a single pin
+ * MFP_ADDR_END to signal the end of pin offset definitions
+ */
+struct pxa3xx_mfp_addr_map {
+ unsigned int start;
+ unsigned int end;
+ unsigned long offset;
+};
+
+#define MFP_ADDR_X(start, end, offset) \
+ { MFP_PIN_##start, MFP_PIN_##end, offset }
+
+#define MFP_ADDR(pin, offset) \
+ { MFP_PIN_##pin, -1, offset }
+
+#define MFP_ADDR_END { MFP_PIN_INVALID, 0 }
+
+struct pxa3xx_mfp_pin {
+ unsigned long mfpr_off; /* MFPRxx register offset */
+ unsigned long mfpr_val; /* MFPRxx register value */
+};
+
+/*
+ * pxa3xx_mfp_read()/pxa3xx_mfp_write() - for direct read/write access
+ * to the MFPR register
+ */
+unsigned long pxa3xx_mfp_read(int mfp);
+void pxa3xx_mfp_write(int mfp, unsigned long mfpr_val);
+
+/*
+ * pxa3xx_mfp_set_afds - set MFP alternate function and drive strength
+ * pxa3xx_mfp_set_rdh - set MFP release delay hold on/off
+ * pxa3xx_mfp_set_lpm - set MFP low power mode state
+ * pxa3xx_mfp_set_edge - set MFP edge detection in low power mode
+ *
+ * use these functions to override/change the default configuration
+ * done by pxa3xx_mfp_set_config(s)
+ */
+void pxa3xx_mfp_set_afds(int mfp, int af, int ds);
+void pxa3xx_mfp_set_rdh(int mfp, int rdh);
+void pxa3xx_mfp_set_lpm(int mfp, int lpm);
+void pxa3xx_mfp_set_edge(int mfp, int edge);
+
+/*
+ * pxa3xx_mfp_config - configure the MFPR registers
+ *
+ * used by board specific initialization code
+ */
+void pxa3xx_mfp_config(mfp_cfg_t *mfp_cfgs, int num);
+
+/*
+ * pxa3xx_mfp_init_addr() - initialize the mapping between mfp pin
+ * index and MFPR register offset
+ *
+ * used by processor specific code
+ */
+void __init pxa3xx_mfp_init_addr(struct pxa3xx_mfp_addr_map *);
+void __init pxa3xx_init_mfp(void);
+
+#endif /* __ASM_ARCH_MFP_H */
diff --git a/include/asm-arm/arch-pxa/pm.h b/include/asm-arm/arch-pxa/pm.h
index 6903db7fae15..9d9f4b54b2ce 100644
--- a/include/asm-arm/arch-pxa/pm.h
+++ b/include/asm-arm/arch-pxa/pm.h
@@ -7,6 +7,8 @@
*
*/
+#include <linux/suspend.h>
+
struct pxa_cpu_pm_fns {
int save_size;
void (*save)(unsigned long *);
diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h
index e68b593d69da..bb68b598c436 100644
--- a/include/asm-arm/arch-pxa/pxa-regs.h
+++ b/include/asm-arm/arch-pxa/pxa-regs.h
@@ -1177,7 +1177,7 @@
#define GPIO_bit(x) (1 << ((x) & 0x1f))
-#ifdef CONFIG_PXA27x
+#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
/* Interrupt Controller */
@@ -1823,6 +1823,7 @@
#define LCCR1 __REG(0x44000004) /* LCD Controller Control Register 1 */
#define LCCR2 __REG(0x44000008) /* LCD Controller Control Register 2 */
#define LCCR3 __REG(0x4400000C) /* LCD Controller Control Register 3 */
+#define LCCR4 __REG(0x44000010) /* LCD Controller Control Register 3 */
#define DFBR0 __REG(0x44000020) /* DMA Channel 0 Frame Branch Register */
#define DFBR1 __REG(0x44000024) /* DMA Channel 1 Frame Branch Register */
#define LCSR __REG(0x44000038) /* LCD Controller Status Register */
@@ -1836,6 +1837,16 @@
#define LCCR3_8BPP (3 << 24)
#define LCCR3_16BPP (4 << 24)
+#define LCCR3_PDFOR_0 (0 << 30)
+#define LCCR3_PDFOR_1 (1 << 30)
+#define LCCR3_PDFOR_2 (2 << 30)
+#define LCCR3_PDFOR_3 (3 << 30)
+
+#define LCCR4_PAL_FOR_0 (0 << 15)
+#define LCCR4_PAL_FOR_1 (1 << 15)
+#define LCCR4_PAL_FOR_2 (2 << 15)
+#define LCCR4_PAL_FOR_MASK (3 << 15)
+
#define FDADR0 __REG(0x44000200) /* DMA Channel 0 Frame Descriptor Address Register */
#define FSADR0 __REG(0x44000204) /* DMA Channel 0 Frame Source Address Register */
#define FIDR0 __REG(0x44000208) /* DMA Channel 0 Frame ID Register */
diff --git a/include/asm-arm/arch-pxa/pxa3xx-regs.h b/include/asm-arm/arch-pxa/pxa3xx-regs.h
new file mode 100644
index 000000000000..3900a0ca0bc0
--- /dev/null
+++ b/include/asm-arm/arch-pxa/pxa3xx-regs.h
@@ -0,0 +1,75 @@
+/*
+ * linux/include/asm-arm/arch-pxa/pxa3xx-regs.h
+ *
+ * PXA3xx specific register definitions
+ *
+ * Copyright (C) 2007 Marvell International Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_PXA3XX_REGS_H
+#define __ASM_ARCH_PXA3XX_REGS_H
+
+/*
+ * Application Subsystem Clock
+ */
+#define ACCR __REG(0x41340000) /* Application Subsystem Clock Configuration Register */
+#define ACSR __REG(0x41340004) /* Application Subsystem Clock Status Register */
+#define AICSR __REG(0x41340008) /* Application Subsystem Interrupt Control/Status Register */
+#define CKENA __REG(0x4134000C) /* A Clock Enable Register */
+#define CKENB __REG(0x41340010) /* B Clock Enable Register */
+#define AC97_DIV __REG(0x41340014) /* AC97 clock divisor value register */
+
+/*
+ * Clock Enable Bit
+ */
+#define CKEN_LCD 1 /* < LCD Clock Enable */
+#define CKEN_USBH 2 /* < USB host clock enable */
+#define CKEN_CAMERA 3 /* < Camera interface clock enable */
+#define CKEN_NAND 4 /* < NAND Flash Controller Clock Enable */
+#define CKEN_USB2 6 /* < USB 2.0 client clock enable. */
+#define CKEN_DMC 8 /* < Dynamic Memory Controller clock enable */
+#define CKEN_SMC 9 /* < Static Memory Controller clock enable */
+#define CKEN_ISC 10 /* < Internal SRAM Controller clock enable */
+#define CKEN_BOOT 11 /* < Boot rom clock enable */
+#define CKEN_MMC1 12 /* < MMC1 Clock enable */
+#define CKEN_MMC2 13 /* < MMC2 clock enable */
+#define CKEN_KEYPAD 14 /* < Keypand Controller Clock Enable */
+#define CKEN_CIR 15 /* < Consumer IR Clock Enable */
+#define CKEN_USIM0 17 /* < USIM[0] Clock Enable */
+#define CKEN_USIM1 18 /* < USIM[1] Clock Enable */
+#define CKEN_TPM 19 /* < TPM clock enable */
+#define CKEN_UDC 20 /* < UDC clock enable */
+#define CKEN_BTUART 21 /* < BTUART clock enable */
+#define CKEN_FFUART 22 /* < FFUART clock enable */
+#define CKEN_STUART 23 /* < STUART clock enable */
+#define CKEN_AC97 24 /* < AC97 clock enable */
+#define CKEN_TOUCH 25 /* < Touch screen Interface Clock Enable */
+#define CKEN_SSP1 26 /* < SSP1 clock enable */
+#define CKEN_SSP2 27 /* < SSP2 clock enable */
+#define CKEN_SSP3 28 /* < SSP3 clock enable */
+#define CKEN_SSP4 29 /* < SSP4 clock enable */
+#define CKEN_MSL0 30 /* < MSL0 clock enable */
+#define CKEN_PWM0 32 /* < PWM[0] clock enable */
+#define CKEN_PWM1 33 /* < PWM[1] clock enable */
+#define CKEN_I2C 36 /* < I2C clock enable */
+#define CKEN_INTC 38 /* < Interrupt controller clock enable */
+#define CKEN_GPIO 39 /* < GPIO clock enable */
+#define CKEN_1WIRE 40 /* < 1-wire clock enable */
+#define CKEN_HSIO2 41 /* < HSIO2 clock enable */
+#define CKEN_MINI_IM 48 /* < Mini-IM */
+#define CKEN_MINI_LCD 49 /* < Mini LCD */
+
+#if defined(CONFIG_CPU_PXA310)
+#define CKEN_MMC3 5 /* < MMC3 Clock Enable */
+#define CKEN_MVED 43 /* < MVED clock enable */
+#endif
+
+/* Note: GCU clock enable bit differs on PXA300/PXA310 and PXA320 */
+#define PXA300_CKEN_GRAPHICS 42 /* Graphics controller clock enable */
+#define PXA320_CKEN_GRAPHICS 7 /* Graphics controller clock enable */
+
+#endif /* __ASM_ARCH_PXA3XX_REGS_H */
diff --git a/include/asm-arm/arch-pxa/pxafb.h b/include/asm-arm/arch-pxa/pxafb.h
index 81c3928d608c..ea2336aa70e4 100644
--- a/include/asm-arm/arch-pxa/pxafb.h
+++ b/include/asm-arm/arch-pxa/pxafb.h
@@ -70,7 +70,12 @@ struct pxafb_mach_info {
* LCCR3_HSP, LCCR3_VSP, LCCR0_Pcd(x), LCCR3_Bpp
*/
u_int lccr3;
-
+ /* The following should be defined in LCCR4
+ * LCCR4_PAL_FOR_0 or LCCR4_PAL_FOR_1 or LCCR4_PAL_FOR_2
+ *
+ * All other bits in LCCR4 should be left alone.
+ */
+ u_int lccr4;
void (*pxafb_backlight_power)(int);
void (*pxafb_lcd_power)(int, struct fb_var_screeninfo *);
diff --git a/include/asm-arm/arch-pxa/timex.h b/include/asm-arm/arch-pxa/timex.h
index 2473bb51d0a6..8d882f0b6a16 100644
--- a/include/asm-arm/arch-pxa/timex.h
+++ b/include/asm-arm/arch-pxa/timex.h
@@ -21,4 +21,6 @@
#else
#define CLOCK_TICK_RATE 3250000
#endif
+#else
+#define CLOCK_TICK_RATE 3250000
#endif
diff --git a/include/asm-arm/arch-pxa/zylonite.h b/include/asm-arm/arch-pxa/zylonite.h
new file mode 100644
index 000000000000..f58b59162b82
--- /dev/null
+++ b/include/asm-arm/arch-pxa/zylonite.h
@@ -0,0 +1,35 @@
+#ifndef __ASM_ARCH_ZYLONITE_H
+#define __ASM_ARCH_ZYLONITE_H
+
+#define ZYLONITE_ETH_PHYS 0x14000000
+
+/* the following variables are processor specific and initialized
+ * by the corresponding zylonite_pxa3xx_init()
+ */
+extern int gpio_backlight;
+extern int gpio_eth_irq;
+
+extern int lcd_id;
+extern int lcd_orientation;
+
+#ifdef CONFIG_CPU_PXA300
+extern void zylonite_pxa300_init(void);
+#else
+static inline void zylonite_pxa300_init(void)
+{
+ if (cpu_is_pxa300() || cpu_is_pxa310())
+ panic("%s: PXA300/PXA310 not supported\n", __FUNCTION__);
+}
+#endif
+
+#ifdef CONFIG_CPU_PXA320
+extern void zylonite_pxa320_init(void);
+#else
+static inline void zylonite_pxa320_init(void)
+{
+ if (cpu_is_pxa320())
+ panic("%s: PXA320 not supported\n", __FUNCTION__);
+}
+#endif
+
+#endif /* __ASM_ARCH_ZYLONITE_H */
diff --git a/include/asm-arm/arch-rpc/uncompress.h b/include/asm-arm/arch-rpc/uncompress.h
index 06231ede54e5..b8e29efd8c5b 100644
--- a/include/asm-arm/arch-rpc/uncompress.h
+++ b/include/asm-arm/arch-rpc/uncompress.h
@@ -11,9 +11,11 @@
#include <asm/hardware.h>
#include <asm/io.h>
+#include <asm/setup.h>
+#include <asm/page.h>
-int video_num_columns, video_num_lines, video_size_row;
-int white, bytes_per_char_h;
+int video_size_row;
+unsigned char bytes_per_char_h;
extern unsigned long con_charconvtable[256];
struct param_struct {
@@ -64,6 +66,13 @@ extern __attribute__((pure)) struct param_struct *params(void);
#define params (params())
#ifndef STANDALONE_DEBUG
+static unsigned long video_num_cols;
+static unsigned long video_num_rows;
+static unsigned long video_x;
+static unsigned long video_y;
+static unsigned char bytes_per_char_v;
+static int white;
+
/*
* This does not append a newline
*/
@@ -73,27 +82,27 @@ static void putc(int c)
int x,y;
char *ptr;
- x = params->video_x;
- y = params->video_y;
+ x = video_x;
+ y = video_y;
if (c == '\n') {
- if (++y >= video_num_lines)
+ if (++y >= video_num_rows)
y--;
} else if (c == '\r') {
x = 0;
} else {
- ptr = VIDMEM + ((y*video_num_columns*params->bytes_per_char_v+x)*bytes_per_char_h);
+ ptr = VIDMEM + ((y*video_num_cols*bytes_per_char_v+x)*bytes_per_char_h);
ll_write_char(ptr, c, white);
- if (++x >= video_num_columns) {
+ if (++x >= video_num_cols) {
x = 0;
- if ( ++y >= video_num_lines ) {
+ if ( ++y >= video_num_rows ) {
y--;
}
}
}
- params->video_x = x;
- params->video_y = y;
+ video_x = x;
+ video_y = y;
}
static inline void flush(void)
@@ -108,11 +117,44 @@ static void error(char *x);
static void arch_decomp_setup(void)
{
int i;
+ struct tag *t = (struct tag *)params;
+ unsigned int nr_pages = 0, page_size = PAGE_SIZE;
+
+ if (t->hdr.tag == ATAG_CORE)
+ {
+ for (; t->hdr.size; t = tag_next(t))
+ {
+ if (t->hdr.tag == ATAG_VIDEOTEXT)
+ {
+ video_num_rows = t->u.videotext.video_lines;
+ video_num_cols = t->u.videotext.video_cols;
+ bytes_per_char_h = t->u.videotext.video_points;
+ bytes_per_char_v = t->u.videotext.video_points;
+ video_x = t->u.videotext.x;
+ video_y = t->u.videotext.y;
+ }
+
+ if (t->hdr.tag == ATAG_MEM)
+ {
+ page_size = PAGE_SIZE;
+ nr_pages += (t->u.mem.size / PAGE_SIZE);
+ }
+ }
+ }
+ else
+ {
+ nr_pages = params->nr_pages;
+ page_size = params->page_size;
+ video_num_rows = params->video_num_rows;
+ video_num_cols = params->video_num_cols;
+ video_x = params->video_x;
+ video_y = params->video_y;
+ bytes_per_char_h = params->bytes_per_char_h;
+ bytes_per_char_v = params->bytes_per_char_v;
+ }
+
+ video_size_row = video_num_cols * bytes_per_char_h;
- video_num_lines = params->video_num_rows;
- video_num_columns = params->video_num_cols;
- bytes_per_char_h = params->bytes_per_char_h;
- video_size_row = video_num_columns * bytes_per_char_h;
if (bytes_per_char_h == 4)
for (i = 0; i < 256; i++)
con_charconvtable[i] =
@@ -146,7 +188,7 @@ static void arch_decomp_setup(void)
white = 7;
}
- if (params->nr_pages * params->page_size < 4096*1024) error("<4M of mem\n");
+ if (nr_pages * page_size < 4096*1024) error("<4M of mem\n");
}
#endif
diff --git a/include/asm-arm/arch-s3c2410/fb.h b/include/asm-arm/arch-s3c2410/fb.h
index 93a58e7862b0..5d0262601a7e 100644
--- a/include/asm-arm/arch-s3c2410/fb.h
+++ b/include/asm-arm/arch-s3c2410/fb.h
@@ -14,12 +14,6 @@
#include <asm/arch/regs-lcd.h>
-struct s3c2410fb_val {
- unsigned int defval;
- unsigned int min;
- unsigned int max;
-};
-
struct s3c2410fb_hw {
unsigned long lcdcon1;
unsigned long lcdcon2;
@@ -28,23 +22,37 @@ struct s3c2410fb_hw {
unsigned long lcdcon5;
};
-struct s3c2410fb_mach_info {
- unsigned char fixed_syncs; /* do not update sync/border */
-
- /* LCD types */
- int type;
+/* LCD description */
+struct s3c2410fb_display {
+ /* LCD type */
+ unsigned type;
/* Screen size */
- int width;
- int height;
+ unsigned short width;
+ unsigned short height;
/* Screen info */
- struct s3c2410fb_val xres;
- struct s3c2410fb_val yres;
- struct s3c2410fb_val bpp;
+ unsigned short xres;
+ unsigned short yres;
+ unsigned short bpp;
+
+ unsigned pixclock; /* pixclock in picoseconds */
+ unsigned short left_margin; /* value in pixels (TFT) or HCLKs (STN) */
+ unsigned short right_margin; /* value in pixels (TFT) or HCLKs (STN) */
+ unsigned short hsync_len; /* value in pixels (TFT) or HCLKs (STN) */
+ unsigned short upper_margin; /* value in lines (TFT) or 0 (STN) */
+ unsigned short lower_margin; /* value in lines (TFT) or 0 (STN) */
+ unsigned short vsync_len; /* value in lines (TFT) or 0 (STN) */
/* lcd configuration registers */
- struct s3c2410fb_hw regs;
+ unsigned long lcdcon5;
+};
+
+struct s3c2410fb_mach_info {
+
+ struct s3c2410fb_display *displays; /* attached diplays info */
+ unsigned num_displays; /* number of defined displays */
+ unsigned default_display;
/* GPIOs */
diff --git a/include/asm-arm/arch-s3c2410/irqs.h b/include/asm-arm/arch-s3c2410/irqs.h
index 3b49cd1c345c..996f65488d2d 100644
--- a/include/asm-arm/arch-s3c2410/irqs.h
+++ b/include/asm-arm/arch-s3c2410/irqs.h
@@ -112,6 +112,13 @@
#define IRQ_TC S3C2410_IRQSUB(9)
#define IRQ_ADC S3C2410_IRQSUB(10)
+/* extra irqs for s3c2412 */
+
+#define IRQ_S3C2412_CFSDI S3C2410_IRQ(21)
+
+#define IRQ_S3C2412_SDI S3C2410_IRQSUB(13)
+#define IRQ_S3C2412_CF S3C2410_IRQSUB(14)
+
/* extra irqs for s3c2440 */
#define IRQ_S3C2440_CAM_C S3C2410_IRQSUB(11) /* S3C2443 too */
diff --git a/include/asm-arm/arch-s3c2410/regs-gpio.h b/include/asm-arm/arch-s3c2410/regs-gpio.h
index dea578b8f7f6..b693158b2d3c 100644
--- a/include/asm-arm/arch-s3c2410/regs-gpio.h
+++ b/include/asm-arm/arch-s3c2410/regs-gpio.h
@@ -1140,10 +1140,16 @@
/* definitions for each pin bit */
#define S3C2412_SLPCON_LOW(x) ( 0x00 << ((x) * 2))
-#define S3C2412_SLPCON_HI(x) ( 0x01 << ((x) * 2))
+#define S3C2412_SLPCON_HIGH(x) ( 0x01 << ((x) * 2))
#define S3C2412_SLPCON_IN(x) ( 0x02 << ((x) * 2))
-#define S3C2412_SLPCON_PDWN(x) ( 0x03 << ((x) * 2))
+#define S3C2412_SLPCON_PULL(x) ( 0x03 << ((x) * 2))
+#define S3C2412_SLPCON_EINT(x) ( 0x02 << ((x) * 2)) /* only IRQ pins */
#define S3C2412_SLPCON_MASK(x) ( 0x03 << ((x) * 2))
+#define S3C2412_SLPCON_ALL_LOW (0x0)
+#define S3C2412_SLPCON_ALL_HIGH (0x11111111 | 0x44444444)
+#define S3C2412_SLPCON_ALL_IN (0x22222222 | 0x88888888)
+#define S3C2412_SLPCON_ALL_PULL (0x33333333)
+
#endif /* __ASM_ARCH_REGS_GPIO_H */
diff --git a/include/asm-arm/arch-s3c2410/regs-power.h b/include/asm-arm/arch-s3c2410/regs-power.h
index 94ff96505b6a..f79987be55e8 100644
--- a/include/asm-arm/arch-s3c2410/regs-power.h
+++ b/include/asm-arm/arch-s3c2410/regs-power.h
@@ -18,6 +18,11 @@
#define S3C2412_PWRMODECON S3C24XX_PWRREG(0x20)
#define S3C2412_PWRCFG S3C24XX_PWRREG(0x24)
+#define S3C2412_INFORM0 S3C24XX_PWRREG(0x70)
+#define S3C2412_INFORM1 S3C24XX_PWRREG(0x74)
+#define S3C2412_INFORM2 S3C24XX_PWRREG(0x78)
+#define S3C2412_INFORM3 S3C24XX_PWRREG(0x7C)
+
#define S3C2412_PWRCFG_BATF_IGNORE (0<<0)
#define S3C2412_PWRCFG_BATF_SLEEP (3<<0)
#define S3C2412_PWRCFG_BATF_MASK (3<<0)
diff --git a/include/asm-arm/arch-s3c2410/regs-s3c2412.h b/include/asm-arm/arch-s3c2410/regs-s3c2412.h
index 8ca6a3bc8555..783b18f5bcea 100644
--- a/include/asm-arm/arch-s3c2410/regs-s3c2412.h
+++ b/include/asm-arm/arch-s3c2410/regs-s3c2412.h
@@ -17,5 +17,7 @@
#define S3C2412_SWRST (S3C24XX_VA_CLKPWR + 0x30)
#define S3C2412_SWRST_RESET (0x533C2412)
+/* see regs-power.h for the other registers in the power block. */
+
#endif /* __ASM_ARCH_REGS_S3C2412_H */
diff --git a/include/asm-arm/arch-sa1100/SA-1101.h b/include/asm-arm/arch-sa1100/SA-1101.h
index 527d887f1ee3..65ca8c79e6d2 100644
--- a/include/asm-arm/arch-sa1100/SA-1101.h
+++ b/include/asm-arm/arch-sa1100/SA-1101.h
@@ -106,7 +106,7 @@
#define SMCR_ColAdrBits( x ) /* col. addr bits 8..11 */ \
(( (x) - 8 ) << FShft (SMCR_DCAC))
#define SMCR_RowAdrBits( x ) /* row addr bits 9..12 */\
- (( (x) - 9 ) << FShft (SMCR_DRAC)
+ (( (x) - 9 ) << FShft (SMCR_DRAC))
#define SNPR_VFBstart Fld(12,0) /* Video frame buffer addr */
#define SNPR_VFBsize Fld(11,12) /* Video frame buffer size */
@@ -394,7 +394,7 @@
#define VgaStatus (*((volatile Word *) SA1101_p2v (_VgaStatus)))
#define VgaInterruptMask (*((volatile Word *) SA1101_p2v (_VgaInterruptMask)))
#define VgaPalette (*((volatile Word *) SA1101_p2v (_VgaPalette)))
-#define DacControl (*((volatile Word *) SA1101_p2v (_DacControl))
+#define DacControl (*((volatile Word *) SA1101_p2v (_DacControl)))
#define VgaTest (*((volatile Word *) SA1101_p2v (_VgaTest)))
#define VideoControl_VgaEn 0x00000000
diff --git a/include/asm-arm/bitops.h b/include/asm-arm/bitops.h
index b41831b6432f..47a6b086eee2 100644
--- a/include/asm-arm/bitops.h
+++ b/include/asm-arm/bitops.h
@@ -19,6 +19,10 @@
#ifdef __KERNEL__
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
#include <linux/compiler.h>
#include <asm/system.h>
@@ -286,6 +290,7 @@ static inline int constant_fls(int x)
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/lock.h>
/*
* Ext2 is defined to use little-endian byte ordering.
diff --git a/include/asm-arm/dma-mapping.h b/include/asm-arm/dma-mapping.h
index c8b5d0db0cf0..e99406a7bece 100644
--- a/include/asm-arm/dma-mapping.h
+++ b/include/asm-arm/dma-mapping.h
@@ -5,7 +5,7 @@
#include <linux/mm.h> /* need struct page */
-#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
/*
* DMA-consistent mapping functions. These allocate/free a region of
@@ -17,7 +17,7 @@
* platforms with CONFIG_DMABOUNCE.
* Use the driver DMA support - see dma-mapping.h (dma_sync_*)
*/
-extern void consistent_sync(const void *kaddr, size_t size, int rw);
+extern void dma_cache_maint(const void *kaddr, size_t size, int rw);
/*
* Return whether the given device DMA address mask can be supported
@@ -165,7 +165,7 @@ dma_map_single(struct device *dev, void *cpu_addr, size_t size,
enum dma_data_direction dir)
{
if (!arch_is_coherent())
- consistent_sync(cpu_addr, size, dir);
+ dma_cache_maint(cpu_addr, size, dir);
return virt_to_dma(dev, (unsigned long)cpu_addr);
}
@@ -274,11 +274,11 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
for (i = 0; i < nents; i++, sg++) {
char *virt;
- sg->dma_address = page_to_dma(dev, sg->page) + sg->offset;
- virt = page_address(sg->page) + sg->offset;
+ sg->dma_address = page_to_dma(dev, sg_page(sg)) + sg->offset;
+ virt = sg_virt(sg);
if (!arch_is_coherent())
- consistent_sync(virt, sg->length, dir);
+ dma_cache_maint(virt, sg->length, dir);
}
return nents;
@@ -334,7 +334,7 @@ dma_sync_single_for_cpu(struct device *dev, dma_addr_t handle, size_t size,
enum dma_data_direction dir)
{
if (!arch_is_coherent())
- consistent_sync((void *)dma_to_virt(dev, handle), size, dir);
+ dma_cache_maint((void *)dma_to_virt(dev, handle), size, dir);
}
static inline void
@@ -342,7 +342,7 @@ dma_sync_single_for_device(struct device *dev, dma_addr_t handle, size_t size,
enum dma_data_direction dir)
{
if (!arch_is_coherent())
- consistent_sync((void *)dma_to_virt(dev, handle), size, dir);
+ dma_cache_maint((void *)dma_to_virt(dev, handle), size, dir);
}
#else
extern void dma_sync_single_for_cpu(struct device*, dma_addr_t, size_t, enum dma_data_direction);
@@ -371,9 +371,9 @@ dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nents,
int i;
for (i = 0; i < nents; i++, sg++) {
- char *virt = page_address(sg->page) + sg->offset;
+ char *virt = sg_virt(sg);
if (!arch_is_coherent())
- consistent_sync(virt, sg->length, dir);
+ dma_cache_maint(virt, sg->length, dir);
}
}
@@ -384,9 +384,9 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents,
int i;
for (i = 0; i < nents; i++, sg++) {
- char *virt = page_address(sg->page) + sg->offset;
+ char *virt = sg_virt(sg);
if (!arch_is_coherent())
- consistent_sync(virt, sg->length, dir);
+ dma_cache_maint(virt, sg->length, dir);
}
}
#else
@@ -401,7 +401,7 @@ extern void dma_sync_sg_for_device(struct device*, struct scatterlist*, int, enu
*
* On the SA-1111, a bug limits DMA to only certain regions of RAM.
* On the IXP425, the PCI inbound window is 64MB (256MB total RAM)
- * On some ADI engineering sytems, PCI inbound window is 32MB (12MB total RAM)
+ * On some ADI engineering systems, PCI inbound window is 32MB (12MB total RAM)
*
* The following are helper functions used by the dmabounce subystem
*
diff --git a/include/asm-arm/flat.h b/include/asm-arm/flat.h
index 16f5375e57b8..9918aa46d9e5 100644
--- a/include/asm-arm/flat.h
+++ b/include/asm-arm/flat.h
@@ -11,8 +11,9 @@
#define flat_argvp_envp_on_stack() 1
#define flat_old_ram_flag(flags) (flags)
#define flat_reloc_valid(reloc, size) ((reloc) <= (size))
-#define flat_get_addr_from_rp(rp, relval, flags) get_unaligned(rp)
+#define flat_get_addr_from_rp(rp, relval, flags, persistent) get_unaligned(rp)
#define flat_put_addr_at_rp(rp, val, relval) put_unaligned(val,rp)
#define flat_get_relocate_addr(rel) (rel)
+#define flat_set_persistent(relval, p) 0
#endif /* __ARM_FLAT_H__ */
diff --git a/include/asm-arm/floppy.h b/include/asm-arm/floppy.h
index d595c15166a4..41a5e9d6bb69 100644
--- a/include/asm-arm/floppy.h
+++ b/include/asm-arm/floppy.h
@@ -128,8 +128,6 @@ static inline void fd_scandrives (void)
#define N_FDC 1
#define N_DRIVE 4
-#define FLOPPY_MOTOR_MASK 0xf0
-
#define CROSS_64KB(a,s) (0)
/*
diff --git a/include/asm-arm/hardware/iop3xx.h b/include/asm-arm/hardware/iop3xx.h
index fb90b421f31c..ede377ec9147 100644
--- a/include/asm-arm/hardware/iop3xx.h
+++ b/include/asm-arm/hardware/iop3xx.h
@@ -231,7 +231,7 @@ extern int init_atu;
IOP3XX_PCI_IO_WINDOW_SIZE - 1)
#define IOP3XX_PCI_UPPER_IO_VA (IOP3XX_PCI_LOWER_IO_VA +\
IOP3XX_PCI_IO_WINDOW_SIZE - 1)
-#define IOP3XX_PCI_IO_PHYS_TO_VIRT(addr) (((u32) addr -\
+#define IOP3XX_PCI_IO_PHYS_TO_VIRT(addr) (((u32) (addr) -\
IOP3XX_PCI_LOWER_IO_PA) +\
IOP3XX_PCI_LOWER_IO_VA)
diff --git a/include/asm-arm/hardware/it8152.h b/include/asm-arm/hardware/it8152.h
new file mode 100644
index 000000000000..aaebb61aca48
--- /dev/null
+++ b/include/asm-arm/hardware/it8152.h
@@ -0,0 +1,99 @@
+/*
+ * linux/include/arm/hardware/it8152.h
+ *
+ * Copyright Compulab Ltd., 2006,2007
+ * Mike Rapoport <mike@compulab.co.il>
+ *
+ * ITE 8152 companion chip register definitions
+ */
+
+#ifndef __ASM_HARDWARE_IT8152_H
+#define __ASM_HARDWARE_IT8152_H
+extern unsigned long it8152_base_address;
+
+#define IT8152_IO_BASE (it8152_base_address + 0x03e00000)
+#define IT8152_CFGREG_BASE (it8152_base_address + 0x03f00000)
+
+#define __REG_IT8152(x) (it8152_base_address + (x))
+
+#define IT8152_PCI_CFG_ADDR __REG_IT8152(0x3f00800)
+#define IT8152_PCI_CFG_DATA __REG_IT8152(0x3f00804)
+
+#define IT8152_INTC_LDCNIRR __REG_IT8152(0x3f00300)
+#define IT8152_INTC_LDPNIRR __REG_IT8152(0x3f00304)
+#define IT8152_INTC_LDCNIMR __REG_IT8152(0x3f00308)
+#define IT8152_INTC_LDPNIMR __REG_IT8152(0x3f0030C)
+#define IT8152_INTC_LDNITR __REG_IT8152(0x3f00310)
+#define IT8152_INTC_LDNIAR __REG_IT8152(0x3f00314)
+#define IT8152_INTC_LPCNIRR __REG_IT8152(0x3f00320)
+#define IT8152_INTC_LPPNIRR __REG_IT8152(0x3f00324)
+#define IT8152_INTC_LPCNIMR __REG_IT8152(0x3f00328)
+#define IT8152_INTC_LPPNIMR __REG_IT8152(0x3f0032C)
+#define IT8152_INTC_LPNITR __REG_IT8152(0x3f00330)
+#define IT8152_INTC_LPNIAR __REG_IT8152(0x3f00334)
+#define IT8152_INTC_PDCNIRR __REG_IT8152(0x3f00340)
+#define IT8152_INTC_PDPNIRR __REG_IT8152(0x3f00344)
+#define IT8152_INTC_PDCNIMR __REG_IT8152(0x3f00348)
+#define IT8152_INTC_PDPNIMR __REG_IT8152(0x3f0034C)
+#define IT8152_INTC_PDNITR __REG_IT8152(0x3f00350)
+#define IT8152_INTC_PDNIAR __REG_IT8152(0x3f00354)
+#define IT8152_INTC_INTC_TYPER __REG_IT8152(0x3f003FC)
+
+#define IT8152_GPIO_GPDR __REG_IT8152(0x3f00500)
+
+/*
+ Interrup contoler per register summary:
+ ---------------------------------------
+ LCDNIRR:
+ IT8152_LD_IRQ(8) PCICLK stop
+ IT8152_LD_IRQ(7) MCLK ready
+ IT8152_LD_IRQ(6) s/w
+ IT8152_LD_IRQ(5) UART
+ IT8152_LD_IRQ(4) GPIO
+ IT8152_LD_IRQ(3) TIMER 4
+ IT8152_LD_IRQ(2) TIMER 3
+ IT8152_LD_IRQ(1) TIMER 2
+ IT8152_LD_IRQ(0) TIMER 1
+
+ LPCNIRR:
+ IT8152_LP_IRQ(x) serial IRQ x
+
+ PCIDNIRR:
+ IT8152_PD_IRQ(14) PCISERR
+ IT8152_PD_IRQ(13) CPU/PCI bridge target abort (h2pTADR)
+ IT8152_PD_IRQ(12) CPU/PCI bridge master abort (h2pMADR)
+ IT8152_PD_IRQ(11) PCI INTD
+ IT8152_PD_IRQ(10) PCI INTC
+ IT8152_PD_IRQ(9) PCI INTB
+ IT8152_PD_IRQ(8) PCI INTA
+ IT8152_PD_IRQ(7) serial INTD
+ IT8152_PD_IRQ(6) serial INTC
+ IT8152_PD_IRQ(5) serial INTB
+ IT8152_PD_IRQ(4) serial INTA
+ IT8152_PD_IRQ(3) serial IRQ IOCHK (IOCHKR)
+ IT8152_PD_IRQ(2) chaining DMA (CDMAR)
+ IT8152_PD_IRQ(1) USB (USBR)
+ IT8152_PD_IRQ(0) Audio controller (ACR)
+ */
+/* frequently used interrupts */
+#define IT8152_PCISERR IT8152_PD_IRQ(14)
+#define IT8152_H2PTADR IT8152_PD_IRQ(13)
+#define IT8152_H2PMAR IT8152_PD_IRQ(12)
+#define IT8152_PCI_INTD IT8152_PD_IRQ(11)
+#define IT8152_PCI_INTC IT8152_PD_IRQ(10)
+#define IT8152_PCI_INTB IT8152_PD_IRQ(9)
+#define IT8152_PCI_INTA IT8152_PD_IRQ(8)
+#define IT8152_CDMA_INT IT8152_PD_IRQ(2)
+#define IT8152_USB_INT IT8152_PD_IRQ(1)
+#define IT8152_AUDIO_INT IT8152_PD_IRQ(0)
+
+struct pci_dev;
+struct pci_sys_data;
+
+extern void it8152_irq_demux(unsigned int irq, struct irq_desc *desc);
+extern void it8152_init_irq(void);
+extern int it8152_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin);
+extern int it8152_pci_setup(int nr, struct pci_sys_data *sys);
+extern struct pci_bus *it8152_pci_scan_bus(int nr, struct pci_sys_data *sys);
+
+#endif /* __ASM_HARDWARE_IT8152_H */
diff --git a/include/asm-arm/ide.h b/include/asm-arm/ide.h
index 4f68c8a5a199..f348fcf3150b 100644
--- a/include/asm-arm/ide.h
+++ b/include/asm-arm/ide.h
@@ -18,7 +18,6 @@
#endif
#if !defined(CONFIG_ARCH_L7200)
-# define IDE_ARCH_OBSOLETE_INIT
# ifdef CONFIG_ARCH_CLPS7500
# define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */
# else
diff --git a/include/asm-arm/ipc.h b/include/asm-arm/ipc.h
deleted file mode 100644
index a46e3d9c2a3f..000000000000
--- a/include/asm-arm/ipc.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ipc.h>
diff --git a/include/asm-arm/kexec.h b/include/asm-arm/kexec.h
index b5b030ef633d..46dcc4d0b9bd 100644
--- a/include/asm-arm/kexec.h
+++ b/include/asm-arm/kexec.h
@@ -14,6 +14,8 @@
#define KEXEC_ARCH KEXEC_ARCH_ARM
+#define KEXEC_BOOT_PARAMS_SIZE 1536
+
#ifndef __ASSEMBLY__
struct kimage;
diff --git a/include/asm-arm/pci.h b/include/asm-arm/pci.h
index ed3f898191f4..75feb1574a69 100644
--- a/include/asm-arm/pci.h
+++ b/include/asm-arm/pci.h
@@ -8,10 +8,17 @@
#define pcibios_scan_all_fns(a, b) 0
+#ifdef CONFIG_PCI_HOST_ITE8152
+/* ITE bridge requires setting latency timer to avoid early bus access
+ termination by PIC bus mater devices
+*/
+extern void pcibios_set_master(struct pci_dev *dev);
+#else
static inline void pcibios_set_master(struct pci_dev *dev)
{
/* No special bus mastering setup handling */
}
+#endif
static inline void pcibios_penalize_isa_irq(int irq, int active)
{
diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h
index d2e8171d1d4e..5e0182485d8c 100644
--- a/include/asm-arm/pgtable.h
+++ b/include/asm-arm/pgtable.h
@@ -249,7 +249,7 @@ extern struct page *empty_zero_page;
#define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext)
#define set_pte_at(mm,addr,ptep,pteval) do { \
- set_pte_ext(ptep, pteval, (addr) >= PAGE_OFFSET ? 0 : PTE_EXT_NG); \
+ set_pte_ext(ptep, pteval, (addr) >= TASK_SIZE ? 0 : PTE_EXT_NG); \
} while (0)
/*
diff --git a/include/asm-arm/plat-s3c/regs-nand.h b/include/asm-arm/plat-s3c/regs-nand.h
index b824d371ae0b..d742205ac172 100644
--- a/include/asm-arm/plat-s3c/regs-nand.h
+++ b/include/asm-arm/plat-s3c/regs-nand.h
@@ -35,7 +35,7 @@
#define S3C2440_NFESTAT1 S3C2410_NFREG(0x28)
#define S3C2440_NFMECC0 S3C2410_NFREG(0x2C)
#define S3C2440_NFMECC1 S3C2410_NFREG(0x30)
-#define S3C2440_NFSECC S3C24E10_NFREG(0x34)
+#define S3C2440_NFSECC S3C2410_NFREG(0x34)
#define S3C2440_NFSBLK S3C2410_NFREG(0x38)
#define S3C2440_NFEBLK S3C2410_NFREG(0x3C)
diff --git a/include/asm-arm/scatterlist.h b/include/asm-arm/scatterlist.h
index de2f65eb42ed..ca0a37d03400 100644
--- a/include/asm-arm/scatterlist.h
+++ b/include/asm-arm/scatterlist.h
@@ -5,7 +5,10 @@
#include <asm/types.h>
struct scatterlist {
- struct page *page; /* buffer page */
+#ifdef CONFIG_DEBUG_SG
+ unsigned long sg_magic;
+#endif
+ unsigned long page_link;
unsigned int offset; /* buffer offset */
dma_addr_t dma_address; /* dma address */
unsigned int length; /* length */
diff --git a/include/asm-arm/semaphore.h b/include/asm-arm/semaphore.h
index d5dc624f452a..1c8b441f89e3 100644
--- a/include/asm-arm/semaphore.h
+++ b/include/asm-arm/semaphore.h
@@ -28,7 +28,6 @@ struct semaphore {
struct semaphore name = __SEMAPHORE_INIT(name,count)
#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
-#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
static inline void sema_init(struct semaphore *sem, int val)
{
diff --git a/include/asm-arm/tlbflush.h b/include/asm-arm/tlbflush.h
index 71be4fded7e2..8c6bc1bb9d1a 100644
--- a/include/asm-arm/tlbflush.h
+++ b/include/asm-arm/tlbflush.h
@@ -463,11 +463,6 @@ extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
*/
extern void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte);
-/*
- * ARM processors do not cache TLB tables in RAM.
- */
-#define flush_tlb_pgtables(mm,start,end) do { } while (0)
-
#endif
#endif /* CONFIG_MMU */
diff --git a/include/asm-arm/types.h b/include/asm-arm/types.h
index 22992ee0627a..3141451a9bd6 100644
--- a/include/asm-arm/types.h
+++ b/include/asm-arm/types.h
@@ -19,9 +19,9 @@ typedef unsigned short __u16;
typedef __signed__ int __s32;
typedef unsigned int __u32;
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
-typedef __signed__ long long __s64;
-typedef unsigned long long __u64;
+#if defined(__GNUC__)
+__extension__ typedef __signed__ long long __s64;
+__extension__ typedef unsigned long long __u64;
#endif
#endif /* __ASSEMBLY__ */
diff --git a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h
index d327b25c986c..88e868b7aae0 100644
--- a/include/asm-arm/unistd.h
+++ b/include/asm-arm/unistd.h
@@ -378,6 +378,7 @@
#define __NR_signalfd (__NR_SYSCALL_BASE+349)
#define __NR_timerfd (__NR_SYSCALL_BASE+350)
#define __NR_eventfd (__NR_SYSCALL_BASE+351)
+#define __NR_fallocate (__NR_SYSCALL_BASE+352)
/*
* The following SWIs are ARM private.
diff --git a/include/asm-avr32/arch-at32ap/board.h b/include/asm-avr32/arch-at32ap/board.h
index 7dbd603c38cc..d6993a6b6473 100644
--- a/include/asm-avr32/arch-at32ap/board.h
+++ b/include/asm-avr32/arch-at32ap/board.h
@@ -44,6 +44,13 @@ struct usba_platform_data {
struct platform_device *
at32_add_device_usba(unsigned int id, struct usba_platform_data *data);
+struct ide_platform_data {
+ u8 cs;
+};
+struct platform_device *
+at32_add_device_ide(unsigned int id, unsigned int extint,
+ struct ide_platform_data *data);
+
/* depending on what's hooked up, not all SSC pins will be used */
#define ATMEL_SSC_TK 0x01
#define ATMEL_SSC_TF 0x02
@@ -58,4 +65,20 @@ at32_add_device_usba(unsigned int id, struct usba_platform_data *data);
struct platform_device *
at32_add_device_ssc(unsigned int id, unsigned int flags);
+struct platform_device *at32_add_device_twi(unsigned int id);
+struct platform_device *at32_add_device_mci(unsigned int id);
+struct platform_device *at32_add_device_ac97c(unsigned int id);
+struct platform_device *at32_add_device_abdac(unsigned int id);
+
+struct cf_platform_data {
+ int detect_pin;
+ int reset_pin;
+ int vcc_pin;
+ int ready_pin;
+ u8 cs;
+};
+struct platform_device *
+at32_add_device_cf(unsigned int id, unsigned int extint,
+ struct cf_platform_data *data);
+
#endif /* __ASM_ARCH_BOARD_H */
diff --git a/include/asm-avr32/bitops.h b/include/asm-avr32/bitops.h
index 5299f8c8e11d..1a50b69b1a19 100644
--- a/include/asm-avr32/bitops.h
+++ b/include/asm-avr32/bitops.h
@@ -8,6 +8,10 @@
#ifndef __ASM_AVR32_BITOPS_H
#define __ASM_AVR32_BITOPS_H
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
#include <asm/byteorder.h>
#include <asm/system.h>
@@ -288,6 +292,7 @@ static inline int ffs(unsigned long word)
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/lock.h>
#include <asm-generic/bitops/ext2-non-atomic.h>
#include <asm-generic/bitops/ext2-atomic.h>
diff --git a/include/asm-avr32/dma-mapping.h b/include/asm-avr32/dma-mapping.h
index 81e342636ac4..57dc672bab8e 100644
--- a/include/asm-avr32/dma-mapping.h
+++ b/include/asm-avr32/dma-mapping.h
@@ -3,7 +3,7 @@
#include <linux/mm.h>
#include <linux/device.h>
-#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
#include <asm/processor.h>
#include <asm/cacheflush.h>
#include <asm/io.h>
@@ -217,8 +217,8 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
for (i = 0; i < nents; i++) {
char *virt;
- sg[i].dma_address = page_to_bus(sg[i].page) + sg[i].offset;
- virt = page_address(sg[i].page) + sg[i].offset;
+ sg[i].dma_address = page_to_bus(sg_page(&sg[i])) + sg[i].offset;
+ virt = sg_virt(&sg[i]);
dma_cache_sync(dev, virt, sg[i].length, direction);
}
@@ -327,8 +327,7 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
int i;
for (i = 0; i < nents; i++) {
- dma_cache_sync(dev, page_address(sg[i].page) + sg[i].offset,
- sg[i].length, direction);
+ dma_cache_sync(dev, sg_virt(&sg[i]), sg[i].length, direction);
}
}
diff --git a/include/asm-avr32/io.h b/include/asm-avr32/io.h
index 64bb92bb6773..8be7ea9c9047 100644
--- a/include/asm-avr32/io.h
+++ b/include/asm-avr32/io.h
@@ -298,13 +298,6 @@ extern void __iounmap(void __iomem *addr);
#define ioport_map(port, nr) ioremap(port, nr)
#define ioport_unmap(port) iounmap(port)
-#define dma_cache_wback_inv(_start, _size) \
- flush_dcache_region(_start, _size)
-#define dma_cache_inv(_start, _size) \
- invalidate_dcache_region(_start, _size)
-#define dma_cache_wback(_start, _size) \
- clean_dcache_region(_start, _size)
-
/*
* Convert a physical pointer to a virtual kernel pointer for /dev/mem
* access
diff --git a/include/asm-avr32/kdebug.h b/include/asm-avr32/kdebug.h
index 7f54e2b15d13..fd7e99046b2f 100644
--- a/include/asm-avr32/kdebug.h
+++ b/include/asm-avr32/kdebug.h
@@ -1,26 +1,10 @@
#ifndef __ASM_AVR32_KDEBUG_H
#define __ASM_AVR32_KDEBUG_H
-#include <linux/notifier.h>
-
/* Grossly misnamed. */
enum die_val {
DIE_BREAKPOINT,
DIE_SSTEP,
};
-/*
- * These are only here because kprobes.c wants them to implement a
- * blatant layering violation. Will hopefully go away soon once all
- * architectures are updated.
- */
-static inline int register_page_fault_notifier(struct notifier_block *nb)
-{
- return 0;
-}
-static inline int unregister_page_fault_notifier(struct notifier_block *nb)
-{
- return 0;
-}
-
#endif /* __ASM_AVR32_KDEBUG_H */
diff --git a/include/asm-avr32/kprobes.h b/include/asm-avr32/kprobes.h
index 190a6377c809..996cb656474e 100644
--- a/include/asm-avr32/kprobes.h
+++ b/include/asm-avr32/kprobes.h
@@ -17,7 +17,7 @@ typedef u16 kprobe_opcode_t;
#define BREAKPOINT_INSTRUCTION 0xd673 /* breakpoint */
#define MAX_INSN_SIZE 2
-#define ARCH_INACTIVE_KPROBE_COUNT 1
+#define kretprobe_blacklist_size 0
#define arch_remove_kprobe(p) do { } while (0)
diff --git a/include/asm-avr32/scatterlist.h b/include/asm-avr32/scatterlist.h
index c6d5ce3b3a25..377320e3bd17 100644
--- a/include/asm-avr32/scatterlist.h
+++ b/include/asm-avr32/scatterlist.h
@@ -4,7 +4,10 @@
#include <asm/types.h>
struct scatterlist {
- struct page *page;
+#ifdef CONFIG_DEBUG_SG
+ unsigned long sg_magic;
+#endif
+ unsigned long page_link;
unsigned int offset;
dma_addr_t dma_address;
unsigned int length;
diff --git a/include/asm-avr32/semaphore.h b/include/asm-avr32/semaphore.h
index ef99ddccc10c..feaf1d453386 100644
--- a/include/asm-avr32/semaphore.h
+++ b/include/asm-avr32/semaphore.h
@@ -36,7 +36,6 @@ struct semaphore {
struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
-#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
static inline void sema_init (struct semaphore *sem, int val)
{
diff --git a/include/asm-avr32/sysreg.h b/include/asm-avr32/sysreg.h
index c02bc8304b13..dd21182b60e0 100644
--- a/include/asm-avr32/sysreg.h
+++ b/include/asm-avr32/sysreg.h
@@ -215,6 +215,8 @@
#define SYSREG_IRP_SIZE 6
/* Bitfields in PCCR */
+#define SYSREG_PCCR_E_OFFSET 0
+#define SYSREG_PCCR_E_SIZE 1
#define SYSREG_PCCR_R_OFFSET 1
#define SYSREG_PCCR_R_SIZE 1
#define SYSREG_PCCR_C_OFFSET 2
diff --git a/include/asm-avr32/tlbflush.h b/include/asm-avr32/tlbflush.h
index 730e268f81f3..5bc7c88a5770 100644
--- a/include/asm-avr32/tlbflush.h
+++ b/include/asm-avr32/tlbflush.h
@@ -19,7 +19,6 @@
* - flush_tlb_page(vma, vmaddr) flushes one page
* - flush_tlb_range(vma, start, end) flushes a range of pages
* - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
- * - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
*/
extern void flush_tlb(void);
extern void flush_tlb_all(void);
@@ -29,12 +28,6 @@ extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long page);
extern void __flush_tlb_page(unsigned long asid, unsigned long page);
-static inline void flush_tlb_pgtables(struct mm_struct *mm,
- unsigned long start, unsigned long end)
-{
- /* Nothing to do */
-}
-
extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
#endif /* __ASM_AVR32_TLBFLUSH_H */
diff --git a/include/asm-avr32/types.h b/include/asm-avr32/types.h
index 2bff153a32ed..8999a3819403 100644
--- a/include/asm-avr32/types.h
+++ b/include/asm-avr32/types.h
@@ -25,9 +25,9 @@ typedef unsigned short __u16;
typedef __signed__ int __s32;
typedef unsigned int __u32;
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
-typedef __signed__ long long __s64;
-typedef unsigned long long __u64;
+#if defined(__GNUC__)
+__extension__ typedef __signed__ long long __s64;
+__extension__ typedef unsigned long long __u64;
#endif
#endif /* __ASSEMBLY__ */
diff --git a/include/asm-blackfin/bf5xx_timers.h b/include/asm-blackfin/bf5xx_timers.h
deleted file mode 100644
index 86c770321b61..000000000000
--- a/include/asm-blackfin/bf5xx_timers.h
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * include/asm/bf5xx_timers.h
- *
- * This file contains the major Data structures and constants
- * used for General Purpose Timer Implementation in BF5xx
- *
- * Copyright (C) 2005 John DeHority
- * Copyright (C) 2006 Hella Aglaia GmbH (awe@aglaia-gmbh.de)
- *
- */
-
-#ifndef _BLACKFIN_TIMERS_H_
-#define _BLACKFIN_TIMERS_H_
-
-#undef MAX_BLACKFIN_GPTIMERS
-/*
- * BF537: 8 timers:
- */
-#if defined(CONFIG_BF537)
-# define MAX_BLACKFIN_GPTIMERS 8
-# define TIMER0_GROUP_REG TIMER_ENABLE
-#endif
-/*
- * BF561: 12 timers:
- */
-#if defined(CONFIG_BF561)
-# define MAX_BLACKFIN_GPTIMERS 12
-# define TIMER0_GROUP_REG TMRS8_ENABLE
-# define TIMER8_GROUP_REG TMRS4_ENABLE
-#endif
-/*
- * All others: 3 timers:
- */
-#if !defined(MAX_BLACKFIN_GPTIMERS)
-# define MAX_BLACKFIN_GPTIMERS 3
-# define TIMER0_GROUP_REG TIMER_ENABLE
-#endif
-
-#define BLACKFIN_GPTIMER_IDMASK ((1UL << MAX_BLACKFIN_GPTIMERS) - 1)
-#define BFIN_TIMER_OCTET(x) ((x) >> 3)
-
-/* used in masks for timer_enable() and timer_disable() */
-#define TIMER0bit 0x0001 /* 0001b */
-#define TIMER1bit 0x0002 /* 0010b */
-#define TIMER2bit 0x0004 /* 0100b */
-
-#if (MAX_BLACKFIN_GPTIMERS > 3)
-# define TIMER3bit 0x0008
-# define TIMER4bit 0x0010
-# define TIMER5bit 0x0020
-# define TIMER6bit 0x0040
-# define TIMER7bit 0x0080
-#endif
-
-#if (MAX_BLACKFIN_GPTIMERS > 8)
-# define TIMER8bit 0x0100
-# define TIMER9bit 0x0200
-# define TIMER10bit 0x0400
-# define TIMER11bit 0x0800
-#endif
-
-#define TIMER0_id 0
-#define TIMER1_id 1
-#define TIMER2_id 2
-
-#if (MAX_BLACKFIN_GPTIMERS > 3)
-# define TIMER3_id 3
-# define TIMER4_id 4
-# define TIMER5_id 5
-# define TIMER6_id 6
-# define TIMER7_id 7
-#endif
-
-#if (MAX_BLACKFIN_GPTIMERS > 8)
-# define TIMER8_id 8
-# define TIMER9_id 9
-# define TIMER10_id 10
-# define TIMER11_id 11
-#endif
-
-/* associated timers for ppi framesync: */
-
-#if defined(CONFIG_BF561)
-# define FS0_1_TIMER_ID TIMER8_id
-# define FS0_2_TIMER_ID TIMER9_id
-# define FS1_1_TIMER_ID TIMER10_id
-# define FS1_2_TIMER_ID TIMER11_id
-# define FS0_1_TIMER_BIT TIMER8bit
-# define FS0_2_TIMER_BIT TIMER9bit
-# define FS1_1_TIMER_BIT TIMER10bit
-# define FS1_2_TIMER_BIT TIMER11bit
-# undef FS1_TIMER_ID
-# undef FS2_TIMER_ID
-# undef FS1_TIMER_BIT
-# undef FS2_TIMER_BIT
-#else
-# define FS1_TIMER_ID TIMER0_id
-# define FS2_TIMER_ID TIMER1_id
-# define FS1_TIMER_BIT TIMER0bit
-# define FS2_TIMER_BIT TIMER1bit
-#endif
-
-/*
-** Timer Configuration Register Bits
-*/
-#define TIMER_ERR 0xC000
-#define TIMER_ERR_OVFL 0x4000
-#define TIMER_ERR_PROG_PER 0x8000
-#define TIMER_ERR_PROG_PW 0xC000
-#define TIMER_EMU_RUN 0x0200
-#define TIMER_TOGGLE_HI 0x0100
-#define TIMER_CLK_SEL 0x0080
-#define TIMER_OUT_DIS 0x0040
-#define TIMER_TIN_SEL 0x0020
-#define TIMER_IRQ_ENA 0x0010
-#define TIMER_PERIOD_CNT 0x0008
-#define TIMER_PULSE_HI 0x0004
-#define TIMER_MODE 0x0003
-#define TIMER_MODE_PWM 0x0001
-#define TIMER_MODE_WDTH 0x0002
-#define TIMER_MODE_EXT_CLK 0x0003
-
-/*
-** Timer Status Register Bits
-*/
-#define TIMER_STATUS_TIMIL0 0x0001
-#define TIMER_STATUS_TIMIL1 0x0002
-#define TIMER_STATUS_TIMIL2 0x0004
-#if (MAX_BLACKFIN_GPTIMERS > 3)
-# define TIMER_STATUS_TIMIL3 0x00000008
-# define TIMER_STATUS_TIMIL4 0x00010000
-# define TIMER_STATUS_TIMIL5 0x00020000
-# define TIMER_STATUS_TIMIL6 0x00040000
-# define TIMER_STATUS_TIMIL7 0x00080000
-# if (MAX_BLACKFIN_GPTIMERS > 8)
-# define TIMER_STATUS_TIMIL8 0x0001
-# define TIMER_STATUS_TIMIL9 0x0002
-# define TIMER_STATUS_TIMIL10 0x0004
-# define TIMER_STATUS_TIMIL11 0x0008
-# endif
-# define TIMER_STATUS_INTR 0x000F000F
-#else
-# define TIMER_STATUS_INTR 0x0007 /* any timer interrupt */
-#endif
-
-#define TIMER_STATUS_TOVF0 0x0010 /* timer 0 overflow error */
-#define TIMER_STATUS_TOVF1 0x0020
-#define TIMER_STATUS_TOVF2 0x0040
-#if (MAX_BLACKFIN_GPTIMERS > 3)
-# define TIMER_STATUS_TOVF3 0x00000080
-# define TIMER_STATUS_TOVF4 0x00100000
-# define TIMER_STATUS_TOVF5 0x00200000
-# define TIMER_STATUS_TOVF6 0x00400000
-# define TIMER_STATUS_TOVF7 0x00800000
-# if (MAX_BLACKFIN_GPTIMERS > 8)
-# define TIMER_STATUS_TOVF8 0x0010
-# define TIMER_STATUS_TOVF9 0x0020
-# define TIMER_STATUS_TOVF10 0x0040
-# define TIMER_STATUS_TOVF11 0x0080
-# endif
-# define TIMER_STATUS_OFLOW 0x00F000F0
-#else
-# define TIMER_STATUS_OFLOW 0x0070 /* any timer overflow */
-#endif
-
-/*
-** Timer Slave Enable Status : write 1 to clear
-*/
-#define TIMER_STATUS_TRUN0 0x1000
-#define TIMER_STATUS_TRUN1 0x2000
-#define TIMER_STATUS_TRUN2 0x4000
-#if (MAX_BLACKFIN_GPTIMERS > 3)
-# define TIMER_STATUS_TRUN3 0x00008000
-# define TIMER_STATUS_TRUN4 0x10000000
-# define TIMER_STATUS_TRUN5 0x20000000
-# define TIMER_STATUS_TRUN6 0x40000000
-# define TIMER_STATUS_TRUN7 0x80000000
-# define TIMER_STATUS_TRUN 0xF000F000
-# if (MAX_BLACKFIN_GPTIMERS > 8)
-# define TIMER_STATUS_TRUN8 0x1000
-# define TIMER_STATUS_TRUN9 0x2000
-# define TIMER_STATUS_TRUN10 0x4000
-# define TIMER_STATUS_TRUN11 0x8000
-# endif
-#else
-# define TIMER_STATUS_TRUN 0x7000
-#endif
-
-/*******************************************************************************
-* GP_TIMER API's
-*******************************************************************************/
-
-void set_gptimer_pwidth (int timer_id, int width);
-int get_gptimer_pwidth (int timer_id);
-void set_gptimer_period (int timer_id, int period);
-int get_gptimer_period (int timer_id);
-int get_gptimer_count (int timer_id);
-short get_gptimer_intr (int timer_id);
-void set_gptimer_config (int timer_id, short config);
-short get_gptimer_config (int timer_id);
-void set_gptimer_pulse_hi (int timer_id);
-void clear_gptimer_pulse_hi(int timer_id);
-void enable_gptimers (short mask);
-void disable_gptimers (short mask);
-short get_enabled_timers (void);
-int get_gptimer_status (int octet);
-void set_gptimer_status (int octet, int value);
-
-#endif
diff --git a/include/asm-blackfin/bfin-global.h b/include/asm-blackfin/bfin-global.h
index a970781a0f98..0212e180b90e 100644
--- a/include/asm-blackfin/bfin-global.h
+++ b/include/asm-blackfin/bfin-global.h
@@ -47,6 +47,8 @@
extern unsigned long get_cclk(void);
extern unsigned long get_sclk(void);
+extern unsigned long sclk_to_usecs(unsigned long sclk);
+extern unsigned long usecs_to_sclk(unsigned long usecs);
extern void dump_thread(struct pt_regs *regs, struct user *dump);
extern void dump_bfin_regs(struct pt_regs *fp, void *retaddr);
@@ -78,6 +80,7 @@ extern int atomic_sub32(void);
extern int atomic_ior32(void);
extern int atomic_and32(void);
extern int atomic_xor32(void);
+extern void safe_user_instruction(void);
extern void sigreturn_stub(void);
extern void *l1_data_A_sram_alloc(size_t);
@@ -105,7 +108,7 @@ extern void led_disp_num(int);
extern void led_toggle_num(int);
extern void init_leds(void);
-extern char *bfin_board_name __attribute__ ((weak));
+extern const char bfin_board_name[];
extern unsigned long wall_jiffies;
extern unsigned long ipdt_table[];
extern unsigned long dpdt_table[];
diff --git a/include/asm-blackfin/bitops.h b/include/asm-blackfin/bitops.h
index 27c2d0e48e1b..b39a175c79c1 100644
--- a/include/asm-blackfin/bitops.h
+++ b/include/asm-blackfin/bitops.h
@@ -11,6 +11,10 @@
#ifdef __KERNEL__
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
#include <asm-generic/bitops/ffs.h>
#include <asm-generic/bitops/__ffs.h>
#include <asm-generic/bitops/sched.h>
@@ -199,6 +203,7 @@ static __inline__ int __test_bit(int nr, const void *addr)
#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/lock.h>
#include <asm-generic/bitops/ext2-atomic.h>
#include <asm-generic/bitops/ext2-non-atomic.h>
diff --git a/include/asm-blackfin/dma.h b/include/asm-blackfin/dma.h
index b42a531e7a1b..b469505af364 100644
--- a/include/asm-blackfin/dma.h
+++ b/include/asm-blackfin/dma.h
@@ -109,9 +109,7 @@ struct dma_register {
unsigned long curr_desc_ptr; /* DMA Current Descriptor Pointer
register */
- unsigned short curr_addr_ptr_lo; /* DMA Current Address Pointer
- register */
- unsigned short curr_addr_ptr_hi; /* DMA Current Address Pointer
+ unsigned long curr_addr_ptr; /* DMA Current Address Pointer
register */
unsigned short irq_status; /* DMA irq status register */
unsigned short dummy6;
@@ -166,6 +164,9 @@ void set_dma_curr_addr(unsigned int channel, unsigned long addr);
unsigned short get_dma_curr_irqstat(unsigned int channel);
unsigned short get_dma_curr_xcount(unsigned int channel);
unsigned short get_dma_curr_ycount(unsigned int channel);
+unsigned long get_dma_next_desc_ptr(unsigned int channel);
+unsigned long get_dma_curr_desc_ptr(unsigned int channel);
+unsigned long get_dma_curr_addr(unsigned int channel);
/* set large DMA mode descriptor */
void set_dma_sg(unsigned int channel, struct dmasg *sg, int nr_sg);
diff --git a/include/asm-blackfin/fixed_code.h b/include/asm-blackfin/fixed_code.h
index e6df84ee1557..37db66c7030d 100644
--- a/include/asm-blackfin/fixed_code.h
+++ b/include/asm-blackfin/fixed_code.h
@@ -17,4 +17,6 @@
#define ATOMIC_SEQS_END 0x480
-#define FIXED_CODE_END 0x480
+#define SAFE_USER_INSTRUCTION 0x480
+
+#define FIXED_CODE_END 0x490
diff --git a/include/asm-blackfin/gpio.h b/include/asm-blackfin/gpio.h
index dd203cd93796..33ce98ef7e0f 100644
--- a/include/asm-blackfin/gpio.h
+++ b/include/asm-blackfin/gpio.h
@@ -29,6 +29,7 @@
/*
* Number BF537/6/4 BF561 BF533/2/1
+* BF527/5/2
*
* GPIO_0 PF0 PF0 PF0
* GPIO_1 PF1 PF1 PF1
@@ -164,7 +165,7 @@
#endif
-#ifdef BF537_FAMILY
+#if defined(BF527_FAMILY) || defined(BF537_FAMILY)
#define MAX_BLACKFIN_GPIOS 48
#define GPIO_PF0 0
diff --git a/include/asm-blackfin/gptimers.h b/include/asm-blackfin/gptimers.h
new file mode 100644
index 000000000000..8265ea473d5b
--- /dev/null
+++ b/include/asm-blackfin/gptimers.h
@@ -0,0 +1,212 @@
+/*
+ * include/asm/bf5xx_timers.h
+ *
+ * This file contains the major Data structures and constants
+ * used for General Purpose Timer Implementation in BF5xx
+ *
+ * Copyright (C) 2005 John DeHority
+ * Copyright (C) 2006 Hella Aglaia GmbH (awe@aglaia-gmbh.de)
+ *
+ */
+
+#ifndef _BLACKFIN_TIMERS_H_
+#define _BLACKFIN_TIMERS_H_
+
+#include <linux/types.h>
+#include <asm/blackfin.h>
+
+/*
+ * BF537/BF527: 8 timers:
+ */
+#if defined(BF527_FAMILY) || defined(BF537_FAMILY)
+# define MAX_BLACKFIN_GPTIMERS 8
+# define TIMER0_GROUP_REG TIMER_ENABLE
+#endif
+/*
+ * BF561: 12 timers:
+ */
+#if defined(CONFIG_BF561)
+# define MAX_BLACKFIN_GPTIMERS 12
+# define TIMER0_GROUP_REG TMRS8_ENABLE
+# define TIMER8_GROUP_REG TMRS4_ENABLE
+#endif
+/*
+ * All others: 3 timers:
+ */
+#if !defined(MAX_BLACKFIN_GPTIMERS)
+# define MAX_BLACKFIN_GPTIMERS 3
+# define TIMER0_GROUP_REG TIMER_ENABLE
+#endif
+
+#define BLACKFIN_GPTIMER_IDMASK ((1UL << MAX_BLACKFIN_GPTIMERS) - 1)
+#define BFIN_TIMER_OCTET(x) ((x) >> 3)
+
+/* used in masks for timer_enable() and timer_disable() */
+#define TIMER0bit 0x0001 /* 0001b */
+#define TIMER1bit 0x0002 /* 0010b */
+#define TIMER2bit 0x0004 /* 0100b */
+
+#if (MAX_BLACKFIN_GPTIMERS > 3)
+# define TIMER3bit 0x0008
+# define TIMER4bit 0x0010
+# define TIMER5bit 0x0020
+# define TIMER6bit 0x0040
+# define TIMER7bit 0x0080
+#endif
+
+#if (MAX_BLACKFIN_GPTIMERS > 8)
+# define TIMER8bit 0x0100
+# define TIMER9bit 0x0200
+# define TIMER10bit 0x0400
+# define TIMER11bit 0x0800
+#endif
+
+#define TIMER0_id 0
+#define TIMER1_id 1
+#define TIMER2_id 2
+
+#if (MAX_BLACKFIN_GPTIMERS > 3)
+# define TIMER3_id 3
+# define TIMER4_id 4
+# define TIMER5_id 5
+# define TIMER6_id 6
+# define TIMER7_id 7
+#endif
+
+#if (MAX_BLACKFIN_GPTIMERS > 8)
+# define TIMER8_id 8
+# define TIMER9_id 9
+# define TIMER10_id 10
+# define TIMER11_id 11
+#endif
+
+/* associated timers for ppi framesync: */
+
+#if defined(CONFIG_BF561)
+# define FS0_1_TIMER_ID TIMER8_id
+# define FS0_2_TIMER_ID TIMER9_id
+# define FS1_1_TIMER_ID TIMER10_id
+# define FS1_2_TIMER_ID TIMER11_id
+# define FS0_1_TIMER_BIT TIMER8bit
+# define FS0_2_TIMER_BIT TIMER9bit
+# define FS1_1_TIMER_BIT TIMER10bit
+# define FS1_2_TIMER_BIT TIMER11bit
+# undef FS1_TIMER_ID
+# undef FS2_TIMER_ID
+# undef FS1_TIMER_BIT
+# undef FS2_TIMER_BIT
+#else
+# define FS1_TIMER_ID TIMER0_id
+# define FS2_TIMER_ID TIMER1_id
+# define FS1_TIMER_BIT TIMER0bit
+# define FS2_TIMER_BIT TIMER1bit
+#endif
+
+/*
+ * Timer Configuration Register Bits
+ */
+#define TIMER_ERR 0xC000
+#define TIMER_ERR_OVFL 0x4000
+#define TIMER_ERR_PROG_PER 0x8000
+#define TIMER_ERR_PROG_PW 0xC000
+#define TIMER_EMU_RUN 0x0200
+#define TIMER_TOGGLE_HI 0x0100
+#define TIMER_CLK_SEL 0x0080
+#define TIMER_OUT_DIS 0x0040
+#define TIMER_TIN_SEL 0x0020
+#define TIMER_IRQ_ENA 0x0010
+#define TIMER_PERIOD_CNT 0x0008
+#define TIMER_PULSE_HI 0x0004
+#define TIMER_MODE 0x0003
+#define TIMER_MODE_PWM 0x0001
+#define TIMER_MODE_WDTH 0x0002
+#define TIMER_MODE_EXT_CLK 0x0003
+
+/*
+ * Timer Status Register Bits
+ */
+#define TIMER_STATUS_TIMIL0 0x0001
+#define TIMER_STATUS_TIMIL1 0x0002
+#define TIMER_STATUS_TIMIL2 0x0004
+#if (MAX_BLACKFIN_GPTIMERS > 3)
+# define TIMER_STATUS_TIMIL3 0x00000008
+# define TIMER_STATUS_TIMIL4 0x00010000
+# define TIMER_STATUS_TIMIL5 0x00020000
+# define TIMER_STATUS_TIMIL6 0x00040000
+# define TIMER_STATUS_TIMIL7 0x00080000
+# if (MAX_BLACKFIN_GPTIMERS > 8)
+# define TIMER_STATUS_TIMIL8 0x0001
+# define TIMER_STATUS_TIMIL9 0x0002
+# define TIMER_STATUS_TIMIL10 0x0004
+# define TIMER_STATUS_TIMIL11 0x0008
+# endif
+# define TIMER_STATUS_INTR 0x000F000F
+#else
+# define TIMER_STATUS_INTR 0x0007 /* any timer interrupt */
+#endif
+
+#define TIMER_STATUS_TOVF0 0x0010 /* timer 0 overflow error */
+#define TIMER_STATUS_TOVF1 0x0020
+#define TIMER_STATUS_TOVF2 0x0040
+#if (MAX_BLACKFIN_GPTIMERS > 3)
+# define TIMER_STATUS_TOVF3 0x00000080
+# define TIMER_STATUS_TOVF4 0x00100000
+# define TIMER_STATUS_TOVF5 0x00200000
+# define TIMER_STATUS_TOVF6 0x00400000
+# define TIMER_STATUS_TOVF7 0x00800000
+# if (MAX_BLACKFIN_GPTIMERS > 8)
+# define TIMER_STATUS_TOVF8 0x0010
+# define TIMER_STATUS_TOVF9 0x0020
+# define TIMER_STATUS_TOVF10 0x0040
+# define TIMER_STATUS_TOVF11 0x0080
+# endif
+# define TIMER_STATUS_OFLOW 0x00F000F0
+#else
+# define TIMER_STATUS_OFLOW 0x0070 /* any timer overflow */
+#endif
+
+/*
+ * Timer Slave Enable Status : write 1 to clear
+ */
+#define TIMER_STATUS_TRUN0 0x1000
+#define TIMER_STATUS_TRUN1 0x2000
+#define TIMER_STATUS_TRUN2 0x4000
+#if (MAX_BLACKFIN_GPTIMERS > 3)
+# define TIMER_STATUS_TRUN3 0x00008000
+# define TIMER_STATUS_TRUN4 0x10000000
+# define TIMER_STATUS_TRUN5 0x20000000
+# define TIMER_STATUS_TRUN6 0x40000000
+# define TIMER_STATUS_TRUN7 0x80000000
+# define TIMER_STATUS_TRUN 0xF000F000
+# if (MAX_BLACKFIN_GPTIMERS > 8)
+# define TIMER_STATUS_TRUN8 0x1000
+# define TIMER_STATUS_TRUN9 0x2000
+# define TIMER_STATUS_TRUN10 0x4000
+# define TIMER_STATUS_TRUN11 0x8000
+# endif
+#else
+# define TIMER_STATUS_TRUN 0x7000
+#endif
+
+/* The actual gptimer API */
+
+void set_gptimer_pwidth (int timer_id, uint32_t width);
+uint32_t get_gptimer_pwidth (int timer_id);
+void set_gptimer_period (int timer_id, uint32_t period);
+uint32_t get_gptimer_period (int timer_id);
+uint32_t get_gptimer_count (int timer_id);
+uint16_t get_gptimer_intr (int timer_id);
+void clear_gptimer_intr (int timer_id);
+uint16_t get_gptimer_over (int timer_id);
+void clear_gptimer_over (int timer_id);
+void set_gptimer_config (int timer_id, uint16_t config);
+uint16_t get_gptimer_config (int timer_id);
+void set_gptimer_pulse_hi (int timer_id);
+void clear_gptimer_pulse_hi(int timer_id);
+void enable_gptimers (uint16_t mask);
+void disable_gptimers (uint16_t mask);
+uint16_t get_enabled_gptimers (void);
+uint32_t get_gptimer_status (int group);
+void set_gptimer_status (int group, uint32_t value);
+
+#endif
diff --git a/include/asm-blackfin/ide.h b/include/asm-blackfin/ide.h
index 41b2db46a168..121e272581d6 100644
--- a/include/asm-blackfin/ide.h
+++ b/include/asm-blackfin/ide.h
@@ -20,7 +20,6 @@
#define MAX_HWIFS 1
/* Legacy ... BLK_DEV_IDECS */
-#define IDE_ARCH_OBSOLETE_INIT
#define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */
diff --git a/include/asm-blackfin/io.h b/include/asm-blackfin/io.h
index 525179bf43d7..d1d2e6be3b59 100644
--- a/include/asm-blackfin/io.h
+++ b/include/asm-blackfin/io.h
@@ -183,10 +183,6 @@ extern void blkfin_inv_cache_all(void);
#define ioport_map(port, nr) ((void __iomem*)(port))
#define ioport_unmap(addr)
-#define dma_cache_inv(_start,_size) do { blkfin_inv_cache_all();} while (0)
-#define dma_cache_wback(_start,_size) do { } while (0)
-#define dma_cache_wback_inv(_start,_size) do { blkfin_inv_cache_all();} while (0)
-
/* Pages to physical address... */
#define page_to_phys(page) ((page - mem_map) << PAGE_SHIFT)
#define page_to_bus(page) ((page - mem_map) << PAGE_SHIFT)
diff --git a/include/asm-blackfin/ipc.h b/include/asm-blackfin/ipc.h
deleted file mode 100644
index a46e3d9c2a3f..000000000000
--- a/include/asm-blackfin/ipc.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ipc.h>
diff --git a/include/asm-blackfin/mach-bf527/anomaly.h b/include/asm-blackfin/mach-bf527/anomaly.h
index 991db986cd4b..a89120445be6 100644
--- a/include/asm-blackfin/mach-bf527/anomaly.h
+++ b/include/asm-blackfin/mach-bf527/anomaly.h
@@ -38,4 +38,12 @@
/* Anomalies that don't exist on this proc */
#define ANOMALY_05000323 (0)
+#define ANOMALY_05000244 (0)
+#define ANOMALY_05000198 (0)
+#define ANOMALY_05000125 (0)
+#define ANOMALY_05000158 (0)
+#define ANOMALY_05000273 (0)
+#define ANOMALY_05000263 (0)
+#define ANOMALY_05000311 (0)
+#define ANOMALY_05000230 (0)
#endif
diff --git a/include/asm-blackfin/mach-bf527/bf527.h b/include/asm-blackfin/mach-bf527/bf527.h
new file mode 100644
index 000000000000..056eb4b9cd25
--- /dev/null
+++ b/include/asm-blackfin/mach-bf527/bf527.h
@@ -0,0 +1,127 @@
+/*
+ * File: include/asm-blackfin/mach-bf527/bf527.h
+ * Based on: include/asm-blackfin/mach-bf537/bf537.h
+ * Author: Michael Hennerich (michael.hennerich@analog.com)
+ *
+ * Created:
+ * Description: SYSTEM MMR REGISTER AND MEMORY MAP FOR ADSP-BF527
+ *
+ * Modified:
+ * Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __MACH_BF527_H__
+#define __MACH_BF527_H__
+
+#define SUPPORTED_REVID 2
+
+#define OFFSET_(x) ((x) & 0x0000FFFF)
+
+/*some misc defines*/
+#define IMASK_IVG15 0x8000
+#define IMASK_IVG14 0x4000
+#define IMASK_IVG13 0x2000
+#define IMASK_IVG12 0x1000
+
+#define IMASK_IVG11 0x0800
+#define IMASK_IVG10 0x0400
+#define IMASK_IVG9 0x0200
+#define IMASK_IVG8 0x0100
+
+#define IMASK_IVG7 0x0080
+#define IMASK_IVGTMR 0x0040
+#define IMASK_IVGHW 0x0020
+
+/***************************/
+
+#define BFIN_DSUBBANKS 4
+#define BFIN_DWAYS 2
+#define BFIN_DLINES 64
+#define BFIN_ISUBBANKS 4
+#define BFIN_IWAYS 4
+#define BFIN_ILINES 32
+
+#define WAY0_L 0x1
+#define WAY1_L 0x2
+#define WAY01_L 0x3
+#define WAY2_L 0x4
+#define WAY02_L 0x5
+#define WAY12_L 0x6
+#define WAY012_L 0x7
+
+#define WAY3_L 0x8
+#define WAY03_L 0x9
+#define WAY13_L 0xA
+#define WAY013_L 0xB
+
+#define WAY32_L 0xC
+#define WAY320_L 0xD
+#define WAY321_L 0xE
+#define WAYALL_L 0xF
+
+#define DMC_ENABLE (2<<2) /*yes, 2, not 1 */
+
+/********************************* EBIU Settings ************************************/
+#define AMBCTL0VAL ((CONFIG_BANK_1 << 16) | CONFIG_BANK_0)
+#define AMBCTL1VAL ((CONFIG_BANK_3 << 16) | CONFIG_BANK_2)
+
+#ifdef CONFIG_C_AMBEN_ALL
+#define V_AMBEN AMBEN_ALL
+#endif
+#ifdef CONFIG_C_AMBEN
+#define V_AMBEN 0x0
+#endif
+#ifdef CONFIG_C_AMBEN_B0
+#define V_AMBEN AMBEN_B0
+#endif
+#ifdef CONFIG_C_AMBEN_B0_B1
+#define V_AMBEN AMBEN_B0_B1
+#endif
+#ifdef CONFIG_C_AMBEN_B0_B1_B2
+#define V_AMBEN AMBEN_B0_B1_B2
+#endif
+#ifdef CONFIG_C_AMCKEN
+#define V_AMCKEN AMCKEN
+#else
+#define V_AMCKEN 0x0
+#endif
+#ifdef CONFIG_C_CDPRIO
+#define V_CDPRIO 0x100
+#else
+#define V_CDPRIO 0x0
+#endif
+
+#define AMGCTLVAL (V_AMBEN | V_AMCKEN | V_CDPRIO)
+
+#ifdef CONFIG_BF527
+#define CPU "BF527"
+#endif
+#ifdef CONFIG_BF525
+#define CPU "BF525"
+#endif
+#ifdef CONFIG_BF522
+#define CPU "BF522"
+#endif
+#ifndef CPU
+#define CPU "UNKNOWN"
+#define CPUID 0x0
+#endif
+
+#endif /* __MACH_BF527_H__ */
diff --git a/include/asm-blackfin/mach-bf527/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf527/bfin_serial_5xx.h
new file mode 100644
index 000000000000..0b867e6a76c4
--- /dev/null
+++ b/include/asm-blackfin/mach-bf527/bfin_serial_5xx.h
@@ -0,0 +1,152 @@
+#include <linux/serial.h>
+#include <asm/dma.h>
+#include <asm/portmux.h>
+
+#define NR_PORTS 2
+
+#define OFFSET_THR 0x00 /* Transmit Holding register */
+#define OFFSET_RBR 0x00 /* Receive Buffer register */
+#define OFFSET_DLL 0x00 /* Divisor Latch (Low-Byte) */
+#define OFFSET_IER 0x04 /* Interrupt Enable Register */
+#define OFFSET_DLH 0x04 /* Divisor Latch (High-Byte) */
+#define OFFSET_IIR 0x08 /* Interrupt Identification Register */
+#define OFFSET_LCR 0x0C /* Line Control Register */
+#define OFFSET_MCR 0x10 /* Modem Control Register */
+#define OFFSET_LSR 0x14 /* Line Status Register */
+#define OFFSET_MSR 0x18 /* Modem Status Register */
+#define OFFSET_SCR 0x1C /* SCR Scratch Register */
+#define OFFSET_GCTL 0x24 /* Global Control Register */
+
+#define UART_GET_CHAR(uart) bfin_read16(((uart)->port.membase + OFFSET_RBR))
+#define UART_GET_DLL(uart) bfin_read16(((uart)->port.membase + OFFSET_DLL))
+#define UART_GET_IER(uart) bfin_read16(((uart)->port.membase + OFFSET_IER))
+#define UART_GET_DLH(uart) bfin_read16(((uart)->port.membase + OFFSET_DLH))
+#define UART_GET_IIR(uart) bfin_read16(((uart)->port.membase + OFFSET_IIR))
+#define UART_GET_LCR(uart) bfin_read16(((uart)->port.membase + OFFSET_LCR))
+#define UART_GET_LSR(uart) bfin_read16(((uart)->port.membase + OFFSET_LSR))
+#define UART_GET_GCTL(uart) bfin_read16(((uart)->port.membase + OFFSET_GCTL))
+
+#define UART_PUT_CHAR(uart, v) bfin_write16(((uart)->port.membase + OFFSET_THR), v)
+#define UART_PUT_DLL(uart, v) bfin_write16(((uart)->port.membase + OFFSET_DLL), v)
+#define UART_PUT_IER(uart, v) bfin_write16(((uart)->port.membase + OFFSET_IER), v)
+#define UART_PUT_DLH(uart, v) bfin_write16(((uart)->port.membase + OFFSET_DLH), v)
+#define UART_PUT_LCR(uart, v) bfin_write16(((uart)->port.membase + OFFSET_LCR), v)
+#define UART_PUT_GCTL(uart, v) bfin_write16(((uart)->port.membase + OFFSET_GCTL), v)
+
+#if defined(CONFIG_BFIN_UART0_CTSRTS) || defined(CONFIG_BFIN_UART1_CTSRTS)
+# define CONFIG_SERIAL_BFIN_CTSRTS
+
+# ifndef CONFIG_UART0_CTS_PIN
+# define CONFIG_UART0_CTS_PIN -1
+# endif
+
+# ifndef CONFIG_UART0_RTS_PIN
+# define CONFIG_UART0_RTS_PIN -1
+# endif
+
+# ifndef CONFIG_UART1_CTS_PIN
+# define CONFIG_UART1_CTS_PIN -1
+# endif
+
+# ifndef CONFIG_UART1_RTS_PIN
+# define CONFIG_UART1_RTS_PIN -1
+# endif
+#endif
+/*
+ * The pin configuration is different from schematic
+ */
+struct bfin_serial_port {
+ struct uart_port port;
+ unsigned int old_status;
+#ifdef CONFIG_SERIAL_BFIN_DMA
+ int tx_done;
+ int tx_count;
+ struct circ_buf rx_dma_buf;
+ struct timer_list rx_dma_timer;
+ int rx_dma_nrows;
+ unsigned int tx_dma_channel;
+ unsigned int rx_dma_channel;
+ struct work_struct tx_dma_workqueue;
+#else
+ struct work_struct cts_workqueue;
+#endif
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+ int cts_pin;
+ int rts_pin;
+#endif
+};
+
+struct bfin_serial_port bfin_serial_ports[NR_PORTS];
+struct bfin_serial_res {
+ unsigned long uart_base_addr;
+ int uart_irq;
+#ifdef CONFIG_SERIAL_BFIN_DMA
+ unsigned int uart_tx_dma_channel;
+ unsigned int uart_rx_dma_channel;
+#endif
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+ int uart_cts_pin;
+ int uart_rts_pin;
+#endif
+};
+
+struct bfin_serial_res bfin_serial_resource[] = {
+#ifdef CONFIG_SERIAL_BFIN_UART0
+ {
+ 0xFFC00400,
+ IRQ_UART0_RX,
+#ifdef CONFIG_SERIAL_BFIN_DMA
+ CH_UART0_TX,
+ CH_UART0_RX,
+#endif
+#ifdef CONFIG_BFIN_UART0_CTSRTS
+ CONFIG_UART0_CTS_PIN,
+ CONFIG_UART0_RTS_PIN,
+#endif
+ },
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART1
+ {
+ 0xFFC02000,
+ IRQ_UART1_RX,
+#ifdef CONFIG_SERIAL_BFIN_DMA
+ CH_UART1_TX,
+ CH_UART1_RX,
+#endif
+#ifdef CONFIG_BFIN_UART1_CTSRTS
+ CONFIG_UART1_CTS_PIN,
+ CONFIG_UART1_RTS_PIN,
+#endif
+ },
+#endif
+};
+
+int nr_ports = ARRAY_SIZE(bfin_serial_resource);
+
+#define DRIVER_NAME "bfin-uart"
+
+static void bfin_serial_hw_init(struct bfin_serial_port *uart)
+{
+
+#ifdef CONFIG_SERIAL_BFIN_UART0
+ peripheral_request(P_UART0_TX, DRIVER_NAME);
+ peripheral_request(P_UART0_RX, DRIVER_NAME);
+#endif
+
+#ifdef CONFIG_SERIAL_BFIN_UART1
+ peripheral_request(P_UART1_TX, DRIVER_NAME);
+ peripheral_request(P_UART1_RX, DRIVER_NAME);
+#endif
+
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+ if (uart->cts_pin >= 0) {
+ gpio_request(uart->cts_pin, DRIVER_NAME);
+ gpio_direction_input(uart->cts_pin);
+ }
+
+ if (uart->rts_pin >= 0) {
+ gpio_request(uart->rts_pin, DRIVER_NAME);
+ gpio_direction_output(uart->rts_pin);
+ }
+#endif
+}
diff --git a/include/asm-blackfin/mach-bf527/blackfin.h b/include/asm-blackfin/mach-bf527/blackfin.h
new file mode 100644
index 000000000000..1bd07e30781c
--- /dev/null
+++ b/include/asm-blackfin/mach-bf527/blackfin.h
@@ -0,0 +1,78 @@
+/*
+ * File: include/asm-blackfin/mach-bf527/blackfin.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _MACH_BLACKFIN_H_
+#define _MACH_BLACKFIN_H_
+
+#define BF527_FAMILY
+
+#include "bf527.h"
+#include "mem_map.h"
+#include "defBF522.h"
+#include "anomaly.h"
+
+#if defined(CONFIG_BF527)
+#include "defBF527.h"
+#endif
+
+#if defined(CONFIG_BF525)
+#include "defBF525.h"
+#endif
+
+#if !defined(__ASSEMBLY__)
+#include "cdefBF522.h"
+
+#if defined(CONFIG_BF527)
+#include "cdefBF527.h"
+#endif
+
+#if defined(CONFIG_BF525)
+#include "cdefBF525.h"
+#endif
+#endif
+
+/* UART_IIR Register */
+#define STATUS(x) ((x << 1) & 0x06)
+#define STATUS_P1 0x02
+#define STATUS_P0 0x01
+
+/* DPMC*/
+#define bfin_read_STOPCK_OFF() bfin_read_STOPCK()
+#define bfin_write_STOPCK_OFF(val) bfin_write_STOPCK(val)
+#define STOPCK_OFF STOPCK
+
+/* PLL_DIV Masks */
+#define CCLK_DIV1 CSEL_DIV1 /* CCLK = VCO / 1 */
+#define CCLK_DIV2 CSEL_DIV2 /* CCLK = VCO / 2 */
+#define CCLK_DIV4 CSEL_DIV4 /* CCLK = VCO / 4 */
+#define CCLK_DIV8 CSEL_DIV8 /* CCLK = VCO / 8 */
+
+#endif
diff --git a/include/asm-blackfin/mach-bf527/cdefBF52x_base.h b/include/asm-blackfin/mach-bf527/cdefBF52x_base.h
index 5f801a0ef797..3f4de5d9d4cb 100644
--- a/include/asm-blackfin/mach-bf527/cdefBF52x_base.h
+++ b/include/asm-blackfin/mach-bf527/cdefBF52x_base.h
@@ -45,8 +45,8 @@
#define bfin_write_PLL_STAT(val) bfin_write16(PLL_STAT, val)
#define bfin_read_PLL_LOCKCNT() bfin_read16(PLL_LOCKCNT)
#define bfin_write_PLL_LOCKCNT(val) bfin_write16(PLL_LOCKCNT, val)
-#define bfin_read_CHIPID() bfin_read16(CHIPID)
-#define bfin_write_CHIPID(val) bfin_write16(CHIPID, val)
+#define bfin_read_CHIPID() bfin_read32(CHIPID)
+#define bfin_write_CHIPID(val) bfin_write32(CHIPID, val)
/* System Interrupt Controller (0xFFC00100 - 0xFFC001FF) */
@@ -59,9 +59,8 @@
#define bfin_write_SIC_RVECT(val) bfin_write32(SIC_RVECT, val)
#define bfin_read_SIC_IMASK0() bfin_read32(SIC_IMASK0)
#define bfin_write_SIC_IMASK0(val) bfin_write32(SIC_IMASK0, val)
-/* legacy register name (below) provided for backwards code compatibility */
-#define bfin_read_SIC_IMASK() bfin_read32(SIC_IMASK)
-#define bfin_write_SIC_IMASK(val) bfin_write32(SIC_IMASK, val)
+#define bfin_read_SIC_IMASK(x) bfin_read32(SIC_IMASK0 + (x << 6))
+#define bfin_write_SIC_IMASK(x, val) bfin_write32((SIC_IMASK0 + (x << 6)), val)
#define bfin_read_SIC_IAR0() bfin_read32(SIC_IAR0)
#define bfin_write_SIC_IAR0(val) bfin_write32(SIC_IAR0, val)
@@ -74,15 +73,13 @@
#define bfin_read_SIC_ISR0() bfin_read32(SIC_ISR0)
#define bfin_write_SIC_ISR0(val) bfin_write32(SIC_ISR0, val)
-/* legacy register name (below) provided for backwards code compatibility */
-#define bfin_read_SIC_ISR() bfin_read32(SIC_ISR)
-#define bfin_write_SIC_ISR(val) bfin_write32(SIC_ISR, val)
+#define bfin_read_SIC_ISR(x) bfin_read32(SIC_ISR0 + (x << 6))
+#define bfin_write_SIC_ISR(x, val) bfin_write32((SIC_ISR0 + (x << 6)), val)
#define bfin_read_SIC_IWR0() bfin_read32(SIC_IWR0)
#define bfin_write_SIC_IWR0(val) bfin_write32(SIC_IWR0, val)
-/* legacy register name (below) provided for backwards code compatibility */
-#define bfin_read_SIC_IWR() bfin_read32(SIC_IWR)
-#define bfin_write_SIC_IWR(val) bfin_write32(SIC_IWR, val)
+#define bfin_read_SIC_IWR(x) bfin_read32(SIC_IWR0 + (x << 6))
+#define bfin_write_SIC_IWR(x, val) bfin_write32((SIC_IWR0 + (x << 6)), val)
/* SIC Additions to ADSP-BF52x (0xFFC0014C - 0xFFC00162) */
diff --git a/include/asm-blackfin/mach-bf527/defBF527.h b/include/asm-blackfin/mach-bf527/defBF527.h
index 2be3293f9e26..82134f578f32 100644
--- a/include/asm-blackfin/mach-bf527/defBF527.h
+++ b/include/asm-blackfin/mach-bf527/defBF527.h
@@ -32,12 +32,12 @@
#define _DEF_BF527_H
/* Include all Core registers and bit definitions */
-#include <def_LPBlackfin.h>
+#include <asm/mach-common/def_LPBlackfin.h>
/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF527 */
/* Include defBF52x_base.h for the set of #defines that are common to all ADSP-BF52x processors */
-#include <defBF52x_base.h>
+#include "defBF52x_base.h"
/* The following are the #defines needed by ADSP-BF527 that are not in the common header */
/* 10/100 Ethernet Controller (0xFFC03000 - 0xFFC031FF) */
diff --git a/include/asm-blackfin/mach-bf527/defBF52x_base.h b/include/asm-blackfin/mach-bf527/defBF52x_base.h
index b1ff67db01f8..fc69cf93f149 100644
--- a/include/asm-blackfin/mach-bf527/defBF52x_base.h
+++ b/include/asm-blackfin/mach-bf527/defBF52x_base.h
@@ -52,13 +52,13 @@
#define SYSCR 0xFFC00104 /* System Configuration Register */
#define SIC_RVECT 0xFFC00108 /* Interrupt Reset Vector Address Register */
-#define SIC_IMASK 0xFFC0010C /* Interrupt Mask Register */
+#define SIC_IMASK0 0xFFC0010C /* Interrupt Mask Register */
#define SIC_IAR0 0xFFC00110 /* Interrupt Assignment Register 0 */
#define SIC_IAR1 0xFFC00114 /* Interrupt Assignment Register 1 */
#define SIC_IAR2 0xFFC00118 /* Interrupt Assignment Register 2 */
#define SIC_IAR3 0xFFC0011C /* Interrupt Assignment Register 3 */
-#define SIC_ISR 0xFFC00120 /* Interrupt Status Register */
-#define SIC_IWR 0xFFC00124 /* Interrupt Wakeup Register */
+#define SIC_ISR0 0xFFC00120 /* Interrupt Status Register */
+#define SIC_IWR0 0xFFC00124 /* Interrupt Wakeup Register */
/* SIC Additions to ADSP-BF52x (0xFFC0014C - 0xFFC00162) */
#define SIC_IMASK1 0xFFC0014C /* Interrupt Mask register of SIC2 */
@@ -691,6 +691,8 @@
/* ************* SYSTEM INTERRUPT CONTROLLER MASKS *************************************/
/* Peripheral Masks For SIC_ISR, SIC_IWR, SIC_IMASK */
+
+#if 0
#define IRQ_PLL_WAKEUP 0x00000001 /* PLL Wakeup Interrupt */
#define IRQ_ERROR1 0x00000002 /* Error Interrupt (DMA, DMARx Block, DMARx Overflow) */
@@ -732,6 +734,7 @@
#define IRQ_DMA15 0x40000000 /* DMA Channels 15 (MDMA0 Destination) TX Interrupt */
#define IRQ_WDOG 0x80000000 /* Software Watchdog Timer Interrupt */
#define IRQ_PFB_PORTG 0x10000000 /* PF Port G (PF31:16) Interrupt B */
+#endif
/* SIC_IAR0 Macros */
#define P0_IVG(x) (((x)&0xF)-7) /* Peripheral #0 assigned IVG #x */
@@ -1715,55 +1718,55 @@
/* Bit masks for HOST_CONTROL */
-#define HOST_EN 0x1 /* Host Enable */
-#define nHOST_EN 0x0
-#define HOST_END 0x2 /* Host Endianess */
-#define nHOST_END 0x0
-#define DATA_SIZE 0x4 /* Data Size */
-#define nDATA_SIZE 0x0
-#define HOST_RST 0x8 /* Host Reset */
-#define nHOST_RST 0x0
-#define HRDY_OVR 0x20 /* Host Ready Override */
-#define nHRDY_OVR 0x0
-#define INT_MODE 0x40 /* Interrupt Mode */
-#define nINT_MODE 0x0
-#define BT_EN 0x80 /* Bus Timeout Enable */
-#define nBT_EN 0x0
-#define EHW 0x100 /* Enable Host Write */
-#define nEHW 0x0
-#define EHR 0x200 /* Enable Host Read */
-#define nEHR 0x0
-#define BDR 0x400 /* Burst DMA Requests */
-#define nBDR 0x0
+#define HOST_CNTR_HOST_EN 0x1 /* Host Enable */
+#define HOST_CNTR_nHOST_EN 0x0
+#define HOST_CNTR_HOST_END 0x2 /* Host Endianess */
+#define HOST_CNTR_nHOST_END 0x0
+#define HOST_CNTR_DATA_SIZE 0x4 /* Data Size */
+#define HOST_CNTR_nDATA_SIZE 0x0
+#define HOST_CNTR_HOST_RST 0x8 /* Host Reset */
+#define HOST_CNTR_nHOST_RST 0x0
+#define HOST_CNTR_HRDY_OVR 0x20 /* Host Ready Override */
+#define HOST_CNTR_nHRDY_OVR 0x0
+#define HOST_CNTR_INT_MODE 0x40 /* Interrupt Mode */
+#define HOST_CNTR_nINT_MODE 0x0
+#define HOST_CNTR_BT_EN 0x80 /* Bus Timeout Enable */
+#define HOST_CNTR_ nBT_EN 0x0
+#define HOST_CNTR_EHW 0x100 /* Enable Host Write */
+#define HOST_CNTR_nEHW 0x0
+#define HOST_CNTR_EHR 0x200 /* Enable Host Read */
+#define HOST_CNTR_nEHR 0x0
+#define HOST_CNTR_BDR 0x400 /* Burst DMA Requests */
+#define HOST_CNTR_nBDR 0x0
/* Bit masks for HOST_STATUS */
-#define READY 0x1 /* DMA Ready */
-#define nREADY 0x0
-#define FIFOFULL 0x2 /* FIFO Full */
-#define nFIFOFULL 0x0
-#define FIFOEMPTY 0x4 /* FIFO Empty */
-#define nFIFOEMPTY 0x0
-#define COMPLETE 0x8 /* DMA Complete */
-#define nCOMPLETE 0x0
-#define HSHK 0x10 /* Host Handshake */
-#define nHSHK 0x0
-#define TIMEOUT 0x20 /* Host Timeout */
-#define nTIMEOUT 0x0
-#define HIRQ 0x40 /* Host Interrupt Request */
-#define nHIRQ 0x0
-#define ALLOW_CNFG 0x80 /* Allow New Configuration */
-#define nALLOW_CNFG 0x0
-#define DMA_DIR 0x100 /* DMA Direction */
-#define nDMA_DIR 0x0
-#define BTE 0x200 /* Bus Timeout Enabled */
-#define nBTE 0x0
-#define HOSTRD_DONE 0x8000 /* Host Read Completion Interrupt */
-#define nHOSTRD_DONE 0x0
+#define HOST_STAT_READY 0x1 /* DMA Ready */
+#define HOST_STAT_nREADY 0x0
+#define HOST_STAT_FIFOFULL 0x2 /* FIFO Full */
+#define HOST_STAT_nFIFOFULL 0x0
+#define HOST_STAT_FIFOEMPTY 0x4 /* FIFO Empty */
+#define HOST_STAT_nFIFOEMPTY 0x0
+#define HOST_STAT_COMPLETE 0x8 /* DMA Complete */
+#define HOST_STAT_nCOMPLETE 0x0
+#define HOST_STAT_HSHK 0x10 /* Host Handshake */
+#define HOST_STAT_nHSHK 0x0
+#define HOST_STAT_TIMEOUT 0x20 /* Host Timeout */
+#define HOST_STAT_nTIMEOUT 0x0
+#define HOST_STAT_HIRQ 0x40 /* Host Interrupt Request */
+#define HOST_STAT_nHIRQ 0x0
+#define HOST_STAT_ALLOW_CNFG 0x80 /* Allow New Configuration */
+#define HOST_STAT_nALLOW_CNFG 0x0
+#define HOST_STAT_DMA_DIR 0x100 /* DMA Direction */
+#define HOST_STAT_nDMA_DIR 0x0
+#define HOST_STAT_BTE 0x200 /* Bus Timeout Enabled */
+#define HOST_STAT_nBTE 0x0
+#define HOST_STAT_HOSTRD_DONE 0x8000 /* Host Read Completion Interrupt */
+#define HOST_STAT_nHOSTRD_DONE 0x0
/* Bit masks for HOST_TIMEOUT */
-#define COUNT_TIMEOUT 0x7ff /* Host Timeout count */
+#define HOST_COUNT_TIMEOUT 0x7ff /* Host Timeout count */
/* Bit masks for CNT_CONFIG */
diff --git a/include/asm-blackfin/mach-bf527/dma.h b/include/asm-blackfin/mach-bf527/dma.h
new file mode 100644
index 000000000000..2dfee12864f6
--- /dev/null
+++ b/include/asm-blackfin/mach-bf527/dma.h
@@ -0,0 +1,65 @@
+/*
+ * file: include/asm-blackfin/mach-bf527/dma.h
+ * based on: include/asm-blackfin/mach-bf537/dma.h
+ * author: Michael Hennerich (michael.hennerich@analog.com)
+ *
+ * created:
+ * description:
+ * system DMA map
+ * rev:
+ *
+ * modified:
+ *
+ *
+ * bugs: enter bugs at http://blackfin.uclinux.org/
+ *
+ * this program is free software; you can redistribute it and/or modify
+ * it under the terms of the gnu general public license as published by
+ * the free software foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this program is distributed in the hope that it will be useful,
+ * but without any warranty; without even the implied warranty of
+ * merchantability or fitness for a particular purpose. see the
+ * gnu general public license for more details.
+ *
+ * you should have received a copy of the gnu general public license
+ * along with this program; see the file copying.
+ * if not, write to the free software foundation,
+ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ */
+
+#ifndef _MACH_DMA_H_
+#define _MACH_DMA_H_
+
+#define MAX_BLACKFIN_DMA_CHANNEL 16
+
+#define CH_PPI 0 /* PPI receive/transmit or NFC */
+#define CH_EMAC_RX 1 /* Ethernet MAC receive or HOSTDP */
+#define CH_EMAC_HOSTDP 1 /* Ethernet MAC receive or HOSTDP */
+#define CH_EMAC_TX 2 /* Ethernet MAC transmit or NFC */
+#define CH_SPORT0_RX 3 /* SPORT0 receive */
+#define CH_SPORT0_TX 4 /* SPORT0 transmit */
+#define CH_SPORT1_RX 5 /* SPORT1 receive */
+#define CH_SPORT1_TX 6 /* SPORT1 transmit */
+#define CH_SPI 7 /* SPI transmit/receive */
+#define CH_UART0_RX 8 /* UART0 receive */
+#define CH_UART0_TX 9 /* UART0 transmit */
+#define CH_UART1_RX 10 /* UART1 receive */
+#define CH_UART1_TX 11 /* UART1 transmit */
+
+#define CH_MEM_STREAM0_DEST 12 /* TX */
+#define CH_MEM_STREAM0_SRC 13 /* RX */
+#define CH_MEM_STREAM1_DEST 14 /* TX */
+#define CH_MEM_STREAM1_SRC 15 /* RX */
+
+#if defined(CONFIG_BF527_NAND_D_PORTF)
+#define CH_NFC CH_PPI /* PPI receive/transmit or NFC */
+#elif defined(CONFIG_BF527_NAND_D_PORTH)
+#define CH_NFC CH_EMAC_TX /* PPI receive/transmit or NFC */
+#endif
+
+extern int channel2irq(unsigned int channel);
+extern struct dma_register *base_addr[];
+
+#endif
diff --git a/include/asm-blackfin/mach-bf527/irq.h b/include/asm-blackfin/mach-bf527/irq.h
new file mode 100644
index 000000000000..304f5bcfebe4
--- /dev/null
+++ b/include/asm-blackfin/mach-bf527/irq.h
@@ -0,0 +1,263 @@
+/*
+ * file: include/asm-blackfin/mach-bf527/irq.h
+ * based on: include/asm-blackfin/mach-bf537/irq.h
+ * author: Michael Hennerich (michael.hennerich@analog.com)
+ *
+ * created:
+ * description:
+ * system mmr register map
+ * rev:
+ *
+ * modified:
+ *
+ *
+ * bugs: enter bugs at http://blackfin.uclinux.org/
+ *
+ * this program is free software; you can redistribute it and/or modify
+ * it under the terms of the gnu general public license as published by
+ * the free software foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this program is distributed in the hope that it will be useful,
+ * but without any warranty; without even the implied warranty of
+ * merchantability or fitness for a particular purpose. see the
+ * gnu general public license for more details.
+ *
+ * you should have received a copy of the gnu general public license
+ * along with this program; see the file copying.
+ * if not, write to the free software foundation,
+ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ */
+
+#ifndef _BF527_IRQ_H_
+#define _BF527_IRQ_H_
+
+/*
+ * Interrupt source definitions
+ Event Source Core Event Name
+ Core Emulation **
+ Events (highest priority) EMU 0
+ Reset RST 1
+ NMI NMI 2
+ Exception EVX 3
+ Reserved -- 4
+ Hardware Error IVHW 5
+ Core Timer IVTMR 6 *
+
+ .....
+
+ Software Interrupt 1 IVG14 31
+ Software Interrupt 2 --
+ (lowest priority) IVG15 32 *
+*/
+
+#define NR_PERI_INTS (2 * 32)
+
+/* The ABSTRACT IRQ definitions */
+/** the first seven of the following are fixed, the rest you change if you need to **/
+#define IRQ_EMU 0 /* Emulation */
+#define IRQ_RST 1 /* reset */
+#define IRQ_NMI 2 /* Non Maskable */
+#define IRQ_EVX 3 /* Exception */
+#define IRQ_UNUSED 4 /* - unused interrupt */
+#define IRQ_HWERR 5 /* Hardware Error */
+#define IRQ_CORETMR 6 /* Core timer */
+
+#define BFIN_IRQ(x) ((x) + 7)
+
+#define IRQ_PLL_WAKEUP BFIN_IRQ(0) /* PLL Wakeup Interrupt */
+#define IRQ_DMA0_ERROR BFIN_IRQ(1) /* DMA Error 0 (generic) */
+#define IRQ_DMAR0_BLK BFIN_IRQ(2) /* DMAR0 Block Interrupt */
+#define IRQ_DMAR1_BLK BFIN_IRQ(3) /* DMAR1 Block Interrupt */
+#define IRQ_DMAR0_OVR BFIN_IRQ(4) /* DMAR0 Overflow Error */
+#define IRQ_DMAR1_OVR BFIN_IRQ(5) /* DMAR1 Overflow Error */
+#define IRQ_PPI_ERROR BFIN_IRQ(6) /* PPI Error */
+#define IRQ_MAC_ERROR BFIN_IRQ(7) /* MAC Status */
+#define IRQ_SPORT0_ERROR BFIN_IRQ(8) /* SPORT0 Status */
+#define IRQ_SPORT1_ERROR BFIN_IRQ(9) /* SPORT1 Status */
+#define IRQ_UART0_ERROR BFIN_IRQ(12) /* UART0 Status */
+#define IRQ_UART1_ERROR BFIN_IRQ(13) /* UART1 Status */
+#define IRQ_RTC BFIN_IRQ(14) /* RTC */
+#define IRQ_PPI BFIN_IRQ(15) /* DMA Channel 0 (PPI/NAND) */
+#define IRQ_SPORT0_RX BFIN_IRQ(16) /* DMA 3 Channel (SPORT0 RX) */
+#define IRQ_SPORT0_TX BFIN_IRQ(17) /* DMA 4 Channel (SPORT0 TX) */
+#define IRQ_SPORT1_RX BFIN_IRQ(18) /* DMA 5 Channel (SPORT1 RX) */
+#define IRQ_SPORT1_TX BFIN_IRQ(19) /* DMA 6 Channel (SPORT1 TX) */
+#define IRQ_TWI BFIN_IRQ(20) /* TWI */
+#define IRQ_SPI BFIN_IRQ(21) /* DMA 7 Channel (SPI) */
+#define IRQ_UART0_RX BFIN_IRQ(22) /* DMA8 Channel (UART0 RX) */
+#define IRQ_UART0_TX BFIN_IRQ(23) /* DMA9 Channel (UART0 TX) */
+#define IRQ_UART1_RX BFIN_IRQ(24) /* DMA10 Channel (UART1 RX) */
+#define IRQ_UART1_TX BFIN_IRQ(25) /* DMA11 Channel (UART1 TX) */
+#define IRQ_OPTSEC BFIN_IRQ(26) /* OTPSEC Interrupt */
+#define IRQ_CNT BFIN_IRQ(27) /* GP Counter */
+#define IRQ_MAC_RX BFIN_IRQ(28) /* DMA1 Channel (MAC RX/HDMA) */
+#define IRQ_PORTH_INTA BFIN_IRQ(29) /* Port H Interrupt A */
+#define IRQ_MAC_TX BFIN_IRQ(30) /* DMA2 Channel (MAC TX/NAND) */
+#define IRQ_NFC BFIN_IRQ(30) /* DMA2 Channel (MAC TX/NAND) */
+#define IRQ_PORTH_INTB BFIN_IRQ(31) /* Port H Interrupt B */
+#define IRQ_TMR0 BFIN_IRQ(32) /* Timer 0 */
+#define IRQ_TMR1 BFIN_IRQ(33) /* Timer 1 */
+#define IRQ_TMR2 BFIN_IRQ(34) /* Timer 2 */
+#define IRQ_TMR3 BFIN_IRQ(35) /* Timer 3 */
+#define IRQ_TMR4 BFIN_IRQ(36) /* Timer 4 */
+#define IRQ_TMR5 BFIN_IRQ(37) /* Timer 5 */
+#define IRQ_TMR6 BFIN_IRQ(38) /* Timer 6 */
+#define IRQ_TMR7 BFIN_IRQ(39) /* Timer 7 */
+#define IRQ_PORTG_INTA BFIN_IRQ(40) /* Port G Interrupt A */
+#define IRQ_PORTG_INTB BFIN_IRQ(41) /* Port G Interrupt B */
+#define IRQ_MEM_DMA0 BFIN_IRQ(42) /* MDMA Stream 0 */
+#define IRQ_MEM_DMA1 BFIN_IRQ(43) /* MDMA Stream 1 */
+#define IRQ_WATCH BFIN_IRQ(44) /* Software Watchdog Timer */
+#define IRQ_PORTF_INTA BFIN_IRQ(45) /* Port F Interrupt A */
+#define IRQ_PORTF_INTB BFIN_IRQ(46) /* Port F Interrupt B */
+#define IRQ_SPI_ERROR BFIN_IRQ(47) /* SPI Status */
+#define IRQ_NFC_ERROR BFIN_IRQ(48) /* NAND Error */
+#define IRQ_HDMA_ERROR BFIN_IRQ(49) /* HDMA Error */
+#define IRQ_HDMA BFIN_IRQ(50) /* HDMA (TFI) */
+#define IRQ_USB_EINT BFIN_IRQ(51) /* USB_EINT Interrupt */
+#define IRQ_USB_INT0 BFIN_IRQ(52) /* USB_INT0 Interrupt */
+#define IRQ_USB_INT1 BFIN_IRQ(53) /* USB_INT1 Interrupt */
+#define IRQ_USB_INT2 BFIN_IRQ(54) /* USB_INT2 Interrupt */
+#define IRQ_USB_DMA BFIN_IRQ(55) /* USB_DMAINT Interrupt */
+
+#define SYS_IRQS BFIN_IRQ(63) /* 70 */
+
+#define IRQ_PF0 71
+#define IRQ_PF1 72
+#define IRQ_PF2 73
+#define IRQ_PF3 74
+#define IRQ_PF4 75
+#define IRQ_PF5 76
+#define IRQ_PF6 77
+#define IRQ_PF7 78
+#define IRQ_PF8 79
+#define IRQ_PF9 80
+#define IRQ_PF10 81
+#define IRQ_PF11 82
+#define IRQ_PF12 83
+#define IRQ_PF13 84
+#define IRQ_PF14 85
+#define IRQ_PF15 86
+
+#define IRQ_PG0 87
+#define IRQ_PG1 88
+#define IRQ_PG2 89
+#define IRQ_PG3 90
+#define IRQ_PG4 91
+#define IRQ_PG5 92
+#define IRQ_PG6 93
+#define IRQ_PG7 94
+#define IRQ_PG8 95
+#define IRQ_PG9 96
+#define IRQ_PG10 97
+#define IRQ_PG11 98
+#define IRQ_PG12 99
+#define IRQ_PG13 100
+#define IRQ_PG14 101
+#define IRQ_PG15 102
+
+#define IRQ_PH0 103
+#define IRQ_PH1 104
+#define IRQ_PH2 105
+#define IRQ_PH3 106
+#define IRQ_PH4 107
+#define IRQ_PH5 108
+#define IRQ_PH6 109
+#define IRQ_PH7 110
+#define IRQ_PH8 111
+#define IRQ_PH9 112
+#define IRQ_PH10 113
+#define IRQ_PH11 114
+#define IRQ_PH12 115
+#define IRQ_PH13 116
+#define IRQ_PH14 117
+#define IRQ_PH15 118
+
+#define GPIO_IRQ_BASE IRQ_PF0
+
+#ifdef CONFIG_IRQCHIP_DEMUX_GPIO
+#define NR_IRQS (IRQ_PH15+1)
+#else
+#define NR_IRQS (SYS_IRQS+1)
+#endif
+
+#define IVG7 7
+#define IVG8 8
+#define IVG9 9
+#define IVG10 10
+#define IVG11 11
+#define IVG12 12
+#define IVG13 13
+#define IVG14 14
+#define IVG15 15
+
+/* IAR0 BIT FIELDS */
+#define IRQ_PLL_WAKEUP_POS 0
+#define IRQ_DMA0_ERROR_POS 4
+#define IRQ_DMAR0_BLK_POS 8
+#define IRQ_DMAR1_BLK_POS 12
+#define IRQ_DMAR0_OVR_POS 16
+#define IRQ_DMAR1_OVR_POS 20
+#define IRQ_PPI_ERROR_POS 24
+#define IRQ_MAC_ERROR_POS 28
+
+/* IAR1 BIT FIELDS */
+#define IRQ_SPORT0_ERROR_POS 0
+#define IRQ_SPORT1_ERROR_POS 4
+#define IRQ_UART0_ERROR_POS 16
+#define IRQ_UART1_ERROR_POS 20
+#define IRQ_RTC_POS 24
+#define IRQ_PPI_POS 28
+
+/* IAR2 BIT FIELDS */
+#define IRQ_SPORT0_RX_POS 0
+#define IRQ_SPORT0_TX_POS 4
+#define IRQ_SPORT1_RX_POS 8
+#define IRQ_SPORT1_TX_POS 12
+#define IRQ_TWI_POS 16
+#define IRQ_SPI_POS 20
+#define IRQ_UART0_RX_POS 24
+#define IRQ_UART0_TX_POS 28
+
+/* IAR3 BIT FIELDS */
+#define IRQ_UART1_RX_POS 0
+#define IRQ_UART1_TX_POS 4
+#define IRQ_OPTSEC_POS 8
+#define IRQ_CNT_POS 12
+#define IRQ_MAC_RX_POS 16
+#define IRQ_PORTH_INTA_POS 20
+#define IRQ_MAC_TX_POS 24
+#define IRQ_PORTH_INTB_POS 28
+
+/* IAR4 BIT FIELDS */
+#define IRQ_TMR0_POS 0
+#define IRQ_TMR1_POS 4
+#define IRQ_TMR2_POS 8
+#define IRQ_TMR3_POS 12
+#define IRQ_TMR4_POS 16
+#define IRQ_TMR5_POS 20
+#define IRQ_TMR6_POS 24
+#define IRQ_TMR7_POS 28
+
+/* IAR5 BIT FIELDS */
+#define IRQ_PORTG_INTA_POS 0
+#define IRQ_PORTG_INTB_POS 4
+#define IRQ_MEM_DMA0_POS 8
+#define IRQ_MEM_DMA1_POS 12
+#define IRQ_WATCH_POS 16
+#define IRQ_PORTF_INTA_POS 20
+#define IRQ_PORTF_INTB_POS 24
+#define IRQ_SPI_ERROR_POS 28
+
+/* IAR6 BIT FIELDS */
+#define IRQ_NFC_ERROR_POS 0
+#define IRQ_HDMA_ERROR_POS 4
+#define IRQ_HDMA_POS 8
+#define IRQ_USB_EINT_POS 12
+#define IRQ_USB_INT0_POS 16
+#define IRQ_USB_INT1_POS 20
+#define IRQ_USB_INT2_POS 24
+#define IRQ_USB_DMA_POS 28
+
+#endif /* _BF527_IRQ_H_ */
diff --git a/include/asm-blackfin/mach-bf527/mem_init.h b/include/asm-blackfin/mach-bf527/mem_init.h
new file mode 100644
index 000000000000..008ca66719e2
--- /dev/null
+++ b/include/asm-blackfin/mach-bf527/mem_init.h
@@ -0,0 +1,337 @@
+/*
+ * File: include/asm-blackfin/mach-bf527/mem_init.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ * Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#if (CONFIG_MEM_MT48LC16M16A2TG_75 || CONFIG_MEM_MT48LC64M4A2FB_7E || CONFIG_MEM_MT48LC16M8A2TG_75 || CONFIG_MEM_GENERIC_BOARD || CONFIG_MEM_MT48LC32M8A2_75 || CONFIG_MEM_MT48LC32M16A2TG_75)
+#if (CONFIG_SCLK_HZ > 119402985)
+#define SDRAM_tRP TRP_2
+#define SDRAM_tRP_num 2
+#define SDRAM_tRAS TRAS_7
+#define SDRAM_tRAS_num 7
+#define SDRAM_tRCD TRCD_2
+#define SDRAM_tWR TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 104477612) && (CONFIG_SCLK_HZ <= 119402985)
+#define SDRAM_tRP TRP_2
+#define SDRAM_tRP_num 2
+#define SDRAM_tRAS TRAS_6
+#define SDRAM_tRAS_num 6
+#define SDRAM_tRCD TRCD_2
+#define SDRAM_tWR TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 89552239) && (CONFIG_SCLK_HZ <= 104477612)
+#define SDRAM_tRP TRP_2
+#define SDRAM_tRP_num 2
+#define SDRAM_tRAS TRAS_5
+#define SDRAM_tRAS_num 5
+#define SDRAM_tRCD TRCD_2
+#define SDRAM_tWR TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 74626866) && (CONFIG_SCLK_HZ <= 89552239)
+#define SDRAM_tRP TRP_2
+#define SDRAM_tRP_num 2
+#define SDRAM_tRAS TRAS_4
+#define SDRAM_tRAS_num 4
+#define SDRAM_tRCD TRCD_2
+#define SDRAM_tWR TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 66666667) && (CONFIG_SCLK_HZ <= 74626866)
+#define SDRAM_tRP TRP_2
+#define SDRAM_tRP_num 2
+#define SDRAM_tRAS TRAS_3
+#define SDRAM_tRAS_num 3
+#define SDRAM_tRCD TRCD_2
+#define SDRAM_tWR TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 59701493) && (CONFIG_SCLK_HZ <= 66666667)
+#define SDRAM_tRP TRP_1
+#define SDRAM_tRP_num 1
+#define SDRAM_tRAS TRAS_4
+#define SDRAM_tRAS_num 3
+#define SDRAM_tRCD TRCD_1
+#define SDRAM_tWR TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 44776119) && (CONFIG_SCLK_HZ <= 59701493)
+#define SDRAM_tRP TRP_1
+#define SDRAM_tRP_num 1
+#define SDRAM_tRAS TRAS_3
+#define SDRAM_tRAS_num 3
+#define SDRAM_tRCD TRCD_1
+#define SDRAM_tWR TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 29850746) && (CONFIG_SCLK_HZ <= 44776119)
+#define SDRAM_tRP TRP_1
+#define SDRAM_tRP_num 1
+#define SDRAM_tRAS TRAS_2
+#define SDRAM_tRAS_num 2
+#define SDRAM_tRCD TRCD_1
+#define SDRAM_tWR TWR_2
+#endif
+#if (CONFIG_SCLK_HZ <= 29850746)
+#define SDRAM_tRP TRP_1
+#define SDRAM_tRP_num 1
+#define SDRAM_tRAS TRAS_1
+#define SDRAM_tRAS_num 1
+#define SDRAM_tRCD TRCD_1
+#define SDRAM_tWR TWR_2
+#endif
+#endif
+
+#if (CONFIG_MEM_MT48LC16M16A2TG_75)
+ /*SDRAM INFORMATION: */
+#define SDRAM_Tref 64 /* Refresh period in milliseconds */
+#define SDRAM_NRA 8192 /* Number of row addresses in SDRAM */
+#define SDRAM_CL CL_3
+#endif
+
+#if (CONFIG_MEM_MT48LC16M8A2TG_75)
+ /*SDRAM INFORMATION: */
+#define SDRAM_Tref 64 /* Refresh period in milliseconds */
+#define SDRAM_NRA 4096 /* Number of row addresses in SDRAM */
+#define SDRAM_CL CL_3
+#endif
+
+#if (CONFIG_MEM_MT48LC32M8A2_75)
+ /*SDRAM INFORMATION: */
+#define SDRAM_Tref 64 /* Refresh period in milliseconds */
+#define SDRAM_NRA 8192 /* Number of row addresses in SDRAM */
+#define SDRAM_CL CL_3
+#endif
+
+#if (CONFIG_MEM_MT48LC64M4A2FB_7E)
+ /*SDRAM INFORMATION: */
+#define SDRAM_Tref 64 /* Refresh period in milliseconds */
+#define SDRAM_NRA 8192 /* Number of row addresses in SDRAM */
+#define SDRAM_CL CL_3
+#endif
+
+#if (CONFIG_MEM_GENERIC_BOARD)
+ /*SDRAM INFORMATION: Modify this for your board */
+#define SDRAM_Tref 64 /* Refresh period in milliseconds */
+#define SDRAM_NRA 8192 /* Number of row addresses in SDRAM */
+#define SDRAM_CL CL_3
+#endif
+
+#if (CONFIG_MEM_MT48LC32M16A2TG_75)
+ /*SDRAM INFORMATION: */
+#define SDRAM_Tref 64 /* Refresh period in milliseconds */
+#define SDRAM_NRA 8192 /* Number of row addresses in SDRAM */
+#define SDRAM_CL CL_3
+#endif
+
+#if (CONFIG_MEM_SIZE == 128)
+#define SDRAM_SIZE EBSZ_128
+#endif
+#if (CONFIG_MEM_SIZE == 64)
+#define SDRAM_SIZE EBSZ_64
+#endif
+#if (CONFIG_MEM_SIZE == 32)
+#define SDRAM_SIZE EBSZ_32
+#endif
+#if (CONFIG_MEM_SIZE == 16)
+#define SDRAM_SIZE EBSZ_16
+#endif
+#if (CONFIG_MEM_ADD_WIDTH == 11)
+#define SDRAM_WIDTH EBCAW_11
+#endif
+#if (CONFIG_MEM_ADD_WIDTH == 10)
+#define SDRAM_WIDTH EBCAW_10
+#endif
+#if (CONFIG_MEM_ADD_WIDTH == 9)
+#define SDRAM_WIDTH EBCAW_9
+#endif
+#if (CONFIG_MEM_ADD_WIDTH == 8)
+#define SDRAM_WIDTH EBCAW_8
+#endif
+
+#define mem_SDBCTL (SDRAM_WIDTH | SDRAM_SIZE | EBE)
+
+/* Equation from section 17 (p17-46) of BF533 HRM */
+#define mem_SDRRC (((CONFIG_SCLK_HZ / 1000) * SDRAM_Tref) / SDRAM_NRA) - (SDRAM_tRAS_num + SDRAM_tRP_num)
+
+/* Enable SCLK Out */
+#define mem_SDGCTL (SCTLE | SDRAM_CL | SDRAM_tRAS | SDRAM_tRP | SDRAM_tRCD | SDRAM_tWR | PSS)
+
+#if defined CONFIG_CLKIN_HALF
+#define CLKIN_HALF 1
+#else
+#define CLKIN_HALF 0
+#endif
+
+#if defined CONFIG_PLL_BYPASS
+#define PLL_BYPASS 1
+#else
+#define PLL_BYPASS 0
+#endif
+
+/***************************************Currently Not Being Used *********************************/
+#define flash_EBIU_AMBCTL_WAT ((CONFIG_FLASH_SPEED_BWAT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
+#define flash_EBIU_AMBCTL_RAT ((CONFIG_FLASH_SPEED_BRAT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
+#define flash_EBIU_AMBCTL_HT ((CONFIG_FLASH_SPEED_BHT * 4) / (4000000000 / CONFIG_SCLK_HZ))
+#define flash_EBIU_AMBCTL_ST ((CONFIG_FLASH_SPEED_BST * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
+#define flash_EBIU_AMBCTL_TT ((CONFIG_FLASH_SPEED_BTT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
+
+#if (flash_EBIU_AMBCTL_TT > 3)
+#define flash_EBIU_AMBCTL0_TT B0TT_4
+#endif
+#if (flash_EBIU_AMBCTL_TT == 3)
+#define flash_EBIU_AMBCTL0_TT B0TT_3
+#endif
+#if (flash_EBIU_AMBCTL_TT == 2)
+#define flash_EBIU_AMBCTL0_TT B0TT_2
+#endif
+#if (flash_EBIU_AMBCTL_TT < 2)
+#define flash_EBIU_AMBCTL0_TT B0TT_1
+#endif
+
+#if (flash_EBIU_AMBCTL_ST > 3)
+#define flash_EBIU_AMBCTL0_ST B0ST_4
+#endif
+#if (flash_EBIU_AMBCTL_ST == 3)
+#define flash_EBIU_AMBCTL0_ST B0ST_3
+#endif
+#if (flash_EBIU_AMBCTL_ST == 2)
+#define flash_EBIU_AMBCTL0_ST B0ST_2
+#endif
+#if (flash_EBIU_AMBCTL_ST < 2)
+#define flash_EBIU_AMBCTL0_ST B0ST_1
+#endif
+
+#if (flash_EBIU_AMBCTL_HT > 2)
+#define flash_EBIU_AMBCTL0_HT B0HT_3
+#endif
+#if (flash_EBIU_AMBCTL_HT == 2)
+#define flash_EBIU_AMBCTL0_HT B0HT_2
+#endif
+#if (flash_EBIU_AMBCTL_HT == 1)
+#define flash_EBIU_AMBCTL0_HT B0HT_1
+#endif
+#if (flash_EBIU_AMBCTL_HT == 0 && CONFIG_FLASH_SPEED_BHT == 0)
+#define flash_EBIU_AMBCTL0_HT B0HT_0
+#endif
+#if (flash_EBIU_AMBCTL_HT == 0 && CONFIG_FLASH_SPEED_BHT != 0)
+#define flash_EBIU_AMBCTL0_HT B0HT_1
+#endif
+
+#if (flash_EBIU_AMBCTL_WAT > 14)
+#define flash_EBIU_AMBCTL0_WAT B0WAT_15
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 14)
+#define flash_EBIU_AMBCTL0_WAT B0WAT_14
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 13)
+#define flash_EBIU_AMBCTL0_WAT B0WAT_13
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 12)
+#define flash_EBIU_AMBCTL0_WAT B0WAT_12
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 11)
+#define flash_EBIU_AMBCTL0_WAT B0WAT_11
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 10)
+#define flash_EBIU_AMBCTL0_WAT B0WAT_10
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 9)
+#define flash_EBIU_AMBCTL0_WAT B0WAT_9
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 8)
+#define flash_EBIU_AMBCTL0_WAT B0WAT_8
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 7)
+#define flash_EBIU_AMBCTL0_WAT B0WAT_7
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 6)
+#define flash_EBIU_AMBCTL0_WAT B0WAT_6
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 5)
+#define flash_EBIU_AMBCTL0_WAT B0WAT_5
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 4)
+#define flash_EBIU_AMBCTL0_WAT B0WAT_4
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 3)
+#define flash_EBIU_AMBCTL0_WAT B0WAT_3
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 2)
+#define flash_EBIU_AMBCTL0_WAT B0WAT_2
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 1)
+#define flash_EBIU_AMBCTL0_WAT B0WAT_1
+#endif
+
+#if (flash_EBIU_AMBCTL_RAT > 14)
+#define flash_EBIU_AMBCTL0_RAT B0RAT_15
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 14)
+#define flash_EBIU_AMBCTL0_RAT B0RAT_14
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 13)
+#define flash_EBIU_AMBCTL0_RAT B0RAT_13
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 12)
+#define flash_EBIU_AMBCTL0_RAT B0RAT_12
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 11)
+#define flash_EBIU_AMBCTL0_RAT B0RAT_11
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 10)
+#define flash_EBIU_AMBCTL0_RAT B0RAT_10
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 9)
+#define flash_EBIU_AMBCTL0_RAT B0RAT_9
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 8)
+#define flash_EBIU_AMBCTL0_RAT B0RAT_8
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 7)
+#define flash_EBIU_AMBCTL0_RAT B0RAT_7
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 6)
+#define flash_EBIU_AMBCTL0_RAT B0RAT_6
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 5)
+#define flash_EBIU_AMBCTL0_RAT B0RAT_5
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 4)
+#define flash_EBIU_AMBCTL0_RAT B0RAT_4
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 3)
+#define flash_EBIU_AMBCTL0_RAT B0RAT_3
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 2)
+#define flash_EBIU_AMBCTL0_RAT B0RAT_2
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 1)
+#define flash_EBIU_AMBCTL0_RAT B0RAT_1
+#endif
+
+#define flash_EBIU_AMBCTL0 \
+ (flash_EBIU_AMBCTL0_WAT | flash_EBIU_AMBCTL0_RAT | flash_EBIU_AMBCTL0_HT | \
+ flash_EBIU_AMBCTL0_ST | flash_EBIU_AMBCTL0_TT | CONFIG_FLASH_SPEED_RDYEN)
diff --git a/include/asm-blackfin/mach-bf527/mem_map.h b/include/asm-blackfin/mach-bf527/mem_map.h
new file mode 100644
index 000000000000..c5aa20102b24
--- /dev/null
+++ b/include/asm-blackfin/mach-bf527/mem_map.h
@@ -0,0 +1,98 @@
+/*
+ * file: include/asm-blackfin/mach-bf527/mem_map.h
+ * based on: include/asm-blackfin/mach-bf537/mem_map.h
+ * author: Michael Hennerich (michael.hennerich@analog.com)
+ *
+ * created:
+ * description:
+ * Memory MAP Common header file for blackfin BF527/5/2 of processors.
+ * rev:
+ *
+ * modified:
+ *
+ * bugs: enter bugs at http://blackfin.uclinux.org/
+ *
+ * this program is free software; you can redistribute it and/or modify
+ * it under the terms of the gnu general public license as published by
+ * the free software foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this program is distributed in the hope that it will be useful,
+ * but without any warranty; without even the implied warranty of
+ * merchantability or fitness for a particular purpose. see the
+ * gnu general public license for more details.
+ *
+ * you should have received a copy of the gnu general public license
+ * along with this program; see the file copying.
+ * if not, write to the free software foundation,
+ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ */
+
+#ifndef _MEM_MAP_527_H_
+#define _MEM_MAP_527_H_
+
+#define COREMMR_BASE 0xFFE00000 /* Core MMRs */
+#define SYSMMR_BASE 0xFFC00000 /* System MMRs */
+
+/* Async Memory Banks */
+#define ASYNC_BANK3_BASE 0x20300000 /* Async Bank 3 */
+#define ASYNC_BANK3_SIZE 0x00100000 /* 1M */
+#define ASYNC_BANK2_BASE 0x20200000 /* Async Bank 2 */
+#define ASYNC_BANK2_SIZE 0x00100000 /* 1M */
+#define ASYNC_BANK1_BASE 0x20100000 /* Async Bank 1 */
+#define ASYNC_BANK1_SIZE 0x00100000 /* 1M */
+#define ASYNC_BANK0_BASE 0x20000000 /* Async Bank 0 */
+#define ASYNC_BANK0_SIZE 0x00100000 /* 1M */
+
+/* Boot ROM Memory */
+
+#define BOOT_ROM_START 0xEF000000
+
+/* Level 1 Memory */
+
+/* Memory Map for ADSP-BF527 ADSP-BF525 ADSP-BF522 processors */
+
+#ifdef CONFIG_BFIN_ICACHE
+#define BFIN_ICACHESIZE (16*1024)
+#else
+#define BFIN_ICACHESIZE (0*1024)
+#endif
+
+#define L1_CODE_START 0xFFA00000
+#define L1_DATA_A_START 0xFF800000
+#define L1_DATA_B_START 0xFF900000
+
+#define L1_CODE_LENGTH 0xC000
+
+#ifdef CONFIG_BFIN_DCACHE
+
+#ifdef CONFIG_BFIN_DCACHE_BANKA
+#define DMEM_CNTR (ACACHE_BSRAM | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH (0x8000 - 0x4000)
+#define L1_DATA_B_LENGTH 0x8000
+#define BFIN_DCACHESIZE (16*1024)
+#define BFIN_DSUPBANKS 1
+#else
+#define DMEM_CNTR (ACACHE_BCACHE | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH (0x8000 - 0x4000)
+#define L1_DATA_B_LENGTH (0x8000 - 0x4000)
+#define BFIN_DCACHESIZE (32*1024)
+#define BFIN_DSUPBANKS 2
+#endif
+
+#else
+#define DMEM_CNTR (ASRAM_BSRAM | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH 0x8000
+#define L1_DATA_B_LENGTH 0x8000
+#define BFIN_DCACHESIZE (0*1024)
+#define BFIN_DSUPBANKS 0
+#endif /*CONFIG_BFIN_DCACHE */
+
+/* Scratch Pad Memory */
+
+#if defined(CONFIG_BF527) || defined(CONFIG_BF536) || defined(CONFIG_BF534)
+#define L1_SCRATCH_START 0xFFB00000
+#define L1_SCRATCH_LENGTH 0x1000
+#endif
+
+#endif /* _MEM_MAP_527_H_ */
diff --git a/include/asm-blackfin/mach-bf527/portmux.h b/include/asm-blackfin/mach-bf527/portmux.h
new file mode 100644
index 000000000000..dcf001adc63c
--- /dev/null
+++ b/include/asm-blackfin/mach-bf527/portmux.h
@@ -0,0 +1,205 @@
+#ifndef _MACH_PORTMUX_H_
+#define _MACH_PORTMUX_H_
+
+#define P_PPI0_D0 (P_DEFINED | P_IDENT(GPIO_PF0) | P_FUNCT(0))
+#define P_PPI0_D1 (P_DEFINED | P_IDENT(GPIO_PF1) | P_FUNCT(0))
+#define P_PPI0_D2 (P_DEFINED | P_IDENT(GPIO_PF2) | P_FUNCT(0))
+#define P_PPI0_D3 (P_DEFINED | P_IDENT(GPIO_PF3) | P_FUNCT(0))
+#define P_PPI0_D4 (P_DEFINED | P_IDENT(GPIO_PF4) | P_FUNCT(0))
+#define P_PPI0_D5 (P_DEFINED | P_IDENT(GPIO_PF5) | P_FUNCT(0))
+#define P_PPI0_D6 (P_DEFINED | P_IDENT(GPIO_PF6) | P_FUNCT(0))
+#define P_PPI0_D7 (P_DEFINED | P_IDENT(GPIO_PF7) | P_FUNCT(0))
+#define P_PPI0_D8 (P_DEFINED | P_IDENT(GPIO_PF8) | P_FUNCT(0))
+#define P_PPI0_D9 (P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(0))
+#define P_PPI0_D10 (P_DEFINED | P_IDENT(GPIO_PF10) | P_FUNCT(0))
+#define P_PPI0_D11 (P_DEFINED | P_IDENT(GPIO_PF11) | P_FUNCT(0))
+#define P_PPI0_D12 (P_DEFINED | P_IDENT(GPIO_PF12) | P_FUNCT(0))
+#define P_PPI0_D13 (P_DEFINED | P_IDENT(GPIO_PF13) | P_FUNCT(0))
+#define P_PPI0_D14 (P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(0))
+#define P_PPI0_D15 (P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(0))
+
+#if defined(CONFIG_BF527_SPORT0_PORTF)
+#define P_SPORT0_DRPRI (P_DEFINED | P_IDENT(GPIO_PF0) | P_FUNCT(1))
+#define P_SPORT0_RFS (P_DEFINED | P_IDENT(GPIO_PF1) | P_FUNCT(1))
+#define P_SPORT0_RSCLK (P_DEFINED | P_IDENT(GPIO_PF2) | P_FUNCT(1))
+#define P_SPORT0_DTPRI (P_DEFINED | P_IDENT(GPIO_PF3) | P_FUNCT(1))
+#define P_SPORT0_TFS (P_DEFINED | P_IDENT(GPIO_PF4) | P_FUNCT(1))
+#define P_SPORT0_TSCLK (P_DEFINED | P_IDENT(GPIO_PF5) | P_FUNCT(1))
+#define P_SPORT0_DTSEC (P_DEFINED | P_IDENT(GPIO_PF6) | P_FUNCT(1))
+#define P_SPORT0_DRSEC (P_DEFINED | P_IDENT(GPIO_PF7) | P_FUNCT(1))
+#elif defined(CONFIG_BF527_SPORT0_PORTG)
+#define P_SPORT0_DTPRI (P_DEFINED | P_IDENT(GPIO_PG6) | P_FUNCT(0))
+#define P_SPORT0_DRSEC (P_DEFINED | P_IDENT(GPIO_PG3) | P_FUNCT(1))
+#define P_SPORT0_DTSEC (P_DEFINED | P_IDENT(GPIO_PG4) | P_FUNCT(1))
+#define P_SPORT0_DRPRI (P_DEFINED | P_IDENT(GPIO_PG7) | P_FUNCT(1))
+#define P_SPORT0_RFS (P_DEFINED | P_IDENT(GPIO_PG8) | P_FUNCT(1))
+#define P_SPORT0_RSCLK (P_DEFINED | P_IDENT(GPIO_PG9) | P_FUNCT(1))
+#if defined(CONFIG_BF527_SPORT0_TSCLK_PG10)
+#define P_SPORT0_TSCLK (P_DEFINED | P_IDENT(GPIO_PG10) | P_FUNCT(1))
+#elif defined(CONFIG_BF527_SPORT0_TSCLK_PG14)
+#define P_SPORT0_TSCLK (P_DEFINED | P_IDENT(GPIO_PG14) | P_FUNCT(0))
+#endif
+#define P_SPORT0_TFS (P_DEFINED | P_IDENT(GPIO_PG15) | P_FUNCT(0))
+#endif
+
+#define P_SPORT1_DRPRI (P_DEFINED | P_IDENT(GPIO_PF8) | P_FUNCT(1))
+#define P_SPORT1_RSCLK (P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(1))
+#define P_SPORT1_RFS (P_DEFINED | P_IDENT(GPIO_PF10) | P_FUNCT(1))
+#define P_SPORT1_TFS (P_DEFINED | P_IDENT(GPIO_PF11) | P_FUNCT(1))
+#define P_SPORT1_DTPRI (P_DEFINED | P_IDENT(GPIO_PF12) | P_FUNCT(1))
+#define P_SPORT1_TSCLK (P_DEFINED | P_IDENT(GPIO_PF13) | P_FUNCT(1))
+#define P_SPORT1_DTSEC (P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(1))
+#define P_SPORT1_DRSEC (P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(1))
+
+#define P_SPI0_SSEL6 (P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(2))
+#define P_SPI0_SSEL7 (P_DEFINED | P_IDENT(GPIO_PF10) | P_FUNCT(2))
+
+#define P_SPI0_SSEL2 (P_DEFINED | P_IDENT(GPIO_PF12) | P_FUNCT(2))
+#define P_SPI0_SSEL3 (P_DEFINED | P_IDENT(GPIO_PF13) | P_FUNCT(2))
+
+#if defined(CONFIG_BF527_UART1_PORTF)
+#define P_UART1_TX (P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(2))
+#define P_UART1_RX (P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(2))
+#elif defined(CONFIG_BF527_UART1_PORTG)
+#define P_UART1_TX (P_DEFINED | P_IDENT(GPIO_PG12) | P_FUNCT(1))
+#define P_UART1_RX (P_DEFINED | P_IDENT(GPIO_PG13) | P_FUNCT(1))
+#endif
+
+#define P_HWAIT (P_DONTCARE)
+
+#define P_SPI0_SS (P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(0))
+#define P_SPI0_SSEL1 (P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(2))
+#define P_SPI0_SCK (P_DEFINED | P_IDENT(GPIO_PG2) | P_FUNCT(2))
+#define P_SPI0_MISO (P_DEFINED | P_IDENT(GPIO_PG3) | P_FUNCT(2))
+#define P_SPI0_MOSI (P_DEFINED | P_IDENT(GPIO_PG4) | P_FUNCT(2))
+#define P_TMR1 (P_DEFINED | P_IDENT(GPIO_PG5) | P_FUNCT(0))
+#define P_PPI0_FS2 (P_DEFINED | P_IDENT(GPIO_PG5) | P_FUNCT(0))
+#define P_TMR3 (P_DEFINED | P_IDENT(GPIO_PG7) | P_FUNCT(0))
+#define P_TMR4 (P_DEFINED | P_IDENT(GPIO_PG8) | P_FUNCT(0))
+#define P_TMR5 (P_DEFINED | P_IDENT(GPIO_PG9) | P_FUNCT(0))
+#define P_TMR6 (P_DEFINED | P_IDENT(GPIO_PG10) | P_FUNCT(0))
+/* #define P_TMR7 (P_DEFINED | P_IDENT(GPIO_PG11) | P_FUNCT(0)) */
+#define P_DMAR1 (P_DEFINED | P_IDENT(GPIO_PG12) | P_FUNCT(0))
+#define P_DMAR0 (P_DEFINED | P_IDENT(GPIO_PG13) | P_FUNCT(0))
+#define P_TMR2 (P_DEFINED | P_IDENT(GPIO_PG6) | P_FUNCT(1))
+#define P_TMR7 (P_DEFINED | P_IDENT(GPIO_PG11) | P_FUNCT(1))
+#define P_MDC (P_DEFINED | P_IDENT(GPIO_PG14) | P_FUNCT(1))
+#define P_RMII0_MDINT (P_DEFINED | P_IDENT(GPIO_PG15) | P_FUNCT(1))
+#define P_MII0_PHYINT (P_DEFINED | P_IDENT(GPIO_PG15) | P_FUNCT(1))
+
+#define P_PPI0_FS3 (P_DEFINED | P_IDENT(GPIO_PG6) | P_FUNCT(2))
+#define P_UART0_TX (P_DEFINED | P_IDENT(GPIO_PG7) | P_FUNCT(2))
+#define P_UART0_RX (P_DEFINED | P_IDENT(GPIO_PG8) | P_FUNCT(2))
+
+#define P_HOST_WR (P_DEFINED | P_IDENT(GPIO_PG11) | P_FUNCT(2))
+#define P_HOST_ACK (P_DEFINED | P_IDENT(GPIO_PG12) | P_FUNCT(2))
+#define P_HOST_ADDR (P_DEFINED | P_IDENT(GPIO_PG13) | P_FUNCT(2))
+#define P_HOST_RD (P_DEFINED | P_IDENT(GPIO_PG14) | P_FUNCT(2))
+#define P_HOST_CE (P_DEFINED | P_IDENT(GPIO_PG15) | P_FUNCT(2))
+
+#if defined(CONFIG_BF527_NAND_D_PORTF)
+#define P_NAND_D0 (P_DEFINED | P_IDENT(GPIO_PF0) | P_FUNCT(2))
+#define P_NAND_D1 (P_DEFINED | P_IDENT(GPIO_PF1) | P_FUNCT(2))
+#define P_NAND_D2 (P_DEFINED | P_IDENT(GPIO_PF2) | P_FUNCT(2))
+#define P_NAND_D3 (P_DEFINED | P_IDENT(GPIO_PF3) | P_FUNCT(2))
+#define P_NAND_D4 (P_DEFINED | P_IDENT(GPIO_PF4) | P_FUNCT(2))
+#define P_NAND_D5 (P_DEFINED | P_IDENT(GPIO_PF5) | P_FUNCT(2))
+#define P_NAND_D6 (P_DEFINED | P_IDENT(GPIO_PF6) | P_FUNCT(2))
+#define P_NAND_D7 (P_DEFINED | P_IDENT(GPIO_PF7) | P_FUNCT(2))
+#elif defined(CONFIG_BF527_NAND_D_PORTH)
+#define P_NAND_D0 (P_DEFINED | P_IDENT(GPIO_PH0) | P_FUNCT(0))
+#define P_NAND_D1 (P_DEFINED | P_IDENT(GPIO_PH1) | P_FUNCT(0))
+#define P_NAND_D2 (P_DEFINED | P_IDENT(GPIO_PH2) | P_FUNCT(0))
+#define P_NAND_D3 (P_DEFINED | P_IDENT(GPIO_PH3) | P_FUNCT(0))
+#define P_NAND_D4 (P_DEFINED | P_IDENT(GPIO_PH4) | P_FUNCT(0))
+#define P_NAND_D5 (P_DEFINED | P_IDENT(GPIO_PH5) | P_FUNCT(0))
+#define P_NAND_D6 (P_DEFINED | P_IDENT(GPIO_PH6) | P_FUNCT(0))
+#define P_NAND_D7 (P_DEFINED | P_IDENT(GPIO_PH7) | P_FUNCT(0))
+#endif
+
+#define P_SPI0_SSEL4 (P_DEFINED | P_IDENT(GPIO_PH8) | P_FUNCT(0))
+#define P_SPI0_SSEL5 (P_DEFINED | P_IDENT(GPIO_PH9) | P_FUNCT(0))
+#define P_NAND_CE (P_DEFINED | P_IDENT(GPIO_PH10) | P_FUNCT(0))
+#define P_NAND_WE (P_DEFINED | P_IDENT(GPIO_PH11) | P_FUNCT(0))
+#define P_NAND_RE (P_DEFINED | P_IDENT(GPIO_PH12) | P_FUNCT(0))
+#define P_NAND_RB (P_DEFINED | P_IDENT(GPIO_PH13) | P_FUNCT(0))
+#define P_NAND_CLE (P_DEFINED | P_IDENT(GPIO_PH14) | P_FUNCT(0))
+#define P_NAND_ALE (P_DEFINED | P_IDENT(GPIO_PH15) | P_FUNCT(0))
+
+#define P_HOST_D0 (P_DEFINED | P_IDENT(GPIO_PH0) | P_FUNCT(2))
+#define P_HOST_D1 (P_DEFINED | P_IDENT(GPIO_PH1) | P_FUNCT(2))
+#define P_HOST_D2 (P_DEFINED | P_IDENT(GPIO_PH2) | P_FUNCT(2))
+#define P_HOST_D3 (P_DEFINED | P_IDENT(GPIO_PH3) | P_FUNCT(2))
+#define P_HOST_D4 (P_DEFINED | P_IDENT(GPIO_PH4) | P_FUNCT(2))
+#define P_HOST_D5 (P_DEFINED | P_IDENT(GPIO_PH5) | P_FUNCT(2))
+#define P_HOST_D6 (P_DEFINED | P_IDENT(GPIO_PH6) | P_FUNCT(2))
+#define P_HOST_D7 (P_DEFINED | P_IDENT(GPIO_PH7) | P_FUNCT(2))
+#define P_HOST_D8 (P_DEFINED | P_IDENT(GPIO_PH8) | P_FUNCT(2))
+#define P_HOST_D9 (P_DEFINED | P_IDENT(GPIO_PH9) | P_FUNCT(2))
+#define P_HOST_D10 (P_DEFINED | P_IDENT(GPIO_PH10) | P_FUNCT(2))
+#define P_HOST_D11 (P_DEFINED | P_IDENT(GPIO_PH11) | P_FUNCT(2))
+#define P_HOST_D12 (P_DEFINED | P_IDENT(GPIO_PH12) | P_FUNCT(2))
+#define P_HOST_D13 (P_DEFINED | P_IDENT(GPIO_PH13) | P_FUNCT(2))
+#define P_HOST_D14 (P_DEFINED | P_IDENT(GPIO_PH14) | P_FUNCT(2))
+#define P_HOST_D15 (P_DEFINED | P_IDENT(GPIO_PH15) | P_FUNCT(2))
+
+#define P_MII0_ETxD0 (P_DEFINED | P_IDENT(GPIO_PH5) | P_FUNCT(1))
+#define P_MII0_ETxD1 (P_DEFINED | P_IDENT(GPIO_PH7) | P_FUNCT(1))
+#define P_MII0_ETxD2 (P_DEFINED | P_IDENT(GPIO_PH9) | P_FUNCT(1))
+#define P_MII0_ETxD3 (P_DEFINED | P_IDENT(GPIO_PH11) | P_FUNCT(1))
+#define P_MII0_ETxEN (P_DEFINED | P_IDENT(GPIO_PH3) | P_FUNCT(1))
+#define P_MII0_TxCLK (P_DEFINED | P_IDENT(GPIO_PH4) | P_FUNCT(1))
+#define P_MII0_COL (P_DEFINED | P_IDENT(GPIO_PH15) | P_FUNCT(1))
+#define P_MII0_ERxD0 (P_DEFINED | P_IDENT(GPIO_PH6) | P_FUNCT(1))
+#define P_MII0_ERxD1 (P_DEFINED | P_IDENT(GPIO_PH8) | P_FUNCT(1))
+#define P_MII0_ERxD2 (P_DEFINED | P_IDENT(GPIO_PH10) | P_FUNCT(1))
+#define P_MII0_ERxD3 (P_DEFINED | P_IDENT(GPIO_PH12) | P_FUNCT(1))
+#define P_MII0_ERxDV (P_DEFINED | P_IDENT(GPIO_PH14) | P_FUNCT(1))
+#define P_MII0_ERxCLK (P_DEFINED | P_IDENT(GPIO_PH13) | P_FUNCT(1))
+#define P_MII0_ERxER (P_DEFINED | P_IDENT(GPIO_PH1) | P_FUNCT(1))
+#define P_MII0_CRS (P_DEFINED | P_IDENT(GPIO_PH0) | P_FUNCT(1))
+#define P_RMII0_REF_CLK (P_DEFINED | P_IDENT(GPIO_PH4) | P_FUNCT(1))
+#define P_RMII0_CRS_DV (P_DEFINED | P_IDENT(GPIO_PH0) | P_FUNCT(1))
+#define P_MDIO (P_DEFINED | P_IDENT(GPIO_PH2) | P_FUNCT(1))
+
+#define P_TWI0_SCL (P_DONTCARE)
+#define P_TWI0_SDA (P_DONTCARE)
+#define P_PPI0_FS1 (P_DONTCARE)
+#define P_TMR0 (P_DONTCARE)
+#define P_TMRCLK (P_DONTCARE)
+#define P_PPI0_CLK (P_DONTCARE)
+
+#define P_MII0 {\
+ P_MII0_ETxD0, \
+ P_MII0_ETxD1, \
+ P_MII0_ETxD2, \
+ P_MII0_ETxD3, \
+ P_MII0_ETxEN, \
+ P_MII0_TxCLK, \
+ P_MII0_PHYINT, \
+ P_MII0_COL, \
+ P_MII0_ERxD0, \
+ P_MII0_ERxD1, \
+ P_MII0_ERxD2, \
+ P_MII0_ERxD3, \
+ P_MII0_ERxDV, \
+ P_MII0_ERxCLK, \
+ P_MII0_ERxER, \
+ P_MII0_CRS, \
+ P_MDC, \
+ P_MDIO, 0}
+
+#define P_RMII0 {\
+ P_MII0_ETxD0, \
+ P_MII0_ETxD1, \
+ P_MII0_ETxEN, \
+ P_MII0_ERxD0, \
+ P_MII0_ERxD1, \
+ P_MII0_ERxER, \
+ P_RMII0_REF_CLK, \
+ P_RMII0_MDINT, \
+ P_RMII0_CRS_DV, \
+ P_MDC, \
+ P_MDIO, 0}
+
+#endif /* _MACH_PORTMUX_H_ */
diff --git a/include/asm-blackfin/mach-bf548/bf54x-lq043.h b/include/asm-blackfin/mach-bf548/bf54x-lq043.h
new file mode 100644
index 000000000000..9c7ca62a45eb
--- /dev/null
+++ b/include/asm-blackfin/mach-bf548/bf54x-lq043.h
@@ -0,0 +1,30 @@
+#ifndef BF54X_LQ043_H
+#define BF54X_LQ043_H
+
+struct bfin_bf54xfb_val {
+ unsigned int defval;
+ unsigned int min;
+ unsigned int max;
+};
+
+struct bfin_bf54xfb_mach_info {
+ unsigned char fixed_syncs; /* do not update sync/border */
+
+ /* LCD types */
+ int type;
+
+ /* Screen size */
+ int width;
+ int height;
+
+ /* Screen info */
+ struct bfin_bf54xfb_val xres;
+ struct bfin_bf54xfb_val yres;
+ struct bfin_bf54xfb_val bpp;
+
+ /* GPIOs */
+ unsigned short disp;
+
+};
+
+#endif /* BF54X_LQ043_H */
diff --git a/include/asm-blackfin/mach-bf548/bf54x_keys.h b/include/asm-blackfin/mach-bf548/bf54x_keys.h
new file mode 100644
index 000000000000..1fb4ec77cc25
--- /dev/null
+++ b/include/asm-blackfin/mach-bf548/bf54x_keys.h
@@ -0,0 +1,17 @@
+#ifndef _BFIN_KPAD_H
+#define _BFIN_KPAD_H
+
+struct bfin_kpad_platform_data {
+ int rows;
+ int cols;
+ const unsigned int *keymap;
+ unsigned short keymapsize;
+ unsigned short repeat;
+ u32 debounce_time; /* in ns */
+ u32 coldrive_time; /* in ns */
+ u32 keyup_test_interval; /* in ms */
+};
+
+#define KEYVAL(col, row, val) (((1 << col) << 24) | ((1 << row) << 16) | (val))
+
+#endif
diff --git a/include/asm-blackfin/mach-bf548/defBF549.h b/include/asm-blackfin/mach-bf548/defBF549.h
index 50b3fe55ef0c..fcb72b41e007 100644
--- a/include/asm-blackfin/mach-bf548/defBF549.h
+++ b/include/asm-blackfin/mach-bf548/defBF549.h
@@ -1178,7 +1178,7 @@
/* Bit masks for HOST_STATUS */
-#define READY 0x1 /* DMA Ready */
+#define DMA_READY 0x1 /* DMA Ready */
#define FIFOFULL 0x2 /* FIFO Full */
#define FIFOEMPTY 0x4 /* FIFO Empty */
#define DMA_COMPLETE 0x8 /* DMA Complete */
@@ -1671,7 +1671,7 @@
/* Bit masks for MXVR_DMAx_CONFIG */
#define MDMAEN 0x1 /* DMA Channel Enable */
-#define DD 0x2 /* DMA Channel Direction */
+#define DMADD 0x2 /* DMA Channel Direction */
#define BY4SWAPEN 0x20 /* DMA Channel Four Byte Swap Enable */
#define LCHAN 0x3c0 /* DMA Channel Logical Channel */
#define BITSWAPEN 0x400 /* DMA Channel Bit Swap Enable */
diff --git a/include/asm-blackfin/mach-bf548/defBF54x_base.h b/include/asm-blackfin/mach-bf548/defBF54x_base.h
index e2632db74baa..da979cb62f7d 100644
--- a/include/asm-blackfin/mach-bf548/defBF54x_base.h
+++ b/include/asm-blackfin/mach-bf548/defBF54x_base.h
@@ -47,6 +47,10 @@
/* Debug/MP/Emulation Registers (0xFFC00014 - 0xFFC00014) */
#define CHIPID 0xffc00014
+/* CHIPID Masks */
+#define CHIPID_VERSION 0xF0000000
+#define CHIPID_FAMILY 0x0FFFF000
+#define CHIPID_MANUFACTURE 0x00000FFE
/* System Reset and Interrupt Controller (0xFFC00100 - 0xFFC00104) */
@@ -2248,6 +2252,13 @@
#define PLL_OFF 0x2 /* Disable PLL */
#define DF 0x1 /* Divide Frequency */
+/* SWRST Masks */
+#define SYSTEM_RESET 0x0007 /* Initiates A System Software Reset */
+#define DOUBLE_FAULT 0x0008 /* Core Double Fault Causes Reset */
+#define RESET_DOUBLE 0x2000 /* SW Reset Generated By Core Double-Fault */
+#define RESET_WDOG 0x4000 /* SW Reset Generated By Watchdog Timer */
+#define RESET_SOFTWARE 0x8000 /* SW Reset Occurred Since Last Read Of SWRST */
+
/* Bit masks for PLL_STAT */
#define PLL_LOCKED 0x20 /* PLL Locked Status */
@@ -3299,7 +3310,7 @@
#define MFD 0xf000 /* Multi channel Frame Delay */
#define FSDR 0x80 /* Frame Sync to Data Relationship */
-#define MCMEM 0x10 /* Multi channel Frame Mode Enable */
+#define MCMEN 0x10 /* Multi channel Frame Mode Enable */
#define MCDRXPE 0x8 /* Multi channel DMA Receive Packing */
#define MCDTXPE 0x4 /* Multi channel DMA Transmit Packing */
#define MCCRM 0x3 /* 2X Clock Recovery Mode */
diff --git a/include/asm-blackfin/mach-bf548/dma.h b/include/asm-blackfin/mach-bf548/dma.h
index 14cb10cc24ae..4d97d3aa97cd 100644
--- a/include/asm-blackfin/mach-bf548/dma.h
+++ b/include/asm-blackfin/mach-bf548/dma.h
@@ -70,5 +70,5 @@
#define MAX_BLACKFIN_DMA_CHANNEL 32
extern int channel2irq(unsigned int channel);
-extern struct dma_register *base_addr[];
+extern struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL];
#endif
diff --git a/include/asm-blackfin/mach-bf548/portmux.h b/include/asm-blackfin/mach-bf548/portmux.h
index b382deb501a7..6b485120015f 100644
--- a/include/asm-blackfin/mach-bf548/portmux.h
+++ b/include/asm-blackfin/mach-bf548/portmux.h
@@ -267,4 +267,18 @@
#define P_AMC_BG (P_DEFINED | P_IDENT(GPIO_PJ12) | P_FUNCT(0))
#define P_AMC_BGH (P_DEFINED | P_IDENT(GPIO_PJ13) | P_FUNCT(0))
+
+#define P_NAND_D0 (P_DONTCARE)
+#define P_NAND_D1 (P_DONTCARE)
+#define P_NAND_D2 (P_DONTCARE)
+#define P_NAND_D3 (P_DONTCARE)
+#define P_NAND_D4 (P_DONTCARE)
+#define P_NAND_D5 (P_DONTCARE)
+#define P_NAND_D6 (P_DONTCARE)
+#define P_NAND_D7 (P_DONTCARE)
+#define P_NAND_WE (P_DONTCARE)
+#define P_NAND_RE (P_DONTCARE)
+#define P_NAND_CLE (P_DONTCARE)
+#define P_NAND_ALE (P_DONTCARE)
+
#endif /* _MACH_PORTMUX_H_ */
diff --git a/include/asm-blackfin/mach-bf561/defBF561.h b/include/asm-blackfin/mach-bf561/defBF561.h
index bf7dc4e00065..7945e8a3a841 100644
--- a/include/asm-blackfin/mach-bf561/defBF561.h
+++ b/include/asm-blackfin/mach-bf561/defBF561.h
@@ -55,6 +55,9 @@
/* For MMR's that are reserved on Core B, set up defines to better integrate with other ports */
#define SWRST SICA_SWRST
#define SYSCR SICA_SYSCR
+#define RESET_DOUBLE (SWRST_DBL_FAULT_B|SWRST_DBL_FAULT_A)
+#define RESET_WDOG (SWRST_WDT_B|SWRST_WDT_A)
+#define RESET_SOFTWARE (SWRST_OCCURRED)
/* System Reset and Interrupt Controller registers for core A (0xFFC0 0100-0xFFC0 01FF) */
#define SICA_SWRST 0xFFC00100 /* Software Reset register */
diff --git a/include/asm-blackfin/processor.h b/include/asm-blackfin/processor.h
index 6bb3e0d4705d..c571e958558c 100644
--- a/include/asm-blackfin/processor.h
+++ b/include/asm-blackfin/processor.h
@@ -104,13 +104,13 @@ unsigned long get_wchan(struct task_struct *p);
#define cpu_relax() barrier()
/* Get the Silicon Revision of the chip */
-static inline __attribute_pure__ uint32_t bfin_revid(void)
+static inline uint32_t __pure bfin_revid(void)
{
/* stored in the upper 4 bits */
return bfin_read_CHIPID() >> 28;
}
-static inline __attribute_pure__ uint32_t bfin_compiled_revid(void)
+static inline uint32_t __pure bfin_compiled_revid(void)
{
#if defined(CONFIG_BF_REV_0_0)
return 0;
diff --git a/include/asm-blackfin/scatterlist.h b/include/asm-blackfin/scatterlist.h
index 60e07b92044c..04f448711cd0 100644
--- a/include/asm-blackfin/scatterlist.h
+++ b/include/asm-blackfin/scatterlist.h
@@ -4,7 +4,10 @@
#include <linux/mm.h>
struct scatterlist {
- struct page *page;
+#ifdef CONFIG_DEBUG_SG
+ unsigned long sg_magic;
+#endif
+ unsigned long page_link;
unsigned int offset;
dma_addr_t dma_address;
unsigned int length;
@@ -17,7 +20,6 @@ struct scatterlist {
* returns, or alternatively stop on the first sg_dma_len(sg) which
* is 0.
*/
-#define sg_address(sg) (page_address((sg)->page) + (sg)->offset)
#define sg_dma_address(sg) ((sg)->dma_address)
#define sg_dma_len(sg) ((sg)->length)
diff --git a/include/asm-blackfin/semaphore.h b/include/asm-blackfin/semaphore.h
index 94c04d7ab23e..533f90fb2e4e 100644
--- a/include/asm-blackfin/semaphore.h
+++ b/include/asm-blackfin/semaphore.h
@@ -35,7 +35,6 @@ struct semaphore {
struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
-#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
static inline void sema_init(struct semaphore *sem, int val)
{
diff --git a/include/asm-blackfin/system.h b/include/asm-blackfin/system.h
index 2b3d47d0bbb6..4a927379ee1c 100644
--- a/include/asm-blackfin/system.h
+++ b/include/asm-blackfin/system.h
@@ -128,9 +128,7 @@ extern unsigned long irq_flags;
#define mb() asm volatile ("" : : :"memory")
#define rmb() asm volatile ("" : : :"memory")
#define wmb() asm volatile ("" : : :"memory")
-#define set_rmb(var, value) do { (void) xchg(&var, value); } while (0)
-#define set_mb(var, value) set_rmb(var, value)
-#define set_wmb(var, value) do { var = value; wmb(); } while (0)
+#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
#define read_barrier_depends() do { } while(0)
diff --git a/include/asm-blackfin/tlbflush.h b/include/asm-blackfin/tlbflush.h
index 10a07ba1e011..277b400924b8 100644
--- a/include/asm-blackfin/tlbflush.h
+++ b/include/asm-blackfin/tlbflush.h
@@ -53,10 +53,4 @@ static inline void flush_tlb_kernel_page(unsigned long addr)
BUG();
}
-static inline void flush_tlb_pgtables(struct mm_struct *mm,
- unsigned long start, unsigned long end)
-{
- BUG();
-}
-
#endif
diff --git a/include/asm-blackfin/types.h b/include/asm-blackfin/types.h
index 36f8dc8c52ba..9785a6d531c6 100644
--- a/include/asm-blackfin/types.h
+++ b/include/asm-blackfin/types.h
@@ -27,9 +27,9 @@ typedef __signed__ int __s32;
typedef unsigned int __u32;
/* HK0617 -- Changes to unsigned long temporarily */
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
-typedef __signed__ long long __s64;
-typedef unsigned long long __u64;
+#if defined(__GNUC__)
+__extension__ typedef __signed__ long long __s64;
+__extension__ typedef unsigned long long __u64;
#endif
#endif /* __ASSEMBLY__ */
diff --git a/include/asm-cris/arch-v32/ide.h b/include/asm-cris/arch-v32/ide.h
index 6590f657500d..11296170d057 100644
--- a/include/asm-cris/arch-v32/ide.h
+++ b/include/asm-cris/arch-v32/ide.h
@@ -54,7 +54,7 @@ static inline unsigned long ide_default_io_base(int index)
#define SUPPORT_VLB_SYNC 0
#define IDE_ARCH_ACK_INTR
-#define ide_ack_intr(hwif) (hwif)->hw.ack_intr(hwif)
+#define ide_ack_intr(hwif) ((hwif)->ack_intr(hwif))
#endif /* __KERNEL__ */
diff --git a/include/asm-cris/atomic.h b/include/asm-cris/atomic.h
index 0b51a87e5532..2949a945876a 100644
--- a/include/asm-cris/atomic.h
+++ b/include/asm-cris/atomic.h
@@ -3,6 +3,8 @@
#ifndef __ASM_CRIS_ATOMIC__
#define __ASM_CRIS_ATOMIC__
+#include <linux/compiler.h>
+
#include <asm/system.h>
#include <asm/arch/atomic.h>
diff --git a/include/asm-cris/bitops.h b/include/asm-cris/bitops.h
index a569065113d9..e2f49c27ed29 100644
--- a/include/asm-cris/bitops.h
+++ b/include/asm-cris/bitops.h
@@ -14,6 +14,10 @@
/* Currently this is unsuitable for consumption outside the kernel. */
#ifdef __KERNEL__
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
#include <asm/arch/bitops.h>
#include <asm/system.h>
#include <asm/atomic.h>
@@ -154,6 +158,7 @@ static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/hweight.h>
#include <asm-generic/bitops/find.h>
+#include <asm-generic/bitops/lock.h>
#include <asm-generic/bitops/ext2-non-atomic.h>
diff --git a/include/asm-cris/checksum.h b/include/asm-cris/checksum.h
index 180dbf2757b0..c6c5be62c698 100644
--- a/include/asm-cris/checksum.h
+++ b/include/asm-cris/checksum.h
@@ -62,7 +62,7 @@ static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
* returns a 16-bit checksum, already complemented
*/
-static inline __sum16 int csum_tcpudp_magic(__be32 saddr, __be32 daddr,
+static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
unsigned short len,
unsigned short proto,
__wsum sum)
diff --git a/include/asm-cris/ethernet.h b/include/asm-cris/ethernet.h
index 30da58a7d00d..4d58652c3a49 100644
--- a/include/asm-cris/ethernet.h
+++ b/include/asm-cris/ethernet.h
@@ -15,4 +15,7 @@
#define SET_ETH_DUPLEX_AUTO SIOCDEVPRIVATE+3 /* Auto neg duplex */
#define SET_ETH_DUPLEX_HALF SIOCDEVPRIVATE+4 /* Full duplex */
#define SET_ETH_DUPLEX_FULL SIOCDEVPRIVATE+5 /* Half duplex */
+#define SET_ETH_ENABLE_LEDS SIOCDEVPRIVATE+6 /* Enable net LEDs */
+#define SET_ETH_DISABLE_LEDS SIOCDEVPRIVATE+7 /* Disable net LEDs */
+#define SET_ETH_AUTONEG SIOCDEVPRIVATE+8
#endif /* _CRIS_ETHERNET_H */
diff --git a/include/asm-cris/fasttimer.h b/include/asm-cris/fasttimer.h
index a3a77132ce32..8f8a8d6c9653 100644
--- a/include/asm-cris/fasttimer.h
+++ b/include/asm-cris/fasttimer.h
@@ -1,9 +1,8 @@
-/* $Id: fasttimer.h,v 1.3 2004/05/14 10:19:19 starvik Exp $
+/*
* linux/include/asm-cris/fasttimer.h
*
* Fast timers for ETRAX100LX
- * This may be useful in other OS than Linux so use 2 space indentation...
- * Copyright (C) 2000, 2002 Axis Communications AB
+ * Copyright (C) 2000-2007 Axis Communications AB
*/
#include <linux/time.h> /* struct timeval */
#include <linux/timex.h>
@@ -12,11 +11,16 @@
typedef void fast_timer_function_type(unsigned long);
+struct fasttime_t {
+ unsigned long tv_jiff; /* jiffies */
+ unsigned long tv_usec; /* microseconds */
+};
+
struct fast_timer{ /* Close to timer_list */
struct fast_timer *next;
struct fast_timer *prev;
- struct timeval tv_set;
- struct timeval tv_expires;
+ struct fasttime_t tv_set;
+ struct fasttime_t tv_expires;
unsigned long delay_us;
fast_timer_function_type *function;
unsigned long data;
@@ -38,6 +42,6 @@ int del_fast_timer(struct fast_timer * t);
void schedule_usleep(unsigned long us);
-void fast_timer_init(void);
+int fast_timer_init(void);
#endif
diff --git a/include/asm-cris/hardirq.h b/include/asm-cris/hardirq.h
index 1c13dd3faac3..74178adeb1cd 100644
--- a/include/asm-cris/hardirq.h
+++ b/include/asm-cris/hardirq.h
@@ -1,6 +1,7 @@
#ifndef __ASM_HARDIRQ_H
#define __ASM_HARDIRQ_H
+#include <asm/irq.h>
#include <linux/threads.h>
#include <linux/cache.h>
diff --git a/include/asm-cris/ipc.h b/include/asm-cris/ipc.h
deleted file mode 100644
index a46e3d9c2a3f..000000000000
--- a/include/asm-cris/ipc.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ipc.h>
diff --git a/include/asm-cris/irq_regs.h b/include/asm-cris/irq_regs.h
new file mode 100644
index 000000000000..3dd9c0b70270
--- /dev/null
+++ b/include/asm-cris/irq_regs.h
@@ -0,0 +1 @@
+#include <asm-generic/irq_regs.h>
diff --git a/include/asm-cris/posix_types.h b/include/asm-cris/posix_types.h
index 7b9ed22ab5dd..3a5e4c43eae7 100644
--- a/include/asm-cris/posix_types.h
+++ b/include/asm-cris/posix_types.h
@@ -52,7 +52,6 @@ typedef struct {
} __kernel_fsid_t;
#ifdef __KERNEL__
-#include <asm/bitops.h>
#undef __FD_SET
#define __FD_SET(fd,fdsetp) set_bit(fd, (void *)(fdsetp))
diff --git a/include/asm-cris/scatterlist.h b/include/asm-cris/scatterlist.h
index 4bdc44c4ac3d..faff53ad1f96 100644
--- a/include/asm-cris/scatterlist.h
+++ b/include/asm-cris/scatterlist.h
@@ -2,11 +2,14 @@
#define __ASM_CRIS_SCATTERLIST_H
struct scatterlist {
+#ifdef CONFIG_DEBUG_SG
+ unsigned long sg_magic;
+#endif
char * address; /* Location data is to be transferred to */
unsigned int length;
/* The following is i386 highmem junk - not used by us */
- struct page * page; /* Location for highmem page, if any */
+ unsigned long page_link;
unsigned int offset;/* for highmem, page offset */
};
diff --git a/include/asm-cris/semaphore.h b/include/asm-cris/semaphore.h
index 53f548b791c1..31a4ac448195 100644
--- a/include/asm-cris/semaphore.h
+++ b/include/asm-cris/semaphore.h
@@ -35,7 +35,6 @@ struct semaphore {
struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
-#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
static inline void sema_init(struct semaphore *sem, int val)
{
diff --git a/include/asm-cris/termbits.h b/include/asm-cris/termbits.h
index 71c1b36269b8..66e1a7492a0c 100644
--- a/include/asm-cris/termbits.h
+++ b/include/asm-cris/termbits.h
@@ -171,6 +171,19 @@ struct ktermios {
#define B115200 0010002
#define B230400 0010003
#define B460800 0010004
+
+/* Unsupported rates, but needed to avoid compile error. */
+#define B500000 0010005
+#define B576000 0010006
+#define B1000000 0010010
+#define B1152000 0010011
+#define B1500000 0010012
+#define B2000000 0010013
+#define B2500000 0010014
+#define B3000000 0010015
+#define B3500000 0010016
+#define B4000000 0010017
+
/* etrax supports these additional three baud rates */
#define B921600 0010005
#define B1843200 0010006
diff --git a/include/asm-cris/thread_info.h b/include/asm-cris/thread_info.h
index fde39f6c49c7..784668ab0fa2 100644
--- a/include/asm-cris/thread_info.h
+++ b/include/asm-cris/thread_info.h
@@ -32,6 +32,7 @@ struct thread_info {
unsigned long flags; /* low level flags */
__u32 cpu; /* current CPU */
int preempt_count; /* 0 => preemptable, <0 => BUG */
+ __u32 tls; /* TLS for this thread */
mm_segment_t addr_limit; /* thread address space:
0-0xBFFFFFFF for user-thead
@@ -79,14 +80,18 @@ struct thread_info {
* - other flags in MSW
*/
#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
-#define TIF_SIGPENDING 1 /* signal pending */
-#define TIF_NEED_RESCHED 2 /* rescheduling necessary */
+#define TIF_NOTIFY_RESUME 1 /* resumption notification requested */
+#define TIF_SIGPENDING 2 /* signal pending */
+#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
+#define TIF_RESTORE_SIGMASK 9 /* restore signal mask in do_signal() */
#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */
#define TIF_MEMDIE 17
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
+#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
+#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
#define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */
diff --git a/include/asm-cris/tlb.h b/include/asm-cris/tlb.h
index 6cc26debe40f..7724246a2601 100644
--- a/include/asm-cris/tlb.h
+++ b/include/asm-cris/tlb.h
@@ -1,6 +1,8 @@
#ifndef _CRIS_TLB_H
#define _CRIS_TLB_H
+#include <linux/pagemap.h>
+
#include <asm/arch/tlb.h>
/*
diff --git a/include/asm-cris/tlbflush.h b/include/asm-cris/tlbflush.h
index 0569612477e3..20697e7ef4f2 100644
--- a/include/asm-cris/tlbflush.h
+++ b/include/asm-cris/tlbflush.h
@@ -38,13 +38,6 @@ static inline void flush_tlb_range(struct vm_area_struct * vma, unsigned long st
flush_tlb_mm(vma->vm_mm);
}
-static inline void flush_tlb_pgtables(struct mm_struct *mm,
- unsigned long start, unsigned long end)
-{
- /* CRIS does not keep any page table caches in TLB */
-}
-
-
static inline void flush_tlb(void)
{
flush_tlb_mm(current->mm);
diff --git a/include/asm-cris/types.h b/include/asm-cris/types.h
index 84557c9bac93..5a21c42bc6c5 100644
--- a/include/asm-cris/types.h
+++ b/include/asm-cris/types.h
@@ -19,9 +19,9 @@ typedef unsigned short __u16;
typedef __signed__ int __s32;
typedef unsigned int __u32;
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
-typedef __signed__ long long __s64;
-typedef unsigned long long __u64;
+#if defined(__GNUC__)
+__extension__ typedef __signed__ long long __s64;
+__extension__ typedef unsigned long long __u64;
#endif
#endif /* __ASSEMBLY__ */
diff --git a/include/asm-cris/unistd.h b/include/asm-cris/unistd.h
index 7c90fa970c38..6f2d924f4fd6 100644
--- a/include/asm-cris/unistd.h
+++ b/include/asm-cris/unistd.h
@@ -255,6 +255,7 @@
#define __NR_io_submit 248
#define __NR_io_cancel 249
#define __NR_fadvise64 250
+/* 251 is available for reuse (was briefly sys_set_zone_reclaim) */
#define __NR_exit_group 252
#define __NR_lookup_dcookie 253
#define __NR_epoll_create 254
@@ -292,10 +293,46 @@
#define __NR_add_key 286
#define __NR_request_key 287
#define __NR_keyctl 288
+#define __NR_ioprio_set 289
+#define __NR_ioprio_get 290
+#define __NR_inotify_init 291
+#define __NR_inotify_add_watch 292
+#define __NR_inotify_rm_watch 293
+#define __NR_migrate_pages 294
+#define __NR_openat 295
+#define __NR_mkdirat 296
+#define __NR_mknodat 297
+#define __NR_fchownat 298
+#define __NR_futimesat 299
+#define __NR_fstatat64 300
+#define __NR_unlinkat 301
+#define __NR_renameat 302
+#define __NR_linkat 303
+#define __NR_symlinkat 304
+#define __NR_readlinkat 305
+#define __NR_fchmodat 306
+#define __NR_faccessat 307
+#define __NR_pselect6 308
+#define __NR_ppoll 309
+#define __NR_unshare 310
+#define __NR_set_robust_list 311
+#define __NR_get_robust_list 312
+#define __NR_splice 313
+#define __NR_sync_file_range 314
+#define __NR_tee 315
+#define __NR_vmsplice 316
+#define __NR_move_pages 317
+#define __NR_getcpu 318
+#define __NR_epoll_pwait 319
+#define __NR_utimensat 320
+#define __NR_signalfd 321
+#define __NR_timerfd 322
+#define __NR_eventfd 323
+#define __NR_fallocate 324
#ifdef __KERNEL__
-#define NR_syscalls 289
+#define NR_syscalls 325
#include <asm/arch/unistd.h>
diff --git a/include/asm-frv/bitops.h b/include/asm-frv/bitops.h
index f8560edf59ff..e29de7131b79 100644
--- a/include/asm-frv/bitops.h
+++ b/include/asm-frv/bitops.h
@@ -21,6 +21,10 @@
#ifdef __KERNEL__
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
#include <asm-generic/bitops/ffz.h>
/*
@@ -302,6 +306,7 @@ int __ilog2_u64(u64 n)
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/lock.h>
#include <asm-generic/bitops/ext2-non-atomic.h>
diff --git a/include/asm-frv/ipc.h b/include/asm-frv/ipc.h
deleted file mode 100644
index a46e3d9c2a3f..000000000000
--- a/include/asm-frv/ipc.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ipc.h>
diff --git a/include/asm-frv/irq.h b/include/asm-frv/irq.h
index 8fefd6b827aa..3a66ebd754bd 100644
--- a/include/asm-frv/irq.h
+++ b/include/asm-frv/irq.h
@@ -12,9 +12,6 @@
#ifndef _ASM_IRQ_H_
#define _ASM_IRQ_H_
-/* this number is used when no interrupt has been assigned */
-#define NO_IRQ (-1)
-
#define NR_IRQS 48
#define IRQ_BASE_CPU (0 * 16)
#define IRQ_BASE_FPGA (1 * 16)
diff --git a/include/asm-frv/scatterlist.h b/include/asm-frv/scatterlist.h
index 8e827fa853f1..2e7143b5a7ad 100644
--- a/include/asm-frv/scatterlist.h
+++ b/include/asm-frv/scatterlist.h
@@ -4,25 +4,27 @@
#include <asm/types.h>
/*
- * Drivers must set either ->address or (preferred) ->page and ->offset
+ * Drivers must set either ->address or (preferred) page and ->offset
* to indicate where data must be transferred to/from.
*
- * Using ->page is recommended since it handles highmem data as well as
+ * Using page is recommended since it handles highmem data as well as
* low mem. ->address is restricted to data which has a virtual mapping, and
- * it will go away in the future. Updating to ->page can be automated very
+ * it will go away in the future. Updating to page can be automated very
* easily -- something like
*
* sg->address = some_ptr;
*
* can be rewritten as
*
- * sg->page = virt_to_page(some_ptr);
- * sg->offset = (unsigned long) some_ptr & ~PAGE_MASK;
+ * sg_set_buf(sg, some_ptr, length);
*
* and that's it. There's no excuse for not highmem enabling YOUR driver. /jens
*/
struct scatterlist {
- struct page *page; /* Location for highmem page, if any */
+#ifdef CONFIG_DEBUG_SG
+ unsigned long sg_magic;
+#endif
+ unsigned long page_link;
unsigned int offset; /* for highmem, page offset */
dma_addr_t dma_address;
diff --git a/include/asm-frv/semaphore.h b/include/asm-frv/semaphore.h
index 09586528e007..d7aaa1911a1a 100644
--- a/include/asm-frv/semaphore.h
+++ b/include/asm-frv/semaphore.h
@@ -49,7 +49,6 @@ struct semaphore {
struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
-#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
static inline void sema_init (struct semaphore *sem, int val)
{
diff --git a/include/asm-frv/thread_info.h b/include/asm-frv/thread_info.h
index cc5433e78b52..348b8f1df17e 100644
--- a/include/asm-frv/thread_info.h
+++ b/include/asm-frv/thread_info.h
@@ -88,9 +88,8 @@ register struct thread_info *__current_thread_info asm("gr15");
({ \
struct thread_info *ret; \
\
- ret = kmalloc(THREAD_SIZE, GFP_KERNEL); \
- if (ret) \
- memset(ret, 0, THREAD_SIZE); \
+ ret = kzalloc(THREAD_SIZE, GFP_KERNEL); \
+ \
ret; \
})
#else
diff --git a/include/asm-frv/tlbflush.h b/include/asm-frv/tlbflush.h
index da3a3179a85d..7ac5eafc5d98 100644
--- a/include/asm-frv/tlbflush.h
+++ b/include/asm-frv/tlbflush.h
@@ -57,8 +57,6 @@ do { \
#define __flush_tlb_global() flush_tlb_all()
#define flush_tlb() flush_tlb_all()
#define flush_tlb_kernel_range(start, end) flush_tlb_all()
-#define flush_tlb_pgtables(mm,start,end) \
- asm volatile("movgs %0,scr0 ! movgs %0,scr1" :: "r"(ULONG_MAX) : "memory");
#else
@@ -67,7 +65,6 @@ do { \
#define flush_tlb_mm(mm) BUG()
#define flush_tlb_page(vma,addr) BUG()
#define flush_tlb_range(mm,start,end) BUG()
-#define flush_tlb_pgtables(mm,start,end) BUG()
#define flush_tlb_kernel_range(start, end) BUG()
#endif
diff --git a/include/asm-frv/types.h b/include/asm-frv/types.h
index 1b6d1923b25b..767e5ed71c4b 100644
--- a/include/asm-frv/types.h
+++ b/include/asm-frv/types.h
@@ -30,9 +30,9 @@ typedef unsigned short __u16;
typedef __signed__ int __s32;
typedef unsigned int __u32;
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
-typedef __signed__ long long __s64;
-typedef unsigned long long __u64;
+#if defined(__GNUC__)
+__extension__ typedef __signed__ long long __s64;
+__extension__ typedef unsigned long long __u64;
#endif
#endif /* __ASSEMBLY__ */
diff --git a/include/asm-generic/Kbuild b/include/asm-generic/Kbuild
index 5bfeef761649..c18110ee30f1 100644
--- a/include/asm-generic/Kbuild
+++ b/include/asm-generic/Kbuild
@@ -2,7 +2,6 @@ header-y += errno-base.h
header-y += errno.h
header-y += fcntl.h
header-y += ioctl.h
-header-y += ipc.h
header-y += mman.h
header-y += poll.h
header-y += signal.h
diff --git a/include/asm-generic/Kbuild.asm b/include/asm-generic/Kbuild.asm
index a37e95fe58d6..8fd81713cfc0 100644
--- a/include/asm-generic/Kbuild.asm
+++ b/include/asm-generic/Kbuild.asm
@@ -30,6 +30,5 @@ unifdef-y += unistd.h
unifdef-y += user.h
# These probably shouldn't be exported
-unifdef-y += shmparam.h
unifdef-y += elf.h
unifdef-y += page.h
diff --git a/include/asm-generic/bitops.h b/include/asm-generic/bitops.h
index 1f9d99193df8..15e6f253dda4 100644
--- a/include/asm-generic/bitops.h
+++ b/include/asm-generic/bitops.h
@@ -19,9 +19,14 @@
#ifdef __KERNEL__
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/ffs.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/lock.h>
#include <asm-generic/bitops/ext2-non-atomic.h>
#include <asm-generic/bitops/ext2-atomic.h>
diff --git a/include/asm-generic/bitops/atomic.h b/include/asm-generic/bitops/atomic.h
index cd8a9641bd66..4657f3e410fc 100644
--- a/include/asm-generic/bitops/atomic.h
+++ b/include/asm-generic/bitops/atomic.h
@@ -3,9 +3,6 @@
#include <asm/types.h>
-#define BITOP_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
-#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
-
#ifdef CONFIG_SMP
#include <asm/spinlock.h>
#include <asm/cache.h> /* we use L1_CACHE_BYTES */
@@ -66,8 +63,8 @@ extern raw_spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned;
*/
static inline void set_bit(int nr, volatile unsigned long *addr)
{
- unsigned long mask = BITOP_MASK(nr);
- unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
+ unsigned long mask = BIT_MASK(nr);
+ unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
unsigned long flags;
_atomic_spin_lock_irqsave(p, flags);
@@ -87,8 +84,8 @@ static inline void set_bit(int nr, volatile unsigned long *addr)
*/
static inline void clear_bit(int nr, volatile unsigned long *addr)
{
- unsigned long mask = BITOP_MASK(nr);
- unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
+ unsigned long mask = BIT_MASK(nr);
+ unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
unsigned long flags;
_atomic_spin_lock_irqsave(p, flags);
@@ -108,8 +105,8 @@ static inline void clear_bit(int nr, volatile unsigned long *addr)
*/
static inline void change_bit(int nr, volatile unsigned long *addr)
{
- unsigned long mask = BITOP_MASK(nr);
- unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
+ unsigned long mask = BIT_MASK(nr);
+ unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
unsigned long flags;
_atomic_spin_lock_irqsave(p, flags);
@@ -128,8 +125,8 @@ static inline void change_bit(int nr, volatile unsigned long *addr)
*/
static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
{
- unsigned long mask = BITOP_MASK(nr);
- unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
+ unsigned long mask = BIT_MASK(nr);
+ unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
unsigned long old;
unsigned long flags;
@@ -152,8 +149,8 @@ static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
*/
static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
{
- unsigned long mask = BITOP_MASK(nr);
- unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
+ unsigned long mask = BIT_MASK(nr);
+ unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
unsigned long old;
unsigned long flags;
@@ -175,8 +172,8 @@ static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
*/
static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
{
- unsigned long mask = BITOP_MASK(nr);
- unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
+ unsigned long mask = BIT_MASK(nr);
+ unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
unsigned long old;
unsigned long flags;
diff --git a/include/asm-generic/bitops/lock.h b/include/asm-generic/bitops/lock.h
new file mode 100644
index 000000000000..308a9e22c802
--- /dev/null
+++ b/include/asm-generic/bitops/lock.h
@@ -0,0 +1,45 @@
+#ifndef _ASM_GENERIC_BITOPS_LOCK_H_
+#define _ASM_GENERIC_BITOPS_LOCK_H_
+
+/**
+ * test_and_set_bit_lock - Set a bit and return its old value, for lock
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is atomic and provides acquire barrier semantics.
+ * It can be used to implement bit locks.
+ */
+#define test_and_set_bit_lock(nr, addr) test_and_set_bit(nr, addr)
+
+/**
+ * clear_bit_unlock - Clear a bit in memory, for unlock
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ *
+ * This operation is atomic and provides release barrier semantics.
+ */
+#define clear_bit_unlock(nr, addr) \
+do { \
+ smp_mb__before_clear_bit(); \
+ clear_bit(nr, addr); \
+} while (0)
+
+/**
+ * __clear_bit_unlock - Clear a bit in memory, for unlock
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ *
+ * This operation is like clear_bit_unlock, however it is not atomic.
+ * It does provide release barrier semantics so it can be used to unlock
+ * a bit lock, however it would only be used if no other CPU can modify
+ * any bits in the memory until the lock is released (a good example is
+ * if the bit lock itself protects access to the other bits in the word).
+ */
+#define __clear_bit_unlock(nr, addr) \
+do { \
+ smp_mb(); \
+ __clear_bit(nr, addr); \
+} while (0)
+
+#endif /* _ASM_GENERIC_BITOPS_LOCK_H_ */
+
diff --git a/include/asm-generic/bitops/non-atomic.h b/include/asm-generic/bitops/non-atomic.h
index 46a825cf2ae1..697cc2b7e0f0 100644
--- a/include/asm-generic/bitops/non-atomic.h
+++ b/include/asm-generic/bitops/non-atomic.h
@@ -3,9 +3,6 @@
#include <asm/types.h>
-#define BITOP_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
-#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
-
/**
* __set_bit - Set a bit in memory
* @nr: the bit to set
@@ -17,16 +14,16 @@
*/
static inline void __set_bit(int nr, volatile unsigned long *addr)
{
- unsigned long mask = BITOP_MASK(nr);
- unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
+ unsigned long mask = BIT_MASK(nr);
+ unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
*p |= mask;
}
static inline void __clear_bit(int nr, volatile unsigned long *addr)
{
- unsigned long mask = BITOP_MASK(nr);
- unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
+ unsigned long mask = BIT_MASK(nr);
+ unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
*p &= ~mask;
}
@@ -42,8 +39,8 @@ static inline void __clear_bit(int nr, volatile unsigned long *addr)
*/
static inline void __change_bit(int nr, volatile unsigned long *addr)
{
- unsigned long mask = BITOP_MASK(nr);
- unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
+ unsigned long mask = BIT_MASK(nr);
+ unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
*p ^= mask;
}
@@ -59,8 +56,8 @@ static inline void __change_bit(int nr, volatile unsigned long *addr)
*/
static inline int __test_and_set_bit(int nr, volatile unsigned long *addr)
{
- unsigned long mask = BITOP_MASK(nr);
- unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
+ unsigned long mask = BIT_MASK(nr);
+ unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
unsigned long old = *p;
*p = old | mask;
@@ -78,8 +75,8 @@ static inline int __test_and_set_bit(int nr, volatile unsigned long *addr)
*/
static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
{
- unsigned long mask = BITOP_MASK(nr);
- unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
+ unsigned long mask = BIT_MASK(nr);
+ unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
unsigned long old = *p;
*p = old & ~mask;
@@ -90,8 +87,8 @@ static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
static inline int __test_and_change_bit(int nr,
volatile unsigned long *addr)
{
- unsigned long mask = BITOP_MASK(nr);
- unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
+ unsigned long mask = BIT_MASK(nr);
+ unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
unsigned long old = *p;
*p = old ^ mask;
@@ -105,7 +102,7 @@ static inline int __test_and_change_bit(int nr,
*/
static inline int test_bit(int nr, const volatile unsigned long *addr)
{
- return 1UL & (addr[BITOP_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
+ return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
}
#endif /* _ASM_GENERIC_BITOPS_NON_ATOMIC_H_ */
diff --git a/include/asm-generic/ipc.h b/include/asm-generic/ipc.h
deleted file mode 100644
index a40407a165ce..000000000000
--- a/include/asm-generic/ipc.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef _ASM_GENERIC_IPC_H
-#define _ASM_GENERIC_IPC_H
-/*
- * These are used to wrap system calls.
- *
- * See architecture code for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf __user *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif /* _ASM_GENERIC_IPC_H */
diff --git a/include/asm-generic/memory_model.h b/include/asm-generic/memory_model.h
index 30d8d33491dd..52226e14bd7d 100644
--- a/include/asm-generic/memory_model.h
+++ b/include/asm-generic/memory_model.h
@@ -46,6 +46,12 @@
__pgdat->node_start_pfn; \
})
+#elif defined(CONFIG_SPARSEMEM_VMEMMAP)
+
+/* memmap is virtually contigious. */
+#define __pfn_to_page(pfn) (vmemmap + (pfn))
+#define __page_to_pfn(page) ((page) - vmemmap)
+
#elif defined(CONFIG_SPARSEMEM)
/*
* Note: section's mem_map is encorded to reflect its start_pfn.
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index 5f0d797d33fd..44ef329531c3 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -125,10 +125,6 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres
#define pgd_offset_gate(mm, addr) pgd_offset(mm, addr)
#endif
-#ifndef __HAVE_ARCH_LAZY_MMU_PROT_UPDATE
-#define lazy_mmu_prot_update(pte) do { } while (0)
-#endif
-
#ifndef __HAVE_ARCH_MOVE_PTE
#define move_pte(pte, prot, old_addr, new_addr) (pte)
#endif
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 5615440027ec..9f584cc5c5fb 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -12,7 +12,11 @@
/* .data section */
#define DATA_DATA \
*(.data) \
- *(.data.init.refok)
+ *(.data.init.refok) \
+ . = ALIGN(8); \
+ VMLINUX_SYMBOL(__start___markers) = .; \
+ *(__markers) \
+ VMLINUX_SYMBOL(__stop___markers) = .;
#define RO_DATA(align) \
. = ALIGN((align)); \
@@ -20,6 +24,7 @@
VMLINUX_SYMBOL(__start_rodata) = .; \
*(.rodata) *(.rodata.*) \
*(__vermagic) /* Kernel version magic */ \
+ *(__markers_strings) /* Markers: strings */ \
} \
\
.rodata1 : AT(ADDR(.rodata1) - LOAD_OFFSET) { \
diff --git a/include/asm-h8300/bitops.h b/include/asm-h8300/bitops.h
index d76299c98b81..cb18e3b0aa94 100644
--- a/include/asm-h8300/bitops.h
+++ b/include/asm-h8300/bitops.h
@@ -10,6 +10,11 @@
#include <asm/system.h>
#ifdef __KERNEL__
+
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
/*
* Function prototypes to keep gcc -Wall happy
*/
@@ -194,6 +199,7 @@ static __inline__ unsigned long __ffs(unsigned long word)
#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/lock.h>
#include <asm-generic/bitops/ext2-non-atomic.h>
#include <asm-generic/bitops/ext2-atomic.h>
#include <asm-generic/bitops/minix.h>
diff --git a/include/asm-h8300/io.h b/include/asm-h8300/io.h
index 91b7487cb7ae..7543a57b4ea1 100644
--- a/include/asm-h8300/io.h
+++ b/include/asm-h8300/io.h
@@ -264,12 +264,6 @@ static inline void *ioremap_fullcache(unsigned long physaddr, unsigned long size
extern void iounmap(void *addr);
-/* Nothing to do */
-
-#define dma_cache_inv(_start,_size) do { } while (0)
-#define dma_cache_wback(_start,_size) do { } while (0)
-#define dma_cache_wback_inv(_start,_size) do { } while (0)
-
/* H8/300 internal I/O functions */
static __inline__ unsigned char ctrl_inb(unsigned long addr)
{
diff --git a/include/asm-h8300/ipc.h b/include/asm-h8300/ipc.h
deleted file mode 100644
index a46e3d9c2a3f..000000000000
--- a/include/asm-h8300/ipc.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ipc.h>
diff --git a/include/asm-h8300/scatterlist.h b/include/asm-h8300/scatterlist.h
index 985fdf54eaca..d3ecdd87ac90 100644
--- a/include/asm-h8300/scatterlist.h
+++ b/include/asm-h8300/scatterlist.h
@@ -4,7 +4,10 @@
#include <asm/types.h>
struct scatterlist {
- struct page *page;
+#ifdef CONFIG_DEBUG_SG
+ unsigned long sg_magic;
+#endif
+ unsigned long page_link;
unsigned int offset;
dma_addr_t dma_address;
unsigned int length;
diff --git a/include/asm-h8300/semaphore.h b/include/asm-h8300/semaphore.h
index 81bae2a99192..f3ffff83ff09 100644
--- a/include/asm-h8300/semaphore.h
+++ b/include/asm-h8300/semaphore.h
@@ -39,7 +39,6 @@ struct semaphore {
struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
-#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
static inline void sema_init (struct semaphore *sem, int val)
{
diff --git a/include/asm-h8300/system.h b/include/asm-h8300/system.h
index 7807018f8500..2c1e83f7b419 100644
--- a/include/asm-h8300/system.h
+++ b/include/asm-h8300/system.h
@@ -82,8 +82,7 @@ asmlinkage void resume(void);
#define mb() asm volatile ("" : : :"memory")
#define rmb() asm volatile ("" : : :"memory")
#define wmb() asm volatile ("" : : :"memory")
-#define set_rmb(var, value) do { xchg(&var, value); } while (0)
-#define set_mb(var, value) set_rmb(var, value)
+#define set_mb(var, value) do { xchg(&var, value); } while (0)
#ifdef CONFIG_SMP
#define smp_mb() mb()
diff --git a/include/asm-h8300/tlbflush.h b/include/asm-h8300/tlbflush.h
index 9a2c5c9fd700..41c148a9208e 100644
--- a/include/asm-h8300/tlbflush.h
+++ b/include/asm-h8300/tlbflush.h
@@ -52,10 +52,4 @@ static inline void flush_tlb_kernel_page(unsigned long addr)
BUG();
}
-static inline void flush_tlb_pgtables(struct mm_struct *mm,
- unsigned long start, unsigned long end)
-{
- BUG();
-}
-
#endif /* _H8300_TLBFLUSH_H */
diff --git a/include/asm-h8300/types.h b/include/asm-h8300/types.h
index 2a8b1b2be782..56566e2a09fd 100644
--- a/include/asm-h8300/types.h
+++ b/include/asm-h8300/types.h
@@ -27,9 +27,9 @@ typedef unsigned short __u16;
typedef __signed__ int __s32;
typedef unsigned int __u32;
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
-typedef __signed__ long long __s64;
-typedef unsigned long long __u64;
+#if defined(__GNUC__)
+__extension__ typedef __signed__ long long __s64;
+__extension__ typedef unsigned long long __u64;
#endif
/*
diff --git a/include/asm-ia64/bitops.h b/include/asm-ia64/bitops.h
index 6cc517e212a9..a977affaebec 100644
--- a/include/asm-ia64/bitops.h
+++ b/include/asm-ia64/bitops.h
@@ -9,6 +9,10 @@
* O(1) scheduler patch
*/
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
#include <linux/compiler.h>
#include <linux/types.h>
#include <asm/intrinsics.h>
@@ -94,6 +98,38 @@ clear_bit (int nr, volatile void *addr)
}
/**
+ * clear_bit_unlock - Clears a bit in memory with release
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ *
+ * clear_bit_unlock() is atomic and may not be reordered. It does
+ * contain a memory barrier suitable for unlock type operations.
+ */
+static __inline__ void
+clear_bit_unlock (int nr, volatile void *addr)
+{
+ __u32 mask, old, new;
+ volatile __u32 *m;
+ CMPXCHG_BUGCHECK_DECL
+
+ m = (volatile __u32 *) addr + (nr >> 5);
+ mask = ~(1 << (nr & 31));
+ do {
+ CMPXCHG_BUGCHECK(m);
+ old = *m;
+ new = old & mask;
+ } while (cmpxchg_rel(m, old, new) != old);
+}
+
+/**
+ * __clear_bit_unlock - Non-atomically clear a bit with release
+ *
+ * This is like clear_bit_unlock, but the implementation may use a non-atomic
+ * store (this one uses an atomic, however).
+ */
+#define __clear_bit_unlock clear_bit_unlock
+
+/**
* __clear_bit - Clears a bit in memory (non-atomic version)
*/
static __inline__ void
@@ -170,6 +206,15 @@ test_and_set_bit (int nr, volatile void *addr)
}
/**
+ * test_and_set_bit_lock - Set a bit and return its old value for lock
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This is the same as test_and_set_bit on ia64
+ */
+#define test_and_set_bit_lock test_and_set_bit
+
+/**
* __test_and_set_bit - Set a bit and return its old value
* @nr: Bit to set
* @addr: Address to count from
diff --git a/include/asm-ia64/cacheflush.h b/include/asm-ia64/cacheflush.h
index 4906916d715b..afcfbda76e20 100644
--- a/include/asm-ia64/cacheflush.h
+++ b/include/asm-ia64/cacheflush.h
@@ -7,8 +7,8 @@
*/
#include <linux/page-flags.h>
+#include <linux/bitops.h>
-#include <asm/bitops.h>
#include <asm/page.h>
/*
diff --git a/include/asm-ia64/dma-mapping.h b/include/asm-ia64/dma-mapping.h
index 6299b51575bb..f1735a22d0ea 100644
--- a/include/asm-ia64/dma-mapping.h
+++ b/include/asm-ia64/dma-mapping.h
@@ -6,6 +6,7 @@
* David Mosberger-Tang <davidm@hpl.hp.com>
*/
#include <asm/machvec.h>
+#include <linux/scatterlist.h>
#define dma_alloc_coherent platform_dma_alloc_coherent
/* coherent mem. is cheap */
diff --git a/include/asm-ia64/elf.h b/include/asm-ia64/elf.h
index 25f9835d5459..f10e29b60b00 100644
--- a/include/asm-ia64/elf.h
+++ b/include/asm-ia64/elf.h
@@ -192,6 +192,7 @@ extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *);
#define GATE_EHDR ((const struct elfhdr *) GATE_ADDR)
+/* update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT entries changes */
#define ARCH_DLINFO \
do { \
extern char __kernel_syscall_via_epc[]; \
diff --git a/include/asm-ia64/ide.h b/include/asm-ia64/ide.h
index e928675de352..1ccf23809329 100644
--- a/include/asm-ia64/ide.h
+++ b/include/asm-ia64/ide.h
@@ -46,7 +46,6 @@ static inline unsigned long ide_default_io_base(int index)
}
}
-#define IDE_ARCH_OBSOLETE_INIT
#define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */
#ifdef CONFIG_PCI
diff --git a/include/asm-ia64/io.h b/include/asm-ia64/io.h
index eb17a8692967..4ebed77aa472 100644
--- a/include/asm-ia64/io.h
+++ b/include/asm-ia64/io.h
@@ -435,10 +435,6 @@ extern void memcpy_fromio(void *dst, const volatile void __iomem *src, long n);
extern void memcpy_toio(volatile void __iomem *dst, const void *src, long n);
extern void memset_io(volatile void __iomem *s, int c, long n);
-#define dma_cache_inv(_start,_size) do { } while (0)
-#define dma_cache_wback(_start,_size) do { } while (0)
-#define dma_cache_wback_inv(_start,_size) do { } while (0)
-
# endif /* __KERNEL__ */
/*
diff --git a/include/asm-ia64/kdebug.h b/include/asm-ia64/kdebug.h
index 320cd8e754ea..35e49407d06c 100644
--- a/include/asm-ia64/kdebug.h
+++ b/include/asm-ia64/kdebug.h
@@ -26,21 +26,6 @@
* 2005-Oct Keith Owens <kaos@sgi.com>. Expand notify_die to cover more
* events.
*/
-#include <linux/notifier.h>
-
-/*
- * These are only here because kprobes.c wants them to implement a
- * blatant layering violation. Will hopefully go away soon once all
- * architectures are updated.
- */
-static inline int register_page_fault_notifier(struct notifier_block *nb)
-{
- return 0;
-}
-static inline int unregister_page_fault_notifier(struct notifier_block *nb)
-{
- return 0;
-}
enum die_val {
DIE_BREAK = 1,
diff --git a/include/asm-ia64/kprobes.h b/include/asm-ia64/kprobes.h
index 067d9dea68f9..a93ce9ef07ff 100644
--- a/include/asm-ia64/kprobes.h
+++ b/include/asm-ia64/kprobes.h
@@ -83,7 +83,7 @@ struct kprobe_ctlblk {
};
#define ARCH_SUPPORTS_KRETPROBES
-#define ARCH_INACTIVE_KPROBE_COUNT 1
+#define kretprobe_blacklist_size 0
#define SLOT0_OPCODE_SHIFT (37)
#define SLOT1_p1_OPCODE_SHIFT (37 - (64-46))
diff --git a/include/asm-ia64/meminit.h b/include/asm-ia64/meminit.h
index 3a62878e84f3..f93308f54b61 100644
--- a/include/asm-ia64/meminit.h
+++ b/include/asm-ia64/meminit.h
@@ -35,7 +35,7 @@ extern void find_memory (void);
extern void reserve_memory (void);
extern void find_initrd (void);
extern int filter_rsvd_memory (unsigned long start, unsigned long end, void *arg);
-extern void efi_memmap_init(unsigned long *, unsigned long *);
+extern unsigned long efi_memmap_init(unsigned long *s, unsigned long *e);
extern int find_max_min_low_pfn (unsigned long , unsigned long, void *);
extern unsigned long vmcore_find_descriptor_size(unsigned long address);
diff --git a/include/asm-ia64/numa.h b/include/asm-ia64/numa.h
index 7d5e2ccc37a0..6a8a27cfae3e 100644
--- a/include/asm-ia64/numa.h
+++ b/include/asm-ia64/numa.h
@@ -24,6 +24,7 @@
extern u16 cpu_to_node_map[NR_CPUS] __cacheline_aligned;
extern cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned;
+extern pg_data_t *pgdat_list[MAX_NUMNODES];
/* Stuff below this line could be architecture independent */
diff --git a/include/asm-ia64/pal.h b/include/asm-ia64/pal.h
index abfcb3a2588f..8a695d3407d2 100644
--- a/include/asm-ia64/pal.h
+++ b/include/asm-ia64/pal.h
@@ -1379,10 +1379,11 @@ struct pal_features_s;
static inline s64
ia64_pal_proc_get_features (u64 *features_avail,
u64 *features_status,
- u64 *features_control)
+ u64 *features_control,
+ u64 features_set)
{
struct ia64_pal_retval iprv;
- PAL_CALL_PHYS(iprv, PAL_PROC_GET_FEATURES, 0, 0, 0);
+ PAL_CALL_PHYS(iprv, PAL_PROC_GET_FEATURES, 0, features_set, 0);
if (iprv.status == 0) {
*features_avail = iprv.v0;
*features_status = iprv.v1;
diff --git a/include/asm-ia64/percpu.h b/include/asm-ia64/percpu.h
index 43a7aac414e0..c4f1e328a5ba 100644
--- a/include/asm-ia64/percpu.h
+++ b/include/asm-ia64/percpu.h
@@ -46,7 +46,7 @@
#ifdef CONFIG_SMP
extern unsigned long __per_cpu_offset[NR_CPUS];
-#define per_cpu_offset(x) (__per_cpu_offset(x))
+#define per_cpu_offset(x) (__per_cpu_offset[x])
/* Equal to __per_cpu_offset[smp_processor_id()], but faster to access: */
DECLARE_PER_CPU(unsigned long, local_per_cpu_offset);
diff --git a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h
index de6d01e24dd0..e6204f14f614 100644
--- a/include/asm-ia64/pgtable.h
+++ b/include/asm-ia64/pgtable.h
@@ -150,7 +150,7 @@
# ifndef __ASSEMBLY__
#include <linux/sched.h> /* for mm_struct */
-#include <asm/bitops.h>
+#include <linux/bitops.h>
#include <asm/cacheflush.h>
#include <asm/mmu_context.h>
#include <asm/processor.h>
@@ -223,12 +223,6 @@ ia64_phys_addr_valid (unsigned long addr)
* page table.
*/
-/*
- * On some architectures, special things need to be done when setting
- * the PTE in a page table. Nothing special needs to be on IA-64.
- */
-#define set_pte(ptep, pteval) (*(ptep) = (pteval))
-#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
#define VMALLOC_START (RGN_BASE(RGN_GATE) + 0x200000000UL)
#ifdef CONFIG_VIRTUAL_MEM_MAP
@@ -236,8 +230,14 @@ ia64_phys_addr_valid (unsigned long addr)
# define VMALLOC_END vmalloc_end
extern unsigned long vmalloc_end;
#else
+#if defined(CONFIG_SPARSEMEM) && defined(CONFIG_SPARSEMEM_VMEMMAP)
+/* SPARSEMEM_VMEMMAP uses half of vmalloc... */
+# define VMALLOC_END (RGN_BASE(RGN_GATE) + (1UL << (4*PAGE_SHIFT - 10)))
+# define vmemmap ((struct page *)VMALLOC_END)
+#else
# define VMALLOC_END (RGN_BASE(RGN_GATE) + (1UL << (4*PAGE_SHIFT - 9)))
#endif
+#endif
/* fs/proc/kcore.c */
#define kc_vaddr_to_offset(v) ((v) - RGN_BASE(RGN_GATE))
@@ -315,6 +315,36 @@ ia64_phys_addr_valid (unsigned long addr)
#define pte_mkhuge(pte) (__pte(pte_val(pte)))
/*
+ * Because ia64's Icache and Dcache is not coherent (on a cpu), we need to
+ * sync icache and dcache when we insert *new* executable page.
+ * __ia64_sync_icache_dcache() check Pg_arch_1 bit and flush icache
+ * if necessary.
+ *
+ * set_pte() is also called by the kernel, but we can expect that the kernel
+ * flushes icache explicitly if necessary.
+ */
+#define pte_present_exec_user(pte)\
+ ((pte_val(pte) & (_PAGE_P | _PAGE_PL_MASK | _PAGE_AR_RX)) == \
+ (_PAGE_P | _PAGE_PL_3 | _PAGE_AR_RX))
+
+extern void __ia64_sync_icache_dcache(pte_t pteval);
+static inline void set_pte(pte_t *ptep, pte_t pteval)
+{
+ /* page is present && page is user && page is executable
+ * && (page swapin or new page or page migraton
+ * || copy_on_write with page copying.)
+ */
+ if (pte_present_exec_user(pteval) &&
+ (!pte_present(*ptep) ||
+ pte_pfn(*ptep) != pte_pfn(pteval)))
+ /* load_module() calles flush_icache_range() explicitly*/
+ __ia64_sync_icache_dcache(pteval);
+ *ptep = pteval;
+}
+
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
+
+/*
* Make page protection values cacheable, uncacheable, or write-
* combining. Note that "protection" is really a misnomer here as the
* protection value contains the memory attribute bits, dirty bits, and
@@ -483,12 +513,6 @@ extern struct page *zero_page_memmap_ptr;
#define HUGETLB_PGDIR_MASK (~(HUGETLB_PGDIR_SIZE-1))
#endif
-/*
- * IA-64 doesn't have any external MMU info: the page tables contain all the necessary
- * information. However, we use this routine to take care of any (delayed) i-cache
- * flushing that may be necessary.
- */
-extern void lazy_mmu_prot_update (pte_t pte);
#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
/*
@@ -578,7 +602,7 @@ extern void lazy_mmu_prot_update (pte_t pte);
#define __HAVE_ARCH_PTEP_SET_WRPROTECT
#define __HAVE_ARCH_PTE_SAME
#define __HAVE_ARCH_PGD_OFFSET_GATE
-#define __HAVE_ARCH_LAZY_MMU_PROT_UPDATE
+
#ifndef CONFIG_PGTABLE_4
#include <asm-generic/pgtable-nopud.h>
diff --git a/include/asm-ia64/scatterlist.h b/include/asm-ia64/scatterlist.h
index a452ea24205a..d6f57874041d 100644
--- a/include/asm-ia64/scatterlist.h
+++ b/include/asm-ia64/scatterlist.h
@@ -9,7 +9,10 @@
#include <asm/types.h>
struct scatterlist {
- struct page *page;
+#ifdef CONFIG_DEBUG_SG
+ unsigned long sg_magic;
+#endif
+ unsigned long page_link;
unsigned int offset;
unsigned int length; /* buffer length */
@@ -30,4 +33,6 @@ struct scatterlist {
#define sg_dma_len(sg) ((sg)->dma_length)
#define sg_dma_address(sg) ((sg)->dma_address)
+#define ARCH_HAS_SG_CHAIN
+
#endif /* _ASM_IA64_SCATTERLIST_H */
diff --git a/include/asm-ia64/semaphore.h b/include/asm-ia64/semaphore.h
index f483eeb95dd1..d8393d11288d 100644
--- a/include/asm-ia64/semaphore.h
+++ b/include/asm-ia64/semaphore.h
@@ -28,7 +28,6 @@ struct semaphore {
struct semaphore name = __SEMAPHORE_INITIALIZER(name, count)
#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name, 1)
-#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name, 0)
static inline void
sema_init (struct semaphore *sem, int val)
diff --git a/include/asm-ia64/smp.h b/include/asm-ia64/smp.h
index 6314b29e8c4d..4fa733dd417a 100644
--- a/include/asm-ia64/smp.h
+++ b/include/asm-ia64/smp.h
@@ -14,8 +14,8 @@
#include <linux/threads.h>
#include <linux/kernel.h>
#include <linux/cpumask.h>
+#include <linux/bitops.h>
-#include <asm/bitops.h>
#include <asm/io.h>
#include <asm/param.h>
#include <asm/processor.h>
@@ -58,9 +58,8 @@ extern char no_int_routing __devinitdata;
extern cpumask_t cpu_online_map;
extern cpumask_t cpu_core_map[NR_CPUS];
-extern cpumask_t cpu_sibling_map[NR_CPUS];
+DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
extern int smp_num_siblings;
-extern int smp_num_cpucores;
extern void __iomem *ipi_base_addr;
extern unsigned char smp_int_redirect;
diff --git a/include/asm-ia64/spinlock.h b/include/asm-ia64/spinlock.h
index ff857e31738a..0229fb95fb38 100644
--- a/include/asm-ia64/spinlock.h
+++ b/include/asm-ia64/spinlock.h
@@ -11,9 +11,9 @@
#include <linux/compiler.h>
#include <linux/kernel.h>
+#include <linux/bitops.h>
#include <asm/atomic.h>
-#include <asm/bitops.h>
#include <asm/intrinsics.h>
#include <asm/system.h>
diff --git a/include/asm-ia64/system.h b/include/asm-ia64/system.h
index 91bb8e00066c..595112bca3cc 100644
--- a/include/asm-ia64/system.h
+++ b/include/asm-ia64/system.h
@@ -32,6 +32,8 @@
#include <linux/kernel.h>
#include <linux/types.h>
+#define AT_VECTOR_SIZE_ARCH 2 /* entries in ARCH_DLINFO */
+
struct pci_vector_struct {
__u16 segment; /* PCI Segment number */
__u16 bus; /* PCI Bus number */
diff --git a/include/asm-ia64/tlbflush.h b/include/asm-ia64/tlbflush.h
index e37f9fbf33af..80bcb0a38e8a 100644
--- a/include/asm-ia64/tlbflush.h
+++ b/include/asm-ia64/tlbflush.h
@@ -84,19 +84,6 @@ flush_tlb_page (struct vm_area_struct *vma, unsigned long addr)
}
/*
- * Flush the TLB entries mapping the virtually mapped linear page
- * table corresponding to address range [START-END).
- */
-static inline void
-flush_tlb_pgtables (struct mm_struct *mm, unsigned long start, unsigned long end)
-{
- /*
- * Deprecated. The virtual page table is now flushed via the normal gather/flush
- * interface (see tlb.h).
- */
-}
-
-/*
* Flush the local TLB. Invoked from another cpu using an IPI.
*/
#ifdef CONFIG_SMP
diff --git a/include/asm-ia64/topology.h b/include/asm-ia64/topology.h
index 233f1caae048..2d67b72b18d0 100644
--- a/include/asm-ia64/topology.h
+++ b/include/asm-ia64/topology.h
@@ -112,7 +112,7 @@ void build_cpu_to_node_map(void);
#define topology_physical_package_id(cpu) (cpu_data(cpu)->socket_id)
#define topology_core_id(cpu) (cpu_data(cpu)->core_id)
#define topology_core_siblings(cpu) (cpu_core_map[cpu])
-#define topology_thread_siblings(cpu) (cpu_sibling_map[cpu])
+#define topology_thread_siblings(cpu) (per_cpu(cpu_sibling_map, cpu))
#define smt_capable() (smp_num_siblings > 1)
#endif
diff --git a/include/asm-m32r/bitops.h b/include/asm-m32r/bitops.h
index 66ab672162cd..6dc9b81bf9f3 100644
--- a/include/asm-m32r/bitops.h
+++ b/include/asm-m32r/bitops.h
@@ -11,6 +11,10 @@
* Copyright (C) 2004 Hirokazu Takata <takata at linux-m32r.org>
*/
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
#include <linux/compiler.h>
#include <asm/assembler.h>
#include <asm/system.h>
@@ -255,6 +259,7 @@ static __inline__ int test_and_change_bit(int nr, volatile void * addr)
#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/ffs.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/lock.h>
#endif /* __KERNEL__ */
diff --git a/include/asm-m32r/ide.h b/include/asm-m32r/ide.h
index 4672a49e8760..5d2044e529ab 100644
--- a/include/asm-m32r/ide.h
+++ b/include/asm-m32r/ide.h
@@ -65,7 +65,6 @@ static __inline__ unsigned long ide_default_io_base(int index)
}
}
-#define IDE_ARCH_OBSOLETE_INIT
#define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */
#ifdef CONFIG_BLK_DEV_IDEPCI
diff --git a/include/asm-m32r/ipc.h b/include/asm-m32r/ipc.h
deleted file mode 100644
index a46e3d9c2a3f..000000000000
--- a/include/asm-m32r/ipc.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ipc.h>
diff --git a/include/asm-m32r/pgtable.h b/include/asm-m32r/pgtable.h
index 92d7266783fd..86505387be08 100644
--- a/include/asm-m32r/pgtable.h
+++ b/include/asm-m32r/pgtable.h
@@ -21,9 +21,9 @@
#ifndef __ASSEMBLY__
#include <linux/threads.h>
+#include <linux/bitops.h>
#include <asm/processor.h>
#include <asm/addrspace.h>
-#include <asm/bitops.h>
#include <asm/page.h>
struct mm_struct;
diff --git a/include/asm-m32r/ptrace.h b/include/asm-m32r/ptrace.h
index 632b4ce4269a..a0755b982028 100644
--- a/include/asm-m32r/ptrace.h
+++ b/include/asm-m32r/ptrace.h
@@ -120,7 +120,10 @@ struct pt_regs {
#include <asm/m32r.h> /* M32R_PSW_BSM, M32R_PSW_BPM */
-#define __ARCH_SYS_PTRACE 1
+struct task_struct;
+extern void init_debug_traps(struct task_struct *);
+#define arch_ptrace_attach(child) \
+ init_debug_traps(child)
#if defined(CONFIG_ISA_M32R2) || defined(CONFIG_CHIP_VDEC2)
#define user_mode(regs) ((M32R_PSW_BPM & (regs)->psw) != 0)
diff --git a/include/asm-m32r/scatterlist.h b/include/asm-m32r/scatterlist.h
index 352415ff5eb9..1ed372c73d0b 100644
--- a/include/asm-m32r/scatterlist.h
+++ b/include/asm-m32r/scatterlist.h
@@ -4,9 +4,12 @@
#include <asm/types.h>
struct scatterlist {
+#ifdef CONFIG_DEBUG_SG
+ unsigned long sg_magic;
+#endif
char * address; /* Location data is to be transferred to, NULL for
* highmem page */
- struct page * page; /* Location for highmem page, if any */
+ unsigned long page_link;
unsigned int offset;/* for highmem, page offset */
dma_addr_t dma_address;
diff --git a/include/asm-m32r/semaphore.h b/include/asm-m32r/semaphore.h
index 41e45d7b87ef..b5bf95a6f2b4 100644
--- a/include/asm-m32r/semaphore.h
+++ b/include/asm-m32r/semaphore.h
@@ -35,7 +35,6 @@ struct semaphore {
struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
-#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
static inline void sema_init (struct semaphore *sem, int val)
{
diff --git a/include/asm-m32r/thread_info.h b/include/asm-m32r/thread_info.h
index b7ccc3e68604..c039820dba7c 100644
--- a/include/asm-m32r/thread_info.h
+++ b/include/asm-m32r/thread_info.h
@@ -100,9 +100,8 @@ static inline struct thread_info *current_thread_info(void)
({ \
struct thread_info *ret; \
\
- ret = kmalloc(THREAD_SIZE, GFP_KERNEL); \
- if (ret) \
- memset(ret, 0, THREAD_SIZE); \
+ ret = kzalloc(THREAD_SIZE, GFP_KERNEL); \
+ \
ret; \
})
#else
diff --git a/include/asm-m32r/tlbflush.h b/include/asm-m32r/tlbflush.h
index 3d37ac002bcc..0ef95307784e 100644
--- a/include/asm-m32r/tlbflush.h
+++ b/include/asm-m32r/tlbflush.h
@@ -12,7 +12,6 @@
* - flush_tlb_page(vma, vmaddr) flushes one page
* - flush_tlb_range(vma, start, end) flushes a range of pages
* - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
- * - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
*/
extern void local_flush_tlb_all(void);
@@ -93,8 +92,6 @@ static __inline__ void __flush_tlb_all(void)
);
}
-#define flush_tlb_pgtables(mm, start, end) do { } while (0)
-
extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
#endif /* _ASM_M32R_TLBFLUSH_H */
diff --git a/include/asm-m32r/types.h b/include/asm-m32r/types.h
index 27d3eb539c50..b64c16639a7b 100644
--- a/include/asm-m32r/types.h
+++ b/include/asm-m32r/types.h
@@ -19,9 +19,9 @@ typedef unsigned short __u16;
typedef __signed__ int __s32;
typedef unsigned int __u32;
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
-typedef __signed__ long long __s64;
-typedef unsigned long long __u64;
+#if defined(__GNUC__)
+__extension__ typedef __signed__ long long __s64;
+__extension__ typedef unsigned long long __u64;
#endif
#endif /* __ASSEMBLY__ */
diff --git a/include/asm-m68k/bitops.h b/include/asm-m68k/bitops.h
index 1a61fdb56aaf..2976b5d68e96 100644
--- a/include/asm-m68k/bitops.h
+++ b/include/asm-m68k/bitops.h
@@ -8,6 +8,10 @@
* for more details.
*/
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
#include <linux/compiler.h>
/*
@@ -314,6 +318,7 @@ static inline int fls(int x)
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/lock.h>
/* Bitmap functions for the minix filesystem */
diff --git a/include/asm-m68k/floppy.h b/include/asm-m68k/floppy.h
index 45dc908932a3..697d50393dd0 100644
--- a/include/asm-m68k/floppy.h
+++ b/include/asm-m68k/floppy.h
@@ -31,9 +31,6 @@ asmlinkage irqreturn_t floppy_hardint(int irq, void *dev_id);
#define FLOPPY0_TYPE (MACH_IS_Q40 ? 6 : 4)
#define FLOPPY1_TYPE 0
-#define FLOPPY_MOTOR_MASK 0xf0
-
-
/* basically PC init + set use_virtual_dma */
#define FDC1 m68k_floppy_init()
diff --git a/include/asm-m68k/ide.h b/include/asm-m68k/ide.h
index f9ffb2cbbae8..909c6dfd3851 100644
--- a/include/asm-m68k/ide.h
+++ b/include/asm-m68k/ide.h
@@ -137,7 +137,7 @@ ide_get_lock(irq_handler_t handler, void *data)
#endif /* CONFIG_BLK_DEV_FALCON_IDE */
#define IDE_ARCH_ACK_INTR
-#define ide_ack_intr(hwif) ((hwif)->hw.ack_intr ? (hwif)->hw.ack_intr(hwif) : 1)
+#define ide_ack_intr(hwif) ((hwif)->ack_intr ? (hwif)->ack_intr(hwif) : 1)
#endif /* __KERNEL__ */
#endif /* _M68K_IDE_H */
diff --git a/include/asm-m68k/io.h b/include/asm-m68k/io.h
index 47bb9cf107b7..baf4f9b8acfc 100644
--- a/include/asm-m68k/io.h
+++ b/include/asm-m68k/io.h
@@ -384,12 +384,6 @@ static inline void __iomem *ioremap_fullcache(unsigned long physaddr,
return __ioremap(physaddr, size, IOMAP_FULL_CACHING);
}
-
-/* m68k caches aren't DMA coherent */
-extern void dma_cache_wback_inv(unsigned long start, unsigned long size);
-extern void dma_cache_wback(unsigned long start, unsigned long size);
-extern void dma_cache_inv(unsigned long start, unsigned long size);
-
static inline void memset_io(volatile void __iomem *addr, unsigned char val, int count)
{
__builtin_memset((void __force *) addr, val, count);
diff --git a/include/asm-m68k/ipc.h b/include/asm-m68k/ipc.h
deleted file mode 100644
index a46e3d9c2a3f..000000000000
--- a/include/asm-m68k/ipc.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ipc.h>
diff --git a/include/asm-m68k/scatterlist.h b/include/asm-m68k/scatterlist.h
index 24887a2d9c7b..d3a7a0edfeca 100644
--- a/include/asm-m68k/scatterlist.h
+++ b/include/asm-m68k/scatterlist.h
@@ -4,7 +4,10 @@
#include <linux/types.h>
struct scatterlist {
- struct page *page;
+#ifdef CONFIG_DEBUG_SG
+ unsigned long sg_magic;
+#endif
+ unsigned long page_link;
unsigned int offset;
unsigned int length;
diff --git a/include/asm-m68k/semaphore.h b/include/asm-m68k/semaphore.h
index fd4c7cc3d3be..64d6b119bb0a 100644
--- a/include/asm-m68k/semaphore.h
+++ b/include/asm-m68k/semaphore.h
@@ -40,7 +40,6 @@ struct semaphore {
struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
-#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
static inline void sema_init(struct semaphore *sem, int val)
{
diff --git a/include/asm-m68k/tlbflush.h b/include/asm-m68k/tlbflush.h
index 31678831ee47..17707ec315e2 100644
--- a/include/asm-m68k/tlbflush.h
+++ b/include/asm-m68k/tlbflush.h
@@ -92,11 +92,6 @@ static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end
flush_tlb_all();
}
-static inline void flush_tlb_pgtables(struct mm_struct *mm,
- unsigned long start, unsigned long end)
-{
-}
-
#else
@@ -219,11 +214,6 @@ static inline void flush_tlb_kernel_page (unsigned long addr)
sun3_put_segmap (addr & ~(SUN3_PMEG_SIZE - 1), SUN3_INVALID_PMEG);
}
-static inline void flush_tlb_pgtables(struct mm_struct *mm,
- unsigned long start, unsigned long end)
-{
-}
-
#endif
#endif /* _M68K_TLBFLUSH_H */
diff --git a/include/asm-m68k/types.h b/include/asm-m68k/types.h
index b5a1febc97d4..c35c09d93b66 100644
--- a/include/asm-m68k/types.h
+++ b/include/asm-m68k/types.h
@@ -27,9 +27,9 @@ typedef unsigned short __u16;
typedef __signed__ int __s32;
typedef unsigned int __u32;
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
-typedef __signed__ long long __s64;
-typedef unsigned long long __u64;
+#if defined(__GNUC__)
+__extension__ typedef __signed__ long long __s64;
+__extension__ typedef unsigned long long __u64;
#endif
#endif /* __ASSEMBLY__ */
diff --git a/include/asm-m68knommu/bitops.h b/include/asm-m68knommu/bitops.h
index 7d6075d9b5cb..f8dfb7ba2e25 100644
--- a/include/asm-m68knommu/bitops.h
+++ b/include/asm-m68knommu/bitops.h
@@ -10,6 +10,10 @@
#ifdef __KERNEL__
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
#include <asm-generic/bitops/ffs.h>
#include <asm-generic/bitops/__ffs.h>
#include <asm-generic/bitops/sched.h>
@@ -160,6 +164,7 @@ static __inline__ int __test_bit(int nr, const volatile unsigned long * addr)
#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/lock.h>
static __inline__ int ext2_set_bit(int nr, volatile void * addr)
{
diff --git a/include/asm-m68knommu/dma.h b/include/asm-m68knommu/dma.h
index 3338001abb40..3f20419c633a 100644
--- a/include/asm-m68knommu/dma.h
+++ b/include/asm-m68knommu/dma.h
@@ -39,6 +39,8 @@
#define MAX_M68K_DMA_CHANNELS 4
#elif defined(CONFIG_M5272)
#define MAX_M68K_DMA_CHANNELS 1
+#elif defined(CONFIG_M532x)
+#define MAX_M68K_DMA_CHANNELS 0
#else
#define MAX_M68K_DMA_CHANNELS 2
#endif
diff --git a/include/asm-m68knommu/io.h b/include/asm-m68knommu/io.h
index 8df4cee2a0cd..653d9b2d7ddf 100644
--- a/include/asm-m68knommu/io.h
+++ b/include/asm-m68knommu/io.h
@@ -165,12 +165,6 @@ static inline void *ioremap_fullcache(unsigned long physaddr, unsigned long size
extern void iounmap(void *addr);
-/* Nothing to do */
-
-#define dma_cache_inv(_start,_size) do { } while (0)
-#define dma_cache_wback(_start,_size) do { } while (0)
-#define dma_cache_wback_inv(_start,_size) do { } while (0)
-
/* Pages to physical address... */
#define page_to_phys(page) ((page - mem_map) << PAGE_SHIFT)
#define page_to_bus(page) ((page - mem_map) << PAGE_SHIFT)
diff --git a/include/asm-m68knommu/ipc.h b/include/asm-m68knommu/ipc.h
deleted file mode 100644
index a46e3d9c2a3f..000000000000
--- a/include/asm-m68knommu/ipc.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ipc.h>
diff --git a/include/asm-m68knommu/machdep.h b/include/asm-m68knommu/machdep.h
index 708d7863ba68..1cf26d240d83 100644
--- a/include/asm-m68knommu/machdep.h
+++ b/include/asm-m68knommu/machdep.h
@@ -3,9 +3,13 @@
#include <linux/interrupt.h>
-extern void (*mach_sched_init) (irq_handler_t handler);
-/* machine dependent timer functions */
-extern unsigned long (*mach_gettimeoffset)(void);
+/* Hardware clock functions */
+extern void hw_timer_init(void);
+extern unsigned long hw_timer_offset(void);
+
+extern irqreturn_t arch_timer_interrupt(int irq, void *dummy);
+
+/* Machine dependent time handling */
extern void (*mach_gettod)(int *year, int *mon, int *day, int *hour,
int *min, int *sec);
extern int (*mach_set_clock_mmss)(unsigned long);
@@ -16,6 +20,5 @@ extern void (*mach_halt)( void );
extern void (*mach_power_off)( void );
extern void config_BSP(char *command, int len);
-extern void (*mach_tick)(void);
#endif /* _M68KNOMMU_MACHDEP_H */
diff --git a/include/asm-m68knommu/mcfuart.h b/include/asm-m68knommu/mcfuart.h
index dc0146c5258b..873d0805219c 100644
--- a/include/asm-m68knommu/mcfuart.h
+++ b/include/asm-m68knommu/mcfuart.h
@@ -51,6 +51,16 @@
#endif
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+
+struct mcf_platform_uart {
+ unsigned long mapbase; /* Physical address base */
+ void __iomem *membase; /* Virtual address if mapped */
+ unsigned int irq; /* Interrupt vector */
+ unsigned int uartclk; /* UART clock rate */
+};
+
/*
* Define the ColdFire UART register set addresses.
*/
diff --git a/include/asm-m68knommu/module.h b/include/asm-m68knommu/module.h
index 57e95cc01ad5..2e45ab50b232 100644
--- a/include/asm-m68knommu/module.h
+++ b/include/asm-m68knommu/module.h
@@ -1 +1,11 @@
-#include <asm-m68k/module.h>
+#ifndef ASM_M68KNOMMU_MODULE_H
+#define ASM_M68KNOMMU_MODULE_H
+
+struct mod_arch_specific {
+};
+
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Sym Elf32_Sym
+#define Elf_Ehdr Elf32_Ehdr
+
+#endif /* ASM_M68KNOMMU_MODULE_H */
diff --git a/include/asm-m68knommu/scatterlist.h b/include/asm-m68knommu/scatterlist.h
index 4da79d3d3f34..afc4788b0d2c 100644
--- a/include/asm-m68knommu/scatterlist.h
+++ b/include/asm-m68knommu/scatterlist.h
@@ -5,13 +5,15 @@
#include <asm/types.h>
struct scatterlist {
- struct page *page;
+#ifdef CONFIG_DEBUG_SG
+ unsigned long sg_magic;
+#endif
+ unsigned long page_link;
unsigned int offset;
dma_addr_t dma_address;
unsigned int length;
};
-#define sg_address(sg) (page_address((sg)->page) + (sg)->offset)
#define sg_dma_address(sg) ((sg)->dma_address)
#define sg_dma_len(sg) ((sg)->length)
diff --git a/include/asm-m68knommu/semaphore.h b/include/asm-m68knommu/semaphore.h
index 5cc1fdd86f50..5779eb6c0689 100644
--- a/include/asm-m68knommu/semaphore.h
+++ b/include/asm-m68knommu/semaphore.h
@@ -39,7 +39,6 @@ struct semaphore {
struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
-#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
static inline void sema_init (struct semaphore *sem, int val)
{
diff --git a/include/asm-m68knommu/system.h b/include/asm-m68knommu/system.h
index 5da43a5d12a3..15b4c7d45c94 100644
--- a/include/asm-m68knommu/system.h
+++ b/include/asm-m68knommu/system.h
@@ -104,8 +104,7 @@ asmlinkage void resume(void);
#define mb() asm volatile ("" : : :"memory")
#define rmb() asm volatile ("" : : :"memory")
#define wmb() asm volatile ("" : : :"memory")
-#define set_rmb(var, value) do { xchg(&var, value); } while (0)
-#define set_mb(var, value) set_rmb(var, value)
+#define set_mb(var, value) do { xchg(&var, value); } while (0)
#ifdef CONFIG_SMP
#define smp_mb() mb()
@@ -253,8 +252,7 @@ cmpxchg(volatile int *p, int old, int new)
"); \
})
#elif defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || \
- defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3) || \
- defined(CONFIG_CLEOPATRA)
+ defined(CONFIG_SECUREEDGEMP3) || defined(CONFIG_CLEOPATRA)
#define HARD_RESET_NOW() ({ \
asm(" \
movew #0x2700, %sr; \
diff --git a/include/asm-m68knommu/tlbflush.h b/include/asm-m68knommu/tlbflush.h
index de858db28b00..a470cfb803eb 100644
--- a/include/asm-m68knommu/tlbflush.h
+++ b/include/asm-m68knommu/tlbflush.h
@@ -52,10 +52,4 @@ static inline void flush_tlb_kernel_page(unsigned long addr)
BUG();
}
-static inline void flush_tlb_pgtables(struct mm_struct *mm,
- unsigned long start, unsigned long end)
-{
- BUG();
-}
-
#endif /* _M68KNOMMU_TLBFLUSH_H */
diff --git a/include/asm-m68knommu/uaccess.h b/include/asm-m68knommu/uaccess.h
index 9ed9169a8849..68bbe9b312f1 100644
--- a/include/asm-m68knommu/uaccess.h
+++ b/include/asm-m68knommu/uaccess.h
@@ -170,10 +170,12 @@ static inline long strnlen_user(const char *src, long n)
*/
static inline unsigned long
-clear_user(void *to, unsigned long n)
+__clear_user(void *to, unsigned long n)
{
memset(to, 0, n);
return 0;
}
+#define clear_user(to,n) __clear_user(to,n)
+
#endif /* _M68KNOMMU_UACCESS_H */
diff --git a/include/asm-m68knommu/unistd.h b/include/asm-m68knommu/unistd.h
index eb1b566793fe..27c2f9bb4dbd 100644
--- a/include/asm-m68knommu/unistd.h
+++ b/include/asm-m68knommu/unistd.h
@@ -185,8 +185,8 @@
#define __NR_rt_sigtimedwait 177
#define __NR_rt_sigqueueinfo 178
#define __NR_rt_sigsuspend 179
-#define __NR_pread 180
-#define __NR_pwrite 181
+#define __NR_pread64 180
+#define __NR_pwrite64 181
#define __NR_lchown 182
#define __NR_getcwd 183
#define __NR_capget 184
diff --git a/include/asm-mips/bitops.h b/include/asm-mips/bitops.h
index 899357a72ac4..ec75ce4cdb8c 100644
--- a/include/asm-mips/bitops.h
+++ b/include/asm-mips/bitops.h
@@ -9,6 +9,10 @@
#ifndef _ASM_BITOPS_H
#define _ASM_BITOPS_H
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
#include <linux/compiler.h>
#include <linux/irqflags.h>
#include <linux/types.h>
@@ -172,6 +176,20 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
}
/*
+ * clear_bit_unlock - Clears a bit in memory
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ *
+ * clear_bit() is atomic and implies release semantics before the memory
+ * operation. It can be used for an unlock.
+ */
+static inline void clear_bit_unlock(unsigned long nr, volatile unsigned long *addr)
+{
+ smp_mb__before_clear_bit();
+ clear_bit(nr, addr);
+}
+
+/*
* change_bit - Toggle a bit in memory
* @nr: Bit to change
* @addr: Address to start counting from
@@ -240,6 +258,8 @@ static inline int test_and_set_bit(unsigned long nr,
unsigned short bit = nr & SZLONG_MASK;
unsigned long res;
+ smp_llsc_mb();
+
if (cpu_has_llsc && R10000_LLSC_WAR) {
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
unsigned long temp;
@@ -295,6 +315,73 @@ static inline int test_and_set_bit(unsigned long nr,
}
/*
+ * test_and_set_bit_lock - Set a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is atomic and implies acquire ordering semantics
+ * after the memory operation.
+ */
+static inline int test_and_set_bit_lock(unsigned long nr,
+ volatile unsigned long *addr)
+{
+ unsigned short bit = nr & SZLONG_MASK;
+ unsigned long res;
+
+ if (cpu_has_llsc && R10000_LLSC_WAR) {
+ unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
+ unsigned long temp;
+
+ __asm__ __volatile__(
+ " .set mips3 \n"
+ "1: " __LL "%0, %1 # test_and_set_bit \n"
+ " or %2, %0, %3 \n"
+ " " __SC "%2, %1 \n"
+ " beqzl %2, 1b \n"
+ " and %2, %0, %3 \n"
+ " .set mips0 \n"
+ : "=&r" (temp), "=m" (*m), "=&r" (res)
+ : "r" (1UL << bit), "m" (*m)
+ : "memory");
+ } else if (cpu_has_llsc) {
+ unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
+ unsigned long temp;
+
+ __asm__ __volatile__(
+ " .set push \n"
+ " .set noreorder \n"
+ " .set mips3 \n"
+ "1: " __LL "%0, %1 # test_and_set_bit \n"
+ " or %2, %0, %3 \n"
+ " " __SC "%2, %1 \n"
+ " beqz %2, 2f \n"
+ " and %2, %0, %3 \n"
+ " .subsection 2 \n"
+ "2: b 1b \n"
+ " nop \n"
+ " .previous \n"
+ " .set pop \n"
+ : "=&r" (temp), "=m" (*m), "=&r" (res)
+ : "r" (1UL << bit), "m" (*m)
+ : "memory");
+ } else {
+ volatile unsigned long *a = addr;
+ unsigned long mask;
+ unsigned long flags;
+
+ a += nr >> SZLONG_LOG;
+ mask = 1UL << bit;
+ raw_local_irq_save(flags);
+ res = (mask & *a);
+ *a |= mask;
+ raw_local_irq_restore(flags);
+ }
+
+ smp_llsc_mb();
+
+ return res != 0;
+}
+/*
* test_and_clear_bit - Clear a bit and return its old value
* @nr: Bit to clear
* @addr: Address to count from
@@ -308,6 +395,8 @@ static inline int test_and_clear_bit(unsigned long nr,
unsigned short bit = nr & SZLONG_MASK;
unsigned long res;
+ smp_llsc_mb();
+
if (cpu_has_llsc && R10000_LLSC_WAR) {
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
unsigned long temp;
@@ -396,6 +485,8 @@ static inline int test_and_change_bit(unsigned long nr,
unsigned short bit = nr & SZLONG_MASK;
unsigned long res;
+ smp_llsc_mb();
+
if (cpu_has_llsc && R10000_LLSC_WAR) {
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
unsigned long temp;
@@ -453,6 +544,21 @@ static inline int test_and_change_bit(unsigned long nr,
#include <asm-generic/bitops/non-atomic.h>
/*
+ * __clear_bit_unlock - Clears a bit in memory
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ *
+ * __clear_bit() is non-atomic and implies release semantics before the memory
+ * operation. It can be used for an unlock if no other CPUs can concurrently
+ * modify other bits in the word.
+ */
+static inline void __clear_bit_unlock(unsigned long nr, volatile unsigned long *addr)
+{
+ smp_mb();
+ __clear_bit(nr, addr);
+}
+
+/*
* Return the bit position (0..63) of the most significant 1 bit in a word
* Returns -1 if no 1 bit exists
*/
diff --git a/include/asm-mips/cpu-info.h b/include/asm-mips/cpu-info.h
index 94f1c8172360..ed5c02c6afbb 100644
--- a/include/asm-mips/cpu-info.h
+++ b/include/asm-mips/cpu-info.h
@@ -54,6 +54,7 @@ struct cpuinfo_mips {
struct cache_desc dcache; /* Primary D or combined I/D cache */
struct cache_desc scache; /* Secondary cache */
struct cache_desc tcache; /* Tertiary/split secondary cache */
+ int srsets; /* Shadow register sets */
#if defined(CONFIG_MIPS_MT_SMTC)
/*
* In the MIPS MT "SMTC" model, each TC is considered
diff --git a/include/asm-mips/floppy.h b/include/asm-mips/floppy.h
index a62d0990c8ae..992d232adc83 100644
--- a/include/asm-mips/floppy.h
+++ b/include/asm-mips/floppy.h
@@ -34,8 +34,6 @@ static inline void fd_cacheflush(char * addr, long size)
#define N_FDC 1 /* do you *really* want a second controller? */
#define N_DRIVE 8
-#define FLOPPY_MOTOR_MASK 0xf0
-
/*
* The DMA channel used by the floppy controller cannot access data at
* addresses >= 16MB
diff --git a/include/asm-mips/fpu.h b/include/asm-mips/fpu.h
index 483685b1592e..e59d4c039661 100644
--- a/include/asm-mips/fpu.h
+++ b/include/asm-mips/fpu.h
@@ -12,12 +12,12 @@
#include <linux/sched.h>
#include <linux/thread_info.h>
+#include <linux/bitops.h>
#include <asm/mipsregs.h>
#include <asm/cpu.h>
#include <asm/cpu-features.h>
#include <asm/hazards.h>
-#include <asm/bitops.h>
#include <asm/processor.h>
#include <asm/current.h>
diff --git a/include/asm-mips/gt64120.h b/include/asm-mips/gt64120.h
index 4bf8e28f8850..e64b41093c49 100644
--- a/include/asm-mips/gt64120.h
+++ b/include/asm-mips/gt64120.h
@@ -21,6 +21,8 @@
#ifndef _ASM_GT64120_H
#define _ASM_GT64120_H
+#include <linux/clocksource.h>
+
#include <asm/addrspace.h>
#include <asm/byteorder.h>
@@ -572,4 +574,7 @@
#define GT_READ(ofs) le32_to_cpu(__GT_READ(ofs))
#define GT_WRITE(ofs, data) __GT_WRITE(ofs, cpu_to_le32(data))
+extern void gt641xx_set_base_clock(unsigned int clock);
+extern int gt641xx_timer0_state(void);
+
#endif /* _ASM_GT64120_H */
diff --git a/include/asm-mips/i8253.h b/include/asm-mips/i8253.h
index 8f689d7df6b1..032ca73f181b 100644
--- a/include/asm-mips/i8253.h
+++ b/include/asm-mips/i8253.h
@@ -2,29 +2,18 @@
* Machine specific IO port address definition for generic.
* Written by Osamu Tomita <tomita@cinet.co.jp>
*/
-#ifndef _MACH_IO_PORTS_H
-#define _MACH_IO_PORTS_H
+#ifndef __ASM_I8253_H
+#define __ASM_I8253_H
+
+#include <linux/spinlock.h>
/* i8253A PIT registers */
#define PIT_MODE 0x43
#define PIT_CH0 0x40
#define PIT_CH2 0x42
-/* i8259A PIC registers */
-#define PIC_MASTER_CMD 0x20
-#define PIC_MASTER_IMR 0x21
-#define PIC_MASTER_ISR PIC_MASTER_CMD
-#define PIC_MASTER_POLL PIC_MASTER_ISR
-#define PIC_MASTER_OCW3 PIC_MASTER_ISR
-#define PIC_SLAVE_CMD 0xa0
-#define PIC_SLAVE_IMR 0xa1
-
-/* i8259A PIC related value */
-#define PIC_CASCADE_IR 2
-#define MASTER_ICW4_DEFAULT 0x01
-#define SLAVE_ICW4_DEFAULT 0x01
-#define PIC_ICW4_AEOI 2
+extern spinlock_t i8253_lock;
extern void setup_pit_timer(void);
-#endif /* !_MACH_IO_PORTS_H */
+#endif /* __ASM_I8253_H */
diff --git a/include/asm-mips/io.h b/include/asm-mips/io.h
index 2cd8323c8586..e62058b0d28c 100644
--- a/include/asm-mips/io.h
+++ b/include/asm-mips/io.h
@@ -554,6 +554,8 @@ static inline void memcpy_toio(volatile void __iomem *dst, const void *src, int
* caches. Dirty lines of the caches may be written back or simply
* be discarded. This operation is necessary before dma operations
* to the memory.
+ *
+ * This API used to be exported; it now is for arch code internal use only.
*/
#ifdef CONFIG_DMA_NONCOHERENT
diff --git a/include/asm-mips/ip32/crime.h b/include/asm-mips/ip32/crime.h
index a13702fafa85..7c36b0e5b1c6 100644
--- a/include/asm-mips/ip32/crime.h
+++ b/include/asm-mips/ip32/crime.h
@@ -17,9 +17,6 @@
*/
#define CRIME_BASE 0x14000000 /* physical */
-#undef BIT
-#define BIT(x) (1UL << (x))
-
struct sgi_crime {
volatile unsigned long id;
#define CRIME_ID_MASK 0xff
diff --git a/include/asm-mips/ip32/ip32_ints.h b/include/asm-mips/ip32/ip32_ints.h
index c3c280e3d591..ab5612f90f6f 100644
--- a/include/asm-mips/ip32/ip32_ints.h
+++ b/include/asm-mips/ip32/ip32_ints.h
@@ -9,86 +9,106 @@
#ifndef __ASM_IP32_INTS_H
#define __ASM_IP32_INTS_H
+#include <asm/irq.h>
+
/*
* This list reflects the assignment of interrupt numbers to
* interrupting events. Order is fairly irrelevant to handling
* priority. This differs from irix.
*/
-/* CPU */
-#define IP32_R4K_TIMER_IRQ 0
+enum ip32_irq_no {
+ /*
+ * CPU interrupts are 0 ... 7
+ */
+
+ CRIME_IRQ_BASE = MIPS_CPU_IRQ_BASE,
-/* MACE */
-#define MACE_VID_IN1_IRQ 1
-#define MACE_VID_IN2_IRQ 2
-#define MACE_VID_OUT_IRQ 3
-#define MACE_ETHERNET_IRQ 4
-/* SUPERIO, MISC, and AUDIO are MACEISA */
-#define MACE_PCI_BRIDGE_IRQ 8
+ /*
+ * MACE
+ */
+ MACE_VID_IN1_IRQ = CRIME_IRQ_BASE,
+ MACE_VID_IN2_IRQ,
+ MACE_VID_OUT_IRQ,
+ MACE_ETHERNET_IRQ,
+ /* SUPERIO, MISC, and AUDIO are MACEISA */
+ __MACE_SUPERIO,
+ __MACE_MISC,
+ __MACE_AUDIO,
+ MACE_PCI_BRIDGE_IRQ,
-/* MACEPCI */
-#define MACEPCI_SCSI0_IRQ 9
-#define MACEPCI_SCSI1_IRQ 10
-#define MACEPCI_SLOT0_IRQ 11
-#define MACEPCI_SLOT1_IRQ 12
-#define MACEPCI_SLOT2_IRQ 13
-#define MACEPCI_SHARED0_IRQ 14
-#define MACEPCI_SHARED1_IRQ 15
-#define MACEPCI_SHARED2_IRQ 16
+ /*
+ * MACEPCI
+ */
+ MACEPCI_SCSI0_IRQ,
+ MACEPCI_SCSI1_IRQ,
+ MACEPCI_SLOT0_IRQ,
+ MACEPCI_SLOT1_IRQ,
+ MACEPCI_SLOT2_IRQ,
+ MACEPCI_SHARED0_IRQ,
+ MACEPCI_SHARED1_IRQ,
+ MACEPCI_SHARED2_IRQ,
-/* CRIME */
-#define CRIME_GBE0_IRQ 17
-#define CRIME_GBE1_IRQ 18
-#define CRIME_GBE2_IRQ 19
-#define CRIME_GBE3_IRQ 20
-#define CRIME_CPUERR_IRQ 21
-#define CRIME_MEMERR_IRQ 22
-#define CRIME_RE_EMPTY_E_IRQ 23
-#define CRIME_RE_FULL_E_IRQ 24
-#define CRIME_RE_IDLE_E_IRQ 25
-#define CRIME_RE_EMPTY_L_IRQ 26
-#define CRIME_RE_FULL_L_IRQ 27
-#define CRIME_RE_IDLE_L_IRQ 28
-#define CRIME_SOFT0_IRQ 29
-#define CRIME_SOFT1_IRQ 30
-#define CRIME_SOFT2_IRQ 31
-#define CRIME_SYSCORERR_IRQ CRIME_SOFT2_IRQ
-#define CRIME_VICE_IRQ 32
+ /*
+ * CRIME
+ */
+ CRIME_GBE0_IRQ,
+ CRIME_GBE1_IRQ,
+ CRIME_GBE2_IRQ,
+ CRIME_GBE3_IRQ,
+ CRIME_CPUERR_IRQ,
+ CRIME_MEMERR_IRQ,
+ CRIME_RE_EMPTY_E_IRQ,
+ CRIME_RE_FULL_E_IRQ,
+ CRIME_RE_IDLE_E_IRQ,
+ CRIME_RE_EMPTY_L_IRQ,
+ CRIME_RE_FULL_L_IRQ,
+ CRIME_RE_IDLE_L_IRQ,
+ CRIME_SOFT0_IRQ,
+ CRIME_SOFT1_IRQ,
+ CRIME_SOFT2_IRQ,
+ CRIME_SYSCORERR_IRQ = CRIME_SOFT2_IRQ,
+ CRIME_VICE_IRQ,
-/* MACEISA */
-#define MACEISA_AUDIO_SW_IRQ 33
-#define MACEISA_AUDIO_SC_IRQ 34
-#define MACEISA_AUDIO1_DMAT_IRQ 35
-#define MACEISA_AUDIO1_OF_IRQ 36
-#define MACEISA_AUDIO2_DMAT_IRQ 37
-#define MACEISA_AUDIO2_MERR_IRQ 38
-#define MACEISA_AUDIO3_DMAT_IRQ 39
-#define MACEISA_AUDIO3_MERR_IRQ 40
-#define MACEISA_RTC_IRQ 41
-#define MACEISA_KEYB_IRQ 42
-/* MACEISA_KEYB_POLL is not an IRQ */
-#define MACEISA_MOUSE_IRQ 44
-/* MACEISA_MOUSE_POLL is not an IRQ */
-#define MACEISA_TIMER0_IRQ 46
-#define MACEISA_TIMER1_IRQ 47
-#define MACEISA_TIMER2_IRQ 48
-#define MACEISA_PARALLEL_IRQ 49
-#define MACEISA_PAR_CTXA_IRQ 50
-#define MACEISA_PAR_CTXB_IRQ 51
-#define MACEISA_PAR_MERR_IRQ 52
-#define MACEISA_SERIAL1_IRQ 53
-#define MACEISA_SERIAL1_TDMAT_IRQ 54
-#define MACEISA_SERIAL1_TDMAPR_IRQ 55
-#define MACEISA_SERIAL1_TDMAME_IRQ 56
-#define MACEISA_SERIAL1_RDMAT_IRQ 57
-#define MACEISA_SERIAL1_RDMAOR_IRQ 58
-#define MACEISA_SERIAL2_IRQ 59
-#define MACEISA_SERIAL2_TDMAT_IRQ 60
-#define MACEISA_SERIAL2_TDMAPR_IRQ 61
-#define MACEISA_SERIAL2_TDMAME_IRQ 62
-#define MACEISA_SERIAL2_RDMAT_IRQ 63
-#define MACEISA_SERIAL2_RDMAOR_IRQ 64
+ /*
+ * MACEISA
+ */
+ MACEISA_AUDIO_SW_IRQ,
+ MACEISA_AUDIO_SC_IRQ,
+ MACEISA_AUDIO1_DMAT_IRQ,
+ MACEISA_AUDIO1_OF_IRQ,
+ MACEISA_AUDIO2_DMAT_IRQ,
+ MACEISA_AUDIO2_MERR_IRQ,
+ MACEISA_AUDIO3_DMAT_IRQ,
+ MACEISA_AUDIO3_MERR_IRQ,
+ MACEISA_RTC_IRQ,
+ MACEISA_KEYB_IRQ,
+ /* MACEISA_KEYB_POLL is not an IRQ */
+ __MACEISA_KEYB_POLL,
+ MACEISA_MOUSE_IRQ,
+ /* MACEISA_MOUSE_POLL is not an IRQ */
+ __MACEISA_MOUSE_POLL,
+ MACEISA_TIMER0_IRQ,
+ MACEISA_TIMER1_IRQ,
+ MACEISA_TIMER2_IRQ,
+ MACEISA_PARALLEL_IRQ,
+ MACEISA_PAR_CTXA_IRQ,
+ MACEISA_PAR_CTXB_IRQ,
+ MACEISA_PAR_MERR_IRQ,
+ MACEISA_SERIAL1_IRQ,
+ MACEISA_SERIAL1_TDMAT_IRQ,
+ MACEISA_SERIAL1_TDMAPR_IRQ,
+ MACEISA_SERIAL1_TDMAME_IRQ,
+ MACEISA_SERIAL1_RDMAT_IRQ,
+ MACEISA_SERIAL1_RDMAOR_IRQ,
+ MACEISA_SERIAL2_IRQ,
+ MACEISA_SERIAL2_TDMAT_IRQ,
+ MACEISA_SERIAL2_TDMAPR_IRQ,
+ MACEISA_SERIAL2_TDMAME_IRQ,
+ MACEISA_SERIAL2_RDMAT_IRQ,
+ MACEISA_SERIAL2_RDMAOR_IRQ,
-#define IP32_IRQ_MAX MACEISA_SERIAL2_RDMAOR_IRQ
+ IP32_IRQ_MAX = MACEISA_SERIAL2_RDMAOR_IRQ
+};
#endif /* __ASM_IP32_INTS_H */
diff --git a/include/asm-mips/ip32/mace.h b/include/asm-mips/ip32/mace.h
index 990082c81f39..d08d7c672139 100644
--- a/include/asm-mips/ip32/mace.h
+++ b/include/asm-mips/ip32/mace.h
@@ -17,9 +17,6 @@
*/
#define MACE_BASE 0x1f000000 /* physical */
-#undef BIT
-#define BIT(x) (1UL << (x))
-
/*
* PCI interface
*/
diff --git a/include/asm-mips/ipc.h b/include/asm-mips/ipc.h
deleted file mode 100644
index a46e3d9c2a3f..000000000000
--- a/include/asm-mips/ipc.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ipc.h>
diff --git a/include/asm-mips/jmr3927/jmr3927.h b/include/asm-mips/jmr3927/jmr3927.h
index b2dc35f56181..81602c8047eb 100644
--- a/include/asm-mips/jmr3927/jmr3927.h
+++ b/include/asm-mips/jmr3927/jmr3927.h
@@ -132,9 +132,7 @@
#define JMR3927_IRQ_IRC_DMA (JMR3927_IRQ_IRC + TX3927_IR_DMA)
#define JMR3927_IRQ_IRC_PIO (JMR3927_IRQ_IRC + TX3927_IR_PIO)
#define JMR3927_IRQ_IRC_PCI (JMR3927_IRQ_IRC + TX3927_IR_PCI)
-#define JMR3927_IRQ_IRC_TMR0 (JMR3927_IRQ_IRC + TX3927_IR_TMR0)
-#define JMR3927_IRQ_IRC_TMR1 (JMR3927_IRQ_IRC + TX3927_IR_TMR1)
-#define JMR3927_IRQ_IRC_TMR2 (JMR3927_IRQ_IRC + TX3927_IR_TMR2)
+#define JMR3927_IRQ_IRC_TMR(ch) (JMR3927_IRQ_IRC + TX3927_IR_TMR(ch))
#define JMR3927_IRQ_IOC_PCIA (JMR3927_IRQ_IOC + JMR3927_IOC_INTB_PCIA)
#define JMR3927_IRQ_IOC_PCIB (JMR3927_IRQ_IOC + JMR3927_IOC_INTB_PCIB)
#define JMR3927_IRQ_IOC_PCIC (JMR3927_IRQ_IOC + JMR3927_IOC_INTB_PCIC)
@@ -148,17 +146,12 @@
#define JMR3927_IRQ_IOCINT JMR3927_IRQ_IRC_INT1
/* TC35815 100M Ether (JMR-TX3912:JPW4:2-3 Short) */
#define JMR3927_IRQ_ETHER0 JMR3927_IRQ_IRC_INT3
-/* Clock Tick (10ms) */
-#define JMR3927_IRQ_TICK JMR3927_IRQ_IRC_TMR0
/* Clocks */
#define JMR3927_CORECLK 132710400 /* 132.7MHz */
#define JMR3927_GBUSCLK (JMR3927_CORECLK / 2) /* 66.35MHz */
#define JMR3927_IMCLK (JMR3927_CORECLK / 4) /* 33.17MHz */
-#define jmr3927_tmrptr tx3927_tmrptr(0) /* TMR0 */
-
-
/*
* TX3927 Pin Configuration:
*
diff --git a/include/asm-mips/jmr3927/tx3927.h b/include/asm-mips/jmr3927/tx3927.h
index 211bcf47fffb..338f99882a39 100644
--- a/include/asm-mips/jmr3927/tx3927.h
+++ b/include/asm-mips/jmr3927/tx3927.h
@@ -222,9 +222,7 @@ struct tx3927_ccfg_reg {
#define TX3927_IR_DMA 8
#define TX3927_IR_PIO 9
#define TX3927_IR_PCI 10
-#define TX3927_IR_TMR0 13
-#define TX3927_IR_TMR1 14
-#define TX3927_IR_TMR2 15
+#define TX3927_IR_TMR(ch) (13 + (ch))
#define TX3927_NUM_IR 16
/*
diff --git a/include/asm-mips/jmr3927/txx927.h b/include/asm-mips/jmr3927/txx927.h
index 58a8ff6be815..0474fe8dac3f 100644
--- a/include/asm-mips/jmr3927/txx927.h
+++ b/include/asm-mips/jmr3927/txx927.h
@@ -10,22 +10,6 @@
#ifndef __ASM_TXX927_H
#define __ASM_TXX927_H
-struct txx927_tmr_reg {
- volatile unsigned long tcr;
- volatile unsigned long tisr;
- volatile unsigned long cpra;
- volatile unsigned long cprb;
- volatile unsigned long itmr;
- volatile unsigned long unused0[3];
- volatile unsigned long ccdr;
- volatile unsigned long unused1[3];
- volatile unsigned long pgmr;
- volatile unsigned long unused2[3];
- volatile unsigned long wtmr;
- volatile unsigned long unused3[43];
- volatile unsigned long trr;
-};
-
struct txx927_sio_reg {
volatile unsigned long lcr;
volatile unsigned long dicr;
@@ -51,27 +35,6 @@ struct txx927_pio_reg {
};
/*
- * TMR
- */
-/* TMTCR : Timer Control */
-#define TXx927_TMTCR_TCE 0x00000080
-#define TXx927_TMTCR_CCDE 0x00000040
-#define TXx927_TMTCR_CRE 0x00000020
-#define TXx927_TMTCR_ECES 0x00000008
-#define TXx927_TMTCR_CCS 0x00000004
-#define TXx927_TMTCR_TMODE_MASK 0x00000003
-#define TXx927_TMTCR_TMODE_ITVL 0x00000000
-
-/* TMTISR : Timer Int. Status */
-#define TXx927_TMTISR_TPIBS 0x00000004
-#define TXx927_TMTISR_TPIAS 0x00000002
-#define TXx927_TMTISR_TIIS 0x00000001
-
-/* TMTITMR : Interval Timer Mode */
-#define TXx927_TMTITMR_TIIE 0x00008000
-#define TXx927_TMTITMR_TZCE 0x00000001
-
-/*
* SIO
*/
/* SILCR : Line Control */
diff --git a/include/asm-mips/lasat/lasatint.h b/include/asm-mips/lasat/lasatint.h
index 065474feeccc..e0d2458b43d0 100644
--- a/include/asm-mips/lasat/lasatint.h
+++ b/include/asm-mips/lasat/lasatint.h
@@ -1,4 +1,5 @@
-#define LASATINT_END 16
+#ifndef __ASM_LASAT_LASATINT_H
+#define __ASM_LASAT_LASATINT_H
/* lasat 100 */
#define LASAT_INT_STATUS_REG_100 (KSEG1ADDR(0x1c880000))
@@ -10,3 +11,4 @@
#define LASAT_INT_MASK_REG_200 (KSEG1ADDR(0x1104003c))
#define LASATINT_MASK_SHIFT_200 16
+#endif /* __ASM_LASAT_LASATINT_H */
diff --git a/include/asm-mips/mach-au1x00/au1000.h b/include/asm-mips/mach-au1x00/au1000.h
index 10f613f23c33..3bdce9126f16 100644
--- a/include/asm-mips/mach-au1x00/au1000.h
+++ b/include/asm-mips/mach-au1x00/au1000.h
@@ -40,7 +40,9 @@
#include <linux/delay.h>
#include <linux/types.h>
+
#include <asm/io.h>
+#include <asm/irq.h>
/* cpu pipeline flush */
void static inline au_sync(void)
@@ -91,23 +93,6 @@ static inline u32 au_readl(unsigned long reg)
}
-static __inline__ int au_ffz(unsigned int x)
-{
- if ((x = ~x) == 0)
- return 32;
- return __ilog2(x & -x);
-}
-
-/*
- * ffs: find first bit set. This is defined the same way as
- * the libc and compiler builtin ffs routines, therefore
- * differs in spirit from the above ffz (man ffs).
- */
-static __inline__ int au_ffs(int x)
-{
- return __ilog2(x & -x) + 1;
-}
-
/* arch/mips/au1000/common/clocks.c */
extern void set_au1x00_speed(unsigned int new_freq);
extern unsigned int get_au1x00_speed(void);
@@ -119,16 +104,16 @@ extern unsigned int get_au1x00_lcd_clock(void);
/*
* Every board describes its IRQ mapping with this table.
*/
-typedef struct au1xxx_irqmap {
+struct au1xxx_irqmap {
int im_irq;
int im_type;
int im_request;
-} au1xxx_irq_map_t;
+};
/*
* init_IRQ looks for a table with this name.
*/
-extern au1xxx_irq_map_t au1xxx_irq_map[];
+extern struct au1xxx_irqmap au1xxx_irq_map[];
#endif /* !defined (_LANGUAGE_ASSEMBLY) */
@@ -540,63 +525,67 @@ extern au1xxx_irq_map_t au1xxx_irq_map[];
/* Interrupt Numbers */
/* Au1000 */
#ifdef CONFIG_SOC_AU1000
-#define AU1000_UART0_INT 0
-#define AU1000_UART1_INT 1 /* au1000 */
-#define AU1000_UART2_INT 2 /* au1000 */
-#define AU1000_UART3_INT 3
-#define AU1000_SSI0_INT 4 /* au1000 */
-#define AU1000_SSI1_INT 5 /* au1000 */
-#define AU1000_DMA_INT_BASE 6
-#define AU1000_TOY_INT 14
-#define AU1000_TOY_MATCH0_INT 15
-#define AU1000_TOY_MATCH1_INT 16
-#define AU1000_TOY_MATCH2_INT 17
-#define AU1000_RTC_INT 18
-#define AU1000_RTC_MATCH0_INT 19
-#define AU1000_RTC_MATCH1_INT 20
-#define AU1000_RTC_MATCH2_INT 21
-#define AU1000_IRDA_TX_INT 22 /* au1000 */
-#define AU1000_IRDA_RX_INT 23 /* au1000 */
-#define AU1000_USB_DEV_REQ_INT 24
-#define AU1000_USB_DEV_SUS_INT 25
-#define AU1000_USB_HOST_INT 26
-#define AU1000_ACSYNC_INT 27
-#define AU1000_MAC0_DMA_INT 28
-#define AU1000_MAC1_DMA_INT 29
-#define AU1000_I2S_UO_INT 30 /* au1000 */
-#define AU1000_AC97C_INT 31
-#define AU1000_GPIO_0 32
-#define AU1000_GPIO_1 33
-#define AU1000_GPIO_2 34
-#define AU1000_GPIO_3 35
-#define AU1000_GPIO_4 36
-#define AU1000_GPIO_5 37
-#define AU1000_GPIO_6 38
-#define AU1000_GPIO_7 39
-#define AU1000_GPIO_8 40
-#define AU1000_GPIO_9 41
-#define AU1000_GPIO_10 42
-#define AU1000_GPIO_11 43
-#define AU1000_GPIO_12 44
-#define AU1000_GPIO_13 45
-#define AU1000_GPIO_14 46
-#define AU1000_GPIO_15 47
-#define AU1000_GPIO_16 48
-#define AU1000_GPIO_17 49
-#define AU1000_GPIO_18 50
-#define AU1000_GPIO_19 51
-#define AU1000_GPIO_20 52
-#define AU1000_GPIO_21 53
-#define AU1000_GPIO_22 54
-#define AU1000_GPIO_23 55
-#define AU1000_GPIO_24 56
-#define AU1000_GPIO_25 57
-#define AU1000_GPIO_26 58
-#define AU1000_GPIO_27 59
-#define AU1000_GPIO_28 60
-#define AU1000_GPIO_29 61
-#define AU1000_GPIO_30 62
-#define AU1000_GPIO_31 63
+enum soc_au1000_ints {
+ AU1000_FIRST_INT = MIPS_CPU_IRQ_BASE,
+ AU1000_UART0_INT = AU1000_FIRST_INT,
+ AU1000_UART1_INT, /* au1000 */
+ AU1000_UART2_INT, /* au1000 */
+ AU1000_UART3_INT,
+ AU1000_SSI0_INT, /* au1000 */
+ AU1000_SSI1_INT, /* au1000 */
+ AU1000_DMA_INT_BASE,
+
+ AU1000_TOY_INT = AU1000_FIRST_INT + 14,
+ AU1000_TOY_MATCH0_INT,
+ AU1000_TOY_MATCH1_INT,
+ AU1000_TOY_MATCH2_INT,
+ AU1000_RTC_INT,
+ AU1000_RTC_MATCH0_INT,
+ AU1000_RTC_MATCH1_INT,
+ AU1000_RTC_MATCH2_INT,
+ AU1000_IRDA_TX_INT, /* au1000 */
+ AU1000_IRDA_RX_INT, /* au1000 */
+ AU1000_USB_DEV_REQ_INT,
+ AU1000_USB_DEV_SUS_INT,
+ AU1000_USB_HOST_INT,
+ AU1000_ACSYNC_INT,
+ AU1000_MAC0_DMA_INT,
+ AU1000_MAC1_DMA_INT,
+ AU1000_I2S_UO_INT, /* au1000 */
+ AU1000_AC97C_INT,
+ AU1000_GPIO_0,
+ AU1000_GPIO_1,
+ AU1000_GPIO_2,
+ AU1000_GPIO_3,
+ AU1000_GPIO_4,
+ AU1000_GPIO_5,
+ AU1000_GPIO_6,
+ AU1000_GPIO_7,
+ AU1000_GPIO_8,
+ AU1000_GPIO_9,
+ AU1000_GPIO_10,
+ AU1000_GPIO_11,
+ AU1000_GPIO_12,
+ AU1000_GPIO_13,
+ AU1000_GPIO_14,
+ AU1000_GPIO_15,
+ AU1000_GPIO_16,
+ AU1000_GPIO_17,
+ AU1000_GPIO_18,
+ AU1000_GPIO_19,
+ AU1000_GPIO_20,
+ AU1000_GPIO_21,
+ AU1000_GPIO_22,
+ AU1000_GPIO_23,
+ AU1000_GPIO_24,
+ AU1000_GPIO_25,
+ AU1000_GPIO_26,
+ AU1000_GPIO_27,
+ AU1000_GPIO_28,
+ AU1000_GPIO_29,
+ AU1000_GPIO_30,
+ AU1000_GPIO_31,
+};
#define UART0_ADDR 0xB1100000
#define UART1_ADDR 0xB1200000
@@ -615,61 +604,65 @@ extern au1xxx_irq_map_t au1xxx_irq_map[];
/* Au1500 */
#ifdef CONFIG_SOC_AU1500
-#define AU1500_UART0_INT 0
-#define AU1000_PCI_INTA 1 /* au1500 */
-#define AU1000_PCI_INTB 2 /* au1500 */
-#define AU1500_UART3_INT 3
-#define AU1000_PCI_INTC 4 /* au1500 */
-#define AU1000_PCI_INTD 5 /* au1500 */
-#define AU1000_DMA_INT_BASE 6
-#define AU1000_TOY_INT 14
-#define AU1000_TOY_MATCH0_INT 15
-#define AU1000_TOY_MATCH1_INT 16
-#define AU1000_TOY_MATCH2_INT 17
-#define AU1000_RTC_INT 18
-#define AU1000_RTC_MATCH0_INT 19
-#define AU1000_RTC_MATCH1_INT 20
-#define AU1000_RTC_MATCH2_INT 21
-#define AU1500_PCI_ERR_INT 22
-#define AU1000_USB_DEV_REQ_INT 24
-#define AU1000_USB_DEV_SUS_INT 25
-#define AU1000_USB_HOST_INT 26
-#define AU1000_ACSYNC_INT 27
-#define AU1500_MAC0_DMA_INT 28
-#define AU1500_MAC1_DMA_INT 29
-#define AU1000_AC97C_INT 31
-#define AU1000_GPIO_0 32
-#define AU1000_GPIO_1 33
-#define AU1000_GPIO_2 34
-#define AU1000_GPIO_3 35
-#define AU1000_GPIO_4 36
-#define AU1000_GPIO_5 37
-#define AU1000_GPIO_6 38
-#define AU1000_GPIO_7 39
-#define AU1000_GPIO_8 40
-#define AU1000_GPIO_9 41
-#define AU1000_GPIO_10 42
-#define AU1000_GPIO_11 43
-#define AU1000_GPIO_12 44
-#define AU1000_GPIO_13 45
-#define AU1000_GPIO_14 46
-#define AU1000_GPIO_15 47
-#define AU1500_GPIO_200 48
-#define AU1500_GPIO_201 49
-#define AU1500_GPIO_202 50
-#define AU1500_GPIO_203 51
-#define AU1500_GPIO_20 52
-#define AU1500_GPIO_204 53
-#define AU1500_GPIO_205 54
-#define AU1500_GPIO_23 55
-#define AU1500_GPIO_24 56
-#define AU1500_GPIO_25 57
-#define AU1500_GPIO_26 58
-#define AU1500_GPIO_27 59
-#define AU1500_GPIO_28 60
-#define AU1500_GPIO_206 61
-#define AU1500_GPIO_207 62
-#define AU1500_GPIO_208_215 63
+enum soc_au1500_ints {
+ AU1500_FIRST_INT = MIPS_CPU_IRQ_BASE,
+ AU1500_UART0_INT = AU1500_FIRST_INT,
+ AU1000_PCI_INTA, /* au1500 */
+ AU1000_PCI_INTB, /* au1500 */
+ AU1500_UART3_INT,
+ AU1000_PCI_INTC, /* au1500 */
+ AU1000_PCI_INTD, /* au1500 */
+ AU1000_DMA_INT_BASE,
+
+ AU1000_TOY_INT = AU1500_FIRST_INT + 14,
+ AU1000_TOY_MATCH0_INT,
+ AU1000_TOY_MATCH1_INT,
+ AU1000_TOY_MATCH2_INT,
+ AU1000_RTC_INT,
+ AU1000_RTC_MATCH0_INT,
+ AU1000_RTC_MATCH1_INT,
+ AU1000_RTC_MATCH2_INT,
+ AU1500_PCI_ERR_INT,
+ AU1000_USB_DEV_REQ_INT,
+ AU1000_USB_DEV_SUS_INT,
+ AU1000_USB_HOST_INT,
+ AU1000_ACSYNC_INT,
+ AU1500_MAC0_DMA_INT,
+ AU1500_MAC1_DMA_INT,
+ AU1000_AC97C_INT = AU1500_FIRST_INT + 31,
+ AU1000_GPIO_0,
+ AU1000_GPIO_1,
+ AU1000_GPIO_2,
+ AU1000_GPIO_3,
+ AU1000_GPIO_4,
+ AU1000_GPIO_5,
+ AU1000_GPIO_6,
+ AU1000_GPIO_7,
+ AU1000_GPIO_8,
+ AU1000_GPIO_9,
+ AU1000_GPIO_10,
+ AU1000_GPIO_11,
+ AU1000_GPIO_12,
+ AU1000_GPIO_13,
+ AU1000_GPIO_14,
+ AU1000_GPIO_15,
+ AU1500_GPIO_200,
+ AU1500_GPIO_201,
+ AU1500_GPIO_202,
+ AU1500_GPIO_203,
+ AU1500_GPIO_20,
+ AU1500_GPIO_204,
+ AU1500_GPIO_205,
+ AU1500_GPIO_23,
+ AU1500_GPIO_24,
+ AU1500_GPIO_25,
+ AU1500_GPIO_26,
+ AU1500_GPIO_27,
+ AU1500_GPIO_28,
+ AU1500_GPIO_206,
+ AU1500_GPIO_207,
+ AU1500_GPIO_208_215,
+};
/* shortcuts */
#define INTA AU1000_PCI_INTA
@@ -692,63 +685,67 @@ extern au1xxx_irq_map_t au1xxx_irq_map[];
/* Au1100 */
#ifdef CONFIG_SOC_AU1100
-#define AU1100_UART0_INT 0
-#define AU1100_UART1_INT 1
-#define AU1100_SD_INT 2
-#define AU1100_UART3_INT 3
-#define AU1000_SSI0_INT 4
-#define AU1000_SSI1_INT 5
-#define AU1000_DMA_INT_BASE 6
-#define AU1000_TOY_INT 14
-#define AU1000_TOY_MATCH0_INT 15
-#define AU1000_TOY_MATCH1_INT 16
-#define AU1000_TOY_MATCH2_INT 17
-#define AU1000_RTC_INT 18
-#define AU1000_RTC_MATCH0_INT 19
-#define AU1000_RTC_MATCH1_INT 20
-#define AU1000_RTC_MATCH2_INT 21
-#define AU1000_IRDA_TX_INT 22
-#define AU1000_IRDA_RX_INT 23
-#define AU1000_USB_DEV_REQ_INT 24
-#define AU1000_USB_DEV_SUS_INT 25
-#define AU1000_USB_HOST_INT 26
-#define AU1000_ACSYNC_INT 27
-#define AU1100_MAC0_DMA_INT 28
-#define AU1100_GPIO_208_215 29
-#define AU1100_LCD_INT 30
-#define AU1000_AC97C_INT 31
-#define AU1000_GPIO_0 32
-#define AU1000_GPIO_1 33
-#define AU1000_GPIO_2 34
-#define AU1000_GPIO_3 35
-#define AU1000_GPIO_4 36
-#define AU1000_GPIO_5 37
-#define AU1000_GPIO_6 38
-#define AU1000_GPIO_7 39
-#define AU1000_GPIO_8 40
-#define AU1000_GPIO_9 41
-#define AU1000_GPIO_10 42
-#define AU1000_GPIO_11 43
-#define AU1000_GPIO_12 44
-#define AU1000_GPIO_13 45
-#define AU1000_GPIO_14 46
-#define AU1000_GPIO_15 47
-#define AU1000_GPIO_16 48
-#define AU1000_GPIO_17 49
-#define AU1000_GPIO_18 50
-#define AU1000_GPIO_19 51
-#define AU1000_GPIO_20 52
-#define AU1000_GPIO_21 53
-#define AU1000_GPIO_22 54
-#define AU1000_GPIO_23 55
-#define AU1000_GPIO_24 56
-#define AU1000_GPIO_25 57
-#define AU1000_GPIO_26 58
-#define AU1000_GPIO_27 59
-#define AU1000_GPIO_28 60
-#define AU1000_GPIO_29 61
-#define AU1000_GPIO_30 62
-#define AU1000_GPIO_31 63
+enum soc_au1100_ints {
+ AU1100_FIRST_INT = MIPS_CPU_IRQ_BASE,
+ AU1100_UART0_INT,
+ AU1100_UART1_INT,
+ AU1100_SD_INT,
+ AU1100_UART3_INT,
+ AU1000_SSI0_INT,
+ AU1000_SSI1_INT,
+ AU1000_DMA_INT_BASE,
+
+ AU1000_TOY_INT = AU1100_FIRST_INT + 14,
+ AU1000_TOY_MATCH0_INT,
+ AU1000_TOY_MATCH1_INT,
+ AU1000_TOY_MATCH2_INT,
+ AU1000_RTC_INT,
+ AU1000_RTC_MATCH0_INT,
+ AU1000_RTC_MATCH1_INT,
+ AU1000_RTC_MATCH2_INT,
+ AU1000_IRDA_TX_INT,
+ AU1000_IRDA_RX_INT,
+ AU1000_USB_DEV_REQ_INT,
+ AU1000_USB_DEV_SUS_INT,
+ AU1000_USB_HOST_INT,
+ AU1000_ACSYNC_INT,
+ AU1100_MAC0_DMA_INT,
+ AU1100_GPIO_208_215,
+ AU1100_LCD_INT,
+ AU1000_AC97C_INT,
+ AU1000_GPIO_0,
+ AU1000_GPIO_1,
+ AU1000_GPIO_2,
+ AU1000_GPIO_3,
+ AU1000_GPIO_4,
+ AU1000_GPIO_5,
+ AU1000_GPIO_6,
+ AU1000_GPIO_7,
+ AU1000_GPIO_8,
+ AU1000_GPIO_9,
+ AU1000_GPIO_10,
+ AU1000_GPIO_11,
+ AU1000_GPIO_12,
+ AU1000_GPIO_13,
+ AU1000_GPIO_14,
+ AU1000_GPIO_15,
+ AU1000_GPIO_16,
+ AU1000_GPIO_17,
+ AU1000_GPIO_18,
+ AU1000_GPIO_19,
+ AU1000_GPIO_20,
+ AU1000_GPIO_21,
+ AU1000_GPIO_22,
+ AU1000_GPIO_23,
+ AU1000_GPIO_24,
+ AU1000_GPIO_25,
+ AU1000_GPIO_26,
+ AU1000_GPIO_27,
+ AU1000_GPIO_28,
+ AU1000_GPIO_29,
+ AU1000_GPIO_30,
+ AU1000_GPIO_31,
+};
#define UART0_ADDR 0xB1100000
#define UART1_ADDR 0xB1200000
@@ -763,69 +760,73 @@ extern au1xxx_irq_map_t au1xxx_irq_map[];
#endif /* CONFIG_SOC_AU1100 */
#ifdef CONFIG_SOC_AU1550
-#define AU1550_UART0_INT 0
-#define AU1550_PCI_INTA 1
-#define AU1550_PCI_INTB 2
-#define AU1550_DDMA_INT 3
-#define AU1550_CRYPTO_INT 4
-#define AU1550_PCI_INTC 5
-#define AU1550_PCI_INTD 6
-#define AU1550_PCI_RST_INT 7
-#define AU1550_UART1_INT 8
-#define AU1550_UART3_INT 9
-#define AU1550_PSC0_INT 10
-#define AU1550_PSC1_INT 11
-#define AU1550_PSC2_INT 12
-#define AU1550_PSC3_INT 13
-#define AU1000_TOY_INT 14
-#define AU1000_TOY_MATCH0_INT 15
-#define AU1000_TOY_MATCH1_INT 16
-#define AU1000_TOY_MATCH2_INT 17
-#define AU1000_RTC_INT 18
-#define AU1000_RTC_MATCH0_INT 19
-#define AU1000_RTC_MATCH1_INT 20
-#define AU1000_RTC_MATCH2_INT 21
-#define AU1550_NAND_INT 23
-#define AU1550_USB_DEV_REQ_INT 24
-#define AU1550_USB_DEV_SUS_INT 25
-#define AU1550_USB_HOST_INT 26
-#define AU1000_USB_DEV_REQ_INT AU1550_USB_DEV_REQ_INT
-#define AU1000_USB_DEV_SUS_INT AU1550_USB_DEV_SUS_INT
-#define AU1000_USB_HOST_INT AU1550_USB_HOST_INT
-#define AU1550_MAC0_DMA_INT 27
-#define AU1550_MAC1_DMA_INT 28
-#define AU1000_GPIO_0 32
-#define AU1000_GPIO_1 33
-#define AU1000_GPIO_2 34
-#define AU1000_GPIO_3 35
-#define AU1000_GPIO_4 36
-#define AU1000_GPIO_5 37
-#define AU1000_GPIO_6 38
-#define AU1000_GPIO_7 39
-#define AU1000_GPIO_8 40
-#define AU1000_GPIO_9 41
-#define AU1000_GPIO_10 42
-#define AU1000_GPIO_11 43
-#define AU1000_GPIO_12 44
-#define AU1000_GPIO_13 45
-#define AU1000_GPIO_14 46
-#define AU1000_GPIO_15 47
-#define AU1550_GPIO_200 48
-#define AU1500_GPIO_201_205 49 // Logical or of GPIO201:205
-#define AU1500_GPIO_16 50
-#define AU1500_GPIO_17 51
-#define AU1500_GPIO_20 52
-#define AU1500_GPIO_21 53
-#define AU1500_GPIO_22 54
-#define AU1500_GPIO_23 55
-#define AU1500_GPIO_24 56
-#define AU1500_GPIO_25 57
-#define AU1500_GPIO_26 58
-#define AU1500_GPIO_27 59
-#define AU1500_GPIO_28 60
-#define AU1500_GPIO_206 61
-#define AU1500_GPIO_207 62
-#define AU1500_GPIO_208_218 63 // Logical or of GPIO208:218
+enum soc_au1550_ints {
+ AU1550_FIRST_INT = MIPS_CPU_IRQ_BASE,
+ AU1550_UART0_INT = AU1550_FIRST_INT,
+ AU1550_PCI_INTA,
+ AU1550_PCI_INTB,
+ AU1550_DDMA_INT,
+ AU1550_CRYPTO_INT,
+ AU1550_PCI_INTC,
+ AU1550_PCI_INTD,
+ AU1550_PCI_RST_INT,
+ AU1550_UART1_INT,
+ AU1550_UART3_INT,
+ AU1550_PSC0_INT,
+ AU1550_PSC1_INT,
+ AU1550_PSC2_INT,
+ AU1550_PSC3_INT,
+ AU1000_TOY_INT,
+ AU1000_TOY_MATCH0_INT,
+ AU1000_TOY_MATCH1_INT,
+ AU1000_TOY_MATCH2_INT,
+ AU1000_RTC_INT,
+ AU1000_RTC_MATCH0_INT,
+ AU1000_RTC_MATCH1_INT,
+ AU1000_RTC_MATCH2_INT,
+
+ AU1550_NAND_INT = AU1550_FIRST_INT + 23,
+ AU1550_USB_DEV_REQ_INT,
+ AU1000_USB_DEV_REQ_INT = AU1550_USB_DEV_REQ_INT,
+ AU1550_USB_DEV_SUS_INT,
+ AU1000_USB_DEV_SUS_INT = AU1550_USB_DEV_SUS_INT,
+ AU1550_USB_HOST_INT,
+ AU1000_USB_HOST_INT = AU1550_USB_HOST_INT,
+ AU1550_MAC0_DMA_INT,
+ AU1550_MAC1_DMA_INT,
+ AU1000_GPIO_0 = AU1550_FIRST_INT + 32,
+ AU1000_GPIO_1,
+ AU1000_GPIO_2,
+ AU1000_GPIO_3,
+ AU1000_GPIO_4,
+ AU1000_GPIO_5,
+ AU1000_GPIO_6,
+ AU1000_GPIO_7,
+ AU1000_GPIO_8,
+ AU1000_GPIO_9,
+ AU1000_GPIO_10,
+ AU1000_GPIO_11,
+ AU1000_GPIO_12,
+ AU1000_GPIO_13,
+ AU1000_GPIO_14,
+ AU1000_GPIO_15,
+ AU1550_GPIO_200,
+ AU1500_GPIO_201_205, /* Logical or of GPIO201:205 */
+ AU1500_GPIO_16,
+ AU1500_GPIO_17,
+ AU1500_GPIO_20,
+ AU1500_GPIO_21,
+ AU1500_GPIO_22,
+ AU1500_GPIO_23,
+ AU1500_GPIO_24,
+ AU1500_GPIO_25,
+ AU1500_GPIO_26,
+ AU1500_GPIO_27,
+ AU1500_GPIO_28,
+ AU1500_GPIO_206,
+ AU1500_GPIO_207,
+ AU1500_GPIO_208_218, /* Logical or of GPIO208:218 */
+};
/* shortcuts */
#define INTA AU1550_PCI_INTA
@@ -849,70 +850,74 @@ extern au1xxx_irq_map_t au1xxx_irq_map[];
#endif /* CONFIG_SOC_AU1550 */
#ifdef CONFIG_SOC_AU1200
-#define AU1200_UART0_INT 0
-#define AU1200_SWT_INT 1
-#define AU1200_SD_INT 2
-#define AU1200_DDMA_INT 3
-#define AU1200_MAE_BE_INT 4
-#define AU1200_GPIO_200 5
-#define AU1200_GPIO_201 6
-#define AU1200_GPIO_202 7
-#define AU1200_UART1_INT 8
-#define AU1200_MAE_FE_INT 9
-#define AU1200_PSC0_INT 10
-#define AU1200_PSC1_INT 11
-#define AU1200_AES_INT 12
-#define AU1200_CAMERA_INT 13
-#define AU1000_TOY_INT 14
-#define AU1000_TOY_MATCH0_INT 15
-#define AU1000_TOY_MATCH1_INT 16
-#define AU1000_TOY_MATCH2_INT 17
-#define AU1000_RTC_INT 18
-#define AU1000_RTC_MATCH0_INT 19
-#define AU1000_RTC_MATCH1_INT 20
-#define AU1000_RTC_MATCH2_INT 21
-#define AU1200_NAND_INT 23
-#define AU1200_GPIO_204 24
-#define AU1200_GPIO_205 25
-#define AU1200_GPIO_206 26
-#define AU1200_GPIO_207 27
-#define AU1200_GPIO_208_215 28 // Logical OR of 208:215
-#define AU1200_USB_INT 29
-#define AU1000_USB_HOST_INT AU1200_USB_INT
-#define AU1200_LCD_INT 30
-#define AU1200_MAE_BOTH_INT 31
-#define AU1000_GPIO_0 32
-#define AU1000_GPIO_1 33
-#define AU1000_GPIO_2 34
-#define AU1000_GPIO_3 35
-#define AU1000_GPIO_4 36
-#define AU1000_GPIO_5 37
-#define AU1000_GPIO_6 38
-#define AU1000_GPIO_7 39
-#define AU1000_GPIO_8 40
-#define AU1000_GPIO_9 41
-#define AU1000_GPIO_10 42
-#define AU1000_GPIO_11 43
-#define AU1000_GPIO_12 44
-#define AU1000_GPIO_13 45
-#define AU1000_GPIO_14 46
-#define AU1000_GPIO_15 47
-#define AU1000_GPIO_16 48
-#define AU1000_GPIO_17 49
-#define AU1000_GPIO_18 50
-#define AU1000_GPIO_19 51
-#define AU1000_GPIO_20 52
-#define AU1000_GPIO_21 53
-#define AU1000_GPIO_22 54
-#define AU1000_GPIO_23 55
-#define AU1000_GPIO_24 56
-#define AU1000_GPIO_25 57
-#define AU1000_GPIO_26 58
-#define AU1000_GPIO_27 59
-#define AU1000_GPIO_28 60
-#define AU1000_GPIO_29 61
-#define AU1000_GPIO_30 62
-#define AU1000_GPIO_31 63
+enum soc_au1200_ints {
+ AU1200_FIRST_INT = MIPS_CPU_IRQ_BASE,
+ AU1200_UART0_INT = AU1200_FIRST_INT,
+ AU1200_SWT_INT,
+ AU1200_SD_INT,
+ AU1200_DDMA_INT,
+ AU1200_MAE_BE_INT,
+ AU1200_GPIO_200,
+ AU1200_GPIO_201,
+ AU1200_GPIO_202,
+ AU1200_UART1_INT,
+ AU1200_MAE_FE_INT,
+ AU1200_PSC0_INT,
+ AU1200_PSC1_INT,
+ AU1200_AES_INT,
+ AU1200_CAMERA_INT,
+ AU1000_TOY_INT,
+ AU1000_TOY_MATCH0_INT,
+ AU1000_TOY_MATCH1_INT,
+ AU1000_TOY_MATCH2_INT,
+ AU1000_RTC_INT,
+ AU1000_RTC_MATCH0_INT,
+ AU1000_RTC_MATCH1_INT,
+ AU1000_RTC_MATCH2_INT,
+
+ AU1200_NAND_INT = AU1200_FIRST_INT + 23,
+ AU1200_GPIO_204,
+ AU1200_GPIO_205,
+ AU1200_GPIO_206,
+ AU1200_GPIO_207,
+ AU1200_GPIO_208_215, /* Logical OR of 208:215 */
+ AU1200_USB_INT,
+ AU1000_USB_HOST_INT = AU1200_USB_INT,
+ AU1200_LCD_INT,
+ AU1200_MAE_BOTH_INT,
+ AU1000_GPIO_0,
+ AU1000_GPIO_1,
+ AU1000_GPIO_2,
+ AU1000_GPIO_3,
+ AU1000_GPIO_4,
+ AU1000_GPIO_5,
+ AU1000_GPIO_6,
+ AU1000_GPIO_7,
+ AU1000_GPIO_8,
+ AU1000_GPIO_9,
+ AU1000_GPIO_10,
+ AU1000_GPIO_11,
+ AU1000_GPIO_12,
+ AU1000_GPIO_13,
+ AU1000_GPIO_14,
+ AU1000_GPIO_15,
+ AU1000_GPIO_16,
+ AU1000_GPIO_17,
+ AU1000_GPIO_18,
+ AU1000_GPIO_19,
+ AU1000_GPIO_20,
+ AU1000_GPIO_21,
+ AU1000_GPIO_22,
+ AU1000_GPIO_23,
+ AU1000_GPIO_24,
+ AU1000_GPIO_25,
+ AU1000_GPIO_26,
+ AU1000_GPIO_27,
+ AU1000_GPIO_28,
+ AU1000_GPIO_29,
+ AU1000_GPIO_30,
+ AU1000_GPIO_31,
+};
#define UART0_ADDR 0xB1100000
#define UART1_ADDR 0xB1200000
@@ -943,10 +948,12 @@ extern au1xxx_irq_map_t au1xxx_irq_map[];
#endif /* CONFIG_SOC_AU1200 */
-#define AU1000_LAST_INTC0_INT 31
-#define AU1000_LAST_INTC1_INT 63
-#define AU1000_MAX_INTR 63
-#define INTX 0xFF /* not valid */
+#define AU1000_INTC0_INT_BASE (MIPS_CPU_IRQ_BASE + 0)
+#define AU1000_INTC0_INT_LAST (MIPS_CPU_IRQ_BASE + 31)
+#define AU1000_INTC1_INT_BASE (MIPS_CPU_IRQ_BASE + 32)
+#define AU1000_INTC1_INT_LAST (MIPS_CPU_IRQ_BASE + 63)
+#define AU1000_MAX_INTR (MIPS_CPU_IRQ_BASE + 63)
+#define INTX 0xFF /* not valid */
/* Programmable Counters 0 and 1 */
#define SYS_BASE 0xB1900000
diff --git a/include/asm-mips/mach-au1x00/prom.h b/include/asm-mips/mach-au1x00/prom.h
new file mode 100644
index 000000000000..e38715577c51
--- /dev/null
+++ b/include/asm-mips/mach-au1x00/prom.h
@@ -0,0 +1,13 @@
+#ifndef __AU1X00_PROM_H
+#define __AU1X00_PROM_H
+
+extern int prom_argc;
+extern char **prom_argv;
+extern char **prom_envp;
+
+extern void prom_init_cmdline(void);
+extern char *prom_getcmdline(void);
+extern char *prom_getenv(char *envname);
+extern int prom_get_ethernet_addr(char *ethernet_addr);
+
+#endif
diff --git a/include/asm-mips/mach-au1x00/timex.h b/include/asm-mips/mach-au1x00/timex.h
deleted file mode 100644
index e3ada66cb636..000000000000
--- a/include/asm-mips/mach-au1x00/timex.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2003 by Ralf Baechle
- */
-#ifndef __ASM_MACH_AU1X00_TIMEX_H
-#define __ASM_MACH_AU1X00_TIMEX_H
-
-#define CLOCK_TICK_RATE ((HZ * 100000UL) / 2)
-
-#endif /* __ASM_MACH_AU1X00_TIMEX_H */
diff --git a/include/asm-mips/mach-cobalt/irq.h b/include/asm-mips/mach-cobalt/irq.h
index 179d0e850b59..57c8c9ac5851 100644
--- a/include/asm-mips/mach-cobalt/irq.h
+++ b/include/asm-mips/mach-cobalt/irq.h
@@ -35,7 +35,7 @@
* 4 - ethernet
* 5 - 16550 UART
* 6 - cascade i8259
- * 7 - CP0 counter (unused)
+ * 7 - CP0 counter
*/
#define MIPS_CPU_IRQ_BASE 16
@@ -48,7 +48,6 @@
#define SCSI_IRQ (MIPS_CPU_IRQ_BASE + 5)
#define I8259_CASCADE_IRQ (MIPS_CPU_IRQ_BASE + 6)
-
#define GT641XX_IRQ_BASE 24
#include <asm/irq_gt641xx.h>
diff --git a/include/asm-mips/mach-db1x00/db1200.h b/include/asm-mips/mach-db1x00/db1200.h
index 647fdb54cc1d..050eae87ff01 100644
--- a/include/asm-mips/mach-db1x00/db1200.h
+++ b/include/asm-mips/mach-db1x00/db1200.h
@@ -181,29 +181,34 @@ static BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR;
#define NAND_PHYS_ADDR 0x20000000
/*
- * External Interrupts for Pb1200 as of 8/6/2004.
- * Bit positions in the CPLD registers can be calculated by taking
- * the interrupt define and subtracting the DB1200_INT_BEGIN value.
- * *example: IDE bis pos is = 64 - 64
- ETH bit pos is = 65 - 64
+ * External Interrupts for Pb1200 as of 8/6/2004.
+ * Bit positions in the CPLD registers can be calculated by taking
+ * the interrupt define and subtracting the DB1200_INT_BEGIN value.
+ *
+ * Example: IDE bis pos is = 64 - 64
+ * ETH bit pos is = 65 - 64
*/
-#define DB1200_INT_BEGIN (AU1000_LAST_INTC1_INT + 1)
-#define DB1200_IDE_INT (DB1200_INT_BEGIN + 0)
-#define DB1200_ETH_INT (DB1200_INT_BEGIN + 1)
-#define DB1200_PC0_INT (DB1200_INT_BEGIN + 2)
-#define DB1200_PC0_STSCHG_INT (DB1200_INT_BEGIN + 3)
-#define DB1200_PC1_INT (DB1200_INT_BEGIN + 4)
-#define DB1200_PC1_STSCHG_INT (DB1200_INT_BEGIN + 5)
-#define DB1200_DC_INT (DB1200_INT_BEGIN + 6)
-#define DB1200_FLASHBUSY_INT (DB1200_INT_BEGIN + 7)
-#define DB1200_PC0_INSERT_INT (DB1200_INT_BEGIN + 8)
-#define DB1200_PC0_EJECT_INT (DB1200_INT_BEGIN + 9)
-#define DB1200_PC1_INSERT_INT (DB1200_INT_BEGIN + 10)
-#define DB1200_PC1_EJECT_INT (DB1200_INT_BEGIN + 11)
-#define DB1200_SD0_INSERT_INT (DB1200_INT_BEGIN + 12)
-#define DB1200_SD0_EJECT_INT (DB1200_INT_BEGIN + 13)
-
-#define DB1200_INT_END (DB1200_INT_BEGIN + 15)
+enum external_pb1200_ints {
+ DB1200_INT_BEGIN = AU1000_MAX_INTR + 1,
+
+ DB1200_IDE_INT = DB1200_INT_BEGIN,
+ DB1200_ETH_INT,
+ DB1200_PC0_INT,
+ DB1200_PC0_STSCHG_INT,
+ DB1200_PC1_INT,
+ DB1200_PC1_STSCHG_INT,
+ DB1200_DC_INT,
+ DB1200_FLASHBUSY_INT,
+ DB1200_PC0_INSERT_INT,
+ DB1200_PC0_EJECT_INT,
+ DB1200_PC1_INSERT_INT,
+ DB1200_PC1_EJECT_INT,
+ DB1200_SD0_INSERT_INT,
+ DB1200_SD0_EJECT_INT,
+
+ DB1200_INT_END = DB1200_INT_BEGIN + 15,
+};
+
/* For drivers/pcmcia/au1000_db1x00.c */
diff --git a/include/asm-mips/mach-generic/ide.h b/include/asm-mips/mach-generic/ide.h
index a77128362a7d..4ec2b930dfbb 100644
--- a/include/asm-mips/mach-generic/ide.h
+++ b/include/asm-mips/mach-generic/ide.h
@@ -98,7 +98,6 @@ static __inline__ unsigned long ide_default_io_base(int index)
}
}
-#define IDE_ARCH_OBSOLETE_INIT
#define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */
#ifdef CONFIG_BLK_DEV_IDEPCI
diff --git a/include/asm-mips/mach-generic/timex.h b/include/asm-mips/mach-generic/timex.h
deleted file mode 100644
index 48b4cfaa0d50..000000000000
--- a/include/asm-mips/mach-generic/timex.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2003, 2005 by Ralf Baechle
- */
-#ifndef __ASM_MACH_GENERIC_TIMEX_H
-#define __ASM_MACH_GENERIC_TIMEX_H
-
-#define CLOCK_TICK_RATE 500000
-
-#endif /* __ASM_MACH_GENERIC_TIMEX_H */
diff --git a/include/asm-mips/mach-ip27/kernel-entry-init.h b/include/asm-mips/mach-ip27/kernel-entry-init.h
index c1a10314b317..624d66c7f290 100644
--- a/include/asm-mips/mach-ip27/kernel-entry-init.h
+++ b/include/asm-mips/mach-ip27/kernel-entry-init.h
@@ -46,7 +46,14 @@
lh t1, KV_RO_NASID_OFFSET(t0)
lh t2, KV_RW_NASID_OFFSET(t0)
MAPPED_KERNEL_SETUP_TLB
- ARC64_TWIDDLE_PC
+
+ /*
+ * We might not get launched at the address the kernel is linked to,
+ * so we jump there.
+ */
+ PTR_LA t0, 0f
+ jr t0
+0:
.endm
#endif /* __ASM_MACH_IP27_KERNEL_ENTRY_H */
diff --git a/include/asm-mips/mach-jazz/timex.h b/include/asm-mips/mach-jazz/timex.h
deleted file mode 100644
index 93affa33dfa8..000000000000
--- a/include/asm-mips/mach-jazz/timex.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2003 by Ralf Baechle
- */
-#ifndef __ASM_MACH_JAZZ_TIMEX_H
-#define __ASM_MACH_JAZZ_TIMEX_H
-
-/*
- * Jazz is still using the R4030 100Hz counter
- */
-#define CLOCK_TICK_RATE 100
-
-#endif /* __ASM_MACH_JAZZ_TIMEX_H */
diff --git a/include/asm-mips/mach-lasat/irq.h b/include/asm-mips/mach-lasat/irq.h
new file mode 100644
index 000000000000..da75f89f3723
--- /dev/null
+++ b/include/asm-mips/mach-lasat/irq.h
@@ -0,0 +1,13 @@
+#ifndef _ASM_MACH_LASAT_IRQ_H
+#define _ASM_MACH_LASAT_IRQ_H
+
+#define LASAT_CASCADE_IRQ (MIPS_CPU_IRQ_BASE + 0)
+
+#define LASAT_IRQ_BASE 8
+#define LASAT_IRQ_END 23
+
+#define NR_IRQS 24
+
+#include_next <irq.h>
+
+#endif /* _ASM_MACH_LASAT_IRQ_H */
diff --git a/include/asm-mips/mach-pb1x00/pb1200.h b/include/asm-mips/mach-pb1x00/pb1200.h
index 409d443322c1..d9f384acfea9 100644
--- a/include/asm-mips/mach-pb1x00/pb1200.h
+++ b/include/asm-mips/mach-pb1x00/pb1200.h
@@ -217,31 +217,35 @@ static BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR;
/*
- * External Interrupts for Pb1200 as of 8/6/2004.
- * Bit positions in the CPLD registers can be calculated by taking
- * the interrupt define and subtracting the PB1200_INT_BEGIN value.
- * *example: IDE bis pos is = 64 - 64
- ETH bit pos is = 65 - 64
+ * External Interrupts for Pb1200 as of 8/6/2004.
+ * Bit positions in the CPLD registers can be calculated by taking
+ * the interrupt define and subtracting the PB1200_INT_BEGIN value.
+ *
+ * Example: IDE bis pos is = 64 - 64
+ * ETH bit pos is = 65 - 64
*/
-#define PB1200_INT_BEGIN (AU1000_LAST_INTC1_INT + 1)
-#define PB1200_IDE_INT (PB1200_INT_BEGIN + 0)
-#define PB1200_ETH_INT (PB1200_INT_BEGIN + 1)
-#define PB1200_PC0_INT (PB1200_INT_BEGIN + 2)
-#define PB1200_PC0_STSCHG_INT (PB1200_INT_BEGIN + 3)
-#define PB1200_PC1_INT (PB1200_INT_BEGIN + 4)
-#define PB1200_PC1_STSCHG_INT (PB1200_INT_BEGIN + 5)
-#define PB1200_DC_INT (PB1200_INT_BEGIN + 6)
-#define PB1200_FLASHBUSY_INT (PB1200_INT_BEGIN + 7)
-#define PB1200_PC0_INSERT_INT (PB1200_INT_BEGIN + 8)
-#define PB1200_PC0_EJECT_INT (PB1200_INT_BEGIN + 9)
-#define PB1200_PC1_INSERT_INT (PB1200_INT_BEGIN + 10)
-#define PB1200_PC1_EJECT_INT (PB1200_INT_BEGIN + 11)
-#define PB1200_SD0_INSERT_INT (PB1200_INT_BEGIN + 12)
-#define PB1200_SD0_EJECT_INT (PB1200_INT_BEGIN + 13)
-#define PB1200_SD1_INSERT_INT (PB1200_INT_BEGIN + 14)
-#define PB1200_SD1_EJECT_INT (PB1200_INT_BEGIN + 15)
-
-#define PB1200_INT_END (PB1200_INT_BEGIN + 15)
+enum external_pb1200_ints {
+ PB1200_INT_BEGIN = AU1000_MAX_INTR + 1,
+
+ PB1200_IDE_INT = PB1200_INT_BEGIN,
+ PB1200_ETH_INT,
+ PB1200_PC0_INT,
+ PB1200_PC0_STSCHG_INT,
+ PB1200_PC1_INT,
+ PB1200_PC1_STSCHG_INT,
+ PB1200_DC_INT,
+ PB1200_FLASHBUSY_INT,
+ PB1200_PC0_INSERT_INT,
+ PB1200_PC0_EJECT_INT,
+ PB1200_PC1_INSERT_INT,
+ PB1200_PC1_EJECT_INT,
+ PB1200_SD0_INSERT_INT,
+ PB1200_SD0_EJECT_INT,
+ PB1200_SD1_INSERT_INT,
+ PB1200_SD1_EJECT_INT,
+
+ PB1200_INT_END (PB1200_INT_BEGIN + 15)
+};
/* For drivers/pcmcia/au1000_db1x00.c */
#define BOARD_PC0_INT PB1200_PC0_INT
diff --git a/include/asm-mips/mach-qemu/timex.h b/include/asm-mips/mach-qemu/timex.h
deleted file mode 100644
index cd543693fb0a..000000000000
--- a/include/asm-mips/mach-qemu/timex.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2005 Daniel Jacobowitz
- */
-#ifndef __ASM_MACH_QEMU_TIMEX_H
-#define __ASM_MACH_QEMU_TIMEX_H
-
-/*
- * We use a simulated i8254 PIC...
- */
-#define CLOCK_TICK_RATE 1193182
-
-#endif /* __ASM_MACH_QEMU_TIMEX_H */
diff --git a/include/asm-mips/mach-rm/timex.h b/include/asm-mips/mach-rm/timex.h
deleted file mode 100644
index 11ff6cb0f214..000000000000
--- a/include/asm-mips/mach-rm/timex.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2003, 2005 by Ralf Baechle
- */
-#ifndef __ASM_MACH_RM200_TIMEX_H
-#define __ASM_MACH_RM200_TIMEX_H
-
-#define CLOCK_TICK_RATE 1193182
-
-#endif /* __ASM_MACH_RM200_TIMEX_H */
diff --git a/include/asm-mips/pci/bridge.h b/include/asm-mips/pci/bridge.h
index b84feebf2cef..5f4b9d4e4114 100644
--- a/include/asm-mips/pci/bridge.h
+++ b/include/asm-mips/pci/bridge.h
@@ -538,7 +538,7 @@ typedef struct bridge_err_cmdword_s {
BRIDGE_ISR_PMU_ESIZE_FAULT)
/*
- * List of Errors which are fatal and kill the sytem
+ * List of Errors which are fatal and kill the system
*/
#define BRIDGE_ISR_ERROR_FATAL \
((BRIDGE_ISR_XTALK_ERROR & ~BRIDGE_ISR_XREAD_REQ_TIMEOUT)|\
diff --git a/include/asm-mips/pmc-sierra/msp71xx/war.h b/include/asm-mips/pmc-sierra/msp71xx/war.h
new file mode 100644
index 000000000000..0bf48fc1892b
--- /dev/null
+++ b/include/asm-mips/pmc-sierra/msp71xx/war.h
@@ -0,0 +1,28 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
+ */
+#ifndef __ASM_MIPS_PMC_SIERRA_WAR_H
+#define __ASM_MIPS_PMC_SIERRA_WAR_H
+
+#define R4600_V1_INDEX_ICACHEOP_WAR 0
+#define R4600_V1_HIT_CACHEOP_WAR 0
+#define R4600_V2_HIT_CACHEOP_WAR 0
+#define R5432_CP0_INTERRUPT_WAR 0
+#define BCM1250_M3_WAR 0
+#define SIBYTE_1956_WAR 0
+#define MIPS4K_ICACHE_REFILL_WAR 0
+#define MIPS_CACHE_SYNC_WAR 0
+#define TX49XX_ICACHE_INDEX_INV_WAR 0
+#define RM9000_CDEX_SMP_WAR 0
+#define ICACHE_REFILLS_WORKAROUND_WAR 0
+#define R10000_LLSC_WAR 0
+#if defined(CONFIG_PMC_MSP7120_EVAL) || defined(CONFIG_PMC_MSP7120_GW) || \
+ defined(CONFIG_PMC_MSP7120_FPGA)
+#define MIPS34K_MISSED_ITLB_WAR 1
+#endif
+
+#endif /* __ASM_MIPS_PMC_SIERRA_WAR_H */
diff --git a/include/asm-mips/ptrace.h b/include/asm-mips/ptrace.h
index 85b44366343a..786f7e3c99bc 100644
--- a/include/asm-mips/ptrace.h
+++ b/include/asm-mips/ptrace.h
@@ -86,9 +86,9 @@ struct pt_regs {
extern asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit);
-extern NORET_TYPE void die(const char *, struct pt_regs *) ATTRIB_NORET;
+extern NORET_TYPE void die(const char *, const struct pt_regs *) ATTRIB_NORET;
-static inline void die_if_kernel(const char *str, struct pt_regs *regs)
+static inline void die_if_kernel(const char *str, const struct pt_regs *regs)
{
if (unlikely(!user_mode(regs)))
die(str, regs);
diff --git a/include/asm-mips/scatterlist.h b/include/asm-mips/scatterlist.h
index 7af104c95b20..83d69fe17c9f 100644
--- a/include/asm-mips/scatterlist.h
+++ b/include/asm-mips/scatterlist.h
@@ -4,7 +4,10 @@
#include <asm/types.h>
struct scatterlist {
- struct page * page;
+#ifdef CONFIG_DEBUG_SG
+ unsigned long sg_magic;
+#endif
+ unsigned long page_link;
unsigned int offset;
dma_addr_t dma_address;
unsigned int length;
diff --git a/include/asm-mips/semaphore.h b/include/asm-mips/semaphore.h
index 080daa77f867..fdf8042b784b 100644
--- a/include/asm-mips/semaphore.h
+++ b/include/asm-mips/semaphore.h
@@ -49,7 +49,6 @@ struct semaphore {
struct semaphore name = __SEMAPHORE_INITIALIZER(name, count)
#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name, 1)
-#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name, 0)
static inline void sema_init(struct semaphore *sem, int val)
{
diff --git a/include/asm-mips/sibyte/sb1250.h b/include/asm-mips/sibyte/sb1250.h
index 494aa65dcfbd..0dad844a3b5b 100644
--- a/include/asm-mips/sibyte/sb1250.h
+++ b/include/asm-mips/sibyte/sb1250.h
@@ -45,13 +45,11 @@ extern unsigned int soc_type;
extern unsigned int periph_rev;
extern unsigned int zbbus_mhz;
-extern void sb1250_hpt_setup(void);
extern void sb1250_time_init(void);
extern void sb1250_mask_irq(int cpu, int irq);
extern void sb1250_unmask_irq(int cpu, int irq);
extern void sb1250_smp_finish(void);
-extern void bcm1480_hpt_setup(void);
extern void bcm1480_time_init(void);
extern void bcm1480_mask_irq(int cpu, int irq);
extern void bcm1480_unmask_irq(int cpu, int irq);
diff --git a/include/asm-mips/sni.h b/include/asm-mips/sni.h
index 4d43dbb7f8b8..af081457f847 100644
--- a/include/asm-mips/sni.h
+++ b/include/asm-mips/sni.h
@@ -141,8 +141,6 @@ extern unsigned int sni_brd_type;
#define A20R_PT_TIM0_ACK 0xbc050000
#define A20R_PT_TIM1_ACK 0xbc060000
-#define SNI_MIPS_IRQ_CPU_TIMER (MIPS_CPU_IRQ_BASE+7)
-
#define SNI_A20R_IRQ_BASE MIPS_CPU_IRQ_BASE
#define SNI_A20R_IRQ_TIMER (SNI_A20R_IRQ_BASE+5)
diff --git a/include/asm-mips/time.h b/include/asm-mips/time.h
index 35555bd5c52d..ee1663e64da1 100644
--- a/include/asm-mips/time.h
+++ b/include/asm-mips/time.h
@@ -10,17 +10,13 @@
* 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.
- *
- * Please refer to Documentation/mips/time.README.
*/
#ifndef _ASM_TIME_H
#define _ASM_TIME_H
-#include <linux/interrupt.h>
-#include <linux/linkage.h>
-#include <linux/ptrace.h>
#include <linux/rtc.h>
#include <linux/spinlock.h>
+#include <linux/clockchips.h>
#include <linux/clocksource.h>
extern spinlock_t rtc_lock;
@@ -37,28 +33,13 @@ extern int rtc_mips_set_mmss(unsigned long);
/*
* Timer interrupt functions.
* mips_timer_state is needed for high precision timer calibration.
- * mips_timer_ack may be NULL if the interrupt is self-recoverable.
*/
extern int (*mips_timer_state)(void);
-extern void (*mips_timer_ack)(void);
-
-/*
- * High precision timer clocksource.
- * If .read is NULL, an R4k-compatible timer setup is attempted.
- */
-extern struct clocksource clocksource_mips;
-
-/*
- * profiling and process accouting is done separately in local_timer_interrupt
- */
-extern void local_timer_interrupt(int irq, void *dev_id);
/*
* board specific routines required by time_init().
*/
-struct irqaction;
extern void plat_time_init(void);
-extern void plat_timer_setup(struct irqaction *irq);
/*
* mips_hpt_frequency - must be set if you intend to use an R4k-compatible
@@ -76,6 +57,17 @@ extern int (*perf_irq)(void);
/*
* Initialize the calling CPU's compare interrupt as clockevent device
*/
+#ifdef CONFIG_CEVT_R4K
extern void mips_clockevent_init(void);
+extern unsigned int __weak get_c0_compare_int(void);
+#else
+static inline void mips_clockevent_init(void)
+{
+}
+#endif
+
+extern void clocksource_set_clock(struct clocksource *cs, unsigned int clock);
+extern void clockevent_set_clock(struct clock_event_device *cd,
+ unsigned int clock);
#endif /* _ASM_TIME_H */
diff --git a/include/asm-mips/timex.h b/include/asm-mips/timex.h
index 87c68ae76ff8..6529704aa73a 100644
--- a/include/asm-mips/timex.h
+++ b/include/asm-mips/timex.h
@@ -13,27 +13,12 @@
#include <asm/mipsregs.h>
/*
- * This is the frequency of the timer used for Linux's timer interrupt.
- * The value should be defined as accurate as possible or under certain
- * circumstances Linux timekeeping might become inaccurate or fail.
- *
- * For many system the exact clockrate of the timer isn't known but due to
- * the way this value is used we can get away with a wrong value as long
- * as this value is:
- *
- * - a multiple of HZ
- * - a divisor of the actual rate
- *
- * 500000 is a good such cheat value.
- *
- * The obscure number 1193182 is the same as used by the original i8254
- * time in legacy PC hardware; the chip unfortunately also found in a
- * bunch of MIPS systems. The last remaining user of the i8254 for the
- * timer interrupt is the RM200; it's a very standard system so there is
- * no reason to make this a separate architecture.
+ * This is the clock rate of the i8253 PIT. A MIPS system may not have
+ * a PIT by the symbol is used all over the kernel including some APIs.
+ * So keeping it defined to the number for the PIT is the only sane thing
+ * for now.
*/
-
-#include <timex.h>
+#define CLOCK_TICK_RATE 1193182
/*
* Standard way to access the cycle counter.
@@ -50,7 +35,7 @@ typedef unsigned int cycles_t;
static inline cycles_t get_cycles(void)
{
- return read_c0_count();
+ return 0;
}
#endif /* __KERNEL__ */
diff --git a/include/asm-mips/tlbflush.h b/include/asm-mips/tlbflush.h
index 730e841fb08a..86b21de12e91 100644
--- a/include/asm-mips/tlbflush.h
+++ b/include/asm-mips/tlbflush.h
@@ -11,7 +11,6 @@
* - flush_tlb_page(vma, vmaddr) flushes one page
* - flush_tlb_range(vma, start, end) flushes a range of pages
* - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
- * - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
*/
extern void local_flush_tlb_all(void);
extern void local_flush_tlb_mm(struct mm_struct *mm);
@@ -45,10 +44,4 @@ extern void flush_tlb_one(unsigned long vaddr);
#endif /* CONFIG_SMP */
-static inline void flush_tlb_pgtables(struct mm_struct *mm,
- unsigned long start, unsigned long end)
-{
- /* Nothing to do on MIPS. */
-}
-
#endif /* __ASM_TLBFLUSH_H */
diff --git a/include/asm-mips/tx4927/tx4927_pci.h b/include/asm-mips/tx4927/tx4927_pci.h
index f98b2bb719d5..3f1e470192e3 100644
--- a/include/asm-mips/tx4927/tx4927_pci.h
+++ b/include/asm-mips/tx4927/tx4927_pci.h
@@ -9,6 +9,7 @@
#define __ASM_TX4927_TX4927_PCI_H
#define TX4927_CCFG_TOE 0x00004000
+#define TX4927_CCFG_TINTDIS 0x01000000
#define TX4927_PCIMEM 0x08000000
#define TX4927_PCIMEM_SIZE 0x08000000
@@ -20,6 +21,8 @@
#define TX4927_PCIC_REG 0xff1fd000
#define TX4927_CCFG_REG 0xff1fe000
#define TX4927_IRC_REG 0xff1ff600
+#define TX4927_NR_TMR 3
+#define TX4927_TMR_REG(ch) (0xff1ff000 + (ch) * 0x100)
#define TX4927_CE3 0x17f00000 /* 1M */
#define TX4927_PCIRESET_ADDR 0xbc00f006
#define TX4927_PCI_CLK_ADDR (KSEG1 + TX4927_CE3 + 0x00040020)
diff --git a/include/asm-mips/tx4938/tx4938.h b/include/asm-mips/tx4938/tx4938.h
index 650b010761f9..f7c448b90578 100644
--- a/include/asm-mips/tx4938/tx4938.h
+++ b/include/asm-mips/tx4938/tx4938.h
@@ -641,7 +641,6 @@ struct tx4938_ccfg_reg {
#define tx4938_pcicptr ((struct tx4938_pcic_reg *)TX4938_PCIC_REG)
#define tx4938_pcic1ptr ((struct tx4938_pcic_reg *)TX4938_PCIC1_REG)
#define tx4938_ccfgptr ((struct tx4938_ccfg_reg *)TX4938_CCFG_REG)
-#define tx4938_tmrptr(ch) ((struct tx4938_tmr_reg *)TX4938_TMR_REG(ch))
#define tx4938_sioptr(ch) ((struct tx4938_sio_reg *)TX4938_SIO_REG(ch))
#define tx4938_pioptr ((struct tx4938_pio_reg *)TX4938_PIO_REG)
#define tx4938_aclcptr ((struct tx4938_aclc_reg *)TX4938_ACLC_REG)
diff --git a/include/asm-mips/txx9tmr.h b/include/asm-mips/txx9tmr.h
new file mode 100644
index 000000000000..67f70a8f09bd
--- /dev/null
+++ b/include/asm-mips/txx9tmr.h
@@ -0,0 +1,67 @@
+/*
+ * include/asm-mips/txx9tmr.h
+ * TX39/TX49 timer controller definitions.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_TXX9TMR_H
+#define __ASM_TXX9TMR_H
+
+#include <linux/types.h>
+
+struct txx9_tmr_reg {
+ u32 tcr;
+ u32 tisr;
+ u32 cpra;
+ u32 cprb;
+ u32 itmr;
+ u32 unused0[3];
+ u32 ccdr;
+ u32 unused1[3];
+ u32 pgmr;
+ u32 unused2[3];
+ u32 wtmr;
+ u32 unused3[43];
+ u32 trr;
+};
+
+/* TMTCR : Timer Control */
+#define TXx9_TMTCR_TCE 0x00000080
+#define TXx9_TMTCR_CCDE 0x00000040
+#define TXx9_TMTCR_CRE 0x00000020
+#define TXx9_TMTCR_ECES 0x00000008
+#define TXx9_TMTCR_CCS 0x00000004
+#define TXx9_TMTCR_TMODE_MASK 0x00000003
+#define TXx9_TMTCR_TMODE_ITVL 0x00000000
+#define TXx9_TMTCR_TMODE_PGEN 0x00000001
+#define TXx9_TMTCR_TMODE_WDOG 0x00000002
+
+/* TMTISR : Timer Int. Status */
+#define TXx9_TMTISR_TPIBS 0x00000004
+#define TXx9_TMTISR_TPIAS 0x00000002
+#define TXx9_TMTISR_TIIS 0x00000001
+
+/* TMITMR : Interval Timer Mode */
+#define TXx9_TMITMR_TIIE 0x00008000
+#define TXx9_TMITMR_TZCE 0x00000001
+
+/* TMWTMR : Watchdog Timer Mode */
+#define TXx9_TMWTMR_TWIE 0x00008000
+#define TXx9_TMWTMR_WDIS 0x00000080
+#define TXx9_TMWTMR_TWC 0x00000001
+
+void txx9_clocksource_init(unsigned long baseaddr,
+ unsigned int imbusclk);
+void txx9_clockevent_init(unsigned long baseaddr, int irq,
+ unsigned int imbusclk);
+void txx9_tmr_init(unsigned long baseaddr);
+
+#ifdef CONFIG_CPU_TX39XX
+#define TXX9_TIMER_BITS 24
+#else
+#define TXX9_TIMER_BITS 32
+#endif
+
+#endif /* __ASM_TXX9TMR_H */
diff --git a/include/asm-mips/types.h b/include/asm-mips/types.h
index 63a13c5bd832..2dd147f519d1 100644
--- a/include/asm-mips/types.h
+++ b/include/asm-mips/types.h
@@ -34,9 +34,9 @@ typedef unsigned long __u64;
#else
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
-typedef __signed__ long long __s64;
-typedef unsigned long long __u64;
+#if defined(__GNUC__)
+__extension__ typedef __signed__ long long __s64;
+__extension__ typedef unsigned long long __u64;
#endif
#endif
diff --git a/include/asm-mips/xxs1500.h b/include/asm-mips/xxs1500.h
deleted file mode 100644
index 4d84a90b0f20..000000000000
--- a/include/asm-mips/xxs1500.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * MyCable XXS1500 Referrence Board
- *
- * Copyright 2003 MontaVista Software Inc.
- * Author: Pete Popov, MontaVista Software, Inc.
- * ppopov@mvista.com or source@mvista.com
- *
- * ########################################################################
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
- *
- *
- */
-#ifndef __ASM_XXS1500_H
-#define __ASM_XXS1500_H
-
-/* PCMCIA XXS1500 specific defines */
-#define PCMCIA_MAX_SOCK 0
-#define PCMCIA_NUM_SOCKS (PCMCIA_MAX_SOCK+1)
-#define PCMCIA_IRQ AU1000_GPIO_4
-
-#endif /* __ASM_XXS1500_ */
diff --git a/include/asm-parisc/Kbuild b/include/asm-parisc/Kbuild
index c68e1680da01..f88b252e419c 100644
--- a/include/asm-parisc/Kbuild
+++ b/include/asm-parisc/Kbuild
@@ -1 +1,3 @@
include include/asm-generic/Kbuild.asm
+
+unifdef-y += pdc.h
diff --git a/include/asm-parisc/bitops.h b/include/asm-parisc/bitops.h
index 015cb0d379bd..f8eebcbad01f 100644
--- a/include/asm-parisc/bitops.h
+++ b/include/asm-parisc/bitops.h
@@ -1,6 +1,10 @@
#ifndef _PARISC_BITOPS_H
#define _PARISC_BITOPS_H
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
#include <linux/compiler.h>
#include <asm/types.h> /* for BITS_PER_LONG/SHIFT_PER_LONG */
#include <asm/byteorder.h>
@@ -208,6 +212,7 @@ static __inline__ int fls(int x)
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/lock.h>
#include <asm-generic/bitops/sched.h>
#endif /* __KERNEL__ */
diff --git a/include/asm-parisc/floppy.h b/include/asm-parisc/floppy.h
index da2f9c157143..4ca69f558fae 100644
--- a/include/asm-parisc/floppy.h
+++ b/include/asm-parisc/floppy.h
@@ -266,10 +266,6 @@ static int FDC2 = -1;
#define N_FDC 1
#define N_DRIVE 8
-#define FLOPPY_MOTOR_MASK 0xf0
-
-#define AUTO_DMA
-
#define EXTRA_FLOPPY_PARAMS
#endif /* __ASM_PARISC_FLOPPY_H */
diff --git a/include/asm-parisc/ide.h b/include/asm-parisc/ide.h
index b27bf7aeb256..be8760fbc8ee 100644
--- a/include/asm-parisc/ide.h
+++ b/include/asm-parisc/ide.h
@@ -17,7 +17,6 @@
#define MAX_HWIFS 2
#endif
-#define IDE_ARCH_OBSOLETE_INIT
#define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */
#define ide_request_irq(irq,hand,flg,dev,id) request_irq((irq),(hand),(flg),(dev),(id))
diff --git a/include/asm-parisc/io.h b/include/asm-parisc/io.h
index 4cc9bcec0564..55ddb1842107 100644
--- a/include/asm-parisc/io.h
+++ b/include/asm-parisc/io.h
@@ -138,7 +138,7 @@ extern void __iomem * __ioremap(unsigned long offset, unsigned long size, unsign
/* Most machines react poorly to I/O-space being cacheable... Instead let's
* define ioremap() in terms of ioremap_nocache().
*/
-extern inline void __iomem * ioremap(unsigned long offset, unsigned long size)
+static inline void __iomem * ioremap(unsigned long offset, unsigned long size)
{
return __ioremap(offset, size, _PAGE_NO_CACHE);
}
@@ -270,11 +270,6 @@ extern void outsl (unsigned long port, const void *src, unsigned long count);
/* IO Port space is : BBiiii where BB is HBA number. */
#define IO_SPACE_LIMIT 0x00ffffff
-
-#define dma_cache_inv(_start,_size) do { flush_kernel_dcache_range(_start,_size); } while (0)
-#define dma_cache_wback(_start,_size) do { flush_kernel_dcache_range(_start,_size); } while (0)
-#define dma_cache_wback_inv(_start,_size) do { flush_kernel_dcache_range(_start,_size); } while (0)
-
/* PA machines have an MM I/O space from 0xf0000000-0xffffffff in 32
* bit mode and from 0xfffffffff0000000-0xfffffffffffffff in 64 bit
* mode (essentially just sign extending. This macro takes in a 32
diff --git a/include/asm-parisc/page.h b/include/asm-parisc/page.h
index f6bba4c13664..b59a1504fc7a 100644
--- a/include/asm-parisc/page.h
+++ b/include/asm-parisc/page.h
@@ -3,6 +3,8 @@
#ifdef __KERNEL__
+#include <linux/const.h>
+
#if defined(CONFIG_PARISC_PAGE_SIZE_4KB)
# define PAGE_SHIFT 12
#elif defined(CONFIG_PARISC_PAGE_SIZE_16KB)
@@ -12,7 +14,7 @@
#else
# error "unknown default kernel page size"
#endif
-#define PAGE_SIZE (1UL << PAGE_SHIFT)
+#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
diff --git a/include/asm-parisc/pci.h b/include/asm-parisc/pci.h
index 61fbd57a8323..4ba868f44a5e 100644
--- a/include/asm-parisc/pci.h
+++ b/include/asm-parisc/pci.h
@@ -207,7 +207,7 @@ extern struct pci_bios_ops *pci_bios;
extern void pcibios_register_hba(struct pci_hba_data *);
extern void pcibios_set_master(struct pci_dev *);
#else
-extern inline void pcibios_register_hba(struct pci_hba_data *x)
+static inline void pcibios_register_hba(struct pci_hba_data *x)
{
}
#endif
diff --git a/include/asm-parisc/pdc.h b/include/asm-parisc/pdc.h
index 876fd8116d4a..5e0c3ca5450b 100644
--- a/include/asm-parisc/pdc.h
+++ b/include/asm-parisc/pdc.h
@@ -1,7 +1,6 @@
#ifndef _PARISC_PDC_H
#define _PARISC_PDC_H
-
/*
* PDC return values ...
* All PDC calls return a subset of these errors.
@@ -20,7 +19,6 @@
#define PDC_BUS_POW_WARN -12 /* Call could not complete in allowed power budget */
#define PDC_NOT_NARROW -17 /* Narrow mode not supported */
-
/*
* PDC entry points...
*/
@@ -50,6 +48,12 @@
#define PDC_MODEL_DISPEC 5 /* disable specific option */
#define PDC_MODEL_CPU_ID 6 /* returns cpu-id (only newer machines!) */
#define PDC_MODEL_CAPABILITIES 7 /* returns OS32/OS64-flags */
+/* Values for PDC_MODEL_CAPABILITIES non-equivalent virtual aliasing support */
+#define PDC_MODEL_IOPDIR_FDC (1 << 2)
+#define PDC_MODEL_NVA_MASK (3 << 4)
+#define PDC_MODEL_NVA_SUPPORTED (0 << 4)
+#define PDC_MODEL_NVA_SLOW (1 << 4)
+#define PDC_MODEL_NVA_UNSUPPORTED (3 << 4)
#define PDC_MODEL_GET_BOOT__OP 8 /* returns boot test options */
#define PDC_MODEL_SET_BOOT__OP 9 /* set boot test options */
@@ -91,7 +95,7 @@
#define PDC_TOD 9 /* time-of-day clock (TOD) */
#define PDC_TOD_READ 0 /* read TOD */
#define PDC_TOD_WRITE 1 /* write TOD */
-#define PDC_TOD_ITIMER 2 /* calibrate Interval Timer (CR16) */
+
#define PDC_STABLE 10 /* stable storage (sprockets) */
#define PDC_STABLE_READ 0
@@ -143,15 +147,6 @@
#define PDC_MEM_RET_PDT_FULL -11
#define PDC_MEM_RET_INVALID_PHYSICAL_LOCATION ~0ULL
-#ifndef __ASSEMBLY__
-typedef struct {
- unsigned long long baseAddr;
- unsigned int pages;
- unsigned int reserved;
-} MemAddrTable_t;
-#endif
-
-
#define PDC_PSW 21 /* Get/Set default System Mask */
#define PDC_PSW_MASK 0 /* Return mask */
#define PDC_PSW_GET_DEFAULTS 1 /* Return defaults */
@@ -274,6 +269,43 @@ typedef struct {
#define PDC_LINK_PCI_ENTRY_POINTS 0 /* list (Arg1) = 0 */
#define PDC_LINK_USB_ENTRY_POINTS 1 /* list (Arg1) = 1 */
+/* cl_class
+ * page 3-33 of IO-Firmware ARS
+ * IODC ENTRY_INIT(Search first) RET[1]
+ */
+#define CL_NULL 0 /* invalid */
+#define CL_RANDOM 1 /* random access (as disk) */
+#define CL_SEQU 2 /* sequential access (as tape) */
+#define CL_DUPLEX 7 /* full-duplex point-to-point (RS-232, Net) */
+#define CL_KEYBD 8 /* half-duplex console (HIL Keyboard) */
+#define CL_DISPL 9 /* half-duplex console (display) */
+#define CL_FC 10 /* FiberChannel access media */
+
+/* IODC ENTRY_INIT() */
+#define ENTRY_INIT_SRCH_FRST 2
+#define ENTRY_INIT_SRCH_NEXT 3
+#define ENTRY_INIT_MOD_DEV 4
+#define ENTRY_INIT_DEV 5
+#define ENTRY_INIT_MOD 6
+#define ENTRY_INIT_MSG 9
+
+/* IODC ENTRY_IO() */
+#define ENTRY_IO_BOOTIN 0
+#define ENTRY_IO_BOOTOUT 1
+#define ENTRY_IO_CIN 2
+#define ENTRY_IO_COUT 3
+#define ENTRY_IO_CLOSE 4
+#define ENTRY_IO_GETMSG 9
+#define ENTRY_IO_BBLOCK_IN 16
+#define ENTRY_IO_BBLOCK_OUT 17
+
+/* IODC ENTRY_SPA() */
+
+/* IODC ENTRY_CONFIG() */
+
+/* IODC ENTRY_TEST() */
+
+/* IODC ENTRY_TLB() */
/* constants for OS (NVM...) */
#define OS_ID_NONE 0 /* Undefined OS ID */
@@ -295,7 +327,13 @@ typedef struct {
#define OSTAT_RUN 6
#define OSTAT_ON 7
-#ifndef __ASSEMBLY__
+/* Page Zero constant offsets used by the HPMC handler */
+#define BOOT_CONSOLE_HPA_OFFSET 0x3c0
+#define BOOT_CONSOLE_SPA_OFFSET 0x3c4
+#define BOOT_CONSOLE_PATH_OFFSET 0x3a8
+
+#if !defined(__ASSEMBLY__)
+#ifdef __KERNEL__
#include <linux/types.h>
@@ -331,14 +369,6 @@ struct pdc_model { /* for PDC_MODEL */
unsigned long curr_key;
};
-/* Values for PDC_MODEL_CAPABILITIES non-equivalent virtual aliasing support */
-
-#define PDC_MODEL_IOPDIR_FDC (1 << 2) /* see sba_iommu.c */
-#define PDC_MODEL_NVA_MASK (3 << 4)
-#define PDC_MODEL_NVA_SUPPORTED (0 << 4)
-#define PDC_MODEL_NVA_SLOW (1 << 4)
-#define PDC_MODEL_NVA_UNSUPPORTED (3 << 4)
-
struct pdc_cache_cf { /* for PDC_CACHE (I/D-caches) */
unsigned long
#ifdef CONFIG_64BIT
@@ -558,15 +588,97 @@ struct pdc_hpmc_pim_20 { /* PDC_PIM */
__u64 fr[32];
};
-#endif /* __ASSEMBLY__ */
+void pdc_console_init(void); /* in pdc_console.c */
+void pdc_console_restart(void);
+
+void setup_pdc(void); /* in inventory.c */
+
+/* wrapper-functions from pdc.c */
+
+int pdc_add_valid(unsigned long address);
+int pdc_chassis_info(struct pdc_chassis_info *chassis_info, void *led_info, unsigned long len);
+int pdc_chassis_disp(unsigned long disp);
+int pdc_chassis_warn(unsigned long *warn);
+int pdc_coproc_cfg(struct pdc_coproc_cfg *pdc_coproc_info);
+int pdc_iodc_read(unsigned long *actcnt, unsigned long hpa, unsigned int index,
+ void *iodc_data, unsigned int iodc_data_size);
+int pdc_system_map_find_mods(struct pdc_system_map_mod_info *pdc_mod_info,
+ struct pdc_module_path *mod_path, long mod_index);
+int pdc_system_map_find_addrs(struct pdc_system_map_addr_info *pdc_addr_info,
+ long mod_index, long addr_index);
+int pdc_model_info(struct pdc_model *model);
+int pdc_model_sysmodel(char *name);
+int pdc_model_cpuid(unsigned long *cpu_id);
+int pdc_model_versions(unsigned long *versions, int id);
+int pdc_model_capabilities(unsigned long *capabilities);
+int pdc_cache_info(struct pdc_cache_info *cache);
+int pdc_spaceid_bits(unsigned long *space_bits);
+#ifndef CONFIG_PA20
+int pdc_btlb_info(struct pdc_btlb_info *btlb);
+int pdc_mem_map_hpa(struct pdc_memory_map *r_addr, struct pdc_module_path *mod_path);
+#endif /* !CONFIG_PA20 */
+int pdc_lan_station_id(char *lan_addr, unsigned long net_hpa);
+
+int pdc_stable_read(unsigned long staddr, void *memaddr, unsigned long count);
+int pdc_stable_write(unsigned long staddr, void *memaddr, unsigned long count);
+int pdc_stable_get_size(unsigned long *size);
+int pdc_stable_verify_contents(void);
+int pdc_stable_initialize(void);
+
+int pdc_pci_irt_size(unsigned long *num_entries, unsigned long hpa);
+int pdc_pci_irt(unsigned long num_entries, unsigned long hpa, void *tbl);
+
+int pdc_get_initiator(struct hardware_path *, struct pdc_initiator *);
+int pdc_tod_read(struct pdc_tod *tod);
+int pdc_tod_set(unsigned long sec, unsigned long usec);
+
+#ifdef CONFIG_64BIT
+int pdc_mem_mem_table(struct pdc_memory_table_raddr *r_addr,
+ struct pdc_memory_table *tbl, unsigned long entries);
+#endif
+
+void set_firmware_width(void);
+int pdc_do_firm_test_reset(unsigned long ftc_bitmap);
+int pdc_do_reset(void);
+int pdc_soft_power_info(unsigned long *power_reg);
+int pdc_soft_power_button(int sw_control);
+void pdc_io_reset(void);
+void pdc_io_reset_devices(void);
+int pdc_iodc_getc(void);
+void pdc_iodc_putc(unsigned char c);
+void pdc_iodc_outc(unsigned char c);
+void pdc_printf(const char *fmt, ...);
+
+void pdc_emergency_unlock(void);
+int pdc_sti_call(unsigned long func, unsigned long flags,
+ unsigned long inptr, unsigned long outputr,
+ unsigned long glob_cfg);
+
+static inline char * os_id_to_string(u16 os_id) {
+ switch(os_id) {
+ case OS_ID_NONE: return "No OS";
+ case OS_ID_HPUX: return "HP-UX";
+ case OS_ID_MPEXL: return "MPE-iX";
+ case OS_ID_OSF: return "OSF";
+ case OS_ID_HPRT: return "HP-RT";
+ case OS_ID_NOVEL: return "Novell Netware";
+ case OS_ID_LINUX: return "Linux";
+ default: return "Unknown";
+ }
+}
+
+#endif /* __KERNEL__ */
+
+#define PAGE0 ((struct zeropage *)__PAGE_OFFSET)
+
+/* DEFINITION OF THE ZERO-PAGE (PAG0) */
+/* based on work by Jason Eckhardt (jason@equator.com) */
-/* flags of the device_path (see below) */
+/* flags of the device_path */
#define PF_AUTOBOOT 0x80
#define PF_AUTOSEARCH 0x40
#define PF_TIMER 0x0F
-#ifndef __ASSEMBLY__
-
struct device_path { /* page 1-69 */
unsigned char flags; /* flags see above! */
unsigned char bc[6]; /* bus converter routing info */
@@ -586,63 +698,6 @@ struct pz_device {
unsigned short cl_class;/* see below */
} __attribute__((aligned(8))) ;
-#endif /* __ASSEMBLY__ */
-
-/* cl_class
- * page 3-33 of IO-Firmware ARS
- * IODC ENTRY_INIT(Search first) RET[1]
- */
-#define CL_NULL 0 /* invalid */
-#define CL_RANDOM 1 /* random access (as disk) */
-#define CL_SEQU 2 /* sequential access (as tape) */
-#define CL_DUPLEX 7 /* full-duplex point-to-point (RS-232, Net) */
-#define CL_KEYBD 8 /* half-duplex console (HIL Keyboard) */
-#define CL_DISPL 9 /* half-duplex console (display) */
-#define CL_FC 10 /* FiberChannel access media */
-
-#if 0
-/* FIXME: DEVCLASS_* duplicates CL_* (above). Delete DEVCLASS_*? */
-#define DEVCLASS_RANDOM 1
-#define DEVCLASS_SEQU 2
-#define DEVCLASS_DUPLEX 7
-#define DEVCLASS_KEYBD 8
-#define DEVCLASS_DISP 9
-#endif
-
-/* IODC ENTRY_INIT() */
-#define ENTRY_INIT_SRCH_FRST 2
-#define ENTRY_INIT_SRCH_NEXT 3
-#define ENTRY_INIT_MOD_DEV 4
-#define ENTRY_INIT_DEV 5
-#define ENTRY_INIT_MOD 6
-#define ENTRY_INIT_MSG 9
-
-/* IODC ENTRY_IO() */
-#define ENTRY_IO_BOOTIN 0
-#define ENTRY_IO_BOOTOUT 1
-#define ENTRY_IO_CIN 2
-#define ENTRY_IO_COUT 3
-#define ENTRY_IO_CLOSE 4
-#define ENTRY_IO_GETMSG 9
-#define ENTRY_IO_BBLOCK_IN 16
-#define ENTRY_IO_BBLOCK_OUT 17
-
-/* IODC ENTRY_SPA() */
-
-/* IODC ENTRY_CONFIG() */
-
-/* IODC ENTRY_TEST() */
-
-/* IODC ENTRY_TLB() */
-
-
-/* DEFINITION OF THE ZERO-PAGE (PAG0) */
-/* based on work by Jason Eckhardt (jason@equator.com) */
-
-#ifndef __ASSEMBLY__
-
-#define PAGE0 ((struct zeropage *)__PAGE_OFFSET)
-
struct zeropage {
/* [0x000] initialize vectors (VEC) */
unsigned int vec_special; /* must be zero */
@@ -699,93 +754,6 @@ struct zeropage {
__u32 pad608[126];
};
-#endif /* __ASSEMBLY__ */
-
-/* Page Zero constant offsets used by the HPMC handler */
-
-#define BOOT_CONSOLE_HPA_OFFSET 0x3c0
-#define BOOT_CONSOLE_SPA_OFFSET 0x3c4
-#define BOOT_CONSOLE_PATH_OFFSET 0x3a8
-
-#ifndef __ASSEMBLY__
-void pdc_console_init(void); /* in pdc_console.c */
-void pdc_console_restart(void);
-
-void setup_pdc(void); /* in inventory.c */
-
-/* wrapper-functions from pdc.c */
-
-int pdc_add_valid(unsigned long address);
-int pdc_chassis_info(struct pdc_chassis_info *chassis_info, void *led_info, unsigned long len);
-int pdc_chassis_disp(unsigned long disp);
-int pdc_chassis_warn(unsigned long *warn);
-int pdc_coproc_cfg(struct pdc_coproc_cfg *pdc_coproc_info);
-int pdc_iodc_read(unsigned long *actcnt, unsigned long hpa, unsigned int index,
- void *iodc_data, unsigned int iodc_data_size);
-int pdc_system_map_find_mods(struct pdc_system_map_mod_info *pdc_mod_info,
- struct pdc_module_path *mod_path, long mod_index);
-int pdc_system_map_find_addrs(struct pdc_system_map_addr_info *pdc_addr_info,
- long mod_index, long addr_index);
-int pdc_model_info(struct pdc_model *model);
-int pdc_model_sysmodel(char *name);
-int pdc_model_cpuid(unsigned long *cpu_id);
-int pdc_model_versions(unsigned long *versions, int id);
-int pdc_model_capabilities(unsigned long *capabilities);
-int pdc_cache_info(struct pdc_cache_info *cache);
-int pdc_spaceid_bits(unsigned long *space_bits);
-#ifndef CONFIG_PA20
-int pdc_btlb_info(struct pdc_btlb_info *btlb);
-int pdc_mem_map_hpa(struct pdc_memory_map *r_addr, struct pdc_module_path *mod_path);
-#endif /* !CONFIG_PA20 */
-int pdc_lan_station_id(char *lan_addr, unsigned long net_hpa);
-
-int pdc_stable_read(unsigned long staddr, void *memaddr, unsigned long count);
-int pdc_stable_write(unsigned long staddr, void *memaddr, unsigned long count);
-int pdc_stable_get_size(unsigned long *size);
-int pdc_stable_verify_contents(void);
-int pdc_stable_initialize(void);
-
-int pdc_pci_irt_size(unsigned long *num_entries, unsigned long hpa);
-int pdc_pci_irt(unsigned long num_entries, unsigned long hpa, void *tbl);
-
-int pdc_get_initiator(struct hardware_path *, struct pdc_initiator *);
-int pdc_tod_read(struct pdc_tod *tod);
-int pdc_tod_set(unsigned long sec, unsigned long usec);
-
-#ifdef CONFIG_64BIT
-int pdc_mem_mem_table(struct pdc_memory_table_raddr *r_addr,
- struct pdc_memory_table *tbl, unsigned long entries);
-#endif
-
-void set_firmware_width(void);
-int pdc_do_firm_test_reset(unsigned long ftc_bitmap);
-int pdc_do_reset(void);
-int pdc_soft_power_info(unsigned long *power_reg);
-int pdc_soft_power_button(int sw_control);
-void pdc_io_reset(void);
-void pdc_io_reset_devices(void);
-int pdc_iodc_getc(void);
-void pdc_iodc_putc(unsigned char c);
-void pdc_iodc_outc(unsigned char c);
-void pdc_printf(const char *fmt, ...);
-
-void pdc_emergency_unlock(void);
-int pdc_sti_call(unsigned long func, unsigned long flags,
- unsigned long inptr, unsigned long outputr,
- unsigned long glob_cfg);
-
-static inline char * os_id_to_string(u16 os_id) {
- switch(os_id) {
- case OS_ID_NONE: return "No OS";
- case OS_ID_HPUX: return "HP-UX";
- case OS_ID_MPEXL: return "MPE-iX";
- case OS_ID_OSF: return "OSF";
- case OS_ID_HPRT: return "HP-RT";
- case OS_ID_NOVEL: return "Novell Netware";
- case OS_ID_LINUX: return "Linux";
- default: return "Unknown";
- }
-}
-#endif /* __ASSEMBLY__ */
+#endif /* !defined(__ASSEMBLY__) */
#endif /* _PARISC_PDC_H */
diff --git a/include/asm-parisc/pgtable.h b/include/asm-parisc/pgtable.h
index e88cacd63724..cd0fa4f73320 100644
--- a/include/asm-parisc/pgtable.h
+++ b/include/asm-parisc/pgtable.h
@@ -11,9 +11,9 @@
*/
#include <linux/mm.h> /* for vm_area_struct */
+#include <linux/bitops.h>
#include <asm/processor.h>
#include <asm/cache.h>
-#include <asm/bitops.h>
/*
* kern_addr_valid(ADDR) tests if ADDR is pointing to valid kernel
@@ -49,14 +49,6 @@
#define pgd_ERROR(e) \
printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, (unsigned long)pgd_val(e))
- /* Note: If you change ISTACK_SIZE, you need to change the corresponding
- * values in vmlinux.lds and vmlinux64.lds (init_istack section). Also,
- * the "order" and size need to agree.
- */
-
-#define ISTACK_SIZE 32768 /* Interrupt Stack Size */
-#define ISTACK_ORDER 3
-
/* This is the size of the initially mapped kernel memory */
#ifdef CONFIG_64BIT
#define KERNEL_INITIAL_ORDER 24 /* 0 to 1<<24 = 16MB */
@@ -325,27 +317,27 @@ static inline void pgd_clear(pgd_t *pgd) {
* setup: the pgd is never bad, and a pmd always exists (as it's folded
* into the pgd entry)
*/
-extern inline int pgd_none(pgd_t pgd) { return 0; }
-extern inline int pgd_bad(pgd_t pgd) { return 0; }
-extern inline int pgd_present(pgd_t pgd) { return 1; }
-extern inline void pgd_clear(pgd_t * pgdp) { }
+static inline int pgd_none(pgd_t pgd) { return 0; }
+static inline int pgd_bad(pgd_t pgd) { return 0; }
+static inline int pgd_present(pgd_t pgd) { return 1; }
+static inline void pgd_clear(pgd_t * pgdp) { }
#endif
/*
* The following only work if pte_present() is true.
* Undefined behaviour if not..
*/
-extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
-extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
-extern inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; }
-extern inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
-
-extern inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
-extern inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
-extern inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_WRITE; return pte; }
-extern inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= _PAGE_DIRTY; return pte; }
-extern inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; return pte; }
-extern inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_WRITE; return pte; }
+static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
+static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
+static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; }
+static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
+
+static inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
+static inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
+static inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_WRITE; return pte; }
+static inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= _PAGE_DIRTY; return pte; }
+static inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; return pte; }
+static inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_WRITE; return pte; }
/*
* Conversion functions: convert a page and protection to a page entry,
@@ -369,7 +361,7 @@ static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot)
return pte;
}
-extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }
/* Permanent address of a page. On parisc we don't have highmem. */
diff --git a/include/asm-parisc/prefetch.h b/include/asm-parisc/prefetch.h
index 5d021726fa33..c5edc60c059f 100644
--- a/include/asm-parisc/prefetch.h
+++ b/include/asm-parisc/prefetch.h
@@ -19,7 +19,7 @@
#ifdef CONFIG_PREFETCH
#define ARCH_HAS_PREFETCH
-extern inline void prefetch(const void *addr)
+static inline void prefetch(const void *addr)
{
__asm__("ldw 0(%0), %%r0" : : "r" (addr));
}
@@ -27,7 +27,7 @@ extern inline void prefetch(const void *addr)
/* LDD is a PA2.0 addition. */
#ifdef CONFIG_PA20
#define ARCH_HAS_PREFETCHW
-extern inline void prefetchw(const void *addr)
+static inline void prefetchw(const void *addr)
{
__asm__("ldd 0(%0), %%r0" : : "r" (addr));
}
diff --git a/include/asm-parisc/rtc.h b/include/asm-parisc/rtc.h
index f4ebff11dcbd..099d641a42c2 100644
--- a/include/asm-parisc/rtc.h
+++ b/include/asm-parisc/rtc.h
@@ -50,10 +50,10 @@ static inline unsigned int get_rtc_time(struct rtc_time *wtime)
long int days, rem, y;
const unsigned short int *ip;
- if(pdc_tod_read(&tod_data) < 0)
+ memset(wtime, 0, sizeof(*wtime));
+ if (pdc_tod_read(&tod_data) < 0)
return RTC_24H | RTC_BATT_BAD;
-
// most of the remainder of this function is:
// Copyright (C) 1991, 1993, 1997, 1998 Free Software Foundation, Inc.
// This was originally a part of the GNU C Library.
diff --git a/include/asm-parisc/scatterlist.h b/include/asm-parisc/scatterlist.h
index e7211c748446..62269b31ebf4 100644
--- a/include/asm-parisc/scatterlist.h
+++ b/include/asm-parisc/scatterlist.h
@@ -5,7 +5,10 @@
#include <asm/types.h>
struct scatterlist {
- struct page *page;
+#ifdef CONFIG_DEBUG_SG
+ unsigned long sg_magic;
+#endif
+ unsigned long page_link;
unsigned int offset;
unsigned int length;
@@ -15,7 +18,7 @@ struct scatterlist {
__u32 iova_length; /* bytes mapped */
};
-#define sg_virt_addr(sg) ((unsigned long)(page_address(sg->page) + sg->offset))
+#define sg_virt_addr(sg) ((unsigned long)sg_virt(sg))
#define sg_dma_address(sg) ((sg)->iova)
#define sg_dma_len(sg) ((sg)->iova_length)
diff --git a/include/asm-parisc/semaphore.h b/include/asm-parisc/semaphore.h
index d45827a21f94..a16271cdc748 100644
--- a/include/asm-parisc/semaphore.h
+++ b/include/asm-parisc/semaphore.h
@@ -53,9 +53,8 @@ struct semaphore {
struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
-#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
-extern inline void sema_init (struct semaphore *sem, int val)
+static inline void sema_init (struct semaphore *sem, int val)
{
*sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
}
@@ -83,7 +82,7 @@ asmlinkage void __up(struct semaphore * sem);
* interrupts while we're messing with the semaphore. Sorry.
*/
-extern __inline__ void down(struct semaphore * sem)
+static inline void down(struct semaphore * sem)
{
might_sleep();
spin_lock_irq(&sem->sentry);
@@ -95,7 +94,7 @@ extern __inline__ void down(struct semaphore * sem)
spin_unlock_irq(&sem->sentry);
}
-extern __inline__ int down_interruptible(struct semaphore * sem)
+static inline int down_interruptible(struct semaphore * sem)
{
int ret = 0;
might_sleep();
@@ -113,7 +112,7 @@ extern __inline__ int down_interruptible(struct semaphore * sem)
* down_trylock returns 0 on success, 1 if we failed to get the lock.
* May not sleep, but must preserve irq state
*/
-extern __inline__ int down_trylock(struct semaphore * sem)
+static inline int down_trylock(struct semaphore * sem)
{
unsigned long flags;
int count;
@@ -130,7 +129,7 @@ extern __inline__ int down_trylock(struct semaphore * sem)
* Note! This is subtle. We jump to wake people up only if
* the semaphore was negative (== somebody was waiting on it).
*/
-extern __inline__ void up(struct semaphore * sem)
+static inline void up(struct semaphore * sem)
{
unsigned long flags;
diff --git a/include/asm-parisc/tlbflush.h b/include/asm-parisc/tlbflush.h
index 270cf309772b..b72ec66db699 100644
--- a/include/asm-parisc/tlbflush.h
+++ b/include/asm-parisc/tlbflush.h
@@ -57,10 +57,6 @@ static inline void flush_tlb_mm(struct mm_struct *mm)
#endif
}
-extern __inline__ void flush_tlb_pgtables(struct mm_struct *mm, unsigned long start, unsigned long end)
-{
-}
-
static inline void flush_tlb_page(struct vm_area_struct *vma,
unsigned long addr)
{
diff --git a/include/asm-parisc/types.h b/include/asm-parisc/types.h
index d4aa33033d98..56c84802da59 100644
--- a/include/asm-parisc/types.h
+++ b/include/asm-parisc/types.h
@@ -19,9 +19,9 @@ typedef unsigned short __u16;
typedef __signed__ int __s32;
typedef unsigned int __u32;
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
-typedef __signed__ long long __s64;
-typedef unsigned long long __u64;
+#if defined(__GNUC__)
+__extension__ typedef __signed__ long long __s64;
+__extension__ typedef unsigned long long __u64;
#endif
#endif /* __ASSEMBLY__ */
diff --git a/include/asm-parisc/unistd.h b/include/asm-parisc/unistd.h
index f74099bdca3c..081b4ae61866 100644
--- a/include/asm-parisc/unistd.h
+++ b/include/asm-parisc/unistd.h
@@ -797,8 +797,9 @@
#define __NR_signalfd (__NR_Linux + 302)
#define __NR_timerfd (__NR_Linux + 303)
#define __NR_eventfd (__NR_Linux + 304)
+#define __NR_fallocate (__NR_Linux + 305)
-#define __NR_Linux_syscalls (__NR_eventfd + 1)
+#define __NR_Linux_syscalls (__NR_fallocate + 1)
#define __IGNORE_select /* newselect */
diff --git a/include/asm-powerpc/Kbuild b/include/asm-powerpc/Kbuild
index 4869513b872f..5f640e542475 100644
--- a/include/asm-powerpc/Kbuild
+++ b/include/asm-powerpc/Kbuild
@@ -13,9 +13,7 @@ header-y += shmbuf.h
header-y += socket.h
header-y += termbits.h
header-y += fcntl.h
-header-y += ipc.h
header-y += poll.h
-header-y += shmparam.h
header-y += sockios.h
header-y += ucontext.h
header-y += ioctl.h
diff --git a/include/asm-powerpc/bitops.h b/include/asm-powerpc/bitops.h
index 8144a2788db6..733b4af7f4f1 100644
--- a/include/asm-powerpc/bitops.h
+++ b/include/asm-powerpc/bitops.h
@@ -38,6 +38,10 @@
#ifdef __KERNEL__
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
#include <linux/compiler.h>
#include <asm/asm-compat.h>
#include <asm/synch.h>
@@ -86,6 +90,24 @@ static __inline__ void clear_bit(int nr, volatile unsigned long *addr)
: "cc" );
}
+static __inline__ void clear_bit_unlock(int nr, volatile unsigned long *addr)
+{
+ unsigned long old;
+ unsigned long mask = BITOP_MASK(nr);
+ unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
+
+ __asm__ __volatile__(
+ LWSYNC_ON_SMP
+"1:" PPC_LLARX "%0,0,%3 # clear_bit_unlock\n"
+ "andc %0,%0,%2\n"
+ PPC405_ERR77(0,%3)
+ PPC_STLCX "%0,0,%3\n"
+ "bne- 1b"
+ : "=&r" (old), "+m" (*p)
+ : "r" (mask), "r" (p)
+ : "cc", "memory");
+}
+
static __inline__ void change_bit(int nr, volatile unsigned long *addr)
{
unsigned long old;
@@ -125,6 +147,27 @@ static __inline__ int test_and_set_bit(unsigned long nr,
return (old & mask) != 0;
}
+static __inline__ int test_and_set_bit_lock(unsigned long nr,
+ volatile unsigned long *addr)
+{
+ unsigned long old, t;
+ unsigned long mask = BITOP_MASK(nr);
+ unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
+
+ __asm__ __volatile__(
+"1:" PPC_LLARX "%0,0,%3 # test_and_set_bit_lock\n"
+ "or %1,%0,%2 \n"
+ PPC405_ERR77(0,%3)
+ PPC_STLCX "%1,0,%3 \n"
+ "bne- 1b"
+ ISYNC_ON_SMP
+ : "=&r" (old), "=&r" (t)
+ : "r" (mask), "r" (p)
+ : "cc", "memory");
+
+ return (old & mask) != 0;
+}
+
static __inline__ int test_and_clear_bit(unsigned long nr,
volatile unsigned long *addr)
{
@@ -185,6 +228,12 @@ static __inline__ void set_bits(unsigned long mask, unsigned long *addr)
#include <asm-generic/bitops/non-atomic.h>
+static __inline__ void __clear_bit_unlock(int nr, volatile unsigned long *addr)
+{
+ __asm__ __volatile__(LWSYNC_ON_SMP "" ::: "memory");
+ __clear_bit(nr, addr);
+}
+
/*
* Return the zero-based bit position (LE, not IBM bit numbering) of
* the most significant 1-bit in a double word.
diff --git a/include/asm-powerpc/commproc.h b/include/asm-powerpc/commproc.h
index 0307c84a5c1d..a2328b8addd8 100644
--- a/include/asm-powerpc/commproc.h
+++ b/include/asm-powerpc/commproc.h
@@ -91,7 +91,7 @@ extern uint m8xx_cpm_hostalloc(uint size);
extern int m8xx_cpm_hostfree(uint start);
extern void m8xx_cpm_hostdump(void);
-extern void cpm_load_patch(volatile immap_t *immr);
+extern void cpm_load_patch(cpm8xx_t *cp);
/* Buffer descriptors used by many of the CPM protocols.
*/
diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h
index ae093ef68363..4525c784dfd0 100644
--- a/include/asm-powerpc/cputable.h
+++ b/include/asm-powerpc/cputable.h
@@ -138,6 +138,7 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
#define CPU_FTR_FPU_UNAVAILABLE ASM_CONST(0x0000000000800000)
#define CPU_FTR_UNIFIED_ID_CACHE ASM_CONST(0x0000000001000000)
#define CPU_FTR_SPE ASM_CONST(0x0000000002000000)
+#define CPU_FTR_NEED_PAIRED_STWCX ASM_CONST(0x0000000004000000)
/*
* Add the 64-bit processor unique features in the top half of the word;
@@ -165,6 +166,7 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
#define CPU_FTR_SPURR LONG_ASM_CONST(0x0001000000000000)
#define CPU_FTR_DSCR LONG_ASM_CONST(0x0002000000000000)
#define CPU_FTR_1T_SEGMENT LONG_ASM_CONST(0x0004000000000000)
+#define CPU_FTR_NO_SLBIE_B LONG_ASM_CONST(0x0008000000000000)
#ifndef __ASSEMBLY__
@@ -260,25 +262,25 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
#define CPU_FTRS_7450_20 (CPU_FTR_COMMON | \
CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
- CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
+ CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE | CPU_FTR_NEED_PAIRED_STWCX)
#define CPU_FTRS_7450_21 (CPU_FTR_COMMON | \
CPU_FTR_USE_TB | \
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \
- CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
+ CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE | CPU_FTR_NEED_PAIRED_STWCX)
#define CPU_FTRS_7450_23 (CPU_FTR_COMMON | \
- CPU_FTR_USE_TB | \
+ CPU_FTR_USE_TB | CPU_FTR_NEED_PAIRED_STWCX | \
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
#define CPU_FTRS_7455_1 (CPU_FTR_COMMON | \
- CPU_FTR_USE_TB | \
+ CPU_FTR_USE_TB | CPU_FTR_NEED_PAIRED_STWCX | \
CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | \
CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_HAS_HIGH_BATS | \
CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
#define CPU_FTRS_7455_20 (CPU_FTR_COMMON | \
- CPU_FTR_USE_TB | \
+ CPU_FTR_USE_TB | CPU_FTR_NEED_PAIRED_STWCX | \
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \
@@ -288,31 +290,32 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
- CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
+ CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE | CPU_FTR_NEED_PAIRED_STWCX)
#define CPU_FTRS_7447_10 (CPU_FTR_COMMON | \
CPU_FTR_USE_TB | \
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
- CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC | CPU_FTR_PPC_LE)
+ CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC | CPU_FTR_PPC_LE | \
+ CPU_FTR_NEED_PAIRED_STWCX)
#define CPU_FTRS_7447 (CPU_FTR_COMMON | \
CPU_FTR_USE_TB | \
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
- CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
+ CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE | CPU_FTR_NEED_PAIRED_STWCX)
#define CPU_FTRS_7447A (CPU_FTR_COMMON | \
CPU_FTR_USE_TB | \
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
- CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
+ CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE | CPU_FTR_NEED_PAIRED_STWCX)
#define CPU_FTRS_7448 (CPU_FTR_COMMON | \
CPU_FTR_USE_TB | \
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
- CPU_FTR_PPC_LE)
+ CPU_FTR_PPC_LE | CPU_FTR_NEED_PAIRED_STWCX)
#define CPU_FTRS_82XX (CPU_FTR_COMMON | \
CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB)
#define CPU_FTRS_G2_LE (CPU_FTR_COMMON | CPU_FTR_MAYBE_CAN_DOZE | \
@@ -367,7 +370,7 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
#define CPU_FTRS_PA6T (CPU_FTR_USE_TB | \
CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
CPU_FTR_ALTIVEC_COMP | CPU_FTR_CI_LARGE_PAGE | \
- CPU_FTR_PURR | CPU_FTR_REAL_LE)
+ CPU_FTR_PURR | CPU_FTR_REAL_LE | CPU_FTR_NO_SLBIE_B)
#define CPU_FTRS_COMPATIBLE (CPU_FTR_USE_TB | \
CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2)
diff --git a/include/asm-powerpc/dcr-mmio.h b/include/asm-powerpc/dcr-mmio.h
index 6b82c3ba495a..08532ff1899c 100644
--- a/include/asm-powerpc/dcr-mmio.h
+++ b/include/asm-powerpc/dcr-mmio.h
@@ -33,16 +33,16 @@ typedef struct {
extern dcr_host_t dcr_map(struct device_node *dev, unsigned int dcr_n,
unsigned int dcr_c);
-extern void dcr_unmap(dcr_host_t host, unsigned int dcr_n, unsigned int dcr_c);
+extern void dcr_unmap(dcr_host_t host, unsigned int dcr_c);
static inline u32 dcr_read(dcr_host_t host, unsigned int dcr_n)
{
- return in_be32(host.token + dcr_n * host.stride);
+ return in_be32(host.token + ((host.base + dcr_n) * host.stride));
}
static inline void dcr_write(dcr_host_t host, unsigned int dcr_n, u32 value)
{
- out_be32(host.token + dcr_n * host.stride, value);
+ out_be32(host.token + ((host.base + dcr_n) * host.stride), value);
}
extern u64 of_translate_dcr_address(struct device_node *dev,
diff --git a/include/asm-powerpc/dcr-native.h b/include/asm-powerpc/dcr-native.h
index f41058c0f6cb..8dbb1ab0aa04 100644
--- a/include/asm-powerpc/dcr-native.h
+++ b/include/asm-powerpc/dcr-native.h
@@ -29,9 +29,9 @@ typedef struct {
#define DCR_MAP_OK(host) (1)
#define dcr_map(dev, dcr_n, dcr_c) ((dcr_host_t){ .base = (dcr_n) })
-#define dcr_unmap(host, dcr_n, dcr_c) do {} while (0)
-#define dcr_read(host, dcr_n) mfdcr(dcr_n)
-#define dcr_write(host, dcr_n, value) mtdcr(dcr_n, value)
+#define dcr_unmap(host, dcr_c) do {} while (0)
+#define dcr_read(host, dcr_n) mfdcr(dcr_n + host.base)
+#define dcr_write(host, dcr_n, value) mtdcr(dcr_n + host.base, value)
/* Device Control Registers */
void __mtdcr(int reg, unsigned int val);
diff --git a/include/asm-powerpc/dma-mapping.h b/include/asm-powerpc/dma-mapping.h
index d05891608f74..ff52013c0e2d 100644
--- a/include/asm-powerpc/dma-mapping.h
+++ b/include/asm-powerpc/dma-mapping.h
@@ -12,7 +12,7 @@
#include <linux/cache.h>
/* need struct page definitions */
#include <linux/mm.h>
-#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
#include <asm/io.h>
#define DMA_ERROR_CODE (~(dma_addr_t)0x0)
@@ -276,17 +276,18 @@ static inline void dma_unmap_page(struct device *dev, dma_addr_t dma_address,
}
static inline int
-dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+dma_map_sg(struct device *dev, struct scatterlist *sgl, int nents,
enum dma_data_direction direction)
{
+ struct scatterlist *sg;
int i;
BUG_ON(direction == DMA_NONE);
- for (i = 0; i < nents; i++, sg++) {
- BUG_ON(!sg->page);
- __dma_sync_page(sg->page, sg->offset, sg->length, direction);
- sg->dma_address = page_to_bus(sg->page) + sg->offset;
+ for_each_sg(sgl, sg, nents, i) {
+ BUG_ON(!sg_page(sg));
+ __dma_sync_page(sg_page(sg), sg->offset, sg->length, direction);
+ sg->dma_address = page_to_bus(sg_page(sg)) + sg->offset;
}
return nents;
@@ -318,27 +319,29 @@ static inline void dma_sync_single_for_device(struct device *dev,
}
static inline void dma_sync_sg_for_cpu(struct device *dev,
- struct scatterlist *sg, int nents,
+ struct scatterlist *sgl, int nents,
enum dma_data_direction direction)
{
+ struct scatterlist *sg;
int i;
BUG_ON(direction == DMA_NONE);
- for (i = 0; i < nents; i++, sg++)
- __dma_sync_page(sg->page, sg->offset, sg->length, direction);
+ for_each_sg(sgl, sg, nents, i)
+ __dma_sync_page(sg_page(sg), sg->offset, sg->length, direction);
}
static inline void dma_sync_sg_for_device(struct device *dev,
- struct scatterlist *sg, int nents,
+ struct scatterlist *sgl, int nents,
enum dma_data_direction direction)
{
+ struct scatterlist *sg;
int i;
BUG_ON(direction == DMA_NONE);
- for (i = 0; i < nents; i++, sg++)
- __dma_sync_page(sg->page, sg->offset, sg->length, direction);
+ for_each_sg(sgl, sg, nents, i)
+ __dma_sync_page(sg_page(sg), sg->offset, sg->length, direction);
}
static inline int dma_mapping_error(dma_addr_t dma_addr)
diff --git a/include/asm-powerpc/elf.h b/include/asm-powerpc/elf.h
index e42820d6d25b..6bd07ef78ac4 100644
--- a/include/asm-powerpc/elf.h
+++ b/include/asm-powerpc/elf.h
@@ -101,6 +101,7 @@ typedef elf_greg_t64 elf_gregset_t64[ELF_NGREG];
typedef unsigned int elf_greg_t32;
typedef elf_greg_t32 elf_gregset_t32[ELF_NGREG];
+typedef elf_gregset_t32 compat_elf_gregset_t;
/*
* ELF_ARCH, CLASS, and DATA are used to set parameters in the core dumps.
@@ -175,26 +176,27 @@ typedef elf_vrreg_t elf_vrregset_t32[ELF_NVRREG32];
#define ELF_ET_DYN_BASE (0x20000000)
-/* Common routine for both 32-bit and 64-bit processes */
+/*
+ * Our registers are always unsigned longs, whether we're a 32 bit
+ * process or 64 bit, on either a 64 bit or 32 bit kernel.
+ *
+ * This macro relies on elf_regs[i] having the right type to truncate to,
+ * either u32 or u64. It defines the body of the elf_core_copy_regs
+ * function, either the native one with elf_gregset_t elf_regs or
+ * the 32-bit one with elf_gregset_t32 elf_regs.
+ */
+#define PPC_ELF_CORE_COPY_REGS(elf_regs, regs) \
+ int i, nregs = min(sizeof(*regs) / sizeof(unsigned long), \
+ (size_t)ELF_NGREG); \
+ for (i = 0; i < nregs; i++) \
+ elf_regs[i] = ((unsigned long *) regs)[i]; \
+ memset(&elf_regs[i], 0, (ELF_NGREG - i) * sizeof(elf_regs[0]))
+
+/* Common routine for both 32-bit and 64-bit native processes */
static inline void ppc_elf_core_copy_regs(elf_gregset_t elf_regs,
- struct pt_regs *regs)
+ struct pt_regs *regs)
{
- int i, nregs;
-
- memset((void *)elf_regs, 0, sizeof(elf_gregset_t));
-
- /* Our registers are always unsigned longs, whether we're a 32 bit
- * process or 64 bit, on either a 64 bit or 32 bit kernel.
- * Don't use ELF_GREG_TYPE here. */
- nregs = sizeof(struct pt_regs) / sizeof(unsigned long);
- if (nregs > ELF_NGREG)
- nregs = ELF_NGREG;
-
- for (i = 0; i < nregs; i++) {
- /* This will correctly truncate 64 bit registers to 32 bits
- * for a 32 bit process on a 64 bit kernel. */
- elf_regs[i] = (elf_greg_t)((ELF_GREG_TYPE *)regs)[i];
- }
+ PPC_ELF_CORE_COPY_REGS(elf_regs, regs);
}
#define ELF_CORE_COPY_REGS(gregs, regs) ppc_elf_core_copy_regs(gregs, regs);
@@ -212,6 +214,14 @@ static inline int dump_task_regs(struct task_struct *tsk,
extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *);
#define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) dump_task_fpu(tsk, elf_fpregs)
+typedef elf_vrregset_t elf_fpxregset_t;
+
+#ifdef CONFIG_ALTIVEC
+extern int dump_task_altivec(struct task_struct *, elf_vrregset_t *vrregs);
+#define ELF_CORE_COPY_XFPREGS(tsk, regs) dump_task_altivec(tsk, regs)
+#define ELF_CORE_XFPREG_TYPE NT_PPC_VMX
+#endif
+
#endif /* __KERNEL__ */
/* ELF_HWCAP yields a mask that user programs can use to figure out what
@@ -281,6 +291,7 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
* AT_IGNOREPPC is used for that.
* - for compatibility with glibc ARCH_DLINFO must always be defined on PPC,
* even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
+ * update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT entries changes
*/
#define ARCH_DLINFO \
do { \
diff --git a/include/asm-powerpc/floppy.h b/include/asm-powerpc/floppy.h
index 34146f0eea63..24bd34c57e9d 100644
--- a/include/asm-powerpc/floppy.h
+++ b/include/asm-powerpc/floppy.h
@@ -202,8 +202,6 @@ static int FDC2 = -1;
#define N_FDC 2 /* Don't change this! */
#define N_DRIVE 8
-#define FLOPPY_MOTOR_MASK 0xf0
-
/*
* The PowerPC has no problems with floppy DMA crossing 64k borders.
*/
diff --git a/include/asm-powerpc/ibmebus.h b/include/asm-powerpc/ibmebus.h
index 87d396e28db2..1a9d9aea21fa 100644
--- a/include/asm-powerpc/ibmebus.h
+++ b/include/asm-powerpc/ibmebus.h
@@ -43,42 +43,18 @@
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/mod_devicetable.h>
-#include <asm/of_device.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
extern struct bus_type ibmebus_bus_type;
-struct ibmebus_dev {
- struct of_device ofdev;
-};
+int ibmebus_register_driver(struct of_platform_driver *drv);
+void ibmebus_unregister_driver(struct of_platform_driver *drv);
-struct ibmebus_driver {
- char *name;
- struct of_device_id *id_table;
- int (*probe) (struct ibmebus_dev *dev, const struct of_device_id *id);
- int (*remove) (struct ibmebus_dev *dev);
- struct device_driver driver;
-};
-
-int ibmebus_register_driver(struct ibmebus_driver *drv);
-void ibmebus_unregister_driver(struct ibmebus_driver *drv);
-
-int ibmebus_request_irq(struct ibmebus_dev *dev,
- u32 ist,
- irq_handler_t handler,
- unsigned long irq_flags, const char * devname,
+int ibmebus_request_irq(u32 ist, irq_handler_t handler,
+ unsigned long irq_flags, const char *devname,
void *dev_id);
-void ibmebus_free_irq(struct ibmebus_dev *dev, u32 ist, void *dev_id);
-
-static inline struct ibmebus_driver *to_ibmebus_driver(struct device_driver *drv)
-{
- return container_of(drv, struct ibmebus_driver, driver);
-}
-
-static inline struct ibmebus_dev *to_ibmebus_dev(struct device *dev)
-{
- return container_of(dev, struct ibmebus_dev, ofdev.dev);
-}
-
+void ibmebus_free_irq(u32 ist, void *dev_id);
#endif /* __KERNEL__ */
#endif /* _ASM_IBMEBUS_H */
diff --git a/include/asm-powerpc/ide.h b/include/asm-powerpc/ide.h
index 1644e44c8757..fd7f5a430f0a 100644
--- a/include/asm-powerpc/ide.h
+++ b/include/asm-powerpc/ide.h
@@ -69,12 +69,11 @@ static __inline__ unsigned long ide_default_io_base(int index)
#ifdef CONFIG_BLK_DEV_MPC8xx_IDE
#define IDE_ARCH_ACK_INTR 1
-#define ide_ack_intr(hwif) (hwif->hw.ack_intr ? hwif->hw.ack_intr(hwif) : 1)
+#define ide_ack_intr(hwif) ((hwif)->ack_intr ? (hwif)->ack_intr(hwif) : 1)
#endif
#endif /* __powerpc64__ */
-#define IDE_ARCH_OBSOLETE_INIT
#define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */
#endif /* __KERNEL__ */
diff --git a/include/asm-powerpc/io.h b/include/asm-powerpc/io.h
index 0d0589ef8ea6..e44cdfc8493a 100644
--- a/include/asm-powerpc/io.h
+++ b/include/asm-powerpc/io.h
@@ -498,23 +498,6 @@ static inline void name at \
#define writeq writeq
#endif
-#ifdef CONFIG_NOT_COHERENT_CACHE
-
-#define dma_cache_inv(_start,_size) \
- invalidate_dcache_range(_start, (_start + _size))
-#define dma_cache_wback(_start,_size) \
- clean_dcache_range(_start, (_start + _size))
-#define dma_cache_wback_inv(_start,_size) \
- flush_dcache_range(_start, (_start + _size))
-
-#else /* CONFIG_NOT_COHERENT_CACHE */
-
-#define dma_cache_inv(_start,_size) do { } while (0)
-#define dma_cache_wback(_start,_size) do { } while (0)
-#define dma_cache_wback_inv(_start,_size) do { } while (0)
-
-#endif /* !CONFIG_NOT_COHERENT_CACHE */
-
/*
* Convert a physical pointer to a virtual kernel pointer for /dev/mem
* access
@@ -539,7 +522,7 @@ static inline void name at \
#else
/*
* Enforce synchronisation of stores vs. spin_unlock
- * (this does it explicitely, though our implementation of spin_unlock
+ * (this does it explicitly, though our implementation of spin_unlock
* does it implicitely too)
*/
static inline void mmiowb(void)
diff --git a/include/asm-powerpc/iommu.h b/include/asm-powerpc/iommu.h
index 870967e47204..4a82fdccee92 100644
--- a/include/asm-powerpc/iommu.h
+++ b/include/asm-powerpc/iommu.h
@@ -26,9 +26,9 @@
#include <linux/spinlock.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
+#include <linux/bitops.h>
#include <asm/machdep.h>
#include <asm/types.h>
-#include <asm/bitops.h>
#define IOMMU_PAGE_SHIFT 12
#define IOMMU_PAGE_SIZE (ASM_CONST(1) << IOMMU_PAGE_SHIFT)
diff --git a/include/asm-powerpc/ipc.h b/include/asm-powerpc/ipc.h
deleted file mode 100644
index a46e3d9c2a3f..000000000000
--- a/include/asm-powerpc/ipc.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ipc.h>
diff --git a/include/asm-powerpc/kdebug.h b/include/asm-powerpc/kdebug.h
index 295f0162c608..ae6d206728af 100644
--- a/include/asm-powerpc/kdebug.h
+++ b/include/asm-powerpc/kdebug.h
@@ -2,25 +2,6 @@
#define _ASM_POWERPC_KDEBUG_H
#ifdef __KERNEL__
-/* nearly identical to x86_64/i386 code */
-
-#include <linux/notifier.h>
-
-/*
- * These are only here because kprobes.c wants them to implement a
- * blatant layering violation. Will hopefully go away soon once all
- * architectures are updated.
- */
-static inline int register_page_fault_notifier(struct notifier_block *nb)
-{
- return 0;
-}
-static inline int unregister_page_fault_notifier(struct notifier_block *nb)
-{
- return 0;
-}
-extern struct atomic_notifier_head powerpc_die_chain;
-
/* Grossly misnamed. */
enum die_val {
DIE_OOPS = 1,
diff --git a/include/asm-powerpc/kprobes.h b/include/asm-powerpc/kprobes.h
index 8b08b447d6f3..afabad230dbb 100644
--- a/include/asm-powerpc/kprobes.h
+++ b/include/asm-powerpc/kprobes.h
@@ -81,8 +81,8 @@ typedef unsigned int kprobe_opcode_t;
#endif
#define ARCH_SUPPORTS_KRETPROBES
-#define ARCH_INACTIVE_KPROBE_COUNT 1
#define flush_insn_slot(p) do { } while (0)
+#define kretprobe_blacklist_size 0
void kretprobe_trampoline(void);
extern void arch_remove_kprobe(struct kprobe *p);
diff --git a/include/asm-powerpc/mmu_context.h b/include/asm-powerpc/mmu_context.h
index f863ac21409e..9102b8bf0ead 100644
--- a/include/asm-powerpc/mmu_context.h
+++ b/include/asm-powerpc/mmu_context.h
@@ -8,7 +8,7 @@
#ifndef CONFIG_PPC64
#include <asm/atomic.h>
-#include <asm/bitops.h>
+#include <linux/bitops.h>
/*
* On 32-bit PowerPC 6xx/7xx/7xxx CPUs, we use a set of 16 VSIDs
diff --git a/include/asm-powerpc/mpc52xx.h b/include/asm-powerpc/mpc52xx.h
index 24751df791ac..fcb2ebbfddbc 100644
--- a/include/asm-powerpc/mpc52xx.h
+++ b/include/asm-powerpc/mpc52xx.h
@@ -18,6 +18,13 @@
#include <asm/prom.h>
#endif /* __ASSEMBLY__ */
+#include <linux/suspend.h>
+
+/* Variants of the 5200(B) */
+#define MPC5200_SVR 0x80110010
+#define MPC5200_SVR_MASK 0xfffffff0
+#define MPC5200B_SVR 0x80110020
+#define MPC5200B_SVR_MASK 0xfffffff0
/* ======================================================================== */
/* Structures mapping of some unit register set */
@@ -242,6 +249,7 @@ struct mpc52xx_cdm {
#ifndef __ASSEMBLY__
extern void __iomem * mpc52xx_find_and_map(const char *);
+extern void __iomem * mpc52xx_find_and_map_path(const char *path);
extern unsigned int mpc52xx_find_ipb_freq(struct device_node *node);
extern void mpc5200_setup_xlb_arbiter(void);
extern void mpc52xx_declare_of_platform_devices(void);
@@ -251,6 +259,9 @@ extern unsigned int mpc52xx_get_irq(void);
extern int __init mpc52xx_add_bridge(struct device_node *node);
+extern void __init mpc52xx_map_wdt(void);
+extern void mpc52xx_restart(char *cmd);
+
#endif /* __ASSEMBLY__ */
#ifdef CONFIG_PM
@@ -267,9 +278,9 @@ extern int mpc52xx_set_wakeup_gpio(u8 pin, u8 level);
extern int __init lite5200_pm_init(void);
/* lite5200 calls mpc5200 suspend functions, so here they are */
-extern int mpc52xx_pm_prepare(suspend_state_t);
+extern int mpc52xx_pm_prepare(void);
extern int mpc52xx_pm_enter(suspend_state_t);
-extern int mpc52xx_pm_finish(suspend_state_t);
+extern void mpc52xx_pm_finish(void);
extern char saved_sram[0x4000]; /* reuse buffer from mpc52xx suspend */
#endif
#endif /* CONFIG_PM */
diff --git a/include/asm-powerpc/of_device.h b/include/asm-powerpc/of_device.h
index 93262f2546ad..6526e139a463 100644
--- a/include/asm-powerpc/of_device.h
+++ b/include/asm-powerpc/of_device.h
@@ -17,6 +17,10 @@ struct of_device
struct device dev; /* Generic device interface */
};
+extern struct of_device *of_device_alloc(struct device_node *np,
+ const char *bus_id,
+ struct device *parent);
+
extern ssize_t of_device_get_modalias(struct of_device *ofdev,
char *str, ssize_t len);
extern int of_device_uevent(struct device *dev,
diff --git a/include/asm-powerpc/paca.h b/include/asm-powerpc/paca.h
index fcd7b428ed0b..f6dfce025adf 100644
--- a/include/asm-powerpc/paca.h
+++ b/include/asm-powerpc/paca.h
@@ -114,11 +114,12 @@ struct paca_struct {
u64 user_time; /* accumulated usermode TB ticks */
u64 system_time; /* accumulated system TB ticks */
u64 startpurr; /* PURR/TB value snapshot */
+ u64 startspurr; /* SPURR value snapshot */
+ u64 purrdelta; /* FIXME: document */
+ u64 spurrdelta; /* FIXME: document */
};
extern struct paca_struct paca[];
-void setup_boot_paca(void);
-
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_PACA_H */
diff --git a/include/asm-powerpc/pgtable-ppc32.h b/include/asm-powerpc/pgtable-ppc32.h
index 86a54a4a8a2a..fea2d8ff1e73 100644
--- a/include/asm-powerpc/pgtable-ppc32.h
+++ b/include/asm-powerpc/pgtable-ppc32.h
@@ -11,6 +11,11 @@
extern unsigned long va_to_phys(unsigned long address);
extern pte_t *va_to_pte(unsigned long address);
extern unsigned long ioremap_bot, ioremap_base;
+
+#ifdef CONFIG_44x
+extern int icache_44x_need_flush;
+#endif
+
#endif /* __ASSEMBLY__ */
/*
@@ -562,6 +567,10 @@ static inline unsigned long pte_update(pte_t *p, unsigned long clr,
: "=&r" (old), "=&r" (tmp), "=m" (*p)
: "r" (p), "r" (clr), "r" (set), "m" (*p)
: "cc" );
+#ifdef CONFIG_44x
+ if ((old & _PAGE_USER) && (old & _PAGE_HWEXEC))
+ icache_44x_need_flush = 1;
+#endif
return old;
}
#else
@@ -582,6 +591,10 @@ static inline unsigned long long pte_update(pte_t *p, unsigned long clr,
: "=&r" (old), "=&r" (tmp), "=m" (*p)
: "r" (p), "r" ((unsigned long)(p) + 4), "r" (clr), "r" (set), "m" (*p)
: "cc" );
+#ifdef CONFIG_44x
+ if ((old & _PAGE_USER) && (old & _PAGE_HWEXEC))
+ icache_44x_need_flush = 1;
+#endif
return old;
}
#endif
diff --git a/include/asm-powerpc/pgtable-ppc64.h b/include/asm-powerpc/pgtable-ppc64.h
index 300f9a199bf2..dd4c26dc57d2 100644
--- a/include/asm-powerpc/pgtable-ppc64.h
+++ b/include/asm-powerpc/pgtable-ppc64.h
@@ -68,6 +68,14 @@
#define USER_REGION_ID (0UL)
/*
+ * Defines the address of the vmemap area, in the top 16th of the
+ * kernel region.
+ */
+#define VMEMMAP_BASE (ASM_CONST(CONFIG_KERNEL_START) + \
+ (0xfUL << (REGION_SHIFT - 4)))
+#define vmemmap ((struct page *)VMEMMAP_BASE)
+
+/*
* Common bits in a linux-style PTE. These match the bits in the
* (hardware-defined) PowerPC PTE as closely as possible. Additional
* bits may be defined in pgtable-*.h
diff --git a/include/asm-powerpc/ps3av.h b/include/asm-powerpc/ps3av.h
index 7df4250802de..967930b82ed3 100644
--- a/include/asm-powerpc/ps3av.h
+++ b/include/asm-powerpc/ps3av.h
@@ -283,7 +283,7 @@
#define PS3AV_CMD_VIDEO_CS_YUV422 0x0002
#define PS3AV_CMD_VIDEO_CS_YUV444 0x0003
-/* for automode */
+/* for broadcast automode */
#define PS3AV_RESBIT_720x480P 0x0003 /* 0x0001 | 0x0002 */
#define PS3AV_RESBIT_720x576P 0x0003 /* 0x0001 | 0x0002 */
#define PS3AV_RESBIT_1280x720P 0x0004
@@ -298,13 +298,22 @@
| PS3AV_RESBIT_1920x1080I \
| PS3AV_RESBIT_1920x1080P)
+/* for VESA automode */
+#define PS3AV_RESBIT_VGA 0x0001
+#define PS3AV_RESBIT_WXGA 0x0002
+#define PS3AV_RESBIT_SXGA 0x0004
+#define PS3AV_RESBIT_WUXGA 0x0008
+#define PS3AV_RES_MASK_VESA (PS3AV_RESBIT_WXGA |\
+ PS3AV_RESBIT_SXGA |\
+ PS3AV_RESBIT_WUXGA)
+
#define PS3AV_MONITOR_TYPE_HDMI 1 /* HDMI */
#define PS3AV_MONITOR_TYPE_DVI 2 /* DVI */
-#define PS3AV_DEFAULT_HDMI_VID_REG_60 PS3AV_CMD_VIDEO_VID_480P
-#define PS3AV_DEFAULT_AVMULTI_VID_REG_60 PS3AV_CMD_VIDEO_VID_480I
-#define PS3AV_DEFAULT_HDMI_VID_REG_50 PS3AV_CMD_VIDEO_VID_576P
-#define PS3AV_DEFAULT_AVMULTI_VID_REG_50 PS3AV_CMD_VIDEO_VID_576I
-#define PS3AV_DEFAULT_DVI_VID PS3AV_CMD_VIDEO_VID_480P
+
+#define PS3AV_DEFAULT_HDMI_MODE_ID_REG_60 2 /* 480p */
+#define PS3AV_DEFAULT_AVMULTI_MODE_ID_REG_60 1 /* 480i */
+#define PS3AV_DEFAULT_HDMI_MODE_ID_REG_50 7 /* 576p */
+#define PS3AV_DEFAULT_AVMULTI_MODE_ID_REG_50 6 /* 576i */
#define PS3AV_REGION_60 0x01
#define PS3AV_REGION_50 0x02
@@ -697,20 +706,12 @@ extern int ps3av_cmd_audio_mute(int, u32 *, u32);
extern int ps3av_cmd_audio_active(int, u32);
extern int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param *, u32);
extern int ps3av_cmd_av_get_hw_conf(struct ps3av_pkt_av_get_hw_conf *);
-#ifdef PS3AV_DEBUG
-extern void ps3av_cmd_av_hw_conf_dump(const struct ps3av_pkt_av_get_hw_conf *);
-extern void ps3av_cmd_av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info *);
-#else
-static inline void ps3av_cmd_av_hw_conf_dump(const struct ps3av_pkt_av_get_hw_conf *hw_conf) {}
-static inline void ps3av_cmd_av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info *monitor_info) {}
-#endif
extern int ps3av_cmd_video_get_monitor_info(struct ps3av_pkt_av_get_monitor_info *,
u32);
-extern int ps3av_set_video_mode(u32, int);
+extern int ps3av_set_video_mode(u32);
extern int ps3av_set_audio_mode(u32, u32, u32, u32, u32);
-extern int ps3av_get_auto_mode(int);
-extern int ps3av_set_mode(u32, int);
+extern int ps3av_get_auto_mode(void);
extern int ps3av_get_mode(void);
extern int ps3av_get_scanmode(int);
extern int ps3av_get_refresh_rate(int);
diff --git a/include/asm-powerpc/scatterlist.h b/include/asm-powerpc/scatterlist.h
index 8c992d1491d4..fcf7d55afe45 100644
--- a/include/asm-powerpc/scatterlist.h
+++ b/include/asm-powerpc/scatterlist.h
@@ -14,7 +14,10 @@
#include <asm/dma.h>
struct scatterlist {
- struct page *page;
+#ifdef CONFIG_DEBUG_SG
+ unsigned long sg_magic;
+#endif
+ unsigned long page_link;
unsigned int offset;
unsigned int length;
@@ -41,5 +44,7 @@ struct scatterlist {
#define ISA_DMA_THRESHOLD (~0UL)
#endif
+#define ARCH_HAS_SG_CHAIN
+
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_SCATTERLIST_H */
diff --git a/include/asm-powerpc/semaphore.h b/include/asm-powerpc/semaphore.h
index 57369d2cadef..48dd32e07749 100644
--- a/include/asm-powerpc/semaphore.h
+++ b/include/asm-powerpc/semaphore.h
@@ -35,7 +35,6 @@ struct semaphore {
struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name, 1)
-#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name, 0)
static inline void sema_init (struct semaphore *sem, int val)
{
diff --git a/include/asm-powerpc/smp.h b/include/asm-powerpc/smp.h
index 19102bfc14ca..505f35bacaa9 100644
--- a/include/asm-powerpc/smp.h
+++ b/include/asm-powerpc/smp.h
@@ -26,6 +26,7 @@
#ifdef CONFIG_PPC64
#include <asm/paca.h>
#endif
+#include <asm/percpu.h>
extern int boot_cpuid;
@@ -58,7 +59,7 @@ extern int smp_hw_index[];
(smp_hw_index[(cpu)] = (phys))
#endif
-extern cpumask_t cpu_sibling_map[NR_CPUS];
+DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
/* Since OpenPIC has only 4 IPIs, we use slightly different message numbers.
*
@@ -77,6 +78,7 @@ void smp_init_pSeries(void);
void smp_init_cell(void);
void smp_init_celleb(void);
void smp_setup_cpu_maps(void);
+void smp_setup_cpu_sibling_map(void);
extern int __cpu_disable(void);
extern void __cpu_die(unsigned int cpu);
diff --git a/include/asm-powerpc/systbl.h b/include/asm-powerpc/systbl.h
index cc6d87228258..11d5383b2f09 100644
--- a/include/asm-powerpc/systbl.h
+++ b/include/asm-powerpc/systbl.h
@@ -308,8 +308,8 @@ COMPAT_SYS_SPU(move_pages)
SYSCALL_SPU(getcpu)
COMPAT_SYS(epoll_pwait)
COMPAT_SYS_SPU(utimensat)
-COMPAT_SYS(fallocate)
COMPAT_SYS_SPU(signalfd)
COMPAT_SYS_SPU(timerfd)
SYSCALL_SPU(eventfd)
COMPAT_SYS_SPU(sync_file_range2)
+COMPAT_SYS(fallocate)
diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h
index d10e99bf5001..87be8c3bc9cb 100644
--- a/include/asm-powerpc/system.h
+++ b/include/asm-powerpc/system.h
@@ -40,6 +40,7 @@
#define set_mb(var, value) do { var = value; mb(); } while (0)
#ifdef __KERNEL__
+#define AT_VECTOR_SIZE_ARCH 6 /* entries in ARCH_DLINFO */
#ifdef CONFIG_SMP
#define smp_mb() mb()
#define smp_rmb() rmb()
diff --git a/include/asm-powerpc/time.h b/include/asm-powerpc/time.h
index f05895522f7f..780f82642756 100644
--- a/include/asm-powerpc/time.h
+++ b/include/asm-powerpc/time.h
@@ -176,25 +176,31 @@ static inline unsigned int get_dec(void)
#endif
}
+/*
+ * Note: Book E and 4xx processors differ from other PowerPC processors
+ * in when the decrementer generates its interrupt: on the 1 to 0
+ * transition for Book E/4xx, but on the 0 to -1 transition for others.
+ */
static inline void set_dec(int val)
{
#if defined(CONFIG_40x)
mtspr(SPRN_PIT, val);
#elif defined(CONFIG_8xx_CPU6)
- set_dec_cpu6(val);
+ set_dec_cpu6(val - 1);
#else
+#ifndef CONFIG_BOOKE
+ --val;
+#endif
#ifdef CONFIG_PPC_ISERIES
- int cur_dec;
-
if (firmware_has_feature(FW_FEATURE_ISERIES) &&
get_lppaca()->shared_proc) {
get_lppaca()->virtual_decr = val;
- cur_dec = get_dec();
- if (cur_dec > val)
+ if (get_dec() > val)
HvCall_setVirtualDecr();
- } else
+ return;
+ }
#endif
- mtspr(SPRN_DEC, val);
+ mtspr(SPRN_DEC, val);
#endif /* not 40x or 8xx_CPU6 */
}
diff --git a/include/asm-powerpc/tlbflush.h b/include/asm-powerpc/tlbflush.h
index a022f806bb21..5c9108147644 100644
--- a/include/asm-powerpc/tlbflush.h
+++ b/include/asm-powerpc/tlbflush.h
@@ -1,5 +1,6 @@
#ifndef _ASM_POWERPC_TLBFLUSH_H
#define _ASM_POWERPC_TLBFLUSH_H
+
/*
* TLB flushing:
*
@@ -8,7 +9,6 @@
* - flush_tlb_page_nohash(vma, vmaddr) flushes one page if SW loaded TLB
* - flush_tlb_range(vma, start, end) flushes a range of pages
* - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
- * - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -17,9 +17,6 @@
*/
#ifdef __KERNEL__
-struct mm_struct;
-struct vm_area_struct;
-
#if defined(CONFIG_4xx) || defined(CONFIG_8xx) || defined(CONFIG_FSL_BOOKE)
/*
* TLB flushing for software loaded TLB chips
@@ -29,7 +26,9 @@ struct vm_area_struct;
* specific tlbie's
*/
-extern void _tlbie(unsigned long address);
+#include <linux/mm.h>
+
+extern void _tlbie(unsigned long address, unsigned int pid);
#if defined(CONFIG_40x) || defined(CONFIG_8xx)
#define _tlbia() asm volatile ("tlbia; sync" : : : "memory")
@@ -45,13 +44,13 @@ static inline void flush_tlb_mm(struct mm_struct *mm)
static inline void flush_tlb_page(struct vm_area_struct *vma,
unsigned long vmaddr)
{
- _tlbie(vmaddr);
+ _tlbie(vmaddr, vma ? vma->vm_mm->context.id : 0);
}
static inline void flush_tlb_page_nohash(struct vm_area_struct *vma,
unsigned long vmaddr)
{
- _tlbie(vmaddr);
+ _tlbie(vmaddr, vma ? vma->vm_mm->context.id : 0);
}
static inline void flush_tlb_range(struct vm_area_struct *vma,
@@ -174,15 +173,5 @@ extern void __flush_hash_table_range(struct mm_struct *mm, unsigned long start,
*/
extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
-/*
- * This is called in munmap when we have freed up some page-table
- * pages. We don't need to do anything here, there's nothing special
- * about our page-table pages. -- paulus
- */
-static inline void flush_tlb_pgtables(struct mm_struct *mm,
- unsigned long start, unsigned long end)
-{
-}
-
#endif /*__KERNEL__ */
#endif /* _ASM_POWERPC_TLBFLUSH_H */
diff --git a/include/asm-powerpc/topology.h b/include/asm-powerpc/topology.h
index 0ad21a849b5f..ca23b681ad05 100644
--- a/include/asm-powerpc/topology.h
+++ b/include/asm-powerpc/topology.h
@@ -108,7 +108,7 @@ static inline void sysfs_remove_device_from_node(struct sys_device *dev,
#ifdef CONFIG_PPC64
#include <asm/smp.h>
-#define topology_thread_siblings(cpu) (cpu_sibling_map[cpu])
+#define topology_thread_siblings(cpu) (per_cpu(cpu_sibling_map, cpu))
#endif
#endif
diff --git a/include/asm-powerpc/types.h b/include/asm-powerpc/types.h
index a584341c87e3..903fd1932436 100644
--- a/include/asm-powerpc/types.h
+++ b/include/asm-powerpc/types.h
@@ -40,9 +40,9 @@ typedef unsigned int __u32;
typedef __signed__ long __s64;
typedef unsigned long __u64;
#else
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
-typedef __signed__ long long __s64;
-typedef unsigned long long __u64;
+#if defined(__GNUC__)
+__extension__ typedef __signed__ long long __s64;
+__extension__ typedef unsigned long long __u64;
#endif
#endif /* __powerpc64__ */
diff --git a/include/asm-ppc/floppy.h b/include/asm-ppc/floppy.h
index ae316e6d2ca9..7d9b3f430d92 100644
--- a/include/asm-ppc/floppy.h
+++ b/include/asm-ppc/floppy.h
@@ -166,8 +166,6 @@ static int FDC2 = -1;
#define N_FDC 2 /* Don't change this! */
#define N_DRIVE 8
-#define FLOPPY_MOTOR_MASK 0xf0
-
/*
* The PowerPC has no problems with floppy DMA crossing 64k borders.
*/
diff --git a/include/asm-ppc/io.h b/include/asm-ppc/io.h
index 8f58231a8bc6..a0d409a5d80f 100644
--- a/include/asm-ppc/io.h
+++ b/include/asm-ppc/io.h
@@ -478,23 +478,6 @@ extern void pci_iounmap(struct pci_dev *dev, void __iomem *);
#include <asm/mpc8260_pci9.h>
#endif
-#ifdef CONFIG_NOT_COHERENT_CACHE
-
-#define dma_cache_inv(_start,_size) \
- invalidate_dcache_range(_start, (_start + _size))
-#define dma_cache_wback(_start,_size) \
- clean_dcache_range(_start, (_start + _size))
-#define dma_cache_wback_inv(_start,_size) \
- flush_dcache_range(_start, (_start + _size))
-
-#else
-
-#define dma_cache_inv(_start,_size) do { } while (0)
-#define dma_cache_wback(_start,_size) do { } while (0)
-#define dma_cache_wback_inv(_start,_size) do { } while (0)
-
-#endif
-
/*
* Convert a physical pointer to a virtual kernel pointer for /dev/mem
* access
diff --git a/include/asm-ppc/irq_regs.h b/include/asm-ppc/irq_regs.h
new file mode 100644
index 000000000000..3dd9c0b70270
--- /dev/null
+++ b/include/asm-ppc/irq_regs.h
@@ -0,0 +1 @@
+#include <asm-generic/irq_regs.h>
diff --git a/include/asm-ppc/mmu_context.h b/include/asm-ppc/mmu_context.h
index a6441a063e5d..b2e25d8997bf 100644
--- a/include/asm-ppc/mmu_context.h
+++ b/include/asm-ppc/mmu_context.h
@@ -2,8 +2,9 @@
#ifndef __PPC_MMU_CONTEXT_H
#define __PPC_MMU_CONTEXT_H
+#include <linux/bitops.h>
+
#include <asm/atomic.h>
-#include <asm/bitops.h>
#include <asm/mmu.h>
#include <asm/cputable.h>
#include <asm-generic/mm_hooks.h>
diff --git a/include/asm-ppc/mpc52xx_psc.h b/include/asm-ppc/mpc52xx_psc.h
index 9d850b2b20b8..c82b8d49a7da 100644
--- a/include/asm-ppc/mpc52xx_psc.h
+++ b/include/asm-ppc/mpc52xx_psc.h
@@ -28,6 +28,10 @@
#define MPC52xx_PSC_MAXNUM 6
/* Programmable Serial Controller (PSC) status register bits */
+#define MPC52xx_PSC_SR_UNEX_RX 0x0001
+#define MPC52xx_PSC_SR_DATA_VAL 0x0002
+#define MPC52xx_PSC_SR_DATA_OVR 0x0004
+#define MPC52xx_PSC_SR_CMDSEND 0x0008
#define MPC52xx_PSC_SR_CDE 0x0080
#define MPC52xx_PSC_SR_RXRDY 0x0100
#define MPC52xx_PSC_SR_RXFULL 0x0200
@@ -132,8 +136,10 @@ struct mpc52xx_psc {
u8 reserved5[3];
u8 ctlr; /* PSC + 0x1c */
u8 reserved6[3];
- u16 ccr; /* PSC + 0x20 */
- u8 reserved7[14];
+ u32 ccr; /* PSC + 0x20 */
+ u32 ac97_slots; /* PSC + 0x24 */
+ u32 ac97_cmd; /* PSC + 0x28 */
+ u32 ac97_data; /* PSC + 0x2c */
u8 ivr; /* PSC + 0x30 */
u8 reserved8[3];
u8 ip; /* PSC + 0x34 */
diff --git a/include/asm-ppc/system.h b/include/asm-ppc/system.h
index cc45780421ca..51df94c73846 100644
--- a/include/asm-ppc/system.h
+++ b/include/asm-ppc/system.h
@@ -33,6 +33,7 @@
#define set_mb(var, value) do { var = value; mb(); } while (0)
+#define AT_VECTOR_SIZE_ARCH 6 /* entries in ARCH_DLINFO */
#ifdef CONFIG_SMP
#define smp_mb() mb()
#define smp_rmb() rmb()
diff --git a/include/asm-ppc/time.h b/include/asm-ppc/time.h
index f7eadf6ac806..81dbcd43a501 100644
--- a/include/asm-ppc/time.h
+++ b/include/asm-ppc/time.h
@@ -57,7 +57,7 @@ static __inline__ void set_dec(unsigned int val)
/* Accessor functions for the timebase (RTC on 601) registers. */
/* If one day CONFIG_POWER is added just define __USE_RTC as 1 */
#ifdef CONFIG_6xx
-extern __inline__ int __attribute_pure__ __USE_RTC(void) {
+extern __inline__ int __pure __USE_RTC(void) {
return (mfspr(SPRN_PVR)>>16) == 1;
}
#else
diff --git a/include/asm-s390/bitops.h b/include/asm-s390/bitops.h
index f79c9b792af1..34d9a6357c38 100644
--- a/include/asm-s390/bitops.h
+++ b/include/asm-s390/bitops.h
@@ -15,6 +15,10 @@
#ifdef __KERNEL__
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
#include <linux/compiler.h>
/*
@@ -746,6 +750,7 @@ static inline int sched_find_first_bit(unsigned long *b)
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/lock.h>
/*
* ATTENTION: intel byte ordering convention for ext2 and minix !!
diff --git a/include/asm-s390/cpu.h b/include/asm-s390/cpu.h
new file mode 100644
index 000000000000..352dde194f3c
--- /dev/null
+++ b/include/asm-s390/cpu.h
@@ -0,0 +1,25 @@
+/*
+ * include/asm-s390/cpu.h
+ *
+ * Copyright IBM Corp. 2007
+ * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
+ */
+
+#ifndef _ASM_S390_CPU_H_
+#define _ASM_S390_CPU_H_
+
+#include <linux/types.h>
+#include <linux/percpu.h>
+#include <linux/spinlock.h>
+
+struct s390_idle_data {
+ spinlock_t lock;
+ unsigned int in_idle;
+ unsigned long long idle_count;
+ unsigned long long idle_enter;
+ unsigned long long idle_time;
+};
+
+DECLARE_PER_CPU(struct s390_idle_data, s390_idle);
+
+#endif /* _ASM_S390_CPU_H_ */
diff --git a/include/asm-s390/ipc.h b/include/asm-s390/ipc.h
deleted file mode 100644
index a46e3d9c2a3f..000000000000
--- a/include/asm-s390/ipc.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ipc.h>
diff --git a/include/asm-s390/kdebug.h b/include/asm-s390/kdebug.h
index 04418af08f85..40db27cd6e60 100644
--- a/include/asm-s390/kdebug.h
+++ b/include/asm-s390/kdebug.h
@@ -4,24 +4,9 @@
/*
* Feb 2006 Ported to s390 <grundym@us.ibm.com>
*/
-#include <linux/notifier.h>
struct pt_regs;
-/*
- * These are only here because kprobes.c wants them to implement a
- * blatant layering violation. Will hopefully go away soon once all
- * architectures are updated.
- */
-static inline int register_page_fault_notifier(struct notifier_block *nb)
-{
- return 0;
-}
-static inline int unregister_page_fault_notifier(struct notifier_block *nb)
-{
- return 0;
-}
-
enum die_val {
DIE_OOPS = 1,
DIE_BPT,
diff --git a/include/asm-s390/kprobes.h b/include/asm-s390/kprobes.h
index 340ba10446ea..948db3d0d05c 100644
--- a/include/asm-s390/kprobes.h
+++ b/include/asm-s390/kprobes.h
@@ -47,7 +47,7 @@ typedef u16 kprobe_opcode_t;
: (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR)))
#define ARCH_SUPPORTS_KRETPROBES
-#define ARCH_INACTIVE_KPROBE_COUNT 0
+#define kretprobe_blacklist_size 0
#define KPROBE_SWAP_INST 0x10
diff --git a/include/asm-s390/mmu_context.h b/include/asm-s390/mmu_context.h
index 501cb9b06314..05b842126b99 100644
--- a/include/asm-s390/mmu_context.h
+++ b/include/asm-s390/mmu_context.h
@@ -21,45 +21,43 @@
#ifndef __s390x__
#define LCTL_OPCODE "lctl"
-#define PGTABLE_BITS (_SEGMENT_TABLE|USER_STD_MASK)
#else
#define LCTL_OPCODE "lctlg"
-#define PGTABLE_BITS (_REGION_TABLE|USER_STD_MASK)
#endif
-static inline void enter_lazy_tlb(struct mm_struct *mm,
- struct task_struct *tsk)
+static inline void update_mm(struct mm_struct *mm, struct task_struct *tsk)
{
+ pgd_t *pgd = mm->pgd;
+ unsigned long asce_bits;
+
+ /* Calculate asce bits from the first pgd table entry. */
+ asce_bits = _ASCE_TABLE_LENGTH | _ASCE_USER_BITS;
+#ifdef CONFIG_64BIT
+ asce_bits |= _ASCE_TYPE_REGION3;
+#endif
+ S390_lowcore.user_asce = asce_bits | __pa(pgd);
+ if (switch_amode) {
+ /* Load primary space page table origin. */
+ pgd_t *shadow_pgd = get_shadow_table(pgd) ? : pgd;
+ S390_lowcore.user_exec_asce = asce_bits | __pa(shadow_pgd);
+ asm volatile(LCTL_OPCODE" 1,1,%0\n"
+ : : "m" (S390_lowcore.user_exec_asce) );
+ } else
+ /* Load home space page table origin. */
+ asm volatile(LCTL_OPCODE" 13,13,%0"
+ : : "m" (S390_lowcore.user_asce) );
}
static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
struct task_struct *tsk)
{
- pgd_t *shadow_pgd = get_shadow_pgd(next->pgd);
-
- if (prev != next) {
- S390_lowcore.user_asce = (__pa(next->pgd) & PAGE_MASK) |
- PGTABLE_BITS;
- if (shadow_pgd) {
- /* Load primary/secondary space page table origin. */
- S390_lowcore.user_exec_asce =
- (__pa(shadow_pgd) & PAGE_MASK) | PGTABLE_BITS;
- asm volatile(LCTL_OPCODE" 1,1,%0\n"
- LCTL_OPCODE" 7,7,%1"
- : : "m" (S390_lowcore.user_exec_asce),
- "m" (S390_lowcore.user_asce) );
- } else if (switch_amode) {
- /* Load primary space page table origin. */
- asm volatile(LCTL_OPCODE" 1,1,%0"
- : : "m" (S390_lowcore.user_asce) );
- } else
- /* Load home space page table origin. */
- asm volatile(LCTL_OPCODE" 13,13,%0"
- : : "m" (S390_lowcore.user_asce) );
- }
+ if (unlikely(prev == next))
+ return;
cpu_set(smp_processor_id(), next->cpu_vm_mask);
+ update_mm(next, tsk);
}
+#define enter_lazy_tlb(mm,tsk) do { } while (0)
#define deactivate_mm(tsk,mm) do { } while (0)
static inline void activate_mm(struct mm_struct *prev,
diff --git a/include/asm-s390/page.h b/include/asm-s390/page.h
index ceec3826a67c..584d0ee3c7f6 100644
--- a/include/asm-s390/page.h
+++ b/include/asm-s390/page.h
@@ -82,6 +82,7 @@ typedef struct { unsigned long pte; } pte_t;
#ifndef __s390x__
typedef struct { unsigned long pmd; } pmd_t;
+typedef struct { unsigned long pud; } pud_t;
typedef struct {
unsigned long pgd0;
unsigned long pgd1;
@@ -90,6 +91,7 @@ typedef struct {
} pgd_t;
#define pmd_val(x) ((x).pmd)
+#define pud_val(x) ((x).pud)
#define pgd_val(x) ((x).pgd0)
#else /* __s390x__ */
@@ -98,10 +100,12 @@ typedef struct {
unsigned long pmd0;
unsigned long pmd1;
} pmd_t;
+typedef struct { unsigned long pud; } pud_t;
typedef struct { unsigned long pgd; } pgd_t;
#define pmd_val(x) ((x).pmd0)
#define pmd_val1(x) ((x).pmd1)
+#define pud_val(x) ((x).pud)
#define pgd_val(x) ((x).pgd)
#endif /* __s390x__ */
diff --git a/include/asm-s390/pgalloc.h b/include/asm-s390/pgalloc.h
index e45d3c9a4b7e..709dd1740956 100644
--- a/include/asm-s390/pgalloc.h
+++ b/include/asm-s390/pgalloc.h
@@ -19,140 +19,115 @@
#define check_pgt_cache() do {} while (0)
-/*
- * Page allocation orders.
- */
-#ifndef __s390x__
-# define PTE_ALLOC_ORDER 0
-# define PMD_ALLOC_ORDER 0
-# define PGD_ALLOC_ORDER 1
-#else /* __s390x__ */
-# define PTE_ALLOC_ORDER 0
-# define PMD_ALLOC_ORDER 2
-# define PGD_ALLOC_ORDER 2
-#endif /* __s390x__ */
+unsigned long *crst_table_alloc(struct mm_struct *, int);
+void crst_table_free(unsigned long *);
-/*
- * Allocate and free page tables. The xxx_kernel() versions are
- * used to allocate a kernel page table - this turns on ASN bits
- * if any.
- */
+unsigned long *page_table_alloc(int);
+void page_table_free(unsigned long *);
-static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+static inline void clear_table(unsigned long *s, unsigned long val, size_t n)
{
- pgd_t *pgd = (pgd_t *) __get_free_pages(GFP_KERNEL, PGD_ALLOC_ORDER);
- int i;
-
- if (!pgd)
- return NULL;
- if (s390_noexec) {
- pgd_t *shadow_pgd = (pgd_t *)
- __get_free_pages(GFP_KERNEL, PGD_ALLOC_ORDER);
- struct page *page = virt_to_page(pgd);
-
- if (!shadow_pgd) {
- free_pages((unsigned long) pgd, PGD_ALLOC_ORDER);
- return NULL;
- }
- page->lru.next = (void *) shadow_pgd;
- }
- for (i = 0; i < PTRS_PER_PGD; i++)
-#ifndef __s390x__
- pmd_clear(pmd_offset(pgd + i, i*PGDIR_SIZE));
+ *s = val;
+ n = (n / 256) - 1;
+ asm volatile(
+#ifdef CONFIG_64BIT
+ " mvc 8(248,%0),0(%0)\n"
#else
- pgd_clear(pgd + i);
+ " mvc 4(252,%0),0(%0)\n"
#endif
- return pgd;
+ "0: mvc 256(256,%0),0(%0)\n"
+ " la %0,256(%0)\n"
+ " brct %1,0b\n"
+ : "+a" (s), "+d" (n));
}
-static inline void pgd_free(pgd_t *pgd)
+static inline void crst_table_init(unsigned long *crst, unsigned long entry)
{
- pgd_t *shadow_pgd = get_shadow_pgd(pgd);
-
- if (shadow_pgd)
- free_pages((unsigned long) shadow_pgd, PGD_ALLOC_ORDER);
- free_pages((unsigned long) pgd, PGD_ALLOC_ORDER);
+ clear_table(crst, entry, sizeof(unsigned long)*2048);
+ crst = get_shadow_table(crst);
+ if (crst)
+ clear_table(crst, entry, sizeof(unsigned long)*2048);
}
#ifndef __s390x__
-/*
- * page middle directory allocation/free routines.
- * We use pmd cache only on s390x, so these are dummy routines. This
- * code never triggers because the pgd will always be present.
- */
-#define pmd_alloc_one(mm,address) ({ BUG(); ((pmd_t *)2); })
-#define pmd_free(x) do { } while (0)
-#define __pmd_free_tlb(tlb,x) do { } while (0)
-#define pgd_populate(mm, pmd, pte) BUG()
-#define pgd_populate_kernel(mm, pmd, pte) BUG()
-#else /* __s390x__ */
-static inline pmd_t * pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
+
+static inline unsigned long pgd_entry_type(struct mm_struct *mm)
{
- pmd_t *pmd = (pmd_t *) __get_free_pages(GFP_KERNEL, PMD_ALLOC_ORDER);
- int i;
-
- if (!pmd)
- return NULL;
- if (s390_noexec) {
- pmd_t *shadow_pmd = (pmd_t *)
- __get_free_pages(GFP_KERNEL, PMD_ALLOC_ORDER);
- struct page *page = virt_to_page(pmd);
-
- if (!shadow_pmd) {
- free_pages((unsigned long) pmd, PMD_ALLOC_ORDER);
- return NULL;
- }
- page->lru.next = (void *) shadow_pmd;
- }
- for (i=0; i < PTRS_PER_PMD; i++)
- pmd_clear(pmd + i);
- return pmd;
+ return _SEGMENT_ENTRY_EMPTY;
}
-static inline void pmd_free (pmd_t *pmd)
+#define pud_alloc_one(mm,address) ({ BUG(); ((pud_t *)2); })
+#define pud_free(x) do { } while (0)
+
+#define pmd_alloc_one(mm,address) ({ BUG(); ((pmd_t *)2); })
+#define pmd_free(x) do { } while (0)
+
+#define pgd_populate(mm, pgd, pud) BUG()
+#define pgd_populate_kernel(mm, pgd, pud) BUG()
+
+#define pud_populate(mm, pud, pmd) BUG()
+#define pud_populate_kernel(mm, pud, pmd) BUG()
+
+#else /* __s390x__ */
+
+static inline unsigned long pgd_entry_type(struct mm_struct *mm)
{
- pmd_t *shadow_pmd = get_shadow_pmd(pmd);
+ return _REGION3_ENTRY_EMPTY;
+}
+
+#define pud_alloc_one(mm,address) ({ BUG(); ((pud_t *)2); })
+#define pud_free(x) do { } while (0)
- if (shadow_pmd)
- free_pages((unsigned long) shadow_pmd, PMD_ALLOC_ORDER);
- free_pages((unsigned long) pmd, PMD_ALLOC_ORDER);
+static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
+{
+ unsigned long *crst = crst_table_alloc(mm, s390_noexec);
+ if (crst)
+ crst_table_init(crst, _SEGMENT_ENTRY_EMPTY);
+ return (pmd_t *) crst;
}
+#define pmd_free(pmd) crst_table_free((unsigned long *) pmd)
-#define __pmd_free_tlb(tlb,pmd) \
- do { \
- tlb_flush_mmu(tlb, 0, 0); \
- pmd_free(pmd); \
- } while (0)
+#define pgd_populate(mm, pgd, pud) BUG()
+#define pgd_populate_kernel(mm, pgd, pud) BUG()
-static inline void
-pgd_populate_kernel(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd)
+static inline void pud_populate_kernel(struct mm_struct *mm,
+ pud_t *pud, pmd_t *pmd)
{
- pgd_val(*pgd) = _PGD_ENTRY | __pa(pmd);
+ pud_val(*pud) = _REGION3_ENTRY | __pa(pmd);
}
-static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd)
+static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
{
- pgd_t *shadow_pgd = get_shadow_pgd(pgd);
- pmd_t *shadow_pmd = get_shadow_pmd(pmd);
+ pud_t *shadow_pud = get_shadow_table(pud);
+ pmd_t *shadow_pmd = get_shadow_table(pmd);
- if (shadow_pgd && shadow_pmd)
- pgd_populate_kernel(mm, shadow_pgd, shadow_pmd);
- pgd_populate_kernel(mm, pgd, pmd);
+ if (shadow_pud && shadow_pmd)
+ pud_populate_kernel(mm, shadow_pud, shadow_pmd);
+ pud_populate_kernel(mm, pud, pmd);
}
#endif /* __s390x__ */
+static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+ unsigned long *crst = crst_table_alloc(mm, s390_noexec);
+ if (crst)
+ crst_table_init(crst, pgd_entry_type(mm));
+ return (pgd_t *) crst;
+}
+#define pgd_free(pgd) crst_table_free((unsigned long *) pgd)
+
static inline void
pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *pte)
{
#ifndef __s390x__
- pmd_val(pmd[0]) = _PAGE_TABLE + __pa(pte);
- pmd_val(pmd[1]) = _PAGE_TABLE + __pa(pte+256);
- pmd_val(pmd[2]) = _PAGE_TABLE + __pa(pte+512);
- pmd_val(pmd[3]) = _PAGE_TABLE + __pa(pte+768);
+ pmd_val(pmd[0]) = _SEGMENT_ENTRY + __pa(pte);
+ pmd_val(pmd[1]) = _SEGMENT_ENTRY + __pa(pte+256);
+ pmd_val(pmd[2]) = _SEGMENT_ENTRY + __pa(pte+512);
+ pmd_val(pmd[3]) = _SEGMENT_ENTRY + __pa(pte+768);
#else /* __s390x__ */
- pmd_val(*pmd) = _PMD_ENTRY + __pa(pte);
- pmd_val1(*pmd) = _PMD_ENTRY + __pa(pte+256);
+ pmd_val(*pmd) = _SEGMENT_ENTRY + __pa(pte);
+ pmd_val1(*pmd) = _SEGMENT_ENTRY + __pa(pte+256);
#endif /* __s390x__ */
}
@@ -160,7 +135,7 @@ static inline void
pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *page)
{
pte_t *pte = (pte_t *)page_to_phys(page);
- pmd_t *shadow_pmd = get_shadow_pmd(pmd);
+ pmd_t *shadow_pmd = get_shadow_table(pmd);
pte_t *shadow_pte = get_shadow_pte(pte);
pmd_populate_kernel(mm, pmd, pte);
@@ -171,67 +146,14 @@ pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *page)
/*
* page table entry allocation/free routines.
*/
-static inline pte_t *
-pte_alloc_one_kernel(struct mm_struct *mm, unsigned long vmaddr)
-{
- pte_t *pte = (pte_t *) __get_free_page(GFP_KERNEL|__GFP_REPEAT);
- int i;
-
- if (!pte)
- return NULL;
- if (s390_noexec) {
- pte_t *shadow_pte = (pte_t *)
- __get_free_page(GFP_KERNEL|__GFP_REPEAT);
- struct page *page = virt_to_page(pte);
-
- if (!shadow_pte) {
- free_page((unsigned long) pte);
- return NULL;
- }
- page->lru.next = (void *) shadow_pte;
- }
- for (i=0; i < PTRS_PER_PTE; i++) {
- pte_clear(mm, vmaddr, pte + i);
- vmaddr += PAGE_SIZE;
- }
- return pte;
-}
-
-static inline struct page *
-pte_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
-{
- pte_t *pte = pte_alloc_one_kernel(mm, vmaddr);
- if (pte)
- return virt_to_page(pte);
- return NULL;
-}
-
-static inline void pte_free_kernel(pte_t *pte)
-{
- pte_t *shadow_pte = get_shadow_pte(pte);
-
- if (shadow_pte)
- free_page((unsigned long) shadow_pte);
- free_page((unsigned long) pte);
-}
-
-static inline void pte_free(struct page *pte)
-{
- struct page *shadow_page = get_shadow_page(pte);
-
- if (shadow_page)
- __free_page(shadow_page);
- __free_page(pte);
-}
-
-#define __pte_free_tlb(tlb, pte) \
-({ \
- struct mmu_gather *__tlb = (tlb); \
- struct page *__pte = (pte); \
- struct page *shadow_page = get_shadow_page(__pte); \
- if (shadow_page) \
- tlb_remove_page(__tlb, shadow_page); \
- tlb_remove_page(__tlb, __pte); \
-})
+#define pte_alloc_one_kernel(mm, vmaddr) \
+ ((pte_t *) page_table_alloc(s390_noexec))
+#define pte_alloc_one(mm, vmaddr) \
+ virt_to_page(page_table_alloc(s390_noexec))
+
+#define pte_free_kernel(pte) \
+ page_table_free((unsigned long *) pte)
+#define pte_free(pte) \
+ page_table_free((unsigned long *) page_to_phys((struct page *) pte))
#endif /* _S390_PGALLOC_H */
diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h
index 39bb5192dc31..f2cc25b74adf 100644
--- a/include/asm-s390/pgtable.h
+++ b/include/asm-s390/pgtable.h
@@ -13,8 +13,6 @@
#ifndef _ASM_S390_PGTABLE_H
#define _ASM_S390_PGTABLE_H
-#include <asm-generic/4level-fixup.h>
-
/*
* The Linux memory management assumes a three-level page table setup. For
* s390 31 bit we "fold" the mid level into the top-level page table, so
@@ -35,9 +33,6 @@
#include <asm/bug.h>
#include <asm/processor.h>
-struct vm_area_struct; /* forward declaration (include/linux/mm.h) */
-struct mm_struct;
-
extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096)));
extern void paging_init(void);
extern void vmem_map_init(void);
@@ -63,14 +58,18 @@ extern char empty_zero_page[PAGE_SIZE];
*/
#ifndef __s390x__
# define PMD_SHIFT 22
+# define PUD_SHIFT 22
# define PGDIR_SHIFT 22
#else /* __s390x__ */
# define PMD_SHIFT 21
+# define PUD_SHIFT 31
# define PGDIR_SHIFT 31
#endif /* __s390x__ */
#define PMD_SIZE (1UL << PMD_SHIFT)
#define PMD_MASK (~(PMD_SIZE-1))
+#define PUD_SIZE (1UL << PUD_SHIFT)
+#define PUD_MASK (~(PUD_SIZE-1))
#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
#define PGDIR_MASK (~(PGDIR_SIZE-1))
@@ -83,10 +82,12 @@ extern char empty_zero_page[PAGE_SIZE];
#ifndef __s390x__
# define PTRS_PER_PTE 1024
# define PTRS_PER_PMD 1
+# define PTRS_PER_PUD 1
# define PTRS_PER_PGD 512
#else /* __s390x__ */
# define PTRS_PER_PTE 512
# define PTRS_PER_PMD 1024
+# define PTRS_PER_PUD 1
# define PTRS_PER_PGD 2048
#endif /* __s390x__ */
@@ -96,6 +97,8 @@ extern char empty_zero_page[PAGE_SIZE];
printk("%s:%d: bad pte %p.\n", __FILE__, __LINE__, (void *) pte_val(e))
#define pmd_ERROR(e) \
printk("%s:%d: bad pmd %p.\n", __FILE__, __LINE__, (void *) pmd_val(e))
+#define pud_ERROR(e) \
+ printk("%s:%d: bad pud %p.\n", __FILE__, __LINE__, (void *) pud_val(e))
#define pgd_ERROR(e) \
printk("%s:%d: bad pgd %p.\n", __FILE__, __LINE__, (void *) pgd_val(e))
@@ -195,7 +198,7 @@ extern unsigned long vmalloc_end;
* I Segment-Invalid Bit: Segment is not available for address-translation
* TT Type 01
* TF
- * TL Table lenght
+ * TL Table length
*
* The 64 bit regiontable origin of S390 has following format:
* | region table origon | DTTL
@@ -221,6 +224,8 @@ extern unsigned long vmalloc_end;
/* Hardware bits in the page table entry */
#define _PAGE_RO 0x200 /* HW read-only bit */
#define _PAGE_INVALID 0x400 /* HW invalid bit */
+
+/* Software bits in the page table entry */
#define _PAGE_SWT 0x001 /* SW pte type bit t */
#define _PAGE_SWX 0x002 /* SW pte type bit x */
@@ -264,60 +269,75 @@ extern unsigned long vmalloc_end;
#ifndef __s390x__
-/* Bits in the segment table entry */
-#define _PAGE_TABLE_LEN 0xf /* only full page-tables */
-#define _PAGE_TABLE_COM 0x10 /* common page-table */
-#define _PAGE_TABLE_INV 0x20 /* invalid page-table */
-#define _SEG_PRESENT 0x001 /* Software (overlap with PTL) */
-
-/* Bits int the storage key */
-#define _PAGE_CHANGED 0x02 /* HW changed bit */
-#define _PAGE_REFERENCED 0x04 /* HW referenced bit */
-
-#define _USER_SEG_TABLE_LEN 0x7f /* user-segment-table up to 2 GB */
-#define _KERNEL_SEG_TABLE_LEN 0x7f /* kernel-segment-table up to 2 GB */
-
-/*
- * User and Kernel pagetables are identical
- */
-#define _PAGE_TABLE _PAGE_TABLE_LEN
-#define _KERNPG_TABLE _PAGE_TABLE_LEN
-
-/*
- * The Kernel segment-tables includes the User segment-table
- */
+/* Bits in the segment table address-space-control-element */
+#define _ASCE_SPACE_SWITCH 0x80000000UL /* space switch event */
+#define _ASCE_ORIGIN_MASK 0x7ffff000UL /* segment table origin */
+#define _ASCE_PRIVATE_SPACE 0x100 /* private space control */
+#define _ASCE_ALT_EVENT 0x80 /* storage alteration event control */
+#define _ASCE_TABLE_LENGTH 0x7f /* 128 x 64 entries = 8k */
-#define _SEGMENT_TABLE (_USER_SEG_TABLE_LEN|0x80000000|0x100)
-#define _KERNSEG_TABLE _KERNEL_SEG_TABLE_LEN
+/* Bits in the segment table entry */
+#define _SEGMENT_ENTRY_ORIGIN 0x7fffffc0UL /* page table origin */
+#define _SEGMENT_ENTRY_INV 0x20 /* invalid segment table entry */
+#define _SEGMENT_ENTRY_COMMON 0x10 /* common segment bit */
+#define _SEGMENT_ENTRY_PTL 0x0f /* page table length */
-#define USER_STD_MASK 0x00000080UL
+#define _SEGMENT_ENTRY (_SEGMENT_ENTRY_PTL)
+#define _SEGMENT_ENTRY_EMPTY (_SEGMENT_ENTRY_INV)
#else /* __s390x__ */
+/* Bits in the segment/region table address-space-control-element */
+#define _ASCE_ORIGIN ~0xfffUL/* segment table origin */
+#define _ASCE_PRIVATE_SPACE 0x100 /* private space control */
+#define _ASCE_ALT_EVENT 0x80 /* storage alteration event control */
+#define _ASCE_SPACE_SWITCH 0x40 /* space switch event */
+#define _ASCE_REAL_SPACE 0x20 /* real space control */
+#define _ASCE_TYPE_MASK 0x0c /* asce table type mask */
+#define _ASCE_TYPE_REGION1 0x0c /* region first table type */
+#define _ASCE_TYPE_REGION2 0x08 /* region second table type */
+#define _ASCE_TYPE_REGION3 0x04 /* region third table type */
+#define _ASCE_TYPE_SEGMENT 0x00 /* segment table type */
+#define _ASCE_TABLE_LENGTH 0x03 /* region table length */
+
+/* Bits in the region table entry */
+#define _REGION_ENTRY_ORIGIN ~0xfffUL/* region/segment table origin */
+#define _REGION_ENTRY_INV 0x20 /* invalid region table entry */
+#define _REGION_ENTRY_TYPE_MASK 0x0c /* region/segment table type mask */
+#define _REGION_ENTRY_TYPE_R1 0x0c /* region first table type */
+#define _REGION_ENTRY_TYPE_R2 0x08 /* region second table type */
+#define _REGION_ENTRY_TYPE_R3 0x04 /* region third table type */
+#define _REGION_ENTRY_LENGTH 0x03 /* region third length */
+
+#define _REGION1_ENTRY (_REGION_ENTRY_TYPE_R1 | _REGION_ENTRY_LENGTH)
+#define _REGION1_ENTRY_EMPTY (_REGION_ENTRY_TYPE_R1 | _REGION_ENTRY_INV)
+#define _REGION2_ENTRY (_REGION_ENTRY_TYPE_R2 | _REGION_ENTRY_LENGTH)
+#define _REGION2_ENTRY_EMPTY (_REGION_ENTRY_TYPE_R2 | _REGION_ENTRY_INV)
+#define _REGION3_ENTRY (_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_LENGTH)
+#define _REGION3_ENTRY_EMPTY (_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_INV)
+
/* Bits in the segment table entry */
-#define _PMD_ENTRY_INV 0x20 /* invalid segment table entry */
-#define _PMD_ENTRY 0x00
+#define _SEGMENT_ENTRY_ORIGIN ~0x7ffUL/* segment table origin */
+#define _SEGMENT_ENTRY_RO 0x200 /* page protection bit */
+#define _SEGMENT_ENTRY_INV 0x20 /* invalid segment table entry */
+
+#define _SEGMENT_ENTRY (0)
+#define _SEGMENT_ENTRY_EMPTY (_SEGMENT_ENTRY_INV)
-/* Bits in the region third table entry */
-#define _PGD_ENTRY_INV 0x20 /* invalid region table entry */
-#define _PGD_ENTRY 0x07
+#endif /* __s390x__ */
/*
- * User and kernel page directory
+ * A user page table pointer has the space-switch-event bit, the
+ * private-space-control bit and the storage-alteration-event-control
+ * bit set. A kernel page table pointer doesn't need them.
*/
-#define _REGION_THIRD 0x4
-#define _REGION_THIRD_LEN 0x3
-#define _REGION_TABLE (_REGION_THIRD|_REGION_THIRD_LEN|0x40|0x100)
-#define _KERN_REGION_TABLE (_REGION_THIRD|_REGION_THIRD_LEN)
-
-#define USER_STD_MASK 0x0000000000000080UL
+#define _ASCE_USER_BITS (_ASCE_SPACE_SWITCH | _ASCE_PRIVATE_SPACE | \
+ _ASCE_ALT_EVENT)
-/* Bits in the storage key */
+/* Bits int the storage key */
#define _PAGE_CHANGED 0x02 /* HW changed bit */
#define _PAGE_REFERENCED 0x04 /* HW referenced bit */
-#endif /* __s390x__ */
-
/*
* Page protection definitions.
*/
@@ -358,65 +378,38 @@ extern unsigned long vmalloc_end;
#define __S111 PAGE_EX_RW
#ifndef __s390x__
-# define PMD_SHADOW_SHIFT 1
-# define PGD_SHADOW_SHIFT 1
+# define PxD_SHADOW_SHIFT 1
#else /* __s390x__ */
-# define PMD_SHADOW_SHIFT 2
-# define PGD_SHADOW_SHIFT 2
+# define PxD_SHADOW_SHIFT 2
#endif /* __s390x__ */
static inline struct page *get_shadow_page(struct page *page)
{
- if (s390_noexec && !list_empty(&page->lru))
- return virt_to_page(page->lru.next);
- return NULL;
-}
-
-static inline pte_t *get_shadow_pte(pte_t *ptep)
-{
- unsigned long pteptr = (unsigned long) (ptep);
-
- if (s390_noexec) {
- unsigned long offset = pteptr & (PAGE_SIZE - 1);
- void *addr = (void *) (pteptr ^ offset);
- struct page *page = virt_to_page(addr);
- if (!list_empty(&page->lru))
- return (pte_t *) ((unsigned long) page->lru.next |
- offset);
- }
+ if (s390_noexec && page->index)
+ return virt_to_page((void *)(addr_t) page->index);
return NULL;
}
-static inline pmd_t *get_shadow_pmd(pmd_t *pmdp)
+static inline void *get_shadow_pte(void *table)
{
- unsigned long pmdptr = (unsigned long) (pmdp);
+ unsigned long addr, offset;
+ struct page *page;
- if (s390_noexec) {
- unsigned long offset = pmdptr &
- ((PAGE_SIZE << PMD_SHADOW_SHIFT) - 1);
- void *addr = (void *) (pmdptr ^ offset);
- struct page *page = virt_to_page(addr);
- if (!list_empty(&page->lru))
- return (pmd_t *) ((unsigned long) page->lru.next |
- offset);
- }
- return NULL;
+ addr = (unsigned long) table;
+ offset = addr & (PAGE_SIZE - 1);
+ page = virt_to_page((void *)(addr ^ offset));
+ return (void *)(addr_t)(page->index ? (page->index | offset) : 0UL);
}
-static inline pgd_t *get_shadow_pgd(pgd_t *pgdp)
+static inline void *get_shadow_table(void *table)
{
- unsigned long pgdptr = (unsigned long) (pgdp);
+ unsigned long addr, offset;
+ struct page *page;
- if (s390_noexec) {
- unsigned long offset = pgdptr &
- ((PAGE_SIZE << PGD_SHADOW_SHIFT) - 1);
- void *addr = (void *) (pgdptr ^ offset);
- struct page *page = virt_to_page(addr);
- if (!list_empty(&page->lru))
- return (pgd_t *) ((unsigned long) page->lru.next |
- offset);
- }
- return NULL;
+ addr = (unsigned long) table;
+ offset = addr & ((PAGE_SIZE << PxD_SHADOW_SHIFT) - 1);
+ page = virt_to_page((void *)(addr ^ offset));
+ return (void *)(addr_t)(page->index ? (page->index | offset) : 0UL);
}
/*
@@ -424,7 +417,8 @@ static inline pgd_t *get_shadow_pgd(pgd_t *pgdp)
* within a page table are directly modified. Thus, the following
* hook is made available.
*/
-static inline void set_pte(pte_t *pteptr, pte_t pteval)
+static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *pteptr, pte_t pteval)
{
pte_t *shadow_pte = get_shadow_pte(pteptr);
@@ -437,7 +431,6 @@ static inline void set_pte(pte_t *pteptr, pte_t pteval)
pte_val(*shadow_pte) = _PAGE_TYPE_EMPTY;
}
}
-#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
/*
* pgd/pmd/pte query functions
@@ -448,47 +441,50 @@ static inline int pgd_present(pgd_t pgd) { return 1; }
static inline int pgd_none(pgd_t pgd) { return 0; }
static inline int pgd_bad(pgd_t pgd) { return 0; }
-static inline int pmd_present(pmd_t pmd) { return pmd_val(pmd) & _SEG_PRESENT; }
-static inline int pmd_none(pmd_t pmd) { return pmd_val(pmd) & _PAGE_TABLE_INV; }
-static inline int pmd_bad(pmd_t pmd)
-{
- return (pmd_val(pmd) & (~PAGE_MASK & ~_PAGE_TABLE_INV)) != _PAGE_TABLE;
-}
+static inline int pud_present(pud_t pud) { return 1; }
+static inline int pud_none(pud_t pud) { return 0; }
+static inline int pud_bad(pud_t pud) { return 0; }
#else /* __s390x__ */
-static inline int pgd_present(pgd_t pgd)
+static inline int pgd_present(pgd_t pgd) { return 1; }
+static inline int pgd_none(pgd_t pgd) { return 0; }
+static inline int pgd_bad(pgd_t pgd) { return 0; }
+
+static inline int pud_present(pud_t pud)
{
- return (pgd_val(pgd) & ~PAGE_MASK) == _PGD_ENTRY;
+ return pud_val(pud) & _REGION_ENTRY_ORIGIN;
}
-static inline int pgd_none(pgd_t pgd)
+static inline int pud_none(pud_t pud)
{
- return pgd_val(pgd) & _PGD_ENTRY_INV;
+ return pud_val(pud) & _REGION_ENTRY_INV;
}
-static inline int pgd_bad(pgd_t pgd)
+static inline int pud_bad(pud_t pud)
{
- return (pgd_val(pgd) & (~PAGE_MASK & ~_PGD_ENTRY_INV)) != _PGD_ENTRY;
+ unsigned long mask = ~_REGION_ENTRY_ORIGIN & ~_REGION_ENTRY_INV;
+ return (pud_val(pud) & mask) != _REGION3_ENTRY;
}
+#endif /* __s390x__ */
+
static inline int pmd_present(pmd_t pmd)
{
- return (pmd_val(pmd) & ~PAGE_MASK) == _PMD_ENTRY;
+ return pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN;
}
static inline int pmd_none(pmd_t pmd)
{
- return pmd_val(pmd) & _PMD_ENTRY_INV;
+ return pmd_val(pmd) & _SEGMENT_ENTRY_INV;
}
static inline int pmd_bad(pmd_t pmd)
{
- return (pmd_val(pmd) & (~PAGE_MASK & ~_PMD_ENTRY_INV)) != _PMD_ENTRY;
+ unsigned long mask = ~_SEGMENT_ENTRY_ORIGIN & ~_SEGMENT_ENTRY_INV;
+ return (pmd_val(pmd) & mask) != _SEGMENT_ENTRY;
}
-#endif /* __s390x__ */
-
static inline int pte_none(pte_t pte)
{
return (pte_val(pte) & _PAGE_INVALID) && !(pte_val(pte) & _PAGE_SWT);
@@ -508,7 +504,8 @@ static inline int pte_file(pte_t pte)
return (pte_val(pte) & mask) == _PAGE_TYPE_FILE;
}
-#define pte_same(a,b) (pte_val(a) == pte_val(b))
+#define __HAVE_ARCH_PTE_SAME
+#define pte_same(a,b) (pte_val(a) == pte_val(b))
/*
* query functions pte_write/pte_dirty/pte_young only work if
@@ -543,58 +540,52 @@ static inline int pte_young(pte_t pte)
#ifndef __s390x__
-static inline void pgd_clear(pgd_t * pgdp) { }
+#define pgd_clear(pgd) do { } while (0)
+#define pud_clear(pud) do { } while (0)
static inline void pmd_clear_kernel(pmd_t * pmdp)
{
- pmd_val(pmdp[0]) = _PAGE_TABLE_INV;
- pmd_val(pmdp[1]) = _PAGE_TABLE_INV;
- pmd_val(pmdp[2]) = _PAGE_TABLE_INV;
- pmd_val(pmdp[3]) = _PAGE_TABLE_INV;
-}
-
-static inline void pmd_clear(pmd_t * pmdp)
-{
- pmd_t *shadow_pmd = get_shadow_pmd(pmdp);
-
- pmd_clear_kernel(pmdp);
- if (shadow_pmd)
- pmd_clear_kernel(shadow_pmd);
+ pmd_val(pmdp[0]) = _SEGMENT_ENTRY_EMPTY;
+ pmd_val(pmdp[1]) = _SEGMENT_ENTRY_EMPTY;
+ pmd_val(pmdp[2]) = _SEGMENT_ENTRY_EMPTY;
+ pmd_val(pmdp[3]) = _SEGMENT_ENTRY_EMPTY;
}
#else /* __s390x__ */
-static inline void pgd_clear_kernel(pgd_t * pgdp)
+#define pgd_clear(pgd) do { } while (0)
+
+static inline void pud_clear_kernel(pud_t *pud)
{
- pgd_val(*pgdp) = _PGD_ENTRY_INV | _PGD_ENTRY;
+ pud_val(*pud) = _REGION3_ENTRY_EMPTY;
}
-static inline void pgd_clear(pgd_t * pgdp)
+static inline void pud_clear(pud_t * pud)
{
- pgd_t *shadow_pgd = get_shadow_pgd(pgdp);
+ pud_t *shadow = get_shadow_table(pud);
- pgd_clear_kernel(pgdp);
- if (shadow_pgd)
- pgd_clear_kernel(shadow_pgd);
+ pud_clear_kernel(pud);
+ if (shadow)
+ pud_clear_kernel(shadow);
}
static inline void pmd_clear_kernel(pmd_t * pmdp)
{
- pmd_val(*pmdp) = _PMD_ENTRY_INV | _PMD_ENTRY;
- pmd_val1(*pmdp) = _PMD_ENTRY_INV | _PMD_ENTRY;
+ pmd_val(*pmdp) = _SEGMENT_ENTRY_EMPTY;
+ pmd_val1(*pmdp) = _SEGMENT_ENTRY_EMPTY;
}
+#endif /* __s390x__ */
+
static inline void pmd_clear(pmd_t * pmdp)
{
- pmd_t *shadow_pmd = get_shadow_pmd(pmdp);
+ pmd_t *shadow_pmd = get_shadow_table(pmdp);
pmd_clear_kernel(pmdp);
if (shadow_pmd)
pmd_clear_kernel(shadow_pmd);
}
-#endif /* __s390x__ */
-
static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
pte_t *shadow_pte = get_shadow_pte(ptep);
@@ -663,24 +654,19 @@ static inline pte_t pte_mkyoung(pte_t pte)
return pte;
}
-static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
+#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
+static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
+ unsigned long addr, pte_t *ptep)
{
return 0;
}
-static inline int
-ptep_clear_flush_young(struct vm_area_struct *vma,
- unsigned long address, pte_t *ptep)
+#define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
+static inline int ptep_clear_flush_young(struct vm_area_struct *vma,
+ unsigned long address, pte_t *ptep)
{
/* No need to flush TLB; bits are in storage key */
- return ptep_test_and_clear_young(vma, address, ptep);
-}
-
-static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
-{
- pte_t pte = *ptep;
- pte_clear(mm, addr, ptep);
- return pte;
+ return 0;
}
static inline void __ptep_ipte(unsigned long address, pte_t *ptep)
@@ -709,6 +695,32 @@ static inline void ptep_invalidate(unsigned long address, pte_t *ptep)
__ptep_ipte(address, ptep);
}
+/*
+ * This is hard to understand. ptep_get_and_clear and ptep_clear_flush
+ * both clear the TLB for the unmapped pte. The reason is that
+ * ptep_get_and_clear is used in common code (e.g. change_pte_range)
+ * to modify an active pte. The sequence is
+ * 1) ptep_get_and_clear
+ * 2) set_pte_at
+ * 3) flush_tlb_range
+ * On s390 the tlb needs to get flushed with the modification of the pte
+ * if the pte is active. The only way how this can be implemented is to
+ * have ptep_get_and_clear do the tlb flush. In exchange flush_tlb_range
+ * is a nop.
+ */
+#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+#define ptep_get_and_clear(__mm, __address, __ptep) \
+({ \
+ pte_t __pte = *(__ptep); \
+ if (atomic_read(&(__mm)->mm_users) > 1 || \
+ (__mm) != current->active_mm) \
+ ptep_invalidate(__address, __ptep); \
+ else \
+ pte_clear((__mm), (__address), (__ptep)); \
+ __pte; \
+})
+
+#define __HAVE_ARCH_PTEP_CLEAR_FLUSH
static inline pte_t ptep_clear_flush(struct vm_area_struct *vma,
unsigned long address, pte_t *ptep)
{
@@ -717,12 +729,40 @@ static inline pte_t ptep_clear_flush(struct vm_area_struct *vma,
return pte;
}
-static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+/*
+ * The batched pte unmap code uses ptep_get_and_clear_full to clear the
+ * ptes. Here an optimization is possible. tlb_gather_mmu flushes all
+ * tlbs of an mm if it can guarantee that the ptes of the mm_struct
+ * cannot be accessed while the batched unmap is running. In this case
+ * full==1 and a simple pte_clear is enough. See tlb.h.
+ */
+#define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
+static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm,
+ unsigned long addr,
+ pte_t *ptep, int full)
{
- pte_t old_pte = *ptep;
- set_pte_at(mm, addr, ptep, pte_wrprotect(old_pte));
+ pte_t pte = *ptep;
+
+ if (full)
+ pte_clear(mm, addr, ptep);
+ else
+ ptep_invalidate(addr, ptep);
+ return pte;
}
+#define __HAVE_ARCH_PTEP_SET_WRPROTECT
+#define ptep_set_wrprotect(__mm, __addr, __ptep) \
+({ \
+ pte_t __pte = *(__ptep); \
+ if (pte_write(__pte)) { \
+ if (atomic_read(&(__mm)->mm_users) > 1 || \
+ (__mm) != current->active_mm) \
+ ptep_invalidate(__addr, __ptep); \
+ set_pte_at(__mm, __addr, __ptep, pte_wrprotect(__pte)); \
+ } \
+})
+
+#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
#define ptep_set_access_flags(__vma, __addr, __ptep, __entry, __dirty) \
({ \
int __changed = !pte_same(*(__ptep), __entry); \
@@ -740,11 +780,13 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
* should therefore only be called if it is not mapped in any
* address space.
*/
+#define __HAVE_ARCH_PAGE_TEST_DIRTY
static inline int page_test_dirty(struct page *page)
{
return (page_get_storage_key(page_to_phys(page)) & _PAGE_CHANGED) != 0;
}
+#define __HAVE_ARCH_PAGE_CLEAR_DIRTY
static inline void page_clear_dirty(struct page *page)
{
page_set_storage_key(page_to_phys(page), PAGE_DEFAULT_KEY);
@@ -753,6 +795,7 @@ static inline void page_clear_dirty(struct page *page)
/*
* Test and clear referenced bit in storage key.
*/
+#define __HAVE_ARCH_PAGE_TEST_AND_CLEAR_YOUNG
static inline int page_test_and_clear_young(struct page *page)
{
unsigned long physpage = page_to_phys(page);
@@ -784,63 +827,48 @@ static inline pte_t mk_pte(struct page *page, pgprot_t pgprot)
return mk_pte_phys(physpage, pgprot);
}
-static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot)
-{
- unsigned long physpage = __pa((pfn) << PAGE_SHIFT);
-
- return mk_pte_phys(physpage, pgprot);
-}
-
-#ifdef __s390x__
-
-static inline pmd_t pfn_pmd(unsigned long pfn, pgprot_t pgprot)
-{
- unsigned long physpage = __pa((pfn) << PAGE_SHIFT);
-
- return __pmd(physpage + pgprot_val(pgprot));
-}
-
-#endif /* __s390x__ */
-
-#define pte_pfn(x) (pte_val(x) >> PAGE_SHIFT)
-#define pte_page(x) pfn_to_page(pte_pfn(x))
+#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
+#define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1))
+#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
+#define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE-1))
-#define pmd_page_vaddr(pmd) (pmd_val(pmd) & PAGE_MASK)
+#define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address))
+#define pgd_offset_k(address) pgd_offset(&init_mm, address)
-#define pmd_page(pmd) pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT)
+#ifndef __s390x__
-#define pgd_page_vaddr(pgd) (pgd_val(pgd) & PAGE_MASK)
+#define pmd_deref(pmd) (pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN)
+#define pud_deref(pmd) ({ BUG(); 0UL; })
+#define pgd_deref(pmd) ({ BUG(); 0UL; })
-#define pgd_page(pgd) pfn_to_page(pgd_val(pgd) >> PAGE_SHIFT)
+#define pud_offset(pgd, address) ((pud_t *) pgd)
+#define pmd_offset(pud, address) ((pmd_t *) pud + pmd_index(address))
-/* to find an entry in a page-table-directory */
-#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
-#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
+#else /* __s390x__ */
-/* to find an entry in a kernel page-table-directory */
-#define pgd_offset_k(address) pgd_offset(&init_mm, address)
+#define pmd_deref(pmd) (pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN)
+#define pud_deref(pud) (pud_val(pud) & _REGION_ENTRY_ORIGIN)
+#define pgd_deref(pgd) ({ BUG(); 0UL; })
-#ifndef __s390x__
+#define pud_offset(pgd, address) ((pud_t *) pgd)
-/* Find an entry in the second-level page table.. */
-static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
+static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address)
{
- return (pmd_t *) dir;
+ pmd_t *pmd = (pmd_t *) pud_deref(*pud);
+ return pmd + pmd_index(address);
}
-#else /* __s390x__ */
+#endif /* __s390x__ */
-/* Find an entry in the second-level page table.. */
-#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
-#define pmd_offset(dir,addr) \
- ((pmd_t *) pgd_page_vaddr(*(dir)) + pmd_index(addr))
+#define pfn_pte(pfn,pgprot) mk_pte_phys(__pa((pfn) << PAGE_SHIFT),(pgprot))
+#define pte_pfn(x) (pte_val(x) >> PAGE_SHIFT)
+#define pte_page(x) pfn_to_page(pte_pfn(x))
-#endif /* __s390x__ */
+#define pmd_page(pmd) pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT)
-/* Find an entry in the third-level page table.. */
-#define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE-1))
-#define pte_offset_kernel(pmd, address) \
- ((pte_t *) pmd_page_vaddr(*(pmd)) + pte_index(address))
+/* Find an entry in the lowest level page table.. */
+#define pte_offset(pmd, addr) ((pte_t *) pmd_deref(*(pmd)) + pte_index(addr))
+#define pte_offset_kernel(pmd, address) pte_offset(pmd,address)
#define pte_offset_map(pmd, address) pte_offset_kernel(pmd, address)
#define pte_offset_map_nested(pmd, address) pte_offset_kernel(pmd, address)
#define pte_unmap(pte) do { } while (0)
@@ -930,17 +958,6 @@ extern int remove_shared_memory(unsigned long start, unsigned long size);
#define __HAVE_ARCH_MEMMAP_INIT
extern void memmap_init(unsigned long, int, unsigned long, unsigned long);
-#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-#define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
-#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
-#define __HAVE_ARCH_PTEP_CLEAR_FLUSH
-#define __HAVE_ARCH_PTEP_SET_WRPROTECT
-#define __HAVE_ARCH_PTE_SAME
-#define __HAVE_ARCH_PAGE_TEST_DIRTY
-#define __HAVE_ARCH_PAGE_CLEAR_DIRTY
-#define __HAVE_ARCH_PAGE_TEST_AND_CLEAR_YOUNG
#include <asm-generic/pgtable.h>
#endif /* _S390_PAGE_H */
-
diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h
index 3b972d4c6b29..21d40a19355e 100644
--- a/include/asm-s390/processor.h
+++ b/include/asm-s390/processor.h
@@ -93,7 +93,6 @@ struct thread_struct {
s390_fp_regs fp_regs;
unsigned int acrs[NUM_ACRS];
unsigned long ksp; /* kernel stack pointer */
- unsigned long user_seg; /* HSTD */
mm_segment_t mm_segment;
unsigned long prot_addr; /* address of protection-excep. */
unsigned int error_code; /* error-code of last prog-excep. */
@@ -128,22 +127,9 @@ struct stack_frame {
#define ARCH_MIN_TASKALIGN 8
-#ifndef __s390x__
-# define __SWAPPER_PG_DIR __pa(&swapper_pg_dir[0]) + _SEGMENT_TABLE
-#else /* __s390x__ */
-# define __SWAPPER_PG_DIR __pa(&swapper_pg_dir[0]) + _REGION_TABLE
-#endif /* __s390x__ */
-
-#define INIT_THREAD {{0,{{0},{0},{0},{0},{0},{0},{0},{0},{0},{0}, \
- {0},{0},{0},{0},{0},{0}}}, \
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
- sizeof(init_stack) + (unsigned long) &init_stack, \
- __SWAPPER_PG_DIR, \
- {0}, \
- 0,0,0, \
- (per_struct) {{{{0,}}},0,0,0,0,{{0,}}}, \
- 0, 0 \
-}
+#define INIT_THREAD { \
+ .ksp = sizeof(init_stack) + (unsigned long) &init_stack, \
+}
/*
* Do necessary setup to start up a new thread.
diff --git a/include/asm-s390/scatterlist.h b/include/asm-s390/scatterlist.h
index a43b3afc5e2d..29ec8e28c8df 100644
--- a/include/asm-s390/scatterlist.h
+++ b/include/asm-s390/scatterlist.h
@@ -2,7 +2,10 @@
#define _ASMS390_SCATTERLIST_H
struct scatterlist {
- struct page *page;
+#ifdef CONFIG_DEBUG_SG
+ unsigned long sg_magic;
+#endif
+ unsigned long page_link;
unsigned int offset;
unsigned int length;
};
diff --git a/include/asm-s390/semaphore.h b/include/asm-s390/semaphore.h
index dbce058aefa9..0e7001ad8392 100644
--- a/include/asm-s390/semaphore.h
+++ b/include/asm-s390/semaphore.h
@@ -33,7 +33,6 @@ struct semaphore {
struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
-#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
static inline void sema_init (struct semaphore *sem, int val)
{
diff --git a/include/asm-s390/tlb.h b/include/asm-s390/tlb.h
index 51bd957b85bd..618693cfc10f 100644
--- a/include/asm-s390/tlb.h
+++ b/include/asm-s390/tlb.h
@@ -2,19 +2,130 @@
#define _S390_TLB_H
/*
- * s390 doesn't need any special per-pte or
- * per-vma handling..
+ * TLB flushing on s390 is complicated. The following requirement
+ * from the principles of operation is the most arduous:
+ *
+ * "A valid table entry must not be changed while it is attached
+ * to any CPU and may be used for translation by that CPU except to
+ * (1) invalidate the entry by using INVALIDATE PAGE TABLE ENTRY,
+ * or INVALIDATE DAT TABLE ENTRY, (2) alter bits 56-63 of a page
+ * table entry, or (3) make a change by means of a COMPARE AND SWAP
+ * AND PURGE instruction that purges the TLB."
+ *
+ * The modification of a pte of an active mm struct therefore is
+ * a two step process: i) invalidate the pte, ii) store the new pte.
+ * This is true for the page protection bit as well.
+ * The only possible optimization is to flush at the beginning of
+ * a tlb_gather_mmu cycle if the mm_struct is currently not in use.
+ *
+ * Pages used for the page tables is a different story. FIXME: more
*/
-#define tlb_start_vma(tlb, vma) do { } while (0)
-#define tlb_end_vma(tlb, vma) do { } while (0)
-#define __tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0)
+
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <asm/processor.h>
+#include <asm/pgalloc.h>
+#include <asm/smp.h>
+#include <asm/tlbflush.h>
+
+#ifndef CONFIG_SMP
+#define TLB_NR_PTRS 1
+#else
+#define TLB_NR_PTRS 508
+#endif
+
+struct mmu_gather {
+ struct mm_struct *mm;
+ unsigned int fullmm;
+ unsigned int nr_ptes;
+ unsigned int nr_pmds;
+ void *array[TLB_NR_PTRS];
+};
+
+DECLARE_PER_CPU(struct mmu_gather, mmu_gathers);
+
+static inline struct mmu_gather *tlb_gather_mmu(struct mm_struct *mm,
+ unsigned int full_mm_flush)
+{
+ struct mmu_gather *tlb = &get_cpu_var(mmu_gathers);
+
+ tlb->mm = mm;
+ tlb->fullmm = full_mm_flush || (num_online_cpus() == 1) ||
+ (atomic_read(&mm->mm_users) <= 1 && mm == current->active_mm);
+ tlb->nr_ptes = 0;
+ tlb->nr_pmds = TLB_NR_PTRS;
+ if (tlb->fullmm)
+ __tlb_flush_mm(mm);
+ return tlb;
+}
+
+static inline void tlb_flush_mmu(struct mmu_gather *tlb,
+ unsigned long start, unsigned long end)
+{
+ if (!tlb->fullmm && (tlb->nr_ptes > 0 || tlb->nr_pmds < TLB_NR_PTRS))
+ __tlb_flush_mm(tlb->mm);
+ while (tlb->nr_ptes > 0)
+ pte_free(tlb->array[--tlb->nr_ptes]);
+ while (tlb->nr_pmds < TLB_NR_PTRS)
+ pmd_free((pmd_t *) tlb->array[tlb->nr_pmds++]);
+}
+
+static inline void tlb_finish_mmu(struct mmu_gather *tlb,
+ unsigned long start, unsigned long end)
+{
+ tlb_flush_mmu(tlb, start, end);
+
+ /* keep the page table cache within bounds */
+ check_pgt_cache();
+
+ put_cpu_var(mmu_gathers);
+}
/*
- * .. because we flush the whole mm when it
- * fills up.
+ * Release the page cache reference for a pte removed by
+ * tlb_ptep_clear_flush. In both flush modes the tlb fo a page cache page
+ * has already been freed, so just do free_page_and_swap_cache.
*/
-#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm)
+static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
+{
+ free_page_and_swap_cache(page);
+}
-#include <asm-generic/tlb.h>
+/*
+ * pte_free_tlb frees a pte table and clears the CRSTE for the
+ * page table from the tlb.
+ */
+static inline void pte_free_tlb(struct mmu_gather *tlb, struct page *page)
+{
+ if (!tlb->fullmm) {
+ tlb->array[tlb->nr_ptes++] = page;
+ if (tlb->nr_ptes >= tlb->nr_pmds)
+ tlb_flush_mmu(tlb, 0, 0);
+ } else
+ pte_free(page);
+}
+/*
+ * pmd_free_tlb frees a pmd table and clears the CRSTE for the
+ * segment table entry from the tlb.
+ */
+static inline void pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
+{
+#ifdef __s390x__
+ if (!tlb->fullmm) {
+ tlb->array[--tlb->nr_pmds] = (struct page *) pmd;
+ if (tlb->nr_ptes >= tlb->nr_pmds)
+ tlb_flush_mmu(tlb, 0, 0);
+ } else
+ pmd_free(pmd);
#endif
+}
+
+#define pud_free_tlb(tlb, pud) do { } while (0)
+
+#define tlb_start_vma(tlb, vma) do { } while (0)
+#define tlb_end_vma(tlb, vma) do { } while (0)
+#define tlb_remove_tlb_entry(tlb, ptep, addr) do { } while (0)
+#define tlb_migrate_finish(mm) do { } while (0)
+
+#endif /* _S390_TLB_H */
diff --git a/include/asm-s390/tlbflush.h b/include/asm-s390/tlbflush.h
index 66793f55c8b2..a69bd2490d52 100644
--- a/include/asm-s390/tlbflush.h
+++ b/include/asm-s390/tlbflush.h
@@ -6,69 +6,19 @@
#include <asm/pgalloc.h>
/*
- * TLB flushing:
- *
- * - flush_tlb() flushes the current mm struct TLBs
- * - flush_tlb_all() flushes all processes TLBs
- * - flush_tlb_mm(mm) flushes the specified mm context TLB's
- * - flush_tlb_page(vma, vmaddr) flushes one page
- * - flush_tlb_range(vma, start, end) flushes a range of pages
- * - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
- * - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
- */
-
-/*
- * S/390 has three ways of flushing TLBs
- * 'ptlb' does a flush of the local processor
- * 'csp' flushes the TLBs on all PUs of a SMP
- * 'ipte' invalidates a pte in a page table and flushes that out of
- * the TLBs of all PUs of a SMP
+ * Flush all tlb entries on the local cpu.
*/
-
-#define local_flush_tlb() \
-do { asm volatile("ptlb": : :"memory"); } while (0)
-
-#ifndef CONFIG_SMP
-
-/*
- * We always need to flush, since s390 does not flush tlb
- * on each context switch
- */
-
-static inline void flush_tlb(void)
-{
- local_flush_tlb();
-}
-static inline void flush_tlb_all(void)
-{
- local_flush_tlb();
-}
-static inline void flush_tlb_mm(struct mm_struct *mm)
+static inline void __tlb_flush_local(void)
{
- local_flush_tlb();
+ asm volatile("ptlb" : : : "memory");
}
-static inline void flush_tlb_page(struct vm_area_struct *vma,
- unsigned long addr)
-{
- local_flush_tlb();
-}
-static inline void flush_tlb_range(struct vm_area_struct *vma,
- unsigned long start, unsigned long end)
-{
- local_flush_tlb();
-}
-
-#define flush_tlb_kernel_range(start, end) \
- local_flush_tlb();
-
-#else
-
-#include <asm/smp.h>
-
-extern void smp_ptlb_all(void);
-static inline void global_flush_tlb(void)
+/*
+ * Flush all tlb entries on all cpus.
+ */
+static inline void __tlb_flush_global(void)
{
+ extern void smp_ptlb_all(void);
register unsigned long reg2 asm("2");
register unsigned long reg3 asm("3");
register unsigned long reg4 asm("4");
@@ -90,72 +40,75 @@ static inline void global_flush_tlb(void)
}
/*
- * We only have to do global flush of tlb if process run since last
- * flush on any other pu than current.
- * If we have threads (mm->count > 1) we always do a global flush,
- * since the process runs on more than one processor at the same time.
+ * Flush all tlb entries of a page table on all cpus.
*/
+static inline void __tlb_flush_idte(pgd_t *pgd)
+{
+ asm volatile(
+ " .insn rrf,0xb98e0000,0,%0,%1,0"
+ : : "a" (2048), "a" (__pa(pgd) & PAGE_MASK) : "cc" );
+}
-static inline void __flush_tlb_mm(struct mm_struct * mm)
+static inline void __tlb_flush_mm(struct mm_struct * mm)
{
cpumask_t local_cpumask;
if (unlikely(cpus_empty(mm->cpu_vm_mask)))
return;
+ /*
+ * If the machine has IDTE we prefer to do a per mm flush
+ * on all cpus instead of doing a local flush if the mm
+ * only ran on the local cpu.
+ */
if (MACHINE_HAS_IDTE) {
- pgd_t *shadow_pgd = get_shadow_pgd(mm->pgd);
+ pgd_t *shadow_pgd = get_shadow_table(mm->pgd);
- if (shadow_pgd) {
- asm volatile(
- " .insn rrf,0xb98e0000,0,%0,%1,0"
- : : "a" (2048),
- "a" (__pa(shadow_pgd) & PAGE_MASK) : "cc" );
- }
- asm volatile(
- " .insn rrf,0xb98e0000,0,%0,%1,0"
- : : "a" (2048), "a" (__pa(mm->pgd)&PAGE_MASK) : "cc");
+ if (shadow_pgd)
+ __tlb_flush_idte(shadow_pgd);
+ __tlb_flush_idte(mm->pgd);
return;
}
preempt_disable();
+ /*
+ * If the process only ran on the local cpu, do a local flush.
+ */
local_cpumask = cpumask_of_cpu(smp_processor_id());
if (cpus_equal(mm->cpu_vm_mask, local_cpumask))
- local_flush_tlb();
+ __tlb_flush_local();
else
- global_flush_tlb();
+ __tlb_flush_global();
preempt_enable();
}
-static inline void flush_tlb(void)
-{
- __flush_tlb_mm(current->mm);
-}
-static inline void flush_tlb_all(void)
-{
- global_flush_tlb();
-}
-static inline void flush_tlb_mm(struct mm_struct *mm)
-{
- __flush_tlb_mm(mm);
-}
-static inline void flush_tlb_page(struct vm_area_struct *vma,
- unsigned long addr)
+static inline void __tlb_flush_mm_cond(struct mm_struct * mm)
{
- __flush_tlb_mm(vma->vm_mm);
+ if (atomic_read(&mm->mm_users) <= 1 && mm == current->active_mm)
+ __tlb_flush_mm(mm);
}
-static inline void flush_tlb_range(struct vm_area_struct *vma,
- unsigned long start, unsigned long end)
-{
- __flush_tlb_mm(vma->vm_mm);
-}
-
-#define flush_tlb_kernel_range(start, end) global_flush_tlb()
-#endif
+/*
+ * TLB flushing:
+ * flush_tlb() - flushes the current mm struct TLBs
+ * flush_tlb_all() - flushes all processes TLBs
+ * flush_tlb_mm(mm) - flushes the specified mm context TLB's
+ * flush_tlb_page(vma, vmaddr) - flushes one page
+ * flush_tlb_range(vma, start, end) - flushes a range of pages
+ * flush_tlb_kernel_range(start, end) - flushes a range of kernel pages
+ */
-static inline void flush_tlb_pgtables(struct mm_struct *mm,
- unsigned long start, unsigned long end)
-{
- /* S/390 does not keep any page table caches in TLB */
-}
+/*
+ * flush_tlb_mm goes together with ptep_set_wrprotect for the
+ * copy_page_range operation and flush_tlb_range is related to
+ * ptep_get_and_clear for change_protection. ptep_set_wrprotect and
+ * ptep_get_and_clear do not flush the TLBs directly if the mm has
+ * only one user. At the end of the update the flush_tlb_mm and
+ * flush_tlb_range functions need to do the flush.
+ */
+#define flush_tlb() do { } while (0)
+#define flush_tlb_all() do { } while (0)
+#define flush_tlb_mm(mm) __tlb_flush_mm_cond(mm)
+#define flush_tlb_page(vma, addr) do { } while (0)
+#define flush_tlb_range(vma, start, end) __tlb_flush_mm_cond(mm)
+#define flush_tlb_kernel_range(start, end) __tlb_flush_mm(&init_mm)
#endif /* _S390_TLBFLUSH_H */
diff --git a/include/asm-s390/types.h b/include/asm-s390/types.h
index fc5d7cf19324..2c5879ae90ca 100644
--- a/include/asm-s390/types.h
+++ b/include/asm-s390/types.h
@@ -28,9 +28,9 @@ typedef __signed__ int __s32;
typedef unsigned int __u32;
#ifndef __s390x__
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
-typedef __signed__ long long __s64;
-typedef unsigned long long __u64;
+#if defined(__GNUC__)
+__extension__ typedef __signed__ long long __s64;
+__extension__ typedef unsigned long long __u64;
#endif
#else /* __s390x__ */
typedef __signed__ long __s64;
diff --git a/include/asm-sh/bitops.h b/include/asm-sh/bitops.h
index 1c16792cee1d..df805f20b267 100644
--- a/include/asm-sh/bitops.h
+++ b/include/asm-sh/bitops.h
@@ -2,6 +2,11 @@
#define __ASM_SH_BITOPS_H
#ifdef __KERNEL__
+
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
#include <asm/system.h>
/* For __swab32 */
#include <asm/byteorder.h>
@@ -137,6 +142,7 @@ static inline unsigned long __ffs(unsigned long word)
#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/ffs.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/lock.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/ext2-non-atomic.h>
#include <asm-generic/bitops/ext2-atomic.h>
diff --git a/include/asm-sh/cache.h b/include/asm-sh/cache.h
index 7a18649d1ccb..01e5cf51ba9b 100644
--- a/include/asm-sh/cache.h
+++ b/include/asm-sh/cache.h
@@ -18,9 +18,8 @@
#define SH_CACHE_ASSOC 8
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
-#define SMP_CACHE_BYTES L1_CACHE_BYTES
-#define L1_CACHE_ALIGN(x) (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
+#define __read_mostly __attribute__((__section__(".data.read_mostly")))
#ifndef __ASSEMBLY__
struct cache_info {
diff --git a/include/asm-sh/cacheflush.h b/include/asm-sh/cacheflush.h
index aa558da08471..b91246153b7e 100644
--- a/include/asm-sh/cacheflush.h
+++ b/include/asm-sh/cacheflush.h
@@ -43,21 +43,31 @@ extern void __flush_purge_region(void *start, int size);
extern void __flush_invalidate_region(void *start, int size);
#endif
-#define flush_cache_vmap(start, end) flush_cache_all()
-#define flush_cache_vunmap(start, end) flush_cache_all()
+#ifdef CONFIG_CPU_SH4
+extern void copy_to_user_page(struct vm_area_struct *vma,
+ struct page *page, unsigned long vaddr, void *dst, const void *src,
+ unsigned long len);
-#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
+extern void copy_from_user_page(struct vm_area_struct *vma,
+ struct page *page, unsigned long vaddr, void *dst, const void *src,
+ unsigned long len);
+#else
+#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
do { \
flush_cache_page(vma, vaddr, page_to_pfn(page));\
memcpy(dst, src, len); \
flush_icache_user_range(vma, page, vaddr, len); \
} while (0)
-#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
+#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
do { \
flush_cache_page(vma, vaddr, page_to_pfn(page));\
memcpy(dst, src, len); \
} while (0)
+#endif
+
+#define flush_cache_vmap(start, end) flush_cache_all()
+#define flush_cache_vunmap(start, end) flush_cache_all()
#define HAVE_ARCH_UNMAPPED_AREA
diff --git a/include/asm-sh/cpu-sh3/timer.h b/include/asm-sh/cpu-sh3/timer.h
index 3880ce047fe0..7b795ac5477c 100644
--- a/include/asm-sh/cpu-sh3/timer.h
+++ b/include/asm-sh/cpu-sh3/timer.h
@@ -23,8 +23,7 @@
* ---------------------------------------------------------------------------
*/
-#if !defined(CONFIG_CPU_SUBTYPE_SH7720) && \
- !defined(CONFIG_CPU_SUBTYPE_SH7727)
+#if !defined(CONFIG_CPU_SUBTYPE_SH7720)
#define TMU_TOCR 0xfffffe90 /* Byte access */
#endif
@@ -58,8 +57,7 @@
#define TMU2_TCOR 0xfffffeac /* Long access */
#define TMU2_TCNT 0xfffffeb0 /* Long access */
#define TMU2_TCR 0xfffffeb4 /* Word access */
-#if !defined(CONFIG_CPU_SUBTYPE_SH7720) && \
- !defined(CONFIG_CPU_SUBTYPE_SH7727)
+#if !defined(CONFIG_CPU_SUBTYPE_SH7720)
#define TMU2_TCPR2 0xfffffeb8 /* Long access */
#endif
#endif
diff --git a/include/asm-sh/dma-mapping.h b/include/asm-sh/dma-mapping.h
index 84fefdaa01a5..fcea067f7a9c 100644
--- a/include/asm-sh/dma-mapping.h
+++ b/include/asm-sh/dma-mapping.h
@@ -2,7 +2,7 @@
#define __ASM_SH_DMA_MAPPING_H
#include <linux/mm.h>
-#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
#include <asm/cacheflush.h>
#include <asm/io.h>
@@ -85,10 +85,9 @@ static inline int dma_map_sg(struct device *dev, struct scatterlist *sg,
for (i = 0; i < nents; i++) {
#if !defined(CONFIG_PCI) || defined(CONFIG_SH_PCIDMA_NONCOHERENT)
- dma_cache_sync(dev, page_address(sg[i].page) + sg[i].offset,
- sg[i].length, dir);
+ dma_cache_sync(dev, sg_virt(&sg[i]), sg[i].length, dir);
#endif
- sg[i].dma_address = page_to_phys(sg[i].page) + sg[i].offset;
+ sg[i].dma_address = sg_phys(&sg[i]);
}
return nents;
@@ -138,10 +137,9 @@ static inline void dma_sync_sg(struct device *dev, struct scatterlist *sg,
for (i = 0; i < nelems; i++) {
#if !defined(CONFIG_PCI) || defined(CONFIG_SH_PCIDMA_NONCOHERENT)
- dma_cache_sync(dev, page_address(sg[i].page) + sg[i].offset,
- sg[i].length, dir);
+ dma_cache_sync(dev, sg_virt(&sg[i]), sg[i].length, dir);
#endif
- sg[i].dma_address = page_to_phys(sg[i].page) + sg[i].offset;
+ sg[i].dma_address = sg_phys(&sg[i]);
}
}
diff --git a/include/asm-sh/elf.h b/include/asm-sh/elf.h
index 43ca244564b1..12cc4b392bf0 100644
--- a/include/asm-sh/elf.h
+++ b/include/asm-sh/elf.h
@@ -133,6 +133,7 @@ extern void __kernel_vsyscall;
#define VDSO_BASE ((unsigned long)current->mm->context.vdso)
#define VDSO_SYM(x) (VDSO_BASE + (unsigned long)(x))
+/* update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT entries changes */
#define ARCH_DLINFO \
do { \
if (vdso_enabled) \
diff --git a/include/asm-sh/floppy.h b/include/asm-sh/floppy.h
index 3b59b3af777b..59fbfdc90dfb 100644
--- a/include/asm-sh/floppy.h
+++ b/include/asm-sh/floppy.h
@@ -213,7 +213,7 @@ static int hard_dma_setup(char *addr, unsigned long size, int mode, int io)
}
#endif
- dma_cache_wback_inv(addr, size);
+ __flush_purge_region(addr, size);
/* actual, physical DMA */
doing_pdma = 0;
@@ -263,10 +263,6 @@ static int FDC2 = -1;
#define N_FDC 2
#define N_DRIVE 8
-#define FLOPPY_MOTOR_MASK 0xf0
-
-#define AUTO_DMA
-
#define EXTRA_FLOPPY_PARAMS
#endif /* __ASM_SH_FLOPPY_H */
diff --git a/include/asm-sh/io.h b/include/asm-sh/io.h
index 1a336cdc75fe..6ed34d8eac5f 100644
--- a/include/asm-sh/io.h
+++ b/include/asm-sh/io.h
@@ -327,31 +327,6 @@ __ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags)
__iounmap((addr))
/*
- * The caches on some architectures aren't dma-coherent and have need to
- * handle this in software. There are three types of operations that
- * can be applied to dma buffers.
- *
- * - dma_cache_wback_inv(start, size) makes caches and RAM coherent by
- * writing the content of the caches back to memory, if necessary.
- * The function also invalidates the affected part of the caches as
- * necessary before DMA transfers from outside to memory.
- * - dma_cache_inv(start, size) invalidates the affected parts of the
- * caches. Dirty lines of the caches may be written back or simply
- * be discarded. This operation is necessary before dma operations
- * to the memory.
- * - dma_cache_wback(start, size) writes back any dirty lines but does
- * not invalidate the cache. This can be used before DMA reads from
- * memory,
- */
-
-#define dma_cache_wback_inv(_start,_size) \
- __flush_purge_region(_start,_size)
-#define dma_cache_inv(_start,_size) \
- __flush_invalidate_region(_start,_size)
-#define dma_cache_wback(_start,_size) \
- __flush_wback_region(_start,_size)
-
-/*
* Convert a physical pointer to a virtual kernel pointer for /dev/mem
* access
*/
diff --git a/include/asm-sh/ipc.h b/include/asm-sh/ipc.h
deleted file mode 100644
index a46e3d9c2a3f..000000000000
--- a/include/asm-sh/ipc.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ipc.h>
diff --git a/include/asm-sh/irq.h b/include/asm-sh/irq.h
index c61d902b8bff..11850f65c922 100644
--- a/include/asm-sh/irq.h
+++ b/include/asm-sh/irq.h
@@ -41,7 +41,7 @@ static inline int generic_irq_demux(int irq)
#define irq_canonicalize(irq) (irq)
#define irq_demux(irq) sh_mv.mv_irq_demux(irq)
-#ifdef CONFIG_4KSTACKS
+#ifdef CONFIG_IRQSTACKS
extern void irq_ctx_init(int cpu);
extern void irq_ctx_exit(int cpu);
# define __ARCH_HAS_DO_SOFTIRQ
diff --git a/include/asm-sh/kdebug.h b/include/asm-sh/kdebug.h
index 382cfc7deb73..49cd69051a88 100644
--- a/include/asm-sh/kdebug.h
+++ b/include/asm-sh/kdebug.h
@@ -1,8 +1,6 @@
#ifndef __ASM_SH_KDEBUG_H
#define __ASM_SH_KDEBUG_H
-#include <linux/notifier.h>
-
/* Grossly misnamed. */
enum die_val {
DIE_TRAP,
diff --git a/include/asm-sh/page.h b/include/asm-sh/page.h
index cb3d46c59eab..d00a8fde7c7f 100644
--- a/include/asm-sh/page.h
+++ b/include/asm-sh/page.h
@@ -73,10 +73,13 @@ extern void copy_page_nommu(void *to, void *from);
#if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_MMU) && \
(defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB))
struct page;
-extern void clear_user_page(void *to, unsigned long address, struct page *pg);
-extern void copy_user_page(void *to, void *from, unsigned long address, struct page *pg);
-extern void __clear_user_page(void *to, void *orig_to);
-extern void __copy_user_page(void *to, void *from, void *orig_to);
+struct vm_area_struct;
+extern void clear_user_page(void *to, unsigned long address, struct page *page);
+#ifdef CONFIG_CPU_SH4
+extern void copy_user_highpage(struct page *to, struct page *from,
+ unsigned long vaddr, struct vm_area_struct *vma);
+#define __HAVE_ARCH_COPY_USER_HIGHPAGE
+#endif
#else
#define clear_user_page(page, vaddr, pg) clear_page(page)
#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
@@ -128,7 +131,6 @@ typedef struct { unsigned long pgd; } pgd_t;
#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
-#define phys_to_page(phys) (pfn_to_page(phys >> PAGE_SHIFT))
#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
/* PFN start number, because of __MEMORY_START */
diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h
index cf0dd2b648c2..8f1e8be8d15d 100644
--- a/include/asm-sh/pgtable.h
+++ b/include/asm-sh/pgtable.h
@@ -322,7 +322,9 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
#define PAGE_KERNEL __pgprot(0)
#define PAGE_KERNEL_NOCACHE __pgprot(0)
#define PAGE_KERNEL_RO __pgprot(0)
-#define PAGE_KERNEL_PCC __pgprot(0)
+
+#define PAGE_KERNEL_PCC(slot, type) \
+ __pgprot(0)
#endif
#endif /* __ASSEMBLY__ */
@@ -399,7 +401,7 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
#define pmd_bad(x) (pmd_val(x) & ~PAGE_MASK)
#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
-#define pte_page(x) phys_to_page(pte_val(x)&PTE_PHYS_MASK)
+#define pte_page(x) pfn_to_page(pte_pfn(x))
/*
* The following only work if pte_present() is true.
diff --git a/include/asm-sh/processor.h b/include/asm-sh/processor.h
index 4f2922a1979c..fda68480f377 100644
--- a/include/asm-sh/processor.h
+++ b/include/asm-sh/processor.h
@@ -49,7 +49,7 @@ enum cpu_type {
/* SH-4 types */
CPU_SH7750, CPU_SH7750S, CPU_SH7750R, CPU_SH7751, CPU_SH7751R,
- CPU_SH7760, CPU_ST40RA, CPU_ST40GX1, CPU_SH4_202, CPU_SH4_501,
+ CPU_SH7760, CPU_SH4_202, CPU_SH4_501,
/* SH-4A types */
CPU_SH7770, CPU_SH7780, CPU_SH7781, CPU_SH7785, CPU_SHX3,
@@ -71,7 +71,7 @@ struct sh_cpuinfo {
struct cache_info scache; /* Secondary cache */
unsigned long flags;
-} __attribute__ ((aligned(SMP_CACHE_BYTES)));
+} __attribute__ ((aligned(L1_CACHE_BYTES)));
extern struct sh_cpuinfo cpu_data[];
#define boot_cpu_data cpu_data[0]
diff --git a/include/asm-sh/ptrace.h b/include/asm-sh/ptrace.h
index ed358a376e6e..b9789c8b4d15 100644
--- a/include/asm-sh/ptrace.h
+++ b/include/asm-sh/ptrace.h
@@ -42,9 +42,6 @@
#define REG_FPSCR 55
#define REG_FPUL 56
-/* options set using PTRACE_SETOPTIONS */
-#define PTRACE_O_TRACESYSGOOD 0x00000001
-
/*
* This struct defines the way the registers are stored on the
* kernel stack during a system call or other kernel entry.
diff --git a/include/asm-sh/scatterlist.h b/include/asm-sh/scatterlist.h
index b9ae53c38365..a7d0d1856a99 100644
--- a/include/asm-sh/scatterlist.h
+++ b/include/asm-sh/scatterlist.h
@@ -4,7 +4,10 @@
#include <asm/types.h>
struct scatterlist {
- struct page * page; /* Location for highmem page, if any */
+#ifdef CONFIG_DEBUG_SG
+ unsigned long sg_magic;
+#endif
+ unsigned long page_link;
unsigned int offset;/* for highmem, page offset */
dma_addr_t dma_address;
unsigned int length;
diff --git a/include/asm-sh/se7751.h b/include/asm-sh/se7751.h
index 02ca9347f043..b36792ac5d66 100644
--- a/include/asm-sh/se7751.h
+++ b/include/asm-sh/se7751.h
@@ -36,7 +36,7 @@
#define PA_LED 0xba000000 /* LED */
#define PA_BCR 0xbb000000 /* FPGA on the MS7751SE01 */
-#define PA_MRSHPC 0xb83fffe0 /* MR-SHPC-01 PCMCIA controler */
+#define PA_MRSHPC 0xb83fffe0 /* MR-SHPC-01 PCMCIA controller */
#define PA_MRSHPC_MW1 0xb8400000 /* MR-SHPC-01 memory window base */
#define PA_MRSHPC_MW2 0xb8500000 /* MR-SHPC-01 attribute window base */
#define PA_MRSHPC_IO 0xb8600000 /* MR-SHPC-01 I/O window base */
diff --git a/include/asm-sh/semaphore.h b/include/asm-sh/semaphore.h
index 489f7847c5d9..9e5a37c4dce2 100644
--- a/include/asm-sh/semaphore.h
+++ b/include/asm-sh/semaphore.h
@@ -37,7 +37,6 @@ struct semaphore {
struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
-#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
static inline void sema_init (struct semaphore *sem, int val)
{
diff --git a/include/asm-sh/setup.h b/include/asm-sh/setup.h
index 586a9711a75d..55a2bd328d99 100644
--- a/include/asm-sh/setup.h
+++ b/include/asm-sh/setup.h
@@ -5,6 +5,20 @@
#ifdef __KERNEL__
+/*
+ * This is set up by the setup-routine at boot-time
+ */
+#define PARAM ((unsigned char *)empty_zero_page)
+
+#define MOUNT_ROOT_RDONLY (*(unsigned long *) (PARAM+0x000))
+#define RAMDISK_FLAGS (*(unsigned long *) (PARAM+0x004))
+#define ORIG_ROOT_DEV (*(unsigned long *) (PARAM+0x008))
+#define LOADER_TYPE (*(unsigned long *) (PARAM+0x00c))
+#define INITRD_START (*(unsigned long *) (PARAM+0x010))
+#define INITRD_SIZE (*(unsigned long *) (PARAM+0x014))
+/* ... */
+#define COMMAND_LINE ((char *) (PARAM+0x100))
+
int setup_early_printk(char *);
void sh_mv_setup(void);
diff --git a/include/asm-sh/system.h b/include/asm-sh/system.h
index 9d849e6df268..4faa2fb88616 100644
--- a/include/asm-sh/system.h
+++ b/include/asm-sh/system.h
@@ -15,6 +15,7 @@
struct task_struct *__switch_to(struct task_struct *prev,
struct task_struct *next);
+#define AT_VECTOR_SIZE_ARCH 1 /* entries in ARCH_DLINFO */
/*
* switch_to() should switch tasks to task nr n, first
*/
diff --git a/include/asm-sh/systemh7751.h b/include/asm-sh/systemh7751.h
index b143bb2a2ca7..4161122c84ef 100644
--- a/include/asm-sh/systemh7751.h
+++ b/include/asm-sh/systemh7751.h
@@ -36,7 +36,7 @@
#define PA_LED 0xba000000 /* LED */
#define PA_BCR 0xbb000000 /* FPGA on the MS7751SE01 */
-#define PA_MRSHPC 0xb83fffe0 /* MR-SHPC-01 PCMCIA controler */
+#define PA_MRSHPC 0xb83fffe0 /* MR-SHPC-01 PCMCIA controller */
#define PA_MRSHPC_MW1 0xb8400000 /* MR-SHPC-01 memory window base */
#define PA_MRSHPC_MW2 0xb8500000 /* MR-SHPC-01 attribute window base */
#define PA_MRSHPC_IO 0xb8600000 /* MR-SHPC-01 I/O window base */
diff --git a/include/asm-sh/tlbflush.h b/include/asm-sh/tlbflush.h
index 455fb8da441e..e0ac97221ae6 100644
--- a/include/asm-sh/tlbflush.h
+++ b/include/asm-sh/tlbflush.h
@@ -9,7 +9,6 @@
* - flush_tlb_page(vma, vmaddr) flushes one page
* - flush_tlb_range(vma, start, end) flushes a range of pages
* - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
- * - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
*/
extern void local_flush_tlb_all(void);
extern void local_flush_tlb_mm(struct mm_struct *mm);
@@ -47,9 +46,4 @@ extern void flush_tlb_one(unsigned long asid, unsigned long page);
#endif /* CONFIG_SMP */
-static inline void flush_tlb_pgtables(struct mm_struct *mm,
- unsigned long start, unsigned long end)
-{
- /* Nothing to do */
-}
#endif /* __ASM_SH_TLBFLUSH_H */
diff --git a/include/asm-sh/types.h b/include/asm-sh/types.h
index fd00dbb82f84..7ba69d9707ef 100644
--- a/include/asm-sh/types.h
+++ b/include/asm-sh/types.h
@@ -19,9 +19,9 @@ typedef unsigned short __u16;
typedef __signed__ int __s32;
typedef unsigned int __u32;
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
-typedef __signed__ long long __s64;
-typedef unsigned long long __u64;
+#if defined(__GNUC__)
+__extension__ typedef __signed__ long long __s64;
+__extension__ typedef unsigned long long __u64;
#endif
#endif /* __ASSEMBLY__ */
diff --git a/include/asm-sh/vga.h b/include/asm-sh/vga.h
new file mode 100644
index 000000000000..06a5de8ace1a
--- /dev/null
+++ b/include/asm-sh/vga.h
@@ -0,0 +1,6 @@
+#ifndef __ASM_SH_VGA_H
+#define __ASM_SH_VGA_H
+
+/* Stupid drivers. */
+
+#endif /* __ASM_SH_VGA_H */
diff --git a/include/asm-sh64/bitops.h b/include/asm-sh64/bitops.h
index f3bdcdb5d046..600c59efb4c2 100644
--- a/include/asm-sh64/bitops.h
+++ b/include/asm-sh64/bitops.h
@@ -13,6 +13,11 @@
*/
#ifdef __KERNEL__
+
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
#include <linux/compiler.h>
#include <asm/system.h>
/* For __swab32 */
@@ -136,6 +141,7 @@ static __inline__ unsigned long ffz(unsigned long word)
#include <asm-generic/bitops/__ffs.h>
#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/lock.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/ffs.h>
#include <asm-generic/bitops/ext2-non-atomic.h>
diff --git a/include/asm-sh64/dma-mapping.h b/include/asm-sh64/dma-mapping.h
index de4309960207..18f8dd642ac5 100644
--- a/include/asm-sh64/dma-mapping.h
+++ b/include/asm-sh64/dma-mapping.h
@@ -2,7 +2,7 @@
#define __ASM_SH_DMA_MAPPING_H
#include <linux/mm.h>
-#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
#include <asm/io.h>
struct pci_dev;
@@ -42,7 +42,12 @@ static inline void dma_free_coherent(struct device *dev, size_t size,
static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
enum dma_data_direction dir)
{
- dma_cache_wback_inv((unsigned long)vaddr, size);
+ unsigned long start = (unsigned long) vaddr;
+ unsigned long s = start & L1_CACHE_ALIGN_MASK;
+ unsigned long e = (start + size) & L1_CACHE_ALIGN_MASK;
+
+ for (; s <= e; s += L1_CACHE_BYTES)
+ asm volatile ("ocbp %0, 0" : : "r" (s));
}
static inline dma_addr_t dma_map_single(struct device *dev,
@@ -67,10 +72,9 @@ static inline int dma_map_sg(struct device *dev, struct scatterlist *sg,
for (i = 0; i < nents; i++) {
#if !defined(CONFIG_PCI) || defined(CONFIG_SH_PCIDMA_NONCOHERENT)
- dma_cache_sync(dev, page_address(sg[i].page) + sg[i].offset,
- sg[i].length, dir);
+ dma_cache_sync(dev, sg_virt(&sg[i]), sg[i].length, dir);
#endif
- sg[i].dma_address = page_to_phys(sg[i].page) + sg[i].offset;
+ sg[i].dma_address = sg_phys(&sg[i]);
}
return nents;
@@ -120,10 +124,9 @@ static inline void dma_sync_sg(struct device *dev, struct scatterlist *sg,
for (i = 0; i < nelems; i++) {
#if !defined(CONFIG_PCI) || defined(CONFIG_SH_PCIDMA_NONCOHERENT)
- dma_cache_sync(dev, page_address(sg[i].page) + sg[i].offset,
- sg[i].length, dir);
+ dma_cache_sync(dev, sg_virt(&sg[i]), sg[i].length, dir);
#endif
- sg[i].dma_address = page_to_phys(sg[i].page) + sg[i].offset;
+ sg[i].dma_address = sg_phys(&sg[i]);
}
}
diff --git a/include/asm-sh64/ide.h b/include/asm-sh64/ide.h
index c9d84d5f772e..b6e31e8b9410 100644
--- a/include/asm-sh64/ide.h
+++ b/include/asm-sh64/ide.h
@@ -19,7 +19,6 @@
/* Without this, the initialisation of PCI IDE cards end up calling
* ide_init_hwif_ports, which won't work. */
#ifdef CONFIG_BLK_DEV_IDEPCI
-#define IDE_ARCH_OBSOLETE_INIT 1
#define ide_default_io_ctl(base) (0)
#endif
diff --git a/include/asm-sh64/io.h b/include/asm-sh64/io.h
index 3de3ad99f457..7bd7314d38c2 100644
--- a/include/asm-sh64/io.h
+++ b/include/asm-sh64/io.h
@@ -182,54 +182,6 @@ unsigned long onchip_remap(unsigned long addr, unsigned long size, const char* n
extern void onchip_unmap(unsigned long vaddr);
/*
- * The caches on some architectures aren't dma-coherent and have need to
- * handle this in software. There are three types of operations that
- * can be applied to dma buffers.
- *
- * - dma_cache_wback_inv(start, size) makes caches and RAM coherent by
- * writing the content of the caches back to memory, if necessary.
- * The function also invalidates the affected part of the caches as
- * necessary before DMA transfers from outside to memory.
- * - dma_cache_inv(start, size) invalidates the affected parts of the
- * caches. Dirty lines of the caches may be written back or simply
- * be discarded. This operation is necessary before dma operations
- * to the memory.
- * - dma_cache_wback(start, size) writes back any dirty lines but does
- * not invalidate the cache. This can be used before DMA reads from
- * memory,
- */
-
-static __inline__ void dma_cache_wback_inv (unsigned long start, unsigned long size)
-{
- unsigned long s = start & L1_CACHE_ALIGN_MASK;
- unsigned long e = (start + size) & L1_CACHE_ALIGN_MASK;
-
- for (; s <= e; s += L1_CACHE_BYTES)
- asm volatile ("ocbp %0, 0" : : "r" (s));
-}
-
-static __inline__ void dma_cache_inv (unsigned long start, unsigned long size)
-{
- // Note that caller has to be careful with overzealous
- // invalidation should there be partial cache lines at the extremities
- // of the specified range
- unsigned long s = start & L1_CACHE_ALIGN_MASK;
- unsigned long e = (start + size) & L1_CACHE_ALIGN_MASK;
-
- for (; s <= e; s += L1_CACHE_BYTES)
- asm volatile ("ocbi %0, 0" : : "r" (s));
-}
-
-static __inline__ void dma_cache_wback (unsigned long start, unsigned long size)
-{
- unsigned long s = start & L1_CACHE_ALIGN_MASK;
- unsigned long e = (start + size) & L1_CACHE_ALIGN_MASK;
-
- for (; s <= e; s += L1_CACHE_BYTES)
- asm volatile ("ocbwb %0, 0" : : "r" (s));
-}
-
-/*
* Convert a physical pointer to a virtual kernel pointer for /dev/mem
* access
*/
diff --git a/include/asm-sh64/ipc.h b/include/asm-sh64/ipc.h
deleted file mode 100644
index a46e3d9c2a3f..000000000000
--- a/include/asm-sh64/ipc.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ipc.h>
diff --git a/include/asm-sh64/pci.h b/include/asm-sh64/pci.h
index 57a67cf7a5c4..18055dbbb4b5 100644
--- a/include/asm-sh64/pci.h
+++ b/include/asm-sh64/pci.h
@@ -72,15 +72,6 @@ static inline void pcibios_penalize_isa_irq(int irq, int active)
#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0)
#endif
-/* These macros should be used after a pci_map_sg call has been done
- * to get bus addresses of each of the SG entries and their lengths.
- * You should only work with the number of sg entries pci_map_sg
- * returns, or alternatively stop on the first sg_dma_len(sg) which
- * is 0.
- */
-#define sg_dma_address(sg) ((sg)->dma_address)
-#define sg_dma_len(sg) ((sg)->length)
-
#ifdef CONFIG_PCI
static inline void pci_dma_burst_advice(struct pci_dev *pdev,
enum pci_dma_burst_strategy *strat,
diff --git a/include/asm-sh64/ptrace.h b/include/asm-sh64/ptrace.h
index a6d4da519db6..c424f80e3ae0 100644
--- a/include/asm-sh64/ptrace.h
+++ b/include/asm-sh64/ptrace.h
@@ -32,6 +32,4 @@ struct pt_regs {
extern void show_regs(struct pt_regs *);
#endif
-#define PTRACE_O_TRACESYSGOOD 0x00000001
-
#endif /* __ASM_SH64_PTRACE_H */
diff --git a/include/asm-sh64/scatterlist.h b/include/asm-sh64/scatterlist.h
index 1c723f2d7a95..7f729bbfce43 100644
--- a/include/asm-sh64/scatterlist.h
+++ b/include/asm-sh64/scatterlist.h
@@ -14,12 +14,24 @@
#include <asm/types.h>
struct scatterlist {
- struct page * page; /* Location for highmem page, if any */
+#ifdef CONFIG_DEBUG_SG
+ unsigned long sg_magic;
+#endif
+ unsigned long page_link;
unsigned int offset;/* for highmem, page offset */
dma_addr_t dma_address;
unsigned int length;
};
+/* These macros should be used after a pci_map_sg call has been done
+ * to get bus addresses of each of the SG entries and their lengths.
+ * You should only work with the number of sg entries pci_map_sg
+ * returns, or alternatively stop on the first sg_dma_len(sg) which
+ * is 0.
+ */
+#define sg_dma_address(sg) ((sg)->dma_address)
+#define sg_dma_len(sg) ((sg)->length)
+
#define ISA_DMA_THRESHOLD (0xffffffff)
#endif /* !__ASM_SH64_SCATTERLIST_H */
diff --git a/include/asm-sh64/semaphore.h b/include/asm-sh64/semaphore.h
index 469526459149..f027cc14b55b 100644
--- a/include/asm-sh64/semaphore.h
+++ b/include/asm-sh64/semaphore.h
@@ -44,7 +44,6 @@ struct semaphore {
struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
-#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
static inline void sema_init (struct semaphore *sem, int val)
{
diff --git a/include/asm-sh64/system.h b/include/asm-sh64/system.h
index 5ff94644e8c8..be2a15ffcc55 100644
--- a/include/asm-sh64/system.h
+++ b/include/asm-sh64/system.h
@@ -62,8 +62,7 @@ extern void __xchg_called_with_bad_pointer(void);
#define smp_read_barrier_depends() do { } while (0)
#endif /* CONFIG_SMP */
-#define set_rmb(var, value) do { (void)xchg(&var, value); } while (0)
-#define set_mb(var, value) set_rmb(var, value)
+#define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
/* Interrupt Control */
#ifndef HARD_CLI
diff --git a/include/asm-sh64/tlbflush.h b/include/asm-sh64/tlbflush.h
index e45beadc29ee..16a164a23754 100644
--- a/include/asm-sh64/tlbflush.h
+++ b/include/asm-sh64/tlbflush.h
@@ -20,10 +20,6 @@ extern void flush_tlb_mm(struct mm_struct *mm);
extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
unsigned long end);
extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long page);
-static inline void flush_tlb_pgtables(struct mm_struct *mm,
- unsigned long start, unsigned long end)
-{
-}
extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
diff --git a/include/asm-sh64/types.h b/include/asm-sh64/types.h
index 8d41db2153b5..2c7ad73b3883 100644
--- a/include/asm-sh64/types.h
+++ b/include/asm-sh64/types.h
@@ -30,9 +30,9 @@ typedef unsigned short __u16;
typedef __signed__ int __s32;
typedef unsigned int __u32;
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
-typedef __signed__ long long __s64;
-typedef unsigned long long __u64;
+#if defined(__GNUC__)
+__extension__ typedef __signed__ long long __s64;
+__extension__ typedef unsigned long long __u64;
#endif
#endif /* __ASSEMBLY__ */
diff --git a/include/asm-sparc/atomic.h b/include/asm-sparc/atomic.h
index bdca5416d8b0..3328950dbfe6 100644
--- a/include/asm-sparc/atomic.h
+++ b/include/asm-sparc/atomic.h
@@ -1,6 +1,6 @@
/* atomic.h: These still suck, but the I-cache hit rate is higher.
*
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
* Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com.au)
* Copyright (C) 2007 Kyle McMartin (kyle@parisc-linux.org)
*
@@ -33,7 +33,7 @@ extern void __cmpxchg_called_with_bad_pointer(void);
extern unsigned long __cmpxchg_u32(volatile u32 *m, u32 old, u32 new_);
/* don't worry...optimizer will get rid of most of this */
-static __inline__ unsigned long
+static inline unsigned long
__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new_, int size)
{
switch(size) {
diff --git a/include/asm-sparc/bitops.h b/include/asm-sparc/bitops.h
index 329e696e7751..cb3cefab6e09 100644
--- a/include/asm-sparc/bitops.h
+++ b/include/asm-sparc/bitops.h
@@ -14,6 +14,10 @@
#ifdef __KERNEL__
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
extern unsigned long ___set_bit(unsigned long *addr, unsigned long mask);
extern unsigned long ___clear_bit(unsigned long *addr, unsigned long mask);
extern unsigned long ___change_bit(unsigned long *addr, unsigned long mask);
@@ -96,6 +100,7 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
#include <asm-generic/bitops/fls.h>
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/lock.h>
#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/ext2-non-atomic.h>
#include <asm-generic/bitops/ext2-atomic.h>
diff --git a/include/asm-sparc/dma.h b/include/asm-sparc/dma.h
index 407b3614468a..959d6c8a71ae 100644
--- a/include/asm-sparc/dma.h
+++ b/include/asm-sparc/dma.h
@@ -1,7 +1,6 @@
-/* $Id: dma.h,v 1.35 1999/12/27 06:37:09 anton Exp $
- * include/asm-sparc/dma.h
+/* include/asm-sparc/dma.h
*
- * Copyright 1995 (C) David S. Miller (davem@caip.rutgers.edu)
+ * Copyright 1995 (C) David S. Miller (davem@davemloft.net)
*/
#ifndef _ASM_SPARC_DMA_H
@@ -21,14 +20,14 @@
struct page;
extern spinlock_t dma_spin_lock;
-static __inline__ unsigned long claim_dma_lock(void)
+static inline unsigned long claim_dma_lock(void)
{
unsigned long flags;
spin_lock_irqsave(&dma_spin_lock, flags);
return flags;
}
-static __inline__ void release_dma_lock(unsigned long flags)
+static inline void release_dma_lock(unsigned long flags)
{
spin_unlock_irqrestore(&dma_spin_lock, flags);
}
diff --git a/include/asm-sparc/floppy.h b/include/asm-sparc/floppy.h
index acd06d8ff70a..dbe7a586be5b 100644
--- a/include/asm-sparc/floppy.h
+++ b/include/asm-sparc/floppy.h
@@ -1,6 +1,6 @@
/* asm-sparc/floppy.h: Sparc specific parts of the Floppy driver.
*
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1995 David S. Miller (davem@davemloft.net)
*/
#ifndef __ASM_SPARC_FLOPPY_H
@@ -77,8 +77,6 @@ static struct sun_floppy_ops sun_fdops;
#define fd_dma_mem_free(addr,size) (vfree((void *)(addr)))
#endif
-#define FLOPPY_MOTOR_MASK 0x10
-
/* XXX This isn't really correct. XXX */
#define get_dma_residue(x) (0)
@@ -234,12 +232,12 @@ extern char *pdma_base;
extern unsigned long pdma_areasize;
/* Common routines to all controller types on the Sparc. */
-static __inline__ void virtual_dma_init(void)
+static inline void virtual_dma_init(void)
{
/* nothing... */
}
-static __inline__ void sun_fd_disable_dma(void)
+static inline void sun_fd_disable_dma(void)
{
doing_pdma = 0;
if (pdma_base) {
@@ -248,7 +246,7 @@ static __inline__ void sun_fd_disable_dma(void)
}
}
-static __inline__ void sun_fd_set_dma_mode(int mode)
+static inline void sun_fd_set_dma_mode(int mode)
{
switch(mode) {
case DMA_MODE_READ:
@@ -263,17 +261,17 @@ static __inline__ void sun_fd_set_dma_mode(int mode)
}
}
-static __inline__ void sun_fd_set_dma_addr(char *buffer)
+static inline void sun_fd_set_dma_addr(char *buffer)
{
pdma_vaddr = buffer;
}
-static __inline__ void sun_fd_set_dma_count(int length)
+static inline void sun_fd_set_dma_count(int length)
{
pdma_size = length;
}
-static __inline__ void sun_fd_enable_dma(void)
+static inline void sun_fd_enable_dma(void)
{
pdma_vaddr = mmu_lockarea(pdma_vaddr, pdma_size);
pdma_base = pdma_vaddr;
diff --git a/include/asm-sparc/ide.h b/include/asm-sparc/ide.h
index a6d735a1310e..4076cb5d1581 100644
--- a/include/asm-sparc/ide.h
+++ b/include/asm-sparc/ide.h
@@ -1,7 +1,6 @@
-/* $Id: ide.h,v 1.7 2002/01/16 20:58:40 davem Exp $
- * ide.h: SPARC PCI specific IDE glue.
+/* ide.h: SPARC PCI specific IDE glue.
*
- * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1997 David S. Miller (davem@davemloft.net)
* Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
* Adaptation from sparc64 version to sparc by Pete Zaitcev.
*/
@@ -18,7 +17,6 @@
#undef MAX_HWIFS
#define MAX_HWIFS 2
-#define IDE_ARCH_OBSOLETE_INIT
#define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */
#define __ide_insl(data_reg, buffer, wcount) \
@@ -32,7 +30,7 @@
#define __ide_mm_outsw __ide_outsw
#define __ide_mm_outsl __ide_outsl
-static __inline__ void __ide_insw(unsigned long port,
+static inline void __ide_insw(unsigned long port,
void *dst,
unsigned long count)
{
@@ -63,7 +61,7 @@ static __inline__ void __ide_insw(unsigned long port,
/* __flush_dcache_range((unsigned long)dst, end); */ /* P3 see hme */
}
-static __inline__ void __ide_outsw(unsigned long port,
+static inline void __ide_outsw(unsigned long port,
const void *src,
unsigned long count)
{
diff --git a/include/asm-sparc/io.h b/include/asm-sparc/io.h
index c23e74a0eaa8..243bf8e9a058 100644
--- a/include/asm-sparc/io.h
+++ b/include/asm-sparc/io.h
@@ -310,13 +310,6 @@ extern void sbus_iounmap(volatile void __iomem *vaddr, unsigned long size);
#define RTC_PORT(x) (rtc_port + (x))
#define RTC_ALWAYS_BCD 0
-/* Nothing to do */
-/* P3: Only IDE DMA may need these. XXX Verify that it still does... */
-
-#define dma_cache_inv(_start,_size) do { } while (0)
-#define dma_cache_wback(_start,_size) do { } while (0)
-#define dma_cache_wback_inv(_start,_size) do { } while (0)
-
#endif
#define __ARCH_HAS_NO_PAGE_ZERO_MAPPED 1
diff --git a/include/asm-sparc/ioctls.h b/include/asm-sparc/ioctls.h
index bdf77b0dfd8e..058c2064f706 100644
--- a/include/asm-sparc/ioctls.h
+++ b/include/asm-sparc/ioctls.h
@@ -15,6 +15,10 @@
#define TCSETS _IOW('T', 9, struct termios)
#define TCSETSW _IOW('T', 10, struct termios)
#define TCSETSF _IOW('T', 11, struct termios)
+#define TCGETS2 _IOR('T', 12, struct termios2)
+#define TCSETS2 _IOW('T', 13, struct termios2)
+#define TCSETSW2 _IOW('T', 14, struct termios2)
+#define TCSETSF2 _IOW('T', 15, struct termios2)
/* Note that all the ioctls that are not available in Linux have a
* double underscore on the front to: a) avoid some programs to
diff --git a/include/asm-sparc/ipc.h b/include/asm-sparc/ipc.h
deleted file mode 100644
index a46e3d9c2a3f..000000000000
--- a/include/asm-sparc/ipc.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ipc.h>
diff --git a/include/asm-sparc/of_platform.h b/include/asm-sparc/of_platform.h
index 64a230064ef2..d638737ff13c 100644
--- a/include/asm-sparc/of_platform.h
+++ b/include/asm-sparc/of_platform.h
@@ -18,12 +18,9 @@
extern struct bus_type ebus_bus_type;
extern struct bus_type sbus_bus_type;
-extern struct bus_type of_platform_bus_type;
+
#define of_bus_type of_platform_bus_type /* for compatibility */
-extern int of_register_driver(struct of_platform_driver *drv,
- struct bus_type *bus);
-extern void of_unregister_driver(struct of_platform_driver *drv);
extern struct of_device *of_platform_device_create(struct device_node *np,
const char *bus_id,
struct device *parent,
diff --git a/include/asm-sparc/posix_types.h b/include/asm-sparc/posix_types.h
index 9ef1b3db4cbf..62c8fa7b36d4 100644
--- a/include/asm-sparc/posix_types.h
+++ b/include/asm-sparc/posix_types.h
@@ -49,7 +49,7 @@ typedef struct {
#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
#undef __FD_SET
-static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
+static inline void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
{
unsigned long _tmp = fd / __NFDBITS;
unsigned long _rem = fd % __NFDBITS;
@@ -57,7 +57,7 @@ static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
}
#undef __FD_CLR
-static __inline__ void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
+static inline void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
{
unsigned long _tmp = fd / __NFDBITS;
unsigned long _rem = fd % __NFDBITS;
@@ -65,7 +65,7 @@ static __inline__ void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
}
#undef __FD_ISSET
-static __inline__ int __FD_ISSET(unsigned long fd, __const__ __kernel_fd_set *p)
+static inline int __FD_ISSET(unsigned long fd, __const__ __kernel_fd_set *p)
{
unsigned long _tmp = fd / __NFDBITS;
unsigned long _rem = fd % __NFDBITS;
@@ -77,7 +77,7 @@ static __inline__ int __FD_ISSET(unsigned long fd, __const__ __kernel_fd_set *p)
* for 256 and 1024-bit fd_sets respectively)
*/
#undef __FD_ZERO
-static __inline__ void __FD_ZERO(__kernel_fd_set *p)
+static inline void __FD_ZERO(__kernel_fd_set *p)
{
unsigned long *tmp = p->fds_bits;
int i;
diff --git a/include/asm-sparc/scatterlist.h b/include/asm-sparc/scatterlist.h
index a4fcf9ac9649..e08d3d775b08 100644
--- a/include/asm-sparc/scatterlist.h
+++ b/include/asm-sparc/scatterlist.h
@@ -5,7 +5,10 @@
#include <linux/types.h>
struct scatterlist {
- struct page *page;
+#ifdef CONFIG_DEBUG_SG
+ unsigned long sg_magic;
+#endif
+ unsigned long page_link;
unsigned int offset;
unsigned int length;
@@ -19,4 +22,6 @@ struct scatterlist {
#define ISA_DMA_THRESHOLD (~0UL)
+#define ARCH_HAS_SG_CHAIN
+
#endif /* !(_SPARC_SCATTERLIST_H) */
diff --git a/include/asm-sparc/semaphore.h b/include/asm-sparc/semaphore.h
index f74ba31e265b..8018f9f4d497 100644
--- a/include/asm-sparc/semaphore.h
+++ b/include/asm-sparc/semaphore.h
@@ -26,7 +26,6 @@ struct semaphore {
struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
-#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
static inline void sema_init (struct semaphore *sem, int val)
{
diff --git a/include/asm-sparc/system.h b/include/asm-sparc/system.h
index 8c259de02614..2655d142b22d 100644
--- a/include/asm-sparc/system.h
+++ b/include/asm-sparc/system.h
@@ -1,5 +1,3 @@
-/* $Id: system.h,v 1.86 2001/10/30 04:57:10 davem Exp $ */
-
#ifndef __SPARC_SYSTEM_H
#define __SPARC_SYSTEM_H
@@ -56,7 +54,7 @@ extern void sun_do_break(void);
extern int serial_console;
extern int stop_a_enabled;
-static __inline__ int con_is_present(void)
+static inline int con_is_present(void)
{
return serial_console ? 0 : 1;
}
@@ -217,7 +215,7 @@ static inline unsigned long xchg_u32(__volatile__ unsigned long *m, unsigned lon
extern void __xchg_called_with_bad_pointer(void);
-static __inline__ unsigned long __xchg(unsigned long x, __volatile__ void * ptr, int size)
+static inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr, int size)
{
switch (size) {
case 4:
diff --git a/include/asm-sparc/termbits.h b/include/asm-sparc/termbits.h
index 5eb00a105d7c..90cf2210118b 100644
--- a/include/asm-sparc/termbits.h
+++ b/include/asm-sparc/termbits.h
@@ -31,6 +31,18 @@ struct termios {
#endif
};
+struct termios2 {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[NCCS]; /* control characters */
+ cc_t _x_cc[2]; /* padding to match ktermios */
+ speed_t c_ispeed; /* input speed */
+ speed_t c_ospeed; /* output speed */
+};
+
struct ktermios {
tcflag_t c_iflag; /* input mode flags */
tcflag_t c_oflag; /* output mode flags */
@@ -160,6 +172,7 @@ struct ktermios {
#define CLOCAL 0x00000800
#define CBAUDEX 0x00001000
/* We'll never see these speeds with the Zilogs, but for completeness... */
+#define BOTHER 0x00001000
#define B57600 0x00001001
#define B115200 0x00001002
#define B230400 0x00001003
@@ -189,6 +202,8 @@ struct ktermios {
#define CMSPAR 0x40000000 /* mark or space (stick) parity */
#define CRTSCTS 0x80000000 /* flow control */
+#define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */
+
/* c_lflag bits */
#define ISIG 0x00000001
#define ICANON 0x00000002
diff --git a/include/asm-sparc/termios.h b/include/asm-sparc/termios.h
index d767f206ab33..4333232abb9f 100644
--- a/include/asm-sparc/termios.h
+++ b/include/asm-sparc/termios.h
@@ -108,13 +108,55 @@ struct winsize {
#define user_termios_to_kernel_termios(k, u) \
({ \
+ int err; \
+ err = get_user((k)->c_iflag, &(u)->c_iflag); \
+ err |= get_user((k)->c_oflag, &(u)->c_oflag); \
+ err |= get_user((k)->c_cflag, &(u)->c_cflag); \
+ err |= get_user((k)->c_lflag, &(u)->c_lflag); \
+ err |= get_user((k)->c_line, &(u)->c_line); \
+ err |= copy_from_user((k)->c_cc, (u)->c_cc, NCCS); \
+ if ((k)->c_lflag & ICANON) { \
+ err |= get_user((k)->c_cc[VEOF], &(u)->c_cc[VEOF]); \
+ err |= get_user((k)->c_cc[VEOL], &(u)->c_cc[VEOL]); \
+ } else { \
+ err |= get_user((k)->c_cc[VMIN], &(u)->c_cc[_VMIN]); \
+ err |= get_user((k)->c_cc[VTIME], &(u)->c_cc[_VTIME]); \
+ } \
+ err |= get_user((k)->c_ispeed, &(u)->c_ispeed); \
+ err |= get_user((k)->c_ospeed, &(u)->c_ospeed); \
+ err; \
+})
+
+#define kernel_termios_to_user_termios(u, k) \
+({ \
+ int err; \
+ err = put_user((k)->c_iflag, &(u)->c_iflag); \
+ err |= put_user((k)->c_oflag, &(u)->c_oflag); \
+ err |= put_user((k)->c_cflag, &(u)->c_cflag); \
+ err |= put_user((k)->c_lflag, &(u)->c_lflag); \
+ err |= put_user((k)->c_line, &(u)->c_line); \
+ err |= copy_to_user((u)->c_cc, (k)->c_cc, NCCS); \
+ if (!((k)->c_lflag & ICANON)) { \
+ err |= put_user((k)->c_cc[VMIN], &(u)->c_cc[_VMIN]); \
+ err |= put_user((k)->c_cc[VTIME], &(u)->c_cc[_VTIME]); \
+ } else { \
+ err |= put_user((k)->c_cc[VEOF], &(u)->c_cc[VEOF]); \
+ err |= put_user((k)->c_cc[VEOL], &(u)->c_cc[VEOL]); \
+ } \
+ err |= put_user((k)->c_ispeed, &(u)->c_ispeed); \
+ err |= put_user((k)->c_ospeed, &(u)->c_ospeed); \
+ err; \
+})
+
+#define user_termios_to_kernel_termios_1(k, u) \
+({ \
get_user((k)->c_iflag, &(u)->c_iflag); \
get_user((k)->c_oflag, &(u)->c_oflag); \
get_user((k)->c_cflag, &(u)->c_cflag); \
get_user((k)->c_lflag, &(u)->c_lflag); \
get_user((k)->c_line, &(u)->c_line); \
copy_from_user((k)->c_cc, (u)->c_cc, NCCS); \
- if((k)->c_lflag & ICANON) { \
+ if ((k)->c_lflag & ICANON) { \
get_user((k)->c_cc[VEOF], &(u)->c_cc[VEOF]); \
get_user((k)->c_cc[VEOL], &(u)->c_cc[VEOL]); \
} else { \
@@ -124,7 +166,7 @@ struct winsize {
0; \
})
-#define kernel_termios_to_user_termios(u, k) \
+#define kernel_termios_to_user_termios_1(u, k) \
({ \
put_user((k)->c_iflag, &(u)->c_iflag); \
put_user((k)->c_oflag, &(u)->c_oflag); \
@@ -132,7 +174,7 @@ struct winsize {
put_user((k)->c_lflag, &(u)->c_lflag); \
put_user((k)->c_line, &(u)->c_line); \
copy_to_user((u)->c_cc, (k)->c_cc, NCCS); \
- if(!((k)->c_lflag & ICANON)) { \
+ if (!((k)->c_lflag & ICANON)) { \
put_user((k)->c_cc[VMIN], &(u)->c_cc[_VMIN]); \
put_user((k)->c_cc[VTIME], &(u)->c_cc[_VTIME]); \
} else { \
diff --git a/include/asm-sparc/tlbflush.h b/include/asm-sparc/tlbflush.h
index a619da5cfaa9..b957e29d2ae1 100644
--- a/include/asm-sparc/tlbflush.h
+++ b/include/asm-sparc/tlbflush.h
@@ -13,7 +13,6 @@
* - flush_tlb_page(vma, vmaddr) flushes one page
* - flush_tlb_range(vma, start, end) flushes a range of pages
* - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
- * - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
*/
#ifdef CONFIG_SMP
@@ -42,11 +41,6 @@ BTFIXUPDEF_CALL(void, flush_tlb_mm, struct mm_struct *)
BTFIXUPDEF_CALL(void, flush_tlb_range, struct vm_area_struct *, unsigned long, unsigned long)
BTFIXUPDEF_CALL(void, flush_tlb_page, struct vm_area_struct *, unsigned long)
-// Thanks to Anton Blanchard, our pagetables became uncached in 2.4. Wee!
-// extern void flush_tlb_pgtables(struct mm_struct *mm,
-// unsigned long start, unsigned long end);
-#define flush_tlb_pgtables(mm, start, end) do{ }while(0)
-
#define flush_tlb_all() BTFIXUP_CALL(flush_tlb_all)()
#define flush_tlb_mm(mm) BTFIXUP_CALL(flush_tlb_mm)(mm)
#define flush_tlb_range(vma,start,end) BTFIXUP_CALL(flush_tlb_range)(vma,start,end)
diff --git a/include/asm-sparc64/Kbuild b/include/asm-sparc64/Kbuild
index 854fd3a65acf..a90dc82129d1 100644
--- a/include/asm-sparc64/Kbuild
+++ b/include/asm-sparc64/Kbuild
@@ -10,7 +10,6 @@ header-y += bbc.h
header-y += bpp.h
header-y += display7seg.h
header-y += envctrl.h
-header-y += ipc.h
header-y += openprom.h
header-y += openpromio.h
header-y += pconf.h
diff --git a/include/asm-sparc64/atomic.h b/include/asm-sparc64/atomic.h
index 3fb4e1f7f186..2c71ec4a3b18 100644
--- a/include/asm-sparc64/atomic.h
+++ b/include/asm-sparc64/atomic.h
@@ -1,5 +1,4 @@
-/* $Id: atomic.h,v 1.22 2001/07/11 23:56:07 davem Exp $
- * atomic.h: Thankfully the V9 is at least reasonable for this
+/* atomic.h: Thankfully the V9 is at least reasonable for this
* stuff.
*
* Copyright (C) 1996, 1997, 2000 David S. Miller (davem@redhat.com)
@@ -74,7 +73,7 @@ extern int atomic64_sub_ret(int, atomic64_t *);
#define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n)))
#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+static inline int atomic_add_unless(atomic_t *v, int a, int u)
{
int c, old;
c = atomic_read(v);
@@ -95,7 +94,7 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n)))
#define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
-static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
+static inline int atomic64_add_unless(atomic64_t *v, long a, long u)
{
long c, old;
c = atomic64_read(v);
diff --git a/include/asm-sparc64/backoff.h b/include/asm-sparc64/backoff.h
new file mode 100644
index 000000000000..dadd6c385c6c
--- /dev/null
+++ b/include/asm-sparc64/backoff.h
@@ -0,0 +1,30 @@
+#ifndef _SPARC64_BACKOFF_H
+#define _SPARC64_BACKOFF_H
+
+#define BACKOFF_LIMIT (4 * 1024)
+
+#ifdef CONFIG_SMP
+
+#define BACKOFF_SETUP(reg) \
+ mov 1, reg
+
+#define BACKOFF_SPIN(reg, tmp, label) \
+ mov reg, tmp; \
+88: brnz,pt tmp, 88b; \
+ sub tmp, 1, tmp; \
+ cmp reg, BACKOFF_LIMIT; \
+ bg,pn %xcc, label; \
+ nop; \
+ ba,pt %xcc, label; \
+ sllx reg, 1, reg;
+
+#else
+
+#define BACKOFF_SETUP(reg)
+#define BACKOFF_SPIN(reg, tmp, label) \
+ ba,pt %xcc, label; \
+ nop;
+
+#endif
+
+#endif /* _SPARC64_BACKOFF_H */
diff --git a/include/asm-sparc64/bitops.h b/include/asm-sparc64/bitops.h
index 3d5e1af84723..982ce8992b91 100644
--- a/include/asm-sparc64/bitops.h
+++ b/include/asm-sparc64/bitops.h
@@ -7,6 +7,10 @@
#ifndef _SPARC64_BITOPS_H
#define _SPARC64_BITOPS_H
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
#include <linux/compiler.h>
#include <asm/byteorder.h>
@@ -81,6 +85,7 @@ static inline unsigned int hweight8(unsigned int w)
#include <asm-generic/bitops/hweight.h>
#endif
+#include <asm-generic/bitops/lock.h>
#endif /* __KERNEL__ */
#include <asm-generic/bitops/find.h>
diff --git a/include/asm-sparc64/byteorder.h b/include/asm-sparc64/byteorder.h
index c69b08af5fe0..3943022906fd 100644
--- a/include/asm-sparc64/byteorder.h
+++ b/include/asm-sparc64/byteorder.h
@@ -1,4 +1,3 @@
-/* $Id: byteorder.h,v 1.8 1997/12/18 02:44:14 ecd Exp $ */
#ifndef _SPARC64_BYTEORDER_H
#define _SPARC64_BYTEORDER_H
@@ -7,7 +6,7 @@
#ifdef __GNUC__
-static __inline__ __u16 ___arch__swab16p(const __u16 *addr)
+static inline __u16 ___arch__swab16p(const __u16 *addr)
{
__u16 ret;
@@ -17,7 +16,7 @@ static __inline__ __u16 ___arch__swab16p(const __u16 *addr)
return ret;
}
-static __inline__ __u32 ___arch__swab32p(const __u32 *addr)
+static inline __u32 ___arch__swab32p(const __u32 *addr)
{
__u32 ret;
@@ -27,7 +26,7 @@ static __inline__ __u32 ___arch__swab32p(const __u32 *addr)
return ret;
}
-static __inline__ __u64 ___arch__swab64p(const __u64 *addr)
+static inline __u64 ___arch__swab64p(const __u64 *addr)
{
__u64 ret;
diff --git a/include/asm-sparc64/floppy.h b/include/asm-sparc64/floppy.h
index 1783239c7b40..c47f58d6c15c 100644
--- a/include/asm-sparc64/floppy.h
+++ b/include/asm-sparc64/floppy.h
@@ -84,8 +84,6 @@ static struct sun_floppy_ops sun_fdops;
#define fd_free_irq() sun_fdops.fd_free_irq()
#define fd_eject(drive) sun_fdops.fd_eject(drive)
-static int FLOPPY_MOTOR_MASK = 0x10;
-
/* Super paranoid... */
#undef HAVE_DISABLE_HLT
@@ -622,7 +620,6 @@ isa_done:
sun_fdops.fd_eject = sun_pci_fd_eject;
fdc_status = (unsigned long) &sun_fdc->status_82077;
- FLOPPY_MOTOR_MASK = 0xf0;
allowed_drive_mask = 0;
sun_floppy_types[0] = 0;
@@ -729,7 +726,6 @@ static unsigned long __init sun_floppy_init(void)
sun_fdops.fd_eject = sun_pci_fd_eject;
fdc_status = (unsigned long) &sun_fdc->status_82077;
- FLOPPY_MOTOR_MASK = 0xf0;
/*
* XXX: Find out on which machines this is really needed.
diff --git a/include/asm-sparc64/fpumacro.h b/include/asm-sparc64/fpumacro.h
index d583e5efd75d..cc463fec806f 100644
--- a/include/asm-sparc64/fpumacro.h
+++ b/include/asm-sparc64/fpumacro.h
@@ -16,7 +16,7 @@ struct fpustate {
#define FPUSTATE (struct fpustate *)(current_thread_info()->fpregs)
-static __inline__ unsigned long fprs_read(void)
+static inline unsigned long fprs_read(void)
{
unsigned long retval;
@@ -25,7 +25,7 @@ static __inline__ unsigned long fprs_read(void)
return retval;
}
-static __inline__ void fprs_write(unsigned long val)
+static inline void fprs_write(unsigned long val)
{
__asm__ __volatile__("wr %0, 0x0, %%fprs" : : "r" (val));
}
diff --git a/include/asm-sparc64/futex.h b/include/asm-sparc64/futex.h
index 876312fe82cc..df1097d6ffbe 100644
--- a/include/asm-sparc64/futex.h
+++ b/include/asm-sparc64/futex.h
@@ -17,7 +17,8 @@
"3:\n" \
" .section .fixup,#alloc,#execinstr\n" \
" .align 4\n" \
- "4: ba 3b\n" \
+ "4: sethi %%hi(3b), %0\n" \
+ " jmpl %0 + %%lo(3b), %%g0\n" \
" mov %5, %0\n" \
" .previous\n" \
" .section __ex_table,\"a\"\n" \
@@ -91,7 +92,8 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
"2:\n"
" .section .fixup,#alloc,#execinstr\n"
" .align 4\n"
- "3: ba 2b\n"
+ "3: sethi %%hi(2b), %0\n"
+ " jmpl %0 + %%lo(2b), %%g0\n"
" mov %4, %0\n"
" .previous\n"
" .section __ex_table,\"a\"\n"
diff --git a/include/asm-sparc64/ide.h b/include/asm-sparc64/ide.h
index 55149cf933c2..ac7eb210b941 100644
--- a/include/asm-sparc64/ide.h
+++ b/include/asm-sparc64/ide.h
@@ -24,7 +24,6 @@
# endif
#endif
-#define IDE_ARCH_OBSOLETE_INIT
#define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */
#define __ide_insl(data_reg, buffer, wcount) \
diff --git a/include/asm-sparc64/io.h b/include/asm-sparc64/io.h
index 9565a892801e..c299b853b5ba 100644
--- a/include/asm-sparc64/io.h
+++ b/include/asm-sparc64/io.h
@@ -1,4 +1,3 @@
-/* $Id: io.h,v 1.47 2001/12/13 10:36:02 davem Exp $ */
#ifndef __SPARC64_IO_H
#define __SPARC64_IO_H
@@ -19,7 +18,7 @@ extern unsigned long kern_base, kern_size;
#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
#define BIO_VMERGE_BOUNDARY 8192
-static __inline__ u8 _inb(unsigned long addr)
+static inline u8 _inb(unsigned long addr)
{
u8 ret;
@@ -30,7 +29,7 @@ static __inline__ u8 _inb(unsigned long addr)
return ret;
}
-static __inline__ u16 _inw(unsigned long addr)
+static inline u16 _inw(unsigned long addr)
{
u16 ret;
@@ -41,7 +40,7 @@ static __inline__ u16 _inw(unsigned long addr)
return ret;
}
-static __inline__ u32 _inl(unsigned long addr)
+static inline u32 _inl(unsigned long addr)
{
u32 ret;
@@ -52,21 +51,21 @@ static __inline__ u32 _inl(unsigned long addr)
return ret;
}
-static __inline__ void _outb(u8 b, unsigned long addr)
+static inline void _outb(u8 b, unsigned long addr)
{
__asm__ __volatile__("stba\t%r0, [%1] %2\t/* pci_outb */"
: /* no outputs */
: "Jr" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
}
-static __inline__ void _outw(u16 w, unsigned long addr)
+static inline void _outw(u16 w, unsigned long addr)
{
__asm__ __volatile__("stha\t%r0, [%1] %2\t/* pci_outw */"
: /* no outputs */
: "Jr" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
}
-static __inline__ void _outl(u32 l, unsigned long addr)
+static inline void _outl(u32 l, unsigned long addr)
{
__asm__ __volatile__("stwa\t%r0, [%1] %2\t/* pci_outl */"
: /* no outputs */
@@ -205,7 +204,7 @@ static inline void _writeq(u64 q, volatile void __iomem *addr)
#define writeq(__q, __addr) _writeq(__q, __addr)
/* Now versions without byte-swapping. */
-static __inline__ u8 _raw_readb(unsigned long addr)
+static inline u8 _raw_readb(unsigned long addr)
{
u8 ret;
@@ -216,7 +215,7 @@ static __inline__ u8 _raw_readb(unsigned long addr)
return ret;
}
-static __inline__ u16 _raw_readw(unsigned long addr)
+static inline u16 _raw_readw(unsigned long addr)
{
u16 ret;
@@ -227,7 +226,7 @@ static __inline__ u16 _raw_readw(unsigned long addr)
return ret;
}
-static __inline__ u32 _raw_readl(unsigned long addr)
+static inline u32 _raw_readl(unsigned long addr)
{
u32 ret;
@@ -238,7 +237,7 @@ static __inline__ u32 _raw_readl(unsigned long addr)
return ret;
}
-static __inline__ u64 _raw_readq(unsigned long addr)
+static inline u64 _raw_readq(unsigned long addr)
{
u64 ret;
@@ -249,28 +248,28 @@ static __inline__ u64 _raw_readq(unsigned long addr)
return ret;
}
-static __inline__ void _raw_writeb(u8 b, unsigned long addr)
+static inline void _raw_writeb(u8 b, unsigned long addr)
{
__asm__ __volatile__("stba\t%r0, [%1] %2\t/* pci_raw_writeb */"
: /* no outputs */
: "Jr" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
}
-static __inline__ void _raw_writew(u16 w, unsigned long addr)
+static inline void _raw_writew(u16 w, unsigned long addr)
{
__asm__ __volatile__("stha\t%r0, [%1] %2\t/* pci_raw_writew */"
: /* no outputs */
: "Jr" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
}
-static __inline__ void _raw_writel(u32 l, unsigned long addr)
+static inline void _raw_writel(u32 l, unsigned long addr)
{
__asm__ __volatile__("stwa\t%r0, [%1] %2\t/* pci_raw_writel */"
: /* no outputs */
: "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
}
-static __inline__ void _raw_writeq(u64 q, unsigned long addr)
+static inline void _raw_writeq(u64 q, unsigned long addr)
{
__asm__ __volatile__("stxa\t%r0, [%1] %2\t/* pci_raw_writeq */"
: /* no outputs */
@@ -474,12 +473,6 @@ extern void pci_iounmap(struct pci_dev *dev, void __iomem *);
#define sbus_iounmap(__addr, __size) \
release_region((unsigned long)(__addr), (__size))
-/* Nothing to do */
-
-#define dma_cache_inv(_start,_size) do { } while (0)
-#define dma_cache_wback(_start,_size) do { } while (0)
-#define dma_cache_wback_inv(_start,_size) do { } while (0)
-
/*
* Convert a physical pointer to a virtual kernel pointer for /dev/mem
* access
diff --git a/include/asm-sparc64/ioctls.h b/include/asm-sparc64/ioctls.h
index 2223b6d0e5ed..083c9a0f37de 100644
--- a/include/asm-sparc64/ioctls.h
+++ b/include/asm-sparc64/ioctls.h
@@ -16,6 +16,10 @@
#define TCSETS _IOW('T', 9, struct termios)
#define TCSETSW _IOW('T', 10, struct termios)
#define TCSETSF _IOW('T', 11, struct termios)
+#define TCGETS2 _IOR('T', 12, struct termios2)
+#define TCSETS2 _IOW('T', 13, struct termios2)
+#define TCSETSW2 _IOW('T', 14, struct termios2)
+#define TCSETSF2 _IOW('T', 15, struct termios2)
/* Note that all the ioctls that are not available in Linux have a
* double underscore on the front to: a) avoid some programs to
diff --git a/include/asm-sparc64/ipc.h b/include/asm-sparc64/ipc.h
deleted file mode 100644
index a46e3d9c2a3f..000000000000
--- a/include/asm-sparc64/ipc.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ipc.h>
diff --git a/include/asm-sparc64/irq.h b/include/asm-sparc64/irq.h
index 182dba05c702..30cb76b47be1 100644
--- a/include/asm-sparc64/irq.h
+++ b/include/asm-sparc64/irq.h
@@ -1,7 +1,6 @@
-/* $Id: irq.h,v 1.21 2002/01/23 11:27:36 davem Exp $
- * irq.h: IRQ registers on the 64-bit Sparc.
+/* irq.h: IRQ registers on the 64-bit Sparc.
*
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
* Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz)
*/
@@ -67,21 +66,21 @@ extern void virt_irq_free(unsigned int virt_irq);
extern void fixup_irqs(void);
-static __inline__ void set_softint(unsigned long bits)
+static inline void set_softint(unsigned long bits)
{
__asm__ __volatile__("wr %0, 0x0, %%set_softint"
: /* No outputs */
: "r" (bits));
}
-static __inline__ void clear_softint(unsigned long bits)
+static inline void clear_softint(unsigned long bits)
{
__asm__ __volatile__("wr %0, 0x0, %%clear_softint"
: /* No outputs */
: "r" (bits));
}
-static __inline__ unsigned long get_softint(void)
+static inline unsigned long get_softint(void)
{
unsigned long retval;
diff --git a/include/asm-sparc64/kdebug.h b/include/asm-sparc64/kdebug.h
index 9974c7b0aebc..f905b773235a 100644
--- a/include/asm-sparc64/kdebug.h
+++ b/include/asm-sparc64/kdebug.h
@@ -1,26 +1,8 @@
#ifndef _SPARC64_KDEBUG_H
#define _SPARC64_KDEBUG_H
-/* Nearly identical to x86_64/i386 code. */
-
-#include <linux/notifier.h>
-
struct pt_regs;
-/*
- * These are only here because kprobes.c wants them to implement a
- * blatant layering violation. Will hopefully go away soon once all
- * architectures are updated.
- */
-static inline int register_page_fault_notifier(struct notifier_block *nb)
-{
- return 0;
-}
-static inline int unregister_page_fault_notifier(struct notifier_block *nb)
-{
- return 0;
-}
-
extern void bad_trap(struct pt_regs *, long);
/* Grossly misnamed. */
diff --git a/include/asm-sparc64/kprobes.h b/include/asm-sparc64/kprobes.h
index 7f6774dca5f4..5020eaf67c29 100644
--- a/include/asm-sparc64/kprobes.h
+++ b/include/asm-sparc64/kprobes.h
@@ -10,8 +10,9 @@ typedef u32 kprobe_opcode_t;
#define BREAKPOINT_INSTRUCTION_2 0x91d02071 /* ta 0x71 */
#define MAX_INSN_SIZE 2
+#define kretprobe_blacklist_size 0
+
#define arch_remove_kprobe(p) do {} while (0)
-#define ARCH_INACTIVE_KPROBE_COUNT 0
#define flush_insn_slot(p) \
do { flushi(&(p)->ainsn.insn[0]); \
diff --git a/include/asm-sparc64/mostek.h b/include/asm-sparc64/mostek.h
index d14dd8988161..c5652de2ace2 100644
--- a/include/asm-sparc64/mostek.h
+++ b/include/asm-sparc64/mostek.h
@@ -1,7 +1,6 @@
-/* $Id: mostek.h,v 1.4 2001/01/11 15:07:09 davem Exp $
- * mostek.h: Describes the various Mostek time of day clock registers.
+/* mostek.h: Describes the various Mostek time of day clock registers.
*
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1995 David S. Miller (davem@davemloft.net)
* Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu)
*/
@@ -38,7 +37,7 @@
*
* We now deal with physical addresses for I/O to the chip. -DaveM
*/
-static __inline__ u8 mostek_read(void __iomem *addr)
+static inline u8 mostek_read(void __iomem *addr)
{
u8 ret;
@@ -48,7 +47,7 @@ static __inline__ u8 mostek_read(void __iomem *addr)
return ret;
}
-static __inline__ void mostek_write(void __iomem *addr, u8 val)
+static inline void mostek_write(void __iomem *addr, u8 val)
{
__asm__ __volatile__("stba %0, [%1] %2"
: /* no outputs */
diff --git a/include/asm-sparc64/ns87303.h b/include/asm-sparc64/ns87303.h
index 6d58fdf349b5..686defe6aaa0 100644
--- a/include/asm-sparc64/ns87303.h
+++ b/include/asm-sparc64/ns87303.h
@@ -1,5 +1,4 @@
-/* $Id: ns87303.h,v 1.3 2000/01/09 15:16:34 ecd Exp $
- * ns87303.h: Configuration Register Description for the
+/* ns87303.h: Configuration Register Description for the
* National Semiconductor PC87303 (SuperIO).
*
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
@@ -85,7 +84,7 @@
extern spinlock_t ns87303_lock;
-static __inline__ int ns87303_modify(unsigned long port, unsigned int index,
+static inline int ns87303_modify(unsigned long port, unsigned int index,
unsigned char clr, unsigned char set)
{
static unsigned char reserved[] = {
diff --git a/include/asm-sparc64/of_platform.h b/include/asm-sparc64/of_platform.h
index f7c1f17c7d52..f15cfa723916 100644
--- a/include/asm-sparc64/of_platform.h
+++ b/include/asm-sparc64/of_platform.h
@@ -19,12 +19,9 @@
extern struct bus_type isa_bus_type;
extern struct bus_type ebus_bus_type;
extern struct bus_type sbus_bus_type;
-extern struct bus_type of_platform_bus_type;
+
#define of_bus_type of_platform_bus_type /* for compatibility */
-extern int of_register_driver(struct of_platform_driver *drv,
- struct bus_type *bus);
-extern void of_unregister_driver(struct of_platform_driver *drv);
extern struct of_device *of_platform_device_create(struct device_node *np,
const char *bus_id,
struct device *parent,
diff --git a/include/asm-sparc64/parport.h b/include/asm-sparc64/parport.h
index 8116e8f6062c..e9555b246c8d 100644
--- a/include/asm-sparc64/parport.h
+++ b/include/asm-sparc64/parport.h
@@ -1,5 +1,4 @@
-/* $Id: parport.h,v 1.11 2001/05/11 07:54:24 davem Exp $
- * parport.h: sparc64 specific parport initialization and dma.
+/* parport.h: sparc64 specific parport initialization and dma.
*
* Copyright (C) 1999 Eddie C. Dost (ecd@skynet.be)
*/
@@ -42,7 +41,7 @@ static struct sparc_ebus_info {
static DECLARE_BITMAP(dma_slot_map, PARPORT_PC_MAX_PORTS);
-static __inline__ int request_dma(unsigned int dmanr, const char *device_id)
+static inline int request_dma(unsigned int dmanr, const char *device_id)
{
if (dmanr >= PARPORT_PC_MAX_PORTS)
return -EINVAL;
@@ -51,7 +50,7 @@ static __inline__ int request_dma(unsigned int dmanr, const char *device_id)
return 0;
}
-static __inline__ void free_dma(unsigned int dmanr)
+static inline void free_dma(unsigned int dmanr)
{
if (dmanr >= PARPORT_PC_MAX_PORTS) {
printk(KERN_WARNING "Trying to free DMA%d\n", dmanr);
@@ -63,7 +62,7 @@ static __inline__ void free_dma(unsigned int dmanr)
}
}
-static __inline__ void enable_dma(unsigned int dmanr)
+static inline void enable_dma(unsigned int dmanr)
{
ebus_dma_enable(&sparc_ebus_dmas[dmanr].info, 1);
@@ -73,32 +72,32 @@ static __inline__ void enable_dma(unsigned int dmanr)
BUG();
}
-static __inline__ void disable_dma(unsigned int dmanr)
+static inline void disable_dma(unsigned int dmanr)
{
ebus_dma_enable(&sparc_ebus_dmas[dmanr].info, 0);
}
-static __inline__ void clear_dma_ff(unsigned int dmanr)
+static inline void clear_dma_ff(unsigned int dmanr)
{
/* nothing */
}
-static __inline__ void set_dma_mode(unsigned int dmanr, char mode)
+static inline void set_dma_mode(unsigned int dmanr, char mode)
{
ebus_dma_prepare(&sparc_ebus_dmas[dmanr].info, (mode != DMA_MODE_WRITE));
}
-static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int addr)
+static inline void set_dma_addr(unsigned int dmanr, unsigned int addr)
{
sparc_ebus_dmas[dmanr].addr = addr;
}
-static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)
+static inline void set_dma_count(unsigned int dmanr, unsigned int count)
{
sparc_ebus_dmas[dmanr].count = count;
}
-static __inline__ unsigned int get_dma_residue(unsigned int dmanr)
+static inline unsigned int get_dma_residue(unsigned int dmanr)
{
return ebus_dma_residue(&sparc_ebus_dmas[dmanr].info);
}
diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h
index 0393380d754a..3167ccff64f8 100644
--- a/include/asm-sparc64/pgtable.h
+++ b/include/asm-sparc64/pgtable.h
@@ -42,6 +42,9 @@
#define HI_OBP_ADDRESS _AC(0x0000000100000000,UL)
#define VMALLOC_START _AC(0x0000000100000000,UL)
#define VMALLOC_END _AC(0x0000000200000000,UL)
+#define VMEMMAP_BASE _AC(0x0000000200000000,UL)
+
+#define vmemmap ((struct page *)VMEMMAP_BASE)
/* XXX All of this needs to be rethought so we can take advantage
* XXX cheetah's full 64-bit virtual address space, ie. no more hole
diff --git a/include/asm-sparc64/posix_types.h b/include/asm-sparc64/posix_types.h
index c86b9452c683..3426a65ecd35 100644
--- a/include/asm-sparc64/posix_types.h
+++ b/include/asm-sparc64/posix_types.h
@@ -53,7 +53,7 @@ typedef struct {
#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
#undef __FD_SET
-static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
+static inline void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
{
unsigned long _tmp = fd / __NFDBITS;
unsigned long _rem = fd % __NFDBITS;
@@ -61,7 +61,7 @@ static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
}
#undef __FD_CLR
-static __inline__ void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
+static inline void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
{
unsigned long _tmp = fd / __NFDBITS;
unsigned long _rem = fd % __NFDBITS;
@@ -69,7 +69,7 @@ static __inline__ void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
}
#undef __FD_ISSET
-static __inline__ int __FD_ISSET(unsigned long fd, __const__ __kernel_fd_set *p)
+static inline int __FD_ISSET(unsigned long fd, __const__ __kernel_fd_set *p)
{
unsigned long _tmp = fd / __NFDBITS;
unsigned long _rem = fd % __NFDBITS;
@@ -81,7 +81,7 @@ static __inline__ int __FD_ISSET(unsigned long fd, __const__ __kernel_fd_set *p)
* for 256 and 1024-bit fd_sets respectively)
*/
#undef __FD_ZERO
-static __inline__ void __FD_ZERO(__kernel_fd_set *p)
+static inline void __FD_ZERO(__kernel_fd_set *p)
{
unsigned long *tmp = p->fds_bits;
int i;
diff --git a/include/asm-sparc64/sbus.h b/include/asm-sparc64/sbus.h
index 0151cad486f3..24a04a55cf85 100644
--- a/include/asm-sparc64/sbus.h
+++ b/include/asm-sparc64/sbus.h
@@ -29,12 +29,12 @@
* numbers + offsets, and vice versa.
*/
-static __inline__ unsigned long sbus_devaddr(int slotnum, unsigned long offset)
+static inline unsigned long sbus_devaddr(int slotnum, unsigned long offset)
{
return (unsigned long) (SUN_SBUS_BVADDR+((slotnum)<<28)+(offset));
}
-static __inline__ int sbus_dev_slot(unsigned long dev_addr)
+static inline int sbus_dev_slot(unsigned long dev_addr)
{
return (int) (((dev_addr)-SUN_SBUS_BVADDR)>>28);
}
diff --git a/include/asm-sparc64/scatterlist.h b/include/asm-sparc64/scatterlist.h
index 048fdb40e81d..6df23f070b1a 100644
--- a/include/asm-sparc64/scatterlist.h
+++ b/include/asm-sparc64/scatterlist.h
@@ -6,7 +6,10 @@
#include <asm/types.h>
struct scatterlist {
- struct page *page;
+#ifdef CONFIG_DEBUG_SG
+ unsigned long sg_magic;
+#endif
+ unsigned long page_link;
unsigned int offset;
unsigned int length;
@@ -20,4 +23,6 @@ struct scatterlist {
#define ISA_DMA_THRESHOLD (~0UL)
+#define ARCH_HAS_SG_CHAIN
+
#endif /* !(_SPARC64_SCATTERLIST_H) */
diff --git a/include/asm-sparc64/semaphore.h b/include/asm-sparc64/semaphore.h
index 093dcc6788db..7f7c0c4e024f 100644
--- a/include/asm-sparc64/semaphore.h
+++ b/include/asm-sparc64/semaphore.h
@@ -26,7 +26,6 @@ struct semaphore {
struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name, 1)
-#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name, 0)
static inline void sema_init (struct semaphore *sem, int val)
{
diff --git a/include/asm-sparc64/shmparam.h b/include/asm-sparc64/shmparam.h
index 911d0427de6d..8c66fded8a32 100644
--- a/include/asm-sparc64/shmparam.h
+++ b/include/asm-sparc64/shmparam.h
@@ -1,7 +1,6 @@
/* $Id: shmparam.h,v 1.5 2001/09/24 21:17:57 kanoj Exp $ */
#ifndef _ASMSPARC64_SHMPARAM_H
#define _ASMSPARC64_SHMPARAM_H
-#ifdef __KERNEL__
#include <asm/spitfire.h>
@@ -9,5 +8,4 @@
/* attach addr a multiple of this */
#define SHMLBA ((PAGE_SIZE > L1DCACHE_SIZE) ? PAGE_SIZE : L1DCACHE_SIZE)
-#endif /* __KERNEL__ */
#endif /* _ASMSPARC64_SHMPARAM_H */
diff --git a/include/asm-sparc64/smp.h b/include/asm-sparc64/smp.h
index e8a96a31761b..1c1c5ea5cea5 100644
--- a/include/asm-sparc64/smp.h
+++ b/include/asm-sparc64/smp.h
@@ -26,10 +26,11 @@
* Private routines/data
*/
-#include <asm/bitops.h>
+#include <linux/bitops.h>
#include <asm/atomic.h>
+#include <asm/percpu.h>
-extern cpumask_t cpu_sibling_map[NR_CPUS];
+DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
extern cpumask_t cpu_core_map[NR_CPUS];
extern int sparc64_multi_core;
diff --git a/include/asm-sparc64/spitfire.h b/include/asm-sparc64/spitfire.h
index cf7807813e85..63b7040e8134 100644
--- a/include/asm-sparc64/spitfire.h
+++ b/include/asm-sparc64/spitfire.h
@@ -1,7 +1,6 @@
-/* $Id: spitfire.h,v 1.18 2001/11/29 16:42:10 kanoj Exp $
- * spitfire.h: SpitFire/BlackBird/Cheetah inline MMU operations.
+/* spitfire.h: SpitFire/BlackBird/Cheetah inline MMU operations.
*
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
*/
#ifndef _SPARC64_SPITFIRE_H
@@ -67,7 +66,7 @@ extern void cheetah_enable_pcache(void);
/* The data cache is write through, so this just invalidates the
* specified line.
*/
-static __inline__ void spitfire_put_dcache_tag(unsigned long addr, unsigned long tag)
+static inline void spitfire_put_dcache_tag(unsigned long addr, unsigned long tag)
{
__asm__ __volatile__("stxa %0, [%1] %2\n\t"
"membar #Sync"
@@ -81,7 +80,7 @@ static __inline__ void spitfire_put_dcache_tag(unsigned long addr, unsigned long
* a flush instruction (to any address) is sufficient to handle
* this issue after the line is invalidated.
*/
-static __inline__ void spitfire_put_icache_tag(unsigned long addr, unsigned long tag)
+static inline void spitfire_put_icache_tag(unsigned long addr, unsigned long tag)
{
__asm__ __volatile__("stxa %0, [%1] %2\n\t"
"membar #Sync"
@@ -89,7 +88,7 @@ static __inline__ void spitfire_put_icache_tag(unsigned long addr, unsigned long
: "r" (tag), "r" (addr), "i" (ASI_IC_TAG));
}
-static __inline__ unsigned long spitfire_get_dtlb_data(int entry)
+static inline unsigned long spitfire_get_dtlb_data(int entry)
{
unsigned long data;
@@ -103,7 +102,7 @@ static __inline__ unsigned long spitfire_get_dtlb_data(int entry)
return data;
}
-static __inline__ unsigned long spitfire_get_dtlb_tag(int entry)
+static inline unsigned long spitfire_get_dtlb_tag(int entry)
{
unsigned long tag;
@@ -113,7 +112,7 @@ static __inline__ unsigned long spitfire_get_dtlb_tag(int entry)
return tag;
}
-static __inline__ void spitfire_put_dtlb_data(int entry, unsigned long data)
+static inline void spitfire_put_dtlb_data(int entry, unsigned long data)
{
__asm__ __volatile__("stxa %0, [%1] %2\n\t"
"membar #Sync"
@@ -122,7 +121,7 @@ static __inline__ void spitfire_put_dtlb_data(int entry, unsigned long data)
"i" (ASI_DTLB_DATA_ACCESS));
}
-static __inline__ unsigned long spitfire_get_itlb_data(int entry)
+static inline unsigned long spitfire_get_itlb_data(int entry)
{
unsigned long data;
@@ -136,7 +135,7 @@ static __inline__ unsigned long spitfire_get_itlb_data(int entry)
return data;
}
-static __inline__ unsigned long spitfire_get_itlb_tag(int entry)
+static inline unsigned long spitfire_get_itlb_tag(int entry)
{
unsigned long tag;
@@ -146,7 +145,7 @@ static __inline__ unsigned long spitfire_get_itlb_tag(int entry)
return tag;
}
-static __inline__ void spitfire_put_itlb_data(int entry, unsigned long data)
+static inline void spitfire_put_itlb_data(int entry, unsigned long data)
{
__asm__ __volatile__("stxa %0, [%1] %2\n\t"
"membar #Sync"
@@ -155,7 +154,7 @@ static __inline__ void spitfire_put_itlb_data(int entry, unsigned long data)
"i" (ASI_ITLB_DATA_ACCESS));
}
-static __inline__ void spitfire_flush_dtlb_nucleus_page(unsigned long page)
+static inline void spitfire_flush_dtlb_nucleus_page(unsigned long page)
{
__asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
"membar #Sync"
@@ -163,7 +162,7 @@ static __inline__ void spitfire_flush_dtlb_nucleus_page(unsigned long page)
: "r" (page | 0x20), "i" (ASI_DMMU_DEMAP));
}
-static __inline__ void spitfire_flush_itlb_nucleus_page(unsigned long page)
+static inline void spitfire_flush_itlb_nucleus_page(unsigned long page)
{
__asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
"membar #Sync"
@@ -172,7 +171,7 @@ static __inline__ void spitfire_flush_itlb_nucleus_page(unsigned long page)
}
/* Cheetah has "all non-locked" tlb flushes. */
-static __inline__ void cheetah_flush_dtlb_all(void)
+static inline void cheetah_flush_dtlb_all(void)
{
__asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
"membar #Sync"
@@ -180,7 +179,7 @@ static __inline__ void cheetah_flush_dtlb_all(void)
: "r" (0x80), "i" (ASI_DMMU_DEMAP));
}
-static __inline__ void cheetah_flush_itlb_all(void)
+static inline void cheetah_flush_itlb_all(void)
{
__asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
"membar #Sync"
@@ -202,7 +201,7 @@ static __inline__ void cheetah_flush_itlb_all(void)
* ASI_{D,I}TLB_DATA_ACCESS loads, doing the load twice fixes
* the problem for me. -DaveM
*/
-static __inline__ unsigned long cheetah_get_ldtlb_data(int entry)
+static inline unsigned long cheetah_get_ldtlb_data(int entry)
{
unsigned long data;
@@ -215,7 +214,7 @@ static __inline__ unsigned long cheetah_get_ldtlb_data(int entry)
return data;
}
-static __inline__ unsigned long cheetah_get_litlb_data(int entry)
+static inline unsigned long cheetah_get_litlb_data(int entry)
{
unsigned long data;
@@ -228,7 +227,7 @@ static __inline__ unsigned long cheetah_get_litlb_data(int entry)
return data;
}
-static __inline__ unsigned long cheetah_get_ldtlb_tag(int entry)
+static inline unsigned long cheetah_get_ldtlb_tag(int entry)
{
unsigned long tag;
@@ -240,7 +239,7 @@ static __inline__ unsigned long cheetah_get_ldtlb_tag(int entry)
return tag;
}
-static __inline__ unsigned long cheetah_get_litlb_tag(int entry)
+static inline unsigned long cheetah_get_litlb_tag(int entry)
{
unsigned long tag;
@@ -252,7 +251,7 @@ static __inline__ unsigned long cheetah_get_litlb_tag(int entry)
return tag;
}
-static __inline__ void cheetah_put_ldtlb_data(int entry, unsigned long data)
+static inline void cheetah_put_ldtlb_data(int entry, unsigned long data)
{
__asm__ __volatile__("stxa %0, [%1] %2\n\t"
"membar #Sync"
@@ -262,7 +261,7 @@ static __inline__ void cheetah_put_ldtlb_data(int entry, unsigned long data)
"i" (ASI_DTLB_DATA_ACCESS));
}
-static __inline__ void cheetah_put_litlb_data(int entry, unsigned long data)
+static inline void cheetah_put_litlb_data(int entry, unsigned long data)
{
__asm__ __volatile__("stxa %0, [%1] %2\n\t"
"membar #Sync"
@@ -272,7 +271,7 @@ static __inline__ void cheetah_put_litlb_data(int entry, unsigned long data)
"i" (ASI_ITLB_DATA_ACCESS));
}
-static __inline__ unsigned long cheetah_get_dtlb_data(int entry, int tlb)
+static inline unsigned long cheetah_get_dtlb_data(int entry, int tlb)
{
unsigned long data;
@@ -284,7 +283,7 @@ static __inline__ unsigned long cheetah_get_dtlb_data(int entry, int tlb)
return data;
}
-static __inline__ unsigned long cheetah_get_dtlb_tag(int entry, int tlb)
+static inline unsigned long cheetah_get_dtlb_tag(int entry, int tlb)
{
unsigned long tag;
@@ -294,7 +293,7 @@ static __inline__ unsigned long cheetah_get_dtlb_tag(int entry, int tlb)
return tag;
}
-static __inline__ void cheetah_put_dtlb_data(int entry, unsigned long data, int tlb)
+static inline void cheetah_put_dtlb_data(int entry, unsigned long data, int tlb)
{
__asm__ __volatile__("stxa %0, [%1] %2\n\t"
"membar #Sync"
@@ -304,7 +303,7 @@ static __inline__ void cheetah_put_dtlb_data(int entry, unsigned long data, int
"i" (ASI_DTLB_DATA_ACCESS));
}
-static __inline__ unsigned long cheetah_get_itlb_data(int entry)
+static inline unsigned long cheetah_get_itlb_data(int entry)
{
unsigned long data;
@@ -317,7 +316,7 @@ static __inline__ unsigned long cheetah_get_itlb_data(int entry)
return data;
}
-static __inline__ unsigned long cheetah_get_itlb_tag(int entry)
+static inline unsigned long cheetah_get_itlb_tag(int entry)
{
unsigned long tag;
@@ -327,7 +326,7 @@ static __inline__ unsigned long cheetah_get_itlb_tag(int entry)
return tag;
}
-static __inline__ void cheetah_put_itlb_data(int entry, unsigned long data)
+static inline void cheetah_put_itlb_data(int entry, unsigned long data)
{
__asm__ __volatile__("stxa %0, [%1] %2\n\t"
"membar #Sync"
diff --git a/include/asm-sparc64/system.h b/include/asm-sparc64/system.h
index 3f175fa7e6d2..99a669c190c7 100644
--- a/include/asm-sparc64/system.h
+++ b/include/asm-sparc64/system.h
@@ -1,4 +1,3 @@
-/* $Id: system.h,v 1.69 2002/02/09 19:49:31 davem Exp $ */
#ifndef __SPARC64_SYSTEM_H
#define __SPARC64_SYSTEM_H
@@ -179,7 +178,9 @@ do { if (test_thread_flag(TIF_PERFCTR)) { \
"ldx [%%g6 + %9], %%g4\n\t" \
"brz,pt %%o7, 1f\n\t" \
" mov %%g7, %0\n\t" \
- "b,a ret_from_syscall\n\t" \
+ "sethi %%hi(ret_from_syscall), %%g1\n\t" \
+ "jmpl %%g1 + %%lo(ret_from_syscall), %%g0\n\t" \
+ " nop\n\t" \
"1:\n\t" \
: "=&r" (last), "=r" (current), "=r" (current_thread_info_reg), \
"=r" (__local_per_cpu_offset) \
@@ -240,7 +241,7 @@ static inline unsigned long xchg64(__volatile__ unsigned long *m, unsigned long
extern void __xchg_called_with_bad_pointer(void);
-static __inline__ unsigned long __xchg(unsigned long x, __volatile__ void * ptr,
+static inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr,
int size)
{
switch (size) {
@@ -263,7 +264,7 @@ extern void die_if_kernel(char *str, struct pt_regs *regs) __attribute__ ((noret
#define __HAVE_ARCH_CMPXCHG 1
-static __inline__ unsigned long
+static inline unsigned long
__cmpxchg_u32(volatile int *m, int old, int new)
{
__asm__ __volatile__("membar #StoreLoad | #LoadLoad\n"
@@ -276,7 +277,7 @@ __cmpxchg_u32(volatile int *m, int old, int new)
return new;
}
-static __inline__ unsigned long
+static inline unsigned long
__cmpxchg_u64(volatile long *m, unsigned long old, unsigned long new)
{
__asm__ __volatile__("membar #StoreLoad | #LoadLoad\n"
@@ -293,7 +294,7 @@ __cmpxchg_u64(volatile long *m, unsigned long old, unsigned long new)
if something tries to do an invalid cmpxchg(). */
extern void __cmpxchg_called_with_bad_pointer(void);
-static __inline__ unsigned long
+static inline unsigned long
__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
{
switch (size) {
diff --git a/include/asm-sparc64/termbits.h b/include/asm-sparc64/termbits.h
index 705cd44b4173..ebe31c152f16 100644
--- a/include/asm-sparc64/termbits.h
+++ b/include/asm-sparc64/termbits.h
@@ -5,8 +5,6 @@
typedef unsigned char cc_t;
typedef unsigned int speed_t;
-
-/* XXX is this right for sparc64? it was an unsigned long... XXX */
typedef unsigned int tcflag_t;
#define NCC 8
@@ -33,6 +31,18 @@ struct termios {
#endif
};
+struct termios2 {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[NCCS]; /* control characters */
+ cc_t _x_cc[2]; /* padding to match ktermios */
+ speed_t c_ispeed; /* input speed */
+ speed_t c_ospeed; /* output speed */
+};
+
struct ktermios {
tcflag_t c_iflag; /* input mode flags */
tcflag_t c_oflag; /* output mode flags */
@@ -161,6 +171,7 @@ struct ktermios {
#define HUPCL 0x00000400
#define CLOCAL 0x00000800
#define CBAUDEX 0x00001000
+#define BOTHER 0x00001000
#define B57600 0x00001001
#define B115200 0x00001002
#define B230400 0x00001003
@@ -190,6 +201,8 @@ struct ktermios {
#define CMSPAR 0x40000000 /* mark or space (stick) parity */
#define CRTSCTS 0x80000000 /* flow control */
+#define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */
+
/* c_lflag bits */
#define ISIG 0x00000001
#define ICANON 0x00000002
diff --git a/include/asm-sparc64/termios.h b/include/asm-sparc64/termios.h
index f05d390993d5..ef527211f8a8 100644
--- a/include/asm-sparc64/termios.h
+++ b/include/asm-sparc64/termios.h
@@ -123,6 +123,8 @@ struct winsize {
err |= get_user((k)->c_cc[VMIN], &(u)->c_cc[_VMIN]); \
err |= get_user((k)->c_cc[VTIME], &(u)->c_cc[_VTIME]); \
} \
+ err |= get_user((k)->c_ispeed, &(u)->c_ispeed); \
+ err |= get_user((k)->c_ospeed, &(u)->c_ospeed); \
err; \
})
@@ -142,6 +144,46 @@ struct winsize {
err |= put_user((k)->c_cc[VEOF], &(u)->c_cc[VEOF]); \
err |= put_user((k)->c_cc[VEOL], &(u)->c_cc[VEOL]); \
} \
+ err |= put_user((k)->c_ispeed, &(u)->c_ispeed); \
+ err |= put_user((k)->c_ospeed, &(u)->c_ospeed); \
+ err; \
+})
+
+#define user_termios_to_kernel_termios_1(k, u) \
+({ \
+ int err; \
+ err = get_user((k)->c_iflag, &(u)->c_iflag); \
+ err |= get_user((k)->c_oflag, &(u)->c_oflag); \
+ err |= get_user((k)->c_cflag, &(u)->c_cflag); \
+ err |= get_user((k)->c_lflag, &(u)->c_lflag); \
+ err |= get_user((k)->c_line, &(u)->c_line); \
+ err |= copy_from_user((k)->c_cc, (u)->c_cc, NCCS); \
+ if((k)->c_lflag & ICANON) { \
+ err |= get_user((k)->c_cc[VEOF], &(u)->c_cc[VEOF]); \
+ err |= get_user((k)->c_cc[VEOL], &(u)->c_cc[VEOL]); \
+ } else { \
+ err |= get_user((k)->c_cc[VMIN], &(u)->c_cc[_VMIN]); \
+ err |= get_user((k)->c_cc[VTIME], &(u)->c_cc[_VTIME]); \
+ } \
+ err; \
+})
+
+#define kernel_termios_to_user_termios_1(u, k) \
+({ \
+ int err; \
+ err = put_user((k)->c_iflag, &(u)->c_iflag); \
+ err |= put_user((k)->c_oflag, &(u)->c_oflag); \
+ err |= put_user((k)->c_cflag, &(u)->c_cflag); \
+ err |= put_user((k)->c_lflag, &(u)->c_lflag); \
+ err |= put_user((k)->c_line, &(u)->c_line); \
+ err |= copy_to_user((u)->c_cc, (k)->c_cc, NCCS); \
+ if(!((k)->c_lflag & ICANON)) { \
+ err |= put_user((k)->c_cc[VMIN], &(u)->c_cc[_VMIN]); \
+ err |= put_user((k)->c_cc[VTIME], &(u)->c_cc[_VTIME]); \
+ } else { \
+ err |= put_user((k)->c_cc[VEOF], &(u)->c_cc[VEOF]); \
+ err |= put_user((k)->c_cc[VEOL], &(u)->c_cc[VEOL]); \
+ } \
err; \
})
diff --git a/include/asm-sparc64/tlbflush.h b/include/asm-sparc64/tlbflush.h
index 3487328570ed..fbb675dbe0c9 100644
--- a/include/asm-sparc64/tlbflush.h
+++ b/include/asm-sparc64/tlbflush.h
@@ -41,11 +41,4 @@ do { flush_tsb_kernel_range(start,end); \
#endif /* ! CONFIG_SMP */
-static inline void flush_tlb_pgtables(struct mm_struct *mm, unsigned long start, unsigned long end)
-{
- /* We don't use virtual page tables for TLB miss processing
- * any more. Nowadays we use the TSB.
- */
-}
-
#endif /* _SPARC64_TLBFLUSH_H */
diff --git a/include/asm-sparc64/topology.h b/include/asm-sparc64/topology.h
index 290ac75f385b..c6b557034f68 100644
--- a/include/asm-sparc64/topology.h
+++ b/include/asm-sparc64/topology.h
@@ -5,7 +5,7 @@
#define topology_physical_package_id(cpu) (cpu_data(cpu).proc_id)
#define topology_core_id(cpu) (cpu_data(cpu).core_id)
#define topology_core_siblings(cpu) (cpu_core_map[cpu])
-#define topology_thread_siblings(cpu) (cpu_sibling_map[cpu])
+#define topology_thread_siblings(cpu) (per_cpu(cpu_sibling_map, cpu))
#define mc_capable() (sparc64_multi_core)
#define smt_capable() (sparc64_multi_core)
#endif /* CONFIG_SMP */
diff --git a/include/asm-sparc64/uaccess.h b/include/asm-sparc64/uaccess.h
index afe236ba555b..93720e7b0289 100644
--- a/include/asm-sparc64/uaccess.h
+++ b/include/asm-sparc64/uaccess.h
@@ -123,7 +123,8 @@ __asm__ __volatile__( \
".section .fixup,#alloc,#execinstr\n\t" \
".align 4\n" \
"3:\n\t" \
- "b 2b\n\t" \
+ "sethi %%hi(2b), %0\n\t" \
+ "jmpl %0 + %%lo(2b), %%g0\n\t" \
" mov %3, %0\n\n\t" \
".previous\n\t" \
".section __ex_table,\"a\"\n\t" \
@@ -165,8 +166,9 @@ __asm__ __volatile__( \
".section .fixup,#alloc,#execinstr\n\t" \
".align 4\n" \
"3:\n\t" \
+ "sethi %%hi(2b), %0\n\t" \
"clr %1\n\t" \
- "b 2b\n\t" \
+ "jmpl %0 + %%lo(2b), %%g0\n\t" \
" mov %3, %0\n\n\t" \
".previous\n\t" \
".section __ex_table,\"a\"\n\t" \
diff --git a/include/asm-sparc64/upa.h b/include/asm-sparc64/upa.h
index 7ae09a22e408..5b1633223f92 100644
--- a/include/asm-sparc64/upa.h
+++ b/include/asm-sparc64/upa.h
@@ -1,4 +1,3 @@
-/* $Id: upa.h,v 1.3 1999/09/21 14:39:47 davem Exp $ */
#ifndef _SPARC64_UPA_H
#define _SPARC64_UPA_H
@@ -25,7 +24,7 @@
/* UPA I/O space accessors */
#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
-static __inline__ unsigned char _upa_readb(unsigned long addr)
+static inline unsigned char _upa_readb(unsigned long addr)
{
unsigned char ret;
@@ -36,7 +35,7 @@ static __inline__ unsigned char _upa_readb(unsigned long addr)
return ret;
}
-static __inline__ unsigned short _upa_readw(unsigned long addr)
+static inline unsigned short _upa_readw(unsigned long addr)
{
unsigned short ret;
@@ -47,7 +46,7 @@ static __inline__ unsigned short _upa_readw(unsigned long addr)
return ret;
}
-static __inline__ unsigned int _upa_readl(unsigned long addr)
+static inline unsigned int _upa_readl(unsigned long addr)
{
unsigned int ret;
@@ -58,7 +57,7 @@ static __inline__ unsigned int _upa_readl(unsigned long addr)
return ret;
}
-static __inline__ unsigned long _upa_readq(unsigned long addr)
+static inline unsigned long _upa_readq(unsigned long addr)
{
unsigned long ret;
@@ -69,28 +68,28 @@ static __inline__ unsigned long _upa_readq(unsigned long addr)
return ret;
}
-static __inline__ void _upa_writeb(unsigned char b, unsigned long addr)
+static inline void _upa_writeb(unsigned char b, unsigned long addr)
{
__asm__ __volatile__("stba\t%0, [%1] %2\t/* upa_writeb */"
: /* no outputs */
: "r" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
}
-static __inline__ void _upa_writew(unsigned short w, unsigned long addr)
+static inline void _upa_writew(unsigned short w, unsigned long addr)
{
__asm__ __volatile__("stha\t%0, [%1] %2\t/* upa_writew */"
: /* no outputs */
: "r" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
}
-static __inline__ void _upa_writel(unsigned int l, unsigned long addr)
+static inline void _upa_writel(unsigned int l, unsigned long addr)
{
__asm__ __volatile__("stwa\t%0, [%1] %2\t/* upa_writel */"
: /* no outputs */
: "r" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
}
-static __inline__ void _upa_writeq(unsigned long q, unsigned long addr)
+static inline void _upa_writeq(unsigned long q, unsigned long addr)
{
__asm__ __volatile__("stxa\t%0, [%1] %2\t/* upa_writeq */"
: /* no outputs */
diff --git a/include/asm-sparc64/vio.h b/include/asm-sparc64/vio.h
index f7417e91b170..d4de32f0f8af 100644
--- a/include/asm-sparc64/vio.h
+++ b/include/asm-sparc64/vio.h
@@ -8,6 +8,7 @@
#include <linux/spinlock.h>
#include <linux/completion.h>
#include <linux/list.h>
+#include <linux/log2.h>
#include <asm/ldc.h>
#include <asm/mdesc.h>
@@ -257,8 +258,7 @@ static inline void *vio_dring_entry(struct vio_dring_state *dr,
static inline u32 vio_dring_avail(struct vio_dring_state *dr,
unsigned int ring_size)
{
- /* Ensure build-time power-of-2. */
- BUILD_BUG_ON(ring_size & (ring_size - 1));
+ BUILD_BUG_ON(!is_power_of_2(ring_size));
return (dr->pending -
((dr->prod - dr->cons) & (ring_size - 1)));
diff --git a/include/asm-sparc64/visasm.h b/include/asm-sparc64/visasm.h
index a74078551e0f..34f2ec64933b 100644
--- a/include/asm-sparc64/visasm.h
+++ b/include/asm-sparc64/visasm.h
@@ -1,4 +1,3 @@
-/* $Id: visasm.h,v 1.5 2001/04/24 01:09:12 davem Exp $ */
#ifndef _SPARC64_VISASM_H
#define _SPARC64_VISASM_H
@@ -44,7 +43,7 @@
wr %o5, 0, %fprs;
#ifndef __ASSEMBLY__
-static __inline__ void save_and_clear_fpu(void) {
+static inline void save_and_clear_fpu(void) {
__asm__ __volatile__ (
" rd %%fprs, %%o5\n"
" andcc %%o5, %0, %%g0\n"
diff --git a/include/asm-um/a.out.h b/include/asm-um/a.out.h
index 78bc9eed26b2..9281dd8eb334 100644
--- a/include/asm-um/a.out.h
+++ b/include/asm-um/a.out.h
@@ -1,8 +1,12 @@
+/*
+ * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
#ifndef __UM_A_OUT_H
#define __UM_A_OUT_H
#include "asm/arch/a.out.h"
-#include "choose-mode.h"
#undef STACK_TOP
#undef STACK_TOP_MAX
@@ -13,10 +17,8 @@ extern unsigned long host_task_size;
#define STACK_ROOM (stacksizelim)
-extern int honeypot;
-#define STACK_TOP \
- CHOOSE_MODE((honeypot ? host_task_size : task_size), task_size)
+#define STACK_TOP task_size
-#define STACK_TOP_MAX STACK_TOP
+#define STACK_TOP_MAX STACK_TOP
#endif
diff --git a/include/asm-um/alternative-asm.i b/include/asm-um/alternative-asm.h
index cae9faca132f..9aa9fa2402a4 100644
--- a/include/asm-um/alternative-asm.i
+++ b/include/asm-um/alternative-asm.h
@@ -1,6 +1,6 @@
#ifndef __UM_ALTERNATIVE_ASM_I
#define __UM_ALTERNATIVE_ASM_I
-#include "asm/arch/alternative-asm.i"
+#include "asm/arch/alternative-asm.h"
#endif
diff --git a/include/asm-um/bitops.h b/include/asm-um/bitops.h
index 46d781953d3a..e4d38d437b97 100644
--- a/include/asm-um/bitops.h
+++ b/include/asm-um/bitops.h
@@ -1,6 +1,10 @@
#ifndef __UM_BITOPS_H
#define __UM_BITOPS_H
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
#include "asm/arch/bitops.h"
#endif
diff --git a/include/asm-um/elf-i386.h b/include/asm-um/elf-i386.h
index 9bab712dc5c0..ca94a136dfe8 100644
--- a/include/asm-um/elf-i386.h
+++ b/include/asm-um/elf-i386.h
@@ -5,7 +5,8 @@
#ifndef __UM_ELF_I386_H
#define __UM_ELF_I386_H
-#include <asm/user.h>
+#include <linux/sched.h>
+#include "skas.h"
#define R_386_NONE 0
#define R_386_32 1
@@ -75,6 +76,15 @@ typedef struct user_i387_struct elf_fpregset_t;
pr_reg[16] = PT_REGS_SS(regs); \
} while(0);
+static inline int elf_core_copy_fpregs(struct task_struct *t,
+ elf_fpregset_t *fpu)
+{
+ int cpu = ((struct thread_info *) t->stack)->cpu;
+ return save_fp_registers(userspace_pid[cpu], (unsigned long *) fpu);
+}
+
+#define ELF_CORE_COPY_FPREGS(t, fpu) elf_core_copy_fpregs(t, fpu)
+
extern long elf_aux_hwcap;
#define ELF_HWCAP (elf_aux_hwcap)
diff --git a/include/asm-um/elf-x86_64.h b/include/asm-um/elf-x86_64.h
index 857471c49dac..3c9d543eb61e 100644
--- a/include/asm-um/elf-x86_64.h
+++ b/include/asm-um/elf-x86_64.h
@@ -1,5 +1,6 @@
/*
* Copyright 2003 PathScale, Inc.
+ * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
*
* Licensed under the GPL
*/
@@ -36,7 +37,7 @@ typedef unsigned long elf_greg_t;
#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t))
typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-typedef struct { } elf_fpregset_t;
+typedef struct user_i387_struct elf_fpregset_t;
/*
* This is used to ensure we don't load something for the wrong architecture.
@@ -67,27 +68,27 @@ typedef struct { } elf_fpregset_t;
} while (0)
#define ELF_CORE_COPY_REGS(pr_reg, regs) \
- (pr_reg)[0] = (regs)->regs.skas.regs[0]; \
- (pr_reg)[1] = (regs)->regs.skas.regs[1]; \
- (pr_reg)[2] = (regs)->regs.skas.regs[2]; \
- (pr_reg)[3] = (regs)->regs.skas.regs[3]; \
- (pr_reg)[4] = (regs)->regs.skas.regs[4]; \
- (pr_reg)[5] = (regs)->regs.skas.regs[5]; \
- (pr_reg)[6] = (regs)->regs.skas.regs[6]; \
- (pr_reg)[7] = (regs)->regs.skas.regs[7]; \
- (pr_reg)[8] = (regs)->regs.skas.regs[8]; \
- (pr_reg)[9] = (regs)->regs.skas.regs[9]; \
- (pr_reg)[10] = (regs)->regs.skas.regs[10]; \
- (pr_reg)[11] = (regs)->regs.skas.regs[11]; \
- (pr_reg)[12] = (regs)->regs.skas.regs[12]; \
- (pr_reg)[13] = (regs)->regs.skas.regs[13]; \
- (pr_reg)[14] = (regs)->regs.skas.regs[14]; \
- (pr_reg)[15] = (regs)->regs.skas.regs[15]; \
- (pr_reg)[16] = (regs)->regs.skas.regs[16]; \
- (pr_reg)[17] = (regs)->regs.skas.regs[17]; \
- (pr_reg)[18] = (regs)->regs.skas.regs[18]; \
- (pr_reg)[19] = (regs)->regs.skas.regs[19]; \
- (pr_reg)[20] = (regs)->regs.skas.regs[20]; \
+ (pr_reg)[0] = (regs)->regs.gp[0]; \
+ (pr_reg)[1] = (regs)->regs.gp[1]; \
+ (pr_reg)[2] = (regs)->regs.gp[2]; \
+ (pr_reg)[3] = (regs)->regs.gp[3]; \
+ (pr_reg)[4] = (regs)->regs.gp[4]; \
+ (pr_reg)[5] = (regs)->regs.gp[5]; \
+ (pr_reg)[6] = (regs)->regs.gp[6]; \
+ (pr_reg)[7] = (regs)->regs.gp[7]; \
+ (pr_reg)[8] = (regs)->regs.gp[8]; \
+ (pr_reg)[9] = (regs)->regs.gp[9]; \
+ (pr_reg)[10] = (regs)->regs.gp[10]; \
+ (pr_reg)[11] = (regs)->regs.gp[11]; \
+ (pr_reg)[12] = (regs)->regs.gp[12]; \
+ (pr_reg)[13] = (regs)->regs.gp[13]; \
+ (pr_reg)[14] = (regs)->regs.gp[14]; \
+ (pr_reg)[15] = (regs)->regs.gp[15]; \
+ (pr_reg)[16] = (regs)->regs.gp[16]; \
+ (pr_reg)[17] = (regs)->regs.gp[17]; \
+ (pr_reg)[18] = (regs)->regs.gp[18]; \
+ (pr_reg)[19] = (regs)->regs.gp[19]; \
+ (pr_reg)[20] = (regs)->regs.gp[20]; \
(pr_reg)[21] = current->thread.arch.fs; \
(pr_reg)[22] = 0; \
(pr_reg)[23] = 0; \
@@ -122,14 +123,3 @@ extern long elf_aux_hwcap;
#define SET_PERSONALITY(ex, ibcs2) do ; while(0)
#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/include/asm-um/frame.i b/include/asm-um/frame.h
index 09d5dca5d928..8a8c1cb415b4 100644
--- a/include/asm-um/frame.i
+++ b/include/asm-um/frame.h
@@ -1,6 +1,6 @@
#ifndef __UM_FRAME_I
#define __UM_FRAME_I
-#include "asm/arch/frame.i"
+#include "asm/arch/frame.h"
#endif
diff --git a/include/asm-um/ipc.h b/include/asm-um/ipc.h
deleted file mode 100644
index a46e3d9c2a3f..000000000000
--- a/include/asm-um/ipc.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ipc.h>
diff --git a/include/asm-um/ldt.h b/include/asm-um/ldt.h
index 96f82a456ce6..b2553f3e87eb 100644
--- a/include/asm-um/ldt.h
+++ b/include/asm-um/ldt.h
@@ -11,11 +11,7 @@
#include "asm/semaphore.h"
#include "asm/host_ldt.h"
-struct mmu_context_skas;
extern void ldt_host_info(void);
-extern long init_new_ldt(struct mmu_context_skas * to_mm,
- struct mmu_context_skas * from_mm);
-extern void free_ldt(struct mmu_context_skas * mm);
#define LDT_PAGES_MAX \
((LDT_ENTRIES * LDT_ENTRY_SIZE)/PAGE_SIZE)
diff --git a/include/asm-um/mmu_context.h b/include/asm-um/mmu_context.h
index 9aa4b44e8cc1..5f3b863aef9a 100644
--- a/include/asm-um/mmu_context.h
+++ b/include/asm-um/mmu_context.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -9,7 +9,6 @@
#include <asm-generic/mm_hooks.h>
#include "linux/sched.h"
-#include "choose-mode.h"
#include "um_mmu.h"
#define get_mmu_context(task) do ; while(0)
@@ -30,8 +29,7 @@ static inline void activate_mm(struct mm_struct *old, struct mm_struct *new)
* possible.
*/
if (old != new && (current->flags & PF_BORROWED_MM))
- CHOOSE_MODE(force_flush_all(),
- switch_mm_skas(&new->context.skas.id));
+ __switch_mm(&new->context.id);
}
static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
@@ -43,8 +41,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
cpu_clear(cpu, prev->cpu_vm_mask);
cpu_set(cpu, next->cpu_vm_mask);
if(next != &init_mm)
- CHOOSE_MODE((void) 0,
- switch_mm_skas(&next->context.skas.id));
+ __switch_mm(&next->context.id);
}
}
@@ -53,38 +50,8 @@ static inline void enter_lazy_tlb(struct mm_struct *mm,
{
}
-extern int init_new_context_skas(struct task_struct *task,
- struct mm_struct *mm);
+extern int init_new_context(struct task_struct *task, struct mm_struct *mm);
-static inline int init_new_context_tt(struct task_struct *task,
- struct mm_struct *mm)
-{
- return(0);
-}
-
-static inline int init_new_context(struct task_struct *task,
- struct mm_struct *mm)
-{
- return(CHOOSE_MODE_PROC(init_new_context_tt, init_new_context_skas,
- task, mm));
-}
-
-extern void destroy_context_skas(struct mm_struct *mm);
-
-static inline void destroy_context(struct mm_struct *mm)
-{
- CHOOSE_MODE((void) 0, destroy_context_skas(mm));
-}
+extern void destroy_context(struct mm_struct *mm);
#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/include/asm-um/page.h b/include/asm-um/page.h
index 8e310d81e5b4..4b424c75fca5 100644
--- a/include/asm-um/page.h
+++ b/include/asm-um/page.h
@@ -9,6 +9,7 @@
struct page;
+#include <linux/types.h>
#include <asm/vm-flags.h>
/* PAGE_SHIFT determines the page size */
diff --git a/include/asm-um/pgalloc.h b/include/asm-um/pgalloc.h
index 34ab268ef40e..14904876e8fb 100644
--- a/include/asm-um/pgalloc.h
+++ b/include/asm-um/pgalloc.h
@@ -42,7 +42,7 @@ static inline void pte_free(struct page *pte)
#ifdef CONFIG_3_LEVEL_PGTABLES
-extern __inline__ void pmd_free(pmd_t *pmd)
+static inline void pmd_free(pmd_t *pmd)
{
free_page((unsigned long)pmd);
}
diff --git a/include/asm-um/pgtable-3level.h b/include/asm-um/pgtable-3level.h
index ca0c2a92a112..3ebafbaacb24 100644
--- a/include/asm-um/pgtable-3level.h
+++ b/include/asm-um/pgtable-3level.h
@@ -69,9 +69,9 @@ static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
return pmd;
}
-extern inline void pud_clear (pud_t *pud)
+static inline void pud_clear (pud_t *pud)
{
- set_pud(pud, __pud(0));
+ set_pud(pud, __pud(_PAGE_NEWPAGE));
}
#define pud_page(pud) phys_to_page(pud_val(pud) & PAGE_MASK)
diff --git a/include/asm-um/processor-generic.h b/include/asm-um/processor-generic.h
index d99bbddffdb9..78c0599cc80c 100644
--- a/include/asm-um/processor-generic.h
+++ b/include/asm-um/processor-generic.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -11,44 +11,32 @@ struct pt_regs;
struct task_struct;
#include "asm/ptrace.h"
-#include "choose-mode.h"
#include "registers.h"
#include "sysdep/archsetjmp.h"
struct mm_struct;
struct thread_struct {
- /* This flag is set to 1 before calling do_fork (and analyzed in
+ struct task_struct *saved_task;
+ /*
+ * This flag is set to 1 before calling do_fork (and analyzed in
* copy_thread) to mark that we are begin called from userspace (fork /
* vfork / clone), and reset to 0 after. It is left to 0 when called
- * from kernelspace (i.e. kernel_thread() or fork_idle(), as of 2.6.11). */
- struct task_struct *saved_task;
+ * from kernelspace (i.e. kernel_thread() or fork_idle(),
+ * as of 2.6.11).
+ */
int forking;
int nsyscalls;
struct pt_regs regs;
int singlestep_syscall;
void *fault_addr;
- void *fault_catcher;
+ jmp_buf *fault_catcher;
struct task_struct *prev_sched;
unsigned long temp_stack;
- void *exec_buf;
+ jmp_buf *exec_buf;
struct arch_thread arch;
- union {
-#ifdef CONFIG_MODE_TT
- struct {
- int extern_pid;
- int tracing;
- int switch_pipe[2];
- int vm_seq;
- } tt;
-#endif
-#ifdef CONFIG_MODE_SKAS
- struct {
- jmp_buf switch_buf;
- int mm_count;
- } skas;
-#endif
- } mode;
+ jmp_buf switch_buf;
+ int mm_count;
struct {
int op;
union {
@@ -71,7 +59,7 @@ struct thread_struct {
{ \
.forking = 0, \
.nsyscalls = 0, \
- .regs = EMPTY_REGS, \
+ .regs = EMPTY_REGS, \
.fault_addr = NULL, \
.prev_sched = NULL, \
.temp_stack = 0, \
@@ -86,7 +74,10 @@ typedef struct {
extern struct task_struct *alloc_task_struct(void);
-extern void release_thread(struct task_struct *);
+static inline void release_thread(struct task_struct *task)
+{
+}
+
extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
static inline void prepare_to_copy(struct task_struct *tsk)
@@ -136,12 +127,7 @@ extern struct cpuinfo_um cpu_data[];
#endif
-#ifdef CONFIG_MODE_SKAS
-#define KSTK_REG(tsk, reg) \
- get_thread_reg(reg, &tsk->thread.mode.skas.switch_buf)
-#else
-#define KSTK_REG(tsk, reg) (0xbadbabe)
-#endif
+#define KSTK_REG(tsk, reg) get_thread_reg(reg, &tsk->thread.switch_buf)
#define get_wchan(p) (0)
#endif
diff --git a/include/asm-um/processor-x86_64.h b/include/asm-um/processor-x86_64.h
index 31c2d4d685bd..d946bf2d334a 100644
--- a/include/asm-um/processor-x86_64.h
+++ b/include/asm-um/processor-x86_64.h
@@ -18,7 +18,7 @@ struct arch_thread {
};
/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
-extern inline void rep_nop(void)
+static inline void rep_nop(void)
{
__asm__ __volatile__("rep;nop": : :"memory");
}
diff --git a/include/asm-um/ptrace-generic.h b/include/asm-um/ptrace-generic.h
index 99c87c5ce994..6aefcd32fc61 100644
--- a/include/asm-um/ptrace-generic.h
+++ b/include/asm-um/ptrace-generic.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -9,10 +9,11 @@
#ifndef __ASSEMBLY__
#include "asm/arch/ptrace-abi.h"
+#include <asm/user.h>
#include "sysdep/ptrace.h"
struct pt_regs {
- union uml_pt_regs regs;
+ struct uml_pt_regs regs;
};
#define EMPTY_REGS { .regs = EMPTY_UML_PT_REGS }
@@ -35,16 +36,18 @@ struct pt_regs {
struct task_struct;
+extern long subarch_ptrace(struct task_struct *child, long request, long addr,
+ long data);
extern unsigned long getreg(struct task_struct *child, int regno);
extern int putreg(struct task_struct *child, int regno, unsigned long value);
-extern int get_fpregs(unsigned long buf, struct task_struct *child);
-extern int set_fpregs(unsigned long buf, struct task_struct *child);
-extern int get_fpxregs(unsigned long buf, struct task_struct *child);
-extern int set_fpxregs(unsigned long buf, struct task_struct *tsk);
+extern int get_fpregs(struct user_i387_struct __user *buf,
+ struct task_struct *child);
+extern int set_fpregs(struct user_i387_struct __user *buf,
+ struct task_struct *child);
extern void show_regs(struct pt_regs *regs);
-extern void send_sigtrap(struct task_struct *tsk, union uml_pt_regs *regs,
+extern void send_sigtrap(struct task_struct *tsk, struct uml_pt_regs *regs,
int error_code);
extern int arch_copy_tls(struct task_struct *new);
diff --git a/include/asm-um/ptrace-i386.h b/include/asm-um/ptrace-i386.h
index 6e2528bb0083..b2d24c5ea2c3 100644
--- a/include/asm-um/ptrace-i386.h
+++ b/include/asm-um/ptrace-i386.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -9,10 +9,9 @@
#define HOST_AUDIT_ARCH AUDIT_ARCH_I386
#include "linux/compiler.h"
-#include "sysdep/ptrace.h"
#include "asm/ptrace-generic.h"
-#include "asm/host_ldt.h"
-#include "choose-mode.h"
+#include <asm/user.h>
+#include "sysdep/ptrace.h"
#define PT_REGS_EAX(r) UPT_EAX(&(r)->regs)
#define PT_REGS_EBX(r) UPT_EBX(&(r)->regs)
@@ -41,34 +40,21 @@
#define user_mode(r) UPT_IS_USER(&(r)->regs)
+/*
+ * Forward declaration to avoid including sysdep/tls.h, which causes a
+ * circular include, and compilation failures.
+ */
+struct user_desc;
+
+extern int get_fpxregs(struct user_fxsr_struct __user *buf,
+ struct task_struct *child);
+extern int set_fpxregs(struct user_fxsr_struct __user *buf,
+ struct task_struct *tsk);
+
extern int ptrace_get_thread_area(struct task_struct *child, int idx,
struct user_desc __user *user_desc);
extern int ptrace_set_thread_area(struct task_struct *child, int idx,
struct user_desc __user *user_desc);
-extern int do_set_thread_area_skas(struct user_desc *info);
-extern int do_get_thread_area_skas(struct user_desc *info);
-
-extern int do_set_thread_area_tt(struct user_desc *info);
-extern int do_get_thread_area_tt(struct user_desc *info);
-
-extern int arch_switch_tls_skas(struct task_struct *from, struct task_struct *to);
-extern int arch_switch_tls_tt(struct task_struct *from, struct task_struct *to);
-
-extern void arch_switch_to_tt(struct task_struct *from, struct task_struct *to);
-extern void arch_switch_to_skas(struct task_struct *from, struct task_struct *to);
-
-static inline int do_get_thread_area(struct user_desc *info)
-{
- return CHOOSE_MODE_PROC(do_get_thread_area_tt, do_get_thread_area_skas, info);
-}
-
-static inline int do_set_thread_area(struct user_desc *info)
-{
- return CHOOSE_MODE_PROC(do_set_thread_area_tt, do_set_thread_area_skas, info);
-}
-
-struct task_struct;
-
#endif
diff --git a/include/asm-um/ptrace-x86_64.h b/include/asm-um/ptrace-x86_64.h
index bf61d17de3f7..4c475350dcf0 100644
--- a/include/asm-um/ptrace-x86_64.h
+++ b/include/asm-um/ptrace-x86_64.h
@@ -76,15 +76,6 @@ static inline int ptrace_set_thread_area(struct task_struct *child, int idx,
return -ENOSYS;
}
-static inline void arch_switch_to_tt(struct task_struct *from,
- struct task_struct *to)
-{
-}
-
-extern void arch_switch_to_skas(struct task_struct *from,
- struct task_struct *to);
-
-extern long arch_prctl_skas(struct task_struct *task, int code,
- unsigned long __user *addr);
-
+extern long arch_prctl(struct task_struct *task, int code,
+ unsigned long __user *addr);
#endif
diff --git a/include/asm-um/smp.h b/include/asm-um/smp.h
index 84f8cf29324e..f27a96313174 100644
--- a/include/asm-um/smp.h
+++ b/include/asm-um/smp.h
@@ -18,7 +18,7 @@ extern int hard_smp_processor_id(void);
extern int ncpus;
-extern inline void smp_cpus_done(unsigned int maxcpus)
+static inline void smp_cpus_done(unsigned int maxcpus)
{
}
diff --git a/include/asm-um/tlbflush.h b/include/asm-um/tlbflush.h
index e78c28c1f350..614f2c091178 100644
--- a/include/asm-um/tlbflush.h
+++ b/include/asm-um/tlbflush.h
@@ -1,5 +1,5 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+/*
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -7,7 +7,6 @@
#define __UM_TLBFLUSH_H
#include <linux/mm.h>
-#include "choose-mode.h"
/*
* TLB flushing:
@@ -18,33 +17,15 @@
* - flush_tlb_page(vma, vmaddr) flushes one page
* - flush_tlb_kernel_vm() flushes the kernel vm area
* - flush_tlb_range(vma, start, end) flushes a range of pages
- * - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
*/
extern void flush_tlb_all(void);
extern void flush_tlb_mm(struct mm_struct *mm);
extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
unsigned long end);
-extern void flush_tlb_page_skas(struct vm_area_struct *vma,
- unsigned long address);
-
-static inline void flush_tlb_page(struct vm_area_struct *vma,
- unsigned long address)
-{
- address &= PAGE_MASK;
-
- CHOOSE_MODE(flush_tlb_range(vma, address, address + PAGE_SIZE),
- flush_tlb_page_skas(vma, address));
-}
-
-extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
+extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long address);
extern void flush_tlb_kernel_vm(void);
extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
extern void __flush_tlb_one(unsigned long addr);
-static inline void flush_tlb_pgtables(struct mm_struct *mm,
- unsigned long start, unsigned long end)
-{
-}
-
#endif
diff --git a/include/asm-um/uaccess.h b/include/asm-um/uaccess.h
index 16c734af9193..077032d4fc47 100644
--- a/include/asm-um/uaccess.h
+++ b/include/asm-um/uaccess.h
@@ -80,7 +80,7 @@
__put_user(x, private_ptr) : -EFAULT); \
})
-#define strlen_user(str) strnlen_user(str, ~0UL >> 1)
+#define strlen_user(str) strnlen_user(str, ~0U >> 1)
struct exception_table_entry
{
diff --git a/include/asm-um/unistd.h b/include/asm-um/unistd.h
index 732c83f04c3d..38bd9d94ee46 100644
--- a/include/asm-um/unistd.h
+++ b/include/asm-um/unistd.h
@@ -14,7 +14,6 @@ extern int um_execve(const char *file, char *const argv[], char *const env[]);
#ifdef __KERNEL__
/* We get __ARCH_WANT_OLD_STAT and __ARCH_WANT_STAT64 from the base arch */
-#define __ARCH_WANT_IPC_PARSE_VERSION
#define __ARCH_WANT_OLD_READDIR
#define __ARCH_WANT_SYS_ALARM
#define __ARCH_WANT_SYS_GETHOSTNAME
diff --git a/include/asm-v850/bitops.h b/include/asm-v850/bitops.h
index 1fa99baf4e25..f82f5b4a56e0 100644
--- a/include/asm-v850/bitops.h
+++ b/include/asm-v850/bitops.h
@@ -13,6 +13,9 @@
#ifndef __V850_BITOPS_H__
#define __V850_BITOPS_H__
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
#include <linux/compiler.h> /* unlikely */
#include <asm/byteorder.h> /* swab32 */
@@ -145,6 +148,7 @@ static inline int __test_bit (int nr, const void *addr)
#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/lock.h>
#include <asm-generic/bitops/ext2-non-atomic.h>
#define ext2_set_bit_atomic(l,n,a) test_and_set_bit(n,a)
diff --git a/include/asm-v850/ipc.h b/include/asm-v850/ipc.h
deleted file mode 100644
index a46e3d9c2a3f..000000000000
--- a/include/asm-v850/ipc.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ipc.h>
diff --git a/include/asm-v850/irq_regs.h b/include/asm-v850/irq_regs.h
new file mode 100644
index 000000000000..3dd9c0b70270
--- /dev/null
+++ b/include/asm-v850/irq_regs.h
@@ -0,0 +1 @@
+#include <asm-generic/irq_regs.h>
diff --git a/include/asm-v850/scatterlist.h b/include/asm-v850/scatterlist.h
index 56f402920db9..02d27b3fb061 100644
--- a/include/asm-v850/scatterlist.h
+++ b/include/asm-v850/scatterlist.h
@@ -17,7 +17,10 @@
#include <asm/types.h>
struct scatterlist {
- struct page *page;
+#ifdef CONFIG_DEBUG_SG
+ unsigned long sg_magic;
+#endif
+ unsigned long page_link;
unsigned offset;
dma_addr_t dma_address;
unsigned length;
diff --git a/include/asm-v850/semaphore.h b/include/asm-v850/semaphore.h
index 735baaf3a16e..10ed0ccf37df 100644
--- a/include/asm-v850/semaphore.h
+++ b/include/asm-v850/semaphore.h
@@ -22,7 +22,6 @@ struct semaphore {
struct semaphore name = __SEMAPHORE_INITIALIZER (name,count)
#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC (name,1)
-#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC (name,0)
static inline void sema_init (struct semaphore *sem, int val)
{
diff --git a/include/asm-v850/system.h b/include/asm-v850/system.h
index 0de2481fd990..a34ddfafd561 100644
--- a/include/asm-v850/system.h
+++ b/include/asm-v850/system.h
@@ -66,8 +66,7 @@ static inline int irqs_disabled (void)
#define rmb() mb ()
#define wmb() mb ()
#define read_barrier_depends() ((void)0)
-#define set_rmb(var, value) do { xchg (&var, value); } while (0)
-#define set_mb(var, value) set_rmb (var, value)
+#define set_mb(var, value) do { xchg (&var, value); } while (0)
#define smp_mb() mb ()
#define smp_rmb() rmb ()
diff --git a/include/asm-v850/tlbflush.h b/include/asm-v850/tlbflush.h
index 5f2f85f636ea..c44aa64449c8 100644
--- a/include/asm-v850/tlbflush.h
+++ b/include/asm-v850/tlbflush.h
@@ -61,10 +61,4 @@ static inline void flush_tlb_kernel_page(unsigned long addr)
BUG ();
}
-static inline void flush_tlb_pgtables(struct mm_struct *mm,
- unsigned long start, unsigned long end)
-{
- BUG ();
-}
-
#endif /* __V850_TLBFLUSH_H__ */
diff --git a/include/asm-v850/types.h b/include/asm-v850/types.h
index dcef57196875..284bda882112 100644
--- a/include/asm-v850/types.h
+++ b/include/asm-v850/types.h
@@ -27,9 +27,9 @@ typedef unsigned short __u16;
typedef __signed__ int __s32;
typedef unsigned int __u32;
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
-typedef __signed__ long long __s64;
-typedef unsigned long long __u64;
+#if defined(__GNUC__)
+__extension__ typedef __signed__ long long __s64;
+__extension__ typedef unsigned long long __u64;
#endif
#endif /* !__ASSEMBLY__ */
diff --git a/include/asm-x86/Kbuild b/include/asm-x86/Kbuild
index c5e43cb39874..12db5a1cdd74 100644
--- a/include/asm-x86/Kbuild
+++ b/include/asm-x86/Kbuild
@@ -1,85 +1,26 @@
include include/asm-generic/Kbuild.asm
header-y += boot.h
-header-y += bootsetup.h
-header-y += debugreg_32.h
-header-y += debugreg_64.h
+header-y += bootparam.h
header-y += debugreg.h
-header-y += ldt_32.h
-header-y += ldt_64.h
header-y += ldt.h
header-y += msr-index.h
header-y += prctl.h
-header-y += ptrace-abi_32.h
-header-y += ptrace-abi_64.h
header-y += ptrace-abi.h
header-y += sigcontext32.h
-header-y += ucontext_32.h
-header-y += ucontext_64.h
header-y += ucontext.h
header-y += vsyscall32.h
-unifdef-y += a.out_32.h
-unifdef-y += a.out_64.h
-unifdef-y += auxvec_32.h
-unifdef-y += auxvec_64.h
-unifdef-y += byteorder_32.h
-unifdef-y += byteorder_64.h
-unifdef-y += elf_32.h
-unifdef-y += elf_64.h
-unifdef-y += errno_32.h
-unifdef-y += errno_64.h
-unifdef-y += ioctls_32.h
-unifdef-y += ioctls_64.h
-unifdef-y += ipcbuf_32.h
-unifdef-y += ipcbuf_64.h
+unifdef-y += e820.h
+unifdef-y += ist.h
unifdef-y += mce.h
-unifdef-y += mman_32.h
-unifdef-y += mman_64.h
-unifdef-y += msgbuf_32.h
-unifdef-y += msgbuf_64.h
-unifdef-y += msr_32.h
-unifdef-y += msr_64.h
unifdef-y += msr.h
-unifdef-y += mtrr_32.h
-unifdef-y += mtrr_64.h
unifdef-y += mtrr.h
unifdef-y += page_32.h
unifdef-y += page_64.h
-unifdef-y += param_32.h
-unifdef-y += param_64.h
unifdef-y += posix_types_32.h
unifdef-y += posix_types_64.h
-unifdef-y += ptrace_32.h
-unifdef-y += ptrace_64.h
-unifdef-y += resource_32.h
-unifdef-y += resource_64.h
-unifdef-y += sembuf_32.h
-unifdef-y += sembuf_64.h
-unifdef-y += setup_32.h
-unifdef-y += setup_64.h
-unifdef-y += shmbuf_32.h
-unifdef-y += shmbuf_64.h
-unifdef-y += shmparam_32.h
-unifdef-y += shmparam_64.h
-unifdef-y += sigcontext_32.h
-unifdef-y += sigcontext_64.h
-unifdef-y += siginfo_32.h
-unifdef-y += siginfo_64.h
-unifdef-y += signal_32.h
-unifdef-y += signal_64.h
-unifdef-y += sockios_32.h
-unifdef-y += sockios_64.h
-unifdef-y += stat_32.h
-unifdef-y += stat_64.h
-unifdef-y += statfs_32.h
-unifdef-y += statfs_64.h
-unifdef-y += termbits_32.h
-unifdef-y += termbits_64.h
-unifdef-y += termios_32.h
-unifdef-y += termios_64.h
-unifdef-y += types_32.h
-unifdef-y += types_64.h
+unifdef-y += ptrace.h
unifdef-y += unistd_32.h
unifdef-y += unistd_64.h
unifdef-y += user_32.h
diff --git a/include/asm-x86/a.out.h b/include/asm-x86/a.out.h
index 5bc9b1d3b227..a62443e38eb8 100644
--- a/include/asm-x86/a.out.h
+++ b/include/asm-x86/a.out.h
@@ -1,13 +1,30 @@
+#ifndef _ASM_X86_A_OUT_H
+#define _ASM_X86_A_OUT_H
+
+struct exec
+{
+ unsigned int a_info; /* Use macros N_MAGIC, etc for access */
+ unsigned a_text; /* length of text, in bytes */
+ unsigned a_data; /* length of data, in bytes */
+ unsigned a_bss; /* length of uninitialized data area for file, in bytes */
+ unsigned a_syms; /* length of symbol table data in file, in bytes */
+ unsigned a_entry; /* start address */
+ unsigned a_trsize; /* length of relocation info for text, in bytes */
+ unsigned a_drsize; /* length of relocation info for data, in bytes */
+};
+
+#define N_TRSIZE(a) ((a).a_trsize)
+#define N_DRSIZE(a) ((a).a_drsize)
+#define N_SYMSIZE(a) ((a).a_syms)
+
#ifdef __KERNEL__
+# include <linux/thread_info.h>
+# define STACK_TOP TASK_SIZE
# ifdef CONFIG_X86_32
-# include "a.out_32.h"
+# define STACK_TOP_MAX STACK_TOP
# else
-# include "a.out_64.h"
-# endif
-#else
-# ifdef __i386__
-# include "a.out_32.h"
-# else
-# include "a.out_64.h"
+# define STACK_TOP_MAX TASK_SIZE64
# endif
#endif
+
+#endif /* _ASM_X86_A_OUT_H */
diff --git a/include/asm-x86/a.out_32.h b/include/asm-x86/a.out_32.h
deleted file mode 100644
index 851a60f8258c..000000000000
--- a/include/asm-x86/a.out_32.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef __I386_A_OUT_H__
-#define __I386_A_OUT_H__
-
-struct exec
-{
- unsigned long a_info; /* Use macros N_MAGIC, etc for access */
- unsigned a_text; /* length of text, in bytes */
- unsigned a_data; /* length of data, in bytes */
- unsigned a_bss; /* length of uninitialized data area for file, in bytes */
- unsigned a_syms; /* length of symbol table data in file, in bytes */
- unsigned a_entry; /* start address */
- unsigned a_trsize; /* length of relocation info for text, in bytes */
- unsigned a_drsize; /* length of relocation info for data, in bytes */
-};
-
-#define N_TRSIZE(a) ((a).a_trsize)
-#define N_DRSIZE(a) ((a).a_drsize)
-#define N_SYMSIZE(a) ((a).a_syms)
-
-#ifdef __KERNEL__
-
-#define STACK_TOP TASK_SIZE
-#define STACK_TOP_MAX STACK_TOP
-
-#endif
-
-#endif /* __A_OUT_GNU_H__ */
diff --git a/include/asm-x86/a.out_64.h b/include/asm-x86/a.out_64.h
deleted file mode 100644
index e789300e41a5..000000000000
--- a/include/asm-x86/a.out_64.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef __X8664_A_OUT_H__
-#define __X8664_A_OUT_H__
-
-/* 32bit a.out */
-
-struct exec
-{
- unsigned int a_info; /* Use macros N_MAGIC, etc for access */
- unsigned a_text; /* length of text, in bytes */
- unsigned a_data; /* length of data, in bytes */
- unsigned a_bss; /* length of uninitialized data area for file, in bytes */
- unsigned a_syms; /* length of symbol table data in file, in bytes */
- unsigned a_entry; /* start address */
- unsigned a_trsize; /* length of relocation info for text, in bytes */
- unsigned a_drsize; /* length of relocation info for data, in bytes */
-};
-
-#define N_TRSIZE(a) ((a).a_trsize)
-#define N_DRSIZE(a) ((a).a_drsize)
-#define N_SYMSIZE(a) ((a).a_syms)
-
-#ifdef __KERNEL__
-#include <linux/thread_info.h>
-#define STACK_TOP TASK_SIZE
-#define STACK_TOP_MAX TASK_SIZE64
-#endif
-
-#endif /* __A_OUT_GNU_H__ */
diff --git a/include/asm-x86/acpi_32.h b/include/asm-x86/acpi_32.h
index 125179adf044..723493e6c851 100644
--- a/include/asm-x86/acpi_32.h
+++ b/include/asm-x86/acpi_32.h
@@ -81,11 +81,7 @@ int __acpi_release_global_lock(unsigned int *lock);
:"=r"(n_hi), "=r"(n_lo) \
:"0"(n_hi), "1"(n_lo))
-#ifdef CONFIG_X86_IO_APIC
-extern void check_acpi_pci(void);
-#else
-static inline void check_acpi_pci(void) { }
-#endif
+extern void early_quirks(void);
#ifdef CONFIG_ACPI
extern int acpi_lapic;
diff --git a/include/asm-x86/agp.h b/include/asm-x86/agp.h
index 9348f1e4f6f1..62df2a9e7130 100644
--- a/include/asm-x86/agp.h
+++ b/include/asm-x86/agp.h
@@ -1,5 +1,40 @@
-#ifdef CONFIG_X86_32
-# include "agp_32.h"
-#else
-# include "agp_64.h"
+#ifndef _ASM_X86_AGP_H
+#define _ASM_X86_AGP_H
+
+#include <asm/pgtable.h>
+#include <asm/cacheflush.h>
+
+/*
+ * Functions to keep the agpgart mappings coherent with the MMU. The
+ * GART gives the CPU a physical alias of pages in memory. The alias
+ * region is mapped uncacheable. Make sure there are no conflicting
+ * mappings with different cachability attributes for the same
+ * page. This avoids data corruption on some CPUs.
+ */
+
+/*
+ * Caller's responsibility to call global_flush_tlb() for performance
+ * reasons
+ */
+#define map_page_into_agp(page) change_page_attr(page, 1, PAGE_KERNEL_NOCACHE)
+#define unmap_page_from_agp(page) change_page_attr(page, 1, PAGE_KERNEL)
+#define flush_agp_mappings() global_flush_tlb()
+
+/*
+ * Could use CLFLUSH here if the cpu supports it. But then it would
+ * need to be called for each cacheline of the whole page so it may
+ * not be worth it. Would need a page for it.
+ */
+#define flush_agp_cache() wbinvd()
+
+/* Convert a physical address to an address suitable for the GART. */
+#define phys_to_gart(x) (x)
+#define gart_to_phys(x) (x)
+
+/* GATT allocation. Returns/accepts GATT kernel virtual address. */
+#define alloc_gatt_pages(order) \
+ ((char *)__get_free_pages(GFP_KERNEL, (order)))
+#define free_gatt_pages(table, order) \
+ free_pages((unsigned long)(table), (order))
+
#endif
diff --git a/include/asm-x86/agp_32.h b/include/asm-x86/agp_32.h
deleted file mode 100644
index 6af173dbf123..000000000000
--- a/include/asm-x86/agp_32.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef AGP_H
-#define AGP_H 1
-
-#include <asm/pgtable.h>
-#include <asm/cacheflush.h>
-
-/*
- * Functions to keep the agpgart mappings coherent with the MMU.
- * The GART gives the CPU a physical alias of pages in memory. The alias region is
- * mapped uncacheable. Make sure there are no conflicting mappings
- * with different cachability attributes for the same page. This avoids
- * data corruption on some CPUs.
- */
-
-/* Caller's responsibility to call global_flush_tlb() for
- * performance reasons */
-#define map_page_into_agp(page) change_page_attr(page, 1, PAGE_KERNEL_NOCACHE)
-#define unmap_page_from_agp(page) change_page_attr(page, 1, PAGE_KERNEL)
-#define flush_agp_mappings() global_flush_tlb()
-
-/* Could use CLFLUSH here if the cpu supports it. But then it would
- need to be called for each cacheline of the whole page so it may not be
- worth it. Would need a page for it. */
-#define flush_agp_cache() wbinvd()
-
-/* Convert a physical address to an address suitable for the GART. */
-#define phys_to_gart(x) (x)
-#define gart_to_phys(x) (x)
-
-/* GATT allocation. Returns/accepts GATT kernel virtual address. */
-#define alloc_gatt_pages(order) \
- ((char *)__get_free_pages(GFP_KERNEL, (order)))
-#define free_gatt_pages(table, order) \
- free_pages((unsigned long)(table), (order))
-
-#endif
diff --git a/include/asm-x86/agp_64.h b/include/asm-x86/agp_64.h
deleted file mode 100644
index de338666f3f9..000000000000
--- a/include/asm-x86/agp_64.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef AGP_H
-#define AGP_H 1
-
-#include <asm/cacheflush.h>
-
-/*
- * Functions to keep the agpgart mappings coherent.
- * The GART gives the CPU a physical alias of memory. The alias is
- * mapped uncacheable. Make sure there are no conflicting mappings
- * with different cachability attributes for the same page.
- */
-
-/* Caller's responsibility to call global_flush_tlb() for
- * performance reasons */
-#define map_page_into_agp(page) change_page_attr(page, 1, PAGE_KERNEL_NOCACHE)
-#define unmap_page_from_agp(page) change_page_attr(page, 1, PAGE_KERNEL)
-#define flush_agp_mappings() global_flush_tlb()
-
-/* Could use CLFLUSH here if the cpu supports it. But then it would
- need to be called for each cacheline of the whole page so it may not be
- worth it. Would need a page for it. */
-#define flush_agp_cache() asm volatile("wbinvd":::"memory")
-
-/* Convert a physical address to an address suitable for the GART. */
-#define phys_to_gart(x) (x)
-#define gart_to_phys(x) (x)
-
-/* GATT allocation. Returns/accepts GATT kernel virtual address. */
-#define alloc_gatt_pages(order) \
- ((char *)__get_free_pages(GFP_KERNEL, (order)))
-#define free_gatt_pages(table, order) \
- free_pages((unsigned long)(table), (order))
-
-#endif
diff --git a/include/asm-x86/alternative-asm.h b/include/asm-x86/alternative-asm.h
new file mode 100644
index 000000000000..e2077d343c33
--- /dev/null
+++ b/include/asm-x86/alternative-asm.h
@@ -0,0 +1,22 @@
+#ifdef __ASSEMBLY__
+
+#ifdef CONFIG_X86_32
+# define X86_ALIGN .long
+#else
+# define X86_ALIGN .quad
+#endif
+
+#ifdef CONFIG_SMP
+ .macro LOCK_PREFIX
+1: lock
+ .section .smp_locks,"a"
+ .align 4
+ X86_ALIGN 1b
+ .previous
+ .endm
+#else
+ .macro LOCK_PREFIX
+ .endm
+#endif
+
+#endif /* __ASSEMBLY__ */
diff --git a/include/asm-x86/alternative-asm.i b/include/asm-x86/alternative-asm.i
deleted file mode 100644
index 4f360cd3c888..000000000000
--- a/include/asm-x86/alternative-asm.i
+++ /dev/null
@@ -1,5 +0,0 @@
-#ifdef CONFIG_X86_32
-# include "alternative-asm_32.i"
-#else
-# include "alternative-asm_64.i"
-#endif
diff --git a/include/asm-x86/alternative-asm_32.i b/include/asm-x86/alternative-asm_32.i
deleted file mode 100644
index f0510209ccbe..000000000000
--- a/include/asm-x86/alternative-asm_32.i
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifdef CONFIG_SMP
- .macro LOCK_PREFIX
-1: lock
- .section .smp_locks,"a"
- .align 4
- .long 1b
- .previous
- .endm
-#else
- .macro LOCK_PREFIX
- .endm
-#endif
diff --git a/include/asm-x86/alternative-asm_64.i b/include/asm-x86/alternative-asm_64.i
deleted file mode 100644
index 0b3f1a2bb2cb..000000000000
--- a/include/asm-x86/alternative-asm_64.i
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifdef CONFIG_SMP
- .macro LOCK_PREFIX
-1: lock
- .section .smp_locks,"a"
- .align 8
- .quad 1b
- .previous
- .endm
-#else
- .macro LOCK_PREFIX
- .endm
-#endif
diff --git a/include/asm-x86/apic_64.h b/include/asm-x86/apic_64.h
index 3c8f21eef0be..2747a11a2b19 100644
--- a/include/asm-x86/apic_64.h
+++ b/include/asm-x86/apic_64.h
@@ -69,6 +69,7 @@ extern void clear_local_APIC (void);
extern void connect_bsp_APIC (void);
extern void disconnect_bsp_APIC (int virt_wire_setup);
extern void disable_local_APIC (void);
+extern void lapic_shutdown (void);
extern int verify_local_APIC (void);
extern void cache_APIC_registers (void);
extern void sync_Arb_IDs (void);
diff --git a/include/asm-x86/atomic_64.h b/include/asm-x86/atomic_64.h
index f2e64634fa48..2d20a7a19f62 100644
--- a/include/asm-x86/atomic_64.h
+++ b/include/asm-x86/atomic_64.h
@@ -206,7 +206,7 @@ static __inline__ int atomic_sub_return(int i, atomic_t *v)
/* An 64bit atomic type */
-typedef struct { volatile long counter; } atomic64_t;
+typedef struct { long counter; } atomic64_t;
#define ATOMIC64_INIT(i) { (i) }
diff --git a/include/asm-x86/auxvec.h b/include/asm-x86/auxvec.h
index 7ff866f829ca..87f5e6d5a020 100644
--- a/include/asm-x86/auxvec.h
+++ b/include/asm-x86/auxvec.h
@@ -1,13 +1,12 @@
-#ifdef __KERNEL__
-# ifdef CONFIG_X86_32
-# include "auxvec_32.h"
-# else
-# include "auxvec_64.h"
-# endif
-#else
-# ifdef __i386__
-# include "auxvec_32.h"
-# else
-# include "auxvec_64.h"
-# endif
+#ifndef _ASM_X86_AUXVEC_H
+#define _ASM_X86_AUXVEC_H
+/*
+ * Architecture-neutral AT_ values in 0-17, leave some room
+ * for more of them, start the x86-specific ones at 32.
+ */
+#ifdef __i386__
+#define AT_SYSINFO 32
+#endif
+#define AT_SYSINFO_EHDR 33
+
#endif
diff --git a/include/asm-x86/auxvec_32.h b/include/asm-x86/auxvec_32.h
deleted file mode 100644
index 395e13016bfb..000000000000
--- a/include/asm-x86/auxvec_32.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef __ASMi386_AUXVEC_H
-#define __ASMi386_AUXVEC_H
-
-/*
- * Architecture-neutral AT_ values in 0-17, leave some room
- * for more of them, start the x86-specific ones at 32.
- */
-#define AT_SYSINFO 32
-#define AT_SYSINFO_EHDR 33
-
-#endif
diff --git a/include/asm-x86/auxvec_64.h b/include/asm-x86/auxvec_64.h
deleted file mode 100644
index 1d5ab0d03950..000000000000
--- a/include/asm-x86/auxvec_64.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_X86_64_AUXVEC_H
-#define __ASM_X86_64_AUXVEC_H
-
-#define AT_SYSINFO_EHDR 33
-
-#endif
diff --git a/include/asm-x86/bitops_32.h b/include/asm-x86/bitops_32.h
index a20fe9822f60..0b40f6d20bea 100644
--- a/include/asm-x86/bitops_32.h
+++ b/include/asm-x86/bitops_32.h
@@ -5,6 +5,10 @@
* Copyright 1992, Linus Torvalds.
*/
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
#include <linux/compiler.h>
#include <asm/alternative.h>
@@ -76,6 +80,20 @@ static inline void clear_bit(int nr, volatile unsigned long * addr)
:"Ir" (nr));
}
+/*
+ * clear_bit_unlock - Clears a bit in memory
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ *
+ * clear_bit() is atomic and implies release semantics before the memory
+ * operation. It can be used for an unlock.
+ */
+static inline void clear_bit_unlock(unsigned long nr, volatile unsigned long *addr)
+{
+ barrier();
+ clear_bit(nr, addr);
+}
+
static inline void __clear_bit(int nr, volatile unsigned long * addr)
{
__asm__ __volatile__(
@@ -83,6 +101,25 @@ static inline void __clear_bit(int nr, volatile unsigned long * addr)
:"+m" (ADDR)
:"Ir" (nr));
}
+
+/*
+ * __clear_bit_unlock - Clears a bit in memory
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ *
+ * __clear_bit() is non-atomic and implies release semantics before the memory
+ * operation. It can be used for an unlock if no other CPUs can concurrently
+ * modify other bits in the word.
+ *
+ * No memory barrier is required here, because x86 cannot reorder stores past
+ * older loads. Same principle as spin_unlock.
+ */
+static inline void __clear_bit_unlock(unsigned long nr, volatile unsigned long *addr)
+{
+ barrier();
+ __clear_bit(nr, addr);
+}
+
#define smp_mb__before_clear_bit() barrier()
#define smp_mb__after_clear_bit() barrier()
@@ -142,6 +179,18 @@ static inline int test_and_set_bit(int nr, volatile unsigned long * addr)
}
/**
+ * test_and_set_bit_lock - Set a bit and return its old value for lock
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This is the same as test_and_set_bit on x86.
+ */
+static inline int test_and_set_bit_lock(int nr, volatile unsigned long *addr)
+{
+ return test_and_set_bit(nr, addr);
+}
+
+/**
* __test_and_set_bit - Set a bit and return its old value
* @nr: Bit to set
* @addr: Address to count from
diff --git a/include/asm-x86/bitops_64.h b/include/asm-x86/bitops_64.h
index d4dbbe5f7bd9..766bcc0470a6 100644
--- a/include/asm-x86/bitops_64.h
+++ b/include/asm-x86/bitops_64.h
@@ -5,6 +5,10 @@
* Copyright 1992, Linus Torvalds.
*/
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
#include <asm/alternative.h>
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 1)
@@ -25,7 +29,7 @@
* Note that @nr may be almost arbitrarily large; this function is not
* restricted to acting on a single-word quantity.
*/
-static __inline__ void set_bit(int nr, volatile void * addr)
+static inline void set_bit(int nr, volatile void *addr)
{
__asm__ __volatile__( LOCK_PREFIX
"btsl %1,%0"
@@ -42,7 +46,7 @@ static __inline__ void set_bit(int nr, volatile void * addr)
* If it's called on the same region of memory simultaneously, the effect
* may be that only one operation succeeds.
*/
-static __inline__ void __set_bit(int nr, volatile void * addr)
+static inline void __set_bit(int nr, volatile void *addr)
{
__asm__ volatile(
"btsl %1,%0"
@@ -60,7 +64,7 @@ static __inline__ void __set_bit(int nr, volatile void * addr)
* you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
* in order to ensure changes are visible on other processors.
*/
-static __inline__ void clear_bit(int nr, volatile void * addr)
+static inline void clear_bit(int nr, volatile void *addr)
{
__asm__ __volatile__( LOCK_PREFIX
"btrl %1,%0"
@@ -68,7 +72,21 @@ static __inline__ void clear_bit(int nr, volatile void * addr)
:"dIr" (nr));
}
-static __inline__ void __clear_bit(int nr, volatile void * addr)
+/*
+ * clear_bit_unlock - Clears a bit in memory
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ *
+ * clear_bit() is atomic and implies release semantics before the memory
+ * operation. It can be used for an unlock.
+ */
+static inline void clear_bit_unlock(unsigned long nr, volatile unsigned long *addr)
+{
+ barrier();
+ clear_bit(nr, addr);
+}
+
+static inline void __clear_bit(int nr, volatile void *addr)
{
__asm__ __volatile__(
"btrl %1,%0"
@@ -76,6 +94,24 @@ static __inline__ void __clear_bit(int nr, volatile void * addr)
:"dIr" (nr));
}
+/*
+ * __clear_bit_unlock - Clears a bit in memory
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ *
+ * __clear_bit() is non-atomic and implies release semantics before the memory
+ * operation. It can be used for an unlock if no other CPUs can concurrently
+ * modify other bits in the word.
+ *
+ * No memory barrier is required here, because x86 cannot reorder stores past
+ * older loads. Same principle as spin_unlock.
+ */
+static inline void __clear_bit_unlock(unsigned long nr, volatile unsigned long *addr)
+{
+ barrier();
+ __clear_bit(nr, addr);
+}
+
#define smp_mb__before_clear_bit() barrier()
#define smp_mb__after_clear_bit() barrier()
@@ -88,7 +124,7 @@ static __inline__ void __clear_bit(int nr, volatile void * addr)
* If it's called on the same region of memory simultaneously, the effect
* may be that only one operation succeeds.
*/
-static __inline__ void __change_bit(int nr, volatile void * addr)
+static inline void __change_bit(int nr, volatile void *addr)
{
__asm__ __volatile__(
"btcl %1,%0"
@@ -105,7 +141,7 @@ static __inline__ void __change_bit(int nr, volatile void * addr)
* Note that @nr may be almost arbitrarily large; this function is not
* restricted to acting on a single-word quantity.
*/
-static __inline__ void change_bit(int nr, volatile void * addr)
+static inline void change_bit(int nr, volatile void *addr)
{
__asm__ __volatile__( LOCK_PREFIX
"btcl %1,%0"
@@ -121,7 +157,7 @@ static __inline__ void change_bit(int nr, volatile void * addr)
* This operation is atomic and cannot be reordered.
* It also implies a memory barrier.
*/
-static __inline__ int test_and_set_bit(int nr, volatile void * addr)
+static inline int test_and_set_bit(int nr, volatile void *addr)
{
int oldbit;
@@ -133,6 +169,18 @@ static __inline__ int test_and_set_bit(int nr, volatile void * addr)
}
/**
+ * test_and_set_bit_lock - Set a bit and return its old value for lock
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This is the same as test_and_set_bit on x86.
+ */
+static inline int test_and_set_bit_lock(int nr, volatile void *addr)
+{
+ return test_and_set_bit(nr, addr);
+}
+
+/**
* __test_and_set_bit - Set a bit and return its old value
* @nr: Bit to set
* @addr: Address to count from
@@ -141,7 +189,7 @@ static __inline__ int test_and_set_bit(int nr, volatile void * addr)
* If two examples of this operation race, one can appear to succeed
* but actually fail. You must protect multiple accesses with a lock.
*/
-static __inline__ int __test_and_set_bit(int nr, volatile void * addr)
+static inline int __test_and_set_bit(int nr, volatile void *addr)
{
int oldbit;
@@ -160,7 +208,7 @@ static __inline__ int __test_and_set_bit(int nr, volatile void * addr)
* This operation is atomic and cannot be reordered.
* It also implies a memory barrier.
*/
-static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
+static inline int test_and_clear_bit(int nr, volatile void *addr)
{
int oldbit;
@@ -180,7 +228,7 @@ static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
* If two examples of this operation race, one can appear to succeed
* but actually fail. You must protect multiple accesses with a lock.
*/
-static __inline__ int __test_and_clear_bit(int nr, volatile void * addr)
+static inline int __test_and_clear_bit(int nr, volatile void *addr)
{
int oldbit;
@@ -192,7 +240,7 @@ static __inline__ int __test_and_clear_bit(int nr, volatile void * addr)
}
/* WARNING: non atomic and it can be reordered! */
-static __inline__ int __test_and_change_bit(int nr, volatile void * addr)
+static inline int __test_and_change_bit(int nr, volatile void *addr)
{
int oldbit;
@@ -211,7 +259,7 @@ static __inline__ int __test_and_change_bit(int nr, volatile void * addr)
* This operation is atomic and cannot be reordered.
* It also implies a memory barrier.
*/
-static __inline__ int test_and_change_bit(int nr, volatile void * addr)
+static inline int test_and_change_bit(int nr, volatile void *addr)
{
int oldbit;
@@ -228,15 +276,15 @@ static __inline__ int test_and_change_bit(int nr, volatile void * addr)
* @nr: bit number to test
* @addr: Address to start counting from
*/
-static int test_bit(int nr, const volatile void * addr);
+static int test_bit(int nr, const volatile void *addr);
#endif
-static __inline__ int constant_test_bit(int nr, const volatile void * addr)
+static inline int constant_test_bit(int nr, const volatile void *addr)
{
return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
}
-static __inline__ int variable_test_bit(int nr, volatile const void * addr)
+static inline int variable_test_bit(int nr, volatile const void *addr)
{
int oldbit;
@@ -254,13 +302,13 @@ static __inline__ int variable_test_bit(int nr, volatile const void * addr)
#undef ADDR
-extern long find_first_zero_bit(const unsigned long * addr, unsigned long size);
-extern long find_next_zero_bit (const unsigned long * addr, long size, long offset);
-extern long find_first_bit(const unsigned long * addr, unsigned long size);
-extern long find_next_bit(const unsigned long * addr, long size, long offset);
+extern long find_first_zero_bit(const unsigned long *addr, unsigned long size);
+extern long find_next_zero_bit(const unsigned long *addr, long size, long offset);
+extern long find_first_bit(const unsigned long *addr, unsigned long size);
+extern long find_next_bit(const unsigned long *addr, long size, long offset);
/* return index of first bet set in val or max when no bit is set */
-static inline unsigned long __scanbit(unsigned long val, unsigned long max)
+static inline long __scanbit(unsigned long val, unsigned long max)
{
asm("bsfq %1,%0 ; cmovz %2,%0" : "=&r" (val) : "r" (val), "r" (max));
return val;
@@ -318,7 +366,7 @@ static inline void __clear_bit_string(unsigned long *bitmap, unsigned long i,
*
* Undefined if no zero exists, so code should check against ~0UL first.
*/
-static __inline__ unsigned long ffz(unsigned long word)
+static inline unsigned long ffz(unsigned long word)
{
__asm__("bsfq %1,%0"
:"=r" (word)
@@ -332,7 +380,7 @@ static __inline__ unsigned long ffz(unsigned long word)
*
* Undefined if no bit exists, so code should check against 0 first.
*/
-static __inline__ unsigned long __ffs(unsigned long word)
+static inline unsigned long __ffs(unsigned long word)
{
__asm__("bsfq %1,%0"
:"=r" (word)
@@ -346,7 +394,7 @@ static __inline__ unsigned long __ffs(unsigned long word)
*
* Undefined if no zero exists, so code should check against ~0UL first.
*/
-static __inline__ unsigned long __fls(unsigned long word)
+static inline unsigned long __fls(unsigned long word)
{
__asm__("bsrq %1,%0"
:"=r" (word)
@@ -366,7 +414,7 @@ static __inline__ unsigned long __fls(unsigned long word)
* the libc and compiler builtin ffs routines, therefore
* differs in spirit from the above ffz (man ffs).
*/
-static __inline__ int ffs(int x)
+static inline int ffs(int x)
{
int r;
@@ -382,7 +430,7 @@ static __inline__ int ffs(int x)
*
* This is defined the same way as fls.
*/
-static __inline__ int fls64(__u64 x)
+static inline int fls64(__u64 x)
{
if (x == 0)
return 0;
@@ -395,7 +443,7 @@ static __inline__ int fls64(__u64 x)
*
* This is defined the same way as ffs.
*/
-static __inline__ int fls(int x)
+static inline int fls(int x)
{
int r;
diff --git a/include/asm-x86/bootparam.h b/include/asm-x86/bootparam.h
index b91b01783e4b..19f3ddf2df4b 100644
--- a/include/asm-x86/bootparam.h
+++ b/include/asm-x86/bootparam.h
@@ -10,77 +10,85 @@
#include <video/edid.h>
struct setup_header {
- u8 setup_sects;
- u16 root_flags;
- u32 syssize;
- u16 ram_size;
- u16 vid_mode;
- u16 root_dev;
- u16 boot_flag;
- u16 jump;
- u32 header;
- u16 version;
- u32 realmode_swtch;
- u16 start_sys;
- u16 kernel_version;
- u8 type_of_loader;
- u8 loadflags;
-#define LOADED_HIGH 0x01
-#define CAN_USE_HEAP 0x80
- u16 setup_move_size;
- u32 code32_start;
- u32 ramdisk_image;
- u32 ramdisk_size;
- u32 bootsect_kludge;
- u16 heap_end_ptr;
- u16 _pad1;
- u32 cmd_line_ptr;
- u32 initrd_addr_max;
- u32 kernel_alignment;
- u8 relocatable_kernel;
+ __u8 setup_sects;
+ __u16 root_flags;
+ __u32 syssize;
+ __u16 ram_size;
+#define RAMDISK_IMAGE_START_MASK 0x07FF
+#define RAMDISK_PROMPT_FLAG 0x8000
+#define RAMDISK_LOAD_FLAG 0x4000
+ __u16 vid_mode;
+ __u16 root_dev;
+ __u16 boot_flag;
+ __u16 jump;
+ __u32 header;
+ __u16 version;
+ __u32 realmode_swtch;
+ __u16 start_sys;
+ __u16 kernel_version;
+ __u8 type_of_loader;
+ __u8 loadflags;
+#define LOADED_HIGH (1<<0)
+#define KEEP_SEGMENTS (1<<6)
+#define CAN_USE_HEAP (1<<7)
+ __u16 setup_move_size;
+ __u32 code32_start;
+ __u32 ramdisk_image;
+ __u32 ramdisk_size;
+ __u32 bootsect_kludge;
+ __u16 heap_end_ptr;
+ __u16 _pad1;
+ __u32 cmd_line_ptr;
+ __u32 initrd_addr_max;
+ __u32 kernel_alignment;
+ __u8 relocatable_kernel;
+ __u8 _pad2[3];
+ __u32 cmdline_size;
+ __u32 hardware_subarch;
+ __u64 hardware_subarch_data;
} __attribute__((packed));
struct sys_desc_table {
- u16 length;
- u8 table[14];
+ __u16 length;
+ __u8 table[14];
};
struct efi_info {
- u32 _pad1;
- u32 efi_systab;
- u32 efi_memdesc_size;
- u32 efi_memdesc_version;
- u32 efi_memmap;
- u32 efi_memmap_size;
- u32 _pad2[2];
+ __u32 _pad1;
+ __u32 efi_systab;
+ __u32 efi_memdesc_size;
+ __u32 efi_memdesc_version;
+ __u32 efi_memmap;
+ __u32 efi_memmap_size;
+ __u32 _pad2[2];
};
/* The so-called "zeropage" */
struct boot_params {
struct screen_info screen_info; /* 0x000 */
struct apm_bios_info apm_bios_info; /* 0x040 */
- u8 _pad2[12]; /* 0x054 */
+ __u8 _pad2[12]; /* 0x054 */
struct ist_info ist_info; /* 0x060 */
- u8 _pad3[16]; /* 0x070 */
- u8 hd0_info[16]; /* obsolete! */ /* 0x080 */
- u8 hd1_info[16]; /* obsolete! */ /* 0x090 */
+ __u8 _pad3[16]; /* 0x070 */
+ __u8 hd0_info[16]; /* obsolete! */ /* 0x080 */
+ __u8 hd1_info[16]; /* obsolete! */ /* 0x090 */
struct sys_desc_table sys_desc_table; /* 0x0a0 */
- u8 _pad4[144]; /* 0x0b0 */
+ __u8 _pad4[144]; /* 0x0b0 */
struct edid_info edid_info; /* 0x140 */
struct efi_info efi_info; /* 0x1c0 */
- u32 alt_mem_k; /* 0x1e0 */
- u32 scratch; /* Scratch field! */ /* 0x1e4 */
- u8 e820_entries; /* 0x1e8 */
- u8 eddbuf_entries; /* 0x1e9 */
- u8 edd_mbr_sig_buf_entries; /* 0x1ea */
- u8 _pad6[6]; /* 0x1eb */
+ __u32 alt_mem_k; /* 0x1e0 */
+ __u32 scratch; /* Scratch field! */ /* 0x1e4 */
+ __u8 e820_entries; /* 0x1e8 */
+ __u8 eddbuf_entries; /* 0x1e9 */
+ __u8 edd_mbr_sig_buf_entries; /* 0x1ea */
+ __u8 _pad6[6]; /* 0x1eb */
struct setup_header hdr; /* setup header */ /* 0x1f1 */
- u8 _pad7[0x290-0x1f1-sizeof(struct setup_header)];
- u32 edd_mbr_sig_buffer[EDD_MBR_SIG_MAX]; /* 0x290 */
+ __u8 _pad7[0x290-0x1f1-sizeof(struct setup_header)];
+ __u32 edd_mbr_sig_buffer[EDD_MBR_SIG_MAX]; /* 0x290 */
struct e820entry e820_map[E820MAX]; /* 0x2d0 */
- u8 _pad8[48]; /* 0xcd0 */
+ __u8 _pad8[48]; /* 0xcd0 */
struct edd_info eddbuf[EDDMAXNR]; /* 0xd00 */
- u8 _pad9[276]; /* 0xeec */
+ __u8 _pad9[276]; /* 0xeec */
} __attribute__((packed));
#endif /* _ASM_BOOTPARAM_H */
diff --git a/include/asm-x86/bootsetup.h b/include/asm-x86/bootsetup.h
deleted file mode 100644
index 7b1c3ad155fd..000000000000
--- a/include/asm-x86/bootsetup.h
+++ /dev/null
@@ -1,40 +0,0 @@
-
-#ifndef _X86_64_BOOTSETUP_H
-#define _X86_64_BOOTSETUP_H 1
-
-#define BOOT_PARAM_SIZE 4096
-extern char x86_boot_params[BOOT_PARAM_SIZE];
-
-/*
- * This is set up by the setup-routine at boot-time
- */
-#define PARAM ((unsigned char *)x86_boot_params)
-#define SCREEN_INFO (*(struct screen_info *) (PARAM+0))
-#define EXT_MEM_K (*(unsigned short *) (PARAM+2))
-#define ALT_MEM_K (*(unsigned int *) (PARAM+0x1e0))
-#define E820_MAP_NR (*(char*) (PARAM+E820NR))
-#define E820_MAP ((struct e820entry *) (PARAM+E820MAP))
-#define APM_BIOS_INFO (*(struct apm_bios_info *) (PARAM+0x40))
-#define DRIVE_INFO (*(struct drive_info_struct *) (PARAM+0x80))
-#define SYS_DESC_TABLE (*(struct sys_desc_table_struct*)(PARAM+0xa0))
-#define MOUNT_ROOT_RDONLY (*(unsigned short *) (PARAM+0x1F2))
-#define RAMDISK_FLAGS (*(unsigned short *) (PARAM+0x1F8))
-#define SAVED_VIDEO_MODE (*(unsigned short *) (PARAM+0x1FA))
-#define ORIG_ROOT_DEV (*(unsigned short *) (PARAM+0x1FC))
-#define AUX_DEVICE_INFO (*(unsigned char *) (PARAM+0x1FF))
-#define LOADER_TYPE (*(unsigned char *) (PARAM+0x210))
-#define KERNEL_START (*(unsigned int *) (PARAM+0x214))
-#define INITRD_START (*(unsigned int *) (PARAM+0x218))
-#define INITRD_SIZE (*(unsigned int *) (PARAM+0x21c))
-#define EDID_INFO (*(struct edid_info *) (PARAM+0x140))
-#define EDD_NR (*(unsigned char *) (PARAM+EDDNR))
-#define EDD_MBR_SIG_NR (*(unsigned char *) (PARAM+EDD_MBR_SIG_NR_BUF))
-#define EDD_MBR_SIGNATURE ((unsigned int *) (PARAM+EDD_MBR_SIG_BUF))
-#define EDD_BUF ((struct edd_info *) (PARAM+EDDBUF))
-#define COMMAND_LINE boot_command_line
-
-#define RAMDISK_IMAGE_START_MASK 0x07FF
-#define RAMDISK_PROMPT_FLAG 0x8000
-#define RAMDISK_LOAD_FLAG 0x4000
-
-#endif
diff --git a/include/asm-x86/bug.h b/include/asm-x86/bug.h
index c655d7f3a5e0..fd8bdc639c48 100644
--- a/include/asm-x86/bug.h
+++ b/include/asm-x86/bug.h
@@ -1,5 +1,42 @@
+#ifndef _ASM_X86_BUG_H
+#define _ASM_X86_BUG_H
+
+#ifdef CONFIG_BUG
+#define HAVE_ARCH_BUG
+
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+
#ifdef CONFIG_X86_32
-# include "bug_32.h"
+# define __BUG_C0 "2:\t.long 1b, %c0\n"
#else
-# include "bug_64.h"
+# define __BUG_C0 "2:\t.quad 1b, %c0\n"
+#endif
+
+#define BUG() \
+ do { \
+ asm volatile("1:\tud2\n" \
+ ".pushsection __bug_table,\"a\"\n" \
+ __BUG_C0 \
+ "\t.word %c1, 0\n" \
+ "\t.org 2b+%c2\n" \
+ ".popsection" \
+ : : "i" (__FILE__), "i" (__LINE__), \
+ "i" (sizeof(struct bug_entry))); \
+ for(;;) ; \
+ } while(0)
+
+#else
+#define BUG() \
+ do { \
+ asm volatile("ud2"); \
+ for(;;) ; \
+ } while(0)
+#endif
+
+void out_of_line_bug(void);
+#else /* CONFIG_BUG */
+static inline void out_of_line_bug(void) { }
+#endif /* !CONFIG_BUG */
+
+#include <asm-generic/bug.h>
#endif
diff --git a/include/asm-x86/bug_32.h b/include/asm-x86/bug_32.h
deleted file mode 100644
index b0fd78ca2619..000000000000
--- a/include/asm-x86/bug_32.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef _I386_BUG_H
-#define _I386_BUG_H
-
-
-/*
- * Tell the user there is some problem.
- * The offending file and line are encoded encoded in the __bug_table section.
- */
-
-#ifdef CONFIG_BUG
-#define HAVE_ARCH_BUG
-
-#ifdef CONFIG_DEBUG_BUGVERBOSE
-#define BUG() \
- do { \
- asm volatile("1:\tud2\n" \
- ".pushsection __bug_table,\"a\"\n" \
- "2:\t.long 1b, %c0\n" \
- "\t.word %c1, 0\n" \
- "\t.org 2b+%c2\n" \
- ".popsection" \
- : : "i" (__FILE__), "i" (__LINE__), \
- "i" (sizeof(struct bug_entry))); \
- for(;;) ; \
- } while(0)
-
-#else
-#define BUG() \
- do { \
- asm volatile("ud2"); \
- for(;;) ; \
- } while(0)
-#endif
-#endif
-
-#include <asm-generic/bug.h>
-#endif
diff --git a/include/asm-x86/bug_64.h b/include/asm-x86/bug_64.h
deleted file mode 100644
index 682606414913..000000000000
--- a/include/asm-x86/bug_64.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef __ASM_X8664_BUG_H
-#define __ASM_X8664_BUG_H 1
-
-#ifdef CONFIG_BUG
-#define HAVE_ARCH_BUG
-
-#ifdef CONFIG_DEBUG_BUGVERBOSE
-#define BUG() \
- do { \
- asm volatile("1:\tud2\n" \
- ".pushsection __bug_table,\"a\"\n" \
- "2:\t.quad 1b, %c0\n" \
- "\t.word %c1, 0\n" \
- "\t.org 2b+%c2\n" \
- ".popsection" \
- : : "i" (__FILE__), "i" (__LINE__), \
- "i" (sizeof(struct bug_entry))); \
- for(;;) ; \
- } while(0)
-#else
-#define BUG() \
- do { \
- asm volatile("ud2"); \
- for(;;) ; \
- } while(0)
-#endif
-
-void out_of_line_bug(void);
-#else
-static inline void out_of_line_bug(void) { }
-#endif
-
-#include <asm-generic/bug.h>
-#endif
diff --git a/include/asm-x86/bugs.h b/include/asm-x86/bugs.h
index ddf42d36dd50..aac8317420af 100644
--- a/include/asm-x86/bugs.h
+++ b/include/asm-x86/bugs.h
@@ -1,5 +1,6 @@
-#ifdef CONFIG_X86_32
-# include "bugs_32.h"
-#else
-# include "bugs_64.h"
-#endif
+#ifndef _ASM_X86_BUGS_H
+#define _ASM_X86_BUGS_H
+
+void check_bugs(void);
+
+#endif /* _ASM_X86_BUGS_H */
diff --git a/include/asm-x86/bugs_32.h b/include/asm-x86/bugs_32.h
deleted file mode 100644
index d28979ff73be..000000000000
--- a/include/asm-x86/bugs_32.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * This is included by init/main.c to check for architecture-dependent bugs.
- *
- * Needs:
- * void check_bugs(void);
- */
-#ifndef _ASM_I386_BUG_H
-#define _ASM_I386_BUG_H
-
-void check_bugs(void);
-
-#endif /* _ASM_I386_BUG_H */
diff --git a/include/asm-x86/bugs_64.h b/include/asm-x86/bugs_64.h
deleted file mode 100644
index b33dc04d8f42..000000000000
--- a/include/asm-x86/bugs_64.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_X86_64_BUGS_H
-#define _ASM_X86_64_BUGS_H
-
-void check_bugs(void);
-
-#endif /* _ASM_X86_64_BUGS_H */
diff --git a/include/asm-x86/byteorder.h b/include/asm-x86/byteorder.h
index eb14b1870ed7..1f2d6d5bf20d 100644
--- a/include/asm-x86/byteorder.h
+++ b/include/asm-x86/byteorder.h
@@ -1,13 +1,72 @@
-#ifdef __KERNEL__
-# ifdef CONFIG_X86_32
-# include "byteorder_32.h"
-# else
-# include "byteorder_64.h"
-# endif
+#ifndef _ASM_X86_BYTEORDER_H
+#define _ASM_X86_BYTEORDER_H
+
+#include <asm/types.h>
+#include <linux/compiler.h>
+
+#ifdef __GNUC__
+
+#ifdef __i386__
+
+static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
+{
+#ifdef CONFIG_X86_BSWAP
+ __asm__("bswap %0" : "=r" (x) : "0" (x));
#else
-# ifdef __i386__
-# include "byteorder_32.h"
-# else
-# include "byteorder_64.h"
-# endif
+ __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */
+ "rorl $16,%0\n\t" /* swap words */
+ "xchgb %b0,%h0" /* swap higher bytes */
+ :"=q" (x)
+ : "0" (x));
#endif
+ return x;
+}
+
+static __inline__ __attribute_const__ __u64 ___arch__swab64(__u64 val)
+{
+ union {
+ struct { __u32 a,b; } s;
+ __u64 u;
+ } v;
+ v.u = val;
+#ifdef CONFIG_X86_BSWAP
+ asm("bswapl %0 ; bswapl %1 ; xchgl %0,%1"
+ : "=r" (v.s.a), "=r" (v.s.b)
+ : "0" (v.s.a), "1" (v.s.b));
+#else
+ v.s.a = ___arch__swab32(v.s.a);
+ v.s.b = ___arch__swab32(v.s.b);
+ asm("xchgl %0,%1" : "=r" (v.s.a), "=r" (v.s.b) : "0" (v.s.a), "1" (v.s.b));
+#endif
+ return v.u;
+}
+
+#else /* __i386__ */
+
+static __inline__ __attribute_const__ __u64 ___arch__swab64(__u64 x)
+{
+ __asm__("bswapq %0" : "=r" (x) : "0" (x));
+ return x;
+}
+
+static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
+{
+ __asm__("bswapl %0" : "=r" (x) : "0" (x));
+ return x;
+}
+
+#endif
+
+/* Do not define swab16. Gcc is smart enough to recognize "C" version and
+ convert it into rotation or exhange. */
+
+#define __arch__swab64(x) ___arch__swab64(x)
+#define __arch__swab32(x) ___arch__swab32(x)
+
+#define __BYTEORDER_HAS_U64__
+
+#endif /* __GNUC__ */
+
+#include <linux/byteorder/little_endian.h>
+
+#endif /* _ASM_X86_BYTEORDER_H */
diff --git a/include/asm-x86/byteorder_32.h b/include/asm-x86/byteorder_32.h
deleted file mode 100644
index a45470a8b74a..000000000000
--- a/include/asm-x86/byteorder_32.h
+++ /dev/null
@@ -1,58 +0,0 @@
-#ifndef _I386_BYTEORDER_H
-#define _I386_BYTEORDER_H
-
-#include <asm/types.h>
-#include <linux/compiler.h>
-
-#ifdef __GNUC__
-
-/* For avoiding bswap on i386 */
-#ifdef __KERNEL__
-#endif
-
-static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
-{
-#ifdef CONFIG_X86_BSWAP
- __asm__("bswap %0" : "=r" (x) : "0" (x));
-#else
- __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */
- "rorl $16,%0\n\t" /* swap words */
- "xchgb %b0,%h0" /* swap higher bytes */
- :"=q" (x)
- : "0" (x));
-#endif
- return x;
-}
-
-static __inline__ __attribute_const__ __u64 ___arch__swab64(__u64 val)
-{
- union {
- struct { __u32 a,b; } s;
- __u64 u;
- } v;
- v.u = val;
-#ifdef CONFIG_X86_BSWAP
- asm("bswapl %0 ; bswapl %1 ; xchgl %0,%1"
- : "=r" (v.s.a), "=r" (v.s.b)
- : "0" (v.s.a), "1" (v.s.b));
-#else
- v.s.a = ___arch__swab32(v.s.a);
- v.s.b = ___arch__swab32(v.s.b);
- asm("xchgl %0,%1" : "=r" (v.s.a), "=r" (v.s.b) : "0" (v.s.a), "1" (v.s.b));
-#endif
- return v.u;
-}
-
-/* Do not define swab16. Gcc is smart enough to recognize "C" version and
- convert it into rotation or exhange. */
-
-#define __arch__swab64(x) ___arch__swab64(x)
-#define __arch__swab32(x) ___arch__swab32(x)
-
-#define __BYTEORDER_HAS_U64__
-
-#endif /* __GNUC__ */
-
-#include <linux/byteorder/little_endian.h>
-
-#endif /* _I386_BYTEORDER_H */
diff --git a/include/asm-x86/byteorder_64.h b/include/asm-x86/byteorder_64.h
deleted file mode 100644
index 5e86c868c75e..000000000000
--- a/include/asm-x86/byteorder_64.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef _X86_64_BYTEORDER_H
-#define _X86_64_BYTEORDER_H
-
-#include <asm/types.h>
-#include <linux/compiler.h>
-
-#ifdef __GNUC__
-
-static __inline__ __attribute_const__ __u64 ___arch__swab64(__u64 x)
-{
- __asm__("bswapq %0" : "=r" (x) : "0" (x));
- return x;
-}
-
-static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
-{
- __asm__("bswapl %0" : "=r" (x) : "0" (x));
- return x;
-}
-
-/* Do not define swab16. Gcc is smart enough to recognize "C" version and
- convert it into rotation or exhange. */
-
-#define __arch__swab32(x) ___arch__swab32(x)
-#define __arch__swab64(x) ___arch__swab64(x)
-
-#endif /* __GNUC__ */
-
-#define __BYTEORDER_HAS_U64__
-
-#include <linux/byteorder/little_endian.h>
-
-#endif /* _X86_64_BYTEORDER_H */
diff --git a/include/asm-x86/cache.h b/include/asm-x86/cache.h
index c36d190ac9d8..1e0bac86f38f 100644
--- a/include/asm-x86/cache.h
+++ b/include/asm-x86/cache.h
@@ -1,5 +1,20 @@
-#ifdef CONFIG_X86_32
-# include "cache_32.h"
-#else
-# include "cache_64.h"
+#ifndef _ARCH_X86_CACHE_H
+#define _ARCH_X86_CACHE_H
+
+/* L1 cache line size */
+#define L1_CACHE_SHIFT (CONFIG_X86_L1_CACHE_SHIFT)
+#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
+
+#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+
+#ifdef CONFIG_X86_VSMP
+/* vSMP Internode cacheline shift */
+#define INTERNODE_CACHE_SHIFT (12)
+#ifdef CONFIG_SMP
+#define __cacheline_aligned_in_smp \
+ __attribute__((__aligned__(1 << (INTERNODE_CACHE_SHIFT)))) \
+ __attribute__((__section__(".data.page_aligned")))
+#endif
+#endif
+
#endif
diff --git a/include/asm-x86/cache_32.h b/include/asm-x86/cache_32.h
deleted file mode 100644
index 57c62f414158..000000000000
--- a/include/asm-x86/cache_32.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * include/asm-i386/cache.h
- */
-#ifndef __ARCH_I386_CACHE_H
-#define __ARCH_I386_CACHE_H
-
-
-/* L1 cache line size */
-#define L1_CACHE_SHIFT (CONFIG_X86_L1_CACHE_SHIFT)
-#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
-
-#define __read_mostly __attribute__((__section__(".data.read_mostly")))
-
-#endif
diff --git a/include/asm-x86/cache_64.h b/include/asm-x86/cache_64.h
deleted file mode 100644
index 052df758ae61..000000000000
--- a/include/asm-x86/cache_64.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * include/asm-x86_64/cache.h
- */
-#ifndef __ARCH_X8664_CACHE_H
-#define __ARCH_X8664_CACHE_H
-
-
-/* L1 cache line size */
-#define L1_CACHE_SHIFT (CONFIG_X86_L1_CACHE_SHIFT)
-#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
-
-#ifdef CONFIG_X86_VSMP
-
-/* vSMP Internode cacheline shift */
-#define INTERNODE_CACHE_SHIFT (12)
-#ifdef CONFIG_SMP
-#define __cacheline_aligned_in_smp \
- __attribute__((__aligned__(1 << (INTERNODE_CACHE_SHIFT)))) \
- __attribute__((__section__(".data.page_aligned")))
-#endif
-
-#endif
-
-#define __read_mostly __attribute__((__section__(".data.read_mostly")))
-
-#endif
diff --git a/include/asm-x86/cacheflush.h b/include/asm-x86/cacheflush.h
index e2df3b55034a..9411a2d3f19c 100644
--- a/include/asm-x86/cacheflush.h
+++ b/include/asm-x86/cacheflush.h
@@ -1,5 +1,41 @@
-#ifdef CONFIG_X86_32
-# include "cacheflush_32.h"
-#else
-# include "cacheflush_64.h"
+#ifndef _ASM_X86_CACHEFLUSH_H
+#define _ASM_X86_CACHEFLUSH_H
+
+/* Keep includes the same across arches. */
+#include <linux/mm.h>
+
+/* Caches aren't brain-dead on the intel. */
+#define flush_cache_all() do { } while (0)
+#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_dup_mm(mm) do { } while (0)
+#define flush_cache_range(vma, start, end) do { } while (0)
+#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
+#define flush_dcache_page(page) do { } while (0)
+#define flush_dcache_mmap_lock(mapping) do { } while (0)
+#define flush_dcache_mmap_unlock(mapping) do { } while (0)
+#define flush_icache_range(start, end) do { } while (0)
+#define flush_icache_page(vma,pg) do { } while (0)
+#define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
+#define flush_cache_vmap(start, end) do { } while (0)
+#define flush_cache_vunmap(start, end) do { } while (0)
+
+#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
+ memcpy(dst, src, len)
+#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
+ memcpy(dst, src, len)
+
+void global_flush_tlb(void);
+int change_page_attr(struct page *page, int numpages, pgprot_t prot);
+int change_page_attr_addr(unsigned long addr, int numpages, pgprot_t prot);
+void clflush_cache_range(void *addr, int size);
+
+#ifdef CONFIG_DEBUG_PAGEALLOC
+/* internal debugging function */
+void kernel_map_pages(struct page *page, int numpages, int enable);
+#endif
+
+#ifdef CONFIG_DEBUG_RODATA
+void mark_rodata_ro(void);
+#endif
+
#endif
diff --git a/include/asm-x86/cacheflush_32.h b/include/asm-x86/cacheflush_32.h
deleted file mode 100644
index 74e03c8f2e51..000000000000
--- a/include/asm-x86/cacheflush_32.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef _I386_CACHEFLUSH_H
-#define _I386_CACHEFLUSH_H
-
-/* Keep includes the same across arches. */
-#include <linux/mm.h>
-
-/* Caches aren't brain-dead on the intel. */
-#define flush_cache_all() do { } while (0)
-#define flush_cache_mm(mm) do { } while (0)
-#define flush_cache_dup_mm(mm) do { } while (0)
-#define flush_cache_range(vma, start, end) do { } while (0)
-#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
-#define flush_dcache_page(page) do { } while (0)
-#define flush_dcache_mmap_lock(mapping) do { } while (0)
-#define flush_dcache_mmap_unlock(mapping) do { } while (0)
-#define flush_icache_range(start, end) do { } while (0)
-#define flush_icache_page(vma,pg) do { } while (0)
-#define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
-#define flush_cache_vmap(start, end) do { } while (0)
-#define flush_cache_vunmap(start, end) do { } while (0)
-
-#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
- memcpy(dst, src, len)
-#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
- memcpy(dst, src, len)
-
-void global_flush_tlb(void);
-int change_page_attr(struct page *page, int numpages, pgprot_t prot);
-
-#ifdef CONFIG_DEBUG_PAGEALLOC
-/* internal debugging function */
-void kernel_map_pages(struct page *page, int numpages, int enable);
-#endif
-
-#ifdef CONFIG_DEBUG_RODATA
-void mark_rodata_ro(void);
-#endif
-
-#endif /* _I386_CACHEFLUSH_H */
diff --git a/include/asm-x86/cacheflush_64.h b/include/asm-x86/cacheflush_64.h
deleted file mode 100644
index ab1cb5c7dc92..000000000000
--- a/include/asm-x86/cacheflush_64.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef _X8664_CACHEFLUSH_H
-#define _X8664_CACHEFLUSH_H
-
-/* Keep includes the same across arches. */
-#include <linux/mm.h>
-
-/* Caches aren't brain-dead on the intel. */
-#define flush_cache_all() do { } while (0)
-#define flush_cache_mm(mm) do { } while (0)
-#define flush_cache_dup_mm(mm) do { } while (0)
-#define flush_cache_range(vma, start, end) do { } while (0)
-#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
-#define flush_dcache_page(page) do { } while (0)
-#define flush_dcache_mmap_lock(mapping) do { } while (0)
-#define flush_dcache_mmap_unlock(mapping) do { } while (0)
-#define flush_icache_range(start, end) do { } while (0)
-#define flush_icache_page(vma,pg) do { } while (0)
-#define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
-#define flush_cache_vmap(start, end) do { } while (0)
-#define flush_cache_vunmap(start, end) do { } while (0)
-
-#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
- memcpy(dst, src, len)
-#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
- memcpy(dst, src, len)
-
-void global_flush_tlb(void);
-int change_page_attr(struct page *page, int numpages, pgprot_t prot);
-int change_page_attr_addr(unsigned long addr, int numpages, pgprot_t prot);
-
-#ifdef CONFIG_DEBUG_RODATA
-void mark_rodata_ro(void);
-#endif
-
-#endif /* _X8664_CACHEFLUSH_H */
diff --git a/include/asm-x86/compat.h b/include/asm-x86/compat.h
index 53cb96b68a62..66ba7987184a 100644
--- a/include/asm-x86/compat.h
+++ b/include/asm-x86/compat.h
@@ -6,6 +6,7 @@
*/
#include <linux/types.h>
#include <linux/sched.h>
+#include <asm/user32.h>
#define COMPAT_USER_HZ 100
@@ -181,6 +182,11 @@ struct compat_shmid64_ds {
};
/*
+ * The type of struct elf_prstatus.pr_reg in compatible core dumps.
+ */
+typedef struct user_regs_struct32 compat_elf_gregset_t;
+
+/*
* A pointer passed in from user mode. This should not
* be used for syscall parameters, just declare them
* as pointers because the syscall entry code will have
diff --git a/include/asm-x86/cpu.h b/include/asm-x86/cpu.h
index 9d914e1e4aad..b1bc7b1b64b0 100644
--- a/include/asm-x86/cpu.h
+++ b/include/asm-x86/cpu.h
@@ -13,9 +13,6 @@ struct i386_cpu {
extern int arch_register_cpu(int num);
#ifdef CONFIG_HOTPLUG_CPU
extern void arch_unregister_cpu(int);
-extern int enable_cpu_hotplug;
-#else
-#define enable_cpu_hotplug 0
#endif
DECLARE_PER_CPU(int, cpu_state);
diff --git a/include/asm-x86/cpufeature_32.h b/include/asm-x86/cpufeature_32.h
index 7b3aa28ebc6e..f17e688dfb05 100644
--- a/include/asm-x86/cpufeature_32.h
+++ b/include/asm-x86/cpufeature_32.h
@@ -92,6 +92,7 @@
#define X86_FEATURE_CID (4*32+10) /* Context ID */
#define X86_FEATURE_CX16 (4*32+13) /* CMPXCHG16B */
#define X86_FEATURE_XTPR (4*32+14) /* Send Task Priority Messages */
+#define X86_FEATURE_DCA (4*32+18) /* Direct Cache Access */
/* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */
#define X86_FEATURE_XSTORE (5*32+ 2) /* on-CPU RNG present (xstore insn) */
diff --git a/include/asm-x86/cputime.h b/include/asm-x86/cputime.h
index 87c37cf6b707..6d68ad7e0ea3 100644
--- a/include/asm-x86/cputime.h
+++ b/include/asm-x86/cputime.h
@@ -1,5 +1 @@
-#ifdef CONFIG_X86_32
-# include "cputime_32.h"
-#else
-# include "cputime_64.h"
-#endif
+#include <asm-generic/cputime.h>
diff --git a/include/asm-x86/cputime_32.h b/include/asm-x86/cputime_32.h
deleted file mode 100644
index 398ed7cd171d..000000000000
--- a/include/asm-x86/cputime_32.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __I386_CPUTIME_H
-#define __I386_CPUTIME_H
-
-#include <asm-generic/cputime.h>
-
-#endif /* __I386_CPUTIME_H */
diff --git a/include/asm-x86/cputime_64.h b/include/asm-x86/cputime_64.h
deleted file mode 100644
index a07012dc5a3c..000000000000
--- a/include/asm-x86/cputime_64.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __X86_64_CPUTIME_H
-#define __X86_64_CPUTIME_H
-
-#include <asm-generic/cputime.h>
-
-#endif /* __X86_64_CPUTIME_H */
diff --git a/include/asm-x86/debugreg.h b/include/asm-x86/debugreg.h
index b6ce7e4fa002..c6344d572b03 100644
--- a/include/asm-x86/debugreg.h
+++ b/include/asm-x86/debugreg.h
@@ -1,13 +1,70 @@
-#ifdef __KERNEL__
-# ifdef CONFIG_X86_32
-# include "debugreg_32.h"
-# else
-# include "debugreg_64.h"
-# endif
+#ifndef _ASM_X86_DEBUGREG_H
+#define _ASM_X86_DEBUGREG_H
+
+
+/* Indicate the register numbers for a number of the specific
+ debug registers. Registers 0-3 contain the addresses we wish to trap on */
+#define DR_FIRSTADDR 0 /* u_debugreg[DR_FIRSTADDR] */
+#define DR_LASTADDR 3 /* u_debugreg[DR_LASTADDR] */
+
+#define DR_STATUS 6 /* u_debugreg[DR_STATUS] */
+#define DR_CONTROL 7 /* u_debugreg[DR_CONTROL] */
+
+/* Define a few things for the status register. We can use this to determine
+ which debugging register was responsible for the trap. The other bits
+ are either reserved or not of interest to us. */
+
+#define DR_TRAP0 (0x1) /* db0 */
+#define DR_TRAP1 (0x2) /* db1 */
+#define DR_TRAP2 (0x4) /* db2 */
+#define DR_TRAP3 (0x8) /* db3 */
+
+#define DR_STEP (0x4000) /* single-step */
+#define DR_SWITCH (0x8000) /* task switch */
+
+/* Now define a bunch of things for manipulating the control register.
+ The top two bytes of the control register consist of 4 fields of 4
+ bits - each field corresponds to one of the four debug registers,
+ and indicates what types of access we trap on, and how large the data
+ field is that we are looking at */
+
+#define DR_CONTROL_SHIFT 16 /* Skip this many bits in ctl register */
+#define DR_CONTROL_SIZE 4 /* 4 control bits per register */
+
+#define DR_RW_EXECUTE (0x0) /* Settings for the access types to trap on */
+#define DR_RW_WRITE (0x1)
+#define DR_RW_READ (0x3)
+
+#define DR_LEN_1 (0x0) /* Settings for data length to trap on */
+#define DR_LEN_2 (0x4)
+#define DR_LEN_4 (0xC)
+#define DR_LEN_8 (0x8)
+
+/* The low byte to the control register determine which registers are
+ enabled. There are 4 fields of two bits. One bit is "local", meaning
+ that the processor will reset the bit after a task switch and the other
+ is global meaning that we have to explicitly reset the bit. With linux,
+ you can use either one, since we explicitly zero the register when we enter
+ kernel mode. */
+
+#define DR_LOCAL_ENABLE_SHIFT 0 /* Extra shift to the local enable bit */
+#define DR_GLOBAL_ENABLE_SHIFT 1 /* Extra shift to the global enable bit */
+#define DR_ENABLE_SIZE 2 /* 2 enable bits per register */
+
+#define DR_LOCAL_ENABLE_MASK (0x55) /* Set local bits for all 4 regs */
+#define DR_GLOBAL_ENABLE_MASK (0xAA) /* Set global bits for all 4 regs */
+
+/* The second byte to the control register has a few special things.
+ We can slow the instruction pipeline for instructions coming via the
+ gdt or the ldt if we want to. I am not sure why this is an advantage */
+
+#ifdef __i386__
+#define DR_CONTROL_RESERVED (0xFC00) /* Reserved by Intel */
#else
-# ifdef __i386__
-# include "debugreg_32.h"
-# else
-# include "debugreg_64.h"
-# endif
+#define DR_CONTROL_RESERVED (0xFFFFFFFF0000FC00UL) /* Reserved */
+#endif
+
+#define DR_LOCAL_SLOWDOWN (0x100) /* Local slow the pipeline */
+#define DR_GLOBAL_SLOWDOWN (0x200) /* Global slow the pipeline */
+
#endif
diff --git a/include/asm-x86/debugreg_32.h b/include/asm-x86/debugreg_32.h
deleted file mode 100644
index f0b2b06ae0f7..000000000000
--- a/include/asm-x86/debugreg_32.h
+++ /dev/null
@@ -1,64 +0,0 @@
-#ifndef _I386_DEBUGREG_H
-#define _I386_DEBUGREG_H
-
-
-/* Indicate the register numbers for a number of the specific
- debug registers. Registers 0-3 contain the addresses we wish to trap on */
-#define DR_FIRSTADDR 0 /* u_debugreg[DR_FIRSTADDR] */
-#define DR_LASTADDR 3 /* u_debugreg[DR_LASTADDR] */
-
-#define DR_STATUS 6 /* u_debugreg[DR_STATUS] */
-#define DR_CONTROL 7 /* u_debugreg[DR_CONTROL] */
-
-/* Define a few things for the status register. We can use this to determine
- which debugging register was responsible for the trap. The other bits
- are either reserved or not of interest to us. */
-
-#define DR_TRAP0 (0x1) /* db0 */
-#define DR_TRAP1 (0x2) /* db1 */
-#define DR_TRAP2 (0x4) /* db2 */
-#define DR_TRAP3 (0x8) /* db3 */
-
-#define DR_STEP (0x4000) /* single-step */
-#define DR_SWITCH (0x8000) /* task switch */
-
-/* Now define a bunch of things for manipulating the control register.
- The top two bytes of the control register consist of 4 fields of 4
- bits - each field corresponds to one of the four debug registers,
- and indicates what types of access we trap on, and how large the data
- field is that we are looking at */
-
-#define DR_CONTROL_SHIFT 16 /* Skip this many bits in ctl register */
-#define DR_CONTROL_SIZE 4 /* 4 control bits per register */
-
-#define DR_RW_EXECUTE (0x0) /* Settings for the access types to trap on */
-#define DR_RW_WRITE (0x1)
-#define DR_RW_READ (0x3)
-
-#define DR_LEN_1 (0x0) /* Settings for data length to trap on */
-#define DR_LEN_2 (0x4)
-#define DR_LEN_4 (0xC)
-
-/* The low byte to the control register determine which registers are
- enabled. There are 4 fields of two bits. One bit is "local", meaning
- that the processor will reset the bit after a task switch and the other
- is global meaning that we have to explicitly reset the bit. With linux,
- you can use either one, since we explicitly zero the register when we enter
- kernel mode. */
-
-#define DR_LOCAL_ENABLE_SHIFT 0 /* Extra shift to the local enable bit */
-#define DR_GLOBAL_ENABLE_SHIFT 1 /* Extra shift to the global enable bit */
-#define DR_ENABLE_SIZE 2 /* 2 enable bits per register */
-
-#define DR_LOCAL_ENABLE_MASK (0x55) /* Set local bits for all 4 regs */
-#define DR_GLOBAL_ENABLE_MASK (0xAA) /* Set global bits for all 4 regs */
-
-/* The second byte to the control register has a few special things.
- We can slow the instruction pipeline for instructions coming via the
- gdt or the ldt if we want to. I am not sure why this is an advantage */
-
-#define DR_CONTROL_RESERVED (0xFC00) /* Reserved by Intel */
-#define DR_LOCAL_SLOWDOWN (0x100) /* Local slow the pipeline */
-#define DR_GLOBAL_SLOWDOWN (0x200) /* Global slow the pipeline */
-
-#endif
diff --git a/include/asm-x86/debugreg_64.h b/include/asm-x86/debugreg_64.h
deleted file mode 100644
index bd1aab1d8c4a..000000000000
--- a/include/asm-x86/debugreg_64.h
+++ /dev/null
@@ -1,65 +0,0 @@
-#ifndef _X86_64_DEBUGREG_H
-#define _X86_64_DEBUGREG_H
-
-
-/* Indicate the register numbers for a number of the specific
- debug registers. Registers 0-3 contain the addresses we wish to trap on */
-#define DR_FIRSTADDR 0 /* u_debugreg[DR_FIRSTADDR] */
-#define DR_LASTADDR 3 /* u_debugreg[DR_LASTADDR] */
-
-#define DR_STATUS 6 /* u_debugreg[DR_STATUS] */
-#define DR_CONTROL 7 /* u_debugreg[DR_CONTROL] */
-
-/* Define a few things for the status register. We can use this to determine
- which debugging register was responsible for the trap. The other bits
- are either reserved or not of interest to us. */
-
-#define DR_TRAP0 (0x1) /* db0 */
-#define DR_TRAP1 (0x2) /* db1 */
-#define DR_TRAP2 (0x4) /* db2 */
-#define DR_TRAP3 (0x8) /* db3 */
-
-#define DR_STEP (0x4000) /* single-step */
-#define DR_SWITCH (0x8000) /* task switch */
-
-/* Now define a bunch of things for manipulating the control register.
- The top two bytes of the control register consist of 4 fields of 4
- bits - each field corresponds to one of the four debug registers,
- and indicates what types of access we trap on, and how large the data
- field is that we are looking at */
-
-#define DR_CONTROL_SHIFT 16 /* Skip this many bits in ctl register */
-#define DR_CONTROL_SIZE 4 /* 4 control bits per register */
-
-#define DR_RW_EXECUTE (0x0) /* Settings for the access types to trap on */
-#define DR_RW_WRITE (0x1)
-#define DR_RW_READ (0x3)
-
-#define DR_LEN_1 (0x0) /* Settings for data length to trap on */
-#define DR_LEN_2 (0x4)
-#define DR_LEN_4 (0xC)
-#define DR_LEN_8 (0x8)
-
-/* The low byte to the control register determine which registers are
- enabled. There are 4 fields of two bits. One bit is "local", meaning
- that the processor will reset the bit after a task switch and the other
- is global meaning that we have to explicitly reset the bit. With linux,
- you can use either one, since we explicitly zero the register when we enter
- kernel mode. */
-
-#define DR_LOCAL_ENABLE_SHIFT 0 /* Extra shift to the local enable bit */
-#define DR_GLOBAL_ENABLE_SHIFT 1 /* Extra shift to the global enable bit */
-#define DR_ENABLE_SIZE 2 /* 2 enable bits per register */
-
-#define DR_LOCAL_ENABLE_MASK (0x55) /* Set local bits for all 4 regs */
-#define DR_GLOBAL_ENABLE_MASK (0xAA) /* Set global bits for all 4 regs */
-
-/* The second byte to the control register has a few special things.
- We can slow the instruction pipeline for instructions coming via the
- gdt or the ldt if we want to. I am not sure why this is an advantage */
-
-#define DR_CONTROL_RESERVED (0xFFFFFFFF0000FC00UL) /* Reserved */
-#define DR_LOCAL_SLOWDOWN (0x100) /* Local slow the pipeline */
-#define DR_GLOBAL_SLOWDOWN (0x200) /* Global slow the pipeline */
-
-#endif
diff --git a/include/asm-x86/delay.h b/include/asm-x86/delay.h
index 10f2c71d622b..d11d47fc1a0e 100644
--- a/include/asm-x86/delay.h
+++ b/include/asm-x86/delay.h
@@ -1,5 +1,31 @@
-#ifdef CONFIG_X86_32
-# include "delay_32.h"
-#else
-# include "delay_64.h"
-#endif
+#ifndef _ASM_X86_DELAY_H
+#define _ASM_X86_DELAY_H
+
+/*
+ * Copyright (C) 1993 Linus Torvalds
+ *
+ * Delay routines calling functions in arch/x86/lib/delay.c
+ */
+
+/* Undefined functions to get compile-time errors */
+extern void __bad_udelay(void);
+extern void __bad_ndelay(void);
+
+extern void __udelay(unsigned long usecs);
+extern void __ndelay(unsigned long nsecs);
+extern void __const_udelay(unsigned long usecs);
+extern void __delay(unsigned long loops);
+
+/* 0x10c7 is 2**32 / 1000000 (rounded up) */
+#define udelay(n) (__builtin_constant_p(n) ? \
+ ((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c7ul)) : \
+ __udelay(n))
+
+/* 0x5 is 2**32 / 1000000000 (rounded up) */
+#define ndelay(n) (__builtin_constant_p(n) ? \
+ ((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
+ __ndelay(n))
+
+void use_tsc_delay(void);
+
+#endif /* _ASM_X86_DELAY_H */
diff --git a/include/asm-x86/delay_32.h b/include/asm-x86/delay_32.h
deleted file mode 100644
index 9ae5e3782ed8..000000000000
--- a/include/asm-x86/delay_32.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef _I386_DELAY_H
-#define _I386_DELAY_H
-
-/*
- * Copyright (C) 1993 Linus Torvalds
- *
- * Delay routines calling functions in arch/i386/lib/delay.c
- */
-
-/* Undefined functions to get compile-time errors */
-extern void __bad_udelay(void);
-extern void __bad_ndelay(void);
-
-extern void __udelay(unsigned long usecs);
-extern void __ndelay(unsigned long nsecs);
-extern void __const_udelay(unsigned long usecs);
-extern void __delay(unsigned long loops);
-
-/* 0x10c7 is 2**32 / 1000000 (rounded up) */
-#define udelay(n) (__builtin_constant_p(n) ? \
- ((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c7ul)) : \
- __udelay(n))
-
-/* 0x5 is 2**32 / 1000000000 (rounded up) */
-#define ndelay(n) (__builtin_constant_p(n) ? \
- ((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
- __ndelay(n))
-
-void use_tsc_delay(void);
-
-#endif /* defined(_I386_DELAY_H) */
diff --git a/include/asm-x86/delay_64.h b/include/asm-x86/delay_64.h
deleted file mode 100644
index c2669f1f5529..000000000000
--- a/include/asm-x86/delay_64.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef _X8664_DELAY_H
-#define _X8664_DELAY_H
-
-/*
- * Copyright (C) 1993 Linus Torvalds
- *
- * Delay routines calling functions in arch/x86_64/lib/delay.c
- */
-
-/* Undefined functions to get compile-time errors */
-extern void __bad_udelay(void);
-extern void __bad_ndelay(void);
-
-extern void __udelay(unsigned long usecs);
-extern void __ndelay(unsigned long nsecs);
-extern void __const_udelay(unsigned long usecs);
-extern void __delay(unsigned long loops);
-
-/* 0x10c7 is 2**32 / 1000000 (rounded up) */
-#define udelay(n) (__builtin_constant_p(n) ? \
- ((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c7ul)) : \
- __udelay(n))
-
-/* 0x5 is 2**32 / 1000000000 (rounded up) */
-#define ndelay(n) (__builtin_constant_p(n) ? \
- ((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
- __ndelay(n))
-
-
-#endif /* defined(_X8664_DELAY_H) */
diff --git a/include/asm-x86/desc_64.h b/include/asm-x86/desc_64.h
index ac991b5ca0fd..7d9c938e69fd 100644
--- a/include/asm-x86/desc_64.h
+++ b/include/asm-x86/desc_64.h
@@ -20,6 +20,16 @@ extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
#define load_LDT_desc() asm volatile("lldt %w0"::"r" (GDT_ENTRY_LDT*8))
#define clear_LDT() asm volatile("lldt %w0"::"r" (0))
+static inline unsigned long __store_tr(void)
+{
+ unsigned long tr;
+
+ asm volatile ("str %w0":"=r" (tr));
+ return tr;
+}
+
+#define store_tr(tr) (tr) = __store_tr()
+
/*
* This is the ldt that every process will get unless we need
* something other than this.
@@ -31,6 +41,16 @@ extern struct desc_ptr cpu_gdt_descr[];
/* the cpu gdt accessor */
#define cpu_gdt(_cpu) ((struct desc_struct *)cpu_gdt_descr[_cpu].address)
+static inline void load_gdt(const struct desc_ptr *ptr)
+{
+ asm volatile("lgdt %w0"::"m" (*ptr));
+}
+
+static inline void store_gdt(struct desc_ptr *ptr)
+{
+ asm("sgdt %w0":"=m" (*ptr));
+}
+
static inline void _set_gate(void *adr, unsigned type, unsigned long func, unsigned dpl, unsigned ist)
{
struct gate_struct s;
@@ -71,6 +91,16 @@ static inline void set_system_gate_ist(int nr, void *func, unsigned ist)
_set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 3, ist);
}
+static inline void load_idt(const struct desc_ptr *ptr)
+{
+ asm volatile("lidt %w0"::"m" (*ptr));
+}
+
+static inline void store_idt(struct desc_ptr *dtr)
+{
+ asm("sidt %w0":"=m" (*dtr));
+}
+
static inline void set_tssldt_descriptor(void *ptr, unsigned long tss, unsigned type,
unsigned size)
{
diff --git a/include/asm-x86/device.h b/include/asm-x86/device.h
index e2bcf7c7dcee..87a715367a1b 100644
--- a/include/asm-x86/device.h
+++ b/include/asm-x86/device.h
@@ -1,5 +1,13 @@
-#ifdef CONFIG_X86_32
-# include "device_32.h"
-#else
-# include "device_64.h"
+#ifndef _ASM_X86_DEVICE_H
+#define _ASM_X86_DEVICE_H
+
+struct dev_archdata {
+#ifdef CONFIG_ACPI
+ void *acpi_handle;
#endif
+#ifdef CONFIG_DMAR
+ void *iommu; /* hook for IOMMU specific extension */
+#endif
+};
+
+#endif /* _ASM_X86_DEVICE_H */
diff --git a/include/asm-x86/device_32.h b/include/asm-x86/device_32.h
deleted file mode 100644
index 849604c70e6b..000000000000
--- a/include/asm-x86/device_32.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Arch specific extensions to struct device
- *
- * This file is released under the GPLv2
- */
-#ifndef _ASM_I386_DEVICE_H
-#define _ASM_I386_DEVICE_H
-
-struct dev_archdata {
-#ifdef CONFIG_ACPI
- void *acpi_handle;
-#endif
-};
-
-#endif /* _ASM_I386_DEVICE_H */
diff --git a/include/asm-x86/device_64.h b/include/asm-x86/device_64.h
deleted file mode 100644
index 3afa03f33a36..000000000000
--- a/include/asm-x86/device_64.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Arch specific extensions to struct device
- *
- * This file is released under the GPLv2
- */
-#ifndef _ASM_X86_64_DEVICE_H
-#define _ASM_X86_64_DEVICE_H
-
-struct dev_archdata {
-#ifdef CONFIG_ACPI
- void *acpi_handle;
-#endif
-};
-
-#endif /* _ASM_X86_64_DEVICE_H */
diff --git a/include/asm-x86/div64.h b/include/asm-x86/div64.h
index 8ac7da6ca284..e98d16e7a37a 100644
--- a/include/asm-x86/div64.h
+++ b/include/asm-x86/div64.h
@@ -1,5 +1,59 @@
+#ifndef _ASM_X86_DIV64_H
+#define _ASM_X86_DIV64_H
+
#ifdef CONFIG_X86_32
-# include "div64_32.h"
+
+#include <linux/types.h>
+
+/*
+ * do_div() is NOT a C function. It wants to return
+ * two values (the quotient and the remainder), but
+ * since that doesn't work very well in C, what it
+ * does is:
+ *
+ * - modifies the 64-bit dividend _in_place_
+ * - returns the 32-bit remainder
+ *
+ * This ends up being the most efficient "calling
+ * convention" on x86.
+ */
+#define do_div(n,base) ({ \
+ unsigned long __upper, __low, __high, __mod, __base; \
+ __base = (base); \
+ asm("":"=a" (__low), "=d" (__high):"A" (n)); \
+ __upper = __high; \
+ if (__high) { \
+ __upper = __high % (__base); \
+ __high = __high / (__base); \
+ } \
+ asm("divl %2":"=a" (__low), "=d" (__mod):"rm" (__base), "0" (__low), "1" (__upper)); \
+ asm("":"=A" (n):"a" (__low),"d" (__high)); \
+ __mod; \
+})
+
+/*
+ * (long)X = ((long long)divs) / (long)div
+ * (long)rem = ((long long)divs) % (long)div
+ *
+ * Warning, this will do an exception if X overflows.
+ */
+#define div_long_long_rem(a,b,c) div_ll_X_l_rem(a,b,c)
+
+static inline long
+div_ll_X_l_rem(long long divs, long div, long *rem)
+{
+ long dum2;
+ __asm__("divl %2":"=a"(dum2), "=d"(*rem)
+ : "rm"(div), "A"(divs));
+
+ return dum2;
+
+}
+
+extern uint64_t div64_64(uint64_t dividend, uint64_t divisor);
+
#else
-# include "div64_64.h"
-#endif
+# include <asm-generic/div64.h>
+#endif /* CONFIG_X86_32 */
+
+#endif /* _ASM_X86_DIV64_H */
diff --git a/include/asm-x86/div64_32.h b/include/asm-x86/div64_32.h
deleted file mode 100644
index 438e980068bd..000000000000
--- a/include/asm-x86/div64_32.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#ifndef __I386_DIV64
-#define __I386_DIV64
-
-#include <linux/types.h>
-
-/*
- * do_div() is NOT a C function. It wants to return
- * two values (the quotient and the remainder), but
- * since that doesn't work very well in C, what it
- * does is:
- *
- * - modifies the 64-bit dividend _in_place_
- * - returns the 32-bit remainder
- *
- * This ends up being the most efficient "calling
- * convention" on x86.
- */
-#define do_div(n,base) ({ \
- unsigned long __upper, __low, __high, __mod, __base; \
- __base = (base); \
- asm("":"=a" (__low), "=d" (__high):"A" (n)); \
- __upper = __high; \
- if (__high) { \
- __upper = __high % (__base); \
- __high = __high / (__base); \
- } \
- asm("divl %2":"=a" (__low), "=d" (__mod):"rm" (__base), "0" (__low), "1" (__upper)); \
- asm("":"=A" (n):"a" (__low),"d" (__high)); \
- __mod; \
-})
-
-/*
- * (long)X = ((long long)divs) / (long)div
- * (long)rem = ((long long)divs) % (long)div
- *
- * Warning, this will do an exception if X overflows.
- */
-#define div_long_long_rem(a,b,c) div_ll_X_l_rem(a,b,c)
-
-static inline long
-div_ll_X_l_rem(long long divs, long div, long *rem)
-{
- long dum2;
- __asm__("divl %2":"=a"(dum2), "=d"(*rem)
- : "rm"(div), "A"(divs));
-
- return dum2;
-
-}
-
-extern uint64_t div64_64(uint64_t dividend, uint64_t divisor);
-#endif
diff --git a/include/asm-x86/div64_64.h b/include/asm-x86/div64_64.h
deleted file mode 100644
index 6cd978cefb28..000000000000
--- a/include/asm-x86/div64_64.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/div64.h>
diff --git a/include/asm-x86/dma-mapping_32.h b/include/asm-x86/dma-mapping_32.h
index f1d72d177f68..55f01bd9e556 100644
--- a/include/asm-x86/dma-mapping_32.h
+++ b/include/asm-x86/dma-mapping_32.h
@@ -2,10 +2,10 @@
#define _ASM_I386_DMA_MAPPING_H
#include <linux/mm.h>
+#include <linux/scatterlist.h>
#include <asm/cache.h>
#include <asm/io.h>
-#include <asm/scatterlist.h>
#include <asm/bug.h>
#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
@@ -35,18 +35,19 @@ dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
}
static inline int
-dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+dma_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
enum dma_data_direction direction)
{
+ struct scatterlist *sg;
int i;
BUG_ON(!valid_dma_direction(direction));
- WARN_ON(nents == 0 || sg[0].length == 0);
+ WARN_ON(nents == 0 || sglist[0].length == 0);
- for (i = 0; i < nents; i++ ) {
- BUG_ON(!sg[i].page);
+ for_each_sg(sglist, sg, nents, i) {
+ BUG_ON(!sg_page(sg));
- sg[i].dma_address = page_to_phys(sg[i].page) + sg[i].offset;
+ sg->dma_address = sg_phys(sg);
}
flush_write_buffers();
diff --git a/include/asm-x86/dma-mapping_64.h b/include/asm-x86/dma-mapping_64.h
index 6897e2a436e5..ecd0f6125ba3 100644
--- a/include/asm-x86/dma-mapping_64.h
+++ b/include/asm-x86/dma-mapping_64.h
@@ -6,8 +6,7 @@
* documentation.
*/
-
-#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
#include <asm/io.h>
#include <asm/swiotlb.h>
diff --git a/include/asm-x86/dmi.h b/include/asm-x86/dmi.h
index c9e4e8ebc270..8e2b0e6aa8e7 100644
--- a/include/asm-x86/dmi.h
+++ b/include/asm-x86/dmi.h
@@ -1,5 +1,35 @@
+#ifndef _ASM_X86_DMI_H
+#define _ASM_X86_DMI_H
+
+#include <asm/io.h>
+
#ifdef CONFIG_X86_32
-# include "dmi_32.h"
-#else
-# include "dmi_64.h"
+
+/* Use early IO mappings for DMI because it's initialized early */
+#define dmi_ioremap bt_ioremap
+#define dmi_iounmap bt_iounmap
+#define dmi_alloc alloc_bootmem
+
+#else /* CONFIG_X86_32 */
+
+#define DMI_MAX_DATA 2048
+
+extern int dmi_alloc_index;
+extern char dmi_alloc_data[DMI_MAX_DATA];
+
+/* This is so early that there is no good way to allocate dynamic memory.
+ Allocate data in an BSS array. */
+static inline void *dmi_alloc(unsigned len)
+{
+ int idx = dmi_alloc_index;
+ if ((dmi_alloc_index += len) > DMI_MAX_DATA)
+ return NULL;
+ return dmi_alloc_data + idx;
+}
+
+#define dmi_ioremap early_ioremap
+#define dmi_iounmap early_iounmap
+
+#endif
+
#endif
diff --git a/include/asm-x86/dmi_32.h b/include/asm-x86/dmi_32.h
deleted file mode 100644
index 38d4eeb7fc7e..000000000000
--- a/include/asm-x86/dmi_32.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef _ASM_DMI_H
-#define _ASM_DMI_H 1
-
-#include <asm/io.h>
-
-/* Use early IO mappings for DMI because it's initialized early */
-#define dmi_ioremap bt_ioremap
-#define dmi_iounmap bt_iounmap
-#define dmi_alloc alloc_bootmem
-
-#endif
diff --git a/include/asm-x86/dmi_64.h b/include/asm-x86/dmi_64.h
deleted file mode 100644
index d02e32e3c3f0..000000000000
--- a/include/asm-x86/dmi_64.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef _ASM_DMI_H
-#define _ASM_DMI_H 1
-
-#include <asm/io.h>
-
-#define DMI_MAX_DATA 2048
-
-extern int dmi_alloc_index;
-extern char dmi_alloc_data[DMI_MAX_DATA];
-
-/* This is so early that there is no good way to allocate dynamic memory.
- Allocate data in an BSS array. */
-static inline void *dmi_alloc(unsigned len)
-{
- int idx = dmi_alloc_index;
- if ((dmi_alloc_index += len) > DMI_MAX_DATA)
- return NULL;
- return dmi_alloc_data + idx;
-}
-
-#define dmi_ioremap early_ioremap
-#define dmi_iounmap early_iounmap
-
-#endif
diff --git a/include/asm-x86/e820.h b/include/asm-x86/e820.h
index 5d4d2183e5db..3e214f39fad3 100644
--- a/include/asm-x86/e820.h
+++ b/include/asm-x86/e820.h
@@ -1,5 +1,33 @@
+#ifndef __ASM_E820_H
+#define __ASM_E820_H
+#define E820MAP 0x2d0 /* our map */
+#define E820MAX 128 /* number of entries in E820MAP */
+#define E820NR 0x1e8 /* # entries in E820MAP */
+
+#define E820_RAM 1
+#define E820_RESERVED 2
+#define E820_ACPI 3
+#define E820_NVS 4
+
+#ifndef __ASSEMBLY__
+struct e820entry {
+ __u64 addr; /* start of memory segment */
+ __u64 size; /* size of memory segment */
+ __u32 type; /* type of memory segment */
+} __attribute__((packed));
+
+struct e820map {
+ __u32 nr_map;
+ struct e820entry map[E820MAX];
+};
+#endif /* __ASSEMBLY__ */
+
+#ifdef __KERNEL__
#ifdef CONFIG_X86_32
# include "e820_32.h"
#else
# include "e820_64.h"
#endif
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_E820_H */
diff --git a/include/asm-x86/e820_32.h b/include/asm-x86/e820_32.h
index cf67dbb1db79..03f60c690c8a 100644
--- a/include/asm-x86/e820_32.h
+++ b/include/asm-x86/e820_32.h
@@ -12,30 +12,10 @@
#ifndef __E820_HEADER
#define __E820_HEADER
-#define E820MAP 0x2d0 /* our map */
-#define E820MAX 128 /* number of entries in E820MAP */
-#define E820NR 0x1e8 /* # entries in E820MAP */
-
-#define E820_RAM 1
-#define E820_RESERVED 2
-#define E820_ACPI 3
-#define E820_NVS 4
-
#define HIGH_MEMORY (1024*1024)
#ifndef __ASSEMBLY__
-struct e820entry {
- u64 addr; /* start of memory segment */
- u64 size; /* size of memory segment */
- u32 type; /* type of memory segment */
-} __attribute__((packed));
-
-struct e820map {
- u32 nr_map;
- struct e820entry map[E820MAX];
-};
-
extern struct e820map e820;
extern int e820_all_mapped(unsigned long start, unsigned long end,
@@ -56,5 +36,4 @@ static inline void e820_mark_nosave_regions(void)
#endif
#endif/*!__ASSEMBLY__*/
-
#endif/*__E820_HEADER*/
diff --git a/include/asm-x86/e820_64.h b/include/asm-x86/e820_64.h
index 3486e701bd86..0bd4787a5d57 100644
--- a/include/asm-x86/e820_64.h
+++ b/include/asm-x86/e820_64.h
@@ -11,27 +11,7 @@
#ifndef __E820_HEADER
#define __E820_HEADER
-#define E820MAP 0x2d0 /* our map */
-#define E820MAX 128 /* number of entries in E820MAP */
-#define E820NR 0x1e8 /* # entries in E820MAP */
-
-#define E820_RAM 1
-#define E820_RESERVED 2
-#define E820_ACPI 3
-#define E820_NVS 4
-
#ifndef __ASSEMBLY__
-struct e820entry {
- u64 addr; /* start of memory segment */
- u64 size; /* size of memory segment */
- u32 type; /* type of memory segment */
-} __attribute__((packed));
-
-struct e820map {
- u32 nr_map;
- struct e820entry map[E820MAX];
-};
-
extern unsigned long find_e820_area(unsigned long start, unsigned long end,
unsigned size);
extern void add_memory_region(unsigned long start, unsigned long size,
diff --git a/include/asm-x86/edac.h b/include/asm-x86/edac.h
index f8b888e140b0..cf3200a745ad 100644
--- a/include/asm-x86/edac.h
+++ b/include/asm-x86/edac.h
@@ -1,5 +1,18 @@
-#ifdef CONFIG_X86_32
-# include "edac_32.h"
-#else
-# include "edac_64.h"
+#ifndef _ASM_X86_EDAC_H
+#define _ASM_X86_EDAC_H
+
+/* ECC atomic, DMA, SMP and interrupt safe scrub function */
+
+static __inline__ void atomic_scrub(void *va, u32 size)
+{
+ u32 i, *virt_addr = va;
+
+ /*
+ * Very carefully read and write to memory atomically so we
+ * are interrupt, DMA and SMP safe.
+ */
+ for (i = 0; i < size / 4; i++, virt_addr++)
+ __asm__ __volatile__("lock; addl $0, %0"::"m"(*virt_addr));
+}
+
#endif
diff --git a/include/asm-x86/edac_32.h b/include/asm-x86/edac_32.h
deleted file mode 100644
index 3e7dd0ab68ce..000000000000
--- a/include/asm-x86/edac_32.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef ASM_EDAC_H
-#define ASM_EDAC_H
-
-/* ECC atomic, DMA, SMP and interrupt safe scrub function */
-
-static __inline__ void atomic_scrub(void *va, u32 size)
-{
- unsigned long *virt_addr = va;
- u32 i;
-
- for (i = 0; i < size / 4; i++, virt_addr++)
- /* Very carefully read and write to memory atomically
- * so we are interrupt, DMA and SMP safe.
- */
- __asm__ __volatile__("lock; addl $0, %0"::"m"(*virt_addr));
-}
-
-#endif
diff --git a/include/asm-x86/edac_64.h b/include/asm-x86/edac_64.h
deleted file mode 100644
index cad1cd42b4ee..000000000000
--- a/include/asm-x86/edac_64.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef ASM_EDAC_H
-#define ASM_EDAC_H
-
-/* ECC atomic, DMA, SMP and interrupt safe scrub function */
-
-static __inline__ void atomic_scrub(void *va, u32 size)
-{
- unsigned int *virt_addr = va;
- u32 i;
-
- for (i = 0; i < size / 4; i++, virt_addr++)
- /* Very carefully read and write to memory atomically
- * so we are interrupt, DMA and SMP safe.
- */
- __asm__ __volatile__("lock; addl $0, %0"::"m"(*virt_addr));
-}
-
-#endif
diff --git a/include/asm-x86/elf.h b/include/asm-x86/elf.h
index ed6bb6e546b9..ec42a4d2e83b 100644
--- a/include/asm-x86/elf.h
+++ b/include/asm-x86/elf.h
@@ -1,13 +1,290 @@
-#ifdef __KERNEL__
-# ifdef CONFIG_X86_32
-# include "elf_32.h"
-# else
-# include "elf_64.h"
-# endif
+#ifndef _ASM_X86_ELF_H
+#define _ASM_X86_ELF_H
+
+/*
+ * ELF register definitions..
+ */
+
+#include <asm/ptrace.h>
+#include <asm/user.h>
+#include <asm/auxvec.h>
+
+typedef unsigned long elf_greg_t;
+
+#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t))
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef struct user_i387_struct elf_fpregset_t;
+
+#ifdef __i386__
+
+typedef struct user_fxsr_struct elf_fpxregset_t;
+
+#define R_386_NONE 0
+#define R_386_32 1
+#define R_386_PC32 2
+#define R_386_GOT32 3
+#define R_386_PLT32 4
+#define R_386_COPY 5
+#define R_386_GLOB_DAT 6
+#define R_386_JMP_SLOT 7
+#define R_386_RELATIVE 8
+#define R_386_GOTOFF 9
+#define R_386_GOTPC 10
+#define R_386_NUM 11
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS ELFCLASS32
+#define ELF_DATA ELFDATA2LSB
+#define ELF_ARCH EM_386
+
#else
-# ifdef __i386__
-# include "elf_32.h"
-# else
-# include "elf_64.h"
-# endif
+
+/* x86-64 relocation types */
+#define R_X86_64_NONE 0 /* No reloc */
+#define R_X86_64_64 1 /* Direct 64 bit */
+#define R_X86_64_PC32 2 /* PC relative 32 bit signed */
+#define R_X86_64_GOT32 3 /* 32 bit GOT entry */
+#define R_X86_64_PLT32 4 /* 32 bit PLT address */
+#define R_X86_64_COPY 5 /* Copy symbol at runtime */
+#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */
+#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */
+#define R_X86_64_RELATIVE 8 /* Adjust by program base */
+#define R_X86_64_GOTPCREL 9 /* 32 bit signed pc relative
+ offset to GOT */
+#define R_X86_64_32 10 /* Direct 32 bit zero extended */
+#define R_X86_64_32S 11 /* Direct 32 bit sign extended */
+#define R_X86_64_16 12 /* Direct 16 bit zero extended */
+#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */
+#define R_X86_64_8 14 /* Direct 8 bit sign extended */
+#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */
+
+#define R_X86_64_NUM 16
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS ELFCLASS64
+#define ELF_DATA ELFDATA2LSB
+#define ELF_ARCH EM_X86_64
+
+#endif
+
+#ifdef __KERNEL__
+
+#ifdef CONFIG_X86_32
+#include <asm/processor.h>
+#include <asm/system.h> /* for savesegment */
+#include <asm/desc.h>
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) \
+ (((x)->e_machine == EM_386) || ((x)->e_machine == EM_486))
+
+/* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program starts %edx
+ contains a pointer to a function which might be registered using `atexit'.
+ This provides a mean for the dynamic linker to call DT_FINI functions for
+ shared libraries that have been loaded before the code runs.
+
+ A value of 0 tells we have no such handler.
+
+ We might as well make sure everything else is cleared too (except for %esp),
+ just to make things more deterministic.
+ */
+#define ELF_PLAT_INIT(_r, load_addr) do { \
+ _r->ebx = 0; _r->ecx = 0; _r->edx = 0; \
+ _r->esi = 0; _r->edi = 0; _r->ebp = 0; \
+ _r->eax = 0; \
+} while (0)
+
+/* regs is struct pt_regs, pr_reg is elf_gregset_t (which is
+ now struct_user_regs, they are different) */
+
+#define ELF_CORE_COPY_REGS(pr_reg, regs) \
+ pr_reg[0] = regs->ebx; \
+ pr_reg[1] = regs->ecx; \
+ pr_reg[2] = regs->edx; \
+ pr_reg[3] = regs->esi; \
+ pr_reg[4] = regs->edi; \
+ pr_reg[5] = regs->ebp; \
+ pr_reg[6] = regs->eax; \
+ pr_reg[7] = regs->xds & 0xffff; \
+ pr_reg[8] = regs->xes & 0xffff; \
+ pr_reg[9] = regs->xfs & 0xffff; \
+ savesegment(gs,pr_reg[10]); \
+ pr_reg[11] = regs->orig_eax; \
+ pr_reg[12] = regs->eip; \
+ pr_reg[13] = regs->xcs & 0xffff; \
+ pr_reg[14] = regs->eflags; \
+ pr_reg[15] = regs->esp; \
+ pr_reg[16] = regs->xss & 0xffff;
+
+#define ELF_PLATFORM (utsname()->machine)
+#define set_personality_64bit() do { } while (0)
+extern unsigned int vdso_enabled;
+
+#else /* CONFIG_X86_32 */
+
+#include <asm/processor.h>
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) \
+ ((x)->e_machine == EM_X86_64)
+
+#define ELF_PLAT_INIT(_r, load_addr) do { \
+ struct task_struct *cur = current; \
+ (_r)->rbx = 0; (_r)->rcx = 0; (_r)->rdx = 0; \
+ (_r)->rsi = 0; (_r)->rdi = 0; (_r)->rbp = 0; \
+ (_r)->rax = 0; \
+ (_r)->r8 = 0; \
+ (_r)->r9 = 0; \
+ (_r)->r10 = 0; \
+ (_r)->r11 = 0; \
+ (_r)->r12 = 0; \
+ (_r)->r13 = 0; \
+ (_r)->r14 = 0; \
+ (_r)->r15 = 0; \
+ cur->thread.fs = 0; cur->thread.gs = 0; \
+ cur->thread.fsindex = 0; cur->thread.gsindex = 0; \
+ cur->thread.ds = 0; cur->thread.es = 0; \
+ clear_thread_flag(TIF_IA32); \
+} while (0)
+
+/* regs is struct pt_regs, pr_reg is elf_gregset_t (which is
+ now struct_user_regs, they are different). Assumes current is the process
+ getting dumped. */
+
+#define ELF_CORE_COPY_REGS(pr_reg, regs) do { \
+ unsigned v; \
+ (pr_reg)[0] = (regs)->r15; \
+ (pr_reg)[1] = (regs)->r14; \
+ (pr_reg)[2] = (regs)->r13; \
+ (pr_reg)[3] = (regs)->r12; \
+ (pr_reg)[4] = (regs)->rbp; \
+ (pr_reg)[5] = (regs)->rbx; \
+ (pr_reg)[6] = (regs)->r11; \
+ (pr_reg)[7] = (regs)->r10; \
+ (pr_reg)[8] = (regs)->r9; \
+ (pr_reg)[9] = (regs)->r8; \
+ (pr_reg)[10] = (regs)->rax; \
+ (pr_reg)[11] = (regs)->rcx; \
+ (pr_reg)[12] = (regs)->rdx; \
+ (pr_reg)[13] = (regs)->rsi; \
+ (pr_reg)[14] = (regs)->rdi; \
+ (pr_reg)[15] = (regs)->orig_rax; \
+ (pr_reg)[16] = (regs)->rip; \
+ (pr_reg)[17] = (regs)->cs; \
+ (pr_reg)[18] = (regs)->eflags; \
+ (pr_reg)[19] = (regs)->rsp; \
+ (pr_reg)[20] = (regs)->ss; \
+ (pr_reg)[21] = current->thread.fs; \
+ (pr_reg)[22] = current->thread.gs; \
+ asm("movl %%ds,%0" : "=r" (v)); (pr_reg)[23] = v; \
+ asm("movl %%es,%0" : "=r" (v)); (pr_reg)[24] = v; \
+ asm("movl %%fs,%0" : "=r" (v)); (pr_reg)[25] = v; \
+ asm("movl %%gs,%0" : "=r" (v)); (pr_reg)[26] = v; \
+} while(0);
+
+/* I'm not sure if we can use '-' here */
+#define ELF_PLATFORM ("x86_64")
+extern void set_personality_64bit(void);
+extern int vdso_enabled;
+
+#endif /* !CONFIG_X86_32 */
+
+#define USE_ELF_CORE_DUMP
+#define ELF_EXEC_PAGESIZE 4096
+
+/* This is the location that an ET_DYN program is loaded if exec'ed. Typical
+ use of this is to invoke "./ld.so someprog" to test out a new version of
+ the loader. We need to make sure that it is out of the way of the program
+ that it will "exec", and that there is sufficient room for the brk. */
+
+#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2)
+
+/* This yields a mask that user programs can use to figure out what
+ instruction set this CPU supports. This could be done in user space,
+ but it's not easy, and we've already done it here. */
+
+#define ELF_HWCAP (boot_cpu_data.x86_capability[0])
+
+/* This yields a string that ld.so will use to load implementation
+ specific libraries for optimization. This is more specific in
+ intent than poking at uname or /proc/cpuinfo.
+
+ For the moment, we have only optimizations for the Intel generations,
+ but that could change... */
+
+#define SET_PERSONALITY(ex, ibcs2) set_personality_64bit()
+
+/*
+ * An executable for which elf_read_implies_exec() returns TRUE will
+ * have the READ_IMPLIES_EXEC personality flag set automatically.
+ */
+#define elf_read_implies_exec(ex, executable_stack) \
+ (executable_stack != EXSTACK_DISABLE_X)
+
+struct task_struct;
+
+extern int dump_task_regs (struct task_struct *, elf_gregset_t *);
+extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *);
+
+#define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs)
+#define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) dump_task_fpu(tsk, elf_fpregs)
+
+#ifdef CONFIG_X86_32
+extern int dump_task_extended_fpu (struct task_struct *,
+ struct user_fxsr_struct *);
+#define ELF_CORE_COPY_XFPREGS(tsk, elf_xfpregs) \
+ dump_task_extended_fpu(tsk, elf_xfpregs)
+#define ELF_CORE_XFPREG_TYPE NT_PRXFPREG
+
+#define VDSO_HIGH_BASE (__fix_to_virt(FIX_VDSO))
+#define VDSO_CURRENT_BASE ((unsigned long)current->mm->context.vdso)
+#define VDSO_PRELINK 0
+
+#define VDSO_SYM(x) \
+ (VDSO_CURRENT_BASE + (unsigned long)(x) - VDSO_PRELINK)
+
+#define VDSO_HIGH_EHDR ((const struct elfhdr *) VDSO_HIGH_BASE)
+#define VDSO_EHDR ((const struct elfhdr *) VDSO_CURRENT_BASE)
+
+extern void __kernel_vsyscall;
+
+#define VDSO_ENTRY VDSO_SYM(&__kernel_vsyscall)
+
+/* update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT entries changes */
+
+#define ARCH_DLINFO \
+do if (vdso_enabled) { \
+ NEW_AUX_ENT(AT_SYSINFO, VDSO_ENTRY); \
+ NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_CURRENT_BASE); \
+} while (0)
+
+#else /* CONFIG_X86_32 */
+
+/* 1GB for 64bit, 8MB for 32bit */
+#define STACK_RND_MASK (test_thread_flag(TIF_IA32) ? 0x7ff : 0x3fffff)
+
+#define ARCH_DLINFO \
+do if (vdso_enabled) { \
+ NEW_AUX_ENT(AT_SYSINFO_EHDR,(unsigned long)current->mm->context.vdso);\
+} while (0)
+
+#endif /* !CONFIG_X86_32 */
+
+struct linux_binprm;
+
+#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
+extern int arch_setup_additional_pages(struct linux_binprm *bprm,
+ int executable_stack);
+
+#endif /* __KERNEL__ */
+
#endif
diff --git a/include/asm-x86/elf_32.h b/include/asm-x86/elf_32.h
deleted file mode 100644
index b32df3a332da..000000000000
--- a/include/asm-x86/elf_32.h
+++ /dev/null
@@ -1,163 +0,0 @@
-#ifndef __ASMi386_ELF_H
-#define __ASMi386_ELF_H
-
-/*
- * ELF register definitions..
- */
-
-#include <asm/ptrace.h>
-#include <asm/user.h>
-#include <asm/auxvec.h>
-
-#define R_386_NONE 0
-#define R_386_32 1
-#define R_386_PC32 2
-#define R_386_GOT32 3
-#define R_386_PLT32 4
-#define R_386_COPY 5
-#define R_386_GLOB_DAT 6
-#define R_386_JMP_SLOT 7
-#define R_386_RELATIVE 8
-#define R_386_GOTOFF 9
-#define R_386_GOTPC 10
-#define R_386_NUM 11
-
-typedef unsigned long elf_greg_t;
-
-#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t))
-typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-
-typedef struct user_i387_struct elf_fpregset_t;
-typedef struct user_fxsr_struct elf_fpxregset_t;
-
-/*
- * This is used to ensure we don't load something for the wrong architecture.
- */
-#define elf_check_arch(x) \
- (((x)->e_machine == EM_386) || ((x)->e_machine == EM_486))
-
-/*
- * These are used to set parameters in the core dumps.
- */
-#define ELF_CLASS ELFCLASS32
-#define ELF_DATA ELFDATA2LSB
-#define ELF_ARCH EM_386
-
-#ifdef __KERNEL__
-
-#include <asm/processor.h>
-#include <asm/system.h> /* for savesegment */
-#include <asm/desc.h>
-
-/* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program starts %edx
- contains a pointer to a function which might be registered using `atexit'.
- This provides a mean for the dynamic linker to call DT_FINI functions for
- shared libraries that have been loaded before the code runs.
-
- A value of 0 tells we have no such handler.
-
- We might as well make sure everything else is cleared too (except for %esp),
- just to make things more deterministic.
- */
-#define ELF_PLAT_INIT(_r, load_addr) do { \
- _r->ebx = 0; _r->ecx = 0; _r->edx = 0; \
- _r->esi = 0; _r->edi = 0; _r->ebp = 0; \
- _r->eax = 0; \
-} while (0)
-
-#define USE_ELF_CORE_DUMP
-#define ELF_EXEC_PAGESIZE 4096
-
-/* This is the location that an ET_DYN program is loaded if exec'ed. Typical
- use of this is to invoke "./ld.so someprog" to test out a new version of
- the loader. We need to make sure that it is out of the way of the program
- that it will "exec", and that there is sufficient room for the brk. */
-
-#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2)
-
-/* regs is struct pt_regs, pr_reg is elf_gregset_t (which is
- now struct_user_regs, they are different) */
-
-#define ELF_CORE_COPY_REGS(pr_reg, regs) \
- pr_reg[0] = regs->ebx; \
- pr_reg[1] = regs->ecx; \
- pr_reg[2] = regs->edx; \
- pr_reg[3] = regs->esi; \
- pr_reg[4] = regs->edi; \
- pr_reg[5] = regs->ebp; \
- pr_reg[6] = regs->eax; \
- pr_reg[7] = regs->xds & 0xffff; \
- pr_reg[8] = regs->xes & 0xffff; \
- pr_reg[9] = regs->xfs & 0xffff; \
- savesegment(gs,pr_reg[10]); \
- pr_reg[11] = regs->orig_eax; \
- pr_reg[12] = regs->eip; \
- pr_reg[13] = regs->xcs & 0xffff; \
- pr_reg[14] = regs->eflags; \
- pr_reg[15] = regs->esp; \
- pr_reg[16] = regs->xss & 0xffff;
-
-/* This yields a mask that user programs can use to figure out what
- instruction set this CPU supports. This could be done in user space,
- but it's not easy, and we've already done it here. */
-
-#define ELF_HWCAP (boot_cpu_data.x86_capability[0])
-
-/* This yields a string that ld.so will use to load implementation
- specific libraries for optimization. This is more specific in
- intent than poking at uname or /proc/cpuinfo.
-
- For the moment, we have only optimizations for the Intel generations,
- but that could change... */
-
-#define ELF_PLATFORM (utsname()->machine)
-
-#define SET_PERSONALITY(ex, ibcs2) do { } while (0)
-
-/*
- * An executable for which elf_read_implies_exec() returns TRUE will
- * have the READ_IMPLIES_EXEC personality flag set automatically.
- */
-#define elf_read_implies_exec(ex, executable_stack) (executable_stack != EXSTACK_DISABLE_X)
-
-struct task_struct;
-
-extern int dump_task_regs (struct task_struct *, elf_gregset_t *);
-extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *);
-extern int dump_task_extended_fpu (struct task_struct *, struct user_fxsr_struct *);
-
-#define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs)
-#define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) dump_task_fpu(tsk, elf_fpregs)
-#define ELF_CORE_COPY_XFPREGS(tsk, elf_xfpregs) dump_task_extended_fpu(tsk, elf_xfpregs)
-
-#define VDSO_HIGH_BASE (__fix_to_virt(FIX_VDSO))
-#define VDSO_CURRENT_BASE ((unsigned long)current->mm->context.vdso)
-#define VDSO_PRELINK 0
-
-#define VDSO_SYM(x) \
- (VDSO_CURRENT_BASE + (unsigned long)(x) - VDSO_PRELINK)
-
-#define VDSO_HIGH_EHDR ((const struct elfhdr *) VDSO_HIGH_BASE)
-#define VDSO_EHDR ((const struct elfhdr *) VDSO_CURRENT_BASE)
-
-extern void __kernel_vsyscall;
-
-#define VDSO_ENTRY VDSO_SYM(&__kernel_vsyscall)
-
-struct linux_binprm;
-
-#define ARCH_HAS_SETUP_ADDITIONAL_PAGES
-extern int arch_setup_additional_pages(struct linux_binprm *bprm,
- int executable_stack);
-
-extern unsigned int vdso_enabled;
-
-#define ARCH_DLINFO \
-do if (vdso_enabled) { \
- NEW_AUX_ENT(AT_SYSINFO, VDSO_ENTRY); \
- NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_CURRENT_BASE); \
-} while (0)
-
-#endif
-
-#endif
diff --git a/include/asm-x86/elf_64.h b/include/asm-x86/elf_64.h
deleted file mode 100644
index b4fbe47f6ccd..000000000000
--- a/include/asm-x86/elf_64.h
+++ /dev/null
@@ -1,180 +0,0 @@
-#ifndef __ASM_X86_64_ELF_H
-#define __ASM_X86_64_ELF_H
-
-/*
- * ELF register definitions..
- */
-
-#include <asm/ptrace.h>
-#include <asm/user.h>
-
-/* x86-64 relocation types */
-#define R_X86_64_NONE 0 /* No reloc */
-#define R_X86_64_64 1 /* Direct 64 bit */
-#define R_X86_64_PC32 2 /* PC relative 32 bit signed */
-#define R_X86_64_GOT32 3 /* 32 bit GOT entry */
-#define R_X86_64_PLT32 4 /* 32 bit PLT address */
-#define R_X86_64_COPY 5 /* Copy symbol at runtime */
-#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */
-#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */
-#define R_X86_64_RELATIVE 8 /* Adjust by program base */
-#define R_X86_64_GOTPCREL 9 /* 32 bit signed pc relative
- offset to GOT */
-#define R_X86_64_32 10 /* Direct 32 bit zero extended */
-#define R_X86_64_32S 11 /* Direct 32 bit sign extended */
-#define R_X86_64_16 12 /* Direct 16 bit zero extended */
-#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */
-#define R_X86_64_8 14 /* Direct 8 bit sign extended */
-#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */
-
-#define R_X86_64_NUM 16
-
-typedef unsigned long elf_greg_t;
-
-#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t))
-typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-
-typedef struct user_i387_struct elf_fpregset_t;
-
-/*
- * These are used to set parameters in the core dumps.
- */
-#define ELF_CLASS ELFCLASS64
-#define ELF_DATA ELFDATA2LSB
-#define ELF_ARCH EM_X86_64
-
-#ifdef __KERNEL__
-#include <asm/processor.h>
-
-/*
- * This is used to ensure we don't load something for the wrong architecture.
- */
-#define elf_check_arch(x) \
- ((x)->e_machine == EM_X86_64)
-
-
-/* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program starts %edx
- contains a pointer to a function which might be registered using `atexit'.
- This provides a mean for the dynamic linker to call DT_FINI functions for
- shared libraries that have been loaded before the code runs.
-
- A value of 0 tells we have no such handler.
-
- We might as well make sure everything else is cleared too (except for %esp),
- just to make things more deterministic.
- */
-#define ELF_PLAT_INIT(_r, load_addr) do { \
- struct task_struct *cur = current; \
- (_r)->rbx = 0; (_r)->rcx = 0; (_r)->rdx = 0; \
- (_r)->rsi = 0; (_r)->rdi = 0; (_r)->rbp = 0; \
- (_r)->rax = 0; \
- (_r)->r8 = 0; \
- (_r)->r9 = 0; \
- (_r)->r10 = 0; \
- (_r)->r11 = 0; \
- (_r)->r12 = 0; \
- (_r)->r13 = 0; \
- (_r)->r14 = 0; \
- (_r)->r15 = 0; \
- cur->thread.fs = 0; cur->thread.gs = 0; \
- cur->thread.fsindex = 0; cur->thread.gsindex = 0; \
- cur->thread.ds = 0; cur->thread.es = 0; \
- clear_thread_flag(TIF_IA32); \
-} while (0)
-
-#define USE_ELF_CORE_DUMP
-#define ELF_EXEC_PAGESIZE 4096
-
-/* This is the location that an ET_DYN program is loaded if exec'ed. Typical
- use of this is to invoke "./ld.so someprog" to test out a new version of
- the loader. We need to make sure that it is out of the way of the program
- that it will "exec", and that there is sufficient room for the brk. */
-
-#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
-
-/* regs is struct pt_regs, pr_reg is elf_gregset_t (which is
- now struct_user_regs, they are different). Assumes current is the process
- getting dumped. */
-
-#define ELF_CORE_COPY_REGS(pr_reg, regs) do { \
- unsigned v; \
- (pr_reg)[0] = (regs)->r15; \
- (pr_reg)[1] = (regs)->r14; \
- (pr_reg)[2] = (regs)->r13; \
- (pr_reg)[3] = (regs)->r12; \
- (pr_reg)[4] = (regs)->rbp; \
- (pr_reg)[5] = (regs)->rbx; \
- (pr_reg)[6] = (regs)->r11; \
- (pr_reg)[7] = (regs)->r10; \
- (pr_reg)[8] = (regs)->r9; \
- (pr_reg)[9] = (regs)->r8; \
- (pr_reg)[10] = (regs)->rax; \
- (pr_reg)[11] = (regs)->rcx; \
- (pr_reg)[12] = (regs)->rdx; \
- (pr_reg)[13] = (regs)->rsi; \
- (pr_reg)[14] = (regs)->rdi; \
- (pr_reg)[15] = (regs)->orig_rax; \
- (pr_reg)[16] = (regs)->rip; \
- (pr_reg)[17] = (regs)->cs; \
- (pr_reg)[18] = (regs)->eflags; \
- (pr_reg)[19] = (regs)->rsp; \
- (pr_reg)[20] = (regs)->ss; \
- (pr_reg)[21] = current->thread.fs; \
- (pr_reg)[22] = current->thread.gs; \
- asm("movl %%ds,%0" : "=r" (v)); (pr_reg)[23] = v; \
- asm("movl %%es,%0" : "=r" (v)); (pr_reg)[24] = v; \
- asm("movl %%fs,%0" : "=r" (v)); (pr_reg)[25] = v; \
- asm("movl %%gs,%0" : "=r" (v)); (pr_reg)[26] = v; \
-} while(0);
-
-/* This yields a mask that user programs can use to figure out what
- instruction set this CPU supports. This could be done in user space,
- but it's not easy, and we've already done it here. */
-
-#define ELF_HWCAP (boot_cpu_data.x86_capability[0])
-
-/* This yields a string that ld.so will use to load implementation
- specific libraries for optimization. This is more specific in
- intent than poking at uname or /proc/cpuinfo.
-
- For the moment, we have only optimizations for the Intel generations,
- but that could change... */
-
-/* I'm not sure if we can use '-' here */
-#define ELF_PLATFORM ("x86_64")
-
-extern void set_personality_64bit(void);
-#define SET_PERSONALITY(ex, ibcs2) set_personality_64bit()
-/*
- * An executable for which elf_read_implies_exec() returns TRUE will
- * have the READ_IMPLIES_EXEC personality flag set automatically.
- */
-#define elf_read_implies_exec(ex, executable_stack) (executable_stack != EXSTACK_DISABLE_X)
-
-struct task_struct;
-
-extern int dump_task_regs (struct task_struct *, elf_gregset_t *);
-extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *);
-
-#define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs)
-#define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) dump_task_fpu(tsk, elf_fpregs)
-
-/* 1GB for 64bit, 8MB for 32bit */
-#define STACK_RND_MASK (test_thread_flag(TIF_IA32) ? 0x7ff : 0x3fffff)
-
-
-#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
-struct linux_binprm;
-extern int arch_setup_additional_pages(struct linux_binprm *bprm,
- int executable_stack);
-
-extern int vdso_enabled;
-
-#define ARCH_DLINFO \
-do if (vdso_enabled) { \
- NEW_AUX_ENT(AT_SYSINFO_EHDR,(unsigned long)current->mm->context.vdso);\
-} while (0)
-
-#endif
-
-#endif
diff --git a/include/asm-x86/errno.h b/include/asm-x86/errno.h
index 9d511be8e573..4c82b503d92f 100644
--- a/include/asm-x86/errno.h
+++ b/include/asm-x86/errno.h
@@ -1,13 +1 @@
-#ifdef __KERNEL__
-# ifdef CONFIG_X86_32
-# include "errno_32.h"
-# else
-# include "errno_64.h"
-# endif
-#else
-# ifdef __i386__
-# include "errno_32.h"
-# else
-# include "errno_64.h"
-# endif
-#endif
+#include <asm-generic/errno.h>
diff --git a/include/asm-x86/errno_32.h b/include/asm-x86/errno_32.h
deleted file mode 100644
index 969b34374728..000000000000
--- a/include/asm-x86/errno_32.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _I386_ERRNO_H
-#define _I386_ERRNO_H
-
-#include <asm-generic/errno.h>
-
-#endif
diff --git a/include/asm-x86/errno_64.h b/include/asm-x86/errno_64.h
deleted file mode 100644
index 311182129e32..000000000000
--- a/include/asm-x86/errno_64.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _X8664_ERRNO_H
-#define _X8664_ERRNO_H
-
-#include <asm-generic/errno.h>
-
-#endif
diff --git a/include/asm-x86/fb.h b/include/asm-x86/fb.h
index 238c7ca45877..53018464aea6 100644
--- a/include/asm-x86/fb.h
+++ b/include/asm-x86/fb.h
@@ -1,5 +1,21 @@
+#ifndef _ASM_X86_FB_H
+#define _ASM_X86_FB_H
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+ unsigned long off)
+{
+ if (boot_cpu_data.x86 > 3)
+ pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
+}
+
#ifdef CONFIG_X86_32
-# include "fb_32.h"
+extern int fb_is_primary_device(struct fb_info *info);
#else
-# include "fb_64.h"
+static inline int fb_is_primary_device(struct fb_info *info) { return 0; }
#endif
+
+#endif /* _ASM_X86_FB_H */
diff --git a/include/asm-x86/fb_32.h b/include/asm-x86/fb_32.h
deleted file mode 100644
index d1c6297d4a61..000000000000
--- a/include/asm-x86/fb_32.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef _ASM_FB_H_
-#define _ASM_FB_H_
-
-#include <linux/fb.h>
-#include <linux/fs.h>
-#include <asm/page.h>
-
-extern int fb_is_primary_device(struct fb_info *info);
-
-static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
- unsigned long off)
-{
- if (boot_cpu_data.x86 > 3)
- pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
-}
-
-#endif /* _ASM_FB_H_ */
diff --git a/include/asm-x86/fb_64.h b/include/asm-x86/fb_64.h
deleted file mode 100644
index 60548e651d12..000000000000
--- a/include/asm-x86/fb_64.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef _ASM_FB_H_
-#define _ASM_FB_H_
-#include <linux/fb.h>
-#include <linux/fs.h>
-#include <asm/page.h>
-
-static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
- unsigned long off)
-{
- if (boot_cpu_data.x86 > 3)
- pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
-}
-
-static inline int fb_is_primary_device(struct fb_info *info)
-{
- return 0;
-}
-
-#endif /* _ASM_FB_H_ */
diff --git a/include/asm-x86/floppy.h b/include/asm-x86/floppy.h
index aecbb6dca21d..a48d7153c097 100644
--- a/include/asm-x86/floppy.h
+++ b/include/asm-x86/floppy.h
@@ -1,5 +1,278 @@
-#ifdef CONFIG_X86_32
-# include "floppy_32.h"
-#else
-# include "floppy_64.h"
+/*
+ * Architecture specific parts of the Floppy driver
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995
+ */
+#ifndef _ASM_X86_FLOPPY_H
+#define _ASM_X86_FLOPPY_H
+
+#include <linux/vmalloc.h>
+
+/*
+ * The DMA channel used by the floppy controller cannot access data at
+ * addresses >= 16MB
+ *
+ * Went back to the 1MB limit, as some people had problems with the floppy
+ * driver otherwise. It doesn't matter much for performance anyway, as most
+ * floppy accesses go through the track buffer.
+ */
+#define _CROSS_64KB(a,s,vdma) \
+(!(vdma) && ((unsigned long)(a)/K_64 != ((unsigned long)(a) + (s) - 1) / K_64))
+
+#define CROSS_64KB(a,s) _CROSS_64KB(a,s,use_virtual_dma & 1)
+
+
+#define SW fd_routine[use_virtual_dma&1]
+#define CSW fd_routine[can_use_virtual_dma & 1]
+
+
+#define fd_inb(port) inb_p(port)
+#define fd_outb(value,port) outb_p(value,port)
+
+#define fd_request_dma() CSW._request_dma(FLOPPY_DMA,"floppy")
+#define fd_free_dma() CSW._free_dma(FLOPPY_DMA)
+#define fd_enable_irq() enable_irq(FLOPPY_IRQ)
+#define fd_disable_irq() disable_irq(FLOPPY_IRQ)
+#define fd_free_irq() free_irq(FLOPPY_IRQ, NULL)
+#define fd_get_dma_residue() SW._get_dma_residue(FLOPPY_DMA)
+#define fd_dma_mem_alloc(size) SW._dma_mem_alloc(size)
+#define fd_dma_setup(addr, size, mode, io) SW._dma_setup(addr, size, mode, io)
+
+#define FLOPPY_CAN_FALLBACK_ON_NODMA
+
+static int virtual_dma_count;
+static int virtual_dma_residue;
+static char *virtual_dma_addr;
+static int virtual_dma_mode;
+static int doing_pdma;
+
+static irqreturn_t floppy_hardint(int irq, void *dev_id)
+{
+ register unsigned char st;
+
+#undef TRACE_FLPY_INT
+
+#ifdef TRACE_FLPY_INT
+ static int calls=0;
+ static int bytes=0;
+ static int dma_wait=0;
#endif
+ if (!doing_pdma)
+ return floppy_interrupt(irq, dev_id);
+
+#ifdef TRACE_FLPY_INT
+ if(!calls)
+ bytes = virtual_dma_count;
+#endif
+
+ {
+ register int lcount;
+ register char *lptr;
+
+ st = 1;
+ for(lcount=virtual_dma_count, lptr=virtual_dma_addr;
+ lcount; lcount--, lptr++) {
+ st=inb(virtual_dma_port+4) & 0xa0 ;
+ if(st != 0xa0)
+ break;
+ if(virtual_dma_mode)
+ outb_p(*lptr, virtual_dma_port+5);
+ else
+ *lptr = inb_p(virtual_dma_port+5);
+ }
+ virtual_dma_count = lcount;
+ virtual_dma_addr = lptr;
+ st = inb(virtual_dma_port+4);
+ }
+
+#ifdef TRACE_FLPY_INT
+ calls++;
+#endif
+ if(st == 0x20)
+ return IRQ_HANDLED;
+ if(!(st & 0x20)) {
+ virtual_dma_residue += virtual_dma_count;
+ virtual_dma_count=0;
+#ifdef TRACE_FLPY_INT
+ printk("count=%x, residue=%x calls=%d bytes=%d dma_wait=%d\n",
+ virtual_dma_count, virtual_dma_residue, calls, bytes,
+ dma_wait);
+ calls = 0;
+ dma_wait=0;
+#endif
+ doing_pdma = 0;
+ floppy_interrupt(irq, dev_id);
+ return IRQ_HANDLED;
+ }
+#ifdef TRACE_FLPY_INT
+ if(!virtual_dma_count)
+ dma_wait++;
+#endif
+ return IRQ_HANDLED;
+}
+
+static void fd_disable_dma(void)
+{
+ if(! (can_use_virtual_dma & 1))
+ disable_dma(FLOPPY_DMA);
+ doing_pdma = 0;
+ virtual_dma_residue += virtual_dma_count;
+ virtual_dma_count=0;
+}
+
+static int vdma_request_dma(unsigned int dmanr, const char * device_id)
+{
+ return 0;
+}
+
+static void vdma_nop(unsigned int dummy)
+{
+}
+
+
+static int vdma_get_dma_residue(unsigned int dummy)
+{
+ return virtual_dma_count + virtual_dma_residue;
+}
+
+
+static int fd_request_irq(void)
+{
+ if(can_use_virtual_dma)
+ return request_irq(FLOPPY_IRQ, floppy_hardint,
+ IRQF_DISABLED, "floppy", NULL);
+ else
+ return request_irq(FLOPPY_IRQ, floppy_interrupt,
+ IRQF_DISABLED, "floppy", NULL);
+}
+
+static unsigned long dma_mem_alloc(unsigned long size)
+{
+ return __get_dma_pages(GFP_KERNEL|__GFP_NORETRY,get_order(size));
+}
+
+
+static unsigned long vdma_mem_alloc(unsigned long size)
+{
+ return (unsigned long) vmalloc(size);
+
+}
+
+#define nodma_mem_alloc(size) vdma_mem_alloc(size)
+
+static void _fd_dma_mem_free(unsigned long addr, unsigned long size)
+{
+ if((unsigned long) addr >= (unsigned long) high_memory)
+ vfree((void *)addr);
+ else
+ free_pages(addr, get_order(size));
+}
+
+#define fd_dma_mem_free(addr, size) _fd_dma_mem_free(addr, size)
+
+static void _fd_chose_dma_mode(char *addr, unsigned long size)
+{
+ if(can_use_virtual_dma == 2) {
+ if((unsigned long) addr >= (unsigned long) high_memory ||
+ isa_virt_to_bus(addr) >= 0x1000000 ||
+ _CROSS_64KB(addr, size, 0))
+ use_virtual_dma = 1;
+ else
+ use_virtual_dma = 0;
+ } else {
+ use_virtual_dma = can_use_virtual_dma & 1;
+ }
+}
+
+#define fd_chose_dma_mode(addr, size) _fd_chose_dma_mode(addr, size)
+
+
+static int vdma_dma_setup(char *addr, unsigned long size, int mode, int io)
+{
+ doing_pdma = 1;
+ virtual_dma_port = io;
+ virtual_dma_mode = (mode == DMA_MODE_WRITE);
+ virtual_dma_addr = addr;
+ virtual_dma_count = size;
+ virtual_dma_residue = 0;
+ return 0;
+}
+
+static int hard_dma_setup(char *addr, unsigned long size, int mode, int io)
+{
+#ifdef FLOPPY_SANITY_CHECK
+ if (CROSS_64KB(addr, size)) {
+ printk("DMA crossing 64-K boundary %p-%p\n", addr, addr+size);
+ return -1;
+ }
+#endif
+ /* actual, physical DMA */
+ doing_pdma = 0;
+ clear_dma_ff(FLOPPY_DMA);
+ set_dma_mode(FLOPPY_DMA,mode);
+ set_dma_addr(FLOPPY_DMA,isa_virt_to_bus(addr));
+ set_dma_count(FLOPPY_DMA,size);
+ enable_dma(FLOPPY_DMA);
+ return 0;
+}
+
+static struct fd_routine_l {
+ int (*_request_dma)(unsigned int dmanr, const char * device_id);
+ void (*_free_dma)(unsigned int dmanr);
+ int (*_get_dma_residue)(unsigned int dummy);
+ unsigned long (*_dma_mem_alloc) (unsigned long size);
+ int (*_dma_setup)(char *addr, unsigned long size, int mode, int io);
+} fd_routine[] = {
+ {
+ request_dma,
+ free_dma,
+ get_dma_residue,
+ dma_mem_alloc,
+ hard_dma_setup
+ },
+ {
+ vdma_request_dma,
+ vdma_nop,
+ vdma_get_dma_residue,
+ vdma_mem_alloc,
+ vdma_dma_setup
+ }
+};
+
+
+static int FDC1 = 0x3f0;
+static int FDC2 = -1;
+
+/*
+ * Floppy types are stored in the rtc's CMOS RAM and so rtc_lock
+ * is needed to prevent corrupted CMOS RAM in case "insmod floppy"
+ * coincides with another rtc CMOS user. Paul G.
+ */
+#define FLOPPY0_TYPE ({ \
+ unsigned long flags; \
+ unsigned char val; \
+ spin_lock_irqsave(&rtc_lock, flags); \
+ val = (CMOS_READ(0x10) >> 4) & 15; \
+ spin_unlock_irqrestore(&rtc_lock, flags); \
+ val; \
+})
+
+#define FLOPPY1_TYPE ({ \
+ unsigned long flags; \
+ unsigned char val; \
+ spin_lock_irqsave(&rtc_lock, flags); \
+ val = CMOS_READ(0x10) & 15; \
+ spin_unlock_irqrestore(&rtc_lock, flags); \
+ val; \
+})
+
+#define N_FDC 2
+#define N_DRIVE 8
+
+#define EXTRA_FLOPPY_PARAMS
+
+#endif /* _ASM_X86_FLOPPY_H */
diff --git a/include/asm-x86/floppy_32.h b/include/asm-x86/floppy_32.h
deleted file mode 100644
index 44ef2f55a8e9..000000000000
--- a/include/asm-x86/floppy_32.h
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Architecture specific parts of the Floppy driver
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995
- */
-#ifndef __ASM_I386_FLOPPY_H
-#define __ASM_I386_FLOPPY_H
-
-#include <linux/vmalloc.h>
-
-
-/*
- * The DMA channel used by the floppy controller cannot access data at
- * addresses >= 16MB
- *
- * Went back to the 1MB limit, as some people had problems with the floppy
- * driver otherwise. It doesn't matter much for performance anyway, as most
- * floppy accesses go through the track buffer.
- */
-#define _CROSS_64KB(a,s,vdma) \
-(!(vdma) && ((unsigned long)(a)/K_64 != ((unsigned long)(a) + (s) - 1) / K_64))
-
-#define CROSS_64KB(a,s) _CROSS_64KB(a,s,use_virtual_dma & 1)
-
-
-#define SW fd_routine[use_virtual_dma&1]
-#define CSW fd_routine[can_use_virtual_dma & 1]
-
-
-#define fd_inb(port) inb_p(port)
-#define fd_outb(value,port) outb_p(value,port)
-
-#define fd_request_dma() CSW._request_dma(FLOPPY_DMA,"floppy")
-#define fd_free_dma() CSW._free_dma(FLOPPY_DMA)
-#define fd_enable_irq() enable_irq(FLOPPY_IRQ)
-#define fd_disable_irq() disable_irq(FLOPPY_IRQ)
-#define fd_free_irq() free_irq(FLOPPY_IRQ, NULL)
-#define fd_get_dma_residue() SW._get_dma_residue(FLOPPY_DMA)
-#define fd_dma_mem_alloc(size) SW._dma_mem_alloc(size)
-#define fd_dma_setup(addr, size, mode, io) SW._dma_setup(addr, size, mode, io)
-
-#define FLOPPY_CAN_FALLBACK_ON_NODMA
-
-static int virtual_dma_count;
-static int virtual_dma_residue;
-static char *virtual_dma_addr;
-static int virtual_dma_mode;
-static int doing_pdma;
-
-static irqreturn_t floppy_hardint(int irq, void *dev_id)
-{
- register unsigned char st;
-
-#undef TRACE_FLPY_INT
-
-#ifdef TRACE_FLPY_INT
- static int calls=0;
- static int bytes=0;
- static int dma_wait=0;
-#endif
- if (!doing_pdma)
- return floppy_interrupt(irq, dev_id);
-
-#ifdef TRACE_FLPY_INT
- if(!calls)
- bytes = virtual_dma_count;
-#endif
-
- {
- register int lcount;
- register char *lptr;
-
- st = 1;
- for(lcount=virtual_dma_count, lptr=virtual_dma_addr;
- lcount; lcount--, lptr++) {
- st=inb(virtual_dma_port+4) & 0xa0 ;
- if(st != 0xa0)
- break;
- if(virtual_dma_mode)
- outb_p(*lptr, virtual_dma_port+5);
- else
- *lptr = inb_p(virtual_dma_port+5);
- }
- virtual_dma_count = lcount;
- virtual_dma_addr = lptr;
- st = inb(virtual_dma_port+4);
- }
-
-#ifdef TRACE_FLPY_INT
- calls++;
-#endif
- if(st == 0x20)
- return IRQ_HANDLED;
- if(!(st & 0x20)) {
- virtual_dma_residue += virtual_dma_count;
- virtual_dma_count=0;
-#ifdef TRACE_FLPY_INT
- printk("count=%x, residue=%x calls=%d bytes=%d dma_wait=%d\n",
- virtual_dma_count, virtual_dma_residue, calls, bytes,
- dma_wait);
- calls = 0;
- dma_wait=0;
-#endif
- doing_pdma = 0;
- floppy_interrupt(irq, dev_id);
- return IRQ_HANDLED;
- }
-#ifdef TRACE_FLPY_INT
- if(!virtual_dma_count)
- dma_wait++;
-#endif
- return IRQ_HANDLED;
-}
-
-static void fd_disable_dma(void)
-{
- if(! (can_use_virtual_dma & 1))
- disable_dma(FLOPPY_DMA);
- doing_pdma = 0;
- virtual_dma_residue += virtual_dma_count;
- virtual_dma_count=0;
-}
-
-static int vdma_request_dma(unsigned int dmanr, const char * device_id)
-{
- return 0;
-}
-
-static void vdma_nop(unsigned int dummy)
-{
-}
-
-
-static int vdma_get_dma_residue(unsigned int dummy)
-{
- return virtual_dma_count + virtual_dma_residue;
-}
-
-
-static int fd_request_irq(void)
-{
- if(can_use_virtual_dma)
- return request_irq(FLOPPY_IRQ, floppy_hardint,
- IRQF_DISABLED, "floppy", NULL);
- else
- return request_irq(FLOPPY_IRQ, floppy_interrupt,
- IRQF_DISABLED, "floppy", NULL);
-
-}
-
-static unsigned long dma_mem_alloc(unsigned long size)
-{
- return __get_dma_pages(GFP_KERNEL,get_order(size));
-}
-
-
-static unsigned long vdma_mem_alloc(unsigned long size)
-{
- return (unsigned long) vmalloc(size);
-
-}
-
-#define nodma_mem_alloc(size) vdma_mem_alloc(size)
-
-static void _fd_dma_mem_free(unsigned long addr, unsigned long size)
-{
- if((unsigned int) addr >= (unsigned int) high_memory)
- vfree((void *)addr);
- else
- free_pages(addr, get_order(size));
-}
-
-#define fd_dma_mem_free(addr, size) _fd_dma_mem_free(addr, size)
-
-static void _fd_chose_dma_mode(char *addr, unsigned long size)
-{
- if(can_use_virtual_dma == 2) {
- if((unsigned int) addr >= (unsigned int) high_memory ||
- isa_virt_to_bus(addr) >= 0x1000000 ||
- _CROSS_64KB(addr, size, 0))
- use_virtual_dma = 1;
- else
- use_virtual_dma = 0;
- } else {
- use_virtual_dma = can_use_virtual_dma & 1;
- }
-}
-
-#define fd_chose_dma_mode(addr, size) _fd_chose_dma_mode(addr, size)
-
-
-static int vdma_dma_setup(char *addr, unsigned long size, int mode, int io)
-{
- doing_pdma = 1;
- virtual_dma_port = io;
- virtual_dma_mode = (mode == DMA_MODE_WRITE);
- virtual_dma_addr = addr;
- virtual_dma_count = size;
- virtual_dma_residue = 0;
- return 0;
-}
-
-static int hard_dma_setup(char *addr, unsigned long size, int mode, int io)
-{
-#ifdef FLOPPY_SANITY_CHECK
- if (CROSS_64KB(addr, size)) {
- printk("DMA crossing 64-K boundary %p-%p\n", addr, addr+size);
- return -1;
- }
-#endif
- /* actual, physical DMA */
- doing_pdma = 0;
- clear_dma_ff(FLOPPY_DMA);
- set_dma_mode(FLOPPY_DMA,mode);
- set_dma_addr(FLOPPY_DMA,isa_virt_to_bus(addr));
- set_dma_count(FLOPPY_DMA,size);
- enable_dma(FLOPPY_DMA);
- return 0;
-}
-
-static struct fd_routine_l {
- int (*_request_dma)(unsigned int dmanr, const char * device_id);
- void (*_free_dma)(unsigned int dmanr);
- int (*_get_dma_residue)(unsigned int dummy);
- unsigned long (*_dma_mem_alloc) (unsigned long size);
- int (*_dma_setup)(char *addr, unsigned long size, int mode, int io);
-} fd_routine[] = {
- {
- request_dma,
- free_dma,
- get_dma_residue,
- dma_mem_alloc,
- hard_dma_setup
- },
- {
- vdma_request_dma,
- vdma_nop,
- vdma_get_dma_residue,
- vdma_mem_alloc,
- vdma_dma_setup
- }
-};
-
-
-static int FDC1 = 0x3f0;
-static int FDC2 = -1;
-
-/*
- * Floppy types are stored in the rtc's CMOS RAM and so rtc_lock
- * is needed to prevent corrupted CMOS RAM in case "insmod floppy"
- * coincides with another rtc CMOS user. Paul G.
- */
-#define FLOPPY0_TYPE ({ \
- unsigned long flags; \
- unsigned char val; \
- spin_lock_irqsave(&rtc_lock, flags); \
- val = (CMOS_READ(0x10) >> 4) & 15; \
- spin_unlock_irqrestore(&rtc_lock, flags); \
- val; \
-})
-
-#define FLOPPY1_TYPE ({ \
- unsigned long flags; \
- unsigned char val; \
- spin_lock_irqsave(&rtc_lock, flags); \
- val = CMOS_READ(0x10) & 15; \
- spin_unlock_irqrestore(&rtc_lock, flags); \
- val; \
-})
-
-#define N_FDC 2
-#define N_DRIVE 8
-
-#define FLOPPY_MOTOR_MASK 0xf0
-
-#define AUTO_DMA
-
-#define EXTRA_FLOPPY_PARAMS
-
-#endif /* __ASM_I386_FLOPPY_H */
diff --git a/include/asm-x86/floppy_64.h b/include/asm-x86/floppy_64.h
deleted file mode 100644
index 6ea13c3806f3..000000000000
--- a/include/asm-x86/floppy_64.h
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * Architecture specific parts of the Floppy driver
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995
- */
-#ifndef __ASM_X86_64_FLOPPY_H
-#define __ASM_X86_64_FLOPPY_H
-
-#include <linux/vmalloc.h>
-
-
-/*
- * The DMA channel used by the floppy controller cannot access data at
- * addresses >= 16MB
- *
- * Went back to the 1MB limit, as some people had problems with the floppy
- * driver otherwise. It doesn't matter much for performance anyway, as most
- * floppy accesses go through the track buffer.
- */
-#define _CROSS_64KB(a,s,vdma) \
-(!(vdma) && ((unsigned long)(a)/K_64 != ((unsigned long)(a) + (s) - 1) / K_64))
-
-#define CROSS_64KB(a,s) _CROSS_64KB(a,s,use_virtual_dma & 1)
-
-
-#define SW fd_routine[use_virtual_dma&1]
-#define CSW fd_routine[can_use_virtual_dma & 1]
-
-
-#define fd_inb(port) inb_p(port)
-#define fd_outb(value,port) outb_p(value,port)
-
-#define fd_request_dma() CSW._request_dma(FLOPPY_DMA,"floppy")
-#define fd_free_dma() CSW._free_dma(FLOPPY_DMA)
-#define fd_enable_irq() enable_irq(FLOPPY_IRQ)
-#define fd_disable_irq() disable_irq(FLOPPY_IRQ)
-#define fd_free_irq() free_irq(FLOPPY_IRQ, NULL)
-#define fd_get_dma_residue() SW._get_dma_residue(FLOPPY_DMA)
-#define fd_dma_mem_alloc(size) SW._dma_mem_alloc(size)
-#define fd_dma_setup(addr, size, mode, io) SW._dma_setup(addr, size, mode, io)
-
-#define FLOPPY_CAN_FALLBACK_ON_NODMA
-
-static int virtual_dma_count;
-static int virtual_dma_residue;
-static char *virtual_dma_addr;
-static int virtual_dma_mode;
-static int doing_pdma;
-
-static irqreturn_t floppy_hardint(int irq, void *dev_id)
-{
- register unsigned char st;
-
-#undef TRACE_FLPY_INT
-
-#ifdef TRACE_FLPY_INT
- static int calls=0;
- static int bytes=0;
- static int dma_wait=0;
-#endif
- if (!doing_pdma)
- return floppy_interrupt(irq, dev_id);
-
-#ifdef TRACE_FLPY_INT
- if(!calls)
- bytes = virtual_dma_count;
-#endif
-
- {
- register int lcount;
- register char *lptr;
-
- st = 1;
- for(lcount=virtual_dma_count, lptr=virtual_dma_addr;
- lcount; lcount--, lptr++) {
- st=inb(virtual_dma_port+4) & 0xa0 ;
- if(st != 0xa0)
- break;
- if(virtual_dma_mode)
- outb_p(*lptr, virtual_dma_port+5);
- else
- *lptr = inb_p(virtual_dma_port+5);
- }
- virtual_dma_count = lcount;
- virtual_dma_addr = lptr;
- st = inb(virtual_dma_port+4);
- }
-
-#ifdef TRACE_FLPY_INT
- calls++;
-#endif
- if(st == 0x20)
- return IRQ_HANDLED;
- if(!(st & 0x20)) {
- virtual_dma_residue += virtual_dma_count;
- virtual_dma_count=0;
-#ifdef TRACE_FLPY_INT
- printk("count=%x, residue=%x calls=%d bytes=%d dma_wait=%d\n",
- virtual_dma_count, virtual_dma_residue, calls, bytes,
- dma_wait);
- calls = 0;
- dma_wait=0;
-#endif
- doing_pdma = 0;
- floppy_interrupt(irq, dev_id);
- return IRQ_HANDLED;
- }
-#ifdef TRACE_FLPY_INT
- if(!virtual_dma_count)
- dma_wait++;
-#endif
- return IRQ_HANDLED;
-}
-
-static void fd_disable_dma(void)
-{
- if(! (can_use_virtual_dma & 1))
- disable_dma(FLOPPY_DMA);
- doing_pdma = 0;
- virtual_dma_residue += virtual_dma_count;
- virtual_dma_count=0;
-}
-
-static int vdma_request_dma(unsigned int dmanr, const char * device_id)
-{
- return 0;
-}
-
-static void vdma_nop(unsigned int dummy)
-{
-}
-
-
-static int vdma_get_dma_residue(unsigned int dummy)
-{
- return virtual_dma_count + virtual_dma_residue;
-}
-
-
-static int fd_request_irq(void)
-{
- if(can_use_virtual_dma)
- return request_irq(FLOPPY_IRQ, floppy_hardint,
- IRQF_DISABLED, "floppy", NULL);
- else
- return request_irq(FLOPPY_IRQ, floppy_interrupt,
- IRQF_DISABLED, "floppy", NULL);
-}
-
-static unsigned long dma_mem_alloc(unsigned long size)
-{
- return __get_dma_pages(GFP_KERNEL|__GFP_NORETRY,get_order(size));
-}
-
-
-static unsigned long vdma_mem_alloc(unsigned long size)
-{
- return (unsigned long) vmalloc(size);
-
-}
-
-#define nodma_mem_alloc(size) vdma_mem_alloc(size)
-
-static void _fd_dma_mem_free(unsigned long addr, unsigned long size)
-{
- if((unsigned long) addr >= (unsigned long) high_memory)
- vfree((void *)addr);
- else
- free_pages(addr, get_order(size));
-}
-
-#define fd_dma_mem_free(addr, size) _fd_dma_mem_free(addr, size)
-
-static void _fd_chose_dma_mode(char *addr, unsigned long size)
-{
- if(can_use_virtual_dma == 2) {
- if((unsigned long) addr >= (unsigned long) high_memory ||
- isa_virt_to_bus(addr) >= 0x1000000 ||
- _CROSS_64KB(addr, size, 0))
- use_virtual_dma = 1;
- else
- use_virtual_dma = 0;
- } else {
- use_virtual_dma = can_use_virtual_dma & 1;
- }
-}
-
-#define fd_chose_dma_mode(addr, size) _fd_chose_dma_mode(addr, size)
-
-
-static int vdma_dma_setup(char *addr, unsigned long size, int mode, int io)
-{
- doing_pdma = 1;
- virtual_dma_port = io;
- virtual_dma_mode = (mode == DMA_MODE_WRITE);
- virtual_dma_addr = addr;
- virtual_dma_count = size;
- virtual_dma_residue = 0;
- return 0;
-}
-
-static int hard_dma_setup(char *addr, unsigned long size, int mode, int io)
-{
-#ifdef FLOPPY_SANITY_CHECK
- if (CROSS_64KB(addr, size)) {
- printk("DMA crossing 64-K boundary %p-%p\n", addr, addr+size);
- return -1;
- }
-#endif
- /* actual, physical DMA */
- doing_pdma = 0;
- clear_dma_ff(FLOPPY_DMA);
- set_dma_mode(FLOPPY_DMA,mode);
- set_dma_addr(FLOPPY_DMA,isa_virt_to_bus(addr));
- set_dma_count(FLOPPY_DMA,size);
- enable_dma(FLOPPY_DMA);
- return 0;
-}
-
-static struct fd_routine_l {
- int (*_request_dma)(unsigned int dmanr, const char * device_id);
- void (*_free_dma)(unsigned int dmanr);
- int (*_get_dma_residue)(unsigned int dummy);
- unsigned long (*_dma_mem_alloc) (unsigned long size);
- int (*_dma_setup)(char *addr, unsigned long size, int mode, int io);
-} fd_routine[] = {
- {
- request_dma,
- free_dma,
- get_dma_residue,
- dma_mem_alloc,
- hard_dma_setup
- },
- {
- vdma_request_dma,
- vdma_nop,
- vdma_get_dma_residue,
- vdma_mem_alloc,
- vdma_dma_setup
- }
-};
-
-
-static int FDC1 = 0x3f0;
-static int FDC2 = -1;
-
-/*
- * Floppy types are stored in the rtc's CMOS RAM and so rtc_lock
- * is needed to prevent corrupted CMOS RAM in case "insmod floppy"
- * coincides with another rtc CMOS user. Paul G.
- */
-#define FLOPPY0_TYPE ({ \
- unsigned long flags; \
- unsigned char val; \
- spin_lock_irqsave(&rtc_lock, flags); \
- val = (CMOS_READ(0x10) >> 4) & 15; \
- spin_unlock_irqrestore(&rtc_lock, flags); \
- val; \
-})
-
-#define FLOPPY1_TYPE ({ \
- unsigned long flags; \
- unsigned char val; \
- spin_lock_irqsave(&rtc_lock, flags); \
- val = CMOS_READ(0x10) & 15; \
- spin_unlock_irqrestore(&rtc_lock, flags); \
- val; \
-})
-
-#define N_FDC 2
-#define N_DRIVE 8
-
-#define FLOPPY_MOTOR_MASK 0xf0
-
-#define AUTO_DMA
-
-#define EXTRA_FLOPPY_PARAMS
-
-#endif /* __ASM_X86_64_FLOPPY_H */
diff --git a/include/asm-x86/frame.i b/include/asm-x86/frame.h
index 03620251ae17..06850a7194e1 100644
--- a/include/asm-x86/frame.i
+++ b/include/asm-x86/frame.h
@@ -1,3 +1,5 @@
+#ifdef __ASSEMBLY__
+
#include <asm/dwarf2.h>
/* The annotation hides the frame from the unwinder and makes it look
@@ -21,3 +23,5 @@
.macro ENDFRAME
.endm
#endif
+
+#endif /* __ASSEMBLY__ */
diff --git a/include/asm-x86/gart.h b/include/asm-x86/gart.h
new file mode 100644
index 000000000000..f704c50519b8
--- /dev/null
+++ b/include/asm-x86/gart.h
@@ -0,0 +1,29 @@
+#ifndef _ASM_X8664_IOMMU_H
+#define _ASM_X8664_IOMMU_H 1
+
+extern void pci_iommu_shutdown(void);
+extern void no_iommu_init(void);
+extern int force_iommu, no_iommu;
+extern int iommu_detected;
+#ifdef CONFIG_GART_IOMMU
+extern void gart_iommu_init(void);
+extern void gart_iommu_shutdown(void);
+extern void __init gart_parse_options(char *);
+extern void gart_iommu_hole_init(void);
+extern int fallback_aper_order;
+extern int fallback_aper_force;
+extern int gart_iommu_aperture;
+extern int gart_iommu_aperture_allowed;
+extern int gart_iommu_aperture_disabled;
+extern int fix_aperture;
+#else
+#define gart_iommu_aperture 0
+#define gart_iommu_aperture_allowed 0
+
+static inline void gart_iommu_shutdown(void)
+{
+}
+
+#endif
+
+#endif
diff --git a/include/asm-x86/geode.h b/include/asm-x86/geode.h
index d94898831bac..771af336734f 100644
--- a/include/asm-x86/geode.h
+++ b/include/asm-x86/geode.h
@@ -38,6 +38,8 @@ extern int geode_get_dev_base(unsigned int dev);
#define MSR_LBAR_ACPI 0x5140000E
#define MSR_LBAR_PMS 0x5140000F
+#define MSR_DIVIL_SOFT_RESET 0x51400017
+
#define MSR_PIC_YSEL_LOW 0x51400020
#define MSR_PIC_YSEL_HIGH 0x51400021
#define MSR_PIC_ZSEL_LOW 0x51400022
diff --git a/include/asm-x86/hardirq_32.h b/include/asm-x86/hardirq_32.h
index 34649585bb59..4f85f0f4b563 100644
--- a/include/asm-x86/hardirq_32.h
+++ b/include/asm-x86/hardirq_32.h
@@ -10,10 +10,14 @@ typedef struct {
unsigned int __nmi_count; /* arch dependent */
unsigned int apic_timer_irqs; /* arch dependent */
unsigned int irq0_irqs;
+ unsigned int irq_resched_count;
+ unsigned int irq_call_count;
+ unsigned int irq_tlb_count;
+ unsigned int irq_thermal_count;
+ unsigned int irq_spurious_count;
} ____cacheline_aligned irq_cpustat_t;
DECLARE_PER_CPU(irq_cpustat_t, irq_stat);
-extern irq_cpustat_t irq_stat[];
#define __ARCH_IRQ_STAT
#define __IRQ_STAT(cpu, member) (per_cpu(irq_stat, cpu).member)
diff --git a/include/asm-x86/hpet.h b/include/asm-x86/hpet.h
index d4ab6db050b6..b1f3c1ea55d9 100644
--- a/include/asm-x86/hpet.h
+++ b/include/asm-x86/hpet.h
@@ -3,12 +3,6 @@
#ifdef CONFIG_HPET_TIMER
-/*
- * Documentation on HPET can be found at:
- * http://www.intel.com/ial/home/sp/pcmmspec.htm
- * ftp://download.intel.com/ial/home/sp/mmts098.pdf
- */
-
#define HPET_MMAP_SIZE 1024
#define HPET_ID 0x000
@@ -64,6 +58,7 @@
/* hpet memory map physical address */
extern unsigned long hpet_address;
extern unsigned long force_hpet_address;
+extern int hpet_force_user;
extern int is_hpet_enabled(void);
extern int hpet_enable(void);
extern unsigned long hpet_readl(unsigned long a);
diff --git a/include/asm-x86/hw_irq_64.h b/include/asm-x86/hw_irq_64.h
index 09dfc18a6dd0..a470d59da678 100644
--- a/include/asm-x86/hw_irq_64.h
+++ b/include/asm-x86/hw_irq_64.h
@@ -40,22 +40,22 @@
/*
* Vectors 0x30-0x3f are used for ISA interrupts.
*/
-#define IRQ0_VECTOR FIRST_EXTERNAL_VECTOR + 0x10
-#define IRQ1_VECTOR IRQ0_VECTOR + 1
-#define IRQ2_VECTOR IRQ0_VECTOR + 2
-#define IRQ3_VECTOR IRQ0_VECTOR + 3
-#define IRQ4_VECTOR IRQ0_VECTOR + 4
-#define IRQ5_VECTOR IRQ0_VECTOR + 5
-#define IRQ6_VECTOR IRQ0_VECTOR + 6
-#define IRQ7_VECTOR IRQ0_VECTOR + 7
-#define IRQ8_VECTOR IRQ0_VECTOR + 8
-#define IRQ9_VECTOR IRQ0_VECTOR + 9
-#define IRQ10_VECTOR IRQ0_VECTOR + 10
-#define IRQ11_VECTOR IRQ0_VECTOR + 11
-#define IRQ12_VECTOR IRQ0_VECTOR + 12
-#define IRQ13_VECTOR IRQ0_VECTOR + 13
-#define IRQ14_VECTOR IRQ0_VECTOR + 14
-#define IRQ15_VECTOR IRQ0_VECTOR + 15
+#define IRQ0_VECTOR (FIRST_EXTERNAL_VECTOR + 0x10)
+#define IRQ1_VECTOR (IRQ0_VECTOR + 1)
+#define IRQ2_VECTOR (IRQ0_VECTOR + 2)
+#define IRQ3_VECTOR (IRQ0_VECTOR + 3)
+#define IRQ4_VECTOR (IRQ0_VECTOR + 4)
+#define IRQ5_VECTOR (IRQ0_VECTOR + 5)
+#define IRQ6_VECTOR (IRQ0_VECTOR + 6)
+#define IRQ7_VECTOR (IRQ0_VECTOR + 7)
+#define IRQ8_VECTOR (IRQ0_VECTOR + 8)
+#define IRQ9_VECTOR (IRQ0_VECTOR + 9)
+#define IRQ10_VECTOR (IRQ0_VECTOR + 10)
+#define IRQ11_VECTOR (IRQ0_VECTOR + 11)
+#define IRQ12_VECTOR (IRQ0_VECTOR + 12)
+#define IRQ13_VECTOR (IRQ0_VECTOR + 13)
+#define IRQ14_VECTOR (IRQ0_VECTOR + 14)
+#define IRQ15_VECTOR (IRQ0_VECTOR + 15)
/*
* Special IRQ vectors used by the SMP architecture, 0xf0-0xff
@@ -148,9 +148,6 @@ extern atomic_t irq_mis_count;
#define IO_APIC_IRQ(x) (((x) >= 16) || ((1<<(x)) & io_apic_irqs))
-#define __STR(x) #x
-#define STR(x) __STR(x)
-
#include <asm/ptrace.h>
#define IRQ_NAME2(nr) nr##_interrupt(void)
diff --git a/include/asm-x86/i387_64.h b/include/asm-x86/i387_64.h
index 0217b74cc9fc..3a4ffba3d6bc 100644
--- a/include/asm-x86/i387_64.h
+++ b/include/asm-x86/i387_64.h
@@ -203,6 +203,11 @@ static inline void save_init_fpu(struct task_struct *tsk)
*/
static inline int restore_i387(struct _fpstate __user *buf)
{
+ set_used_math();
+ if (!(task_thread_info(current)->status & TS_USEDFPU)) {
+ clts();
+ task_thread_info(current)->status |= TS_USEDFPU;
+ }
return restore_fpu_checking((__force struct i387_fxsave_struct *)buf);
}
diff --git a/include/asm-x86/ide.h b/include/asm-x86/ide.h
index e7817a3d6578..42130adf9c7c 100644
--- a/include/asm-x86/ide.h
+++ b/include/asm-x86/ide.h
@@ -62,7 +62,6 @@ static __inline__ unsigned long ide_default_io_base(int index)
}
}
-#define IDE_ARCH_OBSOLETE_INIT
#define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */
#ifdef CONFIG_BLK_DEV_IDEPCI
diff --git a/include/asm-x86/intel_arch_perfmon.h b/include/asm-x86/intel_arch_perfmon.h
index 4f6d4e6bf57e..fa0fd068bc2e 100644
--- a/include/asm-x86/intel_arch_perfmon.h
+++ b/include/asm-x86/intel_arch_perfmon.h
@@ -1,5 +1,31 @@
-#ifdef CONFIG_X86_32
-# include "intel_arch_perfmon_32.h"
-#else
-# include "intel_arch_perfmon_64.h"
-#endif
+#ifndef _ASM_X86_INTEL_ARCH_PERFMON_H
+#define _ASM_X86_INTEL_ARCH_PERFMON_H
+
+#define MSR_ARCH_PERFMON_PERFCTR0 0xc1
+#define MSR_ARCH_PERFMON_PERFCTR1 0xc2
+
+#define MSR_ARCH_PERFMON_EVENTSEL0 0x186
+#define MSR_ARCH_PERFMON_EVENTSEL1 0x187
+
+#define ARCH_PERFMON_EVENTSEL0_ENABLE (1 << 22)
+#define ARCH_PERFMON_EVENTSEL_INT (1 << 20)
+#define ARCH_PERFMON_EVENTSEL_OS (1 << 17)
+#define ARCH_PERFMON_EVENTSEL_USR (1 << 16)
+
+#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL (0x3c)
+#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK (0x00 << 8)
+#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX (0)
+#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT \
+ (1 << (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX))
+
+union cpuid10_eax {
+ struct {
+ unsigned int version_id:8;
+ unsigned int num_counters:8;
+ unsigned int bit_width:8;
+ unsigned int mask_length:8;
+ } split;
+ unsigned int full;
+};
+
+#endif /* _ASM_X86_INTEL_ARCH_PERFMON_H */
diff --git a/include/asm-x86/intel_arch_perfmon_32.h b/include/asm-x86/intel_arch_perfmon_32.h
deleted file mode 100644
index b52cd60a075b..000000000000
--- a/include/asm-x86/intel_arch_perfmon_32.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef X86_INTEL_ARCH_PERFMON_H
-#define X86_INTEL_ARCH_PERFMON_H 1
-
-#define MSR_ARCH_PERFMON_PERFCTR0 0xc1
-#define MSR_ARCH_PERFMON_PERFCTR1 0xc2
-
-#define MSR_ARCH_PERFMON_EVENTSEL0 0x186
-#define MSR_ARCH_PERFMON_EVENTSEL1 0x187
-
-#define ARCH_PERFMON_EVENTSEL0_ENABLE (1 << 22)
-#define ARCH_PERFMON_EVENTSEL_INT (1 << 20)
-#define ARCH_PERFMON_EVENTSEL_OS (1 << 17)
-#define ARCH_PERFMON_EVENTSEL_USR (1 << 16)
-
-#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL (0x3c)
-#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK (0x00 << 8)
-#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX (0)
-#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT \
- (1 << (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX))
-
-union cpuid10_eax {
- struct {
- unsigned int version_id:8;
- unsigned int num_counters:8;
- unsigned int bit_width:8;
- unsigned int mask_length:8;
- } split;
- unsigned int full;
-};
-
-#endif /* X86_INTEL_ARCH_PERFMON_H */
diff --git a/include/asm-x86/intel_arch_perfmon_64.h b/include/asm-x86/intel_arch_perfmon_64.h
deleted file mode 100644
index 8633331420ec..000000000000
--- a/include/asm-x86/intel_arch_perfmon_64.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef X86_64_INTEL_ARCH_PERFMON_H
-#define X86_64_INTEL_ARCH_PERFMON_H 1
-
-#define MSR_ARCH_PERFMON_PERFCTR0 0xc1
-#define MSR_ARCH_PERFMON_PERFCTR1 0xc2
-
-#define MSR_ARCH_PERFMON_EVENTSEL0 0x186
-#define MSR_ARCH_PERFMON_EVENTSEL1 0x187
-
-#define ARCH_PERFMON_EVENTSEL0_ENABLE (1 << 22)
-#define ARCH_PERFMON_EVENTSEL_INT (1 << 20)
-#define ARCH_PERFMON_EVENTSEL_OS (1 << 17)
-#define ARCH_PERFMON_EVENTSEL_USR (1 << 16)
-
-#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL (0x3c)
-#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK (0x00 << 8)
-#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX (0)
-#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT \
- (1 << (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX))
-
-union cpuid10_eax {
- struct {
- unsigned int version_id:8;
- unsigned int num_counters:8;
- unsigned int bit_width:8;
- unsigned int mask_length:8;
- } split;
- unsigned int full;
-};
-
-#endif /* X86_64_INTEL_ARCH_PERFMON_H */
diff --git a/include/asm-x86/io_32.h b/include/asm-x86/io_32.h
index e8e0bd641120..fe881cd1e6f4 100644
--- a/include/asm-x86/io_32.h
+++ b/include/asm-x86/io_32.h
@@ -199,17 +199,22 @@ static inline void writel(unsigned int b, volatile void __iomem *addr)
#define mmiowb()
-static inline void memset_io(volatile void __iomem *addr, unsigned char val, int count)
+static inline void
+memset_io(volatile void __iomem *addr, unsigned char val, int count)
{
- memset((void __force *) addr, val, count);
+ memset((void __force *)addr, val, count);
}
-static inline void memcpy_fromio(void *dst, const volatile void __iomem *src, int count)
+
+static inline void
+memcpy_fromio(void *dst, const volatile void __iomem *src, int count)
{
- __memcpy(dst, (void __force *) src, count);
+ __memcpy(dst, (const void __force *)src, count);
}
-static inline void memcpy_toio(volatile void __iomem *dst, const void *src, int count)
+
+static inline void
+memcpy_toio(volatile void __iomem *dst, const void *src, int count)
{
- __memcpy((void __force *) dst, src, count);
+ __memcpy((void __force *)dst, src, count);
}
/*
@@ -237,18 +242,9 @@ static inline void flush_write_buffers(void)
__asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory");
}
-#define dma_cache_inv(_start,_size) flush_write_buffers()
-#define dma_cache_wback(_start,_size) flush_write_buffers()
-#define dma_cache_wback_inv(_start,_size) flush_write_buffers()
-
#else
-/* Nothing to do */
-
-#define dma_cache_inv(_start,_size) do { } while (0)
-#define dma_cache_wback(_start,_size) do { } while (0)
-#define dma_cache_wback_inv(_start,_size) do { } while (0)
-#define flush_write_buffers()
+#define flush_write_buffers() do { } while (0)
#endif
diff --git a/include/asm-x86/io_64.h b/include/asm-x86/io_64.h
index 7475095c5061..a037b0794332 100644
--- a/include/asm-x86/io_64.h
+++ b/include/asm-x86/io_64.h
@@ -249,12 +249,6 @@ void memset_io(volatile void __iomem *a, int b, size_t c);
*/
#define __ISA_IO_base ((char __iomem *)(PAGE_OFFSET))
-/* Nothing to do */
-
-#define dma_cache_inv(_start,_size) do { } while (0)
-#define dma_cache_wback(_start,_size) do { } while (0)
-#define dma_cache_wback_inv(_start,_size) do { } while (0)
-
#define flush_write_buffers()
extern int iommu_bio_merge;
diff --git a/include/asm-x86/io_apic_64.h b/include/asm-x86/io_apic_64.h
index d9f2e54324d5..e2c13675ee4e 100644
--- a/include/asm-x86/io_apic_64.h
+++ b/include/asm-x86/io_apic_64.h
@@ -133,4 +133,6 @@ void enable_NMI_through_LVT0 (void * dummy);
extern spinlock_t i8259A_lock;
+extern int timer_over_8254;
+
#endif
diff --git a/include/asm-x86/ioctls.h b/include/asm-x86/ioctls.h
index 1e0fd48f18bc..93c894dc5154 100644
--- a/include/asm-x86/ioctls.h
+++ b/include/asm-x86/ioctls.h
@@ -1,13 +1,87 @@
-#ifdef __KERNEL__
-# ifdef CONFIG_X86_32
-# include "ioctls_32.h"
-# else
-# include "ioctls_64.h"
-# endif
-#else
-# ifdef __i386__
-# include "ioctls_32.h"
-# else
-# include "ioctls_64.h"
-# endif
+#ifndef _ASM_X86_IOCTLS_H
+#define _ASM_X86_IOCTLS_H
+
+#include <asm/ioctl.h>
+
+/* 0x54 is just a magic number to make these relatively unique ('T') */
+
+#define TCGETS 0x5401
+#define TCSETS 0x5402 /* Clashes with SNDCTL_TMR_START sound ioctl */
+#define TCSETSW 0x5403
+#define TCSETSF 0x5404
+#define TCGETA 0x5405
+#define TCSETA 0x5406
+#define TCSETAW 0x5407
+#define TCSETAF 0x5408
+#define TCSBRK 0x5409
+#define TCXONC 0x540A
+#define TCFLSH 0x540B
+#define TIOCEXCL 0x540C
+#define TIOCNXCL 0x540D
+#define TIOCSCTTY 0x540E
+#define TIOCGPGRP 0x540F
+#define TIOCSPGRP 0x5410
+#define TIOCOUTQ 0x5411
+#define TIOCSTI 0x5412
+#define TIOCGWINSZ 0x5413
+#define TIOCSWINSZ 0x5414
+#define TIOCMGET 0x5415
+#define TIOCMBIS 0x5416
+#define TIOCMBIC 0x5417
+#define TIOCMSET 0x5418
+#define TIOCGSOFTCAR 0x5419
+#define TIOCSSOFTCAR 0x541A
+#define FIONREAD 0x541B
+#define TIOCINQ FIONREAD
+#define TIOCLINUX 0x541C
+#define TIOCCONS 0x541D
+#define TIOCGSERIAL 0x541E
+#define TIOCSSERIAL 0x541F
+#define TIOCPKT 0x5420
+#define FIONBIO 0x5421
+#define TIOCNOTTY 0x5422
+#define TIOCSETD 0x5423
+#define TIOCGETD 0x5424
+#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
+/* #define TIOCTTYGSTRUCT 0x5426 - Former debugging-only ioctl */
+#define TIOCSBRK 0x5427 /* BSD compatibility */
+#define TIOCCBRK 0x5428 /* BSD compatibility */
+#define TIOCGSID 0x5429 /* Return the session ID of FD */
+#define TCGETS2 _IOR('T',0x2A, struct termios2)
+#define TCSETS2 _IOW('T',0x2B, struct termios2)
+#define TCSETSW2 _IOW('T',0x2C, struct termios2)
+#define TCSETSF2 _IOW('T',0x2D, struct termios2)
+#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
+#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
+
+#define FIONCLEX 0x5450
+#define FIOCLEX 0x5451
+#define FIOASYNC 0x5452
+#define TIOCSERCONFIG 0x5453
+#define TIOCSERGWILD 0x5454
+#define TIOCSERSWILD 0x5455
+#define TIOCGLCKTRMIOS 0x5456
+#define TIOCSLCKTRMIOS 0x5457
+#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
+#define TIOCSERGETLSR 0x5459 /* Get line status register */
+#define TIOCSERGETMULTI 0x545A /* Get multiport config */
+#define TIOCSERSETMULTI 0x545B /* Set multiport config */
+
+#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
+#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
+#define TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */
+#define TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */
+#define FIOQSIZE 0x5460
+
+/* Used for packet mode */
+#define TIOCPKT_DATA 0
+#define TIOCPKT_FLUSHREAD 1
+#define TIOCPKT_FLUSHWRITE 2
+#define TIOCPKT_STOP 4
+#define TIOCPKT_START 8
+#define TIOCPKT_NOSTOP 16
+#define TIOCPKT_DOSTOP 32
+
+#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
+
#endif
diff --git a/include/asm-x86/ioctls_32.h b/include/asm-x86/ioctls_32.h
deleted file mode 100644
index ef5878762dc9..000000000000
--- a/include/asm-x86/ioctls_32.h
+++ /dev/null
@@ -1,87 +0,0 @@
-#ifndef __ARCH_I386_IOCTLS_H__
-#define __ARCH_I386_IOCTLS_H__
-
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS 0x5401
-#define TCSETS 0x5402 /* Clashes with SNDCTL_TMR_START sound ioctl */
-#define TCSETSW 0x5403
-#define TCSETSF 0x5404
-#define TCGETA 0x5405
-#define TCSETA 0x5406
-#define TCSETAW 0x5407
-#define TCSETAF 0x5408
-#define TCSBRK 0x5409
-#define TCXONC 0x540A
-#define TCFLSH 0x540B
-#define TIOCEXCL 0x540C
-#define TIOCNXCL 0x540D
-#define TIOCSCTTY 0x540E
-#define TIOCGPGRP 0x540F
-#define TIOCSPGRP 0x5410
-#define TIOCOUTQ 0x5411
-#define TIOCSTI 0x5412
-#define TIOCGWINSZ 0x5413
-#define TIOCSWINSZ 0x5414
-#define TIOCMGET 0x5415
-#define TIOCMBIS 0x5416
-#define TIOCMBIC 0x5417
-#define TIOCMSET 0x5418
-#define TIOCGSOFTCAR 0x5419
-#define TIOCSSOFTCAR 0x541A
-#define FIONREAD 0x541B
-#define TIOCINQ FIONREAD
-#define TIOCLINUX 0x541C
-#define TIOCCONS 0x541D
-#define TIOCGSERIAL 0x541E
-#define TIOCSSERIAL 0x541F
-#define TIOCPKT 0x5420
-#define FIONBIO 0x5421
-#define TIOCNOTTY 0x5422
-#define TIOCSETD 0x5423
-#define TIOCGETD 0x5424
-#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
-/* #define TIOCTTYGSTRUCT 0x5426 - Former debugging-only ioctl */
-#define TIOCSBRK 0x5427 /* BSD compatibility */
-#define TIOCCBRK 0x5428 /* BSD compatibility */
-#define TIOCGSID 0x5429 /* Return the session ID of FD */
-#define TCGETS2 _IOR('T',0x2A, struct termios2)
-#define TCSETS2 _IOW('T',0x2B, struct termios2)
-#define TCSETSW2 _IOW('T',0x2C, struct termios2)
-#define TCSETSF2 _IOW('T',0x2D, struct termios2)
-#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
-
-#define FIONCLEX 0x5450
-#define FIOCLEX 0x5451
-#define FIOASYNC 0x5452
-#define TIOCSERCONFIG 0x5453
-#define TIOCSERGWILD 0x5454
-#define TIOCSERSWILD 0x5455
-#define TIOCGLCKTRMIOS 0x5456
-#define TIOCSLCKTRMIOS 0x5457
-#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
-#define TIOCSERGETLSR 0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
-#define TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */
-#define TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */
-#define FIOQSIZE 0x5460
-
-/* Used for packet mode */
-#define TIOCPKT_DATA 0
-#define TIOCPKT_FLUSHREAD 1
-#define TIOCPKT_FLUSHWRITE 2
-#define TIOCPKT_STOP 4
-#define TIOCPKT_START 8
-#define TIOCPKT_NOSTOP 16
-#define TIOCPKT_DOSTOP 32
-
-#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
-
-#endif
diff --git a/include/asm-x86/ioctls_64.h b/include/asm-x86/ioctls_64.h
deleted file mode 100644
index 3fc0b15a0d7e..000000000000
--- a/include/asm-x86/ioctls_64.h
+++ /dev/null
@@ -1,86 +0,0 @@
-#ifndef __ARCH_X8664_IOCTLS_H__
-#define __ARCH_X8664_IOCTLS_H__
-
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS 0x5401
-#define TCSETS 0x5402
-#define TCSETSW 0x5403
-#define TCSETSF 0x5404
-#define TCGETA 0x5405
-#define TCSETA 0x5406
-#define TCSETAW 0x5407
-#define TCSETAF 0x5408
-#define TCSBRK 0x5409
-#define TCXONC 0x540A
-#define TCFLSH 0x540B
-#define TIOCEXCL 0x540C
-#define TIOCNXCL 0x540D
-#define TIOCSCTTY 0x540E
-#define TIOCGPGRP 0x540F
-#define TIOCSPGRP 0x5410
-#define TIOCOUTQ 0x5411
-#define TIOCSTI 0x5412
-#define TIOCGWINSZ 0x5413
-#define TIOCSWINSZ 0x5414
-#define TIOCMGET 0x5415
-#define TIOCMBIS 0x5416
-#define TIOCMBIC 0x5417
-#define TIOCMSET 0x5418
-#define TIOCGSOFTCAR 0x5419
-#define TIOCSSOFTCAR 0x541A
-#define FIONREAD 0x541B
-#define TIOCINQ FIONREAD
-#define TIOCLINUX 0x541C
-#define TIOCCONS 0x541D
-#define TIOCGSERIAL 0x541E
-#define TIOCSSERIAL 0x541F
-#define TIOCPKT 0x5420
-#define FIONBIO 0x5421
-#define TIOCNOTTY 0x5422
-#define TIOCSETD 0x5423
-#define TIOCGETD 0x5424
-#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
-#define TIOCSBRK 0x5427 /* BSD compatibility */
-#define TIOCCBRK 0x5428 /* BSD compatibility */
-#define TIOCGSID 0x5429 /* Return the session ID of FD */
-#define TCGETS2 _IOR('T',0x2A, struct termios2)
-#define TCSETS2 _IOW('T',0x2B, struct termios2)
-#define TCSETSW2 _IOW('T',0x2C, struct termios2)
-#define TCSETSF2 _IOW('T',0x2D, struct termios2)
-#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
-
-#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
-#define FIOCLEX 0x5451
-#define FIOASYNC 0x5452
-#define TIOCSERCONFIG 0x5453
-#define TIOCSERGWILD 0x5454
-#define TIOCSERSWILD 0x5455
-#define TIOCGLCKTRMIOS 0x5456
-#define TIOCSLCKTRMIOS 0x5457
-#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
-#define TIOCSERGETLSR 0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
-#define TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */
-#define TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */
-#define FIOQSIZE 0x5460
-
-/* Used for packet mode */
-#define TIOCPKT_DATA 0
-#define TIOCPKT_FLUSHREAD 1
-#define TIOCPKT_FLUSHWRITE 2
-#define TIOCPKT_STOP 4
-#define TIOCPKT_START 8
-#define TIOCPKT_NOSTOP 16
-#define TIOCPKT_DOSTOP 32
-
-#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
-
-#endif
diff --git a/include/asm-x86/iommu.h b/include/asm-x86/iommu.h
index 5af471f228ee..07862fdd23c0 100644
--- a/include/asm-x86/iommu.h
+++ b/include/asm-x86/iommu.h
@@ -1,5 +1,5 @@
-#ifndef _ASM_X8664_IOMMU_H
-#define _ASM_X8664_IOMMU_H 1
+#ifndef _ASM_X8664_GART_H
+#define _ASM_X8664_GART_H 1
extern void pci_iommu_shutdown(void);
extern void no_iommu_init(void);
diff --git a/include/asm-x86/ipc.h b/include/asm-x86/ipc.h
deleted file mode 100644
index a46e3d9c2a3f..000000000000
--- a/include/asm-x86/ipc.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ipc.h>
diff --git a/include/asm-x86/ipcbuf.h b/include/asm-x86/ipcbuf.h
index eb2e448c6e28..2adf8b39a40b 100644
--- a/include/asm-x86/ipcbuf.h
+++ b/include/asm-x86/ipcbuf.h
@@ -1,13 +1,29 @@
-#ifdef __KERNEL__
-# ifdef CONFIG_X86_32
-# include "ipcbuf_32.h"
-# else
-# include "ipcbuf_64.h"
-# endif
-#else
-# ifdef __i386__
-# include "ipcbuf_32.h"
-# else
-# include "ipcbuf_64.h"
-# endif
-#endif
+#ifndef _ASM_X86_IPCBUF_H
+#define _ASM_X86_IPCBUF_H
+
+/*
+ * The ipc64_perm structure for x86 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 32-bit mode_t and seq
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct ipc64_perm
+{
+ __kernel_key_t key;
+ __kernel_uid32_t uid;
+ __kernel_gid32_t gid;
+ __kernel_uid32_t cuid;
+ __kernel_gid32_t cgid;
+ __kernel_mode_t mode;
+ unsigned short __pad1;
+ unsigned short seq;
+ unsigned short __pad2;
+ unsigned long __unused1;
+ unsigned long __unused2;
+};
+
+#endif /* _ASM_X86_IPCBUF_H */
diff --git a/include/asm-x86/ipcbuf_32.h b/include/asm-x86/ipcbuf_32.h
deleted file mode 100644
index 0dcad4f84c2a..000000000000
--- a/include/asm-x86/ipcbuf_32.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef __i386_IPCBUF_H__
-#define __i386_IPCBUF_H__
-
-/*
- * The ipc64_perm structure for i386 architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 32-bit mode_t and seq
- * - 2 miscellaneous 32-bit values
- */
-
-struct ipc64_perm
-{
- __kernel_key_t key;
- __kernel_uid32_t uid;
- __kernel_gid32_t gid;
- __kernel_uid32_t cuid;
- __kernel_gid32_t cgid;
- __kernel_mode_t mode;
- unsigned short __pad1;
- unsigned short seq;
- unsigned short __pad2;
- unsigned long __unused1;
- unsigned long __unused2;
-};
-
-#endif /* __i386_IPCBUF_H__ */
diff --git a/include/asm-x86/ipcbuf_64.h b/include/asm-x86/ipcbuf_64.h
deleted file mode 100644
index 470cf85e3ba8..000000000000
--- a/include/asm-x86/ipcbuf_64.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef __x86_64_IPCBUF_H__
-#define __x86_64_IPCBUF_H__
-
-/*
- * The ipc64_perm structure for x86_64 architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 32-bit mode_t and seq
- * - 2 miscellaneous 32-bit values
- */
-
-struct ipc64_perm
-{
- __kernel_key_t key;
- __kernel_uid32_t uid;
- __kernel_gid32_t gid;
- __kernel_uid32_t cuid;
- __kernel_gid32_t cgid;
- __kernel_mode_t mode;
- unsigned short __pad1;
- unsigned short seq;
- unsigned short __pad2;
- unsigned long __unused1;
- unsigned long __unused2;
-};
-
-#endif /* __x86_64_IPCBUF_H__ */
diff --git a/include/asm-x86/ipi.h b/include/asm-x86/ipi.h
index a7c75ea408a8..6d011bd6067d 100644
--- a/include/asm-x86/ipi.h
+++ b/include/asm-x86/ipi.h
@@ -119,7 +119,7 @@ static inline void send_IPI_mask_sequence(cpumask_t mask, int vector)
*/
local_irq_save(flags);
for_each_cpu_mask(query_cpu, mask) {
- __send_IPI_dest_field(x86_cpu_to_apicid[query_cpu],
+ __send_IPI_dest_field(per_cpu(x86_cpu_to_apicid, query_cpu),
vector, APIC_DEST_PHYSICAL);
}
local_irq_restore(flags);
diff --git a/include/asm-x86/irq_32.h b/include/asm-x86/irq_32.h
index 36f310632c49..aca9c96e8e6b 100644
--- a/include/asm-x86/irq_32.h
+++ b/include/asm-x86/irq_32.h
@@ -45,4 +45,7 @@ unsigned int do_IRQ(struct pt_regs *regs);
void init_IRQ(void);
void __init native_init_IRQ(void);
+/* Interrupt vector management */
+extern DECLARE_BITMAP(used_vectors, NR_VECTORS);
+
#endif /* _ASM_IRQ_H */
diff --git a/include/asm-x86/irqflags_32.h b/include/asm-x86/irqflags_32.h
index d058b04e0083..4c7720089cb5 100644
--- a/include/asm-x86/irqflags_32.h
+++ b/include/asm-x86/irqflags_32.h
@@ -129,6 +129,27 @@ static inline int raw_irqs_disabled(void)
return raw_irqs_disabled_flags(flags);
}
+
+/*
+ * makes the traced hardirq state match with the machine state
+ *
+ * should be a rarely used function, only in places where its
+ * otherwise impossible to know the irq state, like in traps.
+ */
+static inline void trace_hardirqs_fixup_flags(unsigned long flags)
+{
+ if (raw_irqs_disabled_flags(flags))
+ trace_hardirqs_off();
+ else
+ trace_hardirqs_on();
+}
+
+static inline void trace_hardirqs_fixup(void)
+{
+ unsigned long flags = __raw_local_save_flags();
+
+ trace_hardirqs_fixup_flags(flags);
+}
#endif /* __ASSEMBLY__ */
/*
diff --git a/include/asm-x86/irqflags_64.h b/include/asm-x86/irqflags_64.h
index 5341ea1f815a..bb9163bb29d1 100644
--- a/include/asm-x86/irqflags_64.h
+++ b/include/asm-x86/irqflags_64.h
@@ -112,6 +112,26 @@ static inline int raw_irqs_disabled(void)
}
/*
+ * makes the traced hardirq state match with the machine state
+ *
+ * should be a rarely used function, only in places where its
+ * otherwise impossible to know the irq state, like in traps.
+ */
+static inline void trace_hardirqs_fixup_flags(unsigned long flags)
+{
+ if (raw_irqs_disabled_flags(flags))
+ trace_hardirqs_off();
+ else
+ trace_hardirqs_on();
+}
+
+static inline void trace_hardirqs_fixup(void)
+{
+ unsigned long flags = __raw_local_save_flags();
+
+ trace_hardirqs_fixup_flags(flags);
+}
+/*
* Used in the idle loop; sti takes one instruction cycle
* to complete:
*/
diff --git a/include/asm-x86/ist.h b/include/asm-x86/ist.h
index ef2003ebc6f9..6ec6ceed95a7 100644
--- a/include/asm-x86/ist.h
+++ b/include/asm-x86/ist.h
@@ -17,17 +17,17 @@
*/
-#ifdef __KERNEL__
-
#include <linux/types.h>
struct ist_info {
- u32 signature;
- u32 command;
- u32 event;
- u32 perf_level;
+ __u32 signature;
+ __u32 command;
+ __u32 event;
+ __u32 perf_level;
};
+#ifdef __KERNEL__
+
extern struct ist_info ist_info;
#endif /* __KERNEL__ */
diff --git a/include/asm-x86/kdebug.h b/include/asm-x86/kdebug.h
index 38479106c259..e2f9b62e535e 100644
--- a/include/asm-x86/kdebug.h
+++ b/include/asm-x86/kdebug.h
@@ -1,5 +1,33 @@
-#ifdef CONFIG_X86_32
-# include "kdebug_32.h"
-#else
-# include "kdebug_64.h"
+#ifndef _ASM_X86_KDEBUG_H
+#define _ASM_X86_KDEBUG_H
+
+#include <linux/notifier.h>
+
+struct pt_regs;
+
+/* Grossly misnamed. */
+enum die_val {
+ DIE_OOPS = 1,
+ DIE_INT3,
+ DIE_DEBUG,
+ DIE_PANIC,
+ DIE_NMI,
+ DIE_DIE,
+ DIE_NMIWATCHDOG,
+ DIE_KERNELDEBUG,
+ DIE_TRAP,
+ DIE_GPF,
+ DIE_CALL,
+ DIE_NMI_IPI,
+ DIE_PAGE_FAULT,
+};
+
+extern void printk_address(unsigned long address);
+extern void die(const char *,struct pt_regs *,long);
+extern void __die(const char *,struct pt_regs *,long);
+extern void show_registers(struct pt_regs *regs);
+extern void dump_pagetable(unsigned long);
+extern unsigned long oops_begin(void);
+extern void oops_end(unsigned long);
+
#endif
diff --git a/include/asm-x86/kdebug_32.h b/include/asm-x86/kdebug_32.h
deleted file mode 100644
index a185b5f73e7f..000000000000
--- a/include/asm-x86/kdebug_32.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef _I386_KDEBUG_H
-#define _I386_KDEBUG_H 1
-
-/*
- * Aug-05 2004 Ported by Prasanna S Panchamukhi <prasanna@in.ibm.com>
- * from x86_64 architecture.
- */
-#include <linux/notifier.h>
-
-struct pt_regs;
-
-extern int register_page_fault_notifier(struct notifier_block *);
-extern int unregister_page_fault_notifier(struct notifier_block *);
-
-
-/* Grossly misnamed. */
-enum die_val {
- DIE_OOPS = 1,
- DIE_INT3,
- DIE_DEBUG,
- DIE_PANIC,
- DIE_NMI,
- DIE_DIE,
- DIE_NMIWATCHDOG,
- DIE_KERNELDEBUG,
- DIE_TRAP,
- DIE_GPF,
- DIE_CALL,
- DIE_NMI_IPI,
- DIE_PAGE_FAULT,
-};
-
-#endif
diff --git a/include/asm-x86/kdebug_64.h b/include/asm-x86/kdebug_64.h
deleted file mode 100644
index d7e2bcf49e4f..000000000000
--- a/include/asm-x86/kdebug_64.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef _X86_64_KDEBUG_H
-#define _X86_64_KDEBUG_H 1
-
-#include <linux/notifier.h>
-
-struct pt_regs;
-
-extern int register_page_fault_notifier(struct notifier_block *);
-extern int unregister_page_fault_notifier(struct notifier_block *);
-
-/* Grossly misnamed. */
-enum die_val {
- DIE_OOPS = 1,
- DIE_INT3,
- DIE_DEBUG,
- DIE_PANIC,
- DIE_NMI,
- DIE_DIE,
- DIE_NMIWATCHDOG,
- DIE_KERNELDEBUG,
- DIE_TRAP,
- DIE_GPF,
- DIE_CALL,
- DIE_NMI_IPI,
- DIE_PAGE_FAULT,
-};
-
-extern void printk_address(unsigned long address);
-extern void die(const char *,struct pt_regs *,long);
-extern void __die(const char *,struct pt_regs *,long);
-extern void show_registers(struct pt_regs *regs);
-extern void dump_pagetable(unsigned long);
-extern unsigned long oops_begin(void);
-extern void oops_end(unsigned long);
-
-#endif
diff --git a/include/asm-x86/kmap_types.h b/include/asm-x86/kmap_types.h
index e4ec724b298e..5f4174132a22 100644
--- a/include/asm-x86/kmap_types.h
+++ b/include/asm-x86/kmap_types.h
@@ -1,5 +1,29 @@
-#ifdef CONFIG_X86_32
-# include "kmap_types_32.h"
+#ifndef _ASM_X86_KMAP_TYPES_H
+#define _ASM_X86_KMAP_TYPES_H
+
+#if defined(CONFIG_X86_32) && defined(CONFIG_DEBUG_HIGHMEM)
+# define D(n) __KM_FENCE_##n ,
#else
-# include "kmap_types_64.h"
+# define D(n)
+#endif
+
+enum km_type {
+D(0) KM_BOUNCE_READ,
+D(1) KM_SKB_SUNRPC_DATA,
+D(2) KM_SKB_DATA_SOFTIRQ,
+D(3) KM_USER0,
+D(4) KM_USER1,
+D(5) KM_BIO_SRC_IRQ,
+D(6) KM_BIO_DST_IRQ,
+D(7) KM_PTE0,
+D(8) KM_PTE1,
+D(9) KM_IRQ0,
+D(10) KM_IRQ1,
+D(11) KM_SOFTIRQ0,
+D(12) KM_SOFTIRQ1,
+D(13) KM_TYPE_NR
+};
+
+#undef D
+
#endif
diff --git a/include/asm-x86/kmap_types_32.h b/include/asm-x86/kmap_types_32.h
deleted file mode 100644
index 806aae3c5338..000000000000
--- a/include/asm-x86/kmap_types_32.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef _ASM_KMAP_TYPES_H
-#define _ASM_KMAP_TYPES_H
-
-
-#ifdef CONFIG_DEBUG_HIGHMEM
-# define D(n) __KM_FENCE_##n ,
-#else
-# define D(n)
-#endif
-
-enum km_type {
-D(0) KM_BOUNCE_READ,
-D(1) KM_SKB_SUNRPC_DATA,
-D(2) KM_SKB_DATA_SOFTIRQ,
-D(3) KM_USER0,
-D(4) KM_USER1,
-D(5) KM_BIO_SRC_IRQ,
-D(6) KM_BIO_DST_IRQ,
-D(7) KM_PTE0,
-D(8) KM_PTE1,
-D(9) KM_IRQ0,
-D(10) KM_IRQ1,
-D(11) KM_SOFTIRQ0,
-D(12) KM_SOFTIRQ1,
-D(13) KM_TYPE_NR
-};
-
-#undef D
-
-#endif
diff --git a/include/asm-x86/kmap_types_64.h b/include/asm-x86/kmap_types_64.h
deleted file mode 100644
index 7486338c6cea..000000000000
--- a/include/asm-x86/kmap_types_64.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef _ASM_KMAP_TYPES_H
-#define _ASM_KMAP_TYPES_H
-
-enum km_type {
- KM_BOUNCE_READ,
- KM_SKB_SUNRPC_DATA,
- KM_SKB_DATA_SOFTIRQ,
- KM_USER0,
- KM_USER1,
- KM_BIO_SRC_IRQ,
- KM_BIO_DST_IRQ,
- KM_IRQ0,
- KM_IRQ1,
- KM_SOFTIRQ0,
- KM_SOFTIRQ1,
- KM_TYPE_NR
-};
-
-#endif
diff --git a/include/asm-x86/kprobes_32.h b/include/asm-x86/kprobes_32.h
index 06f7303c30ca..b772d5b38685 100644
--- a/include/asm-x86/kprobes_32.h
+++ b/include/asm-x86/kprobes_32.h
@@ -43,9 +43,10 @@ typedef u8 kprobe_opcode_t;
: (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR)))
#define ARCH_SUPPORTS_KRETPROBES
-#define ARCH_INACTIVE_KPROBE_COUNT 0
#define flush_insn_slot(p) do { } while (0)
+extern const int kretprobe_blacklist_size;
+
void arch_remove_kprobe(struct kprobe *p);
void kretprobe_trampoline(void);
@@ -89,4 +90,5 @@ static inline void restore_interrupts(struct pt_regs *regs)
extern int kprobe_exceptions_notify(struct notifier_block *self,
unsigned long val, void *data);
+extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
#endif /* _ASM_KPROBES_H */
diff --git a/include/asm-x86/kprobes_64.h b/include/asm-x86/kprobes_64.h
index 7db825403e01..53f4d8507354 100644
--- a/include/asm-x86/kprobes_64.h
+++ b/include/asm-x86/kprobes_64.h
@@ -42,7 +42,7 @@ typedef u8 kprobe_opcode_t;
: (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR)))
#define ARCH_SUPPORTS_KRETPROBES
-#define ARCH_INACTIVE_KPROBE_COUNT 1
+extern const int kretprobe_blacklist_size;
void kretprobe_trampoline(void);
extern void arch_remove_kprobe(struct kprobe *p);
diff --git a/include/asm-x86/ldt.h b/include/asm-x86/ldt.h
index 3d9cc20d2ba4..20c597242b53 100644
--- a/include/asm-x86/ldt.h
+++ b/include/asm-x86/ldt.h
@@ -1,13 +1,40 @@
-#ifdef __KERNEL__
-# ifdef CONFIG_X86_32
-# include "ldt_32.h"
-# else
-# include "ldt_64.h"
-# endif
-#else
-# ifdef __i386__
-# include "ldt_32.h"
-# else
-# include "ldt_64.h"
-# endif
+/*
+ * ldt.h
+ *
+ * Definitions of structures used with the modify_ldt system call.
+ */
+#ifndef _ASM_X86_LDT_H
+#define _ASM_X86_LDT_H
+
+/* Maximum number of LDT entries supported. */
+#define LDT_ENTRIES 8192
+/* The size of each LDT entry. */
+#define LDT_ENTRY_SIZE 8
+
+#ifndef __ASSEMBLY__
+/*
+ * Note on 64bit base and limit is ignored and you cannot set DS/ES/CS
+ * not to the default values if you still want to do syscalls. This
+ * call is more for 32bit mode therefore.
+ */
+struct user_desc {
+ unsigned int entry_number;
+ unsigned int base_addr;
+ unsigned int limit;
+ unsigned int seg_32bit:1;
+ unsigned int contents:2;
+ unsigned int read_exec_only:1;
+ unsigned int limit_in_pages:1;
+ unsigned int seg_not_present:1;
+ unsigned int useable:1;
+#ifdef __x86_64__
+ unsigned int lm:1;
+#endif
+};
+
+#define MODIFY_LDT_CONTENTS_DATA 0
+#define MODIFY_LDT_CONTENTS_STACK 1
+#define MODIFY_LDT_CONTENTS_CODE 2
+
+#endif /* !__ASSEMBLY__ */
#endif
diff --git a/include/asm-x86/ldt_32.h b/include/asm-x86/ldt_32.h
deleted file mode 100644
index e9d3de1dee6c..000000000000
--- a/include/asm-x86/ldt_32.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * ldt.h
- *
- * Definitions of structures used with the modify_ldt system call.
- */
-#ifndef _LINUX_LDT_H
-#define _LINUX_LDT_H
-
-/* Maximum number of LDT entries supported. */
-#define LDT_ENTRIES 8192
-/* The size of each LDT entry. */
-#define LDT_ENTRY_SIZE 8
-
-#ifndef __ASSEMBLY__
-struct user_desc {
- unsigned int entry_number;
- unsigned long base_addr;
- unsigned int limit;
- unsigned int seg_32bit:1;
- unsigned int contents:2;
- unsigned int read_exec_only:1;
- unsigned int limit_in_pages:1;
- unsigned int seg_not_present:1;
- unsigned int useable:1;
-};
-
-#define MODIFY_LDT_CONTENTS_DATA 0
-#define MODIFY_LDT_CONTENTS_STACK 1
-#define MODIFY_LDT_CONTENTS_CODE 2
-
-#endif /* !__ASSEMBLY__ */
-#endif
diff --git a/include/asm-x86/ldt_64.h b/include/asm-x86/ldt_64.h
deleted file mode 100644
index 9ef647b890d2..000000000000
--- a/include/asm-x86/ldt_64.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * ldt.h
- *
- * Definitions of structures used with the modify_ldt system call.
- */
-#ifndef _LINUX_LDT_H
-#define _LINUX_LDT_H
-
-/* Maximum number of LDT entries supported. */
-#define LDT_ENTRIES 8192
-/* The size of each LDT entry. */
-#define LDT_ENTRY_SIZE 8
-
-#ifndef __ASSEMBLY__
-/* Note on 64bit base and limit is ignored and you cannot set
- DS/ES/CS not to the default values if you still want to do syscalls. This
- call is more for 32bit mode therefore. */
-struct user_desc {
- unsigned int entry_number;
- unsigned int base_addr;
- unsigned int limit;
- unsigned int seg_32bit:1;
- unsigned int contents:2;
- unsigned int read_exec_only:1;
- unsigned int limit_in_pages:1;
- unsigned int seg_not_present:1;
- unsigned int useable:1;
- unsigned int lm:1;
-};
-
-#define MODIFY_LDT_CONTENTS_DATA 0
-#define MODIFY_LDT_CONTENTS_STACK 1
-#define MODIFY_LDT_CONTENTS_CODE 2
-
-#endif /* !__ASSEMBLY__ */
-#endif
diff --git a/include/asm-x86/lguest.h b/include/asm-x86/lguest.h
new file mode 100644
index 000000000000..ccd338460811
--- /dev/null
+++ b/include/asm-x86/lguest.h
@@ -0,0 +1,86 @@
+#ifndef _X86_LGUEST_H
+#define _X86_LGUEST_H
+
+#define GDT_ENTRY_LGUEST_CS 10
+#define GDT_ENTRY_LGUEST_DS 11
+#define LGUEST_CS (GDT_ENTRY_LGUEST_CS * 8)
+#define LGUEST_DS (GDT_ENTRY_LGUEST_DS * 8)
+
+#ifndef __ASSEMBLY__
+#include <asm/desc.h>
+
+#define GUEST_PL 1
+
+/* Every guest maps the core switcher code. */
+#define SHARED_SWITCHER_PAGES \
+ DIV_ROUND_UP(end_switcher_text - start_switcher_text, PAGE_SIZE)
+/* Pages for switcher itself, then two pages per cpu */
+#define TOTAL_SWITCHER_PAGES (SHARED_SWITCHER_PAGES + 2 * NR_CPUS)
+
+/* We map at -4M for ease of mapping into the guest (one PTE page). */
+#define SWITCHER_ADDR 0xFFC00000
+
+/* Found in switcher.S */
+extern unsigned long default_idt_entries[];
+
+struct lguest_regs
+{
+ /* Manually saved part. */
+ unsigned long eax, ebx, ecx, edx;
+ unsigned long esi, edi, ebp;
+ unsigned long gs;
+ unsigned long fs, ds, es;
+ unsigned long trapnum, errcode;
+ /* Trap pushed part */
+ unsigned long eip;
+ unsigned long cs;
+ unsigned long eflags;
+ unsigned long esp;
+ unsigned long ss;
+};
+
+/* This is a guest-specific page (mapped ro) into the guest. */
+struct lguest_ro_state
+{
+ /* Host information we need to restore when we switch back. */
+ u32 host_cr3;
+ struct Xgt_desc_struct host_idt_desc;
+ struct Xgt_desc_struct host_gdt_desc;
+ u32 host_sp;
+
+ /* Fields which are used when guest is running. */
+ struct Xgt_desc_struct guest_idt_desc;
+ struct Xgt_desc_struct guest_gdt_desc;
+ struct i386_hw_tss guest_tss;
+ struct desc_struct guest_idt[IDT_ENTRIES];
+ struct desc_struct guest_gdt[GDT_ENTRIES];
+};
+
+struct lguest_arch
+{
+ /* The GDT entries copied into lguest_ro_state when running. */
+ struct desc_struct gdt[GDT_ENTRIES];
+
+ /* The IDT entries: some copied into lguest_ro_state when running. */
+ struct desc_struct idt[IDT_ENTRIES];
+
+ /* The address of the last guest-visible pagefault (ie. cr2). */
+ unsigned long last_pagefault;
+};
+
+static inline void lguest_set_ts(void)
+{
+ u32 cr0;
+
+ cr0 = read_cr0();
+ if (!(cr0 & 8))
+ write_cr0(cr0|8);
+}
+
+/* Full 4G segment descriptors, suitable for CS and DS. */
+#define FULL_EXEC_SEGMENT ((struct desc_struct){0x0000ffff, 0x00cf9b00})
+#define FULL_SEGMENT ((struct desc_struct){0x0000ffff, 0x00cf9300})
+
+#endif /* __ASSEMBLY__ */
+
+#endif
diff --git a/include/asm-x86/lguest_hcall.h b/include/asm-x86/lguest_hcall.h
new file mode 100644
index 000000000000..2091779e91fb
--- /dev/null
+++ b/include/asm-x86/lguest_hcall.h
@@ -0,0 +1,68 @@
+/* Architecture specific portion of the lguest hypercalls */
+#ifndef _X86_LGUEST_HCALL_H
+#define _X86_LGUEST_HCALL_H
+
+#define LHCALL_FLUSH_ASYNC 0
+#define LHCALL_LGUEST_INIT 1
+#define LHCALL_CRASH 2
+#define LHCALL_LOAD_GDT 3
+#define LHCALL_NEW_PGTABLE 4
+#define LHCALL_FLUSH_TLB 5
+#define LHCALL_LOAD_IDT_ENTRY 6
+#define LHCALL_SET_STACK 7
+#define LHCALL_TS 8
+#define LHCALL_SET_CLOCKEVENT 9
+#define LHCALL_HALT 10
+#define LHCALL_SET_PTE 14
+#define LHCALL_SET_PMD 15
+#define LHCALL_LOAD_TLS 16
+#define LHCALL_NOTIFY 17
+
+#define LGUEST_TRAP_ENTRY 0x1F
+
+#ifndef __ASSEMBLY__
+#include <asm/hw_irq.h>
+
+/*G:031 First, how does our Guest contact the Host to ask for privileged
+ * operations? There are two ways: the direct way is to make a "hypercall",
+ * to make requests of the Host Itself.
+ *
+ * Our hypercall mechanism uses the highest unused trap code (traps 32 and
+ * above are used by real hardware interrupts). Fifteen hypercalls are
+ * available: the hypercall number is put in the %eax register, and the
+ * arguments (when required) are placed in %edx, %ebx and %ecx. If a return
+ * value makes sense, it's returned in %eax.
+ *
+ * Grossly invalid calls result in Sudden Death at the hands of the vengeful
+ * Host, rather than returning failure. This reflects Winston Churchill's
+ * definition of a gentleman: "someone who is only rude intentionally". */
+static inline unsigned long
+hcall(unsigned long call,
+ unsigned long arg1, unsigned long arg2, unsigned long arg3)
+{
+ /* "int" is the Intel instruction to trigger a trap. */
+ asm volatile("int $" __stringify(LGUEST_TRAP_ENTRY)
+ /* The call in %eax (aka "a") might be overwritten */
+ : "=a"(call)
+ /* The arguments are in %eax, %edx, %ebx & %ecx */
+ : "a"(call), "d"(arg1), "b"(arg2), "c"(arg3)
+ /* "memory" means this might write somewhere in memory.
+ * This isn't true for all calls, but it's safe to tell
+ * gcc that it might happen so it doesn't get clever. */
+ : "memory");
+ return call;
+}
+/*:*/
+
+/* Can't use our min() macro here: needs to be a constant */
+#define LGUEST_IRQS (NR_IRQS < 32 ? NR_IRQS: 32)
+
+#define LHCALL_RING_SIZE 64
+struct hcall_args
+{
+ /* These map directly onto eax, ebx, ecx, edx in struct lguest_regs */
+ unsigned long arg0, arg2, arg3, arg1;
+};
+
+#endif /* !__ASSEMBLY__ */
+#endif /* _I386_LGUEST_HCALL_H */
diff --git a/include/asm-x86/mach-default/mach_apicdef.h b/include/asm-x86/mach-default/mach_apicdef.h
index 7bcb350c3ee8..ae9841319094 100644
--- a/include/asm-x86/mach-default/mach_apicdef.h
+++ b/include/asm-x86/mach-default/mach_apicdef.h
@@ -1,11 +1,17 @@
#ifndef __ASM_MACH_APICDEF_H
#define __ASM_MACH_APICDEF_H
+#include <asm/apic.h>
+
#define APIC_ID_MASK (0xF<<24)
static inline unsigned get_apic_id(unsigned long x)
{
- return (((x)>>24)&0xF);
+ unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR));
+ if (APIC_XAPIC(ver))
+ return (((x)>>24)&0xFF);
+ else
+ return (((x)>>24)&0xF);
}
#define GET_APIC_ID(x) get_apic_id(x)
diff --git a/include/asm-x86/mach-visws/cobalt.h b/include/asm-x86/mach-visws/cobalt.h
index 33c36225a042..995258831b7f 100644
--- a/include/asm-x86/mach-visws/cobalt.h
+++ b/include/asm-x86/mach-visws/cobalt.h
@@ -94,22 +94,22 @@
#define CO_IRQ_8259 CO_IRQ(CO_APIC_8259)
#ifdef CONFIG_X86_VISWS_APIC
-extern __inline void co_cpu_write(unsigned long reg, unsigned long v)
+static inline void co_cpu_write(unsigned long reg, unsigned long v)
{
*((volatile unsigned long *)(CO_CPU_VADDR+reg))=v;
}
-extern __inline unsigned long co_cpu_read(unsigned long reg)
+static inline unsigned long co_cpu_read(unsigned long reg)
{
return *((volatile unsigned long *)(CO_CPU_VADDR+reg));
}
-extern __inline void co_apic_write(unsigned long reg, unsigned long v)
+static inline void co_apic_write(unsigned long reg, unsigned long v)
{
*((volatile unsigned long *)(CO_APIC_VADDR+reg))=v;
}
-extern __inline unsigned long co_apic_read(unsigned long reg)
+static inline unsigned long co_apic_read(unsigned long reg)
{
return *((volatile unsigned long *)(CO_APIC_VADDR+reg));
}
diff --git a/include/asm-x86/mach-visws/lithium.h b/include/asm-x86/mach-visws/lithium.h
index d443e68d0066..dfcd4f07ab85 100644
--- a/include/asm-x86/mach-visws/lithium.h
+++ b/include/asm-x86/mach-visws/lithium.h
@@ -29,22 +29,22 @@
#define LI_INTD 0x0080
/* More special purpose macros... */
-extern __inline void li_pcia_write16(unsigned long reg, unsigned short v)
+static inline void li_pcia_write16(unsigned long reg, unsigned short v)
{
*((volatile unsigned short *)(LI_PCIA_VADDR+reg))=v;
}
-extern __inline unsigned short li_pcia_read16(unsigned long reg)
+static inline unsigned short li_pcia_read16(unsigned long reg)
{
return *((volatile unsigned short *)(LI_PCIA_VADDR+reg));
}
-extern __inline void li_pcib_write16(unsigned long reg, unsigned short v)
+static inline void li_pcib_write16(unsigned long reg, unsigned short v)
{
*((volatile unsigned short *)(LI_PCIB_VADDR+reg))=v;
}
-extern __inline unsigned short li_pcib_read16(unsigned long reg)
+static inline unsigned short li_pcib_read16(unsigned long reg)
{
return *((volatile unsigned short *)(LI_PCIB_VADDR+reg));
}
diff --git a/include/asm-x86/mach-voyager/setup_arch.h b/include/asm-x86/mach-voyager/setup_arch.h
index 84d01ad33459..1710ae10eb67 100644
--- a/include/asm-x86/mach-voyager/setup_arch.h
+++ b/include/asm-x86/mach-voyager/setup_arch.h
@@ -1,5 +1,7 @@
#include <asm/voyager.h>
-#define VOYAGER_BIOS_INFO ((struct voyager_bios_info *)(PARAM+0x40))
+#include <asm/setup_32.h>
+#define VOYAGER_BIOS_INFO ((struct voyager_bios_info *) \
+ (&boot_params.apm_bios_info))
/* Hook to call BIOS initialisation function */
diff --git a/include/asm-x86/mce.h b/include/asm-x86/mce.h
index cc8ca389912e..df304fd89c27 100644
--- a/include/asm-x86/mce.h
+++ b/include/asm-x86/mce.h
@@ -1,5 +1,129 @@
+#ifndef _ASM_X86_MCE_H
+#define _ASM_X86_MCE_H
+
+#ifdef __x86_64__
+
+#include <asm/ioctls.h>
+#include <asm/types.h>
+
+/*
+ * Machine Check support for x86
+ */
+
+#define MCG_CTL_P (1UL<<8) /* MCG_CAP register available */
+
+#define MCG_STATUS_RIPV (1UL<<0) /* restart ip valid */
+#define MCG_STATUS_EIPV (1UL<<1) /* eip points to correct instruction */
+#define MCG_STATUS_MCIP (1UL<<2) /* machine check in progress */
+
+#define MCI_STATUS_VAL (1UL<<63) /* valid error */
+#define MCI_STATUS_OVER (1UL<<62) /* previous errors lost */
+#define MCI_STATUS_UC (1UL<<61) /* uncorrected error */
+#define MCI_STATUS_EN (1UL<<60) /* error enabled */
+#define MCI_STATUS_MISCV (1UL<<59) /* misc error reg. valid */
+#define MCI_STATUS_ADDRV (1UL<<58) /* addr reg. valid */
+#define MCI_STATUS_PCC (1UL<<57) /* processor context corrupt */
+
+/* Fields are zero when not available */
+struct mce {
+ __u64 status;
+ __u64 misc;
+ __u64 addr;
+ __u64 mcgstatus;
+ __u64 rip;
+ __u64 tsc; /* cpu time stamp counter */
+ __u64 res1; /* for future extension */
+ __u64 res2; /* dito. */
+ __u8 cs; /* code segment */
+ __u8 bank; /* machine check bank */
+ __u8 cpu; /* cpu that raised the error */
+ __u8 finished; /* entry is valid */
+ __u32 pad;
+};
+
+/*
+ * This structure contains all data related to the MCE log. Also
+ * carries a signature to make it easier to find from external
+ * debugging tools. Each entry is only valid when its finished flag
+ * is set.
+ */
+
+#define MCE_LOG_LEN 32
+
+struct mce_log {
+ char signature[12]; /* "MACHINECHECK" */
+ unsigned len; /* = MCE_LOG_LEN */
+ unsigned next;
+ unsigned flags;
+ unsigned pad0;
+ struct mce entry[MCE_LOG_LEN];
+};
+
+#define MCE_OVERFLOW 0 /* bit 0 in flags means overflow */
+
+#define MCE_LOG_SIGNATURE "MACHINECHECK"
+
+#define MCE_GET_RECORD_LEN _IOR('M', 1, int)
+#define MCE_GET_LOG_LEN _IOR('M', 2, int)
+#define MCE_GETCLEAR_FLAGS _IOR('M', 3, int)
+
+/* Software defined banks */
+#define MCE_EXTENDED_BANK 128
+#define MCE_THERMAL_BANK MCE_EXTENDED_BANK + 0
+
+#define K8_MCE_THRESHOLD_BASE (MCE_EXTENDED_BANK + 1) /* MCE_AMD */
+#define K8_MCE_THRESHOLD_BANK_0 (MCE_THRESHOLD_BASE + 0 * 9)
+#define K8_MCE_THRESHOLD_BANK_1 (MCE_THRESHOLD_BASE + 1 * 9)
+#define K8_MCE_THRESHOLD_BANK_2 (MCE_THRESHOLD_BASE + 2 * 9)
+#define K8_MCE_THRESHOLD_BANK_3 (MCE_THRESHOLD_BASE + 3 * 9)
+#define K8_MCE_THRESHOLD_BANK_4 (MCE_THRESHOLD_BASE + 4 * 9)
+#define K8_MCE_THRESHOLD_BANK_5 (MCE_THRESHOLD_BASE + 5 * 9)
+#define K8_MCE_THRESHOLD_DRAM_ECC (MCE_THRESHOLD_BANK_4 + 0)
+
+#endif /* __x86_64__ */
+
+#ifdef __KERNEL__
+
#ifdef CONFIG_X86_32
-# include "mce_32.h"
+#ifdef CONFIG_X86_MCE
+extern void mcheck_init(struct cpuinfo_x86 *c);
#else
-# include "mce_64.h"
+#define mcheck_init(c) do {} while(0)
+#endif
+
+extern int mce_disabled;
+
+#else /* CONFIG_X86_32 */
+
+#include <asm/atomic.h>
+
+void mce_log(struct mce *m);
+DECLARE_PER_CPU(struct sys_device, device_mce);
+
+#ifdef CONFIG_X86_MCE_INTEL
+void mce_intel_feature_init(struct cpuinfo_x86 *c);
+#else
+static inline void mce_intel_feature_init(struct cpuinfo_x86 *c) { }
+#endif
+
+#ifdef CONFIG_X86_MCE_AMD
+void mce_amd_feature_init(struct cpuinfo_x86 *c);
+#else
+static inline void mce_amd_feature_init(struct cpuinfo_x86 *c) { }
+#endif
+
+void mce_log_therm_throt_event(unsigned int cpu, __u64 status);
+
+extern atomic_t mce_entry;
+
+extern void do_machine_check(struct pt_regs *, long);
+extern int mce_notify_user(void);
+
+#endif /* !CONFIG_X86_32 */
+
+extern void stop_mce(void);
+extern void restart_mce(void);
+
+#endif /* __KERNEL__ */
+
#endif
diff --git a/include/asm-x86/mce_32.h b/include/asm-x86/mce_32.h
deleted file mode 100644
index d56d89742e8f..000000000000
--- a/include/asm-x86/mce_32.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifdef CONFIG_X86_MCE
-extern void mcheck_init(struct cpuinfo_x86 *c);
-#else
-#define mcheck_init(c) do {} while(0)
-#endif
-
-extern int mce_disabled;
-
-extern void stop_mce(void);
-extern void restart_mce(void);
-
diff --git a/include/asm-x86/mce_64.h b/include/asm-x86/mce_64.h
deleted file mode 100644
index 7bc030a1996d..000000000000
--- a/include/asm-x86/mce_64.h
+++ /dev/null
@@ -1,115 +0,0 @@
-#ifndef _ASM_MCE_H
-#define _ASM_MCE_H 1
-
-#include <asm/ioctls.h>
-#include <asm/types.h>
-
-/*
- * Machine Check support for x86
- */
-
-#define MCG_CTL_P (1UL<<8) /* MCG_CAP register available */
-
-#define MCG_STATUS_RIPV (1UL<<0) /* restart ip valid */
-#define MCG_STATUS_EIPV (1UL<<1) /* eip points to correct instruction */
-#define MCG_STATUS_MCIP (1UL<<2) /* machine check in progress */
-
-#define MCI_STATUS_VAL (1UL<<63) /* valid error */
-#define MCI_STATUS_OVER (1UL<<62) /* previous errors lost */
-#define MCI_STATUS_UC (1UL<<61) /* uncorrected error */
-#define MCI_STATUS_EN (1UL<<60) /* error enabled */
-#define MCI_STATUS_MISCV (1UL<<59) /* misc error reg. valid */
-#define MCI_STATUS_ADDRV (1UL<<58) /* addr reg. valid */
-#define MCI_STATUS_PCC (1UL<<57) /* processor context corrupt */
-
-/* Fields are zero when not available */
-struct mce {
- __u64 status;
- __u64 misc;
- __u64 addr;
- __u64 mcgstatus;
- __u64 rip;
- __u64 tsc; /* cpu time stamp counter */
- __u64 res1; /* for future extension */
- __u64 res2; /* dito. */
- __u8 cs; /* code segment */
- __u8 bank; /* machine check bank */
- __u8 cpu; /* cpu that raised the error */
- __u8 finished; /* entry is valid */
- __u32 pad;
-};
-
-/*
- * This structure contains all data related to the MCE log.
- * Also carries a signature to make it easier to find from external debugging tools.
- * Each entry is only valid when its finished flag is set.
- */
-
-#define MCE_LOG_LEN 32
-
-struct mce_log {
- char signature[12]; /* "MACHINECHECK" */
- unsigned len; /* = MCE_LOG_LEN */
- unsigned next;
- unsigned flags;
- unsigned pad0;
- struct mce entry[MCE_LOG_LEN];
-};
-
-#define MCE_OVERFLOW 0 /* bit 0 in flags means overflow */
-
-#define MCE_LOG_SIGNATURE "MACHINECHECK"
-
-#define MCE_GET_RECORD_LEN _IOR('M', 1, int)
-#define MCE_GET_LOG_LEN _IOR('M', 2, int)
-#define MCE_GETCLEAR_FLAGS _IOR('M', 3, int)
-
-/* Software defined banks */
-#define MCE_EXTENDED_BANK 128
-#define MCE_THERMAL_BANK MCE_EXTENDED_BANK + 0
-
-#define K8_MCE_THRESHOLD_BASE (MCE_EXTENDED_BANK + 1) /* MCE_AMD */
-#define K8_MCE_THRESHOLD_BANK_0 (MCE_THRESHOLD_BASE + 0 * 9)
-#define K8_MCE_THRESHOLD_BANK_1 (MCE_THRESHOLD_BASE + 1 * 9)
-#define K8_MCE_THRESHOLD_BANK_2 (MCE_THRESHOLD_BASE + 2 * 9)
-#define K8_MCE_THRESHOLD_BANK_3 (MCE_THRESHOLD_BASE + 3 * 9)
-#define K8_MCE_THRESHOLD_BANK_4 (MCE_THRESHOLD_BASE + 4 * 9)
-#define K8_MCE_THRESHOLD_BANK_5 (MCE_THRESHOLD_BASE + 5 * 9)
-#define K8_MCE_THRESHOLD_DRAM_ECC (MCE_THRESHOLD_BANK_4 + 0)
-
-#ifdef __KERNEL__
-#include <asm/atomic.h>
-
-void mce_log(struct mce *m);
-DECLARE_PER_CPU(struct sys_device, device_mce);
-
-#ifdef CONFIG_X86_MCE_INTEL
-void mce_intel_feature_init(struct cpuinfo_x86 *c);
-#else
-static inline void mce_intel_feature_init(struct cpuinfo_x86 *c)
-{
-}
-#endif
-
-#ifdef CONFIG_X86_MCE_AMD
-void mce_amd_feature_init(struct cpuinfo_x86 *c);
-#else
-static inline void mce_amd_feature_init(struct cpuinfo_x86 *c)
-{
-}
-#endif
-
-void mce_log_therm_throt_event(unsigned int cpu, __u64 status);
-
-extern atomic_t mce_entry;
-
-extern void do_machine_check(struct pt_regs *, long);
-
-extern int mce_notify_user(void);
-
-extern void stop_mce(void);
-extern void restart_mce(void);
-
-#endif
-
-#endif
diff --git a/include/asm-x86/mman.h b/include/asm-x86/mman.h
index 322db07e82c3..c1682b542daf 100644
--- a/include/asm-x86/mman.h
+++ b/include/asm-x86/mman.h
@@ -1,13 +1,19 @@
-#ifdef __KERNEL__
-# ifdef CONFIG_X86_32
-# include "mman_32.h"
-# else
-# include "mman_64.h"
-# endif
-#else
-# ifdef __i386__
-# include "mman_32.h"
-# else
-# include "mman_64.h"
-# endif
-#endif
+#ifndef _ASM_X86_MMAN_H
+#define _ASM_X86_MMAN_H
+
+#include <asm-generic/mman.h>
+
+#define MAP_32BIT 0x40 /* only give out 32bit addresses */
+
+#define MAP_GROWSDOWN 0x0100 /* stack-like segment */
+#define MAP_DENYWRITE 0x0800 /* ETXTBSY */
+#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */
+#define MAP_LOCKED 0x2000 /* pages are locked */
+#define MAP_NORESERVE 0x4000 /* don't check for reservations */
+#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
+#define MAP_NONBLOCK 0x10000 /* do not block on IO */
+
+#define MCL_CURRENT 1 /* lock all current mappings */
+#define MCL_FUTURE 2 /* lock all future mappings */
+
+#endif /* _ASM_X86_MMAN_H */
diff --git a/include/asm-x86/mman_32.h b/include/asm-x86/mman_32.h
deleted file mode 100644
index 8fd9d7ab7faf..000000000000
--- a/include/asm-x86/mman_32.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef __I386_MMAN_H__
-#define __I386_MMAN_H__
-
-#include <asm-generic/mman.h>
-
-#define MAP_GROWSDOWN 0x0100 /* stack-like segment */
-#define MAP_DENYWRITE 0x0800 /* ETXTBSY */
-#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */
-#define MAP_LOCKED 0x2000 /* pages are locked */
-#define MAP_NORESERVE 0x4000 /* don't check for reservations */
-#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
-#define MAP_NONBLOCK 0x10000 /* do not block on IO */
-
-#define MCL_CURRENT 1 /* lock all current mappings */
-#define MCL_FUTURE 2 /* lock all future mappings */
-
-#endif /* __I386_MMAN_H__ */
diff --git a/include/asm-x86/mman_64.h b/include/asm-x86/mman_64.h
deleted file mode 100644
index dd5cb0534d37..000000000000
--- a/include/asm-x86/mman_64.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef __X8664_MMAN_H__
-#define __X8664_MMAN_H__
-
-#include <asm-generic/mman.h>
-
-#define MAP_32BIT 0x40 /* only give out 32bit addresses */
-
-#define MAP_GROWSDOWN 0x0100 /* stack-like segment */
-#define MAP_DENYWRITE 0x0800 /* ETXTBSY */
-#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */
-#define MAP_LOCKED 0x2000 /* pages are locked */
-#define MAP_NORESERVE 0x4000 /* don't check for reservations */
-#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
-#define MAP_NONBLOCK 0x10000 /* do not block on IO */
-
-#define MCL_CURRENT 1 /* lock all current mappings */
-#define MCL_FUTURE 2 /* lock all future mappings */
-
-#endif
diff --git a/include/asm-x86/mmu.h b/include/asm-x86/mmu.h
index 9c628cd70e23..3f922c8e1c88 100644
--- a/include/asm-x86/mmu.h
+++ b/include/asm-x86/mmu.h
@@ -1,5 +1,23 @@
-#ifdef CONFIG_X86_32
-# include "mmu_32.h"
-#else
-# include "mmu_64.h"
+#ifndef _ASM_X86_MMU_H
+#define _ASM_X86_MMU_H
+
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+
+/*
+ * The x86 doesn't have a mmu context, but
+ * we put the segment information here.
+ *
+ * cpu_vm_mask is used to optimize ldt flushing.
+ */
+typedef struct {
+ void *ldt;
+#ifdef CONFIG_X86_64
+ rwlock_t ldtlock;
#endif
+ int size;
+ struct mutex lock;
+ void *vdso;
+} mm_context_t;
+
+#endif /* _ASM_X86_MMU_H */
diff --git a/include/asm-x86/mmu_32.h b/include/asm-x86/mmu_32.h
deleted file mode 100644
index 8358dd3df7aa..000000000000
--- a/include/asm-x86/mmu_32.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef __i386_MMU_H
-#define __i386_MMU_H
-
-#include <asm/semaphore.h>
-/*
- * The i386 doesn't have a mmu context, but
- * we put the segment information here.
- *
- * cpu_vm_mask is used to optimize ldt flushing.
- */
-typedef struct {
- int size;
- struct semaphore sem;
- void *ldt;
- void *vdso;
-} mm_context_t;
-
-#endif
diff --git a/include/asm-x86/mmu_64.h b/include/asm-x86/mmu_64.h
deleted file mode 100644
index d2cd4a9d984d..000000000000
--- a/include/asm-x86/mmu_64.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef __x86_64_MMU_H
-#define __x86_64_MMU_H
-
-#include <linux/spinlock.h>
-#include <asm/semaphore.h>
-
-/*
- * The x86_64 doesn't have a mmu context, but
- * we put the segment information here.
- *
- * cpu_vm_mask is used to optimize ldt flushing.
- */
-typedef struct {
- void *ldt;
- rwlock_t ldtlock;
- int size;
- struct semaphore sem;
- void *vdso;
-} mm_context_t;
-
-#endif
diff --git a/include/asm-x86/msgbuf.h b/include/asm-x86/msgbuf.h
index 154f7d64e862..7e4e9481f51c 100644
--- a/include/asm-x86/msgbuf.h
+++ b/include/asm-x86/msgbuf.h
@@ -1,13 +1,39 @@
-#ifdef __KERNEL__
-# ifdef CONFIG_X86_32
-# include "msgbuf_32.h"
-# else
-# include "msgbuf_64.h"
-# endif
-#else
-# ifdef __i386__
-# include "msgbuf_32.h"
-# else
-# include "msgbuf_64.h"
-# endif
+#ifndef _ASM_X86_MSGBUF_H
+#define _ASM_X86_MSGBUF_H
+
+/*
+ * The msqid64_ds structure for i386 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space on i386 is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ *
+ * Pad space on x8664 is left for:
+ * - 2 miscellaneous 64-bit values
+ */
+struct msqid64_ds {
+ struct ipc64_perm msg_perm;
+ __kernel_time_t msg_stime; /* last msgsnd time */
+#ifdef __i386__
+ unsigned long __unused1;
#endif
+ __kernel_time_t msg_rtime; /* last msgrcv time */
+#ifdef __i386__
+ unsigned long __unused2;
+#endif
+ __kernel_time_t msg_ctime; /* last change time */
+#ifdef __i386__
+ unsigned long __unused3;
+#endif
+ unsigned long msg_cbytes; /* current number of bytes on queue */
+ unsigned long msg_qnum; /* number of messages in queue */
+ unsigned long msg_qbytes; /* max number of bytes on queue */
+ __kernel_pid_t msg_lspid; /* pid of last msgsnd */
+ __kernel_pid_t msg_lrpid; /* last receive pid */
+ unsigned long __unused4;
+ unsigned long __unused5;
+};
+
+#endif /* _ASM_X86_MSGBUF_H */
diff --git a/include/asm-x86/msgbuf_32.h b/include/asm-x86/msgbuf_32.h
deleted file mode 100644
index b8d659c157ae..000000000000
--- a/include/asm-x86/msgbuf_32.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef _I386_MSGBUF_H
-#define _I386_MSGBUF_H
-
-/*
- * The msqid64_ds structure for i386 architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct msqid64_ds {
- struct ipc64_perm msg_perm;
- __kernel_time_t msg_stime; /* last msgsnd time */
- unsigned long __unused1;
- __kernel_time_t msg_rtime; /* last msgrcv time */
- unsigned long __unused2;
- __kernel_time_t msg_ctime; /* last change time */
- unsigned long __unused3;
- unsigned long msg_cbytes; /* current number of bytes on queue */
- unsigned long msg_qnum; /* number of messages in queue */
- unsigned long msg_qbytes; /* max number of bytes on queue */
- __kernel_pid_t msg_lspid; /* pid of last msgsnd */
- __kernel_pid_t msg_lrpid; /* last receive pid */
- unsigned long __unused4;
- unsigned long __unused5;
-};
-
-#endif /* _I386_MSGBUF_H */
diff --git a/include/asm-x86/msgbuf_64.h b/include/asm-x86/msgbuf_64.h
deleted file mode 100644
index cd6f95dd54da..000000000000
--- a/include/asm-x86/msgbuf_64.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef _X8664_MSGBUF_H
-#define _X8664_MSGBUF_H
-
-/*
- * The msqid64_ds structure for x86-64 architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 2 miscellaneous 64-bit values
- */
-
-struct msqid64_ds {
- struct ipc64_perm msg_perm;
- __kernel_time_t msg_stime; /* last msgsnd time */
- __kernel_time_t msg_rtime; /* last msgrcv time */
- __kernel_time_t msg_ctime; /* last change time */
- unsigned long msg_cbytes; /* current number of bytes on queue */
- unsigned long msg_qnum; /* number of messages in queue */
- unsigned long msg_qbytes; /* max number of bytes on queue */
- __kernel_pid_t msg_lspid; /* pid of last msgsnd */
- __kernel_pid_t msg_lrpid; /* last receive pid */
- unsigned long __unused4;
- unsigned long __unused5;
-};
-
-#endif
diff --git a/include/asm-x86/msr-index.h b/include/asm-x86/msr-index.h
index a02eb2991349..a4944732be04 100644
--- a/include/asm-x86/msr-index.h
+++ b/include/asm-x86/msr-index.h
@@ -73,8 +73,32 @@
#define MSR_P6_EVNTSEL0 0x00000186
#define MSR_P6_EVNTSEL1 0x00000187
-/* K7/K8 MSRs. Not complete. See the architecture manual for a more
+/* AMD64 MSRs. Not complete. See the architecture manual for a more
complete list. */
+
+#define MSR_AMD64_IBSFETCHCTL 0xc0011030
+#define MSR_AMD64_IBSFETCHLINAD 0xc0011031
+#define MSR_AMD64_IBSFETCHPHYSAD 0xc0011032
+#define MSR_AMD64_IBSOPCTL 0xc0011033
+#define MSR_AMD64_IBSOPRIP 0xc0011034
+#define MSR_AMD64_IBSOPDATA 0xc0011035
+#define MSR_AMD64_IBSOPDATA2 0xc0011036
+#define MSR_AMD64_IBSOPDATA3 0xc0011037
+#define MSR_AMD64_IBSDCLINAD 0xc0011038
+#define MSR_AMD64_IBSDCPHYSAD 0xc0011039
+#define MSR_AMD64_IBSCTL 0xc001103a
+
+/* K8 MSRs */
+#define MSR_K8_TOP_MEM1 0xc001001a
+#define MSR_K8_TOP_MEM2 0xc001001d
+#define MSR_K8_SYSCFG 0xc0010010
+#define MSR_K8_HWCR 0xc0010015
+#define MSR_K8_ENABLE_C1E 0xc0010055
+#define K8_MTRRFIXRANGE_DRAM_ENABLE 0x00040000 /* MtrrFixDramEn bit */
+#define K8_MTRRFIXRANGE_DRAM_MODIFY 0x00080000 /* MtrrFixDramModEn bit */
+#define K8_MTRR_RDMEM_WRMEM_MASK 0x18181818 /* Mask: RdMem|WrMem */
+
+/* K7 MSRs */
#define MSR_K7_EVNTSEL0 0xc0010000
#define MSR_K7_PERFCTR0 0xc0010004
#define MSR_K7_EVNTSEL1 0xc0010001
@@ -83,20 +107,10 @@
#define MSR_K7_PERFCTR2 0xc0010006
#define MSR_K7_EVNTSEL3 0xc0010003
#define MSR_K7_PERFCTR3 0xc0010007
-#define MSR_K8_TOP_MEM1 0xc001001a
#define MSR_K7_CLK_CTL 0xc001001b
-#define MSR_K8_TOP_MEM2 0xc001001d
-#define MSR_K8_SYSCFG 0xc0010010
-
-#define K8_MTRRFIXRANGE_DRAM_ENABLE 0x00040000 /* MtrrFixDramEn bit */
-#define K8_MTRRFIXRANGE_DRAM_MODIFY 0x00080000 /* MtrrFixDramModEn bit */
-#define K8_MTRR_RDMEM_WRMEM_MASK 0x18181818 /* Mask: RdMem|WrMem */
-
#define MSR_K7_HWCR 0xc0010015
-#define MSR_K8_HWCR 0xc0010015
#define MSR_K7_FID_VID_CTL 0xc0010041
#define MSR_K7_FID_VID_STATUS 0xc0010042
-#define MSR_K8_ENABLE_C1E 0xc0010055
/* K6 MSRs */
#define MSR_K6_EFER 0xc0000080
diff --git a/include/asm-x86/msr.h b/include/asm-x86/msr.h
index 2f87ce007002..ba4b31432120 100644
--- a/include/asm-x86/msr.h
+++ b/include/asm-x86/msr.h
@@ -1,13 +1,350 @@
+#ifndef __ASM_X86_MSR_H_
+#define __ASM_X86_MSR_H_
+
+#include <asm/msr-index.h>
+
+#ifdef __i386__
+
#ifdef __KERNEL__
-# ifdef CONFIG_X86_32
-# include "msr_32.h"
-# else
-# include "msr_64.h"
-# endif
+#ifndef __ASSEMBLY__
+
+#include <asm/errno.h>
+
+static inline unsigned long long native_read_msr(unsigned int msr)
+{
+ unsigned long long val;
+
+ asm volatile("rdmsr" : "=A" (val) : "c" (msr));
+ return val;
+}
+
+static inline unsigned long long native_read_msr_safe(unsigned int msr,
+ int *err)
+{
+ unsigned long long val;
+
+ asm volatile("2: rdmsr ; xorl %0,%0\n"
+ "1:\n\t"
+ ".section .fixup,\"ax\"\n\t"
+ "3: movl %3,%0 ; jmp 1b\n\t"
+ ".previous\n\t"
+ ".section __ex_table,\"a\"\n"
+ " .align 4\n\t"
+ " .long 2b,3b\n\t"
+ ".previous"
+ : "=r" (*err), "=A" (val)
+ : "c" (msr), "i" (-EFAULT));
+
+ return val;
+}
+
+static inline void native_write_msr(unsigned int msr, unsigned long long val)
+{
+ asm volatile("wrmsr" : : "c" (msr), "A"(val));
+}
+
+static inline int native_write_msr_safe(unsigned int msr,
+ unsigned long long val)
+{
+ int err;
+ asm volatile("2: wrmsr ; xorl %0,%0\n"
+ "1:\n\t"
+ ".section .fixup,\"ax\"\n\t"
+ "3: movl %4,%0 ; jmp 1b\n\t"
+ ".previous\n\t"
+ ".section __ex_table,\"a\"\n"
+ " .align 4\n\t"
+ " .long 2b,3b\n\t"
+ ".previous"
+ : "=a" (err)
+ : "c" (msr), "0" ((u32)val), "d" ((u32)(val>>32)),
+ "i" (-EFAULT));
+ return err;
+}
+
+static inline unsigned long long native_read_tsc(void)
+{
+ unsigned long long val;
+ asm volatile("rdtsc" : "=A" (val));
+ return val;
+}
+
+static inline unsigned long long native_read_pmc(void)
+{
+ unsigned long long val;
+ asm volatile("rdpmc" : "=A" (val));
+ return val;
+}
+
+#ifdef CONFIG_PARAVIRT
+#include <asm/paravirt.h>
#else
-# ifdef __i386__
-# include "msr_32.h"
-# else
-# include "msr_64.h"
-# endif
+#include <linux/errno.h>
+/*
+ * Access to machine-specific registers (available on 586 and better only)
+ * Note: the rd* operations modify the parameters directly (without using
+ * pointer indirection), this allows gcc to optimize better
+ */
+
+#define rdmsr(msr,val1,val2) \
+ do { \
+ u64 __val = native_read_msr(msr); \
+ (val1) = (u32)__val; \
+ (val2) = (u32)(__val >> 32); \
+ } while(0)
+
+static inline void wrmsr(u32 __msr, u32 __low, u32 __high)
+{
+ native_write_msr(__msr, ((u64)__high << 32) | __low);
+}
+
+#define rdmsrl(msr,val) \
+ ((val) = native_read_msr(msr))
+
+#define wrmsrl(msr,val) native_write_msr(msr, val)
+
+/* wrmsr with exception handling */
+static inline int wrmsr_safe(u32 __msr, u32 __low, u32 __high)
+{
+ return native_write_msr_safe(__msr, ((u64)__high << 32) | __low);
+}
+
+/* rdmsr with exception handling */
+#define rdmsr_safe(msr,p1,p2) \
+ ({ \
+ int __err; \
+ u64 __val = native_read_msr_safe(msr, &__err); \
+ (*p1) = (u32)__val; \
+ (*p2) = (u32)(__val >> 32); \
+ __err; \
+ })
+
+#define rdtscl(low) \
+ ((low) = (u32)native_read_tsc())
+
+#define rdtscll(val) \
+ ((val) = native_read_tsc())
+
+#define write_tsc(val1,val2) wrmsr(0x10, val1, val2)
+
+#define rdpmc(counter,low,high) \
+ do { \
+ u64 _l = native_read_pmc(); \
+ (low) = (u32)_l; \
+ (high) = (u32)(_l >> 32); \
+ } while(0)
+#endif /* !CONFIG_PARAVIRT */
+
+#ifdef CONFIG_SMP
+void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
+void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
+int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
+int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
+#else /* CONFIG_SMP */
+static inline void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
+{
+ rdmsr(msr_no, *l, *h);
+}
+static inline void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
+{
+ wrmsr(msr_no, l, h);
+}
+static inline int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
+{
+ return rdmsr_safe(msr_no, l, h);
+}
+static inline int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
+{
+ return wrmsr_safe(msr_no, l, h);
+}
+#endif /* CONFIG_SMP */
+#endif /* ! __ASSEMBLY__ */
+#endif /* __KERNEL__ */
+
+#else /* __i386__ */
+
+#ifndef __ASSEMBLY__
+#include <linux/errno.h>
+/*
+ * Access to machine-specific registers (available on 586 and better only)
+ * Note: the rd* operations modify the parameters directly (without using
+ * pointer indirection), this allows gcc to optimize better
+ */
+
+#define rdmsr(msr,val1,val2) \
+ __asm__ __volatile__("rdmsr" \
+ : "=a" (val1), "=d" (val2) \
+ : "c" (msr))
+
+
+#define rdmsrl(msr,val) do { unsigned long a__,b__; \
+ __asm__ __volatile__("rdmsr" \
+ : "=a" (a__), "=d" (b__) \
+ : "c" (msr)); \
+ val = a__ | (b__<<32); \
+} while(0)
+
+#define wrmsr(msr,val1,val2) \
+ __asm__ __volatile__("wrmsr" \
+ : /* no outputs */ \
+ : "c" (msr), "a" (val1), "d" (val2))
+
+#define wrmsrl(msr,val) wrmsr(msr,(__u32)((__u64)(val)),((__u64)(val))>>32)
+
+/* wrmsr with exception handling */
+#define wrmsr_safe(msr,a,b) ({ int ret__; \
+ asm volatile("2: wrmsr ; xorl %0,%0\n" \
+ "1:\n\t" \
+ ".section .fixup,\"ax\"\n\t" \
+ "3: movl %4,%0 ; jmp 1b\n\t" \
+ ".previous\n\t" \
+ ".section __ex_table,\"a\"\n" \
+ " .align 8\n\t" \
+ " .quad 2b,3b\n\t" \
+ ".previous" \
+ : "=a" (ret__) \
+ : "c" (msr), "0" (a), "d" (b), "i" (-EFAULT)); \
+ ret__; })
+
+#define checking_wrmsrl(msr,val) wrmsr_safe(msr,(u32)(val),(u32)((val)>>32))
+
+#define rdmsr_safe(msr,a,b) \
+ ({ int ret__; \
+ asm volatile ("1: rdmsr\n" \
+ "2:\n" \
+ ".section .fixup,\"ax\"\n" \
+ "3: movl %4,%0\n" \
+ " jmp 2b\n" \
+ ".previous\n" \
+ ".section __ex_table,\"a\"\n" \
+ " .align 8\n" \
+ " .quad 1b,3b\n" \
+ ".previous":"=&bDS" (ret__), "=a"(*(a)), "=d"(*(b)) \
+ :"c"(msr), "i"(-EIO), "0"(0)); \
+ ret__; })
+
+#define rdtsc(low,high) \
+ __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
+
+#define rdtscl(low) \
+ __asm__ __volatile__ ("rdtsc" : "=a" (low) : : "edx")
+
+#define rdtscp(low,high,aux) \
+ asm volatile (".byte 0x0f,0x01,0xf9" : "=a" (low), "=d" (high), "=c" (aux))
+
+#define rdtscll(val) do { \
+ unsigned int __a,__d; \
+ asm volatile("rdtsc" : "=a" (__a), "=d" (__d)); \
+ (val) = ((unsigned long)__a) | (((unsigned long)__d)<<32); \
+} while(0)
+
+#define rdtscpll(val, aux) do { \
+ unsigned long __a, __d; \
+ asm volatile (".byte 0x0f,0x01,0xf9" : "=a" (__a), "=d" (__d), "=c" (aux)); \
+ (val) = (__d << 32) | __a; \
+} while (0)
+
+#define write_tsc(val1,val2) wrmsr(0x10, val1, val2)
+
+#define write_rdtscp_aux(val) wrmsr(0xc0000103, val, 0)
+
+#define rdpmc(counter,low,high) \
+ __asm__ __volatile__("rdpmc" \
+ : "=a" (low), "=d" (high) \
+ : "c" (counter))
+
+static inline void cpuid(int op, unsigned int *eax, unsigned int *ebx,
+ unsigned int *ecx, unsigned int *edx)
+{
+ __asm__("cpuid"
+ : "=a" (*eax),
+ "=b" (*ebx),
+ "=c" (*ecx),
+ "=d" (*edx)
+ : "0" (op));
+}
+
+/* Some CPUID calls want 'count' to be placed in ecx */
+static inline void cpuid_count(int op, int count, int *eax, int *ebx, int *ecx,
+ int *edx)
+{
+ __asm__("cpuid"
+ : "=a" (*eax),
+ "=b" (*ebx),
+ "=c" (*ecx),
+ "=d" (*edx)
+ : "0" (op), "c" (count));
+}
+
+/*
+ * CPUID functions returning a single datum
+ */
+static inline unsigned int cpuid_eax(unsigned int op)
+{
+ unsigned int eax;
+
+ __asm__("cpuid"
+ : "=a" (eax)
+ : "0" (op)
+ : "bx", "cx", "dx");
+ return eax;
+}
+static inline unsigned int cpuid_ebx(unsigned int op)
+{
+ unsigned int eax, ebx;
+
+ __asm__("cpuid"
+ : "=a" (eax), "=b" (ebx)
+ : "0" (op)
+ : "cx", "dx" );
+ return ebx;
+}
+static inline unsigned int cpuid_ecx(unsigned int op)
+{
+ unsigned int eax, ecx;
+
+ __asm__("cpuid"
+ : "=a" (eax), "=c" (ecx)
+ : "0" (op)
+ : "bx", "dx" );
+ return ecx;
+}
+static inline unsigned int cpuid_edx(unsigned int op)
+{
+ unsigned int eax, edx;
+
+ __asm__("cpuid"
+ : "=a" (eax), "=d" (edx)
+ : "0" (op)
+ : "bx", "cx");
+ return edx;
+}
+
+#ifdef CONFIG_SMP
+void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
+void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
+int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
+int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
+#else /* CONFIG_SMP */
+static inline void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
+{
+ rdmsr(msr_no, *l, *h);
+}
+static inline void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
+{
+ wrmsr(msr_no, l, h);
+}
+static inline int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
+{
+ return rdmsr_safe(msr_no, l, h);
+}
+static inline int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
+{
+ return wrmsr_safe(msr_no, l, h);
+}
+#endif /* CONFIG_SMP */
+#endif /* __ASSEMBLY__ */
+
+#endif /* !__i386__ */
+
#endif
diff --git a/include/asm-x86/msr_32.h b/include/asm-x86/msr_32.h
deleted file mode 100644
index df21ea049369..000000000000
--- a/include/asm-x86/msr_32.h
+++ /dev/null
@@ -1,161 +0,0 @@
-#ifndef __ASM_MSR_H
-#define __ASM_MSR_H
-
-#include <asm/msr-index.h>
-
-#ifdef __KERNEL__
-#ifndef __ASSEMBLY__
-
-#include <asm/errno.h>
-
-static inline unsigned long long native_read_msr(unsigned int msr)
-{
- unsigned long long val;
-
- asm volatile("rdmsr" : "=A" (val) : "c" (msr));
- return val;
-}
-
-static inline unsigned long long native_read_msr_safe(unsigned int msr,
- int *err)
-{
- unsigned long long val;
-
- asm volatile("2: rdmsr ; xorl %0,%0\n"
- "1:\n\t"
- ".section .fixup,\"ax\"\n\t"
- "3: movl %3,%0 ; jmp 1b\n\t"
- ".previous\n\t"
- ".section __ex_table,\"a\"\n"
- " .align 4\n\t"
- " .long 2b,3b\n\t"
- ".previous"
- : "=r" (*err), "=A" (val)
- : "c" (msr), "i" (-EFAULT));
-
- return val;
-}
-
-static inline void native_write_msr(unsigned int msr, unsigned long long val)
-{
- asm volatile("wrmsr" : : "c" (msr), "A"(val));
-}
-
-static inline int native_write_msr_safe(unsigned int msr,
- unsigned long long val)
-{
- int err;
- asm volatile("2: wrmsr ; xorl %0,%0\n"
- "1:\n\t"
- ".section .fixup,\"ax\"\n\t"
- "3: movl %4,%0 ; jmp 1b\n\t"
- ".previous\n\t"
- ".section __ex_table,\"a\"\n"
- " .align 4\n\t"
- " .long 2b,3b\n\t"
- ".previous"
- : "=a" (err)
- : "c" (msr), "0" ((u32)val), "d" ((u32)(val>>32)),
- "i" (-EFAULT));
- return err;
-}
-
-static inline unsigned long long native_read_tsc(void)
-{
- unsigned long long val;
- asm volatile("rdtsc" : "=A" (val));
- return val;
-}
-
-static inline unsigned long long native_read_pmc(void)
-{
- unsigned long long val;
- asm volatile("rdpmc" : "=A" (val));
- return val;
-}
-
-#ifdef CONFIG_PARAVIRT
-#include <asm/paravirt.h>
-#else
-#include <linux/errno.h>
-/*
- * Access to machine-specific registers (available on 586 and better only)
- * Note: the rd* operations modify the parameters directly (without using
- * pointer indirection), this allows gcc to optimize better
- */
-
-#define rdmsr(msr,val1,val2) \
- do { \
- u64 __val = native_read_msr(msr); \
- (val1) = (u32)__val; \
- (val2) = (u32)(__val >> 32); \
- } while(0)
-
-static inline void wrmsr(u32 __msr, u32 __low, u32 __high)
-{
- native_write_msr(__msr, ((u64)__high << 32) | __low);
-}
-
-#define rdmsrl(msr,val) \
- ((val) = native_read_msr(msr))
-
-#define wrmsrl(msr,val) native_write_msr(msr, val)
-
-/* wrmsr with exception handling */
-static inline int wrmsr_safe(u32 __msr, u32 __low, u32 __high)
-{
- return native_write_msr_safe(__msr, ((u64)__high << 32) | __low);
-}
-
-/* rdmsr with exception handling */
-#define rdmsr_safe(msr,p1,p2) \
- ({ \
- int __err; \
- u64 __val = native_read_msr_safe(msr, &__err); \
- (*p1) = (u32)__val; \
- (*p2) = (u32)(__val >> 32); \
- __err; \
- })
-
-#define rdtscl(low) \
- ((low) = (u32)native_read_tsc())
-
-#define rdtscll(val) \
- ((val) = native_read_tsc())
-
-#define write_tsc(val1,val2) wrmsr(0x10, val1, val2)
-
-#define rdpmc(counter,low,high) \
- do { \
- u64 _l = native_read_pmc(); \
- (low) = (u32)_l; \
- (high) = (u32)(_l >> 32); \
- } while(0)
-#endif /* !CONFIG_PARAVIRT */
-
-#ifdef CONFIG_SMP
-void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
-void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
-int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
-int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
-#else /* CONFIG_SMP */
-static inline void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
-{
- rdmsr(msr_no, *l, *h);
-}
-static inline void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
-{
- wrmsr(msr_no, l, h);
-}
-static inline int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
-{
- return rdmsr_safe(msr_no, l, h);
-}
-static inline int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
-{
- return wrmsr_safe(msr_no, l, h);
-}
-#endif /* CONFIG_SMP */
-#endif
-#endif
-#endif /* __ASM_MSR_H */
diff --git a/include/asm-x86/msr_64.h b/include/asm-x86/msr_64.h
deleted file mode 100644
index d5c55b80da54..000000000000
--- a/include/asm-x86/msr_64.h
+++ /dev/null
@@ -1,187 +0,0 @@
-#ifndef X86_64_MSR_H
-#define X86_64_MSR_H 1
-
-#include <asm/msr-index.h>
-
-#ifndef __ASSEMBLY__
-#include <linux/errno.h>
-/*
- * Access to machine-specific registers (available on 586 and better only)
- * Note: the rd* operations modify the parameters directly (without using
- * pointer indirection), this allows gcc to optimize better
- */
-
-#define rdmsr(msr,val1,val2) \
- __asm__ __volatile__("rdmsr" \
- : "=a" (val1), "=d" (val2) \
- : "c" (msr))
-
-
-#define rdmsrl(msr,val) do { unsigned long a__,b__; \
- __asm__ __volatile__("rdmsr" \
- : "=a" (a__), "=d" (b__) \
- : "c" (msr)); \
- val = a__ | (b__<<32); \
-} while(0)
-
-#define wrmsr(msr,val1,val2) \
- __asm__ __volatile__("wrmsr" \
- : /* no outputs */ \
- : "c" (msr), "a" (val1), "d" (val2))
-
-#define wrmsrl(msr,val) wrmsr(msr,(__u32)((__u64)(val)),((__u64)(val))>>32)
-
-/* wrmsr with exception handling */
-#define wrmsr_safe(msr,a,b) ({ int ret__; \
- asm volatile("2: wrmsr ; xorl %0,%0\n" \
- "1:\n\t" \
- ".section .fixup,\"ax\"\n\t" \
- "3: movl %4,%0 ; jmp 1b\n\t" \
- ".previous\n\t" \
- ".section __ex_table,\"a\"\n" \
- " .align 8\n\t" \
- " .quad 2b,3b\n\t" \
- ".previous" \
- : "=a" (ret__) \
- : "c" (msr), "0" (a), "d" (b), "i" (-EFAULT)); \
- ret__; })
-
-#define checking_wrmsrl(msr,val) wrmsr_safe(msr,(u32)(val),(u32)((val)>>32))
-
-#define rdmsr_safe(msr,a,b) \
- ({ int ret__; \
- asm volatile ("1: rdmsr\n" \
- "2:\n" \
- ".section .fixup,\"ax\"\n" \
- "3: movl %4,%0\n" \
- " jmp 2b\n" \
- ".previous\n" \
- ".section __ex_table,\"a\"\n" \
- " .align 8\n" \
- " .quad 1b,3b\n" \
- ".previous":"=&bDS" (ret__), "=a"(*(a)), "=d"(*(b))\
- :"c"(msr), "i"(-EIO), "0"(0)); \
- ret__; })
-
-#define rdtsc(low,high) \
- __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
-
-#define rdtscl(low) \
- __asm__ __volatile__ ("rdtsc" : "=a" (low) : : "edx")
-
-#define rdtscp(low,high,aux) \
- asm volatile (".byte 0x0f,0x01,0xf9" : "=a" (low), "=d" (high), "=c" (aux))
-
-#define rdtscll(val) do { \
- unsigned int __a,__d; \
- asm volatile("rdtsc" : "=a" (__a), "=d" (__d)); \
- (val) = ((unsigned long)__a) | (((unsigned long)__d)<<32); \
-} while(0)
-
-#define rdtscpll(val, aux) do { \
- unsigned long __a, __d; \
- asm volatile (".byte 0x0f,0x01,0xf9" : "=a" (__a), "=d" (__d), "=c" (aux)); \
- (val) = (__d << 32) | __a; \
-} while (0)
-
-#define write_tsc(val1,val2) wrmsr(0x10, val1, val2)
-
-#define write_rdtscp_aux(val) wrmsr(0xc0000103, val, 0)
-
-#define rdpmc(counter,low,high) \
- __asm__ __volatile__("rdpmc" \
- : "=a" (low), "=d" (high) \
- : "c" (counter))
-
-static inline void cpuid(int op, unsigned int *eax, unsigned int *ebx,
- unsigned int *ecx, unsigned int *edx)
-{
- __asm__("cpuid"
- : "=a" (*eax),
- "=b" (*ebx),
- "=c" (*ecx),
- "=d" (*edx)
- : "0" (op));
-}
-
-/* Some CPUID calls want 'count' to be placed in ecx */
-static inline void cpuid_count(int op, int count, int *eax, int *ebx, int *ecx,
- int *edx)
-{
- __asm__("cpuid"
- : "=a" (*eax),
- "=b" (*ebx),
- "=c" (*ecx),
- "=d" (*edx)
- : "0" (op), "c" (count));
-}
-
-/*
- * CPUID functions returning a single datum
- */
-static inline unsigned int cpuid_eax(unsigned int op)
-{
- unsigned int eax;
-
- __asm__("cpuid"
- : "=a" (eax)
- : "0" (op)
- : "bx", "cx", "dx");
- return eax;
-}
-static inline unsigned int cpuid_ebx(unsigned int op)
-{
- unsigned int eax, ebx;
-
- __asm__("cpuid"
- : "=a" (eax), "=b" (ebx)
- : "0" (op)
- : "cx", "dx" );
- return ebx;
-}
-static inline unsigned int cpuid_ecx(unsigned int op)
-{
- unsigned int eax, ecx;
-
- __asm__("cpuid"
- : "=a" (eax), "=c" (ecx)
- : "0" (op)
- : "bx", "dx" );
- return ecx;
-}
-static inline unsigned int cpuid_edx(unsigned int op)
-{
- unsigned int eax, edx;
-
- __asm__("cpuid"
- : "=a" (eax), "=d" (edx)
- : "0" (op)
- : "bx", "cx");
- return edx;
-}
-
-#ifdef CONFIG_SMP
-void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
-void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
-int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
-int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
-#else /* CONFIG_SMP */
-static inline void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
-{
- rdmsr(msr_no, *l, *h);
-}
-static inline void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
-{
- wrmsr(msr_no, l, h);
-}
-static inline int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
-{
- return rdmsr_safe(msr_no, l, h);
-}
-static inline int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
-{
- return wrmsr_safe(msr_no, l, h);
-}
-#endif /* CONFIG_SMP */
-#endif /* __ASSEMBLY__ */
-#endif /* X86_64_MSR_H */
diff --git a/include/asm-x86/mtrr.h b/include/asm-x86/mtrr.h
index 34f633b3e00c..e8320e4e6ca2 100644
--- a/include/asm-x86/mtrr.h
+++ b/include/asm-x86/mtrr.h
@@ -1,13 +1,164 @@
+/* Generic MTRR (Memory Type Range Register) ioctls.
+
+ Copyright (C) 1997-1999 Richard Gooch
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Richard Gooch may be reached by email at rgooch@atnf.csiro.au
+ The postal address is:
+ Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia.
+*/
+#ifndef _ASM_X86_MTRR_H
+#define _ASM_X86_MTRR_H
+
+#include <linux/ioctl.h>
+#include <linux/errno.h>
+
+#define MTRR_IOCTL_BASE 'M'
+
+struct mtrr_sentry
+{
+ unsigned long base; /* Base address */
+ unsigned int size; /* Size of region */
+ unsigned int type; /* Type of region */
+};
+
+/* Warning: this structure has a different order from i386
+ on x86-64. The 32bit emulation code takes care of that.
+ But you need to use this for 64bit, otherwise your X server
+ will break. */
+
+#ifdef __i386__
+struct mtrr_gentry
+{
+ unsigned int regnum; /* Register number */
+ unsigned long base; /* Base address */
+ unsigned int size; /* Size of region */
+ unsigned int type; /* Type of region */
+};
+
+#else /* __i386__ */
+
+struct mtrr_gentry
+{
+ unsigned long base; /* Base address */
+ unsigned int size; /* Size of region */
+ unsigned int regnum; /* Register number */
+ unsigned int type; /* Type of region */
+};
+#endif /* !__i386__ */
+
+/* These are the various ioctls */
+#define MTRRIOC_ADD_ENTRY _IOW(MTRR_IOCTL_BASE, 0, struct mtrr_sentry)
+#define MTRRIOC_SET_ENTRY _IOW(MTRR_IOCTL_BASE, 1, struct mtrr_sentry)
+#define MTRRIOC_DEL_ENTRY _IOW(MTRR_IOCTL_BASE, 2, struct mtrr_sentry)
+#define MTRRIOC_GET_ENTRY _IOWR(MTRR_IOCTL_BASE, 3, struct mtrr_gentry)
+#define MTRRIOC_KILL_ENTRY _IOW(MTRR_IOCTL_BASE, 4, struct mtrr_sentry)
+#define MTRRIOC_ADD_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 5, struct mtrr_sentry)
+#define MTRRIOC_SET_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 6, struct mtrr_sentry)
+#define MTRRIOC_DEL_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 7, struct mtrr_sentry)
+#define MTRRIOC_GET_PAGE_ENTRY _IOWR(MTRR_IOCTL_BASE, 8, struct mtrr_gentry)
+#define MTRRIOC_KILL_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 9, struct mtrr_sentry)
+
+/* These are the region types */
+#define MTRR_TYPE_UNCACHABLE 0
+#define MTRR_TYPE_WRCOMB 1
+/*#define MTRR_TYPE_ 2*/
+/*#define MTRR_TYPE_ 3*/
+#define MTRR_TYPE_WRTHROUGH 4
+#define MTRR_TYPE_WRPROT 5
+#define MTRR_TYPE_WRBACK 6
+#define MTRR_NUM_TYPES 7
+
#ifdef __KERNEL__
-# ifdef CONFIG_X86_32
-# include "mtrr_32.h"
-# else
-# include "mtrr_64.h"
-# endif
-#else
-# ifdef __i386__
-# include "mtrr_32.h"
-# else
-# include "mtrr_64.h"
-# endif
-#endif
+
+/* The following functions are for use by other drivers */
+# ifdef CONFIG_MTRR
+extern void mtrr_save_fixed_ranges(void *);
+extern void mtrr_save_state(void);
+extern int mtrr_add (unsigned long base, unsigned long size,
+ unsigned int type, char increment);
+extern int mtrr_add_page (unsigned long base, unsigned long size,
+ unsigned int type, char increment);
+extern int mtrr_del (int reg, unsigned long base, unsigned long size);
+extern int mtrr_del_page (int reg, unsigned long base, unsigned long size);
+extern void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi);
+extern void mtrr_ap_init(void);
+extern void mtrr_bp_init(void);
+# else
+#define mtrr_save_fixed_ranges(arg) do {} while (0)
+#define mtrr_save_state() do {} while (0)
+static __inline__ int mtrr_add (unsigned long base, unsigned long size,
+ unsigned int type, char increment)
+{
+ return -ENODEV;
+}
+static __inline__ int mtrr_add_page (unsigned long base, unsigned long size,
+ unsigned int type, char increment)
+{
+ return -ENODEV;
+}
+static __inline__ int mtrr_del (int reg, unsigned long base,
+ unsigned long size)
+{
+ return -ENODEV;
+}
+static __inline__ int mtrr_del_page (int reg, unsigned long base,
+ unsigned long size)
+{
+ return -ENODEV;
+}
+
+static __inline__ void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi) {;}
+
+#define mtrr_ap_init() do {} while (0)
+#define mtrr_bp_init() do {} while (0)
+# endif
+
+#ifdef CONFIG_COMPAT
+#include <linux/compat.h>
+
+struct mtrr_sentry32
+{
+ compat_ulong_t base; /* Base address */
+ compat_uint_t size; /* Size of region */
+ compat_uint_t type; /* Type of region */
+};
+
+struct mtrr_gentry32
+{
+ compat_ulong_t regnum; /* Register number */
+ compat_uint_t base; /* Base address */
+ compat_uint_t size; /* Size of region */
+ compat_uint_t type; /* Type of region */
+};
+
+#define MTRR_IOCTL_BASE 'M'
+
+#define MTRRIOC32_ADD_ENTRY _IOW(MTRR_IOCTL_BASE, 0, struct mtrr_sentry32)
+#define MTRRIOC32_SET_ENTRY _IOW(MTRR_IOCTL_BASE, 1, struct mtrr_sentry32)
+#define MTRRIOC32_DEL_ENTRY _IOW(MTRR_IOCTL_BASE, 2, struct mtrr_sentry32)
+#define MTRRIOC32_GET_ENTRY _IOWR(MTRR_IOCTL_BASE, 3, struct mtrr_gentry32)
+#define MTRRIOC32_KILL_ENTRY _IOW(MTRR_IOCTL_BASE, 4, struct mtrr_sentry32)
+#define MTRRIOC32_ADD_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 5, struct mtrr_sentry32)
+#define MTRRIOC32_SET_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 6, struct mtrr_sentry32)
+#define MTRRIOC32_DEL_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 7, struct mtrr_sentry32)
+#define MTRRIOC32_GET_PAGE_ENTRY _IOWR(MTRR_IOCTL_BASE, 8, struct mtrr_gentry32)
+#define MTRRIOC32_KILL_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 9, struct mtrr_sentry32)
+#endif /* CONFIG_COMPAT */
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_X86_MTRR_H */
diff --git a/include/asm-x86/mtrr_32.h b/include/asm-x86/mtrr_32.h
deleted file mode 100644
index 7e9c7ccbdcfe..000000000000
--- a/include/asm-x86/mtrr_32.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/* Generic MTRR (Memory Type Range Register) ioctls.
-
- Copyright (C) 1997-1999 Richard Gooch
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library 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
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Richard Gooch may be reached by email at rgooch@atnf.csiro.au
- The postal address is:
- Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia.
-*/
-#ifndef _LINUX_MTRR_H
-#define _LINUX_MTRR_H
-
-#include <linux/ioctl.h>
-#include <linux/errno.h>
-
-#define MTRR_IOCTL_BASE 'M'
-
-struct mtrr_sentry
-{
- unsigned long base; /* Base address */
- unsigned int size; /* Size of region */
- unsigned int type; /* Type of region */
-};
-
-struct mtrr_gentry
-{
- unsigned int regnum; /* Register number */
- unsigned long base; /* Base address */
- unsigned int size; /* Size of region */
- unsigned int type; /* Type of region */
-};
-
-/* These are the various ioctls */
-#define MTRRIOC_ADD_ENTRY _IOW(MTRR_IOCTL_BASE, 0, struct mtrr_sentry)
-#define MTRRIOC_SET_ENTRY _IOW(MTRR_IOCTL_BASE, 1, struct mtrr_sentry)
-#define MTRRIOC_DEL_ENTRY _IOW(MTRR_IOCTL_BASE, 2, struct mtrr_sentry)
-#define MTRRIOC_GET_ENTRY _IOWR(MTRR_IOCTL_BASE, 3, struct mtrr_gentry)
-#define MTRRIOC_KILL_ENTRY _IOW(MTRR_IOCTL_BASE, 4, struct mtrr_sentry)
-#define MTRRIOC_ADD_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 5, struct mtrr_sentry)
-#define MTRRIOC_SET_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 6, struct mtrr_sentry)
-#define MTRRIOC_DEL_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 7, struct mtrr_sentry)
-#define MTRRIOC_GET_PAGE_ENTRY _IOWR(MTRR_IOCTL_BASE, 8, struct mtrr_gentry)
-#define MTRRIOC_KILL_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 9, struct mtrr_sentry)
-
-/* These are the region types */
-#define MTRR_TYPE_UNCACHABLE 0
-#define MTRR_TYPE_WRCOMB 1
-/*#define MTRR_TYPE_ 2*/
-/*#define MTRR_TYPE_ 3*/
-#define MTRR_TYPE_WRTHROUGH 4
-#define MTRR_TYPE_WRPROT 5
-#define MTRR_TYPE_WRBACK 6
-#define MTRR_NUM_TYPES 7
-
-#ifdef __KERNEL__
-
-/* The following functions are for use by other drivers */
-# ifdef CONFIG_MTRR
-extern void mtrr_save_fixed_ranges(void *);
-extern void mtrr_save_state(void);
-extern int mtrr_add (unsigned long base, unsigned long size,
- unsigned int type, char increment);
-extern int mtrr_add_page (unsigned long base, unsigned long size,
- unsigned int type, char increment);
-extern int mtrr_del (int reg, unsigned long base, unsigned long size);
-extern int mtrr_del_page (int reg, unsigned long base, unsigned long size);
-extern void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi);
-extern void mtrr_ap_init(void);
-extern void mtrr_bp_init(void);
-# else
-#define mtrr_save_fixed_ranges(arg) do {} while (0)
-#define mtrr_save_state() do {} while (0)
-static __inline__ int mtrr_add (unsigned long base, unsigned long size,
- unsigned int type, char increment)
-{
- return -ENODEV;
-}
-static __inline__ int mtrr_add_page (unsigned long base, unsigned long size,
- unsigned int type, char increment)
-{
- return -ENODEV;
-}
-static __inline__ int mtrr_del (int reg, unsigned long base,
- unsigned long size)
-{
- return -ENODEV;
-}
-static __inline__ int mtrr_del_page (int reg, unsigned long base,
- unsigned long size)
-{
- return -ENODEV;
-}
-
-static __inline__ void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi) {;}
-
-#define mtrr_ap_init() do {} while (0)
-#define mtrr_bp_init() do {} while (0)
-# endif
-
-#endif
-
-#endif /* _LINUX_MTRR_H */
diff --git a/include/asm-x86/mtrr_64.h b/include/asm-x86/mtrr_64.h
deleted file mode 100644
index b557c486bef8..000000000000
--- a/include/asm-x86/mtrr_64.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/* Generic MTRR (Memory Type Range Register) ioctls.
-
- Copyright (C) 1997-1999 Richard Gooch
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library 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
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Richard Gooch may be reached by email at rgooch@atnf.csiro.au
- The postal address is:
- Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia.
-*/
-#ifndef _LINUX_MTRR_H
-#define _LINUX_MTRR_H
-
-#include <linux/ioctl.h>
-
-#define MTRR_IOCTL_BASE 'M'
-
-struct mtrr_sentry
-{
- unsigned long base; /* Base address */
- unsigned int size; /* Size of region */
- unsigned int type; /* Type of region */
-};
-
-/* Warning: this structure has a different order from i386
- on x86-64. The 32bit emulation code takes care of that.
- But you need to use this for 64bit, otherwise your X server
- will break. */
-struct mtrr_gentry
-{
- unsigned long base; /* Base address */
- unsigned int size; /* Size of region */
- unsigned int regnum; /* Register number */
- unsigned int type; /* Type of region */
-};
-
-/* These are the various ioctls */
-#define MTRRIOC_ADD_ENTRY _IOW(MTRR_IOCTL_BASE, 0, struct mtrr_sentry)
-#define MTRRIOC_SET_ENTRY _IOW(MTRR_IOCTL_BASE, 1, struct mtrr_sentry)
-#define MTRRIOC_DEL_ENTRY _IOW(MTRR_IOCTL_BASE, 2, struct mtrr_sentry)
-#define MTRRIOC_GET_ENTRY _IOWR(MTRR_IOCTL_BASE, 3, struct mtrr_gentry)
-#define MTRRIOC_KILL_ENTRY _IOW(MTRR_IOCTL_BASE, 4, struct mtrr_sentry)
-#define MTRRIOC_ADD_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 5, struct mtrr_sentry)
-#define MTRRIOC_SET_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 6, struct mtrr_sentry)
-#define MTRRIOC_DEL_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 7, struct mtrr_sentry)
-#define MTRRIOC_GET_PAGE_ENTRY _IOWR(MTRR_IOCTL_BASE, 8, struct mtrr_gentry)
-#define MTRRIOC_KILL_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 9, struct mtrr_sentry)
-
-/* These are the region types */
-#define MTRR_TYPE_UNCACHABLE 0
-#define MTRR_TYPE_WRCOMB 1
-/*#define MTRR_TYPE_ 2*/
-/*#define MTRR_TYPE_ 3*/
-#define MTRR_TYPE_WRTHROUGH 4
-#define MTRR_TYPE_WRPROT 5
-#define MTRR_TYPE_WRBACK 6
-#define MTRR_NUM_TYPES 7
-
-#ifdef __KERNEL__
-
-/* The following functions are for use by other drivers */
-# ifdef CONFIG_MTRR
-extern int mtrr_add (unsigned long base, unsigned long size,
- unsigned int type, char increment);
-extern int mtrr_add_page (unsigned long base, unsigned long size,
- unsigned int type, char increment);
-extern int mtrr_del (int reg, unsigned long base, unsigned long size);
-extern int mtrr_del_page (int reg, unsigned long base, unsigned long size);
-# else
-static __inline__ int mtrr_add (unsigned long base, unsigned long size,
- unsigned int type, char increment)
-{
- return -ENODEV;
-}
-static __inline__ int mtrr_add_page (unsigned long base, unsigned long size,
- unsigned int type, char increment)
-{
- return -ENODEV;
-}
-static __inline__ int mtrr_del (int reg, unsigned long base,
- unsigned long size)
-{
- return -ENODEV;
-}
-static __inline__ int mtrr_del_page (int reg, unsigned long base,
- unsigned long size)
-{
- return -ENODEV;
-}
-
-#endif /* CONFIG_MTRR */
-
-#ifdef CONFIG_COMPAT
-#include <linux/compat.h>
-
-struct mtrr_sentry32
-{
- compat_ulong_t base; /* Base address */
- compat_uint_t size; /* Size of region */
- compat_uint_t type; /* Type of region */
-};
-
-struct mtrr_gentry32
-{
- compat_ulong_t regnum; /* Register number */
- compat_uint_t base; /* Base address */
- compat_uint_t size; /* Size of region */
- compat_uint_t type; /* Type of region */
-};
-
-#define MTRR_IOCTL_BASE 'M'
-
-#define MTRRIOC32_ADD_ENTRY _IOW(MTRR_IOCTL_BASE, 0, struct mtrr_sentry32)
-#define MTRRIOC32_SET_ENTRY _IOW(MTRR_IOCTL_BASE, 1, struct mtrr_sentry32)
-#define MTRRIOC32_DEL_ENTRY _IOW(MTRR_IOCTL_BASE, 2, struct mtrr_sentry32)
-#define MTRRIOC32_GET_ENTRY _IOWR(MTRR_IOCTL_BASE, 3, struct mtrr_gentry32)
-#define MTRRIOC32_KILL_ENTRY _IOW(MTRR_IOCTL_BASE, 4, struct mtrr_sentry32)
-#define MTRRIOC32_ADD_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 5, struct mtrr_sentry32)
-#define MTRRIOC32_SET_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 6, struct mtrr_sentry32)
-#define MTRRIOC32_DEL_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 7, struct mtrr_sentry32)
-#define MTRRIOC32_GET_PAGE_ENTRY _IOWR(MTRR_IOCTL_BASE, 8, struct mtrr_gentry32)
-#define MTRRIOC32_KILL_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 9, struct mtrr_sentry32)
-
-#endif /* CONFIG_COMPAT */
-
-#ifdef CONFIG_MTRR
-extern void mtrr_ap_init(void);
-extern void mtrr_bp_init(void);
-extern void mtrr_save_fixed_ranges(void *);
-extern void mtrr_save_state(void);
-#else
-#define mtrr_ap_init() do {} while (0)
-#define mtrr_bp_init() do {} while (0)
-#define mtrr_save_fixed_ranges(arg) do {} while (0)
-#define mtrr_save_state() do {} while (0)
-#endif
-
-#endif /* __KERNEL__ */
-
-#endif /* _LINUX_MTRR_H */
diff --git a/include/asm-x86/namei.h b/include/asm-x86/namei.h
index 732f8f0b3dcd..415ef5d9550e 100644
--- a/include/asm-x86/namei.h
+++ b/include/asm-x86/namei.h
@@ -1,5 +1,11 @@
-#ifdef CONFIG_X86_32
-# include "namei_32.h"
-#else
-# include "namei_64.h"
-#endif
+#ifndef _ASM_X86_NAMEI_H
+#define _ASM_X86_NAMEI_H
+
+/* This dummy routine maybe changed to something useful
+ * for /usr/gnemul/ emulation stuff.
+ * Look at asm-sparc/namei.h for details.
+ */
+
+#define __emul_prefix() NULL
+
+#endif /* _ASM_X86_NAMEI_H */
diff --git a/include/asm-x86/namei_32.h b/include/asm-x86/namei_32.h
deleted file mode 100644
index 814865088617..000000000000
--- a/include/asm-x86/namei_32.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* $Id: namei.h,v 1.1 1996/12/13 14:48:21 jj Exp $
- * linux/include/asm-i386/namei.h
- *
- * Included from linux/fs/namei.c
- */
-
-#ifndef __I386_NAMEI_H
-#define __I386_NAMEI_H
-
-/* This dummy routine maybe changed to something useful
- * for /usr/gnemul/ emulation stuff.
- * Look at asm-sparc/namei.h for details.
- */
-
-#define __emul_prefix() NULL
-
-#endif /* __I386_NAMEI_H */
diff --git a/include/asm-x86/namei_64.h b/include/asm-x86/namei_64.h
deleted file mode 100644
index bef239f5318f..000000000000
--- a/include/asm-x86/namei_64.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef __X8664_NAMEI_H
-#define __X8664_NAMEI_H
-
-/* This dummy routine maybe changed to something useful
- * for /usr/gnemul/ emulation stuff.
- * Look at asm-sparc/namei.h for details.
- */
-
-#define __emul_prefix() NULL
-
-#endif
diff --git a/include/asm-x86/numa_64.h b/include/asm-x86/numa_64.h
index 933ff11ece15..0cc5c97a7fc9 100644
--- a/include/asm-x86/numa_64.h
+++ b/include/asm-x86/numa_64.h
@@ -2,6 +2,7 @@
#define _ASM_X8664_NUMA_H 1
#include <linux/nodemask.h>
+#include <asm/apicdef.h>
struct bootnode {
u64 start,end;
@@ -19,7 +20,7 @@ extern void numa_set_node(int cpu, int node);
extern void srat_reserve_add_area(int nodeid);
extern int hotadd_percent;
-extern unsigned char apicid_to_node[256];
+extern unsigned char apicid_to_node[MAX_LOCAL_APIC];
#ifdef CONFIG_NUMA
extern void __init init_cpu_to_node(void);
diff --git a/include/asm-x86/page_64.h b/include/asm-x86/page_64.h
index 88adf1afb0a2..c3b52bcb171e 100644
--- a/include/asm-x86/page_64.h
+++ b/include/asm-x86/page_64.h
@@ -134,6 +134,7 @@ extern unsigned long __phys_addr(unsigned long);
VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
#define __HAVE_ARCH_GATE_AREA 1
+#define vmemmap ((struct page *)VMEMMAP_START)
#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
diff --git a/include/asm-x86/param.h b/include/asm-x86/param.h
index 640851bab124..c996ec4da0c8 100644
--- a/include/asm-x86/param.h
+++ b/include/asm-x86/param.h
@@ -1,13 +1,22 @@
+#ifndef _ASM_X86_PARAM_H
+#define _ASM_X86_PARAM_H
+
#ifdef __KERNEL__
-# ifdef CONFIG_X86_32
-# include "param_32.h"
-# else
-# include "param_64.h"
-# endif
-#else
-# ifdef __i386__
-# include "param_32.h"
-# else
-# include "param_64.h"
-# endif
+# define HZ CONFIG_HZ /* Internal kernel timer frequency */
+# define USER_HZ 100 /* .. some user interfaces are in "ticks" */
+# define CLOCKS_PER_SEC (USER_HZ) /* like times() */
#endif
+
+#ifndef HZ
+#define HZ 100
+#endif
+
+#define EXEC_PAGESIZE 4096
+
+#ifndef NOGROUP
+#define NOGROUP (-1)
+#endif
+
+#define MAXHOSTNAMELEN 64 /* max length of hostname */
+
+#endif /* _ASM_X86_PARAM_H */
diff --git a/include/asm-x86/param_32.h b/include/asm-x86/param_32.h
deleted file mode 100644
index 21b32466fcdc..000000000000
--- a/include/asm-x86/param_32.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef _ASMi386_PARAM_H
-#define _ASMi386_PARAM_H
-
-#ifdef __KERNEL__
-# define HZ CONFIG_HZ /* Internal kernel timer frequency */
-# define USER_HZ 100 /* .. some user interfaces are in "ticks" */
-# define CLOCKS_PER_SEC (USER_HZ) /* like times() */
-#endif
-
-#ifndef HZ
-#define HZ 100
-#endif
-
-#define EXEC_PAGESIZE 4096
-
-#ifndef NOGROUP
-#define NOGROUP (-1)
-#endif
-
-#define MAXHOSTNAMELEN 64 /* max length of hostname */
-
-#endif
diff --git a/include/asm-x86/param_64.h b/include/asm-x86/param_64.h
deleted file mode 100644
index a728786c3c7c..000000000000
--- a/include/asm-x86/param_64.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef _ASMx86_64_PARAM_H
-#define _ASMx86_64_PARAM_H
-
-#ifdef __KERNEL__
-# define HZ CONFIG_HZ /* Internal kernel timer frequency */
-# define USER_HZ 100 /* .. some user interfaces are in "ticks */
-#define CLOCKS_PER_SEC (USER_HZ) /* like times() */
-#endif
-
-#ifndef HZ
-#define HZ 100
-#endif
-
-#define EXEC_PAGESIZE 4096
-
-#ifndef NOGROUP
-#define NOGROUP (-1)
-#endif
-
-#define MAXHOSTNAMELEN 64 /* max length of hostname */
-
-#endif
diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h
index 9fa3fa9e62d1..f59d370c5df4 100644
--- a/include/asm-x86/paravirt.h
+++ b/include/asm-x86/paravirt.h
@@ -25,27 +25,22 @@ struct tss_struct;
struct mm_struct;
struct desc_struct;
-/* Lazy mode for batching updates / context switch */
-enum paravirt_lazy_mode {
- PARAVIRT_LAZY_NONE = 0,
- PARAVIRT_LAZY_MMU = 1,
- PARAVIRT_LAZY_CPU = 2,
- PARAVIRT_LAZY_FLUSH = 3,
-};
-
-struct paravirt_ops
-{
+/* general info */
+struct pv_info {
unsigned int kernel_rpl;
int shared_kernel_pmd;
- int paravirt_enabled;
+ int paravirt_enabled;
const char *name;
+};
+struct pv_init_ops {
/*
- * Patch may replace one of the defined code sequences with arbitrary
- * code, subject to the same register constraints. This generally
- * means the code is not free to clobber any registers other than EAX.
- * The patch function should return the number of bytes of code
- * generated, as we nop pad the rest in generic code.
+ * Patch may replace one of the defined code sequences with
+ * arbitrary code, subject to the same register constraints.
+ * This generally means the code is not free to clobber any
+ * registers other than EAX. The patch function should return
+ * the number of bytes of code generated, as we nop pad the
+ * rest in generic code.
*/
unsigned (*patch)(u8 type, u16 clobber, void *insnbuf,
unsigned long addr, unsigned len);
@@ -55,29 +50,29 @@ struct paravirt_ops
char *(*memory_setup)(void);
void (*post_allocator_init)(void);
- void (*init_IRQ)(void);
- void (*time_init)(void);
-
- /*
- * Called before/after init_mm pagetable setup. setup_start
- * may reset %cr3, and may pre-install parts of the pagetable;
- * pagetable setup is expected to preserve any existing
- * mapping.
- */
- void (*pagetable_setup_start)(pgd_t *pgd_base);
- void (*pagetable_setup_done)(pgd_t *pgd_base);
-
/* Print a banner to identify the environment */
void (*banner)(void);
+};
+
+
+struct pv_lazy_ops {
+ /* Set deferred update mode, used for batching operations. */
+ void (*enter)(void);
+ void (*leave)(void);
+};
+
+struct pv_time_ops {
+ void (*time_init)(void);
/* Set and set time of day */
unsigned long (*get_wallclock)(void);
int (*set_wallclock)(unsigned long);
- /* cpuid emulation, mostly so that caps bits can be disabled */
- void (*cpuid)(unsigned int *eax, unsigned int *ebx,
- unsigned int *ecx, unsigned int *edx);
+ unsigned long long (*sched_clock)(void);
+ unsigned long (*get_cpu_khz)(void);
+};
+struct pv_cpu_ops {
/* hooks for various privileged instructions */
unsigned long (*get_debugreg)(int regno);
void (*set_debugreg)(int regno, unsigned long value);
@@ -87,41 +82,10 @@ struct paravirt_ops
unsigned long (*read_cr0)(void);
void (*write_cr0)(unsigned long);
- unsigned long (*read_cr2)(void);
- void (*write_cr2)(unsigned long);
-
- unsigned long (*read_cr3)(void);
- void (*write_cr3)(unsigned long);
-
unsigned long (*read_cr4_safe)(void);
unsigned long (*read_cr4)(void);
void (*write_cr4)(unsigned long);
- /*
- * Get/set interrupt state. save_fl and restore_fl are only
- * expected to use X86_EFLAGS_IF; all other bits
- * returned from save_fl are undefined, and may be ignored by
- * restore_fl.
- */
- unsigned long (*save_fl)(void);
- void (*restore_fl)(unsigned long);
- void (*irq_disable)(void);
- void (*irq_enable)(void);
- void (*safe_halt)(void);
- void (*halt)(void);
-
- void (*wbinvd)(void);
-
- /* MSR, PMC and TSR operations.
- err = 0/-EFAULT. wrmsr returns 0/-EFAULT. */
- u64 (*read_msr)(unsigned int msr, int *err);
- int (*write_msr)(unsigned int msr, u64 val);
-
- u64 (*read_tsc)(void);
- u64 (*read_pmc)(void);
- unsigned long long (*sched_clock)(void);
- unsigned long (*get_cpu_khz)(void);
-
/* Segment descriptor handling */
void (*load_tr_desc)(void);
void (*load_gdt)(const struct Xgt_desc_struct *);
@@ -140,18 +104,47 @@ struct paravirt_ops
void (*load_esp0)(struct tss_struct *tss, struct thread_struct *t);
void (*set_iopl_mask)(unsigned mask);
+
+ void (*wbinvd)(void);
void (*io_delay)(void);
+ /* cpuid emulation, mostly so that caps bits can be disabled */
+ void (*cpuid)(unsigned int *eax, unsigned int *ebx,
+ unsigned int *ecx, unsigned int *edx);
+
+ /* MSR, PMC and TSR operations.
+ err = 0/-EFAULT. wrmsr returns 0/-EFAULT. */
+ u64 (*read_msr)(unsigned int msr, int *err);
+ int (*write_msr)(unsigned int msr, u64 val);
+
+ u64 (*read_tsc)(void);
+ u64 (*read_pmc)(void);
+
+ /* These two are jmp to, not actually called. */
+ void (*irq_enable_sysexit)(void);
+ void (*iret)(void);
+
+ struct pv_lazy_ops lazy_mode;
+};
+
+struct pv_irq_ops {
+ void (*init_IRQ)(void);
+
/*
- * Hooks for intercepting the creation/use/destruction of an
- * mm_struct.
+ * Get/set interrupt state. save_fl and restore_fl are only
+ * expected to use X86_EFLAGS_IF; all other bits
+ * returned from save_fl are undefined, and may be ignored by
+ * restore_fl.
*/
- void (*activate_mm)(struct mm_struct *prev,
- struct mm_struct *next);
- void (*dup_mmap)(struct mm_struct *oldmm,
- struct mm_struct *mm);
- void (*exit_mmap)(struct mm_struct *mm);
+ unsigned long (*save_fl)(void);
+ void (*restore_fl)(unsigned long);
+ void (*irq_disable)(void);
+ void (*irq_enable)(void);
+ void (*safe_halt)(void);
+ void (*halt)(void);
+};
+struct pv_apic_ops {
#ifdef CONFIG_X86_LOCAL_APIC
/*
* Direct APIC operations, principally for VMI. Ideally
@@ -167,6 +160,34 @@ struct paravirt_ops
unsigned long start_eip,
unsigned long start_esp);
#endif
+};
+
+struct pv_mmu_ops {
+ /*
+ * Called before/after init_mm pagetable setup. setup_start
+ * may reset %cr3, and may pre-install parts of the pagetable;
+ * pagetable setup is expected to preserve any existing
+ * mapping.
+ */
+ void (*pagetable_setup_start)(pgd_t *pgd_base);
+ void (*pagetable_setup_done)(pgd_t *pgd_base);
+
+ unsigned long (*read_cr2)(void);
+ void (*write_cr2)(unsigned long);
+
+ unsigned long (*read_cr3)(void);
+ void (*write_cr3)(unsigned long);
+
+ /*
+ * Hooks for intercepting the creation/use/destruction of an
+ * mm_struct.
+ */
+ void (*activate_mm)(struct mm_struct *prev,
+ struct mm_struct *next);
+ void (*dup_mmap)(struct mm_struct *oldmm,
+ struct mm_struct *mm);
+ void (*exit_mmap)(struct mm_struct *mm);
+
/* TLB operations */
void (*flush_tlb_user)(void);
@@ -191,15 +212,12 @@ struct paravirt_ops
void (*pte_update_defer)(struct mm_struct *mm,
unsigned long addr, pte_t *ptep);
-#ifdef CONFIG_HIGHPTE
- void *(*kmap_atomic_pte)(struct page *page, enum km_type type);
-#endif
-
#ifdef CONFIG_X86_PAE
void (*set_pte_atomic)(pte_t *ptep, pte_t pteval);
- void (*set_pte_present)(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte);
+ void (*set_pte_present)(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pte);
void (*set_pud)(pud_t *pudp, pud_t pudval);
- void (*pte_clear)(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
+ void (*pte_clear)(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
void (*pmd_clear)(pmd_t *pmdp);
unsigned long long (*pte_val)(pte_t);
@@ -217,21 +235,40 @@ struct paravirt_ops
pgd_t (*make_pgd)(unsigned long pgd);
#endif
- /* Set deferred update mode, used for batching operations. */
- void (*set_lazy_mode)(enum paravirt_lazy_mode mode);
+#ifdef CONFIG_HIGHPTE
+ void *(*kmap_atomic_pte)(struct page *page, enum km_type type);
+#endif
- /* These two are jmp to, not actually called. */
- void (*irq_enable_sysexit)(void);
- void (*iret)(void);
+ struct pv_lazy_ops lazy_mode;
};
-extern struct paravirt_ops paravirt_ops;
+/* This contains all the paravirt structures: we get a convenient
+ * number for each function using the offset which we use to indicate
+ * what to patch. */
+struct paravirt_patch_template
+{
+ struct pv_init_ops pv_init_ops;
+ struct pv_time_ops pv_time_ops;
+ struct pv_cpu_ops pv_cpu_ops;
+ struct pv_irq_ops pv_irq_ops;
+ struct pv_apic_ops pv_apic_ops;
+ struct pv_mmu_ops pv_mmu_ops;
+};
+
+extern struct pv_info pv_info;
+extern struct pv_init_ops pv_init_ops;
+extern struct pv_time_ops pv_time_ops;
+extern struct pv_cpu_ops pv_cpu_ops;
+extern struct pv_irq_ops pv_irq_ops;
+extern struct pv_apic_ops pv_apic_ops;
+extern struct pv_mmu_ops pv_mmu_ops;
#define PARAVIRT_PATCH(x) \
- (offsetof(struct paravirt_ops, x) / sizeof(void *))
+ (offsetof(struct paravirt_patch_template, x) / sizeof(void *))
-#define paravirt_type(type) \
- [paravirt_typenum] "i" (PARAVIRT_PATCH(type))
+#define paravirt_type(op) \
+ [paravirt_typenum] "i" (PARAVIRT_PATCH(op)), \
+ [paravirt_opptr] "m" (op)
#define paravirt_clobber(clobber) \
[paravirt_clobber] "i" (clobber)
@@ -258,7 +295,7 @@ unsigned paravirt_patch_call(void *insnbuf,
const void *target, u16 tgt_clobbers,
unsigned long addr, u16 site_clobbers,
unsigned len);
-unsigned paravirt_patch_jmp(const void *target, void *insnbuf,
+unsigned paravirt_patch_jmp(void *insnbuf, const void *target,
unsigned long addr, unsigned len);
unsigned paravirt_patch_default(u8 type, u16 clobbers, void *insnbuf,
unsigned long addr, unsigned len);
@@ -271,14 +308,14 @@ int paravirt_disable_iospace(void);
/*
* This generates an indirect call based on the operation type number.
* The type number, computed in PARAVIRT_PATCH, is derived from the
- * offset into the paravirt_ops structure, and can therefore be freely
- * converted back into a structure offset.
+ * offset into the paravirt_patch_template structure, and can therefore be
+ * freely converted back into a structure offset.
*/
-#define PARAVIRT_CALL "call *(paravirt_ops+%c[paravirt_typenum]*4);"
+#define PARAVIRT_CALL "call *%[paravirt_opptr];"
/*
- * These macros are intended to wrap calls into a paravirt_ops
- * operation, so that they can be later identified and patched at
+ * These macros are intended to wrap calls through one of the paravirt
+ * ops structs, so that they can be later identified and patched at
* runtime.
*
* Normally, a call to a pv_op function is a simple indirect call:
@@ -301,7 +338,7 @@ int paravirt_disable_iospace(void);
* The call instruction itself is marked by placing its start address
* and size into the .parainstructions section, so that
* apply_paravirt() in arch/i386/kernel/alternative.c can do the
- * appropriate patching under the control of the backend paravirt_ops
+ * appropriate patching under the control of the backend pv_init_ops
* implementation.
*
* Unfortunately there's no way to get gcc to generate the args setup
@@ -409,36 +446,36 @@ int paravirt_disable_iospace(void);
static inline int paravirt_enabled(void)
{
- return paravirt_ops.paravirt_enabled;
+ return pv_info.paravirt_enabled;
}
static inline void load_esp0(struct tss_struct *tss,
struct thread_struct *thread)
{
- PVOP_VCALL2(load_esp0, tss, thread);
+ PVOP_VCALL2(pv_cpu_ops.load_esp0, tss, thread);
}
-#define ARCH_SETUP paravirt_ops.arch_setup();
+#define ARCH_SETUP pv_init_ops.arch_setup();
static inline unsigned long get_wallclock(void)
{
- return PVOP_CALL0(unsigned long, get_wallclock);
+ return PVOP_CALL0(unsigned long, pv_time_ops.get_wallclock);
}
static inline int set_wallclock(unsigned long nowtime)
{
- return PVOP_CALL1(int, set_wallclock, nowtime);
+ return PVOP_CALL1(int, pv_time_ops.set_wallclock, nowtime);
}
static inline void (*choose_time_init(void))(void)
{
- return paravirt_ops.time_init;
+ return pv_time_ops.time_init;
}
/* The paravirtualized CPUID instruction. */
static inline void __cpuid(unsigned int *eax, unsigned int *ebx,
unsigned int *ecx, unsigned int *edx)
{
- PVOP_VCALL4(cpuid, eax, ebx, ecx, edx);
+ PVOP_VCALL4(pv_cpu_ops.cpuid, eax, ebx, ecx, edx);
}
/*
@@ -446,87 +483,87 @@ static inline void __cpuid(unsigned int *eax, unsigned int *ebx,
*/
static inline unsigned long paravirt_get_debugreg(int reg)
{
- return PVOP_CALL1(unsigned long, get_debugreg, reg);
+ return PVOP_CALL1(unsigned long, pv_cpu_ops.get_debugreg, reg);
}
#define get_debugreg(var, reg) var = paravirt_get_debugreg(reg)
static inline void set_debugreg(unsigned long val, int reg)
{
- PVOP_VCALL2(set_debugreg, reg, val);
+ PVOP_VCALL2(pv_cpu_ops.set_debugreg, reg, val);
}
static inline void clts(void)
{
- PVOP_VCALL0(clts);
+ PVOP_VCALL0(pv_cpu_ops.clts);
}
static inline unsigned long read_cr0(void)
{
- return PVOP_CALL0(unsigned long, read_cr0);
+ return PVOP_CALL0(unsigned long, pv_cpu_ops.read_cr0);
}
static inline void write_cr0(unsigned long x)
{
- PVOP_VCALL1(write_cr0, x);
+ PVOP_VCALL1(pv_cpu_ops.write_cr0, x);
}
static inline unsigned long read_cr2(void)
{
- return PVOP_CALL0(unsigned long, read_cr2);
+ return PVOP_CALL0(unsigned long, pv_mmu_ops.read_cr2);
}
static inline void write_cr2(unsigned long x)
{
- PVOP_VCALL1(write_cr2, x);
+ PVOP_VCALL1(pv_mmu_ops.write_cr2, x);
}
static inline unsigned long read_cr3(void)
{
- return PVOP_CALL0(unsigned long, read_cr3);
+ return PVOP_CALL0(unsigned long, pv_mmu_ops.read_cr3);
}
static inline void write_cr3(unsigned long x)
{
- PVOP_VCALL1(write_cr3, x);
+ PVOP_VCALL1(pv_mmu_ops.write_cr3, x);
}
static inline unsigned long read_cr4(void)
{
- return PVOP_CALL0(unsigned long, read_cr4);
+ return PVOP_CALL0(unsigned long, pv_cpu_ops.read_cr4);
}
static inline unsigned long read_cr4_safe(void)
{
- return PVOP_CALL0(unsigned long, read_cr4_safe);
+ return PVOP_CALL0(unsigned long, pv_cpu_ops.read_cr4_safe);
}
static inline void write_cr4(unsigned long x)
{
- PVOP_VCALL1(write_cr4, x);
+ PVOP_VCALL1(pv_cpu_ops.write_cr4, x);
}
static inline void raw_safe_halt(void)
{
- PVOP_VCALL0(safe_halt);
+ PVOP_VCALL0(pv_irq_ops.safe_halt);
}
static inline void halt(void)
{
- PVOP_VCALL0(safe_halt);
+ PVOP_VCALL0(pv_irq_ops.safe_halt);
}
static inline void wbinvd(void)
{
- PVOP_VCALL0(wbinvd);
+ PVOP_VCALL0(pv_cpu_ops.wbinvd);
}
-#define get_kernel_rpl() (paravirt_ops.kernel_rpl)
+#define get_kernel_rpl() (pv_info.kernel_rpl)
static inline u64 paravirt_read_msr(unsigned msr, int *err)
{
- return PVOP_CALL2(u64, read_msr, msr, err);
+ return PVOP_CALL2(u64, pv_cpu_ops.read_msr, msr, err);
}
static inline int paravirt_write_msr(unsigned msr, unsigned low, unsigned high)
{
- return PVOP_CALL3(int, write_msr, msr, low, high);
+ return PVOP_CALL3(int, pv_cpu_ops.write_msr, msr, low, high);
}
/* These should all do BUG_ON(_err), but our headers are too tangled. */
@@ -560,7 +597,7 @@ static inline int paravirt_write_msr(unsigned msr, unsigned low, unsigned high)
static inline u64 paravirt_read_tsc(void)
{
- return PVOP_CALL0(u64, read_tsc);
+ return PVOP_CALL0(u64, pv_cpu_ops.read_tsc);
}
#define rdtscl(low) do { \
@@ -572,15 +609,15 @@ static inline u64 paravirt_read_tsc(void)
static inline unsigned long long paravirt_sched_clock(void)
{
- return PVOP_CALL0(unsigned long long, sched_clock);
+ return PVOP_CALL0(unsigned long long, pv_time_ops.sched_clock);
}
-#define calculate_cpu_khz() (paravirt_ops.get_cpu_khz())
+#define calculate_cpu_khz() (pv_time_ops.get_cpu_khz())
#define write_tsc(val1,val2) wrmsr(0x10, val1, val2)
static inline unsigned long long paravirt_read_pmc(int counter)
{
- return PVOP_CALL1(u64, read_pmc, counter);
+ return PVOP_CALL1(u64, pv_cpu_ops.read_pmc, counter);
}
#define rdpmc(counter,low,high) do { \
@@ -591,61 +628,61 @@ static inline unsigned long long paravirt_read_pmc(int counter)
static inline void load_TR_desc(void)
{
- PVOP_VCALL0(load_tr_desc);
+ PVOP_VCALL0(pv_cpu_ops.load_tr_desc);
}
static inline void load_gdt(const struct Xgt_desc_struct *dtr)
{
- PVOP_VCALL1(load_gdt, dtr);
+ PVOP_VCALL1(pv_cpu_ops.load_gdt, dtr);
}
static inline void load_idt(const struct Xgt_desc_struct *dtr)
{
- PVOP_VCALL1(load_idt, dtr);
+ PVOP_VCALL1(pv_cpu_ops.load_idt, dtr);
}
static inline void set_ldt(const void *addr, unsigned entries)
{
- PVOP_VCALL2(set_ldt, addr, entries);
+ PVOP_VCALL2(pv_cpu_ops.set_ldt, addr, entries);
}
static inline void store_gdt(struct Xgt_desc_struct *dtr)
{
- PVOP_VCALL1(store_gdt, dtr);
+ PVOP_VCALL1(pv_cpu_ops.store_gdt, dtr);
}
static inline void store_idt(struct Xgt_desc_struct *dtr)
{
- PVOP_VCALL1(store_idt, dtr);
+ PVOP_VCALL1(pv_cpu_ops.store_idt, dtr);
}
static inline unsigned long paravirt_store_tr(void)
{
- return PVOP_CALL0(unsigned long, store_tr);
+ return PVOP_CALL0(unsigned long, pv_cpu_ops.store_tr);
}
#define store_tr(tr) ((tr) = paravirt_store_tr())
static inline void load_TLS(struct thread_struct *t, unsigned cpu)
{
- PVOP_VCALL2(load_tls, t, cpu);
+ PVOP_VCALL2(pv_cpu_ops.load_tls, t, cpu);
}
static inline void write_ldt_entry(void *dt, int entry, u32 low, u32 high)
{
- PVOP_VCALL4(write_ldt_entry, dt, entry, low, high);
+ PVOP_VCALL4(pv_cpu_ops.write_ldt_entry, dt, entry, low, high);
}
static inline void write_gdt_entry(void *dt, int entry, u32 low, u32 high)
{
- PVOP_VCALL4(write_gdt_entry, dt, entry, low, high);
+ PVOP_VCALL4(pv_cpu_ops.write_gdt_entry, dt, entry, low, high);
}
static inline void write_idt_entry(void *dt, int entry, u32 low, u32 high)
{
- PVOP_VCALL4(write_idt_entry, dt, entry, low, high);
+ PVOP_VCALL4(pv_cpu_ops.write_idt_entry, dt, entry, low, high);
}
static inline void set_iopl_mask(unsigned mask)
{
- PVOP_VCALL1(set_iopl_mask, mask);
+ PVOP_VCALL1(pv_cpu_ops.set_iopl_mask, mask);
}
/* The paravirtualized I/O functions */
static inline void slow_down_io(void) {
- paravirt_ops.io_delay();
+ pv_cpu_ops.io_delay();
#ifdef REALLY_SLOW_IO
- paravirt_ops.io_delay();
- paravirt_ops.io_delay();
- paravirt_ops.io_delay();
+ pv_cpu_ops.io_delay();
+ pv_cpu_ops.io_delay();
+ pv_cpu_ops.io_delay();
#endif
}
@@ -655,121 +692,120 @@ static inline void slow_down_io(void) {
*/
static inline void apic_write(unsigned long reg, unsigned long v)
{
- PVOP_VCALL2(apic_write, reg, v);
+ PVOP_VCALL2(pv_apic_ops.apic_write, reg, v);
}
static inline void apic_write_atomic(unsigned long reg, unsigned long v)
{
- PVOP_VCALL2(apic_write_atomic, reg, v);
+ PVOP_VCALL2(pv_apic_ops.apic_write_atomic, reg, v);
}
static inline unsigned long apic_read(unsigned long reg)
{
- return PVOP_CALL1(unsigned long, apic_read, reg);
+ return PVOP_CALL1(unsigned long, pv_apic_ops.apic_read, reg);
}
static inline void setup_boot_clock(void)
{
- PVOP_VCALL0(setup_boot_clock);
+ PVOP_VCALL0(pv_apic_ops.setup_boot_clock);
}
static inline void setup_secondary_clock(void)
{
- PVOP_VCALL0(setup_secondary_clock);
+ PVOP_VCALL0(pv_apic_ops.setup_secondary_clock);
}
#endif
static inline void paravirt_post_allocator_init(void)
{
- if (paravirt_ops.post_allocator_init)
- (*paravirt_ops.post_allocator_init)();
+ if (pv_init_ops.post_allocator_init)
+ (*pv_init_ops.post_allocator_init)();
}
static inline void paravirt_pagetable_setup_start(pgd_t *base)
{
- if (paravirt_ops.pagetable_setup_start)
- (*paravirt_ops.pagetable_setup_start)(base);
+ (*pv_mmu_ops.pagetable_setup_start)(base);
}
static inline void paravirt_pagetable_setup_done(pgd_t *base)
{
- if (paravirt_ops.pagetable_setup_done)
- (*paravirt_ops.pagetable_setup_done)(base);
+ (*pv_mmu_ops.pagetable_setup_done)(base);
}
#ifdef CONFIG_SMP
static inline void startup_ipi_hook(int phys_apicid, unsigned long start_eip,
unsigned long start_esp)
{
- PVOP_VCALL3(startup_ipi_hook, phys_apicid, start_eip, start_esp);
+ PVOP_VCALL3(pv_apic_ops.startup_ipi_hook,
+ phys_apicid, start_eip, start_esp);
}
#endif
static inline void paravirt_activate_mm(struct mm_struct *prev,
struct mm_struct *next)
{
- PVOP_VCALL2(activate_mm, prev, next);
+ PVOP_VCALL2(pv_mmu_ops.activate_mm, prev, next);
}
static inline void arch_dup_mmap(struct mm_struct *oldmm,
struct mm_struct *mm)
{
- PVOP_VCALL2(dup_mmap, oldmm, mm);
+ PVOP_VCALL2(pv_mmu_ops.dup_mmap, oldmm, mm);
}
static inline void arch_exit_mmap(struct mm_struct *mm)
{
- PVOP_VCALL1(exit_mmap, mm);
+ PVOP_VCALL1(pv_mmu_ops.exit_mmap, mm);
}
static inline void __flush_tlb(void)
{
- PVOP_VCALL0(flush_tlb_user);
+ PVOP_VCALL0(pv_mmu_ops.flush_tlb_user);
}
static inline void __flush_tlb_global(void)
{
- PVOP_VCALL0(flush_tlb_kernel);
+ PVOP_VCALL0(pv_mmu_ops.flush_tlb_kernel);
}
static inline void __flush_tlb_single(unsigned long addr)
{
- PVOP_VCALL1(flush_tlb_single, addr);
+ PVOP_VCALL1(pv_mmu_ops.flush_tlb_single, addr);
}
static inline void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
unsigned long va)
{
- PVOP_VCALL3(flush_tlb_others, &cpumask, mm, va);
+ PVOP_VCALL3(pv_mmu_ops.flush_tlb_others, &cpumask, mm, va);
}
static inline void paravirt_alloc_pt(struct mm_struct *mm, unsigned pfn)
{
- PVOP_VCALL2(alloc_pt, mm, pfn);
+ PVOP_VCALL2(pv_mmu_ops.alloc_pt, mm, pfn);
}
static inline void paravirt_release_pt(unsigned pfn)
{
- PVOP_VCALL1(release_pt, pfn);
+ PVOP_VCALL1(pv_mmu_ops.release_pt, pfn);
}
static inline void paravirt_alloc_pd(unsigned pfn)
{
- PVOP_VCALL1(alloc_pd, pfn);
+ PVOP_VCALL1(pv_mmu_ops.alloc_pd, pfn);
}
static inline void paravirt_alloc_pd_clone(unsigned pfn, unsigned clonepfn,
unsigned start, unsigned count)
{
- PVOP_VCALL4(alloc_pd_clone, pfn, clonepfn, start, count);
+ PVOP_VCALL4(pv_mmu_ops.alloc_pd_clone, pfn, clonepfn, start, count);
}
static inline void paravirt_release_pd(unsigned pfn)
{
- PVOP_VCALL1(release_pd, pfn);
+ PVOP_VCALL1(pv_mmu_ops.release_pd, pfn);
}
#ifdef CONFIG_HIGHPTE
static inline void *kmap_atomic_pte(struct page *page, enum km_type type)
{
unsigned long ret;
- ret = PVOP_CALL2(unsigned long, kmap_atomic_pte, page, type);
+ ret = PVOP_CALL2(unsigned long, pv_mmu_ops.kmap_atomic_pte, page, type);
return (void *)ret;
}
#endif
@@ -777,162 +813,191 @@ static inline void *kmap_atomic_pte(struct page *page, enum km_type type)
static inline void pte_update(struct mm_struct *mm, unsigned long addr,
pte_t *ptep)
{
- PVOP_VCALL3(pte_update, mm, addr, ptep);
+ PVOP_VCALL3(pv_mmu_ops.pte_update, mm, addr, ptep);
}
static inline void pte_update_defer(struct mm_struct *mm, unsigned long addr,
pte_t *ptep)
{
- PVOP_VCALL3(pte_update_defer, mm, addr, ptep);
+ PVOP_VCALL3(pv_mmu_ops.pte_update_defer, mm, addr, ptep);
}
#ifdef CONFIG_X86_PAE
static inline pte_t __pte(unsigned long long val)
{
- unsigned long long ret = PVOP_CALL2(unsigned long long, make_pte,
+ unsigned long long ret = PVOP_CALL2(unsigned long long,
+ pv_mmu_ops.make_pte,
val, val >> 32);
return (pte_t) { ret, ret >> 32 };
}
static inline pmd_t __pmd(unsigned long long val)
{
- return (pmd_t) { PVOP_CALL2(unsigned long long, make_pmd, val, val >> 32) };
+ return (pmd_t) { PVOP_CALL2(unsigned long long, pv_mmu_ops.make_pmd,
+ val, val >> 32) };
}
static inline pgd_t __pgd(unsigned long long val)
{
- return (pgd_t) { PVOP_CALL2(unsigned long long, make_pgd, val, val >> 32) };
+ return (pgd_t) { PVOP_CALL2(unsigned long long, pv_mmu_ops.make_pgd,
+ val, val >> 32) };
}
static inline unsigned long long pte_val(pte_t x)
{
- return PVOP_CALL2(unsigned long long, pte_val, x.pte_low, x.pte_high);
+ return PVOP_CALL2(unsigned long long, pv_mmu_ops.pte_val,
+ x.pte_low, x.pte_high);
}
static inline unsigned long long pmd_val(pmd_t x)
{
- return PVOP_CALL2(unsigned long long, pmd_val, x.pmd, x.pmd >> 32);
+ return PVOP_CALL2(unsigned long long, pv_mmu_ops.pmd_val,
+ x.pmd, x.pmd >> 32);
}
static inline unsigned long long pgd_val(pgd_t x)
{
- return PVOP_CALL2(unsigned long long, pgd_val, x.pgd, x.pgd >> 32);
+ return PVOP_CALL2(unsigned long long, pv_mmu_ops.pgd_val,
+ x.pgd, x.pgd >> 32);
}
static inline void set_pte(pte_t *ptep, pte_t pteval)
{
- PVOP_VCALL3(set_pte, ptep, pteval.pte_low, pteval.pte_high);
+ PVOP_VCALL3(pv_mmu_ops.set_pte, ptep, pteval.pte_low, pteval.pte_high);
}
static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, pte_t pteval)
{
/* 5 arg words */
- paravirt_ops.set_pte_at(mm, addr, ptep, pteval);
+ pv_mmu_ops.set_pte_at(mm, addr, ptep, pteval);
}
static inline void set_pte_atomic(pte_t *ptep, pte_t pteval)
{
- PVOP_VCALL3(set_pte_atomic, ptep, pteval.pte_low, pteval.pte_high);
+ PVOP_VCALL3(pv_mmu_ops.set_pte_atomic, ptep,
+ pteval.pte_low, pteval.pte_high);
}
static inline void set_pte_present(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, pte_t pte)
{
/* 5 arg words */
- paravirt_ops.set_pte_present(mm, addr, ptep, pte);
+ pv_mmu_ops.set_pte_present(mm, addr, ptep, pte);
}
static inline void set_pmd(pmd_t *pmdp, pmd_t pmdval)
{
- PVOP_VCALL3(set_pmd, pmdp, pmdval.pmd, pmdval.pmd >> 32);
+ PVOP_VCALL3(pv_mmu_ops.set_pmd, pmdp,
+ pmdval.pmd, pmdval.pmd >> 32);
}
static inline void set_pud(pud_t *pudp, pud_t pudval)
{
- PVOP_VCALL3(set_pud, pudp, pudval.pgd.pgd, pudval.pgd.pgd >> 32);
+ PVOP_VCALL3(pv_mmu_ops.set_pud, pudp,
+ pudval.pgd.pgd, pudval.pgd.pgd >> 32);
}
static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
- PVOP_VCALL3(pte_clear, mm, addr, ptep);
+ PVOP_VCALL3(pv_mmu_ops.pte_clear, mm, addr, ptep);
}
static inline void pmd_clear(pmd_t *pmdp)
{
- PVOP_VCALL1(pmd_clear, pmdp);
+ PVOP_VCALL1(pv_mmu_ops.pmd_clear, pmdp);
}
#else /* !CONFIG_X86_PAE */
static inline pte_t __pte(unsigned long val)
{
- return (pte_t) { PVOP_CALL1(unsigned long, make_pte, val) };
+ return (pte_t) { PVOP_CALL1(unsigned long, pv_mmu_ops.make_pte, val) };
}
static inline pgd_t __pgd(unsigned long val)
{
- return (pgd_t) { PVOP_CALL1(unsigned long, make_pgd, val) };
+ return (pgd_t) { PVOP_CALL1(unsigned long, pv_mmu_ops.make_pgd, val) };
}
static inline unsigned long pte_val(pte_t x)
{
- return PVOP_CALL1(unsigned long, pte_val, x.pte_low);
+ return PVOP_CALL1(unsigned long, pv_mmu_ops.pte_val, x.pte_low);
}
static inline unsigned long pgd_val(pgd_t x)
{
- return PVOP_CALL1(unsigned long, pgd_val, x.pgd);
+ return PVOP_CALL1(unsigned long, pv_mmu_ops.pgd_val, x.pgd);
}
static inline void set_pte(pte_t *ptep, pte_t pteval)
{
- PVOP_VCALL2(set_pte, ptep, pteval.pte_low);
+ PVOP_VCALL2(pv_mmu_ops.set_pte, ptep, pteval.pte_low);
}
static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, pte_t pteval)
{
- PVOP_VCALL4(set_pte_at, mm, addr, ptep, pteval.pte_low);
+ PVOP_VCALL4(pv_mmu_ops.set_pte_at, mm, addr, ptep, pteval.pte_low);
}
static inline void set_pmd(pmd_t *pmdp, pmd_t pmdval)
{
- PVOP_VCALL2(set_pmd, pmdp, pmdval.pud.pgd.pgd);
+ PVOP_VCALL2(pv_mmu_ops.set_pmd, pmdp, pmdval.pud.pgd.pgd);
}
#endif /* CONFIG_X86_PAE */
+/* Lazy mode for batching updates / context switch */
+enum paravirt_lazy_mode {
+ PARAVIRT_LAZY_NONE,
+ PARAVIRT_LAZY_MMU,
+ PARAVIRT_LAZY_CPU,
+};
+
+enum paravirt_lazy_mode paravirt_get_lazy_mode(void);
+void paravirt_enter_lazy_cpu(void);
+void paravirt_leave_lazy_cpu(void);
+void paravirt_enter_lazy_mmu(void);
+void paravirt_leave_lazy_mmu(void);
+void paravirt_leave_lazy(enum paravirt_lazy_mode mode);
+
#define __HAVE_ARCH_ENTER_LAZY_CPU_MODE
static inline void arch_enter_lazy_cpu_mode(void)
{
- PVOP_VCALL1(set_lazy_mode, PARAVIRT_LAZY_CPU);
+ PVOP_VCALL0(pv_cpu_ops.lazy_mode.enter);
}
static inline void arch_leave_lazy_cpu_mode(void)
{
- PVOP_VCALL1(set_lazy_mode, PARAVIRT_LAZY_NONE);
+ PVOP_VCALL0(pv_cpu_ops.lazy_mode.leave);
}
static inline void arch_flush_lazy_cpu_mode(void)
{
- PVOP_VCALL1(set_lazy_mode, PARAVIRT_LAZY_FLUSH);
+ if (unlikely(paravirt_get_lazy_mode() == PARAVIRT_LAZY_CPU)) {
+ arch_leave_lazy_cpu_mode();
+ arch_enter_lazy_cpu_mode();
+ }
}
#define __HAVE_ARCH_ENTER_LAZY_MMU_MODE
static inline void arch_enter_lazy_mmu_mode(void)
{
- PVOP_VCALL1(set_lazy_mode, PARAVIRT_LAZY_MMU);
+ PVOP_VCALL0(pv_mmu_ops.lazy_mode.enter);
}
static inline void arch_leave_lazy_mmu_mode(void)
{
- PVOP_VCALL1(set_lazy_mode, PARAVIRT_LAZY_NONE);
+ PVOP_VCALL0(pv_mmu_ops.lazy_mode.leave);
}
static inline void arch_flush_lazy_mmu_mode(void)
{
- PVOP_VCALL1(set_lazy_mode, PARAVIRT_LAZY_FLUSH);
+ if (unlikely(paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU)) {
+ arch_leave_lazy_mmu_mode();
+ arch_enter_lazy_mmu_mode();
+ }
}
void _paravirt_nop(void);
@@ -957,7 +1022,7 @@ static inline unsigned long __raw_local_save_flags(void)
PARAVIRT_CALL
"popl %%edx; popl %%ecx")
: "=a"(f)
- : paravirt_type(save_fl),
+ : paravirt_type(pv_irq_ops.save_fl),
paravirt_clobber(CLBR_EAX)
: "memory", "cc");
return f;
@@ -970,7 +1035,7 @@ static inline void raw_local_irq_restore(unsigned long f)
"popl %%edx; popl %%ecx")
: "=a"(f)
: "0"(f),
- paravirt_type(restore_fl),
+ paravirt_type(pv_irq_ops.restore_fl),
paravirt_clobber(CLBR_EAX)
: "memory", "cc");
}
@@ -981,7 +1046,7 @@ static inline void raw_local_irq_disable(void)
PARAVIRT_CALL
"popl %%edx; popl %%ecx")
:
- : paravirt_type(irq_disable),
+ : paravirt_type(pv_irq_ops.irq_disable),
paravirt_clobber(CLBR_EAX)
: "memory", "eax", "cc");
}
@@ -992,7 +1057,7 @@ static inline void raw_local_irq_enable(void)
PARAVIRT_CALL
"popl %%edx; popl %%ecx")
:
- : paravirt_type(irq_enable),
+ : paravirt_type(pv_irq_ops.irq_enable),
paravirt_clobber(CLBR_EAX)
: "memory", "eax", "cc");
}
@@ -1008,21 +1073,23 @@ static inline unsigned long __raw_local_irq_save(void)
#define CLI_STRING \
_paravirt_alt("pushl %%ecx; pushl %%edx;" \
- "call *paravirt_ops+%c[paravirt_cli_type]*4;" \
+ "call *%[paravirt_cli_opptr];" \
"popl %%edx; popl %%ecx", \
"%c[paravirt_cli_type]", "%c[paravirt_clobber]")
#define STI_STRING \
_paravirt_alt("pushl %%ecx; pushl %%edx;" \
- "call *paravirt_ops+%c[paravirt_sti_type]*4;" \
+ "call *%[paravirt_sti_opptr];" \
"popl %%edx; popl %%ecx", \
"%c[paravirt_sti_type]", "%c[paravirt_clobber]")
#define CLI_STI_CLOBBERS , "%eax"
#define CLI_STI_INPUT_ARGS \
, \
- [paravirt_cli_type] "i" (PARAVIRT_PATCH(irq_disable)), \
- [paravirt_sti_type] "i" (PARAVIRT_PATCH(irq_enable)), \
+ [paravirt_cli_type] "i" (PARAVIRT_PATCH(pv_irq_ops.irq_disable)), \
+ [paravirt_cli_opptr] "m" (pv_irq_ops.irq_disable), \
+ [paravirt_sti_type] "i" (PARAVIRT_PATCH(pv_irq_ops.irq_enable)), \
+ [paravirt_sti_opptr] "m" (pv_irq_ops.irq_enable), \
paravirt_clobber(CLBR_EAX)
/* Make sure as little as possible of this mess escapes. */
@@ -1042,7 +1109,7 @@ static inline unsigned long __raw_local_irq_save(void)
#else /* __ASSEMBLY__ */
-#define PARA_PATCH(off) ((off) / 4)
+#define PARA_PATCH(struct, off) ((PARAVIRT_PATCH_##struct + (off)) / 4)
#define PARA_SITE(ptype, clobbers, ops) \
771:; \
@@ -1055,29 +1122,29 @@ static inline unsigned long __raw_local_irq_save(void)
.short clobbers; \
.popsection
-#define INTERRUPT_RETURN \
- PARA_SITE(PARA_PATCH(PARAVIRT_iret), CLBR_NONE, \
- jmp *%cs:paravirt_ops+PARAVIRT_iret)
+#define INTERRUPT_RETURN \
+ PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_iret), CLBR_NONE, \
+ jmp *%cs:pv_cpu_ops+PV_CPU_iret)
#define DISABLE_INTERRUPTS(clobbers) \
- PARA_SITE(PARA_PATCH(PARAVIRT_irq_disable), clobbers, \
+ PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_irq_disable), clobbers, \
pushl %eax; pushl %ecx; pushl %edx; \
- call *%cs:paravirt_ops+PARAVIRT_irq_disable; \
+ call *%cs:pv_irq_ops+PV_IRQ_irq_disable; \
popl %edx; popl %ecx; popl %eax) \
#define ENABLE_INTERRUPTS(clobbers) \
- PARA_SITE(PARA_PATCH(PARAVIRT_irq_enable), clobbers, \
+ PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_irq_enable), clobbers, \
pushl %eax; pushl %ecx; pushl %edx; \
- call *%cs:paravirt_ops+PARAVIRT_irq_enable; \
+ call *%cs:pv_irq_ops+PV_IRQ_irq_enable; \
popl %edx; popl %ecx; popl %eax)
-#define ENABLE_INTERRUPTS_SYSEXIT \
- PARA_SITE(PARA_PATCH(PARAVIRT_irq_enable_sysexit), CLBR_NONE, \
- jmp *%cs:paravirt_ops+PARAVIRT_irq_enable_sysexit)
+#define ENABLE_INTERRUPTS_SYSEXIT \
+ PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_irq_enable_sysexit), CLBR_NONE,\
+ jmp *%cs:pv_cpu_ops+PV_CPU_irq_enable_sysexit)
#define GET_CR0_INTO_EAX \
push %ecx; push %edx; \
- call *paravirt_ops+PARAVIRT_read_cr0; \
+ call *pv_cpu_ops+PV_CPU_read_cr0; \
pop %edx; pop %ecx
#endif /* __ASSEMBLY__ */
diff --git a/include/asm-x86/parport.h b/include/asm-x86/parport.h
index 2a31157349c9..019cbca24a38 100644
--- a/include/asm-x86/parport.h
+++ b/include/asm-x86/parport.h
@@ -1,5 +1,10 @@
-#ifdef CONFIG_X86_32
-# include "parport_32.h"
-#else
-# include "parport_64.h"
-#endif
+#ifndef _ASM_X86_PARPORT_H
+#define _ASM_X86_PARPORT_H
+
+static int __devinit parport_pc_find_isa_ports (int autoirq, int autodma);
+static int __devinit parport_pc_find_nonpci_ports (int autoirq, int autodma)
+{
+ return parport_pc_find_isa_ports (autoirq, autodma);
+}
+
+#endif /* _ASM_X86_PARPORT_H */
diff --git a/include/asm-x86/parport_32.h b/include/asm-x86/parport_32.h
deleted file mode 100644
index fa0e321e498e..000000000000
--- a/include/asm-x86/parport_32.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * parport.h: ia32-specific parport initialisation
- *
- * Copyright (C) 1999, 2000 Tim Waugh <tim@cyberelk.demon.co.uk>
- *
- * This file should only be included by drivers/parport/parport_pc.c.
- */
-
-#ifndef _ASM_I386_PARPORT_H
-#define _ASM_I386_PARPORT_H 1
-
-static int __devinit parport_pc_find_isa_ports (int autoirq, int autodma);
-static int __devinit parport_pc_find_nonpci_ports (int autoirq, int autodma)
-{
- return parport_pc_find_isa_ports (autoirq, autodma);
-}
-
-#endif /* !(_ASM_I386_PARPORT_H) */
diff --git a/include/asm-x86/parport_64.h b/include/asm-x86/parport_64.h
deleted file mode 100644
index 7135ef977c96..000000000000
--- a/include/asm-x86/parport_64.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * parport.h: ia32-specific parport initialisation
- *
- * Copyright (C) 1999, 2000 Tim Waugh <tim@cyberelk.demon.co.uk>
- *
- * This file should only be included by drivers/parport/parport_pc.c.
- */
-
-#ifndef _ASM_X8664_PARPORT_H
-#define _ASM_X8664_PARPORT_H 1
-
-static int __devinit parport_pc_find_isa_ports (int autoirq, int autodma);
-static int __devinit parport_pc_find_nonpci_ports (int autoirq, int autodma)
-{
- return parport_pc_find_isa_ports (autoirq, autodma);
-}
-
-#endif
diff --git a/include/asm-x86/pci_64.h b/include/asm-x86/pci_64.h
index 9baa46d9f594..ef54226a9325 100644
--- a/include/asm-x86/pci_64.h
+++ b/include/asm-x86/pci_64.h
@@ -37,7 +37,7 @@ extern int iommu_setup(char *opt);
*/
#define PCI_DMA_BUS_IS_PHYS (dma_ops->is_phys)
-#if defined(CONFIG_IOMMU) || defined(CONFIG_CALGARY_IOMMU)
+#if defined(CONFIG_GART_IOMMU) || defined(CONFIG_CALGARY_IOMMU)
#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \
dma_addr_t ADDR_NAME;
diff --git a/include/asm-x86/pda.h b/include/asm-x86/pda.h
index fb49f80eb94f..35962bbe5e72 100644
--- a/include/asm-x86/pda.h
+++ b/include/asm-x86/pda.h
@@ -30,6 +30,12 @@ struct x8664_pda {
struct mm_struct *active_mm;
unsigned apic_timer_irqs;
unsigned irq0_irqs;
+ unsigned irq_resched_count;
+ unsigned irq_call_count;
+ unsigned irq_tlb_count;
+ unsigned irq_thermal_count;
+ unsigned irq_threshold_count;
+ unsigned irq_spurious_count;
} ____cacheline_aligned_in_smp;
extern struct x8664_pda *_cpu_pda[];
diff --git a/include/asm-x86/pgtable-3level-defs.h b/include/asm-x86/pgtable-3level-defs.h
index c0df89f66e8b..448ac9516314 100644
--- a/include/asm-x86/pgtable-3level-defs.h
+++ b/include/asm-x86/pgtable-3level-defs.h
@@ -2,7 +2,7 @@
#define _I386_PGTABLE_3LEVEL_DEFS_H
#ifdef CONFIG_PARAVIRT
-#define SHARED_KERNEL_PMD (paravirt_ops.shared_kernel_pmd)
+#define SHARED_KERNEL_PMD (pv_info.shared_kernel_pmd)
#else
#define SHARED_KERNEL_PMD 1
#endif
diff --git a/include/asm-x86/pgtable_32.h b/include/asm-x86/pgtable_32.h
index c7fefa6b12fd..ed3e70d8d04b 100644
--- a/include/asm-x86/pgtable_32.h
+++ b/include/asm-x86/pgtable_32.h
@@ -17,10 +17,7 @@
#include <linux/threads.h>
#include <asm/paravirt.h>
-#ifndef _I386_BITOPS_H
-#include <asm/bitops.h>
-#endif
-
+#include <linux/bitops.h>
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/spinlock.h>
@@ -40,7 +37,7 @@ extern spinlock_t pgd_lock;
extern struct page *pgd_list;
void check_pgt_cache(void);
-void pmd_ctor(void *, struct kmem_cache *, unsigned long);
+void pmd_ctor(struct kmem_cache *, void *);
void pgtable_cache_init(void);
void paging_init(void);
diff --git a/include/asm-x86/pgtable_64.h b/include/asm-x86/pgtable_64.h
index 57dd6b3107ea..9b0ff477b39e 100644
--- a/include/asm-x86/pgtable_64.h
+++ b/include/asm-x86/pgtable_64.h
@@ -9,7 +9,7 @@
* the x86-64 page table tree.
*/
#include <asm/processor.h>
-#include <asm/bitops.h>
+#include <linux/bitops.h>
#include <linux/threads.h>
#include <asm/pda.h>
@@ -137,6 +137,7 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long
#define MAXMEM _AC(0x3fffffffffff, UL)
#define VMALLOC_START _AC(0xffffc20000000000, UL)
#define VMALLOC_END _AC(0xffffe1ffffffffff, UL)
+#define VMEMMAP_START _AC(0xffffe20000000000, UL)
#define MODULES_VADDR _AC(0xffffffff88000000, UL)
#define MODULES_END _AC(0xfffffffffff00000, UL)
#define MODULES_LEN (MODULES_END - MODULES_VADDR)
diff --git a/include/asm-x86/processor_32.h b/include/asm-x86/processor_32.h
index 3845fe72383e..13976b086837 100644
--- a/include/asm-x86/processor_32.h
+++ b/include/asm-x86/processor_32.h
@@ -79,6 +79,7 @@ struct cpuinfo_x86 {
unsigned char booted_cores; /* number of cores as seen by OS */
__u8 phys_proc_id; /* Physical processor id. */
__u8 cpu_core_id; /* Core id */
+ __u8 cpu_index; /* index into per_cpu list */
#endif
} __attribute__((__aligned__(SMP_CACHE_BYTES)));
@@ -103,14 +104,19 @@ extern struct tss_struct doublefault_tss;
DECLARE_PER_CPU(struct tss_struct, init_tss);
#ifdef CONFIG_SMP
-extern struct cpuinfo_x86 cpu_data[];
-#define current_cpu_data cpu_data[smp_processor_id()]
+DECLARE_PER_CPU(struct cpuinfo_x86, cpu_info);
+#define cpu_data(cpu) per_cpu(cpu_info, cpu)
+#define current_cpu_data cpu_data(smp_processor_id())
#else
-#define cpu_data (&boot_cpu_data)
-#define current_cpu_data boot_cpu_data
+#define cpu_data(cpu) boot_cpu_data
+#define current_cpu_data boot_cpu_data
#endif
-extern int cpu_llc_id[NR_CPUS];
+/*
+ * the following now lives in the per cpu area:
+ * extern int cpu_llc_id[NR_CPUS];
+ */
+DECLARE_PER_CPU(u8, cpu_llc_id);
extern char ignore_fpu_irq;
void __init cpu_detect(struct cpuinfo_x86 *c);
@@ -595,7 +601,9 @@ static inline void load_esp0(struct tss_struct *tss, struct thread_struct *threa
* clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx
* resulting in stale register contents being returned.
*/
-static inline void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx)
+static inline void cpuid(unsigned int op,
+ unsigned int *eax, unsigned int *ebx,
+ unsigned int *ecx, unsigned int *edx)
{
*eax = op;
*ecx = 0;
@@ -603,8 +611,9 @@ static inline void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx,
}
/* Some CPUID calls want 'count' to be placed in ecx */
-static inline void cpuid_count(int op, int count, int *eax, int *ebx, int *ecx,
- int *edx)
+static inline void cpuid_count(unsigned int op, int count,
+ unsigned int *eax, unsigned int *ebx,
+ unsigned int *ecx, unsigned int *edx)
{
*eax = op;
*ecx = count;
@@ -674,6 +683,17 @@ static inline unsigned int cpuid_edx(unsigned int op)
#define K7_NOP7 ".byte 0x8D,0x04,0x05,0,0,0,0\n"
#define K7_NOP8 K7_NOP7 ASM_NOP1
+/* P6 nops */
+/* uses eax dependencies (Intel-recommended choice) */
+#define P6_NOP1 GENERIC_NOP1
+#define P6_NOP2 ".byte 0x66,0x90\n"
+#define P6_NOP3 ".byte 0x0f,0x1f,0x00\n"
+#define P6_NOP4 ".byte 0x0f,0x1f,0x40,0\n"
+#define P6_NOP5 ".byte 0x0f,0x1f,0x44,0x00,0\n"
+#define P6_NOP6 ".byte 0x66,0x0f,0x1f,0x44,0x00,0\n"
+#define P6_NOP7 ".byte 0x0f,0x1f,0x80,0,0,0,0\n"
+#define P6_NOP8 ".byte 0x0f,0x1f,0x84,0x00,0,0,0,0\n"
+
#ifdef CONFIG_MK8
#define ASM_NOP1 K8_NOP1
#define ASM_NOP2 K8_NOP2
@@ -692,6 +712,17 @@ static inline unsigned int cpuid_edx(unsigned int op)
#define ASM_NOP6 K7_NOP6
#define ASM_NOP7 K7_NOP7
#define ASM_NOP8 K7_NOP8
+#elif defined(CONFIG_M686) || defined(CONFIG_MPENTIUMII) || \
+ defined(CONFIG_MPENTIUMIII) || defined(CONFIG_MPENTIUMM) || \
+ defined(CONFIG_MCORE2) || defined(CONFIG_PENTIUM4)
+#define ASM_NOP1 P6_NOP1
+#define ASM_NOP2 P6_NOP2
+#define ASM_NOP3 P6_NOP3
+#define ASM_NOP4 P6_NOP4
+#define ASM_NOP5 P6_NOP5
+#define ASM_NOP6 P6_NOP6
+#define ASM_NOP7 P6_NOP7
+#define ASM_NOP8 P6_NOP8
#else
#define ASM_NOP1 GENERIC_NOP1
#define ASM_NOP2 GENERIC_NOP2
diff --git a/include/asm-x86/processor_64.h b/include/asm-x86/processor_64.h
index 31f579b828f2..e4f19970a82b 100644
--- a/include/asm-x86/processor_64.h
+++ b/include/asm-x86/processor_64.h
@@ -74,6 +74,7 @@ struct cpuinfo_x86 {
__u8 booted_cores; /* number of cores as seen by OS */
__u8 phys_proc_id; /* Physical Processor id. */
__u8 cpu_core_id; /* Core id. */
+ __u8 cpu_index; /* index into per_cpu list */
#endif
} ____cacheline_aligned;
@@ -88,11 +89,12 @@ struct cpuinfo_x86 {
#define X86_VENDOR_UNKNOWN 0xff
#ifdef CONFIG_SMP
-extern struct cpuinfo_x86 cpu_data[];
-#define current_cpu_data cpu_data[smp_processor_id()]
+DECLARE_PER_CPU(struct cpuinfo_x86, cpu_info);
+#define cpu_data(cpu) per_cpu(cpu_info, cpu)
+#define current_cpu_data cpu_data(smp_processor_id())
#else
-#define cpu_data (&boot_cpu_data)
-#define current_cpu_data boot_cpu_data
+#define cpu_data(cpu) boot_cpu_data
+#define current_cpu_data boot_cpu_data
#endif
extern char ignore_irq13;
@@ -334,6 +336,16 @@ struct extended_sigtable {
};
+#if defined(CONFIG_MPSC) || defined(CONFIG_MCORE2)
+#define ASM_NOP1 P6_NOP1
+#define ASM_NOP2 P6_NOP2
+#define ASM_NOP3 P6_NOP3
+#define ASM_NOP4 P6_NOP4
+#define ASM_NOP5 P6_NOP5
+#define ASM_NOP6 P6_NOP6
+#define ASM_NOP7 P6_NOP7
+#define ASM_NOP8 P6_NOP8
+#else
#define ASM_NOP1 K8_NOP1
#define ASM_NOP2 K8_NOP2
#define ASM_NOP3 K8_NOP3
@@ -342,6 +354,7 @@ struct extended_sigtable {
#define ASM_NOP6 K8_NOP6
#define ASM_NOP7 K8_NOP7
#define ASM_NOP8 K8_NOP8
+#endif
/* Opteron nops */
#define K8_NOP1 ".byte 0x90\n"
@@ -353,6 +366,17 @@ struct extended_sigtable {
#define K8_NOP7 K8_NOP4 K8_NOP3
#define K8_NOP8 K8_NOP4 K8_NOP4
+/* P6 nops */
+/* uses eax dependencies (Intel-recommended choice) */
+#define P6_NOP1 ".byte 0x90\n"
+#define P6_NOP2 ".byte 0x66,0x90\n"
+#define P6_NOP3 ".byte 0x0f,0x1f,0x00\n"
+#define P6_NOP4 ".byte 0x0f,0x1f,0x40,0\n"
+#define P6_NOP5 ".byte 0x0f,0x1f,0x44,0x00,0\n"
+#define P6_NOP6 ".byte 0x66,0x0f,0x1f,0x44,0x00,0\n"
+#define P6_NOP7 ".byte 0x0f,0x1f,0x80,0,0,0,0\n"
+#define P6_NOP8 ".byte 0x0f,0x1f,0x84,0x00,0,0,0,0\n"
+
#define ASM_NOP_MAX 8
/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
@@ -368,12 +392,6 @@ static inline void sync_core(void)
asm volatile("cpuid" : "=a" (tmp) : "0" (1) : "ebx","ecx","edx","memory");
}
-#define ARCH_HAS_PREFETCH
-static inline void prefetch(void *x)
-{
- asm volatile("prefetcht0 (%0)" :: "r" (x));
-}
-
#define ARCH_HAS_PREFETCHW 1
static inline void prefetchw(void *x)
{
@@ -389,11 +407,6 @@ static inline void prefetchw(void *x)
#define cpu_relax() rep_nop()
-static inline void serialize_cpu(void)
-{
- __asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx");
-}
-
static inline void __monitor(const void *eax, unsigned long ecx,
unsigned long edx)
{
diff --git a/include/asm-x86/proto.h b/include/asm-x86/proto.h
index c44a3a93b5a4..dabba55f7ed8 100644
--- a/include/asm-x86/proto.h
+++ b/include/asm-x86/proto.h
@@ -83,8 +83,6 @@ extern unsigned tsc_khz;
extern int reboot_force;
extern int notsc_setup(char *);
-extern int timer_over_8254;
-
extern int gsi_irq_sharing(int gsi);
extern int force_mwait;
diff --git a/include/asm-x86/ptrace-abi.h b/include/asm-x86/ptrace-abi.h
index 6824c49def1c..7524e1233833 100644
--- a/include/asm-x86/ptrace-abi.h
+++ b/include/asm-x86/ptrace-abi.h
@@ -1,13 +1,81 @@
-#ifdef __KERNEL__
-# ifdef CONFIG_X86_32
-# include "ptrace-abi_32.h"
-# else
-# include "ptrace-abi_64.h"
-# endif
+#ifndef _ASM_X86_PTRACE_ABI_H
+#define _ASM_X86_PTRACE_ABI_H
+
+#ifdef __i386__
+
+#define EBX 0
+#define ECX 1
+#define EDX 2
+#define ESI 3
+#define EDI 4
+#define EBP 5
+#define EAX 6
+#define DS 7
+#define ES 8
+#define FS 9
+#define GS 10
+#define ORIG_EAX 11
+#define EIP 12
+#define CS 13
+#define EFL 14
+#define UESP 15
+#define SS 16
+#define FRAME_SIZE 17
+
+#else /* __i386__ */
+
+#if defined(__ASSEMBLY__) || defined(__FRAME_OFFSETS)
+#define R15 0
+#define R14 8
+#define R13 16
+#define R12 24
+#define RBP 32
+#define RBX 40
+/* arguments: interrupts/non tracing syscalls only save upto here*/
+#define R11 48
+#define R10 56
+#define R9 64
+#define R8 72
+#define RAX 80
+#define RCX 88
+#define RDX 96
+#define RSI 104
+#define RDI 112
+#define ORIG_RAX 120 /* = ERROR */
+/* end of arguments */
+/* cpu exception frame or undefined in case of fast syscall. */
+#define RIP 128
+#define CS 136
+#define EFLAGS 144
+#define RSP 152
+#define SS 160
+#define ARGOFFSET R11
+#endif /* __ASSEMBLY__ */
+
+/* top of stack page */
+#define FRAME_SIZE 168
+
+#endif /* !__i386__ */
+
+/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
+#define PTRACE_GETREGS 12
+#define PTRACE_SETREGS 13
+#define PTRACE_GETFPREGS 14
+#define PTRACE_SETFPREGS 15
+#define PTRACE_GETFPXREGS 18
+#define PTRACE_SETFPXREGS 19
+
+#define PTRACE_OLDSETOPTIONS 21
+
+/* only useful for access 32bit programs / kernels */
+#define PTRACE_GET_THREAD_AREA 25
+#define PTRACE_SET_THREAD_AREA 26
+
+#ifdef __x86_64__
+# define PTRACE_ARCH_PRCTL 30
#else
-# ifdef __i386__
-# include "ptrace-abi_32.h"
-# else
-# include "ptrace-abi_64.h"
-# endif
+# define PTRACE_SYSEMU 31
+# define PTRACE_SYSEMU_SINGLESTEP 32
+#endif
+
#endif
diff --git a/include/asm-x86/ptrace-abi_32.h b/include/asm-x86/ptrace-abi_32.h
deleted file mode 100644
index a44901817a26..000000000000
--- a/include/asm-x86/ptrace-abi_32.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef I386_PTRACE_ABI_H
-#define I386_PTRACE_ABI_H
-
-#define EBX 0
-#define ECX 1
-#define EDX 2
-#define ESI 3
-#define EDI 4
-#define EBP 5
-#define EAX 6
-#define DS 7
-#define ES 8
-#define FS 9
-#define GS 10
-#define ORIG_EAX 11
-#define EIP 12
-#define CS 13
-#define EFL 14
-#define UESP 15
-#define SS 16
-#define FRAME_SIZE 17
-
-/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
-#define PTRACE_GETREGS 12
-#define PTRACE_SETREGS 13
-#define PTRACE_GETFPREGS 14
-#define PTRACE_SETFPREGS 15
-#define PTRACE_GETFPXREGS 18
-#define PTRACE_SETFPXREGS 19
-
-#define PTRACE_OLDSETOPTIONS 21
-
-#define PTRACE_GET_THREAD_AREA 25
-#define PTRACE_SET_THREAD_AREA 26
-
-#define PTRACE_SYSEMU 31
-#define PTRACE_SYSEMU_SINGLESTEP 32
-
-#endif
diff --git a/include/asm-x86/ptrace-abi_64.h b/include/asm-x86/ptrace-abi_64.h
deleted file mode 100644
index 19184b0806b1..000000000000
--- a/include/asm-x86/ptrace-abi_64.h
+++ /dev/null
@@ -1,51 +0,0 @@
-#ifndef _X86_64_PTRACE_ABI_H
-#define _X86_64_PTRACE_ABI_H
-
-#if defined(__ASSEMBLY__) || defined(__FRAME_OFFSETS)
-#define R15 0
-#define R14 8
-#define R13 16
-#define R12 24
-#define RBP 32
-#define RBX 40
-/* arguments: interrupts/non tracing syscalls only save upto here*/
-#define R11 48
-#define R10 56
-#define R9 64
-#define R8 72
-#define RAX 80
-#define RCX 88
-#define RDX 96
-#define RSI 104
-#define RDI 112
-#define ORIG_RAX 120 /* = ERROR */
-/* end of arguments */
-/* cpu exception frame or undefined in case of fast syscall. */
-#define RIP 128
-#define CS 136
-#define EFLAGS 144
-#define RSP 152
-#define SS 160
-#define ARGOFFSET R11
-#endif /* __ASSEMBLY__ */
-
-/* top of stack page */
-#define FRAME_SIZE 168
-
-#define PTRACE_OLDSETOPTIONS 21
-
-/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
-#define PTRACE_GETREGS 12
-#define PTRACE_SETREGS 13
-#define PTRACE_GETFPREGS 14
-#define PTRACE_SETFPREGS 15
-#define PTRACE_GETFPXREGS 18
-#define PTRACE_SETFPXREGS 19
-
-/* only useful for access 32bit programs */
-#define PTRACE_GET_THREAD_AREA 25
-#define PTRACE_SET_THREAD_AREA 26
-
-#define PTRACE_ARCH_PRCTL 30 /* arch_prctl for child */
-
-#endif
diff --git a/include/asm-x86/ptrace.h b/include/asm-x86/ptrace.h
index bc4d64a87689..51ddb2590870 100644
--- a/include/asm-x86/ptrace.h
+++ b/include/asm-x86/ptrace.h
@@ -1,13 +1,142 @@
+#ifndef _ASM_X86_PTRACE_H
+#define _ASM_X86_PTRACE_H
+
+#include <linux/compiler.h> /* For __user */
+#include <asm/ptrace-abi.h>
+
+#ifndef __ASSEMBLY__
+
+#ifdef __i386__
+/* this struct defines the way the registers are stored on the
+ stack during a system call. */
+
+struct pt_regs {
+ long ebx;
+ long ecx;
+ long edx;
+ long esi;
+ long edi;
+ long ebp;
+ long eax;
+ int xds;
+ int xes;
+ int xfs;
+ /* int xgs; */
+ long orig_eax;
+ long eip;
+ int xcs;
+ long eflags;
+ long esp;
+ int xss;
+};
+
#ifdef __KERNEL__
-# ifdef CONFIG_X86_32
-# include "ptrace_32.h"
-# else
-# include "ptrace_64.h"
-# endif
-#else
-# ifdef __i386__
-# include "ptrace_32.h"
-# else
-# include "ptrace_64.h"
-# endif
+
+#include <asm/vm86.h>
+#include <asm/segment.h>
+
+struct task_struct;
+extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code);
+
+/*
+ * user_mode_vm(regs) determines whether a register set came from user mode.
+ * This is true if V8086 mode was enabled OR if the register set was from
+ * protected mode with RPL-3 CS value. This tricky test checks that with
+ * one comparison. Many places in the kernel can bypass this full check
+ * if they have already ruled out V8086 mode, so user_mode(regs) can be used.
+ */
+static inline int user_mode(struct pt_regs *regs)
+{
+ return (regs->xcs & SEGMENT_RPL_MASK) == USER_RPL;
+}
+static inline int user_mode_vm(struct pt_regs *regs)
+{
+ return ((regs->xcs & SEGMENT_RPL_MASK) | (regs->eflags & VM_MASK)) >= USER_RPL;
+}
+static inline int v8086_mode(struct pt_regs *regs)
+{
+ return (regs->eflags & VM_MASK);
+}
+
+#define instruction_pointer(regs) ((regs)->eip)
+#define frame_pointer(regs) ((regs)->ebp)
+#define stack_pointer(regs) ((unsigned long)(regs))
+#define regs_return_value(regs) ((regs)->eax)
+
+extern unsigned long profile_pc(struct pt_regs *regs);
+#endif /* __KERNEL__ */
+
+#else /* __i386__ */
+
+struct pt_regs {
+ unsigned long r15;
+ unsigned long r14;
+ unsigned long r13;
+ unsigned long r12;
+ unsigned long rbp;
+ unsigned long rbx;
+/* arguments: non interrupts/non tracing syscalls only save upto here*/
+ unsigned long r11;
+ unsigned long r10;
+ unsigned long r9;
+ unsigned long r8;
+ unsigned long rax;
+ unsigned long rcx;
+ unsigned long rdx;
+ unsigned long rsi;
+ unsigned long rdi;
+ unsigned long orig_rax;
+/* end of arguments */
+/* cpu exception frame or undefined */
+ unsigned long rip;
+ unsigned long cs;
+ unsigned long eflags;
+ unsigned long rsp;
+ unsigned long ss;
+/* top of stack page */
+};
+
+#ifdef __KERNEL__
+
+#define user_mode(regs) (!!((regs)->cs & 3))
+#define user_mode_vm(regs) user_mode(regs)
+#define instruction_pointer(regs) ((regs)->rip)
+#define frame_pointer(regs) ((regs)->rbp)
+#define stack_pointer(regs) ((regs)->rsp)
+#define regs_return_value(regs) ((regs)->rax)
+
+extern unsigned long profile_pc(struct pt_regs *regs);
+void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
+
+struct task_struct;
+
+extern unsigned long
+convert_rip_to_linear(struct task_struct *child, struct pt_regs *regs);
+
+enum {
+ EF_CF = 0x00000001,
+ EF_PF = 0x00000004,
+ EF_AF = 0x00000010,
+ EF_ZF = 0x00000040,
+ EF_SF = 0x00000080,
+ EF_TF = 0x00000100,
+ EF_IE = 0x00000200,
+ EF_DF = 0x00000400,
+ EF_OF = 0x00000800,
+ EF_IOPL = 0x00003000,
+ EF_IOPL_RING0 = 0x00000000,
+ EF_IOPL_RING1 = 0x00001000,
+ EF_IOPL_RING2 = 0x00002000,
+ EF_NT = 0x00004000, /* nested task */
+ EF_RF = 0x00010000, /* resume */
+ EF_VM = 0x00020000, /* virtual mode */
+ EF_AC = 0x00040000, /* alignment */
+ EF_VIF = 0x00080000, /* virtual interrupt */
+ EF_VIP = 0x00100000, /* virtual interrupt pending */
+ EF_ID = 0x00200000, /* id */
+};
+#endif /* __KERNEL__ */
+#endif /* !__i386__ */
+#endif /* !__ASSEMBLY__ */
+
#endif
diff --git a/include/asm-x86/ptrace_32.h b/include/asm-x86/ptrace_32.h
deleted file mode 100644
index 6002597b9e12..000000000000
--- a/include/asm-x86/ptrace_32.h
+++ /dev/null
@@ -1,63 +0,0 @@
-#ifndef _I386_PTRACE_H
-#define _I386_PTRACE_H
-
-#include <asm/ptrace-abi.h>
-
-/* this struct defines the way the registers are stored on the
- stack during a system call. */
-
-struct pt_regs {
- long ebx;
- long ecx;
- long edx;
- long esi;
- long edi;
- long ebp;
- long eax;
- int xds;
- int xes;
- int xfs;
- /* int xgs; */
- long orig_eax;
- long eip;
- int xcs;
- long eflags;
- long esp;
- int xss;
-};
-
-#ifdef __KERNEL__
-
-#include <asm/vm86.h>
-#include <asm/segment.h>
-
-struct task_struct;
-extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code);
-
-/*
- * user_mode_vm(regs) determines whether a register set came from user mode.
- * This is true if V8086 mode was enabled OR if the register set was from
- * protected mode with RPL-3 CS value. This tricky test checks that with
- * one comparison. Many places in the kernel can bypass this full check
- * if they have already ruled out V8086 mode, so user_mode(regs) can be used.
- */
-static inline int user_mode(struct pt_regs *regs)
-{
- return (regs->xcs & SEGMENT_RPL_MASK) == USER_RPL;
-}
-static inline int user_mode_vm(struct pt_regs *regs)
-{
- return ((regs->xcs & SEGMENT_RPL_MASK) | (regs->eflags & VM_MASK)) >= USER_RPL;
-}
-static inline int v8086_mode(struct pt_regs *regs)
-{
- return (regs->eflags & VM_MASK);
-}
-
-#define instruction_pointer(regs) ((regs)->eip)
-#define regs_return_value(regs) ((regs)->eax)
-
-extern unsigned long profile_pc(struct pt_regs *regs);
-#endif /* __KERNEL__ */
-
-#endif
diff --git a/include/asm-x86/ptrace_64.h b/include/asm-x86/ptrace_64.h
deleted file mode 100644
index 7f166ccb0606..000000000000
--- a/include/asm-x86/ptrace_64.h
+++ /dev/null
@@ -1,78 +0,0 @@
-#ifndef _X86_64_PTRACE_H
-#define _X86_64_PTRACE_H
-
-#include <linux/compiler.h> /* For __user */
-#include <asm/ptrace-abi.h>
-
-#ifndef __ASSEMBLY__
-
-struct pt_regs {
- unsigned long r15;
- unsigned long r14;
- unsigned long r13;
- unsigned long r12;
- unsigned long rbp;
- unsigned long rbx;
-/* arguments: non interrupts/non tracing syscalls only save upto here*/
- unsigned long r11;
- unsigned long r10;
- unsigned long r9;
- unsigned long r8;
- unsigned long rax;
- unsigned long rcx;
- unsigned long rdx;
- unsigned long rsi;
- unsigned long rdi;
- unsigned long orig_rax;
-/* end of arguments */
-/* cpu exception frame or undefined */
- unsigned long rip;
- unsigned long cs;
- unsigned long eflags;
- unsigned long rsp;
- unsigned long ss;
-/* top of stack page */
-};
-
-#endif
-
-#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
-#define user_mode(regs) (!!((regs)->cs & 3))
-#define user_mode_vm(regs) user_mode(regs)
-#define instruction_pointer(regs) ((regs)->rip)
-#define regs_return_value(regs) ((regs)->rax)
-
-extern unsigned long profile_pc(struct pt_regs *regs);
-void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
-
-struct task_struct;
-
-extern unsigned long
-convert_rip_to_linear(struct task_struct *child, struct pt_regs *regs);
-
-enum {
- EF_CF = 0x00000001,
- EF_PF = 0x00000004,
- EF_AF = 0x00000010,
- EF_ZF = 0x00000040,
- EF_SF = 0x00000080,
- EF_TF = 0x00000100,
- EF_IE = 0x00000200,
- EF_DF = 0x00000400,
- EF_OF = 0x00000800,
- EF_IOPL = 0x00003000,
- EF_IOPL_RING0 = 0x00000000,
- EF_IOPL_RING1 = 0x00001000,
- EF_IOPL_RING2 = 0x00002000,
- EF_NT = 0x00004000, /* nested task */
- EF_RF = 0x00010000, /* resume */
- EF_VM = 0x00020000, /* virtual mode */
- EF_AC = 0x00040000, /* alignment */
- EF_VIF = 0x00080000, /* virtual interrupt */
- EF_VIP = 0x00100000, /* virtual interrupt pending */
- EF_ID = 0x00200000, /* id */
-};
-
-#endif
-
-#endif
diff --git a/include/asm-x86/required-features.h b/include/asm-x86/required-features.h
index 8b64f3ea2b78..7400d3ad75c6 100644
--- a/include/asm-x86/required-features.h
+++ b/include/asm-x86/required-features.h
@@ -1,5 +1,72 @@
-#ifdef CONFIG_X86_32
-# include "required-features_32.h"
+#ifndef _ASM_REQUIRED_FEATURES_H
+#define _ASM_REQUIRED_FEATURES_H 1
+
+/* Define minimum CPUID feature set for kernel These bits are checked
+ really early to actually display a visible error message before the
+ kernel dies. Make sure to assign features to the proper mask!
+
+ Some requirements that are not in CPUID yet are also in the
+ CONFIG_X86_MINIMUM_CPU_FAMILY which is checked too.
+
+ The real information is in arch/x86/Kconfig.cpu, this just converts
+ the CONFIGs into a bitmask */
+
+#ifndef CONFIG_MATH_EMULATION
+# define NEED_FPU (1<<(X86_FEATURE_FPU & 31))
#else
-# include "required-features_64.h"
+# define NEED_FPU 0
+#endif
+
+#if defined(CONFIG_X86_PAE) || defined(CONFIG_X86_64)
+# define NEED_PAE (1<<(X86_FEATURE_PAE & 31))
+# define NEED_CX8 (1<<(X86_FEATURE_CX8 & 31))
+#else
+# define NEED_PAE 0
+# define NEED_CX8 0
+#endif
+
+#if defined(CONFIG_X86_CMOV) || defined(CONFIG_X86_64)
+# define NEED_CMOV (1<<(X86_FEATURE_CMOV & 31))
+#else
+# define NEED_CMOV 0
+#endif
+
+#ifdef CONFIG_X86_USE_3DNOW
+# define NEED_3DNOW (1<<(X86_FEATURE_3DNOW & 31))
+#else
+# define NEED_3DNOW 0
+#endif
+
+#ifdef CONFIG_X86_64
+#define NEED_PSE (1<<(X86_FEATURE_PSE & 31))
+#define NEED_MSR (1<<(X86_FEATURE_MSR & 31))
+#define NEED_PGE (1<<(X86_FEATURE_PGE & 31))
+#define NEED_FXSR (1<<(X86_FEATURE_FXSR & 31))
+#define NEED_XMM (1<<(X86_FEATURE_XMM & 31))
+#define NEED_XMM2 (1<<(X86_FEATURE_XMM2 & 31))
+#define NEED_LM (1<<(X86_FEATURE_LM & 31))
+#else
+#define NEED_PSE 0
+#define NEED_MSR 0
+#define NEED_PGE 0
+#define NEED_FXSR 0
+#define NEED_XMM 0
+#define NEED_XMM2 0
+#define NEED_LM 0
+#endif
+
+#define REQUIRED_MASK0 (NEED_FPU|NEED_PSE|NEED_MSR|NEED_PAE|\
+ NEED_CX8|NEED_PGE|NEED_FXSR|NEED_CMOV|\
+ NEED_XMM|NEED_XMM2)
+#define SSE_MASK (NEED_XMM|NEED_XMM2)
+
+#define REQUIRED_MASK1 (NEED_LM|NEED_3DNOW)
+
+#define REQUIRED_MASK2 0
+#define REQUIRED_MASK3 0
+#define REQUIRED_MASK4 0
+#define REQUIRED_MASK5 0
+#define REQUIRED_MASK6 0
+#define REQUIRED_MASK7 0
+
#endif
diff --git a/include/asm-x86/required-features_32.h b/include/asm-x86/required-features_32.h
deleted file mode 100644
index 618feb98f9f5..000000000000
--- a/include/asm-x86/required-features_32.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef _ASM_REQUIRED_FEATURES_H
-#define _ASM_REQUIRED_FEATURES_H 1
-
-/* Define minimum CPUID feature set for kernel These bits are checked
- really early to actually display a visible error message before the
- kernel dies. Make sure to assign features to the proper mask!
-
- Some requirements that are not in CPUID yet are also in the
- CONFIG_X86_MINIMUM_CPU_FAMILY which is checked too.
-
- The real information is in arch/i386/Kconfig.cpu, this just converts
- the CONFIGs into a bitmask */
-
-#ifndef CONFIG_MATH_EMULATION
-# define NEED_FPU (1<<(X86_FEATURE_FPU & 31))
-#else
-# define NEED_FPU 0
-#endif
-
-#ifdef CONFIG_X86_PAE
-# define NEED_PAE (1<<(X86_FEATURE_PAE & 31))
-#else
-# define NEED_PAE 0
-#endif
-
-#ifdef CONFIG_X86_CMOV
-# define NEED_CMOV (1<<(X86_FEATURE_CMOV & 31))
-#else
-# define NEED_CMOV 0
-#endif
-
-#ifdef CONFIG_X86_PAE
-# define NEED_CX8 (1<<(X86_FEATURE_CX8 & 31))
-#else
-# define NEED_CX8 0
-#endif
-
-#define REQUIRED_MASK0 (NEED_FPU|NEED_PAE|NEED_CMOV|NEED_CX8)
-
-#ifdef CONFIG_X86_USE_3DNOW
-# define NEED_3DNOW (1<<(X86_FEATURE_3DNOW & 31))
-#else
-# define NEED_3DNOW 0
-#endif
-
-#define REQUIRED_MASK1 (NEED_3DNOW)
-
-#define REQUIRED_MASK2 0
-#define REQUIRED_MASK3 0
-#define REQUIRED_MASK4 0
-#define REQUIRED_MASK5 0
-#define REQUIRED_MASK6 0
-#define REQUIRED_MASK7 0
-
-#endif
diff --git a/include/asm-x86/required-features_64.h b/include/asm-x86/required-features_64.h
deleted file mode 100644
index e80d5761b00a..000000000000
--- a/include/asm-x86/required-features_64.h
+++ /dev/null
@@ -1,46 +0,0 @@
-#ifndef _ASM_REQUIRED_FEATURES_H
-#define _ASM_REQUIRED_FEATURES_H 1
-
-/* Define minimum CPUID feature set for kernel These bits are checked
- really early to actually display a visible error message before the
- kernel dies. Make sure to assign features to the proper mask!
-
- The real information is in arch/x86_64/Kconfig.cpu, this just converts
- the CONFIGs into a bitmask */
-
-/* x86-64 baseline features */
-#define NEED_FPU (1<<(X86_FEATURE_FPU & 31))
-#define NEED_PSE (1<<(X86_FEATURE_PSE & 31))
-#define NEED_MSR (1<<(X86_FEATURE_MSR & 31))
-#define NEED_PAE (1<<(X86_FEATURE_PAE & 31))
-#define NEED_CX8 (1<<(X86_FEATURE_CX8 & 31))
-#define NEED_PGE (1<<(X86_FEATURE_PGE & 31))
-#define NEED_FXSR (1<<(X86_FEATURE_FXSR & 31))
-#define NEED_CMOV (1<<(X86_FEATURE_CMOV & 31))
-#define NEED_XMM (1<<(X86_FEATURE_XMM & 31))
-#define NEED_XMM2 (1<<(X86_FEATURE_XMM2 & 31))
-
-#define REQUIRED_MASK0 (NEED_FPU|NEED_PSE|NEED_MSR|NEED_PAE|\
- NEED_CX8|NEED_PGE|NEED_FXSR|NEED_CMOV|\
- NEED_XMM|NEED_XMM2)
-#define SSE_MASK (NEED_XMM|NEED_XMM2)
-
-/* x86-64 baseline features */
-#define NEED_LM (1<<(X86_FEATURE_LM & 31))
-
-#ifdef CONFIG_X86_USE_3DNOW
-# define NEED_3DNOW (1<<(X86_FEATURE_3DNOW & 31))
-#else
-# define NEED_3DNOW 0
-#endif
-
-#define REQUIRED_MASK1 (NEED_LM|NEED_3DNOW)
-
-#define REQUIRED_MASK2 0
-#define REQUIRED_MASK3 0
-#define REQUIRED_MASK4 0
-#define REQUIRED_MASK5 0
-#define REQUIRED_MASK6 0
-#define REQUIRED_MASK7 0
-
-#endif
diff --git a/include/asm-x86/resource.h b/include/asm-x86/resource.h
index 732410a8c02a..04bc4db8921b 100644
--- a/include/asm-x86/resource.h
+++ b/include/asm-x86/resource.h
@@ -1,13 +1 @@
-#ifdef __KERNEL__
-# ifdef CONFIG_X86_32
-# include "resource_32.h"
-# else
-# include "resource_64.h"
-# endif
-#else
-# ifdef __i386__
-# include "resource_32.h"
-# else
-# include "resource_64.h"
-# endif
-#endif
+#include <asm-generic/resource.h>
diff --git a/include/asm-x86/resource_32.h b/include/asm-x86/resource_32.h
deleted file mode 100644
index 6c1ea37c7718..000000000000
--- a/include/asm-x86/resource_32.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _I386_RESOURCE_H
-#define _I386_RESOURCE_H
-
-#include <asm-generic/resource.h>
-
-#endif
diff --git a/include/asm-x86/resource_64.h b/include/asm-x86/resource_64.h
deleted file mode 100644
index f40b40623234..000000000000
--- a/include/asm-x86/resource_64.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _X8664_RESOURCE_H
-#define _X8664_RESOURCE_H
-
-#include <asm-generic/resource.h>
-
-#endif
diff --git a/include/asm-x86/rtc.h b/include/asm-x86/rtc.h
index 1f0c98eb2e38..f71c3b0ed360 100644
--- a/include/asm-x86/rtc.h
+++ b/include/asm-x86/rtc.h
@@ -1,5 +1 @@
-#ifdef CONFIG_X86_32
-# include "rtc_32.h"
-#else
-# include "rtc_64.h"
-#endif
+#include <asm-generic/rtc.h>
diff --git a/include/asm-x86/rtc_32.h b/include/asm-x86/rtc_32.h
deleted file mode 100644
index ffd02109a0e5..000000000000
--- a/include/asm-x86/rtc_32.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef _I386_RTC_H
-#define _I386_RTC_H
-
-/*
- * x86 uses the default access methods for the RTC.
- */
-
-#include <asm-generic/rtc.h>
-
-#endif
diff --git a/include/asm-x86/rtc_64.h b/include/asm-x86/rtc_64.h
deleted file mode 100644
index 18ed713ac7de..000000000000
--- a/include/asm-x86/rtc_64.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef _X86_64_RTC_H
-#define _X86_64_RTC_H
-
-/*
- * x86 uses the default access methods for the RTC.
- */
-
-#include <asm-generic/rtc.h>
-
-#endif
diff --git a/include/asm-x86/rwlock.h b/include/asm-x86/rwlock.h
index a3be7d8364af..f2b64a429e6b 100644
--- a/include/asm-x86/rwlock.h
+++ b/include/asm-x86/rwlock.h
@@ -1,5 +1,9 @@
-#ifdef CONFIG_X86_32
-# include "rwlock_32.h"
-#else
-# include "rwlock_64.h"
-#endif
+#ifndef _ASM_X86_RWLOCK_H
+#define _ASM_X86_RWLOCK_H
+
+#define RW_LOCK_BIAS 0x01000000
+#define RW_LOCK_BIAS_STR "0x01000000"
+
+/* Actual code is in asm/spinlock.h or in arch/x86/lib/rwlock.S */
+
+#endif /* _ASM_X86_RWLOCK_H */
diff --git a/include/asm-x86/rwlock_32.h b/include/asm-x86/rwlock_32.h
deleted file mode 100644
index c3e5db32fa48..000000000000
--- a/include/asm-x86/rwlock_32.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* include/asm-i386/rwlock.h
- *
- * Helpers used by both rw spinlocks and rw semaphores.
- *
- * Based in part on code from semaphore.h and
- * spinlock.h Copyright 1996 Linus Torvalds.
- *
- * Copyright 1999 Red Hat, Inc.
- *
- * Written by Benjamin LaHaise.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-#ifndef _ASM_I386_RWLOCK_H
-#define _ASM_I386_RWLOCK_H
-
-#define RW_LOCK_BIAS 0x01000000
-#define RW_LOCK_BIAS_STR "0x01000000"
-
-/* Code is in asm-i386/spinlock.h */
-
-#endif
diff --git a/include/asm-x86/rwlock_64.h b/include/asm-x86/rwlock_64.h
deleted file mode 100644
index 72aeebed920b..000000000000
--- a/include/asm-x86/rwlock_64.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* include/asm-x86_64/rwlock.h
- *
- * Helpers used by both rw spinlocks and rw semaphores.
- *
- * Based in part on code from semaphore.h and
- * spinlock.h Copyright 1996 Linus Torvalds.
- *
- * Copyright 1999 Red Hat, Inc.
- * Copyright 2001,2002 SuSE labs
- *
- * Written by Benjamin LaHaise.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-#ifndef _ASM_X86_64_RWLOCK_H
-#define _ASM_X86_64_RWLOCK_H
-
-#define RW_LOCK_BIAS 0x01000000
-#define RW_LOCK_BIAS_STR "0x01000000"
-
-/* Actual code is in asm/spinlock.h or in arch/x86_64/lib/rwlock.S */
-
-#endif
diff --git a/include/asm-x86/scatterlist_32.h b/include/asm-x86/scatterlist_32.h
index d7e45a8f1aae..0e7d997a34be 100644
--- a/include/asm-x86/scatterlist_32.h
+++ b/include/asm-x86/scatterlist_32.h
@@ -4,12 +4,17 @@
#include <asm/types.h>
struct scatterlist {
- struct page *page;
+#ifdef CONFIG_DEBUG_SG
+ unsigned long sg_magic;
+#endif
+ unsigned long page_link;
unsigned int offset;
dma_addr_t dma_address;
unsigned int length;
};
+#define ARCH_HAS_SG_CHAIN
+
/* These macros should be used after a pci_map_sg call has been done
* to get bus addresses of each of the SG entries and their lengths.
* You should only work with the number of sg entries pci_map_sg
diff --git a/include/asm-x86/scatterlist_64.h b/include/asm-x86/scatterlist_64.h
index eaf7ada27e14..1847c72befeb 100644
--- a/include/asm-x86/scatterlist_64.h
+++ b/include/asm-x86/scatterlist_64.h
@@ -4,13 +4,18 @@
#include <asm/types.h>
struct scatterlist {
- struct page *page;
+#ifdef CONFIG_DEBUG_SG
+ unsigned long sg_magic;
+#endif
+ unsigned long page_link;
unsigned int offset;
unsigned int length;
dma_addr_t dma_address;
unsigned int dma_length;
};
+#define ARCH_HAS_SG_CHAIN
+
#define ISA_DMA_THRESHOLD (0x00ffffff)
/* These macros should be used after a pci_map_sg call has been done
diff --git a/include/asm-x86/sections.h b/include/asm-x86/sections.h
index ae6c69d9be3f..2b8c5160388f 100644
--- a/include/asm-x86/sections.h
+++ b/include/asm-x86/sections.h
@@ -1,5 +1 @@
-#ifdef CONFIG_X86_32
-# include "sections_32.h"
-#else
-# include "sections_64.h"
-#endif
+#include <asm-generic/sections.h>
diff --git a/include/asm-x86/sections_32.h b/include/asm-x86/sections_32.h
deleted file mode 100644
index 2dcbb92918b2..000000000000
--- a/include/asm-x86/sections_32.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _I386_SECTIONS_H
-#define _I386_SECTIONS_H
-
-/* nothing to see, move along */
-#include <asm-generic/sections.h>
-
-#endif
diff --git a/include/asm-x86/sections_64.h b/include/asm-x86/sections_64.h
deleted file mode 100644
index c746d9f1e70c..000000000000
--- a/include/asm-x86/sections_64.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _X8664_SECTIONS_H
-#define _X8664_SECTIONS_H
-
-/* nothing to see, move along */
-#include <asm-generic/sections.h>
-
-#endif
diff --git a/include/asm-x86/semaphore_32.h b/include/asm-x86/semaphore_32.h
index 4e34a468c383..835c1d751a9f 100644
--- a/include/asm-x86/semaphore_32.h
+++ b/include/asm-x86/semaphore_32.h
@@ -59,7 +59,6 @@ struct semaphore {
struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
-#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
static inline void sema_init (struct semaphore *sem, int val)
{
diff --git a/include/asm-x86/semaphore_64.h b/include/asm-x86/semaphore_64.h
index 1194888536b9..79694306bf7d 100644
--- a/include/asm-x86/semaphore_64.h
+++ b/include/asm-x86/semaphore_64.h
@@ -60,7 +60,6 @@ struct semaphore {
struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
-#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
static inline void sema_init (struct semaphore *sem, int val)
{
diff --git a/include/asm-x86/sembuf.h b/include/asm-x86/sembuf.h
index e42c971e383f..ee50c801f7b7 100644
--- a/include/asm-x86/sembuf.h
+++ b/include/asm-x86/sembuf.h
@@ -1,13 +1,24 @@
-#ifdef __KERNEL__
-# ifdef CONFIG_X86_32
-# include "sembuf_32.h"
-# else
-# include "sembuf_64.h"
-# endif
-#else
-# ifdef __i386__
-# include "sembuf_32.h"
-# else
-# include "sembuf_64.h"
-# endif
-#endif
+#ifndef _ASM_X86_SEMBUF_H
+#define _ASM_X86_SEMBUF_H
+
+/*
+ * The semid64_ds structure for x86 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+struct semid64_ds {
+ struct ipc64_perm sem_perm; /* permissions .. see ipc.h */
+ __kernel_time_t sem_otime; /* last semop time */
+ unsigned long __unused1;
+ __kernel_time_t sem_ctime; /* last change time */
+ unsigned long __unused2;
+ unsigned long sem_nsems; /* no. of semaphores in array */
+ unsigned long __unused3;
+ unsigned long __unused4;
+};
+
+#endif /* _ASM_X86_SEMBUF_H */
diff --git a/include/asm-x86/sembuf_32.h b/include/asm-x86/sembuf_32.h
deleted file mode 100644
index 323835166c14..000000000000
--- a/include/asm-x86/sembuf_32.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef _I386_SEMBUF_H
-#define _I386_SEMBUF_H
-
-/*
- * The semid64_ds structure for i386 architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct semid64_ds {
- struct ipc64_perm sem_perm; /* permissions .. see ipc.h */
- __kernel_time_t sem_otime; /* last semop time */
- unsigned long __unused1;
- __kernel_time_t sem_ctime; /* last change time */
- unsigned long __unused2;
- unsigned long sem_nsems; /* no. of semaphores in array */
- unsigned long __unused3;
- unsigned long __unused4;
-};
-
-#endif /* _I386_SEMBUF_H */
diff --git a/include/asm-x86/sembuf_64.h b/include/asm-x86/sembuf_64.h
deleted file mode 100644
index 63b52925ae2a..000000000000
--- a/include/asm-x86/sembuf_64.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef _X86_64_SEMBUF_H
-#define _X86_64_SEMBUF_H
-
-/*
- * The semid64_ds structure for x86_64 architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct semid64_ds {
- struct ipc64_perm sem_perm; /* permissions .. see ipc.h */
- __kernel_time_t sem_otime; /* last semop time */
- unsigned long __unused1;
- __kernel_time_t sem_ctime; /* last change time */
- unsigned long __unused2;
- unsigned long sem_nsems; /* no. of semaphores in array */
- unsigned long __unused3;
- unsigned long __unused4;
-};
-
-#endif /* _X86_64_SEMBUF_H */
diff --git a/include/asm-x86/serial.h b/include/asm-x86/serial.h
index cf1b05227b29..628c801535ea 100644
--- a/include/asm-x86/serial.h
+++ b/include/asm-x86/serial.h
@@ -1,5 +1,29 @@
-#ifdef CONFIG_X86_32
-# include "serial_32.h"
+#ifndef _ASM_X86_SERIAL_H
+#define _ASM_X86_SERIAL_H
+
+/*
+ * This assumes you have a 1.8432 MHz clock for your UART.
+ *
+ * It'd be nice if someone built a serial card with a 24.576 MHz
+ * clock, since the 16550A is capable of handling a top speed of 1.5
+ * megabits/second; but this requires the faster clock.
+ */
+#define BASE_BAUD ( 1843200 / 16 )
+
+/* Standard COM flags (except for COM4, because of the 8514 problem) */
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ)
+#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ)
#else
-# include "serial_64.h"
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
+#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF
#endif
+
+#define SERIAL_PORT_DFNS \
+ /* UART CLK PORT IRQ FLAGS */ \
+ { 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS }, /* ttyS0 */ \
+ { 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS }, /* ttyS1 */ \
+ { 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS }, /* ttyS2 */ \
+ { 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS }, /* ttyS3 */
+
+#endif /* _ASM_X86_SERIAL_H */
diff --git a/include/asm-x86/serial_32.h b/include/asm-x86/serial_32.h
deleted file mode 100644
index bd67480ca109..000000000000
--- a/include/asm-x86/serial_32.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * include/asm-i386/serial.h
- */
-
-
-/*
- * This assumes you have a 1.8432 MHz clock for your UART.
- *
- * It'd be nice if someone built a serial card with a 24.576 MHz
- * clock, since the 16550A is capable of handling a top speed of 1.5
- * megabits/second; but this requires the faster clock.
- */
-#define BASE_BAUD ( 1843200 / 16 )
-
-/* Standard COM flags (except for COM4, because of the 8514 problem) */
-#ifdef CONFIG_SERIAL_DETECT_IRQ
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ)
-#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ)
-#else
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
-#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF
-#endif
-
-#define SERIAL_PORT_DFNS \
- /* UART CLK PORT IRQ FLAGS */ \
- { 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS }, /* ttyS0 */ \
- { 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS }, /* ttyS1 */ \
- { 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS }, /* ttyS2 */ \
- { 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS }, /* ttyS3 */
diff --git a/include/asm-x86/serial_64.h b/include/asm-x86/serial_64.h
deleted file mode 100644
index b0496e0d72a6..000000000000
--- a/include/asm-x86/serial_64.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * include/asm-x86_64/serial.h
- */
-
-
-/*
- * This assumes you have a 1.8432 MHz clock for your UART.
- *
- * It'd be nice if someone built a serial card with a 24.576 MHz
- * clock, since the 16550A is capable of handling a top speed of 1.5
- * megabits/second; but this requires the faster clock.
- */
-#define BASE_BAUD ( 1843200 / 16 )
-
-/* Standard COM flags (except for COM4, because of the 8514 problem) */
-#ifdef CONFIG_SERIAL_DETECT_IRQ
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ)
-#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ)
-#else
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
-#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF
-#endif
-
-#define SERIAL_PORT_DFNS \
- /* UART CLK PORT IRQ FLAGS */ \
- { 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS }, /* ttyS0 */ \
- { 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS }, /* ttyS1 */ \
- { 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS }, /* ttyS2 */ \
- { 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS }, /* ttyS3 */
diff --git a/include/asm-x86/setup.h b/include/asm-x86/setup.h
index 81c0d98bb1c8..24d786e07b49 100644
--- a/include/asm-x86/setup.h
+++ b/include/asm-x86/setup.h
@@ -1,13 +1,63 @@
+#ifndef _ASM_X86_SETUP_H
+#define _ASM_X86_SETUP_H
+
+#define COMMAND_LINE_SIZE 2048
+
#ifdef __KERNEL__
-# ifdef CONFIG_X86_32
-# include "setup_32.h"
-# else
-# include "setup_64.h"
-# endif
-#else
-# ifdef __i386__
-# include "setup_32.h"
-# else
-# include "setup_64.h"
-# endif
+
+#ifdef __i386__
+
+#include <linux/pfn.h>
+/*
+ * Reserved space for vmalloc and iomap - defined in asm/page.h
+ */
+#define MAXMEM_PFN PFN_DOWN(MAXMEM)
+#define MAX_NONPAE_PFN (1 << 20)
+
+#endif /* __i386__ */
+
+#define PARAM_SIZE 4096 /* sizeof(struct boot_params) */
+
+#define OLD_CL_MAGIC 0xA33F
+#define OLD_CL_ADDRESS 0x020 /* Relative to real mode data */
+#define NEW_CL_POINTER 0x228 /* Relative to real mode data */
+
+#ifndef __ASSEMBLY__
+#include <asm/bootparam.h>
+
+#ifndef _SETUP
+
+/*
+ * This is set up by the setup-routine at boot-time
+ */
+extern struct boot_params boot_params;
+
+#ifdef __i386__
+/*
+ * Do NOT EVER look at the BIOS memory size location.
+ * It does not work on many machines.
+ */
+#define LOWMEMSIZE() (0x9f000)
+
+struct e820entry;
+
+char * __init machine_specific_memory_setup(void);
+char *memory_setup(void);
+
+int __init copy_e820_map(struct e820entry * biosmap, int nr_map);
+int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map);
+void __init add_memory_region(unsigned long long start,
+ unsigned long long size, int type);
+
+extern unsigned long init_pg_tables_end;
+
+#ifndef CONFIG_PARAVIRT
+#define paravirt_post_allocator_init() do {} while (0)
#endif
+
+#endif /* __i386__ */
+#endif /* _SETUP */
+#endif /* __ASSEMBLY__ */
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_X86_SETUP_H */
diff --git a/include/asm-x86/setup_32.h b/include/asm-x86/setup_32.h
deleted file mode 100644
index 7862fe858a9e..000000000000
--- a/include/asm-x86/setup_32.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Just a place holder. We don't want to have to test x86 before
- * we include stuff
- */
-
-#ifndef _i386_SETUP_H
-#define _i386_SETUP_H
-
-#define COMMAND_LINE_SIZE 2048
-
-#ifdef __KERNEL__
-#include <linux/pfn.h>
-
-/*
- * Reserved space for vmalloc and iomap - defined in asm/page.h
- */
-#define MAXMEM_PFN PFN_DOWN(MAXMEM)
-#define MAX_NONPAE_PFN (1 << 20)
-
-#define PARAM_SIZE 4096
-
-#define OLD_CL_MAGIC_ADDR 0x90020
-#define OLD_CL_MAGIC 0xA33F
-#define OLD_CL_BASE_ADDR 0x90000
-#define OLD_CL_OFFSET 0x90022
-#define NEW_CL_POINTER 0x228 /* Relative to real mode data */
-
-#ifndef __ASSEMBLY__
-
-#include <asm/bootparam.h>
-
-/*
- * This is set up by the setup-routine at boot-time
- */
-extern struct boot_params boot_params;
-
-#define PARAM ((char *)&boot_params)
-#define SCREEN_INFO (*(struct screen_info *) (PARAM+0))
-#define EXT_MEM_K (*(unsigned short *) (PARAM+2))
-#define ALT_MEM_K (*(unsigned long *) (PARAM+0x1e0))
-#define E820_MAP_NR (*(char*) (PARAM+E820NR))
-#define E820_MAP ((struct e820entry *) (PARAM+E820MAP))
-#define APM_BIOS_INFO (*(struct apm_bios_info *) (PARAM+0x40))
-#define IST_INFO (*(struct ist_info *) (PARAM+0x60))
-#define SYS_DESC_TABLE (*(struct sys_desc_table *)(PARAM+0xa0))
-#define EFI_SYSTAB ((efi_system_table_t *) *((unsigned long *)(PARAM+0x1c4)))
-#define EFI_MEMDESC_SIZE (*((unsigned long *) (PARAM+0x1c8)))
-#define EFI_MEMDESC_VERSION (*((unsigned long *) (PARAM+0x1cc)))
-#define EFI_MEMMAP ((void *) *((unsigned long *)(PARAM+0x1d0)))
-#define EFI_MEMMAP_SIZE (*((unsigned long *) (PARAM+0x1d4)))
-#define MOUNT_ROOT_RDONLY (*(unsigned short *) (PARAM+0x1F2))
-#define RAMDISK_FLAGS (*(unsigned short *) (PARAM+0x1F8))
-#define VIDEO_MODE (*(unsigned short *) (PARAM+0x1FA))
-#define ORIG_ROOT_DEV (*(unsigned short *) (PARAM+0x1FC))
-#define AUX_DEVICE_INFO (*(unsigned char *) (PARAM+0x1FF))
-#define LOADER_TYPE (*(unsigned char *) (PARAM+0x210))
-#define KERNEL_START (*(unsigned long *) (PARAM+0x214))
-#define INITRD_START (*(unsigned long *) (PARAM+0x218))
-#define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c))
-#define EDID_INFO (*(struct edid_info *) (PARAM+0x140))
-#define EDD_NR (*(unsigned char *) (PARAM+EDDNR))
-#define EDD_MBR_SIG_NR (*(unsigned char *) (PARAM+EDD_MBR_SIG_NR_BUF))
-#define EDD_MBR_SIGNATURE ((unsigned int *) (PARAM+EDD_MBR_SIG_BUF))
-#define EDD_BUF ((struct edd_info *) (PARAM+EDDBUF))
-
-/*
- * Do NOT EVER look at the BIOS memory size location.
- * It does not work on many machines.
- */
-#define LOWMEMSIZE() (0x9f000)
-
-struct e820entry;
-
-char * __init machine_specific_memory_setup(void);
-char *memory_setup(void);
-
-int __init copy_e820_map(struct e820entry * biosmap, int nr_map);
-int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map);
-void __init add_memory_region(unsigned long long start,
- unsigned long long size, int type);
-
-extern unsigned long init_pg_tables_end;
-
-#ifndef CONFIG_PARAVIRT
-#define paravirt_post_allocator_init() do {} while (0)
-#endif
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* __KERNEL__ */
-
-#endif /* _i386_SETUP_H */
diff --git a/include/asm-x86/setup_64.h b/include/asm-x86/setup_64.h
deleted file mode 100644
index eaeff73d6c10..000000000000
--- a/include/asm-x86/setup_64.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _x8664_SETUP_H
-#define _x8664_SETUP_H
-
-#define COMMAND_LINE_SIZE 2048
-
-#endif
diff --git a/include/asm-x86/shmbuf.h b/include/asm-x86/shmbuf.h
index e85f1cb11217..b51413b74971 100644
--- a/include/asm-x86/shmbuf.h
+++ b/include/asm-x86/shmbuf.h
@@ -1,13 +1,51 @@
-#ifdef __KERNEL__
-# ifdef CONFIG_X86_32
-# include "shmbuf_32.h"
-# else
-# include "shmbuf_64.h"
-# endif
-#else
-# ifdef __i386__
-# include "shmbuf_32.h"
-# else
-# include "shmbuf_64.h"
-# endif
+#ifndef _ASM_X86_SHMBUF_H
+#define _ASM_X86_SHMBUF_H
+
+/*
+ * The shmid64_ds structure for x86 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space on 32 bit is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ *
+ * Pad space on 64 bit is left for:
+ * - 2 miscellaneous 64-bit values
+ */
+
+struct shmid64_ds {
+ struct ipc64_perm shm_perm; /* operation perms */
+ size_t shm_segsz; /* size of segment (bytes) */
+ __kernel_time_t shm_atime; /* last attach time */
+#ifdef __i386__
+ unsigned long __unused1;
#endif
+ __kernel_time_t shm_dtime; /* last detach time */
+#ifdef __i386__
+ unsigned long __unused2;
+#endif
+ __kernel_time_t shm_ctime; /* last change time */
+#ifdef __i386__
+ unsigned long __unused3;
+#endif
+ __kernel_pid_t shm_cpid; /* pid of creator */
+ __kernel_pid_t shm_lpid; /* pid of last operator */
+ unsigned long shm_nattch; /* no. of current attaches */
+ unsigned long __unused4;
+ unsigned long __unused5;
+};
+
+struct shminfo64 {
+ unsigned long shmmax;
+ unsigned long shmmin;
+ unsigned long shmmni;
+ unsigned long shmseg;
+ unsigned long shmall;
+ unsigned long __unused1;
+ unsigned long __unused2;
+ unsigned long __unused3;
+ unsigned long __unused4;
+};
+
+#endif /* _ASM_X86_SHMBUF_H */
diff --git a/include/asm-x86/shmbuf_32.h b/include/asm-x86/shmbuf_32.h
deleted file mode 100644
index d1cdc3cb079b..000000000000
--- a/include/asm-x86/shmbuf_32.h
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef _I386_SHMBUF_H
-#define _I386_SHMBUF_H
-
-/*
- * The shmid64_ds structure for i386 architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct shmid64_ds {
- struct ipc64_perm shm_perm; /* operation perms */
- size_t shm_segsz; /* size of segment (bytes) */
- __kernel_time_t shm_atime; /* last attach time */
- unsigned long __unused1;
- __kernel_time_t shm_dtime; /* last detach time */
- unsigned long __unused2;
- __kernel_time_t shm_ctime; /* last change time */
- unsigned long __unused3;
- __kernel_pid_t shm_cpid; /* pid of creator */
- __kernel_pid_t shm_lpid; /* pid of last operator */
- unsigned long shm_nattch; /* no. of current attaches */
- unsigned long __unused4;
- unsigned long __unused5;
-};
-
-struct shminfo64 {
- unsigned long shmmax;
- unsigned long shmmin;
- unsigned long shmmni;
- unsigned long shmseg;
- unsigned long shmall;
- unsigned long __unused1;
- unsigned long __unused2;
- unsigned long __unused3;
- unsigned long __unused4;
-};
-
-#endif /* _I386_SHMBUF_H */
diff --git a/include/asm-x86/shmbuf_64.h b/include/asm-x86/shmbuf_64.h
deleted file mode 100644
index 5a6d6dda7c48..000000000000
--- a/include/asm-x86/shmbuf_64.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef _X8664_SHMBUF_H
-#define _X8664_SHMBUF_H
-
-/*
- * The shmid64_ds structure for x8664 architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 2 miscellaneous 64-bit values
- */
-
-struct shmid64_ds {
- struct ipc64_perm shm_perm; /* operation perms */
- size_t shm_segsz; /* size of segment (bytes) */
- __kernel_time_t shm_atime; /* last attach time */
- __kernel_time_t shm_dtime; /* last detach time */
- __kernel_time_t shm_ctime; /* last change time */
- __kernel_pid_t shm_cpid; /* pid of creator */
- __kernel_pid_t shm_lpid; /* pid of last operator */
- unsigned long shm_nattch; /* no. of current attaches */
- unsigned long __unused4;
- unsigned long __unused5;
-};
-
-struct shminfo64 {
- unsigned long shmmax;
- unsigned long shmmin;
- unsigned long shmmni;
- unsigned long shmseg;
- unsigned long shmall;
- unsigned long __unused1;
- unsigned long __unused2;
- unsigned long __unused3;
- unsigned long __unused4;
-};
-
-#endif
diff --git a/include/asm-x86/shmparam.h b/include/asm-x86/shmparam.h
index 165627cc5345..0880cf0917b9 100644
--- a/include/asm-x86/shmparam.h
+++ b/include/asm-x86/shmparam.h
@@ -1,13 +1,6 @@
-#ifdef __KERNEL__
-# ifdef CONFIG_X86_32
-# include "shmparam_32.h"
-# else
-# include "shmparam_64.h"
-# endif
-#else
-# ifdef __i386__
-# include "shmparam_32.h"
-# else
-# include "shmparam_64.h"
-# endif
-#endif
+#ifndef _ASM_X86_SHMPARAM_H
+#define _ASM_X86_SHMPARAM_H
+
+#define SHMLBA PAGE_SIZE /* attach addr a multiple of this */
+
+#endif /* _ASM_X86_SHMPARAM_H */
diff --git a/include/asm-x86/shmparam_32.h b/include/asm-x86/shmparam_32.h
deleted file mode 100644
index 786243a5b319..000000000000
--- a/include/asm-x86/shmparam_32.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASMI386_SHMPARAM_H
-#define _ASMI386_SHMPARAM_H
-
-#define SHMLBA PAGE_SIZE /* attach addr a multiple of this */
-
-#endif /* _ASMI386_SHMPARAM_H */
diff --git a/include/asm-x86/shmparam_64.h b/include/asm-x86/shmparam_64.h
deleted file mode 100644
index d7021620dcb7..000000000000
--- a/include/asm-x86/shmparam_64.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASMX8664_SHMPARAM_H
-#define _ASMX8664_SHMPARAM_H
-
-#define SHMLBA PAGE_SIZE /* attach addr a multiple of this */
-
-#endif /* _ASMX8664_SHMPARAM_H */
diff --git a/include/asm-x86/sigcontext.h b/include/asm-x86/sigcontext.h
index 0d16ceff1599..c047f9dc3423 100644
--- a/include/asm-x86/sigcontext.h
+++ b/include/asm-x86/sigcontext.h
@@ -1,13 +1,138 @@
-#ifdef __KERNEL__
-# ifdef CONFIG_X86_32
-# include "sigcontext_32.h"
-# else
-# include "sigcontext_64.h"
-# endif
-#else
-# ifdef __i386__
-# include "sigcontext_32.h"
-# else
-# include "sigcontext_64.h"
-# endif
+#ifndef _ASM_X86_SIGCONTEXT_H
+#define _ASM_X86_SIGCONTEXT_H
+
+#include <linux/compiler.h>
+#include <asm/types.h>
+
+#ifdef __i386__
+/*
+ * As documented in the iBCS2 standard..
+ *
+ * The first part of "struct _fpstate" is just the normal i387
+ * hardware setup, the extra "status" word is used to save the
+ * coprocessor status word before entering the handler.
+ *
+ * Pentium III FXSR, SSE support
+ * Gareth Hughes <gareth@valinux.com>, May 2000
+ *
+ * The FPU state data structure has had to grow to accommodate the
+ * extended FPU state required by the Streaming SIMD Extensions.
+ * There is no documented standard to accomplish this at the moment.
+ */
+struct _fpreg {
+ unsigned short significand[4];
+ unsigned short exponent;
+};
+
+struct _fpxreg {
+ unsigned short significand[4];
+ unsigned short exponent;
+ unsigned short padding[3];
+};
+
+struct _xmmreg {
+ unsigned long element[4];
+};
+
+struct _fpstate {
+ /* Regular FPU environment */
+ unsigned long cw;
+ unsigned long sw;
+ unsigned long tag;
+ unsigned long ipoff;
+ unsigned long cssel;
+ unsigned long dataoff;
+ unsigned long datasel;
+ struct _fpreg _st[8];
+ unsigned short status;
+ unsigned short magic; /* 0xffff = regular FPU data only */
+
+ /* FXSR FPU environment */
+ unsigned long _fxsr_env[6]; /* FXSR FPU env is ignored */
+ unsigned long mxcsr;
+ unsigned long reserved;
+ struct _fpxreg _fxsr_st[8]; /* FXSR FPU reg data is ignored */
+ struct _xmmreg _xmm[8];
+ unsigned long padding[56];
+};
+
+#define X86_FXSR_MAGIC 0x0000
+
+struct sigcontext {
+ unsigned short gs, __gsh;
+ unsigned short fs, __fsh;
+ unsigned short es, __esh;
+ unsigned short ds, __dsh;
+ unsigned long edi;
+ unsigned long esi;
+ unsigned long ebp;
+ unsigned long esp;
+ unsigned long ebx;
+ unsigned long edx;
+ unsigned long ecx;
+ unsigned long eax;
+ unsigned long trapno;
+ unsigned long err;
+ unsigned long eip;
+ unsigned short cs, __csh;
+ unsigned long eflags;
+ unsigned long esp_at_signal;
+ unsigned short ss, __ssh;
+ struct _fpstate __user * fpstate;
+ unsigned long oldmask;
+ unsigned long cr2;
+};
+
+#else /* __i386__ */
+
+/* FXSAVE frame */
+/* Note: reserved1/2 may someday contain valuable data. Always save/restore
+ them when you change signal frames. */
+struct _fpstate {
+ __u16 cwd;
+ __u16 swd;
+ __u16 twd; /* Note this is not the same as the 32bit/x87/FSAVE twd */
+ __u16 fop;
+ __u64 rip;
+ __u64 rdp;
+ __u32 mxcsr;
+ __u32 mxcsr_mask;
+ __u32 st_space[32]; /* 8*16 bytes for each FP-reg */
+ __u32 xmm_space[64]; /* 16*16 bytes for each XMM-reg */
+ __u32 reserved2[24];
+};
+
+struct sigcontext {
+ unsigned long r8;
+ unsigned long r9;
+ unsigned long r10;
+ unsigned long r11;
+ unsigned long r12;
+ unsigned long r13;
+ unsigned long r14;
+ unsigned long r15;
+ unsigned long rdi;
+ unsigned long rsi;
+ unsigned long rbp;
+ unsigned long rbx;
+ unsigned long rdx;
+ unsigned long rax;
+ unsigned long rcx;
+ unsigned long rsp;
+ unsigned long rip;
+ unsigned long eflags; /* RFLAGS */
+ unsigned short cs;
+ unsigned short gs;
+ unsigned short fs;
+ unsigned short __pad0;
+ unsigned long err;
+ unsigned long trapno;
+ unsigned long oldmask;
+ unsigned long cr2;
+ struct _fpstate __user *fpstate; /* zero when no FPU context */
+ unsigned long reserved1[8];
+};
+
+#endif /* !__i386__ */
+
#endif
diff --git a/include/asm-x86/sigcontext_32.h b/include/asm-x86/sigcontext_32.h
deleted file mode 100644
index aaef089a7787..000000000000
--- a/include/asm-x86/sigcontext_32.h
+++ /dev/null
@@ -1,85 +0,0 @@
-#ifndef _ASMi386_SIGCONTEXT_H
-#define _ASMi386_SIGCONTEXT_H
-
-#include <linux/compiler.h>
-
-/*
- * As documented in the iBCS2 standard..
- *
- * The first part of "struct _fpstate" is just the normal i387
- * hardware setup, the extra "status" word is used to save the
- * coprocessor status word before entering the handler.
- *
- * Pentium III FXSR, SSE support
- * Gareth Hughes <gareth@valinux.com>, May 2000
- *
- * The FPU state data structure has had to grow to accommodate the
- * extended FPU state required by the Streaming SIMD Extensions.
- * There is no documented standard to accomplish this at the moment.
- */
-struct _fpreg {
- unsigned short significand[4];
- unsigned short exponent;
-};
-
-struct _fpxreg {
- unsigned short significand[4];
- unsigned short exponent;
- unsigned short padding[3];
-};
-
-struct _xmmreg {
- unsigned long element[4];
-};
-
-struct _fpstate {
- /* Regular FPU environment */
- unsigned long cw;
- unsigned long sw;
- unsigned long tag;
- unsigned long ipoff;
- unsigned long cssel;
- unsigned long dataoff;
- unsigned long datasel;
- struct _fpreg _st[8];
- unsigned short status;
- unsigned short magic; /* 0xffff = regular FPU data only */
-
- /* FXSR FPU environment */
- unsigned long _fxsr_env[6]; /* FXSR FPU env is ignored */
- unsigned long mxcsr;
- unsigned long reserved;
- struct _fpxreg _fxsr_st[8]; /* FXSR FPU reg data is ignored */
- struct _xmmreg _xmm[8];
- unsigned long padding[56];
-};
-
-#define X86_FXSR_MAGIC 0x0000
-
-struct sigcontext {
- unsigned short gs, __gsh;
- unsigned short fs, __fsh;
- unsigned short es, __esh;
- unsigned short ds, __dsh;
- unsigned long edi;
- unsigned long esi;
- unsigned long ebp;
- unsigned long esp;
- unsigned long ebx;
- unsigned long edx;
- unsigned long ecx;
- unsigned long eax;
- unsigned long trapno;
- unsigned long err;
- unsigned long eip;
- unsigned short cs, __csh;
- unsigned long eflags;
- unsigned long esp_at_signal;
- unsigned short ss, __ssh;
- struct _fpstate __user * fpstate;
- unsigned long oldmask;
- unsigned long cr2;
-};
-
-
-#endif
diff --git a/include/asm-x86/sigcontext_64.h b/include/asm-x86/sigcontext_64.h
deleted file mode 100644
index b4e40236666c..000000000000
--- a/include/asm-x86/sigcontext_64.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef _ASM_X86_64_SIGCONTEXT_H
-#define _ASM_X86_64_SIGCONTEXT_H
-
-#include <asm/types.h>
-#include <linux/compiler.h>
-
-/* FXSAVE frame */
-/* Note: reserved1/2 may someday contain valuable data. Always save/restore
- them when you change signal frames. */
-struct _fpstate {
- __u16 cwd;
- __u16 swd;
- __u16 twd; /* Note this is not the same as the 32bit/x87/FSAVE twd */
- __u16 fop;
- __u64 rip;
- __u64 rdp;
- __u32 mxcsr;
- __u32 mxcsr_mask;
- __u32 st_space[32]; /* 8*16 bytes for each FP-reg */
- __u32 xmm_space[64]; /* 16*16 bytes for each XMM-reg */
- __u32 reserved2[24];
-};
-
-struct sigcontext {
- unsigned long r8;
- unsigned long r9;
- unsigned long r10;
- unsigned long r11;
- unsigned long r12;
- unsigned long r13;
- unsigned long r14;
- unsigned long r15;
- unsigned long rdi;
- unsigned long rsi;
- unsigned long rbp;
- unsigned long rbx;
- unsigned long rdx;
- unsigned long rax;
- unsigned long rcx;
- unsigned long rsp;
- unsigned long rip;
- unsigned long eflags; /* RFLAGS */
- unsigned short cs;
- unsigned short gs;
- unsigned short fs;
- unsigned short __pad0;
- unsigned long err;
- unsigned long trapno;
- unsigned long oldmask;
- unsigned long cr2;
- struct _fpstate __user *fpstate; /* zero when no FPU context */
- unsigned long reserved1[8];
-};
-
-#endif
diff --git a/include/asm-x86/siginfo.h b/include/asm-x86/siginfo.h
index 0b8e4bb47d25..a477bea0c2a1 100644
--- a/include/asm-x86/siginfo.h
+++ b/include/asm-x86/siginfo.h
@@ -1,13 +1,10 @@
-#ifdef __KERNEL__
-# ifdef CONFIG_X86_32
-# include "siginfo_32.h"
-# else
-# include "siginfo_64.h"
-# endif
-#else
-# ifdef __i386__
-# include "siginfo_32.h"
-# else
-# include "siginfo_64.h"
-# endif
+#ifndef _ASM_X86_SIGINFO_H
+#define _ASM_X86_SIGINFO_H
+
+#ifdef __x86_64__
+# define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int))
+#endif
+
+#include <asm-generic/siginfo.h>
+
#endif
diff --git a/include/asm-x86/siginfo_32.h b/include/asm-x86/siginfo_32.h
deleted file mode 100644
index fe18f98fccfa..000000000000
--- a/include/asm-x86/siginfo_32.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _I386_SIGINFO_H
-#define _I386_SIGINFO_H
-
-#include <asm-generic/siginfo.h>
-
-#endif
diff --git a/include/asm-x86/siginfo_64.h b/include/asm-x86/siginfo_64.h
deleted file mode 100644
index d09a1e6e7246..000000000000
--- a/include/asm-x86/siginfo_64.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef _X8664_SIGINFO_H
-#define _X8664_SIGINFO_H
-
-#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int))
-
-#include <asm-generic/siginfo.h>
-
-#endif
diff --git a/include/asm-x86/signal.h b/include/asm-x86/signal.h
index bf5a63f457da..987a422a2c78 100644
--- a/include/asm-x86/signal.h
+++ b/include/asm-x86/signal.h
@@ -1,13 +1,266 @@
+#ifndef _ASM_X86_SIGNAL_H
+#define _ASM_X86_SIGNAL_H
+
+#ifndef __ASSEMBLY__
+#include <linux/types.h>
+#include <linux/time.h>
+#include <linux/compiler.h>
+
+/* Avoid too many header ordering problems. */
+struct siginfo;
+
#ifdef __KERNEL__
-# ifdef CONFIG_X86_32
-# include "signal_32.h"
-# else
-# include "signal_64.h"
-# endif
+#include <linux/linkage.h>
+
+/* Most things should be clean enough to redefine this at will, if care
+ is taken to make libc match. */
+
+#define _NSIG 64
+
+#ifdef __i386__
+# define _NSIG_BPW 32
#else
-# ifdef __i386__
-# include "signal_32.h"
-# else
-# include "signal_64.h"
-# endif
+# define _NSIG_BPW 64
+#endif
+
+#define _NSIG_WORDS (_NSIG / _NSIG_BPW)
+
+typedef unsigned long old_sigset_t; /* at least 32 bits */
+
+typedef struct {
+ unsigned long sig[_NSIG_WORDS];
+} sigset_t;
+
+#else
+/* Here we must cater to libcs that poke about in kernel headers. */
+
+#define NSIG 32
+typedef unsigned long sigset_t;
+
+#endif /* __KERNEL__ */
+#endif /* __ASSEMBLY__ */
+
+#define SIGHUP 1
+#define SIGINT 2
+#define SIGQUIT 3
+#define SIGILL 4
+#define SIGTRAP 5
+#define SIGABRT 6
+#define SIGIOT 6
+#define SIGBUS 7
+#define SIGFPE 8
+#define SIGKILL 9
+#define SIGUSR1 10
+#define SIGSEGV 11
+#define SIGUSR2 12
+#define SIGPIPE 13
+#define SIGALRM 14
+#define SIGTERM 15
+#define SIGSTKFLT 16
+#define SIGCHLD 17
+#define SIGCONT 18
+#define SIGSTOP 19
+#define SIGTSTP 20
+#define SIGTTIN 21
+#define SIGTTOU 22
+#define SIGURG 23
+#define SIGXCPU 24
+#define SIGXFSZ 25
+#define SIGVTALRM 26
+#define SIGPROF 27
+#define SIGWINCH 28
+#define SIGIO 29
+#define SIGPOLL SIGIO
+/*
+#define SIGLOST 29
+*/
+#define SIGPWR 30
+#define SIGSYS 31
+#define SIGUNUSED 31
+
+/* These should not be considered constants from userland. */
+#define SIGRTMIN 32
+#define SIGRTMAX _NSIG
+
+/*
+ * SA_FLAGS values:
+ *
+ * SA_ONSTACK indicates that a registered stack_t will be used.
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
+ * SA_RESETHAND clears the handler when the signal is delivered.
+ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
+ * SA_NODEFER prevents the current signal from being masked in the handler.
+ *
+ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
+ * Unix names RESETHAND and NODEFER respectively.
+ */
+#define SA_NOCLDSTOP 0x00000001u
+#define SA_NOCLDWAIT 0x00000002u
+#define SA_SIGINFO 0x00000004u
+#define SA_ONSTACK 0x08000000u
+#define SA_RESTART 0x10000000u
+#define SA_NODEFER 0x40000000u
+#define SA_RESETHAND 0x80000000u
+
+#define SA_NOMASK SA_NODEFER
+#define SA_ONESHOT SA_RESETHAND
+
+#define SA_RESTORER 0x04000000
+
+/*
+ * sigaltstack controls
+ */
+#define SS_ONSTACK 1
+#define SS_DISABLE 2
+
+#define MINSIGSTKSZ 2048
+#define SIGSTKSZ 8192
+
+#include <asm-generic/signal.h>
+
+#ifndef __ASSEMBLY__
+
+#ifdef __i386__
+# ifdef __KERNEL__
+struct old_sigaction {
+ __sighandler_t sa_handler;
+ old_sigset_t sa_mask;
+ unsigned long sa_flags;
+ __sigrestore_t sa_restorer;
+};
+
+struct sigaction {
+ __sighandler_t sa_handler;
+ unsigned long sa_flags;
+ __sigrestore_t sa_restorer;
+ sigset_t sa_mask; /* mask last for extensibility */
+};
+
+struct k_sigaction {
+ struct sigaction sa;
+};
+# else /* __KERNEL__ */
+/* Here we must cater to libcs that poke about in kernel headers. */
+
+struct sigaction {
+ union {
+ __sighandler_t _sa_handler;
+ void (*_sa_sigaction)(int, struct siginfo *, void *);
+ } _u;
+ sigset_t sa_mask;
+ unsigned long sa_flags;
+ void (*sa_restorer)(void);
+};
+
+#define sa_handler _u._sa_handler
+#define sa_sigaction _u._sa_sigaction
+
+# endif /* ! __KERNEL__ */
+#else /* __i386__ */
+
+struct sigaction {
+ __sighandler_t sa_handler;
+ unsigned long sa_flags;
+ __sigrestore_t sa_restorer;
+ sigset_t sa_mask; /* mask last for extensibility */
+};
+
+struct k_sigaction {
+ struct sigaction sa;
+};
+
+#endif /* !__i386__ */
+
+typedef struct sigaltstack {
+ void __user *ss_sp;
+ int ss_flags;
+ size_t ss_size;
+} stack_t;
+
+#ifdef __KERNEL__
+#include <asm/sigcontext.h>
+
+#ifdef __386__
+
+#define __HAVE_ARCH_SIG_BITOPS
+
+#define sigaddset(set,sig) \
+ (__builtin_constantp(sig) ? \
+ __const_sigaddset((set),(sig)) : \
+ __gen_sigaddset((set),(sig)))
+
+static __inline__ void __gen_sigaddset(sigset_t *set, int _sig)
+{
+ __asm__("btsl %1,%0" : "+m"(*set) : "Ir"(_sig - 1) : "cc");
+}
+
+static __inline__ void __const_sigaddset(sigset_t *set, int _sig)
+{
+ unsigned long sig = _sig - 1;
+ set->sig[sig / _NSIG_BPW] |= 1 << (sig % _NSIG_BPW);
+}
+
+#define sigdelset(set,sig) \
+ (__builtin_constant_p(sig) ? \
+ __const_sigdelset((set),(sig)) : \
+ __gen_sigdelset((set),(sig)))
+
+
+static __inline__ void __gen_sigdelset(sigset_t *set, int _sig)
+{
+ __asm__("btrl %1,%0" : "+m"(*set) : "Ir"(_sig - 1) : "cc");
+}
+
+static __inline__ void __const_sigdelset(sigset_t *set, int _sig)
+{
+ unsigned long sig = _sig - 1;
+ set->sig[sig / _NSIG_BPW] &= ~(1 << (sig % _NSIG_BPW));
+}
+
+static __inline__ int __const_sigismember(sigset_t *set, int _sig)
+{
+ unsigned long sig = _sig - 1;
+ return 1 & (set->sig[sig / _NSIG_BPW] >> (sig % _NSIG_BPW));
+}
+
+static __inline__ int __gen_sigismember(sigset_t *set, int _sig)
+{
+ int ret;
+ __asm__("btl %2,%1\n\tsbbl %0,%0"
+ : "=r"(ret) : "m"(*set), "Ir"(_sig-1) : "cc");
+ return ret;
+}
+
+#define sigismember(set,sig) \
+ (__builtin_constant_p(sig) ? \
+ __const_sigismember((set),(sig)) : \
+ __gen_sigismember((set),(sig)))
+
+static __inline__ int sigfindinword(unsigned long word)
+{
+ __asm__("bsfl %1,%0" : "=r"(word) : "rm"(word) : "cc");
+ return word;
+}
+
+struct pt_regs;
+
+#define ptrace_signal_deliver(regs, cookie) \
+ do { \
+ if (current->ptrace & PT_DTRACE) { \
+ current->ptrace &= ~PT_DTRACE; \
+ (regs)->eflags &= ~TF_MASK; \
+ } \
+ } while (0)
+
+#else /* __i386__ */
+
+#undef __HAVE_ARCH_SIG_BITOPS
+
+#define ptrace_signal_deliver(regs, cookie) do { } while (0)
+
+#endif /* !__i386__ */
+#endif /* __KERNEL__ */
+#endif /* __ASSEMBLY__ */
+
#endif
diff --git a/include/asm-x86/signal_32.h b/include/asm-x86/signal_32.h
deleted file mode 100644
index c3e8adec5918..000000000000
--- a/include/asm-x86/signal_32.h
+++ /dev/null
@@ -1,232 +0,0 @@
-#ifndef _ASMi386_SIGNAL_H
-#define _ASMi386_SIGNAL_H
-
-#include <linux/types.h>
-#include <linux/time.h>
-#include <linux/compiler.h>
-
-/* Avoid too many header ordering problems. */
-struct siginfo;
-
-#ifdef __KERNEL__
-
-#include <linux/linkage.h>
-
-/* Most things should be clean enough to redefine this at will, if care
- is taken to make libc match. */
-
-#define _NSIG 64
-#define _NSIG_BPW 32
-#define _NSIG_WORDS (_NSIG / _NSIG_BPW)
-
-typedef unsigned long old_sigset_t; /* at least 32 bits */
-
-typedef struct {
- unsigned long sig[_NSIG_WORDS];
-} sigset_t;
-
-#else
-/* Here we must cater to libcs that poke about in kernel headers. */
-
-#define NSIG 32
-typedef unsigned long sigset_t;
-
-#endif /* __KERNEL__ */
-
-#define SIGHUP 1
-#define SIGINT 2
-#define SIGQUIT 3
-#define SIGILL 4
-#define SIGTRAP 5
-#define SIGABRT 6
-#define SIGIOT 6
-#define SIGBUS 7
-#define SIGFPE 8
-#define SIGKILL 9
-#define SIGUSR1 10
-#define SIGSEGV 11
-#define SIGUSR2 12
-#define SIGPIPE 13
-#define SIGALRM 14
-#define SIGTERM 15
-#define SIGSTKFLT 16
-#define SIGCHLD 17
-#define SIGCONT 18
-#define SIGSTOP 19
-#define SIGTSTP 20
-#define SIGTTIN 21
-#define SIGTTOU 22
-#define SIGURG 23
-#define SIGXCPU 24
-#define SIGXFSZ 25
-#define SIGVTALRM 26
-#define SIGPROF 27
-#define SIGWINCH 28
-#define SIGIO 29
-#define SIGPOLL SIGIO
-/*
-#define SIGLOST 29
-*/
-#define SIGPWR 30
-#define SIGSYS 31
-#define SIGUNUSED 31
-
-/* These should not be considered constants from userland. */
-#define SIGRTMIN 32
-#define SIGRTMAX _NSIG
-
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP 0x00000001u
-#define SA_NOCLDWAIT 0x00000002u
-#define SA_SIGINFO 0x00000004u
-#define SA_ONSTACK 0x08000000u
-#define SA_RESTART 0x10000000u
-#define SA_NODEFER 0x40000000u
-#define SA_RESETHAND 0x80000000u
-
-#define SA_NOMASK SA_NODEFER
-#define SA_ONESHOT SA_RESETHAND
-
-#define SA_RESTORER 0x04000000
-
-/*
- * sigaltstack controls
- */
-#define SS_ONSTACK 1
-#define SS_DISABLE 2
-
-#define MINSIGSTKSZ 2048
-#define SIGSTKSZ 8192
-
-#include <asm-generic/signal.h>
-
-#ifdef __KERNEL__
-struct old_sigaction {
- __sighandler_t sa_handler;
- old_sigset_t sa_mask;
- unsigned long sa_flags;
- __sigrestore_t sa_restorer;
-};
-
-struct sigaction {
- __sighandler_t sa_handler;
- unsigned long sa_flags;
- __sigrestore_t sa_restorer;
- sigset_t sa_mask; /* mask last for extensibility */
-};
-
-struct k_sigaction {
- struct sigaction sa;
-};
-#else
-/* Here we must cater to libcs that poke about in kernel headers. */
-
-struct sigaction {
- union {
- __sighandler_t _sa_handler;
- void (*_sa_sigaction)(int, struct siginfo *, void *);
- } _u;
- sigset_t sa_mask;
- unsigned long sa_flags;
- void (*sa_restorer)(void);
-};
-
-#define sa_handler _u._sa_handler
-#define sa_sigaction _u._sa_sigaction
-
-#endif /* __KERNEL__ */
-
-typedef struct sigaltstack {
- void __user *ss_sp;
- int ss_flags;
- size_t ss_size;
-} stack_t;
-
-#ifdef __KERNEL__
-#include <asm/sigcontext.h>
-
-#define __HAVE_ARCH_SIG_BITOPS
-
-#define sigaddset(set,sig) \
- (__builtin_constant_p(sig) ? \
- __const_sigaddset((set),(sig)) : \
- __gen_sigaddset((set),(sig)))
-
-static __inline__ void __gen_sigaddset(sigset_t *set, int _sig)
-{
- __asm__("btsl %1,%0" : "+m"(*set) : "Ir"(_sig - 1) : "cc");
-}
-
-static __inline__ void __const_sigaddset(sigset_t *set, int _sig)
-{
- unsigned long sig = _sig - 1;
- set->sig[sig / _NSIG_BPW] |= 1 << (sig % _NSIG_BPW);
-}
-
-#define sigdelset(set,sig) \
- (__builtin_constant_p(sig) ? \
- __const_sigdelset((set),(sig)) : \
- __gen_sigdelset((set),(sig)))
-
-
-static __inline__ void __gen_sigdelset(sigset_t *set, int _sig)
-{
- __asm__("btrl %1,%0" : "+m"(*set) : "Ir"(_sig - 1) : "cc");
-}
-
-static __inline__ void __const_sigdelset(sigset_t *set, int _sig)
-{
- unsigned long sig = _sig - 1;
- set->sig[sig / _NSIG_BPW] &= ~(1 << (sig % _NSIG_BPW));
-}
-
-static __inline__ int __const_sigismember(sigset_t *set, int _sig)
-{
- unsigned long sig = _sig - 1;
- return 1 & (set->sig[sig / _NSIG_BPW] >> (sig % _NSIG_BPW));
-}
-
-static __inline__ int __gen_sigismember(sigset_t *set, int _sig)
-{
- int ret;
- __asm__("btl %2,%1\n\tsbbl %0,%0"
- : "=r"(ret) : "m"(*set), "Ir"(_sig-1) : "cc");
- return ret;
-}
-
-#define sigismember(set,sig) \
- (__builtin_constant_p(sig) ? \
- __const_sigismember((set),(sig)) : \
- __gen_sigismember((set),(sig)))
-
-static __inline__ int sigfindinword(unsigned long word)
-{
- __asm__("bsfl %1,%0" : "=r"(word) : "rm"(word) : "cc");
- return word;
-}
-
-struct pt_regs;
-
-#define ptrace_signal_deliver(regs, cookie) \
- do { \
- if (current->ptrace & PT_DTRACE) { \
- current->ptrace &= ~PT_DTRACE; \
- (regs)->eflags &= ~TF_MASK; \
- } \
- } while (0)
-
-#endif /* __KERNEL__ */
-
-#endif
diff --git a/include/asm-x86/signal_64.h b/include/asm-x86/signal_64.h
deleted file mode 100644
index 4581f978b299..000000000000
--- a/include/asm-x86/signal_64.h
+++ /dev/null
@@ -1,181 +0,0 @@
-#ifndef _ASMx8664_SIGNAL_H
-#define _ASMx8664_SIGNAL_H
-
-#ifndef __ASSEMBLY__
-#include <linux/types.h>
-#include <linux/time.h>
-
-/* Avoid too many header ordering problems. */
-struct siginfo;
-
-#ifdef __KERNEL__
-#include <linux/linkage.h>
-/* Most things should be clean enough to redefine this at will, if care
- is taken to make libc match. */
-
-#define _NSIG 64
-#define _NSIG_BPW 64
-#define _NSIG_WORDS (_NSIG / _NSIG_BPW)
-
-typedef unsigned long old_sigset_t; /* at least 32 bits */
-
-typedef struct {
- unsigned long sig[_NSIG_WORDS];
-} sigset_t;
-
-
-#else
-/* Here we must cater to libcs that poke about in kernel headers. */
-
-#define NSIG 32
-typedef unsigned long sigset_t;
-
-#endif /* __KERNEL__ */
-#endif
-
-#define SIGHUP 1
-#define SIGINT 2
-#define SIGQUIT 3
-#define SIGILL 4
-#define SIGTRAP 5
-#define SIGABRT 6
-#define SIGIOT 6
-#define SIGBUS 7
-#define SIGFPE 8
-#define SIGKILL 9
-#define SIGUSR1 10
-#define SIGSEGV 11
-#define SIGUSR2 12
-#define SIGPIPE 13
-#define SIGALRM 14
-#define SIGTERM 15
-#define SIGSTKFLT 16
-#define SIGCHLD 17
-#define SIGCONT 18
-#define SIGSTOP 19
-#define SIGTSTP 20
-#define SIGTTIN 21
-#define SIGTTOU 22
-#define SIGURG 23
-#define SIGXCPU 24
-#define SIGXFSZ 25
-#define SIGVTALRM 26
-#define SIGPROF 27
-#define SIGWINCH 28
-#define SIGIO 29
-#define SIGPOLL SIGIO
-/*
-#define SIGLOST 29
-*/
-#define SIGPWR 30
-#define SIGSYS 31
-#define SIGUNUSED 31
-
-/* These should not be considered constants from userland. */
-#define SIGRTMIN 32
-#define SIGRTMAX _NSIG
-
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP 0x00000001
-#define SA_NOCLDWAIT 0x00000002
-#define SA_SIGINFO 0x00000004
-#define SA_ONSTACK 0x08000000
-#define SA_RESTART 0x10000000
-#define SA_NODEFER 0x40000000
-#define SA_RESETHAND 0x80000000
-
-#define SA_NOMASK SA_NODEFER
-#define SA_ONESHOT SA_RESETHAND
-
-#define SA_RESTORER 0x04000000
-
-/*
- * sigaltstack controls
- */
-#define SS_ONSTACK 1
-#define SS_DISABLE 2
-
-#define MINSIGSTKSZ 2048
-#define SIGSTKSZ 8192
-
-#include <asm-generic/signal.h>
-
-#ifndef __ASSEMBLY__
-
-struct sigaction {
- __sighandler_t sa_handler;
- unsigned long sa_flags;
- __sigrestore_t sa_restorer;
- sigset_t sa_mask; /* mask last for extensibility */
-};
-
-struct k_sigaction {
- struct sigaction sa;
-};
-
-typedef struct sigaltstack {
- void __user *ss_sp;
- int ss_flags;
- size_t ss_size;
-} stack_t;
-
-#ifdef __KERNEL__
-#include <asm/sigcontext.h>
-
-#undef __HAVE_ARCH_SIG_BITOPS
-#if 0
-
-static inline void sigaddset(sigset_t *set, int _sig)
-{
- __asm__("btsq %1,%0" : "=m"(*set) : "Ir"(_sig - 1) : "cc");
-}
-
-static inline void sigdelset(sigset_t *set, int _sig)
-{
- __asm__("btrq %1,%0" : "=m"(*set) : "Ir"(_sig - 1) : "cc");
-}
-
-static inline int __const_sigismember(sigset_t *set, int _sig)
-{
- unsigned long sig = _sig - 1;
- return 1 & (set->sig[sig / _NSIG_BPW] >> (sig & ~(_NSIG_BPW-1)));
-}
-
-static inline int __gen_sigismember(sigset_t *set, int _sig)
-{
- int ret;
- __asm__("btq %2,%1\n\tsbbq %0,%0"
- : "=r"(ret) : "m"(*set), "Ir"(_sig-1) : "cc");
- return ret;
-}
-
-#define sigismember(set,sig) \
- (__builtin_constant_p(sig) ? \
- __const_sigismember((set),(sig)) : \
- __gen_sigismember((set),(sig)))
-
-static inline int sigfindinword(unsigned long word)
-{
- __asm__("bsfq %1,%0" : "=r"(word) : "rm"(word) : "cc");
- return word;
-}
-#endif
-#endif
-
-#define ptrace_signal_deliver(regs, cookie) do { } while (0)
-
-#endif /* __KERNEL__ */
-
-#endif
diff --git a/include/asm-x86/smp_32.h b/include/asm-x86/smp_32.h
index 1f73bde165b1..e10b7affdfe5 100644
--- a/include/asm-x86/smp_32.h
+++ b/include/asm-x86/smp_32.h
@@ -11,7 +11,7 @@
#endif
#if defined(CONFIG_X86_LOCAL_APIC) && !defined(__ASSEMBLY__)
-#include <asm/bitops.h>
+#include <linux/bitops.h>
#include <asm/mpspec.h>
#include <asm/apic.h>
#ifdef CONFIG_X86_IO_APIC
@@ -30,8 +30,8 @@
extern void smp_alloc_memory(void);
extern int pic_mode;
extern int smp_num_siblings;
-extern cpumask_t cpu_sibling_map[];
-extern cpumask_t cpu_core_map[];
+DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
+DECLARE_PER_CPU(cpumask_t, cpu_core_map);
extern void (*mtrr_hook) (void);
extern void zap_low_mappings (void);
@@ -39,9 +39,11 @@ extern void lock_ipi_call_lock(void);
extern void unlock_ipi_call_lock(void);
#define MAX_APICID 256
-extern u8 x86_cpu_to_apicid[];
+extern u8 __initdata x86_cpu_to_apicid_init[];
+extern void *x86_cpu_to_apicid_ptr;
+DECLARE_PER_CPU(u8, x86_cpu_to_apicid);
-#define cpu_physical_id(cpu) x86_cpu_to_apicid[cpu]
+#define cpu_physical_id(cpu) per_cpu(x86_cpu_to_apicid, cpu)
extern void set_cpu_sibling_map(int cpu);
diff --git a/include/asm-x86/smp_64.h b/include/asm-x86/smp_64.h
index 3f303d2365ed..ab612b0ff270 100644
--- a/include/asm-x86/smp_64.h
+++ b/include/asm-x86/smp_64.h
@@ -37,10 +37,19 @@ extern void lock_ipi_call_lock(void);
extern void unlock_ipi_call_lock(void);
extern int smp_num_siblings;
extern void smp_send_reschedule(int cpu);
+extern int smp_call_function_mask(cpumask_t mask, void (*func)(void *),
+ void *info, int wait);
-extern cpumask_t cpu_sibling_map[NR_CPUS];
-extern cpumask_t cpu_core_map[NR_CPUS];
-extern u8 cpu_llc_id[NR_CPUS];
+/*
+ * cpu_sibling_map and cpu_core_map now live
+ * in the per cpu area
+ *
+ * extern cpumask_t cpu_sibling_map[NR_CPUS];
+ * extern cpumask_t cpu_core_map[NR_CPUS];
+ */
+DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
+DECLARE_PER_CPU(cpumask_t, cpu_core_map);
+DECLARE_PER_CPU(u8, cpu_llc_id);
#define SMP_TRAMPOLINE_BASE 0x6000
@@ -67,6 +76,8 @@ extern unsigned __cpuinitdata disabled_cpus;
#endif /* CONFIG_SMP */
+#define safe_smp_processor_id() smp_processor_id()
+
static inline int hard_smp_processor_id(void)
{
/* we don't want to mark this access volatile - bad code generation */
@@ -77,8 +88,9 @@ static inline int hard_smp_processor_id(void)
* Some lowlevel functions might want to know about
* the real APIC ID <-> CPU # mapping.
*/
-extern u8 x86_cpu_to_apicid[NR_CPUS]; /* physical ID */
-extern u8 x86_cpu_to_log_apicid[NR_CPUS];
+extern u8 __initdata x86_cpu_to_apicid_init[];
+extern void *x86_cpu_to_apicid_ptr;
+DECLARE_PER_CPU(u8, x86_cpu_to_apicid); /* physical ID */
extern u8 bios_cpu_apicid[];
static inline int cpu_present_to_apicid(int mps_cpu)
@@ -109,8 +121,9 @@ static __inline int logical_smp_processor_id(void)
}
#ifdef CONFIG_SMP
-#define cpu_physical_id(cpu) x86_cpu_to_apicid[cpu]
+#define cpu_physical_id(cpu) per_cpu(x86_cpu_to_apicid, cpu)
#else
+extern unsigned int boot_cpu_id;
#define cpu_physical_id(cpu) boot_cpu_id
#endif /* !CONFIG_SMP */
#endif
diff --git a/include/asm-x86/sockios.h b/include/asm-x86/sockios.h
index 5a134fc70b9c..49cc72b5d3c9 100644
--- a/include/asm-x86/sockios.h
+++ b/include/asm-x86/sockios.h
@@ -1,13 +1,13 @@
-#ifdef __KERNEL__
-# ifdef CONFIG_X86_32
-# include "sockios_32.h"
-# else
-# include "sockios_64.h"
-# endif
-#else
-# ifdef __i386__
-# include "sockios_32.h"
-# else
-# include "sockios_64.h"
-# endif
-#endif
+#ifndef _ASM_X86_SOCKIOS_H
+#define _ASM_X86_SOCKIOS_H
+
+/* Socket-level I/O control calls. */
+#define FIOSETOWN 0x8901
+#define SIOCSPGRP 0x8902
+#define FIOGETOWN 0x8903
+#define SIOCGPGRP 0x8904
+#define SIOCATMARK 0x8905
+#define SIOCGSTAMP 0x8906 /* Get stamp (timeval) */
+#define SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */
+
+#endif /* _ASM_X86_SOCKIOS_H */
diff --git a/include/asm-x86/sockios_32.h b/include/asm-x86/sockios_32.h
deleted file mode 100644
index ff528c7d255c..000000000000
--- a/include/asm-x86/sockios_32.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __ARCH_I386_SOCKIOS__
-#define __ARCH_I386_SOCKIOS__
-
-/* Socket-level I/O control calls. */
-#define FIOSETOWN 0x8901
-#define SIOCSPGRP 0x8902
-#define FIOGETOWN 0x8903
-#define SIOCGPGRP 0x8904
-#define SIOCATMARK 0x8905
-#define SIOCGSTAMP 0x8906 /* Get stamp (timeval) */
-#define SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */
-
-#endif
diff --git a/include/asm-x86/sockios_64.h b/include/asm-x86/sockios_64.h
deleted file mode 100644
index d726ba2513e3..000000000000
--- a/include/asm-x86/sockios_64.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __ARCH_X8664_SOCKIOS__
-#define __ARCH_X8664_SOCKIOS__
-
-/* Socket-level I/O control calls. */
-#define FIOSETOWN 0x8901
-#define SIOCSPGRP 0x8902
-#define FIOGETOWN 0x8903
-#define SIOCGPGRP 0x8904
-#define SIOCATMARK 0x8905
-#define SIOCGSTAMP 0x8906 /* Get stamp (timeval) */
-#define SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */
-
-#endif
diff --git a/include/asm-x86/stacktrace.h b/include/asm-x86/stacktrace.h
index 6f0b54594307..70dd5bae3235 100644
--- a/include/asm-x86/stacktrace.h
+++ b/include/asm-x86/stacktrace.h
@@ -15,6 +15,6 @@ struct stacktrace_ops {
};
void dump_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long *stack,
- struct stacktrace_ops *ops, void *data);
+ const struct stacktrace_ops *ops, void *data);
#endif
diff --git a/include/asm-x86/stat.h b/include/asm-x86/stat.h
index 3ff6b50ef833..5c22dcb5d17e 100644
--- a/include/asm-x86/stat.h
+++ b/include/asm-x86/stat.h
@@ -1,13 +1,114 @@
-#ifdef __KERNEL__
-# ifdef CONFIG_X86_32
-# include "stat_32.h"
-# else
-# include "stat_64.h"
-# endif
+#ifndef _ASM_X86_STAT_H
+#define _ASM_X86_STAT_H
+
+#define STAT_HAVE_NSEC 1
+
+#ifdef __i386__
+struct stat {
+ unsigned long st_dev;
+ unsigned long st_ino;
+ unsigned short st_mode;
+ unsigned short st_nlink;
+ unsigned short st_uid;
+ unsigned short st_gid;
+ unsigned long st_rdev;
+ unsigned long st_size;
+ unsigned long st_blksize;
+ unsigned long st_blocks;
+ unsigned long st_atime;
+ unsigned long st_atime_nsec;
+ unsigned long st_mtime;
+ unsigned long st_mtime_nsec;
+ unsigned long st_ctime;
+ unsigned long st_ctime_nsec;
+ unsigned long __unused4;
+ unsigned long __unused5;
+};
+
+#define STAT64_HAS_BROKEN_ST_INO 1
+
+/* This matches struct stat64 in glibc2.1, hence the absolutely
+ * insane amounts of padding around dev_t's.
+ */
+struct stat64 {
+ unsigned long long st_dev;
+ unsigned char __pad0[4];
+
+ unsigned long __st_ino;
+
+ unsigned int st_mode;
+ unsigned int st_nlink;
+
+ unsigned long st_uid;
+ unsigned long st_gid;
+
+ unsigned long long st_rdev;
+ unsigned char __pad3[4];
+
+ long long st_size;
+ unsigned long st_blksize;
+
+ /* Number 512-byte blocks allocated. */
+ unsigned long long st_blocks;
+
+ unsigned long st_atime;
+ unsigned long st_atime_nsec;
+
+ unsigned long st_mtime;
+ unsigned int st_mtime_nsec;
+
+ unsigned long st_ctime;
+ unsigned long st_ctime_nsec;
+
+ unsigned long long st_ino;
+};
+
+#else /* __i386__ */
+
+struct stat {
+ unsigned long st_dev;
+ unsigned long st_ino;
+ unsigned long st_nlink;
+
+ unsigned int st_mode;
+ unsigned int st_uid;
+ unsigned int st_gid;
+ unsigned int __pad0;
+ unsigned long st_rdev;
+ long st_size;
+ long st_blksize;
+ long st_blocks; /* Number 512-byte blocks allocated. */
+
+ unsigned long st_atime;
+ unsigned long st_atime_nsec;
+ unsigned long st_mtime;
+ unsigned long st_mtime_nsec;
+ unsigned long st_ctime;
+ unsigned long st_ctime_nsec;
+ long __unused[3];
+};
+#endif
+
+/* for 32bit emulation and 32 bit kernels */
+struct __old_kernel_stat {
+ unsigned short st_dev;
+ unsigned short st_ino;
+ unsigned short st_mode;
+ unsigned short st_nlink;
+ unsigned short st_uid;
+ unsigned short st_gid;
+ unsigned short st_rdev;
+#ifdef __i386__
+ unsigned long st_size;
+ unsigned long st_atime;
+ unsigned long st_mtime;
+ unsigned long st_ctime;
#else
-# ifdef __i386__
-# include "stat_32.h"
-# else
-# include "stat_64.h"
-# endif
+ unsigned int st_size;
+ unsigned int st_atime;
+ unsigned int st_mtime;
+ unsigned int st_ctime;
+#endif
+};
+
#endif
diff --git a/include/asm-x86/stat_32.h b/include/asm-x86/stat_32.h
deleted file mode 100644
index 67eae78323ba..000000000000
--- a/include/asm-x86/stat_32.h
+++ /dev/null
@@ -1,77 +0,0 @@
-#ifndef _I386_STAT_H
-#define _I386_STAT_H
-
-struct __old_kernel_stat {
- unsigned short st_dev;
- unsigned short st_ino;
- unsigned short st_mode;
- unsigned short st_nlink;
- unsigned short st_uid;
- unsigned short st_gid;
- unsigned short st_rdev;
- unsigned long st_size;
- unsigned long st_atime;
- unsigned long st_mtime;
- unsigned long st_ctime;
-};
-
-struct stat {
- unsigned long st_dev;
- unsigned long st_ino;
- unsigned short st_mode;
- unsigned short st_nlink;
- unsigned short st_uid;
- unsigned short st_gid;
- unsigned long st_rdev;
- unsigned long st_size;
- unsigned long st_blksize;
- unsigned long st_blocks;
- unsigned long st_atime;
- unsigned long st_atime_nsec;
- unsigned long st_mtime;
- unsigned long st_mtime_nsec;
- unsigned long st_ctime;
- unsigned long st_ctime_nsec;
- unsigned long __unused4;
- unsigned long __unused5;
-};
-
-/* This matches struct stat64 in glibc2.1, hence the absolutely
- * insane amounts of padding around dev_t's.
- */
-struct stat64 {
- unsigned long long st_dev;
- unsigned char __pad0[4];
-
-#define STAT64_HAS_BROKEN_ST_INO 1
- unsigned long __st_ino;
-
- unsigned int st_mode;
- unsigned int st_nlink;
-
- unsigned long st_uid;
- unsigned long st_gid;
-
- unsigned long long st_rdev;
- unsigned char __pad3[4];
-
- long long st_size;
- unsigned long st_blksize;
-
- unsigned long long st_blocks; /* Number 512-byte blocks allocated. */
-
- unsigned long st_atime;
- unsigned long st_atime_nsec;
-
- unsigned long st_mtime;
- unsigned int st_mtime_nsec;
-
- unsigned long st_ctime;
- unsigned long st_ctime_nsec;
-
- unsigned long long st_ino;
-};
-
-#define STAT_HAVE_NSEC 1
-
-#endif
diff --git a/include/asm-x86/stat_64.h b/include/asm-x86/stat_64.h
deleted file mode 100644
index fd9f00d560f8..000000000000
--- a/include/asm-x86/stat_64.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef _ASM_X86_64_STAT_H
-#define _ASM_X86_64_STAT_H
-
-#define STAT_HAVE_NSEC 1
-
-struct stat {
- unsigned long st_dev;
- unsigned long st_ino;
- unsigned long st_nlink;
-
- unsigned int st_mode;
- unsigned int st_uid;
- unsigned int st_gid;
- unsigned int __pad0;
- unsigned long st_rdev;
- long st_size;
- long st_blksize;
- long st_blocks; /* Number 512-byte blocks allocated. */
-
- unsigned long st_atime;
- unsigned long st_atime_nsec;
- unsigned long st_mtime;
- unsigned long st_mtime_nsec;
- unsigned long st_ctime;
- unsigned long st_ctime_nsec;
- long __unused[3];
-};
-
-/* For 32bit emulation */
-struct __old_kernel_stat {
- unsigned short st_dev;
- unsigned short st_ino;
- unsigned short st_mode;
- unsigned short st_nlink;
- unsigned short st_uid;
- unsigned short st_gid;
- unsigned short st_rdev;
- unsigned int st_size;
- unsigned int st_atime;
- unsigned int st_mtime;
- unsigned int st_ctime;
-};
-
-#endif
diff --git a/include/asm-x86/statfs.h b/include/asm-x86/statfs.h
index 327fb5d7a148..7c651aa97252 100644
--- a/include/asm-x86/statfs.h
+++ b/include/asm-x86/statfs.h
@@ -1,13 +1,63 @@
-#ifdef __KERNEL__
-# ifdef CONFIG_X86_32
-# include "statfs_32.h"
-# else
-# include "statfs_64.h"
-# endif
+#ifndef _ASM_X86_STATFS_H
+#define _ASM_X86_STATFS_H
+
+#ifdef __i386__
+#include <asm-generic/statfs.h>
#else
-# ifdef __i386__
-# include "statfs_32.h"
-# else
-# include "statfs_64.h"
-# endif
+
+#ifndef __KERNEL_STRICT_NAMES
+
+#include <linux/types.h>
+
+typedef __kernel_fsid_t fsid_t;
+
+#endif
+
+/*
+ * This is ugly -- we're already 64-bit clean, so just duplicate the
+ * definitions.
+ */
+struct statfs {
+ long f_type;
+ long f_bsize;
+ long f_blocks;
+ long f_bfree;
+ long f_bavail;
+ long f_files;
+ long f_ffree;
+ __kernel_fsid_t f_fsid;
+ long f_namelen;
+ long f_frsize;
+ long f_spare[5];
+};
+
+struct statfs64 {
+ long f_type;
+ long f_bsize;
+ long f_blocks;
+ long f_bfree;
+ long f_bavail;
+ long f_files;
+ long f_ffree;
+ __kernel_fsid_t f_fsid;
+ long f_namelen;
+ long f_frsize;
+ long f_spare[5];
+};
+
+struct compat_statfs64 {
+ __u32 f_type;
+ __u32 f_bsize;
+ __u64 f_blocks;
+ __u64 f_bfree;
+ __u64 f_bavail;
+ __u64 f_files;
+ __u64 f_ffree;
+ __kernel_fsid_t f_fsid;
+ __u32 f_namelen;
+ __u32 f_frsize;
+ __u32 f_spare[5];
+} __attribute__((packed));
+
+#endif /* !__i386__ */
#endif
diff --git a/include/asm-x86/statfs_32.h b/include/asm-x86/statfs_32.h
deleted file mode 100644
index 24972c175132..000000000000
--- a/include/asm-x86/statfs_32.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _I386_STATFS_H
-#define _I386_STATFS_H
-
-#include <asm-generic/statfs.h>
-
-#endif
diff --git a/include/asm-x86/statfs_64.h b/include/asm-x86/statfs_64.h
deleted file mode 100644
index b3f4718af30b..000000000000
--- a/include/asm-x86/statfs_64.h
+++ /dev/null
@@ -1,58 +0,0 @@
-#ifndef _X86_64_STATFS_H
-#define _X86_64_STATFS_H
-
-#ifndef __KERNEL_STRICT_NAMES
-
-#include <linux/types.h>
-
-typedef __kernel_fsid_t fsid_t;
-
-#endif
-
-/*
- * This is ugly -- we're already 64-bit clean, so just duplicate the
- * definitions.
- */
-struct statfs {
- long f_type;
- long f_bsize;
- long f_blocks;
- long f_bfree;
- long f_bavail;
- long f_files;
- long f_ffree;
- __kernel_fsid_t f_fsid;
- long f_namelen;
- long f_frsize;
- long f_spare[5];
-};
-
-struct statfs64 {
- long f_type;
- long f_bsize;
- long f_blocks;
- long f_bfree;
- long f_bavail;
- long f_files;
- long f_ffree;
- __kernel_fsid_t f_fsid;
- long f_namelen;
- long f_frsize;
- long f_spare[5];
-};
-
-struct compat_statfs64 {
- __u32 f_type;
- __u32 f_bsize;
- __u64 f_blocks;
- __u64 f_bfree;
- __u64 f_bavail;
- __u64 f_files;
- __u64 f_ffree;
- __kernel_fsid_t f_fsid;
- __u32 f_namelen;
- __u32 f_frsize;
- __u32 f_spare[5];
-} __attribute__((packed));
-
-#endif
diff --git a/include/asm-x86/string_32.h b/include/asm-x86/string_32.h
index a9b64453bdf5..55bfa308f900 100644
--- a/include/asm-x86/string_32.h
+++ b/include/asm-x86/string_32.h
@@ -26,9 +26,6 @@ extern int strncmp(const char *cs, const char *ct, size_t count);
#define __HAVE_ARCH_STRCHR
extern char *strchr(const char *s, int c);
-#define __HAVE_ARCH_STRRCHR
-extern char *strrchr(const char *s, int c);
-
#define __HAVE_ARCH_STRLEN
extern size_t strlen(const char *s);
diff --git a/include/asm-x86/suspend_64.h b/include/asm-x86/suspend_64.h
index b897e8cb55fb..c505a76bcf6e 100644
--- a/include/asm-x86/suspend_64.h
+++ b/include/asm-x86/suspend_64.h
@@ -3,6 +3,9 @@
* Based on code
* Copyright 2001 Patrick Mochel <mochel@osdl.org>
*/
+#ifndef __ASM_X86_64_SUSPEND_H
+#define __ASM_X86_64_SUSPEND_H
+
#include <asm/desc.h>
#include <asm/i387.h>
@@ -12,8 +15,9 @@ arch_prepare_suspend(void)
return 0;
}
-/* Image of the saved processor state. If you touch this, fix acpi_wakeup.S. */
+/* Image of the saved processor state. If you touch this, fix acpi/wakeup.S. */
struct saved_context {
+ struct pt_regs regs;
u16 ds, es, fs, gs, ss;
unsigned long gs_base, gs_kernel_base, fs_base;
unsigned long cr0, cr2, cr3, cr4, cr8;
@@ -29,27 +33,16 @@ struct saved_context {
unsigned long tr;
unsigned long safety;
unsigned long return_address;
- unsigned long eflags;
} __attribute__((packed));
-/* We'll access these from assembly, so we'd better have them outside struct */
-extern unsigned long saved_context_eax, saved_context_ebx, saved_context_ecx, saved_context_edx;
-extern unsigned long saved_context_esp, saved_context_ebp, saved_context_esi, saved_context_edi;
-extern unsigned long saved_context_r08, saved_context_r09, saved_context_r10, saved_context_r11;
-extern unsigned long saved_context_r12, saved_context_r13, saved_context_r14, saved_context_r15;
-extern unsigned long saved_context_eflags;
-
#define loaddebug(thread,register) \
set_debugreg((thread)->debugreg##register, register)
extern void fix_processor_context(void);
-extern unsigned long saved_rip;
-extern unsigned long saved_rsp;
-extern unsigned long saved_rbp;
-extern unsigned long saved_rbx;
-extern unsigned long saved_rsi;
-extern unsigned long saved_rdi;
-
/* routines for saving/restoring kernel state */
extern int acpi_save_state_mem(void);
+extern char core_restore_code;
+extern char restore_registers;
+
+#endif /* __ASM_X86_64_SUSPEND_H */
diff --git a/include/asm-x86/system_32.h b/include/asm-x86/system_32.h
index e7e5d426fef5..ef8468883bac 100644
--- a/include/asm-x86/system_32.h
+++ b/include/asm-x86/system_32.h
@@ -7,6 +7,7 @@
#include <asm/cmpxchg.h>
#ifdef __KERNEL__
+#define AT_VECTOR_SIZE_ARCH 2 /* entries in ARCH_DLINFO */
struct task_struct; /* one of the stranger aspects of C forward declarations.. */
extern struct task_struct * FASTCALL(__switch_to(struct task_struct *prev, struct task_struct *next));
@@ -141,7 +142,7 @@ static inline unsigned long native_read_cr4_safe(void)
{
unsigned long val;
/* This could fault if %cr4 does not exist */
- asm("1: movl %%cr4, %0 \n"
+ asm volatile("1: movl %%cr4, %0 \n"
"2: \n"
".section __ex_table,\"a\" \n"
".long 1b,2b \n"
@@ -160,6 +161,10 @@ static inline void native_wbinvd(void)
asm volatile("wbinvd": : :"memory");
}
+static inline void clflush(volatile void *__p)
+{
+ asm volatile("clflush %0" : "+m" (*(char __force *)__p));
+}
#ifdef CONFIG_PARAVIRT
#include <asm/paravirt.h>
@@ -310,5 +315,6 @@ extern unsigned long arch_align_stack(unsigned long sp);
extern void free_init_pages(char *what, unsigned long begin, unsigned long end);
void default_idle(void);
+void __show_registers(struct pt_regs *, int all);
#endif
diff --git a/include/asm-x86/system_64.h b/include/asm-x86/system_64.h
index 5022aecc333d..4cb23848d460 100644
--- a/include/asm-x86/system_64.h
+++ b/include/asm-x86/system_64.h
@@ -7,9 +7,6 @@
#ifdef __KERNEL__
-#define __STR(x) #x
-#define STR(x) __STR(x)
-
#define __SAVE(reg,offset) "movq %%" #reg ",(14-" #offset ")*8(%%rsp)\n\t"
#define __RESTORE(reg,offset) "movq (14-" #offset ")*8(%%rsp),%%" #reg "\n\t"
@@ -85,7 +82,7 @@ static inline void write_cr0(unsigned long val)
static inline unsigned long read_cr2(void)
{
unsigned long cr2;
- asm("movq %%cr2,%0" : "=r" (cr2));
+ asm volatile("movq %%cr2,%0" : "=r" (cr2));
return cr2;
}
@@ -97,7 +94,7 @@ static inline void write_cr2(unsigned long val)
static inline unsigned long read_cr3(void)
{
unsigned long cr3;
- asm("movq %%cr3,%0" : "=r" (cr3));
+ asm volatile("movq %%cr3,%0" : "=r" (cr3));
return cr3;
}
@@ -109,7 +106,7 @@ static inline void write_cr3(unsigned long val)
static inline unsigned long read_cr4(void)
{
unsigned long cr4;
- asm("movq %%cr4,%0" : "=r" (cr4));
+ asm volatile("movq %%cr4,%0" : "=r" (cr4));
return cr4;
}
@@ -121,7 +118,7 @@ static inline void write_cr4(unsigned long val)
static inline unsigned long read_cr8(void)
{
unsigned long cr8;
- asm("movq %%cr8,%0" : "=r" (cr8));
+ asm volatile("movq %%cr8,%0" : "=r" (cr8));
return cr8;
}
@@ -137,6 +134,11 @@ static inline void write_cr8(unsigned long val)
#endif /* __KERNEL__ */
+static inline void clflush(volatile void *__p)
+{
+ asm volatile("clflush %0" : "+m" (*(char __force *)__p));
+}
+
#define nop() __asm__ __volatile__ ("nop")
#ifdef CONFIG_SMP
diff --git a/include/asm-x86/termbits.h b/include/asm-x86/termbits.h
index 69f3080e2a1d..af1b70ea440f 100644
--- a/include/asm-x86/termbits.h
+++ b/include/asm-x86/termbits.h
@@ -1,13 +1,198 @@
-#ifdef __KERNEL__
-# ifdef CONFIG_X86_32
-# include "termbits_32.h"
-# else
-# include "termbits_64.h"
-# endif
-#else
-# ifdef __i386__
-# include "termbits_32.h"
-# else
-# include "termbits_64.h"
-# endif
-#endif
+#ifndef _ASM_X86_TERMBITS_H
+#define _ASM_X86_TERMBITS_H
+
+#include <linux/posix_types.h>
+
+typedef unsigned char cc_t;
+typedef unsigned int speed_t;
+typedef unsigned int tcflag_t;
+
+#define NCCS 19
+struct termios {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[NCCS]; /* control characters */
+};
+
+struct termios2 {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[NCCS]; /* control characters */
+ speed_t c_ispeed; /* input speed */
+ speed_t c_ospeed; /* output speed */
+};
+
+struct ktermios {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[NCCS]; /* control characters */
+ speed_t c_ispeed; /* input speed */
+ speed_t c_ospeed; /* output speed */
+};
+
+/* c_cc characters */
+#define VINTR 0
+#define VQUIT 1
+#define VERASE 2
+#define VKILL 3
+#define VEOF 4
+#define VTIME 5
+#define VMIN 6
+#define VSWTC 7
+#define VSTART 8
+#define VSTOP 9
+#define VSUSP 10
+#define VEOL 11
+#define VREPRINT 12
+#define VDISCARD 13
+#define VWERASE 14
+#define VLNEXT 15
+#define VEOL2 16
+
+/* c_iflag bits */
+#define IGNBRK 0000001
+#define BRKINT 0000002
+#define IGNPAR 0000004
+#define PARMRK 0000010
+#define INPCK 0000020
+#define ISTRIP 0000040
+#define INLCR 0000100
+#define IGNCR 0000200
+#define ICRNL 0000400
+#define IUCLC 0001000
+#define IXON 0002000
+#define IXANY 0004000
+#define IXOFF 0010000
+#define IMAXBEL 0020000
+#define IUTF8 0040000
+
+/* c_oflag bits */
+#define OPOST 0000001
+#define OLCUC 0000002
+#define ONLCR 0000004
+#define OCRNL 0000010
+#define ONOCR 0000020
+#define ONLRET 0000040
+#define OFILL 0000100
+#define OFDEL 0000200
+#define NLDLY 0000400
+#define NL0 0000000
+#define NL1 0000400
+#define CRDLY 0003000
+#define CR0 0000000
+#define CR1 0001000
+#define CR2 0002000
+#define CR3 0003000
+#define TABDLY 0014000
+#define TAB0 0000000
+#define TAB1 0004000
+#define TAB2 0010000
+#define TAB3 0014000
+#define XTABS 0014000
+#define BSDLY 0020000
+#define BS0 0000000
+#define BS1 0020000
+#define VTDLY 0040000
+#define VT0 0000000
+#define VT1 0040000
+#define FFDLY 0100000
+#define FF0 0000000
+#define FF1 0100000
+
+/* c_cflag bit meaning */
+#define CBAUD 0010017
+#define B0 0000000 /* hang up */
+#define B50 0000001
+#define B75 0000002
+#define B110 0000003
+#define B134 0000004
+#define B150 0000005
+#define B200 0000006
+#define B300 0000007
+#define B600 0000010
+#define B1200 0000011
+#define B1800 0000012
+#define B2400 0000013
+#define B4800 0000014
+#define B9600 0000015
+#define B19200 0000016
+#define B38400 0000017
+#define EXTA B19200
+#define EXTB B38400
+#define CSIZE 0000060
+#define CS5 0000000
+#define CS6 0000020
+#define CS7 0000040
+#define CS8 0000060
+#define CSTOPB 0000100
+#define CREAD 0000200
+#define PARENB 0000400
+#define PARODD 0001000
+#define HUPCL 0002000
+#define CLOCAL 0004000
+#define CBAUDEX 0010000
+#define BOTHER 0010000 /* non standard rate */
+#define B57600 0010001
+#define B115200 0010002
+#define B230400 0010003
+#define B460800 0010004
+#define B500000 0010005
+#define B576000 0010006
+#define B921600 0010007
+#define B1000000 0010010
+#define B1152000 0010011
+#define B1500000 0010012
+#define B2000000 0010013
+#define B2500000 0010014
+#define B3000000 0010015
+#define B3500000 0010016
+#define B4000000 0010017
+#define CIBAUD 002003600000 /* input baud rate */
+#define CMSPAR 010000000000 /* mark or space (stick) parity */
+#define CRTSCTS 020000000000 /* flow control */
+
+#define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */
+
+/* c_lflag bits */
+#define ISIG 0000001
+#define ICANON 0000002
+#define XCASE 0000004
+#define ECHO 0000010
+#define ECHOE 0000020
+#define ECHOK 0000040
+#define ECHONL 0000100
+#define NOFLSH 0000200
+#define TOSTOP 0000400
+#define ECHOCTL 0001000
+#define ECHOPRT 0002000
+#define ECHOKE 0004000
+#define FLUSHO 0010000
+#define PENDIN 0040000
+#define IEXTEN 0100000
+
+/* tcflow() and TCXONC use these */
+#define TCOOFF 0
+#define TCOON 1
+#define TCIOFF 2
+#define TCION 3
+
+/* tcflush() and TCFLSH use these */
+#define TCIFLUSH 0
+#define TCOFLUSH 1
+#define TCIOFLUSH 2
+
+/* tcsetattr uses these */
+#define TCSANOW 0
+#define TCSADRAIN 1
+#define TCSAFLUSH 2
+
+#endif /* _ASM_X86_TERMBITS_H */
diff --git a/include/asm-x86/termbits_32.h b/include/asm-x86/termbits_32.h
deleted file mode 100644
index a21700352e7b..000000000000
--- a/include/asm-x86/termbits_32.h
+++ /dev/null
@@ -1,198 +0,0 @@
-#ifndef __ARCH_I386_TERMBITS_H__
-#define __ARCH_I386_TERMBITS_H__
-
-#include <linux/posix_types.h>
-
-typedef unsigned char cc_t;
-typedef unsigned int speed_t;
-typedef unsigned int tcflag_t;
-
-#define NCCS 19
-struct termios {
- tcflag_t c_iflag; /* input mode flags */
- tcflag_t c_oflag; /* output mode flags */
- tcflag_t c_cflag; /* control mode flags */
- tcflag_t c_lflag; /* local mode flags */
- cc_t c_line; /* line discipline */
- cc_t c_cc[NCCS]; /* control characters */
-};
-
-struct termios2 {
- tcflag_t c_iflag; /* input mode flags */
- tcflag_t c_oflag; /* output mode flags */
- tcflag_t c_cflag; /* control mode flags */
- tcflag_t c_lflag; /* local mode flags */
- cc_t c_line; /* line discipline */
- cc_t c_cc[NCCS]; /* control characters */
- speed_t c_ispeed; /* input speed */
- speed_t c_ospeed; /* output speed */
-};
-
-struct ktermios {
- tcflag_t c_iflag; /* input mode flags */
- tcflag_t c_oflag; /* output mode flags */
- tcflag_t c_cflag; /* control mode flags */
- tcflag_t c_lflag; /* local mode flags */
- cc_t c_line; /* line discipline */
- cc_t c_cc[NCCS]; /* control characters */
- speed_t c_ispeed; /* input speed */
- speed_t c_ospeed; /* output speed */
-};
-
-/* c_cc characters */
-#define VINTR 0
-#define VQUIT 1
-#define VERASE 2
-#define VKILL 3
-#define VEOF 4
-#define VTIME 5
-#define VMIN 6
-#define VSWTC 7
-#define VSTART 8
-#define VSTOP 9
-#define VSUSP 10
-#define VEOL 11
-#define VREPRINT 12
-#define VDISCARD 13
-#define VWERASE 14
-#define VLNEXT 15
-#define VEOL2 16
-
-/* c_iflag bits */
-#define IGNBRK 0000001
-#define BRKINT 0000002
-#define IGNPAR 0000004
-#define PARMRK 0000010
-#define INPCK 0000020
-#define ISTRIP 0000040
-#define INLCR 0000100
-#define IGNCR 0000200
-#define ICRNL 0000400
-#define IUCLC 0001000
-#define IXON 0002000
-#define IXANY 0004000
-#define IXOFF 0010000
-#define IMAXBEL 0020000
-#define IUTF8 0040000
-
-/* c_oflag bits */
-#define OPOST 0000001
-#define OLCUC 0000002
-#define ONLCR 0000004
-#define OCRNL 0000010
-#define ONOCR 0000020
-#define ONLRET 0000040
-#define OFILL 0000100
-#define OFDEL 0000200
-#define NLDLY 0000400
-#define NL0 0000000
-#define NL1 0000400
-#define CRDLY 0003000
-#define CR0 0000000
-#define CR1 0001000
-#define CR2 0002000
-#define CR3 0003000
-#define TABDLY 0014000
-#define TAB0 0000000
-#define TAB1 0004000
-#define TAB2 0010000
-#define TAB3 0014000
-#define XTABS 0014000
-#define BSDLY 0020000
-#define BS0 0000000
-#define BS1 0020000
-#define VTDLY 0040000
-#define VT0 0000000
-#define VT1 0040000
-#define FFDLY 0100000
-#define FF0 0000000
-#define FF1 0100000
-
-/* c_cflag bit meaning */
-#define CBAUD 0010017
-#define B0 0000000 /* hang up */
-#define B50 0000001
-#define B75 0000002
-#define B110 0000003
-#define B134 0000004
-#define B150 0000005
-#define B200 0000006
-#define B300 0000007
-#define B600 0000010
-#define B1200 0000011
-#define B1800 0000012
-#define B2400 0000013
-#define B4800 0000014
-#define B9600 0000015
-#define B19200 0000016
-#define B38400 0000017
-#define EXTA B19200
-#define EXTB B38400
-#define CSIZE 0000060
-#define CS5 0000000
-#define CS6 0000020
-#define CS7 0000040
-#define CS8 0000060
-#define CSTOPB 0000100
-#define CREAD 0000200
-#define PARENB 0000400
-#define PARODD 0001000
-#define HUPCL 0002000
-#define CLOCAL 0004000
-#define CBAUDEX 0010000
-#define BOTHER 0010000
-#define B57600 0010001
-#define B115200 0010002
-#define B230400 0010003
-#define B460800 0010004
-#define B500000 0010005
-#define B576000 0010006
-#define B921600 0010007
-#define B1000000 0010010
-#define B1152000 0010011
-#define B1500000 0010012
-#define B2000000 0010013
-#define B2500000 0010014
-#define B3000000 0010015
-#define B3500000 0010016
-#define B4000000 0010017
-#define CIBAUD 002003600000
-#define CMSPAR 010000000000 /* mark or space (stick) parity */
-#define CRTSCTS 020000000000 /* flow control */
-
-#define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */
-
-/* c_lflag bits */
-#define ISIG 0000001
-#define ICANON 0000002
-#define XCASE 0000004
-#define ECHO 0000010
-#define ECHOE 0000020
-#define ECHOK 0000040
-#define ECHONL 0000100
-#define NOFLSH 0000200
-#define TOSTOP 0000400
-#define ECHOCTL 0001000
-#define ECHOPRT 0002000
-#define ECHOKE 0004000
-#define FLUSHO 0010000
-#define PENDIN 0040000
-#define IEXTEN 0100000
-
-/* tcflow() and TCXONC use these */
-#define TCOOFF 0
-#define TCOON 1
-#define TCIOFF 2
-#define TCION 3
-
-/* tcflush() and TCFLSH use these */
-#define TCIFLUSH 0
-#define TCOFLUSH 1
-#define TCIOFLUSH 2
-
-/* tcsetattr uses these */
-#define TCSANOW 0
-#define TCSADRAIN 1
-#define TCSAFLUSH 2
-
-#endif
diff --git a/include/asm-x86/termbits_64.h b/include/asm-x86/termbits_64.h
deleted file mode 100644
index 7405756dd41b..000000000000
--- a/include/asm-x86/termbits_64.h
+++ /dev/null
@@ -1,198 +0,0 @@
-#ifndef __ARCH_X8664_TERMBITS_H__
-#define __ARCH_X8664_TERMBITS_H__
-
-#include <linux/posix_types.h>
-
-typedef unsigned char cc_t;
-typedef unsigned int speed_t;
-typedef unsigned int tcflag_t;
-
-#define NCCS 19
-struct termios {
- tcflag_t c_iflag; /* input mode flags */
- tcflag_t c_oflag; /* output mode flags */
- tcflag_t c_cflag; /* control mode flags */
- tcflag_t c_lflag; /* local mode flags */
- cc_t c_line; /* line discipline */
- cc_t c_cc[NCCS]; /* control characters */
-};
-
-struct termios2 {
- tcflag_t c_iflag; /* input mode flags */
- tcflag_t c_oflag; /* output mode flags */
- tcflag_t c_cflag; /* control mode flags */
- tcflag_t c_lflag; /* local mode flags */
- cc_t c_line; /* line discipline */
- cc_t c_cc[NCCS]; /* control characters */
- speed_t c_ispeed; /* input speed */
- speed_t c_ospeed; /* output speed */
-};
-
-struct ktermios {
- tcflag_t c_iflag; /* input mode flags */
- tcflag_t c_oflag; /* output mode flags */
- tcflag_t c_cflag; /* control mode flags */
- tcflag_t c_lflag; /* local mode flags */
- cc_t c_line; /* line discipline */
- cc_t c_cc[NCCS]; /* control characters */
- speed_t c_ispeed; /* input speed */
- speed_t c_ospeed; /* output speed */
-};
-
-/* c_cc characters */
-#define VINTR 0
-#define VQUIT 1
-#define VERASE 2
-#define VKILL 3
-#define VEOF 4
-#define VTIME 5
-#define VMIN 6
-#define VSWTC 7
-#define VSTART 8
-#define VSTOP 9
-#define VSUSP 10
-#define VEOL 11
-#define VREPRINT 12
-#define VDISCARD 13
-#define VWERASE 14
-#define VLNEXT 15
-#define VEOL2 16
-
-/* c_iflag bits */
-#define IGNBRK 0000001
-#define BRKINT 0000002
-#define IGNPAR 0000004
-#define PARMRK 0000010
-#define INPCK 0000020
-#define ISTRIP 0000040
-#define INLCR 0000100
-#define IGNCR 0000200
-#define ICRNL 0000400
-#define IUCLC 0001000
-#define IXON 0002000
-#define IXANY 0004000
-#define IXOFF 0010000
-#define IMAXBEL 0020000
-#define IUTF8 0040000
-
-/* c_oflag bits */
-#define OPOST 0000001
-#define OLCUC 0000002
-#define ONLCR 0000004
-#define OCRNL 0000010
-#define ONOCR 0000020
-#define ONLRET 0000040
-#define OFILL 0000100
-#define OFDEL 0000200
-#define NLDLY 0000400
-#define NL0 0000000
-#define NL1 0000400
-#define CRDLY 0003000
-#define CR0 0000000
-#define CR1 0001000
-#define CR2 0002000
-#define CR3 0003000
-#define TABDLY 0014000
-#define TAB0 0000000
-#define TAB1 0004000
-#define TAB2 0010000
-#define TAB3 0014000
-#define XTABS 0014000
-#define BSDLY 0020000
-#define BS0 0000000
-#define BS1 0020000
-#define VTDLY 0040000
-#define VT0 0000000
-#define VT1 0040000
-#define FFDLY 0100000
-#define FF0 0000000
-#define FF1 0100000
-
-/* c_cflag bit meaning */
-#define CBAUD 0010017
-#define B0 0000000 /* hang up */
-#define B50 0000001
-#define B75 0000002
-#define B110 0000003
-#define B134 0000004
-#define B150 0000005
-#define B200 0000006
-#define B300 0000007
-#define B600 0000010
-#define B1200 0000011
-#define B1800 0000012
-#define B2400 0000013
-#define B4800 0000014
-#define B9600 0000015
-#define B19200 0000016
-#define B38400 0000017
-#define EXTA B19200
-#define EXTB B38400
-#define CSIZE 0000060
-#define CS5 0000000
-#define CS6 0000020
-#define CS7 0000040
-#define CS8 0000060
-#define CSTOPB 0000100
-#define CREAD 0000200
-#define PARENB 0000400
-#define PARODD 0001000
-#define HUPCL 0002000
-#define CLOCAL 0004000
-#define CBAUDEX 0010000
-#define BOTHER 0010000 /* non standard rate */
-#define B57600 0010001
-#define B115200 0010002
-#define B230400 0010003
-#define B460800 0010004
-#define B500000 0010005
-#define B576000 0010006
-#define B921600 0010007
-#define B1000000 0010010
-#define B1152000 0010011
-#define B1500000 0010012
-#define B2000000 0010013
-#define B2500000 0010014
-#define B3000000 0010015
-#define B3500000 0010016
-#define B4000000 0010017
-#define CIBAUD 002003600000 /* input baud rate */
-#define CMSPAR 010000000000 /* mark or space (stick) parity */
-#define CRTSCTS 020000000000 /* flow control */
-
-#define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */
-
-/* c_lflag bits */
-#define ISIG 0000001
-#define ICANON 0000002
-#define XCASE 0000004
-#define ECHO 0000010
-#define ECHOE 0000020
-#define ECHOK 0000040
-#define ECHONL 0000100
-#define NOFLSH 0000200
-#define TOSTOP 0000400
-#define ECHOCTL 0001000
-#define ECHOPRT 0002000
-#define ECHOKE 0004000
-#define FLUSHO 0010000
-#define PENDIN 0040000
-#define IEXTEN 0100000
-
-/* tcflow() and TCXONC use these */
-#define TCOOFF 0
-#define TCOON 1
-#define TCIOFF 2
-#define TCION 3
-
-/* tcflush() and TCFLSH use these */
-#define TCIFLUSH 0
-#define TCOFLUSH 1
-#define TCIOFLUSH 2
-
-/* tcsetattr uses these */
-#define TCSANOW 0
-#define TCSADRAIN 1
-#define TCSAFLUSH 2
-
-#endif
diff --git a/include/asm-x86/termios.h b/include/asm-x86/termios.h
index a4f4ae20a591..d501748700d2 100644
--- a/include/asm-x86/termios.h
+++ b/include/asm-x86/termios.h
@@ -1,13 +1,97 @@
+#ifndef _ASM_X86_TERMIOS_H
+#define _ASM_X86_TERMIOS_H
+
+#include <asm/termbits.h>
+#include <asm/ioctls.h>
+
+struct winsize {
+ unsigned short ws_row;
+ unsigned short ws_col;
+ unsigned short ws_xpixel;
+ unsigned short ws_ypixel;
+};
+
+#define NCC 8
+struct termio {
+ unsigned short c_iflag; /* input mode flags */
+ unsigned short c_oflag; /* output mode flags */
+ unsigned short c_cflag; /* control mode flags */
+ unsigned short c_lflag; /* local mode flags */
+ unsigned char c_line; /* line discipline */
+ unsigned char c_cc[NCC]; /* control characters */
+};
+
+/* modem lines */
+#define TIOCM_LE 0x001
+#define TIOCM_DTR 0x002
+#define TIOCM_RTS 0x004
+#define TIOCM_ST 0x008
+#define TIOCM_SR 0x010
+#define TIOCM_CTS 0x020
+#define TIOCM_CAR 0x040
+#define TIOCM_RNG 0x080
+#define TIOCM_DSR 0x100
+#define TIOCM_CD TIOCM_CAR
+#define TIOCM_RI TIOCM_RNG
+#define TIOCM_OUT1 0x2000
+#define TIOCM_OUT2 0x4000
+#define TIOCM_LOOP 0x8000
+
+/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+
#ifdef __KERNEL__
-# ifdef CONFIG_X86_32
-# include "termios_32.h"
-# else
-# include "termios_64.h"
-# endif
-#else
-# ifdef __i386__
-# include "termios_32.h"
-# else
-# include "termios_64.h"
-# endif
-#endif
+
+/* intr=^C quit=^\ erase=del kill=^U
+ eof=^D vtime=\0 vmin=\1 sxtc=\0
+ start=^Q stop=^S susp=^Z eol=\0
+ reprint=^R discard=^U werase=^W lnext=^V
+ eol2=\0
+*/
+#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
+
+/*
+ * Translate a "termio" structure into a "termios". Ugh.
+ */
+#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \
+ unsigned short __tmp; \
+ get_user(__tmp,&(termio)->x); \
+ *(unsigned short *) &(termios)->x = __tmp; \
+}
+
+#define user_termio_to_kernel_termios(termios, termio) \
+({ \
+ SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \
+ SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \
+ SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \
+ SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \
+ copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
+})
+
+/*
+ * Translate a "termios" structure into a "termio". Ugh.
+ */
+#define kernel_termios_to_user_termio(termio, termios) \
+({ \
+ put_user((termios)->c_iflag, &(termio)->c_iflag); \
+ put_user((termios)->c_oflag, &(termio)->c_oflag); \
+ put_user((termios)->c_cflag, &(termio)->c_cflag); \
+ put_user((termios)->c_lflag, &(termio)->c_lflag); \
+ put_user((termios)->c_line, &(termio)->c_line); \
+ copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
+})
+
+#define user_termios_to_kernel_termios(k, u) \
+ copy_from_user(k, u, sizeof(struct termios2))
+
+#define kernel_termios_to_user_termios(u, k) \
+ copy_to_user(u, k, sizeof(struct termios2))
+
+#define user_termios_to_kernel_termios_1(k, u) \
+ copy_from_user(k, u, sizeof(struct termios))
+
+#define kernel_termios_to_user_termios_1(u, k) \
+ copy_to_user(u, k, sizeof(struct termios))
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_X86_TERMIOS_H */
diff --git a/include/asm-x86/termios_32.h b/include/asm-x86/termios_32.h
deleted file mode 100644
index 6fdb2c841b73..000000000000
--- a/include/asm-x86/termios_32.h
+++ /dev/null
@@ -1,90 +0,0 @@
-#ifndef _I386_TERMIOS_H
-#define _I386_TERMIOS_H
-
-#include <asm/termbits.h>
-#include <asm/ioctls.h>
-
-struct winsize {
- unsigned short ws_row;
- unsigned short ws_col;
- unsigned short ws_xpixel;
- unsigned short ws_ypixel;
-};
-
-#define NCC 8
-struct termio {
- unsigned short c_iflag; /* input mode flags */
- unsigned short c_oflag; /* output mode flags */
- unsigned short c_cflag; /* control mode flags */
- unsigned short c_lflag; /* local mode flags */
- unsigned char c_line; /* line discipline */
- unsigned char c_cc[NCC]; /* control characters */
-};
-
-/* modem lines */
-#define TIOCM_LE 0x001
-#define TIOCM_DTR 0x002
-#define TIOCM_RTS 0x004
-#define TIOCM_ST 0x008
-#define TIOCM_SR 0x010
-#define TIOCM_CTS 0x020
-#define TIOCM_CAR 0x040
-#define TIOCM_RNG 0x080
-#define TIOCM_DSR 0x100
-#define TIOCM_CD TIOCM_CAR
-#define TIOCM_RI TIOCM_RNG
-#define TIOCM_OUT1 0x2000
-#define TIOCM_OUT2 0x4000
-#define TIOCM_LOOP 0x8000
-
-/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
-
-#ifdef __KERNEL__
-
-/* intr=^C quit=^\ erase=del kill=^U
- eof=^D vtime=\0 vmin=\1 sxtc=\0
- start=^Q stop=^S susp=^Z eol=\0
- reprint=^R discard=^U werase=^W lnext=^V
- eol2=\0
-*/
-#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
-
-/*
- * Translate a "termio" structure into a "termios". Ugh.
- */
-#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \
- unsigned short __tmp; \
- get_user(__tmp,&(termio)->x); \
- *(unsigned short *) &(termios)->x = __tmp; \
-}
-
-#define user_termio_to_kernel_termios(termios, termio) \
-({ \
- SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \
- SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \
- SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \
- SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \
- copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
-})
-
-/*
- * Translate a "termios" structure into a "termio". Ugh.
- */
-#define kernel_termios_to_user_termio(termio, termios) \
-({ \
- put_user((termios)->c_iflag, &(termio)->c_iflag); \
- put_user((termios)->c_oflag, &(termio)->c_oflag); \
- put_user((termios)->c_cflag, &(termio)->c_cflag); \
- put_user((termios)->c_lflag, &(termio)->c_lflag); \
- put_user((termios)->c_line, &(termio)->c_line); \
- copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
-})
-
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
-#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
-
-#endif /* __KERNEL__ */
-
-#endif /* _I386_TERMIOS_H */
diff --git a/include/asm-x86/termios_64.h b/include/asm-x86/termios_64.h
deleted file mode 100644
index 35ee59b78329..000000000000
--- a/include/asm-x86/termios_64.h
+++ /dev/null
@@ -1,90 +0,0 @@
-#ifndef _X8664_TERMIOS_H
-#define _X8664_TERMIOS_H
-
-#include <asm/termbits.h>
-#include <asm/ioctls.h>
-
-struct winsize {
- unsigned short ws_row;
- unsigned short ws_col;
- unsigned short ws_xpixel;
- unsigned short ws_ypixel;
-};
-
-#define NCC 8
-struct termio {
- unsigned short c_iflag; /* input mode flags */
- unsigned short c_oflag; /* output mode flags */
- unsigned short c_cflag; /* control mode flags */
- unsigned short c_lflag; /* local mode flags */
- unsigned char c_line; /* line discipline */
- unsigned char c_cc[NCC]; /* control characters */
-};
-
-/* modem lines */
-#define TIOCM_LE 0x001
-#define TIOCM_DTR 0x002
-#define TIOCM_RTS 0x004
-#define TIOCM_ST 0x008
-#define TIOCM_SR 0x010
-#define TIOCM_CTS 0x020
-#define TIOCM_CAR 0x040
-#define TIOCM_RNG 0x080
-#define TIOCM_DSR 0x100
-#define TIOCM_CD TIOCM_CAR
-#define TIOCM_RI TIOCM_RNG
-#define TIOCM_OUT1 0x2000
-#define TIOCM_OUT2 0x4000
-#define TIOCM_LOOP 0x8000
-
-/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
-
-#ifdef __KERNEL__
-
-/* intr=^C quit=^\ erase=del kill=^U
- eof=^D vtime=\0 vmin=\1 sxtc=\0
- start=^Q stop=^S susp=^Z eol=\0
- reprint=^R discard=^U werase=^W lnext=^V
- eol2=\0
-*/
-#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
-
-/*
- * Translate a "termio" structure into a "termios". Ugh.
- */
-#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \
- unsigned short __tmp; \
- get_user(__tmp,&(termio)->x); \
- *(unsigned short *) &(termios)->x = __tmp; \
-}
-
-#define user_termio_to_kernel_termios(termios, termio) \
-({ \
- SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \
- SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \
- SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \
- SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \
- copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
-})
-
-/*
- * Translate a "termios" structure into a "termio". Ugh.
- */
-#define kernel_termios_to_user_termio(termio, termios) \
-({ \
- put_user((termios)->c_iflag, &(termio)->c_iflag); \
- put_user((termios)->c_oflag, &(termio)->c_oflag); \
- put_user((termios)->c_cflag, &(termio)->c_cflag); \
- put_user((termios)->c_lflag, &(termio)->c_lflag); \
- put_user((termios)->c_line, &(termio)->c_line); \
- copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
-})
-
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
-#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
-
-#endif /* __KERNEL__ */
-
-#endif /* _X8664_TERMIOS_H */
diff --git a/include/asm-x86/tlb.h b/include/asm-x86/tlb.h
index 7d55c3762b43..e4e9e2d07a93 100644
--- a/include/asm-x86/tlb.h
+++ b/include/asm-x86/tlb.h
@@ -1,5 +1,11 @@
-#ifdef CONFIG_X86_32
-# include "tlb_32.h"
-#else
-# include "tlb_64.h"
+#ifndef _ASM_X86_TLB_H
+#define _ASM_X86_TLB_H
+
+#define tlb_start_vma(tlb, vma) do { } while (0)
+#define tlb_end_vma(tlb, vma) do { } while (0)
+#define __tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0)
+#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm)
+
+#include <asm-generic/tlb.h>
+
#endif
diff --git a/include/asm-x86/tlb_32.h b/include/asm-x86/tlb_32.h
deleted file mode 100644
index c006c5c92bea..000000000000
--- a/include/asm-x86/tlb_32.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef _I386_TLB_H
-#define _I386_TLB_H
-
-/*
- * x86 doesn't need any special per-pte or
- * per-vma handling..
- */
-#define tlb_start_vma(tlb, vma) do { } while (0)
-#define tlb_end_vma(tlb, vma) do { } while (0)
-#define __tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0)
-
-/*
- * .. because we flush the whole mm when it
- * fills up.
- */
-#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm)
-
-#include <asm-generic/tlb.h>
-
-#endif
diff --git a/include/asm-x86/tlb_64.h b/include/asm-x86/tlb_64.h
deleted file mode 100644
index cd4c3c590a0e..000000000000
--- a/include/asm-x86/tlb_64.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef TLB_H
-#define TLB_H 1
-
-
-#define tlb_start_vma(tlb, vma) do { } while (0)
-#define tlb_end_vma(tlb, vma) do { } while (0)
-#define __tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0)
-
-#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm)
-
-#include <asm-generic/tlb.h>
-
-#endif
diff --git a/include/asm-x86/tlbflush_32.h b/include/asm-x86/tlbflush_32.h
index a50fa6741486..2bd5b95e2048 100644
--- a/include/asm-x86/tlbflush_32.h
+++ b/include/asm-x86/tlbflush_32.h
@@ -78,7 +78,6 @@
* - flush_tlb_page(vma, vmaddr) flushes one page
* - flush_tlb_range(vma, start, end) flushes a range of pages
* - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
- * - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
* - flush_tlb_others(cpumask, mm, va) flushes a TLBs on other cpus
*
* ..but the i386 has somewhat limited tlb flushing capabilities,
@@ -166,10 +165,4 @@ static inline void flush_tlb_kernel_range(unsigned long start,
flush_tlb_all();
}
-static inline void flush_tlb_pgtables(struct mm_struct *mm,
- unsigned long start, unsigned long end)
-{
- /* i386 does not keep any page table caches in TLB */
-}
-
#endif /* _I386_TLBFLUSH_H */
diff --git a/include/asm-x86/tlbflush_64.h b/include/asm-x86/tlbflush_64.h
index 888eb4abdd07..7731fd23d572 100644
--- a/include/asm-x86/tlbflush_64.h
+++ b/include/asm-x86/tlbflush_64.h
@@ -31,7 +31,6 @@ static inline void __flush_tlb_all(void)
* - flush_tlb_page(vma, vmaddr) flushes one page
* - flush_tlb_range(vma, start, end) flushes a range of pages
* - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
- * - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
*
* x86-64 can only flush individual pages or full VMs. For a range flush
* we always do the full VM. Might be worth trying if for a small
@@ -98,12 +97,4 @@ static inline void flush_tlb_kernel_range(unsigned long start,
flush_tlb_all();
}
-static inline void flush_tlb_pgtables(struct mm_struct *mm,
- unsigned long start, unsigned long end)
-{
- /* x86_64 does not keep any page table caches in a software TLB.
- The CPUs do in their hardware TLBs, but they are handled
- by the normal TLB flushing algorithms. */
-}
-
#endif /* _X8664_TLBFLUSH_H */
diff --git a/include/asm-x86/topology_32.h b/include/asm-x86/topology_32.h
index 19b2dafd0c81..9040f5a61278 100644
--- a/include/asm-x86/topology_32.h
+++ b/include/asm-x86/topology_32.h
@@ -28,10 +28,10 @@
#define _ASM_I386_TOPOLOGY_H
#ifdef CONFIG_X86_HT
-#define topology_physical_package_id(cpu) (cpu_data[cpu].phys_proc_id)
-#define topology_core_id(cpu) (cpu_data[cpu].cpu_core_id)
-#define topology_core_siblings(cpu) (cpu_core_map[cpu])
-#define topology_thread_siblings(cpu) (cpu_sibling_map[cpu])
+#define topology_physical_package_id(cpu) (cpu_data(cpu).phys_proc_id)
+#define topology_core_id(cpu) (cpu_data(cpu).cpu_core_id)
+#define topology_core_siblings(cpu) (per_cpu(cpu_core_map, cpu))
+#define topology_thread_siblings(cpu) (per_cpu(cpu_sibling_map, cpu))
#endif
#ifdef CONFIG_NUMA
diff --git a/include/asm-x86/topology_64.h b/include/asm-x86/topology_64.h
index 36e52fba7960..a718dda037e0 100644
--- a/include/asm-x86/topology_64.h
+++ b/include/asm-x86/topology_64.h
@@ -5,7 +5,7 @@
#ifdef CONFIG_NUMA
#include <asm/mpspec.h>
-#include <asm/bitops.h>
+#include <linux/bitops.h>
extern cpumask_t cpu_online_map;
@@ -56,10 +56,10 @@ extern int __node_distance(int, int);
#endif
#ifdef CONFIG_SMP
-#define topology_physical_package_id(cpu) (cpu_data[cpu].phys_proc_id)
-#define topology_core_id(cpu) (cpu_data[cpu].cpu_core_id)
-#define topology_core_siblings(cpu) (cpu_core_map[cpu])
-#define topology_thread_siblings(cpu) (cpu_sibling_map[cpu])
+#define topology_physical_package_id(cpu) (cpu_data(cpu).phys_proc_id)
+#define topology_core_id(cpu) (cpu_data(cpu).cpu_core_id)
+#define topology_core_siblings(cpu) (per_cpu(cpu_core_map, cpu))
+#define topology_thread_siblings(cpu) (per_cpu(cpu_sibling_map, cpu))
#define mc_capable() (boot_cpu_data.x86_max_cores > 1)
#define smt_capable() (smp_num_siblings > 1)
#endif
diff --git a/include/asm-x86/types.h b/include/asm-x86/types.h
index a777a9b83974..63733f315688 100644
--- a/include/asm-x86/types.h
+++ b/include/asm-x86/types.h
@@ -1,13 +1,70 @@
-#ifdef __KERNEL__
-# ifdef CONFIG_X86_32
-# include "types_32.h"
-# else
-# include "types_64.h"
+#ifndef _ASM_X86_TYPES_H
+#define _ASM_X86_TYPES_H
+
+#ifndef __ASSEMBLY__
+
+typedef unsigned short umode_t;
+
+/*
+ * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
+ * header files exported to user space
+ */
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+#ifdef __i386__
+# ifdef __GNUC__
+__extension__ typedef __signed__ long long __s64;
+__extension__ typedef unsigned long long __u64;
# endif
#else
-# ifdef __i386__
-# include "types_32.h"
-# else
-# include "types_64.h"
-# endif
+typedef __signed__ long long __s64;
+typedef unsigned long long __u64;
+#endif
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * These aren't exported outside the kernel to avoid name space clashes
+ */
+#ifdef __KERNEL__
+
+#ifdef CONFIG_X86_32
+# define BITS_PER_LONG 32
+#else
+# define BITS_PER_LONG 64
+#endif
+
+#ifndef __ASSEMBLY__
+
+typedef signed char s8;
+typedef unsigned char u8;
+
+typedef signed short s16;
+typedef unsigned short u16;
+
+typedef signed int s32;
+typedef unsigned int u32;
+
+typedef signed long long s64;
+typedef unsigned long long u64;
+
+typedef u64 dma64_addr_t;
+#if defined(CONFIG_X86_64) || defined(CONFIG_HIGHMEM64G)
+/* DMA addresses come in 32-bit and 64-bit flavours. */
+typedef u64 dma_addr_t;
+#else
+typedef u32 dma_addr_t;
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __KERNEL__ */
+
#endif
diff --git a/include/asm-x86/types_32.h b/include/asm-x86/types_32.h
deleted file mode 100644
index ad0a55bd782f..000000000000
--- a/include/asm-x86/types_32.h
+++ /dev/null
@@ -1,64 +0,0 @@
-#ifndef _I386_TYPES_H
-#define _I386_TYPES_H
-
-#ifndef __ASSEMBLY__
-
-typedef unsigned short umode_t;
-
-/*
- * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
- * header files exported to user space
- */
-
-typedef __signed__ char __s8;
-typedef unsigned char __u8;
-
-typedef __signed__ short __s16;
-typedef unsigned short __u16;
-
-typedef __signed__ int __s32;
-typedef unsigned int __u32;
-
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
-typedef __signed__ long long __s64;
-typedef unsigned long long __u64;
-#endif
-
-#endif /* __ASSEMBLY__ */
-
-/*
- * These aren't exported outside the kernel to avoid name space clashes
- */
-#ifdef __KERNEL__
-
-#define BITS_PER_LONG 32
-
-#ifndef __ASSEMBLY__
-
-
-typedef signed char s8;
-typedef unsigned char u8;
-
-typedef signed short s16;
-typedef unsigned short u16;
-
-typedef signed int s32;
-typedef unsigned int u32;
-
-typedef signed long long s64;
-typedef unsigned long long u64;
-
-/* DMA addresses come in generic and 64-bit flavours. */
-
-#ifdef CONFIG_HIGHMEM64G
-typedef u64 dma_addr_t;
-#else
-typedef u32 dma_addr_t;
-#endif
-typedef u64 dma64_addr_t;
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* __KERNEL__ */
-
-#endif
diff --git a/include/asm-x86/types_64.h b/include/asm-x86/types_64.h
deleted file mode 100644
index 2d4491aae281..000000000000
--- a/include/asm-x86/types_64.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef _X86_64_TYPES_H
-#define _X86_64_TYPES_H
-
-#ifndef __ASSEMBLY__
-
-typedef unsigned short umode_t;
-
-/*
- * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
- * header files exported to user space
- */
-
-typedef __signed__ char __s8;
-typedef unsigned char __u8;
-
-typedef __signed__ short __s16;
-typedef unsigned short __u16;
-
-typedef __signed__ int __s32;
-typedef unsigned int __u32;
-
-typedef __signed__ long long __s64;
-typedef unsigned long long __u64;
-
-#endif /* __ASSEMBLY__ */
-
-/*
- * These aren't exported outside the kernel to avoid name space clashes
- */
-#ifdef __KERNEL__
-
-#define BITS_PER_LONG 64
-
-#ifndef __ASSEMBLY__
-
-typedef signed char s8;
-typedef unsigned char u8;
-
-typedef signed short s16;
-typedef unsigned short u16;
-
-typedef signed int s32;
-typedef unsigned int u32;
-
-typedef signed long long s64;
-typedef unsigned long long u64;
-
-typedef u64 dma64_addr_t;
-typedef u64 dma_addr_t;
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* __KERNEL__ */
-
-#endif
diff --git a/include/asm-x86/ucontext.h b/include/asm-x86/ucontext.h
index 175c8cb59731..50a79f7fcde9 100644
--- a/include/asm-x86/ucontext.h
+++ b/include/asm-x86/ucontext.h
@@ -1,13 +1,12 @@
-#ifdef __KERNEL__
-# ifdef CONFIG_X86_32
-# include "ucontext_32.h"
-# else
-# include "ucontext_64.h"
-# endif
-#else
-# ifdef __i386__
-# include "ucontext_32.h"
-# else
-# include "ucontext_64.h"
-# endif
-#endif
+#ifndef _ASM_X86_UCONTEXT_H
+#define _ASM_X86_UCONTEXT_H
+
+struct ucontext {
+ unsigned long uc_flags;
+ struct ucontext *uc_link;
+ stack_t uc_stack;
+ struct sigcontext uc_mcontext;
+ sigset_t uc_sigmask; /* mask last for extensibility */
+};
+
+#endif /* _ASM_X86_UCONTEXT_H */
diff --git a/include/asm-x86/ucontext_32.h b/include/asm-x86/ucontext_32.h
deleted file mode 100644
index b0db36925f55..000000000000
--- a/include/asm-x86/ucontext_32.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _ASMi386_UCONTEXT_H
-#define _ASMi386_UCONTEXT_H
-
-struct ucontext {
- unsigned long uc_flags;
- struct ucontext *uc_link;
- stack_t uc_stack;
- struct sigcontext uc_mcontext;
- sigset_t uc_sigmask; /* mask last for extensibility */
-};
-
-#endif /* !_ASMi386_UCONTEXT_H */
diff --git a/include/asm-x86/ucontext_64.h b/include/asm-x86/ucontext_64.h
deleted file mode 100644
index 159a3da9e112..000000000000
--- a/include/asm-x86/ucontext_64.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _ASMX8664_UCONTEXT_H
-#define _ASMX8664_UCONTEXT_H
-
-struct ucontext {
- unsigned long uc_flags;
- struct ucontext *uc_link;
- stack_t uc_stack;
- struct sigcontext uc_mcontext;
- sigset_t uc_sigmask; /* mask last for extensibility */
-};
-
-#endif
diff --git a/include/asm-x86/unaligned.h b/include/asm-x86/unaligned.h
index 68067150fbcb..913598d4f761 100644
--- a/include/asm-x86/unaligned.h
+++ b/include/asm-x86/unaligned.h
@@ -1,5 +1,37 @@
-#ifdef CONFIG_X86_32
-# include "unaligned_32.h"
-#else
-# include "unaligned_64.h"
-#endif
+#ifndef _ASM_X86_UNALIGNED_H
+#define _ASM_X86_UNALIGNED_H
+
+/*
+ * The x86 can do unaligned accesses itself.
+ *
+ * The strange macros are there to make sure these can't
+ * be misused in a way that makes them not work on other
+ * architectures where unaligned accesses aren't as simple.
+ */
+
+/**
+ * get_unaligned - get value from possibly mis-aligned location
+ * @ptr: pointer to value
+ *
+ * This macro should be used for accessing values larger in size than
+ * single bytes at locations that are expected to be improperly aligned,
+ * e.g. retrieving a u16 value from a location not u16-aligned.
+ *
+ * Note that unaligned accesses can be very expensive on some architectures.
+ */
+#define get_unaligned(ptr) (*(ptr))
+
+/**
+ * put_unaligned - put value to a possibly mis-aligned location
+ * @val: value to place
+ * @ptr: pointer to location
+ *
+ * This macro should be used for placing values larger in size than
+ * single bytes at locations that are expected to be improperly aligned,
+ * e.g. writing a u16 value to a location not u16-aligned.
+ *
+ * Note that unaligned accesses can be very expensive on some architectures.
+ */
+#define put_unaligned(val, ptr) ((void)( *(ptr) = (val) ))
+
+#endif /* _ASM_X86_UNALIGNED_H */
diff --git a/include/asm-x86/unaligned_32.h b/include/asm-x86/unaligned_32.h
deleted file mode 100644
index 7acd7957621e..000000000000
--- a/include/asm-x86/unaligned_32.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef __I386_UNALIGNED_H
-#define __I386_UNALIGNED_H
-
-/*
- * The i386 can do unaligned accesses itself.
- *
- * The strange macros are there to make sure these can't
- * be misused in a way that makes them not work on other
- * architectures where unaligned accesses aren't as simple.
- */
-
-/**
- * get_unaligned - get value from possibly mis-aligned location
- * @ptr: pointer to value
- *
- * This macro should be used for accessing values larger in size than
- * single bytes at locations that are expected to be improperly aligned,
- * e.g. retrieving a u16 value from a location not u16-aligned.
- *
- * Note that unaligned accesses can be very expensive on some architectures.
- */
-#define get_unaligned(ptr) (*(ptr))
-
-/**
- * put_unaligned - put value to a possibly mis-aligned location
- * @val: value to place
- * @ptr: pointer to location
- *
- * This macro should be used for placing values larger in size than
- * single bytes at locations that are expected to be improperly aligned,
- * e.g. writing a u16 value to a location not u16-aligned.
- *
- * Note that unaligned accesses can be very expensive on some architectures.
- */
-#define put_unaligned(val, ptr) ((void)( *(ptr) = (val) ))
-
-#endif
diff --git a/include/asm-x86/unaligned_64.h b/include/asm-x86/unaligned_64.h
deleted file mode 100644
index d4bf78dc6f39..000000000000
--- a/include/asm-x86/unaligned_64.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef __X8664_UNALIGNED_H
-#define __X8664_UNALIGNED_H
-
-/*
- * The x86-64 can do unaligned accesses itself.
- *
- * The strange macros are there to make sure these can't
- * be misused in a way that makes them not work on other
- * architectures where unaligned accesses aren't as simple.
- */
-
-/**
- * get_unaligned - get value from possibly mis-aligned location
- * @ptr: pointer to value
- *
- * This macro should be used for accessing values larger in size than
- * single bytes at locations that are expected to be improperly aligned,
- * e.g. retrieving a u16 value from a location not u16-aligned.
- *
- * Note that unaligned accesses can be very expensive on some architectures.
- */
-#define get_unaligned(ptr) (*(ptr))
-
-/**
- * put_unaligned - put value to a possibly mis-aligned location
- * @val: value to place
- * @ptr: pointer to location
- *
- * This macro should be used for placing values larger in size than
- * single bytes at locations that are expected to be improperly aligned,
- * e.g. writing a u16 value to a location not u16-aligned.
- *
- * Note that unaligned accesses can be very expensive on some architectures.
- */
-#define put_unaligned(val, ptr) ((void)( *(ptr) = (val) ))
-
-#endif
diff --git a/include/asm-x86/unistd_64.h b/include/asm-x86/unistd_64.h
index fc4e73f5f1fa..5ff4d3e24c34 100644
--- a/include/asm-x86/unistd_64.h
+++ b/include/asm-x86/unistd_64.h
@@ -2,635 +2,638 @@
#define _ASM_X86_64_UNISTD_H_
#ifndef __SYSCALL
-#define __SYSCALL(a,b)
+#define __SYSCALL(a,b)
#endif
/*
* This file contains the system call numbers.
- *
+ *
* Note: holes are not allowed.
*/
/* at least 8 syscall per cacheline */
-#define __NR_read 0
+#define __NR_read 0
__SYSCALL(__NR_read, sys_read)
-#define __NR_write 1
+#define __NR_write 1
__SYSCALL(__NR_write, sys_write)
-#define __NR_open 2
+#define __NR_open 2
__SYSCALL(__NR_open, sys_open)
-#define __NR_close 3
+#define __NR_close 3
__SYSCALL(__NR_close, sys_close)
-#define __NR_stat 4
+#define __NR_stat 4
__SYSCALL(__NR_stat, sys_newstat)
-#define __NR_fstat 5
+#define __NR_fstat 5
__SYSCALL(__NR_fstat, sys_newfstat)
-#define __NR_lstat 6
+#define __NR_lstat 6
__SYSCALL(__NR_lstat, sys_newlstat)
-#define __NR_poll 7
+#define __NR_poll 7
__SYSCALL(__NR_poll, sys_poll)
-#define __NR_lseek 8
+#define __NR_lseek 8
__SYSCALL(__NR_lseek, sys_lseek)
-#define __NR_mmap 9
+#define __NR_mmap 9
__SYSCALL(__NR_mmap, sys_mmap)
-#define __NR_mprotect 10
+#define __NR_mprotect 10
__SYSCALL(__NR_mprotect, sys_mprotect)
-#define __NR_munmap 11
+#define __NR_munmap 11
__SYSCALL(__NR_munmap, sys_munmap)
-#define __NR_brk 12
+#define __NR_brk 12
__SYSCALL(__NR_brk, sys_brk)
-#define __NR_rt_sigaction 13
+#define __NR_rt_sigaction 13
__SYSCALL(__NR_rt_sigaction, sys_rt_sigaction)
-#define __NR_rt_sigprocmask 14
+#define __NR_rt_sigprocmask 14
__SYSCALL(__NR_rt_sigprocmask, sys_rt_sigprocmask)
-#define __NR_rt_sigreturn 15
+#define __NR_rt_sigreturn 15
__SYSCALL(__NR_rt_sigreturn, stub_rt_sigreturn)
-#define __NR_ioctl 16
+#define __NR_ioctl 16
__SYSCALL(__NR_ioctl, sys_ioctl)
-#define __NR_pread64 17
+#define __NR_pread64 17
__SYSCALL(__NR_pread64, sys_pread64)
-#define __NR_pwrite64 18
+#define __NR_pwrite64 18
__SYSCALL(__NR_pwrite64, sys_pwrite64)
-#define __NR_readv 19
+#define __NR_readv 19
__SYSCALL(__NR_readv, sys_readv)
-#define __NR_writev 20
+#define __NR_writev 20
__SYSCALL(__NR_writev, sys_writev)
-#define __NR_access 21
+#define __NR_access 21
__SYSCALL(__NR_access, sys_access)
-#define __NR_pipe 22
+#define __NR_pipe 22
__SYSCALL(__NR_pipe, sys_pipe)
-#define __NR_select 23
+#define __NR_select 23
__SYSCALL(__NR_select, sys_select)
-#define __NR_sched_yield 24
+#define __NR_sched_yield 24
__SYSCALL(__NR_sched_yield, sys_sched_yield)
-#define __NR_mremap 25
+#define __NR_mremap 25
__SYSCALL(__NR_mremap, sys_mremap)
-#define __NR_msync 26
+#define __NR_msync 26
__SYSCALL(__NR_msync, sys_msync)
-#define __NR_mincore 27
+#define __NR_mincore 27
__SYSCALL(__NR_mincore, sys_mincore)
-#define __NR_madvise 28
+#define __NR_madvise 28
__SYSCALL(__NR_madvise, sys_madvise)
-#define __NR_shmget 29
+#define __NR_shmget 29
__SYSCALL(__NR_shmget, sys_shmget)
-#define __NR_shmat 30
+#define __NR_shmat 30
__SYSCALL(__NR_shmat, sys_shmat)
-#define __NR_shmctl 31
+#define __NR_shmctl 31
__SYSCALL(__NR_shmctl, sys_shmctl)
-#define __NR_dup 32
+#define __NR_dup 32
__SYSCALL(__NR_dup, sys_dup)
-#define __NR_dup2 33
+#define __NR_dup2 33
__SYSCALL(__NR_dup2, sys_dup2)
-#define __NR_pause 34
+#define __NR_pause 34
__SYSCALL(__NR_pause, sys_pause)
-#define __NR_nanosleep 35
+#define __NR_nanosleep 35
__SYSCALL(__NR_nanosleep, sys_nanosleep)
-#define __NR_getitimer 36
+#define __NR_getitimer 36
__SYSCALL(__NR_getitimer, sys_getitimer)
-#define __NR_alarm 37
+#define __NR_alarm 37
__SYSCALL(__NR_alarm, sys_alarm)
-#define __NR_setitimer 38
+#define __NR_setitimer 38
__SYSCALL(__NR_setitimer, sys_setitimer)
-#define __NR_getpid 39
+#define __NR_getpid 39
__SYSCALL(__NR_getpid, sys_getpid)
-#define __NR_sendfile 40
+#define __NR_sendfile 40
__SYSCALL(__NR_sendfile, sys_sendfile64)
-#define __NR_socket 41
+#define __NR_socket 41
__SYSCALL(__NR_socket, sys_socket)
-#define __NR_connect 42
+#define __NR_connect 42
__SYSCALL(__NR_connect, sys_connect)
-#define __NR_accept 43
+#define __NR_accept 43
__SYSCALL(__NR_accept, sys_accept)
-#define __NR_sendto 44
+#define __NR_sendto 44
__SYSCALL(__NR_sendto, sys_sendto)
-#define __NR_recvfrom 45
+#define __NR_recvfrom 45
__SYSCALL(__NR_recvfrom, sys_recvfrom)
-#define __NR_sendmsg 46
+#define __NR_sendmsg 46
__SYSCALL(__NR_sendmsg, sys_sendmsg)
-#define __NR_recvmsg 47
+#define __NR_recvmsg 47
__SYSCALL(__NR_recvmsg, sys_recvmsg)
-#define __NR_shutdown 48
+#define __NR_shutdown 48
__SYSCALL(__NR_shutdown, sys_shutdown)
-#define __NR_bind 49
+#define __NR_bind 49
__SYSCALL(__NR_bind, sys_bind)
-#define __NR_listen 50
+#define __NR_listen 50
__SYSCALL(__NR_listen, sys_listen)
-#define __NR_getsockname 51
+#define __NR_getsockname 51
__SYSCALL(__NR_getsockname, sys_getsockname)
-#define __NR_getpeername 52
+#define __NR_getpeername 52
__SYSCALL(__NR_getpeername, sys_getpeername)
-#define __NR_socketpair 53
+#define __NR_socketpair 53
__SYSCALL(__NR_socketpair, sys_socketpair)
-#define __NR_setsockopt 54
+#define __NR_setsockopt 54
__SYSCALL(__NR_setsockopt, sys_setsockopt)
-#define __NR_getsockopt 55
+#define __NR_getsockopt 55
__SYSCALL(__NR_getsockopt, sys_getsockopt)
-#define __NR_clone 56
+#define __NR_clone 56
__SYSCALL(__NR_clone, stub_clone)
-#define __NR_fork 57
-__SYSCALL(__NR_fork, stub_fork)
-#define __NR_vfork 58
+#define __NR_fork 57
+__SYSCALL(__NR_fork, stub_fork)
+#define __NR_vfork 58
__SYSCALL(__NR_vfork, stub_vfork)
-#define __NR_execve 59
+#define __NR_execve 59
__SYSCALL(__NR_execve, stub_execve)
-#define __NR_exit 60
+#define __NR_exit 60
__SYSCALL(__NR_exit, sys_exit)
-#define __NR_wait4 61
+#define __NR_wait4 61
__SYSCALL(__NR_wait4, sys_wait4)
-#define __NR_kill 62
+#define __NR_kill 62
__SYSCALL(__NR_kill, sys_kill)
-#define __NR_uname 63
+#define __NR_uname 63
__SYSCALL(__NR_uname, sys_uname)
-#define __NR_semget 64
+#define __NR_semget 64
__SYSCALL(__NR_semget, sys_semget)
-#define __NR_semop 65
+#define __NR_semop 65
__SYSCALL(__NR_semop, sys_semop)
-#define __NR_semctl 66
+#define __NR_semctl 66
__SYSCALL(__NR_semctl, sys_semctl)
-#define __NR_shmdt 67
+#define __NR_shmdt 67
__SYSCALL(__NR_shmdt, sys_shmdt)
-#define __NR_msgget 68
+#define __NR_msgget 68
__SYSCALL(__NR_msgget, sys_msgget)
-#define __NR_msgsnd 69
+#define __NR_msgsnd 69
__SYSCALL(__NR_msgsnd, sys_msgsnd)
-#define __NR_msgrcv 70
+#define __NR_msgrcv 70
__SYSCALL(__NR_msgrcv, sys_msgrcv)
-#define __NR_msgctl 71
+#define __NR_msgctl 71
__SYSCALL(__NR_msgctl, sys_msgctl)
-#define __NR_fcntl 72
+#define __NR_fcntl 72
__SYSCALL(__NR_fcntl, sys_fcntl)
-#define __NR_flock 73
+#define __NR_flock 73
__SYSCALL(__NR_flock, sys_flock)
-#define __NR_fsync 74
+#define __NR_fsync 74
__SYSCALL(__NR_fsync, sys_fsync)
-#define __NR_fdatasync 75
+#define __NR_fdatasync 75
__SYSCALL(__NR_fdatasync, sys_fdatasync)
-#define __NR_truncate 76
+#define __NR_truncate 76
__SYSCALL(__NR_truncate, sys_truncate)
-#define __NR_ftruncate 77
+#define __NR_ftruncate 77
__SYSCALL(__NR_ftruncate, sys_ftruncate)
-#define __NR_getdents 78
+#define __NR_getdents 78
__SYSCALL(__NR_getdents, sys_getdents)
-#define __NR_getcwd 79
+#define __NR_getcwd 79
__SYSCALL(__NR_getcwd, sys_getcwd)
-#define __NR_chdir 80
+#define __NR_chdir 80
__SYSCALL(__NR_chdir, sys_chdir)
-#define __NR_fchdir 81
+#define __NR_fchdir 81
__SYSCALL(__NR_fchdir, sys_fchdir)
-#define __NR_rename 82
+#define __NR_rename 82
__SYSCALL(__NR_rename, sys_rename)
-#define __NR_mkdir 83
+#define __NR_mkdir 83
__SYSCALL(__NR_mkdir, sys_mkdir)
-#define __NR_rmdir 84
+#define __NR_rmdir 84
__SYSCALL(__NR_rmdir, sys_rmdir)
-#define __NR_creat 85
+#define __NR_creat 85
__SYSCALL(__NR_creat, sys_creat)
-#define __NR_link 86
+#define __NR_link 86
__SYSCALL(__NR_link, sys_link)
-#define __NR_unlink 87
+#define __NR_unlink 87
__SYSCALL(__NR_unlink, sys_unlink)
-#define __NR_symlink 88
+#define __NR_symlink 88
__SYSCALL(__NR_symlink, sys_symlink)
-#define __NR_readlink 89
+#define __NR_readlink 89
__SYSCALL(__NR_readlink, sys_readlink)
-#define __NR_chmod 90
+#define __NR_chmod 90
__SYSCALL(__NR_chmod, sys_chmod)
-#define __NR_fchmod 91
+#define __NR_fchmod 91
__SYSCALL(__NR_fchmod, sys_fchmod)
-#define __NR_chown 92
+#define __NR_chown 92
__SYSCALL(__NR_chown, sys_chown)
-#define __NR_fchown 93
+#define __NR_fchown 93
__SYSCALL(__NR_fchown, sys_fchown)
-#define __NR_lchown 94
+#define __NR_lchown 94
__SYSCALL(__NR_lchown, sys_lchown)
-#define __NR_umask 95
+#define __NR_umask 95
__SYSCALL(__NR_umask, sys_umask)
-#define __NR_gettimeofday 96
+#define __NR_gettimeofday 96
__SYSCALL(__NR_gettimeofday, sys_gettimeofday)
-#define __NR_getrlimit 97
+#define __NR_getrlimit 97
__SYSCALL(__NR_getrlimit, sys_getrlimit)
-#define __NR_getrusage 98
+#define __NR_getrusage 98
__SYSCALL(__NR_getrusage, sys_getrusage)
-#define __NR_sysinfo 99
+#define __NR_sysinfo 99
__SYSCALL(__NR_sysinfo, sys_sysinfo)
-#define __NR_times 100
+#define __NR_times 100
__SYSCALL(__NR_times, sys_times)
-#define __NR_ptrace 101
+#define __NR_ptrace 101
__SYSCALL(__NR_ptrace, sys_ptrace)
-#define __NR_getuid 102
+#define __NR_getuid 102
__SYSCALL(__NR_getuid, sys_getuid)
-#define __NR_syslog 103
+#define __NR_syslog 103
__SYSCALL(__NR_syslog, sys_syslog)
/* at the very end the stuff that never runs during the benchmarks */
-#define __NR_getgid 104
+#define __NR_getgid 104
__SYSCALL(__NR_getgid, sys_getgid)
-#define __NR_setuid 105
+#define __NR_setuid 105
__SYSCALL(__NR_setuid, sys_setuid)
-#define __NR_setgid 106
+#define __NR_setgid 106
__SYSCALL(__NR_setgid, sys_setgid)
-#define __NR_geteuid 107
+#define __NR_geteuid 107
__SYSCALL(__NR_geteuid, sys_geteuid)
-#define __NR_getegid 108
+#define __NR_getegid 108
__SYSCALL(__NR_getegid, sys_getegid)
-#define __NR_setpgid 109
+#define __NR_setpgid 109
__SYSCALL(__NR_setpgid, sys_setpgid)
-#define __NR_getppid 110
+#define __NR_getppid 110
__SYSCALL(__NR_getppid, sys_getppid)
-#define __NR_getpgrp 111
+#define __NR_getpgrp 111
__SYSCALL(__NR_getpgrp, sys_getpgrp)
-#define __NR_setsid 112
+#define __NR_setsid 112
__SYSCALL(__NR_setsid, sys_setsid)
-#define __NR_setreuid 113
+#define __NR_setreuid 113
__SYSCALL(__NR_setreuid, sys_setreuid)
-#define __NR_setregid 114
+#define __NR_setregid 114
__SYSCALL(__NR_setregid, sys_setregid)
-#define __NR_getgroups 115
+#define __NR_getgroups 115
__SYSCALL(__NR_getgroups, sys_getgroups)
-#define __NR_setgroups 116
+#define __NR_setgroups 116
__SYSCALL(__NR_setgroups, sys_setgroups)
-#define __NR_setresuid 117
+#define __NR_setresuid 117
__SYSCALL(__NR_setresuid, sys_setresuid)
-#define __NR_getresuid 118
+#define __NR_getresuid 118
__SYSCALL(__NR_getresuid, sys_getresuid)
-#define __NR_setresgid 119
+#define __NR_setresgid 119
__SYSCALL(__NR_setresgid, sys_setresgid)
-#define __NR_getresgid 120
+#define __NR_getresgid 120
__SYSCALL(__NR_getresgid, sys_getresgid)
-#define __NR_getpgid 121
+#define __NR_getpgid 121
__SYSCALL(__NR_getpgid, sys_getpgid)
-#define __NR_setfsuid 122
+#define __NR_setfsuid 122
__SYSCALL(__NR_setfsuid, sys_setfsuid)
-#define __NR_setfsgid 123
+#define __NR_setfsgid 123
__SYSCALL(__NR_setfsgid, sys_setfsgid)
-#define __NR_getsid 124
+#define __NR_getsid 124
__SYSCALL(__NR_getsid, sys_getsid)
-#define __NR_capget 125
+#define __NR_capget 125
__SYSCALL(__NR_capget, sys_capget)
-#define __NR_capset 126
+#define __NR_capset 126
__SYSCALL(__NR_capset, sys_capset)
-#define __NR_rt_sigpending 127
+#define __NR_rt_sigpending 127
__SYSCALL(__NR_rt_sigpending, sys_rt_sigpending)
-#define __NR_rt_sigtimedwait 128
+#define __NR_rt_sigtimedwait 128
__SYSCALL(__NR_rt_sigtimedwait, sys_rt_sigtimedwait)
-#define __NR_rt_sigqueueinfo 129
+#define __NR_rt_sigqueueinfo 129
__SYSCALL(__NR_rt_sigqueueinfo, sys_rt_sigqueueinfo)
-#define __NR_rt_sigsuspend 130
+#define __NR_rt_sigsuspend 130
__SYSCALL(__NR_rt_sigsuspend, stub_rt_sigsuspend)
-#define __NR_sigaltstack 131
+#define __NR_sigaltstack 131
__SYSCALL(__NR_sigaltstack, stub_sigaltstack)
-#define __NR_utime 132
+#define __NR_utime 132
__SYSCALL(__NR_utime, sys_utime)
-#define __NR_mknod 133
+#define __NR_mknod 133
__SYSCALL(__NR_mknod, sys_mknod)
/* Only needed for a.out */
-#define __NR_uselib 134
+#define __NR_uselib 134
__SYSCALL(__NR_uselib, sys_ni_syscall)
-#define __NR_personality 135
+#define __NR_personality 135
__SYSCALL(__NR_personality, sys_personality)
-#define __NR_ustat 136
+#define __NR_ustat 136
__SYSCALL(__NR_ustat, sys_ustat)
-#define __NR_statfs 137
+#define __NR_statfs 137
__SYSCALL(__NR_statfs, sys_statfs)
-#define __NR_fstatfs 138
+#define __NR_fstatfs 138
__SYSCALL(__NR_fstatfs, sys_fstatfs)
-#define __NR_sysfs 139
+#define __NR_sysfs 139
__SYSCALL(__NR_sysfs, sys_sysfs)
-#define __NR_getpriority 140
+#define __NR_getpriority 140
__SYSCALL(__NR_getpriority, sys_getpriority)
-#define __NR_setpriority 141
+#define __NR_setpriority 141
__SYSCALL(__NR_setpriority, sys_setpriority)
-#define __NR_sched_setparam 142
+#define __NR_sched_setparam 142
__SYSCALL(__NR_sched_setparam, sys_sched_setparam)
-#define __NR_sched_getparam 143
+#define __NR_sched_getparam 143
__SYSCALL(__NR_sched_getparam, sys_sched_getparam)
-#define __NR_sched_setscheduler 144
+#define __NR_sched_setscheduler 144
__SYSCALL(__NR_sched_setscheduler, sys_sched_setscheduler)
-#define __NR_sched_getscheduler 145
+#define __NR_sched_getscheduler 145
__SYSCALL(__NR_sched_getscheduler, sys_sched_getscheduler)
-#define __NR_sched_get_priority_max 146
+#define __NR_sched_get_priority_max 146
__SYSCALL(__NR_sched_get_priority_max, sys_sched_get_priority_max)
-#define __NR_sched_get_priority_min 147
+#define __NR_sched_get_priority_min 147
__SYSCALL(__NR_sched_get_priority_min, sys_sched_get_priority_min)
-#define __NR_sched_rr_get_interval 148
+#define __NR_sched_rr_get_interval 148
__SYSCALL(__NR_sched_rr_get_interval, sys_sched_rr_get_interval)
-#define __NR_mlock 149
+#define __NR_mlock 149
__SYSCALL(__NR_mlock, sys_mlock)
-#define __NR_munlock 150
+#define __NR_munlock 150
__SYSCALL(__NR_munlock, sys_munlock)
-#define __NR_mlockall 151
+#define __NR_mlockall 151
__SYSCALL(__NR_mlockall, sys_mlockall)
-#define __NR_munlockall 152
+#define __NR_munlockall 152
__SYSCALL(__NR_munlockall, sys_munlockall)
-#define __NR_vhangup 153
+#define __NR_vhangup 153
__SYSCALL(__NR_vhangup, sys_vhangup)
-#define __NR_modify_ldt 154
+#define __NR_modify_ldt 154
__SYSCALL(__NR_modify_ldt, sys_modify_ldt)
-#define __NR_pivot_root 155
+#define __NR_pivot_root 155
__SYSCALL(__NR_pivot_root, sys_pivot_root)
-#define __NR__sysctl 156
+#define __NR__sysctl 156
__SYSCALL(__NR__sysctl, sys_sysctl)
-#define __NR_prctl 157
+#define __NR_prctl 157
__SYSCALL(__NR_prctl, sys_prctl)
-#define __NR_arch_prctl 158
-__SYSCALL(__NR_arch_prctl, sys_arch_prctl)
+#define __NR_arch_prctl 158
+__SYSCALL(__NR_arch_prctl, sys_arch_prctl)
-#define __NR_adjtimex 159
+#define __NR_adjtimex 159
__SYSCALL(__NR_adjtimex, sys_adjtimex)
-#define __NR_setrlimit 160
+#define __NR_setrlimit 160
__SYSCALL(__NR_setrlimit, sys_setrlimit)
-#define __NR_chroot 161
+#define __NR_chroot 161
__SYSCALL(__NR_chroot, sys_chroot)
-#define __NR_sync 162
+#define __NR_sync 162
__SYSCALL(__NR_sync, sys_sync)
-#define __NR_acct 163
+#define __NR_acct 163
__SYSCALL(__NR_acct, sys_acct)
-#define __NR_settimeofday 164
+#define __NR_settimeofday 164
__SYSCALL(__NR_settimeofday, sys_settimeofday)
-#define __NR_mount 165
+#define __NR_mount 165
__SYSCALL(__NR_mount, sys_mount)
-#define __NR_umount2 166
+#define __NR_umount2 166
__SYSCALL(__NR_umount2, sys_umount)
-#define __NR_swapon 167
+#define __NR_swapon 167
__SYSCALL(__NR_swapon, sys_swapon)
-#define __NR_swapoff 168
+#define __NR_swapoff 168
__SYSCALL(__NR_swapoff, sys_swapoff)
-#define __NR_reboot 169
+#define __NR_reboot 169
__SYSCALL(__NR_reboot, sys_reboot)
-#define __NR_sethostname 170
+#define __NR_sethostname 170
__SYSCALL(__NR_sethostname, sys_sethostname)
-#define __NR_setdomainname 171
+#define __NR_setdomainname 171
__SYSCALL(__NR_setdomainname, sys_setdomainname)
-#define __NR_iopl 172
+#define __NR_iopl 172
__SYSCALL(__NR_iopl, stub_iopl)
-#define __NR_ioperm 173
+#define __NR_ioperm 173
__SYSCALL(__NR_ioperm, sys_ioperm)
-#define __NR_create_module 174
+#define __NR_create_module 174
__SYSCALL(__NR_create_module, sys_ni_syscall)
-#define __NR_init_module 175
+#define __NR_init_module 175
__SYSCALL(__NR_init_module, sys_init_module)
-#define __NR_delete_module 176
+#define __NR_delete_module 176
__SYSCALL(__NR_delete_module, sys_delete_module)
-#define __NR_get_kernel_syms 177
+#define __NR_get_kernel_syms 177
__SYSCALL(__NR_get_kernel_syms, sys_ni_syscall)
-#define __NR_query_module 178
+#define __NR_query_module 178
__SYSCALL(__NR_query_module, sys_ni_syscall)
-#define __NR_quotactl 179
+#define __NR_quotactl 179
__SYSCALL(__NR_quotactl, sys_quotactl)
-#define __NR_nfsservctl 180
+#define __NR_nfsservctl 180
__SYSCALL(__NR_nfsservctl, sys_nfsservctl)
-#define __NR_getpmsg 181 /* reserved for LiS/STREAMS */
+/* reserved for LiS/STREAMS */
+#define __NR_getpmsg 181
__SYSCALL(__NR_getpmsg, sys_ni_syscall)
-#define __NR_putpmsg 182 /* reserved for LiS/STREAMS */
+#define __NR_putpmsg 182
__SYSCALL(__NR_putpmsg, sys_ni_syscall)
-#define __NR_afs_syscall 183 /* reserved for AFS */
+/* reserved for AFS */
+#define __NR_afs_syscall 183
__SYSCALL(__NR_afs_syscall, sys_ni_syscall)
-#define __NR_tuxcall 184 /* reserved for tux */
+/* reserved for tux */
+#define __NR_tuxcall 184
__SYSCALL(__NR_tuxcall, sys_ni_syscall)
-#define __NR_security 185
+#define __NR_security 185
__SYSCALL(__NR_security, sys_ni_syscall)
-#define __NR_gettid 186
+#define __NR_gettid 186
__SYSCALL(__NR_gettid, sys_gettid)
-#define __NR_readahead 187
+#define __NR_readahead 187
__SYSCALL(__NR_readahead, sys_readahead)
-#define __NR_setxattr 188
+#define __NR_setxattr 188
__SYSCALL(__NR_setxattr, sys_setxattr)
-#define __NR_lsetxattr 189
+#define __NR_lsetxattr 189
__SYSCALL(__NR_lsetxattr, sys_lsetxattr)
-#define __NR_fsetxattr 190
+#define __NR_fsetxattr 190
__SYSCALL(__NR_fsetxattr, sys_fsetxattr)
-#define __NR_getxattr 191
+#define __NR_getxattr 191
__SYSCALL(__NR_getxattr, sys_getxattr)
-#define __NR_lgetxattr 192
+#define __NR_lgetxattr 192
__SYSCALL(__NR_lgetxattr, sys_lgetxattr)
-#define __NR_fgetxattr 193
-__SYSCALL(__NR_fgetxattr, sys_fgetxattr)
-#define __NR_listxattr 194
-__SYSCALL(__NR_listxattr, sys_listxattr)
-#define __NR_llistxattr 195
-__SYSCALL(__NR_llistxattr, sys_llistxattr)
-#define __NR_flistxattr 196
-__SYSCALL(__NR_flistxattr, sys_flistxattr)
-#define __NR_removexattr 197
-__SYSCALL(__NR_removexattr, sys_removexattr)
-#define __NR_lremovexattr 198
-__SYSCALL(__NR_lremovexattr, sys_lremovexattr)
-#define __NR_fremovexattr 199
-__SYSCALL(__NR_fremovexattr, sys_fremovexattr)
-#define __NR_tkill 200
-__SYSCALL(__NR_tkill, sys_tkill)
-#define __NR_time 201
+#define __NR_fgetxattr 193
+__SYSCALL(__NR_fgetxattr, sys_fgetxattr)
+#define __NR_listxattr 194
+__SYSCALL(__NR_listxattr, sys_listxattr)
+#define __NR_llistxattr 195
+__SYSCALL(__NR_llistxattr, sys_llistxattr)
+#define __NR_flistxattr 196
+__SYSCALL(__NR_flistxattr, sys_flistxattr)
+#define __NR_removexattr 197
+__SYSCALL(__NR_removexattr, sys_removexattr)
+#define __NR_lremovexattr 198
+__SYSCALL(__NR_lremovexattr, sys_lremovexattr)
+#define __NR_fremovexattr 199
+__SYSCALL(__NR_fremovexattr, sys_fremovexattr)
+#define __NR_tkill 200
+__SYSCALL(__NR_tkill, sys_tkill)
+#define __NR_time 201
__SYSCALL(__NR_time, sys_time)
-#define __NR_futex 202
+#define __NR_futex 202
__SYSCALL(__NR_futex, sys_futex)
-#define __NR_sched_setaffinity 203
+#define __NR_sched_setaffinity 203
__SYSCALL(__NR_sched_setaffinity, sys_sched_setaffinity)
-#define __NR_sched_getaffinity 204
+#define __NR_sched_getaffinity 204
__SYSCALL(__NR_sched_getaffinity, sys_sched_getaffinity)
-#define __NR_set_thread_area 205
+#define __NR_set_thread_area 205
__SYSCALL(__NR_set_thread_area, sys_ni_syscall) /* use arch_prctl */
-#define __NR_io_setup 206
+#define __NR_io_setup 206
__SYSCALL(__NR_io_setup, sys_io_setup)
-#define __NR_io_destroy 207
+#define __NR_io_destroy 207
__SYSCALL(__NR_io_destroy, sys_io_destroy)
-#define __NR_io_getevents 208
+#define __NR_io_getevents 208
__SYSCALL(__NR_io_getevents, sys_io_getevents)
-#define __NR_io_submit 209
+#define __NR_io_submit 209
__SYSCALL(__NR_io_submit, sys_io_submit)
-#define __NR_io_cancel 210
+#define __NR_io_cancel 210
__SYSCALL(__NR_io_cancel, sys_io_cancel)
-#define __NR_get_thread_area 211
+#define __NR_get_thread_area 211
__SYSCALL(__NR_get_thread_area, sys_ni_syscall) /* use arch_prctl */
-#define __NR_lookup_dcookie 212
+#define __NR_lookup_dcookie 212
__SYSCALL(__NR_lookup_dcookie, sys_lookup_dcookie)
-#define __NR_epoll_create 213
+#define __NR_epoll_create 213
__SYSCALL(__NR_epoll_create, sys_epoll_create)
-#define __NR_epoll_ctl_old 214
+#define __NR_epoll_ctl_old 214
__SYSCALL(__NR_epoll_ctl_old, sys_ni_syscall)
-#define __NR_epoll_wait_old 215
+#define __NR_epoll_wait_old 215
__SYSCALL(__NR_epoll_wait_old, sys_ni_syscall)
-#define __NR_remap_file_pages 216
+#define __NR_remap_file_pages 216
__SYSCALL(__NR_remap_file_pages, sys_remap_file_pages)
-#define __NR_getdents64 217
+#define __NR_getdents64 217
__SYSCALL(__NR_getdents64, sys_getdents64)
-#define __NR_set_tid_address 218
+#define __NR_set_tid_address 218
__SYSCALL(__NR_set_tid_address, sys_set_tid_address)
-#define __NR_restart_syscall 219
+#define __NR_restart_syscall 219
__SYSCALL(__NR_restart_syscall, sys_restart_syscall)
-#define __NR_semtimedop 220
+#define __NR_semtimedop 220
__SYSCALL(__NR_semtimedop, sys_semtimedop)
-#define __NR_fadvise64 221
+#define __NR_fadvise64 221
__SYSCALL(__NR_fadvise64, sys_fadvise64)
-#define __NR_timer_create 222
+#define __NR_timer_create 222
__SYSCALL(__NR_timer_create, sys_timer_create)
-#define __NR_timer_settime 223
+#define __NR_timer_settime 223
__SYSCALL(__NR_timer_settime, sys_timer_settime)
-#define __NR_timer_gettime 224
+#define __NR_timer_gettime 224
__SYSCALL(__NR_timer_gettime, sys_timer_gettime)
-#define __NR_timer_getoverrun 225
+#define __NR_timer_getoverrun 225
__SYSCALL(__NR_timer_getoverrun, sys_timer_getoverrun)
-#define __NR_timer_delete 226
+#define __NR_timer_delete 226
__SYSCALL(__NR_timer_delete, sys_timer_delete)
-#define __NR_clock_settime 227
+#define __NR_clock_settime 227
__SYSCALL(__NR_clock_settime, sys_clock_settime)
-#define __NR_clock_gettime 228
+#define __NR_clock_gettime 228
__SYSCALL(__NR_clock_gettime, sys_clock_gettime)
-#define __NR_clock_getres 229
+#define __NR_clock_getres 229
__SYSCALL(__NR_clock_getres, sys_clock_getres)
-#define __NR_clock_nanosleep 230
+#define __NR_clock_nanosleep 230
__SYSCALL(__NR_clock_nanosleep, sys_clock_nanosleep)
-#define __NR_exit_group 231
+#define __NR_exit_group 231
__SYSCALL(__NR_exit_group, sys_exit_group)
-#define __NR_epoll_wait 232
+#define __NR_epoll_wait 232
__SYSCALL(__NR_epoll_wait, sys_epoll_wait)
-#define __NR_epoll_ctl 233
+#define __NR_epoll_ctl 233
__SYSCALL(__NR_epoll_ctl, sys_epoll_ctl)
-#define __NR_tgkill 234
+#define __NR_tgkill 234
__SYSCALL(__NR_tgkill, sys_tgkill)
-#define __NR_utimes 235
+#define __NR_utimes 235
__SYSCALL(__NR_utimes, sys_utimes)
-#define __NR_vserver 236
+#define __NR_vserver 236
__SYSCALL(__NR_vserver, sys_ni_syscall)
-#define __NR_mbind 237
+#define __NR_mbind 237
__SYSCALL(__NR_mbind, sys_mbind)
-#define __NR_set_mempolicy 238
+#define __NR_set_mempolicy 238
__SYSCALL(__NR_set_mempolicy, sys_set_mempolicy)
-#define __NR_get_mempolicy 239
+#define __NR_get_mempolicy 239
__SYSCALL(__NR_get_mempolicy, sys_get_mempolicy)
-#define __NR_mq_open 240
+#define __NR_mq_open 240
__SYSCALL(__NR_mq_open, sys_mq_open)
-#define __NR_mq_unlink 241
+#define __NR_mq_unlink 241
__SYSCALL(__NR_mq_unlink, sys_mq_unlink)
-#define __NR_mq_timedsend 242
+#define __NR_mq_timedsend 242
__SYSCALL(__NR_mq_timedsend, sys_mq_timedsend)
-#define __NR_mq_timedreceive 243
+#define __NR_mq_timedreceive 243
__SYSCALL(__NR_mq_timedreceive, sys_mq_timedreceive)
-#define __NR_mq_notify 244
+#define __NR_mq_notify 244
__SYSCALL(__NR_mq_notify, sys_mq_notify)
-#define __NR_mq_getsetattr 245
+#define __NR_mq_getsetattr 245
__SYSCALL(__NR_mq_getsetattr, sys_mq_getsetattr)
-#define __NR_kexec_load 246
+#define __NR_kexec_load 246
__SYSCALL(__NR_kexec_load, sys_kexec_load)
-#define __NR_waitid 247
+#define __NR_waitid 247
__SYSCALL(__NR_waitid, sys_waitid)
-#define __NR_add_key 248
+#define __NR_add_key 248
__SYSCALL(__NR_add_key, sys_add_key)
-#define __NR_request_key 249
+#define __NR_request_key 249
__SYSCALL(__NR_request_key, sys_request_key)
-#define __NR_keyctl 250
+#define __NR_keyctl 250
__SYSCALL(__NR_keyctl, sys_keyctl)
-#define __NR_ioprio_set 251
+#define __NR_ioprio_set 251
__SYSCALL(__NR_ioprio_set, sys_ioprio_set)
-#define __NR_ioprio_get 252
+#define __NR_ioprio_get 252
__SYSCALL(__NR_ioprio_get, sys_ioprio_get)
-#define __NR_inotify_init 253
+#define __NR_inotify_init 253
__SYSCALL(__NR_inotify_init, sys_inotify_init)
-#define __NR_inotify_add_watch 254
+#define __NR_inotify_add_watch 254
__SYSCALL(__NR_inotify_add_watch, sys_inotify_add_watch)
-#define __NR_inotify_rm_watch 255
+#define __NR_inotify_rm_watch 255
__SYSCALL(__NR_inotify_rm_watch, sys_inotify_rm_watch)
-#define __NR_migrate_pages 256
+#define __NR_migrate_pages 256
__SYSCALL(__NR_migrate_pages, sys_migrate_pages)
-#define __NR_openat 257
+#define __NR_openat 257
__SYSCALL(__NR_openat, sys_openat)
-#define __NR_mkdirat 258
+#define __NR_mkdirat 258
__SYSCALL(__NR_mkdirat, sys_mkdirat)
-#define __NR_mknodat 259
+#define __NR_mknodat 259
__SYSCALL(__NR_mknodat, sys_mknodat)
-#define __NR_fchownat 260
+#define __NR_fchownat 260
__SYSCALL(__NR_fchownat, sys_fchownat)
-#define __NR_futimesat 261
+#define __NR_futimesat 261
__SYSCALL(__NR_futimesat, sys_futimesat)
-#define __NR_newfstatat 262
+#define __NR_newfstatat 262
__SYSCALL(__NR_newfstatat, sys_newfstatat)
-#define __NR_unlinkat 263
+#define __NR_unlinkat 263
__SYSCALL(__NR_unlinkat, sys_unlinkat)
-#define __NR_renameat 264
+#define __NR_renameat 264
__SYSCALL(__NR_renameat, sys_renameat)
-#define __NR_linkat 265
+#define __NR_linkat 265
__SYSCALL(__NR_linkat, sys_linkat)
-#define __NR_symlinkat 266
+#define __NR_symlinkat 266
__SYSCALL(__NR_symlinkat, sys_symlinkat)
-#define __NR_readlinkat 267
+#define __NR_readlinkat 267
__SYSCALL(__NR_readlinkat, sys_readlinkat)
-#define __NR_fchmodat 268
+#define __NR_fchmodat 268
__SYSCALL(__NR_fchmodat, sys_fchmodat)
-#define __NR_faccessat 269
+#define __NR_faccessat 269
__SYSCALL(__NR_faccessat, sys_faccessat)
-#define __NR_pselect6 270
+#define __NR_pselect6 270
__SYSCALL(__NR_pselect6, sys_pselect6)
-#define __NR_ppoll 271
+#define __NR_ppoll 271
__SYSCALL(__NR_ppoll, sys_ppoll)
-#define __NR_unshare 272
+#define __NR_unshare 272
__SYSCALL(__NR_unshare, sys_unshare)
-#define __NR_set_robust_list 273
+#define __NR_set_robust_list 273
__SYSCALL(__NR_set_robust_list, sys_set_robust_list)
-#define __NR_get_robust_list 274
+#define __NR_get_robust_list 274
__SYSCALL(__NR_get_robust_list, sys_get_robust_list)
-#define __NR_splice 275
+#define __NR_splice 275
__SYSCALL(__NR_splice, sys_splice)
-#define __NR_tee 276
+#define __NR_tee 276
__SYSCALL(__NR_tee, sys_tee)
-#define __NR_sync_file_range 277
+#define __NR_sync_file_range 277
__SYSCALL(__NR_sync_file_range, sys_sync_file_range)
-#define __NR_vmsplice 278
+#define __NR_vmsplice 278
__SYSCALL(__NR_vmsplice, sys_vmsplice)
-#define __NR_move_pages 279
+#define __NR_move_pages 279
__SYSCALL(__NR_move_pages, sys_move_pages)
-#define __NR_utimensat 280
+#define __NR_utimensat 280
__SYSCALL(__NR_utimensat, sys_utimensat)
#define __IGNORE_getcpu /* implemented as a vsyscall */
-#define __NR_epoll_pwait 281
+#define __NR_epoll_pwait 281
__SYSCALL(__NR_epoll_pwait, sys_epoll_pwait)
-#define __NR_signalfd 282
+#define __NR_signalfd 282
__SYSCALL(__NR_signalfd, sys_signalfd)
-#define __NR_timerfd 283
+#define __NR_timerfd 283
__SYSCALL(__NR_timerfd, sys_timerfd)
-#define __NR_eventfd 284
+#define __NR_eventfd 284
__SYSCALL(__NR_eventfd, sys_eventfd)
-#define __NR_fallocate 285
+#define __NR_fallocate 285
__SYSCALL(__NR_fallocate, sys_fallocate)
#ifndef __NO_STUBS
@@ -656,26 +659,9 @@ __SYSCALL(__NR_fallocate, sys_fallocate)
#define __ARCH_WANT_SYS_RT_SIGSUSPEND
#define __ARCH_WANT_SYS_TIME
#define __ARCH_WANT_COMPAT_SYS_TIME
-
-#ifdef __KERNEL__
-#ifndef __ASSEMBLY__
-
-#include <linux/linkage.h>
-#include <linux/compiler.h>
-#include <linux/types.h>
-#include <asm/ptrace.h>
-
-asmlinkage long sys_iopl(unsigned int level, struct pt_regs *regs);
-struct sigaction;
-asmlinkage long sys_rt_sigaction(int sig,
- const struct sigaction __user *act,
- struct sigaction __user *oact,
- size_t sigsetsize);
-
-#endif /* __ASSEMBLY__ */
-#endif /* __KERNEL__ */
#endif /* __NO_STUBS */
+#ifdef __KERNEL__
/*
* "Conditional" syscalls
*
@@ -683,5 +669,6 @@ asmlinkage long sys_rt_sigaction(int sig,
* but it doesn't work on all toolchains, so we just do it by hand
*/
#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
+#endif /* __KERNEL__ */
#endif /* _ASM_X86_64_UNISTD_H_ */
diff --git a/include/asm-x86/unwind.h b/include/asm-x86/unwind.h
index 7e4d7ad55208..8b064bd9c553 100644
--- a/include/asm-x86/unwind.h
+++ b/include/asm-x86/unwind.h
@@ -1,5 +1,13 @@
-#ifdef CONFIG_X86_32
-# include "unwind_32.h"
-#else
-# include "unwind_64.h"
-#endif
+#ifndef _ASM_X86_UNWIND_H
+#define _ASM_X86_UNWIND_H
+
+#define UNW_PC(frame) ((void)(frame), 0UL)
+#define UNW_SP(frame) ((void)(frame), 0UL)
+#define UNW_FP(frame) ((void)(frame), 0UL)
+
+static inline int arch_unw_user_mode(const void *info)
+{
+ return 0;
+}
+
+#endif /* _ASM_X86_UNWIND_H */
diff --git a/include/asm-x86/unwind_32.h b/include/asm-x86/unwind_32.h
deleted file mode 100644
index 43c70c3de2f9..000000000000
--- a/include/asm-x86/unwind_32.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef _ASM_I386_UNWIND_H
-#define _ASM_I386_UNWIND_H
-
-#define UNW_PC(frame) ((void)(frame), 0)
-#define UNW_SP(frame) ((void)(frame), 0)
-#define UNW_FP(frame) ((void)(frame), 0)
-
-static inline int arch_unw_user_mode(const void *info)
-{
- return 0;
-}
-
-#endif /* _ASM_I386_UNWIND_H */
diff --git a/include/asm-x86/unwind_64.h b/include/asm-x86/unwind_64.h
deleted file mode 100644
index 02710f6a4560..000000000000
--- a/include/asm-x86/unwind_64.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _ASM_X86_64_UNWIND_H
-#define _ASM_X86_64_UNWIND_H
-
-#define UNW_PC(frame) ((void)(frame), 0UL)
-#define UNW_SP(frame) ((void)(frame), 0UL)
-
-static inline int arch_unw_user_mode(const void *info)
-{
- return 0;
-}
-
-#endif /* _ASM_X86_64_UNWIND_H */
diff --git a/include/asm-xtensa/bitops.h b/include/asm-xtensa/bitops.h
index 1c1e0d933eea..23261e8f2e5a 100644
--- a/include/asm-xtensa/bitops.h
+++ b/include/asm-xtensa/bitops.h
@@ -15,6 +15,10 @@
#ifdef __KERNEL__
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
#include <asm/processor.h>
#include <asm/byteorder.h>
#include <asm/system.h>
@@ -108,6 +112,7 @@ static inline int fls (unsigned int x)
#endif
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/lock.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/minix.h>
diff --git a/include/asm-xtensa/dma-mapping.h b/include/asm-xtensa/dma-mapping.h
index 82b03b3a2ee6..3c7d537dd15d 100644
--- a/include/asm-xtensa/dma-mapping.h
+++ b/include/asm-xtensa/dma-mapping.h
@@ -11,10 +11,10 @@
#ifndef _XTENSA_DMA_MAPPING_H
#define _XTENSA_DMA_MAPPING_H
-#include <asm/scatterlist.h>
#include <asm/cache.h>
#include <asm/io.h>
#include <linux/mm.h>
+#include <linux/scatterlist.h>
/*
* DMA-consistent mapping functions.
@@ -58,11 +58,10 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
BUG_ON(direction == DMA_NONE);
for (i = 0; i < nents; i++, sg++ ) {
- BUG_ON(!sg->page);
+ BUG_ON(!sg_page(sg));
- sg->dma_address = page_to_phys(sg->page) + sg->offset;
- consistent_sync(page_address(sg->page) + sg->offset,
- sg->length, direction);
+ sg->dma_address = sg_phys(sg);
+ consistent_sync(sg_virt(sg), sg->length, direction);
}
return nents;
@@ -128,8 +127,7 @@ dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
{
int i;
for (i = 0; i < nelems; i++, sg++)
- consistent_sync(page_address(sg->page) + sg->offset,
- sg->length, dir);
+ consistent_sync(sg_virt(sg), sg->length, dir);
}
static inline void
@@ -138,8 +136,7 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
{
int i;
for (i = 0; i < nelems; i++, sg++)
- consistent_sync(page_address(sg->page) + sg->offset,
- sg->length, dir);
+ consistent_sync(sg_virt(sg), sg->length, dir);
}
static inline int
dma_mapping_error(dma_addr_t dma_addr)
diff --git a/include/asm-xtensa/scatterlist.h b/include/asm-xtensa/scatterlist.h
index ca337a294290..810080bb0a2b 100644
--- a/include/asm-xtensa/scatterlist.h
+++ b/include/asm-xtensa/scatterlist.h
@@ -14,7 +14,10 @@
#include <asm/types.h>
struct scatterlist {
- struct page *page;
+#ifdef CONFIG_DEBUG_SG
+ unsigned long sg_magic;
+#endif
+ unsigned long page_link;
unsigned int offset;
dma_addr_t dma_address;
unsigned int length;
diff --git a/include/asm-xtensa/semaphore.h b/include/asm-xtensa/semaphore.h
index f10c3487cd4c..3e04167cd9dc 100644
--- a/include/asm-xtensa/semaphore.h
+++ b/include/asm-xtensa/semaphore.h
@@ -33,7 +33,6 @@ struct semaphore {
struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
-#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
static inline void sema_init (struct semaphore *sem, int val)
{
diff --git a/include/asm-xtensa/tlbflush.h b/include/asm-xtensa/tlbflush.h
index 7c637b3c352c..46d240074f74 100644
--- a/include/asm-xtensa/tlbflush.h
+++ b/include/asm-xtensa/tlbflush.h
@@ -41,17 +41,6 @@ extern void flush_tlb_range(struct vm_area_struct*,unsigned long,unsigned long);
#define flush_tlb_kernel_range(start,end) flush_tlb_all()
-
-/* This is calld in munmap when we have freed up some page-table pages.
- * We don't need to do anything here, there's nothing special about our
- * page-table pages.
- */
-
-static inline void flush_tlb_pgtables(struct mm_struct *mm,
- unsigned long start, unsigned long end)
-{
-}
-
/* TLB operations. */
static inline unsigned long itlb_probe(unsigned long addr)
diff --git a/include/asm-xtensa/types.h b/include/asm-xtensa/types.h
index f1e84526f999..b27d841a8eb7 100644
--- a/include/asm-xtensa/types.h
+++ b/include/asm-xtensa/types.h
@@ -38,9 +38,9 @@ typedef unsigned short __u16;
typedef __signed__ int __s32;
typedef unsigned int __u32;
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
-typedef __signed__ long long __s64;
-typedef unsigned long long __u64;
+#if defined(__GNUC__)
+__extension__ typedef __signed__ long long __s64;
+__extension__ typedef unsigned long long __u64;
#endif
/*
diff --git a/include/keys/rxrpc-type.h b/include/keys/rxrpc-type.h
index e2ee73aef0ee..4ea429b18750 100644
--- a/include/keys/rxrpc-type.h
+++ b/include/keys/rxrpc-type.h
@@ -19,4 +19,6 @@
*/
extern struct key_type key_type_rxrpc;
+extern struct key *rxrpc_get_null_key(const char *);
+
#endif /* _KEYS_USER_TYPE_H */
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 818cc3a50e6b..37bfa19d8064 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -46,8 +46,8 @@ header-y += chio.h
header-y += coda_psdev.h
header-y += coff.h
header-y += comstats.h
-header-y += consolemap.h
header-y += const.h
+header-y += cgroupstats.h
header-y += cycx_cfm.h
header-y += dlm_device.h
header-y += dlm_netlink.h
@@ -78,7 +78,6 @@ header-y += if_arcnet.h
header-y += if_bonding.h
header-y += if_cablemodem.h
header-y += if_fc.h
-header-y += if_fddi.h
header-y += if.h
header-y += if_hippi.h
header-y += if_infiniband.h
@@ -121,7 +120,6 @@ header-y += nl80211.h
header-y += oom.h
header-y += param.h
header-y += pci_regs.h
-header-y += personality.h
header-y += pfkeyv2.h
header-y += pg.h
header-y += phantom.h
@@ -151,6 +149,7 @@ header-y += ticable.h
header-y += times.h
header-y += tiocl.h
header-y += tipc.h
+header-y += tipc_config.h
header-y += toshiba.h
header-y += ultrasound.h
header-y += un.h
@@ -159,7 +158,6 @@ header-y += video_decoder.h
header-y += video_encoder.h
header-y += videotext.h
header-y += vt.h
-header-y += wireless.h
header-y += x25.h
unifdef-y += acct.h
@@ -189,6 +187,7 @@ unifdef-y += cyclades.h
unifdef-y += dccp.h
unifdef-y += dirent.h
unifdef-y += dlm.h
+unifdef-y += edd.h
unifdef-y += elfcore.h
unifdef-y += errno.h
unifdef-y += errqueue.h
@@ -286,6 +285,7 @@ unifdef-y += nfs_idmap.h
unifdef-y += n_r3964.h
unifdef-y += nubus.h
unifdef-y += nvram.h
+unifdef-y += oom.h
unifdef-y += parport.h
unifdef-y += patchkey.h
unifdef-y += pci.h
@@ -308,6 +308,7 @@ unifdef-y += rtc.h
unifdef-y += rtnetlink.h
unifdef-y += scc.h
unifdef-y += sched.h
+unifdef-y += screen_info.h
unifdef-y += sdla.h
unifdef-y += selinux_netlink.h
unifdef-y += sem.h
@@ -325,6 +326,7 @@ unifdef-y += sonypi.h
unifdef-y += soundcard.h
unifdef-y += stat.h
unifdef-y += stddef.h
+unifdef-y += string.h
unifdef-y += synclink.h
unifdef-y += sysctl.h
unifdef-y += tcp.h
@@ -343,6 +345,9 @@ unifdef-y += user.h
unifdef-y += utsname.h
unifdef-y += videodev2.h
unifdef-y += videodev.h
+unifdef-y += virtio_config.h
+unifdef-y += virtio_blk.h
+unifdef-y += virtio_net.h
unifdef-y += wait.h
unifdef-y += wanrouter.h
unifdef-y += watchdog.h
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index bf5e0009de75..8ccedf7a0a5a 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -189,32 +189,6 @@ extern int ec_transaction(u8 command,
extern int acpi_blacklisted(void);
extern void acpi_bios_year(char *s);
-#define ACPI_CSTATE_LIMIT_DEFINED /* for driver builds */
-#ifdef CONFIG_ACPI
-
-/*
- * Set highest legal C-state
- * 0: C0 okay, but not C1
- * 1: C1 okay, but not C2
- * 2: C2 okay, but not C3 etc.
- */
-
-extern unsigned int max_cstate;
-
-static inline unsigned int acpi_get_cstate_limit(void)
-{
- return max_cstate;
-}
-static inline void acpi_set_cstate_limit(unsigned int new_limit)
-{
- max_cstate = new_limit;
- return;
-}
-#else
-static inline unsigned int acpi_get_cstate_limit(void) { return 0; }
-static inline void acpi_set_cstate_limit(unsigned int new_limit) { return; }
-#endif
-
#ifdef CONFIG_ACPI_NUMA
int acpi_get_pxm(acpi_handle handle);
int acpi_get_node(acpi_handle *handle);
diff --git a/include/linux/aio.h b/include/linux/aio.h
index d10e608f232d..7ef8de662001 100644
--- a/include/linux/aio.h
+++ b/include/linux/aio.h
@@ -232,18 +232,6 @@ int FASTCALL(io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
__put_ioctx(kioctx); \
} while (0)
-#define in_aio() (unlikely(!is_sync_wait(current->io_wait)))
-
-/* may be used for debugging */
-#define warn_if_async() \
-do { \
- if (in_aio()) { \
- printk(KERN_ERR "%s(%s:%d) called in async context!\n", \
- __FUNCTION__, __FILE__, __LINE__); \
- dump_stack(); \
- } \
-} while (0)
-
#define io_wait_to_kiocb(wait) container_of(wait, struct kiocb, ki_wait)
#include <linux/aio_abi.h>
diff --git a/include/linux/apm_bios.h b/include/linux/apm_bios.h
index 5f921c84827a..9754baa14921 100644
--- a/include/linux/apm_bios.h
+++ b/include/linux/apm_bios.h
@@ -16,29 +16,29 @@
* General Public License for more details.
*/
-typedef unsigned short apm_event_t;
-typedef unsigned short apm_eventinfo_t;
+#include <linux/types.h>
+
+struct apm_bios_info {
+ __u16 version;
+ __u16 cseg;
+ __u32 offset;
+ __u16 cseg_16;
+ __u16 dseg;
+ __u16 flags;
+ __u16 cseg_len;
+ __u16 cseg_16_len;
+ __u16 dseg_len;
+};
#ifdef __KERNEL__
-#include <linux/types.h>
+typedef unsigned short apm_event_t;
+typedef unsigned short apm_eventinfo_t;
#define APM_CS (GDT_ENTRY_APMBIOS_BASE * 8)
#define APM_CS_16 (APM_CS + 8)
#define APM_DS (APM_CS_16 + 8)
-struct apm_bios_info {
- u16 version;
- u16 cseg;
- u32 offset;
- u16 cseg_16;
- u16 dseg;
- u16 flags;
- u16 cseg_len;
- u16 cseg_16_len;
- u16 dseg_len;
-};
-
/* Results of APM Installation Check */
#define APM_16_BIT_SUPPORT 0x0001
#define APM_32_BIT_SUPPORT 0x0002
diff --git a/include/linux/ata.h b/include/linux/ata.h
index a4f373f8b798..5c4e54a2a8d6 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -43,6 +43,7 @@ enum {
ATA_MAX_SECTORS_128 = 128,
ATA_MAX_SECTORS = 256,
ATA_MAX_SECTORS_LBA48 = 65535,/* TODO: 65536? */
+ ATA_MAX_SECTORS_TAPE = 65535,
ATA_ID_WORDS = 256,
ATA_ID_SERNO = 10,
@@ -178,8 +179,9 @@ enum {
ATA_CMD_PACKET = 0xA0,
ATA_CMD_VERIFY = 0x40,
ATA_CMD_VERIFY_EXT = 0x42,
- ATA_CMD_STANDBYNOW1 = 0xE0,
- ATA_CMD_IDLEIMMEDIATE = 0xE1,
+ ATA_CMD_STANDBYNOW1 = 0xE0,
+ ATA_CMD_IDLEIMMEDIATE = 0xE1,
+ ATA_CMD_SLEEP = 0xE6,
ATA_CMD_INIT_DEV_PARAMS = 0x91,
ATA_CMD_READ_NATIVE_MAX = 0xF8,
ATA_CMD_READ_NATIVE_MAX_EXT = 0x27,
@@ -235,6 +237,7 @@ enum {
/* SETFEATURE Sector counts for SATA features */
SATA_AN = 0x05, /* Asynchronous Notification */
+ SATA_DIPM = 0x03, /* Device Initiated Power Management */
/* ATAPI stuff */
ATAPI_PKT_DMA = (1 << 0),
@@ -377,6 +380,26 @@ struct ata_taskfile {
#define ata_id_cdb_intr(id) (((id)[0] & 0x60) == 0x20)
+static inline bool ata_id_has_hipm(const u16 *id)
+{
+ u16 val = id[76];
+
+ if (val == 0 || val == 0xffff)
+ return false;
+
+ return val & (1 << 9);
+}
+
+static inline bool ata_id_has_dipm(const u16 *id)
+{
+ u16 val = id[78];
+
+ if (val == 0 || val == 0xffff)
+ return false;
+
+ return val & (1 << 3);
+}
+
static inline int ata_id_has_fua(const u16 *id)
{
if ((id[84] & 0xC000) != 0x4000)
@@ -402,6 +425,8 @@ static inline int ata_id_has_lba48(const u16 *id)
{
if ((id[83] & 0xC000) != 0x4000)
return 0;
+ if (!ata_id_u64(id, 100))
+ return 0;
return id[83] & (1 << 10);
}
@@ -458,7 +483,7 @@ static inline int ata_id_wcache_enabled(const u16 *id)
* ATA-3 introduces word 80 and accurate reporting
*
* The practical impact of this is that ata_id_major_version cannot
- * reliably report on drives below ATA3.
+ * reliably report on drives below ATA3.
*/
static inline unsigned int ata_id_major_version(const u16 *id)
@@ -512,6 +537,15 @@ static inline int ata_drive_40wire(const u16 *dev_id)
return 1;
}
+static inline int ata_drive_40wire_relaxed(const u16 *dev_id)
+{
+ if (ata_id_is_sata(dev_id))
+ return 0; /* SATA */
+ if ((dev_id[93] & 0x2000) == 0x2000)
+ return 0; /* 80 wire */
+ return 1;
+}
+
static inline int atapi_cdb_len(const u16 *dev_id)
{
u16 tmp = dev_id[0] & 0x3;
@@ -522,6 +556,11 @@ static inline int atapi_cdb_len(const u16 *dev_id)
}
}
+static inline int atapi_command_packet_set(const u16 *dev_id)
+{
+ return (dev_id[0] >> 8) & 0x1f;
+}
+
static inline int is_atapi_taskfile(const struct ata_taskfile *tf)
{
return (tf->protocol == ATA_PROT_ATAPI) ||
diff --git a/include/linux/atmel-ssc.h b/include/linux/atmel-ssc.h
new file mode 100644
index 000000000000..06023393fba9
--- /dev/null
+++ b/include/linux/atmel-ssc.h
@@ -0,0 +1,312 @@
+#ifndef __INCLUDE_ATMEL_SSC_H
+#define __INCLUDE_ATMEL_SSC_H
+
+#include <linux/platform_device.h>
+#include <linux/list.h>
+
+struct ssc_device {
+ struct list_head list;
+ void __iomem *regs;
+ struct platform_device *pdev;
+ struct clk *clk;
+ int user;
+ int irq;
+};
+
+struct ssc_device * __must_check ssc_request(unsigned int ssc_num);
+void ssc_free(struct ssc_device *ssc);
+
+/* SSC register offsets */
+
+/* SSC Control Register */
+#define SSC_CR 0x00000000
+#define SSC_CR_RXDIS_SIZE 1
+#define SSC_CR_RXDIS_OFFSET 1
+#define SSC_CR_RXEN_SIZE 1
+#define SSC_CR_RXEN_OFFSET 0
+#define SSC_CR_SWRST_SIZE 1
+#define SSC_CR_SWRST_OFFSET 15
+#define SSC_CR_TXDIS_SIZE 1
+#define SSC_CR_TXDIS_OFFSET 9
+#define SSC_CR_TXEN_SIZE 1
+#define SSC_CR_TXEN_OFFSET 8
+
+/* SSC Clock Mode Register */
+#define SSC_CMR 0x00000004
+#define SSC_CMR_DIV_SIZE 12
+#define SSC_CMR_DIV_OFFSET 0
+
+/* SSC Receive Clock Mode Register */
+#define SSC_RCMR 0x00000010
+#define SSC_RCMR_CKG_SIZE 2
+#define SSC_RCMR_CKG_OFFSET 6
+#define SSC_RCMR_CKI_SIZE 1
+#define SSC_RCMR_CKI_OFFSET 5
+#define SSC_RCMR_CKO_SIZE 3
+#define SSC_RCMR_CKO_OFFSET 2
+#define SSC_RCMR_CKS_SIZE 2
+#define SSC_RCMR_CKS_OFFSET 0
+#define SSC_RCMR_PERIOD_SIZE 8
+#define SSC_RCMR_PERIOD_OFFSET 24
+#define SSC_RCMR_START_SIZE 4
+#define SSC_RCMR_START_OFFSET 8
+#define SSC_RCMR_STOP_SIZE 1
+#define SSC_RCMR_STOP_OFFSET 12
+#define SSC_RCMR_STTDLY_SIZE 8
+#define SSC_RCMR_STTDLY_OFFSET 16
+
+/* SSC Receive Frame Mode Register */
+#define SSC_RFMR 0x00000014
+#define SSC_RFMR_DATLEN_SIZE 5
+#define SSC_RFMR_DATLEN_OFFSET 0
+#define SSC_RFMR_DATNB_SIZE 4
+#define SSC_RFMR_DATNB_OFFSET 8
+#define SSC_RFMR_FSEDGE_SIZE 1
+#define SSC_RFMR_FSEDGE_OFFSET 24
+#define SSC_RFMR_FSLEN_SIZE 4
+#define SSC_RFMR_FSLEN_OFFSET 16
+#define SSC_RFMR_FSOS_SIZE 4
+#define SSC_RFMR_FSOS_OFFSET 20
+#define SSC_RFMR_LOOP_SIZE 1
+#define SSC_RFMR_LOOP_OFFSET 5
+#define SSC_RFMR_MSBF_SIZE 1
+#define SSC_RFMR_MSBF_OFFSET 7
+
+/* SSC Transmit Clock Mode Register */
+#define SSC_TCMR 0x00000018
+#define SSC_TCMR_CKG_SIZE 2
+#define SSC_TCMR_CKG_OFFSET 6
+#define SSC_TCMR_CKI_SIZE 1
+#define SSC_TCMR_CKI_OFFSET 5
+#define SSC_TCMR_CKO_SIZE 3
+#define SSC_TCMR_CKO_OFFSET 2
+#define SSC_TCMR_CKS_SIZE 2
+#define SSC_TCMR_CKS_OFFSET 0
+#define SSC_TCMR_PERIOD_SIZE 8
+#define SSC_TCMR_PERIOD_OFFSET 24
+#define SSC_TCMR_START_SIZE 4
+#define SSC_TCMR_START_OFFSET 8
+#define SSC_TCMR_STTDLY_SIZE 8
+#define SSC_TCMR_STTDLY_OFFSET 16
+
+/* SSC Transmit Frame Mode Register */
+#define SSC_TFMR 0x0000001c
+#define SSC_TFMR_DATDEF_SIZE 1
+#define SSC_TFMR_DATDEF_OFFSET 5
+#define SSC_TFMR_DATLEN_SIZE 5
+#define SSC_TFMR_DATLEN_OFFSET 0
+#define SSC_TFMR_DATNB_SIZE 4
+#define SSC_TFMR_DATNB_OFFSET 8
+#define SSC_TFMR_FSDEN_SIZE 1
+#define SSC_TFMR_FSDEN_OFFSET 23
+#define SSC_TFMR_FSEDGE_SIZE 1
+#define SSC_TFMR_FSEDGE_OFFSET 24
+#define SSC_TFMR_FSLEN_SIZE 4
+#define SSC_TFMR_FSLEN_OFFSET 16
+#define SSC_TFMR_FSOS_SIZE 3
+#define SSC_TFMR_FSOS_OFFSET 20
+#define SSC_TFMR_MSBF_SIZE 1
+#define SSC_TFMR_MSBF_OFFSET 7
+
+/* SSC Receive Hold Register */
+#define SSC_RHR 0x00000020
+#define SSC_RHR_RDAT_SIZE 32
+#define SSC_RHR_RDAT_OFFSET 0
+
+/* SSC Transmit Hold Register */
+#define SSC_THR 0x00000024
+#define SSC_THR_TDAT_SIZE 32
+#define SSC_THR_TDAT_OFFSET 0
+
+/* SSC Receive Sync. Holding Register */
+#define SSC_RSHR 0x00000030
+#define SSC_RSHR_RSDAT_SIZE 16
+#define SSC_RSHR_RSDAT_OFFSET 0
+
+/* SSC Transmit Sync. Holding Register */
+#define SSC_TSHR 0x00000034
+#define SSC_TSHR_TSDAT_SIZE 16
+#define SSC_TSHR_RSDAT_OFFSET 0
+
+/* SSC Receive Compare 0 Register */
+#define SSC_RC0R 0x00000038
+#define SSC_RC0R_CP0_SIZE 16
+#define SSC_RC0R_CP0_OFFSET 0
+
+/* SSC Receive Compare 1 Register */
+#define SSC_RC1R 0x0000003c
+#define SSC_RC1R_CP1_SIZE 16
+#define SSC_RC1R_CP1_OFFSET 0
+
+/* SSC Status Register */
+#define SSC_SR 0x00000040
+#define SSC_SR_CP0_SIZE 1
+#define SSC_SR_CP0_OFFSET 8
+#define SSC_SR_CP1_SIZE 1
+#define SSC_SR_CP1_OFFSET 9
+#define SSC_SR_ENDRX_SIZE 1
+#define SSC_SR_ENDRX_OFFSET 6
+#define SSC_SR_ENDTX_SIZE 1
+#define SSC_SR_ENDTX_OFFSET 2
+#define SSC_SR_OVRUN_SIZE 1
+#define SSC_SR_OVRUN_OFFSET 5
+#define SSC_SR_RXBUFF_SIZE 1
+#define SSC_SR_RXBUFF_OFFSET 7
+#define SSC_SR_RXEN_SIZE 1
+#define SSC_SR_RXEN_OFFSET 17
+#define SSC_SR_RXRDY_SIZE 1
+#define SSC_SR_RXRDY_OFFSET 4
+#define SSC_SR_RXSYN_SIZE 1
+#define SSC_SR_RXSYN_OFFSET 11
+#define SSC_SR_TXBUFE_SIZE 1
+#define SSC_SR_TXBUFE_OFFSET 3
+#define SSC_SR_TXEMPTY_SIZE 1
+#define SSC_SR_TXEMPTY_OFFSET 1
+#define SSC_SR_TXEN_SIZE 1
+#define SSC_SR_TXEN_OFFSET 16
+#define SSC_SR_TXRDY_SIZE 1
+#define SSC_SR_TXRDY_OFFSET 0
+#define SSC_SR_TXSYN_SIZE 1
+#define SSC_SR_TXSYN_OFFSET 10
+
+/* SSC Interrupt Enable Register */
+#define SSC_IER 0x00000044
+#define SSC_IER_CP0_SIZE 1
+#define SSC_IER_CP0_OFFSET 8
+#define SSC_IER_CP1_SIZE 1
+#define SSC_IER_CP1_OFFSET 9
+#define SSC_IER_ENDRX_SIZE 1
+#define SSC_IER_ENDRX_OFFSET 6
+#define SSC_IER_ENDTX_SIZE 1
+#define SSC_IER_ENDTX_OFFSET 2
+#define SSC_IER_OVRUN_SIZE 1
+#define SSC_IER_OVRUN_OFFSET 5
+#define SSC_IER_RXBUFF_SIZE 1
+#define SSC_IER_RXBUFF_OFFSET 7
+#define SSC_IER_RXRDY_SIZE 1
+#define SSC_IER_RXRDY_OFFSET 4
+#define SSC_IER_RXSYN_SIZE 1
+#define SSC_IER_RXSYN_OFFSET 11
+#define SSC_IER_TXBUFE_SIZE 1
+#define SSC_IER_TXBUFE_OFFSET 3
+#define SSC_IER_TXEMPTY_SIZE 1
+#define SSC_IER_TXEMPTY_OFFSET 1
+#define SSC_IER_TXRDY_SIZE 1
+#define SSC_IER_TXRDY_OFFSET 0
+#define SSC_IER_TXSYN_SIZE 1
+#define SSC_IER_TXSYN_OFFSET 10
+
+/* SSC Interrupt Disable Register */
+#define SSC_IDR 0x00000048
+#define SSC_IDR_CP0_SIZE 1
+#define SSC_IDR_CP0_OFFSET 8
+#define SSC_IDR_CP1_SIZE 1
+#define SSC_IDR_CP1_OFFSET 9
+#define SSC_IDR_ENDRX_SIZE 1
+#define SSC_IDR_ENDRX_OFFSET 6
+#define SSC_IDR_ENDTX_SIZE 1
+#define SSC_IDR_ENDTX_OFFSET 2
+#define SSC_IDR_OVRUN_SIZE 1
+#define SSC_IDR_OVRUN_OFFSET 5
+#define SSC_IDR_RXBUFF_SIZE 1
+#define SSC_IDR_RXBUFF_OFFSET 7
+#define SSC_IDR_RXRDY_SIZE 1
+#define SSC_IDR_RXRDY_OFFSET 4
+#define SSC_IDR_RXSYN_SIZE 1
+#define SSC_IDR_RXSYN_OFFSET 11
+#define SSC_IDR_TXBUFE_SIZE 1
+#define SSC_IDR_TXBUFE_OFFSET 3
+#define SSC_IDR_TXEMPTY_SIZE 1
+#define SSC_IDR_TXEMPTY_OFFSET 1
+#define SSC_IDR_TXRDY_SIZE 1
+#define SSC_IDR_TXRDY_OFFSET 0
+#define SSC_IDR_TXSYN_SIZE 1
+#define SSC_IDR_TXSYN_OFFSET 10
+
+/* SSC Interrupt Mask Register */
+#define SSC_IMR 0x0000004c
+#define SSC_IMR_CP0_SIZE 1
+#define SSC_IMR_CP0_OFFSET 8
+#define SSC_IMR_CP1_SIZE 1
+#define SSC_IMR_CP1_OFFSET 9
+#define SSC_IMR_ENDRX_SIZE 1
+#define SSC_IMR_ENDRX_OFFSET 6
+#define SSC_IMR_ENDTX_SIZE 1
+#define SSC_IMR_ENDTX_OFFSET 2
+#define SSC_IMR_OVRUN_SIZE 1
+#define SSC_IMR_OVRUN_OFFSET 5
+#define SSC_IMR_RXBUFF_SIZE 1
+#define SSC_IMR_RXBUFF_OFFSET 7
+#define SSC_IMR_RXRDY_SIZE 1
+#define SSC_IMR_RXRDY_OFFSET 4
+#define SSC_IMR_RXSYN_SIZE 1
+#define SSC_IMR_RXSYN_OFFSET 11
+#define SSC_IMR_TXBUFE_SIZE 1
+#define SSC_IMR_TXBUFE_OFFSET 3
+#define SSC_IMR_TXEMPTY_SIZE 1
+#define SSC_IMR_TXEMPTY_OFFSET 1
+#define SSC_IMR_TXRDY_SIZE 1
+#define SSC_IMR_TXRDY_OFFSET 0
+#define SSC_IMR_TXSYN_SIZE 1
+#define SSC_IMR_TXSYN_OFFSET 10
+
+/* SSC PDC Receive Pointer Register */
+#define SSC_PDC_RPR 0x00000100
+
+/* SSC PDC Receive Counter Register */
+#define SSC_PDC_RCR 0x00000104
+
+/* SSC PDC Transmit Pointer Register */
+#define SSC_PDC_TPR 0x00000108
+
+/* SSC PDC Receive Next Pointer Register */
+#define SSC_PDC_RNPR 0x00000110
+
+/* SSC PDC Receive Next Counter Register */
+#define SSC_PDC_RNCR 0x00000114
+
+/* SSC PDC Transmit Counter Register */
+#define SSC_PDC_TCR 0x0000010c
+
+/* SSC PDC Transmit Next Pointer Register */
+#define SSC_PDC_TNPR 0x00000118
+
+/* SSC PDC Transmit Next Counter Register */
+#define SSC_PDC_TNCR 0x0000011c
+
+/* SSC PDC Transfer Control Register */
+#define SSC_PDC_PTCR 0x00000120
+#define SSC_PDC_PTCR_RXTDIS_SIZE 1
+#define SSC_PDC_PTCR_RXTDIS_OFFSET 1
+#define SSC_PDC_PTCR_RXTEN_SIZE 1
+#define SSC_PDC_PTCR_RXTEN_OFFSET 0
+#define SSC_PDC_PTCR_TXTDIS_SIZE 1
+#define SSC_PDC_PTCR_TXTDIS_OFFSET 9
+#define SSC_PDC_PTCR_TXTEN_SIZE 1
+#define SSC_PDC_PTCR_TXTEN_OFFSET 8
+
+/* SSC PDC Transfer Status Register */
+#define SSC_PDC_PTSR 0x00000124
+#define SSC_PDC_PTSR_RXTEN_SIZE 1
+#define SSC_PDC_PTSR_RXTEN_OFFSET 0
+#define SSC_PDC_PTSR_TXTEN_SIZE 1
+#define SSC_PDC_PTSR_TXTEN_OFFSET 8
+
+/* Bit manipulation macros */
+#define SSC_BIT(name) \
+ (1 << SSC_##name##_OFFSET)
+#define SSC_BF(name, value) \
+ (((value) & ((1 << SSC_##name##_SIZE) - 1)) \
+ << SSC_##name##_OFFSET)
+#define SSC_BFEXT(name, value) \
+ (((value) >> SSC_##name##_OFFSET) \
+ & ((1 << SSC_##name##_SIZE) - 1))
+#define SSC_BFINS(name, value, old) \
+ (((old) & ~(((1 << SSC_##name##_SIZE) - 1) \
+ << SSC_##name##_OFFSET)) | SSC_BF(name, value))
+
+/* Register access macros */
+#define ssc_readl(base, reg) __raw_readl(base + SSC_##reg)
+#define ssc_writel(base, reg, value) __raw_writel((value), base + SSC_##reg)
+
+#endif /* __INCLUDE_ATMEL_SSC_H */
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 9ae740936a65..c68781692838 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -63,6 +63,8 @@
#define AUDIT_ADD_RULE 1011 /* Add syscall filtering rule */
#define AUDIT_DEL_RULE 1012 /* Delete syscall filtering rule */
#define AUDIT_LIST_RULES 1013 /* List syscall filtering rules */
+#define AUDIT_TRIM 1014 /* Trim junk from watched tree */
+#define AUDIT_MAKE_EQUIV 1015 /* Append to watched tree */
#define AUDIT_TTY_GET 1016 /* Get TTY auditing status */
#define AUDIT_TTY_SET 1017 /* Set TTY auditing status */
@@ -203,6 +205,7 @@
#define AUDIT_SUCCESS 104 /* exit >= 0; value ignored */
#define AUDIT_WATCH 105
#define AUDIT_PERM 106
+#define AUDIT_DIR 107
#define AUDIT_ARG0 200
#define AUDIT_ARG1 (AUDIT_ARG0+1)
@@ -366,8 +369,8 @@ extern void audit_syscall_entry(int arch,
extern void audit_syscall_exit(int failed, long return_code);
extern void __audit_getname(const char *name);
extern void audit_putname(const char *name);
-extern void __audit_inode(const char *name, const struct inode *inode);
-extern void __audit_inode_child(const char *dname, const struct inode *inode,
+extern void __audit_inode(const char *name, const struct dentry *dentry);
+extern void __audit_inode_child(const char *dname, const struct dentry *dentry,
const struct inode *parent);
extern void __audit_ptrace(struct task_struct *t);
@@ -381,15 +384,15 @@ static inline void audit_getname(const char *name)
if (unlikely(!audit_dummy_context()))
__audit_getname(name);
}
-static inline void audit_inode(const char *name, const struct inode *inode) {
+static inline void audit_inode(const char *name, const struct dentry *dentry) {
if (unlikely(!audit_dummy_context()))
- __audit_inode(name, inode);
+ __audit_inode(name, dentry);
}
static inline void audit_inode_child(const char *dname,
- const struct inode *inode,
+ const struct dentry *dentry,
const struct inode *parent) {
if (unlikely(!audit_dummy_context()))
- __audit_inode_child(dname, inode, parent);
+ __audit_inode_child(dname, dentry, parent);
}
void audit_core_dumps(long signr);
@@ -477,9 +480,9 @@ extern int audit_signals;
#define audit_dummy_context() 1
#define audit_getname(n) do { ; } while (0)
#define audit_putname(n) do { ; } while (0)
-#define __audit_inode(n,i) do { ; } while (0)
+#define __audit_inode(n,d) do { ; } while (0)
#define __audit_inode_child(d,i,p) do { ; } while (0)
-#define audit_inode(n,i) do { ; } while (0)
+#define audit_inode(n,d) do { ; } while (0)
#define audit_inode_child(d,i,p) do { ; } while (0)
#define audit_core_dumps(i) do { ; } while (0)
#define auditsc_get_stamp(c,t,s) do { BUG(); } while (0)
diff --git a/include/linux/auxvec.h b/include/linux/auxvec.h
index d2bc0d66e65d..ad895455ab72 100644
--- a/include/linux/auxvec.h
+++ b/include/linux/auxvec.h
@@ -26,6 +26,8 @@
#define AT_SECURE 23 /* secure mode boolean */
-#define AT_VECTOR_SIZE 44 /* Size of auxiliary table. */
+#ifdef __KERNEL__
+#define AT_VECTOR_SIZE_BASE (14 + 2) /* NEW_AUX_ENT entries in auxiliary table */
+#endif
#endif /* _LINUX_AUXVEC_H */
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
index 7011d6255593..48a62baace58 100644
--- a/include/linux/backing-dev.h
+++ b/include/linux/backing-dev.h
@@ -8,6 +8,9 @@
#ifndef _LINUX_BACKING_DEV_H
#define _LINUX_BACKING_DEV_H
+#include <linux/percpu_counter.h>
+#include <linux/log2.h>
+#include <linux/proportions.h>
#include <asm/atomic.h>
struct page;
@@ -24,6 +27,14 @@ enum bdi_state {
typedef int (congested_fn)(void *, int);
+enum bdi_stat_item {
+ BDI_RECLAIMABLE,
+ BDI_WRITEBACK,
+ NR_BDI_STAT_ITEMS
+};
+
+#define BDI_STAT_BATCH (8*(1+ilog2(nr_cpu_ids)))
+
struct backing_dev_info {
unsigned long ra_pages; /* max readahead in PAGE_CACHE_SIZE units */
unsigned long state; /* Always use atomic bitops on this */
@@ -32,8 +43,90 @@ struct backing_dev_info {
void *congested_data; /* Pointer to aux data for congested func */
void (*unplug_io_fn)(struct backing_dev_info *, struct page *);
void *unplug_io_data;
+
+ struct percpu_counter bdi_stat[NR_BDI_STAT_ITEMS];
+
+ struct prop_local_percpu completions;
+ int dirty_exceeded;
};
+int bdi_init(struct backing_dev_info *bdi);
+void bdi_destroy(struct backing_dev_info *bdi);
+
+static inline void __add_bdi_stat(struct backing_dev_info *bdi,
+ enum bdi_stat_item item, s64 amount)
+{
+ __percpu_counter_add(&bdi->bdi_stat[item], amount, BDI_STAT_BATCH);
+}
+
+static inline void __inc_bdi_stat(struct backing_dev_info *bdi,
+ enum bdi_stat_item item)
+{
+ __add_bdi_stat(bdi, item, 1);
+}
+
+static inline void inc_bdi_stat(struct backing_dev_info *bdi,
+ enum bdi_stat_item item)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ __inc_bdi_stat(bdi, item);
+ local_irq_restore(flags);
+}
+
+static inline void __dec_bdi_stat(struct backing_dev_info *bdi,
+ enum bdi_stat_item item)
+{
+ __add_bdi_stat(bdi, item, -1);
+}
+
+static inline void dec_bdi_stat(struct backing_dev_info *bdi,
+ enum bdi_stat_item item)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ __dec_bdi_stat(bdi, item);
+ local_irq_restore(flags);
+}
+
+static inline s64 bdi_stat(struct backing_dev_info *bdi,
+ enum bdi_stat_item item)
+{
+ return percpu_counter_read_positive(&bdi->bdi_stat[item]);
+}
+
+static inline s64 __bdi_stat_sum(struct backing_dev_info *bdi,
+ enum bdi_stat_item item)
+{
+ return percpu_counter_sum_positive(&bdi->bdi_stat[item]);
+}
+
+static inline s64 bdi_stat_sum(struct backing_dev_info *bdi,
+ enum bdi_stat_item item)
+{
+ s64 sum;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ sum = __bdi_stat_sum(bdi, item);
+ local_irq_restore(flags);
+
+ return sum;
+}
+
+/*
+ * maximal error of a stat counter.
+ */
+static inline unsigned long bdi_stat_error(struct backing_dev_info *bdi)
+{
+#ifdef CONFIG_SMP
+ return nr_cpu_ids * BDI_STAT_BATCH;
+#else
+ return 1;
+#endif
+}
/*
* Flags in backing_dev_info::capability
@@ -93,7 +186,6 @@ static inline int bdi_rw_congested(struct backing_dev_info *bdi)
void clear_bdi_congested(struct backing_dev_info *bdi, int rw);
void set_bdi_congested(struct backing_dev_info *bdi, int rw);
long congestion_wait(int rw, long timeout);
-void congestion_end(int rw);
#define bdi_cap_writeback_dirty(bdi) \
(!((bdi)->capabilities & BDI_CAP_NO_WRITEBACK))
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index 91c8c07fe8b7..b7fc55ec8d48 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -37,7 +37,8 @@ struct linux_binprm{
int sh_bang;
struct file * file;
int e_uid, e_gid;
- kernel_cap_t cap_inheritable, cap_permitted, cap_effective;
+ kernel_cap_t cap_inheritable, cap_permitted;
+ bool cap_effective;
void *security;
int argc, envc;
char * filename; /* Name of binary as seen by procps */
@@ -63,17 +64,17 @@ struct linux_binprm{
* linux accepts.
*/
struct linux_binfmt {
- struct linux_binfmt * next;
+ struct list_head lh;
struct module *module;
int (*load_binary)(struct linux_binprm *, struct pt_regs * regs);
int (*load_shlib)(struct file *);
- int (*core_dump)(long signr, struct pt_regs * regs, struct file * file);
+ int (*core_dump)(long signr, struct pt_regs *regs, struct file *file, unsigned long limit);
unsigned long min_coredump; /* minimal dump size */
int hasvdso;
};
extern int register_binfmt(struct linux_binfmt *);
-extern int unregister_binfmt(struct linux_binfmt *);
+extern void unregister_binfmt(struct linux_binfmt *);
extern int prepare_binprm(struct linux_binprm *);
extern int __must_check remove_arg_zero(struct linux_binprm *);
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 089a8bc55dd4..4da441337d6e 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -176,13 +176,28 @@ struct bio {
#define bio_offset(bio) bio_iovec((bio))->bv_offset
#define bio_segments(bio) ((bio)->bi_vcnt - (bio)->bi_idx)
#define bio_sectors(bio) ((bio)->bi_size >> 9)
-#define bio_cur_sectors(bio) (bio_iovec(bio)->bv_len >> 9)
-#define bio_data(bio) (page_address(bio_page((bio))) + bio_offset((bio)))
#define bio_barrier(bio) ((bio)->bi_rw & (1 << BIO_RW_BARRIER))
#define bio_sync(bio) ((bio)->bi_rw & (1 << BIO_RW_SYNC))
#define bio_failfast(bio) ((bio)->bi_rw & (1 << BIO_RW_FAILFAST))
#define bio_rw_ahead(bio) ((bio)->bi_rw & (1 << BIO_RW_AHEAD))
#define bio_rw_meta(bio) ((bio)->bi_rw & (1 << BIO_RW_META))
+#define bio_empty_barrier(bio) (bio_barrier(bio) && !(bio)->bi_size)
+
+static inline unsigned int bio_cur_sectors(struct bio *bio)
+{
+ if (bio->bi_vcnt)
+ return bio_iovec(bio)->bv_len >> 9;
+
+ return 0;
+}
+
+static inline void *bio_data(struct bio *bio)
+{
+ if (bio->bi_vcnt)
+ return page_address(bio_page(bio)) + bio_offset(bio);
+
+ return NULL;
+}
/*
* will die
diff --git a/include/linux/bit_spinlock.h b/include/linux/bit_spinlock.h
index 6b20af0bbb79..7113a32a86ea 100644
--- a/include/linux/bit_spinlock.h
+++ b/include/linux/bit_spinlock.h
@@ -18,7 +18,7 @@ static inline void bit_spin_lock(int bitnum, unsigned long *addr)
*/
preempt_disable();
#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
- while (test_and_set_bit(bitnum, addr)) {
+ while (unlikely(test_and_set_bit_lock(bitnum, addr))) {
while (test_bit(bitnum, addr)) {
preempt_enable();
cpu_relax();
@@ -36,7 +36,7 @@ static inline int bit_spin_trylock(int bitnum, unsigned long *addr)
{
preempt_disable();
#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
- if (test_and_set_bit(bitnum, addr)) {
+ if (unlikely(test_and_set_bit_lock(bitnum, addr))) {
preempt_enable();
return 0;
}
@@ -50,10 +50,28 @@ static inline int bit_spin_trylock(int bitnum, unsigned long *addr)
*/
static inline void bit_spin_unlock(int bitnum, unsigned long *addr)
{
+#ifdef CONFIG_DEBUG_SPINLOCK
+ BUG_ON(!test_bit(bitnum, addr));
+#endif
#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
+ clear_bit_unlock(bitnum, addr);
+#endif
+ preempt_enable();
+ __release(bitlock);
+}
+
+/*
+ * bit-based spin_unlock()
+ * non-atomic version, which can be used eg. if the bit lock itself is
+ * protecting the rest of the flags in the word.
+ */
+static inline void __bit_spin_unlock(int bitnum, unsigned long *addr)
+{
+#ifdef CONFIG_DEBUG_SPINLOCK
BUG_ON(!test_bit(bitnum, addr));
- smp_mb__before_clear_bit();
- clear_bit(bitnum, addr);
+#endif
+#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
+ __clear_bit_unlock(bitnum, addr);
#endif
preempt_enable();
__release(bitlock);
diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index 64b4641904fe..acad1105d942 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -6,6 +6,7 @@
#include <linux/types.h>
#include <linux/bitops.h>
#include <linux/string.h>
+#include <linux/kernel.h>
/*
* bitmaps provide bit arrays that consume one or more unsigned
diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index 638165f571da..69c1edb9fe54 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -2,12 +2,26 @@
#define _LINUX_BITOPS_H
#include <asm/types.h>
+#ifdef __KERNEL__
+#define BIT(nr) (1UL << (nr))
+#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
+#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
+#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_LONG)
+#define BITS_PER_BYTE 8
+#endif
+
/*
* Include this here because some architectures need generic_ffs/fls in
* scope
*/
#include <asm/bitops.h>
+#define for_each_bit(bit, addr, size) \
+ for ((bit) = find_first_bit((addr), (size)); \
+ (bit) < (size); \
+ (bit) = find_next_bit((addr), (size), (bit) + 1))
+
+
static __inline__ int get_bitmask_order(unsigned int count)
{
int order;
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 5ed888b04b29..d18ee67b40f8 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -330,7 +330,6 @@ typedef void (unplug_fn) (struct request_queue *);
struct bio_vec;
typedef int (merge_bvec_fn) (struct request_queue *, struct bio *, struct bio_vec *);
-typedef int (issue_flush_fn) (struct request_queue *, struct gendisk *, sector_t *);
typedef void (prepare_flush_fn) (struct request_queue *, struct request *);
typedef void (softirq_done_fn)(struct request *);
@@ -342,7 +341,6 @@ enum blk_queue_state {
struct blk_queue_tag {
struct request **tag_index; /* map of busy tags */
unsigned long *tag_map; /* bit map of free/busy tags */
- struct list_head busy_list; /* fifo list of busy tags */
int busy; /* current depth */
int max_depth; /* what we will send to device */
int real_max_depth; /* what the array can hold */
@@ -368,7 +366,6 @@ struct request_queue
prep_rq_fn *prep_rq_fn;
unplug_fn *unplug_fn;
merge_bvec_fn *merge_bvec_fn;
- issue_flush_fn *issue_flush_fn;
prepare_flush_fn *prepare_flush_fn;
softirq_done_fn *softirq_done_fn;
@@ -437,6 +434,7 @@ struct request_queue
unsigned int dma_alignment;
struct blk_queue_tag *queue_tags;
+ struct list_head tag_busy_list;
unsigned int nr_sorted;
unsigned int in_flight;
@@ -540,6 +538,7 @@ enum {
#define blk_barrier_rq(rq) ((rq)->cmd_flags & REQ_HARDBARRIER)
#define blk_fua_rq(rq) ((rq)->cmd_flags & REQ_FUA)
#define blk_bidi_rq(rq) ((rq)->next_rq != NULL)
+#define blk_empty_barrier(rq) (blk_barrier_rq(rq) && blk_fs_request(rq) && !(rq)->hard_nr_sectors)
#define list_entry_rq(ptr) list_entry((ptr), struct request, queuelist)
@@ -698,6 +697,7 @@ extern int blk_execute_rq(struct request_queue *, struct gendisk *,
extern void blk_execute_rq_nowait(struct request_queue *, struct gendisk *,
struct request *, int, rq_end_io_fn *);
extern int blk_verify_command(unsigned char *, int);
+extern void blk_unplug(struct request_queue *q);
static inline struct request_queue *bdev_get_queue(struct block_device *bdev)
{
@@ -729,7 +729,9 @@ static inline void blk_run_address_space(struct address_space *mapping)
extern int end_that_request_first(struct request *, int, int);
extern int end_that_request_chunk(struct request *, int, int);
extern void end_that_request_last(struct request *, int);
-extern void end_request(struct request *req, int uptodate);
+extern void end_request(struct request *, int);
+extern void end_queued_request(struct request *, int);
+extern void end_dequeued_request(struct request *, int);
extern void blk_complete_request(struct request *);
/*
@@ -767,7 +769,6 @@ extern void blk_queue_dma_alignment(struct request_queue *, int);
extern void blk_queue_softirq_done(struct request_queue *, softirq_done_fn *);
extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev);
extern int blk_queue_ordered(struct request_queue *, unsigned, prepare_flush_fn *);
-extern void blk_queue_issue_flush_fn(struct request_queue *, issue_flush_fn *);
extern int blk_do_ordered(struct request_queue *, struct request **);
extern unsigned blk_ordered_cur_seq(struct request_queue *);
extern unsigned blk_ordered_req_seq(struct request *);
diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h
index c83534ee1e79..0365ec9fc0c9 100644
--- a/include/linux/bootmem.h
+++ b/include/linux/bootmem.h
@@ -59,7 +59,6 @@ extern void *__alloc_bootmem_core(struct bootmem_data *bdata,
unsigned long align,
unsigned long goal,
unsigned long limit);
-extern void *alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size);
#ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE
extern void reserve_bootmem(unsigned long addr, unsigned long size);
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index 35cadad84b14..da0d83fbadc0 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -203,10 +203,20 @@ void block_invalidatepage(struct page *page, unsigned long offset);
int block_write_full_page(struct page *page, get_block_t *get_block,
struct writeback_control *wbc);
int block_read_full_page(struct page*, get_block_t*);
+int block_write_begin(struct file *, struct address_space *,
+ loff_t, unsigned, unsigned,
+ struct page **, void **, get_block_t*);
+int block_write_end(struct file *, struct address_space *,
+ loff_t, unsigned, unsigned,
+ struct page *, void *);
+int generic_write_end(struct file *, struct address_space *,
+ loff_t, unsigned, unsigned,
+ struct page *, void *);
+void page_zero_new_buffers(struct page *page, unsigned from, unsigned to);
int block_prepare_write(struct page*, unsigned, unsigned, get_block_t*);
-int cont_prepare_write(struct page*, unsigned, unsigned, get_block_t*,
- loff_t *);
-int generic_cont_expand(struct inode *inode, loff_t size);
+int cont_write_begin(struct file *, struct address_space *, loff_t,
+ unsigned, unsigned, struct page **, void **,
+ get_block_t *, loff_t *);
int generic_cont_expand_simple(struct inode *inode, loff_t size);
int block_commit_write(struct page *page, unsigned from, unsigned to);
int block_page_mkwrite(struct vm_area_struct *vma, struct page *page,
@@ -216,9 +226,13 @@ sector_t generic_block_bmap(struct address_space *, sector_t, get_block_t *);
int generic_commit_write(struct file *, struct page *, unsigned, unsigned);
int block_truncate_page(struct address_space *, loff_t, get_block_t *);
int file_fsync(struct file *, struct dentry *, int);
-int nobh_prepare_write(struct page*, unsigned, unsigned, get_block_t*);
-int nobh_commit_write(struct file *, struct page *, unsigned, unsigned);
-int nobh_truncate_page(struct address_space *, loff_t);
+int nobh_write_begin(struct file *, struct address_space *,
+ loff_t, unsigned, unsigned,
+ struct page **, void **, get_block_t*);
+int nobh_write_end(struct file *, struct address_space *,
+ loff_t, unsigned, unsigned,
+ struct page *, void *);
+int nobh_truncate_page(struct address_space *, loff_t, get_block_t *);
int nobh_writepage(struct page *page, get_block_t *get_block,
struct writeback_control *wbc);
diff --git a/include/linux/capability.h b/include/linux/capability.h
index 2dfa58555934..bb017edffd56 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -1,14 +1,14 @@
/*
* This is <linux/capability.h>
*
- * Andrew G. Morgan <morgan@transmeta.com>
+ * Andrew G. Morgan <morgan@kernel.org>
* Alexander Kjeldaas <astor@guardian.no>
* with help from Aleph1, Roland Buresund and Andrew Main.
*
* See here for the libcap library ("POSIX draft" compliance):
*
- * ftp://linux.kernel.org/pub/linux/libs/security/linux-privs/kernel-2.2/
- */
+ * ftp://linux.kernel.org/pub/linux/libs/security/linux-privs/kernel-2.6/
+ */
#ifndef _LINUX_CAPABILITY_H
#define _LINUX_CAPABILITY_H
@@ -28,23 +28,39 @@ struct task_struct;
following structure to such a composite is better handled in a user
library since the draft standard requires the use of malloc/free
etc.. */
-
+
#define _LINUX_CAPABILITY_VERSION 0x19980330
typedef struct __user_cap_header_struct {
__u32 version;
int pid;
} __user *cap_user_header_t;
-
+
typedef struct __user_cap_data_struct {
__u32 effective;
__u32 permitted;
__u32 inheritable;
} __user *cap_user_data_t;
-
-#ifdef __KERNEL__
-#include <asm/current.h>
+#define XATTR_CAPS_SUFFIX "capability"
+#define XATTR_NAME_CAPS XATTR_SECURITY_PREFIX XATTR_CAPS_SUFFIX
+
+#define XATTR_CAPS_SZ (3*sizeof(__le32))
+#define VFS_CAP_REVISION_MASK 0xFF000000
+#define VFS_CAP_REVISION_1 0x01000000
+
+#define VFS_CAP_REVISION VFS_CAP_REVISION_1
+
+#define VFS_CAP_FLAGS_MASK ~VFS_CAP_REVISION_MASK
+#define VFS_CAP_FLAGS_EFFECTIVE 0x000001
+
+struct vfs_cap_data {
+ __u32 magic_etc; /* Little endian */
+ __u32 permitted; /* Little endian */
+ __u32 inheritable; /* Little endian */
+};
+
+#ifdef __KERNEL__
/* #define STRICT_CAP_T_TYPECHECKS */
@@ -59,7 +75,7 @@ typedef struct kernel_cap_struct {
typedef __u32 kernel_cap_t;
#endif
-
+
#define _USER_CAP_HEADER_SIZE (2*sizeof(__u32))
#define _KERNEL_CAP_T_SIZE (sizeof(kernel_cap_t))
@@ -67,7 +83,7 @@ typedef __u32 kernel_cap_t;
/**
- ** POSIX-draft defined capabilities.
+ ** POSIX-draft defined capabilities.
**/
/* In a system with the [_POSIX_CHOWN_RESTRICTED] option defined, this
@@ -87,7 +103,7 @@ typedef __u32 kernel_cap_t;
defined. Excluding DAC access covered by CAP_LINUX_IMMUTABLE. */
#define CAP_DAC_READ_SEARCH 2
-
+
/* Overrides all restrictions about allowed operations on files, where
file owner ID must be equal to the user ID, except where CAP_FSETID
is applicable. It doesn't override MAC and DAC restrictions. */
@@ -257,7 +273,7 @@ typedef __u32 kernel_cap_t;
/* Override reserved space on ext2 filesystem */
/* Modify data journaling mode on ext3 filesystem (uses journaling
resources) */
-/* NOTE: ext2 honors fsuid when checking for resource overrides, so
+/* NOTE: ext2 honors fsuid when checking for resource overrides, so
you can override using fsuid too */
/* Override size restrictions on IPC message queues */
/* Allow more than 64hz interrupts from the real-time clock */
@@ -289,16 +305,14 @@ typedef __u32 kernel_cap_t;
#define CAP_AUDIT_CONTROL 30
+#define CAP_SETFCAP 31
+
#ifdef __KERNEL__
-/*
- * Bounding set
- */
-extern kernel_cap_t cap_bset;
/*
* Internal kernel functions only
*/
-
+
#ifdef STRICT_CAP_T_TYPECHECKS
#define to_cap_t(x) { x }
diff --git a/include/linux/cdrom.h b/include/linux/cdrom.h
index 2b641b176e7f..c6d3e22c0624 100644
--- a/include/linux/cdrom.h
+++ b/include/linux/cdrom.h
@@ -2,7 +2,7 @@
* -- <linux/cdrom.h>
* General header file for linux CD-ROM drivers
* Copyright (C) 1992 David Giller, rafetmad@oxy.edu
- * 1994, 1995 Eberhard Moenkeberg, emoenke@gwdg.de
+ * 1994, 1995 Eberhard Mönkeberg, emoenke@gwdg.de
* 1996 David van Leeuwen, david@tm.tno.nl
* 1997, 1998 Erik Andersen, andersee@debian.org
* 1998-2002 Jens Axboe, axboe@suse.de
@@ -76,7 +76,7 @@
(struct cdrom_multisession) */
#define CDROM_GET_MCN 0x5311 /* Obtain the "Universal Product Code"
if available (struct cdrom_mcn) */
-#define CDROM_GET_UPC CDROM_GET_MCN /* This one is depricated,
+#define CDROM_GET_UPC CDROM_GET_MCN /* This one is deprecated,
but here anyway for compatibility */
#define CDROMRESET 0x5312 /* hard-reset the drive */
#define CDROMVOLREAD 0x5313 /* Get the drive's volume setting
@@ -506,7 +506,7 @@ struct cdrom_generic_command
#define GPMODE_TO_PROTECT_PAGE 0x1d
#define GPMODE_CAPABILITIES_PAGE 0x2a
#define GPMODE_ALL_PAGES 0x3f
-/* Not in Mt. Fuji, but in ATAPI 2.6 -- depricated now in favor
+/* Not in Mt. Fuji, but in ATAPI 2.6 -- deprecated now in favor
* of MODE_SENSE_POWER_PAGE */
#define GPMODE_CDROM_PAGE 0x0d
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
new file mode 100644
index 000000000000..87479328d46d
--- /dev/null
+++ b/include/linux/cgroup.h
@@ -0,0 +1,327 @@
+#ifndef _LINUX_CGROUP_H
+#define _LINUX_CGROUP_H
+/*
+ * cgroup interface
+ *
+ * Copyright (C) 2003 BULL SA
+ * Copyright (C) 2004-2006 Silicon Graphics, Inc.
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/kref.h>
+#include <linux/cpumask.h>
+#include <linux/nodemask.h>
+#include <linux/rcupdate.h>
+#include <linux/cgroupstats.h>
+
+#ifdef CONFIG_CGROUPS
+
+struct cgroupfs_root;
+struct cgroup_subsys;
+struct inode;
+
+extern int cgroup_init_early(void);
+extern int cgroup_init(void);
+extern void cgroup_init_smp(void);
+extern void cgroup_lock(void);
+extern void cgroup_unlock(void);
+extern void cgroup_fork(struct task_struct *p);
+extern void cgroup_fork_callbacks(struct task_struct *p);
+extern void cgroup_post_fork(struct task_struct *p);
+extern void cgroup_exit(struct task_struct *p, int run_callbacks);
+extern int cgroupstats_build(struct cgroupstats *stats,
+ struct dentry *dentry);
+
+extern struct file_operations proc_cgroup_operations;
+
+/* Define the enumeration of all cgroup subsystems */
+#define SUBSYS(_x) _x ## _subsys_id,
+enum cgroup_subsys_id {
+#include <linux/cgroup_subsys.h>
+ CGROUP_SUBSYS_COUNT
+};
+#undef SUBSYS
+
+/* Per-subsystem/per-cgroup state maintained by the system. */
+struct cgroup_subsys_state {
+ /* The cgroup that this subsystem is attached to. Useful
+ * for subsystems that want to know about the cgroup
+ * hierarchy structure */
+ struct cgroup *cgroup;
+
+ /* State maintained by the cgroup system to allow
+ * subsystems to be "busy". Should be accessed via css_get()
+ * and css_put() */
+
+ atomic_t refcnt;
+
+ unsigned long flags;
+};
+
+/* bits in struct cgroup_subsys_state flags field */
+enum {
+ CSS_ROOT, /* This CSS is the root of the subsystem */
+};
+
+/*
+ * Call css_get() to hold a reference on the cgroup;
+ *
+ */
+
+static inline void css_get(struct cgroup_subsys_state *css)
+{
+ /* We don't need to reference count the root state */
+ if (!test_bit(CSS_ROOT, &css->flags))
+ atomic_inc(&css->refcnt);
+}
+/*
+ * css_put() should be called to release a reference taken by
+ * css_get()
+ */
+
+extern void __css_put(struct cgroup_subsys_state *css);
+static inline void css_put(struct cgroup_subsys_state *css)
+{
+ if (!test_bit(CSS_ROOT, &css->flags))
+ __css_put(css);
+}
+
+struct cgroup {
+ unsigned long flags; /* "unsigned long" so bitops work */
+
+ /* count users of this cgroup. >0 means busy, but doesn't
+ * necessarily indicate the number of tasks in the
+ * cgroup */
+ atomic_t count;
+
+ /*
+ * We link our 'sibling' struct into our parent's 'children'.
+ * Our children link their 'sibling' into our 'children'.
+ */
+ struct list_head sibling; /* my parent's children */
+ struct list_head children; /* my children */
+
+ struct cgroup *parent; /* my parent */
+ struct dentry *dentry; /* cgroup fs entry */
+
+ /* Private pointers for each registered subsystem */
+ struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT];
+
+ struct cgroupfs_root *root;
+ struct cgroup *top_cgroup;
+
+ /*
+ * List of cg_cgroup_links pointing at css_sets with
+ * tasks in this cgroup. Protected by css_set_lock
+ */
+ struct list_head css_sets;
+
+ /*
+ * Linked list running through all cgroups that can
+ * potentially be reaped by the release agent. Protected by
+ * release_list_lock
+ */
+ struct list_head release_list;
+};
+
+/* A css_set is a structure holding pointers to a set of
+ * cgroup_subsys_state objects. This saves space in the task struct
+ * object and speeds up fork()/exit(), since a single inc/dec and a
+ * list_add()/del() can bump the reference count on the entire
+ * cgroup set for a task.
+ */
+
+struct css_set {
+
+ /* Reference count */
+ struct kref ref;
+
+ /*
+ * List running through all cgroup groups. Protected by
+ * css_set_lock
+ */
+ struct list_head list;
+
+ /*
+ * List running through all tasks using this cgroup
+ * group. Protected by css_set_lock
+ */
+ struct list_head tasks;
+
+ /*
+ * List of cg_cgroup_link objects on link chains from
+ * cgroups referenced from this css_set. Protected by
+ * css_set_lock
+ */
+ struct list_head cg_links;
+
+ /*
+ * Set of subsystem states, one for each subsystem. This array
+ * is immutable after creation apart from the init_css_set
+ * during subsystem registration (at boot time).
+ */
+ struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT];
+
+};
+
+/* struct cftype:
+ *
+ * The files in the cgroup filesystem mostly have a very simple read/write
+ * handling, some common function will take care of it. Nevertheless some cases
+ * (read tasks) are special and therefore I define this structure for every
+ * kind of file.
+ *
+ *
+ * When reading/writing to a file:
+ * - the cgroup to use in file->f_dentry->d_parent->d_fsdata
+ * - the 'cftype' of the file is file->f_dentry->d_fsdata
+ */
+
+#define MAX_CFTYPE_NAME 64
+struct cftype {
+ /* By convention, the name should begin with the name of the
+ * subsystem, followed by a period */
+ char name[MAX_CFTYPE_NAME];
+ int private;
+ int (*open) (struct inode *inode, struct file *file);
+ ssize_t (*read) (struct cgroup *cont, struct cftype *cft,
+ struct file *file,
+ char __user *buf, size_t nbytes, loff_t *ppos);
+ /*
+ * read_uint() is a shortcut for the common case of returning a
+ * single integer. Use it in place of read()
+ */
+ u64 (*read_uint) (struct cgroup *cont, struct cftype *cft);
+ ssize_t (*write) (struct cgroup *cont, struct cftype *cft,
+ struct file *file,
+ const char __user *buf, size_t nbytes, loff_t *ppos);
+
+ /*
+ * write_uint() is a shortcut for the common case of accepting
+ * a single integer (as parsed by simple_strtoull) from
+ * userspace. Use in place of write(); return 0 or error.
+ */
+ int (*write_uint) (struct cgroup *cont, struct cftype *cft, u64 val);
+
+ int (*release) (struct inode *inode, struct file *file);
+};
+
+/* Add a new file to the given cgroup directory. Should only be
+ * called by subsystems from within a populate() method */
+int cgroup_add_file(struct cgroup *cont, struct cgroup_subsys *subsys,
+ const struct cftype *cft);
+
+/* Add a set of new files to the given cgroup directory. Should
+ * only be called by subsystems from within a populate() method */
+int cgroup_add_files(struct cgroup *cont,
+ struct cgroup_subsys *subsys,
+ const struct cftype cft[],
+ int count);
+
+int cgroup_is_removed(const struct cgroup *cont);
+
+int cgroup_path(const struct cgroup *cont, char *buf, int buflen);
+
+int cgroup_task_count(const struct cgroup *cont);
+
+/* Return true if the cgroup is a descendant of the current cgroup */
+int cgroup_is_descendant(const struct cgroup *cont);
+
+/* Control Group subsystem type. See Documentation/cgroups.txt for details */
+
+struct cgroup_subsys {
+ struct cgroup_subsys_state *(*create)(struct cgroup_subsys *ss,
+ struct cgroup *cont);
+ void (*destroy)(struct cgroup_subsys *ss, struct cgroup *cont);
+ int (*can_attach)(struct cgroup_subsys *ss,
+ struct cgroup *cont, struct task_struct *tsk);
+ void (*attach)(struct cgroup_subsys *ss, struct cgroup *cont,
+ struct cgroup *old_cont, struct task_struct *tsk);
+ void (*fork)(struct cgroup_subsys *ss, struct task_struct *task);
+ void (*exit)(struct cgroup_subsys *ss, struct task_struct *task);
+ int (*populate)(struct cgroup_subsys *ss,
+ struct cgroup *cont);
+ void (*post_clone)(struct cgroup_subsys *ss, struct cgroup *cont);
+ void (*bind)(struct cgroup_subsys *ss, struct cgroup *root);
+ int subsys_id;
+ int active;
+ int early_init;
+#define MAX_CGROUP_TYPE_NAMELEN 32
+ const char *name;
+
+ /* Protected by RCU */
+ struct cgroupfs_root *root;
+
+ struct list_head sibling;
+
+ void *private;
+};
+
+#define SUBSYS(_x) extern struct cgroup_subsys _x ## _subsys;
+#include <linux/cgroup_subsys.h>
+#undef SUBSYS
+
+static inline struct cgroup_subsys_state *cgroup_subsys_state(
+ struct cgroup *cont, int subsys_id)
+{
+ return cont->subsys[subsys_id];
+}
+
+static inline struct cgroup_subsys_state *task_subsys_state(
+ struct task_struct *task, int subsys_id)
+{
+ return rcu_dereference(task->cgroups->subsys[subsys_id]);
+}
+
+static inline struct cgroup* task_cgroup(struct task_struct *task,
+ int subsys_id)
+{
+ return task_subsys_state(task, subsys_id)->cgroup;
+}
+
+int cgroup_path(const struct cgroup *cont, char *buf, int buflen);
+
+int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *ss);
+
+/* A cgroup_iter should be treated as an opaque object */
+struct cgroup_iter {
+ struct list_head *cg_link;
+ struct list_head *task;
+};
+
+/* To iterate across the tasks in a cgroup:
+ *
+ * 1) call cgroup_iter_start to intialize an iterator
+ *
+ * 2) call cgroup_iter_next() to retrieve member tasks until it
+ * returns NULL or until you want to end the iteration
+ *
+ * 3) call cgroup_iter_end() to destroy the iterator.
+ */
+void cgroup_iter_start(struct cgroup *cont, struct cgroup_iter *it);
+struct task_struct *cgroup_iter_next(struct cgroup *cont,
+ struct cgroup_iter *it);
+void cgroup_iter_end(struct cgroup *cont, struct cgroup_iter *it);
+
+#else /* !CONFIG_CGROUPS */
+
+static inline int cgroup_init_early(void) { return 0; }
+static inline int cgroup_init(void) { return 0; }
+static inline void cgroup_init_smp(void) {}
+static inline void cgroup_fork(struct task_struct *p) {}
+static inline void cgroup_fork_callbacks(struct task_struct *p) {}
+static inline void cgroup_post_fork(struct task_struct *p) {}
+static inline void cgroup_exit(struct task_struct *p, int callbacks) {}
+
+static inline void cgroup_lock(void) {}
+static inline void cgroup_unlock(void) {}
+static inline int cgroupstats_build(struct cgroupstats *stats,
+ struct dentry *dentry)
+{
+ return -EINVAL;
+}
+
+#endif /* !CONFIG_CGROUPS */
+
+#endif /* _LINUX_CGROUP_H */
diff --git a/include/linux/cgroup_subsys.h b/include/linux/cgroup_subsys.h
new file mode 100644
index 000000000000..d62fcee9a08a
--- /dev/null
+++ b/include/linux/cgroup_subsys.h
@@ -0,0 +1,32 @@
+/* Add subsystem definitions of the form SUBSYS(<name>) in this
+ * file. Surround each one by a line of comment markers so that
+ * patches don't collide
+ */
+
+/* */
+
+/* */
+
+#ifdef CONFIG_CPUSETS
+SUBSYS(cpuset)
+#endif
+
+/* */
+
+#ifdef CONFIG_CGROUP_DEBUG
+SUBSYS(debug)
+#endif
+
+/* */
+
+#ifdef CONFIG_CGROUP_NS
+SUBSYS(ns)
+#endif
+
+/* */
+
+#ifdef CONFIG_FAIR_CGROUP_SCHED
+SUBSYS(cpu_cgroup)
+#endif
+
+/* */
diff --git a/include/linux/cgroupstats.h b/include/linux/cgroupstats.h
new file mode 100644
index 000000000000..4f53abf6855d
--- /dev/null
+++ b/include/linux/cgroupstats.h
@@ -0,0 +1,70 @@
+/* cgroupstats.h - exporting per-cgroup statistics
+ *
+ * Copyright IBM Corporation, 2007
+ * Author Balbir Singh <balbir@linux.vnet.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2.1 of the GNU Lesser General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef _LINUX_CGROUPSTATS_H
+#define _LINUX_CGROUPSTATS_H
+
+#include <linux/taskstats.h>
+
+/*
+ * Data shared between user space and kernel space on a per cgroup
+ * basis. This data is shared using taskstats.
+ *
+ * Most of these states are derived by looking at the task->state value
+ * For the nr_io_wait state, a flag in the delay accounting structure
+ * indicates that the task is waiting on IO
+ *
+ * Each member is aligned to a 8 byte boundary.
+ */
+struct cgroupstats {
+ __u64 nr_sleeping; /* Number of tasks sleeping */
+ __u64 nr_running; /* Number of tasks running */
+ __u64 nr_stopped; /* Number of tasks in stopped state */
+ __u64 nr_uninterruptible; /* Number of tasks in uninterruptible */
+ /* state */
+ __u64 nr_io_wait; /* Number of tasks waiting on IO */
+};
+
+/*
+ * Commands sent from userspace
+ * Not versioned. New commands should only be inserted at the enum's end
+ * prior to __CGROUPSTATS_CMD_MAX
+ */
+
+enum {
+ CGROUPSTATS_CMD_UNSPEC = __TASKSTATS_CMD_MAX, /* Reserved */
+ CGROUPSTATS_CMD_GET, /* user->kernel request/get-response */
+ CGROUPSTATS_CMD_NEW, /* kernel->user event */
+ __CGROUPSTATS_CMD_MAX,
+};
+
+#define CGROUPSTATS_CMD_MAX (__CGROUPSTATS_CMD_MAX - 1)
+
+enum {
+ CGROUPSTATS_TYPE_UNSPEC = 0, /* Reserved */
+ CGROUPSTATS_TYPE_CGROUP_STATS, /* contains name + stats */
+ __CGROUPSTATS_TYPE_MAX,
+};
+
+#define CGROUPSTATS_TYPE_MAX (__CGROUPSTATS_TYPE_MAX - 1)
+
+enum {
+ CGROUPSTATS_CMD_ATTR_UNSPEC = 0,
+ CGROUPSTATS_CMD_ATTR_FD,
+ __CGROUPSTATS_CMD_ATTR_MAX,
+};
+
+#define CGROUPSTATS_CMD_ATTR_MAX (__CGROUPSTATS_CMD_ATTR_MAX - 1)
+
+#endif /* _LINUX_CGROUPSTATS_H */
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index 16ea3374dddf..107787aacb64 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -221,10 +221,15 @@ extern void clocksource_resume(void);
#ifdef CONFIG_GENERIC_TIME_VSYSCALL
extern void update_vsyscall(struct timespec *ts, struct clocksource *c);
+extern void update_vsyscall_tz(void);
#else
static inline void update_vsyscall(struct timespec *ts, struct clocksource *c)
{
}
+
+static inline void update_vsyscall_tz(void)
+{
+}
#endif
#endif /* _LINUX_CLOCKSOURCE_H */
diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h
index 03ec2311fb29..fe23792f05c1 100644
--- a/include/linux/compiler-gcc.h
+++ b/include/linux/compiler-gcc.h
@@ -1,4 +1,6 @@
-/* Never include this file directly. Include <linux/compiler.h> instead. */
+#ifndef __LINUX_COMPILER_H
+#error "Please don't include <linux/compiler-gcc.h> directly, include <linux/compiler.h> instead."
+#endif
/*
* Common definitions for all gcc versions go here.
@@ -34,10 +36,20 @@
#define __weak __attribute__((weak))
#define __naked __attribute__((naked))
#define __noreturn __attribute__((noreturn))
+
+/*
+ * From the GCC manual:
+ *
+ * Many functions have no effects except the return value and their
+ * return value depends only on the parameters and/or global
+ * variables. Such a function can be subject to common subexpression
+ * elimination and loop optimization just as an arithmetic operator
+ * would be.
+ * [...]
+ */
#define __pure __attribute__((pure))
#define __aligned(x) __attribute__((aligned(x)))
#define __printf(a,b) __attribute__((format(printf,a,b)))
#define noinline __attribute__((noinline))
-#define __attribute_pure__ __attribute__((pure))
#define __attribute_const__ __attribute__((__const__))
#define __maybe_unused __attribute__((unused))
diff --git a/include/linux/compiler-gcc3.h b/include/linux/compiler-gcc3.h
index a9e2863c2dbf..2d8c0f48f55e 100644
--- a/include/linux/compiler-gcc3.h
+++ b/include/linux/compiler-gcc3.h
@@ -1,4 +1,6 @@
-/* Never include this file directly. Include <linux/compiler.h> instead. */
+#ifndef __LINUX_COMPILER_H
+#error "Please don't include <linux/compiler-gcc3.h> directly, include <linux/compiler.h> instead."
+#endif
/* These definitions are for GCC v3.x. */
#include <linux/compiler-gcc.h>
diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h
index 14f7494280f0..ee7ca5de970c 100644
--- a/include/linux/compiler-gcc4.h
+++ b/include/linux/compiler-gcc4.h
@@ -1,4 +1,6 @@
-/* Never include this file directly. Include <linux/compiler.h> instead. */
+#ifndef __LINUX_COMPILER_H
+#error "Please don't include <linux/compiler-gcc4.h> directly, include <linux/compiler.h> instead."
+#endif
/* These definitions are for GCC v4.x. */
#include <linux/compiler-gcc.h>
diff --git a/include/linux/compiler-intel.h b/include/linux/compiler-intel.h
index b769961e6f23..d8e636e5607d 100644
--- a/include/linux/compiler-intel.h
+++ b/include/linux/compiler-intel.h
@@ -1,4 +1,6 @@
-/* Never include this file directly. Include <linux/compiler.h> instead. */
+#ifndef __LINUX_COMPILER_H
+#error "Please don't include <linux/compiler-intel.h> directly, include <linux/compiler.h> instead."
+#endif
#ifdef __ECC
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 86f9a3a6137d..c68b67b86ef1 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -101,6 +101,12 @@ extern void __chk_io_ptr(const volatile void __iomem *);
#undef __must_check
#define __must_check
#endif
+#ifndef CONFIG_ENABLE_WARN_DEPRECATED
+#undef __deprecated
+#undef __deprecated_for_modules
+#define __deprecated
+#define __deprecated_for_modules
+#endif
/*
* Allow us to avoid 'defined but not used' warnings on functions and data,
@@ -132,20 +138,6 @@ extern void __chk_io_ptr(const volatile void __iomem *);
# define __maybe_unused /* unimplemented */
#endif
-/*
- * From the GCC manual:
- *
- * Many functions have no effects except the return value and their
- * return value depends only on the parameters and/or global
- * variables. Such a function can be subject to common subexpression
- * elimination and loop optimization just as an arithmetic operator
- * would be.
- * [...]
- */
-#ifndef __attribute_pure__
-# define __attribute_pure__ /* unimplemented */
-#endif
-
#ifndef noinline
#define noinline
#endif
diff --git a/include/linux/completion.h b/include/linux/completion.h
index 268c5a4a2bd4..33d6aaf94447 100644
--- a/include/linux/completion.h
+++ b/include/linux/completion.h
@@ -42,15 +42,15 @@ static inline void init_completion(struct completion *x)
init_waitqueue_head(&x->wait);
}
-extern void FASTCALL(wait_for_completion(struct completion *));
-extern int FASTCALL(wait_for_completion_interruptible(struct completion *x));
-extern unsigned long FASTCALL(wait_for_completion_timeout(struct completion *x,
- unsigned long timeout));
-extern unsigned long FASTCALL(wait_for_completion_interruptible_timeout(
- struct completion *x, unsigned long timeout));
-
-extern void FASTCALL(complete(struct completion *));
-extern void FASTCALL(complete_all(struct completion *));
+extern void wait_for_completion(struct completion *);
+extern int wait_for_completion_interruptible(struct completion *x);
+extern unsigned long wait_for_completion_timeout(struct completion *x,
+ unsigned long timeout);
+extern unsigned long wait_for_completion_interruptible_timeout(
+ struct completion *x, unsigned long timeout);
+
+extern void complete(struct completion *);
+extern void complete_all(struct completion *);
#define INIT_COMPLETION(x) ((x).done = 0)
diff --git a/include/linux/connector.h b/include/linux/connector.h
index b62f823e90cf..13fc4541bf23 100644
--- a/include/linux/connector.h
+++ b/include/linux/connector.h
@@ -36,14 +36,15 @@
#define CN_VAL_CIFS 0x1
#define CN_W1_IDX 0x3 /* w1 communication */
#define CN_W1_VAL 0x1
+#define CN_IDX_V86D 0x4
+#define CN_VAL_V86D_UVESAFB 0x1
-
-#define CN_NETLINK_USERS 4
+#define CN_NETLINK_USERS 5
/*
* Maximum connector's message size.
*/
-#define CONNECTOR_MAX_MSG_SIZE 1024
+#define CONNECTOR_MAX_MSG_SIZE 16384
/*
* idx and val are unique identifiers which
diff --git a/include/linux/console.h b/include/linux/console.h
index 56a7bcda49cb..a5f88a6a259d 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -45,7 +45,8 @@ struct consw {
int (*con_font_get)(struct vc_data *, struct console_font *);
int (*con_font_default)(struct vc_data *, struct console_font *, char *);
int (*con_font_copy)(struct vc_data *, int);
- int (*con_resize)(struct vc_data *, unsigned int, unsigned int);
+ int (*con_resize)(struct vc_data *, unsigned int, unsigned int,
+ unsigned int);
int (*con_set_palette)(struct vc_data *, unsigned char *);
int (*con_scrolldelta)(struct vc_data *, int);
int (*con_set_origin)(struct vc_data *);
@@ -121,14 +122,11 @@ extern void console_stop(struct console *);
extern void console_start(struct console *);
extern int is_console_locked(void);
-#ifndef CONFIG_DISABLE_CONSOLE_SUSPEND
+extern int console_suspend_enabled;
+
/* Suspend and resume console messages over PM events */
extern void suspend_console(void);
extern void resume_console(void);
-#else
-static inline void suspend_console(void) {}
-static inline void resume_console(void) {}
-#endif /* CONFIG_DISABLE_CONSOLE_SUSPEND */
int mda_console_init(void);
void prom_con_init(void);
diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h
index dc77fed7b285..d71f7c0f931b 100644
--- a/include/linux/console_struct.h
+++ b/include/linux/console_struct.h
@@ -100,6 +100,7 @@ struct vc_data {
unsigned char vc_G1_charset;
unsigned char vc_saved_G0;
unsigned char vc_saved_G1;
+ unsigned int vc_resize_user; /* resize request from user */
unsigned int vc_bell_pitch; /* Console bell pitch */
unsigned int vc_bell_duration; /* Console bell duration */
struct vc_data **vc_display_fg; /* [!] Ptr to var holding fg console for this display */
diff --git a/include/linux/consolemap.h b/include/linux/consolemap.h
index 06b2768c603f..e2bf7e5db39a 100644
--- a/include/linux/consolemap.h
+++ b/include/linux/consolemap.h
@@ -16,4 +16,5 @@ extern u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode);
extern unsigned short *set_translate(int m, struct vc_data *vc);
extern int conv_uni_to_pc(struct vc_data *conp, long ucs);
extern u32 conv_8bit_to_uni(unsigned char c);
+extern int conv_uni_to_8bit(u32 uni);
void console_map_init(void);
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index 0ad72c4cf312..b79c57569367 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -119,8 +119,9 @@ static inline void cpuhotplug_mutex_unlock(struct mutex *cpu_hp_mutex)
#define lock_cpu_hotplug() do { } while (0)
#define unlock_cpu_hotplug() do { } while (0)
#define hotcpu_notifier(fn, pri) do { (void)(fn); } while (0)
-#define register_hotcpu_notifier(nb) do { (void)(nb); } while (0)
-#define unregister_hotcpu_notifier(nb) do { (void)(nb); } while (0)
+/* These aren't inline functions due to a GCC bug. */
+#define register_hotcpu_notifier(nb) ({ (void)(nb); 0; })
+#define unregister_hotcpu_notifier(nb) ({ (void)(nb); })
/* CPUs don't go offline once they're online w/o CONFIG_HOTPLUG_CPU */
static inline int cpu_is_offline(int cpu) { return 0; }
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
new file mode 100644
index 000000000000..16a51546db44
--- /dev/null
+++ b/include/linux/cpuidle.h
@@ -0,0 +1,180 @@
+/*
+ * cpuidle.h - a generic framework for CPU idle power management
+ *
+ * (C) 2007 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+ * Shaohua Li <shaohua.li@intel.com>
+ * Adam Belay <abelay@novell.com>
+ *
+ * This code is licenced under the GPL.
+ */
+
+#ifndef _LINUX_CPUIDLE_H
+#define _LINUX_CPUIDLE_H
+
+#include <linux/percpu.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/kobject.h>
+#include <linux/completion.h>
+
+#define CPUIDLE_STATE_MAX 8
+#define CPUIDLE_NAME_LEN 16
+
+struct cpuidle_device;
+
+
+/****************************
+ * CPUIDLE DEVICE INTERFACE *
+ ****************************/
+
+struct cpuidle_state {
+ char name[CPUIDLE_NAME_LEN];
+ void *driver_data;
+
+ unsigned int flags;
+ unsigned int exit_latency; /* in US */
+ unsigned int power_usage; /* in mW */
+ unsigned int target_residency; /* in US */
+
+ unsigned int usage;
+ unsigned int time; /* in US */
+
+ int (*enter) (struct cpuidle_device *dev,
+ struct cpuidle_state *state);
+};
+
+/* Idle State Flags */
+#define CPUIDLE_FLAG_TIME_VALID (0x01) /* is residency time measurable? */
+#define CPUIDLE_FLAG_CHECK_BM (0x02) /* BM activity will exit state */
+#define CPUIDLE_FLAG_SHALLOW (0x10) /* low latency, minimal savings */
+#define CPUIDLE_FLAG_BALANCED (0x20) /* medium latency, moderate savings */
+#define CPUIDLE_FLAG_DEEP (0x40) /* high latency, large savings */
+
+#define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000)
+
+/**
+ * cpuidle_get_statedata - retrieves private driver state data
+ * @state: the state
+ */
+static inline void * cpuidle_get_statedata(struct cpuidle_state *state)
+{
+ return state->driver_data;
+}
+
+/**
+ * cpuidle_set_statedata - stores private driver state data
+ * @state: the state
+ * @data: the private data
+ */
+static inline void
+cpuidle_set_statedata(struct cpuidle_state *state, void *data)
+{
+ state->driver_data = data;
+}
+
+struct cpuidle_state_kobj {
+ struct cpuidle_state *state;
+ struct completion kobj_unregister;
+ struct kobject kobj;
+};
+
+struct cpuidle_device {
+ int enabled:1;
+ unsigned int cpu;
+
+ int last_residency;
+ int state_count;
+ struct cpuidle_state states[CPUIDLE_STATE_MAX];
+ struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX];
+ struct cpuidle_state *last_state;
+
+ struct list_head device_list;
+ struct kobject kobj;
+ struct completion kobj_unregister;
+ void *governor_data;
+};
+
+DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices);
+
+/**
+ * cpuidle_get_last_residency - retrieves the last state's residency time
+ * @dev: the target CPU
+ *
+ * NOTE: this value is invalid if CPUIDLE_FLAG_TIME_VALID isn't set
+ */
+static inline int cpuidle_get_last_residency(struct cpuidle_device *dev)
+{
+ return dev->last_residency;
+}
+
+
+/****************************
+ * CPUIDLE DRIVER INTERFACE *
+ ****************************/
+
+struct cpuidle_driver {
+ char name[CPUIDLE_NAME_LEN];
+ struct module *owner;
+};
+
+#ifdef CONFIG_CPU_IDLE
+
+extern int cpuidle_register_driver(struct cpuidle_driver *drv);
+extern void cpuidle_unregister_driver(struct cpuidle_driver *drv);
+extern int cpuidle_register_device(struct cpuidle_device *dev);
+extern void cpuidle_unregister_device(struct cpuidle_device *dev);
+
+extern void cpuidle_pause_and_lock(void);
+extern void cpuidle_resume_and_unlock(void);
+extern int cpuidle_enable_device(struct cpuidle_device *dev);
+extern void cpuidle_disable_device(struct cpuidle_device *dev);
+
+#else
+
+static inline int cpuidle_register_driver(struct cpuidle_driver *drv)
+{return 0;}
+static inline void cpuidle_unregister_driver(struct cpuidle_driver *drv) { }
+static inline int cpuidle_register_device(struct cpuidle_device *dev)
+{return 0;}
+static inline void cpuidle_unregister_device(struct cpuidle_device *dev) { }
+
+static inline void cpuidle_pause_and_lock(void) { }
+static inline void cpuidle_resume_and_unlock(void) { }
+static inline int cpuidle_enable_device(struct cpuidle_device *dev)
+{return 0;}
+static inline void cpuidle_disable_device(struct cpuidle_device *dev) { }
+
+#endif
+
+/******************************
+ * CPUIDLE GOVERNOR INTERFACE *
+ ******************************/
+
+struct cpuidle_governor {
+ char name[CPUIDLE_NAME_LEN];
+ struct list_head governor_list;
+ unsigned int rating;
+
+ int (*enable) (struct cpuidle_device *dev);
+ void (*disable) (struct cpuidle_device *dev);
+
+ int (*select) (struct cpuidle_device *dev);
+ void (*reflect) (struct cpuidle_device *dev);
+
+ struct module *owner;
+};
+
+#ifdef CONFIG_CPU_IDLE
+
+extern int cpuidle_register_governor(struct cpuidle_governor *gov);
+extern void cpuidle_unregister_governor(struct cpuidle_governor *gov);
+
+#else
+
+static inline int cpuidle_register_governor(struct cpuidle_governor *gov)
+{return 0;}
+static inline void cpuidle_unregister_governor(struct cpuidle_governor *gov) { }
+
+#endif
+
+#endif /* _LINUX_CPUIDLE_H */
diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
index 826b15e914e2..ecae585ec3da 100644
--- a/include/linux/cpuset.h
+++ b/include/linux/cpuset.h
@@ -11,6 +11,7 @@
#include <linux/sched.h>
#include <linux/cpumask.h>
#include <linux/nodemask.h>
+#include <linux/cgroup.h>
#ifdef CONFIG_CPUSETS
@@ -19,9 +20,8 @@ extern int number_of_cpusets; /* How many cpusets are defined in system? */
extern int cpuset_init_early(void);
extern int cpuset_init(void);
extern void cpuset_init_smp(void);
-extern void cpuset_fork(struct task_struct *p);
-extern void cpuset_exit(struct task_struct *p);
extern cpumask_t cpuset_cpus_allowed(struct task_struct *p);
+extern cpumask_t cpuset_cpus_allowed_locked(struct task_struct *p);
extern nodemask_t cpuset_mems_allowed(struct task_struct *p);
#define cpuset_current_mems_allowed (current->mems_allowed)
void cpuset_init_current_mems_allowed(void);
@@ -45,7 +45,8 @@ static int inline cpuset_zone_allowed_hardwall(struct zone *z, gfp_t gfp_mask)
__cpuset_zone_allowed_hardwall(z, gfp_mask);
}
-extern int cpuset_excl_nodes_overlap(const struct task_struct *p);
+extern int cpuset_mems_allowed_intersects(const struct task_struct *tsk1,
+ const struct task_struct *tsk2);
#define cpuset_memory_pressure_bump() \
do { \
@@ -75,25 +76,29 @@ static inline int cpuset_do_slab_mem_spread(void)
extern void cpuset_track_online_nodes(void);
+extern int current_cpuset_is_being_rebound(void);
+
#else /* !CONFIG_CPUSETS */
static inline int cpuset_init_early(void) { return 0; }
static inline int cpuset_init(void) { return 0; }
static inline void cpuset_init_smp(void) {}
-static inline void cpuset_fork(struct task_struct *p) {}
-static inline void cpuset_exit(struct task_struct *p) {}
static inline cpumask_t cpuset_cpus_allowed(struct task_struct *p)
{
return cpu_possible_map;
}
+static inline cpumask_t cpuset_cpus_allowed_locked(struct task_struct *p)
+{
+ return cpu_possible_map;
+}
static inline nodemask_t cpuset_mems_allowed(struct task_struct *p)
{
return node_possible_map;
}
-#define cpuset_current_mems_allowed (node_online_map)
+#define cpuset_current_mems_allowed (node_states[N_HIGH_MEMORY])
static inline void cpuset_init_current_mems_allowed(void) {}
static inline void cpuset_update_task_memory_state(void) {}
#define cpuset_nodes_subset_current_mems_allowed(nodes) (1)
@@ -113,7 +118,8 @@ static inline int cpuset_zone_allowed_hardwall(struct zone *z, gfp_t gfp_mask)
return 1;
}
-static inline int cpuset_excl_nodes_overlap(const struct task_struct *p)
+static inline int cpuset_mems_allowed_intersects(const struct task_struct *tsk1,
+ const struct task_struct *tsk2)
{
return 1;
}
@@ -146,6 +152,11 @@ static inline int cpuset_do_slab_mem_spread(void)
static inline void cpuset_track_online_nodes(void) {}
+static inline int current_cpuset_is_being_rebound(void)
+{
+ return 0;
+}
+
#endif /* !CONFIG_CPUSETS */
#endif /* _LINUX_CPUSET_H */
diff --git a/include/linux/cramfs_fs.h b/include/linux/cramfs_fs.h
index 1dba681e428d..3be4e5a27d82 100644
--- a/include/linux/cramfs_fs.h
+++ b/include/linux/cramfs_fs.h
@@ -4,6 +4,7 @@
#include <linux/types.h>
#define CRAMFS_MAGIC 0x28cd3d45 /* some random number */
+#define CRAMFS_MAGIC_WEND 0x453dcd28 /* magic number with the wrong endianess */
#define CRAMFS_SIGNATURE "Compressed ROMFS"
/*
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index fc32694287e2..f3110ebe894a 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -6,7 +6,7 @@
* Copyright (c) 2005 Herbert Xu <herbert@gondor.apana.org.au>
*
* Portions derived from Cryptoapi, by Alexander Kjeldaas <astor@fast.no>
- * and Nettle, by Niels Möller.
+ * and Nettle, by Niels Möller.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
diff --git a/include/linux/cyclades.h b/include/linux/cyclades.h
index 72aa00cc4b2d..8f3dcd30828f 100644
--- a/include/linux/cyclades.h
+++ b/include/linux/cyclades.h
@@ -512,11 +512,11 @@ struct cyclades_card {
void __iomem *base_addr;
void __iomem *ctl_addr;
int irq;
- int num_chips; /* 0 if card absent, -1 if Z/PCI, else Y */
- int first_line; /* minor number of first channel on card */
- int nports; /* Number of ports in the card */
- int bus_index; /* address shift - 0 for ISA, 1 for PCI */
- int intr_enabled; /* FW Interrupt flag - 0 disabled, 1 enabled */
+ unsigned int num_chips; /* 0 if card absent, -1 if Z/PCI, else Y */
+ unsigned int first_line; /* minor number of first channel on card */
+ unsigned int nports; /* Number of ports in the card */
+ int bus_index; /* address shift - 0 for ISA, 1 for PCI */
+ int intr_enabled; /* FW Interrupt flag - 0 disabled, 1 enabled */
spinlock_t card_lock;
struct cyclades_port *ports;
};
@@ -566,10 +566,9 @@ struct cyclades_port {
int rtsdtr_inv;
int chip_rev;
int custom_divisor;
- int x_char; /* to be pushed out ASAP */
+ u8 x_char; /* to be pushed out ASAP */
int close_delay;
unsigned short closing_wait;
- unsigned long event;
int count; /* # of fd on device */
int breakon;
int breakoff;
@@ -584,7 +583,6 @@ struct cyclades_port {
struct cyclades_monitor mon;
struct cyclades_idle_stats idle_stats;
struct cyclades_icount icount;
- struct work_struct tqueue;
wait_queue_head_t open_wait;
wait_queue_head_t close_wait;
struct completion shutdown_wait;
@@ -592,19 +590,6 @@ struct cyclades_port {
int throttle;
};
-/*
- * Events are used to schedule things to happen at timer-interrupt
- * time, instead of at cy interrupt time.
- */
-#define Cy_EVENT_READ_PROCESS 0
-#define Cy_EVENT_WRITE_WAKEUP 1
-#define Cy_EVENT_HANGUP 2
-#define Cy_EVENT_BREAK 3
-#define Cy_EVENT_OPEN_WAKEUP 4
-#define Cy_EVENT_SHUTDOWN_WAKEUP 5
-#define Cy_EVENT_DELTA_WAKEUP 6
-#define Cy_EVENT_Z_RX_FULL 7
-
#define CLOSING_WAIT_DELAY 30*HZ
#define CY_CLOSING_WAIT_NONE 65535
#define CY_CLOSING_WAIT_INF 0
diff --git a/include/linux/dca.h b/include/linux/dca.h
new file mode 100644
index 000000000000..83eaecc6f8ab
--- /dev/null
+++ b/include/linux/dca.h
@@ -0,0 +1,47 @@
+#ifndef DCA_H
+#define DCA_H
+/* DCA Provider API */
+
+/* DCA Notifier Interface */
+void dca_register_notify(struct notifier_block *nb);
+void dca_unregister_notify(struct notifier_block *nb);
+
+#define DCA_PROVIDER_ADD 0x0001
+#define DCA_PROVIDER_REMOVE 0x0002
+
+struct dca_provider {
+ struct dca_ops *ops;
+ struct class_device *cd;
+ int id;
+};
+
+struct dca_ops {
+ int (*add_requester) (struct dca_provider *, struct device *);
+ int (*remove_requester) (struct dca_provider *, struct device *);
+ u8 (*get_tag) (struct dca_provider *, int cpu);
+};
+
+struct dca_provider *alloc_dca_provider(struct dca_ops *ops, int priv_size);
+void free_dca_provider(struct dca_provider *dca);
+int register_dca_provider(struct dca_provider *dca, struct device *dev);
+void unregister_dca_provider(struct dca_provider *dca);
+
+static inline void *dca_priv(struct dca_provider *dca)
+{
+ return (void *)dca + sizeof(struct dca_provider);
+}
+
+/* Requester API */
+int dca_add_requester(struct device *dev);
+int dca_remove_requester(struct device *dev);
+u8 dca_get_tag(int cpu);
+
+/* internal stuff */
+int __init dca_sysfs_init(void);
+void __exit dca_sysfs_exit(void);
+int dca_sysfs_add_provider(struct dca_provider *dca, struct device *dev);
+void dca_sysfs_remove_provider(struct dca_provider *dca);
+int dca_sysfs_add_req(struct dca_provider *dca, struct device *dev, int slot);
+void dca_sysfs_remove_req(struct dca_provider *dca, int slot);
+
+#endif /* DCA_H */
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index aab53df4fafa..c2c153f97e8f 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -178,6 +178,7 @@ d_iput: no no no yes
#define DCACHE_INOTIFY_PARENT_WATCHED 0x0020 /* Parent inode is watched */
extern spinlock_t dcache_lock;
+extern seqlock_t rename_lock;
/**
* d_drop - drop a dentry
diff --git a/include/linux/dccp.h b/include/linux/dccp.h
index f3fc4392e93d..333c3ea82a5d 100644
--- a/include/linux/dccp.h
+++ b/include/linux/dccp.h
@@ -144,6 +144,8 @@ enum dccp_reset_codes {
DCCP_RESET_CODE_TOO_BUSY,
DCCP_RESET_CODE_BAD_INIT_COOKIE,
DCCP_RESET_CODE_AGGRESSION_PENALTY,
+
+ DCCP_MAX_RESET_CODES /* Leave at the end! */
};
/* DCCP options */
@@ -270,10 +272,9 @@ static inline struct dccp_hdr *dccp_zeroed_hdr(struct sk_buff *skb, int headlen)
return memset(skb_transport_header(skb), 0, headlen);
}
-static inline struct dccp_hdr_ext *dccp_hdrx(const struct sk_buff *skb)
+static inline struct dccp_hdr_ext *dccp_hdrx(const struct dccp_hdr *dh)
{
- return (struct dccp_hdr_ext *)(skb_transport_header(skb) +
- sizeof(struct dccp_hdr));
+ return (struct dccp_hdr_ext *)((unsigned char *)dh + sizeof(*dh));
}
static inline unsigned int __dccp_basic_hdr_len(const struct dccp_hdr *dh)
@@ -287,13 +288,12 @@ static inline unsigned int dccp_basic_hdr_len(const struct sk_buff *skb)
return __dccp_basic_hdr_len(dh);
}
-static inline __u64 dccp_hdr_seq(const struct sk_buff *skb)
+static inline __u64 dccp_hdr_seq(const struct dccp_hdr *dh)
{
- const struct dccp_hdr *dh = dccp_hdr(skb);
__u64 seq_nr = ntohs(dh->dccph_seq);
if (dh->dccph_x != 0)
- seq_nr = (seq_nr << 32) + ntohl(dccp_hdrx(skb)->dccph_seq_low);
+ seq_nr = (seq_nr << 32) + ntohl(dccp_hdrx(dh)->dccph_seq_low);
else
seq_nr += (u32)dh->dccph_seq2 << 16;
diff --git a/include/linux/delayacct.h b/include/linux/delayacct.h
index 55d1ca5e60f5..ab94bc083558 100644
--- a/include/linux/delayacct.h
+++ b/include/linux/delayacct.h
@@ -26,6 +26,7 @@
* Used to set current->delays->flags
*/
#define DELAYACCT_PF_SWAPIN 0x00000001 /* I am doing a swapin */
+#define DELAYACCT_PF_BLKIO 0x00000002 /* I am waiting on IO */
#ifdef CONFIG_TASK_DELAY_ACCT
@@ -39,6 +40,14 @@ extern void __delayacct_blkio_end(void);
extern int __delayacct_add_tsk(struct taskstats *, struct task_struct *);
extern __u64 __delayacct_blkio_ticks(struct task_struct *);
+static inline int delayacct_is_task_waiting_on_io(struct task_struct *p)
+{
+ if (p->delays)
+ return (p->delays->flags & DELAYACCT_PF_BLKIO);
+ else
+ return 0;
+}
+
static inline void delayacct_set_flag(int flag)
{
if (current->delays)
@@ -71,6 +80,7 @@ static inline void delayacct_tsk_free(struct task_struct *tsk)
static inline void delayacct_blkio_start(void)
{
+ delayacct_set_flag(DELAYACCT_PF_BLKIO);
if (current->delays)
__delayacct_blkio_start();
}
@@ -79,6 +89,7 @@ static inline void delayacct_blkio_end(void)
{
if (current->delays)
__delayacct_blkio_end();
+ delayacct_clear_flag(DELAYACCT_PF_BLKIO);
}
static inline int delayacct_add_tsk(struct taskstats *d,
@@ -116,6 +127,8 @@ static inline int delayacct_add_tsk(struct taskstats *d,
{ return 0; }
static inline __u64 delayacct_blkio_ticks(struct task_struct *tsk)
{ return 0; }
+static inline int delayacct_is_task_waiting_on_io(struct task_struct *p)
+{ return 0; }
#endif /* CONFIG_TASK_DELAY_ACCT */
#endif
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
index 499f5373e213..b8b7c51389fe 100644
--- a/include/linux/device-mapper.h
+++ b/include/linux/device-mapper.h
@@ -116,6 +116,7 @@ struct io_restrictions {
unsigned short hardsect_size;
unsigned int max_segment_size;
unsigned long seg_boundary_mask;
+ unsigned long bounce_pfn;
unsigned char no_cluster; /* inverted so that 0 is default */
};
@@ -183,11 +184,14 @@ int dm_resume(struct mapped_device *md);
*/
uint32_t dm_get_event_nr(struct mapped_device *md);
int dm_wait_event(struct mapped_device *md, int event_nr);
+uint32_t dm_next_uevent_seq(struct mapped_device *md);
+void dm_uevent_add(struct mapped_device *md, struct list_head *elist);
/*
* Info functions.
*/
const char *dm_device_name(struct mapped_device *md);
+int dm_copy_name_and_uuid(struct mapped_device *md, char *name, char *uuid);
struct gendisk *dm_disk(struct mapped_device *md);
int dm_suspended(struct mapped_device *md);
int dm_noflush_suspending(struct dm_target *ti);
diff --git a/include/linux/dm-ioctl.h b/include/linux/dm-ioctl.h
index b93486107821..523281c5b7f5 100644
--- a/include/linux/dm-ioctl.h
+++ b/include/linux/dm-ioctl.h
@@ -131,6 +131,7 @@ struct dm_ioctl {
char name[DM_NAME_LEN]; /* device name */
char uuid[DM_UUID_LEN]; /* unique identifier for
* the block device */
+ char data[7]; /* padding or data */
};
/*
@@ -285,9 +286,9 @@ typedef char ioctl_struct[308];
#define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
#define DM_VERSION_MAJOR 4
-#define DM_VERSION_MINOR 11
+#define DM_VERSION_MINOR 12
#define DM_VERSION_PATCHLEVEL 0
-#define DM_VERSION_EXTRA "-ioctl (2006-10-12)"
+#define DM_VERSION_EXTRA "-ioctl (2007-10-02)"
/* Status bits */
#define DM_READONLY_FLAG (1 << 0) /* In/Out */
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 2dc21cbeb304..101a2d4636be 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -13,16 +13,28 @@ enum dma_data_direction {
DMA_NONE = 3,
};
-#define DMA_64BIT_MASK 0xffffffffffffffffULL
-#define DMA_48BIT_MASK 0x0000ffffffffffffULL
-#define DMA_40BIT_MASK 0x000000ffffffffffULL
-#define DMA_39BIT_MASK 0x0000007fffffffffULL
-#define DMA_32BIT_MASK 0x00000000ffffffffULL
-#define DMA_31BIT_MASK 0x000000007fffffffULL
-#define DMA_30BIT_MASK 0x000000003fffffffULL
-#define DMA_29BIT_MASK 0x000000001fffffffULL
-#define DMA_28BIT_MASK 0x000000000fffffffULL
-#define DMA_24BIT_MASK 0x0000000000ffffffULL
+#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1))
+
+/*
+ * NOTE: do not use the below macros in new code and do not add new definitions
+ * here.
+ *
+ * Instead, just open-code DMA_BIT_MASK(n) within your driver
+ */
+#define DMA_64BIT_MASK DMA_BIT_MASK(64)
+#define DMA_48BIT_MASK DMA_BIT_MASK(48)
+#define DMA_47BIT_MASK DMA_BIT_MASK(47)
+#define DMA_40BIT_MASK DMA_BIT_MASK(40)
+#define DMA_39BIT_MASK DMA_BIT_MASK(39)
+#define DMA_35BIT_MASK DMA_BIT_MASK(35)
+#define DMA_32BIT_MASK DMA_BIT_MASK(32)
+#define DMA_31BIT_MASK DMA_BIT_MASK(31)
+#define DMA_30BIT_MASK DMA_BIT_MASK(30)
+#define DMA_29BIT_MASK DMA_BIT_MASK(29)
+#define DMA_28BIT_MASK DMA_BIT_MASK(28)
+#define DMA_24BIT_MASK DMA_BIT_MASK(24)
+
+#define DMA_MASK_NONE 0x0ULL
static inline int valid_dma_direction(int dma_direction)
{
@@ -31,6 +43,11 @@ static inline int valid_dma_direction(int dma_direction)
(dma_direction == DMA_FROM_DEVICE));
}
+static inline int is_device_dma_capable(struct device *dev)
+{
+ return dev->dma_mask != NULL && *dev->dma_mask != DMA_MASK_NONE;
+}
+
#ifdef CONFIG_HAS_DMA
#include <asm/dma-mapping.h>
#else
diff --git a/include/linux/dmar.h b/include/linux/dmar.h
new file mode 100644
index 000000000000..ffb6439cb5e6
--- /dev/null
+++ b/include/linux/dmar.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Copyright (C) Ashok Raj <ashok.raj@intel.com>
+ * Copyright (C) Shaohua Li <shaohua.li@intel.com>
+ */
+
+#ifndef __DMAR_H__
+#define __DMAR_H__
+
+#include <linux/acpi.h>
+#include <linux/types.h>
+#include <linux/msi.h>
+
+#ifdef CONFIG_DMAR
+struct intel_iommu;
+
+extern char *dmar_get_fault_reason(u8 fault_reason);
+
+/* Can't use the common MSI interrupt functions
+ * since DMAR is not a pci device
+ */
+extern void dmar_msi_unmask(unsigned int irq);
+extern void dmar_msi_mask(unsigned int irq);
+extern void dmar_msi_read(int irq, struct msi_msg *msg);
+extern void dmar_msi_write(int irq, struct msi_msg *msg);
+extern int dmar_set_interrupt(struct intel_iommu *iommu);
+extern int arch_setup_dmar_msi(unsigned int irq);
+
+/* Intel IOMMU detection and initialization functions */
+extern void detect_intel_iommu(void);
+extern int intel_iommu_init(void);
+
+extern int dmar_table_init(void);
+extern int early_dmar_detect(void);
+
+extern struct list_head dmar_drhd_units;
+extern struct list_head dmar_rmrr_units;
+
+struct dmar_drhd_unit {
+ struct list_head list; /* list of drhd units */
+ u64 reg_base_addr; /* register base address*/
+ struct pci_dev **devices; /* target device array */
+ int devices_cnt; /* target device count */
+ u8 ignored:1; /* ignore drhd */
+ u8 include_all:1;
+ struct intel_iommu *iommu;
+};
+
+struct dmar_rmrr_unit {
+ struct list_head list; /* list of rmrr units */
+ u64 base_address; /* reserved base address*/
+ u64 end_address; /* reserved end address */
+ struct pci_dev **devices; /* target devices */
+ int devices_cnt; /* target device count */
+};
+
+#define for_each_drhd_unit(drhd) \
+ list_for_each_entry(drhd, &dmar_drhd_units, list)
+#define for_each_rmrr_units(rmrr) \
+ list_for_each_entry(rmrr, &dmar_rmrr_units, list)
+#else
+static inline void detect_intel_iommu(void)
+{
+ return;
+}
+static inline int intel_iommu_init(void)
+{
+ return -ENODEV;
+}
+
+#endif /* !CONFIG_DMAR */
+#endif /* __DMAR_H__ */
diff --git a/include/linux/edd.h b/include/linux/edd.h
index 7b647822d6dc..5d747c5cd0fe 100644
--- a/include/linux/edd.h
+++ b/include/linux/edd.h
@@ -67,113 +67,113 @@
#define EDD_INFO_USE_INT13_FN50 (1 << 7)
struct edd_device_params {
- u16 length;
- u16 info_flags;
- u32 num_default_cylinders;
- u32 num_default_heads;
- u32 sectors_per_track;
- u64 number_of_sectors;
- u16 bytes_per_sector;
- u32 dpte_ptr; /* 0xFFFFFFFF for our purposes */
- u16 key; /* = 0xBEDD */
- u8 device_path_info_length; /* = 44 */
- u8 reserved2;
- u16 reserved3;
- u8 host_bus_type[4];
- u8 interface_type[8];
+ __u16 length;
+ __u16 info_flags;
+ __u32 num_default_cylinders;
+ __u32 num_default_heads;
+ __u32 sectors_per_track;
+ __u64 number_of_sectors;
+ __u16 bytes_per_sector;
+ __u32 dpte_ptr; /* 0xFFFFFFFF for our purposes */
+ __u16 key; /* = 0xBEDD */
+ __u8 device_path_info_length; /* = 44 */
+ __u8 reserved2;
+ __u16 reserved3;
+ __u8 host_bus_type[4];
+ __u8 interface_type[8];
union {
struct {
- u16 base_address;
- u16 reserved1;
- u32 reserved2;
+ __u16 base_address;
+ __u16 reserved1;
+ __u32 reserved2;
} __attribute__ ((packed)) isa;
struct {
- u8 bus;
- u8 slot;
- u8 function;
- u8 channel;
- u32 reserved;
+ __u8 bus;
+ __u8 slot;
+ __u8 function;
+ __u8 channel;
+ __u32 reserved;
} __attribute__ ((packed)) pci;
/* pcix is same as pci */
struct {
- u64 reserved;
+ __u64 reserved;
} __attribute__ ((packed)) ibnd;
struct {
- u64 reserved;
+ __u64 reserved;
} __attribute__ ((packed)) xprs;
struct {
- u64 reserved;
+ __u64 reserved;
} __attribute__ ((packed)) htpt;
struct {
- u64 reserved;
+ __u64 reserved;
} __attribute__ ((packed)) unknown;
} interface_path;
union {
struct {
- u8 device;
- u8 reserved1;
- u16 reserved2;
- u32 reserved3;
- u64 reserved4;
+ __u8 device;
+ __u8 reserved1;
+ __u16 reserved2;
+ __u32 reserved3;
+ __u64 reserved4;
} __attribute__ ((packed)) ata;
struct {
- u8 device;
- u8 lun;
- u8 reserved1;
- u8 reserved2;
- u32 reserved3;
- u64 reserved4;
+ __u8 device;
+ __u8 lun;
+ __u8 reserved1;
+ __u8 reserved2;
+ __u32 reserved3;
+ __u64 reserved4;
} __attribute__ ((packed)) atapi;
struct {
- u16 id;
- u64 lun;
- u16 reserved1;
- u32 reserved2;
+ __u16 id;
+ __u64 lun;
+ __u16 reserved1;
+ __u32 reserved2;
} __attribute__ ((packed)) scsi;
struct {
- u64 serial_number;
- u64 reserved;
+ __u64 serial_number;
+ __u64 reserved;
} __attribute__ ((packed)) usb;
struct {
- u64 eui;
- u64 reserved;
+ __u64 eui;
+ __u64 reserved;
} __attribute__ ((packed)) i1394;
struct {
- u64 wwid;
- u64 lun;
+ __u64 wwid;
+ __u64 lun;
} __attribute__ ((packed)) fibre;
struct {
- u64 identity_tag;
- u64 reserved;
+ __u64 identity_tag;
+ __u64 reserved;
} __attribute__ ((packed)) i2o;
struct {
- u32 array_number;
- u32 reserved1;
- u64 reserved2;
+ __u32 array_number;
+ __u32 reserved1;
+ __u64 reserved2;
} __attribute__ ((packed)) raid;
struct {
- u8 device;
- u8 reserved1;
- u16 reserved2;
- u32 reserved3;
- u64 reserved4;
+ __u8 device;
+ __u8 reserved1;
+ __u16 reserved2;
+ __u32 reserved3;
+ __u64 reserved4;
} __attribute__ ((packed)) sata;
struct {
- u64 reserved1;
- u64 reserved2;
+ __u64 reserved1;
+ __u64 reserved2;
} __attribute__ ((packed)) unknown;
} device_path;
- u8 reserved4;
- u8 checksum;
+ __u8 reserved4;
+ __u8 checksum;
} __attribute__ ((packed));
struct edd_info {
- u8 device;
- u8 version;
- u16 interface_support;
- u16 legacy_max_cylinder;
- u8 legacy_max_head;
- u8 legacy_sectors_per_track;
+ __u8 device;
+ __u8 version;
+ __u16 interface_support;
+ __u16 legacy_max_cylinder;
+ __u8 legacy_max_head;
+ __u8 legacy_sectors_per_track;
struct edd_device_params params;
} __attribute__ ((packed));
@@ -184,8 +184,9 @@ struct edd {
unsigned char edd_info_nr;
};
+#ifdef __KERNEL__
extern struct edd edd;
-
+#endif /* __KERNEL__ */
#endif /*!__ASSEMBLY__ */
#endif /* _LINUX_EDD_H */
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 0b9579a4cd42..14813b595802 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -298,7 +298,7 @@ extern int efi_mem_attribute_range (unsigned long phys_addr, unsigned long size,
u64 attr);
extern int __init efi_uart_console_only (void);
extern void efi_initialize_iomem_resources(struct resource *code_resource,
- struct resource *data_resource);
+ struct resource *data_resource, struct resource *bss_resource);
extern unsigned long efi_get_time(void);
extern int efi_set_rtc_mmss(unsigned long nowtime);
extern int is_available_memory(efi_memory_desc_t * md);
diff --git a/include/linux/efs_fs.h b/include/linux/efs_fs.h
index 16cb25cbf7c5..dd57fe523e97 100644
--- a/include/linux/efs_fs.h
+++ b/include/linux/efs_fs.h
@@ -35,6 +35,7 @@ static inline struct efs_sb_info *SUPER_INFO(struct super_block *sb)
}
struct statfs;
+struct fid;
extern const struct inode_operations efs_dir_inode_operations;
extern const struct file_operations efs_dir_operations;
@@ -45,7 +46,10 @@ extern efs_block_t efs_map_block(struct inode *, efs_block_t);
extern int efs_get_block(struct inode *, sector_t, struct buffer_head *, int);
extern struct dentry *efs_lookup(struct inode *, struct dentry *, struct nameidata *);
-extern struct dentry *efs_get_dentry(struct super_block *sb, void *vobjp);
+extern struct dentry *efs_fh_to_dentry(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type);
+extern struct dentry *efs_fh_to_parent(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type);
extern struct dentry *efs_get_parent(struct dentry *);
extern int efs_bmap(struct inode *, int);
diff --git a/include/linux/elf.h b/include/linux/elf.h
index d2da84acf45d..576e83bd6d88 100644
--- a/include/linux/elf.h
+++ b/include/linux/elf.h
@@ -2,7 +2,6 @@
#define _LINUX_ELF_H
#include <linux/types.h>
-#include <linux/auxvec.h>
#include <linux/elf-em.h>
#include <asm/elf.h>
@@ -355,6 +354,7 @@ typedef struct elf64_shdr {
#define NT_TASKSTRUCT 4
#define NT_AUXV 6
#define NT_PRXFPREG 0x46e62b7f /* copied from gdb5.1/include/elf/common.h */
+#define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */
/* Note header in a PT_NOTE section */
diff --git a/include/linux/elfcore-compat.h b/include/linux/elfcore-compat.h
new file mode 100644
index 000000000000..532d13adabc4
--- /dev/null
+++ b/include/linux/elfcore-compat.h
@@ -0,0 +1,55 @@
+#ifndef _LINUX_ELFCORE_COMPAT_H
+#define _LINUX_ELFCORE_COMPAT_H
+
+#include <linux/elf.h>
+#include <linux/elfcore.h>
+#include <linux/compat.h>
+
+/*
+ * Make sure these layouts match the linux/elfcore.h native definitions.
+ */
+
+struct compat_elf_siginfo
+{
+ compat_int_t si_signo;
+ compat_int_t si_code;
+ compat_int_t si_errno;
+};
+
+struct compat_elf_prstatus
+{
+ struct compat_elf_siginfo pr_info;
+ short pr_cursig;
+ compat_ulong_t pr_sigpend;
+ compat_ulong_t pr_sighold;
+ compat_pid_t pr_pid;
+ compat_pid_t pr_ppid;
+ compat_pid_t pr_pgrp;
+ compat_pid_t pr_sid;
+ struct compat_timeval pr_utime;
+ struct compat_timeval pr_stime;
+ struct compat_timeval pr_cutime;
+ struct compat_timeval pr_cstime;
+ compat_elf_gregset_t pr_reg;
+#ifdef CONFIG_BINFMT_ELF_FDPIC
+ compat_ulong_t pr_exec_fdpic_loadmap;
+ compat_ulong_t pr_interp_fdpic_loadmap;
+#endif
+ compat_int_t pr_fpvalid;
+};
+
+struct compat_elf_prpsinfo
+{
+ char pr_state;
+ char pr_sname;
+ char pr_zomb;
+ char pr_nice;
+ compat_ulong_t pr_flag;
+ compat_uid_t pr_uid;
+ compat_gid_t pr_gid;
+ compat_pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid;
+ char pr_fname[16];
+ char pr_psargs[ELF_PRARGSZ];
+};
+
+#endif /* _LINUX_ELFCORE_COMPAT_H */
diff --git a/include/linux/eventpoll.h b/include/linux/eventpoll.h
index d2a96cbf4f0e..cf79853967ff 100644
--- a/include/linux/eventpoll.h
+++ b/include/linux/eventpoll.h
@@ -32,18 +32,13 @@
* On x86-64 make the 64bit structure have the same alignment as the
* 32bit structure. This makes 32bit emulation easier.
*
- * UML/x86_64 needs the same packing as x86_64 - UML + UML_X86 +
- * 64_BIT adds up to UML/x86_64.
+ * UML/x86_64 needs the same packing as x86_64
*/
#ifdef __x86_64__
#define EPOLL_PACKED __attribute__((packed))
#else
-#if defined(CONFIG_UML) && defined(CONFIG_UML_X86) && defined(CONFIG_64BIT)
-#define EPOLL_PACKED __attribute__((packed))
-#else
#define EPOLL_PACKED
#endif
-#endif
struct epoll_event {
__u32 events;
diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h
index 8872fe8392d6..51d214138814 100644
--- a/include/linux/exportfs.h
+++ b/include/linux/exportfs.h
@@ -4,9 +4,48 @@
#include <linux/types.h>
struct dentry;
+struct inode;
struct super_block;
struct vfsmount;
+/*
+ * The fileid_type identifies how the file within the filesystem is encoded.
+ * In theory this is freely set and parsed by the filesystem, but we try to
+ * stick to conventions so we can share some generic code and don't confuse
+ * sniffers like ethereal/wireshark.
+ *
+ * The filesystem must not use the value '0' or '0xff'.
+ */
+enum fid_type {
+ /*
+ * The root, or export point, of the filesystem.
+ * (Never actually passed down to the filesystem.
+ */
+ FILEID_ROOT = 0,
+
+ /*
+ * 32bit inode number, 32 bit generation number.
+ */
+ FILEID_INO32_GEN = 1,
+
+ /*
+ * 32bit inode number, 32 bit generation number,
+ * 32 bit parent directory inode number.
+ */
+ FILEID_INO32_GEN_PARENT = 2,
+};
+
+struct fid {
+ union {
+ struct {
+ u32 ino;
+ u32 gen;
+ u32 parent_ino;
+ u32 parent_gen;
+ } i32;
+ __u32 raw[6];
+ };
+};
/**
* struct export_operations - for nfsd to communicate with file systems
@@ -15,43 +54,9 @@ struct vfsmount;
* @get_name: find the name for a given inode in a given directory
* @get_parent: find the parent of a given directory
* @get_dentry: find a dentry for the inode given a file handle sub-fragment
- * @find_exported_dentry:
- * set by the exporting module to a standard helper function.
- *
- * Description:
- * The export_operations structure provides a means for nfsd to communicate
- * with a particular exported file system - particularly enabling nfsd and
- * the filesystem to co-operate when dealing with file handles.
- *
- * export_operations contains two basic operation for dealing with file
- * handles, decode_fh() and encode_fh(), and allows for some other
- * operations to be defined which standard helper routines use to get
- * specific information from the filesystem.
- *
- * nfsd encodes information use to determine which filesystem a filehandle
- * applies to in the initial part of the file handle. The remainder, termed
- * a file handle fragment, is controlled completely by the filesystem. The
- * standard helper routines assume that this fragment will contain one or
- * two sub-fragments, one which identifies the file, and one which may be
- * used to identify the (a) directory containing the file.
*
- * In some situations, nfsd needs to get a dentry which is connected into a
- * specific part of the file tree. To allow for this, it passes the
- * function acceptable() together with a @context which can be used to see
- * if the dentry is acceptable. As there can be multiple dentrys for a
- * given file, the filesystem should check each one for acceptability before
- * looking for the next. As soon as an acceptable one is found, it should
- * be returned.
- *
- * decode_fh:
- * @decode_fh is given a &struct super_block (@sb), a file handle fragment
- * (@fh, @fh_len) and an acceptability testing function (@acceptable,
- * @context). It should return a &struct dentry which refers to the same
- * file that the file handle fragment refers to, and which passes the
- * acceptability test. If it cannot, it should return a %NULL pointer if
- * the file was found but no acceptable &dentries were available, or a
- * %ERR_PTR error code indicating why it couldn't be found (e.g. %ENOENT or
- * %ENOMEM).
+ * See Documentation/filesystems/Exporting for details on how to use
+ * this interface correctly.
*
* encode_fh:
* @encode_fh should store in the file handle fragment @fh (using at most
@@ -63,6 +68,21 @@ struct vfsmount;
* the filehandle fragment. encode_fh() should return the number of bytes
* stored or a negative error code such as %-ENOSPC
*
+ * fh_to_dentry:
+ * @fh_to_dentry is given a &struct super_block (@sb) and a file handle
+ * fragment (@fh, @fh_len). It should return a &struct dentry which refers
+ * to the same file that the file handle fragment refers to. If it cannot,
+ * it should return a %NULL pointer if the file was found but no acceptable
+ * &dentries were available, or an %ERR_PTR error code indicating why it
+ * couldn't be found (e.g. %ENOENT or %ENOMEM). Any suitable dentry can be
+ * returned including, if necessary, a new dentry created with d_alloc_root.
+ * The caller can then find any other extant dentries by following the
+ * d_alias links.
+ *
+ * fh_to_parent:
+ * Same as @fh_to_dentry, except that it returns a pointer to the parent
+ * dentry if it was encoded into the filehandle fragment by @encode_fh.
+ *
* get_name:
* @get_name should find a name for the given @child in the given @parent
* directory. The name should be stored in the @name (with the
@@ -75,52 +95,37 @@ struct vfsmount;
* is also a directory. In the event that it cannot be found, or storage
* space cannot be allocated, a %ERR_PTR should be returned.
*
- * get_dentry:
- * Given a &super_block (@sb) and a pointer to a file-system specific inode
- * identifier, possibly an inode number, (@inump) get_dentry() should find
- * the identified inode and return a dentry for that inode. Any suitable
- * dentry can be returned including, if necessary, a new dentry created with
- * d_alloc_root. The caller can then find any other extant dentrys by
- * following the d_alias links. If a new dentry was created using
- * d_alloc_root, DCACHE_NFSD_DISCONNECTED should be set, and the dentry
- * should be d_rehash()ed.
- *
- * If the inode cannot be found, either a %NULL pointer or an %ERR_PTR code
- * can be returned. The @inump will be whatever was passed to
- * nfsd_find_fh_dentry() in either the @obj or @parent parameters.
- *
* Locking rules:
* get_parent is called with child->d_inode->i_mutex down
* get_name is not (which is possibly inconsistent)
*/
struct export_operations {
- struct dentry *(*decode_fh)(struct super_block *sb, __u32 *fh,
- int fh_len, int fh_type,
- int (*acceptable)(void *context, struct dentry *de),
- void *context);
int (*encode_fh)(struct dentry *de, __u32 *fh, int *max_len,
int connectable);
+ struct dentry * (*fh_to_dentry)(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type);
+ struct dentry * (*fh_to_parent)(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type);
int (*get_name)(struct dentry *parent, char *name,
struct dentry *child);
struct dentry * (*get_parent)(struct dentry *child);
- struct dentry * (*get_dentry)(struct super_block *sb, void *inump);
-
- /* This is set by the exporting module to a standard helper */
- struct dentry * (*find_exported_dentry)(
- struct super_block *sb, void *obj, void *parent,
- int (*acceptable)(void *context, struct dentry *de),
- void *context);
};
-extern struct dentry *find_exported_dentry(struct super_block *sb, void *obj,
- void *parent, int (*acceptable)(void *context, struct dentry *de),
- void *context);
-
-extern int exportfs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
- int connectable);
-extern struct dentry *exportfs_decode_fh(struct vfsmount *mnt, __u32 *fh,
+extern int exportfs_encode_fh(struct dentry *dentry, struct fid *fid,
+ int *max_len, int connectable);
+extern struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid,
int fh_len, int fileid_type, int (*acceptable)(void *, struct dentry *),
void *context);
+/*
+ * Generic helpers for filesystems.
+ */
+extern struct dentry *generic_fh_to_dentry(struct super_block *sb,
+ struct fid *fid, int fh_len, int fh_type,
+ struct inode *(*get_inode) (struct super_block *sb, u64 ino, u32 gen));
+extern struct dentry *generic_fh_to_parent(struct super_block *sb,
+ struct fid *fid, int fh_len, int fh_type,
+ struct inode *(*get_inode) (struct super_block *sb, u64 ino, u32 gen));
+
#endif /* LINUX_EXPORTFS_H */
diff --git a/include/linux/ext2_fs.h b/include/linux/ext2_fs.h
index 153d755376a4..0f6c86c634fd 100644
--- a/include/linux/ext2_fs.h
+++ b/include/linux/ext2_fs.h
@@ -29,11 +29,12 @@
#undef EXT2FS_DEBUG
/*
- * Define EXT2_PREALLOCATE to preallocate data blocks for expanding files
+ * Define EXT2_RESERVATION to reserve data blocks for expanding files
*/
-#define EXT2_PREALLOCATE
-#define EXT2_DEFAULT_PREALLOC_BLOCKS 8
-
+#define EXT2_DEFAULT_RESERVE_BLOCKS 8
+/*max window size: 1024(direct blocks) + 3([t,d]indirect blocks) */
+#define EXT2_MAX_RESERVE_BLOCKS 1027
+#define EXT2_RESERVE_WINDOW_NOT_ALLOCATED 0
/*
* The second extended file system version
*/
@@ -200,6 +201,8 @@ struct ext2_group_desc
#define EXT2_IOC_SETFLAGS FS_IOC_SETFLAGS
#define EXT2_IOC_GETVERSION FS_IOC_GETVERSION
#define EXT2_IOC_SETVERSION FS_IOC_SETVERSION
+#define EXT2_IOC_GETRSVSZ _IOR('f', 5, long)
+#define EXT2_IOC_SETRSVSZ _IOW('f', 6, long)
/*
* ioctl commands in 32 bit emulation
@@ -317,8 +320,9 @@ struct ext2_inode {
#define EXT2_MOUNT_XATTR_USER 0x004000 /* Extended user attributes */
#define EXT2_MOUNT_POSIX_ACL 0x008000 /* POSIX Access Control Lists */
#define EXT2_MOUNT_XIP 0x010000 /* Execute in place */
-#define EXT2_MOUNT_USRQUOTA 0x020000 /* user quota */
-#define EXT2_MOUNT_GRPQUOTA 0x040000 /* group quota */
+#define EXT2_MOUNT_USRQUOTA 0x020000 /* user quota */
+#define EXT2_MOUNT_GRPQUOTA 0x040000 /* group quota */
+#define EXT2_MOUNT_RESERVATION 0x080000 /* Preallocation */
#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
@@ -557,5 +561,13 @@ enum {
#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1)
#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \
~EXT2_DIR_ROUND)
+#define EXT2_MAX_REC_LEN ((1<<16)-1)
+
+static inline ext2_fsblk_t
+ext2_group_first_block_no(struct super_block *sb, unsigned long group_no)
+{
+ return group_no * (ext2_fsblk_t)EXT2_BLOCKS_PER_GROUP(sb) +
+ le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block);
+}
#endif /* _LINUX_EXT2_FS_H */
diff --git a/include/linux/ext2_fs_sb.h b/include/linux/ext2_fs_sb.h
index d149f2959e67..f273415ab6f1 100644
--- a/include/linux/ext2_fs_sb.h
+++ b/include/linux/ext2_fs_sb.h
@@ -18,6 +18,52 @@
#include <linux/blockgroup_lock.h>
#include <linux/percpu_counter.h>
+#include <linux/rbtree.h>
+
+/* XXX Here for now... not interested in restructing headers JUST now */
+
+/* data type for block offset of block group */
+typedef int ext2_grpblk_t;
+
+/* data type for filesystem-wide blocks number */
+typedef unsigned long ext2_fsblk_t;
+
+#define E2FSBLK "%lu"
+
+struct ext2_reserve_window {
+ ext2_fsblk_t _rsv_start; /* First byte reserved */
+ ext2_fsblk_t _rsv_end; /* Last byte reserved or 0 */
+};
+
+struct ext2_reserve_window_node {
+ struct rb_node rsv_node;
+ __u32 rsv_goal_size;
+ __u32 rsv_alloc_hit;
+ struct ext2_reserve_window rsv_window;
+};
+
+struct ext2_block_alloc_info {
+ /* information about reservation window */
+ struct ext2_reserve_window_node rsv_window_node;
+ /*
+ * was i_next_alloc_block in ext2_inode_info
+ * is the logical (file-relative) number of the
+ * most-recently-allocated block in this file.
+ * We use this for detecting linearly ascending allocation requests.
+ */
+ __u32 last_alloc_logical_block;
+ /*
+ * Was i_next_alloc_goal in ext2_inode_info
+ * is the *physical* companion to i_next_alloc_block.
+ * it the the physical block number of the block which was most-recentl
+ * allocated to this file. This give us the goal (target) for the next
+ * allocation when we detect linearly ascending requests.
+ */
+ ext2_fsblk_t last_alloc_physical_block;
+};
+
+#define rsv_start rsv_window._rsv_start
+#define rsv_end rsv_window._rsv_end
/*
* second extended-fs super-block data in memory
@@ -39,6 +85,7 @@ struct ext2_sb_info {
struct ext2_super_block * s_es; /* Pointer to the super block in the buffer */
struct buffer_head ** s_group_desc;
unsigned long s_mount_opt;
+ unsigned long s_sb_block;
uid_t s_resuid;
gid_t s_resgid;
unsigned short s_mount_state;
@@ -55,6 +102,10 @@ struct ext2_sb_info {
struct percpu_counter s_freeinodes_counter;
struct percpu_counter s_dirs_counter;
struct blockgroup_lock s_blockgroup_lock;
+ /* root of the per fs reservation window tree */
+ spinlock_t s_rsv_window_lock;
+ struct rb_root s_rsv_window_root;
+ struct ext2_reserve_window_node s_rsv_window_head;
};
#endif /* _LINUX_EXT2_FS_SB */
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
index ece49a804fe1..241c01cb92b2 100644
--- a/include/linux/ext3_fs.h
+++ b/include/linux/ext3_fs.h
@@ -35,10 +35,6 @@
/*max window size: 1024(direct blocks) + 3([t,d]indirect blocks) */
#define EXT3_MAX_RESERVE_BLOCKS 1027
#define EXT3_RESERVE_WINDOW_NOT_ALLOCATED 0
-/*
- * Always enable hashed directories
- */
-#define CONFIG_EXT3_INDEX
/*
* Debug code
@@ -76,8 +72,8 @@
* Macro-instructions used to manage several block sizes
*/
#define EXT3_MIN_BLOCK_SIZE 1024
-#define EXT3_MAX_BLOCK_SIZE 4096
-#define EXT3_MIN_BLOCK_LOG_SIZE 10
+#define EXT3_MAX_BLOCK_SIZE 65536
+#define EXT3_MIN_BLOCK_LOG_SIZE 10
#ifdef __KERNEL__
# define EXT3_BLOCK_SIZE(s) ((s)->s_blocksize)
#else
@@ -660,22 +656,36 @@ struct ext3_dir_entry_2 {
#define EXT3_DIR_ROUND (EXT3_DIR_PAD - 1)
#define EXT3_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT3_DIR_ROUND) & \
~EXT3_DIR_ROUND)
+#define EXT3_MAX_REC_LEN ((1<<16)-1)
+
+static inline unsigned ext3_rec_len_from_disk(__le16 dlen)
+{
+ unsigned len = le16_to_cpu(dlen);
+
+ if (len == EXT3_MAX_REC_LEN)
+ return 1 << 16;
+ return len;
+}
+
+static inline __le16 ext3_rec_len_to_disk(unsigned len)
+{
+ if (len == (1 << 16))
+ return cpu_to_le16(EXT3_MAX_REC_LEN);
+ else if (len > (1 << 16))
+ BUG();
+ return cpu_to_le16(len);
+}
+
/*
* Hash Tree Directory indexing
* (c) Daniel Phillips, 2001
*/
-#ifdef CONFIG_EXT3_INDEX
- #define is_dx(dir) (EXT3_HAS_COMPAT_FEATURE(dir->i_sb, \
- EXT3_FEATURE_COMPAT_DIR_INDEX) && \
+#define is_dx(dir) (EXT3_HAS_COMPAT_FEATURE(dir->i_sb, \
+ EXT3_FEATURE_COMPAT_DIR_INDEX) && \
(EXT3_I(dir)->i_flags & EXT3_INDEX_FL))
#define EXT3_DIR_LINK_MAX(dir) (!is_dx(dir) && (dir)->i_nlink >= EXT3_LINK_MAX)
#define EXT3_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2 || (dir)->i_nlink == 1)
-#else
- #define is_dx(dir) 0
-#define EXT3_DIR_LINK_MAX(dir) ((dir)->i_nlink >= EXT3_LINK_MAX)
-#define EXT3_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2)
-#endif
/* Legal values for the dx_root hash_version field: */
diff --git a/include/linux/ext3_fs_sb.h b/include/linux/ext3_fs_sb.h
index d3c08353edf6..b65f0288b842 100644
--- a/include/linux/ext3_fs_sb.h
+++ b/include/linux/ext3_fs_sb.h
@@ -44,6 +44,7 @@ struct ext3_sb_info {
struct ext3_super_block * s_es; /* Pointer to the super block in the buffer */
struct buffer_head ** s_group_desc;
unsigned long s_mount_opt;
+ ext3_fsblk_t s_sb_block;
uid_t s_resuid;
gid_t s_resgid;
unsigned short s_mount_state;
diff --git a/include/linux/ext4_fs.h b/include/linux/ext4_fs.h
index cdee7aaa57aa..97dd409d5f4a 100644
--- a/include/linux/ext4_fs.h
+++ b/include/linux/ext4_fs.h
@@ -36,10 +36,6 @@
/*max window size: 1024(direct blocks) + 3([t,d]indirect blocks) */
#define EXT4_MAX_RESERVE_BLOCKS 1027
#define EXT4_RESERVE_WINDOW_NOT_ALLOCATED 0
-/*
- * Always enable hashed directories
- */
-#define CONFIG_EXT4_INDEX
/*
* Debug code
@@ -105,37 +101,29 @@
#define EXT4_BLOCK_ALIGN(size, blkbits) ALIGN((size), (1 << (blkbits)))
/*
- * Macro-instructions used to manage fragments
- */
-#define EXT4_MIN_FRAG_SIZE 1024
-#define EXT4_MAX_FRAG_SIZE 4096
-#define EXT4_MIN_FRAG_LOG_SIZE 10
-#ifdef __KERNEL__
-# define EXT4_FRAG_SIZE(s) (EXT4_SB(s)->s_frag_size)
-# define EXT4_FRAGS_PER_BLOCK(s) (EXT4_SB(s)->s_frags_per_block)
-#else
-# define EXT4_FRAG_SIZE(s) (EXT4_MIN_FRAG_SIZE << (s)->s_log_frag_size)
-# define EXT4_FRAGS_PER_BLOCK(s) (EXT4_BLOCK_SIZE(s) / EXT4_FRAG_SIZE(s))
-#endif
-
-/*
* Structure of a blocks group descriptor
*/
struct ext4_group_desc
{
- __le32 bg_block_bitmap; /* Blocks bitmap block */
- __le32 bg_inode_bitmap; /* Inodes bitmap block */
- __le32 bg_inode_table; /* Inodes table block */
+ __le32 bg_block_bitmap_lo; /* Blocks bitmap block */
+ __le32 bg_inode_bitmap_lo; /* Inodes bitmap block */
+ __le32 bg_inode_table_lo; /* Inodes table block */
__le16 bg_free_blocks_count; /* Free blocks count */
__le16 bg_free_inodes_count; /* Free inodes count */
__le16 bg_used_dirs_count; /* Directories count */
- __u16 bg_flags;
- __u32 bg_reserved[3];
+ __le16 bg_flags; /* EXT4_BG_flags (INODE_UNINIT, etc) */
+ __u32 bg_reserved[2]; /* Likely block/inode bitmap checksum */
+ __le16 bg_itable_unused; /* Unused inodes count */
+ __le16 bg_checksum; /* crc16(sb_uuid+group+desc) */
__le32 bg_block_bitmap_hi; /* Blocks bitmap block MSB */
__le32 bg_inode_bitmap_hi; /* Inodes bitmap block MSB */
__le32 bg_inode_table_hi; /* Inodes table block MSB */
};
+#define EXT4_BG_INODE_UNINIT 0x0001 /* Inode table/bitmap not in use */
+#define EXT4_BG_BLOCK_UNINIT 0x0002 /* Block bitmap not in use */
+#define EXT4_BG_INODE_ZEROED 0x0004 /* On-disk itable initialized to zero */
+
#ifdef __KERNEL__
#include <linux/ext4_fs_i.h>
#include <linux/ext4_fs_sb.h>
@@ -311,27 +299,24 @@ struct ext4_inode {
__le32 i_generation; /* File version (for NFS) */
__le32 i_file_acl; /* File ACL */
__le32 i_dir_acl; /* Directory ACL */
- __le32 i_faddr; /* Fragment address */
+ __le32 i_obso_faddr; /* Obsoleted fragment address */
union {
struct {
- __u8 l_i_frag; /* Fragment number */
- __u8 l_i_fsize; /* Fragment size */
+ __le16 l_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */
__le16 l_i_file_acl_high;
__le16 l_i_uid_high; /* these 2 fields */
__le16 l_i_gid_high; /* were reserved2[0] */
__u32 l_i_reserved2;
} linux2;
struct {
- __u8 h_i_frag; /* Fragment number */
- __u8 h_i_fsize; /* Fragment size */
+ __le16 h_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */
__u16 h_i_mode_high;
__u16 h_i_uid_high;
__u16 h_i_gid_high;
__u32 h_i_author;
} hurd2;
struct {
- __u8 m_i_frag; /* Fragment number */
- __u8 m_i_fsize; /* Fragment size */
+ __le16 h_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */
__le16 m_i_file_acl_high;
__u32 m_i_reserved2[2];
} masix2;
@@ -419,8 +404,6 @@ do { \
#if defined(__KERNEL__) || defined(__linux__)
#define i_reserved1 osd1.linux1.l_i_reserved1
-#define i_frag osd2.linux2.l_i_frag
-#define i_fsize osd2.linux2.l_i_fsize
#define i_file_acl_high osd2.linux2.l_i_file_acl_high
#define i_uid_low i_uid
#define i_gid_low i_gid
@@ -431,8 +414,6 @@ do { \
#elif defined(__GNU__)
#define i_translator osd1.hurd1.h_i_translator
-#define i_frag osd2.hurd2.h_i_frag;
-#define i_fsize osd2.hurd2.h_i_fsize;
#define i_uid_high osd2.hurd2.h_i_uid_high
#define i_gid_high osd2.hurd2.h_i_gid_high
#define i_author osd2.hurd2.h_i_author
@@ -440,8 +421,6 @@ do { \
#elif defined(__masix__)
#define i_reserved1 osd1.masix1.m_i_reserved1
-#define i_frag osd2.masix2.m_i_frag
-#define i_fsize osd2.masix2.m_i_fsize
#define i_file_acl_high osd2.masix2.m_i_file_acl_high
#define i_reserved2 osd2.masix2.m_i_reserved2
@@ -522,15 +501,15 @@ do { \
*/
struct ext4_super_block {
/*00*/ __le32 s_inodes_count; /* Inodes count */
- __le32 s_blocks_count; /* Blocks count */
- __le32 s_r_blocks_count; /* Reserved blocks count */
- __le32 s_free_blocks_count; /* Free blocks count */
+ __le32 s_blocks_count_lo; /* Blocks count */
+ __le32 s_r_blocks_count_lo; /* Reserved blocks count */
+ __le32 s_free_blocks_count_lo; /* Free blocks count */
/*10*/ __le32 s_free_inodes_count; /* Free inodes count */
__le32 s_first_data_block; /* First Data Block */
__le32 s_log_block_size; /* Block size */
- __le32 s_log_frag_size; /* Fragment size */
+ __le32 s_obso_log_frag_size; /* Obsoleted fragment size */
/*20*/ __le32 s_blocks_per_group; /* # Blocks per group */
- __le32 s_frags_per_group; /* # Fragments per group */
+ __le32 s_obso_frags_per_group; /* Obsoleted fragments per group */
__le32 s_inodes_per_group; /* # Inodes per group */
__le32 s_mtime; /* Mount time */
/*30*/ __le32 s_wtime; /* Write time */
@@ -595,13 +574,13 @@ struct ext4_super_block {
/*150*/ __le32 s_blocks_count_hi; /* Blocks count */
__le32 s_r_blocks_count_hi; /* Reserved blocks count */
__le32 s_free_blocks_count_hi; /* Free blocks count */
- __u16 s_min_extra_isize; /* All inodes have at least # bytes */
- __u16 s_want_extra_isize; /* New inodes should reserve # bytes */
- __u32 s_flags; /* Miscellaneous flags */
- __u16 s_raid_stride; /* RAID stride */
- __u16 s_mmp_interval; /* # seconds to wait in MMP checking */
- __u64 s_mmp_block; /* Block for multi-mount protection */
- __u32 s_raid_stripe_width; /* blocks on all data disks (N*stride)*/
+ __le16 s_min_extra_isize; /* All inodes have at least # bytes */
+ __le16 s_want_extra_isize; /* New inodes should reserve # bytes */
+ __le32 s_flags; /* Miscellaneous flags */
+ __le16 s_raid_stride; /* RAID stride */
+ __le16 s_mmp_interval; /* # seconds to wait in MMP checking */
+ __le64 s_mmp_block; /* Block for multi-mount protection */
+ __le32 s_raid_stripe_width; /* blocks on all data disks (N*stride)*/
__u32 s_reserved[163]; /* Padding to the end of the block */
};
@@ -692,6 +671,7 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
#define EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
#define EXT4_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
#define EXT4_FEATURE_RO_COMPAT_BTREE_DIR 0x0004
+#define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010
#define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020
#define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040
@@ -702,15 +682,18 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
#define EXT4_FEATURE_INCOMPAT_META_BG 0x0010
#define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */
#define EXT4_FEATURE_INCOMPAT_64BIT 0x0080
+#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200
#define EXT4_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
#define EXT4_FEATURE_INCOMPAT_SUPP (EXT4_FEATURE_INCOMPAT_FILETYPE| \
EXT4_FEATURE_INCOMPAT_RECOVER| \
EXT4_FEATURE_INCOMPAT_META_BG| \
EXT4_FEATURE_INCOMPAT_EXTENTS| \
- EXT4_FEATURE_INCOMPAT_64BIT)
+ EXT4_FEATURE_INCOMPAT_64BIT| \
+ EXT4_FEATURE_INCOMPAT_FLEX_BG)
#define EXT4_FEATURE_RO_COMPAT_SUPP (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER| \
EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM| \
EXT4_FEATURE_RO_COMPAT_DIR_NLINK | \
EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE | \
EXT4_FEATURE_RO_COMPAT_BTREE_DIR)
@@ -789,17 +772,11 @@ struct ext4_dir_entry_2 {
* (c) Daniel Phillips, 2001
*/
-#ifdef CONFIG_EXT4_INDEX
- #define is_dx(dir) (EXT4_HAS_COMPAT_FEATURE(dir->i_sb, \
- EXT4_FEATURE_COMPAT_DIR_INDEX) && \
+#define is_dx(dir) (EXT4_HAS_COMPAT_FEATURE(dir->i_sb, \
+ EXT4_FEATURE_COMPAT_DIR_INDEX) && \
(EXT4_I(dir)->i_flags & EXT4_INDEX_FL))
#define EXT4_DIR_LINK_MAX(dir) (!is_dx(dir) && (dir)->i_nlink >= EXT4_LINK_MAX)
#define EXT4_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2 || (dir)->i_nlink == 1)
-#else
- #define is_dx(dir) 0
-#define EXT4_DIR_LINK_MAX(dir) ((dir)->i_nlink >= EXT4_LINK_MAX)
-#define EXT4_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2)
-#endif
/* Legal values for the dx_root hash_version field: */
@@ -1004,39 +981,39 @@ extern void ext4_inode_table_set(struct super_block *sb,
static inline ext4_fsblk_t ext4_blocks_count(struct ext4_super_block *es)
{
return ((ext4_fsblk_t)le32_to_cpu(es->s_blocks_count_hi) << 32) |
- le32_to_cpu(es->s_blocks_count);
+ le32_to_cpu(es->s_blocks_count_lo);
}
static inline ext4_fsblk_t ext4_r_blocks_count(struct ext4_super_block *es)
{
return ((ext4_fsblk_t)le32_to_cpu(es->s_r_blocks_count_hi) << 32) |
- le32_to_cpu(es->s_r_blocks_count);
+ le32_to_cpu(es->s_r_blocks_count_lo);
}
static inline ext4_fsblk_t ext4_free_blocks_count(struct ext4_super_block *es)
{
return ((ext4_fsblk_t)le32_to_cpu(es->s_free_blocks_count_hi) << 32) |
- le32_to_cpu(es->s_free_blocks_count);
+ le32_to_cpu(es->s_free_blocks_count_lo);
}
static inline void ext4_blocks_count_set(struct ext4_super_block *es,
ext4_fsblk_t blk)
{
- es->s_blocks_count = cpu_to_le32((u32)blk);
+ es->s_blocks_count_lo = cpu_to_le32((u32)blk);
es->s_blocks_count_hi = cpu_to_le32(blk >> 32);
}
static inline void ext4_free_blocks_count_set(struct ext4_super_block *es,
ext4_fsblk_t blk)
{
- es->s_free_blocks_count = cpu_to_le32((u32)blk);
+ es->s_free_blocks_count_lo = cpu_to_le32((u32)blk);
es->s_free_blocks_count_hi = cpu_to_le32(blk >> 32);
}
static inline void ext4_r_blocks_count_set(struct ext4_super_block *es,
ext4_fsblk_t blk)
{
- es->s_r_blocks_count = cpu_to_le32((u32)blk);
+ es->s_r_blocks_count_lo = cpu_to_le32((u32)blk);
es->s_r_blocks_count_hi = cpu_to_le32(blk >> 32);
}
diff --git a/include/linux/ext4_fs_extents.h b/include/linux/ext4_fs_extents.h
index 81406f3655d4..d2045a26195d 100644
--- a/include/linux/ext4_fs_extents.h
+++ b/include/linux/ext4_fs_extents.h
@@ -74,7 +74,7 @@ struct ext4_extent {
__le32 ee_block; /* first logical block extent covers */
__le16 ee_len; /* number of blocks covered by extent */
__le16 ee_start_hi; /* high 16 bits of physical block */
- __le32 ee_start; /* low 32 bits of physical block */
+ __le32 ee_start_lo; /* low 32 bits of physical block */
};
/*
@@ -83,7 +83,7 @@ struct ext4_extent {
*/
struct ext4_extent_idx {
__le32 ei_block; /* index covers logical blocks from 'block' */
- __le32 ei_leaf; /* pointer to the physical block of the next *
+ __le32 ei_leaf_lo; /* pointer to the physical block of the next *
* level. leaf or next index could be there */
__le16 ei_leaf_hi; /* high 16 bits of physical block */
__u16 ei_unused;
diff --git a/include/linux/ext4_fs_i.h b/include/linux/ext4_fs_i.h
index 1a511e9905aa..86ddfe2089f3 100644
--- a/include/linux/ext4_fs_i.h
+++ b/include/linux/ext4_fs_i.h
@@ -78,11 +78,6 @@ struct ext4_ext_cache {
struct ext4_inode_info {
__le32 i_data[15]; /* unconverted */
__u32 i_flags;
-#ifdef EXT4_FRAGMENTS
- __u32 i_faddr;
- __u8 i_frag_no;
- __u8 i_frag_size;
-#endif
ext4_fsblk_t i_file_acl;
__u32 i_dir_acl;
__u32 i_dtime;
diff --git a/include/linux/ext4_fs_sb.h b/include/linux/ext4_fs_sb.h
index 1b2ffee12be9..b40e827cd495 100644
--- a/include/linux/ext4_fs_sb.h
+++ b/include/linux/ext4_fs_sb.h
@@ -28,11 +28,8 @@
* third extended-fs super-block data in memory
*/
struct ext4_sb_info {
- unsigned long s_frag_size; /* Size of a fragment in bytes */
unsigned long s_desc_size; /* Size of a group descriptor in bytes */
- unsigned long s_frags_per_block;/* Number of fragments per block */
unsigned long s_inodes_per_block;/* Number of inodes per block */
- unsigned long s_frags_per_group;/* Number of fragments in a group */
unsigned long s_blocks_per_group;/* Number of blocks in a group */
unsigned long s_inodes_per_group;/* Number of inodes in a group */
unsigned long s_itb_per_group; /* Number of inode table blocks per group */
@@ -45,6 +42,7 @@ struct ext4_sb_info {
struct ext4_super_block * s_es; /* Pointer to the super block in the buffer */
struct buffer_head ** s_group_desc;
unsigned long s_mount_opt;
+ ext4_fsblk_t s_sb_block;
uid_t s_resuid;
gid_t s_resgid;
unsigned short s_mount_state;
diff --git a/include/linux/ext4_jbd2.h b/include/linux/ext4_jbd2.h
index d716e6392cf6..38c71d3c8dbf 100644
--- a/include/linux/ext4_jbd2.h
+++ b/include/linux/ext4_jbd2.h
@@ -12,8 +12,8 @@
* Ext4-specific journaling extensions.
*/
-#ifndef _LINUX_EXT4_JBD_H
-#define _LINUX_EXT4_JBD_H
+#ifndef _LINUX_EXT4_JBD2_H
+#define _LINUX_EXT4_JBD2_H
#include <linux/fs.h>
#include <linux/jbd2.h>
@@ -228,4 +228,4 @@ static inline int ext4_should_writeback_data(struct inode *inode)
return 0;
}
-#endif /* _LINUX_EXT4_JBD_H */
+#endif /* _LINUX_EXT4_JBD2_H */
diff --git a/include/linux/f75375s.h b/include/linux/f75375s.h
new file mode 100644
index 000000000000..e99e22500668
--- /dev/null
+++ b/include/linux/f75375s.h
@@ -0,0 +1,21 @@
+/*
+ * f75375s.h - platform data structure for f75375s sensor
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007, Riku Voipio <riku.voipio@iki.fi>
+ */
+
+#ifndef __LINUX_F75375S_H
+#define __LINUX_F75375S_H
+
+/* We want to set fans spinning on systems where there is no
+ * BIOS to do that for us */
+struct f75375s_platform_data {
+ u8 pwm[2];
+ u8 pwm_enable[2];
+};
+
+#endif /* __LINUX_F75375S_H */
diff --git a/include/linux/fb.h b/include/linux/fb.h
index cec54106aa87..58c57a33e5dd 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -180,6 +180,7 @@ struct fb_bitfield {
};
#define FB_NONSTD_HAM 1 /* Hold-And-Modify (HAM) */
+#define FB_NONSTD_REV_PIX_IN_B 2 /* order of pixels in each byte is reversed */
#define FB_ACTIVATE_NOW 0 /* set values immediately (or vbl)*/
#define FB_ACTIVATE_NXTOPEN 1 /* activate on next open */
@@ -206,6 +207,7 @@ struct fb_bitfield {
#define FB_VMODE_NONINTERLACED 0 /* non interlaced */
#define FB_VMODE_INTERLACED 1 /* interlaced */
#define FB_VMODE_DOUBLE 2 /* double scan */
+#define FB_VMODE_ODD_FLD_FIRST 4 /* interlaced: top line first */
#define FB_VMODE_MASK 255
#define FB_VMODE_YWRAP 256 /* ywrap instead of panning */
@@ -1054,6 +1056,7 @@ struct fb_videomode {
u32 flag;
};
+extern const char *fb_mode_option;
extern const struct fb_videomode vesa_modes[];
struct fb_modelist {
diff --git a/include/linux/fcntl.h b/include/linux/fcntl.h
index 40b93265d4ba..86037400a6e3 100644
--- a/include/linux/fcntl.h
+++ b/include/linux/fcntl.h
@@ -3,12 +3,17 @@
#include <asm/fcntl.h>
-/* Cancel a blocking posix lock; internal use only until we expose an
- * asynchronous lock api to userspace: */
-#define F_CANCELLK (F_LINUX_SPECIFIC_BASE+5)
+#define F_SETLEASE (F_LINUX_SPECIFIC_BASE + 0)
+#define F_GETLEASE (F_LINUX_SPECIFIC_BASE + 1)
-#define F_SETLEASE (F_LINUX_SPECIFIC_BASE+0)
-#define F_GETLEASE (F_LINUX_SPECIFIC_BASE+1)
+/*
+ * Cancel a blocking posix lock; internal use only until we expose an
+ * asynchronous lock api to userspace:
+ */
+#define F_CANCELLK (F_LINUX_SPECIFIC_BASE + 5)
+
+/* Create a file descriptor with FD_CLOEXEC set. */
+#define F_DUPFD_CLOEXEC (F_LINUX_SPECIFIC_BASE + 6)
/*
* Request nofications on a directory.
diff --git a/include/linux/file.h b/include/linux/file.h
index 0114fbc78061..56023c74e9fd 100644
--- a/include/linux/file.h
+++ b/include/linux/file.h
@@ -62,6 +62,15 @@ extern struct kmem_cache *filp_cachep;
extern void FASTCALL(__fput(struct file *));
extern void FASTCALL(fput(struct file *));
+struct file_operations;
+struct vfsmount;
+struct dentry;
+extern int init_file(struct file *, struct vfsmount *mnt,
+ struct dentry *dentry, mode_t mode,
+ const struct file_operations *fop);
+extern struct file *alloc_file(struct vfsmount *, struct dentry *dentry,
+ mode_t mode, const struct file_operations *fop);
+
static inline void fput_light(struct file *file, int fput_needed)
{
if (unlikely(fput_needed))
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 91b2e3b9251e..ddfa0372a3b7 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -146,6 +146,7 @@ struct sock;
extern unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen);
extern int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk);
+extern int sk_detach_filter(struct sock *sk);
extern int sk_chk_filter(struct sock_filter *filter, int flen);
#endif /* __KERNEL__ */
diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h
index 1a45d6f41b09..0f0e271f97fa 100644
--- a/include/linux/firewire-cdev.h
+++ b/include/linux/firewire-cdev.h
@@ -178,6 +178,7 @@ union fw_cdev_event {
#define FW_CDEV_IOC_QUEUE_ISO _IOWR('#', 0x09, struct fw_cdev_queue_iso)
#define FW_CDEV_IOC_START_ISO _IOW('#', 0x0a, struct fw_cdev_start_iso)
#define FW_CDEV_IOC_STOP_ISO _IOW('#', 0x0b, struct fw_cdev_stop_iso)
+#define FW_CDEV_IOC_GET_CYCLE_TIMER _IOR('#', 0x0c, struct fw_cdev_get_cycle_timer)
/* FW_CDEV_VERSION History
*
@@ -459,4 +460,18 @@ struct fw_cdev_stop_iso {
__u32 handle;
};
+/**
+ * struct fw_cdev_get_cycle_timer - read cycle timer register
+ * @local_time: system time, in microseconds since the Epoch
+ * @cycle_timer: isochronous cycle timer, as per OHCI 1.1 clause 5.13
+ *
+ * The %FW_CDEV_IOC_GET_CYCLE_TIMER ioctl reads the isochronous cycle timer
+ * and also the system clock. This allows to express the receive time of an
+ * isochronous packet as a system time with microsecond accuracy.
+ */
+struct fw_cdev_get_cycle_timer {
+ __u64 local_time;
+ __u32 cycle_timer;
+};
+
#endif /* _LINUX_FIREWIRE_CDEV_H */
diff --git a/include/linux/freezer.h b/include/linux/freezer.h
index efded00ad08c..08934995c7ab 100644
--- a/include/linux/freezer.h
+++ b/include/linux/freezer.h
@@ -4,6 +4,7 @@
#define FREEZER_H_INCLUDED
#include <linux/sched.h>
+#include <linux/wait.h>
#ifdef CONFIG_PM_SLEEP
/*
@@ -126,6 +127,36 @@ static inline void set_freezable(void)
current->flags &= ~PF_NOFREEZE;
}
+/*
+ * Freezer-friendly wrappers around wait_event_interruptible() and
+ * wait_event_interruptible_timeout(), originally defined in <linux/wait.h>
+ */
+
+#define wait_event_freezable(wq, condition) \
+({ \
+ int __retval; \
+ do { \
+ __retval = wait_event_interruptible(wq, \
+ (condition) || freezing(current)); \
+ if (__retval && !freezing(current)) \
+ break; \
+ else if (!(condition)) \
+ __retval = -ERESTARTSYS; \
+ } while (try_to_freeze()); \
+ __retval; \
+})
+
+
+#define wait_event_freezable_timeout(wq, condition, timeout) \
+({ \
+ long __retval = timeout; \
+ do { \
+ __retval = wait_event_interruptible_timeout(wq, \
+ (condition) || freezing(current), \
+ __retval); \
+ } while (try_to_freeze()); \
+ __retval; \
+})
#else /* !CONFIG_PM_SLEEP */
static inline int frozen(struct task_struct *p) { return 0; }
static inline int freezing(struct task_struct *p) { return 0; }
@@ -143,6 +174,13 @@ static inline void freezer_do_not_count(void) {}
static inline void freezer_count(void) {}
static inline int freezer_should_skip(struct task_struct *p) { return 0; }
static inline void set_freezable(void) {}
+
+#define wait_event_freezable(wq, condition) \
+ wait_event_interruptible(wq, condition)
+
+#define wait_event_freezable_timeout(wq, condition, timeout) \
+ wait_event_interruptible_timeout(wq, condition, timeout)
+
#endif /* !CONFIG_PM_SLEEP */
#endif /* FREEZER_H_INCLUDED */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 6d760f1ad875..b3ec4a496d64 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -123,6 +123,7 @@ extern int dir_notify_enable;
#define MS_SLAVE (1<<19) /* change to slave */
#define MS_SHARED (1<<20) /* change to shared */
#define MS_RELATIME (1<<21) /* Update atime relative to mtime/ctime. */
+#define MS_KERNMOUNT (1<<22) /* this is a kern_mount call */
#define MS_ACTIVE (1<<30)
#define MS_NOUSER (1<<31)
@@ -283,7 +284,6 @@ extern int dir_notify_enable;
#include <linux/init.h>
#include <linux/pid.h>
#include <linux/mutex.h>
-#include <linux/sysctl.h>
#include <linux/capability.h>
#include <asm/atomic.h>
@@ -301,9 +301,9 @@ struct kstatfs;
struct vm_area_struct;
struct vfsmount;
-extern void __init inode_init(unsigned long);
+extern void __init inode_init(void);
extern void __init inode_init_early(void);
-extern void __init mnt_init(unsigned long);
+extern void __init mnt_init(void);
extern void __init files_init(unsigned long);
struct buffer_head;
@@ -330,6 +330,8 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
#define ATTR_KILL_SUID 2048
#define ATTR_KILL_SGID 4096
#define ATTR_FILE 8192
+#define ATTR_KILL_PRIV 16384
+#define ATTR_OPEN 32768 /* Truncating from open(O_TRUNC) */
/*
* This is the Inode Attributes structure, used for notify_change(). It
@@ -381,7 +383,7 @@ struct iattr {
* trying again. The aop will be taking reasonable
* precautions not to livelock. If the caller held a page
* reference, it should drop it before retrying. Returned
- * by readpage(), prepare_write(), and commit_write().
+ * by readpage().
*
* address_space_operation functions return these large constants to indicate
* special semantics to the caller. These are much larger than the bytes in a
@@ -394,6 +396,9 @@ enum positive_aop_returns {
AOP_TRUNCATED_PAGE = 0x80001,
};
+#define AOP_FLAG_UNINTERRUPTIBLE 0x0001 /* will not do a short write */
+#define AOP_FLAG_CONT_EXPAND 0x0002 /* called from cont_expand */
+
/*
* oh the beauties of C type declarations.
*/
@@ -401,6 +406,39 @@ struct page;
struct address_space;
struct writeback_control;
+struct iov_iter {
+ const struct iovec *iov;
+ unsigned long nr_segs;
+ size_t iov_offset;
+ size_t count;
+};
+
+size_t iov_iter_copy_from_user_atomic(struct page *page,
+ struct iov_iter *i, unsigned long offset, size_t bytes);
+size_t iov_iter_copy_from_user(struct page *page,
+ struct iov_iter *i, unsigned long offset, size_t bytes);
+void iov_iter_advance(struct iov_iter *i, size_t bytes);
+int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes);
+size_t iov_iter_single_seg_count(struct iov_iter *i);
+
+static inline void iov_iter_init(struct iov_iter *i,
+ const struct iovec *iov, unsigned long nr_segs,
+ size_t count, size_t written)
+{
+ i->iov = iov;
+ i->nr_segs = nr_segs;
+ i->iov_offset = 0;
+ i->count = count + written;
+
+ iov_iter_advance(i, written);
+}
+
+static inline size_t iov_iter_count(struct iov_iter *i)
+{
+ return i->count;
+}
+
+
struct address_space_operations {
int (*writepage)(struct page *page, struct writeback_control *wbc);
int (*readpage)(struct file *, struct page *);
@@ -421,6 +459,14 @@ struct address_space_operations {
*/
int (*prepare_write)(struct file *, struct page *, unsigned, unsigned);
int (*commit_write)(struct file *, struct page *, unsigned, unsigned);
+
+ int (*write_begin)(struct file *, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata);
+ int (*write_end)(struct file *, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata);
+
/* Unfortunately this kludge is needed for FIBMAP. Don't use it */
sector_t (*bmap)(struct address_space *, sector_t);
void (*invalidatepage) (struct page *, unsigned long);
@@ -435,6 +481,18 @@ struct address_space_operations {
int (*launder_page) (struct page *);
};
+/*
+ * pagecache_write_begin/pagecache_write_end must be used by general code
+ * to write into the pagecache.
+ */
+int pagecache_write_begin(struct file *, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata);
+
+int pagecache_write_end(struct file *, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata);
+
struct backing_dev_info;
struct address_space {
struct inode *host; /* owner: inode, block_device */
@@ -697,16 +755,14 @@ struct fown_struct {
* Track a single file's readahead state
*/
struct file_ra_state {
- pgoff_t start; /* where readahead started */
- unsigned long size; /* # of readahead pages */
- unsigned long async_size; /* do asynchronous readahead when
+ pgoff_t start; /* where readahead started */
+ unsigned int size; /* # of readahead pages */
+ unsigned int async_size; /* do asynchronous readahead when
there are only # of pages ahead */
- unsigned long ra_pages; /* Maximum readahead window */
- unsigned long mmap_hit; /* Cache hit stat for mmap accesses */
- unsigned long mmap_miss; /* Cache miss stat for mmap accesses */
- unsigned long prev_index; /* Cache last read() position */
- unsigned int prev_offset; /* Offset where last read() ended in a page */
+ unsigned int ra_pages; /* Maximum readahead window */
+ int mmap_miss; /* Cache miss stat for mmap accesses */
+ loff_t prev_pos; /* Cache last read() position */
};
/*
@@ -739,7 +795,7 @@ struct file {
unsigned int f_uid, f_gid;
struct file_ra_state f_ra;
- unsigned long f_version;
+ u64 f_version;
#ifdef CONFIG_SECURITY
void *f_security;
#endif
@@ -883,6 +939,7 @@ extern int vfs_setlease(struct file *, long, struct file_lock **);
extern int lease_modify(struct file_lock **, int);
extern int lock_may_read(struct inode *, loff_t start, unsigned long count);
extern int lock_may_write(struct inode *, loff_t start, unsigned long count);
+extern struct seq_operations locks_seq_operations;
struct fasync_struct {
int magic;
@@ -930,7 +987,7 @@ struct super_block {
const struct super_operations *s_op;
struct dquot_operations *dq_op;
struct quotactl_ops *s_qcop;
- struct export_operations *s_export_op;
+ const struct export_operations *s_export_op;
unsigned long s_flags;
unsigned long s_magic;
struct dentry *s_root;
@@ -948,6 +1005,7 @@ struct super_block {
struct list_head s_inodes; /* all inodes */
struct list_head s_dirty; /* dirty inodes */
struct list_head s_io; /* parked for writeback */
+ struct list_head s_more_io; /* parked for more writeback */
struct hlist_head s_anon; /* anonymous dentries for (nfs) exporting */
struct list_head s_files;
@@ -1206,16 +1264,68 @@ struct super_operations {
#endif
};
-/* Inode state bits. Protected by inode_lock. */
-#define I_DIRTY_SYNC 1 /* Not dirty enough for O_DATASYNC */
-#define I_DIRTY_DATASYNC 2 /* Data-related inode changes pending */
-#define I_DIRTY_PAGES 4 /* Data-related inode changes pending */
-#define __I_LOCK 3
+/*
+ * Inode state bits. Protected by inode_lock.
+ *
+ * Three bits determine the dirty state of the inode, I_DIRTY_SYNC,
+ * I_DIRTY_DATASYNC and I_DIRTY_PAGES.
+ *
+ * Four bits define the lifetime of an inode. Initially, inodes are I_NEW,
+ * until that flag is cleared. I_WILL_FREE, I_FREEING and I_CLEAR are set at
+ * various stages of removing an inode.
+ *
+ * Two bits are used for locking and completion notification, I_LOCK and I_SYNC.
+ *
+ * I_DIRTY_SYNC Inode itself is dirty.
+ * I_DIRTY_DATASYNC Data-related inode changes pending
+ * I_DIRTY_PAGES Inode has dirty pages. Inode itself may be clean.
+ * I_NEW get_new_inode() sets i_state to I_LOCK|I_NEW. Both
+ * are cleared by unlock_new_inode(), called from iget().
+ * I_WILL_FREE Must be set when calling write_inode_now() if i_count
+ * is zero. I_FREEING must be set when I_WILL_FREE is
+ * cleared.
+ * I_FREEING Set when inode is about to be freed but still has dirty
+ * pages or buffers attached or the inode itself is still
+ * dirty.
+ * I_CLEAR Set by clear_inode(). In this state the inode is clean
+ * and can be destroyed.
+ *
+ * Inodes that are I_WILL_FREE, I_FREEING or I_CLEAR are
+ * prohibited for many purposes. iget() must wait for
+ * the inode to be completely released, then create it
+ * anew. Other functions will just ignore such inodes,
+ * if appropriate. I_LOCK is used for waiting.
+ *
+ * I_LOCK Serves as both a mutex and completion notification.
+ * New inodes set I_LOCK. If two processes both create
+ * the same inode, one of them will release its inode and
+ * wait for I_LOCK to be released before returning.
+ * Inodes in I_WILL_FREE, I_FREEING or I_CLEAR state can
+ * also cause waiting on I_LOCK, without I_LOCK actually
+ * being set. find_inode() uses this to prevent returning
+ * nearly-dead inodes.
+ * I_SYNC Similar to I_LOCK, but limited in scope to writeback
+ * of inode dirty data. Having a seperate lock for this
+ * purpose reduces latency and prevents some filesystem-
+ * specific deadlocks.
+ *
+ * Q: Why does I_DIRTY_DATASYNC exist? It appears as if it could be replaced
+ * by (I_DIRTY_SYNC|I_DIRTY_PAGES).
+ * Q: What is the difference between I_WILL_FREE and I_FREEING?
+ * Q: igrab() only checks on (I_FREEING|I_WILL_FREE). Should it also check on
+ * I_CLEAR? If not, why?
+ */
+#define I_DIRTY_SYNC 1
+#define I_DIRTY_DATASYNC 2
+#define I_DIRTY_PAGES 4
+#define I_NEW 8
+#define I_WILL_FREE 16
+#define I_FREEING 32
+#define I_CLEAR 64
+#define __I_LOCK 7
#define I_LOCK (1 << __I_LOCK)
-#define I_FREEING 16
-#define I_CLEAR 32
-#define I_NEW 64
-#define I_WILL_FREE 128
+#define __I_SYNC 8
+#define I_SYNC (1 << __I_SYNC)
#define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES)
@@ -1350,7 +1460,8 @@ void unnamed_dev_init(void);
extern int register_filesystem(struct file_system_type *);
extern int unregister_filesystem(struct file_system_type *);
-extern struct vfsmount *kern_mount(struct file_system_type *);
+extern struct vfsmount *kern_mount_data(struct file_system_type *, void *data);
+#define kern_mount(type) kern_mount_data(type, NULL)
extern int may_umount_tree(struct vfsmount *);
extern int may_umount(struct vfsmount *);
extern void umount_tree(struct vfsmount *, int, struct list_head *);
@@ -1359,6 +1470,8 @@ extern long do_mount(char *, char *, char *, unsigned long, void *);
extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int);
extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *,
struct vfsmount *);
+extern struct vfsmount *collect_mounts(struct vfsmount *, struct dentry *);
+extern void drop_collected_mounts(struct vfsmount *);
extern int vfs_statfs(struct dentry *, struct kstatfs *);
@@ -1375,12 +1488,25 @@ extern int locks_mandatory_area(int, struct inode *, struct file *, loff_t, size
* Candidates for mandatory locking have the setgid bit set
* but no group execute bit - an otherwise meaningless combination.
*/
-#define MANDATORY_LOCK(inode) \
- (IS_MANDLOCK(inode) && ((inode)->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
+
+static inline int __mandatory_lock(struct inode *ino)
+{
+ return (ino->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID;
+}
+
+/*
+ * ... and these candidates should be on MS_MANDLOCK mounted fs,
+ * otherwise these will be advisory locks
+ */
+
+static inline int mandatory_lock(struct inode *ino)
+{
+ return IS_MANDLOCK(ino) && __mandatory_lock(ino);
+}
static inline int locks_verify_locked(struct inode *inode)
{
- if (MANDATORY_LOCK(inode))
+ if (mandatory_lock(inode))
return locks_mandatory_locked(inode);
return 0;
}
@@ -1391,7 +1517,7 @@ static inline int locks_verify_truncate(struct inode *inode,
struct file *filp,
loff_t size)
{
- if (inode->i_flock && MANDATORY_LOCK(inode))
+ if (inode->i_flock && mandatory_lock(inode))
return locks_mandatory_area(
FLOCK_VERIFY_WRITE, inode, filp,
size < inode->i_size ? size : inode->i_size,
@@ -1412,7 +1538,7 @@ static inline int break_lease(struct inode *inode, unsigned int mode)
extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs,
struct file *filp);
-extern long do_sys_open(int fdf, const char __user *filename, int flags,
+extern long do_sys_open(int dfd, const char __user *filename, int flags,
int mode);
extern struct file *filp_open(const char *, int, int);
extern struct file * dentry_open(struct dentry *, struct vfsmount *, int);
@@ -1661,6 +1787,7 @@ extern int bdev_read_only(struct block_device *);
extern int set_blocksize(struct block_device *, int);
extern int sb_set_blocksize(struct super_block *, int);
extern int sb_min_blocksize(struct super_block *, int);
+extern int sb_has_dirty_inodes(struct super_block *);
extern int generic_file_mmap(struct file *, struct vm_area_struct *);
extern int generic_file_readonly_mmap(struct file *, struct vm_area_struct *);
@@ -1799,6 +1926,8 @@ extern int vfs_fstat(unsigned int, struct kstat *);
extern int vfs_ioctl(struct file *, unsigned int, unsigned int, unsigned long);
+extern void get_filesystem(struct file_system_type *fs);
+extern void put_filesystem(struct file_system_type *fs);
extern struct file_system_type *get_fs_type(const char *name);
extern struct super_block *get_super(struct block_device *);
extern struct super_block *user_get_super(dev_t);
@@ -1819,8 +1948,12 @@ extern int simple_empty(struct dentry *);
extern int simple_readpage(struct file *file, struct page *page);
extern int simple_prepare_write(struct file *file, struct page *page,
unsigned offset, unsigned to);
-extern int simple_commit_write(struct file *file, struct page *page,
- unsigned offset, unsigned to);
+extern int simple_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata);
+extern int simple_write_end(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata);
extern struct dentry *simple_lookup(struct inode *, struct dentry *, struct nameidata *);
extern ssize_t generic_read_dir(struct file *, char __user *, size_t, loff_t *);
@@ -1958,7 +2091,8 @@ static inline void free_secdata(void *secdata)
{ }
#endif /* CONFIG_SECURITY */
-int proc_nr_files(ctl_table *table, int write, struct file *filp,
+struct ctl_table;
+int proc_nr_files(struct ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos);
diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
index dfc4e4f68da4..2bd31fa623b6 100644
--- a/include/linux/fsnotify.h
+++ b/include/linux/fsnotify.h
@@ -41,8 +41,9 @@ static inline void fsnotify_d_move(struct dentry *entry)
*/
static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
const char *old_name, const char *new_name,
- int isdir, struct inode *target, struct inode *source)
+ int isdir, struct inode *target, struct dentry *moved)
{
+ struct inode *source = moved->d_inode;
u32 cookie = inotify_get_cookie();
if (old_dir == new_dir)
@@ -67,7 +68,7 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
if (source) {
inotify_inode_queue_event(source, IN_MOVE_SELF, 0, NULL, NULL);
}
- audit_inode_child(new_name, source, new_dir);
+ audit_inode_child(new_name, moved, new_dir);
}
/*
@@ -98,7 +99,7 @@ static inline void fsnotify_create(struct inode *inode, struct dentry *dentry)
inode_dir_notify(inode, DN_CREATE);
inotify_inode_queue_event(inode, IN_CREATE, 0, dentry->d_name.name,
dentry->d_inode);
- audit_inode_child(dentry->d_name.name, dentry->d_inode, inode);
+ audit_inode_child(dentry->d_name.name, dentry, inode);
}
/*
@@ -109,7 +110,7 @@ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry)
inode_dir_notify(inode, DN_CREATE);
inotify_inode_queue_event(inode, IN_CREATE | IN_ISDIR, 0,
dentry->d_name.name, dentry->d_inode);
- audit_inode_child(dentry->d_name.name, dentry->d_inode, inode);
+ audit_inode_child(dentry->d_name.name, dentry, inode);
}
/*
diff --git a/include/linux/fuse.h b/include/linux/fuse.h
index 9fbe9d258e22..d0c437028c80 100644
--- a/include/linux/fuse.h
+++ b/include/linux/fuse.h
@@ -6,7 +6,17 @@
See the file COPYING.
*/
-/* This file defines the kernel interface of FUSE */
+/*
+ * This file defines the kernel interface of FUSE
+ *
+ * Protocol changelog:
+ *
+ * 7.9:
+ * - new fuse_getattr_in input argument of GETATTR
+ * - add lk_flags in fuse_lk_in
+ * - add lock_owner field to fuse_setattr_in, fuse_read_in and fuse_write_in
+ * - add blksize field to fuse_attr
+ */
#include <asm/types.h>
#include <linux/major.h>
@@ -15,7 +25,7 @@
#define FUSE_KERNEL_VERSION 7
/** Minor version number of this interface */
-#define FUSE_KERNEL_MINOR_VERSION 8
+#define FUSE_KERNEL_MINOR_VERSION 9
/** The node ID of the root inode */
#define FUSE_ROOT_ID 1
@@ -44,6 +54,8 @@ struct fuse_attr {
__u32 uid;
__u32 gid;
__u32 rdev;
+ __u32 blksize;
+ __u32 padding;
};
struct fuse_kstatfs {
@@ -76,6 +88,9 @@ struct fuse_file_lock {
#define FATTR_ATIME (1 << 4)
#define FATTR_MTIME (1 << 5)
#define FATTR_FH (1 << 6)
+#define FATTR_ATIME_NOW (1 << 7)
+#define FATTR_MTIME_NOW (1 << 8)
+#define FATTR_LOCKOWNER (1 << 9)
/**
* Flags returned by the OPEN request
@@ -91,12 +106,38 @@ struct fuse_file_lock {
*/
#define FUSE_ASYNC_READ (1 << 0)
#define FUSE_POSIX_LOCKS (1 << 1)
+#define FUSE_FILE_OPS (1 << 2)
+#define FUSE_ATOMIC_O_TRUNC (1 << 3)
/**
* Release flags
*/
#define FUSE_RELEASE_FLUSH (1 << 0)
+/**
+ * Getattr flags
+ */
+#define FUSE_GETATTR_FH (1 << 0)
+
+/**
+ * Lock flags
+ */
+#define FUSE_LK_FLOCK (1 << 0)
+
+/**
+ * WRITE flags
+ *
+ * FUSE_WRITE_CACHE: delayed write from page cache, file handle is guessed
+ * FUSE_WRITE_LOCKOWNER: lock_owner field is valid
+ */
+#define FUSE_WRITE_CACHE (1 << 0)
+#define FUSE_WRITE_LOCKOWNER (1 << 1)
+
+/**
+ * Read flags
+ */
+#define FUSE_READ_LOCKOWNER (1 << 1)
+
enum fuse_opcode {
FUSE_LOOKUP = 1,
FUSE_FORGET = 2, /* no reply */
@@ -139,6 +180,8 @@ enum fuse_opcode {
/* The read buffer is required to be at least 8k, but may be much larger */
#define FUSE_MIN_READ_BUFFER 8192
+#define FUSE_COMPAT_ENTRY_OUT_SIZE 120
+
struct fuse_entry_out {
__u64 nodeid; /* Inode ID */
__u64 generation; /* Inode generation: nodeid:gen must
@@ -154,6 +197,14 @@ struct fuse_forget_in {
__u64 nlookup;
};
+struct fuse_getattr_in {
+ __u32 getattr_flags;
+ __u32 dummy;
+ __u64 fh;
+};
+
+#define FUSE_COMPAT_ATTR_OUT_SIZE 96
+
struct fuse_attr_out {
__u64 attr_valid; /* Cache timeout for the attributes */
__u32 attr_valid_nsec;
@@ -184,7 +235,7 @@ struct fuse_setattr_in {
__u32 padding;
__u64 fh;
__u64 size;
- __u64 unused1;
+ __u64 lock_owner;
__u64 atime;
__u64 mtime;
__u64 unused2;
@@ -227,14 +278,18 @@ struct fuse_read_in {
__u64 fh;
__u64 offset;
__u32 size;
- __u32 padding;
+ __u32 read_flags;
+ __u64 lock_owner;
};
+#define FUSE_COMPAT_WRITE_IN_SIZE 24
+
struct fuse_write_in {
__u64 fh;
__u64 offset;
__u32 size;
__u32 write_flags;
+ __u64 lock_owner;
};
struct fuse_write_out {
@@ -273,6 +328,8 @@ struct fuse_lk_in {
__u64 fh;
__u64 owner;
struct fuse_file_lock lk;
+ __u32 lk_flags;
+ __u32 padding;
};
struct fuse_lk_out {
diff --git a/include/linux/futex.h b/include/linux/futex.h
index 99650353adfa..92d420fe03f8 100644
--- a/include/linux/futex.h
+++ b/include/linux/futex.h
@@ -149,10 +149,6 @@ union futex_key {
int offset;
} both;
};
-int get_futex_key(u32 __user *uaddr, struct rw_semaphore *shared,
- union futex_key *key);
-void get_futex_key_refs(union futex_key *key);
-void drop_futex_key_refs(union futex_key *key);
#ifdef CONFIG_FUTEX
extern void exit_robust_list(struct task_struct *curr);
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index bc68dd9a6d41..7e93a9ae7064 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -48,18 +48,12 @@ struct vm_area_struct;
#define __GFP_NOMEMALLOC ((__force gfp_t)0x10000u) /* Don't use emergency reserves */
#define __GFP_HARDWALL ((__force gfp_t)0x20000u) /* Enforce hardwall cpuset memory allocs */
#define __GFP_THISNODE ((__force gfp_t)0x40000u)/* No fallback, no policies */
-#define __GFP_MOVABLE ((__force gfp_t)0x80000u) /* Page is movable */
+#define __GFP_RECLAIMABLE ((__force gfp_t)0x80000u) /* Page is reclaimable */
+#define __GFP_MOVABLE ((__force gfp_t)0x100000u) /* Page is movable */
-#define __GFP_BITS_SHIFT 20 /* Room for 20 __GFP_FOO bits */
+#define __GFP_BITS_SHIFT 21 /* Room for 21 __GFP_FOO bits */
#define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1))
-/* if you forget to add the bitmask here kernel will crash, period */
-#define GFP_LEVEL_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_FS| \
- __GFP_COLD|__GFP_NOWARN|__GFP_REPEAT| \
- __GFP_NOFAIL|__GFP_NORETRY|__GFP_COMP| \
- __GFP_NOMEMALLOC|__GFP_HARDWALL|__GFP_THISNODE| \
- __GFP_MOVABLE)
-
/* This equals 0, but use constants in case they ever change */
#define GFP_NOWAIT (GFP_ATOMIC & ~__GFP_HIGH)
/* GFP_ATOMIC means both !wait (__GFP_WAIT not set) and use emergency pool */
@@ -67,6 +61,8 @@ struct vm_area_struct;
#define GFP_NOIO (__GFP_WAIT)
#define GFP_NOFS (__GFP_WAIT | __GFP_IO)
#define GFP_KERNEL (__GFP_WAIT | __GFP_IO | __GFP_FS)
+#define GFP_TEMPORARY (__GFP_WAIT | __GFP_IO | __GFP_FS | \
+ __GFP_RECLAIMABLE)
#define GFP_USER (__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HARDWALL)
#define GFP_HIGHUSER (__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HARDWALL | \
__GFP_HIGHMEM)
@@ -86,6 +82,19 @@ struct vm_area_struct;
#define GFP_THISNODE ((__force gfp_t)0)
#endif
+/* This mask makes up all the page movable related flags */
+#define GFP_MOVABLE_MASK (__GFP_RECLAIMABLE|__GFP_MOVABLE)
+
+/* Control page allocator reclaim behavior */
+#define GFP_RECLAIM_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_FS|\
+ __GFP_NOWARN|__GFP_REPEAT|__GFP_NOFAIL|\
+ __GFP_NORETRY|__GFP_NOMEMALLOC)
+
+/* Control allocation constraints */
+#define GFP_CONSTRAINT_MASK (__GFP_HARDWALL|__GFP_THISNODE)
+
+/* Do not use these with a slab allocator */
+#define GFP_SLAB_BUG_MASK (__GFP_DMA32|__GFP_HIGHMEM|~__GFP_BITS_MASK)
/* Flag - indicates that the buffer will be suitable for DMA. Ignored on some
platforms, used as appropriate on others */
@@ -95,25 +104,50 @@ struct vm_area_struct;
/* 4GB DMA on some platforms */
#define GFP_DMA32 __GFP_DMA32
+/* Convert GFP flags to their corresponding migrate type */
+static inline int allocflags_to_migratetype(gfp_t gfp_flags)
+{
+ WARN_ON((gfp_flags & GFP_MOVABLE_MASK) == GFP_MOVABLE_MASK);
+
+ if (unlikely(page_group_by_mobility_disabled))
+ return MIGRATE_UNMOVABLE;
+
+ /* Group based on mobility */
+ return (((gfp_flags & __GFP_MOVABLE) != 0) << 1) |
+ ((gfp_flags & __GFP_RECLAIMABLE) != 0);
+}
static inline enum zone_type gfp_zone(gfp_t flags)
{
+ int base = 0;
+
+#ifdef CONFIG_NUMA
+ if (flags & __GFP_THISNODE)
+ base = MAX_NR_ZONES;
+#endif
+
#ifdef CONFIG_ZONE_DMA
if (flags & __GFP_DMA)
- return ZONE_DMA;
+ return base + ZONE_DMA;
#endif
#ifdef CONFIG_ZONE_DMA32
if (flags & __GFP_DMA32)
- return ZONE_DMA32;
+ return base + ZONE_DMA32;
#endif
if ((flags & (__GFP_HIGHMEM | __GFP_MOVABLE)) ==
(__GFP_HIGHMEM | __GFP_MOVABLE))
- return ZONE_MOVABLE;
+ return base + ZONE_MOVABLE;
#ifdef CONFIG_HIGHMEM
if (flags & __GFP_HIGHMEM)
- return ZONE_HIGHMEM;
+ return base + ZONE_HIGHMEM;
#endif
- return ZONE_NORMAL;
+ return base + ZONE_NORMAL;
+}
+
+static inline gfp_t set_migrateflags(gfp_t gfp, gfp_t migrate_flags)
+{
+ BUG_ON((gfp & GFP_MOVABLE_MASK) == GFP_MOVABLE_MASK);
+ return (gfp & ~(GFP_MOVABLE_MASK)) | migrate_flags;
}
/*
diff --git a/include/linux/gpio_keys.h b/include/linux/gpio_keys.h
index 265d17830a0f..c6d3a9de5634 100644
--- a/include/linux/gpio_keys.h
+++ b/include/linux/gpio_keys.h
@@ -8,6 +8,7 @@ struct gpio_keys_button {
int active_low;
char *desc;
int type; /* input event type (EV_KEY, EV_SW) */
+ int wakeup; /* configure the button as a wake-up source */
};
struct gpio_keys_platform_data {
diff --git a/include/linux/hid.h b/include/linux/hid.h
index edb8024d744b..6e35b92b1d2c 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -469,8 +469,8 @@ struct hid_device { /* device report descriptor */
/* handler for raw output data, used by hidraw */
int (*hid_output_raw_report) (struct hid_device *, __u8 *, size_t);
#ifdef CONFIG_USB_HIDINPUT_POWERBOOK
- unsigned long pb_pressed_fn[NBITS(KEY_MAX)];
- unsigned long pb_pressed_numlock[NBITS(KEY_MAX)];
+ unsigned long pb_pressed_fn[BITS_TO_LONGS(KEY_CNT)];
+ unsigned long pb_pressed_numlock[BITS_TO_LONGS(KEY_CNT)];
#endif
};
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index 540799bc85f8..7a9398e19704 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -300,7 +300,7 @@ hrtimer_forward(struct hrtimer *timer, ktime_t now, ktime_t interval);
/* Precise sleep: */
extern long hrtimer_nanosleep(struct timespec *rqtp,
- struct timespec __user *rmtp,
+ struct timespec *rmtp,
const enum hrtimer_mode mode,
const clockid_t clockid);
extern long hrtimer_nanosleep_restart(struct restart_block *restart_block);
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index 3a19b032c0eb..24968790bc3e 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -19,7 +19,7 @@ static inline int is_vm_hugetlb_page(struct vm_area_struct *vma)
int hugetlb_sysctl_handler(struct ctl_table *, int, struct file *, void __user *, size_t *, loff_t *);
int hugetlb_treat_movable_handler(struct ctl_table *, int, struct file *, void __user *, size_t *, loff_t *);
int copy_hugetlb_page_range(struct mm_struct *, struct mm_struct *, struct vm_area_struct *);
-int follow_hugetlb_page(struct mm_struct *, struct vm_area_struct *, struct page **, struct vm_area_struct **, unsigned long *, int *, int);
+int follow_hugetlb_page(struct mm_struct *, struct vm_area_struct *, struct page **, struct vm_area_struct **, unsigned long *, int *, int, int);
void unmap_hugepage_range(struct vm_area_struct *, unsigned long, unsigned long);
void __unmap_hugepage_range(struct vm_area_struct *, unsigned long, unsigned long);
int hugetlb_prefault(struct address_space *, struct vm_area_struct *);
@@ -33,6 +33,7 @@ void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed);
extern unsigned long max_huge_pages;
extern unsigned long hugepages_treat_as_movable;
+extern int hugetlb_dynamic_pool;
extern const unsigned long hugetlb_zero, hugetlb_infinity;
extern int sysctl_hugetlb_shm_group;
@@ -105,7 +106,7 @@ static inline unsigned long hugetlb_total_pages(void)
return 0;
}
-#define follow_hugetlb_page(m,v,p,vs,a,b,i) ({ BUG(); 0; })
+#define follow_hugetlb_page(m,v,p,vs,a,b,i,w) ({ BUG(); 0; })
#define follow_huge_addr(mm, addr, write) ERR_PTR(-EINVAL)
#define copy_hugetlb_page_range(src, dst, vma) ({ BUG(); 0; })
#define hugetlb_prefault(mapping, vma) ({ BUG(); 0; })
@@ -164,8 +165,10 @@ static inline struct hugetlbfs_sb_info *HUGETLBFS_SB(struct super_block *sb)
extern const struct file_operations hugetlbfs_file_operations;
extern struct vm_operations_struct hugetlb_vm_ops;
struct file *hugetlb_file_setup(const char *name, size_t);
-int hugetlb_get_quota(struct address_space *mapping);
-void hugetlb_put_quota(struct address_space *mapping);
+int hugetlb_get_quota(struct address_space *mapping, long delta);
+void hugetlb_put_quota(struct address_space *mapping, long delta);
+
+#define BLOCKS_PER_HUGEPAGE (HPAGE_SIZE / 512)
static inline int is_file_hugepages(struct file *file)
{
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
index a271b67a8e2d..88c81403eb3f 100644
--- a/include/linux/i2c-id.h
+++ b/include/linux/i2c-id.h
@@ -120,6 +120,7 @@
#define I2C_DRIVERID_WM8753 91 /* Wolfson WM8753 audio codec */
#define I2C_DRIVERID_LM4857 92 /* LM4857 Audio Amplifier */
#define I2C_DRIVERID_VP27SMPX 93 /* Panasonic VP27s tuner internal MPX */
+#define I2C_DRIVERID_CS4270 94 /* Cirrus Logic 4270 audio codec */
#define I2C_DRIVERID_I2CDEV 900
#define I2C_DRIVERID_ARP 902 /* SMBus ARP Client */
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 8033e6b33271..a100c9f8eb7c 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -400,11 +400,6 @@ extern int i2c_release_client(struct i2c_client *);
extern void i2c_clients_command(struct i2c_adapter *adap,
unsigned int cmd, void *arg);
-/* returns -EBUSY if address has been taken, 0 if not. Note that the only
- other place at which this is called is within i2c_attach_client; so
- you can cheat by simply not registering. Not recommended, of course! */
-extern int i2c_check_addr (struct i2c_adapter *adapter, int addr);
-
/* Detect function. It iterates over all possible addresses itself.
* It will only call found_proc if some client is connected at the
* specific address (unless a 'force' matched);
diff --git a/include/linux/i2o.h b/include/linux/i2o.h
index 9752307d16ba..7da5b98d90e6 100644
--- a/include/linux/i2o.h
+++ b/include/linux/i2o.h
@@ -32,6 +32,7 @@
#include <linux/workqueue.h> /* work_struct */
#include <linux/mempool.h>
#include <linux/mutex.h>
+#include <linux/scatterlist.h>
#include <asm/io.h>
#include <asm/semaphore.h> /* Needed for MUTEX init macros */
@@ -837,7 +838,7 @@ static inline int i2o_dma_map_sg(struct i2o_controller *c,
if ((sizeof(dma_addr_t) > 4) && c->pae_support)
*mptr++ = cpu_to_le32(i2o_dma_high(sg_dma_address(sg)));
#endif
- sg++;
+ sg = sg_next(sg);
}
*sg_ptr = mptr;
diff --git a/include/linux/i8042.h b/include/linux/i8042.h
new file mode 100644
index 000000000000..7907a72403ee
--- /dev/null
+++ b/include/linux/i8042.h
@@ -0,0 +1,35 @@
+#ifndef _LINUX_I8042_H
+#define _LINUX_I8042_H
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+
+/*
+ * Standard commands.
+ */
+
+#define I8042_CMD_CTL_RCTR 0x0120
+#define I8042_CMD_CTL_WCTR 0x1060
+#define I8042_CMD_CTL_TEST 0x01aa
+
+#define I8042_CMD_KBD_DISABLE 0x00ad
+#define I8042_CMD_KBD_ENABLE 0x00ae
+#define I8042_CMD_KBD_TEST 0x01ab
+#define I8042_CMD_KBD_LOOP 0x11d2
+
+#define I8042_CMD_AUX_DISABLE 0x00a7
+#define I8042_CMD_AUX_ENABLE 0x00a8
+#define I8042_CMD_AUX_TEST 0x01a9
+#define I8042_CMD_AUX_SEND 0x10d4
+#define I8042_CMD_AUX_LOOP 0x11d3
+
+#define I8042_CMD_MUX_PFX 0x0090
+#define I8042_CMD_MUX_SEND 0x1090
+
+int i8042_command(unsigned char *param, int command);
+
+#endif
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 02a27e8cbad2..dc75ccbcf991 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -192,22 +192,20 @@ typedef unsigned char byte; /* used everywhere */
struct hwif_s;
typedef int (ide_ack_intr_t)(struct hwif_s *);
-#ifndef NO_DMA
-#define NO_DMA 255
-#endif
-
/*
* hwif_chipset_t is used to keep track of the specific hardware
* chipset used by each IDE interface, if known.
*/
-typedef enum { ide_unknown, ide_generic, ide_pci,
+enum { ide_unknown, ide_generic, ide_pci,
ide_cmd640, ide_dtc2278, ide_ali14xx,
ide_qd65xx, ide_umc8672, ide_ht6560b,
ide_rz1000, ide_trm290,
ide_cmd646, ide_cy82c693, ide_4drives,
ide_pmac, ide_etrax100, ide_acorn,
ide_au1xxx, ide_forced
-} hwif_chipset_t;
+};
+
+typedef u8 hwif_chipset_t;
/*
* Structure to hold all information about the location of this port
@@ -215,22 +213,16 @@ typedef enum { ide_unknown, ide_generic, ide_pci,
typedef struct hw_regs_s {
unsigned long io_ports[IDE_NR_PORTS]; /* task file registers */
int irq; /* our irq number */
- int dma; /* our dma entry */
ide_ack_intr_t *ack_intr; /* acknowledge interrupt */
hwif_chipset_t chipset;
struct device *dev;
} hw_regs_t;
-/*
- * Register new hardware with ide
- */
-int ide_register_hw(hw_regs_t *, int, struct hwif_s **);
-int ide_register_hw_with_fixup(hw_regs_t *, int, struct hwif_s **,
- void (*)(struct hwif_s *));
+struct hwif_s * ide_find_port(unsigned long);
+
+int ide_register_hw(hw_regs_t *, void (*)(struct hwif_s *), int,
+ struct hwif_s **);
-/*
- * Set up hw_regs_t structure before calling ide_register_hw (optional)
- */
void ide_setup_ports( hw_regs_t *hw,
unsigned long base,
int *offsets,
@@ -268,11 +260,7 @@ static inline void ide_std_init_ports(hw_regs_t *hw,
# define ide_init_default_irq(base) (0)
#endif
-/*
- * ide_init_hwif_ports() is OBSOLETE and will be removed in 2.7 series.
- * New ports shouldn't define IDE_ARCH_OBSOLETE_INIT in <asm/ide.h>.
- */
-#ifdef IDE_ARCH_OBSOLETE_INIT
+#ifdef CONFIG_IDE_ARCH_OBSOLETE_INIT
static inline void ide_init_hwif_ports(hw_regs_t *hw,
unsigned long io_addr,
unsigned long ctl_addr,
@@ -302,7 +290,7 @@ static inline void ide_init_hwif_ports(hw_regs_t *hw,
if (io_addr || ctl_addr)
printk(KERN_WARNING "%s: must not be called\n", __FUNCTION__);
}
-#endif /* IDE_ARCH_OBSOLETE_INIT */
+#endif /* CONFIG_IDE_ARCH_OBSOLETE_INIT */
/* Currently only m68k, apus and m8xx need it */
#ifndef IDE_ARCH_ACK_INTR
@@ -363,7 +351,6 @@ typedef union {
* ATA DATA Register Special.
* ATA NSECTOR Count Register().
* ATAPI Byte Count Register.
- * Channel index ordering pairs.
*/
typedef union {
unsigned all :16;
@@ -378,7 +365,7 @@ typedef union {
#error "Please fix <asm/byteorder.h>"
#endif
} b;
-} ata_nsector_t, ata_data_t, atapi_bcount_t, ata_index_t;
+} ata_nsector_t, ata_data_t, atapi_bcount_t;
/*
* ATA-IDE Select Register, aka Device-Head
@@ -576,7 +563,6 @@ typedef struct ide_drive_s {
select_t select; /* basic drive/head select reg value */
u8 keep_settings; /* restore settings after drive reset */
- u8 autodma; /* device can safely use dma on host */
u8 using_dma; /* disk is using dma for read/write */
u8 retry_pio; /* retrying dma capable host in pio */
u8 state; /* retry state */
@@ -600,6 +586,7 @@ typedef struct ide_drive_s {
unsigned nice0 : 1; /* give obvious excess bandwidth */
unsigned nice2 : 1; /* give a share in our own bandwidth */
unsigned doorlocking : 1; /* for removable only: door lock/unlock works */
+ unsigned nodma : 1; /* disallow DMA */
unsigned autotune : 2; /* 0=default, 1=autotune, 2=noautotune */
unsigned remap_0_to_1 : 1; /* 0=noremap, 1=remap 0->1 (for EZDrive) */
unsigned blocked : 1; /* 1=powermanagment told us not to do anything, so sleep nicely */
@@ -657,7 +644,7 @@ typedef struct ide_drive_s {
((1<<ide_pci)|(1<<ide_cmd646)|(1<<ide_ali14xx))
#define IDE_CHIPSET_IS_PCI(c) ((IDE_CHIPSET_PCI_MASK >> (c)) & 1)
-struct ide_pci_device_s;
+struct ide_port_info;
typedef struct hwif_s {
struct hwif_s *next; /* for linked-list in ide_hwgroup_t */
@@ -672,7 +659,6 @@ typedef struct hwif_s {
unsigned long sata_scr[SATA_NR_PORTS];
unsigned long sata_misc[SATA_NR_PORTS];
- hw_regs_t hw; /* Hardware info */
ide_drive_t drives[MAX_DRIVES]; /* drive info */
u8 major; /* our major number */
@@ -681,11 +667,10 @@ typedef struct hwif_s {
u8 straight8; /* Alan's straight 8 check */
u8 bus_state; /* power state of the IDE bus */
- u16 host_flags;
+ u32 host_flags;
u8 pio_mask;
- u8 atapi_dma; /* host supports atapi_dma */
u8 ultra_mask;
u8 mwdma_mask;
u8 swdma_mask;
@@ -695,7 +680,9 @@ typedef struct hwif_s {
hwif_chipset_t chipset; /* sub-module for tuning.. */
struct pci_dev *pci_dev; /* for pci chipsets */
- struct ide_pci_device_s *cds; /* chipset device struct */
+ const struct ide_port_info *cds; /* chipset device struct */
+
+ ide_ack_intr_t *ack_intr;
void (*rw_disk)(ide_drive_t *, struct request *);
@@ -726,6 +713,8 @@ typedef struct hwif_s {
u8 (*mdma_filter)(ide_drive_t *);
u8 (*udma_filter)(ide_drive_t *);
+ void (*fixup)(struct hwif_s *);
+
void (*ata_input_data)(ide_drive_t *, void *, u32);
void (*ata_output_data)(ide_drive_t *, void *, u32);
@@ -736,7 +725,6 @@ typedef struct hwif_s {
void (*dma_exec_cmd)(ide_drive_t *, u8);
void (*dma_start)(ide_drive_t *);
int (*ide_dma_end)(ide_drive_t *drive);
- int (*ide_dma_check)(ide_drive_t *drive);
int (*ide_dma_on)(ide_drive_t *drive);
void (*dma_off_quietly)(ide_drive_t *drive);
int (*ide_dma_test_irq)(ide_drive_t *drive);
@@ -772,7 +760,7 @@ typedef struct hwif_s {
unsigned int nsect;
unsigned int nleft;
- unsigned int cursg;
+ struct scatterlist *cursg;
unsigned int cursg_ofs;
int rqsize; /* max sectors per request */
@@ -798,13 +786,9 @@ typedef struct hwif_s {
unsigned serialized : 1; /* serialized all channel operation */
unsigned sharing_irq: 1; /* 1 = sharing irq with another hwif */
unsigned reset : 1; /* reset after probe */
- unsigned autodma : 1; /* auto-attempt using DMA at boot */
- unsigned no_lba48 : 1; /* 1 = cannot do LBA48 */
- unsigned no_lba48_dma : 1; /* 1 = cannot do LBA48 DMA */
unsigned auto_poll : 1; /* supports nop auto-poll */
unsigned sg_mapped : 1; /* sg_table and sg_nents are ready */
unsigned no_io_32bit : 1; /* 1 = can not do 32-bit IO ops */
- unsigned err_stops_fifo : 1; /* 1=data FIFO is cleared by an error */
unsigned mmio : 1; /* host uses MMIO */
struct device gendev;
@@ -847,8 +831,6 @@ typedef struct hwgroup_s {
/* for pci chipsets */
struct pci_dev *pci_dev;
- /* chipset device struct */
- struct ide_pci_device_s *cds;
/* current request */
struct request *rq;
@@ -1036,68 +1018,29 @@ extern int ide_end_request (ide_drive_t *drive, int uptodate, int nrsecs);
int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq,
int uptodate, int nr_sectors);
-/*
- * This is used on exit from the driver to designate the next irq handler
- * and also to start the safety timer.
- */
extern void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry);
-/*
- * This is used on exit from the driver to designate the next irq handler
- * and start the safety time safely and atomically from the IRQ handler
- * with respect to the command issue (which it also does)
- */
extern void ide_execute_command(ide_drive_t *, task_ioreg_t cmd, ide_handler_t *, unsigned int, ide_expiry_t *);
ide_startstop_t __ide_error(ide_drive_t *, struct request *, u8, u8);
-/*
- * ide_error() takes action based on the error returned by the controller.
- * The caller should return immediately after invoking this.
- *
- * (drive, msg, status)
- */
ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, byte stat);
ide_startstop_t __ide_abort(ide_drive_t *, struct request *);
-/*
- * Abort a running command on the controller triggering the abort
- * from a host side, non error situation
- * (drive, msg)
- */
extern ide_startstop_t ide_abort(ide_drive_t *, const char *);
extern void ide_fix_driveid(struct hd_driveid *);
-/*
- * ide_fixstring() cleans up and (optionally) byte-swaps a text string,
- * removing leading/trailing blanks and compressing internal blanks.
- * It is primarily used to tidy up the model name/number fields as
- * returned by the WIN_[P]IDENTIFY commands.
- *
- * (s, bytecount, byteswap)
- */
+
extern void ide_fixstring(u8 *, const int, const int);
int ide_wait_stat(ide_startstop_t *, ide_drive_t *, u8, u8, unsigned long);
-/*
- * Start a reset operation for an IDE interface.
- * The caller should return immediately after invoking this.
- */
extern ide_startstop_t ide_do_reset (ide_drive_t *);
-/*
- * This function is intended to be used prior to invoking ide_do_drive_cmd().
- */
extern void ide_init_drive_cmd (struct request *rq);
/*
- * this function returns error location sector offset in case of a write error
- */
-extern u64 ide_get_error_location(ide_drive_t *, char *);
-
-/*
* "action" parameter type for ide_do_drive_cmd() below.
*/
typedef enum {
@@ -1109,13 +1052,6 @@ typedef enum {
extern int ide_do_drive_cmd(ide_drive_t *, struct request *, ide_action_t);
-/*
- * Clean up after success/failure of an explicit drive cmd.
- * stat/err are used only when (HWGROUP(drive)->rq->cmd == IDE_DRIVE_CMD).
- * stat/err are used only when (HWGROUP(drive)->rq->cmd == IDE_DRIVE_TASK_MASK).
- *
- * (ide_drive_t *drive, u8 stat, u8 err)
- */
extern void ide_end_drive_cmd(ide_drive_t *, u8, u8);
/*
@@ -1188,10 +1124,6 @@ extern int taskfile_lib_get_identify(ide_drive_t *drive, u8 *);
extern int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout);
-/*
- * ide_stall_queue() can be used by a drive to give excess bandwidth back
- * to the hwgroup by sleeping for timeout jiffies.
- */
extern void ide_stall_queue(ide_drive_t *drive, unsigned long timeout);
extern int ide_spin_wait_hwgroup(ide_drive_t *);
@@ -1211,26 +1143,13 @@ extern int __ide_pci_register_driver(struct pci_driver *driver, struct module *o
#define ide_pci_register_driver(d) pci_register_driver(d)
#endif
-void ide_pci_setup_ports(struct pci_dev *, struct ide_pci_device_s *, int, ata_index_t *);
-extern void ide_setup_pci_noise (struct pci_dev *dev, struct ide_pci_device_s *d);
+void ide_pci_setup_ports(struct pci_dev *, const struct ide_port_info *, int, u8 *);
+void ide_setup_pci_noise(struct pci_dev *, const struct ide_port_info *);
extern void default_hwif_iops(ide_hwif_t *);
extern void default_hwif_mmiops(ide_hwif_t *);
extern void default_hwif_transport(ide_hwif_t *);
-#define ON_BOARD 1
-#define NEVER_BOARD 0
-
-#ifdef CONFIG_BLK_DEV_OFFBOARD
-# define OFF_BOARD ON_BOARD
-#else /* CONFIG_BLK_DEV_OFFBOARD */
-# define OFF_BOARD NEVER_BOARD
-#endif /* CONFIG_BLK_DEV_OFFBOARD */
-
-#define NODMA 0
-#define NOAUTODMA 1
-#define AUTODMA 2
-
typedef struct ide_pci_enablebit_s {
u8 reg; /* byte pci reg holding the enable-bit */
u8 mask; /* mask to isolate the enable-bit */
@@ -1261,29 +1180,65 @@ enum {
IDE_HFLAG_POST_SET_MODE = (1 << 8),
/* don't program host/device for the transfer mode ("smart" hosts) */
IDE_HFLAG_NO_SET_MODE = (1 << 9),
+ /* trust BIOS for programming chipset/device for DMA */
+ IDE_HFLAG_TRUST_BIOS_FOR_DMA = (1 << 10),
+ /* host uses VDMA */
+ IDE_HFLAG_VDMA = (1 << 11),
+ /* ATAPI DMA is unsupported */
+ IDE_HFLAG_NO_ATAPI_DMA = (1 << 12),
+ /* set if host is a "bootable" controller */
+ IDE_HFLAG_BOOTABLE = (1 << 13),
+ /* host doesn't support DMA */
+ IDE_HFLAG_NO_DMA = (1 << 14),
+ /* check if host is PCI IDE device before allowing DMA */
+ IDE_HFLAG_NO_AUTODMA = (1 << 15),
+ /* host is CS5510/CS5520 */
+ IDE_HFLAG_CS5520 = (1 << 16),
+ /* no LBA48 */
+ IDE_HFLAG_NO_LBA48 = (1 << 17),
+ /* no LBA48 DMA */
+ IDE_HFLAG_NO_LBA48_DMA = (1 << 18),
+ /* data FIFO is cleared by an error */
+ IDE_HFLAG_ERROR_STOPS_FIFO = (1 << 19),
+ /* serialize ports */
+ IDE_HFLAG_SERIALIZE = (1 << 20),
+ /* use legacy IRQs */
+ IDE_HFLAG_LEGACY_IRQS = (1 << 21),
+ /* force use of legacy IRQs */
+ IDE_HFLAG_FORCE_LEGACY_IRQS = (1 << 22),
+ /* limit LBA48 requests to 256 sectors */
+ IDE_HFLAG_RQSIZE_256 = (1 << 23),
+ /* use 32-bit I/O ops */
+ IDE_HFLAG_IO_32BIT = (1 << 24),
+ /* unmask IRQs */
+ IDE_HFLAG_UNMASK_IRQS = (1 << 25),
};
-typedef struct ide_pci_device_s {
+#ifdef CONFIG_BLK_DEV_OFFBOARD
+# define IDE_HFLAG_OFF_BOARD IDE_HFLAG_BOOTABLE
+#else
+# define IDE_HFLAG_OFF_BOARD 0
+#endif
+
+struct ide_port_info {
char *name;
- int (*init_setup)(struct pci_dev *, struct ide_pci_device_s *);
- void (*init_setup_dma)(struct pci_dev *, struct ide_pci_device_s *, ide_hwif_t *);
unsigned int (*init_chipset)(struct pci_dev *, const char *);
void (*init_iops)(ide_hwif_t *);
void (*init_hwif)(ide_hwif_t *);
void (*init_dma)(ide_hwif_t *, unsigned long);
void (*fixup)(ide_hwif_t *);
- u8 autodma;
ide_pci_enablebit_t enablebits[2];
- u8 bootable;
+ hwif_chipset_t chipset;
unsigned int extra;
- struct ide_pci_device_s *next;
- u16 host_flags;
+ u32 host_flags;
u8 pio_mask;
+ u8 swdma_mask;
+ u8 mwdma_mask;
u8 udma_mask;
-} ide_pci_device_t;
+};
-extern int ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *);
-extern int ide_setup_pci_devices(struct pci_dev *, struct pci_dev *, ide_pci_device_t *);
+int ide_setup_pci_device(struct pci_dev *, const struct ide_port_info *);
+int ide_setup_pci_devices(struct pci_dev *, struct pci_dev *, const struct ide_port_info *);
void ide_map_sg(ide_drive_t *, struct request *);
void ide_init_sg_cmd(ide_drive_t *, struct request *);
@@ -1308,7 +1263,6 @@ static inline u8 ide_max_dma_mode(ide_drive_t *drive)
return ide_find_dma_mode(drive, XFER_UDMA_6);
}
-int ide_tune_dma(ide_drive_t *);
void ide_dma_off(ide_drive_t *);
void ide_dma_verbose(ide_drive_t *);
int ide_set_dma(ide_drive_t *);
@@ -1335,7 +1289,6 @@ extern void ide_dma_timeout(ide_drive_t *);
#else
static inline u8 ide_find_dma_mode(ide_drive_t *drive, u8 speed) { return 0; }
static inline u8 ide_max_dma_mode(ide_drive_t *drive) { return 0; }
-static inline int ide_tune_dma(ide_drive_t *drive) { return 0; }
static inline void ide_dma_off(ide_drive_t *drive) { ; }
static inline void ide_dma_verbose(ide_drive_t *drive) { ; }
static inline int ide_set_dma(ide_drive_t *drive) { return 1; }
@@ -1368,8 +1321,7 @@ void ide_unregister_region(struct gendisk *);
void ide_undecoded_slave(ide_hwif_t *);
-int probe_hwif_init_with_fixup(ide_hwif_t *, void (*)(ide_hwif_t *));
-extern int probe_hwif_init(ide_hwif_t *);
+int ide_device_add(u8 idx[4]);
static inline void *ide_get_hwifdata (ide_hwif_t * hwif)
{
@@ -1385,7 +1337,6 @@ static inline void ide_set_hwifdata (ide_hwif_t * hwif, void *data)
extern char *ide_xfer_verbose(u8 xfer_rate);
extern void ide_toggle_bounce(ide_drive_t *drive, int on);
extern int ide_set_xfer_rate(ide_drive_t *drive, u8 rate);
-int ide_use_fast_pio(ide_drive_t *);
static inline int ide_dev_has_iordy(struct hd_driveid *id)
{
@@ -1460,4 +1411,11 @@ static inline int hwif_to_node(ide_hwif_t *hwif)
return dev ? pcibus_to_node(dev->bus) : -1;
}
+static inline ide_drive_t *ide_get_paired_drive(ide_drive_t *drive)
+{
+ ide_hwif_t *hwif = HWIF(drive);
+
+ return &hwif->drives[(drive->dn ^ 1) & 1];
+}
+
#endif /* _IDE_H */
diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
index 99e3a1a00099..58e43e566457 100644
--- a/include/linux/if_bridge.h
+++ b/include/linux/if_bridge.h
@@ -107,7 +107,7 @@ struct __fdb_entry
extern void brioctl_set(int (*ioctl_hook)(struct net *, unsigned int, void __user *));
extern struct sk_buff *(*br_handle_frame_hook)(struct net_bridge_port *p,
struct sk_buff *skb);
-extern int (*br_should_route_hook)(struct sk_buff **pskb);
+extern int (*br_should_route_hook)(struct sk_buff *skb);
#endif
diff --git a/include/linux/if_fddi.h b/include/linux/if_fddi.h
index 4aba6b0ad41c..ae77daed6c2f 100644
--- a/include/linux/if_fddi.h
+++ b/include/linux/if_fddi.h
@@ -24,6 +24,8 @@
#ifndef _LINUX_IF_FDDI_H
#define _LINUX_IF_FDDI_H
+#include <linux/types.h>
+
/*
* Define max and min legal sizes. The frame sizes do not include
* 4 byte FCS/CRC (frame check sequence).
diff --git a/include/linux/init.h b/include/linux/init.h
index f8d9d0b5cffc..5141381a7527 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -67,8 +67,10 @@
/* For assembly routines */
#define __INIT .section ".init.text","ax"
+#define __INIT_REFOK .section ".text.init.refok","ax"
#define __FINIT .previous
#define __INITDATA .section ".init.data","aw"
+#define __INITDATA_REFOK .section ".data.init.refok","aw"
#ifndef __ASSEMBLY__
/*
@@ -159,7 +161,7 @@ struct obs_kernel_param {
* obs_kernel_param "array" too far apart in .init.setup.
*/
#define __setup_param(str, unique_id, fn, early) \
- static char __setup_str_##unique_id[] __initdata = str; \
+ static char __setup_str_##unique_id[] __initdata __aligned(1) = str; \
static struct obs_kernel_param __setup_##unique_id \
__attribute_used__ \
__attribute__((__section__(".init.setup"))) \
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 513bc3e489f0..cae35b6b9aec 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -67,16 +67,12 @@
.posix_timers = LIST_HEAD_INIT(sig.posix_timers), \
.cpu_timers = INIT_CPU_TIMERS(sig.cpu_timers), \
.rlim = INIT_RLIMITS, \
- .pgrp = 0, \
- .tty_old_pgrp = NULL, \
- { .__session = 0}, \
}
extern struct nsproxy init_nsproxy;
#define INIT_NSPROXY(nsproxy) { \
.pid_ns = &init_pid_ns, \
.count = ATOMIC_INIT(1), \
- .nslock = __SPIN_LOCK_UNLOCKED(nsproxy.nslock), \
.uts_ns = &init_uts_ns, \
.mnt_ns = NULL, \
INIT_NET_NS(net_ns) \
@@ -95,15 +91,18 @@ extern struct group_info init_groups;
#define INIT_STRUCT_PID { \
.count = ATOMIC_INIT(1), \
- .nr = 0, \
- /* Don't put this struct pid in pid_hash */ \
- .pid_chain = { .next = NULL, .pprev = NULL }, \
.tasks = { \
{ .first = &init_task.pids[PIDTYPE_PID].node }, \
{ .first = &init_task.pids[PIDTYPE_PGID].node }, \
{ .first = &init_task.pids[PIDTYPE_SID].node }, \
}, \
.rcu = RCU_HEAD_INIT, \
+ .level = 0, \
+ .numbers = { { \
+ .nr = 0, \
+ .ns = &init_pid_ns, \
+ .pid_chain = { .next = NULL, .pprev = NULL }, \
+ }, } \
}
#define INIT_PID_LINK(type) \
@@ -171,6 +170,7 @@ extern struct group_info init_groups;
[PIDTYPE_PGID] = INIT_PID_LINK(PIDTYPE_PGID), \
[PIDTYPE_SID] = INIT_PID_LINK(PIDTYPE_SID), \
}, \
+ .dirties = INIT_PROP_LOCAL_SINGLE(dirties), \
INIT_TRACE_IRQFLAGS \
INIT_LOCKDEP \
}
diff --git a/include/linux/inotify.h b/include/linux/inotify.h
index d4f48c6402e6..742b917e7d1b 100644
--- a/include/linux/inotify.h
+++ b/include/linux/inotify.h
@@ -120,6 +120,8 @@ extern __s32 inotify_find_update_watch(struct inotify_handle *, struct inode *,
u32);
extern __s32 inotify_add_watch(struct inotify_handle *, struct inotify_watch *,
struct inode *, __u32);
+extern __s32 inotify_clone_watch(struct inotify_watch *, struct inotify_watch *);
+extern void inotify_evict_watch(struct inotify_watch *);
extern int inotify_rm_watch(struct inotify_handle *, struct inotify_watch *);
extern int inotify_rm_wd(struct inotify_handle *, __u32);
extern void inotify_remove_watch_locked(struct inotify_handle *,
diff --git a/include/linux/input.h b/include/linux/input.h
index 52d1bd434a50..b45f240a8c45 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -98,6 +98,7 @@ struct input_absinfo {
#define EV_PWR 0x16
#define EV_FF_STATUS 0x17
#define EV_MAX 0x1f
+#define EV_CNT (EV_MAX+1)
/*
* Synchronization events.
@@ -526,6 +527,9 @@ struct input_absinfo {
#define KEY_SPELLCHECK 0x1b0 /* AL Spell Check */
#define KEY_LOGOFF 0x1b1 /* AL Logoff */
+#define KEY_DOLLAR 0x1b2
+#define KEY_EURO 0x1b3
+
#define KEY_DEL_EOL 0x1c0
#define KEY_DEL_EOS 0x1c1
#define KEY_INS_LINE 0x1c2
@@ -567,6 +571,7 @@ struct input_absinfo {
/* We avoid low common keys in module aliases so they don't get huge. */
#define KEY_MIN_INTERESTING KEY_MUTE
#define KEY_MAX 0x1ff
+#define KEY_CNT (KEY_MAX+1)
/*
* Relative axes
@@ -583,6 +588,7 @@ struct input_absinfo {
#define REL_WHEEL 0x08
#define REL_MISC 0x09
#define REL_MAX 0x0f
+#define REL_CNT (REL_MAX+1)
/*
* Absolute axes
@@ -615,6 +621,7 @@ struct input_absinfo {
#define ABS_VOLUME 0x20
#define ABS_MISC 0x28
#define ABS_MAX 0x3f
+#define ABS_CNT (ABS_MAX+1)
/*
* Switch events
@@ -625,6 +632,7 @@ struct input_absinfo {
#define SW_HEADPHONE_INSERT 0x02 /* set = inserted */
#define SW_RADIO 0x03 /* set = radio enabled */
#define SW_MAX 0x0f
+#define SW_CNT (SW_MAX+1)
/*
* Misc events
@@ -636,6 +644,7 @@ struct input_absinfo {
#define MSC_RAW 0x03
#define MSC_SCAN 0x04
#define MSC_MAX 0x07
+#define MSC_CNT (MSC_MAX+1)
/*
* LEDs
@@ -653,6 +662,7 @@ struct input_absinfo {
#define LED_MAIL 0x09
#define LED_CHARGING 0x0a
#define LED_MAX 0x0f
+#define LED_CNT (LED_MAX+1)
/*
* Autorepeat values
@@ -670,6 +680,7 @@ struct input_absinfo {
#define SND_BELL 0x01
#define SND_TONE 0x02
#define SND_MAX 0x07
+#define SND_CNT (SND_MAX+1)
/*
* IDs.
@@ -856,7 +867,7 @@ struct ff_rumble_effect {
* defining effect parameters
*
* This structure is sent through ioctl from the application to the driver.
- * To create a new effect aplication should set its @id to -1; the kernel
+ * To create a new effect application should set its @id to -1; the kernel
* will return assigned @id which can later be used to update or delete
* this effect.
*
@@ -920,6 +931,7 @@ struct ff_effect {
#define FF_AUTOCENTER 0x61
#define FF_MAX 0x7f
+#define FF_CNT (FF_MAX+1)
#ifdef __KERNEL__
@@ -932,28 +944,99 @@ struct ff_effect {
#include <linux/timer.h>
#include <linux/mod_devicetable.h>
-#define NBITS(x) (((x)/BITS_PER_LONG)+1)
-#define BIT(x) (1UL<<((x)%BITS_PER_LONG))
-#define LONG(x) ((x)/BITS_PER_LONG)
-
+/**
+ * struct input_dev - represents an input device
+ * @name: name of the device
+ * @phys: physical path to the device in the system hierarchy
+ * @uniq: unique identification code for the device (if device has it)
+ * @id: id of the device (struct input_id)
+ * @evbit: bitmap of types of events supported by the device (EV_KEY,
+ * EV_REL, etc.)
+ * @keybit: bitmap of keys/buttons this device has
+ * @relbit: bitmap of relative axes for the device
+ * @absbit: bitmap of absolute axes for the device
+ * @mscbit: bitmap of miscellaneous events supported by the device
+ * @ledbit: bitmap of leds present on the device
+ * @sndbit: bitmap of sound effects supported by the device
+ * @ffbit: bitmap of force feedback effects supported by the device
+ * @swbit: bitmap of switches present on the device
+ * @keycodemax: size of keycode table
+ * @keycodesize: size of elements in keycode table
+ * @keycode: map of scancodes to keycodes for this device
+ * @setkeycode: optional method to alter current keymap, used to implement
+ * sparse keymaps. If not supplied default mechanism will be used
+ * @getkeycode: optional method to retrieve current keymap. If not supplied
+ * default mechanism will be used
+ * @ff: force feedback structure associated with the device if device
+ * supports force feedback effects
+ * @repeat_key: stores key code of the last key pressed; used to implement
+ * software autorepeat
+ * @timer: timer for software autorepeat
+ * @sync: set to 1 when there were no new events since last EV_SYNC
+ * @abs: current values for reports from absolute axes
+ * @rep: current values for autorepeat parameters (delay, rate)
+ * @key: reflects current state of device's keys/buttons
+ * @led: reflects current state of device's LEDs
+ * @snd: reflects current state of sound effects
+ * @sw: reflects current state of device's switches
+ * @absmax: maximum values for events coming from absolute axes
+ * @absmin: minimum values for events coming from absolute axes
+ * @absfuzz: describes noisiness for axes
+ * @absflat: size of the center flat position (used by joydev)
+ * @open: this method is called when the very first user calls
+ * input_open_device(). The driver must prepare the device
+ * to start generating events (start polling thread,
+ * request an IRQ, submit URB, etc.)
+ * @close: this method is called when the very last user calls
+ * input_close_device().
+ * @flush: purges the device. Most commonly used to get rid of force
+ * feedback effects loaded into the device when disconnecting
+ * from it
+ * @event: event handler for events sent _to_ the device, like EV_LED
+ * or EV_SND. The device is expected to carry out the requested
+ * action (turn on a LED, play sound, etc.) The call is protected
+ * by @event_lock and must not sleep
+ * @grab: input handle that currently has the device grabbed (via
+ * EVIOCGRAB ioctl). When a handle grabs a device it becomes sole
+ * recipient for all input events coming from the device
+ * @event_lock: this spinlock is is taken when input core receives
+ * and processes a new event for the device (in input_event()).
+ * Code that accesses and/or modifies parameters of a device
+ * (such as keymap or absmin, absmax, absfuzz, etc.) after device
+ * has been registered with input core must take this lock.
+ * @mutex: serializes calls to open(), close() and flush() methods
+ * @users: stores number of users (input handlers) that opened this
+ * device. It is used by input_open_device() and input_close_device()
+ * to make sure that dev->open() is only called when the first
+ * user opens device and dev->close() is called when the very
+ * last user closes the device
+ * @going_away: marks devices that are in a middle of unregistering and
+ * causes input_open_device*() fail with -ENODEV.
+ * @dev: driver model's view of this device
+ * @cdev: union for struct device pointer
+ * @h_list: list of input handles associated with the device. When
+ * accessing the list dev->mutex must be held
+ * @node: used to place the device onto input_dev_list
+ */
struct input_dev {
-
- void *private;
+ /* private: */
+ void *private; /* do not use */
+ /* public: */
const char *name;
const char *phys;
const char *uniq;
struct input_id id;
- unsigned long evbit[NBITS(EV_MAX)];
- unsigned long keybit[NBITS(KEY_MAX)];
- unsigned long relbit[NBITS(REL_MAX)];
- unsigned long absbit[NBITS(ABS_MAX)];
- unsigned long mscbit[NBITS(MSC_MAX)];
- unsigned long ledbit[NBITS(LED_MAX)];
- unsigned long sndbit[NBITS(SND_MAX)];
- unsigned long ffbit[NBITS(FF_MAX)];
- unsigned long swbit[NBITS(SW_MAX)];
+ unsigned long evbit[BITS_TO_LONGS(EV_CNT)];
+ unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];
+ unsigned long relbit[BITS_TO_LONGS(REL_CNT)];
+ unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];
+ unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];
+ unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];
+ unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];
+ unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];
+ unsigned long swbit[BITS_TO_LONGS(SW_CNT)];
unsigned int keycodemax;
unsigned int keycodesize;
@@ -966,17 +1049,15 @@ struct input_dev {
unsigned int repeat_key;
struct timer_list timer;
- int state;
-
int sync;
int abs[ABS_MAX + 1];
int rep[REP_MAX + 1];
- unsigned long key[NBITS(KEY_MAX)];
- unsigned long led[NBITS(LED_MAX)];
- unsigned long snd[NBITS(SND_MAX)];
- unsigned long sw[NBITS(SW_MAX)];
+ unsigned long key[BITS_TO_LONGS(KEY_CNT)];
+ unsigned long led[BITS_TO_LONGS(LED_CNT)];
+ unsigned long snd[BITS_TO_LONGS(SND_CNT)];
+ unsigned long sw[BITS_TO_LONGS(SW_CNT)];
int absmax[ABS_MAX + 1];
int absmin[ABS_MAX + 1];
@@ -990,8 +1071,11 @@ struct input_dev {
struct input_handle *grab;
- struct mutex mutex; /* serializes open and close operations */
+ spinlock_t event_lock;
+ struct mutex mutex;
+
unsigned int users;
+ int going_away;
struct device dev;
union { /* temporarily so while we switching to struct device */
@@ -1057,7 +1141,9 @@ struct input_handle;
/**
* struct input_handler - implements one of interfaces for input devices
* @private: driver-specific data
- * @event: event handler
+ * @event: event handler. This method is being called by input core with
+ * interrupts disabled and dev->event_lock spinlock held and so
+ * it may not sleep
* @connect: called when attaching a handler to an input device
* @disconnect: disconnects a handler from input device
* @start: starts handler for given handle. This function is called by
@@ -1069,10 +1155,18 @@ struct input_handle;
* @name: name of the handler, to be shown in /proc/bus/input/handlers
* @id_table: pointer to a table of input_device_ids this driver can
* handle
- * @blacklist: prointer to a table of input_device_ids this driver should
+ * @blacklist: pointer to a table of input_device_ids this driver should
* ignore even if they match @id_table
* @h_list: list of input handles associated with the handler
* @node: for placing the driver onto input_handler_list
+ *
+ * Input handlers attach to input devices and create input handles. There
+ * are likely several handlers attached to any given input device at the
+ * same time. All of them will get their copy of input event generated by
+ * the device.
+ *
+ * Note that input core serializes calls to connect() and disconnect()
+ * methods.
*/
struct input_handler {
@@ -1094,6 +1188,18 @@ struct input_handler {
struct list_head node;
};
+/**
+ * struct input_handle - links input device with an input handler
+ * @private: handler-specific data
+ * @open: counter showing whether the handle is 'open', i.e. should deliver
+ * events from its device
+ * @name: name given to the handle by handler that created it
+ * @dev: input device the handle is attached to
+ * @handler: handler that works with the device through this handle
+ * @d_node: used to put the handle on device's list of attached handles
+ * @h_node: used to put the handle on handler's list of handles from which
+ * it gets events
+ */
struct input_handle {
void *private;
@@ -1136,10 +1242,10 @@ static inline void input_set_drvdata(struct input_dev *dev, void *data)
dev->private = data;
}
-int input_register_device(struct input_dev *);
+int __must_check input_register_device(struct input_dev *);
void input_unregister_device(struct input_dev *);
-int input_register_handler(struct input_handler *);
+int __must_check input_register_handler(struct input_handler *);
void input_unregister_handler(struct input_handler *);
int input_register_handle(struct input_handle *);
@@ -1195,7 +1301,7 @@ static inline void input_set_abs_params(struct input_dev *dev, int axis, int min
dev->absfuzz[axis] = fuzz;
dev->absflat[axis] = flat;
- dev->absbit[LONG(axis)] |= BIT(axis);
+ dev->absbit[BIT_WORD(axis)] |= BIT_MASK(axis);
}
extern struct class input_class;
@@ -1216,7 +1322,7 @@ extern struct class input_class;
* @max_effects: maximum number of effects supported by device
* @effects: pointer to an array of effects currently loaded into device
* @effect_owners: array of effect owners; when file handle owning
- * an effect gets closed the effcet is automatically erased
+ * an effect gets closed the effect is automatically erased
*
* Every force-feedback device must implement upload() and playback()
* methods; erase() is optional. set_gain() and set_autocenter() need
@@ -1236,7 +1342,7 @@ struct ff_device {
void *private;
- unsigned long ffbit[NBITS(FF_MAX)];
+ unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];
struct mutex mutex;
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 5523f19d88d2..2306920fa388 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -55,28 +55,6 @@
#define IRQF_NOBALANCING 0x00000800
#define IRQF_IRQPOLL 0x00001000
-/*
- * Migration helpers. Scheduled for removal in 9/2007
- * Do not use for new code !
- */
-static inline
-unsigned long __deprecated deprecated_irq_flag(unsigned long flag)
-{
- return flag;
-}
-
-#define SA_INTERRUPT deprecated_irq_flag(IRQF_DISABLED)
-#define SA_SAMPLE_RANDOM deprecated_irq_flag(IRQF_SAMPLE_RANDOM)
-#define SA_SHIRQ deprecated_irq_flag(IRQF_SHARED)
-#define SA_PROBEIRQ deprecated_irq_flag(IRQF_PROBE_SHARED)
-#define SA_PERCPU deprecated_irq_flag(IRQF_PERCPU)
-
-#define SA_TRIGGER_LOW deprecated_irq_flag(IRQF_TRIGGER_LOW)
-#define SA_TRIGGER_HIGH deprecated_irq_flag(IRQF_TRIGGER_HIGH)
-#define SA_TRIGGER_FALLING deprecated_irq_flag(IRQF_TRIGGER_FALLING)
-#define SA_TRIGGER_RISING deprecated_irq_flag(IRQF_TRIGGER_RISING)
-#define SA_TRIGGER_MASK deprecated_irq_flag(IRQF_TRIGGER_MASK)
-
typedef irqreturn_t (*irq_handler_t)(int, void *);
struct irqaction {
@@ -205,6 +183,15 @@ static inline int disable_irq_wake(unsigned int irq)
enable_irq(irq)
# endif
+static inline int enable_irq_wake(unsigned int irq)
+{
+ return 0;
+}
+
+static inline int disable_irq_wake(unsigned int irq)
+{
+ return 0;
+}
#endif /* CONFIG_GENERIC_HARDIRQS */
#ifndef __ARCH_SET_SOFTIRQ_PENDING
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index 71ea92319241..6187a8567bc7 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -110,9 +110,6 @@ extern int allocate_resource(struct resource *root, struct resource *new,
int adjust_resource(struct resource *res, resource_size_t start,
resource_size_t size);
-/* get registered SYSTEM_RAM resources in specified area */
-extern int find_next_system_ram(struct resource *res);
-
/* Convenience shorthand with allocation */
#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name))
#define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name))
diff --git a/include/linux/ipc.h b/include/linux/ipc.h
index 3fd3ddd5f0d9..408696ea5189 100644
--- a/include/linux/ipc.h
+++ b/include/linux/ipc.h
@@ -49,6 +49,34 @@ struct ipc_perm
#define IPC_64 0x0100 /* New version (support 32-bit UIDs, bigger
message sizes, etc. */
+/*
+ * These are used to wrap system calls.
+ *
+ * See architecture code for ugly details..
+ */
+struct ipc_kludge {
+ struct msgbuf __user *msgp;
+ long msgtyp;
+};
+
+#define SEMOP 1
+#define SEMGET 2
+#define SEMCTL 3
+#define SEMTIMEDOP 4
+#define MSGSND 11
+#define MSGRCV 12
+#define MSGGET 13
+#define MSGCTL 14
+#define SHMAT 21
+#define SHMDT 22
+#define SHMGET 23
+#define SHMCTL 24
+
+/* Used by the DIPC package, try and avoid reusing it */
+#define DIPC 25
+
+#define IPCCALL(version,op) ((version)<<16 | (op))
+
#ifdef __KERNEL__
#include <linux/kref.h>
@@ -61,6 +89,7 @@ struct kern_ipc_perm
{
spinlock_t lock;
int deleted;
+ int id;
key_t key;
uid_t uid;
gid_t gid;
@@ -82,6 +111,8 @@ struct ipc_namespace {
int msg_ctlmax;
int msg_ctlmnb;
int msg_ctlmni;
+ atomic_t msg_bytes;
+ atomic_t msg_hdrs;
size_t shm_ctlmax;
size_t shm_ctlall;
diff --git a/include/linux/ipmi.h b/include/linux/ipmi.h
index 7a9db390c56a..c5bd28b69aec 100644
--- a/include/linux/ipmi.h
+++ b/include/linux/ipmi.h
@@ -365,6 +365,16 @@ int ipmi_request_supply_msgs(ipmi_user_t user,
int priority);
/*
+ * Poll the IPMI interface for the user. This causes the IPMI code to
+ * do an immediate check for information from the driver and handle
+ * anything that is immediately pending. This will not block in any
+ * way. This is useful if you need to implement polling from the user
+ * for things like modifying the watchdog timeout when a panic occurs
+ * or disabling the watchdog timer on a reboot.
+ */
+void ipmi_poll_interface(ipmi_user_t user);
+
+/*
* When commands come in to the SMS, the user can register to receive
* them. Only one user can be listening on a specific netfn/cmd/chan tuple
* at a time, you will get an EBUSY error if the command is already
diff --git a/include/linux/ipmi_smi.h b/include/linux/ipmi_smi.h
index c0633108d05d..6e8cec503380 100644
--- a/include/linux/ipmi_smi.h
+++ b/include/linux/ipmi_smi.h
@@ -118,7 +118,7 @@ struct ipmi_smi_handlers
/* Enable/disable firmware maintenance mode. Note that this
is *not* the modes defined, this is simply an on/off
setting. The message handler does the mode handling. Note
- that this is called from interupt context, so it cannot
+ that this is called from interrupt context, so it cannot
block. */
void (*set_maintenance_mode)(void *send_info, int enable);
@@ -148,26 +148,46 @@ struct ipmi_device_id {
/* Take a pointer to a raw data buffer and a length and extract device
id information from it. The first byte of data must point to the
- byte from the get device id response after the completion code.
- The caller is responsible for making sure the length is at least
- 11 and the command completed without error. */
-static inline void ipmi_demangle_device_id(unsigned char *data,
- unsigned int data_len,
- struct ipmi_device_id *id)
+ netfn << 2, the data should be of the format:
+ netfn << 2, cmd, completion code, data
+ as normally comes from a device interface. */
+static inline int ipmi_demangle_device_id(const unsigned char *data,
+ unsigned int data_len,
+ struct ipmi_device_id *id)
{
+ if (data_len < 9)
+ return -EINVAL;
+ if (data[0] != IPMI_NETFN_APP_RESPONSE << 2 ||
+ data[1] != IPMI_GET_DEVICE_ID_CMD)
+ /* Strange, didn't get the response we expected. */
+ return -EINVAL;
+ if (data[2] != 0)
+ /* That's odd, it shouldn't be able to fail. */
+ return -EINVAL;
+
+ data += 3;
+ data_len -= 3;
id->device_id = data[0];
id->device_revision = data[1];
id->firmware_revision_1 = data[2];
id->firmware_revision_2 = data[3];
id->ipmi_version = data[4];
id->additional_device_support = data[5];
- id->manufacturer_id = data[6] | (data[7] << 8) | (data[8] << 16);
- id->product_id = data[9] | (data[10] << 8);
+ if (data_len >= 11) {
+ id->manufacturer_id = (data[6] | (data[7] << 8) |
+ (data[8] << 16));
+ id->product_id = data[9] | (data[10] << 8);
+ } else {
+ id->manufacturer_id = 0;
+ id->product_id = 0;
+ }
if (data_len >= 15) {
memcpy(id->aux_firmware_revision, data+11, 4);
id->aux_firmware_revision_set = 1;
} else
id->aux_firmware_revision_set = 0;
+
+ return 0;
}
/* Add a low-level interface to the IPMI driver. Note that if the
diff --git a/include/linux/isdn.h b/include/linux/isdn.h
index ad09506554a3..d0ecc8eebfbf 100644
--- a/include/linux/isdn.h
+++ b/include/linux/isdn.h
@@ -167,6 +167,7 @@ typedef struct {
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/tcp.h>
+#include <linux/mutex.h>
#define ISDN_TTY_MAJOR 43
#define ISDN_TTYAUX_MAJOR 44
@@ -286,7 +287,6 @@ typedef struct {
/* Local interface-data */
typedef struct isdn_net_local_s {
ulong magic;
- char name[10]; /* Name of device */
struct net_device_stats stats; /* Ethernet Statistics */
int isdn_device; /* Index to isdn-device */
int isdn_channel; /* Index to isdn-channel */
@@ -617,7 +617,7 @@ typedef struct isdn_devt {
int v110emu[ISDN_MAX_CHANNELS]; /* V.110 emulator-mode 0=none */
atomic_t v110use[ISDN_MAX_CHANNELS]; /* Usage-Semaphore for stream */
isdn_v110_stream *v110[ISDN_MAX_CHANNELS]; /* V.110 private data */
- struct semaphore sem; /* serialize list access*/
+ struct mutex mtx; /* serialize list access*/
unsigned long global_features;
} isdn_dev;
diff --git a/include/linux/jbd.h b/include/linux/jbd.h
index 700a93b79189..16e7ed855a18 100644
--- a/include/linux/jbd.h
+++ b/include/linux/jbd.h
@@ -58,7 +58,7 @@
* CONFIG_JBD_DEBUG is on.
*/
#define JBD_EXPENSIVE_CHECKING
-extern int journal_enable_debug;
+extern u8 journal_enable_debug;
#define jbd_debug(n, f, a...) \
do { \
@@ -72,14 +72,15 @@ extern int journal_enable_debug;
#define jbd_debug(f, a...) /**/
#endif
-extern void * __jbd_kmalloc (const char *where, size_t size, gfp_t flags, int retry);
-extern void * jbd_slab_alloc(size_t size, gfp_t flags);
-extern void jbd_slab_free(void *ptr, size_t size);
+static inline void *jbd_alloc(size_t size, gfp_t flags)
+{
+ return (void *)__get_free_pages(flags, get_order(size));
+}
-#define jbd_kmalloc(size, flags) \
- __jbd_kmalloc(__FUNCTION__, (size), (flags), journal_oom_retry)
-#define jbd_rep_kmalloc(size, flags) \
- __jbd_kmalloc(__FUNCTION__, (size), (flags), 1)
+static inline void jbd_free(void *ptr, size_t size)
+{
+ free_pages((unsigned long)ptr, get_order(size));
+};
#define JFS_MIN_JOURNAL_BLOCKS 1024
@@ -247,17 +248,7 @@ typedef struct journal_superblock_s
#include <linux/fs.h>
#include <linux/sched.h>
-#define JBD_ASSERTIONS
-#ifdef JBD_ASSERTIONS
-#define J_ASSERT(assert) \
-do { \
- if (!(assert)) { \
- printk (KERN_EMERG \
- "Assertion failure in %s() at %s:%d: \"%s\"\n", \
- __FUNCTION__, __FILE__, __LINE__, # assert); \
- BUG(); \
- } \
-} while (0)
+#define J_ASSERT(assert) BUG_ON(!(assert))
#if defined(CONFIG_BUFFER_DEBUG)
void buffer_assertion_failure(struct buffer_head *bh);
@@ -273,10 +264,6 @@ void buffer_assertion_failure(struct buffer_head *bh);
#define J_ASSERT_JH(jh, expr) J_ASSERT(expr)
#endif
-#else
-#define J_ASSERT(assert) do { } while (0)
-#endif /* JBD_ASSERTIONS */
-
#if defined(JBD_PARANOID_IOFAIL)
#define J_EXPECT(expr, why...) J_ASSERT(expr)
#define J_EXPECT_BH(bh, expr, why...) J_ASSERT_BH(bh, expr)
@@ -372,6 +359,7 @@ struct jbd_revoke_table_s;
* @h_sync: flag for sync-on-close
* @h_jdata: flag to force data journaling
* @h_aborted: flag indicating fatal error on handle
+ * @h_lockdep_map: lockdep info for debugging lock problems
**/
/* Docbook can't yet cope with the bit fields, but will leave the documentation
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
index 260d6d76c5f3..06ef11457051 100644
--- a/include/linux/jbd2.h
+++ b/include/linux/jbd2.h
@@ -13,8 +13,8 @@
* filesystem journaling support.
*/
-#ifndef _LINUX_JBD_H
-#define _LINUX_JBD_H
+#ifndef _LINUX_JBD2_H
+#define _LINUX_JBD2_H
/* Allow this file to be included directly into e2fsprogs */
#ifndef __KERNEL__
@@ -37,26 +37,26 @@
#define journal_oom_retry 1
/*
- * Define JBD_PARANIOD_IOFAIL to cause a kernel BUG() if ext3 finds
+ * Define JBD2_PARANIOD_IOFAIL to cause a kernel BUG() if ext4 finds
* certain classes of error which can occur due to failed IOs. Under
- * normal use we want ext3 to continue after such errors, because
+ * normal use we want ext4 to continue after such errors, because
* hardware _can_ fail, but for debugging purposes when running tests on
* known-good hardware we may want to trap these errors.
*/
-#undef JBD_PARANOID_IOFAIL
+#undef JBD2_PARANOID_IOFAIL
/*
* The default maximum commit age, in seconds.
*/
-#define JBD_DEFAULT_MAX_COMMIT_AGE 5
+#define JBD2_DEFAULT_MAX_COMMIT_AGE 5
#ifdef CONFIG_JBD2_DEBUG
/*
- * Define JBD_EXPENSIVE_CHECKING to enable more expensive internal
+ * Define JBD2_EXPENSIVE_CHECKING to enable more expensive internal
* consistency checks. By default we don't do this unless
* CONFIG_JBD2_DEBUG is on.
*/
-#define JBD_EXPENSIVE_CHECKING
+#define JBD2_EXPENSIVE_CHECKING
extern u8 jbd2_journal_enable_debug;
#define jbd_debug(n, f, a...) \
@@ -71,14 +71,15 @@ extern u8 jbd2_journal_enable_debug;
#define jbd_debug(f, a...) /**/
#endif
-extern void * __jbd2_kmalloc (const char *where, size_t size, gfp_t flags, int retry);
-extern void * jbd2_slab_alloc(size_t size, gfp_t flags);
-extern void jbd2_slab_free(void *ptr, size_t size);
+static inline void *jbd2_alloc(size_t size, gfp_t flags)
+{
+ return (void *)__get_free_pages(flags, get_order(size));
+}
-#define jbd_kmalloc(size, flags) \
- __jbd2_kmalloc(__FUNCTION__, (size), (flags), journal_oom_retry)
-#define jbd_rep_kmalloc(size, flags) \
- __jbd2_kmalloc(__FUNCTION__, (size), (flags), 1)
+static inline void jbd2_free(void *ptr, size_t size)
+{
+ free_pages((unsigned long)ptr, get_order(size));
+};
#define JBD2_MIN_JOURNAL_BLOCKS 1024
@@ -162,8 +163,8 @@ typedef struct journal_block_tag_s
__be32 t_blocknr_high; /* most-significant high 32bits. */
} journal_block_tag_t;
-#define JBD_TAG_SIZE32 (offsetof(journal_block_tag_t, t_blocknr_high))
-#define JBD_TAG_SIZE64 (sizeof(journal_block_tag_t))
+#define JBD2_TAG_SIZE32 (offsetof(journal_block_tag_t, t_blocknr_high))
+#define JBD2_TAG_SIZE64 (sizeof(journal_block_tag_t))
/*
* The revoke descriptor: used on disk to describe a series of blocks to
@@ -255,8 +256,8 @@ typedef struct journal_superblock_s
#include <linux/fs.h>
#include <linux/sched.h>
-#define JBD_ASSERTIONS
-#ifdef JBD_ASSERTIONS
+#define JBD2_ASSERTIONS
+#ifdef JBD2_ASSERTIONS
#define J_ASSERT(assert) \
do { \
if (!(assert)) { \
@@ -283,9 +284,9 @@ void buffer_assertion_failure(struct buffer_head *bh);
#else
#define J_ASSERT(assert) do { } while (0)
-#endif /* JBD_ASSERTIONS */
+#endif /* JBD2_ASSERTIONS */
-#if defined(JBD_PARANOID_IOFAIL)
+#if defined(JBD2_PARANOID_IOFAIL)
#define J_EXPECT(expr, why...) J_ASSERT(expr)
#define J_EXPECT_BH(bh, expr, why...) J_ASSERT_BH(bh, expr)
#define J_EXPECT_JH(jh, expr, why...) J_ASSERT_JH(jh, expr)
@@ -959,12 +960,12 @@ void jbd2_journal_put_journal_head(struct journal_head *jh);
*/
extern struct kmem_cache *jbd2_handle_cache;
-static inline handle_t *jbd_alloc_handle(gfp_t gfp_flags)
+static inline handle_t *jbd2_alloc_handle(gfp_t gfp_flags)
{
return kmem_cache_alloc(jbd2_handle_cache, gfp_flags);
}
-static inline void jbd_free_handle(handle_t *handle)
+static inline void jbd2_free_handle(handle_t *handle)
{
kmem_cache_free(jbd2_handle_cache, handle);
}
@@ -1103,4 +1104,4 @@ extern int jbd_blocks_per_page(struct inode *inode);
#endif /* __KERNEL__ */
-#endif /* _LINUX_JBD_H */
+#endif /* _LINUX_JBD2_H */
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h
index e757a74b9d17..8b080024bbc1 100644
--- a/include/linux/jiffies.h
+++ b/include/linux/jiffies.h
@@ -148,6 +148,8 @@ static inline u64 get_jiffies_64(void)
*/
#define MAX_JIFFY_OFFSET ((LONG_MAX >> 1)-1)
+extern unsigned long preset_lpj;
+
/*
* We want to do realistic conversions of time so we need to use the same
* values the update wall clock code uses as the jiffies size. This value
diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h
index f73de6fb5c68..82de2fb62cb7 100644
--- a/include/linux/kallsyms.h
+++ b/include/linux/kallsyms.h
@@ -6,6 +6,7 @@
#define _LINUX_KALLSYMS_H
#include <linux/errno.h>
+#include <linux/stddef.h>
#define KSYM_NAME_LEN 128
#define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s]") + (KSYM_NAME_LEN - 1) + \
diff --git a/include/linux/kbd_diacr.h b/include/linux/kbd_diacr.h
index 1c1a3ff0535b..7274ec68c246 100644
--- a/include/linux/kbd_diacr.h
+++ b/include/linux/kbd_diacr.h
@@ -2,7 +2,7 @@
#define _DIACR_H
#include <linux/kd.h>
-extern struct kbdiacr accent_table[];
+extern struct kbdiacruc accent_table[];
extern unsigned int accent_table_size;
#endif /* _DIACR_H */
diff --git a/include/linux/kd.h b/include/linux/kd.h
index 28be4fbe9044..c91fc0c9c495 100644
--- a/include/linux/kd.h
+++ b/include/linux/kd.h
@@ -125,6 +125,16 @@ struct kbdiacrs {
#define KDGKBDIACR 0x4B4A /* read kernel accent table */
#define KDSKBDIACR 0x4B4B /* write kernel accent table */
+struct kbdiacruc {
+ __u32 diacr, base, result;
+};
+struct kbdiacrsuc {
+ unsigned int kb_cnt; /* number of entries in following array */
+ struct kbdiacruc kbdiacruc[256]; /* MAX_DIACR from keyboard.h */
+};
+#define KDGKBDIACRUC 0x4BFA /* read kernel accent table - UCS */
+#define KDSKBDIACRUC 0x4BFB /* write kernel accent table - UCS */
+
struct kbkeycode {
unsigned int scancode, keycode;
};
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index d9725a28a265..94bc99656963 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -35,6 +35,7 @@ extern const char linux_proc_banner[];
#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1)
#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
#define PTR_ALIGN(p, a) ((typeof(p))ALIGN((unsigned long)(p), (a)))
+#define IS_ALIGNED(x,a) (((x) % ((typeof(x))(a))) == 0)
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
@@ -75,6 +76,13 @@ extern const char linux_proc_banner[];
#define KERN_INFO "<6>" /* informational */
#define KERN_DEBUG "<7>" /* debug-level messages */
+/*
+ * Annotation for a "continued" line of log printout (only done after a
+ * line that had no enclosing \n). Only to be used by core/arch code
+ * during early bootup (a continued line is not SMP-safe otherwise).
+ */
+#define KERN_CONT ""
+
extern int console_printk[];
#define console_loglevel (console_printk[0])
@@ -171,6 +179,9 @@ asmlinkage int vprintk(const char *fmt, va_list args)
__attribute__ ((format (printf, 1, 0)));
asmlinkage int printk(const char * fmt, ...)
__attribute__ ((format (printf, 1, 2))) __cold;
+extern int log_buf_get_len(void);
+extern int log_buf_read(int idx);
+extern int log_buf_copy(char *dest, int idx, int len);
#else
static inline int vprintk(const char *s, va_list args)
__attribute__ ((format (printf, 1, 0)));
@@ -178,6 +189,9 @@ static inline int vprintk(const char *s, va_list args) { return 0; }
static inline int printk(const char *s, ...)
__attribute__ ((format (printf, 1, 2)));
static inline int __cold printk(const char *s, ...) { return 0; }
+static inline int log_buf_get_len(void) { return 0; }
+static inline int log_buf_read(int idx) { return 0; }
+static inline int log_buf_copy(char *dest, int idx, int len) { return 0; }
#endif
unsigned long int_sqrt(unsigned long);
@@ -244,10 +258,25 @@ extern void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
const void *buf, size_t len);
#define hex_asc(x) "0123456789abcdef"[x]
+#define pr_emerg(fmt, arg...) \
+ printk(KERN_EMERG fmt, ##arg)
+#define pr_alert(fmt, arg...) \
+ printk(KERN_ALERT fmt, ##arg)
+#define pr_crit(fmt, arg...) \
+ printk(KERN_CRIT fmt, ##arg)
+#define pr_err(fmt, arg...) \
+ printk(KERN_ERR fmt, ##arg)
+#define pr_warning(fmt, arg...) \
+ printk(KERN_WARNING fmt, ##arg)
+#define pr_notice(fmt, arg...) \
+ printk(KERN_NOTICE fmt, ##arg)
+#define pr_info(fmt, arg...) \
+ printk(KERN_INFO fmt, ##arg)
+
#ifdef DEBUG
/* If you are writing a driver, please use dev_dbg instead */
-#define pr_debug(fmt,arg...) \
- printk(KERN_DEBUG fmt,##arg)
+#define pr_debug(fmt, arg...) \
+ printk(KERN_DEBUG fmt, ##arg)
#else
static inline int __attribute__ ((format (printf, 1, 2))) pr_debug(const char * fmt, ...)
{
@@ -255,9 +284,6 @@ static inline int __attribute__ ((format (printf, 1, 2))) pr_debug(const char *
}
#endif
-#define pr_info(fmt,arg...) \
- printk(KERN_INFO fmt,##arg)
-
/*
* Display an IP address in readable format.
*/
diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h
index 12bf44f083f5..e8ffce898bf9 100644
--- a/include/linux/kernel_stat.h
+++ b/include/linux/kernel_stat.h
@@ -53,7 +53,9 @@ static inline int kstat_irqs(int irq)
}
extern void account_user_time(struct task_struct *, cputime_t);
+extern void account_user_time_scaled(struct task_struct *, cputime_t);
extern void account_system_time(struct task_struct *, int, cputime_t);
+extern void account_system_time_scaled(struct task_struct *, cputime_t);
extern void account_steal_time(struct task_struct *, cputime_t);
#endif /* _LINUX_KERNEL_STAT_H */
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index 8c2c7fcd58ce..2d9c448d8c52 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -121,6 +121,30 @@ extern struct page *kimage_alloc_control_pages(struct kimage *image,
extern void crash_kexec(struct pt_regs *);
int kexec_should_crash(struct task_struct *);
void crash_save_cpu(struct pt_regs *regs, int cpu);
+void crash_save_vmcoreinfo(void);
+void arch_crash_save_vmcoreinfo(void);
+void vmcoreinfo_append_str(const char *fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
+unsigned long paddr_vmcoreinfo_note(void);
+
+#define VMCOREINFO_SYMBOL(name) \
+ vmcoreinfo_append_str("SYMBOL(%s)=%lx\n", #name, (unsigned long)&name)
+#define VMCOREINFO_SIZE(name) \
+ vmcoreinfo_append_str("SIZE(%s)=%lu\n", #name, \
+ (unsigned long)sizeof(struct name))
+#define VMCOREINFO_TYPEDEF_SIZE(name) \
+ vmcoreinfo_append_str("SIZE(%s)=%lu\n", #name, \
+ (unsigned long)sizeof(name))
+#define VMCOREINFO_OFFSET(name, field) \
+ vmcoreinfo_append_str("OFFSET(%s.%s)=%lu\n", #name, #field, \
+ (unsigned long)&(((struct name *)0)->field))
+#define VMCOREINFO_LENGTH(name, value) \
+ vmcoreinfo_append_str("LENGTH(%s)=%lu\n", #name, (unsigned long)value)
+#define VMCOREINFO_NUMBER(name) \
+ vmcoreinfo_append_str("NUMBER(%s)=%ld\n", #name, (long)name)
+#define VMCOREINFO_CONFIG(name) \
+ vmcoreinfo_append_str("CONFIG_%s=y\n", #name)
+
extern struct kimage *kexec_image;
extern struct kimage *kexec_crash_image;
@@ -148,12 +172,23 @@ extern struct kimage *kexec_crash_image;
#define KEXEC_FLAGS (KEXEC_ON_CRASH) /* List of defined/legal kexec flags */
+#define VMCOREINFO_BYTES (4096)
+#define VMCOREINFO_NOTE_NAME "VMCOREINFO"
+#define VMCOREINFO_NOTE_NAME_BYTES ALIGN(sizeof(VMCOREINFO_NOTE_NAME), 4)
+#define VMCOREINFO_NOTE_SIZE (KEXEC_NOTE_HEAD_BYTES*2 + VMCOREINFO_BYTES \
+ + VMCOREINFO_NOTE_NAME_BYTES)
+
/* Location of a reserved region to hold the crash kernel.
*/
extern struct resource crashk_res;
typedef u32 note_buf_t[KEXEC_NOTE_BYTES/4];
extern note_buf_t *crash_notes;
+extern u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4];
+extern size_t vmcoreinfo_size;
+extern size_t vmcoreinfo_max_size;
+int __init parse_crashkernel(char *cmdline, unsigned long long system_ram,
+ unsigned long long *crash_size, unsigned long long *crash_base);
#else /* !CONFIG_KEXEC */
struct pt_regs;
diff --git a/include/linux/key-type.h b/include/linux/key-type.h
new file mode 100644
index 000000000000..65833d4d5998
--- /dev/null
+++ b/include/linux/key-type.h
@@ -0,0 +1,112 @@
+/* Definitions for key type implementations
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _LINUX_KEY_TYPE_H
+#define _LINUX_KEY_TYPE_H
+
+#include <linux/key.h>
+
+#ifdef CONFIG_KEYS
+
+/*
+ * key under-construction record
+ * - passed to the request_key actor if supplied
+ */
+struct key_construction {
+ struct key *key; /* key being constructed */
+ struct key *authkey;/* authorisation for key being constructed */
+};
+
+typedef int (*request_key_actor_t)(struct key_construction *key,
+ const char *op, void *aux);
+
+/*
+ * kernel managed key type definition
+ */
+struct key_type {
+ /* name of the type */
+ const char *name;
+
+ /* default payload length for quota precalculation (optional)
+ * - this can be used instead of calling key_payload_reserve(), that
+ * function only needs to be called if the real datalen is different
+ */
+ size_t def_datalen;
+
+ /* instantiate a key of this type
+ * - this method should call key_payload_reserve() to determine if the
+ * user's quota will hold the payload
+ */
+ int (*instantiate)(struct key *key, const void *data, size_t datalen);
+
+ /* update a key of this type (optional)
+ * - this method should call key_payload_reserve() to recalculate the
+ * quota consumption
+ * - the key must be locked against read when modifying
+ */
+ int (*update)(struct key *key, const void *data, size_t datalen);
+
+ /* match a key against a description */
+ int (*match)(const struct key *key, const void *desc);
+
+ /* clear some of the data from a key on revokation (optional)
+ * - the key's semaphore will be write-locked by the caller
+ */
+ void (*revoke)(struct key *key);
+
+ /* clear the data from a key (optional) */
+ void (*destroy)(struct key *key);
+
+ /* describe a key */
+ void (*describe)(const struct key *key, struct seq_file *p);
+
+ /* read a key's data (optional)
+ * - permission checks will be done by the caller
+ * - the key's semaphore will be readlocked by the caller
+ * - should return the amount of data that could be read, no matter how
+ * much is copied into the buffer
+ * - shouldn't do the copy if the buffer is NULL
+ */
+ long (*read)(const struct key *key, char __user *buffer, size_t buflen);
+
+ /* handle request_key() for this type instead of invoking
+ * /sbin/request-key (optional)
+ * - key is the key to instantiate
+ * - authkey is the authority to assume when instantiating this key
+ * - op is the operation to be done, usually "create"
+ * - the call must not return until the instantiation process has run
+ * its course
+ */
+ request_key_actor_t request_key;
+
+ /* internal fields */
+ struct list_head link; /* link in types list */
+};
+
+extern struct key_type key_type_keyring;
+
+extern int register_key_type(struct key_type *ktype);
+extern void unregister_key_type(struct key_type *ktype);
+
+extern int key_payload_reserve(struct key *key, size_t datalen);
+extern int key_instantiate_and_link(struct key *key,
+ const void *data,
+ size_t datalen,
+ struct key *keyring,
+ struct key *instkey);
+extern int key_negate_and_link(struct key *key,
+ unsigned timeout,
+ struct key *keyring,
+ struct key *instkey);
+extern void complete_request_key(struct key_construction *cons, int error);
+
+#endif /* CONFIG_KEYS */
+#endif /* _LINUX_KEY_TYPE_H */
diff --git a/include/linux/key.h b/include/linux/key.h
index a9220e75782e..fcdbd5ed227b 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -1,6 +1,6 @@
-/* key.h: authentication token and access key management
+/* Authentication token and access key management
*
- * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2004, 2007 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
@@ -175,78 +175,6 @@ struct key {
} payload;
};
-/*****************************************************************************/
-/*
- * kernel managed key type definition
- */
-typedef int (*request_key_actor_t)(struct key *key, struct key *authkey,
- const char *op, void *aux);
-
-struct key_type {
- /* name of the type */
- const char *name;
-
- /* default payload length for quota precalculation (optional)
- * - this can be used instead of calling key_payload_reserve(), that
- * function only needs to be called if the real datalen is different
- */
- size_t def_datalen;
-
- /* instantiate a key of this type
- * - this method should call key_payload_reserve() to determine if the
- * user's quota will hold the payload
- */
- int (*instantiate)(struct key *key, const void *data, size_t datalen);
-
- /* update a key of this type (optional)
- * - this method should call key_payload_reserve() to recalculate the
- * quota consumption
- * - the key must be locked against read when modifying
- */
- int (*update)(struct key *key, const void *data, size_t datalen);
-
- /* match a key against a description */
- int (*match)(const struct key *key, const void *desc);
-
- /* clear some of the data from a key on revokation (optional)
- * - the key's semaphore will be write-locked by the caller
- */
- void (*revoke)(struct key *key);
-
- /* clear the data from a key (optional) */
- void (*destroy)(struct key *key);
-
- /* describe a key */
- void (*describe)(const struct key *key, struct seq_file *p);
-
- /* read a key's data (optional)
- * - permission checks will be done by the caller
- * - the key's semaphore will be readlocked by the caller
- * - should return the amount of data that could be read, no matter how
- * much is copied into the buffer
- * - shouldn't do the copy if the buffer is NULL
- */
- long (*read)(const struct key *key, char __user *buffer, size_t buflen);
-
- /* handle request_key() for this type instead of invoking
- * /sbin/request-key (optional)
- * - key is the key to instantiate
- * - authkey is the authority to assume when instantiating this key
- * - op is the operation to be done, usually "create"
- * - the call must not return until the instantiation process has run
- * its course
- */
- request_key_actor_t request_key;
-
- /* internal fields */
- struct list_head link; /* link in types list */
-};
-
-extern struct key_type key_type_keyring;
-
-extern int register_key_type(struct key_type *ktype);
-extern void unregister_key_type(struct key_type *ktype);
-
extern struct key *key_alloc(struct key_type *type,
const char *desc,
uid_t uid, gid_t gid,
@@ -259,16 +187,6 @@ extern struct key *key_alloc(struct key_type *type,
#define KEY_ALLOC_QUOTA_OVERRUN 0x0001 /* add to quota, permit even if overrun */
#define KEY_ALLOC_NOT_IN_QUOTA 0x0002 /* not in quota */
-extern int key_payload_reserve(struct key *key, size_t datalen);
-extern int key_instantiate_and_link(struct key *key,
- const void *data,
- size_t datalen,
- struct key *keyring,
- struct key *instkey);
-extern int key_negate_and_link(struct key *key,
- unsigned timeout,
- struct key *keyring,
- struct key *instkey);
extern void key_revoke(struct key *key);
extern void key_put(struct key *key);
@@ -293,6 +211,17 @@ extern struct key *request_key_with_auxdata(struct key_type *type,
const char *callout_info,
void *aux);
+extern struct key *request_key_async(struct key_type *type,
+ const char *description,
+ const char *callout_info);
+
+extern struct key *request_key_async_with_auxdata(struct key_type *type,
+ const char *description,
+ const char *callout_info,
+ void *aux);
+
+extern int wait_for_key_construction(struct key *key, bool intr);
+
extern int key_validate(struct key *key);
extern key_ref_t key_create_or_update(key_ref_t keyring,
@@ -328,8 +257,6 @@ extern int keyring_add_key(struct key *keyring,
extern struct key *key_lookup(key_serial_t id);
-extern void keyring_replace_payload(struct key *key, void *replacement);
-
#define key_serial(key) ((key) ? (key)->serial : 0)
/*
diff --git a/include/linux/keyboard.h b/include/linux/keyboard.h
index 7ddbc30aa8e7..65c2d70853e9 100644
--- a/include/linux/keyboard.h
+++ b/include/linux/keyboard.h
@@ -23,10 +23,21 @@
#define MAX_NR_OF_USER_KEYMAPS 256 /* should be at least 7 */
#ifdef __KERNEL__
+struct notifier_block;
extern const int NR_TYPES;
extern const int max_vals[];
extern unsigned short *key_maps[MAX_NR_KEYMAPS];
extern unsigned short plain_map[NR_KEYS];
+
+struct keyboard_notifier_param {
+ struct vc_data *vc; /* VC on which the keyboard press was done */
+ int down; /* Pressure of the key? */
+ int shift; /* Current shift mask */
+ unsigned int value; /* keycode, unicode value or keysym */
+};
+
+extern int register_keyboard_notifier(struct notifier_block *nb);
+extern int unregister_keyboard_notifier(struct notifier_block *nb);
#endif
#define MAX_NR_FUNC 256 /* max nr of strings assigned to keys */
@@ -416,6 +427,7 @@ extern unsigned short plain_map[NR_KEYS];
#define K_SHIFTRLOCK K(KT_LOCK,KG_SHIFTR)
#define K_CTRLLLOCK K(KT_LOCK,KG_CTRLL)
#define K_CTRLRLOCK K(KT_LOCK,KG_CTRLR)
+#define K_CAPSSHIFTLOCK K(KT_LOCK,KG_CAPSSHIFT)
#define K_SHIFT_SLOCK K(KT_SLOCK,KG_SHIFT)
#define K_CTRL_SLOCK K(KT_SLOCK,KG_CTRL)
@@ -425,8 +437,9 @@ extern unsigned short plain_map[NR_KEYS];
#define K_SHIFTR_SLOCK K(KT_SLOCK,KG_SHIFTR)
#define K_CTRLL_SLOCK K(KT_SLOCK,KG_CTRLL)
#define K_CTRLR_SLOCK K(KT_SLOCK,KG_CTRLR)
+#define K_CAPSSHIFT_SLOCK K(KT_SLOCK,KG_CAPSSHIFT)
-#define NR_LOCK 8
+#define NR_LOCK 9
#define K_BRL_BLANK K(KT_BRL, 0)
#define K_BRL_DOT1 K(KT_BRL, 1)
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 51464d12a4e5..81891581e89b 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -166,6 +166,12 @@ struct kretprobe_instance {
struct task_struct *task;
};
+struct kretprobe_blackpoint {
+ const char *name;
+ void *addr;
+};
+extern struct kretprobe_blackpoint kretprobe_blacklist[];
+
static inline void kretprobe_assert(struct kretprobe_instance *ri,
unsigned long orig_ret_address, unsigned long trampoline_address)
{
diff --git a/include/linux/lguest.h b/include/linux/lguest.h
index 157ad64aa7ce..175e63f4a8c0 100644
--- a/include/linux/lguest.h
+++ b/include/linux/lguest.h
@@ -1,79 +1,19 @@
/* Things the lguest guest needs to know. Note: like all lguest interfaces,
* this is subject to wild and random change between versions. */
-#ifndef _ASM_LGUEST_H
-#define _ASM_LGUEST_H
+#ifndef _LINUX_LGUEST_H
+#define _LINUX_LGUEST_H
#ifndef __ASSEMBLY__
+#include <linux/time.h>
#include <asm/irq.h>
-
-#define LHCALL_FLUSH_ASYNC 0
-#define LHCALL_LGUEST_INIT 1
-#define LHCALL_CRASH 2
-#define LHCALL_LOAD_GDT 3
-#define LHCALL_NEW_PGTABLE 4
-#define LHCALL_FLUSH_TLB 5
-#define LHCALL_LOAD_IDT_ENTRY 6
-#define LHCALL_SET_STACK 7
-#define LHCALL_TS 8
-#define LHCALL_SET_CLOCKEVENT 9
-#define LHCALL_HALT 10
-#define LHCALL_BIND_DMA 12
-#define LHCALL_SEND_DMA 13
-#define LHCALL_SET_PTE 14
-#define LHCALL_SET_PMD 15
-#define LHCALL_LOAD_TLS 16
+#include <asm/lguest_hcall.h>
#define LG_CLOCK_MIN_DELTA 100UL
#define LG_CLOCK_MAX_DELTA ULONG_MAX
-/*G:031 First, how does our Guest contact the Host to ask for privileged
- * operations? There are two ways: the direct way is to make a "hypercall",
- * to make requests of the Host Itself.
- *
- * Our hypercall mechanism uses the highest unused trap code (traps 32 and
- * above are used by real hardware interrupts). Seventeen hypercalls are
- * available: the hypercall number is put in the %eax register, and the
- * arguments (when required) are placed in %edx, %ebx and %ecx. If a return
- * value makes sense, it's returned in %eax.
- *
- * Grossly invalid calls result in Sudden Death at the hands of the vengeful
- * Host, rather than returning failure. This reflects Winston Churchill's
- * definition of a gentleman: "someone who is only rude intentionally". */
-#define LGUEST_TRAP_ENTRY 0x1F
-
-static inline unsigned long
-hcall(unsigned long call,
- unsigned long arg1, unsigned long arg2, unsigned long arg3)
-{
- /* "int" is the Intel instruction to trigger a trap. */
- asm volatile("int $" __stringify(LGUEST_TRAP_ENTRY)
- /* The call is in %eax (aka "a"), and can be replaced */
- : "=a"(call)
- /* The other arguments are in %eax, %edx, %ebx & %ecx */
- : "a"(call), "d"(arg1), "b"(arg2), "c"(arg3)
- /* "memory" means this might write somewhere in memory.
- * This isn't true for all calls, but it's safe to tell
- * gcc that it might happen so it doesn't get clever. */
- : "memory");
- return call;
-}
-/*:*/
-
-void async_hcall(unsigned long call,
- unsigned long arg1, unsigned long arg2, unsigned long arg3);
-
-/* Can't use our min() macro here: needs to be a constant */
-#define LGUEST_IRQS (NR_IRQS < 32 ? NR_IRQS: 32)
-
-#define LHCALL_RING_SIZE 64
-struct hcall_ring
-{
- u32 eax, edx, ebx, ecx;
-};
-
/*G:032 The second method of communicating with the Host is to via "struct
- * lguest_data". The Guest's very first hypercall is to tell the Host where
- * this is, and then the Guest and Host both publish information in it. :*/
+ * lguest_data". Once the Guest's initialization hypercall tells the Host where
+ * this is, the Guest and Host both publish information in it. :*/
struct lguest_data
{
/* 512 == enabled (same as eflags in normal hardware). The Guest
@@ -97,20 +37,24 @@ struct lguest_data
/* 0xFF == done (set by Host), 0 == pending (set by Guest). */
u8 hcall_status[LHCALL_RING_SIZE];
/* The actual registers for the hypercalls. */
- struct hcall_ring hcalls[LHCALL_RING_SIZE];
+ struct hcall_args hcalls[LHCALL_RING_SIZE];
/* Fields initialized by the Host at boot: */
/* Memory not to try to access */
unsigned long reserve_mem;
- /* ID of this Guest (used by network driver to set ethernet address) */
- u16 guestid;
/* KHz for the TSC clock. */
u32 tsc_khz;
+ /* Page where the top-level pagetable is */
+ unsigned long pgdir;
/* Fields initialized by the Guest at boot: */
/* Instruction range to suppress interrupts even if enabled */
unsigned long noirq_start, noirq_end;
+ /* Address above which page tables are all identical. */
+ unsigned long kernel_address;
+ /* The vector to try to use for system calls (0x40 or 0x80). */
+ unsigned int syscall_vec;
};
extern struct lguest_data lguest_data;
#endif /* __ASSEMBLY__ */
-#endif /* _ASM_LGUEST_H */
+#endif /* _LINUX_LGUEST_H */
diff --git a/include/linux/lguest_bus.h b/include/linux/lguest_bus.h
deleted file mode 100644
index d27853ddc644..000000000000
--- a/include/linux/lguest_bus.h
+++ /dev/null
@@ -1,51 +0,0 @@
-#ifndef _ASM_LGUEST_DEVICE_H
-#define _ASM_LGUEST_DEVICE_H
-/* Everything you need to know about lguest devices. */
-#include <linux/device.h>
-#include <linux/lguest.h>
-#include <linux/lguest_launcher.h>
-
-struct lguest_device {
- /* Unique busid, and index into lguest_page->devices[] */
- unsigned int index;
-
- struct device dev;
-
- /* Driver can hang data off here. */
- void *private;
-};
-
-/*D:380 Since interrupt numbers are arbitrary, we use a convention: each device
- * can use the interrupt number corresponding to its index. The +1 is because
- * interrupt 0 is not usable (it's actually the timer interrupt). */
-static inline int lgdev_irq(const struct lguest_device *dev)
-{
- return dev->index + 1;
-}
-/*:*/
-
-/* dma args must not be vmalloced! */
-void lguest_send_dma(unsigned long key, struct lguest_dma *dma);
-int lguest_bind_dma(unsigned long key, struct lguest_dma *dmas,
- unsigned int num, u8 irq);
-void lguest_unbind_dma(unsigned long key, struct lguest_dma *dmas);
-
-/* Map the virtual device space */
-void *lguest_map(unsigned long phys_addr, unsigned long pages);
-void lguest_unmap(void *);
-
-struct lguest_driver {
- const char *name;
- struct module *owner;
- u16 device_type;
- int (*probe)(struct lguest_device *dev);
- void (*remove)(struct lguest_device *dev);
-
- struct device_driver drv;
-};
-
-extern int register_lguest_driver(struct lguest_driver *drv);
-extern void unregister_lguest_driver(struct lguest_driver *drv);
-
-extern struct lguest_device_desc *lguest_devices; /* Just past max_pfn */
-#endif /* _ASM_LGUEST_DEVICE_H */
diff --git a/include/linux/lguest_launcher.h b/include/linux/lguest_launcher.h
index 641670579446..697104da91f1 100644
--- a/include/linux/lguest_launcher.h
+++ b/include/linux/lguest_launcher.h
@@ -1,76 +1,7 @@
-#ifndef _ASM_LGUEST_USER
-#define _ASM_LGUEST_USER
+#ifndef _LINUX_LGUEST_LAUNCHER
+#define _LINUX_LGUEST_LAUNCHER
/* Everything the "lguest" userspace program needs to know. */
-/* They can register up to 32 arrays of lguest_dma. */
-#define LGUEST_MAX_DMA 32
-/* At most we can dma 16 lguest_dma in one op. */
-#define LGUEST_MAX_DMA_SECTIONS 16
-
-/* How many devices? Assume each one wants up to two dma arrays per device. */
-#define LGUEST_MAX_DEVICES (LGUEST_MAX_DMA/2)
-
-/*D:200
- * Lguest I/O
- *
- * The lguest I/O mechanism is the only way Guests can talk to devices. There
- * are two hypercalls involved: SEND_DMA for output and BIND_DMA for input. In
- * each case, "struct lguest_dma" describes the buffer: this contains 16
- * addr/len pairs, and if there are fewer buffer elements the len array is
- * terminated with a 0.
- *
- * I/O is organized by keys: BIND_DMA attaches buffers to a particular key, and
- * SEND_DMA transfers to buffers bound to particular key. By convention, keys
- * correspond to a physical address within the device's page. This means that
- * devices will never accidentally end up with the same keys, and allows the
- * Host use The Futex Trick (as we'll see later in our journey).
- *
- * SEND_DMA simply indicates a key to send to, and the physical address of the
- * "struct lguest_dma" to send. The Host will write the number of bytes
- * transferred into the "struct lguest_dma"'s used_len member.
- *
- * BIND_DMA indicates a key to bind to, a pointer to an array of "struct
- * lguest_dma"s ready for receiving, the size of that array, and an interrupt
- * to trigger when data is received. The Host will only allow transfers into
- * buffers with a used_len of zero: it then sets used_len to the number of
- * bytes transferred and triggers the interrupt for the Guest to process the
- * new input. */
-struct lguest_dma
-{
- /* 0 if free to be used, filled by the Host. */
- u32 used_len;
- unsigned long addr[LGUEST_MAX_DMA_SECTIONS];
- u16 len[LGUEST_MAX_DMA_SECTIONS];
-};
-/*:*/
-
-/*D:460 This is the layout of a block device memory page. The Launcher sets up
- * the num_sectors initially to tell the Guest the size of the disk. The Guest
- * puts the type, sector and length of the request in the first three fields,
- * then DMAs to the Host. The Host processes the request, sets up the result,
- * then DMAs back to the Guest. */
-struct lguest_block_page
-{
- /* 0 is a read, 1 is a write. */
- int type;
- u32 sector; /* Offset in device = sector * 512. */
- u32 bytes; /* Length expected to be read/written in bytes */
- /* 0 = pending, 1 = done, 2 = done, error */
- int result;
- u32 num_sectors; /* Disk length = num_sectors * 512 */
-};
-
-/*D:520 The network device is basically a memory page where all the Guests on
- * the network publish their MAC (ethernet) addresses: it's an array of "struct
- * lguest_net": */
-struct lguest_net
-{
- /* Simply the mac address (with multicast bit meaning promisc). */
- unsigned char mac[6];
-};
-/*:*/
-
-/* Where the Host expects the Guest to SEND_DMA console output to. */
-#define LGUEST_CONSOLE_DMA_KEY 0
+#include <linux/types.h>
/*D:010
* Drivers
@@ -79,49 +10,44 @@ struct lguest_net
* real devices (think of the damage it could do!) we provide virtual devices.
* We could emulate a PCI bus with various devices on it, but that is a fairly
* complex burden for the Host and suboptimal for the Guest, so we have our own
- * "lguest" bus and simple drivers.
+ * simple lguest bus and we use "virtio" drivers. These drivers need a set of
+ * routines from us which will actually do the virtual I/O, but they handle all
+ * the net/block/console stuff themselves. This means that if we want to add
+ * a new device, we simply need to write a new virtio driver and create support
+ * for it in the Launcher: this code won't need to change.
*
- * Devices are described by an array of LGUEST_MAX_DEVICES of these structs,
- * placed by the Launcher just above the top of physical memory:
+ * Devices are described by a simplified ID, a status byte, and some "config"
+ * bytes which describe this device's configuration. This is placed by the
+ * Launcher just above the top of physical memory:
*/
struct lguest_device_desc {
- /* The device type: console, network, disk etc. */
- u16 type;
-#define LGUEST_DEVICE_T_CONSOLE 1
-#define LGUEST_DEVICE_T_NET 2
-#define LGUEST_DEVICE_T_BLOCK 3
-
- /* The specific features of this device: these depends on device type
- * except for LGUEST_DEVICE_F_RANDOMNESS. */
- u16 features;
-#define LGUEST_NET_F_NOCSUM 0x4000 /* Don't bother checksumming */
-#define LGUEST_DEVICE_F_RANDOMNESS 0x8000 /* IRQ is fairly random */
-
- /* This is how the Guest reports status of the device: the Host can set
- * LGUEST_DEVICE_S_REMOVED to indicate removal, but the rest are only
- * ever manipulated by the Guest, and only ever set. */
- u16 status;
-/* 256 and above are device specific. */
-#define LGUEST_DEVICE_S_ACKNOWLEDGE 1 /* We have seen device. */
-#define LGUEST_DEVICE_S_DRIVER 2 /* We have found a driver */
-#define LGUEST_DEVICE_S_DRIVER_OK 4 /* Driver says OK! */
-#define LGUEST_DEVICE_S_REMOVED 8 /* Device has gone away. */
-#define LGUEST_DEVICE_S_REMOVED_ACK 16 /* Driver has been told. */
-#define LGUEST_DEVICE_S_FAILED 128 /* Something actually failed */
+ /* The device type: console, network, disk etc. Type 0 terminates. */
+ __u8 type;
+ /* The number of bytes of the config array. */
+ __u8 config_len;
+ /* A status byte, written by the Guest. */
+ __u8 status;
+ __u8 config[0];
+};
- /* Each device exists somewhere in Guest physical memory, over some
- * number of pages. */
- u16 num_pages;
- u32 pfn;
+/*D:135 This is how we expect the device configuration field for a virtqueue
+ * (type VIRTIO_CONFIG_F_VIRTQUEUE) to be laid out: */
+struct lguest_vqconfig {
+ /* The number of entries in the virtio_ring */
+ __u16 num;
+ /* The interrupt we get when something happens. */
+ __u16 irq;
+ /* The page number of the virtio ring for this device. */
+ __u32 pfn;
};
/*:*/
/* Write command first word is a request. */
enum lguest_req
{
- LHREQ_INITIALIZE, /* + pfnlimit, pgdir, start, pageoffset */
- LHREQ_GETDMA, /* + addr (returns &lguest_dma, irq in ->used_len) */
+ LHREQ_INITIALIZE, /* + base, pfnlimit, pgdir, start */
+ LHREQ_GETDMA, /* No longer used */
LHREQ_IRQ, /* + irq */
LHREQ_BREAK, /* + on/off flag (on blocks until someone does off) */
};
-#endif /* _ASM_LGUEST_USER */
+#endif /* _LINUX_LGUEST_LAUNCHER */
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 229a9ff9f924..56a5673aebad 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -29,7 +29,7 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
-#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
#include <linux/io.h>
#include <linux/ata.h>
#include <linux/workqueue.h>
@@ -133,11 +133,14 @@ enum {
ATA_DFLAG_ACPI_PENDING = (1 << 5), /* ACPI resume action pending */
ATA_DFLAG_ACPI_FAILED = (1 << 6), /* ACPI on devcfg has failed */
ATA_DFLAG_AN = (1 << 7), /* AN configured */
+ ATA_DFLAG_HIPM = (1 << 8), /* device supports HIPM */
+ ATA_DFLAG_DIPM = (1 << 9), /* device supports DIPM */
ATA_DFLAG_CFG_MASK = (1 << 12) - 1,
ATA_DFLAG_PIO = (1 << 12), /* device limited to PIO mode */
ATA_DFLAG_NCQ_OFF = (1 << 13), /* device limited to non-NCQ mode */
ATA_DFLAG_SPUNDOWN = (1 << 14), /* XXX: for spindown_compat */
+ ATA_DFLAG_SLEEPING = (1 << 15), /* device is sleeping */
ATA_DFLAG_INIT_MASK = (1 << 16) - 1,
ATA_DFLAG_DETACH = (1 << 16),
@@ -185,6 +188,7 @@ enum {
ATA_FLAG_ACPI_SATA = (1 << 17), /* need native SATA ACPI layout */
ATA_FLAG_AN = (1 << 18), /* controller supports AN */
ATA_FLAG_PMP = (1 << 19), /* controller supports PMP */
+ ATA_FLAG_IPM = (1 << 20), /* driver can handle IPM */
/* The following flag belongs to ap->pflags but is kept in
* ap->flags because it's referenced in many LLDs and will be
@@ -217,6 +221,7 @@ enum {
ATA_QCFLAG_IO = (1 << 3), /* standard IO command */
ATA_QCFLAG_RESULT_TF = (1 << 4), /* result TF requested */
ATA_QCFLAG_CLEAR_EXCL = (1 << 5), /* clear excl_link on completion */
+ ATA_QCFLAG_QUIET = (1 << 6), /* don't report device error */
ATA_QCFLAG_FAILED = (1 << 16), /* cmd failed and is owned by EH */
ATA_QCFLAG_SENSE_VALID = (1 << 17), /* sense data valid */
@@ -234,6 +239,13 @@ enum {
ATA_TMOUT_INTERNAL = 30 * HZ,
ATA_TMOUT_INTERNAL_QUICK = 5 * HZ,
+ /* FIXME: GoVault needs 2s but we can't afford that without
+ * parallel probing. 800ms is enough for iVDR disk
+ * HHD424020F7SV00. Increase to 2secs when parallel probing
+ * is in place.
+ */
+ ATA_TMOUT_FF_WAIT = 4 * HZ / 5,
+
/* ATA bus states */
BUS_UNKNOWN = 0,
BUS_DMA = 1,
@@ -294,6 +306,7 @@ enum {
ATA_EHI_RESUME_LINK = (1 << 1), /* resume link (reset modifier) */
ATA_EHI_NO_AUTOPSY = (1 << 2), /* no autopsy */
ATA_EHI_QUIET = (1 << 3), /* be quiet */
+ ATA_EHI_LPM = (1 << 4), /* link power management action */
ATA_EHI_DID_SOFTRESET = (1 << 16), /* already soft-reset this port */
ATA_EHI_DID_HARDRESET = (1 << 17), /* already soft-reset this port */
@@ -325,8 +338,10 @@ enum {
ATA_HORKAGE_BROKEN_HPA = (1 << 4), /* Broken HPA */
ATA_HORKAGE_SKIP_PM = (1 << 5), /* Skip PM operations */
ATA_HORKAGE_HPA_SIZE = (1 << 6), /* native size off by one */
+ ATA_HORKAGE_IPM = (1 << 7), /* Link PM problems */
+ ATA_HORKAGE_IVB = (1 << 8), /* cbl det validity bit bugs */
- /* DMA mask for user DMA control: User visible values; DO NOT
+ /* DMA mask for user DMA control: User visible values; DO NOT
renumber */
ATA_DMA_MASK_ATA = (1 << 0), /* DMA on ATA Disk */
ATA_DMA_MASK_ATAPI = (1 << 1), /* DMA on ATAPI */
@@ -370,6 +385,18 @@ typedef int (*ata_reset_fn_t)(struct ata_link *link, unsigned int *classes,
unsigned long deadline);
typedef void (*ata_postreset_fn_t)(struct ata_link *link, unsigned int *classes);
+/*
+ * host pm policy: If you alter this, you also need to alter libata-scsi.c
+ * (for the ascii descriptions)
+ */
+enum link_pm {
+ NOT_AVAILABLE,
+ MIN_POWER,
+ MAX_PERFORMANCE,
+ MEDIUM_POWER,
+};
+extern struct class_device_attribute class_device_attr_link_power_management_policy;
+
struct ata_ioports {
void __iomem *cmd_addr;
void __iomem *data_addr;
@@ -416,6 +443,7 @@ struct ata_queued_cmd {
unsigned long flags; /* ATA_QCFLAG_xxx */
unsigned int tag;
unsigned int n_elem;
+ unsigned int n_iter;
unsigned int orig_n_elem;
int dma_dir;
@@ -426,7 +454,7 @@ struct ata_queued_cmd {
unsigned int nbytes;
unsigned int curbytes;
- unsigned int cursg;
+ struct scatterlist *cursg;
unsigned int cursg_ofs;
struct scatterlist sgent;
@@ -615,6 +643,7 @@ struct ata_port {
pm_message_t pm_mesg;
int *pm_result;
+ enum link_pm pm_policy;
struct timer_list fastdrain_timer;
unsigned long fastdrain_cnt;
@@ -682,7 +711,8 @@ struct ata_port_operations {
int (*port_suspend) (struct ata_port *ap, pm_message_t mesg);
int (*port_resume) (struct ata_port *ap);
-
+ int (*enable_pm) (struct ata_port *ap, enum link_pm policy);
+ void (*disable_pm) (struct ata_port *ap);
int (*port_start) (struct ata_port *ap);
void (*port_stop) (struct ata_port *ap);
@@ -716,7 +746,7 @@ struct ata_timing {
unsigned short udma; /* t2CYCTYP/2 */
};
-#define FIT(v,vmin,vmax) max_t(short,min_t(short,v,vmax),vmin)
+#define FIT(v, vmin, vmax) max_t(short, min_t(short, v, vmax), vmin)
extern const unsigned long sata_deb_timing_normal[];
extern const unsigned long sata_deb_timing_hotplug[];
@@ -798,6 +828,7 @@ extern void ata_host_resume(struct ata_host *host);
extern int ata_ratelimit(void);
extern int ata_busy_sleep(struct ata_port *ap,
unsigned long timeout_pat, unsigned long timeout);
+extern void ata_wait_after_reset(struct ata_port *ap, unsigned long deadline);
extern int ata_wait_ready(struct ata_port *ap, unsigned long deadline);
extern void ata_port_queue_task(struct ata_port *ap, work_func_t fn,
void *data, unsigned long delay);
@@ -815,14 +846,14 @@ extern void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
extern void ata_tf_to_fis(const struct ata_taskfile *tf,
u8 pmp, int is_cmd, u8 *fis);
extern void ata_tf_from_fis(const u8 *fis, struct ata_taskfile *tf);
-extern void ata_noop_dev_select (struct ata_port *ap, unsigned int device);
-extern void ata_std_dev_select (struct ata_port *ap, unsigned int device);
+extern void ata_noop_dev_select(struct ata_port *ap, unsigned int device);
+extern void ata_std_dev_select(struct ata_port *ap, unsigned int device);
extern u8 ata_check_status(struct ata_port *ap);
extern u8 ata_altstatus(struct ata_port *ap);
extern void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf);
-extern int ata_port_start (struct ata_port *ap);
-extern int ata_sff_port_start (struct ata_port *ap);
-extern irqreturn_t ata_interrupt (int irq, void *dev_instance);
+extern int ata_port_start(struct ata_port *ap);
+extern int ata_sff_port_start(struct ata_port *ap);
+extern irqreturn_t ata_interrupt(int irq, void *dev_instance);
extern void ata_data_xfer(struct ata_device *adev, unsigned char *buf,
unsigned int buflen, int write_data);
extern void ata_data_xfer_noirq(struct ata_device *adev, unsigned char *buf,
@@ -843,8 +874,8 @@ extern void ata_id_string(const u16 *id, unsigned char *s,
extern void ata_id_c_string(const u16 *id, unsigned char *s,
unsigned int ofs, unsigned int len);
extern void ata_id_to_dma_mode(struct ata_device *dev, u8 unknown);
-extern void ata_bmdma_setup (struct ata_queued_cmd *qc);
-extern void ata_bmdma_start (struct ata_queued_cmd *qc);
+extern void ata_bmdma_setup(struct ata_queued_cmd *qc);
+extern void ata_bmdma_start(struct ata_queued_cmd *qc);
extern void ata_bmdma_stop(struct ata_queued_cmd *qc);
extern u8 ata_bmdma_status(struct ata_port *ap);
extern void ata_bmdma_irq_clear(struct ata_port *ap);
@@ -919,9 +950,9 @@ static inline int ata_acpi_cbl_80wire(struct ata_port *ap) { return 0; }
#ifdef CONFIG_PCI
struct pci_dev;
-extern int ata_pci_init_one (struct pci_dev *pdev,
+extern int ata_pci_init_one(struct pci_dev *pdev,
const struct ata_port_info * const * ppi);
-extern void ata_pci_remove_one (struct pci_dev *pdev);
+extern void ata_pci_remove_one(struct pci_dev *pdev);
#ifdef CONFIG_PM
extern void ata_pci_device_do_suspend(struct pci_dev *pdev, pm_message_t mesg);
extern int __must_check ata_pci_device_do_resume(struct pci_dev *pdev);
@@ -1036,21 +1067,10 @@ extern void ata_port_pbar_desc(struct ata_port *ap, int bar, ssize_t offset,
/*
* qc helpers
*/
-static inline int
-ata_sg_is_last(struct scatterlist *sg, struct ata_queued_cmd *qc)
-{
- if (sg == &qc->pad_sgent)
- return 1;
- if (qc->pad_len)
- return 0;
- if (((sg - qc->__sg) + 1) == qc->n_elem)
- return 1;
- return 0;
-}
-
static inline struct scatterlist *
ata_qc_first_sg(struct ata_queued_cmd *qc)
{
+ qc->n_iter = 0;
if (qc->n_elem)
return qc->__sg;
if (qc->pad_len)
@@ -1063,8 +1083,8 @@ ata_qc_next_sg(struct scatterlist *sg, struct ata_queued_cmd *qc)
{
if (sg == &qc->pad_sgent)
return NULL;
- if (++sg - qc->__sg < qc->n_elem)
- return sg;
+ if (++qc->n_iter < qc->n_elem)
+ return sg_next(sg);
if (qc->pad_len)
return &qc->pad_sgent;
return NULL;
@@ -1309,9 +1329,11 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc)
qc->dma_dir = DMA_NONE;
qc->__sg = NULL;
qc->flags = 0;
- qc->cursg = qc->cursg_ofs = 0;
+ qc->cursg = NULL;
+ qc->cursg_ofs = 0;
qc->nbytes = qc->curbytes = 0;
qc->n_elem = 0;
+ qc->n_iter = 0;
qc->err_mask = 0;
qc->pad_len = 0;
qc->sect_size = ATA_SECT_SIZE;
diff --git a/include/linux/linkage.h b/include/linux/linkage.h
index 6c9873f88287..ff203dd02919 100644
--- a/include/linux/linkage.h
+++ b/include/linux/linkage.h
@@ -34,6 +34,12 @@
name:
#endif
+#ifndef WEAK
+#define WEAK(name) \
+ .weak name; \
+ name:
+#endif
+
#define KPROBE_ENTRY(name) \
.pushsection .kprobes.text, "ax"; \
ENTRY(name)
diff --git a/include/linux/list.h b/include/linux/list.h
index ad9dcb9e3375..75ce2cb4ff6e 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -478,6 +478,17 @@ static inline void list_splice_init_rcu(struct list_head *list,
pos = n, n = pos->next)
/**
+ * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @n: another &struct list_head to use as temporary storage
+ * @head: the head for your list.
+ */
+#define list_for_each_prev_safe(pos, n, head) \
+ for (pos = (head)->prev, n = pos->prev; \
+ prefetch(pos->prev), pos != (head); \
+ pos = n, n = pos->prev)
+
+/**
* list_for_each_entry - iterate over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
index f6279f68a827..4c4d236ded18 100644
--- a/include/linux/lockdep.h
+++ b/include/linux/lockdep.h
@@ -276,6 +276,14 @@ extern void lockdep_init_map(struct lockdep_map *lock, const char *name,
(lock)->dep_map.key, sub)
/*
+ * To initialize a lockdep_map statically use this macro.
+ * Note that _name must not be NULL.
+ */
+#define STATIC_LOCKDEP_MAP_INIT(_name, _key) \
+ { .name = (_name), .key = (void *)(_key), }
+
+
+/*
* Acquire a lock.
*
* Values for "read":
diff --git a/include/linux/log2.h b/include/linux/log2.h
index 1b8a2c1cb0e3..c8cf5e8ef171 100644
--- a/include/linux/log2.h
+++ b/include/linux/log2.h
@@ -63,6 +63,15 @@ unsigned long __roundup_pow_of_two(unsigned long n)
return 1UL << fls_long(n - 1);
}
+/*
+ * round down to nearest power of two
+ */
+static inline __attribute__((const))
+unsigned long __rounddown_pow_of_two(unsigned long n)
+{
+ return 1UL << (fls_long(n) - 1);
+}
+
/**
* ilog2 - log of base 2 of 32-bit or a 64-bit unsigned value
* @n - parameter
@@ -165,4 +174,20 @@ unsigned long __roundup_pow_of_two(unsigned long n)
__roundup_pow_of_two(n) \
)
+/**
+ * rounddown_pow_of_two - round the given value down to nearest power of two
+ * @n - parameter
+ *
+ * round the given value down to the nearest power of two
+ * - the result is undefined when n == 0
+ * - this can be used to initialise global variables from constant data
+ */
+#define rounddown_pow_of_two(n) \
+( \
+ __builtin_constant_p(n) ? ( \
+ (n == 1) ? 0 : \
+ (1UL << ilog2(n))) : \
+ __rounddown_pow_of_two(n) \
+ )
+
#endif /* _LINUX_LOG2_H */
diff --git a/include/linux/magic.h b/include/linux/magic.h
index 36cc20dfd142..1fa0c2ce4dec 100644
--- a/include/linux/magic.h
+++ b/include/linux/magic.h
@@ -37,5 +37,9 @@
#define SMB_SUPER_MAGIC 0x517B
#define USBDEVICE_SUPER_MAGIC 0x9fa2
+#define CGROUP_SUPER_MAGIC 0x27e0eb
+
+#define FUTEXFS_SUPER_MAGIC 0xBAD1DEA
+#define INOTIFYFS_SUPER_MAGIC 0x2BAD1DEA
#endif /* __LINUX_MAGIC_H__ */
diff --git a/include/linux/marker.h b/include/linux/marker.h
new file mode 100644
index 000000000000..5f36cf946bcb
--- /dev/null
+++ b/include/linux/marker.h
@@ -0,0 +1,129 @@
+#ifndef _LINUX_MARKER_H
+#define _LINUX_MARKER_H
+
+/*
+ * Code markup for dynamic and static tracing.
+ *
+ * See Documentation/marker.txt.
+ *
+ * (C) Copyright 2006 Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
+ *
+ * This file is released under the GPLv2.
+ * See the file COPYING for more details.
+ */
+
+#include <linux/types.h>
+
+struct module;
+struct marker;
+
+/**
+ * marker_probe_func - Type of a marker probe function
+ * @mdata: pointer of type struct marker
+ * @private_data: caller site private data
+ * @fmt: format string
+ * @...: variable argument list
+ *
+ * Type of marker probe functions. They receive the mdata and need to parse the
+ * format string to recover the variable argument list.
+ */
+typedef void marker_probe_func(const struct marker *mdata,
+ void *private_data, const char *fmt, ...);
+
+struct marker {
+ const char *name; /* Marker name */
+ const char *format; /* Marker format string, describing the
+ * variable argument list.
+ */
+ char state; /* Marker state. */
+ marker_probe_func *call;/* Probe handler function pointer */
+ void *private; /* Private probe data */
+} __attribute__((aligned(8)));
+
+#ifdef CONFIG_MARKERS
+
+/*
+ * Note : the empty asm volatile with read constraint is used here instead of a
+ * "used" attribute to fix a gcc 4.1.x bug.
+ * Make sure the alignment of the structure in the __markers section will
+ * not add unwanted padding between the beginning of the section and the
+ * structure. Force alignment to the same alignment as the section start.
+ */
+#define __trace_mark(name, call_data, format, args...) \
+ do { \
+ static const char __mstrtab_name_##name[] \
+ __attribute__((section("__markers_strings"))) \
+ = #name; \
+ static const char __mstrtab_format_##name[] \
+ __attribute__((section("__markers_strings"))) \
+ = format; \
+ static struct marker __mark_##name \
+ __attribute__((section("__markers"), aligned(8))) = \
+ { __mstrtab_name_##name, __mstrtab_format_##name, \
+ 0, __mark_empty_function, NULL }; \
+ __mark_check_format(format, ## args); \
+ if (unlikely(__mark_##name.state)) { \
+ preempt_disable(); \
+ (*__mark_##name.call) \
+ (&__mark_##name, call_data, \
+ format, ## args); \
+ preempt_enable(); \
+ } \
+ } while (0)
+
+extern void marker_update_probe_range(struct marker *begin,
+ struct marker *end, struct module *probe_module, int *refcount);
+#else /* !CONFIG_MARKERS */
+#define __trace_mark(name, call_data, format, args...) \
+ __mark_check_format(format, ## args)
+static inline void marker_update_probe_range(struct marker *begin,
+ struct marker *end, struct module *probe_module, int *refcount)
+{ }
+#endif /* CONFIG_MARKERS */
+
+/**
+ * trace_mark - Marker
+ * @name: marker name, not quoted.
+ * @format: format string
+ * @args...: variable argument list
+ *
+ * Places a marker.
+ */
+#define trace_mark(name, format, args...) \
+ __trace_mark(name, NULL, format, ## args)
+
+#define MARK_MAX_FORMAT_LEN 1024
+
+/**
+ * MARK_NOARGS - Format string for a marker with no argument.
+ */
+#define MARK_NOARGS " "
+
+/* To be used for string format validity checking with gcc */
+static inline void __printf(1, 2) __mark_check_format(const char *fmt, ...)
+{
+}
+
+extern marker_probe_func __mark_empty_function;
+
+/*
+ * Connect a probe to a marker.
+ * private data pointer must be a valid allocated memory address, or NULL.
+ */
+extern int marker_probe_register(const char *name, const char *format,
+ marker_probe_func *probe, void *private);
+
+/*
+ * Returns the private data given to marker_probe_register.
+ */
+extern void *marker_probe_unregister(const char *name);
+/*
+ * Unregister a marker by providing the registered private data.
+ */
+extern void *marker_probe_unregister_private_data(void *private);
+
+extern int marker_arm(const char *name);
+extern int marker_disarm(const char *name);
+extern void *marker_get_private_data(const char *name);
+
+#endif
diff --git a/include/linux/mc146818rtc.h b/include/linux/mc146818rtc.h
index 580b3f4956ee..2f4e957af656 100644
--- a/include/linux/mc146818rtc.h
+++ b/include/linux/mc146818rtc.h
@@ -109,8 +109,11 @@ struct cmos_rtc_board_info {
#ifndef ARCH_RTC_LOCATION /* Override by <asm/mc146818rtc.h>? */
#define RTC_IO_EXTENT 0x8
+#define RTC_IO_EXTENT_USED 0x2
#define RTC_IOMAPPED 1 /* Default to I/O mapping. */
+#else
+#define RTC_IO_EXTENT_USED RTC_IO_EXTENT
#endif /* ARCH_RTC_LOCATION */
#endif /* _MC146818RTC_H */
diff --git a/include/linux/memory.h b/include/linux/memory.h
index 654ef5544878..33f0ff0cf634 100644
--- a/include/linux/memory.h
+++ b/include/linux/memory.h
@@ -41,18 +41,15 @@ struct memory_block {
#define MEM_ONLINE (1<<0) /* exposed to userspace */
#define MEM_GOING_OFFLINE (1<<1) /* exposed to userspace */
#define MEM_OFFLINE (1<<2) /* exposed to userspace */
+#define MEM_GOING_ONLINE (1<<3)
+#define MEM_CANCEL_ONLINE (1<<4)
+#define MEM_CANCEL_OFFLINE (1<<5)
-/*
- * All of these states are currently kernel-internal for notifying
- * kernel components and architectures.
- *
- * For MEM_MAPPING_INVALID, all notifier chains with priority >0
- * are called before pfn_to_page() becomes invalid. The priority=0
- * entry is reserved for the function that actually makes
- * pfn_to_page() stop working. Any notifiers that want to be called
- * after that should have priority <0.
- */
-#define MEM_MAPPING_INVALID (1<<3)
+struct memory_notify {
+ unsigned long start_pfn;
+ unsigned long nr_pages;
+ int status_change_nid;
+};
struct notifier_block;
struct mem_section;
@@ -69,21 +66,31 @@ static inline int register_memory_notifier(struct notifier_block *nb)
static inline void unregister_memory_notifier(struct notifier_block *nb)
{
}
+static inline int memory_notify(unsigned long val, void *v)
+{
+ return 0;
+}
#else
+extern int register_memory_notifier(struct notifier_block *nb);
+extern void unregister_memory_notifier(struct notifier_block *nb);
extern int register_new_memory(struct mem_section *);
extern int unregister_memory_section(struct mem_section *);
extern int memory_dev_init(void);
extern int remove_memory_block(unsigned long, struct mem_section *, int);
-
+extern int memory_notify(unsigned long val, void *v);
#define CONFIG_MEM_BLOCK_SIZE (PAGES_PER_SECTION<<PAGE_SHIFT)
#endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */
+#ifdef CONFIG_MEMORY_HOTPLUG
#define hotplug_memory_notifier(fn, pri) { \
static struct notifier_block fn##_mem_nb = \
{ .notifier_call = fn, .priority = pri }; \
register_memory_notifier(&fn##_mem_nb); \
}
+#else
+#define hotplug_memory_notifier(fn, pri) do { } while (0)
+#endif
#endif /* _LINUX_MEMORY_H_ */
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
index 7b54666cea8e..8fee7a45736b 100644
--- a/include/linux/memory_hotplug.h
+++ b/include/linux/memory_hotplug.h
@@ -3,7 +3,6 @@
#include <linux/mmzone.h>
#include <linux/spinlock.h>
-#include <linux/mmzone.h>
#include <linux/notifier.h>
struct page;
@@ -59,11 +58,21 @@ extern int add_one_highpage(struct page *page, int pfn, int bad_ppro);
extern void online_page(struct page *page);
/* VM interface that may be used by firmware interface */
extern int online_pages(unsigned long, unsigned long);
+extern void __offline_isolated_pages(unsigned long, unsigned long);
+extern int offline_pages(unsigned long, unsigned long, unsigned long);
/* reasonably generic interface to expand the physical pages in a zone */
extern int __add_pages(struct zone *zone, unsigned long start_pfn,
unsigned long nr_pages);
+/*
+ * Walk thorugh all memory which is registered as resource.
+ * arg is (start_pfn, nr_pages, private_arg_pointer)
+ */
+extern int walk_memory_resource(unsigned long start_pfn,
+ unsigned long nr_pages, void *arg,
+ int (*func)(unsigned long, unsigned long, void *));
+
#ifdef CONFIG_NUMA
extern int memory_add_physaddr_to_nid(u64 start);
#else
@@ -161,13 +170,6 @@ static inline int mhp_notimplemented(const char *func)
}
#endif /* ! CONFIG_MEMORY_HOTPLUG */
-static inline int __remove_pages(struct zone *zone, unsigned long start_pfn,
- unsigned long nr_pages)
-{
- printk(KERN_WARNING "%s() called, not yet supported\n", __FUNCTION__);
- dump_stack();
- return -ENOSYS;
-}
extern int add_memory(int nid, u64 start, u64 size);
extern int arch_add_memory(int nid, u64 start, u64 size);
diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h
index a020eb2d4e2a..59c4865bc85f 100644
--- a/include/linux/mempolicy.h
+++ b/include/linux/mempolicy.h
@@ -19,6 +19,7 @@
/* Flags for get_mem_policy */
#define MPOL_F_NODE (1<<0) /* return next IL mode instead of node mask */
#define MPOL_F_ADDR (1<<1) /* look up vma using address */
+#define MPOL_F_MEMS_ALLOWED (1<<2) /* return allowed memories */
/* Flags for mbind */
#define MPOL_MF_STRICT (1<<0) /* Verify existing pages in the mapping */
@@ -143,19 +144,10 @@ struct mempolicy *mpol_shared_policy_lookup(struct shared_policy *sp,
extern void numa_default_policy(void);
extern void numa_policy_init(void);
-extern void mpol_rebind_policy(struct mempolicy *pol, const nodemask_t *new);
extern void mpol_rebind_task(struct task_struct *tsk,
const nodemask_t *new);
extern void mpol_rebind_mm(struct mm_struct *mm, nodemask_t *new);
extern void mpol_fix_fork_child_flag(struct task_struct *p);
-#define set_cpuset_being_rebound(x) (cpuset_being_rebound = (x))
-
-#ifdef CONFIG_CPUSETS
-#define current_cpuset_is_being_rebound() \
- (cpuset_being_rebound == current->cpuset)
-#else
-#define current_cpuset_is_being_rebound() 0
-#endif
extern struct mempolicy default_policy;
extern struct zonelist *huge_zonelist(struct vm_area_struct *vma,
@@ -173,8 +165,6 @@ static inline void check_highest_zone(enum zone_type k)
int do_migrate_pages(struct mm_struct *mm,
const nodemask_t *from_nodes, const nodemask_t *to_nodes, int flags);
-extern void *cpuset_being_rebound; /* Trigger mpol_copy vma rebind */
-
#else
struct mempolicy {};
@@ -235,11 +225,6 @@ static inline void numa_default_policy(void)
{
}
-static inline void mpol_rebind_policy(struct mempolicy *pol,
- const nodemask_t *new)
-{
-}
-
static inline void mpol_rebind_task(struct task_struct *tsk,
const nodemask_t *new)
{
@@ -253,8 +238,6 @@ static inline void mpol_fix_fork_child_flag(struct task_struct *p)
{
}
-#define set_cpuset_being_rebound(x) do {} while (0)
-
static inline struct zonelist *huge_zonelist(struct vm_area_struct *vma,
unsigned long addr, gfp_t gfp_flags, struct mempolicy **mpol)
{
diff --git a/include/linux/mlx4/doorbell.h b/include/linux/mlx4/doorbell.h
index 3f2da442d7cb..f31bba270aa2 100644
--- a/include/linux/mlx4/doorbell.h
+++ b/include/linux/mlx4/doorbell.h
@@ -52,11 +52,6 @@
#define MLX4_INIT_DOORBELL_LOCK(ptr) do { } while (0)
#define MLX4_GET_DOORBELL_LOCK(ptr) (NULL)
-static inline void mlx4_write64_raw(__be64 val, void __iomem *dest)
-{
- __raw_writeq((__force u64) val, dest);
-}
-
static inline void mlx4_write64(__be32 val[2], void __iomem *dest,
spinlock_t *doorbell_lock)
{
@@ -75,12 +70,6 @@ static inline void mlx4_write64(__be32 val[2], void __iomem *dest,
#define MLX4_INIT_DOORBELL_LOCK(ptr) spin_lock_init(ptr)
#define MLX4_GET_DOORBELL_LOCK(ptr) (ptr)
-static inline void mlx4_write64_raw(__be64 val, void __iomem *dest)
-{
- __raw_writel(((__force u32 *) &val)[0], dest);
- __raw_writel(((__force u32 *) &val)[1], dest + 4);
-}
-
static inline void mlx4_write64(__be32 val[2], void __iomem *dest,
spinlock_t *doorbell_lock)
{
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 1692dd6cb915..520238cbae5d 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -10,9 +10,7 @@
#include <linux/mmzone.h>
#include <linux/rbtree.h>
#include <linux/prio_tree.h>
-#include <linux/mutex.h>
#include <linux/debug_locks.h>
-#include <linux/backing-dev.h>
#include <linux/mm_types.h>
struct mempolicy;
@@ -50,69 +48,6 @@ extern int sysctl_legacy_va_layout;
* mmap() functions).
*/
-/*
- * This struct defines a memory VMM memory area. There is one of these
- * per VM-area/task. A VM area is any part of the process virtual memory
- * space that has a special rule for the page-fault handlers (ie a shared
- * library, the executable area etc).
- */
-struct vm_area_struct {
- struct mm_struct * vm_mm; /* The address space we belong to. */
- unsigned long vm_start; /* Our start address within vm_mm. */
- unsigned long vm_end; /* The first byte after our end address
- within vm_mm. */
-
- /* linked list of VM areas per task, sorted by address */
- struct vm_area_struct *vm_next;
-
- pgprot_t vm_page_prot; /* Access permissions of this VMA. */
- unsigned long vm_flags; /* Flags, listed below. */
-
- struct rb_node vm_rb;
-
- /*
- * For areas with an address space and backing store,
- * linkage into the address_space->i_mmap prio tree, or
- * linkage to the list of like vmas hanging off its node, or
- * linkage of vma in the address_space->i_mmap_nonlinear list.
- */
- union {
- struct {
- struct list_head list;
- void *parent; /* aligns with prio_tree_node parent */
- struct vm_area_struct *head;
- } vm_set;
-
- struct raw_prio_tree_node prio_tree_node;
- } shared;
-
- /*
- * A file's MAP_PRIVATE vma can be in both i_mmap tree and anon_vma
- * list, after a COW of one of the file pages. A MAP_SHARED vma
- * can only be in the i_mmap tree. An anonymous MAP_PRIVATE, stack
- * or brk vma (with NULL file) can only be in an anon_vma list.
- */
- struct list_head anon_vma_node; /* Serialized by anon_vma->lock */
- struct anon_vma *anon_vma; /* Serialized by page_table_lock */
-
- /* Function pointers to deal with this struct. */
- struct vm_operations_struct * vm_ops;
-
- /* Information about our backing store: */
- unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE
- units, *not* PAGE_CACHE_SIZE */
- struct file * vm_file; /* File we map to (can be NULL). */
- void * vm_private_data; /* was vm_pte (shared mem) */
- unsigned long vm_truncate_count;/* truncate_count or restart_addr */
-
-#ifndef CONFIG_MMU
- atomic_t vm_usage; /* refcount (VMAs shared if !MMU) */
-#endif
-#ifdef CONFIG_NUMA
- struct mempolicy *vm_policy; /* NUMA policy for the VMA */
-#endif
-};
-
extern struct kmem_cache *vm_area_cachep;
/*
@@ -631,10 +566,6 @@ static inline struct address_space *page_mapping(struct page *page)
VM_BUG_ON(PageSlab(page));
if (unlikely(PageSwapCache(page)))
mapping = &swapper_space;
-#ifdef CONFIG_SLUB
- else if (unlikely(PageSlab(page)))
- mapping = NULL;
-#endif
else if (unlikely((unsigned long)mapping & PAGE_MAPPING_ANON))
mapping = NULL;
return mapping;
@@ -715,9 +646,6 @@ static inline int page_mapped(struct page *page)
extern void show_free_areas(void);
#ifdef CONFIG_SHMEM
-int shmem_set_policy(struct vm_area_struct *vma, struct mempolicy *new);
-struct mempolicy *shmem_get_policy(struct vm_area_struct *vma,
- unsigned long addr);
int shmem_lock(struct file *file, int lock, struct user_struct *user);
#else
static inline int shmem_lock(struct file *file, int lock,
@@ -725,18 +653,6 @@ static inline int shmem_lock(struct file *file, int lock,
{
return 0;
}
-
-static inline int shmem_set_policy(struct vm_area_struct *vma,
- struct mempolicy *new)
-{
- return 0;
-}
-
-static inline struct mempolicy *shmem_get_policy(struct vm_area_struct *vma,
- unsigned long addr)
-{
- return NULL;
-}
#endif
struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags);
@@ -779,8 +695,6 @@ void free_pgtables(struct mmu_gather **tlb, struct vm_area_struct *start_vma,
unsigned long floor, unsigned long ceiling);
int copy_page_range(struct mm_struct *dst, struct mm_struct *src,
struct vm_area_struct *vma);
-int zeromap_page_range(struct vm_area_struct *vma, unsigned long from,
- unsigned long size, pgprot_t prot);
void unmap_mapping_range(struct address_space *mapping,
loff_t const holebegin, loff_t const holelen, int even_cows);
@@ -1106,8 +1020,6 @@ int write_one_page(struct page *page, int wait);
/* readahead.c */
#define VM_MAX_READAHEAD 128 /* kbytes */
#define VM_MIN_READAHEAD 16 /* kbytes (includes current page) */
-#define VM_MAX_CACHE_HIT 256 /* max pages in a row in cache before
- * turning readahead off */
int do_page_cache_readahead(struct address_space *mapping, struct file *filp,
pgoff_t offset, unsigned long nr_to_read);
@@ -1218,5 +1130,16 @@ extern int randomize_va_space;
const char * arch_vma_name(struct vm_area_struct *vma);
+struct page *sparse_mem_map_populate(unsigned long pnum, int nid);
+pgd_t *vmemmap_pgd_populate(unsigned long addr, int node);
+pud_t *vmemmap_pud_populate(pgd_t *pgd, unsigned long addr, int node);
+pmd_t *vmemmap_pmd_populate(pud_t *pud, unsigned long addr, int node);
+pte_t *vmemmap_pte_populate(pmd_t *pmd, unsigned long addr, int node);
+void *vmemmap_alloc_block(unsigned long size, int node);
+void vmemmap_verify(pte_t *, int, unsigned long, unsigned long);
+int vmemmap_populate_basepages(struct page *start_page,
+ unsigned long pages, int node);
+int vmemmap_populate(struct page *start_page, unsigned long pages, int node);
+
#endif /* __KERNEL__ */
#endif /* _LINUX_MM_H */
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index d5bb1796e12b..f4c03e0b355e 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -1,13 +1,31 @@
#ifndef _LINUX_MM_TYPES_H
#define _LINUX_MM_TYPES_H
+#include <linux/auxvec.h>
#include <linux/types.h>
#include <linux/threads.h>
#include <linux/list.h>
#include <linux/spinlock.h>
+#include <linux/prio_tree.h>
+#include <linux/rbtree.h>
+#include <linux/rwsem.h>
+#include <linux/completion.h>
+#include <asm/page.h>
+#include <asm/mmu.h>
+
+#ifndef AT_VECTOR_SIZE_ARCH
+#define AT_VECTOR_SIZE_ARCH 0
+#endif
+#define AT_VECTOR_SIZE (2*(AT_VECTOR_SIZE_ARCH + AT_VECTOR_SIZE_BASE + 1))
struct address_space;
+#if NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS
+typedef atomic_long_t mm_counter_t;
+#else /* NR_CPUS < CONFIG_SPLIT_PTLOCK_CPUS */
+typedef unsigned long mm_counter_t;
+#endif /* NR_CPUS < CONFIG_SPLIT_PTLOCK_CPUS */
+
/*
* Each physical page in the system has a struct page associated with
* it to keep track of whatever it is we are using the page for at the
@@ -24,10 +42,7 @@ struct page {
* to show when page is mapped
* & limit reverse map searches.
*/
- struct { /* SLUB uses */
- short unsigned int inuse;
- short unsigned int offset;
- };
+ unsigned int inuse; /* SLUB: Nr of objects */
};
union {
struct {
@@ -49,13 +64,8 @@ struct page {
#if NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS
spinlock_t ptl;
#endif
- struct { /* SLUB uses */
- void **lockless_freelist;
- struct kmem_cache *slab; /* Pointer to slab */
- };
- struct {
- struct page *first_page; /* Compound pages */
- };
+ struct kmem_cache *slab; /* SLUB: Pointer to slab */
+ struct page *first_page; /* Compound tail pages */
};
union {
pgoff_t index; /* Our offset within mapping. */
@@ -80,4 +90,135 @@ struct page {
#endif /* WANT_PAGE_VIRTUAL */
};
+/*
+ * This struct defines a memory VMM memory area. There is one of these
+ * per VM-area/task. A VM area is any part of the process virtual memory
+ * space that has a special rule for the page-fault handlers (ie a shared
+ * library, the executable area etc).
+ */
+struct vm_area_struct {
+ struct mm_struct * vm_mm; /* The address space we belong to. */
+ unsigned long vm_start; /* Our start address within vm_mm. */
+ unsigned long vm_end; /* The first byte after our end address
+ within vm_mm. */
+
+ /* linked list of VM areas per task, sorted by address */
+ struct vm_area_struct *vm_next;
+
+ pgprot_t vm_page_prot; /* Access permissions of this VMA. */
+ unsigned long vm_flags; /* Flags, listed below. */
+
+ struct rb_node vm_rb;
+
+ /*
+ * For areas with an address space and backing store,
+ * linkage into the address_space->i_mmap prio tree, or
+ * linkage to the list of like vmas hanging off its node, or
+ * linkage of vma in the address_space->i_mmap_nonlinear list.
+ */
+ union {
+ struct {
+ struct list_head list;
+ void *parent; /* aligns with prio_tree_node parent */
+ struct vm_area_struct *head;
+ } vm_set;
+
+ struct raw_prio_tree_node prio_tree_node;
+ } shared;
+
+ /*
+ * A file's MAP_PRIVATE vma can be in both i_mmap tree and anon_vma
+ * list, after a COW of one of the file pages. A MAP_SHARED vma
+ * can only be in the i_mmap tree. An anonymous MAP_PRIVATE, stack
+ * or brk vma (with NULL file) can only be in an anon_vma list.
+ */
+ struct list_head anon_vma_node; /* Serialized by anon_vma->lock */
+ struct anon_vma *anon_vma; /* Serialized by page_table_lock */
+
+ /* Function pointers to deal with this struct. */
+ struct vm_operations_struct * vm_ops;
+
+ /* Information about our backing store: */
+ unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE
+ units, *not* PAGE_CACHE_SIZE */
+ struct file * vm_file; /* File we map to (can be NULL). */
+ void * vm_private_data; /* was vm_pte (shared mem) */
+ unsigned long vm_truncate_count;/* truncate_count or restart_addr */
+
+#ifndef CONFIG_MMU
+ atomic_t vm_usage; /* refcount (VMAs shared if !MMU) */
+#endif
+#ifdef CONFIG_NUMA
+ struct mempolicy *vm_policy; /* NUMA policy for the VMA */
+#endif
+};
+
+struct mm_struct {
+ struct vm_area_struct * mmap; /* list of VMAs */
+ struct rb_root mm_rb;
+ struct vm_area_struct * mmap_cache; /* last find_vma result */
+ unsigned long (*get_unmapped_area) (struct file *filp,
+ unsigned long addr, unsigned long len,
+ unsigned long pgoff, unsigned long flags);
+ void (*unmap_area) (struct mm_struct *mm, unsigned long addr);
+ unsigned long mmap_base; /* base of mmap area */
+ unsigned long task_size; /* size of task vm space */
+ unsigned long cached_hole_size; /* if non-zero, the largest hole below free_area_cache */
+ unsigned long free_area_cache; /* first hole of size cached_hole_size or larger */
+ pgd_t * pgd;
+ atomic_t mm_users; /* How many users with user space? */
+ atomic_t mm_count; /* How many references to "struct mm_struct" (users count as 1) */
+ int map_count; /* number of VMAs */
+ struct rw_semaphore mmap_sem;
+ spinlock_t page_table_lock; /* Protects page tables and some counters */
+
+ struct list_head mmlist; /* List of maybe swapped mm's. These are globally strung
+ * together off init_mm.mmlist, and are protected
+ * by mmlist_lock
+ */
+
+ /* Special counters, in some configurations protected by the
+ * page_table_lock, in other configurations by being atomic.
+ */
+ mm_counter_t _file_rss;
+ mm_counter_t _anon_rss;
+
+ unsigned long hiwater_rss; /* High-watermark of RSS usage */
+ unsigned long hiwater_vm; /* High-water virtual memory usage */
+
+ unsigned long total_vm, locked_vm, shared_vm, exec_vm;
+ unsigned long stack_vm, reserved_vm, def_flags, nr_ptes;
+ unsigned long start_code, end_code, start_data, end_data;
+ unsigned long start_brk, brk, start_stack;
+ unsigned long arg_start, arg_end, env_start, env_end;
+
+ unsigned long saved_auxv[AT_VECTOR_SIZE]; /* for /proc/PID/auxv */
+
+ cpumask_t cpu_vm_mask;
+
+ /* Architecture-specific MM context */
+ mm_context_t context;
+
+ /* Swap token stuff */
+ /*
+ * Last value of global fault stamp as seen by this process.
+ * In other words, this value gives an indication of how long
+ * it has been since this task got the token.
+ * Look at mm/thrash.c
+ */
+ unsigned int faultstamp;
+ unsigned int token_priority;
+ unsigned int last_interval;
+
+ unsigned long flags; /* Must use atomic bitops to access the bits */
+
+ /* coredumping support */
+ int core_waiters;
+ struct completion *core_startup_done, core_done;
+
+ /* aio bits */
+ rwlock_t ioctx_list_lock;
+ struct kioctx *ioctx_list;
+};
+
#endif /* _LINUX_MM_TYPES_H */
diff --git a/include/linux/mmc/sdio_ids.h b/include/linux/mmc/sdio_ids.h
index 09306d47ff5e..ea1bf5ba092f 100644
--- a/include/linux/mmc/sdio_ids.h
+++ b/include/linux/mmc/sdio_ids.h
@@ -19,5 +19,11 @@
#define SDIO_CLASS_WLAN 0x07 /* WLAN interface */
#define SDIO_CLASS_ATA 0x08 /* Embedded SDIO-ATA std interface */
+/*
+ * Vendors and devices. Sort key: vendor first, device next.
+ */
+
+#define SDIO_VENDOR_ID_MARVELL 0x02df
+#define SDIO_DEVICE_ID_MARVELL_LIBERTAS 0x9103
#endif
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 4e5627379b09..4c4522a51a3b 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -7,12 +7,14 @@
#include <linux/spinlock.h>
#include <linux/list.h>
#include <linux/wait.h>
+#include <linux/bitops.h>
#include <linux/cache.h>
#include <linux/threads.h>
#include <linux/numa.h>
#include <linux/init.h>
#include <linux/seqlock.h>
#include <linux/nodemask.h>
+#include <linux/pageblock-flags.h>
#include <asm/atomic.h>
#include <asm/page.h>
@@ -32,8 +34,29 @@
*/
#define PAGE_ALLOC_COSTLY_ORDER 3
+#define MIGRATE_UNMOVABLE 0
+#define MIGRATE_RECLAIMABLE 1
+#define MIGRATE_MOVABLE 2
+#define MIGRATE_RESERVE 3
+#define MIGRATE_ISOLATE 4 /* can't allocate from here */
+#define MIGRATE_TYPES 5
+
+#define for_each_migratetype_order(order, type) \
+ for (order = 0; order < MAX_ORDER; order++) \
+ for (type = 0; type < MIGRATE_TYPES; type++)
+
+extern int page_group_by_mobility_disabled;
+
+static inline int get_pageblock_migratetype(struct page *page)
+{
+ if (unlikely(page_group_by_mobility_disabled))
+ return MIGRATE_UNMOVABLE;
+
+ return get_pageblock_flags_group(page, PB_migrate, PB_migrate_end);
+}
+
struct free_area {
- struct list_head free_list;
+ struct list_head free_list[MIGRATE_TYPES];
unsigned long nr_free;
};
@@ -222,6 +245,14 @@ struct zone {
#endif
struct free_area free_area[MAX_ORDER];
+#ifndef CONFIG_SPARSEMEM
+ /*
+ * Flags for a pageblock_nr_pages block. See pageblock-flags.h.
+ * In SPARSEMEM, this map is stored in struct mem_section
+ */
+ unsigned long *pageblock_flags;
+#endif /* CONFIG_SPARSEMEM */
+
ZONE_PADDING(_pad1_)
@@ -232,10 +263,7 @@ struct zone {
unsigned long nr_scan_active;
unsigned long nr_scan_inactive;
unsigned long pages_scanned; /* since last reclaim */
- int all_unreclaimable; /* All pages pinned */
-
- /* A count of how many reclaimers are scanning this zone */
- atomic_t reclaim_in_progress;
+ unsigned long flags; /* zone flags, see below */
/* Zone statistics */
atomic_long_t vm_stat[NR_VM_ZONE_STAT_ITEMS];
@@ -313,6 +341,42 @@ struct zone {
const char *name;
} ____cacheline_internodealigned_in_smp;
+typedef enum {
+ ZONE_ALL_UNRECLAIMABLE, /* all pages pinned */
+ ZONE_RECLAIM_LOCKED, /* prevents concurrent reclaim */
+ ZONE_OOM_LOCKED, /* zone is in OOM killer zonelist */
+} zone_flags_t;
+
+static inline void zone_set_flag(struct zone *zone, zone_flags_t flag)
+{
+ set_bit(flag, &zone->flags);
+}
+
+static inline int zone_test_and_set_flag(struct zone *zone, zone_flags_t flag)
+{
+ return test_and_set_bit(flag, &zone->flags);
+}
+
+static inline void zone_clear_flag(struct zone *zone, zone_flags_t flag)
+{
+ clear_bit(flag, &zone->flags);
+}
+
+static inline int zone_is_all_unreclaimable(const struct zone *zone)
+{
+ return test_bit(ZONE_ALL_UNRECLAIMABLE, &zone->flags);
+}
+
+static inline int zone_is_reclaim_locked(const struct zone *zone)
+{
+ return test_bit(ZONE_RECLAIM_LOCKED, &zone->flags);
+}
+
+static inline int zone_is_oom_locked(const struct zone *zone)
+{
+ return test_bit(ZONE_OOM_LOCKED, &zone->flags);
+}
+
/*
* The "priority" of VM scanning is how much of the queues we will scan in one
* go. A value of 12 for DEF_PRIORITY implies that we will scan 1/4096th of the
@@ -324,6 +388,17 @@ struct zone {
#define MAX_ZONES_PER_ZONELIST (MAX_NUMNODES * MAX_NR_ZONES)
#ifdef CONFIG_NUMA
+
+/*
+ * The NUMA zonelists are doubled becausse we need zonelists that restrict the
+ * allocations to a single node for GFP_THISNODE.
+ *
+ * [0 .. MAX_NR_ZONES -1] : Zonelists with fallback
+ * [MAZ_NR_ZONES ... MAZ_ZONELISTS -1] : No fallback (GFP_THISNODE)
+ */
+#define MAX_ZONELISTS (2 * MAX_NR_ZONES)
+
+
/*
* We cache key information from each zonelist for smaller cache
* footprint when scanning for free pages in get_page_from_freelist().
@@ -389,6 +464,7 @@ struct zonelist_cache {
unsigned long last_full_zap; /* when last zap'd (jiffies) */
};
#else
+#define MAX_ZONELISTS MAX_NR_ZONES
struct zonelist_cache;
#endif
@@ -455,7 +531,7 @@ extern struct page *mem_map;
struct bootmem_data;
typedef struct pglist_data {
struct zone node_zones[MAX_NR_ZONES];
- struct zonelist node_zonelists[MAX_NR_ZONES];
+ struct zonelist node_zonelists[MAX_ZONELISTS];
int nr_zones;
#ifdef CONFIG_FLAT_NODE_MEM_MAP
struct page *node_mem_map;
@@ -708,6 +784,9 @@ extern struct zone *next_zone(struct zone *zone);
#define PAGES_PER_SECTION (1UL << PFN_SECTION_SHIFT)
#define PAGE_SECTION_MASK (~(PAGES_PER_SECTION-1))
+#define SECTION_BLOCKFLAGS_BITS \
+ ((1UL << (PFN_SECTION_SHIFT - pageblock_order)) * NR_PAGEBLOCK_BITS)
+
#if (MAX_ORDER - 1 + PAGE_SHIFT) > SECTION_SIZE_BITS
#error Allocator MAX_ORDER exceeds SECTION_SIZE
#endif
@@ -727,6 +806,9 @@ struct mem_section {
* before using it wrong.
*/
unsigned long section_mem_map;
+
+ /* See declaration of similar field in struct zone */
+ unsigned long *pageblock_flags;
};
#ifdef CONFIG_SPARSEMEM_EXTREME
@@ -771,12 +853,17 @@ static inline struct page *__section_mem_map_addr(struct mem_section *section)
return (struct page *)map;
}
-static inline int valid_section(struct mem_section *section)
+static inline int present_section(struct mem_section *section)
{
return (section && (section->section_mem_map & SECTION_MARKED_PRESENT));
}
-static inline int section_has_mem_map(struct mem_section *section)
+static inline int present_section_nr(unsigned long nr)
+{
+ return present_section(__nr_to_section(nr));
+}
+
+static inline int valid_section(struct mem_section *section)
{
return (section && (section->section_mem_map & SECTION_HAS_MEM_MAP));
}
@@ -798,6 +885,13 @@ static inline int pfn_valid(unsigned long pfn)
return valid_section(__nr_to_section(pfn_to_section_nr(pfn)));
}
+static inline int pfn_present(unsigned long pfn)
+{
+ if (pfn_to_section_nr(pfn) >= NR_MEM_SECTIONS)
+ return 0;
+ return present_section(__nr_to_section(pfn_to_section_nr(pfn)));
+}
+
/*
* These are _only_ used during initialisation, therefore they
* can use __initdata ... They could have names to indicate
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index 522b0dd836cf..e9fddb42f26c 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -361,4 +361,10 @@ struct ssb_device_id {
#define SSB_ANY_ID 0xFFFF
#define SSB_ANY_REV 0xFF
+struct virtio_device_id {
+ __u32 device;
+ __u32 vendor;
+};
+#define VIRTIO_DEV_ANY_ID 0xffffffff
+
#endif /* LINUX_MOD_DEVICETABLE_H */
diff --git a/include/linux/module.h b/include/linux/module.h
index b6a646cea1cb..2cbc0b87e329 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -15,6 +15,7 @@
#include <linux/stringify.h>
#include <linux/kobject.h>
#include <linux/moduleparam.h>
+#include <linux/marker.h>
#include <asm/local.h>
#include <asm/module.h>
@@ -312,9 +313,6 @@ struct module
/* Arch-specific module values */
struct mod_arch_specific arch;
- /* Am I unsafe to unload? */
- int unsafe;
-
unsigned int taints; /* same bits as kernel:tainted */
#ifdef CONFIG_GENERIC_BUG
@@ -346,6 +344,9 @@ struct module
/* Section attributes */
struct module_sect_attrs *sect_attrs;
+
+ /* Notes attributes */
+ struct module_notes_attrs *notes_attrs;
#endif
/* Per-cpu data. */
@@ -354,6 +355,10 @@ struct module
/* The command line arguments (may be mangled). People like
keeping pointers to this stuff */
char *args;
+#ifdef CONFIG_MARKERS
+ struct marker *markers;
+ unsigned int num_markers;
+#endif
};
#ifndef MODULE_ARCH_INIT
#define MODULE_ARCH_INIT {}
@@ -441,16 +446,6 @@ static inline void __module_get(struct module *module)
__mod ? __mod->name : "kernel"; \
})
-#define __unsafe(mod) \
-do { \
- if (mod && !(mod)->unsafe) { \
- printk(KERN_WARNING \
- "Module %s cannot be unloaded due to unsafe usage in" \
- " %s:%u\n", (mod)->name, __FILE__, __LINE__); \
- (mod)->unsafe = 1; \
- } \
-} while(0)
-
/* For kallsyms to ask for address resolution. NULL means not found. */
const char *module_address_lookup(unsigned long addr,
unsigned long *symbolsize,
@@ -467,6 +462,8 @@ int unregister_module_notifier(struct notifier_block * nb);
extern void print_modules(void);
+extern void module_update_markers(struct module *probe_module, int *refcount);
+
#else /* !CONFIG_MODULES... */
#define EXPORT_SYMBOL(sym)
#define EXPORT_SYMBOL_GPL(sym)
@@ -518,8 +515,6 @@ static inline void module_put(struct module *module)
#define module_name(mod) "kernel"
-#define __unsafe(mod)
-
/* For kallsyms to ask for address resolution. NULL means not found. */
static inline const char *module_address_lookup(unsigned long addr,
unsigned long *symbolsize,
@@ -568,6 +563,11 @@ static inline void print_modules(void)
{
}
+static inline void module_update_markers(struct module *probe_module,
+ int *refcount)
+{
+}
+
#endif /* CONFIG_MODULES */
struct device_driver;
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h
index c83588c8d08b..13410b20600f 100644
--- a/include/linux/moduleparam.h
+++ b/include/linux/moduleparam.h
@@ -38,7 +38,11 @@ struct kernel_param {
unsigned int perm;
param_set_fn set;
param_get_fn get;
- void *arg;
+ union {
+ void *arg;
+ const struct kparam_string *str;
+ const struct kparam_array *arr;
+ };
};
/* Special one for strings we want to copy into */
@@ -66,11 +70,11 @@ struct kparam_array
/* Default value instead of permissions? */ \
static int __param_perm_check_##name __attribute__((unused)) = \
BUILD_BUG_ON_ZERO((perm) < 0 || (perm) > 0777 || ((perm) & 2)); \
- static char __param_str_##name[] = prefix #name; \
+ static const char __param_str_##name[] = prefix #name; \
static struct kernel_param const __param_##name \
__attribute_used__ \
__attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \
- = { __param_str_##name, perm, set, get, arg }
+ = { __param_str_##name, perm, set, get, { arg } }
#define module_param_call(name, set, get, arg, perm) \
__module_param_call(MODULE_PARAM_PREFIX, name, set, get, arg, perm)
@@ -88,10 +92,10 @@ struct kparam_array
/* Actually copy string: maxlen param is usually sizeof(string). */
#define module_param_string(name, string, len, perm) \
- static struct kparam_string __param_string_##name \
+ static const struct kparam_string __param_string_##name \
= { len, string }; \
module_param_call(name, param_set_copystring, param_get_string, \
- &__param_string_##name, perm); \
+ .str = &__param_string_##name, perm); \
__MODULE_PARM_TYPE(name, "string")
/* Called on module insert or kernel boot */
@@ -149,11 +153,11 @@ extern int param_get_invbool(char *buffer, struct kernel_param *kp);
/* Comma-separated array: *nump is set to number they actually specified. */
#define module_param_array_named(name, array, type, nump, perm) \
- static struct kparam_array __param_arr_##name \
+ static const struct kparam_array __param_arr_##name \
= { ARRAY_SIZE(array), nump, param_set_##type, param_get_##type,\
sizeof(array[0]), array }; \
module_param_call(name, param_array_set, param_array_get, \
- &__param_arr_##name, perm); \
+ .arr = &__param_arr_##name, perm); \
__MODULE_PARM_TYPE(name, "array of " #type)
#define module_param_array(name, type, nump, perm) \
diff --git a/include/linux/mroute.h b/include/linux/mroute.h
index 7da2cee8e132..35a8277ec1bd 100644
--- a/include/linux/mroute.h
+++ b/include/linux/mroute.h
@@ -128,6 +128,18 @@ struct igmpmsg
#ifdef __KERNEL__
#include <net/sock.h>
+#ifdef CONFIG_IP_MROUTE
+static inline int ip_mroute_opt(int opt)
+{
+ return (opt >= MRT_BASE) && (opt <= MRT_BASE + 10);
+}
+#else
+static inline int ip_mroute_opt(int opt)
+{
+ return 0;
+}
+#endif
+
extern int ip_mroute_setsockopt(struct sock *, int, char __user *, int);
extern int ip_mroute_getsockopt(struct sock *, int, char __user *, int __user *);
extern int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg);
diff --git a/include/linux/msg.h b/include/linux/msg.h
index f1b60740d641..10a3d5a1abff 100644
--- a/include/linux/msg.h
+++ b/include/linux/msg.h
@@ -77,7 +77,6 @@ struct msg_msg {
/* one msq_queue structure for each present queue on the system */
struct msg_queue {
struct kern_ipc_perm q_perm;
- int q_id;
time_t q_stime; /* last msgsnd time */
time_t q_rtime; /* last msgrcv time */
time_t q_ctime; /* last change time */
diff --git a/include/linux/mutex.h b/include/linux/mutex.h
index 6a735c72f23f..601479772b98 100644
--- a/include/linux/mutex.h
+++ b/include/linux/mutex.h
@@ -29,7 +29,8 @@
* - task may not exit with mutex held
* - memory areas where held locks reside must not be freed
* - held mutexes must not be reinitialized
- * - mutexes may not be used in irq contexts
+ * - mutexes may not be used in hardware or software interrupt
+ * contexts such as tasklets and timers
*
* These semantics are fully enforced when DEBUG_MUTEXES is
* enabled. Furthermore, besides enforcing the above rules, the mutex
diff --git a/include/linux/mv643xx.h b/include/linux/mv643xx.h
index 9c8049005052..d2ae6185f03b 100644
--- a/include/linux/mv643xx.h
+++ b/include/linux/mv643xx.h
@@ -14,6 +14,7 @@
#define __ASM_MV643XX_H
#include <asm/types.h>
+#include <linux/mv643xx_eth.h>
/****************************************/
/* Processor Address Space */
@@ -658,120 +659,6 @@
/* Ethernet Unit Registers */
/****************************************/
-#define MV643XX_ETH_SHARED_REGS 0x2000
-#define MV643XX_ETH_SHARED_REGS_SIZE 0x2000
-
-#define MV643XX_ETH_PHY_ADDR_REG 0x2000
-#define MV643XX_ETH_SMI_REG 0x2004
-#define MV643XX_ETH_UNIT_DEFAULT_ADDR_REG 0x2008
-#define MV643XX_ETH_UNIT_DEFAULTID_REG 0x200c
-#define MV643XX_ETH_UNIT_INTERRUPT_CAUSE_REG 0x2080
-#define MV643XX_ETH_UNIT_INTERRUPT_MASK_REG 0x2084
-#define MV643XX_ETH_UNIT_INTERNAL_USE_REG 0x24fc
-#define MV643XX_ETH_UNIT_ERROR_ADDR_REG 0x2094
-#define MV643XX_ETH_BAR_0 0x2200
-#define MV643XX_ETH_BAR_1 0x2208
-#define MV643XX_ETH_BAR_2 0x2210
-#define MV643XX_ETH_BAR_3 0x2218
-#define MV643XX_ETH_BAR_4 0x2220
-#define MV643XX_ETH_BAR_5 0x2228
-#define MV643XX_ETH_SIZE_REG_0 0x2204
-#define MV643XX_ETH_SIZE_REG_1 0x220c
-#define MV643XX_ETH_SIZE_REG_2 0x2214
-#define MV643XX_ETH_SIZE_REG_3 0x221c
-#define MV643XX_ETH_SIZE_REG_4 0x2224
-#define MV643XX_ETH_SIZE_REG_5 0x222c
-#define MV643XX_ETH_HEADERS_RETARGET_BASE_REG 0x2230
-#define MV643XX_ETH_HEADERS_RETARGET_CONTROL_REG 0x2234
-#define MV643XX_ETH_HIGH_ADDR_REMAP_REG_0 0x2280
-#define MV643XX_ETH_HIGH_ADDR_REMAP_REG_1 0x2284
-#define MV643XX_ETH_HIGH_ADDR_REMAP_REG_2 0x2288
-#define MV643XX_ETH_HIGH_ADDR_REMAP_REG_3 0x228c
-#define MV643XX_ETH_BASE_ADDR_ENABLE_REG 0x2290
-#define MV643XX_ETH_ACCESS_PROTECTION_REG(port) (0x2294 + (port<<2))
-#define MV643XX_ETH_MIB_COUNTERS_BASE(port) (0x3000 + (port<<7))
-#define MV643XX_ETH_PORT_CONFIG_REG(port) (0x2400 + (port<<10))
-#define MV643XX_ETH_PORT_CONFIG_EXTEND_REG(port) (0x2404 + (port<<10))
-#define MV643XX_ETH_MII_SERIAL_PARAMETRS_REG(port) (0x2408 + (port<<10))
-#define MV643XX_ETH_GMII_SERIAL_PARAMETRS_REG(port) (0x240c + (port<<10))
-#define MV643XX_ETH_VLAN_ETHERTYPE_REG(port) (0x2410 + (port<<10))
-#define MV643XX_ETH_MAC_ADDR_LOW(port) (0x2414 + (port<<10))
-#define MV643XX_ETH_MAC_ADDR_HIGH(port) (0x2418 + (port<<10))
-#define MV643XX_ETH_SDMA_CONFIG_REG(port) (0x241c + (port<<10))
-#define MV643XX_ETH_DSCP_0(port) (0x2420 + (port<<10))
-#define MV643XX_ETH_DSCP_1(port) (0x2424 + (port<<10))
-#define MV643XX_ETH_DSCP_2(port) (0x2428 + (port<<10))
-#define MV643XX_ETH_DSCP_3(port) (0x242c + (port<<10))
-#define MV643XX_ETH_DSCP_4(port) (0x2430 + (port<<10))
-#define MV643XX_ETH_DSCP_5(port) (0x2434 + (port<<10))
-#define MV643XX_ETH_DSCP_6(port) (0x2438 + (port<<10))
-#define MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port) (0x243c + (port<<10))
-#define MV643XX_ETH_VLAN_PRIORITY_TAG_TO_PRIORITY(port) (0x2440 + (port<<10))
-#define MV643XX_ETH_PORT_STATUS_REG(port) (0x2444 + (port<<10))
-#define MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port) (0x2448 + (port<<10))
-#define MV643XX_ETH_TX_QUEUE_FIXED_PRIORITY(port) (0x244c + (port<<10))
-#define MV643XX_ETH_PORT_TX_TOKEN_BUCKET_RATE_CONFIG(port) (0x2450 + (port<<10))
-#define MV643XX_ETH_MAXIMUM_TRANSMIT_UNIT(port) (0x2458 + (port<<10))
-#define MV643XX_ETH_PORT_MAXIMUM_TOKEN_BUCKET_SIZE(port) (0x245c + (port<<10))
-#define MV643XX_ETH_INTERRUPT_CAUSE_REG(port) (0x2460 + (port<<10))
-#define MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port) (0x2464 + (port<<10))
-#define MV643XX_ETH_INTERRUPT_MASK_REG(port) (0x2468 + (port<<10))
-#define MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port) (0x246c + (port<<10))
-#define MV643XX_ETH_RX_FIFO_URGENT_THRESHOLD_REG(port) (0x2470 + (port<<10))
-#define MV643XX_ETH_TX_FIFO_URGENT_THRESHOLD_REG(port) (0x2474 + (port<<10))
-#define MV643XX_ETH_RX_MINIMAL_FRAME_SIZE_REG(port) (0x247c + (port<<10))
-#define MV643XX_ETH_RX_DISCARDED_FRAMES_COUNTER(port) (0x2484 + (port<<10))
-#define MV643XX_ETH_PORT_DEBUG_0_REG(port) (0x248c + (port<<10))
-#define MV643XX_ETH_PORT_DEBUG_1_REG(port) (0x2490 + (port<<10))
-#define MV643XX_ETH_PORT_INTERNAL_ADDR_ERROR_REG(port) (0x2494 + (port<<10))
-#define MV643XX_ETH_INTERNAL_USE_REG(port) (0x24fc + (port<<10))
-#define MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port) (0x2680 + (port<<10))
-#define MV643XX_ETH_CURRENT_SERVED_TX_DESC_PTR(port) (0x2684 + (port<<10))
-#define MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(port) (0x260c + (port<<10))
-#define MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_1(port) (0x261c + (port<<10))
-#define MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_2(port) (0x262c + (port<<10))
-#define MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_3(port) (0x263c + (port<<10))
-#define MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_4(port) (0x264c + (port<<10))
-#define MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_5(port) (0x265c + (port<<10))
-#define MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_6(port) (0x266c + (port<<10))
-#define MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_7(port) (0x267c + (port<<10))
-#define MV643XX_ETH_TX_CURRENT_QUEUE_DESC_PTR_0(port) (0x26c0 + (port<<10))
-#define MV643XX_ETH_TX_CURRENT_QUEUE_DESC_PTR_1(port) (0x26c4 + (port<<10))
-#define MV643XX_ETH_TX_CURRENT_QUEUE_DESC_PTR_2(port) (0x26c8 + (port<<10))
-#define MV643XX_ETH_TX_CURRENT_QUEUE_DESC_PTR_3(port) (0x26cc + (port<<10))
-#define MV643XX_ETH_TX_CURRENT_QUEUE_DESC_PTR_4(port) (0x26d0 + (port<<10))
-#define MV643XX_ETH_TX_CURRENT_QUEUE_DESC_PTR_5(port) (0x26d4 + (port<<10))
-#define MV643XX_ETH_TX_CURRENT_QUEUE_DESC_PTR_6(port) (0x26d8 + (port<<10))
-#define MV643XX_ETH_TX_CURRENT_QUEUE_DESC_PTR_7(port) (0x26dc + (port<<10))
-#define MV643XX_ETH_TX_QUEUE_0_TOKEN_BUCKET_COUNT(port) (0x2700 + (port<<10))
-#define MV643XX_ETH_TX_QUEUE_1_TOKEN_BUCKET_COUNT(port) (0x2710 + (port<<10))
-#define MV643XX_ETH_TX_QUEUE_2_TOKEN_BUCKET_COUNT(port) (0x2720 + (port<<10))
-#define MV643XX_ETH_TX_QUEUE_3_TOKEN_BUCKET_COUNT(port) (0x2730 + (port<<10))
-#define MV643XX_ETH_TX_QUEUE_4_TOKEN_BUCKET_COUNT(port) (0x2740 + (port<<10))
-#define MV643XX_ETH_TX_QUEUE_5_TOKEN_BUCKET_COUNT(port) (0x2750 + (port<<10))
-#define MV643XX_ETH_TX_QUEUE_6_TOKEN_BUCKET_COUNT(port) (0x2760 + (port<<10))
-#define MV643XX_ETH_TX_QUEUE_7_TOKEN_BUCKET_COUNT(port) (0x2770 + (port<<10))
-#define MV643XX_ETH_TX_QUEUE_0_TOKEN_BUCKET_CONFIG(port) (0x2704 + (port<<10))
-#define MV643XX_ETH_TX_QUEUE_1_TOKEN_BUCKET_CONFIG(port) (0x2714 + (port<<10))
-#define MV643XX_ETH_TX_QUEUE_2_TOKEN_BUCKET_CONFIG(port) (0x2724 + (port<<10))
-#define MV643XX_ETH_TX_QUEUE_3_TOKEN_BUCKET_CONFIG(port) (0x2734 + (port<<10))
-#define MV643XX_ETH_TX_QUEUE_4_TOKEN_BUCKET_CONFIG(port) (0x2744 + (port<<10))
-#define MV643XX_ETH_TX_QUEUE_5_TOKEN_BUCKET_CONFIG(port) (0x2754 + (port<<10))
-#define MV643XX_ETH_TX_QUEUE_6_TOKEN_BUCKET_CONFIG(port) (0x2764 + (port<<10))
-#define MV643XX_ETH_TX_QUEUE_7_TOKEN_BUCKET_CONFIG(port) (0x2774 + (port<<10))
-#define MV643XX_ETH_TX_QUEUE_0_ARBITER_CONFIG(port) (0x2708 + (port<<10))
-#define MV643XX_ETH_TX_QUEUE_1_ARBITER_CONFIG(port) (0x2718 + (port<<10))
-#define MV643XX_ETH_TX_QUEUE_2_ARBITER_CONFIG(port) (0x2728 + (port<<10))
-#define MV643XX_ETH_TX_QUEUE_3_ARBITER_CONFIG(port) (0x2738 + (port<<10))
-#define MV643XX_ETH_TX_QUEUE_4_ARBITER_CONFIG(port) (0x2748 + (port<<10))
-#define MV643XX_ETH_TX_QUEUE_5_ARBITER_CONFIG(port) (0x2758 + (port<<10))
-#define MV643XX_ETH_TX_QUEUE_6_ARBITER_CONFIG(port) (0x2768 + (port<<10))
-#define MV643XX_ETH_TX_QUEUE_7_ARBITER_CONFIG(port) (0x2778 + (port<<10))
-#define MV643XX_ETH_PORT_TX_TOKEN_BUCKET_COUNT(port) (0x2780 + (port<<10))
-#define MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(port) (0x3400 + (port<<10))
-#define MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(port) (0x3500 + (port<<10))
-#define MV643XX_ETH_DA_FILTER_UNICAST_TABLE_BASE(port) (0x3600 + (port<<10))
-
/*******************************************/
/* CUNIT Registers */
/*******************************************/
@@ -1089,219 +976,6 @@ struct mv64xxx_i2c_pdata {
u32 retries;
};
-/* These macros describe Ethernet Port configuration reg (Px_cR) bits */
-#define MV643XX_ETH_UNICAST_NORMAL_MODE 0
-#define MV643XX_ETH_UNICAST_PROMISCUOUS_MODE (1<<0)
-#define MV643XX_ETH_DEFAULT_RX_QUEUE_0 0
-#define MV643XX_ETH_DEFAULT_RX_QUEUE_1 (1<<1)
-#define MV643XX_ETH_DEFAULT_RX_QUEUE_2 (1<<2)
-#define MV643XX_ETH_DEFAULT_RX_QUEUE_3 ((1<<2) | (1<<1))
-#define MV643XX_ETH_DEFAULT_RX_QUEUE_4 (1<<3)
-#define MV643XX_ETH_DEFAULT_RX_QUEUE_5 ((1<<3) | (1<<1))
-#define MV643XX_ETH_DEFAULT_RX_QUEUE_6 ((1<<3) | (1<<2))
-#define MV643XX_ETH_DEFAULT_RX_QUEUE_7 ((1<<3) | (1<<2) | (1<<1))
-#define MV643XX_ETH_DEFAULT_RX_ARP_QUEUE_0 0
-#define MV643XX_ETH_DEFAULT_RX_ARP_QUEUE_1 (1<<4)
-#define MV643XX_ETH_DEFAULT_RX_ARP_QUEUE_2 (1<<5)
-#define MV643XX_ETH_DEFAULT_RX_ARP_QUEUE_3 ((1<<5) | (1<<4))
-#define MV643XX_ETH_DEFAULT_RX_ARP_QUEUE_4 (1<<6)
-#define MV643XX_ETH_DEFAULT_RX_ARP_QUEUE_5 ((1<<6) | (1<<4))
-#define MV643XX_ETH_DEFAULT_RX_ARP_QUEUE_6 ((1<<6) | (1<<5))
-#define MV643XX_ETH_DEFAULT_RX_ARP_QUEUE_7 ((1<<6) | (1<<5) | (1<<4))
-#define MV643XX_ETH_RECEIVE_BC_IF_NOT_IP_OR_ARP 0
-#define MV643XX_ETH_REJECT_BC_IF_NOT_IP_OR_ARP (1<<7)
-#define MV643XX_ETH_RECEIVE_BC_IF_IP 0
-#define MV643XX_ETH_REJECT_BC_IF_IP (1<<8)
-#define MV643XX_ETH_RECEIVE_BC_IF_ARP 0
-#define MV643XX_ETH_REJECT_BC_IF_ARP (1<<9)
-#define MV643XX_ETH_TX_AM_NO_UPDATE_ERROR_SUMMARY (1<<12)
-#define MV643XX_ETH_CAPTURE_TCP_FRAMES_DIS 0
-#define MV643XX_ETH_CAPTURE_TCP_FRAMES_EN (1<<14)
-#define MV643XX_ETH_CAPTURE_UDP_FRAMES_DIS 0
-#define MV643XX_ETH_CAPTURE_UDP_FRAMES_EN (1<<15)
-#define MV643XX_ETH_DEFAULT_RX_TCP_QUEUE_0 0
-#define MV643XX_ETH_DEFAULT_RX_TCP_QUEUE_1 (1<<16)
-#define MV643XX_ETH_DEFAULT_RX_TCP_QUEUE_2 (1<<17)
-#define MV643XX_ETH_DEFAULT_RX_TCP_QUEUE_3 ((1<<17) | (1<<16))
-#define MV643XX_ETH_DEFAULT_RX_TCP_QUEUE_4 (1<<18)
-#define MV643XX_ETH_DEFAULT_RX_TCP_QUEUE_5 ((1<<18) | (1<<16))
-#define MV643XX_ETH_DEFAULT_RX_TCP_QUEUE_6 ((1<<18) | (1<<17))
-#define MV643XX_ETH_DEFAULT_RX_TCP_QUEUE_7 ((1<<18) | (1<<17) | (1<<16))
-#define MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_0 0
-#define MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_1 (1<<19)
-#define MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_2 (1<<20)
-#define MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_3 ((1<<20) | (1<<19))
-#define MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_4 (1<<21)
-#define MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_5 ((1<<21) | (1<<19))
-#define MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_6 ((1<<21) | (1<<20))
-#define MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_7 ((1<<21) | (1<<20) | (1<<19))
-#define MV643XX_ETH_DEFAULT_RX_BPDU_QUEUE_0 0
-#define MV643XX_ETH_DEFAULT_RX_BPDU_QUEUE_1 (1<<22)
-#define MV643XX_ETH_DEFAULT_RX_BPDU_QUEUE_2 (1<<23)
-#define MV643XX_ETH_DEFAULT_RX_BPDU_QUEUE_3 ((1<<23) | (1<<22))
-#define MV643XX_ETH_DEFAULT_RX_BPDU_QUEUE_4 (1<<24)
-#define MV643XX_ETH_DEFAULT_RX_BPDU_QUEUE_5 ((1<<24) | (1<<22))
-#define MV643XX_ETH_DEFAULT_RX_BPDU_QUEUE_6 ((1<<24) | (1<<23))
-#define MV643XX_ETH_DEFAULT_RX_BPDU_QUEUE_7 ((1<<24) | (1<<23) | (1<<22))
-
-#define MV643XX_ETH_PORT_CONFIG_DEFAULT_VALUE \
- MV643XX_ETH_UNICAST_NORMAL_MODE | \
- MV643XX_ETH_DEFAULT_RX_QUEUE_0 | \
- MV643XX_ETH_DEFAULT_RX_ARP_QUEUE_0 | \
- MV643XX_ETH_RECEIVE_BC_IF_NOT_IP_OR_ARP | \
- MV643XX_ETH_RECEIVE_BC_IF_IP | \
- MV643XX_ETH_RECEIVE_BC_IF_ARP | \
- MV643XX_ETH_CAPTURE_TCP_FRAMES_DIS | \
- MV643XX_ETH_CAPTURE_UDP_FRAMES_DIS | \
- MV643XX_ETH_DEFAULT_RX_TCP_QUEUE_0 | \
- MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_0 | \
- MV643XX_ETH_DEFAULT_RX_BPDU_QUEUE_0
-
-/* These macros describe Ethernet Port configuration extend reg (Px_cXR) bits*/
-#define MV643XX_ETH_CLASSIFY_EN (1<<0)
-#define MV643XX_ETH_SPAN_BPDU_PACKETS_AS_NORMAL 0
-#define MV643XX_ETH_SPAN_BPDU_PACKETS_TO_RX_QUEUE_7 (1<<1)
-#define MV643XX_ETH_PARTITION_DISABLE 0
-#define MV643XX_ETH_PARTITION_ENABLE (1<<2)
-
-#define MV643XX_ETH_PORT_CONFIG_EXTEND_DEFAULT_VALUE \
- MV643XX_ETH_SPAN_BPDU_PACKETS_AS_NORMAL | \
- MV643XX_ETH_PARTITION_DISABLE
-
-/* These macros describe Ethernet Port Sdma configuration reg (SDCR) bits */
-#define MV643XX_ETH_RIFB (1<<0)
-#define MV643XX_ETH_RX_BURST_SIZE_1_64BIT 0
-#define MV643XX_ETH_RX_BURST_SIZE_2_64BIT (1<<1)
-#define MV643XX_ETH_RX_BURST_SIZE_4_64BIT (1<<2)
-#define MV643XX_ETH_RX_BURST_SIZE_8_64BIT ((1<<2) | (1<<1))
-#define MV643XX_ETH_RX_BURST_SIZE_16_64BIT (1<<3)
-#define MV643XX_ETH_BLM_RX_NO_SWAP (1<<4)
-#define MV643XX_ETH_BLM_RX_BYTE_SWAP 0
-#define MV643XX_ETH_BLM_TX_NO_SWAP (1<<5)
-#define MV643XX_ETH_BLM_TX_BYTE_SWAP 0
-#define MV643XX_ETH_DESCRIPTORS_BYTE_SWAP (1<<6)
-#define MV643XX_ETH_DESCRIPTORS_NO_SWAP 0
-#define MV643XX_ETH_TX_BURST_SIZE_1_64BIT 0
-#define MV643XX_ETH_TX_BURST_SIZE_2_64BIT (1<<22)
-#define MV643XX_ETH_TX_BURST_SIZE_4_64BIT (1<<23)
-#define MV643XX_ETH_TX_BURST_SIZE_8_64BIT ((1<<23) | (1<<22))
-#define MV643XX_ETH_TX_BURST_SIZE_16_64BIT (1<<24)
-
-#define MV643XX_ETH_IPG_INT_RX(value) ((value & 0x3fff) << 8)
-
-#define MV643XX_ETH_PORT_SDMA_CONFIG_DEFAULT_VALUE \
- MV643XX_ETH_RX_BURST_SIZE_4_64BIT | \
- MV643XX_ETH_IPG_INT_RX(0) | \
- MV643XX_ETH_TX_BURST_SIZE_4_64BIT
-
-/* These macros describe Ethernet Port serial control reg (PSCR) bits */
-#define MV643XX_ETH_SERIAL_PORT_DISABLE 0
-#define MV643XX_ETH_SERIAL_PORT_ENABLE (1<<0)
-#define MV643XX_ETH_FORCE_LINK_PASS (1<<1)
-#define MV643XX_ETH_DO_NOT_FORCE_LINK_PASS 0
-#define MV643XX_ETH_ENABLE_AUTO_NEG_FOR_DUPLX 0
-#define MV643XX_ETH_DISABLE_AUTO_NEG_FOR_DUPLX (1<<2)
-#define MV643XX_ETH_ENABLE_AUTO_NEG_FOR_FLOW_CTRL 0
-#define MV643XX_ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL (1<<3)
-#define MV643XX_ETH_ADV_NO_FLOW_CTRL 0
-#define MV643XX_ETH_ADV_SYMMETRIC_FLOW_CTRL (1<<4)
-#define MV643XX_ETH_FORCE_FC_MODE_NO_PAUSE_DIS_TX 0
-#define MV643XX_ETH_FORCE_FC_MODE_TX_PAUSE_DIS (1<<5)
-#define MV643XX_ETH_FORCE_BP_MODE_NO_JAM 0
-#define MV643XX_ETH_FORCE_BP_MODE_JAM_TX (1<<7)
-#define MV643XX_ETH_FORCE_BP_MODE_JAM_TX_ON_RX_ERR (1<<8)
-#define MV643XX_ETH_SERIAL_PORT_CONTROL_RESERVED (1<<9)
-#define MV643XX_ETH_FORCE_LINK_FAIL 0
-#define MV643XX_ETH_DO_NOT_FORCE_LINK_FAIL (1<<10)
-#define MV643XX_ETH_RETRANSMIT_16_ATTEMPTS 0
-#define MV643XX_ETH_RETRANSMIT_FOREVER (1<<11)
-#define MV643XX_ETH_DISABLE_AUTO_NEG_SPEED_GMII (1<<13)
-#define MV643XX_ETH_ENABLE_AUTO_NEG_SPEED_GMII 0
-#define MV643XX_ETH_DTE_ADV_0 0
-#define MV643XX_ETH_DTE_ADV_1 (1<<14)
-#define MV643XX_ETH_DISABLE_AUTO_NEG_BYPASS 0
-#define MV643XX_ETH_ENABLE_AUTO_NEG_BYPASS (1<<15)
-#define MV643XX_ETH_AUTO_NEG_NO_CHANGE 0
-#define MV643XX_ETH_RESTART_AUTO_NEG (1<<16)
-#define MV643XX_ETH_MAX_RX_PACKET_1518BYTE 0
-#define MV643XX_ETH_MAX_RX_PACKET_1522BYTE (1<<17)
-#define MV643XX_ETH_MAX_RX_PACKET_1552BYTE (1<<18)
-#define MV643XX_ETH_MAX_RX_PACKET_9022BYTE ((1<<18) | (1<<17))
-#define MV643XX_ETH_MAX_RX_PACKET_9192BYTE (1<<19)
-#define MV643XX_ETH_MAX_RX_PACKET_9700BYTE ((1<<19) | (1<<17))
-#define MV643XX_ETH_SET_EXT_LOOPBACK (1<<20)
-#define MV643XX_ETH_CLR_EXT_LOOPBACK 0
-#define MV643XX_ETH_SET_FULL_DUPLEX_MODE (1<<21)
-#define MV643XX_ETH_SET_HALF_DUPLEX_MODE 0
-#define MV643XX_ETH_ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX (1<<22)
-#define MV643XX_ETH_DISABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX 0
-#define MV643XX_ETH_SET_GMII_SPEED_TO_10_100 0
-#define MV643XX_ETH_SET_GMII_SPEED_TO_1000 (1<<23)
-#define MV643XX_ETH_SET_MII_SPEED_TO_10 0
-#define MV643XX_ETH_SET_MII_SPEED_TO_100 (1<<24)
-
-#define MV643XX_ETH_MAX_RX_PACKET_MASK (0x7<<17)
-
-#define MV643XX_ETH_PORT_SERIAL_CONTROL_DEFAULT_VALUE \
- MV643XX_ETH_DO_NOT_FORCE_LINK_PASS | \
- MV643XX_ETH_ENABLE_AUTO_NEG_FOR_DUPLX | \
- MV643XX_ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL | \
- MV643XX_ETH_ADV_SYMMETRIC_FLOW_CTRL | \
- MV643XX_ETH_FORCE_FC_MODE_NO_PAUSE_DIS_TX | \
- MV643XX_ETH_FORCE_BP_MODE_NO_JAM | \
- (1<<9) /* reserved */ | \
- MV643XX_ETH_DO_NOT_FORCE_LINK_FAIL | \
- MV643XX_ETH_RETRANSMIT_16_ATTEMPTS | \
- MV643XX_ETH_ENABLE_AUTO_NEG_SPEED_GMII | \
- MV643XX_ETH_DTE_ADV_0 | \
- MV643XX_ETH_DISABLE_AUTO_NEG_BYPASS | \
- MV643XX_ETH_AUTO_NEG_NO_CHANGE | \
- MV643XX_ETH_MAX_RX_PACKET_9700BYTE | \
- MV643XX_ETH_CLR_EXT_LOOPBACK | \
- MV643XX_ETH_SET_FULL_DUPLEX_MODE | \
- MV643XX_ETH_ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX
-
-/* These macros describe Ethernet Serial Status reg (PSR) bits */
-#define MV643XX_ETH_PORT_STATUS_MODE_10_BIT (1<<0)
-#define MV643XX_ETH_PORT_STATUS_LINK_UP (1<<1)
-#define MV643XX_ETH_PORT_STATUS_FULL_DUPLEX (1<<2)
-#define MV643XX_ETH_PORT_STATUS_FLOW_CONTROL (1<<3)
-#define MV643XX_ETH_PORT_STATUS_GMII_1000 (1<<4)
-#define MV643XX_ETH_PORT_STATUS_MII_100 (1<<5)
-/* PSR bit 6 is undocumented */
-#define MV643XX_ETH_PORT_STATUS_TX_IN_PROGRESS (1<<7)
-#define MV643XX_ETH_PORT_STATUS_AUTONEG_BYPASSED (1<<8)
-#define MV643XX_ETH_PORT_STATUS_PARTITION (1<<9)
-#define MV643XX_ETH_PORT_STATUS_TX_FIFO_EMPTY (1<<10)
-/* PSR bits 11-31 are reserved */
-
-#define MV643XX_ETH_PORT_DEFAULT_TRANSMIT_QUEUE_SIZE 800
-#define MV643XX_ETH_PORT_DEFAULT_RECEIVE_QUEUE_SIZE 400
-
-#define MV643XX_ETH_DESC_SIZE 64
-
-#define MV643XX_ETH_SHARED_NAME "mv643xx_eth_shared"
-#define MV643XX_ETH_NAME "mv643xx_eth"
-
-struct mv643xx_eth_platform_data {
- int port_number;
- u16 force_phy_addr; /* force override if phy_addr == 0 */
- u16 phy_addr;
-
- /* If speed is 0, then speed and duplex are autonegotiated. */
- int speed; /* 0, SPEED_10, SPEED_100, SPEED_1000 */
- int duplex; /* DUPLEX_HALF or DUPLEX_FULL */
-
- /* non-zero values of the following fields override defaults */
- u32 tx_queue_size;
- u32 rx_queue_size;
- u32 tx_sram_addr;
- u32 tx_sram_size;
- u32 rx_sram_addr;
- u32 rx_sram_size;
- u8 mac_addr[6]; /* mac address if non-zero*/
-};
-
/* Watchdog Platform Device, Driver Data */
#define MV64x60_WDT_NAME "mv64x60_wdt"
diff --git a/include/linux/mv643xx_eth.h b/include/linux/mv643xx_eth.h
new file mode 100644
index 000000000000..30e11aa3c1c9
--- /dev/null
+++ b/include/linux/mv643xx_eth.h
@@ -0,0 +1,34 @@
+/*
+ * MV-643XX ethernet platform device data definition file.
+ */
+#ifndef __LINUX_MV643XX_ETH_H
+#define __LINUX_MV643XX_ETH_H
+
+#define MV643XX_ETH_SHARED_NAME "mv643xx_eth_shared"
+#define MV643XX_ETH_NAME "mv643xx_eth"
+#define MV643XX_ETH_SHARED_REGS 0x2000
+#define MV643XX_ETH_SHARED_REGS_SIZE 0x2000
+#define MV643XX_ETH_BAR_4 0x2220
+#define MV643XX_ETH_SIZE_REG_4 0x2224
+#define MV643XX_ETH_BASE_ADDR_ENABLE_REG 0x2290
+
+struct mv643xx_eth_platform_data {
+ int port_number;
+ u16 force_phy_addr; /* force override if phy_addr == 0 */
+ u16 phy_addr;
+
+ /* If speed is 0, then speed and duplex are autonegotiated. */
+ int speed; /* 0, SPEED_10, SPEED_100, SPEED_1000 */
+ int duplex; /* DUPLEX_HALF or DUPLEX_FULL */
+
+ /* non-zero values of the following fields override defaults */
+ u32 tx_queue_size;
+ u32 rx_queue_size;
+ u32 tx_sram_addr;
+ u32 tx_sram_size;
+ u32 rx_sram_addr;
+ u32 rx_sram_size;
+ u8 mac_addr[6]; /* mac address if non-zero*/
+};
+
+#endif /* __LINUX_MV643XX_ETH_H */
diff --git a/include/linux/namei.h b/include/linux/namei.h
index 6c38efbd810f..4cb4f8d2f78d 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -81,8 +81,8 @@ extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry
extern struct file *nameidata_to_filp(struct nameidata *nd, int flags);
extern void release_open_intent(struct nameidata *);
-extern struct dentry * lookup_one_len(const char *, struct dentry *, int);
-extern struct dentry *lookup_one_len_kern(const char *, struct dentry *, int);
+extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
+extern struct dentry *lookup_one_noperm(const char *, struct dentry *);
extern int follow_down(struct vfsmount **, struct dentry **);
extern int follow_up(struct vfsmount **, struct dentry **);
diff --git a/include/linux/nbd.h b/include/linux/nbd.h
index 0f3e69302540..cc2b47240a8f 100644
--- a/include/linux/nbd.h
+++ b/include/linux/nbd.h
@@ -26,6 +26,7 @@
#define NBD_PRINT_DEBUG _IO( 0xab, 6 )
#define NBD_SET_SIZE_BLOCKS _IO( 0xab, 7 )
#define NBD_DISCONNECT _IO( 0xab, 8 )
+#define NBD_SET_TIMEOUT _IO( 0xab, 9 )
enum {
NBD_CMD_READ = 0,
@@ -65,6 +66,7 @@ struct nbd_device {
int blksize;
u64 bytesize;
pid_t pid; /* pid of nbd-client, if attached */
+ int xmit_timeout;
};
#endif
diff --git a/include/linux/net.h b/include/linux/net.h
index c136abce7ef6..596131ea46f4 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -95,6 +95,12 @@ enum sock_type {
#endif /* ARCH_HAS_SOCKET_TYPES */
+enum sock_shutdown_cmd {
+ SHUT_RD = 0,
+ SHUT_WR = 1,
+ SHUT_RDWR = 2,
+};
+
/**
* struct socket - general BSD socket
* @state: socket state (%SS_CONNECTED, etc)
@@ -223,6 +229,8 @@ extern int kernel_setsockopt(struct socket *sock, int level, int optname,
extern int kernel_sendpage(struct socket *sock, struct page *page, int offset,
size_t size, int flags);
extern int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg);
+extern int kernel_sock_shutdown(struct socket *sock,
+ enum sock_shutdown_cmd how);
#ifndef CONFIG_SMP
#define SOCKOPS_WRAPPED(name) name
@@ -313,6 +321,10 @@ static const struct proto_ops name##_ops = { \
#define MODULE_ALIAS_NET_PF_PROTO(pf, proto) \
MODULE_ALIAS("net-pf-" __stringify(pf) "-proto-" __stringify(proto))
+#define MODULE_ALIAS_NET_PF_PROTO_TYPE(pf, proto, type) \
+ MODULE_ALIAS("net-pf-" __stringify(pf) "-proto-" __stringify(proto) \
+ "-type-" __stringify(type))
+
#ifdef CONFIG_SYSCTL
#include <linux/sysctl.h>
extern ctl_table net_table[];
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 39dd83b183a9..1e6af4f174b6 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -390,7 +390,7 @@ static inline void napi_complete(struct napi_struct *n)
static inline void napi_disable(struct napi_struct *n)
{
while (test_and_set_bit(NAPI_STATE_SCHED, &n->state))
- msleep_interruptible(1);
+ msleep(1);
}
/**
@@ -407,6 +407,24 @@ static inline void napi_enable(struct napi_struct *n)
clear_bit(NAPI_STATE_SCHED, &n->state);
}
+#ifdef CONFIG_SMP
+/**
+ * napi_synchronize - wait until NAPI is not running
+ * @n: napi context
+ *
+ * Wait until NAPI is done being scheduled on this context.
+ * Waits till any outstanding processing completes but
+ * does not disable future activations.
+ */
+static inline void napi_synchronize(const struct napi_struct *n)
+{
+ while (test_bit(NAPI_STATE_SCHED, &n->state))
+ msleep(1);
+}
+#else
+# define napi_synchronize(n) barrier()
+#endif
+
/*
* The DEVICE structure.
* Actually, this whole structure is a big mistake. It mixes I/O
@@ -651,6 +669,8 @@ struct net_device
#define HAVE_SET_MAC_ADDR
int (*set_mac_address)(struct net_device *dev,
void *addr);
+#define HAVE_VALIDATE_ADDR
+ int (*validate_addr)(struct net_device *dev);
#define HAVE_PRIVATE_IOCTL
int (*do_ioctl)(struct net_device *dev,
struct ifreq *ifr, int cmd);
@@ -719,6 +739,16 @@ static inline void *netdev_priv(const struct net_device *dev)
*/
#define SET_NETDEV_DEV(net, pdev) ((net)->dev.parent = (pdev))
+/**
+ * netif_napi_add - initialize a napi context
+ * @dev: network device
+ * @napi: napi context
+ * @poll: polling function
+ * @weight: default weight
+ *
+ * netif_napi_add() must be used to initialize a napi context prior to calling
+ * *any* of the other napi related functions.
+ */
static inline void netif_napi_add(struct net_device *dev,
struct napi_struct *napi,
int (*poll)(struct napi_struct *, int),
@@ -816,7 +846,7 @@ static inline int dev_hard_header(struct sk_buff *skb, struct net_device *dev,
const void *daddr, const void *saddr,
unsigned len)
{
- if (!dev->header_ops)
+ if (!dev->header_ops || !dev->header_ops->create)
return 0;
return dev->header_ops->create(skb, dev, type, daddr, saddr, len);
@@ -827,7 +857,7 @@ static inline int dev_parse_header(const struct sk_buff *skb,
{
const struct net_device *dev = skb->dev;
- if (!dev->header_ops->parse)
+ if (!dev->header_ops || !dev->header_ops->parse)
return 0;
return dev->header_ops->parse(skb, haddr);
}
@@ -978,7 +1008,7 @@ static inline void netif_stop_subqueue(struct net_device *dev, u16 queue_index)
*
* Check individual transmit queue of a device with multiple transmit queues.
*/
-static inline int netif_subqueue_stopped(const struct net_device *dev,
+static inline int __netif_subqueue_stopped(const struct net_device *dev,
u16 queue_index)
{
#ifdef CONFIG_NETDEVICES_MULTIQUEUE
@@ -989,6 +1019,11 @@ static inline int netif_subqueue_stopped(const struct net_device *dev,
#endif
}
+static inline int netif_subqueue_stopped(const struct net_device *dev,
+ struct sk_buff *skb)
+{
+ return __netif_subqueue_stopped(dev, skb_get_queue_mapping(skb));
+}
/**
* netif_wake_subqueue - allow sending packets on subqueue
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index 1dd075eda595..16adac688af5 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -51,7 +51,7 @@ struct sk_buff;
struct net_device;
typedef unsigned int nf_hookfn(unsigned int hooknum,
- struct sk_buff **skb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *));
@@ -183,7 +183,7 @@ void nf_log_packet(int pf,
struct nf_loginfo *li,
const char *fmt, ...);
-int nf_hook_slow(int pf, unsigned int hook, struct sk_buff **pskb,
+int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
struct net_device *indev, struct net_device *outdev,
int (*okfn)(struct sk_buff *), int thresh);
@@ -195,7 +195,7 @@ int nf_hook_slow(int pf, unsigned int hook, struct sk_buff **pskb,
* value indicates the packet has been consumed by the hook.
*/
static inline int nf_hook_thresh(int pf, unsigned int hook,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
struct net_device *indev,
struct net_device *outdev,
int (*okfn)(struct sk_buff *), int thresh,
@@ -207,14 +207,14 @@ static inline int nf_hook_thresh(int pf, unsigned int hook,
if (list_empty(&nf_hooks[pf][hook]))
return 1;
#endif
- return nf_hook_slow(pf, hook, pskb, indev, outdev, okfn, thresh);
+ return nf_hook_slow(pf, hook, skb, indev, outdev, okfn, thresh);
}
-static inline int nf_hook(int pf, unsigned int hook, struct sk_buff **pskb,
+static inline int nf_hook(int pf, unsigned int hook, struct sk_buff *skb,
struct net_device *indev, struct net_device *outdev,
int (*okfn)(struct sk_buff *))
{
- return nf_hook_thresh(pf, hook, pskb, indev, outdev, okfn, INT_MIN, 1);
+ return nf_hook_thresh(pf, hook, skb, indev, outdev, okfn, INT_MIN, 1);
}
/* Activate hook; either okfn or kfree_skb called, unless a hook
@@ -241,13 +241,13 @@ static inline int nf_hook(int pf, unsigned int hook, struct sk_buff **pskb,
#define NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, thresh) \
({int __ret; \
-if ((__ret=nf_hook_thresh(pf, hook, &(skb), indev, outdev, okfn, thresh, 1)) == 1)\
+if ((__ret=nf_hook_thresh(pf, hook, (skb), indev, outdev, okfn, thresh, 1)) == 1)\
__ret = (okfn)(skb); \
__ret;})
#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) \
({int __ret; \
-if ((__ret=nf_hook_thresh(pf, hook, &(skb), indev, outdev, okfn, INT_MIN, cond)) == 1)\
+if ((__ret=nf_hook_thresh(pf, hook, (skb), indev, outdev, okfn, INT_MIN, cond)) == 1)\
__ret = (okfn)(skb); \
__ret;})
@@ -287,7 +287,7 @@ extern void nf_invalidate_cache(int pf);
/* Call this before modifying an existing packet: ensures it is
modifiable and linear to the point you care about (writable_len).
Returns true or false. */
-extern int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len);
+extern int skb_make_writable(struct sk_buff *skb, unsigned int writable_len);
static inline void nf_csum_replace4(__sum16 *sum, __be32 from, __be32 to)
{
@@ -317,7 +317,7 @@ struct nf_afinfo {
unsigned int dataoff, u_int8_t protocol);
void (*saveroute)(const struct sk_buff *skb,
struct nf_info *info);
- int (*reroute)(struct sk_buff **skb,
+ int (*reroute)(struct sk_buff *skb,
const struct nf_info *info);
int route_key_size;
};
@@ -371,15 +371,15 @@ extern struct proc_dir_entry *proc_net_netfilter;
#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb)
static inline int nf_hook_thresh(int pf, unsigned int hook,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
struct net_device *indev,
struct net_device *outdev,
int (*okfn)(struct sk_buff *), int thresh,
int cond)
{
- return okfn(*pskb);
+ return okfn(skb);
}
-static inline int nf_hook(int pf, unsigned int hook, struct sk_buff **pskb,
+static inline int nf_hook(int pf, unsigned int hook, struct sk_buff *skb,
struct net_device *indev, struct net_device *outdev,
int (*okfn)(struct sk_buff *))
{
diff --git a/include/linux/netfilter/Kbuild b/include/linux/netfilter/Kbuild
index f2eaea2234ec..b87e83a5e070 100644
--- a/include/linux/netfilter/Kbuild
+++ b/include/linux/netfilter/Kbuild
@@ -4,25 +4,28 @@ header-y += nfnetlink_conntrack.h
header-y += nfnetlink_log.h
header-y += nfnetlink_queue.h
header-y += xt_CLASSIFY.h
+header-y += xt_CONNMARK.h
+header-y += xt_CONNSECMARK.h
+header-y += xt_DSCP.h
+header-y += xt_MARK.h
+header-y += xt_NFLOG.h
+header-y += xt_NFQUEUE.h
+header-y += xt_SECMARK.h
+header-y += xt_TCPMSS.h
header-y += xt_comment.h
header-y += xt_connbytes.h
header-y += xt_connmark.h
-header-y += xt_CONNMARK.h
header-y += xt_conntrack.h
header-y += xt_dccp.h
header-y += xt_dscp.h
-header-y += xt_DSCP.h
header-y += xt_esp.h
-header-y += xt_helper.h
header-y += xt_hashlimit.h
+header-y += xt_helper.h
header-y += xt_length.h
header-y += xt_limit.h
header-y += xt_mac.h
header-y += xt_mark.h
-header-y += xt_MARK.h
header-y += xt_multiport.h
-header-y += xt_NFQUEUE.h
-header-y += xt_NFLOG.h
header-y += xt_pkttype.h
header-y += xt_policy.h
header-y += xt_realm.h
@@ -32,9 +35,6 @@ header-y += xt_statistic.h
header-y += xt_string.h
header-y += xt_tcpmss.h
header-y += xt_tcpudp.h
-header-y += xt_SECMARK.h
-header-y += xt_CONNSECMARK.h
-header-y += xt_TCPMSS.h
unifdef-y += nf_conntrack_common.h
unifdef-y += nf_conntrack_ftp.h
diff --git a/include/linux/netfilter/nf_conntrack_amanda.h b/include/linux/netfilter/nf_conntrack_amanda.h
index 26c223544ae8..0bb5a6976bf3 100644
--- a/include/linux/netfilter/nf_conntrack_amanda.h
+++ b/include/linux/netfilter/nf_conntrack_amanda.h
@@ -2,7 +2,7 @@
#define _NF_CONNTRACK_AMANDA_H
/* AMANDA tracking. */
-extern unsigned int (*nf_nat_amanda_hook)(struct sk_buff **pskb,
+extern unsigned int (*nf_nat_amanda_hook)(struct sk_buff *skb,
enum ip_conntrack_info ctinfo,
unsigned int matchoff,
unsigned int matchlen,
diff --git a/include/linux/netfilter/nf_conntrack_ftp.h b/include/linux/netfilter/nf_conntrack_ftp.h
index b7c360ffd0d0..47727d7546ea 100644
--- a/include/linux/netfilter/nf_conntrack_ftp.h
+++ b/include/linux/netfilter/nf_conntrack_ftp.h
@@ -32,7 +32,7 @@ struct nf_conntrack_expect;
/* For NAT to hook in when we find a packet which describes what other
* connection we should expect. */
-extern unsigned int (*nf_nat_ftp_hook)(struct sk_buff **pskb,
+extern unsigned int (*nf_nat_ftp_hook)(struct sk_buff *skb,
enum ip_conntrack_info ctinfo,
enum nf_ct_ftp_type type,
unsigned int matchoff,
diff --git a/include/linux/netfilter/nf_conntrack_h323.h b/include/linux/netfilter/nf_conntrack_h323.h
index 08e2f4977c2e..aabd24ac7631 100644
--- a/include/linux/netfilter/nf_conntrack_h323.h
+++ b/include/linux/netfilter/nf_conntrack_h323.h
@@ -36,27 +36,27 @@ extern void nf_conntrack_h245_expect(struct nf_conn *new,
struct nf_conntrack_expect *this);
extern void nf_conntrack_q931_expect(struct nf_conn *new,
struct nf_conntrack_expect *this);
-extern int (*set_h245_addr_hook) (struct sk_buff **pskb,
+extern int (*set_h245_addr_hook) (struct sk_buff *skb,
unsigned char **data, int dataoff,
H245_TransportAddress *taddr,
union nf_conntrack_address *addr,
__be16 port);
-extern int (*set_h225_addr_hook) (struct sk_buff **pskb,
+extern int (*set_h225_addr_hook) (struct sk_buff *skb,
unsigned char **data, int dataoff,
TransportAddress *taddr,
union nf_conntrack_address *addr,
__be16 port);
-extern int (*set_sig_addr_hook) (struct sk_buff **pskb,
+extern int (*set_sig_addr_hook) (struct sk_buff *skb,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data,
TransportAddress *taddr, int count);
-extern int (*set_ras_addr_hook) (struct sk_buff **pskb,
+extern int (*set_ras_addr_hook) (struct sk_buff *skb,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data,
TransportAddress *taddr, int count);
-extern int (*nat_rtp_rtcp_hook) (struct sk_buff **pskb,
+extern int (*nat_rtp_rtcp_hook) (struct sk_buff *skb,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
@@ -64,24 +64,24 @@ extern int (*nat_rtp_rtcp_hook) (struct sk_buff **pskb,
__be16 port, __be16 rtp_port,
struct nf_conntrack_expect *rtp_exp,
struct nf_conntrack_expect *rtcp_exp);
-extern int (*nat_t120_hook) (struct sk_buff **pskb, struct nf_conn *ct,
+extern int (*nat_t120_hook) (struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
H245_TransportAddress *taddr, __be16 port,
struct nf_conntrack_expect *exp);
-extern int (*nat_h245_hook) (struct sk_buff **pskb, struct nf_conn *ct,
+extern int (*nat_h245_hook) (struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
TransportAddress *taddr, __be16 port,
struct nf_conntrack_expect *exp);
-extern int (*nat_callforwarding_hook) (struct sk_buff **pskb,
+extern int (*nat_callforwarding_hook) (struct sk_buff *skb,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
TransportAddress *taddr,
__be16 port,
struct nf_conntrack_expect *exp);
-extern int (*nat_q931_hook) (struct sk_buff **pskb, struct nf_conn *ct,
+extern int (*nat_q931_hook) (struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, TransportAddress *taddr,
int idx, __be16 port,
diff --git a/include/linux/netfilter/nf_conntrack_irc.h b/include/linux/netfilter/nf_conntrack_irc.h
index 2ab6b8255911..36282bf71b63 100644
--- a/include/linux/netfilter/nf_conntrack_irc.h
+++ b/include/linux/netfilter/nf_conntrack_irc.h
@@ -5,7 +5,7 @@
#define IRC_PORT 6667
-extern unsigned int (*nf_nat_irc_hook)(struct sk_buff **pskb,
+extern unsigned int (*nf_nat_irc_hook)(struct sk_buff *skb,
enum ip_conntrack_info ctinfo,
unsigned int matchoff,
unsigned int matchlen,
diff --git a/include/linux/netfilter/nf_conntrack_pptp.h b/include/linux/netfilter/nf_conntrack_pptp.h
index c93061f33144..23435496d24a 100644
--- a/include/linux/netfilter/nf_conntrack_pptp.h
+++ b/include/linux/netfilter/nf_conntrack_pptp.h
@@ -301,13 +301,13 @@ struct nf_conn;
struct nf_conntrack_expect;
extern int
-(*nf_nat_pptp_hook_outbound)(struct sk_buff **pskb,
+(*nf_nat_pptp_hook_outbound)(struct sk_buff *skb,
struct nf_conn *ct, enum ip_conntrack_info ctinfo,
struct PptpControlHeader *ctlh,
union pptp_ctrl_union *pptpReq);
extern int
-(*nf_nat_pptp_hook_inbound)(struct sk_buff **pskb,
+(*nf_nat_pptp_hook_inbound)(struct sk_buff *skb,
struct nf_conn *ct, enum ip_conntrack_info ctinfo,
struct PptpControlHeader *ctlh,
union pptp_ctrl_union *pptpReq);
diff --git a/include/linux/netfilter/nf_conntrack_sip.h b/include/linux/netfilter/nf_conntrack_sip.h
index bb7f2041db74..9fff19779bd5 100644
--- a/include/linux/netfilter/nf_conntrack_sip.h
+++ b/include/linux/netfilter/nf_conntrack_sip.h
@@ -21,11 +21,11 @@ enum sip_header_pos {
POS_SDP_HEADER,
};
-extern unsigned int (*nf_nat_sip_hook)(struct sk_buff **pskb,
+extern unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb,
enum ip_conntrack_info ctinfo,
struct nf_conn *ct,
const char **dptr);
-extern unsigned int (*nf_nat_sdp_hook)(struct sk_buff **pskb,
+extern unsigned int (*nf_nat_sdp_hook)(struct sk_buff *skb,
enum ip_conntrack_info ctinfo,
struct nf_conntrack_expect *exp,
const char *dptr);
diff --git a/include/linux/netfilter/nf_conntrack_tftp.h b/include/linux/netfilter/nf_conntrack_tftp.h
index 0d79b7ae051f..c78d38fdb050 100644
--- a/include/linux/netfilter/nf_conntrack_tftp.h
+++ b/include/linux/netfilter/nf_conntrack_tftp.h
@@ -13,7 +13,7 @@ struct tftphdr {
#define TFTP_OPCODE_ACK 4
#define TFTP_OPCODE_ERROR 5
-extern unsigned int (*nf_nat_tftp_hook)(struct sk_buff **pskb,
+extern unsigned int (*nf_nat_tftp_hook)(struct sk_buff *skb,
enum ip_conntrack_info ctinfo,
struct nf_conntrack_expect *exp);
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 64f425a855bb..03e6ce979eaa 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -191,7 +191,7 @@ struct xt_target
/* Returns verdict. Argument order changed since 2.6.9, as this
must now handle non-linear skbs, using skb_copy_bits and
skb_ip_make_writable. */
- unsigned int (*target)(struct sk_buff **pskb,
+ unsigned int (*target)(struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
unsigned int hooknum,
diff --git a/include/linux/netfilter/xt_sctp.h b/include/linux/netfilter/xt_sctp.h
index b157897e7792..dd5a4fd4cfd3 100644
--- a/include/linux/netfilter/xt_sctp.h
+++ b/include/linux/netfilter/xt_sctp.h
@@ -7,9 +7,6 @@
#define XT_SCTP_VALID_FLAGS 0x07
-#define ELEMCOUNT(x) (sizeof(x)/sizeof(x[0]))
-
-
struct xt_sctp_flag_info {
u_int8_t chunktype;
u_int8_t flag;
@@ -59,21 +56,21 @@ struct xt_sctp_info {
#define SCTP_CHUNKMAP_RESET(chunkmap) \
do { \
int i; \
- for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
+ for (i = 0; i < ARRAY_SIZE(chunkmap); i++) \
chunkmap[i] = 0; \
} while (0)
#define SCTP_CHUNKMAP_SET_ALL(chunkmap) \
do { \
int i; \
- for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
+ for (i = 0; i < ARRAY_SIZE(chunkmap); i++) \
chunkmap[i] = ~0; \
} while (0)
#define SCTP_CHUNKMAP_COPY(destmap, srcmap) \
do { \
int i; \
- for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
+ for (i = 0; i < ARRAY_SIZE(srcmap); i++) \
destmap[i] = srcmap[i]; \
} while (0)
@@ -81,7 +78,7 @@ struct xt_sctp_info {
({ \
int i; \
int flag = 1; \
- for (i = 0; i < ELEMCOUNT(chunkmap); i++) { \
+ for (i = 0; i < ARRAY_SIZE(chunkmap); i++) { \
if (chunkmap[i]) { \
flag = 0; \
break; \
@@ -94,7 +91,7 @@ struct xt_sctp_info {
({ \
int i; \
int flag = 1; \
- for (i = 0; i < ELEMCOUNT(chunkmap); i++) { \
+ for (i = 0; i < ARRAY_SIZE(chunkmap); i++) { \
if (chunkmap[i] != ~0) { \
flag = 0; \
break; \
diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h
index 584cd1b18f12..2fc73fa8e37f 100644
--- a/include/linux/netfilter_arp/arp_tables.h
+++ b/include/linux/netfilter_arp/arp_tables.h
@@ -287,7 +287,7 @@ struct arpt_error
extern int arpt_register_table(struct arpt_table *table,
const struct arpt_replace *repl);
extern void arpt_unregister_table(struct arpt_table *table);
-extern unsigned int arpt_do_table(struct sk_buff **pskb,
+extern unsigned int arpt_do_table(struct sk_buff *skb,
unsigned int hook,
const struct net_device *in,
const struct net_device *out,
diff --git a/include/linux/netfilter_bridge/ebtables.h b/include/linux/netfilter_bridge/ebtables.h
index 94e0a7dc0cb2..892f5b7771c7 100644
--- a/include/linux/netfilter_bridge/ebtables.h
+++ b/include/linux/netfilter_bridge/ebtables.h
@@ -237,7 +237,7 @@ struct ebt_target
struct list_head list;
const char name[EBT_FUNCTION_MAXNAMELEN];
/* returns one of the standard verdicts */
- int (*target)(struct sk_buff **pskb, unsigned int hooknr,
+ int (*target)(struct sk_buff *skb, unsigned int hooknr,
const struct net_device *in, const struct net_device *out,
const void *targetdata, unsigned int datalen);
/* 0 == let it in */
@@ -294,7 +294,7 @@ extern int ebt_register_watcher(struct ebt_watcher *watcher);
extern void ebt_unregister_watcher(struct ebt_watcher *watcher);
extern int ebt_register_target(struct ebt_target *target);
extern void ebt_unregister_target(struct ebt_target *target);
-extern unsigned int ebt_do_table(unsigned int hook, struct sk_buff **pskb,
+extern unsigned int ebt_do_table(unsigned int hook, struct sk_buff *skb,
const struct net_device *in, const struct net_device *out,
struct ebt_table *table);
diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h
index ceae87a4c891..1a63adf5c4c1 100644
--- a/include/linux/netfilter_ipv4.h
+++ b/include/linux/netfilter_ipv4.h
@@ -75,8 +75,8 @@ enum nf_ip_hook_priorities {
#define SO_ORIGINAL_DST 80
#ifdef __KERNEL__
-extern int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type);
-extern int ip_xfrm_me_harder(struct sk_buff **pskb);
+extern int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type);
+extern int ip_xfrm_me_harder(struct sk_buff *skb);
extern __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
unsigned int dataoff, u_int8_t protocol);
#endif /*__KERNEL__*/
diff --git a/include/linux/netfilter_ipv4/Kbuild b/include/linux/netfilter_ipv4/Kbuild
index 7185792b900f..3a7105bb8f33 100644
--- a/include/linux/netfilter_ipv4/Kbuild
+++ b/include/linux/netfilter_ipv4/Kbuild
@@ -1,47 +1,47 @@
-header-y += ipt_addrtype.h
-header-y += ipt_ah.h
header-y += ipt_CLASSIFY.h
header-y += ipt_CLUSTERIP.h
+header-y += ipt_CONNMARK.h
+header-y += ipt_DSCP.h
+header-y += ipt_ECN.h
+header-y += ipt_LOG.h
+header-y += ipt_MARK.h
+header-y += ipt_NFQUEUE.h
+header-y += ipt_REJECT.h
+header-y += ipt_SAME.h
+header-y += ipt_TCPMSS.h
+header-y += ipt_TOS.h
+header-y += ipt_TTL.h
+header-y += ipt_ULOG.h
+header-y += ipt_addrtype.h
+header-y += ipt_ah.h
header-y += ipt_comment.h
header-y += ipt_connbytes.h
header-y += ipt_connmark.h
-header-y += ipt_CONNMARK.h
header-y += ipt_conntrack.h
header-y += ipt_dccp.h
header-y += ipt_dscp.h
-header-y += ipt_DSCP.h
header-y += ipt_ecn.h
-header-y += ipt_ECN.h
header-y += ipt_esp.h
header-y += ipt_hashlimit.h
header-y += ipt_helper.h
header-y += ipt_iprange.h
header-y += ipt_length.h
header-y += ipt_limit.h
-header-y += ipt_LOG.h
header-y += ipt_mac.h
header-y += ipt_mark.h
-header-y += ipt_MARK.h
header-y += ipt_multiport.h
-header-y += ipt_NFQUEUE.h
header-y += ipt_owner.h
header-y += ipt_physdev.h
header-y += ipt_pkttype.h
header-y += ipt_policy.h
header-y += ipt_realm.h
header-y += ipt_recent.h
-header-y += ipt_REJECT.h
-header-y += ipt_SAME.h
header-y += ipt_sctp.h
header-y += ipt_state.h
header-y += ipt_string.h
header-y += ipt_tcpmss.h
-header-y += ipt_TCPMSS.h
header-y += ipt_tos.h
-header-y += ipt_TOS.h
header-y += ipt_ttl.h
-header-y += ipt_TTL.h
-header-y += ipt_ULOG.h
unifdef-y += ip_queue.h
unifdef-y += ip_tables.h
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h
index e992cd6b28f5..d79ed69cbc1f 100644
--- a/include/linux/netfilter_ipv4/ip_tables.h
+++ b/include/linux/netfilter_ipv4/ip_tables.h
@@ -337,7 +337,7 @@ struct ipt_error
.target.errorname = "ERROR", \
}
-extern unsigned int ipt_do_table(struct sk_buff **pskb,
+extern unsigned int ipt_do_table(struct sk_buff *skb,
unsigned int hook,
const struct net_device *in,
const struct net_device *out,
diff --git a/include/linux/netfilter_ipv6/Kbuild b/include/linux/netfilter_ipv6/Kbuild
index 9dd978d149ff..8887a5fcd1d0 100644
--- a/include/linux/netfilter_ipv6/Kbuild
+++ b/include/linux/netfilter_ipv6/Kbuild
@@ -14,8 +14,8 @@ header-y += ip6t_mark.h
header-y += ip6t_multiport.h
header-y += ip6t_opts.h
header-y += ip6t_owner.h
-header-y += ip6t_policy.h
header-y += ip6t_physdev.h
+header-y += ip6t_policy.h
header-y += ip6t_rt.h
unifdef-y += ip6_tables.h
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
index 9a720f05888f..7dc481ce7cba 100644
--- a/include/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/linux/netfilter_ipv6/ip6_tables.h
@@ -336,7 +336,7 @@ extern void ip6t_init(void) __init;
extern int ip6t_register_table(struct xt_table *table,
const struct ip6t_replace *repl);
extern void ip6t_unregister_table(struct xt_table *table);
-extern unsigned int ip6t_do_table(struct sk_buff **pskb,
+extern unsigned int ip6t_do_table(struct sk_buff *skb,
unsigned int hook,
const struct net_device *in,
const struct net_device *out,
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index 7c1f3b1d2ee5..d5bfaba595c7 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -192,7 +192,7 @@ extern int netlink_unregister_notifier(struct notifier_block *nb);
/* finegrained unicast helpers: */
struct sock *netlink_getsockbyfilp(struct file *filp);
int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock,
- long timeo, struct sock *ssk);
+ long *timeo, struct sock *ssk);
void netlink_detachskb(struct sock *sk, struct sk_buff *skb);
int netlink_sendskb(struct sock *sk, struct sk_buff *skb);
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index c5164c257f71..e82a6ebc725d 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -160,6 +160,12 @@ struct nfs_inode {
/* Open contexts for shared mmap writes */
struct list_head open_files;
+ /* Number of in-flight sillydelete RPC calls */
+ atomic_t silly_count;
+ /* List of deferred sillydelete requests */
+ struct hlist_head silly_list;
+ wait_queue_head_t waitqueue;
+
#ifdef CONFIG_NFS_V4
struct nfs4_cached_acl *nfs4_acl;
/* NFSv4 state */
@@ -394,6 +400,8 @@ extern void nfs_release_automount_timer(void);
*/
extern int nfs_async_unlink(struct inode *dir, struct dentry *dentry);
extern void nfs_complete_unlink(struct dentry *dentry, struct inode *);
+extern void nfs_block_sillyrename(struct dentry *dentry);
+extern void nfs_unblock_sillyrename(struct dentry *dentry);
/*
* linux/fs/nfs/write.c
diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
index 5cd192469096..bcb7abafbca9 100644
--- a/include/linux/nfsd/export.h
+++ b/include/linux/nfsd/export.h
@@ -127,17 +127,9 @@ void nfsd_export_shutdown(void);
void nfsd_export_flush(void);
void exp_readlock(void);
void exp_readunlock(void);
-struct svc_export * exp_get_by_name(struct auth_domain *clp,
- struct vfsmount *mnt,
- struct dentry *dentry,
- struct cache_req *reqp);
struct svc_export * rqst_exp_get_by_name(struct svc_rqst *,
struct vfsmount *,
struct dentry *);
-struct svc_export * exp_parent(struct auth_domain *clp,
- struct vfsmount *mnt,
- struct dentry *dentry,
- struct cache_req *reqp);
struct svc_export * rqst_exp_parent(struct svc_rqst *,
struct vfsmount *mnt,
struct dentry *dentry);
@@ -157,9 +149,6 @@ static inline void exp_get(struct svc_export *exp)
{
cache_get(&exp->h);
}
-extern struct svc_export *
-exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv,
- struct cache_req *reqp);
struct svc_export * rqst_exp_find(struct svc_rqst *, int, u32 *);
#endif /* __KERNEL__ */
diff --git a/include/linux/nls.h b/include/linux/nls.h
index 816c04ad7381..6a882208301a 100644
--- a/include/linux/nls.h
+++ b/include/linux/nls.h
@@ -7,13 +7,13 @@
typedef __u16 wchar_t;
struct nls_table {
- char *charset;
- char *alias;
+ const char *charset;
+ const char *alias;
int (*uni2char) (wchar_t uni, unsigned char *out, int boundlen);
int (*char2uni) (const unsigned char *rawstring, int boundlen,
wchar_t *uni);
- unsigned char *charset2lower;
- unsigned char *charset2upper;
+ const unsigned char *charset2lower;
+ const unsigned char *charset2upper;
struct module *owner;
struct nls_table *next;
};
diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h
index 52c54a5720f3..905e18f4b412 100644
--- a/include/linux/nodemask.h
+++ b/include/linux/nodemask.h
@@ -338,31 +338,88 @@ static inline void __nodes_remap(nodemask_t *dstp, const nodemask_t *srcp,
#endif /* MAX_NUMNODES */
/*
+ * Bitmasks that are kept for all the nodes.
+ */
+enum node_states {
+ N_POSSIBLE, /* The node could become online at some point */
+ N_ONLINE, /* The node is online */
+ N_NORMAL_MEMORY, /* The node has regular memory */
+#ifdef CONFIG_HIGHMEM
+ N_HIGH_MEMORY, /* The node has regular or high memory */
+#else
+ N_HIGH_MEMORY = N_NORMAL_MEMORY,
+#endif
+ N_CPU, /* The node has one or more cpus */
+ NR_NODE_STATES
+};
+
+/*
* The following particular system nodemasks and operations
* on them manage all possible and online nodes.
*/
-extern nodemask_t node_online_map;
-extern nodemask_t node_possible_map;
+extern nodemask_t node_states[NR_NODE_STATES];
#if MAX_NUMNODES > 1
-#define num_online_nodes() nodes_weight(node_online_map)
-#define num_possible_nodes() nodes_weight(node_possible_map)
-#define node_online(node) node_isset((node), node_online_map)
-#define node_possible(node) node_isset((node), node_possible_map)
-#define first_online_node first_node(node_online_map)
-#define next_online_node(nid) next_node((nid), node_online_map)
+static inline int node_state(int node, enum node_states state)
+{
+ return node_isset(node, node_states[state]);
+}
+
+static inline void node_set_state(int node, enum node_states state)
+{
+ __node_set(node, &node_states[state]);
+}
+
+static inline void node_clear_state(int node, enum node_states state)
+{
+ __node_clear(node, &node_states[state]);
+}
+
+static inline int num_node_state(enum node_states state)
+{
+ return nodes_weight(node_states[state]);
+}
+
+#define for_each_node_state(__node, __state) \
+ for_each_node_mask((__node), node_states[__state])
+
+#define first_online_node first_node(node_states[N_ONLINE])
+#define next_online_node(nid) next_node((nid), node_states[N_ONLINE])
+
extern int nr_node_ids;
#else
-#define num_online_nodes() 1
-#define num_possible_nodes() 1
-#define node_online(node) ((node) == 0)
-#define node_possible(node) ((node) == 0)
+
+static inline int node_state(int node, enum node_states state)
+{
+ return node == 0;
+}
+
+static inline void node_set_state(int node, enum node_states state)
+{
+}
+
+static inline void node_clear_state(int node, enum node_states state)
+{
+}
+
+static inline int num_node_state(enum node_states state)
+{
+ return 1;
+}
+
+#define for_each_node_state(node, __state) \
+ for ( (node) = 0; (node) == 0; (node) = 1)
+
#define first_online_node 0
#define next_online_node(nid) (MAX_NUMNODES)
#define nr_node_ids 1
+
#endif
+#define node_online_map node_states[N_ONLINE]
+#define node_possible_map node_states[N_POSSIBLE]
+
#define any_online_node(mask) \
({ \
int node; \
@@ -372,10 +429,15 @@ extern int nr_node_ids;
node; \
})
-#define node_set_online(node) set_bit((node), node_online_map.bits)
-#define node_set_offline(node) clear_bit((node), node_online_map.bits)
+#define num_online_nodes() num_node_state(N_ONLINE)
+#define num_possible_nodes() num_node_state(N_POSSIBLE)
+#define node_online(node) node_state((node), N_ONLINE)
+#define node_possible(node) node_state((node), N_POSSIBLE)
+
+#define node_set_online(node) node_set_state((node), N_ONLINE)
+#define node_set_offline(node) node_clear_state((node), N_ONLINE)
-#define for_each_node(node) for_each_node_mask((node), node_possible_map)
-#define for_each_online_node(node) for_each_node_mask((node), node_online_map)
+#define for_each_node(node) for_each_node_state(node, N_POSSIBLE)
+#define for_each_online_node(node) for_each_node_state(node, N_ONLINE)
#endif /* __LINUX_NODEMASK_H */
diff --git a/include/linux/notifier.h b/include/linux/notifier.h
index fad7ff17e468..0c40cc0b4a36 100644
--- a/include/linux/notifier.h
+++ b/include/linux/notifier.h
@@ -231,5 +231,22 @@ static inline int notifier_to_errno(int ret)
#define PM_SUSPEND_PREPARE 0x0003 /* Going to suspend the system */
#define PM_POST_SUSPEND 0x0004 /* Suspend finished */
+/* Console keyboard events.
+ * Note: KBD_KEYCODE is always sent before KBD_UNBOUND_KEYCODE, KBD_UNICODE and
+ * KBD_KEYSYM. */
+#define KBD_KEYCODE 0x0001 /* Keyboard keycode, called before any other */
+#define KBD_UNBOUND_KEYCODE 0x0002 /* Keyboard keycode which is not bound to any other */
+#define KBD_UNICODE 0x0003 /* Keyboard unicode */
+#define KBD_KEYSYM 0x0004 /* Keyboard keysym */
+#define KBD_POST_KEYSYM 0x0005 /* Called after keyboard keysym interpretation */
+
+extern struct blocking_notifier_head reboot_notifier_list;
+
+/* Virtual Terminal events. */
+#define VT_ALLOCATE 0x0001 /* Console got allocated */
+#define VT_DEALLOCATE 0x0002 /* Console will be deallocated */
+#define VT_WRITE 0x0003 /* A char got output */
+#define VT_UPDATE 0x0004 /* A bigger update occurred */
+
#endif /* __KERNEL__ */
#endif /* _LINUX_NOTIFIER_H */
diff --git a/include/linux/nsproxy.h b/include/linux/nsproxy.h
index bec4485e3d76..0e66b57631fc 100644
--- a/include/linux/nsproxy.h
+++ b/include/linux/nsproxy.h
@@ -23,7 +23,6 @@ struct pid_namespace;
*/
struct nsproxy {
atomic_t count;
- spinlock_t nslock;
struct uts_namespace *uts_ns;
struct ipc_namespace *ipc_ns;
struct mnt_namespace *mnt_ns;
@@ -33,8 +32,39 @@ struct nsproxy {
};
extern struct nsproxy init_nsproxy;
+/*
+ * the namespaces access rules are:
+ *
+ * 1. only current task is allowed to change tsk->nsproxy pointer or
+ * any pointer on the nsproxy itself
+ *
+ * 2. when accessing (i.e. reading) current task's namespaces - no
+ * precautions should be taken - just dereference the pointers
+ *
+ * 3. the access to other task namespaces is performed like this
+ * rcu_read_lock();
+ * nsproxy = task_nsproxy(tsk);
+ * if (nsproxy != NULL) {
+ * / *
+ * * work with the namespaces here
+ * * e.g. get the reference on one of them
+ * * /
+ * } / *
+ * * NULL task_nsproxy() means that this task is
+ * * almost dead (zombie)
+ * * /
+ * rcu_read_unlock();
+ *
+ */
+
+static inline struct nsproxy *task_nsproxy(struct task_struct *tsk)
+{
+ return rcu_dereference(tsk->nsproxy);
+}
+
int copy_namespaces(unsigned long flags, struct task_struct *tsk);
-void get_task_namespaces(struct task_struct *tsk);
+void exit_task_namespaces(struct task_struct *tsk);
+void switch_task_namespaces(struct task_struct *tsk, struct nsproxy *new);
void free_nsproxy(struct nsproxy *ns);
int unshare_nsproxy_namespaces(unsigned long, struct nsproxy **,
struct fs_struct *);
@@ -46,14 +76,15 @@ static inline void put_nsproxy(struct nsproxy *ns)
}
}
-static inline void exit_task_namespaces(struct task_struct *p)
+static inline void get_nsproxy(struct nsproxy *ns)
{
- struct nsproxy *ns = p->nsproxy;
- if (ns) {
- task_lock(p);
- p->nsproxy = NULL;
- task_unlock(p);
- put_nsproxy(ns);
- }
+ atomic_inc(&ns->count);
}
+
+#ifdef CONFIG_CGROUP_NS
+int ns_cgroup_clone(struct task_struct *tsk);
+#else
+static inline int ns_cgroup_clone(struct task_struct *tsk) { return 0; }
+#endif
+
#endif
diff --git a/include/linux/of.h b/include/linux/of.h
index 6df80e985914..5c39b9270ff7 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -16,8 +16,8 @@
* 2 of the License, or (at your option) any later version.
*/
#include <linux/types.h>
+#include <linux/bitops.h>
-#include <asm/bitops.h>
#include <asm/prom.h>
/* flag descriptions */
diff --git a/include/linux/of_device.h b/include/linux/of_device.h
index 91bf84b9d144..212bffb2b174 100644
--- a/include/linux/of_device.h
+++ b/include/linux/of_device.h
@@ -22,5 +22,10 @@ extern int of_device_register(struct of_device *ofdev);
extern void of_device_unregister(struct of_device *ofdev);
extern void of_release_dev(struct device *dev);
+static inline void of_device_free(struct of_device *dev)
+{
+ of_release_dev(&dev->dev);
+}
+
#endif /* __KERNEL__ */
#endif /* _LINUX_OF_DEVICE_H */
diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h
index 448f70b30a0c..a8efcfeea732 100644
--- a/include/linux/of_platform.h
+++ b/include/linux/of_platform.h
@@ -48,6 +48,10 @@ struct of_platform_driver
#define to_of_platform_driver(drv) \
container_of(drv,struct of_platform_driver, driver)
+extern int of_register_driver(struct of_platform_driver *drv,
+ struct bus_type *bus);
+extern void of_unregister_driver(struct of_platform_driver *drv);
+
#include <asm/of_platform.h>
extern struct of_device *of_find_device_by_node(struct device_node *np);
diff --git a/include/linux/oom.h b/include/linux/oom.h
index ad76463629a0..3852436b652a 100644
--- a/include/linux/oom.h
+++ b/include/linux/oom.h
@@ -7,4 +7,28 @@
#define OOM_ADJUST_MIN (-16)
#define OOM_ADJUST_MAX 15
-#endif
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+
+struct zonelist;
+struct notifier_block;
+
+/*
+ * Types of limitations to the nodes from which allocations may occur
+ */
+enum oom_constraint {
+ CONSTRAINT_NONE,
+ CONSTRAINT_CPUSET,
+ CONSTRAINT_MEMORY_POLICY,
+};
+
+extern int try_set_zone_oom(struct zonelist *zonelist);
+extern void clear_zonelist_oom(struct zonelist *zonelist);
+
+extern void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order);
+extern int register_oom_notifier(struct notifier_block *nb);
+extern int unregister_oom_notifier(struct notifier_block *nb);
+
+#endif /* __KERNEL__*/
+#endif /* _INCLUDE_LINUX_OOM_H */
diff --git a/include/linux/page-isolation.h b/include/linux/page-isolation.h
new file mode 100644
index 000000000000..051c1b1ede4e
--- /dev/null
+++ b/include/linux/page-isolation.h
@@ -0,0 +1,37 @@
+#ifndef __LINUX_PAGEISOLATION_H
+#define __LINUX_PAGEISOLATION_H
+
+/*
+ * Changes migrate type in [start_pfn, end_pfn) to be MIGRATE_ISOLATE.
+ * If specified range includes migrate types other than MOVABLE,
+ * this will fail with -EBUSY.
+ *
+ * For isolating all pages in the range finally, the caller have to
+ * free all pages in the range. test_page_isolated() can be used for
+ * test it.
+ */
+extern int
+start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn);
+
+/*
+ * Changes MIGRATE_ISOLATE to MIGRATE_MOVABLE.
+ * target range is [start_pfn, end_pfn)
+ */
+extern int
+undo_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn);
+
+/*
+ * test all pages in [start_pfn, end_pfn)are isolated or not.
+ */
+extern int
+test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn);
+
+/*
+ * Internal funcs.Changes pageblock's migrate type.
+ * Please use make_pagetype_isolated()/make_pagetype_movable().
+ */
+extern int set_migratetype_isolate(struct page *page);
+extern void unset_migratetype_isolate(struct page *page);
+
+
+#endif
diff --git a/include/linux/pageblock-flags.h b/include/linux/pageblock-flags.h
new file mode 100644
index 000000000000..e875905f7b12
--- /dev/null
+++ b/include/linux/pageblock-flags.h
@@ -0,0 +1,75 @@
+/*
+ * Macros for manipulating and testing flags related to a
+ * pageblock_nr_pages number of pages.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2006
+ *
+ * Original author, Mel Gorman
+ * Major cleanups and reduction of bit operations, Andy Whitcroft
+ */
+#ifndef PAGEBLOCK_FLAGS_H
+#define PAGEBLOCK_FLAGS_H
+
+#include <linux/types.h>
+
+/* Macro to aid the definition of ranges of bits */
+#define PB_range(name, required_bits) \
+ name, name ## _end = (name + required_bits) - 1
+
+/* Bit indices that affect a whole block of pages */
+enum pageblock_bits {
+ PB_range(PB_migrate, 3), /* 3 bits required for migrate types */
+ NR_PAGEBLOCK_BITS
+};
+
+#ifdef CONFIG_HUGETLB_PAGE
+
+#ifdef CONFIG_HUGETLB_PAGE_SIZE_VARIABLE
+
+/* Huge page sizes are variable */
+extern int pageblock_order;
+
+#else /* CONFIG_HUGETLB_PAGE_SIZE_VARIABLE */
+
+/* Huge pages are a constant size */
+#define pageblock_order HUGETLB_PAGE_ORDER
+
+#endif /* CONFIG_HUGETLB_PAGE_SIZE_VARIABLE */
+
+#else /* CONFIG_HUGETLB_PAGE */
+
+/* If huge pages are not used, group by MAX_ORDER_NR_PAGES */
+#define pageblock_order (MAX_ORDER-1)
+
+#endif /* CONFIG_HUGETLB_PAGE */
+
+#define pageblock_nr_pages (1UL << pageblock_order)
+
+/* Forward declaration */
+struct page;
+
+/* Declarations for getting and setting flags. See mm/page_alloc.c */
+unsigned long get_pageblock_flags_group(struct page *page,
+ int start_bitidx, int end_bitidx);
+void set_pageblock_flags_group(struct page *page, unsigned long flags,
+ int start_bitidx, int end_bitidx);
+
+#define get_pageblock_flags(page) \
+ get_pageblock_flags_group(page, 0, NR_PAGEBLOCK_BITS-1)
+#define set_pageblock_flags(page) \
+ set_pageblock_flags_group(page, 0, NR_PAGEBLOCK_BITS-1)
+
+#endif /* PAGEBLOCK_FLAGS_H */
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 8a83537d6978..db8a410ae9e1 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -84,11 +84,11 @@ static inline struct page *page_cache_alloc_cold(struct address_space *x)
typedef int filler_t(void *, struct page *);
extern struct page * find_get_page(struct address_space *mapping,
- unsigned long index);
+ pgoff_t index);
extern struct page * find_lock_page(struct address_space *mapping,
- unsigned long index);
+ pgoff_t index);
extern struct page * find_or_create_page(struct address_space *mapping,
- unsigned long index, gfp_t gfp_mask);
+ pgoff_t index, gfp_t gfp_mask);
unsigned find_get_pages(struct address_space *mapping, pgoff_t start,
unsigned int nr_pages, struct page **pages);
unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t start,
@@ -96,44 +96,47 @@ unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t start,
unsigned find_get_pages_tag(struct address_space *mapping, pgoff_t *index,
int tag, unsigned int nr_pages, struct page **pages);
+struct page *__grab_cache_page(struct address_space *mapping, pgoff_t index);
+
/*
* Returns locked page at given index in given cache, creating it if needed.
*/
-static inline struct page *grab_cache_page(struct address_space *mapping, unsigned long index)
+static inline struct page *grab_cache_page(struct address_space *mapping,
+ pgoff_t index)
{
return find_or_create_page(mapping, index, mapping_gfp_mask(mapping));
}
extern struct page * grab_cache_page_nowait(struct address_space *mapping,
- unsigned long index);
+ pgoff_t index);
extern struct page * read_cache_page_async(struct address_space *mapping,
- unsigned long index, filler_t *filler,
+ pgoff_t index, filler_t *filler,
void *data);
extern struct page * read_cache_page(struct address_space *mapping,
- unsigned long index, filler_t *filler,
+ pgoff_t index, filler_t *filler,
void *data);
extern int read_cache_pages(struct address_space *mapping,
struct list_head *pages, filler_t *filler, void *data);
static inline struct page *read_mapping_page_async(
struct address_space *mapping,
- unsigned long index, void *data)
+ pgoff_t index, void *data)
{
filler_t *filler = (filler_t *)mapping->a_ops->readpage;
return read_cache_page_async(mapping, index, filler, data);
}
static inline struct page *read_mapping_page(struct address_space *mapping,
- unsigned long index, void *data)
+ pgoff_t index, void *data)
{
filler_t *filler = (filler_t *)mapping->a_ops->readpage;
return read_cache_page(mapping, index, filler, data);
}
int add_to_page_cache(struct page *page, struct address_space *mapping,
- unsigned long index, gfp_t gfp_mask);
+ pgoff_t index, gfp_t gfp_mask);
int add_to_page_cache_lru(struct page *page, struct address_space *mapping,
- unsigned long index, gfp_t gfp_mask);
+ pgoff_t index, gfp_t gfp_mask);
extern void remove_from_page_cache(struct page *page);
extern void __remove_from_page_cache(struct page *page);
@@ -218,6 +221,9 @@ static inline int fault_in_pages_writeable(char __user *uaddr, int size)
{
int ret;
+ if (unlikely(size == 0))
+ return 0;
+
/*
* Writing zeroes into userspace here is OK, because we know that if
* the zero gets there, we'll be overwriting it.
@@ -237,19 +243,23 @@ static inline int fault_in_pages_writeable(char __user *uaddr, int size)
return ret;
}
-static inline void fault_in_pages_readable(const char __user *uaddr, int size)
+static inline int fault_in_pages_readable(const char __user *uaddr, int size)
{
volatile char c;
int ret;
+ if (unlikely(size == 0))
+ return 0;
+
ret = __get_user(c, uaddr);
if (ret == 0) {
const char __user *end = uaddr + size - 1;
if (((unsigned long)uaddr & PAGE_MASK) !=
((unsigned long)end & PAGE_MASK))
- __get_user(c, end);
+ ret = __get_user(c, end);
}
+ return ret;
}
#endif /* _LINUX_PAGEMAP_H */
diff --git a/include/linux/parport.h b/include/linux/parport.h
index 9cdd6943e01b..d1ad546c8c9e 100644
--- a/include/linux/parport.h
+++ b/include/linux/parport.h
@@ -100,6 +100,7 @@ typedef enum {
#include <linux/proc_fs.h>
#include <linux/spinlock.h>
#include <linux/wait.h>
+#include <linux/irqreturn.h>
#include <asm/system.h>
#include <asm/ptrace.h>
#include <asm/semaphore.h>
@@ -229,7 +230,7 @@ struct pardevice {
int (*preempt)(void *);
void (*wakeup)(void *);
void *private;
- void (*irq_func)(int, void *);
+ void (*irq_func)(void *);
unsigned int flags;
struct pardevice *next;
struct pardevice *prev;
@@ -366,6 +367,9 @@ extern void parport_unregister_driver (struct parport_driver *);
extern struct parport *parport_find_number (int);
extern struct parport *parport_find_base (unsigned long);
+/* generic irq handler, if it suits your needs */
+extern irqreturn_t parport_irq_handler(int irq, void *dev_id);
+
/* Reference counting for ports. */
extern struct parport *parport_get_port (struct parport *);
extern void parport_put_port (struct parport *);
@@ -379,7 +383,7 @@ extern void parport_put_port (struct parport *);
struct pardevice *parport_register_device(struct parport *port,
const char *name,
int (*pf)(void *), void (*kf)(void *),
- void (*irq_func)(int, void *),
+ void (*irq_func)(void *),
int flags, void *handle);
/* parport_unregister unlinks a device from the chain. */
@@ -461,7 +465,7 @@ static __inline__ int parport_yield_blocking(struct pardevice *dev)
#define PARPORT_FLAG_EXCL (1<<1) /* EXCL driver registered. */
/* IEEE1284 functions */
-extern void parport_ieee1284_interrupt (int, void *);
+extern void parport_ieee1284_interrupt (void *);
extern int parport_negotiate (struct parport *, int mode);
extern ssize_t parport_write (struct parport *, const void *buf, size_t len);
extern ssize_t parport_read (struct parport *, void *buf, size_t len);
@@ -503,24 +507,19 @@ extern size_t parport_ieee1284_epp_read_addr (struct parport *,
/* IEEE1284.3 functions */
extern int parport_daisy_init (struct parport *port);
extern void parport_daisy_fini (struct parport *port);
-extern struct pardevice *parport_open (int devnum, const char *name,
- int (*pf) (void *),
- void (*kf) (void *),
- void (*irqf) (int, void *),
- int flags, void *handle);
+extern struct pardevice *parport_open (int devnum, const char *name);
extern void parport_close (struct pardevice *dev);
extern ssize_t parport_device_id (int devnum, char *buffer, size_t len);
-extern int parport_device_num (int parport, int mux, int daisy);
extern void parport_daisy_deselect_all (struct parport *port);
extern int parport_daisy_select (struct parport *port, int daisy, int mode);
/* Lowlevel drivers _can_ call this support function to handle irqs. */
-static __inline__ void parport_generic_irq(int irq, struct parport *port)
+static inline void parport_generic_irq(struct parport *port)
{
- parport_ieee1284_interrupt (irq, port);
+ parport_ieee1284_interrupt (port);
read_lock(&port->cad_lock);
if (port->cad && port->cad->irq_func)
- port->cad->irq_func(irq, port->cad->private);
+ port->cad->irq_func(port->cad->private);
read_unlock(&port->cad_lock);
}
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 768b93359f90..0dd93bb62fbe 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -109,6 +109,14 @@ enum pcie_reset_state {
pcie_hot_reset = (__force pcie_reset_state_t) 3
};
+typedef unsigned short __bitwise pci_dev_flags_t;
+enum pci_dev_flags {
+ /* INTX_DISABLE in PCI_COMMAND register disables MSI
+ * generation too.
+ */
+ PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG = (__force pci_dev_flags_t) 1,
+};
+
typedef unsigned short __bitwise pci_bus_flags_t;
enum pci_bus_flags {
PCI_BUS_FLAGS_NO_MSI = (__force pci_bus_flags_t) 1,
@@ -141,6 +149,7 @@ struct pci_dev {
unsigned int class; /* 3 bytes: (base,sub,prog-if) */
u8 revision; /* PCI revision, low byte of class word */
u8 hdr_type; /* PCI header type (`multi' flag masked out) */
+ u8 pcie_type; /* PCI-E device/port type */
u8 rom_base_reg; /* which config register controls the ROM */
u8 pin; /* which interrupt pin this device uses */
@@ -183,6 +192,8 @@ struct pci_dev {
unsigned int msi_enabled:1;
unsigned int msix_enabled:1;
unsigned int is_managed:1;
+ unsigned int is_pcie:1;
+ pci_dev_flags_t dev_flags;
atomic_t enable_cnt; /* pci_enable_device has been called */
u32 saved_config_space[16]; /* config space saved at suspend time */
@@ -477,8 +488,11 @@ extern void pci_sort_breadthfirst(void);
/* Generic PCI functions exported to card drivers */
+#ifdef CONFIG_PCI_LEGACY
struct pci_dev __deprecated *pci_find_device (unsigned int vendor, unsigned int device, const struct pci_dev *from);
struct pci_dev __deprecated *pci_find_slot (unsigned int bus, unsigned int devfn);
+#endif /* CONFIG_PCI_LEGACY */
+
int pci_find_capability (struct pci_dev *dev, int cap);
int pci_find_next_capability (struct pci_dev *dev, u8 pos, int cap);
int pci_find_ext_capability (struct pci_dev *dev, int cap);
@@ -620,7 +634,6 @@ static inline int __must_check pci_register_driver(struct pci_driver *driver)
void pci_unregister_driver(struct pci_driver *);
void pci_remove_behind_bridge(struct pci_dev *);
struct pci_driver *pci_dev_driver(const struct pci_dev *);
-const struct pci_device_id *pci_match_device(struct pci_driver *drv, struct pci_dev *dev);
const struct pci_device_id *pci_match_id(const struct pci_device_id *ids, struct pci_dev *dev);
int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass);
@@ -749,7 +762,6 @@ static inline void pci_unregister_driver(struct pci_driver *drv) { }
static inline int pci_find_capability (struct pci_dev *dev, int cap) {return 0; }
static inline int pci_find_next_capability (struct pci_dev *dev, u8 post, int cap) { return 0; }
static inline int pci_find_ext_capability (struct pci_dev *dev, int cap) {return 0; }
-static inline const struct pci_device_id *pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev) { return NULL; }
/* Power management related routines */
static inline int pci_save_state(struct pci_dev *dev) { return 0; }
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 2aaf1c16ce98..1ee009e8fec8 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -360,9 +360,6 @@
#define PCI_DEVICE_ID_ATI_RS400_166 0x5a32
#define PCI_DEVICE_ID_ATI_RS400_200 0x5a33
#define PCI_DEVICE_ID_ATI_RS480 0x5950
-#define PCI_DEVICE_ID_ATI_RD580 0x5952
-#define PCI_DEVICE_ID_ATI_RX790 0x5957
-#define PCI_DEVICE_ID_ATI_RS690 0x7910
/* ATI IXP Chipset */
#define PCI_DEVICE_ID_ATI_IXP200_IDE 0x4349
#define PCI_DEVICE_ID_ATI_IXP200_SMBUS 0x4353
@@ -1236,6 +1233,10 @@
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE 0x0560
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE 0x056C
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE 0x0759
+#define PCI_DEVICE_ID_NVIDIA_NVENET_32 0x0760
+#define PCI_DEVICE_ID_NVIDIA_NVENET_33 0x0761
+#define PCI_DEVICE_ID_NVIDIA_NVENET_34 0x0762
+#define PCI_DEVICE_ID_NVIDIA_NVENET_35 0x0763
#define PCI_VENDOR_ID_IMS 0x10e0
#define PCI_DEVICE_ID_IMS_TT128 0x9128
@@ -1432,8 +1433,8 @@
#define PCI_DEVICE_ID_SERVERWORKS_HE 0x0008
#define PCI_DEVICE_ID_SERVERWORKS_LE 0x0009
#define PCI_DEVICE_ID_SERVERWORKS_GCNB_LE 0x0017
+#define PCI_DEVICE_ID_SERVERWORKS_HT1000_PXB 0x0036
#define PCI_DEVICE_ID_SERVERWORKS_EPB 0x0103
-#define PCI_DEVICE_ID_SERVERWORKS_HT1000_PCIX 0x0104
#define PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE 0x0132
#define PCI_DEVICE_ID_SERVERWORKS_OSB4 0x0200
#define PCI_DEVICE_ID_SERVERWORKS_CSB5 0x0201
@@ -1636,6 +1637,7 @@
#define PCI_DEVICE_ID_ITE_8211 0x8211
#define PCI_DEVICE_ID_ITE_8212 0x8212
#define PCI_DEVICE_ID_ITE_8213 0x8213
+#define PCI_DEVICE_ID_ITE_8152 0x8152
#define PCI_DEVICE_ID_ITE_8872 0x8872
#define PCI_DEVICE_ID_ITE_IT8330G_0 0xe886
@@ -1942,6 +1944,7 @@
#define PCI_DEVICE_ID_TIGON3_5720 0x1658
#define PCI_DEVICE_ID_TIGON3_5721 0x1659
#define PCI_DEVICE_ID_TIGON3_5722 0x165a
+#define PCI_DEVICE_ID_TIGON3_5723 0x165b
#define PCI_DEVICE_ID_TIGON3_5705M 0x165d
#define PCI_DEVICE_ID_TIGON3_5705M_2 0x165e
#define PCI_DEVICE_ID_TIGON3_5714 0x1668
@@ -1994,6 +1997,8 @@
#define PCI_VENDOR_ID_TOPIC 0x151f
#define PCI_DEVICE_ID_TOPIC_TP560 0x0000
+#define PCI_VENDOR_ID_MAINPINE 0x1522
+#define PCI_DEVICE_ID_MAINPINE_PBRIDGE 0x0100
#define PCI_VENDOR_ID_ENE 0x1524
#define PCI_DEVICE_ID_ENE_CB712_SD 0x0550
#define PCI_DEVICE_ID_ENE_CB712_SD_2 0x0551
@@ -2271,6 +2276,9 @@
#define PCI_DEVICE_ID_INTEL_82915G_IG 0x2582
#define PCI_DEVICE_ID_INTEL_82915GM_HB 0x2590
#define PCI_DEVICE_ID_INTEL_82915GM_IG 0x2592
+#define PCI_DEVICE_ID_INTEL_5000_ERR 0x25F0
+#define PCI_DEVICE_ID_INTEL_5000_FBD0 0x25F5
+#define PCI_DEVICE_ID_INTEL_5000_FBD1 0x25F6
#define PCI_DEVICE_ID_INTEL_82945G_HB 0x2770
#define PCI_DEVICE_ID_INTEL_82945G_IG 0x2772
#define PCI_DEVICE_ID_INTEL_3000_HB 0x2778
@@ -2323,6 +2331,9 @@
#define PCI_DEVICE_ID_INTEL_MCH_PC 0x3599
#define PCI_DEVICE_ID_INTEL_MCH_PC1 0x359a
#define PCI_DEVICE_ID_INTEL_E7525_MCH 0x359e
+#define PCI_DEVICE_ID_INTEL_IOAT_CNB 0x360b
+#define PCI_DEVICE_ID_INTEL_IOAT_SNB 0x402f
+#define PCI_DEVICE_ID_INTEL_IOAT_SCNB 0x65ff
#define PCI_DEVICE_ID_INTEL_TOLAPAI_0 0x5031
#define PCI_DEVICE_ID_INTEL_TOLAPAI_1 0x5032
#define PCI_DEVICE_ID_INTEL_82371SB_0 0x7000
diff --git a/include/linux/percpu_counter.h b/include/linux/percpu_counter.h
index 3d9f70972cdf..9007ccdfc112 100644
--- a/include/linux/percpu_counter.h
+++ b/include/linux/percpu_counter.h
@@ -30,10 +30,28 @@ struct percpu_counter {
#define FBC_BATCH (NR_CPUS*4)
#endif
-void percpu_counter_init(struct percpu_counter *fbc, s64 amount);
+int percpu_counter_init(struct percpu_counter *fbc, s64 amount);
+int percpu_counter_init_irq(struct percpu_counter *fbc, s64 amount);
void percpu_counter_destroy(struct percpu_counter *fbc);
-void percpu_counter_mod(struct percpu_counter *fbc, s32 amount);
-s64 percpu_counter_sum(struct percpu_counter *fbc);
+void percpu_counter_set(struct percpu_counter *fbc, s64 amount);
+void __percpu_counter_add(struct percpu_counter *fbc, s64 amount, s32 batch);
+s64 __percpu_counter_sum(struct percpu_counter *fbc);
+
+static inline void percpu_counter_add(struct percpu_counter *fbc, s64 amount)
+{
+ __percpu_counter_add(fbc, amount, FBC_BATCH);
+}
+
+static inline s64 percpu_counter_sum_positive(struct percpu_counter *fbc)
+{
+ s64 ret = __percpu_counter_sum(fbc);
+ return ret < 0 ? 0 : ret;
+}
+
+static inline s64 percpu_counter_sum(struct percpu_counter *fbc)
+{
+ return __percpu_counter_sum(fbc);
+}
static inline s64 percpu_counter_read(struct percpu_counter *fbc)
{
@@ -61,17 +79,28 @@ struct percpu_counter {
s64 count;
};
-static inline void percpu_counter_init(struct percpu_counter *fbc, s64 amount)
+static inline int percpu_counter_init(struct percpu_counter *fbc, s64 amount)
{
fbc->count = amount;
+ return 0;
}
+#define percpu_counter_init_irq percpu_counter_init
+
static inline void percpu_counter_destroy(struct percpu_counter *fbc)
{
}
+static inline void percpu_counter_set(struct percpu_counter *fbc, s64 amount)
+{
+ fbc->count = amount;
+}
+
+#define __percpu_counter_add(fbc, amount, batch) \
+ percpu_counter_add(fbc, amount)
+
static inline void
-percpu_counter_mod(struct percpu_counter *fbc, s32 amount)
+percpu_counter_add(struct percpu_counter *fbc, s64 amount)
{
preempt_disable();
fbc->count += amount;
@@ -88,21 +117,31 @@ static inline s64 percpu_counter_read_positive(struct percpu_counter *fbc)
return fbc->count;
}
-static inline s64 percpu_counter_sum(struct percpu_counter *fbc)
+static inline s64 percpu_counter_sum_positive(struct percpu_counter *fbc)
{
return percpu_counter_read_positive(fbc);
}
+static inline s64 percpu_counter_sum(struct percpu_counter *fbc)
+{
+ return percpu_counter_read(fbc);
+}
+
#endif /* CONFIG_SMP */
static inline void percpu_counter_inc(struct percpu_counter *fbc)
{
- percpu_counter_mod(fbc, 1);
+ percpu_counter_add(fbc, 1);
}
static inline void percpu_counter_dec(struct percpu_counter *fbc)
{
- percpu_counter_mod(fbc, -1);
+ percpu_counter_add(fbc, -1);
+}
+
+static inline void percpu_counter_sub(struct percpu_counter *fbc, s64 amount)
+{
+ percpu_counter_add(fbc, -amount);
}
#endif /* _LINUX_PERCPU_COUNTER_H */
diff --git a/include/linux/phantom.h b/include/linux/phantom.h
index d3ebbfae6903..96f4048a6cc3 100644
--- a/include/linux/phantom.h
+++ b/include/linux/phantom.h
@@ -30,7 +30,11 @@ struct phm_regs {
#define PHN_SET_REG _IOW (PH_IOC_MAGIC, 1, struct phm_reg *)
#define PHN_GET_REGS _IOWR(PH_IOC_MAGIC, 2, struct phm_regs *)
#define PHN_SET_REGS _IOW (PH_IOC_MAGIC, 3, struct phm_regs *)
-#define PH_IOC_MAXNR 3
+/* this ioctl tells the driver, that the caller is not OpenHaptics and might
+ * use improved registers update (no more phantom switchoffs when using
+ * libphantom) */
+#define PHN_NOT_OH _IO (PH_IOC_MAGIC, 4)
+#define PH_IOC_MAXNR 4
#define PHN_CONTROL 0x6 /* control byte in iaddr space */
#define PHN_CTL_AMP 0x1 /* switch after torques change */
diff --git a/include/linux/pid.h b/include/linux/pid.h
index 1e0e4e3423a6..e29a900a8499 100644
--- a/include/linux/pid.h
+++ b/include/linux/pid.h
@@ -40,15 +40,28 @@ enum pid_type
* processes.
*/
-struct pid
-{
- atomic_t count;
+
+/*
+ * struct upid is used to get the id of the struct pid, as it is
+ * seen in particular namespace. Later the struct pid is found with
+ * find_pid_ns() using the int nr and struct pid_namespace *ns.
+ */
+
+struct upid {
/* Try to keep pid_chain in the same cacheline as nr for find_pid */
int nr;
+ struct pid_namespace *ns;
struct hlist_node pid_chain;
+};
+
+struct pid
+{
+ atomic_t count;
/* lists of tasks that use this pid */
struct hlist_head tasks[PIDTYPE_MAX];
struct rcu_head rcu;
+ int level;
+ struct upid numbers[1];
};
extern struct pid init_struct_pid;
@@ -83,26 +96,60 @@ extern void FASTCALL(detach_pid(struct task_struct *task, enum pid_type));
extern void FASTCALL(transfer_pid(struct task_struct *old,
struct task_struct *new, enum pid_type));
+struct pid_namespace;
+extern struct pid_namespace init_pid_ns;
+
/*
* look up a PID in the hash table. Must be called with the tasklist_lock
* or rcu_read_lock() held.
+ *
+ * find_pid_ns() finds the pid in the namespace specified
+ * find_pid() find the pid by its global id, i.e. in the init namespace
+ * find_vpid() finr the pid by its virtual id, i.e. in the current namespace
+ *
+ * see also find_task_by_pid() set in include/linux/sched.h
*/
-extern struct pid *FASTCALL(find_pid(int nr));
+extern struct pid *FASTCALL(find_pid_ns(int nr, struct pid_namespace *ns));
+extern struct pid *find_vpid(int nr);
+extern struct pid *find_pid(int nr);
/*
* Lookup a PID in the hash table, and return with it's count elevated.
*/
extern struct pid *find_get_pid(int nr);
-extern struct pid *find_ge_pid(int nr);
+extern struct pid *find_ge_pid(int nr, struct pid_namespace *);
-extern struct pid *alloc_pid(void);
+extern struct pid *alloc_pid(struct pid_namespace *ns);
extern void FASTCALL(free_pid(struct pid *pid));
+extern void zap_pid_ns_processes(struct pid_namespace *pid_ns);
+
+/*
+ * the helpers to get the pid's id seen from different namespaces
+ *
+ * pid_nr() : global id, i.e. the id seen from the init namespace;
+ * pid_vnr() : virtual id, i.e. the id seen from the namespace this pid
+ * belongs to. this only makes sence when called in the
+ * context of the task that belongs to the same namespace;
+ * pid_nr_ns() : id seen from the ns specified.
+ *
+ * see also task_xid_nr() etc in include/linux/sched.h
+ */
static inline pid_t pid_nr(struct pid *pid)
{
pid_t nr = 0;
if (pid)
- nr = pid->nr;
+ nr = pid->numbers[0].nr;
+ return nr;
+}
+
+pid_t pid_nr_ns(struct pid *pid, struct pid_namespace *ns);
+
+static inline pid_t pid_vnr(struct pid *pid)
+{
+ pid_t nr = 0;
+ if (pid)
+ nr = pid->numbers[pid->level].nr;
return nr;
}
diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h
index b9a17e08ff0f..1689e28483e4 100644
--- a/include/linux/pid_namespace.h
+++ b/include/linux/pid_namespace.h
@@ -4,7 +4,6 @@
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/threads.h>
-#include <linux/pid.h>
#include <linux/nsproxy.h>
#include <linux/kref.h>
@@ -20,13 +19,22 @@ struct pid_namespace {
struct pidmap pidmap[PIDMAP_ENTRIES];
int last_pid;
struct task_struct *child_reaper;
+ struct kmem_cache *pid_cachep;
+ int level;
+ struct pid_namespace *parent;
+#ifdef CONFIG_PROC_FS
+ struct vfsmount *proc_mnt;
+#endif
};
extern struct pid_namespace init_pid_ns;
-static inline void get_pid_ns(struct pid_namespace *ns)
+#ifdef CONFIG_PID_NS
+static inline struct pid_namespace *get_pid_ns(struct pid_namespace *ns)
{
- kref_get(&ns->kref);
+ if (ns != &init_pid_ns)
+ kref_get(&ns->kref);
+ return ns;
}
extern struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *ns);
@@ -34,12 +42,41 @@ extern void free_pid_ns(struct kref *kref);
static inline void put_pid_ns(struct pid_namespace *ns)
{
- kref_put(&ns->kref, free_pid_ns);
+ if (ns != &init_pid_ns)
+ kref_put(&ns->kref, free_pid_ns);
}
-static inline struct task_struct *child_reaper(struct task_struct *tsk)
+#else /* !CONFIG_PID_NS */
+#include <linux/err.h>
+
+static inline struct pid_namespace *get_pid_ns(struct pid_namespace *ns)
+{
+ return ns;
+}
+
+static inline struct pid_namespace *
+copy_pid_ns(unsigned long flags, struct pid_namespace *ns)
+{
+ if (flags & CLONE_NEWPID)
+ ns = ERR_PTR(-EINVAL);
+ return ns;
+}
+
+static inline void put_pid_ns(struct pid_namespace *ns)
+{
+}
+
+#endif /* CONFIG_PID_NS */
+
+static inline struct pid_namespace *task_active_pid_ns(struct task_struct *tsk)
+{
+ return tsk->nsproxy->pid_ns;
+}
+
+static inline struct task_struct *task_child_reaper(struct task_struct *tsk)
{
- return init_pid_ns.child_reaper;
+ BUG_ON(tsk != current);
+ return tsk->nsproxy->pid_ns->child_reaper;
}
#endif /* _LINUX_PID_NS_H */
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 48b71badfb4c..09a309b7b5d2 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -104,104 +104,6 @@ extern void (*pm_idle)(void);
extern void (*pm_power_off)(void);
extern void (*pm_power_off_prepare)(void);
-typedef int __bitwise suspend_state_t;
-
-#define PM_SUSPEND_ON ((__force suspend_state_t) 0)
-#define PM_SUSPEND_STANDBY ((__force suspend_state_t) 1)
-#define PM_SUSPEND_MEM ((__force suspend_state_t) 3)
-#define PM_SUSPEND_MAX ((__force suspend_state_t) 4)
-
-/**
- * struct pm_ops - Callbacks for managing platform dependent system sleep
- * states.
- *
- * @valid: Callback to determine if given system sleep state is supported by
- * the platform.
- * Valid (ie. supported) states are advertised in /sys/power/state. Note
- * that it still may be impossible to enter given system sleep state if the
- * conditions aren't right.
- * There is the %pm_valid_only_mem function available that can be assigned
- * to this if the platform only supports mem sleep.
- *
- * @set_target: Tell the platform which system sleep state is going to be
- * entered.
- * @set_target() is executed right prior to suspending devices. The
- * information conveyed to the platform code by @set_target() should be
- * disregarded by the platform as soon as @finish() is executed and if
- * @prepare() fails. If @set_target() fails (ie. returns nonzero),
- * @prepare(), @enter() and @finish() will not be called by the PM core.
- * This callback is optional. However, if it is implemented, the argument
- * passed to @prepare(), @enter() and @finish() is meaningless and should
- * be ignored.
- *
- * @prepare: Prepare the platform for entering the system sleep state indicated
- * by @set_target() or represented by the argument if @set_target() is not
- * implemented.
- * @prepare() is called right after devices have been suspended (ie. the
- * appropriate .suspend() method has been executed for each device) and
- * before the nonboot CPUs are disabled (it is executed with IRQs enabled).
- * This callback is optional. It returns 0 on success or a negative
- * error code otherwise, in which case the system cannot enter the desired
- * sleep state (@enter() and @finish() will not be called in that case).
- *
- * @enter: Enter the system sleep state indicated by @set_target() or
- * represented by the argument if @set_target() is not implemented.
- * This callback is mandatory. It returns 0 on success or a negative
- * error code otherwise, in which case the system cannot enter the desired
- * sleep state.
- *
- * @finish: Called when the system has just left a sleep state, right after
- * the nonboot CPUs have been enabled and before devices are resumed (it is
- * executed with IRQs enabled). If @set_target() is not implemented, the
- * argument represents the sleep state being left.
- * This callback is optional, but should be implemented by the platforms
- * that implement @prepare(). If implemented, it is always called after
- * @enter() (even if @enter() fails).
- */
-struct pm_ops {
- int (*valid)(suspend_state_t state);
- int (*set_target)(suspend_state_t state);
- int (*prepare)(suspend_state_t state);
- int (*enter)(suspend_state_t state);
- int (*finish)(suspend_state_t state);
-};
-
-#ifdef CONFIG_SUSPEND
-extern struct pm_ops *pm_ops;
-
-/**
- * pm_set_ops - set platform dependent power management ops
- * @pm_ops: The new power management operations to set.
- */
-extern void pm_set_ops(struct pm_ops *pm_ops);
-extern int pm_valid_only_mem(suspend_state_t state);
-
-/**
- * arch_suspend_disable_irqs - disable IRQs for suspend
- *
- * Disables IRQs (in the default case). This is a weak symbol in the common
- * code and thus allows architectures to override it if more needs to be
- * done. Not called for suspend to disk.
- */
-extern void arch_suspend_disable_irqs(void);
-
-/**
- * arch_suspend_enable_irqs - enable IRQs after suspend
- *
- * Enables IRQs (in the default case). This is a weak symbol in the common
- * code and thus allows architectures to override it if more needs to be
- * done. Not called for suspend to disk.
- */
-extern void arch_suspend_enable_irqs(void);
-
-extern int pm_suspend(suspend_state_t state);
-#else /* !CONFIG_SUSPEND */
-#define suspend_valid_only_mem NULL
-
-static inline void pm_set_ops(struct pm_ops *pm_ops) {}
-static inline int pm_suspend(suspend_state_t state) { return -ENOSYS; }
-#endif /* !CONFIG_SUSPEND */
-
/*
* Device power management
*/
diff --git a/include/linux/pnp.h b/include/linux/pnp.h
index 16b46aace349..664d68cb1fbd 100644
--- a/include/linux/pnp.h
+++ b/include/linux/pnp.h
@@ -243,11 +243,11 @@ struct pnp_fixup {
#define PNP_CONFIGURABLE 0x0008
#define PNP_REMOVABLE 0x0010
-#define pnp_can_read(dev) (((dev)->protocol) && ((dev)->protocol->get) && \
+#define pnp_can_read(dev) (((dev)->protocol->get) && \
((dev)->capabilities & PNP_READ))
-#define pnp_can_write(dev) (((dev)->protocol) && ((dev)->protocol->set) && \
+#define pnp_can_write(dev) (((dev)->protocol->set) && \
((dev)->capabilities & PNP_WRITE))
-#define pnp_can_disable(dev) (((dev)->protocol) && ((dev)->protocol->disable) && \
+#define pnp_can_disable(dev) (((dev)->protocol->disable) && \
((dev)->capabilities & PNP_DISABLE))
#define pnp_can_configure(dev) ((!(dev)->active) && \
((dev)->capabilities & PNP_CONFIGURABLE))
diff --git a/include/linux/poison.h b/include/linux/poison.h
index d93c300a3449..a9c31be7052c 100644
--- a/include/linux/poison.h
+++ b/include/linux/poison.h
@@ -36,7 +36,8 @@
*/
/********** fs/jbd/journal.c **********/
-#define JBD_POISON_FREE 0x5b
+#define JBD_POISON_FREE 0x5b
+#define JBD2_POISON_FREE 0x5c
/********** drivers/base/dmapool.c **********/
#define POOL_POISON_FREED 0xa7 /* !inuse */
diff --git a/include/linux/prefetch.h b/include/linux/prefetch.h
index 1adfe668d031..af7c36a5a521 100644
--- a/include/linux/prefetch.h
+++ b/include/linux/prefetch.h
@@ -34,17 +34,12 @@
*/
-/*
- * These cannot be do{}while(0) macros. See the mental gymnastics in
- * the loop macro.
- */
-
#ifndef ARCH_HAS_PREFETCH
-static inline void prefetch(const void *x) {;}
+#define prefetch(x) __builtin_prefetch(x)
#endif
#ifndef ARCH_HAS_PREFETCHW
-static inline void prefetchw(const void *x) {;}
+#define prefetchw(x) __builtin_prefetch(x,1)
#endif
#ifndef ARCH_HAS_SPINLOCK_PREFETCH
diff --git a/include/linux/prio_heap.h b/include/linux/prio_heap.h
new file mode 100644
index 000000000000..08094350f26a
--- /dev/null
+++ b/include/linux/prio_heap.h
@@ -0,0 +1,58 @@
+#ifndef _LINUX_PRIO_HEAP_H
+#define _LINUX_PRIO_HEAP_H
+
+/*
+ * Simple insertion-only static-sized priority heap containing
+ * pointers, based on CLR, chapter 7
+ */
+
+#include <linux/gfp.h>
+
+/**
+ * struct ptr_heap - simple static-sized priority heap
+ * @ptrs - pointer to data area
+ * @max - max number of elements that can be stored in @ptrs
+ * @size - current number of valid elements in @ptrs (in the range 0..@size-1
+ * @gt: comparison operator, which should implement "greater than"
+ */
+struct ptr_heap {
+ void **ptrs;
+ int max;
+ int size;
+ int (*gt)(void *, void *);
+};
+
+/**
+ * heap_init - initialize an empty heap with a given memory size
+ * @heap: the heap structure to be initialized
+ * @size: amount of memory to use in bytes
+ * @gfp_mask: mask to pass to kmalloc()
+ * @gt: comparison operator, which should implement "greater than"
+ */
+extern int heap_init(struct ptr_heap *heap, size_t size, gfp_t gfp_mask,
+ int (*gt)(void *, void *));
+
+/**
+ * heap_free - release a heap's storage
+ * @heap: the heap structure whose data should be released
+ */
+void heap_free(struct ptr_heap *heap);
+
+/**
+ * heap_insert - insert a value into the heap and return any overflowed value
+ * @heap: the heap to be operated on
+ * @p: the pointer to be inserted
+ *
+ * Attempts to insert the given value into the priority heap. If the
+ * heap is full prior to the insertion, then the resulting heap will
+ * consist of the smallest @max elements of the original heap and the
+ * new element; the greatest element will be removed from the heap and
+ * returned. Note that the returned element will be the new element
+ * (i.e. no change to the heap) if the new element is greater than all
+ * elements currently in the heap.
+ */
+extern void *heap_insert(struct ptr_heap *heap, void *p);
+
+
+
+#endif /* _LINUX_PRIO_HEAP_H */
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 20741f668f7b..1273c6ec535c 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -125,7 +125,8 @@ extern struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
extern void remove_proc_entry(const char *name, struct proc_dir_entry *parent);
extern struct vfsmount *proc_mnt;
-extern int proc_fill_super(struct super_block *,void *,int);
+struct pid_namespace;
+extern int proc_fill_super(struct super_block *);
extern struct inode *proc_get_inode(struct super_block *, unsigned int, struct proc_dir_entry *);
/*
@@ -142,6 +143,9 @@ extern const struct file_operations proc_kcore_operations;
extern const struct file_operations proc_kmsg_operations;
extern const struct file_operations ppc_htab_operations;
+extern int pid_ns_prepare_proc(struct pid_namespace *ns);
+extern void pid_ns_release_proc(struct pid_namespace *ns);
+
/*
* proc_tty.c
*/
@@ -192,8 +196,6 @@ static inline struct proc_dir_entry *create_proc_info_entry(const char *name,
return res;
}
-extern struct proc_dir_entry *proc_net_create(struct net *net,
- const char *name, mode_t mode, get_info_t *get_info);
extern struct proc_dir_entry *proc_net_fops_create(struct net *net,
const char *name, mode_t mode, const struct file_operations *fops);
extern void proc_net_remove(struct net *net, const char *name);
@@ -204,10 +206,11 @@ extern void proc_net_remove(struct net *net, const char *name);
#define proc_bus NULL
#define proc_net_fops_create(net, name, mode, fops) ({ (void)(mode), NULL; })
-#define proc_net_create(net, name, mode, info) ({ (void)(mode), NULL; })
static inline void proc_net_remove(struct net *net, const char *name) {}
-static inline void proc_flush_task(struct task_struct *task) { }
+static inline void proc_flush_task(struct task_struct *task)
+{
+}
static inline struct proc_dir_entry *create_proc_entry(const char *name,
mode_t mode, struct proc_dir_entry *parent) { return NULL; }
@@ -232,6 +235,15 @@ static inline void proc_tty_unregister_driver(struct tty_driver *driver) {};
extern struct proc_dir_entry proc_root;
+static inline int pid_ns_prepare_proc(struct pid_namespace *ns)
+{
+ return 0;
+}
+
+static inline void pid_ns_release_proc(struct pid_namespace *ns)
+{
+}
+
#endif /* CONFIG_PROC_FS */
#if !defined(CONFIG_PROC_KCORE)
diff --git a/include/linux/profile.h b/include/linux/profile.h
index eec48f5f9348..ff576d1db67d 100644
--- a/include/linux/profile.h
+++ b/include/linux/profile.h
@@ -78,9 +78,6 @@ int profile_event_unregister(enum profile_type, struct notifier_block * n);
int register_timer_hook(int (*hook)(struct pt_regs *));
void unregister_timer_hook(int (*hook)(struct pt_regs *));
-/* Timer based profiling hook */
-extern int (*timer_hook)(struct pt_regs *);
-
struct pt_regs;
#else
diff --git a/include/linux/proportions.h b/include/linux/proportions.h
new file mode 100644
index 000000000000..2c3b3cad92be
--- /dev/null
+++ b/include/linux/proportions.h
@@ -0,0 +1,119 @@
+/*
+ * FLoating proportions
+ *
+ * Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *
+ * This file contains the public data structure and API definitions.
+ */
+
+#ifndef _LINUX_PROPORTIONS_H
+#define _LINUX_PROPORTIONS_H
+
+#include <linux/percpu_counter.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+
+struct prop_global {
+ /*
+ * The period over which we differentiate
+ *
+ * period = 2^shift
+ */
+ int shift;
+ /*
+ * The total event counter aka 'time'.
+ *
+ * Treated as an unsigned long; the lower 'shift - 1' bits are the
+ * counter bits, the remaining upper bits the period counter.
+ */
+ struct percpu_counter events;
+};
+
+/*
+ * global proportion descriptor
+ *
+ * this is needed to consitently flip prop_global structures.
+ */
+struct prop_descriptor {
+ int index;
+ struct prop_global pg[2];
+ struct mutex mutex; /* serialize the prop_global switch */
+};
+
+int prop_descriptor_init(struct prop_descriptor *pd, int shift);
+void prop_change_shift(struct prop_descriptor *pd, int new_shift);
+
+/*
+ * ----- PERCPU ------
+ */
+
+struct prop_local_percpu {
+ /*
+ * the local events counter
+ */
+ struct percpu_counter events;
+
+ /*
+ * snapshot of the last seen global state
+ */
+ int shift;
+ unsigned long period;
+ spinlock_t lock; /* protect the snapshot state */
+};
+
+int prop_local_init_percpu(struct prop_local_percpu *pl);
+void prop_local_destroy_percpu(struct prop_local_percpu *pl);
+void __prop_inc_percpu(struct prop_descriptor *pd, struct prop_local_percpu *pl);
+void prop_fraction_percpu(struct prop_descriptor *pd, struct prop_local_percpu *pl,
+ long *numerator, long *denominator);
+
+static inline
+void prop_inc_percpu(struct prop_descriptor *pd, struct prop_local_percpu *pl)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ __prop_inc_percpu(pd, pl);
+ local_irq_restore(flags);
+}
+
+/*
+ * ----- SINGLE ------
+ */
+
+struct prop_local_single {
+ /*
+ * the local events counter
+ */
+ unsigned long events;
+
+ /*
+ * snapshot of the last seen global state
+ * and a lock protecting this state
+ */
+ int shift;
+ unsigned long period;
+ spinlock_t lock; /* protect the snapshot state */
+};
+
+#define INIT_PROP_LOCAL_SINGLE(name) \
+{ .lock = __SPIN_LOCK_UNLOCKED(name.lock), \
+}
+
+int prop_local_init_single(struct prop_local_single *pl);
+void prop_local_destroy_single(struct prop_local_single *pl);
+void __prop_inc_single(struct prop_descriptor *pd, struct prop_local_single *pl);
+void prop_fraction_single(struct prop_descriptor *pd, struct prop_local_single *pl,
+ long *numerator, long *denominator);
+
+static inline
+void prop_inc_single(struct prop_descriptor *pd, struct prop_local_single *pl)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ __prop_inc_single(pd, pl);
+ local_irq_restore(flags);
+}
+
+#endif /* _LINUX_PROPORTIONS_H */
diff --git a/include/linux/quota.h b/include/linux/quota.h
index 62439828395e..6e0393a5b2ea 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -128,6 +128,37 @@ struct if_dqinfo {
__u32 dqi_valid;
};
+/*
+ * Definitions for quota netlink interface
+ */
+#define QUOTA_NL_NOWARN 0
+#define QUOTA_NL_IHARDWARN 1 /* Inode hardlimit reached */
+#define QUOTA_NL_ISOFTLONGWARN 2 /* Inode grace time expired */
+#define QUOTA_NL_ISOFTWARN 3 /* Inode softlimit reached */
+#define QUOTA_NL_BHARDWARN 4 /* Block hardlimit reached */
+#define QUOTA_NL_BSOFTLONGWARN 5 /* Block grace time expired */
+#define QUOTA_NL_BSOFTWARN 6 /* Block softlimit reached */
+
+enum {
+ QUOTA_NL_C_UNSPEC,
+ QUOTA_NL_C_WARNING,
+ __QUOTA_NL_C_MAX,
+};
+#define QUOTA_NL_C_MAX (__QUOTA_NL_C_MAX - 1)
+
+enum {
+ QUOTA_NL_A_UNSPEC,
+ QUOTA_NL_A_QTYPE,
+ QUOTA_NL_A_EXCESS_ID,
+ QUOTA_NL_A_WARNING,
+ QUOTA_NL_A_DEV_MAJOR,
+ QUOTA_NL_A_DEV_MINOR,
+ QUOTA_NL_A_CAUSED_ID,
+ __QUOTA_NL_A_MAX,
+};
+#define QUOTA_NL_A_MAX (__QUOTA_NL_A_MAX - 1)
+
+
#ifdef __KERNEL__
#include <linux/spinlock.h>
#include <linux/rwsem.h>
diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h
index f9e77d2ee320..b6116b4445c7 100644
--- a/include/linux/radix-tree.h
+++ b/include/linux/radix-tree.h
@@ -26,28 +26,31 @@
#include <linux/rcupdate.h>
/*
- * A direct pointer (root->rnode pointing directly to a data item,
- * rather than another radix_tree_node) is signalled by the low bit
- * set in the root->rnode pointer.
+ * An indirect pointer (root->rnode pointing to a radix_tree_node, rather
+ * than a data item) is signalled by the low bit set in the root->rnode
+ * pointer.
*
- * In this case root->height is also NULL, but the direct pointer tests are
- * needed for RCU lookups when root->height is unreliable.
+ * In this case root->height is > 0, but the indirect pointer tests are
+ * needed for RCU lookups (because root->height is unreliable). The only
+ * time callers need worry about this is when doing a lookup_slot under
+ * RCU.
*/
-#define RADIX_TREE_DIRECT_PTR 1
+#define RADIX_TREE_INDIRECT_PTR 1
+#define RADIX_TREE_RETRY ((void *)-1UL)
-static inline void *radix_tree_ptr_to_direct(void *ptr)
+static inline void *radix_tree_ptr_to_indirect(void *ptr)
{
- return (void *)((unsigned long)ptr | RADIX_TREE_DIRECT_PTR);
+ return (void *)((unsigned long)ptr | RADIX_TREE_INDIRECT_PTR);
}
-static inline void *radix_tree_direct_to_ptr(void *ptr)
+static inline void *radix_tree_indirect_to_ptr(void *ptr)
{
- return (void *)((unsigned long)ptr & ~RADIX_TREE_DIRECT_PTR);
+ return (void *)((unsigned long)ptr & ~RADIX_TREE_INDIRECT_PTR);
}
-static inline int radix_tree_is_direct_ptr(void *ptr)
+static inline int radix_tree_is_indirect_ptr(void *ptr)
{
- return (int)((unsigned long)ptr & RADIX_TREE_DIRECT_PTR);
+ return (int)((unsigned long)ptr & RADIX_TREE_INDIRECT_PTR);
}
/*** radix-tree API starts here ***/
@@ -130,7 +133,10 @@ do { \
*/
static inline void *radix_tree_deref_slot(void **pslot)
{
- return radix_tree_direct_to_ptr(*pslot);
+ void *ret = *pslot;
+ if (unlikely(radix_tree_is_indirect_ptr(ret)))
+ ret = RADIX_TREE_RETRY;
+ return ret;
}
/**
* radix_tree_replace_slot - replace item in a slot
@@ -142,10 +148,8 @@ static inline void *radix_tree_deref_slot(void **pslot)
*/
static inline void radix_tree_replace_slot(void **pslot, void *item)
{
- BUG_ON(radix_tree_is_direct_ptr(item));
- rcu_assign_pointer(*pslot,
- (void *)((unsigned long)item |
- ((unsigned long)*pslot & RADIX_TREE_DIRECT_PTR)));
+ BUG_ON(radix_tree_is_indirect_ptr(item));
+ rcu_assign_pointer(*pslot, item);
}
int radix_tree_insert(struct radix_tree_root *, unsigned long, void *);
@@ -155,6 +159,8 @@ void *radix_tree_delete(struct radix_tree_root *, unsigned long);
unsigned int
radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
unsigned long first_index, unsigned int max_items);
+unsigned long radix_tree_next_hole(struct radix_tree_root *root,
+ unsigned long index, unsigned long max_scan);
int radix_tree_preload(gfp_t gfp_mask);
void radix_tree_init(void);
void *radix_tree_tag_set(struct radix_tree_root *root,
diff --git a/include/linux/raid/bitmap.h b/include/linux/raid/bitmap.h
index 75e17a05540e..306a1d1a5af0 100644
--- a/include/linux/raid/bitmap.h
+++ b/include/linux/raid/bitmap.h
@@ -138,7 +138,6 @@ typedef __u16 bitmap_counter_t;
/* use these for bitmap->flags and bitmap->sb->state bit-fields */
enum bitmap_state {
- BITMAP_ACTIVE = 0x001, /* the bitmap is in use */
BITMAP_STALE = 0x002, /* the bitmap file is out of date or had -EIO */
BITMAP_WRITE_ERROR = 0x004, /* A write error has occurred */
BITMAP_HOSTENDIAN = 0x8000,
@@ -258,7 +257,6 @@ struct bitmap {
int bitmap_create(mddev_t *mddev);
void bitmap_flush(mddev_t *mddev);
void bitmap_destroy(mddev_t *mddev);
-int bitmap_active(struct bitmap *bitmap);
char *file_path(struct file *file, char *buf, int count);
void bitmap_print_sb(struct bitmap *bitmap);
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 76c1a530edc5..cc24a01df940 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -231,6 +231,18 @@ extern struct lockdep_map rcu_lock_map;
local_bh_enable(); \
} while(0)
+/*
+ * Prevent the compiler from merging or refetching accesses. The compiler
+ * is also forbidden from reordering successive instances of ACCESS_ONCE(),
+ * but only when the compiler is aware of some particular ordering. One way
+ * to make the compiler aware of ordering is to put the two invocations of
+ * ACCESS_ONCE() in different C statements.
+ *
+ * This macro does absolutely -nothing- to prevent the CPU from reordering,
+ * merging, or refetching absolutely anything at any time.
+ */
+#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
+
/**
* rcu_dereference - fetch an RCU-protected pointer in an
* RCU read-side critical section. This pointer may later
@@ -242,7 +254,7 @@ extern struct lockdep_map rcu_lock_map;
*/
#define rcu_dereference(p) ({ \
- typeof(p) _________p1 = p; \
+ typeof(p) _________p1 = ACCESS_ONCE(p); \
smp_read_barrier_depends(); \
(_________p1); \
})
diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
index 180a9d832dde..422eab4958a6 100644
--- a/include/linux/reiserfs_fs.h
+++ b/include/linux/reiserfs_fs.h
@@ -28,6 +28,8 @@
#include <linux/reiserfs_fs_sb.h>
#endif
+struct fid;
+
/*
* include/linux/reiser_fs.h
*
@@ -85,7 +87,7 @@ void reiserfs_warning(struct super_block *s, const char *fmt, ...);
if( !( cond ) ) \
reiserfs_panic( NULL, "reiserfs[%i]: assertion " scond " failed at " \
__FILE__ ":%i:%s: " format "\n", \
- in_interrupt() ? -1 : current -> pid, __LINE__ , __FUNCTION__ , ##args )
+ in_interrupt() ? -1 : task_pid_nr(current), __LINE__ , __FUNCTION__ , ##args )
#define RASSERT(cond, format, args...) __RASSERT(cond, #cond, format, ##args)
@@ -283,6 +285,18 @@ static inline struct reiserfs_sb_info *REISERFS_SB(const struct super_block *sb)
return sb->s_fs_info;
}
+/* Don't trust REISERFS_SB(sb)->s_bmap_nr, it's a u16
+ * which overflows on large file systems. */
+static inline u32 reiserfs_bmap_count(struct super_block *sb)
+{
+ return (SB_BLOCK_COUNT(sb) - 1) / (sb->s_blocksize * 8) + 1;
+}
+
+static inline int bmap_would_wrap(unsigned bmap_nr)
+{
+ return bmap_nr > ((1LL << 16) - 1);
+}
+
/** this says about version of key of all items (but stat data) the
object consists of */
#define get_inode_item_key_version( inode ) \
@@ -1703,8 +1717,6 @@ static inline int reiserfs_transaction_free_space(struct reiserfs_transaction_ha
return th->t_blocks_allocated - th->t_blocks_logged;
}
-int reiserfs_async_progress_wait(struct super_block *s);
-
struct reiserfs_transaction_handle *reiserfs_persistent_transaction(struct
super_block
*,
@@ -1736,8 +1748,8 @@ int journal_end_sync(struct reiserfs_transaction_handle *, struct super_block *,
int journal_mark_freed(struct reiserfs_transaction_handle *,
struct super_block *, b_blocknr_t blocknr);
int journal_transaction_should_end(struct reiserfs_transaction_handle *, int);
-int reiserfs_in_journal(struct super_block *p_s_sb, int bmap_nr, int bit_nr,
- int searchall, b_blocknr_t * next);
+int reiserfs_in_journal(struct super_block *p_s_sb, unsigned int bmap_nr,
+ int bit_nr, int searchall, b_blocknr_t *next);
int journal_begin(struct reiserfs_transaction_handle *,
struct super_block *p_s_sb, unsigned long);
int journal_join_abort(struct reiserfs_transaction_handle *,
@@ -1745,7 +1757,7 @@ int journal_join_abort(struct reiserfs_transaction_handle *,
void reiserfs_journal_abort(struct super_block *sb, int errno);
void reiserfs_abort(struct super_block *sb, int errno, const char *fmt, ...);
int reiserfs_allocate_list_bitmaps(struct super_block *s,
- struct reiserfs_list_bitmap *, int);
+ struct reiserfs_list_bitmap *, unsigned int);
void add_save_link(struct reiserfs_transaction_handle *th,
struct inode *inode, int truncate);
@@ -1859,8 +1871,6 @@ void padd_item(char *item, int total_length, int length);
#define GET_BLOCK_NO_IMUX 8 /* i_mutex is not held, don't preallocate */
#define GET_BLOCK_NO_DANGLE 16 /* don't leave any transactions running */
-int restart_transaction(struct reiserfs_transaction_handle *th,
- struct inode *inode, struct treepath *path);
void reiserfs_read_locked_inode(struct inode *inode,
struct reiserfs_iget_args *args);
int reiserfs_find_actor(struct inode *inode, void *p);
@@ -1869,12 +1879,10 @@ void reiserfs_delete_inode(struct inode *inode);
int reiserfs_write_inode(struct inode *inode, int);
int reiserfs_get_block(struct inode *inode, sector_t block,
struct buffer_head *bh_result, int create);
-struct dentry *reiserfs_get_dentry(struct super_block *, void *);
-struct dentry *reiserfs_decode_fh(struct super_block *sb, __u32 * data,
- int len, int fhtype,
- int (*acceptable) (void *contect,
- struct dentry * de),
- void *context);
+struct dentry *reiserfs_fh_to_dentry(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type);
+struct dentry *reiserfs_fh_to_parent(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type);
int reiserfs_encode_fh(struct dentry *dentry, __u32 * data, int *lenp,
int connectable);
@@ -2045,7 +2053,7 @@ struct buffer_head *get_FEB(struct tree_balance *);
* arguments, such as node, search path, transaction_handle, etc. */
struct __reiserfs_blocknr_hint {
struct inode *inode; /* inode passed to allocator, if we allocate unf. nodes */
- long block; /* file offset, in blocks */
+ sector_t block; /* file offset, in blocks */
struct in_core_key key;
struct treepath *path; /* search path, used by allocator to deternine search_start by
* various ways */
@@ -2103,7 +2111,8 @@ static inline int reiserfs_new_form_blocknrs(struct tree_balance *tb,
static inline int reiserfs_new_unf_blocknrs(struct reiserfs_transaction_handle
*th, struct inode *inode,
b_blocknr_t * new_blocknrs,
- struct treepath *path, long block)
+ struct treepath *path,
+ sector_t block)
{
reiserfs_blocknr_hint_t hint = {
.th = th,
@@ -2120,7 +2129,8 @@ static inline int reiserfs_new_unf_blocknrs(struct reiserfs_transaction_handle
static inline int reiserfs_new_unf_blocknrs2(struct reiserfs_transaction_handle
*th, struct inode *inode,
b_blocknr_t * new_blocknrs,
- struct treepath *path, long block)
+ struct treepath *path,
+ sector_t block)
{
reiserfs_blocknr_hint_t hint = {
.th = th,
@@ -2137,9 +2147,6 @@ void reiserfs_discard_prealloc(struct reiserfs_transaction_handle *th,
struct inode *inode);
void reiserfs_discard_all_prealloc(struct reiserfs_transaction_handle *th);
#endif
-void reiserfs_claim_blocks_to_be_allocated(struct super_block *sb, int blocks);
-void reiserfs_release_claimed_blocks(struct super_block *sb, int blocks);
-int reiserfs_can_fit_pages(struct super_block *sb);
/* hashes.c */
__u32 keyed_hash(const signed char *msg, int len);
diff --git a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h
index ff9e9234f8ba..10fa0c832018 100644
--- a/include/linux/reiserfs_fs_sb.h
+++ b/include/linux/reiserfs_fs_sb.h
@@ -265,9 +265,7 @@ enum journal_state_bits {
typedef __u32(*hashf_t) (const signed char *, int);
struct reiserfs_bitmap_info {
- // FIXME: Won't work with block sizes > 8K
- __u16 first_zero_hint;
- __u16 free_count;
+ __u32 free_count;
};
struct proc_dir_entry;
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 5bf618241ab9..4e81836191df 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -491,9 +491,11 @@ struct nduseroptmsg
unsigned char nduseropt_family;
unsigned char nduseropt_pad1;
unsigned short nduseropt_opts_len; /* Total length of options */
+ int nduseropt_ifindex;
__u8 nduseropt_icmp_type;
__u8 nduseropt_icmp_code;
unsigned short nduseropt_pad2;
+ unsigned int nduseropt_pad3;
/* Followed by one or more ND options */
};
diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h
index 4efbd9c445f5..259735044148 100644
--- a/include/linux/scatterlist.h
+++ b/include/linux/scatterlist.h
@@ -1,23 +1,281 @@
#ifndef _LINUX_SCATTERLIST_H
#define _LINUX_SCATTERLIST_H
+#include <asm/types.h>
#include <asm/scatterlist.h>
#include <linux/mm.h>
#include <linux/string.h>
+#include <asm/io.h>
+/*
+ * Notes on SG table design.
+ *
+ * Architectures must provide an unsigned long page_link field in the
+ * scatterlist struct. We use that to place the page pointer AND encode
+ * information about the sg table as well. The two lower bits are reserved
+ * for this information.
+ *
+ * If bit 0 is set, then the page_link contains a pointer to the next sg
+ * table list. Otherwise the next entry is at sg + 1.
+ *
+ * If bit 1 is set, then this sg entry is the last element in a list.
+ *
+ * See sg_next().
+ *
+ */
+
+#define SG_MAGIC 0x87654321
+
+/**
+ * sg_assign_page - Assign a given page to an SG entry
+ * @sg: SG entry
+ * @page: The page
+ *
+ * Description:
+ * Assign page to sg entry. Also see sg_set_page(), the most commonly used
+ * variant.
+ *
+ **/
+static inline void sg_assign_page(struct scatterlist *sg, struct page *page)
+{
+ unsigned long page_link = sg->page_link & 0x3;
+
+ /*
+ * In order for the low bit stealing approach to work, pages
+ * must be aligned at a 32-bit boundary as a minimum.
+ */
+ BUG_ON((unsigned long) page & 0x03);
+#ifdef CONFIG_DEBUG_SG
+ BUG_ON(sg->sg_magic != SG_MAGIC);
+#endif
+ sg->page_link = page_link | (unsigned long) page;
+}
+
+/**
+ * sg_set_page - Set sg entry to point at given page
+ * @sg: SG entry
+ * @page: The page
+ * @len: Length of data
+ * @offset: Offset into page
+ *
+ * Description:
+ * Use this function to set an sg entry pointing at a page, never assign
+ * the page directly. We encode sg table information in the lower bits
+ * of the page pointer. See sg_page() for looking up the page belonging
+ * to an sg entry.
+ *
+ **/
+static inline void sg_set_page(struct scatterlist *sg, struct page *page,
+ unsigned int len, unsigned int offset)
+{
+ sg_assign_page(sg, page);
+ sg->offset = offset;
+ sg->length = len;
+}
+
+#define sg_page(sg) ((struct page *) ((sg)->page_link & ~0x3))
+
+/**
+ * sg_set_buf - Set sg entry to point at given data
+ * @sg: SG entry
+ * @buf: Data
+ * @buflen: Data length
+ *
+ **/
static inline void sg_set_buf(struct scatterlist *sg, const void *buf,
unsigned int buflen)
{
- sg->page = virt_to_page(buf);
- sg->offset = offset_in_page(buf);
- sg->length = buflen;
+ sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf));
}
+/*
+ * We overload the LSB of the page pointer to indicate whether it's
+ * a valid sg entry, or whether it points to the start of a new scatterlist.
+ * Those low bits are there for everyone! (thanks mason :-)
+ */
+#define sg_is_chain(sg) ((sg)->page_link & 0x01)
+#define sg_is_last(sg) ((sg)->page_link & 0x02)
+#define sg_chain_ptr(sg) \
+ ((struct scatterlist *) ((sg)->page_link & ~0x03))
+
+/**
+ * sg_next - return the next scatterlist entry in a list
+ * @sg: The current sg entry
+ *
+ * Description:
+ * Usually the next entry will be @sg@ + 1, but if this sg element is part
+ * of a chained scatterlist, it could jump to the start of a new
+ * scatterlist array.
+ *
+ **/
+static inline struct scatterlist *sg_next(struct scatterlist *sg)
+{
+#ifdef CONFIG_DEBUG_SG
+ BUG_ON(sg->sg_magic != SG_MAGIC);
+#endif
+ if (sg_is_last(sg))
+ return NULL;
+
+ sg++;
+ if (unlikely(sg_is_chain(sg)))
+ sg = sg_chain_ptr(sg);
+
+ return sg;
+}
+
+/*
+ * Loop over each sg element, following the pointer to a new list if necessary
+ */
+#define for_each_sg(sglist, sg, nr, __i) \
+ for (__i = 0, sg = (sglist); __i < (nr); __i++, sg = sg_next(sg))
+
+/**
+ * sg_last - return the last scatterlist entry in a list
+ * @sgl: First entry in the scatterlist
+ * @nents: Number of entries in the scatterlist
+ *
+ * Description:
+ * Should only be used casually, it (currently) scan the entire list
+ * to get the last entry.
+ *
+ * Note that the @sgl@ pointer passed in need not be the first one,
+ * the important bit is that @nents@ denotes the number of entries that
+ * exist from @sgl@.
+ *
+ **/
+static inline struct scatterlist *sg_last(struct scatterlist *sgl,
+ unsigned int nents)
+{
+#ifndef ARCH_HAS_SG_CHAIN
+ struct scatterlist *ret = &sgl[nents - 1];
+#else
+ struct scatterlist *sg, *ret = NULL;
+ unsigned int i;
+
+ for_each_sg(sgl, sg, nents, i)
+ ret = sg;
+
+#endif
+#ifdef CONFIG_DEBUG_SG
+ BUG_ON(sgl[0].sg_magic != SG_MAGIC);
+ BUG_ON(!sg_is_last(ret));
+#endif
+ return ret;
+}
+
+/**
+ * sg_chain - Chain two sglists together
+ * @prv: First scatterlist
+ * @prv_nents: Number of entries in prv
+ * @sgl: Second scatterlist
+ *
+ * Description:
+ * Links @prv@ and @sgl@ together, to form a longer scatterlist.
+ *
+ **/
+static inline void sg_chain(struct scatterlist *prv, unsigned int prv_nents,
+ struct scatterlist *sgl)
+{
+#ifndef ARCH_HAS_SG_CHAIN
+ BUG();
+#endif
+ /*
+ * Set lowest bit to indicate a link pointer, and make sure to clear
+ * the termination bit if it happens to be set.
+ */
+ prv[prv_nents - 1].page_link = ((unsigned long) sgl | 0x01) & ~0x02;
+}
+
+/**
+ * sg_mark_end - Mark the end of the scatterlist
+ * @sg: SG entryScatterlist
+ *
+ * Description:
+ * Marks the passed in sg entry as the termination point for the sg
+ * table. A call to sg_next() on this entry will return NULL.
+ *
+ **/
+static inline void sg_mark_end(struct scatterlist *sg)
+{
+#ifdef CONFIG_DEBUG_SG
+ BUG_ON(sg->sg_magic != SG_MAGIC);
+#endif
+ /*
+ * Set termination bit, clear potential chain bit
+ */
+ sg->page_link |= 0x02;
+ sg->page_link &= ~0x01;
+}
+
+/**
+ * sg_init_table - Initialize SG table
+ * @sgl: The SG table
+ * @nents: Number of entries in table
+ *
+ * Notes:
+ * If this is part of a chained sg table, sg_mark_end() should be
+ * used only on the last table part.
+ *
+ **/
+static inline void sg_init_table(struct scatterlist *sgl, unsigned int nents)
+{
+ memset(sgl, 0, sizeof(*sgl) * nents);
+#ifdef CONFIG_DEBUG_SG
+ {
+ unsigned int i;
+ for (i = 0; i < nents; i++)
+ sgl[i].sg_magic = SG_MAGIC;
+ }
+#endif
+ sg_mark_end(&sgl[nents - 1]);
+}
+
+/**
+ * sg_init_one - Initialize a single entry sg list
+ * @sg: SG entry
+ * @buf: Virtual address for IO
+ * @buflen: IO length
+ *
+ * Notes:
+ * This should not be used on a single entry that is part of a larger
+ * table. Use sg_init_table() for that.
+ *
+ **/
static inline void sg_init_one(struct scatterlist *sg, const void *buf,
unsigned int buflen)
{
- memset(sg, 0, sizeof(*sg));
+ sg_init_table(sg, 1);
sg_set_buf(sg, buf, buflen);
}
+/**
+ * sg_phys - Return physical address of an sg entry
+ * @sg: SG entry
+ *
+ * Description:
+ * This calls page_to_phys() on the page in this sg entry, and adds the
+ * sg offset. The caller must know that it is legal to call page_to_phys()
+ * on the sg page.
+ *
+ **/
+static inline dma_addr_t sg_phys(struct scatterlist *sg)
+{
+ return page_to_phys(sg_page(sg)) + sg->offset;
+}
+
+/**
+ * sg_virt - Return virtual address of an sg entry
+ * @sg: SG entry
+ *
+ * Description:
+ * This calls page_address() on the page in this sg entry, and adds the
+ * sg offset. The caller must know that the sg page has a valid virtual
+ * mapping.
+ *
+ **/
+static inline void *sg_virt(struct scatterlist *sg)
+{
+ return page_address(sg_page(sg)) + sg->offset;
+}
+
#endif /* _LINUX_SCATTERLIST_H */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 228e0a8ce248..ee800e7a70de 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1,8 +1,6 @@
#ifndef _LINUX_SCHED_H
#define _LINUX_SCHED_H
-#include <linux/auxvec.h> /* For AT_VECTOR_SIZE */
-
/*
* cloning flags:
*/
@@ -27,6 +25,7 @@
#define CLONE_NEWUTS 0x04000000 /* New utsname group? */
#define CLONE_NEWIPC 0x08000000 /* New ipcs */
#define CLONE_NEWUSER 0x10000000 /* New user namespace */
+#define CLONE_NEWPID 0x20000000 /* New pid namespace */
#define CLONE_NEWNET 0x40000000 /* New network namespace */
/*
@@ -58,12 +57,12 @@ struct sched_param {
#include <linux/cpumask.h>
#include <linux/errno.h>
#include <linux/nodemask.h>
+#include <linux/mm_types.h>
#include <asm/system.h>
#include <asm/semaphore.h>
#include <asm/page.h>
#include <asm/ptrace.h>
-#include <asm/mmu.h>
#include <asm/cputime.h>
#include <linux/smp.h>
@@ -76,6 +75,7 @@ struct sched_param {
#include <linux/pid.h>
#include <linux/percpu.h>
#include <linux/topology.h>
+#include <linux/proportions.h>
#include <linux/seccomp.h>
#include <linux/rcupdate.h>
#include <linux/futex.h>
@@ -254,6 +254,7 @@ long io_schedule_timeout(long timeout);
extern void cpu_init (void);
extern void trap_init(void);
+extern void account_process_tick(struct task_struct *task, int user);
extern void update_process_times(int user);
extern void scheduler_tick(void);
@@ -262,6 +263,7 @@ extern void softlockup_tick(void);
extern void spawn_softlockup_task(void);
extern void touch_softlockup_watchdog(void);
extern void touch_all_softlockup_watchdogs(void);
+extern int softlockup_thresh;
#else
static inline void softlockup_tick(void)
{
@@ -319,7 +321,6 @@ extern void arch_unmap_area_topdown(struct mm_struct *, unsigned long);
#define add_mm_counter(mm, member, value) atomic_long_add(value, &(mm)->_##member)
#define inc_mm_counter(mm, member) atomic_long_inc(&(mm)->_##member)
#define dec_mm_counter(mm, member) atomic_long_dec(&(mm)->_##member)
-typedef atomic_long_t mm_counter_t;
#else /* NR_CPUS < CONFIG_SPLIT_PTLOCK_CPUS */
/*
@@ -331,7 +332,6 @@ typedef atomic_long_t mm_counter_t;
#define add_mm_counter(mm, member, value) (mm)->_##member += (value)
#define inc_mm_counter(mm, member) (mm)->_##member++
#define dec_mm_counter(mm, member) (mm)->_##member--
-typedef unsigned long mm_counter_t;
#endif /* NR_CPUS < CONFIG_SPLIT_PTLOCK_CPUS */
@@ -361,81 +361,14 @@ extern int get_dumpable(struct mm_struct *mm);
#define MMF_DUMP_ANON_SHARED 3
#define MMF_DUMP_MAPPED_PRIVATE 4
#define MMF_DUMP_MAPPED_SHARED 5
+#define MMF_DUMP_ELF_HEADERS 6
#define MMF_DUMP_FILTER_SHIFT MMF_DUMPABLE_BITS
-#define MMF_DUMP_FILTER_BITS 4
+#define MMF_DUMP_FILTER_BITS 5
#define MMF_DUMP_FILTER_MASK \
(((1 << MMF_DUMP_FILTER_BITS) - 1) << MMF_DUMP_FILTER_SHIFT)
#define MMF_DUMP_FILTER_DEFAULT \
((1 << MMF_DUMP_ANON_PRIVATE) | (1 << MMF_DUMP_ANON_SHARED))
-struct mm_struct {
- struct vm_area_struct * mmap; /* list of VMAs */
- struct rb_root mm_rb;
- struct vm_area_struct * mmap_cache; /* last find_vma result */
- unsigned long (*get_unmapped_area) (struct file *filp,
- unsigned long addr, unsigned long len,
- unsigned long pgoff, unsigned long flags);
- void (*unmap_area) (struct mm_struct *mm, unsigned long addr);
- unsigned long mmap_base; /* base of mmap area */
- unsigned long task_size; /* size of task vm space */
- unsigned long cached_hole_size; /* if non-zero, the largest hole below free_area_cache */
- unsigned long free_area_cache; /* first hole of size cached_hole_size or larger */
- pgd_t * pgd;
- atomic_t mm_users; /* How many users with user space? */
- atomic_t mm_count; /* How many references to "struct mm_struct" (users count as 1) */
- int map_count; /* number of VMAs */
- struct rw_semaphore mmap_sem;
- spinlock_t page_table_lock; /* Protects page tables and some counters */
-
- struct list_head mmlist; /* List of maybe swapped mm's. These are globally strung
- * together off init_mm.mmlist, and are protected
- * by mmlist_lock
- */
-
- /* Special counters, in some configurations protected by the
- * page_table_lock, in other configurations by being atomic.
- */
- mm_counter_t _file_rss;
- mm_counter_t _anon_rss;
-
- unsigned long hiwater_rss; /* High-watermark of RSS usage */
- unsigned long hiwater_vm; /* High-water virtual memory usage */
-
- unsigned long total_vm, locked_vm, shared_vm, exec_vm;
- unsigned long stack_vm, reserved_vm, def_flags, nr_ptes;
- unsigned long start_code, end_code, start_data, end_data;
- unsigned long start_brk, brk, start_stack;
- unsigned long arg_start, arg_end, env_start, env_end;
-
- unsigned long saved_auxv[AT_VECTOR_SIZE]; /* for /proc/PID/auxv */
-
- cpumask_t cpu_vm_mask;
-
- /* Architecture-specific MM context */
- mm_context_t context;
-
- /* Swap token stuff */
- /*
- * Last value of global fault stamp as seen by this process.
- * In other words, this value gives an indication of how long
- * it has been since this task got the token.
- * Look at mm/thrash.c
- */
- unsigned int faultstamp;
- unsigned int token_priority;
- unsigned int last_interval;
-
- unsigned long flags; /* Must use atomic bitops to access the bits */
-
- /* coredumping support */
- int core_waiters;
- struct completion *core_startup_done, core_done;
-
- /* aio bits */
- rwlock_t ioctx_list_lock;
- struct kioctx *ioctx_list;
-};
-
struct sighand_struct {
atomic_t count;
struct k_sigaction action[_NSIG];
@@ -497,7 +430,17 @@ struct signal_struct {
cputime_t it_prof_incr, it_virt_incr;
/* job control IDs */
- pid_t pgrp;
+
+ /*
+ * pgrp and session fields are deprecated.
+ * use the task_session_Xnr and task_pgrp_Xnr routines below
+ */
+
+ union {
+ pid_t pgrp __deprecated;
+ pid_t __pgrp;
+ };
+
struct pid *tty_old_pgrp;
union {
@@ -587,8 +530,10 @@ struct user_struct {
atomic_t inotify_watches; /* How many inotify watches does this user have? */
atomic_t inotify_devs; /* How many inotify devs does this user have opened? */
#endif
+#ifdef CONFIG_POSIX_MQUEUE
/* protected by mq_lock */
unsigned long mq_bytes; /* How many bytes can be allocated to mqueue? */
+#endif
unsigned long locked_shm; /* How many pages of mlocked shm ? */
#ifdef CONFIG_KEYS
@@ -602,10 +547,12 @@ struct user_struct {
#ifdef CONFIG_FAIR_USER_SCHED
struct task_group *tg;
+#ifdef CONFIG_SYSFS
struct kset kset;
struct subsys_attribute user_attr;
struct work_struct work;
#endif
+#endif
};
#ifdef CONFIG_FAIR_USER_SCHED
@@ -634,7 +581,7 @@ struct sched_info {
last_queued; /* when we were last queued to run */
#ifdef CONFIG_SCHEDSTATS
/* BKL stats */
- unsigned long bkl_count;
+ unsigned int bkl_count;
#endif
};
#endif /* defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT) */
@@ -770,39 +717,38 @@ struct sched_domain {
#ifdef CONFIG_SCHEDSTATS
/* load_balance() stats */
- unsigned long lb_count[CPU_MAX_IDLE_TYPES];
- unsigned long lb_failed[CPU_MAX_IDLE_TYPES];
- unsigned long lb_balanced[CPU_MAX_IDLE_TYPES];
- unsigned long lb_imbalance[CPU_MAX_IDLE_TYPES];
- unsigned long lb_gained[CPU_MAX_IDLE_TYPES];
- unsigned long lb_hot_gained[CPU_MAX_IDLE_TYPES];
- unsigned long lb_nobusyg[CPU_MAX_IDLE_TYPES];
- unsigned long lb_nobusyq[CPU_MAX_IDLE_TYPES];
+ unsigned int lb_count[CPU_MAX_IDLE_TYPES];
+ unsigned int lb_failed[CPU_MAX_IDLE_TYPES];
+ unsigned int lb_balanced[CPU_MAX_IDLE_TYPES];
+ unsigned int lb_imbalance[CPU_MAX_IDLE_TYPES];
+ unsigned int lb_gained[CPU_MAX_IDLE_TYPES];
+ unsigned int lb_hot_gained[CPU_MAX_IDLE_TYPES];
+ unsigned int lb_nobusyg[CPU_MAX_IDLE_TYPES];
+ unsigned int lb_nobusyq[CPU_MAX_IDLE_TYPES];
/* Active load balancing */
- unsigned long alb_count;
- unsigned long alb_failed;
- unsigned long alb_pushed;
+ unsigned int alb_count;
+ unsigned int alb_failed;
+ unsigned int alb_pushed;
/* SD_BALANCE_EXEC stats */
- unsigned long sbe_count;
- unsigned long sbe_balanced;
- unsigned long sbe_pushed;
+ unsigned int sbe_count;
+ unsigned int sbe_balanced;
+ unsigned int sbe_pushed;
/* SD_BALANCE_FORK stats */
- unsigned long sbf_count;
- unsigned long sbf_balanced;
- unsigned long sbf_pushed;
+ unsigned int sbf_count;
+ unsigned int sbf_balanced;
+ unsigned int sbf_pushed;
/* try_to_wake_up() stats */
- unsigned long ttwu_wake_remote;
- unsigned long ttwu_move_affine;
- unsigned long ttwu_move_balance;
+ unsigned int ttwu_wake_remote;
+ unsigned int ttwu_move_affine;
+ unsigned int ttwu_move_balance;
#endif
};
-extern int partition_sched_domains(cpumask_t *partition1,
- cpumask_t *partition2);
+extern void partition_sched_domains(int ndoms_new, cpumask_t *doms_new);
#endif /* CONFIG_SMP */
@@ -824,8 +770,6 @@ static inline int above_background_load(void)
}
struct io_context; /* See blkdev.h */
-struct cpuset;
-
#define NGROUPS_SMALL 32
#define NGROUPS_PER_BLOCK ((int)(PAGE_SIZE / sizeof(gid_t)))
struct group_info {
@@ -885,12 +829,17 @@ struct sched_class {
struct task_struct * (*pick_next_task) (struct rq *rq);
void (*put_prev_task) (struct rq *rq, struct task_struct *p);
+#ifdef CONFIG_SMP
unsigned long (*load_balance) (struct rq *this_rq, int this_cpu,
- struct rq *busiest,
- unsigned long max_nr_move, unsigned long max_load_move,
+ struct rq *busiest, unsigned long max_load_move,
struct sched_domain *sd, enum cpu_idle_type idle,
int *all_pinned, int *this_best_prio);
+ int (*move_one_task) (struct rq *this_rq, int this_cpu,
+ struct rq *busiest, struct sched_domain *sd,
+ enum cpu_idle_type idle);
+#endif
+
void (*set_curr_task) (struct rq *rq);
void (*task_tick) (struct rq *rq, struct task_struct *p);
void (*task_new) (struct rq *rq, struct task_struct *p);
@@ -914,7 +863,6 @@ struct sched_entity {
struct load_weight load; /* for load-balancing */
struct rb_node run_node;
unsigned int on_rq;
- int peer_preempt;
u64 exec_start;
u64 sum_exec_runtime;
@@ -988,6 +936,16 @@ struct task_struct {
#endif
unsigned short ioprio;
+ /*
+ * fpu_counter contains the number of consecutive context switches
+ * that the FPU is used. If this is over a threshold, the lazy fpu
+ * saving becomes unlazy to save the trap. This is an unsigned char
+ * so that after 256 times the counter wraps and the behavior turns
+ * lazy again; this to deal with bursty apps that only use FPU for
+ * a short time
+ */
+ unsigned char fpu_counter;
+ s8 oomkilladj; /* OOM kill score adjustment (bit shift). */
#ifdef CONFIG_BLK_DEV_IO_TRACE
unsigned int btrace_seq;
#endif
@@ -1049,8 +1007,9 @@ struct task_struct {
int __user *clear_child_tid; /* CLONE_CHILD_CLEARTID */
unsigned int rt_priority;
- cputime_t utime, stime;
+ cputime_t utime, stime, utimescaled, stimescaled;
cputime_t gtime;
+ cputime_t prev_utime, prev_stime;
unsigned long nvcsw, nivcsw; /* context switch counts */
struct timespec start_time; /* monotonic time */
struct timespec real_start_time; /* boot based time */
@@ -1073,16 +1032,6 @@ struct task_struct {
struct key *thread_keyring; /* keyring private to this thread */
unsigned char jit_keyring; /* default keyring to attach requested keys to */
#endif
- /*
- * fpu_counter contains the number of consecutive context switches
- * that the FPU is used. If this is over a threshold, the lazy fpu
- * saving becomes unlazy to save the trap. This is an unsigned char
- * so that after 256 times the counter wraps and the behavior turns
- * lazy again; this to deal with bursty apps that only use FPU for
- * a short time
- */
- unsigned char fpu_counter;
- int oomkilladj; /* OOM kill score adjustment (bit shift). */
char comm[TASK_COMM_LEN]; /* executable name excluding path
- access with [gs]et_task_comm (which lock
it with task_lock())
@@ -1114,8 +1063,9 @@ struct task_struct {
int (*notifier)(void *priv);
void *notifier_data;
sigset_t *notifier_mask;
-
+#ifdef CONFIG_SECURITY
void *security;
+#endif
struct audit_context *audit_context;
seccomp_t seccomp;
@@ -1177,13 +1127,6 @@ struct task_struct {
unsigned long ptrace_message;
siginfo_t *last_siginfo; /* For ptrace use. */
-/*
- * current io wait handle: wait queue entry to use for io waits
- * If this thread is processing aio, this points at the waitqueue
- * inside the currently handled kiocb. It may be NULL (i.e. default
- * to a stack based synchronous wait) if its doing sync IO.
- */
- wait_queue_t *io_wait;
#ifdef CONFIG_TASK_XACCT
/* i/o counters(bytes read/written, #syscalls */
u64 rchar, wchar, syscr, syscw;
@@ -1199,18 +1142,24 @@ struct task_struct {
short il_next;
#endif
#ifdef CONFIG_CPUSETS
- struct cpuset *cpuset;
nodemask_t mems_allowed;
int cpuset_mems_generation;
int cpuset_mem_spread_rotor;
#endif
+#ifdef CONFIG_CGROUPS
+ /* Control Group info protected by css_set_lock */
+ struct css_set *cgroups;
+ /* cg_list protected by css_set_lock and tsk->alloc_lock */
+ struct list_head cg_list;
+#endif
+#ifdef CONFIG_FUTEX
struct robust_list_head __user *robust_list;
#ifdef CONFIG_COMPAT
struct compat_robust_list_head __user *compat_robust_list;
#endif
struct list_head pi_state_list;
struct futex_pi_state *pi_state_cache;
-
+#endif
atomic_t fs_excl; /* holding fs exclusive resources */
struct rcu_head rcu;
@@ -1224,6 +1173,7 @@ struct task_struct {
#ifdef CONFIG_FAULT_INJECTION
int make_it_fail;
#endif
+ struct prop_local_single dirties;
};
/*
@@ -1257,24 +1207,14 @@ static inline int rt_task(struct task_struct *p)
return rt_prio(p->prio);
}
-static inline pid_t process_group(struct task_struct *tsk)
-{
- return tsk->signal->pgrp;
-}
-
-static inline pid_t signal_session(struct signal_struct *sig)
+static inline void set_task_session(struct task_struct *tsk, pid_t session)
{
- return sig->__session;
+ tsk->signal->__session = session;
}
-static inline pid_t process_session(struct task_struct *tsk)
+static inline void set_task_pgrp(struct task_struct *tsk, pid_t pgrp)
{
- return signal_session(tsk->signal);
-}
-
-static inline void set_signal_session(struct signal_struct *sig, pid_t session)
-{
- sig->__session = session;
+ tsk->signal->__pgrp = pgrp;
}
static inline struct pid *task_pid(struct task_struct *task)
@@ -1297,6 +1237,88 @@ static inline struct pid *task_session(struct task_struct *task)
return task->group_leader->pids[PIDTYPE_SID].pid;
}
+struct pid_namespace;
+
+/*
+ * the helpers to get the task's different pids as they are seen
+ * from various namespaces
+ *
+ * task_xid_nr() : global id, i.e. the id seen from the init namespace;
+ * task_xid_vnr() : virtual id, i.e. the id seen from the namespace the task
+ * belongs to. this only makes sence when called in the
+ * context of the task that belongs to the same namespace;
+ * task_xid_nr_ns() : id seen from the ns specified;
+ *
+ * set_task_vxid() : assigns a virtual id to a task;
+ *
+ * task_ppid_nr_ns() : the parent's id as seen from the namespace specified.
+ * the result depends on the namespace and whether the
+ * task in question is the namespace's init. e.g. for the
+ * namespace's init this will return 0 when called from
+ * the namespace of this init, or appropriate id otherwise.
+ *
+ *
+ * see also pid_nr() etc in include/linux/pid.h
+ */
+
+static inline pid_t task_pid_nr(struct task_struct *tsk)
+{
+ return tsk->pid;
+}
+
+pid_t task_pid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns);
+
+static inline pid_t task_pid_vnr(struct task_struct *tsk)
+{
+ return pid_vnr(task_pid(tsk));
+}
+
+
+static inline pid_t task_tgid_nr(struct task_struct *tsk)
+{
+ return tsk->tgid;
+}
+
+pid_t task_tgid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns);
+
+static inline pid_t task_tgid_vnr(struct task_struct *tsk)
+{
+ return pid_vnr(task_tgid(tsk));
+}
+
+
+static inline pid_t task_pgrp_nr(struct task_struct *tsk)
+{
+ return tsk->signal->__pgrp;
+}
+
+pid_t task_pgrp_nr_ns(struct task_struct *tsk, struct pid_namespace *ns);
+
+static inline pid_t task_pgrp_vnr(struct task_struct *tsk)
+{
+ return pid_vnr(task_pgrp(tsk));
+}
+
+
+static inline pid_t task_session_nr(struct task_struct *tsk)
+{
+ return tsk->signal->__session;
+}
+
+pid_t task_session_nr_ns(struct task_struct *tsk, struct pid_namespace *ns);
+
+static inline pid_t task_session_vnr(struct task_struct *tsk)
+{
+ return pid_vnr(task_session(tsk));
+}
+
+
+static inline pid_t task_ppid_nr_ns(struct task_struct *tsk,
+ struct pid_namespace *ns)
+{
+ return pid_nr_ns(task_pid(rcu_dereference(tsk->real_parent)), ns);
+}
+
/**
* pid_alive - check that a task structure is not stale
* @p: Task structure to be checked.
@@ -1311,16 +1333,22 @@ static inline int pid_alive(struct task_struct *p)
}
/**
- * is_init - check if a task structure is init
+ * is_global_init - check if a task structure is init
* @tsk: Task structure to be checked.
*
* Check if a task structure is the first user space task the kernel created.
*/
-static inline int is_init(struct task_struct *tsk)
+static inline int is_global_init(struct task_struct *tsk)
{
return tsk->pid == 1;
}
+/*
+ * is_container_init:
+ * check whether in the task is init in its own pid namespace.
+ */
+extern int is_container_init(struct task_struct *tsk);
+
extern struct pid *cad_pid;
extern void free_task(struct task_struct *tsk);
@@ -1432,12 +1460,17 @@ extern void sched_idle_next(void);
#ifdef CONFIG_SCHED_DEBUG
extern unsigned int sysctl_sched_latency;
-extern unsigned int sysctl_sched_nr_latency;
+extern unsigned int sysctl_sched_min_granularity;
extern unsigned int sysctl_sched_wakeup_granularity;
extern unsigned int sysctl_sched_batch_wakeup_granularity;
extern unsigned int sysctl_sched_child_runs_first;
extern unsigned int sysctl_sched_features;
extern unsigned int sysctl_sched_migration_cost;
+extern unsigned int sysctl_sched_nr_migrate;
+
+int sched_nr_latency_handler(struct ctl_table *table, int write,
+ struct file *file, void __user *buffer, size_t *length,
+ loff_t *ppos);
#endif
extern unsigned int sysctl_sched_compat_yield;
@@ -1492,8 +1525,32 @@ extern struct task_struct init_task;
extern struct mm_struct init_mm;
-#define find_task_by_pid(nr) find_task_by_pid_type(PIDTYPE_PID, nr)
-extern struct task_struct *find_task_by_pid_type(int type, int pid);
+extern struct pid_namespace init_pid_ns;
+
+/*
+ * find a task by one of its numerical ids
+ *
+ * find_task_by_pid_type_ns():
+ * it is the most generic call - it finds a task by all id,
+ * type and namespace specified
+ * find_task_by_pid_ns():
+ * finds a task by its pid in the specified namespace
+ * find_task_by_vpid():
+ * finds a task by its virtual pid
+ * find_task_by_pid():
+ * finds a task by its global pid
+ *
+ * see also find_pid() etc in include/linux/pid.h
+ */
+
+extern struct task_struct *find_task_by_pid_type_ns(int type, int pid,
+ struct pid_namespace *ns);
+
+extern struct task_struct *find_task_by_pid(pid_t nr);
+extern struct task_struct *find_task_by_vpid(pid_t nr);
+extern struct task_struct *find_task_by_pid_ns(pid_t nr,
+ struct pid_namespace *ns);
+
extern void __set_special_pids(pid_t session, pid_t pgrp);
/* per-UID process charging. */
@@ -1680,6 +1737,12 @@ static inline int has_group_leader_pid(struct task_struct *p)
return p->pid == p->tgid;
}
+static inline
+int same_thread_group(struct task_struct *p1, struct task_struct *p2)
+{
+ return p1->tgid == p2->tgid;
+}
+
static inline struct task_struct *next_thread(const struct task_struct *p)
{
return list_entry(rcu_dereference(p->thread_group.next),
@@ -1697,7 +1760,8 @@ static inline int thread_group_empty(struct task_struct *p)
/*
* Protects ->fs, ->files, ->mm, ->group_info, ->comm, keyring
* subscriptions and synchronises with wait4(). Also used in procfs. Also
- * pins the final release of task.io_context. Also protects ->cpuset.
+ * pins the final release of task.io_context. Also protects ->cpuset and
+ * ->cgroup.subsys[].
*
* Nests both inside and outside of read_lock(&tasklist_lock).
* It must not be nested with write_lock_irq(&tasklist_lock),
@@ -1924,6 +1988,14 @@ static inline void inc_syscw(struct task_struct *tsk)
}
#endif
+#ifdef CONFIG_SMP
+void migration_init(void);
+#else
+static inline void migration_init(void)
+{
+}
+#endif
+
#endif /* __KERNEL__ */
#endif
diff --git a/include/linux/screen_info.h b/include/linux/screen_info.h
index 3ee412bc00ec..827b85bbf388 100644
--- a/include/linux/screen_info.h
+++ b/include/linux/screen_info.h
@@ -8,54 +8,43 @@
*/
struct screen_info {
- u8 orig_x; /* 0x00 */
- u8 orig_y; /* 0x01 */
- u16 ext_mem_k; /* 0x02 */
- u16 orig_video_page; /* 0x04 */
- u8 orig_video_mode; /* 0x06 */
- u8 orig_video_cols; /* 0x07 */
- u16 unused2; /* 0x08 */
- u16 orig_video_ega_bx; /* 0x0a */
- u16 unused3; /* 0x0c */
- u8 orig_video_lines; /* 0x0e */
- u8 orig_video_isVGA; /* 0x0f */
- u16 orig_video_points; /* 0x10 */
+ __u8 orig_x; /* 0x00 */
+ __u8 orig_y; /* 0x01 */
+ __u16 ext_mem_k; /* 0x02 */
+ __u16 orig_video_page; /* 0x04 */
+ __u8 orig_video_mode; /* 0x06 */
+ __u8 orig_video_cols; /* 0x07 */
+ __u16 unused2; /* 0x08 */
+ __u16 orig_video_ega_bx;/* 0x0a */
+ __u16 unused3; /* 0x0c */
+ __u8 orig_video_lines; /* 0x0e */
+ __u8 orig_video_isVGA; /* 0x0f */
+ __u16 orig_video_points;/* 0x10 */
/* VESA graphic mode -- linear frame buffer */
- u16 lfb_width; /* 0x12 */
- u16 lfb_height; /* 0x14 */
- u16 lfb_depth; /* 0x16 */
- u32 lfb_base; /* 0x18 */
- u32 lfb_size; /* 0x1c */
- u16 cl_magic, cl_offset; /* 0x20 */
- u16 lfb_linelength; /* 0x24 */
- u8 red_size; /* 0x26 */
- u8 red_pos; /* 0x27 */
- u8 green_size; /* 0x28 */
- u8 green_pos; /* 0x29 */
- u8 blue_size; /* 0x2a */
- u8 blue_pos; /* 0x2b */
- u8 rsvd_size; /* 0x2c */
- u8 rsvd_pos; /* 0x2d */
- u16 vesapm_seg; /* 0x2e */
- u16 vesapm_off; /* 0x30 */
- u16 pages; /* 0x32 */
- u16 vesa_attributes; /* 0x34 */
- u32 capabilities; /* 0x36 */
- u8 _reserved[6]; /* 0x3a */
+ __u16 lfb_width; /* 0x12 */
+ __u16 lfb_height; /* 0x14 */
+ __u16 lfb_depth; /* 0x16 */
+ __u32 lfb_base; /* 0x18 */
+ __u32 lfb_size; /* 0x1c */
+ __u16 cl_magic, cl_offset; /* 0x20 */
+ __u16 lfb_linelength; /* 0x24 */
+ __u8 red_size; /* 0x26 */
+ __u8 red_pos; /* 0x27 */
+ __u8 green_size; /* 0x28 */
+ __u8 green_pos; /* 0x29 */
+ __u8 blue_size; /* 0x2a */
+ __u8 blue_pos; /* 0x2b */
+ __u8 rsvd_size; /* 0x2c */
+ __u8 rsvd_pos; /* 0x2d */
+ __u16 vesapm_seg; /* 0x2e */
+ __u16 vesapm_off; /* 0x30 */
+ __u16 pages; /* 0x32 */
+ __u16 vesa_attributes; /* 0x34 */
+ __u32 capabilities; /* 0x36 */
+ __u8 _reserved[6]; /* 0x3a */
} __attribute__((packed));
-extern struct screen_info screen_info;
-
-#define ORIG_X (screen_info.orig_x)
-#define ORIG_Y (screen_info.orig_y)
-#define ORIG_VIDEO_MODE (screen_info.orig_video_mode)
-#define ORIG_VIDEO_COLS (screen_info.orig_video_cols)
-#define ORIG_VIDEO_EGA_BX (screen_info.orig_video_ega_bx)
-#define ORIG_VIDEO_LINES (screen_info.orig_video_lines)
-#define ORIG_VIDEO_ISVGA (screen_info.orig_video_isVGA)
-#define ORIG_VIDEO_POINTS (screen_info.orig_video_points)
-
#define VIDEO_TYPE_MDA 0x10 /* Monochrome Text Display */
#define VIDEO_TYPE_CGA 0x11 /* CGA Display */
#define VIDEO_TYPE_EGAM 0x20 /* EGA/VGA in Monochrome Mode */
@@ -74,4 +63,17 @@ extern struct screen_info screen_info;
#define VIDEO_TYPE_PMAC 0x60 /* PowerMacintosh frame buffer. */
+#ifdef __KERNEL__
+extern struct screen_info screen_info;
+
+#define ORIG_X (screen_info.orig_x)
+#define ORIG_Y (screen_info.orig_y)
+#define ORIG_VIDEO_MODE (screen_info.orig_video_mode)
+#define ORIG_VIDEO_COLS (screen_info.orig_video_cols)
+#define ORIG_VIDEO_EGA_BX (screen_info.orig_video_ega_bx)
+#define ORIG_VIDEO_LINES (screen_info.orig_video_lines)
+#define ORIG_VIDEO_ISVGA (screen_info.orig_video_isVGA)
+#define ORIG_VIDEO_POINTS (screen_info.orig_video_points)
+#endif /* __KERNEL__ */
+
#endif /* _SCREEN_INFO_H */
diff --git a/include/linux/security.h b/include/linux/security.h
index 1a15526e9f67..ac050830a873 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -34,6 +34,13 @@
#include <linux/xfrm.h>
#include <net/flow.h>
+/*
+ * Bounding set
+ */
+extern kernel_cap_t cap_bset;
+
+extern unsigned securebits;
+
struct ctl_table;
/*
@@ -51,10 +58,16 @@ extern void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe);
extern int cap_bprm_secureexec(struct linux_binprm *bprm);
extern int cap_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags);
extern int cap_inode_removexattr(struct dentry *dentry, char *name);
+extern int cap_inode_need_killpriv(struct dentry *dentry);
+extern int cap_inode_killpriv(struct dentry *dentry);
extern int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
extern void cap_task_reparent_to_init (struct task_struct *p);
+extern int cap_task_kill(struct task_struct *p, struct siginfo *info, int sig, u32 secid);
+extern int cap_task_setscheduler (struct task_struct *p, int policy, struct sched_param *lp);
+extern int cap_task_setioprio (struct task_struct *p, int ioprio);
+extern int cap_task_setnice (struct task_struct *p, int nice);
extern int cap_syslog (int type);
-extern int cap_vm_enough_memory (struct mm_struct *mm, long pages);
+extern int cap_vm_enough_memory(struct mm_struct *mm, long pages);
struct msghdr;
struct sk_buff;
@@ -413,6 +426,18 @@ struct request_sock;
* is specified by @buffer_size. @buffer may be NULL to request
* the size of the buffer required.
* Returns number of bytes used/required on success.
+ * @inode_need_killpriv:
+ * Called when an inode has been changed.
+ * @dentry is the dentry being changed.
+ * Return <0 on error to abort the inode change operation.
+ * Return 0 if inode_killpriv does not need to be called.
+ * Return >0 if inode_killpriv does need to be called.
+ * @inode_killpriv:
+ * The setuid bit is being removed. Remove similar security labels.
+ * Called with the dentry->d_inode->i_mutex held.
+ * @dentry is the dentry being changed.
+ * Return 0 on success. If error is returned, then the operation
+ * causing setuid bit removal is failed.
*
* Security hooks for file operations
*
@@ -504,6 +529,13 @@ struct request_sock;
* @file contains the file structure being received.
* Return 0 if permission is granted.
*
+ * Security hook for dentry
+ *
+ * @dentry_open
+ * Save open-time permission checking state for later use upon
+ * file_permission, and recheck access if anything has changed
+ * since inode_permission.
+ *
* Security hooks for task operations.
*
* @task_create:
@@ -800,9 +832,11 @@ struct request_sock;
* incoming sk_buff @skb has been associated with a particular socket, @sk.
* @sk contains the sock (not socket) associated with the incoming sk_buff.
* @skb contains the incoming network data.
- * @socket_getpeersec:
+ * @socket_getpeersec_stream:
* This hook allows the security module to provide peer socket security
- * state to userspace via getsockopt SO_GETPEERSEC.
+ * state for unix or connected tcp sockets to userspace via getsockopt
+ * SO_GETPEERSEC. For tcp sockets this can be meaningful if the
+ * socket is associated with an ipsec SA.
* @sock is the local socket.
* @optval userspace memory where the security state is to be copied.
* @optlen userspace int where the module should copy the actual length
@@ -811,6 +845,17 @@ struct request_sock;
* by the caller.
* Return 0 if all is well, otherwise, typical getsockopt return
* values.
+ * @socket_getpeersec_dgram:
+ * This hook allows the security module to provide peer socket security
+ * state for udp sockets on a per-packet basis to userspace via
+ * getsockopt SO_GETPEERSEC. The application must first have indicated
+ * the IP_PASSSEC option via getsockopt. It can then retrieve the
+ * security state returned by this hook for a packet via the SCM_SECURITY
+ * ancillary message type.
+ * @skb is the skbuff for the packet being queried
+ * @secdata is a pointer to a buffer in which to copy the security data
+ * @seclen is the maximum length for @secdata
+ * Return 0 on success, error on failure.
* @sk_alloc_security:
* Allocate and attach a security structure to the sk->sk_security field,
* which is used to copy security attributes between local stream sockets.
@@ -1133,10 +1178,6 @@ struct request_sock;
* allow module stacking.
* @name contains the name of the security module being stacked.
* @ops contains a pointer to the struct security_operations of the module to stack.
- * @unregister_security:
- * remove a stacked module.
- * @name contains the name of the security module being unstacked.
- * @ops contains a pointer to the struct security_operations of the module to unstack.
*
* @secid_to_secctx:
* Convert secid to security context.
@@ -1232,7 +1273,8 @@ struct security_operations {
int (*inode_getxattr) (struct dentry *dentry, char *name);
int (*inode_listxattr) (struct dentry *dentry);
int (*inode_removexattr) (struct dentry *dentry, char *name);
- const char *(*inode_xattr_getsuffix) (void);
+ int (*inode_need_killpriv) (struct dentry *dentry);
+ int (*inode_killpriv) (struct dentry *dentry);
int (*inode_getsecurity)(const struct inode *inode, const char *name, void *buffer, size_t size, int err);
int (*inode_setsecurity)(struct inode *inode, const char *name, const void *value, size_t size, int flags);
int (*inode_listsecurity)(struct inode *inode, char *buffer, size_t buffer_size);
@@ -1256,6 +1298,7 @@ struct security_operations {
int (*file_send_sigiotask) (struct task_struct * tsk,
struct fown_struct * fown, int sig);
int (*file_receive) (struct file * file);
+ int (*dentry_open) (struct file *file);
int (*task_create) (unsigned long clone_flags);
int (*task_alloc_security) (struct task_struct * p);
@@ -1322,8 +1365,6 @@ struct security_operations {
/* allow module stacking */
int (*register_security) (const char *name,
struct security_operations *ops);
- int (*unregister_security) (const char *name,
- struct security_operations *ops);
void (*d_instantiate) (struct dentry *dentry, struct inode *inode);
@@ -1401,743 +1442,10 @@ struct security_operations {
};
-/* global variables */
-extern struct security_operations *security_ops;
-
-/* inline stuff */
-static inline int security_ptrace (struct task_struct * parent, struct task_struct * child)
-{
- return security_ops->ptrace (parent, child);
-}
-
-static inline int security_capget (struct task_struct *target,
- kernel_cap_t *effective,
- kernel_cap_t *inheritable,
- kernel_cap_t *permitted)
-{
- return security_ops->capget (target, effective, inheritable, permitted);
-}
-
-static inline int security_capset_check (struct task_struct *target,
- kernel_cap_t *effective,
- kernel_cap_t *inheritable,
- kernel_cap_t *permitted)
-{
- return security_ops->capset_check (target, effective, inheritable, permitted);
-}
-
-static inline void security_capset_set (struct task_struct *target,
- kernel_cap_t *effective,
- kernel_cap_t *inheritable,
- kernel_cap_t *permitted)
-{
- security_ops->capset_set (target, effective, inheritable, permitted);
-}
-
-static inline int security_capable(struct task_struct *tsk, int cap)
-{
- return security_ops->capable(tsk, cap);
-}
-
-static inline int security_acct (struct file *file)
-{
- return security_ops->acct (file);
-}
-
-static inline int security_sysctl(struct ctl_table *table, int op)
-{
- return security_ops->sysctl(table, op);
-}
-
-static inline int security_quotactl (int cmds, int type, int id,
- struct super_block *sb)
-{
- return security_ops->quotactl (cmds, type, id, sb);
-}
-
-static inline int security_quota_on (struct dentry * dentry)
-{
- return security_ops->quota_on (dentry);
-}
-
-static inline int security_syslog(int type)
-{
- return security_ops->syslog(type);
-}
-
-static inline int security_settime(struct timespec *ts, struct timezone *tz)
-{
- return security_ops->settime(ts, tz);
-}
-
-static inline int security_vm_enough_memory(long pages)
-{
- return security_ops->vm_enough_memory(current->mm, pages);
-}
-
-static inline int security_vm_enough_memory_mm(struct mm_struct *mm, long pages)
-{
- return security_ops->vm_enough_memory(mm, pages);
-}
-
-static inline int security_bprm_alloc (struct linux_binprm *bprm)
-{
- return security_ops->bprm_alloc_security (bprm);
-}
-static inline void security_bprm_free (struct linux_binprm *bprm)
-{
- security_ops->bprm_free_security (bprm);
-}
-static inline void security_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
-{
- security_ops->bprm_apply_creds (bprm, unsafe);
-}
-static inline void security_bprm_post_apply_creds (struct linux_binprm *bprm)
-{
- security_ops->bprm_post_apply_creds (bprm);
-}
-static inline int security_bprm_set (struct linux_binprm *bprm)
-{
- return security_ops->bprm_set_security (bprm);
-}
-
-static inline int security_bprm_check (struct linux_binprm *bprm)
-{
- return security_ops->bprm_check_security (bprm);
-}
-
-static inline int security_bprm_secureexec (struct linux_binprm *bprm)
-{
- return security_ops->bprm_secureexec (bprm);
-}
-
-static inline int security_sb_alloc (struct super_block *sb)
-{
- return security_ops->sb_alloc_security (sb);
-}
-
-static inline void security_sb_free (struct super_block *sb)
-{
- security_ops->sb_free_security (sb);
-}
-
-static inline int security_sb_copy_data (struct file_system_type *type,
- void *orig, void *copy)
-{
- return security_ops->sb_copy_data (type, orig, copy);
-}
-
-static inline int security_sb_kern_mount (struct super_block *sb, void *data)
-{
- return security_ops->sb_kern_mount (sb, data);
-}
-
-static inline int security_sb_statfs (struct dentry *dentry)
-{
- return security_ops->sb_statfs (dentry);
-}
-
-static inline int security_sb_mount (char *dev_name, struct nameidata *nd,
- char *type, unsigned long flags,
- void *data)
-{
- return security_ops->sb_mount (dev_name, nd, type, flags, data);
-}
-
-static inline int security_sb_check_sb (struct vfsmount *mnt,
- struct nameidata *nd)
-{
- return security_ops->sb_check_sb (mnt, nd);
-}
-
-static inline int security_sb_umount (struct vfsmount *mnt, int flags)
-{
- return security_ops->sb_umount (mnt, flags);
-}
-
-static inline void security_sb_umount_close (struct vfsmount *mnt)
-{
- security_ops->sb_umount_close (mnt);
-}
-
-static inline void security_sb_umount_busy (struct vfsmount *mnt)
-{
- security_ops->sb_umount_busy (mnt);
-}
-
-static inline void security_sb_post_remount (struct vfsmount *mnt,
- unsigned long flags, void *data)
-{
- security_ops->sb_post_remount (mnt, flags, data);
-}
-
-static inline void security_sb_post_mountroot (void)
-{
- security_ops->sb_post_mountroot ();
-}
-
-static inline void security_sb_post_addmount (struct vfsmount *mnt,
- struct nameidata *mountpoint_nd)
-{
- security_ops->sb_post_addmount (mnt, mountpoint_nd);
-}
-
-static inline int security_sb_pivotroot (struct nameidata *old_nd,
- struct nameidata *new_nd)
-{
- return security_ops->sb_pivotroot (old_nd, new_nd);
-}
-
-static inline void security_sb_post_pivotroot (struct nameidata *old_nd,
- struct nameidata *new_nd)
-{
- security_ops->sb_post_pivotroot (old_nd, new_nd);
-}
-
-static inline int security_inode_alloc (struct inode *inode)
-{
- inode->i_security = NULL;
- return security_ops->inode_alloc_security (inode);
-}
-
-static inline void security_inode_free (struct inode *inode)
-{
- security_ops->inode_free_security (inode);
-}
-
-static inline int security_inode_init_security (struct inode *inode,
- struct inode *dir,
- char **name,
- void **value,
- size_t *len)
-{
- if (unlikely (IS_PRIVATE (inode)))
- return -EOPNOTSUPP;
- return security_ops->inode_init_security (inode, dir, name, value, len);
-}
-
-static inline int security_inode_create (struct inode *dir,
- struct dentry *dentry,
- int mode)
-{
- if (unlikely (IS_PRIVATE (dir)))
- return 0;
- return security_ops->inode_create (dir, dentry, mode);
-}
-
-static inline int security_inode_link (struct dentry *old_dentry,
- struct inode *dir,
- struct dentry *new_dentry)
-{
- if (unlikely (IS_PRIVATE (old_dentry->d_inode)))
- return 0;
- return security_ops->inode_link (old_dentry, dir, new_dentry);
-}
-
-static inline int security_inode_unlink (struct inode *dir,
- struct dentry *dentry)
-{
- if (unlikely (IS_PRIVATE (dentry->d_inode)))
- return 0;
- return security_ops->inode_unlink (dir, dentry);
-}
-
-static inline int security_inode_symlink (struct inode *dir,
- struct dentry *dentry,
- const char *old_name)
-{
- if (unlikely (IS_PRIVATE (dir)))
- return 0;
- return security_ops->inode_symlink (dir, dentry, old_name);
-}
-
-static inline int security_inode_mkdir (struct inode *dir,
- struct dentry *dentry,
- int mode)
-{
- if (unlikely (IS_PRIVATE (dir)))
- return 0;
- return security_ops->inode_mkdir (dir, dentry, mode);
-}
-
-static inline int security_inode_rmdir (struct inode *dir,
- struct dentry *dentry)
-{
- if (unlikely (IS_PRIVATE (dentry->d_inode)))
- return 0;
- return security_ops->inode_rmdir (dir, dentry);
-}
-
-static inline int security_inode_mknod (struct inode *dir,
- struct dentry *dentry,
- int mode, dev_t dev)
-{
- if (unlikely (IS_PRIVATE (dir)))
- return 0;
- return security_ops->inode_mknod (dir, dentry, mode, dev);
-}
-
-static inline int security_inode_rename (struct inode *old_dir,
- struct dentry *old_dentry,
- struct inode *new_dir,
- struct dentry *new_dentry)
-{
- if (unlikely (IS_PRIVATE (old_dentry->d_inode) ||
- (new_dentry->d_inode && IS_PRIVATE (new_dentry->d_inode))))
- return 0;
- return security_ops->inode_rename (old_dir, old_dentry,
- new_dir, new_dentry);
-}
-
-static inline int security_inode_readlink (struct dentry *dentry)
-{
- if (unlikely (IS_PRIVATE (dentry->d_inode)))
- return 0;
- return security_ops->inode_readlink (dentry);
-}
-
-static inline int security_inode_follow_link (struct dentry *dentry,
- struct nameidata *nd)
-{
- if (unlikely (IS_PRIVATE (dentry->d_inode)))
- return 0;
- return security_ops->inode_follow_link (dentry, nd);
-}
-
-static inline int security_inode_permission (struct inode *inode, int mask,
- struct nameidata *nd)
-{
- if (unlikely (IS_PRIVATE (inode)))
- return 0;
- return security_ops->inode_permission (inode, mask, nd);
-}
-
-static inline int security_inode_setattr (struct dentry *dentry,
- struct iattr *attr)
-{
- if (unlikely (IS_PRIVATE (dentry->d_inode)))
- return 0;
- return security_ops->inode_setattr (dentry, attr);
-}
-
-static inline int security_inode_getattr (struct vfsmount *mnt,
- struct dentry *dentry)
-{
- if (unlikely (IS_PRIVATE (dentry->d_inode)))
- return 0;
- return security_ops->inode_getattr (mnt, dentry);
-}
-
-static inline void security_inode_delete (struct inode *inode)
-{
- if (unlikely (IS_PRIVATE (inode)))
- return;
- security_ops->inode_delete (inode);
-}
-
-static inline int security_inode_setxattr (struct dentry *dentry, char *name,
- void *value, size_t size, int flags)
-{
- if (unlikely (IS_PRIVATE (dentry->d_inode)))
- return 0;
- return security_ops->inode_setxattr (dentry, name, value, size, flags);
-}
-
-static inline void security_inode_post_setxattr (struct dentry *dentry, char *name,
- void *value, size_t size, int flags)
-{
- if (unlikely (IS_PRIVATE (dentry->d_inode)))
- return;
- security_ops->inode_post_setxattr (dentry, name, value, size, flags);
-}
-
-static inline int security_inode_getxattr (struct dentry *dentry, char *name)
-{
- if (unlikely (IS_PRIVATE (dentry->d_inode)))
- return 0;
- return security_ops->inode_getxattr (dentry, name);
-}
-
-static inline int security_inode_listxattr (struct dentry *dentry)
-{
- if (unlikely (IS_PRIVATE (dentry->d_inode)))
- return 0;
- return security_ops->inode_listxattr (dentry);
-}
-
-static inline int security_inode_removexattr (struct dentry *dentry, char *name)
-{
- if (unlikely (IS_PRIVATE (dentry->d_inode)))
- return 0;
- return security_ops->inode_removexattr (dentry, name);
-}
-
-static inline const char *security_inode_xattr_getsuffix(void)
-{
- return security_ops->inode_xattr_getsuffix();
-}
-
-static inline int security_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
-{
- if (unlikely (IS_PRIVATE (inode)))
- return 0;
- return security_ops->inode_getsecurity(inode, name, buffer, size, err);
-}
-
-static inline int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags)
-{
- if (unlikely (IS_PRIVATE (inode)))
- return 0;
- return security_ops->inode_setsecurity(inode, name, value, size, flags);
-}
-
-static inline int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
-{
- if (unlikely (IS_PRIVATE (inode)))
- return 0;
- return security_ops->inode_listsecurity(inode, buffer, buffer_size);
-}
-
-static inline int security_file_permission (struct file *file, int mask)
-{
- return security_ops->file_permission (file, mask);
-}
-
-static inline int security_file_alloc (struct file *file)
-{
- return security_ops->file_alloc_security (file);
-}
-
-static inline void security_file_free (struct file *file)
-{
- security_ops->file_free_security (file);
-}
-
-static inline int security_file_ioctl (struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- return security_ops->file_ioctl (file, cmd, arg);
-}
-
-static inline int security_file_mmap (struct file *file, unsigned long reqprot,
- unsigned long prot,
- unsigned long flags,
- unsigned long addr,
- unsigned long addr_only)
-{
- return security_ops->file_mmap (file, reqprot, prot, flags, addr,
- addr_only);
-}
-
-static inline int security_file_mprotect (struct vm_area_struct *vma,
- unsigned long reqprot,
- unsigned long prot)
-{
- return security_ops->file_mprotect (vma, reqprot, prot);
-}
-
-static inline int security_file_lock (struct file *file, unsigned int cmd)
-{
- return security_ops->file_lock (file, cmd);
-}
-
-static inline int security_file_fcntl (struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- return security_ops->file_fcntl (file, cmd, arg);
-}
-
-static inline int security_file_set_fowner (struct file *file)
-{
- return security_ops->file_set_fowner (file);
-}
-
-static inline int security_file_send_sigiotask (struct task_struct *tsk,
- struct fown_struct *fown,
- int sig)
-{
- return security_ops->file_send_sigiotask (tsk, fown, sig);
-}
-
-static inline int security_file_receive (struct file *file)
-{
- return security_ops->file_receive (file);
-}
-
-static inline int security_task_create (unsigned long clone_flags)
-{
- return security_ops->task_create (clone_flags);
-}
-
-static inline int security_task_alloc (struct task_struct *p)
-{
- return security_ops->task_alloc_security (p);
-}
-
-static inline void security_task_free (struct task_struct *p)
-{
- security_ops->task_free_security (p);
-}
-
-static inline int security_task_setuid (uid_t id0, uid_t id1, uid_t id2,
- int flags)
-{
- return security_ops->task_setuid (id0, id1, id2, flags);
-}
-
-static inline int security_task_post_setuid (uid_t old_ruid, uid_t old_euid,
- uid_t old_suid, int flags)
-{
- return security_ops->task_post_setuid (old_ruid, old_euid, old_suid, flags);
-}
-
-static inline int security_task_setgid (gid_t id0, gid_t id1, gid_t id2,
- int flags)
-{
- return security_ops->task_setgid (id0, id1, id2, flags);
-}
-
-static inline int security_task_setpgid (struct task_struct *p, pid_t pgid)
-{
- return security_ops->task_setpgid (p, pgid);
-}
-
-static inline int security_task_getpgid (struct task_struct *p)
-{
- return security_ops->task_getpgid (p);
-}
-
-static inline int security_task_getsid (struct task_struct *p)
-{
- return security_ops->task_getsid (p);
-}
-
-static inline void security_task_getsecid (struct task_struct *p, u32 *secid)
-{
- security_ops->task_getsecid (p, secid);
-}
-
-static inline int security_task_setgroups (struct group_info *group_info)
-{
- return security_ops->task_setgroups (group_info);
-}
-
-static inline int security_task_setnice (struct task_struct *p, int nice)
-{
- return security_ops->task_setnice (p, nice);
-}
-
-static inline int security_task_setioprio (struct task_struct *p, int ioprio)
-{
- return security_ops->task_setioprio (p, ioprio);
-}
-
-static inline int security_task_getioprio (struct task_struct *p)
-{
- return security_ops->task_getioprio (p);
-}
-
-static inline int security_task_setrlimit (unsigned int resource,
- struct rlimit *new_rlim)
-{
- return security_ops->task_setrlimit (resource, new_rlim);
-}
-
-static inline int security_task_setscheduler (struct task_struct *p,
- int policy,
- struct sched_param *lp)
-{
- return security_ops->task_setscheduler (p, policy, lp);
-}
-
-static inline int security_task_getscheduler (struct task_struct *p)
-{
- return security_ops->task_getscheduler (p);
-}
-
-static inline int security_task_movememory (struct task_struct *p)
-{
- return security_ops->task_movememory (p);
-}
-
-static inline int security_task_kill (struct task_struct *p,
- struct siginfo *info, int sig,
- u32 secid)
-{
- return security_ops->task_kill (p, info, sig, secid);
-}
-
-static inline int security_task_wait (struct task_struct *p)
-{
- return security_ops->task_wait (p);
-}
-
-static inline int security_task_prctl (int option, unsigned long arg2,
- unsigned long arg3,
- unsigned long arg4,
- unsigned long arg5)
-{
- return security_ops->task_prctl (option, arg2, arg3, arg4, arg5);
-}
-
-static inline void security_task_reparent_to_init (struct task_struct *p)
-{
- security_ops->task_reparent_to_init (p);
-}
-
-static inline void security_task_to_inode(struct task_struct *p, struct inode *inode)
-{
- security_ops->task_to_inode(p, inode);
-}
-
-static inline int security_ipc_permission (struct kern_ipc_perm *ipcp,
- short flag)
-{
- return security_ops->ipc_permission (ipcp, flag);
-}
-
-static inline int security_msg_msg_alloc (struct msg_msg * msg)
-{
- return security_ops->msg_msg_alloc_security (msg);
-}
-
-static inline void security_msg_msg_free (struct msg_msg * msg)
-{
- security_ops->msg_msg_free_security(msg);
-}
-
-static inline int security_msg_queue_alloc (struct msg_queue *msq)
-{
- return security_ops->msg_queue_alloc_security (msq);
-}
-
-static inline void security_msg_queue_free (struct msg_queue *msq)
-{
- security_ops->msg_queue_free_security (msq);
-}
-
-static inline int security_msg_queue_associate (struct msg_queue * msq,
- int msqflg)
-{
- return security_ops->msg_queue_associate (msq, msqflg);
-}
-
-static inline int security_msg_queue_msgctl (struct msg_queue * msq, int cmd)
-{
- return security_ops->msg_queue_msgctl (msq, cmd);
-}
-
-static inline int security_msg_queue_msgsnd (struct msg_queue * msq,
- struct msg_msg * msg, int msqflg)
-{
- return security_ops->msg_queue_msgsnd (msq, msg, msqflg);
-}
-
-static inline int security_msg_queue_msgrcv (struct msg_queue * msq,
- struct msg_msg * msg,
- struct task_struct * target,
- long type, int mode)
-{
- return security_ops->msg_queue_msgrcv (msq, msg, target, type, mode);
-}
-
-static inline int security_shm_alloc (struct shmid_kernel *shp)
-{
- return security_ops->shm_alloc_security (shp);
-}
-
-static inline void security_shm_free (struct shmid_kernel *shp)
-{
- security_ops->shm_free_security (shp);
-}
-
-static inline int security_shm_associate (struct shmid_kernel * shp,
- int shmflg)
-{
- return security_ops->shm_associate(shp, shmflg);
-}
-
-static inline int security_shm_shmctl (struct shmid_kernel * shp, int cmd)
-{
- return security_ops->shm_shmctl (shp, cmd);
-}
-
-static inline int security_shm_shmat (struct shmid_kernel * shp,
- char __user *shmaddr, int shmflg)
-{
- return security_ops->shm_shmat(shp, shmaddr, shmflg);
-}
-
-static inline int security_sem_alloc (struct sem_array *sma)
-{
- return security_ops->sem_alloc_security (sma);
-}
-
-static inline void security_sem_free (struct sem_array *sma)
-{
- security_ops->sem_free_security (sma);
-}
-
-static inline int security_sem_associate (struct sem_array * sma, int semflg)
-{
- return security_ops->sem_associate (sma, semflg);
-}
-
-static inline int security_sem_semctl (struct sem_array * sma, int cmd)
-{
- return security_ops->sem_semctl(sma, cmd);
-}
-
-static inline int security_sem_semop (struct sem_array * sma,
- struct sembuf * sops, unsigned nsops,
- int alter)
-{
- return security_ops->sem_semop(sma, sops, nsops, alter);
-}
-
-static inline void security_d_instantiate (struct dentry *dentry, struct inode *inode)
-{
- if (unlikely (inode && IS_PRIVATE (inode)))
- return;
- security_ops->d_instantiate (dentry, inode);
-}
-
-static inline int security_getprocattr(struct task_struct *p, char *name, char **value)
-{
- return security_ops->getprocattr(p, name, value);
-}
-
-static inline int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size)
-{
- return security_ops->setprocattr(p, name, value, size);
-}
-
-static inline int security_netlink_send(struct sock *sk, struct sk_buff * skb)
-{
- return security_ops->netlink_send(sk, skb);
-}
-
-static inline int security_netlink_recv(struct sk_buff * skb, int cap)
-{
- return security_ops->netlink_recv(skb, cap);
-}
-
-static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
-{
- return security_ops->secid_to_secctx(secid, secdata, seclen);
-}
-
-static inline void security_release_secctx(char *secdata, u32 seclen)
-{
- return security_ops->release_secctx(secdata, seclen);
-}
-
/* prototypes */
extern int security_init (void);
extern int register_security (struct security_operations *ops);
-extern int unregister_security (struct security_operations *ops);
extern int mod_reg_security (const char *name, struct security_operations *ops);
-extern int mod_unreg_security (const char *name, struct security_operations *ops);
extern struct dentry *securityfs_create_file(const char *name, mode_t mode,
struct dentry *parent, void *data,
const struct file_operations *fops);
@@ -2145,6 +1453,158 @@ extern struct dentry *securityfs_create_dir(const char *name, struct dentry *par
extern void securityfs_remove(struct dentry *dentry);
+/* Security operations */
+int security_ptrace(struct task_struct *parent, struct task_struct *child);
+int security_capget(struct task_struct *target,
+ kernel_cap_t *effective,
+ kernel_cap_t *inheritable,
+ kernel_cap_t *permitted);
+int security_capset_check(struct task_struct *target,
+ kernel_cap_t *effective,
+ kernel_cap_t *inheritable,
+ kernel_cap_t *permitted);
+void security_capset_set(struct task_struct *target,
+ kernel_cap_t *effective,
+ kernel_cap_t *inheritable,
+ kernel_cap_t *permitted);
+int security_capable(struct task_struct *tsk, int cap);
+int security_acct(struct file *file);
+int security_sysctl(struct ctl_table *table, int op);
+int security_quotactl(int cmds, int type, int id, struct super_block *sb);
+int security_quota_on(struct dentry *dentry);
+int security_syslog(int type);
+int security_settime(struct timespec *ts, struct timezone *tz);
+int security_vm_enough_memory(long pages);
+int security_vm_enough_memory_mm(struct mm_struct *mm, long pages);
+int security_bprm_alloc(struct linux_binprm *bprm);
+void security_bprm_free(struct linux_binprm *bprm);
+void security_bprm_apply_creds(struct linux_binprm *bprm, int unsafe);
+void security_bprm_post_apply_creds(struct linux_binprm *bprm);
+int security_bprm_set(struct linux_binprm *bprm);
+int security_bprm_check(struct linux_binprm *bprm);
+int security_bprm_secureexec(struct linux_binprm *bprm);
+int security_sb_alloc(struct super_block *sb);
+void security_sb_free(struct super_block *sb);
+int security_sb_copy_data(struct file_system_type *type, void *orig, void *copy);
+int security_sb_kern_mount(struct super_block *sb, void *data);
+int security_sb_statfs(struct dentry *dentry);
+int security_sb_mount(char *dev_name, struct nameidata *nd,
+ char *type, unsigned long flags, void *data);
+int security_sb_check_sb(struct vfsmount *mnt, struct nameidata *nd);
+int security_sb_umount(struct vfsmount *mnt, int flags);
+void security_sb_umount_close(struct vfsmount *mnt);
+void security_sb_umount_busy(struct vfsmount *mnt);
+void security_sb_post_remount(struct vfsmount *mnt, unsigned long flags, void *data);
+void security_sb_post_mountroot(void);
+void security_sb_post_addmount(struct vfsmount *mnt, struct nameidata *mountpoint_nd);
+int security_sb_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd);
+void security_sb_post_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd);
+int security_inode_alloc(struct inode *inode);
+void security_inode_free(struct inode *inode);
+int security_inode_init_security(struct inode *inode, struct inode *dir,
+ char **name, void **value, size_t *len);
+int security_inode_create(struct inode *dir, struct dentry *dentry, int mode);
+int security_inode_link(struct dentry *old_dentry, struct inode *dir,
+ struct dentry *new_dentry);
+int security_inode_unlink(struct inode *dir, struct dentry *dentry);
+int security_inode_symlink(struct inode *dir, struct dentry *dentry,
+ const char *old_name);
+int security_inode_mkdir(struct inode *dir, struct dentry *dentry, int mode);
+int security_inode_rmdir(struct inode *dir, struct dentry *dentry);
+int security_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
+int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry);
+int security_inode_readlink(struct dentry *dentry);
+int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd);
+int security_inode_permission(struct inode *inode, int mask, struct nameidata *nd);
+int security_inode_setattr(struct dentry *dentry, struct iattr *attr);
+int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry);
+void security_inode_delete(struct inode *inode);
+int security_inode_setxattr(struct dentry *dentry, char *name,
+ void *value, size_t size, int flags);
+void security_inode_post_setxattr(struct dentry *dentry, char *name,
+ void *value, size_t size, int flags);
+int security_inode_getxattr(struct dentry *dentry, char *name);
+int security_inode_listxattr(struct dentry *dentry);
+int security_inode_removexattr(struct dentry *dentry, char *name);
+int security_inode_need_killpriv(struct dentry *dentry);
+int security_inode_killpriv(struct dentry *dentry);
+int security_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err);
+int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags);
+int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size);
+int security_file_permission(struct file *file, int mask);
+int security_file_alloc(struct file *file);
+void security_file_free(struct file *file);
+int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
+int security_file_mmap(struct file *file, unsigned long reqprot,
+ unsigned long prot, unsigned long flags,
+ unsigned long addr, unsigned long addr_only);
+int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
+ unsigned long prot);
+int security_file_lock(struct file *file, unsigned int cmd);
+int security_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg);
+int security_file_set_fowner(struct file *file);
+int security_file_send_sigiotask(struct task_struct *tsk,
+ struct fown_struct *fown, int sig);
+int security_file_receive(struct file *file);
+int security_dentry_open(struct file *file);
+int security_task_create(unsigned long clone_flags);
+int security_task_alloc(struct task_struct *p);
+void security_task_free(struct task_struct *p);
+int security_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags);
+int security_task_post_setuid(uid_t old_ruid, uid_t old_euid,
+ uid_t old_suid, int flags);
+int security_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags);
+int security_task_setpgid(struct task_struct *p, pid_t pgid);
+int security_task_getpgid(struct task_struct *p);
+int security_task_getsid(struct task_struct *p);
+void security_task_getsecid(struct task_struct *p, u32 *secid);
+int security_task_setgroups(struct group_info *group_info);
+int security_task_setnice(struct task_struct *p, int nice);
+int security_task_setioprio(struct task_struct *p, int ioprio);
+int security_task_getioprio(struct task_struct *p);
+int security_task_setrlimit(unsigned int resource, struct rlimit *new_rlim);
+int security_task_setscheduler(struct task_struct *p,
+ int policy, struct sched_param *lp);
+int security_task_getscheduler(struct task_struct *p);
+int security_task_movememory(struct task_struct *p);
+int security_task_kill(struct task_struct *p, struct siginfo *info,
+ int sig, u32 secid);
+int security_task_wait(struct task_struct *p);
+int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
+ unsigned long arg4, unsigned long arg5);
+void security_task_reparent_to_init(struct task_struct *p);
+void security_task_to_inode(struct task_struct *p, struct inode *inode);
+int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag);
+int security_msg_msg_alloc(struct msg_msg *msg);
+void security_msg_msg_free(struct msg_msg *msg);
+int security_msg_queue_alloc(struct msg_queue *msq);
+void security_msg_queue_free(struct msg_queue *msq);
+int security_msg_queue_associate(struct msg_queue *msq, int msqflg);
+int security_msg_queue_msgctl(struct msg_queue *msq, int cmd);
+int security_msg_queue_msgsnd(struct msg_queue *msq,
+ struct msg_msg *msg, int msqflg);
+int security_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
+ struct task_struct *target, long type, int mode);
+int security_shm_alloc(struct shmid_kernel *shp);
+void security_shm_free(struct shmid_kernel *shp);
+int security_shm_associate(struct shmid_kernel *shp, int shmflg);
+int security_shm_shmctl(struct shmid_kernel *shp, int cmd);
+int security_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr, int shmflg);
+int security_sem_alloc(struct sem_array *sma);
+void security_sem_free(struct sem_array *sma);
+int security_sem_associate(struct sem_array *sma, int semflg);
+int security_sem_semctl(struct sem_array *sma, int cmd);
+int security_sem_semop(struct sem_array *sma, struct sembuf *sops,
+ unsigned nsops, int alter);
+void security_d_instantiate (struct dentry *dentry, struct inode *inode);
+int security_getprocattr(struct task_struct *p, char *name, char **value);
+int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size);
+int security_netlink_send(struct sock *sk, struct sk_buff *skb);
+int security_netlink_recv(struct sk_buff *skb, int cap);
+int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
+void security_release_secctx(char *secdata, u32 seclen);
+
#else /* CONFIG_SECURITY */
/*
@@ -2463,9 +1923,14 @@ static inline int security_inode_removexattr (struct dentry *dentry, char *name)
return cap_inode_removexattr(dentry, name);
}
-static inline const char *security_inode_xattr_getsuffix (void)
+static inline int security_inode_need_killpriv(struct dentry *dentry)
+{
+ return cap_inode_need_killpriv(dentry);
+}
+
+static inline int security_inode_killpriv(struct dentry *dentry)
{
- return NULL ;
+ return cap_inode_killpriv(dentry);
}
static inline int security_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
@@ -2546,6 +2011,11 @@ static inline int security_file_receive (struct file *file)
return 0;
}
+static inline int security_dentry_open (struct file *file)
+{
+ return 0;
+}
+
static inline int security_task_create (unsigned long clone_flags)
{
return 0;
@@ -2602,12 +2072,12 @@ static inline int security_task_setgroups (struct group_info *group_info)
static inline int security_task_setnice (struct task_struct *p, int nice)
{
- return 0;
+ return cap_task_setnice(p, nice);
}
static inline int security_task_setioprio (struct task_struct *p, int ioprio)
{
- return 0;
+ return cap_task_setioprio(p, ioprio);
}
static inline int security_task_getioprio (struct task_struct *p)
@@ -2625,7 +2095,7 @@ static inline int security_task_setscheduler (struct task_struct *p,
int policy,
struct sched_param *lp)
{
- return 0;
+ return cap_task_setscheduler(p, policy, lp);
}
static inline int security_task_getscheduler (struct task_struct *p)
@@ -2642,7 +2112,7 @@ static inline int security_task_kill (struct task_struct *p,
struct siginfo *info, int sig,
u32 secid)
{
- return 0;
+ return cap_task_kill(p, info, sig, secid);
}
static inline int security_task_wait (struct task_struct *p)
@@ -2816,170 +2286,43 @@ static inline void security_release_secctx(char *secdata, u32 seclen)
#endif /* CONFIG_SECURITY */
#ifdef CONFIG_SECURITY_NETWORK
-static inline int security_unix_stream_connect(struct socket * sock,
- struct socket * other,
- struct sock * newsk)
-{
- return security_ops->unix_stream_connect(sock, other, newsk);
-}
+int security_unix_stream_connect(struct socket *sock, struct socket *other,
+ struct sock *newsk);
+int security_unix_may_send(struct socket *sock, struct socket *other);
+int security_socket_create(int family, int type, int protocol, int kern);
+int security_socket_post_create(struct socket *sock, int family,
+ int type, int protocol, int kern);
+int security_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen);
+int security_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen);
+int security_socket_listen(struct socket *sock, int backlog);
+int security_socket_accept(struct socket *sock, struct socket *newsock);
+void security_socket_post_accept(struct socket *sock, struct socket *newsock);
+int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size);
+int security_socket_recvmsg(struct socket *sock, struct msghdr *msg,
+ int size, int flags);
+int security_socket_getsockname(struct socket *sock);
+int security_socket_getpeername(struct socket *sock);
+int security_socket_getsockopt(struct socket *sock, int level, int optname);
+int security_socket_setsockopt(struct socket *sock, int level, int optname);
+int security_socket_shutdown(struct socket *sock, int how);
+int security_sock_rcv_skb(struct sock *sk, struct sk_buff *skb);
+int security_socket_getpeersec_stream(struct socket *sock, char __user *optval,
+ int __user *optlen, unsigned len);
+int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid);
+int security_sk_alloc(struct sock *sk, int family, gfp_t priority);
+void security_sk_free(struct sock *sk);
+void security_sk_clone(const struct sock *sk, struct sock *newsk);
+void security_sk_classify_flow(struct sock *sk, struct flowi *fl);
+void security_req_classify_flow(const struct request_sock *req, struct flowi *fl);
+void security_sock_graft(struct sock*sk, struct socket *parent);
+int security_inet_conn_request(struct sock *sk,
+ struct sk_buff *skb, struct request_sock *req);
+void security_inet_csk_clone(struct sock *newsk,
+ const struct request_sock *req);
+void security_inet_conn_established(struct sock *sk,
+ struct sk_buff *skb);
-static inline int security_unix_may_send(struct socket * sock,
- struct socket * other)
-{
- return security_ops->unix_may_send(sock, other);
-}
-
-static inline int security_socket_create (int family, int type,
- int protocol, int kern)
-{
- return security_ops->socket_create(family, type, protocol, kern);
-}
-
-static inline int security_socket_post_create(struct socket * sock,
- int family,
- int type,
- int protocol, int kern)
-{
- return security_ops->socket_post_create(sock, family, type,
- protocol, kern);
-}
-
-static inline int security_socket_bind(struct socket * sock,
- struct sockaddr * address,
- int addrlen)
-{
- return security_ops->socket_bind(sock, address, addrlen);
-}
-
-static inline int security_socket_connect(struct socket * sock,
- struct sockaddr * address,
- int addrlen)
-{
- return security_ops->socket_connect(sock, address, addrlen);
-}
-
-static inline int security_socket_listen(struct socket * sock, int backlog)
-{
- return security_ops->socket_listen(sock, backlog);
-}
-
-static inline int security_socket_accept(struct socket * sock,
- struct socket * newsock)
-{
- return security_ops->socket_accept(sock, newsock);
-}
-
-static inline void security_socket_post_accept(struct socket * sock,
- struct socket * newsock)
-{
- security_ops->socket_post_accept(sock, newsock);
-}
-
-static inline int security_socket_sendmsg(struct socket * sock,
- struct msghdr * msg, int size)
-{
- return security_ops->socket_sendmsg(sock, msg, size);
-}
-
-static inline int security_socket_recvmsg(struct socket * sock,
- struct msghdr * msg, int size,
- int flags)
-{
- return security_ops->socket_recvmsg(sock, msg, size, flags);
-}
-
-static inline int security_socket_getsockname(struct socket * sock)
-{
- return security_ops->socket_getsockname(sock);
-}
-
-static inline int security_socket_getpeername(struct socket * sock)
-{
- return security_ops->socket_getpeername(sock);
-}
-
-static inline int security_socket_getsockopt(struct socket * sock,
- int level, int optname)
-{
- return security_ops->socket_getsockopt(sock, level, optname);
-}
-
-static inline int security_socket_setsockopt(struct socket * sock,
- int level, int optname)
-{
- return security_ops->socket_setsockopt(sock, level, optname);
-}
-
-static inline int security_socket_shutdown(struct socket * sock, int how)
-{
- return security_ops->socket_shutdown(sock, how);
-}
-
-static inline int security_sock_rcv_skb (struct sock * sk,
- struct sk_buff * skb)
-{
- return security_ops->socket_sock_rcv_skb (sk, skb);
-}
-
-static inline int security_socket_getpeersec_stream(struct socket *sock, char __user *optval,
- int __user *optlen, unsigned len)
-{
- return security_ops->socket_getpeersec_stream(sock, optval, optlen, len);
-}
-
-static inline int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
-{
- return security_ops->socket_getpeersec_dgram(sock, skb, secid);
-}
-
-static inline int security_sk_alloc(struct sock *sk, int family, gfp_t priority)
-{
- return security_ops->sk_alloc_security(sk, family, priority);
-}
-
-static inline void security_sk_free(struct sock *sk)
-{
- return security_ops->sk_free_security(sk);
-}
-
-static inline void security_sk_clone(const struct sock *sk, struct sock *newsk)
-{
- return security_ops->sk_clone_security(sk, newsk);
-}
-
-static inline void security_sk_classify_flow(struct sock *sk, struct flowi *fl)
-{
- security_ops->sk_getsecid(sk, &fl->secid);
-}
-
-static inline void security_req_classify_flow(const struct request_sock *req, struct flowi *fl)
-{
- security_ops->req_classify_flow(req, fl);
-}
-
-static inline void security_sock_graft(struct sock* sk, struct socket *parent)
-{
- security_ops->sock_graft(sk, parent);
-}
-
-static inline int security_inet_conn_request(struct sock *sk,
- struct sk_buff *skb, struct request_sock *req)
-{
- return security_ops->inet_conn_request(sk, skb, req);
-}
-
-static inline void security_inet_csk_clone(struct sock *newsk,
- const struct request_sock *req)
-{
- security_ops->inet_csk_clone(newsk, req);
-}
-
-static inline void security_inet_conn_established(struct sock *sk,
- struct sk_buff *skb)
-{
- security_ops->inet_conn_established(sk, skb);
-}
#else /* CONFIG_SECURITY_NETWORK */
static inline int security_unix_stream_connect(struct socket * sock,
struct socket * other,
@@ -3137,77 +2480,24 @@ static inline void security_inet_conn_established(struct sock *sk,
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
-static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx)
-{
- return security_ops->xfrm_policy_alloc_security(xp, sec_ctx);
-}
-static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new)
-{
- return security_ops->xfrm_policy_clone_security(old, new);
-}
-
-static inline void security_xfrm_policy_free(struct xfrm_policy *xp)
-{
- security_ops->xfrm_policy_free_security(xp);
-}
-
-static inline int security_xfrm_policy_delete(struct xfrm_policy *xp)
-{
- return security_ops->xfrm_policy_delete_security(xp);
-}
+int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx);
+int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new);
+void security_xfrm_policy_free(struct xfrm_policy *xp);
+int security_xfrm_policy_delete(struct xfrm_policy *xp);
+int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx);
+int security_xfrm_state_alloc_acquire(struct xfrm_state *x,
+ struct xfrm_sec_ctx *polsec, u32 secid);
+int security_xfrm_state_delete(struct xfrm_state *x);
+void security_xfrm_state_free(struct xfrm_state *x);
+int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir);
+int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
+ struct xfrm_policy *xp, struct flowi *fl);
+int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid);
+void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl);
-static inline int security_xfrm_state_alloc(struct xfrm_state *x,
- struct xfrm_user_sec_ctx *sec_ctx)
-{
- return security_ops->xfrm_state_alloc_security(x, sec_ctx, 0);
-}
-
-static inline int security_xfrm_state_alloc_acquire(struct xfrm_state *x,
- struct xfrm_sec_ctx *polsec, u32 secid)
-{
- if (!polsec)
- return 0;
- /*
- * We want the context to be taken from secid which is usually
- * from the sock.
- */
- return security_ops->xfrm_state_alloc_security(x, NULL, secid);
-}
-
-static inline int security_xfrm_state_delete(struct xfrm_state *x)
-{
- return security_ops->xfrm_state_delete_security(x);
-}
-
-static inline void security_xfrm_state_free(struct xfrm_state *x)
-{
- security_ops->xfrm_state_free_security(x);
-}
-
-static inline int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir)
-{
- return security_ops->xfrm_policy_lookup(xp, fl_secid, dir);
-}
-
-static inline int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
- struct xfrm_policy *xp, struct flowi *fl)
-{
- return security_ops->xfrm_state_pol_flow_match(x, xp, fl);
-}
-
-static inline int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid)
-{
- return security_ops->xfrm_decode_session(skb, secid, 1);
-}
-
-static inline void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl)
-{
- int rc = security_ops->xfrm_decode_session(skb, &fl->secid, 0);
-
- BUG_ON(rc);
-}
#else /* CONFIG_SECURITY_NETWORK_XFRM */
+
static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx)
{
return 0;
@@ -3272,24 +2562,11 @@ static inline void security_skb_classify_flow(struct sk_buff *skb, struct flowi
#ifdef CONFIG_KEYS
#ifdef CONFIG_SECURITY
-static inline int security_key_alloc(struct key *key,
- struct task_struct *tsk,
- unsigned long flags)
-{
- return security_ops->key_alloc(key, tsk, flags);
-}
-
-static inline void security_key_free(struct key *key)
-{
- security_ops->key_free(key);
-}
-static inline int security_key_permission(key_ref_t key_ref,
- struct task_struct *context,
- key_perm_t perm)
-{
- return security_ops->key_permission(key_ref, context, perm);
-}
+int security_key_alloc(struct key *key, struct task_struct *tsk, unsigned long flags);
+void security_key_free(struct key *key);
+int security_key_permission(key_ref_t key_ref,
+ struct task_struct *context, key_perm_t perm);
#else
diff --git a/include/linux/selection.h b/include/linux/selection.h
index f9457861937c..8cdaa1151d2e 100644
--- a/include/linux/selection.h
+++ b/include/linux/selection.h
@@ -13,6 +13,7 @@
struct tty_struct;
extern struct vc_data *sel_cons;
+struct tty_struct;
extern void clear_selection(void);
extern int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty);
diff --git a/include/linux/sem.h b/include/linux/sem.h
index 9aaffb0b1d81..c8eaad9e4b72 100644
--- a/include/linux/sem.h
+++ b/include/linux/sem.h
@@ -90,7 +90,6 @@ struct sem {
/* One sem_array data structure for each set of semaphores in the system. */
struct sem_array {
struct kern_ipc_perm sem_perm; /* permissions .. see ipc.h */
- int sem_id;
time_t sem_otime; /* last semop time */
time_t sem_ctime; /* last change time */
struct sem *sem_base; /* ptr to first semaphore in array */
diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h
index 8bf1e05115b4..ebbc02b325fc 100644
--- a/include/linux/seq_file.h
+++ b/include/linux/seq_file.h
@@ -18,7 +18,7 @@ struct seq_file {
size_t from;
size_t count;
loff_t index;
- loff_t version;
+ u64 version;
struct mutex lock;
const struct seq_operations *op;
void *private;
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 09d17b06bf02..6a5203fb9cf1 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -146,6 +146,9 @@
/* Broadcom SB1250, etc. SOC */
#define PORT_SB1250_DUART 77
+/* Freescale ColdFire */
+#define PORT_MCF 78
+
#ifdef __KERNEL__
@@ -291,7 +294,8 @@ struct uart_port {
resource_size_t mapbase; /* for ioremap */
struct device *dev; /* parent device */
unsigned char hub6; /* this should be in the 8250 driver */
- unsigned char unused[3];
+ unsigned char suspended;
+ unsigned char unused[2];
void *private_data; /* generic platform data pointer */
};
diff --git a/include/linux/shm.h b/include/linux/shm.h
index ad2e3af65997..eeaed921a1dc 100644
--- a/include/linux/shm.h
+++ b/include/linux/shm.h
@@ -16,7 +16,9 @@
#define SHMALL (SHMMAX/PAGE_SIZE*(SHMMNI/16)) /* max shm system wide (pages) */
#define SHMSEG SHMMNI /* max shared segs per process */
+#ifdef __KERNEL__
#include <asm/shmparam.h>
+#endif
/* Obsolete, used only for backwards compatibility and libc5 compiles */
struct shmid_ds {
@@ -77,7 +79,6 @@ struct shmid_kernel /* private to the kernel */
{
struct kern_ipc_perm shm_perm;
struct file * shm_file;
- int id;
unsigned long shm_nattch;
unsigned long shm_segsz;
time_t shm_atim;
diff --git a/include/linux/signalfd.h b/include/linux/signalfd.h
index 4c9ff0910ae0..86f9b1ef0e09 100644
--- a/include/linux/signalfd.h
+++ b/include/linux/signalfd.h
@@ -10,22 +10,22 @@
struct signalfd_siginfo {
- __u32 signo;
- __s32 err;
- __s32 code;
- __u32 pid;
- __u32 uid;
- __s32 fd;
- __u32 tid;
- __u32 band;
- __u32 overrun;
- __u32 trapno;
- __s32 status;
- __s32 svint;
- __u64 svptr;
- __u64 utime;
- __u64 stime;
- __u64 addr;
+ __u32 ssi_signo;
+ __s32 ssi_errno;
+ __s32 ssi_code;
+ __u32 ssi_pid;
+ __u32 ssi_uid;
+ __s32 ssi_fd;
+ __u32 ssi_tid;
+ __u32 ssi_band;
+ __u32 ssi_overrun;
+ __u32 ssi_trapno;
+ __s32 ssi_status;
+ __s32 ssi_int;
+ __u64 ssi_ptr;
+ __u64 ssi_utime;
+ __u64 ssi_stime;
+ __u64 ssi_addr;
/*
* Pad strcture to 128 bytes. Remember to update the
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index a656cecd373c..91140fe8c119 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -41,8 +41,7 @@
#define SKB_DATA_ALIGN(X) (((X) + (SMP_CACHE_BYTES - 1)) & \
~(SMP_CACHE_BYTES - 1))
#define SKB_WITH_OVERHEAD(X) \
- (((X) - sizeof(struct skb_shared_info)) & \
- ~(SMP_CACHE_BYTES - 1))
+ ((X) - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
#define SKB_MAX_ORDER(X, ORDER) \
SKB_WITH_OVERHEAD((PAGE_SIZE << (ORDER)) - (X))
#define SKB_MAX_HEAD(X) (SKB_MAX_ORDER((X), 0))
@@ -301,8 +300,9 @@ struct sk_buff {
#endif
int iif;
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
__u16 queue_mapping;
-
+#endif
#ifdef CONFIG_NET_SCHED
__u16 tc_index; /* traffic control index */
#ifdef CONFIG_NET_CLS_ACT
@@ -357,6 +357,7 @@ static inline struct sk_buff *alloc_skb_fclone(unsigned int size,
}
extern void kfree_skbmem(struct sk_buff *skb);
+extern struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src);
extern struct sk_buff *skb_clone(struct sk_buff *skb,
gfp_t priority);
extern struct sk_buff *skb_copy(const struct sk_buff *skb,
@@ -386,7 +387,9 @@ extern void skb_truesize_bug(struct sk_buff *skb);
static inline void skb_truesize_check(struct sk_buff *skb)
{
- if (unlikely((int)skb->truesize < sizeof(struct sk_buff) + skb->len))
+ int len = sizeof(struct sk_buff) + skb->len;
+
+ if (unlikely((int)skb->truesize < len))
skb_truesize_bug(skb);
}
@@ -993,7 +996,7 @@ static inline int pskb_may_pull(struct sk_buff *skb, unsigned int len)
*
* Return the number of bytes of free space at the head of an &sk_buff.
*/
-static inline int skb_headroom(const struct sk_buff *skb)
+static inline unsigned int skb_headroom(const struct sk_buff *skb)
{
return skb->data - skb->head;
}
@@ -1346,7 +1349,7 @@ static inline struct sk_buff *netdev_alloc_skb(struct net_device *dev,
* Returns true if modifying the header part of the cloned buffer
* does not requires the data to be copied.
*/
-static inline int skb_clone_writable(struct sk_buff *skb, int len)
+static inline int skb_clone_writable(struct sk_buff *skb, unsigned int len)
{
return !skb_header_cloned(skb) &&
skb_headroom(skb) + len <= skb->hdr_len;
@@ -1769,6 +1772,15 @@ static inline void skb_set_queue_mapping(struct sk_buff *skb, u16 queue_mapping)
#endif
}
+static inline u16 skb_get_queue_mapping(struct sk_buff *skb)
+{
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+ return skb->queue_mapping;
+#else
+ return 0;
+#endif
+}
+
static inline void skb_copy_queue_mapping(struct sk_buff *to, const struct sk_buff *from)
{
#ifdef CONFIG_NETDEVICES_MULTIQUEUE
@@ -1781,6 +1793,11 @@ static inline int skb_is_gso(const struct sk_buff *skb)
return skb_shinfo(skb)->gso_size;
}
+static inline int skb_is_gso_v6(const struct sk_buff *skb)
+{
+ return skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6;
+}
+
static inline void skb_forward_csum(struct sk_buff *skb)
{
/* Unfortunately we don't support this one. Any brave souls? */
diff --git a/include/linux/slab.h b/include/linux/slab.h
index d859354b9e51..f3a8eecd99f3 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -24,12 +24,14 @@
#define SLAB_HWCACHE_ALIGN 0x00002000UL /* Align objs on cache lines */
#define SLAB_CACHE_DMA 0x00004000UL /* Use GFP_DMA memory */
#define SLAB_STORE_USER 0x00010000UL /* DEBUG: Store the last owner for bug hunting */
-#define SLAB_RECLAIM_ACCOUNT 0x00020000UL /* Objects are reclaimable */
#define SLAB_PANIC 0x00040000UL /* Panic if kmem_cache_create() fails */
#define SLAB_DESTROY_BY_RCU 0x00080000UL /* Defer freeing slabs to RCU */
#define SLAB_MEM_SPREAD 0x00100000UL /* Spread some memory over cpuset */
#define SLAB_TRACE 0x00200000UL /* Trace allocations and frees */
+/* The following flags affect the page allocator grouping pages by mobility */
+#define SLAB_RECLAIM_ACCOUNT 0x00020000UL /* Objects are reclaimable */
+#define SLAB_TEMPORARY SLAB_RECLAIM_ACCOUNT /* Objects are short-lived */
/*
* ZERO_SIZE_PTR will be returned for zero sized kmalloc requests.
*
@@ -51,7 +53,7 @@ int slab_is_available(void);
struct kmem_cache *kmem_cache_create(const char *, size_t, size_t,
unsigned long,
- void (*)(void *, struct kmem_cache *, unsigned long));
+ void (*)(struct kmem_cache *, void *));
void kmem_cache_destroy(struct kmem_cache *);
int kmem_cache_shrink(struct kmem_cache *);
void kmem_cache_free(struct kmem_cache *, void *);
diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index 74962077f632..40801e754afb 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -11,6 +11,14 @@
#include <linux/workqueue.h>
#include <linux/kobject.h>
+struct kmem_cache_cpu {
+ void **freelist;
+ struct page *page;
+ int node;
+ unsigned int offset;
+ unsigned int objsize;
+};
+
struct kmem_cache_node {
spinlock_t list_lock; /* Protect partial list and nr_partial */
unsigned long nr_partial;
@@ -41,7 +49,7 @@ struct kmem_cache {
/* Allocation and freeing of slabs */
int objects; /* Number of objects in slab */
int refcount; /* Refcount for slab cache destroy */
- void (*ctor)(void *, struct kmem_cache *, unsigned long);
+ void (*ctor)(struct kmem_cache *, void *);
int inuse; /* Offset to metadata */
int align; /* Alignment */
const char *name; /* Name (only for display!) */
@@ -54,7 +62,11 @@ struct kmem_cache {
int defrag_ratio;
struct kmem_cache_node *node[MAX_NUMNODES];
#endif
- struct page *cpu_slab[NR_CPUS];
+#ifdef CONFIG_SMP
+ struct kmem_cache_cpu *cpu_slab[NR_CPUS];
+#else
+ struct kmem_cache_cpu cpu_slab;
+#endif
};
/*
@@ -72,7 +84,7 @@ struct kmem_cache {
* We keep the general caches in an array of slab caches that are used for
* 2^x bytes of allocations.
*/
-extern struct kmem_cache kmalloc_caches[KMALLOC_SHIFT_HIGH + 1];
+extern struct kmem_cache kmalloc_caches[PAGE_SHIFT];
/*
* Sorry that the following has to be that ugly but some versions of GCC
@@ -83,9 +95,6 @@ static __always_inline int kmalloc_index(size_t size)
if (!size)
return 0;
- if (size > KMALLOC_MAX_SIZE)
- return -1;
-
if (size <= KMALLOC_MIN_SIZE)
return KMALLOC_SHIFT_LOW;
@@ -102,6 +111,10 @@ static __always_inline int kmalloc_index(size_t size)
if (size <= 512) return 9;
if (size <= 1024) return 10;
if (size <= 2 * 1024) return 11;
+/*
+ * The following is only needed to support architectures with a larger page
+ * size than 4k.
+ */
if (size <= 4 * 1024) return 12;
if (size <= 8 * 1024) return 13;
if (size <= 16 * 1024) return 14;
@@ -109,13 +122,9 @@ static __always_inline int kmalloc_index(size_t size)
if (size <= 64 * 1024) return 16;
if (size <= 128 * 1024) return 17;
if (size <= 256 * 1024) return 18;
- if (size <= 512 * 1024) return 19;
+ if (size <= 512 * 1024) return 19;
if (size <= 1024 * 1024) return 20;
if (size <= 2 * 1024 * 1024) return 21;
- if (size <= 4 * 1024 * 1024) return 22;
- if (size <= 8 * 1024 * 1024) return 23;
- if (size <= 16 * 1024 * 1024) return 24;
- if (size <= 32 * 1024 * 1024) return 25;
return -1;
/*
@@ -140,19 +149,6 @@ static __always_inline struct kmem_cache *kmalloc_slab(size_t size)
if (index == 0)
return NULL;
- /*
- * This function only gets expanded if __builtin_constant_p(size), so
- * testing it here shouldn't be needed. But some versions of gcc need
- * help.
- */
- if (__builtin_constant_p(size) && index < 0) {
- /*
- * Generate a link failure. Would be great if we could
- * do something to stop the compile here.
- */
- extern void __kmalloc_size_too_large(void);
- __kmalloc_size_too_large();
- }
return &kmalloc_caches[index];
}
@@ -168,15 +164,21 @@ void *__kmalloc(size_t size, gfp_t flags);
static __always_inline void *kmalloc(size_t size, gfp_t flags)
{
- if (__builtin_constant_p(size) && !(flags & SLUB_DMA)) {
- struct kmem_cache *s = kmalloc_slab(size);
+ if (__builtin_constant_p(size)) {
+ if (size > PAGE_SIZE / 2)
+ return (void *)__get_free_pages(flags | __GFP_COMP,
+ get_order(size));
- if (!s)
- return ZERO_SIZE_PTR;
+ if (!(flags & SLUB_DMA)) {
+ struct kmem_cache *s = kmalloc_slab(size);
- return kmem_cache_alloc(s, flags);
- } else
- return __kmalloc(size, flags);
+ if (!s)
+ return ZERO_SIZE_PTR;
+
+ return kmem_cache_alloc(s, flags);
+ }
+ }
+ return __kmalloc(size, flags);
}
#ifdef CONFIG_NUMA
@@ -185,15 +187,16 @@ void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node);
static __always_inline void *kmalloc_node(size_t size, gfp_t flags, int node)
{
- if (__builtin_constant_p(size) && !(flags & SLUB_DMA)) {
- struct kmem_cache *s = kmalloc_slab(size);
+ if (__builtin_constant_p(size) &&
+ size <= PAGE_SIZE / 2 && !(flags & SLUB_DMA)) {
+ struct kmem_cache *s = kmalloc_slab(size);
if (!s)
return ZERO_SIZE_PTR;
return kmem_cache_alloc_node(s, flags, node);
- } else
- return __kmalloc_node(size, flags, node);
+ }
+ return __kmalloc_node(size, flags, node);
}
#endif
diff --git a/include/linux/sm501-regs.h b/include/linux/sm501-regs.h
index 014e73b31fc0..df7620dd8f31 100644
--- a/include/linux/sm501-regs.h
+++ b/include/linux/sm501-regs.h
@@ -15,6 +15,24 @@
/* config 1 */
#define SM501_SYSTEM_CONTROL (0x000000)
+
+#define SM501_SYSCTRL_PANEL_TRISTATE (1<<0)
+#define SM501_SYSCTRL_MEM_TRISTATE (1<<1)
+#define SM501_SYSCTRL_CRT_TRISTATE (1<<2)
+
+#define SM501_SYSCTRL_PCI_SLAVE_BURST_MASK (3<<4)
+#define SM501_SYSCTRL_PCI_SLAVE_BURST_1 (0<<4)
+#define SM501_SYSCTRL_PCI_SLAVE_BURST_2 (1<<4)
+#define SM501_SYSCTRL_PCI_SLAVE_BURST_4 (2<<4)
+#define SM501_SYSCTRL_PCI_SLAVE_BURST_8 (3<<4)
+
+#define SM501_SYSCTRL_PCI_CLOCK_RUN_EN (1<<6)
+#define SM501_SYSCTRL_PCI_RETRY_DISABLE (1<<7)
+#define SM501_SYSCTRL_PCI_SUBSYS_LOCK (1<<11)
+#define SM501_SYSCTRL_PCI_BURST_READ_EN (1<<15)
+
+/* miscellaneous control */
+
#define SM501_MISC_CONTROL (0x000004)
#define SM501_MISC_BUS_SH (0x0)
diff --git a/include/linux/smp.h b/include/linux/smp.h
index 259a13c3bd98..c25e66bcecf3 100644
--- a/include/linux/smp.h
+++ b/include/linux/smp.h
@@ -84,11 +84,12 @@ void smp_prepare_boot_cpu(void);
* These macros fold the SMP functionality into a single CPU system
*/
#define raw_smp_processor_id() 0
-static inline int up_smp_call_function(void)
+static inline int up_smp_call_function(void (*func)(void *), void *info)
{
return 0;
}
-#define smp_call_function(func,info,retry,wait) (up_smp_call_function())
+#define smp_call_function(func, info, retry, wait) \
+ (up_smp_call_function(func, info))
#define on_each_cpu(func,info,retry,wait) \
({ \
local_irq_disable(); \
@@ -107,6 +108,8 @@ static inline void smp_send_reschedule(int cpu) { }
local_irq_enable(); \
0; \
})
+#define smp_call_function_mask(mask, func, info, wait) \
+ (up_smp_call_function(func, info))
#endif /* !SMP */
diff --git a/include/linux/socket.h b/include/linux/socket.h
index f852e1afd65a..c22ef1c1afb8 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -291,6 +291,7 @@ struct ucred {
#define SOL_TIPC 271
#define SOL_RXRPC 272
#define SOL_PPPOL2TP 273
+#define SOL_BLUETOOTH 274
/* IPX options */
#define IPX_TYPE 1
diff --git a/include/linux/spi/at73c213.h b/include/linux/spi/at73c213.h
new file mode 100644
index 000000000000..0f20a70e5eb4
--- /dev/null
+++ b/include/linux/spi/at73c213.h
@@ -0,0 +1,25 @@
+/*
+ * Board-specific data used to set up AT73c213 audio DAC driver.
+ */
+
+#ifndef __LINUX_SPI_AT73C213_H
+#define __LINUX_SPI_AT73C213_H
+
+/**
+ * at73c213_board_info - how the external DAC is wired to the device.
+ *
+ * @ssc_id: SSC platform_driver id the DAC shall use to stream the audio.
+ * @dac_clk: the external clock used to provide master clock to the DAC.
+ * @shortname: a short discription for the DAC, seen by userspace tools.
+ *
+ * This struct contains the configuration of the hardware connection to the
+ * external DAC. The DAC needs a master clock and a I2S audio stream. It also
+ * provides a name which is used to identify it in userspace tools.
+ */
+struct at73c213_board_info {
+ int ssc_id;
+ struct clk *dac_clk;
+ char shortname[32];
+};
+
+#endif /* __LINUX_SPI_AT73C213_H */
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 002a3cddbdd5..387e428f1cdf 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -195,7 +195,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
/**
* struct spi_master - interface to SPI master controller
- * @cdev: class interface to this driver
+ * @dev: device interface to this driver
* @bus_num: board-specific (and often SOC-specific) identifier for a
* given SPI controller.
* @num_chipselect: chipselects are used to distinguish individual
@@ -222,7 +222,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
* message's completion function when the transaction completes.
*/
struct spi_master {
- struct class_device cdev;
+ struct device dev;
/* other than negative (== assign one dynamically), bus_num is fully
* board-specific. usually that simplifies to being SOC-specific.
@@ -268,17 +268,17 @@ struct spi_master {
static inline void *spi_master_get_devdata(struct spi_master *master)
{
- return class_get_devdata(&master->cdev);
+ return dev_get_drvdata(&master->dev);
}
static inline void spi_master_set_devdata(struct spi_master *master, void *data)
{
- class_set_devdata(&master->cdev, data);
+ dev_set_drvdata(&master->dev, data);
}
static inline struct spi_master *spi_master_get(struct spi_master *master)
{
- if (!master || !class_device_get(&master->cdev))
+ if (!master || !get_device(&master->dev))
return NULL;
return master;
}
@@ -286,7 +286,7 @@ static inline struct spi_master *spi_master_get(struct spi_master *master)
static inline void spi_master_put(struct spi_master *master)
{
if (master)
- class_device_put(&master->cdev);
+ put_device(&master->dev);
}
diff --git a/include/linux/string.h b/include/linux/string.h
index 836062b7582a..c5d3fcad7b57 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -3,16 +3,14 @@
/* We don't want strings.h stuff being user by user stuff by accident */
-#ifdef __KERNEL__
+#ifndef __KERNEL__
+#include <string.h>
+#else
#include <linux/compiler.h> /* for inline */
#include <linux/types.h> /* for size_t */
#include <linux/stddef.h> /* for NULL */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
extern char *strndup_user(const char __user *, long);
/*
@@ -111,9 +109,5 @@ extern void *kmemdup(const void *src, size_t len, gfp_t gfp);
extern char **argv_split(gfp_t gfp, const char *str, int *argcp);
extern void argv_free(char **argv);
-#ifdef __cplusplus
-}
-#endif
-
#endif
#endif /* _LINUX_STRING_H_ */
diff --git a/include/linux/sunrpc/rpc_rdma.h b/include/linux/sunrpc/rpc_rdma.h
index 0013a0d8dc6b..87b895d5c786 100644
--- a/include/linux/sunrpc/rpc_rdma.h
+++ b/include/linux/sunrpc/rpc_rdma.h
@@ -41,17 +41,17 @@
#define _LINUX_SUNRPC_RPC_RDMA_H
struct rpcrdma_segment {
- uint32_t rs_handle; /* Registered memory handle */
- uint32_t rs_length; /* Length of the chunk in bytes */
- uint64_t rs_offset; /* Chunk virtual address or offset */
+ __be32 rs_handle; /* Registered memory handle */
+ __be32 rs_length; /* Length of the chunk in bytes */
+ __be64 rs_offset; /* Chunk virtual address or offset */
};
/*
* read chunk(s), encoded as a linked list.
*/
struct rpcrdma_read_chunk {
- uint32_t rc_discrim; /* 1 indicates presence */
- uint32_t rc_position; /* Position in XDR stream */
+ __be32 rc_discrim; /* 1 indicates presence */
+ __be32 rc_position; /* Position in XDR stream */
struct rpcrdma_segment rc_target;
};
@@ -66,29 +66,29 @@ struct rpcrdma_write_chunk {
* write chunk(s), encoded as a counted array.
*/
struct rpcrdma_write_array {
- uint32_t wc_discrim; /* 1 indicates presence */
- uint32_t wc_nchunks; /* Array count */
+ __be32 wc_discrim; /* 1 indicates presence */
+ __be32 wc_nchunks; /* Array count */
struct rpcrdma_write_chunk wc_array[0];
};
struct rpcrdma_msg {
- uint32_t rm_xid; /* Mirrors the RPC header xid */
- uint32_t rm_vers; /* Version of this protocol */
- uint32_t rm_credit; /* Buffers requested/granted */
- uint32_t rm_type; /* Type of message (enum rpcrdma_proc) */
+ __be32 rm_xid; /* Mirrors the RPC header xid */
+ __be32 rm_vers; /* Version of this protocol */
+ __be32 rm_credit; /* Buffers requested/granted */
+ __be32 rm_type; /* Type of message (enum rpcrdma_proc) */
union {
struct { /* no chunks */
- uint32_t rm_empty[3]; /* 3 empty chunk lists */
+ __be32 rm_empty[3]; /* 3 empty chunk lists */
} rm_nochunks;
struct { /* no chunks and padded */
- uint32_t rm_align; /* Padding alignment */
- uint32_t rm_thresh; /* Padding threshold */
- uint32_t rm_pempty[3]; /* 3 empty chunk lists */
+ __be32 rm_align; /* Padding alignment */
+ __be32 rm_thresh; /* Padding threshold */
+ __be32 rm_pempty[3]; /* 3 empty chunk lists */
} rm_padded;
- uint32_t rm_chunks[0]; /* read, write and reply chunks */
+ __be32 rm_chunks[0]; /* read, write and reply chunks */
} rm_body;
};
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index 388cace9751f..4360e0816956 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -1,5 +1,5 @@
-#ifndef _LINUX_SWSUSP_H
-#define _LINUX_SWSUSP_H
+#ifndef _LINUX_SUSPEND_H
+#define _LINUX_SUSPEND_H
#if defined(CONFIG_X86) || defined(CONFIG_FRV) || defined(CONFIG_PPC32) || defined(CONFIG_PPC64)
#include <asm/suspend.h>
@@ -9,6 +9,108 @@
#include <linux/init.h>
#include <linux/pm.h>
#include <linux/mm.h>
+#include <asm/errno.h>
+
+#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE)
+extern int pm_prepare_console(void);
+extern void pm_restore_console(void);
+#else
+static inline int pm_prepare_console(void) { return 0; }
+static inline void pm_restore_console(void) {}
+#endif
+
+typedef int __bitwise suspend_state_t;
+
+#define PM_SUSPEND_ON ((__force suspend_state_t) 0)
+#define PM_SUSPEND_STANDBY ((__force suspend_state_t) 1)
+#define PM_SUSPEND_MEM ((__force suspend_state_t) 3)
+#define PM_SUSPEND_MAX ((__force suspend_state_t) 4)
+
+/**
+ * struct platform_suspend_ops - Callbacks for managing platform dependent
+ * system sleep states.
+ *
+ * @valid: Callback to determine if given system sleep state is supported by
+ * the platform.
+ * Valid (ie. supported) states are advertised in /sys/power/state. Note
+ * that it still may be impossible to enter given system sleep state if the
+ * conditions aren't right.
+ * There is the %suspend_valid_only_mem function available that can be
+ * assigned to this if the platform only supports mem sleep.
+ *
+ * @set_target: Tell the platform which system sleep state is going to be
+ * entered.
+ * @set_target() is executed right prior to suspending devices. The
+ * information conveyed to the platform code by @set_target() should be
+ * disregarded by the platform as soon as @finish() is executed and if
+ * @prepare() fails. If @set_target() fails (ie. returns nonzero),
+ * @prepare(), @enter() and @finish() will not be called by the PM core.
+ * This callback is optional. However, if it is implemented, the argument
+ * passed to @enter() is meaningless and should be ignored.
+ *
+ * @prepare: Prepare the platform for entering the system sleep state indicated
+ * by @set_target().
+ * @prepare() is called right after devices have been suspended (ie. the
+ * appropriate .suspend() method has been executed for each device) and
+ * before the nonboot CPUs are disabled (it is executed with IRQs enabled).
+ * This callback is optional. It returns 0 on success or a negative
+ * error code otherwise, in which case the system cannot enter the desired
+ * sleep state (@enter() and @finish() will not be called in that case).
+ *
+ * @enter: Enter the system sleep state indicated by @set_target() or
+ * represented by the argument if @set_target() is not implemented.
+ * This callback is mandatory. It returns 0 on success or a negative
+ * error code otherwise, in which case the system cannot enter the desired
+ * sleep state.
+ *
+ * @finish: Called when the system has just left a sleep state, right after
+ * the nonboot CPUs have been enabled and before devices are resumed (it is
+ * executed with IRQs enabled).
+ * This callback is optional, but should be implemented by the platforms
+ * that implement @prepare(). If implemented, it is always called after
+ * @enter() (even if @enter() fails).
+ */
+struct platform_suspend_ops {
+ int (*valid)(suspend_state_t state);
+ int (*set_target)(suspend_state_t state);
+ int (*prepare)(void);
+ int (*enter)(suspend_state_t state);
+ void (*finish)(void);
+};
+
+#ifdef CONFIG_SUSPEND
+/**
+ * suspend_set_ops - set platform dependent suspend operations
+ * @ops: The new suspend operations to set.
+ */
+extern void suspend_set_ops(struct platform_suspend_ops *ops);
+extern int suspend_valid_only_mem(suspend_state_t state);
+
+/**
+ * arch_suspend_disable_irqs - disable IRQs for suspend
+ *
+ * Disables IRQs (in the default case). This is a weak symbol in the common
+ * code and thus allows architectures to override it if more needs to be
+ * done. Not called for suspend to disk.
+ */
+extern void arch_suspend_disable_irqs(void);
+
+/**
+ * arch_suspend_enable_irqs - enable IRQs after suspend
+ *
+ * Enables IRQs (in the default case). This is a weak symbol in the common
+ * code and thus allows architectures to override it if more needs to be
+ * done. Not called for suspend to disk.
+ */
+extern void arch_suspend_enable_irqs(void);
+
+extern int pm_suspend(suspend_state_t state);
+#else /* !CONFIG_SUSPEND */
+#define suspend_valid_only_mem NULL
+
+static inline void suspend_set_ops(struct platform_suspend_ops *ops) {}
+static inline int pm_suspend(suspend_state_t state) { return -ENOSYS; }
+#endif /* !CONFIG_SUSPEND */
/* struct pbe is used for creating lists of pages that should be restored
* atomically during the resume from disk, because the page frames they have
@@ -24,32 +126,57 @@ struct pbe {
extern void drain_local_pages(void);
extern void mark_free_pages(struct zone *zone);
-#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE)
-extern int pm_prepare_console(void);
-extern void pm_restore_console(void);
-#else
-static inline int pm_prepare_console(void) { return 0; }
-static inline void pm_restore_console(void) {}
-#endif
-
/**
- * struct hibernation_ops - hibernation platform support
+ * struct platform_hibernation_ops - hibernation platform support
*
* The methods in this structure allow a platform to override the default
* mechanism of shutting down the machine during a hibernation transition.
*
* All three methods must be assigned.
*
- * @prepare: prepare system for hibernation
- * @enter: shut down system after state has been saved to disk
- * @finish: finish/clean up after state has been reloaded
- * @pre_restore: prepare system for the restoration from a hibernation image
- * @restore_cleanup: clean up after a failing image restoration
+ * @start: Tell the platform driver that we're starting hibernation.
+ * Called right after shrinking memory and before freezing devices.
+ *
+ * @pre_snapshot: Prepare the platform for creating the hibernation image.
+ * Called right after devices have been frozen and before the nonboot
+ * CPUs are disabled (runs with IRQs on).
+ *
+ * @finish: Restore the previous state of the platform after the hibernation
+ * image has been created *or* put the platform into the normal operation
+ * mode after the hibernation (the same method is executed in both cases).
+ * Called right after the nonboot CPUs have been enabled and before
+ * thawing devices (runs with IRQs on).
+ *
+ * @prepare: Prepare the platform for entering the low power state.
+ * Called right after the hibernation image has been saved and before
+ * devices are prepared for entering the low power state.
+ *
+ * @enter: Put the system into the low power state after the hibernation image
+ * has been saved to disk.
+ * Called after the nonboot CPUs have been disabled and all of the low
+ * level devices have been shut down (runs with IRQs off).
+ *
+ * @leave: Perform the first stage of the cleanup after the system sleep state
+ * indicated by @set_target() has been left.
+ * Called right after the control has been passed from the boot kernel to
+ * the image kernel, before the nonboot CPUs are enabled and before devices
+ * are resumed. Executed with interrupts disabled.
+ *
+ * @pre_restore: Prepare system for the restoration from a hibernation image.
+ * Called right after devices have been frozen and before the nonboot
+ * CPUs are disabled (runs with IRQs on).
+ *
+ * @restore_cleanup: Clean up after a failing image restoration.
+ * Called right after the nonboot CPUs have been enabled and before
+ * thawing devices (runs with IRQs on).
*/
-struct hibernation_ops {
+struct platform_hibernation_ops {
+ int (*start)(void);
+ int (*pre_snapshot)(void);
+ void (*finish)(void);
int (*prepare)(void);
int (*enter)(void);
- void (*finish)(void);
+ void (*leave)(void);
int (*pre_restore)(void);
void (*restore_cleanup)(void);
};
@@ -70,14 +197,14 @@ extern void swsusp_set_page_free(struct page *);
extern void swsusp_unset_page_free(struct page *);
extern unsigned long get_safe_page(gfp_t gfp_mask);
-extern void hibernation_set_ops(struct hibernation_ops *ops);
+extern void hibernation_set_ops(struct platform_hibernation_ops *ops);
extern int hibernate(void);
#else /* CONFIG_HIBERNATION */
static inline int swsusp_page_is_forbidden(struct page *p) { return 0; }
static inline void swsusp_set_page_free(struct page *p) {}
static inline void swsusp_unset_page_free(struct page *p) {}
-static inline void hibernation_set_ops(struct hibernation_ops *ops) {}
+static inline void hibernation_set_ops(struct platform_hibernation_ops *ops) {}
static inline int hibernate(void) { return -ENOSYS; }
#endif /* CONFIG_HIBERNATION */
@@ -130,4 +257,4 @@ static inline void register_nosave_region_late(unsigned long b, unsigned long e)
}
#endif
-#endif /* _LINUX_SWSUSP_H */
+#endif /* _LINUX_SUSPEND_H */
diff --git a/include/linux/swap.h b/include/linux/swap.h
index edf681a7fd8f..4f3838adbb30 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -158,11 +158,6 @@ struct swap_list_t {
/* Swap 50% full? Release swapcache more aggressively.. */
#define vm_swap_full() (nr_swap_pages*2 < total_swap_pages)
-/* linux/mm/oom_kill.c */
-extern void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order);
-extern int register_oom_notifier(struct notifier_block *nb);
-extern int unregister_oom_notifier(struct notifier_block *nb);
-
/* linux/mm/memory.c */
extern void swapin_readahead(swp_entry_t, unsigned long, struct vm_area_struct *);
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 483050c924c3..e99171f01b4c 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -238,6 +238,7 @@ enum
NET_LLC=18,
NET_NETFILTER=19,
NET_DCCP=20,
+ NET_IRDA=412,
};
/* /proc/sys/kernel/random */
@@ -795,6 +796,25 @@ enum {
NET_BRIDGE_NF_FILTER_PPPOE_TAGGED = 5,
};
+/* proc/sys/net/irda */
+enum {
+ NET_IRDA_DISCOVERY=1,
+ NET_IRDA_DEVNAME=2,
+ NET_IRDA_DEBUG=3,
+ NET_IRDA_FAST_POLL=4,
+ NET_IRDA_DISCOVERY_SLOTS=5,
+ NET_IRDA_DISCOVERY_TIMEOUT=6,
+ NET_IRDA_SLOT_TIMEOUT=7,
+ NET_IRDA_MAX_BAUD_RATE=8,
+ NET_IRDA_MIN_TX_TURN_TIME=9,
+ NET_IRDA_MAX_TX_DATA_SIZE=10,
+ NET_IRDA_MAX_TX_WINDOW=11,
+ NET_IRDA_MAX_NOREPLY_TIME=12,
+ NET_IRDA_WARN_NOREPLY_TIME=13,
+ NET_IRDA_LAP_KEEPALIVE_TIME=14,
+};
+
+
/* CTL_FS names: */
enum
{
@@ -937,41 +957,42 @@ extern int sysctl_perm(struct ctl_table *table, int op);
typedef struct ctl_table ctl_table;
-typedef int ctl_handler (ctl_table *table, int __user *name, int nlen,
+typedef int ctl_handler (struct ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen);
-typedef int proc_handler (ctl_table *ctl, int write, struct file * filp,
+typedef int proc_handler (struct ctl_table *ctl, int write, struct file * filp,
void __user *buffer, size_t *lenp, loff_t *ppos);
-extern int proc_dostring(ctl_table *, int, struct file *,
+extern int proc_dostring(struct ctl_table *, int, struct file *,
void __user *, size_t *, loff_t *);
-extern int proc_dointvec(ctl_table *, int, struct file *,
+extern int proc_dointvec(struct ctl_table *, int, struct file *,
void __user *, size_t *, loff_t *);
-extern int proc_dointvec_bset(ctl_table *, int, struct file *,
+extern int proc_dointvec_bset(struct ctl_table *, int, struct file *,
void __user *, size_t *, loff_t *);
-extern int proc_dointvec_minmax(ctl_table *, int, struct file *,
+extern int proc_dointvec_minmax(struct ctl_table *, int, struct file *,
void __user *, size_t *, loff_t *);
-extern int proc_dointvec_jiffies(ctl_table *, int, struct file *,
+extern int proc_dointvec_jiffies(struct ctl_table *, int, struct file *,
void __user *, size_t *, loff_t *);
-extern int proc_dointvec_userhz_jiffies(ctl_table *, int, struct file *,
+extern int proc_dointvec_userhz_jiffies(struct ctl_table *, int, struct file *,
void __user *, size_t *, loff_t *);
-extern int proc_dointvec_ms_jiffies(ctl_table *, int, struct file *,
+extern int proc_dointvec_ms_jiffies(struct ctl_table *, int, struct file *,
void __user *, size_t *, loff_t *);
-extern int proc_doulongvec_minmax(ctl_table *, int, struct file *,
+extern int proc_doulongvec_minmax(struct ctl_table *, int, struct file *,
void __user *, size_t *, loff_t *);
-extern int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int,
+extern int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int,
struct file *, void __user *, size_t *, loff_t *);
extern int do_sysctl (int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen);
-extern int do_sysctl_strategy (ctl_table *table,
+extern int do_sysctl_strategy (struct ctl_table *table,
int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen);
+extern ctl_handler sysctl_data;
extern ctl_handler sysctl_string;
extern ctl_handler sysctl_intvec;
extern ctl_handler sysctl_jiffies;
@@ -980,7 +1001,7 @@ extern ctl_handler sysctl_ms_jiffies;
/*
* Register a set of sysctl names by calling register_sysctl_table
- * with an initialised array of ctl_table's. An entry with zero
+ * with an initialised array of struct ctl_table's. An entry with zero
* ctl_name and NULL procname terminates the table. table->de will be
* set up by the registration and need not be initialised in advance.
*
@@ -1026,8 +1047,8 @@ struct ctl_table
void *data;
int maxlen;
mode_t mode;
- ctl_table *child;
- ctl_table *parent; /* Automatically set */
+ struct ctl_table *child;
+ struct ctl_table *parent; /* Automatically set */
proc_handler *proc_handler; /* Callback for text formatting */
ctl_handler *strategy; /* Callback function for all r/w */
void *extra1;
@@ -1035,18 +1056,19 @@ struct ctl_table
};
/* struct ctl_table_header is used to maintain dynamic lists of
- ctl_table trees. */
+ struct ctl_table trees. */
struct ctl_table_header
{
- ctl_table *ctl_table;
+ struct ctl_table *ctl_table;
struct list_head ctl_entry;
int used;
struct completion *unregistering;
};
-struct ctl_table_header * register_sysctl_table(ctl_table * table);
+struct ctl_table_header *register_sysctl_table(struct ctl_table * table);
void unregister_sysctl_table(struct ctl_table_header * table);
+int sysctl_check_table(struct ctl_table *table);
#else /* __KERNEL__ */
diff --git a/include/linux/taskstats.h b/include/linux/taskstats.h
index dce1ed204972..5d69c0744fff 100644
--- a/include/linux/taskstats.h
+++ b/include/linux/taskstats.h
@@ -31,7 +31,7 @@
*/
-#define TASKSTATS_VERSION 5
+#define TASKSTATS_VERSION 6
#define TS_COMM_LEN 32 /* should be >= TASK_COMM_LEN
* in linux/sched.h */
@@ -152,6 +152,11 @@ struct taskstats {
__u64 nvcsw; /* voluntary_ctxt_switches */
__u64 nivcsw; /* nonvoluntary_ctxt_switches */
+
+ /* time accounting for SMT machines */
+ __u64 ac_utimescaled; /* utime scaled on frequency etc */
+ __u64 ac_stimescaled; /* stime scaled on frequency etc */
+ __u64 cpu_scaled_run_real_total; /* scaled cpu_run_real_total */
};
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index c5b94c1a5ee2..bac17c59b24e 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -315,7 +315,7 @@ struct tcp_sock {
*/
u32 snd_ssthresh; /* Slow start size threshold */
u32 snd_cwnd; /* Sending congestion window */
- u16 snd_cwnd_cnt; /* Linear increase counter */
+ u32 snd_cwnd_cnt; /* Linear increase counter */
u32 snd_cwnd_clamp; /* Do not allow snd_cwnd to grow above this */
u32 snd_cwnd_used;
u32 snd_cwnd_stamp;
diff --git a/include/linux/tick.h b/include/linux/tick.h
index 9a7252e089b9..f4a1395e05ff 100644
--- a/include/linux/tick.h
+++ b/include/linux/tick.h
@@ -40,6 +40,7 @@ enum tick_nohz_mode {
* @idle_sleeps: Number of idle calls, where the sched tick was stopped
* @idle_entrytime: Time when the idle call was entered
* @idle_sleeptime: Sum of the time slept in idle with sched tick stopped
+ * @sleep_length: Duration of the current idle sleep
*/
struct tick_sched {
struct hrtimer sched_timer;
@@ -52,6 +53,7 @@ struct tick_sched {
unsigned long idle_sleeps;
ktime_t idle_entrytime;
ktime_t idle_sleeptime;
+ ktime_t sleep_length;
unsigned long last_jiffies;
unsigned long next_jiffies;
ktime_t idle_expires;
@@ -100,10 +102,17 @@ static inline int tick_check_oneshot_change(int allow_nohz) { return 0; }
extern void tick_nohz_stop_sched_tick(void);
extern void tick_nohz_restart_sched_tick(void);
extern void tick_nohz_update_jiffies(void);
+extern ktime_t tick_nohz_get_sleep_length(void);
# else
static inline void tick_nohz_stop_sched_tick(void) { }
static inline void tick_nohz_restart_sched_tick(void) { }
static inline void tick_nohz_update_jiffies(void) { }
+static inline ktime_t tick_nohz_get_sleep_length(void)
+{
+ ktime_t len = { .tv64 = NSEC_PER_SEC/HZ };
+
+ return len;
+}
# endif /* !NO_HZ */
#endif
diff --git a/include/linux/time.h b/include/linux/time.h
index 6a5f503b4f1d..b04136d60a2f 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -92,7 +92,7 @@ static inline struct timespec timespec_sub(struct timespec lhs,
extern struct timespec xtime;
extern struct timespec wall_to_monotonic;
-extern seqlock_t xtime_lock __attribute__((weak));
+extern seqlock_t xtime_lock;
extern unsigned long read_persistent_clock(void);
extern int update_persistent_clock(struct timespec now);
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 60478f6e5dc6..c555f5442bd7 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -81,11 +81,6 @@ struct tty_bufhead {
int memory_used; /* Buffer space used excluding free queue */
};
/*
- * The pty uses char_buf and flag_buf as a contiguous buffer
- */
-#define PTY_BUF_SIZE 4*TTY_FLIPBUF_SIZE
-
-/*
* When a break, frame error, or parity error happens, these codes are
* stuffed into the flags buffer.
*/
@@ -321,6 +316,9 @@ extern void tty_flip_buffer_push(struct tty_struct *tty);
extern speed_t tty_get_baud_rate(struct tty_struct *tty);
extern speed_t tty_termios_baud_rate(struct ktermios *termios);
extern speed_t tty_termios_input_baud_rate(struct ktermios *termios);
+extern void tty_termios_encode_baud_rate(struct ktermios *termios, speed_t ibaud, speed_t obaud);
+extern void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud);
+extern void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old);
extern struct tty_ldisc *tty_ldisc_ref(struct tty_struct *);
extern void tty_ldisc_deref(struct tty_ldisc *);
@@ -334,7 +332,9 @@ extern void tty_ldisc_flush(struct tty_struct *tty);
extern int tty_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg);
-
+extern int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg);
+extern int tty_perform_flush(struct tty_struct *tty, unsigned long arg);
extern dev_t tty_devnum(struct tty_struct *tty);
extern void proc_clear_tty(struct task_struct *p);
extern struct tty_struct *get_current_tty(void);
diff --git a/include/linux/types.h b/include/linux/types.h
index 0351bf2fac85..f4f8d19158e4 100644
--- a/include/linux/types.h
+++ b/include/linux/types.h
@@ -3,12 +3,9 @@
#ifdef __KERNEL__
-#define BITS_TO_LONGS(bits) \
- (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG)
#define DECLARE_BITMAP(name,bits) \
unsigned long name[BITS_TO_LONGS(bits)]
-#define BITS_PER_BYTE 8
#endif
#include <linux/posix_types.h>
@@ -40,6 +37,8 @@ typedef __kernel_gid32_t gid_t;
typedef __kernel_uid16_t uid16_t;
typedef __kernel_gid16_t gid16_t;
+typedef unsigned long uintptr_t;
+
#ifdef CONFIG_UID16
/* This is defined by include/asm-{arch}/posix_types.h */
typedef __kernel_old_uid_t old_uid_t;
diff --git a/include/linux/ufs_fs.h b/include/linux/ufs_fs.h
index daeba22b7656..10b854d3561f 100644
--- a/include/linux/ufs_fs.h
+++ b/include/linux/ufs_fs.h
@@ -46,11 +46,6 @@ typedef __u32 __bitwise __fs32;
typedef __u16 __bitwise __fs16;
#endif
-#ifdef __KERNEL__
-#include <linux/ufs_fs_i.h>
-#include <linux/ufs_fs_sb.h>
-#endif
-
#define UFS_BBLOCK 0
#define UFS_BBSIZE 8192
#define UFS_SBLOCK 8192
@@ -170,8 +165,9 @@ typedef __u16 __bitwise __fs16;
#define UFS_ST_MASK 0x00000700 /* mask for the following */
#define UFS_ST_OLD 0x00000000
#define UFS_ST_44BSD 0x00000100
-#define UFS_ST_SUN 0x00000200
-#define UFS_ST_SUNx86 0x00000400
+#define UFS_ST_SUN 0x00000200 /* Solaris */
+#define UFS_ST_SUNOS 0x00000300
+#define UFS_ST_SUNx86 0x00000400 /* Solaris x86 */
/*cylinder group encoding */
#define UFS_CG_MASK 0x00003000 /* mask for the following */
#define UFS_CG_OLD 0x00000000
@@ -187,28 +183,6 @@ typedef __u16 __bitwise __fs16;
#define UFS_42INODEFMT -1
#define UFS_44INODEFMT 2
-/* mount options */
-#define UFS_MOUNT_ONERROR 0x0000000F
-#define UFS_MOUNT_ONERROR_PANIC 0x00000001
-#define UFS_MOUNT_ONERROR_LOCK 0x00000002
-#define UFS_MOUNT_ONERROR_UMOUNT 0x00000004
-#define UFS_MOUNT_ONERROR_REPAIR 0x00000008
-
-#define UFS_MOUNT_UFSTYPE 0x0000FFF0
-#define UFS_MOUNT_UFSTYPE_OLD 0x00000010
-#define UFS_MOUNT_UFSTYPE_44BSD 0x00000020
-#define UFS_MOUNT_UFSTYPE_SUN 0x00000040
-#define UFS_MOUNT_UFSTYPE_NEXTSTEP 0x00000080
-#define UFS_MOUNT_UFSTYPE_NEXTSTEP_CD 0x00000100
-#define UFS_MOUNT_UFSTYPE_OPENSTEP 0x00000200
-#define UFS_MOUNT_UFSTYPE_SUNx86 0x00000400
-#define UFS_MOUNT_UFSTYPE_HP 0x00000800
-#define UFS_MOUNT_UFSTYPE_UFS2 0x00001000
-
-#define ufs_clear_opt(o,opt) o &= ~UFS_MOUNT_##opt
-#define ufs_set_opt(o,opt) o |= UFS_MOUNT_##opt
-#define ufs_test_opt(o,opt) ((o) & UFS_MOUNT_##opt)
-
/*
* MINFREE gives the minimum acceptable percentage of file system
* blocks which may be free. If the freelist drops below this level
@@ -223,19 +197,6 @@ typedef __u16 __bitwise __fs16;
*/
#define UFS_MINFREE 5
#define UFS_DEFAULTOPT UFS_OPTTIME
-
-/*
- * Debug code
- */
-#ifdef CONFIG_UFS_DEBUG
-# define UFSD(f, a...) { \
- printk ("UFSD (%s, %d): %s:", \
- __FILE__, __LINE__, __FUNCTION__); \
- printk (f, ## a); \
- }
-#else
-# define UFSD(f, a...) /**/
-#endif
/*
* Turn file system block numbers into disk block addresses.
@@ -374,7 +335,14 @@ struct ufs_csum_core {
* struct ufs_super_block_(first,second,third) instead.
*/
struct ufs_super_block {
- __fs32 fs_link; /* UNUSED */
+ union {
+ struct {
+ __fs32 fs_link; /* UNUSED */
+ } fs_42;
+ struct {
+ __fs32 fs_state; /* file system state flag */
+ } fs_sun;
+ } fs_u0;
__fs32 fs_rlink; /* UNUSED */
__fs32 fs_sblkno; /* addr of super-block in filesys */
__fs32 fs_cblkno; /* offset of cyl-block in filesys */
@@ -545,6 +513,15 @@ struct ufs_super_block {
#define CG_MAGIC 0x090255
#define ufs_cg_chkmagic(sb, ucg) \
(fs32_to_cpu((sb), (ucg)->cg_magic) == CG_MAGIC)
+/*
+ * Macros for access to old cylinder group array structures
+ */
+#define ufs_ocg_blktot(sb, ucg) fs32_to_cpu((sb), ((struct ufs_old_cylinder_group *)(ucg))->cg_btot)
+#define ufs_ocg_blks(sb, ucg, cylno) fs32_to_cpu((sb), ((struct ufs_old_cylinder_group *)(ucg))->cg_b[cylno])
+#define ufs_ocg_inosused(sb, ucg) fs32_to_cpu((sb), ((struct ufs_old_cylinder_group *)(ucg))->cg_iused)
+#define ufs_ocg_blksfree(sb, ucg) fs32_to_cpu((sb), ((struct ufs_old_cylinder_group *)(ucg))->cg_free)
+#define ufs_ocg_chkmagic(sb, ucg) \
+ (fs32_to_cpu((sb), ((struct ufs_old_cylinder_group *)(ucg))->cg_magic) == CG_MAGIC)
/*
* size of this structure is 172 B
@@ -590,6 +567,28 @@ struct ufs_cylinder_group {
/* actually longer */
};
+/* Historic Cylinder group info */
+struct ufs_old_cylinder_group {
+ __fs32 cg_link; /* linked list of cyl groups */
+ __fs32 cg_rlink; /* for incore cyl groups */
+ __fs32 cg_time; /* time last written */
+ __fs32 cg_cgx; /* we are the cgx'th cylinder group */
+ __fs16 cg_ncyl; /* number of cyl's this cg */
+ __fs16 cg_niblk; /* number of inode blocks this cg */
+ __fs32 cg_ndblk; /* number of data blocks this cg */
+ struct ufs_csum cg_cs; /* cylinder summary information */
+ __fs32 cg_rotor; /* position of last used block */
+ __fs32 cg_frotor; /* position of last used frag */
+ __fs32 cg_irotor; /* position of last used inode */
+ __fs32 cg_frsum[8]; /* counts of available frags */
+ __fs32 cg_btot[32]; /* block totals per cylinder */
+ __fs16 cg_b[32][8]; /* positions of free blocks */
+ __u8 cg_iused[256]; /* used inode map */
+ __fs32 cg_magic; /* magic number */
+ __u8 cg_free[1]; /* free block map */
+/* actually longer */
+};
+
/*
* structure of an on-disk inode
*/
@@ -796,7 +795,14 @@ struct ufs_sb_private_info {
* ufs_super_block_third 356
*/
struct ufs_super_block_first {
- __fs32 fs_link;
+ union {
+ struct {
+ __fs32 fs_link; /* UNUSED */
+ } fs_42;
+ struct {
+ __fs32 fs_state; /* file system state flag */
+ } fs_sun;
+ } fs_u0;
__fs32 fs_rlink;
__fs32 fs_sblkno;
__fs32 fs_cblkno;
@@ -944,89 +950,4 @@ struct ufs_super_block_third {
__u8 fs_space[1];
};
-#ifdef __KERNEL__
-
-/* balloc.c */
-extern void ufs_free_fragments (struct inode *, u64, unsigned);
-extern void ufs_free_blocks (struct inode *, u64, unsigned);
-extern u64 ufs_new_fragments(struct inode *, void *, u64, u64,
- unsigned, int *, struct page *);
-
-/* cylinder.c */
-extern struct ufs_cg_private_info * ufs_load_cylinder (struct super_block *, unsigned);
-extern void ufs_put_cylinder (struct super_block *, unsigned);
-
-/* dir.c */
-extern const struct inode_operations ufs_dir_inode_operations;
-extern int ufs_add_link (struct dentry *, struct inode *);
-extern ino_t ufs_inode_by_name(struct inode *, struct dentry *);
-extern int ufs_make_empty(struct inode *, struct inode *);
-extern struct ufs_dir_entry *ufs_find_entry(struct inode *, struct dentry *, struct page **);
-extern int ufs_delete_entry(struct inode *, struct ufs_dir_entry *, struct page *);
-extern int ufs_empty_dir (struct inode *);
-extern struct ufs_dir_entry *ufs_dotdot(struct inode *, struct page **);
-extern void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de,
- struct page *page, struct inode *inode);
-
-/* file.c */
-extern const struct inode_operations ufs_file_inode_operations;
-extern const struct file_operations ufs_file_operations;
-
-extern const struct address_space_operations ufs_aops;
-
-/* ialloc.c */
-extern void ufs_free_inode (struct inode *inode);
-extern struct inode * ufs_new_inode (struct inode *, int);
-
-/* inode.c */
-extern void ufs_read_inode (struct inode *);
-extern void ufs_put_inode (struct inode *);
-extern int ufs_write_inode (struct inode *, int);
-extern int ufs_sync_inode (struct inode *);
-extern void ufs_delete_inode (struct inode *);
-extern struct buffer_head * ufs_bread (struct inode *, unsigned, int, int *);
-extern int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create);
-
-/* namei.c */
-extern const struct file_operations ufs_dir_operations;
-
-/* super.c */
-extern void ufs_warning (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
-extern void ufs_error (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
-extern void ufs_panic (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
-
-/* symlink.c */
-extern const struct inode_operations ufs_fast_symlink_inode_operations;
-
-/* truncate.c */
-extern int ufs_truncate (struct inode *, loff_t);
-
-static inline struct ufs_sb_info *UFS_SB(struct super_block *sb)
-{
- return sb->s_fs_info;
-}
-
-static inline struct ufs_inode_info *UFS_I(struct inode *inode)
-{
- return container_of(inode, struct ufs_inode_info, vfs_inode);
-}
-
-/*
- * Give cylinder group number for a file system block.
- * Give cylinder group block number for a file system block.
- */
-/* #define ufs_dtog(d) ((d) / uspi->s_fpg) */
-static inline u64 ufs_dtog(struct ufs_sb_private_info * uspi, u64 b)
-{
- do_div(b, uspi->s_fpg);
- return b;
-}
-/* #define ufs_dtogd(d) ((d) % uspi->s_fpg) */
-static inline u32 ufs_dtogd(struct ufs_sb_private_info * uspi, u64 b)
-{
- return do_div(b, uspi->s_fpg);
-}
-
-#endif /* __KERNEL__ */
-
#endif /* __LINUX_UFS_FS_H */
diff --git a/include/linux/ufs_fs_i.h b/include/linux/ufs_fs_i.h
deleted file mode 100644
index 6496caa82f9e..000000000000
--- a/include/linux/ufs_fs_i.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * linux/include/linux/ufs_fs_i.h
- *
- * Copyright (C) 1996
- * Adrian Rodriguez (adrian@franklins-tower.rutgers.edu)
- * Laboratory for Computer Science Research Computing Facility
- * Rutgers, The State University of New Jersey
- *
- * NeXTstep support added on February 5th 1998 by
- * Niels Kristian Bech Jensen <nkbj@image.dk>.
- */
-
-#ifndef _LINUX_UFS_FS_I_H
-#define _LINUX_UFS_FS_I_H
-
-struct ufs_inode_info {
- union {
- __fs32 i_data[15];
- __u8 i_symlink[4*15];
- __fs64 u2_i_data[15];
- } i_u1;
- __u32 i_flags;
- __u32 i_shadow;
- __u32 i_unused1;
- __u32 i_unused2;
- __u32 i_oeftflag;
- __u16 i_osync;
- __u64 i_lastfrag;
- __u32 i_dir_start_lookup;
- struct inode vfs_inode;
-};
-
-#endif /* _LINUX_UFS_FS_I_H */
diff --git a/include/linux/ufs_fs_sb.h b/include/linux/ufs_fs_sb.h
deleted file mode 100644
index e114c93fc578..000000000000
--- a/include/linux/ufs_fs_sb.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * linux/include/linux/ufs_fs_sb.h
- *
- * Copyright (C) 1996
- * Adrian Rodriguez (adrian@franklins-tower.rutgers.edu)
- * Laboratory for Computer Science Research Computing Facility
- * Rutgers, The State University of New Jersey
- *
- * $Id: ufs_fs_sb.h,v 1.8 1998/05/06 12:04:40 jj Exp $
- *
- * Write support by Daniel Pirkl <daniel.pirkl@email.cz>
- */
-
-#ifndef __LINUX_UFS_FS_SB_H
-#define __LINUX_UFS_FS_SB_H
-
-
-#define UFS_MAX_GROUP_LOADED 8
-#define UFS_CGNO_EMPTY ((unsigned)-1)
-
-struct ufs_sb_private_info;
-struct ufs_cg_private_info;
-struct ufs_csum;
-
-struct ufs_sb_info {
- struct ufs_sb_private_info * s_uspi;
- struct ufs_csum * s_csp;
- unsigned s_bytesex;
- unsigned s_flags;
- struct buffer_head ** s_ucg;
- struct ufs_cg_private_info * s_ucpi[UFS_MAX_GROUP_LOADED];
- unsigned s_cgno[UFS_MAX_GROUP_LOADED];
- unsigned short s_cg_loaded;
- unsigned s_mount_opt;
-};
-
-#endif
diff --git a/include/linux/uinput.h b/include/linux/uinput.h
index a6c1e8eed226..15ddd4483b09 100644
--- a/include/linux/uinput.h
+++ b/include/linux/uinput.h
@@ -162,10 +162,6 @@ struct uinput_ff_erase {
#define UI_FF_UPLOAD 1
#define UI_FF_ERASE 2
-#ifndef NBITS
-#define NBITS(x) ((((x)-1)/(sizeof(long)*8))+1)
-#endif /* NBITS */
-
#define UINPUT_MAX_NAME_SIZE 80
struct uinput_user_dev {
char name[UINPUT_MAX_NAME_SIZE];
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 46705e91573d..c1527c2ef3cb 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -481,7 +481,7 @@ static inline void *get_gadget_data (struct usb_gadget *gadget)
/**
* gadget_is_dualspeed - return true iff the hardware handles high speed
- * @gadget: controller that might support both high and full speeds
+ * @g: controller that might support both high and full speeds
*/
static inline int gadget_is_dualspeed(struct usb_gadget *g)
{
@@ -497,7 +497,7 @@ static inline int gadget_is_dualspeed(struct usb_gadget *g)
/**
* gadget_is_otg - return true iff the hardware is OTG-ready
- * @gadget: controller that might have a Mini-AB connector
+ * @g: controller that might have a Mini-AB connector
*
* This is a runtime test, since kernels with a USB-OTG stack sometimes
* run on boards which only have a Mini-B (or Mini-A) connector.
diff --git a/include/linux/videodev.h b/include/linux/videodev.h
index 8dba97a291f6..52e3d5fd5be4 100644
--- a/include/linux/videodev.h
+++ b/include/linux/videodev.h
@@ -294,48 +294,6 @@ struct video_code
#define VID_PLAY_RESET 13
#define VID_PLAY_END_MARK 14
-
-
-#define VID_HARDWARE_BT848 1
-#define VID_HARDWARE_QCAM_BW 2
-#define VID_HARDWARE_PMS 3
-#define VID_HARDWARE_QCAM_C 4
-#define VID_HARDWARE_PSEUDO 5
-#define VID_HARDWARE_SAA5249 6
-#define VID_HARDWARE_AZTECH 7
-#define VID_HARDWARE_SF16MI 8
-#define VID_HARDWARE_RTRACK 9
-#define VID_HARDWARE_ZOLTRIX 10
-#define VID_HARDWARE_SAA7146 11
-#define VID_HARDWARE_VIDEUM 12 /* Reserved for Winnov videum */
-#define VID_HARDWARE_RTRACK2 13
-#define VID_HARDWARE_PERMEDIA2 14 /* Reserved for Permedia2 */
-#define VID_HARDWARE_RIVA128 15 /* Reserved for RIVA 128 */
-#define VID_HARDWARE_PLANB 16 /* PowerMac motherboard video-in */
-#define VID_HARDWARE_BROADWAY 17 /* Broadway project */
-#define VID_HARDWARE_GEMTEK 18
-#define VID_HARDWARE_TYPHOON 19
-#define VID_HARDWARE_VINO 20 /* SGI Indy Vino */
-#define VID_HARDWARE_CADET 21 /* Cadet radio */
-#define VID_HARDWARE_TRUST 22 /* Trust FM Radio */
-#define VID_HARDWARE_TERRATEC 23 /* TerraTec ActiveRadio */
-#define VID_HARDWARE_CPIA 24
-#define VID_HARDWARE_ZR36120 25 /* Zoran ZR36120/ZR36125 */
-#define VID_HARDWARE_ZR36067 26 /* Zoran ZR36067/36060 */
-#define VID_HARDWARE_OV511 27
-#define VID_HARDWARE_ZR356700 28 /* Zoran 36700 series */
-#define VID_HARDWARE_W9966 29
-#define VID_HARDWARE_SE401 30 /* SE401 USB webcams */
-#define VID_HARDWARE_PWC 31 /* Philips webcams */
-#define VID_HARDWARE_MEYE 32 /* Sony Vaio MotionEye cameras */
-#define VID_HARDWARE_CPIA2 33
-#define VID_HARDWARE_VICAM 34
-#define VID_HARDWARE_SF16FMR2 35
-#define VID_HARDWARE_W9968CF 36
-#define VID_HARDWARE_SAA7114H 37
-#define VID_HARDWARE_SN9C102 38
-#define VID_HARDWARE_ARV 39
-
#endif /* CONFIG_VIDEO_V4L1_COMPAT */
#endif /* __LINUX_VIDEODEV_H */
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 1f503e94eff1..439474f24e34 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -441,94 +441,6 @@ struct v4l2_timecode
#define V4L2_TC_USERBITS_8BITCHARS 0x0008
/* The above is based on SMPTE timecodes */
-#ifdef __KERNEL__
-/*
- * M P E G C O M P R E S S I O N P A R A M E T E R S
- *
- * ### WARNING: This experimental MPEG compression API is obsolete.
- * ### It is replaced by the MPEG controls API.
- * ### This old API will disappear in the near future!
- *
- */
-enum v4l2_bitrate_mode {
- V4L2_BITRATE_NONE = 0, /* not specified */
- V4L2_BITRATE_CBR, /* constant bitrate */
- V4L2_BITRATE_VBR, /* variable bitrate */
-};
-struct v4l2_bitrate {
- /* rates are specified in kbit/sec */
- enum v4l2_bitrate_mode mode;
- __u32 min;
- __u32 target; /* use this one for CBR */
- __u32 max;
-};
-
-enum v4l2_mpeg_streamtype {
- V4L2_MPEG_SS_1, /* MPEG-1 system stream */
- V4L2_MPEG_PS_2, /* MPEG-2 program stream */
- V4L2_MPEG_TS_2, /* MPEG-2 transport stream */
- V4L2_MPEG_PS_DVD, /* MPEG-2 program stream with DVD header fixups */
-};
-enum v4l2_mpeg_audiotype {
- V4L2_MPEG_AU_2_I, /* MPEG-2 layer 1 */
- V4L2_MPEG_AU_2_II, /* MPEG-2 layer 2 */
- V4L2_MPEG_AU_2_III, /* MPEG-2 layer 3 */
- V4L2_MPEG_AC3, /* AC3 */
- V4L2_MPEG_LPCM, /* LPCM */
-};
-enum v4l2_mpeg_videotype {
- V4L2_MPEG_VI_1, /* MPEG-1 */
- V4L2_MPEG_VI_2, /* MPEG-2 */
-};
-enum v4l2_mpeg_aspectratio {
- V4L2_MPEG_ASPECT_SQUARE = 1, /* square pixel */
- V4L2_MPEG_ASPECT_4_3 = 2, /* 4 : 3 */
- V4L2_MPEG_ASPECT_16_9 = 3, /* 16 : 9 */
- V4L2_MPEG_ASPECT_1_221 = 4, /* 1 : 2,21 */
-};
-
-struct v4l2_mpeg_compression {
- /* general */
- enum v4l2_mpeg_streamtype st_type;
- struct v4l2_bitrate st_bitrate;
-
- /* transport streams */
- __u16 ts_pid_pmt;
- __u16 ts_pid_audio;
- __u16 ts_pid_video;
- __u16 ts_pid_pcr;
-
- /* program stream */
- __u16 ps_size;
- __u16 reserved_1; /* align */
-
- /* audio */
- enum v4l2_mpeg_audiotype au_type;
- struct v4l2_bitrate au_bitrate;
- __u32 au_sample_rate;
- __u8 au_pesid;
- __u8 reserved_2[3]; /* align */
-
- /* video */
- enum v4l2_mpeg_videotype vi_type;
- enum v4l2_mpeg_aspectratio vi_aspect_ratio;
- struct v4l2_bitrate vi_bitrate;
- __u32 vi_frame_rate;
- __u16 vi_frames_per_gop;
- __u16 vi_bframes_count;
- __u8 vi_pesid;
- __u8 reserved_3[3]; /* align */
-
- /* misc flags */
- __u32 closed_gops:1;
- __u32 pulldown:1;
- __u32 reserved_4:30; /* align */
-
- /* I don't expect the above being perfect yet ;) */
- __u32 reserved_5[8];
-};
-#endif
-
struct v4l2_jpegcompression
{
int quality;
@@ -1420,10 +1332,6 @@ struct v4l2_chip_ident {
#define VIDIOC_ENUM_FMT _IOWR ('V', 2, struct v4l2_fmtdesc)
#define VIDIOC_G_FMT _IOWR ('V', 4, struct v4l2_format)
#define VIDIOC_S_FMT _IOWR ('V', 5, struct v4l2_format)
-#ifdef __KERNEL__
-#define VIDIOC_G_MPEGCOMP _IOR ('V', 6, struct v4l2_mpeg_compression)
-#define VIDIOC_S_MPEGCOMP _IOW ('V', 7, struct v4l2_mpeg_compression)
-#endif
#define VIDIOC_REQBUFS _IOWR ('V', 8, struct v4l2_requestbuffers)
#define VIDIOC_QUERYBUF _IOWR ('V', 9, struct v4l2_buffer)
#define VIDIOC_G_FBUF _IOR ('V', 10, struct v4l2_framebuffer)
diff --git a/include/linux/virtio.h b/include/linux/virtio.h
new file mode 100644
index 000000000000..14e1379876d3
--- /dev/null
+++ b/include/linux/virtio.h
@@ -0,0 +1,110 @@
+#ifndef _LINUX_VIRTIO_H
+#define _LINUX_VIRTIO_H
+/* Everything a virtio driver needs to work with any particular virtio
+ * implementation. */
+#include <linux/types.h>
+#include <linux/scatterlist.h>
+#include <linux/spinlock.h>
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
+
+/**
+ * virtqueue - a queue to register buffers for sending or receiving.
+ * @callback: the function to call when buffers are consumed (can be NULL).
+ * If this returns false, callbacks are suppressed until vq_ops->restart
+ * is called.
+ * @vdev: the virtio device this queue was created for.
+ * @vq_ops: the operations for this virtqueue (see below).
+ * @priv: a pointer for the virtqueue implementation to use.
+ */
+struct virtqueue
+{
+ bool (*callback)(struct virtqueue *vq);
+ struct virtio_device *vdev;
+ struct virtqueue_ops *vq_ops;
+ void *priv;
+};
+
+/**
+ * virtqueue_ops - operations for virtqueue abstraction layer
+ * @add_buf: expose buffer to other end
+ * vq: the struct virtqueue we're talking about.
+ * sg: the description of the buffer(s).
+ * out_num: the number of sg readable by other side
+ * in_num: the number of sg which are writable (after readable ones)
+ * data: the token identifying the buffer.
+ * Returns 0 or an error.
+ * @kick: update after add_buf
+ * vq: the struct virtqueue
+ * After one or more add_buf calls, invoke this to kick the other side.
+ * @get_buf: get the next used buffer
+ * vq: the struct virtqueue we're talking about.
+ * len: the length written into the buffer
+ * Returns NULL or the "data" token handed to add_buf.
+ * @restart: restart callbacks after callback returned false.
+ * vq: the struct virtqueue we're talking about.
+ * This returns "false" (and doesn't re-enable) if there are pending
+ * buffers in the queue, to avoid a race.
+ * @shutdown: "unadd" all buffers.
+ * vq: the struct virtqueue we're talking about.
+ * Remove everything from the queue.
+ *
+ * Locking rules are straightforward: the driver is responsible for
+ * locking. No two operations may be invoked simultaneously.
+ *
+ * All operations can be called in any context.
+ */
+struct virtqueue_ops {
+ int (*add_buf)(struct virtqueue *vq,
+ struct scatterlist sg[],
+ unsigned int out_num,
+ unsigned int in_num,
+ void *data);
+
+ void (*kick)(struct virtqueue *vq);
+
+ void *(*get_buf)(struct virtqueue *vq, unsigned int *len);
+
+ bool (*restart)(struct virtqueue *vq);
+
+ void (*shutdown)(struct virtqueue *vq);
+};
+
+/**
+ * virtio_device - representation of a device using virtio
+ * @index: unique position on the virtio bus
+ * @dev: underlying device.
+ * @id: the device type identification (used to match it with a driver).
+ * @config: the configuration ops for this device.
+ * @priv: private pointer for the driver's use.
+ */
+struct virtio_device
+{
+ int index;
+ struct device dev;
+ struct virtio_device_id id;
+ struct virtio_config_ops *config;
+ void *priv;
+};
+
+int register_virtio_device(struct virtio_device *dev);
+void unregister_virtio_device(struct virtio_device *dev);
+
+/**
+ * virtio_driver - operations for a virtio I/O driver
+ * @driver: underlying device driver (populate name and owner).
+ * @id_table: the ids serviced by this driver.
+ * @probe: the function to call when a device is found. Returns a token for
+ * remove, or PTR_ERR().
+ * @remove: the function when a device is removed.
+ */
+struct virtio_driver {
+ struct device_driver driver;
+ const struct virtio_device_id *id_table;
+ int (*probe)(struct virtio_device *dev);
+ void (*remove)(struct virtio_device *dev);
+};
+
+int register_virtio_driver(struct virtio_driver *drv);
+void unregister_virtio_driver(struct virtio_driver *drv);
+#endif /* _LINUX_VIRTIO_H */
diff --git a/include/linux/virtio_9p.h b/include/linux/virtio_9p.h
new file mode 100644
index 000000000000..8eff0b53910b
--- /dev/null
+++ b/include/linux/virtio_9p.h
@@ -0,0 +1,10 @@
+#ifndef _LINUX_VIRTIO_9P_H
+#define _LINUX_VIRTIO_9P_H
+#include <linux/virtio_config.h>
+
+/* The ID for virtio console */
+#define VIRTIO_ID_9P 9
+/* Maximum number of virtio channels per partition (1 for now) */
+#define MAX_9P_CHAN 1
+
+#endif /* _LINUX_VIRTIO_9P_H */
diff --git a/include/linux/virtio_blk.h b/include/linux/virtio_blk.h
new file mode 100644
index 000000000000..7bd2bce0cfd9
--- /dev/null
+++ b/include/linux/virtio_blk.h
@@ -0,0 +1,51 @@
+#ifndef _LINUX_VIRTIO_BLK_H
+#define _LINUX_VIRTIO_BLK_H
+#include <linux/virtio_config.h>
+
+/* The ID for virtio_block */
+#define VIRTIO_ID_BLOCK 2
+
+/* Feature bits */
+#define VIRTIO_CONFIG_BLK_F 0x40
+#define VIRTIO_BLK_F_BARRIER 1 /* Does host support barriers? */
+
+/* The capacity (in 512-byte sectors). */
+#define VIRTIO_CONFIG_BLK_F_CAPACITY 0x41
+/* The maximum segment size. */
+#define VIRTIO_CONFIG_BLK_F_SIZE_MAX 0x42
+/* The maximum number of segments. */
+#define VIRTIO_CONFIG_BLK_F_SEG_MAX 0x43
+
+/* These two define direction. */
+#define VIRTIO_BLK_T_IN 0
+#define VIRTIO_BLK_T_OUT 1
+
+/* This bit says it's a scsi command, not an actual read or write. */
+#define VIRTIO_BLK_T_SCSI_CMD 2
+
+/* Barrier before this op. */
+#define VIRTIO_BLK_T_BARRIER 0x80000000
+
+/* This is the first element of the read scatter-gather list. */
+struct virtio_blk_outhdr
+{
+ /* VIRTIO_BLK_T* */
+ __u32 type;
+ /* io priority. */
+ __u32 ioprio;
+ /* Sector (ie. 512 byte offset) */
+ __u64 sector;
+ /* Where to put reply. */
+ __u64 id;
+};
+
+#define VIRTIO_BLK_S_OK 0
+#define VIRTIO_BLK_S_IOERR 1
+#define VIRTIO_BLK_S_UNSUPP 2
+
+/* This is the first element of the write scatter-gather list */
+struct virtio_blk_inhdr
+{
+ unsigned char status;
+};
+#endif /* _LINUX_VIRTIO_BLK_H */
diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
new file mode 100644
index 000000000000..bcc01888df78
--- /dev/null
+++ b/include/linux/virtio_config.h
@@ -0,0 +1,111 @@
+#ifndef _LINUX_VIRTIO_CONFIG_H
+#define _LINUX_VIRTIO_CONFIG_H
+/* Virtio devices use a standardized configuration space to define their
+ * features and pass configuration information, but each implementation can
+ * store and access that space differently. */
+#include <linux/types.h>
+
+/* Status byte for guest to report progress, and synchronize config. */
+/* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */
+#define VIRTIO_CONFIG_S_ACKNOWLEDGE 1
+/* We have found a driver for the device. */
+#define VIRTIO_CONFIG_S_DRIVER 2
+/* Driver has used its parts of the config, and is happy */
+#define VIRTIO_CONFIG_S_DRIVER_OK 4
+/* We've given up on this device. */
+#define VIRTIO_CONFIG_S_FAILED 0x80
+
+/* Feature byte (actually 7 bits availabe): */
+/* Requirements/features of the virtio implementation. */
+#define VIRTIO_CONFIG_F_VIRTIO 1
+/* Requirements/features of the virtqueue (may have more than one). */
+#define VIRTIO_CONFIG_F_VIRTQUEUE 2
+
+#ifdef __KERNEL__
+struct virtio_device;
+
+/**
+ * virtio_config_ops - operations for configuring a virtio device
+ * @find: search for the next configuration field of the given type.
+ * vdev: the virtio_device
+ * type: the feature type
+ * len: the (returned) length of the field if found.
+ * Returns a token if found, or NULL. Never returnes the same field twice
+ * (ie. it's used up).
+ * @get: read the value of a configuration field after find().
+ * vdev: the virtio_device
+ * token: the token returned from find().
+ * buf: the buffer to write the field value into.
+ * len: the length of the buffer (given by find()).
+ * Note that contents are conventionally little-endian.
+ * @set: write the value of a configuration field after find().
+ * vdev: the virtio_device
+ * token: the token returned from find().
+ * buf: the buffer to read the field value from.
+ * len: the length of the buffer (given by find()).
+ * Note that contents are conventionally little-endian.
+ * @get_status: read the status byte
+ * vdev: the virtio_device
+ * Returns the status byte
+ * @set_status: write the status byte
+ * vdev: the virtio_device
+ * status: the new status byte
+ * @find_vq: find the first VIRTIO_CONFIG_F_VIRTQUEUE and create a virtqueue.
+ * vdev: the virtio_device
+ * callback: the virqtueue callback
+ * Returns the new virtqueue or ERR_PTR().
+ * @del_vq: free a virtqueue found by find_vq().
+ */
+struct virtio_config_ops
+{
+ void *(*find)(struct virtio_device *vdev, u8 type, unsigned *len);
+ void (*get)(struct virtio_device *vdev, void *token,
+ void *buf, unsigned len);
+ void (*set)(struct virtio_device *vdev, void *token,
+ const void *buf, unsigned len);
+ u8 (*get_status)(struct virtio_device *vdev);
+ void (*set_status)(struct virtio_device *vdev, u8 status);
+ struct virtqueue *(*find_vq)(struct virtio_device *vdev,
+ bool (*callback)(struct virtqueue *));
+ void (*del_vq)(struct virtqueue *vq);
+};
+
+/**
+ * virtio_config_val - get a single virtio config and mark it used.
+ * @config: the virtio config space
+ * @type: the type to search for.
+ * @val: a pointer to the value to fill in.
+ *
+ * Once used, the config type is marked with VIRTIO_CONFIG_F_USED so it can't
+ * be found again. This version does endian conversion. */
+#define virtio_config_val(vdev, type, v) ({ \
+ int _err = __virtio_config_val((vdev),(type),(v),sizeof(*(v))); \
+ \
+ BUILD_BUG_ON(sizeof(*(v)) != 1 && sizeof(*(v)) != 2 \
+ && sizeof(*(v)) != 4 && sizeof(*(v)) != 8); \
+ if (!_err) { \
+ switch (sizeof(*(v))) { \
+ case 2: le16_to_cpus((__u16 *) v); break; \
+ case 4: le32_to_cpus((__u32 *) v); break; \
+ case 8: le64_to_cpus((__u64 *) v); break; \
+ } \
+ } \
+ _err; \
+})
+
+int __virtio_config_val(struct virtio_device *dev,
+ u8 type, void *val, size_t size);
+
+/**
+ * virtio_use_bit - helper to use a feature bit in a bitfield value.
+ * @dev: the virtio device
+ * @token: the token as returned from vdev->config->find().
+ * @len: the length of the field.
+ * @bitnum: the bit to test.
+ *
+ * If handed a NULL token, it returns false, otherwise returns bit status.
+ * If it's one, it sets the mirroring acknowledgement bit. */
+int virtio_use_bit(struct virtio_device *vdev,
+ void *token, unsigned int len, unsigned int bitnum);
+#endif /* __KERNEL__ */
+#endif /* _LINUX_VIRTIO_CONFIG_H */
diff --git a/include/linux/virtio_console.h b/include/linux/virtio_console.h
new file mode 100644
index 000000000000..ed2d4ead7eb7
--- /dev/null
+++ b/include/linux/virtio_console.h
@@ -0,0 +1,12 @@
+#ifndef _LINUX_VIRTIO_CONSOLE_H
+#define _LINUX_VIRTIO_CONSOLE_H
+#include <linux/virtio_config.h>
+
+/* The ID for virtio console */
+#define VIRTIO_ID_CONSOLE 3
+
+#ifdef __KERNEL__
+int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int));
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_VIRTIO_CONSOLE_H */
diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h
new file mode 100644
index 000000000000..ae469ae55d36
--- /dev/null
+++ b/include/linux/virtio_net.h
@@ -0,0 +1,36 @@
+#ifndef _LINUX_VIRTIO_NET_H
+#define _LINUX_VIRTIO_NET_H
+#include <linux/virtio_config.h>
+
+/* The ID for virtio_net */
+#define VIRTIO_ID_NET 1
+
+/* The bitmap of config for virtio net */
+#define VIRTIO_CONFIG_NET_F 0x40
+#define VIRTIO_NET_F_NO_CSUM 0
+#define VIRTIO_NET_F_TSO4 1
+#define VIRTIO_NET_F_UFO 2
+#define VIRTIO_NET_F_TSO4_ECN 3
+#define VIRTIO_NET_F_TSO6 4
+
+/* The config defining mac address. */
+#define VIRTIO_CONFIG_NET_MAC_F 0x41
+
+/* This is the first element of the scatter-gather list. If you don't
+ * specify GSO or CSUM features, you can simply ignore the header. */
+struct virtio_net_hdr
+{
+#define VIRTIO_NET_HDR_F_NEEDS_CSUM 1 // Use csum_start, csum_offset
+ __u8 flags;
+#define VIRTIO_NET_HDR_GSO_NONE 0 // Not a GSO frame
+#define VIRTIO_NET_HDR_GSO_TCPV4 1 // GSO frame, IPv4 TCP (TSO)
+/* FIXME: Do we need this? If they said they can handle ECN, do they care? */
+#define VIRTIO_NET_HDR_GSO_TCPV4_ECN 2 // GSO frame, IPv4 TCP w/ ECN
+#define VIRTIO_NET_HDR_GSO_UDP 3 // GSO frame, IPv4 UDP (UFO)
+#define VIRTIO_NET_HDR_GSO_TCPV6 4 // GSO frame, IPv6 TCP
+ __u8 gso_type;
+ __u16 gso_size;
+ __u16 csum_start;
+ __u16 csum_offset;
+};
+#endif /* _LINUX_VIRTIO_NET_H */
diff --git a/include/linux/virtio_ring.h b/include/linux/virtio_ring.h
new file mode 100644
index 000000000000..1a4ed49f6478
--- /dev/null
+++ b/include/linux/virtio_ring.h
@@ -0,0 +1,122 @@
+#ifndef _LINUX_VIRTIO_RING_H
+#define _LINUX_VIRTIO_RING_H
+/* An interface for efficient virtio implementation, currently for use by KVM
+ * and lguest, but hopefully others soon. Do NOT change this since it will
+ * break existing servers and clients.
+ *
+ * This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers.
+ *
+ * Copyright Rusty Russell IBM Corporation 2007. */
+#include <linux/types.h>
+
+/* This marks a buffer as continuing via the next field. */
+#define VRING_DESC_F_NEXT 1
+/* This marks a buffer as write-only (otherwise read-only). */
+#define VRING_DESC_F_WRITE 2
+
+/* This means don't notify other side when buffer added. */
+#define VRING_USED_F_NO_NOTIFY 1
+/* This means don't interrupt guest when buffer consumed. */
+#define VRING_AVAIL_F_NO_INTERRUPT 1
+
+/* Virtio ring descriptors: 16 bytes. These can chain together via "next". */
+struct vring_desc
+{
+ /* Address (guest-physical). */
+ __u64 addr;
+ /* Length. */
+ __u32 len;
+ /* The flags as indicated above. */
+ __u16 flags;
+ /* We chain unused descriptors via this, too */
+ __u16 next;
+};
+
+struct vring_avail
+{
+ __u16 flags;
+ __u16 idx;
+ __u16 ring[];
+};
+
+/* u32 is used here for ids for padding reasons. */
+struct vring_used_elem
+{
+ /* Index of start of used descriptor chain. */
+ __u32 id;
+ /* Total length of the descriptor chain which was used (written to) */
+ __u32 len;
+};
+
+struct vring_used
+{
+ __u16 flags;
+ __u16 idx;
+ struct vring_used_elem ring[];
+};
+
+struct vring {
+ unsigned int num;
+
+ struct vring_desc *desc;
+
+ struct vring_avail *avail;
+
+ struct vring_used *used;
+};
+
+/* The standard layout for the ring is a continuous chunk of memory which looks
+ * like this. We assume num is a power of 2.
+ *
+ * struct vring
+ * {
+ * // The actual descriptors (16 bytes each)
+ * struct vring_desc desc[num];
+ *
+ * // A ring of available descriptor heads with free-running index.
+ * __u16 avail_flags;
+ * __u16 avail_idx;
+ * __u16 available[num];
+ *
+ * // Padding to the next page boundary.
+ * char pad[];
+ *
+ * // A ring of used descriptor heads with free-running index.
+ * __u16 used_flags;
+ * __u16 used_idx;
+ * struct vring_used_elem used[num];
+ * };
+ */
+static inline void vring_init(struct vring *vr, unsigned int num, void *p,
+ unsigned int pagesize)
+{
+ vr->num = num;
+ vr->desc = p;
+ vr->avail = p + num*sizeof(struct vring_desc);
+ vr->used = (void *)(((unsigned long)&vr->avail->ring[num] + pagesize-1)
+ & ~(pagesize - 1));
+}
+
+static inline unsigned vring_size(unsigned int num, unsigned int pagesize)
+{
+ return ((sizeof(struct vring_desc) * num + sizeof(__u16) * (2 + num)
+ + pagesize - 1) & ~(pagesize - 1))
+ + sizeof(__u16) * 2 + sizeof(struct vring_used_elem) * num;
+}
+
+#ifdef __KERNEL__
+#include <linux/irqreturn.h>
+struct virtio_device;
+struct virtqueue;
+
+struct virtqueue *vring_new_virtqueue(unsigned int num,
+ struct virtio_device *vdev,
+ void *pages,
+ void (*notify)(struct virtqueue *vq),
+ bool (*callback)(struct virtqueue *vq));
+void vring_del_virtqueue(struct virtqueue *vq);
+
+irqreturn_t vring_interrupt(int irq, void *_vq);
+#endif /* __KERNEL__ */
+#endif /* _LINUX_VIRTIO_RING_H */
diff --git a/include/linux/vt.h b/include/linux/vt.h
index ba806e8711be..02c1c0288770 100644
--- a/include/linux/vt.h
+++ b/include/linux/vt.h
@@ -1,6 +1,18 @@
#ifndef _LINUX_VT_H
#define _LINUX_VT_H
+#ifdef __KERNEL__
+struct notifier_block;
+
+struct vt_notifier_param {
+ struct vc_data *vc; /* VC on which the update happened */
+ unsigned int c; /* Printed char */
+};
+
+extern int register_vt_notifier(struct notifier_block *nb);
+extern int unregister_vt_notifier(struct notifier_block *nb);
+#endif
+
/*
* These constants are also useful for user-level apps (e.g., VC
* resizing).
diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h
index 699b7e9864fa..feb5e99a1079 100644
--- a/include/linux/vt_kern.h
+++ b/include/linux/vt_kern.h
@@ -87,6 +87,7 @@ extern int unbind_con_driver(const struct consw *csw, int first, int last,
extern char con_buf[CON_BUF_SIZE];
extern struct mutex con_buf_mtx;
extern char vt_dont_switch;
+extern int default_utf8;
struct vt_spawn_console {
spinlock_t lock;
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index ce6badc98f6d..7daafdc2514b 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -8,6 +8,7 @@
#include <linux/timer.h>
#include <linux/linkage.h>
#include <linux/bitops.h>
+#include <linux/lockdep.h>
#include <asm/atomic.h>
struct workqueue_struct;
@@ -28,6 +29,9 @@ struct work_struct {
#define WORK_STRUCT_WQ_DATA_MASK (~WORK_STRUCT_FLAG_MASK)
struct list_head entry;
work_func_t func;
+#ifdef CONFIG_LOCKDEP
+ struct lockdep_map lockdep_map;
+#endif
};
#define WORK_DATA_INIT() ATOMIC_LONG_INIT(0)
@@ -41,10 +45,23 @@ struct execute_work {
struct work_struct work;
};
+#ifdef CONFIG_LOCKDEP
+/*
+ * NB: because we have to copy the lockdep_map, setting _key
+ * here is required, otherwise it could get initialised to the
+ * copy of the lockdep_map!
+ */
+#define __WORK_INIT_LOCKDEP_MAP(n, k) \
+ .lockdep_map = STATIC_LOCKDEP_MAP_INIT(n, k),
+#else
+#define __WORK_INIT_LOCKDEP_MAP(n, k)
+#endif
+
#define __WORK_INITIALIZER(n, f) { \
.data = WORK_DATA_INIT(), \
.entry = { &(n).entry, &(n).entry }, \
.func = (f), \
+ __WORK_INIT_LOCKDEP_MAP(#n, &(n)) \
}
#define __DELAYED_WORK_INITIALIZER(n, f) { \
@@ -76,12 +93,24 @@ struct execute_work {
* assignment of the work data initializer allows the compiler
* to generate better code.
*/
+#ifdef CONFIG_LOCKDEP
+#define INIT_WORK(_work, _func) \
+ do { \
+ static struct lock_class_key __key; \
+ \
+ (_work)->data = (atomic_long_t) WORK_DATA_INIT(); \
+ lockdep_init_map(&(_work)->lockdep_map, #_work, &__key, 0);\
+ INIT_LIST_HEAD(&(_work)->entry); \
+ PREPARE_WORK((_work), (_func)); \
+ } while (0)
+#else
#define INIT_WORK(_work, _func) \
do { \
(_work)->data = (atomic_long_t) WORK_DATA_INIT(); \
INIT_LIST_HEAD(&(_work)->entry); \
PREPARE_WORK((_work), (_func)); \
} while (0)
+#endif
#define INIT_DELAYED_WORK(_work, _func) \
do { \
@@ -118,9 +147,23 @@ struct execute_work {
clear_bit(WORK_STRUCT_PENDING, work_data_bits(work))
-extern struct workqueue_struct *__create_workqueue(const char *name,
- int singlethread,
- int freezeable);
+extern struct workqueue_struct *
+__create_workqueue_key(const char *name, int singlethread,
+ int freezeable, struct lock_class_key *key);
+
+#ifdef CONFIG_LOCKDEP
+#define __create_workqueue(name, singlethread, freezeable) \
+({ \
+ static struct lock_class_key __key; \
+ \
+ __create_workqueue_key((name), (singlethread), \
+ (freezeable), &__key); \
+})
+#else
+#define __create_workqueue(name, singlethread, freezeable) \
+ __create_workqueue_key((name), (singlethread), (freezeable), NULL)
+#endif
+
#define create_workqueue(name) __create_workqueue((name), 0, 0)
#define create_freezeable_workqueue(name) __create_workqueue((name), 1, 1)
#define create_singlethread_workqueue(name) __create_workqueue((name), 1, 0)
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index d1321a81c9c4..bef7d66601cb 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -62,13 +62,13 @@ struct writeback_control {
unsigned for_reclaim:1; /* Invoked from the page allocator */
unsigned for_writepages:1; /* This is a writepages() call */
unsigned range_cyclic:1; /* range_start is cyclic */
+ unsigned more_io:1; /* more io to be dispatched */
};
/*
* fs/fs-writeback.c
*/
void writeback_inodes(struct writeback_control *wbc);
-void wake_up_inode(struct inode *inode);
int inode_wait(void *);
void sync_inodes_sb(struct super_block *, int wait);
void sync_inodes(int wait);
@@ -80,6 +80,13 @@ static inline void wait_on_inode(struct inode *inode)
wait_on_bit(&inode->i_state, __I_LOCK, inode_wait,
TASK_UNINTERRUPTIBLE);
}
+static inline void inode_sync_wait(struct inode *inode)
+{
+ might_sleep();
+ wait_on_bit(&inode->i_state, __I_SYNC, inode_wait,
+ TASK_UNINTERRUPTIBLE);
+}
+
/*
* mm/page-writeback.c
@@ -97,6 +104,10 @@ extern int dirty_expire_interval;
extern int block_dump;
extern int laptop_mode;
+extern int dirty_ratio_handler(struct ctl_table *table, int write,
+ struct file *filp, void __user *buffer, size_t *lenp,
+ loff_t *ppos);
+
struct ctl_table;
struct file;
int dirty_writeback_centisecs_handler(struct ctl_table *, int, struct file *,
diff --git a/include/media/saa7146.h b/include/media/saa7146.h
index cd3ff2c29d5e..88b2b5a619aa 100644
--- a/include/media/saa7146.h
+++ b/include/media/saa7146.h
@@ -12,6 +12,7 @@
#include <asm/io.h> /* for accessing devices */
#include <linux/stringify.h>
#include <linux/mutex.h>
+#include <linux/scatterlist.h>
#include <linux/vmalloc.h> /* for vmalloc() */
#include <linux/mm.h> /* for vmalloc_to_page() */
diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
index e75d5e6c4cea..c544c6f90893 100644
--- a/include/media/v4l2-dev.h
+++ b/include/media/v4l2-dev.h
@@ -94,7 +94,6 @@ struct video_device
char name[32];
int type; /* v4l1 */
int type2; /* v4l2 */
- int hardware;
int minor;
int debug; /* Activates debug level*/
@@ -272,10 +271,6 @@ struct video_device
int (*vidioc_s_crop) (struct file *file, void *fh,
struct v4l2_crop *a);
/* Compression ioctls */
- int (*vidioc_g_mpegcomp) (struct file *file, void *fh,
- struct v4l2_mpeg_compression *a);
- int (*vidioc_s_mpegcomp) (struct file *file, void *fh,
- struct v4l2_mpeg_compression *a);
int (*vidioc_g_jpegcomp) (struct file *file, void *fh,
struct v4l2_jpegcompression *a);
int (*vidioc_s_jpegcomp) (struct file *file, void *fh,
diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h
index 7726ff41c3e6..625346c47ee2 100644
--- a/include/net/9p/9p.h
+++ b/include/net/9p/9p.h
@@ -44,7 +44,7 @@ extern unsigned int p9_debug_level;
do { \
if ((p9_debug_level & level) == level) \
printk(KERN_NOTICE "-- %s (%d): " \
- format , __FUNCTION__, current->pid , ## arg); \
+ format , __FUNCTION__, task_pid_nr(current) , ## arg); \
} while (0)
#define PRINT_FCALL_ERROR(s, fcall) P9_DPRINTK(P9_DEBUG_ERROR, \
@@ -59,7 +59,7 @@ do { \
#define P9_EPRINTK(level, format, arg...) \
do { \
printk(level "9p: %s (%d): " \
- format , __FUNCTION__, current->pid , ## arg); \
+ format , __FUNCTION__, task_pid_nr(current), ## arg); \
} while (0)
@@ -216,6 +216,7 @@ struct p9_tauth {
u32 afid;
struct p9_str uname;
struct p9_str aname;
+ u32 n_uname; /* 9P2000.u extensions */
};
struct p9_rauth {
@@ -239,6 +240,7 @@ struct p9_tattach {
u32 afid;
struct p9_str uname;
struct p9_str aname;
+ u32 n_uname; /* 9P2000.u extensions */
};
struct p9_rattach {
@@ -382,8 +384,9 @@ int p9_deserialize_fcall(void *buf, u32 buflen, struct p9_fcall *fc, int dotu);
void p9_set_tag(struct p9_fcall *fc, u16 tag);
struct p9_fcall *p9_create_tversion(u32 msize, char *version);
struct p9_fcall *p9_create_tattach(u32 fid, u32 afid, char *uname,
- char *aname);
-struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname);
+ char *aname, u32 n_uname, int dotu);
+struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname,
+ u32 n_uname, int dotu);
struct p9_fcall *p9_create_tflush(u16 oldtag);
struct p9_fcall *p9_create_twalk(u32 fid, u32 newfid, u16 nwname,
char **wnames);
@@ -412,18 +415,4 @@ int p9_idpool_check(int id, struct p9_idpool *p);
int p9_error_init(void);
int p9_errstr2errno(char *, int);
-
-#ifdef CONFIG_SYSCTL
-int __init p9_sysctl_register(void);
-void __exit p9_sysctl_unregister(void);
-#else
-static inline int p9_sysctl_register(void)
-{
- return 0;
-}
-static inline void p9_sysctl_unregister(void)
-{
-}
-#endif
-
#endif /* NET_9P_H */
diff --git a/include/net/9p/client.h b/include/net/9p/client.h
index d65ed7c69063..9b9221a21392 100644
--- a/include/net/9p/client.h
+++ b/include/net/9p/client.h
@@ -29,7 +29,7 @@ struct p9_client {
spinlock_t lock; /* protect client structure */
int msize;
unsigned char dotu;
- struct p9_transport *trans;
+ struct p9_trans *trans;
struct p9_conn *conn;
struct p9_idpool *fidpool;
@@ -52,13 +52,14 @@ struct p9_fid {
struct list_head dlist; /* list of all fids attached to a dentry */
};
-struct p9_client *p9_client_create(struct p9_transport *trans, int msize,
+struct p9_client *p9_client_create(struct p9_trans *trans, int msize,
int dotu);
void p9_client_destroy(struct p9_client *clnt);
void p9_client_disconnect(struct p9_client *clnt);
struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
- char *uname, char *aname);
-struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname, char *aname);
+ char *uname, u32 n_uname, char *aname);
+struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname,
+ u32 n_uname, char *aname);
struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
int clone);
int p9_client_open(struct p9_fid *fid, int mode);
diff --git a/include/net/9p/conn.h b/include/net/9p/conn.h
index 583b6a2cb3df..756d8784f953 100644
--- a/include/net/9p/conn.h
+++ b/include/net/9p/conn.h
@@ -42,8 +42,8 @@ struct p9_req;
*/
typedef void (*p9_conn_req_callback)(struct p9_req *req, void *a);
-struct p9_conn *p9_conn_create(struct p9_transport *trans, int msize,
- unsigned char *dotu);
+struct p9_conn *p9_conn_create(struct p9_trans *trans, int msize,
+ unsigned char *dotu);
void p9_conn_destroy(struct p9_conn *);
int p9_conn_rpc(struct p9_conn *m, struct p9_fcall *tc, struct p9_fcall **rc);
diff --git a/include/net/9p/transport.h b/include/net/9p/transport.h
index 462d42279fb0..9dd4a05619a8 100644
--- a/include/net/9p/transport.h
+++ b/include/net/9p/transport.h
@@ -26,24 +26,31 @@
#ifndef NET_9P_TRANSPORT_H
#define NET_9P_TRANSPORT_H
-enum p9_transport_status {
+enum p9_trans_status {
Connected,
Disconnected,
Hung,
};
-struct p9_transport {
- enum p9_transport_status status;
+struct p9_trans {
+ enum p9_trans_status status;
void *priv;
+ int (*write) (struct p9_trans *, void *, int);
+ int (*read) (struct p9_trans *, void *, int);
+ void (*close) (struct p9_trans *);
+ unsigned int (*poll)(struct p9_trans *, struct poll_table_struct *);
+};
- int (*write) (struct p9_transport *, void *, int);
- int (*read) (struct p9_transport *, void *, int);
- void (*close) (struct p9_transport *);
- unsigned int (*poll)(struct p9_transport *, struct poll_table_struct *);
+struct p9_trans_module {
+ struct list_head list;
+ char *name; /* name of transport */
+ int maxsize; /* max message size of transport */
+ int def; /* this transport should be default */
+ struct p9_trans * (*create)(const char *devname, char *options);
};
-struct p9_transport *p9_trans_create_tcp(const char *addr, int port);
-struct p9_transport *p9_trans_create_unix(const char *addr);
-struct p9_transport *p9_trans_create_fd(int rfd, int wfd);
+void v9fs_register_trans(struct p9_trans_module *m);
+struct p9_trans_module *v9fs_match_trans(const substring_t *name);
+struct p9_trans_module *v9fs_default_trans(void);
#endif /* NET_9P_TRANSPORT_H */
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index 0864a775de24..a1c805d7f488 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -12,7 +12,7 @@ extern void unix_gc(void);
#define UNIX_HASH_SIZE 256
-extern atomic_t unix_tot_inflight;
+extern unsigned int unix_tot_inflight;
struct unix_address {
atomic_t refcnt;
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index ebfb96b41106..a8a9eb6af966 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -200,119 +200,18 @@ enum {
#define HCI_LM_SECURE 0x0020
/* ----- HCI Commands ---- */
-/* OGF & OCF values */
-
-/* Informational Parameters */
-#define OGF_INFO_PARAM 0x04
-
-#define OCF_READ_LOCAL_VERSION 0x0001
-struct hci_rp_read_loc_version {
- __u8 status;
- __u8 hci_ver;
- __le16 hci_rev;
- __u8 lmp_ver;
- __le16 manufacturer;
- __le16 lmp_subver;
-} __attribute__ ((packed));
-
-#define OCF_READ_LOCAL_FEATURES 0x0003
-struct hci_rp_read_local_features {
- __u8 status;
- __u8 features[8];
-} __attribute__ ((packed));
-
-#define OCF_READ_BUFFER_SIZE 0x0005
-struct hci_rp_read_buffer_size {
- __u8 status;
- __le16 acl_mtu;
- __u8 sco_mtu;
- __le16 acl_max_pkt;
- __le16 sco_max_pkt;
-} __attribute__ ((packed));
-
-#define OCF_READ_BD_ADDR 0x0009
-struct hci_rp_read_bd_addr {
- __u8 status;
- bdaddr_t bdaddr;
-} __attribute__ ((packed));
-
-/* Host Controller and Baseband */
-#define OGF_HOST_CTL 0x03
-#define OCF_RESET 0x0003
-#define OCF_READ_AUTH_ENABLE 0x001F
-#define OCF_WRITE_AUTH_ENABLE 0x0020
- #define AUTH_DISABLED 0x00
- #define AUTH_ENABLED 0x01
-
-#define OCF_READ_ENCRYPT_MODE 0x0021
-#define OCF_WRITE_ENCRYPT_MODE 0x0022
- #define ENCRYPT_DISABLED 0x00
- #define ENCRYPT_P2P 0x01
- #define ENCRYPT_BOTH 0x02
-
-#define OCF_WRITE_CA_TIMEOUT 0x0016
-#define OCF_WRITE_PG_TIMEOUT 0x0018
-
-#define OCF_WRITE_SCAN_ENABLE 0x001A
- #define SCAN_DISABLED 0x00
- #define SCAN_INQUIRY 0x01
- #define SCAN_PAGE 0x02
-
-#define OCF_SET_EVENT_FLT 0x0005
-struct hci_cp_set_event_flt {
- __u8 flt_type;
- __u8 cond_type;
- __u8 condition[0];
-} __attribute__ ((packed));
-
-/* Filter types */
-#define HCI_FLT_CLEAR_ALL 0x00
-#define HCI_FLT_INQ_RESULT 0x01
-#define HCI_FLT_CONN_SETUP 0x02
-
-/* CONN_SETUP Condition types */
-#define HCI_CONN_SETUP_ALLOW_ALL 0x00
-#define HCI_CONN_SETUP_ALLOW_CLASS 0x01
-#define HCI_CONN_SETUP_ALLOW_BDADDR 0x02
-
-/* CONN_SETUP Conditions */
-#define HCI_CONN_SETUP_AUTO_OFF 0x01
-#define HCI_CONN_SETUP_AUTO_ON 0x02
-
-#define OCF_READ_CLASS_OF_DEV 0x0023
-struct hci_rp_read_dev_class {
- __u8 status;
- __u8 dev_class[3];
-} __attribute__ ((packed));
-
-#define OCF_WRITE_CLASS_OF_DEV 0x0024
-struct hci_cp_write_dev_class {
- __u8 dev_class[3];
-} __attribute__ ((packed));
-
-#define OCF_READ_VOICE_SETTING 0x0025
-struct hci_rp_read_voice_setting {
- __u8 status;
- __le16 voice_setting;
+#define HCI_OP_INQUIRY 0x0401
+struct hci_cp_inquiry {
+ __u8 lap[3];
+ __u8 length;
+ __u8 num_rsp;
} __attribute__ ((packed));
-#define OCF_WRITE_VOICE_SETTING 0x0026
-struct hci_cp_write_voice_setting {
- __le16 voice_setting;
-} __attribute__ ((packed));
+#define HCI_OP_INQUIRY_CANCEL 0x0402
-#define OCF_HOST_BUFFER_SIZE 0x0033
-struct hci_cp_host_buffer_size {
- __le16 acl_mtu;
- __u8 sco_mtu;
- __le16 acl_max_pkt;
- __le16 sco_max_pkt;
-} __attribute__ ((packed));
-
-/* Link Control */
-#define OGF_LINK_CTL 0x01
+#define HCI_OP_EXIT_PERIODIC_INQ 0x0404
-#define OCF_CREATE_CONN 0x0005
+#define HCI_OP_CREATE_CONN 0x0405
struct hci_cp_create_conn {
bdaddr_t bdaddr;
__le16 pkt_type;
@@ -322,105 +221,138 @@ struct hci_cp_create_conn {
__u8 role_switch;
} __attribute__ ((packed));
-#define OCF_CREATE_CONN_CANCEL 0x0008
-struct hci_cp_create_conn_cancel {
- bdaddr_t bdaddr;
-} __attribute__ ((packed));
-
-#define OCF_ACCEPT_CONN_REQ 0x0009
-struct hci_cp_accept_conn_req {
- bdaddr_t bdaddr;
- __u8 role;
-} __attribute__ ((packed));
-
-#define OCF_REJECT_CONN_REQ 0x000a
-struct hci_cp_reject_conn_req {
- bdaddr_t bdaddr;
- __u8 reason;
-} __attribute__ ((packed));
-
-#define OCF_DISCONNECT 0x0006
+#define HCI_OP_DISCONNECT 0x0406
struct hci_cp_disconnect {
__le16 handle;
__u8 reason;
} __attribute__ ((packed));
-#define OCF_ADD_SCO 0x0007
+#define HCI_OP_ADD_SCO 0x0407
struct hci_cp_add_sco {
__le16 handle;
__le16 pkt_type;
} __attribute__ ((packed));
-#define OCF_INQUIRY 0x0001
-struct hci_cp_inquiry {
- __u8 lap[3];
- __u8 length;
- __u8 num_rsp;
+#define HCI_OP_CREATE_CONN_CANCEL 0x0408
+struct hci_cp_create_conn_cancel {
+ bdaddr_t bdaddr;
} __attribute__ ((packed));
-#define OCF_INQUIRY_CANCEL 0x0002
+#define HCI_OP_ACCEPT_CONN_REQ 0x0409
+struct hci_cp_accept_conn_req {
+ bdaddr_t bdaddr;
+ __u8 role;
+} __attribute__ ((packed));
-#define OCF_EXIT_PERIODIC_INQ 0x0004
+#define HCI_OP_REJECT_CONN_REQ 0x040a
+struct hci_cp_reject_conn_req {
+ bdaddr_t bdaddr;
+ __u8 reason;
+} __attribute__ ((packed));
-#define OCF_LINK_KEY_REPLY 0x000B
+#define HCI_OP_LINK_KEY_REPLY 0x040b
struct hci_cp_link_key_reply {
bdaddr_t bdaddr;
__u8 link_key[16];
} __attribute__ ((packed));
-#define OCF_LINK_KEY_NEG_REPLY 0x000C
+#define HCI_OP_LINK_KEY_NEG_REPLY 0x040c
struct hci_cp_link_key_neg_reply {
bdaddr_t bdaddr;
} __attribute__ ((packed));
-#define OCF_PIN_CODE_REPLY 0x000D
+#define HCI_OP_PIN_CODE_REPLY 0x040d
struct hci_cp_pin_code_reply {
bdaddr_t bdaddr;
__u8 pin_len;
__u8 pin_code[16];
} __attribute__ ((packed));
-#define OCF_PIN_CODE_NEG_REPLY 0x000E
+#define HCI_OP_PIN_CODE_NEG_REPLY 0x040e
struct hci_cp_pin_code_neg_reply {
bdaddr_t bdaddr;
} __attribute__ ((packed));
-#define OCF_CHANGE_CONN_PTYPE 0x000F
+#define HCI_OP_CHANGE_CONN_PTYPE 0x040f
struct hci_cp_change_conn_ptype {
__le16 handle;
__le16 pkt_type;
} __attribute__ ((packed));
-#define OCF_AUTH_REQUESTED 0x0011
+#define HCI_OP_AUTH_REQUESTED 0x0411
struct hci_cp_auth_requested {
__le16 handle;
} __attribute__ ((packed));
-#define OCF_SET_CONN_ENCRYPT 0x0013
+#define HCI_OP_SET_CONN_ENCRYPT 0x0413
struct hci_cp_set_conn_encrypt {
__le16 handle;
__u8 encrypt;
} __attribute__ ((packed));
-#define OCF_CHANGE_CONN_LINK_KEY 0x0015
+#define HCI_OP_CHANGE_CONN_LINK_KEY 0x0415
struct hci_cp_change_conn_link_key {
__le16 handle;
} __attribute__ ((packed));
-#define OCF_READ_REMOTE_FEATURES 0x001B
+#define HCI_OP_REMOTE_NAME_REQ 0x0419
+struct hci_cp_remote_name_req {
+ bdaddr_t bdaddr;
+ __u8 pscan_rep_mode;
+ __u8 pscan_mode;
+ __le16 clock_offset;
+} __attribute__ ((packed));
+
+#define HCI_OP_REMOTE_NAME_REQ_CANCEL 0x041a
+struct hci_cp_remote_name_req_cancel {
+ bdaddr_t bdaddr;
+} __attribute__ ((packed));
+
+#define HCI_OP_READ_REMOTE_FEATURES 0x041b
struct hci_cp_read_remote_features {
__le16 handle;
} __attribute__ ((packed));
-#define OCF_READ_REMOTE_VERSION 0x001D
+#define HCI_OP_READ_REMOTE_EXT_FEATURES 0x041c
+struct hci_cp_read_remote_ext_features {
+ __le16 handle;
+ __u8 page;
+} __attribute__ ((packed));
+
+#define HCI_OP_READ_REMOTE_VERSION 0x041d
struct hci_cp_read_remote_version {
__le16 handle;
} __attribute__ ((packed));
-/* Link Policy */
-#define OGF_LINK_POLICY 0x02
+#define HCI_OP_SETUP_SYNC_CONN 0x0428
+struct hci_cp_setup_sync_conn {
+ __le16 handle;
+ __le32 tx_bandwidth;
+ __le32 rx_bandwidth;
+ __le16 max_latency;
+ __le16 voice_setting;
+ __u8 retrans_effort;
+ __le16 pkt_type;
+} __attribute__ ((packed));
-#define OCF_SNIFF_MODE 0x0003
+#define HCI_OP_ACCEPT_SYNC_CONN_REQ 0x0429
+struct hci_cp_accept_sync_conn_req {
+ bdaddr_t bdaddr;
+ __le32 tx_bandwidth;
+ __le32 rx_bandwidth;
+ __le16 max_latency;
+ __le16 content_format;
+ __u8 retrans_effort;
+ __le16 pkt_type;
+} __attribute__ ((packed));
+
+#define HCI_OP_REJECT_SYNC_CONN_REQ 0x042a
+struct hci_cp_reject_sync_conn_req {
+ bdaddr_t bdaddr;
+ __u8 reason;
+} __attribute__ ((packed));
+
+#define HCI_OP_SNIFF_MODE 0x0803
struct hci_cp_sniff_mode {
__le16 handle;
__le16 max_interval;
@@ -429,12 +361,12 @@ struct hci_cp_sniff_mode {
__le16 timeout;
} __attribute__ ((packed));
-#define OCF_EXIT_SNIFF_MODE 0x0004
+#define HCI_OP_EXIT_SNIFF_MODE 0x0804
struct hci_cp_exit_sniff_mode {
__le16 handle;
} __attribute__ ((packed));
-#define OCF_ROLE_DISCOVERY 0x0009
+#define HCI_OP_ROLE_DISCOVERY 0x0809
struct hci_cp_role_discovery {
__le16 handle;
} __attribute__ ((packed));
@@ -444,7 +376,13 @@ struct hci_rp_role_discovery {
__u8 role;
} __attribute__ ((packed));
-#define OCF_READ_LINK_POLICY 0x000C
+#define HCI_OP_SWITCH_ROLE 0x080b
+struct hci_cp_switch_role {
+ bdaddr_t bdaddr;
+ __u8 role;
+} __attribute__ ((packed));
+
+#define HCI_OP_READ_LINK_POLICY 0x080c
struct hci_cp_read_link_policy {
__le16 handle;
} __attribute__ ((packed));
@@ -454,13 +392,7 @@ struct hci_rp_read_link_policy {
__le16 policy;
} __attribute__ ((packed));
-#define OCF_SWITCH_ROLE 0x000B
-struct hci_cp_switch_role {
- bdaddr_t bdaddr;
- __u8 role;
-} __attribute__ ((packed));
-
-#define OCF_WRITE_LINK_POLICY 0x000D
+#define HCI_OP_WRITE_LINK_POLICY 0x080d
struct hci_cp_write_link_policy {
__le16 handle;
__le16 policy;
@@ -470,7 +402,7 @@ struct hci_rp_write_link_policy {
__le16 handle;
} __attribute__ ((packed));
-#define OCF_SNIFF_SUBRATE 0x0011
+#define HCI_OP_SNIFF_SUBRATE 0x0811
struct hci_cp_sniff_subrate {
__le16 handle;
__le16 max_latency;
@@ -478,59 +410,156 @@ struct hci_cp_sniff_subrate {
__le16 min_local_timeout;
} __attribute__ ((packed));
-/* Status params */
-#define OGF_STATUS_PARAM 0x05
+#define HCI_OP_SET_EVENT_MASK 0x0c01
+struct hci_cp_set_event_mask {
+ __u8 mask[8];
+} __attribute__ ((packed));
-/* Testing commands */
-#define OGF_TESTING_CMD 0x3E
+#define HCI_OP_RESET 0x0c03
-/* Vendor specific commands */
-#define OGF_VENDOR_CMD 0x3F
+#define HCI_OP_SET_EVENT_FLT 0x0c05
+struct hci_cp_set_event_flt {
+ __u8 flt_type;
+ __u8 cond_type;
+ __u8 condition[0];
+} __attribute__ ((packed));
-/* ---- HCI Events ---- */
-#define HCI_EV_INQUIRY_COMPLETE 0x01
+/* Filter types */
+#define HCI_FLT_CLEAR_ALL 0x00
+#define HCI_FLT_INQ_RESULT 0x01
+#define HCI_FLT_CONN_SETUP 0x02
-#define HCI_EV_INQUIRY_RESULT 0x02
-struct inquiry_info {
- bdaddr_t bdaddr;
- __u8 pscan_rep_mode;
- __u8 pscan_period_mode;
- __u8 pscan_mode;
+/* CONN_SETUP Condition types */
+#define HCI_CONN_SETUP_ALLOW_ALL 0x00
+#define HCI_CONN_SETUP_ALLOW_CLASS 0x01
+#define HCI_CONN_SETUP_ALLOW_BDADDR 0x02
+
+/* CONN_SETUP Conditions */
+#define HCI_CONN_SETUP_AUTO_OFF 0x01
+#define HCI_CONN_SETUP_AUTO_ON 0x02
+
+#define HCI_OP_WRITE_LOCAL_NAME 0x0c13
+struct hci_cp_write_local_name {
+ __u8 name[248];
+} __attribute__ ((packed));
+
+#define HCI_OP_READ_LOCAL_NAME 0x0c14
+struct hci_rp_read_local_name {
+ __u8 status;
+ __u8 name[248];
+} __attribute__ ((packed));
+
+#define HCI_OP_WRITE_CA_TIMEOUT 0x0c16
+
+#define HCI_OP_WRITE_PG_TIMEOUT 0x0c18
+
+#define HCI_OP_WRITE_SCAN_ENABLE 0x0c1a
+ #define SCAN_DISABLED 0x00
+ #define SCAN_INQUIRY 0x01
+ #define SCAN_PAGE 0x02
+
+#define HCI_OP_READ_AUTH_ENABLE 0x0c1f
+
+#define HCI_OP_WRITE_AUTH_ENABLE 0x0c20
+ #define AUTH_DISABLED 0x00
+ #define AUTH_ENABLED 0x01
+
+#define HCI_OP_READ_ENCRYPT_MODE 0x0c21
+
+#define HCI_OP_WRITE_ENCRYPT_MODE 0x0c22
+ #define ENCRYPT_DISABLED 0x00
+ #define ENCRYPT_P2P 0x01
+ #define ENCRYPT_BOTH 0x02
+
+#define HCI_OP_READ_CLASS_OF_DEV 0x0c23
+struct hci_rp_read_class_of_dev {
+ __u8 status;
__u8 dev_class[3];
- __le16 clock_offset;
} __attribute__ ((packed));
-#define HCI_EV_INQUIRY_RESULT_WITH_RSSI 0x22
-struct inquiry_info_with_rssi {
- bdaddr_t bdaddr;
- __u8 pscan_rep_mode;
- __u8 pscan_period_mode;
+#define HCI_OP_WRITE_CLASS_OF_DEV 0x0c24
+struct hci_cp_write_class_of_dev {
__u8 dev_class[3];
- __le16 clock_offset;
- __s8 rssi;
} __attribute__ ((packed));
-struct inquiry_info_with_rssi_and_pscan_mode {
+
+#define HCI_OP_READ_VOICE_SETTING 0x0c25
+struct hci_rp_read_voice_setting {
+ __u8 status;
+ __le16 voice_setting;
+} __attribute__ ((packed));
+
+#define HCI_OP_WRITE_VOICE_SETTING 0x0c26
+struct hci_cp_write_voice_setting {
+ __le16 voice_setting;
+} __attribute__ ((packed));
+
+#define HCI_OP_HOST_BUFFER_SIZE 0x0c33
+struct hci_cp_host_buffer_size {
+ __le16 acl_mtu;
+ __u8 sco_mtu;
+ __le16 acl_max_pkt;
+ __le16 sco_max_pkt;
+} __attribute__ ((packed));
+
+#define HCI_OP_READ_LOCAL_VERSION 0x1001
+struct hci_rp_read_local_version {
+ __u8 status;
+ __u8 hci_ver;
+ __le16 hci_rev;
+ __u8 lmp_ver;
+ __le16 manufacturer;
+ __le16 lmp_subver;
+} __attribute__ ((packed));
+
+#define HCI_OP_READ_LOCAL_COMMANDS 0x1002
+struct hci_rp_read_local_commands {
+ __u8 status;
+ __u8 commands[64];
+} __attribute__ ((packed));
+
+#define HCI_OP_READ_LOCAL_FEATURES 0x1003
+struct hci_rp_read_local_features {
+ __u8 status;
+ __u8 features[8];
+} __attribute__ ((packed));
+
+#define HCI_OP_READ_LOCAL_EXT_FEATURES 0x1004
+struct hci_rp_read_local_ext_features {
+ __u8 status;
+ __u8 page;
+ __u8 max_page;
+ __u8 features[8];
+} __attribute__ ((packed));
+
+#define HCI_OP_READ_BUFFER_SIZE 0x1005
+struct hci_rp_read_buffer_size {
+ __u8 status;
+ __le16 acl_mtu;
+ __u8 sco_mtu;
+ __le16 acl_max_pkt;
+ __le16 sco_max_pkt;
+} __attribute__ ((packed));
+
+#define HCI_OP_READ_BD_ADDR 0x1009
+struct hci_rp_read_bd_addr {
+ __u8 status;
bdaddr_t bdaddr;
- __u8 pscan_rep_mode;
- __u8 pscan_period_mode;
- __u8 pscan_mode;
- __u8 dev_class[3];
- __le16 clock_offset;
- __s8 rssi;
} __attribute__ ((packed));
-#define HCI_EV_EXTENDED_INQUIRY_RESULT 0x2F
-struct extended_inquiry_info {
+/* ---- HCI Events ---- */
+#define HCI_EV_INQUIRY_COMPLETE 0x01
+
+#define HCI_EV_INQUIRY_RESULT 0x02
+struct inquiry_info {
bdaddr_t bdaddr;
__u8 pscan_rep_mode;
__u8 pscan_period_mode;
+ __u8 pscan_mode;
__u8 dev_class[3];
__le16 clock_offset;
- __s8 rssi;
- __u8 data[240];
} __attribute__ ((packed));
-#define HCI_EV_CONN_COMPLETE 0x03
+#define HCI_EV_CONN_COMPLETE 0x03
struct hci_ev_conn_complete {
__u8 status;
__le16 handle;
@@ -539,40 +568,63 @@ struct hci_ev_conn_complete {
__u8 encr_mode;
} __attribute__ ((packed));
-#define HCI_EV_CONN_REQUEST 0x04
+#define HCI_EV_CONN_REQUEST 0x04
struct hci_ev_conn_request {
bdaddr_t bdaddr;
__u8 dev_class[3];
__u8 link_type;
} __attribute__ ((packed));
-#define HCI_EV_DISCONN_COMPLETE 0x05
+#define HCI_EV_DISCONN_COMPLETE 0x05
struct hci_ev_disconn_complete {
__u8 status;
__le16 handle;
__u8 reason;
} __attribute__ ((packed));
-#define HCI_EV_AUTH_COMPLETE 0x06
+#define HCI_EV_AUTH_COMPLETE 0x06
struct hci_ev_auth_complete {
__u8 status;
__le16 handle;
} __attribute__ ((packed));
-#define HCI_EV_ENCRYPT_CHANGE 0x08
+#define HCI_EV_REMOTE_NAME 0x07
+struct hci_ev_remote_name {
+ __u8 status;
+ bdaddr_t bdaddr;
+ __u8 name[248];
+} __attribute__ ((packed));
+
+#define HCI_EV_ENCRYPT_CHANGE 0x08
struct hci_ev_encrypt_change {
__u8 status;
__le16 handle;
__u8 encrypt;
} __attribute__ ((packed));
-#define HCI_EV_CHANGE_CONN_LINK_KEY_COMPLETE 0x09
-struct hci_ev_change_conn_link_key_complete {
+#define HCI_EV_CHANGE_LINK_KEY_COMPLETE 0x09
+struct hci_ev_change_link_key_complete {
+ __u8 status;
+ __le16 handle;
+} __attribute__ ((packed));
+
+#define HCI_EV_REMOTE_FEATURES 0x0b
+struct hci_ev_remote_features {
+ __u8 status;
+ __le16 handle;
+ __u8 features[8];
+} __attribute__ ((packed));
+
+#define HCI_EV_REMOTE_VERSION 0x0c
+struct hci_ev_remote_version {
__u8 status;
__le16 handle;
+ __u8 lmp_ver;
+ __le16 manufacturer;
+ __le16 lmp_subver;
} __attribute__ ((packed));
-#define HCI_EV_QOS_SETUP_COMPLETE 0x0D
+#define HCI_EV_QOS_SETUP_COMPLETE 0x0d
struct hci_qos {
__u8 service_type;
__u32 token_rate;
@@ -586,33 +638,33 @@ struct hci_ev_qos_setup_complete {
struct hci_qos qos;
} __attribute__ ((packed));
-#define HCI_EV_CMD_COMPLETE 0x0E
+#define HCI_EV_CMD_COMPLETE 0x0e
struct hci_ev_cmd_complete {
__u8 ncmd;
__le16 opcode;
} __attribute__ ((packed));
-#define HCI_EV_CMD_STATUS 0x0F
+#define HCI_EV_CMD_STATUS 0x0f
struct hci_ev_cmd_status {
__u8 status;
__u8 ncmd;
__le16 opcode;
} __attribute__ ((packed));
-#define HCI_EV_NUM_COMP_PKTS 0x13
-struct hci_ev_num_comp_pkts {
- __u8 num_hndl;
- /* variable length part */
-} __attribute__ ((packed));
-
-#define HCI_EV_ROLE_CHANGE 0x12
+#define HCI_EV_ROLE_CHANGE 0x12
struct hci_ev_role_change {
__u8 status;
bdaddr_t bdaddr;
__u8 role;
} __attribute__ ((packed));
-#define HCI_EV_MODE_CHANGE 0x14
+#define HCI_EV_NUM_COMP_PKTS 0x13
+struct hci_ev_num_comp_pkts {
+ __u8 num_hndl;
+ /* variable length part */
+} __attribute__ ((packed));
+
+#define HCI_EV_MODE_CHANGE 0x14
struct hci_ev_mode_change {
__u8 status;
__le16 handle;
@@ -620,53 +672,88 @@ struct hci_ev_mode_change {
__le16 interval;
} __attribute__ ((packed));
-#define HCI_EV_PIN_CODE_REQ 0x16
+#define HCI_EV_PIN_CODE_REQ 0x16
struct hci_ev_pin_code_req {
bdaddr_t bdaddr;
} __attribute__ ((packed));
-#define HCI_EV_LINK_KEY_REQ 0x17
+#define HCI_EV_LINK_KEY_REQ 0x17
struct hci_ev_link_key_req {
bdaddr_t bdaddr;
} __attribute__ ((packed));
-#define HCI_EV_LINK_KEY_NOTIFY 0x18
+#define HCI_EV_LINK_KEY_NOTIFY 0x18
struct hci_ev_link_key_notify {
bdaddr_t bdaddr;
- __u8 link_key[16];
- __u8 key_type;
+ __u8 link_key[16];
+ __u8 key_type;
} __attribute__ ((packed));
-#define HCI_EV_REMOTE_FEATURES 0x0B
-struct hci_ev_remote_features {
+#define HCI_EV_CLOCK_OFFSET 0x1c
+struct hci_ev_clock_offset {
__u8 status;
__le16 handle;
- __u8 features[8];
+ __le16 clock_offset;
} __attribute__ ((packed));
-#define HCI_EV_REMOTE_VERSION 0x0C
-struct hci_ev_remote_version {
+#define HCI_EV_PSCAN_REP_MODE 0x20
+struct hci_ev_pscan_rep_mode {
+ bdaddr_t bdaddr;
+ __u8 pscan_rep_mode;
+} __attribute__ ((packed));
+
+#define HCI_EV_INQUIRY_RESULT_WITH_RSSI 0x22
+struct inquiry_info_with_rssi {
+ bdaddr_t bdaddr;
+ __u8 pscan_rep_mode;
+ __u8 pscan_period_mode;
+ __u8 dev_class[3];
+ __le16 clock_offset;
+ __s8 rssi;
+} __attribute__ ((packed));
+struct inquiry_info_with_rssi_and_pscan_mode {
+ bdaddr_t bdaddr;
+ __u8 pscan_rep_mode;
+ __u8 pscan_period_mode;
+ __u8 pscan_mode;
+ __u8 dev_class[3];
+ __le16 clock_offset;
+ __s8 rssi;
+} __attribute__ ((packed));
+
+#define HCI_EV_REMOTE_EXT_FEATURES 0x23
+struct hci_ev_remote_ext_features {
__u8 status;
__le16 handle;
- __u8 lmp_ver;
- __le16 manufacturer;
- __le16 lmp_subver;
+ __u8 page;
+ __u8 max_page;
+ __u8 features[8];
} __attribute__ ((packed));
-#define HCI_EV_CLOCK_OFFSET 0x01C
-struct hci_ev_clock_offset {
+#define HCI_EV_SYNC_CONN_COMPLETE 0x2c
+struct hci_ev_sync_conn_complete {
__u8 status;
__le16 handle;
- __le16 clock_offset;
+ bdaddr_t bdaddr;
+ __u8 link_type;
+ __u8 tx_interval;
+ __u8 retrans_window;
+ __le16 rx_pkt_len;
+ __le16 tx_pkt_len;
+ __u8 air_mode;
} __attribute__ ((packed));
-#define HCI_EV_PSCAN_REP_MODE 0x20
-struct hci_ev_pscan_rep_mode {
- bdaddr_t bdaddr;
- __u8 pscan_rep_mode;
+#define HCI_EV_SYNC_CONN_CHANGED 0x2d
+struct hci_ev_sync_conn_changed {
+ __u8 status;
+ __le16 handle;
+ __u8 tx_interval;
+ __u8 retrans_window;
+ __le16 rx_pkt_len;
+ __le16 tx_pkt_len;
} __attribute__ ((packed));
-#define HCI_EV_SNIFF_SUBRATE 0x2E
+#define HCI_EV_SNIFF_SUBRATE 0x2e
struct hci_ev_sniff_subrate {
__u8 status;
__le16 handle;
@@ -676,14 +763,25 @@ struct hci_ev_sniff_subrate {
__le16 max_local_timeout;
} __attribute__ ((packed));
+#define HCI_EV_EXTENDED_INQUIRY_RESULT 0x2f
+struct extended_inquiry_info {
+ bdaddr_t bdaddr;
+ __u8 pscan_rep_mode;
+ __u8 pscan_period_mode;
+ __u8 dev_class[3];
+ __le16 clock_offset;
+ __s8 rssi;
+ __u8 data[240];
+} __attribute__ ((packed));
+
/* Internal events generated by Bluetooth stack */
-#define HCI_EV_STACK_INTERNAL 0xFD
+#define HCI_EV_STACK_INTERNAL 0xfd
struct hci_ev_stack_internal {
__u16 type;
__u8 data[0];
} __attribute__ ((packed));
-#define HCI_EV_SI_DEVICE 0x01
+#define HCI_EV_SI_DEVICE 0x01
struct hci_ev_si_device {
__u16 event;
__u16 dev_id;
@@ -704,40 +802,40 @@ struct hci_ev_si_security {
#define HCI_SCO_HDR_SIZE 3
struct hci_command_hdr {
- __le16 opcode; /* OCF & OGF */
+ __le16 opcode; /* OCF & OGF */
__u8 plen;
} __attribute__ ((packed));
struct hci_event_hdr {
- __u8 evt;
- __u8 plen;
+ __u8 evt;
+ __u8 plen;
} __attribute__ ((packed));
struct hci_acl_hdr {
- __le16 handle; /* Handle & Flags(PB, BC) */
- __le16 dlen;
+ __le16 handle; /* Handle & Flags(PB, BC) */
+ __le16 dlen;
} __attribute__ ((packed));
struct hci_sco_hdr {
- __le16 handle;
- __u8 dlen;
+ __le16 handle;
+ __u8 dlen;
} __attribute__ ((packed));
#ifdef __KERNEL__
#include <linux/skbuff.h>
static inline struct hci_event_hdr *hci_event_hdr(const struct sk_buff *skb)
{
- return (struct hci_event_hdr *)skb->data;
+ return (struct hci_event_hdr *) skb->data;
}
static inline struct hci_acl_hdr *hci_acl_hdr(const struct sk_buff *skb)
{
- return (struct hci_acl_hdr *)skb->data;
+ return (struct hci_acl_hdr *) skb->data;
}
static inline struct hci_sco_hdr *hci_sco_hdr(const struct sk_buff *skb)
{
- return (struct hci_sco_hdr *)skb->data;
+ return (struct hci_sco_hdr *) skb->data;
}
#endif
@@ -771,13 +869,13 @@ struct sockaddr_hci {
struct hci_filter {
unsigned long type_mask;
unsigned long event_mask[2];
- __le16 opcode;
+ __le16 opcode;
};
struct hci_ufilter {
- __u32 type_mask;
- __u32 event_mask[2];
- __le16 opcode;
+ __u32 type_mask;
+ __u32 event_mask[2];
+ __le16 opcode;
};
#define HCI_FLT_TYPE_BITS 31
@@ -825,15 +923,15 @@ struct hci_dev_info {
struct hci_conn_info {
__u16 handle;
bdaddr_t bdaddr;
- __u8 type;
- __u8 out;
- __u16 state;
- __u32 link_mode;
+ __u8 type;
+ __u8 out;
+ __u16 state;
+ __u32 link_mode;
};
struct hci_dev_req {
- __u16 dev_id;
- __u32 dev_opt;
+ __u16 dev_id;
+ __u32 dev_opt;
};
struct hci_dev_list_req {
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 8f67c8a7169b..ea13baa3851b 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -71,7 +71,10 @@ struct hci_dev {
__u16 id;
__u8 type;
bdaddr_t bdaddr;
+ __u8 dev_name[248];
+ __u8 dev_class[3];
__u8 features[8];
+ __u8 commands[64];
__u8 hci_ver;
__u16 hci_rev;
__u16 manufacturer;
@@ -310,10 +313,12 @@ static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev,
void hci_acl_connect(struct hci_conn *conn);
void hci_acl_disconn(struct hci_conn *conn, __u8 reason);
void hci_add_sco(struct hci_conn *conn, __u16 handle);
+void hci_setup_sync(struct hci_conn *conn, __u16 handle);
struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst);
-int hci_conn_del(struct hci_conn *conn);
-void hci_conn_hash_flush(struct hci_dev *hdev);
+int hci_conn_del(struct hci_conn *conn);
+void hci_conn_hash_flush(struct hci_dev *hdev);
+void hci_conn_check_pending(struct hci_dev *hdev);
struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *src);
int hci_conn_auth(struct hci_conn *conn);
@@ -617,11 +622,11 @@ int hci_unregister_cb(struct hci_cb *hcb);
int hci_register_notifier(struct notifier_block *nb);
int hci_unregister_notifier(struct notifier_block *nb);
-int hci_send_cmd(struct hci_dev *hdev, __u16 ogf, __u16 ocf, __u32 plen, void *param);
+int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param);
int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags);
int hci_send_sco(struct hci_conn *conn, struct sk_buff *skb);
-void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 ogf, __u16 ocf);
+void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode);
void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data);
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 70e70f5d3dd6..73e115bc12dd 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -29,7 +29,8 @@
#define L2CAP_DEFAULT_MTU 672
#define L2CAP_DEFAULT_FLUSH_TO 0xFFFF
-#define L2CAP_CONN_TIMEOUT (HZ * 40)
+#define L2CAP_CONN_TIMEOUT (40000) /* 40 seconds */
+#define L2CAP_INFO_TIMEOUT (4000) /* 4 seconds */
/* L2CAP socket address */
struct sockaddr_l2 {
@@ -148,6 +149,19 @@ struct l2cap_conf_opt {
#define L2CAP_CONF_MAX_SIZE 22
+struct l2cap_conf_rfc {
+ __u8 mode;
+ __u8 txwin_size;
+ __u8 max_transmit;
+ __le16 retrans_timeout;
+ __le16 monitor_timeout;
+ __le16 max_pdu_size;
+} __attribute__ ((packed));
+
+#define L2CAP_MODE_BASIC 0x00
+#define L2CAP_MODE_RETRANS 0x01
+#define L2CAP_MODE_FLOWCTL 0x02
+
struct l2cap_disconn_req {
__le16 dcid;
__le16 scid;
@@ -160,7 +174,6 @@ struct l2cap_disconn_rsp {
struct l2cap_info_req {
__le16 type;
- __u8 data[0];
} __attribute__ ((packed));
struct l2cap_info_rsp {
@@ -192,6 +205,13 @@ struct l2cap_conn {
unsigned int mtu;
+ __u32 feat_mask;
+
+ __u8 info_state;
+ __u8 info_ident;
+
+ struct timer_list info_timer;
+
spinlock_t lock;
struct sk_buff *rx_skb;
@@ -202,6 +222,9 @@ struct l2cap_conn {
struct l2cap_chan_list chan_list;
};
+#define L2CAP_INFO_CL_MTU_REQ_SENT 0x01
+#define L2CAP_INFO_FEAT_MASK_REQ_SENT 0x02
+
/* ----- L2CAP channel and socket info ----- */
#define l2cap_pi(sk) ((struct l2cap_pinfo *) sk)
@@ -221,7 +244,6 @@ struct l2cap_pinfo {
__u8 conf_len;
__u8 conf_state;
__u8 conf_retry;
- __u16 conf_mtu;
__u8 ident;
@@ -232,10 +254,11 @@ struct l2cap_pinfo {
struct sock *prev_c;
};
-#define L2CAP_CONF_REQ_SENT 0x01
-#define L2CAP_CONF_INPUT_DONE 0x02
-#define L2CAP_CONF_OUTPUT_DONE 0x04
-#define L2CAP_CONF_MAX_RETRIES 2
+#define L2CAP_CONF_REQ_SENT 0x01
+#define L2CAP_CONF_INPUT_DONE 0x02
+#define L2CAP_CONF_OUTPUT_DONE 0x04
+
+#define L2CAP_CONF_MAX_RETRIES 2
void l2cap_load(void);
diff --git a/include/net/dst.h b/include/net/dst.h
index e9ff4a4caef9..2f65e894b829 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -143,6 +143,13 @@ static inline void dst_hold(struct dst_entry * dst)
atomic_inc(&dst->__refcnt);
}
+static inline void dst_use(struct dst_entry *dst, unsigned long time)
+{
+ dst_hold(dst);
+ dst->__use++;
+ dst->lastuse = time;
+}
+
static inline
struct dst_entry * dst_clone(struct dst_entry * dst)
{
diff --git a/include/net/esp.h b/include/net/esp.h
index c1bc529809da..c05f529bff28 100644
--- a/include/net/esp.h
+++ b/include/net/esp.h
@@ -3,7 +3,7 @@
#include <linux/crypto.h>
#include <net/xfrm.h>
-#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
#define ESP_NUM_FAST_SG 4
diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h
index 017aebd90683..41a301e38643 100644
--- a/include/net/fib_rules.h
+++ b/include/net/fib_rules.h
@@ -107,4 +107,7 @@ extern int fib_rules_unregister(struct fib_rules_ops *);
extern int fib_rules_lookup(struct fib_rules_ops *,
struct flowi *, int flags,
struct fib_lookup_arg *);
+extern int fib_default_rule_add(struct fib_rules_ops *,
+ u32 pref, u32 table,
+ u32 flags);
#endif
diff --git a/include/net/inet_common.h b/include/net/inet_common.h
index 227adcbdfec8..38d5a1e9980d 100644
--- a/include/net/inet_common.h
+++ b/include/net/inet_common.h
@@ -13,9 +13,6 @@ struct sock;
struct sockaddr;
struct socket;
-extern void inet_remove_sock(struct sock *sk1);
-extern void inet_put_sock(unsigned short num,
- struct sock *sk);
extern int inet_release(struct socket *sock);
extern int inet_stream_connect(struct socket *sock,
struct sockaddr * uaddr,
@@ -30,7 +27,6 @@ extern int inet_sendmsg(struct kiocb *iocb,
struct msghdr *msg,
size_t size);
extern int inet_shutdown(struct socket *sock, int how);
-extern unsigned int inet_poll(struct file * file, struct socket *sock, struct poll_table_struct *wait);
extern int inet_listen(struct socket *sock, int backlog);
extern void inet_sock_destruct(struct sock *sk);
diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h
new file mode 100644
index 000000000000..954def408975
--- /dev/null
+++ b/include/net/inet_frag.h
@@ -0,0 +1,67 @@
+#ifndef __NET_FRAG_H__
+#define __NET_FRAG_H__
+
+struct inet_frag_queue {
+ struct hlist_node list;
+ struct list_head lru_list; /* lru list member */
+ spinlock_t lock;
+ atomic_t refcnt;
+ struct timer_list timer; /* when will this queue expire? */
+ struct sk_buff *fragments; /* list of received fragments */
+ ktime_t stamp;
+ int len; /* total length of orig datagram */
+ int meat;
+ __u8 last_in; /* first/last segment arrived? */
+
+#define COMPLETE 4
+#define FIRST_IN 2
+#define LAST_IN 1
+};
+
+#define INETFRAGS_HASHSZ 64
+
+struct inet_frags_ctl {
+ int high_thresh;
+ int low_thresh;
+ int timeout;
+ int secret_interval;
+};
+
+struct inet_frags {
+ struct list_head lru_list;
+ struct hlist_head hash[INETFRAGS_HASHSZ];
+ rwlock_t lock;
+ u32 rnd;
+ int nqueues;
+ int qsize;
+ atomic_t mem;
+ struct timer_list secret_timer;
+ struct inet_frags_ctl *ctl;
+
+ unsigned int (*hashfn)(struct inet_frag_queue *);
+ void (*constructor)(struct inet_frag_queue *q,
+ void *arg);
+ void (*destructor)(struct inet_frag_queue *);
+ void (*skb_free)(struct sk_buff *);
+ int (*match)(struct inet_frag_queue *q,
+ void *arg);
+ void (*frag_expire)(unsigned long data);
+};
+
+void inet_frags_init(struct inet_frags *);
+void inet_frags_fini(struct inet_frags *);
+
+void inet_frag_kill(struct inet_frag_queue *q, struct inet_frags *f);
+void inet_frag_destroy(struct inet_frag_queue *q,
+ struct inet_frags *f, int *work);
+int inet_frag_evictor(struct inet_frags *f);
+struct inet_frag_queue *inet_frag_find(struct inet_frags *f, void *key,
+ unsigned int hash);
+
+static inline void inet_frag_put(struct inet_frag_queue *q, struct inet_frags *f)
+{
+ if (atomic_dec_and_test(&q->refcnt))
+ inet_frag_destroy(q, f, NULL);
+}
+
+#endif
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index 8228b57eb18f..469216d93663 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -23,10 +23,10 @@
#include <linux/spinlock.h>
#include <linux/types.h>
#include <linux/wait.h>
+#include <linux/vmalloc.h>
#include <net/inet_connection_sock.h>
#include <net/inet_sock.h>
-#include <net/route.h>
#include <net/sock.h>
#include <net/tcp_states.h>
@@ -38,7 +38,6 @@
* I'll experiment with dynamic table growth later.
*/
struct inet_ehash_bucket {
- rwlock_t lock;
struct hlist_head chain;
struct hlist_head twchain;
};
@@ -101,6 +100,9 @@ struct inet_hashinfo {
* TIME_WAIT sockets use a separate chain (twchain).
*/
struct inet_ehash_bucket *ehash;
+ rwlock_t *ehash_locks;
+ unsigned int ehash_size;
+ unsigned int ehash_locks_mask;
/* Ok, let's try this, I give up, we do need a local binding
* TCP hash as well as the others for fast bind/connect.
@@ -108,7 +110,7 @@ struct inet_hashinfo {
struct inet_bind_hashbucket *bhash;
unsigned int bhash_size;
- unsigned int ehash_size;
+ /* Note : 4 bytes padding on 64 bit arches */
/* All sockets in TCP_LISTEN state will be in here. This is the only
* table where wildcard'd TCP sockets can exist. Hash function here
@@ -135,6 +137,62 @@ static inline struct inet_ehash_bucket *inet_ehash_bucket(
return &hashinfo->ehash[hash & (hashinfo->ehash_size - 1)];
}
+static inline rwlock_t *inet_ehash_lockp(
+ struct inet_hashinfo *hashinfo,
+ unsigned int hash)
+{
+ return &hashinfo->ehash_locks[hash & hashinfo->ehash_locks_mask];
+}
+
+static inline int inet_ehash_locks_alloc(struct inet_hashinfo *hashinfo)
+{
+ unsigned int i, size = 256;
+#if defined(CONFIG_PROVE_LOCKING)
+ unsigned int nr_pcpus = 2;
+#else
+ unsigned int nr_pcpus = num_possible_cpus();
+#endif
+ if (nr_pcpus >= 4)
+ size = 512;
+ if (nr_pcpus >= 8)
+ size = 1024;
+ if (nr_pcpus >= 16)
+ size = 2048;
+ if (nr_pcpus >= 32)
+ size = 4096;
+ if (sizeof(rwlock_t) != 0) {
+#ifdef CONFIG_NUMA
+ if (size * sizeof(rwlock_t) > PAGE_SIZE)
+ hashinfo->ehash_locks = vmalloc(size * sizeof(rwlock_t));
+ else
+#endif
+ hashinfo->ehash_locks = kmalloc(size * sizeof(rwlock_t),
+ GFP_KERNEL);
+ if (!hashinfo->ehash_locks)
+ return ENOMEM;
+ for (i = 0; i < size; i++)
+ rwlock_init(&hashinfo->ehash_locks[i]);
+ }
+ hashinfo->ehash_locks_mask = size - 1;
+ return 0;
+}
+
+static inline void inet_ehash_locks_free(struct inet_hashinfo *hashinfo)
+{
+ if (hashinfo->ehash_locks) {
+#ifdef CONFIG_NUMA
+ unsigned int size = (hashinfo->ehash_locks_mask + 1) *
+ sizeof(rwlock_t);
+ if (size > PAGE_SIZE)
+ vfree(hashinfo->ehash_locks);
+ else
+#else
+ kfree(hashinfo->ehash_locks);
+#endif
+ hashinfo->ehash_locks = NULL;
+ }
+}
+
extern struct inet_bind_bucket *
inet_bind_bucket_create(struct kmem_cache *cachep,
struct inet_bind_hashbucket *head,
@@ -223,7 +281,7 @@ static inline void __inet_hash(struct inet_hashinfo *hashinfo,
sk->sk_hash = inet_sk_ehashfn(sk);
head = inet_ehash_bucket(hashinfo, sk->sk_hash);
list = &head->chain;
- lock = &head->lock;
+ lock = inet_ehash_lockp(hashinfo, sk->sk_hash);
write_lock(lock);
}
__sk_add_node(sk, list);
@@ -254,7 +312,7 @@ static inline void inet_unhash(struct inet_hashinfo *hashinfo, struct sock *sk)
inet_listen_wlock(hashinfo);
lock = &hashinfo->lhash_lock;
} else {
- lock = &inet_ehash_bucket(hashinfo, sk->sk_hash)->lock;
+ lock = inet_ehash_lockp(hashinfo, sk->sk_hash);
write_lock_bh(lock);
}
@@ -266,11 +324,6 @@ out:
wake_up(&hashinfo->lhash_wait);
}
-static inline int inet_iif(const struct sk_buff *skb)
-{
- return ((struct rtable *)skb->dst)->rt_iif;
-}
-
extern struct sock *__inet_lookup_listener(struct inet_hashinfo *hashinfo,
const __be32 daddr,
const unsigned short hnum,
@@ -360,9 +413,10 @@ static inline struct sock *
*/
unsigned int hash = inet_ehashfn(daddr, hnum, saddr, sport);
struct inet_ehash_bucket *head = inet_ehash_bucket(hashinfo, hash);
+ rwlock_t *lock = inet_ehash_lockp(hashinfo, hash);
prefetch(head->chain.first);
- read_lock(&head->lock);
+ read_lock(lock);
sk_for_each(sk, node, &head->chain) {
if (INET_MATCH(sk, hash, acookie, saddr, daddr, ports, dif))
goto hit; /* You sunk my battleship! */
@@ -375,7 +429,7 @@ static inline struct sock *
}
sk = NULL;
out:
- read_unlock(&head->lock);
+ read_unlock(lock);
return sk;
hit:
sock_hold(sk);
diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
index 62daf214931f..70013c5f4e59 100644
--- a/include/net/inet_sock.h
+++ b/include/net/inet_sock.h
@@ -24,6 +24,7 @@
#include <net/flow.h>
#include <net/sock.h>
#include <net/request_sock.h>
+#include <net/route.h>
/** struct ip_options - IP Options
*
@@ -190,4 +191,10 @@ static inline int inet_sk_ehashfn(const struct sock *sk)
return inet_ehashfn(laddr, lport, faddr, fport);
}
+
+static inline int inet_iif(const struct sk_buff *skb)
+{
+ return ((struct rtable *)skb->dst)->rt_iif;
+}
+
#endif /* _INET_SOCK_H */
diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h
index aa10a8178e70..ad8404b56113 100644
--- a/include/net/inetpeer.h
+++ b/include/net/inetpeer.h
@@ -22,7 +22,7 @@ struct inet_peer
__be32 v4daddr; /* peer's address */
__u16 avl_height;
__u16 ip_id_count; /* IP ID for the next packet */
- struct inet_peer *unused_next, **unused_prevp;
+ struct list_head unused;
__u32 dtime; /* the time of last use of not
* referenced entries */
atomic_t refcnt;
diff --git a/include/net/ip.h b/include/net/ip.h
index 3af3ed9d320b..840dd91b513b 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -160,6 +160,7 @@ DECLARE_SNMP_STAT(struct ipstats_mib, ip_statistics);
#define IP_INC_STATS(field) SNMP_INC_STATS(ip_statistics, field)
#define IP_INC_STATS_BH(field) SNMP_INC_STATS_BH(ip_statistics, field)
#define IP_INC_STATS_USER(field) SNMP_INC_STATS_USER(ip_statistics, field)
+#define IP_ADD_STATS_BH(field, val) SNMP_ADD_STATS_BH(ip_statistics, field, val)
DECLARE_SNMP_STAT(struct linux_mib, net_statistics);
#define NET_INC_STATS(field) SNMP_INC_STATS(net_statistics, field)
#define NET_INC_STATS_BH(field) SNMP_INC_STATS_BH(net_statistics, field)
@@ -177,10 +178,8 @@ extern int sysctl_ip_default_ttl;
extern int sysctl_ip_nonlocal_bind;
/* From ip_fragment.c */
-extern int sysctl_ipfrag_high_thresh;
-extern int sysctl_ipfrag_low_thresh;
-extern int sysctl_ipfrag_time;
-extern int sysctl_ipfrag_secret_interval;
+struct inet_frags_ctl;
+extern struct inet_frags_ctl ip4_frags_ctl;
extern int sysctl_ipfrag_max_dist;
/* From inetpeer.c */
@@ -332,9 +331,9 @@ enum ip_defrag_users
IP_DEFRAG_VS_FWD
};
-struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user);
-extern int ip_frag_nqueues;
-extern atomic_t ip_frag_mem;
+int ip_defrag(struct sk_buff *skb, u32 user);
+int ip_frag_mem(void);
+int ip_frag_nqueues(void);
/*
* Functions provided by ip_forward.c
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 8cadc77c7df4..ed514bfb61ba 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -185,6 +185,12 @@ static inline void fib_select_default(const struct flowi *flp, struct fib_result
}
#else /* CONFIG_IP_MULTIPLE_TABLES */
+extern void __init fib4_rules_init(void);
+
+#ifdef CONFIG_NET_CLS_ROUTE
+extern u32 fib_rules_tclass(struct fib_result *res);
+#endif
+
#define ip_fib_local_table fib_get_table(RT_TABLE_LOCAL)
#define ip_fib_main_table fib_get_table(RT_TABLE_MAIN)
@@ -214,15 +220,6 @@ extern __be32 __fib_res_prefsrc(struct fib_result *res);
/* Exported by fib_hash.c */
extern struct fib_table *fib_hash_init(u32 id);
-#ifdef CONFIG_IP_MULTIPLE_TABLES
-extern void __init fib4_rules_init(void);
-
-#ifdef CONFIG_NET_CLS_ROUTE
-extern u32 fib_rules_tclass(struct fib_result *res);
-#endif
-
-#endif
-
static inline void fib_combine_itag(u32 *itag, struct fib_result *res)
{
#ifdef CONFIG_NET_CLS_ROUTE
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 672564e5a81d..67ea2c0c0ab7 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -464,10 +464,10 @@ struct ip_vs_protocol {
unsigned int proto_off,
int inverse);
- int (*snat_handler)(struct sk_buff **pskb,
+ int (*snat_handler)(struct sk_buff *skb,
struct ip_vs_protocol *pp, struct ip_vs_conn *cp);
- int (*dnat_handler)(struct sk_buff **pskb,
+ int (*dnat_handler)(struct sk_buff *skb,
struct ip_vs_protocol *pp, struct ip_vs_conn *cp);
int (*csum_check)(struct sk_buff *skb, struct ip_vs_protocol *pp);
@@ -520,6 +520,10 @@ struct ip_vs_conn {
spinlock_t lock; /* lock for state transition */
volatile __u16 flags; /* status flags */
volatile __u16 state; /* state info */
+ volatile __u16 old_state; /* old state, to be used for
+ * state transition triggerd
+ * synchronization
+ */
/* Control members */
struct ip_vs_conn *control; /* Master control connection */
@@ -654,11 +658,11 @@ struct ip_vs_app
/* output hook: return false if can't linearize. diff set for TCP. */
int (*pkt_out)(struct ip_vs_app *, struct ip_vs_conn *,
- struct sk_buff **, int *diff);
+ struct sk_buff *, int *diff);
/* input hook: return false if can't linearize. diff set for TCP. */
int (*pkt_in)(struct ip_vs_app *, struct ip_vs_conn *,
- struct sk_buff **, int *diff);
+ struct sk_buff *, int *diff);
/* ip_vs_app initializer */
int (*init_conn)(struct ip_vs_app *, struct ip_vs_conn *);
@@ -832,8 +836,8 @@ register_ip_vs_app_inc(struct ip_vs_app *app, __u16 proto, __u16 port);
extern int ip_vs_app_inc_get(struct ip_vs_app *inc);
extern void ip_vs_app_inc_put(struct ip_vs_app *inc);
-extern int ip_vs_app_pkt_out(struct ip_vs_conn *, struct sk_buff **pskb);
-extern int ip_vs_app_pkt_in(struct ip_vs_conn *, struct sk_buff **pskb);
+extern int ip_vs_app_pkt_out(struct ip_vs_conn *, struct sk_buff *skb);
+extern int ip_vs_app_pkt_in(struct ip_vs_conn *, struct sk_buff *skb);
extern int ip_vs_skb_replace(struct sk_buff *skb, gfp_t pri,
char *o_buf, int o_len, char *n_buf, int n_len);
extern int ip_vs_app_init(void);
@@ -901,6 +905,10 @@ extern int ip_vs_use_count_inc(void);
extern void ip_vs_use_count_dec(void);
extern int ip_vs_control_init(void);
extern void ip_vs_control_cleanup(void);
+extern struct ip_vs_dest *
+ip_vs_find_dest(__be32 daddr, __be16 dport,
+ __be32 vaddr, __be16 vport, __u16 protocol);
+extern struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp);
/*
@@ -984,7 +992,6 @@ static inline char ip_vs_fwd_tag(struct ip_vs_conn *cp)
return fwd;
}
-extern int ip_vs_make_skb_writable(struct sk_buff **pskb, int len);
extern void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp,
struct ip_vs_conn *cp, int dir);
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 31b3f1b45a2b..ae328b680ff2 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -120,12 +120,21 @@ extern int sysctl_mld_max_msf;
SNMP_INC_STATS##modifier(statname##_statistics, (field)); \
})
+#define _DEVADD(statname, modifier, idev, field, val) \
+({ \
+ struct inet6_dev *_idev = (idev); \
+ if (likely(_idev != NULL)) \
+ SNMP_ADD_STATS##modifier((_idev)->stats.statname, (field), (val)); \
+ SNMP_ADD_STATS##modifier(statname##_statistics, (field), (val));\
+})
+
/* MIBs */
DECLARE_SNMP_STAT(struct ipstats_mib, ipv6_statistics);
#define IP6_INC_STATS(idev,field) _DEVINC(ipv6, , idev, field)
#define IP6_INC_STATS_BH(idev,field) _DEVINC(ipv6, _BH, idev, field)
#define IP6_INC_STATS_USER(idev,field) _DEVINC(ipv6, _USER, idev, field)
+#define IP6_ADD_STATS_BH(idev,field,val) _DEVADD(ipv6, _BH, idev, field, val)
DECLARE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics);
DECLARE_SNMP_STAT(struct icmpv6msg_mib, icmpv6msg_statistics);
@@ -240,7 +249,7 @@ extern int ip6_ra_control(struct sock *sk, int sel,
void (*destructor)(struct sock *));
-extern int ipv6_parse_hopopts(struct sk_buff **skbp);
+extern int ipv6_parse_hopopts(struct sk_buff *skb);
extern struct ipv6_txoptions * ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt);
extern struct ipv6_txoptions * ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
@@ -252,8 +261,8 @@ struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
extern int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb);
-extern int ip6_frag_nqueues;
-extern atomic_t ip6_frag_mem;
+int ip6_frag_nqueues(void);
+int ip6_frag_mem(void);
#define IPV6_FRAG_TIMEOUT (60*HZ) /* 60 seconds */
@@ -368,6 +377,17 @@ static inline int ipv6_prefix_equal(const struct in6_addr *a1,
prefixlen);
}
+struct inet_frag_queue;
+
+struct ip6_create_arg {
+ __be32 id;
+ struct in6_addr *src;
+ struct in6_addr *dst;
+};
+
+void ip6_frag_init(struct inet_frag_queue *q, void *a);
+int ip6_frag_match(struct inet_frag_queue *q, void *a);
+
static inline int ipv6_addr_any(const struct in6_addr *a)
{
return ((a->s6_addr32[0] | a->s6_addr32[1] |
@@ -565,10 +585,8 @@ extern int inet6_hash_connect(struct inet_timewait_death_row *death_row,
/*
* reassembly.c
*/
-extern int sysctl_ip6frag_high_thresh;
-extern int sysctl_ip6frag_low_thresh;
-extern int sysctl_ip6frag_time;
-extern int sysctl_ip6frag_secret_interval;
+struct inet_frags_ctl;
+extern struct inet_frags_ctl ip6_frags_ctl;
extern const struct proto_ops inet6_stream_ops;
extern const struct proto_ops inet6_dgram_ops;
diff --git a/include/net/irda/ircomm_tty.h b/include/net/irda/ircomm_tty.h
index 8dabdd603fe1..eea2e6152389 100644
--- a/include/net/irda/ircomm_tty.h
+++ b/include/net/irda/ircomm_tty.h
@@ -127,7 +127,6 @@ extern int ircomm_tty_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg);
extern void ircomm_tty_set_termios(struct tty_struct *tty,
struct ktermios *old_termios);
-extern hashbin_t *ircomm_tty;
#endif
diff --git a/include/net/irda/irttp.h b/include/net/irda/irttp.h
index cf80c1af5854..32c385dd9e06 100644
--- a/include/net/irda/irttp.h
+++ b/include/net/irda/irttp.h
@@ -56,7 +56,7 @@
/* Receive queue sizes */
/* Minimum of credit that the peer should hold.
- * If the peer has less credits than 9 frames, we will explicitely send
+ * If the peer has less credits than 9 frames, we will explicitly send
* him some credits (through irttp_give_credit() and a specific frame).
* Note that when we give credits it's likely that it won't be sent in
* this LAP window, but in the next one. So, we make sure that the peer
@@ -66,7 +66,7 @@
/* This is the default maximum number of credits held by the peer, so the
* default maximum number of frames he can send us before needing flow
* control answer from us (this may be negociated differently at TSAP setup).
- * We want to minimise the number of times we have to explicitely send some
+ * We want to minimise the number of times we have to explicitly send some
* credit to the peer, hoping we can piggyback it on the return data. In
* particular, it doesn't make sense for us to send credit more than once
* per LAP window.
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 5fcc4c104340..17b60391fcd6 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -706,11 +706,16 @@ enum ieee80211_hw_flags {
*
* @queues: number of available hardware transmit queues for
* data packets. WMM/QoS requires at least four.
+ *
+ * @rate_control_algorithm: rate control algorithm for this hardware.
+ * If unset (NULL), the default algorithm will be used. Must be
+ * set before calling ieee80211_register_hw().
*/
struct ieee80211_hw {
struct ieee80211_conf conf;
struct wiphy *wiphy;
struct workqueue_struct *workqueue;
+ const char *rate_control_algorithm;
void *priv;
u32 flags;
unsigned int extra_tx_headroom;
@@ -936,27 +941,11 @@ enum ieee80211_erp_change_flags {
* and remove_interface calls, i.e. while the interface with the
* given local_address is enabled.
*
- * @set_ieee8021x: Enable/disable IEEE 802.1X. This item requests wlan card
- * to pass unencrypted EAPOL-Key frames even when encryption is
- * configured. If the wlan card does not require such a configuration,
- * this function pointer can be set to NULL.
- *
- * @set_port_auth: Set port authorization state (IEEE 802.1X PAE) to be
- * authorized (@authorized=1) or unauthorized (=0). This function can be
- * used if the wlan hardware or low-level driver implements PAE.
- * mac80211 will filter frames based on authorization state in any case,
- * so this function pointer can be NULL if low-level driver does not
- * require event notification about port state changes.
- *
* @hw_scan: Ask the hardware to service the scan request, no need to start
* the scan state machine in stack.
*
* @get_stats: return low-level statistics
*
- * @set_privacy_invoked: For devices that generate their own beacons and probe
- * response or association responses this updates the state of privacy_invoked
- * returns 0 for success or an error number.
- *
* @get_sequence_counter: For devices that have internal sequence counters this
* callback allows mac80211 to access the current value of a counter.
* This callback seems not well-defined, tell us if you need it.
@@ -1029,14 +1018,9 @@ struct ieee80211_ops {
int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd,
const u8 *local_address, const u8 *address,
struct ieee80211_key_conf *key);
- int (*set_ieee8021x)(struct ieee80211_hw *hw, int use_ieee8021x);
- int (*set_port_auth)(struct ieee80211_hw *hw, u8 *addr,
- int authorized);
int (*hw_scan)(struct ieee80211_hw *hw, u8 *ssid, size_t len);
int (*get_stats)(struct ieee80211_hw *hw,
struct ieee80211_low_level_stats *stats);
- int (*set_privacy_invoked)(struct ieee80211_hw *hw,
- int privacy_invoked);
int (*get_sequence_counter)(struct ieee80211_hw *hw,
u8* addr, u8 keyidx, u8 txrx,
u32* iv32, u16* iv16);
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 93aa87d32804..5dd6d90b37eb 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -51,13 +51,12 @@ static inline struct net *copy_net_ns(unsigned long flags, struct net *net_ns)
}
#endif
+#ifdef CONFIG_NET_NS
extern void __put_net(struct net *net);
static inline struct net *get_net(struct net *net)
{
-#ifdef CONFIG_NET
atomic_inc(&net->count);
-#endif
return net;
}
@@ -75,26 +74,44 @@ static inline struct net *maybe_get_net(struct net *net)
static inline void put_net(struct net *net)
{
-#ifdef CONFIG_NET
if (atomic_dec_and_test(&net->count))
__put_net(net);
-#endif
}
static inline struct net *hold_net(struct net *net)
{
-#ifdef CONFIG_NET
atomic_inc(&net->use_count);
-#endif
return net;
}
static inline void release_net(struct net *net)
{
-#ifdef CONFIG_NET
atomic_dec(&net->use_count);
-#endif
}
+#else
+static inline struct net *get_net(struct net *net)
+{
+ return net;
+}
+
+static inline void put_net(struct net *net)
+{
+}
+
+static inline struct net *hold_net(struct net *net)
+{
+ return net;
+}
+
+static inline void release_net(struct net *net)
+{
+}
+
+static inline struct net *maybe_get_net(struct net *net)
+{
+ return net;
+}
+#endif
#define for_each_net(VAR) \
list_for_each_entry(VAR, &net_namespace_list, list)
diff --git a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
index 070d12cb4634..f703533fb4db 100644
--- a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
+++ b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
@@ -15,8 +15,7 @@ extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb,
struct net_device *out,
int (*okfn)(struct sk_buff *));
-extern unsigned int nf_ct_frag6_timeout;
-extern unsigned int nf_ct_frag6_low_thresh;
-extern unsigned int nf_ct_frag6_high_thresh;
+struct inet_frags_ctl;
+extern struct inet_frags_ctl nf_frags_ctl;
#endif /* _NF_CONNTRACK_IPV6_H*/
diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h
index 4056f5f08da1..a532e7b5ed6a 100644
--- a/include/net/netfilter/nf_conntrack_core.h
+++ b/include/net/netfilter/nf_conntrack_core.h
@@ -22,7 +22,7 @@
of connection tracking. */
extern unsigned int nf_conntrack_in(int pf,
unsigned int hooknum,
- struct sk_buff **pskb);
+ struct sk_buff *skb);
extern int nf_conntrack_init(void);
extern void nf_conntrack_cleanup(void);
@@ -60,17 +60,17 @@ nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
extern struct nf_conntrack_tuple_hash *
nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple);
-extern int __nf_conntrack_confirm(struct sk_buff **pskb);
+extern int __nf_conntrack_confirm(struct sk_buff *skb);
/* Confirm a connection: returns NF_DROP if packet must be dropped. */
-static inline int nf_conntrack_confirm(struct sk_buff **pskb)
+static inline int nf_conntrack_confirm(struct sk_buff *skb)
{
- struct nf_conn *ct = (struct nf_conn *)(*pskb)->nfct;
+ struct nf_conn *ct = (struct nf_conn *)skb->nfct;
int ret = NF_ACCEPT;
if (ct) {
if (!nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct))
- ret = __nf_conntrack_confirm(pskb);
+ ret = __nf_conntrack_confirm(skb);
nf_ct_deliver_cached_events(ct);
}
return ret;
diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h
index 0dcc4c828ce9..d7b2d5483a71 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -29,7 +29,7 @@ struct nf_conntrack_helper
/* Function to call when data passes; return verdict, or -1 to
invalidate. */
- int (*help)(struct sk_buff **pskb,
+ int (*help)(struct sk_buff *skb,
unsigned int protoff,
struct nf_conn *ct,
enum ip_conntrack_info conntrackinfo);
diff --git a/include/net/netfilter/nf_nat_core.h b/include/net/netfilter/nf_nat_core.h
index c3cd127ba4bb..f29eeb9777e0 100644
--- a/include/net/netfilter/nf_nat_core.h
+++ b/include/net/netfilter/nf_nat_core.h
@@ -10,12 +10,12 @@
extern unsigned int nf_nat_packet(struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned int hooknum,
- struct sk_buff **pskb);
+ struct sk_buff *skb);
extern int nf_nat_icmp_reply_translation(struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned int hooknum,
- struct sk_buff **pskb);
+ struct sk_buff *skb);
static inline int nf_nat_initialized(struct nf_conn *ct,
enum nf_nat_manip_type manip)
diff --git a/include/net/netfilter/nf_nat_helper.h b/include/net/netfilter/nf_nat_helper.h
index ec98ecf95fc8..58dd22687949 100644
--- a/include/net/netfilter/nf_nat_helper.h
+++ b/include/net/netfilter/nf_nat_helper.h
@@ -7,21 +7,21 @@
struct sk_buff;
/* These return true or false. */
-extern int nf_nat_mangle_tcp_packet(struct sk_buff **skb,
+extern int nf_nat_mangle_tcp_packet(struct sk_buff *skb,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned int match_offset,
unsigned int match_len,
const char *rep_buffer,
unsigned int rep_len);
-extern int nf_nat_mangle_udp_packet(struct sk_buff **skb,
+extern int nf_nat_mangle_udp_packet(struct sk_buff *skb,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned int match_offset,
unsigned int match_len,
const char *rep_buffer,
unsigned int rep_len);
-extern int nf_nat_seq_adjust(struct sk_buff **pskb,
+extern int nf_nat_seq_adjust(struct sk_buff *skb,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo);
diff --git a/include/net/netfilter/nf_nat_protocol.h b/include/net/netfilter/nf_nat_protocol.h
index 14c7b2d7263c..04578bfe23e1 100644
--- a/include/net/netfilter/nf_nat_protocol.h
+++ b/include/net/netfilter/nf_nat_protocol.h
@@ -18,7 +18,7 @@ struct nf_nat_protocol
/* Translate a packet to the target according to manip type.
Return true if succeeded. */
- int (*manip_pkt)(struct sk_buff **pskb,
+ int (*manip_pkt)(struct sk_buff *skb,
unsigned int iphdroff,
const struct nf_conntrack_tuple *tuple,
enum nf_nat_manip_type maniptype);
diff --git a/include/net/netfilter/nf_nat_rule.h b/include/net/netfilter/nf_nat_rule.h
index f9743187d57f..75d1825031d7 100644
--- a/include/net/netfilter/nf_nat_rule.h
+++ b/include/net/netfilter/nf_nat_rule.h
@@ -6,7 +6,7 @@
extern int nf_nat_rule_init(void) __init;
extern void nf_nat_rule_cleanup(void);
-extern int nf_nat_rule_find(struct sk_buff **pskb,
+extern int nf_nat_rule_find(struct sk_buff *skb,
unsigned int hooknum,
const struct net_device *in,
const struct net_device *out,
diff --git a/include/net/protocol.h b/include/net/protocol.h
index 105bf12b0c79..1166ffb4b3ec 100644
--- a/include/net/protocol.h
+++ b/include/net/protocol.h
@@ -45,7 +45,7 @@ struct net_protocol {
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
struct inet6_protocol
{
- int (*handler)(struct sk_buff **skb);
+ int (*handler)(struct sk_buff *skb);
void (*err_handler)(struct sk_buff *skb,
struct inet6_skb_parm *opt,
diff --git a/include/net/request_sock.h b/include/net/request_sock.h
index 7aed02ce2b65..cff4608179c1 100644
--- a/include/net/request_sock.h
+++ b/include/net/request_sock.h
@@ -124,23 +124,7 @@ struct request_sock_queue {
extern int reqsk_queue_alloc(struct request_sock_queue *queue,
unsigned int nr_table_entries);
-static inline struct listen_sock *reqsk_queue_yank_listen_sk(struct request_sock_queue *queue)
-{
- struct listen_sock *lopt;
-
- write_lock_bh(&queue->syn_wait_lock);
- lopt = queue->listen_opt;
- queue->listen_opt = NULL;
- write_unlock_bh(&queue->syn_wait_lock);
-
- return lopt;
-}
-
-static inline void __reqsk_queue_destroy(struct request_sock_queue *queue)
-{
- kfree(reqsk_queue_yank_listen_sk(queue));
-}
-
+extern void __reqsk_queue_destroy(struct request_sock_queue *queue);
extern void reqsk_queue_destroy(struct request_sock_queue *queue);
static inline struct request_sock *
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index a02ec9e5fea5..c9265518a378 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -316,4 +316,19 @@ static inline u32 qdisc_l2t(struct qdisc_rate_table* rtab, unsigned int pktlen)
return rtab->data[slot];
}
+#ifdef CONFIG_NET_CLS_ACT
+static inline struct sk_buff *skb_act_clone(struct sk_buff *skb, gfp_t gfp_mask)
+{
+ struct sk_buff *n = skb_clone(skb, gfp_mask);
+
+ if (n) {
+ n->tc_verd = SET_TC_VERD(n->tc_verd, 0);
+ n->tc_verd = CLR_TC_OK2MUNGE(n->tc_verd);
+ n->tc_verd = CLR_TC_MUNGED(n->tc_verd);
+ n->iif = skb->iif;
+ }
+ return n;
+}
+#endif
+
#endif
diff --git a/include/net/scm.h b/include/net/scm.h
index 423cb1d5ac25..06df126103ca 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -4,6 +4,8 @@
#include <linux/limits.h>
#include <linux/net.h>
#include <linux/security.h>
+#include <linux/pid.h>
+#include <linux/nsproxy.h>
/* Well, we should have at least one descriptor open
* to accept passed FDs 8)
@@ -54,7 +56,7 @@ static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
struct task_struct *p = current;
scm->creds.uid = p->uid;
scm->creds.gid = p->gid;
- scm->creds.pid = p->tgid;
+ scm->creds.pid = task_tgid_vnr(p);
scm->fp = NULL;
scm->seq = 0;
unix_get_peersec_dgram(sock, scm);
diff --git a/include/net/sctp/auth.h b/include/net/sctp/auth.h
index 4945954a16af..5db261a1e85e 100644
--- a/include/net/sctp/auth.h
+++ b/include/net/sctp/auth.h
@@ -88,7 +88,6 @@ static inline void sctp_auth_key_hold(struct sctp_auth_bytes *key)
void sctp_auth_key_put(struct sctp_auth_bytes *key);
struct sctp_shared_key *sctp_auth_shkey_create(__u16 key_id, gfp_t gfp);
-void sctp_auth_shkey_free(struct sctp_shared_key *sh_key);
void sctp_auth_destroy_keys(struct list_head *keys);
int sctp_auth_asoc_init_active_key(struct sctp_association *asoc, gfp_t gfp);
struct sctp_shared_key *sctp_auth_get_shkey(
@@ -104,7 +103,7 @@ struct sctp_hmac *sctp_auth_asoc_get_hmac(const struct sctp_association *asoc);
void sctp_auth_asoc_set_default_hmac(struct sctp_association *asoc,
struct sctp_hmac_algo_param *hmacs);
int sctp_auth_asoc_verify_hmac_id(const struct sctp_association *asoc,
- __u16 hmac_id);
+ __be16 hmac_id);
int sctp_auth_send_cid(sctp_cid_t chunk, const struct sctp_association *asoc);
int sctp_auth_recv_cid(sctp_cid_t chunk, const struct sctp_association *asoc);
void sctp_auth_calculate_hmac(const struct sctp_association *asoc,
diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h
index b8733364557f..c1f797673571 100644
--- a/include/net/sctp/command.h
+++ b/include/net/sctp/command.h
@@ -103,6 +103,7 @@ typedef enum {
SCTP_CMD_ASSOC_CHANGE, /* generate and send assoc_change event */
SCTP_CMD_ADAPTATION_IND, /* generate and send adaptation event */
SCTP_CMD_ASSOC_SHKEY, /* generate the association shared keys */
+ SCTP_CMD_T1_RETRAN, /* Mark for retransmission after T1 timeout */
SCTP_CMD_LAST
} sctp_verb_t;
diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h
index da8354e8e33c..f30b537d6952 100644
--- a/include/net/sctp/constants.h
+++ b/include/net/sctp/constants.h
@@ -186,6 +186,8 @@ typedef enum {
SCTP_IERROR_AUTH_BAD_HMAC,
SCTP_IERROR_AUTH_BAD_KEYID,
SCTP_IERROR_PROTO_VIOLATION,
+ SCTP_IERROR_ERROR,
+ SCTP_IERROR_ABORT,
} sctp_ierror_t;
@@ -407,6 +409,7 @@ typedef enum {
SCTP_RTXR_T3_RTX,
SCTP_RTXR_FAST_RTX,
SCTP_RTXR_PMTUD,
+ SCTP_RTXR_T1_RTX,
} sctp_retransmit_reason_t;
/* Reasons to lower cwnd. */
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 119f5a1ed499..34318a33a94c 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -65,7 +65,6 @@
#ifdef TEST_FRAME
-#undef CONFIG_PROC_FS
#undef CONFIG_SCTP_DBG_OBJCNT
#undef CONFIG_SYSCTL
#endif /* TEST_FRAME */
@@ -156,7 +155,6 @@ int sctp_primitive_ASCONF(struct sctp_association *, void *arg);
__u32 sctp_start_cksum(__u8 *ptr, __u16 count);
__u32 sctp_update_cksum(__u8 *ptr, __u16 count, __u32 cksum);
__u32 sctp_end_cksum(__u32 cksum);
-__u32 sctp_update_copy_cksum(__u8 *, __u8 *, __u16 count, __u32 cksum);
/*
* sctp/input.c
@@ -268,6 +266,7 @@ enum
SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS,
SCTP_MIB_DELAY_SACK_EXPIREDS,
SCTP_MIB_AUTOCLOSE_EXPIREDS,
+ SCTP_MIB_T1_RETRANSMITS,
SCTP_MIB_T3_RETRANSMITS,
SCTP_MIB_PMTUD_RETRANSMITS,
SCTP_MIB_FAST_RETRANSMITS,
@@ -665,6 +664,9 @@ static inline int sctp_vtag_hashfn(__u16 lport, __u16 rport, __u32 vtag)
return (h & (sctp_assoc_hashsize-1));
}
+#define sctp_for_each_hentry(epb, node, head) \
+ hlist_for_each_entry(epb, node, head, node)
+
/* Is a socket of this style? */
#define sctp_style(sk, style) __sctp_style((sk), (SCTP_SOCKET_##style))
static inline int __sctp_style(const struct sock *sk, sctp_socket_type_t style)
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index ef892e00c833..eb3113c38a94 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -100,20 +100,19 @@ struct crypto_hash;
struct sctp_bind_bucket {
unsigned short port;
unsigned short fastreuse;
- struct sctp_bind_bucket *next;
- struct sctp_bind_bucket **pprev;
+ struct hlist_node node;
struct hlist_head owner;
};
struct sctp_bind_hashbucket {
spinlock_t lock;
- struct sctp_bind_bucket *chain;
+ struct hlist_head chain;
};
/* Used for hashing all associations. */
struct sctp_hashbucket {
rwlock_t lock;
- struct sctp_ep_common *chain;
+ struct hlist_head chain;
} __attribute__((__aligned__(8)));
@@ -212,6 +211,7 @@ extern struct sctp_globals {
/* Flag to indicate if addip is enabled. */
int addip_enable;
+ int addip_noauth_enable;
/* Flag to indicate if PR-SCTP is enabled. */
int prsctp_enable;
@@ -249,6 +249,7 @@ extern struct sctp_globals {
#define sctp_local_addr_list (sctp_globals.local_addr_list)
#define sctp_local_addr_lock (sctp_globals.addr_list_lock)
#define sctp_addip_enable (sctp_globals.addip_enable)
+#define sctp_addip_noauth (sctp_globals.addip_noauth_enable)
#define sctp_prsctp_enable (sctp_globals.prsctp_enable)
#define sctp_auth_enable (sctp_globals.auth_enable)
@@ -873,10 +874,11 @@ struct sctp_transport {
* address list derived from the INIT or INIT ACK chunk, a
* number of data elements needs to be maintained including:
*/
- __u32 rtt; /* This is the most recent RTT. */
-
/* RTO : The current retransmission timeout value. */
unsigned long rto;
+ unsigned long last_rto;
+
+ __u32 rtt; /* This is the most recent RTT. */
/* RTTVAR : The current RTT variation. */
__u32 rttvar;
@@ -1184,9 +1186,7 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
int flags);
int sctp_add_bind_addr(struct sctp_bind_addr *, union sctp_addr *,
__u8 use_as_src, gfp_t gfp);
-int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *,
- void fastcall (*rcu_call)(struct rcu_head *,
- void (*func)(struct rcu_head *)));
+int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *);
int sctp_bind_addr_match(struct sctp_bind_addr *, const union sctp_addr *,
struct sctp_sock *);
union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr *bp,
@@ -1229,8 +1229,7 @@ typedef enum {
struct sctp_ep_common {
/* Fields to help us manage our entries in the hash tables. */
- struct sctp_ep_common *next;
- struct sctp_ep_common **pprev;
+ struct hlist_node node;
int hashent;
/* Runtime type information. What kind of endpoint is this? */
@@ -1541,7 +1540,6 @@ struct sctp_association {
__u8 asconf_capable; /* Does peer support ADDIP? */
__u8 prsctp_capable; /* Can peer do PR-SCTP? */
__u8 auth_capable; /* Is peer doing SCTP-AUTH? */
- __u8 addip_capable; /* Can peer do ADD-IP */
__u32 adaptation_ind; /* Adaptation Code point. */
diff --git a/include/net/sock.h b/include/net/sock.h
index 453c79d0915b..567e468d7492 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -560,6 +560,14 @@ struct proto {
void (*unhash)(struct sock *sk);
int (*get_port)(struct sock *sk, unsigned short snum);
+#ifdef CONFIG_SMP
+ /* Keeping track of sockets in use */
+ void (*inuse_add)(struct proto *prot, int inc);
+ int (*inuse_getval)(const struct proto *prot);
+ int *inuse_ptr;
+#else
+ int inuse;
+#endif
/* Memory pressure */
void (*enter_memory_pressure)(void);
atomic_t *memory_allocated; /* Current allocated memory. */
@@ -592,12 +600,38 @@ struct proto {
#ifdef SOCK_REFCNT_DEBUG
atomic_t socks;
#endif
- struct {
- int inuse;
- u8 __pad[SMP_CACHE_BYTES - sizeof(int)];
- } stats[NR_CPUS];
};
+/*
+ * Special macros to let protos use a fast version of inuse{get|add}
+ * using a static percpu variable per proto instead of an allocated one,
+ * saving one dereference.
+ * This might be changed if/when dynamic percpu vars become fast.
+ */
+#ifdef CONFIG_SMP
+# define DEFINE_PROTO_INUSE(NAME) \
+static DEFINE_PER_CPU(int, NAME##_inuse); \
+static void NAME##_inuse_add(struct proto *prot, int inc) \
+{ \
+ __get_cpu_var(NAME##_inuse) += inc; \
+} \
+ \
+static int NAME##_inuse_getval(const struct proto *prot)\
+{ \
+ int res = 0, cpu; \
+ \
+ for_each_possible_cpu(cpu) \
+ res += per_cpu(NAME##_inuse, cpu); \
+ return res; \
+}
+# define REF_PROTO_INUSE(NAME) \
+ .inuse_add = NAME##_inuse_add, \
+ .inuse_getval = NAME##_inuse_getval,
+#else
+# define DEFINE_PROTO_INUSE(NAME)
+# define REF_PROTO_INUSE(NAME)
+#endif
+
extern int proto_register(struct proto *prot, int alloc_slab);
extern void proto_unregister(struct proto *prot);
@@ -629,12 +663,29 @@ static inline void sk_refcnt_debug_release(const struct sock *sk)
/* Called with local bh disabled */
static __inline__ void sock_prot_inc_use(struct proto *prot)
{
- prot->stats[smp_processor_id()].inuse++;
+#ifdef CONFIG_SMP
+ prot->inuse_add(prot, 1);
+#else
+ prot->inuse++;
+#endif
}
static __inline__ void sock_prot_dec_use(struct proto *prot)
{
- prot->stats[smp_processor_id()].inuse--;
+#ifdef CONFIG_SMP
+ prot->inuse_add(prot, -1);
+#else
+ prot->inuse--;
+#endif
+}
+
+static __inline__ int sock_prot_inuse(struct proto *proto)
+{
+#ifdef CONFIG_SMP
+ return proto->inuse_getval(proto);
+#else
+ return proto->inuse;
+#endif
}
/* With per-bucket locks this operation is not-atomic, so that
@@ -779,7 +830,7 @@ extern void FASTCALL(release_sock(struct sock *sk));
extern struct sock *sk_alloc(struct net *net, int family,
gfp_t priority,
- struct proto *prot, int zero_it);
+ struct proto *prot);
extern void sk_free(struct sock *sk);
extern struct sock *sk_clone(const struct sock *sk,
const gfp_t priority);
@@ -905,16 +956,6 @@ static inline int sk_filter(struct sock *sk, struct sk_buff *skb)
}
/**
- * sk_filter_rcu_free: Free a socket filter
- * @rcu: rcu_head that contains the sk_filter to free
- */
-static inline void sk_filter_rcu_free(struct rcu_head *rcu)
-{
- struct sk_filter *fp = container_of(rcu, struct sk_filter, rcu);
- kfree(fp);
-}
-
-/**
* sk_filter_release: Release a socket filter
* @sk: socket
* @fp: filter to remove
@@ -922,14 +963,18 @@ static inline void sk_filter_rcu_free(struct rcu_head *rcu)
* Remove a filter from a socket and release its resources.
*/
-static inline void sk_filter_release(struct sock *sk, struct sk_filter *fp)
+static inline void sk_filter_release(struct sk_filter *fp)
+{
+ if (atomic_dec_and_test(&fp->refcnt))
+ kfree(fp);
+}
+
+static inline void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp)
{
unsigned int size = sk_filter_len(fp);
atomic_sub(size, &sk->sk_omem_alloc);
-
- if (atomic_dec_and_test(&fp->refcnt))
- call_rcu_bh(&fp->rcu, sk_filter_rcu_free);
+ sk_filter_release(fp);
}
static inline void sk_filter_charge(struct sock *sk, struct sk_filter *fp)
@@ -999,20 +1044,6 @@ static inline void sock_graft(struct sock *sk, struct socket *parent)
write_unlock_bh(&sk->sk_callback_lock);
}
-static inline void sock_copy(struct sock *nsk, const struct sock *osk)
-{
-#ifdef CONFIG_SECURITY_NETWORK
- void *sptr = nsk->sk_security;
-#endif
-
- memcpy(nsk, osk, osk->sk_prot->obj_size);
- get_net(nsk->sk_net);
-#ifdef CONFIG_SECURITY_NETWORK
- nsk->sk_security = sptr;
- security_sk_clone(osk, nsk);
-#endif
-}
-
extern int sock_i_uid(struct sock *sk);
extern unsigned long sock_i_ino(struct sock *sk);
@@ -1204,14 +1235,16 @@ static inline struct sk_buff *sk_stream_alloc_pskb(struct sock *sk,
gfp_t gfp)
{
struct sk_buff *skb;
- int hdr_len;
- hdr_len = SKB_DATA_ALIGN(sk->sk_prot->max_header);
- skb = alloc_skb_fclone(size + hdr_len, gfp);
+ skb = alloc_skb_fclone(size + sk->sk_prot->max_header, gfp);
if (skb) {
skb->truesize += mem;
if (sk_stream_wmem_schedule(sk, skb->truesize)) {
- skb_reserve(skb, hdr_len);
+ /*
+ * Make sure that we have exactly size bytes
+ * available to the caller, no more, no less.
+ */
+ skb_reserve(skb, skb_tailroom(skb) - size);
return skb;
}
__kfree_skb(skb);
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 92049e681258..d695cea7730d 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -803,7 +803,7 @@ static inline int tcp_is_cwnd_limited(const struct sock *sk, u32 in_flight)
return left <= tcp_max_burst(tp);
}
-static inline void tcp_minshall_update(struct tcp_sock *tp, int mss,
+static inline void tcp_minshall_update(struct tcp_sock *tp, unsigned int mss,
const struct sk_buff *skb)
{
if (skb->len < mss)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 77be396ca633..58dfa82889aa 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -37,6 +37,8 @@
extern struct sock *xfrm_nl;
extern u32 sysctl_xfrm_aevent_etime;
extern u32 sysctl_xfrm_aevent_rseqth;
+extern int sysctl_xfrm_larval_drop;
+extern u32 sysctl_xfrm_acq_expires;
extern struct mutex xfrm_cfg_mutex;
@@ -186,7 +188,8 @@ struct xfrm_state
/* Reference to data common to all the instances of this
* transformer. */
struct xfrm_type *type;
- struct xfrm_mode *mode;
+ struct xfrm_mode *inner_mode;
+ struct xfrm_mode *outer_mode;
/* Security context */
struct xfrm_sec_ctx *security;
@@ -228,8 +231,6 @@ struct xfrm_type;
struct xfrm_dst;
struct xfrm_policy_afinfo {
unsigned short family;
- struct xfrm_type *type_map[IPPROTO_MAX];
- struct xfrm_mode *mode_map[XFRM_MODE_MAX];
struct dst_ops *dst_ops;
void (*garbage_collect)(void);
int (*dst_lookup)(struct xfrm_dst **dst, struct flowi *fl);
@@ -255,7 +256,10 @@ extern void km_state_expired(struct xfrm_state *x, int hard, u32 pid);
extern int __xfrm_state_delete(struct xfrm_state *x);
struct xfrm_state_afinfo {
- unsigned short family;
+ unsigned int family;
+ struct module *owner;
+ struct xfrm_type *type_map[IPPROTO_MAX];
+ struct xfrm_mode *mode_map[XFRM_MODE_MAX];
int (*init_flags)(struct xfrm_state *x);
void (*init_tempsel)(struct xfrm_state *x, struct flowi *fl,
struct xfrm_tmpl *tmpl,
@@ -267,8 +271,6 @@ struct xfrm_state_afinfo {
extern int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo);
extern int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo);
-extern struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family);
-extern void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
extern void xfrm_state_delete_tunnel(struct xfrm_state *x);
@@ -295,8 +297,6 @@ struct xfrm_type
extern int xfrm_register_type(struct xfrm_type *type, unsigned short family);
extern int xfrm_unregister_type(struct xfrm_type *type, unsigned short family);
-extern struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family);
-extern void xfrm_put_type(struct xfrm_type *type);
struct xfrm_mode {
int (*input)(struct xfrm_state *x, struct sk_buff *skb);
@@ -314,14 +314,19 @@ struct xfrm_mode {
*/
int (*output)(struct xfrm_state *x,struct sk_buff *skb);
+ struct xfrm_state_afinfo *afinfo;
struct module *owner;
unsigned int encap;
+ int flags;
+};
+
+/* Flags for xfrm_mode. */
+enum {
+ XFRM_MODE_FLAG_TUNNEL = 1,
};
extern int xfrm_register_mode(struct xfrm_mode *mode, int family);
extern int xfrm_unregister_mode(struct xfrm_mode *mode, int family);
-extern struct xfrm_mode *xfrm_get_mode(unsigned int encap, int family);
-extern void xfrm_put_mode(struct xfrm_mode *mode);
struct xfrm_tmpl
{
@@ -1046,12 +1051,20 @@ extern void xfrm_replay_notify(struct xfrm_state *x, int event);
extern int xfrm_state_mtu(struct xfrm_state *x, int mtu);
extern int xfrm_init_state(struct xfrm_state *x);
extern int xfrm_output(struct sk_buff *skb);
+extern int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
+ int encap_type);
extern int xfrm4_rcv(struct sk_buff *skb);
+
+static inline int xfrm4_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
+{
+ return xfrm4_rcv_encap(skb, nexthdr, spi, 0);
+}
+
extern int xfrm4_output(struct sk_buff *skb);
extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family);
extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family);
-extern int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi);
-extern int xfrm6_rcv(struct sk_buff **pskb);
+extern int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi);
+extern int xfrm6_rcv(struct sk_buff *skb);
extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
xfrm_address_t *saddr, u8 proto);
extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family);
diff --git a/include/pcmcia/cs_types.h b/include/pcmcia/cs_types.h
index c1d1629fcd27..5f388035687d 100644
--- a/include/pcmcia/cs_types.h
+++ b/include/pcmcia/cs_types.h
@@ -21,7 +21,7 @@
#include <sys/types.h>
#endif
-#if defined(__arm__) || defined(__mips__)
+#if defined(__arm__) || defined(__mips__) || defined(__avr32__)
/* This (ioaddr_t) is exposed to userspace & hence cannot be changed. */
typedef u_int ioaddr_t;
#else
diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h
index 90ef552c42dd..f047a1fd64f8 100644
--- a/include/pcmcia/ds.h
+++ b/include/pcmcia/ds.h
@@ -184,6 +184,7 @@ struct pcmcia_device {
char * prod_id[4];
+ u64 dma_mask;
struct device dev;
#ifdef CONFIG_PCMCIA_IOCTL
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 4bea182d7116..11f39606e7d9 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -48,9 +48,9 @@
#include <linux/kref.h>
#include <linux/list.h>
#include <linux/rwsem.h>
+#include <linux/scatterlist.h>
#include <asm/atomic.h>
-#include <asm/scatterlist.h>
#include <asm/uaccess.h>
union ib_gid {
diff --git a/include/scsi/Kbuild b/include/scsi/Kbuild
deleted file mode 100644
index 744f85011f1e..000000000000
--- a/include/scsi/Kbuild
+++ /dev/null
@@ -1,4 +0,0 @@
-header-y += scsi.h
-
-unifdef-y += scsi_ioctl.h
-unifdef-y += sg.h
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index 8dda2d66b5b9..a466c2cb8955 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -36,7 +36,7 @@
#include <scsi/scsi_device.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_transport_sas.h>
-#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
struct block_device;
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index 9f8f80ab0c8b..702fcfeb37f1 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -11,13 +11,6 @@
#include <linux/types.h>
/*
- * The maximum sg list length SCSI can cope with
- * (currently must be a power of 2 between 32 and 256)
- */
-#define SCSI_MAX_PHYS_SEGMENTS MAX_PHYS_SEGMENTS
-
-
-/*
* SCSI command lengths
*/
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index 65ab5145a09b..3f47e522a1ec 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -5,6 +5,7 @@
#include <linux/list.h>
#include <linux/types.h>
#include <linux/timer.h>
+#include <linux/scatterlist.h>
struct request;
struct scatterlist;
@@ -68,7 +69,7 @@ struct scsi_cmnd {
/* These elements define the operation we ultimately want to perform */
unsigned short use_sg; /* Number of pieces of scatter-gather */
- unsigned short sglist_len; /* size of malloc'd scatter-gather list */
+ unsigned short __use_sg;
unsigned underflow; /* Return error if less than
this amount is transferred */
@@ -128,7 +129,7 @@ extern void *scsi_kmap_atomic_sg(struct scatterlist *sg, int sg_count,
extern void scsi_kunmap_atomic_sg(void *virt);
extern struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *, gfp_t);
-extern void scsi_free_sgtable(struct scatterlist *, int);
+extern void scsi_free_sgtable(struct scsi_cmnd *);
extern int scsi_dma_map(struct scsi_cmnd *cmd);
extern void scsi_dma_unmap(struct scsi_cmnd *cmd);
@@ -148,6 +149,6 @@ static inline int scsi_get_resid(struct scsi_cmnd *cmd)
}
#define scsi_for_each_sg(cmd, sg, nseg, __i) \
- for (__i = 0, sg = scsi_sglist(cmd); __i < (nseg); __i++, (sg)++)
+ for_each_sg(scsi_sglist(cmd), sg, nseg, __i)
#endif /* _SCSI_SCSI_CMND_H */
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index d5057bc338ff..66e9058357e0 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -46,6 +46,22 @@ enum scsi_device_state {
* to the scsi lld. */
};
+enum scsi_device_event {
+ SDEV_EVT_MEDIA_CHANGE = 1, /* media has changed */
+
+ SDEV_EVT_LAST = SDEV_EVT_MEDIA_CHANGE,
+ SDEV_EVT_MAXBITS = SDEV_EVT_LAST + 1
+};
+
+struct scsi_event {
+ enum scsi_device_event evt_type;
+ struct list_head node;
+
+ /* put union of data structures, for non-simple event types,
+ * here
+ */
+};
+
struct scsi_device {
struct Scsi_Host *host;
struct request_queue *request_queue;
@@ -127,6 +143,10 @@ struct scsi_device {
unsigned guess_capacity:1; /* READ_CAPACITY might be too high by 1 */
unsigned retry_hwerror:1; /* Retry HARDWARE_ERROR */
+ DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */
+ struct list_head event_list; /* asserted events */
+ struct work_struct event_work;
+
unsigned int device_blocked; /* Device returned QUEUE_FULL. */
unsigned int max_device_blocked; /* what device_blocked counts down from */
@@ -275,6 +295,11 @@ extern int scsi_test_unit_ready(struct scsi_device *sdev, int timeout,
int retries);
extern int scsi_device_set_state(struct scsi_device *sdev,
enum scsi_device_state state);
+extern struct scsi_event *sdev_evt_alloc(enum scsi_device_event evt_type,
+ gfp_t gfpflags);
+extern void sdev_evt_send(struct scsi_device *sdev, struct scsi_event *evt);
+extern void sdev_evt_send_simple(struct scsi_device *sdev,
+ enum scsi_device_event evt_type, gfp_t gfpflags);
extern int scsi_device_quiesce(struct scsi_device *sdev);
extern void scsi_device_resume(struct scsi_device *sdev);
extern void scsi_target_quiesce(struct scsi_target *);
diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h
index 44224ba4dd90..d21b8913ceb3 100644
--- a/include/scsi/scsi_eh.h
+++ b/include/scsi/scsi_eh.h
@@ -1,6 +1,8 @@
#ifndef _SCSI_SCSI_EH_H
#define _SCSI_SCSI_EH_H
+#include <linux/scatterlist.h>
+
#include <scsi/scsi_cmnd.h>
struct scsi_device;
struct Scsi_Host;
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 7d210cd6c38d..0fd4746ee39d 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -39,6 +39,9 @@ struct blk_queue_tags;
#define DISABLE_CLUSTERING 0
#define ENABLE_CLUSTERING 1
+#define DISABLE_SG_CHAINING 0
+#define ENABLE_SG_CHAINING 1
+
enum scsi_eh_timer_return {
EH_NOT_HANDLED,
EH_HANDLED,
@@ -443,6 +446,15 @@ struct scsi_host_template {
unsigned ordered_tag:1;
/*
+ * true if the low-level driver can support sg chaining. this
+ * will be removed eventually when all the drivers are
+ * converted to support sg chaining.
+ *
+ * Status: OBSOLETE
+ */
+ unsigned use_sg_chaining:1;
+
+ /*
* Countdown for host blocking with no commands outstanding
*/
unsigned int max_host_blocked;
@@ -586,6 +598,7 @@ struct Scsi_Host {
unsigned unchecked_isa_dma:1;
unsigned use_clustering:1;
unsigned use_blk_tcq:1;
+ unsigned use_sg_chaining:1;
/*
* Host has requested that no further requests come through for the
diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h
index 246ac23534bd..01480581f825 100644
--- a/include/sound/ac97_codec.h
+++ b/include/sound/ac97_codec.h
@@ -2,7 +2,7 @@
#define __SOUND_AC97_CODEC_H
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Universal interface for Audio Codec '97
*
* For more details look to AC '97 component specification revision 2.1
@@ -345,9 +345,9 @@
#define AC97_ALC650_GPIO_STATUS 0x78
#define AC97_ALC650_CLOCK 0x7a
-/* specific - Yamaha YMF753 */
-#define AC97_YMF753_DIT_CTRL2 0x66 /* DIT Control 2 */
-#define AC97_YMF753_3D_MODE_SEL 0x68 /* 3D Mode Select */
+/* specific - Yamaha YMF7x3 */
+#define AC97_YMF7X3_DIT_CTRL 0x66 /* DIT Control (YMF743) / 2 (YMF753) */
+#define AC97_YMF7X3_3D_MODE_SEL 0x68 /* 3D Mode Select */
/* specific - C-Media */
#define AC97_CM9738_VENDOR_CTRL 0x5a
diff --git a/include/sound/ad1848.h b/include/sound/ad1848.h
index b2c3f00a9b35..d04f9e78c7c1 100644
--- a/include/sound/ad1848.h
+++ b/include/sound/ad1848.h
@@ -2,7 +2,7 @@
#define __SOUND_AD1848_H
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Definitions for AD1847/AD1848/CS4248 chips
*
*
@@ -27,7 +27,7 @@
/* IO ports */
-#define AD1848P( codec, x ) ( (chip) -> port + c_d_c_AD1848##x )
+#define AD1848P( chip, x ) ( (chip) -> port + c_d_c_AD1848##x )
#define c_d_c_AD1848REGSEL 0
#define c_d_c_AD1848REG 1
@@ -154,7 +154,6 @@ struct snd_ad1848 {
#endif
spinlock_t reg_lock;
- struct mutex open_mutex;
};
/* exported functions */
diff --git a/include/sound/ainstr_gf1.h b/include/sound/ainstr_gf1.h
index 47726fe0f46d..b62b665c69c6 100644
--- a/include/sound/ainstr_gf1.h
+++ b/include/sound/ainstr_gf1.h
@@ -2,7 +2,7 @@
* Advanced Linux Sound Architecture
*
* GF1 (GUS) Patch Instrument Format
- * Copyright (c) 1994-99 by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 1994-99 by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/include/sound/ainstr_iw.h b/include/sound/ainstr_iw.h
index 251feaf1b388..11bd25082600 100644
--- a/include/sound/ainstr_iw.h
+++ b/include/sound/ainstr_iw.h
@@ -2,7 +2,7 @@
* Advanced Linux Sound Architecture
*
* InterWave FFFF Instrument Format
- * Copyright (c) 1994-99 by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 1994-99 by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/include/sound/ainstr_simple.h b/include/sound/ainstr_simple.h
index 5eead12e58ae..da08e7287557 100644
--- a/include/sound/ainstr_simple.h
+++ b/include/sound/ainstr_simple.h
@@ -2,7 +2,7 @@
* Advanced Linux Sound Architecture
*
* Simple (MOD player) Instrument Format
- * Copyright (c) 1994-99 by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 1994-99 by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/include/sound/ak4114.h b/include/sound/ak4114.h
index d647dae912b9..4e80d3fe7381 100644
--- a/include/sound/ak4114.h
+++ b/include/sound/ak4114.h
@@ -3,7 +3,7 @@
/*
* Routines for Asahi Kasei AK4114
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>,
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/include/sound/ak4117.h b/include/sound/ak4117.h
index d650d52e3d29..1e8178171baf 100644
--- a/include/sound/ak4117.h
+++ b/include/sound/ak4117.h
@@ -3,7 +3,7 @@
/*
* Routines for Asahi Kasei AK4117
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>,
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/include/sound/ak4531_codec.h b/include/sound/ak4531_codec.h
index fb30faab43a8..575296cf7987 100644
--- a/include/sound/ak4531_codec.h
+++ b/include/sound/ak4531_codec.h
@@ -2,7 +2,7 @@
#define __SOUND_AK4531_CODEC_H
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Universal interface for Audio Codec '97
*
* For more details look to AC '97 component specification revision 2.1
diff --git a/include/sound/ak4xxx-adda.h b/include/sound/ak4xxx-adda.h
index fd0a6c46f497..891cf1aea8b1 100644
--- a/include/sound/ak4xxx-adda.h
+++ b/include/sound/ak4xxx-adda.h
@@ -5,7 +5,7 @@
* ALSA driver for AK4524 / AK4528 / AK4529 / AK4355 / AK4381
* AD and DA converters
*
- * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz>
*
* 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
diff --git a/include/sound/asequencer.h b/include/sound/asequencer.h
index 3f2f4042a20d..64daccbe8b29 100644
--- a/include/sound/asequencer.h
+++ b/include/sound/asequencer.h
@@ -1,7 +1,7 @@
/*
* Main header file for the ALSA sequencer
* Copyright (c) 1998-1999 by Frank van de Pol <fvdpol@coil.demon.nl>
- * (c) 1998-1999 by Jaroslav Kysela <perex@suse.cz>
+ * (c) 1998-1999 by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/include/sound/asound.h b/include/sound/asound.h
index c1621c650a9a..af9d11d315e9 100644
--- a/include/sound/asound.h
+++ b/include/sound/asound.h
@@ -1,6 +1,6 @@
/*
* Advanced Linux Sound Architecture - ALSA - Driver
- * Copyright (c) 1994-2003 by Jaroslav Kysela <perex@suse.cz>,
+ * Copyright (c) 1994-2003 by Jaroslav Kysela <perex@perex.cz>,
* Abramo Bagnara <abramo@alsa-project.org>
*
*
@@ -92,6 +92,7 @@ enum {
SNDRV_HWDEP_IFACE_USX2Y_PCM, /* Tascam US122, US224 & US428 rawusb pcm */
SNDRV_HWDEP_IFACE_PCXHR, /* Digigram PCXHR */
SNDRV_HWDEP_IFACE_SB_RC, /* SB Extigy/Audigy2NX remote control */
+ SNDRV_HWDEP_IFACE_HDA, /* HD-audio */
/* Don't forget to change the following: */
SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_SB_RC
diff --git a/include/sound/asound_fm.h b/include/sound/asound_fm.h
index 956fdc23c595..8fbcab7cc73b 100644
--- a/include/sound/asound_fm.h
+++ b/include/sound/asound_fm.h
@@ -5,7 +5,7 @@
* Advanced Linux Sound Architecture - ALSA
*
* Interface file between ALSA driver & user space
- * Copyright (c) 1994-98 by Jaroslav Kysela <perex@suse.cz>,
+ * Copyright (c) 1994-98 by Jaroslav Kysela <perex@perex.cz>,
* 4Front Technologies
*
* Direct FM control
diff --git a/include/sound/asoundef.h b/include/sound/asoundef.h
index 58c9ef3d1825..024ce62f7d16 100644
--- a/include/sound/asoundef.h
+++ b/include/sound/asoundef.h
@@ -3,7 +3,7 @@
/*
* Advanced Linux Sound Architecture - ALSA - Driver
- * Copyright (c) 1994-2000 by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 1994-2000 by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/include/sound/control.h b/include/sound/control.h
index 72e759f619b1..e79baa63912f 100644
--- a/include/sound/control.h
+++ b/include/sound/control.h
@@ -3,7 +3,7 @@
/*
* Header file for control interface
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -161,4 +161,12 @@ static inline struct snd_ctl_elem_id *snd_ctl_build_ioff(struct snd_ctl_elem_id
return dst_id;
}
+/*
+ * Frequently used control callbacks
+ */
+int snd_ctl_boolean_mono_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo);
+int snd_ctl_boolean_stereo_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo);
+
#endif /* __SOUND_CONTROL_H */
diff --git a/include/sound/core.h b/include/sound/core.h
index 4b9e609975ab..6954836487ed 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -3,7 +3,7 @@
/*
* Main header file for the ALSA driver
- * Copyright (c) 1994-2001 by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 1994-2001 by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/include/sound/cs4231-regs.h b/include/sound/cs4231-regs.h
new file mode 100644
index 000000000000..f1490265c9b8
--- /dev/null
+++ b/include/sound/cs4231-regs.h
@@ -0,0 +1,180 @@
+#ifndef __SOUND_CS4231_REGS_H
+#define __SOUND_CS4231_REGS_H
+
+/*
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
+ * Definitions for CS4231 & InterWave chips & compatible chips registers
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* IO ports */
+
+#define CS4231P(x) (c_d_c_CS4231##x)
+
+#define c_d_c_CS4231REGSEL 0
+#define c_d_c_CS4231REG 1
+#define c_d_c_CS4231STATUS 2
+#define c_d_c_CS4231PIO 3
+
+/* codec registers */
+
+#define CS4231_LEFT_INPUT 0x00 /* left input control */
+#define CS4231_RIGHT_INPUT 0x01 /* right input control */
+#define CS4231_AUX1_LEFT_INPUT 0x02 /* left AUX1 input control */
+#define CS4231_AUX1_RIGHT_INPUT 0x03 /* right AUX1 input control */
+#define CS4231_AUX2_LEFT_INPUT 0x04 /* left AUX2 input control */
+#define CS4231_AUX2_RIGHT_INPUT 0x05 /* right AUX2 input control */
+#define CS4231_LEFT_OUTPUT 0x06 /* left output control register */
+#define CS4231_RIGHT_OUTPUT 0x07 /* right output control register */
+#define CS4231_PLAYBK_FORMAT 0x08 /* clock and data format - playback - bits 7-0 MCE */
+#define CS4231_IFACE_CTRL 0x09 /* interface control - bits 7-2 MCE */
+#define CS4231_PIN_CTRL 0x0a /* pin control */
+#define CS4231_TEST_INIT 0x0b /* test and initialization */
+#define CS4231_MISC_INFO 0x0c /* miscellaneaous information */
+#define CS4231_LOOPBACK 0x0d /* loopback control */
+#define CS4231_PLY_UPR_CNT 0x0e /* playback upper base count */
+#define CS4231_PLY_LWR_CNT 0x0f /* playback lower base count */
+#define CS4231_ALT_FEATURE_1 0x10 /* alternate #1 feature enable */
+#define AD1845_AF1_MIC_LEFT 0x10 /* alternate #1 feature + MIC left */
+#define CS4231_ALT_FEATURE_2 0x11 /* alternate #2 feature enable */
+#define AD1845_AF2_MIC_RIGHT 0x11 /* alternate #2 feature + MIC right */
+#define CS4231_LEFT_LINE_IN 0x12 /* left line input control */
+#define CS4231_RIGHT_LINE_IN 0x13 /* right line input control */
+#define CS4231_TIMER_LOW 0x14 /* timer low byte */
+#define CS4231_TIMER_HIGH 0x15 /* timer high byte */
+#define CS4231_LEFT_MIC_INPUT 0x16 /* left MIC input control register (InterWave only) */
+#define AD1845_UPR_FREQ_SEL 0x16 /* upper byte of frequency select */
+#define CS4231_RIGHT_MIC_INPUT 0x17 /* right MIC input control register (InterWave only) */
+#define AD1845_LWR_FREQ_SEL 0x17 /* lower byte of frequency select */
+#define CS4236_EXT_REG 0x17 /* extended register access */
+#define CS4231_IRQ_STATUS 0x18 /* irq status register */
+#define CS4231_LINE_LEFT_OUTPUT 0x19 /* left line output control register (InterWave only) */
+#define CS4231_VERSION 0x19 /* CS4231(A) - version values */
+#define CS4231_MONO_CTRL 0x1a /* mono input/output control */
+#define CS4231_LINE_RIGHT_OUTPUT 0x1b /* right line output control register (InterWave only) */
+#define AD1845_PWR_DOWN 0x1b /* power down control */
+#define CS4235_LEFT_MASTER 0x1b /* left master output control */
+#define CS4231_REC_FORMAT 0x1c /* clock and data format - record - bits 7-0 MCE */
+#define CS4231_PLY_VAR_FREQ 0x1d /* playback variable frequency */
+#define AD1845_CLOCK 0x1d /* crystal clock select and total power down */
+#define CS4235_RIGHT_MASTER 0x1d /* right master output control */
+#define CS4231_REC_UPR_CNT 0x1e /* record upper count */
+#define CS4231_REC_LWR_CNT 0x1f /* record lower count */
+
+/* definitions for codec register select port - CODECP( REGSEL ) */
+
+#define CS4231_INIT 0x80 /* CODEC is initializing */
+#define CS4231_MCE 0x40 /* mode change enable */
+#define CS4231_TRD 0x20 /* transfer request disable */
+
+/* definitions for codec status register - CODECP( STATUS ) */
+
+#define CS4231_GLOBALIRQ 0x01 /* IRQ is active */
+
+/* definitions for codec irq status */
+
+#define CS4231_PLAYBACK_IRQ 0x10
+#define CS4231_RECORD_IRQ 0x20
+#define CS4231_TIMER_IRQ 0x40
+#define CS4231_ALL_IRQS 0x70
+#define CS4231_REC_UNDERRUN 0x08
+#define CS4231_REC_OVERRUN 0x04
+#define CS4231_PLY_OVERRUN 0x02
+#define CS4231_PLY_UNDERRUN 0x01
+
+/* definitions for CS4231_LEFT_INPUT and CS4231_RIGHT_INPUT registers */
+
+#define CS4231_ENABLE_MIC_GAIN 0x20
+
+#define CS4231_MIXS_LINE 0x00
+#define CS4231_MIXS_AUX1 0x40
+#define CS4231_MIXS_MIC 0x80
+#define CS4231_MIXS_ALL 0xc0
+
+/* definitions for clock and data format register - CS4231_PLAYBK_FORMAT */
+
+#define CS4231_LINEAR_8 0x00 /* 8-bit unsigned data */
+#define CS4231_ALAW_8 0x60 /* 8-bit A-law companded */
+#define CS4231_ULAW_8 0x20 /* 8-bit U-law companded */
+#define CS4231_LINEAR_16 0x40 /* 16-bit twos complement data - little endian */
+#define CS4231_LINEAR_16_BIG 0xc0 /* 16-bit twos complement data - big endian */
+#define CS4231_ADPCM_16 0xa0 /* 16-bit ADPCM */
+#define CS4231_STEREO 0x10 /* stereo mode */
+/* bits 3-1 define frequency divisor */
+#define CS4231_XTAL1 0x00 /* 24.576 crystal */
+#define CS4231_XTAL2 0x01 /* 16.9344 crystal */
+
+/* definitions for interface control register - CS4231_IFACE_CTRL */
+
+#define CS4231_RECORD_PIO 0x80 /* record PIO enable */
+#define CS4231_PLAYBACK_PIO 0x40 /* playback PIO enable */
+#define CS4231_CALIB_MODE 0x18 /* calibration mode bits */
+#define CS4231_AUTOCALIB 0x08 /* auto calibrate */
+#define CS4231_SINGLE_DMA 0x04 /* use single DMA channel */
+#define CS4231_RECORD_ENABLE 0x02 /* record enable */
+#define CS4231_PLAYBACK_ENABLE 0x01 /* playback enable */
+
+/* definitions for pin control register - CS4231_PIN_CTRL */
+
+#define CS4231_IRQ_ENABLE 0x02 /* enable IRQ */
+#define CS4231_XCTL1 0x40 /* external control #1 */
+#define CS4231_XCTL0 0x80 /* external control #0 */
+
+/* definitions for test and init register - CS4231_TEST_INIT */
+
+#define CS4231_CALIB_IN_PROGRESS 0x20 /* auto calibrate in progress */
+#define CS4231_DMA_REQUEST 0x10 /* DMA request in progress */
+
+/* definitions for misc control register - CS4231_MISC_INFO */
+
+#define CS4231_MODE2 0x40 /* MODE 2 */
+#define CS4231_IW_MODE3 0x6c /* MODE 3 - InterWave enhanced mode */
+#define CS4231_4236_MODE3 0xe0 /* MODE 3 - CS4236+ enhanced mode */
+
+/* definitions for alternate feature 1 register - CS4231_ALT_FEATURE_1 */
+
+#define CS4231_DACZ 0x01 /* zero DAC when underrun */
+#define CS4231_TIMER_ENABLE 0x40 /* codec timer enable */
+#define CS4231_OLB 0x80 /* output level bit */
+
+/* definitions for Extended Registers - CS4236+ */
+
+#define CS4236_REG(i23val) (((i23val << 2) & 0x10) | ((i23val >> 4) & 0x0f))
+#define CS4236_I23VAL(reg) ((((reg)&0xf) << 4) | (((reg)&0x10) >> 2) | 0x8)
+
+#define CS4236_LEFT_LINE 0x08 /* left LINE alternate volume */
+#define CS4236_RIGHT_LINE 0x18 /* right LINE alternate volume */
+#define CS4236_LEFT_MIC 0x28 /* left MIC volume */
+#define CS4236_RIGHT_MIC 0x38 /* right MIC volume */
+#define CS4236_LEFT_MIX_CTRL 0x48 /* synthesis and left input mixer control */
+#define CS4236_RIGHT_MIX_CTRL 0x58 /* right input mixer control */
+#define CS4236_LEFT_FM 0x68 /* left FM volume */
+#define CS4236_RIGHT_FM 0x78 /* right FM volume */
+#define CS4236_LEFT_DSP 0x88 /* left DSP serial port volume */
+#define CS4236_RIGHT_DSP 0x98 /* right DSP serial port volume */
+#define CS4236_RIGHT_LOOPBACK 0xa8 /* right loopback monitor volume */
+#define CS4236_DAC_MUTE 0xb8 /* DAC mute and IFSE enable */
+#define CS4236_ADC_RATE 0xc8 /* indenpendent ADC sample frequency */
+#define CS4236_DAC_RATE 0xd8 /* indenpendent DAC sample frequency */
+#define CS4236_LEFT_MASTER 0xe8 /* left master digital audio volume */
+#define CS4236_RIGHT_MASTER 0xf8 /* right master digital audio volume */
+#define CS4236_LEFT_WAVE 0x0c /* left wavetable serial port volume */
+#define CS4236_RIGHT_WAVE 0x1c /* right wavetable serial port volume */
+#define CS4236_VERSION 0x9c /* chip version and ID */
+
+#endif /* __SOUND_CS4231_REGS_H */
diff --git a/include/sound/cs4231.h b/include/sound/cs4231.h
index ab51ce1ba9a5..66055d702aa3 100644
--- a/include/sound/cs4231.h
+++ b/include/sound/cs4231.h
@@ -2,7 +2,7 @@
#define __SOUND_CS4231_H
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Definitions for CS4231 & InterWave chips & compatible chips
*
*
@@ -26,160 +26,7 @@
#include "pcm.h"
#include "timer.h"
-/* IO ports */
-
-#define CS4231P(x) (c_d_c_CS4231##x)
-
-#define c_d_c_CS4231REGSEL 0
-#define c_d_c_CS4231REG 1
-#define c_d_c_CS4231STATUS 2
-#define c_d_c_CS4231PIO 3
-
-/* codec registers */
-
-#define CS4231_LEFT_INPUT 0x00 /* left input control */
-#define CS4231_RIGHT_INPUT 0x01 /* right input control */
-#define CS4231_AUX1_LEFT_INPUT 0x02 /* left AUX1 input control */
-#define CS4231_AUX1_RIGHT_INPUT 0x03 /* right AUX1 input control */
-#define CS4231_AUX2_LEFT_INPUT 0x04 /* left AUX2 input control */
-#define CS4231_AUX2_RIGHT_INPUT 0x05 /* right AUX2 input control */
-#define CS4231_LEFT_OUTPUT 0x06 /* left output control register */
-#define CS4231_RIGHT_OUTPUT 0x07 /* right output control register */
-#define CS4231_PLAYBK_FORMAT 0x08 /* clock and data format - playback - bits 7-0 MCE */
-#define CS4231_IFACE_CTRL 0x09 /* interface control - bits 7-2 MCE */
-#define CS4231_PIN_CTRL 0x0a /* pin control */
-#define CS4231_TEST_INIT 0x0b /* test and initialization */
-#define CS4231_MISC_INFO 0x0c /* miscellaneaous information */
-#define CS4231_LOOPBACK 0x0d /* loopback control */
-#define CS4231_PLY_UPR_CNT 0x0e /* playback upper base count */
-#define CS4231_PLY_LWR_CNT 0x0f /* playback lower base count */
-#define CS4231_ALT_FEATURE_1 0x10 /* alternate #1 feature enable */
-#define AD1845_AF1_MIC_LEFT 0x10 /* alternate #1 feature + MIC left */
-#define CS4231_ALT_FEATURE_2 0x11 /* alternate #2 feature enable */
-#define AD1845_AF2_MIC_RIGHT 0x11 /* alternate #2 feature + MIC right */
-#define CS4231_LEFT_LINE_IN 0x12 /* left line input control */
-#define CS4231_RIGHT_LINE_IN 0x13 /* right line input control */
-#define CS4231_TIMER_LOW 0x14 /* timer low byte */
-#define CS4231_TIMER_HIGH 0x15 /* timer high byte */
-#define CS4231_LEFT_MIC_INPUT 0x16 /* left MIC input control register (InterWave only) */
-#define AD1845_UPR_FREQ_SEL 0x16 /* upper byte of frequency select */
-#define CS4231_RIGHT_MIC_INPUT 0x17 /* right MIC input control register (InterWave only) */
-#define AD1845_LWR_FREQ_SEL 0x17 /* lower byte of frequency select */
-#define CS4236_EXT_REG 0x17 /* extended register access */
-#define CS4231_IRQ_STATUS 0x18 /* irq status register */
-#define CS4231_LINE_LEFT_OUTPUT 0x19 /* left line output control register (InterWave only) */
-#define CS4231_VERSION 0x19 /* CS4231(A) - version values */
-#define CS4231_MONO_CTRL 0x1a /* mono input/output control */
-#define CS4231_LINE_RIGHT_OUTPUT 0x1b /* right line output control register (InterWave only) */
-#define AD1845_PWR_DOWN 0x1b /* power down control */
-#define CS4235_LEFT_MASTER 0x1b /* left master output control */
-#define CS4231_REC_FORMAT 0x1c /* clock and data format - record - bits 7-0 MCE */
-#define CS4231_PLY_VAR_FREQ 0x1d /* playback variable frequency */
-#define AD1845_CLOCK 0x1d /* crystal clock select and total power down */
-#define CS4235_RIGHT_MASTER 0x1d /* right master output control */
-#define CS4231_REC_UPR_CNT 0x1e /* record upper count */
-#define CS4231_REC_LWR_CNT 0x1f /* record lower count */
-
-/* definitions for codec register select port - CODECP( REGSEL ) */
-
-#define CS4231_INIT 0x80 /* CODEC is initializing */
-#define CS4231_MCE 0x40 /* mode change enable */
-#define CS4231_TRD 0x20 /* transfer request disable */
-
-/* definitions for codec status register - CODECP( STATUS ) */
-
-#define CS4231_GLOBALIRQ 0x01 /* IRQ is active */
-
-/* definitions for codec irq status */
-
-#define CS4231_PLAYBACK_IRQ 0x10
-#define CS4231_RECORD_IRQ 0x20
-#define CS4231_TIMER_IRQ 0x40
-#define CS4231_ALL_IRQS 0x70
-#define CS4231_REC_UNDERRUN 0x08
-#define CS4231_REC_OVERRUN 0x04
-#define CS4231_PLY_OVERRUN 0x02
-#define CS4231_PLY_UNDERRUN 0x01
-
-/* definitions for CS4231_LEFT_INPUT and CS4231_RIGHT_INPUT registers */
-
-#define CS4231_ENABLE_MIC_GAIN 0x20
-
-#define CS4231_MIXS_LINE 0x00
-#define CS4231_MIXS_AUX1 0x40
-#define CS4231_MIXS_MIC 0x80
-#define CS4231_MIXS_ALL 0xc0
-
-/* definitions for clock and data format register - CS4231_PLAYBK_FORMAT */
-
-#define CS4231_LINEAR_8 0x00 /* 8-bit unsigned data */
-#define CS4231_ALAW_8 0x60 /* 8-bit A-law companded */
-#define CS4231_ULAW_8 0x20 /* 8-bit U-law companded */
-#define CS4231_LINEAR_16 0x40 /* 16-bit twos complement data - little endian */
-#define CS4231_LINEAR_16_BIG 0xc0 /* 16-bit twos complement data - big endian */
-#define CS4231_ADPCM_16 0xa0 /* 16-bit ADPCM */
-#define CS4231_STEREO 0x10 /* stereo mode */
-/* bits 3-1 define frequency divisor */
-#define CS4231_XTAL1 0x00 /* 24.576 crystal */
-#define CS4231_XTAL2 0x01 /* 16.9344 crystal */
-
-/* definitions for interface control register - CS4231_IFACE_CTRL */
-
-#define CS4231_RECORD_PIO 0x80 /* record PIO enable */
-#define CS4231_PLAYBACK_PIO 0x40 /* playback PIO enable */
-#define CS4231_CALIB_MODE 0x18 /* calibration mode bits */
-#define CS4231_AUTOCALIB 0x08 /* auto calibrate */
-#define CS4231_SINGLE_DMA 0x04 /* use single DMA channel */
-#define CS4231_RECORD_ENABLE 0x02 /* record enable */
-#define CS4231_PLAYBACK_ENABLE 0x01 /* playback enable */
-
-/* definitions for pin control register - CS4231_PIN_CTRL */
-
-#define CS4231_IRQ_ENABLE 0x02 /* enable IRQ */
-#define CS4231_XCTL1 0x40 /* external control #1 */
-#define CS4231_XCTL0 0x80 /* external control #0 */
-
-/* definitions for test and init register - CS4231_TEST_INIT */
-
-#define CS4231_CALIB_IN_PROGRESS 0x20 /* auto calibrate in progress */
-#define CS4231_DMA_REQUEST 0x10 /* DMA request in progress */
-
-/* definitions for misc control register - CS4231_MISC_INFO */
-
-#define CS4231_MODE2 0x40 /* MODE 2 */
-#define CS4231_IW_MODE3 0x6c /* MODE 3 - InterWave enhanced mode */
-#define CS4231_4236_MODE3 0xe0 /* MODE 3 - CS4236+ enhanced mode */
-
-/* definitions for alternate feature 1 register - CS4231_ALT_FEATURE_1 */
-
-#define CS4231_DACZ 0x01 /* zero DAC when underrun */
-#define CS4231_TIMER_ENABLE 0x40 /* codec timer enable */
-#define CS4231_OLB 0x80 /* output level bit */
-
-/* definitions for Extended Registers - CS4236+ */
-
-#define CS4236_REG(i23val) (((i23val << 2) & 0x10) | ((i23val >> 4) & 0x0f))
-#define CS4236_I23VAL(reg) ((((reg)&0xf) << 4) | (((reg)&0x10) >> 2) | 0x8)
-
-#define CS4236_LEFT_LINE 0x08 /* left LINE alternate volume */
-#define CS4236_RIGHT_LINE 0x18 /* right LINE alternate volume */
-#define CS4236_LEFT_MIC 0x28 /* left MIC volume */
-#define CS4236_RIGHT_MIC 0x38 /* right MIC volume */
-#define CS4236_LEFT_MIX_CTRL 0x48 /* synthesis and left input mixer control */
-#define CS4236_RIGHT_MIX_CTRL 0x58 /* right input mixer control */
-#define CS4236_LEFT_FM 0x68 /* left FM volume */
-#define CS4236_RIGHT_FM 0x78 /* right FM volume */
-#define CS4236_LEFT_DSP 0x88 /* left DSP serial port volume */
-#define CS4236_RIGHT_DSP 0x98 /* right DSP serial port volume */
-#define CS4236_RIGHT_LOOPBACK 0xa8 /* right loopback monitor volume */
-#define CS4236_DAC_MUTE 0xb8 /* DAC mute and IFSE enable */
-#define CS4236_ADC_RATE 0xc8 /* indenpendent ADC sample frequency */
-#define CS4236_DAC_RATE 0xd8 /* indenpendent DAC sample frequency */
-#define CS4236_LEFT_MASTER 0xe8 /* left master digital audio volume */
-#define CS4236_RIGHT_MASTER 0xf8 /* right master digital audio volume */
-#define CS4236_LEFT_WAVE 0x0c /* left wavetable serial port volume */
-#define CS4236_RIGHT_WAVE 0x1c /* right wavetable serial port volume */
-#define CS4236_VERSION 0x9c /* chip version and ID */
+#include "cs4231-regs.h"
/* defines for codec.mode */
@@ -210,7 +57,7 @@
#define CS4231_HW_CS4239 0x0404 /* CS4239 - Crystal Clear (tm) stereo enhancement */
/* compatible, but clones */
#define CS4231_HW_INTERWAVE 0x1000 /* InterWave chip */
-#define CS4231_HW_OPL3SA2 0x1001 /* OPL3-SA2 chip */
+#define CS4231_HW_OPL3SA2 0x1101 /* OPL3-SA2 chip, similar to cs4231 */
/* defines for codec.hwshare */
#define CS4231_HWSHARE_IRQ (1<<0)
diff --git a/include/sound/cs46xx.h b/include/sound/cs46xx.h
index 353910ce9755..6b40ee60f4c5 100644
--- a/include/sound/cs46xx.h
+++ b/include/sound/cs46xx.h
@@ -2,7 +2,7 @@
#define __SOUND_CS46XX_H
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>,
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
* Cirrus Logic, Inc.
* Definitions for Cirrus Logic CS46xx chips
*
diff --git a/include/sound/cs46xx_dsp_scb_types.h b/include/sound/cs46xx_dsp_scb_types.h
index 9cb6c7d09567..080857ad0ca2 100644
--- a/include/sound/cs46xx_dsp_scb_types.h
+++ b/include/sound/cs46xx_dsp_scb_types.h
@@ -1,6 +1,6 @@
/*
* The driver for the Cirrus Logic's Sound Fusion CS46XX based soundcards
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/include/sound/cs46xx_dsp_spos.h b/include/sound/cs46xx_dsp_spos.h
index d9da9e59cf37..7c44667e79a6 100644
--- a/include/sound/cs46xx_dsp_spos.h
+++ b/include/sound/cs46xx_dsp_spos.h
@@ -1,6 +1,6 @@
/*
* The driver for the Cirrus Logic's Sound Fusion CS46XX based soundcards
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/include/sound/cs46xx_dsp_task_types.h b/include/sound/cs46xx_dsp_task_types.h
index b3076c487de6..5cf920bfda27 100644
--- a/include/sound/cs46xx_dsp_task_types.h
+++ b/include/sound/cs46xx_dsp_task_types.h
@@ -1,6 +1,6 @@
/*
* The driver for the Cirrus Logic's Sound Fusion CS46XX based soundcards
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/include/sound/cs8403.h b/include/sound/cs8403.h
index c6c3f9f0da78..3a8c174a4209 100644
--- a/include/sound/cs8403.h
+++ b/include/sound/cs8403.h
@@ -3,7 +3,7 @@
/*
* Routines for Cirrus Logic CS8403/CS8404A IEC958 (S/PDIF) Transmitter
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>,
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
* Takashi Iwai <tiwai@suse.de>
*
*
diff --git a/include/sound/cs8427.h b/include/sound/cs8427.h
index 97fd9acf8028..f862cfff5f6a 100644
--- a/include/sound/cs8427.h
+++ b/include/sound/cs8427.h
@@ -3,7 +3,7 @@
/*
* Routines for Cirrus Logic CS8427
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>,
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/include/sound/driver.h b/include/sound/driver.h
index 3c522e59a33c..5ccb6c5feecb 100644
--- a/include/sound/driver.h
+++ b/include/sound/driver.h
@@ -3,7 +3,7 @@
/*
* Main header file for the ALSA driver
- * Copyright (c) 1994-2000 by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 1994-2000 by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h
index 529d0a564367..441aa06dcd6f 100644
--- a/include/sound/emu10k1.h
+++ b/include/sound/emu10k1.h
@@ -2,7 +2,7 @@
#define __SOUND_EMU10K1_H
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>,
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
* Creative Labs, Inc.
* Definitions for EMU10K1 (SB Live!) chips
*
@@ -1408,8 +1408,6 @@ struct snd_emu10k1_fx8010 {
struct snd_emu10k1_fx8010_irq *irq_handlers;
};
-#define emu10k1_gpr_ctl(n) list_entry(n, struct snd_emu10k1_fx8010_ctl, list)
-
struct snd_emu10k1_midi {
struct snd_emu10k1 *emu;
struct snd_rawmidi *rmidi;
@@ -1456,6 +1454,9 @@ struct snd_emu1010 {
unsigned int adc_pads; /* bit mask */
unsigned int dac_pads; /* bit mask */
unsigned int internal_clock; /* 44100 or 48000 */
+ unsigned int optical_in; /* 0:SPDIF, 1:ADAT */
+ unsigned int optical_out; /* 0:SPDIF, 1:ADAT */
+ struct task_struct *firmware_thread;
};
struct snd_emu10k1 {
@@ -1599,9 +1600,9 @@ unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu, unsigned int reg,
void snd_emu10k1_ptr20_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data);
int snd_emu10k1_spi_write(struct snd_emu10k1 * emu, unsigned int data);
int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, u32 reg, u32 value);
-int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, int reg, int value);
-int snd_emu1010_fpga_read(struct snd_emu10k1 * emu, int reg, int *value);
-int snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 * emu, int dst, int src);
+int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, u32 reg, u32 value);
+int snd_emu1010_fpga_read(struct snd_emu10k1 * emu, u32 reg, u32 *value);
+int snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 * emu, u32 dst, u32 src);
unsigned int snd_emu10k1_efx_read(struct snd_emu10k1 *emu, unsigned int pc);
void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb);
void snd_emu10k1_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb);
@@ -1746,6 +1747,8 @@ int snd_emu10k1_fx8010_unregister_irq_handler(struct snd_emu10k1 *emu,
#define A_FXBUS2(x) (0x80 + (x)) /* x = 0x00 - 0x1f extra outs used for EFX capture -> A_FXWC2 */
#define A_EMU32OUTH(x) (0xa0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_10 - _1F" - ??? */
#define A_EMU32OUTL(x) (0xb0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_1 - _F" - ??? */
+#define A3_EMU32IN(x) (0x160 + (x)) /* x = 0x00 - 0x3f "EMU32_IN_00 - _3F" - Only when .device = 0x0008 */
+#define A3_EMU32OUT(x) (0x1E0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_00 - _3F" - Only when .device = 0x0008 */
#define A_GPR(x) (A_FXGPREGBASE + (x))
/* cc_reg constants */
diff --git a/include/sound/es1688.h b/include/sound/es1688.h
index fc1c47dae3da..10fcf1465810 100644
--- a/include/sound/es1688.h
+++ b/include/sound/es1688.h
@@ -3,7 +3,7 @@
/*
* Header file for ES488/ES1688
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/include/sound/gus.h b/include/sound/gus.h
index c49ea57db8cc..e5433d8b78bc 100644
--- a/include/sound/gus.h
+++ b/include/sound/gus.h
@@ -3,7 +3,7 @@
/*
* Global structures used for GUS part of ALSA driver
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/include/sound/hda_hwdep.h b/include/sound/hda_hwdep.h
new file mode 100644
index 000000000000..1c0034e87f22
--- /dev/null
+++ b/include/sound/hda_hwdep.h
@@ -0,0 +1,44 @@
+/*
+ * HWDEP Interface for HD-audio codec
+ *
+ * Copyright (c) 2007 Takashi Iwai <tiwai@suse.de>
+ *
+ * This driver is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This driver is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __SOUND_HDA_HWDEP_H
+#define __SOUND_HDA_HWDEP_H
+
+#define HDA_HWDEP_VERSION ((1 << 16) | (0 << 8) | (0 << 0)) /* 1.0.0 */
+
+/* verb */
+#define HDA_REG_NID_SHIFT 24
+#define HDA_REG_VERB_SHIFT 8
+#define HDA_REG_VAL_SHIFT 0
+#define HDA_VERB(nid,verb,param) ((nid)<<24 | (verb)<<8 | (param))
+
+struct hda_verb_ioctl {
+ u32 verb; /* HDA_VERB() */
+ u32 res; /* response */
+};
+
+/*
+ * ioctls
+ */
+#define HDA_IOCTL_PVERSION _IOR('H', 0x10, int)
+#define HDA_IOCTL_VERB_WRITE _IOWR('H', 0x11, struct hda_verb_ioctl)
+#define HDA_IOCTL_GET_WCAP _IOWR('H', 0x12, struct hda_verb_ioctl)
+
+#endif
diff --git a/include/sound/hdspm.h b/include/sound/hdspm.h
index c3c854d99c28..81990b2bcc98 100644
--- a/include/sound/hdspm.h
+++ b/include/sound/hdspm.h
@@ -1,4 +1,4 @@
-#ifndef __SOUND_HDSPM_H /* -*- linux-c -*- */
+#ifndef __SOUND_HDSPM_H
#define __SOUND_HDSPM_H
/*
* Copyright (C) 2003 Winfried Ritsch (IEM)
@@ -61,7 +61,8 @@ struct hdspm_peak_rms_ioctl {
};
/* use indirect access due to the limit of ioctl bit size */
-#define SNDRV_HDSPM_IOCTL_GET_PEAK_RMS _IOR('H', 0x40, struct hdspm_peak_rms_ioctl)
+#define SNDRV_HDSPM_IOCTL_GET_PEAK_RMS \
+ _IOR('H', 0x40, struct hdspm_peak_rms_ioctl)
/* ------------ CONFIG block IOCTL ---------------------- */
@@ -79,7 +80,8 @@ struct hdspm_config_info {
unsigned int analog_out;
};
-#define SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO _IOR('H', 0x41, struct hdspm_config_info)
+#define SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO \
+ _IOR('H', 0x41, struct hdspm_config_info)
/* get Soundcard Version */
@@ -93,10 +95,14 @@ struct hdspm_version {
/* ------------- get Matrix Mixer IOCTL --------------- */
-/* MADI mixer: 64inputs+64playback in 64outputs = 8192 => *4Byte = 32768 Bytes */
+/* MADI mixer: 64inputs+64playback in 64outputs = 8192 => *4Byte =
+ * 32768 Bytes
+ */
/* organisation is 64 channelfader in a continous memory block */
-/* equivalent to hardware definition, maybe for future feature of mmap of them */
+/* equivalent to hardware definition, maybe for future feature of mmap of
+ * them
+ */
/* each of 64 outputs has 64 infader and 64 outfader:
Ins to Outs mixer[out].in[in], Outstreams to Outs mixer[out].pb[pb] */
diff --git a/include/sound/hwdep.h b/include/sound/hwdep.h
index 94c387b5d724..d9eea013c753 100644
--- a/include/sound/hwdep.h
+++ b/include/sound/hwdep.h
@@ -3,7 +3,7 @@
/*
* Hardware dependent layer
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/include/sound/info.h b/include/sound/info.h
index 97ffc4fb9969..fecbb1ffd540 100644
--- a/include/sound/info.h
+++ b/include/sound/info.h
@@ -3,7 +3,7 @@
/*
* Header file for info interface
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/include/sound/initval.h b/include/sound/initval.h
index e85b90750a59..1daa6dff8297 100644
--- a/include/sound/initval.h
+++ b/include/sound/initval.h
@@ -3,7 +3,7 @@
/*
* Init values for soundcard modules
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
* 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
diff --git a/include/sound/memalloc.h b/include/sound/memalloc.h
index 83489c3abbaf..ae2921d9ddcc 100644
--- a/include/sound/memalloc.h
+++ b/include/sound/memalloc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Takashi Iwai <tiwai@suse.de>
*
* Generic memory allocators
diff --git a/include/sound/mixer_oss.h b/include/sound/mixer_oss.h
index 197b9e3d612b..51fbcb4a277a 100644
--- a/include/sound/mixer_oss.h
+++ b/include/sound/mixer_oss.h
@@ -3,7 +3,7 @@
/*
* OSS MIXER API
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/include/sound/mpu401.h b/include/sound/mpu401.h
index d5c1396c4c9e..d45218b44dfe 100644
--- a/include/sound/mpu401.h
+++ b/include/sound/mpu401.h
@@ -3,7 +3,7 @@
/*
* Header file for MPU-401 and compatible cards
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -50,7 +50,6 @@
#define MPU401_INFO_INTEGRATED (1 << 2) /* integrated h/w port */
#define MPU401_INFO_MMIO (1 << 3) /* MMIO access */
#define MPU401_INFO_TX_IRQ (1 << 4) /* independent TX irq */
-#define MPU401_INFO_UART_ONLY (1 << 5) /* No ENTER_UART cmd needed */
#define MPU401_MODE_BIT_INPUT 0
#define MPU401_MODE_BIT_OUTPUT 1
diff --git a/include/sound/opl3.h b/include/sound/opl3.h
index 82fdb0930720..1d14b3f82393 100644
--- a/include/sound/opl3.h
+++ b/include/sound/opl3.h
@@ -4,7 +4,7 @@
/*
* Definitions of the OPL-3 registers.
*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>,
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
* Hannu Savolainen 1993-1996
*
*
diff --git a/include/sound/pcm-indirect.h b/include/sound/pcm-indirect.h
index 7003d7702e26..1df7acaaa535 100644
--- a/include/sound/pcm-indirect.h
+++ b/include/sound/pcm-indirect.h
@@ -2,7 +2,7 @@
* Helper functions for indirect PCM data transfer
*
* Copyright (c) by Takashi Iwai <tiwai@suse.de>
- * Jaroslav Kysela <perex@suse.cz>
+ * Jaroslav Kysela <perex@perex.cz>
*
* 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
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 73334e0f823f..5e9cc460075e 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -3,7 +3,7 @@
/*
* Digital Audio (PCM) abstract layer
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Abramo Bagnara <abramo@alsa-project.org>
*
*
@@ -301,8 +301,8 @@ struct snd_pcm_runtime {
union snd_pcm_sync_id sync; /* hardware synchronization ID */
/* -- mmap -- */
- volatile struct snd_pcm_mmap_status *status;
- volatile struct snd_pcm_mmap_control *control;
+ struct snd_pcm_mmap_status *status;
+ struct snd_pcm_mmap_control *control;
/* -- locking / scheduling -- */
wait_queue_head_t sleep;
@@ -791,13 +791,13 @@ static inline struct snd_interval *hw_param_interval(struct snd_pcm_hw_params *p
static inline const struct snd_mask *hw_param_mask_c(const struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var)
{
- return (const struct snd_mask *)hw_param_mask((struct snd_pcm_hw_params*) params, var);
+ return &params->masks[var - SNDRV_PCM_HW_PARAM_FIRST_MASK];
}
static inline const struct snd_interval *hw_param_interval_c(const struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var)
{
- return (const struct snd_interval *)hw_param_interval((struct snd_pcm_hw_params*) params, var);
+ return &params->intervals[var - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL];
}
#define params_access(p) snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_ACCESS))
@@ -922,7 +922,10 @@ snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream,
snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream,
void __user **bufs, snd_pcm_uframes_t frames);
+extern const struct snd_pcm_hw_constraint_list snd_pcm_known_rates;
+
int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime);
+unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate);
static inline void snd_pcm_set_runtime_buffer(struct snd_pcm_substream *substream,
struct snd_dma_buffer *bufp)
diff --git a/include/sound/pcm_oss.h b/include/sound/pcm_oss.h
index 1cd4f64cdf31..cc4e226f35fd 100644
--- a/include/sound/pcm_oss.h
+++ b/include/sound/pcm_oss.h
@@ -3,7 +3,7 @@
/*
* Digital Audio (PCM) - OSS compatibility abstract layer
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h
index 7dbcd10fa215..b550a416d075 100644
--- a/include/sound/rawmidi.h
+++ b/include/sound/rawmidi.h
@@ -3,7 +3,7 @@
/*
* Abstract layer for MIDI v1.0 stream
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/include/sound/sb.h b/include/sound/sb.h
index 3ad854b397d2..d0c9ed3546c8 100644
--- a/include/sound/sb.h
+++ b/include/sound/sb.h
@@ -3,7 +3,7 @@
/*
* Header file for SoundBlaster cards
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/include/sound/seq_instr.h b/include/sound/seq_instr.h
index f2db03bfd74e..93b0c51df5b0 100644
--- a/include/sound/seq_instr.h
+++ b/include/sound/seq_instr.h
@@ -3,7 +3,7 @@
/*
* Main kernel header file for the ALSA sequencer
- * Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/include/sound/seq_midi_event.h b/include/sound/seq_midi_event.h
index dd789e7cdb20..5efab8b29c57 100644
--- a/include/sound/seq_midi_event.h
+++ b/include/sound/seq_midi_event.h
@@ -5,7 +5,7 @@
* MIDI byte <-> sequencer event coder
*
* Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>,
- * Jaroslav Kysela <perex@suse.cz>
+ * Jaroslav Kysela <perex@perex.cz>
*
* 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
diff --git a/include/sound/seq_virmidi.h b/include/sound/seq_virmidi.h
index 8d5aea76d7c3..d888433a3096 100644
--- a/include/sound/seq_virmidi.h
+++ b/include/sound/seq_virmidi.h
@@ -4,7 +4,7 @@
/*
* Virtual Raw MIDI client on Sequencer
* Copyright (c) 2000 by Takashi Iwai <tiwai@suse.de>,
- * Jaroslav Kysela <perex@suse.cz>
+ * Jaroslav Kysela <perex@perex.cz>
*
* 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
diff --git a/include/sound/soc.h b/include/sound/soc.h
index db6edba8ef08..f47ef1f75f18 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -201,8 +201,7 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo);
int snd_soc_info_volsw_ext(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo);
-int snd_soc_info_bool_ext(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo);
+#define snd_soc_info_bool_ext snd_ctl_boolean_mono
int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
diff --git a/include/sound/tea575x-tuner.h b/include/sound/tea575x-tuner.h
index b5067d3c2387..e8eeb3a1ed29 100644
--- a/include/sound/tea575x-tuner.h
+++ b/include/sound/tea575x-tuner.h
@@ -4,7 +4,7 @@
/*
* ALSA driver for TEA5757/5759 Philips AM/FM tuner chips
*
- * Copyright (c) 2004 Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 2004 Jaroslav Kysela <perex@perex.cz>
*
* 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
diff --git a/include/sound/timer.h b/include/sound/timer.h
index d42c083db1da..7990469a44ce 100644
--- a/include/sound/timer.h
+++ b/include/sound/timer.h
@@ -3,7 +3,7 @@
/*
* Timer abstract layer
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>,
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
* Abramo Bagnara <abramo@alsa-project.org>
*
*
diff --git a/include/sound/tlv.h b/include/sound/tlv.h
index d93a96b91875..d136ea2181ed 100644
--- a/include/sound/tlv.h
+++ b/include/sound/tlv.h
@@ -3,7 +3,7 @@
/*
* Advanced Linux Sound Architecture - ALSA - Driver
- * Copyright (c) 2006 by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 2006 by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/include/sound/version.h b/include/sound/version.h
index 6bbcfefd2c38..a2be8ad8894b 100644
--- a/include/sound/version.h
+++ b/include/sound/version.h
@@ -1,3 +1,3 @@
/* include/version.h. Generated by alsa/ksync script. */
-#define CONFIG_SND_VERSION "1.0.14"
-#define CONFIG_SND_DATE " (Fri Jul 20 09:12:58 2007 UTC)"
+#define CONFIG_SND_VERSION "1.0.15"
+#define CONFIG_SND_DATE " (Tue Oct 23 06:09:18 2007 UTC)"
diff --git a/include/sound/ymfpci.h b/include/sound/ymfpci.h
index 203d2b45b788..05ead6698434 100644
--- a/include/sound/ymfpci.h
+++ b/include/sound/ymfpci.h
@@ -2,7 +2,7 @@
#define __SOUND_YMFPCI_H
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Definitions for Yahama YMF724/740/744/754 chips
*
*
diff --git a/include/video/Kbuild b/include/video/Kbuild
index a14f9c045b8c..0e406f730c2f 100644
--- a/include/video/Kbuild
+++ b/include/video/Kbuild
@@ -1 +1,2 @@
-unifdef-y += sisfb.h
+unifdef-y += sisfb.h uvesafb.h
+unifdef-y += edid.h
diff --git a/include/video/edid.h b/include/video/edid.h
index f6a42d6c2e2d..928c342b33d6 100644
--- a/include/video/edid.h
+++ b/include/video/edid.h
@@ -1,17 +1,16 @@
#ifndef __linux_video_edid_h__
#define __linux_video_edid_h__
-#ifdef __KERNEL__
-
+#if !defined(__KERNEL__) || defined(CONFIG_X86)
-#ifdef CONFIG_X86
struct edid_info {
unsigned char dummy[128];
};
+#ifdef __KERNEL__
extern struct edid_info edid_info;
-#endif /* CONFIG_X86 */
-
#endif /* __KERNEL__ */
+#endif
+
#endif /* __linux_video_edid_h__ */
diff --git a/include/video/mbxfb.h b/include/video/mbxfb.h
index 20b9002712ef..ea18961fc5e7 100644
--- a/include/video/mbxfb.h
+++ b/include/video/mbxfb.h
@@ -29,18 +29,18 @@ struct mbxfb_platform_data {
};
/* planar */
-#define MBXFB_FMT_YUV12 0
+#define MBXFB_FMT_YUV16 0
+#define MBXFB_FMT_YUV12 1
/* packed */
-#define MBXFB_FMT_UY0VY1 1
-#define MBXFB_FMT_VY0UY1 2
-#define MBXFB_FMT_Y0UY1V 3
-#define MBXFB_FMT_Y0VY1U 4
+#define MBXFB_FMT_UY0VY1 2
+#define MBXFB_FMT_VY0UY1 3
+#define MBXFB_FMT_Y0UY1V 4
+#define MBXFB_FMT_Y0VY1U 5
struct mbxfb_overlaySetup {
__u32 enable;
__u32 x, y;
__u32 width, height;
- __u32 alpha;
__u32 fmt;
__u32 mem_offset;
__u32 scaled_width;
@@ -54,6 +54,45 @@ struct mbxfb_overlaySetup {
__u16 UV_stride;
};
-#define MBXFB_IOCX_OVERLAY _IOWR(0xF4, 0x00,struct mbxfb_overlaySetup)
+#define MBXFB_ALPHABLEND_NONE 0
+#define MBXFB_ALPHABLEND_GLOBAL 1
+#define MBXFB_ALPHABLEND_PIXEL 2
+
+#define MBXFB_COLORKEY_DISABLED 0
+#define MBXFB_COLORKEY_PREVIOUS 1
+#define MBXFB_COLORKEY_CURRENT 2
+struct mbxfb_alphaCtl {
+ __u8 overlay_blend_mode;
+ __u8 overlay_colorkey_mode;
+ __u8 overlay_global_alpha;
+ __u32 overlay_colorkey;
+ __u32 overlay_colorkey_mask;
+
+ __u8 graphics_blend_mode;
+ __u8 graphics_colorkey_mode;
+ __u8 graphics_global_alpha;
+ __u32 graphics_colorkey;
+ __u32 graphics_colorkey_mask;
+};
+
+#define MBXFB_PLANE_GRAPHICS 0
+#define MBXFB_PLANE_VIDEO 1
+struct mbxfb_planeorder {
+ __u8 bottom;
+ __u8 top;
+};
+
+struct mbxfb_reg {
+ __u32 addr; /* offset from 0x03fe 0000 */
+ __u32 val; /* value */
+ __u32 mask; /* which bits to touch (for write) */
+};
+
+#define MBXFB_IOCX_OVERLAY _IOWR(0xF4, 0x00,struct mbxfb_overlaySetup)
+#define MBXFB_IOCG_ALPHA _IOR(0xF4, 0x01,struct mbxfb_alphaCtl)
+#define MBXFB_IOCS_ALPHA _IOW(0xF4, 0x02,struct mbxfb_alphaCtl)
+#define MBXFB_IOCS_PLANEORDER _IOR(0xF4, 0x03,struct mbxfb_planeorder)
+#define MBXFB_IOCS_REG _IOW(0xF4, 0x04,struct mbxfb_reg)
+#define MBXFB_IOCX_REG _IOWR(0xF4, 0x05,struct mbxfb_reg)
#endif /* __MBX_FB_H */
diff --git a/include/video/permedia2.h b/include/video/permedia2.h
index 9e49c9571ec3..9ce9adbfda2b 100644
--- a/include/video/permedia2.h
+++ b/include/video/permedia2.h
@@ -58,7 +58,14 @@
#define PM2R_RD_PALETTE_DATA 0x4008
#define PM2R_RD_PIXEL_MASK 0x4010
#define PM2R_RD_PALETTE_READ_ADDRESS 0x4018
+#define PM2R_RD_CURSOR_COLOR_ADDRESS 0x4020
+#define PM2R_RD_CURSOR_COLOR_DATA 0x4028
#define PM2R_RD_INDEXED_DATA 0x4050
+#define PM2R_RD_CURSOR_DATA 0x4058
+#define PM2R_RD_CURSOR_X_LSB 0x4060
+#define PM2R_RD_CURSOR_X_MSB 0x4068
+#define PM2R_RD_CURSOR_Y_LSB 0x4070
+#define PM2R_RD_CURSOR_Y_MSB 0x4078
#define PM2R_START_X_DOM 0x8000
#define PM2R_D_X_DOM 0x8008
@@ -68,11 +75,14 @@
#define PM2R_D_Y 0x8028
#define PM2R_COUNT 0x8030
#define PM2R_RENDER 0x8038
+#define PM2R_BIT_MASK_PATTERN 0x8068
#define PM2R_RASTERIZER_MODE 0x80a0
#define PM2R_RECTANGLE_ORIGIN 0x80d0
#define PM2R_RECTANGLE_SIZE 0x80d8
#define PM2R_PACKED_DATA_LIMITS 0x8150
#define PM2R_SCISSOR_MODE 0x8180
+#define PM2R_SCISSOR_MIN_XY 0x8188
+#define PM2R_SCISSOR_MAX_XY 0x8190
#define PM2R_SCREEN_SIZE 0x8198
#define PM2R_AREA_STIPPLE_MODE 0x81a0
#define PM2R_WINDOW_ORIGIN 0x81c8
@@ -83,7 +93,9 @@
#define PM2R_TEXEL_LUT_MODE 0x8678
#define PM2R_TEXTURE_COLOR_MODE 0x8680
#define PM2R_FOG_MODE 0x8690
+#define PM2R_TEXEL0 0x8760
#define PM2R_COLOR_DDA_MODE 0x87e0
+#define PM2R_CONSTANT_COLOR 0x87e8
#define PM2R_ALPHA_BLEND_MODE 0x8810
#define PM2R_DITHER_MODE 0x8818
#define PM2R_FB_SOFT_WRITE_MASK 0x8820
@@ -148,6 +160,7 @@
#define PM2VI_RD_CURSOR_Y_HIGH 0x00A
#define PM2VI_RD_CURSOR_X_HOT 0x00B
#define PM2VI_RD_CURSOR_Y_HOT 0x00C
+#define PM2VI_RD_OVERLAY_KEY 0x00D
#define PM2VI_RD_CLK0_PRESCALE 0x201
#define PM2VI_RD_CLK0_FEEDBACK 0x202
#define PM2VI_RD_CLK0_POSTSCALE 0x203
@@ -169,6 +182,8 @@
#define PM2F_RENDER_TRAPEZOID (1L<<6)
#define PM2F_RENDER_POINT (2L<<6)
#define PM2F_RENDER_RECTANGLE (3L<<6)
+#define PM2F_RENDER_SYNC_ON_BIT_MASK (1L<<11)
+#define PM2F_RENDER_TEXTURE_ENABLE (1L<<13)
#define PM2F_SYNCHRONIZATION (1L<<10)
#define PM2F_PLL_LOCKED 0x10
#define PM2F_BEING_RESET (1L<<31)
@@ -224,6 +239,8 @@
#define PM2F_APERTURE_STANDARD 0
#define PM2F_APERTURE_BYTESWAP 1
#define PM2F_APERTURE_HALFWORDSWAP 2
+#define PM2F_CURSORMODE_CURSOR_ENABLE (1 << 0)
+#define PM2F_CURSORMODE_TYPE_X (1 << 4)
typedef enum {
PM2_TYPE_PERMEDIA2,
diff --git a/include/video/pm3fb.h b/include/video/pm3fb.h
index d52e45a1e9b8..2b85134fe96f 100644
--- a/include/video/pm3fb.h
+++ b/include/video/pm3fb.h
@@ -1,6 +1,6 @@
/*
* linux/drivers/video/pm3fb.h -- 3DLabs Permedia3 frame buffer device
- *
+ *
* Copyright (C) 2001 Romain Dolbeau <dolbeau@irisa.fr>
* Copyright (C) 2001 Sven Luther, <luther@dpt-info.u-strasbg.fr>
*
@@ -51,37 +51,36 @@
* GLINT Permedia3 Region 0 Bypass Controls *
***********************************************/
#define PM3ByAperture1Mode 0x0300
- #define PM3ByApertureMode_BYTESWAP_ABCD (0<<0)
- #define PM3ByApertureMode_BYTESWAP_BADC (1<<0)
- #define PM3ByApertureMode_BYTESWAP_CDAB (2<<0)
- #define PM3ByApertureMode_BYTESWAP_DCBA (3<<0)
- #define PM3ByApertureMode_PATCH_DISABLE (0<<2)
- #define PM3ByApertureMode_PATCH_ENABLE (1<<2)
- #define PM3ByApertureMode_FORMAT_RAW (0<<3)
- #define PM3ByApertureMode_FORMAT_YUYV (1<<3)
- #define PM3ByApertureMode_FORMAT_UYVY (2<<3)
- #define PM3ByApertureMode_PIXELSIZE_8BIT (0<<5)
- #define PM3ByApertureMode_PIXELSIZE_16BIT (1<<5)
- #define PM3ByApertureMode_PIXELSIZE_32BIT (2<<5)
- #define PM3ByApertureMode_PIXELSIZE_MASK (3<<5)
- #define PM3ByApertureMode_EFFECTIVE_STRIDE_1024 (0<<7)
- #define PM3ByApertureMode_EFFECTIVE_STRIDE_2048 (1<<7)
- #define PM3ByApertureMode_EFFECTIVE_STRIDE_4096 (2<<7)
- #define PM3ByApertureMode_EFFECTIVE_STRIDE_8192 (3<<7)
- #define PM3ByApertureMode_PATCH_OFFSET_X(off) (((off)&7f)<<9)
- #define PM3ByApertureMode_PATCH_OFFSET_Y(off) (((off)&7f)<<16)
- #define PM3ByApertureMode_FRAMEBUFFER (0<<21)
- #define PM3ByApertureMode_LOCALBUFFER (1<<21)
- #define PM3ByApertureMode_DOUBLE_WRITE_OFF (0<<22)
- #define PM3ByApertureMode_DOUBLE_WRITE_1MB (1<<22)
- #define PM3ByApertureMode_DOUBLE_WRITE_2MB (2<<22)
- #define PM3ByApertureMode_DOUBLE_WRITE_4MB (3<<22)
- #define PM3ByApertureMode_DOUBLE_WRITE_8MB (4<<22)
- #define PM3ByApertureMode_DOUBLE_WRITE_16MB (5<<22)
- #define PM3ByApertureMode_DOUBLE_WRITE_32MB (6<<22)
+ #define PM3ByApertureMode_BYTESWAP_ABCD (0 << 0)
+ #define PM3ByApertureMode_BYTESWAP_BADC (1 << 0)
+ #define PM3ByApertureMode_BYTESWAP_CDAB (2 << 0)
+ #define PM3ByApertureMode_BYTESWAP_DCBA (3 << 0)
+ #define PM3ByApertureMode_PATCH_ENABLE (1 << 2)
+ #define PM3ByApertureMode_FORMAT_RAW (0 << 3)
+ #define PM3ByApertureMode_FORMAT_YUYV (1 << 3)
+ #define PM3ByApertureMode_FORMAT_UYVY (2 << 3)
+ #define PM3ByApertureMode_PIXELSIZE_8BIT (0 << 5)
+ #define PM3ByApertureMode_PIXELSIZE_16BIT (1 << 5)
+ #define PM3ByApertureMode_PIXELSIZE_32BIT (2 << 5)
+ #define PM3ByApertureMode_PIXELSIZE_MASK (3 << 5)
+ #define PM3ByApertureMode_EFFECTIVE_STRIDE_1024 (0 << 7)
+ #define PM3ByApertureMode_EFFECTIVE_STRIDE_2048 (1 << 7)
+ #define PM3ByApertureMode_EFFECTIVE_STRIDE_4096 (2 << 7)
+ #define PM3ByApertureMode_EFFECTIVE_STRIDE_8192 (3 << 7)
+ #define PM3ByApertureMode_PATCH_OFFSET_X(off) (((off) & 0x7f) << 9)
+ #define PM3ByApertureMode_PATCH_OFFSET_Y(off) (((off) & 0x7f) << 16)
+ #define PM3ByApertureMode_FRAMEBUFFER (0 << 21)
+ #define PM3ByApertureMode_LOCALBUFFER (1 << 21)
+ #define PM3ByApertureMode_DOUBLE_WRITE_OFF (0 << 22)
+ #define PM3ByApertureMode_DOUBLE_WRITE_1MB (1 << 22)
+ #define PM3ByApertureMode_DOUBLE_WRITE_2MB (2 << 22)
+ #define PM3ByApertureMode_DOUBLE_WRITE_4MB (3 << 22)
+ #define PM3ByApertureMode_DOUBLE_WRITE_8MB (4 << 22)
+ #define PM3ByApertureMode_DOUBLE_WRITE_16MB (5 << 22)
+ #define PM3ByApertureMode_DOUBLE_WRITE_32MB (6 << 22)
#define PM3ByAperture2Mode 0x0328
-
+
/**********************************************
* GLINT Permedia3 Memory Control (0x1000) *
***********************************************/
@@ -89,7 +88,7 @@
#define PM3MemBypassWriteMask 0x1008
#define PM3MemScratch 0x1010
#define PM3LocalMemCaps 0x1018
- #define PM3LocalMemCaps_NoWriteMask (1 << 28)
+ #define PM3LocalMemCaps_NoWriteMask (1 << 28)
#define PM3LocalMemTimings 0x1020
#define PM3LocalMemControl 0x1028
#define PM3LocalMemRefresh 0x1030
@@ -112,45 +111,41 @@
#define PM3VsStart 0x3048
#define PM3VsEnd 0x3050
#define PM3VideoControl 0x3058
- #define PM3VideoControl_DISABLE (0<<0)
- #define PM3VideoControl_ENABLE (1<<0)
- #define PM3VideoControl_BLANK_ACTIVE_HIGH (0<<1)
- #define PM3VideoControl_BLANK_ACTIVE_LOW (1<<1)
- #define PM3VideoControl_LINE_DOUBLE_OFF (0<<2)
- #define PM3VideoControl_LINE_DOUBLE_ON (1<<2)
- #define PM3VideoControl_HSYNC_FORCE_HIGH (0<<3)
- #define PM3VideoControl_HSYNC_ACTIVE_HIGH (1<<3)
- #define PM3VideoControl_HSYNC_FORCE_LOW (2<<3)
- #define PM3VideoControl_HSYNC_ACTIVE_LOW (3<<3)
- #define PM3VideoControl_HSYNC_MASK (3<<3)
- #define PM3VideoControl_VSYNC_FORCE_HIGH (0<<5)
- #define PM3VideoControl_VSYNC_ACTIVE_HIGH (1<<5)
- #define PM3VideoControl_VSYNC_FORCE_LOW (2<<5)
- #define PM3VideoControl_VSYNC_ACTIVE_LOW (3<<5)
- #define PM3VideoControl_VSYNC_MASK (3<<5)
- #define PM3VideoControl_BYTE_DOUBLE_OFF (0<<7)
- #define PM3VideoControl_BYTE_DOUBLE_ON (1<<7)
- #define PM3VideoControl_BUFFER_SWAP_SYNCON_FRAMEBLANK (0<<9)
- #define PM3VideoControl_BUFFER_SWAP_FREE_RUNNING (1<<9)
- #define PM3VideoControl_BUFFER_SWAP_LIMITETO_FRAMERATE (2<<9)
- #define PM3VideoControl_STEREO_DISABLE (0<<11)
- #define PM3VideoControl_STEREO_ENABLE (1<<11)
- #define PM3VideoControl_RIGHT_EYE_ACTIVE_HIGH (0<<12)
- #define PM3VideoControl_RIGHT_EYE_ACTIVE_LOW (1<<12)
- #define PM3VideoControl_VIDEO_EXT_LOW (0<<14)
- #define PM3VideoControl_VIDEO_EXT_HIGH (1<<14)
- #define PM3VideoControl_SYNC_MODE_INDEPENDENT (0<<16)
- #define PM3VideoControl_SYNC_MODE_SYNCTO_VSA (1<<16)
- #define PM3VideoControl_SYNC_MODE_SYNCTO_VSB (2<<16)
- #define PM3VideoControl_PATCH_DISABLE (0<<18)
- #define PM3VideoControl_PATCH_ENABLE (1<<18)
- #define PM3VideoControl_PIXELSIZE_8BIT (0<<19)
- #define PM3VideoControl_PIXELSIZE_16BIT (1<<19)
- #define PM3VideoControl_PIXELSIZE_32BIT (2<<19)
- #define PM3VideoControl_DISPLAY_DISABLE (0<<21)
- #define PM3VideoControl_DISPLAY_ENABLE (1<<21)
- #define PM3VideoControl_PATCH_OFFSET_X(off) (((off)&0x3f)<<22)
- #define PM3VideoControl_PATCH_OFFSET_Y(off) (((off)&0x3f)<<28)
+ #define PM3VideoControl_ENABLE (1 << 0)
+ #define PM3VideoControl_BLANK_ACTIVE_HIGH (0 << 1)
+ #define PM3VideoControl_BLANK_ACTIVE_LOW (1 << 1)
+ #define PM3VideoControl_LINE_DOUBLE_OFF (0 << 2)
+ #define PM3VideoControl_LINE_DOUBLE_ON (1 << 2)
+ #define PM3VideoControl_HSYNC_FORCE_HIGH (0 << 3)
+ #define PM3VideoControl_HSYNC_ACTIVE_HIGH (1 << 3)
+ #define PM3VideoControl_HSYNC_FORCE_LOW (2 << 3)
+ #define PM3VideoControl_HSYNC_ACTIVE_LOW (3 << 3)
+ #define PM3VideoControl_HSYNC_MASK (3 << 3)
+ #define PM3VideoControl_VSYNC_FORCE_HIGH (0 << 5)
+ #define PM3VideoControl_VSYNC_ACTIVE_HIGH (1 << 5)
+ #define PM3VideoControl_VSYNC_FORCE_LOW (2 << 5)
+ #define PM3VideoControl_VSYNC_ACTIVE_LOW (3 << 5)
+ #define PM3VideoControl_VSYNC_MASK (3 << 5)
+ #define PM3VideoControl_BYTE_DOUBLE_OFF (0 << 7)
+ #define PM3VideoControl_BYTE_DOUBLE_ON (1 << 7)
+ #define PM3VideoControl_BUFFER_SWAP_SYNCON_FRAMEBLANK (0 << 9)
+ #define PM3VideoControl_BUFFER_SWAP_FREE_RUNNING (1 << 9)
+ #define PM3VideoControl_BUFFER_SWAP_LIMITETO_FRAMERATE (2 << 9)
+ #define PM3VideoControl_STEREO_ENABLE (1 << 11)
+ #define PM3VideoControl_RIGHT_EYE_ACTIVE_HIGH (0 << 12)
+ #define PM3VideoControl_RIGHT_EYE_ACTIVE_LOW (1 << 12)
+ #define PM3VideoControl_VIDEO_EXT_LOW (0 << 14)
+ #define PM3VideoControl_VIDEO_EXT_HIGH (1 << 14)
+ #define PM3VideoControl_SYNC_MODE_INDEPENDENT (0 << 16)
+ #define PM3VideoControl_SYNC_MODE_SYNCTO_VSA (1 << 16)
+ #define PM3VideoControl_SYNC_MODE_SYNCTO_VSB (2 << 16)
+ #define PM3VideoControl_PATCH_ENABLE (1 << 18)
+ #define PM3VideoControl_PIXELSIZE_8BIT (0 << 19)
+ #define PM3VideoControl_PIXELSIZE_16BIT (1 << 19)
+ #define PM3VideoControl_PIXELSIZE_32BIT (2 << 19)
+ #define PM3VideoControl_DISPLAY_ENABLE (1 << 21)
+ #define PM3VideoControl_PATCH_OFFSET_X(off) (((off) & 0x3f) << 22)
+ #define PM3VideoControl_PATCH_OFFSET_Y(off) (((off) & 0x3f) << 28)
#define PM3InterruptLine 0x3060
#define PM3DisplayData 0x3068
#define PM3VerticalLineCount 0x3070
@@ -159,80 +154,93 @@
#define PM3MiscControl 0x3088
#define PM3VideoOverlayUpdate 0x3100
- #define PM3VideoOverlayUpdate_DISABLE (0<<0)
- #define PM3VideoOverlayUpdate_ENABLE (1<<0)
+ #define PM3VideoOverlayUpdate_ENABLE (1 << 0)
#define PM3VideoOverlayMode 0x3108
- #define PM3VideoOverlayMode_DISABLE (0<<0)
- #define PM3VideoOverlayMode_ENABLE (1<<0)
- #define PM3VideoOverlayMode_BUFFERSYNC_MANUAL (0<<1)
- #define PM3VideoOverlayMode_BUFFERSYNC_VIDEOSTREAMA (1<<1)
- #define PM3VideoOverlayMode_BUFFERSYNC_VIDEOSTREAMB (2<<1)
- #define PM3VideoOverlayMode_FIELDPOLARITY_NORMAL (0<<4)
- #define PM3VideoOverlayMode_FIELDPOLARITY_INVERT (1<<4)
- #define PM3VideoOverlayMode_PIXELSIZE_8BIT (0<<5)
- #define PM3VideoOverlayMode_PIXELSIZE_16BIT (1<<5)
- #define PM3VideoOverlayMode_PIXELSIZE_32BIT (2<<5)
- #define PM3VideoOverlayMode_COLORFORMAT_RGB8888 ((0<<7)|(1<<12)|(2<<5))
- #define PM3VideoOverlayMode_COLORFORMAT_RGB4444 ((1<<7)|(1<<12)|(1<<5))
- #define PM3VideoOverlayMode_COLORFORMAT_RGB5551 ((2<<7)|(1<<12)|(1<<5))
- #define PM3VideoOverlayMode_COLORFORMAT_RGB565 ((3<<7)|(1<<12)|(1<<5))
- #define PM3VideoOverlayMode_COLORFORMAT_RGB332 ((4<<7)|(1<<12)|(0<<5))
- #define PM3VideoOverlayMode_COLORFORMAT_BGR8888 ((0<<7)|(2<<5))
- #define PM3VideoOverlayMode_COLORFORMAT_BGR4444 ((1<<7)|(1<<5))
- #define PM3VideoOverlayMode_COLORFORMAT_BGR5551 ((2<<7)|(1<<5))
- #define PM3VideoOverlayMode_COLORFORMAT_BGR565 ((3<<7)|(1<<5))
- #define PM3VideoOverlayMode_COLORFORMAT_BGR332 ((4<<7)|(0<<5))
- #define PM3VideoOverlayMode_COLORFORMAT_CI8 ((5<<7)|(1<<12)|(0<<5))
- #define PM3VideoOverlayMode_COLORFORMAT_VUY444 ((2<<10)|(1<<12)|(2<<5))
- #define PM3VideoOverlayMode_COLORFORMAT_YUV444 ((2<<10)|(2<<5))
- #define PM3VideoOverlayMode_COLORFORMAT_VUY422 ((1<<10)|(1<<12)|(1<<5))
- #define PM3VideoOverlayMode_COLORFORMAT_YUV422 ((1<<10)|(1<<5))
- #define PM3VideoOverlayMode_COLORORDER_BGR (0<<12)
- #define PM3VideoOverlayMode_COLORORDER_RGB (1<<12)
- #define PM3VideoOverlayMode_LINEARCOLOREXT_OFF (0<<13)
- #define PM3VideoOverlayMode_LINEARCOLOREXT_ON (1<<13)
- #define PM3VideoOverlayMode_FILTER_MASK (3<<14)
- #define PM3VideoOverlayMode_FILTER_OFF (0<<14)
- #define PM3VideoOverlayMode_FILTER_FULL (1<<14)
- #define PM3VideoOverlayMode_FILTER_PARTIAL (2<<14)
- #define PM3VideoOverlayMode_DEINTERLACE_OFF (0<<16)
- #define PM3VideoOverlayMode_DEINTERLACE_BOB (1<<16)
- #define PM3VideoOverlayMode_PATCHMODE_OFF (0<<18)
- #define PM3VideoOverlayMode_PATCHMODE_ON (1<<18)
- #define PM3VideoOverlayMode_FLIP_VIDEO (0<<20)
- #define PM3VideoOverlayMode_FLIP_VIDEOSTREAMA (1<<20)
- #define PM3VideoOverlayMode_FLIP_VIDEOSTREAMB (2<<20)
- #define PM3VideoOverlayMode_MIRROR_MASK (3<<23)
- #define PM3VideoOverlayMode_MIRRORX_OFF (0<<23)
- #define PM3VideoOverlayMode_MIRRORX_ON (1<<23)
- #define PM3VideoOverlayMode_MIRRORY_OFF (0<<24)
- #define PM3VideoOverlayMode_MIRRORY_ON (1<<24)
+ #define PM3VideoOverlayMode_ENABLE (1 << 0)
+ #define PM3VideoOverlayMode_BUFFERSYNC_MANUAL (0 << 1)
+ #define PM3VideoOverlayMode_BUFFERSYNC_VIDEOSTREAMA (1 << 1)
+ #define PM3VideoOverlayMode_BUFFERSYNC_VIDEOSTREAMB (2 << 1)
+ #define PM3VideoOverlayMode_FIELDPOLARITY_NORMAL (0 << 4)
+ #define PM3VideoOverlayMode_FIELDPOLARITY_INVERT (1 << 4)
+ #define PM3VideoOverlayMode_PIXELSIZE_8BIT (0 << 5)
+ #define PM3VideoOverlayMode_PIXELSIZE_16BIT (1 << 5)
+ #define PM3VideoOverlayMode_PIXELSIZE_32BIT (2 << 5)
+ #define PM3VideoOverlayMode_COLORFORMAT_RGB8888 \
+ ((0 << 7)|(1 << 12)|(2 << 5))
+ #define PM3VideoOverlayMode_COLORFORMAT_RGB4444 \
+ ((1 << 7)|(1 << 12)|(1 << 5))
+ #define PM3VideoOverlayMode_COLORFORMAT_RGB5551 \
+ ((2 << 7)|(1 << 12)|(1 << 5))
+ #define PM3VideoOverlayMode_COLORFORMAT_RGB565 \
+ ((3 << 7)|(1 << 12)|(1 << 5))
+ #define PM3VideoOverlayMode_COLORFORMAT_RGB332 \
+ ((4 << 7)|(1 << 12)|(0 << 5))
+ #define PM3VideoOverlayMode_COLORFORMAT_BGR8888 \
+ ((0 << 7)|(2 << 5))
+ #define PM3VideoOverlayMode_COLORFORMAT_BGR4444 \
+ ((1 << 7)|(1 << 5))
+ #define PM3VideoOverlayMode_COLORFORMAT_BGR5551 \
+ ((2 << 7)|(1 << 5))
+ #define PM3VideoOverlayMode_COLORFORMAT_BGR565 \
+ ((3 << 7)|(1 << 5))
+ #define PM3VideoOverlayMode_COLORFORMAT_BGR332 \
+ ((4 << 7)|(0 << 5))
+ #define PM3VideoOverlayMode_COLORFORMAT_CI8 \
+ ((5 << 7)|(1 << 12)|(0 << 5))
+ #define PM3VideoOverlayMode_COLORFORMAT_VUY444 \
+ ((2 << 10)|(1 << 12)|(2 << 5))
+ #define PM3VideoOverlayMode_COLORFORMAT_YUV444 \
+ ((2 << 10)|(2 << 5))
+ #define PM3VideoOverlayMode_COLORFORMAT_VUY422 \
+ ((1 << 10)|(1 << 12)|(1 << 5))
+ #define PM3VideoOverlayMode_COLORFORMAT_YUV422 \
+ ((1 << 10)|(1 << 5))
+ #define PM3VideoOverlayMode_COLORORDER_BGR (0 << 12)
+ #define PM3VideoOverlayMode_COLORORDER_RGB (1 << 12)
+ #define PM3VideoOverlayMode_LINEARCOLOREXT_OFF (0 << 13)
+ #define PM3VideoOverlayMode_LINEARCOLOREXT_ON (1 << 13)
+ #define PM3VideoOverlayMode_FILTER_MASK (3 << 14)
+ #define PM3VideoOverlayMode_FILTER_OFF (0 << 14)
+ #define PM3VideoOverlayMode_FILTER_FULL (1 << 14)
+ #define PM3VideoOverlayMode_FILTER_PARTIAL (2 << 14)
+ #define PM3VideoOverlayMode_DEINTERLACE_OFF (0 << 16)
+ #define PM3VideoOverlayMode_DEINTERLACE_BOB (1 << 16)
+ #define PM3VideoOverlayMode_PATCHMODE_OFF (0 << 18)
+ #define PM3VideoOverlayMode_PATCHMODE_ON (1 << 18)
+ #define PM3VideoOverlayMode_FLIP_VIDEO (0 << 20)
+ #define PM3VideoOverlayMode_FLIP_VIDEOSTREAMA (1 << 20)
+ #define PM3VideoOverlayMode_FLIP_VIDEOSTREAMB (2 << 20)
+ #define PM3VideoOverlayMode_MIRROR_MASK (3 << 23)
+ #define PM3VideoOverlayMode_MIRRORX_OFF (0 << 23)
+ #define PM3VideoOverlayMode_MIRRORX_ON (1 << 23)
+ #define PM3VideoOverlayMode_MIRRORY_OFF (0 << 24)
+ #define PM3VideoOverlayMode_MIRRORY_ON (1 << 24)
#define PM3VideoOverlayFifoControl 0x3110
#define PM3VideoOverlayIndex 0x3118
#define PM3VideoOverlayBase0 0x3120
#define PM3VideoOverlayBase1 0x3128
#define PM3VideoOverlayBase2 0x3130
#define PM3VideoOverlayStride 0x3138
- #define PM3VideoOverlayStride_STRIDE(s) (((s)&0xfff)<<0)
-#define PM3VideoOverlayWidth 0x3140
- #define PM3VideoOverlayWidth_WIDTH(w) (((w)&0xfff)<<0)
-#define PM3VideoOverlayHeight 0x3148
- #define PM3VideoOverlayHeight_HEIGHT(h) (((h)&0xfff)<<0)
-#define PM3VideoOverlayOrigin 0x3150
- #define PM3VideoOverlayOrigin_XORIGIN(x) (((x)&0xfff)<<0)
- #define PM3VideoOverlayOrigin_YORIGIN(y) (((y)&0xfff)<<16)
-#define PM3VideoOverlayShrinkXDelta 0x3158
- #define PM3VideoOverlayShrinkXDelta_NONE (1<<16)
- #define PM3VideoOverlayShrinkXDelta_DELTA(s,d) \
- ((((s)<<16)/(d))&0x0ffffff0)
-#define PM3VideoOverlayZoomXDelta 0x3160
- #define PM3VideoOverlayZoomXDelta_NONE (1<<16)
- #define PM3VideoOverlayZoomXDelta_DELTA(s,d) \
- ((((s)<<16)/(d))&0x0001fff0)
-#define PM3VideoOverlayYDelta 0x3168
- #define PM3VideoOverlayYDelta_NONE (1<<16)
- #define PM3VideoOverlayYDelta_DELTA(s,d) \
- ((((s)<<16)/(d))&0x0ffffff0)
+ #define PM3VideoOverlayStride_STRIDE(s) (((s) & 0xfff) << 0)
+#define PM3VideoOverlayWidth 0x3140
+ #define PM3VideoOverlayWidth_WIDTH(w) (((w) & 0xfff) << 0)
+#define PM3VideoOverlayHeight 0x3148
+ #define PM3VideoOverlayHeight_HEIGHT(h) (((h) & 0xfff) << 0)
+#define PM3VideoOverlayOrigin 0x3150
+ #define PM3VideoOverlayOrigin_XORIGIN(x) (((x) & 0xfff) << 0)
+ #define PM3VideoOverlayOrigin_YORIGIN(y) (((y) & 0xfff) << 16)
+#define PM3VideoOverlayShrinkXDelta 0x3158
+ #define PM3VideoOverlayShrinkXDelta_NONE (1 << 16)
+ #define PM3VideoOverlayShrinkXDelta_DELTA(s,d) \
+ ((((s) << 16)/(d)) & 0x0ffffff0)
+#define PM3VideoOverlayZoomXDelta 0x3160
+ #define PM3VideoOverlayZoomXDelta_NONE (1 << 16)
+ #define PM3VideoOverlayZoomXDelta_DELTA(s,d) \
+ ((((s) << 16)/(d)) & 0x0001fff0)
+#define PM3VideoOverlayYDelta 0x3168
+ #define PM3VideoOverlayYDelta_NONE (1 << 16)
+ #define PM3VideoOverlayYDelta_DELTA(s,d) \
+ ((((s) << 16)/(d)) & 0x0ffffff0)
#define PM3VideoOverlayFieldOffset 0x3170
#define PM3VideoOverlayStatus 0x3178
@@ -249,102 +257,82 @@
#define PM3RD_IndexHigh 0x4028
#define PM3RD_IndexedData 0x4030
#define PM3RD_IndexControl 0x4038
- #define PM3RD_IndexControl_AUTOINCREMENT_ENABLE (1<<0)
- #define PM3RD_IndexControl_AUTOINCREMENT_DISABLE (0<<0)
+ #define PM3RD_IndexControl_AUTOINCREMENT_ENABLE (1 << 0)
/* Indirect Registers */
#define PM3RD_MiscControl 0x000
- #define PM3RD_MiscControl_HIGHCOLOR_RES_DISABLE (0<<0)
- #define PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE (1<<0)
- #define PM3RD_MiscControl_PIXELDOUBLE_DISABLE (0<<1)
- #define PM3RD_MiscControl_PIXELDOUBLE_ENABLE (1<<1)
- #define PM3RD_MiscControl_LASTREAD_ADDR_DISABLE (0<<2)
- #define PM3RD_MiscControl_LASTREAD_ADDR_ENABLE (1<<2)
- #define PM3RD_MiscControl_DIRECTCOLOR_DISABLE (0<<3)
- #define PM3RD_MiscControl_DIRECTCOLOR_ENABLE (1<<3)
- #define PM3RD_MiscControl_OVERLAY_DISABLE (0<<4)
- #define PM3RD_MiscControl_OVERLAY_ENABLE (1<<4)
- #define PM3RD_MiscControl_PIXELDOUBLE_BUFFER_DISABLE (0<<5)
- #define PM3RD_MiscControl_PIXELDOUBLE_BUFFER_ENABLE (1<<5)
- #define PM3RD_MiscControl_VSB_OUTPUT_DISABLE (0<<6)
- #define PM3RD_MiscControl_VSB_OUTPUT_ENABLE (1<<6)
- #define PM3RD_MiscControl_STEREODOUBLE_BUFFER_DISABLE (0<<7)
- #define PM3RD_MiscControl_STEREODOUBLE_BUFFER_ENABLE (1<<7)
+ #define PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE (1 << 0)
+ #define PM3RD_MiscControl_PIXELDOUBLE_ENABLE (1 << 1)
+ #define PM3RD_MiscControl_LASTREAD_ADDR_ENABLE (1 << 2)
+ #define PM3RD_MiscControl_DIRECTCOLOR_ENABLE (1 << 3)
+ #define PM3RD_MiscControl_OVERLAY_ENABLE (1 << 4)
+ #define PM3RD_MiscControl_PIXELDOUBLE_BUFFER_ENABLE (1 << 5)
+ #define PM3RD_MiscControl_VSB_OUTPUT_ENABLE (1 << 6)
+ #define PM3RD_MiscControl_STEREODOUBLE_BUFFER_ENABLE (1 << 7)
#define PM3RD_SyncControl 0x001
- #define PM3RD_SyncControl_HSYNC_ACTIVE_LOW (0<<0)
- #define PM3RD_SyncControl_HSYNC_ACTIVE_HIGH (1<<0)
- #define PM3RD_SyncControl_HSYNC_FORCE_ACTIVE (3<<0)
- #define PM3RD_SyncControl_HSYNC_FORCE_INACTIVE (4<<0)
- #define PM3RD_SyncControl_HSYNC_TRI_STATE (2<<0)
- #define PM3RD_SyncControl_VSYNC_ACTIVE_LOW (0<<3)
- #define PM3RD_SyncControl_VSYNC_ACTIVE_HIGH (1<<3)
- #define PM3RD_SyncControl_VSYNC_TRI_STATE (2<<3)
- #define PM3RD_SyncControl_VSYNC_FORCE_ACTIVE (3<<3)
- #define PM3RD_SyncControl_VSYNC_FORCE_INACTIVE (4<<3)
- #define PM3RD_SyncControl_HSYNC_OVERRIDE_SETBY_HSYNC (0<<6)
- #define PM3RD_SyncControl_HSYNC_OVERRIDE_FORCE_HIGH (1<<6)
- #define PM3RD_SyncControl_VSYNC_OVERRIDE_SETBY_VSYNC (0<<7)
- #define PM3RD_SyncControl_VSYNC_OVERRIDE_FORCE_HIGH (1<<7)
+ #define PM3RD_SyncControl_HSYNC_ACTIVE_LOW (0 << 0)
+ #define PM3RD_SyncControl_HSYNC_ACTIVE_HIGH (1 << 0)
+ #define PM3RD_SyncControl_HSYNC_FORCE_ACTIVE (3 << 0)
+ #define PM3RD_SyncControl_HSYNC_FORCE_INACTIVE (4 << 0)
+ #define PM3RD_SyncControl_HSYNC_TRI_STATE (2 << 0)
+ #define PM3RD_SyncControl_VSYNC_ACTIVE_LOW (0 << 3)
+ #define PM3RD_SyncControl_VSYNC_ACTIVE_HIGH (1 << 3)
+ #define PM3RD_SyncControl_VSYNC_TRI_STATE (2 << 3)
+ #define PM3RD_SyncControl_VSYNC_FORCE_ACTIVE (3 << 3)
+ #define PM3RD_SyncControl_VSYNC_FORCE_INACTIVE (4 << 3)
+ #define PM3RD_SyncControl_HSYNC_OVERRIDE_SETBY_HSYNC (0 << 6)
+ #define PM3RD_SyncControl_HSYNC_OVERRIDE_FORCE_HIGH (1 << 6)
+ #define PM3RD_SyncControl_VSYNC_OVERRIDE_SETBY_VSYNC (0 << 7)
+ #define PM3RD_SyncControl_VSYNC_OVERRIDE_FORCE_HIGH (1 << 7)
#define PM3RD_DACControl 0x002
- #define PM3RD_DACControl_DAC_POWER_ON (0<<0)
- #define PM3RD_DACControl_DAC_POWER_OFF (1<<0)
- #define PM3RD_DACControl_SYNC_ON_GREEN_DISABLE (0<<3)
- #define PM3RD_DACControl_SYNC_ON_GREEN_ENABLE (1<<3)
- #define PM3RD_DACControl_BLANK_RED_DAC_DISABLE (0<<4)
- #define PM3RD_DACControl_BLANK_RED_DAC_ENABLE (1<<4)
- #define PM3RD_DACControl_BLANK_GREEN_DAC_DISABLE (0<<5)
- #define PM3RD_DACControl_BLANK_GREEN_DAC_ENABLE (1<<5)
- #define PM3RD_DACControl_BLANK_BLUE_DAC_DISABLE (0<<6)
- #define PM3RD_DACControl_BLANK_BLUE_DAC_ENABLE (1<<6)
- #define PM3RD_DACControl_BLANK_PEDESTAL_DISABLE (0<<7)
- #define PM3RD_DACControl_BLANK_PEDESTAL_ENABLE (1<<7)
+ #define PM3RD_DACControl_DAC_POWER_ON (0 << 0)
+ #define PM3RD_DACControl_DAC_POWER_OFF (1 << 0)
+ #define PM3RD_DACControl_SYNC_ON_GREEN_ENABLE (1 << 3)
+ #define PM3RD_DACControl_BLANK_RED_DAC_ENABLE (1 << 4)
+ #define PM3RD_DACControl_BLANK_GREEN_DAC_ENABLE (1 << 5)
+ #define PM3RD_DACControl_BLANK_BLUE_DAC_ENABLE (1 << 6)
+ #define PM3RD_DACControl_BLANK_PEDESTAL_ENABLE (1 << 7)
#define PM3RD_PixelSize 0x003
- #define PM3RD_PixelSize_24_BIT_PIXELS (4<<0)
- #define PM3RD_PixelSize_32_BIT_PIXELS (2<<0)
- #define PM3RD_PixelSize_16_BIT_PIXELS (1<<0)
- #define PM3RD_PixelSize_8_BIT_PIXELS (0<<0)
+ #define PM3RD_PixelSize_24_BIT_PIXELS (4 << 0)
+ #define PM3RD_PixelSize_32_BIT_PIXELS (2 << 0)
+ #define PM3RD_PixelSize_16_BIT_PIXELS (1 << 0)
+ #define PM3RD_PixelSize_8_BIT_PIXELS (0 << 0)
#define PM3RD_ColorFormat 0x004
- #define PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE (1<<6)
- #define PM3RD_ColorFormat_LINEAR_COLOR_EXT_DISABLE (0<<6)
- #define PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW (1<<5)
- #define PM3RD_ColorFormat_COLOR_ORDER_RED_LOW (0<<5)
- #define PM3RD_ColorFormat_COLOR_FORMAT_MASK (0x1f<<0)
- #define PM3RD_ColorFormat_8888_COLOR (0<<0)
- #define PM3RD_ColorFormat_5551_FRONT_COLOR (1<<0)
- #define PM3RD_ColorFormat_4444_COLOR (2<<0)
- #define PM3RD_ColorFormat_332_FRONT_COLOR (5<<0)
- #define PM3RD_ColorFormat_332_BACK_COLOR (6<<0)
- #define PM3RD_ColorFormat_2321_FRONT_COLOR (9<<0)
- #define PM3RD_ColorFormat_2321_BACK_COLOR (10<<0)
- #define PM3RD_ColorFormat_232_FRONTOFF_COLOR (11<<0)
- #define PM3RD_ColorFormat_232_BACKOFF_COLOR (12<<0)
- #define PM3RD_ColorFormat_5551_BACK_COLOR (13<<0)
- #define PM3RD_ColorFormat_CI8_COLOR (14<<0)
- #define PM3RD_ColorFormat_565_FRONT_COLOR (16<<0)
- #define PM3RD_ColorFormat_565_BACK_COLOR (17<<0)
+ #define PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE (1 << 6)
+ #define PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW (1 << 5)
+ #define PM3RD_ColorFormat_COLOR_ORDER_RED_LOW (0 << 5)
+ #define PM3RD_ColorFormat_COLOR_FORMAT_MASK (0x1f << 0)
+ #define PM3RD_ColorFormat_8888_COLOR (0 << 0)
+ #define PM3RD_ColorFormat_5551_FRONT_COLOR (1 << 0)
+ #define PM3RD_ColorFormat_4444_COLOR (2 << 0)
+ #define PM3RD_ColorFormat_332_FRONT_COLOR (5 << 0)
+ #define PM3RD_ColorFormat_332_BACK_COLOR (6 << 0)
+ #define PM3RD_ColorFormat_2321_FRONT_COLOR (9 << 0)
+ #define PM3RD_ColorFormat_2321_BACK_COLOR (10 << 0)
+ #define PM3RD_ColorFormat_232_FRONTOFF_COLOR (11 << 0)
+ #define PM3RD_ColorFormat_232_BACKOFF_COLOR (12 << 0)
+ #define PM3RD_ColorFormat_5551_BACK_COLOR (13 << 0)
+ #define PM3RD_ColorFormat_CI8_COLOR (14 << 0)
+ #define PM3RD_ColorFormat_565_FRONT_COLOR (16 << 0)
+ #define PM3RD_ColorFormat_565_BACK_COLOR (17 << 0)
#define PM3RD_CursorMode 0x005
- #define PM3RD_CursorMode_CURSOR_DISABLE (0<<0)
- #define PM3RD_CursorMode_CURSOR_ENABLE (1<<0)
- #define PM3RD_CursorMode_FORMAT_64x64_2BPE_P0123 (0<<2)
- #define PM3RD_CursorMode_FORMAT_32x32_2BPE_P0 (1<<2)
- #define PM3RD_CursorMode_FORMAT_32x32_2BPE_P1 (2<<2)
- #define PM3RD_CursorMode_FORMAT_32x32_2BPE_P2 (3<<2)
- #define PM3RD_CursorMode_FORMAT_32x32_2BPE_P3 (4<<2)
- #define PM3RD_CursorMode_FORMAT_32x32_4BPE_P01 (5<<2)
- #define PM3RD_CursorMode_FORMAT_32x32_4BPE_P23 (6<<2)
- #define PM3RD_CursorMode_TYPE_MS (0<<4)
- #define PM3RD_CursorMode_TYPE_X (1<<4)
- #define PM3RD_CursorMode_REVERSE_PIXEL_ORDER_DISABLE (0<<6)
- #define PM3RD_CursorMode_REVERSE_PIXEL_ORDER_ENABLE (1<<6)
- #define PM3RD_CursorMode_REVERSE_PIXEL_ORDER_3_COLOR (2<<6)
- #define PM3RD_CursorMode_REVERSE_PIXEL_ORDER_15_COLOR (3<<6)
+ #define PM3RD_CursorMode_CURSOR_ENABLE (1 << 0)
+ #define PM3RD_CursorMode_FORMAT_64x64_2BPE_P0123 (0 << 2)
+ #define PM3RD_CursorMode_FORMAT_32x32_2BPE_P0 (1 << 2)
+ #define PM3RD_CursorMode_FORMAT_32x32_2BPE_P1 (2 << 2)
+ #define PM3RD_CursorMode_FORMAT_32x32_2BPE_P2 (3 << 2)
+ #define PM3RD_CursorMode_FORMAT_32x32_2BPE_P3 (4 << 2)
+ #define PM3RD_CursorMode_FORMAT_32x32_4BPE_P01 (5 << 2)
+ #define PM3RD_CursorMode_FORMAT_32x32_4BPE_P23 (6 << 2)
+ #define PM3RD_CursorMode_TYPE_MS (0 << 4)
+ #define PM3RD_CursorMode_TYPE_X (1 << 4)
+ #define PM3RD_CursorMode_REVERSE_PIXEL_ORDER_ENABLE (1 << 6)
+ #define PM3RD_CursorMode_REVERSE_PIXEL_ORDER_3_COLOR (2 << 6)
+ #define PM3RD_CursorMode_REVERSE_PIXEL_ORDER_15_COLOR (3 << 6)
#define PM3RD_CursorControl 0x006
- #define PM3RD_CursorControl_DOUBLE_X_DISABLED (0<<0)
- #define PM3RD_CursorControl_DOUBLE_X_ENABLED (1<<0)
- #define PM3RD_CursorControl_DOUBLE_Y_DISABLED (0<<1)
- #define PM3RD_CursorControl_DOUBLE_Y_ENABLED (1<<1)
- #define PM3RD_CursorControl_READBACK_POS_DISABLED (0<<2)
- #define PM3RD_CursorControl_READBACK_POS_ENABLED (1<<2)
+ #define PM3RD_CursorControl_DOUBLE_X_ENABLED (1 << 0)
+ #define PM3RD_CursorControl_DOUBLE_Y_ENABLED (1 << 1)
+ #define PM3RD_CursorControl_READBACK_POS_ENABLED (1 << 2)
#define PM3RD_CursorXLow 0x007
#define PM3RD_CursorXHigh 0x008
@@ -354,17 +342,13 @@
#define PM3RD_CursorHotSpotY 0x00c
#define PM3RD_OverlayKey 0x00d
#define PM3RD_Pan 0x00e
- #define PM3RD_Pan_DISABLE (0<<0)
- #define PM3RD_Pan_ENABLE (1<<0)
- #define PM3RD_Pan_GATE_DISABLE (0<<1)
- #define PM3RD_Pan_GATE_ENABLE (1<<1)
+ #define PM3RD_Pan_ENABLE (1 << 0)
+ #define PM3RD_Pan_GATE_ENABLE (1 << 1)
#define PM3RD_Sense 0x00f
#define PM3RD_CheckControl 0x018
- #define PM3RD_CheckControl_PIXEL_DISABLED (0<<0)
- #define PM3RD_CheckControl_PIXEL_ENABLED (1<<0)
- #define PM3RD_CheckControl_LUT_DISABLED (0<<1)
- #define PM3RD_CheckControl_LUT_ENABLED (1<<1)
+ #define PM3RD_CheckControl_PIXEL_ENABLED (1 << 0)
+ #define PM3RD_CheckControl_LUT_ENABLED (1 << 1)
#define PM3RD_CheckPixelRed 0x019
#define PM3RD_CheckPixelGreen 0x01a
#define PM3RD_CheckPixelBlue 0x01b
@@ -374,19 +358,17 @@
#define PM3RD_Scratch 0x01f
#define PM3RD_VideoOverlayControl 0x020
- #define PM3RD_VideoOverlayControl_DISABLE (0<<0)
- #define PM3RD_VideoOverlayControl_ENABLE (1<<0)
- #define PM3RD_VideoOverlayControl_MODE_MASK (3<<1)
- #define PM3RD_VideoOverlayControl_MODE_MAINKEY (0<<1)
- #define PM3RD_VideoOverlayControl_MODE_OVERLAYKEY (1<<1)
- #define PM3RD_VideoOverlayControl_MODE_ALWAYS (2<<1)
- #define PM3RD_VideoOverlayControl_MODE_BLEND (3<<1)
- #define PM3RD_VideoOverlayControl_DIRECTCOLOR_DISABLED (0<<3)
- #define PM3RD_VideoOverlayControl_DIRECTCOLOR_ENABLED (1<<3)
- #define PM3RD_VideoOverlayControl_BLENDSRC_MAIN (0<<4)
- #define PM3RD_VideoOverlayControl_BLENDSRC_REGISTER (1<<4)
- #define PM3RD_VideoOverlayControl_KEY_COLOR (0<<5)
- #define PM3RD_VideoOverlayControl_KEY_ALPHA (1<<5)
+ #define PM3RD_VideoOverlayControl_ENABLE (1 << 0)
+ #define PM3RD_VideoOverlayControl_MODE_MASK (3 << 1)
+ #define PM3RD_VideoOverlayControl_MODE_MAINKEY (0 << 1)
+ #define PM3RD_VideoOverlayControl_MODE_OVERLAYKEY (1 << 1)
+ #define PM3RD_VideoOverlayControl_MODE_ALWAYS (2 << 1)
+ #define PM3RD_VideoOverlayControl_MODE_BLEND (3 << 1)
+ #define PM3RD_VideoOverlayControl_DIRECTCOLOR_ENABLED (1 << 3)
+ #define PM3RD_VideoOverlayControl_BLENDSRC_MAIN (0 << 4)
+ #define PM3RD_VideoOverlayControl_BLENDSRC_REGISTER (1 << 4)
+ #define PM3RD_VideoOverlayControl_KEY_COLOR (0 << 5)
+ #define PM3RD_VideoOverlayControl_KEY_ALPHA (1 << 5)
#define PM3RD_VideoOverlayXStartLow 0x021
#define PM3RD_VideoOverlayXStartHigh 0x022
#define PM3RD_VideoOverlayYStartLow 0x023
@@ -399,10 +381,10 @@
#define PM3RD_VideoOverlayKeyG 0x02a
#define PM3RD_VideoOverlayKeyB 0x02b
#define PM3RD_VideoOverlayBlend 0x02c
- #define PM3RD_VideoOverlayBlend_FACTOR_0_PERCENT (0<<6)
- #define PM3RD_VideoOverlayBlend_FACTOR_25_PERCENT (1<<6)
- #define PM3RD_VideoOverlayBlend_FACTOR_75_PERCENT (2<<6)
- #define PM3RD_VideoOverlayBlend_FACTOR_100_PERCENT (3<<6)
+ #define PM3RD_VideoOverlayBlend_FACTOR_0_PERCENT (0 << 6)
+ #define PM3RD_VideoOverlayBlend_FACTOR_25_PERCENT (1 << 6)
+ #define PM3RD_VideoOverlayBlend_FACTOR_75_PERCENT (2 << 6)
+ #define PM3RD_VideoOverlayBlend_FACTOR_100_PERCENT (3 << 6)
#define PM3RD_DClkSetup1 0x1f0
#define PM3RD_DClkSetup2 0x1f1
@@ -410,21 +392,20 @@
#define PM3RD_KClkSetup2 0x1f3
#define PM3RD_DClkControl 0x200
- #define PM3RD_DClkControl_SOURCE_PLL (0<<4)
- #define PM3RD_DClkControl_SOURCE_VSA (1<<4)
- #define PM3RD_DClkControl_SOURCE_VSB (2<<4)
- #define PM3RD_DClkControl_SOURCE_EXT (3<<4)
- #define PM3RD_DClkControl_STATE_RUN (2<<2)
- #define PM3RD_DClkControl_STATE_HIGH (1<<2)
- #define PM3RD_DClkControl_STATE_LOW (0<<2)
- #define PM3RD_DClkControl_LOCKED (1<<1)
- #define PM3RD_DClkControl_NOT_LOCKED (0<<1)
- #define PM3RD_DClkControl_ENABLE (1<<0)
- #define PM3RD_DClkControl_DISABLE (0<<0)
+ #define PM3RD_DClkControl_SOURCE_PLL (0 << 4)
+ #define PM3RD_DClkControl_SOURCE_VSA (1 << 4)
+ #define PM3RD_DClkControl_SOURCE_VSB (2 << 4)
+ #define PM3RD_DClkControl_SOURCE_EXT (3 << 4)
+ #define PM3RD_DClkControl_STATE_RUN (2 << 2)
+ #define PM3RD_DClkControl_STATE_HIGH (1 << 2)
+ #define PM3RD_DClkControl_STATE_LOW (0 << 2)
+ #define PM3RD_DClkControl_LOCKED (1 << 1)
+ #define PM3RD_DClkControl_NOT_LOCKED (0 << 1)
+ #define PM3RD_DClkControl_ENABLE (1 << 0)
#define PM3RD_DClk0PreScale 0x201
#define PM3RD_DClk0FeedbackScale 0x202
#define PM3RD_DClk0PostScale 0x203
- #define PM3_REF_CLOCK 14318
+ #define PM3_REF_CLOCK 14318
#define PM3RD_DClk1PreScale 0x204
#define PM3RD_DClk1FeedbackScale 0x205
#define PM3RD_DClk1PostScale 0x206
@@ -435,59 +416,56 @@
#define PM3RD_DClk3FeedbackScale 0x20b
#define PM3RD_DClk3PostScale 0x20c
#define PM3RD_KClkControl 0x20d
- #define PM3RD_KClkControl_DISABLE (0<<0)
- #define PM3RD_KClkControl_ENABLE (1<<0)
- #define PM3RD_KClkControl_NOT_LOCKED (0<<1)
- #define PM3RD_KClkControl_LOCKED (1<<1)
- #define PM3RD_KClkControl_STATE_LOW (0<<2)
- #define PM3RD_KClkControl_STATE_HIGH (1<<2)
- #define PM3RD_KClkControl_STATE_RUN (2<<2)
- #define PM3RD_KClkControl_STATE_LOW_POWER (3<<2)
- #define PM3RD_KClkControl_SOURCE_PCLK (0<<4)
- #define PM3RD_KClkControl_SOURCE_HALF_PCLK (1<<4)
- #define PM3RD_KClkControl_SOURCE_PLL (2<<4)
+ #define PM3RD_KClkControl_ENABLE (1 << 0)
+ #define PM3RD_KClkControl_NOT_LOCKED (0 << 1)
+ #define PM3RD_KClkControl_LOCKED (1 << 1)
+ #define PM3RD_KClkControl_STATE_LOW (0 << 2)
+ #define PM3RD_KClkControl_STATE_HIGH (1 << 2)
+ #define PM3RD_KClkControl_STATE_RUN (2 << 2)
+ #define PM3RD_KClkControl_STATE_LOW_POWER (3 << 2)
+ #define PM3RD_KClkControl_SOURCE_PCLK (0 << 4)
+ #define PM3RD_KClkControl_SOURCE_HALF_PCLK (1 << 4)
+ #define PM3RD_KClkControl_SOURCE_PLL (2 << 4)
#define PM3RD_KClkPreScale 0x20e
#define PM3RD_KClkFeedbackScale 0x20f
#define PM3RD_KClkPostScale 0x210
#define PM3RD_MClkControl 0x211
- #define PM3RD_MClkControl_DISABLE (0<<0)
- #define PM3RD_MClkControl_ENABLE (1<<0)
- #define PM3RD_MClkControl_NOT_LOCKED (0<<1)
- #define PM3RD_MClkControl_LOCKED (1<<1)
- #define PM3RD_MClkControl_STATE_LOW (0<<2)
- #define PM3RD_MClkControl_STATE_HIGH (1<<2)
- #define PM3RD_MClkControl_STATE_RUN (2<<2)
- #define PM3RD_MClkControl_STATE_LOW_POWER (3<<2)
- #define PM3RD_MClkControl_SOURCE_PCLK (0<<4)
- #define PM3RD_MClkControl_SOURCE_HALF_PCLK (1<<4)
- #define PM3RD_MClkControl_SOURCE_HALF_EXT (3<<4)
- #define PM3RD_MClkControl_SOURCE_EXT (4<<4)
- #define PM3RD_MClkControl_SOURCE_HALF_KCLK (5<<4)
- #define PM3RD_MClkControl_SOURCE_KCLK (6<<4)
+ #define PM3RD_MClkControl_ENABLE (1 << 0)
+ #define PM3RD_MClkControl_NOT_LOCKED (0 << 1)
+ #define PM3RD_MClkControl_LOCKED (1 << 1)
+ #define PM3RD_MClkControl_STATE_LOW (0 << 2)
+ #define PM3RD_MClkControl_STATE_HIGH (1 << 2)
+ #define PM3RD_MClkControl_STATE_RUN (2 << 2)
+ #define PM3RD_MClkControl_STATE_LOW_POWER (3 << 2)
+ #define PM3RD_MClkControl_SOURCE_PCLK (0 << 4)
+ #define PM3RD_MClkControl_SOURCE_HALF_PCLK (1 << 4)
+ #define PM3RD_MClkControl_SOURCE_HALF_EXT (3 << 4)
+ #define PM3RD_MClkControl_SOURCE_EXT (4 << 4)
+ #define PM3RD_MClkControl_SOURCE_HALF_KCLK (5 << 4)
+ #define PM3RD_MClkControl_SOURCE_KCLK (6 << 4)
#define PM3RD_MClkPreScale 0x212
#define PM3RD_MClkFeedbackScale 0x213
#define PM3RD_MClkPostScale 0x214
#define PM3RD_SClkControl 0x215
- #define PM3RD_SClkControl_DISABLE (0<<0)
- #define PM3RD_SClkControl_ENABLE (1<<0)
- #define PM3RD_SClkControl_NOT_LOCKED (0<<1)
- #define PM3RD_SClkControl_LOCKED (1<<1)
- #define PM3RD_SClkControl_STATE_LOW (0<<2)
- #define PM3RD_SClkControl_STATE_HIGH (1<<2)
- #define PM3RD_SClkControl_STATE_RUN (2<<2)
- #define PM3RD_SClkControl_STATE_LOW_POWER (3<<2)
- #define PM3RD_SClkControl_SOURCE_PCLK (0<<4)
- #define PM3RD_SClkControl_SOURCE_HALF_PCLK (1<<4)
- #define PM3RD_SClkControl_SOURCE_HALF_EXT (3<<4)
- #define PM3RD_SClkControl_SOURCE_EXT (4<<4)
- #define PM3RD_SClkControl_SOURCE_HALF_KCLK (5<<4)
- #define PM3RD_SClkControl_SOURCE_KCLK (6<<4)
+ #define PM3RD_SClkControl_ENABLE (1 << 0)
+ #define PM3RD_SClkControl_NOT_LOCKED (0 << 1)
+ #define PM3RD_SClkControl_LOCKED (1 << 1)
+ #define PM3RD_SClkControl_STATE_LOW (0 << 2)
+ #define PM3RD_SClkControl_STATE_HIGH (1 << 2)
+ #define PM3RD_SClkControl_STATE_RUN (2 << 2)
+ #define PM3RD_SClkControl_STATE_LOW_POWER (3 << 2)
+ #define PM3RD_SClkControl_SOURCE_PCLK (0 << 4)
+ #define PM3RD_SClkControl_SOURCE_HALF_PCLK (1 << 4)
+ #define PM3RD_SClkControl_SOURCE_HALF_EXT (3 << 4)
+ #define PM3RD_SClkControl_SOURCE_EXT (4 << 4)
+ #define PM3RD_SClkControl_SOURCE_HALF_KCLK (5 << 4)
+ #define PM3RD_SClkControl_SOURCE_KCLK (6 << 4)
#define PM3RD_SClkPreScale 0x216
#define PM3RD_SClkFeedbackScale 0x217
#define PM3RD_SClkPostScale 0x218
-#define PM3RD_CursorPalette(p) (0x303+(p))
-#define PM3RD_CursorPattern(p) (0x400+(p))
+#define PM3RD_CursorPalette(p) (0x303 + (p))
+#define PM3RD_CursorPattern(p) (0x400 + (p))
/******************************************************
* GLINT Permedia3 Video Streaming Registers (0x5000) *
*******************************************************/
@@ -521,10 +499,10 @@
#define PM3ColorDDAModeOr 0xabe8
#define PM3CommandInterrupt 0xa990
#define PM3ConstantColorDDA 0xafb0
- #define PM3ConstantColorDDA_R(r) ((r)&0xff)
- #define PM3ConstantColorDDA_G(g) (((g)&0xff)<<8)
- #define PM3ConstantColorDDA_B(b) (((b)&0xff)<<16)
- #define PM3ConstantColorDDA_A(a) (((a)&0xff)<<24)
+ #define PM3ConstantColorDDA_R(r) ((r) & 0xff)
+ #define PM3ConstantColorDDA_G(g) (((g) & 0xff) << 8)
+ #define PM3ConstantColorDDA_B(b) (((b) & 0xff) << 16)
+ #define PM3ConstantColorDDA_A(a) (((a) & 0xff) << 24)
#define PM3ContextData 0x8dd0
#define PM3ContextDump 0x8dc0
#define PM3ContextRestore 0x8dc8
@@ -568,59 +546,59 @@
#define PM3FBDestReadBufferOffset1 0xaea8
#define PM3FBDestReadBufferOffset2 0xaeb0
#define PM3FBDestReadBufferOffset3 0xaeb8
- #define PM3FBDestReadBufferOffset_XOffset(x) ((x)&0xffff)
- #define PM3FBDestReadBufferOffset_YOffset(y) (((y)&0xffff)<<16)
+ #define PM3FBDestReadBufferOffset_XOffset(x) ((x) & 0xffff)
+ #define PM3FBDestReadBufferOffset_YOffset(y) (((y) & 0xffff) << 16)
#define PM3FBDestReadBufferWidth0 0xaec0
#define PM3FBDestReadBufferWidth1 0xaec8
#define PM3FBDestReadBufferWidth2 0xaed0
#define PM3FBDestReadBufferWidth3 0xaed8
- #define PM3FBDestReadBufferWidth_Width(w) ((w)&0x0fff)
+ #define PM3FBDestReadBufferWidth_Width(w) ((w) & 0x0fff)
#define PM3FBDestReadEnables 0xaee8
#define PM3FBDestReadEnablesAnd 0xad20
#define PM3FBDestReadEnablesOr 0xad28
- #define PM3FBDestReadEnables_E(e) ((e)&0xff)
- #define PM3FBDestReadEnables_E0 1<<0
- #define PM3FBDestReadEnables_E1 1<<1
- #define PM3FBDestReadEnables_E2 1<<2
- #define PM3FBDestReadEnables_E3 1<<3
- #define PM3FBDestReadEnables_E4 1<<4
- #define PM3FBDestReadEnables_E5 1<<5
- #define PM3FBDestReadEnables_E6 1<<6
- #define PM3FBDestReadEnables_E7 1<<7
- #define PM3FBDestReadEnables_R(r) (((r)&0xff)<<8)
- #define PM3FBDestReadEnables_R0 1<<8
- #define PM3FBDestReadEnables_R1 1<<9
- #define PM3FBDestReadEnables_R2 1<<10
- #define PM3FBDestReadEnables_R3 1<<11
- #define PM3FBDestReadEnables_R4 1<<12
- #define PM3FBDestReadEnables_R5 1<<13
- #define PM3FBDestReadEnables_R6 1<<14
- #define PM3FBDestReadEnables_R7 1<<15
- #define PM3FBDestReadEnables_ReferenceAlpha(a) (((a)&0xff)<<24)
+ #define PM3FBDestReadEnables_E(e) ((e) & 0xff)
+ #define PM3FBDestReadEnables_E0 (1 << 0)
+ #define PM3FBDestReadEnables_E1 (1 << 1)
+ #define PM3FBDestReadEnables_E2 (1 << 2)
+ #define PM3FBDestReadEnables_E3 (1 << 3)
+ #define PM3FBDestReadEnables_E4 (1 << 4)
+ #define PM3FBDestReadEnables_E5 (1 << 5)
+ #define PM3FBDestReadEnables_E6 (1 << 6)
+ #define PM3FBDestReadEnables_E7 (1 << 7)
+ #define PM3FBDestReadEnables_R(r) (((r) & 0xff) << 8)
+ #define PM3FBDestReadEnables_R0 (1 << 8)
+ #define PM3FBDestReadEnables_R1 (1 << 9)
+ #define PM3FBDestReadEnables_R2 (1 << 10)
+ #define PM3FBDestReadEnables_R3 (1 << 11)
+ #define PM3FBDestReadEnables_R4 (1 << 12)
+ #define PM3FBDestReadEnables_R5 (1 << 13)
+ #define PM3FBDestReadEnables_R6 (1 << 14)
+ #define PM3FBDestReadEnables_R7 (1 << 15)
+ #define PM3FBDestReadEnables_ReferenceAlpha(a) (((a) & 0xff) << 24)
#define PM3FBDestReadMode 0xaee0
#define PM3FBDestReadModeAnd 0xac90
#define PM3FBDestReadModeOr 0xac98
- #define PM3FBDestReadMode_ReadDisable 0<<0
- #define PM3FBDestReadMode_ReadEnable 1<<0
- #define PM3FBDestReadMode_StripePitch(sp) (((sp)&0x7)<<2)
- #define PM3FBDestReadMode_StripeHeight(sh) (((sh)&0x7)<<7)
- #define PM3FBDestReadMode_Enable0 1<<8
- #define PM3FBDestReadMode_Enable1 1<<9
- #define PM3FBDestReadMode_Enable2 1<<10
- #define PM3FBDestReadMode_Enable3 1<<11
- #define PM3FBDestReadMode_Layout0(l) (((l)&0x3)<<12)
- #define PM3FBDestReadMode_Layout1(l) (((l)&0x3)<<14)
- #define PM3FBDestReadMode_Layout2(l) (((l)&0x3)<<16)
- #define PM3FBDestReadMode_Layout3(l) (((l)&0x3)<<18)
- #define PM3FBDestReadMode_Origin0 1<<20
- #define PM3FBDestReadMode_Origin1 1<<21
- #define PM3FBDestReadMode_Origin2 1<<22
- #define PM3FBDestReadMode_Origin3 1<<23
- #define PM3FBDestReadMode_Blocking 1<<24
- #define PM3FBDestReadMode_UseReadEnabled 1<<26
- #define PM3FBDestReadMode_AlphaFiltering 1<<27
+ #define PM3FBDestReadMode_ReadDisable (0 << 0)
+ #define PM3FBDestReadMode_ReadEnable (1 << 0)
+ #define PM3FBDestReadMode_StripePitch(sp) (((sp) & 0x7) << 2)
+ #define PM3FBDestReadMode_StripeHeight(sh) (((sh) & 0x7) << 7)
+ #define PM3FBDestReadMode_Enable0 (1 << 8)
+ #define PM3FBDestReadMode_Enable1 (1 << 9)
+ #define PM3FBDestReadMode_Enable2 (1 << 10)
+ #define PM3FBDestReadMode_Enable3 (1 << 11)
+ #define PM3FBDestReadMode_Layout0(l) (((l) & 0x3) << 12)
+ #define PM3FBDestReadMode_Layout1(l) (((l) & 0x3) << 14)
+ #define PM3FBDestReadMode_Layout2(l) (((l) & 0x3) << 16)
+ #define PM3FBDestReadMode_Layout3(l) (((l) & 0x3) << 18)
+ #define PM3FBDestReadMode_Origin0 (1 << 20)
+ #define PM3FBDestReadMode_Origin1 (1 << 21)
+ #define PM3FBDestReadMode_Origin2 (1 << 22)
+ #define PM3FBDestReadMode_Origin3 (1 << 23)
+ #define PM3FBDestReadMode_Blocking (1 << 24)
+ #define PM3FBDestReadMode_UseReadEnabled (1 << 26)
+ #define PM3FBDestReadMode_AlphaFiltering (1 << 27)
#define PM3FBHardwareWriteMask 0x8ac0
#define PM3FBSoftwareWriteMask 0x8820
@@ -628,65 +606,65 @@
#define PM3FBSourceData 0x8aa8
#define PM3FBSourceReadBufferAddr 0xaf08
#define PM3FBSourceReadBufferOffset 0xaf10
- #define PM3FBSourceReadBufferOffset_XOffset(x) ((x)&0xffff)
- #define PM3FBSourceReadBufferOffset_YOffset(y) (((y)&0xffff)<<16)
+ #define PM3FBSourceReadBufferOffset_XOffset(x) ((x) & 0xffff)
+ #define PM3FBSourceReadBufferOffset_YOffset(y) (((y) & 0xffff) << 16)
#define PM3FBSourceReadBufferWidth 0xaf18
- #define PM3FBSourceReadBufferWidth_Width(w) ((w)&0x0fff)
+ #define PM3FBSourceReadBufferWidth_Width(w) ((w) & 0x0fff)
#define PM3FBSourceReadMode 0xaf00
#define PM3FBSourceReadModeAnd 0xaca0
#define PM3FBSourceReadModeOr 0xaca8
- #define PM3FBSourceReadMode_ReadDisable (0<<0)
- #define PM3FBSourceReadMode_ReadEnable (1<<0)
- #define PM3FBSourceReadMode_StripePitch(sp) (((sp)&0x7)<<2)
- #define PM3FBSourceReadMode_StripeHeight(sh) (((sh)&0x7)<<7)
- #define PM3FBSourceReadMode_Layout(l) (((l)&0x3)<<8)
- #define PM3FBSourceReadMode_Origin 1<<10
- #define PM3FBSourceReadMode_Blocking 1<<11
- #define PM3FBSourceReadMode_UserTexelCoord 1<<13
- #define PM3FBSourceReadMode_WrapXEnable 1<<14
- #define PM3FBSourceReadMode_WrapYEnable 1<<15
- #define PM3FBSourceReadMode_WrapX(w) (((w)&0xf)<<16)
- #define PM3FBSourceReadMode_WrapY(w) (((w)&0xf)<<20)
- #define PM3FBSourceReadMode_ExternalSourceData 1<<24
-#define PM3FBWriteBufferAddr0 0xb000
-#define PM3FBWriteBufferAddr1 0xb008
-#define PM3FBWriteBufferAddr2 0xb010
-#define PM3FBWriteBufferAddr3 0xb018
+ #define PM3FBSourceReadMode_ReadDisable (0 << 0)
+ #define PM3FBSourceReadMode_ReadEnable (1 << 0)
+ #define PM3FBSourceReadMode_StripePitch(sp) (((sp) & 0x7) << 2)
+ #define PM3FBSourceReadMode_StripeHeight(sh) (((sh) & 0x7) << 7)
+ #define PM3FBSourceReadMode_Layout(l) (((l) & 0x3) << 8)
+ #define PM3FBSourceReadMode_Origin (1 << 10)
+ #define PM3FBSourceReadMode_Blocking (1 << 11)
+ #define PM3FBSourceReadMode_UserTexelCoord (1 << 13)
+ #define PM3FBSourceReadMode_WrapXEnable (1 << 14)
+ #define PM3FBSourceReadMode_WrapYEnable (1 << 15)
+ #define PM3FBSourceReadMode_WrapX(w) (((w) & 0xf) << 16)
+ #define PM3FBSourceReadMode_WrapY(w) (((w) & 0xf) << 20)
+ #define PM3FBSourceReadMode_ExternalSourceData (1 << 24)
+#define PM3FBWriteBufferAddr0 0xb000
+#define PM3FBWriteBufferAddr1 0xb008
+#define PM3FBWriteBufferAddr2 0xb010
+#define PM3FBWriteBufferAddr3 0xb018
-#define PM3FBWriteBufferOffset0 0xb020
-#define PM3FBWriteBufferOffset1 0xb028
-#define PM3FBWriteBufferOffset2 0xb030
-#define PM3FBWriteBufferOffset3 0xb038
- #define PM3FBWriteBufferOffset_XOffset(x) ((x)&0xffff)
- #define PM3FBWriteBufferOffset_YOffset(y) (((y)&0xffff)<<16)
+#define PM3FBWriteBufferOffset0 0xb020
+#define PM3FBWriteBufferOffset1 0xb028
+#define PM3FBWriteBufferOffset2 0xb030
+#define PM3FBWriteBufferOffset3 0xb038
+ #define PM3FBWriteBufferOffset_XOffset(x) ((x) & 0xffff)
+ #define PM3FBWriteBufferOffset_YOffset(y) (((y) & 0xffff) << 16)
-#define PM3FBWriteBufferWidth0 0xb040
-#define PM3FBWriteBufferWidth1 0xb048
-#define PM3FBWriteBufferWidth2 0xb050
-#define PM3FBWriteBufferWidth3 0xb058
- #define PM3FBWriteBufferWidth_Width(w) ((w)&0x0fff)
+#define PM3FBWriteBufferWidth0 0xb040
+#define PM3FBWriteBufferWidth1 0xb048
+#define PM3FBWriteBufferWidth2 0xb050
+#define PM3FBWriteBufferWidth3 0xb058
+ #define PM3FBWriteBufferWidth_Width(w) ((w) & 0x0fff)
-#define PM3FBWriteMode 0x8ab8
-#define PM3FBWriteModeAnd 0xacf0
-#define PM3FBWriteModeOr 0xacf8
- #define PM3FBWriteMode_WriteDisable 0<<0
- #define PM3FBWriteMode_WriteEnable 1<<0
- #define PM3FBWriteMode_Replicate 1<<4
- #define PM3FBWriteMode_OpaqueSpan 1<<5
- #define PM3FBWriteMode_StripePitch(p) (((p)&0x7)<<6)
- #define PM3FBWriteMode_StripeHeight(h) (((h)&0x7)<<9)
- #define PM3FBWriteMode_Enable0 1<<12
- #define PM3FBWriteMode_Enable1 1<<13
- #define PM3FBWriteMode_Enable2 1<<14
- #define PM3FBWriteMode_Enable3 1<<15
- #define PM3FBWriteMode_Layout0(l) (((l)&0x3)<<16)
- #define PM3FBWriteMode_Layout1(l) (((l)&0x3)<<18)
- #define PM3FBWriteMode_Layout2(l) (((l)&0x3)<<20)
- #define PM3FBWriteMode_Layout3(l) (((l)&0x3)<<22)
- #define PM3FBWriteMode_Origin0 1<<24
- #define PM3FBWriteMode_Origin1 1<<25
- #define PM3FBWriteMode_Origin2 1<<26
- #define PM3FBWriteMode_Origin3 1<<27
+#define PM3FBWriteMode 0x8ab8
+#define PM3FBWriteModeAnd 0xacf0
+#define PM3FBWriteModeOr 0xacf8
+ #define PM3FBWriteMode_WriteDisable (0 << 0)
+ #define PM3FBWriteMode_WriteEnable (1 << 0)
+ #define PM3FBWriteMode_Replicate (1 << 4)
+ #define PM3FBWriteMode_OpaqueSpan (1 << 5)
+ #define PM3FBWriteMode_StripePitch(p) (((p) & 0x7) << 6)
+ #define PM3FBWriteMode_StripeHeight(h) (((h) & 0x7) << 9)
+ #define PM3FBWriteMode_Enable0 (1 << 12)
+ #define PM3FBWriteMode_Enable1 (1 << 13)
+ #define PM3FBWriteMode_Enable2 (1 << 14)
+ #define PM3FBWriteMode_Enable3 (1 << 15)
+ #define PM3FBWriteMode_Layout0(l) (((l) & 0x3) << 16)
+ #define PM3FBWriteMode_Layout1(l) (((l) & 0x3) << 18)
+ #define PM3FBWriteMode_Layout2(l) (((l) & 0x3) << 20)
+ #define PM3FBWriteMode_Layout3(l) (((l) & 0x3) << 22)
+ #define PM3FBWriteMode_Origin0 (1 << 24)
+ #define PM3FBWriteMode_Origin1 (1 << 25)
+ #define PM3FBWriteMode_Origin2 (1 << 26)
+ #define PM3FBWriteMode_Origin3 (1 << 27)
#define PM3ForegroundColor 0xb0c0
/* ... */
#define PM3GIDMode 0xb538
@@ -701,55 +679,55 @@
#define PM3LBDestReadMode 0xb500
#define PM3LBDestReadModeAnd 0xb580
#define PM3LBDestReadModeOr 0xb588
- #define PM3LBDestReadMode_Disable 0<<0
- #define PM3LBDestReadMode_Enable 1<<0
- #define PM3LBDestReadMode_StripePitch(p) (((p)&0x7)<<2)
- #define PM3LBDestReadMode_StripeHeight(h) (((h)&0x7)<<5)
- #define PM3LBDestReadMode_Layout 1<<8
- #define PM3LBDestReadMode_Origin 1<<9
- #define PM3LBDestReadMode_UserReadEnables 1<<10
- #define PM3LBDestReadMode_Packed16 1<<11
- #define PM3LBDestReadMode_Width(w) (((w)&0xfff)<<12)
+ #define PM3LBDestReadMode_Disable (0 << 0)
+ #define PM3LBDestReadMode_Enable (1 << 0)
+ #define PM3LBDestReadMode_StripePitch(p) (((p) & 0x7) << 2)
+ #define PM3LBDestReadMode_StripeHeight(h) (((h) & 0x7) << 5)
+ #define PM3LBDestReadMode_Layout (1 << 8)
+ #define PM3LBDestReadMode_Origin (1 << 9)
+ #define PM3LBDestReadMode_UserReadEnables (1 << 10)
+ #define PM3LBDestReadMode_Packed16 (1 << 11)
+ #define PM3LBDestReadMode_Width(w) (((w) & 0xfff) << 12)
#define PM3LBReadFormat 0x8888
- #define PM3LBReadFormat_DepthWidth(w) (((w)&0x3)<<0)
- #define PM3LBReadFormat_StencilWidth(w) (((w)&0xf)<<2)
- #define PM3LBReadFormat_StencilPosition(p) (((p)&0x1f)<<6)
- #define PM3LBReadFormat_FCPWidth(w) (((w)&0xf)<<11)
- #define PM3LBReadFormat_FCPPosition(p) (((p)&0x1f)<<15)
- #define PM3LBReadFormat_GIDWidth(w) (((w)&0x7)<<20)
- #define PM3LBReadFormat_GIDPosition(p) (((p)&0x1f)<<23)
+ #define PM3LBReadFormat_DepthWidth(w) (((w) & 0x3) << 0)
+ #define PM3LBReadFormat_StencilWidth(w) (((w) & 0xf) << 2)
+ #define PM3LBReadFormat_StencilPosition(p) (((p) & 0x1f) << 6)
+ #define PM3LBReadFormat_FCPWidth(w) (((w) & 0xf) << 11)
+ #define PM3LBReadFormat_FCPPosition(p) (((p) & 0x1f) << 15)
+ #define PM3LBReadFormat_GIDWidth(w) (((w) & 0x7) << 20)
+ #define PM3LBReadFormat_GIDPosition(p) (((p) & 0x1f) << 23)
#define PM3LBSourceReadBufferAddr 0xb528
#define PM3LBSourceReadBufferOffset 0xb530
#define PM3LBSourceReadMode 0xb520
#define PM3LBSourceReadModeAnd 0xb5a0
#define PM3LBSourceReadModeOr 0xb5a8
- #define PM3LBSourceReadMode_Enable 1<<0
- #define PM3LBSourceReadMode_StripePitch(p) (((p)&0x7)<<2)
- #define PM3LBSourceReadMode_StripeHeight(h) (((h)&0x7)<<5)
- #define PM3LBSourceReadMode_Layout 1<<8
- #define PM3LBSourceReadMode_Origin 1<<9
- #define PM3LBSourceReadMode_Packed16 1<<10
- #define PM3LBSourceReadMode_Width(w) (((w)&0xfff)<<11)
+ #define PM3LBSourceReadMode_Enable (1 << 0)
+ #define PM3LBSourceReadMode_StripePitch(p) (((p) & 0x7) << 2)
+ #define PM3LBSourceReadMode_StripeHeight(h) (((h) & 0x7) << 5)
+ #define PM3LBSourceReadMode_Layout (1 << 8)
+ #define PM3LBSourceReadMode_Origin (1 << 9)
+ #define PM3LBSourceReadMode_Packed16 (1 << 10)
+ #define PM3LBSourceReadMode_Width(w) (((w) & 0xfff) << 11)
#define PM3LBStencil 0x88a8
#define PM3LBWriteBufferAddr 0xb540
#define PM3LBWriteBufferOffset 0xb548
#define PM3LBWriteFormat 0x88c8
- #define PM3LBWriteFormat_DepthWidth(w) (((w)&0x3)<<0)
- #define PM3LBWriteFormat_StencilWidth(w) (((w)&0xf)<<2)
- #define PM3LBWriteFormat_StencilPosition(p) (((p)&0x1f)<<6)
- #define PM3LBWriteFormat_GIDWidth(w) (((w)&0x7)<<20)
- #define PM3LBWriteFormat_GIDPosition(p) (((p)&0x1f)<<23)
+ #define PM3LBWriteFormat_DepthWidth(w) (((w) & 0x3) << 0)
+ #define PM3LBWriteFormat_StencilWidth(w) (((w) & 0xf) << 2)
+ #define PM3LBWriteFormat_StencilPosition(p) (((p) & 0x1f) << 6)
+ #define PM3LBWriteFormat_GIDWidth(w) (((w) & 0x7) << 20)
+ #define PM3LBWriteFormat_GIDPosition(p) (((p) & 0x1f) << 23)
#define PM3LBWriteMode 0x88c0
#define PM3LBWriteModeAnd 0xac80
#define PM3LBWriteModeOr 0xac88
- #define PM3LBWriteMode_WriteDisable 0<<0
- #define PM3LBWriteMode_WriteEnable 1<<0
- #define PM3LBWriteMode_StripePitch(p) (((p)&0x7)<<3)
- #define PM3LBWriteMode_StripeHeight(h) (((h)&0x7)<<6)
- #define PM3LBWriteMode_Layout 1<<9
- #define PM3LBWriteMode_Origin 1<<10
- #define PM3LBWriteMode_Packed16 1<<11
- #define PM3LBWriteMode_Width(w) (((w)&0xfff)<<12)
+ #define PM3LBWriteMode_WriteDisable (0 << 0)
+ #define PM3LBWriteMode_WriteEnable (1 << 0)
+ #define PM3LBWriteMode_StripePitch(p) (((p) & 0x7) << 3)
+ #define PM3LBWriteMode_StripeHeight(h) (((h) & 0x7) << 6)
+ #define PM3LBWriteMode_Layout (1 << 9)
+ #define PM3LBWriteMode_Origin (1 << 10)
+ #define PM3LBWriteMode_Packed16 (1 << 11)
+ #define PM3LBWriteMode_Width(w) (((w) & 0xfff) << 12)
/* ... */
#define PM3LineStippleMode 0x81a8
#define PM3LineStippleModeAnd 0xabc0
@@ -759,19 +737,16 @@
#define PM3LogicalOpMode 0x8828
#define PM3LogicalOpModeAnd 0xace0
#define PM3LogicalOpModeOr 0xace8
- #define PM3LogicalOpMode_Disable (0<<0)
- #define PM3LogicalOpMode_Enable (1<<0)
- #define PM3LogicalOpMode_LogicOp(op) (((op)&0xf)<<1)
- #define PM3LogicalOpMode_UseConstantWriteData_Disable (0<<5)
- #define PM3LogicalOpMode_UseConstantWriteData_Enable (1<<5)
- #define PM3LogicalOpMode_Background_Disable (0<<6)
- #define PM3LogicalOpMode_Background_Enable (1<<6)
- #define PM3LogicalOpMode_Background_LogicOp(op) (((op)&0xf)<<7)
- #define PM3LogicalOpMode_UseConstantSource_Disable (0<<11)
- #define PM3LogicalOpMode_UseConstantSource_Enable (1<<11)
-
-/* ... */
-#define PM3LUT 0x8e80
+ #define PM3LogicalOpMode_Disable (0 << 0)
+ #define PM3LogicalOpMode_Enable (1 << 0)
+ #define PM3LogicalOpMode_LogicOp(op) (((op) & 0xf) << 1)
+ #define PM3LogicalOpMode_UseConstantWriteData_Disable (0 << 5)
+ #define PM3LogicalOpMode_UseConstantWriteData_Enable (1 << 5)
+ #define PM3LogicalOpMode_Background_Disable (0 << 6)
+ #define PM3LogicalOpMode_Background_Enable (1 << 6)
+ #define PM3LogicalOpMode_Background_LogicOp(op) (((op) & 0xf) << 7)
+ #define PM3LogicalOpMode_UseConstantSource_Disable (0 << 11)
+ #define PM3LogicalOpMode_UseConstantSource_Enable (1 << 11)
/* ... */
#define PM3LUT 0x8e80
#define PM3LUTAddress 0x84d0
@@ -783,75 +758,74 @@
#define PM3LUTTransfer 0x84d8
/* ... */
#define PM3PixelSize 0x80c0
- #define PM3PixelSize_GLOBAL_32BIT (0<<0)
- #define PM3PixelSize_GLOBAL_16BIT (1<<0)
- #define PM3PixelSize_GLOBAL_8BIT (2<<0)
- #define PM3PixelSize_RASTERIZER_32BIT (0<<2)
- #define PM3PixelSize_RASTERIZER_16BIT (1<<2)
- #define PM3PixelSize_RASTERIZER_8BIT (2<<2)
- #define PM3PixelSize_SCISSOR_AND_STIPPLE_32BIT (0<<4)
- #define PM3PixelSize_SCISSOR_AND_STIPPLE_16BIT (1<<4)
- #define PM3PixelSize_SCISSOR_AND_STIPPLE_8BIT (2<<4)
- #define PM3PixelSize_TEXTURE_32BIT (0<<6)
- #define PM3PixelSize_TEXTURE_16BIT (1<<6)
- #define PM3PixelSize_TEXTURE_8BIT (2<<6)
- #define PM3PixelSize_LUT_32BIT (0<<8)
- #define PM3PixelSize_LUT_16BIT (1<<8)
- #define PM3PixelSize_LUT_8BIT (2<<8)
- #define PM3PixelSize_FRAMEBUFFER_32BIT (0<<10)
- #define PM3PixelSize_FRAMEBUFFER_16BIT (1<<10)
- #define PM3PixelSize_FRAMEBUFFER_8BIT (2<<10)
- #define PM3PixelSize_LOGICAL_OP_32BIT (0<<12)
- #define PM3PixelSize_LOGICAL_OP_16BIT (1<<12)
- #define PM3PixelSize_LOGICAL_OP_8BIT (2<<12)
- #define PM3PixelSize_LOCALBUFFER_32BIT (0<<14)
- #define PM3PixelSize_LOCALBUFFER_16BIT (1<<14)
- #define PM3PixelSize_LOCALBUFFER_8BIT (2<<14)
- #define PM3PixelSize_SETUP_32BIT (0<<16)
- #define PM3PixelSize_SETUP_16BIT (1<<16)
- #define PM3PixelSize_SETUP_8BIT (2<<16)
- #define PM3PixelSize_GLOBAL (0<<31)
- #define PM3PixelSize_INDIVIDUAL (1<<31)
+ #define PM3PixelSize_GLOBAL_32BIT (0 << 0)
+ #define PM3PixelSize_GLOBAL_16BIT (1 << 0)
+ #define PM3PixelSize_GLOBAL_8BIT (2 << 0)
+ #define PM3PixelSize_RASTERIZER_32BIT (0 << 2)
+ #define PM3PixelSize_RASTERIZER_16BIT (1 << 2)
+ #define PM3PixelSize_RASTERIZER_8BIT (2 << 2)
+ #define PM3PixelSize_SCISSOR_AND_STIPPLE_32BIT (0 << 4)
+ #define PM3PixelSize_SCISSOR_AND_STIPPLE_16BIT (1 << 4)
+ #define PM3PixelSize_SCISSOR_AND_STIPPLE_8BIT (2 << 4)
+ #define PM3PixelSize_TEXTURE_32BIT (0 << 6)
+ #define PM3PixelSize_TEXTURE_16BIT (1 << 6)
+ #define PM3PixelSize_TEXTURE_8BIT (2 << 6)
+ #define PM3PixelSize_LUT_32BIT (0 << 8)
+ #define PM3PixelSize_LUT_16BIT (1 << 8)
+ #define PM3PixelSize_LUT_8BIT (2 << 8)
+ #define PM3PixelSize_FRAMEBUFFER_32BIT (0 << 10)
+ #define PM3PixelSize_FRAMEBUFFER_16BIT (1 << 10)
+ #define PM3PixelSize_FRAMEBUFFER_8BIT (2 << 10)
+ #define PM3PixelSize_LOGICAL_OP_32BIT (0 << 12)
+ #define PM3PixelSize_LOGICAL_OP_16BIT (1 << 12)
+ #define PM3PixelSize_LOGICAL_OP_8BIT (2 << 12)
+ #define PM3PixelSize_LOCALBUFFER_32BIT (0 << 14)
+ #define PM3PixelSize_LOCALBUFFER_16BIT (1 << 14)
+ #define PM3PixelSize_LOCALBUFFER_8BIT (2 << 14)
+ #define PM3PixelSize_SETUP_32BIT (0 << 16)
+ #define PM3PixelSize_SETUP_16BIT (1 << 16)
+ #define PM3PixelSize_SETUP_8BIT (2 << 16)
+ #define PM3PixelSize_GLOBAL (0 << 31)
+ #define PM3PixelSize_INDIVIDUAL (1 << 31)
/* ... */
#define PM3Render 0x8038
- #define PM3Render_AreaStipple_Disable (0<<0)
- #define PM3Render_AreaStipple_Enable (1<<0)
- #define PM3Render_LineStipple_Disable (0<<1)
- #define PM3Render_LineStipple_Enable (1<<1)
- #define PM3Render_ResetLine_Disable (0<<2)
- #define PM3Render_ResetLine_Enable (1<<2)
- #define PM3Render_FastFill_Disable (0<<3)
- #define PM3Render_FastFill_Enable (1<<3)
- #define PM3Render_Primitive_Line (0<<6)
- #define PM3Render_Primitive_Trapezoid (1<<6)
- #define PM3Render_Primitive_Point (2<<6)
- #define PM3Render_Antialias_Disable (0<<8)
- #define PM3Render_Antialias_Enable (1<<8)
- #define PM3Render_Antialias_SubPixelRes_4x4 (0<<9)
- #define PM3Render_Antialias_SubPixelRes_8x8 (1<<9)
- #define PM3Render_UsePointTable_Disable (0<<10)
- #define PM3Render_UsePointTable_Enable (1<<10)
- #define PM3Render_SyncOnbitMask_Disable (0<<11)
- #define PM3Render_SyncOnBitMask_Enable (1<<11)
- #define PM3Render_SyncOnHostData_Disable (0<<12)
- #define PM3Render_SyncOnHostData_Enable (1<<12)
- #define PM3Render_Texture_Disable (0<<13)
- #define PM3Render_Texture_Enable (1<<13)
- #define PM3Render_Fog_Disable (0<<14)
- #define PM3Render_Fog_Enable (1<<14)
- #define PM3Render_Coverage_Disable (0<<15)
- #define PM3Render_Coverage_Enable (1<<15)
- #define PM3Render_SubPixelCorrection_Disable (0<<16)
- #define PM3Render_SubPixelCorrection_Enable (1<<16)
- #define PM3Render_SpanOperation_Disable (0<<18)
- #define PM3Render_SpanOperation_Enable (1<<18)
- #define PM3Render_FBSourceRead_Disable (0<<27)
- #define PM3Render_FBSourceRead_Enable (1<<27)
+ #define PM3Render_AreaStipple_Disable (0 << 0)
+ #define PM3Render_AreaStipple_Enable (1 << 0)
+ #define PM3Render_LineStipple_Disable (0 << 1)
+ #define PM3Render_LineStipple_Enable (1 << 1)
+ #define PM3Render_ResetLine_Disable (0 << 2)
+ #define PM3Render_ResetLine_Enable (1 << 2)
+ #define PM3Render_FastFill_Disable (0 << 3)
+ #define PM3Render_FastFill_Enable (1 << 3)
+ #define PM3Render_Primitive_Line (0 << 6)
+ #define PM3Render_Primitive_Trapezoid (1 << 6)
+ #define PM3Render_Primitive_Point (2 << 6)
+ #define PM3Render_Antialias_Disable (0 << 8)
+ #define PM3Render_Antialias_Enable (1 << 8)
+ #define PM3Render_Antialias_SubPixelRes_4x4 (0 << 9)
+ #define PM3Render_Antialias_SubPixelRes_8x8 (1 << 9)
+ #define PM3Render_UsePointTable_Disable (0 << 10)
+ #define PM3Render_UsePointTable_Enable (1 << 10)
+ #define PM3Render_SyncOnbitMask_Disable (0 << 11)
+ #define PM3Render_SyncOnBitMask_Enable (1 << 11)
+ #define PM3Render_SyncOnHostData_Disable (0 << 12)
+ #define PM3Render_SyncOnHostData_Enable (1 << 12)
+ #define PM3Render_Texture_Disable (0 << 13)
+ #define PM3Render_Texture_Enable (1 << 13)
+ #define PM3Render_Fog_Disable (0 << 14)
+ #define PM3Render_Fog_Enable (1 << 14)
+ #define PM3Render_Coverage_Disable (0 << 15)
+ #define PM3Render_Coverage_Enable (1 << 15)
+ #define PM3Render_SubPixelCorrection_Disable (0 << 16)
+ #define PM3Render_SubPixelCorrection_Enable (1 << 16)
+ #define PM3Render_SpanOperation_Disable (0 << 18)
+ #define PM3Render_SpanOperation_Enable (1 << 18)
+ #define PM3Render_FBSourceRead_Disable (0 << 27)
+ #define PM3Render_FBSourceRead_Enable (1 << 27)
#define PM3RasterizerMode 0x80a0
#define PM3RasterizerModeAnd 0xaba0
-#define PM3RasterizerModeOr 0xabb8
+#define PM3RasterizerModeOr 0xaba8
#define PM3RectangleHeight 0x94e0
-#define PM3Render 0x8038
#define PM3RepeatLine 0x9328
#define PM3ResetPickResult 0x8c20
#define PM3RLEMask 0x8c48
@@ -918,31 +892,31 @@
#define PM3TextureIndexMode1And 0xb3d0
#define PM3TextureIndexMode1Or 0xb3d8
/* ... */
-#define PM3TextureMapSize 0xb428
-#define PM3TextureMapWidth0 0x8580
-#define PM3TextureMapWidth1 0x8588
- #define PM3TextureMapWidth_Width(w) ((w&0xfff)<<0)
- #define PM3TextureMapWidth_BorderLayout (1<<12)
- #define PM3TextureMapWidth_Layout_Linear (0<<13)
- #define PM3TextureMapWidth_Layout_Patch64 (1<<13)
- #define PM3TextureMapWidth_Layout_Patch32_2 (2<<13)
- #define PM3TextureMapWidth_Layout_Patch2 (3<<13)
- #define PM3TextureMapWidth_HostTexture (1<<15)
-#define PM3TextureReadMode0 0xb400
-#define PM3TextureReadMode0And 0xac30
-#define PM3TextureReadMode0Or 0xac38
-#define PM3TextureReadMode1 0xb408
-#define PM3TextureReadMode1And 0xad40
-#define PM3TextureReadMode1Or 0xad48
+#define PM3TextureMapSize 0xb428
+#define PM3TextureMapWidth0 0x8580
+#define PM3TextureMapWidth1 0x8588
+ #define PM3TextureMapWidth_Width(w) (((w) & 0xfff) << 0)
+ #define PM3TextureMapWidth_BorderLayout (1 << 12)
+ #define PM3TextureMapWidth_Layout_Linear (0 << 13)
+ #define PM3TextureMapWidth_Layout_Patch64 (1 << 13)
+ #define PM3TextureMapWidth_Layout_Patch32_2 (2 << 13)
+ #define PM3TextureMapWidth_Layout_Patch2 (3 << 13)
+ #define PM3TextureMapWidth_HostTexture (1 << 15)
+#define PM3TextureReadMode0 0xb400
+#define PM3TextureReadMode0And 0xac30
+#define PM3TextureReadMode0Or 0xac38
+#define PM3TextureReadMode1 0xb408
+#define PM3TextureReadMode1And 0xad40
+#define PM3TextureReadMode1Or 0xad48
/* ... */
#define PM3WaitForCompletion 0x80b8
#define PM3Window 0x8980
- #define PM3Window_ForceLBUpdate 1<<3
- #define PM3Window_LBUpdateSource 1<<4
- #define PM3Window_FrameCount(c) (((c)&0xff)<<9)
- #define PM3Window_StencilFCP 1<<17
- #define PM3Window_DepthFCP 1<<18
- #define PM3Window_OverrideWriteFiltering 1<<19
+ #define PM3Window_ForceLBUpdate (1 << 3)
+ #define PM3Window_LBUpdateSource (1 << 4)
+ #define PM3Window_FrameCount(c) (((c) & 0xff) << 9)
+ #define PM3Window_StencilFCP (1 << 17)
+ #define PM3Window_DepthFCP (1 << 18)
+ #define PM3Window_OverrideWriteFiltering (1 << 19)
#define PM3WindowAnd 0xab80
#define PM3WindowOr 0xab88
#define PM3WindowOrigin 0x81c8
@@ -957,169 +931,131 @@
/**********************************************
-* GLINT Permedia3 2D setup Unit *
+* GLINT Permedia3 2D setup Unit *
***********************************************/
#define PM3Config2D 0xb618
- #define PM3Config2D_OpaqueSpan 1<<0
- #define PM3Config2D_MultiRXBlit 1<<1
- #define PM3Config2D_UserScissorEnable 1<<2
- #define PM3Config2D_FBDestReadEnable 1<<3
- #define PM3Config2D_AlphaBlendEnable 1<<4
- #define PM3Config2D_DitherEnable 1<<5
- #define PM3Config2D_ForegroundROPEnable 1<<6
- #define PM3Config2D_ForegroundROP(rop) (((rop)&0xf)<<7)
- #define PM3Config2D_BackgroundROPEnable 1<<11
- #define PM3Config2D_BackgroundROP(rop) (((rop)&0xf)<<12)
- #define PM3Config2D_UseConstantSource 1<<16
- #define PM3Config2D_FBWriteEnable 1<<17
- #define PM3Config2D_Blocking 1<<18
- #define PM3Config2D_ExternalSourceData 1<<19
- #define PM3Config2D_LUTModeEnable 1<<20
+ #define PM3Config2D_OpaqueSpan (1 << 0)
+ #define PM3Config2D_MultiRXBlit (1 << 1)
+ #define PM3Config2D_UserScissorEnable (1 << 2)
+ #define PM3Config2D_FBDestReadEnable (1 << 3)
+ #define PM3Config2D_AlphaBlendEnable (1 << 4)
+ #define PM3Config2D_DitherEnable (1 << 5)
+ #define PM3Config2D_ForegroundROPEnable (1 << 6)
+ #define PM3Config2D_ForegroundROP(rop) (((rop) & 0xf) << 7)
+ #define PM3Config2D_BackgroundROPEnable (1 << 11)
+ #define PM3Config2D_BackgroundROP(rop) (((rop) & 0xf) << 12)
+ #define PM3Config2D_UseConstantSource (1 << 16)
+ #define PM3Config2D_FBWriteEnable (1 << 17)
+ #define PM3Config2D_Blocking (1 << 18)
+ #define PM3Config2D_ExternalSourceData (1 << 19)
+ #define PM3Config2D_LUTModeEnable (1 << 20)
#define PM3DownloadGlyphwidth 0xb658
- #define PM3DownloadGlyphwidth_GlyphWidth(gw) ((gw)&0xffff)
+ #define PM3DownloadGlyphwidth_GlyphWidth(gw) ((gw) & 0xffff)
#define PM3DownloadTarget 0xb650
- #define PM3DownloadTarget_TagName(tag) ((tag)&0x1fff)
+ #define PM3DownloadTarget_TagName(tag) ((tag) & 0x1fff)
#define PM3GlyphData 0xb660
#define PM3GlyphPosition 0xb608
- #define PM3GlyphPosition_XOffset(x) ((x)&0xffff)
- #define PM3GlyphPosition_YOffset(y) (((y)&0xffff)<<16)
+ #define PM3GlyphPosition_XOffset(x) ((x) & 0xffff)
+ #define PM3GlyphPosition_YOffset(y) (((y) & 0xffff) << 16)
#define PM3Packed4Pixels 0xb668
#define PM3Packed8Pixels 0xb630
#define PM3Packed16Pixels 0xb638
#define PM3RectanglePosition 0xb600
- #define PM3RectanglePosition_XOffset(x) ((x)&0xffff)
- #define PM3RectanglePosition_YOffset(y) (((y)&0xffff)<<16)
+ #define PM3RectanglePosition_XOffset(x) ((x) & 0xffff)
+ #define PM3RectanglePosition_YOffset(y) (((y) & 0xffff) << 16)
#define PM3Render2D 0xb640
- #define PM3Render2D_Width(w) ((w)&0x0fff)
- #define PM3Render2D_Operation_Normal 0<<12
- #define PM3Render2D_Operation_SyncOnHostData 1<<12
- #define PM3Render2D_Operation_SyncOnBitMask 2<<12
- #define PM3Render2D_Operation_PatchOrderRendering 3<<12
- #define PM3Render2D_FBSourceReadEnable 1<<14
- #define PM3Render2D_SpanOperation 1<<15
- #define PM3Render2D_Height(h) (((h)&0x0fff)<<16)
- #define PM3Render2D_XPositive 1<<28
- #define PM3Render2D_YPositive 1<<29
- #define PM3Render2D_AreaStippleEnable 1<<30
- #define PM3Render2D_TextureEnable 1<<31
+ #define PM3Render2D_Width(w) ((w) & 0x0fff)
+ #define PM3Render2D_Operation_Normal (0 << 12)
+ #define PM3Render2D_Operation_SyncOnHostData (1 << 12)
+ #define PM3Render2D_Operation_SyncOnBitMask (2 << 12)
+ #define PM3Render2D_Operation_PatchOrderRendering (3 << 12)
+ #define PM3Render2D_FBSourceReadEnable (1 << 14)
+ #define PM3Render2D_SpanOperation (1 << 15)
+ #define PM3Render2D_Height(h) (((h) & 0x0fff) << 16)
+ #define PM3Render2D_XPositive (1 << 28)
+ #define PM3Render2D_YPositive (1 << 29)
+ #define PM3Render2D_AreaStippleEnable (1 << 30)
+ #define PM3Render2D_TextureEnable (1 << 31)
#define PM3Render2DGlyph 0xb648
- #define PM3Render2DGlyph_Width(w) ((w)&0x7f)
- #define PM3Render2DGlyph_Height(h) (((h)&0x7f)<<7)
- #define PM3Render2DGlyph_XOffset(x) (((x)&0x1ff)<<14)
- #define PM3Render2DGlyph_YOffset(y) (((y)&0x1ff)<<23)
+ #define PM3Render2DGlyph_Width(w) ((w) & 0x7f)
+ #define PM3Render2DGlyph_Height(h) (((h) & 0x7f) << 7)
+ #define PM3Render2DGlyph_XOffset(x) (((x) & 0x1ff) << 14)
+ #define PM3Render2DGlyph_YOffset(y) (((y) & 0x1ff) << 23)
#define PM3RenderPatchOffset 0xb610
- #define PM3RenderPatchOffset_XOffset(x) ((x)&0xffff)
- #define PM3RenderPatchOffset_YOffset(y) (((y)&0xffff)<<16)
+ #define PM3RenderPatchOffset_XOffset(x) ((x) & 0xffff)
+ #define PM3RenderPatchOffset_YOffset(y) (((y) & 0xffff) << 16)
#define PM3RLCount 0xb678
- #define PM3RLCount_Count(c) ((c)&0x0fff)
+ #define PM3RLCount_Count(c) ((c) & 0x0fff)
#define PM3RLData 0xb670
/**********************************************
-* GLINT Permedia3 Alias Register *
+* GLINT Permedia3 Alias Register *
***********************************************/
-#define PM3FillBackgroundColor 0x8330
-#define PM3FillConfig2D0 0x8338
-#define PM3FillConfig2D1 0x8360
- #define PM3FillConfig2D_OpaqueSpan 1<<0
- #define PM3FillConfig2D_MultiRXBlit 1<<1
- #define PM3FillConfig2D_UserScissorEnable 1<<2
- #define PM3FillConfig2D_FBDestReadEnable 1<<3
- #define PM3FillConfig2D_AlphaBlendEnable 1<<4
- #define PM3FillConfig2D_DitherEnable 1<<5
- #define PM3FillConfig2D_ForegroundROPEnable 1<<6
- #define PM3FillConfig2D_ForegroundROP(rop) (((rop)&0xf)<<7)
- #define PM3FillConfig2D_BackgroundROPEnable 1<<11
- #define PM3FillConfig2D_BackgroundROP(rop) (((rop)&0xf)<<12)
- #define PM3FillConfig2D_UseConstantSource 1<<16
- #define PM3FillConfig2D_FBWriteEnable 1<<17
- #define PM3FillConfig2D_Blocking 1<<18
- #define PM3FillConfig2D_ExternalSourceData 1<<19
- #define PM3FillConfig2D_LUTModeEnable 1<<20
-#define PM3FillFBDestReadBufferAddr 0x8310
-#define PM3FillFBSourceReadBufferAddr 0x8308
-#define PM3FillFBSourceReadBufferOffset 0x8340
- #define PM3FillFBSourceReadBufferOffset_XOffset(x) ((x)&0xffff)
- #define PM3FillFBSourceReadBufferOffset_YOffset(y) (((y)&0xffff)<<16)
-#define PM3FillFBWriteBufferAddr 0x8300
-#define PM3FillForegroundColor0 0x8328
-#define PM3FillForegroundColor1 0x8358
-#define PM3FillGlyphPosition 0x8368
- #define PM3FillGlyphPosition_XOffset(x) ((x)&0xffff)
- #define PM3FillGlyphPosition_YOffset(y) (((y)&0xffff)<<16)
-#define PM3FillRectanglePosition 0x8348
- #define PM3FillRectanglePosition_XOffset(x) ((x)&0xffff)
- #define PM3FillRectanglePosition_YOffset(y) (((y)&0xffff)<<16)
+#define PM3FillBackgroundColor 0x8330
+#define PM3FillConfig2D0 0x8338
+#define PM3FillConfig2D1 0x8360
+ #define PM3FillConfig2D_OpaqueSpan (1 << 0)
+ #define PM3FillConfig2D_MultiRXBlit (1 << 1)
+ #define PM3FillConfig2D_UserScissorEnable (1 << 2)
+ #define PM3FillConfig2D_FBDestReadEnable (1 << 3)
+ #define PM3FillConfig2D_AlphaBlendEnable (1 << 4)
+ #define PM3FillConfig2D_DitherEnable (1 << 5)
+ #define PM3FillConfig2D_ForegroundROPEnable (1 << 6)
+ #define PM3FillConfig2D_ForegroundROP(rop) (((rop) & 0xf) << 7)
+ #define PM3FillConfig2D_BackgroundROPEnable (1 << 11)
+ #define PM3FillConfig2D_BackgroundROP(rop) (((rop) & 0xf) << 12)
+ #define PM3FillConfig2D_UseConstantSource (1 << 16)
+ #define PM3FillConfig2D_FBWriteEnable (1 << 17)
+ #define PM3FillConfig2D_Blocking (1 << 18)
+ #define PM3FillConfig2D_ExternalSourceData (1 << 19)
+ #define PM3FillConfig2D_LUTModeEnable (1 << 20)
+#define PM3FillFBDestReadBufferAddr 0x8310
+#define PM3FillFBSourceReadBufferAddr 0x8308
+#define PM3FillFBSourceReadBufferOffset 0x8340
+ #define PM3FillFBSourceReadBufferOffset_XOffset(x) ((x) & 0xffff)
+ #define PM3FillFBSourceReadBufferOffset_YOffset(y) \
+ (((y) & 0xffff) << 16)
+#define PM3FillFBWriteBufferAddr 0x8300
+#define PM3FillForegroundColor0 0x8328
+#define PM3FillForegroundColor1 0x8358
+#define PM3FillGlyphPosition 0x8368
+ #define PM3FillGlyphPosition_XOffset(x) ((x) & 0xffff)
+ #define PM3FillGlyphPosition_YOffset(y) (((y) & 0xffff) << 16)
+#define PM3FillRectanglePosition 0x8348
+ #define PM3FillRectanglePosition_XOffset(x) ((x) & 0xffff)
+ #define PM3FillRectanglePosition_YOffset(y) (((y) & 0xffff) << 16)
-#define PM3_REGS_SIZE 0x10000
-#define PM3_MAX_PIXCLOCK 300000
/* a few more useful registers & regs value... */
-#define PM3Sync 0x8c40
- #define PM3Sync_Tag 0x188
-#define PM3FilterMode 0x8c00
- #define PM3FilterModeSync 0x400
-#define PM3OutputFifo 0x2000
-#define PM3StatisticMode 0x8c08
-#define PM3AreaStippleMode 0x81a0
- #define AreaStipplePattern0 (0x8200)
- #define AreaStipplePattern1 (0x8208)
- #define AreaStipplePattern2 (0x8210)
- #define AreaStipplePattern3 (0x8218)
- #define AreaStipplePattern4 (0x8220)
- #define AreaStipplePattern5 (0x8228)
- #define AreaStipplePattern6 (0x8230)
- #define AreaStipplePattern7 (0x8238)
- #define AreaStipplePattern8 (0x8240)
- #define AreaStipplePattern9 (0x8248)
- #define AreaStipplePattern10 (0x8250)
- #define AreaStipplePattern11 (0x8258)
- #define AreaStipplePattern12 (0x8260)
- #define AreaStipplePattern13 (0x8268)
- #define AreaStipplePattern14 (0x8270)
- #define AreaStipplePattern15 (0x8278)
- #define AreaStipplePattern16 (0x8280)
- #define AreaStipplePattern17 (0x8288)
- #define AreaStipplePattern18 (0x8290)
- #define AreaStipplePattern19 (0x8298)
- #define AreaStipplePattern20 (0x82a0)
- #define AreaStipplePattern21 (0x82a8)
- #define AreaStipplePattern22 (0x82b0)
- #define AreaStipplePattern23 (0x82b8)
- #define AreaStipplePattern24 (0x82c0)
- #define AreaStipplePattern25 (0x82c8)
- #define AreaStipplePattern26 (0x82d0)
- #define AreaStipplePattern27 (0x82d8)
- #define AreaStipplePattern28 (0x82eo)
- #define AreaStipplePattern29 (0x82e8)
- #define AreaStipplePattern30 (0x82f0)
- #define AreaStipplePattern31 (0x82f8)
- #define AreaStipplePattern_indexed(i) (0x8200 + ((i) * 0x8))
+#define PM3Sync 0x8c40
+ #define PM3Sync_Tag 0x188
+#define PM3FilterMode 0x8c00
+ #define PM3FilterModeSync 0x400
+#define PM3OutputFifo 0x2000
+#define PM3StatisticMode 0x8c08
+#define PM3AreaStippleMode 0x81a0
+#define AreaStipplePattern_indexed(i) (0x8200 + ((i) * 0x8))
-#define PM3DepthMode 0x89a0
-#define PM3StencilMode 0x8988
-#define PM3StencilData 0x8990
-#define PM3TextureReadMode 0x8670
-#define PM3FogMode 0x8690
-#define PM3ChromaTestMode 0x8f18
-#define PM3YUVMode 0x8f00
-#define PM3BitMaskPattern 0x8068
+#define PM3DepthMode 0x89a0
+#define PM3StencilMode 0x8988
+#define PM3StencilData 0x8990
+#define PM3TextureReadMode 0x8670
+#define PM3FogMode 0x8690
+#define PM3ChromaTestMode 0x8f18
+#define PM3YUVMode 0x8f00
+#define PM3BitMaskPattern 0x8068
/* ***************************** */
/* ***** pm3fb IOCTL const ***** */
/* ***************************** */
-/* debug-only IOCTL */
-#define PM3FBIO_CLEARMEMORY 0x504D3300 /* 'PM3\000' */
-#define PM3FBIO_CLEARCMAP 0x504D3301 /* 'PM3\001' */
-/* common use IOCTL */
-#define PM3FBIO_RESETCHIP 0x504D33FF /* 'PM3\377' */
+#define PM3FBIO_RESETCHIP 0x504D33FF /* 'PM3\377' */
/* ***************************************** */
/* ***** pm3fb useful define and macro ***** */
/* ***************************************** */
-/* max size of options */
-#define PM3_OPTIONS_SIZE 256
-
-/* max size of font name */
-#define PM3_FONTNAME_SIZE 40
+/* fifo size in chip */
+#define PM3_FIFO_SIZE 120
+#define PM3_REGS_SIZE 0x10000
+#define PM3_MAX_PIXCLOCK 300000
#endif /* PM3FB_H */
diff --git a/include/video/sstfb.h b/include/video/sstfb.h
index baa163f770ab..b52f07381243 100644
--- a/include/video/sstfb.h
+++ b/include/video/sstfb.h
@@ -68,7 +68,6 @@
# define print_var(X,Y...)
#endif
-#define BIT(x) (1ul<<(x))
#define POW2(x) (1ul<<(x))
/*
diff --git a/include/video/tdfx.h b/include/video/tdfx.h
index c1cc94ba3fdd..7431d9681e57 100644
--- a/include/video/tdfx.h
+++ b/include/video/tdfx.h
@@ -2,140 +2,138 @@
#define _TDFX_H
/* membase0 register offsets */
-#define STATUS 0x00
-#define PCIINIT0 0x04
-#define SIPMONITOR 0x08
-#define LFBMEMORYCONFIG 0x0c
-#define MISCINIT0 0x10
-#define MISCINIT1 0x14
-#define DRAMINIT0 0x18
-#define DRAMINIT1 0x1c
-#define AGPINIT 0x20
-#define TMUGBEINIT 0x24
-#define VGAINIT0 0x28
-#define VGAINIT1 0x2c
-#define DRAMCOMMAND 0x30
-#define DRAMDATA 0x34
-/* reserved 0x38 */
-/* reserved 0x3c */
-#define PLLCTRL0 0x40
-#define PLLCTRL1 0x44
-#define PLLCTRL2 0x48
-#define DACMODE 0x4c
-#define DACADDR 0x50
-#define DACDATA 0x54
-#define RGBMAXDELTA 0x58
-#define VIDPROCCFG 0x5c
-#define HWCURPATADDR 0x60
-#define HWCURLOC 0x64
-#define HWCURC0 0x68
-#define HWCURC1 0x6c
-#define VIDINFORMAT 0x70
-#define VIDINSTATUS 0x74
-#define VIDSERPARPORT 0x78
-#define VIDINXDELTA 0x7c
-#define VIDININITERR 0x80
-#define VIDINYDELTA 0x84
-#define VIDPIXBUFTHOLD 0x88
-#define VIDCHRMIN 0x8c
-#define VIDCHRMAX 0x90
-#define VIDCURLIN 0x94
-#define VIDSCREENSIZE 0x98
-#define VIDOVRSTARTCRD 0x9c
-#define VIDOVRENDCRD 0xa0
-#define VIDOVRDUDX 0xa4
-#define VIDOVRDUDXOFF 0xa8
-#define VIDOVRDVDY 0xac
-/* ... */
-#define VIDOVRDVDYOFF 0xe0
-#define VIDDESKSTART 0xe4
-#define VIDDESKSTRIDE 0xe8
-#define VIDINADDR0 0xec
-#define VIDINADDR1 0xf0
-#define VIDINADDR2 0xf4
-#define VIDINSTRIDE 0xf8
-#define VIDCUROVRSTART 0xfc
-
-#define INTCTRL (0x00100000 + 0x04)
-#define CLIP0MIN (0x00100000 + 0x08)
-#define CLIP0MAX (0x00100000 + 0x0c)
-#define DSTBASE (0x00100000 + 0x10)
-#define DSTFORMAT (0x00100000 + 0x14)
-#define SRCBASE (0x00100000 + 0x34)
-#define COMMANDEXTRA_2D (0x00100000 + 0x38)
-#define CLIP1MIN (0x00100000 + 0x4c)
-#define CLIP1MAX (0x00100000 + 0x50)
-#define SRCFORMAT (0x00100000 + 0x54)
-#define SRCSIZE (0x00100000 + 0x58)
-#define SRCXY (0x00100000 + 0x5c)
-#define COLORBACK (0x00100000 + 0x60)
-#define COLORFORE (0x00100000 + 0x64)
-#define DSTSIZE (0x00100000 + 0x68)
-#define DSTXY (0x00100000 + 0x6c)
-#define COMMAND_2D (0x00100000 + 0x70)
-#define LAUNCH_2D (0x00100000 + 0x80)
-
-#define COMMAND_3D (0x00200000 + 0x120)
+#define STATUS 0x00
+#define PCIINIT0 0x04
+#define SIPMONITOR 0x08
+#define LFBMEMORYCONFIG 0x0c
+#define MISCINIT0 0x10
+#define MISCINIT1 0x14
+#define DRAMINIT0 0x18
+#define DRAMINIT1 0x1c
+#define AGPINIT 0x20
+#define TMUGBEINIT 0x24
+#define VGAINIT0 0x28
+#define VGAINIT1 0x2c
+#define DRAMCOMMAND 0x30
+#define DRAMDATA 0x34
+/* reserved 0x38 */
+/* reserved 0x3c */
+#define PLLCTRL0 0x40
+#define PLLCTRL1 0x44
+#define PLLCTRL2 0x48
+#define DACMODE 0x4c
+#define DACADDR 0x50
+#define DACDATA 0x54
+#define RGBMAXDELTA 0x58
+#define VIDPROCCFG 0x5c
+#define HWCURPATADDR 0x60
+#define HWCURLOC 0x64
+#define HWCURC0 0x68
+#define HWCURC1 0x6c
+#define VIDINFORMAT 0x70
+#define VIDINSTATUS 0x74
+#define VIDSERPARPORT 0x78
+#define VIDINXDELTA 0x7c
+#define VIDININITERR 0x80
+#define VIDINYDELTA 0x84
+#define VIDPIXBUFTHOLD 0x88
+#define VIDCHRMIN 0x8c
+#define VIDCHRMAX 0x90
+#define VIDCURLIN 0x94
+#define VIDSCREENSIZE 0x98
+#define VIDOVRSTARTCRD 0x9c
+#define VIDOVRENDCRD 0xa0
+#define VIDOVRDUDX 0xa4
+#define VIDOVRDUDXOFF 0xa8
+#define VIDOVRDVDY 0xac
+/* ... */
+#define VIDOVRDVDYOFF 0xe0
+#define VIDDESKSTART 0xe4
+#define VIDDESKSTRIDE 0xe8
+#define VIDINADDR0 0xec
+#define VIDINADDR1 0xf0
+#define VIDINADDR2 0xf4
+#define VIDINSTRIDE 0xf8
+#define VIDCUROVRSTART 0xfc
+
+#define INTCTRL (0x00100000 + 0x04)
+#define CLIP0MIN (0x00100000 + 0x08)
+#define CLIP0MAX (0x00100000 + 0x0c)
+#define DSTBASE (0x00100000 + 0x10)
+#define DSTFORMAT (0x00100000 + 0x14)
+#define SRCBASE (0x00100000 + 0x34)
+#define COMMANDEXTRA_2D (0x00100000 + 0x38)
+#define CLIP1MIN (0x00100000 + 0x4c)
+#define CLIP1MAX (0x00100000 + 0x50)
+#define SRCFORMAT (0x00100000 + 0x54)
+#define SRCSIZE (0x00100000 + 0x58)
+#define SRCXY (0x00100000 + 0x5c)
+#define COLORBACK (0x00100000 + 0x60)
+#define COLORFORE (0x00100000 + 0x64)
+#define DSTSIZE (0x00100000 + 0x68)
+#define DSTXY (0x00100000 + 0x6c)
+#define COMMAND_2D (0x00100000 + 0x70)
+#define LAUNCH_2D (0x00100000 + 0x80)
+
+#define COMMAND_3D (0x00200000 + 0x120)
/* register bitfields (not all, only as needed) */
-#define BIT(x) (1UL << (x))
-
/* COMMAND_2D reg. values */
-#define TDFX_ROP_COPY 0xcc // src
-#define TDFX_ROP_INVERT 0x55 // NOT dst
-#define TDFX_ROP_XOR 0x66 // src XOR dst
-
-#define AUTOINC_DSTX BIT(10)
-#define AUTOINC_DSTY BIT(11)
-#define COMMAND_2D_FILLRECT 0x05
-#define COMMAND_2D_S2S_BITBLT 0x01 // screen to screen
-#define COMMAND_2D_H2S_BITBLT 0x03 // host to screen
-
-#define COMMAND_3D_NOP 0x00
-#define STATUS_RETRACE BIT(6)
-#define STATUS_BUSY BIT(9)
-#define MISCINIT1_CLUT_INV BIT(0)
-#define MISCINIT1_2DBLOCK_DIS BIT(15)
-#define DRAMINIT0_SGRAM_NUM BIT(26)
-#define DRAMINIT0_SGRAM_TYPE BIT(27)
-#define DRAMINIT0_SGRAM_TYPE_MASK (BIT(27)|BIT(28)|BIT(29))
+#define TDFX_ROP_COPY 0xcc /* src */
+#define TDFX_ROP_INVERT 0x55 /* NOT dst */
+#define TDFX_ROP_XOR 0x66 /* src XOR dst */
+
+#define AUTOINC_DSTX BIT(10)
+#define AUTOINC_DSTY BIT(11)
+#define COMMAND_2D_FILLRECT 0x05
+#define COMMAND_2D_S2S_BITBLT 0x01 /* screen to screen */
+#define COMMAND_2D_H2S_BITBLT 0x03 /* host to screen */
+
+#define COMMAND_3D_NOP 0x00
+#define STATUS_RETRACE BIT(6)
+#define STATUS_BUSY BIT(9)
+#define MISCINIT1_CLUT_INV BIT(0)
+#define MISCINIT1_2DBLOCK_DIS BIT(15)
+#define DRAMINIT0_SGRAM_NUM BIT(26)
+#define DRAMINIT0_SGRAM_TYPE BIT(27)
+#define DRAMINIT0_SGRAM_TYPE_MASK (BIT(27) | BIT(28) | BIT(29))
#define DRAMINIT0_SGRAM_TYPE_SHIFT 27
-#define DRAMINIT1_MEM_SDRAM BIT(30)
-#define VGAINIT0_VGA_DISABLE BIT(0)
-#define VGAINIT0_EXT_TIMING BIT(1)
-#define VGAINIT0_8BIT_DAC BIT(2)
-#define VGAINIT0_EXT_ENABLE BIT(6)
-#define VGAINIT0_WAKEUP_3C3 BIT(8)
-#define VGAINIT0_LEGACY_DISABLE BIT(9)
-#define VGAINIT0_ALT_READBACK BIT(10)
-#define VGAINIT0_FAST_BLINK BIT(11)
-#define VGAINIT0_EXTSHIFTOUT BIT(12)
-#define VGAINIT0_DECODE_3C6 BIT(13)
-#define VGAINIT0_SGRAM_HBLANK_DISABLE BIT(22)
-#define VGAINIT1_MASK 0x1fffff
-#define VIDCFG_VIDPROC_ENABLE BIT(0)
-#define VIDCFG_CURS_X11 BIT(1)
-#define VIDCFG_INTERLACE BIT(3)
-#define VIDCFG_HALF_MODE BIT(4)
-#define VIDCFG_DESK_ENABLE BIT(7)
-#define VIDCFG_CLUT_BYPASS BIT(10)
-#define VIDCFG_2X BIT(26)
-#define VIDCFG_HWCURSOR_ENABLE BIT(27)
+#define DRAMINIT1_MEM_SDRAM BIT(30)
+#define VGAINIT0_VGA_DISABLE BIT(0)
+#define VGAINIT0_EXT_TIMING BIT(1)
+#define VGAINIT0_8BIT_DAC BIT(2)
+#define VGAINIT0_EXT_ENABLE BIT(6)
+#define VGAINIT0_WAKEUP_3C3 BIT(8)
+#define VGAINIT0_LEGACY_DISABLE BIT(9)
+#define VGAINIT0_ALT_READBACK BIT(10)
+#define VGAINIT0_FAST_BLINK BIT(11)
+#define VGAINIT0_EXTSHIFTOUT BIT(12)
+#define VGAINIT0_DECODE_3C6 BIT(13)
+#define VGAINIT0_SGRAM_HBLANK_DISABLE BIT(22)
+#define VGAINIT1_MASK 0x1fffff
+#define VIDCFG_VIDPROC_ENABLE BIT(0)
+#define VIDCFG_CURS_X11 BIT(1)
+#define VIDCFG_INTERLACE BIT(3)
+#define VIDCFG_HALF_MODE BIT(4)
+#define VIDCFG_DESK_ENABLE BIT(7)
+#define VIDCFG_CLUT_BYPASS BIT(10)
+#define VIDCFG_2X BIT(26)
+#define VIDCFG_HWCURSOR_ENABLE BIT(27)
#define VIDCFG_PIXFMT_SHIFT 18
-#define DACMODE_2X BIT(0)
+#define DACMODE_2X BIT(0)
/* VGA rubbish, need to change this for multihead support */
-#define MISC_W 0x3c2
-#define MISC_R 0x3cc
-#define SEQ_I 0x3c4
-#define SEQ_D 0x3c5
-#define CRT_I 0x3d4
-#define CRT_D 0x3d5
-#define ATT_IW 0x3c0
-#define IS1_R 0x3da
-#define GRA_I 0x3ce
-#define GRA_D 0x3cf
+#define MISC_W 0x3c2
+#define MISC_R 0x3cc
+#define SEQ_I 0x3c4
+#define SEQ_D 0x3c5
+#define CRT_I 0x3d4
+#define CRT_D 0x3d5
+#define ATT_IW 0x3c0
+#define IS1_R 0x3da
+#define GRA_I 0x3ce
+#define GRA_D 0x3cf
#ifdef __KERNEL__
@@ -143,9 +141,9 @@ struct banshee_reg {
/* VGA rubbish */
unsigned char att[21];
unsigned char crt[25];
- unsigned char gra[ 9];
+ unsigned char gra[9];
unsigned char misc[1];
- unsigned char seq[ 5];
+ unsigned char seq[5];
/* Banshee extensions */
unsigned char ext[2];
@@ -167,8 +165,6 @@ struct banshee_reg {
unsigned long clip0max;
unsigned long clip1min;
unsigned long clip1max;
- unsigned long srcbase;
- unsigned long dstbase;
unsigned long miscinit0;
};
@@ -177,18 +173,10 @@ struct tdfx_par {
u32 palette[16];
void __iomem *regbase_virt;
unsigned long iobase;
- u32 baseline;
-
- struct {
- int w,u,d;
- unsigned long enable,disable;
- struct timer_list timer;
- } hwcursor;
-
- spinlock_t DAClock;
+ int mtrr_handle;
};
-#endif /* __KERNEL__ */
+#endif /* __KERNEL__ */
-#endif /* _TDFX_H */
+#endif /* _TDFX_H */
diff --git a/include/video/uvesafb.h b/include/video/uvesafb.h
new file mode 100644
index 000000000000..95bcef193954
--- /dev/null
+++ b/include/video/uvesafb.h
@@ -0,0 +1,193 @@
+#ifndef _UVESAFB_H
+#define _UVESAFB_H
+
+struct v86_regs {
+ __u32 ebx;
+ __u32 ecx;
+ __u32 edx;
+ __u32 esi;
+ __u32 edi;
+ __u32 ebp;
+ __u32 eax;
+ __u32 eip;
+ __u32 eflags;
+ __u32 esp;
+ __u16 cs;
+ __u16 ss;
+ __u16 es;
+ __u16 ds;
+ __u16 fs;
+ __u16 gs;
+};
+
+/* Task flags */
+#define TF_VBEIB 0x01
+#define TF_BUF_ESDI 0x02
+#define TF_BUF_ESBX 0x04
+#define TF_BUF_RET 0x08
+#define TF_EXIT 0x10
+
+struct uvesafb_task {
+ __u8 flags;
+ int buf_len;
+ struct v86_regs regs;
+};
+
+/* Constants for the capabilities field
+ * in vbe_ib */
+#define VBE_CAP_CAN_SWITCH_DAC 0x01
+#define VBE_CAP_VGACOMPAT 0x02
+
+/* The VBE Info Block */
+struct vbe_ib {
+ char vbe_signature[4];
+ __u16 vbe_version;
+ __u32 oem_string_ptr;
+ __u32 capabilities;
+ __u32 mode_list_ptr;
+ __u16 total_memory;
+ __u16 oem_software_rev;
+ __u32 oem_vendor_name_ptr;
+ __u32 oem_product_name_ptr;
+ __u32 oem_product_rev_ptr;
+ __u8 reserved[222];
+ char oem_data[256];
+ char misc_data[512];
+} __attribute__ ((packed));
+
+#ifdef __KERNEL__
+
+/* VBE CRTC Info Block */
+struct vbe_crtc_ib {
+ u16 horiz_total;
+ u16 horiz_start;
+ u16 horiz_end;
+ u16 vert_total;
+ u16 vert_start;
+ u16 vert_end;
+ u8 flags;
+ u32 pixel_clock;
+ u16 refresh_rate;
+ u8 reserved[40];
+} __attribute__ ((packed));
+
+#define VBE_MODE_VGACOMPAT 0x20
+#define VBE_MODE_COLOR 0x08
+#define VBE_MODE_SUPPORTEDHW 0x01
+#define VBE_MODE_GRAPHICS 0x10
+#define VBE_MODE_LFB 0x80
+
+#define VBE_MODE_MASK (VBE_MODE_COLOR | VBE_MODE_SUPPORTEDHW | \
+ VBE_MODE_GRAPHICS | VBE_MODE_LFB)
+
+/* VBE Mode Info Block */
+struct vbe_mode_ib {
+ /* for all VBE revisions */
+ u16 mode_attr;
+ u8 winA_attr;
+ u8 winB_attr;
+ u16 win_granularity;
+ u16 win_size;
+ u16 winA_seg;
+ u16 winB_seg;
+ u32 win_func_ptr;
+ u16 bytes_per_scan_line;
+
+ /* for VBE 1.2+ */
+ u16 x_res;
+ u16 y_res;
+ u8 x_char_size;
+ u8 y_char_size;
+ u8 planes;
+ u8 bits_per_pixel;
+ u8 banks;
+ u8 memory_model;
+ u8 bank_size;
+ u8 image_pages;
+ u8 reserved1;
+
+ /* Direct color fields for direct/6 and YUV/7 memory models. */
+ /* Offsets are bit positions of lsb in the mask. */
+ u8 red_len;
+ u8 red_off;
+ u8 green_len;
+ u8 green_off;
+ u8 blue_len;
+ u8 blue_off;
+ u8 rsvd_len;
+ u8 rsvd_off;
+ u8 direct_color_info; /* direct color mode attributes */
+
+ /* for VBE 2.0+ */
+ u32 phys_base_ptr;
+ u8 reserved2[6];
+
+ /* for VBE 3.0+ */
+ u16 lin_bytes_per_scan_line;
+ u8 bnk_image_pages;
+ u8 lin_image_pages;
+ u8 lin_red_len;
+ u8 lin_red_off;
+ u8 lin_green_len;
+ u8 lin_green_off;
+ u8 lin_blue_len;
+ u8 lin_blue_off;
+ u8 lin_rsvd_len;
+ u8 lin_rsvd_off;
+ u32 max_pixel_clock;
+ u16 mode_id;
+ u8 depth;
+} __attribute__ ((packed));
+
+#define UVESAFB_DEFAULT_MODE "640x480-16"
+
+/* How long to wait for a reply from userspace [ms] */
+#define UVESAFB_TIMEOUT 5000
+
+/* Max number of concurrent tasks */
+#define UVESAFB_TASKS_MAX 16
+
+#define dac_reg (0x3c8)
+#define dac_val (0x3c9)
+
+struct uvesafb_pal_entry {
+ u_char blue, green, red, pad;
+} __attribute__ ((packed));
+
+struct uvesafb_ktask {
+ struct uvesafb_task t;
+ void *buf;
+ struct completion *done;
+ u32 ack;
+};
+
+static int uvesafb_exec(struct uvesafb_ktask *tsk);
+
+#define UVESAFB_EXACT_RES 1
+#define UVESAFB_EXACT_DEPTH 2
+
+struct uvesafb_par {
+ struct vbe_ib vbe_ib; /* VBE Info Block */
+ struct vbe_mode_ib *vbe_modes; /* list of supported VBE modes */
+ int vbe_modes_cnt;
+
+ u8 nocrtc;
+ u8 ypan; /* 0 - nothing, 1 - ypan, 2 - ywrap */
+ u8 pmi_setpal; /* PMI for palette changes */
+ u16 *pmi_base; /* protected mode interface location */
+ void *pmi_start;
+ void *pmi_pal;
+ u8 *vbe_state_orig; /*
+ * original hardware state, before the
+ * driver was loaded
+ */
+ u8 *vbe_state_saved; /* state saved by fb_save_state */
+ int vbe_state_size;
+ atomic_t ref_count;
+
+ int mode_idx;
+ struct vbe_crtc_ib crtc;
+};
+
+#endif /* __KERNEL__ */
+#endif /* _UVESAFB_H */
diff --git a/include/xen/interface/vcpu.h b/include/xen/interface/vcpu.h
index ff61ea365997..b05d8a6d9143 100644
--- a/include/xen/interface/vcpu.h
+++ b/include/xen/interface/vcpu.h
@@ -160,8 +160,9 @@ struct vcpu_set_singleshot_timer {
*/
#define VCPUOP_register_vcpu_info 10 /* arg == struct vcpu_info */
struct vcpu_register_vcpu_info {
- uint32_t mfn; /* mfn of page to place vcpu_info */
- uint32_t offset; /* offset within page */
+ uint64_t mfn; /* mfn of page to place vcpu_info */
+ uint32_t offset; /* offset within page */
+ uint32_t rsvd; /* unused */
};
#endif /* __XEN_PUBLIC_VCPU_H__ */
diff --git a/init/Kconfig b/init/Kconfig
index 54f31a191b88..c5b354b1409e 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -215,6 +215,18 @@ config USER_NS
vservers, to use user namespaces to provide different
user info for different servers. If unsure, say N.
+config PID_NS
+ bool "PID Namespaces (EXPERIMENTAL)"
+ default n
+ depends on EXPERIMENTAL
+ help
+ Suport process id namespaces. This allows having multiple
+ process with the same pid as long as they are in different
+ pid namespaces. This is a building block of containers.
+
+ Unless you want to work with an experimental feature
+ say N here.
+
config AUDIT
bool "Auditing support"
depends on NET
@@ -234,6 +246,10 @@ config AUDITSYSCALL
such as SELinux. To use audit's filesystem watch feature, please
ensure that INOTIFY is configured.
+config AUDIT_TREE
+ def_bool y
+ depends on AUDITSYSCALL && INOTIFY
+
config IKCONFIG
tristate "Kernel .config support"
---help---
@@ -270,9 +286,36 @@ config LOG_BUF_SHIFT
13 => 8 KB
12 => 4 KB
+config CGROUPS
+ bool "Control Group support"
+ help
+ This option will let you use process cgroup subsystems
+ such as Cpusets
+
+ Say N if unsure.
+
+config CGROUP_DEBUG
+ bool "Example debug cgroup subsystem"
+ depends on CGROUPS
+ help
+ This option enables a simple cgroup subsystem that
+ exports useful debugging information about the cgroups
+ framework
+
+ Say N if unsure
+
+config CGROUP_NS
+ bool "Namespace cgroup subsystem"
+ depends on CGROUPS
+ help
+ Provides a simple namespace cgroup subsystem to
+ provide hierarchical naming of sets of namespaces,
+ for instance virtual servers and checkpoint/restart
+ jobs.
+
config CPUSETS
bool "Cpuset support"
- depends on SMP
+ depends on SMP && CGROUPS
help
This option will let you create and manage CPUSETs which
allow dynamically partitioning a system into sets of CPUs and
@@ -284,7 +327,6 @@ config CPUSETS
config FAIR_GROUP_SCHED
bool "Fair group CPU scheduler"
default y
- depends on EXPERIMENTAL
help
This feature lets CPU scheduler recognize task groups and control CPU
bandwidth allocation to such task groups.
@@ -300,6 +342,16 @@ config FAIR_USER_SCHED
This option will choose userid as the basis for grouping
tasks, thus providing equal CPU bandwidth to each user.
+config FAIR_CGROUP_SCHED
+ bool "Control groups"
+ depends on CGROUPS
+ help
+ This option allows you to create arbitrary task groups
+ using the "cgroup" pseudo filesystem and control
+ the cpu bandwidth allocated to each such task group.
+ Refer to Documentation/cgroups.txt for more information
+ on "cgroup" pseudo filesystem.
+
endchoice
config SYSFS_DEPRECATED
@@ -322,6 +374,11 @@ config SYSFS_DEPRECATED
If you are using a distro that was released in 2006 or later,
it should be safe to say N here.
+config PROC_PID_CPUSET
+ bool "Include legacy /proc/<pid>/cpuset file"
+ depends on CPUSETS
+ default y
+
config RELAY
bool "Kernel->user space relay support (formerly relayfs)"
help
@@ -689,3 +746,6 @@ config STOP_MACHINE
Need stop_machine() primitive.
source "block/Kconfig"
+
+config PREEMPT_NOTIFIERS
+ bool
diff --git a/init/Makefile b/init/Makefile
index 0154aea1e52d..633392f5cdee 100644
--- a/init/Makefile
+++ b/init/Makefile
@@ -30,4 +30,4 @@ $(obj)/version.o: include/linux/compile.h
include/linux/compile.h: FORCE
@echo ' CHK $@'
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkcompile_h $@ \
- "$(UTS_MACHINE)" "$(CONFIG_SMP)" "$(CONFIG_PREEMPT)" "$(CC) $(CFLAGS)"
+ "$(UTS_MACHINE)" "$(CONFIG_SMP)" "$(CONFIG_PREEMPT)" "$(CC) $(KBUILD_CFLAGS)"
diff --git a/init/calibrate.c b/init/calibrate.c
index 40ff3b404895..2d3d73bd4ce1 100644
--- a/init/calibrate.c
+++ b/init/calibrate.c
@@ -10,7 +10,7 @@
#include <asm/timex.h>
-static unsigned long preset_lpj;
+unsigned long preset_lpj;
static int __init lpj_setup(char *str)
{
preset_lpj = simple_strtoul(str,NULL,0);
diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c
index ed652f40f075..3ac5904d1b12 100644
--- a/init/do_mounts_rd.c
+++ b/init/do_mounts_rd.c
@@ -57,7 +57,7 @@ identify_ramdisk_image(int fd, int start_block)
unsigned char *buf;
buf = kmalloc(size, GFP_KERNEL);
- if (buf == 0)
+ if (!buf)
return -1;
minixsb = (struct minix_super_block *) buf;
@@ -407,12 +407,12 @@ static int __init crd_load(int in_fd, int out_fd)
crd_infd = in_fd;
crd_outfd = out_fd;
inbuf = kmalloc(INBUFSIZ, GFP_KERNEL);
- if (inbuf == 0) {
+ if (!inbuf) {
printk(KERN_ERR "RAMDISK: Couldn't allocate gzip buffer\n");
return -1;
}
window = kmalloc(WSIZE, GFP_KERNEL);
- if (window == 0) {
+ if (!window) {
printk(KERN_ERR "RAMDISK: Couldn't allocate gzip window\n");
kfree(inbuf);
return -1;
diff --git a/init/main.c b/init/main.c
index 9def935ab13a..80b04b6c5157 100644
--- a/init/main.c
+++ b/init/main.c
@@ -39,6 +39,7 @@
#include <linux/writeback.h>
#include <linux/cpu.h>
#include <linux/cpuset.h>
+#include <linux/cgroup.h>
#include <linux/efi.h>
#include <linux/tick.h>
#include <linux/interrupt.h>
@@ -55,6 +56,7 @@
#include <linux/pid_namespace.h>
#include <linux/device.h>
#include <linux/kthread.h>
+#include <linux/sched.h>
#include <asm/io.h>
#include <asm/bugs.h>
@@ -69,15 +71,7 @@
/*
* This is one of the first .c files built. Error out early if we have compiler
* trouble.
- *
- * Versions of gcc older than that listed below may actually compile and link
- * okay, but the end product can have subtle run time bugs. To avoid associated
- * bogus bug reports, we flatly refuse to compile with a gcc that is known to be
- * too old from the very beginning.
*/
-#if (__GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 2)
-#error Sorry, your GCC is too old. It builds incorrect kernels.
-#endif
#if __GNUC__ == 4 && __GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ == 0
#warning gcc-4.1.0 is known to miscompile the kernel. A different compiler version is recommended.
@@ -287,7 +281,7 @@ static int __init unknown_bootoption(char *param, char *val)
return 0;
/*
- * Preemptive maintenance for "why didn't my mispelled command
+ * Preemptive maintenance for "why didn't my misspelled command
* line work?"
*/
if (strchr(param, '.') && (!val || strchr(param, '.') < val)) {
@@ -523,6 +517,7 @@ asmlinkage void __init start_kernel(void)
*/
unwind_init();
lockdep_init();
+ cgroup_init_early();
local_irq_disable();
early_boot_irqs_off();
@@ -640,6 +635,7 @@ asmlinkage void __init start_kernel(void)
#ifdef CONFIG_PROC_FS
proc_root_init();
#endif
+ cgroup_init();
cpuset_init();
taskstats_init_early();
delayacct_init();
@@ -752,11 +748,8 @@ __setup("nosoftlockup", nosoftlockup_setup);
static void __init do_pre_smp_initcalls(void)
{
extern int spawn_ksoftirqd(void);
-#ifdef CONFIG_SMP
- extern int migration_init(void);
migration_init();
-#endif
spawn_ksoftirqd();
if (!nosoftlockup)
spawn_softlockup_task();
diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c
index a88934a1b769..79e24e878c1e 100644
--- a/ipc/ipc_sysctl.c
+++ b/ipc/ipc_sysctl.c
@@ -15,7 +15,6 @@
#include <linux/sysctl.h>
#include <linux/uaccess.h>
-#ifdef CONFIG_IPC_NS
static void *get_ipc(ctl_table *table)
{
char *which = table->data;
@@ -23,9 +22,6 @@ static void *get_ipc(ctl_table *table)
which = (which - (char *)&init_ipc_ns) + (char *)ipc_ns;
return which;
}
-#else
-#define get_ipc(T) ((T)->data)
-#endif
#ifdef CONFIG_PROC_FS
static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp,
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 24df3347ad4b..1e04cd464af9 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -29,6 +29,8 @@
#include <linux/audit.h>
#include <linux/signal.h>
#include <linux/mutex.h>
+#include <linux/nsproxy.h>
+#include <linux/pid.h>
#include <net/sock.h>
#include "util.h"
@@ -44,12 +46,6 @@
#define STATE_PENDING 1
#define STATE_READY 2
-/* used by sysctl */
-#define FS_MQUEUE 1
-#define CTL_QUEUESMAX 2
-#define CTL_MSGMAX 3
-#define CTL_MSGSIZEMAX 4
-
/* default values */
#define DFLT_QUEUESMAX 256 /* max number of message queues */
#define DFLT_MSGMAX 10 /* max number of messages in each queue */
@@ -211,7 +207,7 @@ static int mqueue_get_sb(struct file_system_type *fs_type,
return get_sb_single(fs_type, flags, data, mqueue_fill_super, mnt);
}
-static void init_once(void *foo, struct kmem_cache * cachep, unsigned long flags)
+static void init_once(struct kmem_cache *cachep, void *foo)
{
struct mqueue_inode_info *p = (struct mqueue_inode_info *) foo;
@@ -336,7 +332,8 @@ static ssize_t mqueue_read_file(struct file *filp, char __user *u_data,
(info->notify_owner &&
info->notify.sigev_notify == SIGEV_SIGNAL) ?
info->notify.sigev_signo : 0,
- pid_nr(info->notify_owner));
+ pid_nr_ns(info->notify_owner,
+ current->nsproxy->pid_ns));
spin_unlock(&info->lock);
buffer[sizeof(buffer)-1] = '\0';
slen = strlen(buffer)+1;
@@ -513,7 +510,7 @@ static void __do_notify(struct mqueue_inode_info *info)
sig_i.si_errno = 0;
sig_i.si_code = SI_MESGQ;
sig_i.si_value = info->notify.sigev_value;
- sig_i.si_pid = current->tgid;
+ sig_i.si_pid = task_pid_vnr(current);
sig_i.si_uid = current->uid;
kill_pid_info(info->notify.sigev_signo,
@@ -679,7 +676,7 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
if (oflag & O_CREAT) {
if (dentry->d_inode) { /* entry already exists */
- audit_inode(name, dentry->d_inode);
+ audit_inode(name, dentry);
error = -EEXIST;
if (oflag & O_EXCL)
goto out;
@@ -692,7 +689,7 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
error = -ENOENT;
if (!dentry->d_inode)
goto out;
- audit_inode(name, dentry->d_inode);
+ audit_inode(name, dentry);
filp = do_open(dentry, oflag);
}
@@ -840,7 +837,7 @@ asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr,
if (unlikely(filp->f_op != &mqueue_file_operations))
goto out_fput;
info = MQUEUE_I(inode);
- audit_inode(NULL, inode);
+ audit_inode(NULL, filp->f_path.dentry);
if (unlikely(!(filp->f_mode & FMODE_WRITE)))
goto out_fput;
@@ -924,7 +921,7 @@ asmlinkage ssize_t sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr,
if (unlikely(filp->f_op != &mqueue_file_operations))
goto out_fput;
info = MQUEUE_I(inode);
- audit_inode(NULL, inode);
+ audit_inode(NULL, filp->f_path.dentry);
if (unlikely(!(filp->f_mode & FMODE_READ)))
goto out_fput;
@@ -1013,6 +1010,8 @@ asmlinkage long sys_mq_notify(mqd_t mqdes,
return -EINVAL;
}
if (notification.sigev_notify == SIGEV_THREAD) {
+ long timeo;
+
/* create the notify skb */
nc = alloc_skb(NOTIFY_COOKIE_LEN, GFP_KERNEL);
ret = -ENOMEM;
@@ -1041,8 +1040,8 @@ retry:
goto out;
}
- ret = netlink_attachskb(sock, nc, 0,
- MAX_SCHEDULE_TIMEOUT, NULL);
+ timeo = MAX_SCHEDULE_TIMEOUT;
+ ret = netlink_attachskb(sock, nc, 0, &timeo, NULL);
if (ret == 1)
goto retry;
if (ret) {
@@ -1196,7 +1195,6 @@ static int msg_maxsize_limit_max = INT_MAX;
static ctl_table mq_sysctls[] = {
{
- .ctl_name = CTL_QUEUESMAX,
.procname = "queues_max",
.data = &queues_max,
.maxlen = sizeof(int),
@@ -1204,7 +1202,6 @@ static ctl_table mq_sysctls[] = {
.proc_handler = &proc_dointvec,
},
{
- .ctl_name = CTL_MSGMAX,
.procname = "msg_max",
.data = &msg_max,
.maxlen = sizeof(int),
@@ -1214,7 +1211,6 @@ static ctl_table mq_sysctls[] = {
.extra2 = &msg_max_limit_max,
},
{
- .ctl_name = CTL_MSGSIZEMAX,
.procname = "msgsize_max",
.data = &msgsize_max,
.maxlen = sizeof(int),
@@ -1228,7 +1224,6 @@ static ctl_table mq_sysctls[] = {
static ctl_table mq_sysctl_dir[] = {
{
- .ctl_name = FS_MQUEUE,
.procname = "mqueue",
.mode = 0555,
.child = mq_sysctls,
diff --git a/ipc/msg.c b/ipc/msg.c
index a03fcb522fff..fdf3db5731ce 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -34,7 +34,7 @@
#include <linux/syscalls.h>
#include <linux/audit.h>
#include <linux/seq_file.h>
-#include <linux/mutex.h>
+#include <linux/rwsem.h>
#include <linux/nsproxy.h>
#include <asm/current.h>
@@ -66,23 +66,15 @@ struct msg_sender {
#define SEARCH_NOTEQUAL 3
#define SEARCH_LESSEQUAL 4
-static atomic_t msg_bytes = ATOMIC_INIT(0);
-static atomic_t msg_hdrs = ATOMIC_INIT(0);
-
static struct ipc_ids init_msg_ids;
#define msg_ids(ns) (*((ns)->ids[IPC_MSG_IDS]))
-#define msg_lock(ns, id) ((struct msg_queue*)ipc_lock(&msg_ids(ns), id))
#define msg_unlock(msq) ipc_unlock(&(msq)->q_perm)
-#define msg_rmid(ns, id) ((struct msg_queue*)ipc_rmid(&msg_ids(ns), id))
-#define msg_checkid(ns, msq, msgid) \
- ipc_checkid(&msg_ids(ns), &msq->q_perm, msgid)
-#define msg_buildid(ns, id, seq) \
- ipc_buildid(&msg_ids(ns), id, seq)
-
-static void freeque (struct ipc_namespace *ns, struct msg_queue *msq, int id);
-static int newque (struct ipc_namespace *ns, key_t key, int msgflg);
+#define msg_buildid(id, seq) ipc_buildid(id, seq)
+
+static void freeque(struct ipc_namespace *, struct msg_queue *);
+static int newque(struct ipc_namespace *, struct ipc_params *);
#ifdef CONFIG_PROC_FS
static int sysvipc_msg_proc_show(struct seq_file *s, void *it);
#endif
@@ -93,7 +85,9 @@ static void __msg_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
ns->msg_ctlmax = MSGMAX;
ns->msg_ctlmnb = MSGMNB;
ns->msg_ctlmni = MSGMNI;
- ipc_init_ids(ids, ns->msg_ctlmni);
+ atomic_set(&ns->msg_bytes, 0);
+ atomic_set(&ns->msg_hdrs, 0);
+ ipc_init_ids(ids);
}
int msg_init_ns(struct ipc_namespace *ns)
@@ -110,20 +104,25 @@ int msg_init_ns(struct ipc_namespace *ns)
void msg_exit_ns(struct ipc_namespace *ns)
{
- int i;
struct msg_queue *msq;
+ int next_id;
+ int total, in_use;
+
+ down_write(&msg_ids(ns).rw_mutex);
+
+ in_use = msg_ids(ns).in_use;
- mutex_lock(&msg_ids(ns).mutex);
- for (i = 0; i <= msg_ids(ns).max_id; i++) {
- msq = msg_lock(ns, i);
+ for (total = 0, next_id = 0; total < in_use; next_id++) {
+ msq = idr_find(&msg_ids(ns).ipcs_idr, next_id);
if (msq == NULL)
continue;
-
- freeque(ns, msq, i);
+ ipc_lock_by_ptr(&msq->q_perm);
+ freeque(ns, msq);
+ total++;
}
- mutex_unlock(&msg_ids(ns).mutex);
- ipc_fini_ids(ns->ids[IPC_MSG_IDS]);
+ up_write(&msg_ids(ns).rw_mutex);
+
kfree(ns->ids[IPC_MSG_IDS]);
ns->ids[IPC_MSG_IDS] = NULL;
}
@@ -136,10 +135,55 @@ void __init msg_init(void)
IPC_MSG_IDS, sysvipc_msg_proc_show);
}
-static int newque (struct ipc_namespace *ns, key_t key, int msgflg)
+/*
+ * This routine is called in the paths where the rw_mutex is held to protect
+ * access to the idr tree.
+ */
+static inline struct msg_queue *msg_lock_check_down(struct ipc_namespace *ns,
+ int id)
+{
+ struct kern_ipc_perm *ipcp = ipc_lock_check_down(&msg_ids(ns), id);
+
+ return container_of(ipcp, struct msg_queue, q_perm);
+}
+
+/*
+ * msg_lock_(check_) routines are called in the paths where the rw_mutex
+ * is not held.
+ */
+static inline struct msg_queue *msg_lock(struct ipc_namespace *ns, int id)
+{
+ struct kern_ipc_perm *ipcp = ipc_lock(&msg_ids(ns), id);
+
+ return container_of(ipcp, struct msg_queue, q_perm);
+}
+
+static inline struct msg_queue *msg_lock_check(struct ipc_namespace *ns,
+ int id)
+{
+ struct kern_ipc_perm *ipcp = ipc_lock_check(&msg_ids(ns), id);
+
+ return container_of(ipcp, struct msg_queue, q_perm);
+}
+
+static inline void msg_rmid(struct ipc_namespace *ns, struct msg_queue *s)
+{
+ ipc_rmid(&msg_ids(ns), &s->q_perm);
+}
+
+/**
+ * newque - Create a new msg queue
+ * @ns: namespace
+ * @params: ptr to the structure that contains the key and msgflg
+ *
+ * Called with msg_ids.rw_mutex held (writer)
+ */
+static int newque(struct ipc_namespace *ns, struct ipc_params *params)
{
struct msg_queue *msq;
int id, retval;
+ key_t key = params->key;
+ int msgflg = params->flg;
msq = ipc_rcu_alloc(sizeof(*msq));
if (!msq)
@@ -155,14 +199,17 @@ static int newque (struct ipc_namespace *ns, key_t key, int msgflg)
return retval;
}
+ /*
+ * ipc_addid() locks msq
+ */
id = ipc_addid(&msg_ids(ns), &msq->q_perm, ns->msg_ctlmni);
- if (id == -1) {
+ if (id < 0) {
security_msg_queue_free(msq);
ipc_rcu_putref(msq);
- return -ENOSPC;
+ return id;
}
- msq->q_id = msg_buildid(ns, id, msq->q_perm.seq);
+ msq->q_perm.id = msg_buildid(id, msq->q_perm.seq);
msq->q_stime = msq->q_rtime = 0;
msq->q_ctime = get_seconds();
msq->q_cbytes = msq->q_qnum = 0;
@@ -171,9 +218,10 @@ static int newque (struct ipc_namespace *ns, key_t key, int msgflg)
INIT_LIST_HEAD(&msq->q_messages);
INIT_LIST_HEAD(&msq->q_receivers);
INIT_LIST_HEAD(&msq->q_senders);
+
msg_unlock(msq);
- return msq->q_id;
+ return msq->q_perm.id;
}
static inline void ss_add(struct msg_queue *msq, struct msg_sender *mss)
@@ -224,19 +272,19 @@ static void expunge_all(struct msg_queue *msq, int res)
/*
* freeque() wakes up waiters on the sender and receiver waiting queue,
- * removes the message queue from message queue ID
- * array, and cleans up all the messages associated with this queue.
+ * removes the message queue from message queue ID IDR, and cleans up all the
+ * messages associated with this queue.
*
- * msg_ids.mutex and the spinlock for this message queue is hold
- * before freeque() is called. msg_ids.mutex remains locked on exit.
+ * msg_ids.rw_mutex (writer) and the spinlock for this message queue are held
+ * before freeque() is called. msg_ids.rw_mutex remains locked on exit.
*/
-static void freeque(struct ipc_namespace *ns, struct msg_queue *msq, int id)
+static void freeque(struct ipc_namespace *ns, struct msg_queue *msq)
{
struct list_head *tmp;
expunge_all(msq, -EIDRM);
ss_wakeup(&msq->q_senders, 1);
- msq = msg_rmid(ns, id);
+ msg_rmid(ns, msq);
msg_unlock(msq);
tmp = msq->q_messages.next;
@@ -244,49 +292,40 @@ static void freeque(struct ipc_namespace *ns, struct msg_queue *msq, int id)
struct msg_msg *msg = list_entry(tmp, struct msg_msg, m_list);
tmp = tmp->next;
- atomic_dec(&msg_hdrs);
+ atomic_dec(&ns->msg_hdrs);
free_msg(msg);
}
- atomic_sub(msq->q_cbytes, &msg_bytes);
+ atomic_sub(msq->q_cbytes, &ns->msg_bytes);
security_msg_queue_free(msq);
ipc_rcu_putref(msq);
}
+/*
+ * Called with msg_ids.rw_mutex and ipcp locked.
+ */
+static inline int msg_security(struct kern_ipc_perm *ipcp, int msgflg)
+{
+ struct msg_queue *msq = container_of(ipcp, struct msg_queue, q_perm);
+
+ return security_msg_queue_associate(msq, msgflg);
+}
+
asmlinkage long sys_msgget(key_t key, int msgflg)
{
- struct msg_queue *msq;
- int id, ret = -EPERM;
struct ipc_namespace *ns;
+ struct ipc_ops msg_ops;
+ struct ipc_params msg_params;
ns = current->nsproxy->ipc_ns;
-
- mutex_lock(&msg_ids(ns).mutex);
- if (key == IPC_PRIVATE)
- ret = newque(ns, key, msgflg);
- else if ((id = ipc_findkey(&msg_ids(ns), key)) == -1) { /* key not used */
- if (!(msgflg & IPC_CREAT))
- ret = -ENOENT;
- else
- ret = newque(ns, key, msgflg);
- } else if (msgflg & IPC_CREAT && msgflg & IPC_EXCL) {
- ret = -EEXIST;
- } else {
- msq = msg_lock(ns, id);
- BUG_ON(msq == NULL);
- if (ipcperms(&msq->q_perm, msgflg))
- ret = -EACCES;
- else {
- int qid = msg_buildid(ns, id, msq->q_perm.seq);
-
- ret = security_msg_queue_associate(msq, msgflg);
- if (!ret)
- ret = qid;
- }
- msg_unlock(msq);
- }
- mutex_unlock(&msg_ids(ns).mutex);
- return ret;
+ msg_ops.getnew = newque;
+ msg_ops.associate = msg_security;
+ msg_ops.more_checks = NULL;
+
+ msg_params.key = key;
+ msg_params.flg = msgflg;
+
+ return ipcget(ns, &msg_ids(ns), &msg_ops, &msg_params);
}
static inline unsigned long
@@ -420,23 +459,23 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
msginfo.msgmnb = ns->msg_ctlmnb;
msginfo.msgssz = MSGSSZ;
msginfo.msgseg = MSGSEG;
- mutex_lock(&msg_ids(ns).mutex);
+ down_read(&msg_ids(ns).rw_mutex);
if (cmd == MSG_INFO) {
msginfo.msgpool = msg_ids(ns).in_use;
- msginfo.msgmap = atomic_read(&msg_hdrs);
- msginfo.msgtql = atomic_read(&msg_bytes);
+ msginfo.msgmap = atomic_read(&ns->msg_hdrs);
+ msginfo.msgtql = atomic_read(&ns->msg_bytes);
} else {
msginfo.msgmap = MSGMAP;
msginfo.msgpool = MSGPOOL;
msginfo.msgtql = MSGTQL;
}
- max_id = msg_ids(ns).max_id;
- mutex_unlock(&msg_ids(ns).mutex);
+ max_id = ipc_get_maxid(&msg_ids(ns));
+ up_read(&msg_ids(ns).rw_mutex);
if (copy_to_user(buf, &msginfo, sizeof(struct msginfo)))
return -EFAULT;
return (max_id < 0) ? 0 : max_id;
}
- case MSG_STAT:
+ case MSG_STAT: /* msqid is an index rather than a msg queue id */
case IPC_STAT:
{
struct msqid64_ds tbuf;
@@ -444,21 +483,16 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
if (!buf)
return -EFAULT;
- if (cmd == MSG_STAT && msqid >= msg_ids(ns).entries->size)
- return -EINVAL;
-
- memset(&tbuf, 0, sizeof(tbuf));
-
- msq = msg_lock(ns, msqid);
- if (msq == NULL)
- return -EINVAL;
if (cmd == MSG_STAT) {
- success_return = msg_buildid(ns, msqid, msq->q_perm.seq);
+ msq = msg_lock(ns, msqid);
+ if (IS_ERR(msq))
+ return PTR_ERR(msq);
+ success_return = msq->q_perm.id;
} else {
- err = -EIDRM;
- if (msg_checkid(ns, msq, msqid))
- goto out_unlock;
+ msq = msg_lock_check(ns, msqid);
+ if (IS_ERR(msq))
+ return PTR_ERR(msq);
success_return = 0;
}
err = -EACCES;
@@ -469,6 +503,8 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
if (err)
goto out_unlock;
+ memset(&tbuf, 0, sizeof(tbuf));
+
kernel_to_ipc64_perm(&msq->q_perm, &tbuf.msg_perm);
tbuf.msg_stime = msq->q_stime;
tbuf.msg_rtime = msq->q_rtime;
@@ -495,15 +531,13 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
return -EINVAL;
}
- mutex_lock(&msg_ids(ns).mutex);
- msq = msg_lock(ns, msqid);
- err = -EINVAL;
- if (msq == NULL)
+ down_write(&msg_ids(ns).rw_mutex);
+ msq = msg_lock_check_down(ns, msqid);
+ if (IS_ERR(msq)) {
+ err = PTR_ERR(msq);
goto out_up;
+ }
- err = -EIDRM;
- if (msg_checkid(ns, msq, msqid))
- goto out_unlock_up;
ipcp = &msq->q_perm;
err = audit_ipc_obj(ipcp);
@@ -552,12 +586,12 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
break;
}
case IPC_RMID:
- freeque(ns, msq, msqid);
+ freeque(ns, msq);
break;
}
err = 0;
out_up:
- mutex_unlock(&msg_ids(ns).mutex);
+ up_write(&msg_ids(ns).rw_mutex);
return err;
out_unlock_up:
msg_unlock(msq);
@@ -611,7 +645,7 @@ static inline int pipelined_send(struct msg_queue *msq, struct msg_msg *msg)
msr->r_msg = ERR_PTR(-E2BIG);
} else {
msr->r_msg = NULL;
- msq->q_lrpid = msr->r_tsk->pid;
+ msq->q_lrpid = task_pid_vnr(msr->r_tsk);
msq->q_rtime = get_seconds();
wake_up_process(msr->r_tsk);
smp_mb();
@@ -646,14 +680,11 @@ long do_msgsnd(int msqid, long mtype, void __user *mtext,
msg->m_type = mtype;
msg->m_ts = msgsz;
- msq = msg_lock(ns, msqid);
- err = -EINVAL;
- if (msq == NULL)
+ msq = msg_lock_check(ns, msqid);
+ if (IS_ERR(msq)) {
+ err = PTR_ERR(msq);
goto out_free;
-
- err= -EIDRM;
- if (msg_checkid(ns, msq, msqid))
- goto out_unlock_free;
+ }
for (;;) {
struct msg_sender s;
@@ -695,7 +726,7 @@ long do_msgsnd(int msqid, long mtype, void __user *mtext,
}
}
- msq->q_lspid = current->tgid;
+ msq->q_lspid = task_tgid_vnr(current);
msq->q_stime = get_seconds();
if (!pipelined_send(msq, msg)) {
@@ -703,8 +734,8 @@ long do_msgsnd(int msqid, long mtype, void __user *mtext,
list_add_tail(&msg->m_list, &msq->q_messages);
msq->q_cbytes += msgsz;
msq->q_qnum++;
- atomic_add(msgsz, &msg_bytes);
- atomic_inc(&msg_hdrs);
+ atomic_add(msgsz, &ns->msg_bytes);
+ atomic_inc(&ns->msg_hdrs);
}
err = 0;
@@ -760,13 +791,9 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
mode = convert_mode(&msgtyp, msgflg);
ns = current->nsproxy->ipc_ns;
- msq = msg_lock(ns, msqid);
- if (msq == NULL)
- return -EINVAL;
-
- msg = ERR_PTR(-EIDRM);
- if (msg_checkid(ns, msq, msqid))
- goto out_unlock;
+ msq = msg_lock_check(ns, msqid);
+ if (IS_ERR(msq))
+ return PTR_ERR(msq);
for (;;) {
struct msg_receiver msr_d;
@@ -810,10 +837,10 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
list_del(&msg->m_list);
msq->q_qnum--;
msq->q_rtime = get_seconds();
- msq->q_lrpid = current->tgid;
+ msq->q_lrpid = task_tgid_vnr(current);
msq->q_cbytes -= msg->m_ts;
- atomic_sub(msg->m_ts, &msg_bytes);
- atomic_dec(&msg_hdrs);
+ atomic_sub(msg->m_ts, &ns->msg_bytes);
+ atomic_dec(&ns->msg_hdrs);
ss_wakeup(&msq->q_senders, 0);
msg_unlock(msq);
break;
@@ -926,7 +953,7 @@ static int sysvipc_msg_proc_show(struct seq_file *s, void *it)
return seq_printf(s,
"%10d %10d %4o %10lu %10lu %5u %5u %5u %5u %5u %5u %10lu %10lu %10lu\n",
msq->q_perm.key,
- msq->q_id,
+ msq->q_perm.id,
msq->q_perm.mode,
msq->q_cbytes,
msq->q_qnum,
diff --git a/ipc/sem.c b/ipc/sem.c
index b676fef6d208..35952c0bae46 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -80,7 +80,7 @@
#include <linux/audit.h>
#include <linux/capability.h>
#include <linux/seq_file.h>
-#include <linux/mutex.h>
+#include <linux/rwsem.h>
#include <linux/nsproxy.h>
#include <asm/uaccess.h>
@@ -88,18 +88,14 @@
#define sem_ids(ns) (*((ns)->ids[IPC_SEM_IDS]))
-#define sem_lock(ns, id) ((struct sem_array*)ipc_lock(&sem_ids(ns), id))
#define sem_unlock(sma) ipc_unlock(&(sma)->sem_perm)
-#define sem_rmid(ns, id) ((struct sem_array*)ipc_rmid(&sem_ids(ns), id))
-#define sem_checkid(ns, sma, semid) \
- ipc_checkid(&sem_ids(ns),&sma->sem_perm,semid)
-#define sem_buildid(ns, id, seq) \
- ipc_buildid(&sem_ids(ns), id, seq)
+#define sem_checkid(sma, semid) ipc_checkid(&sma->sem_perm, semid)
+#define sem_buildid(id, seq) ipc_buildid(id, seq)
static struct ipc_ids init_sem_ids;
-static int newary(struct ipc_namespace *, key_t, int, int);
-static void freeary(struct ipc_namespace *ns, struct sem_array *sma, int id);
+static int newary(struct ipc_namespace *, struct ipc_params *);
+static void freeary(struct ipc_namespace *, struct sem_array *);
#ifdef CONFIG_PROC_FS
static int sysvipc_sem_proc_show(struct seq_file *s, void *it);
#endif
@@ -129,7 +125,7 @@ static void __sem_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
ns->sc_semopm = SEMOPM;
ns->sc_semmni = SEMMNI;
ns->used_sems = 0;
- ipc_init_ids(ids, ns->sc_semmni);
+ ipc_init_ids(ids);
}
int sem_init_ns(struct ipc_namespace *ns)
@@ -146,20 +142,24 @@ int sem_init_ns(struct ipc_namespace *ns)
void sem_exit_ns(struct ipc_namespace *ns)
{
- int i;
struct sem_array *sma;
+ int next_id;
+ int total, in_use;
- mutex_lock(&sem_ids(ns).mutex);
- for (i = 0; i <= sem_ids(ns).max_id; i++) {
- sma = sem_lock(ns, i);
+ down_write(&sem_ids(ns).rw_mutex);
+
+ in_use = sem_ids(ns).in_use;
+
+ for (total = 0, next_id = 0; total < in_use; next_id++) {
+ sma = idr_find(&sem_ids(ns).ipcs_idr, next_id);
if (sma == NULL)
continue;
-
- freeary(ns, sma, i);
+ ipc_lock_by_ptr(&sma->sem_perm);
+ freeary(ns, sma);
+ total++;
}
- mutex_unlock(&sem_ids(ns).mutex);
+ up_write(&sem_ids(ns).rw_mutex);
- ipc_fini_ids(ns->ids[IPC_SEM_IDS]);
kfree(ns->ids[IPC_SEM_IDS]);
ns->ids[IPC_SEM_IDS] = NULL;
}
@@ -173,6 +173,42 @@ void __init sem_init (void)
}
/*
+ * This routine is called in the paths where the rw_mutex is held to protect
+ * access to the idr tree.
+ */
+static inline struct sem_array *sem_lock_check_down(struct ipc_namespace *ns,
+ int id)
+{
+ struct kern_ipc_perm *ipcp = ipc_lock_check_down(&sem_ids(ns), id);
+
+ return container_of(ipcp, struct sem_array, sem_perm);
+}
+
+/*
+ * sem_lock_(check_) routines are called in the paths where the rw_mutex
+ * is not held.
+ */
+static inline struct sem_array *sem_lock(struct ipc_namespace *ns, int id)
+{
+ struct kern_ipc_perm *ipcp = ipc_lock(&sem_ids(ns), id);
+
+ return container_of(ipcp, struct sem_array, sem_perm);
+}
+
+static inline struct sem_array *sem_lock_check(struct ipc_namespace *ns,
+ int id)
+{
+ struct kern_ipc_perm *ipcp = ipc_lock_check(&sem_ids(ns), id);
+
+ return container_of(ipcp, struct sem_array, sem_perm);
+}
+
+static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s)
+{
+ ipc_rmid(&sem_ids(ns), &s->sem_perm);
+}
+
+/*
* Lockless wakeup algorithm:
* Without the check/retry algorithm a lockless wakeup is possible:
* - queue.status is initialized to -EINTR before blocking.
@@ -206,12 +242,23 @@ void __init sem_init (void)
*/
#define IN_WAKEUP 1
-static int newary (struct ipc_namespace *ns, key_t key, int nsems, int semflg)
+/**
+ * newary - Create a new semaphore set
+ * @ns: namespace
+ * @params: ptr to the structure that contains key, semflg and nsems
+ *
+ * Called with sem_ids.rw_mutex held (as a writer)
+ */
+
+static int newary(struct ipc_namespace *ns, struct ipc_params *params)
{
int id;
int retval;
struct sem_array *sma;
int size;
+ key_t key = params->key;
+ int nsems = params->u.nsems;
+ int semflg = params->flg;
if (!nsems)
return -EINVAL;
@@ -236,14 +283,14 @@ static int newary (struct ipc_namespace *ns, key_t key, int nsems, int semflg)
}
id = ipc_addid(&sem_ids(ns), &sma->sem_perm, ns->sc_semmni);
- if(id == -1) {
+ if (id < 0) {
security_sem_free(sma);
ipc_rcu_putref(sma);
- return -ENOSPC;
+ return id;
}
ns->used_sems += nsems;
- sma->sem_id = sem_buildid(ns, id, sma->sem_perm.seq);
+ sma->sem_perm.id = sem_buildid(id, sma->sem_perm.seq);
sma->sem_base = (struct sem *) &sma[1];
/* sma->sem_pending = NULL; */
sma->sem_pending_last = &sma->sem_pending;
@@ -252,48 +299,56 @@ static int newary (struct ipc_namespace *ns, key_t key, int nsems, int semflg)
sma->sem_ctime = get_seconds();
sem_unlock(sma);
- return sma->sem_id;
+ return sma->sem_perm.id;
+}
+
+
+/*
+ * Called with sem_ids.rw_mutex and ipcp locked.
+ */
+static inline int sem_security(struct kern_ipc_perm *ipcp, int semflg)
+{
+ struct sem_array *sma;
+
+ sma = container_of(ipcp, struct sem_array, sem_perm);
+ return security_sem_associate(sma, semflg);
}
-asmlinkage long sys_semget (key_t key, int nsems, int semflg)
+/*
+ * Called with sem_ids.rw_mutex and ipcp locked.
+ */
+static inline int sem_more_checks(struct kern_ipc_perm *ipcp,
+ struct ipc_params *params)
{
- int id, err = -EINVAL;
struct sem_array *sma;
+
+ sma = container_of(ipcp, struct sem_array, sem_perm);
+ if (params->u.nsems > sma->sem_nsems)
+ return -EINVAL;
+
+ return 0;
+}
+
+asmlinkage long sys_semget(key_t key, int nsems, int semflg)
+{
struct ipc_namespace *ns;
+ struct ipc_ops sem_ops;
+ struct ipc_params sem_params;
ns = current->nsproxy->ipc_ns;
if (nsems < 0 || nsems > ns->sc_semmsl)
return -EINVAL;
- mutex_lock(&sem_ids(ns).mutex);
-
- if (key == IPC_PRIVATE) {
- err = newary(ns, key, nsems, semflg);
- } else if ((id = ipc_findkey(&sem_ids(ns), key)) == -1) { /* key not used */
- if (!(semflg & IPC_CREAT))
- err = -ENOENT;
- else
- err = newary(ns, key, nsems, semflg);
- } else if (semflg & IPC_CREAT && semflg & IPC_EXCL) {
- err = -EEXIST;
- } else {
- sma = sem_lock(ns, id);
- BUG_ON(sma==NULL);
- if (nsems > sma->sem_nsems)
- err = -EINVAL;
- else if (ipcperms(&sma->sem_perm, semflg))
- err = -EACCES;
- else {
- int semid = sem_buildid(ns, id, sma->sem_perm.seq);
- err = security_sem_associate(sma, semflg);
- if (!err)
- err = semid;
- }
- sem_unlock(sma);
- }
- mutex_unlock(&sem_ids(ns).mutex);
- return err;
+ sem_ops.getnew = newary;
+ sem_ops.associate = sem_security;
+ sem_ops.more_checks = sem_more_checks;
+
+ sem_params.key = key;
+ sem_params.flg = semflg;
+ sem_params.u.nsems = nsems;
+
+ return ipcget(ns, &sem_ids(ns), &sem_ops, &sem_params);
}
/* Manage the doubly linked list sma->sem_pending as a FIFO:
@@ -487,15 +542,14 @@ static int count_semzcnt (struct sem_array * sma, ushort semnum)
return semzcnt;
}
-/* Free a semaphore set. freeary() is called with sem_ids.mutex locked and
- * the spinlock for this semaphore set hold. sem_ids.mutex remains locked
- * on exit.
+/* Free a semaphore set. freeary() is called with sem_ids.rw_mutex locked
+ * as a writer and the spinlock for this semaphore set hold. sem_ids.rw_mutex
+ * remains locked on exit.
*/
-static void freeary (struct ipc_namespace *ns, struct sem_array *sma, int id)
+static void freeary(struct ipc_namespace *ns, struct sem_array *sma)
{
struct sem_undo *un;
struct sem_queue *q;
- int size;
/* Invalidate the existing undo structures for this semaphore set.
* (They will be freed without any further action in exit_sem()
@@ -518,12 +572,11 @@ static void freeary (struct ipc_namespace *ns, struct sem_array *sma, int id)
q = n;
}
- /* Remove the semaphore set from the ID array*/
- sma = sem_rmid(ns, id);
+ /* Remove the semaphore set from the IDR */
+ sem_rmid(ns, sma);
sem_unlock(sma);
ns->used_sems -= sma->sem_nsems;
- size = sizeof (*sma) + sma->sem_nsems * sizeof (struct sem);
security_sem_free(sma);
ipc_rcu_putref(sma);
}
@@ -576,7 +629,7 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid, int semnum,
seminfo.semmnu = SEMMNU;
seminfo.semmap = SEMMAP;
seminfo.semume = SEMUME;
- mutex_lock(&sem_ids(ns).mutex);
+ down_read(&sem_ids(ns).rw_mutex);
if (cmd == SEM_INFO) {
seminfo.semusz = sem_ids(ns).in_use;
seminfo.semaem = ns->used_sems;
@@ -584,8 +637,8 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid, int semnum,
seminfo.semusz = SEMUSZ;
seminfo.semaem = SEMAEM;
}
- max_id = sem_ids(ns).max_id;
- mutex_unlock(&sem_ids(ns).mutex);
+ max_id = ipc_get_maxid(&sem_ids(ns));
+ up_read(&sem_ids(ns).rw_mutex);
if (copy_to_user (arg.__buf, &seminfo, sizeof(struct seminfo)))
return -EFAULT;
return (max_id < 0) ? 0: max_id;
@@ -595,14 +648,9 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid, int semnum,
struct semid64_ds tbuf;
int id;
- if(semid >= sem_ids(ns).entries->size)
- return -EINVAL;
-
- memset(&tbuf,0,sizeof(tbuf));
-
sma = sem_lock(ns, semid);
- if(sma == NULL)
- return -EINVAL;
+ if (IS_ERR(sma))
+ return PTR_ERR(sma);
err = -EACCES;
if (ipcperms (&sma->sem_perm, S_IRUGO))
@@ -612,7 +660,9 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid, int semnum,
if (err)
goto out_unlock;
- id = sem_buildid(ns, semid, sma->sem_perm.seq);
+ id = sma->sem_perm.id;
+
+ memset(&tbuf, 0, sizeof(tbuf));
kernel_to_ipc64_perm(&sma->sem_perm, &tbuf.sem_perm);
tbuf.sem_otime = sma->sem_otime;
@@ -642,16 +692,12 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
ushort* sem_io = fast_sem_io;
int nsems;
- sma = sem_lock(ns, semid);
- if(sma==NULL)
- return -EINVAL;
+ sma = sem_lock_check(ns, semid);
+ if (IS_ERR(sma))
+ return PTR_ERR(sma);
nsems = sma->sem_nsems;
- err=-EIDRM;
- if (sem_checkid(ns,sma,semid))
- goto out_unlock;
-
err = -EACCES;
if (ipcperms (&sma->sem_perm, (cmd==SETVAL||cmd==SETALL)?S_IWUGO:S_IRUGO))
goto out_unlock;
@@ -795,7 +841,7 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
for (un = sma->undo; un; un = un->id_next)
un->semadj[semnum] = 0;
curr->semval = val;
- curr->sempid = current->tgid;
+ curr->sempid = task_tgid_vnr(current);
sma->sem_ctime = get_seconds();
/* maybe some queued-up processes were waiting for this */
update_queue(sma);
@@ -863,14 +909,10 @@ static int semctl_down(struct ipc_namespace *ns, int semid, int semnum,
if(copy_semid_from_user (&setbuf, arg.buf, version))
return -EFAULT;
}
- sma = sem_lock(ns, semid);
- if(sma==NULL)
- return -EINVAL;
+ sma = sem_lock_check_down(ns, semid);
+ if (IS_ERR(sma))
+ return PTR_ERR(sma);
- if (sem_checkid(ns,sma,semid)) {
- err=-EIDRM;
- goto out_unlock;
- }
ipcp = &sma->sem_perm;
err = audit_ipc_obj(ipcp);
@@ -894,7 +936,7 @@ static int semctl_down(struct ipc_namespace *ns, int semid, int semnum,
switch(cmd){
case IPC_RMID:
- freeary(ns, sma, semid);
+ freeary(ns, sma);
err = 0;
break;
case IPC_SET:
@@ -948,45 +990,15 @@ asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg)
return err;
case IPC_RMID:
case IPC_SET:
- mutex_lock(&sem_ids(ns).mutex);
+ down_write(&sem_ids(ns).rw_mutex);
err = semctl_down(ns,semid,semnum,cmd,version,arg);
- mutex_unlock(&sem_ids(ns).mutex);
+ up_write(&sem_ids(ns).rw_mutex);
return err;
default:
return -EINVAL;
}
}
-static inline void lock_semundo(void)
-{
- struct sem_undo_list *undo_list;
-
- undo_list = current->sysvsem.undo_list;
- if (undo_list)
- spin_lock(&undo_list->lock);
-}
-
-/* This code has an interaction with copy_semundo().
- * Consider; two tasks are sharing the undo_list. task1
- * acquires the undo_list lock in lock_semundo(). If task2 now
- * exits before task1 releases the lock (by calling
- * unlock_semundo()), then task1 will never call spin_unlock().
- * This leave the sem_undo_list in a locked state. If task1 now creats task3
- * and once again shares the sem_undo_list, the sem_undo_list will still be
- * locked, and future SEM_UNDO operations will deadlock. This case is
- * dealt with in copy_semundo() by having it reinitialize the spin lock when
- * the refcnt goes from 1 to 2.
- */
-static inline void unlock_semundo(void)
-{
- struct sem_undo_list *undo_list;
-
- undo_list = current->sysvsem.undo_list;
- if (undo_list)
- spin_unlock(&undo_list->lock);
-}
-
-
/* If the task doesn't already have a undo_list, then allocate one
* here. We guarantee there is only one thread using this undo list,
* and current is THE ONE
@@ -1047,22 +1059,17 @@ static struct sem_undo *find_undo(struct ipc_namespace *ns, int semid)
if (error)
return ERR_PTR(error);
- lock_semundo();
+ spin_lock(&ulp->lock);
un = lookup_undo(ulp, semid);
- unlock_semundo();
+ spin_unlock(&ulp->lock);
if (likely(un!=NULL))
goto out;
/* no undo structure around - allocate one. */
- sma = sem_lock(ns, semid);
- un = ERR_PTR(-EINVAL);
- if(sma==NULL)
- goto out;
- un = ERR_PTR(-EIDRM);
- if (sem_checkid(ns,sma,semid)) {
- sem_unlock(sma);
- goto out;
- }
+ sma = sem_lock_check(ns, semid);
+ if (IS_ERR(sma))
+ return ERR_PTR(PTR_ERR(sma));
+
nsems = sma->sem_nsems;
ipc_rcu_getref(sma);
sem_unlock(sma);
@@ -1077,10 +1084,10 @@ static struct sem_undo *find_undo(struct ipc_namespace *ns, int semid)
new->semadj = (short *) &new[1];
new->semid = semid;
- lock_semundo();
+ spin_lock(&ulp->lock);
un = lookup_undo(ulp, semid);
if (un) {
- unlock_semundo();
+ spin_unlock(&ulp->lock);
kfree(new);
ipc_lock_by_ptr(&sma->sem_perm);
ipc_rcu_putref(sma);
@@ -1091,7 +1098,7 @@ static struct sem_undo *find_undo(struct ipc_namespace *ns, int semid)
ipc_rcu_putref(sma);
if (sma->sem_perm.deleted) {
sem_unlock(sma);
- unlock_semundo();
+ spin_unlock(&ulp->lock);
kfree(new);
un = ERR_PTR(-EIDRM);
goto out;
@@ -1102,7 +1109,7 @@ static struct sem_undo *find_undo(struct ipc_namespace *ns, int semid)
sma->undo = new;
sem_unlock(sma);
un = new;
- unlock_semundo();
+ spin_unlock(&ulp->lock);
out:
return un;
}
@@ -1168,15 +1175,14 @@ retry_undos:
} else
un = NULL;
- sma = sem_lock(ns, semid);
- error=-EINVAL;
- if(sma==NULL)
+ sma = sem_lock_check(ns, semid);
+ if (IS_ERR(sma)) {
+ error = PTR_ERR(sma);
goto out_free;
- error = -EIDRM;
- if (sem_checkid(ns,sma,semid))
- goto out_unlock_free;
+ }
+
/*
- * semid identifies are not unique - find_undo may have
+ * semid identifiers are not unique - find_undo may have
* allocated an undo structure, it was invalidated by an RMID
* and now a new array with received the same id. Check and retry.
*/
@@ -1196,7 +1202,7 @@ retry_undos:
if (error)
goto out_unlock_free;
- error = try_atomic_semop (sma, sops, nsops, un, current->tgid);
+ error = try_atomic_semop (sma, sops, nsops, un, task_tgid_vnr(current));
if (error <= 0) {
if (alter && error == 0)
update_queue (sma);
@@ -1211,7 +1217,7 @@ retry_undos:
queue.sops = sops;
queue.nsops = nsops;
queue.undo = un;
- queue.pid = current->tgid;
+ queue.pid = task_tgid_vnr(current);
queue.id = semid;
queue.alter = alter;
if (alter)
@@ -1242,7 +1248,7 @@ retry_undos:
}
sma = sem_lock(ns, semid);
- if(sma==NULL) {
+ if (IS_ERR(sma)) {
BUG_ON(queue.prev != NULL);
error = -EIDRM;
goto out_free;
@@ -1279,10 +1285,6 @@ asmlinkage long sys_semop (int semid, struct sembuf __user *tsops, unsigned nsop
/* If CLONE_SYSVSEM is set, establish sharing of SEM_UNDO state between
* parent and child tasks.
- *
- * See the notes above unlock_semundo() regarding the spin_lock_init()
- * in this code. Initialize the undo_list->lock here instead of get_undo_list()
- * because of the reasoning in the comment above unlock_semundo.
*/
int copy_semundo(unsigned long clone_flags, struct task_struct *tsk)
@@ -1342,13 +1344,13 @@ void exit_sem(struct task_struct *tsk)
if(semid == -1)
continue;
sma = sem_lock(ns, semid);
- if (sma == NULL)
+ if (IS_ERR(sma))
continue;
if (u->semid == -1)
goto next_entry;
- BUG_ON(sem_checkid(ns,sma,u->semid));
+ BUG_ON(sem_checkid(sma, u->semid));
/* remove u from the sma->undo list */
for (unp = &sma->undo; (un = *unp); unp = &un->id_next) {
@@ -1382,7 +1384,7 @@ found:
semaphore->semval = 0;
if (semaphore->semval > SEMVMX)
semaphore->semval = SEMVMX;
- semaphore->sempid = current->tgid;
+ semaphore->sempid = task_tgid_vnr(current);
}
}
sma->sem_otime = get_seconds();
@@ -1402,7 +1404,7 @@ static int sysvipc_sem_proc_show(struct seq_file *s, void *it)
return seq_printf(s,
"%10d %10d %4o %10lu %5u %5u %5u %5u %10lu %10lu\n",
sma->sem_perm.key,
- sma->sem_id,
+ sma->sem_perm.id,
sma->sem_perm.mode,
sma->sem_nsems,
sma->sem_perm.uid,
diff --git a/ipc/shm.c b/ipc/shm.c
index a86a3a5c8a19..3818fae625c5 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -35,7 +35,7 @@
#include <linux/capability.h>
#include <linux/ptrace.h>
#include <linux/seq_file.h>
-#include <linux/mutex.h>
+#include <linux/rwsem.h>
#include <linux/nsproxy.h>
#include <linux/mount.h>
@@ -59,17 +59,11 @@ static struct ipc_ids init_shm_ids;
#define shm_ids(ns) (*((ns)->ids[IPC_SHM_IDS]))
-#define shm_lock(ns, id) \
- ((struct shmid_kernel*)ipc_lock(&shm_ids(ns),id))
#define shm_unlock(shp) \
ipc_unlock(&(shp)->shm_perm)
-#define shm_get(ns, id) \
- ((struct shmid_kernel*)ipc_get(&shm_ids(ns),id))
-#define shm_buildid(ns, id, seq) \
- ipc_buildid(&shm_ids(ns), id, seq)
+#define shm_buildid(id, seq) ipc_buildid(id, seq)
-static int newseg (struct ipc_namespace *ns, key_t key,
- int shmflg, size_t size);
+static int newseg(struct ipc_namespace *, struct ipc_params *);
static void shm_open(struct vm_area_struct *vma);
static void shm_close(struct vm_area_struct *vma);
static void shm_destroy (struct ipc_namespace *ns, struct shmid_kernel *shp);
@@ -84,9 +78,13 @@ static void __shm_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
ns->shm_ctlall = SHMALL;
ns->shm_ctlmni = SHMMNI;
ns->shm_tot = 0;
- ipc_init_ids(ids, 1);
+ ipc_init_ids(ids);
}
+/*
+ * Called with shm_ids.rw_mutex (writer) and the shp structure locked.
+ * Only shm_ids.rw_mutex remains locked on exit.
+ */
static void do_shm_rmid(struct ipc_namespace *ns, struct shmid_kernel *shp)
{
if (shp->shm_nattch){
@@ -112,20 +110,24 @@ int shm_init_ns(struct ipc_namespace *ns)
void shm_exit_ns(struct ipc_namespace *ns)
{
- int i;
struct shmid_kernel *shp;
+ int next_id;
+ int total, in_use;
+
+ down_write(&shm_ids(ns).rw_mutex);
- mutex_lock(&shm_ids(ns).mutex);
- for (i = 0; i <= shm_ids(ns).max_id; i++) {
- shp = shm_lock(ns, i);
+ in_use = shm_ids(ns).in_use;
+
+ for (total = 0, next_id = 0; total < in_use; next_id++) {
+ shp = idr_find(&shm_ids(ns).ipcs_idr, next_id);
if (shp == NULL)
continue;
-
+ ipc_lock_by_ptr(&shp->shm_perm);
do_shm_rmid(ns, shp);
+ total++;
}
- mutex_unlock(&shm_ids(ns).mutex);
+ up_write(&shm_ids(ns).rw_mutex);
- ipc_fini_ids(ns->ids[IPC_SHM_IDS]);
kfree(ns->ids[IPC_SHM_IDS]);
ns->ids[IPC_SHM_IDS] = NULL;
}
@@ -138,17 +140,49 @@ void __init shm_init (void)
IPC_SHM_IDS, sysvipc_shm_proc_show);
}
-static inline int shm_checkid(struct ipc_namespace *ns,
- struct shmid_kernel *s, int id)
+/*
+ * shm_lock_(check_)down routines are called in the paths where the rw_mutex
+ * is held to protect access to the idr tree.
+ */
+static inline struct shmid_kernel *shm_lock_down(struct ipc_namespace *ns,
+ int id)
{
- if (ipc_checkid(&shm_ids(ns), &s->shm_perm, id))
- return -EIDRM;
- return 0;
+ struct kern_ipc_perm *ipcp = ipc_lock_down(&shm_ids(ns), id);
+
+ return container_of(ipcp, struct shmid_kernel, shm_perm);
+}
+
+static inline struct shmid_kernel *shm_lock_check_down(
+ struct ipc_namespace *ns,
+ int id)
+{
+ struct kern_ipc_perm *ipcp = ipc_lock_check_down(&shm_ids(ns), id);
+
+ return container_of(ipcp, struct shmid_kernel, shm_perm);
}
-static inline struct shmid_kernel *shm_rmid(struct ipc_namespace *ns, int id)
+/*
+ * shm_lock_(check_) routines are called in the paths where the rw_mutex
+ * is not held.
+ */
+static inline struct shmid_kernel *shm_lock(struct ipc_namespace *ns, int id)
{
- return (struct shmid_kernel *)ipc_rmid(&shm_ids(ns), id);
+ struct kern_ipc_perm *ipcp = ipc_lock(&shm_ids(ns), id);
+
+ return container_of(ipcp, struct shmid_kernel, shm_perm);
+}
+
+static inline struct shmid_kernel *shm_lock_check(struct ipc_namespace *ns,
+ int id)
+{
+ struct kern_ipc_perm *ipcp = ipc_lock_check(&shm_ids(ns), id);
+
+ return container_of(ipcp, struct shmid_kernel, shm_perm);
+}
+
+static inline void shm_rmid(struct ipc_namespace *ns, struct shmid_kernel *s)
+{
+ ipc_rmid(&shm_ids(ns), &s->shm_perm);
}
static inline int shm_addid(struct ipc_namespace *ns, struct shmid_kernel *shp)
@@ -166,9 +200,9 @@ static void shm_open(struct vm_area_struct *vma)
struct shmid_kernel *shp;
shp = shm_lock(sfd->ns, sfd->id);
- BUG_ON(!shp);
+ BUG_ON(IS_ERR(shp));
shp->shm_atim = get_seconds();
- shp->shm_lprid = current->tgid;
+ shp->shm_lprid = task_tgid_vnr(current);
shp->shm_nattch++;
shm_unlock(shp);
}
@@ -176,15 +210,16 @@ static void shm_open(struct vm_area_struct *vma)
/*
* shm_destroy - free the struct shmid_kernel
*
+ * @ns: namespace
* @shp: struct to free
*
- * It has to be called with shp and shm_ids.mutex locked,
+ * It has to be called with shp and shm_ids.rw_mutex (writer) locked,
* but returns with shp unlocked and freed.
*/
static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp)
{
ns->shm_tot -= (shp->shm_segsz + PAGE_SIZE - 1) >> PAGE_SHIFT;
- shm_rmid(ns, shp->id);
+ shm_rmid(ns, shp);
shm_unlock(shp);
if (!is_file_hugepages(shp->shm_file))
shmem_lock(shp->shm_file, 0, shp->mlock_user);
@@ -209,11 +244,11 @@ static void shm_close(struct vm_area_struct *vma)
struct shmid_kernel *shp;
struct ipc_namespace *ns = sfd->ns;
- mutex_lock(&shm_ids(ns).mutex);
+ down_write(&shm_ids(ns).rw_mutex);
/* remove from the list of attaches of the shm segment */
- shp = shm_lock(ns, sfd->id);
- BUG_ON(!shp);
- shp->shm_lprid = current->tgid;
+ shp = shm_lock_down(ns, sfd->id);
+ BUG_ON(IS_ERR(shp));
+ shp->shm_lprid = task_tgid_vnr(current);
shp->shm_dtim = get_seconds();
shp->shm_nattch--;
if(shp->shm_nattch == 0 &&
@@ -221,7 +256,7 @@ static void shm_close(struct vm_area_struct *vma)
shm_destroy(ns, shp);
else
shm_unlock(shp);
- mutex_unlock(&shm_ids(ns).mutex);
+ up_write(&shm_ids(ns).rw_mutex);
}
static int shm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
@@ -233,7 +268,7 @@ static int shm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
}
#ifdef CONFIG_NUMA
-int shm_set_policy(struct vm_area_struct *vma, struct mempolicy *new)
+static int shm_set_policy(struct vm_area_struct *vma, struct mempolicy *new)
{
struct file *file = vma->vm_file;
struct shm_file_data *sfd = shm_file_data(file);
@@ -243,7 +278,8 @@ int shm_set_policy(struct vm_area_struct *vma, struct mempolicy *new)
return err;
}
-struct mempolicy *shm_get_policy(struct vm_area_struct *vma, unsigned long addr)
+static struct mempolicy *shm_get_policy(struct vm_area_struct *vma,
+ unsigned long addr)
{
struct file *file = vma->vm_file;
struct shm_file_data *sfd = shm_file_data(file);
@@ -336,8 +372,19 @@ static struct vm_operations_struct shm_vm_ops = {
#endif
};
-static int newseg (struct ipc_namespace *ns, key_t key, int shmflg, size_t size)
+/**
+ * newseg - Create a new shared memory segment
+ * @ns: namespace
+ * @params: ptr to the structure that contains key, size and shmflg
+ *
+ * Called with shm_ids.rw_mutex held as a writer.
+ */
+
+static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
{
+ key_t key = params->key;
+ int shmflg = params->flg;
+ size_t size = params->u.size;
int error;
struct shmid_kernel *shp;
int numpages = (size + PAGE_SIZE -1) >> PAGE_SHIFT;
@@ -386,28 +433,30 @@ static int newseg (struct ipc_namespace *ns, key_t key, int shmflg, size_t size)
if (IS_ERR(file))
goto no_file;
- error = -ENOSPC;
id = shm_addid(ns, shp);
- if(id == -1)
+ if (id < 0) {
+ error = id;
goto no_id;
+ }
- shp->shm_cprid = current->tgid;
+ shp->shm_cprid = task_tgid_vnr(current);
shp->shm_lprid = 0;
shp->shm_atim = shp->shm_dtim = 0;
shp->shm_ctim = get_seconds();
shp->shm_segsz = size;
shp->shm_nattch = 0;
- shp->id = shm_buildid(ns, id, shp->shm_perm.seq);
+ shp->shm_perm.id = shm_buildid(id, shp->shm_perm.seq);
shp->shm_file = file;
/*
* shmid gets reported as "inode#" in /proc/pid/maps.
* proc-ps tools use this. Changing this will break them.
*/
- file->f_dentry->d_inode->i_ino = shp->id;
+ file->f_dentry->d_inode->i_ino = shp->shm_perm.id;
ns->shm_tot += numpages;
+ error = shp->shm_perm.id;
shm_unlock(shp);
- return shp->id;
+ return error;
no_id:
fput(file);
@@ -417,42 +466,49 @@ no_file:
return error;
}
-asmlinkage long sys_shmget (key_t key, size_t size, int shmflg)
+/*
+ * Called with shm_ids.rw_mutex and ipcp locked.
+ */
+static inline int shm_security(struct kern_ipc_perm *ipcp, int shmflg)
{
struct shmid_kernel *shp;
- int err, id = 0;
+
+ shp = container_of(ipcp, struct shmid_kernel, shm_perm);
+ return security_shm_associate(shp, shmflg);
+}
+
+/*
+ * Called with shm_ids.rw_mutex and ipcp locked.
+ */
+static inline int shm_more_checks(struct kern_ipc_perm *ipcp,
+ struct ipc_params *params)
+{
+ struct shmid_kernel *shp;
+
+ shp = container_of(ipcp, struct shmid_kernel, shm_perm);
+ if (shp->shm_segsz < params->u.size)
+ return -EINVAL;
+
+ return 0;
+}
+
+asmlinkage long sys_shmget (key_t key, size_t size, int shmflg)
+{
struct ipc_namespace *ns;
+ struct ipc_ops shm_ops;
+ struct ipc_params shm_params;
ns = current->nsproxy->ipc_ns;
- mutex_lock(&shm_ids(ns).mutex);
- if (key == IPC_PRIVATE) {
- err = newseg(ns, key, shmflg, size);
- } else if ((id = ipc_findkey(&shm_ids(ns), key)) == -1) {
- if (!(shmflg & IPC_CREAT))
- err = -ENOENT;
- else
- err = newseg(ns, key, shmflg, size);
- } else if ((shmflg & IPC_CREAT) && (shmflg & IPC_EXCL)) {
- err = -EEXIST;
- } else {
- shp = shm_lock(ns, id);
- BUG_ON(shp==NULL);
- if (shp->shm_segsz < size)
- err = -EINVAL;
- else if (ipcperms(&shp->shm_perm, shmflg))
- err = -EACCES;
- else {
- int shmid = shm_buildid(ns, id, shp->shm_perm.seq);
- err = security_shm_associate(shp, shmflg);
- if (!err)
- err = shmid;
- }
- shm_unlock(shp);
- }
- mutex_unlock(&shm_ids(ns).mutex);
+ shm_ops.getnew = newseg;
+ shm_ops.associate = shm_security;
+ shm_ops.more_checks = shm_more_checks;
- return err;
+ shm_params.key = key;
+ shm_params.flg = shmflg;
+ shm_params.u.size = size;
+
+ return ipcget(ns, &shm_ids(ns), &shm_ops, &shm_params);
}
static inline unsigned long copy_shmid_to_user(void __user *buf, struct shmid64_ds *in, int version)
@@ -546,20 +602,26 @@ static inline unsigned long copy_shminfo_to_user(void __user *buf, struct shminf
}
}
+/*
+ * Called with shm_ids.rw_mutex held as a reader
+ */
static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss,
unsigned long *swp)
{
- int i;
+ int next_id;
+ int total, in_use;
*rss = 0;
*swp = 0;
- for (i = 0; i <= shm_ids(ns).max_id; i++) {
+ in_use = shm_ids(ns).in_use;
+
+ for (total = 0, next_id = 0; total < in_use; next_id++) {
struct shmid_kernel *shp;
struct inode *inode;
- shp = shm_get(ns, i);
- if(!shp)
+ shp = idr_find(&shm_ids(ns).ipcs_idr, next_id);
+ if (shp == NULL)
continue;
inode = shp->shm_file->f_path.dentry->d_inode;
@@ -574,6 +636,8 @@ static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss,
*swp += info->swapped;
spin_unlock(&info->lock);
}
+
+ total++;
}
}
@@ -609,8 +673,11 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
shminfo.shmmin = SHMMIN;
if(copy_shminfo_to_user (buf, &shminfo, version))
return -EFAULT;
- /* reading a integer is always atomic */
- err= shm_ids(ns).max_id;
+
+ down_read(&shm_ids(ns).rw_mutex);
+ err = ipc_get_maxid(&shm_ids(ns));
+ up_read(&shm_ids(ns).rw_mutex);
+
if(err<0)
err = 0;
goto out;
@@ -624,14 +691,14 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
return err;
memset(&shm_info,0,sizeof(shm_info));
- mutex_lock(&shm_ids(ns).mutex);
+ down_read(&shm_ids(ns).rw_mutex);
shm_info.used_ids = shm_ids(ns).in_use;
shm_get_stat (ns, &shm_info.shm_rss, &shm_info.shm_swp);
shm_info.shm_tot = ns->shm_tot;
shm_info.swap_attempts = 0;
shm_info.swap_successes = 0;
- err = shm_ids(ns).max_id;
- mutex_unlock(&shm_ids(ns).mutex);
+ err = ipc_get_maxid(&shm_ids(ns));
+ up_read(&shm_ids(ns).rw_mutex);
if(copy_to_user (buf, &shm_info, sizeof(shm_info))) {
err = -EFAULT;
goto out;
@@ -645,20 +712,25 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
{
struct shmid64_ds tbuf;
int result;
- memset(&tbuf, 0, sizeof(tbuf));
- shp = shm_lock(ns, shmid);
- if(shp==NULL) {
- err = -EINVAL;
+
+ if (!buf) {
+ err = -EFAULT;
goto out;
- } else if(cmd==SHM_STAT) {
- err = -EINVAL;
- if (shmid > shm_ids(ns).max_id)
- goto out_unlock;
- result = shm_buildid(ns, shmid, shp->shm_perm.seq);
+ }
+
+ if (cmd == SHM_STAT) {
+ shp = shm_lock(ns, shmid);
+ if (IS_ERR(shp)) {
+ err = PTR_ERR(shp);
+ goto out;
+ }
+ result = shp->shm_perm.id;
} else {
- err = shm_checkid(ns, shp,shmid);
- if(err)
- goto out_unlock;
+ shp = shm_lock_check(ns, shmid);
+ if (IS_ERR(shp)) {
+ err = PTR_ERR(shp);
+ goto out;
+ }
result = 0;
}
err=-EACCES;
@@ -667,6 +739,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
err = security_shm_shmctl(shp, cmd);
if (err)
goto out_unlock;
+ memset(&tbuf, 0, sizeof(tbuf));
kernel_to_ipc64_perm(&shp->shm_perm, &tbuf.shm_perm);
tbuf.shm_segsz = shp->shm_segsz;
tbuf.shm_atime = shp->shm_atim;
@@ -685,14 +758,11 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
case SHM_LOCK:
case SHM_UNLOCK:
{
- shp = shm_lock(ns, shmid);
- if(shp==NULL) {
- err = -EINVAL;
+ shp = shm_lock_check(ns, shmid);
+ if (IS_ERR(shp)) {
+ err = PTR_ERR(shp);
goto out;
}
- err = shm_checkid(ns, shp,shmid);
- if(err)
- goto out_unlock;
err = audit_ipc_obj(&(shp->shm_perm));
if (err)
@@ -741,14 +811,12 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
* Instead we set a destroyed flag, and then blow
* the name away when the usage hits zero.
*/
- mutex_lock(&shm_ids(ns).mutex);
- shp = shm_lock(ns, shmid);
- err = -EINVAL;
- if (shp == NULL)
+ down_write(&shm_ids(ns).rw_mutex);
+ shp = shm_lock_check_down(ns, shmid);
+ if (IS_ERR(shp)) {
+ err = PTR_ERR(shp);
goto out_up;
- err = shm_checkid(ns, shp, shmid);
- if(err)
- goto out_unlock_up;
+ }
err = audit_ipc_obj(&(shp->shm_perm));
if (err)
@@ -766,24 +834,27 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
goto out_unlock_up;
do_shm_rmid(ns, shp);
- mutex_unlock(&shm_ids(ns).mutex);
+ up_write(&shm_ids(ns).rw_mutex);
goto out;
}
case IPC_SET:
{
+ if (!buf) {
+ err = -EFAULT;
+ goto out;
+ }
+
if (copy_shmid_from_user (&setbuf, buf, version)) {
err = -EFAULT;
goto out;
}
- mutex_lock(&shm_ids(ns).mutex);
- shp = shm_lock(ns, shmid);
- err=-EINVAL;
- if(shp==NULL)
+ down_write(&shm_ids(ns).rw_mutex);
+ shp = shm_lock_check_down(ns, shmid);
+ if (IS_ERR(shp)) {
+ err = PTR_ERR(shp);
goto out_up;
- err = shm_checkid(ns, shp,shmid);
- if(err)
- goto out_unlock_up;
+ }
err = audit_ipc_obj(&(shp->shm_perm));
if (err)
goto out_unlock_up;
@@ -818,7 +889,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
out_unlock_up:
shm_unlock(shp);
out_up:
- mutex_unlock(&shm_ids(ns).mutex);
+ up_write(&shm_ids(ns).rw_mutex);
goto out;
out_unlock:
shm_unlock(shp);
@@ -889,13 +960,11 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
* additional creator id...
*/
ns = current->nsproxy->ipc_ns;
- shp = shm_lock(ns, shmid);
- if(shp == NULL)
+ shp = shm_lock_check(ns, shmid);
+ if (IS_ERR(shp)) {
+ err = PTR_ERR(shp);
goto out;
-
- err = shm_checkid(ns, shp,shmid);
- if (err)
- goto out_unlock;
+ }
err = -EACCES;
if (ipcperms(&shp->shm_perm, acc_mode))
@@ -906,7 +975,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
goto out_unlock;
path.dentry = dget(shp->shm_file->f_path.dentry);
- path.mnt = mntget(shp->shm_file->f_path.mnt);
+ path.mnt = shp->shm_file->f_path.mnt;
shp->shm_nattch++;
size = i_size_read(path.dentry->d_inode);
shm_unlock(shp);
@@ -914,19 +983,17 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
err = -ENOMEM;
sfd = kzalloc(sizeof(*sfd), GFP_KERNEL);
if (!sfd)
- goto out_put_path;
+ goto out_put_dentry;
err = -ENOMEM;
- file = get_empty_filp();
+
+ file = alloc_file(path.mnt, path.dentry, f_mode, &shm_file_operations);
if (!file)
goto out_free;
- file->f_op = &shm_file_operations;
file->private_data = sfd;
- file->f_path = path;
file->f_mapping = shp->shm_file->f_mapping;
- file->f_mode = f_mode;
- sfd->id = shp->id;
+ sfd->id = shp->shm_perm.id;
sfd->ns = get_ipc_ns(ns);
sfd->file = shp->shm_file;
sfd->vm_ops = NULL;
@@ -956,16 +1023,16 @@ invalid:
fput(file);
out_nattch:
- mutex_lock(&shm_ids(ns).mutex);
- shp = shm_lock(ns, shmid);
- BUG_ON(!shp);
+ down_write(&shm_ids(ns).rw_mutex);
+ shp = shm_lock_down(ns, shmid);
+ BUG_ON(IS_ERR(shp));
shp->shm_nattch--;
if(shp->shm_nattch == 0 &&
shp->shm_perm.mode & SHM_DEST)
shm_destroy(ns, shp);
else
shm_unlock(shp);
- mutex_unlock(&shm_ids(ns).mutex);
+ up_write(&shm_ids(ns).rw_mutex);
out:
return err;
@@ -976,9 +1043,8 @@ out_unlock:
out_free:
kfree(sfd);
-out_put_path:
+out_put_dentry:
dput(path.dentry);
- mntput(path.mnt);
goto out_nattch;
}
@@ -1096,7 +1162,7 @@ static int sysvipc_shm_proc_show(struct seq_file *s, void *it)
format = BIG_STRING;
return seq_printf(s, format,
shp->shm_perm.key,
- shp->id,
+ shp->shm_perm.id,
shp->shm_perm.mode,
shp->shm_segsz,
shp->shm_cprid,
diff --git a/ipc/util.c b/ipc/util.c
index 44e5135aee47..1aa0ebf71bac 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -32,6 +32,7 @@
#include <linux/proc_fs.h>
#include <linux/audit.h>
#include <linux/nsproxy.h>
+#include <linux/rwsem.h>
#include <asm/unistd.h>
@@ -129,23 +130,16 @@ __initcall(ipc_init);
/**
* ipc_init_ids - initialise IPC identifiers
* @ids: Identifier set
- * @size: Number of identifiers
*
- * Given a size for the ipc identifier range (limited below IPCMNI)
- * set up the sequence range to use then allocate and initialise the
- * array itself.
+ * Set up the sequence range to use for the ipc identifier range (limited
+ * below IPCMNI) then initialise the ids idr.
*/
-void ipc_init_ids(struct ipc_ids* ids, int size)
+void ipc_init_ids(struct ipc_ids *ids)
{
- int i;
+ init_rwsem(&ids->rw_mutex);
- mutex_init(&ids->mutex);
-
- if(size > IPCMNI)
- size = IPCMNI;
ids->in_use = 0;
- ids->max_id = -1;
ids->seq = 0;
{
int seq_limit = INT_MAX/SEQ_MULTIPLIER;
@@ -155,17 +149,7 @@ void ipc_init_ids(struct ipc_ids* ids, int size)
ids->seq_max = seq_limit;
}
- ids->entries = ipc_rcu_alloc(sizeof(struct kern_ipc_perm *)*size +
- sizeof(struct ipc_id_ary));
-
- if(ids->entries == NULL) {
- printk(KERN_ERR "ipc_init_ids() failed, ipc service disabled.\n");
- size = 0;
- ids->entries = &ids->nullentry;
- }
- ids->entries->size = size;
- for(i=0;i<size;i++)
- ids->entries->p[i] = NULL;
+ idr_init(&ids->ipcs_idr);
}
#ifdef CONFIG_PROC_FS
@@ -208,99 +192,96 @@ void __init ipc_init_proc_interface(const char *path, const char *header,
* @ids: Identifier set
* @key: The key to find
*
- * Requires ipc_ids.mutex locked.
- * Returns the identifier if found or -1 if not.
+ * Requires ipc_ids.rw_mutex locked.
+ * Returns the LOCKED pointer to the ipc structure if found or NULL
+ * if not.
+ * If key is found ipc points to the owning ipc structure
*/
-int ipc_findkey(struct ipc_ids* ids, key_t key)
+static struct kern_ipc_perm *ipc_findkey(struct ipc_ids *ids, key_t key)
{
- int id;
- struct kern_ipc_perm* p;
- int max_id = ids->max_id;
+ struct kern_ipc_perm *ipc;
+ int next_id;
+ int total;
- /*
- * rcu_dereference() is not needed here
- * since ipc_ids.mutex is held
- */
- for (id = 0; id <= max_id; id++) {
- p = ids->entries->p[id];
- if(p==NULL)
+ for (total = 0, next_id = 0; total < ids->in_use; next_id++) {
+ ipc = idr_find(&ids->ipcs_idr, next_id);
+
+ if (ipc == NULL)
+ continue;
+
+ if (ipc->key != key) {
+ total++;
continue;
- if (key == p->key)
- return id;
+ }
+
+ ipc_lock_by_ptr(ipc);
+ return ipc;
}
- return -1;
+
+ return NULL;
}
-/*
- * Requires ipc_ids.mutex locked
+/**
+ * ipc_get_maxid - get the last assigned id
+ * @ids: IPC identifier set
+ *
+ * Called with ipc_ids.rw_mutex held.
*/
-static int grow_ary(struct ipc_ids* ids, int newsize)
-{
- struct ipc_id_ary* new;
- struct ipc_id_ary* old;
- int i;
- int size = ids->entries->size;
-
- if(newsize > IPCMNI)
- newsize = IPCMNI;
- if(newsize <= size)
- return newsize;
-
- new = ipc_rcu_alloc(sizeof(struct kern_ipc_perm *)*newsize +
- sizeof(struct ipc_id_ary));
- if(new == NULL)
- return size;
- new->size = newsize;
- memcpy(new->p, ids->entries->p, sizeof(struct kern_ipc_perm *)*size);
- for(i=size;i<newsize;i++) {
- new->p[i] = NULL;
- }
- old = ids->entries;
- /*
- * Use rcu_assign_pointer() to make sure the memcpyed contents
- * of the new array are visible before the new array becomes visible.
- */
- rcu_assign_pointer(ids->entries, new);
+int ipc_get_maxid(struct ipc_ids *ids)
+{
+ struct kern_ipc_perm *ipc;
+ int max_id = -1;
+ int total, id;
+
+ if (ids->in_use == 0)
+ return -1;
- __ipc_fini_ids(ids, old);
- return newsize;
+ if (ids->in_use == IPCMNI)
+ return IPCMNI - 1;
+
+ /* Look for the last assigned id */
+ total = 0;
+ for (id = 0; id < IPCMNI && total < ids->in_use; id++) {
+ ipc = idr_find(&ids->ipcs_idr, id);
+ if (ipc != NULL) {
+ max_id = id;
+ total++;
+ }
+ }
+ return max_id;
}
/**
* ipc_addid - add an IPC identifier
* @ids: IPC identifier set
* @new: new IPC permission set
- * @size: new size limit for the id array
+ * @size: limit for the number of used ids
*
- * Add an entry 'new' to the IPC arrays. The permissions object is
+ * Add an entry 'new' to the IPC ids idr. The permissions object is
* initialised and the first free entry is set up and the id assigned
- * is returned. The list is returned in a locked state on success.
- * On failure the list is not locked and -1 is returned.
+ * is returned. The 'new' entry is returned in a locked state on success.
+ * On failure the entry is not locked and a negative err-code is returned.
*
- * Called with ipc_ids.mutex held.
+ * Called with ipc_ids.rw_mutex held as a writer.
*/
int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
{
- int id;
+ int id, err;
- size = grow_ary(ids,size);
+ if (size > IPCMNI)
+ size = IPCMNI;
+
+ if (ids->in_use >= size)
+ return -ENOSPC;
+
+ err = idr_get_new(&ids->ipcs_idr, new, &id);
+ if (err)
+ return err;
- /*
- * rcu_dereference()() is not needed here since
- * ipc_ids.mutex is held
- */
- for (id = 0; id < size; id++) {
- if(ids->entries->p[id] == NULL)
- goto found;
- }
- return -1;
-found:
ids->in_use++;
- if (id > ids->max_id)
- ids->max_id = id;
new->cuid = new->uid = current->euid;
new->gid = new->cgid = current->egid;
@@ -313,48 +294,153 @@ found:
new->deleted = 0;
rcu_read_lock();
spin_lock(&new->lock);
- ids->entries->p[id] = new;
return id;
}
/**
+ * ipcget_new - create a new ipc object
+ * @ns: namespace
+ * @ids: IPC identifer set
+ * @ops: the actual creation routine to call
+ * @params: its parameters
+ *
+ * This routine is called by sys_msgget, sys_semget() and sys_shmget()
+ * when the key is IPC_PRIVATE.
+ */
+int ipcget_new(struct ipc_namespace *ns, struct ipc_ids *ids,
+ struct ipc_ops *ops, struct ipc_params *params)
+{
+ int err;
+retry:
+ err = idr_pre_get(&ids->ipcs_idr, GFP_KERNEL);
+
+ if (!err)
+ return -ENOMEM;
+
+ down_write(&ids->rw_mutex);
+ err = ops->getnew(ns, params);
+ up_write(&ids->rw_mutex);
+
+ if (err == -EAGAIN)
+ goto retry;
+
+ return err;
+}
+
+/**
+ * ipc_check_perms - check security and permissions for an IPC
+ * @ipcp: ipc permission set
+ * @ops: the actual security routine to call
+ * @params: its parameters
+ *
+ * This routine is called by sys_msgget(), sys_semget() and sys_shmget()
+ * when the key is not IPC_PRIVATE and that key already exists in the
+ * ids IDR.
+ *
+ * On success, the IPC id is returned.
+ *
+ * It is called with ipc_ids.rw_mutex and ipcp->lock held.
+ */
+static int ipc_check_perms(struct kern_ipc_perm *ipcp, struct ipc_ops *ops,
+ struct ipc_params *params)
+{
+ int err;
+
+ if (ipcperms(ipcp, params->flg))
+ err = -EACCES;
+ else {
+ err = ops->associate(ipcp, params->flg);
+ if (!err)
+ err = ipcp->id;
+ }
+
+ return err;
+}
+
+/**
+ * ipcget_public - get an ipc object or create a new one
+ * @ns: namespace
+ * @ids: IPC identifer set
+ * @ops: the actual creation routine to call
+ * @params: its parameters
+ *
+ * This routine is called by sys_msgget, sys_semget() and sys_shmget()
+ * when the key is not IPC_PRIVATE.
+ * It adds a new entry if the key is not found and does some permission
+ * / security checkings if the key is found.
+ *
+ * On success, the ipc id is returned.
+ */
+int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids,
+ struct ipc_ops *ops, struct ipc_params *params)
+{
+ struct kern_ipc_perm *ipcp;
+ int flg = params->flg;
+ int err;
+retry:
+ err = idr_pre_get(&ids->ipcs_idr, GFP_KERNEL);
+
+ /*
+ * Take the lock as a writer since we are potentially going to add
+ * a new entry + read locks are not "upgradable"
+ */
+ down_write(&ids->rw_mutex);
+ ipcp = ipc_findkey(ids, params->key);
+ if (ipcp == NULL) {
+ /* key not used */
+ if (!(flg & IPC_CREAT))
+ err = -ENOENT;
+ else if (!err)
+ err = -ENOMEM;
+ else
+ err = ops->getnew(ns, params);
+ } else {
+ /* ipc object has been locked by ipc_findkey() */
+
+ if (flg & IPC_CREAT && flg & IPC_EXCL)
+ err = -EEXIST;
+ else {
+ err = 0;
+ if (ops->more_checks)
+ err = ops->more_checks(ipcp, params);
+ if (!err)
+ /*
+ * ipc_check_perms returns the IPC id on
+ * success
+ */
+ err = ipc_check_perms(ipcp, ops, params);
+ }
+ ipc_unlock(ipcp);
+ }
+ up_write(&ids->rw_mutex);
+
+ if (err == -EAGAIN)
+ goto retry;
+
+ return err;
+}
+
+
+/**
* ipc_rmid - remove an IPC identifier
- * @ids: identifier set
- * @id: Identifier to remove
+ * @ids: IPC identifier set
+ * @ipcp: ipc perm structure containing the identifier to remove
*
- * The identifier must be valid, and in use. The kernel will panic if
- * fed an invalid identifier. The entry is removed and internal
- * variables recomputed. The object associated with the identifier
- * is returned.
- * ipc_ids.mutex and the spinlock for this ID is hold before this function
- * is called, and remain locked on the exit.
+ * ipc_ids.rw_mutex (as a writer) and the spinlock for this ID are held
+ * before this function is called, and remain locked on the exit.
*/
-struct kern_ipc_perm* ipc_rmid(struct ipc_ids* ids, int id)
+void ipc_rmid(struct ipc_ids *ids, struct kern_ipc_perm *ipcp)
{
- struct kern_ipc_perm* p;
- int lid = id % SEQ_MULTIPLIER;
- BUG_ON(lid >= ids->entries->size);
+ int lid = ipcid_to_idx(ipcp->id);
+
+ idr_remove(&ids->ipcs_idr, lid);
- /*
- * do not need a rcu_dereference()() here to force ordering
- * on Alpha, since the ipc_ids.mutex is held.
- */
- p = ids->entries->p[lid];
- ids->entries->p[lid] = NULL;
- BUG_ON(p==NULL);
ids->in_use--;
- if (lid == ids->max_id) {
- do {
- lid--;
- if(lid == -1)
- break;
- } while (ids->entries->p[lid] == NULL);
- ids->max_id = lid;
- }
- p->deleted = 1;
- return p;
+ ipcp->deleted = 1;
+
+ return;
}
/**
@@ -491,10 +577,12 @@ static void ipc_do_vfree(struct work_struct *work)
*/
static void ipc_schedule_free(struct rcu_head *head)
{
- struct ipc_rcu_grace *grace =
- container_of(head, struct ipc_rcu_grace, rcu);
- struct ipc_rcu_sched *sched =
- container_of(&(grace->data[0]), struct ipc_rcu_sched, data[0]);
+ struct ipc_rcu_grace *grace;
+ struct ipc_rcu_sched *sched;
+
+ grace = container_of(head, struct ipc_rcu_grace, rcu);
+ sched = container_of(&(grace->data[0]), struct ipc_rcu_sched,
+ data[0]);
INIT_WORK(&sched->work, ipc_do_vfree);
schedule_work(&sched->work);
@@ -583,7 +671,7 @@ void kernel_to_ipc64_perm (struct kern_ipc_perm *in, struct ipc64_perm *out)
}
/**
- * ipc64_perm_to_ipc_perm - convert old ipc permissions to new
+ * ipc64_perm_to_ipc_perm - convert new ipc permissions to old
* @in: new style IPC permissions
* @out: old style IPC permissions
*
@@ -602,44 +690,37 @@ void ipc64_perm_to_ipc_perm (struct ipc64_perm *in, struct ipc_perm *out)
out->seq = in->seq;
}
-/*
- * So far only shm_get_stat() calls ipc_get() via shm_get(), so ipc_get()
- * is called with shm_ids.mutex locked. Since grow_ary() is also called with
- * shm_ids.mutex down(for Shared Memory), there is no need to add read
- * barriers here to gurantee the writes in grow_ary() are seen in order
- * here (for Alpha).
+/**
+ * ipc_lock - Lock an ipc structure without rw_mutex held
+ * @ids: IPC identifier set
+ * @id: ipc id to look for
+ *
+ * Look for an id in the ipc ids idr and lock the associated ipc object.
*
- * However ipc_get() itself does not necessary require ipc_ids.mutex down. So
- * if in the future ipc_get() is used by other places without ipc_ids.mutex
- * down, then ipc_get() needs read memery barriers as ipc_lock() does.
+ * The ipc object is locked on exit.
+ *
+ * This is the routine that should be called when the rw_mutex is not already
+ * held, i.e. idr tree not protected: it protects the idr tree in read mode
+ * during the idr_find().
*/
-struct kern_ipc_perm* ipc_get(struct ipc_ids* ids, int id)
-{
- struct kern_ipc_perm* out;
- int lid = id % SEQ_MULTIPLIER;
- if(lid >= ids->entries->size)
- return NULL;
- out = ids->entries->p[lid];
- return out;
-}
-struct kern_ipc_perm* ipc_lock(struct ipc_ids* ids, int id)
+struct kern_ipc_perm *ipc_lock(struct ipc_ids *ids, int id)
{
- struct kern_ipc_perm* out;
- int lid = id % SEQ_MULTIPLIER;
- struct ipc_id_ary* entries;
+ struct kern_ipc_perm *out;
+ int lid = ipcid_to_idx(id);
+
+ down_read(&ids->rw_mutex);
rcu_read_lock();
- entries = rcu_dereference(ids->entries);
- if(lid >= entries->size) {
- rcu_read_unlock();
- return NULL;
- }
- out = entries->p[lid];
- if(out == NULL) {
+ out = idr_find(&ids->ipcs_idr, lid);
+ if (out == NULL) {
rcu_read_unlock();
- return NULL;
+ up_read(&ids->rw_mutex);
+ return ERR_PTR(-EINVAL);
}
+
+ up_read(&ids->rw_mutex);
+
spin_lock(&out->lock);
/* ipc_rmid() may have already freed the ID while ipc_lock
@@ -648,33 +729,44 @@ struct kern_ipc_perm* ipc_lock(struct ipc_ids* ids, int id)
if (out->deleted) {
spin_unlock(&out->lock);
rcu_read_unlock();
- return NULL;
+ return ERR_PTR(-EINVAL);
}
+
return out;
}
-void ipc_lock_by_ptr(struct kern_ipc_perm *perm)
-{
- rcu_read_lock();
- spin_lock(&perm->lock);
-}
+/**
+ * ipc_lock_down - Lock an ipc structure with rw_sem held
+ * @ids: IPC identifier set
+ * @id: ipc id to look for
+ *
+ * Look for an id in the ipc ids idr and lock the associated ipc object.
+ *
+ * The ipc object is locked on exit.
+ *
+ * This is the routine that should be called when the rw_mutex is already
+ * held, i.e. idr tree protected.
+ */
-void ipc_unlock(struct kern_ipc_perm* perm)
+struct kern_ipc_perm *ipc_lock_down(struct ipc_ids *ids, int id)
{
- spin_unlock(&perm->lock);
- rcu_read_unlock();
-}
+ struct kern_ipc_perm *out;
+ int lid = ipcid_to_idx(id);
-int ipc_buildid(struct ipc_ids* ids, int id, int seq)
-{
- return SEQ_MULTIPLIER*seq + id;
-}
+ rcu_read_lock();
+ out = idr_find(&ids->ipcs_idr, lid);
+ if (out == NULL) {
+ rcu_read_unlock();
+ return ERR_PTR(-EINVAL);
+ }
-int ipc_checkid(struct ipc_ids* ids, struct kern_ipc_perm* ipcp, int uid)
-{
- if(uid/SEQ_MULTIPLIER != ipcp->seq)
- return 1;
- return 0;
+ spin_lock(&out->lock);
+
+ /*
+ * No need to verify that the structure is still valid since the
+ * rw_mutex is held.
+ */
+ return out;
}
#ifdef __ARCH_WANT_IPC_PARSE_VERSION
@@ -707,27 +799,30 @@ struct ipc_proc_iter {
struct ipc_proc_iface *iface;
};
-static void *sysvipc_proc_next(struct seq_file *s, void *it, loff_t *pos)
+/*
+ * This routine locks the ipc structure found at least at position pos.
+ */
+struct kern_ipc_perm *sysvipc_find_ipc(struct ipc_ids *ids, loff_t pos,
+ loff_t *new_pos)
{
- struct ipc_proc_iter *iter = s->private;
- struct ipc_proc_iface *iface = iter->iface;
- struct kern_ipc_perm *ipc = it;
- loff_t p;
- struct ipc_ids *ids;
+ struct kern_ipc_perm *ipc;
+ int total, id;
- ids = iter->ns->ids[iface->ids];
+ total = 0;
+ for (id = 0; id < pos && total < ids->in_use; id++) {
+ ipc = idr_find(&ids->ipcs_idr, id);
+ if (ipc != NULL)
+ total++;
+ }
- /* If we had an ipc id locked before, unlock it */
- if (ipc && ipc != SEQ_START_TOKEN)
- ipc_unlock(ipc);
+ if (total >= ids->in_use)
+ return NULL;
- /*
- * p = *pos - 1 (because id 0 starts at position 1)
- * + 1 (because we increment the position by one)
- */
- for (p = *pos; p <= ids->max_id; p++) {
- if ((ipc = ipc_lock(ids, p)) != NULL) {
- *pos = p + 1;
+ for ( ; pos < IPCMNI; pos++) {
+ ipc = idr_find(&ids->ipcs_idr, pos);
+ if (ipc != NULL) {
+ *new_pos = pos + 1;
+ ipc_lock_by_ptr(ipc);
return ipc;
}
}
@@ -736,16 +831,27 @@ static void *sysvipc_proc_next(struct seq_file *s, void *it, loff_t *pos)
return NULL;
}
+static void *sysvipc_proc_next(struct seq_file *s, void *it, loff_t *pos)
+{
+ struct ipc_proc_iter *iter = s->private;
+ struct ipc_proc_iface *iface = iter->iface;
+ struct kern_ipc_perm *ipc = it;
+
+ /* If we had an ipc id locked before, unlock it */
+ if (ipc && ipc != SEQ_START_TOKEN)
+ ipc_unlock(ipc);
+
+ return sysvipc_find_ipc(iter->ns->ids[iface->ids], *pos, pos);
+}
+
/*
- * File positions: pos 0 -> header, pos n -> ipc id + 1.
- * SeqFile iterator: iterator value locked shp or SEQ_TOKEN_START.
+ * File positions: pos 0 -> header, pos n -> ipc id = n - 1.
+ * SeqFile iterator: iterator value locked ipc pointer or SEQ_TOKEN_START.
*/
static void *sysvipc_proc_start(struct seq_file *s, loff_t *pos)
{
struct ipc_proc_iter *iter = s->private;
struct ipc_proc_iface *iface = iter->iface;
- struct kern_ipc_perm *ipc;
- loff_t p;
struct ipc_ids *ids;
ids = iter->ns->ids[iface->ids];
@@ -754,7 +860,7 @@ static void *sysvipc_proc_start(struct seq_file *s, loff_t *pos)
* Take the lock - this will be released by the corresponding
* call to stop().
*/
- mutex_lock(&ids->mutex);
+ down_read(&ids->rw_mutex);
/* pos < 0 is invalid */
if (*pos < 0)
@@ -765,13 +871,7 @@ static void *sysvipc_proc_start(struct seq_file *s, loff_t *pos)
return SEQ_START_TOKEN;
/* Find the (pos-1)th ipc */
- for (p = *pos - 1; p <= ids->max_id; p++) {
- if ((ipc = ipc_lock(ids, p)) != NULL) {
- *pos = p + 1;
- return ipc;
- }
- }
- return NULL;
+ return sysvipc_find_ipc(ids, *pos - 1, pos);
}
static void sysvipc_proc_stop(struct seq_file *s, void *it)
@@ -781,13 +881,13 @@ static void sysvipc_proc_stop(struct seq_file *s, void *it)
struct ipc_proc_iface *iface = iter->iface;
struct ipc_ids *ids;
- /* If we had a locked segment, release it */
+ /* If we had a locked structure, release it */
if (ipc && ipc != SEQ_START_TOKEN)
ipc_unlock(ipc);
ids = iter->ns->ids[iface->ids];
/* Release the lock we took in start() */
- mutex_unlock(&ids->mutex);
+ up_read(&ids->rw_mutex);
}
static int sysvipc_proc_show(struct seq_file *s, void *it)
diff --git a/ipc/util.h b/ipc/util.h
index 333e891bcaca..9ffea40457ce 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -10,6 +10,9 @@
#ifndef _IPC_UTIL_H
#define _IPC_UTIL_H
+#include <linux/idr.h>
+#include <linux/err.h>
+
#define USHRT_MAX 0xffff
#define SEQ_MULTIPLIER (IPCMNI)
@@ -25,24 +28,46 @@ void sem_exit_ns(struct ipc_namespace *ns);
void msg_exit_ns(struct ipc_namespace *ns);
void shm_exit_ns(struct ipc_namespace *ns);
-struct ipc_id_ary {
- int size;
- struct kern_ipc_perm *p[0];
-};
-
struct ipc_ids {
int in_use;
- int max_id;
unsigned short seq;
unsigned short seq_max;
- struct mutex mutex;
- struct ipc_id_ary nullentry;
- struct ipc_id_ary* entries;
+ struct rw_semaphore rw_mutex;
+ struct idr ipcs_idr;
+};
+
+/*
+ * Structure that holds the parameters needed by the ipc operations
+ * (see after)
+ */
+struct ipc_params {
+ key_t key;
+ int flg;
+ union {
+ size_t size; /* for shared memories */
+ int nsems; /* for semaphores */
+ } u; /* holds the getnew() specific param */
+};
+
+/*
+ * Structure that holds some ipc operations. This structure is used to unify
+ * the calls to sys_msgget(), sys_semget(), sys_shmget()
+ * . routine to call to create a new ipc object. Can be one of newque,
+ * newary, newseg
+ * . routine to call to check permissions for a new ipc object.
+ * Can be one of security_msg_associate, security_sem_associate,
+ * security_shm_associate
+ * . routine to call for an extra check if needed
+ */
+struct ipc_ops {
+ int (*getnew) (struct ipc_namespace *, struct ipc_params *);
+ int (*associate) (struct kern_ipc_perm *, int);
+ int (*more_checks) (struct kern_ipc_perm *, struct ipc_params *);
};
struct seq_file;
-void ipc_init_ids(struct ipc_ids *ids, int size);
+void ipc_init_ids(struct ipc_ids *);
#ifdef CONFIG_PROC_FS
void __init ipc_init_proc_interface(const char *path, const char *header,
int ids, int (*show)(struct seq_file *, void *));
@@ -54,14 +79,19 @@ void __init ipc_init_proc_interface(const char *path, const char *header,
#define IPC_MSG_IDS 1
#define IPC_SHM_IDS 2
-/* must be called with ids->mutex acquired.*/
-int ipc_findkey(struct ipc_ids* ids, key_t key);
-int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size);
+#define ipcid_to_idx(id) ((id) % SEQ_MULTIPLIER)
+
+/* must be called with ids->rw_mutex acquired for writing */
+int ipc_addid(struct ipc_ids *, struct kern_ipc_perm *, int);
+
+/* must be called with ids->rw_mutex acquired for reading */
+int ipc_get_maxid(struct ipc_ids *);
/* must be called with both locks acquired. */
-struct kern_ipc_perm* ipc_rmid(struct ipc_ids* ids, int id);
+void ipc_rmid(struct ipc_ids *, struct kern_ipc_perm *);
-int ipcperms (struct kern_ipc_perm *ipcp, short flg);
+/* must be called with ipcp locked */
+int ipcperms(struct kern_ipc_perm *ipcp, short flg);
/* for rare, potentially huge allocations.
* both function can sleep
@@ -79,24 +109,12 @@ void* ipc_rcu_alloc(int size);
void ipc_rcu_getref(void *ptr);
void ipc_rcu_putref(void *ptr);
-static inline void __ipc_fini_ids(struct ipc_ids *ids,
- struct ipc_id_ary *entries)
-{
- if (entries != &ids->nullentry)
- ipc_rcu_putref(entries);
-}
-
-static inline void ipc_fini_ids(struct ipc_ids *ids)
-{
- __ipc_fini_ids(ids, ids->entries);
-}
-
-struct kern_ipc_perm* ipc_get(struct ipc_ids* ids, int id);
-struct kern_ipc_perm* ipc_lock(struct ipc_ids* ids, int id);
-void ipc_lock_by_ptr(struct kern_ipc_perm *ipcp);
-void ipc_unlock(struct kern_ipc_perm* perm);
-int ipc_buildid(struct ipc_ids* ids, int id, int seq);
-int ipc_checkid(struct ipc_ids* ids, struct kern_ipc_perm* ipcp, int uid);
+/*
+ * ipc_lock_down: called with rw_mutex held
+ * ipc_lock: called without that lock held
+ */
+struct kern_ipc_perm *ipc_lock_down(struct ipc_ids *, int);
+struct kern_ipc_perm *ipc_lock(struct ipc_ids *, int);
void kernel_to_ipc64_perm(struct kern_ipc_perm *in, struct ipc64_perm *out);
void ipc64_perm_to_ipc_perm(struct ipc64_perm *in, struct ipc_perm *out);
@@ -111,5 +129,89 @@ int ipc_parse_version (int *cmd);
extern void free_msg(struct msg_msg *msg);
extern struct msg_msg *load_msg(const void __user *src, int len);
extern int store_msg(void __user *dest, struct msg_msg *msg, int len);
+extern int ipcget_new(struct ipc_namespace *, struct ipc_ids *,
+ struct ipc_ops *, struct ipc_params *);
+extern int ipcget_public(struct ipc_namespace *, struct ipc_ids *,
+ struct ipc_ops *, struct ipc_params *);
+
+static inline int ipc_buildid(int id, int seq)
+{
+ return SEQ_MULTIPLIER * seq + id;
+}
+
+/*
+ * Must be called with ipcp locked
+ */
+static inline int ipc_checkid(struct kern_ipc_perm *ipcp, int uid)
+{
+ if (uid / SEQ_MULTIPLIER != ipcp->seq)
+ return 1;
+ return 0;
+}
+
+static inline void ipc_lock_by_ptr(struct kern_ipc_perm *perm)
+{
+ rcu_read_lock();
+ spin_lock(&perm->lock);
+}
+
+static inline void ipc_unlock(struct kern_ipc_perm *perm)
+{
+ spin_unlock(&perm->lock);
+ rcu_read_unlock();
+}
+
+static inline struct kern_ipc_perm *ipc_lock_check_down(struct ipc_ids *ids,
+ int id)
+{
+ struct kern_ipc_perm *out;
+
+ out = ipc_lock_down(ids, id);
+ if (IS_ERR(out))
+ return out;
+
+ if (ipc_checkid(out, id)) {
+ ipc_unlock(out);
+ return ERR_PTR(-EIDRM);
+ }
+
+ return out;
+}
+
+static inline struct kern_ipc_perm *ipc_lock_check(struct ipc_ids *ids,
+ int id)
+{
+ struct kern_ipc_perm *out;
+
+ out = ipc_lock(ids, id);
+ if (IS_ERR(out))
+ return out;
+
+ if (ipc_checkid(out, id)) {
+ ipc_unlock(out);
+ return ERR_PTR(-EIDRM);
+ }
+
+ return out;
+}
+
+/**
+ * ipcget - Common sys_*get() code
+ * @ns : namsepace
+ * @ids : IPC identifier set
+ * @ops : operations to be called on ipc object creation, permission checks
+ * and further checks
+ * @params : the parameters needed by the previous operations.
+ *
+ * Common routine called by sys_msgget(), sys_semget() and sys_shmget().
+ */
+static inline int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids,
+ struct ipc_ops *ops, struct ipc_params *params)
+{
+ if (params->key == IPC_PRIVATE)
+ return ipcget_new(ns, ids, ops, params);
+ else
+ return ipcget_public(ns, ids, ops, params);
+}
#endif
diff --git a/kernel/Kconfig.instrumentation b/kernel/Kconfig.instrumentation
new file mode 100644
index 000000000000..f5f2c769d95e
--- /dev/null
+++ b/kernel/Kconfig.instrumentation
@@ -0,0 +1,49 @@
+menuconfig INSTRUMENTATION
+ bool "Instrumentation Support"
+ default y
+ ---help---
+ Say Y here to get to see options related to performance measurement,
+ system-wide debugging, and testing. This option alone does not add any
+ kernel code.
+
+ If you say N, all options in this submenu will be skipped and
+ disabled. If you're trying to debug the kernel itself, go see the
+ Kernel Hacking menu.
+
+if INSTRUMENTATION
+
+config PROFILING
+ bool "Profiling support (EXPERIMENTAL)"
+ help
+ Say Y here to enable the extended profiling support mechanisms used
+ by profilers such as OProfile.
+
+config OPROFILE
+ tristate "OProfile system profiling (EXPERIMENTAL)"
+ depends on PROFILING
+ depends on ALPHA || ARM || BLACKFIN || X86_32 || IA64 || M32R || MIPS || PARISC || PPC || S390 || SUPERH || SPARC || X86_64
+ help
+ OProfile is a profiling system capable of profiling the
+ whole system, include the kernel, kernel modules, libraries,
+ and applications.
+
+ If unsure, say N.
+
+config KPROBES
+ bool "Kprobes"
+ depends on KALLSYMS && MODULES
+ depends on X86_32 || IA64 || PPC || S390 || SPARC64 || X86_64 || AVR32
+ help
+ Kprobes allows you to trap at almost any kernel address and
+ execute a callback function. register_kprobe() establishes
+ a probepoint and specifies the callback. Kprobes is useful
+ for kernel debugging, non-intrusive instrumentation and testing.
+ If in doubt, say "N".
+
+config MARKERS
+ bool "Activate markers"
+ help
+ Place an empty function call at each marker site. Can be
+ dynamically changed for a probe function.
+
+endif # INSTRUMENTATION
diff --git a/kernel/Kconfig.preempt b/kernel/Kconfig.preempt
index 6b066632e40c..c64ce9c14207 100644
--- a/kernel/Kconfig.preempt
+++ b/kernel/Kconfig.preempt
@@ -63,6 +63,3 @@ config PREEMPT_BKL
Say Y here if you are building a kernel for a desktop system.
Say N if you are unsure.
-config PREEMPT_NOTIFIERS
- bool
-
diff --git a/kernel/Makefile b/kernel/Makefile
index 2a999836ca18..dfa96956dae0 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -8,9 +8,10 @@ obj-y = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
signal.o sys.o kmod.o workqueue.o pid.o \
rcupdate.o extable.o params.o posix-timers.o \
kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
- hrtimer.o rwsem.o latency.o nsproxy.o srcu.o die_notifier.o \
- utsname.o
+ hrtimer.o rwsem.o latency.o nsproxy.o srcu.o \
+ utsname.o notifier.o
+obj-$(CONFIG_SYSCTL) += sysctl_check.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-y += time/
obj-$(CONFIG_DEBUG_MUTEXES) += mutex-debug.o
@@ -36,11 +37,15 @@ obj-$(CONFIG_PM) += power/
obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
obj-$(CONFIG_KEXEC) += kexec.o
obj-$(CONFIG_COMPAT) += compat.o
+obj-$(CONFIG_CGROUPS) += cgroup.o
+obj-$(CONFIG_CGROUP_DEBUG) += cgroup_debug.o
obj-$(CONFIG_CPUSETS) += cpuset.o
+obj-$(CONFIG_CGROUP_NS) += ns_cgroup.o
obj-$(CONFIG_IKCONFIG) += configs.o
obj-$(CONFIG_STOP_MACHINE) += stop_machine.o
obj-$(CONFIG_AUDIT) += audit.o auditfilter.o
obj-$(CONFIG_AUDITSYSCALL) += auditsc.o
+obj-$(CONFIG_AUDIT_TREE) += audit_tree.o
obj-$(CONFIG_KPROBES) += kprobes.o
obj-$(CONFIG_SYSFS) += ksysfs.o
obj-$(CONFIG_DETECT_SOFTLOCKUP) += softlockup.o
@@ -51,6 +56,7 @@ obj-$(CONFIG_RELAY) += relay.o
obj-$(CONFIG_SYSCTL) += utsname_sysctl.o
obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o
obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o
+obj-$(CONFIG_MARKERS) += marker.o
ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y)
# According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
diff --git a/kernel/acct.c b/kernel/acct.c
index 24f0f8b2ba72..fce53d8df8a7 100644
--- a/kernel/acct.c
+++ b/kernel/acct.c
@@ -329,16 +329,16 @@ static comp_t encode_comp_t(unsigned long value)
}
/*
- * If we need to round up, do it (and handle overflow correctly).
- */
+ * If we need to round up, do it (and handle overflow correctly).
+ */
if (rnd && (++value > MAXFRACT)) {
value >>= EXPSIZE;
exp++;
}
/*
- * Clean it up and polish it off.
- */
+ * Clean it up and polish it off.
+ */
exp <<= MANTSIZE; /* Shift the exponent into place */
exp += value; /* and add on the mantissa. */
return exp;
@@ -361,30 +361,30 @@ static comp_t encode_comp_t(unsigned long value)
static comp2_t encode_comp2_t(u64 value)
{
- int exp, rnd;
-
- exp = (value > (MAXFRACT2>>1));
- rnd = 0;
- while (value > MAXFRACT2) {
- rnd = value & 1;
- value >>= 1;
- exp++;
- }
-
- /*
- * If we need to round up, do it (and handle overflow correctly).
- */
- if (rnd && (++value > MAXFRACT2)) {
- value >>= 1;
- exp++;
- }
-
- if (exp > MAXEXP2) {
- /* Overflow. Return largest representable number instead. */
- return (1ul << (MANTSIZE2+EXPSIZE2-1)) - 1;
- } else {
- return (value & (MAXFRACT2>>1)) | (exp << (MANTSIZE2-1));
- }
+ int exp, rnd;
+
+ exp = (value > (MAXFRACT2>>1));
+ rnd = 0;
+ while (value > MAXFRACT2) {
+ rnd = value & 1;
+ value >>= 1;
+ exp++;
+ }
+
+ /*
+ * If we need to round up, do it (and handle overflow correctly).
+ */
+ if (rnd && (++value > MAXFRACT2)) {
+ value >>= 1;
+ exp++;
+ }
+
+ if (exp > MAXEXP2) {
+ /* Overflow. Return largest representable number instead. */
+ return (1ul << (MANTSIZE2+EXPSIZE2-1)) - 1;
+ } else {
+ return (value & (MAXFRACT2>>1)) | (exp << (MANTSIZE2-1));
+ }
}
#endif
@@ -501,14 +501,14 @@ static void do_acct_process(struct file *file)
ac.ac_swaps = encode_comp_t(0);
/*
- * Kernel segment override to datasegment and write it
- * to the accounting file.
- */
+ * Kernel segment override to datasegment and write it
+ * to the accounting file.
+ */
fs = get_fs();
set_fs(KERNEL_DS);
/*
- * Accounting records are not subject to resource limits.
- */
+ * Accounting records are not subject to resource limits.
+ */
flim = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
current->signal->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
file->f_op->write(file, (char *)&ac,
diff --git a/kernel/audit.c b/kernel/audit.c
index 2924251a6547..f93c2713017d 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -468,6 +468,21 @@ int audit_send_list(void *_dest)
return 0;
}
+#ifdef CONFIG_AUDIT_TREE
+static int prune_tree_thread(void *unused)
+{
+ mutex_lock(&audit_cmd_mutex);
+ audit_prune_trees();
+ mutex_unlock(&audit_cmd_mutex);
+ return 0;
+}
+
+void audit_schedule_prune(void)
+{
+ kthread_run(prune_tree_thread, NULL, "audit_prune_tree");
+}
+#endif
+
struct sk_buff *audit_make_reply(int pid, int seq, int type, int done,
int multi, void *payload, int size)
{
@@ -540,6 +555,8 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)
case AUDIT_SIGNAL_INFO:
case AUDIT_TTY_GET:
case AUDIT_TTY_SET:
+ case AUDIT_TRIM:
+ case AUDIT_MAKE_EQUIV:
if (security_netlink_recv(skb, CAP_AUDIT_CONTROL))
err = -EPERM;
break;
@@ -664,11 +681,11 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
if (sid) {
if (selinux_sid_to_string(
sid, &ctx, &len)) {
- audit_log_format(ab,
+ audit_log_format(ab,
" ssid=%u", sid);
/* Maybe call audit_panic? */
} else
- audit_log_format(ab,
+ audit_log_format(ab,
" subj=%s", ctx);
kfree(ctx);
}
@@ -756,6 +773,76 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
uid, seq, data, nlmsg_len(nlh),
loginuid, sid);
break;
+ case AUDIT_TRIM:
+ audit_trim_trees();
+ ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
+ if (!ab)
+ break;
+ audit_log_format(ab, "auid=%u", loginuid);
+ if (sid) {
+ u32 len;
+ ctx = NULL;
+ if (selinux_sid_to_string(sid, &ctx, &len))
+ audit_log_format(ab, " ssid=%u", sid);
+ else
+ audit_log_format(ab, " subj=%s", ctx);
+ kfree(ctx);
+ }
+ audit_log_format(ab, " op=trim res=1");
+ audit_log_end(ab);
+ break;
+ case AUDIT_MAKE_EQUIV: {
+ void *bufp = data;
+ u32 sizes[2];
+ size_t len = nlmsg_len(nlh);
+ char *old, *new;
+
+ err = -EINVAL;
+ if (len < 2 * sizeof(u32))
+ break;
+ memcpy(sizes, bufp, 2 * sizeof(u32));
+ bufp += 2 * sizeof(u32);
+ len -= 2 * sizeof(u32);
+ old = audit_unpack_string(&bufp, &len, sizes[0]);
+ if (IS_ERR(old)) {
+ err = PTR_ERR(old);
+ break;
+ }
+ new = audit_unpack_string(&bufp, &len, sizes[1]);
+ if (IS_ERR(new)) {
+ err = PTR_ERR(new);
+ kfree(old);
+ break;
+ }
+ /* OK, here comes... */
+ err = audit_tag_tree(old, new);
+
+ ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
+ if (!ab) {
+ kfree(old);
+ kfree(new);
+ break;
+ }
+ audit_log_format(ab, "auid=%u", loginuid);
+ if (sid) {
+ u32 len;
+ ctx = NULL;
+ if (selinux_sid_to_string(sid, &ctx, &len))
+ audit_log_format(ab, " ssid=%u", sid);
+ else
+ audit_log_format(ab, " subj=%s", ctx);
+ kfree(ctx);
+ }
+ audit_log_format(ab, " op=make_equiv old=");
+ audit_log_untrustedstring(ab, old);
+ audit_log_format(ab, " new=");
+ audit_log_untrustedstring(ab, new);
+ audit_log_format(ab, " res=%d", !err);
+ audit_log_end(ab);
+ kfree(old);
+ kfree(new);
+ break;
+ }
case AUDIT_SIGNAL_INFO:
err = selinux_sid_to_string(audit_sig_sid, &ctx, &len);
if (err)
@@ -769,7 +856,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
sig_data->pid = audit_sig_pid;
memcpy(sig_data->ctx, ctx, len);
kfree(ctx);
- audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_SIGNAL_INFO,
+ audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_SIGNAL_INFO,
0, 0, sig_data, sizeof(*sig_data) + len);
kfree(sig_data);
break;
@@ -1005,7 +1092,7 @@ unsigned int audit_serial(void)
return ret;
}
-static inline void audit_get_stamp(struct audit_context *ctx,
+static inline void audit_get_stamp(struct audit_context *ctx,
struct timespec *t, unsigned int *serial)
{
if (ctx)
@@ -1056,7 +1143,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
if (gfp_mask & __GFP_WAIT)
reserve = 0;
else
- reserve = 5; /* Allow atomic callers to go up to five
+ reserve = 5; /* Allow atomic callers to go up to five
entries over the normal backlog limit */
while (audit_backlog_limit
@@ -1319,7 +1406,7 @@ void audit_log_d_path(struct audit_buffer *ab, const char *prefix,
if (IS_ERR(p)) { /* Should never happen since we send PATH_MAX */
/* FIXME: can we save some information here? */
audit_log_format(ab, "<too long>");
- } else
+ } else
audit_log_untrustedstring(ab, p);
kfree(path);
}
@@ -1365,7 +1452,7 @@ void audit_log_end(struct audit_buffer *ab)
* audit_log_vformat, and audit_log_end. It may be called
* in any context.
*/
-void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
+void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
const char *fmt, ...)
{
struct audit_buffer *ab;
diff --git a/kernel/audit.h b/kernel/audit.h
index 95877435c347..2554bd524fd1 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -73,6 +73,9 @@ struct audit_field {
struct selinux_audit_rule *se_rule;
};
+struct audit_tree;
+struct audit_chunk;
+
struct audit_krule {
int vers_ops;
u32 flags;
@@ -86,7 +89,8 @@ struct audit_krule {
struct audit_field *arch_f; /* quick access to arch field */
struct audit_field *inode_f; /* quick access to an inode field */
struct audit_watch *watch; /* associated watch */
- struct list_head rlist; /* entry in audit_watch.rules list */
+ struct audit_tree *tree; /* associated watched tree */
+ struct list_head rlist; /* entry in audit_{watch,tree}.rules list */
};
struct audit_entry {
@@ -130,6 +134,34 @@ extern void audit_handle_ievent(struct inotify_watch *, u32, u32, u32,
const char *, struct inode *);
extern int selinux_audit_rule_update(void);
+extern struct mutex audit_filter_mutex;
+extern void audit_free_rule_rcu(struct rcu_head *);
+
+#ifdef CONFIG_AUDIT_TREE
+extern struct audit_chunk *audit_tree_lookup(const struct inode *);
+extern void audit_put_chunk(struct audit_chunk *);
+extern int audit_tree_match(struct audit_chunk *, struct audit_tree *);
+extern int audit_make_tree(struct audit_krule *, char *, u32);
+extern int audit_add_tree_rule(struct audit_krule *);
+extern int audit_remove_tree_rule(struct audit_krule *);
+extern void audit_trim_trees(void);
+extern int audit_tag_tree(char *old, char *new);
+extern void audit_schedule_prune(void);
+extern void audit_prune_trees(void);
+extern const char *audit_tree_path(struct audit_tree *);
+extern void audit_put_tree(struct audit_tree *);
+#else
+#define audit_remove_tree_rule(rule) BUG()
+#define audit_add_tree_rule(rule) -EINVAL
+#define audit_make_tree(rule, str, op) -EINVAL
+#define audit_trim_trees() (void)0
+#define audit_put_tree(tree) (void)0
+#define audit_tag_tree(old, new) -EINVAL
+#define audit_tree_path(rule) "" /* never called */
+#endif
+
+extern char *audit_unpack_string(void **, size_t *, size_t);
+
#ifdef CONFIG_AUDITSYSCALL
extern int __audit_signal_info(int sig, struct task_struct *t);
static inline int audit_signal_info(int sig, struct task_struct *t)
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c
new file mode 100644
index 000000000000..f4fcf58f20f8
--- /dev/null
+++ b/kernel/audit_tree.c
@@ -0,0 +1,903 @@
+#include "audit.h"
+#include <linux/inotify.h>
+#include <linux/namei.h>
+#include <linux/mount.h>
+
+struct audit_tree;
+struct audit_chunk;
+
+struct audit_tree {
+ atomic_t count;
+ int goner;
+ struct audit_chunk *root;
+ struct list_head chunks;
+ struct list_head rules;
+ struct list_head list;
+ struct list_head same_root;
+ struct rcu_head head;
+ char pathname[];
+};
+
+struct audit_chunk {
+ struct list_head hash;
+ struct inotify_watch watch;
+ struct list_head trees; /* with root here */
+ int dead;
+ int count;
+ struct rcu_head head;
+ struct node {
+ struct list_head list;
+ struct audit_tree *owner;
+ unsigned index; /* index; upper bit indicates 'will prune' */
+ } owners[];
+};
+
+static LIST_HEAD(tree_list);
+static LIST_HEAD(prune_list);
+
+/*
+ * One struct chunk is attached to each inode of interest.
+ * We replace struct chunk on tagging/untagging.
+ * Rules have pointer to struct audit_tree.
+ * Rules have struct list_head rlist forming a list of rules over
+ * the same tree.
+ * References to struct chunk are collected at audit_inode{,_child}()
+ * time and used in AUDIT_TREE rule matching.
+ * These references are dropped at the same time we are calling
+ * audit_free_names(), etc.
+ *
+ * Cyclic lists galore:
+ * tree.chunks anchors chunk.owners[].list hash_lock
+ * tree.rules anchors rule.rlist audit_filter_mutex
+ * chunk.trees anchors tree.same_root hash_lock
+ * chunk.hash is a hash with middle bits of watch.inode as
+ * a hash function. RCU, hash_lock
+ *
+ * tree is refcounted; one reference for "some rules on rules_list refer to
+ * it", one for each chunk with pointer to it.
+ *
+ * chunk is refcounted by embedded inotify_watch.
+ *
+ * node.index allows to get from node.list to containing chunk.
+ * MSB of that sucker is stolen to mark taggings that we might have to
+ * revert - several operations have very unpleasant cleanup logics and
+ * that makes a difference. Some.
+ */
+
+static struct inotify_handle *rtree_ih;
+
+static struct audit_tree *alloc_tree(const char *s)
+{
+ struct audit_tree *tree;
+
+ tree = kmalloc(sizeof(struct audit_tree) + strlen(s) + 1, GFP_KERNEL);
+ if (tree) {
+ atomic_set(&tree->count, 1);
+ tree->goner = 0;
+ INIT_LIST_HEAD(&tree->chunks);
+ INIT_LIST_HEAD(&tree->rules);
+ INIT_LIST_HEAD(&tree->list);
+ INIT_LIST_HEAD(&tree->same_root);
+ tree->root = NULL;
+ strcpy(tree->pathname, s);
+ }
+ return tree;
+}
+
+static inline void get_tree(struct audit_tree *tree)
+{
+ atomic_inc(&tree->count);
+}
+
+static void __put_tree(struct rcu_head *rcu)
+{
+ struct audit_tree *tree = container_of(rcu, struct audit_tree, head);
+ kfree(tree);
+}
+
+static inline void put_tree(struct audit_tree *tree)
+{
+ if (atomic_dec_and_test(&tree->count))
+ call_rcu(&tree->head, __put_tree);
+}
+
+/* to avoid bringing the entire thing in audit.h */
+const char *audit_tree_path(struct audit_tree *tree)
+{
+ return tree->pathname;
+}
+
+static struct audit_chunk *alloc_chunk(int count)
+{
+ struct audit_chunk *chunk;
+ size_t size;
+ int i;
+
+ size = offsetof(struct audit_chunk, owners) + count * sizeof(struct node);
+ chunk = kzalloc(size, GFP_KERNEL);
+ if (!chunk)
+ return NULL;
+
+ INIT_LIST_HEAD(&chunk->hash);
+ INIT_LIST_HEAD(&chunk->trees);
+ chunk->count = count;
+ for (i = 0; i < count; i++) {
+ INIT_LIST_HEAD(&chunk->owners[i].list);
+ chunk->owners[i].index = i;
+ }
+ inotify_init_watch(&chunk->watch);
+ return chunk;
+}
+
+static void __free_chunk(struct rcu_head *rcu)
+{
+ struct audit_chunk *chunk = container_of(rcu, struct audit_chunk, head);
+ int i;
+
+ for (i = 0; i < chunk->count; i++) {
+ if (chunk->owners[i].owner)
+ put_tree(chunk->owners[i].owner);
+ }
+ kfree(chunk);
+}
+
+static inline void free_chunk(struct audit_chunk *chunk)
+{
+ call_rcu(&chunk->head, __free_chunk);
+}
+
+void audit_put_chunk(struct audit_chunk *chunk)
+{
+ put_inotify_watch(&chunk->watch);
+}
+
+enum {HASH_SIZE = 128};
+static struct list_head chunk_hash_heads[HASH_SIZE];
+static __cacheline_aligned_in_smp DEFINE_SPINLOCK(hash_lock);
+
+static inline struct list_head *chunk_hash(const struct inode *inode)
+{
+ unsigned long n = (unsigned long)inode / L1_CACHE_BYTES;
+ return chunk_hash_heads + n % HASH_SIZE;
+}
+
+/* hash_lock is held by caller */
+static void insert_hash(struct audit_chunk *chunk)
+{
+ struct list_head *list = chunk_hash(chunk->watch.inode);
+ list_add_rcu(&chunk->hash, list);
+}
+
+/* called under rcu_read_lock */
+struct audit_chunk *audit_tree_lookup(const struct inode *inode)
+{
+ struct list_head *list = chunk_hash(inode);
+ struct list_head *pos;
+
+ list_for_each_rcu(pos, list) {
+ struct audit_chunk *p = container_of(pos, struct audit_chunk, hash);
+ if (p->watch.inode == inode) {
+ get_inotify_watch(&p->watch);
+ return p;
+ }
+ }
+ return NULL;
+}
+
+int audit_tree_match(struct audit_chunk *chunk, struct audit_tree *tree)
+{
+ int n;
+ for (n = 0; n < chunk->count; n++)
+ if (chunk->owners[n].owner == tree)
+ return 1;
+ return 0;
+}
+
+/* tagging and untagging inodes with trees */
+
+static void untag_chunk(struct audit_chunk *chunk, struct node *p)
+{
+ struct audit_chunk *new;
+ struct audit_tree *owner;
+ int size = chunk->count - 1;
+ int i, j;
+
+ mutex_lock(&chunk->watch.inode->inotify_mutex);
+ if (chunk->dead) {
+ mutex_unlock(&chunk->watch.inode->inotify_mutex);
+ return;
+ }
+
+ owner = p->owner;
+
+ if (!size) {
+ chunk->dead = 1;
+ spin_lock(&hash_lock);
+ list_del_init(&chunk->trees);
+ if (owner->root == chunk)
+ owner->root = NULL;
+ list_del_init(&p->list);
+ list_del_rcu(&chunk->hash);
+ spin_unlock(&hash_lock);
+ inotify_evict_watch(&chunk->watch);
+ mutex_unlock(&chunk->watch.inode->inotify_mutex);
+ put_inotify_watch(&chunk->watch);
+ return;
+ }
+
+ new = alloc_chunk(size);
+ if (!new)
+ goto Fallback;
+ if (inotify_clone_watch(&chunk->watch, &new->watch) < 0) {
+ free_chunk(new);
+ goto Fallback;
+ }
+
+ chunk->dead = 1;
+ spin_lock(&hash_lock);
+ list_replace_init(&chunk->trees, &new->trees);
+ if (owner->root == chunk) {
+ list_del_init(&owner->same_root);
+ owner->root = NULL;
+ }
+
+ for (i = j = 0; i < size; i++, j++) {
+ struct audit_tree *s;
+ if (&chunk->owners[j] == p) {
+ list_del_init(&p->list);
+ i--;
+ continue;
+ }
+ s = chunk->owners[j].owner;
+ new->owners[i].owner = s;
+ new->owners[i].index = chunk->owners[j].index - j + i;
+ if (!s) /* result of earlier fallback */
+ continue;
+ get_tree(s);
+ list_replace_init(&chunk->owners[i].list, &new->owners[j].list);
+ }
+
+ list_replace_rcu(&chunk->hash, &new->hash);
+ list_for_each_entry(owner, &new->trees, same_root)
+ owner->root = new;
+ spin_unlock(&hash_lock);
+ inotify_evict_watch(&chunk->watch);
+ mutex_unlock(&chunk->watch.inode->inotify_mutex);
+ put_inotify_watch(&chunk->watch);
+ return;
+
+Fallback:
+ // do the best we can
+ spin_lock(&hash_lock);
+ if (owner->root == chunk) {
+ list_del_init(&owner->same_root);
+ owner->root = NULL;
+ }
+ list_del_init(&p->list);
+ p->owner = NULL;
+ put_tree(owner);
+ spin_unlock(&hash_lock);
+ mutex_unlock(&chunk->watch.inode->inotify_mutex);
+}
+
+static int create_chunk(struct inode *inode, struct audit_tree *tree)
+{
+ struct audit_chunk *chunk = alloc_chunk(1);
+ if (!chunk)
+ return -ENOMEM;
+
+ if (inotify_add_watch(rtree_ih, &chunk->watch, inode, IN_IGNORED | IN_DELETE_SELF) < 0) {
+ free_chunk(chunk);
+ return -ENOSPC;
+ }
+
+ mutex_lock(&inode->inotify_mutex);
+ spin_lock(&hash_lock);
+ if (tree->goner) {
+ spin_unlock(&hash_lock);
+ chunk->dead = 1;
+ inotify_evict_watch(&chunk->watch);
+ mutex_unlock(&inode->inotify_mutex);
+ put_inotify_watch(&chunk->watch);
+ return 0;
+ }
+ chunk->owners[0].index = (1U << 31);
+ chunk->owners[0].owner = tree;
+ get_tree(tree);
+ list_add(&chunk->owners[0].list, &tree->chunks);
+ if (!tree->root) {
+ tree->root = chunk;
+ list_add(&tree->same_root, &chunk->trees);
+ }
+ insert_hash(chunk);
+ spin_unlock(&hash_lock);
+ mutex_unlock(&inode->inotify_mutex);
+ return 0;
+}
+
+/* the first tagged inode becomes root of tree */
+static int tag_chunk(struct inode *inode, struct audit_tree *tree)
+{
+ struct inotify_watch *watch;
+ struct audit_tree *owner;
+ struct audit_chunk *chunk, *old;
+ struct node *p;
+ int n;
+
+ if (inotify_find_watch(rtree_ih, inode, &watch) < 0)
+ return create_chunk(inode, tree);
+
+ old = container_of(watch, struct audit_chunk, watch);
+
+ /* are we already there? */
+ spin_lock(&hash_lock);
+ for (n = 0; n < old->count; n++) {
+ if (old->owners[n].owner == tree) {
+ spin_unlock(&hash_lock);
+ put_inotify_watch(watch);
+ return 0;
+ }
+ }
+ spin_unlock(&hash_lock);
+
+ chunk = alloc_chunk(old->count + 1);
+ if (!chunk)
+ return -ENOMEM;
+
+ mutex_lock(&inode->inotify_mutex);
+ if (inotify_clone_watch(&old->watch, &chunk->watch) < 0) {
+ mutex_unlock(&inode->inotify_mutex);
+ free_chunk(chunk);
+ return -ENOSPC;
+ }
+ spin_lock(&hash_lock);
+ if (tree->goner) {
+ spin_unlock(&hash_lock);
+ chunk->dead = 1;
+ inotify_evict_watch(&chunk->watch);
+ mutex_unlock(&inode->inotify_mutex);
+ put_inotify_watch(&chunk->watch);
+ return 0;
+ }
+ list_replace_init(&old->trees, &chunk->trees);
+ for (n = 0, p = chunk->owners; n < old->count; n++, p++) {
+ struct audit_tree *s = old->owners[n].owner;
+ p->owner = s;
+ p->index = old->owners[n].index;
+ if (!s) /* result of fallback in untag */
+ continue;
+ get_tree(s);
+ list_replace_init(&old->owners[n].list, &p->list);
+ }
+ p->index = (chunk->count - 1) | (1U<<31);
+ p->owner = tree;
+ get_tree(tree);
+ list_add(&p->list, &tree->chunks);
+ list_replace_rcu(&old->hash, &chunk->hash);
+ list_for_each_entry(owner, &chunk->trees, same_root)
+ owner->root = chunk;
+ old->dead = 1;
+ if (!tree->root) {
+ tree->root = chunk;
+ list_add(&tree->same_root, &chunk->trees);
+ }
+ spin_unlock(&hash_lock);
+ inotify_evict_watch(&old->watch);
+ mutex_unlock(&inode->inotify_mutex);
+ put_inotify_watch(&old->watch);
+ return 0;
+}
+
+static struct audit_chunk *find_chunk(struct node *p)
+{
+ int index = p->index & ~(1U<<31);
+ p -= index;
+ return container_of(p, struct audit_chunk, owners[0]);
+}
+
+static void kill_rules(struct audit_tree *tree)
+{
+ struct audit_krule *rule, *next;
+ struct audit_entry *entry;
+ struct audit_buffer *ab;
+
+ list_for_each_entry_safe(rule, next, &tree->rules, rlist) {
+ entry = container_of(rule, struct audit_entry, rule);
+
+ list_del_init(&rule->rlist);
+ if (rule->tree) {
+ /* not a half-baked one */
+ ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
+ audit_log_format(ab, "op=remove rule dir=");
+ audit_log_untrustedstring(ab, rule->tree->pathname);
+ if (rule->filterkey) {
+ audit_log_format(ab, " key=");
+ audit_log_untrustedstring(ab, rule->filterkey);
+ } else
+ audit_log_format(ab, " key=(null)");
+ audit_log_format(ab, " list=%d res=1", rule->listnr);
+ audit_log_end(ab);
+ rule->tree = NULL;
+ list_del_rcu(&entry->list);
+ call_rcu(&entry->rcu, audit_free_rule_rcu);
+ }
+ }
+}
+
+/*
+ * finish killing struct audit_tree
+ */
+static void prune_one(struct audit_tree *victim)
+{
+ spin_lock(&hash_lock);
+ while (!list_empty(&victim->chunks)) {
+ struct node *p;
+ struct audit_chunk *chunk;
+
+ p = list_entry(victim->chunks.next, struct node, list);
+ chunk = find_chunk(p);
+ get_inotify_watch(&chunk->watch);
+ spin_unlock(&hash_lock);
+
+ untag_chunk(chunk, p);
+
+ put_inotify_watch(&chunk->watch);
+ spin_lock(&hash_lock);
+ }
+ spin_unlock(&hash_lock);
+ put_tree(victim);
+}
+
+/* trim the uncommitted chunks from tree */
+
+static void trim_marked(struct audit_tree *tree)
+{
+ struct list_head *p, *q;
+ spin_lock(&hash_lock);
+ if (tree->goner) {
+ spin_unlock(&hash_lock);
+ return;
+ }
+ /* reorder */
+ for (p = tree->chunks.next; p != &tree->chunks; p = q) {
+ struct node *node = list_entry(p, struct node, list);
+ q = p->next;
+ if (node->index & (1U<<31)) {
+ list_del_init(p);
+ list_add(p, &tree->chunks);
+ }
+ }
+
+ while (!list_empty(&tree->chunks)) {
+ struct node *node;
+ struct audit_chunk *chunk;
+
+ node = list_entry(tree->chunks.next, struct node, list);
+
+ /* have we run out of marked? */
+ if (!(node->index & (1U<<31)))
+ break;
+
+ chunk = find_chunk(node);
+ get_inotify_watch(&chunk->watch);
+ spin_unlock(&hash_lock);
+
+ untag_chunk(chunk, node);
+
+ put_inotify_watch(&chunk->watch);
+ spin_lock(&hash_lock);
+ }
+ if (!tree->root && !tree->goner) {
+ tree->goner = 1;
+ spin_unlock(&hash_lock);
+ mutex_lock(&audit_filter_mutex);
+ kill_rules(tree);
+ list_del_init(&tree->list);
+ mutex_unlock(&audit_filter_mutex);
+ prune_one(tree);
+ } else {
+ spin_unlock(&hash_lock);
+ }
+}
+
+/* called with audit_filter_mutex */
+int audit_remove_tree_rule(struct audit_krule *rule)
+{
+ struct audit_tree *tree;
+ tree = rule->tree;
+ if (tree) {
+ spin_lock(&hash_lock);
+ list_del_init(&rule->rlist);
+ if (list_empty(&tree->rules) && !tree->goner) {
+ tree->root = NULL;
+ list_del_init(&tree->same_root);
+ tree->goner = 1;
+ list_move(&tree->list, &prune_list);
+ rule->tree = NULL;
+ spin_unlock(&hash_lock);
+ audit_schedule_prune();
+ return 1;
+ }
+ rule->tree = NULL;
+ spin_unlock(&hash_lock);
+ return 1;
+ }
+ return 0;
+}
+
+void audit_trim_trees(void)
+{
+ struct list_head cursor;
+
+ mutex_lock(&audit_filter_mutex);
+ list_add(&cursor, &tree_list);
+ while (cursor.next != &tree_list) {
+ struct audit_tree *tree;
+ struct nameidata nd;
+ struct vfsmount *root_mnt;
+ struct node *node;
+ struct list_head list;
+ int err;
+
+ tree = container_of(cursor.next, struct audit_tree, list);
+ get_tree(tree);
+ list_del(&cursor);
+ list_add(&cursor, &tree->list);
+ mutex_unlock(&audit_filter_mutex);
+
+ err = path_lookup(tree->pathname, 0, &nd);
+ if (err)
+ goto skip_it;
+
+ root_mnt = collect_mounts(nd.mnt, nd.dentry);
+ path_release(&nd);
+ if (!root_mnt)
+ goto skip_it;
+
+ list_add_tail(&list, &root_mnt->mnt_list);
+ spin_lock(&hash_lock);
+ list_for_each_entry(node, &tree->chunks, list) {
+ struct audit_chunk *chunk = find_chunk(node);
+ struct inode *inode = chunk->watch.inode;
+ struct vfsmount *mnt;
+ node->index |= 1U<<31;
+ list_for_each_entry(mnt, &list, mnt_list) {
+ if (mnt->mnt_root->d_inode == inode) {
+ node->index &= ~(1U<<31);
+ break;
+ }
+ }
+ }
+ spin_unlock(&hash_lock);
+ trim_marked(tree);
+ put_tree(tree);
+ list_del_init(&list);
+ drop_collected_mounts(root_mnt);
+skip_it:
+ mutex_lock(&audit_filter_mutex);
+ }
+ list_del(&cursor);
+ mutex_unlock(&audit_filter_mutex);
+}
+
+static int is_under(struct vfsmount *mnt, struct dentry *dentry,
+ struct nameidata *nd)
+{
+ if (mnt != nd->mnt) {
+ for (;;) {
+ if (mnt->mnt_parent == mnt)
+ return 0;
+ if (mnt->mnt_parent == nd->mnt)
+ break;
+ mnt = mnt->mnt_parent;
+ }
+ dentry = mnt->mnt_mountpoint;
+ }
+ return is_subdir(dentry, nd->dentry);
+}
+
+int audit_make_tree(struct audit_krule *rule, char *pathname, u32 op)
+{
+
+ if (pathname[0] != '/' ||
+ rule->listnr != AUDIT_FILTER_EXIT ||
+ op & ~AUDIT_EQUAL ||
+ rule->inode_f || rule->watch || rule->tree)
+ return -EINVAL;
+ rule->tree = alloc_tree(pathname);
+ if (!rule->tree)
+ return -ENOMEM;
+ return 0;
+}
+
+void audit_put_tree(struct audit_tree *tree)
+{
+ put_tree(tree);
+}
+
+/* called with audit_filter_mutex */
+int audit_add_tree_rule(struct audit_krule *rule)
+{
+ struct audit_tree *seed = rule->tree, *tree;
+ struct nameidata nd;
+ struct vfsmount *mnt, *p;
+ struct list_head list;
+ int err;
+
+ list_for_each_entry(tree, &tree_list, list) {
+ if (!strcmp(seed->pathname, tree->pathname)) {
+ put_tree(seed);
+ rule->tree = tree;
+ list_add(&rule->rlist, &tree->rules);
+ return 0;
+ }
+ }
+ tree = seed;
+ list_add(&tree->list, &tree_list);
+ list_add(&rule->rlist, &tree->rules);
+ /* do not set rule->tree yet */
+ mutex_unlock(&audit_filter_mutex);
+
+ err = path_lookup(tree->pathname, 0, &nd);
+ if (err)
+ goto Err;
+ mnt = collect_mounts(nd.mnt, nd.dentry);
+ path_release(&nd);
+ if (!mnt) {
+ err = -ENOMEM;
+ goto Err;
+ }
+ list_add_tail(&list, &mnt->mnt_list);
+
+ get_tree(tree);
+ list_for_each_entry(p, &list, mnt_list) {
+ err = tag_chunk(p->mnt_root->d_inode, tree);
+ if (err)
+ break;
+ }
+
+ list_del(&list);
+ drop_collected_mounts(mnt);
+
+ if (!err) {
+ struct node *node;
+ spin_lock(&hash_lock);
+ list_for_each_entry(node, &tree->chunks, list)
+ node->index &= ~(1U<<31);
+ spin_unlock(&hash_lock);
+ } else {
+ trim_marked(tree);
+ goto Err;
+ }
+
+ mutex_lock(&audit_filter_mutex);
+ if (list_empty(&rule->rlist)) {
+ put_tree(tree);
+ return -ENOENT;
+ }
+ rule->tree = tree;
+ put_tree(tree);
+
+ return 0;
+Err:
+ mutex_lock(&audit_filter_mutex);
+ list_del_init(&tree->list);
+ list_del_init(&tree->rules);
+ put_tree(tree);
+ return err;
+}
+
+int audit_tag_tree(char *old, char *new)
+{
+ struct list_head cursor, barrier;
+ int failed = 0;
+ struct nameidata nd;
+ struct vfsmount *tagged;
+ struct list_head list;
+ struct vfsmount *mnt;
+ struct dentry *dentry;
+ int err;
+
+ err = path_lookup(new, 0, &nd);
+ if (err)
+ return err;
+ tagged = collect_mounts(nd.mnt, nd.dentry);
+ path_release(&nd);
+ if (!tagged)
+ return -ENOMEM;
+
+ err = path_lookup(old, 0, &nd);
+ if (err) {
+ drop_collected_mounts(tagged);
+ return err;
+ }
+ mnt = mntget(nd.mnt);
+ dentry = dget(nd.dentry);
+ path_release(&nd);
+
+ if (dentry == tagged->mnt_root && dentry == mnt->mnt_root)
+ follow_up(&mnt, &dentry);
+
+ list_add_tail(&list, &tagged->mnt_list);
+
+ mutex_lock(&audit_filter_mutex);
+ list_add(&barrier, &tree_list);
+ list_add(&cursor, &barrier);
+
+ while (cursor.next != &tree_list) {
+ struct audit_tree *tree;
+ struct vfsmount *p;
+
+ tree = container_of(cursor.next, struct audit_tree, list);
+ get_tree(tree);
+ list_del(&cursor);
+ list_add(&cursor, &tree->list);
+ mutex_unlock(&audit_filter_mutex);
+
+ err = path_lookup(tree->pathname, 0, &nd);
+ if (err) {
+ put_tree(tree);
+ mutex_lock(&audit_filter_mutex);
+ continue;
+ }
+
+ spin_lock(&vfsmount_lock);
+ if (!is_under(mnt, dentry, &nd)) {
+ spin_unlock(&vfsmount_lock);
+ path_release(&nd);
+ put_tree(tree);
+ mutex_lock(&audit_filter_mutex);
+ continue;
+ }
+ spin_unlock(&vfsmount_lock);
+ path_release(&nd);
+
+ list_for_each_entry(p, &list, mnt_list) {
+ failed = tag_chunk(p->mnt_root->d_inode, tree);
+ if (failed)
+ break;
+ }
+
+ if (failed) {
+ put_tree(tree);
+ mutex_lock(&audit_filter_mutex);
+ break;
+ }
+
+ mutex_lock(&audit_filter_mutex);
+ spin_lock(&hash_lock);
+ if (!tree->goner) {
+ list_del(&tree->list);
+ list_add(&tree->list, &tree_list);
+ }
+ spin_unlock(&hash_lock);
+ put_tree(tree);
+ }
+
+ while (barrier.prev != &tree_list) {
+ struct audit_tree *tree;
+
+ tree = container_of(barrier.prev, struct audit_tree, list);
+ get_tree(tree);
+ list_del(&tree->list);
+ list_add(&tree->list, &barrier);
+ mutex_unlock(&audit_filter_mutex);
+
+ if (!failed) {
+ struct node *node;
+ spin_lock(&hash_lock);
+ list_for_each_entry(node, &tree->chunks, list)
+ node->index &= ~(1U<<31);
+ spin_unlock(&hash_lock);
+ } else {
+ trim_marked(tree);
+ }
+
+ put_tree(tree);
+ mutex_lock(&audit_filter_mutex);
+ }
+ list_del(&barrier);
+ list_del(&cursor);
+ list_del(&list);
+ mutex_unlock(&audit_filter_mutex);
+ dput(dentry);
+ mntput(mnt);
+ drop_collected_mounts(tagged);
+ return failed;
+}
+
+/*
+ * That gets run when evict_chunk() ends up needing to kill audit_tree.
+ * Runs from a separate thread, with audit_cmd_mutex held.
+ */
+void audit_prune_trees(void)
+{
+ mutex_lock(&audit_filter_mutex);
+
+ while (!list_empty(&prune_list)) {
+ struct audit_tree *victim;
+
+ victim = list_entry(prune_list.next, struct audit_tree, list);
+ list_del_init(&victim->list);
+
+ mutex_unlock(&audit_filter_mutex);
+
+ prune_one(victim);
+
+ mutex_lock(&audit_filter_mutex);
+ }
+
+ mutex_unlock(&audit_filter_mutex);
+}
+
+/*
+ * Here comes the stuff asynchronous to auditctl operations
+ */
+
+/* inode->inotify_mutex is locked */
+static void evict_chunk(struct audit_chunk *chunk)
+{
+ struct audit_tree *owner;
+ int n;
+
+ if (chunk->dead)
+ return;
+
+ chunk->dead = 1;
+ mutex_lock(&audit_filter_mutex);
+ spin_lock(&hash_lock);
+ while (!list_empty(&chunk->trees)) {
+ owner = list_entry(chunk->trees.next,
+ struct audit_tree, same_root);
+ owner->goner = 1;
+ owner->root = NULL;
+ list_del_init(&owner->same_root);
+ spin_unlock(&hash_lock);
+ kill_rules(owner);
+ list_move(&owner->list, &prune_list);
+ audit_schedule_prune();
+ spin_lock(&hash_lock);
+ }
+ list_del_rcu(&chunk->hash);
+ for (n = 0; n < chunk->count; n++)
+ list_del_init(&chunk->owners[n].list);
+ spin_unlock(&hash_lock);
+ mutex_unlock(&audit_filter_mutex);
+}
+
+static void handle_event(struct inotify_watch *watch, u32 wd, u32 mask,
+ u32 cookie, const char *dname, struct inode *inode)
+{
+ struct audit_chunk *chunk = container_of(watch, struct audit_chunk, watch);
+
+ if (mask & IN_IGNORED) {
+ evict_chunk(chunk);
+ put_inotify_watch(watch);
+ }
+}
+
+static void destroy_watch(struct inotify_watch *watch)
+{
+ struct audit_chunk *chunk = container_of(watch, struct audit_chunk, watch);
+ free_chunk(chunk);
+}
+
+static const struct inotify_operations rtree_inotify_ops = {
+ .handle_event = handle_event,
+ .destroy_watch = destroy_watch,
+};
+
+static int __init audit_tree_init(void)
+{
+ int i;
+
+ rtree_ih = inotify_init(&rtree_inotify_ops);
+ if (IS_ERR(rtree_ih))
+ audit_panic("cannot initialize inotify handle for rectree watches");
+
+ for (i = 0; i < HASH_SIZE; i++)
+ INIT_LIST_HEAD(&chunk_hash_heads[i]);
+
+ return 0;
+}
+__initcall(audit_tree_init);
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 359645cff5b2..5d96f2cc7be8 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -87,7 +87,7 @@ struct list_head audit_filter_list[AUDIT_NR_FILTERS] = {
#endif
};
-static DEFINE_MUTEX(audit_filter_mutex);
+DEFINE_MUTEX(audit_filter_mutex);
/* Inotify handle */
extern struct inotify_handle *audit_ih;
@@ -145,7 +145,7 @@ static inline void audit_free_rule(struct audit_entry *e)
kfree(e);
}
-static inline void audit_free_rule_rcu(struct rcu_head *head)
+void audit_free_rule_rcu(struct rcu_head *head)
{
struct audit_entry *e = container_of(head, struct audit_entry, rcu);
audit_free_rule(e);
@@ -217,7 +217,7 @@ static inline struct audit_entry *audit_init_entry(u32 field_count)
/* Unpack a filter field's string representation from user-space
* buffer. */
-static char *audit_unpack_string(void **bufp, size_t *remain, size_t len)
+char *audit_unpack_string(void **bufp, size_t *remain, size_t len)
{
char *str;
@@ -247,7 +247,7 @@ static inline int audit_to_inode(struct audit_krule *krule,
struct audit_field *f)
{
if (krule->listnr != AUDIT_FILTER_EXIT ||
- krule->watch || krule->inode_f)
+ krule->watch || krule->inode_f || krule->tree)
return -EINVAL;
krule->inode_f = f;
@@ -266,7 +266,7 @@ static int audit_to_watch(struct audit_krule *krule, char *path, int len,
if (path[0] != '/' || path[len-1] == '/' ||
krule->listnr != AUDIT_FILTER_EXIT ||
op & ~AUDIT_EQUAL ||
- krule->inode_f || krule->watch) /* 1 inode # per rule, for hash */
+ krule->inode_f || krule->watch || krule->tree)
return -EINVAL;
watch = audit_init_watch(path);
@@ -622,6 +622,17 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
goto exit_free;
}
break;
+ case AUDIT_DIR:
+ str = audit_unpack_string(&bufp, &remain, f->val);
+ if (IS_ERR(str))
+ goto exit_free;
+ entry->rule.buflen += f->val;
+
+ err = audit_make_tree(&entry->rule, str, f->op);
+ kfree(str);
+ if (err)
+ goto exit_free;
+ break;
case AUDIT_INODE:
err = audit_to_inode(&entry->rule, f);
if (err)
@@ -668,7 +679,7 @@ exit_free:
}
/* Pack a filter field's string representation into data block. */
-static inline size_t audit_pack_string(void **bufp, char *str)
+static inline size_t audit_pack_string(void **bufp, const char *str)
{
size_t len = strlen(str);
@@ -747,6 +758,11 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule)
data->buflen += data->values[i] =
audit_pack_string(&bufp, krule->watch->path);
break;
+ case AUDIT_DIR:
+ data->buflen += data->values[i] =
+ audit_pack_string(&bufp,
+ audit_tree_path(krule->tree));
+ break;
case AUDIT_FILTERKEY:
data->buflen += data->values[i] =
audit_pack_string(&bufp, krule->filterkey);
@@ -795,6 +811,11 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b)
if (strcmp(a->watch->path, b->watch->path))
return 1;
break;
+ case AUDIT_DIR:
+ if (strcmp(audit_tree_path(a->tree),
+ audit_tree_path(b->tree)))
+ return 1;
+ break;
case AUDIT_FILTERKEY:
/* both filterkeys exist based on above type compare */
if (strcmp(a->filterkey, b->filterkey))
@@ -897,6 +918,14 @@ static struct audit_entry *audit_dupe_rule(struct audit_krule *old,
new->inode_f = old->inode_f;
new->watch = NULL;
new->field_count = old->field_count;
+ /*
+ * note that we are OK with not refcounting here; audit_match_tree()
+ * never dereferences tree and we can't get false positives there
+ * since we'd have to have rule gone from the list *and* removed
+ * before the chunks found by lookup had been allocated, i.e. before
+ * the beginning of list scan.
+ */
+ new->tree = old->tree;
memcpy(new->fields, old->fields, sizeof(struct audit_field) * fcount);
/* deep copy this information, updating the se_rule fields, because
@@ -1217,6 +1246,7 @@ static inline int audit_add_rule(struct audit_entry *entry,
struct audit_entry *e;
struct audit_field *inode_f = entry->rule.inode_f;
struct audit_watch *watch = entry->rule.watch;
+ struct audit_tree *tree = entry->rule.tree;
struct nameidata *ndp = NULL, *ndw = NULL;
int h, err;
#ifdef CONFIG_AUDITSYSCALL
@@ -1238,6 +1268,9 @@ static inline int audit_add_rule(struct audit_entry *entry,
mutex_unlock(&audit_filter_mutex);
if (e) {
err = -EEXIST;
+ /* normally audit_add_tree_rule() will free it on failure */
+ if (tree)
+ audit_put_tree(tree);
goto error;
}
@@ -1259,6 +1292,13 @@ static inline int audit_add_rule(struct audit_entry *entry,
h = audit_hash_ino((u32)watch->ino);
list = &audit_inode_hash[h];
}
+ if (tree) {
+ err = audit_add_tree_rule(&entry->rule);
+ if (err) {
+ mutex_unlock(&audit_filter_mutex);
+ goto error;
+ }
+ }
if (entry->rule.flags & AUDIT_FILTER_PREPEND) {
list_add_rcu(&entry->list, list);
@@ -1292,6 +1332,7 @@ static inline int audit_del_rule(struct audit_entry *entry,
struct audit_entry *e;
struct audit_field *inode_f = entry->rule.inode_f;
struct audit_watch *watch, *tmp_watch = entry->rule.watch;
+ struct audit_tree *tree = entry->rule.tree;
LIST_HEAD(inotify_list);
int h, ret = 0;
#ifdef CONFIG_AUDITSYSCALL
@@ -1336,6 +1377,9 @@ static inline int audit_del_rule(struct audit_entry *entry,
}
}
+ if (e->rule.tree)
+ audit_remove_tree_rule(&e->rule);
+
list_del_rcu(&e->list);
call_rcu(&e->rcu, audit_free_rule_rcu);
@@ -1354,6 +1398,8 @@ static inline int audit_del_rule(struct audit_entry *entry,
out:
if (tmp_watch)
audit_put_watch(tmp_watch); /* match initial get */
+ if (tree)
+ audit_put_tree(tree); /* that's the temporary one */
return ret;
}
@@ -1498,7 +1544,7 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
* auditctl to read from it... which isn't ever going to
* happen if we're actually running in the context of auditctl
* trying to _send_ the stuff */
-
+
dest = kmalloc(sizeof(struct audit_netlink_list), GFP_KERNEL);
if (!dest)
return -ENOMEM;
@@ -1678,7 +1724,7 @@ int audit_filter_type(int type)
{
struct audit_entry *e;
int result = 0;
-
+
rcu_read_lock();
if (list_empty(&audit_filter_list[AUDIT_FILTER_TYPE]))
goto unlock_and_return;
@@ -1737,6 +1783,7 @@ int selinux_audit_rule_update(void)
{
struct audit_entry *entry, *n, *nentry;
struct audit_watch *watch;
+ struct audit_tree *tree;
int i, err = 0;
/* audit_filter_mutex synchronizes the writers */
@@ -1748,6 +1795,7 @@ int selinux_audit_rule_update(void)
continue;
watch = entry->rule.watch;
+ tree = entry->rule.tree;
nentry = audit_dupe_rule(&entry->rule, watch);
if (unlikely(IS_ERR(nentry))) {
/* save the first error encountered for the
@@ -1763,7 +1811,9 @@ int selinux_audit_rule_update(void)
list_add(&nentry->rule.rlist,
&watch->rules);
list_del(&entry->rule.rlist);
- }
+ } else if (tree)
+ list_replace_init(&entry->rule.rlist,
+ &nentry->rule.rlist);
list_replace_rcu(&entry->list, &nentry->list);
}
call_rcu(&entry->rcu, audit_free_rule_rcu);
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 0ae703c157ba..bce9ecdb7712 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -45,7 +45,6 @@
#include <linux/init.h>
#include <asm/types.h>
#include <asm/atomic.h>
-#include <asm/types.h>
#include <linux/fs.h>
#include <linux/namei.h>
#include <linux/mm.h>
@@ -66,6 +65,7 @@
#include <linux/binfmts.h>
#include <linux/highmem.h>
#include <linux/syscalls.h>
+#include <linux/inotify.h>
#include "audit.h"
@@ -180,6 +180,11 @@ struct audit_aux_data_pids {
int pid_count;
};
+struct audit_tree_refs {
+ struct audit_tree_refs *next;
+ struct audit_chunk *c[31];
+};
+
/* The per-task audit context. */
struct audit_context {
int dummy; /* must be the first element */
@@ -212,6 +217,9 @@ struct audit_context {
pid_t target_pid;
u32 target_sid;
+ struct audit_tree_refs *trees, *first_trees;
+ int tree_count;
+
#if AUDIT_DEBUG
int put_count;
int ino_count;
@@ -266,6 +274,117 @@ static int audit_match_perm(struct audit_context *ctx, int mask)
}
}
+/*
+ * We keep a linked list of fixed-sized (31 pointer) arrays of audit_chunk *;
+ * ->first_trees points to its beginning, ->trees - to the current end of data.
+ * ->tree_count is the number of free entries in array pointed to by ->trees.
+ * Original condition is (NULL, NULL, 0); as soon as it grows we never revert to NULL,
+ * "empty" becomes (p, p, 31) afterwards. We don't shrink the list (and seriously,
+ * it's going to remain 1-element for almost any setup) until we free context itself.
+ * References in it _are_ dropped - at the same time we free/drop aux stuff.
+ */
+
+#ifdef CONFIG_AUDIT_TREE
+static int put_tree_ref(struct audit_context *ctx, struct audit_chunk *chunk)
+{
+ struct audit_tree_refs *p = ctx->trees;
+ int left = ctx->tree_count;
+ if (likely(left)) {
+ p->c[--left] = chunk;
+ ctx->tree_count = left;
+ return 1;
+ }
+ if (!p)
+ return 0;
+ p = p->next;
+ if (p) {
+ p->c[30] = chunk;
+ ctx->trees = p;
+ ctx->tree_count = 30;
+ return 1;
+ }
+ return 0;
+}
+
+static int grow_tree_refs(struct audit_context *ctx)
+{
+ struct audit_tree_refs *p = ctx->trees;
+ ctx->trees = kzalloc(sizeof(struct audit_tree_refs), GFP_KERNEL);
+ if (!ctx->trees) {
+ ctx->trees = p;
+ return 0;
+ }
+ if (p)
+ p->next = ctx->trees;
+ else
+ ctx->first_trees = ctx->trees;
+ ctx->tree_count = 31;
+ return 1;
+}
+#endif
+
+static void unroll_tree_refs(struct audit_context *ctx,
+ struct audit_tree_refs *p, int count)
+{
+#ifdef CONFIG_AUDIT_TREE
+ struct audit_tree_refs *q;
+ int n;
+ if (!p) {
+ /* we started with empty chain */
+ p = ctx->first_trees;
+ count = 31;
+ /* if the very first allocation has failed, nothing to do */
+ if (!p)
+ return;
+ }
+ n = count;
+ for (q = p; q != ctx->trees; q = q->next, n = 31) {
+ while (n--) {
+ audit_put_chunk(q->c[n]);
+ q->c[n] = NULL;
+ }
+ }
+ while (n-- > ctx->tree_count) {
+ audit_put_chunk(q->c[n]);
+ q->c[n] = NULL;
+ }
+ ctx->trees = p;
+ ctx->tree_count = count;
+#endif
+}
+
+static void free_tree_refs(struct audit_context *ctx)
+{
+ struct audit_tree_refs *p, *q;
+ for (p = ctx->first_trees; p; p = q) {
+ q = p->next;
+ kfree(p);
+ }
+}
+
+static int match_tree_refs(struct audit_context *ctx, struct audit_tree *tree)
+{
+#ifdef CONFIG_AUDIT_TREE
+ struct audit_tree_refs *p;
+ int n;
+ if (!tree)
+ return 0;
+ /* full ones */
+ for (p = ctx->first_trees; p != ctx->trees; p = p->next) {
+ for (n = 0; n < 31; n++)
+ if (audit_tree_match(p->c[n], tree))
+ return 1;
+ }
+ /* partial */
+ if (p) {
+ for (n = ctx->tree_count; n < 31; n++)
+ if (audit_tree_match(p->c[n], tree))
+ return 1;
+ }
+#endif
+ return 0;
+}
+
/* Determine if any context name data matches a rule's watch data */
/* Compare a task_struct with an audit_rule. Return 1 on match, 0
* otherwise. */
@@ -321,7 +440,7 @@ static int audit_filter_rules(struct task_struct *tsk,
result = audit_comparator(tsk->personality, f->op, f->val);
break;
case AUDIT_ARCH:
- if (ctx)
+ if (ctx)
result = audit_comparator(ctx->arch, f->op, f->val);
break;
@@ -380,6 +499,10 @@ static int audit_filter_rules(struct task_struct *tsk,
result = (name->dev == rule->watch->dev &&
name->ino == rule->watch->ino);
break;
+ case AUDIT_DIR:
+ if (ctx)
+ result = match_tree_refs(ctx, rule->tree);
+ break;
case AUDIT_LOGINUID:
result = 0;
if (ctx)
@@ -728,6 +851,8 @@ static inline void audit_free_context(struct audit_context *context)
context->name_count, count);
}
audit_free_names(context);
+ unroll_tree_refs(context, NULL, 0);
+ free_tree_refs(context);
audit_free_aux(context);
kfree(context->filterkey);
kfree(context);
@@ -899,7 +1024,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
if (context->personality != PER_LINUX)
audit_log_format(ab, " per=%lx", context->personality);
if (context->return_valid)
- audit_log_format(ab, " success=%s exit=%ld",
+ audit_log_format(ab, " success=%s exit=%ld",
(context->return_valid==AUDITSC_SUCCESS)?"yes":"no",
context->return_code);
@@ -1136,8 +1261,8 @@ void audit_free(struct task_struct *tsk)
return;
/* Check for system calls that do not go through the exit
- * function (e.g., exit_group), then free context block.
- * We use GFP_ATOMIC here because we might be doing this
+ * function (e.g., exit_group), then free context block.
+ * We use GFP_ATOMIC here because we might be doing this
* in the context of the idle thread */
/* that can happen only if we are called from do_exit() */
if (context->in_syscall && context->auditable)
@@ -1271,6 +1396,7 @@ void audit_syscall_exit(int valid, long return_code)
tsk->audit_context = new_context;
} else {
audit_free_names(context);
+ unroll_tree_refs(context, NULL, 0);
audit_free_aux(context);
context->aux = NULL;
context->aux_pids = NULL;
@@ -1282,6 +1408,95 @@ void audit_syscall_exit(int valid, long return_code)
}
}
+static inline void handle_one(const struct inode *inode)
+{
+#ifdef CONFIG_AUDIT_TREE
+ struct audit_context *context;
+ struct audit_tree_refs *p;
+ struct audit_chunk *chunk;
+ int count;
+ if (likely(list_empty(&inode->inotify_watches)))
+ return;
+ context = current->audit_context;
+ p = context->trees;
+ count = context->tree_count;
+ rcu_read_lock();
+ chunk = audit_tree_lookup(inode);
+ rcu_read_unlock();
+ if (!chunk)
+ return;
+ if (likely(put_tree_ref(context, chunk)))
+ return;
+ if (unlikely(!grow_tree_refs(context))) {
+ printk(KERN_WARNING "out of memory, audit has lost a tree reference");
+ audit_set_auditable(context);
+ audit_put_chunk(chunk);
+ unroll_tree_refs(context, p, count);
+ return;
+ }
+ put_tree_ref(context, chunk);
+#endif
+}
+
+static void handle_path(const struct dentry *dentry)
+{
+#ifdef CONFIG_AUDIT_TREE
+ struct audit_context *context;
+ struct audit_tree_refs *p;
+ const struct dentry *d, *parent;
+ struct audit_chunk *drop;
+ unsigned long seq;
+ int count;
+
+ context = current->audit_context;
+ p = context->trees;
+ count = context->tree_count;
+retry:
+ drop = NULL;
+ d = dentry;
+ rcu_read_lock();
+ seq = read_seqbegin(&rename_lock);
+ for(;;) {
+ struct inode *inode = d->d_inode;
+ if (inode && unlikely(!list_empty(&inode->inotify_watches))) {
+ struct audit_chunk *chunk;
+ chunk = audit_tree_lookup(inode);
+ if (chunk) {
+ if (unlikely(!put_tree_ref(context, chunk))) {
+ drop = chunk;
+ break;
+ }
+ }
+ }
+ parent = d->d_parent;
+ if (parent == d)
+ break;
+ d = parent;
+ }
+ if (unlikely(read_seqretry(&rename_lock, seq) || drop)) { /* in this order */
+ rcu_read_unlock();
+ if (!drop) {
+ /* just a race with rename */
+ unroll_tree_refs(context, p, count);
+ goto retry;
+ }
+ audit_put_chunk(drop);
+ if (grow_tree_refs(context)) {
+ /* OK, got more space */
+ unroll_tree_refs(context, p, count);
+ goto retry;
+ }
+ /* too bad */
+ printk(KERN_WARNING
+ "out of memory, audit has lost a tree reference");
+ unroll_tree_refs(context, p, count);
+ audit_set_auditable(context);
+ return;
+ }
+ rcu_read_unlock();
+#endif
+}
+
/**
* audit_getname - add a name to the list
* @name: name to add
@@ -1317,7 +1532,7 @@ void __audit_getname(const char *name)
context->pwdmnt = mntget(current->fs->pwdmnt);
read_unlock(&current->fs->lock);
}
-
+
}
/* audit_putname - intercept a putname request
@@ -1400,14 +1615,15 @@ static void audit_copy_inode(struct audit_names *name, const struct inode *inode
/**
* audit_inode - store the inode and device from a lookup
* @name: name being audited
- * @inode: inode being audited
+ * @dentry: dentry being audited
*
* Called from fs/namei.c:path_lookup().
*/
-void __audit_inode(const char *name, const struct inode *inode)
+void __audit_inode(const char *name, const struct dentry *dentry)
{
int idx;
struct audit_context *context = current->audit_context;
+ const struct inode *inode = dentry->d_inode;
if (!context->in_syscall)
return;
@@ -1427,13 +1643,14 @@ void __audit_inode(const char *name, const struct inode *inode)
idx = context->name_count - 1;
context->names[idx].name = NULL;
}
+ handle_path(dentry);
audit_copy_inode(&context->names[idx], inode);
}
/**
* audit_inode_child - collect inode info for created/removed objects
* @dname: inode's dentry name
- * @inode: inode being audited
+ * @dentry: dentry being audited
* @parent: inode of dentry parent
*
* For syscalls that create or remove filesystem objects, audit_inode
@@ -1444,17 +1661,20 @@ void __audit_inode(const char *name, const struct inode *inode)
* must be hooked prior, in order to capture the target inode during
* unsuccessful attempts.
*/
-void __audit_inode_child(const char *dname, const struct inode *inode,
+void __audit_inode_child(const char *dname, const struct dentry *dentry,
const struct inode *parent)
{
int idx;
struct audit_context *context = current->audit_context;
const char *found_parent = NULL, *found_child = NULL;
+ const struct inode *inode = dentry->d_inode;
int dirlen = 0;
if (!context->in_syscall)
return;
+ if (inode)
+ handle_one(inode);
/* determine matching parent */
if (!dname)
goto add_names;
diff --git a/kernel/capability.c b/kernel/capability.c
index c8d3c7762034..efbd9cdce132 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -3,23 +3,18 @@
*
* Copyright (C) 1997 Andrew Main <zefram@fysh.org>
*
- * Integrated into 2.1.97+, Andrew G. Morgan <morgan@transmeta.com>
+ * Integrated into 2.1.97+, Andrew G. Morgan <morgan@kernel.org>
* 30 May 2002: Cleanup, Robert M. Love <rml@tech9.net>
- */
+ */
#include <linux/capability.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/security.h>
#include <linux/syscalls.h>
+#include <linux/pid_namespace.h>
#include <asm/uaccess.h>
-unsigned securebits = SECUREBITS_DEFAULT; /* systemwide security settings */
-kernel_cap_t cap_bset = CAP_INIT_EFF_SET;
-
-EXPORT_SYMBOL(securebits);
-EXPORT_SYMBOL(cap_bset);
-
/*
* This lock protects task->cap_* for all tasks including current.
* Locking rule: acquire this prior to tasklist_lock.
@@ -43,49 +38,49 @@ static DEFINE_SPINLOCK(task_capability_lock);
*/
asmlinkage long sys_capget(cap_user_header_t header, cap_user_data_t dataptr)
{
- int ret = 0;
- pid_t pid;
- __u32 version;
- struct task_struct *target;
- struct __user_cap_data_struct data;
-
- if (get_user(version, &header->version))
- return -EFAULT;
-
- if (version != _LINUX_CAPABILITY_VERSION) {
- if (put_user(_LINUX_CAPABILITY_VERSION, &header->version))
- return -EFAULT;
- return -EINVAL;
- }
+ int ret = 0;
+ pid_t pid;
+ __u32 version;
+ struct task_struct *target;
+ struct __user_cap_data_struct data;
+
+ if (get_user(version, &header->version))
+ return -EFAULT;
+
+ if (version != _LINUX_CAPABILITY_VERSION) {
+ if (put_user(_LINUX_CAPABILITY_VERSION, &header->version))
+ return -EFAULT;
+ return -EINVAL;
+ }
- if (get_user(pid, &header->pid))
- return -EFAULT;
+ if (get_user(pid, &header->pid))
+ return -EFAULT;
- if (pid < 0)
- return -EINVAL;
+ if (pid < 0)
+ return -EINVAL;
- spin_lock(&task_capability_lock);
- read_lock(&tasklist_lock);
+ spin_lock(&task_capability_lock);
+ read_lock(&tasklist_lock);
- if (pid && pid != current->pid) {
- target = find_task_by_pid(pid);
- if (!target) {
- ret = -ESRCH;
- goto out;
- }
- } else
- target = current;
+ if (pid && pid != task_pid_vnr(current)) {
+ target = find_task_by_vpid(pid);
+ if (!target) {
+ ret = -ESRCH;
+ goto out;
+ }
+ } else
+ target = current;
- ret = security_capget(target, &data.effective, &data.inheritable, &data.permitted);
+ ret = security_capget(target, &data.effective, &data.inheritable, &data.permitted);
out:
- read_unlock(&tasklist_lock);
- spin_unlock(&task_capability_lock);
+ read_unlock(&tasklist_lock);
+ spin_unlock(&task_capability_lock);
- if (!ret && copy_to_user(dataptr, &data, sizeof data))
- return -EFAULT;
+ if (!ret && copy_to_user(dataptr, &data, sizeof data))
+ return -EFAULT;
- return ret;
+ return ret;
}
/*
@@ -101,7 +96,7 @@ static inline int cap_set_pg(int pgrp_nr, kernel_cap_t *effective,
int found = 0;
struct pid *pgrp;
- pgrp = find_pid(pgrp_nr);
+ pgrp = find_vpid(pgrp_nr);
do_each_pid_task(pgrp, PIDTYPE_PGID, g) {
target = g;
while_each_thread(g, target) {
@@ -118,7 +113,7 @@ static inline int cap_set_pg(int pgrp_nr, kernel_cap_t *effective,
} while_each_pid_task(pgrp, PIDTYPE_PGID, g);
if (!found)
- ret = 0;
+ ret = 0;
return ret;
}
@@ -135,7 +130,7 @@ static inline int cap_set_all(kernel_cap_t *effective,
int found = 0;
do_each_thread(g, target) {
- if (target == current || is_init(target))
+ if (target == current || is_container_init(target->group_leader))
continue;
found = 1;
if (security_capset_check(target, effective, inheritable,
@@ -172,68 +167,68 @@ static inline int cap_set_all(kernel_cap_t *effective,
*/
asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
{
- kernel_cap_t inheritable, permitted, effective;
- __u32 version;
- struct task_struct *target;
- int ret;
- pid_t pid;
-
- if (get_user(version, &header->version))
- return -EFAULT;
-
- if (version != _LINUX_CAPABILITY_VERSION) {
- if (put_user(_LINUX_CAPABILITY_VERSION, &header->version))
- return -EFAULT;
- return -EINVAL;
- }
-
- if (get_user(pid, &header->pid))
- return -EFAULT;
-
- if (pid && pid != current->pid && !capable(CAP_SETPCAP))
- return -EPERM;
-
- if (copy_from_user(&effective, &data->effective, sizeof(effective)) ||
- copy_from_user(&inheritable, &data->inheritable, sizeof(inheritable)) ||
- copy_from_user(&permitted, &data->permitted, sizeof(permitted)))
- return -EFAULT;
-
- spin_lock(&task_capability_lock);
- read_lock(&tasklist_lock);
-
- if (pid > 0 && pid != current->pid) {
- target = find_task_by_pid(pid);
- if (!target) {
- ret = -ESRCH;
- goto out;
- }
- } else
- target = current;
-
- ret = 0;
-
- /* having verified that the proposed changes are legal,
- we now put them into effect. */
- if (pid < 0) {
- if (pid == -1) /* all procs other than current and init */
- ret = cap_set_all(&effective, &inheritable, &permitted);
-
- else /* all procs in process group */
- ret = cap_set_pg(-pid, &effective, &inheritable,
- &permitted);
- } else {
- ret = security_capset_check(target, &effective, &inheritable,
- &permitted);
- if (!ret)
- security_capset_set(target, &effective, &inheritable,
- &permitted);
- }
+ kernel_cap_t inheritable, permitted, effective;
+ __u32 version;
+ struct task_struct *target;
+ int ret;
+ pid_t pid;
+
+ if (get_user(version, &header->version))
+ return -EFAULT;
+
+ if (version != _LINUX_CAPABILITY_VERSION) {
+ if (put_user(_LINUX_CAPABILITY_VERSION, &header->version))
+ return -EFAULT;
+ return -EINVAL;
+ }
+
+ if (get_user(pid, &header->pid))
+ return -EFAULT;
+
+ if (pid && pid != task_pid_vnr(current) && !capable(CAP_SETPCAP))
+ return -EPERM;
+
+ if (copy_from_user(&effective, &data->effective, sizeof(effective)) ||
+ copy_from_user(&inheritable, &data->inheritable, sizeof(inheritable)) ||
+ copy_from_user(&permitted, &data->permitted, sizeof(permitted)))
+ return -EFAULT;
+
+ spin_lock(&task_capability_lock);
+ read_lock(&tasklist_lock);
+
+ if (pid > 0 && pid != task_pid_vnr(current)) {
+ target = find_task_by_vpid(pid);
+ if (!target) {
+ ret = -ESRCH;
+ goto out;
+ }
+ } else
+ target = current;
+
+ ret = 0;
+
+ /* having verified that the proposed changes are legal,
+ we now put them into effect. */
+ if (pid < 0) {
+ if (pid == -1) /* all procs other than current and init */
+ ret = cap_set_all(&effective, &inheritable, &permitted);
+
+ else /* all procs in process group */
+ ret = cap_set_pg(-pid, &effective, &inheritable,
+ &permitted);
+ } else {
+ ret = security_capset_check(target, &effective, &inheritable,
+ &permitted);
+ if (!ret)
+ security_capset_set(target, &effective, &inheritable,
+ &permitted);
+ }
out:
- read_unlock(&tasklist_lock);
- spin_unlock(&task_capability_lock);
+ read_unlock(&tasklist_lock);
+ spin_unlock(&task_capability_lock);
- return ret;
+ return ret;
}
int __capable(struct task_struct *t, int cap)
@@ -244,7 +239,6 @@ int __capable(struct task_struct *t, int cap)
}
return 0;
}
-EXPORT_SYMBOL(__capable);
int capable(int cap)
{
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
new file mode 100644
index 000000000000..1a3c23936d43
--- /dev/null
+++ b/kernel/cgroup.c
@@ -0,0 +1,2803 @@
+/*
+ * Generic process-grouping system.
+ *
+ * Based originally on the cpuset system, extracted by Paul Menage
+ * Copyright (C) 2006 Google, Inc
+ *
+ * Copyright notices from the original cpuset code:
+ * --------------------------------------------------
+ * Copyright (C) 2003 BULL SA.
+ * Copyright (C) 2004-2006 Silicon Graphics, Inc.
+ *
+ * Portions derived from Patrick Mochel's sysfs code.
+ * sysfs is Copyright (c) 2001-3 Patrick Mochel
+ *
+ * 2003-10-10 Written by Simon Derr.
+ * 2003-10-22 Updates by Stephen Hemminger.
+ * 2004 May-July Rework by Paul Jackson.
+ * ---------------------------------------------------
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of the Linux
+ * distribution for more details.
+ */
+
+#include <linux/cgroup.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/mount.h>
+#include <linux/pagemap.h>
+#include <linux/proc_fs.h>
+#include <linux/rcupdate.h>
+#include <linux/sched.h>
+#include <linux/backing-dev.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/magic.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/sort.h>
+#include <linux/kmod.h>
+#include <linux/delayacct.h>
+#include <linux/cgroupstats.h>
+
+#include <asm/atomic.h>
+
+static DEFINE_MUTEX(cgroup_mutex);
+
+/* Generate an array of cgroup subsystem pointers */
+#define SUBSYS(_x) &_x ## _subsys,
+
+static struct cgroup_subsys *subsys[] = {
+#include <linux/cgroup_subsys.h>
+};
+
+/*
+ * A cgroupfs_root represents the root of a cgroup hierarchy,
+ * and may be associated with a superblock to form an active
+ * hierarchy
+ */
+struct cgroupfs_root {
+ struct super_block *sb;
+
+ /*
+ * The bitmask of subsystems intended to be attached to this
+ * hierarchy
+ */
+ unsigned long subsys_bits;
+
+ /* The bitmask of subsystems currently attached to this hierarchy */
+ unsigned long actual_subsys_bits;
+
+ /* A list running through the attached subsystems */
+ struct list_head subsys_list;
+
+ /* The root cgroup for this hierarchy */
+ struct cgroup top_cgroup;
+
+ /* Tracks how many cgroups are currently defined in hierarchy.*/
+ int number_of_cgroups;
+
+ /* A list running through the mounted hierarchies */
+ struct list_head root_list;
+
+ /* Hierarchy-specific flags */
+ unsigned long flags;
+
+ /* The path to use for release notifications. No locking
+ * between setting and use - so if userspace updates this
+ * while child cgroups exist, you could miss a
+ * notification. We ensure that it's always a valid
+ * NUL-terminated string */
+ char release_agent_path[PATH_MAX];
+};
+
+
+/*
+ * The "rootnode" hierarchy is the "dummy hierarchy", reserved for the
+ * subsystems that are otherwise unattached - it never has more than a
+ * single cgroup, and all tasks are part of that cgroup.
+ */
+static struct cgroupfs_root rootnode;
+
+/* The list of hierarchy roots */
+
+static LIST_HEAD(roots);
+static int root_count;
+
+/* dummytop is a shorthand for the dummy hierarchy's top cgroup */
+#define dummytop (&rootnode.top_cgroup)
+
+/* This flag indicates whether tasks in the fork and exit paths should
+ * take callback_mutex and check for fork/exit handlers to call. This
+ * avoids us having to do extra work in the fork/exit path if none of the
+ * subsystems need to be called.
+ */
+static int need_forkexit_callback;
+
+/* bits in struct cgroup flags field */
+enum {
+ /* Control Group is dead */
+ CGRP_REMOVED,
+ /* Control Group has previously had a child cgroup or a task,
+ * but no longer (only if CGRP_NOTIFY_ON_RELEASE is set) */
+ CGRP_RELEASABLE,
+ /* Control Group requires release notifications to userspace */
+ CGRP_NOTIFY_ON_RELEASE,
+};
+
+/* convenient tests for these bits */
+inline int cgroup_is_removed(const struct cgroup *cgrp)
+{
+ return test_bit(CGRP_REMOVED, &cgrp->flags);
+}
+
+/* bits in struct cgroupfs_root flags field */
+enum {
+ ROOT_NOPREFIX, /* mounted subsystems have no named prefix */
+};
+
+inline int cgroup_is_releasable(const struct cgroup *cgrp)
+{
+ const int bits =
+ (1 << CGRP_RELEASABLE) |
+ (1 << CGRP_NOTIFY_ON_RELEASE);
+ return (cgrp->flags & bits) == bits;
+}
+
+inline int notify_on_release(const struct cgroup *cgrp)
+{
+ return test_bit(CGRP_NOTIFY_ON_RELEASE, &cgrp->flags);
+}
+
+/*
+ * for_each_subsys() allows you to iterate on each subsystem attached to
+ * an active hierarchy
+ */
+#define for_each_subsys(_root, _ss) \
+list_for_each_entry(_ss, &_root->subsys_list, sibling)
+
+/* for_each_root() allows you to iterate across the active hierarchies */
+#define for_each_root(_root) \
+list_for_each_entry(_root, &roots, root_list)
+
+/* the list of cgroups eligible for automatic release. Protected by
+ * release_list_lock */
+static LIST_HEAD(release_list);
+static DEFINE_SPINLOCK(release_list_lock);
+static void cgroup_release_agent(struct work_struct *work);
+static DECLARE_WORK(release_agent_work, cgroup_release_agent);
+static void check_for_release(struct cgroup *cgrp);
+
+/* Link structure for associating css_set objects with cgroups */
+struct cg_cgroup_link {
+ /*
+ * List running through cg_cgroup_links associated with a
+ * cgroup, anchored on cgroup->css_sets
+ */
+ struct list_head cgrp_link_list;
+ /*
+ * List running through cg_cgroup_links pointing at a
+ * single css_set object, anchored on css_set->cg_links
+ */
+ struct list_head cg_link_list;
+ struct css_set *cg;
+};
+
+/* The default css_set - used by init and its children prior to any
+ * hierarchies being mounted. It contains a pointer to the root state
+ * for each subsystem. Also used to anchor the list of css_sets. Not
+ * reference-counted, to improve performance when child cgroups
+ * haven't been created.
+ */
+
+static struct css_set init_css_set;
+static struct cg_cgroup_link init_css_set_link;
+
+/* css_set_lock protects the list of css_set objects, and the
+ * chain of tasks off each css_set. Nests outside task->alloc_lock
+ * due to cgroup_iter_start() */
+static DEFINE_RWLOCK(css_set_lock);
+static int css_set_count;
+
+/* We don't maintain the lists running through each css_set to its
+ * task until after the first call to cgroup_iter_start(). This
+ * reduces the fork()/exit() overhead for people who have cgroups
+ * compiled into their kernel but not actually in use */
+static int use_task_css_set_links;
+
+/* When we create or destroy a css_set, the operation simply
+ * takes/releases a reference count on all the cgroups referenced
+ * by subsystems in this css_set. This can end up multiple-counting
+ * some cgroups, but that's OK - the ref-count is just a
+ * busy/not-busy indicator; ensuring that we only count each cgroup
+ * once would require taking a global lock to ensure that no
+ * subsystems moved between hierarchies while we were doing so.
+ *
+ * Possible TODO: decide at boot time based on the number of
+ * registered subsystems and the number of CPUs or NUMA nodes whether
+ * it's better for performance to ref-count every subsystem, or to
+ * take a global lock and only add one ref count to each hierarchy.
+ */
+
+/*
+ * unlink a css_set from the list and free it
+ */
+static void unlink_css_set(struct css_set *cg)
+{
+ write_lock(&css_set_lock);
+ list_del(&cg->list);
+ css_set_count--;
+ while (!list_empty(&cg->cg_links)) {
+ struct cg_cgroup_link *link;
+ link = list_entry(cg->cg_links.next,
+ struct cg_cgroup_link, cg_link_list);
+ list_del(&link->cg_link_list);
+ list_del(&link->cgrp_link_list);
+ kfree(link);
+ }
+ write_unlock(&css_set_lock);
+}
+
+static void __release_css_set(struct kref *k, int taskexit)
+{
+ int i;
+ struct css_set *cg = container_of(k, struct css_set, ref);
+
+ unlink_css_set(cg);
+
+ rcu_read_lock();
+ for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
+ struct cgroup *cgrp = cg->subsys[i]->cgroup;
+ if (atomic_dec_and_test(&cgrp->count) &&
+ notify_on_release(cgrp)) {
+ if (taskexit)
+ set_bit(CGRP_RELEASABLE, &cgrp->flags);
+ check_for_release(cgrp);
+ }
+ }
+ rcu_read_unlock();
+ kfree(cg);
+}
+
+static void release_css_set(struct kref *k)
+{
+ __release_css_set(k, 0);
+}
+
+static void release_css_set_taskexit(struct kref *k)
+{
+ __release_css_set(k, 1);
+}
+
+/*
+ * refcounted get/put for css_set objects
+ */
+static inline void get_css_set(struct css_set *cg)
+{
+ kref_get(&cg->ref);
+}
+
+static inline void put_css_set(struct css_set *cg)
+{
+ kref_put(&cg->ref, release_css_set);
+}
+
+static inline void put_css_set_taskexit(struct css_set *cg)
+{
+ kref_put(&cg->ref, release_css_set_taskexit);
+}
+
+/*
+ * find_existing_css_set() is a helper for
+ * find_css_set(), and checks to see whether an existing
+ * css_set is suitable. This currently walks a linked-list for
+ * simplicity; a later patch will use a hash table for better
+ * performance
+ *
+ * oldcg: the cgroup group that we're using before the cgroup
+ * transition
+ *
+ * cgrp: the cgroup that we're moving into
+ *
+ * template: location in which to build the desired set of subsystem
+ * state objects for the new cgroup group
+ */
+
+static struct css_set *find_existing_css_set(
+ struct css_set *oldcg,
+ struct cgroup *cgrp,
+ struct cgroup_subsys_state *template[])
+{
+ int i;
+ struct cgroupfs_root *root = cgrp->root;
+ struct list_head *l = &init_css_set.list;
+
+ /* Built the set of subsystem state objects that we want to
+ * see in the new css_set */
+ for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
+ if (root->subsys_bits & (1ull << i)) {
+ /* Subsystem is in this hierarchy. So we want
+ * the subsystem state from the new
+ * cgroup */
+ template[i] = cgrp->subsys[i];
+ } else {
+ /* Subsystem is not in this hierarchy, so we
+ * don't want to change the subsystem state */
+ template[i] = oldcg->subsys[i];
+ }
+ }
+
+ /* Look through existing cgroup groups to find one to reuse */
+ do {
+ struct css_set *cg =
+ list_entry(l, struct css_set, list);
+
+ if (!memcmp(template, cg->subsys, sizeof(cg->subsys))) {
+ /* All subsystems matched */
+ return cg;
+ }
+ /* Try the next cgroup group */
+ l = l->next;
+ } while (l != &init_css_set.list);
+
+ /* No existing cgroup group matched */
+ return NULL;
+}
+
+/*
+ * allocate_cg_links() allocates "count" cg_cgroup_link structures
+ * and chains them on tmp through their cgrp_link_list fields. Returns 0 on
+ * success or a negative error
+ */
+
+static int allocate_cg_links(int count, struct list_head *tmp)
+{
+ struct cg_cgroup_link *link;
+ int i;
+ INIT_LIST_HEAD(tmp);
+ for (i = 0; i < count; i++) {
+ link = kmalloc(sizeof(*link), GFP_KERNEL);
+ if (!link) {
+ while (!list_empty(tmp)) {
+ link = list_entry(tmp->next,
+ struct cg_cgroup_link,
+ cgrp_link_list);
+ list_del(&link->cgrp_link_list);
+ kfree(link);
+ }
+ return -ENOMEM;
+ }
+ list_add(&link->cgrp_link_list, tmp);
+ }
+ return 0;
+}
+
+static void free_cg_links(struct list_head *tmp)
+{
+ while (!list_empty(tmp)) {
+ struct cg_cgroup_link *link;
+ link = list_entry(tmp->next,
+ struct cg_cgroup_link,
+ cgrp_link_list);
+ list_del(&link->cgrp_link_list);
+ kfree(link);
+ }
+}
+
+/*
+ * find_css_set() takes an existing cgroup group and a
+ * cgroup object, and returns a css_set object that's
+ * equivalent to the old group, but with the given cgroup
+ * substituted into the appropriate hierarchy. Must be called with
+ * cgroup_mutex held
+ */
+
+static struct css_set *find_css_set(
+ struct css_set *oldcg, struct cgroup *cgrp)
+{
+ struct css_set *res;
+ struct cgroup_subsys_state *template[CGROUP_SUBSYS_COUNT];
+ int i;
+
+ struct list_head tmp_cg_links;
+ struct cg_cgroup_link *link;
+
+ /* First see if we already have a cgroup group that matches
+ * the desired set */
+ write_lock(&css_set_lock);
+ res = find_existing_css_set(oldcg, cgrp, template);
+ if (res)
+ get_css_set(res);
+ write_unlock(&css_set_lock);
+
+ if (res)
+ return res;
+
+ res = kmalloc(sizeof(*res), GFP_KERNEL);
+ if (!res)
+ return NULL;
+
+ /* Allocate all the cg_cgroup_link objects that we'll need */
+ if (allocate_cg_links(root_count, &tmp_cg_links) < 0) {
+ kfree(res);
+ return NULL;
+ }
+
+ kref_init(&res->ref);
+ INIT_LIST_HEAD(&res->cg_links);
+ INIT_LIST_HEAD(&res->tasks);
+
+ /* Copy the set of subsystem state objects generated in
+ * find_existing_css_set() */
+ memcpy(res->subsys, template, sizeof(res->subsys));
+
+ write_lock(&css_set_lock);
+ /* Add reference counts and links from the new css_set. */
+ for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
+ struct cgroup *cgrp = res->subsys[i]->cgroup;
+ struct cgroup_subsys *ss = subsys[i];
+ atomic_inc(&cgrp->count);
+ /*
+ * We want to add a link once per cgroup, so we
+ * only do it for the first subsystem in each
+ * hierarchy
+ */
+ if (ss->root->subsys_list.next == &ss->sibling) {
+ BUG_ON(list_empty(&tmp_cg_links));
+ link = list_entry(tmp_cg_links.next,
+ struct cg_cgroup_link,
+ cgrp_link_list);
+ list_del(&link->cgrp_link_list);
+ list_add(&link->cgrp_link_list, &cgrp->css_sets);
+ link->cg = res;
+ list_add(&link->cg_link_list, &res->cg_links);
+ }
+ }
+ if (list_empty(&rootnode.subsys_list)) {
+ link = list_entry(tmp_cg_links.next,
+ struct cg_cgroup_link,
+ cgrp_link_list);
+ list_del(&link->cgrp_link_list);
+ list_add(&link->cgrp_link_list, &dummytop->css_sets);
+ link->cg = res;
+ list_add(&link->cg_link_list, &res->cg_links);
+ }
+
+ BUG_ON(!list_empty(&tmp_cg_links));
+
+ /* Link this cgroup group into the list */
+ list_add(&res->list, &init_css_set.list);
+ css_set_count++;
+ INIT_LIST_HEAD(&res->tasks);
+ write_unlock(&css_set_lock);
+
+ return res;
+}
+
+/*
+ * There is one global cgroup mutex. We also require taking
+ * task_lock() when dereferencing a task's cgroup subsys pointers.
+ * See "The task_lock() exception", at the end of this comment.
+ *
+ * A task must hold cgroup_mutex to modify cgroups.
+ *
+ * Any task can increment and decrement the count field without lock.
+ * So in general, code holding cgroup_mutex can't rely on the count
+ * field not changing. However, if the count goes to zero, then only
+ * attach_task() can increment it again. Because a count of zero
+ * means that no tasks are currently attached, therefore there is no
+ * way a task attached to that cgroup can fork (the other way to
+ * increment the count). So code holding cgroup_mutex can safely
+ * assume that if the count is zero, it will stay zero. Similarly, if
+ * a task holds cgroup_mutex on a cgroup with zero count, it
+ * knows that the cgroup won't be removed, as cgroup_rmdir()
+ * needs that mutex.
+ *
+ * The cgroup_common_file_write handler for operations that modify
+ * the cgroup hierarchy holds cgroup_mutex across the entire operation,
+ * single threading all such cgroup modifications across the system.
+ *
+ * The fork and exit callbacks cgroup_fork() and cgroup_exit(), don't
+ * (usually) take cgroup_mutex. These are the two most performance
+ * critical pieces of code here. The exception occurs on cgroup_exit(),
+ * when a task in a notify_on_release cgroup exits. Then cgroup_mutex
+ * is taken, and if the cgroup count is zero, a usermode call made
+ * to /sbin/cgroup_release_agent with the name of the cgroup (path
+ * relative to the root of cgroup file system) as the argument.
+ *
+ * A cgroup can only be deleted if both its 'count' of using tasks
+ * is zero, and its list of 'children' cgroups is empty. Since all
+ * tasks in the system use _some_ cgroup, and since there is always at
+ * least one task in the system (init, pid == 1), therefore, top_cgroup
+ * always has either children cgroups and/or using tasks. So we don't
+ * need a special hack to ensure that top_cgroup cannot be deleted.
+ *
+ * The task_lock() exception
+ *
+ * The need for this exception arises from the action of
+ * attach_task(), which overwrites one tasks cgroup pointer with
+ * another. It does so using cgroup_mutexe, however there are
+ * several performance critical places that need to reference
+ * task->cgroup without the expense of grabbing a system global
+ * mutex. Therefore except as noted below, when dereferencing or, as
+ * in attach_task(), modifying a task'ss cgroup pointer we use
+ * task_lock(), which acts on a spinlock (task->alloc_lock) already in
+ * the task_struct routinely used for such matters.
+ *
+ * P.S. One more locking exception. RCU is used to guard the
+ * update of a tasks cgroup pointer by attach_task()
+ */
+
+/**
+ * cgroup_lock - lock out any changes to cgroup structures
+ *
+ */
+
+void cgroup_lock(void)
+{
+ mutex_lock(&cgroup_mutex);
+}
+
+/**
+ * cgroup_unlock - release lock on cgroup changes
+ *
+ * Undo the lock taken in a previous cgroup_lock() call.
+ */
+
+void cgroup_unlock(void)
+{
+ mutex_unlock(&cgroup_mutex);
+}
+
+/*
+ * A couple of forward declarations required, due to cyclic reference loop:
+ * cgroup_mkdir -> cgroup_create -> cgroup_populate_dir ->
+ * cgroup_add_file -> cgroup_create_file -> cgroup_dir_inode_operations
+ * -> cgroup_mkdir.
+ */
+
+static int cgroup_mkdir(struct inode *dir, struct dentry *dentry, int mode);
+static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry);
+static int cgroup_populate_dir(struct cgroup *cgrp);
+static struct inode_operations cgroup_dir_inode_operations;
+static struct file_operations proc_cgroupstats_operations;
+
+static struct backing_dev_info cgroup_backing_dev_info = {
+ .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
+};
+
+static struct inode *cgroup_new_inode(mode_t mode, struct super_block *sb)
+{
+ struct inode *inode = new_inode(sb);
+
+ if (inode) {
+ inode->i_mode = mode;
+ inode->i_uid = current->fsuid;
+ inode->i_gid = current->fsgid;
+ inode->i_blocks = 0;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_mapping->backing_dev_info = &cgroup_backing_dev_info;
+ }
+ return inode;
+}
+
+static void cgroup_diput(struct dentry *dentry, struct inode *inode)
+{
+ /* is dentry a directory ? if so, kfree() associated cgroup */
+ if (S_ISDIR(inode->i_mode)) {
+ struct cgroup *cgrp = dentry->d_fsdata;
+ BUG_ON(!(cgroup_is_removed(cgrp)));
+ /* It's possible for external users to be holding css
+ * reference counts on a cgroup; css_put() needs to
+ * be able to access the cgroup after decrementing
+ * the reference count in order to know if it needs to
+ * queue the cgroup to be handled by the release
+ * agent */
+ synchronize_rcu();
+ kfree(cgrp);
+ }
+ iput(inode);
+}
+
+static void remove_dir(struct dentry *d)
+{
+ struct dentry *parent = dget(d->d_parent);
+
+ d_delete(d);
+ simple_rmdir(parent->d_inode, d);
+ dput(parent);
+}
+
+static void cgroup_clear_directory(struct dentry *dentry)
+{
+ struct list_head *node;
+
+ BUG_ON(!mutex_is_locked(&dentry->d_inode->i_mutex));
+ spin_lock(&dcache_lock);
+ node = dentry->d_subdirs.next;
+ while (node != &dentry->d_subdirs) {
+ struct dentry *d = list_entry(node, struct dentry, d_u.d_child);
+ list_del_init(node);
+ if (d->d_inode) {
+ /* This should never be called on a cgroup
+ * directory with child cgroups */
+ BUG_ON(d->d_inode->i_mode & S_IFDIR);
+ d = dget_locked(d);
+ spin_unlock(&dcache_lock);
+ d_delete(d);
+ simple_unlink(dentry->d_inode, d);
+ dput(d);
+ spin_lock(&dcache_lock);
+ }
+ node = dentry->d_subdirs.next;
+ }
+ spin_unlock(&dcache_lock);
+}
+
+/*
+ * NOTE : the dentry must have been dget()'ed
+ */
+static void cgroup_d_remove_dir(struct dentry *dentry)
+{
+ cgroup_clear_directory(dentry);
+
+ spin_lock(&dcache_lock);
+ list_del_init(&dentry->d_u.d_child);
+ spin_unlock(&dcache_lock);
+ remove_dir(dentry);
+}
+
+static int rebind_subsystems(struct cgroupfs_root *root,
+ unsigned long final_bits)
+{
+ unsigned long added_bits, removed_bits;
+ struct cgroup *cgrp = &root->top_cgroup;
+ int i;
+
+ removed_bits = root->actual_subsys_bits & ~final_bits;
+ added_bits = final_bits & ~root->actual_subsys_bits;
+ /* Check that any added subsystems are currently free */
+ for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
+ unsigned long long bit = 1ull << i;
+ struct cgroup_subsys *ss = subsys[i];
+ if (!(bit & added_bits))
+ continue;
+ if (ss->root != &rootnode) {
+ /* Subsystem isn't free */
+ return -EBUSY;
+ }
+ }
+
+ /* Currently we don't handle adding/removing subsystems when
+ * any child cgroups exist. This is theoretically supportable
+ * but involves complex error handling, so it's being left until
+ * later */
+ if (!list_empty(&cgrp->children))
+ return -EBUSY;
+
+ /* Process each subsystem */
+ for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
+ struct cgroup_subsys *ss = subsys[i];
+ unsigned long bit = 1UL << i;
+ if (bit & added_bits) {
+ /* We're binding this subsystem to this hierarchy */
+ BUG_ON(cgrp->subsys[i]);
+ BUG_ON(!dummytop->subsys[i]);
+ BUG_ON(dummytop->subsys[i]->cgroup != dummytop);
+ cgrp->subsys[i] = dummytop->subsys[i];
+ cgrp->subsys[i]->cgroup = cgrp;
+ list_add(&ss->sibling, &root->subsys_list);
+ rcu_assign_pointer(ss->root, root);
+ if (ss->bind)
+ ss->bind(ss, cgrp);
+
+ } else if (bit & removed_bits) {
+ /* We're removing this subsystem */
+ BUG_ON(cgrp->subsys[i] != dummytop->subsys[i]);
+ BUG_ON(cgrp->subsys[i]->cgroup != cgrp);
+ if (ss->bind)
+ ss->bind(ss, dummytop);
+ dummytop->subsys[i]->cgroup = dummytop;
+ cgrp->subsys[i] = NULL;
+ rcu_assign_pointer(subsys[i]->root, &rootnode);
+ list_del(&ss->sibling);
+ } else if (bit & final_bits) {
+ /* Subsystem state should already exist */
+ BUG_ON(!cgrp->subsys[i]);
+ } else {
+ /* Subsystem state shouldn't exist */
+ BUG_ON(cgrp->subsys[i]);
+ }
+ }
+ root->subsys_bits = root->actual_subsys_bits = final_bits;
+ synchronize_rcu();
+
+ return 0;
+}
+
+static int cgroup_show_options(struct seq_file *seq, struct vfsmount *vfs)
+{
+ struct cgroupfs_root *root = vfs->mnt_sb->s_fs_info;
+ struct cgroup_subsys *ss;
+
+ mutex_lock(&cgroup_mutex);
+ for_each_subsys(root, ss)
+ seq_printf(seq, ",%s", ss->name);
+ if (test_bit(ROOT_NOPREFIX, &root->flags))
+ seq_puts(seq, ",noprefix");
+ if (strlen(root->release_agent_path))
+ seq_printf(seq, ",release_agent=%s", root->release_agent_path);
+ mutex_unlock(&cgroup_mutex);
+ return 0;
+}
+
+struct cgroup_sb_opts {
+ unsigned long subsys_bits;
+ unsigned long flags;
+ char *release_agent;
+};
+
+/* Convert a hierarchy specifier into a bitmask of subsystems and
+ * flags. */
+static int parse_cgroupfs_options(char *data,
+ struct cgroup_sb_opts *opts)
+{
+ char *token, *o = data ?: "all";
+
+ opts->subsys_bits = 0;
+ opts->flags = 0;
+ opts->release_agent = NULL;
+
+ while ((token = strsep(&o, ",")) != NULL) {
+ if (!*token)
+ return -EINVAL;
+ if (!strcmp(token, "all")) {
+ opts->subsys_bits = (1 << CGROUP_SUBSYS_COUNT) - 1;
+ } else if (!strcmp(token, "noprefix")) {
+ set_bit(ROOT_NOPREFIX, &opts->flags);
+ } else if (!strncmp(token, "release_agent=", 14)) {
+ /* Specifying two release agents is forbidden */
+ if (opts->release_agent)
+ return -EINVAL;
+ opts->release_agent = kzalloc(PATH_MAX, GFP_KERNEL);
+ if (!opts->release_agent)
+ return -ENOMEM;
+ strncpy(opts->release_agent, token + 14, PATH_MAX - 1);
+ opts->release_agent[PATH_MAX - 1] = 0;
+ } else {
+ struct cgroup_subsys *ss;
+ int i;
+ for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
+ ss = subsys[i];
+ if (!strcmp(token, ss->name)) {
+ set_bit(i, &opts->subsys_bits);
+ break;
+ }
+ }
+ if (i == CGROUP_SUBSYS_COUNT)
+ return -ENOENT;
+ }
+ }
+
+ /* We can't have an empty hierarchy */
+ if (!opts->subsys_bits)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int cgroup_remount(struct super_block *sb, int *flags, char *data)
+{
+ int ret = 0;
+ struct cgroupfs_root *root = sb->s_fs_info;
+ struct cgroup *cgrp = &root->top_cgroup;
+ struct cgroup_sb_opts opts;
+
+ mutex_lock(&cgrp->dentry->d_inode->i_mutex);
+ mutex_lock(&cgroup_mutex);
+
+ /* See what subsystems are wanted */
+ ret = parse_cgroupfs_options(data, &opts);
+ if (ret)
+ goto out_unlock;
+
+ /* Don't allow flags to change at remount */
+ if (opts.flags != root->flags) {
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+
+ ret = rebind_subsystems(root, opts.subsys_bits);
+
+ /* (re)populate subsystem files */
+ if (!ret)
+ cgroup_populate_dir(cgrp);
+
+ if (opts.release_agent)
+ strcpy(root->release_agent_path, opts.release_agent);
+ out_unlock:
+ if (opts.release_agent)
+ kfree(opts.release_agent);
+ mutex_unlock(&cgroup_mutex);
+ mutex_unlock(&cgrp->dentry->d_inode->i_mutex);
+ return ret;
+}
+
+static struct super_operations cgroup_ops = {
+ .statfs = simple_statfs,
+ .drop_inode = generic_delete_inode,
+ .show_options = cgroup_show_options,
+ .remount_fs = cgroup_remount,
+};
+
+static void init_cgroup_root(struct cgroupfs_root *root)
+{
+ struct cgroup *cgrp = &root->top_cgroup;
+ INIT_LIST_HEAD(&root->subsys_list);
+ INIT_LIST_HEAD(&root->root_list);
+ root->number_of_cgroups = 1;
+ cgrp->root = root;
+ cgrp->top_cgroup = cgrp;
+ INIT_LIST_HEAD(&cgrp->sibling);
+ INIT_LIST_HEAD(&cgrp->children);
+ INIT_LIST_HEAD(&cgrp->css_sets);
+ INIT_LIST_HEAD(&cgrp->release_list);
+}
+
+static int cgroup_test_super(struct super_block *sb, void *data)
+{
+ struct cgroupfs_root *new = data;
+ struct cgroupfs_root *root = sb->s_fs_info;
+
+ /* First check subsystems */
+ if (new->subsys_bits != root->subsys_bits)
+ return 0;
+
+ /* Next check flags */
+ if (new->flags != root->flags)
+ return 0;
+
+ return 1;
+}
+
+static int cgroup_set_super(struct super_block *sb, void *data)
+{
+ int ret;
+ struct cgroupfs_root *root = data;
+
+ ret = set_anon_super(sb, NULL);
+ if (ret)
+ return ret;
+
+ sb->s_fs_info = root;
+ root->sb = sb;
+
+ sb->s_blocksize = PAGE_CACHE_SIZE;
+ sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
+ sb->s_magic = CGROUP_SUPER_MAGIC;
+ sb->s_op = &cgroup_ops;
+
+ return 0;
+}
+
+static int cgroup_get_rootdir(struct super_block *sb)
+{
+ struct inode *inode =
+ cgroup_new_inode(S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR, sb);
+ struct dentry *dentry;
+
+ if (!inode)
+ return -ENOMEM;
+
+ inode->i_op = &simple_dir_inode_operations;
+ inode->i_fop = &simple_dir_operations;
+ inode->i_op = &cgroup_dir_inode_operations;
+ /* directories start off with i_nlink == 2 (for "." entry) */
+ inc_nlink(inode);
+ dentry = d_alloc_root(inode);
+ if (!dentry) {
+ iput(inode);
+ return -ENOMEM;
+ }
+ sb->s_root = dentry;
+ return 0;
+}
+
+static int cgroup_get_sb(struct file_system_type *fs_type,
+ int flags, const char *unused_dev_name,
+ void *data, struct vfsmount *mnt)
+{
+ struct cgroup_sb_opts opts;
+ int ret = 0;
+ struct super_block *sb;
+ struct cgroupfs_root *root;
+ struct list_head tmp_cg_links, *l;
+ INIT_LIST_HEAD(&tmp_cg_links);
+
+ /* First find the desired set of subsystems */
+ ret = parse_cgroupfs_options(data, &opts);
+ if (ret) {
+ if (opts.release_agent)
+ kfree(opts.release_agent);
+ return ret;
+ }
+
+ root = kzalloc(sizeof(*root), GFP_KERNEL);
+ if (!root)
+ return -ENOMEM;
+
+ init_cgroup_root(root);
+ root->subsys_bits = opts.subsys_bits;
+ root->flags = opts.flags;
+ if (opts.release_agent) {
+ strcpy(root->release_agent_path, opts.release_agent);
+ kfree(opts.release_agent);
+ }
+
+ sb = sget(fs_type, cgroup_test_super, cgroup_set_super, root);
+
+ if (IS_ERR(sb)) {
+ kfree(root);
+ return PTR_ERR(sb);
+ }
+
+ if (sb->s_fs_info != root) {
+ /* Reusing an existing superblock */
+ BUG_ON(sb->s_root == NULL);
+ kfree(root);
+ root = NULL;
+ } else {
+ /* New superblock */
+ struct cgroup *cgrp = &root->top_cgroup;
+ struct inode *inode;
+
+ BUG_ON(sb->s_root != NULL);
+
+ ret = cgroup_get_rootdir(sb);
+ if (ret)
+ goto drop_new_super;
+ inode = sb->s_root->d_inode;
+
+ mutex_lock(&inode->i_mutex);
+ mutex_lock(&cgroup_mutex);
+
+ /*
+ * We're accessing css_set_count without locking
+ * css_set_lock here, but that's OK - it can only be
+ * increased by someone holding cgroup_lock, and
+ * that's us. The worst that can happen is that we
+ * have some link structures left over
+ */
+ ret = allocate_cg_links(css_set_count, &tmp_cg_links);
+ if (ret) {
+ mutex_unlock(&cgroup_mutex);
+ mutex_unlock(&inode->i_mutex);
+ goto drop_new_super;
+ }
+
+ ret = rebind_subsystems(root, root->subsys_bits);
+ if (ret == -EBUSY) {
+ mutex_unlock(&cgroup_mutex);
+ mutex_unlock(&inode->i_mutex);
+ goto drop_new_super;
+ }
+
+ /* EBUSY should be the only error here */
+ BUG_ON(ret);
+
+ list_add(&root->root_list, &roots);
+ root_count++;
+
+ sb->s_root->d_fsdata = &root->top_cgroup;
+ root->top_cgroup.dentry = sb->s_root;
+
+ /* Link the top cgroup in this hierarchy into all
+ * the css_set objects */
+ write_lock(&css_set_lock);
+ l = &init_css_set.list;
+ do {
+ struct css_set *cg;
+ struct cg_cgroup_link *link;
+ cg = list_entry(l, struct css_set, list);
+ BUG_ON(list_empty(&tmp_cg_links));
+ link = list_entry(tmp_cg_links.next,
+ struct cg_cgroup_link,
+ cgrp_link_list);
+ list_del(&link->cgrp_link_list);
+ link->cg = cg;
+ list_add(&link->cgrp_link_list,
+ &root->top_cgroup.css_sets);
+ list_add(&link->cg_link_list, &cg->cg_links);
+ l = l->next;
+ } while (l != &init_css_set.list);
+ write_unlock(&css_set_lock);
+
+ free_cg_links(&tmp_cg_links);
+
+ BUG_ON(!list_empty(&cgrp->sibling));
+ BUG_ON(!list_empty(&cgrp->children));
+ BUG_ON(root->number_of_cgroups != 1);
+
+ cgroup_populate_dir(cgrp);
+ mutex_unlock(&inode->i_mutex);
+ mutex_unlock(&cgroup_mutex);
+ }
+
+ return simple_set_mnt(mnt, sb);
+
+ drop_new_super:
+ up_write(&sb->s_umount);
+ deactivate_super(sb);
+ free_cg_links(&tmp_cg_links);
+ return ret;
+}
+
+static void cgroup_kill_sb(struct super_block *sb) {
+ struct cgroupfs_root *root = sb->s_fs_info;
+ struct cgroup *cgrp = &root->top_cgroup;
+ int ret;
+
+ BUG_ON(!root);
+
+ BUG_ON(root->number_of_cgroups != 1);
+ BUG_ON(!list_empty(&cgrp->children));
+ BUG_ON(!list_empty(&cgrp->sibling));
+
+ mutex_lock(&cgroup_mutex);
+
+ /* Rebind all subsystems back to the default hierarchy */
+ ret = rebind_subsystems(root, 0);
+ /* Shouldn't be able to fail ... */
+ BUG_ON(ret);
+
+ /*
+ * Release all the links from css_sets to this hierarchy's
+ * root cgroup
+ */
+ write_lock(&css_set_lock);
+ while (!list_empty(&cgrp->css_sets)) {
+ struct cg_cgroup_link *link;
+ link = list_entry(cgrp->css_sets.next,
+ struct cg_cgroup_link, cgrp_link_list);
+ list_del(&link->cg_link_list);
+ list_del(&link->cgrp_link_list);
+ kfree(link);
+ }
+ write_unlock(&css_set_lock);
+
+ if (!list_empty(&root->root_list)) {
+ list_del(&root->root_list);
+ root_count--;
+ }
+ mutex_unlock(&cgroup_mutex);
+
+ kfree(root);
+ kill_litter_super(sb);
+}
+
+static struct file_system_type cgroup_fs_type = {
+ .name = "cgroup",
+ .get_sb = cgroup_get_sb,
+ .kill_sb = cgroup_kill_sb,
+};
+
+static inline struct cgroup *__d_cgrp(struct dentry *dentry)
+{
+ return dentry->d_fsdata;
+}
+
+static inline struct cftype *__d_cft(struct dentry *dentry)
+{
+ return dentry->d_fsdata;
+}
+
+/*
+ * Called with cgroup_mutex held. Writes path of cgroup into buf.
+ * Returns 0 on success, -errno on error.
+ */
+int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen)
+{
+ char *start;
+
+ if (cgrp == dummytop) {
+ /*
+ * Inactive subsystems have no dentry for their root
+ * cgroup
+ */
+ strcpy(buf, "/");
+ return 0;
+ }
+
+ start = buf + buflen;
+
+ *--start = '\0';
+ for (;;) {
+ int len = cgrp->dentry->d_name.len;
+ if ((start -= len) < buf)
+ return -ENAMETOOLONG;
+ memcpy(start, cgrp->dentry->d_name.name, len);
+ cgrp = cgrp->parent;
+ if (!cgrp)
+ break;
+ if (!cgrp->parent)
+ continue;
+ if (--start < buf)
+ return -ENAMETOOLONG;
+ *start = '/';
+ }
+ memmove(buf, start, buf + buflen - start);
+ return 0;
+}
+
+/*
+ * Return the first subsystem attached to a cgroup's hierarchy, and
+ * its subsystem id.
+ */
+
+static void get_first_subsys(const struct cgroup *cgrp,
+ struct cgroup_subsys_state **css, int *subsys_id)
+{
+ const struct cgroupfs_root *root = cgrp->root;
+ const struct cgroup_subsys *test_ss;
+ BUG_ON(list_empty(&root->subsys_list));
+ test_ss = list_entry(root->subsys_list.next,
+ struct cgroup_subsys, sibling);
+ if (css) {
+ *css = cgrp->subsys[test_ss->subsys_id];
+ BUG_ON(!*css);
+ }
+ if (subsys_id)
+ *subsys_id = test_ss->subsys_id;
+}
+
+/*
+ * Attach task 'tsk' to cgroup 'cgrp'
+ *
+ * Call holding cgroup_mutex. May take task_lock of
+ * the task 'pid' during call.
+ */
+static int attach_task(struct cgroup *cgrp, struct task_struct *tsk)
+{
+ int retval = 0;
+ struct cgroup_subsys *ss;
+ struct cgroup *oldcgrp;
+ struct css_set *cg = tsk->cgroups;
+ struct css_set *newcg;
+ struct cgroupfs_root *root = cgrp->root;
+ int subsys_id;
+
+ get_first_subsys(cgrp, NULL, &subsys_id);
+
+ /* Nothing to do if the task is already in that cgroup */
+ oldcgrp = task_cgroup(tsk, subsys_id);
+ if (cgrp == oldcgrp)
+ return 0;
+
+ for_each_subsys(root, ss) {
+ if (ss->can_attach) {
+ retval = ss->can_attach(ss, cgrp, tsk);
+ if (retval) {
+ return retval;
+ }
+ }
+ }
+
+ /*
+ * Locate or allocate a new css_set for this task,
+ * based on its final set of cgroups
+ */
+ newcg = find_css_set(cg, cgrp);
+ if (!newcg) {
+ return -ENOMEM;
+ }
+
+ task_lock(tsk);
+ if (tsk->flags & PF_EXITING) {
+ task_unlock(tsk);
+ put_css_set(newcg);
+ return -ESRCH;
+ }
+ rcu_assign_pointer(tsk->cgroups, newcg);
+ task_unlock(tsk);
+
+ /* Update the css_set linked lists if we're using them */
+ write_lock(&css_set_lock);
+ if (!list_empty(&tsk->cg_list)) {
+ list_del(&tsk->cg_list);
+ list_add(&tsk->cg_list, &newcg->tasks);
+ }
+ write_unlock(&css_set_lock);
+
+ for_each_subsys(root, ss) {
+ if (ss->attach) {
+ ss->attach(ss, cgrp, oldcgrp, tsk);
+ }
+ }
+ set_bit(CGRP_RELEASABLE, &oldcgrp->flags);
+ synchronize_rcu();
+ put_css_set(cg);
+ return 0;
+}
+
+/*
+ * Attach task with pid 'pid' to cgroup 'cgrp'. Call with
+ * cgroup_mutex, may take task_lock of task
+ */
+static int attach_task_by_pid(struct cgroup *cgrp, char *pidbuf)
+{
+ pid_t pid;
+ struct task_struct *tsk;
+ int ret;
+
+ if (sscanf(pidbuf, "%d", &pid) != 1)
+ return -EIO;
+
+ if (pid) {
+ rcu_read_lock();
+ tsk = find_task_by_pid(pid);
+ if (!tsk || tsk->flags & PF_EXITING) {
+ rcu_read_unlock();
+ return -ESRCH;
+ }
+ get_task_struct(tsk);
+ rcu_read_unlock();
+
+ if ((current->euid) && (current->euid != tsk->uid)
+ && (current->euid != tsk->suid)) {
+ put_task_struct(tsk);
+ return -EACCES;
+ }
+ } else {
+ tsk = current;
+ get_task_struct(tsk);
+ }
+
+ ret = attach_task(cgrp, tsk);
+ put_task_struct(tsk);
+ return ret;
+}
+
+/* The various types of files and directories in a cgroup file system */
+
+enum cgroup_filetype {
+ FILE_ROOT,
+ FILE_DIR,
+ FILE_TASKLIST,
+ FILE_NOTIFY_ON_RELEASE,
+ FILE_RELEASABLE,
+ FILE_RELEASE_AGENT,
+};
+
+static ssize_t cgroup_write_uint(struct cgroup *cgrp, struct cftype *cft,
+ struct file *file,
+ const char __user *userbuf,
+ size_t nbytes, loff_t *unused_ppos)
+{
+ char buffer[64];
+ int retval = 0;
+ u64 val;
+ char *end;
+
+ if (!nbytes)
+ return -EINVAL;
+ if (nbytes >= sizeof(buffer))
+ return -E2BIG;
+ if (copy_from_user(buffer, userbuf, nbytes))
+ return -EFAULT;
+
+ buffer[nbytes] = 0; /* nul-terminate */
+
+ /* strip newline if necessary */
+ if (nbytes && (buffer[nbytes-1] == '\n'))
+ buffer[nbytes-1] = 0;
+ val = simple_strtoull(buffer, &end, 0);
+ if (*end)
+ return -EINVAL;
+
+ /* Pass to subsystem */
+ retval = cft->write_uint(cgrp, cft, val);
+ if (!retval)
+ retval = nbytes;
+ return retval;
+}
+
+static ssize_t cgroup_common_file_write(struct cgroup *cgrp,
+ struct cftype *cft,
+ struct file *file,
+ const char __user *userbuf,
+ size_t nbytes, loff_t *unused_ppos)
+{
+ enum cgroup_filetype type = cft->private;
+ char *buffer;
+ int retval = 0;
+
+ if (nbytes >= PATH_MAX)
+ return -E2BIG;
+
+ /* +1 for nul-terminator */
+ buffer = kmalloc(nbytes + 1, GFP_KERNEL);
+ if (buffer == NULL)
+ return -ENOMEM;
+
+ if (copy_from_user(buffer, userbuf, nbytes)) {
+ retval = -EFAULT;
+ goto out1;
+ }
+ buffer[nbytes] = 0; /* nul-terminate */
+
+ mutex_lock(&cgroup_mutex);
+
+ if (cgroup_is_removed(cgrp)) {
+ retval = -ENODEV;
+ goto out2;
+ }
+
+ switch (type) {
+ case FILE_TASKLIST:
+ retval = attach_task_by_pid(cgrp, buffer);
+ break;
+ case FILE_NOTIFY_ON_RELEASE:
+ clear_bit(CGRP_RELEASABLE, &cgrp->flags);
+ if (simple_strtoul(buffer, NULL, 10) != 0)
+ set_bit(CGRP_NOTIFY_ON_RELEASE, &cgrp->flags);
+ else
+ clear_bit(CGRP_NOTIFY_ON_RELEASE, &cgrp->flags);
+ break;
+ case FILE_RELEASE_AGENT:
+ {
+ struct cgroupfs_root *root = cgrp->root;
+ /* Strip trailing newline */
+ if (nbytes && (buffer[nbytes-1] == '\n')) {
+ buffer[nbytes-1] = 0;
+ }
+ if (nbytes < sizeof(root->release_agent_path)) {
+ /* We never write anything other than '\0'
+ * into the last char of release_agent_path,
+ * so it always remains a NUL-terminated
+ * string */
+ strncpy(root->release_agent_path, buffer, nbytes);
+ root->release_agent_path[nbytes] = 0;
+ } else {
+ retval = -ENOSPC;
+ }
+ break;
+ }
+ default:
+ retval = -EINVAL;
+ goto out2;
+ }
+
+ if (retval == 0)
+ retval = nbytes;
+out2:
+ mutex_unlock(&cgroup_mutex);
+out1:
+ kfree(buffer);
+ return retval;
+}
+
+static ssize_t cgroup_file_write(struct file *file, const char __user *buf,
+ size_t nbytes, loff_t *ppos)
+{
+ struct cftype *cft = __d_cft(file->f_dentry);
+ struct cgroup *cgrp = __d_cgrp(file->f_dentry->d_parent);
+
+ if (!cft)
+ return -ENODEV;
+ if (cft->write)
+ return cft->write(cgrp, cft, file, buf, nbytes, ppos);
+ if (cft->write_uint)
+ return cgroup_write_uint(cgrp, cft, file, buf, nbytes, ppos);
+ return -EINVAL;
+}
+
+static ssize_t cgroup_read_uint(struct cgroup *cgrp, struct cftype *cft,
+ struct file *file,
+ char __user *buf, size_t nbytes,
+ loff_t *ppos)
+{
+ char tmp[64];
+ u64 val = cft->read_uint(cgrp, cft);
+ int len = sprintf(tmp, "%llu\n", (unsigned long long) val);
+
+ return simple_read_from_buffer(buf, nbytes, ppos, tmp, len);
+}
+
+static ssize_t cgroup_common_file_read(struct cgroup *cgrp,
+ struct cftype *cft,
+ struct file *file,
+ char __user *buf,
+ size_t nbytes, loff_t *ppos)
+{
+ enum cgroup_filetype type = cft->private;
+ char *page;
+ ssize_t retval = 0;
+ char *s;
+
+ if (!(page = (char *)__get_free_page(GFP_KERNEL)))
+ return -ENOMEM;
+
+ s = page;
+
+ switch (type) {
+ case FILE_RELEASE_AGENT:
+ {
+ struct cgroupfs_root *root;
+ size_t n;
+ mutex_lock(&cgroup_mutex);
+ root = cgrp->root;
+ n = strnlen(root->release_agent_path,
+ sizeof(root->release_agent_path));
+ n = min(n, (size_t) PAGE_SIZE);
+ strncpy(s, root->release_agent_path, n);
+ mutex_unlock(&cgroup_mutex);
+ s += n;
+ break;
+ }
+ default:
+ retval = -EINVAL;
+ goto out;
+ }
+ *s++ = '\n';
+
+ retval = simple_read_from_buffer(buf, nbytes, ppos, page, s - page);
+out:
+ free_page((unsigned long)page);
+ return retval;
+}
+
+static ssize_t cgroup_file_read(struct file *file, char __user *buf,
+ size_t nbytes, loff_t *ppos)
+{
+ struct cftype *cft = __d_cft(file->f_dentry);
+ struct cgroup *cgrp = __d_cgrp(file->f_dentry->d_parent);
+
+ if (!cft)
+ return -ENODEV;
+
+ if (cft->read)
+ return cft->read(cgrp, cft, file, buf, nbytes, ppos);
+ if (cft->read_uint)
+ return cgroup_read_uint(cgrp, cft, file, buf, nbytes, ppos);
+ return -EINVAL;
+}
+
+static int cgroup_file_open(struct inode *inode, struct file *file)
+{
+ int err;
+ struct cftype *cft;
+
+ err = generic_file_open(inode, file);
+ if (err)
+ return err;
+
+ cft = __d_cft(file->f_dentry);
+ if (!cft)
+ return -ENODEV;
+ if (cft->open)
+ err = cft->open(inode, file);
+ else
+ err = 0;
+
+ return err;
+}
+
+static int cgroup_file_release(struct inode *inode, struct file *file)
+{
+ struct cftype *cft = __d_cft(file->f_dentry);
+ if (cft->release)
+ return cft->release(inode, file);
+ return 0;
+}
+
+/*
+ * cgroup_rename - Only allow simple rename of directories in place.
+ */
+static int cgroup_rename(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry)
+{
+ if (!S_ISDIR(old_dentry->d_inode->i_mode))
+ return -ENOTDIR;
+ if (new_dentry->d_inode)
+ return -EEXIST;
+ if (old_dir != new_dir)
+ return -EIO;
+ return simple_rename(old_dir, old_dentry, new_dir, new_dentry);
+}
+
+static struct file_operations cgroup_file_operations = {
+ .read = cgroup_file_read,
+ .write = cgroup_file_write,
+ .llseek = generic_file_llseek,
+ .open = cgroup_file_open,
+ .release = cgroup_file_release,
+};
+
+static struct inode_operations cgroup_dir_inode_operations = {
+ .lookup = simple_lookup,
+ .mkdir = cgroup_mkdir,
+ .rmdir = cgroup_rmdir,
+ .rename = cgroup_rename,
+};
+
+static int cgroup_create_file(struct dentry *dentry, int mode,
+ struct super_block *sb)
+{
+ static struct dentry_operations cgroup_dops = {
+ .d_iput = cgroup_diput,
+ };
+
+ struct inode *inode;
+
+ if (!dentry)
+ return -ENOENT;
+ if (dentry->d_inode)
+ return -EEXIST;
+
+ inode = cgroup_new_inode(mode, sb);
+ if (!inode)
+ return -ENOMEM;
+
+ if (S_ISDIR(mode)) {
+ inode->i_op = &cgroup_dir_inode_operations;
+ inode->i_fop = &simple_dir_operations;
+
+ /* start off with i_nlink == 2 (for "." entry) */
+ inc_nlink(inode);
+
+ /* start with the directory inode held, so that we can
+ * populate it without racing with another mkdir */
+ mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD);
+ } else if (S_ISREG(mode)) {
+ inode->i_size = 0;
+ inode->i_fop = &cgroup_file_operations;
+ }
+ dentry->d_op = &cgroup_dops;
+ d_instantiate(dentry, inode);
+ dget(dentry); /* Extra count - pin the dentry in core */
+ return 0;
+}
+
+/*
+ * cgroup_create_dir - create a directory for an object.
+ * cgrp: the cgroup we create the directory for.
+ * It must have a valid ->parent field
+ * And we are going to fill its ->dentry field.
+ * dentry: dentry of the new cgroup
+ * mode: mode to set on new directory.
+ */
+static int cgroup_create_dir(struct cgroup *cgrp, struct dentry *dentry,
+ int mode)
+{
+ struct dentry *parent;
+ int error = 0;
+
+ parent = cgrp->parent->dentry;
+ error = cgroup_create_file(dentry, S_IFDIR | mode, cgrp->root->sb);
+ if (!error) {
+ dentry->d_fsdata = cgrp;
+ inc_nlink(parent->d_inode);
+ cgrp->dentry = dentry;
+ dget(dentry);
+ }
+ dput(dentry);
+
+ return error;
+}
+
+int cgroup_add_file(struct cgroup *cgrp,
+ struct cgroup_subsys *subsys,
+ const struct cftype *cft)
+{
+ struct dentry *dir = cgrp->dentry;
+ struct dentry *dentry;
+ int error;
+
+ char name[MAX_CGROUP_TYPE_NAMELEN + MAX_CFTYPE_NAME + 2] = { 0 };
+ if (subsys && !test_bit(ROOT_NOPREFIX, &cgrp->root->flags)) {
+ strcpy(name, subsys->name);
+ strcat(name, ".");
+ }
+ strcat(name, cft->name);
+ BUG_ON(!mutex_is_locked(&dir->d_inode->i_mutex));
+ dentry = lookup_one_len(name, dir, strlen(name));
+ if (!IS_ERR(dentry)) {
+ error = cgroup_create_file(dentry, 0644 | S_IFREG,
+ cgrp->root->sb);
+ if (!error)
+ dentry->d_fsdata = (void *)cft;
+ dput(dentry);
+ } else
+ error = PTR_ERR(dentry);
+ return error;
+}
+
+int cgroup_add_files(struct cgroup *cgrp,
+ struct cgroup_subsys *subsys,
+ const struct cftype cft[],
+ int count)
+{
+ int i, err;
+ for (i = 0; i < count; i++) {
+ err = cgroup_add_file(cgrp, subsys, &cft[i]);
+ if (err)
+ return err;
+ }
+ return 0;
+}
+
+/* Count the number of tasks in a cgroup. */
+
+int cgroup_task_count(const struct cgroup *cgrp)
+{
+ int count = 0;
+ struct list_head *l;
+
+ read_lock(&css_set_lock);
+ l = cgrp->css_sets.next;
+ while (l != &cgrp->css_sets) {
+ struct cg_cgroup_link *link =
+ list_entry(l, struct cg_cgroup_link, cgrp_link_list);
+ count += atomic_read(&link->cg->ref.refcount);
+ l = l->next;
+ }
+ read_unlock(&css_set_lock);
+ return count;
+}
+
+/*
+ * Advance a list_head iterator. The iterator should be positioned at
+ * the start of a css_set
+ */
+static void cgroup_advance_iter(struct cgroup *cgrp,
+ struct cgroup_iter *it)
+{
+ struct list_head *l = it->cg_link;
+ struct cg_cgroup_link *link;
+ struct css_set *cg;
+
+ /* Advance to the next non-empty css_set */
+ do {
+ l = l->next;
+ if (l == &cgrp->css_sets) {
+ it->cg_link = NULL;
+ return;
+ }
+ link = list_entry(l, struct cg_cgroup_link, cgrp_link_list);
+ cg = link->cg;
+ } while (list_empty(&cg->tasks));
+ it->cg_link = l;
+ it->task = cg->tasks.next;
+}
+
+void cgroup_iter_start(struct cgroup *cgrp, struct cgroup_iter *it)
+{
+ /*
+ * The first time anyone tries to iterate across a cgroup,
+ * we need to enable the list linking each css_set to its
+ * tasks, and fix up all existing tasks.
+ */
+ if (!use_task_css_set_links) {
+ struct task_struct *p, *g;
+ write_lock(&css_set_lock);
+ use_task_css_set_links = 1;
+ do_each_thread(g, p) {
+ task_lock(p);
+ if (list_empty(&p->cg_list))
+ list_add(&p->cg_list, &p->cgroups->tasks);
+ task_unlock(p);
+ } while_each_thread(g, p);
+ write_unlock(&css_set_lock);
+ }
+ read_lock(&css_set_lock);
+ it->cg_link = &cgrp->css_sets;
+ cgroup_advance_iter(cgrp, it);
+}
+
+struct task_struct *cgroup_iter_next(struct cgroup *cgrp,
+ struct cgroup_iter *it)
+{
+ struct task_struct *res;
+ struct list_head *l = it->task;
+
+ /* If the iterator cg is NULL, we have no tasks */
+ if (!it->cg_link)
+ return NULL;
+ res = list_entry(l, struct task_struct, cg_list);
+ /* Advance iterator to find next entry */
+ l = l->next;
+ if (l == &res->cgroups->tasks) {
+ /* We reached the end of this task list - move on to
+ * the next cg_cgroup_link */
+ cgroup_advance_iter(cgrp, it);
+ } else {
+ it->task = l;
+ }
+ return res;
+}
+
+void cgroup_iter_end(struct cgroup *cgrp, struct cgroup_iter *it)
+{
+ read_unlock(&css_set_lock);
+}
+
+/*
+ * Stuff for reading the 'tasks' file.
+ *
+ * Reading this file can return large amounts of data if a cgroup has
+ * *lots* of attached tasks. So it may need several calls to read(),
+ * but we cannot guarantee that the information we produce is correct
+ * unless we produce it entirely atomically.
+ *
+ * Upon tasks file open(), a struct ctr_struct is allocated, that
+ * will have a pointer to an array (also allocated here). The struct
+ * ctr_struct * is stored in file->private_data. Its resources will
+ * be freed by release() when the file is closed. The array is used
+ * to sprintf the PIDs and then used by read().
+ */
+struct ctr_struct {
+ char *buf;
+ int bufsz;
+};
+
+/*
+ * Load into 'pidarray' up to 'npids' of the tasks using cgroup
+ * 'cgrp'. Return actual number of pids loaded. No need to
+ * task_lock(p) when reading out p->cgroup, since we're in an RCU
+ * read section, so the css_set can't go away, and is
+ * immutable after creation.
+ */
+static int pid_array_load(pid_t *pidarray, int npids, struct cgroup *cgrp)
+{
+ int n = 0;
+ struct cgroup_iter it;
+ struct task_struct *tsk;
+ cgroup_iter_start(cgrp, &it);
+ while ((tsk = cgroup_iter_next(cgrp, &it))) {
+ if (unlikely(n == npids))
+ break;
+ pidarray[n++] = task_pid_nr(tsk);
+ }
+ cgroup_iter_end(cgrp, &it);
+ return n;
+}
+
+/**
+ * Build and fill cgroupstats so that taskstats can export it to user
+ * space.
+ *
+ * @stats: cgroupstats to fill information into
+ * @dentry: A dentry entry belonging to the cgroup for which stats have
+ * been requested.
+ */
+int cgroupstats_build(struct cgroupstats *stats, struct dentry *dentry)
+{
+ int ret = -EINVAL;
+ struct cgroup *cgrp;
+ struct cgroup_iter it;
+ struct task_struct *tsk;
+ /*
+ * Validate dentry by checking the superblock operations
+ */
+ if (dentry->d_sb->s_op != &cgroup_ops)
+ goto err;
+
+ ret = 0;
+ cgrp = dentry->d_fsdata;
+ rcu_read_lock();
+
+ cgroup_iter_start(cgrp, &it);
+ while ((tsk = cgroup_iter_next(cgrp, &it))) {
+ switch (tsk->state) {
+ case TASK_RUNNING:
+ stats->nr_running++;
+ break;
+ case TASK_INTERRUPTIBLE:
+ stats->nr_sleeping++;
+ break;
+ case TASK_UNINTERRUPTIBLE:
+ stats->nr_uninterruptible++;
+ break;
+ case TASK_STOPPED:
+ stats->nr_stopped++;
+ break;
+ default:
+ if (delayacct_is_task_waiting_on_io(tsk))
+ stats->nr_io_wait++;
+ break;
+ }
+ }
+ cgroup_iter_end(cgrp, &it);
+
+ rcu_read_unlock();
+err:
+ return ret;
+}
+
+static int cmppid(const void *a, const void *b)
+{
+ return *(pid_t *)a - *(pid_t *)b;
+}
+
+/*
+ * Convert array 'a' of 'npids' pid_t's to a string of newline separated
+ * decimal pids in 'buf'. Don't write more than 'sz' chars, but return
+ * count 'cnt' of how many chars would be written if buf were large enough.
+ */
+static int pid_array_to_buf(char *buf, int sz, pid_t *a, int npids)
+{
+ int cnt = 0;
+ int i;
+
+ for (i = 0; i < npids; i++)
+ cnt += snprintf(buf + cnt, max(sz - cnt, 0), "%d\n", a[i]);
+ return cnt;
+}
+
+/*
+ * Handle an open on 'tasks' file. Prepare a buffer listing the
+ * process id's of tasks currently attached to the cgroup being opened.
+ *
+ * Does not require any specific cgroup mutexes, and does not take any.
+ */
+static int cgroup_tasks_open(struct inode *unused, struct file *file)
+{
+ struct cgroup *cgrp = __d_cgrp(file->f_dentry->d_parent);
+ struct ctr_struct *ctr;
+ pid_t *pidarray;
+ int npids;
+ char c;
+
+ if (!(file->f_mode & FMODE_READ))
+ return 0;
+
+ ctr = kmalloc(sizeof(*ctr), GFP_KERNEL);
+ if (!ctr)
+ goto err0;
+
+ /*
+ * If cgroup gets more users after we read count, we won't have
+ * enough space - tough. This race is indistinguishable to the
+ * caller from the case that the additional cgroup users didn't
+ * show up until sometime later on.
+ */
+ npids = cgroup_task_count(cgrp);
+ if (npids) {
+ pidarray = kmalloc(npids * sizeof(pid_t), GFP_KERNEL);
+ if (!pidarray)
+ goto err1;
+
+ npids = pid_array_load(pidarray, npids, cgrp);
+ sort(pidarray, npids, sizeof(pid_t), cmppid, NULL);
+
+ /* Call pid_array_to_buf() twice, first just to get bufsz */
+ ctr->bufsz = pid_array_to_buf(&c, sizeof(c), pidarray, npids) + 1;
+ ctr->buf = kmalloc(ctr->bufsz, GFP_KERNEL);
+ if (!ctr->buf)
+ goto err2;
+ ctr->bufsz = pid_array_to_buf(ctr->buf, ctr->bufsz, pidarray, npids);
+
+ kfree(pidarray);
+ } else {
+ ctr->buf = 0;
+ ctr->bufsz = 0;
+ }
+ file->private_data = ctr;
+ return 0;
+
+err2:
+ kfree(pidarray);
+err1:
+ kfree(ctr);
+err0:
+ return -ENOMEM;
+}
+
+static ssize_t cgroup_tasks_read(struct cgroup *cgrp,
+ struct cftype *cft,
+ struct file *file, char __user *buf,
+ size_t nbytes, loff_t *ppos)
+{
+ struct ctr_struct *ctr = file->private_data;
+
+ return simple_read_from_buffer(buf, nbytes, ppos, ctr->buf, ctr->bufsz);
+}
+
+static int cgroup_tasks_release(struct inode *unused_inode,
+ struct file *file)
+{
+ struct ctr_struct *ctr;
+
+ if (file->f_mode & FMODE_READ) {
+ ctr = file->private_data;
+ kfree(ctr->buf);
+ kfree(ctr);
+ }
+ return 0;
+}
+
+static u64 cgroup_read_notify_on_release(struct cgroup *cgrp,
+ struct cftype *cft)
+{
+ return notify_on_release(cgrp);
+}
+
+static u64 cgroup_read_releasable(struct cgroup *cgrp, struct cftype *cft)
+{
+ return test_bit(CGRP_RELEASABLE, &cgrp->flags);
+}
+
+/*
+ * for the common functions, 'private' gives the type of file
+ */
+static struct cftype files[] = {
+ {
+ .name = "tasks",
+ .open = cgroup_tasks_open,
+ .read = cgroup_tasks_read,
+ .write = cgroup_common_file_write,
+ .release = cgroup_tasks_release,
+ .private = FILE_TASKLIST,
+ },
+
+ {
+ .name = "notify_on_release",
+ .read_uint = cgroup_read_notify_on_release,
+ .write = cgroup_common_file_write,
+ .private = FILE_NOTIFY_ON_RELEASE,
+ },
+
+ {
+ .name = "releasable",
+ .read_uint = cgroup_read_releasable,
+ .private = FILE_RELEASABLE,
+ }
+};
+
+static struct cftype cft_release_agent = {
+ .name = "release_agent",
+ .read = cgroup_common_file_read,
+ .write = cgroup_common_file_write,
+ .private = FILE_RELEASE_AGENT,
+};
+
+static int cgroup_populate_dir(struct cgroup *cgrp)
+{
+ int err;
+ struct cgroup_subsys *ss;
+
+ /* First clear out any existing files */
+ cgroup_clear_directory(cgrp->dentry);
+
+ err = cgroup_add_files(cgrp, NULL, files, ARRAY_SIZE(files));
+ if (err < 0)
+ return err;
+
+ if (cgrp == cgrp->top_cgroup) {
+ if ((err = cgroup_add_file(cgrp, NULL, &cft_release_agent)) < 0)
+ return err;
+ }
+
+ for_each_subsys(cgrp->root, ss) {
+ if (ss->populate && (err = ss->populate(ss, cgrp)) < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+static void init_cgroup_css(struct cgroup_subsys_state *css,
+ struct cgroup_subsys *ss,
+ struct cgroup *cgrp)
+{
+ css->cgroup = cgrp;
+ atomic_set(&css->refcnt, 0);
+ css->flags = 0;
+ if (cgrp == dummytop)
+ set_bit(CSS_ROOT, &css->flags);
+ BUG_ON(cgrp->subsys[ss->subsys_id]);
+ cgrp->subsys[ss->subsys_id] = css;
+}
+
+/*
+ * cgroup_create - create a cgroup
+ * parent: cgroup that will be parent of the new cgroup.
+ * name: name of the new cgroup. Will be strcpy'ed.
+ * mode: mode to set on new inode
+ *
+ * Must be called with the mutex on the parent inode held
+ */
+
+static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
+ int mode)
+{
+ struct cgroup *cgrp;
+ struct cgroupfs_root *root = parent->root;
+ int err = 0;
+ struct cgroup_subsys *ss;
+ struct super_block *sb = root->sb;
+
+ cgrp = kzalloc(sizeof(*cgrp), GFP_KERNEL);
+ if (!cgrp)
+ return -ENOMEM;
+
+ /* Grab a reference on the superblock so the hierarchy doesn't
+ * get deleted on unmount if there are child cgroups. This
+ * can be done outside cgroup_mutex, since the sb can't
+ * disappear while someone has an open control file on the
+ * fs */
+ atomic_inc(&sb->s_active);
+
+ mutex_lock(&cgroup_mutex);
+
+ cgrp->flags = 0;
+ INIT_LIST_HEAD(&cgrp->sibling);
+ INIT_LIST_HEAD(&cgrp->children);
+ INIT_LIST_HEAD(&cgrp->css_sets);
+ INIT_LIST_HEAD(&cgrp->release_list);
+
+ cgrp->parent = parent;
+ cgrp->root = parent->root;
+ cgrp->top_cgroup = parent->top_cgroup;
+
+ for_each_subsys(root, ss) {
+ struct cgroup_subsys_state *css = ss->create(ss, cgrp);
+ if (IS_ERR(css)) {
+ err = PTR_ERR(css);
+ goto err_destroy;
+ }
+ init_cgroup_css(css, ss, cgrp);
+ }
+
+ list_add(&cgrp->sibling, &cgrp->parent->children);
+ root->number_of_cgroups++;
+
+ err = cgroup_create_dir(cgrp, dentry, mode);
+ if (err < 0)
+ goto err_remove;
+
+ /* The cgroup directory was pre-locked for us */
+ BUG_ON(!mutex_is_locked(&cgrp->dentry->d_inode->i_mutex));
+
+ err = cgroup_populate_dir(cgrp);
+ /* If err < 0, we have a half-filled directory - oh well ;) */
+
+ mutex_unlock(&cgroup_mutex);
+ mutex_unlock(&cgrp->dentry->d_inode->i_mutex);
+
+ return 0;
+
+ err_remove:
+
+ list_del(&cgrp->sibling);
+ root->number_of_cgroups--;
+
+ err_destroy:
+
+ for_each_subsys(root, ss) {
+ if (cgrp->subsys[ss->subsys_id])
+ ss->destroy(ss, cgrp);
+ }
+
+ mutex_unlock(&cgroup_mutex);
+
+ /* Release the reference count that we took on the superblock */
+ deactivate_super(sb);
+
+ kfree(cgrp);
+ return err;
+}
+
+static int cgroup_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+{
+ struct cgroup *c_parent = dentry->d_parent->d_fsdata;
+
+ /* the vfs holds inode->i_mutex already */
+ return cgroup_create(c_parent, dentry, mode | S_IFDIR);
+}
+
+static inline int cgroup_has_css_refs(struct cgroup *cgrp)
+{
+ /* Check the reference count on each subsystem. Since we
+ * already established that there are no tasks in the
+ * cgroup, if the css refcount is also 0, then there should
+ * be no outstanding references, so the subsystem is safe to
+ * destroy. We scan across all subsystems rather than using
+ * the per-hierarchy linked list of mounted subsystems since
+ * we can be called via check_for_release() with no
+ * synchronization other than RCU, and the subsystem linked
+ * list isn't RCU-safe */
+ int i;
+ for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
+ struct cgroup_subsys *ss = subsys[i];
+ struct cgroup_subsys_state *css;
+ /* Skip subsystems not in this hierarchy */
+ if (ss->root != cgrp->root)
+ continue;
+ css = cgrp->subsys[ss->subsys_id];
+ /* When called from check_for_release() it's possible
+ * that by this point the cgroup has been removed
+ * and the css deleted. But a false-positive doesn't
+ * matter, since it can only happen if the cgroup
+ * has been deleted and hence no longer needs the
+ * release agent to be called anyway. */
+ if (css && atomic_read(&css->refcnt)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry)
+{
+ struct cgroup *cgrp = dentry->d_fsdata;
+ struct dentry *d;
+ struct cgroup *parent;
+ struct cgroup_subsys *ss;
+ struct super_block *sb;
+ struct cgroupfs_root *root;
+
+ /* the vfs holds both inode->i_mutex already */
+
+ mutex_lock(&cgroup_mutex);
+ if (atomic_read(&cgrp->count) != 0) {
+ mutex_unlock(&cgroup_mutex);
+ return -EBUSY;
+ }
+ if (!list_empty(&cgrp->children)) {
+ mutex_unlock(&cgroup_mutex);
+ return -EBUSY;
+ }
+
+ parent = cgrp->parent;
+ root = cgrp->root;
+ sb = root->sb;
+
+ if (cgroup_has_css_refs(cgrp)) {
+ mutex_unlock(&cgroup_mutex);
+ return -EBUSY;
+ }
+
+ for_each_subsys(root, ss) {
+ if (cgrp->subsys[ss->subsys_id])
+ ss->destroy(ss, cgrp);
+ }
+
+ spin_lock(&release_list_lock);
+ set_bit(CGRP_REMOVED, &cgrp->flags);
+ if (!list_empty(&cgrp->release_list))
+ list_del(&cgrp->release_list);
+ spin_unlock(&release_list_lock);
+ /* delete my sibling from parent->children */
+ list_del(&cgrp->sibling);
+ spin_lock(&cgrp->dentry->d_lock);
+ d = dget(cgrp->dentry);
+ cgrp->dentry = NULL;
+ spin_unlock(&d->d_lock);
+
+ cgroup_d_remove_dir(d);
+ dput(d);
+ root->number_of_cgroups--;
+
+ set_bit(CGRP_RELEASABLE, &parent->flags);
+ check_for_release(parent);
+
+ mutex_unlock(&cgroup_mutex);
+ /* Drop the active superblock reference that we took when we
+ * created the cgroup */
+ deactivate_super(sb);
+ return 0;
+}
+
+static void cgroup_init_subsys(struct cgroup_subsys *ss)
+{
+ struct cgroup_subsys_state *css;
+ struct list_head *l;
+
+ printk(KERN_INFO "Initializing cgroup subsys %s\n", ss->name);
+
+ /* Create the top cgroup state for this subsystem */
+ ss->root = &rootnode;
+ css = ss->create(ss, dummytop);
+ /* We don't handle early failures gracefully */
+ BUG_ON(IS_ERR(css));
+ init_cgroup_css(css, ss, dummytop);
+
+ /* Update all cgroup groups to contain a subsys
+ * pointer to this state - since the subsystem is
+ * newly registered, all tasks and hence all cgroup
+ * groups are in the subsystem's top cgroup. */
+ write_lock(&css_set_lock);
+ l = &init_css_set.list;
+ do {
+ struct css_set *cg =
+ list_entry(l, struct css_set, list);
+ cg->subsys[ss->subsys_id] = dummytop->subsys[ss->subsys_id];
+ l = l->next;
+ } while (l != &init_css_set.list);
+ write_unlock(&css_set_lock);
+
+ /* If this subsystem requested that it be notified with fork
+ * events, we should send it one now for every process in the
+ * system */
+ if (ss->fork) {
+ struct task_struct *g, *p;
+
+ read_lock(&tasklist_lock);
+ do_each_thread(g, p) {
+ ss->fork(ss, p);
+ } while_each_thread(g, p);
+ read_unlock(&tasklist_lock);
+ }
+
+ need_forkexit_callback |= ss->fork || ss->exit;
+
+ ss->active = 1;
+}
+
+/**
+ * cgroup_init_early - initialize cgroups at system boot, and
+ * initialize any subsystems that request early init.
+ */
+int __init cgroup_init_early(void)
+{
+ int i;
+ kref_init(&init_css_set.ref);
+ kref_get(&init_css_set.ref);
+ INIT_LIST_HEAD(&init_css_set.list);
+ INIT_LIST_HEAD(&init_css_set.cg_links);
+ INIT_LIST_HEAD(&init_css_set.tasks);
+ css_set_count = 1;
+ init_cgroup_root(&rootnode);
+ list_add(&rootnode.root_list, &roots);
+ root_count = 1;
+ init_task.cgroups = &init_css_set;
+
+ init_css_set_link.cg = &init_css_set;
+ list_add(&init_css_set_link.cgrp_link_list,
+ &rootnode.top_cgroup.css_sets);
+ list_add(&init_css_set_link.cg_link_list,
+ &init_css_set.cg_links);
+
+ for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
+ struct cgroup_subsys *ss = subsys[i];
+
+ BUG_ON(!ss->name);
+ BUG_ON(strlen(ss->name) > MAX_CGROUP_TYPE_NAMELEN);
+ BUG_ON(!ss->create);
+ BUG_ON(!ss->destroy);
+ if (ss->subsys_id != i) {
+ printk(KERN_ERR "cgroup: Subsys %s id == %d\n",
+ ss->name, ss->subsys_id);
+ BUG();
+ }
+
+ if (ss->early_init)
+ cgroup_init_subsys(ss);
+ }
+ return 0;
+}
+
+/**
+ * cgroup_init - register cgroup filesystem and /proc file, and
+ * initialize any subsystems that didn't request early init.
+ */
+int __init cgroup_init(void)
+{
+ int err;
+ int i;
+ struct proc_dir_entry *entry;
+
+ err = bdi_init(&cgroup_backing_dev_info);
+ if (err)
+ return err;
+
+ for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
+ struct cgroup_subsys *ss = subsys[i];
+ if (!ss->early_init)
+ cgroup_init_subsys(ss);
+ }
+
+ err = register_filesystem(&cgroup_fs_type);
+ if (err < 0)
+ goto out;
+
+ entry = create_proc_entry("cgroups", 0, NULL);
+ if (entry)
+ entry->proc_fops = &proc_cgroupstats_operations;
+
+out:
+ if (err)
+ bdi_destroy(&cgroup_backing_dev_info);
+
+ return err;
+}
+
+/*
+ * proc_cgroup_show()
+ * - Print task's cgroup paths into seq_file, one line for each hierarchy
+ * - Used for /proc/<pid>/cgroup.
+ * - No need to task_lock(tsk) on this tsk->cgroup reference, as it
+ * doesn't really matter if tsk->cgroup changes after we read it,
+ * and we take cgroup_mutex, keeping attach_task() from changing it
+ * anyway. No need to check that tsk->cgroup != NULL, thanks to
+ * the_top_cgroup_hack in cgroup_exit(), which sets an exiting tasks
+ * cgroup to top_cgroup.
+ */
+
+/* TODO: Use a proper seq_file iterator */
+static int proc_cgroup_show(struct seq_file *m, void *v)
+{
+ struct pid *pid;
+ struct task_struct *tsk;
+ char *buf;
+ int retval;
+ struct cgroupfs_root *root;
+
+ retval = -ENOMEM;
+ buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!buf)
+ goto out;
+
+ retval = -ESRCH;
+ pid = m->private;
+ tsk = get_pid_task(pid, PIDTYPE_PID);
+ if (!tsk)
+ goto out_free;
+
+ retval = 0;
+
+ mutex_lock(&cgroup_mutex);
+
+ for_each_root(root) {
+ struct cgroup_subsys *ss;
+ struct cgroup *cgrp;
+ int subsys_id;
+ int count = 0;
+
+ /* Skip this hierarchy if it has no active subsystems */
+ if (!root->actual_subsys_bits)
+ continue;
+ for_each_subsys(root, ss)
+ seq_printf(m, "%s%s", count++ ? "," : "", ss->name);
+ seq_putc(m, ':');
+ get_first_subsys(&root->top_cgroup, NULL, &subsys_id);
+ cgrp = task_cgroup(tsk, subsys_id);
+ retval = cgroup_path(cgrp, buf, PAGE_SIZE);
+ if (retval < 0)
+ goto out_unlock;
+ seq_puts(m, buf);
+ seq_putc(m, '\n');
+ }
+
+out_unlock:
+ mutex_unlock(&cgroup_mutex);
+ put_task_struct(tsk);
+out_free:
+ kfree(buf);
+out:
+ return retval;
+}
+
+static int cgroup_open(struct inode *inode, struct file *file)
+{
+ struct pid *pid = PROC_I(inode)->pid;
+ return single_open(file, proc_cgroup_show, pid);
+}
+
+struct file_operations proc_cgroup_operations = {
+ .open = cgroup_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+/* Display information about each subsystem and each hierarchy */
+static int proc_cgroupstats_show(struct seq_file *m, void *v)
+{
+ int i;
+
+ seq_puts(m, "#subsys_name\thierarchy\tnum_cgroups\n");
+ mutex_lock(&cgroup_mutex);
+ for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
+ struct cgroup_subsys *ss = subsys[i];
+ seq_printf(m, "%s\t%lu\t%d\n",
+ ss->name, ss->root->subsys_bits,
+ ss->root->number_of_cgroups);
+ }
+ mutex_unlock(&cgroup_mutex);
+ return 0;
+}
+
+static int cgroupstats_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, proc_cgroupstats_show, 0);
+}
+
+static struct file_operations proc_cgroupstats_operations = {
+ .open = cgroupstats_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+/**
+ * cgroup_fork - attach newly forked task to its parents cgroup.
+ * @tsk: pointer to task_struct of forking parent process.
+ *
+ * Description: A task inherits its parent's cgroup at fork().
+ *
+ * A pointer to the shared css_set was automatically copied in
+ * fork.c by dup_task_struct(). However, we ignore that copy, since
+ * it was not made under the protection of RCU or cgroup_mutex, so
+ * might no longer be a valid cgroup pointer. attach_task() might
+ * have already changed current->cgroups, allowing the previously
+ * referenced cgroup group to be removed and freed.
+ *
+ * At the point that cgroup_fork() is called, 'current' is the parent
+ * task, and the passed argument 'child' points to the child task.
+ */
+void cgroup_fork(struct task_struct *child)
+{
+ task_lock(current);
+ child->cgroups = current->cgroups;
+ get_css_set(child->cgroups);
+ task_unlock(current);
+ INIT_LIST_HEAD(&child->cg_list);
+}
+
+/**
+ * cgroup_fork_callbacks - called on a new task very soon before
+ * adding it to the tasklist. No need to take any locks since no-one
+ * can be operating on this task
+ */
+void cgroup_fork_callbacks(struct task_struct *child)
+{
+ if (need_forkexit_callback) {
+ int i;
+ for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
+ struct cgroup_subsys *ss = subsys[i];
+ if (ss->fork)
+ ss->fork(ss, child);
+ }
+ }
+}
+
+/**
+ * cgroup_post_fork - called on a new task after adding it to the
+ * task list. Adds the task to the list running through its css_set
+ * if necessary. Has to be after the task is visible on the task list
+ * in case we race with the first call to cgroup_iter_start() - to
+ * guarantee that the new task ends up on its list. */
+void cgroup_post_fork(struct task_struct *child)
+{
+ if (use_task_css_set_links) {
+ write_lock(&css_set_lock);
+ if (list_empty(&child->cg_list))
+ list_add(&child->cg_list, &child->cgroups->tasks);
+ write_unlock(&css_set_lock);
+ }
+}
+/**
+ * cgroup_exit - detach cgroup from exiting task
+ * @tsk: pointer to task_struct of exiting process
+ *
+ * Description: Detach cgroup from @tsk and release it.
+ *
+ * Note that cgroups marked notify_on_release force every task in
+ * them to take the global cgroup_mutex mutex when exiting.
+ * This could impact scaling on very large systems. Be reluctant to
+ * use notify_on_release cgroups where very high task exit scaling
+ * is required on large systems.
+ *
+ * the_top_cgroup_hack:
+ *
+ * Set the exiting tasks cgroup to the root cgroup (top_cgroup).
+ *
+ * We call cgroup_exit() while the task is still competent to
+ * handle notify_on_release(), then leave the task attached to the
+ * root cgroup in each hierarchy for the remainder of its exit.
+ *
+ * To do this properly, we would increment the reference count on
+ * top_cgroup, and near the very end of the kernel/exit.c do_exit()
+ * code we would add a second cgroup function call, to drop that
+ * reference. This would just create an unnecessary hot spot on
+ * the top_cgroup reference count, to no avail.
+ *
+ * Normally, holding a reference to a cgroup without bumping its
+ * count is unsafe. The cgroup could go away, or someone could
+ * attach us to a different cgroup, decrementing the count on
+ * the first cgroup that we never incremented. But in this case,
+ * top_cgroup isn't going away, and either task has PF_EXITING set,
+ * which wards off any attach_task() attempts, or task is a failed
+ * fork, never visible to attach_task.
+ *
+ */
+void cgroup_exit(struct task_struct *tsk, int run_callbacks)
+{
+ int i;
+ struct css_set *cg;
+
+ if (run_callbacks && need_forkexit_callback) {
+ for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
+ struct cgroup_subsys *ss = subsys[i];
+ if (ss->exit)
+ ss->exit(ss, tsk);
+ }
+ }
+
+ /*
+ * Unlink from the css_set task list if necessary.
+ * Optimistically check cg_list before taking
+ * css_set_lock
+ */
+ if (!list_empty(&tsk->cg_list)) {
+ write_lock(&css_set_lock);
+ if (!list_empty(&tsk->cg_list))
+ list_del(&tsk->cg_list);
+ write_unlock(&css_set_lock);
+ }
+
+ /* Reassign the task to the init_css_set. */
+ task_lock(tsk);
+ cg = tsk->cgroups;
+ tsk->cgroups = &init_css_set;
+ task_unlock(tsk);
+ if (cg)
+ put_css_set_taskexit(cg);
+}
+
+/**
+ * cgroup_clone - duplicate the current cgroup in the hierarchy
+ * that the given subsystem is attached to, and move this task into
+ * the new child
+ */
+int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys)
+{
+ struct dentry *dentry;
+ int ret = 0;
+ char nodename[MAX_CGROUP_TYPE_NAMELEN];
+ struct cgroup *parent, *child;
+ struct inode *inode;
+ struct css_set *cg;
+ struct cgroupfs_root *root;
+ struct cgroup_subsys *ss;
+
+ /* We shouldn't be called by an unregistered subsystem */
+ BUG_ON(!subsys->active);
+
+ /* First figure out what hierarchy and cgroup we're dealing
+ * with, and pin them so we can drop cgroup_mutex */
+ mutex_lock(&cgroup_mutex);
+ again:
+ root = subsys->root;
+ if (root == &rootnode) {
+ printk(KERN_INFO
+ "Not cloning cgroup for unused subsystem %s\n",
+ subsys->name);
+ mutex_unlock(&cgroup_mutex);
+ return 0;
+ }
+ cg = tsk->cgroups;
+ parent = task_cgroup(tsk, subsys->subsys_id);
+
+ snprintf(nodename, MAX_CGROUP_TYPE_NAMELEN, "node_%d", tsk->pid);
+
+ /* Pin the hierarchy */
+ atomic_inc(&parent->root->sb->s_active);
+
+ /* Keep the cgroup alive */
+ get_css_set(cg);
+ mutex_unlock(&cgroup_mutex);
+
+ /* Now do the VFS work to create a cgroup */
+ inode = parent->dentry->d_inode;
+
+ /* Hold the parent directory mutex across this operation to
+ * stop anyone else deleting the new cgroup */
+ mutex_lock(&inode->i_mutex);
+ dentry = lookup_one_len(nodename, parent->dentry, strlen(nodename));
+ if (IS_ERR(dentry)) {
+ printk(KERN_INFO
+ "cgroup: Couldn't allocate dentry for %s: %ld\n", nodename,
+ PTR_ERR(dentry));
+ ret = PTR_ERR(dentry);
+ goto out_release;
+ }
+
+ /* Create the cgroup directory, which also creates the cgroup */
+ ret = vfs_mkdir(inode, dentry, S_IFDIR | 0755);
+ child = __d_cgrp(dentry);
+ dput(dentry);
+ if (ret) {
+ printk(KERN_INFO
+ "Failed to create cgroup %s: %d\n", nodename,
+ ret);
+ goto out_release;
+ }
+
+ if (!child) {
+ printk(KERN_INFO
+ "Couldn't find new cgroup %s\n", nodename);
+ ret = -ENOMEM;
+ goto out_release;
+ }
+
+ /* The cgroup now exists. Retake cgroup_mutex and check
+ * that we're still in the same state that we thought we
+ * were. */
+ mutex_lock(&cgroup_mutex);
+ if ((root != subsys->root) ||
+ (parent != task_cgroup(tsk, subsys->subsys_id))) {
+ /* Aargh, we raced ... */
+ mutex_unlock(&inode->i_mutex);
+ put_css_set(cg);
+
+ deactivate_super(parent->root->sb);
+ /* The cgroup is still accessible in the VFS, but
+ * we're not going to try to rmdir() it at this
+ * point. */
+ printk(KERN_INFO
+ "Race in cgroup_clone() - leaking cgroup %s\n",
+ nodename);
+ goto again;
+ }
+
+ /* do any required auto-setup */
+ for_each_subsys(root, ss) {
+ if (ss->post_clone)
+ ss->post_clone(ss, child);
+ }
+
+ /* All seems fine. Finish by moving the task into the new cgroup */
+ ret = attach_task(child, tsk);
+ mutex_unlock(&cgroup_mutex);
+
+ out_release:
+ mutex_unlock(&inode->i_mutex);
+
+ mutex_lock(&cgroup_mutex);
+ put_css_set(cg);
+ mutex_unlock(&cgroup_mutex);
+ deactivate_super(parent->root->sb);
+ return ret;
+}
+
+/*
+ * See if "cgrp" is a descendant of the current task's cgroup in
+ * the appropriate hierarchy
+ *
+ * If we are sending in dummytop, then presumably we are creating
+ * the top cgroup in the subsystem.
+ *
+ * Called only by the ns (nsproxy) cgroup.
+ */
+int cgroup_is_descendant(const struct cgroup *cgrp)
+{
+ int ret;
+ struct cgroup *target;
+ int subsys_id;
+
+ if (cgrp == dummytop)
+ return 1;
+
+ get_first_subsys(cgrp, NULL, &subsys_id);
+ target = task_cgroup(current, subsys_id);
+ while (cgrp != target && cgrp!= cgrp->top_cgroup)
+ cgrp = cgrp->parent;
+ ret = (cgrp == target);
+ return ret;
+}
+
+static void check_for_release(struct cgroup *cgrp)
+{
+ /* All of these checks rely on RCU to keep the cgroup
+ * structure alive */
+ if (cgroup_is_releasable(cgrp) && !atomic_read(&cgrp->count)
+ && list_empty(&cgrp->children) && !cgroup_has_css_refs(cgrp)) {
+ /* Control Group is currently removeable. If it's not
+ * already queued for a userspace notification, queue
+ * it now */
+ int need_schedule_work = 0;
+ spin_lock(&release_list_lock);
+ if (!cgroup_is_removed(cgrp) &&
+ list_empty(&cgrp->release_list)) {
+ list_add(&cgrp->release_list, &release_list);
+ need_schedule_work = 1;
+ }
+ spin_unlock(&release_list_lock);
+ if (need_schedule_work)
+ schedule_work(&release_agent_work);
+ }
+}
+
+void __css_put(struct cgroup_subsys_state *css)
+{
+ struct cgroup *cgrp = css->cgroup;
+ rcu_read_lock();
+ if (atomic_dec_and_test(&css->refcnt) && notify_on_release(cgrp)) {
+ set_bit(CGRP_RELEASABLE, &cgrp->flags);
+ check_for_release(cgrp);
+ }
+ rcu_read_unlock();
+}
+
+/*
+ * Notify userspace when a cgroup is released, by running the
+ * configured release agent with the name of the cgroup (path
+ * relative to the root of cgroup file system) as the argument.
+ *
+ * Most likely, this user command will try to rmdir this cgroup.
+ *
+ * This races with the possibility that some other task will be
+ * attached to this cgroup before it is removed, or that some other
+ * user task will 'mkdir' a child cgroup of this cgroup. That's ok.
+ * The presumed 'rmdir' will fail quietly if this cgroup is no longer
+ * unused, and this cgroup will be reprieved from its death sentence,
+ * to continue to serve a useful existence. Next time it's released,
+ * we will get notified again, if it still has 'notify_on_release' set.
+ *
+ * The final arg to call_usermodehelper() is UMH_WAIT_EXEC, which
+ * means only wait until the task is successfully execve()'d. The
+ * separate release agent task is forked by call_usermodehelper(),
+ * then control in this thread returns here, without waiting for the
+ * release agent task. We don't bother to wait because the caller of
+ * this routine has no use for the exit status of the release agent
+ * task, so no sense holding our caller up for that.
+ *
+ */
+
+static void cgroup_release_agent(struct work_struct *work)
+{
+ BUG_ON(work != &release_agent_work);
+ mutex_lock(&cgroup_mutex);
+ spin_lock(&release_list_lock);
+ while (!list_empty(&release_list)) {
+ char *argv[3], *envp[3];
+ int i;
+ char *pathbuf;
+ struct cgroup *cgrp = list_entry(release_list.next,
+ struct cgroup,
+ release_list);
+ list_del_init(&cgrp->release_list);
+ spin_unlock(&release_list_lock);
+ pathbuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!pathbuf) {
+ spin_lock(&release_list_lock);
+ continue;
+ }
+
+ if (cgroup_path(cgrp, pathbuf, PAGE_SIZE) < 0) {
+ kfree(pathbuf);
+ spin_lock(&release_list_lock);
+ continue;
+ }
+
+ i = 0;
+ argv[i++] = cgrp->root->release_agent_path;
+ argv[i++] = (char *)pathbuf;
+ argv[i] = NULL;
+
+ i = 0;
+ /* minimal command environment */
+ envp[i++] = "HOME=/";
+ envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+ envp[i] = NULL;
+
+ /* Drop the lock while we invoke the usermode helper,
+ * since the exec could involve hitting disk and hence
+ * be a slow process */
+ mutex_unlock(&cgroup_mutex);
+ call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
+ kfree(pathbuf);
+ mutex_lock(&cgroup_mutex);
+ spin_lock(&release_list_lock);
+ }
+ spin_unlock(&release_list_lock);
+ mutex_unlock(&cgroup_mutex);
+}
diff --git a/kernel/cgroup_debug.c b/kernel/cgroup_debug.c
new file mode 100644
index 000000000000..37301e877cb0
--- /dev/null
+++ b/kernel/cgroup_debug.c
@@ -0,0 +1,97 @@
+/*
+ * kernel/ccontainer_debug.c - Example cgroup subsystem that
+ * exposes debug info
+ *
+ * Copyright (C) Google Inc, 2007
+ *
+ * Developed by Paul Menage (menage@google.com)
+ *
+ */
+
+#include <linux/cgroup.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/rcupdate.h>
+
+#include <asm/atomic.h>
+
+static struct cgroup_subsys_state *debug_create(struct cgroup_subsys *ss,
+ struct cgroup *cont)
+{
+ struct cgroup_subsys_state *css = kzalloc(sizeof(*css), GFP_KERNEL);
+
+ if (!css)
+ return ERR_PTR(-ENOMEM);
+
+ return css;
+}
+
+static void debug_destroy(struct cgroup_subsys *ss, struct cgroup *cont)
+{
+ kfree(cont->subsys[debug_subsys_id]);
+}
+
+static u64 cgroup_refcount_read(struct cgroup *cont, struct cftype *cft)
+{
+ return atomic_read(&cont->count);
+}
+
+static u64 taskcount_read(struct cgroup *cont, struct cftype *cft)
+{
+ u64 count;
+
+ cgroup_lock();
+ count = cgroup_task_count(cont);
+ cgroup_unlock();
+ return count;
+}
+
+static u64 current_css_set_read(struct cgroup *cont, struct cftype *cft)
+{
+ return (u64)(long)current->cgroups;
+}
+
+static u64 current_css_set_refcount_read(struct cgroup *cont,
+ struct cftype *cft)
+{
+ u64 count;
+
+ rcu_read_lock();
+ count = atomic_read(&current->cgroups->ref.refcount);
+ rcu_read_unlock();
+ return count;
+}
+
+static struct cftype files[] = {
+ {
+ .name = "cgroup_refcount",
+ .read_uint = cgroup_refcount_read,
+ },
+ {
+ .name = "taskcount",
+ .read_uint = taskcount_read,
+ },
+
+ {
+ .name = "current_css_set",
+ .read_uint = current_css_set_read,
+ },
+
+ {
+ .name = "current_css_set_refcount",
+ .read_uint = current_css_set_refcount_read,
+ },
+};
+
+static int debug_populate(struct cgroup_subsys *ss, struct cgroup *cont)
+{
+ return cgroup_add_files(cont, ss, files, ARRAY_SIZE(files));
+}
+
+struct cgroup_subsys debug_subsys = {
+ .name = "debug",
+ .create = debug_create,
+ .destroy = debug_destroy,
+ .populate = debug_populate,
+ .subsys_id = debug_subsys_id,
+};
diff --git a/kernel/compat.c b/kernel/compat.c
index 3bae3742c2aa..42a1ed4b61b1 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -40,62 +40,27 @@ int put_compat_timespec(const struct timespec *ts, struct compat_timespec __user
__put_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
}
-static long compat_nanosleep_restart(struct restart_block *restart)
-{
- unsigned long expire = restart->arg0, now = jiffies;
- struct compat_timespec __user *rmtp;
-
- /* Did it expire while we handled signals? */
- if (!time_after(expire, now))
- return 0;
-
- expire = schedule_timeout_interruptible(expire - now);
- if (expire == 0)
- return 0;
-
- rmtp = (struct compat_timespec __user *)restart->arg1;
- if (rmtp) {
- struct compat_timespec ct;
- struct timespec t;
-
- jiffies_to_timespec(expire, &t);
- ct.tv_sec = t.tv_sec;
- ct.tv_nsec = t.tv_nsec;
- if (copy_to_user(rmtp, &ct, sizeof(ct)))
- return -EFAULT;
- }
- /* The 'restart' block is already filled in */
- return -ERESTART_RESTARTBLOCK;
-}
-
asmlinkage long compat_sys_nanosleep(struct compat_timespec __user *rqtp,
- struct compat_timespec __user *rmtp)
+ struct compat_timespec __user *rmtp)
{
- struct timespec t;
- struct restart_block *restart;
- unsigned long expire;
+ struct timespec tu, rmt;
+ long ret;
- if (get_compat_timespec(&t, rqtp))
+ if (get_compat_timespec(&tu, rqtp))
return -EFAULT;
- if ((t.tv_nsec >= 1000000000L) || (t.tv_nsec < 0) || (t.tv_sec < 0))
+ if (!timespec_valid(&tu))
return -EINVAL;
- expire = timespec_to_jiffies(&t) + (t.tv_sec || t.tv_nsec);
- expire = schedule_timeout_interruptible(expire);
- if (expire == 0)
- return 0;
+ ret = hrtimer_nanosleep(&tu, rmtp ? &rmt : NULL, HRTIMER_MODE_REL,
+ CLOCK_MONOTONIC);
- if (rmtp) {
- jiffies_to_timespec(expire, &t);
- if (put_compat_timespec(&t, rmtp))
+ if (ret && rmtp) {
+ if (put_compat_timespec(&rmt, rmtp))
return -EFAULT;
}
- restart = &current_thread_info()->restart_block;
- restart->fn = compat_nanosleep_restart;
- restart->arg0 = jiffies + expire;
- restart->arg1 = (unsigned long) rmtp;
- return -ERESTART_RESTARTBLOCK;
+
+ return ret;
}
static inline long get_compat_itimerval(struct itimerval *o,
@@ -247,8 +212,8 @@ asmlinkage long compat_sys_setrlimit(unsigned int resource,
int ret;
mm_segment_t old_fs = get_fs ();
- if (resource >= RLIM_NLIMITS)
- return -EINVAL;
+ if (resource >= RLIM_NLIMITS)
+ return -EINVAL;
if (!access_ok(VERIFY_READ, rlim, sizeof(*rlim)) ||
__get_user(r.rlim_cur, &rlim->rlim_cur) ||
@@ -477,21 +442,21 @@ asmlinkage long compat_sys_sched_getaffinity(compat_pid_t pid, unsigned int len,
int get_compat_itimerspec(struct itimerspec *dst,
const struct compat_itimerspec __user *src)
-{
+{
if (get_compat_timespec(&dst->it_interval, &src->it_interval) ||
get_compat_timespec(&dst->it_value, &src->it_value))
return -EFAULT;
return 0;
-}
+}
int put_compat_itimerspec(struct compat_itimerspec __user *dst,
const struct itimerspec *src)
-{
+{
if (put_compat_timespec(&src->it_interval, &dst->it_interval) ||
put_compat_timespec(&src->it_value, &dst->it_value))
return -EFAULT;
return 0;
-}
+}
long compat_sys_timer_create(clockid_t which_clock,
struct compat_sigevent __user *timer_event_spec,
@@ -512,9 +477,9 @@ long compat_sys_timer_create(clockid_t which_clock,
}
long compat_sys_timer_settime(timer_t timer_id, int flags,
- struct compat_itimerspec __user *new,
+ struct compat_itimerspec __user *new,
struct compat_itimerspec __user *old)
-{
+{
long err;
mm_segment_t oldfs;
struct itimerspec newts, oldts;
@@ -522,58 +487,58 @@ long compat_sys_timer_settime(timer_t timer_id, int flags,
if (!new)
return -EINVAL;
if (get_compat_itimerspec(&newts, new))
- return -EFAULT;
+ return -EFAULT;
oldfs = get_fs();
set_fs(KERNEL_DS);
err = sys_timer_settime(timer_id, flags,
(struct itimerspec __user *) &newts,
(struct itimerspec __user *) &oldts);
- set_fs(oldfs);
+ set_fs(oldfs);
if (!err && old && put_compat_itimerspec(old, &oldts))
return -EFAULT;
return err;
-}
+}
long compat_sys_timer_gettime(timer_t timer_id,
struct compat_itimerspec __user *setting)
-{
+{
long err;
mm_segment_t oldfs;
- struct itimerspec ts;
+ struct itimerspec ts;
oldfs = get_fs();
set_fs(KERNEL_DS);
err = sys_timer_gettime(timer_id,
- (struct itimerspec __user *) &ts);
- set_fs(oldfs);
+ (struct itimerspec __user *) &ts);
+ set_fs(oldfs);
if (!err && put_compat_itimerspec(setting, &ts))
return -EFAULT;
return err;
-}
+}
long compat_sys_clock_settime(clockid_t which_clock,
struct compat_timespec __user *tp)
{
long err;
mm_segment_t oldfs;
- struct timespec ts;
+ struct timespec ts;
if (get_compat_timespec(&ts, tp))
- return -EFAULT;
+ return -EFAULT;
oldfs = get_fs();
- set_fs(KERNEL_DS);
+ set_fs(KERNEL_DS);
err = sys_clock_settime(which_clock,
(struct timespec __user *) &ts);
set_fs(oldfs);
return err;
-}
+}
long compat_sys_clock_gettime(clockid_t which_clock,
struct compat_timespec __user *tp)
{
long err;
mm_segment_t oldfs;
- struct timespec ts;
+ struct timespec ts;
oldfs = get_fs();
set_fs(KERNEL_DS);
@@ -581,16 +546,16 @@ long compat_sys_clock_gettime(clockid_t which_clock,
(struct timespec __user *) &ts);
set_fs(oldfs);
if (!err && put_compat_timespec(&ts, tp))
- return -EFAULT;
+ return -EFAULT;
return err;
-}
+}
long compat_sys_clock_getres(clockid_t which_clock,
struct compat_timespec __user *tp)
{
long err;
mm_segment_t oldfs;
- struct timespec ts;
+ struct timespec ts;
oldfs = get_fs();
set_fs(KERNEL_DS);
@@ -598,9 +563,9 @@ long compat_sys_clock_getres(clockid_t which_clock,
(struct timespec __user *) &ts);
set_fs(oldfs);
if (!err && tp && put_compat_timespec(&ts, tp))
- return -EFAULT;
+ return -EFAULT;
return err;
-}
+}
static long compat_clock_nanosleep_restart(struct restart_block *restart)
{
@@ -632,10 +597,10 @@ long compat_sys_clock_nanosleep(clockid_t which_clock, int flags,
{
long err;
mm_segment_t oldfs;
- struct timespec in, out;
+ struct timespec in, out;
struct restart_block *restart;
- if (get_compat_timespec(&in, rqtp))
+ if (get_compat_timespec(&in, rqtp))
return -EFAULT;
oldfs = get_fs();
@@ -654,8 +619,8 @@ long compat_sys_clock_nanosleep(clockid_t which_clock, int flags,
restart->fn = compat_clock_nanosleep_restart;
restart->arg1 = (unsigned long) rmtp;
}
- return err;
-}
+ return err;
+}
/*
* We currently only need the following fields from the sigevent
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 38033db8d8ec..6b3a0c15144f 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -98,7 +98,8 @@ static inline void check_for_tasks(int cpu)
!cputime_eq(p->stime, cputime_zero)))
printk(KERN_WARNING "Task %s (pid = %d) is on cpu %d\
(state = %ld, flags = %x) \n",
- p->comm, p->pid, cpu, p->state, p->flags);
+ p->comm, task_pid_nr(p), cpu,
+ p->state, p->flags);
}
write_unlock_irq(&tasklist_lock);
}
@@ -150,6 +151,7 @@ static int _cpu_down(unsigned int cpu, int tasks_frozen)
err = __raw_notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE | mod,
hcpu, -1, &nr_calls);
if (err == NOTIFY_BAD) {
+ nr_calls--;
__raw_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED | mod,
hcpu, nr_calls, NULL);
printk("%s: attempt to take down CPU %u failed\n",
@@ -233,6 +235,7 @@ static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen)
ret = __raw_notifier_call_chain(&cpu_chain, CPU_UP_PREPARE | mod, hcpu,
-1, &nr_calls);
if (ret == NOTIFY_BAD) {
+ nr_calls--;
printk("%s: attempt to bring up CPU %u failed\n",
__FUNCTION__, cpu);
ret = -EINVAL;
@@ -262,6 +265,15 @@ out_notify:
int __cpuinit cpu_up(unsigned int cpu)
{
int err = 0;
+ if (!cpu_isset(cpu, cpu_possible_map)) {
+ printk(KERN_ERR "can't online cpu %d because it is not "
+ "configured as may-hotadd at boot time\n", cpu);
+#if defined(CONFIG_IA64) || defined(CONFIG_X86_64) || defined(CONFIG_S390)
+ printk(KERN_ERR "please check additional_cpus= boot "
+ "parameter\n");
+#endif
+ return -EINVAL;
+ }
mutex_lock(&cpu_add_remove_lock);
if (cpu_hotplug_disabled)
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 57e6448b171e..50f5dc463688 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -4,7 +4,8 @@
* Processor and Memory placement constraints for sets of tasks.
*
* Copyright (C) 2003 BULL SA.
- * Copyright (C) 2004-2006 Silicon Graphics, Inc.
+ * Copyright (C) 2004-2007 Silicon Graphics, Inc.
+ * Copyright (C) 2006 Google, Inc
*
* Portions derived from Patrick Mochel's sysfs code.
* sysfs is Copyright (c) 2001-3 Patrick Mochel
@@ -12,6 +13,7 @@
* 2003-10-10 Written by Simon Derr.
* 2003-10-22 Updates by Stephen Hemminger.
* 2004 May-July Rework by Paul Jackson.
+ * 2006 Rework by Paul Menage to use generic cgroups
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of the Linux
@@ -36,6 +38,7 @@
#include <linux/mount.h>
#include <linux/namei.h>
#include <linux/pagemap.h>
+#include <linux/prio_heap.h>
#include <linux/proc_fs.h>
#include <linux/rcupdate.h>
#include <linux/sched.h>
@@ -52,8 +55,7 @@
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <linux/mutex.h>
-
-#define CPUSET_SUPER_MAGIC 0x27e0eb
+#include <linux/kfifo.h>
/*
* Tracks how many cpusets are currently defined in system.
@@ -62,6 +64,10 @@
*/
int number_of_cpusets __read_mostly;
+/* Retrieve the cpuset from a cgroup */
+struct cgroup_subsys cpuset_subsys;
+struct cpuset;
+
/* See "Frequency meter" comments, below. */
struct fmeter {
@@ -72,24 +78,13 @@ struct fmeter {
};
struct cpuset {
+ struct cgroup_subsys_state css;
+
unsigned long flags; /* "unsigned long" so bitops work */
cpumask_t cpus_allowed; /* CPUs allowed to tasks in cpuset */
nodemask_t mems_allowed; /* Memory Nodes allowed to tasks */
- /*
- * Count is atomic so can incr (fork) or decr (exit) without a lock.
- */
- atomic_t count; /* count tasks using this cpuset */
-
- /*
- * We link our 'sibling' struct into our parents 'children'.
- * Our children link their 'sibling' into our 'children'.
- */
- struct list_head sibling; /* my parents children */
- struct list_head children; /* my children */
-
struct cpuset *parent; /* my parent */
- struct dentry *dentry; /* cpuset fs entry */
/*
* Copy of global cpuset_mems_generation as of the most
@@ -98,15 +93,32 @@ struct cpuset {
int mems_generation;
struct fmeter fmeter; /* memory_pressure filter */
+
+ /* partition number for rebuild_sched_domains() */
+ int pn;
};
+/* Retrieve the cpuset for a cgroup */
+static inline struct cpuset *cgroup_cs(struct cgroup *cont)
+{
+ return container_of(cgroup_subsys_state(cont, cpuset_subsys_id),
+ struct cpuset, css);
+}
+
+/* Retrieve the cpuset for a task */
+static inline struct cpuset *task_cs(struct task_struct *task)
+{
+ return container_of(task_subsys_state(task, cpuset_subsys_id),
+ struct cpuset, css);
+}
+
+
/* bits in struct cpuset flags field */
typedef enum {
CS_CPU_EXCLUSIVE,
CS_MEM_EXCLUSIVE,
CS_MEMORY_MIGRATE,
- CS_REMOVED,
- CS_NOTIFY_ON_RELEASE,
+ CS_SCHED_LOAD_BALANCE,
CS_SPREAD_PAGE,
CS_SPREAD_SLAB,
} cpuset_flagbits_t;
@@ -122,14 +134,9 @@ static inline int is_mem_exclusive(const struct cpuset *cs)
return test_bit(CS_MEM_EXCLUSIVE, &cs->flags);
}
-static inline int is_removed(const struct cpuset *cs)
+static inline int is_sched_load_balance(const struct cpuset *cs)
{
- return test_bit(CS_REMOVED, &cs->flags);
-}
-
-static inline int notify_on_release(const struct cpuset *cs)
-{
- return test_bit(CS_NOTIFY_ON_RELEASE, &cs->flags);
+ return test_bit(CS_SCHED_LOAD_BALANCE, &cs->flags);
}
static inline int is_memory_migrate(const struct cpuset *cs)
@@ -172,14 +179,8 @@ static struct cpuset top_cpuset = {
.flags = ((1 << CS_CPU_EXCLUSIVE) | (1 << CS_MEM_EXCLUSIVE)),
.cpus_allowed = CPU_MASK_ALL,
.mems_allowed = NODE_MASK_ALL,
- .count = ATOMIC_INIT(0),
- .sibling = LIST_HEAD_INIT(top_cpuset.sibling),
- .children = LIST_HEAD_INIT(top_cpuset.children),
};
-static struct vfsmount *cpuset_mount;
-static struct super_block *cpuset_sb;
-
/*
* We have two global cpuset mutexes below. They can nest.
* It is ok to first take manage_mutex, then nest callback_mutex. We also
@@ -263,297 +264,33 @@ static struct super_block *cpuset_sb;
* the routine cpuset_update_task_memory_state().
*/
-static DEFINE_MUTEX(manage_mutex);
static DEFINE_MUTEX(callback_mutex);
-/*
- * A couple of forward declarations required, due to cyclic reference loop:
- * cpuset_mkdir -> cpuset_create -> cpuset_populate_dir -> cpuset_add_file
- * -> cpuset_create_file -> cpuset_dir_inode_operations -> cpuset_mkdir.
- */
-
-static int cpuset_mkdir(struct inode *dir, struct dentry *dentry, int mode);
-static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry);
-
-static struct backing_dev_info cpuset_backing_dev_info = {
- .ra_pages = 0, /* No readahead */
- .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
-};
-
-static struct inode *cpuset_new_inode(mode_t mode)
-{
- struct inode *inode = new_inode(cpuset_sb);
-
- if (inode) {
- inode->i_mode = mode;
- inode->i_uid = current->fsuid;
- inode->i_gid = current->fsgid;
- inode->i_blocks = 0;
- inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
- inode->i_mapping->backing_dev_info = &cpuset_backing_dev_info;
- }
- return inode;
-}
-
-static void cpuset_diput(struct dentry *dentry, struct inode *inode)
-{
- /* is dentry a directory ? if so, kfree() associated cpuset */
- if (S_ISDIR(inode->i_mode)) {
- struct cpuset *cs = dentry->d_fsdata;
- BUG_ON(!(is_removed(cs)));
- kfree(cs);
- }
- iput(inode);
-}
-
-static struct dentry_operations cpuset_dops = {
- .d_iput = cpuset_diput,
-};
-
-static struct dentry *cpuset_get_dentry(struct dentry *parent, const char *name)
-{
- struct dentry *d = lookup_one_len(name, parent, strlen(name));
- if (!IS_ERR(d))
- d->d_op = &cpuset_dops;
- return d;
-}
-
-static void remove_dir(struct dentry *d)
-{
- struct dentry *parent = dget(d->d_parent);
-
- d_delete(d);
- simple_rmdir(parent->d_inode, d);
- dput(parent);
-}
-
-/*
- * NOTE : the dentry must have been dget()'ed
- */
-static void cpuset_d_remove_dir(struct dentry *dentry)
-{
- struct list_head *node;
-
- spin_lock(&dcache_lock);
- node = dentry->d_subdirs.next;
- while (node != &dentry->d_subdirs) {
- struct dentry *d = list_entry(node, struct dentry, d_u.d_child);
- list_del_init(node);
- if (d->d_inode) {
- d = dget_locked(d);
- spin_unlock(&dcache_lock);
- d_delete(d);
- simple_unlink(dentry->d_inode, d);
- dput(d);
- spin_lock(&dcache_lock);
- }
- node = dentry->d_subdirs.next;
- }
- list_del_init(&dentry->d_u.d_child);
- spin_unlock(&dcache_lock);
- remove_dir(dentry);
-}
-
-static struct super_operations cpuset_ops = {
- .statfs = simple_statfs,
- .drop_inode = generic_delete_inode,
-};
-
-static int cpuset_fill_super(struct super_block *sb, void *unused_data,
- int unused_silent)
-{
- struct inode *inode;
- struct dentry *root;
-
- sb->s_blocksize = PAGE_CACHE_SIZE;
- sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
- sb->s_magic = CPUSET_SUPER_MAGIC;
- sb->s_op = &cpuset_ops;
- cpuset_sb = sb;
-
- inode = cpuset_new_inode(S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR);
- if (inode) {
- inode->i_op = &simple_dir_inode_operations;
- inode->i_fop = &simple_dir_operations;
- /* directories start off with i_nlink == 2 (for "." entry) */
- inc_nlink(inode);
- } else {
- return -ENOMEM;
- }
-
- root = d_alloc_root(inode);
- if (!root) {
- iput(inode);
- return -ENOMEM;
- }
- sb->s_root = root;
- return 0;
-}
-
+/* This is ugly, but preserves the userspace API for existing cpuset
+ * users. If someone tries to mount the "cpuset" filesystem, we
+ * silently switch it to mount "cgroup" instead */
static int cpuset_get_sb(struct file_system_type *fs_type,
int flags, const char *unused_dev_name,
void *data, struct vfsmount *mnt)
{
- return get_sb_single(fs_type, flags, data, cpuset_fill_super, mnt);
+ struct file_system_type *cgroup_fs = get_fs_type("cgroup");
+ int ret = -ENODEV;
+ if (cgroup_fs) {
+ char mountopts[] =
+ "cpuset,noprefix,"
+ "release_agent=/sbin/cpuset_release_agent";
+ ret = cgroup_fs->get_sb(cgroup_fs, flags,
+ unused_dev_name, mountopts, mnt);
+ put_filesystem(cgroup_fs);
+ }
+ return ret;
}
static struct file_system_type cpuset_fs_type = {
.name = "cpuset",
.get_sb = cpuset_get_sb,
- .kill_sb = kill_litter_super,
-};
-
-/* struct cftype:
- *
- * The files in the cpuset filesystem mostly have a very simple read/write
- * handling, some common function will take care of it. Nevertheless some cases
- * (read tasks) are special and therefore I define this structure for every
- * kind of file.
- *
- *
- * When reading/writing to a file:
- * - the cpuset to use in file->f_path.dentry->d_parent->d_fsdata
- * - the 'cftype' of the file is file->f_path.dentry->d_fsdata
- */
-
-struct cftype {
- char *name;
- int private;
- int (*open) (struct inode *inode, struct file *file);
- ssize_t (*read) (struct file *file, char __user *buf, size_t nbytes,
- loff_t *ppos);
- int (*write) (struct file *file, const char __user *buf, size_t nbytes,
- loff_t *ppos);
- int (*release) (struct inode *inode, struct file *file);
};
-static inline struct cpuset *__d_cs(struct dentry *dentry)
-{
- return dentry->d_fsdata;
-}
-
-static inline struct cftype *__d_cft(struct dentry *dentry)
-{
- return dentry->d_fsdata;
-}
-
-/*
- * Call with manage_mutex held. Writes path of cpuset into buf.
- * Returns 0 on success, -errno on error.
- */
-
-static int cpuset_path(const struct cpuset *cs, char *buf, int buflen)
-{
- char *start;
-
- start = buf + buflen;
-
- *--start = '\0';
- for (;;) {
- int len = cs->dentry->d_name.len;
- if ((start -= len) < buf)
- return -ENAMETOOLONG;
- memcpy(start, cs->dentry->d_name.name, len);
- cs = cs->parent;
- if (!cs)
- break;
- if (!cs->parent)
- continue;
- if (--start < buf)
- return -ENAMETOOLONG;
- *start = '/';
- }
- memmove(buf, start, buf + buflen - start);
- return 0;
-}
-
-/*
- * Notify userspace when a cpuset is released, by running
- * /sbin/cpuset_release_agent with the name of the cpuset (path
- * relative to the root of cpuset file system) as the argument.
- *
- * Most likely, this user command will try to rmdir this cpuset.
- *
- * This races with the possibility that some other task will be
- * attached to this cpuset before it is removed, or that some other
- * user task will 'mkdir' a child cpuset of this cpuset. That's ok.
- * The presumed 'rmdir' will fail quietly if this cpuset is no longer
- * unused, and this cpuset will be reprieved from its death sentence,
- * to continue to serve a useful existence. Next time it's released,
- * we will get notified again, if it still has 'notify_on_release' set.
- *
- * The final arg to call_usermodehelper() is 0, which means don't
- * wait. The separate /sbin/cpuset_release_agent task is forked by
- * call_usermodehelper(), then control in this thread returns here,
- * without waiting for the release agent task. We don't bother to
- * wait because the caller of this routine has no use for the exit
- * status of the /sbin/cpuset_release_agent task, so no sense holding
- * our caller up for that.
- *
- * When we had only one cpuset mutex, we had to call this
- * without holding it, to avoid deadlock when call_usermodehelper()
- * allocated memory. With two locks, we could now call this while
- * holding manage_mutex, but we still don't, so as to minimize
- * the time manage_mutex is held.
- */
-
-static void cpuset_release_agent(const char *pathbuf)
-{
- char *argv[3], *envp[3];
- int i;
-
- if (!pathbuf)
- return;
-
- i = 0;
- argv[i++] = "/sbin/cpuset_release_agent";
- argv[i++] = (char *)pathbuf;
- argv[i] = NULL;
-
- i = 0;
- /* minimal command environment */
- envp[i++] = "HOME=/";
- envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
- envp[i] = NULL;
-
- call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
- kfree(pathbuf);
-}
-
-/*
- * Either cs->count of using tasks transitioned to zero, or the
- * cs->children list of child cpusets just became empty. If this
- * cs is notify_on_release() and now both the user count is zero and
- * the list of children is empty, prepare cpuset path in a kmalloc'd
- * buffer, to be returned via ppathbuf, so that the caller can invoke
- * cpuset_release_agent() with it later on, once manage_mutex is dropped.
- * Call here with manage_mutex held.
- *
- * This check_for_release() routine is responsible for kmalloc'ing
- * pathbuf. The above cpuset_release_agent() is responsible for
- * kfree'ing pathbuf. The caller of these routines is responsible
- * for providing a pathbuf pointer, initialized to NULL, then
- * calling check_for_release() with manage_mutex held and the address
- * of the pathbuf pointer, then dropping manage_mutex, then calling
- * cpuset_release_agent() with pathbuf, as set by check_for_release().
- */
-
-static void check_for_release(struct cpuset *cs, char **ppathbuf)
-{
- if (notify_on_release(cs) && atomic_read(&cs->count) == 0 &&
- list_empty(&cs->children)) {
- char *buf;
-
- buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
- if (!buf)
- return;
- if (cpuset_path(cs, buf, PAGE_SIZE) < 0)
- kfree(buf);
- else
- *ppathbuf = buf;
- }
-}
-
/*
* Return in *pmask the portion of a cpusets's cpus_allowed that
* are online. If none are online, walk up the cpuset hierarchy
@@ -581,26 +318,28 @@ static void guarantee_online_cpus(const struct cpuset *cs, cpumask_t *pmask)
/*
* Return in *pmask the portion of a cpusets's mems_allowed that
- * are online. If none are online, walk up the cpuset hierarchy
- * until we find one that does have some online mems. If we get
- * all the way to the top and still haven't found any online mems,
- * return node_online_map.
+ * are online, with memory. If none are online with memory, walk
+ * up the cpuset hierarchy until we find one that does have some
+ * online mems. If we get all the way to the top and still haven't
+ * found any online mems, return node_states[N_HIGH_MEMORY].
*
* One way or another, we guarantee to return some non-empty subset
- * of node_online_map.
+ * of node_states[N_HIGH_MEMORY].
*
* Call with callback_mutex held.
*/
static void guarantee_online_mems(const struct cpuset *cs, nodemask_t *pmask)
{
- while (cs && !nodes_intersects(cs->mems_allowed, node_online_map))
+ while (cs && !nodes_intersects(cs->mems_allowed,
+ node_states[N_HIGH_MEMORY]))
cs = cs->parent;
if (cs)
- nodes_and(*pmask, cs->mems_allowed, node_online_map);
+ nodes_and(*pmask, cs->mems_allowed,
+ node_states[N_HIGH_MEMORY]);
else
- *pmask = node_online_map;
- BUG_ON(!nodes_intersects(*pmask, node_online_map));
+ *pmask = node_states[N_HIGH_MEMORY];
+ BUG_ON(!nodes_intersects(*pmask, node_states[N_HIGH_MEMORY]));
}
/**
@@ -651,20 +390,19 @@ void cpuset_update_task_memory_state(void)
struct task_struct *tsk = current;
struct cpuset *cs;
- if (tsk->cpuset == &top_cpuset) {
+ if (task_cs(tsk) == &top_cpuset) {
/* Don't need rcu for top_cpuset. It's never freed. */
my_cpusets_mem_gen = top_cpuset.mems_generation;
} else {
rcu_read_lock();
- cs = rcu_dereference(tsk->cpuset);
- my_cpusets_mem_gen = cs->mems_generation;
+ my_cpusets_mem_gen = task_cs(current)->mems_generation;
rcu_read_unlock();
}
if (my_cpusets_mem_gen != tsk->cpuset_mems_generation) {
mutex_lock(&callback_mutex);
task_lock(tsk);
- cs = tsk->cpuset; /* Maybe changed when task not locked */
+ cs = task_cs(tsk); /* Maybe changed when task not locked */
guarantee_online_mems(cs, &tsk->mems_allowed);
tsk->cpuset_mems_generation = cs->mems_generation;
if (is_spread_page(cs))
@@ -719,11 +457,12 @@ static int is_cpuset_subset(const struct cpuset *p, const struct cpuset *q)
static int validate_change(const struct cpuset *cur, const struct cpuset *trial)
{
+ struct cgroup *cont;
struct cpuset *c, *par;
/* Each of our child cpusets must be a subset of us */
- list_for_each_entry(c, &cur->children, sibling) {
- if (!is_cpuset_subset(c, trial))
+ list_for_each_entry(cont, &cur->css.cgroup->children, sibling) {
+ if (!is_cpuset_subset(cgroup_cs(cont), trial))
return -EBUSY;
}
@@ -738,7 +477,8 @@ static int validate_change(const struct cpuset *cur, const struct cpuset *trial)
return -EACCES;
/* If either I or some sibling (!= me) is exclusive, we can't overlap */
- list_for_each_entry(c, &par->children, sibling) {
+ list_for_each_entry(cont, &par->css.cgroup->children, sibling) {
+ c = cgroup_cs(cont);
if ((is_cpu_exclusive(trial) || is_cpu_exclusive(c)) &&
c != cur &&
cpus_intersects(trial->cpus_allowed, c->cpus_allowed))
@@ -749,62 +489,247 @@ static int validate_change(const struct cpuset *cur, const struct cpuset *trial)
return -EINVAL;
}
+ /* Cpusets with tasks can't have empty cpus_allowed or mems_allowed */
+ if (cgroup_task_count(cur->css.cgroup)) {
+ if (cpus_empty(trial->cpus_allowed) ||
+ nodes_empty(trial->mems_allowed)) {
+ return -ENOSPC;
+ }
+ }
+
return 0;
}
/*
- * For a given cpuset cur, partition the system as follows
- * a. All cpus in the parent cpuset's cpus_allowed that are not part of any
- * exclusive child cpusets
- * b. All cpus in the current cpuset's cpus_allowed that are not part of any
- * exclusive child cpusets
- * Build these two partitions by calling partition_sched_domains
- *
- * Call with manage_mutex held. May nest a call to the
- * lock_cpu_hotplug()/unlock_cpu_hotplug() pair.
- * Must not be called holding callback_mutex, because we must
- * not call lock_cpu_hotplug() while holding callback_mutex.
+ * Helper routine for rebuild_sched_domains().
+ * Do cpusets a, b have overlapping cpus_allowed masks?
*/
-static void update_cpu_domains(struct cpuset *cur)
+static int cpusets_overlap(struct cpuset *a, struct cpuset *b)
{
- struct cpuset *c, *par = cur->parent;
- cpumask_t pspan, cspan;
+ return cpus_intersects(a->cpus_allowed, b->cpus_allowed);
+}
- if (par == NULL || cpus_empty(cur->cpus_allowed))
- return;
+/*
+ * rebuild_sched_domains()
+ *
+ * If the flag 'sched_load_balance' of any cpuset with non-empty
+ * 'cpus' changes, or if the 'cpus' allowed changes in any cpuset
+ * which has that flag enabled, or if any cpuset with a non-empty
+ * 'cpus' is removed, then call this routine to rebuild the
+ * scheduler's dynamic sched domains.
+ *
+ * This routine builds a partial partition of the systems CPUs
+ * (the set of non-overlappping cpumask_t's in the array 'part'
+ * below), and passes that partial partition to the kernel/sched.c
+ * partition_sched_domains() routine, which will rebuild the
+ * schedulers load balancing domains (sched domains) as specified
+ * by that partial partition. A 'partial partition' is a set of
+ * non-overlapping subsets whose union is a subset of that set.
+ *
+ * See "What is sched_load_balance" in Documentation/cpusets.txt
+ * for a background explanation of this.
+ *
+ * Does not return errors, on the theory that the callers of this
+ * routine would rather not worry about failures to rebuild sched
+ * domains when operating in the severe memory shortage situations
+ * that could cause allocation failures below.
+ *
+ * Call with cgroup_mutex held. May take callback_mutex during
+ * call due to the kfifo_alloc() and kmalloc() calls. May nest
+ * a call to the lock_cpu_hotplug()/unlock_cpu_hotplug() pair.
+ * Must not be called holding callback_mutex, because we must not
+ * call lock_cpu_hotplug() while holding callback_mutex. Elsewhere
+ * the kernel nests callback_mutex inside lock_cpu_hotplug() calls.
+ * So the reverse nesting would risk an ABBA deadlock.
+ *
+ * The three key local variables below are:
+ * q - a kfifo queue of cpuset pointers, used to implement a
+ * top-down scan of all cpusets. This scan loads a pointer
+ * to each cpuset marked is_sched_load_balance into the
+ * array 'csa'. For our purposes, rebuilding the schedulers
+ * sched domains, we can ignore !is_sched_load_balance cpusets.
+ * csa - (for CpuSet Array) Array of pointers to all the cpusets
+ * that need to be load balanced, for convenient iterative
+ * access by the subsequent code that finds the best partition,
+ * i.e the set of domains (subsets) of CPUs such that the
+ * cpus_allowed of every cpuset marked is_sched_load_balance
+ * is a subset of one of these domains, while there are as
+ * many such domains as possible, each as small as possible.
+ * doms - Conversion of 'csa' to an array of cpumasks, for passing to
+ * the kernel/sched.c routine partition_sched_domains() in a
+ * convenient format, that can be easily compared to the prior
+ * value to determine what partition elements (sched domains)
+ * were changed (added or removed.)
+ *
+ * Finding the best partition (set of domains):
+ * The triple nested loops below over i, j, k scan over the
+ * load balanced cpusets (using the array of cpuset pointers in
+ * csa[]) looking for pairs of cpusets that have overlapping
+ * cpus_allowed, but which don't have the same 'pn' partition
+ * number and gives them in the same partition number. It keeps
+ * looping on the 'restart' label until it can no longer find
+ * any such pairs.
+ *
+ * The union of the cpus_allowed masks from the set of
+ * all cpusets having the same 'pn' value then form the one
+ * element of the partition (one sched domain) to be passed to
+ * partition_sched_domains().
+ */
- /*
- * Get all cpus from parent's cpus_allowed not part of exclusive
- * children
- */
- pspan = par->cpus_allowed;
- list_for_each_entry(c, &par->children, sibling) {
- if (is_cpu_exclusive(c))
- cpus_andnot(pspan, pspan, c->cpus_allowed);
+static void rebuild_sched_domains(void)
+{
+ struct kfifo *q; /* queue of cpusets to be scanned */
+ struct cpuset *cp; /* scans q */
+ struct cpuset **csa; /* array of all cpuset ptrs */
+ int csn; /* how many cpuset ptrs in csa so far */
+ int i, j, k; /* indices for partition finding loops */
+ cpumask_t *doms; /* resulting partition; i.e. sched domains */
+ int ndoms; /* number of sched domains in result */
+ int nslot; /* next empty doms[] cpumask_t slot */
+
+ q = NULL;
+ csa = NULL;
+ doms = NULL;
+
+ /* Special case for the 99% of systems with one, full, sched domain */
+ if (is_sched_load_balance(&top_cpuset)) {
+ ndoms = 1;
+ doms = kmalloc(sizeof(cpumask_t), GFP_KERNEL);
+ if (!doms)
+ goto rebuild;
+ *doms = top_cpuset.cpus_allowed;
+ goto rebuild;
}
- if (!is_cpu_exclusive(cur)) {
- cpus_or(pspan, pspan, cur->cpus_allowed);
- if (cpus_equal(pspan, cur->cpus_allowed))
- return;
- cspan = CPU_MASK_NONE;
- } else {
- if (cpus_empty(pspan))
- return;
- cspan = cur->cpus_allowed;
- /*
- * Get all cpus from current cpuset's cpus_allowed not part
- * of exclusive children
- */
- list_for_each_entry(c, &cur->children, sibling) {
- if (is_cpu_exclusive(c))
- cpus_andnot(cspan, cspan, c->cpus_allowed);
+
+ q = kfifo_alloc(number_of_cpusets * sizeof(cp), GFP_KERNEL, NULL);
+ if (IS_ERR(q))
+ goto done;
+ csa = kmalloc(number_of_cpusets * sizeof(cp), GFP_KERNEL);
+ if (!csa)
+ goto done;
+ csn = 0;
+
+ cp = &top_cpuset;
+ __kfifo_put(q, (void *)&cp, sizeof(cp));
+ while (__kfifo_get(q, (void *)&cp, sizeof(cp))) {
+ struct cgroup *cont;
+ struct cpuset *child; /* scans child cpusets of cp */
+ if (is_sched_load_balance(cp))
+ csa[csn++] = cp;
+ list_for_each_entry(cont, &cp->css.cgroup->children, sibling) {
+ child = cgroup_cs(cont);
+ __kfifo_put(q, (void *)&child, sizeof(cp));
+ }
+ }
+
+ for (i = 0; i < csn; i++)
+ csa[i]->pn = i;
+ ndoms = csn;
+
+restart:
+ /* Find the best partition (set of sched domains) */
+ for (i = 0; i < csn; i++) {
+ struct cpuset *a = csa[i];
+ int apn = a->pn;
+
+ for (j = 0; j < csn; j++) {
+ struct cpuset *b = csa[j];
+ int bpn = b->pn;
+
+ if (apn != bpn && cpusets_overlap(a, b)) {
+ for (k = 0; k < csn; k++) {
+ struct cpuset *c = csa[k];
+
+ if (c->pn == bpn)
+ c->pn = apn;
+ }
+ ndoms--; /* one less element */
+ goto restart;
+ }
+ }
+ }
+
+ /* Convert <csn, csa> to <ndoms, doms> */
+ doms = kmalloc(ndoms * sizeof(cpumask_t), GFP_KERNEL);
+ if (!doms)
+ goto rebuild;
+
+ for (nslot = 0, i = 0; i < csn; i++) {
+ struct cpuset *a = csa[i];
+ int apn = a->pn;
+
+ if (apn >= 0) {
+ cpumask_t *dp = doms + nslot;
+
+ if (nslot == ndoms) {
+ static int warnings = 10;
+ if (warnings) {
+ printk(KERN_WARNING
+ "rebuild_sched_domains confused:"
+ " nslot %d, ndoms %d, csn %d, i %d,"
+ " apn %d\n",
+ nslot, ndoms, csn, i, apn);
+ warnings--;
+ }
+ continue;
+ }
+
+ cpus_clear(*dp);
+ for (j = i; j < csn; j++) {
+ struct cpuset *b = csa[j];
+
+ if (apn == b->pn) {
+ cpus_or(*dp, *dp, b->cpus_allowed);
+ b->pn = -1;
+ }
+ }
+ nslot++;
}
}
+ BUG_ON(nslot != ndoms);
+rebuild:
+ /* Have scheduler rebuild sched domains */
lock_cpu_hotplug();
- partition_sched_domains(&pspan, &cspan);
+ partition_sched_domains(ndoms, doms);
unlock_cpu_hotplug();
+
+done:
+ if (q && !IS_ERR(q))
+ kfifo_free(q);
+ kfree(csa);
+ /* Don't kfree(doms) -- partition_sched_domains() does that. */
+}
+
+static inline int started_after_time(struct task_struct *t1,
+ struct timespec *time,
+ struct task_struct *t2)
+{
+ int start_diff = timespec_compare(&t1->start_time, time);
+ if (start_diff > 0) {
+ return 1;
+ } else if (start_diff < 0) {
+ return 0;
+ } else {
+ /*
+ * Arbitrarily, if two processes started at the same
+ * time, we'll say that the lower pointer value
+ * started first. Note that t2 may have exited by now
+ * so this may not be a valid pointer any longer, but
+ * that's fine - it still serves to distinguish
+ * between two tasks started (effectively)
+ * simultaneously.
+ */
+ return t1 > t2;
+ }
+}
+
+static inline int started_after(void *p1, void *p2)
+{
+ struct task_struct *t1 = p1;
+ struct task_struct *t2 = p2;
+ return started_after_time(t1, &t2->start_time, t2);
}
/*
@@ -814,7 +739,15 @@ static void update_cpu_domains(struct cpuset *cur)
static int update_cpumask(struct cpuset *cs, char *buf)
{
struct cpuset trialcs;
- int retval, cpus_unchanged;
+ int retval, i;
+ int is_load_balanced;
+ struct cgroup_iter it;
+ struct cgroup *cgrp = cs->css.cgroup;
+ struct task_struct *p, *dropped;
+ /* Never dereference latest_task, since it's not refcounted */
+ struct task_struct *latest_task = NULL;
+ struct ptr_heap heap;
+ struct timespec latest_time = { 0, 0 };
/* top_cpuset.cpus_allowed tracks cpu_online_map; it's read-only */
if (cs == &top_cpuset)
@@ -823,11 +756,13 @@ static int update_cpumask(struct cpuset *cs, char *buf)
trialcs = *cs;
/*
- * We allow a cpuset's cpus_allowed to be empty; if it has attached
- * tasks, we'll catch it later when we validate the change and return
- * -ENOSPC.
+ * An empty cpus_allowed is ok iff there are no tasks in the cpuset.
+ * Since cpulist_parse() fails on an empty mask, we special case
+ * that parsing. The validate_change() call ensures that cpusets
+ * with tasks have cpus.
*/
- if (!buf[0] || (buf[0] == '\n' && !buf[1])) {
+ buf = strstrip(buf);
+ if (!*buf) {
cpus_clear(trialcs.cpus_allowed);
} else {
retval = cpulist_parse(buf, trialcs.cpus_allowed);
@@ -835,18 +770,79 @@ static int update_cpumask(struct cpuset *cs, char *buf)
return retval;
}
cpus_and(trialcs.cpus_allowed, trialcs.cpus_allowed, cpu_online_map);
- /* cpus_allowed cannot be empty for a cpuset with attached tasks. */
- if (atomic_read(&cs->count) && cpus_empty(trialcs.cpus_allowed))
- return -ENOSPC;
retval = validate_change(cs, &trialcs);
if (retval < 0)
return retval;
- cpus_unchanged = cpus_equal(cs->cpus_allowed, trialcs.cpus_allowed);
+
+ /* Nothing to do if the cpus didn't change */
+ if (cpus_equal(cs->cpus_allowed, trialcs.cpus_allowed))
+ return 0;
+ retval = heap_init(&heap, PAGE_SIZE, GFP_KERNEL, &started_after);
+ if (retval)
+ return retval;
+
+ is_load_balanced = is_sched_load_balance(&trialcs);
+
mutex_lock(&callback_mutex);
cs->cpus_allowed = trialcs.cpus_allowed;
mutex_unlock(&callback_mutex);
- if (is_cpu_exclusive(cs) && !cpus_unchanged)
- update_cpu_domains(cs);
+
+ again:
+ /*
+ * Scan tasks in the cpuset, and update the cpumasks of any
+ * that need an update. Since we can't call set_cpus_allowed()
+ * while holding tasklist_lock, gather tasks to be processed
+ * in a heap structure. If the statically-sized heap fills up,
+ * overflow tasks that started later, and in future iterations
+ * only consider tasks that started after the latest task in
+ * the previous pass. This guarantees forward progress and
+ * that we don't miss any tasks
+ */
+ heap.size = 0;
+ cgroup_iter_start(cgrp, &it);
+ while ((p = cgroup_iter_next(cgrp, &it))) {
+ /* Only affect tasks that don't have the right cpus_allowed */
+ if (cpus_equal(p->cpus_allowed, cs->cpus_allowed))
+ continue;
+ /*
+ * Only process tasks that started after the last task
+ * we processed
+ */
+ if (!started_after_time(p, &latest_time, latest_task))
+ continue;
+ dropped = heap_insert(&heap, p);
+ if (dropped == NULL) {
+ get_task_struct(p);
+ } else if (dropped != p) {
+ get_task_struct(p);
+ put_task_struct(dropped);
+ }
+ }
+ cgroup_iter_end(cgrp, &it);
+ if (heap.size) {
+ for (i = 0; i < heap.size; i++) {
+ struct task_struct *p = heap.ptrs[i];
+ if (i == 0) {
+ latest_time = p->start_time;
+ latest_task = p;
+ }
+ set_cpus_allowed(p, cs->cpus_allowed);
+ put_task_struct(p);
+ }
+ /*
+ * If we had to process any tasks at all, scan again
+ * in case some of them were in the middle of forking
+ * children that didn't notice the new cpumask
+ * restriction. Not the most efficient way to do it,
+ * but it avoids having to take callback_mutex in the
+ * fork path
+ */
+ goto again;
+ }
+ heap_free(&heap);
+ if (is_load_balanced)
+ rebuild_sched_domains();
+
return 0;
}
@@ -895,7 +891,7 @@ static void cpuset_migrate_mm(struct mm_struct *mm, const nodemask_t *from,
do_migrate_pages(mm, from, to, MPOL_MF_MOVE_ALL);
mutex_lock(&callback_mutex);
- guarantee_online_mems(tsk->cpuset, &tsk->mems_allowed);
+ guarantee_online_mems(task_cs(tsk),&tsk->mems_allowed);
mutex_unlock(&callback_mutex);
}
@@ -913,46 +909,50 @@ static void cpuset_migrate_mm(struct mm_struct *mm, const nodemask_t *from,
* their mempolicies to the cpusets new mems_allowed.
*/
+static void *cpuset_being_rebound;
+
static int update_nodemask(struct cpuset *cs, char *buf)
{
struct cpuset trialcs;
nodemask_t oldmem;
- struct task_struct *g, *p;
+ struct task_struct *p;
struct mm_struct **mmarray;
int i, n, ntasks;
int migrate;
int fudge;
int retval;
+ struct cgroup_iter it;
- /* top_cpuset.mems_allowed tracks node_online_map; it's read-only */
+ /*
+ * top_cpuset.mems_allowed tracks node_stats[N_HIGH_MEMORY];
+ * it's read-only
+ */
if (cs == &top_cpuset)
return -EACCES;
trialcs = *cs;
/*
- * We allow a cpuset's mems_allowed to be empty; if it has attached
- * tasks, we'll catch it later when we validate the change and return
- * -ENOSPC.
+ * An empty mems_allowed is ok iff there are no tasks in the cpuset.
+ * Since nodelist_parse() fails on an empty mask, we special case
+ * that parsing. The validate_change() call ensures that cpusets
+ * with tasks have memory.
*/
- if (!buf[0] || (buf[0] == '\n' && !buf[1])) {
+ buf = strstrip(buf);
+ if (!*buf) {
nodes_clear(trialcs.mems_allowed);
} else {
retval = nodelist_parse(buf, trialcs.mems_allowed);
if (retval < 0)
goto done;
}
- nodes_and(trialcs.mems_allowed, trialcs.mems_allowed, node_online_map);
+ nodes_and(trialcs.mems_allowed, trialcs.mems_allowed,
+ node_states[N_HIGH_MEMORY]);
oldmem = cs->mems_allowed;
if (nodes_equal(oldmem, trialcs.mems_allowed)) {
retval = 0; /* Too easy - nothing to do */
goto done;
}
- /* mems_allowed cannot be empty for a cpuset with attached tasks. */
- if (atomic_read(&cs->count) && nodes_empty(trialcs.mems_allowed)) {
- retval = -ENOSPC;
- goto done;
- }
retval = validate_change(cs, &trialcs);
if (retval < 0)
goto done;
@@ -962,7 +962,7 @@ static int update_nodemask(struct cpuset *cs, char *buf)
cs->mems_generation = cpuset_mems_generation++;
mutex_unlock(&callback_mutex);
- set_cpuset_being_rebound(cs); /* causes mpol_copy() rebind */
+ cpuset_being_rebound = cs; /* causes mpol_copy() rebind */
fudge = 10; /* spare mmarray[] slots */
fudge += cpus_weight(cs->cpus_allowed); /* imagine one fork-bomb/cpu */
@@ -976,13 +976,13 @@ static int update_nodemask(struct cpuset *cs, char *buf)
* enough mmarray[] w/o using GFP_ATOMIC.
*/
while (1) {
- ntasks = atomic_read(&cs->count); /* guess */
+ ntasks = cgroup_task_count(cs->css.cgroup); /* guess */
ntasks += fudge;
mmarray = kmalloc(ntasks * sizeof(*mmarray), GFP_KERNEL);
if (!mmarray)
goto done;
read_lock(&tasklist_lock); /* block fork */
- if (atomic_read(&cs->count) <= ntasks)
+ if (cgroup_task_count(cs->css.cgroup) <= ntasks)
break; /* got enough */
read_unlock(&tasklist_lock); /* try again */
kfree(mmarray);
@@ -991,21 +991,21 @@ static int update_nodemask(struct cpuset *cs, char *buf)
n = 0;
/* Load up mmarray[] with mm reference for each task in cpuset. */
- do_each_thread(g, p) {
+ cgroup_iter_start(cs->css.cgroup, &it);
+ while ((p = cgroup_iter_next(cs->css.cgroup, &it))) {
struct mm_struct *mm;
if (n >= ntasks) {
printk(KERN_WARNING
"Cpuset mempolicy rebind incomplete.\n");
- continue;
+ break;
}
- if (p->cpuset != cs)
- continue;
mm = get_task_mm(p);
if (!mm)
continue;
mmarray[n++] = mm;
- } while_each_thread(g, p);
+ }
+ cgroup_iter_end(cs->css.cgroup, &it);
read_unlock(&tasklist_lock);
/*
@@ -1033,12 +1033,17 @@ static int update_nodemask(struct cpuset *cs, char *buf)
/* We're done rebinding vma's to this cpusets new mems_allowed. */
kfree(mmarray);
- set_cpuset_being_rebound(NULL);
+ cpuset_being_rebound = NULL;
retval = 0;
done:
return retval;
}
+int current_cpuset_is_being_rebound(void)
+{
+ return task_cs(current) == cpuset_being_rebound;
+}
+
/*
* Call with manage_mutex held.
*/
@@ -1055,6 +1060,7 @@ static int update_memory_pressure_enabled(struct cpuset *cs, char *buf)
/*
* update_flag - read a 0 or a 1 in a file and update associated flag
* bit: the bit to update (CS_CPU_EXCLUSIVE, CS_MEM_EXCLUSIVE,
+ * CS_SCHED_LOAD_BALANCE,
* CS_NOTIFY_ON_RELEASE, CS_MEMORY_MIGRATE,
* CS_SPREAD_PAGE, CS_SPREAD_SLAB)
* cs: the cpuset to update
@@ -1067,7 +1073,8 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs, char *buf)
{
int turning_on;
struct cpuset trialcs;
- int err, cpu_exclusive_changed;
+ int err;
+ int cpus_nonempty, balance_flag_changed;
turning_on = (simple_strtoul(buf, NULL, 10) != 0);
@@ -1080,14 +1087,18 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs, char *buf)
err = validate_change(cs, &trialcs);
if (err < 0)
return err;
- cpu_exclusive_changed =
- (is_cpu_exclusive(cs) != is_cpu_exclusive(&trialcs));
+
+ cpus_nonempty = !cpus_empty(trialcs.cpus_allowed);
+ balance_flag_changed = (is_sched_load_balance(cs) !=
+ is_sched_load_balance(&trialcs));
+
mutex_lock(&callback_mutex);
cs->flags = trialcs.flags;
mutex_unlock(&callback_mutex);
- if (cpu_exclusive_changed)
- update_cpu_domains(cs);
+ if (cpus_nonempty && balance_flag_changed)
+ rebuild_sched_domains();
+
return 0;
}
@@ -1189,85 +1200,34 @@ static int fmeter_getrate(struct fmeter *fmp)
return val;
}
-/*
- * Attack task specified by pid in 'pidbuf' to cpuset 'cs', possibly
- * writing the path of the old cpuset in 'ppathbuf' if it needs to be
- * notified on release.
- *
- * Call holding manage_mutex. May take callback_mutex and task_lock of
- * the task 'pid' during call.
- */
-
-static int attach_task(struct cpuset *cs, char *pidbuf, char **ppathbuf)
+static int cpuset_can_attach(struct cgroup_subsys *ss,
+ struct cgroup *cont, struct task_struct *tsk)
{
- pid_t pid;
- struct task_struct *tsk;
- struct cpuset *oldcs;
- cpumask_t cpus;
- nodemask_t from, to;
- struct mm_struct *mm;
- int retval;
+ struct cpuset *cs = cgroup_cs(cont);
- if (sscanf(pidbuf, "%d", &pid) != 1)
- return -EIO;
if (cpus_empty(cs->cpus_allowed) || nodes_empty(cs->mems_allowed))
return -ENOSPC;
- if (pid) {
- read_lock(&tasklist_lock);
-
- tsk = find_task_by_pid(pid);
- if (!tsk || tsk->flags & PF_EXITING) {
- read_unlock(&tasklist_lock);
- return -ESRCH;
- }
-
- get_task_struct(tsk);
- read_unlock(&tasklist_lock);
-
- if ((current->euid) && (current->euid != tsk->uid)
- && (current->euid != tsk->suid)) {
- put_task_struct(tsk);
- return -EACCES;
- }
- } else {
- tsk = current;
- get_task_struct(tsk);
- }
+ return security_task_setscheduler(tsk, 0, NULL);
+}
- retval = security_task_setscheduler(tsk, 0, NULL);
- if (retval) {
- put_task_struct(tsk);
- return retval;
- }
+static void cpuset_attach(struct cgroup_subsys *ss,
+ struct cgroup *cont, struct cgroup *oldcont,
+ struct task_struct *tsk)
+{
+ cpumask_t cpus;
+ nodemask_t from, to;
+ struct mm_struct *mm;
+ struct cpuset *cs = cgroup_cs(cont);
+ struct cpuset *oldcs = cgroup_cs(oldcont);
mutex_lock(&callback_mutex);
-
- task_lock(tsk);
- oldcs = tsk->cpuset;
- /*
- * After getting 'oldcs' cpuset ptr, be sure still not exiting.
- * If 'oldcs' might be the top_cpuset due to the_top_cpuset_hack
- * then fail this attach_task(), to avoid breaking top_cpuset.count.
- */
- if (tsk->flags & PF_EXITING) {
- task_unlock(tsk);
- mutex_unlock(&callback_mutex);
- put_task_struct(tsk);
- return -ESRCH;
- }
- atomic_inc(&cs->count);
- rcu_assign_pointer(tsk->cpuset, cs);
- task_unlock(tsk);
-
guarantee_online_cpus(cs, &cpus);
set_cpus_allowed(tsk, cpus);
+ mutex_unlock(&callback_mutex);
from = oldcs->mems_allowed;
to = cs->mems_allowed;
-
- mutex_unlock(&callback_mutex);
-
mm = get_task_mm(tsk);
if (mm) {
mpol_rebind_mm(mm, &to);
@@ -1276,44 +1236,36 @@ static int attach_task(struct cpuset *cs, char *pidbuf, char **ppathbuf)
mmput(mm);
}
- put_task_struct(tsk);
- synchronize_rcu();
- if (atomic_dec_and_test(&oldcs->count))
- check_for_release(oldcs, ppathbuf);
- return 0;
}
/* The various types of files and directories in a cpuset file system */
typedef enum {
- FILE_ROOT,
- FILE_DIR,
FILE_MEMORY_MIGRATE,
FILE_CPULIST,
FILE_MEMLIST,
FILE_CPU_EXCLUSIVE,
FILE_MEM_EXCLUSIVE,
- FILE_NOTIFY_ON_RELEASE,
+ FILE_SCHED_LOAD_BALANCE,
FILE_MEMORY_PRESSURE_ENABLED,
FILE_MEMORY_PRESSURE,
FILE_SPREAD_PAGE,
FILE_SPREAD_SLAB,
- FILE_TASKLIST,
} cpuset_filetype_t;
-static ssize_t cpuset_common_file_write(struct file *file,
+static ssize_t cpuset_common_file_write(struct cgroup *cont,
+ struct cftype *cft,
+ struct file *file,
const char __user *userbuf,
size_t nbytes, loff_t *unused_ppos)
{
- struct cpuset *cs = __d_cs(file->f_path.dentry->d_parent);
- struct cftype *cft = __d_cft(file->f_path.dentry);
+ struct cpuset *cs = cgroup_cs(cont);
cpuset_filetype_t type = cft->private;
char *buffer;
- char *pathbuf = NULL;
int retval = 0;
/* Crude upper limit on largest legitimate cpulist user might write. */
- if (nbytes > 100 + 6 * max(NR_CPUS, MAX_NUMNODES))
+ if (nbytes > 100U + 6 * max(NR_CPUS, MAX_NUMNODES))
return -E2BIG;
/* +1 for nul-terminator */
@@ -1326,9 +1278,9 @@ static ssize_t cpuset_common_file_write(struct file *file,
}
buffer[nbytes] = 0; /* nul-terminate */
- mutex_lock(&manage_mutex);
+ cgroup_lock();
- if (is_removed(cs)) {
+ if (cgroup_is_removed(cont)) {
retval = -ENODEV;
goto out2;
}
@@ -1346,8 +1298,8 @@ static ssize_t cpuset_common_file_write(struct file *file,
case FILE_MEM_EXCLUSIVE:
retval = update_flag(CS_MEM_EXCLUSIVE, cs, buffer);
break;
- case FILE_NOTIFY_ON_RELEASE:
- retval = update_flag(CS_NOTIFY_ON_RELEASE, cs, buffer);
+ case FILE_SCHED_LOAD_BALANCE:
+ retval = update_flag(CS_SCHED_LOAD_BALANCE, cs, buffer);
break;
case FILE_MEMORY_MIGRATE:
retval = update_flag(CS_MEMORY_MIGRATE, cs, buffer);
@@ -1366,9 +1318,6 @@ static ssize_t cpuset_common_file_write(struct file *file,
retval = update_flag(CS_SPREAD_SLAB, cs, buffer);
cs->mems_generation = cpuset_mems_generation++;
break;
- case FILE_TASKLIST:
- retval = attach_task(cs, buffer, &pathbuf);
- break;
default:
retval = -EINVAL;
goto out2;
@@ -1377,30 +1326,12 @@ static ssize_t cpuset_common_file_write(struct file *file,
if (retval == 0)
retval = nbytes;
out2:
- mutex_unlock(&manage_mutex);
- cpuset_release_agent(pathbuf);
+ cgroup_unlock();
out1:
kfree(buffer);
return retval;
}
-static ssize_t cpuset_file_write(struct file *file, const char __user *buf,
- size_t nbytes, loff_t *ppos)
-{
- ssize_t retval = 0;
- struct cftype *cft = __d_cft(file->f_path.dentry);
- if (!cft)
- return -ENODEV;
-
- /* special function ? */
- if (cft->write)
- retval = cft->write(file, buf, nbytes, ppos);
- else
- retval = cpuset_common_file_write(file, buf, nbytes, ppos);
-
- return retval;
-}
-
/*
* These ascii lists should be read in a single call, by using a user
* buffer large enough to hold the entire map. If read in smaller
@@ -1435,17 +1366,19 @@ static int cpuset_sprintf_memlist(char *page, struct cpuset *cs)
return nodelist_scnprintf(page, PAGE_SIZE, mask);
}
-static ssize_t cpuset_common_file_read(struct file *file, char __user *buf,
- size_t nbytes, loff_t *ppos)
+static ssize_t cpuset_common_file_read(struct cgroup *cont,
+ struct cftype *cft,
+ struct file *file,
+ char __user *buf,
+ size_t nbytes, loff_t *ppos)
{
- struct cftype *cft = __d_cft(file->f_path.dentry);
- struct cpuset *cs = __d_cs(file->f_path.dentry->d_parent);
+ struct cpuset *cs = cgroup_cs(cont);
cpuset_filetype_t type = cft->private;
char *page;
ssize_t retval = 0;
char *s;
- if (!(page = (char *)__get_free_page(GFP_KERNEL)))
+ if (!(page = (char *)__get_free_page(GFP_TEMPORARY)))
return -ENOMEM;
s = page;
@@ -1463,8 +1396,8 @@ static ssize_t cpuset_common_file_read(struct file *file, char __user *buf,
case FILE_MEM_EXCLUSIVE:
*s++ = is_mem_exclusive(cs) ? '1' : '0';
break;
- case FILE_NOTIFY_ON_RELEASE:
- *s++ = notify_on_release(cs) ? '1' : '0';
+ case FILE_SCHED_LOAD_BALANCE:
+ *s++ = is_sched_load_balance(cs) ? '1' : '0';
break;
case FILE_MEMORY_MIGRATE:
*s++ = is_memory_migrate(cs) ? '1' : '0';
@@ -1493,390 +1426,150 @@ out:
return retval;
}
-static ssize_t cpuset_file_read(struct file *file, char __user *buf, size_t nbytes,
- loff_t *ppos)
-{
- ssize_t retval = 0;
- struct cftype *cft = __d_cft(file->f_path.dentry);
- if (!cft)
- return -ENODEV;
- /* special function ? */
- if (cft->read)
- retval = cft->read(file, buf, nbytes, ppos);
- else
- retval = cpuset_common_file_read(file, buf, nbytes, ppos);
- return retval;
-}
-static int cpuset_file_open(struct inode *inode, struct file *file)
-{
- int err;
- struct cftype *cft;
-
- err = generic_file_open(inode, file);
- if (err)
- return err;
-
- cft = __d_cft(file->f_path.dentry);
- if (!cft)
- return -ENODEV;
- if (cft->open)
- err = cft->open(inode, file);
- else
- err = 0;
-
- return err;
-}
-
-static int cpuset_file_release(struct inode *inode, struct file *file)
-{
- struct cftype *cft = __d_cft(file->f_path.dentry);
- if (cft->release)
- return cft->release(inode, file);
- return 0;
-}
-
-/*
- * cpuset_rename - Only allow simple rename of directories in place.
- */
-static int cpuset_rename(struct inode *old_dir, struct dentry *old_dentry,
- struct inode *new_dir, struct dentry *new_dentry)
-{
- if (!S_ISDIR(old_dentry->d_inode->i_mode))
- return -ENOTDIR;
- if (new_dentry->d_inode)
- return -EEXIST;
- if (old_dir != new_dir)
- return -EIO;
- return simple_rename(old_dir, old_dentry, new_dir, new_dentry);
-}
-
-static const struct file_operations cpuset_file_operations = {
- .read = cpuset_file_read,
- .write = cpuset_file_write,
- .llseek = generic_file_llseek,
- .open = cpuset_file_open,
- .release = cpuset_file_release,
-};
-
-static const struct inode_operations cpuset_dir_inode_operations = {
- .lookup = simple_lookup,
- .mkdir = cpuset_mkdir,
- .rmdir = cpuset_rmdir,
- .rename = cpuset_rename,
-};
-
-static int cpuset_create_file(struct dentry *dentry, int mode)
-{
- struct inode *inode;
-
- if (!dentry)
- return -ENOENT;
- if (dentry->d_inode)
- return -EEXIST;
-
- inode = cpuset_new_inode(mode);
- if (!inode)
- return -ENOMEM;
-
- if (S_ISDIR(mode)) {
- inode->i_op = &cpuset_dir_inode_operations;
- inode->i_fop = &simple_dir_operations;
-
- /* start off with i_nlink == 2 (for "." entry) */
- inc_nlink(inode);
- } else if (S_ISREG(mode)) {
- inode->i_size = 0;
- inode->i_fop = &cpuset_file_operations;
- }
-
- d_instantiate(dentry, inode);
- dget(dentry); /* Extra count - pin the dentry in core */
- return 0;
-}
-
-/*
- * cpuset_create_dir - create a directory for an object.
- * cs: the cpuset we create the directory for.
- * It must have a valid ->parent field
- * And we are going to fill its ->dentry field.
- * name: The name to give to the cpuset directory. Will be copied.
- * mode: mode to set on new directory.
- */
-
-static int cpuset_create_dir(struct cpuset *cs, const char *name, int mode)
-{
- struct dentry *dentry = NULL;
- struct dentry *parent;
- int error = 0;
-
- parent = cs->parent->dentry;
- dentry = cpuset_get_dentry(parent, name);
- if (IS_ERR(dentry))
- return PTR_ERR(dentry);
- error = cpuset_create_file(dentry, S_IFDIR | mode);
- if (!error) {
- dentry->d_fsdata = cs;
- inc_nlink(parent->d_inode);
- cs->dentry = dentry;
- }
- dput(dentry);
-
- return error;
-}
-
-static int cpuset_add_file(struct dentry *dir, const struct cftype *cft)
-{
- struct dentry *dentry;
- int error;
-
- mutex_lock(&dir->d_inode->i_mutex);
- dentry = cpuset_get_dentry(dir, cft->name);
- if (!IS_ERR(dentry)) {
- error = cpuset_create_file(dentry, 0644 | S_IFREG);
- if (!error)
- dentry->d_fsdata = (void *)cft;
- dput(dentry);
- } else
- error = PTR_ERR(dentry);
- mutex_unlock(&dir->d_inode->i_mutex);
- return error;
-}
-
-/*
- * Stuff for reading the 'tasks' file.
- *
- * Reading this file can return large amounts of data if a cpuset has
- * *lots* of attached tasks. So it may need several calls to read(),
- * but we cannot guarantee that the information we produce is correct
- * unless we produce it entirely atomically.
- *
- * Upon tasks file open(), a struct ctr_struct is allocated, that
- * will have a pointer to an array (also allocated here). The struct
- * ctr_struct * is stored in file->private_data. Its resources will
- * be freed by release() when the file is closed. The array is used
- * to sprintf the PIDs and then used by read().
- */
-
-/* cpusets_tasks_read array */
-
-struct ctr_struct {
- char *buf;
- int bufsz;
-};
-
-/*
- * Load into 'pidarray' up to 'npids' of the tasks using cpuset 'cs'.
- * Return actual number of pids loaded. No need to task_lock(p)
- * when reading out p->cpuset, as we don't really care if it changes
- * on the next cycle, and we are not going to try to dereference it.
- */
-static int pid_array_load(pid_t *pidarray, int npids, struct cpuset *cs)
-{
- int n = 0;
- struct task_struct *g, *p;
-
- read_lock(&tasklist_lock);
-
- do_each_thread(g, p) {
- if (p->cpuset == cs) {
- if (unlikely(n == npids))
- goto array_full;
- pidarray[n++] = p->pid;
- }
- } while_each_thread(g, p);
-
-array_full:
- read_unlock(&tasklist_lock);
- return n;
-}
-
-static int cmppid(const void *a, const void *b)
-{
- return *(pid_t *)a - *(pid_t *)b;
-}
-
-/*
- * Convert array 'a' of 'npids' pid_t's to a string of newline separated
- * decimal pids in 'buf'. Don't write more than 'sz' chars, but return
- * count 'cnt' of how many chars would be written if buf were large enough.
- */
-static int pid_array_to_buf(char *buf, int sz, pid_t *a, int npids)
-{
- int cnt = 0;
- int i;
-
- for (i = 0; i < npids; i++)
- cnt += snprintf(buf + cnt, max(sz - cnt, 0), "%d\n", a[i]);
- return cnt;
-}
-
-/*
- * Handle an open on 'tasks' file. Prepare a buffer listing the
- * process id's of tasks currently attached to the cpuset being opened.
- *
- * Does not require any specific cpuset mutexes, and does not take any.
- */
-static int cpuset_tasks_open(struct inode *unused, struct file *file)
-{
- struct cpuset *cs = __d_cs(file->f_path.dentry->d_parent);
- struct ctr_struct *ctr;
- pid_t *pidarray;
- int npids;
- char c;
-
- if (!(file->f_mode & FMODE_READ))
- return 0;
-
- ctr = kmalloc(sizeof(*ctr), GFP_KERNEL);
- if (!ctr)
- goto err0;
-
- /*
- * If cpuset gets more users after we read count, we won't have
- * enough space - tough. This race is indistinguishable to the
- * caller from the case that the additional cpuset users didn't
- * show up until sometime later on.
- */
- npids = atomic_read(&cs->count);
- pidarray = kmalloc(npids * sizeof(pid_t), GFP_KERNEL);
- if (!pidarray)
- goto err1;
-
- npids = pid_array_load(pidarray, npids, cs);
- sort(pidarray, npids, sizeof(pid_t), cmppid, NULL);
-
- /* Call pid_array_to_buf() twice, first just to get bufsz */
- ctr->bufsz = pid_array_to_buf(&c, sizeof(c), pidarray, npids) + 1;
- ctr->buf = kmalloc(ctr->bufsz, GFP_KERNEL);
- if (!ctr->buf)
- goto err2;
- ctr->bufsz = pid_array_to_buf(ctr->buf, ctr->bufsz, pidarray, npids);
-
- kfree(pidarray);
- file->private_data = ctr;
- return 0;
-
-err2:
- kfree(pidarray);
-err1:
- kfree(ctr);
-err0:
- return -ENOMEM;
-}
-
-static ssize_t cpuset_tasks_read(struct file *file, char __user *buf,
- size_t nbytes, loff_t *ppos)
-{
- struct ctr_struct *ctr = file->private_data;
-
- return simple_read_from_buffer(buf, nbytes, ppos, ctr->buf, ctr->bufsz);
-}
-
-static int cpuset_tasks_release(struct inode *unused_inode, struct file *file)
-{
- struct ctr_struct *ctr;
-
- if (file->f_mode & FMODE_READ) {
- ctr = file->private_data;
- kfree(ctr->buf);
- kfree(ctr);
- }
- return 0;
-}
/*
* for the common functions, 'private' gives the type of file
*/
-static struct cftype cft_tasks = {
- .name = "tasks",
- .open = cpuset_tasks_open,
- .read = cpuset_tasks_read,
- .release = cpuset_tasks_release,
- .private = FILE_TASKLIST,
-};
-
static struct cftype cft_cpus = {
.name = "cpus",
+ .read = cpuset_common_file_read,
+ .write = cpuset_common_file_write,
.private = FILE_CPULIST,
};
static struct cftype cft_mems = {
.name = "mems",
+ .read = cpuset_common_file_read,
+ .write = cpuset_common_file_write,
.private = FILE_MEMLIST,
};
static struct cftype cft_cpu_exclusive = {
.name = "cpu_exclusive",
+ .read = cpuset_common_file_read,
+ .write = cpuset_common_file_write,
.private = FILE_CPU_EXCLUSIVE,
};
static struct cftype cft_mem_exclusive = {
.name = "mem_exclusive",
+ .read = cpuset_common_file_read,
+ .write = cpuset_common_file_write,
.private = FILE_MEM_EXCLUSIVE,
};
-static struct cftype cft_notify_on_release = {
- .name = "notify_on_release",
- .private = FILE_NOTIFY_ON_RELEASE,
+static struct cftype cft_sched_load_balance = {
+ .name = "sched_load_balance",
+ .read = cpuset_common_file_read,
+ .write = cpuset_common_file_write,
+ .private = FILE_SCHED_LOAD_BALANCE,
};
static struct cftype cft_memory_migrate = {
.name = "memory_migrate",
+ .read = cpuset_common_file_read,
+ .write = cpuset_common_file_write,
.private = FILE_MEMORY_MIGRATE,
};
static struct cftype cft_memory_pressure_enabled = {
.name = "memory_pressure_enabled",
+ .read = cpuset_common_file_read,
+ .write = cpuset_common_file_write,
.private = FILE_MEMORY_PRESSURE_ENABLED,
};
static struct cftype cft_memory_pressure = {
.name = "memory_pressure",
+ .read = cpuset_common_file_read,
+ .write = cpuset_common_file_write,
.private = FILE_MEMORY_PRESSURE,
};
static struct cftype cft_spread_page = {
.name = "memory_spread_page",
+ .read = cpuset_common_file_read,
+ .write = cpuset_common_file_write,
.private = FILE_SPREAD_PAGE,
};
static struct cftype cft_spread_slab = {
.name = "memory_spread_slab",
+ .read = cpuset_common_file_read,
+ .write = cpuset_common_file_write,
.private = FILE_SPREAD_SLAB,
};
-static int cpuset_populate_dir(struct dentry *cs_dentry)
+static int cpuset_populate(struct cgroup_subsys *ss, struct cgroup *cont)
{
int err;
- if ((err = cpuset_add_file(cs_dentry, &cft_cpus)) < 0)
- return err;
- if ((err = cpuset_add_file(cs_dentry, &cft_mems)) < 0)
+ if ((err = cgroup_add_file(cont, ss, &cft_cpus)) < 0)
return err;
- if ((err = cpuset_add_file(cs_dentry, &cft_cpu_exclusive)) < 0)
+ if ((err = cgroup_add_file(cont, ss, &cft_mems)) < 0)
return err;
- if ((err = cpuset_add_file(cs_dentry, &cft_mem_exclusive)) < 0)
+ if ((err = cgroup_add_file(cont, ss, &cft_cpu_exclusive)) < 0)
return err;
- if ((err = cpuset_add_file(cs_dentry, &cft_notify_on_release)) < 0)
+ if ((err = cgroup_add_file(cont, ss, &cft_mem_exclusive)) < 0)
return err;
- if ((err = cpuset_add_file(cs_dentry, &cft_memory_migrate)) < 0)
+ if ((err = cgroup_add_file(cont, ss, &cft_memory_migrate)) < 0)
return err;
- if ((err = cpuset_add_file(cs_dentry, &cft_memory_pressure)) < 0)
+ if ((err = cgroup_add_file(cont, ss, &cft_sched_load_balance)) < 0)
return err;
- if ((err = cpuset_add_file(cs_dentry, &cft_spread_page)) < 0)
+ if ((err = cgroup_add_file(cont, ss, &cft_memory_pressure)) < 0)
return err;
- if ((err = cpuset_add_file(cs_dentry, &cft_spread_slab)) < 0)
+ if ((err = cgroup_add_file(cont, ss, &cft_spread_page)) < 0)
return err;
- if ((err = cpuset_add_file(cs_dentry, &cft_tasks)) < 0)
+ if ((err = cgroup_add_file(cont, ss, &cft_spread_slab)) < 0)
return err;
+ /* memory_pressure_enabled is in root cpuset only */
+ if (err == 0 && !cont->parent)
+ err = cgroup_add_file(cont, ss,
+ &cft_memory_pressure_enabled);
return 0;
}
/*
+ * post_clone() is called at the end of cgroup_clone().
+ * 'cgroup' was just created automatically as a result of
+ * a cgroup_clone(), and the current task is about to
+ * be moved into 'cgroup'.
+ *
+ * Currently we refuse to set up the cgroup - thereby
+ * refusing the task to be entered, and as a result refusing
+ * the sys_unshare() or clone() which initiated it - if any
+ * sibling cpusets have exclusive cpus or mem.
+ *
+ * If this becomes a problem for some users who wish to
+ * allow that scenario, then cpuset_post_clone() could be
+ * changed to grant parent->cpus_allowed-sibling_cpus_exclusive
+ * (and likewise for mems) to the new cgroup.
+ */
+static void cpuset_post_clone(struct cgroup_subsys *ss,
+ struct cgroup *cgroup)
+{
+ struct cgroup *parent, *child;
+ struct cpuset *cs, *parent_cs;
+
+ parent = cgroup->parent;
+ list_for_each_entry(child, &parent->children, sibling) {
+ cs = cgroup_cs(child);
+ if (is_mem_exclusive(cs) || is_cpu_exclusive(cs))
+ return;
+ }
+ cs = cgroup_cs(cgroup);
+ parent_cs = cgroup_cs(parent);
+
+ cs->mems_allowed = parent_cs->mems_allowed;
+ cs->cpus_allowed = parent_cs->cpus_allowed;
+ return;
+}
+
+/*
* cpuset_create - create a cpuset
* parent: cpuset that will be parent of the new cpuset.
* name: name of the new cpuset. Will be strcpy'ed.
@@ -1885,124 +1578,77 @@ static int cpuset_populate_dir(struct dentry *cs_dentry)
* Must be called with the mutex on the parent inode held
*/
-static long cpuset_create(struct cpuset *parent, const char *name, int mode)
+static struct cgroup_subsys_state *cpuset_create(
+ struct cgroup_subsys *ss,
+ struct cgroup *cont)
{
struct cpuset *cs;
- int err;
+ struct cpuset *parent;
+ if (!cont->parent) {
+ /* This is early initialization for the top cgroup */
+ top_cpuset.mems_generation = cpuset_mems_generation++;
+ return &top_cpuset.css;
+ }
+ parent = cgroup_cs(cont->parent);
cs = kmalloc(sizeof(*cs), GFP_KERNEL);
if (!cs)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
- mutex_lock(&manage_mutex);
cpuset_update_task_memory_state();
cs->flags = 0;
- if (notify_on_release(parent))
- set_bit(CS_NOTIFY_ON_RELEASE, &cs->flags);
if (is_spread_page(parent))
set_bit(CS_SPREAD_PAGE, &cs->flags);
if (is_spread_slab(parent))
set_bit(CS_SPREAD_SLAB, &cs->flags);
+ set_bit(CS_SCHED_LOAD_BALANCE, &cs->flags);
cs->cpus_allowed = CPU_MASK_NONE;
cs->mems_allowed = NODE_MASK_NONE;
- atomic_set(&cs->count, 0);
- INIT_LIST_HEAD(&cs->sibling);
- INIT_LIST_HEAD(&cs->children);
cs->mems_generation = cpuset_mems_generation++;
fmeter_init(&cs->fmeter);
cs->parent = parent;
-
- mutex_lock(&callback_mutex);
- list_add(&cs->sibling, &cs->parent->children);
number_of_cpusets++;
- mutex_unlock(&callback_mutex);
-
- err = cpuset_create_dir(cs, name, mode);
- if (err < 0)
- goto err;
-
- /*
- * Release manage_mutex before cpuset_populate_dir() because it
- * will down() this new directory's i_mutex and if we race with
- * another mkdir, we might deadlock.
- */
- mutex_unlock(&manage_mutex);
-
- err = cpuset_populate_dir(cs->dentry);
- /* If err < 0, we have a half-filled directory - oh well ;) */
- return 0;
-err:
- list_del(&cs->sibling);
- mutex_unlock(&manage_mutex);
- kfree(cs);
- return err;
-}
-
-static int cpuset_mkdir(struct inode *dir, struct dentry *dentry, int mode)
-{
- struct cpuset *c_parent = dentry->d_parent->d_fsdata;
-
- /* the vfs holds inode->i_mutex already */
- return cpuset_create(c_parent, dentry->d_name.name, mode | S_IFDIR);
+ return &cs->css ;
}
/*
* Locking note on the strange update_flag() call below:
*
- * If the cpuset being removed is marked cpu_exclusive, then simulate
- * turning cpu_exclusive off, which will call update_cpu_domains().
- * The lock_cpu_hotplug() call in update_cpu_domains() must not be
- * made while holding callback_mutex. Elsewhere the kernel nests
- * callback_mutex inside lock_cpu_hotplug() calls. So the reverse
- * nesting would risk an ABBA deadlock.
+ * If the cpuset being removed has its flag 'sched_load_balance'
+ * enabled, then simulate turning sched_load_balance off, which
+ * will call rebuild_sched_domains(). The lock_cpu_hotplug()
+ * call in rebuild_sched_domains() must not be made while holding
+ * callback_mutex. Elsewhere the kernel nests callback_mutex inside
+ * lock_cpu_hotplug() calls. So the reverse nesting would risk an
+ * ABBA deadlock.
*/
-static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry)
+static void cpuset_destroy(struct cgroup_subsys *ss, struct cgroup *cont)
{
- struct cpuset *cs = dentry->d_fsdata;
- struct dentry *d;
- struct cpuset *parent;
- char *pathbuf = NULL;
-
- /* the vfs holds both inode->i_mutex already */
+ struct cpuset *cs = cgroup_cs(cont);
- mutex_lock(&manage_mutex);
cpuset_update_task_memory_state();
- if (atomic_read(&cs->count) > 0) {
- mutex_unlock(&manage_mutex);
- return -EBUSY;
- }
- if (!list_empty(&cs->children)) {
- mutex_unlock(&manage_mutex);
- return -EBUSY;
- }
- if (is_cpu_exclusive(cs)) {
- int retval = update_flag(CS_CPU_EXCLUSIVE, cs, "0");
- if (retval < 0) {
- mutex_unlock(&manage_mutex);
- return retval;
- }
- }
- parent = cs->parent;
- mutex_lock(&callback_mutex);
- set_bit(CS_REMOVED, &cs->flags);
- list_del(&cs->sibling); /* delete my sibling from parent->children */
- spin_lock(&cs->dentry->d_lock);
- d = dget(cs->dentry);
- cs->dentry = NULL;
- spin_unlock(&d->d_lock);
- cpuset_d_remove_dir(d);
- dput(d);
+
+ if (is_sched_load_balance(cs))
+ update_flag(CS_SCHED_LOAD_BALANCE, cs, "0");
+
number_of_cpusets--;
- mutex_unlock(&callback_mutex);
- if (list_empty(&parent->children))
- check_for_release(parent, &pathbuf);
- mutex_unlock(&manage_mutex);
- cpuset_release_agent(pathbuf);
- return 0;
+ kfree(cs);
}
+struct cgroup_subsys cpuset_subsys = {
+ .name = "cpuset",
+ .create = cpuset_create,
+ .destroy = cpuset_destroy,
+ .can_attach = cpuset_can_attach,
+ .attach = cpuset_attach,
+ .populate = cpuset_populate,
+ .post_clone = cpuset_post_clone,
+ .subsys_id = cpuset_subsys_id,
+ .early_init = 1,
+};
+
/*
* cpuset_init_early - just enough so that the calls to
* cpuset_update_task_memory_state() in early init code
@@ -2011,13 +1657,11 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry)
int __init cpuset_init_early(void)
{
- struct task_struct *tsk = current;
-
- tsk->cpuset = &top_cpuset;
- tsk->cpuset->mems_generation = cpuset_mems_generation++;
+ top_cpuset.mems_generation = cpuset_mems_generation++;
return 0;
}
+
/**
* cpuset_init - initialize cpusets at system boot
*
@@ -2026,39 +1670,21 @@ int __init cpuset_init_early(void)
int __init cpuset_init(void)
{
- struct dentry *root;
- int err;
+ int err = 0;
top_cpuset.cpus_allowed = CPU_MASK_ALL;
top_cpuset.mems_allowed = NODE_MASK_ALL;
fmeter_init(&top_cpuset.fmeter);
top_cpuset.mems_generation = cpuset_mems_generation++;
-
- init_task.cpuset = &top_cpuset;
+ set_bit(CS_SCHED_LOAD_BALANCE, &top_cpuset.flags);
err = register_filesystem(&cpuset_fs_type);
if (err < 0)
- goto out;
- cpuset_mount = kern_mount(&cpuset_fs_type);
- if (IS_ERR(cpuset_mount)) {
- printk(KERN_ERR "cpuset: could not mount!\n");
- err = PTR_ERR(cpuset_mount);
- cpuset_mount = NULL;
- goto out;
- }
- root = cpuset_mount->mnt_sb->s_root;
- root->d_fsdata = &top_cpuset;
- inc_nlink(root->d_inode);
- top_cpuset.dentry = root;
- root->d_inode->i_op = &cpuset_dir_inode_operations;
+ return err;
+
number_of_cpusets = 1;
- err = cpuset_populate_dir(root);
- /* memory_pressure_enabled is in root cpuset only */
- if (err == 0)
- err = cpuset_add_file(root, &cft_memory_pressure_enabled);
-out:
- return err;
+ return 0;
}
/*
@@ -2084,10 +1710,12 @@ out:
static void guarantee_online_cpus_mems_in_subtree(const struct cpuset *cur)
{
+ struct cgroup *cont;
struct cpuset *c;
/* Each of our child cpusets mems must be online */
- list_for_each_entry(c, &cur->children, sibling) {
+ list_for_each_entry(cont, &cur->css.cgroup->children, sibling) {
+ c = cgroup_cs(cont);
guarantee_online_cpus_mems_in_subtree(c);
if (!cpus_empty(c->cpus_allowed))
guarantee_online_cpus(c, &c->cpus_allowed);
@@ -2098,8 +1726,9 @@ static void guarantee_online_cpus_mems_in_subtree(const struct cpuset *cur)
/*
* The cpus_allowed and mems_allowed nodemasks in the top_cpuset track
- * cpu_online_map and node_online_map. Force the top cpuset to track
- * whats online after any CPU or memory node hotplug or unplug event.
+ * cpu_online_map and node_states[N_HIGH_MEMORY]. Force the top cpuset to
+ * track what's online after any CPU or memory node hotplug or unplug
+ * event.
*
* To ensure that we don't remove a CPU or node from the top cpuset
* that is currently in use by a child cpuset (which would violate
@@ -2114,15 +1743,15 @@ static void guarantee_online_cpus_mems_in_subtree(const struct cpuset *cur)
static void common_cpu_mem_hotplug_unplug(void)
{
- mutex_lock(&manage_mutex);
+ cgroup_lock();
mutex_lock(&callback_mutex);
guarantee_online_cpus_mems_in_subtree(&top_cpuset);
top_cpuset.cpus_allowed = cpu_online_map;
- top_cpuset.mems_allowed = node_online_map;
+ top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY];
mutex_unlock(&callback_mutex);
- mutex_unlock(&manage_mutex);
+ cgroup_unlock();
}
/*
@@ -2135,8 +1764,8 @@ static void common_cpu_mem_hotplug_unplug(void)
* cpu_online_map on each CPU hotplug (cpuhp) event.
*/
-static int cpuset_handle_cpuhp(struct notifier_block *nb,
- unsigned long phase, void *cpu)
+static int cpuset_handle_cpuhp(struct notifier_block *unused_nb,
+ unsigned long phase, void *unused_cpu)
{
if (phase == CPU_DYING || phase == CPU_DYING_FROZEN)
return NOTIFY_DONE;
@@ -2147,8 +1776,9 @@ static int cpuset_handle_cpuhp(struct notifier_block *nb,
#ifdef CONFIG_MEMORY_HOTPLUG
/*
- * Keep top_cpuset.mems_allowed tracking node_online_map.
- * Call this routine anytime after you change node_online_map.
+ * Keep top_cpuset.mems_allowed tracking node_states[N_HIGH_MEMORY].
+ * Call this routine anytime after you change
+ * node_states[N_HIGH_MEMORY].
* See also the previous routine cpuset_handle_cpuhp().
*/
@@ -2167,115 +1797,13 @@ void cpuset_track_online_nodes(void)
void __init cpuset_init_smp(void)
{
top_cpuset.cpus_allowed = cpu_online_map;
- top_cpuset.mems_allowed = node_online_map;
+ top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY];
hotcpu_notifier(cpuset_handle_cpuhp, 0);
}
/**
- * cpuset_fork - attach newly forked task to its parents cpuset.
- * @tsk: pointer to task_struct of forking parent process.
- *
- * Description: A task inherits its parent's cpuset at fork().
- *
- * A pointer to the shared cpuset was automatically copied in fork.c
- * by dup_task_struct(). However, we ignore that copy, since it was
- * not made under the protection of task_lock(), so might no longer be
- * a valid cpuset pointer. attach_task() might have already changed
- * current->cpuset, allowing the previously referenced cpuset to
- * be removed and freed. Instead, we task_lock(current) and copy
- * its present value of current->cpuset for our freshly forked child.
- *
- * At the point that cpuset_fork() is called, 'current' is the parent
- * task, and the passed argument 'child' points to the child task.
- **/
-
-void cpuset_fork(struct task_struct *child)
-{
- task_lock(current);
- child->cpuset = current->cpuset;
- atomic_inc(&child->cpuset->count);
- task_unlock(current);
-}
-
-/**
- * cpuset_exit - detach cpuset from exiting task
- * @tsk: pointer to task_struct of exiting process
- *
- * Description: Detach cpuset from @tsk and release it.
- *
- * Note that cpusets marked notify_on_release force every task in
- * them to take the global manage_mutex mutex when exiting.
- * This could impact scaling on very large systems. Be reluctant to
- * use notify_on_release cpusets where very high task exit scaling
- * is required on large systems.
- *
- * Don't even think about derefencing 'cs' after the cpuset use count
- * goes to zero, except inside a critical section guarded by manage_mutex
- * or callback_mutex. Otherwise a zero cpuset use count is a license to
- * any other task to nuke the cpuset immediately, via cpuset_rmdir().
- *
- * This routine has to take manage_mutex, not callback_mutex, because
- * it is holding that mutex while calling check_for_release(),
- * which calls kmalloc(), so can't be called holding callback_mutex().
- *
- * the_top_cpuset_hack:
- *
- * Set the exiting tasks cpuset to the root cpuset (top_cpuset).
- *
- * Don't leave a task unable to allocate memory, as that is an
- * accident waiting to happen should someone add a callout in
- * do_exit() after the cpuset_exit() call that might allocate.
- * If a task tries to allocate memory with an invalid cpuset,
- * it will oops in cpuset_update_task_memory_state().
- *
- * We call cpuset_exit() while the task is still competent to
- * handle notify_on_release(), then leave the task attached to
- * the root cpuset (top_cpuset) for the remainder of its exit.
- *
- * To do this properly, we would increment the reference count on
- * top_cpuset, and near the very end of the kernel/exit.c do_exit()
- * code we would add a second cpuset function call, to drop that
- * reference. This would just create an unnecessary hot spot on
- * the top_cpuset reference count, to no avail.
- *
- * Normally, holding a reference to a cpuset without bumping its
- * count is unsafe. The cpuset could go away, or someone could
- * attach us to a different cpuset, decrementing the count on
- * the first cpuset that we never incremented. But in this case,
- * top_cpuset isn't going away, and either task has PF_EXITING set,
- * which wards off any attach_task() attempts, or task is a failed
- * fork, never visible to attach_task.
- *
- * Another way to do this would be to set the cpuset pointer
- * to NULL here, and check in cpuset_update_task_memory_state()
- * for a NULL pointer. This hack avoids that NULL check, for no
- * cost (other than this way too long comment ;).
- **/
-
-void cpuset_exit(struct task_struct *tsk)
-{
- struct cpuset *cs;
-
- task_lock(current);
- cs = tsk->cpuset;
- tsk->cpuset = &top_cpuset; /* the_top_cpuset_hack - see above */
- task_unlock(current);
-
- if (notify_on_release(cs)) {
- char *pathbuf = NULL;
-
- mutex_lock(&manage_mutex);
- if (atomic_dec_and_test(&cs->count))
- check_for_release(cs, &pathbuf);
- mutex_unlock(&manage_mutex);
- cpuset_release_agent(pathbuf);
- } else {
- atomic_dec(&cs->count);
- }
-}
-/**
* cpuset_cpus_allowed - return cpus_allowed mask from a tasks cpuset.
* @tsk: pointer to task_struct from which to obtain cpuset->cpus_allowed.
*
@@ -2290,10 +1818,23 @@ cpumask_t cpuset_cpus_allowed(struct task_struct *tsk)
cpumask_t mask;
mutex_lock(&callback_mutex);
+ mask = cpuset_cpus_allowed_locked(tsk);
+ mutex_unlock(&callback_mutex);
+
+ return mask;
+}
+
+/**
+ * cpuset_cpus_allowed_locked - return cpus_allowed mask from a tasks cpuset.
+ * Must be called with callback_mutex held.
+ **/
+cpumask_t cpuset_cpus_allowed_locked(struct task_struct *tsk)
+{
+ cpumask_t mask;
+
task_lock(tsk);
- guarantee_online_cpus(tsk->cpuset, &mask);
+ guarantee_online_cpus(task_cs(tsk), &mask);
task_unlock(tsk);
- mutex_unlock(&callback_mutex);
return mask;
}
@@ -2309,7 +1850,7 @@ void cpuset_init_current_mems_allowed(void)
*
* Description: Returns the nodemask_t mems_allowed of the cpuset
* attached to the specified @tsk. Guaranteed to return some non-empty
- * subset of node_online_map, even if this means going outside the
+ * subset of node_states[N_HIGH_MEMORY], even if this means going outside the
* tasks cpuset.
**/
@@ -2319,7 +1860,7 @@ nodemask_t cpuset_mems_allowed(struct task_struct *tsk)
mutex_lock(&callback_mutex);
task_lock(tsk);
- guarantee_online_mems(tsk->cpuset, &mask);
+ guarantee_online_mems(task_cs(tsk), &mask);
task_unlock(tsk);
mutex_unlock(&callback_mutex);
@@ -2450,7 +1991,7 @@ int __cpuset_zone_allowed_softwall(struct zone *z, gfp_t gfp_mask)
mutex_lock(&callback_mutex);
task_lock(current);
- cs = nearest_exclusive_ancestor(current->cpuset);
+ cs = nearest_exclusive_ancestor(task_cs(current));
task_unlock(current);
allowed = node_isset(node, cs->mems_allowed);
@@ -2491,12 +2032,12 @@ int __cpuset_zone_allowed_hardwall(struct zone *z, gfp_t gfp_mask)
node = zone_to_nid(z);
if (node_isset(node, current->mems_allowed))
return 1;
- /*
- * Allow tasks that have access to memory reserves because they have
- * been OOM killed to get memory anywhere.
- */
- if (unlikely(test_thread_flag(TIF_MEMDIE)))
- return 1;
+ /*
+ * Allow tasks that have access to memory reserves because they have
+ * been OOM killed to get memory anywhere.
+ */
+ if (unlikely(test_thread_flag(TIF_MEMDIE)))
+ return 1;
return 0;
}
@@ -2566,41 +2107,20 @@ int cpuset_mem_spread_node(void)
EXPORT_SYMBOL_GPL(cpuset_mem_spread_node);
/**
- * cpuset_excl_nodes_overlap - Do we overlap @p's mem_exclusive ancestors?
- * @p: pointer to task_struct of some other task.
- *
- * Description: Return true if the nearest mem_exclusive ancestor
- * cpusets of tasks @p and current overlap. Used by oom killer to
- * determine if task @p's memory usage might impact the memory
- * available to the current task.
- *
- * Call while holding callback_mutex.
+ * cpuset_mems_allowed_intersects - Does @tsk1's mems_allowed intersect @tsk2's?
+ * @tsk1: pointer to task_struct of some task.
+ * @tsk2: pointer to task_struct of some other task.
+ *
+ * Description: Return true if @tsk1's mems_allowed intersects the
+ * mems_allowed of @tsk2. Used by the OOM killer to determine if
+ * one of the task's memory usage might impact the memory available
+ * to the other.
**/
-int cpuset_excl_nodes_overlap(const struct task_struct *p)
+int cpuset_mems_allowed_intersects(const struct task_struct *tsk1,
+ const struct task_struct *tsk2)
{
- const struct cpuset *cs1, *cs2; /* my and p's cpuset ancestors */
- int overlap = 1; /* do cpusets overlap? */
-
- task_lock(current);
- if (current->flags & PF_EXITING) {
- task_unlock(current);
- goto done;
- }
- cs1 = nearest_exclusive_ancestor(current->cpuset);
- task_unlock(current);
-
- task_lock((struct task_struct *)p);
- if (p->flags & PF_EXITING) {
- task_unlock((struct task_struct *)p);
- goto done;
- }
- cs2 = nearest_exclusive_ancestor(p->cpuset);
- task_unlock((struct task_struct *)p);
-
- overlap = nodes_intersects(cs1->mems_allowed, cs2->mems_allowed);
-done:
- return overlap;
+ return nodes_intersects(tsk1->mems_allowed, tsk2->mems_allowed);
}
/*
@@ -2631,14 +2151,12 @@ int cpuset_memory_pressure_enabled __read_mostly;
void __cpuset_memory_pressure_bump(void)
{
- struct cpuset *cs;
-
task_lock(current);
- cs = current->cpuset;
- fmeter_markevent(&cs->fmeter);
+ fmeter_markevent(&task_cs(current)->fmeter);
task_unlock(current);
}
+#ifdef CONFIG_PROC_PID_CPUSET
/*
* proc_cpuset_show()
* - Print tasks cpuset path into seq_file.
@@ -2650,11 +2168,12 @@ void __cpuset_memory_pressure_bump(void)
* the_top_cpuset_hack in cpuset_exit(), which sets an exiting tasks
* cpuset to top_cpuset.
*/
-static int proc_cpuset_show(struct seq_file *m, void *v)
+static int proc_cpuset_show(struct seq_file *m, void *unused_v)
{
struct pid *pid;
struct task_struct *tsk;
char *buf;
+ struct cgroup_subsys_state *css;
int retval;
retval = -ENOMEM;
@@ -2669,15 +2188,15 @@ static int proc_cpuset_show(struct seq_file *m, void *v)
goto out_free;
retval = -EINVAL;
- mutex_lock(&manage_mutex);
-
- retval = cpuset_path(tsk->cpuset, buf, PAGE_SIZE);
+ cgroup_lock();
+ css = task_subsys_state(tsk, cpuset_subsys_id);
+ retval = cgroup_path(css->cgroup, buf, PAGE_SIZE);
if (retval < 0)
goto out_unlock;
seq_puts(m, buf);
seq_putc(m, '\n');
out_unlock:
- mutex_unlock(&manage_mutex);
+ cgroup_unlock();
put_task_struct(tsk);
out_free:
kfree(buf);
@@ -2697,6 +2216,7 @@ const struct file_operations proc_cpuset_operations = {
.llseek = seq_lseek,
.release = single_release,
};
+#endif /* CONFIG_PROC_PID_CPUSET */
/* Display task cpus_allowed, mems_allowed in /proc/<pid>/status file. */
char *cpuset_task_status_allowed(struct task_struct *task, char *buffer)
diff --git a/kernel/delayacct.c b/kernel/delayacct.c
index 09e9574eeb26..10e43fd8b721 100644
--- a/kernel/delayacct.c
+++ b/kernel/delayacct.c
@@ -115,6 +115,12 @@ int __delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk)
tmp += timespec_to_ns(&ts);
d->cpu_run_real_total = (tmp < (s64)d->cpu_run_real_total) ? 0 : tmp;
+ tmp = (s64)d->cpu_scaled_run_real_total;
+ cputime_to_timespec(tsk->utimescaled + tsk->stimescaled, &ts);
+ tmp += timespec_to_ns(&ts);
+ d->cpu_scaled_run_real_total =
+ (tmp < (s64)d->cpu_scaled_run_real_total) ? 0 : tmp;
+
/*
* No locking available for sched_info (and too expensive to add one)
* Mitigate by taking snapshot of values
diff --git a/kernel/die_notifier.c b/kernel/die_notifier.c
deleted file mode 100644
index 0d98827887a7..000000000000
--- a/kernel/die_notifier.c
+++ /dev/null
@@ -1,38 +0,0 @@
-
-#include <linux/module.h>
-#include <linux/notifier.h>
-#include <linux/vmalloc.h>
-#include <linux/kdebug.h>
-
-
-static ATOMIC_NOTIFIER_HEAD(die_chain);
-
-int notify_die(enum die_val val, const char *str,
- struct pt_regs *regs, long err, int trap, int sig)
-{
- struct die_args args = {
- .regs = regs,
- .str = str,
- .err = err,
- .trapnr = trap,
- .signr = sig,
-
- };
-
- return atomic_notifier_call_chain(&die_chain, val, &args);
-}
-
-int register_die_notifier(struct notifier_block *nb)
-{
- vmalloc_sync_all();
- return atomic_notifier_chain_register(&die_chain, nb);
-}
-EXPORT_SYMBOL_GPL(register_die_notifier);
-
-int unregister_die_notifier(struct notifier_block *nb)
-{
- return atomic_notifier_chain_unregister(&die_chain, nb);
-}
-EXPORT_SYMBOL_GPL(unregister_die_notifier);
-
-
diff --git a/kernel/dma.c b/kernel/dma.c
index 937b13ca33ba..6a82bb716dac 100644
--- a/kernel/dma.c
+++ b/kernel/dma.c
@@ -20,7 +20,7 @@
#include <asm/dma.h>
#include <asm/system.h>
-
+
/* A note on resource allocation:
*
@@ -95,7 +95,7 @@ void free_dma(unsigned int dmanr)
if (xchg(&dma_chan_busy[dmanr].lock, 0) == 0) {
printk(KERN_WARNING "Trying to free free DMA%d\n", dmanr);
return;
- }
+ }
} /* free_dma */
@@ -121,8 +121,8 @@ static int proc_dma_show(struct seq_file *m, void *v)
for (i = 0 ; i < MAX_DMA_CHANNELS ; i++) {
if (dma_chan_busy[i].lock) {
- seq_printf(m, "%2d: %s\n", i,
- dma_chan_busy[i].device_id);
+ seq_printf(m, "%2d: %s\n", i,
+ dma_chan_busy[i].device_id);
}
}
return 0;
diff --git a/kernel/exec_domain.c b/kernel/exec_domain.c
index 3c2eaea66b1e..a9e6bad9f706 100644
--- a/kernel/exec_domain.c
+++ b/kernel/exec_domain.c
@@ -57,7 +57,7 @@ lookup_exec_domain(u_long personality)
{
struct exec_domain * ep;
u_long pers = personality(personality);
-
+
read_lock(&exec_domains_lock);
for (ep = exec_domains; ep; ep = ep->next) {
if (pers >= ep->pers_low && pers <= ep->pers_high)
diff --git a/kernel/exit.c b/kernel/exit.c
index 7f7959de4a87..cd0f1d4137a7 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -31,7 +31,7 @@
#include <linux/taskstats_kern.h>
#include <linux/delayacct.h>
#include <linux/freezer.h>
-#include <linux/cpuset.h>
+#include <linux/cgroup.h>
#include <linux/syscalls.h>
#include <linux/signal.h>
#include <linux/posix-timers.h>
@@ -44,7 +44,6 @@
#include <linux/resource.h>
#include <linux/blkdev.h>
#include <linux/task_io_accounting_ops.h>
-#include <linux/freezer.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
@@ -93,10 +92,9 @@ static void __exit_signal(struct task_struct *tsk)
* If there is any task waiting for the group exit
* then notify it:
*/
- if (sig->group_exit_task && atomic_read(&sig->count) == sig->notify_count) {
+ if (sig->group_exit_task && atomic_read(&sig->count) == sig->notify_count)
wake_up_process(sig->group_exit_task);
- sig->group_exit_task = NULL;
- }
+
if (tsk == sig->curr_target)
sig->curr_target = next_thread(tsk);
/*
@@ -150,6 +148,7 @@ void release_task(struct task_struct * p)
int zap_leader;
repeat:
atomic_dec(&p->user->processes);
+ proc_flush_task(p);
write_lock_irq(&tasklist_lock);
ptrace_unlink(p);
BUG_ON(!list_empty(&p->ptrace_list) || !list_empty(&p->ptrace_children));
@@ -177,7 +176,6 @@ repeat:
}
write_unlock_irq(&tasklist_lock);
- proc_flush_task(p);
release_thread(p);
call_rcu(&p->rcu, delayed_put_task_struct);
@@ -223,7 +221,7 @@ static int will_become_orphaned_pgrp(struct pid *pgrp, struct task_struct *ignor
do_each_pid_task(pgrp, PIDTYPE_PGID, p) {
if (p == ignored_task
|| p->exit_state
- || is_init(p->real_parent))
+ || is_global_init(p->real_parent))
continue;
if (task_pgrp(p->real_parent) != pgrp &&
task_session(p->real_parent) == task_session(p)) {
@@ -301,14 +299,14 @@ void __set_special_pids(pid_t session, pid_t pgrp)
{
struct task_struct *curr = current->group_leader;
- if (process_session(curr) != session) {
+ if (task_session_nr(curr) != session) {
detach_pid(curr, PIDTYPE_SID);
- set_signal_session(curr->signal, session);
+ set_task_session(curr, session);
attach_pid(curr, PIDTYPE_SID, find_pid(session));
}
- if (process_group(curr) != pgrp) {
+ if (task_pgrp_nr(curr) != pgrp) {
detach_pid(curr, PIDTYPE_PGID);
- curr->signal->pgrp = pgrp;
+ set_task_pgrp(curr, pgrp);
attach_pid(curr, PIDTYPE_PGID, find_pid(pgrp));
}
}
@@ -402,11 +400,12 @@ void daemonize(const char *name, ...)
current->fs = fs;
atomic_inc(&fs->count);
- exit_task_namespaces(current);
- current->nsproxy = init_task.nsproxy;
- get_task_namespaces(current);
+ if (current->nsproxy != init_task.nsproxy) {
+ get_nsproxy(init_task.nsproxy);
+ switch_task_namespaces(current, init_task.nsproxy);
+ }
- exit_files(current);
+ exit_files(current);
current->files = init_task.files;
atomic_inc(&current->files->count);
@@ -494,7 +493,7 @@ void reset_files_struct(struct task_struct *tsk, struct files_struct *files)
}
EXPORT_SYMBOL(reset_files_struct);
-static inline void __exit_files(struct task_struct *tsk)
+static void __exit_files(struct task_struct *tsk)
{
struct files_struct * files = tsk->files;
@@ -511,7 +510,7 @@ void exit_files(struct task_struct *tsk)
__exit_files(tsk);
}
-static inline void __put_fs_struct(struct fs_struct *fs)
+static void __put_fs_struct(struct fs_struct *fs)
{
/* No need to hold fs->lock if we are killing it */
if (atomic_dec_and_test(&fs->count)) {
@@ -532,7 +531,7 @@ void put_fs_struct(struct fs_struct *fs)
__put_fs_struct(fs);
}
-static inline void __exit_fs(struct task_struct *tsk)
+static void __exit_fs(struct task_struct *tsk)
{
struct fs_struct * fs = tsk->fs;
@@ -593,17 +592,6 @@ static void exit_mm(struct task_struct * tsk)
mmput(mm);
}
-static inline void
-choose_new_parent(struct task_struct *p, struct task_struct *reaper)
-{
- /*
- * Make sure we're not reparenting to ourselves and that
- * the parent is not a zombie.
- */
- BUG_ON(p == reaper || reaper->exit_state);
- p->real_parent = reaper;
-}
-
static void
reparent_thread(struct task_struct *p, struct task_struct *father, int traced)
{
@@ -678,19 +666,22 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced)
* the child reaper process (ie "init") in our pid
* space.
*/
-static void
-forget_original_parent(struct task_struct *father, struct list_head *to_release)
+static void forget_original_parent(struct task_struct *father)
{
- struct task_struct *p, *reaper = father;
- struct list_head *_p, *_n;
+ struct task_struct *p, *n, *reaper = father;
+ struct list_head ptrace_dead;
+
+ INIT_LIST_HEAD(&ptrace_dead);
+
+ write_lock_irq(&tasklist_lock);
do {
reaper = next_thread(reaper);
if (reaper == father) {
- reaper = child_reaper(father);
+ reaper = task_child_reaper(father);
break;
}
- } while (reaper->exit_state);
+ } while (reaper->flags & PF_EXITING);
/*
* There are only two places where our children can be:
@@ -700,9 +691,8 @@ forget_original_parent(struct task_struct *father, struct list_head *to_release)
*
* Search them and reparent children.
*/
- list_for_each_safe(_p, _n, &father->children) {
+ list_for_each_entry_safe(p, n, &father->children, sibling) {
int ptrace;
- p = list_entry(_p, struct task_struct, sibling);
ptrace = p->ptrace;
@@ -711,7 +701,7 @@ forget_original_parent(struct task_struct *father, struct list_head *to_release)
if (father == p->real_parent) {
/* reparent with a reaper, real father it's us */
- choose_new_parent(p, reaper);
+ p->real_parent = reaper;
reparent_thread(p, father, 0);
} else {
/* reparent ptraced task to its real parent */
@@ -728,13 +718,23 @@ forget_original_parent(struct task_struct *father, struct list_head *to_release)
* while it was being traced by us, to be able to see it in wait4.
*/
if (unlikely(ptrace && p->exit_state == EXIT_ZOMBIE && p->exit_signal == -1))
- list_add(&p->ptrace_list, to_release);
+ list_add(&p->ptrace_list, &ptrace_dead);
}
- list_for_each_safe(_p, _n, &father->ptrace_children) {
- p = list_entry(_p, struct task_struct, ptrace_list);
- choose_new_parent(p, reaper);
+
+ list_for_each_entry_safe(p, n, &father->ptrace_children, ptrace_list) {
+ p->real_parent = reaper;
reparent_thread(p, father, 1);
}
+
+ write_unlock_irq(&tasklist_lock);
+ BUG_ON(!list_empty(&father->children));
+ BUG_ON(!list_empty(&father->ptrace_children));
+
+ list_for_each_entry_safe(p, n, &ptrace_dead, ptrace_list) {
+ list_del_init(&p->ptrace_list);
+ release_task(p);
+ }
+
}
/*
@@ -745,7 +745,6 @@ static void exit_notify(struct task_struct *tsk)
{
int state;
struct task_struct *t;
- struct list_head ptrace_dead, *_p, *_n;
struct pid *pgrp;
if (signal_pending(tsk) && !(tsk->signal->flags & SIGNAL_GROUP_EXIT)
@@ -759,17 +758,13 @@ static void exit_notify(struct task_struct *tsk)
* Now we'll wake all the threads in the group just to make
* sure someone gets all the pending signals.
*/
- read_lock(&tasklist_lock);
spin_lock_irq(&tsk->sighand->siglock);
for (t = next_thread(tsk); t != tsk; t = next_thread(t))
if (!signal_pending(t) && !(t->flags & PF_EXITING))
recalc_sigpending_and_wake(t);
spin_unlock_irq(&tsk->sighand->siglock);
- read_unlock(&tasklist_lock);
}
- write_lock_irq(&tasklist_lock);
-
/*
* This does two things:
*
@@ -778,12 +773,10 @@ static void exit_notify(struct task_struct *tsk)
* as a result of our exiting, and if they have any stopped
* jobs, send them a SIGHUP and then a SIGCONT. (POSIX 3.2.2.2)
*/
+ forget_original_parent(tsk);
+ exit_task_namespaces(tsk);
- INIT_LIST_HEAD(&ptrace_dead);
- forget_original_parent(tsk, &ptrace_dead);
- BUG_ON(!list_empty(&tsk->children));
- BUG_ON(!list_empty(&tsk->ptrace_children));
-
+ write_lock_irq(&tasklist_lock);
/*
* Check to see if any process groups have become orphaned
* as a result of our exiting, and if they have any stopped
@@ -793,9 +786,8 @@ static void exit_notify(struct task_struct *tsk)
* and we were the only connection outside, so our pgrp
* is about to become orphaned.
*/
-
t = tsk->real_parent;
-
+
pgrp = task_pgrp(tsk);
if ((task_pgrp(t) != pgrp) &&
(task_session(t) == task_session(tsk)) &&
@@ -808,7 +800,7 @@ static void exit_notify(struct task_struct *tsk)
/* Let father know we died
*
* Thread signals are configurable, but you aren't going to use
- * that to send signals to arbitary processes.
+ * that to send signals to arbitary processes.
* That stops right now.
*
* If the parent exec id doesn't match the exec id we saved
@@ -842,13 +834,12 @@ static void exit_notify(struct task_struct *tsk)
state = EXIT_DEAD;
tsk->exit_state = state;
- write_unlock_irq(&tasklist_lock);
+ if (thread_group_leader(tsk) &&
+ tsk->signal->notify_count < 0 &&
+ tsk->signal->group_exit_task)
+ wake_up_process(tsk->signal->group_exit_task);
- list_for_each_safe(_p, _n, &ptrace_dead) {
- list_del_init(_p);
- t = list_entry(_p, struct task_struct, ptrace_list);
- release_task(t);
- }
+ write_unlock_irq(&tasklist_lock);
/* If the process is dead, release it - nobody will wait for it */
if (state == EXIT_DEAD)
@@ -883,6 +874,39 @@ static void check_stack_usage(void)
static inline void check_stack_usage(void) {}
#endif
+static inline void exit_child_reaper(struct task_struct *tsk)
+{
+ if (likely(tsk->group_leader != task_child_reaper(tsk)))
+ return;
+
+ if (tsk->nsproxy->pid_ns == &init_pid_ns)
+ panic("Attempted to kill init!");
+
+ /*
+ * @tsk is the last thread in the 'cgroup-init' and is exiting.
+ * Terminate all remaining processes in the namespace and reap them
+ * before exiting @tsk.
+ *
+ * Note that @tsk (last thread of cgroup-init) may not necessarily
+ * be the child-reaper (i.e main thread of cgroup-init) of the
+ * namespace i.e the child_reaper may have already exited.
+ *
+ * Even after a child_reaper exits, we let it inherit orphaned children,
+ * because, pid_ns->child_reaper remains valid as long as there is
+ * at least one living sub-thread in the cgroup init.
+
+ * This living sub-thread of the cgroup-init will be notified when
+ * a child inherited by the 'child-reaper' exits (do_notify_parent()
+ * uses __group_send_sig_info()). Further, when reaping child processes,
+ * do_wait() iterates over children of all living sub threads.
+
+ * i.e even though 'child_reaper' thread is listed as the parent of the
+ * orphaned children, any living sub-thread in the cgroup-init can
+ * perform the role of the child_reaper.
+ */
+ zap_pid_ns_processes(tsk->nsproxy->pid_ns);
+}
+
fastcall NORET_TYPE void do_exit(long code)
{
struct task_struct *tsk = current;
@@ -896,13 +920,6 @@ fastcall NORET_TYPE void do_exit(long code)
panic("Aiee, killing interrupt handler!");
if (unlikely(!tsk->pid))
panic("Attempted to kill the idle task!");
- if (unlikely(tsk == child_reaper(tsk))) {
- if (tsk->nsproxy->pid_ns != &init_pid_ns)
- tsk->nsproxy->pid_ns->child_reaper = init_pid_ns.child_reaper;
- else
- panic("Attempted to kill init!");
- }
-
if (unlikely(current->ptrace & PT_TRACE_EXIT)) {
current->ptrace_message = code;
@@ -932,17 +949,17 @@ fastcall NORET_TYPE void do_exit(long code)
schedule();
}
+ tsk->flags |= PF_EXITING;
/*
* tsk->flags are checked in the futex code to protect against
* an exiting task cleaning up the robust pi futexes.
*/
- spin_lock_irq(&tsk->pi_lock);
- tsk->flags |= PF_EXITING;
- spin_unlock_irq(&tsk->pi_lock);
+ smp_mb();
+ spin_unlock_wait(&tsk->pi_lock);
if (unlikely(in_atomic()))
printk(KERN_INFO "note: %s[%d] exited with preempt_count %d\n",
- current->comm, current->pid,
+ current->comm, task_pid_nr(current),
preempt_count());
acct_update_integrals(tsk);
@@ -952,16 +969,19 @@ fastcall NORET_TYPE void do_exit(long code)
}
group_dead = atomic_dec_and_test(&tsk->signal->live);
if (group_dead) {
+ exit_child_reaper(tsk);
hrtimer_cancel(&tsk->signal->real_timer);
exit_itimers(tsk->signal);
}
acct_collect(code, group_dead);
+#ifdef CONFIG_FUTEX
if (unlikely(tsk->robust_list))
exit_robust_list(tsk);
-#if defined(CONFIG_FUTEX) && defined(CONFIG_COMPAT)
+#ifdef CONFIG_COMPAT
if (unlikely(tsk->compat_robust_list))
compat_exit_robust_list(tsk);
#endif
+#endif
if (group_dead)
tty_audit_exit();
if (unlikely(tsk->audit_context))
@@ -979,7 +999,7 @@ fastcall NORET_TYPE void do_exit(long code)
__exit_fs(tsk);
check_stack_usage();
exit_thread();
- cpuset_exit(tsk);
+ cgroup_exit(tsk, 1);
exit_keys(tsk);
if (group_dead && tsk->signal->leader)
@@ -990,12 +1010,12 @@ fastcall NORET_TYPE void do_exit(long code)
module_put(tsk->binfmt->module);
proc_exit_connector(tsk);
- exit_task_namespaces(tsk);
exit_notify(tsk);
#ifdef CONFIG_NUMA
mpol_free(tsk->mempolicy);
tsk->mempolicy = NULL;
#endif
+#ifdef CONFIG_FUTEX
/*
* This must happen late, after the PID is not
* hashed anymore:
@@ -1004,6 +1024,7 @@ fastcall NORET_TYPE void do_exit(long code)
exit_pi_state_list(tsk);
if (unlikely(current->pi_state_cache))
kfree(current->pi_state_cache);
+#endif
/*
* Make sure we are holding no locks:
*/
@@ -1091,15 +1112,17 @@ asmlinkage void sys_exit_group(int error_code)
static int eligible_child(pid_t pid, int options, struct task_struct *p)
{
int err;
+ struct pid_namespace *ns;
+ ns = current->nsproxy->pid_ns;
if (pid > 0) {
- if (p->pid != pid)
+ if (task_pid_nr_ns(p, ns) != pid)
return 0;
} else if (!pid) {
- if (process_group(p) != process_group(current))
+ if (task_pgrp_nr_ns(p, ns) != task_pgrp_vnr(current))
return 0;
} else if (pid != -1) {
- if (process_group(p) != -pid)
+ if (task_pgrp_nr_ns(p, ns) != -pid)
return 0;
}
@@ -1168,11 +1191,13 @@ static int wait_task_zombie(struct task_struct *p, int noreap,
int __user *stat_addr, struct rusage __user *ru)
{
unsigned long state;
- int retval;
- int status;
+ int retval, status, traced;
+ struct pid_namespace *ns;
+
+ ns = current->nsproxy->pid_ns;
if (unlikely(noreap)) {
- pid_t pid = p->pid;
+ pid_t pid = task_pid_nr_ns(p, ns);
uid_t uid = p->uid;
int exit_code = p->exit_code;
int why, status;
@@ -1203,15 +1228,11 @@ static int wait_task_zombie(struct task_struct *p, int noreap,
BUG_ON(state != EXIT_DEAD);
return 0;
}
- if (unlikely(p->exit_signal == -1 && p->ptrace == 0)) {
- /*
- * This can only happen in a race with a ptraced thread
- * dying on another processor.
- */
- return 0;
- }
- if (likely(p->real_parent == p->parent) && likely(p->signal)) {
+ /* traced means p->ptrace, but not vice versa */
+ traced = (p->real_parent != p->parent);
+
+ if (likely(!traced)) {
struct signal_struct *psig;
struct signal_struct *sig;
@@ -1295,38 +1316,33 @@ static int wait_task_zombie(struct task_struct *p, int noreap,
retval = put_user(status, &infop->si_status);
}
if (!retval && infop)
- retval = put_user(p->pid, &infop->si_pid);
+ retval = put_user(task_pid_nr_ns(p, ns), &infop->si_pid);
if (!retval && infop)
retval = put_user(p->uid, &infop->si_uid);
- if (retval) {
- // TODO: is this safe?
- p->exit_state = EXIT_ZOMBIE;
- return retval;
- }
- retval = p->pid;
- if (p->real_parent != p->parent) {
+ if (!retval)
+ retval = task_pid_nr_ns(p, ns);
+
+ if (traced) {
write_lock_irq(&tasklist_lock);
- /* Double-check with lock held. */
- if (p->real_parent != p->parent) {
- __ptrace_unlink(p);
- // TODO: is this safe?
- p->exit_state = EXIT_ZOMBIE;
- /*
- * If this is not a detached task, notify the parent.
- * If it's still not detached after that, don't release
- * it now.
- */
+ /* We dropped tasklist, ptracer could die and untrace */
+ ptrace_unlink(p);
+ /*
+ * If this is not a detached task, notify the parent.
+ * If it's still not detached after that, don't release
+ * it now.
+ */
+ if (p->exit_signal != -1) {
+ do_notify_parent(p, p->exit_signal);
if (p->exit_signal != -1) {
- do_notify_parent(p, p->exit_signal);
- if (p->exit_signal != -1)
- p = NULL;
+ p->exit_state = EXIT_ZOMBIE;
+ p = NULL;
}
}
write_unlock_irq(&tasklist_lock);
}
if (p != NULL)
release_task(p);
- BUG_ON(!retval);
+
return retval;
}
@@ -1341,11 +1357,12 @@ static int wait_task_stopped(struct task_struct *p, int delayed_group_leader,
int __user *stat_addr, struct rusage __user *ru)
{
int retval, exit_code;
+ struct pid_namespace *ns;
if (!p->exit_code)
return 0;
if (delayed_group_leader && !(p->ptrace & PT_PTRACED) &&
- p->signal && p->signal->group_stop_count > 0)
+ p->signal->group_stop_count > 0)
/*
* A group stop is in progress and this is the group leader.
* We won't report until all threads have stopped.
@@ -1359,17 +1376,17 @@ static int wait_task_stopped(struct task_struct *p, int delayed_group_leader,
* keep holding onto the tasklist_lock while we call getrusage and
* possibly take page faults for user memory.
*/
+ ns = current->nsproxy->pid_ns;
get_task_struct(p);
read_unlock(&tasklist_lock);
if (unlikely(noreap)) {
- pid_t pid = p->pid;
+ pid_t pid = task_pid_nr_ns(p, ns);
uid_t uid = p->uid;
int why = (p->ptrace & PT_PTRACED) ? CLD_TRAPPED : CLD_STOPPED;
exit_code = p->exit_code;
- if (unlikely(!exit_code) ||
- unlikely(p->state & TASK_TRACED))
+ if (unlikely(!exit_code) || unlikely(p->exit_state))
goto bail_ref;
return wait_noreap_copyout(p, pid, uid,
why, (exit_code << 8) | 0x7f,
@@ -1434,11 +1451,11 @@ bail_ref:
if (!retval && infop)
retval = put_user(exit_code, &infop->si_status);
if (!retval && infop)
- retval = put_user(p->pid, &infop->si_pid);
+ retval = put_user(task_pid_nr_ns(p, ns), &infop->si_pid);
if (!retval && infop)
retval = put_user(p->uid, &infop->si_uid);
if (!retval)
- retval = p->pid;
+ retval = task_pid_nr_ns(p, ns);
put_task_struct(p);
BUG_ON(!retval);
@@ -1458,9 +1475,7 @@ static int wait_task_continued(struct task_struct *p, int noreap,
int retval;
pid_t pid;
uid_t uid;
-
- if (unlikely(!p->signal))
- return 0;
+ struct pid_namespace *ns;
if (!(p->signal->flags & SIGNAL_STOP_CONTINUED))
return 0;
@@ -1475,7 +1490,8 @@ static int wait_task_continued(struct task_struct *p, int noreap,
p->signal->flags &= ~SIGNAL_STOP_CONTINUED;
spin_unlock_irq(&p->sighand->siglock);
- pid = p->pid;
+ ns = current->nsproxy->pid_ns;
+ pid = task_pid_nr_ns(p, ns);
uid = p->uid;
get_task_struct(p);
read_unlock(&tasklist_lock);
@@ -1486,7 +1502,7 @@ static int wait_task_continued(struct task_struct *p, int noreap,
if (!retval && stat_addr)
retval = put_user(0xffff, stat_addr);
if (!retval)
- retval = p->pid;
+ retval = task_pid_nr_ns(p, ns);
} else {
retval = wait_noreap_copyout(p, pid, uid,
CLD_CONTINUED, SIGCONT,
@@ -1535,12 +1551,9 @@ repeat:
tsk = current;
do {
struct task_struct *p;
- struct list_head *_p;
int ret;
- list_for_each(_p,&tsk->children) {
- p = list_entry(_p, struct task_struct, sibling);
-
+ list_for_each_entry(p, &tsk->children, sibling) {
ret = eligible_child(pid, options, p);
if (!ret)
continue;
@@ -1622,9 +1635,8 @@ check_continued:
}
}
if (!flag) {
- list_for_each(_p, &tsk->ptrace_children) {
- p = list_entry(_p, struct task_struct,
- ptrace_list);
+ list_for_each_entry(p, &tsk->ptrace_children,
+ ptrace_list) {
if (!eligible_child(pid, options, p))
continue;
flag = 1;
diff --git a/kernel/fork.c b/kernel/fork.c
index 3fc3c1383912..8ca1a14cdc8c 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -29,7 +29,7 @@
#include <linux/nsproxy.h>
#include <linux/capability.h>
#include <linux/cpu.h>
-#include <linux/cpuset.h>
+#include <linux/cgroup.h>
#include <linux/security.h>
#include <linux/swap.h>
#include <linux/syscalls.h>
@@ -50,6 +50,7 @@
#include <linux/taskstats_kern.h>
#include <linux/random.h>
#include <linux/tty.h>
+#include <linux/proc_fs.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
@@ -107,6 +108,7 @@ static struct kmem_cache *mm_cachep;
void free_task(struct task_struct *tsk)
{
+ prop_local_destroy_single(&tsk->dirties);
free_thread_info(tsk->stack);
rt_mutex_debug_task_free(tsk);
free_task_struct(tsk);
@@ -115,7 +117,7 @@ EXPORT_SYMBOL(free_task);
void __put_task_struct(struct task_struct *tsk)
{
- WARN_ON(!(tsk->exit_state & (EXIT_DEAD | EXIT_ZOMBIE)));
+ WARN_ON(!tsk->exit_state);
WARN_ON(atomic_read(&tsk->usage));
WARN_ON(tsk == current);
@@ -163,6 +165,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
{
struct task_struct *tsk;
struct thread_info *ti;
+ int err;
prepare_to_copy(orig);
@@ -178,6 +181,14 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
*tsk = *orig;
tsk->stack = ti;
+
+ err = prop_local_init_single(&tsk->dirties);
+ if (err) {
+ free_thread_info(ti);
+ free_task_struct(tsk);
+ return NULL;
+ }
+
setup_thread_stack(tsk, orig);
#ifdef CONFIG_CC_STACKPROTECTOR
@@ -195,7 +206,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
}
#ifdef CONFIG_MMU
-static inline int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
+static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
{
struct vm_area_struct *mpnt, *tmp, **pprev;
struct rb_node **rb_link, *rb_parent;
@@ -258,7 +269,7 @@ static inline int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
get_file(file);
if (tmp->vm_flags & VM_DENYWRITE)
atomic_dec(&inode->i_writecount);
-
+
/* insert tmp into the share list, just after mpnt */
spin_lock(&file->f_mapping->i_mmap_lock);
tmp->vm_truncate_count = mpnt->vm_truncate_count;
@@ -321,7 +332,7 @@ static inline void mm_free_pgd(struct mm_struct * mm)
#define mm_free_pgd(mm)
#endif /* CONFIG_MMU */
- __cacheline_aligned_in_smp DEFINE_SPINLOCK(mmlist_lock);
+__cacheline_aligned_in_smp DEFINE_SPINLOCK(mmlist_lock);
#define allocate_mm() (kmem_cache_alloc(mm_cachep, GFP_KERNEL))
#define free_mm(mm) (kmem_cache_free(mm_cachep, (mm)))
@@ -573,7 +584,7 @@ fail_nomem:
return retval;
}
-static inline struct fs_struct *__copy_fs_struct(struct fs_struct *old)
+static struct fs_struct *__copy_fs_struct(struct fs_struct *old)
{
struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL);
/* We don't need to lock fs - think why ;-) */
@@ -605,7 +616,7 @@ struct fs_struct *copy_fs_struct(struct fs_struct *old)
EXPORT_SYMBOL_GPL(copy_fs_struct);
-static inline int copy_fs(unsigned long clone_flags, struct task_struct * tsk)
+static int copy_fs(unsigned long clone_flags, struct task_struct *tsk)
{
if (clone_flags & CLONE_FS) {
atomic_inc(&current->fs->count);
@@ -728,8 +739,8 @@ static struct files_struct *dup_fd(struct files_struct *oldf, int *errorp)
/* compute the remainder to be cleared */
size = (new_fdt->max_fds - open_files) * sizeof(struct file *);
- /* This is long word aligned thus could use a optimized version */
- memset(new_fds, 0, size);
+ /* This is long word aligned thus could use a optimized version */
+ memset(new_fds, 0, size);
if (new_fdt->max_fds > open_files) {
int left = (new_fdt->max_fds-open_files)/8;
@@ -808,7 +819,7 @@ int unshare_files(void)
EXPORT_SYMBOL(unshare_files);
-static inline int copy_sighand(unsigned long clone_flags, struct task_struct * tsk)
+static int copy_sighand(unsigned long clone_flags, struct task_struct *tsk)
{
struct sighand_struct *sig;
@@ -831,7 +842,7 @@ void __cleanup_sighand(struct sighand_struct *sighand)
kmem_cache_free(sighand_cachep, sighand);
}
-static inline int copy_signal(unsigned long clone_flags, struct task_struct * tsk)
+static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
{
struct signal_struct *sig;
int ret;
@@ -913,7 +924,7 @@ void __cleanup_signal(struct signal_struct *sig)
kmem_cache_free(signal_cachep, sig);
}
-static inline void cleanup_signal(struct task_struct *tsk)
+static void cleanup_signal(struct task_struct *tsk)
{
struct signal_struct *sig = tsk->signal;
@@ -923,7 +934,7 @@ static inline void cleanup_signal(struct task_struct *tsk)
__cleanup_signal(sig);
}
-static inline void copy_flags(unsigned long clone_flags, struct task_struct *p)
+static void copy_flags(unsigned long clone_flags, struct task_struct *p)
{
unsigned long new_flags = p->flags;
@@ -932,16 +943,17 @@ static inline void copy_flags(unsigned long clone_flags, struct task_struct *p)
if (!(clone_flags & CLONE_PTRACE))
p->ptrace = 0;
p->flags = new_flags;
+ clear_freeze_flag(p);
}
asmlinkage long sys_set_tid_address(int __user *tidptr)
{
current->clear_child_tid = tidptr;
- return current->pid;
+ return task_pid_vnr(current);
}
-static inline void rt_mutex_init_task(struct task_struct *p)
+static void rt_mutex_init_task(struct task_struct *p)
{
spin_lock_init(&p->pi_lock);
#ifdef CONFIG_RT_MUTEXES
@@ -962,12 +974,12 @@ static struct task_struct *copy_process(unsigned long clone_flags,
unsigned long stack_start,
struct pt_regs *regs,
unsigned long stack_size,
- int __user *parent_tidptr,
int __user *child_tidptr,
struct pid *pid)
{
int retval;
- struct task_struct *p = NULL;
+ struct task_struct *p;
+ int cgroup_callbacks_done = 0;
if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
return ERR_PTR(-EINVAL);
@@ -1031,12 +1043,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
p->did_exec = 0;
delayacct_tsk_init(p); /* Must remain after dup_task_struct() */
copy_flags(clone_flags, p);
- p->pid = pid_nr(pid);
- retval = -EFAULT;
- if (clone_flags & CLONE_PARENT_SETTID)
- if (put_user(p->pid, parent_tidptr))
- goto bad_fork_cleanup_delays_binfmt;
-
INIT_LIST_HEAD(&p->children);
INIT_LIST_HEAD(&p->sibling);
p->vfork_done = NULL;
@@ -1048,6 +1054,10 @@ static struct task_struct *copy_process(unsigned long clone_flags,
p->utime = cputime_zero;
p->stime = cputime_zero;
p->gtime = cputime_zero;
+ p->utimescaled = cputime_zero;
+ p->stimescaled = cputime_zero;
+ p->prev_utime = cputime_zero;
+ p->prev_stime = cputime_zero;
#ifdef CONFIG_TASK_XACCT
p->rchar = 0; /* I/O counter: bytes read */
@@ -1058,28 +1068,29 @@ static struct task_struct *copy_process(unsigned long clone_flags,
task_io_accounting_init(p);
acct_clear_integrals(p);
- p->it_virt_expires = cputime_zero;
+ p->it_virt_expires = cputime_zero;
p->it_prof_expires = cputime_zero;
- p->it_sched_expires = 0;
- INIT_LIST_HEAD(&p->cpu_timers[0]);
- INIT_LIST_HEAD(&p->cpu_timers[1]);
- INIT_LIST_HEAD(&p->cpu_timers[2]);
+ p->it_sched_expires = 0;
+ INIT_LIST_HEAD(&p->cpu_timers[0]);
+ INIT_LIST_HEAD(&p->cpu_timers[1]);
+ INIT_LIST_HEAD(&p->cpu_timers[2]);
p->lock_depth = -1; /* -1 = no lock */
do_posix_clock_monotonic_gettime(&p->start_time);
p->real_start_time = p->start_time;
monotonic_to_bootbased(&p->real_start_time);
+#ifdef CONFIG_SECURITY
p->security = NULL;
+#endif
p->io_context = NULL;
- p->io_wait = NULL;
p->audit_context = NULL;
- cpuset_fork(p);
+ cgroup_fork(p);
#ifdef CONFIG_NUMA
p->mempolicy = mpol_copy(p->mempolicy);
if (IS_ERR(p->mempolicy)) {
retval = PTR_ERR(p->mempolicy);
p->mempolicy = NULL;
- goto bad_fork_cleanup_cpuset;
+ goto bad_fork_cleanup_cgroup;
}
mpol_fix_fork_child_flag(p);
#endif
@@ -1112,9 +1123,8 @@ static struct task_struct *copy_process(unsigned long clone_flags,
p->blocked_on = NULL; /* not blocked yet */
#endif
- p->tgid = p->pid;
- if (clone_flags & CLONE_THREAD)
- p->tgid = current->tgid;
+ /* Perform scheduler related setup. Assign this task to a CPU. */
+ sched_fork(p, clone_flags);
if ((retval = security_task_alloc(p)))
goto bad_fork_cleanup_policy;
@@ -1141,18 +1151,37 @@ static struct task_struct *copy_process(unsigned long clone_flags,
if (retval)
goto bad_fork_cleanup_namespaces;
+ if (pid != &init_struct_pid) {
+ retval = -ENOMEM;
+ pid = alloc_pid(task_active_pid_ns(p));
+ if (!pid)
+ goto bad_fork_cleanup_namespaces;
+
+ if (clone_flags & CLONE_NEWPID) {
+ retval = pid_ns_prepare_proc(task_active_pid_ns(p));
+ if (retval < 0)
+ goto bad_fork_free_pid;
+ }
+ }
+
+ p->pid = pid_nr(pid);
+ p->tgid = p->pid;
+ if (clone_flags & CLONE_THREAD)
+ p->tgid = current->tgid;
+
p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL;
/*
* Clear TID on mm_release()?
*/
p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr: NULL;
+#ifdef CONFIG_FUTEX
p->robust_list = NULL;
#ifdef CONFIG_COMPAT
p->compat_robust_list = NULL;
#endif
INIT_LIST_HEAD(&p->pi_state_list);
p->pi_state_cache = NULL;
-
+#endif
/*
* sigaltstack should be cleared when sharing the same VM
*/
@@ -1186,8 +1215,11 @@ static struct task_struct *copy_process(unsigned long clone_flags,
INIT_LIST_HEAD(&p->ptrace_children);
INIT_LIST_HEAD(&p->ptrace_list);
- /* Perform scheduler related setup. Assign this task to a CPU. */
- sched_fork(p, clone_flags);
+ /* Now that the task is set up, run cgroup callbacks if
+ * necessary. We need to run them before the task is visible
+ * on the tasklist. */
+ cgroup_fork_callbacks(p);
+ cgroup_callbacks_done = 1;
/* Need tasklist lock for parent etc handling! */
write_lock_irq(&tasklist_lock);
@@ -1226,12 +1258,12 @@ static struct task_struct *copy_process(unsigned long clone_flags,
* A fatal signal pending means that current will exit, so the new
* thread can't slip out of an OOM kill (or normal SIGKILL).
*/
- recalc_sigpending();
+ recalc_sigpending();
if (signal_pending(current)) {
spin_unlock(&current->sighand->siglock);
write_unlock_irq(&tasklist_lock);
retval = -ERESTARTNOINTR;
- goto bad_fork_cleanup_namespaces;
+ goto bad_fork_free_pid;
}
if (clone_flags & CLONE_THREAD) {
@@ -1260,11 +1292,22 @@ static struct task_struct *copy_process(unsigned long clone_flags,
__ptrace_link(p, current->parent);
if (thread_group_leader(p)) {
- p->signal->tty = current->signal->tty;
- p->signal->pgrp = process_group(current);
- set_signal_session(p->signal, process_session(current));
- attach_pid(p, PIDTYPE_PGID, task_pgrp(current));
- attach_pid(p, PIDTYPE_SID, task_session(current));
+ if (clone_flags & CLONE_NEWPID) {
+ p->nsproxy->pid_ns->child_reaper = p;
+ p->signal->tty = NULL;
+ set_task_pgrp(p, p->pid);
+ set_task_session(p, p->pid);
+ attach_pid(p, PIDTYPE_PGID, pid);
+ attach_pid(p, PIDTYPE_SID, pid);
+ } else {
+ p->signal->tty = current->signal->tty;
+ set_task_pgrp(p, task_pgrp_nr(current));
+ set_task_session(p, task_session_nr(current));
+ attach_pid(p, PIDTYPE_PGID,
+ task_pgrp(current));
+ attach_pid(p, PIDTYPE_SID,
+ task_session(current));
+ }
list_add_tail_rcu(&p->tasks, &init_task.tasks);
__get_cpu_var(process_counts)++;
@@ -1277,8 +1320,12 @@ static struct task_struct *copy_process(unsigned long clone_flags,
spin_unlock(&current->sighand->siglock);
write_unlock_irq(&tasklist_lock);
proc_fork_connector(p);
+ cgroup_post_fork(p);
return p;
+bad_fork_free_pid:
+ if (pid != &init_struct_pid)
+ free_pid(pid);
bad_fork_cleanup_namespaces:
exit_task_namespaces(p);
bad_fork_cleanup_keys:
@@ -1303,10 +1350,9 @@ bad_fork_cleanup_security:
bad_fork_cleanup_policy:
#ifdef CONFIG_NUMA
mpol_free(p->mempolicy);
-bad_fork_cleanup_cpuset:
+bad_fork_cleanup_cgroup:
#endif
- cpuset_exit(p);
-bad_fork_cleanup_delays_binfmt:
+ cgroup_exit(p, cgroup_callbacks_done);
delayacct_tsk_free(p);
if (p->binfmt)
module_put(p->binfmt->module);
@@ -1333,7 +1379,7 @@ struct task_struct * __cpuinit fork_idle(int cpu)
struct task_struct *task;
struct pt_regs regs;
- task = copy_process(CLONE_VM, 0, idle_regs(&regs), 0, NULL, NULL,
+ task = copy_process(CLONE_VM, 0, idle_regs(&regs), 0, NULL,
&init_struct_pid);
if (!IS_ERR(task))
init_idle(task, cpu);
@@ -1341,7 +1387,7 @@ struct task_struct * __cpuinit fork_idle(int cpu)
return task;
}
-static inline int fork_traceflag (unsigned clone_flags)
+static int fork_traceflag(unsigned clone_flags)
{
if (clone_flags & CLONE_UNTRACED)
return 0;
@@ -1372,19 +1418,16 @@ long do_fork(unsigned long clone_flags,
{
struct task_struct *p;
int trace = 0;
- struct pid *pid = alloc_pid();
long nr;
- if (!pid)
- return -EAGAIN;
- nr = pid->nr;
if (unlikely(current->ptrace)) {
trace = fork_traceflag (clone_flags);
if (trace)
clone_flags |= CLONE_PTRACE;
}
- p = copy_process(clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tidptr, pid);
+ p = copy_process(clone_flags, stack_start, regs, stack_size,
+ child_tidptr, NULL);
/*
* Do this prior waking up the new thread - the thread pointer
* might get invalid after that point, if the thread exits quickly.
@@ -1392,6 +1435,17 @@ long do_fork(unsigned long clone_flags,
if (!IS_ERR(p)) {
struct completion vfork;
+ /*
+ * this is enough to call pid_nr_ns here, but this if
+ * improves optimisation of regular fork()
+ */
+ nr = (clone_flags & CLONE_NEWPID) ?
+ task_pid_nr_ns(p, current->nsproxy->pid_ns) :
+ task_pid_vnr(p);
+
+ if (clone_flags & CLONE_PARENT_SETTID)
+ put_user(nr, parent_tidptr);
+
if (clone_flags & CLONE_VFORK) {
p->vfork_done = &vfork;
init_completion(&vfork);
@@ -1425,7 +1479,6 @@ long do_fork(unsigned long clone_flags,
}
}
} else {
- free_pid(pid);
nr = PTR_ERR(p);
}
return nr;
@@ -1435,8 +1488,7 @@ long do_fork(unsigned long clone_flags,
#define ARCH_MIN_MMSTRUCT_ALIGN 0
#endif
-static void sighand_ctor(void *data, struct kmem_cache *cachep,
- unsigned long flags)
+static void sighand_ctor(struct kmem_cache *cachep, void *data)
{
struct sighand_struct *sighand = data;
@@ -1471,7 +1523,7 @@ void __init proc_caches_init(void)
* Check constraints on flags passed to the unshare system call and
* force unsharing of additional process context as appropriate.
*/
-static inline void check_unshare_flags(unsigned long *flags_ptr)
+static void check_unshare_flags(unsigned long *flags_ptr)
{
/*
* If unsharing a thread from a thread group, must also
@@ -1603,7 +1655,7 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
struct mm_struct *mm, *new_mm = NULL, *active_mm = NULL;
struct files_struct *fd, *new_fd = NULL;
struct sem_undo_list *new_ulist = NULL;
- struct nsproxy *new_nsproxy = NULL, *old_nsproxy = NULL;
+ struct nsproxy *new_nsproxy = NULL;
check_unshare_flags(&unshare_flags);
@@ -1633,14 +1685,13 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
if (new_fs || new_mm || new_fd || new_ulist || new_nsproxy) {
- task_lock(current);
-
if (new_nsproxy) {
- old_nsproxy = current->nsproxy;
- current->nsproxy = new_nsproxy;
- new_nsproxy = old_nsproxy;
+ switch_task_namespaces(current, new_nsproxy);
+ new_nsproxy = NULL;
}
+ task_lock(current);
+
if (new_fs) {
fs = current->fs;
current->fs = new_fs;
diff --git a/kernel/futex.c b/kernel/futex.c
index fcc94e7b4086..9dc591ab681a 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -52,6 +52,10 @@
#include <linux/syscalls.h>
#include <linux/signal.h>
#include <linux/module.h>
+#include <linux/magic.h>
+#include <linux/pid.h>
+#include <linux/nsproxy.h>
+
#include <asm/futex.h>
#include "rtmutex_common.h"
@@ -177,8 +181,8 @@ static inline int match_futex(union futex_key *key1, union futex_key *key2)
* For other futexes, it points to &current->mm->mmap_sem and
* caller must have taken the reader lock. but NOT any spinlocks.
*/
-int get_futex_key(u32 __user *uaddr, struct rw_semaphore *fshared,
- union futex_key *key)
+static int get_futex_key(u32 __user *uaddr, struct rw_semaphore *fshared,
+ union futex_key *key)
{
unsigned long address = (unsigned long)uaddr;
struct mm_struct *mm = current->mm;
@@ -264,14 +268,13 @@ int get_futex_key(u32 __user *uaddr, struct rw_semaphore *fshared,
}
return err;
}
-EXPORT_SYMBOL_GPL(get_futex_key);
/*
* Take a reference to the resource addressed by a key.
* Can be called while holding spinlocks.
*
*/
-inline void get_futex_key_refs(union futex_key *key)
+static void get_futex_key_refs(union futex_key *key)
{
if (key->both.ptr == 0)
return;
@@ -284,15 +287,14 @@ inline void get_futex_key_refs(union futex_key *key)
break;
}
}
-EXPORT_SYMBOL_GPL(get_futex_key_refs);
/*
* Drop a reference to the resource addressed by a key.
* The hash bucket spinlock must not be held.
*/
-void drop_futex_key_refs(union futex_key *key)
+static void drop_futex_key_refs(union futex_key *key)
{
- if (key->both.ptr == 0)
+ if (!key->both.ptr)
return;
switch (key->both.offset & (FUT_OFF_INODE|FUT_OFF_MMSHARED)) {
case FUT_OFF_INODE:
@@ -303,7 +305,6 @@ void drop_futex_key_refs(union futex_key *key)
break;
}
}
-EXPORT_SYMBOL_GPL(drop_futex_key_refs);
static u32 cmpxchg_futex_value_locked(u32 __user *uaddr, u32 uval, u32 newval)
{
@@ -442,8 +443,7 @@ static struct task_struct * futex_find_get_task(pid_t pid)
struct task_struct *p;
rcu_read_lock();
- p = find_task_by_pid(pid);
-
+ p = find_task_by_vpid(pid);
if (!p || ((current->euid != p->euid) && (current->euid != p->uid)))
p = ERR_PTR(-ESRCH);
else
@@ -652,7 +652,7 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this)
if (!(uval & FUTEX_OWNER_DIED)) {
int ret = 0;
- newval = FUTEX_WAITERS | new_owner->pid;
+ newval = FUTEX_WAITERS | task_pid_vnr(new_owner);
curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
@@ -1045,7 +1045,7 @@ static int unqueue_me(struct futex_q *q)
retry:
lock_ptr = q->lock_ptr;
barrier();
- if (lock_ptr != 0) {
+ if (lock_ptr != NULL) {
spin_lock(lock_ptr);
/*
* q->lock_ptr can change between reading it and
@@ -1105,7 +1105,7 @@ static void unqueue_me_pi(struct futex_q *q)
static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
struct task_struct *curr)
{
- u32 newtid = curr->pid | FUTEX_WAITERS;
+ u32 newtid = task_pid_vnr(curr) | FUTEX_WAITERS;
struct futex_pi_state *pi_state = q->pi_state;
u32 uval, curval, newval;
int ret;
@@ -1367,7 +1367,7 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
* (by doing a 0 -> TID atomic cmpxchg), while holding all
* the locks. It will most likely not succeed.
*/
- newval = current->pid;
+ newval = task_pid_vnr(current);
curval = cmpxchg_futex_value_locked(uaddr, 0, newval);
@@ -1378,7 +1378,7 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
* Detect deadlocks. In case of REQUEUE_PI this is a valid
* situation and we return success to user space.
*/
- if (unlikely((curval & FUTEX_TID_MASK) == current->pid)) {
+ if (unlikely((curval & FUTEX_TID_MASK) == task_pid_vnr(current))) {
ret = -EDEADLK;
goto out_unlock_release_sem;
}
@@ -1407,7 +1407,7 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
*/
if (unlikely(ownerdied || !(curval & FUTEX_TID_MASK))) {
/* Keep the OWNER_DIED bit */
- newval = (curval & ~FUTEX_TID_MASK) | current->pid;
+ newval = (curval & ~FUTEX_TID_MASK) | task_pid_vnr(current);
ownerdied = 0;
lock_taken = 1;
}
@@ -1586,7 +1586,7 @@ retry:
/*
* We release only a lock we actually own:
*/
- if ((uval & FUTEX_TID_MASK) != current->pid)
+ if ((uval & FUTEX_TID_MASK) != task_pid_vnr(current))
return -EPERM;
/*
* First take all the futex related locks:
@@ -1607,7 +1607,7 @@ retry_unlocked:
* anyone else up:
*/
if (!(uval & FUTEX_OWNER_DIED))
- uval = cmpxchg_futex_value_locked(uaddr, current->pid, 0);
+ uval = cmpxchg_futex_value_locked(uaddr, task_pid_vnr(current), 0);
if (unlikely(uval == -EFAULT))
@@ -1616,7 +1616,7 @@ retry_unlocked:
* Rare case: we managed to release the lock atomically,
* no need to wake anyone else up:
*/
- if (unlikely(uval == current->pid))
+ if (unlikely(uval == task_pid_vnr(current)))
goto out_unlock;
/*
@@ -1853,7 +1853,7 @@ sys_get_robust_list(int pid, struct robust_list_head __user * __user *head_ptr,
ret = -ESRCH;
rcu_read_lock();
- p = find_task_by_pid(pid);
+ p = find_task_by_vpid(pid);
if (!p)
goto err_unlock;
ret = -EPERM;
@@ -1886,7 +1886,7 @@ retry:
if (get_user(uval, uaddr))
return -1;
- if ((uval & FUTEX_TID_MASK) == curr->pid) {
+ if ((uval & FUTEX_TID_MASK) == task_pid_vnr(curr)) {
/*
* Ok, this dying thread is truly holding a futex
* of interest. Set the OWNER_DIED bit atomically
@@ -2080,7 +2080,7 @@ static int futexfs_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data,
struct vfsmount *mnt)
{
- return get_sb_pseudo(fs_type, "futex", NULL, 0xBAD1DEA, mnt);
+ return get_sb_pseudo(fs_type, "futex", NULL, FUTEXFS_SUPER_MAGIC, mnt);
}
static struct file_system_type futex_fs_type = {
diff --git a/kernel/futex_compat.c b/kernel/futex_compat.c
index 2c2e2954b713..0a43def6fee7 100644
--- a/kernel/futex_compat.c
+++ b/kernel/futex_compat.c
@@ -8,6 +8,7 @@
#include <linux/linkage.h>
#include <linux/compat.h>
+#include <linux/nsproxy.h>
#include <linux/futex.h>
#include <asm/uaccess.h>
@@ -29,6 +30,15 @@ fetch_robust_entry(compat_uptr_t *uentry, struct robust_list __user **entry,
return 0;
}
+static void __user *futex_uaddr(struct robust_list *entry,
+ compat_long_t futex_offset)
+{
+ compat_uptr_t base = ptr_to_compat(entry);
+ void __user *uaddr = compat_ptr(base + futex_offset);
+
+ return uaddr;
+}
+
/*
* Walk curr->robust_list (very carefully, it's a userspace list!)
* and mark any locks found there dead, and notify any waiters.
@@ -75,11 +85,12 @@ void compat_exit_robust_list(struct task_struct *curr)
* A pending lock might already be on the list, so
* dont process it twice:
*/
- if (entry != pending)
- if (handle_futex_death((void __user *)entry + futex_offset,
- curr, pi))
- return;
+ if (entry != pending) {
+ void __user *uaddr = futex_uaddr(entry, futex_offset);
+ if (handle_futex_death(uaddr, curr, pi))
+ return;
+ }
if (rc)
return;
uentry = next_uentry;
@@ -93,9 +104,11 @@ void compat_exit_robust_list(struct task_struct *curr)
cond_resched();
}
- if (pending)
- handle_futex_death((void __user *)pending + futex_offset,
- curr, pip);
+ if (pending) {
+ void __user *uaddr = futex_uaddr(pending, futex_offset);
+
+ handle_futex_death(uaddr, curr, pip);
+ }
}
asmlinkage long
@@ -124,7 +137,7 @@ compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr,
ret = -ESRCH;
read_lock(&tasklist_lock);
- p = find_task_by_pid(pid);
+ p = find_task_by_vpid(pid);
if (!p)
goto err_unlock;
ret = -EPERM;
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index dc8a4451d79b..22a25142e4cf 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -412,7 +412,7 @@ static int hrtimer_reprogram(struct hrtimer *timer,
/*
* When the callback is running, we do not reprogram the clock event
* device. The timer callback is either running on a different CPU or
- * the callback is executed in the hrtimer_interupt context. The
+ * the callback is executed in the hrtimer_interrupt context. The
* reprogramming is handled either by the softirq, which called the
* callback or at the end of the hrtimer_interrupt.
*/
@@ -602,7 +602,7 @@ static int hrtimer_switch_to_hres(void)
/* "Retrigger" the interrupt to get things going */
retrigger_next_event(NULL);
local_irq_restore(flags);
- printk(KERN_INFO "Switched to high resolution mode on CPU %d\n",
+ printk(KERN_DEBUG "Switched to high resolution mode on CPU %d\n",
smp_processor_id());
return 1;
}
@@ -638,7 +638,7 @@ void __timer_stats_hrtimer_set_start_info(struct hrtimer *timer, void *addr)
#endif
/*
- * Counterpart to lock_timer_base above:
+ * Counterpart to lock_hrtimer_base above:
*/
static inline
void unlock_hrtimer_base(const struct hrtimer *timer, unsigned long *flags)
@@ -1286,8 +1286,7 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod
long __sched hrtimer_nanosleep_restart(struct restart_block *restart)
{
struct hrtimer_sleeper t;
- struct timespec __user *rmtp;
- struct timespec tu;
+ struct timespec *rmtp;
ktime_t time;
restart->fn = do_no_restart_syscall;
@@ -1298,14 +1297,12 @@ long __sched hrtimer_nanosleep_restart(struct restart_block *restart)
if (do_nanosleep(&t, HRTIMER_MODE_ABS))
return 0;
- rmtp = (struct timespec __user *) restart->arg1;
+ rmtp = (struct timespec *)restart->arg1;
if (rmtp) {
time = ktime_sub(t.timer.expires, t.timer.base->get_time());
if (time.tv64 <= 0)
return 0;
- tu = ktime_to_timespec(time);
- if (copy_to_user(rmtp, &tu, sizeof(tu)))
- return -EFAULT;
+ *rmtp = ktime_to_timespec(time);
}
restart->fn = hrtimer_nanosleep_restart;
@@ -1314,12 +1311,11 @@ long __sched hrtimer_nanosleep_restart(struct restart_block *restart)
return -ERESTART_RESTARTBLOCK;
}
-long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
+long hrtimer_nanosleep(struct timespec *rqtp, struct timespec *rmtp,
const enum hrtimer_mode mode, const clockid_t clockid)
{
struct restart_block *restart;
struct hrtimer_sleeper t;
- struct timespec tu;
ktime_t rem;
hrtimer_init(&t.timer, clockid, mode);
@@ -1335,9 +1331,7 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
rem = ktime_sub(t.timer.expires, t.timer.base->get_time());
if (rem.tv64 <= 0)
return 0;
- tu = ktime_to_timespec(rem);
- if (copy_to_user(rmtp, &tu, sizeof(tu)))
- return -EFAULT;
+ *rmtp = ktime_to_timespec(rem);
}
restart = &current_thread_info()->restart_block;
@@ -1353,7 +1347,8 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
asmlinkage long
sys_nanosleep(struct timespec __user *rqtp, struct timespec __user *rmtp)
{
- struct timespec tu;
+ struct timespec tu, rmt;
+ int ret;
if (copy_from_user(&tu, rqtp, sizeof(tu)))
return -EFAULT;
@@ -1361,7 +1356,15 @@ sys_nanosleep(struct timespec __user *rqtp, struct timespec __user *rmtp)
if (!timespec_valid(&tu))
return -EINVAL;
- return hrtimer_nanosleep(&tu, rmtp, HRTIMER_MODE_REL, CLOCK_MONOTONIC);
+ ret = hrtimer_nanosleep(&tu, rmtp ? &rmt : NULL, HRTIMER_MODE_REL,
+ CLOCK_MONOTONIC);
+
+ if (ret && rmtp) {
+ if (copy_to_user(rmtp, &rmt, sizeof(*rmtp)))
+ return -EFAULT;
+ }
+
+ return ret;
}
/*
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index f1a73f0b54e7..9b5dff6b3f6a 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -503,7 +503,6 @@ out_unlock:
spin_unlock(&desc->lock);
}
-#ifdef CONFIG_SMP
/**
* handle_percpu_IRQ - Per CPU local irq handler
* @irq: the interrupt number
@@ -529,8 +528,6 @@ handle_percpu_irq(unsigned int irq, struct irq_desc *desc)
desc->chip->eoi(irq);
}
-#endif /* CONFIG_SMP */
-
void
__set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
const char *name)
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index e391cbb1f566..dc335ad27525 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -178,9 +178,11 @@ fastcall unsigned int __do_IRQ(unsigned int irq)
*/
if (desc->chip->ack)
desc->chip->ack(irq);
- action_ret = handle_IRQ_event(irq, desc->action);
- if (!noirqdebug)
- note_interrupt(irq, desc, action_ret);
+ if (likely(!(desc->status & IRQ_DISABLED))) {
+ action_ret = handle_IRQ_event(irq, desc->action);
+ if (!noirqdebug)
+ note_interrupt(irq, desc, action_ret);
+ }
desc->chip->end(irq);
return 1;
}
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 7230d914eaa2..1f314221d534 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -29,12 +29,28 @@
void synchronize_irq(unsigned int irq)
{
struct irq_desc *desc = irq_desc + irq;
+ unsigned int status;
if (irq >= NR_IRQS)
return;
- while (desc->status & IRQ_INPROGRESS)
- cpu_relax();
+ do {
+ unsigned long flags;
+
+ /*
+ * Wait until we're out of the critical section. This might
+ * give the wrong answer due to the lack of memory barriers.
+ */
+ while (desc->status & IRQ_INPROGRESS)
+ cpu_relax();
+
+ /* Ok, that indicated we're done: double-check carefully. */
+ spin_lock_irqsave(&desc->lock, flags);
+ status = desc->status;
+ spin_unlock_irqrestore(&desc->lock, flags);
+
+ /* Oops, that failed? */
+ } while (status & IRQ_INPROGRESS);
}
EXPORT_SYMBOL(synchronize_irq);
@@ -405,7 +421,6 @@ void free_irq(unsigned int irq, void *dev_id)
struct irq_desc *desc;
struct irqaction **p;
unsigned long flags;
- irqreturn_t (*handler)(int, void *) = NULL;
WARN_ON(in_interrupt());
if (irq >= NR_IRQS)
@@ -445,8 +460,21 @@ void free_irq(unsigned int irq, void *dev_id)
/* Make sure it's not being used on another CPU */
synchronize_irq(irq);
- if (action->flags & IRQF_SHARED)
- handler = action->handler;
+#ifdef CONFIG_DEBUG_SHIRQ
+ /*
+ * It's a shared IRQ -- the driver ought to be
+ * prepared for it to happen even now it's
+ * being freed, so let's make sure.... We do
+ * this after actually deregistering it, to
+ * make sure that a 'real' IRQ doesn't run in
+ * parallel with our fake
+ */
+ if (action->flags & IRQF_SHARED) {
+ local_irq_save(flags);
+ action->handler(irq, dev_id);
+ local_irq_restore(flags);
+ }
+#endif
kfree(action);
return;
}
@@ -454,19 +482,6 @@ void free_irq(unsigned int irq, void *dev_id)
spin_unlock_irqrestore(&desc->lock, flags);
return;
}
-#ifdef CONFIG_DEBUG_SHIRQ
- if (handler) {
- /*
- * It's a shared IRQ -- the driver ought to be prepared for it
- * to happen even now it's being freed, so let's make sure....
- * We do this after actually deregistering it, to make sure that
- * a 'real' IRQ doesn't run in parallel with our fake
- */
- local_irq_save(flags);
- handler(irq, dev_id);
- local_irq_restore(flags);
- }
-#endif
}
EXPORT_SYMBOL(free_irq);
diff --git a/kernel/itimer.c b/kernel/itimer.c
index 3205e8e114fa..2fab344dbf56 100644
--- a/kernel/itimer.c
+++ b/kernel/itimer.c
@@ -130,7 +130,7 @@ asmlinkage long sys_getitimer(int which, struct itimerval __user *value)
enum hrtimer_restart it_real_fn(struct hrtimer *timer)
{
struct signal_struct *sig =
- container_of(timer, struct signal_struct, real_timer);
+ container_of(timer, struct signal_struct, real_timer);
send_group_sig_info(SIGALRM, SEND_SIG_PRIV, sig->tsk);
@@ -291,6 +291,6 @@ asmlinkage long sys_setitimer(int which,
return error;
if (copy_to_user(ovalue, &get_buffer, sizeof(get_buffer)))
- return -EFAULT;
+ return -EFAULT;
return 0;
}
diff --git a/kernel/kexec.c b/kernel/kexec.c
index 25db14b89e82..aa74a1ef2da8 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -17,21 +17,30 @@
#include <linux/highmem.h>
#include <linux/syscalls.h>
#include <linux/reboot.h>
-#include <linux/syscalls.h>
#include <linux/ioport.h>
#include <linux/hardirq.h>
#include <linux/elf.h>
#include <linux/elfcore.h>
+#include <linux/utsrelease.h>
+#include <linux/utsname.h>
+#include <linux/numa.h>
#include <asm/page.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/semaphore.h>
+#include <asm/sections.h>
/* Per cpu memory for storing cpu states in case of system crash. */
note_buf_t* crash_notes;
+/* vmcoreinfo stuff */
+unsigned char vmcoreinfo_data[VMCOREINFO_BYTES];
+u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4];
+size_t vmcoreinfo_size;
+size_t vmcoreinfo_max_size = sizeof(vmcoreinfo_data);
+
/* Location of the reserved area for the crash kernel */
struct resource crashk_res = {
.name = "Crash kernel",
@@ -42,7 +51,7 @@ struct resource crashk_res = {
int kexec_should_crash(struct task_struct *p)
{
- if (in_interrupt() || !p->pid || is_init(p) || panic_on_oops)
+ if (in_interrupt() || !p->pid || is_global_init(p) || panic_on_oops)
return 1;
return 0;
}
@@ -776,7 +785,7 @@ static int kimage_load_normal_segment(struct kimage *image,
size_t uchunk, mchunk;
page = kimage_alloc_page(image, GFP_HIGHUSER, maddr);
- if (page == 0) {
+ if (!page) {
result = -ENOMEM;
goto out;
}
@@ -835,7 +844,7 @@ static int kimage_load_crash_segment(struct kimage *image,
size_t uchunk, mchunk;
page = pfn_to_page(maddr >> PAGE_SHIFT);
- if (page == 0) {
+ if (!page) {
result = -ENOMEM;
goto out;
}
@@ -1061,6 +1070,7 @@ void crash_kexec(struct pt_regs *regs)
if (kexec_crash_image) {
struct pt_regs fixed_regs;
crash_setup_regs(&fixed_regs, regs);
+ crash_save_vmcoreinfo();
machine_crash_shutdown(&fixed_regs);
machine_kexec(kexec_crash_image);
}
@@ -1135,3 +1145,270 @@ static int __init crash_notes_memory_init(void)
return 0;
}
module_init(crash_notes_memory_init)
+
+
+/*
+ * parsing the "crashkernel" commandline
+ *
+ * this code is intended to be called from architecture specific code
+ */
+
+
+/*
+ * This function parses command lines in the format
+ *
+ * crashkernel=ramsize-range:size[,...][@offset]
+ *
+ * The function returns 0 on success and -EINVAL on failure.
+ */
+static int __init parse_crashkernel_mem(char *cmdline,
+ unsigned long long system_ram,
+ unsigned long long *crash_size,
+ unsigned long long *crash_base)
+{
+ char *cur = cmdline, *tmp;
+
+ /* for each entry of the comma-separated list */
+ do {
+ unsigned long long start, end = ULLONG_MAX, size;
+
+ /* get the start of the range */
+ start = memparse(cur, &tmp);
+ if (cur == tmp) {
+ pr_warning("crashkernel: Memory value expected\n");
+ return -EINVAL;
+ }
+ cur = tmp;
+ if (*cur != '-') {
+ pr_warning("crashkernel: '-' expected\n");
+ return -EINVAL;
+ }
+ cur++;
+
+ /* if no ':' is here, than we read the end */
+ if (*cur != ':') {
+ end = memparse(cur, &tmp);
+ if (cur == tmp) {
+ pr_warning("crashkernel: Memory "
+ "value expected\n");
+ return -EINVAL;
+ }
+ cur = tmp;
+ if (end <= start) {
+ pr_warning("crashkernel: end <= start\n");
+ return -EINVAL;
+ }
+ }
+
+ if (*cur != ':') {
+ pr_warning("crashkernel: ':' expected\n");
+ return -EINVAL;
+ }
+ cur++;
+
+ size = memparse(cur, &tmp);
+ if (cur == tmp) {
+ pr_warning("Memory value expected\n");
+ return -EINVAL;
+ }
+ cur = tmp;
+ if (size >= system_ram) {
+ pr_warning("crashkernel: invalid size\n");
+ return -EINVAL;
+ }
+
+ /* match ? */
+ if (system_ram >= start && system_ram <= end) {
+ *crash_size = size;
+ break;
+ }
+ } while (*cur++ == ',');
+
+ if (*crash_size > 0) {
+ while (*cur != ' ' && *cur != '@')
+ cur++;
+ if (*cur == '@') {
+ cur++;
+ *crash_base = memparse(cur, &tmp);
+ if (cur == tmp) {
+ pr_warning("Memory value expected "
+ "after '@'\n");
+ return -EINVAL;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * That function parses "simple" (old) crashkernel command lines like
+ *
+ * crashkernel=size[@offset]
+ *
+ * It returns 0 on success and -EINVAL on failure.
+ */
+static int __init parse_crashkernel_simple(char *cmdline,
+ unsigned long long *crash_size,
+ unsigned long long *crash_base)
+{
+ char *cur = cmdline;
+
+ *crash_size = memparse(cmdline, &cur);
+ if (cmdline == cur) {
+ pr_warning("crashkernel: memory value expected\n");
+ return -EINVAL;
+ }
+
+ if (*cur == '@')
+ *crash_base = memparse(cur+1, &cur);
+
+ return 0;
+}
+
+/*
+ * That function is the entry point for command line parsing and should be
+ * called from the arch-specific code.
+ */
+int __init parse_crashkernel(char *cmdline,
+ unsigned long long system_ram,
+ unsigned long long *crash_size,
+ unsigned long long *crash_base)
+{
+ char *p = cmdline, *ck_cmdline = NULL;
+ char *first_colon, *first_space;
+
+ BUG_ON(!crash_size || !crash_base);
+ *crash_size = 0;
+ *crash_base = 0;
+
+ /* find crashkernel and use the last one if there are more */
+ p = strstr(p, "crashkernel=");
+ while (p) {
+ ck_cmdline = p;
+ p = strstr(p+1, "crashkernel=");
+ }
+
+ if (!ck_cmdline)
+ return -EINVAL;
+
+ ck_cmdline += 12; /* strlen("crashkernel=") */
+
+ /*
+ * if the commandline contains a ':', then that's the extended
+ * syntax -- if not, it must be the classic syntax
+ */
+ first_colon = strchr(ck_cmdline, ':');
+ first_space = strchr(ck_cmdline, ' ');
+ if (first_colon && (!first_space || first_colon < first_space))
+ return parse_crashkernel_mem(ck_cmdline, system_ram,
+ crash_size, crash_base);
+ else
+ return parse_crashkernel_simple(ck_cmdline, crash_size,
+ crash_base);
+
+ return 0;
+}
+
+
+
+void crash_save_vmcoreinfo(void)
+{
+ u32 *buf;
+
+ if (!vmcoreinfo_size)
+ return;
+
+ vmcoreinfo_append_str("CRASHTIME=%ld", get_seconds());
+
+ buf = (u32 *)vmcoreinfo_note;
+
+ buf = append_elf_note(buf, VMCOREINFO_NOTE_NAME, 0, vmcoreinfo_data,
+ vmcoreinfo_size);
+
+ final_note(buf);
+}
+
+void vmcoreinfo_append_str(const char *fmt, ...)
+{
+ va_list args;
+ char buf[0x50];
+ int r;
+
+ va_start(args, fmt);
+ r = vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ if (r + vmcoreinfo_size > vmcoreinfo_max_size)
+ r = vmcoreinfo_max_size - vmcoreinfo_size;
+
+ memcpy(&vmcoreinfo_data[vmcoreinfo_size], buf, r);
+
+ vmcoreinfo_size += r;
+}
+
+/*
+ * provide an empty default implementation here -- architecture
+ * code may override this
+ */
+void __attribute__ ((weak)) arch_crash_save_vmcoreinfo(void)
+{}
+
+unsigned long __attribute__ ((weak)) paddr_vmcoreinfo_note(void)
+{
+ return __pa((unsigned long)(char *)&vmcoreinfo_note);
+}
+
+static int __init crash_save_vmcoreinfo_init(void)
+{
+ vmcoreinfo_append_str("OSRELEASE=%s\n", init_uts_ns.name.release);
+ vmcoreinfo_append_str("PAGESIZE=%ld\n", PAGE_SIZE);
+
+ VMCOREINFO_SYMBOL(init_uts_ns);
+ VMCOREINFO_SYMBOL(node_online_map);
+ VMCOREINFO_SYMBOL(swapper_pg_dir);
+ VMCOREINFO_SYMBOL(_stext);
+
+#ifndef CONFIG_NEED_MULTIPLE_NODES
+ VMCOREINFO_SYMBOL(mem_map);
+ VMCOREINFO_SYMBOL(contig_page_data);
+#endif
+#ifdef CONFIG_SPARSEMEM
+ VMCOREINFO_SYMBOL(mem_section);
+ VMCOREINFO_LENGTH(mem_section, NR_SECTION_ROOTS);
+ VMCOREINFO_SIZE(mem_section);
+ VMCOREINFO_OFFSET(mem_section, section_mem_map);
+#endif
+ VMCOREINFO_SIZE(page);
+ VMCOREINFO_SIZE(pglist_data);
+ VMCOREINFO_SIZE(zone);
+ VMCOREINFO_SIZE(free_area);
+ VMCOREINFO_SIZE(list_head);
+ VMCOREINFO_TYPEDEF_SIZE(nodemask_t);
+ VMCOREINFO_OFFSET(page, flags);
+ VMCOREINFO_OFFSET(page, _count);
+ VMCOREINFO_OFFSET(page, mapping);
+ VMCOREINFO_OFFSET(page, lru);
+ VMCOREINFO_OFFSET(pglist_data, node_zones);
+ VMCOREINFO_OFFSET(pglist_data, nr_zones);
+#ifdef CONFIG_FLAT_NODE_MEM_MAP
+ VMCOREINFO_OFFSET(pglist_data, node_mem_map);
+#endif
+ VMCOREINFO_OFFSET(pglist_data, node_start_pfn);
+ VMCOREINFO_OFFSET(pglist_data, node_spanned_pages);
+ VMCOREINFO_OFFSET(pglist_data, node_id);
+ VMCOREINFO_OFFSET(zone, free_area);
+ VMCOREINFO_OFFSET(zone, vm_stat);
+ VMCOREINFO_OFFSET(zone, spanned_pages);
+ VMCOREINFO_OFFSET(free_area, free_list);
+ VMCOREINFO_OFFSET(list_head, next);
+ VMCOREINFO_OFFSET(list_head, prev);
+ VMCOREINFO_LENGTH(zone.free_area, MAX_ORDER);
+ VMCOREINFO_NUMBER(NR_FREE_PAGES);
+
+ arch_crash_save_vmcoreinfo();
+
+ return 0;
+}
+
+module_init(crash_save_vmcoreinfo_init)
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 4b8a4493c541..e3a5d817ac9b 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -64,7 +64,6 @@
static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE];
static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE];
-static atomic_t kprobe_count;
/* NOTE: change this value only with kprobe_mutex held */
static bool kprobe_enabled;
@@ -73,11 +72,6 @@ DEFINE_MUTEX(kprobe_mutex); /* Protects kprobe_table */
DEFINE_SPINLOCK(kretprobe_lock); /* Protects kretprobe_inst_table */
static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL;
-static struct notifier_block kprobe_page_fault_nb = {
- .notifier_call = kprobe_exceptions_notify,
- .priority = 0x7fffffff /* we need to notified first */
-};
-
#ifdef __ARCH_WANT_KPROBES_INSN_SLOT
/*
* kprobe->ainsn.insn points to the copy of the instruction to be
@@ -556,8 +550,6 @@ static int __kprobes __register_kprobe(struct kprobe *p,
old_p = get_kprobe(p->addr);
if (old_p) {
ret = register_aggr_kprobe(old_p, p);
- if (!ret)
- atomic_inc(&kprobe_count);
goto out;
}
@@ -569,13 +561,9 @@ static int __kprobes __register_kprobe(struct kprobe *p,
hlist_add_head_rcu(&p->hlist,
&kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]);
- if (kprobe_enabled) {
- if (atomic_add_return(1, &kprobe_count) == \
- (ARCH_INACTIVE_KPROBE_COUNT + 1))
- register_page_fault_notifier(&kprobe_page_fault_nb);
-
+ if (kprobe_enabled)
arch_arm_kprobe(p);
- }
+
out:
mutex_unlock(&kprobe_mutex);
@@ -658,16 +646,6 @@ valid_p:
}
mutex_unlock(&kprobe_mutex);
}
-
- /* Call unregister_page_fault_notifier()
- * if no probes are active
- */
- mutex_lock(&kprobe_mutex);
- if (atomic_add_return(-1, &kprobe_count) == \
- ARCH_INACTIVE_KPROBE_COUNT)
- unregister_page_fault_notifier(&kprobe_page_fault_nb);
- mutex_unlock(&kprobe_mutex);
- return;
}
static struct notifier_block kprobe_exceptions_nb = {
@@ -738,6 +716,18 @@ int __kprobes register_kretprobe(struct kretprobe *rp)
int ret = 0;
struct kretprobe_instance *inst;
int i;
+ void *addr = rp->kp.addr;
+
+ if (kretprobe_blacklist_size) {
+ if (addr == NULL)
+ kprobe_lookup_name(rp->kp.symbol_name, addr);
+ addr += rp->kp.offset;
+
+ for (i = 0; kretprobe_blacklist[i].name != NULL; i++) {
+ if (kretprobe_blacklist[i].addr == addr)
+ return -EINVAL;
+ }
+ }
rp->kp.pre_handler = pre_handler_kretprobe;
rp->kp.post_handler = NULL;
@@ -815,7 +805,17 @@ static int __init init_kprobes(void)
INIT_HLIST_HEAD(&kprobe_table[i]);
INIT_HLIST_HEAD(&kretprobe_inst_table[i]);
}
- atomic_set(&kprobe_count, 0);
+
+ if (kretprobe_blacklist_size) {
+ /* lookup the function address from its name */
+ for (i = 0; kretprobe_blacklist[i].name != NULL; i++) {
+ kprobe_lookup_name(kretprobe_blacklist[i].name,
+ kretprobe_blacklist[i].addr);
+ if (!kretprobe_blacklist[i].addr)
+ printk("kretprobe: lookup failed: %s\n",
+ kretprobe_blacklist[i].name);
+ }
+ }
/* By default, kprobes are enabled */
kprobe_enabled = true;
@@ -921,13 +921,6 @@ static void __kprobes enable_all_kprobes(void)
if (kprobe_enabled)
goto already_enabled;
- /*
- * Re-register the page fault notifier only if there are any
- * active probes at the time of enabling kprobes globally
- */
- if (atomic_read(&kprobe_count) > ARCH_INACTIVE_KPROBE_COUNT)
- register_page_fault_notifier(&kprobe_page_fault_nb);
-
for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
head = &kprobe_table[i];
hlist_for_each_entry_rcu(p, node, head, hlist)
@@ -968,10 +961,7 @@ static void __kprobes disable_all_kprobes(void)
mutex_unlock(&kprobe_mutex);
/* Allow all currently running kprobes to complete */
synchronize_sched();
-
- mutex_lock(&kprobe_mutex);
- /* Unconditionally unregister the page_fault notifier */
- unregister_page_fault_notifier(&kprobe_page_fault_nb);
+ return;
already_disabled:
mutex_unlock(&kprobe_mutex);
diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c
index 6046939d0804..65daa5373ca6 100644
--- a/kernel/ksysfs.c
+++ b/kernel/ksysfs.c
@@ -61,6 +61,15 @@ static ssize_t kexec_crash_loaded_show(struct kset *kset, char *page)
return sprintf(page, "%d\n", !!kexec_crash_image);
}
KERNEL_ATTR_RO(kexec_crash_loaded);
+
+static ssize_t vmcoreinfo_show(struct kset *kset, char *page)
+{
+ return sprintf(page, "%lx %x\n",
+ paddr_vmcoreinfo_note(),
+ (unsigned int)vmcoreinfo_max_size);
+}
+KERNEL_ATTR_RO(vmcoreinfo);
+
#endif /* CONFIG_KEXEC */
/*
@@ -96,6 +105,7 @@ static struct attribute * kernel_attrs[] = {
#ifdef CONFIG_KEXEC
&kexec_loaded_attr.attr,
&kexec_crash_loaded_attr.attr,
+ &vmcoreinfo_attr.attr,
#endif
NULL
};
diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index a6f1ee9c92d9..ed38bbfc48a3 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -511,11 +511,11 @@ static void lockdep_print_held_locks(struct task_struct *curr)
int i, depth = curr->lockdep_depth;
if (!depth) {
- printk("no locks held by %s/%d.\n", curr->comm, curr->pid);
+ printk("no locks held by %s/%d.\n", curr->comm, task_pid_nr(curr));
return;
}
printk("%d lock%s held by %s/%d:\n",
- depth, depth > 1 ? "s" : "", curr->comm, curr->pid);
+ depth, depth > 1 ? "s" : "", curr->comm, task_pid_nr(curr));
for (i = 0; i < depth; i++) {
printk(" #%d: ", i);
@@ -904,7 +904,7 @@ print_circular_bug_header(struct lock_list *entry, unsigned int depth)
print_kernel_version();
printk( "-------------------------------------------------------\n");
printk("%s/%d is trying to acquire lock:\n",
- curr->comm, curr->pid);
+ curr->comm, task_pid_nr(curr));
print_lock(check_source);
printk("\nbut task is already holding lock:\n");
print_lock(check_target);
@@ -1085,7 +1085,7 @@ print_bad_irq_dependency(struct task_struct *curr,
print_kernel_version();
printk( "------------------------------------------------------\n");
printk("%s/%d [HC%u[%lu]:SC%u[%lu]:HE%u:SE%u] is trying to acquire:\n",
- curr->comm, curr->pid,
+ curr->comm, task_pid_nr(curr),
curr->hardirq_context, hardirq_count() >> HARDIRQ_SHIFT,
curr->softirq_context, softirq_count() >> SOFTIRQ_SHIFT,
curr->hardirqs_enabled,
@@ -1237,7 +1237,7 @@ print_deadlock_bug(struct task_struct *curr, struct held_lock *prev,
print_kernel_version();
printk( "---------------------------------------------\n");
printk("%s/%d is trying to acquire lock:\n",
- curr->comm, curr->pid);
+ curr->comm, task_pid_nr(curr));
print_lock(next);
printk("\nbut task is already holding lock:\n");
print_lock(prev);
@@ -1521,7 +1521,7 @@ cache_hit:
}
static int validate_chain(struct task_struct *curr, struct lockdep_map *lock,
- struct held_lock *hlock, int chain_head, u64 chain_key)
+ struct held_lock *hlock, int chain_head, u64 chain_key)
{
/*
* Trylock needs to maintain the stack of held locks, but it
@@ -1641,7 +1641,7 @@ print_usage_bug(struct task_struct *curr, struct held_lock *this,
usage_str[prev_bit], usage_str[new_bit]);
printk("%s/%d [HC%u[%lu]:SC%u[%lu]:HE%u:SE%u] takes:\n",
- curr->comm, curr->pid,
+ curr->comm, task_pid_nr(curr),
trace_hardirq_context(curr), hardirq_count() >> HARDIRQ_SHIFT,
trace_softirq_context(curr), softirq_count() >> SOFTIRQ_SHIFT,
trace_hardirqs_enabled(curr),
@@ -1694,7 +1694,7 @@ print_irq_inversion_bug(struct task_struct *curr, struct lock_class *other,
print_kernel_version();
printk( "---------------------------------------------------------\n");
printk("%s/%d just changed the state of lock:\n",
- curr->comm, curr->pid);
+ curr->comm, task_pid_nr(curr));
print_lock(this);
if (forwards)
printk("but this lock took another, %s-irq-unsafe lock in the past:\n", irqclass);
@@ -2424,7 +2424,7 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass,
return 0;
/*
- * Calculate the chain hash: it's the combined has of all the
+ * Calculate the chain hash: it's the combined hash of all the
* lock keys along the dependency chain. We save the hash value
* at every step so that we can get the current hash easily
* after unlock. The chain hash is then used to cache dependency
@@ -2487,7 +2487,7 @@ print_unlock_inbalance_bug(struct task_struct *curr, struct lockdep_map *lock,
printk( "[ BUG: bad unlock balance detected! ]\n");
printk( "-------------------------------------\n");
printk("%s/%d is trying to release lock (",
- curr->comm, curr->pid);
+ curr->comm, task_pid_nr(curr));
print_lockdep_cache(lock);
printk(") at:\n");
print_ip_sym(ip);
@@ -2737,7 +2737,7 @@ print_lock_contention_bug(struct task_struct *curr, struct lockdep_map *lock,
printk( "[ BUG: bad contention detected! ]\n");
printk( "---------------------------------\n");
printk("%s/%d is trying to contend lock (",
- curr->comm, curr->pid);
+ curr->comm, task_pid_nr(curr));
print_lockdep_cache(lock);
printk(") at:\n");
print_ip_sym(ip);
@@ -3072,7 +3072,7 @@ print_freed_lock_bug(struct task_struct *curr, const void *mem_from,
printk( "[ BUG: held lock freed! ]\n");
printk( "-------------------------\n");
printk("%s/%d is freeing memory %p-%p, with a lock still held there!\n",
- curr->comm, curr->pid, mem_from, mem_to-1);
+ curr->comm, task_pid_nr(curr), mem_from, mem_to-1);
print_lock(hlock);
lockdep_print_held_locks(curr);
@@ -3125,7 +3125,7 @@ static void print_held_locks_bug(struct task_struct *curr)
printk( "[ BUG: lock held at task exit time! ]\n");
printk( "-------------------------------------\n");
printk("%s/%d is exiting with locks still held!\n",
- curr->comm, curr->pid);
+ curr->comm, task_pid_nr(curr));
lockdep_print_held_locks(curr);
printk("\nstack backtrace:\n");
diff --git a/kernel/marker.c b/kernel/marker.c
new file mode 100644
index 000000000000..5323cfaedbce
--- /dev/null
+++ b/kernel/marker.c
@@ -0,0 +1,518 @@
+/*
+ * Copyright (C) 2007 Mathieu Desnoyers
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
+#include <linux/jhash.h>
+#include <linux/list.h>
+#include <linux/rcupdate.h>
+#include <linux/marker.h>
+#include <linux/err.h>
+
+extern struct marker __start___markers[];
+extern struct marker __stop___markers[];
+
+/*
+ * markers_mutex nests inside module_mutex. Markers mutex protects the builtin
+ * and module markers, the hash table and deferred_sync.
+ */
+static DEFINE_MUTEX(markers_mutex);
+
+/*
+ * Marker deferred synchronization.
+ * Upon marker probe_unregister, we delay call to synchronize_sched() to
+ * accelerate mass unregistration (only when there is no more reference to a
+ * given module do we call synchronize_sched()). However, we need to make sure
+ * every critical region has ended before we re-arm a marker that has been
+ * unregistered and then registered back with a different probe data.
+ */
+static int deferred_sync;
+
+/*
+ * Marker hash table, containing the active markers.
+ * Protected by module_mutex.
+ */
+#define MARKER_HASH_BITS 6
+#define MARKER_TABLE_SIZE (1 << MARKER_HASH_BITS)
+
+struct marker_entry {
+ struct hlist_node hlist;
+ char *format;
+ marker_probe_func *probe;
+ void *private;
+ int refcount; /* Number of times armed. 0 if disarmed. */
+ char name[0]; /* Contains name'\0'format'\0' */
+};
+
+static struct hlist_head marker_table[MARKER_TABLE_SIZE];
+
+/**
+ * __mark_empty_function - Empty probe callback
+ * @mdata: pointer of type const struct marker
+ * @fmt: format string
+ * @...: variable argument list
+ *
+ * Empty callback provided as a probe to the markers. By providing this to a
+ * disabled marker, we make sure the execution flow is always valid even
+ * though the function pointer change and the marker enabling are two distinct
+ * operations that modifies the execution flow of preemptible code.
+ */
+void __mark_empty_function(const struct marker *mdata, void *private,
+ const char *fmt, ...)
+{
+}
+EXPORT_SYMBOL_GPL(__mark_empty_function);
+
+/*
+ * Get marker if the marker is present in the marker hash table.
+ * Must be called with markers_mutex held.
+ * Returns NULL if not present.
+ */
+static struct marker_entry *get_marker(const char *name)
+{
+ struct hlist_head *head;
+ struct hlist_node *node;
+ struct marker_entry *e;
+ u32 hash = jhash(name, strlen(name), 0);
+
+ head = &marker_table[hash & ((1 << MARKER_HASH_BITS)-1)];
+ hlist_for_each_entry(e, node, head, hlist) {
+ if (!strcmp(name, e->name))
+ return e;
+ }
+ return NULL;
+}
+
+/*
+ * Add the marker to the marker hash table. Must be called with markers_mutex
+ * held.
+ */
+static int add_marker(const char *name, const char *format,
+ marker_probe_func *probe, void *private)
+{
+ struct hlist_head *head;
+ struct hlist_node *node;
+ struct marker_entry *e;
+ size_t name_len = strlen(name) + 1;
+ size_t format_len = 0;
+ u32 hash = jhash(name, name_len-1, 0);
+
+ if (format)
+ format_len = strlen(format) + 1;
+ head = &marker_table[hash & ((1 << MARKER_HASH_BITS)-1)];
+ hlist_for_each_entry(e, node, head, hlist) {
+ if (!strcmp(name, e->name)) {
+ printk(KERN_NOTICE
+ "Marker %s busy, probe %p already installed\n",
+ name, e->probe);
+ return -EBUSY; /* Already there */
+ }
+ }
+ /*
+ * Using kmalloc here to allocate a variable length element. Could
+ * cause some memory fragmentation if overused.
+ */
+ e = kmalloc(sizeof(struct marker_entry) + name_len + format_len,
+ GFP_KERNEL);
+ if (!e)
+ return -ENOMEM;
+ memcpy(&e->name[0], name, name_len);
+ if (format) {
+ e->format = &e->name[name_len];
+ memcpy(e->format, format, format_len);
+ trace_mark(core_marker_format, "name %s format %s",
+ e->name, e->format);
+ } else
+ e->format = NULL;
+ e->probe = probe;
+ e->private = private;
+ e->refcount = 0;
+ hlist_add_head(&e->hlist, head);
+ return 0;
+}
+
+/*
+ * Remove the marker from the marker hash table. Must be called with mutex_lock
+ * held.
+ */
+static void *remove_marker(const char *name)
+{
+ struct hlist_head *head;
+ struct hlist_node *node;
+ struct marker_entry *e;
+ int found = 0;
+ size_t len = strlen(name) + 1;
+ void *private = NULL;
+ u32 hash = jhash(name, len-1, 0);
+
+ head = &marker_table[hash & ((1 << MARKER_HASH_BITS)-1)];
+ hlist_for_each_entry(e, node, head, hlist) {
+ if (!strcmp(name, e->name)) {
+ found = 1;
+ break;
+ }
+ }
+ if (found) {
+ private = e->private;
+ hlist_del(&e->hlist);
+ kfree(e);
+ }
+ return private;
+}
+
+/*
+ * Set the mark_entry format to the format found in the element.
+ */
+static int marker_set_format(struct marker_entry **entry, const char *format)
+{
+ struct marker_entry *e;
+ size_t name_len = strlen((*entry)->name) + 1;
+ size_t format_len = strlen(format) + 1;
+
+ e = kmalloc(sizeof(struct marker_entry) + name_len + format_len,
+ GFP_KERNEL);
+ if (!e)
+ return -ENOMEM;
+ memcpy(&e->name[0], (*entry)->name, name_len);
+ e->format = &e->name[name_len];
+ memcpy(e->format, format, format_len);
+ e->probe = (*entry)->probe;
+ e->private = (*entry)->private;
+ e->refcount = (*entry)->refcount;
+ hlist_add_before(&e->hlist, &(*entry)->hlist);
+ hlist_del(&(*entry)->hlist);
+ kfree(*entry);
+ *entry = e;
+ trace_mark(core_marker_format, "name %s format %s",
+ e->name, e->format);
+ return 0;
+}
+
+/*
+ * Sets the probe callback corresponding to one marker.
+ */
+static int set_marker(struct marker_entry **entry, struct marker *elem)
+{
+ int ret;
+ WARN_ON(strcmp((*entry)->name, elem->name) != 0);
+
+ if ((*entry)->format) {
+ if (strcmp((*entry)->format, elem->format) != 0) {
+ printk(KERN_NOTICE
+ "Format mismatch for probe %s "
+ "(%s), marker (%s)\n",
+ (*entry)->name,
+ (*entry)->format,
+ elem->format);
+ return -EPERM;
+ }
+ } else {
+ ret = marker_set_format(entry, elem->format);
+ if (ret)
+ return ret;
+ }
+ elem->call = (*entry)->probe;
+ elem->private = (*entry)->private;
+ elem->state = 1;
+ return 0;
+}
+
+/*
+ * Disable a marker and its probe callback.
+ * Note: only after a synchronize_sched() issued after setting elem->call to the
+ * empty function insures that the original callback is not used anymore. This
+ * insured by preemption disabling around the call site.
+ */
+static void disable_marker(struct marker *elem)
+{
+ elem->state = 0;
+ elem->call = __mark_empty_function;
+ /*
+ * Leave the private data and id there, because removal is racy and
+ * should be done only after a synchronize_sched(). These are never used
+ * until the next initialization anyway.
+ */
+}
+
+/**
+ * marker_update_probe_range - Update a probe range
+ * @begin: beginning of the range
+ * @end: end of the range
+ * @probe_module: module address of the probe being updated
+ * @refcount: number of references left to the given probe_module (out)
+ *
+ * Updates the probe callback corresponding to a range of markers.
+ */
+void marker_update_probe_range(struct marker *begin,
+ struct marker *end, struct module *probe_module,
+ int *refcount)
+{
+ struct marker *iter;
+ struct marker_entry *mark_entry;
+
+ mutex_lock(&markers_mutex);
+ for (iter = begin; iter < end; iter++) {
+ mark_entry = get_marker(iter->name);
+ if (mark_entry && mark_entry->refcount) {
+ set_marker(&mark_entry, iter);
+ /*
+ * ignore error, continue
+ */
+ if (probe_module)
+ if (probe_module ==
+ __module_text_address((unsigned long)mark_entry->probe))
+ (*refcount)++;
+ } else {
+ disable_marker(iter);
+ }
+ }
+ mutex_unlock(&markers_mutex);
+}
+
+/*
+ * Update probes, removing the faulty probes.
+ * Issues a synchronize_sched() when no reference to the module passed
+ * as parameter is found in the probes so the probe module can be
+ * safely unloaded from now on.
+ */
+static void marker_update_probes(struct module *probe_module)
+{
+ int refcount = 0;
+
+ /* Core kernel markers */
+ marker_update_probe_range(__start___markers,
+ __stop___markers, probe_module, &refcount);
+ /* Markers in modules. */
+ module_update_markers(probe_module, &refcount);
+ if (probe_module && refcount == 0) {
+ synchronize_sched();
+ deferred_sync = 0;
+ }
+}
+
+/**
+ * marker_probe_register - Connect a probe to a marker
+ * @name: marker name
+ * @format: format string
+ * @probe: probe handler
+ * @private: probe private data
+ *
+ * private data must be a valid allocated memory address, or NULL.
+ * Returns 0 if ok, error value on error.
+ */
+int marker_probe_register(const char *name, const char *format,
+ marker_probe_func *probe, void *private)
+{
+ struct marker_entry *entry;
+ int ret = 0;
+
+ mutex_lock(&markers_mutex);
+ entry = get_marker(name);
+ if (entry && entry->refcount) {
+ ret = -EBUSY;
+ goto end;
+ }
+ if (deferred_sync) {
+ synchronize_sched();
+ deferred_sync = 0;
+ }
+ ret = add_marker(name, format, probe, private);
+ if (ret)
+ goto end;
+ mutex_unlock(&markers_mutex);
+ marker_update_probes(NULL);
+ return ret;
+end:
+ mutex_unlock(&markers_mutex);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(marker_probe_register);
+
+/**
+ * marker_probe_unregister - Disconnect a probe from a marker
+ * @name: marker name
+ *
+ * Returns the private data given to marker_probe_register, or an ERR_PTR().
+ */
+void *marker_probe_unregister(const char *name)
+{
+ struct module *probe_module;
+ struct marker_entry *entry;
+ void *private;
+
+ mutex_lock(&markers_mutex);
+ entry = get_marker(name);
+ if (!entry) {
+ private = ERR_PTR(-ENOENT);
+ goto end;
+ }
+ entry->refcount = 0;
+ /* In what module is the probe handler ? */
+ probe_module = __module_text_address((unsigned long)entry->probe);
+ private = remove_marker(name);
+ deferred_sync = 1;
+ mutex_unlock(&markers_mutex);
+ marker_update_probes(probe_module);
+ return private;
+end:
+ mutex_unlock(&markers_mutex);
+ return private;
+}
+EXPORT_SYMBOL_GPL(marker_probe_unregister);
+
+/**
+ * marker_probe_unregister_private_data - Disconnect a probe from a marker
+ * @private: probe private data
+ *
+ * Unregister a marker by providing the registered private data.
+ * Returns the private data given to marker_probe_register, or an ERR_PTR().
+ */
+void *marker_probe_unregister_private_data(void *private)
+{
+ struct module *probe_module;
+ struct hlist_head *head;
+ struct hlist_node *node;
+ struct marker_entry *entry;
+ int found = 0;
+ unsigned int i;
+
+ mutex_lock(&markers_mutex);
+ for (i = 0; i < MARKER_TABLE_SIZE; i++) {
+ head = &marker_table[i];
+ hlist_for_each_entry(entry, node, head, hlist) {
+ if (entry->private == private) {
+ found = 1;
+ goto iter_end;
+ }
+ }
+ }
+iter_end:
+ if (!found) {
+ private = ERR_PTR(-ENOENT);
+ goto end;
+ }
+ entry->refcount = 0;
+ /* In what module is the probe handler ? */
+ probe_module = __module_text_address((unsigned long)entry->probe);
+ private = remove_marker(entry->name);
+ deferred_sync = 1;
+ mutex_unlock(&markers_mutex);
+ marker_update_probes(probe_module);
+ return private;
+end:
+ mutex_unlock(&markers_mutex);
+ return private;
+}
+EXPORT_SYMBOL_GPL(marker_probe_unregister_private_data);
+
+/**
+ * marker_arm - Arm a marker
+ * @name: marker name
+ *
+ * Activate a marker. It keeps a reference count of the number of
+ * arming/disarming done.
+ * Returns 0 if ok, error value on error.
+ */
+int marker_arm(const char *name)
+{
+ struct marker_entry *entry;
+ int ret = 0;
+
+ mutex_lock(&markers_mutex);
+ entry = get_marker(name);
+ if (!entry) {
+ ret = -ENOENT;
+ goto end;
+ }
+ /*
+ * Only need to update probes when refcount passes from 0 to 1.
+ */
+ if (entry->refcount++)
+ goto end;
+end:
+ mutex_unlock(&markers_mutex);
+ marker_update_probes(NULL);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(marker_arm);
+
+/**
+ * marker_disarm - Disarm a marker
+ * @name: marker name
+ *
+ * Disarm a marker. It keeps a reference count of the number of arming/disarming
+ * done.
+ * Returns 0 if ok, error value on error.
+ */
+int marker_disarm(const char *name)
+{
+ struct marker_entry *entry;
+ int ret = 0;
+
+ mutex_lock(&markers_mutex);
+ entry = get_marker(name);
+ if (!entry) {
+ ret = -ENOENT;
+ goto end;
+ }
+ /*
+ * Only permit decrement refcount if higher than 0.
+ * Do probe update only on 1 -> 0 transition.
+ */
+ if (entry->refcount) {
+ if (--entry->refcount)
+ goto end;
+ } else {
+ ret = -EPERM;
+ goto end;
+ }
+end:
+ mutex_unlock(&markers_mutex);
+ marker_update_probes(NULL);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(marker_disarm);
+
+/**
+ * marker_get_private_data - Get a marker's probe private data
+ * @name: marker name
+ *
+ * Returns the private data pointer, or an ERR_PTR.
+ * The private data pointer should _only_ be dereferenced if the caller is the
+ * owner of the data, or its content could vanish. This is mostly used to
+ * confirm that a caller is the owner of a registered probe.
+ */
+void *marker_get_private_data(const char *name)
+{
+ struct hlist_head *head;
+ struct hlist_node *node;
+ struct marker_entry *e;
+ size_t name_len = strlen(name) + 1;
+ u32 hash = jhash(name, name_len-1, 0);
+ int found = 0;
+
+ head = &marker_table[hash & ((1 << MARKER_HASH_BITS)-1)];
+ hlist_for_each_entry(e, node, head, hlist) {
+ if (!strcmp(name, e->name)) {
+ found = 1;
+ return e->private;
+ }
+ }
+ return ERR_PTR(-ENOENT);
+}
+EXPORT_SYMBOL_GPL(marker_get_private_data);
diff --git a/kernel/module.c b/kernel/module.c
index db0ead0363e2..3202c9950073 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -20,6 +20,7 @@
#include <linux/moduleloader.h>
#include <linux/init.h>
#include <linux/kallsyms.h>
+#include <linux/sysfs.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
@@ -104,7 +105,7 @@ void __module_put_and_exit(struct module *mod, long code)
do_exit(code);
}
EXPORT_SYMBOL(__module_put_and_exit);
-
+
/* Find a module section: 0 means not found. */
static unsigned int find_sec(Elf_Ehdr *hdr,
Elf_Shdr *sechdrs,
@@ -178,7 +179,7 @@ static unsigned long __find_symbol(const char *name,
struct module *mod;
const struct kernel_symbol *ks;
- /* Core kernel first. */
+ /* Core kernel first. */
*owner = NULL;
ks = lookup_symbol(name, __start___ksymtab, __stop___ksymtab);
if (ks) {
@@ -230,7 +231,7 @@ static unsigned long __find_symbol(const char *name,
return ks->value;
}
- /* Now try modules. */
+ /* Now try modules. */
list_for_each_entry(mod, &modules, list) {
*owner = mod;
ks = lookup_symbol(name, mod->syms, mod->syms + mod->num_syms);
@@ -284,7 +285,7 @@ static unsigned long __find_symbol(const char *name,
}
}
DEBUGP("Failed to find symbol %s\n", name);
- return 0;
+ return 0;
}
/* Search for module by name: must hold module_mutex. */
@@ -440,7 +441,7 @@ static int percpu_modinit(void)
}
return 0;
-}
+}
__initcall(percpu_modinit);
#else /* ... !CONFIG_SMP */
static inline void *percpu_modalloc(unsigned long size, unsigned long align,
@@ -482,8 +483,8 @@ static int modinfo_##field##_exists(struct module *mod) \
} \
static void free_modinfo_##field(struct module *mod) \
{ \
- kfree(mod->field); \
- mod->field = NULL; \
+ kfree(mod->field); \
+ mod->field = NULL; \
} \
static struct module_attribute modinfo_##field = { \
.attr = { .name = __stringify(field), .mode = 0444 }, \
@@ -692,8 +693,7 @@ sys_delete_module(const char __user *name_user, unsigned int flags)
}
/* If it has an init func, it must have an exit func to unload */
- if ((mod->init != NULL && mod->exit == NULL)
- || mod->unsafe) {
+ if (mod->init && !mod->exit) {
forced = try_force_unload(flags);
if (!forced) {
/* This module can't be removed */
@@ -741,11 +741,6 @@ static void print_unload_info(struct seq_file *m, struct module *mod)
seq_printf(m, "%s,", use->module_which_uses->name);
}
- if (mod->unsafe) {
- printed_something = 1;
- seq_printf(m, "[unsafe],");
- }
-
if (mod->init != NULL && mod->exit == NULL) {
printed_something = 1;
seq_printf(m, "[permanent],");
@@ -995,7 +990,7 @@ static void add_sect_attrs(struct module *mod, unsigned int nsect,
struct module_sect_attrs *sect_attrs;
struct module_sect_attr *sattr;
struct attribute **gattr;
-
+
/* Count loaded sections and allocate structures */
for (i = 0; i < nsect; i++)
if (sechdrs[i].sh_flags & SHF_ALLOC)
@@ -1053,6 +1048,100 @@ static void remove_sect_attrs(struct module *mod)
}
}
+/*
+ * /sys/module/foo/notes/.section.name gives contents of SHT_NOTE sections.
+ */
+
+struct module_notes_attrs {
+ struct kobject *dir;
+ unsigned int notes;
+ struct bin_attribute attrs[0];
+};
+
+static ssize_t module_notes_read(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t pos, size_t count)
+{
+ /*
+ * The caller checked the pos and count against our size.
+ */
+ memcpy(buf, bin_attr->private + pos, count);
+ return count;
+}
+
+static void free_notes_attrs(struct module_notes_attrs *notes_attrs,
+ unsigned int i)
+{
+ if (notes_attrs->dir) {
+ while (i-- > 0)
+ sysfs_remove_bin_file(notes_attrs->dir,
+ &notes_attrs->attrs[i]);
+ kobject_del(notes_attrs->dir);
+ }
+ kfree(notes_attrs);
+}
+
+static void add_notes_attrs(struct module *mod, unsigned int nsect,
+ char *secstrings, Elf_Shdr *sechdrs)
+{
+ unsigned int notes, loaded, i;
+ struct module_notes_attrs *notes_attrs;
+ struct bin_attribute *nattr;
+
+ /* Count notes sections and allocate structures. */
+ notes = 0;
+ for (i = 0; i < nsect; i++)
+ if ((sechdrs[i].sh_flags & SHF_ALLOC) &&
+ (sechdrs[i].sh_type == SHT_NOTE))
+ ++notes;
+
+ if (notes == 0)
+ return;
+
+ notes_attrs = kzalloc(sizeof(*notes_attrs)
+ + notes * sizeof(notes_attrs->attrs[0]),
+ GFP_KERNEL);
+ if (notes_attrs == NULL)
+ return;
+
+ notes_attrs->notes = notes;
+ nattr = &notes_attrs->attrs[0];
+ for (loaded = i = 0; i < nsect; ++i) {
+ if (!(sechdrs[i].sh_flags & SHF_ALLOC))
+ continue;
+ if (sechdrs[i].sh_type == SHT_NOTE) {
+ nattr->attr.name = mod->sect_attrs->attrs[loaded].name;
+ nattr->attr.mode = S_IRUGO;
+ nattr->size = sechdrs[i].sh_size;
+ nattr->private = (void *) sechdrs[i].sh_addr;
+ nattr->read = module_notes_read;
+ ++nattr;
+ }
+ ++loaded;
+ }
+
+ notes_attrs->dir = kobject_add_dir(&mod->mkobj.kobj, "notes");
+ if (!notes_attrs->dir)
+ goto out;
+
+ for (i = 0; i < notes; ++i)
+ if (sysfs_create_bin_file(notes_attrs->dir,
+ &notes_attrs->attrs[i]))
+ goto out;
+
+ mod->notes_attrs = notes_attrs;
+ return;
+
+ out:
+ free_notes_attrs(notes_attrs, i);
+}
+
+static void remove_notes_attrs(struct module *mod)
+{
+ if (mod->notes_attrs)
+ free_notes_attrs(mod->notes_attrs, mod->notes_attrs->notes);
+}
+
#else
static inline void add_sect_attrs(struct module *mod, unsigned int nsect,
@@ -1063,6 +1152,15 @@ static inline void add_sect_attrs(struct module *mod, unsigned int nsect,
static inline void remove_sect_attrs(struct module *mod)
{
}
+
+static inline void add_notes_attrs(struct module *mod, unsigned int nsect,
+ char *sectstrings, Elf_Shdr *sechdrs)
+{
+}
+
+static inline void remove_notes_attrs(struct module *mod)
+{
+}
#endif /* CONFIG_KALLSYMS */
#ifdef CONFIG_SYSFS
@@ -1197,6 +1295,7 @@ static void free_module(struct module *mod)
{
/* Delete from various lists */
stop_machine_run(__unlink_module, mod, NR_CPUS);
+ remove_notes_attrs(mod);
remove_sect_attrs(mod);
mod_kobject_remove(mod);
@@ -1249,14 +1348,14 @@ static int verify_export_symbols(struct module *mod)
const unsigned long *crc;
for (i = 0; i < mod->num_syms; i++)
- if (__find_symbol(mod->syms[i].name, &owner, &crc, 1)) {
+ if (__find_symbol(mod->syms[i].name, &owner, &crc, 1)) {
name = mod->syms[i].name;
ret = -ENOEXEC;
goto dup;
}
for (i = 0; i < mod->num_gpl_syms; i++)
- if (__find_symbol(mod->gpl_syms[i].name, &owner, &crc, 1)) {
+ if (__find_symbol(mod->gpl_syms[i].name, &owner, &crc, 1)) {
name = mod->gpl_syms[i].name;
ret = -ENOEXEC;
goto dup;
@@ -1574,6 +1673,8 @@ static struct module *load_module(void __user *umod,
unsigned int unusedcrcindex;
unsigned int unusedgplindex;
unsigned int unusedgplcrcindex;
+ unsigned int markersindex;
+ unsigned int markersstringsindex;
struct module *mod;
long err = 0;
void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
@@ -1782,7 +1883,8 @@ static struct module *load_module(void __user *umod,
module_unload_init(mod);
/* Initialize kobject, so we can reference it. */
- if (mod_sysfs_init(mod) != 0)
+ err = mod_sysfs_init(mod);
+ if (err)
goto cleanup;
/* Set up license info based on the info section */
@@ -1829,7 +1931,7 @@ static struct module *load_module(void __user *umod,
mod->unused_crcs = (void *)sechdrs[unusedgplcrcindex].sh_addr;
#ifdef CONFIG_MODVERSIONS
- if ((mod->num_syms && !crcindex) ||
+ if ((mod->num_syms && !crcindex) ||
(mod->num_gpl_syms && !gplcrcindex) ||
(mod->num_gpl_future_syms && !gplfuturecrcindex) ||
(mod->num_unused_syms && !unusedcrcindex) ||
@@ -1839,6 +1941,9 @@ static struct module *load_module(void __user *umod,
add_taint_module(mod, TAINT_FORCED_MODULE);
}
#endif
+ markersindex = find_sec(hdr, sechdrs, secstrings, "__markers");
+ markersstringsindex = find_sec(hdr, sechdrs, secstrings,
+ "__markers_strings");
/* Now do relocations. */
for (i = 1; i < hdr->e_shnum; i++) {
@@ -1861,6 +1966,11 @@ static struct module *load_module(void __user *umod,
if (err < 0)
goto cleanup;
}
+#ifdef CONFIG_MARKERS
+ mod->markers = (void *)sechdrs[markersindex].sh_addr;
+ mod->num_markers =
+ sechdrs[markersindex].sh_size / sizeof(*mod->markers);
+#endif
/* Find duplicate symbols */
err = verify_export_symbols(mod);
@@ -1879,6 +1989,11 @@ static struct module *load_module(void __user *umod,
add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);
+#ifdef CONFIG_MARKERS
+ if (!mod->taints)
+ marker_update_probe_range(mod->markers,
+ mod->markers + mod->num_markers, NULL, NULL);
+#endif
err = module_finalize(hdr, sechdrs, mod);
if (err < 0)
goto cleanup;
@@ -1916,7 +2031,7 @@ static struct module *load_module(void __user *umod,
if (err < 0)
goto arch_cleanup;
- err = mod_sysfs_setup(mod,
+ err = mod_sysfs_setup(mod,
(struct kernel_param *)
sechdrs[setupindex].sh_addr,
sechdrs[setupindex].sh_size
@@ -1924,11 +2039,12 @@ static struct module *load_module(void __user *umod,
if (err < 0)
goto arch_cleanup;
add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs);
+ add_notes_attrs(mod, hdr->e_shnum, secstrings, sechdrs);
/* Size of section 0 is 0, so this works well if no unwind info. */
mod->unwind_info = unwind_add_table(mod,
- (void *)sechdrs[unwindex].sh_addr,
- sechdrs[unwindex].sh_size);
+ (void *)sechdrs[unwindex].sh_addr,
+ sechdrs[unwindex].sh_size);
/* Get rid of temporary copy */
vfree(hdr);
@@ -2011,15 +2127,10 @@ sys_init_module(void __user *umod,
buggy refcounters. */
mod->state = MODULE_STATE_GOING;
synchronize_sched();
- if (mod->unsafe)
- printk(KERN_ERR "%s: module is now stuck!\n",
- mod->name);
- else {
- module_put(mod);
- mutex_lock(&module_mutex);
- free_module(mod);
- mutex_unlock(&module_mutex);
- }
+ module_put(mod);
+ mutex_lock(&module_mutex);
+ free_module(mod);
+ mutex_unlock(&module_mutex);
return ret;
}
@@ -2050,7 +2161,7 @@ static inline int within(unsigned long addr, void *start, unsigned long size)
*/
static inline int is_arm_mapping_symbol(const char *str)
{
- return str[0] == '$' && strchr("atd", str[1])
+ return str[0] == '$' && strchr("atd", str[1])
&& (str[2] == '\0' || str[2] == '.');
}
@@ -2065,11 +2176,11 @@ static const char *get_ksymbol(struct module *mod,
/* At worse, next value is at end of module */
if (within(addr, mod->module_init, mod->init_size))
nextval = (unsigned long)mod->module_init+mod->init_text_size;
- else
+ else
nextval = (unsigned long)mod->module_core+mod->core_text_size;
/* Scan for closest preceeding symbol, and next symbol. (ELF
- starts real symbols at 1). */
+ starts real symbols at 1). */
for (i = 1; i < mod->num_symtab; i++) {
if (mod->symtab[i].st_shndx == SHN_UNDEF)
continue;
@@ -2311,7 +2422,7 @@ const struct exception_table_entry *search_module_extables(unsigned long addr)
list_for_each_entry(mod, &modules, list) {
if (mod->num_exentries == 0)
continue;
-
+
e = search_extable(mod->extable,
mod->extable + mod->num_exentries - 1,
addr);
@@ -2321,7 +2432,7 @@ const struct exception_table_entry *search_module_extables(unsigned long addr)
preempt_enable();
/* Now, if we found one, we are running inside it now, hence
- we cannot unload the module, hence no refcnt needed. */
+ we cannot unload the module, hence no refcnt needed. */
return e;
}
@@ -2474,3 +2585,18 @@ EXPORT_SYMBOL(module_remove_driver);
void struct_module(struct module *mod) { return; }
EXPORT_SYMBOL(struct_module);
#endif
+
+#ifdef CONFIG_MARKERS
+void module_update_markers(struct module *probe_module, int *refcount)
+{
+ struct module *mod;
+
+ mutex_lock(&module_mutex);
+ list_for_each_entry(mod, &modules, list)
+ if (!mod->taints)
+ marker_update_probe_range(mod->markers,
+ mod->markers + mod->num_markers,
+ probe_module, refcount);
+ mutex_unlock(&module_mutex);
+}
+#endif
diff --git a/kernel/notifier.c b/kernel/notifier.c
new file mode 100644
index 000000000000..4253f472f060
--- /dev/null
+++ b/kernel/notifier.c
@@ -0,0 +1,539 @@
+#include <linux/kdebug.h>
+#include <linux/kprobes.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/rcupdate.h>
+#include <linux/vmalloc.h>
+
+/*
+ * Notifier list for kernel code which wants to be called
+ * at shutdown. This is used to stop any idling DMA operations
+ * and the like.
+ */
+BLOCKING_NOTIFIER_HEAD(reboot_notifier_list);
+
+/*
+ * Notifier chain core routines. The exported routines below
+ * are layered on top of these, with appropriate locking added.
+ */
+
+static int notifier_chain_register(struct notifier_block **nl,
+ struct notifier_block *n)
+{
+ while ((*nl) != NULL) {
+ if (n->priority > (*nl)->priority)
+ break;
+ nl = &((*nl)->next);
+ }
+ n->next = *nl;
+ rcu_assign_pointer(*nl, n);
+ return 0;
+}
+
+static int notifier_chain_unregister(struct notifier_block **nl,
+ struct notifier_block *n)
+{
+ while ((*nl) != NULL) {
+ if ((*nl) == n) {
+ rcu_assign_pointer(*nl, n->next);
+ return 0;
+ }
+ nl = &((*nl)->next);
+ }
+ return -ENOENT;
+}
+
+/**
+ * notifier_call_chain - Informs the registered notifiers about an event.
+ * @nl: Pointer to head of the blocking notifier chain
+ * @val: Value passed unmodified to notifier function
+ * @v: Pointer passed unmodified to notifier function
+ * @nr_to_call: Number of notifier functions to be called. Don't care
+ * value of this parameter is -1.
+ * @nr_calls: Records the number of notifications sent. Don't care
+ * value of this field is NULL.
+ * @returns: notifier_call_chain returns the value returned by the
+ * last notifier function called.
+ */
+static int __kprobes notifier_call_chain(struct notifier_block **nl,
+ unsigned long val, void *v,
+ int nr_to_call, int *nr_calls)
+{
+ int ret = NOTIFY_DONE;
+ struct notifier_block *nb, *next_nb;
+
+ nb = rcu_dereference(*nl);
+
+ while (nb && nr_to_call) {
+ next_nb = rcu_dereference(nb->next);
+ ret = nb->notifier_call(nb, val, v);
+
+ if (nr_calls)
+ (*nr_calls)++;
+
+ if ((ret & NOTIFY_STOP_MASK) == NOTIFY_STOP_MASK)
+ break;
+ nb = next_nb;
+ nr_to_call--;
+ }
+ return ret;
+}
+
+/*
+ * Atomic notifier chain routines. Registration and unregistration
+ * use a spinlock, and call_chain is synchronized by RCU (no locks).
+ */
+
+/**
+ * atomic_notifier_chain_register - Add notifier to an atomic notifier chain
+ * @nh: Pointer to head of the atomic notifier chain
+ * @n: New entry in notifier chain
+ *
+ * Adds a notifier to an atomic notifier chain.
+ *
+ * Currently always returns zero.
+ */
+int atomic_notifier_chain_register(struct atomic_notifier_head *nh,
+ struct notifier_block *n)
+{
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&nh->lock, flags);
+ ret = notifier_chain_register(&nh->head, n);
+ spin_unlock_irqrestore(&nh->lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(atomic_notifier_chain_register);
+
+/**
+ * atomic_notifier_chain_unregister - Remove notifier from an atomic notifier chain
+ * @nh: Pointer to head of the atomic notifier chain
+ * @n: Entry to remove from notifier chain
+ *
+ * Removes a notifier from an atomic notifier chain.
+ *
+ * Returns zero on success or %-ENOENT on failure.
+ */
+int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
+ struct notifier_block *n)
+{
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&nh->lock, flags);
+ ret = notifier_chain_unregister(&nh->head, n);
+ spin_unlock_irqrestore(&nh->lock, flags);
+ synchronize_rcu();
+ return ret;
+}
+EXPORT_SYMBOL_GPL(atomic_notifier_chain_unregister);
+
+/**
+ * __atomic_notifier_call_chain - Call functions in an atomic notifier chain
+ * @nh: Pointer to head of the atomic notifier chain
+ * @val: Value passed unmodified to notifier function
+ * @v: Pointer passed unmodified to notifier function
+ * @nr_to_call: See the comment for notifier_call_chain.
+ * @nr_calls: See the comment for notifier_call_chain.
+ *
+ * Calls each function in a notifier chain in turn. The functions
+ * run in an atomic context, so they must not block.
+ * This routine uses RCU to synchronize with changes to the chain.
+ *
+ * If the return value of the notifier can be and'ed
+ * with %NOTIFY_STOP_MASK then atomic_notifier_call_chain()
+ * will return immediately, with the return value of
+ * the notifier function which halted execution.
+ * Otherwise the return value is the return value
+ * of the last notifier function called.
+ */
+int __kprobes __atomic_notifier_call_chain(struct atomic_notifier_head *nh,
+ unsigned long val, void *v,
+ int nr_to_call, int *nr_calls)
+{
+ int ret;
+
+ rcu_read_lock();
+ ret = notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls);
+ rcu_read_unlock();
+ return ret;
+}
+EXPORT_SYMBOL_GPL(__atomic_notifier_call_chain);
+
+int __kprobes atomic_notifier_call_chain(struct atomic_notifier_head *nh,
+ unsigned long val, void *v)
+{
+ return __atomic_notifier_call_chain(nh, val, v, -1, NULL);
+}
+EXPORT_SYMBOL_GPL(atomic_notifier_call_chain);
+
+/*
+ * Blocking notifier chain routines. All access to the chain is
+ * synchronized by an rwsem.
+ */
+
+/**
+ * blocking_notifier_chain_register - Add notifier to a blocking notifier chain
+ * @nh: Pointer to head of the blocking notifier chain
+ * @n: New entry in notifier chain
+ *
+ * Adds a notifier to a blocking notifier chain.
+ * Must be called in process context.
+ *
+ * Currently always returns zero.
+ */
+int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
+ struct notifier_block *n)
+{
+ int ret;
+
+ /*
+ * This code gets used during boot-up, when task switching is
+ * not yet working and interrupts must remain disabled. At
+ * such times we must not call down_write().
+ */
+ if (unlikely(system_state == SYSTEM_BOOTING))
+ return notifier_chain_register(&nh->head, n);
+
+ down_write(&nh->rwsem);
+ ret = notifier_chain_register(&nh->head, n);
+ up_write(&nh->rwsem);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(blocking_notifier_chain_register);
+
+/**
+ * blocking_notifier_chain_unregister - Remove notifier from a blocking notifier chain
+ * @nh: Pointer to head of the blocking notifier chain
+ * @n: Entry to remove from notifier chain
+ *
+ * Removes a notifier from a blocking notifier chain.
+ * Must be called from process context.
+ *
+ * Returns zero on success or %-ENOENT on failure.
+ */
+int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
+ struct notifier_block *n)
+{
+ int ret;
+
+ /*
+ * This code gets used during boot-up, when task switching is
+ * not yet working and interrupts must remain disabled. At
+ * such times we must not call down_write().
+ */
+ if (unlikely(system_state == SYSTEM_BOOTING))
+ return notifier_chain_unregister(&nh->head, n);
+
+ down_write(&nh->rwsem);
+ ret = notifier_chain_unregister(&nh->head, n);
+ up_write(&nh->rwsem);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(blocking_notifier_chain_unregister);
+
+/**
+ * __blocking_notifier_call_chain - Call functions in a blocking notifier chain
+ * @nh: Pointer to head of the blocking notifier chain
+ * @val: Value passed unmodified to notifier function
+ * @v: Pointer passed unmodified to notifier function
+ * @nr_to_call: See comment for notifier_call_chain.
+ * @nr_calls: See comment for notifier_call_chain.
+ *
+ * Calls each function in a notifier chain in turn. The functions
+ * run in a process context, so they are allowed to block.
+ *
+ * If the return value of the notifier can be and'ed
+ * with %NOTIFY_STOP_MASK then blocking_notifier_call_chain()
+ * will return immediately, with the return value of
+ * the notifier function which halted execution.
+ * Otherwise the return value is the return value
+ * of the last notifier function called.
+ */
+int __blocking_notifier_call_chain(struct blocking_notifier_head *nh,
+ unsigned long val, void *v,
+ int nr_to_call, int *nr_calls)
+{
+ int ret = NOTIFY_DONE;
+
+ /*
+ * We check the head outside the lock, but if this access is
+ * racy then it does not matter what the result of the test
+ * is, we re-check the list after having taken the lock anyway:
+ */
+ if (rcu_dereference(nh->head)) {
+ down_read(&nh->rwsem);
+ ret = notifier_call_chain(&nh->head, val, v, nr_to_call,
+ nr_calls);
+ up_read(&nh->rwsem);
+ }
+ return ret;
+}
+EXPORT_SYMBOL_GPL(__blocking_notifier_call_chain);
+
+int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
+ unsigned long val, void *v)
+{
+ return __blocking_notifier_call_chain(nh, val, v, -1, NULL);
+}
+EXPORT_SYMBOL_GPL(blocking_notifier_call_chain);
+
+/*
+ * Raw notifier chain routines. There is no protection;
+ * the caller must provide it. Use at your own risk!
+ */
+
+/**
+ * raw_notifier_chain_register - Add notifier to a raw notifier chain
+ * @nh: Pointer to head of the raw notifier chain
+ * @n: New entry in notifier chain
+ *
+ * Adds a notifier to a raw notifier chain.
+ * All locking must be provided by the caller.
+ *
+ * Currently always returns zero.
+ */
+int raw_notifier_chain_register(struct raw_notifier_head *nh,
+ struct notifier_block *n)
+{
+ return notifier_chain_register(&nh->head, n);
+}
+EXPORT_SYMBOL_GPL(raw_notifier_chain_register);
+
+/**
+ * raw_notifier_chain_unregister - Remove notifier from a raw notifier chain
+ * @nh: Pointer to head of the raw notifier chain
+ * @n: Entry to remove from notifier chain
+ *
+ * Removes a notifier from a raw notifier chain.
+ * All locking must be provided by the caller.
+ *
+ * Returns zero on success or %-ENOENT on failure.
+ */
+int raw_notifier_chain_unregister(struct raw_notifier_head *nh,
+ struct notifier_block *n)
+{
+ return notifier_chain_unregister(&nh->head, n);
+}
+EXPORT_SYMBOL_GPL(raw_notifier_chain_unregister);
+
+/**
+ * __raw_notifier_call_chain - Call functions in a raw notifier chain
+ * @nh: Pointer to head of the raw notifier chain
+ * @val: Value passed unmodified to notifier function
+ * @v: Pointer passed unmodified to notifier function
+ * @nr_to_call: See comment for notifier_call_chain.
+ * @nr_calls: See comment for notifier_call_chain
+ *
+ * Calls each function in a notifier chain in turn. The functions
+ * run in an undefined context.
+ * All locking must be provided by the caller.
+ *
+ * If the return value of the notifier can be and'ed
+ * with %NOTIFY_STOP_MASK then raw_notifier_call_chain()
+ * will return immediately, with the return value of
+ * the notifier function which halted execution.
+ * Otherwise the return value is the return value
+ * of the last notifier function called.
+ */
+int __raw_notifier_call_chain(struct raw_notifier_head *nh,
+ unsigned long val, void *v,
+ int nr_to_call, int *nr_calls)
+{
+ return notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls);
+}
+EXPORT_SYMBOL_GPL(__raw_notifier_call_chain);
+
+int raw_notifier_call_chain(struct raw_notifier_head *nh,
+ unsigned long val, void *v)
+{
+ return __raw_notifier_call_chain(nh, val, v, -1, NULL);
+}
+EXPORT_SYMBOL_GPL(raw_notifier_call_chain);
+
+/*
+ * SRCU notifier chain routines. Registration and unregistration
+ * use a mutex, and call_chain is synchronized by SRCU (no locks).
+ */
+
+/**
+ * srcu_notifier_chain_register - Add notifier to an SRCU notifier chain
+ * @nh: Pointer to head of the SRCU notifier chain
+ * @n: New entry in notifier chain
+ *
+ * Adds a notifier to an SRCU notifier chain.
+ * Must be called in process context.
+ *
+ * Currently always returns zero.
+ */
+int srcu_notifier_chain_register(struct srcu_notifier_head *nh,
+ struct notifier_block *n)
+{
+ int ret;
+
+ /*
+ * This code gets used during boot-up, when task switching is
+ * not yet working and interrupts must remain disabled. At
+ * such times we must not call mutex_lock().
+ */
+ if (unlikely(system_state == SYSTEM_BOOTING))
+ return notifier_chain_register(&nh->head, n);
+
+ mutex_lock(&nh->mutex);
+ ret = notifier_chain_register(&nh->head, n);
+ mutex_unlock(&nh->mutex);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(srcu_notifier_chain_register);
+
+/**
+ * srcu_notifier_chain_unregister - Remove notifier from an SRCU notifier chain
+ * @nh: Pointer to head of the SRCU notifier chain
+ * @n: Entry to remove from notifier chain
+ *
+ * Removes a notifier from an SRCU notifier chain.
+ * Must be called from process context.
+ *
+ * Returns zero on success or %-ENOENT on failure.
+ */
+int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh,
+ struct notifier_block *n)
+{
+ int ret;
+
+ /*
+ * This code gets used during boot-up, when task switching is
+ * not yet working and interrupts must remain disabled. At
+ * such times we must not call mutex_lock().
+ */
+ if (unlikely(system_state == SYSTEM_BOOTING))
+ return notifier_chain_unregister(&nh->head, n);
+
+ mutex_lock(&nh->mutex);
+ ret = notifier_chain_unregister(&nh->head, n);
+ mutex_unlock(&nh->mutex);
+ synchronize_srcu(&nh->srcu);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(srcu_notifier_chain_unregister);
+
+/**
+ * __srcu_notifier_call_chain - Call functions in an SRCU notifier chain
+ * @nh: Pointer to head of the SRCU notifier chain
+ * @val: Value passed unmodified to notifier function
+ * @v: Pointer passed unmodified to notifier function
+ * @nr_to_call: See comment for notifier_call_chain.
+ * @nr_calls: See comment for notifier_call_chain
+ *
+ * Calls each function in a notifier chain in turn. The functions
+ * run in a process context, so they are allowed to block.
+ *
+ * If the return value of the notifier can be and'ed
+ * with %NOTIFY_STOP_MASK then srcu_notifier_call_chain()
+ * will return immediately, with the return value of
+ * the notifier function which halted execution.
+ * Otherwise the return value is the return value
+ * of the last notifier function called.
+ */
+int __srcu_notifier_call_chain(struct srcu_notifier_head *nh,
+ unsigned long val, void *v,
+ int nr_to_call, int *nr_calls)
+{
+ int ret;
+ int idx;
+
+ idx = srcu_read_lock(&nh->srcu);
+ ret = notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls);
+ srcu_read_unlock(&nh->srcu, idx);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(__srcu_notifier_call_chain);
+
+int srcu_notifier_call_chain(struct srcu_notifier_head *nh,
+ unsigned long val, void *v)
+{
+ return __srcu_notifier_call_chain(nh, val, v, -1, NULL);
+}
+EXPORT_SYMBOL_GPL(srcu_notifier_call_chain);
+
+/**
+ * srcu_init_notifier_head - Initialize an SRCU notifier head
+ * @nh: Pointer to head of the srcu notifier chain
+ *
+ * Unlike other sorts of notifier heads, SRCU notifier heads require
+ * dynamic initialization. Be sure to call this routine before
+ * calling any of the other SRCU notifier routines for this head.
+ *
+ * If an SRCU notifier head is deallocated, it must first be cleaned
+ * up by calling srcu_cleanup_notifier_head(). Otherwise the head's
+ * per-cpu data (used by the SRCU mechanism) will leak.
+ */
+void srcu_init_notifier_head(struct srcu_notifier_head *nh)
+{
+ mutex_init(&nh->mutex);
+ if (init_srcu_struct(&nh->srcu) < 0)
+ BUG();
+ nh->head = NULL;
+}
+EXPORT_SYMBOL_GPL(srcu_init_notifier_head);
+
+/**
+ * register_reboot_notifier - Register function to be called at reboot time
+ * @nb: Info about notifier function to be called
+ *
+ * Registers a function with the list of functions
+ * to be called at reboot time.
+ *
+ * Currently always returns zero, as blocking_notifier_chain_register()
+ * always returns zero.
+ */
+int register_reboot_notifier(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_register(&reboot_notifier_list, nb);
+}
+EXPORT_SYMBOL(register_reboot_notifier);
+
+/**
+ * unregister_reboot_notifier - Unregister previously registered reboot notifier
+ * @nb: Hook to be unregistered
+ *
+ * Unregisters a previously registered reboot
+ * notifier function.
+ *
+ * Returns zero on success, or %-ENOENT on failure.
+ */
+int unregister_reboot_notifier(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_unregister(&reboot_notifier_list, nb);
+}
+EXPORT_SYMBOL(unregister_reboot_notifier);
+
+static ATOMIC_NOTIFIER_HEAD(die_chain);
+
+int notify_die(enum die_val val, const char *str,
+ struct pt_regs *regs, long err, int trap, int sig)
+{
+ struct die_args args = {
+ .regs = regs,
+ .str = str,
+ .err = err,
+ .trapnr = trap,
+ .signr = sig,
+
+ };
+ return atomic_notifier_call_chain(&die_chain, val, &args);
+}
+
+int register_die_notifier(struct notifier_block *nb)
+{
+ vmalloc_sync_all();
+ return atomic_notifier_chain_register(&die_chain, nb);
+}
+EXPORT_SYMBOL_GPL(register_die_notifier);
+
+int unregister_die_notifier(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_unregister(&die_chain, nb);
+}
+EXPORT_SYMBOL_GPL(unregister_die_notifier);
diff --git a/kernel/ns_cgroup.c b/kernel/ns_cgroup.c
new file mode 100644
index 000000000000..aead4d69f62b
--- /dev/null
+++ b/kernel/ns_cgroup.c
@@ -0,0 +1,100 @@
+/*
+ * ns_cgroup.c - namespace cgroup subsystem
+ *
+ * Copyright 2006, 2007 IBM Corp
+ */
+
+#include <linux/module.h>
+#include <linux/cgroup.h>
+#include <linux/fs.h>
+
+struct ns_cgroup {
+ struct cgroup_subsys_state css;
+ spinlock_t lock;
+};
+
+struct cgroup_subsys ns_subsys;
+
+static inline struct ns_cgroup *cgroup_to_ns(
+ struct cgroup *cgroup)
+{
+ return container_of(cgroup_subsys_state(cgroup, ns_subsys_id),
+ struct ns_cgroup, css);
+}
+
+int ns_cgroup_clone(struct task_struct *task)
+{
+ return cgroup_clone(task, &ns_subsys);
+}
+
+/*
+ * Rules:
+ * 1. you can only enter a cgroup which is a child of your current
+ * cgroup
+ * 2. you can only place another process into a cgroup if
+ * a. you have CAP_SYS_ADMIN
+ * b. your cgroup is an ancestor of task's destination cgroup
+ * (hence either you are in the same cgroup as task, or in an
+ * ancestor cgroup thereof)
+ */
+static int ns_can_attach(struct cgroup_subsys *ss,
+ struct cgroup *new_cgroup, struct task_struct *task)
+{
+ struct cgroup *orig;
+
+ if (current != task) {
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ if (!cgroup_is_descendant(new_cgroup))
+ return -EPERM;
+ }
+
+ if (atomic_read(&new_cgroup->count) != 0)
+ return -EPERM;
+
+ orig = task_cgroup(task, ns_subsys_id);
+ if (orig && orig != new_cgroup->parent)
+ return -EPERM;
+
+ return 0;
+}
+
+/*
+ * Rules: you can only create a cgroup if
+ * 1. you are capable(CAP_SYS_ADMIN)
+ * 2. the target cgroup is a descendant of your own cgroup
+ */
+static struct cgroup_subsys_state *ns_create(struct cgroup_subsys *ss,
+ struct cgroup *cgroup)
+{
+ struct ns_cgroup *ns_cgroup;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return ERR_PTR(-EPERM);
+ if (!cgroup_is_descendant(cgroup))
+ return ERR_PTR(-EPERM);
+
+ ns_cgroup = kzalloc(sizeof(*ns_cgroup), GFP_KERNEL);
+ if (!ns_cgroup)
+ return ERR_PTR(-ENOMEM);
+ spin_lock_init(&ns_cgroup->lock);
+ return &ns_cgroup->css;
+}
+
+static void ns_destroy(struct cgroup_subsys *ss,
+ struct cgroup *cgroup)
+{
+ struct ns_cgroup *ns_cgroup;
+
+ ns_cgroup = cgroup_to_ns(cgroup);
+ kfree(ns_cgroup);
+}
+
+struct cgroup_subsys ns_subsys = {
+ .name = "ns",
+ .can_attach = ns_can_attach,
+ .create = ns_create,
+ .destroy = ns_destroy,
+ .subsys_id = ns_subsys_id,
+};
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index f1decd21a534..79f871bc0ef4 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -26,19 +26,6 @@ static struct kmem_cache *nsproxy_cachep;
struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
-static inline void get_nsproxy(struct nsproxy *ns)
-{
- atomic_inc(&ns->count);
-}
-
-void get_task_namespaces(struct task_struct *tsk)
-{
- struct nsproxy *ns = tsk->nsproxy;
- if (ns) {
- get_nsproxy(ns);
- }
-}
-
/*
* creates a copy of "orig" with refcount 1.
*/
@@ -87,7 +74,7 @@ static struct nsproxy *create_new_namespaces(unsigned long flags,
goto out_ipc;
}
- new_nsp->pid_ns = copy_pid_ns(flags, tsk->nsproxy->pid_ns);
+ new_nsp->pid_ns = copy_pid_ns(flags, task_active_pid_ns(tsk));
if (IS_ERR(new_nsp->pid_ns)) {
err = PTR_ERR(new_nsp->pid_ns);
goto out_pid;
@@ -142,7 +129,8 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk)
get_nsproxy(old_ns);
- if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWUSER | CLONE_NEWNET)))
+ if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
+ CLONE_NEWUSER | CLONE_NEWPID | CLONE_NEWNET)))
return 0;
if (!capable(CAP_SYS_ADMIN)) {
@@ -156,7 +144,14 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk)
goto out;
}
+ err = ns_cgroup_clone(tsk);
+ if (err) {
+ put_nsproxy(new_ns);
+ goto out;
+ }
+
tsk->nsproxy = new_ns;
+
out:
put_nsproxy(old_ns);
return err;
@@ -196,15 +191,49 @@ int unshare_nsproxy_namespaces(unsigned long unshare_flags,
*new_nsp = create_new_namespaces(unshare_flags, current,
new_fs ? new_fs : current->fs);
- if (IS_ERR(*new_nsp))
+ if (IS_ERR(*new_nsp)) {
err = PTR_ERR(*new_nsp);
+ goto out;
+ }
+
+ err = ns_cgroup_clone(current);
+ if (err)
+ put_nsproxy(*new_nsp);
+
+out:
return err;
}
+void switch_task_namespaces(struct task_struct *p, struct nsproxy *new)
+{
+ struct nsproxy *ns;
+
+ might_sleep();
+
+ ns = p->nsproxy;
+
+ rcu_assign_pointer(p->nsproxy, new);
+
+ if (ns && atomic_dec_and_test(&ns->count)) {
+ /*
+ * wait for others to get what they want from this nsproxy.
+ *
+ * cannot release this nsproxy via the call_rcu() since
+ * put_mnt_ns() will want to sleep
+ */
+ synchronize_rcu();
+ free_nsproxy(ns);
+ }
+}
+
+void exit_task_namespaces(struct task_struct *p)
+{
+ switch_task_namespaces(p, NULL);
+}
+
static int __init nsproxy_cache_init(void)
{
- nsproxy_cachep = kmem_cache_create("nsproxy", sizeof(struct nsproxy),
- 0, SLAB_PANIC, NULL);
+ nsproxy_cachep = KMEM_CACHE(nsproxy, SLAB_PANIC);
return 0;
}
diff --git a/kernel/panic.c b/kernel/panic.c
index f64f4c1ac11f..6f6e03e91595 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -56,14 +56,14 @@ EXPORT_SYMBOL(panic_blink);
*
* This function never returns.
*/
-
+
NORET_TYPE void panic(const char * fmt, ...)
{
long i;
static char buf[1024];
va_list args;
#if defined(CONFIG_S390)
- unsigned long caller = (unsigned long) __builtin_return_address(0);
+ unsigned long caller = (unsigned long) __builtin_return_address(0);
#endif
/*
@@ -128,7 +128,7 @@ NORET_TYPE void panic(const char * fmt, ...)
}
#endif
#if defined(CONFIG_S390)
- disabled_wait(caller);
+ disabled_wait(caller);
#endif
local_irq_enable();
for (i = 0;;) {
@@ -148,13 +148,13 @@ EXPORT_SYMBOL(panic);
* 'F' - Module has been forcibly loaded.
* 'S' - SMP with CPUs not designed for SMP.
* 'R' - User forced a module unload.
- * 'M' - Machine had a machine check experience.
+ * 'M' - System experienced a machine check exception.
* 'B' - System has hit bad_page.
* 'U' - Userspace-defined naughtiness.
*
* The string is overwritten by the next call to print_taint().
*/
-
+
const char *print_tainted(void)
{
static char buf[20];
@@ -164,7 +164,7 @@ const char *print_tainted(void)
tainted & TAINT_FORCED_MODULE ? 'F' : ' ',
tainted & TAINT_UNSAFE_SMP ? 'S' : ' ',
tainted & TAINT_FORCED_RMMOD ? 'R' : ' ',
- tainted & TAINT_MACHINE_CHECK ? 'M' : ' ',
+ tainted & TAINT_MACHINE_CHECK ? 'M' : ' ',
tainted & TAINT_BAD_PAGE ? 'B' : ' ',
tainted & TAINT_USER ? 'U' : ' ',
tainted & TAINT_DIE ? 'D' : ' ');
diff --git a/kernel/params.c b/kernel/params.c
index 4e57732fcfb4..2a4c51487e72 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -252,8 +252,9 @@ int param_get_bool(char *buffer, struct kernel_param *kp)
int param_set_invbool(const char *val, struct kernel_param *kp)
{
int boolval, ret;
- struct kernel_param dummy = { .arg = &boolval };
+ struct kernel_param dummy;
+ dummy.arg = &boolval;
ret = param_set_bool(val, &dummy);
if (ret == 0)
*(int *)kp->arg = !boolval;
@@ -262,11 +263,7 @@ int param_set_invbool(const char *val, struct kernel_param *kp)
int param_get_invbool(char *buffer, struct kernel_param *kp)
{
- int val;
- struct kernel_param dummy = { .arg = &val };
-
- val = !*(int *)kp->arg;
- return param_get_bool(buffer, &dummy);
+ return sprintf(buffer, "%c", (*(int *)kp->arg) ? 'N' : 'Y');
}
/* We break the rule and mangle the string. */
@@ -325,7 +322,7 @@ static int param_array(const char *name,
int param_array_set(const char *val, struct kernel_param *kp)
{
- struct kparam_array *arr = kp->arg;
+ const struct kparam_array *arr = kp->arr;
unsigned int temp_num;
return param_array(kp->name, val, 1, arr->max, arr->elem,
@@ -335,7 +332,7 @@ int param_array_set(const char *val, struct kernel_param *kp)
int param_array_get(char *buffer, struct kernel_param *kp)
{
int i, off, ret;
- struct kparam_array *arr = kp->arg;
+ const struct kparam_array *arr = kp->arr;
struct kernel_param p;
p = *kp;
@@ -354,7 +351,7 @@ int param_array_get(char *buffer, struct kernel_param *kp)
int param_set_copystring(const char *val, struct kernel_param *kp)
{
- struct kparam_string *kps = kp->arg;
+ const struct kparam_string *kps = kp->str;
if (!val) {
printk(KERN_ERR "%s: missing param set value\n", kp->name);
@@ -371,7 +368,7 @@ int param_set_copystring(const char *val, struct kernel_param *kp)
int param_get_string(char *buffer, struct kernel_param *kp)
{
- struct kparam_string *kps = kp->arg;
+ const struct kparam_string *kps = kp->str;
return strlcpy(buffer, kps->string, kps->maxlen);
}
@@ -595,13 +592,16 @@ static void __init param_sysfs_builtin(void)
for (i=0; i < __stop___param - __start___param; i++) {
char *dot;
+ size_t max_name_len;
kp = &__start___param[i];
+ max_name_len =
+ min_t(size_t, MAX_KBUILD_MODNAME, strlen(kp->name));
- /* We do not handle args without periods. */
- dot = memchr(kp->name, '.', MAX_KBUILD_MODNAME);
+ dot = memchr(kp->name, '.', max_name_len);
if (!dot) {
- DEBUGP("couldn't find period in %s\n", kp->name);
+ DEBUGP("couldn't find period in first %d characters "
+ "of %s\n", MAX_KBUILD_MODNAME, kp->name);
continue;
}
name_len = dot - kp->name;
diff --git a/kernel/pid.c b/kernel/pid.c
index c6e3f9ffff87..f815455431bf 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -18,6 +18,12 @@
* allocation scenario when all but one out of 1 million PIDs possible are
* allocated already: the scanning of 32 list entries and at most PAGE_SIZE
* bytes. The typical fastpath is a single successful setbit. Freeing is O(1).
+ *
+ * Pid namespaces:
+ * (C) 2007 Pavel Emelyanov <xemul@openvz.org>, OpenVZ, SWsoft Inc.
+ * (C) 2007 Sukadev Bhattiprolu <sukadev@us.ibm.com>, IBM
+ * Many thanks to Oleg Nesterov for comments and help
+ *
*/
#include <linux/mm.h>
@@ -28,12 +34,14 @@
#include <linux/hash.h>
#include <linux/pid_namespace.h>
#include <linux/init_task.h>
+#include <linux/syscalls.h>
-#define pid_hashfn(nr) hash_long((unsigned long)nr, pidhash_shift)
+#define pid_hashfn(nr, ns) \
+ hash_long((unsigned long)nr + (unsigned long)ns, pidhash_shift)
static struct hlist_head *pid_hash;
static int pidhash_shift;
-static struct kmem_cache *pid_cachep;
struct pid init_struct_pid = INIT_STRUCT_PID;
+static struct kmem_cache *pid_ns_cachep;
int pid_max = PID_MAX_DEFAULT;
@@ -68,8 +76,25 @@ struct pid_namespace init_pid_ns = {
[ 0 ... PIDMAP_ENTRIES-1] = { ATOMIC_INIT(BITS_PER_PAGE), NULL }
},
.last_pid = 0,
- .child_reaper = &init_task
+ .level = 0,
+ .child_reaper = &init_task,
};
+EXPORT_SYMBOL_GPL(init_pid_ns);
+
+int is_container_init(struct task_struct *tsk)
+{
+ int ret = 0;
+ struct pid *pid;
+
+ rcu_read_lock();
+ pid = task_pid(tsk);
+ if (pid != NULL && pid->numbers[pid->level].nr == 1)
+ ret = 1;
+ rcu_read_unlock();
+
+ return ret;
+}
+EXPORT_SYMBOL(is_container_init);
/*
* Note: disable interrupts while the pidmap_lock is held as an
@@ -176,11 +201,17 @@ static int next_pidmap(struct pid_namespace *pid_ns, int last)
fastcall void put_pid(struct pid *pid)
{
+ struct pid_namespace *ns;
+
if (!pid)
return;
+
+ ns = pid->numbers[pid->level].ns;
if ((atomic_read(&pid->count) == 1) ||
- atomic_dec_and_test(&pid->count))
- kmem_cache_free(pid_cachep, pid);
+ atomic_dec_and_test(&pid->count)) {
+ kmem_cache_free(ns->pid_cachep, pid);
+ put_pid_ns(ns);
+ }
}
EXPORT_SYMBOL_GPL(put_pid);
@@ -193,60 +224,94 @@ static void delayed_put_pid(struct rcu_head *rhp)
fastcall void free_pid(struct pid *pid)
{
/* We can be called with write_lock_irq(&tasklist_lock) held */
+ int i;
unsigned long flags;
spin_lock_irqsave(&pidmap_lock, flags);
- hlist_del_rcu(&pid->pid_chain);
+ for (i = 0; i <= pid->level; i++)
+ hlist_del_rcu(&pid->numbers[i].pid_chain);
spin_unlock_irqrestore(&pidmap_lock, flags);
- free_pidmap(&init_pid_ns, pid->nr);
+ for (i = 0; i <= pid->level; i++)
+ free_pidmap(pid->numbers[i].ns, pid->numbers[i].nr);
+
call_rcu(&pid->rcu, delayed_put_pid);
}
-struct pid *alloc_pid(void)
+struct pid *alloc_pid(struct pid_namespace *ns)
{
struct pid *pid;
enum pid_type type;
- int nr = -1;
+ int i, nr;
+ struct pid_namespace *tmp;
+ struct upid *upid;
- pid = kmem_cache_alloc(pid_cachep, GFP_KERNEL);
+ pid = kmem_cache_alloc(ns->pid_cachep, GFP_KERNEL);
if (!pid)
goto out;
- nr = alloc_pidmap(current->nsproxy->pid_ns);
- if (nr < 0)
- goto out_free;
+ tmp = ns;
+ for (i = ns->level; i >= 0; i--) {
+ nr = alloc_pidmap(tmp);
+ if (nr < 0)
+ goto out_free;
+
+ pid->numbers[i].nr = nr;
+ pid->numbers[i].ns = tmp;
+ tmp = tmp->parent;
+ }
+ get_pid_ns(ns);
+ pid->level = ns->level;
atomic_set(&pid->count, 1);
- pid->nr = nr;
for (type = 0; type < PIDTYPE_MAX; ++type)
INIT_HLIST_HEAD(&pid->tasks[type]);
spin_lock_irq(&pidmap_lock);
- hlist_add_head_rcu(&pid->pid_chain, &pid_hash[pid_hashfn(pid->nr)]);
+ for (i = ns->level; i >= 0; i--) {
+ upid = &pid->numbers[i];
+ hlist_add_head_rcu(&upid->pid_chain,
+ &pid_hash[pid_hashfn(upid->nr, upid->ns)]);
+ }
spin_unlock_irq(&pidmap_lock);
out:
return pid;
out_free:
- kmem_cache_free(pid_cachep, pid);
+ for (i++; i <= ns->level; i++)
+ free_pidmap(pid->numbers[i].ns, pid->numbers[i].nr);
+
+ kmem_cache_free(ns->pid_cachep, pid);
pid = NULL;
goto out;
}
-struct pid * fastcall find_pid(int nr)
+struct pid * fastcall find_pid_ns(int nr, struct pid_namespace *ns)
{
struct hlist_node *elem;
- struct pid *pid;
+ struct upid *pnr;
+
+ hlist_for_each_entry_rcu(pnr, elem,
+ &pid_hash[pid_hashfn(nr, ns)], pid_chain)
+ if (pnr->nr == nr && pnr->ns == ns)
+ return container_of(pnr, struct pid,
+ numbers[ns->level]);
- hlist_for_each_entry_rcu(pid, elem,
- &pid_hash[pid_hashfn(nr)], pid_chain) {
- if (pid->nr == nr)
- return pid;
- }
return NULL;
}
+EXPORT_SYMBOL_GPL(find_pid_ns);
+
+struct pid *find_vpid(int nr)
+{
+ return find_pid_ns(nr, current->nsproxy->pid_ns);
+}
+EXPORT_SYMBOL_GPL(find_vpid);
+
+struct pid *find_pid(int nr)
+{
+ return find_pid_ns(nr, &init_pid_ns);
+}
EXPORT_SYMBOL_GPL(find_pid);
/*
@@ -307,12 +372,32 @@ struct task_struct * fastcall pid_task(struct pid *pid, enum pid_type type)
/*
* Must be called under rcu_read_lock() or with tasklist_lock read-held.
*/
-struct task_struct *find_task_by_pid_type(int type, int nr)
+struct task_struct *find_task_by_pid_type_ns(int type, int nr,
+ struct pid_namespace *ns)
{
- return pid_task(find_pid(nr), type);
+ return pid_task(find_pid_ns(nr, ns), type);
}
-EXPORT_SYMBOL(find_task_by_pid_type);
+EXPORT_SYMBOL(find_task_by_pid_type_ns);
+
+struct task_struct *find_task_by_pid(pid_t nr)
+{
+ return find_task_by_pid_type_ns(PIDTYPE_PID, nr, &init_pid_ns);
+}
+EXPORT_SYMBOL(find_task_by_pid);
+
+struct task_struct *find_task_by_vpid(pid_t vnr)
+{
+ return find_task_by_pid_type_ns(PIDTYPE_PID, vnr,
+ current->nsproxy->pid_ns);
+}
+EXPORT_SYMBOL(find_task_by_vpid);
+
+struct task_struct *find_task_by_pid_ns(pid_t nr, struct pid_namespace *ns)
+{
+ return find_task_by_pid_type_ns(PIDTYPE_PID, nr, ns);
+}
+EXPORT_SYMBOL(find_task_by_pid_ns);
struct pid *get_task_pid(struct task_struct *task, enum pid_type type)
{
@@ -339,45 +424,241 @@ struct pid *find_get_pid(pid_t nr)
struct pid *pid;
rcu_read_lock();
- pid = get_pid(find_pid(nr));
+ pid = get_pid(find_vpid(nr));
rcu_read_unlock();
return pid;
}
+pid_t pid_nr_ns(struct pid *pid, struct pid_namespace *ns)
+{
+ struct upid *upid;
+ pid_t nr = 0;
+
+ if (pid && ns->level <= pid->level) {
+ upid = &pid->numbers[ns->level];
+ if (upid->ns == ns)
+ nr = upid->nr;
+ }
+ return nr;
+}
+
+pid_t task_pid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns)
+{
+ return pid_nr_ns(task_pid(tsk), ns);
+}
+EXPORT_SYMBOL(task_pid_nr_ns);
+
+pid_t task_tgid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns)
+{
+ return pid_nr_ns(task_tgid(tsk), ns);
+}
+EXPORT_SYMBOL(task_tgid_nr_ns);
+
+pid_t task_pgrp_nr_ns(struct task_struct *tsk, struct pid_namespace *ns)
+{
+ return pid_nr_ns(task_pgrp(tsk), ns);
+}
+EXPORT_SYMBOL(task_pgrp_nr_ns);
+
+pid_t task_session_nr_ns(struct task_struct *tsk, struct pid_namespace *ns)
+{
+ return pid_nr_ns(task_session(tsk), ns);
+}
+EXPORT_SYMBOL(task_session_nr_ns);
+
/*
* Used by proc to find the first pid that is greater then or equal to nr.
*
* If there is a pid at nr this function is exactly the same as find_pid.
*/
-struct pid *find_ge_pid(int nr)
+struct pid *find_ge_pid(int nr, struct pid_namespace *ns)
{
struct pid *pid;
do {
- pid = find_pid(nr);
+ pid = find_pid_ns(nr, ns);
if (pid)
break;
- nr = next_pidmap(current->nsproxy->pid_ns, nr);
+ nr = next_pidmap(ns, nr);
} while (nr > 0);
return pid;
}
EXPORT_SYMBOL_GPL(find_get_pid);
+struct pid_cache {
+ int nr_ids;
+ char name[16];
+ struct kmem_cache *cachep;
+ struct list_head list;
+};
+
+static LIST_HEAD(pid_caches_lh);
+static DEFINE_MUTEX(pid_caches_mutex);
+
+/*
+ * creates the kmem cache to allocate pids from.
+ * @nr_ids: the number of numerical ids this pid will have to carry
+ */
+
+static struct kmem_cache *create_pid_cachep(int nr_ids)
+{
+ struct pid_cache *pcache;
+ struct kmem_cache *cachep;
+
+ mutex_lock(&pid_caches_mutex);
+ list_for_each_entry (pcache, &pid_caches_lh, list)
+ if (pcache->nr_ids == nr_ids)
+ goto out;
+
+ pcache = kmalloc(sizeof(struct pid_cache), GFP_KERNEL);
+ if (pcache == NULL)
+ goto err_alloc;
+
+ snprintf(pcache->name, sizeof(pcache->name), "pid_%d", nr_ids);
+ cachep = kmem_cache_create(pcache->name,
+ sizeof(struct pid) + (nr_ids - 1) * sizeof(struct upid),
+ 0, SLAB_HWCACHE_ALIGN, NULL);
+ if (cachep == NULL)
+ goto err_cachep;
+
+ pcache->nr_ids = nr_ids;
+ pcache->cachep = cachep;
+ list_add(&pcache->list, &pid_caches_lh);
+out:
+ mutex_unlock(&pid_caches_mutex);
+ return pcache->cachep;
+
+err_cachep:
+ kfree(pcache);
+err_alloc:
+ mutex_unlock(&pid_caches_mutex);
+ return NULL;
+}
+
+#ifdef CONFIG_PID_NS
+static struct pid_namespace *create_pid_namespace(int level)
+{
+ struct pid_namespace *ns;
+ int i;
+
+ ns = kmem_cache_alloc(pid_ns_cachep, GFP_KERNEL);
+ if (ns == NULL)
+ goto out;
+
+ ns->pidmap[0].page = kzalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!ns->pidmap[0].page)
+ goto out_free;
+
+ ns->pid_cachep = create_pid_cachep(level + 1);
+ if (ns->pid_cachep == NULL)
+ goto out_free_map;
+
+ kref_init(&ns->kref);
+ ns->last_pid = 0;
+ ns->child_reaper = NULL;
+ ns->level = level;
+
+ set_bit(0, ns->pidmap[0].page);
+ atomic_set(&ns->pidmap[0].nr_free, BITS_PER_PAGE - 1);
+
+ for (i = 1; i < PIDMAP_ENTRIES; i++) {
+ ns->pidmap[i].page = 0;
+ atomic_set(&ns->pidmap[i].nr_free, BITS_PER_PAGE);
+ }
+
+ return ns;
+
+out_free_map:
+ kfree(ns->pidmap[0].page);
+out_free:
+ kmem_cache_free(pid_ns_cachep, ns);
+out:
+ return ERR_PTR(-ENOMEM);
+}
+
+static void destroy_pid_namespace(struct pid_namespace *ns)
+{
+ int i;
+
+ for (i = 0; i < PIDMAP_ENTRIES; i++)
+ kfree(ns->pidmap[i].page);
+ kmem_cache_free(pid_ns_cachep, ns);
+}
+
struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *old_ns)
{
+ struct pid_namespace *new_ns;
+
BUG_ON(!old_ns);
- get_pid_ns(old_ns);
- return old_ns;
+ new_ns = get_pid_ns(old_ns);
+ if (!(flags & CLONE_NEWPID))
+ goto out;
+
+ new_ns = ERR_PTR(-EINVAL);
+ if (flags & CLONE_THREAD)
+ goto out_put;
+
+ new_ns = create_pid_namespace(old_ns->level + 1);
+ if (!IS_ERR(new_ns))
+ new_ns->parent = get_pid_ns(old_ns);
+
+out_put:
+ put_pid_ns(old_ns);
+out:
+ return new_ns;
}
void free_pid_ns(struct kref *kref)
{
- struct pid_namespace *ns;
+ struct pid_namespace *ns, *parent;
ns = container_of(kref, struct pid_namespace, kref);
- kfree(ns);
+
+ parent = ns->parent;
+ destroy_pid_namespace(ns);
+
+ if (parent != NULL)
+ put_pid_ns(parent);
+}
+#endif /* CONFIG_PID_NS */
+
+void zap_pid_ns_processes(struct pid_namespace *pid_ns)
+{
+ int nr;
+ int rc;
+
+ /*
+ * The last thread in the cgroup-init thread group is terminating.
+ * Find remaining pid_ts in the namespace, signal and wait for them
+ * to exit.
+ *
+ * Note: This signals each threads in the namespace - even those that
+ * belong to the same thread group, To avoid this, we would have
+ * to walk the entire tasklist looking a processes in this
+ * namespace, but that could be unnecessarily expensive if the
+ * pid namespace has just a few processes. Or we need to
+ * maintain a tasklist for each pid namespace.
+ *
+ */
+ read_lock(&tasklist_lock);
+ nr = next_pidmap(pid_ns, 1);
+ while (nr > 0) {
+ kill_proc_info(SIGKILL, SEND_SIG_PRIV, nr);
+ nr = next_pidmap(pid_ns, nr);
+ }
+ read_unlock(&tasklist_lock);
+
+ do {
+ clear_thread_flag(TIF_SIGPENDING);
+ rc = sys_wait4(-1, NULL, __WALL, NULL);
+ } while (rc != -ECHILD);
+
+
+ /* Child reaper for the pid namespace is going away */
+ pid_ns->child_reaper = NULL;
+ return;
}
/*
@@ -412,5 +693,9 @@ void __init pidmap_init(void)
set_bit(0, init_pid_ns.pidmap[0].page);
atomic_dec(&init_pid_ns.pidmap[0].nr_free);
- pid_cachep = KMEM_CACHE(pid, SLAB_PANIC);
+ init_pid_ns.pid_cachep = create_pid_cachep(1);
+ if (init_pid_ns.pid_cachep == NULL)
+ panic("Can't create pid_1 cachep\n");
+
+ pid_ns_cachep = KMEM_CACHE(pid_namespace, SLAB_PANIC);
}
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index b53c8fcd9d82..68c96376e84a 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -21,8 +21,8 @@ static int check_clock(const clockid_t which_clock)
read_lock(&tasklist_lock);
p = find_task_by_pid(pid);
- if (!p || (CPUCLOCK_PERTHREAD(which_clock) ?
- p->tgid != current->tgid : p->tgid != pid)) {
+ if (!p || !(CPUCLOCK_PERTHREAD(which_clock) ?
+ same_thread_group(p, current) : thread_group_leader(p))) {
error = -EINVAL;
}
read_unlock(&tasklist_lock);
@@ -308,13 +308,13 @@ int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *tp)
p = find_task_by_pid(pid);
if (p) {
if (CPUCLOCK_PERTHREAD(which_clock)) {
- if (p->tgid == current->tgid) {
+ if (same_thread_group(p, current)) {
error = cpu_clock_sample(which_clock,
p, &rtn);
}
} else {
read_lock(&tasklist_lock);
- if (p->tgid == pid && p->signal) {
+ if (thread_group_leader(p) && p->signal) {
error =
cpu_clock_sample_group(which_clock,
p, &rtn);
@@ -355,7 +355,7 @@ int posix_cpu_timer_create(struct k_itimer *new_timer)
p = current;
} else {
p = find_task_by_pid(pid);
- if (p && p->tgid != current->tgid)
+ if (p && !same_thread_group(p, current))
p = NULL;
}
} else {
@@ -363,7 +363,7 @@ int posix_cpu_timer_create(struct k_itimer *new_timer)
p = current->group_leader;
} else {
p = find_task_by_pid(pid);
- if (p && p->tgid != pid)
+ if (p && !thread_group_leader(p))
p = NULL;
}
}
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
index 57efe0400bc2..35b4bbfc78ff 100644
--- a/kernel/posix-timers.c
+++ b/kernel/posix-timers.c
@@ -241,7 +241,8 @@ static __init int init_posix_timers(void)
register_posix_clock(CLOCK_MONOTONIC, &clock_monotonic);
posix_timers_cache = kmem_cache_create("posix_timers_cache",
- sizeof (struct k_itimer), 0, 0, NULL);
+ sizeof (struct k_itimer), 0, SLAB_PANIC,
+ NULL);
idr_init(&posix_timers_id);
return 0;
}
@@ -403,7 +404,7 @@ static struct task_struct * good_sigevent(sigevent_t * event)
if ((event->sigev_notify & SIGEV_THREAD_ID ) &&
(!(rtn = find_task_by_pid(event->sigev_notify_thread_id)) ||
- rtn->tgid != current->tgid ||
+ !same_thread_group(rtn, current) ||
(event->sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_SIGNAL))
return NULL;
@@ -607,7 +608,7 @@ static struct k_itimer * lock_timer(timer_t timer_id, unsigned long *flags)
spin_lock(&timr->it_lock);
if ((timr->it_id != timer_id) || !(timr->it_process) ||
- timr->it_process->tgid != current->tgid) {
+ !same_thread_group(timr->it_process, current)) {
spin_unlock(&timr->it_lock);
spin_unlock_irqrestore(&idr_lock, *flags);
timr = NULL;
@@ -980,9 +981,20 @@ sys_clock_getres(const clockid_t which_clock, struct timespec __user *tp)
static int common_nsleep(const clockid_t which_clock, int flags,
struct timespec *tsave, struct timespec __user *rmtp)
{
- return hrtimer_nanosleep(tsave, rmtp, flags & TIMER_ABSTIME ?
- HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
- which_clock);
+ struct timespec rmt;
+ int ret;
+
+ ret = hrtimer_nanosleep(tsave, rmtp ? &rmt : NULL,
+ flags & TIMER_ABSTIME ?
+ HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
+ which_clock);
+
+ if (ret && rmtp) {
+ if (copy_to_user(rmtp, &rmt, sizeof(*rmtp)))
+ return -EFAULT;
+ }
+
+ return ret;
}
asmlinkage long
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index 14b0e10dc95c..8e186c678149 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -44,17 +44,6 @@ config PM_VERBOSE
---help---
This option enables verbose messages from the Power Management code.
-config DISABLE_CONSOLE_SUSPEND
- bool "Keep console(s) enabled during suspend/resume (DANGEROUS)"
- depends on PM_DEBUG && PM_SLEEP
- default n
- ---help---
- This option turns off the console suspend mechanism that prevents
- debug messages from reaching the console during the suspend/resume
- operations. This may be helpful when debugging device drivers'
- suspend/resume routines, but may itself lead to problems, for example
- if netconsole is used.
-
config PM_TRACE
bool "Suspend/resume event tracing"
depends on PM_DEBUG && X86 && PM_SLEEP && EXPERIMENTAL
diff --git a/kernel/power/disk.c b/kernel/power/disk.c
index eb72255b5c86..05b64790fe83 100644
--- a/kernel/power/disk.c
+++ b/kernel/power/disk.c
@@ -45,17 +45,18 @@ enum {
static int hibernation_mode = HIBERNATION_SHUTDOWN;
-static struct hibernation_ops *hibernation_ops;
+static struct platform_hibernation_ops *hibernation_ops;
/**
* hibernation_set_ops - set the global hibernate operations
* @ops: the hibernation operations to use in subsequent hibernation transitions
*/
-void hibernation_set_ops(struct hibernation_ops *ops)
+void hibernation_set_ops(struct platform_hibernation_ops *ops)
{
- if (ops && !(ops->prepare && ops->enter && ops->finish
- && ops->pre_restore && ops->restore_cleanup)) {
+ if (ops && !(ops->start && ops->pre_snapshot && ops->finish
+ && ops->prepare && ops->enter && ops->pre_restore
+ && ops->restore_cleanup)) {
WARN_ON(1);
return;
}
@@ -69,16 +70,37 @@ void hibernation_set_ops(struct hibernation_ops *ops)
mutex_unlock(&pm_mutex);
}
+/**
+ * platform_start - tell the platform driver that we're starting
+ * hibernation
+ */
+
+static int platform_start(int platform_mode)
+{
+ return (platform_mode && hibernation_ops) ?
+ hibernation_ops->start() : 0;
+}
/**
- * platform_prepare - prepare the machine for hibernation using the
+ * platform_pre_snapshot - prepare the machine for hibernation using the
* platform driver if so configured and return an error code if it fails
*/
-static int platform_prepare(int platform_mode)
+static int platform_pre_snapshot(int platform_mode)
{
return (platform_mode && hibernation_ops) ?
- hibernation_ops->prepare() : 0;
+ hibernation_ops->pre_snapshot() : 0;
+}
+
+/**
+ * platform_leave - prepare the machine for switching to the normal mode
+ * of operation using the platform driver (called with interrupts disabled)
+ */
+
+static void platform_leave(int platform_mode)
+{
+ if (platform_mode && hibernation_ops)
+ hibernation_ops->leave();
}
/**
@@ -118,6 +140,51 @@ static void platform_restore_cleanup(int platform_mode)
}
/**
+ * create_image - freeze devices that need to be frozen with interrupts
+ * off, create the hibernation image and thaw those devices. Control
+ * reappears in this routine after a restore.
+ */
+
+int create_image(int platform_mode)
+{
+ int error;
+
+ error = arch_prepare_suspend();
+ if (error)
+ return error;
+
+ local_irq_disable();
+ /* At this point, device_suspend() has been called, but *not*
+ * device_power_down(). We *must* call device_power_down() now.
+ * Otherwise, drivers for some devices (e.g. interrupt controllers)
+ * become desynchronized with the actual state of the hardware
+ * at resume time, and evil weirdness ensues.
+ */
+ error = device_power_down(PMSG_FREEZE);
+ if (error) {
+ printk(KERN_ERR "Some devices failed to power down, "
+ KERN_ERR "aborting suspend\n");
+ goto Enable_irqs;
+ }
+
+ save_processor_state();
+ error = swsusp_arch_suspend();
+ if (error)
+ printk(KERN_ERR "Error %d while creating the image\n", error);
+ /* Restore control flow magically appears here */
+ restore_processor_state();
+ if (!in_suspend)
+ platform_leave(platform_mode);
+ /* NOTE: device_power_up() is just a resume() for devices
+ * that suspended with irqs off ... no overall powerup.
+ */
+ device_power_up();
+ Enable_irqs:
+ local_irq_enable();
+ return error;
+}
+
+/**
* hibernation_snapshot - quiesce devices and create the hibernation
* snapshot image.
* @platform_mode - if set, use the platform driver, if available, to
@@ -135,12 +202,16 @@ int hibernation_snapshot(int platform_mode)
if (error)
return error;
+ error = platform_start(platform_mode);
+ if (error)
+ return error;
+
suspend_console();
error = device_suspend(PMSG_FREEZE);
if (error)
goto Resume_console;
- error = platform_prepare(platform_mode);
+ error = platform_pre_snapshot(platform_mode);
if (error)
goto Resume_devices;
@@ -148,7 +219,7 @@ int hibernation_snapshot(int platform_mode)
if (!error) {
if (hibernation_mode != HIBERNATION_TEST) {
in_suspend = 1;
- error = swsusp_suspend();
+ error = create_image(platform_mode);
/* Control returns here after successful restore */
} else {
printk("swsusp debug: Waiting for 5 seconds.\n");
@@ -207,21 +278,50 @@ int hibernation_platform_enter(void)
{
int error;
- if (hibernation_ops) {
- kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK);
- /*
- * We have cancelled the power transition by running
- * hibernation_ops->finish() before saving the image, so we
- * should let the firmware know that we're going to enter the
- * sleep state after all
- */
- error = hibernation_ops->prepare();
- sysdev_shutdown();
- if (!error)
- error = hibernation_ops->enter();
- } else {
- error = -ENOSYS;
+ if (!hibernation_ops)
+ return -ENOSYS;
+
+ /*
+ * We have cancelled the power transition by running
+ * hibernation_ops->finish() before saving the image, so we should let
+ * the firmware know that we're going to enter the sleep state after all
+ */
+ error = hibernation_ops->start();
+ if (error)
+ return error;
+
+ suspend_console();
+ error = device_suspend(PMSG_SUSPEND);
+ if (error)
+ goto Resume_console;
+
+ error = hibernation_ops->prepare();
+ if (error)
+ goto Resume_devices;
+
+ error = disable_nonboot_cpus();
+ if (error)
+ goto Finish;
+
+ local_irq_disable();
+ error = device_power_down(PMSG_SUSPEND);
+ if (!error) {
+ hibernation_ops->enter();
+ /* We should never get here */
+ while (1);
}
+ local_irq_enable();
+
+ /*
+ * We don't need to reenable the nonboot CPUs or resume consoles, since
+ * the system is going to be halted anyway.
+ */
+ Finish:
+ hibernation_ops->finish();
+ Resume_devices:
+ device_resume();
+ Resume_console:
+ resume_console();
return error;
}
@@ -238,14 +338,14 @@ static void power_down(void)
case HIBERNATION_TEST:
case HIBERNATION_TESTPROC:
break;
- case HIBERNATION_SHUTDOWN:
- kernel_power_off();
- break;
case HIBERNATION_REBOOT:
kernel_restart(NULL);
break;
case HIBERNATION_PLATFORM:
hibernation_platform_enter();
+ case HIBERNATION_SHUTDOWN:
+ kernel_power_off();
+ break;
}
kernel_halt();
/*
@@ -298,6 +398,10 @@ int hibernate(void)
if (error)
goto Exit;
+ printk("Syncing filesystems ... ");
+ sys_sync();
+ printk("done.\n");
+
error = prepare_processes();
if (error)
goto Finish;
@@ -352,7 +456,17 @@ static int software_resume(void)
int error;
unsigned int flags;
- mutex_lock(&pm_mutex);
+ /*
+ * 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
+ * calling hibernate functions (which take pm_mutex) this can
+ * cause lockdep to complain about a possible ABBA deadlock
+ * which cannot happen since we're in the boot code here and
+ * sysfs can't be invoked yet. Therefore, we use a subclass
+ * here to avoid lockdep complaining.
+ */
+ mutex_lock_nested(&pm_mutex, SINGLE_DEPTH_NESTING);
if (!swsusp_resume_device) {
if (!strlen(resume_file)) {
mutex_unlock(&pm_mutex);
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 350b485b3b60..3cdf95b1dc92 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -20,6 +20,7 @@
#include <linux/resume-trace.h>
#include <linux/freezer.h>
#include <linux/vmstat.h>
+#include <linux/syscalls.h>
#include "power.h"
@@ -32,39 +33,32 @@ DEFINE_MUTEX(pm_mutex);
/* This is just an arbitrary number */
#define FREE_PAGE_NUMBER (100)
-struct pm_ops *pm_ops;
+static struct platform_suspend_ops *suspend_ops;
/**
- * pm_set_ops - Set the global power method table.
+ * suspend_set_ops - Set the global suspend method table.
* @ops: Pointer to ops structure.
*/
-void pm_set_ops(struct pm_ops * ops)
+void suspend_set_ops(struct platform_suspend_ops *ops)
{
mutex_lock(&pm_mutex);
- pm_ops = ops;
+ suspend_ops = ops;
mutex_unlock(&pm_mutex);
}
/**
- * pm_valid_only_mem - generic memory-only valid callback
+ * suspend_valid_only_mem - generic memory-only valid callback
*
- * pm_ops drivers that implement mem suspend only and only need
+ * Platform drivers that implement mem suspend only and only need
* to check for that in their .valid callback can use this instead
* of rolling their own .valid callback.
*/
-int pm_valid_only_mem(suspend_state_t state)
+int suspend_valid_only_mem(suspend_state_t state)
{
return state == PM_SUSPEND_MEM;
}
-
-static inline void pm_finish(suspend_state_t state)
-{
- if (pm_ops->finish)
- pm_ops->finish(state);
-}
-
/**
* suspend_prepare - Do prep work before entering low-power state.
*
@@ -76,7 +70,7 @@ static int suspend_prepare(void)
int error;
unsigned int free_pages;
- if (!pm_ops || !pm_ops->enter)
+ if (!suspend_ops || !suspend_ops->enter)
return -EPERM;
error = pm_notifier_call_chain(PM_SUSPEND_PREPARE);
@@ -128,7 +122,7 @@ void __attribute__ ((weak)) arch_suspend_enable_irqs(void)
*
* This function should be called after devices have been suspended.
*/
-int suspend_enter(suspend_state_t state)
+static int suspend_enter(suspend_state_t state)
{
int error = 0;
@@ -139,7 +133,7 @@ int suspend_enter(suspend_state_t state)
printk(KERN_ERR "Some devices failed to power down\n");
goto Done;
}
- error = pm_ops->enter(state);
+ error = suspend_ops->enter(state);
device_power_up();
Done:
arch_suspend_enable_irqs();
@@ -156,11 +150,11 @@ int suspend_devices_and_enter(suspend_state_t state)
{
int error;
- if (!pm_ops)
+ if (!suspend_ops)
return -ENOSYS;
- if (pm_ops->set_target) {
- error = pm_ops->set_target(state);
+ if (suspend_ops->set_target) {
+ error = suspend_ops->set_target(state);
if (error)
return error;
}
@@ -170,8 +164,8 @@ int suspend_devices_and_enter(suspend_state_t state)
printk(KERN_ERR "Some devices failed to suspend\n");
goto Resume_console;
}
- if (pm_ops->prepare) {
- error = pm_ops->prepare(state);
+ if (suspend_ops->prepare) {
+ error = suspend_ops->prepare();
if (error)
goto Resume_devices;
}
@@ -180,7 +174,8 @@ int suspend_devices_and_enter(suspend_state_t state)
suspend_enter(state);
enable_nonboot_cpus();
- pm_finish(state);
+ if (suspend_ops->finish)
+ suspend_ops->finish();
Resume_devices:
device_resume();
Resume_console:
@@ -214,7 +209,7 @@ static inline int valid_state(suspend_state_t state)
/* All states need lowlevel support and need to be valid
* to the lowlevel implementation, no valid callback
* implies that none are valid. */
- if (!pm_ops || !pm_ops->valid || !pm_ops->valid(state))
+ if (!suspend_ops || !suspend_ops->valid || !suspend_ops->valid(state))
return 0;
return 1;
}
@@ -236,9 +231,14 @@ static int enter_state(suspend_state_t state)
if (!valid_state(state))
return -ENODEV;
+
if (!mutex_trylock(&pm_mutex))
return -EBUSY;
+ printk("Syncing filesystems ... ");
+ sys_sync();
+ printk("done.\n");
+
pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]);
if ((error = suspend_prepare()))
goto Unlock;
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 95fbf2dd3fe3..195dc4611764 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -11,14 +11,32 @@ struct swsusp_info {
unsigned long size;
} __attribute__((aligned(PAGE_SIZE)));
+#ifdef CONFIG_HIBERNATION
+#ifdef CONFIG_ARCH_HIBERNATION_HEADER
+/* Maximum size of architecture specific data in a hibernation header */
+#define MAX_ARCH_HEADER_SIZE (sizeof(struct new_utsname) + 4)
+extern int arch_hibernation_header_save(void *addr, unsigned int max_size);
+extern int arch_hibernation_header_restore(void *addr);
+
+static inline int init_header_complete(struct swsusp_info *info)
+{
+ return arch_hibernation_header_save(info, MAX_ARCH_HEADER_SIZE);
+}
+
+static inline char *check_image_kernel(struct swsusp_info *info)
+{
+ return arch_hibernation_header_restore(info) ?
+ "architecture specific data" : NULL;
+}
+#endif /* CONFIG_ARCH_HIBERNATION_HEADER */
-#ifdef CONFIG_HIBERNATION
/*
* Keep some memory free so that I/O operations can succeed without paging
* [Might this be more than 4 MB?]
*/
#define PAGES_FOR_IO ((4096 * 1024) >> PAGE_SHIFT)
+
/*
* Keep 1 MB of memory free so that device drivers can allocate some pages in
* their .suspend() routines without breaking the suspend to disk.
@@ -165,7 +183,6 @@ extern int swsusp_swap_in_use(void);
extern int swsusp_check(void);
extern int swsusp_shrink_memory(void);
extern void swsusp_free(void);
-extern int swsusp_suspend(void);
extern int swsusp_resume(void);
extern int swsusp_read(unsigned int *flags_p);
extern int swsusp_write(unsigned int flags);
diff --git a/kernel/power/process.c b/kernel/power/process.c
index 3434940a3df1..6533923e711b 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -75,21 +75,79 @@ void refrigerator(void)
__set_current_state(save);
}
-static void freeze_task(struct task_struct *p)
+static void fake_signal_wake_up(struct task_struct *p, int resume)
{
unsigned long flags;
- if (!freezing(p)) {
+ spin_lock_irqsave(&p->sighand->siglock, flags);
+ signal_wake_up(p, resume);
+ spin_unlock_irqrestore(&p->sighand->siglock, flags);
+}
+
+static void send_fake_signal(struct task_struct *p)
+{
+ if (p->state == TASK_STOPPED)
+ force_sig_specific(SIGSTOP, p);
+ fake_signal_wake_up(p, p->state == TASK_STOPPED);
+}
+
+static int has_mm(struct task_struct *p)
+{
+ return (p->mm && !(p->flags & PF_BORROWED_MM));
+}
+
+/**
+ * freeze_task - send a freeze request to given task
+ * @p: task to send the request to
+ * @with_mm_only: if set, the request will only be sent if the task has its
+ * own mm
+ * Return value: 0, if @with_mm_only is set and the task has no mm of its
+ * own or the task is frozen, 1, otherwise
+ *
+ * The freeze request is sent by seting the tasks's TIF_FREEZE flag and
+ * either sending a fake signal to it or waking it up, depending on whether
+ * or not it has its own mm (ie. it is a user land task). If @with_mm_only
+ * is set and the task has no mm of its own (ie. it is a kernel thread),
+ * its TIF_FREEZE flag should not be set.
+ *
+ * The task_lock() is necessary to prevent races with exit_mm() or
+ * use_mm()/unuse_mm() from occuring.
+ */
+static int freeze_task(struct task_struct *p, int with_mm_only)
+{
+ int ret = 1;
+
+ task_lock(p);
+ if (freezing(p)) {
+ if (has_mm(p)) {
+ if (!signal_pending(p))
+ fake_signal_wake_up(p, 0);
+ } else {
+ if (with_mm_only)
+ ret = 0;
+ else
+ wake_up_state(p, TASK_INTERRUPTIBLE);
+ }
+ } else {
rmb();
- if (!frozen(p)) {
- set_freeze_flag(p);
- if (p->state == TASK_STOPPED)
- force_sig_specific(SIGSTOP, p);
- spin_lock_irqsave(&p->sighand->siglock, flags);
- signal_wake_up(p, p->state == TASK_STOPPED);
- spin_unlock_irqrestore(&p->sighand->siglock, flags);
+ if (frozen(p)) {
+ ret = 0;
+ } else {
+ if (has_mm(p)) {
+ set_freeze_flag(p);
+ send_fake_signal(p);
+ } else {
+ if (with_mm_only) {
+ ret = 0;
+ } else {
+ set_freeze_flag(p);
+ wake_up_state(p, TASK_INTERRUPTIBLE);
+ }
+ }
}
}
+ task_unlock(p);
+ return ret;
}
static void cancel_freezing(struct task_struct *p)
@@ -110,6 +168,11 @@ static int try_to_freeze_tasks(int freeze_user_space)
struct task_struct *g, *p;
unsigned long end_time;
unsigned int todo;
+ struct timeval start, end;
+ s64 elapsed_csecs64;
+ unsigned int elapsed_csecs;
+
+ do_gettimeofday(&start);
end_time = jiffies + TIMEOUT;
do {
@@ -119,31 +182,14 @@ static int try_to_freeze_tasks(int freeze_user_space)
if (frozen(p) || !freezeable(p))
continue;
- if (freeze_user_space) {
- if (p->state == TASK_TRACED &&
- frozen(p->parent)) {
- cancel_freezing(p);
- continue;
- }
- /*
- * Kernel threads should not have TIF_FREEZE set
- * at this point, so we must ensure that either
- * p->mm is not NULL *and* PF_BORROWED_MM is
- * unset, or TIF_FRREZE is left unset.
- * The task_lock() is necessary to prevent races
- * with exit_mm() or use_mm()/unuse_mm() from
- * occuring.
- */
- task_lock(p);
- if (!p->mm || (p->flags & PF_BORROWED_MM)) {
- task_unlock(p);
- continue;
- }
- freeze_task(p);
- task_unlock(p);
- } else {
- freeze_task(p);
+ if (p->state == TASK_TRACED && frozen(p->parent)) {
+ cancel_freezing(p);
+ continue;
}
+
+ if (!freeze_task(p, freeze_user_space))
+ continue;
+
if (!freezer_should_skip(p))
todo++;
} while_each_thread(g, p);
@@ -153,6 +199,11 @@ static int try_to_freeze_tasks(int freeze_user_space)
break;
} while (todo);
+ do_gettimeofday(&end);
+ elapsed_csecs64 = timeval_to_ns(&end) - timeval_to_ns(&start);
+ do_div(elapsed_csecs64, NSEC_PER_SEC / 100);
+ elapsed_csecs = elapsed_csecs64;
+
if (todo) {
/* This does not unfreeze processes that are already frozen
* (we have slightly ugly calling convention in that respect,
@@ -160,10 +211,9 @@ static int try_to_freeze_tasks(int freeze_user_space)
* but it cleans up leftover PF_FREEZE requests.
*/
printk("\n");
- printk(KERN_ERR "Freezing of %s timed out after %d seconds "
+ printk(KERN_ERR "Freezing of tasks failed after %d.%02d seconds "
"(%d tasks refusing to freeze):\n",
- freeze_user_space ? "user space " : "tasks ",
- TIMEOUT / HZ, todo);
+ elapsed_csecs / 100, elapsed_csecs % 100, todo);
show_state();
read_lock(&tasklist_lock);
do_each_thread(g, p) {
@@ -174,6 +224,9 @@ static int try_to_freeze_tasks(int freeze_user_space)
task_unlock(p);
} while_each_thread(g, p);
read_unlock(&tasklist_lock);
+ } else {
+ printk("(elapsed %d.%02d seconds) ", elapsed_csecs / 100,
+ elapsed_csecs % 100);
}
return todo ? -EBUSY : 0;
@@ -186,19 +239,21 @@ int freeze_processes(void)
{
int error;
- printk("Stopping tasks ... ");
+ printk("Freezing user space processes ... ");
error = try_to_freeze_tasks(FREEZER_USER_SPACE);
if (error)
- return error;
+ goto Exit;
+ printk("done.\n");
- sys_sync();
+ printk("Freezing remaining freezable tasks ... ");
error = try_to_freeze_tasks(FREEZER_KERNEL_THREADS);
if (error)
- return error;
-
- printk("done.\n");
+ goto Exit;
+ printk("done.");
+ Exit:
BUG_ON(in_atomic());
- return 0;
+ printk("\n");
+ return error;
}
static void thaw_tasks(int thaw_user_space)
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index a686590d88c1..78039b477d2b 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -1005,11 +1005,12 @@ copy_data_pages(struct memory_bitmap *copy_bm, struct memory_bitmap *orig_bm)
}
memory_bm_position_reset(orig_bm);
memory_bm_position_reset(copy_bm);
- do {
+ for(;;) {
pfn = memory_bm_next_pfn(orig_bm);
- if (likely(pfn != BM_END_OF_MAP))
- copy_data_page(memory_bm_next_pfn(copy_bm), pfn);
- } while (pfn != BM_END_OF_MAP);
+ if (unlikely(pfn == BM_END_OF_MAP))
+ break;
+ copy_data_page(memory_bm_next_pfn(copy_bm), pfn);
+ }
}
/* Total number of image pages */
@@ -1239,17 +1240,39 @@ asmlinkage int swsusp_save(void)
return 0;
}
-static void init_header(struct swsusp_info *info)
+#ifndef CONFIG_ARCH_HIBERNATION_HEADER
+static int init_header_complete(struct swsusp_info *info)
{
- memset(info, 0, sizeof(struct swsusp_info));
+ memcpy(&info->uts, init_utsname(), sizeof(struct new_utsname));
info->version_code = LINUX_VERSION_CODE;
+ return 0;
+}
+
+static char *check_image_kernel(struct swsusp_info *info)
+{
+ if (info->version_code != LINUX_VERSION_CODE)
+ return "kernel version";
+ if (strcmp(info->uts.sysname,init_utsname()->sysname))
+ return "system type";
+ if (strcmp(info->uts.release,init_utsname()->release))
+ return "kernel release";
+ if (strcmp(info->uts.version,init_utsname()->version))
+ return "version";
+ if (strcmp(info->uts.machine,init_utsname()->machine))
+ return "machine";
+ return NULL;
+}
+#endif /* CONFIG_ARCH_HIBERNATION_HEADER */
+
+static int init_header(struct swsusp_info *info)
+{
+ memset(info, 0, sizeof(struct swsusp_info));
info->num_physpages = num_physpages;
- memcpy(&info->uts, init_utsname(), sizeof(struct new_utsname));
- info->cpus = num_online_cpus();
info->image_pages = nr_copy_pages;
info->pages = nr_copy_pages + nr_meta_pages + 1;
info->size = info->pages;
info->size <<= PAGE_SHIFT;
+ return init_header_complete(info);
}
/**
@@ -1303,7 +1326,11 @@ int snapshot_read_next(struct snapshot_handle *handle, size_t count)
return -ENOMEM;
}
if (!handle->offset) {
- init_header((struct swsusp_info *)buffer);
+ int error;
+
+ error = init_header((struct swsusp_info *)buffer);
+ if (error)
+ return error;
handle->buffer = buffer;
memory_bm_position_reset(&orig_bm);
memory_bm_position_reset(&copy_bm);
@@ -1394,22 +1421,13 @@ duplicate_memory_bitmap(struct memory_bitmap *dst, struct memory_bitmap *src)
}
}
-static inline int check_header(struct swsusp_info *info)
+static int check_header(struct swsusp_info *info)
{
- char *reason = NULL;
+ char *reason;
- if (info->version_code != LINUX_VERSION_CODE)
- reason = "kernel version";
- if (info->num_physpages != num_physpages)
+ reason = check_image_kernel(info);
+ if (!reason && info->num_physpages != num_physpages)
reason = "memory size";
- if (strcmp(info->uts.sysname,init_utsname()->sysname))
- reason = "system type";
- if (strcmp(info->uts.release,init_utsname()->release))
- reason = "kernel release";
- if (strcmp(info->uts.version,init_utsname()->version))
- reason = "version";
- if (strcmp(info->uts.machine,init_utsname()->machine))
- reason = "machine";
if (reason) {
printk(KERN_ERR "swsusp: Resume mismatch: %s\n", reason);
return -EPERM;
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c
index 5da304c8f1f6..e1722d3155f1 100644
--- a/kernel/power/swsusp.c
+++ b/kernel/power/swsusp.c
@@ -270,39 +270,6 @@ int swsusp_shrink_memory(void)
return 0;
}
-int swsusp_suspend(void)
-{
- int error;
-
- if ((error = arch_prepare_suspend()))
- return error;
-
- local_irq_disable();
- /* At this point, device_suspend() has been called, but *not*
- * device_power_down(). We *must* device_power_down() now.
- * Otherwise, drivers for some devices (e.g. interrupt controllers)
- * become desynchronized with the actual state of the hardware
- * at resume time, and evil weirdness ensues.
- */
- if ((error = device_power_down(PMSG_FREEZE))) {
- printk(KERN_ERR "Some devices failed to power down, aborting suspend\n");
- goto Enable_irqs;
- }
-
- save_processor_state();
- if ((error = swsusp_arch_suspend()))
- printk(KERN_ERR "Error %d suspending\n", error);
- /* Restore control flow magically appears here */
- restore_processor_state();
- /* NOTE: device_power_up() is just a resume() for devices
- * that suspended with irqs off ... no overall powerup.
- */
- device_power_up();
- Enable_irqs:
- local_irq_enable();
- return error;
-}
-
int swsusp_resume(void)
{
int error;
diff --git a/kernel/power/user.c b/kernel/power/user.c
index bd0723a7df3f..5bd321bcbb75 100644
--- a/kernel/power/user.c
+++ b/kernel/power/user.c
@@ -153,6 +153,10 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
mutex_lock(&pm_mutex);
error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE);
if (!error) {
+ printk("Syncing filesystems ... ");
+ sys_sync();
+ printk("done.\n");
+
error = freeze_processes();
if (error)
thaw_processes();
diff --git a/kernel/printk.c b/kernel/printk.c
index 8451dfc31d25..a30fe33de395 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -22,6 +22,8 @@
#include <linux/tty_driver.h>
#include <linux/console.h>
#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/nmi.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/interrupt.h> /* For in_interrupt() */
@@ -162,6 +164,113 @@ out:
__setup("log_buf_len=", log_buf_len_setup);
+#ifdef CONFIG_BOOT_PRINTK_DELAY
+
+static unsigned int boot_delay; /* msecs delay after each printk during bootup */
+static unsigned long long printk_delay_msec; /* per msec, based on boot_delay */
+
+static int __init boot_delay_setup(char *str)
+{
+ unsigned long lpj;
+ unsigned long long loops_per_msec;
+
+ lpj = preset_lpj ? preset_lpj : 1000000; /* some guess */
+ loops_per_msec = (unsigned long long)lpj / 1000 * HZ;
+
+ get_option(&str, &boot_delay);
+ if (boot_delay > 10 * 1000)
+ boot_delay = 0;
+
+ printk_delay_msec = loops_per_msec;
+ printk(KERN_DEBUG "boot_delay: %u, preset_lpj: %ld, lpj: %lu, "
+ "HZ: %d, printk_delay_msec: %llu\n",
+ boot_delay, preset_lpj, lpj, HZ, printk_delay_msec);
+ return 1;
+}
+__setup("boot_delay=", boot_delay_setup);
+
+static void boot_delay_msec(void)
+{
+ unsigned long long k;
+ unsigned long timeout;
+
+ if (boot_delay == 0 || system_state != SYSTEM_BOOTING)
+ return;
+
+ k = (unsigned long long)printk_delay_msec * boot_delay;
+
+ timeout = jiffies + msecs_to_jiffies(boot_delay);
+ while (k) {
+ k--;
+ cpu_relax();
+ /*
+ * use (volatile) jiffies to prevent
+ * compiler reduction; loop termination via jiffies
+ * is secondary and may or may not happen.
+ */
+ if (time_after(jiffies, timeout))
+ break;
+ touch_nmi_watchdog();
+ }
+}
+#else
+static inline void boot_delay_msec(void)
+{
+}
+#endif
+
+/*
+ * Return the number of unread characters in the log buffer.
+ */
+int log_buf_get_len(void)
+{
+ return logged_chars;
+}
+
+/*
+ * Copy a range of characters from the log buffer.
+ */
+int log_buf_copy(char *dest, int idx, int len)
+{
+ int ret, max;
+ bool took_lock = false;
+
+ if (!oops_in_progress) {
+ spin_lock_irq(&logbuf_lock);
+ took_lock = true;
+ }
+
+ max = log_buf_get_len();
+ if (idx < 0 || idx >= max) {
+ ret = -1;
+ } else {
+ if (len > max)
+ len = max;
+ ret = len;
+ idx += (log_end - max);
+ while (len-- > 0)
+ dest[len] = LOG_BUF(idx + len);
+ }
+
+ if (took_lock)
+ spin_unlock_irq(&logbuf_lock);
+
+ return ret;
+}
+
+/*
+ * Extract a single character from the log buffer.
+ */
+int log_buf_read(int idx)
+{
+ char ret;
+
+ if (log_buf_copy(&ret, idx, 1) == 1)
+ return ret;
+ else
+ return -1;
+}
+
/*
* Commands to do_syslog:
*
@@ -527,6 +636,8 @@ asmlinkage int vprintk(const char *fmt, va_list args)
static char printk_buf[1024];
static int log_level_unknown = 1;
+ boot_delay_msec();
+
preempt_disable();
if (unlikely(oops_in_progress) && printk_cpu == smp_processor_id())
/* If a crash is occurring during printk() on this CPU,
@@ -751,7 +862,16 @@ int update_console_cmdline(char *name, int idx, char *name_new, int idx_new, cha
return -1;
}
-#ifndef CONFIG_DISABLE_CONSOLE_SUSPEND
+int console_suspend_enabled = 1;
+EXPORT_SYMBOL(console_suspend_enabled);
+
+static int __init console_suspend_disable(char *str)
+{
+ console_suspend_enabled = 0;
+ return 1;
+}
+__setup("no_console_suspend", console_suspend_disable);
+
/**
* suspend_console - suspend the console subsystem
*
@@ -759,6 +879,8 @@ int update_console_cmdline(char *name, int idx, char *name_new, int idx_new, cha
*/
void suspend_console(void)
{
+ if (!console_suspend_enabled)
+ return;
printk("Suspending console(s)\n");
acquire_console_sem();
console_suspended = 1;
@@ -766,10 +888,11 @@ void suspend_console(void)
void resume_console(void)
{
+ if (!console_suspend_enabled)
+ return;
console_suspended = 0;
release_console_sem();
}
-#endif /* CONFIG_DISABLE_CONSOLE_SUSPEND */
/**
* acquire_console_sem - lock the console system for exclusive use.
diff --git a/kernel/profile.c b/kernel/profile.c
index cb1e37d2dac3..5e95330e5120 100644
--- a/kernel/profile.c
+++ b/kernel/profile.c
@@ -37,7 +37,7 @@ struct profile_hit {
#define NR_PROFILE_GRP (NR_PROFILE_HIT/PROFILE_GRPSZ)
/* Oprofile timer tick hook */
-int (*timer_hook)(struct pt_regs *) __read_mostly;
+static int (*timer_hook)(struct pt_regs *) __read_mostly;
static atomic_t *prof_buffer;
static unsigned long prof_len, prof_shift;
@@ -60,6 +60,7 @@ static int __init profile_setup(char * str)
int par;
if (!strncmp(str, sleepstr, strlen(sleepstr))) {
+#ifdef CONFIG_SCHEDSTATS
prof_on = SLEEP_PROFILING;
if (str[strlen(sleepstr)] == ',')
str += strlen(sleepstr) + 1;
@@ -68,6 +69,10 @@ static int __init profile_setup(char * str)
printk(KERN_INFO
"kernel sleep profiling enabled (shift: %ld)\n",
prof_shift);
+#else
+ printk(KERN_WARNING
+ "kernel sleep profiling requires CONFIG_SCHEDSTATS\n");
+#endif /* CONFIG_SCHEDSTATS */
} else if (!strncmp(str, schedstr, strlen(schedstr))) {
prof_on = SCHED_PROFILING;
if (str[strlen(schedstr)] == ',')
@@ -346,7 +351,7 @@ static int __devinit profile_cpu_callback(struct notifier_block *info,
per_cpu(cpu_profile_flip, cpu) = 0;
if (!per_cpu(cpu_profile_hits, cpu)[1]) {
page = alloc_pages_node(node,
- GFP_KERNEL | __GFP_ZERO | GFP_THISNODE,
+ GFP_KERNEL | __GFP_ZERO,
0);
if (!page)
return NOTIFY_BAD;
@@ -354,7 +359,7 @@ static int __devinit profile_cpu_callback(struct notifier_block *info,
}
if (!per_cpu(cpu_profile_hits, cpu)[0]) {
page = alloc_pages_node(node,
- GFP_KERNEL | __GFP_ZERO | GFP_THISNODE,
+ GFP_KERNEL | __GFP_ZERO,
0);
if (!page)
goto out_free;
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 3eca7a55f2ee..7c76f2ffaeaa 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -19,6 +19,7 @@
#include <linux/security.h>
#include <linux/signal.h>
#include <linux/audit.h>
+#include <linux/pid_namespace.h>
#include <asm/pgtable.h>
#include <asm/uaccess.h>
@@ -168,7 +169,7 @@ int ptrace_attach(struct task_struct *task)
retval = -EPERM;
if (task->pid <= 1)
goto out;
- if (task->tgid == current->tgid)
+ if (same_thread_group(task, current))
goto out;
repeat:
@@ -386,6 +387,9 @@ int ptrace_request(struct task_struct *child, long request,
case PTRACE_SETSIGINFO:
ret = ptrace_setsiginfo(child, (siginfo_t __user *) data);
break;
+ case PTRACE_DETACH: /* detach a process that was attached. */
+ ret = ptrace_detach(child, data);
+ break;
default:
break;
}
@@ -440,7 +444,7 @@ struct task_struct *ptrace_get_task_struct(pid_t pid)
return ERR_PTR(-EPERM);
read_lock(&tasklist_lock);
- child = find_task_by_pid(pid);
+ child = find_task_by_vpid(pid);
if (child)
get_task_struct(child);
@@ -450,6 +454,10 @@ struct task_struct *ptrace_get_task_struct(pid_t pid)
return child;
}
+#ifndef arch_ptrace_attach
+#define arch_ptrace_attach(child) do { } while (0)
+#endif
+
#ifndef __ARCH_SYS_PTRACE
asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
{
@@ -473,6 +481,12 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
if (request == PTRACE_ATTACH) {
ret = ptrace_attach(child);
+ /*
+ * Some architectures need to do book-keeping after
+ * a ptrace attach.
+ */
+ if (!ret)
+ arch_ptrace_attach(child);
goto out_put_task_struct;
}
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c
index 130214f3d229..a66d4d1615f7 100644
--- a/kernel/rcupdate.c
+++ b/kernel/rcupdate.c
@@ -45,7 +45,6 @@
#include <linux/moduleparam.h>
#include <linux/percpu.h>
#include <linux/notifier.h>
-#include <linux/rcupdate.h>
#include <linux/cpu.h>
#include <linux/mutex.h>
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c
index ddff33247785..c3e165c2318f 100644
--- a/kernel/rcutorture.c
+++ b/kernel/rcutorture.c
@@ -35,14 +35,12 @@
#include <linux/sched.h>
#include <asm/atomic.h>
#include <linux/bitops.h>
-#include <linux/module.h>
#include <linux/completion.h>
#include <linux/moduleparam.h>
#include <linux/percpu.h>
#include <linux/notifier.h>
#include <linux/freezer.h>
#include <linux/cpu.h>
-#include <linux/random.h>
#include <linux/delay.h>
#include <linux/byteorder/swabb.h>
#include <linux/stat.h>
@@ -166,16 +164,14 @@ struct rcu_random_state {
/*
* Crude but fast random-number generator. Uses a linear congruential
- * generator, with occasional help from get_random_bytes().
+ * generator, with occasional help from cpu_clock().
*/
static unsigned long
rcu_random(struct rcu_random_state *rrsp)
{
- long refresh;
-
if (--rrsp->rrs_count < 0) {
- get_random_bytes(&refresh, sizeof(refresh));
- rrsp->rrs_state += refresh;
+ rrsp->rrs_state +=
+ (unsigned long)cpu_clock(raw_smp_processor_id());
rrsp->rrs_count = RCU_RANDOM_REFRESH;
}
rrsp->rrs_state = rrsp->rrs_state * RCU_RANDOM_MULT + RCU_RANDOM_ADD;
diff --git a/kernel/relay.c b/kernel/relay.c
index ad855017bc59..61134eb7a0c8 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -370,7 +370,7 @@ void relay_reset(struct rchan *chan)
if (!chan)
return;
- if (chan->is_global && chan->buf[0]) {
+ if (chan->is_global && chan->buf[0]) {
__relay_reset(chan->buf[0], 0);
return;
}
@@ -850,13 +850,13 @@ static int relay_file_read_avail(struct rchan_buf *buf, size_t read_pos)
buf->subbufs_consumed = consumed;
buf->bytes_consumed = 0;
}
-
+
produced = (produced % n_subbufs) * subbuf_size + buf->offset;
consumed = (consumed % n_subbufs) * subbuf_size + buf->bytes_consumed;
if (consumed > produced)
produced += n_subbufs * subbuf_size;
-
+
if (consumed == produced)
return 0;
diff --git a/kernel/resource.c b/kernel/resource.c
index 9bd14fd3e6de..2eb553d9b517 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -234,7 +234,7 @@ EXPORT_SYMBOL(release_resource);
* the caller must specify res->start, res->end, res->flags.
* If found, returns 0, res is overwritten, if not found, returns -1.
*/
-int find_next_system_ram(struct resource *res)
+static int find_next_system_ram(struct resource *res)
{
resource_size_t start, end;
struct resource *p;
@@ -267,6 +267,30 @@ int find_next_system_ram(struct resource *res)
res->end = p->end;
return 0;
}
+int
+walk_memory_resource(unsigned long start_pfn, unsigned long nr_pages, void *arg,
+ int (*func)(unsigned long, unsigned long, void *))
+{
+ struct resource res;
+ unsigned long pfn, len;
+ u64 orig_end;
+ int ret = -1;
+ res.start = (u64) start_pfn << PAGE_SHIFT;
+ res.end = ((u64)(start_pfn + nr_pages) << PAGE_SHIFT) - 1;
+ res.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+ orig_end = res.end;
+ while ((res.start < res.end) && (find_next_system_ram(&res) >= 0)) {
+ pfn = (unsigned long)(res.start >> PAGE_SHIFT);
+ len = (unsigned long)((res.end + 1 - res.start) >> PAGE_SHIFT);
+ ret = (*func)(pfn, len, arg);
+ if (ret)
+ break;
+ res.start = res.end + 1;
+ res.end = orig_end;
+ }
+ return ret;
+}
+
#endif
/*
diff --git a/kernel/rtmutex-debug.c b/kernel/rtmutex-debug.c
index 5aedbee014df..56d73cb8826d 100644
--- a/kernel/rtmutex-debug.c
+++ b/kernel/rtmutex-debug.c
@@ -82,17 +82,12 @@ do { \
* into the tracing code when doing error printk or
* executing a BUG():
*/
-int rt_trace_on = 1;
-
-void deadlock_trace_off(void)
-{
- rt_trace_on = 0;
-}
+static int rt_trace_on = 1;
static void printk_task(struct task_struct *p)
{
if (p)
- printk("%16s:%5d [%p, %3d]", p->comm, p->pid, p, p->prio);
+ printk("%16s:%5d [%p, %3d]", p->comm, task_pid_nr(p), p, p->prio);
else
printk("<none>");
}
@@ -157,22 +152,25 @@ void debug_rt_mutex_print_deadlock(struct rt_mutex_waiter *waiter)
printk( "[ BUG: circular locking deadlock detected! ]\n");
printk( "--------------------------------------------\n");
printk("%s/%d is deadlocking current task %s/%d\n\n",
- task->comm, task->pid, current->comm, current->pid);
+ task->comm, task_pid_nr(task),
+ current->comm, task_pid_nr(current));
printk("\n1) %s/%d is trying to acquire this lock:\n",
- current->comm, current->pid);
+ current->comm, task_pid_nr(current));
printk_lock(waiter->lock, 1);
- printk("\n2) %s/%d is blocked on this lock:\n", task->comm, task->pid);
+ printk("\n2) %s/%d is blocked on this lock:\n",
+ task->comm, task_pid_nr(task));
printk_lock(waiter->deadlock_lock, 1);
debug_show_held_locks(current);
debug_show_held_locks(task);
- printk("\n%s/%d's [blocked] stackdump:\n\n", task->comm, task->pid);
+ printk("\n%s/%d's [blocked] stackdump:\n\n",
+ task->comm, task_pid_nr(task));
show_stack(task, NULL);
printk("\n%s/%d's [current] stackdump:\n\n",
- current->comm, current->pid);
+ current->comm, task_pid_nr(current));
dump_stack();
debug_show_all_locks();
diff --git a/kernel/rtmutex.c b/kernel/rtmutex.c
index 8cd9bd2cdb34..0deef71ff8d2 100644
--- a/kernel/rtmutex.c
+++ b/kernel/rtmutex.c
@@ -185,7 +185,7 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task,
prev_max = max_lock_depth;
printk(KERN_WARNING "Maximum lock depth %d reached "
"task: %s (%d)\n", max_lock_depth,
- top_task->comm, top_task->pid);
+ top_task->comm, task_pid_nr(top_task));
}
put_task_struct(task);
diff --git a/kernel/sched.c b/kernel/sched.c
index bba57adb9504..38933cafea8a 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -44,6 +44,7 @@
#include <linux/vmalloc.h>
#include <linux/blkdev.h>
#include <linux/delay.h>
+#include <linux/pid_namespace.h>
#include <linux/smp.h>
#include <linux/threads.h>
#include <linux/timer.h>
@@ -64,6 +65,7 @@
#include <linux/pagemap.h>
#include <asm/tlb.h>
+#include <asm/irq_regs.h>
/*
* Scheduler clock - returns current time in nanosec units.
@@ -72,7 +74,7 @@
*/
unsigned long long __attribute__((weak)) sched_clock(void)
{
- return (unsigned long long)jiffies * (1000000000 / HZ);
+ return (unsigned long long)jiffies * (NSEC_PER_SEC / HZ);
}
/*
@@ -96,8 +98,8 @@ unsigned long long __attribute__((weak)) sched_clock(void)
/*
* Some helpers for converting nanosecond timing to jiffy resolution
*/
-#define NS_TO_JIFFIES(TIME) ((unsigned long)(TIME) / (1000000000 / HZ))
-#define JIFFIES_TO_NS(TIME) ((TIME) * (1000000000 / HZ))
+#define NS_TO_JIFFIES(TIME) ((unsigned long)(TIME) / (NSEC_PER_SEC / HZ))
+#define JIFFIES_TO_NS(TIME) ((TIME) * (NSEC_PER_SEC / HZ))
#define NICE_0_LOAD SCHED_LOAD_SCALE
#define NICE_0_SHIFT SCHED_LOAD_SHIFT
@@ -153,10 +155,15 @@ struct rt_prio_array {
#ifdef CONFIG_FAIR_GROUP_SCHED
+#include <linux/cgroup.h>
+
struct cfs_rq;
/* task group related information */
struct task_group {
+#ifdef CONFIG_FAIR_CGROUP_SCHED
+ struct cgroup_subsys_state css;
+#endif
/* schedulable entities of this group on each cpu */
struct sched_entity **se;
/* runqueue "owned" by this group on each cpu */
@@ -164,6 +171,7 @@ struct task_group {
unsigned long shares;
/* spinlock to serialize modification to shares */
spinlock_t lock;
+ struct rcu_head rcu;
};
/* Default task group's sched entity on each cpu */
@@ -197,6 +205,9 @@ static inline struct task_group *task_group(struct task_struct *p)
#ifdef CONFIG_FAIR_USER_SCHED
tg = p->user->tg;
+#elif defined(CONFIG_FAIR_CGROUP_SCHED)
+ tg = container_of(task_subsys_state(p, cpu_cgroup_subsys_id),
+ struct task_group, css);
#else
tg = &init_task_group;
#endif
@@ -205,15 +216,15 @@ static inline struct task_group *task_group(struct task_struct *p)
}
/* Change a task's cfs_rq and parent entity if it moves across CPUs/groups */
-static inline void set_task_cfs_rq(struct task_struct *p)
+static inline void set_task_cfs_rq(struct task_struct *p, unsigned int cpu)
{
- p->se.cfs_rq = task_group(p)->cfs_rq[task_cpu(p)];
- p->se.parent = task_group(p)->se[task_cpu(p)];
+ p->se.cfs_rq = task_group(p)->cfs_rq[cpu];
+ p->se.parent = task_group(p)->se[cpu];
}
#else
-static inline void set_task_cfs_rq(struct task_struct *p) { }
+static inline void set_task_cfs_rq(struct task_struct *p, unsigned int cpu) { }
#endif /* CONFIG_FAIR_GROUP_SCHED */
@@ -247,7 +258,6 @@ struct cfs_rq {
*/
struct list_head leaf_cfs_rq_list; /* Better name : task_cfs_rq_list? */
struct task_group *tg; /* group that "owns" this runqueue */
- struct rcu_head rcu;
#endif
};
@@ -266,7 +276,8 @@ struct rt_rq {
* acquire operations must be ordered by ascending &runqueue.
*/
struct rq {
- spinlock_t lock; /* runqueue lock */
+ /* runqueue lock: */
+ spinlock_t lock;
/*
* nr_running and cpu_load should be in the same cacheline because
@@ -279,13 +290,15 @@ struct rq {
#ifdef CONFIG_NO_HZ
unsigned char in_nohz_recently;
#endif
- struct load_weight load; /* capture load from *all* tasks on this cpu */
+ /* capture load from *all* tasks on this cpu: */
+ struct load_weight load;
unsigned long nr_load_updates;
u64 nr_switches;
struct cfs_rq cfs;
#ifdef CONFIG_FAIR_GROUP_SCHED
- struct list_head leaf_cfs_rq_list; /* list of leaf cfs_rq on this cpu */
+ /* list of leaf cfs_rq on this cpu: */
+ struct list_head leaf_cfs_rq_list;
#endif
struct rt_rq rt;
@@ -317,7 +330,8 @@ struct rq {
/* For active balancing */
int active_balance;
int push_cpu;
- int cpu; /* cpu of this runqueue */
+ /* cpu of this runqueue: */
+ int cpu;
struct task_struct *migration_thread;
struct list_head migration_queue;
@@ -328,22 +342,22 @@ struct rq {
struct sched_info rq_sched_info;
/* sys_sched_yield() stats */
- unsigned long yld_exp_empty;
- unsigned long yld_act_empty;
- unsigned long yld_both_empty;
- unsigned long yld_count;
+ unsigned int yld_exp_empty;
+ unsigned int yld_act_empty;
+ unsigned int yld_both_empty;
+ unsigned int yld_count;
/* schedule() stats */
- unsigned long sched_switch;
- unsigned long sched_count;
- unsigned long sched_goidle;
+ unsigned int sched_switch;
+ unsigned int sched_count;
+ unsigned int sched_goidle;
/* try_to_wake_up() stats */
- unsigned long ttwu_count;
- unsigned long ttwu_local;
+ unsigned int ttwu_count;
+ unsigned int ttwu_local;
/* BKL stats */
- unsigned long bkl_count;
+ unsigned int bkl_count;
#endif
struct lock_class_key rq_lock_key;
};
@@ -441,24 +455,28 @@ static void update_rq_clock(struct rq *rq)
*/
enum {
SCHED_FEAT_NEW_FAIR_SLEEPERS = 1,
- SCHED_FEAT_START_DEBIT = 2,
- SCHED_FEAT_TREE_AVG = 4,
- SCHED_FEAT_APPROX_AVG = 8,
- SCHED_FEAT_WAKEUP_PREEMPT = 16,
- SCHED_FEAT_PREEMPT_RESTRICT = 32,
+ SCHED_FEAT_WAKEUP_PREEMPT = 2,
+ SCHED_FEAT_START_DEBIT = 4,
+ SCHED_FEAT_TREE_AVG = 8,
+ SCHED_FEAT_APPROX_AVG = 16,
};
const_debug unsigned int sysctl_sched_features =
- SCHED_FEAT_NEW_FAIR_SLEEPERS *1 |
- SCHED_FEAT_START_DEBIT *1 |
- SCHED_FEAT_TREE_AVG *0 |
- SCHED_FEAT_APPROX_AVG *0 |
- SCHED_FEAT_WAKEUP_PREEMPT *1 |
- SCHED_FEAT_PREEMPT_RESTRICT *1;
+ SCHED_FEAT_NEW_FAIR_SLEEPERS * 1 |
+ SCHED_FEAT_WAKEUP_PREEMPT * 1 |
+ SCHED_FEAT_START_DEBIT * 1 |
+ SCHED_FEAT_TREE_AVG * 0 |
+ SCHED_FEAT_APPROX_AVG * 0;
#define sched_feat(x) (sysctl_sched_features & SCHED_FEAT_##x)
/*
+ * Number of tasks to iterate in a single balance run.
+ * Limited because this is done with IRQs disabled.
+ */
+const_debug unsigned int sysctl_sched_nr_migrate = 32;
+
+/*
* For kernel-internal use: high-speed (but slightly incorrect) per-cpu
* clock constructed from sched_clock():
*/
@@ -823,11 +841,18 @@ struct rq_iterator {
struct task_struct *(*next)(void *);
};
-static int balance_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
- unsigned long max_nr_move, unsigned long max_load_move,
- struct sched_domain *sd, enum cpu_idle_type idle,
- int *all_pinned, unsigned long *load_moved,
- int *this_best_prio, struct rq_iterator *iterator);
+#ifdef CONFIG_SMP
+static unsigned long
+balance_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
+ unsigned long max_load_move, struct sched_domain *sd,
+ enum cpu_idle_type idle, int *all_pinned,
+ int *this_best_prio, struct rq_iterator *iterator);
+
+static int
+iter_move_one_task(struct rq *this_rq, int this_cpu, struct rq *busiest,
+ struct sched_domain *sd, enum cpu_idle_type idle,
+ struct rq_iterator *iterator);
+#endif
#include "sched_stats.h"
#include "sched_idletask.c"
@@ -997,10 +1022,16 @@ unsigned long weighted_cpuload(const int cpu)
static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu)
{
+ set_task_cfs_rq(p, cpu);
#ifdef CONFIG_SMP
+ /*
+ * After ->cpu is set up to a new value, task_rq_lock(p, ...) can be
+ * successfuly executed on another CPU. We must ensure that updates of
+ * per-task data have been completed by this moment.
+ */
+ smp_wmb();
task_thread_info(p)->cpu = cpu;
#endif
- set_task_cfs_rq(p);
}
#ifdef CONFIG_SMP
@@ -1712,7 +1743,7 @@ void fastcall wake_up_new_task(struct task_struct *p, unsigned long clone_flags)
p->prio = effective_prio(p);
- if (!p->sched_class->task_new || !current->se.on_rq || !rq->cfs.curr) {
+ if (!p->sched_class->task_new || !current->se.on_rq) {
activate_task(rq, p, 0);
} else {
/*
@@ -1871,7 +1902,7 @@ asmlinkage void schedule_tail(struct task_struct *prev)
preempt_enable();
#endif
if (current->set_child_tid)
- put_user(current->pid, current->set_child_tid);
+ put_user(task_pid_vnr(current), current->set_child_tid);
}
/*
@@ -2209,17 +2240,17 @@ int can_migrate_task(struct task_struct *p, struct rq *rq, int this_cpu,
return 1;
}
-static int balance_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
- unsigned long max_nr_move, unsigned long max_load_move,
- struct sched_domain *sd, enum cpu_idle_type idle,
- int *all_pinned, unsigned long *load_moved,
- int *this_best_prio, struct rq_iterator *iterator)
+static unsigned long
+balance_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
+ unsigned long max_load_move, struct sched_domain *sd,
+ enum cpu_idle_type idle, int *all_pinned,
+ int *this_best_prio, struct rq_iterator *iterator)
{
- int pulled = 0, pinned = 0, skip_for_load;
+ int loops = 0, pulled = 0, pinned = 0, skip_for_load;
struct task_struct *p;
long rem_load_move = max_load_move;
- if (max_nr_move == 0 || max_load_move == 0)
+ if (max_load_move == 0)
goto out;
pinned = 1;
@@ -2229,10 +2260,10 @@ static int balance_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
*/
p = iterator->start(iterator->arg);
next:
- if (!p)
+ if (!p || loops++ > sysctl_sched_nr_migrate)
goto out;
/*
- * To help distribute high priority tasks accross CPUs we don't
+ * To help distribute high priority tasks across CPUs we don't
* skip a task if it will be the highest priority task (i.e. smallest
* prio value) on its new queue regardless of its load weight
*/
@@ -2249,10 +2280,9 @@ next:
rem_load_move -= p->se.load.weight;
/*
- * We only want to steal up to the prescribed number of tasks
- * and the prescribed amount of weighted load.
+ * We only want to steal up to the prescribed amount of weighted load.
*/
- if (pulled < max_nr_move && rem_load_move > 0) {
+ if (rem_load_move > 0) {
if (p->prio < *this_best_prio)
*this_best_prio = p->prio;
p = iterator->next(iterator->arg);
@@ -2260,7 +2290,7 @@ next:
}
out:
/*
- * Right now, this is the only place pull_task() is called,
+ * Right now, this is one of only two places pull_task() is called,
* so we can safely collect pull_task() stats here rather than
* inside pull_task().
*/
@@ -2268,8 +2298,8 @@ out:
if (all_pinned)
*all_pinned = pinned;
- *load_moved = max_load_move - rem_load_move;
- return pulled;
+
+ return max_load_move - rem_load_move;
}
/*
@@ -2291,7 +2321,7 @@ static int move_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
do {
total_load_moved +=
class->load_balance(this_rq, this_cpu, busiest,
- ULONG_MAX, max_load_move - total_load_moved,
+ max_load_move - total_load_moved,
sd, idle, all_pinned, &this_best_prio);
class = class->next;
} while (class && max_load_move > total_load_moved);
@@ -2299,6 +2329,32 @@ static int move_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
return total_load_moved > 0;
}
+static int
+iter_move_one_task(struct rq *this_rq, int this_cpu, struct rq *busiest,
+ struct sched_domain *sd, enum cpu_idle_type idle,
+ struct rq_iterator *iterator)
+{
+ struct task_struct *p = iterator->start(iterator->arg);
+ int pinned = 0;
+
+ while (p) {
+ if (can_migrate_task(p, busiest, this_cpu, sd, idle, &pinned)) {
+ pull_task(busiest, p, this_rq, this_cpu);
+ /*
+ * Right now, this is only the second place pull_task()
+ * is called, so we can safely collect pull_task()
+ * stats here rather than inside pull_task().
+ */
+ schedstat_inc(sd, lb_gained[idle]);
+
+ return 1;
+ }
+ p = iterator->next(iterator->arg);
+ }
+
+ return 0;
+}
+
/*
* move_one_task tries to move exactly one task from busiest to this_rq, as
* part of active balancing operations within "domain".
@@ -2310,12 +2366,9 @@ static int move_one_task(struct rq *this_rq, int this_cpu, struct rq *busiest,
struct sched_domain *sd, enum cpu_idle_type idle)
{
const struct sched_class *class;
- int this_best_prio = MAX_PRIO;
for (class = sched_class_highest; class; class = class->next)
- if (class->load_balance(this_rq, this_cpu, busiest,
- 1, ULONG_MAX, sd, idle, NULL,
- &this_best_prio))
+ if (class->move_one_task(this_rq, this_cpu, busiest, sd, idle))
return 1;
return 0;
@@ -2336,7 +2389,7 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
unsigned long max_pull;
unsigned long busiest_load_per_task, busiest_nr_running;
unsigned long this_load_per_task, this_nr_running;
- int load_idx;
+ int load_idx, group_imb = 0;
#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
int power_savings_balance = 1;
unsigned long leader_nr_running = 0, min_load_per_task = 0;
@@ -2355,9 +2408,10 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
load_idx = sd->idle_idx;
do {
- unsigned long load, group_capacity;
+ unsigned long load, group_capacity, max_cpu_load, min_cpu_load;
int local_group;
int i;
+ int __group_imb = 0;
unsigned int balance_cpu = -1, first_idle_cpu = 0;
unsigned long sum_nr_running, sum_weighted_load;
@@ -2368,6 +2422,8 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
/* Tally up the load of all CPUs in the group */
sum_weighted_load = sum_nr_running = avg_load = 0;
+ max_cpu_load = 0;
+ min_cpu_load = ~0UL;
for_each_cpu_mask(i, group->cpumask) {
struct rq *rq;
@@ -2388,8 +2444,13 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
}
load = target_load(i, load_idx);
- } else
+ } else {
load = source_load(i, load_idx);
+ if (load > max_cpu_load)
+ max_cpu_load = load;
+ if (min_cpu_load > load)
+ min_cpu_load = load;
+ }
avg_load += load;
sum_nr_running += rq->nr_running;
@@ -2415,6 +2476,9 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
avg_load = sg_div_cpu_power(group,
avg_load * SCHED_LOAD_SCALE);
+ if ((max_cpu_load - min_cpu_load) > SCHED_LOAD_SCALE)
+ __group_imb = 1;
+
group_capacity = group->__cpu_power / SCHED_LOAD_SCALE;
if (local_group) {
@@ -2423,11 +2487,12 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
this_nr_running = sum_nr_running;
this_load_per_task = sum_weighted_load;
} else if (avg_load > max_load &&
- sum_nr_running > group_capacity) {
+ (sum_nr_running > group_capacity || __group_imb)) {
max_load = avg_load;
busiest = group;
busiest_nr_running = sum_nr_running;
busiest_load_per_task = sum_weighted_load;
+ group_imb = __group_imb;
}
#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
@@ -2499,6 +2564,9 @@ group_next:
goto out_balanced;
busiest_load_per_task /= busiest_nr_running;
+ if (group_imb)
+ busiest_load_per_task = min(busiest_load_per_task, avg_load);
+
/*
* We're trying to get all the cpus to the average_load, so we don't
* want to push ourselves above the average load, nor do we wish to
@@ -3237,18 +3305,6 @@ static inline void idle_balance(int cpu, struct rq *rq)
{
}
-/* Avoid "used but not defined" warning on UP */
-static int balance_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
- unsigned long max_nr_move, unsigned long max_load_move,
- struct sched_domain *sd, enum cpu_idle_type idle,
- int *all_pinned, unsigned long *load_moved,
- int *this_best_prio, struct rq_iterator *iterator)
-{
- *load_moved = 0;
-
- return 0;
-}
-
#endif
DEFINE_PER_CPU(struct kernel_stat, kstat);
@@ -3281,7 +3337,6 @@ unsigned long long task_sched_runtime(struct task_struct *p)
/*
* Account user cpu time to a process.
* @p: the process that the cpu time gets accounted to
- * @hardirq_offset: the offset to subtract from hardirq_count()
* @cputime: the cpu time spent in user space since the last update
*/
void account_user_time(struct task_struct *p, cputime_t cputime)
@@ -3304,7 +3359,7 @@ void account_user_time(struct task_struct *p, cputime_t cputime)
* @p: the process that the cpu time gets accounted to
* @cputime: the cpu time spent in virtual machine since the last update
*/
-void account_guest_time(struct task_struct *p, cputime_t cputime)
+static void account_guest_time(struct task_struct *p, cputime_t cputime)
{
cputime64_t tmp;
struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
@@ -3319,6 +3374,16 @@ void account_guest_time(struct task_struct *p, cputime_t cputime)
}
/*
+ * Account scaled user cpu time to a process.
+ * @p: the process that the cpu time gets accounted to
+ * @cputime: the cpu time spent in user space since the last update
+ */
+void account_user_time_scaled(struct task_struct *p, cputime_t cputime)
+{
+ p->utimescaled = cputime_add(p->utimescaled, cputime);
+}
+
+/*
* Account system cpu time to a process.
* @p: the process that the cpu time gets accounted to
* @hardirq_offset: the offset to subtract from hardirq_count()
@@ -3331,11 +3396,8 @@ void account_system_time(struct task_struct *p, int hardirq_offset,
struct rq *rq = this_rq();
cputime64_t tmp;
- if (p->flags & PF_VCPU) {
- account_guest_time(p, cputime);
- p->flags &= ~PF_VCPU;
- return;
- }
+ if ((p->flags & PF_VCPU) && (irq_count() - hardirq_offset == 0))
+ return account_guest_time(p, cputime);
p->stime = cputime_add(p->stime, cputime);
@@ -3356,6 +3418,17 @@ void account_system_time(struct task_struct *p, int hardirq_offset,
}
/*
+ * Account scaled system cpu time to a process.
+ * @p: the process that the cpu time gets accounted to
+ * @hardirq_offset: the offset to subtract from hardirq_count()
+ * @cputime: the cpu time spent in kernel space since the last update
+ */
+void account_system_time_scaled(struct task_struct *p, cputime_t cputime)
+{
+ p->stimescaled = cputime_add(p->stimescaled, cputime);
+}
+
+/*
* Account for involuntary wait time.
* @p: the process from which the cpu time has been stolen
* @steal: the cpu time spent in involuntary wait
@@ -3452,12 +3525,19 @@ EXPORT_SYMBOL(sub_preempt_count);
*/
static noinline void __schedule_bug(struct task_struct *prev)
{
- printk(KERN_ERR "BUG: scheduling while atomic: %s/0x%08x/%d\n",
- prev->comm, preempt_count(), prev->pid);
+ struct pt_regs *regs = get_irq_regs();
+
+ printk(KERN_ERR "BUG: scheduling while atomic: %s/%d/0x%08x\n",
+ prev->comm, prev->pid, preempt_count());
+
debug_show_held_locks(prev);
if (irqs_disabled())
print_irqtrace_events(prev);
- dump_stack();
+
+ if (regs)
+ show_regs(regs);
+ else
+ dump_stack();
}
/*
@@ -3765,7 +3845,7 @@ __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr_exclusive)
}
EXPORT_SYMBOL_GPL(__wake_up_sync); /* For internal use only */
-void fastcall complete(struct completion *x)
+void complete(struct completion *x)
{
unsigned long flags;
@@ -3777,7 +3857,7 @@ void fastcall complete(struct completion *x)
}
EXPORT_SYMBOL(complete);
-void fastcall complete_all(struct completion *x)
+void complete_all(struct completion *x)
{
unsigned long flags;
@@ -3829,13 +3909,13 @@ wait_for_common(struct completion *x, long timeout, int state)
return timeout;
}
-void fastcall __sched wait_for_completion(struct completion *x)
+void __sched wait_for_completion(struct completion *x)
{
wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_UNINTERRUPTIBLE);
}
EXPORT_SYMBOL(wait_for_completion);
-unsigned long fastcall __sched
+unsigned long __sched
wait_for_completion_timeout(struct completion *x, unsigned long timeout)
{
return wait_for_common(x, timeout, TASK_UNINTERRUPTIBLE);
@@ -3844,11 +3924,14 @@ EXPORT_SYMBOL(wait_for_completion_timeout);
int __sched wait_for_completion_interruptible(struct completion *x)
{
- return wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_INTERRUPTIBLE);
+ long t = wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_INTERRUPTIBLE);
+ if (t == -ERESTARTSYS)
+ return t;
+ return 0;
}
EXPORT_SYMBOL(wait_for_completion_interruptible);
-unsigned long fastcall __sched
+unsigned long __sched
wait_for_completion_interruptible_timeout(struct completion *x,
unsigned long timeout)
{
@@ -4116,7 +4199,7 @@ struct task_struct *idle_task(int cpu)
*/
static struct task_struct *find_process_by_pid(pid_t pid)
{
- return pid ? find_task_by_pid(pid) : current;
+ return pid ? find_task_by_vpid(pid) : current;
}
/* Actually do priority change: must hold rq lock. */
@@ -4419,8 +4502,21 @@ long sched_setaffinity(pid_t pid, cpumask_t new_mask)
cpus_allowed = cpuset_cpus_allowed(p);
cpus_and(new_mask, new_mask, cpus_allowed);
+ again:
retval = set_cpus_allowed(p, new_mask);
+ if (!retval) {
+ cpus_allowed = cpuset_cpus_allowed(p);
+ if (!cpus_subset(new_mask, cpus_allowed)) {
+ /*
+ * We must have raced with a concurrent cpuset
+ * update. Just reset the cpus_allowed to the
+ * cpuset's cpus_allowed
+ */
+ new_mask = cpus_allowed;
+ goto again;
+ }
+ }
out_unlock:
put_task_struct(p);
mutex_unlock(&sched_hotcpu_mutex);
@@ -4779,18 +4875,18 @@ static void show_task(struct task_struct *p)
unsigned state;
state = p->state ? __ffs(p->state) + 1 : 0;
- printk("%-13.13s %c", p->comm,
+ printk(KERN_INFO "%-13.13s %c", p->comm,
state < sizeof(stat_nam) - 1 ? stat_nam[state] : '?');
#if BITS_PER_LONG == 32
if (state == TASK_RUNNING)
- printk(" running ");
+ printk(KERN_CONT " running ");
else
- printk(" %08lx ", thread_saved_pc(p));
+ printk(KERN_CONT " %08lx ", thread_saved_pc(p));
#else
if (state == TASK_RUNNING)
- printk(" running task ");
+ printk(KERN_CONT " running task ");
else
- printk(" %016lx ", thread_saved_pc(p));
+ printk(KERN_CONT " %016lx ", thread_saved_pc(p));
#endif
#ifdef CONFIG_DEBUG_STACK_USAGE
{
@@ -4800,7 +4896,8 @@ static void show_task(struct task_struct *p)
free = (unsigned long)n - (unsigned long)end_of_stack(p);
}
#endif
- printk("%5lu %5d %6d\n", free, p->pid, p->parent->pid);
+ printk(KERN_CONT "%5lu %5d %6d\n", free,
+ task_pid_nr(p), task_pid_nr(p->parent));
if (state != TASK_RUNNING)
show_stack(p, NULL);
@@ -4894,6 +4991,32 @@ void __cpuinit init_idle(struct task_struct *idle, int cpu)
*/
cpumask_t nohz_cpu_mask = CPU_MASK_NONE;
+/*
+ * Increase the granularity value when there are more CPUs,
+ * because with more CPUs the 'effective latency' as visible
+ * to users decreases. But the relationship is not linear,
+ * so pick a second-best guess by going with the log2 of the
+ * number of CPUs.
+ *
+ * This idea comes from the SD scheduler of Con Kolivas:
+ */
+static inline void sched_init_granularity(void)
+{
+ unsigned int factor = 1 + ilog2(num_online_cpus());
+ const unsigned long limit = 200000000;
+
+ sysctl_sched_min_granularity *= factor;
+ if (sysctl_sched_min_granularity > limit)
+ sysctl_sched_min_granularity = limit;
+
+ sysctl_sched_latency *= factor;
+ if (sysctl_sched_latency > limit)
+ sysctl_sched_latency = limit;
+
+ sysctl_sched_wakeup_granularity *= factor;
+ sysctl_sched_batch_wakeup_granularity *= factor;
+}
+
#ifdef CONFIG_SMP
/*
* This is how migration works:
@@ -5060,8 +5183,19 @@ wait_to_die:
}
#ifdef CONFIG_HOTPLUG_CPU
+
+static int __migrate_task_irq(struct task_struct *p, int src_cpu, int dest_cpu)
+{
+ int ret;
+
+ local_irq_disable();
+ ret = __migrate_task(p, src_cpu, dest_cpu);
+ local_irq_enable();
+ return ret;
+}
+
/*
- * Figure out where task on dead CPU should go, use force if neccessary.
+ * Figure out where task on dead CPU should go, use force if necessary.
* NOTE: interrupts should be disabled by the caller
*/
static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *p)
@@ -5083,8 +5217,16 @@ static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *p)
/* No more Mr. Nice Guy. */
if (dest_cpu == NR_CPUS) {
+ cpumask_t cpus_allowed = cpuset_cpus_allowed_locked(p);
+ /*
+ * Try to stay on the same cpuset, where the
+ * current cpuset may be a subset of all cpus.
+ * The cpuset_cpus_allowed_locked() variant of
+ * cpuset_cpus_allowed() will not block. It must be
+ * called within calls to cpuset_lock/cpuset_unlock.
+ */
rq = task_rq_lock(p, &flags);
- cpus_setall(p->cpus_allowed);
+ p->cpus_allowed = cpus_allowed;
dest_cpu = any_online_cpu(p->cpus_allowed);
task_rq_unlock(rq, &flags);
@@ -5096,9 +5238,9 @@ static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *p)
if (p->mm && printk_ratelimit())
printk(KERN_INFO "process %d (%s) no "
"longer affine to cpu%d\n",
- p->pid, p->comm, dead_cpu);
+ task_pid_nr(p), p->comm, dead_cpu);
}
- } while (!__migrate_task(p, dead_cpu, dest_cpu));
+ } while (!__migrate_task_irq(p, dead_cpu, dest_cpu));
}
/*
@@ -5126,7 +5268,7 @@ static void migrate_live_tasks(int src_cpu)
{
struct task_struct *p, *t;
- write_lock_irq(&tasklist_lock);
+ read_lock(&tasklist_lock);
do_each_thread(t, p) {
if (p == current)
@@ -5136,27 +5278,13 @@ static void migrate_live_tasks(int src_cpu)
move_task_off_dead_cpu(src_cpu, p);
} while_each_thread(t, p);
- write_unlock_irq(&tasklist_lock);
-}
-
-/*
- * activate_idle_task - move idle task to the _front_ of runqueue.
- */
-static void activate_idle_task(struct task_struct *p, struct rq *rq)
-{
- update_rq_clock(rq);
-
- if (p->state == TASK_UNINTERRUPTIBLE)
- rq->nr_uninterruptible--;
-
- enqueue_task(rq, p, 0);
- inc_nr_running(p, rq);
+ read_unlock(&tasklist_lock);
}
/*
* Schedules idle task to be the next runnable task on current CPU.
- * It does so by boosting its priority to highest possible and adding it to
- * the _front_ of the runqueue. Used by CPU offline code.
+ * It does so by boosting its priority to highest possible.
+ * Used by CPU offline code.
*/
void sched_idle_next(void)
{
@@ -5176,8 +5304,8 @@ void sched_idle_next(void)
__setscheduler(rq, p, SCHED_FIFO, MAX_RT_PRIO-1);
- /* Add idle task to the _front_ of its priority queue: */
- activate_idle_task(p, rq);
+ update_rq_clock(rq);
+ activate_task(rq, p, 0);
spin_unlock_irqrestore(&rq->lock, flags);
}
@@ -5203,7 +5331,7 @@ static void migrate_dead(unsigned int dead_cpu, struct task_struct *p)
struct rq *rq = cpu_rq(dead_cpu);
/* Must be exiting, otherwise would be on tasklist. */
- BUG_ON(p->exit_state != EXIT_ZOMBIE && p->exit_state != EXIT_DEAD);
+ BUG_ON(!p->exit_state);
/* Cannot have done final schedule yet: would have vanished. */
BUG_ON(p->state == TASK_DEAD);
@@ -5214,11 +5342,10 @@ static void migrate_dead(unsigned int dead_cpu, struct task_struct *p)
* Drop lock around migration; if someone else moves it,
* that's OK. No task can be added to this CPU, so iteration is
* fine.
- * NOTE: interrupts should be left disabled --dev@
*/
- spin_unlock(&rq->lock);
+ spin_unlock_irq(&rq->lock);
move_task_off_dead_cpu(dead_cpu, p);
- spin_lock(&rq->lock);
+ spin_lock_irq(&rq->lock);
put_task_struct(p);
}
@@ -5249,7 +5376,7 @@ static struct ctl_table sd_ctl_dir[] = {
.procname = "sched_domain",
.mode = 0555,
},
- {0,},
+ {0, },
};
static struct ctl_table sd_ctl_root[] = {
@@ -5259,7 +5386,7 @@ static struct ctl_table sd_ctl_root[] = {
.mode = 0555,
.child = sd_ctl_dir,
},
- {0,},
+ {0, },
};
static struct ctl_table *sd_alloc_ctl_entry(int n)
@@ -5272,11 +5399,20 @@ static struct ctl_table *sd_alloc_ctl_entry(int n)
static void sd_free_ctl_entry(struct ctl_table **tablep)
{
- struct ctl_table *entry = *tablep;
+ struct ctl_table *entry;
- for (entry = *tablep; entry->procname; entry++)
+ /*
+ * In the intermediate directories, both the child directory and
+ * procname are dynamically allocated and could fail but the mode
+ * will always be set. In the lowest directory the names are
+ * static strings and all have proc handlers.
+ */
+ for (entry = *tablep; entry->mode; entry++) {
if (entry->child)
sd_free_ctl_entry(&entry->child);
+ if (entry->proc_handler == NULL)
+ kfree(entry->procname);
+ }
kfree(*tablep);
*tablep = NULL;
@@ -5330,7 +5466,7 @@ sd_alloc_ctl_domain_table(struct sched_domain *sd)
return table;
}
-static ctl_table *sd_alloc_ctl_cpu_table(int cpu)
+static ctl_table * sd_alloc_ctl_cpu_table(int cpu)
{
struct ctl_table *entry, *table;
struct sched_domain *sd;
@@ -5362,11 +5498,12 @@ static void register_sched_domain_sysctl(void)
struct ctl_table *entry = sd_alloc_ctl_entry(cpu_num + 1);
char buf[32];
+ WARN_ON(sd_ctl_dir[0].child);
+ sd_ctl_dir[0].child = entry;
+
if (entry == NULL)
return;
- sd_ctl_dir[0].child = entry;
-
for_each_online_cpu(i) {
snprintf(buf, 32, "cpu%d", i);
entry->procname = kstrdup(buf, GFP_KERNEL);
@@ -5374,14 +5511,19 @@ static void register_sched_domain_sysctl(void)
entry->child = sd_alloc_ctl_cpu_table(i);
entry++;
}
+
+ WARN_ON(sd_sysctl_header);
sd_sysctl_header = register_sysctl_table(sd_ctl_root);
}
+/* may be called multiple times per register */
static void unregister_sched_domain_sysctl(void)
{
- unregister_sysctl_table(sd_sysctl_header);
+ if (sd_sysctl_header)
+ unregister_sysctl_table(sd_sysctl_header);
sd_sysctl_header = NULL;
- sd_free_ctl_entry(&sd_ctl_dir[0].child);
+ if (sd_ctl_dir[0].child)
+ sd_free_ctl_entry(&sd_ctl_dir[0].child);
}
#else
static void register_sched_domain_sysctl(void)
@@ -5424,7 +5566,7 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu)
case CPU_ONLINE:
case CPU_ONLINE_FROZEN:
- /* Strictly unneccessary, as first user will wake it. */
+ /* Strictly unnecessary, as first user will wake it. */
wake_up_process(cpu_rq(cpu)->migration_thread);
break;
@@ -5442,19 +5584,21 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu)
case CPU_DEAD:
case CPU_DEAD_FROZEN:
+ cpuset_lock(); /* around calls to cpuset_cpus_allowed_lock() */
migrate_live_tasks(cpu);
rq = cpu_rq(cpu);
kthread_stop(rq->migration_thread);
rq->migration_thread = NULL;
/* Idle task back to normal (off runqueue, low prio) */
- rq = task_rq_lock(rq->idle, &flags);
+ spin_lock_irq(&rq->lock);
update_rq_clock(rq);
deactivate_task(rq, rq->idle, 0);
rq->idle->static_prio = MAX_PRIO;
__setscheduler(rq, rq->idle, SCHED_NORMAL, 0);
rq->idle->sched_class = &idle_sched_class;
migrate_dead_tasks(cpu);
- task_rq_unlock(rq, &flags);
+ spin_unlock_irq(&rq->lock);
+ cpuset_unlock();
migrate_nr_uninterruptible(rq);
BUG_ON(rq->nr_running != 0);
@@ -5488,7 +5632,7 @@ static struct notifier_block __cpuinitdata migration_notifier = {
.priority = 10
};
-int __init migration_init(void)
+void __init migration_init(void)
{
void *cpu = (void *)(long)smp_processor_id();
int err;
@@ -5498,8 +5642,6 @@ int __init migration_init(void)
BUG_ON(err == NOTIFY_BAD);
migration_call(&migration_notifier, CPU_ONLINE, cpu);
register_cpu_notifier(&migration_notifier);
-
- return 0;
}
#endif
@@ -5510,101 +5652,101 @@ int nr_cpu_ids __read_mostly = NR_CPUS;
EXPORT_SYMBOL(nr_cpu_ids);
#ifdef CONFIG_SCHED_DEBUG
-static void sched_domain_debug(struct sched_domain *sd, int cpu)
+
+static int sched_domain_debug_one(struct sched_domain *sd, int cpu, int level)
{
- int level = 0;
+ struct sched_group *group = sd->groups;
+ cpumask_t groupmask;
+ char str[NR_CPUS];
- if (!sd) {
- printk(KERN_DEBUG "CPU%d attaching NULL sched-domain.\n", cpu);
- return;
+ cpumask_scnprintf(str, NR_CPUS, sd->span);
+ cpus_clear(groupmask);
+
+ printk(KERN_DEBUG "%*s domain %d: ", level, "", level);
+
+ if (!(sd->flags & SD_LOAD_BALANCE)) {
+ printk("does not load-balance\n");
+ if (sd->parent)
+ printk(KERN_ERR "ERROR: !SD_LOAD_BALANCE domain"
+ " has parent");
+ return -1;
}
- printk(KERN_DEBUG "CPU%d attaching sched-domain:\n", cpu);
+ printk(KERN_CONT "span %s\n", str);
+ if (!cpu_isset(cpu, sd->span)) {
+ printk(KERN_ERR "ERROR: domain->span does not contain "
+ "CPU%d\n", cpu);
+ }
+ if (!cpu_isset(cpu, group->cpumask)) {
+ printk(KERN_ERR "ERROR: domain->groups does not contain"
+ " CPU%d\n", cpu);
+ }
+
+ printk(KERN_DEBUG "%*s groups:", level + 1, "");
do {
- int i;
- char str[NR_CPUS];
- struct sched_group *group = sd->groups;
- cpumask_t groupmask;
-
- cpumask_scnprintf(str, NR_CPUS, sd->span);
- cpus_clear(groupmask);
-
- printk(KERN_DEBUG);
- for (i = 0; i < level + 1; i++)
- printk(" ");
- printk("domain %d: ", level);
-
- if (!(sd->flags & SD_LOAD_BALANCE)) {
- printk("does not load-balance\n");
- if (sd->parent)
- printk(KERN_ERR "ERROR: !SD_LOAD_BALANCE domain"
- " has parent");
+ if (!group) {
+ printk("\n");
+ printk(KERN_ERR "ERROR: group is NULL\n");
break;
}
- printk("span %s\n", str);
+ if (!group->__cpu_power) {
+ printk(KERN_CONT "\n");
+ printk(KERN_ERR "ERROR: domain->cpu_power not "
+ "set\n");
+ break;
+ }
- if (!cpu_isset(cpu, sd->span))
- printk(KERN_ERR "ERROR: domain->span does not contain "
- "CPU%d\n", cpu);
- if (!cpu_isset(cpu, group->cpumask))
- printk(KERN_ERR "ERROR: domain->groups does not contain"
- " CPU%d\n", cpu);
+ if (!cpus_weight(group->cpumask)) {
+ printk(KERN_CONT "\n");
+ printk(KERN_ERR "ERROR: empty group\n");
+ break;
+ }
- printk(KERN_DEBUG);
- for (i = 0; i < level + 2; i++)
- printk(" ");
- printk("groups:");
- do {
- if (!group) {
- printk("\n");
- printk(KERN_ERR "ERROR: group is NULL\n");
- break;
- }
+ if (cpus_intersects(groupmask, group->cpumask)) {
+ printk(KERN_CONT "\n");
+ printk(KERN_ERR "ERROR: repeated CPUs\n");
+ break;
+ }
- if (!group->__cpu_power) {
- printk("\n");
- printk(KERN_ERR "ERROR: domain->cpu_power not "
- "set\n");
- break;
- }
+ cpus_or(groupmask, groupmask, group->cpumask);
- if (!cpus_weight(group->cpumask)) {
- printk("\n");
- printk(KERN_ERR "ERROR: empty group\n");
- break;
- }
+ cpumask_scnprintf(str, NR_CPUS, group->cpumask);
+ printk(KERN_CONT " %s", str);
- if (cpus_intersects(groupmask, group->cpumask)) {
- printk("\n");
- printk(KERN_ERR "ERROR: repeated CPUs\n");
- break;
- }
+ group = group->next;
+ } while (group != sd->groups);
+ printk(KERN_CONT "\n");
- cpus_or(groupmask, groupmask, group->cpumask);
+ if (!cpus_equal(sd->span, groupmask))
+ printk(KERN_ERR "ERROR: groups don't span domain->span\n");
- cpumask_scnprintf(str, NR_CPUS, group->cpumask);
- printk(" %s", str);
+ if (sd->parent && !cpus_subset(groupmask, sd->parent->span))
+ printk(KERN_ERR "ERROR: parent span is not a superset "
+ "of domain->span\n");
+ return 0;
+}
+
+static void sched_domain_debug(struct sched_domain *sd, int cpu)
+{
+ int level = 0;
- group = group->next;
- } while (group != sd->groups);
- printk("\n");
+ if (!sd) {
+ printk(KERN_DEBUG "CPU%d attaching NULL sched-domain.\n", cpu);
+ return;
+ }
- if (!cpus_equal(sd->span, groupmask))
- printk(KERN_ERR "ERROR: groups don't span "
- "domain->span\n");
+ printk(KERN_DEBUG "CPU%d attaching sched-domain:\n", cpu);
+ for (;;) {
+ if (sched_domain_debug_one(sd, cpu, level))
+ break;
level++;
sd = sd->parent;
if (!sd)
- continue;
-
- if (!cpus_subset(groupmask, sd->span))
- printk(KERN_ERR "ERROR: parent span is not a superset "
- "of domain->span\n");
-
- } while (sd);
+ break;
+ }
}
#else
# define sched_domain_debug(sd, cpu) do { } while (0)
@@ -5869,7 +6011,7 @@ static int cpu_to_core_group(int cpu, const cpumask_t *cpu_map,
struct sched_group **sg)
{
int group;
- cpumask_t mask = cpu_sibling_map[cpu];
+ cpumask_t mask = per_cpu(cpu_sibling_map, cpu);
cpus_and(mask, mask, *cpu_map);
group = first_cpu(mask);
if (sg)
@@ -5898,7 +6040,7 @@ static int cpu_to_phys_group(int cpu, const cpumask_t *cpu_map,
cpus_and(mask, mask, *cpu_map);
group = first_cpu(mask);
#elif defined(CONFIG_SCHED_SMT)
- cpumask_t mask = cpu_sibling_map[cpu];
+ cpumask_t mask = per_cpu(cpu_sibling_map, cpu);
cpus_and(mask, mask, *cpu_map);
group = first_cpu(mask);
#else
@@ -6132,7 +6274,7 @@ static int build_sched_domains(const cpumask_t *cpu_map)
p = sd;
sd = &per_cpu(cpu_domains, i);
*sd = SD_SIBLING_INIT;
- sd->span = cpu_sibling_map[i];
+ sd->span = per_cpu(cpu_sibling_map, i);
cpus_and(sd->span, sd->span, *cpu_map);
sd->parent = p;
p->child = sd;
@@ -6143,7 +6285,7 @@ static int build_sched_domains(const cpumask_t *cpu_map)
#ifdef CONFIG_SCHED_SMT
/* Set up CPU (sibling) groups */
for_each_cpu_mask(i, *cpu_map) {
- cpumask_t this_sibling_map = cpu_sibling_map[i];
+ cpumask_t this_sibling_map = per_cpu(cpu_sibling_map, i);
cpus_and(this_sibling_map, this_sibling_map, *cpu_map);
if (i != first_cpu(this_sibling_map))
continue;
@@ -6305,23 +6447,32 @@ error:
return -ENOMEM;
#endif
}
+
+static cpumask_t *doms_cur; /* current sched domains */
+static int ndoms_cur; /* number of sched domains in 'doms_cur' */
+
+/*
+ * Special case: If a kmalloc of a doms_cur partition (array of
+ * cpumask_t) fails, then fallback to a single sched domain,
+ * as determined by the single cpumask_t fallback_doms.
+ */
+static cpumask_t fallback_doms;
+
/*
* Set up scheduler domains and groups. Callers must hold the hotplug lock.
+ * For now this just excludes isolated cpus, but could be used to
+ * exclude other special cases in the future.
*/
static int arch_init_sched_domains(const cpumask_t *cpu_map)
{
- cpumask_t cpu_default_map;
int err;
- /*
- * Setup mask for cpus without special case scheduling requirements.
- * For now this just excludes isolated cpus, but could be used to
- * exclude other special cases in the future.
- */
- cpus_andnot(cpu_default_map, *cpu_map, cpu_isolated_map);
-
- err = build_sched_domains(&cpu_default_map);
-
+ ndoms_cur = 1;
+ doms_cur = kmalloc(sizeof(cpumask_t), GFP_KERNEL);
+ if (!doms_cur)
+ doms_cur = &fallback_doms;
+ cpus_andnot(*doms_cur, *cpu_map, cpu_isolated_map);
+ err = build_sched_domains(doms_cur);
register_sched_domain_sysctl();
return err;
@@ -6349,32 +6500,70 @@ static void detach_destroy_domains(const cpumask_t *cpu_map)
}
/*
- * Partition sched domains as specified by the cpumasks below.
- * This attaches all cpus from the cpumasks to the NULL domain,
- * waits for a RCU quiescent period, recalculates sched
- * domain information and then attaches them back to the
- * correct sched domains
+ * Partition sched domains as specified by the 'ndoms_new'
+ * cpumasks in the array doms_new[] of cpumasks. This compares
+ * doms_new[] to the current sched domain partitioning, doms_cur[].
+ * It destroys each deleted domain and builds each new domain.
+ *
+ * 'doms_new' is an array of cpumask_t's of length 'ndoms_new'.
+ * The masks don't intersect (don't overlap.) We should setup one
+ * sched domain for each mask. CPUs not in any of the cpumasks will
+ * not be load balanced. If the same cpumask appears both in the
+ * current 'doms_cur' domains and in the new 'doms_new', we can leave
+ * it as it is.
+ *
+ * The passed in 'doms_new' should be kmalloc'd. This routine takes
+ * ownership of it and will kfree it when done with it. If the caller
+ * failed the kmalloc call, then it can pass in doms_new == NULL,
+ * and partition_sched_domains() will fallback to the single partition
+ * 'fallback_doms'.
+ *
* Call with hotplug lock held
*/
-int partition_sched_domains(cpumask_t *partition1, cpumask_t *partition2)
+void partition_sched_domains(int ndoms_new, cpumask_t *doms_new)
{
- cpumask_t change_map;
- int err = 0;
+ int i, j;
+
+ /* always unregister in case we don't destroy any domains */
+ unregister_sched_domain_sysctl();
- cpus_and(*partition1, *partition1, cpu_online_map);
- cpus_and(*partition2, *partition2, cpu_online_map);
- cpus_or(change_map, *partition1, *partition2);
+ if (doms_new == NULL) {
+ ndoms_new = 1;
+ doms_new = &fallback_doms;
+ cpus_andnot(doms_new[0], cpu_online_map, cpu_isolated_map);
+ }
- /* Detach sched domains from all of the affected cpus */
- detach_destroy_domains(&change_map);
- if (!cpus_empty(*partition1))
- err = build_sched_domains(partition1);
- if (!err && !cpus_empty(*partition2))
- err = build_sched_domains(partition2);
+ /* Destroy deleted domains */
+ for (i = 0; i < ndoms_cur; i++) {
+ for (j = 0; j < ndoms_new; j++) {
+ if (cpus_equal(doms_cur[i], doms_new[j]))
+ goto match1;
+ }
+ /* no match - a current sched domain not in new doms_new[] */
+ detach_destroy_domains(doms_cur + i);
+match1:
+ ;
+ }
- register_sched_domain_sysctl();
+ /* Build new domains */
+ for (i = 0; i < ndoms_new; i++) {
+ for (j = 0; j < ndoms_cur; j++) {
+ if (cpus_equal(doms_new[i], doms_cur[j]))
+ goto match2;
+ }
+ /* no match - add a new doms_new */
+ build_sched_domains(doms_new + i);
+match2:
+ ;
+ }
- return err;
+ /* Remember the new sched domains */
+ if (doms_cur != &fallback_doms)
+ kfree(doms_cur);
+ doms_cur = doms_new;
+ ndoms_cur = ndoms_new;
+
+ register_sched_domain_sysctl();
}
#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
@@ -6508,10 +6697,12 @@ void __init sched_init_smp(void)
/* Move init over to a non-isolated CPU */
if (set_cpus_allowed(current, non_isolated_cpus) < 0)
BUG();
+ sched_init_granularity();
}
#else
void __init sched_init_smp(void)
{
+ sched_init_granularity();
}
#endif /* CONFIG_SMP */
@@ -6839,8 +7030,8 @@ err:
/* rcu callback to free various structures associated with a task group */
static void free_sched_group(struct rcu_head *rhp)
{
- struct cfs_rq *cfs_rq = container_of(rhp, struct cfs_rq, rcu);
- struct task_group *tg = cfs_rq->tg;
+ struct task_group *tg = container_of(rhp, struct task_group, rcu);
+ struct cfs_rq *cfs_rq;
struct sched_entity *se;
int i;
@@ -6861,7 +7052,7 @@ static void free_sched_group(struct rcu_head *rhp)
/* Destroy runqueue etc associated with a task group */
void sched_destroy_group(struct task_group *tg)
{
- struct cfs_rq *cfs_rq;
+ struct cfs_rq *cfs_rq = NULL;
int i;
for_each_possible_cpu(i) {
@@ -6869,10 +7060,10 @@ void sched_destroy_group(struct task_group *tg)
list_del_rcu(&cfs_rq->leaf_cfs_rq_list);
}
- cfs_rq = tg->cfs_rq[0];
+ BUG_ON(!cfs_rq);
/* wait for possible concurrent references to cfs_rqs complete */
- call_rcu(&cfs_rq->rcu, free_sched_group);
+ call_rcu(&tg->rcu, free_sched_group);
}
/* change task's runqueue when it moves between groups.
@@ -6888,8 +7079,10 @@ void sched_move_task(struct task_struct *tsk)
rq = task_rq_lock(tsk, &flags);
- if (tsk->sched_class != &fair_sched_class)
+ if (tsk->sched_class != &fair_sched_class) {
+ set_task_cfs_rq(tsk, task_cpu(tsk));
goto done;
+ }
update_rq_clock(rq);
@@ -6902,7 +7095,7 @@ void sched_move_task(struct task_struct *tsk)
tsk->sched_class->put_prev_task(rq, tsk);
}
- set_task_cfs_rq(tsk);
+ set_task_cfs_rq(tsk, task_cpu(tsk));
if (on_rq) {
if (unlikely(running))
@@ -6958,3 +7151,127 @@ unsigned long sched_group_shares(struct task_group *tg)
}
#endif /* CONFIG_FAIR_GROUP_SCHED */
+
+#ifdef CONFIG_FAIR_CGROUP_SCHED
+
+/* return corresponding task_group object of a cgroup */
+static inline struct task_group *cgroup_tg(struct cgroup *cgrp)
+{
+ return container_of(cgroup_subsys_state(cgrp, cpu_cgroup_subsys_id),
+ struct task_group, css);
+}
+
+static struct cgroup_subsys_state *
+cpu_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cgrp)
+{
+ struct task_group *tg;
+
+ if (!cgrp->parent) {
+ /* This is early initialization for the top cgroup */
+ init_task_group.css.cgroup = cgrp;
+ return &init_task_group.css;
+ }
+
+ /* we support only 1-level deep hierarchical scheduler atm */
+ if (cgrp->parent->parent)
+ return ERR_PTR(-EINVAL);
+
+ tg = sched_create_group();
+ if (IS_ERR(tg))
+ return ERR_PTR(-ENOMEM);
+
+ /* Bind the cgroup to task_group object we just created */
+ tg->css.cgroup = cgrp;
+
+ return &tg->css;
+}
+
+static void cpu_cgroup_destroy(struct cgroup_subsys *ss,
+ struct cgroup *cgrp)
+{
+ struct task_group *tg = cgroup_tg(cgrp);
+
+ sched_destroy_group(tg);
+}
+
+static int cpu_cgroup_can_attach(struct cgroup_subsys *ss,
+ struct cgroup *cgrp, struct task_struct *tsk)
+{
+ /* We don't support RT-tasks being in separate groups */
+ if (tsk->sched_class != &fair_sched_class)
+ return -EINVAL;
+
+ return 0;
+}
+
+static void
+cpu_cgroup_attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
+ struct cgroup *old_cont, struct task_struct *tsk)
+{
+ sched_move_task(tsk);
+}
+
+static int cpu_shares_write_uint(struct cgroup *cgrp, struct cftype *cftype,
+ u64 shareval)
+{
+ return sched_group_set_shares(cgroup_tg(cgrp), shareval);
+}
+
+static u64 cpu_shares_read_uint(struct cgroup *cgrp, struct cftype *cft)
+{
+ struct task_group *tg = cgroup_tg(cgrp);
+
+ return (u64) tg->shares;
+}
+
+static u64 cpu_usage_read(struct cgroup *cgrp, struct cftype *cft)
+{
+ struct task_group *tg = cgroup_tg(cgrp);
+ unsigned long flags;
+ u64 res = 0;
+ int i;
+
+ for_each_possible_cpu(i) {
+ /*
+ * Lock to prevent races with updating 64-bit counters
+ * on 32-bit arches.
+ */
+ spin_lock_irqsave(&cpu_rq(i)->lock, flags);
+ res += tg->se[i]->sum_exec_runtime;
+ spin_unlock_irqrestore(&cpu_rq(i)->lock, flags);
+ }
+ /* Convert from ns to ms */
+ do_div(res, NSEC_PER_MSEC);
+
+ return res;
+}
+
+static struct cftype cpu_files[] = {
+ {
+ .name = "shares",
+ .read_uint = cpu_shares_read_uint,
+ .write_uint = cpu_shares_write_uint,
+ },
+ {
+ .name = "usage",
+ .read_uint = cpu_usage_read,
+ },
+};
+
+static int cpu_cgroup_populate(struct cgroup_subsys *ss, struct cgroup *cont)
+{
+ return cgroup_add_files(cont, ss, cpu_files, ARRAY_SIZE(cpu_files));
+}
+
+struct cgroup_subsys cpu_cgroup_subsys = {
+ .name = "cpu",
+ .create = cpu_cgroup_create,
+ .destroy = cpu_cgroup_destroy,
+ .can_attach = cpu_cgroup_can_attach,
+ .attach = cpu_cgroup_attach,
+ .populate = cpu_cgroup_populate,
+ .subsys_id = cpu_cgroup_subsys_id,
+ .early_init = 1,
+};
+
+#endif /* CONFIG_FAIR_CGROUP_SCHED */
diff --git a/kernel/sched_debug.c b/kernel/sched_debug.c
index a5e517ec07c3..ca198a797bfa 100644
--- a/kernel/sched_debug.c
+++ b/kernel/sched_debug.c
@@ -80,6 +80,7 @@ print_task(struct seq_file *m, struct rq *rq, struct task_struct *p)
static void print_rq(struct seq_file *m, struct rq *rq, int rq_cpu)
{
struct task_struct *g, *p;
+ unsigned long flags;
SEQ_printf(m,
"\nrunnable tasks:\n"
@@ -88,7 +89,7 @@ static void print_rq(struct seq_file *m, struct rq *rq, int rq_cpu)
"------------------------------------------------------"
"----------------------------------------------------\n");
- read_lock_irq(&tasklist_lock);
+ read_lock_irqsave(&tasklist_lock, flags);
do_each_thread(g, p) {
if (!p->se.on_rq || task_cpu(p) != rq_cpu)
@@ -97,7 +98,7 @@ static void print_rq(struct seq_file *m, struct rq *rq, int rq_cpu)
print_task(m, rq, p);
} while_each_thread(g, p);
- read_unlock_irq(&tasklist_lock);
+ read_unlock_irqrestore(&tasklist_lock, flags);
}
void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq)
@@ -137,7 +138,7 @@ void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq)
SEQ_printf(m, " .%-30s: %ld\n", "nr_running", cfs_rq->nr_running);
SEQ_printf(m, " .%-30s: %ld\n", "load", cfs_rq->load.weight);
#ifdef CONFIG_SCHEDSTATS
- SEQ_printf(m, " .%-30s: %ld\n", "bkl_count",
+ SEQ_printf(m, " .%-30s: %d\n", "bkl_count",
rq->bkl_count);
#endif
SEQ_printf(m, " .%-30s: %ld\n", "nr_spread_over",
@@ -210,7 +211,7 @@ static int sched_debug_show(struct seq_file *m, void *v)
#define PN(x) \
SEQ_printf(m, " .%-40s: %Ld.%06ld\n", #x, SPLIT_NS(x))
PN(sysctl_sched_latency);
- PN(sysctl_sched_nr_latency);
+ PN(sysctl_sched_min_granularity);
PN(sysctl_sched_wakeup_granularity);
PN(sysctl_sched_batch_wakeup_granularity);
PN(sysctl_sched_child_runs_first);
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c
index a17b785d7000..ee00da284b12 100644
--- a/kernel/sched_fair.c
+++ b/kernel/sched_fair.c
@@ -22,7 +22,7 @@
/*
* Targeted preemption latency for CPU-bound tasks:
- * (default: 20ms, units: nanoseconds)
+ * (default: 20ms * ilog(ncpus), units: nanoseconds)
*
* NOTE: this latency value is not the same as the concept of
* 'timeslice length' - timeslices in CFS are of variable length
@@ -32,19 +32,24 @@
* (to see the precise effective timeslice length of your workload,
* run vmstat and monitor the context-switches (cs) field)
*/
-const_debug unsigned int sysctl_sched_latency = 20000000ULL;
+unsigned int sysctl_sched_latency = 20000000ULL;
/*
- * After fork, child runs first. (default) If set to 0 then
- * parent will (try to) run first.
+ * Minimal preemption granularity for CPU-bound tasks:
+ * (default: 1 msec * ilog(ncpus), units: nanoseconds)
*/
-const_debug unsigned int sysctl_sched_child_runs_first = 1;
+unsigned int sysctl_sched_min_granularity = 1000000ULL;
/*
- * Minimal preemption granularity for CPU-bound tasks:
- * (default: 2 msec, units: nanoseconds)
+ * is kept at sysctl_sched_latency / sysctl_sched_min_granularity
*/
-const_debug unsigned int sysctl_sched_nr_latency = 20;
+static unsigned int sched_nr_latency = 20;
+
+/*
+ * After fork, child runs first. (default) If set to 0 then
+ * parent will (try to) run first.
+ */
+const_debug unsigned int sysctl_sched_child_runs_first = 1;
/*
* sys_sched_yield() compat mode
@@ -56,23 +61,23 @@ unsigned int __read_mostly sysctl_sched_compat_yield;
/*
* SCHED_BATCH wake-up granularity.
- * (default: 10 msec, units: nanoseconds)
+ * (default: 10 msec * ilog(ncpus), units: nanoseconds)
*
* This option delays the preemption effects of decoupled workloads
* and reduces their over-scheduling. Synchronous workloads will still
* have immediate wakeup/sleep latencies.
*/
-const_debug unsigned int sysctl_sched_batch_wakeup_granularity = 10000000UL;
+unsigned int sysctl_sched_batch_wakeup_granularity = 10000000UL;
/*
* SCHED_OTHER wake-up granularity.
- * (default: 10 msec, units: nanoseconds)
+ * (default: 10 msec * ilog(ncpus), units: nanoseconds)
*
* This option delays the preemption effects of decoupled workloads
* and reduces their over-scheduling. Synchronous workloads will still
* have immediate wakeup/sleep latencies.
*/
-const_debug unsigned int sysctl_sched_wakeup_granularity = 10000000UL;
+unsigned int sysctl_sched_wakeup_granularity = 10000000UL;
const_debug unsigned int sysctl_sched_migration_cost = 500000UL;
@@ -212,6 +217,22 @@ static inline struct sched_entity *__pick_last_entity(struct cfs_rq *cfs_rq)
* Scheduling class statistics methods:
*/
+#ifdef CONFIG_SCHED_DEBUG
+int sched_nr_latency_handler(struct ctl_table *table, int write,
+ struct file *filp, void __user *buffer, size_t *lenp,
+ loff_t *ppos)
+{
+ int ret = proc_dointvec_minmax(table, write, filp, buffer, lenp, ppos);
+
+ if (ret || !write)
+ return ret;
+
+ sched_nr_latency = DIV_ROUND_UP(sysctl_sched_latency,
+ sysctl_sched_min_granularity);
+
+ return 0;
+}
+#endif
/*
* The idea is to set a period in which each task runs once.
@@ -224,7 +245,7 @@ static inline struct sched_entity *__pick_last_entity(struct cfs_rq *cfs_rq)
static u64 __sched_period(unsigned long nr_running)
{
u64 period = sysctl_sched_latency;
- unsigned long nr_latency = sysctl_sched_nr_latency;
+ unsigned long nr_latency = sched_nr_latency;
if (unlikely(nr_running > nr_latency)) {
period *= nr_running;
@@ -259,6 +280,7 @@ static u64 __sched_vslice(unsigned long rq_weight, unsigned long nr_running)
{
u64 vslice = __sched_period(nr_running);
+ vslice *= NICE_0_LOAD;
do_div(vslice, rq_weight);
return vslice;
@@ -472,19 +494,26 @@ place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int initial)
} else if (sched_feat(APPROX_AVG) && cfs_rq->nr_running)
vruntime += sched_vslice(cfs_rq)/2;
+ /*
+ * The 'current' period is already promised to the current tasks,
+ * however the extra weight of the new task will slow them down a
+ * little, place the new task so that it fits in the slot that
+ * stays open at the end.
+ */
if (initial && sched_feat(START_DEBIT))
vruntime += sched_vslice_add(cfs_rq, se);
if (!initial) {
+ /* sleeps upto a single latency don't count. */
if (sched_feat(NEW_FAIR_SLEEPERS) && entity_is_task(se) &&
task_of(se)->policy != SCHED_BATCH)
vruntime -= sysctl_sched_latency;
- vruntime = max_t(s64, vruntime, se->vruntime);
+ /* ensure we never gain time by being placed backwards. */
+ vruntime = max_vruntime(se->vruntime, vruntime);
}
se->vruntime = vruntime;
-
}
static void
@@ -517,7 +546,6 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep)
update_stats_dequeue(cfs_rq, se);
if (sleep) {
- se->peer_preempt = 0;
#ifdef CONFIG_SCHEDSTATS
if (entity_is_task(se)) {
struct task_struct *tsk = task_of(se);
@@ -545,10 +573,8 @@ check_preempt_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr)
ideal_runtime = sched_slice(cfs_rq, curr);
delta_exec = curr->sum_exec_runtime - curr->prev_sum_exec_runtime;
- if (delta_exec > ideal_runtime ||
- (sched_feat(PREEMPT_RESTRICT) && curr->peer_preempt))
+ if (delta_exec > ideal_runtime)
resched_task(rq_of(cfs_rq)->curr);
- curr->peer_preempt = 0;
}
static void
@@ -811,7 +837,7 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p)
struct task_struct *curr = rq->curr;
struct cfs_rq *cfs_rq = task_cfs_rq(curr);
struct sched_entity *se = &curr->se, *pse = &p->se;
- s64 delta, gran;
+ unsigned long gran;
if (unlikely(rt_prio(p->prio))) {
update_rq_clock(rq);
@@ -826,24 +852,20 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p)
if (unlikely(p->policy == SCHED_BATCH))
return;
- if (sched_feat(WAKEUP_PREEMPT)) {
- while (!is_same_group(se, pse)) {
- se = parent_entity(se);
- pse = parent_entity(pse);
- }
+ if (!sched_feat(WAKEUP_PREEMPT))
+ return;
- delta = se->vruntime - pse->vruntime;
- gran = sysctl_sched_wakeup_granularity;
- if (unlikely(se->load.weight != NICE_0_LOAD))
- gran = calc_delta_fair(gran, &se->load);
+ while (!is_same_group(se, pse)) {
+ se = parent_entity(se);
+ pse = parent_entity(pse);
+ }
- if (delta > gran) {
- int now = !sched_feat(PREEMPT_RESTRICT);
+ gran = sysctl_sched_wakeup_granularity;
+ if (unlikely(se->load.weight != NICE_0_LOAD))
+ gran = calc_delta_fair(gran, &se->load);
- if (now || p->prio < curr->prio || !se->peer_preempt++)
- resched_task(curr);
- }
- }
+ if (pse->vruntime + gran < se->vruntime)
+ resched_task(curr);
}
static struct task_struct *pick_next_task_fair(struct rq *rq)
@@ -876,6 +898,7 @@ static void put_prev_task_fair(struct rq *rq, struct task_struct *prev)
}
}
+#ifdef CONFIG_SMP
/**************************************************
* Fair scheduling class load-balancing methods:
*/
@@ -936,12 +959,11 @@ static int cfs_rq_best_prio(struct cfs_rq *cfs_rq)
static unsigned long
load_balance_fair(struct rq *this_rq, int this_cpu, struct rq *busiest,
- unsigned long max_nr_move, unsigned long max_load_move,
+ unsigned long max_load_move,
struct sched_domain *sd, enum cpu_idle_type idle,
int *all_pinned, int *this_best_prio)
{
struct cfs_rq *busy_cfs_rq;
- unsigned long load_moved, total_nr_moved = 0, nr_moved;
long rem_load_move = max_load_move;
struct rq_iterator cfs_rq_iterator;
@@ -969,25 +991,48 @@ load_balance_fair(struct rq *this_rq, int this_cpu, struct rq *busiest,
#else
# define maxload rem_load_move
#endif
- /* pass busy_cfs_rq argument into
+ /*
+ * pass busy_cfs_rq argument into
* load_balance_[start|next]_fair iterators
*/
cfs_rq_iterator.arg = busy_cfs_rq;
- nr_moved = balance_tasks(this_rq, this_cpu, busiest,
- max_nr_move, maxload, sd, idle, all_pinned,
- &load_moved, this_best_prio, &cfs_rq_iterator);
-
- total_nr_moved += nr_moved;
- max_nr_move -= nr_moved;
- rem_load_move -= load_moved;
+ rem_load_move -= balance_tasks(this_rq, this_cpu, busiest,
+ maxload, sd, idle, all_pinned,
+ this_best_prio,
+ &cfs_rq_iterator);
- if (max_nr_move <= 0 || rem_load_move <= 0)
+ if (rem_load_move <= 0)
break;
}
return max_load_move - rem_load_move;
}
+static int
+move_one_task_fair(struct rq *this_rq, int this_cpu, struct rq *busiest,
+ struct sched_domain *sd, enum cpu_idle_type idle)
+{
+ struct cfs_rq *busy_cfs_rq;
+ struct rq_iterator cfs_rq_iterator;
+
+ cfs_rq_iterator.start = load_balance_start_fair;
+ cfs_rq_iterator.next = load_balance_next_fair;
+
+ for_each_leaf_cfs_rq(busiest, busy_cfs_rq) {
+ /*
+ * pass busy_cfs_rq argument into
+ * load_balance_[start|next]_fair iterators
+ */
+ cfs_rq_iterator.arg = busy_cfs_rq;
+ if (iter_move_one_task(this_rq, this_cpu, busiest, sd, idle,
+ &cfs_rq_iterator))
+ return 1;
+ }
+
+ return 0;
+}
+#endif
+
/*
* scheduler tick hitting a task of our scheduling class:
*/
@@ -1002,7 +1047,7 @@ static void task_tick_fair(struct rq *rq, struct task_struct *curr)
}
}
-#define swap(a,b) do { typeof(a) tmp = (a); (a) = (b); (b) = tmp; } while (0)
+#define swap(a, b) do { typeof(a) tmp = (a); (a) = (b); (b) = tmp; } while (0)
/*
* Share the fairness runtime between parent and child, thus the
@@ -1022,8 +1067,9 @@ static void task_new_fair(struct rq *rq, struct task_struct *p)
update_curr(cfs_rq);
place_entity(cfs_rq, se, 1);
+ /* 'curr' will be NULL if the child belongs to a different group */
if (sysctl_sched_child_runs_first && this_cpu == task_cpu(p) &&
- curr->vruntime < se->vruntime) {
+ curr && curr->vruntime < se->vruntime) {
/*
* Upon rescheduling, sched_class::put_prev_task() will place
* 'current' within the tree based on its new key value.
@@ -1031,12 +1077,7 @@ static void task_new_fair(struct rq *rq, struct task_struct *p)
swap(curr->vruntime, se->vruntime);
}
- update_stats_enqueue(cfs_rq, se);
- check_spread(cfs_rq, se);
- check_spread(cfs_rq, curr);
- __enqueue_entity(cfs_rq, se);
- account_entity_enqueue(cfs_rq, se);
- se->peer_preempt = 0;
+ enqueue_task_fair(rq, p, 0);
resched_task(rq->curr);
}
@@ -1067,7 +1108,10 @@ static const struct sched_class fair_sched_class = {
.pick_next_task = pick_next_task_fair,
.put_prev_task = put_prev_task_fair,
+#ifdef CONFIG_SMP
.load_balance = load_balance_fair,
+ .move_one_task = move_one_task_fair,
+#endif
.set_curr_task = set_curr_task_fair,
.task_tick = task_tick_fair,
diff --git a/kernel/sched_idletask.c b/kernel/sched_idletask.c
index 6e2ead41516e..bf9c25c15b8b 100644
--- a/kernel/sched_idletask.c
+++ b/kernel/sched_idletask.c
@@ -37,15 +37,24 @@ static void put_prev_task_idle(struct rq *rq, struct task_struct *prev)
{
}
+#ifdef CONFIG_SMP
static unsigned long
load_balance_idle(struct rq *this_rq, int this_cpu, struct rq *busiest,
- unsigned long max_nr_move, unsigned long max_load_move,
- struct sched_domain *sd, enum cpu_idle_type idle,
- int *all_pinned, int *this_best_prio)
+ unsigned long max_load_move,
+ struct sched_domain *sd, enum cpu_idle_type idle,
+ int *all_pinned, int *this_best_prio)
{
return 0;
}
+static int
+move_one_task_idle(struct rq *this_rq, int this_cpu, struct rq *busiest,
+ struct sched_domain *sd, enum cpu_idle_type idle)
+{
+ return 0;
+}
+#endif
+
static void task_tick_idle(struct rq *rq, struct task_struct *curr)
{
}
@@ -69,7 +78,10 @@ const struct sched_class idle_sched_class = {
.pick_next_task = pick_next_task_idle,
.put_prev_task = put_prev_task_idle,
+#ifdef CONFIG_SMP
.load_balance = load_balance_idle,
+ .move_one_task = move_one_task_idle,
+#endif
.set_curr_task = set_curr_task_idle,
.task_tick = task_tick_idle,
diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c
index d0097a0634e5..8abd752a0ebd 100644
--- a/kernel/sched_rt.c
+++ b/kernel/sched_rt.c
@@ -98,6 +98,7 @@ static void put_prev_task_rt(struct rq *rq, struct task_struct *p)
p->se.exec_start = 0;
}
+#ifdef CONFIG_SMP
/*
* Load-balancing iterator. Note: while the runqueue stays locked
* during the whole iteration, the current task might be
@@ -172,13 +173,11 @@ static struct task_struct *load_balance_next_rt(void *arg)
static unsigned long
load_balance_rt(struct rq *this_rq, int this_cpu, struct rq *busiest,
- unsigned long max_nr_move, unsigned long max_load_move,
- struct sched_domain *sd, enum cpu_idle_type idle,
- int *all_pinned, int *this_best_prio)
+ unsigned long max_load_move,
+ struct sched_domain *sd, enum cpu_idle_type idle,
+ int *all_pinned, int *this_best_prio)
{
- int nr_moved;
struct rq_iterator rt_rq_iterator;
- unsigned long load_moved;
rt_rq_iterator.start = load_balance_start_rt;
rt_rq_iterator.next = load_balance_next_rt;
@@ -187,12 +186,24 @@ load_balance_rt(struct rq *this_rq, int this_cpu, struct rq *busiest,
*/
rt_rq_iterator.arg = busiest;
- nr_moved = balance_tasks(this_rq, this_cpu, busiest, max_nr_move,
- max_load_move, sd, idle, all_pinned, &load_moved,
- this_best_prio, &rt_rq_iterator);
+ return balance_tasks(this_rq, this_cpu, busiest, max_load_move, sd,
+ idle, all_pinned, this_best_prio, &rt_rq_iterator);
+}
+
+static int
+move_one_task_rt(struct rq *this_rq, int this_cpu, struct rq *busiest,
+ struct sched_domain *sd, enum cpu_idle_type idle)
+{
+ struct rq_iterator rt_rq_iterator;
+
+ rt_rq_iterator.start = load_balance_start_rt;
+ rt_rq_iterator.next = load_balance_next_rt;
+ rt_rq_iterator.arg = busiest;
- return load_moved;
+ return iter_move_one_task(this_rq, this_cpu, busiest, sd, idle,
+ &rt_rq_iterator);
}
+#endif
static void task_tick_rt(struct rq *rq, struct task_struct *p)
{
@@ -236,7 +247,10 @@ const struct sched_class rt_sched_class = {
.pick_next_task = pick_next_task_rt,
.put_prev_task = put_prev_task_rt,
+#ifdef CONFIG_SMP
.load_balance = load_balance_rt,
+ .move_one_task = move_one_task_rt,
+#endif
.set_curr_task = set_curr_task_rt,
.task_tick = task_tick_rt,
diff --git a/kernel/sched_stats.h b/kernel/sched_stats.h
index 1c084842c3e7..630178e53bb6 100644
--- a/kernel/sched_stats.h
+++ b/kernel/sched_stats.h
@@ -21,7 +21,7 @@ static int show_schedstat(struct seq_file *seq, void *v)
/* runqueue-specific stats */
seq_printf(seq,
- "cpu%d %lu %lu %lu %lu %lu %lu %lu %lu %lu %llu %llu %lu",
+ "cpu%d %u %u %u %u %u %u %u %u %u %llu %llu %lu",
cpu, rq->yld_both_empty,
rq->yld_act_empty, rq->yld_exp_empty, rq->yld_count,
rq->sched_switch, rq->sched_count, rq->sched_goidle,
@@ -42,8 +42,7 @@ static int show_schedstat(struct seq_file *seq, void *v)
seq_printf(seq, "domain%d %s", dcount++, mask_str);
for (itype = CPU_IDLE; itype < CPU_MAX_IDLE_TYPES;
itype++) {
- seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu "
- "%lu",
+ seq_printf(seq, " %u %u %u %u %u %u %u %u",
sd->lb_count[itype],
sd->lb_balanced[itype],
sd->lb_failed[itype],
@@ -53,8 +52,7 @@ static int show_schedstat(struct seq_file *seq, void *v)
sd->lb_nobusyq[itype],
sd->lb_nobusyg[itype]);
}
- seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu %lu %lu"
- " %lu %lu %lu\n",
+ seq_printf(seq, " %u %u %u %u %u %u %u %u %u %u %u %u\n",
sd->alb_count, sd->alb_failed, sd->alb_pushed,
sd->sbe_count, sd->sbe_balanced, sd->sbe_pushed,
sd->sbf_count, sd->sbf_balanced, sd->sbf_pushed,
@@ -129,7 +127,7 @@ rq_sched_info_depart(struct rq *rq, unsigned long long delta)
# define schedstat_set(var, val) do { } while (0)
#endif
-#ifdef CONFIG_SCHEDSTATS
+#if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
/*
* Called when a process is dequeued from the active array and given
* the cpu. We should note that with the exception of interactive
@@ -157,7 +155,7 @@ static inline void sched_info_dequeued(struct task_struct *t)
*/
static void sched_info_arrive(struct task_struct *t)
{
- unsigned long long now = sched_clock(), delta = 0;
+ unsigned long long now = task_rq(t)->clock, delta = 0;
if (t->sched_info.last_queued)
delta = now - t->sched_info.last_queued;
@@ -188,7 +186,7 @@ static inline void sched_info_queued(struct task_struct *t)
{
if (unlikely(sched_info_on()))
if (!t->sched_info.last_queued)
- t->sched_info.last_queued = sched_clock();
+ t->sched_info.last_queued = task_rq(t)->clock;
}
/*
@@ -197,7 +195,8 @@ static inline void sched_info_queued(struct task_struct *t)
*/
static inline void sched_info_depart(struct task_struct *t)
{
- unsigned long long delta = sched_clock() - t->sched_info.last_arrival;
+ unsigned long long delta = task_rq(t)->clock -
+ t->sched_info.last_arrival;
t->sched_info.cpu_time += delta;
rq_sched_info_depart(task_rq(t), delta);
@@ -233,5 +232,5 @@ sched_info_switch(struct task_struct *prev, struct task_struct *next)
#else
#define sched_info_queued(t) do { } while (0)
#define sched_info_switch(t, next) do { } while (0)
-#endif /* CONFIG_SCHEDSTATS */
+#endif /* CONFIG_SCHEDSTATS || CONFIG_TASK_DELAY_ACCT */
diff --git a/kernel/signal.c b/kernel/signal.c
index 792952381092..afa4f781f924 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -55,7 +55,7 @@ static int sig_ignored(struct task_struct *t, int sig)
* signal handler may change by the time it is
* unblocked.
*/
- if (sigismember(&t->blocked, sig))
+ if (sigismember(&t->blocked, sig) || sigismember(&t->real_blocked, sig))
return 0;
/* Is it explicitly or implicitly ignored? */
@@ -99,7 +99,6 @@ static inline int has_pending_signals(sigset_t *signal, sigset_t *blocked)
static int recalc_sigpending_tsk(struct task_struct *t)
{
if (t->signal->group_stop_count > 0 ||
- (freezing(t)) ||
PENDING(&t->pending, &t->blocked) ||
PENDING(&t->signal->shared_pending, &t->blocked)) {
set_tsk_thread_flag(t, TIF_SIGPENDING);
@@ -125,7 +124,7 @@ void recalc_sigpending_and_wake(struct task_struct *t)
void recalc_sigpending(void)
{
- if (!recalc_sigpending_tsk(current))
+ if (!recalc_sigpending_tsk(current) && !freezing(current))
clear_thread_flag(TIF_SIGPENDING);
}
@@ -257,7 +256,7 @@ flush_signal_handlers(struct task_struct *t, int force_default)
int unhandled_signal(struct task_struct *tsk, int sig)
{
- if (is_init(tsk))
+ if (is_global_init(tsk))
return 1;
if (tsk->ptrace & PT_PTRACED)
return 0;
@@ -537,7 +536,7 @@ static int check_kill_permission(int sig, struct siginfo *info,
return error;
error = -EPERM;
if (((sig != SIGCONT) ||
- (process_session(current) != process_session(t)))
+ (task_session_nr(current) != task_session_nr(t)))
&& (current->euid ^ t->suid) && (current->euid ^ t->uid)
&& (current->uid ^ t->suid) && (current->uid ^ t->uid)
&& !capable(CAP_KILL))
@@ -695,7 +694,7 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t,
q->info.si_signo = sig;
q->info.si_errno = 0;
q->info.si_code = SI_USER;
- q->info.si_pid = current->pid;
+ q->info.si_pid = task_pid_vnr(current);
q->info.si_uid = current->uid;
break;
case (unsigned long) SEND_SIG_PRIV:
@@ -731,9 +730,9 @@ int print_fatal_signals;
static void print_fatal_signal(struct pt_regs *regs, int signr)
{
printk("%s/%d: potentially unexpected fatal signal %d.\n",
- current->comm, current->pid, signr);
+ current->comm, task_pid_nr(current), signr);
-#ifdef __i386__
+#if defined(__i386__) && !defined(__arch_um__)
printk("code at %08lx: ", regs->eip);
{
int i;
@@ -909,8 +908,7 @@ __group_complete_signal(int sig, struct task_struct *p)
do {
sigaddset(&t->pending.signal, SIGKILL);
signal_wake_up(t, 1);
- t = next_thread(t);
- } while (t != p);
+ } while_each_thread(p, t);
return;
}
@@ -928,13 +926,11 @@ __group_complete_signal(int sig, struct task_struct *p)
rm_from_queue(SIG_KERNEL_STOP_MASK, &p->signal->shared_pending);
p->signal->group_stop_count = 0;
p->signal->group_exit_task = t;
- t = p;
+ p = t;
do {
p->signal->group_stop_count++;
- signal_wake_up(t, 0);
- t = next_thread(t);
- } while (t != p);
- wake_up_process(p->signal->group_exit_task);
+ signal_wake_up(t, t == p);
+ } while_each_thread(p, t);
return;
}
@@ -985,9 +981,6 @@ void zap_other_threads(struct task_struct *p)
p->signal->flags = SIGNAL_GROUP_EXIT;
p->signal->group_stop_count = 0;
- if (thread_group_empty(p))
- return;
-
for (t = next_thread(p); t != p; t = next_thread(t)) {
/*
* Don't bother with already dead threads
@@ -1096,7 +1089,7 @@ kill_proc_info(int sig, struct siginfo *info, pid_t pid)
{
int error;
rcu_read_lock();
- error = kill_pid_info(sig, info, find_pid(pid));
+ error = kill_pid_info(sig, info, find_vpid(pid));
rcu_read_unlock();
return error;
}
@@ -1157,7 +1150,7 @@ static int kill_something_info(int sig, struct siginfo *info, int pid)
read_lock(&tasklist_lock);
for_each_process(p) {
- if (p->pid > 1 && p->tgid != current->tgid) {
+ if (p->pid > 1 && !same_thread_group(p, current)) {
int err = group_send_sig_info(sig, info, p);
++count;
if (err != -EPERM)
@@ -1167,9 +1160,9 @@ static int kill_something_info(int sig, struct siginfo *info, int pid)
read_unlock(&tasklist_lock);
ret = count ? retval : -ESRCH;
} else if (pid < 0) {
- ret = kill_pgrp_info(sig, info, find_pid(-pid));
+ ret = kill_pgrp_info(sig, info, find_vpid(-pid));
} else {
- ret = kill_pid_info(sig, info, find_pid(pid));
+ ret = kill_pid_info(sig, info, find_vpid(pid));
}
rcu_read_unlock();
return ret;
@@ -1273,7 +1266,12 @@ EXPORT_SYMBOL(kill_pid);
int
kill_proc(pid_t pid, int sig, int priv)
{
- return kill_proc_info(sig, __si_special(priv), pid);
+ int ret;
+
+ rcu_read_lock();
+ ret = kill_pid_info(sig, __si_special(priv), find_pid(pid));
+ rcu_read_unlock();
+ return ret;
}
/*
@@ -1450,7 +1448,22 @@ void do_notify_parent(struct task_struct *tsk, int sig)
info.si_signo = sig;
info.si_errno = 0;
- info.si_pid = tsk->pid;
+ /*
+ * we are under tasklist_lock here so our parent is tied to
+ * us and cannot exit and release its namespace.
+ *
+ * the only it can is to switch its nsproxy with sys_unshare,
+ * bu uncharing pid namespaces is not allowed, so we'll always
+ * see relevant namespace
+ *
+ * write_lock() currently calls preempt_disable() which is the
+ * same as rcu_read_lock(), but according to Oleg, this is not
+ * correct to rely on this
+ */
+ rcu_read_lock();
+ info.si_pid = task_pid_nr_ns(tsk, tsk->parent->nsproxy->pid_ns);
+ rcu_read_unlock();
+
info.si_uid = tsk->uid;
/* FIXME: find out whether or not this is supposed to be c*time. */
@@ -1515,7 +1528,13 @@ static void do_notify_parent_cldstop(struct task_struct *tsk, int why)
info.si_signo = SIGCHLD;
info.si_errno = 0;
- info.si_pid = tsk->pid;
+ /*
+ * see comment in do_notify_parent() abot the following 3 lines
+ */
+ rcu_read_lock();
+ info.si_pid = task_pid_nr_ns(tsk, tsk->parent->nsproxy->pid_ns);
+ rcu_read_unlock();
+
info.si_uid = tsk->uid;
/* FIXME: find out whether or not this is supposed to be c*time. */
@@ -1641,7 +1660,7 @@ void ptrace_notify(int exit_code)
memset(&info, 0, sizeof info);
info.si_signo = SIGTRAP;
info.si_code = exit_code;
- info.si_pid = current->pid;
+ info.si_pid = task_pid_vnr(current);
info.si_uid = current->uid;
/* Let the debugger run. */
@@ -1811,7 +1830,7 @@ relock:
info->si_signo = signr;
info->si_errno = 0;
info->si_code = SI_USER;
- info->si_pid = current->parent->pid;
+ info->si_pid = task_pid_vnr(current->parent);
info->si_uid = current->parent->uid;
}
@@ -1842,11 +1861,9 @@ relock:
continue;
/*
- * Init of a pid space gets no signals it doesn't want from
- * within that pid space. It can of course get signals from
- * its parent pid space.
+ * Global init gets no signals it doesn't want.
*/
- if (current == child_reaper(current))
+ if (is_global_init(current))
continue;
if (sig_kernel_stop(signr)) {
@@ -2200,7 +2217,7 @@ sys_kill(int pid, int sig)
info.si_signo = sig;
info.si_errno = 0;
info.si_code = SI_USER;
- info.si_pid = current->tgid;
+ info.si_pid = task_tgid_vnr(current);
info.si_uid = current->uid;
return kill_something_info(sig, &info, pid);
@@ -2216,12 +2233,12 @@ static int do_tkill(int tgid, int pid, int sig)
info.si_signo = sig;
info.si_errno = 0;
info.si_code = SI_TKILL;
- info.si_pid = current->tgid;
+ info.si_pid = task_tgid_vnr(current);
info.si_uid = current->uid;
read_lock(&tasklist_lock);
- p = find_task_by_pid(pid);
- if (p && (tgid <= 0 || p->tgid == tgid)) {
+ p = find_task_by_vpid(pid);
+ if (p && (tgid <= 0 || task_tgid_vnr(p) == tgid)) {
error = check_kill_permission(sig, &info, p);
/*
* The null signal is a permissions and process existence
@@ -2300,15 +2317,6 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
k = &current->sighand->action[sig-1];
spin_lock_irq(&current->sighand->siglock);
- if (signal_pending(current)) {
- /*
- * If there might be a fatal signal pending on multiple
- * threads, make sure we take it before changing the action.
- */
- spin_unlock_irq(&current->sighand->siglock);
- return -ERESTARTNOINTR;
- }
-
if (oact)
*oact = *k;
@@ -2335,7 +2343,6 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
rm_from_queue_full(&mask, &t->signal->shared_pending);
do {
rm_from_queue_full(&mask, &t->pending);
- recalc_sigpending_and_wake(t);
t = next_thread(t);
} while (t != current);
}
diff --git a/kernel/softlockup.c b/kernel/softlockup.c
index 708d4882c0c3..11df812263c8 100644
--- a/kernel/softlockup.c
+++ b/kernel/softlockup.c
@@ -15,13 +15,16 @@
#include <linux/notifier.h>
#include <linux/module.h>
+#include <asm/irq_regs.h>
+
static DEFINE_SPINLOCK(print_lock);
static DEFINE_PER_CPU(unsigned long, touch_timestamp);
static DEFINE_PER_CPU(unsigned long, print_timestamp);
static DEFINE_PER_CPU(struct task_struct *, watchdog_task);
-static int did_panic = 0;
+static int did_panic;
+int softlockup_thresh = 10;
static int
softlock_panic(struct notifier_block *this, unsigned long event, void *ptr)
@@ -40,14 +43,16 @@ static struct notifier_block panic_block = {
* resolution, and we don't need to waste time with a big divide when
* 2^30ns == 1.074s.
*/
-static unsigned long get_timestamp(void)
+static unsigned long get_timestamp(int this_cpu)
{
- return sched_clock() >> 30; /* 2^30 ~= 10^9 */
+ return cpu_clock(this_cpu) >> 30; /* 2^30 ~= 10^9 */
}
void touch_softlockup_watchdog(void)
{
- __raw_get_cpu_var(touch_timestamp) = get_timestamp();
+ int this_cpu = raw_smp_processor_id();
+
+ __raw_get_cpu_var(touch_timestamp) = get_timestamp(this_cpu);
}
EXPORT_SYMBOL(touch_softlockup_watchdog);
@@ -70,6 +75,7 @@ void softlockup_tick(void)
int this_cpu = smp_processor_id();
unsigned long touch_timestamp = per_cpu(touch_timestamp, this_cpu);
unsigned long print_timestamp;
+ struct pt_regs *regs = get_irq_regs();
unsigned long now;
if (touch_timestamp == 0) {
@@ -80,10 +86,11 @@ void softlockup_tick(void)
print_timestamp = per_cpu(print_timestamp, this_cpu);
/* report at most once a second */
- if (print_timestamp < (touch_timestamp + 1) ||
- did_panic ||
- !per_cpu(watchdog_task, this_cpu))
+ if ((print_timestamp >= touch_timestamp &&
+ print_timestamp < (touch_timestamp + 1)) ||
+ did_panic || !per_cpu(watchdog_task, this_cpu)) {
return;
+ }
/* do not print during early bootup: */
if (unlikely(system_state != SYSTEM_RUNNING)) {
@@ -91,28 +98,33 @@ void softlockup_tick(void)
return;
}
- now = get_timestamp();
+ now = get_timestamp(this_cpu);
/* Wake up the high-prio watchdog task every second: */
if (now > (touch_timestamp + 1))
wake_up_process(per_cpu(watchdog_task, this_cpu));
/* Warn about unreasonable 10+ seconds delays: */
- if (now > (touch_timestamp + 10)) {
- per_cpu(print_timestamp, this_cpu) = touch_timestamp;
+ if (now <= (touch_timestamp + softlockup_thresh))
+ return;
- spin_lock(&print_lock);
- printk(KERN_ERR "BUG: soft lockup detected on CPU#%d!\n",
- this_cpu);
+ per_cpu(print_timestamp, this_cpu) = touch_timestamp;
+
+ spin_lock(&print_lock);
+ printk(KERN_ERR "BUG: soft lockup - CPU#%d stuck for %lus! [%s:%d]\n",
+ this_cpu, now - touch_timestamp,
+ current->comm, task_pid_nr(current));
+ if (regs)
+ show_regs(regs);
+ else
dump_stack();
- spin_unlock(&print_lock);
- }
+ spin_unlock(&print_lock);
}
/*
* The watchdog thread - runs every second and touches the timestamp.
*/
-static int watchdog(void * __bind_cpu)
+static int watchdog(void *__bind_cpu)
{
struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
@@ -150,13 +162,13 @@ cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
BUG_ON(per_cpu(watchdog_task, hotcpu));
p = kthread_create(watchdog, hcpu, "watchdog/%d", hotcpu);
if (IS_ERR(p)) {
- printk("watchdog for %i failed\n", hotcpu);
+ printk(KERN_ERR "watchdog for %i failed\n", hotcpu);
return NOTIFY_BAD;
}
- per_cpu(touch_timestamp, hotcpu) = 0;
- per_cpu(watchdog_task, hotcpu) = p;
+ per_cpu(touch_timestamp, hotcpu) = 0;
+ per_cpu(watchdog_task, hotcpu) = p;
kthread_bind(p, hotcpu);
- break;
+ break;
case CPU_ONLINE:
case CPU_ONLINE_FROZEN:
wake_up_process(per_cpu(watchdog_task, hotcpu));
@@ -176,7 +188,7 @@ cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
kthread_stop(p);
break;
#endif /* CONFIG_HOTPLUG_CPU */
- }
+ }
return NOTIFY_OK;
}
diff --git a/kernel/sys.c b/kernel/sys.c
index 8ae2e636eb1b..304b5410d746 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -105,538 +105,6 @@ EXPORT_SYMBOL(cad_pid);
*/
void (*pm_power_off_prepare)(void);
-EXPORT_SYMBOL(pm_power_off_prepare);
-
-/*
- * Notifier list for kernel code which wants to be called
- * at shutdown. This is used to stop any idling DMA operations
- * and the like.
- */
-
-static BLOCKING_NOTIFIER_HEAD(reboot_notifier_list);
-
-/*
- * Notifier chain core routines. The exported routines below
- * are layered on top of these, with appropriate locking added.
- */
-
-static int notifier_chain_register(struct notifier_block **nl,
- struct notifier_block *n)
-{
- while ((*nl) != NULL) {
- if (n->priority > (*nl)->priority)
- break;
- nl = &((*nl)->next);
- }
- n->next = *nl;
- rcu_assign_pointer(*nl, n);
- return 0;
-}
-
-static int notifier_chain_unregister(struct notifier_block **nl,
- struct notifier_block *n)
-{
- while ((*nl) != NULL) {
- if ((*nl) == n) {
- rcu_assign_pointer(*nl, n->next);
- return 0;
- }
- nl = &((*nl)->next);
- }
- return -ENOENT;
-}
-
-/**
- * notifier_call_chain - Informs the registered notifiers about an event.
- * @nl: Pointer to head of the blocking notifier chain
- * @val: Value passed unmodified to notifier function
- * @v: Pointer passed unmodified to notifier function
- * @nr_to_call: Number of notifier functions to be called. Don't care
- * value of this parameter is -1.
- * @nr_calls: Records the number of notifications sent. Don't care
- * value of this field is NULL.
- * @returns: notifier_call_chain returns the value returned by the
- * last notifier function called.
- */
-
-static int __kprobes notifier_call_chain(struct notifier_block **nl,
- unsigned long val, void *v,
- int nr_to_call, int *nr_calls)
-{
- int ret = NOTIFY_DONE;
- struct notifier_block *nb, *next_nb;
-
- nb = rcu_dereference(*nl);
-
- while (nb && nr_to_call) {
- next_nb = rcu_dereference(nb->next);
- ret = nb->notifier_call(nb, val, v);
-
- if (nr_calls)
- (*nr_calls)++;
-
- if ((ret & NOTIFY_STOP_MASK) == NOTIFY_STOP_MASK)
- break;
- nb = next_nb;
- nr_to_call--;
- }
- return ret;
-}
-
-/*
- * Atomic notifier chain routines. Registration and unregistration
- * use a spinlock, and call_chain is synchronized by RCU (no locks).
- */
-
-/**
- * atomic_notifier_chain_register - Add notifier to an atomic notifier chain
- * @nh: Pointer to head of the atomic notifier chain
- * @n: New entry in notifier chain
- *
- * Adds a notifier to an atomic notifier chain.
- *
- * Currently always returns zero.
- */
-
-int atomic_notifier_chain_register(struct atomic_notifier_head *nh,
- struct notifier_block *n)
-{
- unsigned long flags;
- int ret;
-
- spin_lock_irqsave(&nh->lock, flags);
- ret = notifier_chain_register(&nh->head, n);
- spin_unlock_irqrestore(&nh->lock, flags);
- return ret;
-}
-
-EXPORT_SYMBOL_GPL(atomic_notifier_chain_register);
-
-/**
- * atomic_notifier_chain_unregister - Remove notifier from an atomic notifier chain
- * @nh: Pointer to head of the atomic notifier chain
- * @n: Entry to remove from notifier chain
- *
- * Removes a notifier from an atomic notifier chain.
- *
- * Returns zero on success or %-ENOENT on failure.
- */
-int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
- struct notifier_block *n)
-{
- unsigned long flags;
- int ret;
-
- spin_lock_irqsave(&nh->lock, flags);
- ret = notifier_chain_unregister(&nh->head, n);
- spin_unlock_irqrestore(&nh->lock, flags);
- synchronize_rcu();
- return ret;
-}
-
-EXPORT_SYMBOL_GPL(atomic_notifier_chain_unregister);
-
-/**
- * __atomic_notifier_call_chain - Call functions in an atomic notifier chain
- * @nh: Pointer to head of the atomic notifier chain
- * @val: Value passed unmodified to notifier function
- * @v: Pointer passed unmodified to notifier function
- * @nr_to_call: See the comment for notifier_call_chain.
- * @nr_calls: See the comment for notifier_call_chain.
- *
- * Calls each function in a notifier chain in turn. The functions
- * run in an atomic context, so they must not block.
- * This routine uses RCU to synchronize with changes to the chain.
- *
- * If the return value of the notifier can be and'ed
- * with %NOTIFY_STOP_MASK then atomic_notifier_call_chain()
- * will return immediately, with the return value of
- * the notifier function which halted execution.
- * Otherwise the return value is the return value
- * of the last notifier function called.
- */
-
-int __kprobes __atomic_notifier_call_chain(struct atomic_notifier_head *nh,
- unsigned long val, void *v,
- int nr_to_call, int *nr_calls)
-{
- int ret;
-
- rcu_read_lock();
- ret = notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls);
- rcu_read_unlock();
- return ret;
-}
-
-EXPORT_SYMBOL_GPL(__atomic_notifier_call_chain);
-
-int __kprobes atomic_notifier_call_chain(struct atomic_notifier_head *nh,
- unsigned long val, void *v)
-{
- return __atomic_notifier_call_chain(nh, val, v, -1, NULL);
-}
-
-EXPORT_SYMBOL_GPL(atomic_notifier_call_chain);
-/*
- * Blocking notifier chain routines. All access to the chain is
- * synchronized by an rwsem.
- */
-
-/**
- * blocking_notifier_chain_register - Add notifier to a blocking notifier chain
- * @nh: Pointer to head of the blocking notifier chain
- * @n: New entry in notifier chain
- *
- * Adds a notifier to a blocking notifier chain.
- * Must be called in process context.
- *
- * Currently always returns zero.
- */
-
-int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
- struct notifier_block *n)
-{
- int ret;
-
- /*
- * This code gets used during boot-up, when task switching is
- * not yet working and interrupts must remain disabled. At
- * such times we must not call down_write().
- */
- if (unlikely(system_state == SYSTEM_BOOTING))
- return notifier_chain_register(&nh->head, n);
-
- down_write(&nh->rwsem);
- ret = notifier_chain_register(&nh->head, n);
- up_write(&nh->rwsem);
- return ret;
-}
-
-EXPORT_SYMBOL_GPL(blocking_notifier_chain_register);
-
-/**
- * blocking_notifier_chain_unregister - Remove notifier from a blocking notifier chain
- * @nh: Pointer to head of the blocking notifier chain
- * @n: Entry to remove from notifier chain
- *
- * Removes a notifier from a blocking notifier chain.
- * Must be called from process context.
- *
- * Returns zero on success or %-ENOENT on failure.
- */
-int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
- struct notifier_block *n)
-{
- int ret;
-
- /*
- * This code gets used during boot-up, when task switching is
- * not yet working and interrupts must remain disabled. At
- * such times we must not call down_write().
- */
- if (unlikely(system_state == SYSTEM_BOOTING))
- return notifier_chain_unregister(&nh->head, n);
-
- down_write(&nh->rwsem);
- ret = notifier_chain_unregister(&nh->head, n);
- up_write(&nh->rwsem);
- return ret;
-}
-
-EXPORT_SYMBOL_GPL(blocking_notifier_chain_unregister);
-
-/**
- * __blocking_notifier_call_chain - Call functions in a blocking notifier chain
- * @nh: Pointer to head of the blocking notifier chain
- * @val: Value passed unmodified to notifier function
- * @v: Pointer passed unmodified to notifier function
- * @nr_to_call: See comment for notifier_call_chain.
- * @nr_calls: See comment for notifier_call_chain.
- *
- * Calls each function in a notifier chain in turn. The functions
- * run in a process context, so they are allowed to block.
- *
- * If the return value of the notifier can be and'ed
- * with %NOTIFY_STOP_MASK then blocking_notifier_call_chain()
- * will return immediately, with the return value of
- * the notifier function which halted execution.
- * Otherwise the return value is the return value
- * of the last notifier function called.
- */
-
-int __blocking_notifier_call_chain(struct blocking_notifier_head *nh,
- unsigned long val, void *v,
- int nr_to_call, int *nr_calls)
-{
- int ret = NOTIFY_DONE;
-
- /*
- * We check the head outside the lock, but if this access is
- * racy then it does not matter what the result of the test
- * is, we re-check the list after having taken the lock anyway:
- */
- if (rcu_dereference(nh->head)) {
- down_read(&nh->rwsem);
- ret = notifier_call_chain(&nh->head, val, v, nr_to_call,
- nr_calls);
- up_read(&nh->rwsem);
- }
- return ret;
-}
-EXPORT_SYMBOL_GPL(__blocking_notifier_call_chain);
-
-int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
- unsigned long val, void *v)
-{
- return __blocking_notifier_call_chain(nh, val, v, -1, NULL);
-}
-EXPORT_SYMBOL_GPL(blocking_notifier_call_chain);
-
-/*
- * Raw notifier chain routines. There is no protection;
- * the caller must provide it. Use at your own risk!
- */
-
-/**
- * raw_notifier_chain_register - Add notifier to a raw notifier chain
- * @nh: Pointer to head of the raw notifier chain
- * @n: New entry in notifier chain
- *
- * Adds a notifier to a raw notifier chain.
- * All locking must be provided by the caller.
- *
- * Currently always returns zero.
- */
-
-int raw_notifier_chain_register(struct raw_notifier_head *nh,
- struct notifier_block *n)
-{
- return notifier_chain_register(&nh->head, n);
-}
-
-EXPORT_SYMBOL_GPL(raw_notifier_chain_register);
-
-/**
- * raw_notifier_chain_unregister - Remove notifier from a raw notifier chain
- * @nh: Pointer to head of the raw notifier chain
- * @n: Entry to remove from notifier chain
- *
- * Removes a notifier from a raw notifier chain.
- * All locking must be provided by the caller.
- *
- * Returns zero on success or %-ENOENT on failure.
- */
-int raw_notifier_chain_unregister(struct raw_notifier_head *nh,
- struct notifier_block *n)
-{
- return notifier_chain_unregister(&nh->head, n);
-}
-
-EXPORT_SYMBOL_GPL(raw_notifier_chain_unregister);
-
-/**
- * __raw_notifier_call_chain - Call functions in a raw notifier chain
- * @nh: Pointer to head of the raw notifier chain
- * @val: Value passed unmodified to notifier function
- * @v: Pointer passed unmodified to notifier function
- * @nr_to_call: See comment for notifier_call_chain.
- * @nr_calls: See comment for notifier_call_chain
- *
- * Calls each function in a notifier chain in turn. The functions
- * run in an undefined context.
- * All locking must be provided by the caller.
- *
- * If the return value of the notifier can be and'ed
- * with %NOTIFY_STOP_MASK then raw_notifier_call_chain()
- * will return immediately, with the return value of
- * the notifier function which halted execution.
- * Otherwise the return value is the return value
- * of the last notifier function called.
- */
-
-int __raw_notifier_call_chain(struct raw_notifier_head *nh,
- unsigned long val, void *v,
- int nr_to_call, int *nr_calls)
-{
- return notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls);
-}
-
-EXPORT_SYMBOL_GPL(__raw_notifier_call_chain);
-
-int raw_notifier_call_chain(struct raw_notifier_head *nh,
- unsigned long val, void *v)
-{
- return __raw_notifier_call_chain(nh, val, v, -1, NULL);
-}
-
-EXPORT_SYMBOL_GPL(raw_notifier_call_chain);
-
-/*
- * SRCU notifier chain routines. Registration and unregistration
- * use a mutex, and call_chain is synchronized by SRCU (no locks).
- */
-
-/**
- * srcu_notifier_chain_register - Add notifier to an SRCU notifier chain
- * @nh: Pointer to head of the SRCU notifier chain
- * @n: New entry in notifier chain
- *
- * Adds a notifier to an SRCU notifier chain.
- * Must be called in process context.
- *
- * Currently always returns zero.
- */
-
-int srcu_notifier_chain_register(struct srcu_notifier_head *nh,
- struct notifier_block *n)
-{
- int ret;
-
- /*
- * This code gets used during boot-up, when task switching is
- * not yet working and interrupts must remain disabled. At
- * such times we must not call mutex_lock().
- */
- if (unlikely(system_state == SYSTEM_BOOTING))
- return notifier_chain_register(&nh->head, n);
-
- mutex_lock(&nh->mutex);
- ret = notifier_chain_register(&nh->head, n);
- mutex_unlock(&nh->mutex);
- return ret;
-}
-
-EXPORT_SYMBOL_GPL(srcu_notifier_chain_register);
-
-/**
- * srcu_notifier_chain_unregister - Remove notifier from an SRCU notifier chain
- * @nh: Pointer to head of the SRCU notifier chain
- * @n: Entry to remove from notifier chain
- *
- * Removes a notifier from an SRCU notifier chain.
- * Must be called from process context.
- *
- * Returns zero on success or %-ENOENT on failure.
- */
-int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh,
- struct notifier_block *n)
-{
- int ret;
-
- /*
- * This code gets used during boot-up, when task switching is
- * not yet working and interrupts must remain disabled. At
- * such times we must not call mutex_lock().
- */
- if (unlikely(system_state == SYSTEM_BOOTING))
- return notifier_chain_unregister(&nh->head, n);
-
- mutex_lock(&nh->mutex);
- ret = notifier_chain_unregister(&nh->head, n);
- mutex_unlock(&nh->mutex);
- synchronize_srcu(&nh->srcu);
- return ret;
-}
-
-EXPORT_SYMBOL_GPL(srcu_notifier_chain_unregister);
-
-/**
- * __srcu_notifier_call_chain - Call functions in an SRCU notifier chain
- * @nh: Pointer to head of the SRCU notifier chain
- * @val: Value passed unmodified to notifier function
- * @v: Pointer passed unmodified to notifier function
- * @nr_to_call: See comment for notifier_call_chain.
- * @nr_calls: See comment for notifier_call_chain
- *
- * Calls each function in a notifier chain in turn. The functions
- * run in a process context, so they are allowed to block.
- *
- * If the return value of the notifier can be and'ed
- * with %NOTIFY_STOP_MASK then srcu_notifier_call_chain()
- * will return immediately, with the return value of
- * the notifier function which halted execution.
- * Otherwise the return value is the return value
- * of the last notifier function called.
- */
-
-int __srcu_notifier_call_chain(struct srcu_notifier_head *nh,
- unsigned long val, void *v,
- int nr_to_call, int *nr_calls)
-{
- int ret;
- int idx;
-
- idx = srcu_read_lock(&nh->srcu);
- ret = notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls);
- srcu_read_unlock(&nh->srcu, idx);
- return ret;
-}
-EXPORT_SYMBOL_GPL(__srcu_notifier_call_chain);
-
-int srcu_notifier_call_chain(struct srcu_notifier_head *nh,
- unsigned long val, void *v)
-{
- return __srcu_notifier_call_chain(nh, val, v, -1, NULL);
-}
-EXPORT_SYMBOL_GPL(srcu_notifier_call_chain);
-
-/**
- * srcu_init_notifier_head - Initialize an SRCU notifier head
- * @nh: Pointer to head of the srcu notifier chain
- *
- * Unlike other sorts of notifier heads, SRCU notifier heads require
- * dynamic initialization. Be sure to call this routine before
- * calling any of the other SRCU notifier routines for this head.
- *
- * If an SRCU notifier head is deallocated, it must first be cleaned
- * up by calling srcu_cleanup_notifier_head(). Otherwise the head's
- * per-cpu data (used by the SRCU mechanism) will leak.
- */
-
-void srcu_init_notifier_head(struct srcu_notifier_head *nh)
-{
- mutex_init(&nh->mutex);
- if (init_srcu_struct(&nh->srcu) < 0)
- BUG();
- nh->head = NULL;
-}
-
-EXPORT_SYMBOL_GPL(srcu_init_notifier_head);
-
-/**
- * register_reboot_notifier - Register function to be called at reboot time
- * @nb: Info about notifier function to be called
- *
- * Registers a function with the list of functions
- * to be called at reboot time.
- *
- * Currently always returns zero, as blocking_notifier_chain_register()
- * always returns zero.
- */
-
-int register_reboot_notifier(struct notifier_block * nb)
-{
- return blocking_notifier_chain_register(&reboot_notifier_list, nb);
-}
-
-EXPORT_SYMBOL(register_reboot_notifier);
-
-/**
- * unregister_reboot_notifier - Unregister previously registered reboot notifier
- * @nb: Hook to be unregistered
- *
- * Unregisters a previously registered reboot
- * notifier function.
- *
- * Returns zero on success, or %-ENOENT on failure.
- */
-
-int unregister_reboot_notifier(struct notifier_block * nb)
-{
- return blocking_notifier_chain_unregister(&reboot_notifier_list, nb);
-}
-
-EXPORT_SYMBOL(unregister_reboot_notifier);
static int set_one_prio(struct task_struct *p, int niceval, int error)
{
@@ -684,7 +152,7 @@ asmlinkage long sys_setpriority(int which, int who, int niceval)
switch (which) {
case PRIO_PROCESS:
if (who)
- p = find_task_by_pid(who);
+ p = find_task_by_vpid(who);
else
p = current;
if (p)
@@ -692,7 +160,7 @@ asmlinkage long sys_setpriority(int which, int who, int niceval)
break;
case PRIO_PGRP:
if (who)
- pgrp = find_pid(who);
+ pgrp = find_vpid(who);
else
pgrp = task_pgrp(current);
do_each_pid_task(pgrp, PIDTYPE_PGID, p) {
@@ -741,7 +209,7 @@ asmlinkage long sys_getpriority(int which, int who)
switch (which) {
case PRIO_PROCESS:
if (who)
- p = find_task_by_pid(who);
+ p = find_task_by_vpid(who);
else
p = current;
if (p) {
@@ -752,7 +220,7 @@ asmlinkage long sys_getpriority(int which, int who)
break;
case PRIO_PGRP:
if (who)
- pgrp = find_pid(who);
+ pgrp = find_vpid(who);
else
pgrp = task_pgrp(current);
do_each_pid_task(pgrp, PIDTYPE_PGID, p) {
@@ -1449,9 +917,10 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
struct task_struct *p;
struct task_struct *group_leader = current->group_leader;
int err = -EINVAL;
+ struct pid_namespace *ns;
if (!pid)
- pid = group_leader->pid;
+ pid = task_pid_vnr(group_leader);
if (!pgid)
pgid = pid;
if (pgid < 0)
@@ -1460,10 +929,12 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
/* From this point forward we keep holding onto the tasklist lock
* so that our parent does not change from under us. -DaveM
*/
+ ns = current->nsproxy->pid_ns;
+
write_lock_irq(&tasklist_lock);
err = -ESRCH;
- p = find_task_by_pid(pid);
+ p = find_task_by_pid_ns(pid, ns);
if (!p)
goto out;
@@ -1489,9 +960,9 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
goto out;
if (pgid != pid) {
- struct task_struct *g =
- find_task_by_pid_type(PIDTYPE_PGID, pgid);
+ struct task_struct *g;
+ g = find_task_by_pid_type_ns(PIDTYPE_PGID, pgid, ns);
if (!g || task_session(g) != task_session(group_leader))
goto out;
}
@@ -1500,10 +971,13 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
if (err)
goto out;
- if (process_group(p) != pgid) {
+ if (task_pgrp_nr_ns(p, ns) != pgid) {
+ struct pid *pid;
+
detach_pid(p, PIDTYPE_PGID);
- p->signal->pgrp = pgid;
- attach_pid(p, PIDTYPE_PGID, find_pid(pgid));
+ pid = find_vpid(pgid);
+ attach_pid(p, PIDTYPE_PGID, pid);
+ set_task_pgrp(p, pid_nr(pid));
}
err = 0;
@@ -1516,19 +990,21 @@ out:
asmlinkage long sys_getpgid(pid_t pid)
{
if (!pid)
- return process_group(current);
+ return task_pgrp_vnr(current);
else {
int retval;
struct task_struct *p;
+ struct pid_namespace *ns;
- read_lock(&tasklist_lock);
- p = find_task_by_pid(pid);
+ ns = current->nsproxy->pid_ns;
+ read_lock(&tasklist_lock);
+ p = find_task_by_pid_ns(pid, ns);
retval = -ESRCH;
if (p) {
retval = security_task_getpgid(p);
if (!retval)
- retval = process_group(p);
+ retval = task_pgrp_nr_ns(p, ns);
}
read_unlock(&tasklist_lock);
return retval;
@@ -1540,7 +1016,7 @@ asmlinkage long sys_getpgid(pid_t pid)
asmlinkage long sys_getpgrp(void)
{
/* SMP - assuming writes are word atomic this is fine */
- return process_group(current);
+ return task_pgrp_vnr(current);
}
#endif
@@ -1548,19 +1024,21 @@ asmlinkage long sys_getpgrp(void)
asmlinkage long sys_getsid(pid_t pid)
{
if (!pid)
- return process_session(current);
+ return task_session_vnr(current);
else {
int retval;
struct task_struct *p;
+ struct pid_namespace *ns;
- read_lock(&tasklist_lock);
- p = find_task_by_pid(pid);
+ ns = current->nsproxy->pid_ns;
+ read_lock(&tasklist_lock);
+ p = find_task_by_pid_ns(pid, ns);
retval = -ESRCH;
if (p) {
retval = security_task_getsid(p);
if (!retval)
- retval = process_session(p);
+ retval = task_session_nr_ns(p, ns);
}
read_unlock(&tasklist_lock);
return retval;
@@ -1587,7 +1065,8 @@ asmlinkage long sys_setsid(void)
* session id and so the check will always fail and make it so
* init cannot successfully call setsid.
*/
- if (session > 1 && find_task_by_pid_type(PIDTYPE_PGID, session))
+ if (session > 1 && find_task_by_pid_type_ns(PIDTYPE_PGID,
+ session, &init_pid_ns))
goto out;
group_leader->signal->leader = 1;
@@ -1597,7 +1076,7 @@ asmlinkage long sys_setsid(void)
group_leader->signal->tty = NULL;
spin_unlock(&group_leader->sighand->siglock);
- err = process_group(group_leader);
+ err = task_pgrp_vnr(group_leader);
out:
write_unlock_irq(&tasklist_lock);
return err;
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index b0ec498a18d9..56cb009a4b35 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -4,6 +4,10 @@
#include <asm/unistd.h>
+/* we can't #include <linux/syscalls.h> here,
+ but tell gcc to not warn with -Wmissing-prototypes */
+asmlinkage long sys_ni_syscall(void);
+
/*
* Non-implemented system calls get redirected here.
*/
@@ -36,10 +40,14 @@ cond_syscall(sys_recvfrom);
cond_syscall(sys_recv);
cond_syscall(sys_socket);
cond_syscall(sys_setsockopt);
+cond_syscall(compat_sys_setsockopt);
cond_syscall(sys_getsockopt);
+cond_syscall(compat_sys_getsockopt);
cond_syscall(sys_shutdown);
cond_syscall(sys_sendmsg);
+cond_syscall(compat_sys_sendmsg);
cond_syscall(sys_recvmsg);
+cond_syscall(compat_sys_recvmsg);
cond_syscall(sys_socketcall);
cond_syscall(sys_futex);
cond_syscall(compat_sys_futex);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index ec14aa8ac51f..0deed82a6156 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -24,7 +24,7 @@
#include <linux/slab.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
-#include <linux/capability.h>
+#include <linux/security.h>
#include <linux/ctype.h>
#include <linux/utsname.h>
#include <linux/smp_lock.h>
@@ -55,6 +55,8 @@
#include <asm/stacktrace.h>
#endif
+static int deprecated_sysctl_warning(struct __sysctl_args *args);
+
#if defined(CONFIG_SYSCTL)
/* External variables not in a header file. */
@@ -63,6 +65,7 @@ extern int print_fatal_signals;
extern int sysctl_overcommit_memory;
extern int sysctl_overcommit_ratio;
extern int sysctl_panic_on_oom;
+extern int sysctl_oom_kill_allocating_task;
extern int max_threads;
extern int core_uses_pid;
extern int suid_dumpable;
@@ -79,6 +82,19 @@ extern int maps_protect;
extern int sysctl_stat_interval;
extern int audit_argv_kb;
+/* Constants used for minimum and maximum */
+#ifdef CONFIG_DETECT_SOFTLOCKUP
+static int one = 1;
+static int sixty = 60;
+#endif
+
+#ifdef CONFIG_MMU
+static int two = 2;
+#endif
+
+static int zero;
+static int one_hundred = 100;
+
/* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
static int maxolduid = 65535;
static int minolduid;
@@ -128,32 +144,29 @@ extern int max_lock_depth;
#ifdef CONFIG_SYSCTL_SYSCALL
static int parse_table(int __user *, int, void __user *, size_t __user *,
- void __user *, size_t, ctl_table *);
+ void __user *, size_t, struct ctl_table *);
#endif
#ifdef CONFIG_PROC_SYSCTL
-static int proc_do_cad_pid(ctl_table *table, int write, struct file *filp,
+static int proc_do_cad_pid(struct ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos);
-static int proc_dointvec_taint(ctl_table *table, int write, struct file *filp,
+static int proc_dointvec_taint(struct ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos);
#endif
-static ctl_table root_table[];
+static struct ctl_table root_table[];
static struct ctl_table_header root_table_header =
{ root_table, LIST_HEAD_INIT(root_table_header.ctl_entry) };
-static ctl_table kern_table[];
-static ctl_table vm_table[];
-static ctl_table fs_table[];
-static ctl_table debug_table[];
-static ctl_table dev_table[];
-extern ctl_table random_table[];
-#ifdef CONFIG_UNIX98_PTYS
-extern ctl_table pty_table[];
-#endif
+static struct ctl_table kern_table[];
+static struct ctl_table vm_table[];
+static struct ctl_table fs_table[];
+static struct ctl_table debug_table[];
+static struct ctl_table dev_table[];
+extern struct ctl_table random_table[];
#ifdef CONFIG_INOTIFY_USER
-extern ctl_table inotify_table[];
+extern struct ctl_table inotify_table[];
#endif
#ifdef HAVE_ARCH_PICK_MMAP_LAYOUT
@@ -165,7 +178,7 @@ extern int lock_stat;
/* The default sysctl tables: */
-static ctl_table root_table[] = {
+static struct ctl_table root_table[] = {
{
.ctl_name = CTL_KERN,
.procname = "kernel",
@@ -213,20 +226,23 @@ static ctl_table root_table[] = {
#ifdef CONFIG_SCHED_DEBUG
static unsigned long min_sched_granularity_ns = 100000; /* 100 usecs */
-static unsigned long max_sched_granularity_ns = 1000000000; /* 1 second */
+static unsigned long max_sched_granularity_ns = NSEC_PER_SEC; /* 1 second */
static unsigned long min_wakeup_granularity_ns; /* 0 usecs */
-static unsigned long max_wakeup_granularity_ns = 1000000000; /* 1 second */
+static unsigned long max_wakeup_granularity_ns = NSEC_PER_SEC; /* 1 second */
#endif
-static ctl_table kern_table[] = {
+static struct ctl_table kern_table[] = {
#ifdef CONFIG_SCHED_DEBUG
{
.ctl_name = CTL_UNNUMBERED,
- .procname = "sched_nr_latency",
- .data = &sysctl_sched_nr_latency,
+ .procname = "sched_min_granularity_ns",
+ .data = &sysctl_sched_min_granularity,
.maxlen = sizeof(unsigned int),
.mode = 0644,
- .proc_handler = &proc_dointvec,
+ .proc_handler = &sched_nr_latency_handler,
+ .strategy = &sysctl_intvec,
+ .extra1 = &min_sched_granularity_ns,
+ .extra2 = &max_sched_granularity_ns,
},
{
.ctl_name = CTL_UNNUMBERED,
@@ -234,7 +250,7 @@ static ctl_table kern_table[] = {
.data = &sysctl_sched_latency,
.maxlen = sizeof(unsigned int),
.mode = 0644,
- .proc_handler = &proc_dointvec_minmax,
+ .proc_handler = &sched_nr_latency_handler,
.strategy = &sysctl_intvec,
.extra1 = &min_sched_granularity_ns,
.extra2 = &max_sched_granularity_ns,
@@ -285,6 +301,14 @@ static ctl_table kern_table[] = {
.mode = 0644,
.proc_handler = &proc_dointvec,
},
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "sched_nr_migrate",
+ .data = &sysctl_sched_nr_migrate,
+ .maxlen = sizeof(unsigned int),
+ .mode = 644,
+ .proc_handler = &proc_dointvec,
+ },
#endif
{
.ctl_name = CTL_UNNUMBERED,
@@ -351,7 +375,6 @@ static ctl_table kern_table[] = {
},
#ifdef CONFIG_PROC_SYSCTL
{
- .ctl_name = KERN_TAINTED,
.procname = "tainted",
.data = &tainted,
.maxlen = sizeof(int),
@@ -359,14 +382,15 @@ static ctl_table kern_table[] = {
.proc_handler = &proc_dointvec_taint,
},
#endif
+#ifdef CONFIG_SECURITY_CAPABILITIES
{
- .ctl_name = KERN_CAP_BSET,
.procname = "cap-bound",
.data = &cap_bset,
.maxlen = sizeof(kernel_cap_t),
.mode = 0600,
.proc_handler = &proc_dointvec_bset,
},
+#endif /* def CONFIG_SECURITY_CAPABILITIES */
#ifdef CONFIG_BLK_DEV_INITRD
{
.ctl_name = KERN_REALROOTDEV,
@@ -500,7 +524,6 @@ static ctl_table kern_table[] = {
#endif
#ifdef CONFIG_PROC_SYSCTL
{
- .ctl_name = KERN_CADPID,
.procname = "cad_pid",
.data = NULL,
.maxlen = sizeof (int),
@@ -522,14 +545,6 @@ static ctl_table kern_table[] = {
.mode = 0555,
.child = random_table,
},
-#ifdef CONFIG_UNIX98_PTYS
- {
- .ctl_name = KERN_PTY,
- .procname = "pty",
- .mode = 0555,
- .child = pty_table,
- },
-#endif
{
.ctl_name = KERN_OVERFLOWUID,
.procname = "overflowuid",
@@ -636,7 +651,6 @@ static ctl_table kern_table[] = {
.proc_handler = &proc_dointvec,
},
{
- .ctl_name = KERN_NMI_WATCHDOG,
.procname = "nmi_watchdog",
.data = &nmi_watchdog_enabled,
.maxlen = sizeof (int),
@@ -692,7 +706,6 @@ static ctl_table kern_table[] = {
#endif
#if defined(CONFIG_ACPI_SLEEP) && defined(CONFIG_X86)
{
- .ctl_name = KERN_ACPI_VIDEO_FLAGS,
.procname = "acpi_video_flags",
.data = &acpi_realmode_flags,
.maxlen = sizeof (unsigned long),
@@ -710,6 +723,19 @@ static ctl_table kern_table[] = {
.proc_handler = &proc_dointvec,
},
#endif
+#ifdef CONFIG_DETECT_SOFTLOCKUP
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "softlockup_thresh",
+ .data = &softlockup_thresh,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .strategy = &sysctl_intvec,
+ .extra1 = &one,
+ .extra2 = &sixty,
+ },
+#endif
#ifdef CONFIG_COMPAT
{
.ctl_name = KERN_COMPAT_LOG,
@@ -756,14 +782,7 @@ static ctl_table kern_table[] = {
{ .ctl_name = 0 }
};
-/* Constants for minimum and maximum testing in vm_table.
- We use these as one-element integer vectors. */
-static int zero;
-static int two = 2;
-static int one_hundred = 100;
-
-
-static ctl_table vm_table[] = {
+static struct ctl_table vm_table[] = {
{
.ctl_name = VM_OVERCOMMIT_MEMORY,
.procname = "overcommit_memory",
@@ -781,6 +800,14 @@ static ctl_table vm_table[] = {
.proc_handler = &proc_dointvec,
},
{
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "oom_kill_allocating_task",
+ .data = &sysctl_oom_kill_allocating_task,
+ .maxlen = sizeof(sysctl_oom_kill_allocating_task),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
+ {
.ctl_name = VM_OVERCOMMIT_RATIO,
.procname = "overcommit_ratio",
.data = &sysctl_overcommit_ratio,
@@ -813,13 +840,12 @@ static ctl_table vm_table[] = {
.data = &vm_dirty_ratio,
.maxlen = sizeof(vm_dirty_ratio),
.mode = 0644,
- .proc_handler = &proc_dointvec_minmax,
+ .proc_handler = &dirty_ratio_handler,
.strategy = &sysctl_intvec,
.extra1 = &zero,
.extra2 = &one_hundred,
},
{
- .ctl_name = VM_DIRTY_WB_CS,
.procname = "dirty_writeback_centisecs",
.data = &dirty_writeback_interval,
.maxlen = sizeof(dirty_writeback_interval),
@@ -827,7 +853,6 @@ static ctl_table vm_table[] = {
.proc_handler = &dirty_writeback_centisecs_handler,
},
{
- .ctl_name = VM_DIRTY_EXPIRE_CS,
.procname = "dirty_expire_centisecs",
.data = &dirty_expire_interval,
.maxlen = sizeof(dirty_expire_interval),
@@ -855,7 +880,6 @@ static ctl_table vm_table[] = {
},
#ifdef CONFIG_HUGETLB_PAGE
{
- .ctl_name = VM_HUGETLB_PAGES,
.procname = "nr_hugepages",
.data = &max_huge_pages,
.maxlen = sizeof(unsigned long),
@@ -880,6 +904,14 @@ static ctl_table vm_table[] = {
.mode = 0644,
.proc_handler = &hugetlb_treat_movable_handler,
},
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "hugetlb_dynamic_pool",
+ .data = &hugetlb_dynamic_pool,
+ .maxlen = sizeof(hugetlb_dynamic_pool),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
#endif
{
.ctl_name = VM_LOWMEM_RESERVE_RATIO,
@@ -1057,12 +1089,12 @@ static ctl_table vm_table[] = {
};
#if defined(CONFIG_BINFMT_MISC) || defined(CONFIG_BINFMT_MISC_MODULE)
-static ctl_table binfmt_misc_table[] = {
+static struct ctl_table binfmt_misc_table[] = {
{ .ctl_name = 0 }
};
#endif
-static ctl_table fs_table[] = {
+static struct ctl_table fs_table[] = {
{
.ctl_name = FS_NRINODE,
.procname = "inode-nr",
@@ -1080,7 +1112,6 @@ static ctl_table fs_table[] = {
.proc_handler = &proc_dointvec,
},
{
- .ctl_name = FS_NRFILE,
.procname = "file-nr",
.data = &files_stat,
.maxlen = 3*sizeof(int),
@@ -1156,7 +1187,6 @@ static ctl_table fs_table[] = {
.extra2 = &two,
},
{
- .ctl_name = FS_AIO_NR,
.procname = "aio-nr",
.data = &aio_nr,
.maxlen = sizeof(aio_nr),
@@ -1164,7 +1194,6 @@ static ctl_table fs_table[] = {
.proc_handler = &proc_doulongvec_minmax,
},
{
- .ctl_name = FS_AIO_MAX_NR,
.procname = "aio-max-nr",
.data = &aio_max_nr,
.maxlen = sizeof(aio_max_nr),
@@ -1203,7 +1232,7 @@ static ctl_table fs_table[] = {
{ .ctl_name = 0 }
};
-static ctl_table debug_table[] = {
+static struct ctl_table debug_table[] = {
#if defined(CONFIG_X86) || defined(CONFIG_PPC)
{
.ctl_name = CTL_UNNUMBERED,
@@ -1217,7 +1246,7 @@ static ctl_table debug_table[] = {
{ .ctl_name = 0 }
};
-static ctl_table dev_table[] = {
+static struct ctl_table dev_table[] = {
{ .ctl_name = 0 }
};
@@ -1333,10 +1362,15 @@ asmlinkage long sys_sysctl(struct __sysctl_args __user *args)
if (copy_from_user(&tmp, args, sizeof(tmp)))
return -EFAULT;
+ error = deprecated_sysctl_warning(&tmp);
+ if (error)
+ goto out;
+
lock_kernel();
error = do_sysctl(tmp.name, tmp.nlen, tmp.oldval, tmp.oldlenp,
tmp.newval, tmp.newlen);
unlock_kernel();
+out:
return error;
}
#endif /* CONFIG_SYSCTL_SYSCALL */
@@ -1357,7 +1391,7 @@ static int test_perm(int mode, int op)
return -EACCES;
}
-int sysctl_perm(ctl_table *table, int op)
+int sysctl_perm(struct ctl_table *table, int op)
{
int error;
error = security_sysctl(table, op);
@@ -1370,7 +1404,7 @@ int sysctl_perm(ctl_table *table, int op)
static int parse_table(int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen,
- ctl_table *table)
+ struct ctl_table *table)
{
int n;
repeat:
@@ -1401,13 +1435,12 @@ repeat:
}
/* Perform the actual read/write of a sysctl table entry. */
-int do_sysctl_strategy (ctl_table *table,
+int do_sysctl_strategy (struct ctl_table *table,
int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen)
{
int op = 0, rc;
- size_t len;
if (oldval)
op |= 004;
@@ -1428,25 +1461,10 @@ int do_sysctl_strategy (ctl_table *table,
/* If there is no strategy routine, or if the strategy returns
* zero, proceed with automatic r/w */
if (table->data && table->maxlen) {
- if (oldval && oldlenp) {
- if (get_user(len, oldlenp))
- return -EFAULT;
- if (len) {
- if (len > table->maxlen)
- len = table->maxlen;
- if(copy_to_user(oldval, table->data, len))
- return -EFAULT;
- if(put_user(len, oldlenp))
- return -EFAULT;
- }
- }
- if (newval && newlen) {
- len = newlen;
- if (len > table->maxlen)
- len = table->maxlen;
- if(copy_from_user(table->data, newval, len))
- return -EFAULT;
- }
+ rc = sysctl_data(table, name, nlen, oldval, oldlenp,
+ newval, newlen);
+ if (rc < 0)
+ return rc;
}
return 0;
}
@@ -1463,7 +1481,9 @@ static void sysctl_set_parent(struct ctl_table *parent, struct ctl_table *table)
static __init int sysctl_init(void)
{
+ int err;
sysctl_set_parent(NULL, root_table);
+ err = sysctl_check_table(root_table);
return 0;
}
@@ -1476,7 +1496,7 @@ core_initcall(sysctl_init);
* Register a sysctl table hierarchy. @table should be a filled in ctl_table
* array. An entry with a ctl_name of 0 terminates the table.
*
- * The members of the &ctl_table structure are used as follows:
+ * The members of the &struct ctl_table structure are used as follows:
*
* ctl_name - This is the numeric sysctl value used by sysctl(2). The number
* must be unique within that level of sysctl
@@ -1537,7 +1557,7 @@ core_initcall(sysctl_init);
* This routine returns %NULL on a failure to register, and a pointer
* to the table header on success.
*/
-struct ctl_table_header *register_sysctl_table(ctl_table * table)
+struct ctl_table_header *register_sysctl_table(struct ctl_table * table)
{
struct ctl_table_header *tmp;
tmp = kmalloc(sizeof(struct ctl_table_header), GFP_KERNEL);
@@ -1548,6 +1568,10 @@ struct ctl_table_header *register_sysctl_table(ctl_table * table)
tmp->used = 0;
tmp->unregistering = NULL;
sysctl_set_parent(NULL, table);
+ if (sysctl_check_table(tmp->ctl_table)) {
+ kfree(tmp);
+ return NULL;
+ }
spin_lock(&sysctl_lock);
list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry);
spin_unlock(&sysctl_lock);
@@ -1571,7 +1595,7 @@ void unregister_sysctl_table(struct ctl_table_header * header)
}
#else /* !CONFIG_SYSCTL */
-struct ctl_table_header *register_sysctl_table(ctl_table * table)
+struct ctl_table_header *register_sysctl_table(struct ctl_table * table)
{
return NULL;
}
@@ -1664,7 +1688,7 @@ static int _proc_do_string(void* data, int maxlen, int write,
*
* Returns 0 on success.
*/
-int proc_dostring(ctl_table *table, int write, struct file *filp,
+int proc_dostring(struct ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
return _proc_do_string(table->data, table->maxlen, write, filp,
@@ -1691,7 +1715,7 @@ static int do_proc_dointvec_conv(int *negp, unsigned long *lvalp,
return 0;
}
-static int __do_proc_dointvec(void *tbl_data, ctl_table *table,
+static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,
int write, struct file *filp, void __user *buffer,
size_t *lenp, loff_t *ppos,
int (*conv)(int *negp, unsigned long *lvalp, int *valp,
@@ -1801,7 +1825,7 @@ static int __do_proc_dointvec(void *tbl_data, ctl_table *table,
#undef TMPBUFLEN
}
-static int do_proc_dointvec(ctl_table *table, int write, struct file *filp,
+static int do_proc_dointvec(struct ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos,
int (*conv)(int *negp, unsigned long *lvalp, int *valp,
int write, void *data),
@@ -1825,7 +1849,7 @@ static int do_proc_dointvec(ctl_table *table, int write, struct file *filp,
*
* Returns 0 on success.
*/
-int proc_dointvec(ctl_table *table, int write, struct file *filp,
+int proc_dointvec(struct ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
@@ -1861,11 +1885,12 @@ static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp,
return 0;
}
+#ifdef CONFIG_SECURITY_CAPABILITIES
/*
* init may raise the set.
*/
-
-int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
+
+int proc_dointvec_bset(struct ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
int op;
@@ -1874,15 +1899,16 @@ int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
return -EPERM;
}
- op = is_init(current) ? OP_SET : OP_AND;
+ op = is_global_init(current) ? OP_SET : OP_AND;
return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
do_proc_dointvec_bset_conv,&op);
}
+#endif /* def CONFIG_SECURITY_CAPABILITIES */
/*
* Taint values can only be increased
*/
-static int proc_dointvec_taint(ctl_table *table, int write, struct file *filp,
+static int proc_dointvec_taint(struct ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
int op;
@@ -1941,7 +1967,7 @@ static int do_proc_dointvec_minmax_conv(int *negp, unsigned long *lvalp,
*
* Returns 0 on success.
*/
-int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
+int proc_dointvec_minmax(struct ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
struct do_proc_dointvec_minmax_conv_param param = {
@@ -1952,7 +1978,7 @@ int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
do_proc_dointvec_minmax_conv, &param);
}
-static int __do_proc_doulongvec_minmax(void *data, ctl_table *table, int write,
+static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int write,
struct file *filp,
void __user *buffer,
size_t *lenp, loff_t *ppos,
@@ -2057,7 +2083,7 @@ static int __do_proc_doulongvec_minmax(void *data, ctl_table *table, int write,
#undef TMPBUFLEN
}
-static int do_proc_doulongvec_minmax(ctl_table *table, int write,
+static int do_proc_doulongvec_minmax(struct ctl_table *table, int write,
struct file *filp,
void __user *buffer,
size_t *lenp, loff_t *ppos,
@@ -2085,7 +2111,7 @@ static int do_proc_doulongvec_minmax(ctl_table *table, int write,
*
* Returns 0 on success.
*/
-int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
+int proc_doulongvec_minmax(struct ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
return do_proc_doulongvec_minmax(table, write, filp, buffer, lenp, ppos, 1l, 1l);
@@ -2109,7 +2135,7 @@ int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
*
* Returns 0 on success.
*/
-int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
+int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int write,
struct file *filp,
void __user *buffer,
size_t *lenp, loff_t *ppos)
@@ -2202,7 +2228,7 @@ static int do_proc_dointvec_ms_jiffies_conv(int *negp, unsigned long *lvalp,
*
* Returns 0 on success.
*/
-int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp,
+int proc_dointvec_jiffies(struct ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
@@ -2225,7 +2251,7 @@ int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp,
*
* Returns 0 on success.
*/
-int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp,
+int proc_dointvec_userhz_jiffies(struct ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
@@ -2249,21 +2275,21 @@ int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp,
*
* Returns 0 on success.
*/
-int proc_dointvec_ms_jiffies(ctl_table *table, int write, struct file *filp,
+int proc_dointvec_ms_jiffies(struct ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
return do_proc_dointvec(table, write, filp, buffer, lenp, ppos,
do_proc_dointvec_ms_jiffies_conv, NULL);
}
-static int proc_do_cad_pid(ctl_table *table, int write, struct file *filp,
+static int proc_do_cad_pid(struct ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
struct pid *new_pid;
pid_t tmp;
int r;
- tmp = pid_nr(cad_pid);
+ tmp = pid_nr_ns(cad_pid, current->nsproxy->pid_ns);
r = __do_proc_dointvec(&tmp, table, write, filp, buffer,
lenp, ppos, NULL, NULL);
@@ -2280,55 +2306,55 @@ static int proc_do_cad_pid(ctl_table *table, int write, struct file *filp,
#else /* CONFIG_PROC_FS */
-int proc_dostring(ctl_table *table, int write, struct file *filp,
+int proc_dostring(struct ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
return -ENOSYS;
}
-int proc_dointvec(ctl_table *table, int write, struct file *filp,
+int proc_dointvec(struct ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
return -ENOSYS;
}
-int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
+int proc_dointvec_bset(struct ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
return -ENOSYS;
}
-int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
+int proc_dointvec_minmax(struct ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
return -ENOSYS;
}
-int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp,
+int proc_dointvec_jiffies(struct ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
return -ENOSYS;
}
-int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp,
+int proc_dointvec_userhz_jiffies(struct ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
return -ENOSYS;
}
-int proc_dointvec_ms_jiffies(ctl_table *table, int write, struct file *filp,
+int proc_dointvec_ms_jiffies(struct ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
return -ENOSYS;
}
-int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
+int proc_doulongvec_minmax(struct ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
return -ENOSYS;
}
-int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
+int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int write,
struct file *filp,
void __user *buffer,
size_t *lenp, loff_t *ppos)
@@ -2345,8 +2371,42 @@ int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
* General sysctl support routines
*/
+/* The generic sysctl data routine (used if no strategy routine supplied) */
+int sysctl_data(struct ctl_table *table, int __user *name, int nlen,
+ void __user *oldval, size_t __user *oldlenp,
+ void __user *newval, size_t newlen)
+{
+ size_t len;
+
+ /* Get out of I don't have a variable */
+ if (!table->data || !table->maxlen)
+ return -ENOTDIR;
+
+ if (oldval && oldlenp) {
+ if (get_user(len, oldlenp))
+ return -EFAULT;
+ if (len) {
+ if (len > table->maxlen)
+ len = table->maxlen;
+ if (copy_to_user(oldval, table->data, len))
+ return -EFAULT;
+ if (put_user(len, oldlenp))
+ return -EFAULT;
+ }
+ }
+
+ if (newval && newlen) {
+ if (newlen > table->maxlen)
+ newlen = table->maxlen;
+
+ if (copy_from_user(table->data, newval, newlen))
+ return -EFAULT;
+ }
+ return 1;
+}
+
/* The generic string strategy routine: */
-int sysctl_string(ctl_table *table, int __user *name, int nlen,
+int sysctl_string(struct ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen)
{
@@ -2392,7 +2452,7 @@ int sysctl_string(ctl_table *table, int __user *name, int nlen,
* are between the minimum and maximum values given in the arrays
* table->extra1 and table->extra2, respectively.
*/
-int sysctl_intvec(ctl_table *table, int __user *name, int nlen,
+int sysctl_intvec(struct ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen)
{
@@ -2428,7 +2488,7 @@ int sysctl_intvec(ctl_table *table, int __user *name, int nlen,
}
/* Strategy function to convert jiffies to seconds */
-int sysctl_jiffies(ctl_table *table, int __user *name, int nlen,
+int sysctl_jiffies(struct ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen)
{
@@ -2462,7 +2522,7 @@ int sysctl_jiffies(ctl_table *table, int __user *name, int nlen,
}
/* Strategy function to convert jiffies to seconds */
-int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen,
+int sysctl_ms_jiffies(struct ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen)
{
@@ -2502,59 +2562,50 @@ int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen,
asmlinkage long sys_sysctl(struct __sysctl_args __user *args)
{
- static int msg_count;
struct __sysctl_args tmp;
- int name[CTL_MAXNAME];
- int i;
+ int error;
- /* Read in the sysctl name for better debug message logging */
if (copy_from_user(&tmp, args, sizeof(tmp)))
return -EFAULT;
- if (tmp.nlen <= 0 || tmp.nlen >= CTL_MAXNAME)
- return -ENOTDIR;
- for (i = 0; i < tmp.nlen; i++)
- if (get_user(name[i], tmp.name + i))
- return -EFAULT;
- /* Ignore accesses to kernel.version */
- if ((tmp.nlen == 2) && (name[0] == CTL_KERN) && (name[1] == KERN_VERSION))
- goto out;
+ error = deprecated_sysctl_warning(&tmp);
- if (msg_count < 5) {
- msg_count++;
- printk(KERN_INFO
- "warning: process `%s' used the removed sysctl "
- "system call with ", current->comm);
- for (i = 0; i < tmp.nlen; i++)
- printk("%d.", name[i]);
- printk("\n");
- }
-out:
+ /* If no error reading the parameters then just -ENOSYS ... */
+ if (!error)
+ error = -ENOSYS;
+
+ return error;
+}
+
+int sysctl_data(struct ctl_table *table, int __user *name, int nlen,
+ void __user *oldval, size_t __user *oldlenp,
+ void __user *newval, size_t newlen)
+{
return -ENOSYS;
}
-int sysctl_string(ctl_table *table, int __user *name, int nlen,
+int sysctl_string(struct ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen)
{
return -ENOSYS;
}
-int sysctl_intvec(ctl_table *table, int __user *name, int nlen,
+int sysctl_intvec(struct ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen)
{
return -ENOSYS;
}
-int sysctl_jiffies(ctl_table *table, int __user *name, int nlen,
+int sysctl_jiffies(struct ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen)
{
return -ENOSYS;
}
-int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen,
+int sysctl_ms_jiffies(struct ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen)
{
@@ -2563,6 +2614,37 @@ int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen,
#endif /* CONFIG_SYSCTL_SYSCALL */
+static int deprecated_sysctl_warning(struct __sysctl_args *args)
+{
+ static int msg_count;
+ int name[CTL_MAXNAME];
+ int i;
+
+ /* Check args->nlen. */
+ if (args->nlen < 0 || args->nlen > CTL_MAXNAME)
+ return -ENOTDIR;
+
+ /* Read in the sysctl name for better debug message logging */
+ for (i = 0; i < args->nlen; i++)
+ if (get_user(name[i], args->name + i))
+ return -EFAULT;
+
+ /* Ignore accesses to kernel.version */
+ if ((args->nlen == 2) && (name[0] == CTL_KERN) && (name[1] == KERN_VERSION))
+ return 0;
+
+ if (msg_count < 5) {
+ msg_count++;
+ printk(KERN_INFO
+ "warning: process `%s' used the deprecated sysctl "
+ "system call with ", current->comm);
+ for (i = 0; i < args->nlen; i++)
+ printk("%d.", name[i]);
+ printk("\n");
+ }
+ return 0;
+}
+
/*
* No sense putting this after each symbol definition, twice,
* exception granted :-)
@@ -2580,4 +2662,5 @@ EXPORT_SYMBOL(sysctl_intvec);
EXPORT_SYMBOL(sysctl_jiffies);
EXPORT_SYMBOL(sysctl_ms_jiffies);
EXPORT_SYMBOL(sysctl_string);
+EXPORT_SYMBOL(sysctl_data);
EXPORT_SYMBOL(unregister_sysctl_table);
diff --git a/kernel/sysctl_check.c b/kernel/sysctl_check.c
new file mode 100644
index 000000000000..4abc6d2306f4
--- /dev/null
+++ b/kernel/sysctl_check.c
@@ -0,0 +1,1589 @@
+#include <linux/stat.h>
+#include <linux/sysctl.h>
+#include "../arch/s390/appldata/appldata.h"
+#include "../fs/xfs/linux-2.6/xfs_sysctl.h"
+#include <linux/sunrpc/debug.h>
+#include <linux/string.h>
+#include <net/ip_vs.h>
+
+struct trans_ctl_table {
+ int ctl_name;
+ const char *procname;
+ struct trans_ctl_table *child;
+};
+
+static struct trans_ctl_table trans_random_table[] = {
+ { RANDOM_POOLSIZE, "poolsize" },
+ { RANDOM_ENTROPY_COUNT, "entropy_avail" },
+ { RANDOM_READ_THRESH, "read_wakeup_threshold" },
+ { RANDOM_WRITE_THRESH, "write_wakeup_threshold" },
+ { RANDOM_BOOT_ID, "boot_id" },
+ { RANDOM_UUID, "uuid" },
+ {}
+};
+
+static struct trans_ctl_table trans_pty_table[] = {
+ { PTY_MAX, "max" },
+ { PTY_NR, "nr" },
+ {}
+};
+
+static struct trans_ctl_table trans_kern_table[] = {
+ { KERN_OSTYPE, "ostype" },
+ { KERN_OSRELEASE, "osrelease" },
+ /* KERN_OSREV not used */
+ { KERN_VERSION, "version" },
+ /* KERN_SECUREMASK not used */
+ /* KERN_PROF not used */
+ { KERN_NODENAME, "hostname" },
+ { KERN_DOMAINNAME, "domainname" },
+
+#ifdef CONFIG_SECURITY_CAPABILITIES
+ { KERN_CAP_BSET, "cap-bound" },
+#endif /* def CONFIG_SECURITY_CAPABILITIES */
+
+ { KERN_PANIC, "panic" },
+ { KERN_REALROOTDEV, "real-root-dev" },
+
+ { KERN_SPARC_REBOOT, "reboot-cmd" },
+ { KERN_CTLALTDEL, "ctrl-alt-del" },
+ { KERN_PRINTK, "printk" },
+
+ /* KERN_NAMETRANS not used */
+ /* KERN_PPC_HTABRECLAIM not used */
+ /* KERN_PPC_ZEROPAGED not used */
+ { KERN_PPC_POWERSAVE_NAP, "powersave-nap" },
+
+ { KERN_MODPROBE, "modprobe" },
+ { KERN_SG_BIG_BUFF, "sg-big-buff" },
+ { KERN_ACCT, "acct" },
+ { KERN_PPC_L2CR, "l2cr" },
+
+ /* KERN_RTSIGNR not used */
+ /* KERN_RTSIGMAX not used */
+
+ { KERN_SHMMAX, "shmmax" },
+ { KERN_MSGMAX, "msgmax" },
+ { KERN_MSGMNB, "msgmnb" },
+ /* KERN_MSGPOOL not used*/
+ { KERN_SYSRQ, "sysrq" },
+ { KERN_MAX_THREADS, "threads-max" },
+ { KERN_RANDOM, "random", trans_random_table },
+ { KERN_SHMALL, "shmall" },
+ { KERN_MSGMNI, "msgmni" },
+ { KERN_SEM, "sem" },
+ { KERN_SPARC_STOP_A, "stop-a" },
+ { KERN_SHMMNI, "shmmni" },
+
+ { KERN_OVERFLOWUID, "overflowuid" },
+ { KERN_OVERFLOWGID, "overflowgid" },
+
+ { KERN_HOTPLUG, "hotplug", },
+ { KERN_IEEE_EMULATION_WARNINGS, "ieee_emulation_warnings" },
+
+ { KERN_S390_USER_DEBUG_LOGGING, "userprocess_debug" },
+ { KERN_CORE_USES_PID, "core_uses_pid" },
+ { KERN_TAINTED, "tainted" },
+ { KERN_CADPID, "cad_pid" },
+ { KERN_PIDMAX, "pid_max" },
+ { KERN_CORE_PATTERN, "core_pattern" },
+ { KERN_PANIC_ON_OOPS, "panic_on_oops" },
+ { KERN_HPPA_PWRSW, "soft-power" },
+ { KERN_HPPA_UNALIGNED, "unaligned-trap" },
+
+ { KERN_PRINTK_RATELIMIT, "printk_ratelimit" },
+ { KERN_PRINTK_RATELIMIT_BURST, "printk_ratelimit_burst" },
+
+ { KERN_PTY, "pty", trans_pty_table },
+ { KERN_NGROUPS_MAX, "ngroups_max" },
+ { KERN_SPARC_SCONS_PWROFF, "scons_poweroff" },
+ { KERN_HZ_TIMER, "hz_timer" },
+ { KERN_UNKNOWN_NMI_PANIC, "unknown_nmi_panic" },
+ { KERN_BOOTLOADER_TYPE, "bootloader_type" },
+ { KERN_RANDOMIZE, "randomize_va_space" },
+
+ { KERN_SPIN_RETRY, "spin_retry" },
+ { KERN_ACPI_VIDEO_FLAGS, "acpi_video_flags" },
+ { KERN_IA64_UNALIGNED, "ignore-unaligned-usertrap" },
+ { KERN_COMPAT_LOG, "compat-log" },
+ { KERN_MAX_LOCK_DEPTH, "max_lock_depth" },
+ { KERN_NMI_WATCHDOG, "nmi_watchdog" },
+ { KERN_PANIC_ON_NMI, "panic_on_unrecovered_nmi" },
+ {}
+};
+
+static struct trans_ctl_table trans_vm_table[] = {
+ { VM_OVERCOMMIT_MEMORY, "overcommit_memory" },
+ { VM_PAGE_CLUSTER, "page-cluster" },
+ { VM_DIRTY_BACKGROUND, "dirty_background_ratio" },
+ { VM_DIRTY_RATIO, "dirty_ratio" },
+ { VM_DIRTY_WB_CS, "dirty_writeback_centisecs" },
+ { VM_DIRTY_EXPIRE_CS, "dirty_expire_centisecs" },
+ { VM_NR_PDFLUSH_THREADS, "nr_pdflush_threads" },
+ { VM_OVERCOMMIT_RATIO, "overcommit_ratio" },
+ /* VM_PAGEBUF unused */
+ { VM_HUGETLB_PAGES, "nr_hugepages" },
+ { VM_SWAPPINESS, "swappiness" },
+ { VM_LOWMEM_RESERVE_RATIO, "lowmem_reserve_ratio" },
+ { VM_MIN_FREE_KBYTES, "min_free_kbytes" },
+ { VM_MAX_MAP_COUNT, "max_map_count" },
+ { VM_LAPTOP_MODE, "laptop_mode" },
+ { VM_BLOCK_DUMP, "block_dump" },
+ { VM_HUGETLB_GROUP, "hugetlb_shm_group" },
+ { VM_VFS_CACHE_PRESSURE, "vfs_cache_pressure" },
+ { VM_LEGACY_VA_LAYOUT, "legacy_va_layout" },
+ /* VM_SWAP_TOKEN_TIMEOUT unused */
+ { VM_DROP_PAGECACHE, "drop_caches" },
+ { VM_PERCPU_PAGELIST_FRACTION, "percpu_pagelist_fraction" },
+ { VM_ZONE_RECLAIM_MODE, "zone_reclaim_mode" },
+ { VM_MIN_UNMAPPED, "min_unmapped_ratio" },
+ { VM_PANIC_ON_OOM, "panic_on_oom" },
+ { VM_VDSO_ENABLED, "vdso_enabled" },
+ { VM_MIN_SLAB, "min_slab_ratio" },
+ { VM_CMM_PAGES, "cmm_pages" },
+ { VM_CMM_TIMED_PAGES, "cmm_timed_pages" },
+ { VM_CMM_TIMEOUT, "cmm_timeout" },
+
+ {}
+};
+
+static struct trans_ctl_table trans_net_core_table[] = {
+ { NET_CORE_WMEM_MAX, "wmem_max" },
+ { NET_CORE_RMEM_MAX, "rmem_max" },
+ { NET_CORE_WMEM_DEFAULT, "wmem_default" },
+ { NET_CORE_RMEM_DEFAULT, "rmem_default" },
+ /* NET_CORE_DESTROY_DELAY unused */
+ { NET_CORE_MAX_BACKLOG, "netdev_max_backlog" },
+ /* NET_CORE_FASTROUTE unused */
+ { NET_CORE_MSG_COST, "message_cost" },
+ { NET_CORE_MSG_BURST, "message_burst" },
+ { NET_CORE_OPTMEM_MAX, "optmem_max" },
+ /* NET_CORE_HOT_LIST_LENGTH unused */
+ /* NET_CORE_DIVERT_VERSION unused */
+ /* NET_CORE_NO_CONG_THRESH unused */
+ /* NET_CORE_NO_CONG unused */
+ /* NET_CORE_LO_CONG unused */
+ /* NET_CORE_MOD_CONG unused */
+ { NET_CORE_DEV_WEIGHT, "dev_weight" },
+ { NET_CORE_SOMAXCONN, "somaxconn" },
+ { NET_CORE_BUDGET, "netdev_budget" },
+ { NET_CORE_AEVENT_ETIME, "xfrm_aevent_etime" },
+ { NET_CORE_AEVENT_RSEQTH, "xfrm_aevent_rseqth" },
+ { NET_CORE_WARNINGS, "warnings" },
+ {},
+};
+
+static struct trans_ctl_table trans_net_unix_table[] = {
+ /* NET_UNIX_DESTROY_DELAY unused */
+ /* NET_UNIX_DELETE_DELAY unused */
+ { NET_UNIX_MAX_DGRAM_QLEN, "max_dgram_qlen" },
+ {}
+};
+
+static struct trans_ctl_table trans_net_ipv4_route_table[] = {
+ { NET_IPV4_ROUTE_FLUSH, "flush" },
+ { NET_IPV4_ROUTE_MIN_DELAY, "min_delay" },
+ { NET_IPV4_ROUTE_MAX_DELAY, "max_delay" },
+ { NET_IPV4_ROUTE_GC_THRESH, "gc_thresh" },
+ { NET_IPV4_ROUTE_MAX_SIZE, "max_size" },
+ { NET_IPV4_ROUTE_GC_MIN_INTERVAL, "gc_min_interval" },
+ { NET_IPV4_ROUTE_GC_TIMEOUT, "gc_timeout" },
+ { NET_IPV4_ROUTE_GC_INTERVAL, "gc_interval" },
+ { NET_IPV4_ROUTE_REDIRECT_LOAD, "redirect_load" },
+ { NET_IPV4_ROUTE_REDIRECT_NUMBER, "redirect_number" },
+ { NET_IPV4_ROUTE_REDIRECT_SILENCE, "redirect_silence" },
+ { NET_IPV4_ROUTE_ERROR_COST, "error_cost" },
+ { NET_IPV4_ROUTE_ERROR_BURST, "error_burst" },
+ { NET_IPV4_ROUTE_GC_ELASTICITY, "gc_elasticity" },
+ { NET_IPV4_ROUTE_MTU_EXPIRES, "mtu_expires" },
+ { NET_IPV4_ROUTE_MIN_PMTU, "min_pmtu" },
+ { NET_IPV4_ROUTE_MIN_ADVMSS, "min_adv_mss" },
+ { NET_IPV4_ROUTE_SECRET_INTERVAL, "secret_interval" },
+ { NET_IPV4_ROUTE_GC_MIN_INTERVAL_MS, "gc_min_interval_ms" },
+ {}
+};
+
+static struct trans_ctl_table trans_net_ipv4_conf_vars_table[] = {
+ { NET_IPV4_CONF_FORWARDING, "forwarding" },
+ { NET_IPV4_CONF_MC_FORWARDING, "mc_forwarding" },
+
+ { NET_IPV4_CONF_PROXY_ARP, "proxy_arp" },
+ { NET_IPV4_CONF_ACCEPT_REDIRECTS, "accept_redirects" },
+ { NET_IPV4_CONF_SECURE_REDIRECTS, "secure_redirects" },
+ { NET_IPV4_CONF_SEND_REDIRECTS, "send_redirects" },
+ { NET_IPV4_CONF_SHARED_MEDIA, "shared_media" },
+ { NET_IPV4_CONF_RP_FILTER, "rp_filter" },
+ { NET_IPV4_CONF_ACCEPT_SOURCE_ROUTE, "accept_source_route" },
+ { NET_IPV4_CONF_BOOTP_RELAY, "bootp_relay" },
+ { NET_IPV4_CONF_LOG_MARTIANS, "log_martians" },
+ { NET_IPV4_CONF_TAG, "tag" },
+ { NET_IPV4_CONF_ARPFILTER, "arp_filter" },
+ { NET_IPV4_CONF_MEDIUM_ID, "medium_id" },
+ { NET_IPV4_CONF_NOXFRM, "disable_xfrm" },
+ { NET_IPV4_CONF_NOPOLICY, "disable_policy" },
+ { NET_IPV4_CONF_FORCE_IGMP_VERSION, "force_igmp_version" },
+
+ { NET_IPV4_CONF_ARP_ANNOUNCE, "arp_announce" },
+ { NET_IPV4_CONF_ARP_IGNORE, "arp_ignore" },
+ { NET_IPV4_CONF_PROMOTE_SECONDARIES, "promote_secondaries" },
+ { NET_IPV4_CONF_ARP_ACCEPT, "arp_accept" },
+ {}
+};
+
+static struct trans_ctl_table trans_net_ipv4_conf_table[] = {
+ { NET_PROTO_CONF_ALL, "all", trans_net_ipv4_conf_vars_table },
+ { NET_PROTO_CONF_DEFAULT, "default", trans_net_ipv4_conf_vars_table },
+ { 0, NULL, trans_net_ipv4_conf_vars_table },
+ {}
+};
+
+
+static struct trans_ctl_table trans_net_ipv4_vs_table[] = {
+ { NET_IPV4_VS_AMEMTHRESH, "amemthresh" },
+ { NET_IPV4_VS_DEBUG_LEVEL, "debug_level" },
+ { NET_IPV4_VS_AMDROPRATE, "am_droprate" },
+ { NET_IPV4_VS_DROP_ENTRY, "drop_entry" },
+ { NET_IPV4_VS_DROP_PACKET, "drop_packet" },
+ { NET_IPV4_VS_SECURE_TCP, "secure_tcp" },
+ { NET_IPV4_VS_TO_ES, "timeout_established" },
+ { NET_IPV4_VS_TO_SS, "timeout_synsent" },
+ { NET_IPV4_VS_TO_SR, "timeout_synrecv" },
+ { NET_IPV4_VS_TO_FW, "timeout_finwait" },
+ { NET_IPV4_VS_TO_TW, "timeout_timewait" },
+ { NET_IPV4_VS_TO_CL, "timeout_close" },
+ { NET_IPV4_VS_TO_CW, "timeout_closewait" },
+ { NET_IPV4_VS_TO_LA, "timeout_lastack" },
+ { NET_IPV4_VS_TO_LI, "timeout_listen" },
+ { NET_IPV4_VS_TO_SA, "timeout_synack" },
+ { NET_IPV4_VS_TO_UDP, "timeout_udp" },
+ { NET_IPV4_VS_TO_ICMP, "timeout_icmp" },
+ { NET_IPV4_VS_CACHE_BYPASS, "cache_bypass" },
+ { NET_IPV4_VS_EXPIRE_NODEST_CONN, "expire_nodest_conn" },
+ { NET_IPV4_VS_EXPIRE_QUIESCENT_TEMPLATE, "expire_quiescent_template" },
+ { NET_IPV4_VS_SYNC_THRESHOLD, "sync_threshold" },
+ { NET_IPV4_VS_NAT_ICMP_SEND, "nat_icmp_send" },
+ { NET_IPV4_VS_LBLC_EXPIRE, "lblc_expiration" },
+ { NET_IPV4_VS_LBLCR_EXPIRE, "lblcr_expiration" },
+ {}
+};
+
+static struct trans_ctl_table trans_net_neigh_vars_table[] = {
+ { NET_NEIGH_MCAST_SOLICIT, "mcast_solicit" },
+ { NET_NEIGH_UCAST_SOLICIT, "ucast_solicit" },
+ { NET_NEIGH_APP_SOLICIT, "app_solicit" },
+ { NET_NEIGH_RETRANS_TIME, "retrans_time" },
+ { NET_NEIGH_REACHABLE_TIME, "base_reachable_time" },
+ { NET_NEIGH_DELAY_PROBE_TIME, "delay_first_probe_time" },
+ { NET_NEIGH_GC_STALE_TIME, "gc_stale_time" },
+ { NET_NEIGH_UNRES_QLEN, "unres_qlen" },
+ { NET_NEIGH_PROXY_QLEN, "proxy_qlen" },
+ { NET_NEIGH_ANYCAST_DELAY, "anycast_delay" },
+ { NET_NEIGH_PROXY_DELAY, "proxy_delay" },
+ { NET_NEIGH_LOCKTIME, "locktime" },
+ { NET_NEIGH_GC_INTERVAL, "gc_interval" },
+ { NET_NEIGH_GC_THRESH1, "gc_thresh1" },
+ { NET_NEIGH_GC_THRESH2, "gc_thresh2" },
+ { NET_NEIGH_GC_THRESH3, "gc_thresh3" },
+ { NET_NEIGH_RETRANS_TIME_MS, "retrans_time_ms" },
+ { NET_NEIGH_REACHABLE_TIME_MS, "base_reachable_time_ms" },
+ {}
+};
+
+static struct trans_ctl_table trans_net_neigh_table[] = {
+ { NET_PROTO_CONF_DEFAULT, "default", trans_net_neigh_vars_table },
+ { 0, NULL, trans_net_neigh_vars_table },
+ {}
+};
+
+static struct trans_ctl_table trans_net_ipv4_netfilter_table[] = {
+ { NET_IPV4_NF_CONNTRACK_MAX, "ip_conntrack_max" },
+
+ { NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT, "ip_conntrack_tcp_timeout_syn_sent" },
+ { NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV, "ip_conntrack_tcp_timeout_syn_recv" },
+ { NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED, "ip_conntrack_tcp_timeout_established" },
+ { NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT, "ip_conntrack_tcp_timeout_fin_wait" },
+ { NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT, "ip_conntrack_tcp_timeout_close_wait" },
+ { NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK, "ip_conntrack_tcp_timeout_last_ack" },
+ { NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT, "ip_conntrack_tcp_timeout_time_wait" },
+ { NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE, "ip_conntrack_tcp_timeout_close" },
+
+ { NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT, "ip_conntrack_udp_timeout" },
+ { NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT_STREAM, "ip_conntrack_udp_timeout_stream" },
+ { NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT, "ip_conntrack_icmp_timeout" },
+ { NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT, "ip_conntrack_generic_timeout" },
+
+ { NET_IPV4_NF_CONNTRACK_BUCKETS, "ip_conntrack_buckets" },
+ { NET_IPV4_NF_CONNTRACK_LOG_INVALID, "ip_conntrack_log_invalid" },
+ { NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_MAX_RETRANS, "ip_conntrack_tcp_timeout_max_retrans" },
+ { NET_IPV4_NF_CONNTRACK_TCP_LOOSE, "ip_conntrack_tcp_loose" },
+ { NET_IPV4_NF_CONNTRACK_TCP_BE_LIBERAL, "ip_conntrack_tcp_be_liberal" },
+ { NET_IPV4_NF_CONNTRACK_TCP_MAX_RETRANS, "ip_conntrack_tcp_max_retrans" },
+
+ { NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_CLOSED, "ip_conntrack_sctp_timeout_closed" },
+ { NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_WAIT, "ip_conntrack_sctp_timeout_cookie_wait" },
+ { NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_ECHOED, "ip_conntrack_sctp_timeout_cookie_echoed" },
+ { NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_ESTABLISHED, "ip_conntrack_sctp_timeout_established" },
+ { NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_SENT, "ip_conntrack_sctp_timeout_shutdown_sent" },
+ { NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_RECD, "ip_conntrack_sctp_timeout_shutdown_recd" },
+ { NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_ACK_SENT, "ip_conntrack_sctp_timeout_shutdown_ack_sent" },
+
+ { NET_IPV4_NF_CONNTRACK_COUNT, "ip_conntrack_count" },
+ { NET_IPV4_NF_CONNTRACK_CHECKSUM, "ip_conntrack_checksum" },
+ {}
+};
+
+static struct trans_ctl_table trans_net_ipv4_table[] = {
+ { NET_IPV4_FORWARD, "ip_forward" },
+ { NET_IPV4_DYNADDR, "ip_dynaddr" },
+
+ { NET_IPV4_CONF, "conf", trans_net_ipv4_conf_table },
+ { NET_IPV4_NEIGH, "neigh", trans_net_neigh_table },
+ { NET_IPV4_ROUTE, "route", trans_net_ipv4_route_table },
+ /* NET_IPV4_FIB_HASH unused */
+ { NET_IPV4_NETFILTER, "netfilter", trans_net_ipv4_netfilter_table },
+ { NET_IPV4_VS, "vs", trans_net_ipv4_vs_table },
+
+ { NET_IPV4_TCP_TIMESTAMPS, "tcp_timestamps" },
+ { NET_IPV4_TCP_WINDOW_SCALING, "tcp_window_scaling" },
+ { NET_IPV4_TCP_SACK, "tcp_sack" },
+ { NET_IPV4_TCP_RETRANS_COLLAPSE, "tcp_retrans_collapse" },
+ { NET_IPV4_DEFAULT_TTL, "ip_default_ttl" },
+ /* NET_IPV4_AUTOCONFIG unused */
+ { NET_IPV4_NO_PMTU_DISC, "ip_no_pmtu_disc" },
+ { NET_IPV4_TCP_SYN_RETRIES, "tcp_syn_retries" },
+ { NET_IPV4_IPFRAG_HIGH_THRESH, "ipfrag_high_thresh" },
+ { NET_IPV4_IPFRAG_LOW_THRESH, "ipfrag_low_thresh" },
+ { NET_IPV4_IPFRAG_TIME, "ipfrag_time" },
+ /* NET_IPV4_TCP_MAX_KA_PROBES unused */
+ { NET_IPV4_TCP_KEEPALIVE_TIME, "tcp_keepalive_time" },
+ { NET_IPV4_TCP_KEEPALIVE_PROBES, "tcp_keepalive_probes" },
+ { NET_IPV4_TCP_RETRIES1, "tcp_retries1" },
+ { NET_IPV4_TCP_RETRIES2, "tcp_retries2" },
+ { NET_IPV4_TCP_FIN_TIMEOUT, "tcp_fin_timeout" },
+ /* NET_IPV4_IP_MASQ_DEBUG unused */
+ { NET_TCP_SYNCOOKIES, "tcp_syncookies" },
+ { NET_TCP_STDURG, "tcp_stdurg" },
+ { NET_TCP_RFC1337, "tcp_rfc1337" },
+ /* NET_TCP_SYN_TAILDROP unused */
+ { NET_TCP_MAX_SYN_BACKLOG, "tcp_max_syn_backlog" },
+ { NET_IPV4_LOCAL_PORT_RANGE, "ip_local_port_range" },
+ { NET_IPV4_ICMP_ECHO_IGNORE_ALL, "icmp_echo_ignore_all" },
+ { NET_IPV4_ICMP_ECHO_IGNORE_BROADCASTS, "icmp_echo_ignore_broadcasts" },
+ /* NET_IPV4_ICMP_SOURCEQUENCH_RATE unused */
+ /* NET_IPV4_ICMP_DESTUNREACH_RATE unused */
+ /* NET_IPV4_ICMP_TIMEEXCEED_RATE unused */
+ /* NET_IPV4_ICMP_PARAMPROB_RATE unused */
+ /* NET_IPV4_ICMP_ECHOREPLY_RATE unused */
+ { NET_IPV4_ICMP_IGNORE_BOGUS_ERROR_RESPONSES, "icmp_ignore_bogus_error_responses" },
+ { NET_IPV4_IGMP_MAX_MEMBERSHIPS, "igmp_max_memberships" },
+ { NET_TCP_TW_RECYCLE, "tcp_tw_recycle" },
+ /* NET_IPV4_ALWAYS_DEFRAG unused */
+ { NET_IPV4_TCP_KEEPALIVE_INTVL, "tcp_keepalive_intvl" },
+ { NET_IPV4_INET_PEER_THRESHOLD, "inet_peer_threshold" },
+ { NET_IPV4_INET_PEER_MINTTL, "inet_peer_minttl" },
+ { NET_IPV4_INET_PEER_MAXTTL, "inet_peer_maxttl" },
+ { NET_IPV4_INET_PEER_GC_MINTIME, "inet_peer_gc_mintime" },
+ { NET_IPV4_INET_PEER_GC_MAXTIME, "inet_peer_gc_maxtime" },
+ { NET_TCP_ORPHAN_RETRIES, "tcp_orphan_retries" },
+ { NET_TCP_ABORT_ON_OVERFLOW, "tcp_abort_on_overflow" },
+ { NET_TCP_SYNACK_RETRIES, "tcp_synack_retries" },
+ { NET_TCP_MAX_ORPHANS, "tcp_max_orphans" },
+ { NET_TCP_MAX_TW_BUCKETS, "tcp_max_tw_buckets" },
+ { NET_TCP_FACK, "tcp_fack" },
+ { NET_TCP_REORDERING, "tcp_reordering" },
+ { NET_TCP_ECN, "tcp_ecn" },
+ { NET_TCP_DSACK, "tcp_dsack" },
+ { NET_TCP_MEM, "tcp_mem" },
+ { NET_TCP_WMEM, "tcp_wmem" },
+ { NET_TCP_RMEM, "tcp_rmem" },
+ { NET_TCP_APP_WIN, "tcp_app_win" },
+ { NET_TCP_ADV_WIN_SCALE, "tcp_adv_win_scale" },
+ { NET_IPV4_NONLOCAL_BIND, "ip_nonlocal_bind" },
+ { NET_IPV4_ICMP_RATELIMIT, "icmp_ratelimit" },
+ { NET_IPV4_ICMP_RATEMASK, "icmp_ratemask" },
+ { NET_TCP_TW_REUSE, "tcp_tw_reuse" },
+ { NET_TCP_FRTO, "tcp_frto" },
+ { NET_TCP_LOW_LATENCY, "tcp_low_latency" },
+ { NET_IPV4_IPFRAG_SECRET_INTERVAL, "ipfrag_secret_interval" },
+ { NET_IPV4_IGMP_MAX_MSF, "igmp_max_msf" },
+ { NET_TCP_NO_METRICS_SAVE, "tcp_no_metrics_save" },
+ /* NET_TCP_DEFAULT_WIN_SCALE unused */
+ { NET_TCP_MODERATE_RCVBUF, "tcp_moderate_rcvbuf" },
+ { NET_TCP_TSO_WIN_DIVISOR, "tcp_tso_win_divisor" },
+ /* NET_TCP_BIC_BETA unused */
+ { NET_IPV4_ICMP_ERRORS_USE_INBOUND_IFADDR, "icmp_errors_use_inbound_ifaddr" },
+ { NET_TCP_CONG_CONTROL, "tcp_congestion_control" },
+ { NET_TCP_ABC, "tcp_abc" },
+ { NET_IPV4_IPFRAG_MAX_DIST, "ipfrag_max_dist" },
+ { NET_TCP_MTU_PROBING, "tcp_mtu_probing" },
+ { NET_TCP_BASE_MSS, "tcp_base_mss" },
+ { NET_IPV4_TCP_WORKAROUND_SIGNED_WINDOWS, "tcp_workaround_signed_windows" },
+ { NET_TCP_DMA_COPYBREAK, "tcp_dma_copybreak" },
+ { NET_TCP_SLOW_START_AFTER_IDLE, "tcp_slow_start_after_idle" },
+ { NET_CIPSOV4_CACHE_ENABLE, "cipso_cache_enable" },
+ { NET_CIPSOV4_CACHE_BUCKET_SIZE, "cipso_cache_bucket_size" },
+ { NET_CIPSOV4_RBM_OPTFMT, "cipso_rbm_optfmt" },
+ { NET_CIPSOV4_RBM_STRICTVALID, "cipso_rbm_strictvalid" },
+ { NET_TCP_AVAIL_CONG_CONTROL, "tcp_available_congestion_control" },
+ { NET_TCP_ALLOWED_CONG_CONTROL, "tcp_allowed_congestion_control" },
+ { NET_TCP_MAX_SSTHRESH, "tcp_max_ssthresh" },
+ { NET_TCP_FRTO_RESPONSE, "tcp_frto_response" },
+ { 2088 /* NET_IPQ_QMAX */, "ip_queue_maxlen" },
+ {}
+};
+
+static struct trans_ctl_table trans_net_ipx_table[] = {
+ { NET_IPX_PPROP_BROADCASTING, "ipx_pprop_broadcasting" },
+ /* NET_IPX_FORWARDING unused */
+ {}
+};
+
+static struct trans_ctl_table trans_net_atalk_table[] = {
+ { NET_ATALK_AARP_EXPIRY_TIME, "aarp-expiry-time" },
+ { NET_ATALK_AARP_TICK_TIME, "aarp-tick-time" },
+ { NET_ATALK_AARP_RETRANSMIT_LIMIT, "aarp-retransmit-limit" },
+ { NET_ATALK_AARP_RESOLVE_TIME, "aarp-resolve-time" },
+ {},
+};
+
+static struct trans_ctl_table trans_net_netrom_table[] = {
+ { NET_NETROM_DEFAULT_PATH_QUALITY, "default_path_quality" },
+ { NET_NETROM_OBSOLESCENCE_COUNT_INITIALISER, "obsolescence_count_initialiser" },
+ { NET_NETROM_NETWORK_TTL_INITIALISER, "network_ttl_initialiser" },
+ { NET_NETROM_TRANSPORT_TIMEOUT, "transport_timeout" },
+ { NET_NETROM_TRANSPORT_MAXIMUM_TRIES, "transport_maximum_tries" },
+ { NET_NETROM_TRANSPORT_ACKNOWLEDGE_DELAY, "transport_acknowledge_delay" },
+ { NET_NETROM_TRANSPORT_BUSY_DELAY, "transport_busy_delay" },
+ { NET_NETROM_TRANSPORT_REQUESTED_WINDOW_SIZE, "transport_requested_window_size" },
+ { NET_NETROM_TRANSPORT_NO_ACTIVITY_TIMEOUT, "transport_no_activity_timeout" },
+ { NET_NETROM_ROUTING_CONTROL, "routing_control" },
+ { NET_NETROM_LINK_FAILS_COUNT, "link_fails_count" },
+ { NET_NETROM_RESET, "reset" },
+ {}
+};
+
+static struct trans_ctl_table trans_net_ax25_table[] = {
+ { NET_AX25_IP_DEFAULT_MODE, "ip_default_mode" },
+ { NET_AX25_DEFAULT_MODE, "ax25_default_mode" },
+ { NET_AX25_BACKOFF_TYPE, "backoff_type" },
+ { NET_AX25_CONNECT_MODE, "connect_mode" },
+ { NET_AX25_STANDARD_WINDOW, "standard_window_size" },
+ { NET_AX25_EXTENDED_WINDOW, "extended_window_size" },
+ { NET_AX25_T1_TIMEOUT, "t1_timeout" },
+ { NET_AX25_T2_TIMEOUT, "t2_timeout" },
+ { NET_AX25_T3_TIMEOUT, "t3_timeout" },
+ { NET_AX25_IDLE_TIMEOUT, "idle_timeout" },
+ { NET_AX25_N2, "maximum_retry_count" },
+ { NET_AX25_PACLEN, "maximum_packet_length" },
+ { NET_AX25_PROTOCOL, "protocol" },
+ { NET_AX25_DAMA_SLAVE_TIMEOUT, "dama_slave_timeout" },
+ {}
+};
+
+static struct trans_ctl_table trans_net_bridge_table[] = {
+ { NET_BRIDGE_NF_CALL_ARPTABLES, "bridge-nf-call-arptables" },
+ { NET_BRIDGE_NF_CALL_IPTABLES, "bridge-nf-call-iptables" },
+ { NET_BRIDGE_NF_CALL_IP6TABLES, "bridge-nf-call-ip6tables" },
+ { NET_BRIDGE_NF_FILTER_VLAN_TAGGED, "bridge-nf-filter-vlan-tagged" },
+ { NET_BRIDGE_NF_FILTER_PPPOE_TAGGED, "bridge-nf-filter-pppoe-tagged" },
+ {}
+};
+
+static struct trans_ctl_table trans_net_rose_table[] = {
+ { NET_ROSE_RESTART_REQUEST_TIMEOUT, "restart_request_timeout" },
+ { NET_ROSE_CALL_REQUEST_TIMEOUT, "call_request_timeout" },
+ { NET_ROSE_RESET_REQUEST_TIMEOUT, "reset_request_timeout" },
+ { NET_ROSE_CLEAR_REQUEST_TIMEOUT, "clear_request_timeout" },
+ { NET_ROSE_ACK_HOLD_BACK_TIMEOUT, "acknowledge_hold_back_timeout" },
+ { NET_ROSE_ROUTING_CONTROL, "routing_control" },
+ { NET_ROSE_LINK_FAIL_TIMEOUT, "link_fail_timeout" },
+ { NET_ROSE_MAX_VCS, "maximum_virtual_circuits" },
+ { NET_ROSE_WINDOW_SIZE, "window_size" },
+ { NET_ROSE_NO_ACTIVITY_TIMEOUT, "no_activity_timeout" },
+ {}
+};
+
+static struct trans_ctl_table trans_net_ipv6_conf_var_table[] = {
+ { NET_IPV6_FORWARDING, "forwarding" },
+ { NET_IPV6_HOP_LIMIT, "hop_limit" },
+ { NET_IPV6_MTU, "mtu" },
+ { NET_IPV6_ACCEPT_RA, "accept_ra" },
+ { NET_IPV6_ACCEPT_REDIRECTS, "accept_redirects" },
+ { NET_IPV6_AUTOCONF, "autoconf" },
+ { NET_IPV6_DAD_TRANSMITS, "dad_transmits" },
+ { NET_IPV6_RTR_SOLICITS, "router_solicitations" },
+ { NET_IPV6_RTR_SOLICIT_INTERVAL, "router_solicitation_interval" },
+ { NET_IPV6_RTR_SOLICIT_DELAY, "router_solicitation_delay" },
+ { NET_IPV6_USE_TEMPADDR, "use_tempaddr" },
+ { NET_IPV6_TEMP_VALID_LFT, "temp_valid_lft" },
+ { NET_IPV6_TEMP_PREFERED_LFT, "temp_prefered_lft" },
+ { NET_IPV6_REGEN_MAX_RETRY, "regen_max_retry" },
+ { NET_IPV6_MAX_DESYNC_FACTOR, "max_desync_factor" },
+ { NET_IPV6_MAX_ADDRESSES, "max_addresses" },
+ { NET_IPV6_FORCE_MLD_VERSION, "force_mld_version" },
+ { NET_IPV6_ACCEPT_RA_DEFRTR, "accept_ra_defrtr" },
+ { NET_IPV6_ACCEPT_RA_PINFO, "accept_ra_pinfo" },
+ { NET_IPV6_ACCEPT_RA_RTR_PREF, "accept_ra_rtr_pref" },
+ { NET_IPV6_RTR_PROBE_INTERVAL, "router_probe_interval" },
+ { NET_IPV6_ACCEPT_RA_RT_INFO_MAX_PLEN, "accept_ra_rt_info_max_plen" },
+ { NET_IPV6_PROXY_NDP, "proxy_ndp" },
+ { NET_IPV6_ACCEPT_SOURCE_ROUTE, "accept_source_route" },
+ {}
+};
+
+static struct trans_ctl_table trans_net_ipv6_conf_table[] = {
+ { NET_PROTO_CONF_ALL, "all", trans_net_ipv6_conf_var_table },
+ { NET_PROTO_CONF_DEFAULT, "default", trans_net_ipv6_conf_var_table },
+ { 0, NULL, trans_net_ipv6_conf_var_table },
+ {}
+};
+
+static struct trans_ctl_table trans_net_ipv6_route_table[] = {
+ { NET_IPV6_ROUTE_FLUSH, "flush" },
+ { NET_IPV6_ROUTE_GC_THRESH, "gc_thresh" },
+ { NET_IPV6_ROUTE_MAX_SIZE, "max_size" },
+ { NET_IPV6_ROUTE_GC_MIN_INTERVAL, "gc_min_interval" },
+ { NET_IPV6_ROUTE_GC_TIMEOUT, "gc_timeout" },
+ { NET_IPV6_ROUTE_GC_INTERVAL, "gc_interval" },
+ { NET_IPV6_ROUTE_GC_ELASTICITY, "gc_elasticity" },
+ { NET_IPV6_ROUTE_MTU_EXPIRES, "mtu_expires" },
+ { NET_IPV6_ROUTE_MIN_ADVMSS, "min_adv_mss" },
+ { NET_IPV6_ROUTE_GC_MIN_INTERVAL_MS, "gc_min_interval_ms" },
+ {}
+};
+
+static struct trans_ctl_table trans_net_ipv6_icmp_table[] = {
+ { NET_IPV6_ICMP_RATELIMIT, "ratelimit" },
+ {}
+};
+
+static struct trans_ctl_table trans_net_ipv6_table[] = {
+ { NET_IPV6_CONF, "conf", trans_net_ipv6_conf_table },
+ { NET_IPV6_NEIGH, "neigh", trans_net_neigh_table },
+ { NET_IPV6_ROUTE, "route", trans_net_ipv6_route_table },
+ { NET_IPV6_ICMP, "icmp", trans_net_ipv6_icmp_table },
+ { NET_IPV6_BINDV6ONLY, "bindv6only" },
+ { NET_IPV6_IP6FRAG_HIGH_THRESH, "ip6frag_high_thresh" },
+ { NET_IPV6_IP6FRAG_LOW_THRESH, "ip6frag_low_thresh" },
+ { NET_IPV6_IP6FRAG_TIME, "ip6frag_time" },
+ { NET_IPV6_IP6FRAG_SECRET_INTERVAL, "ip6frag_secret_interval" },
+ { NET_IPV6_MLD_MAX_MSF, "mld_max_msf" },
+ { 2088 /* IPQ_QMAX */, "ip6_queue_maxlen" },
+ {}
+};
+
+static struct trans_ctl_table trans_net_x25_table[] = {
+ { NET_X25_RESTART_REQUEST_TIMEOUT, "restart_request_timeout" },
+ { NET_X25_CALL_REQUEST_TIMEOUT, "call_request_timeout" },
+ { NET_X25_RESET_REQUEST_TIMEOUT, "reset_request_timeout" },
+ { NET_X25_CLEAR_REQUEST_TIMEOUT, "clear_request_timeout" },
+ { NET_X25_ACK_HOLD_BACK_TIMEOUT, "acknowledgement_hold_back_timeout" },
+ { NET_X25_FORWARD, "x25_forward" },
+ {}
+};
+
+static struct trans_ctl_table trans_net_tr_table[] = {
+ { NET_TR_RIF_TIMEOUT, "rif_timeout" },
+ {}
+};
+
+
+static struct trans_ctl_table trans_net_decnet_conf_vars[] = {
+ { NET_DECNET_CONF_DEV_FORWARDING, "forwarding" },
+ { NET_DECNET_CONF_DEV_PRIORITY, "priority" },
+ { NET_DECNET_CONF_DEV_T2, "t2" },
+ { NET_DECNET_CONF_DEV_T3, "t3" },
+ {}
+};
+
+static struct trans_ctl_table trans_net_decnet_conf[] = {
+ { 0, NULL, trans_net_decnet_conf_vars },
+ {}
+};
+
+static struct trans_ctl_table trans_net_decnet_table[] = {
+ { NET_DECNET_CONF, "conf", trans_net_decnet_conf },
+ { NET_DECNET_NODE_ADDRESS, "node_address" },
+ { NET_DECNET_NODE_NAME, "node_name" },
+ { NET_DECNET_DEFAULT_DEVICE, "default_device" },
+ { NET_DECNET_TIME_WAIT, "time_wait" },
+ { NET_DECNET_DN_COUNT, "dn_count" },
+ { NET_DECNET_DI_COUNT, "di_count" },
+ { NET_DECNET_DR_COUNT, "dr_count" },
+ { NET_DECNET_DST_GC_INTERVAL, "dst_gc_interval" },
+ { NET_DECNET_NO_FC_MAX_CWND, "no_fc_max_cwnd" },
+ { NET_DECNET_MEM, "decnet_mem" },
+ { NET_DECNET_RMEM, "decnet_rmem" },
+ { NET_DECNET_WMEM, "decnet_wmem" },
+ { NET_DECNET_DEBUG_LEVEL, "debug" },
+ {}
+};
+
+static struct trans_ctl_table trans_net_sctp_table[] = {
+ { NET_SCTP_RTO_INITIAL, "rto_initial" },
+ { NET_SCTP_RTO_MIN, "rto_min" },
+ { NET_SCTP_RTO_MAX, "rto_max" },
+ { NET_SCTP_RTO_ALPHA, "rto_alpha_exp_divisor" },
+ { NET_SCTP_RTO_BETA, "rto_beta_exp_divisor" },
+ { NET_SCTP_VALID_COOKIE_LIFE, "valid_cookie_life" },
+ { NET_SCTP_ASSOCIATION_MAX_RETRANS, "association_max_retrans" },
+ { NET_SCTP_PATH_MAX_RETRANS, "path_max_retrans" },
+ { NET_SCTP_MAX_INIT_RETRANSMITS, "max_init_retransmits" },
+ { NET_SCTP_HB_INTERVAL, "hb_interval" },
+ { NET_SCTP_PRESERVE_ENABLE, "cookie_preserve_enable" },
+ { NET_SCTP_MAX_BURST, "max_burst" },
+ { NET_SCTP_ADDIP_ENABLE, "addip_enable" },
+ { NET_SCTP_PRSCTP_ENABLE, "prsctp_enable" },
+ { NET_SCTP_SNDBUF_POLICY, "sndbuf_policy" },
+ { NET_SCTP_SACK_TIMEOUT, "sack_timeout" },
+ { NET_SCTP_RCVBUF_POLICY, "rcvbuf_policy" },
+ {}
+};
+
+static struct trans_ctl_table trans_net_llc_llc2_timeout_table[] = {
+ { NET_LLC2_ACK_TIMEOUT, "ack" },
+ { NET_LLC2_P_TIMEOUT, "p" },
+ { NET_LLC2_REJ_TIMEOUT, "rej" },
+ { NET_LLC2_BUSY_TIMEOUT, "busy" },
+ {}
+};
+
+static struct trans_ctl_table trans_net_llc_station_table[] = {
+ { NET_LLC_STATION_ACK_TIMEOUT, "ack_timeout" },
+ {}
+};
+
+static struct trans_ctl_table trans_net_llc_llc2_table[] = {
+ { NET_LLC2, "timeout", trans_net_llc_llc2_timeout_table },
+ {}
+};
+
+static struct trans_ctl_table trans_net_llc_table[] = {
+ { NET_LLC2, "llc2", trans_net_llc_llc2_table },
+ { NET_LLC_STATION, "station", trans_net_llc_station_table },
+ {}
+};
+
+static struct trans_ctl_table trans_net_netfilter_table[] = {
+ { NET_NF_CONNTRACK_MAX, "nf_conntrack_max" },
+ { NET_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT, "nf_conntrack_tcp_timeout_syn_sent" },
+ { NET_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV, "nf_conntrack_tcp_timeout_syn_recv" },
+ { NET_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED, "nf_conntrack_tcp_timeout_established" },
+ { NET_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT, "nf_conntrack_tcp_timeout_fin_wait" },
+ { NET_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT, "nf_conntrack_tcp_timeout_close_wait" },
+ { NET_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK, "nf_conntrack_tcp_timeout_last_ack" },
+ { NET_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT, "nf_conntrack_tcp_timeout_time_wait" },
+ { NET_NF_CONNTRACK_TCP_TIMEOUT_CLOSE, "nf_conntrack_tcp_timeout_close" },
+ { NET_NF_CONNTRACK_UDP_TIMEOUT, "nf_conntrack_udp_timeout" },
+ { NET_NF_CONNTRACK_UDP_TIMEOUT_STREAM, "nf_conntrack_udp_timeout_stream" },
+ { NET_NF_CONNTRACK_ICMP_TIMEOUT, "nf_conntrack_icmp_timeout" },
+ { NET_NF_CONNTRACK_GENERIC_TIMEOUT, "nf_conntrack_generic_timeout" },
+ { NET_NF_CONNTRACK_BUCKETS, "nf_conntrack_buckets" },
+ { NET_NF_CONNTRACK_LOG_INVALID, "nf_conntrack_log_invalid" },
+ { NET_NF_CONNTRACK_TCP_TIMEOUT_MAX_RETRANS, "nf_conntrack_tcp_timeout_max_retrans" },
+ { NET_NF_CONNTRACK_TCP_LOOSE, "nf_conntrack_tcp_loose" },
+ { NET_NF_CONNTRACK_TCP_BE_LIBERAL, "nf_conntrack_tcp_be_liberal" },
+ { NET_NF_CONNTRACK_TCP_MAX_RETRANS, "nf_conntrack_tcp_max_retrans" },
+ { NET_NF_CONNTRACK_SCTP_TIMEOUT_CLOSED, "nf_conntrack_sctp_timeout_closed" },
+ { NET_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_WAIT, "nf_conntrack_sctp_timeout_cookie_wait" },
+ { NET_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_ECHOED, "nf_conntrack_sctp_timeout_cookie_echoed" },
+ { NET_NF_CONNTRACK_SCTP_TIMEOUT_ESTABLISHED, "nf_conntrack_sctp_timeout_established" },
+ { NET_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_SENT, "nf_conntrack_sctp_timeout_shutdown_sent" },
+ { NET_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_RECD, "nf_conntrack_sctp_timeout_shutdown_recd" },
+ { NET_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_ACK_SENT, "nf_conntrack_sctp_timeout_shutdown_ack_sent" },
+ { NET_NF_CONNTRACK_COUNT, "nf_conntrack_count" },
+ { NET_NF_CONNTRACK_ICMPV6_TIMEOUT, "nf_conntrack_icmpv6_timeout" },
+ { NET_NF_CONNTRACK_FRAG6_TIMEOUT, "nf_conntrack_frag6_timeout" },
+ { NET_NF_CONNTRACK_FRAG6_LOW_THRESH, "nf_conntrack_frag6_low_thresh" },
+ { NET_NF_CONNTRACK_FRAG6_HIGH_THRESH, "nf_conntrack_frag6_high_thresh" },
+ { NET_NF_CONNTRACK_CHECKSUM, "nf_conntrack_checksum" },
+
+ {}
+};
+
+static struct trans_ctl_table trans_net_dccp_table[] = {
+ { NET_DCCP_DEFAULT, "default" },
+ {}
+};
+
+static struct trans_ctl_table trans_net_irda_table[] = {
+ { NET_IRDA_DISCOVERY, "discovery" },
+ { NET_IRDA_DEVNAME, "devname" },
+ { NET_IRDA_DEBUG, "debug" },
+ { NET_IRDA_FAST_POLL, "fast_poll_increase" },
+ { NET_IRDA_DISCOVERY_SLOTS, "discovery_slots" },
+ { NET_IRDA_DISCOVERY_TIMEOUT, "discovery_timeout" },
+ { NET_IRDA_SLOT_TIMEOUT, "slot_timeout" },
+ { NET_IRDA_MAX_BAUD_RATE, "max_baud_rate" },
+ { NET_IRDA_MIN_TX_TURN_TIME, "min_tx_turn_time" },
+ { NET_IRDA_MAX_TX_DATA_SIZE, "max_tx_data_size" },
+ { NET_IRDA_MAX_TX_WINDOW, "max_tx_window" },
+ { NET_IRDA_MAX_NOREPLY_TIME, "max_noreply_time" },
+ { NET_IRDA_WARN_NOREPLY_TIME, "warn_noreply_time" },
+ { NET_IRDA_LAP_KEEPALIVE_TIME, "lap_keepalive_time" },
+ {}
+};
+
+static struct trans_ctl_table trans_net_table[] = {
+ { NET_CORE, "core", trans_net_core_table },
+ /* NET_ETHER not used */
+ /* NET_802 not used */
+ { NET_UNIX, "unix", trans_net_unix_table },
+ { NET_IPV4, "ipv4", trans_net_ipv4_table },
+ { NET_IPX, "ipx", trans_net_ipx_table },
+ { NET_ATALK, "appletalk", trans_net_atalk_table },
+ { NET_NETROM, "netrom", trans_net_netrom_table },
+ { NET_AX25, "ax25", trans_net_ax25_table },
+ { NET_BRIDGE, "bridge", trans_net_bridge_table },
+ { NET_ROSE, "rose", trans_net_rose_table },
+ { NET_IPV6, "ipv6", trans_net_ipv6_table },
+ { NET_X25, "x25", trans_net_x25_table },
+ { NET_TR, "token-ring", trans_net_tr_table },
+ { NET_DECNET, "decnet", trans_net_decnet_table },
+ /* NET_ECONET not used */
+ { NET_SCTP, "sctp", trans_net_sctp_table },
+ { NET_LLC, "llc", trans_net_llc_table },
+ { NET_NETFILTER, "netfilter", trans_net_netfilter_table },
+ { NET_DCCP, "dccp", trans_net_dccp_table },
+ { NET_IRDA, "irda", trans_net_irda_table },
+ { 2089, "nf_conntrack_max" },
+ {}
+};
+
+static struct trans_ctl_table trans_fs_quota_table[] = {
+ { FS_DQ_LOOKUPS, "lookups" },
+ { FS_DQ_DROPS, "drops" },
+ { FS_DQ_READS, "reads" },
+ { FS_DQ_WRITES, "writes" },
+ { FS_DQ_CACHE_HITS, "cache_hits" },
+ { FS_DQ_ALLOCATED, "allocated_dquots" },
+ { FS_DQ_FREE, "free_dquots" },
+ { FS_DQ_SYNCS, "syncs" },
+ { FS_DQ_WARNINGS, "warnings" },
+ {}
+};
+
+static struct trans_ctl_table trans_fs_xfs_table[] = {
+ { XFS_RESTRICT_CHOWN, "restrict_chown" },
+ { XFS_SGID_INHERIT, "irix_sgid_inherit" },
+ { XFS_SYMLINK_MODE, "irix_symlink_mode" },
+ { XFS_PANIC_MASK, "panic_mask" },
+
+ { XFS_ERRLEVEL, "error_level" },
+ { XFS_SYNCD_TIMER, "xfssyncd_centisecs" },
+ { XFS_INHERIT_SYNC, "inherit_sync" },
+ { XFS_INHERIT_NODUMP, "inherit_nodump" },
+ { XFS_INHERIT_NOATIME, "inherit_noatime" },
+ { XFS_BUF_TIMER, "xfsbufd_centisecs" },
+ { XFS_BUF_AGE, "age_buffer_centisecs" },
+ { XFS_INHERIT_NOSYM, "inherit_nosymlinks" },
+ { XFS_ROTORSTEP, "rotorstep" },
+ { XFS_INHERIT_NODFRG, "inherit_nodefrag" },
+ { XFS_FILESTREAM_TIMER, "filestream_centisecs" },
+ { XFS_STATS_CLEAR, "stats_clear" },
+ {}
+};
+
+static struct trans_ctl_table trans_fs_ocfs2_nm_table[] = {
+ { 1, "hb_ctl_path" },
+ {}
+};
+
+static struct trans_ctl_table trans_fs_ocfs2_table[] = {
+ { 1, "nm", trans_fs_ocfs2_nm_table },
+ {}
+};
+
+static struct trans_ctl_table trans_inotify_table[] = {
+ { INOTIFY_MAX_USER_INSTANCES, "max_user_instances" },
+ { INOTIFY_MAX_USER_WATCHES, "max_user_watches" },
+ { INOTIFY_MAX_QUEUED_EVENTS, "max_queued_events" },
+ {}
+};
+
+static struct trans_ctl_table trans_fs_table[] = {
+ { FS_NRINODE, "inode-nr" },
+ { FS_STATINODE, "inode-state" },
+ /* FS_MAXINODE unused */
+ /* FS_NRDQUOT unused */
+ /* FS_MAXDQUOT unused */
+ { FS_NRFILE, "file-nr" },
+ { FS_MAXFILE, "file-max" },
+ { FS_DENTRY, "dentry-state" },
+ /* FS_NRSUPER unused */
+ /* FS_MAXUPSER unused */
+ { FS_OVERFLOWUID, "overflowuid" },
+ { FS_OVERFLOWGID, "overflowgid" },
+ { FS_LEASES, "leases-enable" },
+ { FS_DIR_NOTIFY, "dir-notify-enable" },
+ { FS_LEASE_TIME, "lease-break-time" },
+ { FS_DQSTATS, "quota", trans_fs_quota_table },
+ { FS_XFS, "xfs", trans_fs_xfs_table },
+ { FS_AIO_NR, "aio-nr" },
+ { FS_AIO_MAX_NR, "aio-max-nr" },
+ { FS_INOTIFY, "inotify", trans_inotify_table },
+ { FS_OCFS2, "ocfs2", trans_fs_ocfs2_table },
+ { KERN_SETUID_DUMPABLE, "suid_dumpable" },
+ {}
+};
+
+static struct trans_ctl_table trans_debug_table[] = {
+ {}
+};
+
+static struct trans_ctl_table trans_cdrom_table[] = {
+ { DEV_CDROM_INFO, "info" },
+ { DEV_CDROM_AUTOCLOSE, "autoclose" },
+ { DEV_CDROM_AUTOEJECT, "autoeject" },
+ { DEV_CDROM_DEBUG, "debug" },
+ { DEV_CDROM_LOCK, "lock" },
+ { DEV_CDROM_CHECK_MEDIA, "check_media" },
+ {}
+};
+
+static struct trans_ctl_table trans_ipmi_table[] = {
+ { DEV_IPMI_POWEROFF_POWERCYCLE, "poweroff_powercycle" },
+ {}
+};
+
+static struct trans_ctl_table trans_mac_hid_files[] = {
+ /* DEV_MAC_HID_KEYBOARD_SENDS_LINUX_KEYCODES unused */
+ /* DEV_MAC_HID_KEYBOARD_LOCK_KEYCODES unused */
+ { DEV_MAC_HID_MOUSE_BUTTON_EMULATION, "mouse_button_emulation" },
+ { DEV_MAC_HID_MOUSE_BUTTON2_KEYCODE, "mouse_button2_keycode" },
+ { DEV_MAC_HID_MOUSE_BUTTON3_KEYCODE, "mouse_button3_keycode" },
+ /* DEV_MAC_HID_ADB_MOUSE_SENDS_KEYCODES unused */
+ {}
+};
+
+static struct trans_ctl_table trans_raid_table[] = {
+ { DEV_RAID_SPEED_LIMIT_MIN, "speed_limit_min" },
+ { DEV_RAID_SPEED_LIMIT_MAX, "speed_limit_max" },
+ {}
+};
+
+static struct trans_ctl_table trans_scsi_table[] = {
+ { DEV_SCSI_LOGGING_LEVEL, "logging_level" },
+ {}
+};
+
+static struct trans_ctl_table trans_parport_default_table[] = {
+ { DEV_PARPORT_DEFAULT_TIMESLICE, "timeslice" },
+ { DEV_PARPORT_DEFAULT_SPINTIME, "spintime" },
+ {}
+};
+
+static struct trans_ctl_table trans_parport_device_table[] = {
+ { DEV_PARPORT_DEVICE_TIMESLICE, "timeslice" },
+ {}
+};
+
+static struct trans_ctl_table trans_parport_devices_table[] = {
+ { DEV_PARPORT_DEVICES_ACTIVE, "active" },
+ { 0, NULL, trans_parport_device_table },
+ {}
+};
+
+static struct trans_ctl_table trans_parport_parport_table[] = {
+ { DEV_PARPORT_SPINTIME, "spintime" },
+ { DEV_PARPORT_BASE_ADDR, "base-addr" },
+ { DEV_PARPORT_IRQ, "irq" },
+ { DEV_PARPORT_DMA, "dma" },
+ { DEV_PARPORT_MODES, "modes" },
+ { DEV_PARPORT_DEVICES, "devices", trans_parport_devices_table },
+ { DEV_PARPORT_AUTOPROBE, "autoprobe" },
+ { DEV_PARPORT_AUTOPROBE + 1, "autoprobe0" },
+ { DEV_PARPORT_AUTOPROBE + 2, "autoprobe1" },
+ { DEV_PARPORT_AUTOPROBE + 3, "autoprobe2" },
+ { DEV_PARPORT_AUTOPROBE + 4, "autoprobe3" },
+ {}
+};
+static struct trans_ctl_table trans_parport_table[] = {
+ { DEV_PARPORT_DEFAULT, "default", trans_parport_default_table },
+ { 0, NULL, trans_parport_parport_table },
+ {}
+};
+
+static struct trans_ctl_table trans_dev_table[] = {
+ { DEV_CDROM, "cdrom", trans_cdrom_table },
+ /* DEV_HWMON unused */
+ { DEV_PARPORT, "parport", trans_parport_table },
+ { DEV_RAID, "raid", trans_raid_table },
+ { DEV_MAC_HID, "mac_hid", trans_mac_hid_files },
+ { DEV_SCSI, "scsi", trans_scsi_table },
+ { DEV_IPMI, "ipmi", trans_ipmi_table },
+ {}
+};
+
+static struct trans_ctl_table trans_bus_isa_table[] = {
+ { BUS_ISA_MEM_BASE, "membase" },
+ { BUS_ISA_PORT_BASE, "portbase" },
+ { BUS_ISA_PORT_SHIFT, "portshift" },
+ {}
+};
+
+static struct trans_ctl_table trans_bus_table[] = {
+ { CTL_BUS_ISA, "isa", trans_bus_isa_table },
+ {}
+};
+
+static struct trans_ctl_table trans_arlan_conf_table0[] = {
+ { 1, "spreadingCode" },
+ { 2, "channelNumber" },
+ { 3, "scramblingDisable" },
+ { 4, "txAttenuation" },
+ { 5, "systemId" },
+ { 6, "maxDatagramSize" },
+ { 7, "maxFrameSize" },
+ { 8, "maxRetries" },
+ { 9, "receiveMode" },
+ { 10, "priority" },
+ { 11, "rootOrRepeater" },
+ { 12, "SID" },
+ { 13, "registrationMode" },
+ { 14, "registrationFill" },
+ { 15, "localTalkAddress" },
+ { 16, "codeFormat" },
+ { 17, "numChannels" },
+ { 18, "channel1" },
+ { 19, "channel2" },
+ { 20, "channel3" },
+ { 21, "channel4" },
+ { 22, "txClear" },
+ { 23, "txRetries" },
+ { 24, "txRouting" },
+ { 25, "txScrambled" },
+ { 26, "rxParameter" },
+ { 27, "txTimeoutMs" },
+ { 28, "waitCardTimeout" },
+ { 29, "channelSet" },
+ { 30, "name" },
+ { 31, "waitTime" },
+ { 32, "lParameter" },
+ { 33, "_15" },
+ { 34, "headerSize" },
+ { 36, "tx_delay_ms" },
+ { 37, "retries" },
+ { 38, "ReTransmitPacketMaxSize" },
+ { 39, "waitReTransmitPacketMaxSize" },
+ { 40, "fastReTransCount" },
+ { 41, "driverRetransmissions" },
+ { 42, "txAckTimeoutMs" },
+ { 43, "registrationInterrupts" },
+ { 44, "hardwareType" },
+ { 45, "radioType" },
+ { 46, "writeEEPROM" },
+ { 47, "writeRadioType" },
+ { 48, "entry_exit_debug" },
+ { 49, "debug" },
+ { 50, "in_speed" },
+ { 51, "out_speed" },
+ { 52, "in_speed10" },
+ { 53, "out_speed10" },
+ { 54, "in_speed_max" },
+ { 55, "out_speed_max" },
+ { 56, "measure_rate" },
+ { 57, "pre_Command_Wait" },
+ { 58, "rx_tweak1" },
+ { 59, "rx_tweak2" },
+ { 60, "tx_queue_len" },
+
+ { 150, "arlan0-txRing" },
+ { 151, "arlan0-rxRing" },
+ { 152, "arlan0-18" },
+ { 153, "arlan0-ring" },
+ { 154, "arlan0-shm-cpy" },
+ { 155, "config0" },
+ { 156, "reset0" },
+ {}
+};
+
+static struct trans_ctl_table trans_arlan_conf_table1[] = {
+ { 1, "spreadingCode" },
+ { 2, "channelNumber" },
+ { 3, "scramblingDisable" },
+ { 4, "txAttenuation" },
+ { 5, "systemId" },
+ { 6, "maxDatagramSize" },
+ { 7, "maxFrameSize" },
+ { 8, "maxRetries" },
+ { 9, "receiveMode" },
+ { 10, "priority" },
+ { 11, "rootOrRepeater" },
+ { 12, "SID" },
+ { 13, "registrationMode" },
+ { 14, "registrationFill" },
+ { 15, "localTalkAddress" },
+ { 16, "codeFormat" },
+ { 17, "numChannels" },
+ { 18, "channel1" },
+ { 19, "channel2" },
+ { 20, "channel3" },
+ { 21, "channel4" },
+ { 22, "txClear" },
+ { 23, "txRetries" },
+ { 24, "txRouting" },
+ { 25, "txScrambled" },
+ { 26, "rxParameter" },
+ { 27, "txTimeoutMs" },
+ { 28, "waitCardTimeout" },
+ { 29, "channelSet" },
+ { 30, "name" },
+ { 31, "waitTime" },
+ { 32, "lParameter" },
+ { 33, "_15" },
+ { 34, "headerSize" },
+ { 36, "tx_delay_ms" },
+ { 37, "retries" },
+ { 38, "ReTransmitPacketMaxSize" },
+ { 39, "waitReTransmitPacketMaxSize" },
+ { 40, "fastReTransCount" },
+ { 41, "driverRetransmissions" },
+ { 42, "txAckTimeoutMs" },
+ { 43, "registrationInterrupts" },
+ { 44, "hardwareType" },
+ { 45, "radioType" },
+ { 46, "writeEEPROM" },
+ { 47, "writeRadioType" },
+ { 48, "entry_exit_debug" },
+ { 49, "debug" },
+ { 50, "in_speed" },
+ { 51, "out_speed" },
+ { 52, "in_speed10" },
+ { 53, "out_speed10" },
+ { 54, "in_speed_max" },
+ { 55, "out_speed_max" },
+ { 56, "measure_rate" },
+ { 57, "pre_Command_Wait" },
+ { 58, "rx_tweak1" },
+ { 59, "rx_tweak2" },
+ { 60, "tx_queue_len" },
+
+ { 150, "arlan1-txRing" },
+ { 151, "arlan1-rxRing" },
+ { 152, "arlan1-18" },
+ { 153, "arlan1-ring" },
+ { 154, "arlan1-shm-cpy" },
+ { 155, "config1" },
+ { 156, "reset1" },
+ {}
+};
+
+static struct trans_ctl_table trans_arlan_conf_table2[] = {
+ { 1, "spreadingCode" },
+ { 2, "channelNumber" },
+ { 3, "scramblingDisable" },
+ { 4, "txAttenuation" },
+ { 5, "systemId" },
+ { 6, "maxDatagramSize" },
+ { 7, "maxFrameSize" },
+ { 8, "maxRetries" },
+ { 9, "receiveMode" },
+ { 10, "priority" },
+ { 11, "rootOrRepeater" },
+ { 12, "SID" },
+ { 13, "registrationMode" },
+ { 14, "registrationFill" },
+ { 15, "localTalkAddress" },
+ { 16, "codeFormat" },
+ { 17, "numChannels" },
+ { 18, "channel1" },
+ { 19, "channel2" },
+ { 20, "channel3" },
+ { 21, "channel4" },
+ { 22, "txClear" },
+ { 23, "txRetries" },
+ { 24, "txRouting" },
+ { 25, "txScrambled" },
+ { 26, "rxParameter" },
+ { 27, "txTimeoutMs" },
+ { 28, "waitCardTimeout" },
+ { 29, "channelSet" },
+ { 30, "name" },
+ { 31, "waitTime" },
+ { 32, "lParameter" },
+ { 33, "_15" },
+ { 34, "headerSize" },
+ { 36, "tx_delay_ms" },
+ { 37, "retries" },
+ { 38, "ReTransmitPacketMaxSize" },
+ { 39, "waitReTransmitPacketMaxSize" },
+ { 40, "fastReTransCount" },
+ { 41, "driverRetransmissions" },
+ { 42, "txAckTimeoutMs" },
+ { 43, "registrationInterrupts" },
+ { 44, "hardwareType" },
+ { 45, "radioType" },
+ { 46, "writeEEPROM" },
+ { 47, "writeRadioType" },
+ { 48, "entry_exit_debug" },
+ { 49, "debug" },
+ { 50, "in_speed" },
+ { 51, "out_speed" },
+ { 52, "in_speed10" },
+ { 53, "out_speed10" },
+ { 54, "in_speed_max" },
+ { 55, "out_speed_max" },
+ { 56, "measure_rate" },
+ { 57, "pre_Command_Wait" },
+ { 58, "rx_tweak1" },
+ { 59, "rx_tweak2" },
+ { 60, "tx_queue_len" },
+
+ { 150, "arlan2-txRing" },
+ { 151, "arlan2-rxRing" },
+ { 152, "arlan2-18" },
+ { 153, "arlan2-ring" },
+ { 154, "arlan2-shm-cpy" },
+ { 155, "config2" },
+ { 156, "reset2" },
+ {}
+};
+
+static struct trans_ctl_table trans_arlan_conf_table3[] = {
+ { 1, "spreadingCode" },
+ { 2, "channelNumber" },
+ { 3, "scramblingDisable" },
+ { 4, "txAttenuation" },
+ { 5, "systemId" },
+ { 6, "maxDatagramSize" },
+ { 7, "maxFrameSize" },
+ { 8, "maxRetries" },
+ { 9, "receiveMode" },
+ { 10, "priority" },
+ { 11, "rootOrRepeater" },
+ { 12, "SID" },
+ { 13, "registrationMode" },
+ { 14, "registrationFill" },
+ { 15, "localTalkAddress" },
+ { 16, "codeFormat" },
+ { 17, "numChannels" },
+ { 18, "channel1" },
+ { 19, "channel2" },
+ { 20, "channel3" },
+ { 21, "channel4" },
+ { 22, "txClear" },
+ { 23, "txRetries" },
+ { 24, "txRouting" },
+ { 25, "txScrambled" },
+ { 26, "rxParameter" },
+ { 27, "txTimeoutMs" },
+ { 28, "waitCardTimeout" },
+ { 29, "channelSet" },
+ { 30, "name" },
+ { 31, "waitTime" },
+ { 32, "lParameter" },
+ { 33, "_15" },
+ { 34, "headerSize" },
+ { 36, "tx_delay_ms" },
+ { 37, "retries" },
+ { 38, "ReTransmitPacketMaxSize" },
+ { 39, "waitReTransmitPacketMaxSize" },
+ { 40, "fastReTransCount" },
+ { 41, "driverRetransmissions" },
+ { 42, "txAckTimeoutMs" },
+ { 43, "registrationInterrupts" },
+ { 44, "hardwareType" },
+ { 45, "radioType" },
+ { 46, "writeEEPROM" },
+ { 47, "writeRadioType" },
+ { 48, "entry_exit_debug" },
+ { 49, "debug" },
+ { 50, "in_speed" },
+ { 51, "out_speed" },
+ { 52, "in_speed10" },
+ { 53, "out_speed10" },
+ { 54, "in_speed_max" },
+ { 55, "out_speed_max" },
+ { 56, "measure_rate" },
+ { 57, "pre_Command_Wait" },
+ { 58, "rx_tweak1" },
+ { 59, "rx_tweak2" },
+ { 60, "tx_queue_len" },
+
+ { 150, "arlan3-txRing" },
+ { 151, "arlan3-rxRing" },
+ { 152, "arlan3-18" },
+ { 153, "arlan3-ring" },
+ { 154, "arlan3-shm-cpy" },
+ { 155, "config3" },
+ { 156, "reset3" },
+ {}
+};
+
+static struct trans_ctl_table trans_arlan_table[] = {
+ { 1, "arlan0", trans_arlan_conf_table0 },
+ { 2, "arlan1", trans_arlan_conf_table1 },
+ { 3, "arlan2", trans_arlan_conf_table2 },
+ { 4, "arlan3", trans_arlan_conf_table3 },
+ {}
+};
+
+static struct trans_ctl_table trans_appldata_table[] = {
+ { CTL_APPLDATA_TIMER, "timer" },
+ { CTL_APPLDATA_INTERVAL, "interval" },
+ { CTL_APPLDATA_OS, "os" },
+ { CTL_APPLDATA_NET_SUM, "net_sum" },
+ { CTL_APPLDATA_MEM, "mem" },
+ {}
+
+};
+
+static struct trans_ctl_table trans_s390dbf_table[] = {
+ { 5678 /* CTL_S390DBF_STOPPABLE */, "debug_stoppable" },
+ { 5679 /* CTL_S390DBF_ACTIVE */, "debug_active" },
+ {}
+};
+
+static struct trans_ctl_table trans_sunrpc_table[] = {
+ { CTL_RPCDEBUG, "rpc_debug" },
+ { CTL_NFSDEBUG, "nfs_debug" },
+ { CTL_NFSDDEBUG, "nfsd_debug" },
+ { CTL_NLMDEBUG, "nlm_debug" },
+ { CTL_SLOTTABLE_UDP, "udp_slot_table_entries" },
+ { CTL_SLOTTABLE_TCP, "tcp_slot_table_entries" },
+ { CTL_MIN_RESVPORT, "min_resvport" },
+ { CTL_MAX_RESVPORT, "max_resvport" },
+ {}
+};
+
+static struct trans_ctl_table trans_pm_table[] = {
+ { 1 /* CTL_PM_SUSPEND */, "suspend" },
+ { 2 /* CTL_PM_CMODE */, "cmode" },
+ { 3 /* CTL_PM_P0 */, "p0" },
+ { 4 /* CTL_PM_CM */, "cm" },
+ {}
+};
+
+static struct trans_ctl_table trans_frv_table[] = {
+ { 1, "cache-mode" },
+ { 2, "pin-cxnr" },
+ {}
+};
+
+static struct trans_ctl_table trans_root_table[] = {
+ { CTL_KERN, "kernel", trans_kern_table },
+ { CTL_VM, "vm", trans_vm_table },
+ { CTL_NET, "net", trans_net_table },
+ /* CTL_PROC not used */
+ { CTL_FS, "fs", trans_fs_table },
+ { CTL_DEBUG, "debug", trans_debug_table },
+ { CTL_DEV, "dev", trans_dev_table },
+ { CTL_BUS, "bus", trans_bus_table },
+ { CTL_ABI, "abi" },
+ /* CTL_CPU not used */
+ { CTL_ARLAN, "arlan", trans_arlan_table },
+ { CTL_APPLDATA, "appldata", trans_appldata_table },
+ { CTL_S390DBF, "s390dbf", trans_s390dbf_table },
+ { CTL_SUNRPC, "sunrpc", trans_sunrpc_table },
+ { CTL_PM, "pm", trans_pm_table },
+ { CTL_FRV, "frv", trans_frv_table },
+ {}
+};
+
+
+
+
+static int sysctl_depth(struct ctl_table *table)
+{
+ struct ctl_table *tmp;
+ int depth;
+
+ depth = 0;
+ for (tmp = table; tmp->parent; tmp = tmp->parent)
+ depth++;
+
+ return depth;
+}
+
+static struct ctl_table *sysctl_parent(struct ctl_table *table, int n)
+{
+ int i;
+
+ for (i = 0; table && i < n; i++)
+ table = table->parent;
+
+ return table;
+}
+
+static struct trans_ctl_table *sysctl_binary_lookup(struct ctl_table *table)
+{
+ struct ctl_table *test;
+ struct trans_ctl_table *ref;
+ int depth, cur_depth;
+
+ depth = sysctl_depth(table);
+
+ cur_depth = depth;
+ ref = trans_root_table;
+repeat:
+ test = sysctl_parent(table, cur_depth);
+ for (; ref->ctl_name || ref->procname || ref->child; ref++) {
+ int match = 0;
+
+ if (cur_depth && !ref->child)
+ continue;
+
+ if (test->procname && ref->procname &&
+ (strcmp(test->procname, ref->procname) == 0))
+ match++;
+
+ if (test->ctl_name && ref->ctl_name &&
+ (test->ctl_name == ref->ctl_name))
+ match++;
+
+ if (!ref->ctl_name && !ref->procname)
+ match++;
+
+ if (match) {
+ if (cur_depth != 0) {
+ cur_depth--;
+ ref = ref->child;
+ goto repeat;
+ }
+ goto out;
+ }
+ }
+ ref = NULL;
+out:
+ return ref;
+}
+
+static void sysctl_print_path(struct ctl_table *table)
+{
+ struct ctl_table *tmp;
+ int depth, i;
+ depth = sysctl_depth(table);
+ if (table->procname) {
+ for (i = depth; i >= 0; i--) {
+ tmp = sysctl_parent(table, i);
+ printk("/%s", tmp->procname?tmp->procname:"");
+ }
+ }
+ printk(" ");
+ if (table->ctl_name) {
+ for (i = depth; i >= 0; i--) {
+ tmp = sysctl_parent(table, i);
+ printk(".%d", tmp->ctl_name);
+ }
+ }
+}
+
+static void sysctl_repair_table(struct ctl_table *table)
+{
+ /* Don't complain about the classic default
+ * sysctl strategy routine. Maybe later we
+ * can get the tables fixed and complain about
+ * this.
+ */
+ if (table->ctl_name && table->procname &&
+ (table->proc_handler == proc_dointvec) &&
+ (!table->strategy)) {
+ table->strategy = sysctl_data;
+ }
+}
+
+static struct ctl_table *sysctl_check_lookup(struct ctl_table *table)
+{
+ struct ctl_table_header *head;
+ struct ctl_table *ref, *test;
+ int depth, cur_depth;
+
+ depth = sysctl_depth(table);
+
+ for (head = sysctl_head_next(NULL); head;
+ head = sysctl_head_next(head)) {
+ cur_depth = depth;
+ ref = head->ctl_table;
+repeat:
+ test = sysctl_parent(table, cur_depth);
+ for (; ref->ctl_name || ref->procname; ref++) {
+ int match = 0;
+ if (cur_depth && !ref->child)
+ continue;
+
+ if (test->procname && ref->procname &&
+ (strcmp(test->procname, ref->procname) == 0))
+ match++;
+
+ if (test->ctl_name && ref->ctl_name &&
+ (test->ctl_name == ref->ctl_name))
+ match++;
+
+ if (match) {
+ if (cur_depth != 0) {
+ cur_depth--;
+ ref = ref->child;
+ goto repeat;
+ }
+ goto out;
+ }
+ }
+ }
+ ref = NULL;
+out:
+ sysctl_head_finish(head);
+ return ref;
+}
+
+static void set_fail(const char **fail, struct ctl_table *table, const char *str)
+{
+ if (*fail) {
+ printk(KERN_ERR "sysctl table check failed: ");
+ sysctl_print_path(table);
+ printk(" %s\n", *fail);
+ dump_stack();
+ }
+ *fail = str;
+}
+
+static int sysctl_check_dir(struct ctl_table *table)
+{
+ struct ctl_table *ref;
+ int error;
+
+ error = 0;
+ ref = sysctl_check_lookup(table);
+ if (ref) {
+ int match = 0;
+ if ((!table->procname && !ref->procname) ||
+ (table->procname && ref->procname &&
+ (strcmp(table->procname, ref->procname) == 0)))
+ match++;
+
+ if ((!table->ctl_name && !ref->ctl_name) ||
+ (table->ctl_name && ref->ctl_name &&
+ (table->ctl_name == ref->ctl_name)))
+ match++;
+
+ if (match != 2) {
+ printk(KERN_ERR "%s: failed: ", __func__);
+ sysctl_print_path(table);
+ printk(" ref: ");
+ sysctl_print_path(ref);
+ printk("\n");
+ error = -EINVAL;
+ }
+ }
+ return error;
+}
+
+static void sysctl_check_leaf(struct ctl_table *table, const char **fail)
+{
+ struct ctl_table *ref;
+
+ ref = sysctl_check_lookup(table);
+ if (ref && (ref != table))
+ set_fail(fail, table, "Sysctl already exists");
+}
+
+static void sysctl_check_bin_path(struct ctl_table *table, const char **fail)
+{
+ struct trans_ctl_table *ref;
+
+ ref = sysctl_binary_lookup(table);
+ if (table->ctl_name && !ref)
+ set_fail(fail, table, "Unknown sysctl binary path");
+ if (ref) {
+ if (ref->procname &&
+ (!table->procname ||
+ (strcmp(table->procname, ref->procname) != 0)))
+ set_fail(fail, table, "procname does not match binary path procname");
+
+ if (ref->ctl_name && table->ctl_name &&
+ (table->ctl_name != ref->ctl_name))
+ set_fail(fail, table, "ctl_name does not match binary path ctl_name");
+ }
+}
+
+int sysctl_check_table(struct ctl_table *table)
+{
+ int error = 0;
+ for (; table->ctl_name || table->procname; table++) {
+ const char *fail = NULL;
+
+ sysctl_repair_table(table);
+ if (table->parent) {
+ if (table->procname && !table->parent->procname)
+ set_fail(&fail, table, "Parent without procname");
+ if (table->ctl_name && !table->parent->ctl_name)
+ set_fail(&fail, table, "Parent without ctl_name");
+ }
+ if (!table->procname)
+ set_fail(&fail, table, "No procname");
+ if (table->child) {
+ if (table->data)
+ set_fail(&fail, table, "Directory with data?");
+ if (table->maxlen)
+ set_fail(&fail, table, "Directory with maxlen?");
+ if ((table->mode & (S_IRUGO|S_IXUGO)) != table->mode)
+ set_fail(&fail, table, "Writable sysctl directory");
+ if (table->proc_handler)
+ set_fail(&fail, table, "Directory with proc_handler");
+ if (table->strategy)
+ set_fail(&fail, table, "Directory with strategy");
+ if (table->extra1)
+ set_fail(&fail, table, "Directory with extra1");
+ if (table->extra2)
+ set_fail(&fail, table, "Directory with extra2");
+ if (sysctl_check_dir(table))
+ set_fail(&fail, table, "Inconsistent directory names");
+ } else {
+ if ((table->strategy == sysctl_data) ||
+ (table->strategy == sysctl_string) ||
+ (table->strategy == sysctl_intvec) ||
+ (table->strategy == sysctl_jiffies) ||
+ (table->strategy == sysctl_ms_jiffies) ||
+ (table->proc_handler == proc_dostring) ||
+ (table->proc_handler == proc_dointvec) ||
+#ifdef CONFIG_SECURITY_CAPABILITIES
+ (table->proc_handler == proc_dointvec_bset) ||
+#endif /* def CONFIG_SECURITY_CAPABILITIES */
+ (table->proc_handler == proc_dointvec_minmax) ||
+ (table->proc_handler == proc_dointvec_jiffies) ||
+ (table->proc_handler == proc_dointvec_userhz_jiffies) ||
+ (table->proc_handler == proc_dointvec_ms_jiffies) ||
+ (table->proc_handler == proc_doulongvec_minmax) ||
+ (table->proc_handler == proc_doulongvec_ms_jiffies_minmax)) {
+ if (!table->data)
+ set_fail(&fail, table, "No data");
+ if (!table->maxlen)
+ set_fail(&fail, table, "No maxlen");
+ }
+ if ((table->proc_handler == proc_doulongvec_minmax) ||
+ (table->proc_handler == proc_doulongvec_ms_jiffies_minmax)) {
+ if (table->maxlen > sizeof (unsigned long)) {
+ if (!table->extra1)
+ set_fail(&fail, table, "No min");
+ if (!table->extra2)
+ set_fail(&fail, table, "No max");
+ }
+ }
+#ifdef CONFIG_SYSCTL_SYSCALL
+ if (table->ctl_name && !table->strategy)
+ set_fail(&fail, table, "Missing strategy");
+#endif
+#if 0
+ if (!table->ctl_name && table->strategy)
+ set_fail(&fail, table, "Strategy without ctl_name");
+#endif
+#ifdef CONFIG_PROC_FS
+ if (table->procname && !table->proc_handler)
+ set_fail(&fail, table, "No proc_handler");
+#endif
+#if 0
+ if (!table->procname && table->proc_handler)
+ set_fail(&fail, table, "proc_handler without procname");
+#endif
+ sysctl_check_leaf(table, &fail);
+ }
+ sysctl_check_bin_path(table, &fail);
+ if (fail) {
+ set_fail(&fail, table, NULL);
+ error = -EINVAL;
+ }
+ if (table->child)
+ error |= sysctl_check_table(table->child);
+ }
+ return error;
+}
diff --git a/kernel/taskstats.c b/kernel/taskstats.c
index 059431ed67db..07e86a828073 100644
--- a/kernel/taskstats.c
+++ b/kernel/taskstats.c
@@ -20,9 +20,12 @@
#include <linux/taskstats_kern.h>
#include <linux/tsacct_kern.h>
#include <linux/delayacct.h>
-#include <linux/tsacct_kern.h>
#include <linux/cpumask.h>
#include <linux/percpu.h>
+#include <linux/cgroupstats.h>
+#include <linux/cgroup.h>
+#include <linux/fs.h>
+#include <linux/file.h>
#include <net/genetlink.h>
#include <asm/atomic.h>
@@ -50,6 +53,11 @@ __read_mostly = {
[TASKSTATS_CMD_ATTR_REGISTER_CPUMASK] = { .type = NLA_STRING },
[TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK] = { .type = NLA_STRING },};
+static struct nla_policy
+cgroupstats_cmd_get_policy[CGROUPSTATS_CMD_ATTR_MAX+1] __read_mostly = {
+ [CGROUPSTATS_CMD_ATTR_FD] = { .type = NLA_U32 },
+};
+
struct listener {
struct list_head list;
pid_t pid;
@@ -255,7 +263,7 @@ out:
stats->version = TASKSTATS_VERSION;
/*
- * Accounting subsytems can also add calls here to modify
+ * Accounting subsystems can also add calls here to modify
* fields of taskstats.
*/
return rc;
@@ -373,6 +381,51 @@ err:
return NULL;
}
+static int cgroupstats_user_cmd(struct sk_buff *skb, struct genl_info *info)
+{
+ int rc = 0;
+ struct sk_buff *rep_skb;
+ struct cgroupstats *stats;
+ struct nlattr *na;
+ size_t size;
+ u32 fd;
+ struct file *file;
+ int fput_needed;
+
+ na = info->attrs[CGROUPSTATS_CMD_ATTR_FD];
+ if (!na)
+ return -EINVAL;
+
+ fd = nla_get_u32(info->attrs[CGROUPSTATS_CMD_ATTR_FD]);
+ file = fget_light(fd, &fput_needed);
+ if (!file)
+ return 0;
+
+ size = nla_total_size(sizeof(struct cgroupstats));
+
+ rc = prepare_reply(info, CGROUPSTATS_CMD_NEW, &rep_skb,
+ size);
+ if (rc < 0)
+ goto err;
+
+ na = nla_reserve(rep_skb, CGROUPSTATS_TYPE_CGROUP_STATS,
+ sizeof(struct cgroupstats));
+ stats = nla_data(na);
+ memset(stats, 0, sizeof(*stats));
+
+ rc = cgroupstats_build(stats, file->f_dentry);
+ if (rc < 0) {
+ nlmsg_free(rep_skb);
+ goto err;
+ }
+
+ rc = send_reply(rep_skb, info->snd_pid);
+
+err:
+ fput_light(file, fput_needed);
+ return rc;
+}
+
static int taskstats_user_cmd(struct sk_buff *skb, struct genl_info *info)
{
int rc = 0;
@@ -523,6 +576,12 @@ static struct genl_ops taskstats_ops = {
.policy = taskstats_cmd_get_policy,
};
+static struct genl_ops cgroupstats_ops = {
+ .cmd = CGROUPSTATS_CMD_GET,
+ .doit = cgroupstats_user_cmd,
+ .policy = cgroupstats_cmd_get_policy,
+};
+
/* Needed early in initialization */
void __init taskstats_init_early(void)
{
@@ -547,8 +606,15 @@ static int __init taskstats_init(void)
if (rc < 0)
goto err;
+ rc = genl_register_ops(&family, &cgroupstats_ops);
+ if (rc < 0)
+ goto err_cgroup_ops;
+
family_registered = 1;
+ printk("registered taskstats version %d\n", TASKSTATS_GENL_VERSION);
return 0;
+err_cgroup_ops:
+ genl_unregister_ops(&family, &taskstats_ops);
err:
genl_unregister_family(&family);
return rc;
diff --git a/kernel/time.c b/kernel/time.c
index 2289a8d68314..09d3c45c4da7 100644
--- a/kernel/time.c
+++ b/kernel/time.c
@@ -9,9 +9,9 @@
*/
/*
* Modification history kernel/time.c
- *
+ *
* 1993-09-02 Philip Gladstone
- * Created file with time related functions from sched.c and adjtimex()
+ * Created file with time related functions from sched.c and adjtimex()
* 1993-10-08 Torsten Duwe
* adjtime interface update and CMOS clock write code
* 1995-08-13 Torsten Duwe
@@ -30,16 +30,16 @@
#include <linux/module.h>
#include <linux/timex.h>
#include <linux/capability.h>
+#include <linux/clocksource.h>
#include <linux/errno.h>
#include <linux/syscalls.h>
#include <linux/security.h>
#include <linux/fs.h>
-#include <linux/module.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
-/*
+/*
* The timezone where the local system is located. Used as a default by some
* programs who obtain this value by using gettimeofday.
*/
@@ -57,11 +57,7 @@ EXPORT_SYMBOL(sys_tz);
*/
asmlinkage long sys_time(time_t __user * tloc)
{
- time_t i;
- struct timespec tv;
-
- getnstimeofday(&tv);
- i = tv.tv_sec;
+ time_t i = get_seconds();
if (tloc) {
if (put_user(i,tloc))
@@ -76,7 +72,7 @@ asmlinkage long sys_time(time_t __user * tloc)
* why not move it into the appropriate arch directory (for those
* architectures that need it).
*/
-
+
asmlinkage long sys_stime(time_t __user *tptr)
{
struct timespec tv;
@@ -115,10 +111,10 @@ asmlinkage long sys_gettimeofday(struct timeval __user *tv, struct timezone __us
/*
* Adjust the time obtained from the CMOS to be UTC time instead of
* local time.
- *
+ *
* This is ugly, but preferable to the alternatives. Otherwise we
* would either need to write a program to do it in /etc/rc (and risk
- * confusion if the program gets run more than once; it would also be
+ * confusion if the program gets run more than once; it would also be
* hard to make the program warp the clock precisely n hours) or
* compile in the timezone information into the kernel. Bad, bad....
*
@@ -163,6 +159,7 @@ int do_sys_settimeofday(struct timespec *tv, struct timezone *tz)
if (tz) {
/* SMP safe, global irq locking makes it work. */
sys_tz = *tz;
+ update_vsyscall_tz();
if (firsttime) {
firsttime = 0;
if (!tv)
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index 51b6a6a6158c..c8a9d13874df 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -207,15 +207,12 @@ static inline void clocksource_resume_watchdog(void) { }
*/
void clocksource_resume(void)
{
- struct list_head *tmp;
+ struct clocksource *cs;
unsigned long flags;
spin_lock_irqsave(&clocksource_lock, flags);
- list_for_each(tmp, &clocksource_list) {
- struct clocksource *cs;
-
- cs = list_entry(tmp, struct clocksource, list);
+ list_for_each_entry(cs, &clocksource_list, list) {
if (cs->resume)
cs->resume();
}
@@ -369,7 +366,6 @@ static ssize_t sysfs_override_clocksource(struct sys_device *dev,
const char *buf, size_t count)
{
struct clocksource *ovr = NULL;
- struct list_head *tmp;
size_t ret = count;
int len;
@@ -389,12 +385,11 @@ static ssize_t sysfs_override_clocksource(struct sys_device *dev,
len = strlen(override_name);
if (len) {
+ struct clocksource *cs;
+
ovr = clocksource_override;
/* try to select it: */
- list_for_each(tmp, &clocksource_list) {
- struct clocksource *cs;
-
- cs = list_entry(tmp, struct clocksource, list);
+ list_for_each_entry(cs, &clocksource_list, list) {
if (strlen(cs->name) == len &&
!strcmp(cs->name, override_name))
ovr = cs;
@@ -422,14 +417,11 @@ static ssize_t sysfs_override_clocksource(struct sys_device *dev,
static ssize_t
sysfs_show_available_clocksources(struct sys_device *dev, char *buf)
{
- struct list_head *tmp;
+ struct clocksource *src;
char *curr = buf;
spin_lock_irq(&clocksource_lock);
- list_for_each(tmp, &clocksource_list) {
- struct clocksource *src;
-
- src = list_entry(tmp, struct clocksource, list);
+ list_for_each_entry(src, &clocksource_list, list) {
curr += sprintf(curr, "%s ", src->name);
}
spin_unlock_irq(&clocksource_lock);
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
index fc3fc79b3d59..aa82d7bf478a 100644
--- a/kernel/time/tick-broadcast.c
+++ b/kernel/time/tick-broadcast.c
@@ -222,20 +222,8 @@ static void tick_do_broadcast_on_off(void *why)
if (!dev || !(dev->features & CLOCK_EVT_FEAT_C3STOP))
goto out;
- /*
- * Defect device ?
- */
- if (!tick_device_is_functional(dev)) {
- /*
- * AMD C1E wreckage fixup:
- *
- * Device was registered functional in the first
- * place. Now the secondary CPU detected the C1E
- * misfeature and notifies us to fix it up
- */
- if (*reason != CLOCK_EVT_NOTIFY_BROADCAST_FORCE)
- goto out;
- }
+ if (!tick_device_is_functional(dev))
+ goto out;
switch (*reason) {
case CLOCK_EVT_NOTIFY_BROADCAST_ON:
@@ -246,6 +234,8 @@ static void tick_do_broadcast_on_off(void *why)
clockevents_set_mode(dev,
CLOCK_EVT_MODE_SHUTDOWN);
}
+ if (*reason == CLOCK_EVT_NOTIFY_BROADCAST_FORCE)
+ dev->features |= CLOCK_EVT_FEAT_DUMMY;
break;
case CLOCK_EVT_NOTIFY_BROADCAST_OFF:
if (cpu_isset(cpu, tick_broadcast_mask)) {
@@ -274,21 +264,12 @@ out:
*/
void tick_broadcast_on_off(unsigned long reason, int *oncpu)
{
- int cpu = get_cpu();
-
- if (!cpu_isset(*oncpu, cpu_online_map)) {
+ if (!cpu_isset(*oncpu, cpu_online_map))
printk(KERN_ERR "tick-braodcast: ignoring broadcast for "
"offline CPU #%d\n", *oncpu);
- } else {
-
- if (cpu == *oncpu)
- tick_do_broadcast_on_off(&reason);
- else
- smp_call_function_single(*oncpu,
- tick_do_broadcast_on_off,
- &reason, 1, 1);
- }
- put_cpu();
+ else
+ smp_call_function_single(*oncpu, tick_do_broadcast_on_off,
+ &reason, 1, 1);
}
/*
@@ -527,7 +508,7 @@ static void tick_broadcast_clear_oneshot(int cpu)
}
/**
- * tick_broadcast_setup_highres - setup the broadcast device for highres
+ * tick_broadcast_setup_oneshot - setup the broadcast device
*/
void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
{
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 8c3fef1db09c..27a2338deb4a 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -153,6 +153,7 @@ void tick_nohz_stop_sched_tick(void)
unsigned long seq, last_jiffies, next_jiffies, delta_jiffies, flags;
struct tick_sched *ts;
ktime_t last_update, expires, now, delta;
+ struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
int cpu;
local_irq_save(flags);
@@ -302,12 +303,25 @@ void tick_nohz_stop_sched_tick(void)
out:
ts->next_jiffies = next_jiffies;
ts->last_jiffies = last_jiffies;
+ ts->sleep_length = ktime_sub(dev->next_event, now);
end:
local_irq_restore(flags);
}
/**
- * nohz_restart_sched_tick - restart the idle tick from the idle task
+ * tick_nohz_get_sleep_length - return the length of the current sleep
+ *
+ * Called from power state control code with interrupts disabled
+ */
+ktime_t tick_nohz_get_sleep_length(void)
+{
+ struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
+
+ return ts->sleep_length;
+}
+
+/**
+ * tick_nohz_restart_sched_tick - restart the idle tick from the idle task
*
* Restart the idle tick when the CPU is woken up from idle
*/
@@ -570,7 +584,7 @@ void tick_setup_sched_timer(void)
/* Get the next period (per cpu) */
ts->sched_timer.expires = tick_init_jiffy_update();
offset = ktime_to_ns(tick_period) >> 1;
- do_div(offset, NR_CPUS);
+ do_div(offset, num_possible_cpus());
offset *= smp_processor_id();
ts->sched_timer.expires = ktime_add_ns(ts->sched_timer.expires, offset);
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 4ad79f6bdec6..e5e466b27598 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -24,9 +24,7 @@
* This read-write spinlock protects us from races in SMP while
* playing with xtime and avenrun.
*/
-__attribute__((weak)) __cacheline_aligned_in_smp DEFINE_SEQLOCK(xtime_lock);
-
-EXPORT_SYMBOL(xtime_lock);
+__cacheline_aligned_in_smp DEFINE_SEQLOCK(xtime_lock);
/*
@@ -47,21 +45,13 @@ EXPORT_SYMBOL(xtime_lock);
struct timespec xtime __attribute__ ((aligned (16)));
struct timespec wall_to_monotonic __attribute__ ((aligned (16)));
static unsigned long total_sleep_time; /* seconds */
-EXPORT_SYMBOL(xtime);
-
-#ifdef CONFIG_NO_HZ
static struct timespec xtime_cache __attribute__ ((aligned (16)));
static inline void update_xtime_cache(u64 nsec)
{
xtime_cache = xtime;
timespec_add_ns(&xtime_cache, nsec);
}
-#else
-#define xtime_cache xtime
-/* We do *not* want to evaluate the argument for this case */
-#define update_xtime_cache(n) do { } while (0)
-#endif
static struct clocksource *clock; /* pointer to current clocksource */
diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c
index fdb2e03d4fe0..12c5f4cb6b8c 100644
--- a/kernel/time/timer_list.c
+++ b/kernel/time/timer_list.c
@@ -129,7 +129,8 @@ static void print_cpu(struct seq_file *m, int cpu, u64 now)
struct hrtimer_cpu_base *cpu_base = &per_cpu(hrtimer_bases, cpu);
int i;
- SEQ_printf(m, "\ncpu: %d\n", cpu);
+ SEQ_printf(m, "\n");
+ SEQ_printf(m, "cpu: %d\n", cpu);
for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
SEQ_printf(m, " clock %d:\n", i);
print_base(m, cpu_base->clock_base + i, now);
@@ -184,7 +185,8 @@ print_tickdevice(struct seq_file *m, struct tick_device *td)
{
struct clock_event_device *dev = td->evtdev;
- SEQ_printf(m, "\nTick Device: mode: %d\n", td->mode);
+ SEQ_printf(m, "\n");
+ SEQ_printf(m, "Tick Device: mode: %d\n", td->mode);
SEQ_printf(m, "Clock Event Device: ");
if (!dev) {
diff --git a/kernel/timer.c b/kernel/timer.c
index 6ce1952eea7d..a05817c021d6 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -26,6 +26,7 @@
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/swap.h>
+#include <linux/pid_namespace.h>
#include <linux/notifier.h>
#include <linux/thread_info.h>
#include <linux/time.h>
@@ -789,7 +790,7 @@ static unsigned long cmp_next_hrtimer_event(unsigned long now,
}
/**
- * next_timer_interrupt - return the jiffy of the next pending timer
+ * get_next_timer_interrupt - return the jiffy of the next pending timer
* @now: current time (in jiffies)
*/
unsigned long get_next_timer_interrupt(unsigned long now)
@@ -816,8 +817,21 @@ unsigned long next_timer_interrupt(void)
#endif
+#ifndef CONFIG_VIRT_CPU_ACCOUNTING
+void account_process_tick(struct task_struct *p, int user_tick)
+{
+ if (user_tick) {
+ account_user_time(p, jiffies_to_cputime(1));
+ account_user_time_scaled(p, jiffies_to_cputime(1));
+ } else {
+ account_system_time(p, HARDIRQ_OFFSET, jiffies_to_cputime(1));
+ account_system_time_scaled(p, jiffies_to_cputime(1));
+ }
+}
+#endif
+
/*
- * Called from the timer interrupt handler to charge one tick to the current
+ * Called from the timer interrupt handler to charge one tick to the current
* process. user_tick is 1 if the tick is user time, 0 for system.
*/
void update_process_times(int user_tick)
@@ -826,10 +840,7 @@ void update_process_times(int user_tick)
int cpu = smp_processor_id();
/* Note: this timer irq context must be accounted for as well. */
- if (user_tick)
- account_user_time(p, jiffies_to_cputime(1));
- else
- account_system_time(p, HARDIRQ_OFFSET, jiffies_to_cputime(1));
+ account_process_tick(p, user_tick);
run_local_timers();
if (rcu_pending(cpu))
rcu_check_callbacks(cpu, user_tick);
@@ -953,7 +964,7 @@ asmlinkage unsigned long sys_alarm(unsigned int seconds)
*/
asmlinkage long sys_getpid(void)
{
- return current->tgid;
+ return task_tgid_vnr(current);
}
/*
@@ -967,7 +978,7 @@ asmlinkage long sys_getppid(void)
int pid;
rcu_read_lock();
- pid = rcu_dereference(current->real_parent)->tgid;
+ pid = task_ppid_nr_ns(current, current->nsproxy->pid_ns);
rcu_read_unlock();
return pid;
@@ -1099,7 +1110,7 @@ EXPORT_SYMBOL(schedule_timeout_uninterruptible);
/* Thread ID - the internal kernel "pid" */
asmlinkage long sys_gettid(void)
{
- return current->pid;
+ return task_pid_vnr(current);
}
/**
diff --git a/kernel/tsacct.c b/kernel/tsacct.c
index c122131a122f..4ab1b584961b 100644
--- a/kernel/tsacct.c
+++ b/kernel/tsacct.c
@@ -62,6 +62,10 @@ void bacct_add_tsk(struct taskstats *stats, struct task_struct *tsk)
rcu_read_unlock();
stats->ac_utime = cputime_to_msecs(tsk->utime) * USEC_PER_MSEC;
stats->ac_stime = cputime_to_msecs(tsk->stime) * USEC_PER_MSEC;
+ stats->ac_utimescaled =
+ cputime_to_msecs(tsk->utimescaled) * USEC_PER_MSEC;
+ stats->ac_stimescaled =
+ cputime_to_msecs(tsk->stimescaled) * USEC_PER_MSEC;
stats->ac_minflt = tsk->min_flt;
stats->ac_majflt = tsk->maj_flt;
diff --git a/kernel/user.c b/kernel/user.c
index f0e561e6d085..0f3aa0234107 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -44,7 +44,6 @@ struct user_struct root_user = {
.processes = ATOMIC_INIT(1),
.files = ATOMIC_INIT(0),
.sigpending = ATOMIC_INIT(0),
- .mq_bytes = 0,
.locked_shm = 0,
#ifdef CONFIG_KEYS
.uid_keyring = &root_user_keyring,
@@ -58,19 +57,17 @@ struct user_struct root_user = {
/*
* These routines must be called with the uidhash spinlock held!
*/
-static inline void uid_hash_insert(struct user_struct *up,
- struct hlist_head *hashent)
+static void uid_hash_insert(struct user_struct *up, struct hlist_head *hashent)
{
hlist_add_head(&up->uidhash_node, hashent);
}
-static inline void uid_hash_remove(struct user_struct *up)
+static void uid_hash_remove(struct user_struct *up)
{
hlist_del_init(&up->uidhash_node);
}
-static inline struct user_struct *uid_hash_find(uid_t uid,
- struct hlist_head *hashent)
+static struct user_struct *uid_hash_find(uid_t uid, struct hlist_head *hashent)
{
struct user_struct *user;
struct hlist_node *h;
@@ -87,9 +84,6 @@ static inline struct user_struct *uid_hash_find(uid_t uid,
#ifdef CONFIG_FAIR_USER_SCHED
-static struct kobject uids_kobject; /* represents /sys/kernel/uids directory */
-static DEFINE_MUTEX(uids_mutex);
-
static void sched_destroy_user(struct user_struct *up)
{
sched_destroy_group(up->tg);
@@ -111,6 +105,19 @@ static void sched_switch_user(struct task_struct *p)
sched_move_task(p);
}
+#else /* CONFIG_FAIR_USER_SCHED */
+
+static void sched_destroy_user(struct user_struct *up) { }
+static int sched_create_user(struct user_struct *up) { return 0; }
+static void sched_switch_user(struct task_struct *p) { }
+
+#endif /* CONFIG_FAIR_USER_SCHED */
+
+#if defined(CONFIG_FAIR_USER_SCHED) && defined(CONFIG_SYSFS)
+
+static struct kobject uids_kobject; /* represents /sys/kernel/uids directory */
+static DEFINE_MUTEX(uids_mutex);
+
static inline void uids_mutex_lock(void)
{
mutex_lock(&uids_mutex);
@@ -122,7 +129,7 @@ static inline void uids_mutex_unlock(void)
}
/* return cpu shares held by the user */
-ssize_t cpu_shares_show(struct kset *kset, char *buffer)
+static ssize_t cpu_shares_show(struct kset *kset, char *buffer)
{
struct user_struct *up = container_of(kset, struct user_struct, kset);
@@ -130,7 +137,8 @@ ssize_t cpu_shares_show(struct kset *kset, char *buffer)
}
/* modify cpu shares held by the user */
-ssize_t cpu_shares_store(struct kset *kset, const char *buffer, size_t size)
+static ssize_t cpu_shares_store(struct kset *kset, const char *buffer,
+ size_t size)
{
struct user_struct *up = container_of(kset, struct user_struct, kset);
unsigned long shares;
@@ -257,11 +265,8 @@ static inline void free_user(struct user_struct *up, unsigned long flags)
schedule_work(&up->work);
}
-#else /* CONFIG_FAIR_USER_SCHED */
+#else /* CONFIG_FAIR_USER_SCHED && CONFIG_SYSFS */
-static void sched_destroy_user(struct user_struct *up) { }
-static int sched_create_user(struct user_struct *up) { return 0; }
-static void sched_switch_user(struct task_struct *p) { }
static inline int user_kobject_create(struct user_struct *up) { return 0; }
static inline void uids_mutex_lock(void) { }
static inline void uids_mutex_unlock(void) { }
@@ -280,7 +285,7 @@ static inline void free_user(struct user_struct *up, unsigned long flags)
kmem_cache_free(uid_cachep, up);
}
-#endif /* CONFIG_FAIR_USER_SCHED */
+#endif
/*
* Locate the user_struct for the passed UID. If found, take a ref on it. The
@@ -343,8 +348,9 @@ struct user_struct * alloc_uid(struct user_namespace *ns, uid_t uid)
atomic_set(&new->inotify_watches, 0);
atomic_set(&new->inotify_devs, 0);
#endif
-
+#ifdef CONFIG_POSIX_MQUEUE
new->mq_bytes = 0;
+#endif
new->locked_shm = 0;
if (alloc_uid_keyring(new, current) < 0) {
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index e080d1d744cc..52d5e7c9a8e6 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -32,6 +32,7 @@
#include <linux/freezer.h>
#include <linux/kallsyms.h>
#include <linux/debug_locks.h>
+#include <linux/lockdep.h>
/*
* The per-CPU workqueue (if single thread, we always use the first
@@ -61,6 +62,9 @@ struct workqueue_struct {
const char *name;
int singlethread;
int freezeable; /* Freeze threads during suspend */
+#ifdef CONFIG_LOCKDEP
+ struct lockdep_map lockdep_map;
+#endif
};
/* All the per-cpu workqueues on the system, for hotplug cpu to add/remove
@@ -250,6 +254,17 @@ static void run_workqueue(struct cpu_workqueue_struct *cwq)
struct work_struct *work = list_entry(cwq->worklist.next,
struct work_struct, entry);
work_func_t f = work->func;
+#ifdef CONFIG_LOCKDEP
+ /*
+ * It is permissible to free the struct work_struct
+ * from inside the function that is called from it,
+ * this we need to take into account for lockdep too.
+ * To avoid bogus "held lock freed" warnings as well
+ * as problems when looking into work->lockdep_map,
+ * make a copy and use that here.
+ */
+ struct lockdep_map lockdep_map = work->lockdep_map;
+#endif
cwq->current_work = work;
list_del_init(cwq->worklist.next);
@@ -257,13 +272,17 @@ static void run_workqueue(struct cpu_workqueue_struct *cwq)
BUG_ON(get_wq_data(work) != cwq);
work_clear_pending(work);
+ lock_acquire(&cwq->wq->lockdep_map, 0, 0, 0, 2, _THIS_IP_);
+ lock_acquire(&lockdep_map, 0, 0, 0, 2, _THIS_IP_);
f(work);
+ lock_release(&lockdep_map, 1, _THIS_IP_);
+ lock_release(&cwq->wq->lockdep_map, 1, _THIS_IP_);
if (unlikely(in_atomic() || lockdep_depth(current) > 0)) {
printk(KERN_ERR "BUG: workqueue leaked lock or atomic: "
"%s/0x%08x/%d\n",
current->comm, preempt_count(),
- current->pid);
+ task_pid_nr(current));
printk(KERN_ERR " last function: ");
print_symbol("%s\n", (unsigned long)f);
debug_show_held_locks(current);
@@ -376,6 +395,8 @@ void fastcall flush_workqueue(struct workqueue_struct *wq)
int cpu;
might_sleep();
+ lock_acquire(&wq->lockdep_map, 0, 0, 0, 2, _THIS_IP_);
+ lock_release(&wq->lockdep_map, 1, _THIS_IP_);
for_each_cpu_mask(cpu, *cpu_map)
flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, cpu));
}
@@ -446,6 +467,9 @@ static void wait_on_work(struct work_struct *work)
might_sleep();
+ lock_acquire(&work->lockdep_map, 0, 0, 0, 2, _THIS_IP_);
+ lock_release(&work->lockdep_map, 1, _THIS_IP_);
+
cwq = get_wq_data(work);
if (!cwq)
return;
@@ -695,8 +719,10 @@ static void start_workqueue_thread(struct cpu_workqueue_struct *cwq, int cpu)
}
}
-struct workqueue_struct *__create_workqueue(const char *name,
- int singlethread, int freezeable)
+struct workqueue_struct *__create_workqueue_key(const char *name,
+ int singlethread,
+ int freezeable,
+ struct lock_class_key *key)
{
struct workqueue_struct *wq;
struct cpu_workqueue_struct *cwq;
@@ -713,6 +739,7 @@ struct workqueue_struct *__create_workqueue(const char *name,
}
wq->name = name;
+ lockdep_init_map(&wq->lockdep_map, name, key, 0);
wq->singlethread = singlethread;
wq->freezeable = freezeable;
INIT_LIST_HEAD(&wq->list);
@@ -741,7 +768,7 @@ struct workqueue_struct *__create_workqueue(const char *name,
}
return wq;
}
-EXPORT_SYMBOL_GPL(__create_workqueue);
+EXPORT_SYMBOL_GPL(__create_workqueue_key);
static void cleanup_workqueue_thread(struct cpu_workqueue_struct *cwq, int cpu)
{
@@ -752,6 +779,9 @@ static void cleanup_workqueue_thread(struct cpu_workqueue_struct *cwq, int cpu)
if (cwq->thread == NULL)
return;
+ lock_acquire(&cwq->wq->lockdep_map, 0, 0, 0, 2, _THIS_IP_);
+ lock_release(&cwq->wq->lockdep_map, 1, _THIS_IP_);
+
flush_cpu_workqueue(cwq);
/*
* If the caller is CPU_DEAD and cwq->worklist was not empty,
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 396c38b3cb69..1e5f207b9074 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -9,6 +9,14 @@ config PRINTK_TIME
operations. This is useful for identifying long delays
in kernel startup.
+config ENABLE_WARN_DEPRECATED
+ bool "Enable __deprecated logic"
+ default y
+ help
+ Enable the __deprecated logic in the kernel build.
+ Disable this to suppress the "warning: 'foo' is deprecated
+ (declared at kernel/power/somefile.c:1234)" messages.
+
config ENABLE_MUST_CHECK
bool "Enable __must_check logic"
default y
@@ -389,6 +397,16 @@ config DEBUG_LIST
If unsure, say N.
+config DEBUG_SG
+ bool "Debug SG table operations"
+ depends on DEBUG_KERNEL
+ help
+ Enable this to turn on checks on scatter-gather tables. This can
+ help find problems with drivers that do not properly initialize
+ their sg tables.
+
+ If unsure, say N.
+
config FRAME_POINTER
bool "Compile the kernel with frame pointers"
depends on DEBUG_KERNEL && (X86 || CRIS || M68K || M68KNOMMU || FRV || UML || S390 || AVR32 || SUPERH || BFIN)
@@ -413,6 +431,24 @@ config FORCED_INLINING
become the default in the future, until then this option is there to
test gcc for this.
+config BOOT_PRINTK_DELAY
+ bool "Delay each boot printk message by N milliseconds"
+ depends on DEBUG_KERNEL && PRINTK && GENERIC_CALIBRATE_DELAY
+ help
+ This build option allows you to read kernel boot messages
+ by inserting a short delay after each one. The delay is
+ specified in milliseconds on the kernel command line,
+ using "boot_delay=N".
+
+ It is likely that you would also need to use "lpj=M" to preset
+ the "loops per jiffie" value.
+ See a previous boot log for the "lpj" value to use for your
+ system, and then set "lpj=M" before setting "boot_delay=N".
+ NOTE: Using this option may adversely affect SMP systems.
+ I.e., processors other than the first one may not boot up.
+ BOOT_PRINTK_DELAY also may cause DETECT_SOFTLOCKUP to detect
+ what it believes to be lockup conditions.
+
config RCU_TORTURE_TEST
tristate "torture tests for RCU"
depends on DEBUG_KERNEL
@@ -480,3 +516,5 @@ config FAULT_INJECTION_STACKTRACE_FILTER
select FRAME_POINTER
help
Provide stacktrace filter for fault-injection capabilities
+
+source "samples/Kconfig"
diff --git a/lib/Makefile b/lib/Makefile
index 6c4ea33bb2cb..b6793ed28d84 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -4,8 +4,9 @@
lib-y := ctype.o string.o vsprintf.o cmdline.o \
rbtree.o radix-tree.o dump_stack.o \
- idr.o int_sqrt.o bitmap.o extable.o prio_tree.o \
- sha1.o irq_regs.o reciprocal_div.o argv_split.o
+ idr.o int_sqrt.o extable.o prio_tree.o \
+ sha1.o irq_regs.o reciprocal_div.o argv_split.o \
+ proportions.o prio_heap.o
lib-$(CONFIG_MMU) += ioremap.o
lib-$(CONFIG_SMP) += cpumask.o
@@ -13,7 +14,7 @@ lib-$(CONFIG_SMP) += cpumask.o
lib-y += kobject.o kref.o klist.o
obj-y += div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
- bust_spinlocks.o hexdump.o kasprintf.o
+ bust_spinlocks.o hexdump.o kasprintf.o bitmap.o
ifeq ($(CONFIG_DEBUG_KOBJECT),y)
CFLAGS_kobject.o += -DDEBUG
diff --git a/lib/argv_split.c b/lib/argv_split.c
index 4096ed42f490..5205a8dae5bc 100644
--- a/lib/argv_split.c
+++ b/lib/argv_split.c
@@ -4,7 +4,8 @@
#include <linux/kernel.h>
#include <linux/ctype.h>
-#include <linux/bug.h>
+#include <linux/slab.h>
+#include <linux/module.h>
static const char *skip_sep(const char *cp)
{
@@ -75,7 +76,9 @@ char **argv_split(gfp_t gfp, const char *str, int *argcp)
if (argv == NULL)
goto out;
- *argcp = argc;
+ if (argcp)
+ *argcp = argc;
+
argvp = argv;
while (*str) {
diff --git a/lib/bitmap.c b/lib/bitmap.c
index 26ebafa8c41d..2c9242e3fed0 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -469,6 +469,10 @@ int bitmap_scnlistprintf(char *buf, unsigned int buflen,
/* current bit is 'cur', most recently seen range is [rbot, rtop] */
int cur, rbot, rtop;
+ if (buflen == 0)
+ return 0;
+ buf[0] = 0;
+
rbot = cur = find_first_bit(maskp, nmaskbits);
while (cur < nmaskbits) {
rtop = cur;
diff --git a/lib/bust_spinlocks.c b/lib/bust_spinlocks.c
index accb35658169..486da62b2b07 100644
--- a/lib/bust_spinlocks.c
+++ b/lib/bust_spinlocks.c
@@ -17,13 +17,13 @@
void __attribute__((weak)) bust_spinlocks(int yes)
{
if (yes) {
- oops_in_progress = 1;
+ ++oops_in_progress;
} else {
#ifdef CONFIG_VT
unblank_screen();
#endif
- oops_in_progress = 0;
- wake_up_klogd();
+ if (--oops_in_progress == 0)
+ wake_up_klogd();
}
}
diff --git a/lib/crc32.c b/lib/crc32.c
index bfc33314c720..d2c2f257bedd 100644
--- a/lib/crc32.c
+++ b/lib/crc32.c
@@ -49,7 +49,7 @@ MODULE_LICENSE("GPL");
* @p: pointer to buffer over which CRC is run
* @len: length of buffer @p
*/
-u32 __attribute_pure__ crc32_le(u32 crc, unsigned char const *p, size_t len);
+u32 __pure crc32_le(u32 crc, unsigned char const *p, size_t len);
#if CRC_LE_BITS == 1
/*
@@ -57,7 +57,7 @@ u32 __attribute_pure__ crc32_le(u32 crc, unsigned char const *p, size_t len);
* simplified by inlining the table in ?: form.
*/
-u32 __attribute_pure__ crc32_le(u32 crc, unsigned char const *p, size_t len)
+u32 __pure crc32_le(u32 crc, unsigned char const *p, size_t len)
{
int i;
while (len--) {
@@ -69,7 +69,7 @@ u32 __attribute_pure__ crc32_le(u32 crc, unsigned char const *p, size_t len)
}
#else /* Table-based approach */
-u32 __attribute_pure__ crc32_le(u32 crc, unsigned char const *p, size_t len)
+u32 __pure crc32_le(u32 crc, unsigned char const *p, size_t len)
{
# if CRC_LE_BITS == 8
const u32 *b =(u32 *)p;
@@ -145,7 +145,7 @@ u32 __attribute_pure__ crc32_le(u32 crc, unsigned char const *p, size_t len)
* @p: pointer to buffer over which CRC is run
* @len: length of buffer @p
*/
-u32 __attribute_pure__ crc32_be(u32 crc, unsigned char const *p, size_t len);
+u32 __pure crc32_be(u32 crc, unsigned char const *p, size_t len);
#if CRC_BE_BITS == 1
/*
@@ -153,7 +153,7 @@ u32 __attribute_pure__ crc32_be(u32 crc, unsigned char const *p, size_t len);
* simplified by inlining the table in ?: form.
*/
-u32 __attribute_pure__ crc32_be(u32 crc, unsigned char const *p, size_t len)
+u32 __pure crc32_be(u32 crc, unsigned char const *p, size_t len)
{
int i;
while (len--) {
@@ -167,7 +167,7 @@ u32 __attribute_pure__ crc32_be(u32 crc, unsigned char const *p, size_t len)
}
#else /* Table-based approach */
-u32 __attribute_pure__ crc32_be(u32 crc, unsigned char const *p, size_t len)
+u32 __pure crc32_be(u32 crc, unsigned char const *p, size_t len)
{
# if CRC_BE_BITS == 8
const u32 *b =(u32 *)p;
diff --git a/lib/hweight.c b/lib/hweight.c
index 360556a7803d..389424ecb129 100644
--- a/lib/hweight.c
+++ b/lib/hweight.c
@@ -1,6 +1,6 @@
#include <linux/module.h>
+#include <linux/bitops.h>
#include <asm/types.h>
-#include <asm/bitops.h>
/**
* hweightN - returns the hamming weight of a N-bit word
diff --git a/lib/idr.c b/lib/idr.c
index 09cbe2b69edb..afbb0b1023d4 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -580,8 +580,7 @@ void *idr_replace(struct idr *idp, void *ptr, int id)
}
EXPORT_SYMBOL(idr_replace);
-static void idr_cache_ctor(void * idr_layer, struct kmem_cache *idr_layer_cache,
- unsigned long flags)
+static void idr_cache_ctor(struct kmem_cache *idr_layer_cache, void *idr_layer)
{
memset(idr_layer, 0, sizeof(struct idr_layer));
}
diff --git a/lib/iomap.c b/lib/iomap.c
index 864f2ec1966e..72c42687ba10 100644
--- a/lib/iomap.c
+++ b/lib/iomap.c
@@ -40,7 +40,7 @@ static void bad_io_access(unsigned long port, const char *access)
static int count = 10;
if (count) {
count--;
- printk(KERN_ERR "Bad IO access at port %lx (%s)\n", port, access);
+ printk(KERN_ERR "Bad IO access at port %#lx (%s)\n", port, access);
WARN_ON(1);
}
}
diff --git a/lib/ioremap.c b/lib/ioremap.c
index 760521417b69..14c6078f17a2 100644
--- a/lib/ioremap.c
+++ b/lib/ioremap.c
@@ -8,6 +8,7 @@
#include <linux/vmalloc.h>
#include <linux/mm.h>
#include <linux/sched.h>
+#include <linux/io.h>
#include <asm/cacheflush.h>
#include <asm/pgtable.h>
diff --git a/lib/kernel_lock.c b/lib/kernel_lock.c
index e0fdfddb406e..f73e2f8c308f 100644
--- a/lib/kernel_lock.c
+++ b/lib/kernel_lock.c
@@ -2,7 +2,7 @@
* lib/kernel_lock.c
*
* This is the traditional BKL - big kernel lock. Largely
- * relegated to obsolescense, but used by various less
+ * relegated to obsolescence, but used by various less
* important (or lazy) subsystems.
*/
#include <linux/smp_lock.h>
diff --git a/lib/kobject.c b/lib/kobject.c
index 03d40360ff1b..a7e3bf4d3c70 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -308,6 +308,19 @@ int kobject_rename(struct kobject * kobj, const char *new_name)
if (!kobj->parent)
return -EINVAL;
+ /* see if this name is already in use */
+ if (kobj->kset) {
+ struct kobject *temp_kobj;
+ temp_kobj = kset_find_obj(kobj->kset, new_name);
+ if (temp_kobj) {
+ printk(KERN_WARNING "kobject '%s' can not be renamed "
+ "to '%s' as '%s' is already in existance.\n",
+ kobject_name(kobj), new_name, new_name);
+ kobject_put(temp_kobj);
+ return -EINVAL;
+ }
+ }
+
devpath = kobject_get_path(kobj, GFP_KERNEL);
if (!devpath) {
error = -ENOMEM;
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index 2e4eae5b0824..5886147252d0 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -126,7 +126,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
else
subsystem = kobject_name(&kset->kobj);
if (!subsystem) {
- pr_debug("unset subsytem caused the event to drop!\n");
+ pr_debug("unset subsystem caused the event to drop!\n");
return 0;
}
diff --git a/lib/libcrc32c.c b/lib/libcrc32c.c
index 60f46803af3f..b5c3287d8ea4 100644
--- a/lib/libcrc32c.c
+++ b/lib/libcrc32c.c
@@ -33,7 +33,6 @@
#include <linux/crc32c.h>
#include <linux/compiler.h>
#include <linux/module.h>
-#include <asm/byteorder.h>
MODULE_AUTHOR("Clay Haapala <chaapala@cisco.com>");
MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations");
@@ -66,7 +65,7 @@ EXPORT_SYMBOL(crc32c_le);
* loop below with crc32 and vary the POLY if we don't find value in terms
* of space and maintainability in keeping the two modules separate.
*/
-u32 __attribute_pure__
+u32 __pure
crc32c_le(u32 crc, unsigned char const *p, size_t len)
{
int i;
@@ -160,16 +159,14 @@ static const u32 crc32c_table[256] = {
* crc using table.
*/
-u32 __attribute_pure__
-crc32c_le(u32 seed, unsigned char const *data, size_t length)
+u32 __pure
+crc32c_le(u32 crc, unsigned char const *data, size_t length)
{
- u32 crc = __cpu_to_le32(seed);
-
while (length--)
crc =
crc32c_table[(crc ^ *data++) & 0xFFL] ^ (crc >> 8);
- return __le32_to_cpu(crc);
+ return crc;
}
#endif /* CRC_LE_BITS == 8 */
@@ -177,7 +174,7 @@ crc32c_le(u32 seed, unsigned char const *data, size_t length)
EXPORT_SYMBOL(crc32c_be);
#if CRC_BE_BITS == 1
-u32 __attribute_pure__
+u32 __pure
crc32c_be(u32 crc, unsigned char const *p, size_t len)
{
int i;
diff --git a/lib/percpu_counter.c b/lib/percpu_counter.c
index cf22c617baa4..393a0e915c23 100644
--- a/lib/percpu_counter.c
+++ b/lib/percpu_counter.c
@@ -14,15 +14,29 @@ static LIST_HEAD(percpu_counters);
static DEFINE_MUTEX(percpu_counters_lock);
#endif
-void percpu_counter_mod(struct percpu_counter *fbc, s32 amount)
+void percpu_counter_set(struct percpu_counter *fbc, s64 amount)
{
- long count;
+ int cpu;
+
+ spin_lock(&fbc->lock);
+ for_each_possible_cpu(cpu) {
+ s32 *pcount = per_cpu_ptr(fbc->counters, cpu);
+ *pcount = 0;
+ }
+ fbc->count = amount;
+ spin_unlock(&fbc->lock);
+}
+EXPORT_SYMBOL(percpu_counter_set);
+
+void __percpu_counter_add(struct percpu_counter *fbc, s64 amount, s32 batch)
+{
+ s64 count;
s32 *pcount;
int cpu = get_cpu();
pcount = per_cpu_ptr(fbc->counters, cpu);
count = *pcount + amount;
- if (count >= FBC_BATCH || count <= -FBC_BATCH) {
+ if (count >= batch || count <= -batch) {
spin_lock(&fbc->lock);
fbc->count += count;
*pcount = 0;
@@ -32,13 +46,13 @@ void percpu_counter_mod(struct percpu_counter *fbc, s32 amount)
}
put_cpu();
}
-EXPORT_SYMBOL(percpu_counter_mod);
+EXPORT_SYMBOL(__percpu_counter_add);
/*
* Add up all the per-cpu counts, return the result. This is a more accurate
* but much slower version of percpu_counter_read_positive()
*/
-s64 percpu_counter_sum(struct percpu_counter *fbc)
+s64 __percpu_counter_sum(struct percpu_counter *fbc)
{
s64 ret;
int cpu;
@@ -50,25 +64,43 @@ s64 percpu_counter_sum(struct percpu_counter *fbc)
ret += *pcount;
}
spin_unlock(&fbc->lock);
- return ret < 0 ? 0 : ret;
+ return ret;
}
-EXPORT_SYMBOL(percpu_counter_sum);
+EXPORT_SYMBOL(__percpu_counter_sum);
+
+static struct lock_class_key percpu_counter_irqsafe;
-void percpu_counter_init(struct percpu_counter *fbc, s64 amount)
+int percpu_counter_init(struct percpu_counter *fbc, s64 amount)
{
spin_lock_init(&fbc->lock);
fbc->count = amount;
fbc->counters = alloc_percpu(s32);
+ if (!fbc->counters)
+ return -ENOMEM;
#ifdef CONFIG_HOTPLUG_CPU
mutex_lock(&percpu_counters_lock);
list_add(&fbc->list, &percpu_counters);
mutex_unlock(&percpu_counters_lock);
#endif
+ return 0;
}
EXPORT_SYMBOL(percpu_counter_init);
+int percpu_counter_init_irq(struct percpu_counter *fbc, s64 amount)
+{
+ int err;
+
+ err = percpu_counter_init(fbc, amount);
+ if (!err)
+ lockdep_set_class(&fbc->lock, &percpu_counter_irqsafe);
+ return err;
+}
+
void percpu_counter_destroy(struct percpu_counter *fbc)
{
+ if (!fbc->counters)
+ return;
+
free_percpu(fbc->counters);
#ifdef CONFIG_HOTPLUG_CPU
mutex_lock(&percpu_counters_lock);
@@ -92,12 +124,13 @@ static int __cpuinit percpu_counter_hotcpu_callback(struct notifier_block *nb,
mutex_lock(&percpu_counters_lock);
list_for_each_entry(fbc, &percpu_counters, list) {
s32 *pcount;
+ unsigned long flags;
- spin_lock(&fbc->lock);
+ spin_lock_irqsave(&fbc->lock, flags);
pcount = per_cpu_ptr(fbc->counters, cpu);
fbc->count += *pcount;
*pcount = 0;
- spin_unlock(&fbc->lock);
+ spin_unlock_irqrestore(&fbc->lock, flags);
}
mutex_unlock(&percpu_counters_lock);
return NOTIFY_OK;
diff --git a/lib/prio_heap.c b/lib/prio_heap.c
new file mode 100644
index 000000000000..471944a54e23
--- /dev/null
+++ b/lib/prio_heap.c
@@ -0,0 +1,70 @@
+/*
+ * Simple insertion-only static-sized priority heap containing
+ * pointers, based on CLR, chapter 7
+ */
+
+#include <linux/slab.h>
+#include <linux/prio_heap.h>
+
+int heap_init(struct ptr_heap *heap, size_t size, gfp_t gfp_mask,
+ int (*gt)(void *, void *))
+{
+ heap->ptrs = kmalloc(size, gfp_mask);
+ if (!heap->ptrs)
+ return -ENOMEM;
+ heap->size = 0;
+ heap->max = size / sizeof(void *);
+ heap->gt = gt;
+ return 0;
+}
+
+void heap_free(struct ptr_heap *heap)
+{
+ kfree(heap->ptrs);
+}
+
+void *heap_insert(struct ptr_heap *heap, void *p)
+{
+ void *res;
+ void **ptrs = heap->ptrs;
+ int pos;
+
+ if (heap->size < heap->max) {
+ /* Heap insertion */
+ int pos = heap->size++;
+ while (pos > 0 && heap->gt(p, ptrs[(pos-1)/2])) {
+ ptrs[pos] = ptrs[(pos-1)/2];
+ pos = (pos-1)/2;
+ }
+ ptrs[pos] = p;
+ return NULL;
+ }
+
+ /* The heap is full, so something will have to be dropped */
+
+ /* If the new pointer is greater than the current max, drop it */
+ if (heap->gt(p, ptrs[0]))
+ return p;
+
+ /* Replace the current max and heapify */
+ res = ptrs[0];
+ ptrs[0] = p;
+ pos = 0;
+
+ while (1) {
+ int left = 2 * pos + 1;
+ int right = 2 * pos + 2;
+ int largest = pos;
+ if (left < heap->size && heap->gt(ptrs[left], p))
+ largest = left;
+ if (right < heap->size && heap->gt(ptrs[right], ptrs[largest]))
+ largest = right;
+ if (largest == pos)
+ break;
+ /* Push p down the heap one level and bump one up */
+ ptrs[pos] = ptrs[largest];
+ ptrs[largest] = p;
+ pos = largest;
+ }
+ return res;
+}
diff --git a/lib/proportions.c b/lib/proportions.c
new file mode 100644
index 000000000000..332d8c58184d
--- /dev/null
+++ b/lib/proportions.c
@@ -0,0 +1,384 @@
+/*
+ * Floating proportions
+ *
+ * Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *
+ * Description:
+ *
+ * The floating proportion is a time derivative with an exponentially decaying
+ * history:
+ *
+ * p_{j} = \Sum_{i=0} (dx_{j}/dt_{-i}) / 2^(1+i)
+ *
+ * Where j is an element from {prop_local}, x_{j} is j's number of events,
+ * and i the time period over which the differential is taken. So d/dt_{-i} is
+ * the differential over the i-th last period.
+ *
+ * The decaying history gives smooth transitions. The time differential carries
+ * the notion of speed.
+ *
+ * The denominator is 2^(1+i) because we want the series to be normalised, ie.
+ *
+ * \Sum_{i=0} 1/2^(1+i) = 1
+ *
+ * Further more, if we measure time (t) in the same events as x; so that:
+ *
+ * t = \Sum_{j} x_{j}
+ *
+ * we get that:
+ *
+ * \Sum_{j} p_{j} = 1
+ *
+ * Writing this in an iterative fashion we get (dropping the 'd's):
+ *
+ * if (++x_{j}, ++t > period)
+ * t /= 2;
+ * for_each (j)
+ * x_{j} /= 2;
+ *
+ * so that:
+ *
+ * p_{j} = x_{j} / t;
+ *
+ * We optimize away the '/= 2' for the global time delta by noting that:
+ *
+ * if (++t > period) t /= 2:
+ *
+ * Can be approximated by:
+ *
+ * period/2 + (++t % period/2)
+ *
+ * [ Furthermore, when we choose period to be 2^n it can be written in terms of
+ * binary operations and wraparound artefacts disappear. ]
+ *
+ * Also note that this yields a natural counter of the elapsed periods:
+ *
+ * c = t / (period/2)
+ *
+ * [ Its monotonic increasing property can be applied to mitigate the wrap-
+ * around issue. ]
+ *
+ * This allows us to do away with the loop over all prop_locals on each period
+ * expiration. By remembering the period count under which it was last accessed
+ * as c_{j}, we can obtain the number of 'missed' cycles from:
+ *
+ * c - c_{j}
+ *
+ * We can then lazily catch up to the global period count every time we are
+ * going to use x_{j}, by doing:
+ *
+ * x_{j} /= 2^(c - c_{j}), c_{j} = c
+ */
+
+#include <linux/proportions.h>
+#include <linux/rcupdate.h>
+
+/*
+ * Limit the time part in order to ensure there are some bits left for the
+ * cycle counter.
+ */
+#define PROP_MAX_SHIFT (3*BITS_PER_LONG/4)
+
+int prop_descriptor_init(struct prop_descriptor *pd, int shift)
+{
+ int err;
+
+ if (shift > PROP_MAX_SHIFT)
+ shift = PROP_MAX_SHIFT;
+
+ pd->index = 0;
+ pd->pg[0].shift = shift;
+ mutex_init(&pd->mutex);
+ err = percpu_counter_init_irq(&pd->pg[0].events, 0);
+ if (err)
+ goto out;
+
+ err = percpu_counter_init_irq(&pd->pg[1].events, 0);
+ if (err)
+ percpu_counter_destroy(&pd->pg[0].events);
+
+out:
+ return err;
+}
+
+/*
+ * We have two copies, and flip between them to make it seem like an atomic
+ * update. The update is not really atomic wrt the events counter, but
+ * it is internally consistent with the bit layout depending on shift.
+ *
+ * We copy the events count, move the bits around and flip the index.
+ */
+void prop_change_shift(struct prop_descriptor *pd, int shift)
+{
+ int index;
+ int offset;
+ u64 events;
+ unsigned long flags;
+
+ if (shift > PROP_MAX_SHIFT)
+ shift = PROP_MAX_SHIFT;
+
+ mutex_lock(&pd->mutex);
+
+ index = pd->index ^ 1;
+ offset = pd->pg[pd->index].shift - shift;
+ if (!offset)
+ goto out;
+
+ pd->pg[index].shift = shift;
+
+ local_irq_save(flags);
+ events = percpu_counter_sum(&pd->pg[pd->index].events);
+ if (offset < 0)
+ events <<= -offset;
+ else
+ events >>= offset;
+ percpu_counter_set(&pd->pg[index].events, events);
+
+ /*
+ * ensure the new pg is fully written before the switch
+ */
+ smp_wmb();
+ pd->index = index;
+ local_irq_restore(flags);
+
+ synchronize_rcu();
+
+out:
+ mutex_unlock(&pd->mutex);
+}
+
+/*
+ * wrap the access to the data in an rcu_read_lock() section;
+ * this is used to track the active references.
+ */
+static struct prop_global *prop_get_global(struct prop_descriptor *pd)
+{
+ int index;
+
+ rcu_read_lock();
+ index = pd->index;
+ /*
+ * match the wmb from vcd_flip()
+ */
+ smp_rmb();
+ return &pd->pg[index];
+}
+
+static void prop_put_global(struct prop_descriptor *pd, struct prop_global *pg)
+{
+ rcu_read_unlock();
+}
+
+static void
+prop_adjust_shift(int *pl_shift, unsigned long *pl_period, int new_shift)
+{
+ int offset = *pl_shift - new_shift;
+
+ if (!offset)
+ return;
+
+ if (offset < 0)
+ *pl_period <<= -offset;
+ else
+ *pl_period >>= offset;
+
+ *pl_shift = new_shift;
+}
+
+/*
+ * PERCPU
+ */
+
+int prop_local_init_percpu(struct prop_local_percpu *pl)
+{
+ spin_lock_init(&pl->lock);
+ pl->shift = 0;
+ pl->period = 0;
+ return percpu_counter_init_irq(&pl->events, 0);
+}
+
+void prop_local_destroy_percpu(struct prop_local_percpu *pl)
+{
+ percpu_counter_destroy(&pl->events);
+}
+
+/*
+ * Catch up with missed period expirations.
+ *
+ * until (c_{j} == c)
+ * x_{j} -= x_{j}/2;
+ * c_{j}++;
+ */
+static
+void prop_norm_percpu(struct prop_global *pg, struct prop_local_percpu *pl)
+{
+ unsigned long period = 1UL << (pg->shift - 1);
+ unsigned long period_mask = ~(period - 1);
+ unsigned long global_period;
+ unsigned long flags;
+
+ global_period = percpu_counter_read(&pg->events);
+ global_period &= period_mask;
+
+ /*
+ * Fast path - check if the local and global period count still match
+ * outside of the lock.
+ */
+ if (pl->period == global_period)
+ return;
+
+ spin_lock_irqsave(&pl->lock, flags);
+ prop_adjust_shift(&pl->shift, &pl->period, pg->shift);
+ /*
+ * For each missed period, we half the local counter.
+ * basically:
+ * pl->events >> (global_period - pl->period);
+ *
+ * but since the distributed nature of percpu counters make division
+ * rather hard, use a regular subtraction loop. This is safe, because
+ * the events will only every be incremented, hence the subtraction
+ * can never result in a negative number.
+ */
+ while (pl->period != global_period) {
+ unsigned long val = percpu_counter_read(&pl->events);
+ unsigned long half = (val + 1) >> 1;
+
+ /*
+ * Half of zero won't be much less, break out.
+ * This limits the loop to shift iterations, even
+ * if we missed a million.
+ */
+ if (!val)
+ break;
+
+ percpu_counter_add(&pl->events, -half);
+ pl->period += period;
+ }
+ pl->period = global_period;
+ spin_unlock_irqrestore(&pl->lock, flags);
+}
+
+/*
+ * ++x_{j}, ++t
+ */
+void __prop_inc_percpu(struct prop_descriptor *pd, struct prop_local_percpu *pl)
+{
+ struct prop_global *pg = prop_get_global(pd);
+
+ prop_norm_percpu(pg, pl);
+ percpu_counter_add(&pl->events, 1);
+ percpu_counter_add(&pg->events, 1);
+ prop_put_global(pd, pg);
+}
+
+/*
+ * Obtain a fraction of this proportion
+ *
+ * p_{j} = x_{j} / (period/2 + t % period/2)
+ */
+void prop_fraction_percpu(struct prop_descriptor *pd,
+ struct prop_local_percpu *pl,
+ long *numerator, long *denominator)
+{
+ struct prop_global *pg = prop_get_global(pd);
+ unsigned long period_2 = 1UL << (pg->shift - 1);
+ unsigned long counter_mask = period_2 - 1;
+ unsigned long global_count;
+
+ prop_norm_percpu(pg, pl);
+ *numerator = percpu_counter_read_positive(&pl->events);
+
+ global_count = percpu_counter_read(&pg->events);
+ *denominator = period_2 + (global_count & counter_mask);
+
+ prop_put_global(pd, pg);
+}
+
+/*
+ * SINGLE
+ */
+
+int prop_local_init_single(struct prop_local_single *pl)
+{
+ spin_lock_init(&pl->lock);
+ pl->shift = 0;
+ pl->period = 0;
+ pl->events = 0;
+ return 0;
+}
+
+void prop_local_destroy_single(struct prop_local_single *pl)
+{
+}
+
+/*
+ * Catch up with missed period expirations.
+ */
+static
+void prop_norm_single(struct prop_global *pg, struct prop_local_single *pl)
+{
+ unsigned long period = 1UL << (pg->shift - 1);
+ unsigned long period_mask = ~(period - 1);
+ unsigned long global_period;
+ unsigned long flags;
+
+ global_period = percpu_counter_read(&pg->events);
+ global_period &= period_mask;
+
+ /*
+ * Fast path - check if the local and global period count still match
+ * outside of the lock.
+ */
+ if (pl->period == global_period)
+ return;
+
+ spin_lock_irqsave(&pl->lock, flags);
+ prop_adjust_shift(&pl->shift, &pl->period, pg->shift);
+ /*
+ * For each missed period, we half the local counter.
+ */
+ period = (global_period - pl->period) >> (pg->shift - 1);
+ if (likely(period < BITS_PER_LONG))
+ pl->events >>= period;
+ else
+ pl->events = 0;
+ pl->period = global_period;
+ spin_unlock_irqrestore(&pl->lock, flags);
+}
+
+/*
+ * ++x_{j}, ++t
+ */
+void __prop_inc_single(struct prop_descriptor *pd, struct prop_local_single *pl)
+{
+ struct prop_global *pg = prop_get_global(pd);
+
+ prop_norm_single(pg, pl);
+ pl->events++;
+ percpu_counter_add(&pg->events, 1);
+ prop_put_global(pd, pg);
+}
+
+/*
+ * Obtain a fraction of this proportion
+ *
+ * p_{j} = x_{j} / (period/2 + t % period/2)
+ */
+void prop_fraction_single(struct prop_descriptor *pd,
+ struct prop_local_single *pl,
+ long *numerator, long *denominator)
+{
+ struct prop_global *pg = prop_get_global(pd);
+ unsigned long period_2 = 1UL << (pg->shift - 1);
+ unsigned long counter_mask = period_2 - 1;
+ unsigned long global_count;
+
+ prop_norm_single(pg, pl);
+ *numerator = pl->events;
+
+ global_count = percpu_counter_read(&pg->events);
+ *denominator = period_2 + (global_count & counter_mask);
+
+ prop_put_global(pd, pg);
+}
diff --git a/lib/radix-tree.c b/lib/radix-tree.c
index 514efb200be6..48c250fe2233 100644
--- a/lib/radix-tree.c
+++ b/lib/radix-tree.c
@@ -60,9 +60,14 @@ struct radix_tree_path {
};
#define RADIX_TREE_INDEX_BITS (8 /* CHAR_BIT */ * sizeof(unsigned long))
-#define RADIX_TREE_MAX_PATH (RADIX_TREE_INDEX_BITS/RADIX_TREE_MAP_SHIFT + 2)
+#define RADIX_TREE_MAX_PATH (DIV_ROUND_UP(RADIX_TREE_INDEX_BITS, \
+ RADIX_TREE_MAP_SHIFT))
-static unsigned long height_to_maxindex[RADIX_TREE_MAX_PATH] __read_mostly;
+/*
+ * The height_to_maxindex array needs to be one deeper than the maximum
+ * path as height 0 holds only 1 entry.
+ */
+static unsigned long height_to_maxindex[RADIX_TREE_MAX_PATH + 1] __read_mostly;
/*
* Radix tree node cache.
@@ -93,7 +98,8 @@ radix_tree_node_alloc(struct radix_tree_root *root)
struct radix_tree_node *ret;
gfp_t gfp_mask = root_gfp_mask(root);
- ret = kmem_cache_alloc(radix_tree_node_cachep, gfp_mask);
+ ret = kmem_cache_alloc(radix_tree_node_cachep,
+ set_migrateflags(gfp_mask, __GFP_RECLAIMABLE));
if (ret == NULL && !(gfp_mask & __GFP_WAIT)) {
struct radix_tree_preload *rtp;
@@ -104,7 +110,7 @@ radix_tree_node_alloc(struct radix_tree_root *root)
rtp->nr--;
}
}
- BUG_ON(radix_tree_is_direct_ptr(ret));
+ BUG_ON(radix_tree_is_indirect_ptr(ret));
return ret;
}
@@ -137,7 +143,8 @@ int radix_tree_preload(gfp_t gfp_mask)
rtp = &__get_cpu_var(radix_tree_preloads);
while (rtp->nr < ARRAY_SIZE(rtp->nodes)) {
preempt_enable();
- node = kmem_cache_alloc(radix_tree_node_cachep, gfp_mask);
+ node = kmem_cache_alloc(radix_tree_node_cachep,
+ set_migrateflags(gfp_mask, __GFP_RECLAIMABLE));
if (node == NULL)
goto out;
preempt_disable();
@@ -240,7 +247,7 @@ static int radix_tree_extend(struct radix_tree_root *root, unsigned long index)
return -ENOMEM;
/* Increase the height. */
- node->slots[0] = radix_tree_direct_to_ptr(root->rnode);
+ node->slots[0] = radix_tree_indirect_to_ptr(root->rnode);
/* Propagate the aggregated tag info into the new root */
for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) {
@@ -251,6 +258,7 @@ static int radix_tree_extend(struct radix_tree_root *root, unsigned long index)
newheight = root->height+1;
node->height = newheight;
node->count = 1;
+ node = radix_tree_ptr_to_indirect(node);
rcu_assign_pointer(root->rnode, node);
root->height = newheight;
} while (height > root->height);
@@ -274,7 +282,7 @@ int radix_tree_insert(struct radix_tree_root *root,
int offset;
int error;
- BUG_ON(radix_tree_is_direct_ptr(item));
+ BUG_ON(radix_tree_is_indirect_ptr(item));
/* Make sure the tree is high enough. */
if (index > radix_tree_maxindex(root->height)) {
@@ -283,7 +291,8 @@ int radix_tree_insert(struct radix_tree_root *root,
return error;
}
- slot = root->rnode;
+ slot = radix_tree_indirect_to_ptr(root->rnode);
+
height = root->height;
shift = (height-1) * RADIX_TREE_MAP_SHIFT;
@@ -298,7 +307,8 @@ int radix_tree_insert(struct radix_tree_root *root,
rcu_assign_pointer(node->slots[offset], slot);
node->count++;
} else
- rcu_assign_pointer(root->rnode, slot);
+ rcu_assign_pointer(root->rnode,
+ radix_tree_ptr_to_indirect(slot));
}
/* Go a level down */
@@ -318,7 +328,7 @@ int radix_tree_insert(struct radix_tree_root *root,
BUG_ON(tag_get(node, 0, offset));
BUG_ON(tag_get(node, 1, offset));
} else {
- rcu_assign_pointer(root->rnode, radix_tree_ptr_to_direct(item));
+ rcu_assign_pointer(root->rnode, item);
BUG_ON(root_tag_get(root, 0));
BUG_ON(root_tag_get(root, 1));
}
@@ -350,11 +360,12 @@ void **radix_tree_lookup_slot(struct radix_tree_root *root, unsigned long index)
if (node == NULL)
return NULL;
- if (radix_tree_is_direct_ptr(node)) {
+ if (!radix_tree_is_indirect_ptr(node)) {
if (index > 0)
return NULL;
return (void **)&root->rnode;
}
+ node = radix_tree_indirect_to_ptr(node);
height = node->height;
if (index > radix_tree_maxindex(height))
@@ -398,11 +409,12 @@ void *radix_tree_lookup(struct radix_tree_root *root, unsigned long index)
if (node == NULL)
return NULL;
- if (radix_tree_is_direct_ptr(node)) {
+ if (!radix_tree_is_indirect_ptr(node)) {
if (index > 0)
return NULL;
- return radix_tree_direct_to_ptr(node);
+ return node;
}
+ node = radix_tree_indirect_to_ptr(node);
height = node->height;
if (index > radix_tree_maxindex(height))
@@ -447,7 +459,7 @@ void *radix_tree_tag_set(struct radix_tree_root *root,
height = root->height;
BUG_ON(index > radix_tree_maxindex(height));
- slot = root->rnode;
+ slot = radix_tree_indirect_to_ptr(root->rnode);
shift = (height - 1) * RADIX_TREE_MAP_SHIFT;
while (height > 0) {
@@ -487,7 +499,11 @@ EXPORT_SYMBOL(radix_tree_tag_set);
void *radix_tree_tag_clear(struct radix_tree_root *root,
unsigned long index, unsigned int tag)
{
- struct radix_tree_path path[RADIX_TREE_MAX_PATH], *pathp = path;
+ /*
+ * The radix tree path needs to be one longer than the maximum path
+ * since the "list" is null terminated.
+ */
+ struct radix_tree_path path[RADIX_TREE_MAX_PATH + 1], *pathp = path;
struct radix_tree_node *slot = NULL;
unsigned int height, shift;
@@ -497,7 +513,7 @@ void *radix_tree_tag_clear(struct radix_tree_root *root,
shift = (height - 1) * RADIX_TREE_MAP_SHIFT;
pathp->node = NULL;
- slot = root->rnode;
+ slot = radix_tree_indirect_to_ptr(root->rnode);
while (height > 0) {
int offset;
@@ -562,8 +578,9 @@ int radix_tree_tag_get(struct radix_tree_root *root,
if (node == NULL)
return 0;
- if (radix_tree_is_direct_ptr(node))
+ if (!radix_tree_is_indirect_ptr(node))
return (index == 0);
+ node = radix_tree_indirect_to_ptr(node);
height = node->height;
if (index > radix_tree_maxindex(height))
@@ -599,6 +616,42 @@ int radix_tree_tag_get(struct radix_tree_root *root,
EXPORT_SYMBOL(radix_tree_tag_get);
#endif
+/**
+ * radix_tree_next_hole - find the next hole (not-present entry)
+ * @root: tree root
+ * @index: index key
+ * @max_scan: maximum range to search
+ *
+ * Search the set [index, min(index+max_scan-1, MAX_INDEX)] for the lowest
+ * indexed hole.
+ *
+ * Returns: the index of the hole if found, otherwise returns an index
+ * outside of the set specified (in which case 'return - index >= max_scan'
+ * will be true).
+ *
+ * radix_tree_next_hole may be called under rcu_read_lock. However, like
+ * radix_tree_gang_lookup, this will not atomically search a snapshot of the
+ * tree at a single point in time. For example, if a hole is created at index
+ * 5, then subsequently a hole is created at index 10, radix_tree_next_hole
+ * covering both indexes may return 10 if called under rcu_read_lock.
+ */
+unsigned long radix_tree_next_hole(struct radix_tree_root *root,
+ unsigned long index, unsigned long max_scan)
+{
+ unsigned long i;
+
+ for (i = 0; i < max_scan; i++) {
+ if (!radix_tree_lookup(root, index))
+ break;
+ index++;
+ if (index == 0)
+ break;
+ }
+
+ return index;
+}
+EXPORT_SYMBOL(radix_tree_next_hole);
+
static unsigned int
__lookup(struct radix_tree_node *slot, void **results, unsigned long index,
unsigned int max_items, unsigned long *next_index)
@@ -680,13 +733,13 @@ radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
if (!node)
return 0;
- if (radix_tree_is_direct_ptr(node)) {
+ if (!radix_tree_is_indirect_ptr(node)) {
if (first_index > 0)
return 0;
- node = radix_tree_direct_to_ptr(node);
- results[0] = rcu_dereference(node);
+ results[0] = node;
return 1;
}
+ node = radix_tree_indirect_to_ptr(node);
max_index = radix_tree_maxindex(node->height);
@@ -808,13 +861,13 @@ radix_tree_gang_lookup_tag(struct radix_tree_root *root, void **results,
if (!node)
return 0;
- if (radix_tree_is_direct_ptr(node)) {
+ if (!radix_tree_is_indirect_ptr(node)) {
if (first_index > 0)
return 0;
- node = radix_tree_direct_to_ptr(node);
- results[0] = rcu_dereference(node);
+ results[0] = node;
return 1;
}
+ node = radix_tree_indirect_to_ptr(node);
max_index = radix_tree_maxindex(node->height);
@@ -844,12 +897,22 @@ EXPORT_SYMBOL(radix_tree_gang_lookup_tag);
static inline void radix_tree_shrink(struct radix_tree_root *root)
{
/* try to shrink tree height */
- while (root->height > 0 &&
- root->rnode->count == 1 &&
- root->rnode->slots[0]) {
+ while (root->height > 0) {
struct radix_tree_node *to_free = root->rnode;
void *newptr;
+ BUG_ON(!radix_tree_is_indirect_ptr(to_free));
+ to_free = radix_tree_indirect_to_ptr(to_free);
+
+ /*
+ * The candidate node has more than one child, or its child
+ * is not at the leftmost slot, we cannot shrink.
+ */
+ if (to_free->count != 1)
+ break;
+ if (!to_free->slots[0])
+ break;
+
/*
* We don't need rcu_assign_pointer(), since we are simply
* moving the node from one part of the tree to another. If
@@ -858,8 +921,8 @@ static inline void radix_tree_shrink(struct radix_tree_root *root)
* one (root->rnode).
*/
newptr = to_free->slots[0];
- if (root->height == 1)
- newptr = radix_tree_ptr_to_direct(newptr);
+ if (root->height > 1)
+ newptr = radix_tree_ptr_to_indirect(newptr);
root->rnode = newptr;
root->height--;
/* must only free zeroed nodes into the slab */
@@ -882,7 +945,11 @@ static inline void radix_tree_shrink(struct radix_tree_root *root)
*/
void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
{
- struct radix_tree_path path[RADIX_TREE_MAX_PATH], *pathp = path;
+ /*
+ * The radix tree path needs to be one longer than the maximum path
+ * since the "list" is null terminated.
+ */
+ struct radix_tree_path path[RADIX_TREE_MAX_PATH + 1], *pathp = path;
struct radix_tree_node *slot = NULL;
struct radix_tree_node *to_free;
unsigned int height, shift;
@@ -894,12 +961,12 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
goto out;
slot = root->rnode;
- if (height == 0 && root->rnode) {
- slot = radix_tree_direct_to_ptr(slot);
+ if (height == 0) {
root_tag_clear_all(root);
root->rnode = NULL;
goto out;
}
+ slot = radix_tree_indirect_to_ptr(slot);
shift = (height - 1) * RADIX_TREE_MAP_SHIFT;
pathp->node = NULL;
@@ -941,7 +1008,8 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
radix_tree_node_free(to_free);
if (pathp->node->count) {
- if (pathp->node == root->rnode)
+ if (pathp->node ==
+ radix_tree_indirect_to_ptr(root->rnode))
radix_tree_shrink(root);
goto out;
}
@@ -974,19 +1042,21 @@ int radix_tree_tagged(struct radix_tree_root *root, unsigned int tag)
EXPORT_SYMBOL(radix_tree_tagged);
static void
-radix_tree_node_ctor(void *node, struct kmem_cache *cachep, unsigned long flags)
+radix_tree_node_ctor(struct kmem_cache *cachep, void *node)
{
memset(node, 0, sizeof(struct radix_tree_node));
}
static __init unsigned long __maxindex(unsigned int height)
{
- unsigned int tmp = height * RADIX_TREE_MAP_SHIFT;
- unsigned long index = (~0UL >> (RADIX_TREE_INDEX_BITS - tmp - 1)) >> 1;
-
- if (tmp >= RADIX_TREE_INDEX_BITS)
- index = ~0UL;
- return index;
+ unsigned int width = height * RADIX_TREE_MAP_SHIFT;
+ int shift = RADIX_TREE_INDEX_BITS - width;
+
+ if (shift < 0)
+ return ~0UL;
+ if (shift >= BITS_PER_LONG)
+ return 0UL;
+ return ~0UL >> shift;
}
static __init void radix_tree_init_maxindex(void)
diff --git a/lib/reed_solomon/decode_rs.c b/lib/reed_solomon/decode_rs.c
index a58df56f09b6..0ec3f257ffdf 100644
--- a/lib/reed_solomon/decode_rs.c
+++ b/lib/reed_solomon/decode_rs.c
@@ -39,8 +39,7 @@
/* Check length parameter for validity */
pad = nn - nroots - len;
- if (pad < 0 || pad >= nn)
- return -ERANGE;
+ BUG_ON(pad < 0 || pad >= nn);
/* Does the caller provide the syndrome ? */
if (s != NULL)
@@ -203,7 +202,7 @@
* deg(lambda) unequal to number of roots => uncorrectable
* error detected
*/
- count = -1;
+ count = -EBADMSG;
goto finish;
}
/*
diff --git a/lib/reed_solomon/reed_solomon.c b/lib/reed_solomon/reed_solomon.c
index 5b0d8522b7ca..3ea2db94d5b0 100644
--- a/lib/reed_solomon/reed_solomon.c
+++ b/lib/reed_solomon/reed_solomon.c
@@ -320,6 +320,7 @@ EXPORT_SYMBOL_GPL(encode_rs8);
* The syndrome and parity uses a uint16_t data type to enable
* symbol size > 8. The calling code must take care of decoding of the
* syndrome result and the received parity before calling this code.
+ * Returns the number of corrected bits or -EBADMSG for uncorrectable errors.
*/
int decode_rs8(struct rs_control *rs, uint8_t *data, uint16_t *par, int len,
uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk,
@@ -363,6 +364,7 @@ EXPORT_SYMBOL_GPL(encode_rs16);
* @corr: buffer to store correction bitmask on eras_pos
*
* Each field in the data array contains up to symbol size bits of valid data.
+ * Returns the number of corrected bits or -EBADMSG for uncorrectable errors.
*/
int decode_rs16(struct rs_control *rs, uint16_t *data, uint16_t *par, int len,
uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk,
diff --git a/lib/sort.c b/lib/sort.c
index 961567894d16..6abbaf3d5858 100644
--- a/lib/sort.c
+++ b/lib/sort.c
@@ -67,7 +67,7 @@ void sort(void *base, size_t num, size_t size,
}
/* sort */
- for (i = n - size; i >= 0; i -= size) {
+ for (i = n - size; i > 0; i -= size) {
swap(base, base + i, size);
for (r = 0; r * 2 + size < i; r = c) {
c = r * 2 + size;
diff --git a/lib/spinlock_debug.c b/lib/spinlock_debug.c
index 479fd462eaa9..9c4b0256490b 100644
--- a/lib/spinlock_debug.c
+++ b/lib/spinlock_debug.c
@@ -60,12 +60,12 @@ static void spin_bug(spinlock_t *lock, const char *msg)
owner = lock->owner;
printk(KERN_EMERG "BUG: spinlock %s on CPU#%d, %s/%d\n",
msg, raw_smp_processor_id(),
- current->comm, current->pid);
+ current->comm, task_pid_nr(current));
printk(KERN_EMERG " lock: %p, .magic: %08x, .owner: %s/%d, "
".owner_cpu: %d\n",
lock, lock->magic,
owner ? owner->comm : "<none>",
- owner ? owner->pid : -1,
+ owner ? task_pid_nr(owner) : -1,
lock->owner_cpu);
dump_stack();
}
@@ -116,7 +116,7 @@ static void __spin_lock_debug(spinlock_t *lock)
printk(KERN_EMERG "BUG: spinlock lockup on CPU#%d, "
"%s/%d, %p\n",
raw_smp_processor_id(), current->comm,
- current->pid, lock);
+ task_pid_nr(current), lock);
dump_stack();
#ifdef CONFIG_SMP
trigger_all_cpu_backtrace();
@@ -161,7 +161,7 @@ static void rwlock_bug(rwlock_t *lock, const char *msg)
printk(KERN_EMERG "BUG: rwlock %s on CPU#%d, %s/%d, %p\n",
msg, raw_smp_processor_id(), current->comm,
- current->pid, lock);
+ task_pid_nr(current), lock);
dump_stack();
}
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 30c1400e749e..1a8050ade861 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -35,7 +35,7 @@
#define OFFSET(val,align) ((unsigned long) \
( (val) & ( (align) - 1)))
-#define SG_ENT_VIRT_ADDRESS(sg) (page_address((sg)->page) + (sg)->offset)
+#define SG_ENT_VIRT_ADDRESS(sg) (sg_virt((sg)))
#define SG_ENT_PHYS_ADDRESS(sg) virt_to_bus(SG_ENT_VIRT_ADDRESS(sg))
/*
@@ -677,16 +677,17 @@ swiotlb_sync_single_range_for_device(struct device *hwdev, dma_addr_t dev_addr,
* same here.
*/
int
-swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nelems,
+swiotlb_map_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
int dir)
{
+ struct scatterlist *sg;
void *addr;
dma_addr_t dev_addr;
int i;
BUG_ON(dir == DMA_NONE);
- for (i = 0; i < nelems; i++, sg++) {
+ for_each_sg(sgl, sg, nelems, i) {
addr = SG_ENT_VIRT_ADDRESS(sg);
dev_addr = virt_to_bus(addr);
if (swiotlb_force || address_needs_mapping(hwdev, dev_addr)) {
@@ -695,8 +696,8 @@ swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nelems,
/* Don't panic here, we expect map_sg users
to do proper error handling. */
swiotlb_full(hwdev, sg->length, dir, 0);
- swiotlb_unmap_sg(hwdev, sg - i, i, dir);
- sg[0].dma_length = 0;
+ swiotlb_unmap_sg(hwdev, sgl, i, dir);
+ sgl[0].dma_length = 0;
return 0;
}
sg->dma_address = virt_to_bus(map);
@@ -712,19 +713,21 @@ swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nelems,
* concerning calls here are the same as for swiotlb_unmap_single() above.
*/
void
-swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nelems,
+swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
int dir)
{
+ struct scatterlist *sg;
int i;
BUG_ON(dir == DMA_NONE);
- for (i = 0; i < nelems; i++, sg++)
+ for_each_sg(sgl, sg, nelems, i) {
if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg))
unmap_single(hwdev, bus_to_virt(sg->dma_address),
sg->dma_length, dir);
else if (dir == DMA_FROM_DEVICE)
dma_mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length);
+ }
}
/*
@@ -735,19 +738,21 @@ swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nelems,
* and usage.
*/
static void
-swiotlb_sync_sg(struct device *hwdev, struct scatterlist *sg,
+swiotlb_sync_sg(struct device *hwdev, struct scatterlist *sgl,
int nelems, int dir, int target)
{
+ struct scatterlist *sg;
int i;
BUG_ON(dir == DMA_NONE);
- for (i = 0; i < nelems; i++, sg++)
+ for_each_sg(sgl, sg, nelems, i) {
if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg))
sync_single(hwdev, bus_to_virt(sg->dma_address),
sg->dma_length, dir, target);
else if (dir == DMA_FROM_DEVICE)
dma_mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length);
+ }
}
void
diff --git a/mm/Kconfig b/mm/Kconfig
index a7609cbcb00d..c070ec0c15bf 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -37,7 +37,7 @@ config DISCONTIGMEM_MANUAL
in their physical address spaces, and this option provides
more efficient handling of these holes. However, the vast
majority of hardware has quite flat address spaces, and
- can have degraded performance from extra overhead that
+ can have degraded performance from the extra overhead that
this option imposes.
Many NUMA configurations will have this as the only option.
@@ -112,6 +112,19 @@ config SPARSEMEM_EXTREME
def_bool y
depends on SPARSEMEM && !SPARSEMEM_STATIC
+#
+# SPARSEMEM_VMEMMAP uses a virtually mapped mem_map to optimise pfn_to_page
+# and page_to_pfn. The most efficient option where kernel virtual space is
+# not under pressure.
+#
+config SPARSEMEM_VMEMMAP_ENABLE
+ def_bool n
+
+config SPARSEMEM_VMEMMAP
+ bool
+ depends on SPARSEMEM
+ default y if (SPARSEMEM_VMEMMAP_ENABLE)
+
# eventually, we can have this option just 'select SPARSEMEM'
config MEMORY_HOTPLUG
bool "Allow for memory hot-add"
@@ -126,6 +139,11 @@ config MEMORY_HOTPLUG_SPARSE
def_bool y
depends on SPARSEMEM && MEMORY_HOTPLUG
+config MEMORY_HOTREMOVE
+ bool "Allow for memory hot remove"
+ depends on MEMORY_HOTPLUG && ARCH_ENABLE_MEMORY_HOTREMOVE
+ depends on MIGRATION
+
# Heavily threaded applications may benefit from splitting the mm-wide
# page_table_lock, so that faults on different parts of the user address
# space can be handled with less contention: split it at this NR_CPUS.
@@ -137,7 +155,6 @@ config SPLIT_PTLOCK_CPUS
int
default "4096" if ARM && !CPU_CACHE_VIPT
default "4096" if PARISC && !PA20
- default "4096" if XEN
default "4"
#
diff --git a/mm/Makefile b/mm/Makefile
index 245e33ab00c4..5c0b0ea7572d 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -11,13 +11,14 @@ obj-y := bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \
page_alloc.o page-writeback.o pdflush.o \
readahead.o swap.o truncate.o vmscan.o \
prio_tree.o util.o mmzone.o vmstat.o backing-dev.o \
- $(mmu-y)
+ page_isolation.o $(mmu-y)
obj-$(CONFIG_BOUNCE) += bounce.o
obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o thrash.o
obj-$(CONFIG_HUGETLBFS) += hugetlb.o
obj-$(CONFIG_NUMA) += mempolicy.o
obj-$(CONFIG_SPARSEMEM) += sparse.o
+obj-$(CONFIG_SPARSEMEM_VMEMMAP) += sparse-vmemmap.o
obj-$(CONFIG_SHMEM) += shmem.o
obj-$(CONFIG_TMPFS_POSIX_ACL) += shmem_acl.o
obj-$(CONFIG_TINY_SHMEM) += tiny-shmem.o
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index f50a2811f9dc..b0ceb29da4c7 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -5,6 +5,41 @@
#include <linux/sched.h>
#include <linux/module.h>
+int bdi_init(struct backing_dev_info *bdi)
+{
+ int i, j;
+ int err;
+
+ for (i = 0; i < NR_BDI_STAT_ITEMS; i++) {
+ err = percpu_counter_init_irq(&bdi->bdi_stat[i], 0);
+ if (err)
+ goto err;
+ }
+
+ bdi->dirty_exceeded = 0;
+ err = prop_local_init_percpu(&bdi->completions);
+
+ if (err) {
+err:
+ for (j = 0; j < i; j++)
+ percpu_counter_destroy(&bdi->bdi_stat[i]);
+ }
+
+ return err;
+}
+EXPORT_SYMBOL(bdi_init);
+
+void bdi_destroy(struct backing_dev_info *bdi)
+{
+ int i;
+
+ for (i = 0; i < NR_BDI_STAT_ITEMS; i++)
+ percpu_counter_destroy(&bdi->bdi_stat[i]);
+
+ prop_local_destroy_percpu(&bdi->completions);
+}
+EXPORT_SYMBOL(bdi_destroy);
+
static wait_queue_head_t congestion_wqh[2] = {
__WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[0]),
__WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[1])
@@ -55,15 +90,3 @@ long congestion_wait(int rw, long timeout)
}
EXPORT_SYMBOL(congestion_wait);
-/**
- * congestion_end - wake up sleepers on a congested backing_dev_info
- * @rw: READ or WRITE
- */
-void congestion_end(int rw)
-{
- wait_queue_head_t *wqh = &congestion_wqh[rw];
-
- if (waitqueue_active(wqh))
- wake_up(wqh);
-}
-EXPORT_SYMBOL(congestion_end);
diff --git a/mm/bounce.c b/mm/bounce.c
index 3b549bf31f7d..b6d2d0f1019b 100644
--- a/mm/bounce.c
+++ b/mm/bounce.c
@@ -265,6 +265,12 @@ void blk_queue_bounce(struct request_queue *q, struct bio **bio_orig)
mempool_t *pool;
/*
+ * Data-less bio, nothing to bounce
+ */
+ if (bio_empty_barrier(*bio_orig))
+ return;
+
+ /*
* for non-isa bounce case, just check if the bounce pfn is equal
* to or bigger than the highest pfn in the system -- in that case,
* don't waste time iterating over bio segments
diff --git a/mm/filemap.c b/mm/filemap.c
index 15c8413ee929..188cf5fd3e8d 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -25,12 +25,14 @@
#include <linux/uio.h>
#include <linux/hash.h>
#include <linux/writeback.h>
+#include <linux/backing-dev.h>
#include <linux/pagevec.h>
#include <linux/blkdev.h>
+#include <linux/backing-dev.h>
#include <linux/security.h>
#include <linux/syscalls.h>
#include <linux/cpuset.h>
-#include "filemap.h"
+#include <linux/hardirq.h> /* for BUG_ON(!in_atomic()) only */
#include "internal.h"
/*
@@ -63,6 +65,7 @@ generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
* ->private_lock (__free_pte->__set_page_dirty_buffers)
* ->swap_lock (exclusive_swap_page, others)
* ->mapping->tree_lock
+ * ->zone.lock
*
* ->i_mutex
* ->i_mmap_lock (truncate->unmap_mapping_range)
@@ -593,7 +596,7 @@ void fastcall __lock_page_nosync(struct page *page)
* Is there a pagecache struct page at the given (mapping, offset) tuple?
* If yes, increment its refcount and return it; if no, return NULL.
*/
-struct page * find_get_page(struct address_space *mapping, unsigned long offset)
+struct page * find_get_page(struct address_space *mapping, pgoff_t offset)
{
struct page *page;
@@ -617,30 +620,31 @@ EXPORT_SYMBOL(find_get_page);
* Returns zero if the page was not present. find_lock_page() may sleep.
*/
struct page *find_lock_page(struct address_space *mapping,
- unsigned long offset)
+ pgoff_t offset)
{
struct page *page;
- read_lock_irq(&mapping->tree_lock);
repeat:
+ read_lock_irq(&mapping->tree_lock);
page = radix_tree_lookup(&mapping->page_tree, offset);
if (page) {
page_cache_get(page);
if (TestSetPageLocked(page)) {
read_unlock_irq(&mapping->tree_lock);
__lock_page(page);
- read_lock_irq(&mapping->tree_lock);
/* Has the page been truncated while we slept? */
- if (unlikely(page->mapping != mapping ||
- page->index != offset)) {
+ if (unlikely(page->mapping != mapping)) {
unlock_page(page);
page_cache_release(page);
goto repeat;
}
+ VM_BUG_ON(page->index != offset);
+ goto out;
}
}
read_unlock_irq(&mapping->tree_lock);
+out:
return page;
}
EXPORT_SYMBOL(find_lock_page);
@@ -663,29 +667,24 @@ EXPORT_SYMBOL(find_lock_page);
* memory exhaustion.
*/
struct page *find_or_create_page(struct address_space *mapping,
- unsigned long index, gfp_t gfp_mask)
+ pgoff_t index, gfp_t gfp_mask)
{
- struct page *page, *cached_page = NULL;
+ struct page *page;
int err;
repeat:
page = find_lock_page(mapping, index);
if (!page) {
- if (!cached_page) {
- cached_page =
- __page_cache_alloc(gfp_mask);
- if (!cached_page)
- return NULL;
+ page = __page_cache_alloc(gfp_mask);
+ if (!page)
+ return NULL;
+ err = add_to_page_cache_lru(page, mapping, index, gfp_mask);
+ if (unlikely(err)) {
+ page_cache_release(page);
+ page = NULL;
+ if (err == -EEXIST)
+ goto repeat;
}
- err = add_to_page_cache_lru(cached_page, mapping,
- index, gfp_mask);
- if (!err) {
- page = cached_page;
- cached_page = NULL;
- } else if (err == -EEXIST)
- goto repeat;
}
- if (cached_page)
- page_cache_release(cached_page);
return page;
}
EXPORT_SYMBOL(find_or_create_page);
@@ -797,7 +796,7 @@ EXPORT_SYMBOL(find_get_pages_tag);
* and deadlock against the caller's locked page.
*/
struct page *
-grab_cache_page_nowait(struct address_space *mapping, unsigned long index)
+grab_cache_page_nowait(struct address_space *mapping, pgoff_t index)
{
struct page *page = find_get_page(mapping, index);
@@ -843,7 +842,7 @@ static void shrink_readahead_size_eio(struct file *filp,
/**
* do_generic_mapping_read - generic file read routine
* @mapping: address_space to be read
- * @_ra: file's readahead state
+ * @ra: file's readahead state
* @filp: the file to read
* @ppos: current file position
* @desc: read_descriptor
@@ -859,34 +858,29 @@ static void shrink_readahead_size_eio(struct file *filp,
* It may be NULL.
*/
void do_generic_mapping_read(struct address_space *mapping,
- struct file_ra_state *_ra,
+ struct file_ra_state *ra,
struct file *filp,
loff_t *ppos,
read_descriptor_t *desc,
read_actor_t actor)
{
struct inode *inode = mapping->host;
- unsigned long index;
- unsigned long offset;
- unsigned long last_index;
- unsigned long next_index;
- unsigned long prev_index;
+ pgoff_t index;
+ pgoff_t last_index;
+ pgoff_t prev_index;
+ unsigned long offset; /* offset into pagecache page */
unsigned int prev_offset;
- struct page *cached_page;
int error;
- struct file_ra_state ra = *_ra;
- cached_page = NULL;
index = *ppos >> PAGE_CACHE_SHIFT;
- next_index = index;
- prev_index = ra.prev_index;
- prev_offset = ra.prev_offset;
+ prev_index = ra->prev_pos >> PAGE_CACHE_SHIFT;
+ prev_offset = ra->prev_pos & (PAGE_CACHE_SIZE-1);
last_index = (*ppos + desc->count + PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT;
offset = *ppos & ~PAGE_CACHE_MASK;
for (;;) {
struct page *page;
- unsigned long end_index;
+ pgoff_t end_index;
loff_t isize;
unsigned long nr, ret;
@@ -895,7 +889,7 @@ find_page:
page = find_get_page(mapping, index);
if (!page) {
page_cache_sync_readahead(mapping,
- &ra, filp,
+ ra, filp,
index, last_index - index);
page = find_get_page(mapping, index);
if (unlikely(page == NULL))
@@ -903,7 +897,7 @@ find_page:
}
if (PageReadahead(page)) {
page_cache_async_readahead(mapping,
- &ra, filp, page,
+ ra, filp, page,
index, last_index - index);
}
if (!PageUptodate(page))
@@ -966,7 +960,6 @@ page_ok:
index += offset >> PAGE_CACHE_SHIFT;
offset &= ~PAGE_CACHE_MASK;
prev_offset = offset;
- ra.prev_offset = offset;
page_cache_release(page);
if (ret == nr && desc->count)
@@ -1015,7 +1008,7 @@ readpage:
}
unlock_page(page);
error = -EIO;
- shrink_readahead_size_eio(filp, &ra);
+ shrink_readahead_size_eio(filp, ra);
goto readpage_error;
}
unlock_page(page);
@@ -1034,33 +1027,29 @@ no_cached_page:
* Ok, it wasn't cached, so we need to create a new
* page..
*/
- if (!cached_page) {
- cached_page = page_cache_alloc_cold(mapping);
- if (!cached_page) {
- desc->error = -ENOMEM;
- goto out;
- }
+ page = page_cache_alloc_cold(mapping);
+ if (!page) {
+ desc->error = -ENOMEM;
+ goto out;
}
- error = add_to_page_cache_lru(cached_page, mapping,
+ error = add_to_page_cache_lru(page, mapping,
index, GFP_KERNEL);
if (error) {
+ page_cache_release(page);
if (error == -EEXIST)
goto find_page;
desc->error = error;
goto out;
}
- page = cached_page;
- cached_page = NULL;
goto readpage;
}
out:
- *_ra = ra;
- _ra->prev_index = prev_index;
+ ra->prev_pos = prev_index;
+ ra->prev_pos <<= PAGE_CACHE_SHIFT;
+ ra->prev_pos |= prev_offset;
- *ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset;
- if (cached_page)
- page_cache_release(cached_page);
+ *ppos = ((loff_t)index << PAGE_CACHE_SHIFT) + offset;
if (filp)
file_accessed(filp);
}
@@ -1220,7 +1209,7 @@ EXPORT_SYMBOL(generic_file_aio_read);
static ssize_t
do_readahead(struct address_space *mapping, struct file *filp,
- unsigned long index, unsigned long nr)
+ pgoff_t index, unsigned long nr)
{
if (!mapping || !mapping->a_ops || !mapping->a_ops->readpage)
return -EINVAL;
@@ -1240,8 +1229,8 @@ asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count)
if (file) {
if (file->f_mode & FMODE_READ) {
struct address_space *mapping = file->f_mapping;
- unsigned long start = offset >> PAGE_CACHE_SHIFT;
- unsigned long end = (offset + count - 1) >> PAGE_CACHE_SHIFT;
+ pgoff_t start = offset >> PAGE_CACHE_SHIFT;
+ pgoff_t end = (offset + count - 1) >> PAGE_CACHE_SHIFT;
unsigned long len = end - start + 1;
ret = do_readahead(mapping, file, start, len);
}
@@ -1251,7 +1240,6 @@ asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count)
}
#ifdef CONFIG_MMU
-static int FASTCALL(page_cache_read(struct file * file, unsigned long offset));
/**
* page_cache_read - adds requested page to the page cache if not already there
* @file: file to read
@@ -1260,7 +1248,7 @@ static int FASTCALL(page_cache_read(struct file * file, unsigned long offset));
* This adds the requested page to the page cache if it isn't already there,
* and schedules an I/O to read in its contents from disk.
*/
-static int fastcall page_cache_read(struct file * file, unsigned long offset)
+static int fastcall page_cache_read(struct file * file, pgoff_t offset)
{
struct address_space *mapping = file->f_mapping;
struct page *page;
@@ -1312,7 +1300,7 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
if (vmf->pgoff >= size)
- goto outside_data_content;
+ return VM_FAULT_SIGBUS;
/* If we don't want any read-ahead, don't bother */
if (VM_RandomReadHint(vma))
@@ -1349,7 +1337,7 @@ retry_find:
* Do we miss much more than hit in this file? If so,
* stop bothering with read-ahead. It will only hurt.
*/
- if (ra->mmap_miss > ra->mmap_hit + MMAP_LOTSAMISS)
+ if (ra->mmap_miss > MMAP_LOTSAMISS)
goto no_cached_page;
/*
@@ -1375,7 +1363,7 @@ retry_find:
}
if (!did_readaround)
- ra->mmap_hit++;
+ ra->mmap_miss--;
/*
* We have a locked page in the page cache, now we need to check
@@ -1389,26 +1377,17 @@ retry_find:
if (unlikely(vmf->pgoff >= size)) {
unlock_page(page);
page_cache_release(page);
- goto outside_data_content;
+ return VM_FAULT_SIGBUS;
}
/*
* Found the page and have a reference on it.
*/
mark_page_accessed(page);
- ra->prev_index = page->index;
+ ra->prev_pos = (loff_t)page->index << PAGE_CACHE_SHIFT;
vmf->page = page;
return ret | VM_FAULT_LOCKED;
-outside_data_content:
- /*
- * An external ptracer can access pages that normally aren't
- * accessible..
- */
- if (vma->vm_mm == current->mm)
- return VM_FAULT_SIGBUS;
-
- /* Fall through to the non-read-ahead case */
no_cached_page:
/*
* We're only likely to ever get here if MADV_RANDOM is in
@@ -1501,39 +1480,32 @@ EXPORT_SYMBOL(generic_file_mmap);
EXPORT_SYMBOL(generic_file_readonly_mmap);
static struct page *__read_cache_page(struct address_space *mapping,
- unsigned long index,
+ pgoff_t index,
int (*filler)(void *,struct page*),
void *data)
{
- struct page *page, *cached_page = NULL;
+ struct page *page;
int err;
repeat:
page = find_get_page(mapping, index);
if (!page) {
- if (!cached_page) {
- cached_page = page_cache_alloc_cold(mapping);
- if (!cached_page)
- return ERR_PTR(-ENOMEM);
- }
- err = add_to_page_cache_lru(cached_page, mapping,
- index, GFP_KERNEL);
- if (err == -EEXIST)
- goto repeat;
- if (err < 0) {
+ page = page_cache_alloc_cold(mapping);
+ if (!page)
+ return ERR_PTR(-ENOMEM);
+ err = add_to_page_cache_lru(page, mapping, index, GFP_KERNEL);
+ if (unlikely(err)) {
+ page_cache_release(page);
+ if (err == -EEXIST)
+ goto repeat;
/* Presumably ENOMEM for radix tree node */
- page_cache_release(cached_page);
return ERR_PTR(err);
}
- page = cached_page;
- cached_page = NULL;
err = filler(data, page);
if (err < 0) {
page_cache_release(page);
page = ERR_PTR(err);
}
}
- if (cached_page)
- page_cache_release(cached_page);
return page;
}
@@ -1542,7 +1514,7 @@ repeat:
* after submitting it to the filler.
*/
struct page *read_cache_page_async(struct address_space *mapping,
- unsigned long index,
+ pgoff_t index,
int (*filler)(void *,struct page*),
void *data)
{
@@ -1590,7 +1562,7 @@ EXPORT_SYMBOL(read_cache_page_async);
* If the page does not get brought uptodate, return -EIO.
*/
struct page *read_cache_page(struct address_space *mapping,
- unsigned long index,
+ pgoff_t index,
int (*filler)(void *,struct page*),
void *data)
{
@@ -1610,40 +1582,6 @@ struct page *read_cache_page(struct address_space *mapping,
EXPORT_SYMBOL(read_cache_page);
/*
- * If the page was newly created, increment its refcount and add it to the
- * caller's lru-buffering pagevec. This function is specifically for
- * generic_file_write().
- */
-static inline struct page *
-__grab_cache_page(struct address_space *mapping, unsigned long index,
- struct page **cached_page, struct pagevec *lru_pvec)
-{
- int err;
- struct page *page;
-repeat:
- page = find_lock_page(mapping, index);
- if (!page) {
- if (!*cached_page) {
- *cached_page = page_cache_alloc(mapping);
- if (!*cached_page)
- return NULL;
- }
- err = add_to_page_cache(*cached_page, mapping,
- index, GFP_KERNEL);
- if (err == -EEXIST)
- goto repeat;
- if (err == 0) {
- page = *cached_page;
- page_cache_get(page);
- if (!pagevec_add(lru_pvec, page))
- __pagevec_lru_add(lru_pvec);
- *cached_page = NULL;
- }
- }
- return page;
-}
-
-/*
* The logic we want is
*
* if suid or (sgid and xgrp)
@@ -1682,17 +1620,22 @@ int __remove_suid(struct dentry *dentry, int kill)
int remove_suid(struct dentry *dentry)
{
- int kill = should_remove_suid(dentry);
+ int killsuid = should_remove_suid(dentry);
+ int killpriv = security_inode_need_killpriv(dentry);
+ int error = 0;
- if (unlikely(kill))
- return __remove_suid(dentry, kill);
+ if (killpriv < 0)
+ return killpriv;
+ if (killpriv)
+ error = security_inode_killpriv(dentry);
+ if (!error && killsuid)
+ error = __remove_suid(dentry, killsuid);
- return 0;
+ return error;
}
EXPORT_SYMBOL(remove_suid);
-size_t
-__filemap_copy_from_user_iovec_inatomic(char *vaddr,
+static size_t __iovec_copy_from_user_inatomic(char *vaddr,
const struct iovec *iov, size_t base, size_t bytes)
{
size_t copied = 0, left = 0;
@@ -1715,6 +1658,124 @@ __filemap_copy_from_user_iovec_inatomic(char *vaddr,
}
/*
+ * Copy as much as we can into the page and return the number of bytes which
+ * were sucessfully copied. If a fault is encountered then return the number of
+ * bytes which were copied.
+ */
+size_t iov_iter_copy_from_user_atomic(struct page *page,
+ struct iov_iter *i, unsigned long offset, size_t bytes)
+{
+ char *kaddr;
+ size_t copied;
+
+ BUG_ON(!in_atomic());
+ kaddr = kmap_atomic(page, KM_USER0);
+ if (likely(i->nr_segs == 1)) {
+ int left;
+ char __user *buf = i->iov->iov_base + i->iov_offset;
+ left = __copy_from_user_inatomic_nocache(kaddr + offset,
+ buf, bytes);
+ copied = bytes - left;
+ } else {
+ copied = __iovec_copy_from_user_inatomic(kaddr + offset,
+ i->iov, i->iov_offset, bytes);
+ }
+ kunmap_atomic(kaddr, KM_USER0);
+
+ return copied;
+}
+EXPORT_SYMBOL(iov_iter_copy_from_user_atomic);
+
+/*
+ * This has the same sideeffects and return value as
+ * iov_iter_copy_from_user_atomic().
+ * The difference is that it attempts to resolve faults.
+ * Page must not be locked.
+ */
+size_t iov_iter_copy_from_user(struct page *page,
+ struct iov_iter *i, unsigned long offset, size_t bytes)
+{
+ char *kaddr;
+ size_t copied;
+
+ kaddr = kmap(page);
+ if (likely(i->nr_segs == 1)) {
+ int left;
+ char __user *buf = i->iov->iov_base + i->iov_offset;
+ left = __copy_from_user_nocache(kaddr + offset, buf, bytes);
+ copied = bytes - left;
+ } else {
+ copied = __iovec_copy_from_user_inatomic(kaddr + offset,
+ i->iov, i->iov_offset, bytes);
+ }
+ kunmap(page);
+ return copied;
+}
+EXPORT_SYMBOL(iov_iter_copy_from_user);
+
+static void __iov_iter_advance_iov(struct iov_iter *i, size_t bytes)
+{
+ if (likely(i->nr_segs == 1)) {
+ i->iov_offset += bytes;
+ } else {
+ const struct iovec *iov = i->iov;
+ size_t base = i->iov_offset;
+
+ while (bytes) {
+ int copy = min(bytes, iov->iov_len - base);
+
+ bytes -= copy;
+ base += copy;
+ if (iov->iov_len == base) {
+ iov++;
+ base = 0;
+ }
+ }
+ i->iov = iov;
+ i->iov_offset = base;
+ }
+}
+
+void iov_iter_advance(struct iov_iter *i, size_t bytes)
+{
+ BUG_ON(i->count < bytes);
+
+ __iov_iter_advance_iov(i, bytes);
+ i->count -= bytes;
+}
+EXPORT_SYMBOL(iov_iter_advance);
+
+/*
+ * Fault in the first iovec of the given iov_iter, to a maximum length
+ * of bytes. Returns 0 on success, or non-zero if the memory could not be
+ * accessed (ie. because it is an invalid address).
+ *
+ * writev-intensive code may want this to prefault several iovecs -- that
+ * would be possible (callers must not rely on the fact that _only_ the
+ * first iovec will be faulted with the current implementation).
+ */
+int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes)
+{
+ char __user *buf = i->iov->iov_base + i->iov_offset;
+ bytes = min(bytes, i->iov->iov_len - i->iov_offset);
+ return fault_in_pages_readable(buf, bytes);
+}
+EXPORT_SYMBOL(iov_iter_fault_in_readable);
+
+/*
+ * Return the count of just the current iov_iter segment.
+ */
+size_t iov_iter_single_seg_count(struct iov_iter *i)
+{
+ const struct iovec *iov = i->iov;
+ if (i->nr_segs == 1)
+ return i->count;
+ else
+ return min(i->count, iov->iov_len - i->iov_offset);
+}
+EXPORT_SYMBOL(iov_iter_single_seg_count);
+
+/*
* Performs necessary checks before doing a write
*
* Can adjust writing position or amount of bytes to write.
@@ -1796,6 +1857,91 @@ inline int generic_write_checks(struct file *file, loff_t *pos, size_t *count, i
}
EXPORT_SYMBOL(generic_write_checks);
+int pagecache_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
+{
+ const struct address_space_operations *aops = mapping->a_ops;
+
+ if (aops->write_begin) {
+ return aops->write_begin(file, mapping, pos, len, flags,
+ pagep, fsdata);
+ } else {
+ int ret;
+ pgoff_t index = pos >> PAGE_CACHE_SHIFT;
+ unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
+ struct inode *inode = mapping->host;
+ struct page *page;
+again:
+ page = __grab_cache_page(mapping, index);
+ *pagep = page;
+ if (!page)
+ return -ENOMEM;
+
+ if (flags & AOP_FLAG_UNINTERRUPTIBLE && !PageUptodate(page)) {
+ /*
+ * There is no way to resolve a short write situation
+ * for a !Uptodate page (except by double copying in
+ * the caller done by generic_perform_write_2copy).
+ *
+ * Instead, we have to bring it uptodate here.
+ */
+ ret = aops->readpage(file, page);
+ page_cache_release(page);
+ if (ret) {
+ if (ret == AOP_TRUNCATED_PAGE)
+ goto again;
+ return ret;
+ }
+ goto again;
+ }
+
+ ret = aops->prepare_write(file, page, offset, offset+len);
+ if (ret) {
+ unlock_page(page);
+ page_cache_release(page);
+ if (pos + len > inode->i_size)
+ vmtruncate(inode, inode->i_size);
+ }
+ return ret;
+ }
+}
+EXPORT_SYMBOL(pagecache_write_begin);
+
+int pagecache_write_end(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata)
+{
+ const struct address_space_operations *aops = mapping->a_ops;
+ int ret;
+
+ if (aops->write_end) {
+ mark_page_accessed(page);
+ ret = aops->write_end(file, mapping, pos, len, copied,
+ page, fsdata);
+ } else {
+ unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
+ struct inode *inode = mapping->host;
+
+ flush_dcache_page(page);
+ ret = aops->commit_write(file, page, offset, offset+len);
+ unlock_page(page);
+ mark_page_accessed(page);
+ page_cache_release(page);
+
+ if (ret < 0) {
+ if (pos + len > inode->i_size)
+ vmtruncate(inode, inode->i_size);
+ } else if (ret > 0)
+ ret = min_t(size_t, copied, ret);
+ else
+ ret = copied;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(pagecache_write_end);
+
ssize_t
generic_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
unsigned long *nr_segs, loff_t pos, loff_t *ppos,
@@ -1835,151 +1981,314 @@ generic_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
}
EXPORT_SYMBOL(generic_file_direct_write);
-ssize_t
-generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
- unsigned long nr_segs, loff_t pos, loff_t *ppos,
- size_t count, ssize_t written)
+/*
+ * Find or create a page at the given pagecache position. Return the locked
+ * page. This function is specifically for buffered writes.
+ */
+struct page *__grab_cache_page(struct address_space *mapping, pgoff_t index)
{
- struct file *file = iocb->ki_filp;
- struct address_space * mapping = file->f_mapping;
- const struct address_space_operations *a_ops = mapping->a_ops;
- struct inode *inode = mapping->host;
- long status = 0;
- struct page *page;
- struct page *cached_page = NULL;
- size_t bytes;
- struct pagevec lru_pvec;
- const struct iovec *cur_iov = iov; /* current iovec */
- size_t iov_base = 0; /* offset in the current iovec */
- char __user *buf;
-
- pagevec_init(&lru_pvec, 0);
+ int status;
+ struct page *page;
+repeat:
+ page = find_lock_page(mapping, index);
+ if (likely(page))
+ return page;
- /*
- * handle partial DIO write. Adjust cur_iov if needed.
- */
- if (likely(nr_segs == 1))
- buf = iov->iov_base + written;
- else {
- filemap_set_next_iovec(&cur_iov, &iov_base, written);
- buf = cur_iov->iov_base + iov_base;
+ page = page_cache_alloc(mapping);
+ if (!page)
+ return NULL;
+ status = add_to_page_cache_lru(page, mapping, index, GFP_KERNEL);
+ if (unlikely(status)) {
+ page_cache_release(page);
+ if (status == -EEXIST)
+ goto repeat;
+ return NULL;
}
+ return page;
+}
+EXPORT_SYMBOL(__grab_cache_page);
+
+static ssize_t generic_perform_write_2copy(struct file *file,
+ struct iov_iter *i, loff_t pos)
+{
+ struct address_space *mapping = file->f_mapping;
+ const struct address_space_operations *a_ops = mapping->a_ops;
+ struct inode *inode = mapping->host;
+ long status = 0;
+ ssize_t written = 0;
do {
- unsigned long index;
- unsigned long offset;
- size_t copied;
+ struct page *src_page;
+ struct page *page;
+ pgoff_t index; /* Pagecache index for current page */
+ unsigned long offset; /* Offset into pagecache page */
+ unsigned long bytes; /* Bytes to write to page */
+ size_t copied; /* Bytes copied from user */
- offset = (pos & (PAGE_CACHE_SIZE -1)); /* Within page */
+ offset = (pos & (PAGE_CACHE_SIZE - 1));
index = pos >> PAGE_CACHE_SHIFT;
- bytes = PAGE_CACHE_SIZE - offset;
-
- /* Limit the size of the copy to the caller's write size */
- bytes = min(bytes, count);
+ bytes = min_t(unsigned long, PAGE_CACHE_SIZE - offset,
+ iov_iter_count(i));
- /* We only need to worry about prefaulting when writes are from
- * user-space. NFSd uses vfs_writev with several non-aligned
- * segments in the vector, and limiting to one segment a time is
- * a noticeable performance for re-write
+ /*
+ * a non-NULL src_page indicates that we're doing the
+ * copy via get_user_pages and kmap.
*/
- if (!segment_eq(get_fs(), KERNEL_DS)) {
- /*
- * Limit the size of the copy to that of the current
- * segment, because fault_in_pages_readable() doesn't
- * know how to walk segments.
- */
- bytes = min(bytes, cur_iov->iov_len - iov_base);
+ src_page = NULL;
- /*
- * Bring in the user page that we will copy from
- * _first_. Otherwise there's a nasty deadlock on
- * copying from the same page as we're writing to,
- * without it being marked up-to-date.
- */
- fault_in_pages_readable(buf, bytes);
+ /*
+ * Bring in the user page that we will copy from _first_.
+ * Otherwise there's a nasty deadlock on copying from the
+ * same page as we're writing to, without it being marked
+ * up-to-date.
+ *
+ * Not only is this an optimisation, but it is also required
+ * to check that the address is actually valid, when atomic
+ * usercopies are used, below.
+ */
+ if (unlikely(iov_iter_fault_in_readable(i, bytes))) {
+ status = -EFAULT;
+ break;
}
- page = __grab_cache_page(mapping,index,&cached_page,&lru_pvec);
+
+ page = __grab_cache_page(mapping, index);
if (!page) {
status = -ENOMEM;
break;
}
- if (unlikely(bytes == 0)) {
- status = 0;
- copied = 0;
- goto zero_length_segment;
- }
+ /*
+ * non-uptodate pages cannot cope with short copies, and we
+ * cannot take a pagefault with the destination page locked.
+ * So pin the source page to copy it.
+ */
+ if (!PageUptodate(page) && !segment_eq(get_fs(), KERNEL_DS)) {
+ unlock_page(page);
- status = a_ops->prepare_write(file, page, offset, offset+bytes);
- if (unlikely(status)) {
- loff_t isize = i_size_read(inode);
+ src_page = alloc_page(GFP_KERNEL);
+ if (!src_page) {
+ page_cache_release(page);
+ status = -ENOMEM;
+ break;
+ }
- if (status != AOP_TRUNCATED_PAGE)
+ /*
+ * Cannot get_user_pages with a page locked for the
+ * same reason as we can't take a page fault with a
+ * page locked (as explained below).
+ */
+ copied = iov_iter_copy_from_user(src_page, i,
+ offset, bytes);
+ if (unlikely(copied == 0)) {
+ status = -EFAULT;
+ page_cache_release(page);
+ page_cache_release(src_page);
+ break;
+ }
+ bytes = copied;
+
+ lock_page(page);
+ /*
+ * Can't handle the page going uptodate here, because
+ * that means we would use non-atomic usercopies, which
+ * zero out the tail of the page, which can cause
+ * zeroes to become transiently visible. We could just
+ * use a non-zeroing copy, but the APIs aren't too
+ * consistent.
+ */
+ if (unlikely(!page->mapping || PageUptodate(page))) {
unlock_page(page);
- page_cache_release(page);
- if (status == AOP_TRUNCATED_PAGE)
+ page_cache_release(page);
+ page_cache_release(src_page);
continue;
+ }
+ }
+
+ status = a_ops->prepare_write(file, page, offset, offset+bytes);
+ if (unlikely(status))
+ goto fs_write_aop_error;
+
+ if (!src_page) {
/*
- * prepare_write() may have instantiated a few blocks
- * outside i_size. Trim these off again.
+ * Must not enter the pagefault handler here, because
+ * we hold the page lock, so we might recursively
+ * deadlock on the same lock, or get an ABBA deadlock
+ * against a different lock, or against the mmap_sem
+ * (which nests outside the page lock). So increment
+ * preempt count, and use _atomic usercopies.
+ *
+ * The page is uptodate so we are OK to encounter a
+ * short copy: if unmodified parts of the page are
+ * marked dirty and written out to disk, it doesn't
+ * really matter.
*/
- if (pos + bytes > isize)
- vmtruncate(inode, isize);
- break;
+ pagefault_disable();
+ copied = iov_iter_copy_from_user_atomic(page, i,
+ offset, bytes);
+ pagefault_enable();
+ } else {
+ void *src, *dst;
+ src = kmap_atomic(src_page, KM_USER0);
+ dst = kmap_atomic(page, KM_USER1);
+ memcpy(dst + offset, src + offset, bytes);
+ kunmap_atomic(dst, KM_USER1);
+ kunmap_atomic(src, KM_USER0);
+ copied = bytes;
}
- if (likely(nr_segs == 1))
- copied = filemap_copy_from_user(page, offset,
- buf, bytes);
- else
- copied = filemap_copy_from_user_iovec(page, offset,
- cur_iov, iov_base, bytes);
flush_dcache_page(page);
+
status = a_ops->commit_write(file, page, offset, offset+bytes);
- if (status == AOP_TRUNCATED_PAGE) {
- page_cache_release(page);
- continue;
- }
-zero_length_segment:
- if (likely(copied >= 0)) {
- if (!status)
- status = copied;
-
- if (status >= 0) {
- written += status;
- count -= status;
- pos += status;
- buf += status;
- if (unlikely(nr_segs > 1)) {
- filemap_set_next_iovec(&cur_iov,
- &iov_base, status);
- if (count)
- buf = cur_iov->iov_base +
- iov_base;
- } else {
- iov_base += status;
- }
- }
- }
- if (unlikely(copied != bytes))
- if (status >= 0)
- status = -EFAULT;
+ if (unlikely(status < 0))
+ goto fs_write_aop_error;
+ if (unlikely(status > 0)) /* filesystem did partial write */
+ copied = min_t(size_t, copied, status);
+
unlock_page(page);
mark_page_accessed(page);
page_cache_release(page);
- if (status < 0)
- break;
+ if (src_page)
+ page_cache_release(src_page);
+
+ iov_iter_advance(i, copied);
+ pos += copied;
+ written += copied;
+
balance_dirty_pages_ratelimited(mapping);
cond_resched();
- } while (count);
- *ppos = pos;
+ continue;
+
+fs_write_aop_error:
+ unlock_page(page);
+ page_cache_release(page);
+ if (src_page)
+ page_cache_release(src_page);
+
+ /*
+ * prepare_write() may have instantiated a few blocks
+ * outside i_size. Trim these off again. Don't need
+ * i_size_read because we hold i_mutex.
+ */
+ if (pos + bytes > inode->i_size)
+ vmtruncate(inode, inode->i_size);
+ break;
+ } while (iov_iter_count(i));
+
+ return written ? written : status;
+}
- if (cached_page)
- page_cache_release(cached_page);
+static ssize_t generic_perform_write(struct file *file,
+ struct iov_iter *i, loff_t pos)
+{
+ struct address_space *mapping = file->f_mapping;
+ const struct address_space_operations *a_ops = mapping->a_ops;
+ long status = 0;
+ ssize_t written = 0;
+ unsigned int flags = 0;
/*
- * For now, when the user asks for O_SYNC, we'll actually give O_DSYNC
+ * Copies from kernel address space cannot fail (NFSD is a big user).
*/
+ if (segment_eq(get_fs(), KERNEL_DS))
+ flags |= AOP_FLAG_UNINTERRUPTIBLE;
+
+ do {
+ struct page *page;
+ pgoff_t index; /* Pagecache index for current page */
+ unsigned long offset; /* Offset into pagecache page */
+ unsigned long bytes; /* Bytes to write to page */
+ size_t copied; /* Bytes copied from user */
+ void *fsdata;
+
+ offset = (pos & (PAGE_CACHE_SIZE - 1));
+ index = pos >> PAGE_CACHE_SHIFT;
+ bytes = min_t(unsigned long, PAGE_CACHE_SIZE - offset,
+ iov_iter_count(i));
+
+again:
+
+ /*
+ * Bring in the user page that we will copy from _first_.
+ * Otherwise there's a nasty deadlock on copying from the
+ * same page as we're writing to, without it being marked
+ * up-to-date.
+ *
+ * Not only is this an optimisation, but it is also required
+ * to check that the address is actually valid, when atomic
+ * usercopies are used, below.
+ */
+ if (unlikely(iov_iter_fault_in_readable(i, bytes))) {
+ status = -EFAULT;
+ break;
+ }
+
+ status = a_ops->write_begin(file, mapping, pos, bytes, flags,
+ &page, &fsdata);
+ if (unlikely(status))
+ break;
+
+ pagefault_disable();
+ copied = iov_iter_copy_from_user_atomic(page, i, offset, bytes);
+ pagefault_enable();
+ flush_dcache_page(page);
+
+ status = a_ops->write_end(file, mapping, pos, bytes, copied,
+ page, fsdata);
+ if (unlikely(status < 0))
+ break;
+ copied = status;
+
+ cond_resched();
+
+ if (unlikely(copied == 0)) {
+ /*
+ * If we were unable to copy any data at all, we must
+ * fall back to a single segment length write.
+ *
+ * If we didn't fallback here, we could livelock
+ * because not all segments in the iov can be copied at
+ * once without a pagefault.
+ */
+ bytes = min_t(unsigned long, PAGE_CACHE_SIZE - offset,
+ iov_iter_single_seg_count(i));
+ goto again;
+ }
+ iov_iter_advance(i, copied);
+ pos += copied;
+ written += copied;
+
+ balance_dirty_pages_ratelimited(mapping);
+
+ } while (iov_iter_count(i));
+
+ return written ? written : status;
+}
+
+ssize_t
+generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos, loff_t *ppos,
+ size_t count, ssize_t written)
+{
+ struct file *file = iocb->ki_filp;
+ struct address_space *mapping = file->f_mapping;
+ const struct address_space_operations *a_ops = mapping->a_ops;
+ struct inode *inode = mapping->host;
+ ssize_t status;
+ struct iov_iter i;
+
+ iov_iter_init(&i, iov, nr_segs, count, written);
+ if (a_ops->write_begin)
+ status = generic_perform_write(file, &i, pos);
+ else
+ status = generic_perform_write_2copy(file, &i, pos);
+
if (likely(status >= 0)) {
+ written += status;
+ *ppos = pos + status;
+
+ /*
+ * For now, when the user asks for O_SYNC, we'll actually give
+ * O_DSYNC
+ */
if (unlikely((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
if (!a_ops->writepage || !is_sync_kiocb(iocb))
status = generic_osync_inode(inode, mapping,
@@ -1995,7 +2304,6 @@ zero_length_segment:
if (unlikely(file->f_flags & O_DIRECT) && written)
status = filemap_write_and_wait(mapping);
- pagevec_lru_add(&lru_pvec);
return written ? written : status;
}
EXPORT_SYMBOL(generic_file_buffered_write);
@@ -2194,21 +2502,17 @@ generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
}
retval = mapping->a_ops->direct_IO(rw, iocb, iov, offset, nr_segs);
- if (retval)
- goto out;
/*
* Finally, try again to invalidate clean pages which might have been
- * faulted in by get_user_pages() if the source of the write was an
- * mmap()ed region of the file we're writing. That's a pretty crazy
- * thing to do, so we don't support it 100%. If this invalidation
- * fails and we have -EIOCBQUEUED we ignore the failure.
+ * cached by non-direct readahead, or faulted in by get_user_pages()
+ * if the source of the write was an mmap'ed region of the file
+ * we're writing. Either one is a pretty crazy thing to do,
+ * so we don't support it 100%. If this invalidation
+ * fails, tough, the write still worked...
*/
if (rw == WRITE && mapping->nrpages) {
- int err = invalidate_inode_pages2_range(mapping,
- offset >> PAGE_CACHE_SHIFT, end);
- if (err && retval >= 0)
- retval = err;
+ invalidate_inode_pages2_range(mapping, offset >> PAGE_CACHE_SHIFT, end);
}
out:
return retval;
diff --git a/mm/filemap.h b/mm/filemap.h
deleted file mode 100644
index c2bff04c84ed..000000000000
--- a/mm/filemap.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * linux/mm/filemap.h
- *
- * Copyright (C) 1994-1999 Linus Torvalds
- */
-
-#ifndef __FILEMAP_H
-#define __FILEMAP_H
-
-#include <linux/types.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/highmem.h>
-#include <linux/uio.h>
-#include <linux/uaccess.h>
-
-size_t
-__filemap_copy_from_user_iovec_inatomic(char *vaddr,
- const struct iovec *iov,
- size_t base,
- size_t bytes);
-
-/*
- * Copy as much as we can into the page and return the number of bytes which
- * were sucessfully copied. If a fault is encountered then clear the page
- * out to (offset+bytes) and return the number of bytes which were copied.
- *
- * NOTE: For this to work reliably we really want copy_from_user_inatomic_nocache
- * to *NOT* zero any tail of the buffer that it failed to copy. If it does,
- * and if the following non-atomic copy succeeds, then there is a small window
- * where the target page contains neither the data before the write, nor the
- * data after the write (it contains zero). A read at this time will see
- * data that is inconsistent with any ordering of the read and the write.
- * (This has been detected in practice).
- */
-static inline size_t
-filemap_copy_from_user(struct page *page, unsigned long offset,
- const char __user *buf, unsigned bytes)
-{
- char *kaddr;
- int left;
-
- kaddr = kmap_atomic(page, KM_USER0);
- left = __copy_from_user_inatomic_nocache(kaddr + offset, buf, bytes);
- kunmap_atomic(kaddr, KM_USER0);
-
- if (left != 0) {
- /* Do it the slow way */
- kaddr = kmap(page);
- left = __copy_from_user_nocache(kaddr + offset, buf, bytes);
- kunmap(page);
- }
- return bytes - left;
-}
-
-/*
- * This has the same sideeffects and return value as filemap_copy_from_user().
- * The difference is that on a fault we need to memset the remainder of the
- * page (out to offset+bytes), to emulate filemap_copy_from_user()'s
- * single-segment behaviour.
- */
-static inline size_t
-filemap_copy_from_user_iovec(struct page *page, unsigned long offset,
- const struct iovec *iov, size_t base, size_t bytes)
-{
- char *kaddr;
- size_t copied;
-
- kaddr = kmap_atomic(page, KM_USER0);
- copied = __filemap_copy_from_user_iovec_inatomic(kaddr + offset, iov,
- base, bytes);
- kunmap_atomic(kaddr, KM_USER0);
- if (copied != bytes) {
- kaddr = kmap(page);
- copied = __filemap_copy_from_user_iovec_inatomic(kaddr + offset, iov,
- base, bytes);
- if (bytes - copied)
- memset(kaddr + offset + copied, 0, bytes - copied);
- kunmap(page);
- }
- return copied;
-}
-
-static inline void
-filemap_set_next_iovec(const struct iovec **iovp, size_t *basep, size_t bytes)
-{
- const struct iovec *iov = *iovp;
- size_t base = *basep;
-
- do {
- int copy = min(bytes, iov->iov_len - base);
-
- bytes -= copy;
- base += copy;
- if (iov->iov_len == base) {
- iov++;
- base = 0;
- }
- } while (bytes);
- *iovp = iov;
- *basep = base;
-}
-#endif
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c
index 53ee6a299635..32132f3cd641 100644
--- a/mm/filemap_xip.c
+++ b/mm/filemap_xip.c
@@ -15,7 +15,6 @@
#include <linux/rmap.h>
#include <linux/sched.h>
#include <asm/tlbflush.h>
-#include "filemap.h"
/*
* We do use our own empty page to avoid interference with other users
@@ -288,6 +287,7 @@ __xip_file_write(struct file *filp, const char __user *buf,
unsigned long index;
unsigned long offset;
size_t copied;
+ char *kaddr;
offset = (pos & (PAGE_CACHE_SIZE -1)); /* Within page */
index = pos >> PAGE_CACHE_SHIFT;
@@ -295,14 +295,6 @@ __xip_file_write(struct file *filp, const char __user *buf,
if (bytes > count)
bytes = count;
- /*
- * Bring in the user page that we will copy from _first_.
- * Otherwise there's a nasty deadlock on copying from the
- * same page as we're writing to, without it being marked
- * up-to-date.
- */
- fault_in_pages_readable(buf, bytes);
-
page = a_ops->get_xip_page(mapping,
index*(PAGE_SIZE/512), 0);
if (IS_ERR(page) && (PTR_ERR(page) == -ENODATA)) {
@@ -319,8 +311,13 @@ __xip_file_write(struct file *filp, const char __user *buf,
break;
}
- copied = filemap_copy_from_user(page, offset, buf, bytes);
+ fault_in_pages_readable(buf, bytes);
+ kaddr = kmap_atomic(page, KM_USER0);
+ copied = bytes -
+ __copy_from_user_inatomic_nocache(kaddr, buf, bytes);
+ kunmap_atomic(kaddr, KM_USER0);
flush_dcache_page(page);
+
if (likely(copied > 0)) {
status = copied;
diff --git a/mm/fremap.c b/mm/fremap.c
index 95bcb5641c72..14bd3bf7826e 100644
--- a/mm/fremap.c
+++ b/mm/fremap.c
@@ -5,7 +5,7 @@
*
* started by Ingo Molnar, Copyright (C) 2002, 2003
*/
-
+#include <linux/backing-dev.h>
#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/file.h>
@@ -97,26 +97,28 @@ static int populate_range(struct mm_struct *mm, struct vm_area_struct *vma,
}
-/***
- * sys_remap_file_pages - remap arbitrary pages of a shared backing store
- * file within an existing vma.
+/**
+ * sys_remap_file_pages - remap arbitrary pages of an existing VM_SHARED vma
* @start: start of the remapped virtual memory range
* @size: size of the remapped virtual memory range
- * @prot: new protection bits of the range
- * @pgoff: to be mapped page of the backing store file
+ * @prot: new protection bits of the range (see NOTE)
+ * @pgoff: to-be-mapped page of the backing store file
* @flags: 0 or MAP_NONBLOCKED - the later will cause no IO.
*
- * this syscall works purely via pagetables, so it's the most efficient
+ * sys_remap_file_pages remaps arbitrary pages of an existing VM_SHARED vma
+ * (shared backing store file).
+ *
+ * This syscall works purely via pagetables, so it's the most efficient
* way to map the same (large) file into a given virtual window. Unlike
* mmap()/mremap() it does not create any new vmas. The new mappings are
* also safe across swapout.
*
- * NOTE: the 'prot' parameter right now is ignored, and the vma's default
- * protection is used. Arbitrary protections might be implemented in the
- * future.
+ * NOTE: the 'prot' parameter right now is ignored (but must be zero),
+ * and the vma's default protection is used. Arbitrary protections
+ * might be implemented in the future.
*/
asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size,
- unsigned long __prot, unsigned long pgoff, unsigned long flags)
+ unsigned long prot, unsigned long pgoff, unsigned long flags)
{
struct mm_struct *mm = current->mm;
struct address_space *mapping;
@@ -125,7 +127,7 @@ asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size,
int err = -EINVAL;
int has_write_lock = 0;
- if (__prot)
+ if (prot)
return err;
/*
* Sanitize the syscall parameters:
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index eab8c428cc93..6121b57bbe96 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -23,12 +23,16 @@
const unsigned long hugetlb_zero = 0, hugetlb_infinity = ~0UL;
static unsigned long nr_huge_pages, free_huge_pages, resv_huge_pages;
+static unsigned long surplus_huge_pages;
unsigned long max_huge_pages;
static struct list_head hugepage_freelists[MAX_NUMNODES];
static unsigned int nr_huge_pages_node[MAX_NUMNODES];
static unsigned int free_huge_pages_node[MAX_NUMNODES];
+static unsigned int surplus_huge_pages_node[MAX_NUMNODES];
static gfp_t htlb_alloc_mask = GFP_HIGHUSER;
unsigned long hugepages_treat_as_movable;
+int hugetlb_dynamic_pool;
+static int hugetlb_next_nid;
/*
* Protects updates to hugepage_freelists, nr_huge_pages, and free_huge_pages
@@ -85,6 +89,8 @@ static struct page *dequeue_huge_page(struct vm_area_struct *vma,
list_del(&page->lru);
free_huge_pages--;
free_huge_pages_node[nid]--;
+ if (vma && vma->vm_flags & VM_MAYSHARE)
+ resv_huge_pages--;
break;
}
}
@@ -92,73 +98,311 @@ static struct page *dequeue_huge_page(struct vm_area_struct *vma,
return page;
}
+static void update_and_free_page(struct page *page)
+{
+ int i;
+ nr_huge_pages--;
+ nr_huge_pages_node[page_to_nid(page)]--;
+ for (i = 0; i < (HPAGE_SIZE / PAGE_SIZE); i++) {
+ page[i].flags &= ~(1 << PG_locked | 1 << PG_error | 1 << PG_referenced |
+ 1 << PG_dirty | 1 << PG_active | 1 << PG_reserved |
+ 1 << PG_private | 1<< PG_writeback);
+ }
+ set_compound_page_dtor(page, NULL);
+ set_page_refcounted(page);
+ __free_pages(page, HUGETLB_PAGE_ORDER);
+}
+
static void free_huge_page(struct page *page)
{
- BUG_ON(page_count(page));
+ int nid = page_to_nid(page);
+ struct address_space *mapping;
+ mapping = (struct address_space *) page_private(page);
+ BUG_ON(page_count(page));
INIT_LIST_HEAD(&page->lru);
spin_lock(&hugetlb_lock);
- enqueue_huge_page(page);
+ if (surplus_huge_pages_node[nid]) {
+ update_and_free_page(page);
+ surplus_huge_pages--;
+ surplus_huge_pages_node[nid]--;
+ } else {
+ enqueue_huge_page(page);
+ }
spin_unlock(&hugetlb_lock);
+ if (mapping)
+ hugetlb_put_quota(mapping, 1);
+ set_page_private(page, 0);
}
-static int alloc_fresh_huge_page(void)
+/*
+ * Increment or decrement surplus_huge_pages. Keep node-specific counters
+ * balanced by operating on them in a round-robin fashion.
+ * Returns 1 if an adjustment was made.
+ */
+static int adjust_pool_surplus(int delta)
{
static int prev_nid;
- struct page *page;
- int nid;
+ int nid = prev_nid;
+ int ret = 0;
+
+ VM_BUG_ON(delta != -1 && delta != 1);
+ do {
+ nid = next_node(nid, node_online_map);
+ if (nid == MAX_NUMNODES)
+ nid = first_node(node_online_map);
+
+ /* To shrink on this node, there must be a surplus page */
+ if (delta < 0 && !surplus_huge_pages_node[nid])
+ continue;
+ /* Surplus cannot exceed the total number of pages */
+ if (delta > 0 && surplus_huge_pages_node[nid] >=
+ nr_huge_pages_node[nid])
+ continue;
+
+ surplus_huge_pages += delta;
+ surplus_huge_pages_node[nid] += delta;
+ ret = 1;
+ break;
+ } while (nid != prev_nid);
- /*
- * Copy static prev_nid to local nid, work on that, then copy it
- * back to prev_nid afterwards: otherwise there's a window in which
- * a racer might pass invalid nid MAX_NUMNODES to alloc_pages_node.
- * But we don't need to use a spin_lock here: it really doesn't
- * matter if occasionally a racer chooses the same nid as we do.
- */
- nid = next_node(prev_nid, node_online_map);
- if (nid == MAX_NUMNODES)
- nid = first_node(node_online_map);
prev_nid = nid;
+ return ret;
+}
- page = alloc_pages_node(nid, htlb_alloc_mask|__GFP_COMP|__GFP_NOWARN,
- HUGETLB_PAGE_ORDER);
+static struct page *alloc_fresh_huge_page_node(int nid)
+{
+ struct page *page;
+
+ page = alloc_pages_node(nid,
+ htlb_alloc_mask|__GFP_COMP|__GFP_THISNODE|__GFP_NOWARN,
+ HUGETLB_PAGE_ORDER);
if (page) {
set_compound_page_dtor(page, free_huge_page);
spin_lock(&hugetlb_lock);
nr_huge_pages++;
- nr_huge_pages_node[page_to_nid(page)]++;
+ nr_huge_pages_node[nid]++;
spin_unlock(&hugetlb_lock);
put_page(page); /* free it into the hugepage allocator */
- return 1;
}
- return 0;
+
+ return page;
}
-static struct page *alloc_huge_page(struct vm_area_struct *vma,
- unsigned long addr)
+static int alloc_fresh_huge_page(void)
+{
+ struct page *page;
+ int start_nid;
+ int next_nid;
+ int ret = 0;
+
+ start_nid = hugetlb_next_nid;
+
+ do {
+ page = alloc_fresh_huge_page_node(hugetlb_next_nid);
+ if (page)
+ ret = 1;
+ /*
+ * Use a helper variable to find the next node and then
+ * copy it back to hugetlb_next_nid afterwards:
+ * otherwise there's a window in which a racer might
+ * pass invalid nid MAX_NUMNODES to alloc_pages_node.
+ * But we don't need to use a spin_lock here: it really
+ * doesn't matter if occasionally a racer chooses the
+ * same nid as we do. Move nid forward in the mask even
+ * if we just successfully allocated a hugepage so that
+ * the next caller gets hugepages on the next node.
+ */
+ next_nid = next_node(hugetlb_next_nid, node_online_map);
+ if (next_nid == MAX_NUMNODES)
+ next_nid = first_node(node_online_map);
+ hugetlb_next_nid = next_nid;
+ } while (!page && hugetlb_next_nid != start_nid);
+
+ return ret;
+}
+
+static struct page *alloc_buddy_huge_page(struct vm_area_struct *vma,
+ unsigned long address)
{
struct page *page;
+ /* Check if the dynamic pool is enabled */
+ if (!hugetlb_dynamic_pool)
+ return NULL;
+
+ page = alloc_pages(htlb_alloc_mask|__GFP_COMP|__GFP_NOWARN,
+ HUGETLB_PAGE_ORDER);
+ if (page) {
+ set_compound_page_dtor(page, free_huge_page);
+ spin_lock(&hugetlb_lock);
+ nr_huge_pages++;
+ nr_huge_pages_node[page_to_nid(page)]++;
+ surplus_huge_pages++;
+ surplus_huge_pages_node[page_to_nid(page)]++;
+ spin_unlock(&hugetlb_lock);
+ }
+
+ return page;
+}
+
+/*
+ * Increase the hugetlb pool such that it can accomodate a reservation
+ * of size 'delta'.
+ */
+static int gather_surplus_pages(int delta)
+{
+ struct list_head surplus_list;
+ struct page *page, *tmp;
+ int ret, i;
+ int needed, allocated;
+
+ needed = (resv_huge_pages + delta) - free_huge_pages;
+ if (needed <= 0)
+ return 0;
+
+ allocated = 0;
+ INIT_LIST_HEAD(&surplus_list);
+
+ ret = -ENOMEM;
+retry:
+ spin_unlock(&hugetlb_lock);
+ for (i = 0; i < needed; i++) {
+ page = alloc_buddy_huge_page(NULL, 0);
+ if (!page) {
+ /*
+ * We were not able to allocate enough pages to
+ * satisfy the entire reservation so we free what
+ * we've allocated so far.
+ */
+ spin_lock(&hugetlb_lock);
+ needed = 0;
+ goto free;
+ }
+
+ list_add(&page->lru, &surplus_list);
+ }
+ allocated += needed;
+
+ /*
+ * After retaking hugetlb_lock, we need to recalculate 'needed'
+ * because either resv_huge_pages or free_huge_pages may have changed.
+ */
spin_lock(&hugetlb_lock);
- if (vma->vm_flags & VM_MAYSHARE)
- resv_huge_pages--;
- else if (free_huge_pages <= resv_huge_pages)
- goto fail;
+ needed = (resv_huge_pages + delta) - (free_huge_pages + allocated);
+ if (needed > 0)
+ goto retry;
+
+ /*
+ * The surplus_list now contains _at_least_ the number of extra pages
+ * needed to accomodate the reservation. Add the appropriate number
+ * of pages to the hugetlb pool and free the extras back to the buddy
+ * allocator.
+ */
+ needed += allocated;
+ ret = 0;
+free:
+ list_for_each_entry_safe(page, tmp, &surplus_list, lru) {
+ list_del(&page->lru);
+ if ((--needed) >= 0)
+ enqueue_huge_page(page);
+ else {
+ /*
+ * Decrement the refcount and free the page using its
+ * destructor. This must be done with hugetlb_lock
+ * unlocked which is safe because free_huge_page takes
+ * hugetlb_lock before deciding how to free the page.
+ */
+ spin_unlock(&hugetlb_lock);
+ put_page(page);
+ spin_lock(&hugetlb_lock);
+ }
+ }
+
+ return ret;
+}
+
+/*
+ * When releasing a hugetlb pool reservation, any surplus pages that were
+ * allocated to satisfy the reservation must be explicitly freed if they were
+ * never used.
+ */
+static void return_unused_surplus_pages(unsigned long unused_resv_pages)
+{
+ static int nid = -1;
+ struct page *page;
+ unsigned long nr_pages;
+ nr_pages = min(unused_resv_pages, surplus_huge_pages);
+
+ while (nr_pages) {
+ nid = next_node(nid, node_online_map);
+ if (nid == MAX_NUMNODES)
+ nid = first_node(node_online_map);
+
+ if (!surplus_huge_pages_node[nid])
+ continue;
+
+ if (!list_empty(&hugepage_freelists[nid])) {
+ page = list_entry(hugepage_freelists[nid].next,
+ struct page, lru);
+ list_del(&page->lru);
+ update_and_free_page(page);
+ free_huge_pages--;
+ free_huge_pages_node[nid]--;
+ surplus_huge_pages--;
+ surplus_huge_pages_node[nid]--;
+ nr_pages--;
+ }
+ }
+}
+
+
+static struct page *alloc_huge_page_shared(struct vm_area_struct *vma,
+ unsigned long addr)
+{
+ struct page *page;
+
+ spin_lock(&hugetlb_lock);
page = dequeue_huge_page(vma, addr);
- if (!page)
- goto fail;
+ spin_unlock(&hugetlb_lock);
+ return page ? page : ERR_PTR(-VM_FAULT_OOM);
+}
+
+static struct page *alloc_huge_page_private(struct vm_area_struct *vma,
+ unsigned long addr)
+{
+ struct page *page = NULL;
+ if (hugetlb_get_quota(vma->vm_file->f_mapping, 1))
+ return ERR_PTR(-VM_FAULT_SIGBUS);
+
+ spin_lock(&hugetlb_lock);
+ if (free_huge_pages > resv_huge_pages)
+ page = dequeue_huge_page(vma, addr);
spin_unlock(&hugetlb_lock);
- set_page_refcounted(page);
- return page;
+ if (!page)
+ page = alloc_buddy_huge_page(vma, addr);
+ return page ? page : ERR_PTR(-VM_FAULT_OOM);
+}
+
+static struct page *alloc_huge_page(struct vm_area_struct *vma,
+ unsigned long addr)
+{
+ struct page *page;
+ struct address_space *mapping = vma->vm_file->f_mapping;
-fail:
if (vma->vm_flags & VM_MAYSHARE)
- resv_huge_pages++;
- spin_unlock(&hugetlb_lock);
- return NULL;
+ page = alloc_huge_page_shared(vma, addr);
+ else
+ page = alloc_huge_page_private(vma, addr);
+
+ if (!IS_ERR(page)) {
+ set_page_refcounted(page);
+ set_page_private(page, (unsigned long) mapping);
+ }
+ return page;
}
static int __init hugetlb_init(void)
@@ -171,6 +415,8 @@ static int __init hugetlb_init(void)
for (i = 0; i < MAX_NUMNODES; ++i)
INIT_LIST_HEAD(&hugepage_freelists[i]);
+ hugetlb_next_nid = first_node(node_online_map);
+
for (i = 0; i < max_huge_pages; ++i) {
if (!alloc_fresh_huge_page())
break;
@@ -201,21 +447,6 @@ static unsigned int cpuset_mems_nr(unsigned int *array)
}
#ifdef CONFIG_SYSCTL
-static void update_and_free_page(struct page *page)
-{
- int i;
- nr_huge_pages--;
- nr_huge_pages_node[page_to_nid(page)]--;
- for (i = 0; i < (HPAGE_SIZE / PAGE_SIZE); i++) {
- page[i].flags &= ~(1 << PG_locked | 1 << PG_error | 1 << PG_referenced |
- 1 << PG_dirty | 1 << PG_active | 1 << PG_reserved |
- 1 << PG_private | 1<< PG_writeback);
- }
- set_compound_page_dtor(page, NULL);
- set_page_refcounted(page);
- __free_pages(page, HUGETLB_PAGE_ORDER);
-}
-
#ifdef CONFIG_HIGHMEM
static void try_to_free_low(unsigned long count)
{
@@ -224,14 +455,14 @@ static void try_to_free_low(unsigned long count)
for (i = 0; i < MAX_NUMNODES; ++i) {
struct page *page, *next;
list_for_each_entry_safe(page, next, &hugepage_freelists[i], lru) {
+ if (count >= nr_huge_pages)
+ return;
if (PageHighMem(page))
continue;
list_del(&page->lru);
update_and_free_page(page);
free_huge_pages--;
free_huge_pages_node[page_to_nid(page)]--;
- if (count >= nr_huge_pages)
- return;
}
}
}
@@ -241,26 +472,61 @@ static inline void try_to_free_low(unsigned long count)
}
#endif
+#define persistent_huge_pages (nr_huge_pages - surplus_huge_pages)
static unsigned long set_max_huge_pages(unsigned long count)
{
- while (count > nr_huge_pages) {
- if (!alloc_fresh_huge_page())
- return nr_huge_pages;
- }
- if (count >= nr_huge_pages)
- return nr_huge_pages;
+ unsigned long min_count, ret;
+ /*
+ * Increase the pool size
+ * First take pages out of surplus state. Then make up the
+ * remaining difference by allocating fresh huge pages.
+ */
spin_lock(&hugetlb_lock);
- count = max(count, resv_huge_pages);
- try_to_free_low(count);
- while (count < nr_huge_pages) {
+ while (surplus_huge_pages && count > persistent_huge_pages) {
+ if (!adjust_pool_surplus(-1))
+ break;
+ }
+
+ while (count > persistent_huge_pages) {
+ int ret;
+ /*
+ * If this allocation races such that we no longer need the
+ * page, free_huge_page will handle it by freeing the page
+ * and reducing the surplus.
+ */
+ spin_unlock(&hugetlb_lock);
+ ret = alloc_fresh_huge_page();
+ spin_lock(&hugetlb_lock);
+ if (!ret)
+ goto out;
+
+ }
+
+ /*
+ * Decrease the pool size
+ * First return free pages to the buddy allocator (being careful
+ * to keep enough around to satisfy reservations). Then place
+ * pages into surplus state as needed so the pool will shrink
+ * to the desired size as pages become free.
+ */
+ min_count = resv_huge_pages + nr_huge_pages - free_huge_pages;
+ min_count = max(count, min_count);
+ try_to_free_low(min_count);
+ while (min_count < persistent_huge_pages) {
struct page *page = dequeue_huge_page(NULL, 0);
if (!page)
break;
update_and_free_page(page);
}
+ while (count < persistent_huge_pages) {
+ if (!adjust_pool_surplus(1))
+ break;
+ }
+out:
+ ret = persistent_huge_pages;
spin_unlock(&hugetlb_lock);
- return nr_huge_pages;
+ return ret;
}
int hugetlb_sysctl_handler(struct ctl_table *table, int write,
@@ -292,10 +558,12 @@ int hugetlb_report_meminfo(char *buf)
"HugePages_Total: %5lu\n"
"HugePages_Free: %5lu\n"
"HugePages_Rsvd: %5lu\n"
+ "HugePages_Surp: %5lu\n"
"Hugepagesize: %5lu kB\n",
nr_huge_pages,
free_huge_pages,
resv_huge_pages,
+ surplus_huge_pages,
HPAGE_SIZE/1024);
}
@@ -355,7 +623,6 @@ static void set_huge_ptep_writable(struct vm_area_struct *vma,
entry = pte_mkwrite(pte_mkdirty(*ptep));
if (ptep_set_access_flags(vma, address, ptep, entry, 1)) {
update_mmu_cache(vma, address, entry);
- lazy_mmu_prot_update(entry);
}
}
@@ -479,9 +746,9 @@ static int hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma,
page_cache_get(old_page);
new_page = alloc_huge_page(vma, address);
- if (!new_page) {
+ if (IS_ERR(new_page)) {
page_cache_release(old_page);
- return VM_FAULT_OOM;
+ return -PTR_ERR(new_page);
}
spin_unlock(&mm->page_table_lock);
@@ -525,27 +792,28 @@ retry:
size = i_size_read(mapping->host) >> HPAGE_SHIFT;
if (idx >= size)
goto out;
- if (hugetlb_get_quota(mapping))
- goto out;
page = alloc_huge_page(vma, address);
- if (!page) {
- hugetlb_put_quota(mapping);
- ret = VM_FAULT_OOM;
+ if (IS_ERR(page)) {
+ ret = -PTR_ERR(page);
goto out;
}
clear_huge_page(page, address);
if (vma->vm_flags & VM_SHARED) {
int err;
+ struct inode *inode = mapping->host;
err = add_to_page_cache(page, mapping, idx, GFP_KERNEL);
if (err) {
put_page(page);
- hugetlb_put_quota(mapping);
if (err == -EEXIST)
goto retry;
goto out;
}
+
+ spin_lock(&inode->i_lock);
+ inode->i_blocks += BLOCKS_PER_HUGEPAGE;
+ spin_unlock(&inode->i_lock);
} else
lock_page(page);
}
@@ -575,7 +843,6 @@ out:
backout:
spin_unlock(&mm->page_table_lock);
- hugetlb_put_quota(mapping);
unlock_page(page);
put_page(page);
goto out;
@@ -621,7 +888,8 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
struct page **pages, struct vm_area_struct **vmas,
- unsigned long *position, int *length, int i)
+ unsigned long *position, int *length, int i,
+ int write)
{
unsigned long pfn_offset;
unsigned long vaddr = *position;
@@ -643,7 +911,7 @@ int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
int ret;
spin_unlock(&mm->page_table_lock);
- ret = hugetlb_fault(mm, vma, vaddr, 0);
+ ret = hugetlb_fault(mm, vma, vaddr, write);
spin_lock(&mm->page_table_lock);
if (!(ret & VM_FAULT_ERROR))
continue;
@@ -708,7 +976,6 @@ void hugetlb_change_protection(struct vm_area_struct *vma,
pte = huge_ptep_get_and_clear(mm, address, ptep);
pte = pte_mkhuge(pte_modify(pte, newprot));
set_huge_pte_at(mm, address, ptep, pte);
- lazy_mmu_prot_update(pte);
}
}
spin_unlock(&mm->page_table_lock);
@@ -771,10 +1038,10 @@ static long region_chg(struct list_head *head, long f, long t)
/* If we are below the current region then a new region is required.
* Subtle, allocate a new region at the position but make it zero
- * size such that we can guarentee to record the reservation. */
+ * size such that we can guarantee to record the reservation. */
if (&rg->link == head || t < rg->from) {
nrg = kmalloc(sizeof(*nrg), GFP_KERNEL);
- if (nrg == 0)
+ if (!nrg)
return -ENOMEM;
nrg->from = f;
nrg->to = f;
@@ -843,21 +1110,6 @@ static int hugetlb_acct_memory(long delta)
int ret = -ENOMEM;
spin_lock(&hugetlb_lock);
- if ((delta + resv_huge_pages) <= free_huge_pages) {
- resv_huge_pages += delta;
- ret = 0;
- }
- spin_unlock(&hugetlb_lock);
- return ret;
-}
-
-int hugetlb_reserve_pages(struct inode *inode, long from, long to)
-{
- long ret, chg;
-
- chg = region_chg(&inode->i_mapping->private_list, from, to);
- if (chg < 0)
- return chg;
/*
* When cpuset is configured, it breaks the strict hugetlb page
* reservation as the accounting is done on a global variable. Such
@@ -875,9 +1127,34 @@ int hugetlb_reserve_pages(struct inode *inode, long from, long to)
* a best attempt and hopefully to minimize the impact of changing
* semantics that cpuset has.
*/
- if (chg > cpuset_mems_nr(free_huge_pages_node))
- return -ENOMEM;
+ if (delta > 0) {
+ if (gather_surplus_pages(delta) < 0)
+ goto out;
+
+ if (delta > cpuset_mems_nr(free_huge_pages_node))
+ goto out;
+ }
+
+ ret = 0;
+ resv_huge_pages += delta;
+ if (delta < 0)
+ return_unused_surplus_pages((unsigned long) -delta);
+
+out:
+ spin_unlock(&hugetlb_lock);
+ return ret;
+}
+
+int hugetlb_reserve_pages(struct inode *inode, long from, long to)
+{
+ long ret, chg;
+ chg = region_chg(&inode->i_mapping->private_list, from, to);
+ if (chg < 0)
+ return chg;
+
+ if (hugetlb_get_quota(inode->i_mapping, chg))
+ return -ENOSPC;
ret = hugetlb_acct_memory(chg);
if (ret < 0)
return ret;
@@ -888,5 +1165,11 @@ int hugetlb_reserve_pages(struct inode *inode, long from, long to)
void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed)
{
long chg = region_truncate(&inode->i_mapping->private_list, offset);
- hugetlb_acct_memory(freed - chg);
+
+ spin_lock(&inode->i_lock);
+ inode->i_blocks -= BLOCKS_PER_HUGEPAGE * freed;
+ spin_unlock(&inode->i_lock);
+
+ hugetlb_put_quota(inode->i_mapping, (chg - freed));
+ hugetlb_acct_memory(-(chg - freed));
}
diff --git a/mm/internal.h b/mm/internal.h
index a3110c02aea7..953f941ea867 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -37,4 +37,14 @@ static inline void __put_page(struct page *page)
extern void fastcall __init __free_pages_bootmem(struct page *page,
unsigned int order);
+/*
+ * function for dealing with page's order in buddy system.
+ * zone->lock is already acquired when we use these.
+ * So, we don't need atomic page->flags operations here.
+ */
+static inline unsigned long page_order(struct page *page)
+{
+ VM_BUG_ON(!PageBuddy(page));
+ return page_private(page);
+}
#endif
diff --git a/mm/memory.c b/mm/memory.c
index f82b359b2745..4bf0b6d0eb2a 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -259,9 +259,6 @@ void free_pgd_range(struct mmu_gather **tlb,
continue;
free_pud_range(*tlb, pgd, addr, next, floor, ceiling);
} while (pgd++, addr = next, addr != end);
-
- if (!(*tlb)->fullmm)
- flush_tlb_pgtables((*tlb)->mm, start, end);
}
void free_pgtables(struct mmu_gather **tlb, struct vm_area_struct *vma,
@@ -966,7 +963,7 @@ no_page_table:
* has touched so far, we don't want to allocate page tables.
*/
if (flags & FOLL_ANON) {
- page = ZERO_PAGE(address);
+ page = ZERO_PAGE(0);
if (flags & FOLL_GET)
get_page(page);
BUG_ON(flags & FOLL_WRITE);
@@ -1039,7 +1036,7 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
if (is_vm_hugetlb_page(vma)) {
i = follow_hugetlb_page(mm, vma, pages, vmas,
- &start, &len, i);
+ &start, &len, i, write);
continue;
}
@@ -1111,95 +1108,6 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
}
EXPORT_SYMBOL(get_user_pages);
-static int zeromap_pte_range(struct mm_struct *mm, pmd_t *pmd,
- unsigned long addr, unsigned long end, pgprot_t prot)
-{
- pte_t *pte;
- spinlock_t *ptl;
- int err = 0;
-
- pte = pte_alloc_map_lock(mm, pmd, addr, &ptl);
- if (!pte)
- return -EAGAIN;
- arch_enter_lazy_mmu_mode();
- do {
- struct page *page = ZERO_PAGE(addr);
- pte_t zero_pte = pte_wrprotect(mk_pte(page, prot));
-
- if (unlikely(!pte_none(*pte))) {
- err = -EEXIST;
- pte++;
- break;
- }
- page_cache_get(page);
- page_add_file_rmap(page);
- inc_mm_counter(mm, file_rss);
- set_pte_at(mm, addr, pte, zero_pte);
- } while (pte++, addr += PAGE_SIZE, addr != end);
- arch_leave_lazy_mmu_mode();
- pte_unmap_unlock(pte - 1, ptl);
- return err;
-}
-
-static inline int zeromap_pmd_range(struct mm_struct *mm, pud_t *pud,
- unsigned long addr, unsigned long end, pgprot_t prot)
-{
- pmd_t *pmd;
- unsigned long next;
- int err;
-
- pmd = pmd_alloc(mm, pud, addr);
- if (!pmd)
- return -EAGAIN;
- do {
- next = pmd_addr_end(addr, end);
- err = zeromap_pte_range(mm, pmd, addr, next, prot);
- if (err)
- break;
- } while (pmd++, addr = next, addr != end);
- return err;
-}
-
-static inline int zeromap_pud_range(struct mm_struct *mm, pgd_t *pgd,
- unsigned long addr, unsigned long end, pgprot_t prot)
-{
- pud_t *pud;
- unsigned long next;
- int err;
-
- pud = pud_alloc(mm, pgd, addr);
- if (!pud)
- return -EAGAIN;
- do {
- next = pud_addr_end(addr, end);
- err = zeromap_pmd_range(mm, pud, addr, next, prot);
- if (err)
- break;
- } while (pud++, addr = next, addr != end);
- return err;
-}
-
-int zeromap_page_range(struct vm_area_struct *vma,
- unsigned long addr, unsigned long size, pgprot_t prot)
-{
- pgd_t *pgd;
- unsigned long next;
- unsigned long end = addr + size;
- struct mm_struct *mm = vma->vm_mm;
- int err;
-
- BUG_ON(addr >= end);
- pgd = pgd_offset(mm, addr);
- flush_cache_range(vma, addr, end);
- do {
- next = pgd_addr_end(addr, end);
- err = zeromap_pud_range(mm, pgd, addr, next, prot);
- if (err)
- break;
- } while (pgd++, addr = next, addr != end);
- return err;
-}
-
pte_t * fastcall get_locked_pte(struct mm_struct *mm, unsigned long addr, spinlock_t **ptl)
{
pgd_t * pgd = pgd_offset(mm, addr);
@@ -1700,10 +1608,8 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
flush_cache_page(vma, address, pte_pfn(orig_pte));
entry = pte_mkyoung(orig_pte);
entry = maybe_mkwrite(pte_mkdirty(entry), vma);
- if (ptep_set_access_flags(vma, address, page_table, entry,1)) {
+ if (ptep_set_access_flags(vma, address, page_table, entry,1))
update_mmu_cache(vma, address, entry);
- lazy_mmu_prot_update(entry);
- }
ret |= VM_FAULT_WRITE;
goto unlock;
}
@@ -1717,16 +1623,11 @@ gotten:
if (unlikely(anon_vma_prepare(vma)))
goto oom;
- if (old_page == ZERO_PAGE(address)) {
- new_page = alloc_zeroed_user_highpage_movable(vma, address);
- if (!new_page)
- goto oom;
- } else {
- new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address);
- if (!new_page)
- goto oom;
- cow_user_page(new_page, old_page, address, vma);
- }
+ VM_BUG_ON(old_page == ZERO_PAGE(0));
+ new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address);
+ if (!new_page)
+ goto oom;
+ cow_user_page(new_page, old_page, address, vma);
/*
* Re-check the pte - we dropped the lock
@@ -1744,7 +1645,6 @@ gotten:
flush_cache_page(vma, address, pte_pfn(orig_pte));
entry = mk_pte(new_page, vma->vm_page_prot);
entry = maybe_mkwrite(pte_mkdirty(entry), vma);
- lazy_mmu_prot_update(entry);
/*
* Clear the pte entry and flush it first, before updating the
* pte with the new entry. This will avoid a race condition
@@ -2184,9 +2084,9 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,
count_vm_event(PGMAJFAULT);
}
- delayacct_clear_flag(DELAYACCT_PF_SWAPIN);
mark_page_accessed(page);
lock_page(page);
+ delayacct_clear_flag(DELAYACCT_PF_SWAPIN);
/*
* Back out if somebody else already faulted in this pte.
@@ -2252,44 +2152,28 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
spinlock_t *ptl;
pte_t entry;
- if (write_access) {
- /* Allocate our own private page. */
- pte_unmap(page_table);
-
- if (unlikely(anon_vma_prepare(vma)))
- goto oom;
- page = alloc_zeroed_user_highpage_movable(vma, address);
- if (!page)
- goto oom;
-
- entry = mk_pte(page, vma->vm_page_prot);
- entry = maybe_mkwrite(pte_mkdirty(entry), vma);
+ /* Allocate our own private page. */
+ pte_unmap(page_table);
- page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
- if (!pte_none(*page_table))
- goto release;
- inc_mm_counter(mm, anon_rss);
- lru_cache_add_active(page);
- page_add_new_anon_rmap(page, vma, address);
- } else {
- /* Map the ZERO_PAGE - vm_page_prot is readonly */
- page = ZERO_PAGE(address);
- page_cache_get(page);
- entry = mk_pte(page, vma->vm_page_prot);
+ if (unlikely(anon_vma_prepare(vma)))
+ goto oom;
+ page = alloc_zeroed_user_highpage_movable(vma, address);
+ if (!page)
+ goto oom;
- ptl = pte_lockptr(mm, pmd);
- spin_lock(ptl);
- if (!pte_none(*page_table))
- goto release;
- inc_mm_counter(mm, file_rss);
- page_add_file_rmap(page);
- }
+ entry = mk_pte(page, vma->vm_page_prot);
+ entry = maybe_mkwrite(pte_mkdirty(entry), vma);
+ page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
+ if (!pte_none(*page_table))
+ goto release;
+ inc_mm_counter(mm, anon_rss);
+ lru_cache_add_active(page);
+ page_add_new_anon_rmap(page, vma, address);
set_pte_at(mm, address, page_table, entry);
/* No need to invalidate - it was non-present before */
update_mmu_cache(vma, address, entry);
- lazy_mmu_prot_update(entry);
unlock:
pte_unmap_unlock(page_table, ptl);
return 0;
@@ -2442,7 +2326,6 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
/* no need to invalidate: a not-present page won't be cached */
update_mmu_cache(vma, address, entry);
- lazy_mmu_prot_update(entry);
} else {
if (anon)
page_cache_release(page);
@@ -2470,7 +2353,7 @@ static int do_linear_fault(struct mm_struct *mm, struct vm_area_struct *vma,
int write_access, pte_t orig_pte)
{
pgoff_t pgoff = (((address & PAGE_MASK)
- - vma->vm_start) >> PAGE_CACHE_SHIFT) + vma->vm_pgoff;
+ - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
unsigned int flags = (write_access ? FAULT_FLAG_WRITE : 0);
pte_unmap(page_table);
@@ -2614,7 +2497,6 @@ static inline int handle_pte_fault(struct mm_struct *mm,
entry = pte_mkyoung(entry);
if (ptep_set_access_flags(vma, address, pte, entry, write_access)) {
update_mmu_cache(vma, address, entry);
- lazy_mmu_prot_update(entry);
} else {
/*
* This is needed only for protection faults but the arch code
@@ -2831,7 +2713,7 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in
return 0;
down_read(&mm->mmap_sem);
- /* ignore errors, just check how much was sucessfully transfered */
+ /* ignore errors, just check how much was successfully transferred */
while (len) {
int bytes, ret, offset;
void *maddr;
@@ -2866,4 +2748,3 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in
return buf - old_buf;
}
-EXPORT_SYMBOL_GPL(access_process_vm);
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index df9d554bea30..9512a544d044 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -23,6 +23,9 @@
#include <linux/vmalloc.h>
#include <linux/ioport.h>
#include <linux/cpuset.h>
+#include <linux/delay.h>
+#include <linux/migrate.h>
+#include <linux/page-isolation.h>
#include <asm/tlbflush.h>
@@ -36,7 +39,7 @@ static struct resource *register_memory_resource(u64 start, u64 size)
res->name = "System RAM";
res->start = start;
res->end = start + size - 1;
- res->flags = IORESOURCE_MEM;
+ res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
if (request_resource(&iomem_resource, res) < 0) {
printk("System RAM resource %llx - %llx cannot be added\n",
(unsigned long long)res->start, (unsigned long long)res->end);
@@ -118,7 +121,7 @@ int __add_pages(struct zone *zone, unsigned long phys_start_pfn,
err = __add_section(zone, i << PFN_SECTION_SHIFT);
/*
- * EEXIST is finally dealed with by ioresource collision
+ * EEXIST is finally dealt with by ioresource collision
* check. see add_memory() => register_memory_resource()
* Warning will be printed if there is collision.
*/
@@ -161,17 +164,47 @@ static void grow_pgdat_span(struct pglist_data *pgdat,
pgdat->node_start_pfn;
}
-int online_pages(unsigned long pfn, unsigned long nr_pages)
+static int online_pages_range(unsigned long start_pfn, unsigned long nr_pages,
+ void *arg)
{
unsigned long i;
+ unsigned long onlined_pages = *(unsigned long *)arg;
+ struct page *page;
+ if (PageReserved(pfn_to_page(start_pfn)))
+ for (i = 0; i < nr_pages; i++) {
+ page = pfn_to_page(start_pfn + i);
+ online_page(page);
+ onlined_pages++;
+ }
+ *(unsigned long *)arg = onlined_pages;
+ return 0;
+}
+
+
+int online_pages(unsigned long pfn, unsigned long nr_pages)
+{
unsigned long flags;
unsigned long onlined_pages = 0;
- struct resource res;
- u64 section_end;
- unsigned long start_pfn;
struct zone *zone;
int need_zonelists_rebuild = 0;
+ int nid;
+ int ret;
+ struct memory_notify arg;
+ arg.start_pfn = pfn;
+ arg.nr_pages = nr_pages;
+ arg.status_change_nid = -1;
+
+ nid = page_to_nid(pfn_to_page(pfn));
+ if (node_present_pages(nid) == 0)
+ arg.status_change_nid = nid;
+
+ ret = memory_notify(MEM_GOING_ONLINE, &arg);
+ ret = notifier_to_errno(ret);
+ if (ret) {
+ memory_notify(MEM_CANCEL_ONLINE, &arg);
+ return ret;
+ }
/*
* This doesn't need a lock to do pfn_to_page().
* The section can't be removed here because of the
@@ -191,37 +224,25 @@ int online_pages(unsigned long pfn, unsigned long nr_pages)
if (!populated_zone(zone))
need_zonelists_rebuild = 1;
- res.start = (u64)pfn << PAGE_SHIFT;
- res.end = res.start + ((u64)nr_pages << PAGE_SHIFT) - 1;
- res.flags = IORESOURCE_MEM; /* we just need system ram */
- section_end = res.end;
-
- while ((res.start < res.end) && (find_next_system_ram(&res) >= 0)) {
- start_pfn = (unsigned long)(res.start >> PAGE_SHIFT);
- nr_pages = (unsigned long)
- ((res.end + 1 - res.start) >> PAGE_SHIFT);
-
- if (PageReserved(pfn_to_page(start_pfn))) {
- /* this region's page is not onlined now */
- for (i = 0; i < nr_pages; i++) {
- struct page *page = pfn_to_page(start_pfn + i);
- online_page(page);
- onlined_pages++;
- }
- }
-
- res.start = res.end + 1;
- res.end = section_end;
- }
+ walk_memory_resource(pfn, nr_pages, &onlined_pages,
+ online_pages_range);
zone->present_pages += onlined_pages;
zone->zone_pgdat->node_present_pages += onlined_pages;
setup_per_zone_pages_min();
+ if (onlined_pages) {
+ kswapd_run(zone_to_nid(zone));
+ node_set_state(zone_to_nid(zone), N_HIGH_MEMORY);
+ }
if (need_zonelists_rebuild)
build_all_zonelists();
vm_total_pages = nr_free_pagecache_pages();
writeback_set_ratelimit();
+
+ if (onlined_pages)
+ memory_notify(MEM_ONLINE, &arg);
+
return 0;
}
#endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */
@@ -271,9 +292,6 @@ int add_memory(int nid, u64 start, u64 size)
if (!pgdat)
return -ENOMEM;
new_pgdat = 1;
- ret = kswapd_run(nid);
- if (ret)
- goto error;
}
/* call arch's memory hotadd */
@@ -308,3 +326,281 @@ error:
return ret;
}
EXPORT_SYMBOL_GPL(add_memory);
+
+#ifdef CONFIG_MEMORY_HOTREMOVE
+/*
+ * Confirm all pages in a range [start, end) is belongs to the same zone.
+ */
+static int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn)
+{
+ unsigned long pfn;
+ struct zone *zone = NULL;
+ struct page *page;
+ int i;
+ for (pfn = start_pfn;
+ pfn < end_pfn;
+ pfn += MAX_ORDER_NR_PAGES) {
+ i = 0;
+ /* This is just a CONFIG_HOLES_IN_ZONE check.*/
+ while ((i < MAX_ORDER_NR_PAGES) && !pfn_valid_within(pfn + i))
+ i++;
+ if (i == MAX_ORDER_NR_PAGES)
+ continue;
+ page = pfn_to_page(pfn + i);
+ if (zone && page_zone(page) != zone)
+ return 0;
+ zone = page_zone(page);
+ }
+ return 1;
+}
+
+/*
+ * Scanning pfn is much easier than scanning lru list.
+ * Scan pfn from start to end and Find LRU page.
+ */
+int scan_lru_pages(unsigned long start, unsigned long end)
+{
+ unsigned long pfn;
+ struct page *page;
+ for (pfn = start; pfn < end; pfn++) {
+ if (pfn_valid(pfn)) {
+ page = pfn_to_page(pfn);
+ if (PageLRU(page))
+ return pfn;
+ }
+ }
+ return 0;
+}
+
+static struct page *
+hotremove_migrate_alloc(struct page *page,
+ unsigned long private,
+ int **x)
+{
+ /* This should be improoooooved!! */
+ return alloc_page(GFP_HIGHUSER_PAGECACHE);
+}
+
+
+#define NR_OFFLINE_AT_ONCE_PAGES (256)
+static int
+do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
+{
+ unsigned long pfn;
+ struct page *page;
+ int move_pages = NR_OFFLINE_AT_ONCE_PAGES;
+ int not_managed = 0;
+ int ret = 0;
+ LIST_HEAD(source);
+
+ for (pfn = start_pfn; pfn < end_pfn && move_pages > 0; pfn++) {
+ if (!pfn_valid(pfn))
+ continue;
+ page = pfn_to_page(pfn);
+ if (!page_count(page))
+ continue;
+ /*
+ * We can skip free pages. And we can only deal with pages on
+ * LRU.
+ */
+ ret = isolate_lru_page(page, &source);
+ if (!ret) { /* Success */
+ move_pages--;
+ } else {
+ /* Becasue we don't have big zone->lock. we should
+ check this again here. */
+ if (page_count(page))
+ not_managed++;
+#ifdef CONFIG_DEBUG_VM
+ printk(KERN_INFO "removing from LRU failed"
+ " %lx/%d/%lx\n",
+ pfn, page_count(page), page->flags);
+#endif
+ }
+ }
+ ret = -EBUSY;
+ if (not_managed) {
+ if (!list_empty(&source))
+ putback_lru_pages(&source);
+ goto out;
+ }
+ ret = 0;
+ if (list_empty(&source))
+ goto out;
+ /* this function returns # of failed pages */
+ ret = migrate_pages(&source, hotremove_migrate_alloc, 0);
+
+out:
+ return ret;
+}
+
+/*
+ * remove from free_area[] and mark all as Reserved.
+ */
+static int
+offline_isolated_pages_cb(unsigned long start, unsigned long nr_pages,
+ void *data)
+{
+ __offline_isolated_pages(start, start + nr_pages);
+ return 0;
+}
+
+static void
+offline_isolated_pages(unsigned long start_pfn, unsigned long end_pfn)
+{
+ walk_memory_resource(start_pfn, end_pfn - start_pfn, NULL,
+ offline_isolated_pages_cb);
+}
+
+/*
+ * Check all pages in range, recoreded as memory resource, are isolated.
+ */
+static int
+check_pages_isolated_cb(unsigned long start_pfn, unsigned long nr_pages,
+ void *data)
+{
+ int ret;
+ long offlined = *(long *)data;
+ ret = test_pages_isolated(start_pfn, start_pfn + nr_pages);
+ offlined = nr_pages;
+ if (!ret)
+ *(long *)data += offlined;
+ return ret;
+}
+
+static long
+check_pages_isolated(unsigned long start_pfn, unsigned long end_pfn)
+{
+ long offlined = 0;
+ int ret;
+
+ ret = walk_memory_resource(start_pfn, end_pfn - start_pfn, &offlined,
+ check_pages_isolated_cb);
+ if (ret < 0)
+ offlined = (long)ret;
+ return offlined;
+}
+
+extern void drain_all_local_pages(void);
+
+int offline_pages(unsigned long start_pfn,
+ unsigned long end_pfn, unsigned long timeout)
+{
+ unsigned long pfn, nr_pages, expire;
+ long offlined_pages;
+ int ret, drain, retry_max, node;
+ struct zone *zone;
+ struct memory_notify arg;
+
+ BUG_ON(start_pfn >= end_pfn);
+ /* at least, alignment against pageblock is necessary */
+ if (!IS_ALIGNED(start_pfn, pageblock_nr_pages))
+ return -EINVAL;
+ if (!IS_ALIGNED(end_pfn, pageblock_nr_pages))
+ return -EINVAL;
+ /* This makes hotplug much easier...and readable.
+ we assume this for now. .*/
+ if (!test_pages_in_a_zone(start_pfn, end_pfn))
+ return -EINVAL;
+
+ zone = page_zone(pfn_to_page(start_pfn));
+ node = zone_to_nid(zone);
+ nr_pages = end_pfn - start_pfn;
+
+ /* set above range as isolated */
+ ret = start_isolate_page_range(start_pfn, end_pfn);
+ if (ret)
+ return ret;
+
+ arg.start_pfn = start_pfn;
+ arg.nr_pages = nr_pages;
+ arg.status_change_nid = -1;
+ if (nr_pages >= node_present_pages(node))
+ arg.status_change_nid = node;
+
+ ret = memory_notify(MEM_GOING_OFFLINE, &arg);
+ ret = notifier_to_errno(ret);
+ if (ret)
+ goto failed_removal;
+
+ pfn = start_pfn;
+ expire = jiffies + timeout;
+ drain = 0;
+ retry_max = 5;
+repeat:
+ /* start memory hot removal */
+ ret = -EAGAIN;
+ if (time_after(jiffies, expire))
+ goto failed_removal;
+ ret = -EINTR;
+ if (signal_pending(current))
+ goto failed_removal;
+ ret = 0;
+ if (drain) {
+ lru_add_drain_all();
+ flush_scheduled_work();
+ cond_resched();
+ drain_all_local_pages();
+ }
+
+ pfn = scan_lru_pages(start_pfn, end_pfn);
+ if (pfn) { /* We have page on LRU */
+ ret = do_migrate_range(pfn, end_pfn);
+ if (!ret) {
+ drain = 1;
+ goto repeat;
+ } else {
+ if (ret < 0)
+ if (--retry_max == 0)
+ goto failed_removal;
+ yield();
+ drain = 1;
+ goto repeat;
+ }
+ }
+ /* drain all zone's lru pagevec, this is asyncronous... */
+ lru_add_drain_all();
+ flush_scheduled_work();
+ yield();
+ /* drain pcp pages , this is synchrouns. */
+ drain_all_local_pages();
+ /* check again */
+ offlined_pages = check_pages_isolated(start_pfn, end_pfn);
+ if (offlined_pages < 0) {
+ ret = -EBUSY;
+ goto failed_removal;
+ }
+ printk(KERN_INFO "Offlined Pages %ld\n", offlined_pages);
+ /* Ok, all of our target is islaoted.
+ We cannot do rollback at this point. */
+ offline_isolated_pages(start_pfn, end_pfn);
+ /* reset pagetype flags and makes migrate type to be MOVABLE */
+ undo_isolate_page_range(start_pfn, end_pfn);
+ /* removal success */
+ zone->present_pages -= offlined_pages;
+ zone->zone_pgdat->node_present_pages -= offlined_pages;
+ totalram_pages -= offlined_pages;
+ num_physpages -= offlined_pages;
+
+ vm_total_pages = nr_free_pagecache_pages();
+ writeback_set_ratelimit();
+
+ memory_notify(MEM_OFFLINE, &arg);
+ return 0;
+
+failed_removal:
+ printk(KERN_INFO "memory offlining %lx to %lx failed\n",
+ start_pfn, end_pfn);
+ memory_notify(MEM_CANCEL_OFFLINE, &arg);
+ /* pushback to free area */
+ undo_isolate_page_range(start_pfn, end_pfn);
+
+ return ret;
+}
+#else
+int remove_memory(u64 start, u64 size)
+{
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(remove_memory);
+#endif /* CONFIG_MEMORY_HOTREMOVE */
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 3d6ac9505d07..83c69f8a64c2 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -72,23 +72,23 @@
#include <linux/hugetlb.h>
#include <linux/kernel.h>
#include <linux/sched.h>
-#include <linux/mm.h>
#include <linux/nodemask.h>
#include <linux/cpuset.h>
#include <linux/gfp.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/module.h>
+#include <linux/nsproxy.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/compat.h>
-#include <linux/mempolicy.h>
#include <linux/swap.h>
#include <linux/seq_file.h>
#include <linux/proc_fs.h>
#include <linux/migrate.h>
#include <linux/rmap.h>
#include <linux/security.h>
+#include <linux/syscalls.h>
#include <asm/tlbflush.h>
#include <asm/uaccess.h>
@@ -110,6 +110,9 @@ struct mempolicy default_policy = {
.policy = MPOL_DEFAULT,
};
+static void mpol_rebind_policy(struct mempolicy *pol,
+ const nodemask_t *newmask);
+
/* Do sanity checking on a policy */
static int mpol_check_policy(int mode, nodemask_t *nodes)
{
@@ -128,7 +131,7 @@ static int mpol_check_policy(int mode, nodemask_t *nodes)
return -EINVAL;
break;
}
- return nodes_subset(*nodes, node_online_map) ? 0 : -EINVAL;
+ return nodes_subset(*nodes, node_states[N_HIGH_MEMORY]) ? 0 : -EINVAL;
}
/* Generate a custom zonelist for the BIND policy. */
@@ -185,7 +188,9 @@ static struct mempolicy *mpol_new(int mode, nodemask_t *nodes)
switch (mode) {
case MPOL_INTERLEAVE:
policy->v.nodes = *nodes;
- if (nodes_weight(*nodes) == 0) {
+ nodes_and(policy->v.nodes, policy->v.nodes,
+ node_states[N_HIGH_MEMORY]);
+ if (nodes_weight(policy->v.nodes) == 0) {
kmem_cache_free(policy_cache, policy);
return ERR_PTR(-EINVAL);
}
@@ -459,7 +464,7 @@ static void mpol_set_task_struct_flag(void)
}
/* Set the process memory policy */
-long do_set_mempolicy(int mode, nodemask_t *nodes)
+static long do_set_mempolicy(int mode, nodemask_t *nodes)
{
struct mempolicy *new;
@@ -494,9 +499,9 @@ static void get_zonemask(struct mempolicy *p, nodemask_t *nodes)
*nodes = p->v.nodes;
break;
case MPOL_PREFERRED:
- /* or use current node instead of online map? */
+ /* or use current node instead of memory_map? */
if (p->v.preferred_node < 0)
- *nodes = node_online_map;
+ *nodes = node_states[N_HIGH_MEMORY];
else
node_set(p->v.preferred_node, *nodes);
break;
@@ -519,8 +524,8 @@ static int lookup_node(struct mm_struct *mm, unsigned long addr)
}
/* Retrieve NUMA policy */
-long do_get_mempolicy(int *policy, nodemask_t *nmask,
- unsigned long addr, unsigned long flags)
+static long do_get_mempolicy(int *policy, nodemask_t *nmask,
+ unsigned long addr, unsigned long flags)
{
int err;
struct mm_struct *mm = current->mm;
@@ -528,8 +533,18 @@ long do_get_mempolicy(int *policy, nodemask_t *nmask,
struct mempolicy *pol = current->mempolicy;
cpuset_update_task_memory_state();
- if (flags & ~(unsigned long)(MPOL_F_NODE|MPOL_F_ADDR))
+ if (flags &
+ ~(unsigned long)(MPOL_F_NODE|MPOL_F_ADDR|MPOL_F_MEMS_ALLOWED))
return -EINVAL;
+
+ if (flags & MPOL_F_MEMS_ALLOWED) {
+ if (flags & (MPOL_F_NODE|MPOL_F_ADDR))
+ return -EINVAL;
+ *policy = 0; /* just so it's initialized */
+ *nmask = cpuset_current_mems_allowed;
+ return 0;
+ }
+
if (flags & MPOL_F_ADDR) {
down_read(&mm->mmap_sem);
vma = find_vma_intersection(mm, addr, addr+1);
@@ -601,7 +616,8 @@ static struct page *new_node_page(struct page *page, unsigned long node, int **x
* Migrate pages from one node to a target node.
* Returns error or the number of pages not migrated.
*/
-int migrate_to_node(struct mm_struct *mm, int source, int dest, int flags)
+static int migrate_to_node(struct mm_struct *mm, int source, int dest,
+ int flags)
{
nodemask_t nmask;
LIST_HEAD(pagelist);
@@ -706,12 +722,29 @@ out:
}
+/*
+ * Allocate a new page for page migration based on vma policy.
+ * Start assuming that page is mapped by vma pointed to by @private.
+ * Search forward from there, if not. N.B., this assumes that the
+ * list of pages handed to migrate_pages()--which is how we get here--
+ * is in virtual address order.
+ */
static struct page *new_vma_page(struct page *page, unsigned long private, int **x)
{
struct vm_area_struct *vma = (struct vm_area_struct *)private;
+ unsigned long uninitialized_var(address);
+
+ while (vma) {
+ address = page_address_in_vma(page, vma);
+ if (address != -EFAULT)
+ break;
+ vma = vma->vm_next;
+ }
- return alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma,
- page_address_in_vma(page, vma));
+ /*
+ * if !vma, alloc_page_vma() will use task or system default policy
+ */
+ return alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address);
}
#else
@@ -732,8 +765,9 @@ static struct page *new_vma_page(struct page *page, unsigned long private, int *
}
#endif
-long do_mbind(unsigned long start, unsigned long len,
- unsigned long mode, nodemask_t *nmask, unsigned long flags)
+static long do_mbind(unsigned long start, unsigned long len,
+ unsigned long mode, nodemask_t *nmask,
+ unsigned long flags)
{
struct vm_area_struct *vma;
struct mm_struct *mm = current->mm;
@@ -924,7 +958,7 @@ asmlinkage long sys_migrate_pages(pid_t pid, unsigned long maxnode,
/* Find the mm_struct */
read_lock(&tasklist_lock);
- task = pid ? find_task_by_pid(pid) : current;
+ task = pid ? find_task_by_vpid(pid) : current;
if (!task) {
read_unlock(&tasklist_lock);
return -ESRCH;
@@ -955,7 +989,7 @@ asmlinkage long sys_migrate_pages(pid_t pid, unsigned long maxnode,
goto out;
}
- if (!nodes_subset(new, node_online_map)) {
+ if (!nodes_subset(new, node_states[N_HIGH_MEMORY])) {
err = -EINVAL;
goto out;
}
@@ -978,7 +1012,8 @@ asmlinkage long sys_get_mempolicy(int __user *policy,
unsigned long maxnode,
unsigned long addr, unsigned long flags)
{
- int err, pval;
+ int err;
+ int uninitialized_var(pval);
nodemask_t nodes;
if (nmask != NULL && maxnode < MAX_NUMNODES)
@@ -1371,7 +1406,6 @@ EXPORT_SYMBOL(alloc_pages_current);
* keeps mempolicies cpuset relative after its cpuset moves. See
* further kernel/cpuset.c update_nodemask().
*/
-void *cpuset_being_rebound;
/* Slow path of a mempolicy copy */
struct mempolicy *__mpol_copy(struct mempolicy *old)
@@ -1527,8 +1561,8 @@ static void sp_delete(struct shared_policy *sp, struct sp_node *n)
kmem_cache_free(sn_cache, n);
}
-struct sp_node *
-sp_alloc(unsigned long start, unsigned long end, struct mempolicy *pol)
+static struct sp_node *sp_alloc(unsigned long start, unsigned long end,
+ struct mempolicy *pol)
{
struct sp_node *n = kmem_cache_alloc(sn_cache, GFP_KERNEL);
@@ -1677,7 +1711,7 @@ void __init numa_policy_init(void)
* fall back to the largest node if they're all smaller.
*/
nodes_clear(interleave_nodes);
- for_each_online_node(nid) {
+ for_each_node_state(nid, N_HIGH_MEMORY) {
unsigned long total_pages = node_present_pages(nid);
/* Preserve the largest node */
@@ -1706,7 +1740,8 @@ void numa_default_policy(void)
}
/* Migrate a policy to a different set of nodes */
-void mpol_rebind_policy(struct mempolicy *pol, const nodemask_t *newmask)
+static void mpol_rebind_policy(struct mempolicy *pol,
+ const nodemask_t *newmask)
{
nodemask_t *mpolmask;
nodemask_t tmp;
@@ -1963,7 +1998,7 @@ int show_numa_map(struct seq_file *m, void *v)
seq_printf(m, " huge");
} else {
check_pgd_range(vma, vma->vm_start, vma->vm_end,
- &node_online_map, MPOL_MF_STATS, md);
+ &node_states[N_HIGH_MEMORY], MPOL_MF_STATS, md);
}
if (!md->pages)
@@ -1990,7 +2025,7 @@ int show_numa_map(struct seq_file *m, void *v)
if (md->writeback)
seq_printf(m," writeback=%lu", md->writeback);
- for_each_online_node(n)
+ for_each_node_state(n, N_HIGH_MEMORY)
if (md->node[n])
seq_printf(m, " N%d=%lu", n, md->node[n]);
out:
@@ -2001,4 +2036,3 @@ out:
m->version = (vma != priv->tail_vma) ? vma->vm_start : 0;
return 0;
}
-
diff --git a/mm/mempool.c b/mm/mempool.c
index 02d5ec3feabc..a46eb1b4bb66 100644
--- a/mm/mempool.c
+++ b/mm/mempool.c
@@ -299,7 +299,7 @@ EXPORT_SYMBOL(mempool_free_slab);
/*
* A commonly used alloc and free fn that kmalloc/kfrees the amount of memory
- * specfied by pool_data
+ * specified by pool_data
*/
void *mempool_kmalloc(gfp_t gfp_mask, void *pool_data)
{
diff --git a/mm/migrate.c b/mm/migrate.c
index 07f22d4a431f..6a207e8d17ea 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -19,6 +19,7 @@
#include <linux/pagemap.h>
#include <linux/buffer_head.h>
#include <linux/mm_inline.h>
+#include <linux/nsproxy.h>
#include <linux/pagevec.h>
#include <linux/rmap.h>
#include <linux/topology.h>
@@ -171,6 +172,7 @@ static void remove_migration_pte(struct vm_area_struct *vma,
pte = pte_mkold(mk_pte(new, vma->vm_page_prot));
if (is_write_migration_entry(entry))
pte = pte_mkwrite(pte);
+ flush_cache_page(vma, addr, pte_pfn(pte));
set_pte_at(mm, addr, ptep, pte);
if (PageAnon(new))
@@ -180,7 +182,6 @@ static void remove_migration_pte(struct vm_area_struct *vma,
/* No need to invalidate - it was non-present before */
update_mmu_cache(vma, addr, pte);
- lazy_mmu_prot_update(pte);
out:
pte_unmap_unlock(ptep, ptl);
@@ -705,7 +706,7 @@ move_newpage:
* The function returns after 10 attempts or if no pages
* are movable anymore because to has become empty
* or no retryable pages exist anymore. All pages will be
- * retruned to the LRU or freed.
+ * returned to the LRU or freed.
*
* Return: Number of pages not migrated or error code.
*/
@@ -924,7 +925,7 @@ asmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages,
/* Find the mm_struct */
read_lock(&tasklist_lock);
- task = pid ? find_task_by_pid(pid) : current;
+ task = pid ? find_task_by_vpid(pid) : current;
if (!task) {
read_unlock(&tasklist_lock);
return -ESRCH;
@@ -986,7 +987,7 @@ asmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages,
goto out;
err = -ENODEV;
- if (!node_online(node))
+ if (!node_state(node, N_HIGH_MEMORY))
goto out;
err = -EACCES;
diff --git a/mm/mmap.c b/mm/mmap.c
index 0d40e66c841b..facc1a75bd4f 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -7,6 +7,7 @@
*/
#include <linux/slab.h>
+#include <linux/backing-dev.h>
#include <linux/mm.h>
#include <linux/shm.h>
#include <linux/mman.h>
@@ -180,8 +181,6 @@ error:
return -ENOMEM;
}
-EXPORT_SYMBOL(__vm_enough_memory);
-
/*
* Requires inode->i_mapping->i_mmap_lock
*/
@@ -1049,8 +1048,7 @@ int vma_wants_writenotify(struct vm_area_struct *vma)
/* The open routine did something to the protections already? */
if (pgprot_val(vma->vm_page_prot) !=
- pgprot_val(protection_map[vm_flags &
- (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)]))
+ pgprot_val(vm_get_page_prot(vm_flags)))
return 0;
/* Specialty mapping? */
@@ -1131,8 +1129,7 @@ munmap_back:
vma->vm_start = addr;
vma->vm_end = addr + len;
vma->vm_flags = vm_flags;
- vma->vm_page_prot = protection_map[vm_flags &
- (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)];
+ vma->vm_page_prot = vm_get_page_prot(vm_flags);
vma->vm_pgoff = pgoff;
if (file) {
@@ -1174,8 +1171,7 @@ munmap_back:
vm_flags = vma->vm_flags;
if (vma_wants_writenotify(vma))
- vma->vm_page_prot =
- protection_map[vm_flags & (VM_READ|VM_WRITE|VM_EXEC)];
+ vma->vm_page_prot = vm_get_page_prot(vm_flags & ~VM_SHARED);
if (!file || !vma_merge(mm, prev, addr, vma->vm_end,
vma->vm_flags, NULL, file, pgoff, vma_policy(vma))) {
@@ -2003,8 +1999,7 @@ unsigned long do_brk(unsigned long addr, unsigned long len)
vma->vm_end = addr + len;
vma->vm_pgoff = pgoff;
vma->vm_flags = flags;
- vma->vm_page_prot = protection_map[flags &
- (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)];
+ vma->vm_page_prot = vm_get_page_prot(flags);
vma_link(mm, vma, prev, rb_link, rb_parent);
out:
mm->total_vm += len >> PAGE_SHIFT;
@@ -2210,7 +2205,7 @@ int install_special_mapping(struct mm_struct *mm,
vma->vm_end = addr + len;
vma->vm_flags = vm_flags | mm->def_flags;
- vma->vm_page_prot = protection_map[vma->vm_flags & 7];
+ vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
vma->vm_ops = &special_mapping_vmops;
vma->vm_private_data = pages;
diff --git a/mm/mprotect.c b/mm/mprotect.c
index e8346c30abec..4de546899dc1 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -53,7 +53,6 @@ static void change_pte_range(struct mm_struct *mm, pmd_t *pmd,
if (dirty_accountable && pte_dirty(ptent))
ptent = pte_mkwrite(ptent);
set_pte_at(mm, addr, pte, ptent);
- lazy_mmu_prot_update(ptent);
#ifdef CONFIG_MIGRATION
} else if (!pte_file(oldpte)) {
swp_entry_t entry = pte_to_swp_entry(oldpte);
@@ -193,11 +192,9 @@ success:
* held in write mode.
*/
vma->vm_flags = newflags;
- vma->vm_page_prot = protection_map[newflags &
- (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)];
+ vma->vm_page_prot = vm_get_page_prot(newflags);
if (vma_wants_writenotify(vma)) {
- vma->vm_page_prot = protection_map[newflags &
- (VM_READ|VM_WRITE|VM_EXEC)];
+ vma->vm_page_prot = vm_get_page_prot(newflags & ~VM_SHARED);
dirty_accountable = 1;
}
diff --git a/mm/mremap.c b/mm/mremap.c
index 8ea5c2412c6e..08e3c7f2bd15 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -291,7 +291,7 @@ unsigned long do_mremap(unsigned long addr,
if ((addr <= new_addr) && (addr+old_len) > new_addr)
goto out;
- ret = security_file_mmap(0, 0, 0, 0, new_addr, 1);
+ ret = security_file_mmap(NULL, 0, 0, 0, new_addr, 1);
if (ret)
goto out;
@@ -399,7 +399,7 @@ unsigned long do_mremap(unsigned long addr,
goto out;
}
- ret = security_file_mmap(0, 0, 0, 0, new_addr, 1);
+ ret = security_file_mmap(NULL, 0, 0, 0, new_addr, 1);
if (ret)
goto out;
}
diff --git a/mm/nommu.c b/mm/nommu.c
index 8ed0cb43118a..35622c590925 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -12,6 +12,7 @@
* Copyright (c) 2002 Greg Ungerer <gerg@snapgear.com>
*/
+#include <linux/module.h>
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/swap.h>
@@ -44,7 +45,6 @@ int sysctl_max_map_count = DEFAULT_MAX_MAP_COUNT;
int heap_stack_gap = 0;
EXPORT_SYMBOL(mem_map);
-EXPORT_SYMBOL(__vm_enough_memory);
EXPORT_SYMBOL(num_physpages);
/* list of shareable VMAs */
@@ -176,7 +176,8 @@ EXPORT_SYMBOL(vfree);
void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot)
{
/*
- * kmalloc doesn't like __GFP_HIGHMEM for some reason
+ * You can't specify __GFP_HIGHMEM with kmalloc() since kmalloc()
+ * returns only a logical address.
*/
return kmalloc(size, (gfp_mask | __GFP_COMP) & ~__GFP_HIGHMEM);
}
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index f9b82ad5047f..91a081a82f55 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -27,6 +27,8 @@
#include <linux/notifier.h>
int sysctl_panic_on_oom;
+int sysctl_oom_kill_allocating_task;
+static DEFINE_SPINLOCK(zone_scan_mutex);
/* #define DEBUG */
/**
@@ -141,7 +143,7 @@ unsigned long badness(struct task_struct *p, unsigned long uptime)
* because p may have allocated or otherwise mapped memory on
* this node before. However it will be less likely.
*/
- if (!cpuset_excl_nodes_overlap(p))
+ if (!cpuset_mems_allowed_intersects(current, p))
points /= 8;
/*
@@ -164,27 +166,14 @@ unsigned long badness(struct task_struct *p, unsigned long uptime)
}
/*
- * Types of limitations to the nodes from which allocations may occur
- */
-#define CONSTRAINT_NONE 1
-#define CONSTRAINT_MEMORY_POLICY 2
-#define CONSTRAINT_CPUSET 3
-
-/*
* Determine the type of allocation constraint.
*/
-static inline int constrained_alloc(struct zonelist *zonelist, gfp_t gfp_mask)
+static inline enum oom_constraint constrained_alloc(struct zonelist *zonelist,
+ gfp_t gfp_mask)
{
#ifdef CONFIG_NUMA
struct zone **z;
- nodemask_t nodes;
- int node;
-
- nodes_clear(nodes);
- /* node has memory ? */
- for_each_online_node(node)
- if (NODE_DATA(node)->node_present_pages)
- node_set(node, nodes);
+ nodemask_t nodes = node_states[N_HIGH_MEMORY];
for (z = zonelist->zones; *z; z++)
if (cpuset_zone_allowed_softwall(*z, gfp_mask))
@@ -223,7 +212,7 @@ static struct task_struct *select_bad_process(unsigned long *ppoints)
if (!p->mm)
continue;
/* skip the init task */
- if (is_init(p))
+ if (is_global_init(p))
continue;
/*
@@ -276,7 +265,7 @@ static struct task_struct *select_bad_process(unsigned long *ppoints)
*/
static void __oom_kill_task(struct task_struct *p, int verbose)
{
- if (is_init(p)) {
+ if (is_global_init(p)) {
WARN_ON(1);
printk(KERN_WARNING "tried to kill init!\n");
return;
@@ -289,7 +278,8 @@ static void __oom_kill_task(struct task_struct *p, int verbose)
}
if (verbose)
- printk(KERN_ERR "Killed process %d (%s)\n", p->pid, p->comm);
+ printk(KERN_ERR "Killed process %d (%s)\n",
+ task_pid_nr(p), p->comm);
/*
* We give our sacrificial lamb high priority and access to
@@ -337,18 +327,25 @@ static int oom_kill_task(struct task_struct *p)
* to memory reserves though, otherwise we might deplete all memory.
*/
do_each_thread(g, q) {
- if (q->mm == mm && q->tgid != p->tgid)
+ if (q->mm == mm && !same_thread_group(q, p))
force_sig(SIGKILL, q);
} while_each_thread(g, q);
return 0;
}
-static int oom_kill_process(struct task_struct *p, unsigned long points,
- const char *message)
+static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
+ unsigned long points, const char *message)
{
struct task_struct *c;
- struct list_head *tsk;
+
+ if (printk_ratelimit()) {
+ printk(KERN_WARNING "%s invoked oom-killer: "
+ "gfp_mask=0x%x, order=%d, oomkilladj=%d\n",
+ current->comm, gfp_mask, order, current->oomkilladj);
+ dump_stack();
+ show_mem();
+ }
/*
* If the task is already exiting, don't alarm the sysadmin or kill
@@ -360,11 +357,10 @@ static int oom_kill_process(struct task_struct *p, unsigned long points,
}
printk(KERN_ERR "%s: kill process %d (%s) score %li or a child\n",
- message, p->pid, p->comm, points);
+ message, task_pid_nr(p), p->comm, points);
/* Try to kill a child first */
- list_for_each(tsk, &p->children) {
- c = list_entry(tsk, struct task_struct, sibling);
+ list_for_each_entry(c, &p->children, sibling) {
if (c->mm == p->mm)
continue;
if (!oom_kill_task(c))
@@ -387,6 +383,57 @@ int unregister_oom_notifier(struct notifier_block *nb)
}
EXPORT_SYMBOL_GPL(unregister_oom_notifier);
+/*
+ * Try to acquire the OOM killer lock for the zones in zonelist. Returns zero
+ * if a parallel OOM killing is already taking place that includes a zone in
+ * the zonelist. Otherwise, locks all zones in the zonelist and returns 1.
+ */
+int try_set_zone_oom(struct zonelist *zonelist)
+{
+ struct zone **z;
+ int ret = 1;
+
+ z = zonelist->zones;
+
+ spin_lock(&zone_scan_mutex);
+ do {
+ if (zone_is_oom_locked(*z)) {
+ ret = 0;
+ goto out;
+ }
+ } while (*(++z) != NULL);
+
+ /*
+ * Lock each zone in the zonelist under zone_scan_mutex so a parallel
+ * invocation of try_set_zone_oom() doesn't succeed when it shouldn't.
+ */
+ z = zonelist->zones;
+ do {
+ zone_set_flag(*z, ZONE_OOM_LOCKED);
+ } while (*(++z) != NULL);
+out:
+ spin_unlock(&zone_scan_mutex);
+ return ret;
+}
+
+/*
+ * Clears the ZONE_OOM_LOCKED flag for all zones in the zonelist so that failed
+ * allocation attempts with zonelists containing them may now recall the OOM
+ * killer, if necessary.
+ */
+void clear_zonelist_oom(struct zonelist *zonelist)
+{
+ struct zone **z;
+
+ z = zonelist->zones;
+
+ spin_lock(&zone_scan_mutex);
+ do {
+ zone_clear_flag(*z, ZONE_OOM_LOCKED);
+ } while (*(++z) != NULL);
+ spin_unlock(&zone_scan_mutex);
+}
+
/**
* out_of_memory - kill the "best" process when we run out of memory
*
@@ -400,21 +447,13 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order)
struct task_struct *p;
unsigned long points = 0;
unsigned long freed = 0;
- int constraint;
+ enum oom_constraint constraint;
blocking_notifier_call_chain(&oom_notify_list, 0, &freed);
if (freed > 0)
/* Got some memory back in the last second. */
return;
- if (printk_ratelimit()) {
- printk(KERN_WARNING "%s invoked oom-killer: "
- "gfp_mask=0x%x, order=%d, oomkilladj=%d\n",
- current->comm, gfp_mask, order, current->oomkilladj);
- dump_stack();
- show_mem();
- }
-
if (sysctl_panic_on_oom == 2)
panic("out of memory. Compulsory panic_on_oom is selected.\n");
@@ -423,23 +462,24 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order)
* NUMA) that may require different handling.
*/
constraint = constrained_alloc(zonelist, gfp_mask);
- cpuset_lock();
read_lock(&tasklist_lock);
switch (constraint) {
case CONSTRAINT_MEMORY_POLICY:
- oom_kill_process(current, points,
+ oom_kill_process(current, gfp_mask, order, points,
"No available memory (MPOL_BIND)");
break;
- case CONSTRAINT_CPUSET:
- oom_kill_process(current, points,
- "No available memory in cpuset");
- break;
-
case CONSTRAINT_NONE:
if (sysctl_panic_on_oom)
panic("out of memory. panic_on_oom is selected\n");
+ /* Fall-through */
+ case CONSTRAINT_CPUSET:
+ if (sysctl_oom_kill_allocating_task) {
+ oom_kill_process(current, gfp_mask, order, points,
+ "Out of memory (oom_kill_allocating_task)");
+ break;
+ }
retry:
/*
* Rambo mode: Shoot down a process and hope it solves whatever
@@ -453,11 +493,11 @@ retry:
/* Found nothing?!?! Either we hang forever, or we panic. */
if (!p) {
read_unlock(&tasklist_lock);
- cpuset_unlock();
panic("Out of memory and no killable processes...\n");
}
- if (oom_kill_process(p, points, "Out of memory"))
+ if (oom_kill_process(p, gfp_mask, order, points,
+ "Out of memory"))
goto retry;
break;
@@ -465,7 +505,6 @@ retry:
out:
read_unlock(&tasklist_lock);
- cpuset_unlock();
/*
* Give "p" a good chance of killing itself before we
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 44720363374c..d55cfcae2ef1 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -2,6 +2,7 @@
* mm/page-writeback.c
*
* Copyright (C) 2002, Linus Torvalds.
+ * Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
*
* Contains functions related to writing back dirty pages at the
* address_space level.
@@ -36,7 +37,7 @@
/*
* The maximum number of pages to writeout in a single bdflush/kupdate
- * operation. We do this so we don't hold I_LOCK against an inode for
+ * operation. We do this so we don't hold I_SYNC against an inode for
* enormous amounts of time, which would block a userspace task which has
* been forced to throttle against that inode. Also, the code reevaluates
* the dirty each time it has written this many pages.
@@ -49,8 +50,6 @@
*/
static long ratelimit_pages = 32;
-static int dirty_exceeded __cacheline_aligned_in_smp; /* Dirty mem may be over limit */
-
/*
* When balance_dirty_pages decides that the caller needs to perform some
* non-background writeback, this is how many pages it will attempt to write.
@@ -103,6 +102,141 @@ EXPORT_SYMBOL(laptop_mode);
static void background_writeout(unsigned long _min_pages);
/*
+ * Scale the writeback cache size proportional to the relative writeout speeds.
+ *
+ * We do this by keeping a floating proportion between BDIs, based on page
+ * writeback completions [end_page_writeback()]. Those devices that write out
+ * pages fastest will get the larger share, while the slower will get a smaller
+ * share.
+ *
+ * We use page writeout completions because we are interested in getting rid of
+ * dirty pages. Having them written out is the primary goal.
+ *
+ * We introduce a concept of time, a period over which we measure these events,
+ * because demand can/will vary over time. The length of this period itself is
+ * measured in page writeback completions.
+ *
+ */
+static struct prop_descriptor vm_completions;
+static struct prop_descriptor vm_dirties;
+
+static unsigned long determine_dirtyable_memory(void);
+
+/*
+ * couple the period to the dirty_ratio:
+ *
+ * period/2 ~ roundup_pow_of_two(dirty limit)
+ */
+static int calc_period_shift(void)
+{
+ unsigned long dirty_total;
+
+ dirty_total = (vm_dirty_ratio * determine_dirtyable_memory()) / 100;
+ return 2 + ilog2(dirty_total - 1);
+}
+
+/*
+ * update the period when the dirty ratio changes.
+ */
+int dirty_ratio_handler(struct ctl_table *table, int write,
+ struct file *filp, void __user *buffer, size_t *lenp,
+ loff_t *ppos)
+{
+ int old_ratio = vm_dirty_ratio;
+ int ret = proc_dointvec_minmax(table, write, filp, buffer, lenp, ppos);
+ if (ret == 0 && write && vm_dirty_ratio != old_ratio) {
+ int shift = calc_period_shift();
+ prop_change_shift(&vm_completions, shift);
+ prop_change_shift(&vm_dirties, shift);
+ }
+ return ret;
+}
+
+/*
+ * Increment the BDI's writeout completion count and the global writeout
+ * completion count. Called from test_clear_page_writeback().
+ */
+static inline void __bdi_writeout_inc(struct backing_dev_info *bdi)
+{
+ __prop_inc_percpu(&vm_completions, &bdi->completions);
+}
+
+static inline void task_dirty_inc(struct task_struct *tsk)
+{
+ prop_inc_single(&vm_dirties, &tsk->dirties);
+}
+
+/*
+ * Obtain an accurate fraction of the BDI's portion.
+ */
+static void bdi_writeout_fraction(struct backing_dev_info *bdi,
+ long *numerator, long *denominator)
+{
+ if (bdi_cap_writeback_dirty(bdi)) {
+ prop_fraction_percpu(&vm_completions, &bdi->completions,
+ numerator, denominator);
+ } else {
+ *numerator = 0;
+ *denominator = 1;
+ }
+}
+
+/*
+ * Clip the earned share of dirty pages to that which is actually available.
+ * This avoids exceeding the total dirty_limit when the floating averages
+ * fluctuate too quickly.
+ */
+static void
+clip_bdi_dirty_limit(struct backing_dev_info *bdi, long dirty, long *pbdi_dirty)
+{
+ long avail_dirty;
+
+ avail_dirty = dirty -
+ (global_page_state(NR_FILE_DIRTY) +
+ global_page_state(NR_WRITEBACK) +
+ global_page_state(NR_UNSTABLE_NFS));
+
+ if (avail_dirty < 0)
+ avail_dirty = 0;
+
+ avail_dirty += bdi_stat(bdi, BDI_RECLAIMABLE) +
+ bdi_stat(bdi, BDI_WRITEBACK);
+
+ *pbdi_dirty = min(*pbdi_dirty, avail_dirty);
+}
+
+static inline void task_dirties_fraction(struct task_struct *tsk,
+ long *numerator, long *denominator)
+{
+ prop_fraction_single(&vm_dirties, &tsk->dirties,
+ numerator, denominator);
+}
+
+/*
+ * scale the dirty limit
+ *
+ * task specific dirty limit:
+ *
+ * dirty -= (dirty/8) * p_{t}
+ */
+void task_dirty_limit(struct task_struct *tsk, long *pdirty)
+{
+ long numerator, denominator;
+ long dirty = *pdirty;
+ u64 inv = dirty >> 3;
+
+ task_dirties_fraction(tsk, &numerator, &denominator);
+ inv *= numerator;
+ do_div(inv, denominator);
+
+ dirty -= inv;
+ if (dirty < *pdirty/2)
+ dirty = *pdirty/2;
+
+ *pdirty = dirty;
+}
+
+/*
* Work out the current dirty-memory clamping and background writeout
* thresholds.
*
@@ -126,7 +260,7 @@ static unsigned long highmem_dirtyable_memory(unsigned long total)
int node;
unsigned long x = 0;
- for_each_online_node(node) {
+ for_each_node_state(node, N_HIGH_MEMORY) {
struct zone *z =
&NODE_DATA(node)->node_zones[ZONE_HIGHMEM];
@@ -158,25 +292,17 @@ static unsigned long determine_dirtyable_memory(void)
}
static void
-get_dirty_limits(long *pbackground, long *pdirty,
- struct address_space *mapping)
+get_dirty_limits(long *pbackground, long *pdirty, long *pbdi_dirty,
+ struct backing_dev_info *bdi)
{
int background_ratio; /* Percentages */
int dirty_ratio;
- int unmapped_ratio;
long background;
long dirty;
unsigned long available_memory = determine_dirtyable_memory();
struct task_struct *tsk;
- unmapped_ratio = 100 - ((global_page_state(NR_FILE_MAPPED) +
- global_page_state(NR_ANON_PAGES)) * 100) /
- available_memory;
-
dirty_ratio = vm_dirty_ratio;
- if (dirty_ratio > unmapped_ratio / 2)
- dirty_ratio = unmapped_ratio / 2;
-
if (dirty_ratio < 5)
dirty_ratio = 5;
@@ -193,6 +319,23 @@ get_dirty_limits(long *pbackground, long *pdirty,
}
*pbackground = background;
*pdirty = dirty;
+
+ if (bdi) {
+ u64 bdi_dirty = dirty;
+ long numerator, denominator;
+
+ /*
+ * Calculate this BDI's share of the dirty ratio.
+ */
+ bdi_writeout_fraction(bdi, &numerator, &denominator);
+
+ bdi_dirty *= numerator;
+ do_div(bdi_dirty, denominator);
+
+ *pbdi_dirty = bdi_dirty;
+ clip_bdi_dirty_limit(bdi, dirty, pbdi_dirty);
+ task_dirty_limit(current, pbdi_dirty);
+ }
}
/*
@@ -204,9 +347,11 @@ get_dirty_limits(long *pbackground, long *pdirty,
*/
static void balance_dirty_pages(struct address_space *mapping)
{
- long nr_reclaimable;
+ long nr_reclaimable, bdi_nr_reclaimable;
+ long nr_writeback, bdi_nr_writeback;
long background_thresh;
long dirty_thresh;
+ long bdi_thresh;
unsigned long pages_written = 0;
unsigned long write_chunk = sync_writeback_pages();
@@ -221,15 +366,30 @@ static void balance_dirty_pages(struct address_space *mapping)
.range_cyclic = 1,
};
- get_dirty_limits(&background_thresh, &dirty_thresh, mapping);
+ get_dirty_limits(&background_thresh, &dirty_thresh,
+ &bdi_thresh, bdi);
+
nr_reclaimable = global_page_state(NR_FILE_DIRTY) +
global_page_state(NR_UNSTABLE_NFS);
- if (nr_reclaimable + global_page_state(NR_WRITEBACK) <=
- dirty_thresh)
- break;
+ nr_writeback = global_page_state(NR_WRITEBACK);
+
+ bdi_nr_reclaimable = bdi_stat(bdi, BDI_RECLAIMABLE);
+ bdi_nr_writeback = bdi_stat(bdi, BDI_WRITEBACK);
+
+ if (bdi_nr_reclaimable + bdi_nr_writeback <= bdi_thresh)
+ break;
- if (!dirty_exceeded)
- dirty_exceeded = 1;
+ /*
+ * Throttle it only when the background writeback cannot
+ * catch-up. This avoids (excessively) small writeouts
+ * when the bdi limits are ramping up.
+ */
+ if (nr_reclaimable + nr_writeback <
+ (background_thresh + dirty_thresh) / 2)
+ break;
+
+ if (!bdi->dirty_exceeded)
+ bdi->dirty_exceeded = 1;
/* Note: nr_reclaimable denotes nr_dirty + nr_unstable.
* Unstable writes are a feature of certain networked
@@ -237,26 +397,42 @@ static void balance_dirty_pages(struct address_space *mapping)
* written to the server's write cache, but has not yet
* been flushed to permanent storage.
*/
- if (nr_reclaimable) {
+ if (bdi_nr_reclaimable) {
writeback_inodes(&wbc);
- get_dirty_limits(&background_thresh,
- &dirty_thresh, mapping);
- nr_reclaimable = global_page_state(NR_FILE_DIRTY) +
- global_page_state(NR_UNSTABLE_NFS);
- if (nr_reclaimable +
- global_page_state(NR_WRITEBACK)
- <= dirty_thresh)
- break;
pages_written += write_chunk - wbc.nr_to_write;
- if (pages_written >= write_chunk)
- break; /* We've done our duty */
+ get_dirty_limits(&background_thresh, &dirty_thresh,
+ &bdi_thresh, bdi);
}
+
+ /*
+ * In order to avoid the stacked BDI deadlock we need
+ * to ensure we accurately count the 'dirty' pages when
+ * the threshold is low.
+ *
+ * Otherwise it would be possible to get thresh+n pages
+ * reported dirty, even though there are thresh-m pages
+ * actually dirty; with m+n sitting in the percpu
+ * deltas.
+ */
+ if (bdi_thresh < 2*bdi_stat_error(bdi)) {
+ bdi_nr_reclaimable = bdi_stat_sum(bdi, BDI_RECLAIMABLE);
+ bdi_nr_writeback = bdi_stat_sum(bdi, BDI_WRITEBACK);
+ } else if (bdi_nr_reclaimable) {
+ bdi_nr_reclaimable = bdi_stat(bdi, BDI_RECLAIMABLE);
+ bdi_nr_writeback = bdi_stat(bdi, BDI_WRITEBACK);
+ }
+
+ if (bdi_nr_reclaimable + bdi_nr_writeback <= bdi_thresh)
+ break;
+ if (pages_written >= write_chunk)
+ break; /* We've done our duty */
+
congestion_wait(WRITE, HZ/10);
}
- if (nr_reclaimable + global_page_state(NR_WRITEBACK)
- <= dirty_thresh && dirty_exceeded)
- dirty_exceeded = 0;
+ if (bdi_nr_reclaimable + bdi_nr_writeback < bdi_thresh &&
+ bdi->dirty_exceeded)
+ bdi->dirty_exceeded = 0;
if (writeback_in_progress(bdi))
return; /* pdflush is already working this queue */
@@ -270,7 +446,9 @@ static void balance_dirty_pages(struct address_space *mapping)
* background_thresh, to keep the amount of dirty memory low.
*/
if ((laptop_mode && pages_written) ||
- (!laptop_mode && (nr_reclaimable > background_thresh)))
+ (!laptop_mode && (global_page_state(NR_FILE_DIRTY)
+ + global_page_state(NR_UNSTABLE_NFS)
+ > background_thresh)))
pdflush_operation(background_writeout, 0);
}
@@ -306,7 +484,7 @@ void balance_dirty_pages_ratelimited_nr(struct address_space *mapping,
unsigned long *p;
ratelimit = ratelimit_pages;
- if (dirty_exceeded)
+ if (mapping->backing_dev_info->dirty_exceeded)
ratelimit = 8;
/*
@@ -331,18 +509,8 @@ void throttle_vm_writeout(gfp_t gfp_mask)
long background_thresh;
long dirty_thresh;
- if ((gfp_mask & (__GFP_FS|__GFP_IO)) != (__GFP_FS|__GFP_IO)) {
- /*
- * The caller might hold locks which can prevent IO completion
- * or progress in the filesystem. So we cannot just sit here
- * waiting for IO to complete.
- */
- congestion_wait(WRITE, HZ/10);
- return;
- }
-
for ( ; ; ) {
- get_dirty_limits(&background_thresh, &dirty_thresh, NULL);
+ get_dirty_limits(&background_thresh, &dirty_thresh, NULL, NULL);
/*
* Boost the allowable dirty threshold a bit for page
@@ -354,6 +522,14 @@ void throttle_vm_writeout(gfp_t gfp_mask)
global_page_state(NR_WRITEBACK) <= dirty_thresh)
break;
congestion_wait(WRITE, HZ/10);
+
+ /*
+ * The caller might hold locks which can prevent IO completion
+ * or progress in the filesystem. So we cannot just sit here
+ * waiting for IO to complete.
+ */
+ if ((gfp_mask & (__GFP_FS|__GFP_IO)) != (__GFP_FS|__GFP_IO))
+ break;
}
}
@@ -377,11 +553,12 @@ static void background_writeout(unsigned long _min_pages)
long background_thresh;
long dirty_thresh;
- get_dirty_limits(&background_thresh, &dirty_thresh, NULL);
+ get_dirty_limits(&background_thresh, &dirty_thresh, NULL, NULL);
if (global_page_state(NR_FILE_DIRTY) +
global_page_state(NR_UNSTABLE_NFS) < background_thresh
&& min_pages <= 0)
break;
+ wbc.more_io = 0;
wbc.encountered_congestion = 0;
wbc.nr_to_write = MAX_WRITEBACK_PAGES;
wbc.pages_skipped = 0;
@@ -389,8 +566,9 @@ static void background_writeout(unsigned long _min_pages)
min_pages -= MAX_WRITEBACK_PAGES - wbc.nr_to_write;
if (wbc.nr_to_write > 0 || wbc.pages_skipped > 0) {
/* Wrote less than expected */
- congestion_wait(WRITE, HZ/10);
- if (!wbc.encountered_congestion)
+ if (wbc.encountered_congestion || wbc.more_io)
+ congestion_wait(WRITE, HZ/10);
+ else
break;
}
}
@@ -455,11 +633,12 @@ static void wb_kupdate(unsigned long arg)
global_page_state(NR_UNSTABLE_NFS) +
(inodes_stat.nr_inodes - inodes_stat.nr_unused);
while (nr_to_write > 0) {
+ wbc.more_io = 0;
wbc.encountered_congestion = 0;
wbc.nr_to_write = MAX_WRITEBACK_PAGES;
writeback_inodes(&wbc);
if (wbc.nr_to_write > 0) {
- if (wbc.encountered_congestion)
+ if (wbc.encountered_congestion || wbc.more_io)
congestion_wait(WRITE, HZ/10);
else
break; /* All the old data is written */
@@ -580,9 +759,15 @@ static struct notifier_block __cpuinitdata ratelimit_nb = {
*/
void __init page_writeback_init(void)
{
+ int shift;
+
mod_timer(&wb_timer, jiffies + dirty_writeback_interval);
writeback_set_ratelimit();
register_cpu_notifier(&ratelimit_nb);
+
+ shift = calc_period_shift();
+ prop_descriptor_init(&vm_completions, shift);
+ prop_descriptor_init(&vm_dirties, shift);
}
/**
@@ -672,8 +857,10 @@ retry:
ret = (*writepage)(page, wbc, data);
- if (unlikely(ret == AOP_WRITEPAGE_ACTIVATE))
+ if (unlikely(ret == AOP_WRITEPAGE_ACTIVATE)) {
unlock_page(page);
+ ret = 0;
+ }
if (ret || (--(wbc->nr_to_write) <= 0))
done = 1;
if (wbc->nonblocking && bdi_write_congested(bdi)) {
@@ -809,7 +996,7 @@ int __set_page_dirty_no_writeback(struct page *page)
* mapping is pinned by the vma's ->vm_file reference.
*
* We take care to handle the case where the page was truncated from the
- * mapping by re-checking page_mapping() insode tree_lock.
+ * mapping by re-checking page_mapping() inside tree_lock.
*/
int __set_page_dirty_nobuffers(struct page *page)
{
@@ -827,6 +1014,8 @@ int __set_page_dirty_nobuffers(struct page *page)
WARN_ON_ONCE(!PagePrivate(page) && !PageUptodate(page));
if (mapping_cap_account_dirty(mapping)) {
__inc_zone_page_state(page, NR_FILE_DIRTY);
+ __inc_bdi_stat(mapping->backing_dev_info,
+ BDI_RECLAIMABLE);
task_io_account_write(PAGE_CACHE_SIZE);
}
radix_tree_tag_set(&mapping->page_tree,
@@ -859,7 +1048,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.
*/
-int fastcall set_page_dirty(struct page *page)
+static int __set_page_dirty(struct page *page)
{
struct address_space *mapping = page_mapping(page);
@@ -877,6 +1066,14 @@ int fastcall set_page_dirty(struct page *page)
}
return 0;
}
+
+int fastcall 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);
/*
@@ -961,6 +1158,8 @@ int clear_page_dirty_for_io(struct page *page)
*/
if (TestClearPageDirty(page)) {
dec_zone_page_state(page, NR_FILE_DIRTY);
+ dec_bdi_stat(mapping->backing_dev_info,
+ BDI_RECLAIMABLE);
return 1;
}
return 0;
@@ -975,14 +1174,20 @@ int test_clear_page_writeback(struct page *page)
int ret;
if (mapping) {
+ struct backing_dev_info *bdi = mapping->backing_dev_info;
unsigned long flags;
write_lock_irqsave(&mapping->tree_lock, flags);
ret = TestClearPageWriteback(page);
- if (ret)
+ if (ret) {
radix_tree_tag_clear(&mapping->page_tree,
page_index(page),
PAGECACHE_TAG_WRITEBACK);
+ if (bdi_cap_writeback_dirty(bdi)) {
+ __dec_bdi_stat(bdi, BDI_WRITEBACK);
+ __bdi_writeout_inc(bdi);
+ }
+ }
write_unlock_irqrestore(&mapping->tree_lock, flags);
} else {
ret = TestClearPageWriteback(page);
@@ -998,14 +1203,18 @@ int test_set_page_writeback(struct page *page)
int ret;
if (mapping) {
+ struct backing_dev_info *bdi = mapping->backing_dev_info;
unsigned long flags;
write_lock_irqsave(&mapping->tree_lock, flags);
ret = TestSetPageWriteback(page);
- if (!ret)
+ if (!ret) {
radix_tree_tag_set(&mapping->page_tree,
page_index(page),
PAGECACHE_TAG_WRITEBACK);
+ if (bdi_cap_writeback_dirty(bdi))
+ __inc_bdi_stat(bdi, BDI_WRITEBACK);
+ }
if (!PageDirty(page))
radix_tree_tag_clear(&mapping->page_tree,
page_index(page),
@@ -1022,17 +1231,15 @@ int test_set_page_writeback(struct page *page)
EXPORT_SYMBOL(test_set_page_writeback);
/*
- * Return true if any of the pages in the mapping are marged with the
+ * Return true if any of the pages in the mapping are marked with the
* passed tag.
*/
int mapping_tagged(struct address_space *mapping, int tag)
{
- unsigned long flags;
int ret;
-
- read_lock_irqsave(&mapping->tree_lock, flags);
+ rcu_read_lock();
ret = radix_tree_tagged(&mapping->page_tree, tag);
- read_unlock_irqrestore(&mapping->tree_lock, flags);
+ rcu_read_unlock();
return ret;
}
EXPORT_SYMBOL(mapping_tagged);
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 1a8c59571cb7..12376ae3f733 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -27,6 +27,7 @@
#include <linux/pagevec.h>
#include <linux/blkdev.h>
#include <linux/slab.h>
+#include <linux/oom.h>
#include <linux/notifier.h>
#include <linux/topology.h>
#include <linux/sysctl.h>
@@ -41,24 +42,37 @@
#include <linux/pfn.h>
#include <linux/backing-dev.h>
#include <linux/fault-inject.h>
+#include <linux/page-isolation.h>
#include <asm/tlbflush.h>
#include <asm/div64.h>
#include "internal.h"
/*
- * MCD - HACK: Find somewhere to initialize this EARLY, or make this
- * initializer cleaner
+ * Array of node states.
*/
-nodemask_t node_online_map __read_mostly = { { [0] = 1UL } };
-EXPORT_SYMBOL(node_online_map);
-nodemask_t node_possible_map __read_mostly = NODE_MASK_ALL;
-EXPORT_SYMBOL(node_possible_map);
+nodemask_t node_states[NR_NODE_STATES] __read_mostly = {
+ [N_POSSIBLE] = NODE_MASK_ALL,
+ [N_ONLINE] = { { [0] = 1UL } },
+#ifndef CONFIG_NUMA
+ [N_NORMAL_MEMORY] = { { [0] = 1UL } },
+#ifdef CONFIG_HIGHMEM
+ [N_HIGH_MEMORY] = { { [0] = 1UL } },
+#endif
+ [N_CPU] = { { [0] = 1UL } },
+#endif /* NUMA */
+};
+EXPORT_SYMBOL(node_states);
+
unsigned long totalram_pages __read_mostly;
unsigned long totalreserve_pages __read_mostly;
long nr_swap_pages;
int percpu_pagelist_fraction;
+#ifdef CONFIG_HUGETLB_PAGE_SIZE_VARIABLE
+int pageblock_order __read_mostly;
+#endif
+
static void __free_pages_ok(struct page *page, unsigned int order);
/*
@@ -109,7 +123,7 @@ static unsigned long __meminitdata dma_reserve;
#ifdef CONFIG_ARCH_POPULATES_NODE_MAP
/*
- * MAX_ACTIVE_REGIONS determines the maxmimum number of distinct
+ * MAX_ACTIVE_REGIONS determines the maximum number of distinct
* ranges of memory (RAM) that may be registered with add_active_range().
* Ranges passed to add_active_range() will be merged if possible
* so the number of times add_active_range() can be called is
@@ -137,7 +151,7 @@ static unsigned long __meminitdata dma_reserve;
static unsigned long __meminitdata node_boundary_end_pfn[MAX_NUMNODES];
#endif /* CONFIG_MEMORY_HOTPLUG_RESERVE */
unsigned long __initdata required_kernelcore;
- unsigned long __initdata required_movablecore;
+ static unsigned long __initdata required_movablecore;
unsigned long __meminitdata zone_movable_pfn[MAX_NUMNODES];
/* movable_zone is the "real" zone pages in ZONE_MOVABLE are taken from */
@@ -150,6 +164,14 @@ int nr_node_ids __read_mostly = MAX_NUMNODES;
EXPORT_SYMBOL(nr_node_ids);
#endif
+int page_group_by_mobility_disabled __read_mostly;
+
+static void set_pageblock_migratetype(struct page *page, int migratetype)
+{
+ set_pageblock_flags_group(page, (unsigned long)migratetype,
+ PB_migrate, PB_migrate_end);
+}
+
#ifdef CONFIG_DEBUG_VM
static int page_outside_zone_boundaries(struct zone *zone, struct page *page)
{
@@ -293,16 +315,6 @@ static inline void prep_zero_page(struct page *page, int order, gfp_t gfp_flags)
clear_highpage(page + i);
}
-/*
- * function for dealing with page's order in buddy system.
- * zone->lock is already acquired when we use these.
- * So, we don't need atomic page->flags operations here.
- */
-static inline unsigned long page_order(struct page *page)
-{
- return page_private(page);
-}
-
static inline void set_page_order(struct page *page, int order)
{
set_page_private(page, order);
@@ -404,6 +416,7 @@ static inline void __free_one_page(struct page *page,
{
unsigned long page_idx;
int order_size = 1 << order;
+ int migratetype = get_pageblock_migratetype(page);
if (unlikely(PageCompound(page)))
destroy_compound_page(page, order);
@@ -416,7 +429,6 @@ static inline void __free_one_page(struct page *page,
__mod_zone_page_state(zone, NR_FREE_PAGES, order_size);
while (order < MAX_ORDER-1) {
unsigned long combined_idx;
- struct free_area *area;
struct page *buddy;
buddy = __page_find_buddy(page, page_idx, order);
@@ -424,8 +436,7 @@ static inline void __free_one_page(struct page *page,
break; /* Move the buddy up one level. */
list_del(&buddy->lru);
- area = zone->free_area + order;
- area->nr_free--;
+ zone->free_area[order].nr_free--;
rmv_page_order(buddy);
combined_idx = __find_combined_index(page_idx, order);
page = page + (combined_idx - page_idx);
@@ -433,7 +444,8 @@ static inline void __free_one_page(struct page *page,
order++;
}
set_page_order(page, order);
- list_add(&page->lru, &zone->free_area[order].free_list);
+ list_add(&page->lru,
+ &zone->free_area[order].free_list[migratetype]);
zone->free_area[order].nr_free++;
}
@@ -478,7 +490,7 @@ static void free_pages_bulk(struct zone *zone, int count,
struct list_head *list, int order)
{
spin_lock(&zone->lock);
- zone->all_unreclaimable = 0;
+ zone_clear_flag(zone, ZONE_ALL_UNRECLAIMABLE);
zone->pages_scanned = 0;
while (count--) {
struct page *page;
@@ -495,7 +507,7 @@ static void free_pages_bulk(struct zone *zone, int count,
static void free_one_page(struct zone *zone, struct page *page, int order)
{
spin_lock(&zone->lock);
- zone->all_unreclaimable = 0;
+ zone_clear_flag(zone, ZONE_ALL_UNRECLAIMABLE);
zone->pages_scanned = 0;
__free_one_page(page, zone, order);
spin_unlock(&zone->lock);
@@ -567,7 +579,8 @@ void fastcall __init __free_pages_bootmem(struct page *page, unsigned int order)
* -- wli
*/
static inline void expand(struct zone *zone, struct page *page,
- int low, int high, struct free_area *area)
+ int low, int high, struct free_area *area,
+ int migratetype)
{
unsigned long size = 1 << high;
@@ -576,7 +589,7 @@ static inline void expand(struct zone *zone, struct page *page,
high--;
size >>= 1;
VM_BUG_ON(bad_range(zone, &page[size]));
- list_add(&page[size].lru, &area->free_list);
+ list_add(&page[size].lru, &area->free_list[migratetype]);
area->nr_free++;
set_page_order(&page[size], high);
}
@@ -628,49 +641,215 @@ static int prep_new_page(struct page *page, int order, gfp_t gfp_flags)
return 0;
}
-/*
- * Do the hard work of removing an element from the buddy allocator.
- * Call me with the zone->lock already held.
+/*
+ * Go through the free lists for the given migratetype and remove
+ * the smallest available page from the freelists
*/
-static struct page *__rmqueue(struct zone *zone, unsigned int order)
+static struct page *__rmqueue_smallest(struct zone *zone, unsigned int order,
+ int migratetype)
{
- struct free_area * area;
unsigned int current_order;
+ struct free_area * area;
struct page *page;
+ /* Find a page of the appropriate size in the preferred list */
for (current_order = order; current_order < MAX_ORDER; ++current_order) {
- area = zone->free_area + current_order;
- if (list_empty(&area->free_list))
+ area = &(zone->free_area[current_order]);
+ if (list_empty(&area->free_list[migratetype]))
continue;
- page = list_entry(area->free_list.next, struct page, lru);
+ page = list_entry(area->free_list[migratetype].next,
+ struct page, lru);
list_del(&page->lru);
rmv_page_order(page);
area->nr_free--;
__mod_zone_page_state(zone, NR_FREE_PAGES, - (1UL << order));
- expand(zone, page, order, current_order, area);
+ expand(zone, page, order, current_order, area, migratetype);
return page;
}
return NULL;
}
+
+/*
+ * This array describes the order lists are fallen back to when
+ * the free lists for the desirable migrate type are depleted
+ */
+static int fallbacks[MIGRATE_TYPES][MIGRATE_TYPES-1] = {
+ [MIGRATE_UNMOVABLE] = { MIGRATE_RECLAIMABLE, MIGRATE_MOVABLE, MIGRATE_RESERVE },
+ [MIGRATE_RECLAIMABLE] = { MIGRATE_UNMOVABLE, MIGRATE_MOVABLE, MIGRATE_RESERVE },
+ [MIGRATE_MOVABLE] = { MIGRATE_RECLAIMABLE, MIGRATE_UNMOVABLE, MIGRATE_RESERVE },
+ [MIGRATE_RESERVE] = { MIGRATE_RESERVE, MIGRATE_RESERVE, MIGRATE_RESERVE }, /* Never used */
+};
+
+/*
+ * Move the free pages in a range to the free lists of the requested type.
+ * Note that start_page and end_pages are not aligned on a pageblock
+ * boundary. If alignment is required, use move_freepages_block()
+ */
+int move_freepages(struct zone *zone,
+ struct page *start_page, struct page *end_page,
+ int migratetype)
+{
+ struct page *page;
+ unsigned long order;
+ int pages_moved = 0;
+
+#ifndef CONFIG_HOLES_IN_ZONE
+ /*
+ * page_zone is not safe to call in this context when
+ * CONFIG_HOLES_IN_ZONE is set. This bug check is probably redundant
+ * anyway as we check zone boundaries in move_freepages_block().
+ * Remove at a later date when no bug reports exist related to
+ * grouping pages by mobility
+ */
+ BUG_ON(page_zone(start_page) != page_zone(end_page));
+#endif
+
+ for (page = start_page; page <= end_page;) {
+ if (!pfn_valid_within(page_to_pfn(page))) {
+ page++;
+ continue;
+ }
+
+ if (!PageBuddy(page)) {
+ page++;
+ continue;
+ }
+
+ order = page_order(page);
+ list_del(&page->lru);
+ list_add(&page->lru,
+ &zone->free_area[order].free_list[migratetype]);
+ page += 1 << order;
+ pages_moved += 1 << order;
+ }
+
+ return pages_moved;
+}
+
+int move_freepages_block(struct zone *zone, struct page *page, int migratetype)
+{
+ unsigned long start_pfn, end_pfn;
+ struct page *start_page, *end_page;
+
+ start_pfn = page_to_pfn(page);
+ start_pfn = start_pfn & ~(pageblock_nr_pages-1);
+ start_page = pfn_to_page(start_pfn);
+ end_page = start_page + pageblock_nr_pages - 1;
+ end_pfn = start_pfn + pageblock_nr_pages - 1;
+
+ /* Do not cross zone boundaries */
+ if (start_pfn < zone->zone_start_pfn)
+ start_page = page;
+ if (end_pfn >= zone->zone_start_pfn + zone->spanned_pages)
+ return 0;
+
+ return move_freepages(zone, start_page, end_page, migratetype);
+}
+
+/* Remove an element from the buddy allocator from the fallback list */
+static struct page *__rmqueue_fallback(struct zone *zone, int order,
+ int start_migratetype)
+{
+ struct free_area * area;
+ int current_order;
+ struct page *page;
+ int migratetype, i;
+
+ /* Find the largest possible block of pages in the other list */
+ for (current_order = MAX_ORDER-1; current_order >= order;
+ --current_order) {
+ for (i = 0; i < MIGRATE_TYPES - 1; i++) {
+ migratetype = fallbacks[start_migratetype][i];
+
+ /* MIGRATE_RESERVE handled later if necessary */
+ if (migratetype == MIGRATE_RESERVE)
+ continue;
+
+ area = &(zone->free_area[current_order]);
+ if (list_empty(&area->free_list[migratetype]))
+ continue;
+
+ page = list_entry(area->free_list[migratetype].next,
+ struct page, lru);
+ area->nr_free--;
+
+ /*
+ * If breaking a large block of pages, move all free
+ * pages to the preferred allocation list. If falling
+ * back for a reclaimable kernel allocation, be more
+ * agressive about taking ownership of free pages
+ */
+ if (unlikely(current_order >= (pageblock_order >> 1)) ||
+ start_migratetype == MIGRATE_RECLAIMABLE) {
+ unsigned long pages;
+ pages = move_freepages_block(zone, page,
+ start_migratetype);
+
+ /* Claim the whole block if over half of it is free */
+ if (pages >= (1 << (pageblock_order-1)))
+ set_pageblock_migratetype(page,
+ start_migratetype);
+
+ migratetype = start_migratetype;
+ }
+
+ /* Remove the page from the freelists */
+ list_del(&page->lru);
+ rmv_page_order(page);
+ __mod_zone_page_state(zone, NR_FREE_PAGES,
+ -(1UL << order));
+
+ if (current_order == pageblock_order)
+ set_pageblock_migratetype(page,
+ start_migratetype);
+
+ expand(zone, page, order, current_order, area, migratetype);
+ return page;
+ }
+ }
+
+ /* Use MIGRATE_RESERVE rather than fail an allocation */
+ return __rmqueue_smallest(zone, order, MIGRATE_RESERVE);
+}
+
+/*
+ * Do the hard work of removing an element from the buddy allocator.
+ * Call me with the zone->lock already held.
+ */
+static struct page *__rmqueue(struct zone *zone, unsigned int order,
+ int migratetype)
+{
+ struct page *page;
+
+ page = __rmqueue_smallest(zone, order, migratetype);
+
+ if (unlikely(!page))
+ page = __rmqueue_fallback(zone, order, migratetype);
+
+ return page;
+}
+
/*
* Obtain a specified number of elements from the buddy allocator, all under
* a single hold of the lock, for efficiency. Add them to the supplied list.
* Returns the number of new pages which were placed at *list.
*/
static int rmqueue_bulk(struct zone *zone, unsigned int order,
- unsigned long count, struct list_head *list)
+ unsigned long count, struct list_head *list,
+ int migratetype)
{
int i;
spin_lock(&zone->lock);
for (i = 0; i < count; ++i) {
- struct page *page = __rmqueue(zone, order);
+ struct page *page = __rmqueue(zone, order, migratetype);
if (unlikely(page == NULL))
break;
- list_add_tail(&page->lru, list);
+ list_add(&page->lru, list);
+ set_page_private(page, migratetype);
}
spin_unlock(&zone->lock);
return i;
@@ -732,7 +911,7 @@ void mark_free_pages(struct zone *zone)
{
unsigned long pfn, max_zone_pfn;
unsigned long flags;
- int order;
+ int order, t;
struct list_head *curr;
if (!zone->spanned_pages)
@@ -749,17 +928,18 @@ void mark_free_pages(struct zone *zone)
swsusp_unset_page_free(page);
}
- for (order = MAX_ORDER - 1; order >= 0; --order)
- list_for_each(curr, &zone->free_area[order].free_list) {
+ for_each_migratetype_order(order, t) {
+ list_for_each(curr, &zone->free_area[order].free_list[t]) {
unsigned long i;
pfn = page_to_pfn(list_entry(curr, struct page, lru));
for (i = 0; i < (1UL << order); i++)
swsusp_set_page_free(pfn_to_page(pfn + i));
}
-
+ }
spin_unlock_irqrestore(&zone->lock, flags);
}
+#endif /* CONFIG_PM */
/*
* Spill all of this CPU's per-cpu pages back into the buddy allocator.
@@ -772,7 +952,25 @@ void drain_local_pages(void)
__drain_pages(smp_processor_id());
local_irq_restore(flags);
}
-#endif /* CONFIG_HIBERNATION */
+
+void smp_drain_local_pages(void *arg)
+{
+ drain_local_pages();
+}
+
+/*
+ * Spill all the per-cpu pages from all CPUs back into the buddy allocator
+ */
+void drain_all_local_pages(void)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ __drain_pages(smp_processor_id());
+ local_irq_restore(flags);
+
+ smp_call_function(smp_drain_local_pages, NULL, 0, 1);
+}
/*
* Free a 0-order page
@@ -797,6 +995,7 @@ static void fastcall free_hot_cold_page(struct page *page, int cold)
local_irq_save(flags);
__count_vm_event(PGFREE);
list_add(&page->lru, &pcp->list);
+ set_page_private(page, get_pageblock_migratetype(page));
pcp->count++;
if (pcp->count >= pcp->high) {
free_pages_bulk(zone, pcp->batch, &pcp->list, 0);
@@ -846,6 +1045,7 @@ static struct page *buffered_rmqueue(struct zonelist *zonelist,
struct page *page;
int cold = !!(gfp_flags & __GFP_COLD);
int cpu;
+ int migratetype = allocflags_to_migratetype(gfp_flags);
again:
cpu = get_cpu();
@@ -856,16 +1056,28 @@ again:
local_irq_save(flags);
if (!pcp->count) {
pcp->count = rmqueue_bulk(zone, 0,
- pcp->batch, &pcp->list);
+ pcp->batch, &pcp->list, migratetype);
if (unlikely(!pcp->count))
goto failed;
}
- page = list_entry(pcp->list.next, struct page, lru);
+
+ /* Find a page of the appropriate migrate type */
+ list_for_each_entry(page, &pcp->list, lru)
+ if (page_private(page) == migratetype)
+ break;
+
+ /* Allocate more to the pcp list if necessary */
+ if (unlikely(&page->lru == &pcp->list)) {
+ pcp->count += rmqueue_bulk(zone, 0,
+ pcp->batch, &pcp->list, migratetype);
+ page = list_entry(pcp->list.next, struct page, lru);
+ }
+
list_del(&page->lru);
pcp->count--;
} else {
spin_lock_irqsave(&zone->lock, flags);
- page = __rmqueue(zone, order);
+ page = __rmqueue(zone, order, migratetype);
spin_unlock(&zone->lock);
if (!page)
goto failed;
@@ -1028,11 +1240,11 @@ int zone_watermark_ok(struct zone *z, int order, unsigned long mark,
* skip over zones that are not allowed by the cpuset, or that have
* been recently (in last second) found to be nearly full. See further
* comments in mmzone.h. Reduces cache footprint of zonelist scans
- * that have to skip over alot of full or unallowed zones.
+ * that have to skip over a lot of full or unallowed zones.
*
* If the zonelist cache is present in the passed in zonelist, then
* returns a pointer to the allowed node mask (either the current
- * tasks mems_allowed, or node_online_map.)
+ * tasks mems_allowed, or node_states[N_HIGH_MEMORY].)
*
* If the zonelist cache is not available for this zonelist, does
* nothing and returns NULL.
@@ -1061,7 +1273,7 @@ static nodemask_t *zlc_setup(struct zonelist *zonelist, int alloc_flags)
allowednodes = !in_interrupt() && (alloc_flags & ALLOC_CPUSET) ?
&cpuset_current_mems_allowed :
- &node_online_map;
+ &node_states[N_HIGH_MEMORY];
return allowednodes;
}
@@ -1183,9 +1395,6 @@ zonelist_scan:
!zlc_zone_worth_trying(zonelist, z, allowednodes))
continue;
zone = *z;
- if (unlikely(NUMA_BUILD && (gfp_mask & __GFP_THISNODE) &&
- zone->zone_pgdat != zonelist->zones[0]->zone_pgdat))
- break;
if ((alloc_flags & ALLOC_CPUSET) &&
!cpuset_zone_allowed_softwall(zone, gfp_mask))
goto try_next_zone;
@@ -1254,7 +1463,10 @@ restart:
z = zonelist->zones; /* the list of zones suitable for gfp_mask */
if (unlikely(*z == NULL)) {
- /* Should this ever happen?? */
+ /*
+ * Happens if we have an empty zonelist as a result of
+ * GFP_THISNODE being used on a memoryless node
+ */
return NULL;
}
@@ -1346,12 +1558,20 @@ nofail_alloc:
cond_resched();
+ if (order != 0)
+ drain_all_local_pages();
+
if (likely(did_some_progress)) {
page = get_page_from_freelist(gfp_mask, order,
zonelist, alloc_flags);
if (page)
goto got_pg;
} else if ((gfp_mask & __GFP_FS) && !(gfp_mask & __GFP_NORETRY)) {
+ if (!try_set_zone_oom(zonelist)) {
+ schedule_timeout_uninterruptible(1);
+ goto restart;
+ }
+
/*
* Go through the zonelist yet one more time, keep
* very high watermark here, this is only to catch
@@ -1360,14 +1580,19 @@ nofail_alloc:
*/
page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, order,
zonelist, ALLOC_WMARK_HIGH|ALLOC_CPUSET);
- if (page)
+ if (page) {
+ clear_zonelist_oom(zonelist);
goto got_pg;
+ }
/* The OOM killer will not help higher order allocs so fail */
- if (order > PAGE_ALLOC_COSTLY_ORDER)
+ if (order > PAGE_ALLOC_COSTLY_ORDER) {
+ clear_zonelist_oom(zonelist);
goto nopage;
+ }
out_of_memory(zonelist, gfp_mask, order);
+ clear_zonelist_oom(zonelist);
goto restart;
}
@@ -1616,7 +1841,7 @@ void show_free_areas(void)
K(zone_page_state(zone, NR_INACTIVE)),
K(zone->present_pages),
zone->pages_scanned,
- (zone->all_unreclaimable ? "yes" : "no")
+ (zone_is_all_unreclaimable(zone) ? "yes" : "no")
);
printk("lowmem_reserve[]:");
for (i = 0; i < MAX_NR_ZONES; i++)
@@ -1794,7 +2019,7 @@ static int find_next_best_node(int node, nodemask_t *used_node_mask)
return node;
}
- for_each_online_node(n) {
+ for_each_node_state(n, N_HIGH_MEMORY) {
cpumask_t tmp;
/* Don't want a node to appear more than once */
@@ -1850,6 +2075,22 @@ static void build_zonelists_in_node_order(pg_data_t *pgdat, int node)
}
/*
+ * Build gfp_thisnode zonelists
+ */
+static void build_thisnode_zonelists(pg_data_t *pgdat)
+{
+ enum zone_type i;
+ int j;
+ struct zonelist *zonelist;
+
+ for (i = 0; i < MAX_NR_ZONES; i++) {
+ zonelist = pgdat->node_zonelists + MAX_NR_ZONES + i;
+ j = build_zonelists_node(pgdat, zonelist, 0, i);
+ zonelist->zones[j] = NULL;
+ }
+}
+
+/*
* Build zonelists ordered by zone and nodes within zones.
* This results in conserving DMA zone[s] until all Normal memory is
* exhausted, but results in overflowing to remote node while memory
@@ -1915,7 +2156,8 @@ static int default_zonelist_order(void)
* If there is a node whose DMA/DMA32 memory is very big area on
* local memory, NODE_ORDER may be suitable.
*/
- average_size = total_size / (num_online_nodes() + 1);
+ average_size = total_size /
+ (nodes_weight(node_states[N_HIGH_MEMORY]) + 1);
for_each_online_node(nid) {
low_kmem_size = 0;
total_size = 0;
@@ -1953,7 +2195,7 @@ static void build_zonelists(pg_data_t *pgdat)
int order = current_zonelist_order;
/* initialize zonelists */
- for (i = 0; i < MAX_NR_ZONES; i++) {
+ for (i = 0; i < MAX_ZONELISTS; i++) {
zonelist = pgdat->node_zonelists + i;
zonelist->zones[0] = NULL;
}
@@ -1998,6 +2240,8 @@ static void build_zonelists(pg_data_t *pgdat)
/* calculate node order -- i.e., DMA last! */
build_zonelists_in_zone_order(pgdat, j);
}
+
+ build_thisnode_zonelists(pgdat);
}
/* Construct the zonelist performance cache - see further mmzone.h */
@@ -2078,8 +2322,10 @@ static int __build_all_zonelists(void *dummy)
int nid;
for_each_online_node(nid) {
- build_zonelists(NODE_DATA(nid));
- build_zonelist_cache(NODE_DATA(nid));
+ pg_data_t *pgdat = NODE_DATA(nid);
+
+ build_zonelists(pgdat);
+ build_zonelist_cache(pgdat);
}
return 0;
}
@@ -2092,15 +2338,29 @@ void build_all_zonelists(void)
__build_all_zonelists(NULL);
cpuset_init_current_mems_allowed();
} else {
- /* we have to stop all cpus to guaranntee there is no user
+ /* we have to stop all cpus to guarantee there is no user
of zonelist */
stop_machine_run(__build_all_zonelists, NULL, NR_CPUS);
/* cpuset refresh routine should be here */
}
vm_total_pages = nr_free_pagecache_pages();
- printk("Built %i zonelists in %s order. Total pages: %ld\n",
+ /*
+ * Disable grouping by mobility if the number of pages in the
+ * system is too low to allow the mechanism to work. It would be
+ * more accurate, but expensive to check per-zone. This check is
+ * made on memory-hotadd so a system can start with mobility
+ * disabled and enable it later
+ */
+ if (vm_total_pages < (pageblock_nr_pages * MIGRATE_TYPES))
+ page_group_by_mobility_disabled = 1;
+ else
+ page_group_by_mobility_disabled = 0;
+
+ printk("Built %i zonelists in %s order, mobility grouping %s. "
+ "Total pages: %ld\n",
num_online_nodes(),
zonelist_order_name[current_zonelist_order],
+ page_group_by_mobility_disabled ? "off" : "on",
vm_total_pages);
#ifdef CONFIG_NUMA
printk("Policy zone: %s\n", zone_names[policy_zone]);
@@ -2176,6 +2436,61 @@ static inline unsigned long wait_table_bits(unsigned long size)
#define LONG_ALIGN(x) (((x)+(sizeof(long))-1)&~((sizeof(long))-1))
/*
+ * Mark a number of pageblocks as MIGRATE_RESERVE. The number
+ * of blocks reserved is based on zone->pages_min. The memory within the
+ * reserve will tend to store contiguous free pages. Setting min_free_kbytes
+ * higher will lead to a bigger reserve which will get freed as contiguous
+ * blocks as reclaim kicks in
+ */
+static void setup_zone_migrate_reserve(struct zone *zone)
+{
+ unsigned long start_pfn, pfn, end_pfn;
+ struct page *page;
+ unsigned long reserve, block_migratetype;
+
+ /* Get the start pfn, end pfn and the number of blocks to reserve */
+ start_pfn = zone->zone_start_pfn;
+ end_pfn = start_pfn + zone->spanned_pages;
+ reserve = roundup(zone->pages_min, pageblock_nr_pages) >>
+ pageblock_order;
+
+ for (pfn = start_pfn; pfn < end_pfn; pfn += pageblock_nr_pages) {
+ if (!pfn_valid(pfn))
+ continue;
+ page = pfn_to_page(pfn);
+
+ /* Blocks with reserved pages will never free, skip them. */
+ if (PageReserved(page))
+ continue;
+
+ block_migratetype = get_pageblock_migratetype(page);
+
+ /* If this block is reserved, account for it */
+ if (reserve > 0 && block_migratetype == MIGRATE_RESERVE) {
+ reserve--;
+ continue;
+ }
+
+ /* Suitable for reserving if this block is movable */
+ if (reserve > 0 && block_migratetype == MIGRATE_MOVABLE) {
+ set_pageblock_migratetype(page, MIGRATE_RESERVE);
+ move_freepages_block(zone, page, MIGRATE_RESERVE);
+ reserve--;
+ continue;
+ }
+
+ /*
+ * If the reserve is met and this is a previous reserved block,
+ * take it back
+ */
+ if (block_migratetype == MIGRATE_RESERVE) {
+ set_pageblock_migratetype(page, MIGRATE_MOVABLE);
+ move_freepages_block(zone, page, MIGRATE_MOVABLE);
+ }
+ }
+}
+
+/*
* Initially all pages are reserved - free ones are freed
* up by free_all_bootmem() once the early boot process is
* done. Non-atomic initialization, single-pass.
@@ -2204,6 +2519,19 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
init_page_count(page);
reset_page_mapcount(page);
SetPageReserved(page);
+
+ /*
+ * Mark the block movable so that blocks are reserved for
+ * movable at startup. This will force kernel allocations
+ * to reserve their blocks rather than leaking throughout
+ * the address space during boot when many long-lived
+ * kernel allocations are made. Later some blocks near
+ * the start are marked MIGRATE_RESERVE by
+ * setup_zone_migrate_reserve()
+ */
+ if ((pfn & (pageblock_nr_pages-1)))
+ set_pageblock_migratetype(page, MIGRATE_MOVABLE);
+
INIT_LIST_HEAD(&page->lru);
#ifdef WANT_PAGE_VIRTUAL
/* The shift won't overflow because ZONE_NORMAL is below 4G. */
@@ -2216,9 +2544,9 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
static void __meminit zone_init_free_lists(struct pglist_data *pgdat,
struct zone *zone, unsigned long size)
{
- int order;
- for (order = 0; order < MAX_ORDER ; order++) {
- INIT_LIST_HEAD(&zone->free_area[order].free_list);
+ int order, t;
+ for_each_migratetype_order(order, t) {
+ INIT_LIST_HEAD(&zone->free_area[order].free_list[t]);
zone->free_area[order].nr_free = 0;
}
}
@@ -2324,6 +2652,9 @@ static struct per_cpu_pageset boot_pageset[NR_CPUS];
static int __cpuinit process_zones(int cpu)
{
struct zone *zone, *dzone;
+ int node = cpu_to_node(cpu);
+
+ node_set_state(node, N_CPU); /* this node has a cpu */
for_each_zone(zone) {
@@ -2331,7 +2662,7 @@ static int __cpuinit process_zones(int cpu)
continue;
zone_pcp(zone, cpu) = kmalloc_node(sizeof(struct per_cpu_pageset),
- GFP_KERNEL, cpu_to_node(cpu));
+ GFP_KERNEL, node);
if (!zone_pcp(zone, cpu))
goto bad;
@@ -2444,7 +2775,7 @@ int zone_wait_table_init(struct zone *zone, unsigned long zone_size_pages)
* To use this new node's memory, further consideration will be
* necessary.
*/
- zone->wait_table = (wait_queue_head_t *)vmalloc(alloc_size);
+ zone->wait_table = vmalloc(alloc_size);
}
if (!zone->wait_table)
return -ENOMEM;
@@ -2513,7 +2844,7 @@ static int __meminit first_active_region_index_in_nid(int nid)
/*
* Basic iterator support. Return the next active range of PFNs for a node
- * Note: nid == MAX_NUMNODES returns next region regardles of node
+ * Note: nid == MAX_NUMNODES returns next region regardless of node
*/
static int __meminit next_active_region_index_in_nid(int index, int nid)
{
@@ -2680,10 +3011,8 @@ void __meminit get_pfn_range_for_nid(unsigned int nid,
*end_pfn = max(*end_pfn, early_node_map[i].end_pfn);
}
- if (*start_pfn == -1UL) {
- printk(KERN_WARNING "Node %u active with no memory\n", nid);
+ if (*start_pfn == -1UL)
*start_pfn = 0;
- }
/* Push the node boundaries out if requested */
account_node_boundary(nid, start_pfn, end_pfn);
@@ -2901,6 +3230,62 @@ static void __meminit calculate_node_totalpages(struct pglist_data *pgdat,
realtotalpages);
}
+#ifndef CONFIG_SPARSEMEM
+/*
+ * Calculate the size of the zone->blockflags rounded to an unsigned long
+ * Start by making sure zonesize is a multiple of pageblock_order by rounding
+ * up. Then use 1 NR_PAGEBLOCK_BITS worth of bits per pageblock, finally
+ * round what is now in bits to nearest long in bits, then return it in
+ * bytes.
+ */
+static unsigned long __init usemap_size(unsigned long zonesize)
+{
+ unsigned long usemapsize;
+
+ usemapsize = roundup(zonesize, pageblock_nr_pages);
+ usemapsize = usemapsize >> pageblock_order;
+ usemapsize *= NR_PAGEBLOCK_BITS;
+ usemapsize = roundup(usemapsize, 8 * sizeof(unsigned long));
+
+ return usemapsize / 8;
+}
+
+static void __init setup_usemap(struct pglist_data *pgdat,
+ struct zone *zone, unsigned long zonesize)
+{
+ unsigned long usemapsize = usemap_size(zonesize);
+ zone->pageblock_flags = NULL;
+ if (usemapsize) {
+ zone->pageblock_flags = alloc_bootmem_node(pgdat, usemapsize);
+ memset(zone->pageblock_flags, 0, usemapsize);
+ }
+}
+#else
+static void inline setup_usemap(struct pglist_data *pgdat,
+ struct zone *zone, unsigned long zonesize) {}
+#endif /* CONFIG_SPARSEMEM */
+
+#ifdef CONFIG_HUGETLB_PAGE_SIZE_VARIABLE
+/* Initialise the number of pages represented by NR_PAGEBLOCK_BITS */
+static inline void __init set_pageblock_order(unsigned int order)
+{
+ /* Check that pageblock_nr_pages has not already been setup */
+ if (pageblock_order)
+ return;
+
+ /*
+ * Assume the largest contiguous order of interest is a huge page.
+ * This value may be variable depending on boot parameters on IA64
+ */
+ pageblock_order = order;
+}
+#else /* CONFIG_HUGETLB_PAGE_SIZE_VARIABLE */
+
+/* Defined this way to avoid accidently referencing HUGETLB_PAGE_ORDER */
+#define set_pageblock_order(x) do {} while (0)
+
+#endif /* CONFIG_HUGETLB_PAGE_SIZE_VARIABLE */
+
/*
* Set up the zone data structures:
* - mark all pages reserved
@@ -2977,10 +3362,12 @@ static void __meminit free_area_init_core(struct pglist_data *pgdat,
zone->nr_scan_active = 0;
zone->nr_scan_inactive = 0;
zap_zone_vm_stats(zone);
- atomic_set(&zone->reclaim_in_progress, 0);
+ zone->flags = 0;
if (!size)
continue;
+ set_pageblock_order(HUGETLB_PAGE_ORDER);
+ setup_usemap(pgdat, zone, size);
ret = init_currently_empty_zone(zone, zone_start_pfn,
size, MEMMAP_EARLY);
BUG_ON(ret);
@@ -3234,16 +3621,24 @@ unsigned long __init find_max_pfn_with_active_regions(void)
return max_pfn;
}
-unsigned long __init early_calculate_totalpages(void)
+/*
+ * early_calculate_totalpages()
+ * Sum pages in active regions for movable zone.
+ * Populate N_HIGH_MEMORY for calculating usable_nodes.
+ */
+static unsigned long __init early_calculate_totalpages(void)
{
int i;
unsigned long totalpages = 0;
- for (i = 0; i < nr_nodemap_entries; i++)
- totalpages += early_node_map[i].end_pfn -
+ for (i = 0; i < nr_nodemap_entries; i++) {
+ unsigned long pages = early_node_map[i].end_pfn -
early_node_map[i].start_pfn;
-
- return totalpages;
+ totalpages += pages;
+ if (pages)
+ node_set_state(early_node_map[i].nid, N_HIGH_MEMORY);
+ }
+ return totalpages;
}
/*
@@ -3257,7 +3652,8 @@ void __init find_zone_movable_pfns_for_nodes(unsigned long *movable_pfn)
int i, nid;
unsigned long usable_startpfn;
unsigned long kernelcore_node, kernelcore_remaining;
- int usable_nodes = num_online_nodes();
+ unsigned long totalpages = early_calculate_totalpages();
+ int usable_nodes = nodes_weight(node_states[N_HIGH_MEMORY]);
/*
* If movablecore was specified, calculate what size of
@@ -3268,7 +3664,6 @@ void __init find_zone_movable_pfns_for_nodes(unsigned long *movable_pfn)
* what movablecore would have allowed.
*/
if (required_movablecore) {
- unsigned long totalpages = early_calculate_totalpages();
unsigned long corepages;
/*
@@ -3293,7 +3688,7 @@ void __init find_zone_movable_pfns_for_nodes(unsigned long *movable_pfn)
restart:
/* Spread kernelcore memory as evenly as possible throughout nodes */
kernelcore_node = required_kernelcore / usable_nodes;
- for_each_online_node(nid) {
+ for_each_node_state(nid, N_HIGH_MEMORY) {
/*
* Recalculate kernelcore_node if the division per node
* now exceeds what is necessary to satisfy the requested
@@ -3385,6 +3780,20 @@ restart:
roundup(zone_movable_pfn[nid], MAX_ORDER_NR_PAGES);
}
+/* Any regular memory on that node ? */
+static void check_for_regular_memory(pg_data_t *pgdat)
+{
+#ifdef CONFIG_HIGHMEM
+ enum zone_type zone_type;
+
+ for (zone_type = 0; zone_type <= ZONE_NORMAL; zone_type++) {
+ struct zone *zone = &pgdat->node_zones[zone_type];
+ if (zone->present_pages)
+ node_set_state(zone_to_nid(zone), N_NORMAL_MEMORY);
+ }
+#endif
+}
+
/**
* free_area_init_nodes - Initialise all pg_data_t and zone data
* @max_zone_pfn: an array of max PFNs for each zone
@@ -3459,6 +3868,11 @@ void __init free_area_init_nodes(unsigned long *max_zone_pfn)
pg_data_t *pgdat = NODE_DATA(nid);
free_area_init_node(nid, pgdat, NULL,
find_min_pfn_for_node(nid), NULL);
+
+ /* Any memory on that node */
+ if (pgdat->node_present_pages)
+ node_set_state(nid, N_HIGH_MEMORY);
+ check_for_regular_memory(pgdat);
}
}
@@ -3673,6 +4087,7 @@ void setup_per_zone_pages_min(void)
zone->pages_low = zone->pages_min + (tmp >> 2);
zone->pages_high = zone->pages_min + (tmp >> 1);
+ setup_zone_migrate_reserve(zone);
spin_unlock_irqrestore(&zone->lru_lock, flags);
}
@@ -3934,4 +4349,169 @@ EXPORT_SYMBOL(pfn_to_page);
EXPORT_SYMBOL(page_to_pfn);
#endif /* CONFIG_OUT_OF_LINE_PFN_TO_PAGE */
+/* Return a pointer to the bitmap storing bits affecting a block of pages */
+static inline unsigned long *get_pageblock_bitmap(struct zone *zone,
+ unsigned long pfn)
+{
+#ifdef CONFIG_SPARSEMEM
+ return __pfn_to_section(pfn)->pageblock_flags;
+#else
+ return zone->pageblock_flags;
+#endif /* CONFIG_SPARSEMEM */
+}
+
+static inline int pfn_to_bitidx(struct zone *zone, unsigned long pfn)
+{
+#ifdef CONFIG_SPARSEMEM
+ pfn &= (PAGES_PER_SECTION-1);
+ return (pfn >> pageblock_order) * NR_PAGEBLOCK_BITS;
+#else
+ pfn = pfn - zone->zone_start_pfn;
+ return (pfn >> pageblock_order) * NR_PAGEBLOCK_BITS;
+#endif /* CONFIG_SPARSEMEM */
+}
+
+/**
+ * get_pageblock_flags_group - Return the requested group of flags for the pageblock_nr_pages block of pages
+ * @page: The page within the block of interest
+ * @start_bitidx: The first bit of interest to retrieve
+ * @end_bitidx: The last bit of interest
+ * returns pageblock_bits flags
+ */
+unsigned long get_pageblock_flags_group(struct page *page,
+ int start_bitidx, int end_bitidx)
+{
+ struct zone *zone;
+ unsigned long *bitmap;
+ unsigned long pfn, bitidx;
+ unsigned long flags = 0;
+ unsigned long value = 1;
+
+ zone = page_zone(page);
+ pfn = page_to_pfn(page);
+ bitmap = get_pageblock_bitmap(zone, pfn);
+ bitidx = pfn_to_bitidx(zone, pfn);
+
+ for (; start_bitidx <= end_bitidx; start_bitidx++, value <<= 1)
+ if (test_bit(bitidx + start_bitidx, bitmap))
+ flags |= value;
+
+ return flags;
+}
+/**
+ * set_pageblock_flags_group - Set the requested group of flags for a pageblock_nr_pages block of pages
+ * @page: The page within the block of interest
+ * @start_bitidx: The first bit of interest
+ * @end_bitidx: The last bit of interest
+ * @flags: The flags to set
+ */
+void set_pageblock_flags_group(struct page *page, unsigned long flags,
+ int start_bitidx, int end_bitidx)
+{
+ struct zone *zone;
+ unsigned long *bitmap;
+ unsigned long pfn, bitidx;
+ unsigned long value = 1;
+
+ zone = page_zone(page);
+ pfn = page_to_pfn(page);
+ bitmap = get_pageblock_bitmap(zone, pfn);
+ bitidx = pfn_to_bitidx(zone, pfn);
+
+ for (; start_bitidx <= end_bitidx; start_bitidx++, value <<= 1)
+ if (flags & value)
+ __set_bit(bitidx + start_bitidx, bitmap);
+ else
+ __clear_bit(bitidx + start_bitidx, bitmap);
+}
+
+/*
+ * This is designed as sub function...plz see page_isolation.c also.
+ * set/clear page block's type to be ISOLATE.
+ * page allocater never alloc memory from ISOLATE block.
+ */
+
+int set_migratetype_isolate(struct page *page)
+{
+ struct zone *zone;
+ unsigned long flags;
+ int ret = -EBUSY;
+
+ zone = page_zone(page);
+ spin_lock_irqsave(&zone->lock, flags);
+ /*
+ * In future, more migrate types will be able to be isolation target.
+ */
+ if (get_pageblock_migratetype(page) != MIGRATE_MOVABLE)
+ goto out;
+ set_pageblock_migratetype(page, MIGRATE_ISOLATE);
+ move_freepages_block(zone, page, MIGRATE_ISOLATE);
+ ret = 0;
+out:
+ spin_unlock_irqrestore(&zone->lock, flags);
+ if (!ret)
+ drain_all_local_pages();
+ return ret;
+}
+
+void unset_migratetype_isolate(struct page *page)
+{
+ struct zone *zone;
+ unsigned long flags;
+ zone = page_zone(page);
+ spin_lock_irqsave(&zone->lock, flags);
+ if (get_pageblock_migratetype(page) != MIGRATE_ISOLATE)
+ goto out;
+ set_pageblock_migratetype(page, MIGRATE_MOVABLE);
+ move_freepages_block(zone, page, MIGRATE_MOVABLE);
+out:
+ spin_unlock_irqrestore(&zone->lock, flags);
+}
+
+#ifdef CONFIG_MEMORY_HOTREMOVE
+/*
+ * All pages in the range must be isolated before calling this.
+ */
+void
+__offline_isolated_pages(unsigned long start_pfn, unsigned long end_pfn)
+{
+ struct page *page;
+ struct zone *zone;
+ int order, i;
+ unsigned long pfn;
+ unsigned long flags;
+ /* find the first valid pfn */
+ for (pfn = start_pfn; pfn < end_pfn; pfn++)
+ if (pfn_valid(pfn))
+ break;
+ if (pfn == end_pfn)
+ return;
+ zone = page_zone(pfn_to_page(pfn));
+ spin_lock_irqsave(&zone->lock, flags);
+ pfn = start_pfn;
+ while (pfn < end_pfn) {
+ if (!pfn_valid(pfn)) {
+ pfn++;
+ continue;
+ }
+ page = pfn_to_page(pfn);
+ BUG_ON(page_count(page));
+ BUG_ON(!PageBuddy(page));
+ order = page_order(page);
+#ifdef CONFIG_DEBUG_VM
+ printk(KERN_INFO "remove from free list %lx %d %lx\n",
+ pfn, 1 << order, end_pfn);
+#endif
+ list_del(&page->lru);
+ rmv_page_order(page);
+ zone->free_area[order].nr_free--;
+ __mod_zone_page_state(zone, NR_FREE_PAGES,
+ - (1UL << order));
+ for (i = 0; i < (1 << order); i++)
+ SetPageReserved((page+i));
+ pfn += (1 << order);
+ }
+ spin_unlock_irqrestore(&zone->lock, flags);
+}
+#endif
diff --git a/mm/page_isolation.c b/mm/page_isolation.c
new file mode 100644
index 000000000000..3444b58033c8
--- /dev/null
+++ b/mm/page_isolation.c
@@ -0,0 +1,138 @@
+/*
+ * linux/mm/page_isolation.c
+ */
+
+#include <stddef.h>
+#include <linux/mm.h>
+#include <linux/page-isolation.h>
+#include <linux/pageblock-flags.h>
+#include "internal.h"
+
+static inline struct page *
+__first_valid_page(unsigned long pfn, unsigned long nr_pages)
+{
+ int i;
+ for (i = 0; i < nr_pages; i++)
+ if (pfn_valid_within(pfn + i))
+ break;
+ if (unlikely(i == nr_pages))
+ return NULL;
+ return pfn_to_page(pfn + i);
+}
+
+/*
+ * start_isolate_page_range() -- make page-allocation-type of range of pages
+ * to be MIGRATE_ISOLATE.
+ * @start_pfn: The lower PFN of the range to be isolated.
+ * @end_pfn: The upper PFN of the range to be isolated.
+ *
+ * Making page-allocation-type to be MIGRATE_ISOLATE means free pages in
+ * the range will never be allocated. Any free pages and pages freed in the
+ * future will not be allocated again.
+ *
+ * start_pfn/end_pfn must be aligned to pageblock_order.
+ * Returns 0 on success and -EBUSY if any part of range cannot be isolated.
+ */
+int
+start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn)
+{
+ unsigned long pfn;
+ unsigned long undo_pfn;
+ struct page *page;
+
+ BUG_ON((start_pfn) & (pageblock_nr_pages - 1));
+ BUG_ON((end_pfn) & (pageblock_nr_pages - 1));
+
+ for (pfn = start_pfn;
+ pfn < end_pfn;
+ pfn += pageblock_nr_pages) {
+ page = __first_valid_page(pfn, pageblock_nr_pages);
+ if (page && set_migratetype_isolate(page)) {
+ undo_pfn = pfn;
+ goto undo;
+ }
+ }
+ return 0;
+undo:
+ for (pfn = start_pfn;
+ pfn < undo_pfn;
+ pfn += pageblock_nr_pages)
+ unset_migratetype_isolate(pfn_to_page(pfn));
+
+ return -EBUSY;
+}
+
+/*
+ * Make isolated pages available again.
+ */
+int
+undo_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn)
+{
+ unsigned long pfn;
+ struct page *page;
+ BUG_ON((start_pfn) & (pageblock_nr_pages - 1));
+ BUG_ON((end_pfn) & (pageblock_nr_pages - 1));
+ for (pfn = start_pfn;
+ pfn < end_pfn;
+ pfn += pageblock_nr_pages) {
+ page = __first_valid_page(pfn, pageblock_nr_pages);
+ if (!page || get_pageblock_migratetype(page) != MIGRATE_ISOLATE)
+ continue;
+ unset_migratetype_isolate(page);
+ }
+ return 0;
+}
+/*
+ * Test all pages in the range is free(means isolated) or not.
+ * all pages in [start_pfn...end_pfn) must be in the same zone.
+ * zone->lock must be held before call this.
+ *
+ * Returns 0 if all pages in the range is isolated.
+ */
+static int
+__test_page_isolated_in_pageblock(unsigned long pfn, unsigned long end_pfn)
+{
+ struct page *page;
+
+ while (pfn < end_pfn) {
+ if (!pfn_valid_within(pfn)) {
+ pfn++;
+ continue;
+ }
+ page = pfn_to_page(pfn);
+ if (PageBuddy(page))
+ pfn += 1 << page_order(page);
+ else if (page_count(page) == 0 &&
+ page_private(page) == MIGRATE_ISOLATE)
+ pfn += 1;
+ else
+ break;
+ }
+ if (pfn < end_pfn)
+ return 0;
+ return 1;
+}
+
+int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn)
+{
+ unsigned long pfn;
+ struct page *page;
+
+ pfn = start_pfn;
+ /*
+ * Note: pageblock_nr_page != MAX_ORDER. Then, chunks of free page
+ * is not aligned to pageblock_nr_pages.
+ * Then we just check pagetype fist.
+ */
+ for (pfn = start_pfn; pfn < end_pfn; pfn += pageblock_nr_pages) {
+ page = __first_valid_page(pfn, pageblock_nr_pages);
+ if (page && get_pageblock_migratetype(page) != MIGRATE_ISOLATE)
+ break;
+ }
+ if (pfn < end_pfn)
+ return -EBUSY;
+ /* Check all pages are free or Marked as ISOLATED */
+ if (__test_page_isolated_in_pageblock(start_pfn, end_pfn))
+ return 0;
+ return -EBUSY;
+}
diff --git a/mm/prio_tree.c b/mm/prio_tree.c
index b4e76c25f953..603ae98d9694 100644
--- a/mm/prio_tree.c
+++ b/mm/prio_tree.c
@@ -34,7 +34,7 @@
* Radix priority search tree for address_space->i_mmap
*
* For each vma that map a unique set of file pages i.e., unique [radix_index,
- * heap_index] value, we have a corresponing priority search tree node. If
+ * heap_index] value, we have a corresponding priority search tree node. If
* multiple vmas have identical [radix_index, heap_index] value, then one of
* them is used as a tree node and others are stored in a vm_set list. The tree
* node points to the first vma (head) of the list using vm_set.head.
diff --git a/mm/readahead.c b/mm/readahead.c
index be20c9d699d3..c9c50ca1ec38 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -22,16 +22,8 @@ void default_unplug_io_fn(struct backing_dev_info *bdi, struct page *page)
}
EXPORT_SYMBOL(default_unplug_io_fn);
-/*
- * Convienent macros for min/max read-ahead pages.
- * Note that MAX_RA_PAGES is rounded down, while MIN_RA_PAGES is rounded up.
- * The latter is necessary for systems with large page size(i.e. 64k).
- */
-#define MAX_RA_PAGES (VM_MAX_READAHEAD*1024 / PAGE_CACHE_SIZE)
-#define MIN_RA_PAGES DIV_ROUND_UP(VM_MIN_READAHEAD*1024, PAGE_CACHE_SIZE)
-
struct backing_dev_info default_backing_dev_info = {
- .ra_pages = MAX_RA_PAGES,
+ .ra_pages = VM_MAX_READAHEAD * 1024 / PAGE_CACHE_SIZE,
.state = 0,
.capabilities = BDI_CAP_MAP_COPY,
.unplug_io_fn = default_unplug_io_fn,
@@ -46,7 +38,7 @@ void
file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping)
{
ra->ra_pages = mapping->backing_dev_info->ra_pages;
- ra->prev_index = -1;
+ ra->prev_pos = -1;
}
EXPORT_SYMBOL_GPL(file_ra_state_init);
@@ -66,28 +58,25 @@ int read_cache_pages(struct address_space *mapping, struct list_head *pages,
int (*filler)(void *, struct page *), void *data)
{
struct page *page;
- struct pagevec lru_pvec;
int ret = 0;
- pagevec_init(&lru_pvec, 0);
-
while (!list_empty(pages)) {
page = list_to_page(pages);
list_del(&page->lru);
- if (add_to_page_cache(page, mapping, page->index, GFP_KERNEL)) {
+ if (add_to_page_cache_lru(page, mapping,
+ page->index, GFP_KERNEL)) {
page_cache_release(page);
continue;
}
+ page_cache_release(page);
+
ret = filler(data, page);
- if (!pagevec_add(&lru_pvec, page))
- __pagevec_lru_add(&lru_pvec);
- if (ret) {
+ if (unlikely(ret)) {
put_pages_list(pages);
break;
}
task_io_account_read(PAGE_CACHE_SIZE);
}
- pagevec_lru_add(&lru_pvec);
return ret;
}
@@ -97,7 +86,6 @@ static int read_pages(struct address_space *mapping, struct file *filp,
struct list_head *pages, unsigned nr_pages)
{
unsigned page_idx;
- struct pagevec lru_pvec;
int ret;
if (mapping->a_ops->readpages) {
@@ -107,19 +95,15 @@ static int read_pages(struct address_space *mapping, struct file *filp,
goto out;
}
- pagevec_init(&lru_pvec, 0);
for (page_idx = 0; page_idx < nr_pages; page_idx++) {
struct page *page = list_to_page(pages);
list_del(&page->lru);
- if (!add_to_page_cache(page, mapping,
+ if (!add_to_page_cache_lru(page, mapping,
page->index, GFP_KERNEL)) {
mapping->a_ops->readpage(filp, page);
- if (!pagevec_add(&lru_pvec, page))
- __pagevec_lru_add(&lru_pvec);
- } else
- page_cache_release(page);
+ }
+ page_cache_release(page);
}
- pagevec_lru_add(&lru_pvec);
ret = 0;
out:
return ret;
@@ -157,20 +141,19 @@ __do_page_cache_readahead(struct address_space *mapping, struct file *filp,
/*
* Preallocate as many pages as we will need.
*/
- read_lock_irq(&mapping->tree_lock);
for (page_idx = 0; page_idx < nr_to_read; page_idx++) {
pgoff_t page_offset = offset + page_idx;
if (page_offset > end_index)
break;
+ rcu_read_lock();
page = radix_tree_lookup(&mapping->page_tree, page_offset);
+ rcu_read_unlock();
if (page)
continue;
- read_unlock_irq(&mapping->tree_lock);
page = page_cache_alloc_cold(mapping);
- read_lock_irq(&mapping->tree_lock);
if (!page)
break;
page->index = page_offset;
@@ -179,7 +162,6 @@ __do_page_cache_readahead(struct address_space *mapping, struct file *filp,
SetPageReadahead(page);
ret++;
}
- read_unlock_irq(&mapping->tree_lock);
/*
* Now start the IO. We ignore I/O errors - if the page is not
@@ -251,6 +233,12 @@ unsigned long max_sane_readahead(unsigned long nr)
+ node_page_state(numa_node_id(), NR_FREE_PAGES)) / 2);
}
+static int __init readahead_init(void)
+{
+ return bdi_init(&default_backing_dev_info);
+}
+subsys_initcall(readahead_init);
+
/*
* Submit IO for the read-ahead request in file_ra_state.
*/
@@ -327,7 +315,7 @@ static unsigned long get_next_ra_size(struct file_ra_state *ra,
* indicator. The flag won't be set on already cached pages, to avoid the
* readahead-for-nothing fuss, saving pointless page cache lookups.
*
- * prev_index tracks the last visited page in the _previous_ read request.
+ * prev_pos tracks the last visited byte in the _previous_ read request.
* It should be maintained by the caller, and will be used for detecting
* small random reads. Note that the readahead algorithm checks loosely
* for sequential patterns. Hence interleaved reads might be served as
@@ -351,11 +339,9 @@ ondemand_readahead(struct address_space *mapping,
bool hit_readahead_marker, pgoff_t offset,
unsigned long req_size)
{
- unsigned long max; /* max readahead pages */
- int sequential;
-
- max = ra->ra_pages;
- sequential = (offset - ra->prev_index <= 1UL) || (req_size > max);
+ int max = ra->ra_pages; /* max readahead pages */
+ pgoff_t prev_offset;
+ int sequential;
/*
* It's the expected callback offset, assume sequential access.
@@ -369,6 +355,9 @@ ondemand_readahead(struct address_space *mapping,
goto readit;
}
+ prev_offset = ra->prev_pos >> PAGE_CACHE_SHIFT;
+ sequential = offset - prev_offset <= 1UL || req_size > max;
+
/*
* Standalone, small read.
* Read as is, and do not pollute the readahead state.
@@ -379,6 +368,29 @@ ondemand_readahead(struct address_space *mapping,
}
/*
+ * Hit a marked page without valid readahead state.
+ * E.g. interleaved reads.
+ * Query the pagecache for async_size, which normally equals to
+ * readahead size. Ramp it up and use it as the new readahead size.
+ */
+ if (hit_readahead_marker) {
+ pgoff_t start;
+
+ read_lock_irq(&mapping->tree_lock);
+ start = radix_tree_next_hole(&mapping->page_tree, offset, max+1);
+ read_unlock_irq(&mapping->tree_lock);
+
+ if (!start || start - offset > max)
+ return 0;
+
+ ra->start = start;
+ ra->size = start - offset; /* old async_size */
+ ra->size = get_next_ra_size(ra, max);
+ ra->async_size = ra->size;
+ goto readit;
+ }
+
+ /*
* It may be one of
* - first read on start of file
* - sequential cache miss
@@ -389,16 +401,6 @@ ondemand_readahead(struct address_space *mapping,
ra->size = get_init_ra_size(req_size, max);
ra->async_size = ra->size > req_size ? ra->size - req_size : ra->size;
- /*
- * Hit on a marked page without valid readahead state.
- * E.g. interleaved reads.
- * Not knowing its readahead pos/size, bet on the minimal possible one.
- */
- if (hit_readahead_marker) {
- ra->start++;
- ra->size = get_next_ra_size(ra, max);
- }
-
readit:
return ra_submit(ra, mapping, filp);
}
diff --git a/mm/rmap.c b/mm/rmap.c
index 41ac39749ef4..dc3be5f5b0da 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -36,6 +36,7 @@
* mapping->tree_lock (widely used, in set_page_dirty,
* in arch-dependent flush_dcache_mmap_lock,
* within inode_lock in __sync_single_inode)
+ * zone->lock (within radix tree node alloc)
*/
#include <linux/mm.h>
@@ -137,8 +138,7 @@ void anon_vma_unlink(struct vm_area_struct *vma)
anon_vma_free(anon_vma);
}
-static void anon_vma_ctor(void *data, struct kmem_cache *cachep,
- unsigned long flags)
+static void anon_vma_ctor(struct kmem_cache *cachep, void *data)
{
struct anon_vma *anon_vma = data;
@@ -183,7 +183,9 @@ static void page_unlock_anon_vma(struct anon_vma *anon_vma)
}
/*
- * At what user virtual address is page expected in vma?
+ * At what user virtual address is page expected in @vma?
+ * Returns virtual address or -EFAULT if page's index/offset is not
+ * within the range mapped the @vma.
*/
static inline unsigned long
vma_address(struct page *page, struct vm_area_struct *vma)
@@ -193,8 +195,7 @@ vma_address(struct page *page, struct vm_area_struct *vma)
address = vma->vm_start + ((pgoff - vma->vm_pgoff) << PAGE_SHIFT);
if (unlikely(address < vma->vm_start || address >= vma->vm_end)) {
- /* page should be within any vma from prio_tree_next */
- BUG_ON(!PageAnon(page));
+ /* page should be within @vma mapping range */
return -EFAULT;
}
return address;
@@ -436,7 +437,6 @@ static int page_mkclean_one(struct page *page, struct vm_area_struct *vma)
entry = pte_wrprotect(entry);
entry = pte_mkclean(entry);
set_pte_at(mm, address, pte, entry);
- lazy_mmu_prot_update(entry);
ret = 1;
}
diff --git a/mm/shmem.c b/mm/shmem.c
index fcd19d323f9f..253d205914ba 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -49,7 +49,6 @@
#include <linux/ctype.h>
#include <linux/migrate.h>
#include <linux/highmem.h>
-#include <linux/backing-dev.h>
#include <asm/uaccess.h>
#include <asm/div64.h>
@@ -96,9 +95,9 @@ static inline struct page *shmem_dir_alloc(gfp_t gfp_mask)
* BLOCKS_PER_PAGE on indirect pages, assume PAGE_CACHE_SIZE:
* might be reconsidered if it ever diverges from PAGE_SIZE.
*
- * __GFP_MOVABLE is masked out as swap vectors cannot move
+ * Mobility flags are masked out as swap vectors cannot move
*/
- return alloc_pages((gfp_mask & ~__GFP_MOVABLE) | __GFP_ZERO,
+ return alloc_pages((gfp_mask & ~GFP_MOVABLE_MASK) | __GFP_ZERO,
PAGE_CACHE_SHIFT-PAGE_SHIFT);
}
@@ -916,6 +915,21 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
struct inode *inode;
BUG_ON(!PageLocked(page));
+ /*
+ * shmem_backing_dev_info's capabilities prevent regular writeback or
+ * sync from ever calling shmem_writepage; but a stacking filesystem
+ * may use the ->writepage of its underlying filesystem, in which case
+ * we want to do nothing when that underlying filesystem is tmpfs
+ * (writing out to swap is useful as a response to memory pressure, but
+ * of no use to stabilize the data) - just redirty the page, unlock it
+ * and claim success in this case. AOP_WRITEPAGE_ACTIVATE, and the
+ * page_mapped check below, must be avoided unless we're in reclaim.
+ */
+ if (!wbc->for_reclaim) {
+ set_page_dirty(page);
+ unlock_page(page);
+ return 0;
+ }
BUG_ON(page_mapped(page));
mapping = page->mapping;
@@ -972,7 +986,7 @@ static inline int shmem_parse_mpol(char *value, int *policy, nodemask_t *policy_
*nodelist++ = '\0';
if (nodelist_parse(nodelist, *policy_nodes))
goto out;
- if (!nodes_subset(*policy_nodes, node_online_map))
+ if (!nodes_subset(*policy_nodes, node_states[N_HIGH_MEMORY]))
goto out;
}
if (!strcmp(value, "default")) {
@@ -997,9 +1011,11 @@ static inline int shmem_parse_mpol(char *value, int *policy, nodemask_t *policy_
err = 0;
} else if (!strcmp(value, "interleave")) {
*policy = MPOL_INTERLEAVE;
- /* Default to nodes online if no nodelist */
+ /*
+ * Default to online nodes with memory if no nodelist
+ */
if (!nodelist)
- *policy_nodes = node_online_map;
+ *policy_nodes = node_states[N_HIGH_MEMORY];
err = 0;
}
out:
@@ -1025,8 +1041,8 @@ static struct page *shmem_swapin_async(struct shared_policy *p,
return page;
}
-struct page *shmem_swapin(struct shmem_inode_info *info, swp_entry_t entry,
- unsigned long idx)
+static struct page *shmem_swapin(struct shmem_inode_info *info,
+ swp_entry_t entry, unsigned long idx)
{
struct shared_policy *p = &info->policy;
int i, num;
@@ -1061,7 +1077,8 @@ shmem_alloc_page(gfp_t gfp, struct shmem_inode_info *info,
return page;
}
#else
-static inline int shmem_parse_mpol(char *value, int *policy, nodemask_t *policy_nodes)
+static inline int shmem_parse_mpol(char *value, int *policy,
+ nodemask_t *policy_nodes)
{
return 1;
}
@@ -1109,7 +1126,7 @@ static int shmem_getpage(struct inode *inode, unsigned long idx,
* Normally, filepage is NULL on entry, and either found
* uptodate immediately, or allocated and zeroed, or read
* in under swappage, which is then assigned to filepage.
- * But shmem_readpage and shmem_prepare_write pass in a locked
+ * But shmem_readpage and shmem_write_begin pass in a locked
* filepage, which may be found not uptodate by other callers
* too, and may need to be copied from the swappage read in.
*/
@@ -1327,14 +1344,14 @@ static int shmem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
}
#ifdef CONFIG_NUMA
-int shmem_set_policy(struct vm_area_struct *vma, struct mempolicy *new)
+static int shmem_set_policy(struct vm_area_struct *vma, struct mempolicy *new)
{
struct inode *i = vma->vm_file->f_path.dentry->d_inode;
return mpol_set_shared_policy(&SHMEM_I(i)->policy, vma, new);
}
-struct mempolicy *
-shmem_get_policy(struct vm_area_struct *vma, unsigned long addr)
+static struct mempolicy *shmem_get_policy(struct vm_area_struct *vma,
+ unsigned long addr)
{
struct inode *i = vma->vm_file->f_path.dentry->d_inode;
unsigned long idx;
@@ -1446,7 +1463,7 @@ static const struct inode_operations shmem_symlink_inode_operations;
static const struct inode_operations shmem_symlink_inline_operations;
/*
- * Normally tmpfs avoids the use of shmem_readpage and shmem_prepare_write;
+ * Normally tmpfs avoids the use of shmem_readpage and shmem_write_begin;
* but providing them allows a tmpfs file to be used for splice, sendfile, and
* below the loop driver, in the generic fashion that many filesystems support.
*/
@@ -1459,10 +1476,30 @@ static int shmem_readpage(struct file *file, struct page *page)
}
static int
-shmem_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
+shmem_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
{
- struct inode *inode = page->mapping->host;
- return shmem_getpage(inode, page->index, &page, SGP_WRITE, NULL);
+ struct inode *inode = mapping->host;
+ pgoff_t index = pos >> PAGE_CACHE_SHIFT;
+ *pagep = NULL;
+ return shmem_getpage(inode, index, pagep, SGP_WRITE, NULL);
+}
+
+static int
+shmem_write_end(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata)
+{
+ struct inode *inode = mapping->host;
+
+ set_page_dirty(page);
+ page_cache_release(page);
+
+ if (pos+copied > inode->i_size)
+ i_size_write(inode, pos+copied);
+
+ return copied;
}
static ssize_t
@@ -1998,33 +2035,25 @@ static int shmem_match(struct inode *ino, void *vfh)
return ino->i_ino == inum && fh[0] == ino->i_generation;
}
-static struct dentry *shmem_get_dentry(struct super_block *sb, void *vfh)
+static struct dentry *shmem_fh_to_dentry(struct super_block *sb,
+ struct fid *fid, int fh_len, int fh_type)
{
- struct dentry *de = NULL;
struct inode *inode;
- __u32 *fh = vfh;
- __u64 inum = fh[2];
- inum = (inum << 32) | fh[1];
+ struct dentry *dentry = NULL;
+ u64 inum = fid->raw[2];
+ inum = (inum << 32) | fid->raw[1];
+
+ if (fh_len < 3)
+ return NULL;
- inode = ilookup5(sb, (unsigned long)(inum+fh[0]), shmem_match, vfh);
+ inode = ilookup5(sb, (unsigned long)(inum + fid->raw[0]),
+ shmem_match, fid->raw);
if (inode) {
- de = d_find_alias(inode);
+ dentry = d_find_alias(inode);
iput(inode);
}
- return de? de: ERR_PTR(-ESTALE);
-}
-
-static struct dentry *shmem_decode_fh(struct super_block *sb, __u32 *fh,
- int len, int type,
- int (*acceptable)(void *context, struct dentry *de),
- void *context)
-{
- if (len < 3)
- return ERR_PTR(-ESTALE);
-
- return sb->s_export_op->find_exported_dentry(sb, fh, NULL, acceptable,
- context);
+ return dentry;
}
static int shmem_encode_fh(struct dentry *dentry, __u32 *fh, int *len,
@@ -2057,11 +2086,10 @@ static int shmem_encode_fh(struct dentry *dentry, __u32 *fh, int *len,
return 1;
}
-static struct export_operations shmem_export_ops = {
+static const struct export_operations shmem_export_ops = {
.get_parent = shmem_get_parent,
- .get_dentry = shmem_get_dentry,
.encode_fh = shmem_encode_fh,
- .decode_fh = shmem_decode_fh,
+ .fh_to_dentry = shmem_fh_to_dentry,
};
static int shmem_parse_options(char *options, int *mode, uid_t *uid,
@@ -2219,7 +2247,7 @@ static int shmem_fill_super(struct super_block *sb,
unsigned long blocks = 0;
unsigned long inodes = 0;
int policy = MPOL_DEFAULT;
- nodemask_t policy_nodes = node_online_map;
+ nodemask_t policy_nodes = node_states[N_HIGH_MEMORY];
#ifdef CONFIG_TMPFS
/*
@@ -2306,8 +2334,7 @@ static void shmem_destroy_inode(struct inode *inode)
kmem_cache_free(shmem_inode_cachep, SHMEM_I(inode));
}
-static void init_once(void *foo, struct kmem_cache *cachep,
- unsigned long flags)
+static void init_once(struct kmem_cache *cachep, void *foo)
{
struct shmem_inode_info *p = (struct shmem_inode_info *) foo;
@@ -2322,9 +2349,7 @@ static int init_inodecache(void)
{
shmem_inode_cachep = kmem_cache_create("shmem_inode_cache",
sizeof(struct shmem_inode_info),
- 0, 0, init_once);
- if (shmem_inode_cachep == NULL)
- return -ENOMEM;
+ 0, SLAB_PANIC, init_once);
return 0;
}
@@ -2338,8 +2363,8 @@ static const struct address_space_operations shmem_aops = {
.set_page_dirty = __set_page_dirty_no_writeback,
#ifdef CONFIG_TMPFS
.readpage = shmem_readpage,
- .prepare_write = shmem_prepare_write,
- .commit_write = simple_commit_write,
+ .write_begin = shmem_write_begin,
+ .write_end = shmem_write_end,
#endif
.migratepage = migrate_page,
};
@@ -2442,6 +2467,10 @@ static int __init init_tmpfs(void)
{
int error;
+ error = bdi_init(&shmem_backing_dev_info);
+ if (error)
+ goto out4;
+
error = init_inodecache();
if (error)
goto out3;
@@ -2466,6 +2495,8 @@ out1:
out2:
destroy_inodecache();
out3:
+ bdi_destroy(&shmem_backing_dev_info);
+out4:
shm_mnt = ERR_PTR(error);
return error;
}
@@ -2518,11 +2549,8 @@ struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags)
d_instantiate(dentry, inode);
inode->i_size = size;
inode->i_nlink = 0; /* It is unlinked */
- file->f_path.mnt = mntget(shm_mnt);
- file->f_path.dentry = dentry;
- file->f_mapping = inode->i_mapping;
- file->f_op = &shmem_file_operations;
- file->f_mode = FMODE_WRITE | FMODE_READ;
+ init_file(file, shm_mnt, dentry, FMODE_WRITE | FMODE_READ,
+ &shmem_file_operations);
return file;
close_file:
diff --git a/mm/slab.c b/mm/slab.c
index 6f6abef83a1a..c31cd3682a0b 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -26,7 +26,7 @@
* initialized objects.
*
* This means, that your constructor is used only for newly allocated
- * slabs and you must pass objects with the same intializations to
+ * slabs and you must pass objects with the same initializations to
* kmem_cache_free.
*
* Each cache can only support one memory type (GFP_DMA, GFP_HIGHMEM,
@@ -267,11 +267,10 @@ struct array_cache {
unsigned int batchcount;
unsigned int touched;
spinlock_t lock;
- void *entry[0]; /*
+ void *entry[]; /*
* Must have this definition in here for the proper
* alignment of array_cache. Also simplifies accessing
* the entries.
- * [0] is for gcc 2.95. It should really be [].
*/
};
@@ -408,7 +407,7 @@ struct kmem_cache {
unsigned int dflags; /* dynamic flags */
/* constructor func */
- void (*ctor) (void *, struct kmem_cache *, unsigned long);
+ void (*ctor)(struct kmem_cache *, void *);
/* 5) cache creation/removal */
const char *name;
@@ -1044,7 +1043,7 @@ static struct array_cache **alloc_alien_cache(int node, int limit)
}
ac_ptr[i] = alloc_arraycache(node, limit, 0xbaadf00d);
if (!ac_ptr[i]) {
- for (i--; i <= 0; i--)
+ for (i--; i >= 0; i--)
kfree(ac_ptr[i]);
kfree(ac_ptr);
return NULL;
@@ -1157,105 +1156,187 @@ static inline int cache_free_alien(struct kmem_cache *cachep, void *objp)
}
#endif
-static int __cpuinit cpuup_callback(struct notifier_block *nfb,
- unsigned long action, void *hcpu)
+static void __cpuinit cpuup_canceled(long cpu)
+{
+ struct kmem_cache *cachep;
+ struct kmem_list3 *l3 = NULL;
+ int node = cpu_to_node(cpu);
+
+ list_for_each_entry(cachep, &cache_chain, next) {
+ struct array_cache *nc;
+ struct array_cache *shared;
+ struct array_cache **alien;
+ cpumask_t mask;
+
+ mask = node_to_cpumask(node);
+ /* cpu is dead; no one can alloc from it. */
+ nc = cachep->array[cpu];
+ cachep->array[cpu] = NULL;
+ l3 = cachep->nodelists[node];
+
+ if (!l3)
+ goto free_array_cache;
+
+ spin_lock_irq(&l3->list_lock);
+
+ /* Free limit for this kmem_list3 */
+ l3->free_limit -= cachep->batchcount;
+ if (nc)
+ free_block(cachep, nc->entry, nc->avail, node);
+
+ if (!cpus_empty(mask)) {
+ spin_unlock_irq(&l3->list_lock);
+ goto free_array_cache;
+ }
+
+ shared = l3->shared;
+ if (shared) {
+ free_block(cachep, shared->entry,
+ shared->avail, node);
+ l3->shared = NULL;
+ }
+
+ alien = l3->alien;
+ l3->alien = NULL;
+
+ spin_unlock_irq(&l3->list_lock);
+
+ kfree(shared);
+ if (alien) {
+ drain_alien_cache(cachep, alien);
+ free_alien_cache(alien);
+ }
+free_array_cache:
+ kfree(nc);
+ }
+ /*
+ * In the previous loop, all the objects were freed to
+ * the respective cache's slabs, now we can go ahead and
+ * shrink each nodelist to its limit.
+ */
+ list_for_each_entry(cachep, &cache_chain, next) {
+ l3 = cachep->nodelists[node];
+ if (!l3)
+ continue;
+ drain_freelist(cachep, l3, l3->free_objects);
+ }
+}
+
+static int __cpuinit cpuup_prepare(long cpu)
{
- long cpu = (long)hcpu;
struct kmem_cache *cachep;
struct kmem_list3 *l3 = NULL;
int node = cpu_to_node(cpu);
const int memsize = sizeof(struct kmem_list3);
- switch (action) {
- case CPU_LOCK_ACQUIRE:
- mutex_lock(&cache_chain_mutex);
- break;
- case CPU_UP_PREPARE:
- case CPU_UP_PREPARE_FROZEN:
+ /*
+ * We need to do this right in the beginning since
+ * alloc_arraycache's are going to use this list.
+ * kmalloc_node allows us to add the slab to the right
+ * kmem_list3 and not this cpu's kmem_list3
+ */
+
+ list_for_each_entry(cachep, &cache_chain, next) {
/*
- * We need to do this right in the beginning since
- * alloc_arraycache's are going to use this list.
- * kmalloc_node allows us to add the slab to the right
- * kmem_list3 and not this cpu's kmem_list3
+ * Set up the size64 kmemlist for cpu before we can
+ * begin anything. Make sure some other cpu on this
+ * node has not already allocated this
*/
+ if (!cachep->nodelists[node]) {
+ l3 = kmalloc_node(memsize, GFP_KERNEL, node);
+ if (!l3)
+ goto bad;
+ kmem_list3_init(l3);
+ l3->next_reap = jiffies + REAPTIMEOUT_LIST3 +
+ ((unsigned long)cachep) % REAPTIMEOUT_LIST3;
- list_for_each_entry(cachep, &cache_chain, next) {
/*
- * Set up the size64 kmemlist for cpu before we can
- * begin anything. Make sure some other cpu on this
- * node has not already allocated this
+ * The l3s don't come and go as CPUs come and
+ * go. cache_chain_mutex is sufficient
+ * protection here.
*/
- if (!cachep->nodelists[node]) {
- l3 = kmalloc_node(memsize, GFP_KERNEL, node);
- if (!l3)
- goto bad;
- kmem_list3_init(l3);
- l3->next_reap = jiffies + REAPTIMEOUT_LIST3 +
- ((unsigned long)cachep) % REAPTIMEOUT_LIST3;
-
- /*
- * The l3s don't come and go as CPUs come and
- * go. cache_chain_mutex is sufficient
- * protection here.
- */
- cachep->nodelists[node] = l3;
- }
-
- spin_lock_irq(&cachep->nodelists[node]->list_lock);
- cachep->nodelists[node]->free_limit =
- (1 + nr_cpus_node(node)) *
- cachep->batchcount + cachep->num;
- spin_unlock_irq(&cachep->nodelists[node]->list_lock);
+ cachep->nodelists[node] = l3;
}
- /*
- * Now we can go ahead with allocating the shared arrays and
- * array caches
- */
- list_for_each_entry(cachep, &cache_chain, next) {
- struct array_cache *nc;
- struct array_cache *shared = NULL;
- struct array_cache **alien = NULL;
-
- nc = alloc_arraycache(node, cachep->limit,
- cachep->batchcount);
- if (!nc)
+ spin_lock_irq(&cachep->nodelists[node]->list_lock);
+ cachep->nodelists[node]->free_limit =
+ (1 + nr_cpus_node(node)) *
+ cachep->batchcount + cachep->num;
+ spin_unlock_irq(&cachep->nodelists[node]->list_lock);
+ }
+
+ /*
+ * Now we can go ahead with allocating the shared arrays and
+ * array caches
+ */
+ list_for_each_entry(cachep, &cache_chain, next) {
+ struct array_cache *nc;
+ struct array_cache *shared = NULL;
+ struct array_cache **alien = NULL;
+
+ nc = alloc_arraycache(node, cachep->limit,
+ cachep->batchcount);
+ if (!nc)
+ goto bad;
+ if (cachep->shared) {
+ shared = alloc_arraycache(node,
+ cachep->shared * cachep->batchcount,
+ 0xbaadf00d);
+ if (!shared) {
+ kfree(nc);
goto bad;
- if (cachep->shared) {
- shared = alloc_arraycache(node,
- cachep->shared * cachep->batchcount,
- 0xbaadf00d);
- if (!shared)
- goto bad;
}
- if (use_alien_caches) {
- alien = alloc_alien_cache(node, cachep->limit);
- if (!alien)
- goto bad;
- }
- cachep->array[cpu] = nc;
- l3 = cachep->nodelists[node];
- BUG_ON(!l3);
-
- spin_lock_irq(&l3->list_lock);
- if (!l3->shared) {
- /*
- * We are serialised from CPU_DEAD or
- * CPU_UP_CANCELLED by the cpucontrol lock
- */
- l3->shared = shared;
- shared = NULL;
+ }
+ if (use_alien_caches) {
+ alien = alloc_alien_cache(node, cachep->limit);
+ if (!alien) {
+ kfree(shared);
+ kfree(nc);
+ goto bad;
}
+ }
+ cachep->array[cpu] = nc;
+ l3 = cachep->nodelists[node];
+ BUG_ON(!l3);
+
+ spin_lock_irq(&l3->list_lock);
+ if (!l3->shared) {
+ /*
+ * We are serialised from CPU_DEAD or
+ * CPU_UP_CANCELLED by the cpucontrol lock
+ */
+ l3->shared = shared;
+ shared = NULL;
+ }
#ifdef CONFIG_NUMA
- if (!l3->alien) {
- l3->alien = alien;
- alien = NULL;
- }
-#endif
- spin_unlock_irq(&l3->list_lock);
- kfree(shared);
- free_alien_cache(alien);
+ if (!l3->alien) {
+ l3->alien = alien;
+ alien = NULL;
}
+#endif
+ spin_unlock_irq(&l3->list_lock);
+ kfree(shared);
+ free_alien_cache(alien);
+ }
+ return 0;
+bad:
+ cpuup_canceled(cpu);
+ return -ENOMEM;
+}
+
+static int __cpuinit cpuup_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ long cpu = (long)hcpu;
+ int err = 0;
+
+ switch (action) {
+ case CPU_LOCK_ACQUIRE:
+ mutex_lock(&cache_chain_mutex);
+ break;
+ case CPU_UP_PREPARE:
+ case CPU_UP_PREPARE_FROZEN:
+ err = cpuup_prepare(cpu);
break;
case CPU_ONLINE:
case CPU_ONLINE_FROZEN:
@@ -1288,76 +1369,17 @@ static int __cpuinit cpuup_callback(struct notifier_block *nfb,
* structure is usually allocated from kmem_cache_create() and
* gets destroyed at kmem_cache_destroy().
*/
- /* fall thru */
+ /* fall through */
#endif
case CPU_UP_CANCELED:
case CPU_UP_CANCELED_FROZEN:
- list_for_each_entry(cachep, &cache_chain, next) {
- struct array_cache *nc;
- struct array_cache *shared;
- struct array_cache **alien;
- cpumask_t mask;
-
- mask = node_to_cpumask(node);
- /* cpu is dead; no one can alloc from it. */
- nc = cachep->array[cpu];
- cachep->array[cpu] = NULL;
- l3 = cachep->nodelists[node];
-
- if (!l3)
- goto free_array_cache;
-
- spin_lock_irq(&l3->list_lock);
-
- /* Free limit for this kmem_list3 */
- l3->free_limit -= cachep->batchcount;
- if (nc)
- free_block(cachep, nc->entry, nc->avail, node);
-
- if (!cpus_empty(mask)) {
- spin_unlock_irq(&l3->list_lock);
- goto free_array_cache;
- }
-
- shared = l3->shared;
- if (shared) {
- free_block(cachep, shared->entry,
- shared->avail, node);
- l3->shared = NULL;
- }
-
- alien = l3->alien;
- l3->alien = NULL;
-
- spin_unlock_irq(&l3->list_lock);
-
- kfree(shared);
- if (alien) {
- drain_alien_cache(cachep, alien);
- free_alien_cache(alien);
- }
-free_array_cache:
- kfree(nc);
- }
- /*
- * In the previous loop, all the objects were freed to
- * the respective cache's slabs, now we can go ahead and
- * shrink each nodelist to its limit.
- */
- list_for_each_entry(cachep, &cache_chain, next) {
- l3 = cachep->nodelists[node];
- if (!l3)
- continue;
- drain_freelist(cachep, l3, l3->free_objects);
- }
+ cpuup_canceled(cpu);
break;
case CPU_LOCK_RELEASE:
mutex_unlock(&cache_chain_mutex);
break;
}
- return NOTIFY_OK;
-bad:
- return NOTIFY_BAD;
+ return err ? NOTIFY_BAD : NOTIFY_OK;
}
static struct notifier_block __cpuinitdata cpucache_notifier = {
@@ -1568,7 +1590,7 @@ void __init kmem_cache_init(void)
/* Replace the static kmem_list3 structures for the boot cpu */
init_list(&cache_cache, &initkmem_list3[CACHE_CACHE], node);
- for_each_online_node(nid) {
+ for_each_node_state(nid, N_NORMAL_MEMORY) {
init_list(malloc_sizes[INDEX_AC].cs_cachep,
&initkmem_list3[SIZE_AC + nid], nid);
@@ -1643,6 +1665,8 @@ static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid)
#endif
flags |= cachep->gfpflags;
+ if (cachep->flags & SLAB_RECLAIM_ACCOUNT)
+ flags |= __GFP_RECLAIMABLE;
page = alloc_pages_node(nodeid, flags, cachep->gfporder);
if (!page)
@@ -1944,7 +1968,7 @@ static void __init set_up_list3s(struct kmem_cache *cachep, int index)
{
int node;
- for_each_online_node(node) {
+ for_each_node_state(node, N_NORMAL_MEMORY) {
cachep->nodelists[node] = &initkmem_list3[index + node];
cachep->nodelists[node]->next_reap = jiffies +
REAPTIMEOUT_LIST3 +
@@ -2075,7 +2099,7 @@ static int __init_refok setup_cpu_cache(struct kmem_cache *cachep)
g_cpucache_up = PARTIAL_L3;
} else {
int node;
- for_each_online_node(node) {
+ for_each_node_state(node, N_NORMAL_MEMORY) {
cachep->nodelists[node] =
kmalloc_node(sizeof(struct kmem_list3),
GFP_KERNEL, node);
@@ -2127,7 +2151,7 @@ static int __init_refok setup_cpu_cache(struct kmem_cache *cachep)
struct kmem_cache *
kmem_cache_create (const char *name, size_t size, size_t align,
unsigned long flags,
- void (*ctor)(void*, struct kmem_cache *, unsigned long))
+ void (*ctor)(struct kmem_cache *, void *))
{
size_t left_over, slab_size, ralign;
struct kmem_cache *cachep = NULL, *pc;
@@ -2634,8 +2658,7 @@ static void cache_init_objs(struct kmem_cache *cachep,
* They must also be threaded.
*/
if (cachep->ctor && !(cachep->flags & SLAB_POISON))
- cachep->ctor(objp + obj_offset(cachep), cachep,
- 0);
+ cachep->ctor(cachep, objp + obj_offset(cachep));
if (cachep->flags & SLAB_RED_ZONE) {
if (*dbg_redzone2(cachep, objp) != RED_INACTIVE)
@@ -2651,7 +2674,7 @@ static void cache_init_objs(struct kmem_cache *cachep,
cachep->buffer_size / PAGE_SIZE, 0);
#else
if (cachep->ctor)
- cachep->ctor(objp, cachep, 0);
+ cachep->ctor(cachep, objp);
#endif
slab_bufctl(slabp)[i] = i + 1;
}
@@ -2746,9 +2769,9 @@ static int cache_grow(struct kmem_cache *cachep,
* Be lazy and only check for valid flags here, keeping it out of the
* critical path in kmem_cache_alloc().
*/
- BUG_ON(flags & ~(GFP_DMA | __GFP_ZERO | GFP_LEVEL_MASK));
+ BUG_ON(flags & GFP_SLAB_BUG_MASK);
+ local_flags = flags & (GFP_CONSTRAINT_MASK|GFP_RECLAIM_MASK);
- local_flags = (flags & GFP_LEVEL_MASK);
/* Take the l3 list lock to change the colour_next on this node */
check_irq_off();
l3 = cachep->nodelists[nodeid];
@@ -2785,7 +2808,7 @@ static int cache_grow(struct kmem_cache *cachep,
/* Get slab management. */
slabp = alloc_slabmgmt(cachep, objp, offset,
- local_flags & ~GFP_THISNODE, nodeid);
+ local_flags & ~GFP_CONSTRAINT_MASK, nodeid);
if (!slabp)
goto opps1;
@@ -3076,7 +3099,7 @@ static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep,
#endif
objp += obj_offset(cachep);
if (cachep->ctor && cachep->flags & SLAB_POISON)
- cachep->ctor(objp, cachep, 0);
+ cachep->ctor(cachep, objp);
#if ARCH_SLAB_MINALIGN
if ((u32)objp & (ARCH_SLAB_MINALIGN-1)) {
printk(KERN_ERR "0x%p: not aligned to ARCH_SLAB_MINALIGN=%d\n",
@@ -3225,7 +3248,7 @@ static void *fallback_alloc(struct kmem_cache *cache, gfp_t flags)
zonelist = &NODE_DATA(slab_node(current->mempolicy))
->node_zonelists[gfp_zone(flags)];
- local_flags = (flags & GFP_LEVEL_MASK);
+ local_flags = flags & (GFP_CONSTRAINT_MASK|GFP_RECLAIM_MASK);
retry:
/*
@@ -3783,7 +3806,7 @@ const char *kmem_cache_name(struct kmem_cache *cachep)
EXPORT_SYMBOL_GPL(kmem_cache_name);
/*
- * This initializes kmem_list3 or resizes varioius caches for all nodes.
+ * This initializes kmem_list3 or resizes various caches for all nodes.
*/
static int alloc_kmemlist(struct kmem_cache *cachep)
{
@@ -3792,7 +3815,7 @@ static int alloc_kmemlist(struct kmem_cache *cachep)
struct array_cache *new_shared;
struct array_cache **new_alien = NULL;
- for_each_online_node(node) {
+ for_each_node_state(node, N_NORMAL_MEMORY) {
if (use_alien_caches) {
new_alien = alloc_alien_cache(node, cachep->limit);
@@ -4446,7 +4469,8 @@ const struct seq_operations slabstats_op = {
*/
size_t ksize(const void *objp)
{
- if (unlikely(ZERO_OR_NULL_PTR(objp)))
+ BUG_ON(!objp);
+ if (unlikely(objp == ZERO_SIZE_PTR))
return 0;
return obj_size(virt_to_cache(objp));
diff --git a/mm/slob.c b/mm/slob.c
index ec33fcdc852e..08a9bd91a1aa 100644
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -321,7 +321,8 @@ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node)
/* Improve fragment distribution and reduce our average
* search time by starting our next search here. (see
* Knuth vol 1, sec 2.5, pg 449) */
- if (free_slob_pages.next != prev->next)
+ if (prev != free_slob_pages.prev &&
+ free_slob_pages.next != prev->next)
list_move_tail(&free_slob_pages, prev->next);
break;
}
@@ -360,7 +361,7 @@ static void slob_free(void *block, int size)
slobidx_t units;
unsigned long flags;
- if (ZERO_OR_NULL_PTR(block))
+ if (unlikely(ZERO_OR_NULL_PTR(block)))
return;
BUG_ON(!size);
@@ -466,7 +467,7 @@ void kfree(const void *block)
{
struct slob_page *sp;
- if (ZERO_OR_NULL_PTR(block))
+ if (unlikely(ZERO_OR_NULL_PTR(block)))
return;
sp = (struct slob_page *)virt_to_page(block);
@@ -484,7 +485,8 @@ size_t ksize(const void *block)
{
struct slob_page *sp;
- if (ZERO_OR_NULL_PTR(block))
+ BUG_ON(!block);
+ if (unlikely(block == ZERO_SIZE_PTR))
return 0;
sp = (struct slob_page *)virt_to_page(block);
@@ -498,12 +500,12 @@ struct kmem_cache {
unsigned int size, align;
unsigned long flags;
const char *name;
- void (*ctor)(void *, struct kmem_cache *, unsigned long);
+ void (*ctor)(struct kmem_cache *, void *);
};
struct kmem_cache *kmem_cache_create(const char *name, size_t size,
size_t align, unsigned long flags,
- void (*ctor)(void*, struct kmem_cache *, unsigned long))
+ void (*ctor)(struct kmem_cache *, void *))
{
struct kmem_cache *c;
@@ -547,7 +549,7 @@ void *kmem_cache_alloc_node(struct kmem_cache *c, gfp_t flags, int node)
b = slob_new_page(flags, get_order(c->size), node);
if (c->ctor)
- c->ctor(b, c, 0);
+ c->ctor(c, b);
return b;
}
diff --git a/mm/slub.c b/mm/slub.c
index addb20a6d67d..9acb413858ac 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -20,6 +20,7 @@
#include <linux/mempolicy.h>
#include <linux/ctype.h>
#include <linux/kallsyms.h>
+#include <linux/memory.h>
/*
* Lock order:
@@ -90,7 +91,7 @@
* One use of this flag is to mark slabs that are
* used for allocations. Then such a slab becomes a cpu
* slab. The cpu slab may be equipped with an additional
- * lockless_freelist that allows lockless access to
+ * freelist that allows lockless access to
* free objects in addition to the regular freelist
* that requires the slab lock.
*
@@ -140,11 +141,6 @@ static inline void ClearSlabDebug(struct page *page)
/*
* Issues still to be resolved:
*
- * - The per cpu array is updated for each new slab and and is a remote
- * cacheline for most nodes. This could become a bouncing cacheline given
- * enough frequent updates. There are 16 pointers in a cacheline, so at
- * max 16 cpus could compete for the cacheline which may be okay.
- *
* - Support PAGE_ALLOC_DEBUG. Should be easy to do.
*
* - Variable sizing of the per node arrays
@@ -205,11 +201,6 @@ static inline void ClearSlabDebug(struct page *page)
#define ARCH_SLAB_MINALIGN __alignof__(unsigned long long)
#endif
-/*
- * The page->inuse field is 16 bit thus we have this limitation
- */
-#define MAX_OBJECTS_PER_SLAB 65535
-
/* Internal SLUB flags */
#define __OBJECT_POISON 0x80000000 /* Poison object */
#define __SYSFS_ADD_DEFERRED 0x40000000 /* Not yet visible via sysfs */
@@ -277,6 +268,15 @@ static inline struct kmem_cache_node *get_node(struct kmem_cache *s, int node)
#endif
}
+static inline struct kmem_cache_cpu *get_cpu_slab(struct kmem_cache *s, int cpu)
+{
+#ifdef CONFIG_SMP
+ return s->cpu_slab[cpu];
+#else
+ return &s->cpu_slab;
+#endif
+}
+
static inline int check_valid_pointer(struct kmem_cache *s,
struct page *page, const void *object)
{
@@ -729,11 +729,6 @@ static int check_slab(struct kmem_cache *s, struct page *page)
slab_err(s, page, "Not a valid slab page");
return 0;
}
- if (page->offset * sizeof(void *) != s->offset) {
- slab_err(s, page, "Corrupted offset %lu",
- (unsigned long)(page->offset * sizeof(void *)));
- return 0;
- }
if (page->inuse > s->objects) {
slab_err(s, page, "inuse %u > max %u",
s->name, page->inuse, s->objects);
@@ -872,8 +867,6 @@ bad:
slab_fix(s, "Marking all objects used");
page->inuse = s->objects;
page->freelist = NULL;
- /* Fix up fields that may be corrupted */
- page->offset = s->offset / sizeof(void *);
}
return 0;
}
@@ -988,7 +981,7 @@ __setup("slub_debug", setup_slub_debug);
static unsigned long kmem_cache_flags(unsigned long objsize,
unsigned long flags, const char *name,
- void (*ctor)(void *, struct kmem_cache *, unsigned long))
+ void (*ctor)(struct kmem_cache *, void *))
{
/*
* The page->offset field is only 16 bit wide. This is an offset
@@ -1035,7 +1028,7 @@ static inline int check_object(struct kmem_cache *s, struct page *page,
static inline void add_full(struct kmem_cache_node *n, struct page *page) {}
static inline unsigned long kmem_cache_flags(unsigned long objsize,
unsigned long flags, const char *name,
- void (*ctor)(void *, struct kmem_cache *, unsigned long))
+ void (*ctor)(struct kmem_cache *, void *))
{
return flags;
}
@@ -1055,6 +1048,9 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node)
if (s->flags & SLAB_CACHE_DMA)
flags |= SLUB_DMA;
+ if (s->flags & SLAB_RECLAIM_ACCOUNT)
+ flags |= __GFP_RECLAIMABLE;
+
if (node == -1)
page = alloc_pages(flags, s->order);
else
@@ -1076,7 +1072,7 @@ static void setup_object(struct kmem_cache *s, struct page *page,
{
setup_object_debug(s, page, object);
if (unlikely(s->ctor))
- s->ctor(object, s, 0);
+ s->ctor(s, object);
}
static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
@@ -1084,23 +1080,19 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
struct page *page;
struct kmem_cache_node *n;
void *start;
- void *end;
void *last;
void *p;
- BUG_ON(flags & ~(GFP_DMA | __GFP_ZERO | GFP_LEVEL_MASK));
-
- if (flags & __GFP_WAIT)
- local_irq_enable();
+ BUG_ON(flags & GFP_SLAB_BUG_MASK);
- page = allocate_slab(s, flags & GFP_LEVEL_MASK, node);
+ page = allocate_slab(s,
+ flags & (GFP_RECLAIM_MASK | GFP_CONSTRAINT_MASK), node);
if (!page)
goto out;
n = get_node(s, page_to_nid(page));
if (n)
atomic_long_inc(&n->nr_slabs);
- page->offset = s->offset / sizeof(void *);
page->slab = s;
page->flags |= 1 << PG_slab;
if (s->flags & (SLAB_DEBUG_FREE | SLAB_RED_ZONE | SLAB_POISON |
@@ -1108,7 +1100,6 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
SetSlabDebug(page);
start = page_address(page);
- end = start + s->objects * s->size;
if (unlikely(s->flags & SLAB_POISON))
memset(start, POISON_INUSE, PAGE_SIZE << s->order);
@@ -1123,11 +1114,8 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
set_freepointer(s, last, NULL);
page->freelist = start;
- page->lockless_freelist = NULL;
page->inuse = 0;
out:
- if (flags & __GFP_WAIT)
- local_irq_disable();
return page;
}
@@ -1149,7 +1137,6 @@ static void __free_slab(struct kmem_cache *s, struct page *page)
NR_SLAB_RECLAIMABLE : NR_SLAB_UNRECLAIMABLE,
- pages);
- page->mapping = NULL;
__free_pages(page, s->order);
}
@@ -1383,33 +1370,34 @@ static void unfreeze_slab(struct kmem_cache *s, struct page *page)
/*
* Remove the cpu slab
*/
-static void deactivate_slab(struct kmem_cache *s, struct page *page, int cpu)
+static void deactivate_slab(struct kmem_cache *s, struct kmem_cache_cpu *c)
{
+ struct page *page = c->page;
/*
* Merge cpu freelist into freelist. Typically we get here
* because both freelists are empty. So this is unlikely
* to occur.
*/
- while (unlikely(page->lockless_freelist)) {
+ while (unlikely(c->freelist)) {
void **object;
/* Retrieve object from cpu_freelist */
- object = page->lockless_freelist;
- page->lockless_freelist = page->lockless_freelist[page->offset];
+ object = c->freelist;
+ c->freelist = c->freelist[c->offset];
/* And put onto the regular freelist */
- object[page->offset] = page->freelist;
+ object[c->offset] = page->freelist;
page->freelist = object;
page->inuse--;
}
- s->cpu_slab[cpu] = NULL;
+ c->page = NULL;
unfreeze_slab(s, page);
}
-static inline void flush_slab(struct kmem_cache *s, struct page *page, int cpu)
+static inline void flush_slab(struct kmem_cache *s, struct kmem_cache_cpu *c)
{
- slab_lock(page);
- deactivate_slab(s, page, cpu);
+ slab_lock(c->page);
+ deactivate_slab(s, c);
}
/*
@@ -1418,18 +1406,17 @@ static inline void flush_slab(struct kmem_cache *s, struct page *page, int cpu)
*/
static inline void __flush_cpu_slab(struct kmem_cache *s, int cpu)
{
- struct page *page = s->cpu_slab[cpu];
+ struct kmem_cache_cpu *c = get_cpu_slab(s, cpu);
- if (likely(page))
- flush_slab(s, page, cpu);
+ if (likely(c && c->page))
+ flush_slab(s, c);
}
static void flush_cpu_slab(void *d)
{
struct kmem_cache *s = d;
- int cpu = smp_processor_id();
- __flush_cpu_slab(s, cpu);
+ __flush_cpu_slab(s, smp_processor_id());
}
static void flush_all(struct kmem_cache *s)
@@ -1446,6 +1433,19 @@ static void flush_all(struct kmem_cache *s)
}
/*
+ * Check if the objects in a per cpu structure fit numa
+ * locality expectations.
+ */
+static inline int node_match(struct kmem_cache_cpu *c, int node)
+{
+#ifdef CONFIG_NUMA
+ if (node != -1 && c->node != node)
+ return 0;
+#endif
+ return 1;
+}
+
+/*
* Slow path. The lockless freelist is empty or we need to perform
* debugging duties.
*
@@ -1463,80 +1463,69 @@ static void flush_all(struct kmem_cache *s)
* we need to allocate a new slab. This is slowest path since we may sleep.
*/
static void *__slab_alloc(struct kmem_cache *s,
- gfp_t gfpflags, int node, void *addr, struct page *page)
+ gfp_t gfpflags, int node, void *addr, struct kmem_cache_cpu *c)
{
void **object;
- int cpu = smp_processor_id();
+ struct page *new;
- if (!page)
+ if (!c->page)
goto new_slab;
- slab_lock(page);
- if (unlikely(node != -1 && page_to_nid(page) != node))
+ slab_lock(c->page);
+ if (unlikely(!node_match(c, node)))
goto another_slab;
load_freelist:
- object = page->freelist;
+ object = c->page->freelist;
if (unlikely(!object))
goto another_slab;
- if (unlikely(SlabDebug(page)))
+ if (unlikely(SlabDebug(c->page)))
goto debug;
- object = page->freelist;
- page->lockless_freelist = object[page->offset];
- page->inuse = s->objects;
- page->freelist = NULL;
- slab_unlock(page);
+ object = c->page->freelist;
+ c->freelist = object[c->offset];
+ c->page->inuse = s->objects;
+ c->page->freelist = NULL;
+ c->node = page_to_nid(c->page);
+ slab_unlock(c->page);
return object;
another_slab:
- deactivate_slab(s, page, cpu);
+ deactivate_slab(s, c);
new_slab:
- page = get_partial(s, gfpflags, node);
- if (page) {
- s->cpu_slab[cpu] = page;
+ new = get_partial(s, gfpflags, node);
+ if (new) {
+ c->page = new;
goto load_freelist;
}
- page = new_slab(s, gfpflags, node);
- if (page) {
- cpu = smp_processor_id();
- if (s->cpu_slab[cpu]) {
- /*
- * Someone else populated the cpu_slab while we
- * enabled interrupts, or we have gotten scheduled
- * on another cpu. The page may not be on the
- * requested node even if __GFP_THISNODE was
- * specified. So we need to recheck.
- */
- if (node == -1 ||
- page_to_nid(s->cpu_slab[cpu]) == node) {
- /*
- * Current cpuslab is acceptable and we
- * want the current one since its cache hot
- */
- discard_slab(s, page);
- page = s->cpu_slab[cpu];
- slab_lock(page);
- goto load_freelist;
- }
- /* New slab does not fit our expectations */
- flush_slab(s, s->cpu_slab[cpu], cpu);
- }
- slab_lock(page);
- SetSlabFrozen(page);
- s->cpu_slab[cpu] = page;
+ if (gfpflags & __GFP_WAIT)
+ local_irq_enable();
+
+ new = new_slab(s, gfpflags, node);
+
+ if (gfpflags & __GFP_WAIT)
+ local_irq_disable();
+
+ if (new) {
+ c = get_cpu_slab(s, smp_processor_id());
+ if (c->page)
+ flush_slab(s, c);
+ slab_lock(new);
+ SetSlabFrozen(new);
+ c->page = new;
goto load_freelist;
}
return NULL;
debug:
- object = page->freelist;
- if (!alloc_debug_processing(s, page, object, addr))
+ object = c->page->freelist;
+ if (!alloc_debug_processing(s, c->page, object, addr))
goto another_slab;
- page->inuse++;
- page->freelist = object[page->offset];
- slab_unlock(page);
+ c->page->inuse++;
+ c->page->freelist = object[c->offset];
+ c->node = -1;
+ slab_unlock(c->page);
return object;
}
@@ -1553,25 +1542,24 @@ debug:
static void __always_inline *slab_alloc(struct kmem_cache *s,
gfp_t gfpflags, int node, void *addr)
{
- struct page *page;
void **object;
unsigned long flags;
+ struct kmem_cache_cpu *c;
local_irq_save(flags);
- page = s->cpu_slab[smp_processor_id()];
- if (unlikely(!page || !page->lockless_freelist ||
- (node != -1 && page_to_nid(page) != node)))
+ c = get_cpu_slab(s, smp_processor_id());
+ if (unlikely(!c->freelist || !node_match(c, node)))
- object = __slab_alloc(s, gfpflags, node, addr, page);
+ object = __slab_alloc(s, gfpflags, node, addr, c);
else {
- object = page->lockless_freelist;
- page->lockless_freelist = object[page->offset];
+ object = c->freelist;
+ c->freelist = object[c->offset];
}
local_irq_restore(flags);
if (unlikely((gfpflags & __GFP_ZERO) && object))
- memset(object, 0, s->objsize);
+ memset(object, 0, c->objsize);
return object;
}
@@ -1599,7 +1587,7 @@ EXPORT_SYMBOL(kmem_cache_alloc_node);
* handling required then we can return immediately.
*/
static void __slab_free(struct kmem_cache *s, struct page *page,
- void *x, void *addr)
+ void *x, void *addr, unsigned int offset)
{
void *prior;
void **object = (void *)x;
@@ -1609,7 +1597,7 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
if (unlikely(SlabDebug(page)))
goto debug;
checks_ok:
- prior = object[page->offset] = page->freelist;
+ prior = object[offset] = page->freelist;
page->freelist = object;
page->inuse--;
@@ -1664,15 +1652,16 @@ static void __always_inline slab_free(struct kmem_cache *s,
{
void **object = (void *)x;
unsigned long flags;
+ struct kmem_cache_cpu *c;
local_irq_save(flags);
debug_check_no_locks_freed(object, s->objsize);
- if (likely(page == s->cpu_slab[smp_processor_id()] &&
- !SlabDebug(page))) {
- object[page->offset] = page->lockless_freelist;
- page->lockless_freelist = object;
+ c = get_cpu_slab(s, smp_processor_id());
+ if (likely(page == c->page && c->node >= 0)) {
+ object[c->offset] = c->freelist;
+ c->freelist = object;
} else
- __slab_free(s, page, x, addr);
+ __slab_free(s, page, x, addr, c->offset);
local_irq_restore(flags);
}
@@ -1759,14 +1748,6 @@ static inline int slab_order(int size, int min_objects,
int rem;
int min_order = slub_min_order;
- /*
- * If we would create too many object per slab then reduce
- * the slab order even if it goes below slub_min_order.
- */
- while (min_order > 0 &&
- (PAGE_SIZE << min_order) >= MAX_OBJECTS_PER_SLAB * size)
- min_order--;
-
for (order = max(min_order,
fls(min_objects * size - 1) - PAGE_SHIFT);
order <= max_order; order++) {
@@ -1781,9 +1762,6 @@ static inline int slab_order(int size, int min_objects,
if (rem <= slab_size / fract_leftover)
break;
- /* If the next size is too high then exit now */
- if (slab_size * 2 >= MAX_OBJECTS_PER_SLAB * size)
- break;
}
return order;
@@ -1858,6 +1836,16 @@ static unsigned long calculate_alignment(unsigned long flags,
return ALIGN(align, sizeof(void *));
}
+static void init_kmem_cache_cpu(struct kmem_cache *s,
+ struct kmem_cache_cpu *c)
+{
+ c->page = NULL;
+ c->freelist = NULL;
+ c->node = 0;
+ c->offset = s->offset / sizeof(void *);
+ c->objsize = s->objsize;
+}
+
static void init_kmem_cache_node(struct kmem_cache_node *n)
{
n->nr_partial = 0;
@@ -1869,6 +1857,131 @@ static void init_kmem_cache_node(struct kmem_cache_node *n)
#endif
}
+#ifdef CONFIG_SMP
+/*
+ * Per cpu array for per cpu structures.
+ *
+ * The per cpu array places all kmem_cache_cpu structures from one processor
+ * close together meaning that it becomes possible that multiple per cpu
+ * structures are contained in one cacheline. This may be particularly
+ * beneficial for the kmalloc caches.
+ *
+ * A desktop system typically has around 60-80 slabs. With 100 here we are
+ * likely able to get per cpu structures for all caches from the array defined
+ * here. We must be able to cover all kmalloc caches during bootstrap.
+ *
+ * If the per cpu array is exhausted then fall back to kmalloc
+ * of individual cachelines. No sharing is possible then.
+ */
+#define NR_KMEM_CACHE_CPU 100
+
+static DEFINE_PER_CPU(struct kmem_cache_cpu,
+ kmem_cache_cpu)[NR_KMEM_CACHE_CPU];
+
+static DEFINE_PER_CPU(struct kmem_cache_cpu *, kmem_cache_cpu_free);
+static cpumask_t kmem_cach_cpu_free_init_once = CPU_MASK_NONE;
+
+static struct kmem_cache_cpu *alloc_kmem_cache_cpu(struct kmem_cache *s,
+ int cpu, gfp_t flags)
+{
+ struct kmem_cache_cpu *c = per_cpu(kmem_cache_cpu_free, cpu);
+
+ if (c)
+ per_cpu(kmem_cache_cpu_free, cpu) =
+ (void *)c->freelist;
+ else {
+ /* Table overflow: So allocate ourselves */
+ c = kmalloc_node(
+ ALIGN(sizeof(struct kmem_cache_cpu), cache_line_size()),
+ flags, cpu_to_node(cpu));
+ if (!c)
+ return NULL;
+ }
+
+ init_kmem_cache_cpu(s, c);
+ return c;
+}
+
+static void free_kmem_cache_cpu(struct kmem_cache_cpu *c, int cpu)
+{
+ if (c < per_cpu(kmem_cache_cpu, cpu) ||
+ c > per_cpu(kmem_cache_cpu, cpu) + NR_KMEM_CACHE_CPU) {
+ kfree(c);
+ return;
+ }
+ c->freelist = (void *)per_cpu(kmem_cache_cpu_free, cpu);
+ per_cpu(kmem_cache_cpu_free, cpu) = c;
+}
+
+static void free_kmem_cache_cpus(struct kmem_cache *s)
+{
+ int cpu;
+
+ for_each_online_cpu(cpu) {
+ struct kmem_cache_cpu *c = get_cpu_slab(s, cpu);
+
+ if (c) {
+ s->cpu_slab[cpu] = NULL;
+ free_kmem_cache_cpu(c, cpu);
+ }
+ }
+}
+
+static int alloc_kmem_cache_cpus(struct kmem_cache *s, gfp_t flags)
+{
+ int cpu;
+
+ for_each_online_cpu(cpu) {
+ struct kmem_cache_cpu *c = get_cpu_slab(s, cpu);
+
+ if (c)
+ continue;
+
+ c = alloc_kmem_cache_cpu(s, cpu, flags);
+ if (!c) {
+ free_kmem_cache_cpus(s);
+ return 0;
+ }
+ s->cpu_slab[cpu] = c;
+ }
+ return 1;
+}
+
+/*
+ * Initialize the per cpu array.
+ */
+static void init_alloc_cpu_cpu(int cpu)
+{
+ int i;
+
+ if (cpu_isset(cpu, kmem_cach_cpu_free_init_once))
+ return;
+
+ for (i = NR_KMEM_CACHE_CPU - 1; i >= 0; i--)
+ free_kmem_cache_cpu(&per_cpu(kmem_cache_cpu, cpu)[i], cpu);
+
+ cpu_set(cpu, kmem_cach_cpu_free_init_once);
+}
+
+static void __init init_alloc_cpu(void)
+{
+ int cpu;
+
+ for_each_online_cpu(cpu)
+ init_alloc_cpu_cpu(cpu);
+ }
+
+#else
+static inline void free_kmem_cache_cpus(struct kmem_cache *s) {}
+static inline void init_alloc_cpu(void) {}
+
+static inline int alloc_kmem_cache_cpus(struct kmem_cache *s, gfp_t flags)
+{
+ init_kmem_cache_cpu(s, &s->cpu_slab);
+ return 1;
+}
+#endif
+
#ifdef CONFIG_NUMA
/*
* No kmalloc_node yet so do it by hand. We know that this is the first
@@ -1876,10 +1989,11 @@ static void init_kmem_cache_node(struct kmem_cache_node *n)
* possible.
*
* Note that this function only works on the kmalloc_node_cache
- * when allocating for the kmalloc_node_cache.
+ * when allocating for the kmalloc_node_cache. This is used for bootstrapping
+ * memory on a fresh node that has no slab structures yet.
*/
-static struct kmem_cache_node * __init early_kmem_cache_node_alloc(gfp_t gfpflags,
- int node)
+static struct kmem_cache_node *early_kmem_cache_node_alloc(gfp_t gfpflags,
+ int node)
{
struct page *page;
struct kmem_cache_node *n;
@@ -1908,12 +2022,6 @@ static struct kmem_cache_node * __init early_kmem_cache_node_alloc(gfp_t gfpflag
init_kmem_cache_node(n);
atomic_long_inc(&n->nr_slabs);
add_partial(n, page);
-
- /*
- * new_slab() disables interupts. If we do not reenable interrupts here
- * then bootup would continue with interrupts disabled.
- */
- local_irq_enable();
return n;
}
@@ -1921,7 +2029,7 @@ static void free_kmem_cache_nodes(struct kmem_cache *s)
{
int node;
- for_each_online_node(node) {
+ for_each_node_state(node, N_NORMAL_MEMORY) {
struct kmem_cache_node *n = s->node[node];
if (n && n != &s->local_node)
kmem_cache_free(kmalloc_caches, n);
@@ -1939,7 +2047,7 @@ static int init_kmem_cache_nodes(struct kmem_cache *s, gfp_t gfpflags)
else
local_node = 0;
- for_each_online_node(node) {
+ for_each_node_state(node, N_NORMAL_MEMORY) {
struct kmem_cache_node *n;
if (local_node == node)
@@ -2077,21 +2185,14 @@ static int calculate_sizes(struct kmem_cache *s)
*/
s->objects = (PAGE_SIZE << s->order) / size;
- /*
- * Verify that the number of objects is within permitted limits.
- * The page->inuse field is only 16 bit wide! So we cannot have
- * more than 64k objects per slab.
- */
- if (!s->objects || s->objects > MAX_OBJECTS_PER_SLAB)
- return 0;
- return 1;
+ return !!s->objects;
}
static int kmem_cache_open(struct kmem_cache *s, gfp_t gfpflags,
const char *name, size_t size,
size_t align, unsigned long flags,
- void (*ctor)(void *, struct kmem_cache *, unsigned long))
+ void (*ctor)(struct kmem_cache *, void *))
{
memset(s, 0, kmem_size);
s->name = name;
@@ -2107,9 +2208,12 @@ static int kmem_cache_open(struct kmem_cache *s, gfp_t gfpflags,
#ifdef CONFIG_NUMA
s->defrag_ratio = 100;
#endif
+ if (!init_kmem_cache_nodes(s, gfpflags & ~SLUB_DMA))
+ goto error;
- if (init_kmem_cache_nodes(s, gfpflags & ~SLUB_DMA))
+ if (alloc_kmem_cache_cpus(s, gfpflags & ~SLUB_DMA))
return 1;
+ free_kmem_cache_nodes(s);
error:
if (flags & SLAB_PANIC)
panic("Cannot create slab %s size=%lu realsize=%u "
@@ -2192,7 +2296,8 @@ static inline int kmem_cache_close(struct kmem_cache *s)
flush_all(s);
/* Attempt to free all objects */
- for_each_online_node(node) {
+ free_kmem_cache_cpus(s);
+ for_each_node_state(node, N_NORMAL_MEMORY) {
struct kmem_cache_node *n = get_node(s, node);
n->nr_partial -= free_list(s, n, &n->partial);
@@ -2227,11 +2332,11 @@ EXPORT_SYMBOL(kmem_cache_destroy);
* Kmalloc subsystem
*******************************************************************/
-struct kmem_cache kmalloc_caches[KMALLOC_SHIFT_HIGH + 1] __cacheline_aligned;
+struct kmem_cache kmalloc_caches[PAGE_SHIFT] __cacheline_aligned;
EXPORT_SYMBOL(kmalloc_caches);
#ifdef CONFIG_ZONE_DMA
-static struct kmem_cache *kmalloc_caches_dma[KMALLOC_SHIFT_HIGH + 1];
+static struct kmem_cache *kmalloc_caches_dma[PAGE_SHIFT];
#endif
static int __init setup_slub_min_order(char *str)
@@ -2397,12 +2502,8 @@ static struct kmem_cache *get_slab(size_t size, gfp_t flags)
return ZERO_SIZE_PTR;
index = size_index[(size - 1) / 8];
- } else {
- if (size > KMALLOC_MAX_SIZE)
- return NULL;
-
+ } else
index = fls(size - 1);
- }
#ifdef CONFIG_ZONE_DMA
if (unlikely((flags & SLUB_DMA)))
@@ -2414,9 +2515,15 @@ static struct kmem_cache *get_slab(size_t size, gfp_t flags)
void *__kmalloc(size_t size, gfp_t flags)
{
- struct kmem_cache *s = get_slab(size, flags);
+ struct kmem_cache *s;
+
+ if (unlikely(size > PAGE_SIZE / 2))
+ return (void *)__get_free_pages(flags | __GFP_COMP,
+ get_order(size));
+
+ s = get_slab(size, flags);
- if (ZERO_OR_NULL_PTR(s))
+ if (unlikely(ZERO_OR_NULL_PTR(s)))
return s;
return slab_alloc(s, flags, -1, __builtin_return_address(0));
@@ -2426,9 +2533,15 @@ EXPORT_SYMBOL(__kmalloc);
#ifdef CONFIG_NUMA
void *__kmalloc_node(size_t size, gfp_t flags, int node)
{
- struct kmem_cache *s = get_slab(size, flags);
+ struct kmem_cache *s;
+
+ if (unlikely(size > PAGE_SIZE / 2))
+ return (void *)__get_free_pages(flags | __GFP_COMP,
+ get_order(size));
- if (ZERO_OR_NULL_PTR(s))
+ s = get_slab(size, flags);
+
+ if (unlikely(ZERO_OR_NULL_PTR(s)))
return s;
return slab_alloc(s, flags, node, __builtin_return_address(0));
@@ -2441,7 +2554,8 @@ size_t ksize(const void *object)
struct page *page;
struct kmem_cache *s;
- if (ZERO_OR_NULL_PTR(object))
+ BUG_ON(!object);
+ if (unlikely(object == ZERO_SIZE_PTR))
return 0;
page = get_object_page(object);
@@ -2473,22 +2587,17 @@ EXPORT_SYMBOL(ksize);
void kfree(const void *x)
{
- struct kmem_cache *s;
struct page *page;
- /*
- * This has to be an unsigned comparison. According to Linus
- * some gcc version treat a pointer as a signed entity. Then
- * this comparison would be true for all "negative" pointers
- * (which would cover the whole upper half of the address space).
- */
- if (ZERO_OR_NULL_PTR(x))
+ if (unlikely(ZERO_OR_NULL_PTR(x)))
return;
page = virt_to_head_page(x);
- s = page->slab;
-
- slab_free(s, page, (void *)x, __builtin_return_address(0));
+ if (unlikely(!PageSlab(page))) {
+ put_page(page);
+ return;
+ }
+ slab_free(page->slab, page, (void *)x, __builtin_return_address(0));
}
EXPORT_SYMBOL(kfree);
@@ -2517,7 +2626,7 @@ int kmem_cache_shrink(struct kmem_cache *s)
return -ENOMEM;
flush_all(s);
- for_each_online_node(node) {
+ for_each_node_state(node, N_NORMAL_MEMORY) {
n = get_node(s, node);
if (!n->nr_partial)
@@ -2566,6 +2675,121 @@ int kmem_cache_shrink(struct kmem_cache *s)
}
EXPORT_SYMBOL(kmem_cache_shrink);
+#if defined(CONFIG_NUMA) && defined(CONFIG_MEMORY_HOTPLUG)
+static int slab_mem_going_offline_callback(void *arg)
+{
+ struct kmem_cache *s;
+
+ down_read(&slub_lock);
+ list_for_each_entry(s, &slab_caches, list)
+ kmem_cache_shrink(s);
+ up_read(&slub_lock);
+
+ return 0;
+}
+
+static void slab_mem_offline_callback(void *arg)
+{
+ struct kmem_cache_node *n;
+ struct kmem_cache *s;
+ struct memory_notify *marg = arg;
+ int offline_node;
+
+ offline_node = marg->status_change_nid;
+
+ /*
+ * If the node still has available memory. we need kmem_cache_node
+ * for it yet.
+ */
+ if (offline_node < 0)
+ return;
+
+ down_read(&slub_lock);
+ list_for_each_entry(s, &slab_caches, list) {
+ n = get_node(s, offline_node);
+ if (n) {
+ /*
+ * if n->nr_slabs > 0, slabs still exist on the node
+ * that is going down. We were unable to free them,
+ * and offline_pages() function shoudn't call this
+ * callback. So, we must fail.
+ */
+ BUG_ON(atomic_long_read(&n->nr_slabs));
+
+ s->node[offline_node] = NULL;
+ kmem_cache_free(kmalloc_caches, n);
+ }
+ }
+ up_read(&slub_lock);
+}
+
+static int slab_mem_going_online_callback(void *arg)
+{
+ struct kmem_cache_node *n;
+ struct kmem_cache *s;
+ struct memory_notify *marg = arg;
+ int nid = marg->status_change_nid;
+ int ret = 0;
+
+ /*
+ * If the node's memory is already available, then kmem_cache_node is
+ * already created. Nothing to do.
+ */
+ if (nid < 0)
+ return 0;
+
+ /*
+ * We are bringing a node online. No memory is availabe yet. We must
+ * allocate a kmem_cache_node structure in order to bring the node
+ * online.
+ */
+ down_read(&slub_lock);
+ list_for_each_entry(s, &slab_caches, list) {
+ /*
+ * XXX: kmem_cache_alloc_node will fallback to other nodes
+ * since memory is not yet available from the node that
+ * is brought up.
+ */
+ n = kmem_cache_alloc(kmalloc_caches, GFP_KERNEL);
+ if (!n) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ init_kmem_cache_node(n);
+ s->node[nid] = n;
+ }
+out:
+ up_read(&slub_lock);
+ return ret;
+}
+
+static int slab_memory_callback(struct notifier_block *self,
+ unsigned long action, void *arg)
+{
+ int ret = 0;
+
+ switch (action) {
+ case MEM_GOING_ONLINE:
+ ret = slab_mem_going_online_callback(arg);
+ break;
+ case MEM_GOING_OFFLINE:
+ ret = slab_mem_going_offline_callback(arg);
+ break;
+ case MEM_OFFLINE:
+ case MEM_CANCEL_ONLINE:
+ slab_mem_offline_callback(arg);
+ break;
+ case MEM_ONLINE:
+ case MEM_CANCEL_OFFLINE:
+ break;
+ }
+
+ ret = notifier_from_errno(ret);
+ return ret;
+}
+
+#endif /* CONFIG_MEMORY_HOTPLUG */
+
/********************************************************************
* Basic setup of slabs
*******************************************************************/
@@ -2575,6 +2799,8 @@ void __init kmem_cache_init(void)
int i;
int caches = 0;
+ init_alloc_cpu();
+
#ifdef CONFIG_NUMA
/*
* Must first have the slab cache available for the allocations of the
@@ -2585,6 +2811,8 @@ void __init kmem_cache_init(void)
sizeof(struct kmem_cache_node), GFP_KERNEL);
kmalloc_caches[0].refcount = -1;
caches++;
+
+ hotplug_memory_notifier(slab_memory_callback, 1);
#endif
/* Able to allocate the per node structures */
@@ -2602,7 +2830,7 @@ void __init kmem_cache_init(void)
caches++;
}
- for (i = KMALLOC_SHIFT_LOW; i <= KMALLOC_SHIFT_HIGH; i++) {
+ for (i = KMALLOC_SHIFT_LOW; i < PAGE_SHIFT; i++) {
create_kmalloc_cache(&kmalloc_caches[i],
"kmalloc", 1 << i, GFP_KERNEL);
caches++;
@@ -2629,16 +2857,18 @@ void __init kmem_cache_init(void)
slab_state = UP;
/* Provide the correct kmalloc names now that the caches are up */
- for (i = KMALLOC_SHIFT_LOW; i <= KMALLOC_SHIFT_HIGH; i++)
+ for (i = KMALLOC_SHIFT_LOW; i < PAGE_SHIFT; i++)
kmalloc_caches[i]. name =
kasprintf(GFP_KERNEL, "kmalloc-%d", 1 << i);
#ifdef CONFIG_SMP
register_cpu_notifier(&slab_notifier);
+ kmem_size = offsetof(struct kmem_cache, cpu_slab) +
+ nr_cpu_ids * sizeof(struct kmem_cache_cpu *);
+#else
+ kmem_size = sizeof(struct kmem_cache);
#endif
- kmem_size = offsetof(struct kmem_cache, cpu_slab) +
- nr_cpu_ids * sizeof(struct page *);
printk(KERN_INFO "SLUB: Genslabs=%d, HWalign=%d, Order=%d-%d, MinObjects=%d,"
" CPUs=%d, Nodes=%d\n",
@@ -2669,7 +2899,7 @@ static int slab_unmergeable(struct kmem_cache *s)
static struct kmem_cache *find_mergeable(size_t size,
size_t align, unsigned long flags, const char *name,
- void (*ctor)(void *, struct kmem_cache *, unsigned long))
+ void (*ctor)(struct kmem_cache *, void *))
{
struct kmem_cache *s;
@@ -2710,19 +2940,28 @@ static struct kmem_cache *find_mergeable(size_t size,
struct kmem_cache *kmem_cache_create(const char *name, size_t size,
size_t align, unsigned long flags,
- void (*ctor)(void *, struct kmem_cache *, unsigned long))
+ void (*ctor)(struct kmem_cache *, void *))
{
struct kmem_cache *s;
down_write(&slub_lock);
s = find_mergeable(size, align, flags, name, ctor);
if (s) {
+ int cpu;
+
s->refcount++;
/*
* Adjust the object sizes so that we clear
* the complete object on kzalloc.
*/
s->objsize = max(s->objsize, (int)size);
+
+ /*
+ * And then we need to update the object size in the
+ * per cpu structures
+ */
+ for_each_online_cpu(cpu)
+ get_cpu_slab(s, cpu)->objsize = s->objsize;
s->inuse = max_t(int, s->inuse, ALIGN(size, sizeof(void *)));
up_write(&slub_lock);
if (sysfs_slab_alias(s, name))
@@ -2765,15 +3004,29 @@ static int __cpuinit slab_cpuup_callback(struct notifier_block *nfb,
unsigned long flags;
switch (action) {
+ case CPU_UP_PREPARE:
+ case CPU_UP_PREPARE_FROZEN:
+ init_alloc_cpu_cpu(cpu);
+ down_read(&slub_lock);
+ list_for_each_entry(s, &slab_caches, list)
+ s->cpu_slab[cpu] = alloc_kmem_cache_cpu(s, cpu,
+ GFP_KERNEL);
+ up_read(&slub_lock);
+ break;
+
case CPU_UP_CANCELED:
case CPU_UP_CANCELED_FROZEN:
case CPU_DEAD:
case CPU_DEAD_FROZEN:
down_read(&slub_lock);
list_for_each_entry(s, &slab_caches, list) {
+ struct kmem_cache_cpu *c = get_cpu_slab(s, cpu);
+
local_irq_save(flags);
__flush_cpu_slab(s, cpu);
local_irq_restore(flags);
+ free_kmem_cache_cpu(c, cpu);
+ s->cpu_slab[cpu] = NULL;
}
up_read(&slub_lock);
break;
@@ -2790,9 +3043,14 @@ static struct notifier_block __cpuinitdata slab_notifier =
void *__kmalloc_track_caller(size_t size, gfp_t gfpflags, void *caller)
{
- struct kmem_cache *s = get_slab(size, gfpflags);
+ struct kmem_cache *s;
+
+ if (unlikely(size > PAGE_SIZE / 2))
+ return (void *)__get_free_pages(gfpflags | __GFP_COMP,
+ get_order(size));
+ s = get_slab(size, gfpflags);
- if (ZERO_OR_NULL_PTR(s))
+ if (unlikely(ZERO_OR_NULL_PTR(s)))
return s;
return slab_alloc(s, gfpflags, -1, caller);
@@ -2801,9 +3059,14 @@ void *__kmalloc_track_caller(size_t size, gfp_t gfpflags, void *caller)
void *__kmalloc_node_track_caller(size_t size, gfp_t gfpflags,
int node, void *caller)
{
- struct kmem_cache *s = get_slab(size, gfpflags);
+ struct kmem_cache *s;
+
+ if (unlikely(size > PAGE_SIZE / 2))
+ return (void *)__get_free_pages(gfpflags | __GFP_COMP,
+ get_order(size));
+ s = get_slab(size, gfpflags);
- if (ZERO_OR_NULL_PTR(s))
+ if (unlikely(ZERO_OR_NULL_PTR(s)))
return s;
return slab_alloc(s, gfpflags, node, caller);
@@ -2902,7 +3165,7 @@ static long validate_slab_cache(struct kmem_cache *s)
return -ENOMEM;
flush_all(s);
- for_each_online_node(node) {
+ for_each_node_state(node, N_NORMAL_MEMORY) {
struct kmem_cache_node *n = get_node(s, node);
count += validate_slab_node(s, n, map);
@@ -3116,13 +3379,13 @@ static int list_locations(struct kmem_cache *s, char *buf,
int node;
if (!alloc_loc_track(&t, PAGE_SIZE / sizeof(struct location),
- GFP_KERNEL))
+ GFP_TEMPORARY))
return sprintf(buf, "Out of memory\n");
/* Push back cpu slabs */
flush_all(s);
- for_each_online_node(node) {
+ for_each_node_state(node, N_NORMAL_MEMORY) {
struct kmem_cache_node *n = get_node(s, node);
unsigned long flags;
struct page *page;
@@ -3230,11 +3493,18 @@ static unsigned long slab_objects(struct kmem_cache *s,
per_cpu = nodes + nr_node_ids;
for_each_possible_cpu(cpu) {
- struct page *page = s->cpu_slab[cpu];
+ struct page *page;
int node;
+ struct kmem_cache_cpu *c = get_cpu_slab(s, cpu);
+
+ if (!c)
+ continue;
+ page = c->page;
+ node = c->node;
+ if (node < 0)
+ continue;
if (page) {
- node = page_to_nid(page);
if (flags & SO_CPU) {
int x = 0;
@@ -3249,7 +3519,7 @@ static unsigned long slab_objects(struct kmem_cache *s,
}
}
- for_each_online_node(node) {
+ for_each_node_state(node, N_NORMAL_MEMORY) {
struct kmem_cache_node *n = get_node(s, node);
if (flags & SO_PARTIAL) {
@@ -3277,7 +3547,7 @@ static unsigned long slab_objects(struct kmem_cache *s,
x = sprintf(buf, "%lu", total);
#ifdef CONFIG_NUMA
- for_each_online_node(node)
+ for_each_node_state(node, N_NORMAL_MEMORY)
if (nodes[node])
x += sprintf(buf + x, " N%d=%lu",
node, nodes[node]);
@@ -3291,13 +3561,19 @@ static int any_slab_objects(struct kmem_cache *s)
int node;
int cpu;
- for_each_possible_cpu(cpu)
- if (s->cpu_slab[cpu])
+ for_each_possible_cpu(cpu) {
+ struct kmem_cache_cpu *c = get_cpu_slab(s, cpu);
+
+ if (c && c->page)
return 1;
+ }
- for_each_node(node) {
+ for_each_online_node(node) {
struct kmem_cache_node *n = get_node(s, node);
+ if (!n)
+ continue;
+
if (n->nr_partial || atomic_long_read(&n->nr_slabs))
return 1;
}
diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c
new file mode 100644
index 000000000000..22620f6a976b
--- /dev/null
+++ b/mm/sparse-vmemmap.c
@@ -0,0 +1,149 @@
+/*
+ * Virtual Memory Map support
+ *
+ * (C) 2007 sgi. Christoph Lameter <clameter@sgi.com>.
+ *
+ * Virtual memory maps allow VM primitives pfn_to_page, page_to_pfn,
+ * virt_to_page, page_address() to be implemented as a base offset
+ * calculation without memory access.
+ *
+ * However, virtual mappings need a page table and TLBs. Many Linux
+ * architectures already map their physical space using 1-1 mappings
+ * via TLBs. For those arches the virtual memmory map is essentially
+ * for free if we use the same page size as the 1-1 mappings. In that
+ * case the overhead consists of a few additional pages that are
+ * allocated to create a view of memory for vmemmap.
+ *
+ * The architecture is expected to provide a vmemmap_populate() function
+ * to instantiate the mapping.
+ */
+#include <linux/mm.h>
+#include <linux/mmzone.h>
+#include <linux/bootmem.h>
+#include <linux/highmem.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/vmalloc.h>
+#include <linux/sched.h>
+#include <asm/dma.h>
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+
+/*
+ * Allocate a block of memory to be used to back the virtual memory map
+ * or to back the page tables that are used to create the mapping.
+ * Uses the main allocators if they are available, else bootmem.
+ */
+void * __meminit vmemmap_alloc_block(unsigned long size, int node)
+{
+ /* If the main allocator is up use that, fallback to bootmem. */
+ if (slab_is_available()) {
+ struct page *page = alloc_pages_node(node,
+ GFP_KERNEL | __GFP_ZERO, get_order(size));
+ if (page)
+ return page_address(page);
+ return NULL;
+ } else
+ return __alloc_bootmem_node(NODE_DATA(node), size, size,
+ __pa(MAX_DMA_ADDRESS));
+}
+
+void __meminit vmemmap_verify(pte_t *pte, int node,
+ unsigned long start, unsigned long end)
+{
+ unsigned long pfn = pte_pfn(*pte);
+ int actual_node = early_pfn_to_nid(pfn);
+
+ if (actual_node != node)
+ printk(KERN_WARNING "[%lx-%lx] potential offnode "
+ "page_structs\n", start, end - 1);
+}
+
+pte_t * __meminit vmemmap_pte_populate(pmd_t *pmd, unsigned long addr, int node)
+{
+ pte_t *pte = pte_offset_kernel(pmd, addr);
+ if (pte_none(*pte)) {
+ pte_t entry;
+ void *p = vmemmap_alloc_block(PAGE_SIZE, node);
+ if (!p)
+ return 0;
+ entry = pfn_pte(__pa(p) >> PAGE_SHIFT, PAGE_KERNEL);
+ set_pte_at(&init_mm, addr, pte, entry);
+ }
+ return pte;
+}
+
+pmd_t * __meminit vmemmap_pmd_populate(pud_t *pud, unsigned long addr, int node)
+{
+ pmd_t *pmd = pmd_offset(pud, addr);
+ if (pmd_none(*pmd)) {
+ void *p = vmemmap_alloc_block(PAGE_SIZE, node);
+ if (!p)
+ return 0;
+ pmd_populate_kernel(&init_mm, pmd, p);
+ }
+ return pmd;
+}
+
+pud_t * __meminit vmemmap_pud_populate(pgd_t *pgd, unsigned long addr, int node)
+{
+ pud_t *pud = pud_offset(pgd, addr);
+ if (pud_none(*pud)) {
+ void *p = vmemmap_alloc_block(PAGE_SIZE, node);
+ if (!p)
+ return 0;
+ pud_populate(&init_mm, pud, p);
+ }
+ return pud;
+}
+
+pgd_t * __meminit vmemmap_pgd_populate(unsigned long addr, int node)
+{
+ pgd_t *pgd = pgd_offset_k(addr);
+ if (pgd_none(*pgd)) {
+ void *p = vmemmap_alloc_block(PAGE_SIZE, node);
+ if (!p)
+ return 0;
+ pgd_populate(&init_mm, pgd, p);
+ }
+ return pgd;
+}
+
+int __meminit vmemmap_populate_basepages(struct page *start_page,
+ unsigned long size, int node)
+{
+ unsigned long addr = (unsigned long)start_page;
+ unsigned long end = (unsigned long)(start_page + size);
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte;
+
+ for (; addr < end; addr += PAGE_SIZE) {
+ pgd = vmemmap_pgd_populate(addr, node);
+ if (!pgd)
+ return -ENOMEM;
+ pud = vmemmap_pud_populate(pgd, addr, node);
+ if (!pud)
+ return -ENOMEM;
+ pmd = vmemmap_pmd_populate(pud, addr, node);
+ if (!pmd)
+ return -ENOMEM;
+ pte = vmemmap_pte_populate(pmd, addr, node);
+ if (!pte)
+ return -ENOMEM;
+ vmemmap_verify(pte, node, addr, addr + PAGE_SIZE);
+ }
+
+ return 0;
+}
+
+struct page * __meminit sparse_mem_map_populate(unsigned long pnum, int nid)
+{
+ struct page *map = pfn_to_page(pnum * PAGES_PER_SECTION);
+ int error = vmemmap_populate(map, PAGES_PER_SECTION, nid);
+ if (error)
+ return NULL;
+
+ return map;
+}
diff --git a/mm/sparse.c b/mm/sparse.c
index 239f5a720d38..e06f514fe04f 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -9,6 +9,8 @@
#include <linux/spinlock.h>
#include <linux/vmalloc.h>
#include <asm/dma.h>
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
/*
* Permanent SPARSEMEM data:
@@ -106,7 +108,7 @@ static inline int sparse_index_init(unsigned long section_nr, int nid)
/*
* Although written for the SPARSEMEM_EXTREME case, this happens
- * to also work for the flat array case becase
+ * to also work for the flat array case because
* NR_SECTION_ROOTS==NR_MEM_SECTIONS.
*/
int __section_nr(struct mem_section* ms)
@@ -176,7 +178,7 @@ unsigned long __init node_memmap_size_bytes(int nid, unsigned long start_pfn,
if (nid != early_pfn_to_nid(pfn))
continue;
- if (pfn_valid(pfn))
+ if (pfn_present(pfn))
nr_pages += PAGES_PER_SECTION;
}
@@ -204,44 +206,79 @@ struct page *sparse_decode_mem_map(unsigned long coded_mem_map, unsigned long pn
}
static int __meminit sparse_init_one_section(struct mem_section *ms,
- unsigned long pnum, struct page *mem_map)
+ unsigned long pnum, struct page *mem_map,
+ unsigned long *pageblock_bitmap)
{
- if (!valid_section(ms))
+ if (!present_section(ms))
return -EINVAL;
ms->section_mem_map &= ~SECTION_MAP_MASK;
- ms->section_mem_map |= sparse_encode_mem_map(mem_map, pnum);
+ ms->section_mem_map |= sparse_encode_mem_map(mem_map, pnum) |
+ SECTION_HAS_MEM_MAP;
+ ms->pageblock_flags = pageblock_bitmap;
return 1;
}
-__attribute__((weak)) __init
-void *alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size)
+static unsigned long usemap_size(void)
{
- return NULL;
+ unsigned long size_bytes;
+ size_bytes = roundup(SECTION_BLOCKFLAGS_BITS, 8) / 8;
+ size_bytes = roundup(size_bytes, sizeof(unsigned long));
+ return size_bytes;
}
-static struct page __init *sparse_early_mem_map_alloc(unsigned long pnum)
+#ifdef CONFIG_MEMORY_HOTPLUG
+static unsigned long *__kmalloc_section_usemap(void)
{
- struct page *map;
+ return kmalloc(usemap_size(), GFP_KERNEL);
+}
+#endif /* CONFIG_MEMORY_HOTPLUG */
+
+static unsigned long *sparse_early_usemap_alloc(unsigned long pnum)
+{
+ unsigned long *usemap;
struct mem_section *ms = __nr_to_section(pnum);
int nid = sparse_early_nid(ms);
- map = alloc_remap(nid, sizeof(struct page) * PAGES_PER_SECTION);
- if (map)
- return map;
+ usemap = alloc_bootmem_node(NODE_DATA(nid), usemap_size());
+ if (usemap)
+ return usemap;
- map = alloc_bootmem_high_node(NODE_DATA(nid),
- sizeof(struct page) * PAGES_PER_SECTION);
+ /* Stupid: suppress gcc warning for SPARSEMEM && !NUMA */
+ nid = 0;
+
+ printk(KERN_WARNING "%s: allocation failed\n", __FUNCTION__);
+ return NULL;
+}
+
+#ifndef CONFIG_SPARSEMEM_VMEMMAP
+struct page __init *sparse_mem_map_populate(unsigned long pnum, int nid)
+{
+ struct page *map;
+
+ map = alloc_remap(nid, sizeof(struct page) * PAGES_PER_SECTION);
if (map)
return map;
map = alloc_bootmem_node(NODE_DATA(nid),
sizeof(struct page) * PAGES_PER_SECTION);
+ return map;
+}
+#endif /* !CONFIG_SPARSEMEM_VMEMMAP */
+
+struct page __init *sparse_early_mem_map_alloc(unsigned long pnum)
+{
+ struct page *map;
+ struct mem_section *ms = __nr_to_section(pnum);
+ int nid = sparse_early_nid(ms);
+
+ map = sparse_mem_map_populate(pnum, nid);
if (map)
return map;
- printk(KERN_WARNING "%s: allocation failed\n", __FUNCTION__);
+ printk(KERN_ERR "%s: sparsemem memory map backing failed "
+ "some memory will not be available.\n", __FUNCTION__);
ms->section_mem_map = 0;
return NULL;
}
@@ -254,19 +291,38 @@ void __init sparse_init(void)
{
unsigned long pnum;
struct page *map;
+ unsigned long *usemap;
for (pnum = 0; pnum < NR_MEM_SECTIONS; pnum++) {
- if (!valid_section_nr(pnum))
+ if (!present_section_nr(pnum))
continue;
map = sparse_early_mem_map_alloc(pnum);
if (!map)
continue;
- sparse_init_one_section(__nr_to_section(pnum), pnum, map);
+
+ usemap = sparse_early_usemap_alloc(pnum);
+ if (!usemap)
+ continue;
+
+ sparse_init_one_section(__nr_to_section(pnum), pnum, map,
+ usemap);
}
}
#ifdef CONFIG_MEMORY_HOTPLUG
+#ifdef CONFIG_SPARSEMEM_VMEMMAP
+static inline struct page *kmalloc_section_memmap(unsigned long pnum, int nid,
+ unsigned long nr_pages)
+{
+ /* This will make the necessary allocations eventually. */
+ return sparse_mem_map_populate(pnum, nid);
+}
+static void __kfree_section_memmap(struct page *memmap, unsigned long nr_pages)
+{
+ return; /* XXX: Not implemented yet */
+}
+#else
static struct page *__kmalloc_section_memmap(unsigned long nr_pages)
{
struct page *page, *ret;
@@ -289,6 +345,12 @@ got_map_ptr:
return ret;
}
+static inline struct page *kmalloc_section_memmap(unsigned long pnum, int nid,
+ unsigned long nr_pages)
+{
+ return __kmalloc_section_memmap(nr_pages);
+}
+
static int vaddr_in_vmalloc_area(void *addr)
{
if (addr >= (void *)VMALLOC_START &&
@@ -305,6 +367,7 @@ static void __kfree_section_memmap(struct page *memmap, unsigned long nr_pages)
free_pages((unsigned long)memmap,
get_order(sizeof(struct page) * nr_pages));
}
+#endif /* CONFIG_SPARSEMEM_VMEMMAP */
/*
* returns the number of sections whose mem_maps were properly
@@ -318,6 +381,7 @@ int sparse_add_one_section(struct zone *zone, unsigned long start_pfn,
struct pglist_data *pgdat = zone->zone_pgdat;
struct mem_section *ms;
struct page *memmap;
+ unsigned long *usemap;
unsigned long flags;
int ret;
@@ -326,7 +390,8 @@ int sparse_add_one_section(struct zone *zone, unsigned long start_pfn,
* plus, it does a kmalloc
*/
sparse_index_init(section_nr, pgdat->node_id);
- memmap = __kmalloc_section_memmap(nr_pages);
+ memmap = kmalloc_section_memmap(section_nr, pgdat->node_id, nr_pages);
+ usemap = __kmalloc_section_usemap();
pgdat_resize_lock(pgdat, &flags);
@@ -335,9 +400,14 @@ int sparse_add_one_section(struct zone *zone, unsigned long start_pfn,
ret = -EEXIST;
goto out;
}
+
+ if (!usemap) {
+ ret = -ENOMEM;
+ goto out;
+ }
ms->section_mem_map |= SECTION_MARKED_PRESENT;
- ret = sparse_init_one_section(ms, section_nr, memmap);
+ ret = sparse_init_one_section(ms, section_nr, memmap, usemap);
out:
pgdat_resize_unlock(pgdat, &flags);
diff --git a/mm/swap.c b/mm/swap.c
index d3cb966fe992..9ac88323d237 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -5,7 +5,7 @@
*/
/*
- * This file contains the default values for the opereation of the
+ * This file contains the default values for the operation of the
* Linux VM subsystem. Fine-tuning documentation can be found in
* Documentation/sysctl/vm.txt.
* Started 18.12.91
@@ -24,16 +24,19 @@
#include <linux/module.h>
#include <linux/mm_inline.h>
#include <linux/buffer_head.h> /* for try_to_release_page() */
-#include <linux/module.h>
#include <linux/percpu_counter.h>
#include <linux/percpu.h>
#include <linux/cpu.h>
#include <linux/notifier.h>
-#include <linux/init.h>
+#include <linux/backing-dev.h>
/* How many pages do we try to swap or page in/out together? */
int page_cluster;
+static DEFINE_PER_CPU(struct pagevec, lru_add_pvecs) = { 0, };
+static DEFINE_PER_CPU(struct pagevec, lru_add_active_pvecs) = { 0, };
+static DEFINE_PER_CPU(struct pagevec, lru_rotate_pvecs) = { 0, };
+
/*
* This path almost never happens for VM activity - pages are normally
* freed via pagevecs. But it gets used by networking.
@@ -94,23 +97,47 @@ void put_pages_list(struct list_head *pages)
EXPORT_SYMBOL(put_pages_list);
/*
+ * pagevec_move_tail() must be called with IRQ disabled.
+ * Otherwise this may cause nasty races.
+ */
+static void pagevec_move_tail(struct pagevec *pvec)
+{
+ int i;
+ int pgmoved = 0;
+ struct zone *zone = NULL;
+
+ for (i = 0; i < pagevec_count(pvec); i++) {
+ struct page *page = pvec->pages[i];
+ struct zone *pagezone = page_zone(page);
+
+ if (pagezone != zone) {
+ if (zone)
+ spin_unlock(&zone->lru_lock);
+ zone = pagezone;
+ spin_lock(&zone->lru_lock);
+ }
+ if (PageLRU(page) && !PageActive(page)) {
+ list_move_tail(&page->lru, &zone->inactive_list);
+ pgmoved++;
+ }
+ }
+ if (zone)
+ spin_unlock(&zone->lru_lock);
+ __count_vm_events(PGROTATED, pgmoved);
+ release_pages(pvec->pages, pvec->nr, pvec->cold);
+ pagevec_reinit(pvec);
+}
+
+/*
* Writeback is about to end against a page which has been marked for immediate
* reclaim. If it still appears to be reclaimable, move it to the tail of the
- * inactive list. The page still has PageWriteback set, which will pin it.
- *
- * We don't expect many pages to come through here, so don't bother batching
- * things up.
- *
- * To avoid placing the page at the tail of the LRU while PG_writeback is still
- * set, this function will clear PG_writeback before performing the page
- * motion. Do that inside the lru lock because once PG_writeback is cleared
- * we may not touch the page.
+ * inactive list.
*
* Returns zero if it cleared PG_writeback.
*/
int rotate_reclaimable_page(struct page *page)
{
- struct zone *zone;
+ struct pagevec *pvec;
unsigned long flags;
if (PageLocked(page))
@@ -122,15 +149,16 @@ int rotate_reclaimable_page(struct page *page)
if (!PageLRU(page))
return 1;
- zone = page_zone(page);
- spin_lock_irqsave(&zone->lru_lock, flags);
- if (PageLRU(page) && !PageActive(page)) {
- list_move_tail(&page->lru, &zone->inactive_list);
- __count_vm_event(PGROTATED);
- }
+ page_cache_get(page);
+ local_irq_save(flags);
+ pvec = &__get_cpu_var(lru_rotate_pvecs);
+ if (!pagevec_add(pvec, page))
+ pagevec_move_tail(pvec);
+ local_irq_restore(flags);
+
if (!test_clear_page_writeback(page))
BUG();
- spin_unlock_irqrestore(&zone->lru_lock, flags);
+
return 0;
}
@@ -174,9 +202,6 @@ EXPORT_SYMBOL(mark_page_accessed);
* lru_cache_add: add a page to the page lists
* @page: the page to add
*/
-static DEFINE_PER_CPU(struct pagevec, lru_add_pvecs) = { 0, };
-static DEFINE_PER_CPU(struct pagevec, lru_add_active_pvecs) = { 0, };
-
void fastcall lru_cache_add(struct page *page)
{
struct pagevec *pvec = &get_cpu_var(lru_add_pvecs);
@@ -197,21 +222,37 @@ void fastcall lru_cache_add_active(struct page *page)
put_cpu_var(lru_add_active_pvecs);
}
-static void __lru_add_drain(int cpu)
+/*
+ * Drain pages out of the cpu's pagevecs.
+ * Either "cpu" is the current CPU, and preemption has already been
+ * disabled; or "cpu" is being hot-unplugged, and is already dead.
+ */
+static void drain_cpu_pagevecs(int cpu)
{
- struct pagevec *pvec = &per_cpu(lru_add_pvecs, cpu);
+ struct pagevec *pvec;
- /* CPU is dead, so no locking needed. */
+ pvec = &per_cpu(lru_add_pvecs, cpu);
if (pagevec_count(pvec))
__pagevec_lru_add(pvec);
+
pvec = &per_cpu(lru_add_active_pvecs, cpu);
if (pagevec_count(pvec))
__pagevec_lru_add_active(pvec);
+
+ pvec = &per_cpu(lru_rotate_pvecs, cpu);
+ if (pagevec_count(pvec)) {
+ unsigned long flags;
+
+ /* No harm done if a racing interrupt already did this */
+ local_irq_save(flags);
+ pagevec_move_tail(pvec);
+ local_irq_restore(flags);
+ }
}
void lru_add_drain(void)
{
- __lru_add_drain(get_cpu());
+ drain_cpu_pagevecs(get_cpu());
put_cpu();
}
@@ -258,6 +299,7 @@ void release_pages(struct page **pages, int nr, int cold)
int i;
struct pagevec pages_to_free;
struct zone *zone = NULL;
+ unsigned long uninitialized_var(flags);
pagevec_init(&pages_to_free, cold);
for (i = 0; i < nr; i++) {
@@ -265,7 +307,7 @@ void release_pages(struct page **pages, int nr, int cold)
if (unlikely(PageCompound(page))) {
if (zone) {
- spin_unlock_irq(&zone->lru_lock);
+ spin_unlock_irqrestore(&zone->lru_lock, flags);
zone = NULL;
}
put_compound_page(page);
@@ -279,9 +321,10 @@ void release_pages(struct page **pages, int nr, int cold)
struct zone *pagezone = page_zone(page);
if (pagezone != zone) {
if (zone)
- spin_unlock_irq(&zone->lru_lock);
+ spin_unlock_irqrestore(&zone->lru_lock,
+ flags);
zone = pagezone;
- spin_lock_irq(&zone->lru_lock);
+ spin_lock_irqsave(&zone->lru_lock, flags);
}
VM_BUG_ON(!PageLRU(page));
__ClearPageLRU(page);
@@ -290,7 +333,7 @@ void release_pages(struct page **pages, int nr, int cold)
if (!pagevec_add(&pages_to_free, page)) {
if (zone) {
- spin_unlock_irq(&zone->lru_lock);
+ spin_unlock_irqrestore(&zone->lru_lock, flags);
zone = NULL;
}
__pagevec_free(&pages_to_free);
@@ -298,7 +341,7 @@ void release_pages(struct page **pages, int nr, int cold)
}
}
if (zone)
- spin_unlock_irq(&zone->lru_lock);
+ spin_unlock_irqrestore(&zone->lru_lock, flags);
pagevec_free(&pages_to_free);
}
@@ -491,7 +534,7 @@ static int cpu_swap_callback(struct notifier_block *nfb,
if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) {
atomic_add(*committed, &vm_committed_space);
*committed = 0;
- __lru_add_drain((long)hcpu);
+ drain_cpu_pagevecs((long)hcpu);
}
return NOTIFY_OK;
}
@@ -505,6 +548,10 @@ void __init swap_setup(void)
{
unsigned long megs = num_physpages >> (20 - PAGE_SHIFT);
+#ifdef CONFIG_SWAP
+ bdi_init(swapper_space.backing_dev_info);
+#endif
+
/* Use a smaller cluster for small-memory machines */
if (megs < 16)
page_cluster = 2;
diff --git a/mm/swap_state.c b/mm/swap_state.c
index 67daecb6031a..b52635601dfe 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -74,6 +74,7 @@ static int __add_to_swap_cache(struct page *page, swp_entry_t entry,
{
int error;
+ BUG_ON(!PageLocked(page));
BUG_ON(PageSwapCache(page));
BUG_ON(PagePrivate(page));
error = radix_tree_preload(gfp_mask);
@@ -83,7 +84,6 @@ static int __add_to_swap_cache(struct page *page, swp_entry_t entry,
entry.val, page);
if (!error) {
page_cache_get(page);
- SetPageLocked(page);
SetPageSwapCache(page);
set_page_private(page, entry.val);
total_swapcache_pages++;
@@ -99,15 +99,18 @@ static int add_to_swap_cache(struct page *page, swp_entry_t entry)
{
int error;
+ BUG_ON(PageLocked(page));
if (!swap_duplicate(entry)) {
INC_CACHE_INFO(noent_race);
return -ENOENT;
}
+ SetPageLocked(page);
error = __add_to_swap_cache(page, entry, GFP_KERNEL);
/*
* Anon pages are already on the LRU, we don't run lru_cache_add here.
*/
if (error) {
+ ClearPageLocked(page);
swap_free(entry);
if (error == -EEXIST)
INC_CACHE_INFO(exist_race);
diff --git a/mm/tiny-shmem.c b/mm/tiny-shmem.c
index 8803471593fd..d436a9c82db7 100644
--- a/mm/tiny-shmem.c
+++ b/mm/tiny-shmem.c
@@ -66,24 +66,19 @@ struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags)
if (!dentry)
goto put_memory;
- error = -ENFILE;
- file = get_empty_filp();
- if (!file)
- goto put_dentry;
-
error = -ENOSPC;
inode = ramfs_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0);
if (!inode)
- goto close_file;
+ goto put_dentry;
d_instantiate(dentry, inode);
- inode->i_nlink = 0; /* It is unlinked */
+ error = -ENFILE;
+ file = alloc_file(shm_mnt, dentry, FMODE_WRITE | FMODE_READ,
+ &ramfs_file_operations);
+ if (!file)
+ goto put_dentry;
- file->f_path.mnt = mntget(shm_mnt);
- file->f_path.dentry = dentry;
- file->f_mapping = inode->i_mapping;
- file->f_op = &ramfs_file_operations;
- file->f_mode = FMODE_WRITE | FMODE_READ;
+ inode->i_nlink = 0; /* It is unlinked */
/* notify everyone as to the change of file size */
error = do_truncate(dentry, size, 0, file);
diff --git a/mm/truncate.c b/mm/truncate.c
index 5cdfbc1a59fd..cadc15653dde 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -8,6 +8,7 @@
*/
#include <linux/kernel.h>
+#include <linux/backing-dev.h>
#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/module.h>
@@ -72,6 +73,8 @@ void cancel_dirty_page(struct page *page, unsigned int account_size)
struct address_space *mapping = page->mapping;
if (mapping && mapping_cap_account_dirty(mapping)) {
dec_zone_page_state(page, NR_FILE_DIRTY);
+ dec_bdi_stat(mapping->backing_dev_info,
+ BDI_RECLAIMABLE);
if (account_size)
task_io_account_cancelled_write(account_size);
}
diff --git a/mm/util.c b/mm/util.c
index bf340d806868..8f18683825bc 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -81,20 +81,22 @@ EXPORT_SYMBOL(kmemdup);
void *krealloc(const void *p, size_t new_size, gfp_t flags)
{
void *ret;
- size_t ks;
+ size_t ks = 0;
if (unlikely(!new_size)) {
kfree(p);
return ZERO_SIZE_PTR;
}
- ks = ksize(p);
+ if (p)
+ ks = ksize(p);
+
if (ks >= new_size)
return (void *)p;
ret = kmalloc_track_caller(new_size, flags);
- if (ret) {
- memcpy(ret, p, min(new_size, ks));
+ if (ret && p) {
+ memcpy(ret, p, ks);
kfree(p);
}
return ret;
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 3cee76a8c9f0..af77e171e339 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -190,7 +190,8 @@ static struct vm_struct *__get_vm_area_node(unsigned long size, unsigned long fl
if (unlikely(!size))
return NULL;
- area = kmalloc_node(sizeof(*area), gfp_mask & GFP_LEVEL_MASK, node);
+ area = kmalloc_node(sizeof(*area), gfp_mask & GFP_RECLAIM_MASK, node);
+
if (unlikely(!area))
return NULL;
@@ -246,7 +247,7 @@ struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
EXPORT_SYMBOL_GPL(__get_vm_area);
/**
- * get_vm_area - reserve a contingous kernel virtual area
+ * get_vm_area - reserve a contiguous kernel virtual area
* @size: size of the area
* @flags: %VM_IOREMAP for I/O mappings or VM_ALLOC
*
@@ -302,7 +303,7 @@ found:
}
/**
- * remove_vm_area - find and remove a contingous kernel virtual area
+ * remove_vm_area - find and remove a continuous kernel virtual area
* @addr: base address
*
* Search for the kernel VM area starting at @addr, and remove it.
@@ -363,7 +364,7 @@ static void __vunmap(void *addr, int deallocate_pages)
* vfree - release memory allocated by vmalloc()
* @addr: memory base address
*
- * Free the virtually contiguous memory area starting at @addr, as
+ * Free the virtually continuous memory area starting at @addr, as
* obtained from vmalloc(), vmalloc_32() or __vmalloc(). If @addr is
* NULL, no operation is performed.
*
@@ -439,7 +440,7 @@ void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
area->flags |= VM_VPAGES;
} else {
pages = kmalloc_node(array_size,
- (gfp_mask & GFP_LEVEL_MASK) | __GFP_ZERO,
+ (gfp_mask & GFP_RECLAIM_MASK) | __GFP_ZERO,
node);
}
area->pages = pages;
diff --git a/mm/vmscan.c b/mm/vmscan.c
index a6e65d024995..e5a9597e3bbc 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -141,7 +141,7 @@ EXPORT_SYMBOL(unregister_shrinker);
* percentages of the lru and ageable caches. This should balance the seeks
* generated by these structures.
*
- * If the vm encounted mapped pages on the LRU it increase the pressure on
+ * If the vm encountered mapped pages on the LRU it increase the pressure on
* slab to avoid swapping.
*
* We do weird things to avoid (scanned*seeks*entries) overflowing 32 bits.
@@ -932,6 +932,7 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone,
long mapped_ratio;
long distress;
long swap_tendency;
+ long imbalance;
if (zone_is_near_oom(zone))
goto force_reclaim_mapped;
@@ -967,6 +968,46 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone,
swap_tendency = mapped_ratio / 2 + distress + sc->swappiness;
/*
+ * If there's huge imbalance between active and inactive
+ * (think active 100 times larger than inactive) we should
+ * become more permissive, or the system will take too much
+ * cpu before it start swapping during memory pressure.
+ * Distress is about avoiding early-oom, this is about
+ * making swappiness graceful despite setting it to low
+ * values.
+ *
+ * Avoid div by zero with nr_inactive+1, and max resulting
+ * value is vm_total_pages.
+ */
+ imbalance = zone_page_state(zone, NR_ACTIVE);
+ imbalance /= zone_page_state(zone, NR_INACTIVE) + 1;
+
+ /*
+ * Reduce the effect of imbalance if swappiness is low,
+ * this means for a swappiness very low, the imbalance
+ * must be much higher than 100 for this logic to make
+ * the difference.
+ *
+ * Max temporary value is vm_total_pages*100.
+ */
+ imbalance *= (vm_swappiness + 1);
+ imbalance /= 100;
+
+ /*
+ * If not much of the ram is mapped, makes the imbalance
+ * less relevant, it's high priority we refill the inactive
+ * list with mapped pages only in presence of high ratio of
+ * mapped pages.
+ *
+ * Max temporary value is vm_total_pages*100.
+ */
+ imbalance *= mapped_ratio;
+ imbalance /= 100;
+
+ /* apply imbalance feedback to swap_tendency */
+ swap_tendency += imbalance;
+
+ /*
* Now use this metric to decide whether to start moving mapped
* memory onto the inactive list.
*/
@@ -1067,8 +1108,6 @@ static unsigned long shrink_zone(int priority, struct zone *zone,
unsigned long nr_to_scan;
unsigned long nr_reclaimed = 0;
- atomic_inc(&zone->reclaim_in_progress);
-
/*
* Add one to `nr_to_scan' just to make sure that the kernel will
* slowly sift through the active list.
@@ -1107,8 +1146,6 @@ static unsigned long shrink_zone(int priority, struct zone *zone,
}
throttle_vm_writeout(sc->gfp_mask);
-
- atomic_dec(&zone->reclaim_in_progress);
return nr_reclaimed;
}
@@ -1146,7 +1183,7 @@ static unsigned long shrink_zones(int priority, struct zone **zones,
note_zone_scanning_priority(zone, priority);
- if (zone->all_unreclaimable && priority != DEF_PRIORITY)
+ if (zone_is_all_unreclaimable(zone) && priority != DEF_PRIORITY)
continue; /* Let kswapd poll it */
sc->all_unreclaimable = 0;
@@ -1245,7 +1282,7 @@ out:
*/
if (priority < 0)
priority = 0;
- for (i = 0; zones[i] != 0; i++) {
+ for (i = 0; zones[i] != NULL; i++) {
struct zone *zone = zones[i];
if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL))
@@ -1327,7 +1364,8 @@ loop_again:
if (!populated_zone(zone))
continue;
- if (zone->all_unreclaimable && priority != DEF_PRIORITY)
+ if (zone_is_all_unreclaimable(zone) &&
+ priority != DEF_PRIORITY)
continue;
if (!zone_watermark_ok(zone, order, zone->pages_high,
@@ -1362,7 +1400,8 @@ loop_again:
if (!populated_zone(zone))
continue;
- if (zone->all_unreclaimable && priority != DEF_PRIORITY)
+ if (zone_is_all_unreclaimable(zone) &&
+ priority != DEF_PRIORITY)
continue;
if (!zone_watermark_ok(zone, order, zone->pages_high,
@@ -1371,18 +1410,25 @@ loop_again:
temp_priority[i] = priority;
sc.nr_scanned = 0;
note_zone_scanning_priority(zone, priority);
- nr_reclaimed += shrink_zone(priority, zone, &sc);
+ /*
+ * We put equal pressure on every zone, unless one
+ * zone has way too many pages free already.
+ */
+ if (!zone_watermark_ok(zone, order, 8*zone->pages_high,
+ end_zone, 0))
+ nr_reclaimed += shrink_zone(priority, zone, &sc);
reclaim_state->reclaimed_slab = 0;
nr_slab = shrink_slab(sc.nr_scanned, GFP_KERNEL,
lru_pages);
nr_reclaimed += reclaim_state->reclaimed_slab;
total_scanned += sc.nr_scanned;
- if (zone->all_unreclaimable)
+ if (zone_is_all_unreclaimable(zone))
continue;
if (nr_slab == 0 && zone->pages_scanned >=
(zone_page_state(zone, NR_ACTIVE)
+ zone_page_state(zone, NR_INACTIVE)) * 6)
- zone->all_unreclaimable = 1;
+ zone_set_flag(zone,
+ ZONE_ALL_UNRECLAIMABLE);
/*
* If we've done a decent amount of scanning and
* the reclaim ratio is low, start doing writepage
@@ -1548,7 +1594,7 @@ static unsigned long shrink_all_zones(unsigned long nr_pages, int prio,
if (!populated_zone(zone))
continue;
- if (zone->all_unreclaimable && prio != DEF_PRIORITY)
+ if (zone_is_all_unreclaimable(zone) && prio != DEF_PRIORITY)
continue;
/* For pass = 0 we don't shrink the active list */
@@ -1688,9 +1734,11 @@ static int __devinit cpu_callback(struct notifier_block *nfb,
{
pg_data_t *pgdat;
cpumask_t mask;
+ int nid;
if (action == CPU_ONLINE || action == CPU_ONLINE_FROZEN) {
- for_each_online_pgdat(pgdat) {
+ for_each_node_state(nid, N_HIGH_MEMORY) {
+ pgdat = NODE_DATA(nid);
mask = node_to_cpumask(pgdat->node_id);
if (any_online_cpu(mask) != NR_CPUS)
/* One of our CPUs online: restore mask */
@@ -1727,7 +1775,7 @@ static int __init kswapd_init(void)
int nid;
swap_setup();
- for_each_online_node(nid)
+ for_each_node_state(nid, N_HIGH_MEMORY)
kswapd_run(nid);
hotcpu_notifier(cpu_callback, 0);
return 0;
@@ -1847,8 +1895,8 @@ static int __zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
int zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
{
- cpumask_t mask;
int node_id;
+ int ret;
/*
* Zone reclaim reclaims unmapped file backed pages and
@@ -1866,15 +1914,13 @@ int zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
<= zone->min_slab_pages)
return 0;
+ if (zone_is_all_unreclaimable(zone))
+ return 0;
+
/*
- * Avoid concurrent zone reclaims, do not reclaim in a zone that does
- * not have reclaimable pages and if we should not delay the allocation
- * then do not scan.
+ * Do not scan if the allocation should not be delayed.
*/
- if (!(gfp_mask & __GFP_WAIT) ||
- zone->all_unreclaimable ||
- atomic_read(&zone->reclaim_in_progress) > 0 ||
- (current->flags & PF_MEMALLOC))
+ if (!(gfp_mask & __GFP_WAIT) || (current->flags & PF_MEMALLOC))
return 0;
/*
@@ -1884,9 +1930,14 @@ int zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
* as wide as possible.
*/
node_id = zone_to_nid(zone);
- mask = node_to_cpumask(node_id);
- if (!cpus_empty(mask) && node_id != numa_node_id())
+ if (node_state(node_id, N_CPU) && node_id != numa_node_id())
+ return 0;
+
+ if (zone_test_and_set_flag(zone, ZONE_RECLAIM_LOCKED))
return 0;
- return __zone_reclaim(zone, gfp_mask, order);
+ ret = __zone_reclaim(zone, gfp_mask, order);
+ zone_clear_flag(zone, ZONE_RECLAIM_LOCKED);
+
+ return ret;
}
#endif
diff --git a/mm/vmstat.c b/mm/vmstat.c
index c64d169537bf..e8d846f57774 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -353,23 +353,6 @@ void refresh_cpu_vm_stats(int cpu)
}
}
-static void __refresh_cpu_vm_stats(void *dummy)
-{
- refresh_cpu_vm_stats(smp_processor_id());
-}
-
-/*
- * Consolidate all counters.
- *
- * Note that the result is less inaccurate but still inaccurate
- * if concurrent processes are allowed to run.
- */
-void refresh_vm_stats(void)
-{
- on_each_cpu(__refresh_cpu_vm_stats, NULL, 0, 1);
-}
-EXPORT_SYMBOL(refresh_vm_stats);
-
#endif
#ifdef CONFIG_NUMA
@@ -398,6 +381,13 @@ void zone_statistics(struct zonelist *zonelist, struct zone *z)
#include <linux/seq_file.h>
+static char * const migratetype_names[MIGRATE_TYPES] = {
+ "Unmovable",
+ "Reclaimable",
+ "Movable",
+ "Reserve",
+};
+
static void *frag_start(struct seq_file *m, loff_t *pos)
{
pg_data_t *pgdat;
@@ -422,28 +412,144 @@ static void frag_stop(struct seq_file *m, void *arg)
{
}
-/*
- * This walks the free areas for each zone.
- */
-static int frag_show(struct seq_file *m, void *arg)
+/* Walk all the zones in a node and print using a callback */
+static void walk_zones_in_node(struct seq_file *m, pg_data_t *pgdat,
+ void (*print)(struct seq_file *m, pg_data_t *, struct zone *))
{
- pg_data_t *pgdat = (pg_data_t *)arg;
struct zone *zone;
struct zone *node_zones = pgdat->node_zones;
unsigned long flags;
- int order;
for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; ++zone) {
if (!populated_zone(zone))
continue;
spin_lock_irqsave(&zone->lock, flags);
- seq_printf(m, "Node %d, zone %8s ", pgdat->node_id, zone->name);
- for (order = 0; order < MAX_ORDER; ++order)
- seq_printf(m, "%6lu ", zone->free_area[order].nr_free);
+ print(m, pgdat, zone);
spin_unlock_irqrestore(&zone->lock, flags);
+ }
+}
+
+static void frag_show_print(struct seq_file *m, pg_data_t *pgdat,
+ struct zone *zone)
+{
+ int order;
+
+ seq_printf(m, "Node %d, zone %8s ", pgdat->node_id, zone->name);
+ for (order = 0; order < MAX_ORDER; ++order)
+ seq_printf(m, "%6lu ", zone->free_area[order].nr_free);
+ seq_putc(m, '\n');
+}
+
+/*
+ * This walks the free areas for each zone.
+ */
+static int frag_show(struct seq_file *m, void *arg)
+{
+ pg_data_t *pgdat = (pg_data_t *)arg;
+ walk_zones_in_node(m, pgdat, frag_show_print);
+ return 0;
+}
+
+static void pagetypeinfo_showfree_print(struct seq_file *m,
+ pg_data_t *pgdat, struct zone *zone)
+{
+ int order, mtype;
+
+ for (mtype = 0; mtype < MIGRATE_TYPES; mtype++) {
+ seq_printf(m, "Node %4d, zone %8s, type %12s ",
+ pgdat->node_id,
+ zone->name,
+ migratetype_names[mtype]);
+ for (order = 0; order < MAX_ORDER; ++order) {
+ unsigned long freecount = 0;
+ struct free_area *area;
+ struct list_head *curr;
+
+ area = &(zone->free_area[order]);
+
+ list_for_each(curr, &area->free_list[mtype])
+ freecount++;
+ seq_printf(m, "%6lu ", freecount);
+ }
seq_putc(m, '\n');
}
+}
+
+/* Print out the free pages at each order for each migatetype */
+static int pagetypeinfo_showfree(struct seq_file *m, void *arg)
+{
+ int order;
+ pg_data_t *pgdat = (pg_data_t *)arg;
+
+ /* Print header */
+ seq_printf(m, "%-43s ", "Free pages count per migrate type at order");
+ for (order = 0; order < MAX_ORDER; ++order)
+ seq_printf(m, "%6d ", order);
+ seq_putc(m, '\n');
+
+ walk_zones_in_node(m, pgdat, pagetypeinfo_showfree_print);
+
+ return 0;
+}
+
+static void pagetypeinfo_showblockcount_print(struct seq_file *m,
+ pg_data_t *pgdat, struct zone *zone)
+{
+ int mtype;
+ unsigned long pfn;
+ unsigned long start_pfn = zone->zone_start_pfn;
+ unsigned long end_pfn = start_pfn + zone->spanned_pages;
+ unsigned long count[MIGRATE_TYPES] = { 0, };
+
+ for (pfn = start_pfn; pfn < end_pfn; pfn += pageblock_nr_pages) {
+ struct page *page;
+
+ if (!pfn_valid(pfn))
+ continue;
+
+ page = pfn_to_page(pfn);
+ mtype = get_pageblock_migratetype(page);
+
+ count[mtype]++;
+ }
+
+ /* Print counts */
+ seq_printf(m, "Node %d, zone %8s ", pgdat->node_id, zone->name);
+ for (mtype = 0; mtype < MIGRATE_TYPES; mtype++)
+ seq_printf(m, "%12lu ", count[mtype]);
+ seq_putc(m, '\n');
+}
+
+/* Print out the free pages at each order for each migratetype */
+static int pagetypeinfo_showblockcount(struct seq_file *m, void *arg)
+{
+ int mtype;
+ pg_data_t *pgdat = (pg_data_t *)arg;
+
+ seq_printf(m, "\n%-23s", "Number of blocks type ");
+ for (mtype = 0; mtype < MIGRATE_TYPES; mtype++)
+ seq_printf(m, "%12s ", migratetype_names[mtype]);
+ seq_putc(m, '\n');
+ walk_zones_in_node(m, pgdat, pagetypeinfo_showblockcount_print);
+
+ return 0;
+}
+
+/*
+ * This prints out statistics in relation to grouping pages by mobility.
+ * It is expensive to collect so do not constantly read the file.
+ */
+static int pagetypeinfo_show(struct seq_file *m, void *arg)
+{
+ pg_data_t *pgdat = (pg_data_t *)arg;
+
+ seq_printf(m, "Page block order: %d\n", pageblock_order);
+ seq_printf(m, "Pages per block: %lu\n", pageblock_nr_pages);
+ seq_putc(m, '\n');
+ pagetypeinfo_showfree(m, pgdat);
+ pagetypeinfo_showblockcount(m, pgdat);
+
return 0;
}
@@ -454,6 +560,13 @@ const struct seq_operations fragmentation_op = {
.show = frag_show,
};
+const struct seq_operations pagetypeinfo_op = {
+ .start = frag_start,
+ .next = frag_next,
+ .stop = frag_stop,
+ .show = pagetypeinfo_show,
+};
+
#ifdef CONFIG_ZONE_DMA
#define TEXT_FOR_DMA(xx) xx "_dma",
#else
@@ -532,84 +645,78 @@ static const char * const vmstat_text[] = {
#endif
};
-/*
- * Output information about zones in @pgdat.
- */
-static int zoneinfo_show(struct seq_file *m, void *arg)
+static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,
+ struct zone *zone)
{
- pg_data_t *pgdat = arg;
- struct zone *zone;
- struct zone *node_zones = pgdat->node_zones;
- unsigned long flags;
-
- for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; zone++) {
- int i;
-
- if (!populated_zone(zone))
- continue;
-
- spin_lock_irqsave(&zone->lock, flags);
- seq_printf(m, "Node %d, zone %8s", pgdat->node_id, zone->name);
- seq_printf(m,
- "\n pages free %lu"
- "\n min %lu"
- "\n low %lu"
- "\n high %lu"
- "\n scanned %lu (a: %lu i: %lu)"
- "\n spanned %lu"
- "\n present %lu",
- zone_page_state(zone, NR_FREE_PAGES),
- zone->pages_min,
- zone->pages_low,
- zone->pages_high,
- zone->pages_scanned,
- zone->nr_scan_active, zone->nr_scan_inactive,
- zone->spanned_pages,
- zone->present_pages);
+ int i;
+ seq_printf(m, "Node %d, zone %8s", pgdat->node_id, zone->name);
+ seq_printf(m,
+ "\n pages free %lu"
+ "\n min %lu"
+ "\n low %lu"
+ "\n high %lu"
+ "\n scanned %lu (a: %lu i: %lu)"
+ "\n spanned %lu"
+ "\n present %lu",
+ zone_page_state(zone, NR_FREE_PAGES),
+ zone->pages_min,
+ zone->pages_low,
+ zone->pages_high,
+ zone->pages_scanned,
+ zone->nr_scan_active, zone->nr_scan_inactive,
+ zone->spanned_pages,
+ zone->present_pages);
- for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
- seq_printf(m, "\n %-12s %lu", vmstat_text[i],
- zone_page_state(zone, i));
-
- seq_printf(m,
- "\n protection: (%lu",
- zone->lowmem_reserve[0]);
- for (i = 1; i < ARRAY_SIZE(zone->lowmem_reserve); i++)
- seq_printf(m, ", %lu", zone->lowmem_reserve[i]);
- seq_printf(m,
- ")"
- "\n pagesets");
- for_each_online_cpu(i) {
- struct per_cpu_pageset *pageset;
- int j;
-
- pageset = zone_pcp(zone, i);
- for (j = 0; j < ARRAY_SIZE(pageset->pcp); j++) {
- seq_printf(m,
- "\n cpu: %i pcp: %i"
- "\n count: %i"
- "\n high: %i"
- "\n batch: %i",
- i, j,
- pageset->pcp[j].count,
- pageset->pcp[j].high,
- pageset->pcp[j].batch);
+ for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
+ seq_printf(m, "\n %-12s %lu", vmstat_text[i],
+ zone_page_state(zone, i));
+
+ seq_printf(m,
+ "\n protection: (%lu",
+ zone->lowmem_reserve[0]);
+ for (i = 1; i < ARRAY_SIZE(zone->lowmem_reserve); i++)
+ seq_printf(m, ", %lu", zone->lowmem_reserve[i]);
+ seq_printf(m,
+ ")"
+ "\n pagesets");
+ for_each_online_cpu(i) {
+ struct per_cpu_pageset *pageset;
+ int j;
+
+ pageset = zone_pcp(zone, i);
+ for (j = 0; j < ARRAY_SIZE(pageset->pcp); j++) {
+ seq_printf(m,
+ "\n cpu: %i pcp: %i"
+ "\n count: %i"
+ "\n high: %i"
+ "\n batch: %i",
+ i, j,
+ pageset->pcp[j].count,
+ pageset->pcp[j].high,
+ pageset->pcp[j].batch);
}
#ifdef CONFIG_SMP
- seq_printf(m, "\n vm stats threshold: %d",
- pageset->stat_threshold);
+ seq_printf(m, "\n vm stats threshold: %d",
+ pageset->stat_threshold);
#endif
- }
- seq_printf(m,
- "\n all_unreclaimable: %u"
- "\n prev_priority: %i"
- "\n start_pfn: %lu",
- zone->all_unreclaimable,
- zone->prev_priority,
- zone->zone_start_pfn);
- spin_unlock_irqrestore(&zone->lock, flags);
- seq_putc(m, '\n');
}
+ seq_printf(m,
+ "\n all_unreclaimable: %u"
+ "\n prev_priority: %i"
+ "\n start_pfn: %lu",
+ zone_is_all_unreclaimable(zone),
+ zone->prev_priority,
+ zone->zone_start_pfn);
+ seq_putc(m, '\n');
+}
+
+/*
+ * Output information about zones in @pgdat.
+ */
+static int zoneinfo_show(struct seq_file *m, void *arg)
+{
+ pg_data_t *pgdat = (pg_data_t *)arg;
+ walk_zones_in_node(m, pgdat, zoneinfo_show_print);
return 0;
}
@@ -696,7 +803,7 @@ static void vmstat_update(struct work_struct *w)
sysctl_stat_interval);
}
-static void __devinit start_cpu_timer(int cpu)
+static void __cpuinit start_cpu_timer(int cpu)
{
struct delayed_work *vmstat_work = &per_cpu(vmstat_work, cpu);
@@ -741,7 +848,7 @@ static int __cpuinit vmstat_cpuup_callback(struct notifier_block *nfb,
static struct notifier_block __cpuinitdata vmstat_notifier =
{ &vmstat_cpuup_callback, NULL, 0 };
-int __init setup_vmstat(void)
+static int __init setup_vmstat(void)
{
int cpu;
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 3fe4fc86055f..6567213959cb 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -376,6 +376,7 @@ void vlan_setup(struct net_device *new_dev)
new_dev->init = vlan_dev_init;
new_dev->open = vlan_dev_open;
new_dev->stop = vlan_dev_stop;
+ new_dev->set_mac_address = vlan_set_mac_address;
new_dev->set_multicast_list = vlan_dev_set_multicast_list;
new_dev->change_rx_flags = vlan_change_rx_flags;
new_dev->destructor = free_netdev;
@@ -636,6 +637,10 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
if (!vlandev)
continue;
+ flgs = vlandev->flags;
+ if (!(flgs & IFF_UP))
+ continue;
+
vlan_sync_address(dev, vlandev);
}
break;
@@ -747,6 +752,7 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)
vlan_dev_set_ingress_priority(dev,
args.u.skb_priority,
args.vlan_qos);
+ err = 0;
break;
case SET_VLAN_EGRESS_PRIORITY_CMD:
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index cf4a80d06b35..2cd1393073ec 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -60,6 +60,7 @@ int vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, struct net_device *dev
int vlan_dev_change_mtu(struct net_device *dev, int new_mtu);
int vlan_dev_open(struct net_device* dev);
int vlan_dev_stop(struct net_device* dev);
+int vlan_set_mac_address(struct net_device *dev, void *p);
int vlan_dev_ioctl(struct net_device* dev, struct ifreq *ifr, int cmd);
void vlan_dev_set_ingress_priority(const struct net_device *dev,
u32 skb_prio, short vlan_prio);
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 1a1740aa9a8b..7a36878241da 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -665,6 +665,32 @@ int vlan_dev_stop(struct net_device *dev)
return 0;
}
+int vlan_set_mac_address(struct net_device *dev, void *p)
+{
+ struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev;
+ struct sockaddr *addr = p;
+ int err;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ if (!(dev->flags & IFF_UP))
+ goto out;
+
+ if (compare_ether_addr(addr->sa_data, real_dev->dev_addr)) {
+ err = dev_unicast_add(real_dev, addr->sa_data, ETH_ALEN);
+ if (err < 0)
+ return err;
+ }
+
+ if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr))
+ dev_unicast_delete(real_dev, dev->dev_addr, ETH_ALEN);
+
+out:
+ memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
+ return 0;
+}
+
int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev;
diff --git a/net/9p/Kconfig b/net/9p/Kconfig
index 66821cd64a76..bafc50c9e6ff 100644
--- a/net/9p/Kconfig
+++ b/net/9p/Kconfig
@@ -13,9 +13,26 @@ menuconfig NET_9P
If unsure, say N.
+config NET_9P_FD
+ depends on NET_9P
+ default y if NET_9P
+ tristate "9P File Descriptor Transports (Experimental)"
+ help
+ This builds support for file descriptor transports for 9p
+ which includes support for TCP/IP, named pipes, or passed
+ file descriptors. TCP/IP is the default transport for 9p,
+ so if you are going to use 9p, you'll likely want this.
+
+config NET_9P_VIRTIO
+ depends on NET_9P && EXPERIMENTAL && VIRTIO
+ tristate "9P Virtio Transport (Experimental)"
+ help
+ This builds support for a transports between
+ guest partitions and a host partition.
+
config NET_9P_DEBUG
bool "Debug information"
depends on NET_9P
help
- Say Y if you want the 9P subsistem to log debug information.
+ Say Y if you want the 9P subsystem to log debug information.
diff --git a/net/9p/Makefile b/net/9p/Makefile
index 85b3a7838acf..d3abb246ccab 100644
--- a/net/9p/Makefile
+++ b/net/9p/Makefile
@@ -1,8 +1,9 @@
obj-$(CONFIG_NET_9P) := 9pnet.o
+obj-$(CONFIG_NET_9P_FD) += 9pnet_fd.o
+obj-$(CONFIG_NET_9P_VIRTIO) += 9pnet_virtio.o
9pnet-objs := \
mod.o \
- trans_fd.o \
mux.o \
client.o \
conv.o \
@@ -10,4 +11,8 @@ obj-$(CONFIG_NET_9P) := 9pnet.o
fcprint.o \
util.o \
-9pnet-$(CONFIG_SYSCTL) += sysctl.o
+9pnet_fd-objs := \
+ trans_fd.o \
+
+9pnet_virtio-objs := \
+ trans_virtio.o \
diff --git a/net/9p/client.c b/net/9p/client.c
index cb170750337c..af9199364049 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -30,6 +30,7 @@
#include <linux/sched.h>
#include <linux/uaccess.h>
#include <net/9p/9p.h>
+#include <linux/parser.h>
#include <net/9p/transport.h>
#include <net/9p/conn.h>
#include <net/9p/client.h>
@@ -38,7 +39,7 @@ static struct p9_fid *p9_fid_create(struct p9_client *clnt);
static void p9_fid_destroy(struct p9_fid *fid);
static struct p9_stat *p9_clone_stat(struct p9_stat *st, int dotu);
-struct p9_client *p9_client_create(struct p9_transport *trans, int msize,
+struct p9_client *p9_client_create(struct p9_trans *trans, int msize,
int dotu)
{
int err, n;
@@ -146,7 +147,7 @@ void p9_client_disconnect(struct p9_client *clnt)
EXPORT_SYMBOL(p9_client_disconnect);
struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
- char *uname, char *aname)
+ char *uname, u32 n_uname, char *aname)
{
int err;
struct p9_fcall *tc, *rc;
@@ -165,7 +166,8 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
goto error;
}
- tc = p9_create_tattach(fid->fid, afid?afid->fid:P9_NOFID, uname, aname);
+ tc = p9_create_tattach(fid->fid, afid?afid->fid:P9_NOFID, uname, aname,
+ n_uname, clnt->dotu);
if (IS_ERR(tc)) {
err = PTR_ERR(tc);
tc = NULL;
@@ -190,7 +192,8 @@ error:
}
EXPORT_SYMBOL(p9_client_attach);
-struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname, char *aname)
+struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname,
+ u32 n_uname, char *aname)
{
int err;
struct p9_fcall *tc, *rc;
@@ -209,7 +212,7 @@ struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname, char *aname)
goto error;
}
- tc = p9_create_tauth(fid->fid, uname, aname);
+ tc = p9_create_tauth(fid->fid, uname, aname, n_uname, clnt->dotu);
if (IS_ERR(tc)) {
err = PTR_ERR(tc);
tc = NULL;
diff --git a/net/9p/conv.c b/net/9p/conv.c
index d979d958ea19..aa2aa9884f95 100644
--- a/net/9p/conv.c
+++ b/net/9p/conv.c
@@ -547,7 +547,8 @@ error:
}
EXPORT_SYMBOL(p9_create_tversion);
-struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname)
+struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname,
+ u32 n_uname, int dotu)
{
int size;
struct p9_fcall *fc;
@@ -555,7 +556,16 @@ struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname)
struct cbuf *bufp = &buffer;
/* afid[4] uname[s] aname[s] */
- size = 4 + 2 + strlen(uname) + 2 + strlen(aname);
+ size = 4 + 2 + 2;
+ if (uname)
+ size += strlen(uname);
+
+ if (aname)
+ size += strlen(aname);
+
+ if (dotu)
+ size += 4; /* n_uname */
+
fc = p9_create_common(bufp, size, P9_TAUTH);
if (IS_ERR(fc))
goto error;
@@ -563,6 +573,8 @@ struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname)
p9_put_int32(bufp, afid, &fc->params.tauth.afid);
p9_put_str(bufp, uname, &fc->params.tauth.uname);
p9_put_str(bufp, aname, &fc->params.tauth.aname);
+ if (dotu)
+ p9_put_int32(bufp, n_uname, &fc->params.tauth.n_uname);
if (buf_check_overflow(bufp)) {
kfree(fc);
@@ -574,7 +586,8 @@ error:
EXPORT_SYMBOL(p9_create_tauth);
struct p9_fcall *
-p9_create_tattach(u32 fid, u32 afid, char *uname, char *aname)
+p9_create_tattach(u32 fid, u32 afid, char *uname, char *aname,
+ u32 n_uname, int dotu)
{
int size;
struct p9_fcall *fc;
@@ -582,7 +595,16 @@ p9_create_tattach(u32 fid, u32 afid, char *uname, char *aname)
struct cbuf *bufp = &buffer;
/* fid[4] afid[4] uname[s] aname[s] */
- size = 4 + 4 + 2 + strlen(uname) + 2 + strlen(aname);
+ size = 4 + 4 + 2 + 2;
+ if (uname)
+ size += strlen(uname);
+
+ if (aname)
+ size += strlen(aname);
+
+ if (dotu)
+ size += 4; /* n_uname */
+
fc = p9_create_common(bufp, size, P9_TATTACH);
if (IS_ERR(fc))
goto error;
@@ -591,6 +613,8 @@ p9_create_tattach(u32 fid, u32 afid, char *uname, char *aname)
p9_put_int32(bufp, afid, &fc->params.tattach.afid);
p9_put_str(bufp, uname, &fc->params.tattach.uname);
p9_put_str(bufp, aname, &fc->params.tattach.aname);
+ if (dotu)
+ p9_put_int32(bufp, n_uname, &fc->params.tattach.n_uname);
error:
return fc;
diff --git a/net/9p/mod.c b/net/9p/mod.c
index 4f9e1d2ac257..8f9763a9dc12 100644
--- a/net/9p/mod.c
+++ b/net/9p/mod.c
@@ -27,6 +27,10 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <net/9p/9p.h>
+#include <linux/fs.h>
+#include <linux/parser.h>
+#include <net/9p/transport.h>
+#include <linux/list.h>
#ifdef CONFIG_NET_9P_DEBUG
unsigned int p9_debug_level = 0; /* feature-rific global debug level */
@@ -37,8 +41,64 @@ MODULE_PARM_DESC(debug, "9P debugging level");
extern int p9_mux_global_init(void);
extern void p9_mux_global_exit(void);
-extern int p9_sysctl_register(void);
-extern void p9_sysctl_unregister(void);
+
+/*
+ * Dynamic Transport Registration Routines
+ *
+ */
+
+static LIST_HEAD(v9fs_trans_list);
+static struct p9_trans_module *v9fs_default_transport;
+
+/**
+ * v9fs_register_trans - register a new transport with 9p
+ * @m - structure describing the transport module and entry points
+ *
+ */
+void v9fs_register_trans(struct p9_trans_module *m)
+{
+ list_add_tail(&m->list, &v9fs_trans_list);
+ if (m->def)
+ v9fs_default_transport = m;
+}
+EXPORT_SYMBOL(v9fs_register_trans);
+
+/**
+ * v9fs_match_trans - match transport versus registered transports
+ * @arg: string identifying transport
+ *
+ */
+struct p9_trans_module *v9fs_match_trans(const substring_t *name)
+{
+ struct list_head *p;
+ struct p9_trans_module *t = NULL;
+
+ list_for_each(p, &v9fs_trans_list) {
+ t = list_entry(p, struct p9_trans_module, list);
+ if (strncmp(t->name, name->from, name->to-name->from) == 0)
+ return t;
+ }
+ return NULL;
+}
+EXPORT_SYMBOL(v9fs_match_trans);
+
+/**
+ * v9fs_default_trans - returns pointer to default transport
+ *
+ */
+
+struct p9_trans_module *v9fs_default_trans(void)
+{
+ if (v9fs_default_transport)
+ return v9fs_default_transport;
+ else if (!list_empty(&v9fs_trans_list))
+ return list_first_entry(&v9fs_trans_list,
+ struct p9_trans_module, list);
+ else
+ return NULL;
+}
+EXPORT_SYMBOL(v9fs_default_trans);
+
/**
* v9fs_init - Initialize module
@@ -56,12 +116,6 @@ static int __init init_p9(void)
return ret;
}
- ret = p9_sysctl_register();
- if (ret) {
- printk(KERN_WARNING "9p: registering sysctl failed\n");
- return ret;
- }
-
return ret;
}
@@ -72,7 +126,6 @@ static int __init init_p9(void)
static void __exit exit_p9(void)
{
- p9_sysctl_unregister();
p9_mux_global_exit();
}
diff --git a/net/9p/mux.c b/net/9p/mux.c
index 5d70558c4c61..c9f0805048e4 100644
--- a/net/9p/mux.c
+++ b/net/9p/mux.c
@@ -31,6 +31,7 @@
#include <linux/idr.h>
#include <linux/mutex.h>
#include <net/9p/9p.h>
+#include <linux/parser.h>
#include <net/9p/transport.h>
#include <net/9p/conn.h>
@@ -71,7 +72,7 @@ struct p9_conn {
struct p9_mux_poll_task *poll_task;
int msize;
unsigned char *extended;
- struct p9_transport *trans;
+ struct p9_trans *trans;
struct p9_idpool *tagpool;
int err;
wait_queue_head_t equeue;
@@ -221,8 +222,10 @@ static int p9_mux_poll_start(struct p9_conn *m)
}
if (i >= ARRAY_SIZE(p9_mux_poll_tasks)) {
- if (vptlast == NULL)
+ if (vptlast == NULL) {
+ mutex_unlock(&p9_mux_task_lock);
return -ENOMEM;
+ }
P9_DPRINTK(P9_DEBUG_MUX, "put in proc %d\n", i);
list_add(&m->mux_list, &vptlast->mux_list);
@@ -271,7 +274,7 @@ static void p9_mux_poll_stop(struct p9_conn *m)
* @msize - maximum message size
* @extended - pointer to the extended flag
*/
-struct p9_conn *p9_conn_create(struct p9_transport *trans, int msize,
+struct p9_conn *p9_conn_create(struct p9_trans *trans, int msize,
unsigned char *extended)
{
int i, n;
diff --git a/net/9p/sysctl.c b/net/9p/sysctl.c
deleted file mode 100644
index 8b61027a24ea..000000000000
--- a/net/9p/sysctl.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * net/9p/sysctl.c
- *
- * 9P sysctl interface
- *
- * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to:
- * Free Software Foundation
- * 51 Franklin Street, Fifth Floor
- * Boston, MA 02111-1301 USA
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/sysctl.h>
-#include <linux/init.h>
-#include <net/9p/9p.h>
-
-static struct ctl_table p9_table[] = {
-#ifdef CONFIG_NET_9P_DEBUG
- {
- .ctl_name = CTL_UNNUMBERED,
- .procname = "debug",
- .data = &p9_debug_level,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec
- },
-#endif
- {},
-};
-
-static struct ctl_table p9_net_table[] = {
- {
- .ctl_name = CTL_UNNUMBERED,
- .procname = "9p",
- .maxlen = 0,
- .mode = 0555,
- .child = p9_table,
- },
- {},
-};
-
-static struct ctl_table p9_ctl_table[] = {
- {
- .ctl_name = CTL_NET,
- .procname = "net",
- .maxlen = 0,
- .mode = 0555,
- .child = p9_net_table,
- },
- {},
-};
-
-static struct ctl_table_header *p9_table_header;
-
-int __init p9_sysctl_register(void)
-{
- p9_table_header = register_sysctl_table(p9_ctl_table);
- if (!p9_table_header)
- return -ENOMEM;
-
- return 0;
-}
-
-void __exit p9_sysctl_unregister(void)
-{
- unregister_sysctl_table(p9_table_header);
-}
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
index fd636e94358f..62332ed9da4a 100644
--- a/net/9p/trans_fd.c
+++ b/net/9p/trans_fd.c
@@ -5,7 +5,7 @@
*
* Copyright (C) 2006 by Russ Cox <rsc@swtch.com>
* Copyright (C) 2004-2005 by Latchesar Ionkov <lucho@ionkov.net>
- * Copyright (C) 2004-2005 by Eric Van Hensbergen <ericvh@gmail.com>
+ * Copyright (C) 2004-2007 by Eric Van Hensbergen <ericvh@gmail.com>
* Copyright (C) 1997-2002 by Ron Minnich <rminnich@sarnoff.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -36,160 +36,115 @@
#include <linux/inet.h>
#include <linux/idr.h>
#include <linux/file.h>
+#include <linux/parser.h>
#include <net/9p/9p.h>
#include <net/9p/transport.h>
#define P9_PORT 564
+#define MAX_SOCK_BUF (64*1024)
+
+
+struct p9_fd_opts {
+ int rfd;
+ int wfd;
+ u16 port;
+};
struct p9_trans_fd {
struct file *rd;
struct file *wr;
};
-static int p9_socket_open(struct p9_transport *trans, struct socket *csocket);
-static int p9_fd_open(struct p9_transport *trans, int rfd, int wfd);
-static int p9_fd_read(struct p9_transport *trans, void *v, int len);
-static int p9_fd_write(struct p9_transport *trans, void *v, int len);
-static unsigned int p9_fd_poll(struct p9_transport *trans,
- struct poll_table_struct *pt);
-static void p9_fd_close(struct p9_transport *trans);
-
-struct p9_transport *p9_trans_create_tcp(const char *addr, int port)
-{
- int err;
- struct p9_transport *trans;
- struct socket *csocket;
- struct sockaddr_in sin_server;
-
- csocket = NULL;
- trans = kmalloc(sizeof(struct p9_transport), GFP_KERNEL);
- if (!trans)
- return ERR_PTR(-ENOMEM);
-
- trans->write = p9_fd_write;
- trans->read = p9_fd_read;
- trans->close = p9_fd_close;
- trans->poll = p9_fd_poll;
-
- sin_server.sin_family = AF_INET;
- sin_server.sin_addr.s_addr = in_aton(addr);
- sin_server.sin_port = htons(port);
- sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket);
-
- if (!csocket) {
- P9_EPRINTK(KERN_ERR, "p9_trans_tcp: problem creating socket\n");
- err = -EIO;
- goto error;
- }
-
- err = csocket->ops->connect(csocket,
- (struct sockaddr *)&sin_server,
- sizeof(struct sockaddr_in), 0);
- if (err < 0) {
- P9_EPRINTK(KERN_ERR,
- "p9_trans_tcp: problem connecting socket to %s\n",
- addr);
- goto error;
- }
-
- err = p9_socket_open(trans, csocket);
- if (err < 0)
- goto error;
+/*
+ * Option Parsing (code inspired by NFS code)
+ * - a little lazy - parse all fd-transport options
+ */
- return trans;
+enum {
+ /* Options that take integer arguments */
+ Opt_port, Opt_rfdno, Opt_wfdno, Opt_err,
+};
-error:
- if (csocket)
- sock_release(csocket);
+static match_table_t tokens = {
+ {Opt_port, "port=%u"},
+ {Opt_rfdno, "rfdno=%u"},
+ {Opt_wfdno, "wfdno=%u"},
+ {Opt_err, NULL},
+};
- kfree(trans);
- return ERR_PTR(err);
-}
-EXPORT_SYMBOL(p9_trans_create_tcp);
+/**
+ * v9fs_parse_options - parse mount options into session structure
+ * @options: options string passed from mount
+ * @v9ses: existing v9fs session information
+ *
+ */
-struct p9_transport *p9_trans_create_unix(const char *addr)
+static void parse_opts(char *options, struct p9_fd_opts *opts)
{
- int err;
- struct socket *csocket;
- struct sockaddr_un sun_server;
- struct p9_transport *trans;
-
- csocket = NULL;
- trans = kmalloc(sizeof(struct p9_transport), GFP_KERNEL);
- if (!trans)
- return ERR_PTR(-ENOMEM);
+ char *p;
+ substring_t args[MAX_OPT_ARGS];
+ int option;
+ int ret;
- trans->write = p9_fd_write;
- trans->read = p9_fd_read;
- trans->close = p9_fd_close;
- trans->poll = p9_fd_poll;
+ opts->port = P9_PORT;
+ opts->rfd = ~0;
+ opts->wfd = ~0;
- if (strlen(addr) > UNIX_PATH_MAX) {
- P9_EPRINTK(KERN_ERR, "p9_trans_unix: address too long: %s\n",
- addr);
- err = -ENAMETOOLONG;
- goto error;
- }
+ if (!options)
+ return;
- sun_server.sun_family = PF_UNIX;
- strcpy(sun_server.sun_path, addr);
- sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket);
- err = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server,
- sizeof(struct sockaddr_un) - 1, 0);
- if (err < 0) {
- P9_EPRINTK(KERN_ERR,
- "p9_trans_unix: problem connecting socket: %s: %d\n",
- addr, err);
- goto error;
+ while ((p = strsep(&options, ",")) != NULL) {
+ int token;
+ if (!*p)
+ continue;
+ token = match_token(p, tokens, args);
+ ret = match_int(&args[0], &option);
+ if (ret < 0) {
+ P9_DPRINTK(P9_DEBUG_ERROR,
+ "integer field, but no integer?\n");
+ continue;
+ }
+ switch (token) {
+ case Opt_port:
+ opts->port = option;
+ break;
+ case Opt_rfdno:
+ opts->rfd = option;
+ break;
+ case Opt_wfdno:
+ opts->wfd = option;
+ break;
+ default:
+ continue;
+ }
}
-
- err = p9_socket_open(trans, csocket);
- if (err < 0)
- goto error;
-
- return trans;
-
-error:
- if (csocket)
- sock_release(csocket);
-
- kfree(trans);
- return ERR_PTR(err);
}
-EXPORT_SYMBOL(p9_trans_create_unix);
-struct p9_transport *p9_trans_create_fd(int rfd, int wfd)
+static int p9_fd_open(struct p9_trans *trans, int rfd, int wfd)
{
- int err;
- struct p9_transport *trans;
+ struct p9_trans_fd *ts = kmalloc(sizeof(struct p9_trans_fd),
+ GFP_KERNEL);
+ if (!ts)
+ return -ENOMEM;
- if (rfd == ~0 || wfd == ~0) {
- printk(KERN_ERR "v9fs: Insufficient options for proto=fd\n");
- return ERR_PTR(-ENOPROTOOPT);
+ ts->rd = fget(rfd);
+ ts->wr = fget(wfd);
+ if (!ts->rd || !ts->wr) {
+ if (ts->rd)
+ fput(ts->rd);
+ if (ts->wr)
+ fput(ts->wr);
+ kfree(ts);
+ return -EIO;
}
- trans = kmalloc(sizeof(struct p9_transport), GFP_KERNEL);
- if (!trans)
- return ERR_PTR(-ENOMEM);
-
- trans->write = p9_fd_write;
- trans->read = p9_fd_read;
- trans->close = p9_fd_close;
- trans->poll = p9_fd_poll;
-
- err = p9_fd_open(trans, rfd, wfd);
- if (err < 0)
- goto error;
-
- return trans;
+ trans->priv = ts;
+ trans->status = Connected;
-error:
- kfree(trans);
- return ERR_PTR(err);
+ return 0;
}
-EXPORT_SYMBOL(p9_trans_create_fd);
-static int p9_socket_open(struct p9_transport *trans, struct socket *csocket)
+static int p9_socket_open(struct p9_trans *trans, struct socket *csocket)
{
int fd, ret;
@@ -212,30 +167,6 @@ static int p9_socket_open(struct p9_transport *trans, struct socket *csocket)
return 0;
}
-static int p9_fd_open(struct p9_transport *trans, int rfd, int wfd)
-{
- struct p9_trans_fd *ts = kmalloc(sizeof(struct p9_trans_fd),
- GFP_KERNEL);
- if (!ts)
- return -ENOMEM;
-
- ts->rd = fget(rfd);
- ts->wr = fget(wfd);
- if (!ts->rd || !ts->wr) {
- if (ts->rd)
- fput(ts->rd);
- if (ts->wr)
- fput(ts->wr);
- kfree(ts);
- return -EIO;
- }
-
- trans->priv = ts;
- trans->status = Connected;
-
- return 0;
-}
-
/**
* p9_fd_read- read from a fd
* @v9ses: session information
@@ -243,7 +174,7 @@ static int p9_fd_open(struct p9_transport *trans, int rfd, int wfd)
* @len: size of receive buffer
*
*/
-static int p9_fd_read(struct p9_transport *trans, void *v, int len)
+static int p9_fd_read(struct p9_trans *trans, void *v, int len)
{
int ret;
struct p9_trans_fd *ts = NULL;
@@ -270,7 +201,7 @@ static int p9_fd_read(struct p9_transport *trans, void *v, int len)
* @len: size of send buffer
*
*/
-static int p9_fd_write(struct p9_transport *trans, void *v, int len)
+static int p9_fd_write(struct p9_trans *trans, void *v, int len)
{
int ret;
mm_segment_t oldfs;
@@ -297,7 +228,7 @@ static int p9_fd_write(struct p9_transport *trans, void *v, int len)
}
static unsigned int
-p9_fd_poll(struct p9_transport *trans, struct poll_table_struct *pt)
+p9_fd_poll(struct p9_trans *trans, struct poll_table_struct *pt)
{
int ret, n;
struct p9_trans_fd *ts = NULL;
@@ -341,7 +272,7 @@ end:
* @trans: private socket structure
*
*/
-static void p9_fd_close(struct p9_transport *trans)
+static void p9_fd_close(struct p9_trans *trans)
{
struct p9_trans_fd *ts;
@@ -361,3 +292,182 @@ static void p9_fd_close(struct p9_transport *trans)
kfree(ts);
}
+static struct p9_trans *p9_trans_create_tcp(const char *addr, char *args)
+{
+ int err;
+ struct p9_trans *trans;
+ struct socket *csocket;
+ struct sockaddr_in sin_server;
+ struct p9_fd_opts opts;
+
+ parse_opts(args, &opts);
+
+ csocket = NULL;
+ trans = kmalloc(sizeof(struct p9_trans), GFP_KERNEL);
+ if (!trans)
+ return ERR_PTR(-ENOMEM);
+
+ trans->write = p9_fd_write;
+ trans->read = p9_fd_read;
+ trans->close = p9_fd_close;
+ trans->poll = p9_fd_poll;
+
+ sin_server.sin_family = AF_INET;
+ sin_server.sin_addr.s_addr = in_aton(addr);
+ sin_server.sin_port = htons(opts.port);
+ sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket);
+
+ if (!csocket) {
+ P9_EPRINTK(KERN_ERR, "p9_trans_tcp: problem creating socket\n");
+ err = -EIO;
+ goto error;
+ }
+
+ err = csocket->ops->connect(csocket,
+ (struct sockaddr *)&sin_server,
+ sizeof(struct sockaddr_in), 0);
+ if (err < 0) {
+ P9_EPRINTK(KERN_ERR,
+ "p9_trans_tcp: problem connecting socket to %s\n",
+ addr);
+ goto error;
+ }
+
+ err = p9_socket_open(trans, csocket);
+ if (err < 0)
+ goto error;
+
+ return trans;
+
+error:
+ if (csocket)
+ sock_release(csocket);
+
+ kfree(trans);
+ return ERR_PTR(err);
+}
+
+static struct p9_trans *p9_trans_create_unix(const char *addr, char *args)
+{
+ int err;
+ struct socket *csocket;
+ struct sockaddr_un sun_server;
+ struct p9_trans *trans;
+
+ csocket = NULL;
+ trans = kmalloc(sizeof(struct p9_trans), GFP_KERNEL);
+ if (!trans)
+ return ERR_PTR(-ENOMEM);
+
+ trans->write = p9_fd_write;
+ trans->read = p9_fd_read;
+ trans->close = p9_fd_close;
+ trans->poll = p9_fd_poll;
+
+ if (strlen(addr) > UNIX_PATH_MAX) {
+ P9_EPRINTK(KERN_ERR, "p9_trans_unix: address too long: %s\n",
+ addr);
+ err = -ENAMETOOLONG;
+ goto error;
+ }
+
+ sun_server.sun_family = PF_UNIX;
+ strcpy(sun_server.sun_path, addr);
+ sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket);
+ err = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server,
+ sizeof(struct sockaddr_un) - 1, 0);
+ if (err < 0) {
+ P9_EPRINTK(KERN_ERR,
+ "p9_trans_unix: problem connecting socket: %s: %d\n",
+ addr, err);
+ goto error;
+ }
+
+ err = p9_socket_open(trans, csocket);
+ if (err < 0)
+ goto error;
+
+ return trans;
+
+error:
+ if (csocket)
+ sock_release(csocket);
+
+ kfree(trans);
+ return ERR_PTR(err);
+}
+
+static struct p9_trans *p9_trans_create_fd(const char *name, char *args)
+{
+ int err;
+ struct p9_trans *trans;
+ struct p9_fd_opts opts;
+
+ parse_opts(args, &opts);
+
+ if (opts.rfd == ~0 || opts.wfd == ~0) {
+ printk(KERN_ERR "v9fs: Insufficient options for proto=fd\n");
+ return ERR_PTR(-ENOPROTOOPT);
+ }
+
+ trans = kmalloc(sizeof(struct p9_trans), GFP_KERNEL);
+ if (!trans)
+ return ERR_PTR(-ENOMEM);
+
+ trans->write = p9_fd_write;
+ trans->read = p9_fd_read;
+ trans->close = p9_fd_close;
+ trans->poll = p9_fd_poll;
+
+ err = p9_fd_open(trans, opts.rfd, opts.wfd);
+ if (err < 0)
+ goto error;
+
+ return trans;
+
+error:
+ kfree(trans);
+ return ERR_PTR(err);
+}
+
+static struct p9_trans_module p9_tcp_trans = {
+ .name = "tcp",
+ .maxsize = MAX_SOCK_BUF,
+ .def = 1,
+ .create = p9_trans_create_tcp,
+};
+
+static struct p9_trans_module p9_unix_trans = {
+ .name = "unix",
+ .maxsize = MAX_SOCK_BUF,
+ .def = 0,
+ .create = p9_trans_create_unix,
+};
+
+static struct p9_trans_module p9_fd_trans = {
+ .name = "fd",
+ .maxsize = MAX_SOCK_BUF,
+ .def = 0,
+ .create = p9_trans_create_fd,
+};
+
+static int __init p9_trans_fd_init(void)
+{
+ v9fs_register_trans(&p9_tcp_trans);
+ v9fs_register_trans(&p9_unix_trans);
+ v9fs_register_trans(&p9_fd_trans);
+
+ return 1;
+}
+
+static void __exit p9_trans_fd_exit(void) {
+ printk(KERN_ERR "Removal of 9p transports not implemented\n");
+ BUG();
+}
+
+module_init(p9_trans_fd_init);
+module_exit(p9_trans_fd_exit);
+
+MODULE_AUTHOR("Latchesar Ionkov <lucho@ionkov.net>");
+MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>");
+MODULE_LICENSE("GPL");
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
new file mode 100644
index 000000000000..40b71a29fc3f
--- /dev/null
+++ b/net/9p/trans_virtio.c
@@ -0,0 +1,353 @@
+/*
+ * The Guest 9p transport driver
+ *
+ * This is a trivial pipe-based transport driver based on the lguest console
+ * code: we use lguest's DMA mechanism to send bytes out, and register a
+ * DMA buffer to receive bytes in. It is assumed to be present and available
+ * from the very beginning of boot.
+ *
+ * This may be have been done by just instaniating another HVC console,
+ * but HVC's blocksize of 16 bytes is annoying and painful to performance.
+ *
+ * A more efficient transport could be built based on the virtio block driver
+ * but it requires some changes in the 9p transport model (which are in
+ * progress)
+ *
+ */
+/*
+ * Copyright (C) 2007 Eric Van Hensbergen, IBM Corporation
+ *
+ * Based on virtio console driver
+ * Copyright (C) 2006, 2007 Rusty Russell, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+#include <linux/in.h>
+#include <linux/module.h>
+#include <linux/net.h>
+#include <linux/ipv6.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/un.h>
+#include <linux/uaccess.h>
+#include <linux/inet.h>
+#include <linux/idr.h>
+#include <linux/file.h>
+#include <net/9p/9p.h>
+#include <linux/parser.h>
+#include <net/9p/transport.h>
+#include <linux/scatterlist.h>
+#include <linux/virtio.h>
+#include <linux/virtio_9p.h>
+
+/* a single mutex to manage channel initialization and attachment */
+static DECLARE_MUTEX(virtio_9p_lock);
+/* global which tracks highest initialized channel */
+static int chan_index;
+
+/* We keep all per-channel information in a structure.
+ * This structure is allocated within the devices dev->mem space.
+ * A pointer to the structure will get put in the transport private.
+ */
+static struct virtio_chan {
+ bool initialized; /* channel is initialized */
+ bool inuse; /* channel is in use */
+
+ struct virtqueue *in_vq, *out_vq;
+ struct virtio_device *vdev;
+
+ /* This is our input buffer, and how much data is left in it. */
+ unsigned int in_len;
+ char *in, *inbuf;
+
+ wait_queue_head_t wq; /* waitq for buffer */
+} channels[MAX_9P_CHAN];
+
+/* How many bytes left in this page. */
+static unsigned int rest_of_page(void *data)
+{
+ return PAGE_SIZE - ((unsigned long)data % PAGE_SIZE);
+}
+
+static int p9_virtio_write(struct p9_trans *trans, void *buf, int count)
+{
+ struct virtio_chan *chan = (struct virtio_chan *) trans->priv;
+ struct virtqueue *out_vq = chan->out_vq;
+ struct scatterlist sg[1];
+ unsigned int len;
+
+ P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio write (%d)\n", count);
+
+ /* keep it simple - make sure we don't overflow a page */
+ if (rest_of_page(buf) < count)
+ count = rest_of_page(buf);
+
+ sg_init_one(sg, buf, count);
+
+ /* add_buf wants a token to identify this buffer: we hand it any
+ * non-NULL pointer, since there's only ever one buffer. */
+ if (out_vq->vq_ops->add_buf(out_vq, sg, 1, 0, (void *)1) == 0) {
+ /* Tell Host to go! */
+ out_vq->vq_ops->kick(out_vq);
+ /* Chill out until it's done with the buffer. */
+ while (!out_vq->vq_ops->get_buf(out_vq, &len))
+ cpu_relax();
+ }
+
+ P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio wrote (%d)\n", count);
+
+ /* We're expected to return the amount of data we wrote: all of it. */
+ return count;
+}
+
+/* Create a scatter-gather list representing our input buffer and put it in the
+ * queue. */
+static void add_inbuf(struct virtio_chan *chan)
+{
+ struct scatterlist sg[1];
+
+ sg_init_one(sg, chan->inbuf, PAGE_SIZE);
+
+ /* We should always be able to add one buffer to an empty queue. */
+ if (chan->in_vq->vq_ops->add_buf(chan->in_vq, sg, 0, 1, chan->inbuf))
+ BUG();
+ chan->in_vq->vq_ops->kick(chan->in_vq);
+}
+
+static int p9_virtio_read(struct p9_trans *trans, void *buf, int count)
+{
+ struct virtio_chan *chan = (struct virtio_chan *) trans->priv;
+ struct virtqueue *in_vq = chan->in_vq;
+
+ P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio read (%d)\n", count);
+
+ /* If we don't have an input queue yet, we can't get input. */
+ BUG_ON(!in_vq);
+
+ /* No buffer? Try to get one. */
+ if (!chan->in_len) {
+ chan->in = in_vq->vq_ops->get_buf(in_vq, &chan->in_len);
+ if (!chan->in)
+ return 0;
+ }
+
+ /* You want more than we have to give? Well, try wanting less! */
+ if (chan->in_len < count)
+ count = chan->in_len;
+
+ /* Copy across to their buffer and increment offset. */
+ memcpy(buf, chan->in, count);
+ chan->in += count;
+ chan->in_len -= count;
+
+ /* Finished? Re-register buffer so Host will use it again. */
+ if (chan->in_len == 0)
+ add_inbuf(chan);
+
+ P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio finished read (%d)\n",
+ count);
+
+ return count;
+}
+
+/* The poll function is used by 9p transports to determine if there
+ * is there is activity available on a particular channel. In our case
+ * we use it to wait for a callback from the input routines.
+ */
+static unsigned int
+p9_virtio_poll(struct p9_trans *trans, struct poll_table_struct *pt)
+{
+ struct virtio_chan *chan = (struct virtio_chan *)trans->priv;
+ struct virtqueue *in_vq = chan->in_vq;
+ int ret = POLLOUT; /* we can always handle more output */
+
+ poll_wait(NULL, &chan->wq, pt);
+
+ /* No buffer? Try to get one. */
+ if (!chan->in_len)
+ chan->in = in_vq->vq_ops->get_buf(in_vq, &chan->in_len);
+
+ if (chan->in_len)
+ ret |= POLLIN;
+
+ return ret;
+}
+
+static void p9_virtio_close(struct p9_trans *trans)
+{
+ struct virtio_chan *chan = trans->priv;
+
+ down(&virtio_9p_lock);
+ chan->inuse = false;
+ up(&virtio_9p_lock);
+
+ kfree(trans);
+}
+
+static bool p9_virtio_intr(struct virtqueue *q)
+{
+ struct virtio_chan *chan = q->vdev->priv;
+
+ P9_DPRINTK(P9_DEBUG_TRANS, "9p poll_wakeup: %p\n", &chan->wq);
+ wake_up_interruptible(&chan->wq);
+
+ return true;
+}
+
+static int p9_virtio_probe(struct virtio_device *dev)
+{
+ int err;
+ struct virtio_chan *chan;
+ int index;
+
+ down(&virtio_9p_lock);
+ index = chan_index++;
+ chan = &channels[index];
+ up(&virtio_9p_lock);
+
+ if (chan_index > MAX_9P_CHAN) {
+ printk(KERN_ERR "9p: virtio: Maximum channels exceeded\n");
+ BUG();
+ }
+
+ chan->vdev = dev;
+
+ /* This is the scratch page we use to receive console input */
+ chan->inbuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!chan->inbuf) {
+ err = -ENOMEM;
+ goto fail;
+ }
+
+ /* Find the input queue. */
+ dev->priv = chan;
+ chan->in_vq = dev->config->find_vq(dev, p9_virtio_intr);
+ if (IS_ERR(chan->in_vq)) {
+ err = PTR_ERR(chan->in_vq);
+ goto free;
+ }
+
+ chan->out_vq = dev->config->find_vq(dev, NULL);
+ if (IS_ERR(chan->out_vq)) {
+ err = PTR_ERR(chan->out_vq);
+ goto free_in_vq;
+ }
+
+ init_waitqueue_head(&chan->wq);
+
+ /* Register the input buffer the first time. */
+ add_inbuf(chan);
+ chan->inuse = false;
+ chan->initialized = true;
+
+ return 0;
+
+free_in_vq:
+ dev->config->del_vq(chan->in_vq);
+free:
+ kfree(chan->inbuf);
+fail:
+ down(&virtio_9p_lock);
+ chan_index--;
+ up(&virtio_9p_lock);
+ return err;
+}
+
+/* This sets up a transport channel for 9p communication. Right now
+ * we only match the first available channel, but eventually we couldlook up
+ * alternate channels by matching devname versus a virtio_config entry.
+ * We use a simple reference count mechanism to ensure that only a single
+ * mount has a channel open at a time. */
+static struct p9_trans *p9_virtio_create(const char *devname, char *args)
+{
+ struct p9_trans *trans;
+ int index = 0;
+ struct virtio_chan *chan = channels;
+
+ down(&virtio_9p_lock);
+ while (index < MAX_9P_CHAN) {
+ if (chan->initialized && !chan->inuse) {
+ chan->inuse = true;
+ break;
+ } else {
+ index++;
+ chan = &channels[index];
+ }
+ }
+ up(&virtio_9p_lock);
+
+ if (index >= MAX_9P_CHAN) {
+ printk(KERN_ERR "9p: virtio: couldn't find a free channel\n");
+ return NULL;
+ }
+
+ trans = kmalloc(sizeof(struct p9_trans), GFP_KERNEL);
+ if (!trans) {
+ printk(KERN_ERR "9p: couldn't allocate transport\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ trans->write = p9_virtio_write;
+ trans->read = p9_virtio_read;
+ trans->close = p9_virtio_close;
+ trans->poll = p9_virtio_poll;
+ trans->priv = chan;
+
+ return trans;
+}
+
+#define VIRTIO_ID_9P 9
+
+static struct virtio_device_id id_table[] = {
+ { VIRTIO_ID_9P, VIRTIO_DEV_ANY_ID },
+ { 0 },
+};
+
+/* The standard "struct lguest_driver": */
+static struct virtio_driver p9_virtio_drv = {
+ .driver.name = KBUILD_MODNAME,
+ .driver.owner = THIS_MODULE,
+ .id_table = id_table,
+ .probe = p9_virtio_probe,
+};
+
+static struct p9_trans_module p9_virtio_trans = {
+ .name = "virtio",
+ .create = p9_virtio_create,
+ .maxsize = PAGE_SIZE,
+ .def = 0,
+};
+
+/* The standard init function */
+static int __init p9_virtio_init(void)
+{
+ int count;
+
+ for (count = 0; count < MAX_9P_CHAN; count++)
+ channels[count].initialized = false;
+
+ v9fs_register_trans(&p9_virtio_trans);
+ return register_virtio_driver(&p9_virtio_drv);
+}
+
+module_init(p9_virtio_init);
+
+MODULE_DEVICE_TABLE(virtio, id_table);
+MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>");
+MODULE_DESCRIPTION("Virtio 9p Transport");
+MODULE_LICENSE("GPL");
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 7c0b5151d526..e0d37d6dc1f8 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -1044,7 +1044,7 @@ static int atalk_create(struct net *net, struct socket *sock, int protocol)
if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM)
goto out;
rc = -ENOMEM;
- sk = sk_alloc(net, PF_APPLETALK, GFP_KERNEL, &ddp_proto, 1);
+ sk = sk_alloc(net, PF_APPLETALK, GFP_KERNEL, &ddp_proto);
if (!sk)
goto out;
rc = 0;
diff --git a/net/atm/br2684.c b/net/atm/br2684.c
index c742d37bfb97..ba6428f204f9 100644
--- a/net/atm/br2684.c
+++ b/net/atm/br2684.c
@@ -24,16 +24,6 @@ Author: Marcell GAL, 2000, XDSL Ltd, Hungary
#include "common.h"
-/*
- * Define this to use a version of the code which interacts with the higher
- * layers in a more intellegent way, by always reserving enough space for
- * our header at the begining of the packet. However, there may still be
- * some problems with programs like tcpdump. In 2.5 we'll sort out what
- * we need to do to get this perfect. For now we just will copy the packet
- * if we need space for the header
- */
-/* #define FASTER_VERSION */
-
#ifdef SKB_DEBUG
static void skb_debug(const struct sk_buff *skb)
{
@@ -69,9 +59,7 @@ struct br2684_vcc {
#ifdef CONFIG_ATM_BR2684_IPFILTER
struct br2684_filter filter;
#endif /* CONFIG_ATM_BR2684_IPFILTER */
-#ifndef FASTER_VERSION
unsigned copies_needed, copies_failed;
-#endif /* FASTER_VERSION */
};
struct br2684_dev {
@@ -147,13 +135,6 @@ static int br2684_xmit_vcc(struct sk_buff *skb, struct br2684_dev *brdev,
struct br2684_vcc *brvcc)
{
struct atm_vcc *atmvcc;
-#ifdef FASTER_VERSION
- if (brvcc->encaps == e_llc)
- memcpy(skb_push(skb, 8), llc_oui_pid_pad, 8);
- /* last 2 bytes of llc_oui_pid_pad are managed by header routines;
- yes, you got it: 8 + 2 = sizeof(llc_oui_pid_pad)
- */
-#else
int minheadroom = (brvcc->encaps == e_llc) ? 10 : 2;
if (skb_headroom(skb) < minheadroom) {
struct sk_buff *skb2 = skb_realloc_headroom(skb, minheadroom);
@@ -170,7 +151,6 @@ static int br2684_xmit_vcc(struct sk_buff *skb, struct br2684_dev *brdev,
skb_copy_to_linear_data(skb, llc_oui_pid_pad, 10);
else
memset(skb->data, 0, 2);
-#endif /* FASTER_VERSION */
skb_debug(skb);
ATM_SKB(skb)->vcc = atmvcc = brvcc->atmvcc;
@@ -237,87 +217,6 @@ static struct net_device_stats *br2684_get_stats(struct net_device *dev)
return &BRPRIV(dev)->stats;
}
-#ifdef FASTER_VERSION
-/*
- * These mirror eth_header and eth_header_cache. They are not usually
- * exported for use in modules, so we grab them from net_device
- * after ether_setup() is done with it. Bit of a hack.
- */
-static int (*my_eth_header)(struct sk_buff *, struct net_device *,
- unsigned short, void *, void *, unsigned);
-static int (*my_eth_header_cache)(struct neighbour *, struct hh_cache *);
-
-static int
-br2684_header(struct sk_buff *skb, struct net_device *dev,
- unsigned short type, void *daddr, void *saddr, unsigned len)
-{
- u16 *pad_before_eth;
- int t = my_eth_header(skb, dev, type, daddr, saddr, len);
- if (t > 0) {
- pad_before_eth = (u16 *) skb_push(skb, 2);
- *pad_before_eth = 0;
- return dev->hard_header_len; /* or return 16; ? */
- } else
- return t;
-}
-
-static int
-br2684_header_cache(struct neighbour *neigh, struct hh_cache *hh)
-{
-/* hh_data is 16 bytes long. if encaps is ether-llc we need 24, so
-xmit will add the additional header part in that case */
- u16 *pad_before_eth = (u16 *)(hh->hh_data);
- int t = my_eth_header_cache(neigh, hh);
- DPRINTK("br2684_header_cache, neigh=%p, hh_cache=%p\n", neigh, hh);
- if (t < 0)
- return t;
- else {
- *pad_before_eth = 0;
- hh->hh_len = PADLEN + ETH_HLEN;
- }
- return 0;
-}
-
-/*
- * This is similar to eth_type_trans, which cannot be used because of
- * our dev->hard_header_len
- */
-static inline __be16 br_type_trans(struct sk_buff *skb, struct net_device *dev)
-{
- struct ethhdr *eth;
- unsigned char *rawp;
- eth = eth_hdr(skb);
-
- if (is_multicast_ether_addr(eth->h_dest)) {
- if (!compare_ether_addr(eth->h_dest, dev->broadcast))
- skb->pkt_type = PACKET_BROADCAST;
- else
- skb->pkt_type = PACKET_MULTICAST;
- }
-
- else if (compare_ether_addr(eth->h_dest, dev->dev_addr))
- skb->pkt_type = PACKET_OTHERHOST;
-
- if (ntohs(eth->h_proto) >= 1536)
- return eth->h_proto;
-
- rawp = skb->data;
-
- /*
- * This is a magic hack to spot IPX packets. Older Novell breaks
- * the protocol design and runs IPX over 802.3 without an 802.2 LLC
- * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
- * won't work for fault tolerant netware but does for the rest.
- */
- if (*(unsigned short *) rawp == 0xFFFF)
- return htons(ETH_P_802_3);
-
- /*
- * Real 802.2 LLC
- */
- return htons(ETH_P_802_2);
-}
-#endif /* FASTER_VERSION */
/*
* We remember when the MAC gets set, so we don't override it later with
@@ -448,17 +347,8 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
return;
}
-#ifdef FASTER_VERSION
- /* FIXME: tcpdump shows that pointer to mac header is 2 bytes earlier,
- than should be. What else should I set? */
- skb_pull(skb, plen);
- skb_set_mac_header(skb, -ETH_HLEN);
- skb->pkt_type = PACKET_HOST;
- skb->protocol = br_type_trans(skb, net_dev);
-#else
skb_pull(skb, plen - ETH_HLEN);
skb->protocol = eth_type_trans(skb, net_dev);
-#endif /* FASTER_VERSION */
#ifdef CONFIG_ATM_BR2684_IPFILTER
if (unlikely(packet_fails_filter(skb->protocol, brvcc, skb))) {
brdev->stats.rx_dropped++;
@@ -584,13 +474,6 @@ static void br2684_setup(struct net_device *netdev)
ether_setup(netdev);
brdev->net_dev = netdev;
-#ifdef FASTER_VERSION
- my_eth_header = netdev->hard_header;
- netdev->hard_header = br2684_header;
- my_eth_header_cache = netdev->hard_header_cache;
- netdev->hard_header_cache = br2684_header_cache;
- netdev->hard_header_len = sizeof(llc_oui_pid_pad) + ETH_HLEN; /* 10 + 14 */
-#endif
my_eth_mac_addr = netdev->set_mac_address;
netdev->set_mac_address = br2684_mac_addr;
netdev->hard_start_xmit = br2684_start_xmit;
@@ -719,16 +602,12 @@ static int br2684_seq_show(struct seq_file *seq, void *v)
list_for_each_entry(brvcc, &brdev->brvccs, brvccs) {
seq_printf(seq, " vcc %d.%d.%d: encaps=%s"
-#ifndef FASTER_VERSION
", failed copies %u/%u"
-#endif /* FASTER_VERSION */
"\n", brvcc->atmvcc->dev->number,
brvcc->atmvcc->vpi, brvcc->atmvcc->vci,
(brvcc->encaps == e_llc) ? "LLC" : "VC"
-#ifndef FASTER_VERSION
, brvcc->copies_failed
, brvcc->copies_needed
-#endif /* FASTER_VERSION */
);
#ifdef CONFIG_ATM_BR2684_IPFILTER
#define b1(var, byte) ((u8 *) &brvcc->filter.var)[byte]
diff --git a/net/atm/common.c b/net/atm/common.c
index e166d9e0ffd9..eba09a04f6bf 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -133,7 +133,7 @@ int vcc_create(struct net *net, struct socket *sock, int protocol, int family)
sock->sk = NULL;
if (sock->type == SOCK_STREAM)
return -EINVAL;
- sk = sk_alloc(net, family, GFP_KERNEL, &vcc_proto, 1);
+ sk = sk_alloc(net, family, GFP_KERNEL, &vcc_proto);
if (!sk)
return -ENOMEM;
sock_init_data(sock, sk);
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index 993e5c75e909..8378afd54b30 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -836,7 +836,8 @@ static int ax25_create(struct net *net, struct socket *sock, int protocol)
return -ESOCKTNOSUPPORT;
}
- if ((sk = sk_alloc(net, PF_AX25, GFP_ATOMIC, &ax25_proto, 1)) == NULL)
+ sk = sk_alloc(net, PF_AX25, GFP_ATOMIC, &ax25_proto);
+ if (sk == NULL)
return -ENOMEM;
ax25 = sk->sk_protinfo = ax25_create_cb();
@@ -861,7 +862,8 @@ struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev)
struct sock *sk;
ax25_cb *ax25, *oax25;
- if ((sk = sk_alloc(osk->sk_net, PF_AX25, GFP_ATOMIC, osk->sk_prot, 1)) == NULL)
+ sk = sk_alloc(osk->sk_net, PF_AX25, GFP_ATOMIC, osk->sk_prot);
+ if (sk == NULL)
return NULL;
if ((ax25 = ax25_create_cb()) == NULL) {
diff --git a/net/ax25/ax25_ds_in.c b/net/ax25/ax25_ds_in.c
index e37d217a986a..8273b1200eee 100644
--- a/net/ax25/ax25_ds_in.c
+++ b/net/ax25/ax25_ds_in.c
@@ -75,7 +75,7 @@ static int ax25_ds_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int framet
}
ax25_dama_on(ax25);
- /* according to DK4EG´s spec we are required to
+ /* according to DK4EG's spec we are required to
* send a RR RESPONSE FINAL NR=0.
*/
diff --git a/net/ax25/ax25_ds_subr.c b/net/ax25/ax25_ds_subr.c
index a49773ff2b92..b5e59787be2f 100644
--- a/net/ax25/ax25_ds_subr.c
+++ b/net/ax25/ax25_ds_subr.c
@@ -41,7 +41,7 @@ void ax25_ds_enquiry_response(ax25_cb *ax25)
ax25_cb *ax25o;
struct hlist_node *node;
- /* Please note that neither DK4EG´s nor DG2FEF´s
+ /* Please note that neither DK4EG's nor DG2FEF's
* DAMA spec mention the following behaviour as seen
* with TheFirmware:
*
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
index 1f78c3e336d8..347e935faaf0 100644
--- a/net/bluetooth/bnep/core.c
+++ b/net/bluetooth/bnep/core.c
@@ -2,7 +2,7 @@
BNEP implementation for Linux Bluetooth stack (BlueZ).
Copyright (C) 2001-2002 Inventel Systemes
Written 2001-2002 by
- Clément Moreau <clement.moreau@inventel.fr>
+ Clément Moreau <clement.moreau@inventel.fr>
David Libault <david.libault@inventel.fr>
Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com>
diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c
index 9092816f58de..95e3837e4312 100644
--- a/net/bluetooth/bnep/netdev.c
+++ b/net/bluetooth/bnep/netdev.c
@@ -2,7 +2,7 @@
BNEP implementation for Linux Bluetooth stack (BlueZ).
Copyright (C) 2001-2002 Inventel Systemes
Written 2001-2002 by
- Clément Moreau <clement.moreau@inventel.fr>
+ Clément Moreau <clement.moreau@inventel.fr>
David Libault <david.libault@inventel.fr>
Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com>
diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c
index f718965f296c..9ebd3c64474d 100644
--- a/net/bluetooth/bnep/sock.c
+++ b/net/bluetooth/bnep/sock.c
@@ -213,7 +213,7 @@ static int bnep_sock_create(struct net *net, struct socket *sock, int protocol)
if (sock->type != SOCK_RAW)
return -ESOCKTNOSUPPORT;
- sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &bnep_proto, 1);
+ sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &bnep_proto);
if (!sk)
return -ENOMEM;
diff --git a/net/bluetooth/cmtp/sock.c b/net/bluetooth/cmtp/sock.c
index cf700c20d11e..783edab12ce8 100644
--- a/net/bluetooth/cmtp/sock.c
+++ b/net/bluetooth/cmtp/sock.c
@@ -204,7 +204,7 @@ static int cmtp_sock_create(struct net *net, struct socket *sock, int protocol)
if (sock->type != SOCK_RAW)
return -ESOCKTNOSUPPORT;
- sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &cmtp_proto, 1);
+ sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &cmtp_proto);
if (!sk)
return -ENOMEM;
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 5fdfc9a67d39..9483320f6dad 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -78,11 +78,11 @@ void hci_acl_connect(struct hci_conn *conn)
cp.pkt_type = cpu_to_le16(hdev->pkt_type & ACL_PTYPE_MASK);
if (lmp_rswitch_capable(hdev) && !(hdev->link_mode & HCI_LM_MASTER))
- cp.role_switch = 0x01;
+ cp.role_switch = 0x01;
else
- cp.role_switch = 0x00;
+ cp.role_switch = 0x00;
- hci_send_cmd(hdev, OGF_LINK_CTL, OCF_CREATE_CONN, sizeof(cp), &cp);
+ hci_send_cmd(hdev, HCI_OP_CREATE_CONN, sizeof(cp), &cp);
}
static void hci_acl_connect_cancel(struct hci_conn *conn)
@@ -95,8 +95,7 @@ static void hci_acl_connect_cancel(struct hci_conn *conn)
return;
bacpy(&cp.bdaddr, &conn->dst);
- hci_send_cmd(conn->hdev, OGF_LINK_CTL,
- OCF_CREATE_CONN_CANCEL, sizeof(cp), &cp);
+ hci_send_cmd(conn->hdev, HCI_OP_CREATE_CONN_CANCEL, sizeof(cp), &cp);
}
void hci_acl_disconn(struct hci_conn *conn, __u8 reason)
@@ -109,8 +108,7 @@ void hci_acl_disconn(struct hci_conn *conn, __u8 reason)
cp.handle = cpu_to_le16(conn->handle);
cp.reason = reason;
- hci_send_cmd(conn->hdev, OGF_LINK_CTL,
- OCF_DISCONNECT, sizeof(cp), &cp);
+ hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp);
}
void hci_add_sco(struct hci_conn *conn, __u16 handle)
@@ -126,7 +124,29 @@ void hci_add_sco(struct hci_conn *conn, __u16 handle)
cp.handle = cpu_to_le16(handle);
cp.pkt_type = cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK);
- hci_send_cmd(hdev, OGF_LINK_CTL, OCF_ADD_SCO, sizeof(cp), &cp);
+ hci_send_cmd(hdev, HCI_OP_ADD_SCO, sizeof(cp), &cp);
+}
+
+void hci_setup_sync(struct hci_conn *conn, __u16 handle)
+{
+ struct hci_dev *hdev = conn->hdev;
+ struct hci_cp_setup_sync_conn cp;
+
+ BT_DBG("%p", conn);
+
+ conn->state = BT_CONNECT;
+ conn->out = 1;
+
+ cp.handle = cpu_to_le16(handle);
+ cp.pkt_type = cpu_to_le16(hdev->esco_type);
+
+ cp.tx_bandwidth = cpu_to_le32(0x00001f40);
+ cp.rx_bandwidth = cpu_to_le32(0x00001f40);
+ cp.max_latency = cpu_to_le16(0xffff);
+ cp.voice_setting = cpu_to_le16(hdev->voice_setting);
+ cp.retrans_effort = 0xff;
+
+ hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp);
}
static void hci_conn_timeout(unsigned long arg)
@@ -143,7 +163,10 @@ static void hci_conn_timeout(unsigned long arg)
switch (conn->state) {
case BT_CONNECT:
- hci_acl_connect_cancel(conn);
+ if (conn->type == ACL_LINK)
+ hci_acl_connect_cancel(conn);
+ else
+ hci_acl_disconn(conn, 0x13);
break;
case BT_CONNECTED:
hci_acl_disconn(conn, 0x13);
@@ -330,8 +353,12 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)
hci_conn_hold(sco);
if (acl->state == BT_CONNECTED &&
- (sco->state == BT_OPEN || sco->state == BT_CLOSED))
- hci_add_sco(sco, acl->handle);
+ (sco->state == BT_OPEN || sco->state == BT_CLOSED)) {
+ if (lmp_esco_capable(hdev))
+ hci_setup_sync(sco, acl->handle);
+ else
+ hci_add_sco(sco, acl->handle);
+ }
return sco;
}
@@ -348,7 +375,7 @@ int hci_conn_auth(struct hci_conn *conn)
if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
struct hci_cp_auth_requested cp;
cp.handle = cpu_to_le16(conn->handle);
- hci_send_cmd(conn->hdev, OGF_LINK_CTL, OCF_AUTH_REQUESTED, sizeof(cp), &cp);
+ hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
}
return 0;
}
@@ -369,7 +396,7 @@ int hci_conn_encrypt(struct hci_conn *conn)
struct hci_cp_set_conn_encrypt cp;
cp.handle = cpu_to_le16(conn->handle);
cp.encrypt = 1;
- hci_send_cmd(conn->hdev, OGF_LINK_CTL, OCF_SET_CONN_ENCRYPT, sizeof(cp), &cp);
+ hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), &cp);
}
return 0;
}
@@ -383,7 +410,7 @@ int hci_conn_change_link_key(struct hci_conn *conn)
if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
struct hci_cp_change_conn_link_key cp;
cp.handle = cpu_to_le16(conn->handle);
- hci_send_cmd(conn->hdev, OGF_LINK_CTL, OCF_CHANGE_CONN_LINK_KEY, sizeof(cp), &cp);
+ hci_send_cmd(conn->hdev, HCI_OP_CHANGE_CONN_LINK_KEY, sizeof(cp), &cp);
}
return 0;
}
@@ -401,7 +428,7 @@ int hci_conn_switch_role(struct hci_conn *conn, uint8_t role)
struct hci_cp_switch_role cp;
bacpy(&cp.bdaddr, &conn->dst);
cp.role = role;
- hci_send_cmd(conn->hdev, OGF_LINK_POLICY, OCF_SWITCH_ROLE, sizeof(cp), &cp);
+ hci_send_cmd(conn->hdev, HCI_OP_SWITCH_ROLE, sizeof(cp), &cp);
}
return 0;
}
@@ -423,8 +450,7 @@ void hci_conn_enter_active_mode(struct hci_conn *conn)
if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
struct hci_cp_exit_sniff_mode cp;
cp.handle = cpu_to_le16(conn->handle);
- hci_send_cmd(hdev, OGF_LINK_POLICY,
- OCF_EXIT_SNIFF_MODE, sizeof(cp), &cp);
+ hci_send_cmd(hdev, HCI_OP_EXIT_SNIFF_MODE, sizeof(cp), &cp);
}
timer:
@@ -455,8 +481,7 @@ void hci_conn_enter_sniff_mode(struct hci_conn *conn)
cp.max_latency = cpu_to_le16(0);
cp.min_remote_timeout = cpu_to_le16(0);
cp.min_local_timeout = cpu_to_le16(0);
- hci_send_cmd(hdev, OGF_LINK_POLICY,
- OCF_SNIFF_SUBRATE, sizeof(cp), &cp);
+ hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp);
}
if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
@@ -466,8 +491,7 @@ void hci_conn_enter_sniff_mode(struct hci_conn *conn)
cp.min_interval = cpu_to_le16(hdev->sniff_min_interval);
cp.attempt = cpu_to_le16(4);
cp.timeout = cpu_to_le16(1);
- hci_send_cmd(hdev, OGF_LINK_POLICY,
- OCF_SNIFF_MODE, sizeof(cp), &cp);
+ hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp);
}
}
@@ -493,6 +517,22 @@ void hci_conn_hash_flush(struct hci_dev *hdev)
}
}
+/* Check pending connect attempts */
+void hci_conn_check_pending(struct hci_dev *hdev)
+{
+ struct hci_conn *conn;
+
+ BT_DBG("hdev %s", hdev->name);
+
+ hci_dev_lock(hdev);
+
+ conn = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
+ if (conn)
+ hci_acl_connect(conn);
+
+ hci_dev_unlock(hdev);
+}
+
int hci_get_conn_list(void __user *arg)
{
struct hci_conn_list_req req, *cl;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 18e3afc964df..372b0d3b75a8 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -176,7 +176,7 @@ static void hci_reset_req(struct hci_dev *hdev, unsigned long opt)
BT_DBG("%s %ld", hdev->name, opt);
/* Reset device */
- hci_send_cmd(hdev, OGF_HOST_CTL, OCF_RESET, 0, NULL);
+ hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL);
}
static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
@@ -202,16 +202,16 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
/* Reset */
if (test_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks))
- hci_send_cmd(hdev, OGF_HOST_CTL, OCF_RESET, 0, NULL);
+ hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL);
/* Read Local Supported Features */
- hci_send_cmd(hdev, OGF_INFO_PARAM, OCF_READ_LOCAL_FEATURES, 0, NULL);
+ hci_send_cmd(hdev, HCI_OP_READ_LOCAL_FEATURES, 0, NULL);
/* Read Local Version */
- hci_send_cmd(hdev, OGF_INFO_PARAM, OCF_READ_LOCAL_VERSION, 0, NULL);
+ hci_send_cmd(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL);
/* Read Buffer Size (ACL mtu, max pkt, etc.) */
- hci_send_cmd(hdev, OGF_INFO_PARAM, OCF_READ_BUFFER_SIZE, 0, NULL);
+ hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL);
#if 0
/* Host buffer size */
@@ -221,29 +221,35 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
cp.sco_mtu = HCI_MAX_SCO_SIZE;
cp.acl_max_pkt = cpu_to_le16(0xffff);
cp.sco_max_pkt = cpu_to_le16(0xffff);
- hci_send_cmd(hdev, OGF_HOST_CTL, OCF_HOST_BUFFER_SIZE, sizeof(cp), &cp);
+ hci_send_cmd(hdev, HCI_OP_HOST_BUFFER_SIZE, sizeof(cp), &cp);
}
#endif
/* Read BD Address */
- hci_send_cmd(hdev, OGF_INFO_PARAM, OCF_READ_BD_ADDR, 0, NULL);
+ hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL);
+
+ /* Read Class of Device */
+ hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL);
+
+ /* Read Local Name */
+ hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL);
/* Read Voice Setting */
- hci_send_cmd(hdev, OGF_HOST_CTL, OCF_READ_VOICE_SETTING, 0, NULL);
+ hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL);
/* Optional initialization */
/* Clear Event Filters */
flt_type = HCI_FLT_CLEAR_ALL;
- hci_send_cmd(hdev, OGF_HOST_CTL, OCF_SET_EVENT_FLT, 1, &flt_type);
+ hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type);
/* Page timeout ~20 secs */
param = cpu_to_le16(0x8000);
- hci_send_cmd(hdev, OGF_HOST_CTL, OCF_WRITE_PG_TIMEOUT, 2, &param);
+ hci_send_cmd(hdev, HCI_OP_WRITE_PG_TIMEOUT, 2, &param);
/* Connection accept timeout ~20 secs */
param = cpu_to_le16(0x7d00);
- hci_send_cmd(hdev, OGF_HOST_CTL, OCF_WRITE_CA_TIMEOUT, 2, &param);
+ hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, &param);
}
static void hci_scan_req(struct hci_dev *hdev, unsigned long opt)
@@ -253,7 +259,7 @@ static void hci_scan_req(struct hci_dev *hdev, unsigned long opt)
BT_DBG("%s %x", hdev->name, scan);
/* Inquiry and Page scans */
- hci_send_cmd(hdev, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE, 1, &scan);
+ hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
}
static void hci_auth_req(struct hci_dev *hdev, unsigned long opt)
@@ -263,7 +269,7 @@ static void hci_auth_req(struct hci_dev *hdev, unsigned long opt)
BT_DBG("%s %x", hdev->name, auth);
/* Authentication */
- hci_send_cmd(hdev, OGF_HOST_CTL, OCF_WRITE_AUTH_ENABLE, 1, &auth);
+ hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, 1, &auth);
}
static void hci_encrypt_req(struct hci_dev *hdev, unsigned long opt)
@@ -273,7 +279,7 @@ static void hci_encrypt_req(struct hci_dev *hdev, unsigned long opt)
BT_DBG("%s %x", hdev->name, encrypt);
/* Authentication */
- hci_send_cmd(hdev, OGF_HOST_CTL, OCF_WRITE_ENCRYPT_MODE, 1, &encrypt);
+ hci_send_cmd(hdev, HCI_OP_WRITE_ENCRYPT_MODE, 1, &encrypt);
}
/* Get HCI device by index.
@@ -384,7 +390,7 @@ static void hci_inq_req(struct hci_dev *hdev, unsigned long opt)
memcpy(&cp.lap, &ir->lap, 3);
cp.length = ir->length;
cp.num_rsp = ir->num_rsp;
- hci_send_cmd(hdev, OGF_LINK_CTL, OCF_INQUIRY, sizeof(cp), &cp);
+ hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp);
}
int hci_inquiry(void __user *arg)
@@ -1111,13 +1117,13 @@ static int hci_send_frame(struct sk_buff *skb)
}
/* Send HCI command */
-int hci_send_cmd(struct hci_dev *hdev, __u16 ogf, __u16 ocf, __u32 plen, void *param)
+int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param)
{
int len = HCI_COMMAND_HDR_SIZE + plen;
struct hci_command_hdr *hdr;
struct sk_buff *skb;
- BT_DBG("%s ogf 0x%x ocf 0x%x plen %d", hdev->name, ogf, ocf, plen);
+ BT_DBG("%s opcode 0x%x plen %d", hdev->name, opcode, plen);
skb = bt_skb_alloc(len, GFP_ATOMIC);
if (!skb) {
@@ -1126,7 +1132,7 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 ogf, __u16 ocf, __u32 plen, void *p
}
hdr = (struct hci_command_hdr *) skb_put(skb, HCI_COMMAND_HDR_SIZE);
- hdr->opcode = cpu_to_le16(hci_opcode_pack(ogf, ocf));
+ hdr->opcode = cpu_to_le16(opcode);
hdr->plen = plen;
if (plen)
@@ -1143,7 +1149,7 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 ogf, __u16 ocf, __u32 plen, void *p
}
/* Get data from the previously sent command */
-void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 ogf, __u16 ocf)
+void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode)
{
struct hci_command_hdr *hdr;
@@ -1152,10 +1158,10 @@ void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 ogf, __u16 ocf)
hdr = (void *) hdev->sent_cmd->data;
- if (hdr->opcode != cpu_to_le16(hci_opcode_pack(ogf, ocf)))
+ if (hdr->opcode != cpu_to_le16(opcode))
return NULL;
- BT_DBG("%s ogf 0x%x ocf 0x%x", hdev->name, ogf, ocf);
+ BT_DBG("%s opcode 0x%x", hdev->name, opcode);
return hdev->sent_cmd->data + HCI_COMMAND_HDR_SIZE;
}
@@ -1355,6 +1361,26 @@ static inline void hci_sched_sco(struct hci_dev *hdev)
}
}
+static inline void hci_sched_esco(struct hci_dev *hdev)
+{
+ struct hci_conn *conn;
+ struct sk_buff *skb;
+ int quote;
+
+ BT_DBG("%s", hdev->name);
+
+ while (hdev->sco_cnt && (conn = hci_low_sent(hdev, ESCO_LINK, &quote))) {
+ while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
+ BT_DBG("skb %p len %d", skb, skb->len);
+ hci_send_frame(skb);
+
+ conn->sent++;
+ if (conn->sent == ~0)
+ conn->sent = 0;
+ }
+ }
+}
+
static void hci_tx_task(unsigned long arg)
{
struct hci_dev *hdev = (struct hci_dev *) arg;
@@ -1370,6 +1396,8 @@ static void hci_tx_task(unsigned long arg)
hci_sched_sco(hdev);
+ hci_sched_esco(hdev);
+
/* Send next queued raw (unknown type) packet */
while ((skb = skb_dequeue(&hdev->raw_q)))
hci_send_frame(skb);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 4baea1e38652..46df2e403df8 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -52,234 +52,273 @@
/* Handle HCI Event packets */
-/* Command Complete OGF LINK_CTL */
-static void hci_cc_link_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb)
+static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
{
- __u8 status;
- struct hci_conn *pend;
+ __u8 status = *((__u8 *) skb->data);
- BT_DBG("%s ocf 0x%x", hdev->name, ocf);
+ BT_DBG("%s status 0x%x", hdev->name, status);
- switch (ocf) {
- case OCF_INQUIRY_CANCEL:
- case OCF_EXIT_PERIODIC_INQ:
- status = *((__u8 *) skb->data);
+ if (status)
+ return;
- if (status) {
- BT_DBG("%s Inquiry cancel error: status 0x%x", hdev->name, status);
- } else {
- clear_bit(HCI_INQUIRY, &hdev->flags);
- hci_req_complete(hdev, status);
- }
+ clear_bit(HCI_INQUIRY, &hdev->flags);
- hci_dev_lock(hdev);
+ hci_req_complete(hdev, status);
- pend = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
- if (pend)
- hci_acl_connect(pend);
+ hci_conn_check_pending(hdev);
+}
- hci_dev_unlock(hdev);
+static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ __u8 status = *((__u8 *) skb->data);
- break;
+ BT_DBG("%s status 0x%x", hdev->name, status);
- default:
- BT_DBG("%s Command complete: ogf LINK_CTL ocf %x", hdev->name, ocf);
- break;
+ if (status)
+ return;
+
+ clear_bit(HCI_INQUIRY, &hdev->flags);
+
+ hci_conn_check_pending(hdev);
+}
+
+static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ BT_DBG("%s", hdev->name);
+}
+
+static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_rp_role_discovery *rp = (void *) skb->data;
+ struct hci_conn *conn;
+
+ BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+ if (rp->status)
+ return;
+
+ hci_dev_lock(hdev);
+
+ conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
+ if (conn) {
+ if (rp->role)
+ conn->link_mode &= ~HCI_LM_MASTER;
+ else
+ conn->link_mode |= HCI_LM_MASTER;
}
+
+ hci_dev_unlock(hdev);
}
-/* Command Complete OGF LINK_POLICY */
-static void hci_cc_link_policy(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb)
+static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
{
+ struct hci_rp_write_link_policy *rp = (void *) skb->data;
struct hci_conn *conn;
- struct hci_rp_role_discovery *rd;
- struct hci_rp_write_link_policy *lp;
void *sent;
- BT_DBG("%s ocf 0x%x", hdev->name, ocf);
+ BT_DBG("%s status 0x%x", hdev->name, rp->status);
- switch (ocf) {
- case OCF_ROLE_DISCOVERY:
- rd = (void *) skb->data;
+ if (rp->status)
+ return;
- if (rd->status)
- break;
+ sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
+ if (!sent)
+ return;
- hci_dev_lock(hdev);
+ hci_dev_lock(hdev);
- conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rd->handle));
- if (conn) {
- if (rd->role)
- conn->link_mode &= ~HCI_LM_MASTER;
- else
- conn->link_mode |= HCI_LM_MASTER;
- }
+ conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
+ if (conn) {
+ __le16 policy = get_unaligned((__le16 *) (sent + 2));
+ conn->link_policy = __le16_to_cpu(policy);
+ }
- hci_dev_unlock(hdev);
- break;
+ hci_dev_unlock(hdev);
+}
- case OCF_WRITE_LINK_POLICY:
- sent = hci_sent_cmd_data(hdev, OGF_LINK_POLICY, OCF_WRITE_LINK_POLICY);
- if (!sent)
- break;
+static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ __u8 status = *((__u8 *) skb->data);
- lp = (struct hci_rp_write_link_policy *) skb->data;
+ BT_DBG("%s status 0x%x", hdev->name, status);
- if (lp->status)
- break;
+ hci_req_complete(hdev, status);
+}
- hci_dev_lock(hdev);
+static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ __u8 status = *((__u8 *) skb->data);
+ void *sent;
- conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(lp->handle));
- if (conn) {
- __le16 policy = get_unaligned((__le16 *) (sent + 2));
- conn->link_policy = __le16_to_cpu(policy);
- }
+ BT_DBG("%s status 0x%x", hdev->name, status);
- hci_dev_unlock(hdev);
- break;
+ sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
+ if (!sent)
+ return;
- default:
- BT_DBG("%s: Command complete: ogf LINK_POLICY ocf %x",
- hdev->name, ocf);
- break;
+ if (!status)
+ memcpy(hdev->dev_name, sent, 248);
+}
+
+static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_rp_read_local_name *rp = (void *) skb->data;
+
+ BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+ if (rp->status)
+ return;
+
+ memcpy(hdev->dev_name, rp->name, 248);
+}
+
+static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ __u8 status = *((__u8 *) skb->data);
+ void *sent;
+
+ BT_DBG("%s status 0x%x", hdev->name, status);
+
+ sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
+ if (!sent)
+ return;
+
+ if (!status) {
+ __u8 param = *((__u8 *) sent);
+
+ if (param == AUTH_ENABLED)
+ set_bit(HCI_AUTH, &hdev->flags);
+ else
+ clear_bit(HCI_AUTH, &hdev->flags);
}
+
+ hci_req_complete(hdev, status);
}
-/* Command Complete OGF HOST_CTL */
-static void hci_cc_host_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb)
+static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
{
- __u8 status, param;
- __u16 setting;
- struct hci_rp_read_voice_setting *vs;
+ __u8 status = *((__u8 *) skb->data);
void *sent;
- BT_DBG("%s ocf 0x%x", hdev->name, ocf);
+ BT_DBG("%s status 0x%x", hdev->name, status);
- switch (ocf) {
- case OCF_RESET:
- status = *((__u8 *) skb->data);
- hci_req_complete(hdev, status);
- break;
+ sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
+ if (!sent)
+ return;
- case OCF_SET_EVENT_FLT:
- status = *((__u8 *) skb->data);
- if (status) {
- BT_DBG("%s SET_EVENT_FLT failed %d", hdev->name, status);
- } else {
- BT_DBG("%s SET_EVENT_FLT succeseful", hdev->name);
- }
- break;
+ if (!status) {
+ __u8 param = *((__u8 *) sent);
- case OCF_WRITE_AUTH_ENABLE:
- sent = hci_sent_cmd_data(hdev, OGF_HOST_CTL, OCF_WRITE_AUTH_ENABLE);
- if (!sent)
- break;
+ if (param)
+ set_bit(HCI_ENCRYPT, &hdev->flags);
+ else
+ clear_bit(HCI_ENCRYPT, &hdev->flags);
+ }
- status = *((__u8 *) skb->data);
- param = *((__u8 *) sent);
+ hci_req_complete(hdev, status);
+}
- if (!status) {
- if (param == AUTH_ENABLED)
- set_bit(HCI_AUTH, &hdev->flags);
- else
- clear_bit(HCI_AUTH, &hdev->flags);
- }
- hci_req_complete(hdev, status);
- break;
+static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ __u8 status = *((__u8 *) skb->data);
+ void *sent;
- case OCF_WRITE_ENCRYPT_MODE:
- sent = hci_sent_cmd_data(hdev, OGF_HOST_CTL, OCF_WRITE_ENCRYPT_MODE);
- if (!sent)
- break;
+ BT_DBG("%s status 0x%x", hdev->name, status);
- status = *((__u8 *) skb->data);
- param = *((__u8 *) sent);
+ sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
+ if (!sent)
+ return;
- if (!status) {
- if (param)
- set_bit(HCI_ENCRYPT, &hdev->flags);
- else
- clear_bit(HCI_ENCRYPT, &hdev->flags);
- }
- hci_req_complete(hdev, status);
- break;
+ if (!status) {
+ __u8 param = *((__u8 *) sent);
- case OCF_WRITE_CA_TIMEOUT:
- status = *((__u8 *) skb->data);
- if (status) {
- BT_DBG("%s OCF_WRITE_CA_TIMEOUT failed %d", hdev->name, status);
- } else {
- BT_DBG("%s OCF_WRITE_CA_TIMEOUT succeseful", hdev->name);
- }
- break;
+ clear_bit(HCI_PSCAN, &hdev->flags);
+ clear_bit(HCI_ISCAN, &hdev->flags);
- case OCF_WRITE_PG_TIMEOUT:
- status = *((__u8 *) skb->data);
- if (status) {
- BT_DBG("%s OCF_WRITE_PG_TIMEOUT failed %d", hdev->name, status);
- } else {
- BT_DBG("%s: OCF_WRITE_PG_TIMEOUT succeseful", hdev->name);
- }
- break;
+ if (param & SCAN_INQUIRY)
+ set_bit(HCI_ISCAN, &hdev->flags);
- case OCF_WRITE_SCAN_ENABLE:
- sent = hci_sent_cmd_data(hdev, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE);
- if (!sent)
- break;
+ if (param & SCAN_PAGE)
+ set_bit(HCI_PSCAN, &hdev->flags);
+ }
- status = *((__u8 *) skb->data);
- param = *((__u8 *) sent);
+ hci_req_complete(hdev, status);
+}
- BT_DBG("param 0x%x", param);
+static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
- if (!status) {
- clear_bit(HCI_PSCAN, &hdev->flags);
- clear_bit(HCI_ISCAN, &hdev->flags);
- if (param & SCAN_INQUIRY)
- set_bit(HCI_ISCAN, &hdev->flags);
+ BT_DBG("%s status 0x%x", hdev->name, rp->status);
- if (param & SCAN_PAGE)
- set_bit(HCI_PSCAN, &hdev->flags);
- }
- hci_req_complete(hdev, status);
- break;
+ if (rp->status)
+ return;
- case OCF_READ_VOICE_SETTING:
- vs = (struct hci_rp_read_voice_setting *) skb->data;
+ memcpy(hdev->dev_class, rp->dev_class, 3);
- if (vs->status) {
- BT_DBG("%s READ_VOICE_SETTING failed %d", hdev->name, vs->status);
- break;
- }
+ BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
+ hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
+}
- setting = __le16_to_cpu(vs->voice_setting);
+static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ __u8 status = *((__u8 *) skb->data);
+ void *sent;
- if (hdev->voice_setting != setting ) {
- hdev->voice_setting = setting;
+ BT_DBG("%s status 0x%x", hdev->name, status);
- BT_DBG("%s: voice setting 0x%04x", hdev->name, setting);
+ sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
+ if (!sent)
+ return;
- if (hdev->notify) {
- tasklet_disable(&hdev->tx_task);
- hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
- tasklet_enable(&hdev->tx_task);
- }
- }
- break;
+ if (!status)
+ memcpy(hdev->dev_class, sent, 3);
+}
- case OCF_WRITE_VOICE_SETTING:
- sent = hci_sent_cmd_data(hdev, OGF_HOST_CTL, OCF_WRITE_VOICE_SETTING);
- if (!sent)
- break;
+static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_rp_read_voice_setting *rp = (void *) skb->data;
+ __u16 setting;
+
+ BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+ if (rp->status)
+ return;
+
+ setting = __le16_to_cpu(rp->voice_setting);
+
+ if (hdev->voice_setting == setting )
+ return;
+
+ hdev->voice_setting = setting;
- status = *((__u8 *) skb->data);
- setting = __le16_to_cpu(get_unaligned((__le16 *) sent));
+ BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
- if (!status && hdev->voice_setting != setting) {
+ if (hdev->notify) {
+ tasklet_disable(&hdev->tx_task);
+ hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
+ tasklet_enable(&hdev->tx_task);
+ }
+}
+
+static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ __u8 status = *((__u8 *) skb->data);
+ void *sent;
+
+ BT_DBG("%s status 0x%x", hdev->name, status);
+
+ sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
+ if (!sent)
+ return;
+
+ if (!status) {
+ __u16 setting = __le16_to_cpu(get_unaligned((__le16 *) sent));
+
+ if (hdev->voice_setting != setting) {
hdev->voice_setting = setting;
- BT_DBG("%s: voice setting 0x%04x", hdev->name, setting);
+ BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
if (hdev->notify) {
tasklet_disable(&hdev->tx_task);
@@ -287,143 +326,153 @@ static void hci_cc_host_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb
tasklet_enable(&hdev->tx_task);
}
}
- hci_req_complete(hdev, status);
- break;
-
- case OCF_HOST_BUFFER_SIZE:
- status = *((__u8 *) skb->data);
- if (status) {
- BT_DBG("%s OCF_BUFFER_SIZE failed %d", hdev->name, status);
- hci_req_complete(hdev, status);
- }
- break;
-
- default:
- BT_DBG("%s Command complete: ogf HOST_CTL ocf %x", hdev->name, ocf);
- break;
}
}
-/* Command Complete OGF INFO_PARAM */
-static void hci_cc_info_param(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb)
+static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_rp_read_loc_version *lv;
- struct hci_rp_read_local_features *lf;
- struct hci_rp_read_buffer_size *bs;
- struct hci_rp_read_bd_addr *ba;
+ __u8 status = *((__u8 *) skb->data);
- BT_DBG("%s ocf 0x%x", hdev->name, ocf);
+ BT_DBG("%s status 0x%x", hdev->name, status);
- switch (ocf) {
- case OCF_READ_LOCAL_VERSION:
- lv = (struct hci_rp_read_loc_version *) skb->data;
+ hci_req_complete(hdev, status);
+}
- if (lv->status) {
- BT_DBG("%s READ_LOCAL_VERSION failed %d", hdev->name, lf->status);
- break;
- }
+static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_rp_read_local_version *rp = (void *) skb->data;
- hdev->hci_ver = lv->hci_ver;
- hdev->hci_rev = btohs(lv->hci_rev);
- hdev->manufacturer = btohs(lv->manufacturer);
+ BT_DBG("%s status 0x%x", hdev->name, rp->status);
- BT_DBG("%s: manufacturer %d hci_ver %d hci_rev %d", hdev->name,
- hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
+ if (rp->status)
+ return;
- break;
+ hdev->hci_ver = rp->hci_ver;
+ hdev->hci_rev = btohs(rp->hci_rev);
+ hdev->manufacturer = btohs(rp->manufacturer);
- case OCF_READ_LOCAL_FEATURES:
- lf = (struct hci_rp_read_local_features *) skb->data;
+ BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
+ hdev->manufacturer,
+ hdev->hci_ver, hdev->hci_rev);
+}
- if (lf->status) {
- BT_DBG("%s READ_LOCAL_FEATURES failed %d", hdev->name, lf->status);
- break;
- }
+static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_rp_read_local_commands *rp = (void *) skb->data;
- memcpy(hdev->features, lf->features, sizeof(hdev->features));
+ BT_DBG("%s status 0x%x", hdev->name, rp->status);
- /* Adjust default settings according to features
- * supported by device. */
- if (hdev->features[0] & LMP_3SLOT)
- hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
+ if (rp->status)
+ return;
- if (hdev->features[0] & LMP_5SLOT)
- hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
+ memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
+}
- if (hdev->features[1] & LMP_HV2) {
- hdev->pkt_type |= (HCI_HV2);
- hdev->esco_type |= (ESCO_HV2);
- }
+static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_rp_read_local_features *rp = (void *) skb->data;
- if (hdev->features[1] & LMP_HV3) {
- hdev->pkt_type |= (HCI_HV3);
- hdev->esco_type |= (ESCO_HV3);
- }
+ BT_DBG("%s status 0x%x", hdev->name, rp->status);
- if (hdev->features[3] & LMP_ESCO)
- hdev->esco_type |= (ESCO_EV3);
+ if (rp->status)
+ return;
- if (hdev->features[4] & LMP_EV4)
- hdev->esco_type |= (ESCO_EV4);
+ memcpy(hdev->features, rp->features, 8);
- if (hdev->features[4] & LMP_EV5)
- hdev->esco_type |= (ESCO_EV5);
+ /* Adjust default settings according to features
+ * supported by device. */
- BT_DBG("%s: features 0x%x 0x%x 0x%x", hdev->name,
- lf->features[0], lf->features[1], lf->features[2]);
+ if (hdev->features[0] & LMP_3SLOT)
+ hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
- break;
+ if (hdev->features[0] & LMP_5SLOT)
+ hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
- case OCF_READ_BUFFER_SIZE:
- bs = (struct hci_rp_read_buffer_size *) skb->data;
+ if (hdev->features[1] & LMP_HV2) {
+ hdev->pkt_type |= (HCI_HV2);
+ hdev->esco_type |= (ESCO_HV2);
+ }
- if (bs->status) {
- BT_DBG("%s READ_BUFFER_SIZE failed %d", hdev->name, bs->status);
- hci_req_complete(hdev, bs->status);
- break;
- }
+ if (hdev->features[1] & LMP_HV3) {
+ hdev->pkt_type |= (HCI_HV3);
+ hdev->esco_type |= (ESCO_HV3);
+ }
- hdev->acl_mtu = __le16_to_cpu(bs->acl_mtu);
- hdev->sco_mtu = bs->sco_mtu;
- hdev->acl_pkts = __le16_to_cpu(bs->acl_max_pkt);
- hdev->sco_pkts = __le16_to_cpu(bs->sco_max_pkt);
+ if (hdev->features[3] & LMP_ESCO)
+ hdev->esco_type |= (ESCO_EV3);
- if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
- hdev->sco_mtu = 64;
- hdev->sco_pkts = 8;
- }
+ if (hdev->features[4] & LMP_EV4)
+ hdev->esco_type |= (ESCO_EV4);
- hdev->acl_cnt = hdev->acl_pkts;
- hdev->sco_cnt = hdev->sco_pkts;
+ if (hdev->features[4] & LMP_EV5)
+ hdev->esco_type |= (ESCO_EV5);
- BT_DBG("%s mtu: acl %d, sco %d max_pkt: acl %d, sco %d", hdev->name,
- hdev->acl_mtu, hdev->sco_mtu, hdev->acl_pkts, hdev->sco_pkts);
- break;
+ BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
+ hdev->features[0], hdev->features[1],
+ hdev->features[2], hdev->features[3],
+ hdev->features[4], hdev->features[5],
+ hdev->features[6], hdev->features[7]);
+}
- case OCF_READ_BD_ADDR:
- ba = (struct hci_rp_read_bd_addr *) skb->data;
+static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_rp_read_buffer_size *rp = (void *) skb->data;
- if (!ba->status) {
- bacpy(&hdev->bdaddr, &ba->bdaddr);
- } else {
- BT_DBG("%s: READ_BD_ADDR failed %d", hdev->name, ba->status);
- }
+ BT_DBG("%s status 0x%x", hdev->name, rp->status);
- hci_req_complete(hdev, ba->status);
- break;
+ if (rp->status)
+ return;
- default:
- BT_DBG("%s Command complete: ogf INFO_PARAM ocf %x", hdev->name, ocf);
- break;
+ hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu);
+ hdev->sco_mtu = rp->sco_mtu;
+ hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
+ hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
+
+ if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
+ hdev->sco_mtu = 64;
+ hdev->sco_pkts = 8;
}
+
+ hdev->acl_cnt = hdev->acl_pkts;
+ hdev->sco_cnt = hdev->sco_pkts;
+
+ BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
+ hdev->acl_mtu, hdev->acl_pkts,
+ hdev->sco_mtu, hdev->sco_pkts);
+}
+
+static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_rp_read_bd_addr *rp = (void *) skb->data;
+
+ BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+ if (!rp->status)
+ bacpy(&hdev->bdaddr, &rp->bdaddr);
+
+ hci_req_complete(hdev, rp->status);
+}
+
+static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
+{
+ BT_DBG("%s status 0x%x", hdev->name, status);
+
+ if (status) {
+ hci_req_complete(hdev, status);
+
+ hci_conn_check_pending(hdev);
+ } else
+ set_bit(HCI_INQUIRY, &hdev->flags);
}
-/* Command Status OGF LINK_CTL */
static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
{
+ struct hci_cp_create_conn *cp;
struct hci_conn *conn;
- struct hci_cp_create_conn *cp = hci_sent_cmd_data(hdev, OGF_LINK_CTL, OCF_CREATE_CONN);
+ BT_DBG("%s status 0x%x", hdev->name, status);
+
+ cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
if (!cp)
return;
@@ -431,8 +480,7 @@ static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
- BT_DBG("%s status 0x%x bdaddr %s conn %p", hdev->name,
- status, batostr(&cp->bdaddr), conn);
+ BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
if (status) {
if (conn && conn->state == BT_CONNECT) {
@@ -457,234 +505,138 @@ static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
hci_dev_unlock(hdev);
}
-static void hci_cs_link_ctl(struct hci_dev *hdev, __u16 ocf, __u8 status)
+static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
{
- BT_DBG("%s ocf 0x%x", hdev->name, ocf);
+ struct hci_cp_add_sco *cp;
+ struct hci_conn *acl, *sco;
+ __u16 handle;
- switch (ocf) {
- case OCF_CREATE_CONN:
- hci_cs_create_conn(hdev, status);
- break;
-
- case OCF_ADD_SCO:
- if (status) {
- struct hci_conn *acl, *sco;
- struct hci_cp_add_sco *cp = hci_sent_cmd_data(hdev, OGF_LINK_CTL, OCF_ADD_SCO);
- __u16 handle;
-
- if (!cp)
- break;
+ BT_DBG("%s status 0x%x", hdev->name, status);
- handle = __le16_to_cpu(cp->handle);
-
- BT_DBG("%s Add SCO error: handle %d status 0x%x", hdev->name, handle, status);
+ if (!status)
+ return;
- hci_dev_lock(hdev);
+ cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
+ if (!cp)
+ return;
- acl = hci_conn_hash_lookup_handle(hdev, handle);
- if (acl && (sco = acl->link)) {
- sco->state = BT_CLOSED;
+ handle = __le16_to_cpu(cp->handle);
- hci_proto_connect_cfm(sco, status);
- hci_conn_del(sco);
- }
+ BT_DBG("%s handle %d", hdev->name, handle);
- hci_dev_unlock(hdev);
- }
- break;
+ hci_dev_lock(hdev);
- case OCF_INQUIRY:
- if (status) {
- BT_DBG("%s Inquiry error: status 0x%x", hdev->name, status);
- hci_req_complete(hdev, status);
- } else {
- set_bit(HCI_INQUIRY, &hdev->flags);
- }
- break;
+ acl = hci_conn_hash_lookup_handle(hdev, handle);
+ if (acl && (sco = acl->link)) {
+ sco->state = BT_CLOSED;
- default:
- BT_DBG("%s Command status: ogf LINK_CTL ocf %x status %d",
- hdev->name, ocf, status);
- break;
+ hci_proto_connect_cfm(sco, status);
+ hci_conn_del(sco);
}
+
+ hci_dev_unlock(hdev);
}
-/* Command Status OGF LINK_POLICY */
-static void hci_cs_link_policy(struct hci_dev *hdev, __u16 ocf, __u8 status)
+static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
{
- BT_DBG("%s ocf 0x%x", hdev->name, ocf);
-
- switch (ocf) {
- case OCF_SNIFF_MODE:
- if (status) {
- struct hci_conn *conn;
- struct hci_cp_sniff_mode *cp = hci_sent_cmd_data(hdev, OGF_LINK_POLICY, OCF_SNIFF_MODE);
+ BT_DBG("%s status 0x%x", hdev->name, status);
+}
- if (!cp)
- break;
+static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
+{
+ struct hci_cp_setup_sync_conn *cp;
+ struct hci_conn *acl, *sco;
+ __u16 handle;
- hci_dev_lock(hdev);
+ BT_DBG("%s status 0x%x", hdev->name, status);
- conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
- if (conn) {
- clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
- }
-
- hci_dev_unlock(hdev);
- }
- break;
+ if (!status)
+ return;
- case OCF_EXIT_SNIFF_MODE:
- if (status) {
- struct hci_conn *conn;
- struct hci_cp_exit_sniff_mode *cp = hci_sent_cmd_data(hdev, OGF_LINK_POLICY, OCF_EXIT_SNIFF_MODE);
+ cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
+ if (!cp)
+ return;
- if (!cp)
- break;
+ handle = __le16_to_cpu(cp->handle);
- hci_dev_lock(hdev);
+ BT_DBG("%s handle %d", hdev->name, handle);
- conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
- if (conn) {
- clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
- }
+ hci_dev_lock(hdev);
- hci_dev_unlock(hdev);
- }
- break;
+ acl = hci_conn_hash_lookup_handle(hdev, handle);
+ if (acl && (sco = acl->link)) {
+ sco->state = BT_CLOSED;
- default:
- BT_DBG("%s Command status: ogf LINK_POLICY ocf %x", hdev->name, ocf);
- break;
+ hci_proto_connect_cfm(sco, status);
+ hci_conn_del(sco);
}
-}
-/* Command Status OGF HOST_CTL */
-static void hci_cs_host_ctl(struct hci_dev *hdev, __u16 ocf, __u8 status)
-{
- BT_DBG("%s ocf 0x%x", hdev->name, ocf);
-
- switch (ocf) {
- default:
- BT_DBG("%s Command status: ogf HOST_CTL ocf %x", hdev->name, ocf);
- break;
- }
+ hci_dev_unlock(hdev);
}
-/* Command Status OGF INFO_PARAM */
-static void hci_cs_info_param(struct hci_dev *hdev, __u16 ocf, __u8 status)
+static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
{
- BT_DBG("%s: hci_cs_info_param: ocf 0x%x", hdev->name, ocf);
-
- switch (ocf) {
- default:
- BT_DBG("%s Command status: ogf INFO_PARAM ocf %x", hdev->name, ocf);
- break;
- }
-}
+ struct hci_cp_sniff_mode *cp;
+ struct hci_conn *conn;
-/* Inquiry Complete */
-static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
-{
- __u8 status = *((__u8 *) skb->data);
- struct hci_conn *pend;
+ BT_DBG("%s status 0x%x", hdev->name, status);
- BT_DBG("%s status %d", hdev->name, status);
+ if (!status)
+ return;
- clear_bit(HCI_INQUIRY, &hdev->flags);
- hci_req_complete(hdev, status);
+ cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
+ if (!cp)
+ return;
hci_dev_lock(hdev);
- pend = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
- if (pend)
- hci_acl_connect(pend);
+ conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
+ if (conn)
+ clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
hci_dev_unlock(hdev);
}
-/* Inquiry Result */
-static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
{
- struct inquiry_data data;
- struct inquiry_info *info = (struct inquiry_info *) (skb->data + 1);
- int num_rsp = *((__u8 *) skb->data);
+ struct hci_cp_exit_sniff_mode *cp;
+ struct hci_conn *conn;
- BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
+ BT_DBG("%s status 0x%x", hdev->name, status);
- if (!num_rsp)
+ if (!status)
+ return;
+
+ cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
+ if (!cp)
return;
hci_dev_lock(hdev);
- for (; num_rsp; num_rsp--) {
- bacpy(&data.bdaddr, &info->bdaddr);
- data.pscan_rep_mode = info->pscan_rep_mode;
- data.pscan_period_mode = info->pscan_period_mode;
- data.pscan_mode = info->pscan_mode;
- memcpy(data.dev_class, info->dev_class, 3);
- data.clock_offset = info->clock_offset;
- data.rssi = 0x00;
- info++;
- hci_inquiry_cache_update(hdev, &data);
- }
+ conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
+ if (conn)
+ clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
hci_dev_unlock(hdev);
}
-/* Inquiry Result With RSSI */
-static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct inquiry_data data;
- int num_rsp = *((__u8 *) skb->data);
-
- BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
-
- if (!num_rsp)
- return;
-
- hci_dev_lock(hdev);
+ __u8 status = *((__u8 *) skb->data);
- if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
- struct inquiry_info_with_rssi_and_pscan_mode *info =
- (struct inquiry_info_with_rssi_and_pscan_mode *) (skb->data + 1);
+ BT_DBG("%s status %d", hdev->name, status);
- for (; num_rsp; num_rsp--) {
- bacpy(&data.bdaddr, &info->bdaddr);
- data.pscan_rep_mode = info->pscan_rep_mode;
- data.pscan_period_mode = info->pscan_period_mode;
- data.pscan_mode = info->pscan_mode;
- memcpy(data.dev_class, info->dev_class, 3);
- data.clock_offset = info->clock_offset;
- data.rssi = info->rssi;
- info++;
- hci_inquiry_cache_update(hdev, &data);
- }
- } else {
- struct inquiry_info_with_rssi *info =
- (struct inquiry_info_with_rssi *) (skb->data + 1);
+ clear_bit(HCI_INQUIRY, &hdev->flags);
- for (; num_rsp; num_rsp--) {
- bacpy(&data.bdaddr, &info->bdaddr);
- data.pscan_rep_mode = info->pscan_rep_mode;
- data.pscan_period_mode = info->pscan_period_mode;
- data.pscan_mode = 0x00;
- memcpy(data.dev_class, info->dev_class, 3);
- data.clock_offset = info->clock_offset;
- data.rssi = info->rssi;
- info++;
- hci_inquiry_cache_update(hdev, &data);
- }
- }
+ hci_req_complete(hdev, status);
- hci_dev_unlock(hdev);
+ hci_conn_check_pending(hdev);
}
-/* Extended Inquiry Result */
-static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct inquiry_data data;
- struct extended_inquiry_info *info = (struct extended_inquiry_info *) (skb->data + 1);
+ struct inquiry_info *info = (void *) (skb->data + 1);
int num_rsp = *((__u8 *) skb->data);
BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
@@ -696,12 +648,12 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct
for (; num_rsp; num_rsp--) {
bacpy(&data.bdaddr, &info->bdaddr);
- data.pscan_rep_mode = info->pscan_rep_mode;
- data.pscan_period_mode = info->pscan_period_mode;
- data.pscan_mode = 0x00;
+ data.pscan_rep_mode = info->pscan_rep_mode;
+ data.pscan_period_mode = info->pscan_period_mode;
+ data.pscan_mode = info->pscan_mode;
memcpy(data.dev_class, info->dev_class, 3);
- data.clock_offset = info->clock_offset;
- data.rssi = info->rssi;
+ data.clock_offset = info->clock_offset;
+ data.rssi = 0x00;
info++;
hci_inquiry_cache_update(hdev, &data);
}
@@ -709,70 +661,18 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct
hci_dev_unlock(hdev);
}
-/* Connect Request */
-static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
-{
- struct hci_ev_conn_request *ev = (struct hci_ev_conn_request *) skb->data;
- int mask = hdev->link_mode;
-
- BT_DBG("%s Connection request: %s type 0x%x", hdev->name,
- batostr(&ev->bdaddr), ev->link_type);
-
- mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
-
- if (mask & HCI_LM_ACCEPT) {
- /* Connection accepted */
- struct hci_conn *conn;
- struct hci_cp_accept_conn_req cp;
-
- hci_dev_lock(hdev);
- conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
- if (!conn) {
- if (!(conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr))) {
- BT_ERR("No memmory for new connection");
- hci_dev_unlock(hdev);
- return;
- }
- }
- memcpy(conn->dev_class, ev->dev_class, 3);
- conn->state = BT_CONNECT;
- hci_dev_unlock(hdev);
-
- bacpy(&cp.bdaddr, &ev->bdaddr);
-
- if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
- cp.role = 0x00; /* Become master */
- else
- cp.role = 0x01; /* Remain slave */
-
- hci_send_cmd(hdev, OGF_LINK_CTL,
- OCF_ACCEPT_CONN_REQ, sizeof(cp), &cp);
- } else {
- /* Connection rejected */
- struct hci_cp_reject_conn_req cp;
-
- bacpy(&cp.bdaddr, &ev->bdaddr);
- cp.reason = 0x0f;
- hci_send_cmd(hdev, OGF_LINK_CTL,
- OCF_REJECT_CONN_REQ, sizeof(cp), &cp);
- }
-}
-
-/* Connect Complete */
static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_conn_complete *ev = (struct hci_ev_conn_complete *) skb->data;
- struct hci_conn *conn, *pend;
+ struct hci_ev_conn_complete *ev = (void *) skb->data;
+ struct hci_conn *conn;
BT_DBG("%s", hdev->name);
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
- if (!conn) {
- hci_dev_unlock(hdev);
- return;
- }
+ if (!conn)
+ goto unlock;
if (!ev->status) {
conn->handle = __le16_to_cpu(ev->handle);
@@ -788,8 +688,7 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
if (conn->type == ACL_LINK) {
struct hci_cp_read_remote_features cp;
cp.handle = ev->handle;
- hci_send_cmd(hdev, OGF_LINK_CTL,
- OCF_READ_REMOTE_FEATURES, sizeof(cp), &cp);
+ hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, sizeof(cp), &cp);
}
/* Set link policy */
@@ -797,8 +696,7 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
struct hci_cp_write_link_policy cp;
cp.handle = ev->handle;
cp.policy = cpu_to_le16(hdev->link_policy);
- hci_send_cmd(hdev, OGF_LINK_POLICY,
- OCF_WRITE_LINK_POLICY, sizeof(cp), &cp);
+ hci_send_cmd(hdev, HCI_OP_WRITE_LINK_POLICY, sizeof(cp), &cp);
}
/* Set packet type for incoming connection */
@@ -809,8 +707,7 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
cpu_to_le16(hdev->pkt_type & ACL_PTYPE_MASK):
cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK);
- hci_send_cmd(hdev, OGF_LINK_CTL,
- OCF_CHANGE_CONN_PTYPE, sizeof(cp), &cp);
+ hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp), &cp);
} else {
/* Update disconnect timer */
hci_conn_hold(conn);
@@ -822,9 +719,12 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
if (conn->type == ACL_LINK) {
struct hci_conn *sco = conn->link;
if (sco) {
- if (!ev->status)
- hci_add_sco(sco, conn->handle);
- else {
+ if (!ev->status) {
+ if (lmp_esco_capable(hdev))
+ hci_setup_sync(sco, conn->handle);
+ else
+ hci_add_sco(sco, conn->handle);
+ } else {
hci_proto_connect_cfm(sco, ev->status);
hci_conn_del(sco);
}
@@ -835,136 +735,104 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
if (ev->status)
hci_conn_del(conn);
- pend = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
- if (pend)
- hci_acl_connect(pend);
-
+unlock:
hci_dev_unlock(hdev);
-}
-
-/* Disconnect Complete */
-static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
-{
- struct hci_ev_disconn_complete *ev = (struct hci_ev_disconn_complete *) skb->data;
- struct hci_conn *conn;
-
- BT_DBG("%s status %d", hdev->name, ev->status);
-
- if (ev->status)
- return;
- hci_dev_lock(hdev);
-
- conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
- if (conn) {
- conn->state = BT_CLOSED;
- hci_proto_disconn_ind(conn, ev->reason);
- hci_conn_del(conn);
- }
-
- hci_dev_unlock(hdev);
+ hci_conn_check_pending(hdev);
}
-/* Number of completed packets */
-static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_num_comp_pkts *ev = (struct hci_ev_num_comp_pkts *) skb->data;
- __le16 *ptr;
- int i;
-
- skb_pull(skb, sizeof(*ev));
-
- BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
+ struct hci_ev_conn_request *ev = (void *) skb->data;
+ int mask = hdev->link_mode;
- if (skb->len < ev->num_hndl * 4) {
- BT_DBG("%s bad parameters", hdev->name);
- return;
- }
+ BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
+ batostr(&ev->bdaddr), ev->link_type);
- tasklet_disable(&hdev->tx_task);
+ mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
- for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) {
+ if (mask & HCI_LM_ACCEPT) {
+ /* Connection accepted */
struct hci_conn *conn;
- __u16 handle, count;
-
- handle = __le16_to_cpu(get_unaligned(ptr++));
- count = __le16_to_cpu(get_unaligned(ptr++));
- conn = hci_conn_hash_lookup_handle(hdev, handle);
- if (conn) {
- conn->sent -= count;
+ hci_dev_lock(hdev);
- if (conn->type == ACL_LINK) {
- if ((hdev->acl_cnt += count) > hdev->acl_pkts)
- hdev->acl_cnt = hdev->acl_pkts;
- } else {
- if ((hdev->sco_cnt += count) > hdev->sco_pkts)
- hdev->sco_cnt = hdev->sco_pkts;
+ conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
+ if (!conn) {
+ if (!(conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr))) {
+ BT_ERR("No memmory for new connection");
+ hci_dev_unlock(hdev);
+ return;
}
}
- }
- hci_sched_tx(hdev);
- tasklet_enable(&hdev->tx_task);
-}
+ memcpy(conn->dev_class, ev->dev_class, 3);
+ conn->state = BT_CONNECT;
-/* Role Change */
-static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
-{
- struct hci_ev_role_change *ev = (struct hci_ev_role_change *) skb->data;
- struct hci_conn *conn;
+ hci_dev_unlock(hdev);
- BT_DBG("%s status %d", hdev->name, ev->status);
+ if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
+ struct hci_cp_accept_conn_req cp;
- hci_dev_lock(hdev);
+ bacpy(&cp.bdaddr, &ev->bdaddr);
- conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
- if (conn) {
- if (!ev->status) {
- if (ev->role)
- conn->link_mode &= ~HCI_LM_MASTER;
+ if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
+ cp.role = 0x00; /* Become master */
else
- conn->link_mode |= HCI_LM_MASTER;
- }
+ cp.role = 0x01; /* Remain slave */
- clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend);
+ hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
+ sizeof(cp), &cp);
+ } else {
+ struct hci_cp_accept_sync_conn_req cp;
- hci_role_switch_cfm(conn, ev->status, ev->role);
- }
+ bacpy(&cp.bdaddr, &ev->bdaddr);
+ cp.pkt_type = cpu_to_le16(hdev->esco_type);
- hci_dev_unlock(hdev);
+ cp.tx_bandwidth = cpu_to_le32(0x00001f40);
+ cp.rx_bandwidth = cpu_to_le32(0x00001f40);
+ cp.max_latency = cpu_to_le16(0xffff);
+ cp.content_format = cpu_to_le16(hdev->voice_setting);
+ cp.retrans_effort = 0xff;
+
+ hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
+ sizeof(cp), &cp);
+ }
+ } else {
+ /* Connection rejected */
+ struct hci_cp_reject_conn_req cp;
+
+ bacpy(&cp.bdaddr, &ev->bdaddr);
+ cp.reason = 0x0f;
+ hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
+ }
}
-/* Mode Change */
-static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_mode_change *ev = (struct hci_ev_mode_change *) skb->data;
+ struct hci_ev_disconn_complete *ev = (void *) skb->data;
struct hci_conn *conn;
BT_DBG("%s status %d", hdev->name, ev->status);
+ if (ev->status)
+ return;
+
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
if (conn) {
- conn->mode = ev->mode;
- conn->interval = __le16_to_cpu(ev->interval);
-
- if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
- if (conn->mode == HCI_CM_ACTIVE)
- conn->power_save = 1;
- else
- conn->power_save = 0;
- }
+ conn->state = BT_CLOSED;
+ hci_proto_disconn_ind(conn, ev->reason);
+ hci_conn_del(conn);
}
hci_dev_unlock(hdev);
}
-/* Authentication Complete */
static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_auth_complete *ev = (struct hci_ev_auth_complete *) skb->data;
+ struct hci_ev_auth_complete *ev = (void *) skb->data;
struct hci_conn *conn;
BT_DBG("%s status %d", hdev->name, ev->status);
@@ -985,8 +853,8 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s
struct hci_cp_set_conn_encrypt cp;
cp.handle = cpu_to_le16(conn->handle);
cp.encrypt = 1;
- hci_send_cmd(conn->hdev, OGF_LINK_CTL,
- OCF_SET_CONN_ENCRYPT, sizeof(cp), &cp);
+ hci_send_cmd(conn->hdev,
+ HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), &cp);
} else {
clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
hci_encrypt_cfm(conn, ev->status, 0x00);
@@ -997,10 +865,16 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s
hci_dev_unlock(hdev);
}
-/* Encryption Change */
+static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ BT_DBG("%s", hdev->name);
+
+ hci_conn_check_pending(hdev);
+}
+
static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_encrypt_change *ev = (struct hci_ev_encrypt_change *) skb->data;
+ struct hci_ev_encrypt_change *ev = (void *) skb->data;
struct hci_conn *conn;
BT_DBG("%s status %d", hdev->name, ev->status);
@@ -1024,10 +898,9 @@ static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *
hci_dev_unlock(hdev);
}
-/* Change Connection Link Key Complete */
-static inline void hci_change_conn_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_change_conn_link_key_complete *ev = (struct hci_ev_change_conn_link_key_complete *) skb->data;
+ struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
struct hci_conn *conn;
BT_DBG("%s status %d", hdev->name, ev->status);
@@ -1047,25 +920,263 @@ static inline void hci_change_conn_link_key_complete_evt(struct hci_dev *hdev, s
hci_dev_unlock(hdev);
}
-/* Pin Code Request*/
-static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
+ struct hci_ev_remote_features *ev = (void *) skb->data;
+ struct hci_conn *conn;
+
+ BT_DBG("%s status %d", hdev->name, ev->status);
+
+ if (ev->status)
+ return;
+
+ hci_dev_lock(hdev);
+
+ conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
+ if (conn)
+ memcpy(conn->features, ev->features, 8);
+
+ hci_dev_unlock(hdev);
}
-/* Link Key Request */
-static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
+ BT_DBG("%s", hdev->name);
}
-/* Link Key Notification */
-static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
+ BT_DBG("%s", hdev->name);
}
-/* Remote Features */
-static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_remote_features *ev = (struct hci_ev_remote_features *) skb->data;
+ struct hci_ev_cmd_complete *ev = (void *) skb->data;
+ __u16 opcode;
+
+ skb_pull(skb, sizeof(*ev));
+
+ opcode = __le16_to_cpu(ev->opcode);
+
+ switch (opcode) {
+ case HCI_OP_INQUIRY_CANCEL:
+ hci_cc_inquiry_cancel(hdev, skb);
+ break;
+
+ case HCI_OP_EXIT_PERIODIC_INQ:
+ hci_cc_exit_periodic_inq(hdev, skb);
+ break;
+
+ case HCI_OP_REMOTE_NAME_REQ_CANCEL:
+ hci_cc_remote_name_req_cancel(hdev, skb);
+ break;
+
+ case HCI_OP_ROLE_DISCOVERY:
+ hci_cc_role_discovery(hdev, skb);
+ break;
+
+ case HCI_OP_WRITE_LINK_POLICY:
+ hci_cc_write_link_policy(hdev, skb);
+ break;
+
+ case HCI_OP_RESET:
+ hci_cc_reset(hdev, skb);
+ break;
+
+ case HCI_OP_WRITE_LOCAL_NAME:
+ hci_cc_write_local_name(hdev, skb);
+ break;
+
+ case HCI_OP_READ_LOCAL_NAME:
+ hci_cc_read_local_name(hdev, skb);
+ break;
+
+ case HCI_OP_WRITE_AUTH_ENABLE:
+ hci_cc_write_auth_enable(hdev, skb);
+ break;
+
+ case HCI_OP_WRITE_ENCRYPT_MODE:
+ hci_cc_write_encrypt_mode(hdev, skb);
+ break;
+
+ case HCI_OP_WRITE_SCAN_ENABLE:
+ hci_cc_write_scan_enable(hdev, skb);
+ break;
+
+ case HCI_OP_READ_CLASS_OF_DEV:
+ hci_cc_read_class_of_dev(hdev, skb);
+ break;
+
+ case HCI_OP_WRITE_CLASS_OF_DEV:
+ hci_cc_write_class_of_dev(hdev, skb);
+ break;
+
+ case HCI_OP_READ_VOICE_SETTING:
+ hci_cc_read_voice_setting(hdev, skb);
+ break;
+
+ case HCI_OP_WRITE_VOICE_SETTING:
+ hci_cc_write_voice_setting(hdev, skb);
+ break;
+
+ case HCI_OP_HOST_BUFFER_SIZE:
+ hci_cc_host_buffer_size(hdev, skb);
+ break;
+
+ case HCI_OP_READ_LOCAL_VERSION:
+ hci_cc_read_local_version(hdev, skb);
+ break;
+
+ case HCI_OP_READ_LOCAL_COMMANDS:
+ hci_cc_read_local_commands(hdev, skb);
+ break;
+
+ case HCI_OP_READ_LOCAL_FEATURES:
+ hci_cc_read_local_features(hdev, skb);
+ break;
+
+ case HCI_OP_READ_BUFFER_SIZE:
+ hci_cc_read_buffer_size(hdev, skb);
+ break;
+
+ case HCI_OP_READ_BD_ADDR:
+ hci_cc_read_bd_addr(hdev, skb);
+ break;
+
+ default:
+ BT_DBG("%s opcode 0x%x", hdev->name, opcode);
+ break;
+ }
+
+ if (ev->ncmd) {
+ atomic_set(&hdev->cmd_cnt, 1);
+ if (!skb_queue_empty(&hdev->cmd_q))
+ hci_sched_cmd(hdev);
+ }
+}
+
+static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_ev_cmd_status *ev = (void *) skb->data;
+ __u16 opcode;
+
+ skb_pull(skb, sizeof(*ev));
+
+ opcode = __le16_to_cpu(ev->opcode);
+
+ switch (opcode) {
+ case HCI_OP_INQUIRY:
+ hci_cs_inquiry(hdev, ev->status);
+ break;
+
+ case HCI_OP_CREATE_CONN:
+ hci_cs_create_conn(hdev, ev->status);
+ break;
+
+ case HCI_OP_ADD_SCO:
+ hci_cs_add_sco(hdev, ev->status);
+ break;
+
+ case HCI_OP_REMOTE_NAME_REQ:
+ hci_cs_remote_name_req(hdev, ev->status);
+ break;
+
+ case HCI_OP_SETUP_SYNC_CONN:
+ hci_cs_setup_sync_conn(hdev, ev->status);
+ break;
+
+ case HCI_OP_SNIFF_MODE:
+ hci_cs_sniff_mode(hdev, ev->status);
+ break;
+
+ case HCI_OP_EXIT_SNIFF_MODE:
+ hci_cs_exit_sniff_mode(hdev, ev->status);
+ break;
+
+ default:
+ BT_DBG("%s opcode 0x%x", hdev->name, opcode);
+ break;
+ }
+
+ if (ev->ncmd) {
+ atomic_set(&hdev->cmd_cnt, 1);
+ if (!skb_queue_empty(&hdev->cmd_q))
+ hci_sched_cmd(hdev);
+ }
+}
+
+static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_ev_role_change *ev = (void *) skb->data;
+ struct hci_conn *conn;
+
+ BT_DBG("%s status %d", hdev->name, ev->status);
+
+ hci_dev_lock(hdev);
+
+ conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
+ if (conn) {
+ if (!ev->status) {
+ if (ev->role)
+ conn->link_mode &= ~HCI_LM_MASTER;
+ else
+ conn->link_mode |= HCI_LM_MASTER;
+ }
+
+ clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend);
+
+ hci_role_switch_cfm(conn, ev->status, ev->role);
+ }
+
+ hci_dev_unlock(hdev);
+}
+
+static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
+ __le16 *ptr;
+ int i;
+
+ skb_pull(skb, sizeof(*ev));
+
+ BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
+
+ if (skb->len < ev->num_hndl * 4) {
+ BT_DBG("%s bad parameters", hdev->name);
+ return;
+ }
+
+ tasklet_disable(&hdev->tx_task);
+
+ for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) {
+ struct hci_conn *conn;
+ __u16 handle, count;
+
+ handle = __le16_to_cpu(get_unaligned(ptr++));
+ count = __le16_to_cpu(get_unaligned(ptr++));
+
+ conn = hci_conn_hash_lookup_handle(hdev, handle);
+ if (conn) {
+ conn->sent -= count;
+
+ if (conn->type == ACL_LINK) {
+ if ((hdev->acl_cnt += count) > hdev->acl_pkts)
+ hdev->acl_cnt = hdev->acl_pkts;
+ } else {
+ if ((hdev->sco_cnt += count) > hdev->sco_pkts)
+ hdev->sco_cnt = hdev->sco_pkts;
+ }
+ }
+ }
+
+ hci_sched_tx(hdev);
+
+ tasklet_enable(&hdev->tx_task);
+}
+
+static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_ev_mode_change *ev = (void *) skb->data;
struct hci_conn *conn;
BT_DBG("%s status %d", hdev->name, ev->status);
@@ -1073,17 +1184,39 @@ static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
- if (conn && !ev->status) {
- memcpy(conn->features, ev->features, sizeof(conn->features));
+ if (conn) {
+ conn->mode = ev->mode;
+ conn->interval = __le16_to_cpu(ev->interval);
+
+ if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
+ if (conn->mode == HCI_CM_ACTIVE)
+ conn->power_save = 1;
+ else
+ conn->power_save = 0;
+ }
}
hci_dev_unlock(hdev);
}
-/* Clock Offset */
+static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ BT_DBG("%s", hdev->name);
+}
+
+static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ BT_DBG("%s", hdev->name);
+}
+
+static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ BT_DBG("%s", hdev->name);
+}
+
static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_clock_offset *ev = (struct hci_ev_clock_offset *) skb->data;
+ struct hci_ev_clock_offset *ev = (void *) skb->data;
struct hci_conn *conn;
BT_DBG("%s status %d", hdev->name, ev->status);
@@ -1103,10 +1236,9 @@ static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *sk
hci_dev_unlock(hdev);
}
-/* Page Scan Repetition Mode */
static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_pscan_rep_mode *ev = (struct hci_ev_pscan_rep_mode *) skb->data;
+ struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
struct inquiry_entry *ie;
BT_DBG("%s", hdev->name);
@@ -1121,10 +1253,91 @@ static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *
hci_dev_unlock(hdev);
}
-/* Sniff Subrate */
+static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct inquiry_data data;
+ int num_rsp = *((__u8 *) skb->data);
+
+ BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
+
+ if (!num_rsp)
+ return;
+
+ hci_dev_lock(hdev);
+
+ if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
+ struct inquiry_info_with_rssi_and_pscan_mode *info = (void *) (skb->data + 1);
+
+ for (; num_rsp; num_rsp--) {
+ bacpy(&data.bdaddr, &info->bdaddr);
+ data.pscan_rep_mode = info->pscan_rep_mode;
+ data.pscan_period_mode = info->pscan_period_mode;
+ data.pscan_mode = info->pscan_mode;
+ memcpy(data.dev_class, info->dev_class, 3);
+ data.clock_offset = info->clock_offset;
+ data.rssi = info->rssi;
+ info++;
+ hci_inquiry_cache_update(hdev, &data);
+ }
+ } else {
+ struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
+
+ for (; num_rsp; num_rsp--) {
+ bacpy(&data.bdaddr, &info->bdaddr);
+ data.pscan_rep_mode = info->pscan_rep_mode;
+ data.pscan_period_mode = info->pscan_period_mode;
+ data.pscan_mode = 0x00;
+ memcpy(data.dev_class, info->dev_class, 3);
+ data.clock_offset = info->clock_offset;
+ data.rssi = info->rssi;
+ info++;
+ hci_inquiry_cache_update(hdev, &data);
+ }
+ }
+
+ hci_dev_unlock(hdev);
+}
+
+static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ BT_DBG("%s", hdev->name);
+}
+
+static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
+ struct hci_conn *conn;
+
+ BT_DBG("%s status %d", hdev->name, ev->status);
+
+ hci_dev_lock(hdev);
+
+ conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
+ if (!conn)
+ goto unlock;
+
+ if (!ev->status) {
+ conn->handle = __le16_to_cpu(ev->handle);
+ conn->state = BT_CONNECTED;
+ } else
+ conn->state = BT_CLOSED;
+
+ hci_proto_connect_cfm(conn, ev->status);
+ if (ev->status)
+ hci_conn_del(conn);
+
+unlock:
+ hci_dev_unlock(hdev);
+}
+
+static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ BT_DBG("%s", hdev->name);
+}
+
static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_sniff_subrate *ev = (struct hci_ev_sniff_subrate *) skb->data;
+ struct hci_ev_sniff_subrate *ev = (void *) skb->data;
struct hci_conn *conn;
BT_DBG("%s status %d", hdev->name, ev->status);
@@ -1138,22 +1351,42 @@ static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *s
hci_dev_unlock(hdev);
}
-void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
+static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_event_hdr *hdr = (struct hci_event_hdr *) skb->data;
- struct hci_ev_cmd_complete *ec;
- struct hci_ev_cmd_status *cs;
- u16 opcode, ocf, ogf;
+ struct inquiry_data data;
+ struct extended_inquiry_info *info = (void *) (skb->data + 1);
+ int num_rsp = *((__u8 *) skb->data);
- skb_pull(skb, HCI_EVENT_HDR_SIZE);
+ BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
- BT_DBG("%s evt 0x%x", hdev->name, hdr->evt);
+ if (!num_rsp)
+ return;
- switch (hdr->evt) {
- case HCI_EV_NUM_COMP_PKTS:
- hci_num_comp_pkts_evt(hdev, skb);
- break;
+ hci_dev_lock(hdev);
+
+ for (; num_rsp; num_rsp--) {
+ bacpy(&data.bdaddr, &info->bdaddr);
+ data.pscan_rep_mode = info->pscan_rep_mode;
+ data.pscan_period_mode = info->pscan_period_mode;
+ data.pscan_mode = 0x00;
+ memcpy(data.dev_class, info->dev_class, 3);
+ data.clock_offset = info->clock_offset;
+ data.rssi = info->rssi;
+ info++;
+ hci_inquiry_cache_update(hdev, &data);
+ }
+ hci_dev_unlock(hdev);
+}
+
+void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_event_hdr *hdr = (void *) skb->data;
+ __u8 event = hdr->evt;
+
+ skb_pull(skb, HCI_EVENT_HDR_SIZE);
+
+ switch (event) {
case HCI_EV_INQUIRY_COMPLETE:
hci_inquiry_complete_evt(hdev, skb);
break;
@@ -1162,44 +1395,64 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
hci_inquiry_result_evt(hdev, skb);
break;
- case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
- hci_inquiry_result_with_rssi_evt(hdev, skb);
- break;
-
- case HCI_EV_EXTENDED_INQUIRY_RESULT:
- hci_extended_inquiry_result_evt(hdev, skb);
+ case HCI_EV_CONN_COMPLETE:
+ hci_conn_complete_evt(hdev, skb);
break;
case HCI_EV_CONN_REQUEST:
hci_conn_request_evt(hdev, skb);
break;
- case HCI_EV_CONN_COMPLETE:
- hci_conn_complete_evt(hdev, skb);
- break;
-
case HCI_EV_DISCONN_COMPLETE:
hci_disconn_complete_evt(hdev, skb);
break;
- case HCI_EV_ROLE_CHANGE:
- hci_role_change_evt(hdev, skb);
- break;
-
- case HCI_EV_MODE_CHANGE:
- hci_mode_change_evt(hdev, skb);
- break;
-
case HCI_EV_AUTH_COMPLETE:
hci_auth_complete_evt(hdev, skb);
break;
+ case HCI_EV_REMOTE_NAME:
+ hci_remote_name_evt(hdev, skb);
+ break;
+
case HCI_EV_ENCRYPT_CHANGE:
hci_encrypt_change_evt(hdev, skb);
break;
- case HCI_EV_CHANGE_CONN_LINK_KEY_COMPLETE:
- hci_change_conn_link_key_complete_evt(hdev, skb);
+ case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
+ hci_change_link_key_complete_evt(hdev, skb);
+ break;
+
+ case HCI_EV_REMOTE_FEATURES:
+ hci_remote_features_evt(hdev, skb);
+ break;
+
+ case HCI_EV_REMOTE_VERSION:
+ hci_remote_version_evt(hdev, skb);
+ break;
+
+ case HCI_EV_QOS_SETUP_COMPLETE:
+ hci_qos_setup_complete_evt(hdev, skb);
+ break;
+
+ case HCI_EV_CMD_COMPLETE:
+ hci_cmd_complete_evt(hdev, skb);
+ break;
+
+ case HCI_EV_CMD_STATUS:
+ hci_cmd_status_evt(hdev, skb);
+ break;
+
+ case HCI_EV_ROLE_CHANGE:
+ hci_role_change_evt(hdev, skb);
+ break;
+
+ case HCI_EV_NUM_COMP_PKTS:
+ hci_num_comp_pkts_evt(hdev, skb);
+ break;
+
+ case HCI_EV_MODE_CHANGE:
+ hci_mode_change_evt(hdev, skb);
break;
case HCI_EV_PIN_CODE_REQ:
@@ -1214,10 +1467,6 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
hci_link_key_notify_evt(hdev, skb);
break;
- case HCI_EV_REMOTE_FEATURES:
- hci_remote_features_evt(hdev, skb);
- break;
-
case HCI_EV_CLOCK_OFFSET:
hci_clock_offset_evt(hdev, skb);
break;
@@ -1226,82 +1475,32 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
hci_pscan_rep_mode_evt(hdev, skb);
break;
- case HCI_EV_SNIFF_SUBRATE:
- hci_sniff_subrate_evt(hdev, skb);
+ case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
+ hci_inquiry_result_with_rssi_evt(hdev, skb);
break;
- case HCI_EV_CMD_STATUS:
- cs = (struct hci_ev_cmd_status *) skb->data;
- skb_pull(skb, sizeof(cs));
-
- opcode = __le16_to_cpu(cs->opcode);
- ogf = hci_opcode_ogf(opcode);
- ocf = hci_opcode_ocf(opcode);
-
- switch (ogf) {
- case OGF_INFO_PARAM:
- hci_cs_info_param(hdev, ocf, cs->status);
- break;
-
- case OGF_HOST_CTL:
- hci_cs_host_ctl(hdev, ocf, cs->status);
- break;
-
- case OGF_LINK_CTL:
- hci_cs_link_ctl(hdev, ocf, cs->status);
- break;
-
- case OGF_LINK_POLICY:
- hci_cs_link_policy(hdev, ocf, cs->status);
- break;
-
- default:
- BT_DBG("%s Command Status OGF %x", hdev->name, ogf);
- break;
- }
-
- if (cs->ncmd) {
- atomic_set(&hdev->cmd_cnt, 1);
- if (!skb_queue_empty(&hdev->cmd_q))
- hci_sched_cmd(hdev);
- }
+ case HCI_EV_REMOTE_EXT_FEATURES:
+ hci_remote_ext_features_evt(hdev, skb);
break;
- case HCI_EV_CMD_COMPLETE:
- ec = (struct hci_ev_cmd_complete *) skb->data;
- skb_pull(skb, sizeof(*ec));
-
- opcode = __le16_to_cpu(ec->opcode);
- ogf = hci_opcode_ogf(opcode);
- ocf = hci_opcode_ocf(opcode);
-
- switch (ogf) {
- case OGF_INFO_PARAM:
- hci_cc_info_param(hdev, ocf, skb);
- break;
-
- case OGF_HOST_CTL:
- hci_cc_host_ctl(hdev, ocf, skb);
- break;
+ case HCI_EV_SYNC_CONN_COMPLETE:
+ hci_sync_conn_complete_evt(hdev, skb);
+ break;
- case OGF_LINK_CTL:
- hci_cc_link_ctl(hdev, ocf, skb);
- break;
+ case HCI_EV_SYNC_CONN_CHANGED:
+ hci_sync_conn_changed_evt(hdev, skb);
+ break;
- case OGF_LINK_POLICY:
- hci_cc_link_policy(hdev, ocf, skb);
- break;
+ case HCI_EV_SNIFF_SUBRATE:
+ hci_sniff_subrate_evt(hdev, skb);
+ break;
- default:
- BT_DBG("%s Command Completed OGF %x", hdev->name, ogf);
- break;
- }
+ case HCI_EV_EXTENDED_INQUIRY_RESULT:
+ hci_extended_inquiry_result_evt(hdev, skb);
+ break;
- if (ec->ncmd) {
- atomic_set(&hdev->cmd_cnt, 1);
- if (!skb_queue_empty(&hdev->cmd_q))
- hci_sched_cmd(hdev);
- }
+ default:
+ BT_DBG("%s event 0x%x", hdev->name, event);
break;
}
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 43dd6373bff9..14991323c273 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -451,7 +451,7 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
goto drop;
}
- if (test_bit(HCI_RAW, &hdev->flags) || (ogf == OGF_VENDOR_CMD)) {
+ if (test_bit(HCI_RAW, &hdev->flags) || (ogf == 0x3f)) {
skb_queue_tail(&hdev->raw_q, skb);
hci_sched_tx(hdev);
} else {
@@ -645,7 +645,7 @@ static int hci_sock_create(struct net *net, struct socket *sock, int protocol)
sock->ops = &hci_sock_ops;
- sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto, 1);
+ sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto);
if (!sk)
return -ENOMEM;
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index 25835403d659..cef1e3e1881c 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -41,6 +41,26 @@ static ssize_t show_type(struct device *dev, struct device_attribute *attr, char
return sprintf(buf, "%s\n", typetostr(hdev->type));
}
+static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct hci_dev *hdev = dev_get_drvdata(dev);
+ char name[249];
+ int i;
+
+ for (i = 0; i < 248; i++)
+ name[i] = hdev->dev_name[i];
+
+ name[248] = '\0';
+ return sprintf(buf, "%s\n", name);
+}
+
+static ssize_t show_class(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct hci_dev *hdev = dev_get_drvdata(dev);
+ return sprintf(buf, "0x%.2x%.2x%.2x\n",
+ hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
+}
+
static ssize_t show_address(struct device *dev, struct device_attribute *attr, char *buf)
{
struct hci_dev *hdev = dev_get_drvdata(dev);
@@ -49,6 +69,17 @@ static ssize_t show_address(struct device *dev, struct device_attribute *attr, c
return sprintf(buf, "%s\n", batostr(&bdaddr));
}
+static ssize_t show_features(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct hci_dev *hdev = dev_get_drvdata(dev);
+
+ return sprintf(buf, "0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+ hdev->features[0], hdev->features[1],
+ hdev->features[2], hdev->features[3],
+ hdev->features[4], hdev->features[5],
+ hdev->features[6], hdev->features[7]);
+}
+
static ssize_t show_manufacturer(struct device *dev, struct device_attribute *attr, char *buf)
{
struct hci_dev *hdev = dev_get_drvdata(dev);
@@ -170,7 +201,10 @@ static ssize_t store_sniff_min_interval(struct device *dev, struct device_attrib
}
static DEVICE_ATTR(type, S_IRUGO, show_type, NULL);
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+static DEVICE_ATTR(class, S_IRUGO, show_class, NULL);
static DEVICE_ATTR(address, S_IRUGO, show_address, NULL);
+static DEVICE_ATTR(features, S_IRUGO, show_features, NULL);
static DEVICE_ATTR(manufacturer, S_IRUGO, show_manufacturer, NULL);
static DEVICE_ATTR(hci_version, S_IRUGO, show_hci_version, NULL);
static DEVICE_ATTR(hci_revision, S_IRUGO, show_hci_revision, NULL);
@@ -185,7 +219,10 @@ static DEVICE_ATTR(sniff_min_interval, S_IRUGO | S_IWUSR,
static struct device_attribute *bt_attrs[] = {
&dev_attr_type,
+ &dev_attr_name,
+ &dev_attr_class,
&dev_attr_address,
+ &dev_attr_features,
&dev_attr_manufacturer,
&dev_attr_hci_version,
&dev_attr_hci_revision,
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index ff5784b440d7..4bbacddeb49d 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -247,7 +247,7 @@ static inline int hidp_queue_report(struct hidp_session *session, unsigned char
{
struct sk_buff *skb;
- BT_DBG("session %p hid %p data %p size %d", session, device, data, size);
+ BT_DBG("session %p hid %p data %p size %d", session, session->hid, data, size);
if (!(skb = alloc_skb(size + 1, GFP_ATOMIC))) {
BT_ERR("Can't allocate memory for new frame");
@@ -656,11 +656,13 @@ static inline int hidp_setup_input(struct hidp_session *session, struct hidp_con
}
if (req->subclass & 0x80) {
- input->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- input->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
- input->relbit[0] = BIT(REL_X) | BIT(REL_Y);
- input->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA);
- input->relbit[0] |= BIT(REL_WHEEL);
+ input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+ input->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
+ BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);
+ input->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
+ input->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_SIDE) |
+ BIT_MASK(BTN_EXTRA);
+ input->relbit[0] |= BIT_MASK(REL_WHEEL);
}
input->dev.parent = hidp_get_device(session);
diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c
index 1de2b6fbcac0..3292b956a7c4 100644
--- a/net/bluetooth/hidp/sock.c
+++ b/net/bluetooth/hidp/sock.c
@@ -255,7 +255,7 @@ static int hidp_sock_create(struct net *net, struct socket *sock, int protocol)
if (sock->type != SOCK_RAW)
return -ESOCKTNOSUPPORT;
- sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hidp_proto, 1);
+ sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hidp_proto);
if (!sk)
return -ENOMEM;
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 36ef27b625db..477e052b17b5 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -55,7 +55,9 @@
#define BT_DBG(D...)
#endif
-#define VERSION "2.8"
+#define VERSION "2.9"
+
+static u32 l2cap_feat_mask = 0x0000;
static const struct proto_ops l2cap_sock_ops;
@@ -258,7 +260,119 @@ static void l2cap_chan_del(struct sock *sk, int err)
sk->sk_state_change(sk);
}
+static inline u8 l2cap_get_ident(struct l2cap_conn *conn)
+{
+ u8 id;
+
+ /* Get next available identificator.
+ * 1 - 128 are used by kernel.
+ * 129 - 199 are reserved.
+ * 200 - 254 are used by utilities like l2ping, etc.
+ */
+
+ spin_lock_bh(&conn->lock);
+
+ if (++conn->tx_ident > 128)
+ conn->tx_ident = 1;
+
+ id = conn->tx_ident;
+
+ spin_unlock_bh(&conn->lock);
+
+ return id;
+}
+
+static inline int l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
+{
+ struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
+
+ BT_DBG("code 0x%2.2x", code);
+
+ if (!skb)
+ return -ENOMEM;
+
+ return hci_send_acl(conn->hcon, skb, 0);
+}
+
/* ---- L2CAP connections ---- */
+static void l2cap_conn_start(struct l2cap_conn *conn)
+{
+ struct l2cap_chan_list *l = &conn->chan_list;
+ struct sock *sk;
+
+ BT_DBG("conn %p", conn);
+
+ read_lock(&l->lock);
+
+ for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
+ bh_lock_sock(sk);
+
+ if (sk->sk_type != SOCK_SEQPACKET) {
+ l2cap_sock_clear_timer(sk);
+ sk->sk_state = BT_CONNECTED;
+ sk->sk_state_change(sk);
+ } else if (sk->sk_state == BT_CONNECT) {
+ struct l2cap_conn_req req;
+ l2cap_pi(sk)->ident = l2cap_get_ident(conn);
+ req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
+ req.psm = l2cap_pi(sk)->psm;
+ l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
+ L2CAP_CONN_REQ, sizeof(req), &req);
+ }
+
+ bh_unlock_sock(sk);
+ }
+
+ read_unlock(&l->lock);
+}
+
+static void l2cap_conn_ready(struct l2cap_conn *conn)
+{
+ BT_DBG("conn %p", conn);
+
+ if (conn->chan_list.head || !hlist_empty(&l2cap_sk_list.head)) {
+ struct l2cap_info_req req;
+
+ req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
+
+ conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
+ conn->info_ident = l2cap_get_ident(conn);
+
+ mod_timer(&conn->info_timer,
+ jiffies + msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
+
+ l2cap_send_cmd(conn, conn->info_ident,
+ L2CAP_INFO_REQ, sizeof(req), &req);
+ }
+}
+
+/* Notify sockets that we cannot guaranty reliability anymore */
+static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
+{
+ struct l2cap_chan_list *l = &conn->chan_list;
+ struct sock *sk;
+
+ BT_DBG("conn %p", conn);
+
+ read_lock(&l->lock);
+
+ for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
+ if (l2cap_pi(sk)->link_mode & L2CAP_LM_RELIABLE)
+ sk->sk_err = err;
+ }
+
+ read_unlock(&l->lock);
+}
+
+static void l2cap_info_timeout(unsigned long arg)
+{
+ struct l2cap_conn *conn = (void *) arg;
+
+ conn->info_ident = 0;
+
+ l2cap_conn_start(conn);
+}
+
static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
{
struct l2cap_conn *conn = hcon->l2cap_data;
@@ -279,6 +393,12 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
conn->src = &hcon->hdev->bdaddr;
conn->dst = &hcon->dst;
+ conn->feat_mask = 0;
+
+ init_timer(&conn->info_timer);
+ conn->info_timer.function = l2cap_info_timeout;
+ conn->info_timer.data = (unsigned long) conn;
+
spin_lock_init(&conn->lock);
rwlock_init(&conn->chan_list.lock);
@@ -318,40 +438,6 @@ static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, stru
write_unlock_bh(&l->lock);
}
-static inline u8 l2cap_get_ident(struct l2cap_conn *conn)
-{
- u8 id;
-
- /* Get next available identificator.
- * 1 - 128 are used by kernel.
- * 129 - 199 are reserved.
- * 200 - 254 are used by utilities like l2ping, etc.
- */
-
- spin_lock_bh(&conn->lock);
-
- if (++conn->tx_ident > 128)
- conn->tx_ident = 1;
-
- id = conn->tx_ident;
-
- spin_unlock_bh(&conn->lock);
-
- return id;
-}
-
-static inline int l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
-{
- struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
-
- BT_DBG("code 0x%2.2x", code);
-
- if (!skb)
- return -ENOMEM;
-
- return hci_send_acl(conn->hcon, skb, 0);
-}
-
/* ---- Socket interface ---- */
static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src)
{
@@ -508,7 +594,6 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent)
/* Default config options */
pi->conf_len = 0;
- pi->conf_mtu = L2CAP_DEFAULT_MTU;
pi->flush_to = L2CAP_DEFAULT_FLUSH_TO;
}
@@ -522,7 +607,7 @@ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int p
{
struct sock *sk;
- sk = sk_alloc(net, PF_BLUETOOTH, prio, &l2cap_proto, 1);
+ sk = sk_alloc(net, PF_BLUETOOTH, prio, &l2cap_proto);
if (!sk)
return NULL;
@@ -530,7 +615,7 @@ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int p
INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
sk->sk_destruct = l2cap_sock_destruct;
- sk->sk_sndtimeo = L2CAP_CONN_TIMEOUT;
+ sk->sk_sndtimeo = msecs_to_jiffies(L2CAP_CONN_TIMEOUT);
sock_reset_flag(sk, SOCK_ZAPPED);
@@ -650,6 +735,11 @@ static int l2cap_do_connect(struct sock *sk)
l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
if (hcon->state == BT_CONNECTED) {
+ if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)) {
+ l2cap_conn_ready(conn);
+ goto done;
+ }
+
if (sk->sk_type == SOCK_SEQPACKET) {
struct l2cap_conn_req req;
l2cap_pi(sk)->ident = l2cap_get_ident(conn);
@@ -958,7 +1048,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
opts.imtu = l2cap_pi(sk)->imtu;
opts.omtu = l2cap_pi(sk)->omtu;
opts.flush_to = l2cap_pi(sk)->flush_to;
- opts.mode = 0x00;
+ opts.mode = L2CAP_MODE_BASIC;
len = min_t(unsigned int, sizeof(opts), optlen);
if (copy_from_user((char *) &opts, optval, len)) {
@@ -1007,7 +1097,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
opts.imtu = l2cap_pi(sk)->imtu;
opts.omtu = l2cap_pi(sk)->omtu;
opts.flush_to = l2cap_pi(sk)->flush_to;
- opts.mode = 0x00;
+ opts.mode = L2CAP_MODE_BASIC;
len = min_t(unsigned int, len, sizeof(opts));
if (copy_to_user(optval, (char *) &opts, len))
@@ -1084,52 +1174,6 @@ static int l2cap_sock_release(struct socket *sock)
return err;
}
-static void l2cap_conn_ready(struct l2cap_conn *conn)
-{
- struct l2cap_chan_list *l = &conn->chan_list;
- struct sock *sk;
-
- BT_DBG("conn %p", conn);
-
- read_lock(&l->lock);
-
- for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
- bh_lock_sock(sk);
-
- if (sk->sk_type != SOCK_SEQPACKET) {
- l2cap_sock_clear_timer(sk);
- sk->sk_state = BT_CONNECTED;
- sk->sk_state_change(sk);
- } else if (sk->sk_state == BT_CONNECT) {
- struct l2cap_conn_req req;
- l2cap_pi(sk)->ident = l2cap_get_ident(conn);
- req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
- req.psm = l2cap_pi(sk)->psm;
- l2cap_send_cmd(conn, l2cap_pi(sk)->ident, L2CAP_CONN_REQ, sizeof(req), &req);
- }
-
- bh_unlock_sock(sk);
- }
-
- read_unlock(&l->lock);
-}
-
-/* Notify sockets that we cannot guaranty reliability anymore */
-static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
-{
- struct l2cap_chan_list *l = &conn->chan_list;
- struct sock *sk;
-
- BT_DBG("conn %p", conn);
-
- read_lock(&l->lock);
- for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
- if (l2cap_pi(sk)->link_mode & L2CAP_LM_RELIABLE)
- sk->sk_err = err;
- }
- read_unlock(&l->lock);
-}
-
static void l2cap_chan_ready(struct sock *sk)
{
struct sock *parent = bt_sk(sk)->parent;
@@ -1256,11 +1300,11 @@ static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned
break;
case 2:
- *val = __le16_to_cpu(*((__le16 *)opt->val));
+ *val = __le16_to_cpu(*((__le16 *) opt->val));
break;
case 4:
- *val = __le32_to_cpu(*((__le32 *)opt->val));
+ *val = __le32_to_cpu(*((__le32 *) opt->val));
break;
default:
@@ -1332,6 +1376,8 @@ static int l2cap_parse_conf_req(struct sock *sk, void *data)
int len = pi->conf_len;
int type, hint, olen;
unsigned long val;
+ struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
+ u16 mtu = L2CAP_DEFAULT_MTU;
u16 result = L2CAP_CONF_SUCCESS;
BT_DBG("sk %p", sk);
@@ -1344,7 +1390,7 @@ static int l2cap_parse_conf_req(struct sock *sk, void *data)
switch (type) {
case L2CAP_CONF_MTU:
- pi->conf_mtu = val;
+ mtu = val;
break;
case L2CAP_CONF_FLUSH_TO:
@@ -1354,6 +1400,11 @@ static int l2cap_parse_conf_req(struct sock *sk, void *data)
case L2CAP_CONF_QOS:
break;
+ case L2CAP_CONF_RFC:
+ if (olen == sizeof(rfc))
+ memcpy(&rfc, (void *) val, olen);
+ break;
+
default:
if (hint)
break;
@@ -1368,12 +1419,24 @@ static int l2cap_parse_conf_req(struct sock *sk, void *data)
/* Configure output options and let the other side know
* which ones we don't like. */
- if (pi->conf_mtu < pi->omtu)
+ if (rfc.mode == L2CAP_MODE_BASIC) {
+ if (mtu < pi->omtu)
+ result = L2CAP_CONF_UNACCEPT;
+ else {
+ pi->omtu = mtu;
+ pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
+ }
+
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
+ } else {
result = L2CAP_CONF_UNACCEPT;
- else
- pi->omtu = pi->conf_mtu;
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
+ memset(&rfc, 0, sizeof(rfc));
+ rfc.mode = L2CAP_MODE_BASIC;
+
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
+ sizeof(rfc), (unsigned long) &rfc);
+ }
}
rsp->scid = cpu_to_le16(pi->dcid);
@@ -1397,6 +1460,23 @@ static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 fla
return ptr - data;
}
+static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
+{
+ struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
+
+ if (rej->reason != 0x0000)
+ return 0;
+
+ if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
+ cmd->ident == conn->info_ident) {
+ conn->info_ident = 0;
+ del_timer(&conn->info_timer);
+ l2cap_conn_start(conn);
+ }
+
+ return 0;
+}
+
static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
{
struct l2cap_chan_list *list = &conn->chan_list;
@@ -1577,16 +1657,19 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
- /* Output config done. */
- l2cap_pi(sk)->conf_state |= L2CAP_CONF_OUTPUT_DONE;
-
/* Reset config buffer. */
l2cap_pi(sk)->conf_len = 0;
+ if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
+ goto unlock;
+
if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
sk->sk_state = BT_CONNECTED;
l2cap_chan_ready(sk);
- } else if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
+ goto unlock;
+ }
+
+ if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
u8 req[64];
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
l2cap_build_conf_req(sk, req), req);
@@ -1646,7 +1729,6 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
if (flags & 0x01)
goto done;
- /* Input config done */
l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
@@ -1711,16 +1793,27 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
{
struct l2cap_info_req *req = (struct l2cap_info_req *) data;
- struct l2cap_info_rsp rsp;
u16 type;
type = __le16_to_cpu(req->type);
BT_DBG("type 0x%4.4x", type);
- rsp.type = cpu_to_le16(type);
- rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
- l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp), &rsp);
+ if (type == L2CAP_IT_FEAT_MASK) {
+ u8 buf[8];
+ struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
+ rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
+ rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
+ put_unaligned(cpu_to_le32(l2cap_feat_mask), (__le32 *) rsp->data);
+ l2cap_send_cmd(conn, cmd->ident,
+ L2CAP_INFO_RSP, sizeof(buf), buf);
+ } else {
+ struct l2cap_info_rsp rsp;
+ rsp.type = cpu_to_le16(type);
+ rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
+ l2cap_send_cmd(conn, cmd->ident,
+ L2CAP_INFO_RSP, sizeof(rsp), &rsp);
+ }
return 0;
}
@@ -1735,6 +1828,15 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm
BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
+ conn->info_ident = 0;
+
+ del_timer(&conn->info_timer);
+
+ if (type == L2CAP_IT_FEAT_MASK)
+ conn->feat_mask = __le32_to_cpu(get_unaligned((__le32 *) rsp->data));
+
+ l2cap_conn_start(conn);
+
return 0;
}
@@ -1764,7 +1866,7 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn, struct sk_buff *sk
switch (cmd.code) {
case L2CAP_COMMAND_REJ:
- /* FIXME: We should process this */
+ l2cap_command_rej(conn, &cmd, data);
break;
case L2CAP_CONN_REQ:
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index bb7220770f2c..e7ac6ba7ecab 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -33,11 +33,11 @@
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/init.h>
-#include <linux/freezer.h>
#include <linux/wait.h>
#include <linux/device.h>
#include <linux/net.h>
#include <linux/mutex.h>
+#include <linux/kthread.h>
#include <net/sock.h>
#include <asm/uaccess.h>
@@ -68,7 +68,6 @@ static DEFINE_MUTEX(rfcomm_mutex);
static unsigned long rfcomm_event;
static LIST_HEAD(session_list);
-static atomic_t terminate, running;
static int rfcomm_send_frame(struct rfcomm_session *s, u8 *data, int len);
static int rfcomm_send_sabm(struct rfcomm_session *s, u8 dlci);
@@ -1850,26 +1849,6 @@ static inline void rfcomm_process_sessions(void)
rfcomm_unlock();
}
-static void rfcomm_worker(void)
-{
- BT_DBG("");
-
- while (!atomic_read(&terminate)) {
- set_current_state(TASK_INTERRUPTIBLE);
- if (!test_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event)) {
- /* No pending events. Let's sleep.
- * Incoming connections and data will wake us up. */
- schedule();
- }
- set_current_state(TASK_RUNNING);
-
- /* Process stuff */
- clear_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event);
- rfcomm_process_sessions();
- }
- return;
-}
-
static int rfcomm_add_listener(bdaddr_t *ba)
{
struct sockaddr_l2 addr;
@@ -1935,22 +1914,28 @@ static void rfcomm_kill_listener(void)
static int rfcomm_run(void *unused)
{
- rfcomm_thread = current;
-
- atomic_inc(&running);
+ BT_DBG("");
- daemonize("krfcommd");
set_user_nice(current, -10);
- BT_DBG("");
-
rfcomm_add_listener(BDADDR_ANY);
- rfcomm_worker();
+ while (!kthread_should_stop()) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (!test_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event)) {
+ /* No pending events. Let's sleep.
+ * Incoming connections and data will wake us up. */
+ schedule();
+ }
+ set_current_state(TASK_RUNNING);
+
+ /* Process stuff */
+ clear_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event);
+ rfcomm_process_sessions();
+ }
rfcomm_kill_listener();
- atomic_dec(&running);
return 0;
}
@@ -2059,7 +2044,11 @@ static int __init rfcomm_init(void)
hci_register_cb(&rfcomm_cb);
- kernel_thread(rfcomm_run, NULL, CLONE_KERNEL);
+ rfcomm_thread = kthread_run(rfcomm_run, NULL, "krfcommd");
+ if (IS_ERR(rfcomm_thread)) {
+ hci_unregister_cb(&rfcomm_cb);
+ return PTR_ERR(rfcomm_thread);
+ }
if (class_create_file(bt_class, &class_attr_rfcomm_dlc) < 0)
BT_ERR("Failed to create RFCOMM info file");
@@ -2081,14 +2070,7 @@ static void __exit rfcomm_exit(void)
hci_unregister_cb(&rfcomm_cb);
- /* Terminate working thread.
- * ie. Set terminate flag and wake it up */
- atomic_inc(&terminate);
- rfcomm_schedule(RFCOMM_SCHED_STATE);
-
- /* Wait until thread is running */
- while (atomic_read(&running))
- schedule();
+ kthread_stop(rfcomm_thread);
#ifdef CONFIG_BT_RFCOMM_TTY
rfcomm_cleanup_ttys();
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 266b6972667d..c46d51035e77 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -287,7 +287,7 @@ static struct sock *rfcomm_sock_alloc(struct net *net, struct socket *sock, int
struct rfcomm_dlc *d;
struct sock *sk;
- sk = sk_alloc(net, PF_BLUETOOTH, prio, &rfcomm_proto, 1);
+ sk = sk_alloc(net, PF_BLUETOOTH, prio, &rfcomm_proto);
if (!sk)
return NULL;
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index 22a832098d44..e447651a2dbe 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -189,6 +189,23 @@ static struct device *rfcomm_get_device(struct rfcomm_dev *dev)
return conn ? &conn->dev : NULL;
}
+static ssize_t show_address(struct device *tty_dev, struct device_attribute *attr, char *buf)
+{
+ struct rfcomm_dev *dev = dev_get_drvdata(tty_dev);
+ bdaddr_t bdaddr;
+ baswap(&bdaddr, &dev->dst);
+ return sprintf(buf, "%s\n", batostr(&bdaddr));
+}
+
+static ssize_t show_channel(struct device *tty_dev, struct device_attribute *attr, char *buf)
+{
+ struct rfcomm_dev *dev = dev_get_drvdata(tty_dev);
+ return sprintf(buf, "%d\n", dev->channel);
+}
+
+static DEVICE_ATTR(address, S_IRUGO, show_address, NULL);
+static DEVICE_ATTR(channel, S_IRUGO, show_channel, NULL);
+
static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
{
struct rfcomm_dev *dev;
@@ -281,6 +298,14 @@ out:
return err;
}
+ dev_set_drvdata(dev->tty_dev, dev);
+
+ if (device_create_file(dev->tty_dev, &dev_attr_address) < 0)
+ BT_ERR("Failed to create address attribute");
+
+ if (device_create_file(dev->tty_dev, &dev_attr_channel) < 0)
+ BT_ERR("Failed to create channel attribute");
+
return dev->id;
}
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 65b6fb1c4154..93ad1aae3f38 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -189,7 +189,7 @@ static int sco_connect(struct sock *sk)
struct sco_conn *conn;
struct hci_conn *hcon;
struct hci_dev *hdev;
- int err = 0;
+ int err, type;
BT_DBG("%s -> %s", batostr(src), batostr(dst));
@@ -200,7 +200,9 @@ static int sco_connect(struct sock *sk)
err = -ENOMEM;
- hcon = hci_connect(hdev, SCO_LINK, dst);
+ type = lmp_esco_capable(hdev) ? ESCO_LINK : SCO_LINK;
+
+ hcon = hci_connect(hdev, type, dst);
if (!hcon)
goto done;
@@ -224,6 +226,7 @@ static int sco_connect(struct sock *sk)
sk->sk_state = BT_CONNECT;
sco_sock_set_timer(sk, sk->sk_sndtimeo);
}
+
done:
hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
@@ -418,7 +421,7 @@ static struct sock *sco_sock_alloc(struct net *net, struct socket *sock, int pro
{
struct sock *sk;
- sk = sk_alloc(net, PF_BLUETOOTH, prio, &sco_proto, 1);
+ sk = sk_alloc(net, PF_BLUETOOTH, prio, &sco_proto);
if (!sk)
return NULL;
@@ -846,7 +849,7 @@ static int sco_connect_cfm(struct hci_conn *hcon, __u8 status)
{
BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
- if (hcon->type != SCO_LINK)
+ if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
return 0;
if (!status) {
@@ -865,10 +868,11 @@ static int sco_disconn_ind(struct hci_conn *hcon, __u8 reason)
{
BT_DBG("hcon %p reason %d", hcon, reason);
- if (hcon->type != SCO_LINK)
+ if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
return 0;
sco_conn_del(hcon, bt_err(reason));
+
return 0;
}
diff --git a/net/bridge/br.c b/net/bridge/br.c
index 848b8fa8bedd..93867bb6cc97 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -23,7 +23,7 @@
#include "br_private.h"
-int (*br_should_route_hook) (struct sk_buff **pskb) = NULL;
+int (*br_should_route_hook)(struct sk_buff *skb);
static struct llc_sap *br_stp_sap;
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 3a8a015c92e0..3cedd4eeeed6 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -126,6 +126,10 @@ struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct sk_buff *skb)
if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
goto drop;
+ skb = skb_share_check(skb, GFP_ATOMIC);
+ if (!skb)
+ return NULL;
+
if (unlikely(is_link_local(dest))) {
/* Pause frames shouldn't be passed up by driver anyway */
if (skb->protocol == htons(ETH_P_PAUSE))
@@ -145,7 +149,7 @@ struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct sk_buff *skb)
case BR_STATE_FORWARDING:
if (br_should_route_hook) {
- if (br_should_route_hook(&skb))
+ if (br_should_route_hook(skb))
return skb;
dest = eth_hdr(skb)->h_dest;
}
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 8245f051ccbb..c1757c79dfbb 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -503,18 +503,14 @@ inhdr_error:
* receiving device) to make netfilter happy, the REDIRECT
* target in particular. Save the original destination IP
* address to be able to detect DNAT afterwards. */
-static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
+static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
struct iphdr *iph;
- struct sk_buff *skb = *pskb;
__u32 len = nf_bridge_encap_header_len(skb);
- if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
- return NF_STOLEN;
-
if (unlikely(!pskb_may_pull(skb, len)))
goto out;
@@ -584,13 +580,11 @@ out:
* took place when the packet entered the bridge), but we
* register an IPv4 PRE_ROUTING 'sabotage' hook that will
* prevent this from happening. */
-static unsigned int br_nf_local_in(unsigned int hook, struct sk_buff **pskb,
+static unsigned int br_nf_local_in(unsigned int hook, struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
- struct sk_buff *skb = *pskb;
-
if (skb->dst == (struct dst_entry *)&__fake_rtable) {
dst_release(skb->dst);
skb->dst = NULL;
@@ -625,12 +619,11 @@ static int br_nf_forward_finish(struct sk_buff *skb)
* but we are still able to filter on the 'real' indev/outdev
* because of the physdev module. For ARP, indev and outdev are the
* bridge ports. */
-static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb,
+static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
- struct sk_buff *skb = *pskb;
struct nf_bridge_info *nf_bridge;
struct net_device *parent;
int pf;
@@ -648,7 +641,7 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb,
else
pf = PF_INET6;
- nf_bridge_pull_encap_header(*pskb);
+ nf_bridge_pull_encap_header(skb);
nf_bridge = skb->nf_bridge;
if (skb->pkt_type == PACKET_OTHERHOST) {
@@ -666,12 +659,11 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb,
return NF_STOLEN;
}
-static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb,
+static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
- struct sk_buff *skb = *pskb;
struct net_device **d = (struct net_device **)(skb->cb);
#ifdef CONFIG_SYSCTL
@@ -682,12 +674,12 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb,
if (skb->protocol != htons(ETH_P_ARP)) {
if (!IS_VLAN_ARP(skb))
return NF_ACCEPT;
- nf_bridge_pull_encap_header(*pskb);
+ nf_bridge_pull_encap_header(skb);
}
if (arp_hdr(skb)->ar_pln != 4) {
if (IS_VLAN_ARP(skb))
- nf_bridge_push_encap_header(*pskb);
+ nf_bridge_push_encap_header(skb);
return NF_ACCEPT;
}
*d = (struct net_device *)in;
@@ -709,13 +701,12 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb,
* NF_BR_PRI_FIRST, so no relevant PF_BRIDGE/INPUT functions have been nor
* will be executed.
*/
-static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
+static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
struct net_device *realindev;
- struct sk_buff *skb = *pskb;
struct nf_bridge_info *nf_bridge;
if (!skb->nf_bridge)
@@ -752,13 +743,12 @@ static int br_nf_dev_queue_xmit(struct sk_buff *skb)
}
/* PF_BRIDGE/POST_ROUTING ********************************************/
-static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
+static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
- struct sk_buff *skb = *pskb;
- struct nf_bridge_info *nf_bridge = (*pskb)->nf_bridge;
+ struct nf_bridge_info *nf_bridge = skb->nf_bridge;
struct net_device *realoutdev = bridge_parent(skb->dev);
int pf;
@@ -776,6 +766,9 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
if (!nf_bridge)
return NF_ACCEPT;
+ if (!(nf_bridge->mask & (BRNF_BRIDGED | BRNF_BRIDGED_DNAT)))
+ return NF_ACCEPT;
+
if (!realoutdev)
return NF_DROP;
@@ -828,13 +821,13 @@ print_error:
/* IP/SABOTAGE *****************************************************/
/* Don't hand locally destined packets to PF_INET(6)/PRE_ROUTING
* for the second time. */
-static unsigned int ip_sabotage_in(unsigned int hook, struct sk_buff **pskb,
+static unsigned int ip_sabotage_in(unsigned int hook, struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
- if ((*pskb)->nf_bridge &&
- !((*pskb)->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)) {
+ if (skb->nf_bridge &&
+ !(skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)) {
return NF_STOP;
}
diff --git a/net/bridge/netfilter/ebt_arp.c b/net/bridge/netfilter/ebt_arp.c
index 1a46952a56d9..18141392a9b4 100644
--- a/net/bridge/netfilter/ebt_arp.c
+++ b/net/bridge/netfilter/ebt_arp.c
@@ -34,7 +34,7 @@ static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in
ah->ar_pro, EBT_ARP_PTYPE))
return EBT_NOMATCH;
- if (info->bitmask & (EBT_ARP_SRC_IP | EBT_ARP_DST_IP)) {
+ if (info->bitmask & (EBT_ARP_SRC_IP | EBT_ARP_DST_IP | EBT_ARP_GRAT)) {
__be32 saddr, daddr, *sap, *dap;
if (ah->ar_pln != sizeof(__be32) || ah->ar_pro != htons(ETH_P_IP))
diff --git a/net/bridge/netfilter/ebt_arpreply.c b/net/bridge/netfilter/ebt_arpreply.c
index ffe468a632e7..48a80e423287 100644
--- a/net/bridge/netfilter/ebt_arpreply.c
+++ b/net/bridge/netfilter/ebt_arpreply.c
@@ -15,7 +15,7 @@
#include <net/arp.h>
#include <linux/module.h>
-static int ebt_target_reply(struct sk_buff **pskb, unsigned int hooknr,
+static int ebt_target_reply(struct sk_buff *skb, unsigned int hooknr,
const struct net_device *in, const struct net_device *out,
const void *data, unsigned int datalen)
{
@@ -23,7 +23,6 @@ static int ebt_target_reply(struct sk_buff **pskb, unsigned int hooknr,
__be32 _sip, *siptr, _dip, *diptr;
struct arphdr _ah, *ap;
unsigned char _sha[ETH_ALEN], *shp;
- struct sk_buff *skb = *pskb;
ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah);
if (ap == NULL)
diff --git a/net/bridge/netfilter/ebt_dnat.c b/net/bridge/netfilter/ebt_dnat.c
index 4582659dff0e..74262e9a566a 100644
--- a/net/bridge/netfilter/ebt_dnat.c
+++ b/net/bridge/netfilter/ebt_dnat.c
@@ -8,29 +8,22 @@
*
*/
+#include <linux/netfilter.h>
#include <linux/netfilter_bridge/ebtables.h>
#include <linux/netfilter_bridge/ebt_nat.h>
#include <linux/module.h>
#include <net/sock.h>
-static int ebt_target_dnat(struct sk_buff **pskb, unsigned int hooknr,
+static int ebt_target_dnat(struct sk_buff *skb, unsigned int hooknr,
const struct net_device *in, const struct net_device *out,
const void *data, unsigned int datalen)
{
struct ebt_nat_info *info = (struct ebt_nat_info *)data;
- if (skb_shared(*pskb) || skb_cloned(*pskb)) {
- struct sk_buff *nskb;
+ if (skb_make_writable(skb, 0))
+ return NF_DROP;
- nskb = skb_copy(*pskb, GFP_ATOMIC);
- if (!nskb)
- return NF_DROP;
- if ((*pskb)->sk)
- skb_set_owner_w(nskb, (*pskb)->sk);
- kfree_skb(*pskb);
- *pskb = nskb;
- }
- memcpy(eth_hdr(*pskb)->h_dest, info->mac, ETH_ALEN);
+ memcpy(eth_hdr(skb)->h_dest, info->mac, ETH_ALEN);
return info->target;
}
diff --git a/net/bridge/netfilter/ebt_mark.c b/net/bridge/netfilter/ebt_mark.c
index 62d23c7b25e6..6cba54309c09 100644
--- a/net/bridge/netfilter/ebt_mark.c
+++ b/net/bridge/netfilter/ebt_mark.c
@@ -17,7 +17,7 @@
#include <linux/netfilter_bridge/ebt_mark_t.h>
#include <linux/module.h>
-static int ebt_target_mark(struct sk_buff **pskb, unsigned int hooknr,
+static int ebt_target_mark(struct sk_buff *skb, unsigned int hooknr,
const struct net_device *in, const struct net_device *out,
const void *data, unsigned int datalen)
{
@@ -25,13 +25,13 @@ static int ebt_target_mark(struct sk_buff **pskb, unsigned int hooknr,
int action = info->target & -16;
if (action == MARK_SET_VALUE)
- (*pskb)->mark = info->mark;
+ skb->mark = info->mark;
else if (action == MARK_OR_VALUE)
- (*pskb)->mark |= info->mark;
+ skb->mark |= info->mark;
else if (action == MARK_AND_VALUE)
- (*pskb)->mark &= info->mark;
+ skb->mark &= info->mark;
else
- (*pskb)->mark ^= info->mark;
+ skb->mark ^= info->mark;
return info->target | ~EBT_VERDICT_BITS;
}
diff --git a/net/bridge/netfilter/ebt_redirect.c b/net/bridge/netfilter/ebt_redirect.c
index 9f378eab72d0..422cb834cff9 100644
--- a/net/bridge/netfilter/ebt_redirect.c
+++ b/net/bridge/netfilter/ebt_redirect.c
@@ -8,35 +8,28 @@
*
*/
+#include <linux/netfilter.h>
#include <linux/netfilter_bridge/ebtables.h>
#include <linux/netfilter_bridge/ebt_redirect.h>
#include <linux/module.h>
#include <net/sock.h>
#include "../br_private.h"
-static int ebt_target_redirect(struct sk_buff **pskb, unsigned int hooknr,
+static int ebt_target_redirect(struct sk_buff *skb, unsigned int hooknr,
const struct net_device *in, const struct net_device *out,
const void *data, unsigned int datalen)
{
struct ebt_redirect_info *info = (struct ebt_redirect_info *)data;
- if (skb_shared(*pskb) || skb_cloned(*pskb)) {
- struct sk_buff *nskb;
+ if (skb_make_writable(skb, 0))
+ return NF_DROP;
- nskb = skb_copy(*pskb, GFP_ATOMIC);
- if (!nskb)
- return NF_DROP;
- if ((*pskb)->sk)
- skb_set_owner_w(nskb, (*pskb)->sk);
- kfree_skb(*pskb);
- *pskb = nskb;
- }
if (hooknr != NF_BR_BROUTING)
- memcpy(eth_hdr(*pskb)->h_dest,
+ memcpy(eth_hdr(skb)->h_dest,
in->br_port->br->dev->dev_addr, ETH_ALEN);
else
- memcpy(eth_hdr(*pskb)->h_dest, in->dev_addr, ETH_ALEN);
- (*pskb)->pkt_type = PACKET_HOST;
+ memcpy(eth_hdr(skb)->h_dest, in->dev_addr, ETH_ALEN);
+ skb->pkt_type = PACKET_HOST;
return info->target;
}
diff --git a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c
index a50722182bfe..425ac920904d 100644
--- a/net/bridge/netfilter/ebt_snat.c
+++ b/net/bridge/netfilter/ebt_snat.c
@@ -8,6 +8,7 @@
*
*/
+#include <linux/netfilter.h>
#include <linux/netfilter_bridge/ebtables.h>
#include <linux/netfilter_bridge/ebt_nat.h>
#include <linux/module.h>
@@ -15,34 +16,26 @@
#include <linux/if_arp.h>
#include <net/arp.h>
-static int ebt_target_snat(struct sk_buff **pskb, unsigned int hooknr,
+static int ebt_target_snat(struct sk_buff *skb, unsigned int hooknr,
const struct net_device *in, const struct net_device *out,
const void *data, unsigned int datalen)
{
struct ebt_nat_info *info = (struct ebt_nat_info *) data;
- if (skb_shared(*pskb) || skb_cloned(*pskb)) {
- struct sk_buff *nskb;
+ if (skb_make_writable(skb, 0))
+ return NF_DROP;
- nskb = skb_copy(*pskb, GFP_ATOMIC);
- if (!nskb)
- return NF_DROP;
- if ((*pskb)->sk)
- skb_set_owner_w(nskb, (*pskb)->sk);
- kfree_skb(*pskb);
- *pskb = nskb;
- }
- memcpy(eth_hdr(*pskb)->h_source, info->mac, ETH_ALEN);
+ memcpy(eth_hdr(skb)->h_source, info->mac, ETH_ALEN);
if (!(info->target & NAT_ARP_BIT) &&
- eth_hdr(*pskb)->h_proto == htons(ETH_P_ARP)) {
+ eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) {
struct arphdr _ah, *ap;
- ap = skb_header_pointer(*pskb, 0, sizeof(_ah), &_ah);
+ ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah);
if (ap == NULL)
return EBT_DROP;
if (ap->ar_hln != ETH_ALEN)
goto out;
- if (skb_store_bits(*pskb, sizeof(_ah), info->mac,ETH_ALEN))
+ if (skb_store_bits(skb, sizeof(_ah), info->mac,ETH_ALEN))
return EBT_DROP;
}
out:
diff --git a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c
index d37ce0478938..e44519ebf1d2 100644
--- a/net/bridge/netfilter/ebtable_broute.c
+++ b/net/bridge/netfilter/ebtable_broute.c
@@ -51,11 +51,11 @@ static struct ebt_table broute_table =
.me = THIS_MODULE,
};
-static int ebt_broute(struct sk_buff **pskb)
+static int ebt_broute(struct sk_buff *skb)
{
int ret;
- ret = ebt_do_table(NF_BR_BROUTING, pskb, (*pskb)->dev, NULL,
+ ret = ebt_do_table(NF_BR_BROUTING, skb, skb->dev, NULL,
&broute_table);
if (ret == NF_DROP)
return 1; /* route it */
diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c
index 81d84145c417..210493f99bc4 100644
--- a/net/bridge/netfilter/ebtable_filter.c
+++ b/net/bridge/netfilter/ebtable_filter.c
@@ -61,10 +61,10 @@ static struct ebt_table frame_filter =
};
static unsigned int
-ebt_hook (unsigned int hook, struct sk_buff **pskb, const struct net_device *in,
+ebt_hook(unsigned int hook, struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, int (*okfn)(struct sk_buff *))
{
- return ebt_do_table(hook, pskb, in, out, &frame_filter);
+ return ebt_do_table(hook, skb, in, out, &frame_filter);
}
static struct nf_hook_ops ebt_ops_filter[] = {
diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c
index 9c50488b62eb..3e58c2e5ee21 100644
--- a/net/bridge/netfilter/ebtable_nat.c
+++ b/net/bridge/netfilter/ebtable_nat.c
@@ -61,17 +61,17 @@ static struct ebt_table frame_nat =
};
static unsigned int
-ebt_nat_dst(unsigned int hook, struct sk_buff **pskb, const struct net_device *in
+ebt_nat_dst(unsigned int hook, struct sk_buff *skb, const struct net_device *in
, const struct net_device *out, int (*okfn)(struct sk_buff *))
{
- return ebt_do_table(hook, pskb, in, out, &frame_nat);
+ return ebt_do_table(hook, skb, in, out, &frame_nat);
}
static unsigned int
-ebt_nat_src(unsigned int hook, struct sk_buff **pskb, const struct net_device *in
+ebt_nat_src(unsigned int hook, struct sk_buff *skb, const struct net_device *in
, const struct net_device *out, int (*okfn)(struct sk_buff *))
{
- return ebt_do_table(hook, pskb, in, out, &frame_nat);
+ return ebt_do_table(hook, skb, in, out, &frame_nat);
}
static struct nf_hook_ops ebt_ops_nat[] = {
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 6018d0e51938..817169e718c1 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -142,7 +142,7 @@ static inline int ebt_basic_match(struct ebt_entry *e, struct ethhdr *h,
}
/* Do some firewalling */
-unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
+unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb,
const struct net_device *in, const struct net_device *out,
struct ebt_table *table)
{
@@ -172,19 +172,19 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
base = private->entries;
i = 0;
while (i < nentries) {
- if (ebt_basic_match(point, eth_hdr(*pskb), in, out))
+ if (ebt_basic_match(point, eth_hdr(skb), in, out))
goto letscontinue;
- if (EBT_MATCH_ITERATE(point, ebt_do_match, *pskb, in, out) != 0)
+ if (EBT_MATCH_ITERATE(point, ebt_do_match, skb, in, out) != 0)
goto letscontinue;
/* increase counter */
(*(counter_base + i)).pcnt++;
- (*(counter_base + i)).bcnt+=(**pskb).len;
+ (*(counter_base + i)).bcnt += skb->len;
/* these should only watch: not modify, nor tell us
what to do with the packet */
- EBT_WATCHER_ITERATE(point, ebt_do_watcher, *pskb, hook, in,
+ EBT_WATCHER_ITERATE(point, ebt_do_watcher, skb, hook, in,
out);
t = (struct ebt_entry_target *)
@@ -193,7 +193,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
if (!t->u.target->target)
verdict = ((struct ebt_standard_target *)t)->verdict;
else
- verdict = t->u.target->target(pskb, hook,
+ verdict = t->u.target->target(skb, hook,
in, out, t->data, t->target_size);
if (verdict == EBT_ACCEPT) {
read_unlock_bh(&table->lock);
@@ -871,7 +871,7 @@ static int translate_table(char *name, struct ebt_table_info *newinfo)
return -EINVAL;
}
- /* we now know the following (along with E=mc²):
+ /* we now know the following (along with E=mc²):
- the nr of entries in each chain is right
- the size of the allocated space is right
- all valid hooks have a corresponding chain
diff --git a/net/core/dev.c b/net/core/dev.c
index 99b7bda37d10..86d62611f2fc 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -120,6 +120,8 @@
#include <linux/ctype.h>
#include <linux/if_arp.h>
+#include "net-sysfs.h"
+
/*
* The list of packet types we will receive (as opposed to discard)
* and the routines to invoke.
@@ -249,10 +251,6 @@ static RAW_NOTIFIER_HEAD(netdev_chain);
DEFINE_PER_CPU(struct softnet_data, softnet_data);
-extern int netdev_kobject_init(void);
-extern int netdev_register_kobject(struct net_device *);
-extern void netdev_unregister_kobject(struct net_device *);
-
#ifdef CONFIG_DEBUG_LOCK_ALLOC
/*
* register_netdevice() inits dev->_xmit_lock and sets lockdep class
@@ -885,6 +883,9 @@ int dev_change_name(struct net_device *dev, char *newname)
if (!dev_valid_name(newname))
return -EINVAL;
+ if (strncmp(newname, dev->name, IFNAMSIZ) == 0)
+ return 0;
+
memcpy(oldname, dev->name, IFNAMSIZ);
if (strchr(newname, '%')) {
@@ -1007,17 +1008,20 @@ int dev_open(struct net_device *dev)
* Call device private open method
*/
set_bit(__LINK_STATE_START, &dev->state);
- if (dev->open) {
+
+ if (dev->validate_addr)
+ ret = dev->validate_addr(dev);
+
+ if (!ret && dev->open)
ret = dev->open(dev);
- if (ret)
- clear_bit(__LINK_STATE_START, &dev->state);
- }
/*
* If it went open OK then:
*/
- if (!ret) {
+ if (ret)
+ clear_bit(__LINK_STATE_START, &dev->state);
+ else {
/*
* Set the flags.
*/
@@ -1038,6 +1042,7 @@ int dev_open(struct net_device *dev)
*/
call_netdevice_notifiers(NETDEV_UP, dev);
}
+
return ret;
}
@@ -1166,6 +1171,8 @@ rollback:
nb->notifier_call(nb, NETDEV_UNREGISTER, dev);
}
}
+
+ raw_notifier_chain_unregister(&netdev_chain, nb);
goto unlock;
}
@@ -1362,22 +1369,21 @@ int skb_checksum_help(struct sk_buff *skb)
goto out_set_summed;
}
- if (skb_cloned(skb)) {
+ offset = skb->csum_start - skb_headroom(skb);
+ BUG_ON(offset >= skb_headlen(skb));
+ csum = skb_checksum(skb, offset, skb->len - offset, 0);
+
+ offset += skb->csum_offset;
+ BUG_ON(offset + sizeof(__sum16) > skb_headlen(skb));
+
+ if (skb_cloned(skb) &&
+ !skb_clone_writable(skb, offset + sizeof(__sum16))) {
ret = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
if (ret)
goto out;
}
- offset = skb->csum_start - skb_headroom(skb);
- BUG_ON(offset > (int)skb->len);
- csum = skb_checksum(skb, offset, skb->len-offset, 0);
-
- offset = skb_headlen(skb) - offset;
- BUG_ON(offset <= 0);
- BUG_ON(skb->csum_offset + 2 > offset);
-
- *(__sum16 *)(skb->head + skb->csum_start + skb->csum_offset) =
- csum_fold(csum);
+ *(__sum16 *)(skb->data + offset) = csum_fold(csum);
out_set_summed:
skb->ip_summed = CHECKSUM_NONE;
out:
@@ -1554,7 +1560,7 @@ gso:
return rc;
}
if (unlikely((netif_queue_stopped(dev) ||
- netif_subqueue_stopped(dev, skb->queue_mapping)) &&
+ netif_subqueue_stopped(dev, skb)) &&
skb->next))
return NETDEV_TX_BUSY;
} while (skb->next);
@@ -1662,7 +1668,7 @@ gso:
q = dev->qdisc;
if (q->enqueue) {
/* reset queue_mapping to zero */
- skb->queue_mapping = 0;
+ skb_set_queue_mapping(skb, 0);
rc = q->enqueue(skb, q);
qdisc_run(dev);
spin_unlock(&dev->queue_lock);
@@ -1693,7 +1699,7 @@ gso:
HARD_TX_LOCK(dev, cpu);
if (!netif_queue_stopped(dev) &&
- !netif_subqueue_stopped(dev, skb->queue_mapping)) {
+ !netif_subqueue_stopped(dev, skb)) {
rc = 0;
if (!dev_hard_start_xmit(skb, dev)) {
HARD_TX_UNLOCK(dev);
@@ -1747,9 +1753,6 @@ DEFINE_PER_CPU(struct netif_rx_stats, netdev_rx_stat) = { 0, };
*
* return values:
* NET_RX_SUCCESS (no congestion)
- * NET_RX_CN_LOW (low congestion)
- * NET_RX_CN_MOD (moderate congestion)
- * NET_RX_CN_HIGH (high congestion)
* NET_RX_DROP (packet was dropped)
*
*/
@@ -1949,30 +1952,69 @@ static int ing_filter(struct sk_buff *skb)
struct Qdisc *q;
struct net_device *dev = skb->dev;
int result = TC_ACT_OK;
+ u32 ttl = G_TC_RTTL(skb->tc_verd);
- if (dev->qdisc_ingress) {
- __u32 ttl = (__u32) G_TC_RTTL(skb->tc_verd);
- if (MAX_RED_LOOP < ttl++) {
- printk(KERN_WARNING "Redir loop detected Dropping packet (%d->%d)\n",
- skb->iif, skb->dev->ifindex);
- return TC_ACT_SHOT;
- }
+ if (MAX_RED_LOOP < ttl++) {
+ printk(KERN_WARNING
+ "Redir loop detected Dropping packet (%d->%d)\n",
+ skb->iif, dev->ifindex);
+ return TC_ACT_SHOT;
+ }
- skb->tc_verd = SET_TC_RTTL(skb->tc_verd,ttl);
+ skb->tc_verd = SET_TC_RTTL(skb->tc_verd, ttl);
+ skb->tc_verd = SET_TC_AT(skb->tc_verd, AT_INGRESS);
- skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_INGRESS);
+ spin_lock(&dev->ingress_lock);
+ if ((q = dev->qdisc_ingress) != NULL)
+ result = q->enqueue(skb, q);
+ spin_unlock(&dev->ingress_lock);
- spin_lock(&dev->ingress_lock);
- if ((q = dev->qdisc_ingress) != NULL)
- result = q->enqueue(skb, q);
- spin_unlock(&dev->ingress_lock);
+ return result;
+}
+static inline struct sk_buff *handle_ing(struct sk_buff *skb,
+ struct packet_type **pt_prev,
+ int *ret, struct net_device *orig_dev)
+{
+ if (!skb->dev->qdisc_ingress)
+ goto out;
+
+ if (*pt_prev) {
+ *ret = deliver_skb(skb, *pt_prev, orig_dev);
+ *pt_prev = NULL;
+ } else {
+ /* Huh? Why does turning on AF_PACKET affect this? */
+ skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd);
}
- return result;
+ switch (ing_filter(skb)) {
+ case TC_ACT_SHOT:
+ case TC_ACT_STOLEN:
+ kfree_skb(skb);
+ return NULL;
+ }
+
+out:
+ skb->tc_verd = 0;
+ return skb;
}
#endif
+/**
+ * netif_receive_skb - process receive buffer from network
+ * @skb: buffer to process
+ *
+ * netif_receive_skb() is the main receive data processing function.
+ * It always succeeds. The buffer may be dropped during processing
+ * for congestion control or by the protocol layers.
+ *
+ * This function may only be called from softirq context and interrupts
+ * should be enabled.
+ *
+ * Return values (usually ignored):
+ * NET_RX_SUCCESS: no congestion
+ * NET_RX_DROP: packet was dropped
+ */
int netif_receive_skb(struct sk_buff *skb)
{
struct packet_type *ptype, *pt_prev;
@@ -2021,21 +2063,9 @@ int netif_receive_skb(struct sk_buff *skb)
}
#ifdef CONFIG_NET_CLS_ACT
- if (pt_prev) {
- ret = deliver_skb(skb, pt_prev, orig_dev);
- pt_prev = NULL; /* noone else should process this after*/
- } else {
- skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd);
- }
-
- ret = ing_filter(skb);
-
- if (ret == TC_ACT_SHOT || (ret == TC_ACT_STOLEN)) {
- kfree_skb(skb);
+ skb = handle_ing(skb, &pt_prev, &ret, orig_dev);
+ if (!skb)
goto out;
- }
-
- skb->tc_verd = 0;
ncls:
#endif
@@ -2156,7 +2186,15 @@ static void net_rx_action(struct softirq_action *h)
weight = n->weight;
- work = n->poll(n, weight);
+ /* This NAPI_STATE_SCHED test is for avoiding a race
+ * with netpoll's poll_napi(). Only the entity which
+ * obtains the lock and sees NAPI_STATE_SCHED set will
+ * actually make the ->poll() call. Therefore we avoid
+ * accidently calling ->poll() when NAPI is not scheduled.
+ */
+ work = 0;
+ if (test_bit(NAPI_STATE_SCHED, &n->state))
+ work = n->poll(n, weight);
WARN_ON_ONCE(work > weight);
@@ -3472,6 +3510,60 @@ static void net_set_todo(struct net_device *dev)
spin_unlock(&net_todo_list_lock);
}
+static void rollback_registered(struct net_device *dev)
+{
+ BUG_ON(dev_boot_phase);
+ ASSERT_RTNL();
+
+ /* Some devices call without registering for initialization unwind. */
+ if (dev->reg_state == NETREG_UNINITIALIZED) {
+ printk(KERN_DEBUG "unregister_netdevice: device %s/%p never "
+ "was registered\n", dev->name, dev);
+
+ WARN_ON(1);
+ return;
+ }
+
+ BUG_ON(dev->reg_state != NETREG_REGISTERED);
+
+ /* If device is running, close it first. */
+ dev_close(dev);
+
+ /* And unlink it from device chain. */
+ unlist_netdevice(dev);
+
+ dev->reg_state = NETREG_UNREGISTERING;
+
+ synchronize_net();
+
+ /* Shutdown queueing discipline. */
+ dev_shutdown(dev);
+
+
+ /* Notify protocols, that we are about to destroy
+ this device. They should clean all the things.
+ */
+ call_netdevice_notifiers(NETDEV_UNREGISTER, dev);
+
+ /*
+ * Flush the unicast and multicast chains
+ */
+ dev_addr_discard(dev);
+
+ if (dev->uninit)
+ dev->uninit(dev);
+
+ /* Notifier chain MUST detach us from master device. */
+ BUG_TRAP(!dev->master);
+
+ /* Remove entries from kobject tree */
+ netdev_unregister_kobject(dev);
+
+ synchronize_net();
+
+ dev_put(dev);
+}
+
/**
* register_netdevice - register a network device
* @dev: device to register
@@ -3609,8 +3701,10 @@ int register_netdevice(struct net_device *dev)
/* Notify protocols, that a new device appeared. */
ret = call_netdevice_notifiers(NETDEV_REGISTER, dev);
ret = notifier_to_errno(ret);
- if (ret)
- unregister_netdevice(dev);
+ if (ret) {
+ rollback_registered(dev);
+ dev->reg_state = NETREG_UNREGISTERED;
+ }
out:
return ret;
@@ -3887,59 +3981,9 @@ void synchronize_net(void)
void unregister_netdevice(struct net_device *dev)
{
- BUG_ON(dev_boot_phase);
- ASSERT_RTNL();
-
- /* Some devices call without registering for initialization unwind. */
- if (dev->reg_state == NETREG_UNINITIALIZED) {
- printk(KERN_DEBUG "unregister_netdevice: device %s/%p never "
- "was registered\n", dev->name, dev);
-
- WARN_ON(1);
- return;
- }
-
- BUG_ON(dev->reg_state != NETREG_REGISTERED);
-
- /* If device is running, close it first. */
- dev_close(dev);
-
- /* And unlink it from device chain. */
- unlist_netdevice(dev);
-
- dev->reg_state = NETREG_UNREGISTERING;
-
- synchronize_net();
-
- /* Shutdown queueing discipline. */
- dev_shutdown(dev);
-
-
- /* Notify protocols, that we are about to destroy
- this device. They should clean all the things.
- */
- call_netdevice_notifiers(NETDEV_UNREGISTER, dev);
-
- /*
- * Flush the unicast and multicast chains
- */
- dev_addr_discard(dev);
-
- if (dev->uninit)
- dev->uninit(dev);
-
- /* Notifier chain MUST detach us from master device. */
- BUG_TRAP(!dev->master);
-
- /* Remove entries from kobject tree */
- netdev_unregister_kobject(dev);
-
+ rollback_registered(dev);
/* Finish processing unregister after unlock */
net_set_todo(dev);
-
- synchronize_net();
-
- dev_put(dev);
}
/**
@@ -4288,7 +4332,6 @@ static struct hlist_head *netdev_create_hash(void)
static int __net_init netdev_init(struct net *net)
{
INIT_LIST_HEAD(&net->dev_base_head);
- rwlock_init(&dev_base_lock);
net->dev_name_head = netdev_create_hash();
if (net->dev_name_head == NULL)
diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c
index 15241cf48af8..69fff16ece10 100644
--- a/net/core/dev_mcast.c
+++ b/net/core/dev_mcast.c
@@ -168,13 +168,13 @@ void dev_mc_unsync(struct net_device *to, struct net_device *from)
da = from->mc_list;
while (da != NULL) {
next = da->next;
- if (!da->da_synced)
- continue;
- __dev_addr_delete(&to->mc_list, &to->mc_count,
- da->da_addr, da->da_addrlen, 0);
- da->da_synced = 0;
- __dev_addr_delete(&from->mc_list, &from->mc_count,
- da->da_addr, da->da_addrlen, 0);
+ if (da->da_synced) {
+ __dev_addr_delete(&to->mc_list, &to->mc_count,
+ da->da_addr, da->da_addrlen, 0);
+ da->da_synced = 0;
+ __dev_addr_delete(&from->mc_list, &from->mc_count,
+ da->da_addr, da->da_addrlen, 0);
+ }
da = next;
}
__dev_set_rx_mode(to);
diff --git a/net/core/dst.c b/net/core/dst.c
index 16958e64e577..03daead3592a 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -18,7 +18,6 @@
#include <linux/types.h>
#include <net/net_namespace.h>
-#include <net/net_namespace.h>
#include <net/dst.h>
/*
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 13de6f53f098..848132b6cb73 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -18,6 +18,28 @@
static LIST_HEAD(rules_ops);
static DEFINE_SPINLOCK(rules_mod_lock);
+int fib_default_rule_add(struct fib_rules_ops *ops,
+ u32 pref, u32 table, u32 flags)
+{
+ struct fib_rule *r;
+
+ r = kzalloc(ops->rule_size, GFP_KERNEL);
+ if (r == NULL)
+ return -ENOMEM;
+
+ atomic_set(&r->refcnt, 1);
+ r->action = FR_ACT_TO_TBL;
+ r->pref = pref;
+ r->table = table;
+ r->flags = flags;
+
+ /* The lock is not required here, the list in unreacheable
+ * at the moment this function is called */
+ list_add_tail(&r->list, &ops->rules_list);
+ return 0;
+}
+EXPORT_SYMBOL(fib_default_rule_add);
+
static void notify_rule_change(int event, struct fib_rule *rule,
struct fib_rules_ops *ops, struct nlmsghdr *nlh,
u32 pid);
diff --git a/net/core/filter.c b/net/core/filter.c
index bd903aaf7aa7..e0a06942c025 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -387,6 +387,25 @@ int sk_chk_filter(struct sock_filter *filter, int flen)
}
/**
+ * sk_filter_rcu_release: Release a socket filter by rcu_head
+ * @rcu: rcu_head that contains the sk_filter to free
+ */
+static void sk_filter_rcu_release(struct rcu_head *rcu)
+{
+ struct sk_filter *fp = container_of(rcu, struct sk_filter, rcu);
+
+ sk_filter_release(fp);
+}
+
+static void sk_filter_delayed_uncharge(struct sock *sk, struct sk_filter *fp)
+{
+ unsigned int size = sk_filter_len(fp);
+
+ atomic_sub(size, &sk->sk_omem_alloc);
+ call_rcu_bh(&fp->rcu, sk_filter_rcu_release);
+}
+
+/**
* sk_attach_filter - attach a socket filter
* @fprog: the filter program
* @sk: the socket to use
@@ -398,7 +417,7 @@ int sk_chk_filter(struct sock_filter *filter, int flen)
*/
int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
{
- struct sk_filter *fp;
+ struct sk_filter *fp, *old_fp;
unsigned int fsize = sizeof(struct sock_filter) * fprog->len;
int err;
@@ -418,19 +437,35 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
fp->len = fprog->len;
err = sk_chk_filter(fp->insns, fp->len);
- if (!err) {
- struct sk_filter *old_fp;
-
- rcu_read_lock_bh();
- old_fp = rcu_dereference(sk->sk_filter);
- rcu_assign_pointer(sk->sk_filter, fp);
- rcu_read_unlock_bh();
- fp = old_fp;
+ if (err) {
+ sk_filter_uncharge(sk, fp);
+ return err;
}
- if (fp)
- sk_filter_release(sk, fp);
- return err;
+ rcu_read_lock_bh();
+ old_fp = rcu_dereference(sk->sk_filter);
+ rcu_assign_pointer(sk->sk_filter, fp);
+ rcu_read_unlock_bh();
+
+ if (old_fp)
+ sk_filter_delayed_uncharge(sk, old_fp);
+ return 0;
+}
+
+int sk_detach_filter(struct sock *sk)
+{
+ int ret = -ENOENT;
+ struct sk_filter *filter;
+
+ rcu_read_lock_bh();
+ filter = rcu_dereference(sk->sk_filter);
+ if (filter) {
+ rcu_assign_pointer(sk->sk_filter, NULL);
+ sk_filter_delayed_uncharge(sk, filter);
+ ret = 0;
+ }
+ rcu_read_unlock_bh();
+ return ret;
}
EXPORT_SYMBOL(sk_chk_filter);
diff --git a/net/core/flow.c b/net/core/flow.c
index 0ab5234b17d8..3ed2b4b1d6d4 100644
--- a/net/core/flow.c
+++ b/net/core/flow.c
@@ -142,8 +142,6 @@ typedef u64 flow_compare_t;
typedef u32 flow_compare_t;
#endif
-extern void flowi_is_missized(void);
-
/* I hear what you're saying, use memcmp. But memcmp cannot make
* important assumptions that we can here, such as alignment and
* constant size.
@@ -153,8 +151,7 @@ static int flow_key_compare(struct flowi *key1, struct flowi *key2)
flow_compare_t *k1, *k1_lim, *k2;
const int n_elem = sizeof(struct flowi) / sizeof(flow_compare_t);
- if (sizeof(struct flowi) % sizeof(flow_compare_t))
- flowi_is_missized();
+ BUILD_BUG_ON(sizeof(struct flowi) % sizeof(flow_compare_t));
k1 = (flow_compare_t *) key1;
k1_lim = k1 + n_elem;
diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c
index 590a767b029c..daadbcc4e8dd 100644
--- a/net/core/gen_estimator.c
+++ b/net/core/gen_estimator.c
@@ -15,7 +15,7 @@
#include <asm/uaccess.h>
#include <asm/system.h>
-#include <asm/bitops.h>
+#include <linux/bitops.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index c52df858d0be..29b8ee4e35d6 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -481,6 +481,8 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, const void *pkey,
if (!creat)
goto out;
+ ASSERT_RTNL();
+
n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL);
if (!n)
goto out;
@@ -1433,9 +1435,14 @@ int neigh_table_clear(struct neigh_table *tbl)
kfree(tbl->phash_buckets);
tbl->phash_buckets = NULL;
+ remove_proc_entry(tbl->id, init_net.proc_net_stat);
+
free_percpu(tbl->stats);
tbl->stats = NULL;
+ kmem_cache_destroy(tbl->kmem_cachep);
+ tbl->kmem_cachep = NULL;
+
return 0;
}
@@ -2494,7 +2501,6 @@ static struct neigh_sysctl_table {
.proc_handler = &proc_dointvec,
},
{
- .ctl_name = NET_NEIGH_RETRANS_TIME,
.procname = "retrans_time",
.maxlen = sizeof(int),
.mode = 0644,
@@ -2539,27 +2545,40 @@ static struct neigh_sysctl_table {
.proc_handler = &proc_dointvec,
},
{
- .ctl_name = NET_NEIGH_ANYCAST_DELAY,
.procname = "anycast_delay",
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_userhz_jiffies,
},
{
- .ctl_name = NET_NEIGH_PROXY_DELAY,
.procname = "proxy_delay",
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_userhz_jiffies,
},
{
- .ctl_name = NET_NEIGH_LOCKTIME,
.procname = "locktime",
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_userhz_jiffies,
},
{
+ .ctl_name = NET_NEIGH_RETRANS_TIME_MS,
+ .procname = "retrans_time_ms",
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_ms_jiffies,
+ .strategy = &sysctl_ms_jiffies,
+ },
+ {
+ .ctl_name = NET_NEIGH_REACHABLE_TIME_MS,
+ .procname = "base_reachable_time_ms",
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_ms_jiffies,
+ .strategy = &sysctl_ms_jiffies,
+ },
+ {
.ctl_name = NET_NEIGH_GC_INTERVAL,
.procname = "gc_interval",
.maxlen = sizeof(int),
@@ -2588,22 +2607,7 @@ static struct neigh_sysctl_table {
.mode = 0644,
.proc_handler = &proc_dointvec,
},
- {
- .ctl_name = NET_NEIGH_RETRANS_TIME_MS,
- .procname = "retrans_time_ms",
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec_ms_jiffies,
- .strategy = &sysctl_ms_jiffies,
- },
- {
- .ctl_name = NET_NEIGH_REACHABLE_TIME_MS,
- .procname = "base_reachable_time_ms",
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec_ms_jiffies,
- .strategy = &sysctl_ms_jiffies,
- },
+ {}
},
.neigh_dev = {
{
@@ -2656,42 +2660,48 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
t->neigh_vars[9].data = &p->anycast_delay;
t->neigh_vars[10].data = &p->proxy_delay;
t->neigh_vars[11].data = &p->locktime;
+ t->neigh_vars[12].data = &p->retrans_time;
+ t->neigh_vars[13].data = &p->base_reachable_time;
if (dev) {
dev_name_source = dev->name;
t->neigh_dev[0].ctl_name = dev->ifindex;
- t->neigh_vars[12].procname = NULL;
- t->neigh_vars[13].procname = NULL;
- t->neigh_vars[14].procname = NULL;
- t->neigh_vars[15].procname = NULL;
+ /* Terminate the table early */
+ memset(&t->neigh_vars[14], 0, sizeof(t->neigh_vars[14]));
} else {
dev_name_source = t->neigh_dev[0].procname;
- t->neigh_vars[12].data = (int *)(p + 1);
- t->neigh_vars[13].data = (int *)(p + 1) + 1;
- t->neigh_vars[14].data = (int *)(p + 1) + 2;
- t->neigh_vars[15].data = (int *)(p + 1) + 3;
+ t->neigh_vars[14].data = (int *)(p + 1);
+ t->neigh_vars[15].data = (int *)(p + 1) + 1;
+ t->neigh_vars[16].data = (int *)(p + 1) + 2;
+ t->neigh_vars[17].data = (int *)(p + 1) + 3;
}
- t->neigh_vars[16].data = &p->retrans_time;
- t->neigh_vars[17].data = &p->base_reachable_time;
if (handler || strategy) {
/* RetransTime */
t->neigh_vars[3].proc_handler = handler;
t->neigh_vars[3].strategy = strategy;
t->neigh_vars[3].extra1 = dev;
+ if (!strategy)
+ t->neigh_vars[3].ctl_name = CTL_UNNUMBERED;
/* ReachableTime */
t->neigh_vars[4].proc_handler = handler;
t->neigh_vars[4].strategy = strategy;
t->neigh_vars[4].extra1 = dev;
+ if (!strategy)
+ t->neigh_vars[4].ctl_name = CTL_UNNUMBERED;
/* RetransTime (in milliseconds)*/
- t->neigh_vars[16].proc_handler = handler;
- t->neigh_vars[16].strategy = strategy;
- t->neigh_vars[16].extra1 = dev;
+ t->neigh_vars[12].proc_handler = handler;
+ t->neigh_vars[12].strategy = strategy;
+ t->neigh_vars[12].extra1 = dev;
+ if (!strategy)
+ t->neigh_vars[12].ctl_name = CTL_UNNUMBERED;
/* ReachableTime (in milliseconds) */
- t->neigh_vars[17].proc_handler = handler;
- t->neigh_vars[17].strategy = strategy;
- t->neigh_vars[17].extra1 = dev;
+ t->neigh_vars[13].proc_handler = handler;
+ t->neigh_vars[13].strategy = strategy;
+ t->neigh_vars[13].extra1 = dev;
+ if (!strategy)
+ t->neigh_vars[13].ctl_name = CTL_UNNUMBERED;
}
dev_name = kstrdup(dev_name_source, GFP_KERNEL);
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 6628e457ddc0..61ead1d11132 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -18,6 +18,8 @@
#include <linux/wireless.h>
#include <net/iw_handler.h>
+#include "net-sysfs.h"
+
#ifdef CONFIG_SYSFS
static const char fmt_hex[] = "%#x\n";
static const char fmt_long_hex[] = "%#lx\n";
diff --git a/net/core/net-sysfs.h b/net/core/net-sysfs.h
new file mode 100644
index 000000000000..f5f108db3924
--- /dev/null
+++ b/net/core/net-sysfs.h
@@ -0,0 +1,8 @@
+#ifndef __NET_SYSFS_H__
+#define __NET_SYSFS_H__
+
+int netdev_kobject_init(void);
+int netdev_register_kobject(struct net_device *);
+void netdev_unregister_kobject(struct net_device *);
+
+#endif
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 6f71db8c4428..383252b50411 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -17,74 +17,13 @@ static DEFINE_MUTEX(net_mutex);
LIST_HEAD(net_namespace_list);
-static struct kmem_cache *net_cachep;
-
struct net init_net;
EXPORT_SYMBOL_GPL(init_net);
-static struct net *net_alloc(void)
-{
- return kmem_cache_zalloc(net_cachep, GFP_KERNEL);
-}
-
-static void net_free(struct net *net)
-{
- if (!net)
- return;
-
- if (unlikely(atomic_read(&net->use_count) != 0)) {
- printk(KERN_EMERG "network namespace not free! Usage: %d\n",
- atomic_read(&net->use_count));
- return;
- }
-
- kmem_cache_free(net_cachep, net);
-}
-
-static void cleanup_net(struct work_struct *work)
-{
- struct pernet_operations *ops;
- struct net *net;
-
- net = container_of(work, struct net, work);
-
- mutex_lock(&net_mutex);
-
- /* Don't let anyone else find us. */
- rtnl_lock();
- list_del(&net->list);
- rtnl_unlock();
-
- /* Run all of the network namespace exit methods */
- list_for_each_entry_reverse(ops, &pernet_list, list) {
- if (ops->exit)
- ops->exit(net);
- }
-
- mutex_unlock(&net_mutex);
-
- /* Ensure there are no outstanding rcu callbacks using this
- * network namespace.
- */
- rcu_barrier();
-
- /* Finally it is safe to free my network namespace structure */
- net_free(net);
-}
-
-
-void __put_net(struct net *net)
-{
- /* Cleanup the network namespace in process context */
- INIT_WORK(&net->work, cleanup_net);
- schedule_work(&net->work);
-}
-EXPORT_SYMBOL_GPL(__put_net);
-
/*
* setup_net runs the initializers for the network namespace object.
*/
-static int setup_net(struct net *net)
+static __net_init int setup_net(struct net *net)
{
/* Must be called with net_mutex held */
struct pernet_operations *ops;
@@ -112,9 +51,33 @@ out_undo:
if (ops->exit)
ops->exit(net);
}
+
+ rcu_barrier();
goto out;
}
+#ifdef CONFIG_NET_NS
+static struct kmem_cache *net_cachep;
+
+static struct net *net_alloc(void)
+{
+ return kmem_cache_zalloc(net_cachep, GFP_KERNEL);
+}
+
+static void net_free(struct net *net)
+{
+ if (!net)
+ return;
+
+ if (unlikely(atomic_read(&net->use_count) != 0)) {
+ printk(KERN_EMERG "network namespace not free! Usage: %d\n",
+ atomic_read(&net->use_count));
+ return;
+ }
+
+ kmem_cache_free(net_cachep, net);
+}
+
struct net *copy_net_ns(unsigned long flags, struct net *old_net)
{
struct net *new_net = NULL;
@@ -125,10 +88,6 @@ struct net *copy_net_ns(unsigned long flags, struct net *old_net)
if (!(flags & CLONE_NEWNET))
return old_net;
-#ifndef CONFIG_NET_NS
- return ERR_PTR(-EINVAL);
-#endif
-
err = -ENOMEM;
new_net = net_alloc();
if (!new_net)
@@ -155,14 +114,64 @@ out:
return new_net;
}
+static void cleanup_net(struct work_struct *work)
+{
+ struct pernet_operations *ops;
+ struct net *net;
+
+ net = container_of(work, struct net, work);
+
+ mutex_lock(&net_mutex);
+
+ /* Don't let anyone else find us. */
+ rtnl_lock();
+ list_del(&net->list);
+ rtnl_unlock();
+
+ /* Run all of the network namespace exit methods */
+ list_for_each_entry_reverse(ops, &pernet_list, list) {
+ if (ops->exit)
+ ops->exit(net);
+ }
+
+ mutex_unlock(&net_mutex);
+
+ /* Ensure there are no outstanding rcu callbacks using this
+ * network namespace.
+ */
+ rcu_barrier();
+
+ /* Finally it is safe to free my network namespace structure */
+ net_free(net);
+}
+
+void __put_net(struct net *net)
+{
+ /* Cleanup the network namespace in process context */
+ INIT_WORK(&net->work, cleanup_net);
+ schedule_work(&net->work);
+}
+EXPORT_SYMBOL_GPL(__put_net);
+
+#else
+struct net *copy_net_ns(unsigned long flags, struct net *old_net)
+{
+ if (flags & CLONE_NEWNET)
+ return ERR_PTR(-EINVAL);
+ return old_net;
+}
+#endif
+
static int __init net_ns_init(void)
{
int err;
printk(KERN_INFO "net_namespace: %zd bytes\n", sizeof(struct net));
+#ifdef CONFIG_NET_NS
net_cachep = kmem_cache_create("net_namespace", sizeof(struct net),
SMP_CACHE_BYTES,
SLAB_PANIC, NULL);
+#endif
mutex_lock(&net_mutex);
err = setup_net(&init_net);
@@ -179,35 +188,35 @@ static int __init net_ns_init(void)
pure_initcall(net_ns_init);
+#ifdef CONFIG_NET_NS
static int register_pernet_operations(struct list_head *list,
struct pernet_operations *ops)
{
struct net *net, *undo_net;
int error;
- error = 0;
list_add_tail(&ops->list, list);
- for_each_net(net) {
- if (ops->init) {
+ if (ops->init) {
+ for_each_net(net) {
error = ops->init(net);
if (error)
goto out_undo;
}
}
-out:
- return error;
+ return 0;
out_undo:
/* If I have an error cleanup all namespaces I initialized */
list_del(&ops->list);
- for_each_net(undo_net) {
- if (undo_net == net)
- goto undone;
- if (ops->exit)
+ if (ops->exit) {
+ for_each_net(undo_net) {
+ if (undo_net == net)
+ goto undone;
ops->exit(undo_net);
+ }
}
undone:
- goto out;
+ return error;
}
static void unregister_pernet_operations(struct pernet_operations *ops)
@@ -215,11 +224,28 @@ static void unregister_pernet_operations(struct pernet_operations *ops)
struct net *net;
list_del(&ops->list);
- for_each_net(net)
- if (ops->exit)
+ if (ops->exit)
+ for_each_net(net)
ops->exit(net);
}
+#else
+
+static int register_pernet_operations(struct list_head *list,
+ struct pernet_operations *ops)
+{
+ if (ops->init == NULL)
+ return 0;
+ return ops->init(&init_net);
+}
+
+static void unregister_pernet_operations(struct pernet_operations *ops)
+{
+ if (ops->exit)
+ ops->exit(&init_net);
+}
+#endif
+
/**
* register_pernet_subsys - register a network namespace subsystem
* @ops: pernet operations structure for the subsystem
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 95daba624967..c499b5c69bed 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -67,7 +67,7 @@ static void queue_process(struct work_struct *work)
local_irq_save(flags);
netif_tx_lock(dev);
if ((netif_queue_stopped(dev) ||
- netif_subqueue_stopped(dev, skb->queue_mapping)) ||
+ netif_subqueue_stopped(dev, skb)) ||
dev->hard_start_xmit(skb, dev) != NETDEV_TX_OK) {
skb_queue_head(&npinfo->txq, skb);
netif_tx_unlock(dev);
@@ -116,6 +116,29 @@ static __sum16 checksum_udp(struct sk_buff *skb, struct udphdr *uh,
* network adapter, forcing superfluous retries and possibly timeouts.
* Thus, we set our budget to greater than 1.
*/
+static int poll_one_napi(struct netpoll_info *npinfo,
+ struct napi_struct *napi, int budget)
+{
+ int work;
+
+ /* net_rx_action's ->poll() invocations and our's are
+ * synchronized by this test which is only made while
+ * holding the napi->poll_lock.
+ */
+ if (!test_bit(NAPI_STATE_SCHED, &napi->state))
+ return budget;
+
+ npinfo->rx_flags |= NETPOLL_RX_DROP;
+ atomic_inc(&trapped);
+
+ work = napi->poll(napi, budget);
+
+ atomic_dec(&trapped);
+ npinfo->rx_flags &= ~NETPOLL_RX_DROP;
+
+ return budget - work;
+}
+
static void poll_napi(struct netpoll *np)
{
struct netpoll_info *npinfo = np->dev->npinfo;
@@ -123,17 +146,13 @@ static void poll_napi(struct netpoll *np)
int budget = 16;
list_for_each_entry(napi, &np->dev->napi_list, dev_list) {
- if (test_bit(NAPI_STATE_SCHED, &napi->state) &&
- napi->poll_owner != smp_processor_id() &&
+ if (napi->poll_owner != smp_processor_id() &&
spin_trylock(&napi->poll_lock)) {
- npinfo->rx_flags |= NETPOLL_RX_DROP;
- atomic_inc(&trapped);
-
- napi->poll(napi, budget);
-
- atomic_dec(&trapped);
- npinfo->rx_flags &= ~NETPOLL_RX_DROP;
+ budget = poll_one_napi(npinfo, napi, budget);
spin_unlock(&napi->poll_lock);
+
+ if (!budget)
+ break;
}
}
}
@@ -269,7 +288,7 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
tries > 0; --tries) {
if (netif_tx_trylock(dev)) {
if (!netif_queue_stopped(dev) &&
- !netif_subqueue_stopped(dev, skb->queue_mapping))
+ !netif_subqueue_stopped(dev, skb))
status = dev->hard_start_xmit(skb, dev);
netif_tx_unlock(dev);
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 2100c734b102..de33f36947e9 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -6,7 +6,7 @@
*
* Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
* Ben Greear <greearb@candelatech.com>
- * Jens Låås <jens.laas@data.slu.se>
+ * Jens Låås <jens.laas@data.slu.se>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -161,7 +161,7 @@
#endif
#include <asm/byteorder.h>
#include <linux/rcupdate.h>
-#include <asm/bitops.h>
+#include <linux/bitops.h>
#include <asm/io.h>
#include <asm/dma.h>
#include <asm/uaccess.h>
@@ -2454,7 +2454,7 @@ static int pktgen_output_ipsec(struct sk_buff *skb, struct pktgen_dev *pkt_dev)
spin_lock(&x->lock);
iph = ip_hdr(skb);
- err = x->mode->output(x, skb);
+ err = x->outer_mode->output(x, skb);
if (err)
goto error;
err = x->type->output(x, skb);
@@ -2603,8 +2603,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
skb->network_header = skb->tail;
skb->transport_header = skb->network_header + sizeof(struct iphdr);
skb_put(skb, sizeof(struct iphdr) + sizeof(struct udphdr));
- skb->queue_mapping = pkt_dev->cur_queue_map;
-
+ skb_set_queue_mapping(skb, pkt_dev->cur_queue_map);
iph = ip_hdr(skb);
udph = udp_hdr(skb);
@@ -2941,8 +2940,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
skb->network_header = skb->tail;
skb->transport_header = skb->network_header + sizeof(struct ipv6hdr);
skb_put(skb, sizeof(struct ipv6hdr) + sizeof(struct udphdr));
- skb->queue_mapping = pkt_dev->cur_queue_map;
-
+ skb_set_queue_mapping(skb, pkt_dev->cur_queue_map);
iph = ipv6_hdr(skb);
udph = udp_hdr(skb);
@@ -3385,7 +3383,7 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev)
if ((netif_queue_stopped(odev) ||
(pkt_dev->skb &&
- netif_subqueue_stopped(odev, pkt_dev->skb->queue_mapping))) ||
+ netif_subqueue_stopped(odev, pkt_dev->skb))) ||
need_resched()) {
idle_start = getCurUs();
@@ -3402,7 +3400,7 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev)
pkt_dev->idle_acc += getCurUs() - idle_start;
if (netif_queue_stopped(odev) ||
- netif_subqueue_stopped(odev, pkt_dev->skb->queue_mapping)) {
+ netif_subqueue_stopped(odev, pkt_dev->skb)) {
pkt_dev->next_tx_us = getCurUs(); /* TODO */
pkt_dev->next_tx_ns = 0;
goto out; /* Try the next interface */
@@ -3431,7 +3429,7 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev)
netif_tx_lock_bh(odev);
if (!netif_queue_stopped(odev) &&
- !netif_subqueue_stopped(odev, pkt_dev->skb->queue_mapping)) {
+ !netif_subqueue_stopped(odev, pkt_dev->skb)) {
atomic_inc(&(pkt_dev->skb->users));
retry_now:
@@ -3514,7 +3512,7 @@ static int pktgen_thread_worker(void *arg)
init_waitqueue_head(&t->queue);
- pr_debug("pktgen: starting pktgen/%d: pid=%d\n", cpu, current->pid);
+ pr_debug("pktgen: starting pktgen/%d: pid=%d\n", cpu, task_pid_nr(current));
set_current_state(TASK_INTERRUPTIBLE);
diff --git a/net/core/request_sock.c b/net/core/request_sock.c
index 5f0818d815e6..45aed75cb571 100644
--- a/net/core/request_sock.c
+++ b/net/core/request_sock.c
@@ -71,6 +71,41 @@ int reqsk_queue_alloc(struct request_sock_queue *queue,
EXPORT_SYMBOL(reqsk_queue_alloc);
+void __reqsk_queue_destroy(struct request_sock_queue *queue)
+{
+ struct listen_sock *lopt;
+ size_t lopt_size;
+
+ /*
+ * this is an error recovery path only
+ * no locking needed and the lopt is not NULL
+ */
+
+ lopt = queue->listen_opt;
+ lopt_size = sizeof(struct listen_sock) +
+ lopt->nr_table_entries * sizeof(struct request_sock *);
+
+ if (lopt_size > PAGE_SIZE)
+ vfree(lopt);
+ else
+ kfree(lopt);
+}
+
+EXPORT_SYMBOL(__reqsk_queue_destroy);
+
+static inline struct listen_sock *reqsk_queue_yank_listen_sk(
+ struct request_sock_queue *queue)
+{
+ struct listen_sock *lopt;
+
+ write_lock_bh(&queue->syn_wait_lock);
+ lopt = queue->listen_opt;
+ queue->listen_opt = NULL;
+ write_unlock_bh(&queue->syn_wait_lock);
+
+ return lopt;
+}
+
void reqsk_queue_destroy(struct request_sock_queue *queue)
{
/* make all the listen_opt local to us */
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 1072d16696c3..e1ba26fb4bf2 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -742,12 +742,12 @@ static struct net *get_net_ns_by_pid(pid_t pid)
/* Lookup the network namespace */
net = ERR_PTR(-ESRCH);
rcu_read_lock();
- tsk = find_task_by_pid(pid);
+ tsk = find_task_by_vpid(pid);
if (tsk) {
- task_lock(tsk);
- if (tsk->nsproxy)
- net = get_net(tsk->nsproxy->net_ns);
- task_unlock(tsk);
+ struct nsproxy *nsproxy;
+ nsproxy = task_nsproxy(tsk);
+ if (nsproxy)
+ net = get_net(nsproxy->net_ns);
}
rcu_read_unlock();
return net;
diff --git a/net/core/scm.c b/net/core/scm.c
index 530bee8d9ed9..100ba6d9d478 100644
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -24,6 +24,8 @@
#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/security.h>
+#include <linux/pid.h>
+#include <linux/nsproxy.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -42,7 +44,7 @@
static __inline__ int scm_check_creds(struct ucred *creds)
{
- if ((creds->pid == current->tgid || capable(CAP_SYS_ADMIN)) &&
+ if ((creds->pid == task_tgid_vnr(current) || capable(CAP_SYS_ADMIN)) &&
((creds->uid == current->uid || creds->uid == current->euid ||
creds->uid == current->suid) || capable(CAP_SETUID)) &&
((creds->gid == current->gid || creds->gid == current->egid ||
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 944189d96323..32d5826b7177 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -362,6 +362,90 @@ void kfree_skb(struct sk_buff *skb)
__kfree_skb(skb);
}
+static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
+{
+ new->tstamp = old->tstamp;
+ new->dev = old->dev;
+ new->transport_header = old->transport_header;
+ new->network_header = old->network_header;
+ new->mac_header = old->mac_header;
+ new->dst = dst_clone(old->dst);
+#ifdef CONFIG_INET
+ new->sp = secpath_get(old->sp);
+#endif
+ memcpy(new->cb, old->cb, sizeof(old->cb));
+ new->csum_start = old->csum_start;
+ new->csum_offset = old->csum_offset;
+ new->local_df = old->local_df;
+ new->pkt_type = old->pkt_type;
+ new->ip_summed = old->ip_summed;
+ skb_copy_queue_mapping(new, old);
+ new->priority = old->priority;
+#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
+ new->ipvs_property = old->ipvs_property;
+#endif
+ new->protocol = old->protocol;
+ new->mark = old->mark;
+ __nf_copy(new, old);
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+ defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+ new->nf_trace = old->nf_trace;
+#endif
+#ifdef CONFIG_NET_SCHED
+ new->tc_index = old->tc_index;
+#ifdef CONFIG_NET_CLS_ACT
+ new->tc_verd = old->tc_verd;
+#endif
+#endif
+ skb_copy_secmark(new, old);
+}
+
+static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
+{
+#define C(x) n->x = skb->x
+
+ n->next = n->prev = NULL;
+ n->sk = NULL;
+ __copy_skb_header(n, skb);
+
+ C(len);
+ C(data_len);
+ C(mac_len);
+ n->cloned = 1;
+ n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len;
+ n->nohdr = 0;
+ n->destructor = NULL;
+ C(truesize);
+ atomic_set(&n->users, 1);
+ C(head);
+ C(data);
+ C(tail);
+ C(end);
+
+ atomic_inc(&(skb_shinfo(skb)->dataref));
+ skb->cloned = 1;
+
+ return n;
+#undef C
+}
+
+/**
+ * skb_morph - morph one skb into another
+ * @dst: the skb to receive the contents
+ * @src: the skb to supply the contents
+ *
+ * This is identical to skb_clone except that the target skb is
+ * supplied by the user.
+ *
+ * The target skb is returned upon exit.
+ */
+struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src)
+{
+ skb_release_data(dst);
+ return __skb_clone(dst, src);
+}
+EXPORT_SYMBOL_GPL(skb_morph);
+
/**
* skb_clone - duplicate an sk_buff
* @skb: buffer to clone
@@ -393,66 +477,7 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
n->fclone = SKB_FCLONE_UNAVAILABLE;
}
-#define C(x) n->x = skb->x
-
- n->next = n->prev = NULL;
- n->sk = NULL;
- C(tstamp);
- C(dev);
- C(transport_header);
- C(network_header);
- C(mac_header);
- C(dst);
- dst_clone(skb->dst);
- C(sp);
-#ifdef CONFIG_INET
- secpath_get(skb->sp);
-#endif
- memcpy(n->cb, skb->cb, sizeof(skb->cb));
- C(len);
- C(data_len);
- C(mac_len);
- C(csum);
- C(local_df);
- n->cloned = 1;
- n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len;
- n->nohdr = 0;
- C(pkt_type);
- C(ip_summed);
- skb_copy_queue_mapping(n, skb);
- C(priority);
-#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
- C(ipvs_property);
-#endif
- C(protocol);
- n->destructor = NULL;
- C(mark);
- __nf_copy(n, skb);
-#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
- defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
- C(nf_trace);
-#endif
-#ifdef CONFIG_NET_SCHED
- C(tc_index);
-#ifdef CONFIG_NET_CLS_ACT
- n->tc_verd = SET_TC_VERD(skb->tc_verd,0);
- n->tc_verd = CLR_TC_OK2MUNGE(n->tc_verd);
- n->tc_verd = CLR_TC_MUNGED(n->tc_verd);
- C(iif);
-#endif
-#endif
- skb_copy_secmark(n, skb);
- C(truesize);
- atomic_set(&n->users, 1);
- C(head);
- C(data);
- C(tail);
- C(end);
-
- atomic_inc(&(skb_shinfo(skb)->dataref));
- skb->cloned = 1;
-
- return n;
+ return __skb_clone(n, skb);
}
static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
@@ -463,50 +488,15 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
*/
unsigned long offset = new->data - old->data;
#endif
- new->sk = NULL;
- new->dev = old->dev;
- skb_copy_queue_mapping(new, old);
- new->priority = old->priority;
- new->protocol = old->protocol;
- new->dst = dst_clone(old->dst);
-#ifdef CONFIG_INET
- new->sp = secpath_get(old->sp);
-#endif
- new->csum_start = old->csum_start;
- new->csum_offset = old->csum_offset;
- new->ip_summed = old->ip_summed;
- new->transport_header = old->transport_header;
- new->network_header = old->network_header;
- new->mac_header = old->mac_header;
+
+ __copy_skb_header(new, old);
+
#ifndef NET_SKBUFF_DATA_USES_OFFSET
/* {transport,network,mac}_header are relative to skb->head */
new->transport_header += offset;
new->network_header += offset;
new->mac_header += offset;
#endif
- memcpy(new->cb, old->cb, sizeof(old->cb));
- new->local_df = old->local_df;
- new->fclone = SKB_FCLONE_UNAVAILABLE;
- new->pkt_type = old->pkt_type;
- new->tstamp = old->tstamp;
- new->destructor = NULL;
- new->mark = old->mark;
- __nf_copy(new, old);
-#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
- defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
- new->nf_trace = old->nf_trace;
-#endif
-#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
- new->ipvs_property = old->ipvs_property;
-#endif
-#ifdef CONFIG_NET_SCHED
-#ifdef CONFIG_NET_CLS_ACT
- new->tc_verd = old->tc_verd;
-#endif
- new->tc_index = old->tc_index;
-#endif
- skb_copy_secmark(new, old);
- atomic_set(&new->users, 1);
skb_shinfo(new)->gso_size = skb_shinfo(old)->gso_size;
skb_shinfo(new)->gso_segs = skb_shinfo(old)->gso_segs;
skb_shinfo(new)->gso_type = skb_shinfo(old)->gso_type;
@@ -685,7 +675,7 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
skb->transport_header += off;
skb->network_header += off;
skb->mac_header += off;
- skb->csum_start += off;
+ skb->csum_start += nhead;
skb->cloned = 0;
skb->hdr_len = 0;
skb->nohdr = 0;
@@ -2038,8 +2028,8 @@ void __init skb_init(void)
* Fill the specified scatter-gather list with mappings/pointers into a
* region of the buffer space attached to a socket buffer.
*/
-int
-skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
+static int
+__skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
{
int start = skb_headlen(skb);
int i, copy = start - offset;
@@ -2048,9 +2038,7 @@ skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
if (copy > 0) {
if (copy > len)
copy = len;
- sg[elt].page = virt_to_page(skb->data + offset);
- sg[elt].offset = (unsigned long)(skb->data + offset) % PAGE_SIZE;
- sg[elt].length = copy;
+ sg_set_buf(sg, skb->data + offset, copy);
elt++;
if ((len -= copy) == 0)
return elt;
@@ -2068,9 +2056,8 @@ skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
if (copy > len)
copy = len;
- sg[elt].page = frag->page;
- sg[elt].offset = frag->page_offset+offset-start;
- sg[elt].length = copy;
+ sg_set_page(&sg[elt], frag->page, copy,
+ frag->page_offset+offset-start);
elt++;
if (!(len -= copy))
return elt;
@@ -2091,7 +2078,8 @@ skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
if ((copy = end - offset) > 0) {
if (copy > len)
copy = len;
- elt += skb_to_sgvec(list, sg+elt, offset - start, copy);
+ elt += __skb_to_sgvec(list, sg+elt, offset - start,
+ copy);
if ((len -= copy) == 0)
return elt;
offset += copy;
@@ -2103,6 +2091,15 @@ skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
return elt;
}
+int skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
+{
+ int nsg = __skb_to_sgvec(skb, sg, offset, len);
+
+ sg_mark_end(&sg[nsg - 1]);
+
+ return nsg;
+}
+
/**
* skb_cow_data - Check that a socket buffer's data buffers are writable
* @skb: The socket buffer to check.
diff --git a/net/core/sock.c b/net/core/sock.c
index d45ecdccc6a1..c519b439b8b1 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -232,7 +232,7 @@ static int sock_set_timeout(long *timeo_p, char __user *optval, int optlen)
warned++;
printk(KERN_INFO "sock_set_timeout: `%s' (pid %d) "
"tries to set negative timeout\n",
- current->comm, current->pid);
+ current->comm, task_pid_nr(current));
return 0;
}
*timeo_p = MAX_SCHEDULE_TIMEOUT;
@@ -428,7 +428,6 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
char __user *optval, int optlen)
{
struct sock *sk=sock->sk;
- struct sk_filter *filter;
int val;
int valbool;
struct linger ling;
@@ -652,16 +651,7 @@ set_rcvbuf:
break;
case SO_DETACH_FILTER:
- rcu_read_lock_bh();
- filter = rcu_dereference(sk->sk_filter);
- if (filter) {
- rcu_assign_pointer(sk->sk_filter, NULL);
- sk_filter_release(sk, filter);
- rcu_read_unlock_bh();
- break;
- }
- rcu_read_unlock_bh();
- ret = -ENONET;
+ ret = sk_detach_filter(sk);
break;
case SO_PASSSEC:
@@ -867,46 +857,43 @@ static inline void sock_lock_init(struct sock *sk)
af_family_keys + sk->sk_family);
}
-/**
- * sk_alloc - All socket objects are allocated here
- * @net: the applicable net namespace
- * @family: protocol family
- * @priority: for allocation (%GFP_KERNEL, %GFP_ATOMIC, etc)
- * @prot: struct proto associated with this new sock instance
- * @zero_it: if we should zero the newly allocated sock
- */
-struct sock *sk_alloc(struct net *net, int family, gfp_t priority,
- struct proto *prot, int zero_it)
+static void sock_copy(struct sock *nsk, const struct sock *osk)
{
- struct sock *sk = NULL;
- struct kmem_cache *slab = prot->slab;
+#ifdef CONFIG_SECURITY_NETWORK
+ void *sptr = nsk->sk_security;
+#endif
+
+ memcpy(nsk, osk, osk->sk_prot->obj_size);
+#ifdef CONFIG_SECURITY_NETWORK
+ nsk->sk_security = sptr;
+ security_sk_clone(osk, nsk);
+#endif
+}
+
+static struct sock *sk_prot_alloc(struct proto *prot, gfp_t priority,
+ int family)
+{
+ struct sock *sk;
+ struct kmem_cache *slab;
+ slab = prot->slab;
if (slab != NULL)
sk = kmem_cache_alloc(slab, priority);
else
sk = kmalloc(prot->obj_size, priority);
- if (sk) {
- if (zero_it) {
- memset(sk, 0, prot->obj_size);
- sk->sk_family = family;
- /*
- * See comment in struct sock definition to understand
- * why we need sk_prot_creator -acme
- */
- sk->sk_prot = sk->sk_prot_creator = prot;
- sock_lock_init(sk);
- sk->sk_net = get_net(net);
- }
-
+ if (sk != NULL) {
if (security_sk_alloc(sk, family, priority))
goto out_free;
if (!try_module_get(prot->owner))
- goto out_free;
+ goto out_free_sec;
}
+
return sk;
+out_free_sec:
+ security_sk_free(sk);
out_free:
if (slab != NULL)
kmem_cache_free(slab, sk);
@@ -915,17 +902,60 @@ out_free:
return NULL;
}
+static void sk_prot_free(struct proto *prot, struct sock *sk)
+{
+ struct kmem_cache *slab;
+ struct module *owner;
+
+ owner = prot->owner;
+ slab = prot->slab;
+
+ security_sk_free(sk);
+ if (slab != NULL)
+ kmem_cache_free(slab, sk);
+ else
+ kfree(sk);
+ module_put(owner);
+}
+
+/**
+ * sk_alloc - All socket objects are allocated here
+ * @net: the applicable net namespace
+ * @family: protocol family
+ * @priority: for allocation (%GFP_KERNEL, %GFP_ATOMIC, etc)
+ * @prot: struct proto associated with this new sock instance
+ * @zero_it: if we should zero the newly allocated sock
+ */
+struct sock *sk_alloc(struct net *net, int family, gfp_t priority,
+ struct proto *prot)
+{
+ struct sock *sk;
+
+ sk = sk_prot_alloc(prot, priority | __GFP_ZERO, family);
+ if (sk) {
+ sk->sk_family = family;
+ /*
+ * See comment in struct sock definition to understand
+ * why we need sk_prot_creator -acme
+ */
+ sk->sk_prot = sk->sk_prot_creator = prot;
+ sock_lock_init(sk);
+ sk->sk_net = get_net(net);
+ }
+
+ return sk;
+}
+
void sk_free(struct sock *sk)
{
struct sk_filter *filter;
- struct module *owner = sk->sk_prot_creator->owner;
if (sk->sk_destruct)
sk->sk_destruct(sk);
filter = rcu_dereference(sk->sk_filter);
if (filter) {
- sk_filter_release(sk, filter);
+ sk_filter_uncharge(sk, filter);
rcu_assign_pointer(sk->sk_filter, NULL);
}
@@ -935,25 +965,22 @@ void sk_free(struct sock *sk)
printk(KERN_DEBUG "%s: optmem leakage (%d bytes) detected.\n",
__FUNCTION__, atomic_read(&sk->sk_omem_alloc));
- security_sk_free(sk);
put_net(sk->sk_net);
- if (sk->sk_prot_creator->slab != NULL)
- kmem_cache_free(sk->sk_prot_creator->slab, sk);
- else
- kfree(sk);
- module_put(owner);
+ sk_prot_free(sk->sk_prot_creator, sk);
}
struct sock *sk_clone(const struct sock *sk, const gfp_t priority)
{
- struct sock *newsk = sk_alloc(sk->sk_net, sk->sk_family, priority, sk->sk_prot, 0);
+ struct sock *newsk;
+ newsk = sk_prot_alloc(sk->sk_prot, priority, sk->sk_family);
if (newsk != NULL) {
struct sk_filter *filter;
sock_copy(newsk, sk);
/* SANITY */
+ get_net(newsk->sk_net);
sk_node_init(&newsk->sk_node);
sock_lock_init(newsk);
bh_lock_sock(newsk);
@@ -1659,7 +1686,6 @@ void sock_enable_timestamp(struct sock *sk)
net_enable_timestamp();
}
}
-EXPORT_SYMBOL(sock_enable_timestamp);
/*
* Get a socket option on an socket.
@@ -1775,11 +1801,65 @@ EXPORT_SYMBOL(sk_common_release);
static DEFINE_RWLOCK(proto_list_lock);
static LIST_HEAD(proto_list);
+#ifdef CONFIG_SMP
+/*
+ * Define default functions to keep track of inuse sockets per protocol
+ * Note that often used protocols use dedicated functions to get a speed increase.
+ * (see DEFINE_PROTO_INUSE/REF_PROTO_INUSE)
+ */
+static void inuse_add(struct proto *prot, int inc)
+{
+ per_cpu_ptr(prot->inuse_ptr, smp_processor_id())[0] += inc;
+}
+
+static int inuse_get(const struct proto *prot)
+{
+ int res = 0, cpu;
+ for_each_possible_cpu(cpu)
+ res += per_cpu_ptr(prot->inuse_ptr, cpu)[0];
+ return res;
+}
+
+static int inuse_init(struct proto *prot)
+{
+ if (!prot->inuse_getval || !prot->inuse_add) {
+ prot->inuse_ptr = alloc_percpu(int);
+ if (prot->inuse_ptr == NULL)
+ return -ENOBUFS;
+
+ prot->inuse_getval = inuse_get;
+ prot->inuse_add = inuse_add;
+ }
+ return 0;
+}
+
+static void inuse_fini(struct proto *prot)
+{
+ if (prot->inuse_ptr != NULL) {
+ free_percpu(prot->inuse_ptr);
+ prot->inuse_ptr = NULL;
+ prot->inuse_getval = NULL;
+ prot->inuse_add = NULL;
+ }
+}
+#else
+static inline int inuse_init(struct proto *prot)
+{
+ return 0;
+}
+
+static inline void inuse_fini(struct proto *prot)
+{
+}
+#endif
+
int proto_register(struct proto *prot, int alloc_slab)
{
char *request_sock_slab_name = NULL;
char *timewait_sock_slab_name;
- int rc = -ENOBUFS;
+
+ if (inuse_init(prot))
+ goto out;
if (alloc_slab) {
prot->slab = kmem_cache_create(prot->name, prot->obj_size, 0,
@@ -1788,7 +1868,7 @@ int proto_register(struct proto *prot, int alloc_slab)
if (prot->slab == NULL) {
printk(KERN_CRIT "%s: Can't create sock SLAB cache!\n",
prot->name);
- goto out;
+ goto out_free_inuse;
}
if (prot->rsk_prot != NULL) {
@@ -1832,9 +1912,8 @@ int proto_register(struct proto *prot, int alloc_slab)
write_lock(&proto_list_lock);
list_add(&prot->node, &proto_list);
write_unlock(&proto_list_lock);
- rc = 0;
-out:
- return rc;
+ return 0;
+
out_free_timewait_sock_slab_name:
kfree(timewait_sock_slab_name);
out_free_request_sock_slab:
@@ -1847,7 +1926,10 @@ out_free_request_sock_slab_name:
out_free_sock_slab:
kmem_cache_destroy(prot->slab);
prot->slab = NULL;
- goto out;
+out_free_inuse:
+ inuse_fini(prot);
+out:
+ return -ENOBUFS;
}
EXPORT_SYMBOL(proto_register);
@@ -1858,6 +1940,7 @@ void proto_unregister(struct proto *prot)
list_del(&prot->node);
write_unlock(&proto_list_lock);
+ inuse_fini(prot);
if (prot->slab != NULL) {
kmem_cache_destroy(prot->slab);
prot->slab = NULL;
@@ -2014,7 +2097,3 @@ EXPORT_SYMBOL(sock_wmalloc);
EXPORT_SYMBOL(sock_i_uid);
EXPORT_SYMBOL(sock_i_ino);
EXPORT_SYMBOL(sysctl_optmem_max);
-#ifdef CONFIG_SYSCTL
-EXPORT_SYMBOL(sysctl_rmem_max);
-EXPORT_SYMBOL(sysctl_wmem_max);
-#endif
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
index 6d5ea9762040..113cc728dc31 100644
--- a/net/core/sysctl_net_core.c
+++ b/net/core/sysctl_net_core.c
@@ -9,25 +9,12 @@
#include <linux/sysctl.h>
#include <linux/module.h>
#include <linux/socket.h>
+#include <linux/netdevice.h>
#include <net/sock.h>
+#include <net/xfrm.h>
#ifdef CONFIG_SYSCTL
-extern int netdev_max_backlog;
-extern int weight_p;
-
-extern __u32 sysctl_wmem_max;
-extern __u32 sysctl_rmem_max;
-
-extern int sysctl_core_destroy_delay;
-
-#ifdef CONFIG_XFRM
-extern u32 sysctl_xfrm_aevent_etime;
-extern u32 sysctl_xfrm_aevent_rseqth;
-extern int sysctl_xfrm_larval_drop;
-extern u32 sysctl_xfrm_acq_expires;
-#endif
-
ctl_table core_table[] = {
#ifdef CONFIG_NET
{
diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c
index 426008e3b7e3..d694656b8800 100644
--- a/net/dccp/ccids/ccid2.c
+++ b/net/dccp/ccids/ccid2.c
@@ -750,20 +750,16 @@ static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
*/
hctx->ccid2hctx_ssthresh = ~0;
hctx->ccid2hctx_numdupack = 3;
- hctx->ccid2hctx_seqbufc = 0;
/* XXX init ~ to window size... */
if (ccid2_hc_tx_alloc_seq(hctx))
return -ENOMEM;
- hctx->ccid2hctx_sent = 0;
hctx->ccid2hctx_rto = 3 * HZ;
ccid2_change_srtt(hctx, -1);
hctx->ccid2hctx_rttvar = -1;
- hctx->ccid2hctx_lastrtt = 0;
hctx->ccid2hctx_rpdupack = -1;
hctx->ccid2hctx_last_cong = jiffies;
- hctx->ccid2hctx_high_ack = 0;
hctx->ccid2hctx_rtotimer.function = &ccid2_hc_tx_rto_expire;
hctx->ccid2hctx_rtotimer.data = (unsigned long)sk;
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index 25772c326172..19b33586333d 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -40,6 +40,8 @@
#include "lib/tfrc.h"
#include "ccid3.h"
+#include <asm/unaligned.h>
+
#ifdef CONFIG_IP_DCCP_CCID3_DEBUG
static int ccid3_debug;
#define ccid3_pr_debug(format, a...) DCCP_PR_DEBUG(ccid3_debug, format, ##a)
@@ -544,6 +546,7 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
const struct dccp_sock *dp = dccp_sk(sk);
struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
struct ccid3_options_received *opt_recv;
+ __be32 opt_val;
opt_recv = &hctx->ccid3hctx_options_received;
@@ -563,8 +566,8 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
dccp_role(sk), sk, len);
rc = -EINVAL;
} else {
- opt_recv->ccid3or_loss_event_rate =
- ntohl(*(__be32 *)value);
+ opt_val = get_unaligned((__be32 *)value);
+ opt_recv->ccid3or_loss_event_rate = ntohl(opt_val);
ccid3_pr_debug("%s(%p), LOSS_EVENT_RATE=%u\n",
dccp_role(sk), sk,
opt_recv->ccid3or_loss_event_rate);
@@ -585,8 +588,8 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
dccp_role(sk), sk, len);
rc = -EINVAL;
} else {
- opt_recv->ccid3or_receive_rate =
- ntohl(*(__be32 *)value);
+ opt_val = get_unaligned((__be32 *)value);
+ opt_recv->ccid3or_receive_rate = ntohl(opt_val);
ccid3_pr_debug("%s(%p), RECEIVE_RATE=%u\n",
dccp_role(sk), sk,
opt_recv->ccid3or_receive_rate);
@@ -601,8 +604,6 @@ static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk)
{
struct ccid3_hc_tx_sock *hctx = ccid_priv(ccid);
- hctx->ccid3hctx_s = 0;
- hctx->ccid3hctx_rtt = 0;
hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT;
INIT_LIST_HEAD(&hctx->ccid3hctx_hist);
@@ -963,8 +964,6 @@ static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk)
INIT_LIST_HEAD(&hcrx->ccid3hcrx_li_hist);
hcrx->ccid3hcrx_tstamp_last_feedback =
hcrx->ccid3hcrx_tstamp_last_ack = ktime_get_real();
- hcrx->ccid3hcrx_s = 0;
- hcrx->ccid3hcrx_rtt = 0;
return 0;
}
diff --git a/net/dccp/diag.c b/net/dccp/diag.c
index 0f3745585a94..d8a3509b26f6 100644
--- a/net/dccp/diag.c
+++ b/net/dccp/diag.c
@@ -68,3 +68,4 @@ module_exit(dccp_diag_fini);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Arnaldo Carvalho de Melo <acme@mandriva.com>");
MODULE_DESCRIPTION("DCCP inet_diag handler");
+MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_INET_DIAG, DCCPDIAG_GETSOCK);
diff --git a/net/dccp/input.c b/net/dccp/input.c
index 19d7e1dbd87e..1ce101062824 100644
--- a/net/dccp/input.c
+++ b/net/dccp/input.c
@@ -19,6 +19,9 @@
#include "ccid.h"
#include "dccp.h"
+/* rate-limit for syncs in reply to sequence-invalid packets; RFC 4340, 7.5.4 */
+int sysctl_dccp_sync_ratelimit __read_mostly = HZ / 8;
+
static void dccp_fin(struct sock *sk, struct sk_buff *skb)
{
sk->sk_shutdown |= RCV_SHUTDOWN;
@@ -55,6 +58,42 @@ static void dccp_rcv_closereq(struct sock *sk, struct sk_buff *skb)
dccp_send_close(sk, 0);
}
+static u8 dccp_reset_code_convert(const u8 code)
+{
+ const u8 error_code[] = {
+ [DCCP_RESET_CODE_CLOSED] = 0, /* normal termination */
+ [DCCP_RESET_CODE_UNSPECIFIED] = 0, /* nothing known */
+ [DCCP_RESET_CODE_ABORTED] = ECONNRESET,
+
+ [DCCP_RESET_CODE_NO_CONNECTION] = ECONNREFUSED,
+ [DCCP_RESET_CODE_CONNECTION_REFUSED] = ECONNREFUSED,
+ [DCCP_RESET_CODE_TOO_BUSY] = EUSERS,
+ [DCCP_RESET_CODE_AGGRESSION_PENALTY] = EDQUOT,
+
+ [DCCP_RESET_CODE_PACKET_ERROR] = ENOMSG,
+ [DCCP_RESET_CODE_BAD_INIT_COOKIE] = EBADR,
+ [DCCP_RESET_CODE_BAD_SERVICE_CODE] = EBADRQC,
+ [DCCP_RESET_CODE_OPTION_ERROR] = EILSEQ,
+ [DCCP_RESET_CODE_MANDATORY_ERROR] = EOPNOTSUPP,
+ };
+
+ return code >= DCCP_MAX_RESET_CODES ? 0 : error_code[code];
+}
+
+static void dccp_rcv_reset(struct sock *sk, struct sk_buff *skb)
+{
+ u8 err = dccp_reset_code_convert(dccp_hdr_reset(skb)->dccph_reset_code);
+
+ sk->sk_err = err;
+
+ /* Queue the equivalent of TCP fin so that dccp_recvmsg exits the loop */
+ dccp_fin(sk, skb);
+
+ if (err && !sock_flag(sk, SOCK_DEAD))
+ sk_wake_async(sk, 0, POLL_ERR);
+ dccp_time_wait(sk, DCCP_TIME_WAIT, 0);
+}
+
static void dccp_event_ack_recv(struct sock *sk, struct sk_buff *skb)
{
struct dccp_sock *dp = dccp_sk(sk);
@@ -188,9 +227,8 @@ static int __dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
* S.state := TIMEWAIT
* Set TIMEWAIT timer
* Drop packet and return
- */
- dccp_fin(sk, skb);
- dccp_time_wait(sk, DCCP_TIME_WAIT, 0);
+ */
+ dccp_rcv_reset(sk, skb);
return 0;
case DCCP_PKT_CLOSEREQ:
dccp_rcv_closereq(sk, skb);
@@ -518,12 +556,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
* Drop packet and return
*/
if (dh->dccph_type == DCCP_PKT_RESET) {
- /*
- * Queue the equivalent of TCP fin so that dccp_recvmsg
- * exits the loop
- */
- dccp_fin(sk, skb);
- dccp_time_wait(sk, DCCP_TIME_WAIT, 0);
+ dccp_rcv_reset(sk, skb);
return 0;
/*
* Step 7: Check for unexpected packet types
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 44f6e17e105f..db17b83e8d3e 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -241,8 +241,8 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
goto out;
dp = dccp_sk(sk);
- seq = dccp_hdr_seq(skb);
- if (sk->sk_state != DCCP_LISTEN &&
+ seq = dccp_hdr_seq(dh);
+ if ((1 << sk->sk_state) & ~(DCCPF_REQUESTING | DCCPF_LISTEN) &&
!between48(seq, dp->dccps_swl, dp->dccps_swh)) {
NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS);
goto out;
@@ -795,7 +795,7 @@ static int dccp_v4_rcv(struct sk_buff *skb)
dh = dccp_hdr(skb);
- DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(skb);
+ DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(dh);
DCCP_SKB_CB(skb)->dccpd_type = dh->dccph_type;
dccp_pr_debug("%8.8s "
@@ -922,6 +922,8 @@ static struct timewait_sock_ops dccp_timewait_sock_ops = {
.twsk_obj_size = sizeof(struct inet_timewait_sock),
};
+DEFINE_PROTO_INUSE(dccp_v4)
+
static struct proto dccp_v4_prot = {
.name = "DCCP",
.owner = THIS_MODULE,
@@ -950,6 +952,7 @@ static struct proto dccp_v4_prot = {
.compat_setsockopt = compat_dccp_setsockopt,
.compat_getsockopt = compat_dccp_getsockopt,
#endif
+ REF_PROTO_INUSE(dccp_v4)
};
static struct net_protocol dccp_v4_protocol = {
@@ -1037,8 +1040,8 @@ module_exit(dccp_v4_exit);
* values directly, Also cover the case where the protocol is not specified,
* i.e. net-pf-PF_INET-proto-0-type-SOCK_DCCP
*/
-MODULE_ALIAS("net-pf-" __stringify(PF_INET) "-proto-33-type-6");
-MODULE_ALIAS("net-pf-" __stringify(PF_INET) "-proto-0-type-6");
+MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 33, 6);
+MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 0, 6);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Arnaldo Carvalho de Melo <acme@mandriva.com>");
MODULE_DESCRIPTION("DCCP - Datagram Congestion Controlled Protocol");
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 006a3834fbcd..87c98fb86fa8 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -173,7 +173,7 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
icmpv6_err_convert(type, code, &err);
- seq = DCCP_SKB_CB(skb)->dccpd_seq;
+ seq = dccp_hdr_seq(dh);
/* Might be for an request_sock */
switch (sk->sk_state) {
struct request_sock *req, **prev;
@@ -767,10 +767,9 @@ discard:
return 0;
}
-static int dccp_v6_rcv(struct sk_buff **pskb)
+static int dccp_v6_rcv(struct sk_buff *skb)
{
const struct dccp_hdr *dh;
- struct sk_buff *skb = *pskb;
struct sock *sk;
int min_cov;
@@ -788,7 +787,7 @@ static int dccp_v6_rcv(struct sk_buff **pskb)
dh = dccp_hdr(skb);
- DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(skb);
+ DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(dh);
DCCP_SKB_CB(skb)->dccpd_type = dh->dccph_type;
if (dccp_packet_without_ack(skb))
@@ -1108,6 +1107,8 @@ static struct timewait_sock_ops dccp6_timewait_sock_ops = {
.twsk_obj_size = sizeof(struct dccp6_timewait_sock),
};
+DEFINE_PROTO_INUSE(dccp_v6)
+
static struct proto dccp_v6_prot = {
.name = "DCCPv6",
.owner = THIS_MODULE,
@@ -1136,6 +1137,7 @@ static struct proto dccp_v6_prot = {
.compat_setsockopt = compat_dccp_setsockopt,
.compat_getsockopt = compat_dccp_getsockopt,
#endif
+ REF_PROTO_INUSE(dccp_v6)
};
static struct inet6_protocol dccp_v6_protocol = {
@@ -1220,8 +1222,8 @@ module_exit(dccp_v6_exit);
* values directly, Also cover the case where the protocol is not specified,
* i.e. net-pf-PF_INET6-proto-0-type-SOCK_DCCP
*/
-MODULE_ALIAS("net-pf-" __stringify(PF_INET6) "-proto-33-type-6");
-MODULE_ALIAS("net-pf-" __stringify(PF_INET6) "-proto-0-type-6");
+MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET6, 33, 6);
+MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET6, 0, 6);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Arnaldo Carvalho de Melo <acme@mandriva.com>");
MODULE_DESCRIPTION("DCCPv6 - Datagram Congestion Controlled Protocol");
diff --git a/net/dccp/options.c b/net/dccp/options.c
index d361b5533309..d286cffe2c49 100644
--- a/net/dccp/options.c
+++ b/net/dccp/options.c
@@ -14,6 +14,7 @@
#include <linux/dccp.h>
#include <linux/module.h>
#include <linux/types.h>
+#include <asm/unaligned.h>
#include <linux/kernel.h>
#include <linux/skbuff.h>
@@ -59,6 +60,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
unsigned char opt, len;
unsigned char *value;
u32 elapsed_time;
+ __be32 opt_val;
int rc;
int mandatory = 0;
@@ -145,7 +147,8 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
if (len != 4)
goto out_invalid_option;
- opt_recv->dccpor_timestamp = ntohl(*(__be32 *)value);
+ opt_val = get_unaligned((__be32 *)value);
+ opt_recv->dccpor_timestamp = ntohl(opt_val);
dp->dccps_timestamp_echo = opt_recv->dccpor_timestamp;
dp->dccps_timestamp_time = ktime_get_real();
@@ -159,7 +162,8 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
if (len != 4 && len != 6 && len != 8)
goto out_invalid_option;
- opt_recv->dccpor_timestamp_echo = ntohl(*(__be32 *)value);
+ opt_val = get_unaligned((__be32 *)value);
+ opt_recv->dccpor_timestamp_echo = ntohl(opt_val);
dccp_pr_debug("%s rx opt: TIMESTAMP_ECHO=%u, len=%d, "
"ackno=%llu", dccp_role(sk),
@@ -168,16 +172,20 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
(unsigned long long)
DCCP_SKB_CB(skb)->dccpd_ack_seq);
+ value += 4;
- if (len == 4) {
+ if (len == 4) { /* no elapsed time included */
dccp_pr_debug_cat("\n");
break;
}
- if (len == 6)
- elapsed_time = ntohs(*(__be16 *)(value + 4));
- else
- elapsed_time = ntohl(*(__be32 *)(value + 4));
+ if (len == 6) { /* 2-byte elapsed time */
+ __be16 opt_val2 = get_unaligned((__be16 *)value);
+ elapsed_time = ntohs(opt_val2);
+ } else { /* 4-byte elapsed time */
+ opt_val = get_unaligned((__be32 *)value);
+ elapsed_time = ntohl(opt_val);
+ }
dccp_pr_debug_cat(", ELAPSED_TIME=%u\n", elapsed_time);
@@ -192,10 +200,13 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
if (pkt_type == DCCP_PKT_DATA)
continue;
- if (len == 2)
- elapsed_time = ntohs(*(__be16 *)value);
- else
- elapsed_time = ntohl(*(__be32 *)value);
+ if (len == 2) {
+ __be16 opt_val2 = get_unaligned((__be16 *)value);
+ elapsed_time = ntohs(opt_val2);
+ } else {
+ opt_val = get_unaligned((__be32 *)value);
+ elapsed_time = ntohl(opt_val);
+ }
if (elapsed_time > opt_recv->dccpor_elapsed_time)
opt_recv->dccpor_elapsed_time = elapsed_time;
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index cc9bf1cb2646..7a3bea9c28c1 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -26,6 +26,7 @@
#include <net/sock.h>
#include <net/xfrm.h>
+#include <asm/ioctls.h>
#include <asm/semaphore.h>
#include <linux/spinlock.h>
#include <linux/timer.h>
@@ -378,8 +379,36 @@ EXPORT_SYMBOL_GPL(dccp_poll);
int dccp_ioctl(struct sock *sk, int cmd, unsigned long arg)
{
- dccp_pr_debug("entry\n");
- return -ENOIOCTLCMD;
+ int rc = -ENOTCONN;
+
+ lock_sock(sk);
+
+ if (sk->sk_state == DCCP_LISTEN)
+ goto out;
+
+ switch (cmd) {
+ case SIOCINQ: {
+ struct sk_buff *skb;
+ unsigned long amount = 0;
+
+ skb = skb_peek(&sk->sk_receive_queue);
+ if (skb != NULL) {
+ /*
+ * We will only return the amount of this packet since
+ * that is all that will be read.
+ */
+ amount = skb->len;
+ }
+ rc = put_user(amount, (int __user *)arg);
+ }
+ break;
+ default:
+ rc = -ENOIOCTLCMD;
+ break;
+ }
+out:
+ release_sock(sk);
+ return rc;
}
EXPORT_SYMBOL_GPL(dccp_ioctl);
@@ -1043,11 +1072,13 @@ static int __init dccp_init(void)
}
for (i = 0; i < dccp_hashinfo.ehash_size; i++) {
- rwlock_init(&dccp_hashinfo.ehash[i].lock);
INIT_HLIST_HEAD(&dccp_hashinfo.ehash[i].chain);
INIT_HLIST_HEAD(&dccp_hashinfo.ehash[i].twchain);
}
+ if (inet_ehash_locks_alloc(&dccp_hashinfo))
+ goto out_free_dccp_ehash;
+
bhash_order = ehash_order;
do {
@@ -1062,7 +1093,7 @@ static int __init dccp_init(void)
if (!dccp_hashinfo.bhash) {
DCCP_CRIT("Failed to allocate DCCP bind hash table");
- goto out_free_dccp_ehash;
+ goto out_free_dccp_locks;
}
for (i = 0; i < dccp_hashinfo.bhash_size; i++) {
@@ -1092,6 +1123,8 @@ out_free_dccp_mib:
out_free_dccp_bhash:
free_pages((unsigned long)dccp_hashinfo.bhash, bhash_order);
dccp_hashinfo.bhash = NULL;
+out_free_dccp_locks:
+ inet_ehash_locks_free(&dccp_hashinfo);
out_free_dccp_ehash:
free_pages((unsigned long)dccp_hashinfo.ehash, ehash_order);
dccp_hashinfo.ehash = NULL;
@@ -1110,6 +1143,7 @@ static void __exit dccp_fini(void)
free_pages((unsigned long)dccp_hashinfo.ehash,
get_order(dccp_hashinfo.ehash_size *
sizeof(struct inet_ehash_bucket)));
+ inet_ehash_locks_free(&dccp_hashinfo);
kmem_cache_destroy(dccp_hashinfo.bind_bucket_cachep);
dccp_ackvec_exit();
dccp_sysctl_exit();
diff --git a/net/dccp/sysctl.c b/net/dccp/sysctl.c
index 9364b2fb4dbd..c62c05039f69 100644
--- a/net/dccp/sysctl.c
+++ b/net/dccp/sysctl.c
@@ -18,9 +18,6 @@
#error This file should not be compiled without CONFIG_SYSCTL defined
#endif
-/* rate-limit for syncs in reply to sequence-invalid packets; RFC 4340, 7.5.4 */
-int sysctl_dccp_sync_ratelimit __read_mostly = HZ / 8;
-
static struct ctl_table dccp_default_table[] = {
{
.procname = "seq_window",
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
index aabe98d9402f..57d574951838 100644
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -474,7 +474,7 @@ static struct proto dn_proto = {
static struct sock *dn_alloc_sock(struct net *net, struct socket *sock, gfp_t gfp)
{
struct dn_scp *scp;
- struct sock *sk = sk_alloc(net, PF_DECnet, gfp, &dn_proto, 1);
+ struct sock *sk = sk_alloc(net, PF_DECnet, gfp, &dn_proto);
if (!sk)
goto out;
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index 26130afd8029..66e266fb5908 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -1439,7 +1439,7 @@ static const struct file_operations dn_dev_seq_fops = {
#endif /* CONFIG_PROC_FS */
-static int __initdata addr[2];
+static int addr[2];
module_param_array(addr, int, NULL, 0444);
MODULE_PARM_DESC(addr, "The DECnet address of this machine: area,node");
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 97eee5e8fbbe..66663e5d7acd 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -293,9 +293,7 @@ static int dn_insert_route(struct dn_route *rt, unsigned hash, struct dn_route *
dn_rt_hash_table[hash].chain);
rcu_assign_pointer(dn_rt_hash_table[hash].chain, rth);
- rth->u.dst.__use++;
- dst_hold(&rth->u.dst);
- rth->u.dst.lastuse = now;
+ dst_use(&rth->u.dst, now);
spin_unlock_bh(&dn_rt_hash_table[hash].lock);
dnrt_drop(rt);
@@ -308,9 +306,7 @@ static int dn_insert_route(struct dn_route *rt, unsigned hash, struct dn_route *
rcu_assign_pointer(rt->u.dst.dn_next, dn_rt_hash_table[hash].chain);
rcu_assign_pointer(dn_rt_hash_table[hash].chain, rt);
- dst_hold(&rt->u.dst);
- rt->u.dst.__use++;
- rt->u.dst.lastuse = now;
+ dst_use(&rt->u.dst, now);
spin_unlock_bh(&dn_rt_hash_table[hash].lock);
*rp = rt;
return 0;
@@ -1182,9 +1178,7 @@ static int __dn_route_output_key(struct dst_entry **pprt, const struct flowi *fl
(flp->mark == rt->fl.mark) &&
(rt->fl.iif == 0) &&
(rt->fl.oif == flp->oif)) {
- rt->u.dst.lastuse = jiffies;
- dst_hold(&rt->u.dst);
- rt->u.dst.__use++;
+ dst_use(&rt->u.dst, jiffies);
rcu_read_unlock_bh();
*pprt = &rt->u.dst;
return 0;
@@ -1456,9 +1450,7 @@ int dn_route_input(struct sk_buff *skb)
(rt->fl.oif == 0) &&
(rt->fl.mark == skb->mark) &&
(rt->fl.iif == cb->iif)) {
- rt->u.dst.lastuse = jiffies;
- dst_hold(&rt->u.dst);
- rt->u.dst.__use++;
+ dst_use(&rt->u.dst, jiffies);
rcu_read_unlock();
skb->dst = (struct dst_entry *)rt;
return 0;
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c
index ddd3f04f0919..ffebea04cc99 100644
--- a/net/decnet/dn_rules.c
+++ b/net/decnet/dn_rules.c
@@ -48,15 +48,6 @@ struct dn_fib_rule
u8 flags;
};
-static struct dn_fib_rule default_rule = {
- .common = {
- .refcnt = ATOMIC_INIT(2),
- .pref = 0x7fff,
- .table = RT_TABLE_MAIN,
- .action = FR_ACT_TO_TBL,
- },
-};
-
int dn_fib_lookup(struct flowi *flp, struct dn_fib_res *res)
{
@@ -262,8 +253,8 @@ static struct fib_rules_ops dn_fib_rules_ops = {
void __init dn_fib_rules_init(void)
{
- list_add_tail(&default_rule.common.list,
- &dn_fib_rules_ops.rules_list);
+ BUG_ON(fib_default_rule_add(&dn_fib_rules_ops, 0x7fff,
+ RT_TABLE_MAIN, 0));
fib_rules_register(&dn_fib_rules_ops);
}
diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c
index f7fba7721e63..43fcd29046d1 100644
--- a/net/decnet/netfilter/dn_rtmsg.c
+++ b/net/decnet/netfilter/dn_rtmsg.c
@@ -88,12 +88,12 @@ static void dnrmg_send_peer(struct sk_buff *skb)
static unsigned int dnrmg_hook(unsigned int hook,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
- dnrmg_send_peer(*pskb);
+ dnrmg_send_peer(skb);
return NF_ACCEPT;
}
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c
index 9cae16b4e0b7..f70df073c588 100644
--- a/net/econet/af_econet.c
+++ b/net/econet/af_econet.c
@@ -624,7 +624,7 @@ static int econet_create(struct net *net, struct socket *sock, int protocol)
sock->state = SS_UNCONNECTED;
err = -ENOBUFS;
- sk = sk_alloc(net, PF_ECONET, GFP_KERNEL, &econet_proto, 1);
+ sk = sk_alloc(net, PF_ECONET, GFP_KERNEL, &econet_proto);
if (sk == NULL)
goto out;
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
index ed8a3d49487d..6b2e454ae313 100644
--- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c
@@ -298,6 +298,14 @@ static int eth_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
+static int eth_validate_addr(struct net_device *dev)
+{
+ if (!is_valid_ether_addr(dev->dev_addr))
+ return -EINVAL;
+
+ return 0;
+}
+
const struct header_ops eth_header_ops ____cacheline_aligned = {
.create = eth_header,
.parse = eth_header_parse,
@@ -317,6 +325,7 @@ void ether_setup(struct net_device *dev)
dev->change_mtu = eth_change_mtu;
dev->set_mac_address = eth_mac_addr;
+ dev->validate_addr = eth_validate_addr;
dev->type = ARPHRD_ETHER;
dev->hard_header_len = ETH_HLEN;
diff --git a/net/ieee80211/ieee80211_crypt_ccmp.c b/net/ieee80211/ieee80211_crypt_ccmp.c
index 0936a3e0210b..c6d760d9fbbe 100644
--- a/net/ieee80211/ieee80211_crypt_ccmp.c
+++ b/net/ieee80211/ieee80211_crypt_ccmp.c
@@ -25,7 +25,6 @@
#include <net/ieee80211.h>
#include <linux/crypto.h>
-#include <asm/scatterlist.h>
MODULE_AUTHOR("Jouni Malinen");
MODULE_DESCRIPTION("Host AP crypt: CCMP");
diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c
index 6cc54eeca3ed..58b22619ab15 100644
--- a/net/ieee80211/ieee80211_crypt_tkip.c
+++ b/net/ieee80211/ieee80211_crypt_tkip.c
@@ -14,6 +14,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/random.h>
+#include <linux/scatterlist.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/mm.h>
@@ -24,7 +25,6 @@
#include <net/ieee80211.h>
#include <linux/crypto.h>
-#include <asm/scatterlist.h>
#include <linux/crc32.h>
MODULE_AUTHOR("Jouni Malinen");
@@ -390,9 +390,7 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
icv[3] = crc >> 24;
crypto_blkcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16);
- sg.page = virt_to_page(pos);
- sg.offset = offset_in_page(pos);
- sg.length = len + 4;
+ sg_init_one(&sg, pos, len + 4);
return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
}
@@ -485,9 +483,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
plen = skb->len - hdr_len - 12;
crypto_blkcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16);
- sg.page = virt_to_page(pos);
- sg.offset = offset_in_page(pos);
- sg.length = plen + 4;
+ sg_init_one(&sg, pos, plen + 4);
if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) {
if (net_ratelimit()) {
printk(KERN_DEBUG ": TKIP: failed to decrypt "
@@ -539,13 +535,9 @@ static int michael_mic(struct crypto_hash *tfm_michael, u8 * key, u8 * hdr,
printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n");
return -1;
}
- sg[0].page = virt_to_page(hdr);
- sg[0].offset = offset_in_page(hdr);
- sg[0].length = 16;
-
- sg[1].page = virt_to_page(data);
- sg[1].offset = offset_in_page(data);
- sg[1].length = data_len;
+ sg_init_table(sg, 2);
+ sg_set_buf(&sg[0], hdr, 16);
+ sg_set_buf(&sg[1], data, data_len);
if (crypto_hash_setkey(tfm_michael, key, 8))
return -1;
@@ -586,7 +578,7 @@ static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr)
if (stype & IEEE80211_STYPE_QOS_DATA) {
const struct ieee80211_hdr_3addrqos *qoshdr =
(struct ieee80211_hdr_3addrqos *)skb->data;
- hdr[12] = qoshdr->qos_ctl & cpu_to_le16(IEEE80211_QCTL_TID);
+ hdr[12] = le16_to_cpu(qoshdr->qos_ctl) & IEEE80211_QCTL_TID;
} else
hdr[12] = 0; /* priority */
diff --git a/net/ieee80211/ieee80211_crypt_wep.c b/net/ieee80211/ieee80211_crypt_wep.c
index 8d182459344e..3fa30c40779f 100644
--- a/net/ieee80211/ieee80211_crypt_wep.c
+++ b/net/ieee80211/ieee80211_crypt_wep.c
@@ -14,6 +14,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/random.h>
+#include <linux/scatterlist.h>
#include <linux/skbuff.h>
#include <linux/mm.h>
#include <asm/string.h>
@@ -21,7 +22,6 @@
#include <net/ieee80211.h>
#include <linux/crypto.h>
-#include <asm/scatterlist.h>
#include <linux/crc32.h>
MODULE_AUTHOR("Jouni Malinen");
@@ -170,9 +170,7 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
icv[3] = crc >> 24;
crypto_blkcipher_setkey(wep->tx_tfm, key, klen);
- sg.page = virt_to_page(pos);
- sg.offset = offset_in_page(pos);
- sg.length = len + 4;
+ sg_init_one(&sg, pos, len + 4);
return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
}
@@ -212,9 +210,7 @@ static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
plen = skb->len - hdr_len - 8;
crypto_blkcipher_setkey(wep->rx_tfm, key, klen);
- sg.page = virt_to_page(pos);
- sg.offset = offset_in_page(pos);
- sg.length = plen + 4;
+ sg_init_one(&sg, pos, plen + 4);
if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4))
return -7;
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index 9b58dd67acb6..d309e8f19992 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -409,7 +409,7 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
(*crypt)->priv);
sec.flags |= (1 << key);
/* This ensures a key will be activated if no key is
- * explicitely set */
+ * explicitly set */
if (key == sec.active_key)
sec.flags |= SEC_ACTIVE_KEY;
diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c
index ac36767b56e8..e01b59aedc54 100644
--- a/net/ieee80211/softmac/ieee80211softmac_wx.c
+++ b/net/ieee80211/softmac/ieee80211softmac_wx.c
@@ -470,7 +470,7 @@ ieee80211softmac_wx_set_mlme(struct net_device *dev,
{
struct ieee80211softmac_device *mac = ieee80211_priv(dev);
struct iw_mlme *mlme = (struct iw_mlme *)extra;
- u16 reason = cpu_to_le16(mlme->reason_code);
+ u16 reason = mlme->reason_code;
struct ieee80211softmac_network *net;
int err = -EINVAL;
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index d894f616c3d6..9f9fd2c6f6e2 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -560,7 +560,7 @@ config TCP_CONG_ILLINOIS
depends on EXPERIMENTAL
default n
---help---
- TCP-Illinois is a sender-side modificatio of TCP Reno for
+ TCP-Illinois is a sender-side modification of TCP Reno for
high speed long delay links. It uses round-trip-time to
adjust the alpha and beta parameters to achieve a higher average
throughput and maintain fairness.
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index a02c36d0a13e..93fe3966805d 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -10,7 +10,8 @@ obj-y := route.o inetpeer.o protocol.o \
tcp_minisocks.o tcp_cong.o \
datagram.o raw.o udp.o udplite.o \
arp.o icmp.o devinet.o af_inet.o igmp.o \
- sysctl_net_ipv4.o fib_frontend.o fib_semantics.o
+ sysctl_net_ipv4.o fib_frontend.o fib_semantics.o \
+ inet_fragment.o
obj-$(CONFIG_IP_FIB_HASH) += fib_hash.o
obj-$(CONFIG_IP_FIB_TRIE) += fib_trie.o
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 621b128897d7..d2f22e74b267 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -323,7 +323,7 @@ lookup_protocol:
BUG_TRAP(answer_prot->slab != NULL);
err = -ENOBUFS;
- sk = sk_alloc(net, PF_INET, GFP_KERNEL, answer_prot, 1);
+ sk = sk_alloc(net, PF_INET, GFP_KERNEL, answer_prot);
if (sk == NULL)
goto out;
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index 4e8e3b079f5b..5fc346d8b566 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -8,7 +8,6 @@
#include <linux/spinlock.h>
#include <net/icmp.h>
#include <net/protocol.h>
-#include <asm/scatterlist.h>
/* Clear mutable options and find final destination to substitute
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index 805a78e6ed55..f18e88bc86ec 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -504,22 +504,16 @@ int cipso_v4_doi_add(struct cipso_v4_doi *doi_def)
INIT_RCU_HEAD(&doi_def->rcu);
INIT_LIST_HEAD(&doi_def->dom_list);
- rcu_read_lock();
- if (cipso_v4_doi_search(doi_def->doi) != NULL)
- goto doi_add_failure_rlock;
spin_lock(&cipso_v4_doi_list_lock);
if (cipso_v4_doi_search(doi_def->doi) != NULL)
- goto doi_add_failure_slock;
+ goto doi_add_failure;
list_add_tail_rcu(&doi_def->list, &cipso_v4_doi_list);
spin_unlock(&cipso_v4_doi_list_lock);
- rcu_read_unlock();
return 0;
-doi_add_failure_slock:
+doi_add_failure:
spin_unlock(&cipso_v4_doi_list_lock);
-doi_add_failure_rlock:
- rcu_read_unlock();
return -EEXIST;
}
@@ -543,29 +537,23 @@ int cipso_v4_doi_remove(u32 doi,
struct cipso_v4_doi *doi_def;
struct cipso_v4_domhsh_entry *dom_iter;
- rcu_read_lock();
- if (cipso_v4_doi_search(doi) != NULL) {
- spin_lock(&cipso_v4_doi_list_lock);
- doi_def = cipso_v4_doi_search(doi);
- if (doi_def == NULL) {
- spin_unlock(&cipso_v4_doi_list_lock);
- rcu_read_unlock();
- return -ENOENT;
- }
+ spin_lock(&cipso_v4_doi_list_lock);
+ doi_def = cipso_v4_doi_search(doi);
+ if (doi_def != NULL) {
doi_def->valid = 0;
list_del_rcu(&doi_def->list);
spin_unlock(&cipso_v4_doi_list_lock);
+ rcu_read_lock();
list_for_each_entry_rcu(dom_iter, &doi_def->dom_list, list)
if (dom_iter->valid)
netlbl_domhsh_remove(dom_iter->domain,
audit_info);
- cipso_v4_cache_invalidate();
rcu_read_unlock();
-
+ cipso_v4_cache_invalidate();
call_rcu(&doi_def->rcu, callback);
return 0;
}
- rcu_read_unlock();
+ spin_unlock(&cipso_v4_doi_list_lock);
return -ENOENT;
}
@@ -653,22 +641,19 @@ int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, const char *domain)
new_dom->valid = 1;
INIT_RCU_HEAD(&new_dom->rcu);
- rcu_read_lock();
spin_lock(&cipso_v4_doi_list_lock);
- list_for_each_entry_rcu(iter, &doi_def->dom_list, list)
+ list_for_each_entry(iter, &doi_def->dom_list, list)
if (iter->valid &&
((domain != NULL && iter->domain != NULL &&
strcmp(iter->domain, domain) == 0) ||
(domain == NULL && iter->domain == NULL))) {
spin_unlock(&cipso_v4_doi_list_lock);
- rcu_read_unlock();
kfree(new_dom->domain);
kfree(new_dom);
return -EEXIST;
}
list_add_tail_rcu(&new_dom->list, &doi_def->dom_list);
spin_unlock(&cipso_v4_doi_list_lock);
- rcu_read_unlock();
return 0;
}
@@ -689,9 +674,8 @@ int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def,
{
struct cipso_v4_domhsh_entry *iter;
- rcu_read_lock();
spin_lock(&cipso_v4_doi_list_lock);
- list_for_each_entry_rcu(iter, &doi_def->dom_list, list)
+ list_for_each_entry(iter, &doi_def->dom_list, list)
if (iter->valid &&
((domain != NULL && iter->domain != NULL &&
strcmp(iter->domain, domain) == 0) ||
@@ -699,13 +683,10 @@ int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def,
iter->valid = 0;
list_del_rcu(&iter->list);
spin_unlock(&cipso_v4_doi_list_lock);
- rcu_read_unlock();
call_rcu(&iter->rcu, cipso_v4_doi_domhsh_free);
-
return 0;
}
spin_unlock(&cipso_v4_doi_list_lock);
- rcu_read_unlock();
return -ENOENT;
}
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 6b1a31a74cf2..c31bccb9b526 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -3,7 +3,7 @@
#include <net/ip.h>
#include <net/xfrm.h>
#include <net/esp.h>
-#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
#include <linux/crypto.h>
#include <linux/kernel.h>
#include <linux/pfkeyv2.h>
@@ -110,7 +110,11 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
if (!sg)
goto unlock;
}
- skb_to_sgvec(skb, sg, esph->enc_data+esp->conf.ivlen-skb->data, clen);
+ sg_init_table(sg, nfrags);
+ skb_to_sgvec(skb, sg,
+ esph->enc_data +
+ esp->conf.ivlen -
+ skb->data, clen);
err = crypto_blkcipher_encrypt(&desc, sg, sg, clen);
if (unlikely(sg != &esp->sgbuf[0]))
kfree(sg);
@@ -201,7 +205,10 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
if (!sg)
goto out;
}
- skb_to_sgvec(skb, sg, sizeof(*esph) + esp->conf.ivlen, elen);
+ sg_init_table(sg, nfrags);
+ skb_to_sgvec(skb, sg,
+ sizeof(*esph) + esp->conf.ivlen,
+ elen);
err = crypto_blkcipher_decrypt(&desc, sg, sg, elen);
if (unlikely(sg != &esp->sgbuf[0]))
kfree(sg);
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 78b514ba1414..732d8f088b13 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -59,6 +59,13 @@ struct fib_table *ip_fib_main_table;
#define FIB_TABLE_HASHSZ 1
static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ];
+static void __init fib4_rules_init(void)
+{
+ ip_fib_local_table = fib_hash_init(RT_TABLE_LOCAL);
+ hlist_add_head_rcu(&ip_fib_local_table->tb_hlist, &fib_table_hash[0]);
+ ip_fib_main_table = fib_hash_init(RT_TABLE_MAIN);
+ hlist_add_head_rcu(&ip_fib_main_table->tb_hlist, &fib_table_hash[0]);
+}
#else
#define FIB_TABLE_HASHSZ 256
@@ -128,13 +135,14 @@ struct net_device * ip_dev_find(__be32 addr)
struct flowi fl = { .nl_u = { .ip4_u = { .daddr = addr } } };
struct fib_result res;
struct net_device *dev = NULL;
+ struct fib_table *local_table;
#ifdef CONFIG_IP_MULTIPLE_TABLES
res.r = NULL;
#endif
- if (!ip_fib_local_table ||
- ip_fib_local_table->tb_lookup(ip_fib_local_table, &fl, &res))
+ local_table = fib_get_table(RT_TABLE_LOCAL);
+ if (!local_table || local_table->tb_lookup(local_table, &fl, &res))
return NULL;
if (res.type != RTN_LOCAL)
goto out;
@@ -152,6 +160,7 @@ unsigned inet_addr_type(__be32 addr)
struct flowi fl = { .nl_u = { .ip4_u = { .daddr = addr } } };
struct fib_result res;
unsigned ret = RTN_BROADCAST;
+ struct fib_table *local_table;
if (ZERONET(addr) || BADCLASS(addr))
return RTN_BROADCAST;
@@ -162,10 +171,10 @@ unsigned inet_addr_type(__be32 addr)
res.r = NULL;
#endif
- if (ip_fib_local_table) {
+ local_table = fib_get_table(RT_TABLE_LOCAL);
+ if (local_table) {
ret = RTN_UNICAST;
- if (!ip_fib_local_table->tb_lookup(ip_fib_local_table,
- &fl, &res)) {
+ if (!local_table->tb_lookup(local_table, &fl, &res)) {
ret = res.type;
fib_res_put(&res);
}
@@ -903,14 +912,8 @@ void __init ip_fib_init(void)
for (i = 0; i < FIB_TABLE_HASHSZ; i++)
INIT_HLIST_HEAD(&fib_table_hash[i]);
-#ifndef CONFIG_IP_MULTIPLE_TABLES
- ip_fib_local_table = fib_hash_init(RT_TABLE_LOCAL);
- hlist_add_head_rcu(&ip_fib_local_table->tb_hlist, &fib_table_hash[0]);
- ip_fib_main_table = fib_hash_init(RT_TABLE_MAIN);
- hlist_add_head_rcu(&ip_fib_main_table->tb_hlist, &fib_table_hash[0]);
-#else
+
fib4_rules_init();
-#endif
register_netdevice_notifier(&fib_netdev_notifier);
register_inetaddr_notifier(&fib_inetaddr_notifier);
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index f16839c6a721..a0ada3a8d8dd 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -49,33 +49,6 @@ struct fib4_rule
#endif
};
-static struct fib4_rule default_rule = {
- .common = {
- .refcnt = ATOMIC_INIT(2),
- .pref = 0x7FFF,
- .table = RT_TABLE_DEFAULT,
- .action = FR_ACT_TO_TBL,
- },
-};
-
-static struct fib4_rule main_rule = {
- .common = {
- .refcnt = ATOMIC_INIT(2),
- .pref = 0x7FFE,
- .table = RT_TABLE_MAIN,
- .action = FR_ACT_TO_TBL,
- },
-};
-
-static struct fib4_rule local_rule = {
- .common = {
- .refcnt = ATOMIC_INIT(2),
- .table = RT_TABLE_LOCAL,
- .action = FR_ACT_TO_TBL,
- .flags = FIB_RULE_PERMANENT,
- },
-};
-
#ifdef CONFIG_NET_CLS_ROUTE
u32 fib_rules_tclass(struct fib_result *res)
{
@@ -319,11 +292,27 @@ static struct fib_rules_ops fib4_rules_ops = {
.owner = THIS_MODULE,
};
-void __init fib4_rules_init(void)
+static int __init fib_default_rules_init(void)
{
- list_add_tail(&local_rule.common.list, &fib4_rules_ops.rules_list);
- list_add_tail(&main_rule.common.list, &fib4_rules_ops.rules_list);
- list_add_tail(&default_rule.common.list, &fib4_rules_ops.rules_list);
+ int err;
+
+ err = fib_default_rule_add(&fib4_rules_ops, 0,
+ RT_TABLE_LOCAL, FIB_RULE_PERMANENT);
+ if (err < 0)
+ return err;
+ err = fib_default_rule_add(&fib4_rules_ops, 0x7FFE,
+ RT_TABLE_MAIN, 0);
+ if (err < 0)
+ return err;
+ err = fib_default_rule_add(&fib4_rules_ops, 0x7FFF,
+ RT_TABLE_DEFAULT, 0);
+ if (err < 0)
+ return err;
+ return 0;
+}
+void __init fib4_rules_init(void)
+{
+ BUG_ON(fib_default_rules_init());
fib_rules_register(&fib4_rules_ops);
}
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 81a8285d6d6a..8d8c2915e064 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -54,7 +54,7 @@
#include <asm/uaccess.h>
#include <asm/system.h>
-#include <asm/bitops.h>
+#include <linux/bitops.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/mm.h>
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 272c69e106e9..233de0634298 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -1104,5 +1104,4 @@ void __init icmp_init(struct net_proto_family *ops)
EXPORT_SYMBOL(icmp_err_convert);
EXPORT_SYMBOL(icmp_send);
EXPORT_SYMBOL(icmp_statistics);
-EXPORT_SYMBOL(icmpmsg_statistics);
EXPORT_SYMBOL(xrlim_allow);
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 3cef12835c4b..8fb6ca23700a 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -93,7 +93,7 @@ int inet_csk_get_port(struct inet_hashinfo *hashinfo,
int remaining, rover, low, high;
inet_get_local_port_range(&low, &high);
- remaining = high - low;
+ remaining = (high - low) + 1;
rover = net_random() % remaining + low;
do {
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index 7eb83ebed2ec..b0170732b5e9 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -747,13 +747,14 @@ skip_listen_ht:
for (i = s_i; i < hashinfo->ehash_size; i++) {
struct inet_ehash_bucket *head = &hashinfo->ehash[i];
+ rwlock_t *lock = inet_ehash_lockp(hashinfo, i);
struct sock *sk;
struct hlist_node *node;
if (i > s_i)
s_num = 0;
- read_lock_bh(&head->lock);
+ read_lock_bh(lock);
num = 0;
sk_for_each(sk, node, &head->chain) {
struct inet_sock *inet = inet_sk(sk);
@@ -769,7 +770,7 @@ skip_listen_ht:
r->id.idiag_dport)
goto next_normal;
if (inet_csk_diag_dump(sk, skb, cb) < 0) {
- read_unlock_bh(&head->lock);
+ read_unlock_bh(lock);
goto done;
}
next_normal:
@@ -791,14 +792,14 @@ next_normal:
r->id.idiag_dport)
goto next_dying;
if (inet_twsk_diag_dump(tw, skb, cb) < 0) {
- read_unlock_bh(&head->lock);
+ read_unlock_bh(lock);
goto done;
}
next_dying:
++num;
}
}
- read_unlock_bh(&head->lock);
+ read_unlock_bh(lock);
}
done:
@@ -815,6 +816,12 @@ static int inet_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
nlmsg_len(nlh) < hdrlen)
return -EINVAL;
+#ifdef CONFIG_KMOD
+ if (inet_diag_table[nlh->nlmsg_type] == NULL)
+ request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK,
+ NETLINK_INET_DIAG, nlh->nlmsg_type);
+#endif
+
if (inet_diag_table[nlh->nlmsg_type] == NULL)
return -ENOENT;
@@ -914,3 +921,4 @@ static void __exit inet_diag_exit(void)
module_init(inet_diag_init);
module_exit(inet_diag_exit);
MODULE_LICENSE("GPL");
+MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_INET_DIAG);
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c
new file mode 100644
index 000000000000..e15e04fc6661
--- /dev/null
+++ b/net/ipv4/inet_fragment.c
@@ -0,0 +1,261 @@
+/*
+ * inet fragments management
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Authors: Pavel Emelyanov <xemul@openvz.org>
+ * Started as consolidation of ipv4/ip_fragment.c,
+ * ipv6/reassembly. and ipv6 nf conntrack reassembly
+ */
+
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/random.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+
+#include <net/inet_frag.h>
+
+static void inet_frag_secret_rebuild(unsigned long dummy)
+{
+ struct inet_frags *f = (struct inet_frags *)dummy;
+ unsigned long now = jiffies;
+ int i;
+
+ write_lock(&f->lock);
+ get_random_bytes(&f->rnd, sizeof(u32));
+ for (i = 0; i < INETFRAGS_HASHSZ; i++) {
+ struct inet_frag_queue *q;
+ struct hlist_node *p, *n;
+
+ hlist_for_each_entry_safe(q, p, n, &f->hash[i], list) {
+ unsigned int hval = f->hashfn(q);
+
+ if (hval != i) {
+ hlist_del(&q->list);
+
+ /* Relink to new hash chain. */
+ hlist_add_head(&q->list, &f->hash[hval]);
+ }
+ }
+ }
+ write_unlock(&f->lock);
+
+ mod_timer(&f->secret_timer, now + f->ctl->secret_interval);
+}
+
+void inet_frags_init(struct inet_frags *f)
+{
+ int i;
+
+ for (i = 0; i < INETFRAGS_HASHSZ; i++)
+ INIT_HLIST_HEAD(&f->hash[i]);
+
+ INIT_LIST_HEAD(&f->lru_list);
+ rwlock_init(&f->lock);
+
+ f->rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^
+ (jiffies ^ (jiffies >> 6)));
+
+ f->nqueues = 0;
+ atomic_set(&f->mem, 0);
+
+ init_timer(&f->secret_timer);
+ f->secret_timer.function = inet_frag_secret_rebuild;
+ f->secret_timer.data = (unsigned long)f;
+ f->secret_timer.expires = jiffies + f->ctl->secret_interval;
+ add_timer(&f->secret_timer);
+}
+EXPORT_SYMBOL(inet_frags_init);
+
+void inet_frags_fini(struct inet_frags *f)
+{
+ del_timer(&f->secret_timer);
+}
+EXPORT_SYMBOL(inet_frags_fini);
+
+static inline void fq_unlink(struct inet_frag_queue *fq, struct inet_frags *f)
+{
+ write_lock(&f->lock);
+ hlist_del(&fq->list);
+ list_del(&fq->lru_list);
+ f->nqueues--;
+ write_unlock(&f->lock);
+}
+
+void inet_frag_kill(struct inet_frag_queue *fq, struct inet_frags *f)
+{
+ if (del_timer(&fq->timer))
+ atomic_dec(&fq->refcnt);
+
+ if (!(fq->last_in & COMPLETE)) {
+ fq_unlink(fq, f);
+ atomic_dec(&fq->refcnt);
+ fq->last_in |= COMPLETE;
+ }
+}
+
+EXPORT_SYMBOL(inet_frag_kill);
+
+static inline void frag_kfree_skb(struct inet_frags *f, struct sk_buff *skb,
+ int *work)
+{
+ if (work)
+ *work -= skb->truesize;
+
+ atomic_sub(skb->truesize, &f->mem);
+ if (f->skb_free)
+ f->skb_free(skb);
+ kfree_skb(skb);
+}
+
+void inet_frag_destroy(struct inet_frag_queue *q, struct inet_frags *f,
+ int *work)
+{
+ struct sk_buff *fp;
+
+ BUG_TRAP(q->last_in & COMPLETE);
+ BUG_TRAP(del_timer(&q->timer) == 0);
+
+ /* Release all fragment data. */
+ fp = q->fragments;
+ while (fp) {
+ struct sk_buff *xp = fp->next;
+
+ frag_kfree_skb(f, fp, work);
+ fp = xp;
+ }
+
+ if (work)
+ *work -= f->qsize;
+ atomic_sub(f->qsize, &f->mem);
+
+ if (f->destructor)
+ f->destructor(q);
+ kfree(q);
+
+}
+EXPORT_SYMBOL(inet_frag_destroy);
+
+int inet_frag_evictor(struct inet_frags *f)
+{
+ struct inet_frag_queue *q;
+ int work, evicted = 0;
+
+ work = atomic_read(&f->mem) - f->ctl->low_thresh;
+ while (work > 0) {
+ read_lock(&f->lock);
+ if (list_empty(&f->lru_list)) {
+ read_unlock(&f->lock);
+ break;
+ }
+
+ q = list_first_entry(&f->lru_list,
+ struct inet_frag_queue, lru_list);
+ atomic_inc(&q->refcnt);
+ read_unlock(&f->lock);
+
+ spin_lock(&q->lock);
+ if (!(q->last_in & COMPLETE))
+ inet_frag_kill(q, f);
+ spin_unlock(&q->lock);
+
+ if (atomic_dec_and_test(&q->refcnt))
+ inet_frag_destroy(q, f, &work);
+ evicted++;
+ }
+
+ return evicted;
+}
+EXPORT_SYMBOL(inet_frag_evictor);
+
+static struct inet_frag_queue *inet_frag_intern(struct inet_frag_queue *qp_in,
+ struct inet_frags *f, unsigned int hash, void *arg)
+{
+ struct inet_frag_queue *qp;
+#ifdef CONFIG_SMP
+ struct hlist_node *n;
+#endif
+
+ write_lock(&f->lock);
+#ifdef CONFIG_SMP
+ /* With SMP race we have to recheck hash table, because
+ * such entry could be created on other cpu, while we
+ * promoted read lock to write lock.
+ */
+ hlist_for_each_entry(qp, n, &f->hash[hash], list) {
+ if (f->match(qp, arg)) {
+ atomic_inc(&qp->refcnt);
+ write_unlock(&f->lock);
+ qp_in->last_in |= COMPLETE;
+ inet_frag_put(qp_in, f);
+ return qp;
+ }
+ }
+#endif
+ qp = qp_in;
+ if (!mod_timer(&qp->timer, jiffies + f->ctl->timeout))
+ atomic_inc(&qp->refcnt);
+
+ atomic_inc(&qp->refcnt);
+ hlist_add_head(&qp->list, &f->hash[hash]);
+ list_add_tail(&qp->lru_list, &f->lru_list);
+ f->nqueues++;
+ write_unlock(&f->lock);
+ return qp;
+}
+
+static struct inet_frag_queue *inet_frag_alloc(struct inet_frags *f, void *arg)
+{
+ struct inet_frag_queue *q;
+
+ q = kzalloc(f->qsize, GFP_ATOMIC);
+ if (q == NULL)
+ return NULL;
+
+ f->constructor(q, arg);
+ atomic_add(f->qsize, &f->mem);
+ setup_timer(&q->timer, f->frag_expire, (unsigned long)q);
+ spin_lock_init(&q->lock);
+ atomic_set(&q->refcnt, 1);
+
+ return q;
+}
+
+static struct inet_frag_queue *inet_frag_create(struct inet_frags *f,
+ void *arg, unsigned int hash)
+{
+ struct inet_frag_queue *q;
+
+ q = inet_frag_alloc(f, arg);
+ if (q == NULL)
+ return NULL;
+
+ return inet_frag_intern(q, f, hash, arg);
+}
+
+struct inet_frag_queue *inet_frag_find(struct inet_frags *f, void *key,
+ unsigned int hash)
+{
+ struct inet_frag_queue *q;
+ struct hlist_node *n;
+
+ read_lock(&f->lock);
+ hlist_for_each_entry(q, n, &f->hash[hash], list) {
+ if (f->match(q, key)) {
+ atomic_inc(&q->refcnt);
+ read_unlock(&f->lock);
+ return q;
+ }
+ }
+ read_unlock(&f->lock);
+
+ return inet_frag_create(f, key, hash);
+}
+EXPORT_SYMBOL(inet_frag_find);
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index fac6398e4367..67704da04fc4 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -204,12 +204,13 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row,
const __portpair ports = INET_COMBINED_PORTS(inet->dport, lport);
unsigned int hash = inet_ehashfn(daddr, lport, saddr, inet->dport);
struct inet_ehash_bucket *head = inet_ehash_bucket(hinfo, hash);
+ rwlock_t *lock = inet_ehash_lockp(hinfo, hash);
struct sock *sk2;
const struct hlist_node *node;
struct inet_timewait_sock *tw;
prefetch(head->chain.first);
- write_lock(&head->lock);
+ write_lock(lock);
/* Check TIME-WAIT sockets first. */
sk_for_each(sk2, node, &head->twchain) {
@@ -239,7 +240,7 @@ unique:
BUG_TRAP(sk_unhashed(sk));
__sk_add_node(sk, &head->chain);
sock_prot_inc_use(sk->sk_prot);
- write_unlock(&head->lock);
+ write_unlock(lock);
if (twp) {
*twp = tw;
@@ -255,7 +256,7 @@ unique:
return 0;
not_unique:
- write_unlock(&head->lock);
+ write_unlock(lock);
return -EADDRNOTAVAIL;
}
@@ -286,7 +287,7 @@ int inet_hash_connect(struct inet_timewait_death_row *death_row,
struct inet_timewait_sock *tw = NULL;
inet_get_local_port_range(&low, &high);
- remaining = high - low;
+ remaining = (high - low) + 1;
local_bh_disable();
for (i = 1; i <= remaining; i++) {
diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c
index 4e189e28f306..a60b99e0ebdc 100644
--- a/net/ipv4/inet_timewait_sock.c
+++ b/net/ipv4/inet_timewait_sock.c
@@ -20,16 +20,16 @@ static void __inet_twsk_kill(struct inet_timewait_sock *tw,
struct inet_bind_hashbucket *bhead;
struct inet_bind_bucket *tb;
/* Unlink from established hashes. */
- struct inet_ehash_bucket *ehead = inet_ehash_bucket(hashinfo, tw->tw_hash);
+ rwlock_t *lock = inet_ehash_lockp(hashinfo, tw->tw_hash);
- write_lock(&ehead->lock);
+ write_lock(lock);
if (hlist_unhashed(&tw->tw_node)) {
- write_unlock(&ehead->lock);
+ write_unlock(lock);
return;
}
__hlist_del(&tw->tw_node);
sk_node_init(&tw->tw_node);
- write_unlock(&ehead->lock);
+ write_unlock(lock);
/* Disassociate with bind bucket. */
bhead = &hashinfo->bhash[inet_bhashfn(tw->tw_num, hashinfo->bhash_size)];
@@ -59,6 +59,7 @@ void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk,
const struct inet_sock *inet = inet_sk(sk);
const struct inet_connection_sock *icsk = inet_csk(sk);
struct inet_ehash_bucket *ehead = inet_ehash_bucket(hashinfo, sk->sk_hash);
+ rwlock_t *lock = inet_ehash_lockp(hashinfo, sk->sk_hash);
struct inet_bind_hashbucket *bhead;
/* Step 1: Put TW into bind hash. Original socket stays there too.
Note, that any socket with inet->num != 0 MUST be bound in
@@ -71,7 +72,7 @@ void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk,
inet_twsk_add_bind_node(tw, &tw->tw_tb->owners);
spin_unlock(&bhead->lock);
- write_lock(&ehead->lock);
+ write_lock(lock);
/* Step 2: Remove SK from established hash. */
if (__sk_del_node_init(sk))
@@ -81,7 +82,7 @@ void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk,
inet_twsk_add_node(tw, &ehead->twchain);
atomic_inc(&tw->tw_refcnt);
- write_unlock(&ehead->lock);
+ write_unlock(lock);
}
EXPORT_SYMBOL_GPL(__inet_twsk_hashdance);
diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c
index 771031dfbd0f..af995198f643 100644
--- a/net/ipv4/inetpeer.c
+++ b/net/ipv4/inetpeer.c
@@ -61,7 +61,7 @@
* 4. Global variable peer_total is modified under the pool lock.
* 5. struct inet_peer fields modification:
* avl_left, avl_right, avl_parent, avl_height: pool lock
- * unused_next, unused_prevp: unused node list lock
+ * unused: unused node list lock
* refcnt: atomically against modifications on other CPU;
* usually under some other lock to prevent node disappearing
* dtime: unused node list lock
@@ -94,8 +94,7 @@ int inet_peer_maxttl __read_mostly = 10 * 60 * HZ; /* usual time to live: 10 min
int inet_peer_gc_mintime __read_mostly = 10 * HZ;
int inet_peer_gc_maxtime __read_mostly = 120 * HZ;
-static struct inet_peer *inet_peer_unused_head;
-static struct inet_peer **inet_peer_unused_tailp = &inet_peer_unused_head;
+static LIST_HEAD(unused_peers);
static DEFINE_SPINLOCK(inet_peer_unused_lock);
static void peer_check_expire(unsigned long dummy);
@@ -138,15 +137,7 @@ void __init inet_initpeers(void)
static void unlink_from_unused(struct inet_peer *p)
{
spin_lock_bh(&inet_peer_unused_lock);
- if (p->unused_prevp != NULL) {
- /* On unused list. */
- *p->unused_prevp = p->unused_next;
- if (p->unused_next != NULL)
- p->unused_next->unused_prevp = p->unused_prevp;
- else
- inet_peer_unused_tailp = p->unused_prevp;
- p->unused_prevp = NULL; /* mark it as removed */
- }
+ list_del_init(&p->unused);
spin_unlock_bh(&inet_peer_unused_lock);
}
@@ -337,24 +328,24 @@ static void unlink_from_pool(struct inet_peer *p)
/* May be called with local BH enabled. */
static int cleanup_once(unsigned long ttl)
{
- struct inet_peer *p;
+ struct inet_peer *p = NULL;
/* Remove the first entry from the list of unused nodes. */
spin_lock_bh(&inet_peer_unused_lock);
- p = inet_peer_unused_head;
- if (p != NULL) {
- __u32 delta = (__u32)jiffies - p->dtime;
+ if (!list_empty(&unused_peers)) {
+ __u32 delta;
+
+ p = list_first_entry(&unused_peers, struct inet_peer, unused);
+ delta = (__u32)jiffies - p->dtime;
+
if (delta < ttl) {
/* Do not prune fresh entries. */
spin_unlock_bh(&inet_peer_unused_lock);
return -1;
}
- inet_peer_unused_head = p->unused_next;
- if (p->unused_next != NULL)
- p->unused_next->unused_prevp = p->unused_prevp;
- else
- inet_peer_unused_tailp = p->unused_prevp;
- p->unused_prevp = NULL; /* mark as not on the list */
+
+ list_del_init(&p->unused);
+
/* Grab an extra reference to prevent node disappearing
* before unlink_from_pool() call. */
atomic_inc(&p->refcnt);
@@ -412,7 +403,7 @@ struct inet_peer *inet_getpeer(__be32 daddr, int create)
/* Link the node. */
link_to_pool(n);
- n->unused_prevp = NULL; /* not on the list */
+ INIT_LIST_HEAD(&n->unused);
peer_total++;
write_unlock_bh(&peer_pool_lock);
@@ -467,10 +458,7 @@ void inet_putpeer(struct inet_peer *p)
{
spin_lock_bh(&inet_peer_unused_lock);
if (atomic_dec_and_test(&p->refcnt)) {
- p->unused_prevp = inet_peer_unused_tailp;
- p->unused_next = NULL;
- *inet_peer_unused_tailp = p;
- inet_peer_unused_tailp = &p->unused_next;
+ list_add_tail(&p->unused, &unused_peers);
p->dtime = (__u32)jiffies;
}
spin_unlock_bh(&inet_peer_unused_lock);
diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c
index afbf938836f5..877da3ed52e2 100644
--- a/net/ipv4/ip_forward.c
+++ b/net/ipv4/ip_forward.c
@@ -40,7 +40,7 @@
#include <net/route.h>
#include <net/xfrm.h>
-static inline int ip_forward_finish(struct sk_buff *skb)
+static int ip_forward_finish(struct sk_buff *skb)
{
struct ip_options * opt = &(IPCB(skb)->opt);
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index fabb86db763b..2143bf30597a 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -39,6 +39,7 @@
#include <net/icmp.h>
#include <net/checksum.h>
#include <net/inetpeer.h>
+#include <net/inet_frag.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/inet.h>
@@ -49,21 +50,8 @@
* as well. Or notify me, at least. --ANK
*/
-/* Fragment cache limits. We will commit 256K at one time. Should we
- * cross that limit we will prune down to 192K. This should cope with
- * even the most extreme cases without allowing an attacker to measurably
- * harm machine performance.
- */
-int sysctl_ipfrag_high_thresh __read_mostly = 256*1024;
-int sysctl_ipfrag_low_thresh __read_mostly = 192*1024;
-
int sysctl_ipfrag_max_dist __read_mostly = 64;
-/* Important NOTE! Fragment queue must be destroyed before MSL expires.
- * RFC791 is wrong proposing to prolongate timer each fragment arrival by TTL.
- */
-int sysctl_ipfrag_time __read_mostly = IP_FRAG_TIME;
-
struct ipfrag_skb_cb
{
struct inet_skb_parm h;
@@ -74,153 +62,123 @@ struct ipfrag_skb_cb
/* Describe an entry in the "incomplete datagrams" queue. */
struct ipq {
- struct hlist_node list;
- struct list_head lru_list; /* lru list member */
+ struct inet_frag_queue q;
+
u32 user;
__be32 saddr;
__be32 daddr;
__be16 id;
u8 protocol;
- u8 last_in;
-#define COMPLETE 4
-#define FIRST_IN 2
-#define LAST_IN 1
-
- struct sk_buff *fragments; /* linked list of received fragments */
- int len; /* total length of original datagram */
- int meat;
- spinlock_t lock;
- atomic_t refcnt;
- struct timer_list timer; /* when will this queue expire? */
- ktime_t stamp;
int iif;
unsigned int rid;
struct inet_peer *peer;
};
-/* Hash table. */
+struct inet_frags_ctl ip4_frags_ctl __read_mostly = {
+ /*
+ * Fragment cache limits. We will commit 256K at one time. Should we
+ * cross that limit we will prune down to 192K. This should cope with
+ * even the most extreme cases without allowing an attacker to
+ * measurably harm machine performance.
+ */
+ .high_thresh = 256 * 1024,
+ .low_thresh = 192 * 1024,
-#define IPQ_HASHSZ 64
+ /*
+ * Important NOTE! Fragment queue must be destroyed before MSL expires.
+ * RFC791 is wrong proposing to prolongate timer each fragment arrival
+ * by TTL.
+ */
+ .timeout = IP_FRAG_TIME,
+ .secret_interval = 10 * 60 * HZ,
+};
-/* Per-bucket lock is easy to add now. */
-static struct hlist_head ipq_hash[IPQ_HASHSZ];
-static DEFINE_RWLOCK(ipfrag_lock);
-static u32 ipfrag_hash_rnd;
-static LIST_HEAD(ipq_lru_list);
-int ip_frag_nqueues = 0;
+static struct inet_frags ip4_frags;
-static __inline__ void __ipq_unlink(struct ipq *qp)
+int ip_frag_nqueues(void)
{
- hlist_del(&qp->list);
- list_del(&qp->lru_list);
- ip_frag_nqueues--;
+ return ip4_frags.nqueues;
}
-static __inline__ void ipq_unlink(struct ipq *ipq)
+int ip_frag_mem(void)
{
- write_lock(&ipfrag_lock);
- __ipq_unlink(ipq);
- write_unlock(&ipfrag_lock);
+ return atomic_read(&ip4_frags.mem);
}
+static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
+ struct net_device *dev);
+
+struct ip4_create_arg {
+ struct iphdr *iph;
+ u32 user;
+};
+
static unsigned int ipqhashfn(__be16 id, __be32 saddr, __be32 daddr, u8 prot)
{
return jhash_3words((__force u32)id << 16 | prot,
(__force u32)saddr, (__force u32)daddr,
- ipfrag_hash_rnd) & (IPQ_HASHSZ - 1);
+ ip4_frags.rnd) & (INETFRAGS_HASHSZ - 1);
}
-static struct timer_list ipfrag_secret_timer;
-int sysctl_ipfrag_secret_interval __read_mostly = 10 * 60 * HZ;
-
-static void ipfrag_secret_rebuild(unsigned long dummy)
+static unsigned int ip4_hashfn(struct inet_frag_queue *q)
{
- unsigned long now = jiffies;
- int i;
+ struct ipq *ipq;
- write_lock(&ipfrag_lock);
- get_random_bytes(&ipfrag_hash_rnd, sizeof(u32));
- for (i = 0; i < IPQ_HASHSZ; i++) {
- struct ipq *q;
- struct hlist_node *p, *n;
-
- hlist_for_each_entry_safe(q, p, n, &ipq_hash[i], list) {
- unsigned int hval = ipqhashfn(q->id, q->saddr,
- q->daddr, q->protocol);
-
- if (hval != i) {
- hlist_del(&q->list);
-
- /* Relink to new hash chain. */
- hlist_add_head(&q->list, &ipq_hash[hval]);
- }
- }
- }
- write_unlock(&ipfrag_lock);
-
- mod_timer(&ipfrag_secret_timer, now + sysctl_ipfrag_secret_interval);
+ ipq = container_of(q, struct ipq, q);
+ return ipqhashfn(ipq->id, ipq->saddr, ipq->daddr, ipq->protocol);
}
-atomic_t ip_frag_mem = ATOMIC_INIT(0); /* Memory used for fragments */
+static int ip4_frag_match(struct inet_frag_queue *q, void *a)
+{
+ struct ipq *qp;
+ struct ip4_create_arg *arg = a;
+
+ qp = container_of(q, struct ipq, q);
+ return (qp->id == arg->iph->id &&
+ qp->saddr == arg->iph->saddr &&
+ qp->daddr == arg->iph->daddr &&
+ qp->protocol == arg->iph->protocol &&
+ qp->user == arg->user);
+}
/* Memory Tracking Functions. */
static __inline__ void frag_kfree_skb(struct sk_buff *skb, int *work)
{
if (work)
*work -= skb->truesize;
- atomic_sub(skb->truesize, &ip_frag_mem);
+ atomic_sub(skb->truesize, &ip4_frags.mem);
kfree_skb(skb);
}
-static __inline__ void frag_free_queue(struct ipq *qp, int *work)
+static void ip4_frag_init(struct inet_frag_queue *q, void *a)
{
- if (work)
- *work -= sizeof(struct ipq);
- atomic_sub(sizeof(struct ipq), &ip_frag_mem);
- kfree(qp);
+ struct ipq *qp = container_of(q, struct ipq, q);
+ struct ip4_create_arg *arg = a;
+
+ qp->protocol = arg->iph->protocol;
+ qp->id = arg->iph->id;
+ qp->saddr = arg->iph->saddr;
+ qp->daddr = arg->iph->daddr;
+ qp->user = arg->user;
+ qp->peer = sysctl_ipfrag_max_dist ?
+ inet_getpeer(arg->iph->saddr, 1) : NULL;
}
-static __inline__ struct ipq *frag_alloc_queue(void)
+static __inline__ void ip4_frag_free(struct inet_frag_queue *q)
{
- struct ipq *qp = kmalloc(sizeof(struct ipq), GFP_ATOMIC);
-
- if (!qp)
- return NULL;
- atomic_add(sizeof(struct ipq), &ip_frag_mem);
- return qp;
-}
-
-
-/* Destruction primitives. */
-
-/* Complete destruction of ipq. */
-static void ip_frag_destroy(struct ipq *qp, int *work)
-{
- struct sk_buff *fp;
-
- BUG_TRAP(qp->last_in&COMPLETE);
- BUG_TRAP(del_timer(&qp->timer) == 0);
+ struct ipq *qp;
+ qp = container_of(q, struct ipq, q);
if (qp->peer)
inet_putpeer(qp->peer);
+}
- /* Release all fragment data. */
- fp = qp->fragments;
- while (fp) {
- struct sk_buff *xp = fp->next;
-
- frag_kfree_skb(fp, work);
- fp = xp;
- }
- /* Finally, release the queue descriptor itself. */
- frag_free_queue(qp, work);
-}
+/* Destruction primitives. */
-static __inline__ void ipq_put(struct ipq *ipq, int *work)
+static __inline__ void ipq_put(struct ipq *ipq)
{
- if (atomic_dec_and_test(&ipq->refcnt))
- ip_frag_destroy(ipq, work);
+ inet_frag_put(&ipq->q, &ip4_frags);
}
/* Kill ipq entry. It is not destroyed immediately,
@@ -228,14 +186,7 @@ static __inline__ void ipq_put(struct ipq *ipq, int *work)
*/
static void ipq_kill(struct ipq *ipq)
{
- if (del_timer(&ipq->timer))
- atomic_dec(&ipq->refcnt);
-
- if (!(ipq->last_in & COMPLETE)) {
- ipq_unlink(ipq);
- atomic_dec(&ipq->refcnt);
- ipq->last_in |= COMPLETE;
- }
+ inet_frag_kill(&ipq->q, &ip4_frags);
}
/* Memory limiting on fragments. Evictor trashes the oldest
@@ -243,33 +194,11 @@ static void ipq_kill(struct ipq *ipq)
*/
static void ip_evictor(void)
{
- struct ipq *qp;
- struct list_head *tmp;
- int work;
-
- work = atomic_read(&ip_frag_mem) - sysctl_ipfrag_low_thresh;
- if (work <= 0)
- return;
-
- while (work > 0) {
- read_lock(&ipfrag_lock);
- if (list_empty(&ipq_lru_list)) {
- read_unlock(&ipfrag_lock);
- return;
- }
- tmp = ipq_lru_list.next;
- qp = list_entry(tmp, struct ipq, lru_list);
- atomic_inc(&qp->refcnt);
- read_unlock(&ipfrag_lock);
-
- spin_lock(&qp->lock);
- if (!(qp->last_in&COMPLETE))
- ipq_kill(qp);
- spin_unlock(&qp->lock);
+ int evicted;
- ipq_put(qp, &work);
- IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
- }
+ evicted = inet_frag_evictor(&ip4_frags);
+ if (evicted)
+ IP_ADD_STATS_BH(IPSTATS_MIB_REASMFAILS, evicted);
}
/*
@@ -277,11 +206,13 @@ static void ip_evictor(void)
*/
static void ip_expire(unsigned long arg)
{
- struct ipq *qp = (struct ipq *) arg;
+ struct ipq *qp;
+
+ qp = container_of((struct inet_frag_queue *) arg, struct ipq, q);
- spin_lock(&qp->lock);
+ spin_lock(&qp->q.lock);
- if (qp->last_in & COMPLETE)
+ if (qp->q.last_in & COMPLETE)
goto out;
ipq_kill(qp);
@@ -289,8 +220,8 @@ static void ip_expire(unsigned long arg)
IP_INC_STATS_BH(IPSTATS_MIB_REASMTIMEOUT);
IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
- if ((qp->last_in&FIRST_IN) && qp->fragments != NULL) {
- struct sk_buff *head = qp->fragments;
+ if ((qp->q.last_in&FIRST_IN) && qp->q.fragments != NULL) {
+ struct sk_buff *head = qp->q.fragments;
/* Send an ICMP "Fragment Reassembly Timeout" message. */
if ((head->dev = dev_get_by_index(&init_net, qp->iif)) != NULL) {
icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0);
@@ -298,121 +229,34 @@ static void ip_expire(unsigned long arg)
}
}
out:
- spin_unlock(&qp->lock);
- ipq_put(qp, NULL);
+ spin_unlock(&qp->q.lock);
+ ipq_put(qp);
}
-/* Creation primitives. */
-
-static struct ipq *ip_frag_intern(struct ipq *qp_in)
+/* Find the correct entry in the "incomplete datagrams" queue for
+ * this IP datagram, and create new one, if nothing is found.
+ */
+static inline struct ipq *ip_find(struct iphdr *iph, u32 user)
{
- struct ipq *qp;
-#ifdef CONFIG_SMP
- struct hlist_node *n;
-#endif
+ struct inet_frag_queue *q;
+ struct ip4_create_arg arg;
unsigned int hash;
- write_lock(&ipfrag_lock);
- hash = ipqhashfn(qp_in->id, qp_in->saddr, qp_in->daddr,
- qp_in->protocol);
-#ifdef CONFIG_SMP
- /* With SMP race we have to recheck hash table, because
- * such entry could be created on other cpu, while we
- * promoted read lock to write lock.
- */
- hlist_for_each_entry(qp, n, &ipq_hash[hash], list) {
- if (qp->id == qp_in->id &&
- qp->saddr == qp_in->saddr &&
- qp->daddr == qp_in->daddr &&
- qp->protocol == qp_in->protocol &&
- qp->user == qp_in->user) {
- atomic_inc(&qp->refcnt);
- write_unlock(&ipfrag_lock);
- qp_in->last_in |= COMPLETE;
- ipq_put(qp_in, NULL);
- return qp;
- }
- }
-#endif
- qp = qp_in;
-
- if (!mod_timer(&qp->timer, jiffies + sysctl_ipfrag_time))
- atomic_inc(&qp->refcnt);
-
- atomic_inc(&qp->refcnt);
- hlist_add_head(&qp->list, &ipq_hash[hash]);
- INIT_LIST_HEAD(&qp->lru_list);
- list_add_tail(&qp->lru_list, &ipq_lru_list);
- ip_frag_nqueues++;
- write_unlock(&ipfrag_lock);
- return qp;
-}
-
-/* Add an entry to the 'ipq' queue for a newly received IP datagram. */
-static struct ipq *ip_frag_create(struct iphdr *iph, u32 user)
-{
- struct ipq *qp;
+ arg.iph = iph;
+ arg.user = user;
+ hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol);
- if ((qp = frag_alloc_queue()) == NULL)
+ q = inet_frag_find(&ip4_frags, &arg, hash);
+ if (q == NULL)
goto out_nomem;
- qp->protocol = iph->protocol;
- qp->last_in = 0;
- qp->id = iph->id;
- qp->saddr = iph->saddr;
- qp->daddr = iph->daddr;
- qp->user = user;
- qp->len = 0;
- qp->meat = 0;
- qp->fragments = NULL;
- qp->iif = 0;
- qp->peer = sysctl_ipfrag_max_dist ? inet_getpeer(iph->saddr, 1) : NULL;
-
- /* Initialize a timer for this entry. */
- init_timer(&qp->timer);
- qp->timer.data = (unsigned long) qp; /* pointer to queue */
- qp->timer.function = ip_expire; /* expire function */
- spin_lock_init(&qp->lock);
- atomic_set(&qp->refcnt, 1);
-
- return ip_frag_intern(qp);
+ return container_of(q, struct ipq, q);
out_nomem:
LIMIT_NETDEBUG(KERN_ERR "ip_frag_create: no memory left !\n");
return NULL;
}
-/* Find the correct entry in the "incomplete datagrams" queue for
- * this IP datagram, and create new one, if nothing is found.
- */
-static inline struct ipq *ip_find(struct iphdr *iph, u32 user)
-{
- __be16 id = iph->id;
- __be32 saddr = iph->saddr;
- __be32 daddr = iph->daddr;
- __u8 protocol = iph->protocol;
- unsigned int hash;
- struct ipq *qp;
- struct hlist_node *n;
-
- read_lock(&ipfrag_lock);
- hash = ipqhashfn(id, saddr, daddr, protocol);
- hlist_for_each_entry(qp, n, &ipq_hash[hash], list) {
- if (qp->id == id &&
- qp->saddr == saddr &&
- qp->daddr == daddr &&
- qp->protocol == protocol &&
- qp->user == user) {
- atomic_inc(&qp->refcnt);
- read_unlock(&ipfrag_lock);
- return qp;
- }
- }
- read_unlock(&ipfrag_lock);
-
- return ip_frag_create(iph, user);
-}
-
/* Is the fragment too far ahead to be part of ipq? */
static inline int ip_frag_too_far(struct ipq *qp)
{
@@ -429,7 +273,7 @@ static inline int ip_frag_too_far(struct ipq *qp)
end = atomic_inc_return(&peer->rid);
qp->rid = end;
- rc = qp->fragments && (end - start) > max;
+ rc = qp->q.fragments && (end - start) > max;
if (rc) {
IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
@@ -442,39 +286,42 @@ static int ip_frag_reinit(struct ipq *qp)
{
struct sk_buff *fp;
- if (!mod_timer(&qp->timer, jiffies + sysctl_ipfrag_time)) {
- atomic_inc(&qp->refcnt);
+ if (!mod_timer(&qp->q.timer, jiffies + ip4_frags_ctl.timeout)) {
+ atomic_inc(&qp->q.refcnt);
return -ETIMEDOUT;
}
- fp = qp->fragments;
+ fp = qp->q.fragments;
do {
struct sk_buff *xp = fp->next;
frag_kfree_skb(fp, NULL);
fp = xp;
} while (fp);
- qp->last_in = 0;
- qp->len = 0;
- qp->meat = 0;
- qp->fragments = NULL;
+ qp->q.last_in = 0;
+ qp->q.len = 0;
+ qp->q.meat = 0;
+ qp->q.fragments = NULL;
qp->iif = 0;
return 0;
}
/* Add new segment to existing queue. */
-static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
+static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
{
struct sk_buff *prev, *next;
+ struct net_device *dev;
int flags, offset;
int ihl, end;
+ int err = -ENOENT;
- if (qp->last_in & COMPLETE)
+ if (qp->q.last_in & COMPLETE)
goto err;
if (!(IPCB(skb)->flags & IPSKB_FRAG_COMPLETE) &&
- unlikely(ip_frag_too_far(qp)) && unlikely(ip_frag_reinit(qp))) {
+ unlikely(ip_frag_too_far(qp)) &&
+ unlikely(err = ip_frag_reinit(qp))) {
ipq_kill(qp);
goto err;
}
@@ -487,36 +334,40 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
/* Determine the position of this fragment. */
end = offset + skb->len - ihl;
+ err = -EINVAL;
/* Is this the final fragment? */
if ((flags & IP_MF) == 0) {
/* If we already have some bits beyond end
* or have different end, the segment is corrrupted.
*/
- if (end < qp->len ||
- ((qp->last_in & LAST_IN) && end != qp->len))
+ if (end < qp->q.len ||
+ ((qp->q.last_in & LAST_IN) && end != qp->q.len))
goto err;
- qp->last_in |= LAST_IN;
- qp->len = end;
+ qp->q.last_in |= LAST_IN;
+ qp->q.len = end;
} else {
if (end&7) {
end &= ~7;
if (skb->ip_summed != CHECKSUM_UNNECESSARY)
skb->ip_summed = CHECKSUM_NONE;
}
- if (end > qp->len) {
+ if (end > qp->q.len) {
/* Some bits beyond end -> corruption. */
- if (qp->last_in & LAST_IN)
+ if (qp->q.last_in & LAST_IN)
goto err;
- qp->len = end;
+ qp->q.len = end;
}
}
if (end == offset)
goto err;
+ err = -ENOMEM;
if (pskb_pull(skb, ihl) == NULL)
goto err;
- if (pskb_trim_rcsum(skb, end-offset))
+
+ err = pskb_trim_rcsum(skb, end - offset);
+ if (err)
goto err;
/* Find out which fragments are in front and at the back of us
@@ -524,7 +375,7 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
* this fragment, right?
*/
prev = NULL;
- for (next = qp->fragments; next != NULL; next = next->next) {
+ for (next = qp->q.fragments; next != NULL; next = next->next) {
if (FRAG_CB(next)->offset >= offset)
break; /* bingo! */
prev = next;
@@ -539,8 +390,10 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
if (i > 0) {
offset += i;
+ err = -EINVAL;
if (end <= offset)
goto err;
+ err = -ENOMEM;
if (!pskb_pull(skb, i))
goto err;
if (skb->ip_summed != CHECKSUM_UNNECESSARY)
@@ -548,6 +401,8 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
}
}
+ err = -ENOMEM;
+
while (next && FRAG_CB(next)->offset < end) {
int i = end - FRAG_CB(next)->offset; /* overlap is 'i' bytes */
@@ -558,7 +413,7 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
if (!pskb_pull(next, i))
goto err;
FRAG_CB(next)->offset += i;
- qp->meat -= i;
+ qp->q.meat -= i;
if (next->ip_summed != CHECKSUM_UNNECESSARY)
next->ip_summed = CHECKSUM_NONE;
break;
@@ -573,9 +428,9 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
if (prev)
prev->next = next;
else
- qp->fragments = next;
+ qp->q.fragments = next;
- qp->meat -= free_it->len;
+ qp->q.meat -= free_it->len;
frag_kfree_skb(free_it, NULL);
}
}
@@ -587,46 +442,71 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
if (prev)
prev->next = skb;
else
- qp->fragments = skb;
-
- if (skb->dev)
- qp->iif = skb->dev->ifindex;
- skb->dev = NULL;
- qp->stamp = skb->tstamp;
- qp->meat += skb->len;
- atomic_add(skb->truesize, &ip_frag_mem);
+ qp->q.fragments = skb;
+
+ dev = skb->dev;
+ if (dev) {
+ qp->iif = dev->ifindex;
+ skb->dev = NULL;
+ }
+ qp->q.stamp = skb->tstamp;
+ qp->q.meat += skb->len;
+ atomic_add(skb->truesize, &ip4_frags.mem);
if (offset == 0)
- qp->last_in |= FIRST_IN;
+ qp->q.last_in |= FIRST_IN;
- write_lock(&ipfrag_lock);
- list_move_tail(&qp->lru_list, &ipq_lru_list);
- write_unlock(&ipfrag_lock);
+ if (qp->q.last_in == (FIRST_IN | LAST_IN) && qp->q.meat == qp->q.len)
+ return ip_frag_reasm(qp, prev, dev);
- return;
+ write_lock(&ip4_frags.lock);
+ list_move_tail(&qp->q.lru_list, &ip4_frags.lru_list);
+ write_unlock(&ip4_frags.lock);
+ return -EINPROGRESS;
err:
kfree_skb(skb);
+ return err;
}
/* Build a new IP datagram from all its fragments. */
-static struct sk_buff *ip_frag_reasm(struct ipq *qp, struct net_device *dev)
+static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
+ struct net_device *dev)
{
struct iphdr *iph;
- struct sk_buff *fp, *head = qp->fragments;
+ struct sk_buff *fp, *head = qp->q.fragments;
int len;
int ihlen;
+ int err;
ipq_kill(qp);
+ /* Make the one we just received the head. */
+ if (prev) {
+ head = prev->next;
+ fp = skb_clone(head, GFP_ATOMIC);
+ if (!fp)
+ goto out_nomem;
+
+ fp->next = head->next;
+ prev->next = fp;
+
+ skb_morph(head, qp->q.fragments);
+ head->next = qp->q.fragments->next;
+
+ kfree_skb(qp->q.fragments);
+ qp->q.fragments = head;
+ }
+
BUG_TRAP(head != NULL);
BUG_TRAP(FRAG_CB(head)->offset == 0);
/* Allocate a new buffer for the datagram. */
ihlen = ip_hdrlen(head);
- len = ihlen + qp->len;
+ len = ihlen + qp->q.len;
+ err = -E2BIG;
if (len > 65535)
goto out_oversize;
@@ -654,12 +534,12 @@ static struct sk_buff *ip_frag_reasm(struct ipq *qp, struct net_device *dev)
head->len -= clone->len;
clone->csum = 0;
clone->ip_summed = head->ip_summed;
- atomic_add(clone->truesize, &ip_frag_mem);
+ atomic_add(clone->truesize, &ip4_frags.mem);
}
skb_shinfo(head)->frag_list = head->next;
skb_push(head, head->data - skb_network_header(head));
- atomic_sub(head->truesize, &ip_frag_mem);
+ atomic_sub(head->truesize, &ip4_frags.mem);
for (fp=head->next; fp; fp = fp->next) {
head->data_len += fp->len;
@@ -669,23 +549,24 @@ static struct sk_buff *ip_frag_reasm(struct ipq *qp, struct net_device *dev)
else if (head->ip_summed == CHECKSUM_COMPLETE)
head->csum = csum_add(head->csum, fp->csum);
head->truesize += fp->truesize;
- atomic_sub(fp->truesize, &ip_frag_mem);
+ atomic_sub(fp->truesize, &ip4_frags.mem);
}
head->next = NULL;
head->dev = dev;
- head->tstamp = qp->stamp;
+ head->tstamp = qp->q.stamp;
iph = ip_hdr(head);
iph->frag_off = 0;
iph->tot_len = htons(len);
IP_INC_STATS_BH(IPSTATS_MIB_REASMOKS);
- qp->fragments = NULL;
- return head;
+ qp->q.fragments = NULL;
+ return 0;
out_nomem:
LIMIT_NETDEBUG(KERN_ERR "IP: queue_glue: no memory for gluing "
"queue %p\n", qp);
+ err = -ENOMEM;
goto out_fail;
out_oversize:
if (net_ratelimit())
@@ -694,54 +575,49 @@ out_oversize:
NIPQUAD(qp->saddr));
out_fail:
IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
- return NULL;
+ return err;
}
/* Process an incoming IP datagram fragment. */
-struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user)
+int ip_defrag(struct sk_buff *skb, u32 user)
{
struct ipq *qp;
- struct net_device *dev;
IP_INC_STATS_BH(IPSTATS_MIB_REASMREQDS);
/* Start by cleaning up the memory. */
- if (atomic_read(&ip_frag_mem) > sysctl_ipfrag_high_thresh)
+ if (atomic_read(&ip4_frags.mem) > ip4_frags_ctl.high_thresh)
ip_evictor();
- dev = skb->dev;
-
/* Lookup (or create) queue header */
if ((qp = ip_find(ip_hdr(skb), user)) != NULL) {
- struct sk_buff *ret = NULL;
+ int ret;
- spin_lock(&qp->lock);
+ spin_lock(&qp->q.lock);
- ip_frag_queue(qp, skb);
+ ret = ip_frag_queue(qp, skb);
- if (qp->last_in == (FIRST_IN|LAST_IN) &&
- qp->meat == qp->len)
- ret = ip_frag_reasm(qp, dev);
-
- spin_unlock(&qp->lock);
- ipq_put(qp, NULL);
+ spin_unlock(&qp->q.lock);
+ ipq_put(qp);
return ret;
}
IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
kfree_skb(skb);
- return NULL;
+ return -ENOMEM;
}
void __init ipfrag_init(void)
{
- ipfrag_hash_rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^
- (jiffies ^ (jiffies >> 6)));
-
- init_timer(&ipfrag_secret_timer);
- ipfrag_secret_timer.function = ipfrag_secret_rebuild;
- ipfrag_secret_timer.expires = jiffies + sysctl_ipfrag_secret_interval;
- add_timer(&ipfrag_secret_timer);
+ ip4_frags.ctl = &ip4_frags_ctl;
+ ip4_frags.hashfn = ip4_hashfn;
+ ip4_frags.constructor = ip4_frag_init;
+ ip4_frags.destructor = ip4_frag_free;
+ ip4_frags.skb_free = NULL;
+ ip4_frags.qsize = sizeof(struct ipq);
+ ip4_frags.match = ip4_frag_match;
+ ip4_frags.frag_expire = ip_expire;
+ inet_frags_init(&ip4_frags);
}
EXPORT_SYMBOL(ip_defrag);
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index f151900efaf9..02b02a8d681c 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -674,7 +674,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
struct rtable *rt; /* Route to the other host */
struct net_device *tdev; /* Device to other host */
struct iphdr *iph; /* Our new IP header */
- int max_headroom; /* The extra header space needed */
+ unsigned int max_headroom; /* The extra header space needed */
int gre_hlen;
__be32 dst;
int mtu;
@@ -1033,7 +1033,6 @@ static int ipgre_tunnel_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
-#ifdef CONFIG_NET_IPGRE_BROADCAST
/* Nice toy. Unfortunately, useless in real life :-)
It allows to construct virtual multiprotocol broadcast "LAN"
over the Internet, provided multicast routing is tuned.
@@ -1092,10 +1091,19 @@ static int ipgre_header(struct sk_buff *skb, struct net_device *dev,
return -t->hlen;
}
+static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr)
+{
+ struct iphdr *iph = (struct iphdr*) skb_mac_header(skb);
+ memcpy(haddr, &iph->saddr, 4);
+ return 4;
+}
+
static const struct header_ops ipgre_header_ops = {
.create = ipgre_header,
+ .parse = ipgre_header_parse,
};
+#ifdef CONFIG_NET_IPGRE_BROADCAST
static int ipgre_open(struct net_device *dev)
{
struct ip_tunnel *t = netdev_priv(dev);
@@ -1197,6 +1205,8 @@ static int ipgre_tunnel_init(struct net_device *dev)
dev->stop = ipgre_close;
}
#endif
+ } else {
+ dev->header_ops = &ipgre_header_ops;
}
if (!tdev && tunnel->parms.link)
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 41d8964591e7..168c871fcd79 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -172,8 +172,7 @@ int ip_call_ra_chain(struct sk_buff *skb)
(!sk->sk_bound_dev_if ||
sk->sk_bound_dev_if == skb->dev->ifindex)) {
if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
- skb = ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN);
- if (skb == NULL) {
+ if (ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN)) {
read_unlock(&ip_ra_lock);
return 1;
}
@@ -196,7 +195,7 @@ int ip_call_ra_chain(struct sk_buff *skb)
return 0;
}
-static inline int ip_local_deliver_finish(struct sk_buff *skb)
+static int ip_local_deliver_finish(struct sk_buff *skb)
{
__skb_pull(skb, ip_hdrlen(skb));
@@ -265,8 +264,7 @@ int ip_local_deliver(struct sk_buff *skb)
*/
if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
- skb = ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER);
- if (!skb)
+ if (ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER))
return 0;
}
@@ -326,7 +324,7 @@ drop:
return -1;
}
-static inline int ip_rcv_finish(struct sk_buff *skb)
+static int ip_rcv_finish(struct sk_buff *skb)
{
const struct iphdr *iph = ip_hdr(skb);
struct rtable *rt;
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 699f06781fd8..fd99fbd685ea 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -161,7 +161,7 @@ static inline int ip_finish_output2(struct sk_buff *skb)
struct dst_entry *dst = skb->dst;
struct rtable *rt = (struct rtable *)dst;
struct net_device *dev = dst->dev;
- int hh_len = LL_RESERVED_SPACE(dev);
+ unsigned int hh_len = LL_RESERVED_SPACE(dev);
if (rt->rt_type == RTN_MULTICAST)
IP_INC_STATS(IPSTATS_MIB_OUTMCASTPKTS);
@@ -202,7 +202,7 @@ static inline int ip_skb_dst_mtu(struct sk_buff *skb)
skb->dst->dev->mtu : dst_mtu(skb->dst);
}
-static inline int ip_finish_output(struct sk_buff *skb)
+static int ip_finish_output(struct sk_buff *skb)
{
#if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM)
/* Policy lookup after SNAT yielded a new policy */
@@ -1183,6 +1183,17 @@ error:
return err;
}
+static void ip_cork_release(struct inet_sock *inet)
+{
+ inet->cork.flags &= ~IPCORK_OPT;
+ kfree(inet->cork.opt);
+ inet->cork.opt = NULL;
+ if (inet->cork.rt) {
+ ip_rt_put(inet->cork.rt);
+ inet->cork.rt = NULL;
+ }
+}
+
/*
* Combined all pending IP fragments on the socket as one IP datagram
* and push them out.
@@ -1276,13 +1287,7 @@ int ip_push_pending_frames(struct sock *sk)
}
out:
- inet->cork.flags &= ~IPCORK_OPT;
- kfree(inet->cork.opt);
- inet->cork.opt = NULL;
- if (inet->cork.rt) {
- ip_rt_put(inet->cork.rt);
- inet->cork.rt = NULL;
- }
+ ip_cork_release(inet);
return err;
error:
@@ -1295,19 +1300,12 @@ error:
*/
void ip_flush_pending_frames(struct sock *sk)
{
- struct inet_sock *inet = inet_sk(sk);
struct sk_buff *skb;
while ((skb = __skb_dequeue_tail(&sk->sk_write_queue)) != NULL)
kfree_skb(skb);
- inet->cork.flags &= ~IPCORK_OPT;
- kfree(inet->cork.opt);
- inet->cork.opt = NULL;
- if (inet->cork.rt) {
- ip_rt_put(inet->cork.rt);
- inet->cork.rt = NULL;
- }
+ ip_cork_release(inet_sk(sk));
}
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index f51f20e487c8..82817e554363 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -437,10 +437,8 @@ static int do_ip_setsockopt(struct sock *sk, int level,
/* If optlen==0, it is equivalent to val == 0 */
-#ifdef CONFIG_IP_MROUTE
- if (optname >= MRT_BASE && optname <= (MRT_BASE + 10))
+ if (ip_mroute_opt(optname))
return ip_mroute_setsockopt(sk,optname,optval,optlen);
-#endif
err = 0;
lock_sock(sk);
@@ -909,11 +907,9 @@ int ip_setsockopt(struct sock *sk, int level,
#ifdef CONFIG_NETFILTER
/* we need to exclude all possible ENOPROTOOPTs except default case */
if (err == -ENOPROTOOPT && optname != IP_HDRINCL &&
- optname != IP_IPSEC_POLICY && optname != IP_XFRM_POLICY
-#ifdef CONFIG_IP_MROUTE
- && (optname < MRT_BASE || optname > (MRT_BASE + 10))
-#endif
- ) {
+ optname != IP_IPSEC_POLICY &&
+ optname != IP_XFRM_POLICY &&
+ !ip_mroute_opt(optname)) {
lock_sock(sk);
err = nf_setsockopt(sk, PF_INET, optname, optval, optlen);
release_sock(sk);
@@ -935,11 +931,9 @@ int compat_ip_setsockopt(struct sock *sk, int level, int optname,
#ifdef CONFIG_NETFILTER
/* we need to exclude all possible ENOPROTOOPTs except default case */
if (err == -ENOPROTOOPT && optname != IP_HDRINCL &&
- optname != IP_IPSEC_POLICY && optname != IP_XFRM_POLICY
-#ifdef CONFIG_IP_MROUTE
- && (optname < MRT_BASE || optname > (MRT_BASE + 10))
-#endif
- ) {
+ optname != IP_IPSEC_POLICY &&
+ optname != IP_XFRM_POLICY &&
+ !ip_mroute_opt(optname)) {
lock_sock(sk);
err = compat_nf_setsockopt(sk, PF_INET, optname,
optval, optlen);
@@ -967,11 +961,8 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname,
if (level != SOL_IP)
return -EOPNOTSUPP;
-#ifdef CONFIG_IP_MROUTE
- if (optname >= MRT_BASE && optname <= MRT_BASE+10) {
+ if (ip_mroute_opt(optname))
return ip_mroute_getsockopt(sk,optname,optval,optlen);
- }
-#endif
if (get_user(len,optlen))
return -EFAULT;
@@ -1171,11 +1162,8 @@ int ip_getsockopt(struct sock *sk, int level,
err = do_ip_getsockopt(sk, level, optname, optval, optlen);
#ifdef CONFIG_NETFILTER
/* we need to exclude all possible ENOPROTOOPTs except default case */
- if (err == -ENOPROTOOPT && optname != IP_PKTOPTIONS
-#ifdef CONFIG_IP_MROUTE
- && (optname < MRT_BASE || optname > MRT_BASE+10)
-#endif
- ) {
+ if (err == -ENOPROTOOPT && optname != IP_PKTOPTIONS &&
+ !ip_mroute_opt(optname)) {
int len;
if (get_user(len,optlen))
@@ -1200,11 +1188,8 @@ int compat_ip_getsockopt(struct sock *sk, int level, int optname,
int err = do_ip_getsockopt(sk, level, optname, optval, optlen);
#ifdef CONFIG_NETFILTER
/* we need to exclude all possible ENOPROTOOPTs except default case */
- if (err == -ENOPROTOOPT && optname != IP_PKTOPTIONS
-#ifdef CONFIG_IP_MROUTE
- && (optname < MRT_BASE || optname > MRT_BASE+10)
-#endif
- ) {
+ if (err == -ENOPROTOOPT && optname != IP_PKTOPTIONS &&
+ !ip_mroute_opt(optname)) {
int len;
if (get_user(len, optlen))
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index 0bfeb02a5f87..2c44a94c2135 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -14,9 +14,9 @@
* - Adaptive compression.
*/
#include <linux/module.h>
-#include <asm/scatterlist.h>
#include <asm/semaphore.h>
#include <linux/crypto.h>
+#include <linux/err.h>
#include <linux/pfkeyv2.h>
#include <linux/percpu.h>
#include <linux/smp.h>
@@ -345,7 +345,7 @@ static struct crypto_comp **ipcomp_alloc_tfms(const char *alg_name)
for_each_possible_cpu(cpu) {
struct crypto_comp *tfm = crypto_alloc_comp(alg_name, 0,
CRYPTO_ALG_ASYNC);
- if (!tfm)
+ if (IS_ERR(tfm))
goto error;
*per_cpu_ptr(tfms, cpu) = tfm;
}
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 5cd5bbe1379a..8c2b2b0741da 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -515,7 +515,7 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
struct net_device *tdev; /* Device to other host */
struct iphdr *old_iph = ip_hdr(skb);
struct iphdr *iph; /* Our new IP header */
- int max_headroom; /* The extra header space needed */
+ unsigned int max_headroom; /* The extra header space needed */
__be32 dst = tiph->daddr;
int mtu;
diff --git a/net/ipv4/ipvs/ip_vs_app.c b/net/ipv4/ipvs/ip_vs_app.c
index 341474eefa55..664cb8e97c1c 100644
--- a/net/ipv4/ipvs/ip_vs_app.c
+++ b/net/ipv4/ipvs/ip_vs_app.c
@@ -25,6 +25,7 @@
#include <linux/skbuff.h>
#include <linux/in.h>
#include <linux/ip.h>
+#include <linux/netfilter.h>
#include <net/net_namespace.h>
#include <net/protocol.h>
#include <net/tcp.h>
@@ -328,18 +329,18 @@ static inline void vs_seq_update(struct ip_vs_conn *cp, struct ip_vs_seq *vseq,
spin_unlock(&cp->lock);
}
-static inline int app_tcp_pkt_out(struct ip_vs_conn *cp, struct sk_buff **pskb,
+static inline int app_tcp_pkt_out(struct ip_vs_conn *cp, struct sk_buff *skb,
struct ip_vs_app *app)
{
int diff;
- const unsigned int tcp_offset = ip_hdrlen(*pskb);
+ const unsigned int tcp_offset = ip_hdrlen(skb);
struct tcphdr *th;
__u32 seq;
- if (!ip_vs_make_skb_writable(pskb, tcp_offset + sizeof(*th)))
+ if (!skb_make_writable(skb, tcp_offset + sizeof(*th)))
return 0;
- th = (struct tcphdr *)(skb_network_header(*pskb) + tcp_offset);
+ th = (struct tcphdr *)(skb_network_header(skb) + tcp_offset);
/*
* Remember seq number in case this pkt gets resized
@@ -360,7 +361,7 @@ static inline int app_tcp_pkt_out(struct ip_vs_conn *cp, struct sk_buff **pskb,
if (app->pkt_out == NULL)
return 1;
- if (!app->pkt_out(app, cp, pskb, &diff))
+ if (!app->pkt_out(app, cp, skb, &diff))
return 0;
/*
@@ -378,7 +379,7 @@ static inline int app_tcp_pkt_out(struct ip_vs_conn *cp, struct sk_buff **pskb,
* called by ipvs packet handler, assumes previously checked cp!=NULL
* returns false if it can't handle packet (oom)
*/
-int ip_vs_app_pkt_out(struct ip_vs_conn *cp, struct sk_buff **pskb)
+int ip_vs_app_pkt_out(struct ip_vs_conn *cp, struct sk_buff *skb)
{
struct ip_vs_app *app;
@@ -391,7 +392,7 @@ int ip_vs_app_pkt_out(struct ip_vs_conn *cp, struct sk_buff **pskb)
/* TCP is complicated */
if (cp->protocol == IPPROTO_TCP)
- return app_tcp_pkt_out(cp, pskb, app);
+ return app_tcp_pkt_out(cp, skb, app);
/*
* Call private output hook function
@@ -399,22 +400,22 @@ int ip_vs_app_pkt_out(struct ip_vs_conn *cp, struct sk_buff **pskb)
if (app->pkt_out == NULL)
return 1;
- return app->pkt_out(app, cp, pskb, NULL);
+ return app->pkt_out(app, cp, skb, NULL);
}
-static inline int app_tcp_pkt_in(struct ip_vs_conn *cp, struct sk_buff **pskb,
+static inline int app_tcp_pkt_in(struct ip_vs_conn *cp, struct sk_buff *skb,
struct ip_vs_app *app)
{
int diff;
- const unsigned int tcp_offset = ip_hdrlen(*pskb);
+ const unsigned int tcp_offset = ip_hdrlen(skb);
struct tcphdr *th;
__u32 seq;
- if (!ip_vs_make_skb_writable(pskb, tcp_offset + sizeof(*th)))
+ if (!skb_make_writable(skb, tcp_offset + sizeof(*th)))
return 0;
- th = (struct tcphdr *)(skb_network_header(*pskb) + tcp_offset);
+ th = (struct tcphdr *)(skb_network_header(skb) + tcp_offset);
/*
* Remember seq number in case this pkt gets resized
@@ -435,7 +436,7 @@ static inline int app_tcp_pkt_in(struct ip_vs_conn *cp, struct sk_buff **pskb,
if (app->pkt_in == NULL)
return 1;
- if (!app->pkt_in(app, cp, pskb, &diff))
+ if (!app->pkt_in(app, cp, skb, &diff))
return 0;
/*
@@ -453,7 +454,7 @@ static inline int app_tcp_pkt_in(struct ip_vs_conn *cp, struct sk_buff **pskb,
* called by ipvs packet handler, assumes previously checked cp!=NULL.
* returns false if can't handle packet (oom).
*/
-int ip_vs_app_pkt_in(struct ip_vs_conn *cp, struct sk_buff **pskb)
+int ip_vs_app_pkt_in(struct ip_vs_conn *cp, struct sk_buff *skb)
{
struct ip_vs_app *app;
@@ -466,7 +467,7 @@ int ip_vs_app_pkt_in(struct ip_vs_conn *cp, struct sk_buff **pskb)
/* TCP is complicated */
if (cp->protocol == IPPROTO_TCP)
- return app_tcp_pkt_in(cp, pskb, app);
+ return app_tcp_pkt_in(cp, skb, app);
/*
* Call private input hook function
@@ -474,7 +475,7 @@ int ip_vs_app_pkt_in(struct ip_vs_conn *cp, struct sk_buff **pskb)
if (app->pkt_in == NULL)
return 1;
- return app->pkt_in(app, cp, pskb, NULL);
+ return app->pkt_in(app, cp, skb, NULL);
}
diff --git a/net/ipv4/ipvs/ip_vs_conn.c b/net/ipv4/ipvs/ip_vs_conn.c
index 4b702f708d30..0a9f3c37e18d 100644
--- a/net/ipv4/ipvs/ip_vs_conn.c
+++ b/net/ipv4/ipvs/ip_vs_conn.c
@@ -426,6 +426,24 @@ ip_vs_bind_dest(struct ip_vs_conn *cp, struct ip_vs_dest *dest)
/*
+ * Check if there is a destination for the connection, if so
+ * bind the connection to the destination.
+ */
+struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp)
+{
+ struct ip_vs_dest *dest;
+
+ if ((cp) && (!cp->dest)) {
+ dest = ip_vs_find_dest(cp->daddr, cp->dport,
+ cp->vaddr, cp->vport, cp->protocol);
+ ip_vs_bind_dest(cp, dest);
+ return dest;
+ } else
+ return NULL;
+}
+
+
+/*
* Unbind a connection entry with its VS destination
* Called by the ip_vs_conn_expire function.
*/
diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c
index fbca2a2ff29f..20c884a57721 100644
--- a/net/ipv4/ipvs/ip_vs_core.c
+++ b/net/ipv4/ipvs/ip_vs_core.c
@@ -58,7 +58,6 @@ EXPORT_SYMBOL(ip_vs_conn_put);
#ifdef CONFIG_IP_VS_DEBUG
EXPORT_SYMBOL(ip_vs_get_debug_level);
#endif
-EXPORT_SYMBOL(ip_vs_make_skb_writable);
/* ID used in ICMP lookups */
@@ -163,42 +162,6 @@ ip_vs_set_state(struct ip_vs_conn *cp, int direction,
}
-int ip_vs_make_skb_writable(struct sk_buff **pskb, int writable_len)
-{
- struct sk_buff *skb = *pskb;
-
- /* skb is already used, better copy skb and its payload */
- if (unlikely(skb_shared(skb) || skb->sk))
- goto copy_skb;
-
- /* skb data is already used, copy it */
- if (unlikely(skb_cloned(skb)))
- goto copy_data;
-
- return pskb_may_pull(skb, writable_len);
-
- copy_data:
- if (unlikely(writable_len > skb->len))
- return 0;
- return !pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
-
- copy_skb:
- if (unlikely(writable_len > skb->len))
- return 0;
- skb = skb_copy(skb, GFP_ATOMIC);
- if (!skb)
- return 0;
- BUG_ON(skb_is_nonlinear(skb));
-
- /* Rest of kernel will get very unhappy if we pass it a
- suddenly-orphaned skbuff */
- if ((*pskb)->sk)
- skb_set_owner_w(skb, (*pskb)->sk);
- kfree_skb(*pskb);
- *pskb = skb;
- return 1;
-}
-
/*
* IPVS persistent scheduling function
* It creates a connection entry according to its template if exists,
@@ -525,12 +488,12 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
* for VS/NAT.
*/
static unsigned int ip_vs_post_routing(unsigned int hooknum,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
- if (!((*pskb)->ipvs_property))
+ if (!skb->ipvs_property)
return NF_ACCEPT;
/* The packet was sent from IPVS, exit this chain */
return NF_STOP;
@@ -541,13 +504,14 @@ __sum16 ip_vs_checksum_complete(struct sk_buff *skb, int offset)
return csum_fold(skb_checksum(skb, offset, skb->len - offset, 0));
}
-static inline struct sk_buff *
-ip_vs_gather_frags(struct sk_buff *skb, u_int32_t user)
+static inline int ip_vs_gather_frags(struct sk_buff *skb, u_int32_t user)
{
- skb = ip_defrag(skb, user);
- if (skb)
+ int err = ip_defrag(skb, user);
+
+ if (!err)
ip_send_check(ip_hdr(skb));
- return skb;
+
+ return err;
}
/*
@@ -605,9 +569,8 @@ void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp,
* Currently handles error types - unreachable, quench, ttl exceeded.
* (Only used in VS/NAT)
*/
-static int ip_vs_out_icmp(struct sk_buff **pskb, int *related)
+static int ip_vs_out_icmp(struct sk_buff *skb, int *related)
{
- struct sk_buff *skb = *pskb;
struct iphdr *iph;
struct icmphdr _icmph, *ic;
struct iphdr _ciph, *cih; /* The ip header contained within the ICMP */
@@ -619,10 +582,8 @@ static int ip_vs_out_icmp(struct sk_buff **pskb, int *related)
/* reassemble IP fragments */
if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
- skb = ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT);
- if (!skb)
+ if (ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT))
return NF_STOLEN;
- *pskb = skb;
}
iph = ip_hdr(skb);
@@ -690,9 +651,8 @@ static int ip_vs_out_icmp(struct sk_buff **pskb, int *related)
if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol)
offset += 2 * sizeof(__u16);
- if (!ip_vs_make_skb_writable(pskb, offset))
+ if (!skb_make_writable(skb, offset))
goto out;
- skb = *pskb;
ip_vs_nat_icmp(skb, pp, cp, 1);
@@ -724,11 +684,10 @@ static inline int is_tcp_reset(const struct sk_buff *skb)
* rewrite addresses of the packet and send it on its way...
*/
static unsigned int
-ip_vs_out(unsigned int hooknum, struct sk_buff **pskb,
+ip_vs_out(unsigned int hooknum, struct sk_buff *skb,
const struct net_device *in, const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
- struct sk_buff *skb = *pskb;
struct iphdr *iph;
struct ip_vs_protocol *pp;
struct ip_vs_conn *cp;
@@ -741,11 +700,10 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb,
iph = ip_hdr(skb);
if (unlikely(iph->protocol == IPPROTO_ICMP)) {
- int related, verdict = ip_vs_out_icmp(pskb, &related);
+ int related, verdict = ip_vs_out_icmp(skb, &related);
if (related)
return verdict;
- skb = *pskb;
iph = ip_hdr(skb);
}
@@ -756,11 +714,9 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb,
/* reassemble IP fragments */
if (unlikely(iph->frag_off & htons(IP_MF|IP_OFFSET) &&
!pp->dont_defrag)) {
- skb = ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT);
- if (!skb)
+ if (ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT))
return NF_STOLEN;
iph = ip_hdr(skb);
- *pskb = skb;
}
ihl = iph->ihl << 2;
@@ -802,13 +758,12 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb,
IP_VS_DBG_PKT(11, pp, skb, 0, "Outgoing packet");
- if (!ip_vs_make_skb_writable(pskb, ihl))
+ if (!skb_make_writable(skb, ihl))
goto drop;
/* mangle the packet */
- if (pp->snat_handler && !pp->snat_handler(pskb, pp, cp))
+ if (pp->snat_handler && !pp->snat_handler(skb, pp, cp))
goto drop;
- skb = *pskb;
ip_hdr(skb)->saddr = cp->vaddr;
ip_send_check(ip_hdr(skb));
@@ -818,9 +773,8 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb,
* if it came from this machine itself. So re-compute
* the routing information.
*/
- if (ip_route_me_harder(pskb, RTN_LOCAL) != 0)
+ if (ip_route_me_harder(skb, RTN_LOCAL) != 0)
goto drop;
- skb = *pskb;
IP_VS_DBG_PKT(10, pp, skb, 0, "After SNAT");
@@ -835,7 +789,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb,
drop:
ip_vs_conn_put(cp);
- kfree_skb(*pskb);
+ kfree_skb(skb);
return NF_STOLEN;
}
@@ -847,9 +801,8 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb,
* Currently handles error types - unreachable, quench, ttl exceeded.
*/
static int
-ip_vs_in_icmp(struct sk_buff **pskb, int *related, unsigned int hooknum)
+ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum)
{
- struct sk_buff *skb = *pskb;
struct iphdr *iph;
struct icmphdr _icmph, *ic;
struct iphdr _ciph, *cih; /* The ip header contained within the ICMP */
@@ -861,12 +814,9 @@ ip_vs_in_icmp(struct sk_buff **pskb, int *related, unsigned int hooknum)
/* reassemble IP fragments */
if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
- skb = ip_vs_gather_frags(skb,
- hooknum == NF_IP_LOCAL_IN ?
- IP_DEFRAG_VS_IN : IP_DEFRAG_VS_FWD);
- if (!skb)
+ if (ip_vs_gather_frags(skb, hooknum == NF_IP_LOCAL_IN ?
+ IP_DEFRAG_VS_IN : IP_DEFRAG_VS_FWD))
return NF_STOLEN;
- *pskb = skb;
}
iph = ip_hdr(skb);
@@ -945,11 +895,10 @@ ip_vs_in_icmp(struct sk_buff **pskb, int *related, unsigned int hooknum)
* and send it on its way...
*/
static unsigned int
-ip_vs_in(unsigned int hooknum, struct sk_buff **pskb,
+ip_vs_in(unsigned int hooknum, struct sk_buff *skb,
const struct net_device *in, const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
- struct sk_buff *skb = *pskb;
struct iphdr *iph;
struct ip_vs_protocol *pp;
struct ip_vs_conn *cp;
@@ -971,11 +920,10 @@ ip_vs_in(unsigned int hooknum, struct sk_buff **pskb,
iph = ip_hdr(skb);
if (unlikely(iph->protocol == IPPROTO_ICMP)) {
- int related, verdict = ip_vs_in_icmp(pskb, &related, hooknum);
+ int related, verdict = ip_vs_in_icmp(skb, &related, hooknum);
if (related)
return verdict;
- skb = *pskb;
iph = ip_hdr(skb);
}
@@ -1031,15 +979,23 @@ ip_vs_in(unsigned int hooknum, struct sk_buff **pskb,
ret = NF_ACCEPT;
}
- /* increase its packet counter and check if it is needed
- to be synchronized */
+ /* Increase its packet counter and check if it is needed
+ * to be synchronized
+ *
+ * Sync connection if it is about to close to
+ * encorage the standby servers to update the connections timeout
+ */
atomic_inc(&cp->in_pkts);
if ((ip_vs_sync_state & IP_VS_STATE_MASTER) &&
- (cp->protocol != IPPROTO_TCP ||
- cp->state == IP_VS_TCP_S_ESTABLISHED) &&
- (atomic_read(&cp->in_pkts) % sysctl_ip_vs_sync_threshold[1]
- == sysctl_ip_vs_sync_threshold[0]))
+ (((cp->protocol != IPPROTO_TCP ||
+ cp->state == IP_VS_TCP_S_ESTABLISHED) &&
+ (atomic_read(&cp->in_pkts) % sysctl_ip_vs_sync_threshold[1]
+ == sysctl_ip_vs_sync_threshold[0])) ||
+ ((cp->protocol == IPPROTO_TCP) && (cp->old_state != cp->state) &&
+ ((cp->state == IP_VS_TCP_S_FIN_WAIT) ||
+ (cp->state == IP_VS_TCP_S_CLOSE)))))
ip_vs_sync_conn(cp);
+ cp->old_state = cp->state;
ip_vs_conn_put(cp);
return ret;
@@ -1056,16 +1012,16 @@ ip_vs_in(unsigned int hooknum, struct sk_buff **pskb,
* and send them to ip_vs_in_icmp.
*/
static unsigned int
-ip_vs_forward_icmp(unsigned int hooknum, struct sk_buff **pskb,
+ip_vs_forward_icmp(unsigned int hooknum, struct sk_buff *skb,
const struct net_device *in, const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
int r;
- if (ip_hdr(*pskb)->protocol != IPPROTO_ICMP)
+ if (ip_hdr(skb)->protocol != IPPROTO_ICMP)
return NF_ACCEPT;
- return ip_vs_in_icmp(pskb, &r, hooknum);
+ return ip_vs_in_icmp(skb, &r, hooknum);
}
diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c
index 7345fc252a23..b64cf45a9ead 100644
--- a/net/ipv4/ipvs/ip_vs_ctl.c
+++ b/net/ipv4/ipvs/ip_vs_ctl.c
@@ -579,6 +579,31 @@ ip_vs_lookup_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport)
return NULL;
}
+/*
+ * Find destination by {daddr,dport,vaddr,protocol}
+ * Cretaed to be used in ip_vs_process_message() in
+ * the backup synchronization daemon. It finds the
+ * destination to be bound to the received connection
+ * on the backup.
+ *
+ * ip_vs_lookup_real_service() looked promissing, but
+ * seems not working as expected.
+ */
+struct ip_vs_dest *ip_vs_find_dest(__be32 daddr, __be16 dport,
+ __be32 vaddr, __be16 vport, __u16 protocol)
+{
+ struct ip_vs_dest *dest;
+ struct ip_vs_service *svc;
+
+ svc = ip_vs_service_get(0, protocol, vaddr, vport);
+ if (!svc)
+ return NULL;
+ dest = ip_vs_lookup_dest(svc, daddr, dport);
+ if (dest)
+ atomic_inc(&dest->refcnt);
+ ip_vs_service_put(svc);
+ return dest;
+}
/*
* Lookup dest by {svc,addr,port} in the destination trash.
diff --git a/net/ipv4/ipvs/ip_vs_ftp.c b/net/ipv4/ipvs/ip_vs_ftp.c
index 344ddbbdc756..59aa166b7678 100644
--- a/net/ipv4/ipvs/ip_vs_ftp.c
+++ b/net/ipv4/ipvs/ip_vs_ftp.c
@@ -30,6 +30,7 @@
#include <linux/skbuff.h>
#include <linux/in.h>
#include <linux/ip.h>
+#include <linux/netfilter.h>
#include <net/protocol.h>
#include <net/tcp.h>
#include <asm/unaligned.h>
@@ -135,7 +136,7 @@ static int ip_vs_ftp_get_addrport(char *data, char *data_limit,
* xxx,xxx,xxx,xxx is the server address, ppp,ppp is the server port number.
*/
static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp,
- struct sk_buff **pskb, int *diff)
+ struct sk_buff *skb, int *diff)
{
struct iphdr *iph;
struct tcphdr *th;
@@ -155,14 +156,14 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp,
return 1;
/* Linear packets are much easier to deal with. */
- if (!ip_vs_make_skb_writable(pskb, (*pskb)->len))
+ if (!skb_make_writable(skb, skb->len))
return 0;
if (cp->app_data == &ip_vs_ftp_pasv) {
- iph = ip_hdr(*pskb);
+ iph = ip_hdr(skb);
th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
data = (char *)th + (th->doff << 2);
- data_limit = skb_tail_pointer(*pskb);
+ data_limit = skb_tail_pointer(skb);
if (ip_vs_ftp_get_addrport(data, data_limit,
SERVER_STRING,
@@ -213,7 +214,7 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp,
memcpy(start, buf, buf_len);
ret = 1;
} else {
- ret = !ip_vs_skb_replace(*pskb, GFP_ATOMIC, start,
+ ret = !ip_vs_skb_replace(skb, GFP_ATOMIC, start,
end-start, buf, buf_len);
}
@@ -238,7 +239,7 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp,
* the client.
*/
static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp,
- struct sk_buff **pskb, int *diff)
+ struct sk_buff *skb, int *diff)
{
struct iphdr *iph;
struct tcphdr *th;
@@ -256,20 +257,20 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp,
return 1;
/* Linear packets are much easier to deal with. */
- if (!ip_vs_make_skb_writable(pskb, (*pskb)->len))
+ if (!skb_make_writable(skb, skb->len))
return 0;
/*
* Detecting whether it is passive
*/
- iph = ip_hdr(*pskb);
+ iph = ip_hdr(skb);
th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
/* Since there may be OPTIONS in the TCP packet and the HLEN is
the length of the header in 32-bit multiples, it is accurate
to calculate data address by th+HLEN*4 */
data = data_start = (char *)th + (th->doff << 2);
- data_limit = skb_tail_pointer(*pskb);
+ data_limit = skb_tail_pointer(skb);
while (data <= data_limit - 6) {
if (strnicmp(data, "PASV\r\n", 6) == 0) {
diff --git a/net/ipv4/ipvs/ip_vs_lblcr.c b/net/ipv4/ipvs/ip_vs_lblcr.c
index 6a1fec416eaf..427b593c1069 100644
--- a/net/ipv4/ipvs/ip_vs_lblcr.c
+++ b/net/ipv4/ipvs/ip_vs_lblcr.c
@@ -48,8 +48,6 @@
/* for sysctl */
#include <linux/fs.h>
#include <linux/sysctl.h>
-/* for proc_net_create/proc_net_remove */
-#include <linux/proc_fs.h>
#include <net/net_namespace.h>
#include <net/ip_vs.h>
@@ -547,71 +545,6 @@ static void ip_vs_lblcr_check_expire(unsigned long data)
mod_timer(&tbl->periodic_timer, jiffies+CHECK_EXPIRE_INTERVAL);
}
-
-#ifdef CONFIG_IP_VS_LBLCR_DEBUG
-static struct ip_vs_lblcr_table *lblcr_table_list;
-
-/*
- * /proc/net/ip_vs_lblcr to display the mappings of
- * destination IP address <==> its serverSet
- */
-static int
-ip_vs_lblcr_getinfo(char *buffer, char **start, off_t offset, int length)
-{
- off_t pos=0, begin;
- int len=0, size;
- struct ip_vs_lblcr_table *tbl;
- unsigned long now = jiffies;
- int i;
- struct ip_vs_lblcr_entry *en;
-
- tbl = lblcr_table_list;
-
- size = sprintf(buffer, "LastTime Dest IP address Server set\n");
- pos += size;
- len += size;
-
- for (i=0; i<IP_VS_LBLCR_TAB_SIZE; i++) {
- read_lock_bh(&tbl->lock);
- list_for_each_entry(en, &tbl->bucket[i], list) {
- char tbuf[16];
- struct ip_vs_dest_list *d;
-
- sprintf(tbuf, "%u.%u.%u.%u", NIPQUAD(en->addr));
- size = sprintf(buffer+len, "%8lu %-16s ",
- now-en->lastuse, tbuf);
-
- read_lock(&en->set.lock);
- for (d=en->set.list; d!=NULL; d=d->next) {
- size += sprintf(buffer+len+size,
- "%u.%u.%u.%u ",
- NIPQUAD(d->dest->addr));
- }
- read_unlock(&en->set.lock);
- size += sprintf(buffer+len+size, "\n");
- len += size;
- pos += size;
- if (pos <= offset)
- len=0;
- if (pos >= offset+length) {
- read_unlock_bh(&tbl->lock);
- goto done;
- }
- }
- read_unlock_bh(&tbl->lock);
- }
-
- done:
- begin = len - (pos - offset);
- *start = buffer + begin;
- len -= begin;
- if(len>length)
- len = length;
- return len;
-}
-#endif
-
-
static int ip_vs_lblcr_init_svc(struct ip_vs_service *svc)
{
int i;
@@ -650,9 +583,6 @@ static int ip_vs_lblcr_init_svc(struct ip_vs_service *svc)
tbl->periodic_timer.expires = jiffies+CHECK_EXPIRE_INTERVAL;
add_timer(&tbl->periodic_timer);
-#ifdef CONFIG_IP_VS_LBLCR_DEBUG
- lblcr_table_list = tbl;
-#endif
return 0;
}
@@ -843,18 +773,12 @@ static int __init ip_vs_lblcr_init(void)
{
INIT_LIST_HEAD(&ip_vs_lblcr_scheduler.n_list);
sysctl_header = register_sysctl_table(lblcr_root_table);
-#ifdef CONFIG_IP_VS_LBLCR_DEBUG
- proc_net_create(&init_net, "ip_vs_lblcr", 0, ip_vs_lblcr_getinfo);
-#endif
return register_ip_vs_scheduler(&ip_vs_lblcr_scheduler);
}
static void __exit ip_vs_lblcr_cleanup(void)
{
-#ifdef CONFIG_IP_VS_LBLCR_DEBUG
- proc_net_remove(&init_net, "ip_vs_lblcr");
-#endif
unregister_sysctl_table(sysctl_header);
unregister_ip_vs_scheduler(&ip_vs_lblcr_scheduler);
}
diff --git a/net/ipv4/ipvs/ip_vs_proto_tcp.c b/net/ipv4/ipvs/ip_vs_proto_tcp.c
index e65577a77006..12dc0d640b6d 100644
--- a/net/ipv4/ipvs/ip_vs_proto_tcp.c
+++ b/net/ipv4/ipvs/ip_vs_proto_tcp.c
@@ -20,6 +20,7 @@
#include <linux/tcp.h> /* for tcphdr */
#include <net/ip.h>
#include <net/tcp.h> /* for csum_tcpudp_magic */
+#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <net/ip_vs.h>
@@ -122,27 +123,27 @@ tcp_fast_csum_update(struct tcphdr *tcph, __be32 oldip, __be32 newip,
static int
-tcp_snat_handler(struct sk_buff **pskb,
+tcp_snat_handler(struct sk_buff *skb,
struct ip_vs_protocol *pp, struct ip_vs_conn *cp)
{
struct tcphdr *tcph;
- const unsigned int tcphoff = ip_hdrlen(*pskb);
+ const unsigned int tcphoff = ip_hdrlen(skb);
/* csum_check requires unshared skb */
- if (!ip_vs_make_skb_writable(pskb, tcphoff+sizeof(*tcph)))
+ if (!skb_make_writable(skb, tcphoff+sizeof(*tcph)))
return 0;
if (unlikely(cp->app != NULL)) {
/* Some checks before mangling */
- if (pp->csum_check && !pp->csum_check(*pskb, pp))
+ if (pp->csum_check && !pp->csum_check(skb, pp))
return 0;
/* Call application helper if needed */
- if (!ip_vs_app_pkt_out(cp, pskb))
+ if (!ip_vs_app_pkt_out(cp, skb))
return 0;
}
- tcph = (void *)ip_hdr(*pskb) + tcphoff;
+ tcph = (void *)ip_hdr(skb) + tcphoff;
tcph->source = cp->vport;
/* Adjust TCP checksums */
@@ -150,17 +151,15 @@ tcp_snat_handler(struct sk_buff **pskb,
/* Only port and addr are changed, do fast csum update */
tcp_fast_csum_update(tcph, cp->daddr, cp->vaddr,
cp->dport, cp->vport);
- if ((*pskb)->ip_summed == CHECKSUM_COMPLETE)
- (*pskb)->ip_summed = CHECKSUM_NONE;
+ if (skb->ip_summed == CHECKSUM_COMPLETE)
+ skb->ip_summed = CHECKSUM_NONE;
} else {
/* full checksum calculation */
tcph->check = 0;
- (*pskb)->csum = skb_checksum(*pskb, tcphoff,
- (*pskb)->len - tcphoff, 0);
+ skb->csum = skb_checksum(skb, tcphoff, skb->len - tcphoff, 0);
tcph->check = csum_tcpudp_magic(cp->vaddr, cp->caddr,
- (*pskb)->len - tcphoff,
- cp->protocol,
- (*pskb)->csum);
+ skb->len - tcphoff,
+ cp->protocol, skb->csum);
IP_VS_DBG(11, "O-pkt: %s O-csum=%d (+%zd)\n",
pp->name, tcph->check,
(char*)&(tcph->check) - (char*)tcph);
@@ -170,30 +169,30 @@ tcp_snat_handler(struct sk_buff **pskb,
static int
-tcp_dnat_handler(struct sk_buff **pskb,
+tcp_dnat_handler(struct sk_buff *skb,
struct ip_vs_protocol *pp, struct ip_vs_conn *cp)
{
struct tcphdr *tcph;
- const unsigned int tcphoff = ip_hdrlen(*pskb);
+ const unsigned int tcphoff = ip_hdrlen(skb);
/* csum_check requires unshared skb */
- if (!ip_vs_make_skb_writable(pskb, tcphoff+sizeof(*tcph)))
+ if (!skb_make_writable(skb, tcphoff+sizeof(*tcph)))
return 0;
if (unlikely(cp->app != NULL)) {
/* Some checks before mangling */
- if (pp->csum_check && !pp->csum_check(*pskb, pp))
+ if (pp->csum_check && !pp->csum_check(skb, pp))
return 0;
/*
* Attempt ip_vs_app call.
* It will fix ip_vs_conn and iph ack_seq stuff
*/
- if (!ip_vs_app_pkt_in(cp, pskb))
+ if (!ip_vs_app_pkt_in(cp, skb))
return 0;
}
- tcph = (void *)ip_hdr(*pskb) + tcphoff;
+ tcph = (void *)ip_hdr(skb) + tcphoff;
tcph->dest = cp->dport;
/*
@@ -203,18 +202,16 @@ tcp_dnat_handler(struct sk_buff **pskb,
/* Only port and addr are changed, do fast csum update */
tcp_fast_csum_update(tcph, cp->vaddr, cp->daddr,
cp->vport, cp->dport);
- if ((*pskb)->ip_summed == CHECKSUM_COMPLETE)
- (*pskb)->ip_summed = CHECKSUM_NONE;
+ if (skb->ip_summed == CHECKSUM_COMPLETE)
+ skb->ip_summed = CHECKSUM_NONE;
} else {
/* full checksum calculation */
tcph->check = 0;
- (*pskb)->csum = skb_checksum(*pskb, tcphoff,
- (*pskb)->len - tcphoff, 0);
+ skb->csum = skb_checksum(skb, tcphoff, skb->len - tcphoff, 0);
tcph->check = csum_tcpudp_magic(cp->caddr, cp->daddr,
- (*pskb)->len - tcphoff,
- cp->protocol,
- (*pskb)->csum);
- (*pskb)->ip_summed = CHECKSUM_UNNECESSARY;
+ skb->len - tcphoff,
+ cp->protocol, skb->csum);
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
}
return 1;
}
diff --git a/net/ipv4/ipvs/ip_vs_proto_udp.c b/net/ipv4/ipvs/ip_vs_proto_udp.c
index 8ee5fe6a101d..1fa7b330b9ac 100644
--- a/net/ipv4/ipvs/ip_vs_proto_udp.c
+++ b/net/ipv4/ipvs/ip_vs_proto_udp.c
@@ -18,6 +18,7 @@
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/kernel.h>
+#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/udp.h>
@@ -129,29 +130,29 @@ udp_fast_csum_update(struct udphdr *uhdr, __be32 oldip, __be32 newip,
}
static int
-udp_snat_handler(struct sk_buff **pskb,
+udp_snat_handler(struct sk_buff *skb,
struct ip_vs_protocol *pp, struct ip_vs_conn *cp)
{
struct udphdr *udph;
- const unsigned int udphoff = ip_hdrlen(*pskb);
+ const unsigned int udphoff = ip_hdrlen(skb);
/* csum_check requires unshared skb */
- if (!ip_vs_make_skb_writable(pskb, udphoff+sizeof(*udph)))
+ if (!skb_make_writable(skb, udphoff+sizeof(*udph)))
return 0;
if (unlikely(cp->app != NULL)) {
/* Some checks before mangling */
- if (pp->csum_check && !pp->csum_check(*pskb, pp))
+ if (pp->csum_check && !pp->csum_check(skb, pp))
return 0;
/*
* Call application helper if needed
*/
- if (!ip_vs_app_pkt_out(cp, pskb))
+ if (!ip_vs_app_pkt_out(cp, skb))
return 0;
}
- udph = (void *)ip_hdr(*pskb) + udphoff;
+ udph = (void *)ip_hdr(skb) + udphoff;
udph->source = cp->vport;
/*
@@ -161,17 +162,15 @@ udp_snat_handler(struct sk_buff **pskb,
/* Only port and addr are changed, do fast csum update */
udp_fast_csum_update(udph, cp->daddr, cp->vaddr,
cp->dport, cp->vport);
- if ((*pskb)->ip_summed == CHECKSUM_COMPLETE)
- (*pskb)->ip_summed = CHECKSUM_NONE;
+ if (skb->ip_summed == CHECKSUM_COMPLETE)
+ skb->ip_summed = CHECKSUM_NONE;
} else {
/* full checksum calculation */
udph->check = 0;
- (*pskb)->csum = skb_checksum(*pskb, udphoff,
- (*pskb)->len - udphoff, 0);
+ skb->csum = skb_checksum(skb, udphoff, skb->len - udphoff, 0);
udph->check = csum_tcpudp_magic(cp->vaddr, cp->caddr,
- (*pskb)->len - udphoff,
- cp->protocol,
- (*pskb)->csum);
+ skb->len - udphoff,
+ cp->protocol, skb->csum);
if (udph->check == 0)
udph->check = CSUM_MANGLED_0;
IP_VS_DBG(11, "O-pkt: %s O-csum=%d (+%zd)\n",
@@ -183,30 +182,30 @@ udp_snat_handler(struct sk_buff **pskb,
static int
-udp_dnat_handler(struct sk_buff **pskb,
+udp_dnat_handler(struct sk_buff *skb,
struct ip_vs_protocol *pp, struct ip_vs_conn *cp)
{
struct udphdr *udph;
- unsigned int udphoff = ip_hdrlen(*pskb);
+ unsigned int udphoff = ip_hdrlen(skb);
/* csum_check requires unshared skb */
- if (!ip_vs_make_skb_writable(pskb, udphoff+sizeof(*udph)))
+ if (!skb_make_writable(skb, udphoff+sizeof(*udph)))
return 0;
if (unlikely(cp->app != NULL)) {
/* Some checks before mangling */
- if (pp->csum_check && !pp->csum_check(*pskb, pp))
+ if (pp->csum_check && !pp->csum_check(skb, pp))
return 0;
/*
* Attempt ip_vs_app call.
* It will fix ip_vs_conn
*/
- if (!ip_vs_app_pkt_in(cp, pskb))
+ if (!ip_vs_app_pkt_in(cp, skb))
return 0;
}
- udph = (void *)ip_hdr(*pskb) + udphoff;
+ udph = (void *)ip_hdr(skb) + udphoff;
udph->dest = cp->dport;
/*
@@ -216,20 +215,18 @@ udp_dnat_handler(struct sk_buff **pskb,
/* Only port and addr are changed, do fast csum update */
udp_fast_csum_update(udph, cp->vaddr, cp->daddr,
cp->vport, cp->dport);
- if ((*pskb)->ip_summed == CHECKSUM_COMPLETE)
- (*pskb)->ip_summed = CHECKSUM_NONE;
+ if (skb->ip_summed == CHECKSUM_COMPLETE)
+ skb->ip_summed = CHECKSUM_NONE;
} else {
/* full checksum calculation */
udph->check = 0;
- (*pskb)->csum = skb_checksum(*pskb, udphoff,
- (*pskb)->len - udphoff, 0);
+ skb->csum = skb_checksum(skb, udphoff, skb->len - udphoff, 0);
udph->check = csum_tcpudp_magic(cp->caddr, cp->daddr,
- (*pskb)->len - udphoff,
- cp->protocol,
- (*pskb)->csum);
+ skb->len - udphoff,
+ cp->protocol, skb->csum);
if (udph->check == 0)
udph->check = CSUM_MANGLED_0;
- (*pskb)->ip_summed = CHECKSUM_UNNECESSARY;
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
}
return 1;
}
diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c
index 1960747f354c..bd930efc18da 100644
--- a/net/ipv4/ipvs/ip_vs_sync.c
+++ b/net/ipv4/ipvs/ip_vs_sync.c
@@ -72,7 +72,6 @@ struct ip_vs_sync_thread_data {
int state;
};
-#define IP_VS_SYNC_CONN_TIMEOUT (3*60*HZ)
#define SIMPLE_CONN_SIZE (sizeof(struct ip_vs_sync_conn))
#define FULL_CONN_SIZE \
(sizeof(struct ip_vs_sync_conn) + sizeof(struct ip_vs_sync_conn_options))
@@ -284,6 +283,8 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen)
struct ip_vs_sync_conn *s;
struct ip_vs_sync_conn_options *opt;
struct ip_vs_conn *cp;
+ struct ip_vs_protocol *pp;
+ struct ip_vs_dest *dest;
char *p;
int i;
@@ -317,20 +318,34 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen)
s->caddr, s->cport,
s->vaddr, s->vport);
if (!cp) {
+ /*
+ * Find the appropriate destination for the connection.
+ * If it is not found the connection will remain unbound
+ * but still handled.
+ */
+ dest = ip_vs_find_dest(s->daddr, s->dport,
+ s->vaddr, s->vport,
+ s->protocol);
cp = ip_vs_conn_new(s->protocol,
s->caddr, s->cport,
s->vaddr, s->vport,
s->daddr, s->dport,
- flags, NULL);
+ flags, dest);
+ if (dest)
+ atomic_dec(&dest->refcnt);
if (!cp) {
IP_VS_ERR("ip_vs_conn_new failed\n");
return;
}
cp->state = ntohs(s->state);
} else if (!cp->dest) {
- /* it is an entry created by the synchronization */
- cp->state = ntohs(s->state);
- cp->flags = flags | IP_VS_CONN_F_HASHED;
+ dest = ip_vs_try_bind_dest(cp);
+ if (!dest) {
+ /* it is an unbound entry created by
+ * synchronization */
+ cp->flags = flags | IP_VS_CONN_F_HASHED;
+ } else
+ atomic_dec(&dest->refcnt);
} /* Note that we don't touch its state and flags
if it is a normal entry. */
@@ -342,7 +357,9 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen)
p += SIMPLE_CONN_SIZE;
atomic_set(&cp->in_pkts, sysctl_ip_vs_sync_threshold[0]);
- cp->timeout = IP_VS_SYNC_CONN_TIMEOUT;
+ cp->state = ntohs(s->state);
+ pp = ip_vs_proto_get(s->protocol);
+ cp->timeout = pp->timeout_table[cp->state];
ip_vs_conn_put(cp);
if (p > buffer+buflen) {
@@ -794,7 +811,7 @@ static int sync_thread(void *startup)
add_wait_queue(&sync_wait, &wait);
- set_sync_pid(state, current->pid);
+ set_sync_pid(state, task_pid_nr(current));
complete(tinfo->startup);
/*
@@ -877,7 +894,7 @@ int start_sync_thread(int state, char *mcast_ifn, __u8 syncid)
if (!tinfo)
return -ENOMEM;
- IP_VS_DBG(7, "%s: pid %d\n", __FUNCTION__, current->pid);
+ IP_VS_DBG(7, "%s: pid %d\n", __FUNCTION__, task_pid_nr(current));
IP_VS_DBG(7, "Each ip_vs_sync_conn entry need %Zd bytes\n",
sizeof(struct ip_vs_sync_conn));
@@ -917,7 +934,7 @@ int stop_sync_thread(int state)
(state == IP_VS_STATE_BACKUP && !sync_backup_pid))
return -ESRCH;
- IP_VS_DBG(7, "%s: pid %d\n", __FUNCTION__, current->pid);
+ IP_VS_DBG(7, "%s: pid %d\n", __FUNCTION__, task_pid_nr(current));
IP_VS_INFO("stopping sync thread %d ...\n",
(state == IP_VS_STATE_MASTER) ?
sync_master_pid : sync_backup_pid);
diff --git a/net/ipv4/ipvs/ip_vs_xmit.c b/net/ipv4/ipvs/ip_vs_xmit.c
index 666e080a74a3..7c074e386c17 100644
--- a/net/ipv4/ipvs/ip_vs_xmit.c
+++ b/net/ipv4/ipvs/ip_vs_xmit.c
@@ -253,7 +253,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
}
/* copy-on-write the packet before mangling it */
- if (!ip_vs_make_skb_writable(&skb, sizeof(struct iphdr)))
+ if (!skb_make_writable(skb, sizeof(struct iphdr)))
goto tx_error_put;
if (skb_cow(skb, rt->u.dst.dev->hard_header_len))
@@ -264,7 +264,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
skb->dst = &rt->u.dst;
/* mangle the packet */
- if (pp->dnat_handler && !pp->dnat_handler(&skb, pp, cp))
+ if (pp->dnat_handler && !pp->dnat_handler(skb, pp, cp))
goto tx_error;
ip_hdr(skb)->daddr = cp->daddr;
ip_send_check(ip_hdr(skb));
@@ -325,7 +325,7 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
__be16 df = old_iph->frag_off;
sk_buff_data_t old_transport_header = skb->transport_header;
struct iphdr *iph; /* Our new IP header */
- int max_headroom; /* The extra header space needed */
+ unsigned int max_headroom; /* The extra header space needed */
int mtu;
EnterFunction(10);
@@ -529,7 +529,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
}
/* copy-on-write the packet before mangling it */
- if (!ip_vs_make_skb_writable(&skb, offset))
+ if (!skb_make_writable(skb, offset))
goto tx_error_put;
if (skb_cow(skb, rt->u.dst.dev->hard_header_len))
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index b44192924f95..5539debf4973 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -3,14 +3,15 @@
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/ip.h>
+#include <linux/skbuff.h>
#include <net/route.h>
#include <net/xfrm.h>
#include <net/ip.h>
/* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */
-int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type)
+int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type)
{
- const struct iphdr *iph = ip_hdr(*pskb);
+ const struct iphdr *iph = ip_hdr(skb);
struct rtable *rt;
struct flowi fl = {};
struct dst_entry *odst;
@@ -29,14 +30,14 @@ int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type)
if (type == RTN_LOCAL)
fl.nl_u.ip4_u.saddr = iph->saddr;
fl.nl_u.ip4_u.tos = RT_TOS(iph->tos);
- fl.oif = (*pskb)->sk ? (*pskb)->sk->sk_bound_dev_if : 0;
- fl.mark = (*pskb)->mark;
+ fl.oif = skb->sk ? skb->sk->sk_bound_dev_if : 0;
+ fl.mark = skb->mark;
if (ip_route_output_key(&rt, &fl) != 0)
return -1;
/* Drop old route. */
- dst_release((*pskb)->dst);
- (*pskb)->dst = &rt->u.dst;
+ dst_release(skb->dst);
+ skb->dst = &rt->u.dst;
} else {
/* non-local src, find valid iif to satisfy
* rp-filter when calling ip_route_input. */
@@ -44,8 +45,8 @@ int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type)
if (ip_route_output_key(&rt, &fl) != 0)
return -1;
- odst = (*pskb)->dst;
- if (ip_route_input(*pskb, iph->daddr, iph->saddr,
+ odst = skb->dst;
+ if (ip_route_input(skb, iph->daddr, iph->saddr,
RT_TOS(iph->tos), rt->u.dst.dev) != 0) {
dst_release(&rt->u.dst);
return -1;
@@ -54,70 +55,54 @@ int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type)
dst_release(odst);
}
- if ((*pskb)->dst->error)
+ if (skb->dst->error)
return -1;
#ifdef CONFIG_XFRM
- if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED) &&
- xfrm_decode_session(*pskb, &fl, AF_INET) == 0)
- if (xfrm_lookup(&(*pskb)->dst, &fl, (*pskb)->sk, 0))
+ if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) &&
+ xfrm_decode_session(skb, &fl, AF_INET) == 0)
+ if (xfrm_lookup(&skb->dst, &fl, skb->sk, 0))
return -1;
#endif
/* Change in oif may mean change in hh_len. */
- hh_len = (*pskb)->dst->dev->hard_header_len;
- if (skb_headroom(*pskb) < hh_len) {
- struct sk_buff *nskb;
-
- nskb = skb_realloc_headroom(*pskb, hh_len);
- if (!nskb)
- return -1;
- if ((*pskb)->sk)
- skb_set_owner_w(nskb, (*pskb)->sk);
- kfree_skb(*pskb);
- *pskb = nskb;
- }
+ hh_len = skb->dst->dev->hard_header_len;
+ if (skb_headroom(skb) < hh_len &&
+ pskb_expand_head(skb, hh_len - skb_headroom(skb), 0, GFP_ATOMIC))
+ return -1;
return 0;
}
EXPORT_SYMBOL(ip_route_me_harder);
#ifdef CONFIG_XFRM
-int ip_xfrm_me_harder(struct sk_buff **pskb)
+int ip_xfrm_me_harder(struct sk_buff *skb)
{
struct flowi fl;
unsigned int hh_len;
struct dst_entry *dst;
- if (IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED)
+ if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
return 0;
- if (xfrm_decode_session(*pskb, &fl, AF_INET) < 0)
+ if (xfrm_decode_session(skb, &fl, AF_INET) < 0)
return -1;
- dst = (*pskb)->dst;
+ dst = skb->dst;
if (dst->xfrm)
dst = ((struct xfrm_dst *)dst)->route;
dst_hold(dst);
- if (xfrm_lookup(&dst, &fl, (*pskb)->sk, 0) < 0)
+ if (xfrm_lookup(&dst, &fl, skb->sk, 0) < 0)
return -1;
- dst_release((*pskb)->dst);
- (*pskb)->dst = dst;
+ dst_release(skb->dst);
+ skb->dst = dst;
/* Change in oif may mean change in hh_len. */
- hh_len = (*pskb)->dst->dev->hard_header_len;
- if (skb_headroom(*pskb) < hh_len) {
- struct sk_buff *nskb;
-
- nskb = skb_realloc_headroom(*pskb, hh_len);
- if (!nskb)
- return -1;
- if ((*pskb)->sk)
- skb_set_owner_w(nskb, (*pskb)->sk);
- kfree_skb(*pskb);
- *pskb = nskb;
- }
+ hh_len = skb->dst->dev->hard_header_len;
+ if (skb_headroom(skb) < hh_len &&
+ pskb_expand_head(skb, hh_len - skb_headroom(skb), 0, GFP_ATOMIC))
+ return -1;
return 0;
}
EXPORT_SYMBOL(ip_xfrm_me_harder);
@@ -150,17 +135,17 @@ static void nf_ip_saveroute(const struct sk_buff *skb, struct nf_info *info)
}
}
-static int nf_ip_reroute(struct sk_buff **pskb, const struct nf_info *info)
+static int nf_ip_reroute(struct sk_buff *skb, const struct nf_info *info)
{
const struct ip_rt_info *rt_info = nf_info_reroute(info);
if (info->hook == NF_IP_LOCAL_OUT) {
- const struct iphdr *iph = ip_hdr(*pskb);
+ const struct iphdr *iph = ip_hdr(skb);
if (!(iph->tos == rt_info->tos
&& iph->daddr == rt_info->daddr
&& iph->saddr == rt_info->saddr))
- return ip_route_me_harder(pskb, RTN_UNSPEC);
+ return ip_route_me_harder(skb, RTN_UNSPEC);
}
return 0;
}
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index fa97947c6ae1..9aca9c55687c 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -128,7 +128,7 @@ config IP_NF_MATCH_ADDRTYPE
eg. UNICAST, LOCAL, BROADCAST, ...
If you want to compile it as a module, say M here and read
- <file:Documentation/modules.txt>. If unsure, say `N'.
+ <file:Documentation/kbuild/modules.txt>. If unsure, say `N'.
# `filter', generic and specific targets
config IP_NF_FILTER
@@ -371,7 +371,7 @@ config IP_NF_RAW
and OUTPUT chains.
If you want to compile it as a module, say M here and read
- <file:Documentation/modules.txt>. If unsure, say `N'.
+ <file:Documentation/kbuild/modules.txt>. If unsure, say `N'.
# ARP tables
config IP_NF_ARPTABLES
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 409d273f6f82..7456833d6ade 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -41,27 +41,27 @@ obj-$(CONFIG_NF_NAT) += iptable_nat.o
obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
# matches
+obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
+obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o
+obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
-obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
-obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
-obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o
+obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
-obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
# targets
-obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
-obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o
+obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o
obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
+obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
-obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
+obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
+obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o
-obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
-obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
-obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o
+obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o
obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
+obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
# generic ARP tables
obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 29114a9ccd1d..2909c92ecd99 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -197,7 +197,7 @@ static inline int arp_checkentry(const struct arpt_arp *arp)
return 1;
}
-static unsigned int arpt_error(struct sk_buff **pskb,
+static unsigned int arpt_error(struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
unsigned int hooknum,
@@ -215,7 +215,7 @@ static inline struct arpt_entry *get_entry(void *base, unsigned int offset)
return (struct arpt_entry *)(base + offset);
}
-unsigned int arpt_do_table(struct sk_buff **pskb,
+unsigned int arpt_do_table(struct sk_buff *skb,
unsigned int hook,
const struct net_device *in,
const struct net_device *out,
@@ -231,9 +231,9 @@ unsigned int arpt_do_table(struct sk_buff **pskb,
struct xt_table_info *private;
/* ARP header, plus 2 device addresses, plus 2 IP addresses. */
- if (!pskb_may_pull((*pskb), (sizeof(struct arphdr) +
- (2 * (*pskb)->dev->addr_len) +
- (2 * sizeof(u32)))))
+ if (!pskb_may_pull(skb, (sizeof(struct arphdr) +
+ (2 * skb->dev->addr_len) +
+ (2 * sizeof(u32)))))
return NF_DROP;
indev = in ? in->name : nulldevname;
@@ -245,14 +245,14 @@ unsigned int arpt_do_table(struct sk_buff **pskb,
e = get_entry(table_base, private->hook_entry[hook]);
back = get_entry(table_base, private->underflow[hook]);
- arp = arp_hdr(*pskb);
+ arp = arp_hdr(skb);
do {
- if (arp_packet_match(arp, (*pskb)->dev, indev, outdev, &e->arp)) {
+ if (arp_packet_match(arp, skb->dev, indev, outdev, &e->arp)) {
struct arpt_entry_target *t;
int hdr_len;
hdr_len = sizeof(*arp) + (2 * sizeof(struct in_addr)) +
- (2 * (*pskb)->dev->addr_len);
+ (2 * skb->dev->addr_len);
ADD_COUNTER(e->counters, hdr_len, 1);
t = arpt_get_target(e);
@@ -290,14 +290,14 @@ unsigned int arpt_do_table(struct sk_buff **pskb,
/* Targets which reenter must return
* abs. verdicts
*/
- verdict = t->u.kernel.target->target(pskb,
+ verdict = t->u.kernel.target->target(skb,
in, out,
hook,
t->u.kernel.target,
t->data);
/* Target might have changed stuff. */
- arp = arp_hdr(*pskb);
+ arp = arp_hdr(skb);
if (verdict == ARPT_CONTINUE)
e = (void *)e + e->next_offset;
diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c
index c4bdab47597f..45fa4e20094a 100644
--- a/net/ipv4/netfilter/arpt_mangle.c
+++ b/net/ipv4/netfilter/arpt_mangle.c
@@ -1,5 +1,6 @@
/* module that allows mangling of the arp payload */
#include <linux/module.h>
+#include <linux/netfilter.h>
#include <linux/netfilter_arp/arpt_mangle.h>
#include <net/sock.h>
@@ -8,7 +9,7 @@ MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
MODULE_DESCRIPTION("arptables arp payload mangle target");
static unsigned int
-target(struct sk_buff **pskb,
+target(struct sk_buff *skb,
const struct net_device *in, const struct net_device *out,
unsigned int hooknum, const struct xt_target *target,
const void *targinfo)
@@ -18,47 +19,38 @@ target(struct sk_buff **pskb,
unsigned char *arpptr;
int pln, hln;
- if (skb_shared(*pskb) || skb_cloned(*pskb)) {
- struct sk_buff *nskb;
+ if (skb_make_writable(skb, skb->len))
+ return NF_DROP;
- nskb = skb_copy(*pskb, GFP_ATOMIC);
- if (!nskb)
- return NF_DROP;
- if ((*pskb)->sk)
- skb_set_owner_w(nskb, (*pskb)->sk);
- kfree_skb(*pskb);
- *pskb = nskb;
- }
-
- arp = arp_hdr(*pskb);
- arpptr = skb_network_header(*pskb) + sizeof(*arp);
+ arp = arp_hdr(skb);
+ arpptr = skb_network_header(skb) + sizeof(*arp);
pln = arp->ar_pln;
hln = arp->ar_hln;
/* We assume that pln and hln were checked in the match */
if (mangle->flags & ARPT_MANGLE_SDEV) {
if (ARPT_DEV_ADDR_LEN_MAX < hln ||
- (arpptr + hln > skb_tail_pointer(*pskb)))
+ (arpptr + hln > skb_tail_pointer(skb)))
return NF_DROP;
memcpy(arpptr, mangle->src_devaddr, hln);
}
arpptr += hln;
if (mangle->flags & ARPT_MANGLE_SIP) {
if (ARPT_MANGLE_ADDR_LEN_MAX < pln ||
- (arpptr + pln > skb_tail_pointer(*pskb)))
+ (arpptr + pln > skb_tail_pointer(skb)))
return NF_DROP;
memcpy(arpptr, &mangle->u_s.src_ip, pln);
}
arpptr += pln;
if (mangle->flags & ARPT_MANGLE_TDEV) {
if (ARPT_DEV_ADDR_LEN_MAX < hln ||
- (arpptr + hln > skb_tail_pointer(*pskb)))
+ (arpptr + hln > skb_tail_pointer(skb)))
return NF_DROP;
memcpy(arpptr, mangle->tgt_devaddr, hln);
}
arpptr += hln;
if (mangle->flags & ARPT_MANGLE_TIP) {
if (ARPT_MANGLE_ADDR_LEN_MAX < pln ||
- (arpptr + pln > skb_tail_pointer(*pskb)))
+ (arpptr + pln > skb_tail_pointer(skb)))
return NF_DROP;
memcpy(arpptr, &mangle->u_t.tgt_ip, pln);
}
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c
index 75c023062533..302d3da5f696 100644
--- a/net/ipv4/netfilter/arptable_filter.c
+++ b/net/ipv4/netfilter/arptable_filter.c
@@ -56,12 +56,12 @@ static struct arpt_table packet_filter = {
/* The work comes in here from netfilter.c */
static unsigned int arpt_hook(unsigned int hook,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
- return arpt_do_table(pskb, hook, in, out, &packet_filter);
+ return arpt_do_table(skb, hook, in, out, &packet_filter);
}
static struct nf_hook_ops arpt_ops[] = {
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index 23cbfc7c80fd..14d64a383db1 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -22,6 +22,7 @@
#include <linux/spinlock.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <linux/security.h>
#include <linux/mutex.h>
#include <net/net_namespace.h>
@@ -335,6 +336,7 @@ static int
ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
{
int diff;
+ int err;
struct iphdr *user_iph = (struct iphdr *)v->payload;
if (v->data_len < sizeof(*user_iph))
@@ -347,25 +349,18 @@ ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
if (v->data_len > 0xFFFF)
return -EINVAL;
if (diff > skb_tailroom(e->skb)) {
- struct sk_buff *newskb;
-
- newskb = skb_copy_expand(e->skb,
- skb_headroom(e->skb),
- diff,
- GFP_ATOMIC);
- if (newskb == NULL) {
- printk(KERN_WARNING "ip_queue: OOM "
- "in mangle, dropping packet\n");
- return -ENOMEM;
+ err = pskb_expand_head(e->skb, 0,
+ diff - skb_tailroom(e->skb),
+ GFP_ATOMIC);
+ if (err) {
+ printk(KERN_WARNING "ip_queue: error "
+ "in mangle, dropping packet: %d\n", -err);
+ return err;
}
- if (e->skb->sk)
- skb_set_owner_w(newskb, e->skb->sk);
- kfree_skb(e->skb);
- e->skb = newskb;
}
skb_put(e->skb, diff);
}
- if (!skb_make_writable(&e->skb, v->data_len))
+ if (!skb_make_writable(e->skb, v->data_len))
return -ENOMEM;
skb_copy_to_linear_data(e->skb, v->payload, v->data_len);
e->skb->ip_summed = CHECKSUM_NONE;
@@ -613,15 +608,11 @@ static ctl_table ipq_root_table[] = {
{ .ctl_name = 0 }
};
-#ifdef CONFIG_PROC_FS
-static int
-ipq_get_info(char *buffer, char **start, off_t offset, int length)
+static int ip_queue_show(struct seq_file *m, void *v)
{
- int len;
-
read_lock_bh(&queue_lock);
- len = sprintf(buffer,
+ seq_printf(m,
"Peer PID : %d\n"
"Copy mode : %hu\n"
"Copy range : %u\n"
@@ -638,16 +629,21 @@ ipq_get_info(char *buffer, char **start, off_t offset, int length)
queue_user_dropped);
read_unlock_bh(&queue_lock);
+ return 0;
+}
- *start = buffer + offset;
- len -= offset;
- if (len > length)
- len = length;
- else if (len < 0)
- len = 0;
- return len;
+static int ip_queue_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, ip_queue_show, NULL);
}
-#endif /* CONFIG_PROC_FS */
+
+static const struct file_operations ip_queue_proc_fops = {
+ .open = ip_queue_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .owner = THIS_MODULE,
+};
static struct nf_queue_handler nfqh = {
.name = "ip_queue",
@@ -667,10 +663,11 @@ static int __init ip_queue_init(void)
goto cleanup_netlink_notifier;
}
- proc = proc_net_create(&init_net, IPQ_PROC_FS_NAME, 0, ipq_get_info);
- if (proc)
+ proc = create_proc_entry(IPQ_PROC_FS_NAME, 0, init_net.proc_net);
+ if (proc) {
proc->owner = THIS_MODULE;
- else {
+ proc->proc_fops = &ip_queue_proc_fops;
+ } else {
printk(KERN_ERR "ip_queue: failed to create proc entry\n");
goto cleanup_ipqnl;
}
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 6486894f450c..4b10b98640ac 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -169,7 +169,7 @@ ip_checkentry(const struct ipt_ip *ip)
}
static unsigned int
-ipt_error(struct sk_buff **pskb,
+ipt_error(struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
unsigned int hooknum,
@@ -312,7 +312,7 @@ static void trace_packet(struct sk_buff *skb,
/* Returns one of the generic firewall policies, like NF_ACCEPT. */
unsigned int
-ipt_do_table(struct sk_buff **pskb,
+ipt_do_table(struct sk_buff *skb,
unsigned int hook,
const struct net_device *in,
const struct net_device *out,
@@ -331,8 +331,8 @@ ipt_do_table(struct sk_buff **pskb,
struct xt_table_info *private;
/* Initialization */
- ip = ip_hdr(*pskb);
- datalen = (*pskb)->len - ip->ihl * 4;
+ ip = ip_hdr(skb);
+ datalen = skb->len - ip->ihl * 4;
indev = in ? in->name : nulldevname;
outdev = out ? out->name : nulldevname;
/* We handle fragments by dealing with the first fragment as
@@ -359,7 +359,7 @@ ipt_do_table(struct sk_buff **pskb,
struct ipt_entry_target *t;
if (IPT_MATCH_ITERATE(e, do_match,
- *pskb, in, out,
+ skb, in, out,
offset, &hotdrop) != 0)
goto no_match;
@@ -371,8 +371,8 @@ ipt_do_table(struct sk_buff **pskb,
#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
/* The packet is traced: log it */
- if (unlikely((*pskb)->nf_trace))
- trace_packet(*pskb, hook, in, out,
+ if (unlikely(skb->nf_trace))
+ trace_packet(skb, hook, in, out,
table->name, private, e);
#endif
/* Standard target? */
@@ -410,7 +410,7 @@ ipt_do_table(struct sk_buff **pskb,
((struct ipt_entry *)table_base)->comefrom
= 0xeeeeeeec;
#endif
- verdict = t->u.kernel.target->target(pskb,
+ verdict = t->u.kernel.target->target(skb,
in, out,
hook,
t->u.kernel.target,
@@ -428,8 +428,8 @@ ipt_do_table(struct sk_buff **pskb,
= 0x57acc001;
#endif
/* Target might have changed stuff. */
- ip = ip_hdr(*pskb);
- datalen = (*pskb)->len - ip->ihl * 4;
+ ip = ip_hdr(skb);
+ datalen = skb->len - ip->ihl * 4;
if (verdict == IPT_CONTINUE)
e = (void *)e + e->next_offset;
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 27f14e1ebd8b..2f544dac72df 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -289,7 +289,7 @@ clusterip_responsible(const struct clusterip_config *config, u_int32_t hash)
***********************************************************************/
static unsigned int
-target(struct sk_buff **pskb,
+target(struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
unsigned int hooknum,
@@ -305,7 +305,7 @@ target(struct sk_buff **pskb,
* is only decremented by destroy() - and ip_tables guarantees
* that the ->target() function isn't called after ->destroy() */
- ct = nf_ct_get(*pskb, &ctinfo);
+ ct = nf_ct_get(skb, &ctinfo);
if (ct == NULL) {
printk(KERN_ERR "CLUSTERIP: no conntrack!\n");
/* FIXME: need to drop invalid ones, since replies
@@ -316,7 +316,7 @@ target(struct sk_buff **pskb,
/* special case: ICMP error handling. conntrack distinguishes between
* error messages (RELATED) and information requests (see below) */
- if (ip_hdr(*pskb)->protocol == IPPROTO_ICMP
+ if (ip_hdr(skb)->protocol == IPPROTO_ICMP
&& (ctinfo == IP_CT_RELATED
|| ctinfo == IP_CT_RELATED+IP_CT_IS_REPLY))
return XT_CONTINUE;
@@ -325,7 +325,7 @@ target(struct sk_buff **pskb,
* TIMESTAMP, INFO_REQUEST or ADDRESS type icmp packets from here
* on, which all have an ID field [relevant for hashing]. */
- hash = clusterip_hashfn(*pskb, cipinfo->config);
+ hash = clusterip_hashfn(skb, cipinfo->config);
switch (ctinfo) {
case IP_CT_NEW:
@@ -355,7 +355,7 @@ target(struct sk_buff **pskb,
/* despite being received via linklayer multicast, this is
* actually a unicast IP packet. TCP doesn't like PACKET_MULTICAST */
- (*pskb)->pkt_type = PACKET_HOST;
+ skb->pkt_type = PACKET_HOST;
return XT_CONTINUE;
}
@@ -505,12 +505,12 @@ static void arp_print(struct arp_payload *payload)
static unsigned int
arp_mangle(unsigned int hook,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
- struct arphdr *arp = arp_hdr(*pskb);
+ struct arphdr *arp = arp_hdr(skb);
struct arp_payload *payload;
struct clusterip_config *c;
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c
index f1253bd3837f..add110060a22 100644
--- a/net/ipv4/netfilter/ipt_ECN.c
+++ b/net/ipv4/netfilter/ipt_ECN.c
@@ -26,15 +26,15 @@ MODULE_DESCRIPTION("iptables ECN modification module");
/* set ECT codepoint from IP header.
* return false if there was an error. */
static inline bool
-set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
+set_ect_ip(struct sk_buff *skb, const struct ipt_ECN_info *einfo)
{
- struct iphdr *iph = ip_hdr(*pskb);
+ struct iphdr *iph = ip_hdr(skb);
if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) {
__u8 oldtos;
- if (!skb_make_writable(pskb, sizeof(struct iphdr)))
+ if (!skb_make_writable(skb, sizeof(struct iphdr)))
return false;
- iph = ip_hdr(*pskb);
+ iph = ip_hdr(skb);
oldtos = iph->tos;
iph->tos &= ~IPT_ECN_IP_MASK;
iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK);
@@ -45,14 +45,13 @@ set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
/* Return false if there was an error. */
static inline bool
-set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
+set_ect_tcp(struct sk_buff *skb, const struct ipt_ECN_info *einfo)
{
struct tcphdr _tcph, *tcph;
__be16 oldval;
/* Not enought header? */
- tcph = skb_header_pointer(*pskb, ip_hdrlen(*pskb),
- sizeof(_tcph), &_tcph);
+ tcph = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_tcph), &_tcph);
if (!tcph)
return false;
@@ -62,9 +61,9 @@ set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
tcph->cwr == einfo->proto.tcp.cwr))
return true;
- if (!skb_make_writable(pskb, ip_hdrlen(*pskb) + sizeof(*tcph)))
+ if (!skb_make_writable(skb, ip_hdrlen(skb) + sizeof(*tcph)))
return false;
- tcph = (void *)ip_hdr(*pskb) + ip_hdrlen(*pskb);
+ tcph = (void *)ip_hdr(skb) + ip_hdrlen(skb);
oldval = ((__be16 *)tcph)[6];
if (einfo->operation & IPT_ECN_OP_SET_ECE)
@@ -72,13 +71,13 @@ set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
if (einfo->operation & IPT_ECN_OP_SET_CWR)
tcph->cwr = einfo->proto.tcp.cwr;
- nf_proto_csum_replace2(&tcph->check, *pskb,
+ nf_proto_csum_replace2(&tcph->check, skb,
oldval, ((__be16 *)tcph)[6], 0);
return true;
}
static unsigned int
-target(struct sk_buff **pskb,
+target(struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
unsigned int hooknum,
@@ -88,12 +87,12 @@ target(struct sk_buff **pskb,
const struct ipt_ECN_info *einfo = targinfo;
if (einfo->operation & IPT_ECN_OP_SET_IP)
- if (!set_ect_ip(pskb, einfo))
+ if (!set_ect_ip(skb, einfo))
return NF_DROP;
if (einfo->operation & (IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR)
- && ip_hdr(*pskb)->protocol == IPPROTO_TCP)
- if (!set_ect_tcp(pskb, einfo))
+ && ip_hdr(skb)->protocol == IPPROTO_TCP)
+ if (!set_ect_tcp(skb, einfo))
return NF_DROP;
return XT_CONTINUE;
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
index 127a5e89bf14..4b5e8216a4e7 100644
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ b/net/ipv4/netfilter/ipt_LOG.c
@@ -418,7 +418,7 @@ ipt_log_packet(unsigned int pf,
}
static unsigned int
-ipt_log_target(struct sk_buff **pskb,
+ipt_log_target(struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
unsigned int hooknum,
@@ -432,7 +432,7 @@ ipt_log_target(struct sk_buff **pskb,
li.u.log.level = loginfo->level;
li.u.log.logflags = loginfo->logflags;
- ipt_log_packet(PF_INET, hooknum, *pskb, in, out, &li,
+ ipt_log_packet(PF_INET, hooknum, skb, in, out, &li,
loginfo->prefix);
return XT_CONTINUE;
}
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index 3e0b562b2db7..44b516e7cb79 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -52,7 +52,7 @@ masquerade_check(const char *tablename,
}
static unsigned int
-masquerade_target(struct sk_buff **pskb,
+masquerade_target(struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
unsigned int hooknum,
@@ -69,7 +69,7 @@ masquerade_target(struct sk_buff **pskb,
NF_CT_ASSERT(hooknum == NF_IP_POST_ROUTING);
- ct = nf_ct_get(*pskb, &ctinfo);
+ ct = nf_ct_get(skb, &ctinfo);
nat = nfct_nat(ct);
NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED
@@ -82,7 +82,7 @@ masquerade_target(struct sk_buff **pskb,
return NF_ACCEPT;
mr = targinfo;
- rt = (struct rtable *)(*pskb)->dst;
+ rt = (struct rtable *)skb->dst;
newsrc = inet_select_addr(out, rt->rt_gateway, RT_SCOPE_UNIVERSE);
if (!newsrc) {
printk("MASQUERADE: %s ate my IP address\n", out->name);
diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c
index 41a011d5a065..f8699291e33d 100644
--- a/net/ipv4/netfilter/ipt_NETMAP.c
+++ b/net/ipv4/netfilter/ipt_NETMAP.c
@@ -43,7 +43,7 @@ check(const char *tablename,
}
static unsigned int
-target(struct sk_buff **pskb,
+target(struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
unsigned int hooknum,
@@ -59,14 +59,14 @@ target(struct sk_buff **pskb,
NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING
|| hooknum == NF_IP_POST_ROUTING
|| hooknum == NF_IP_LOCAL_OUT);
- ct = nf_ct_get(*pskb, &ctinfo);
+ ct = nf_ct_get(skb, &ctinfo);
netmask = ~(mr->range[0].min_ip ^ mr->range[0].max_ip);
if (hooknum == NF_IP_PRE_ROUTING || hooknum == NF_IP_LOCAL_OUT)
- new_ip = ip_hdr(*pskb)->daddr & ~netmask;
+ new_ip = ip_hdr(skb)->daddr & ~netmask;
else
- new_ip = ip_hdr(*pskb)->saddr & ~netmask;
+ new_ip = ip_hdr(skb)->saddr & ~netmask;
new_ip |= mr->range[0].min_ip & netmask;
newrange = ((struct nf_nat_range)
diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c
index 6ac7a2373316..f7cf7d61a2d4 100644
--- a/net/ipv4/netfilter/ipt_REDIRECT.c
+++ b/net/ipv4/netfilter/ipt_REDIRECT.c
@@ -47,7 +47,7 @@ redirect_check(const char *tablename,
}
static unsigned int
-redirect_target(struct sk_buff **pskb,
+redirect_target(struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
unsigned int hooknum,
@@ -63,7 +63,7 @@ redirect_target(struct sk_buff **pskb,
NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING
|| hooknum == NF_IP_LOCAL_OUT);
- ct = nf_ct_get(*pskb, &ctinfo);
+ ct = nf_ct_get(skb, &ctinfo);
NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED));
/* Local packets: make them go to loopback */
@@ -76,7 +76,7 @@ redirect_target(struct sk_buff **pskb,
newdst = 0;
rcu_read_lock();
- indev = __in_dev_get_rcu((*pskb)->dev);
+ indev = __in_dev_get_rcu(skb->dev);
if (indev && (ifa = indev->ifa_list))
newdst = ifa->ifa_local;
rcu_read_unlock();
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index cb038c8fbc9d..dcf4d21d5116 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -131,7 +131,7 @@ static void send_reset(struct sk_buff *oldskb, int hook)
)
addr_type = RTN_LOCAL;
- if (ip_route_me_harder(&nskb, addr_type))
+ if (ip_route_me_harder(nskb, addr_type))
goto free_nskb;
nskb->ip_summed = CHECKSUM_NONE;
@@ -162,7 +162,7 @@ static inline void send_unreach(struct sk_buff *skb_in, int code)
icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0);
}
-static unsigned int reject(struct sk_buff **pskb,
+static unsigned int reject(struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
unsigned int hooknum,
@@ -173,7 +173,7 @@ static unsigned int reject(struct sk_buff **pskb,
/* Our naive response construction doesn't deal with IP
options, and probably shouldn't try. */
- if (ip_hdrlen(*pskb) != sizeof(struct iphdr))
+ if (ip_hdrlen(skb) != sizeof(struct iphdr))
return NF_DROP;
/* WARNING: This code causes reentry within iptables.
@@ -181,28 +181,28 @@ static unsigned int reject(struct sk_buff **pskb,
must return an absolute verdict. --RR */
switch (reject->with) {
case IPT_ICMP_NET_UNREACHABLE:
- send_unreach(*pskb, ICMP_NET_UNREACH);
+ send_unreach(skb, ICMP_NET_UNREACH);
break;
case IPT_ICMP_HOST_UNREACHABLE:
- send_unreach(*pskb, ICMP_HOST_UNREACH);
+ send_unreach(skb, ICMP_HOST_UNREACH);
break;
case IPT_ICMP_PROT_UNREACHABLE:
- send_unreach(*pskb, ICMP_PROT_UNREACH);
+ send_unreach(skb, ICMP_PROT_UNREACH);
break;
case IPT_ICMP_PORT_UNREACHABLE:
- send_unreach(*pskb, ICMP_PORT_UNREACH);
+ send_unreach(skb, ICMP_PORT_UNREACH);
break;
case IPT_ICMP_NET_PROHIBITED:
- send_unreach(*pskb, ICMP_NET_ANO);
+ send_unreach(skb, ICMP_NET_ANO);
break;
case IPT_ICMP_HOST_PROHIBITED:
- send_unreach(*pskb, ICMP_HOST_ANO);
+ send_unreach(skb, ICMP_HOST_ANO);
break;
case IPT_ICMP_ADMIN_PROHIBITED:
- send_unreach(*pskb, ICMP_PKT_FILTERED);
+ send_unreach(skb, ICMP_PKT_FILTERED);
break;
case IPT_TCP_RESET:
- send_reset(*pskb, hooknum);
+ send_reset(skb, hooknum);
case IPT_ICMP_ECHOREPLY:
/* Doesn't happen. */
break;
diff --git a/net/ipv4/netfilter/ipt_SAME.c b/net/ipv4/netfilter/ipt_SAME.c
index 97641f1a97f6..8988571436b8 100644
--- a/net/ipv4/netfilter/ipt_SAME.c
+++ b/net/ipv4/netfilter/ipt_SAME.c
@@ -104,7 +104,7 @@ same_destroy(const struct xt_target *target, void *targinfo)
}
static unsigned int
-same_target(struct sk_buff **pskb,
+same_target(struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
unsigned int hooknum,
@@ -121,7 +121,7 @@ same_target(struct sk_buff **pskb,
NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING ||
hooknum == NF_IP_POST_ROUTING);
- ct = nf_ct_get(*pskb, &ctinfo);
+ ct = nf_ct_get(skb, &ctinfo);
t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
diff --git a/net/ipv4/netfilter/ipt_TOS.c b/net/ipv4/netfilter/ipt_TOS.c
index 25f5d0b39065..d4573baa7f27 100644
--- a/net/ipv4/netfilter/ipt_TOS.c
+++ b/net/ipv4/netfilter/ipt_TOS.c
@@ -21,7 +21,7 @@ MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
MODULE_DESCRIPTION("iptables TOS mangling module");
static unsigned int
-target(struct sk_buff **pskb,
+target(struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
unsigned int hooknum,
@@ -29,13 +29,13 @@ target(struct sk_buff **pskb,
const void *targinfo)
{
const struct ipt_tos_target_info *tosinfo = targinfo;
- struct iphdr *iph = ip_hdr(*pskb);
+ struct iphdr *iph = ip_hdr(skb);
if ((iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) {
__u8 oldtos;
- if (!skb_make_writable(pskb, sizeof(struct iphdr)))
+ if (!skb_make_writable(skb, sizeof(struct iphdr)))
return NF_DROP;
- iph = ip_hdr(*pskb);
+ iph = ip_hdr(skb);
oldtos = iph->tos;
iph->tos = (iph->tos & IPTOS_PREC_MASK) | tosinfo->tos;
nf_csum_replace2(&iph->check, htons(oldtos), htons(iph->tos));
diff --git a/net/ipv4/netfilter/ipt_TTL.c b/net/ipv4/netfilter/ipt_TTL.c
index 2b54e7b0cfe8..c620a0527666 100644
--- a/net/ipv4/netfilter/ipt_TTL.c
+++ b/net/ipv4/netfilter/ipt_TTL.c
@@ -20,7 +20,7 @@ MODULE_DESCRIPTION("IP tables TTL modification module");
MODULE_LICENSE("GPL");
static unsigned int
-ipt_ttl_target(struct sk_buff **pskb,
+ipt_ttl_target(struct sk_buff *skb,
const struct net_device *in, const struct net_device *out,
unsigned int hooknum, const struct xt_target *target,
const void *targinfo)
@@ -29,10 +29,10 @@ ipt_ttl_target(struct sk_buff **pskb,
const struct ipt_TTL_info *info = targinfo;
int new_ttl;
- if (!skb_make_writable(pskb, (*pskb)->len))
+ if (!skb_make_writable(skb, skb->len))
return NF_DROP;
- iph = ip_hdr(*pskb);
+ iph = ip_hdr(skb);
switch (info->mode) {
case IPT_TTL_SET:
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index c636d6d63574..212b830765a4 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -279,7 +279,7 @@ alloc_failure:
spin_unlock_bh(&ulog_lock);
}
-static unsigned int ipt_ulog_target(struct sk_buff **pskb,
+static unsigned int ipt_ulog_target(struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
unsigned int hooknum,
@@ -288,7 +288,7 @@ static unsigned int ipt_ulog_target(struct sk_buff **pskb,
{
struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
- ipt_ulog_packet(hooknum, *pskb, in, out, loginfo, NULL);
+ ipt_ulog_packet(hooknum, skb, in, out, loginfo, NULL);
return XT_CONTINUE;
}
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
index 4f51c1d7d2d6..ba3262c60437 100644
--- a/net/ipv4/netfilter/iptable_filter.c
+++ b/net/ipv4/netfilter/iptable_filter.c
@@ -62,31 +62,31 @@ static struct xt_table packet_filter = {
/* The work comes in here from netfilter.c. */
static unsigned int
ipt_hook(unsigned int hook,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
- return ipt_do_table(pskb, hook, in, out, &packet_filter);
+ return ipt_do_table(skb, hook, in, out, &packet_filter);
}
static unsigned int
ipt_local_out_hook(unsigned int hook,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
/* root is playing with raw sockets. */
- if ((*pskb)->len < sizeof(struct iphdr)
- || ip_hdrlen(*pskb) < sizeof(struct iphdr)) {
+ if (skb->len < sizeof(struct iphdr) ||
+ ip_hdrlen(skb) < sizeof(struct iphdr)) {
if (net_ratelimit())
printk("iptable_filter: ignoring short SOCK_RAW "
"packet.\n");
return NF_ACCEPT;
}
- return ipt_do_table(pskb, hook, in, out, &packet_filter);
+ return ipt_do_table(skb, hook, in, out, &packet_filter);
}
static struct nf_hook_ops ipt_ops[] = {
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index 902446f7cbca..b4360a69d5ca 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -75,17 +75,17 @@ static struct xt_table packet_mangler = {
/* The work comes in here from netfilter.c. */
static unsigned int
ipt_route_hook(unsigned int hook,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
- return ipt_do_table(pskb, hook, in, out, &packet_mangler);
+ return ipt_do_table(skb, hook, in, out, &packet_mangler);
}
static unsigned int
ipt_local_hook(unsigned int hook,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
@@ -97,8 +97,8 @@ ipt_local_hook(unsigned int hook,
u_int32_t mark;
/* root is playing with raw sockets. */
- if ((*pskb)->len < sizeof(struct iphdr)
- || ip_hdrlen(*pskb) < sizeof(struct iphdr)) {
+ if (skb->len < sizeof(struct iphdr)
+ || ip_hdrlen(skb) < sizeof(struct iphdr)) {
if (net_ratelimit())
printk("iptable_mangle: ignoring short SOCK_RAW "
"packet.\n");
@@ -106,22 +106,22 @@ ipt_local_hook(unsigned int hook,
}
/* Save things which could affect route */
- mark = (*pskb)->mark;
- iph = ip_hdr(*pskb);
+ mark = skb->mark;
+ iph = ip_hdr(skb);
saddr = iph->saddr;
daddr = iph->daddr;
tos = iph->tos;
- ret = ipt_do_table(pskb, hook, in, out, &packet_mangler);
+ ret = ipt_do_table(skb, hook, in, out, &packet_mangler);
/* Reroute for ANY change. */
if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE) {
- iph = ip_hdr(*pskb);
+ iph = ip_hdr(skb);
if (iph->saddr != saddr ||
iph->daddr != daddr ||
- (*pskb)->mark != mark ||
+ skb->mark != mark ||
iph->tos != tos)
- if (ip_route_me_harder(pskb, RTN_UNSPEC))
+ if (ip_route_me_harder(skb, RTN_UNSPEC))
ret = NF_DROP;
}
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
index d6e503395684..5de6e57ac55c 100644
--- a/net/ipv4/netfilter/iptable_raw.c
+++ b/net/ipv4/netfilter/iptable_raw.c
@@ -47,30 +47,30 @@ static struct xt_table packet_raw = {
/* The work comes in here from netfilter.c. */
static unsigned int
ipt_hook(unsigned int hook,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
- return ipt_do_table(pskb, hook, in, out, &packet_raw);
+ return ipt_do_table(skb, hook, in, out, &packet_raw);
}
static unsigned int
ipt_local_hook(unsigned int hook,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
/* root is playing with raw sockets. */
- if ((*pskb)->len < sizeof(struct iphdr) ||
- ip_hdrlen(*pskb) < sizeof(struct iphdr)) {
+ if (skb->len < sizeof(struct iphdr) ||
+ ip_hdrlen(skb) < sizeof(struct iphdr)) {
if (net_ratelimit())
printk("iptable_raw: ignoring short SOCK_RAW"
"packet.\n");
return NF_ACCEPT;
}
- return ipt_do_table(pskb, hook, in, out, &packet_raw);
+ return ipt_do_table(skb, hook, in, out, &packet_raw);
}
/* 'raw' is the very first table. */
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 2fcb9249a8da..831e9b29806d 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -63,19 +63,20 @@ static int ipv4_print_conntrack(struct seq_file *s,
}
/* Returns new sk_buff, or NULL */
-static struct sk_buff *
-nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user)
+static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user)
{
+ int err;
+
skb_orphan(skb);
local_bh_disable();
- skb = ip_defrag(skb, user);
+ err = ip_defrag(skb, user);
local_bh_enable();
- if (skb)
+ if (!err)
ip_send_check(ip_hdr(skb));
- return skb;
+ return err;
}
static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
@@ -99,17 +100,17 @@ static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
}
static unsigned int ipv4_confirm(unsigned int hooknum,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
/* We've seen it coming out the other side: confirm it */
- return nf_conntrack_confirm(pskb);
+ return nf_conntrack_confirm(skb);
}
static unsigned int ipv4_conntrack_help(unsigned int hooknum,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
@@ -120,7 +121,7 @@ static unsigned int ipv4_conntrack_help(unsigned int hooknum,
struct nf_conntrack_helper *helper;
/* This is where we call the helper: as the packet goes out. */
- ct = nf_ct_get(*pskb, &ctinfo);
+ ct = nf_ct_get(skb, &ctinfo);
if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)
return NF_ACCEPT;
@@ -131,56 +132,55 @@ static unsigned int ipv4_conntrack_help(unsigned int hooknum,
helper = rcu_dereference(help->helper);
if (!helper)
return NF_ACCEPT;
- return helper->help(pskb, skb_network_offset(*pskb) + ip_hdrlen(*pskb),
+ return helper->help(skb, skb_network_offset(skb) + ip_hdrlen(skb),
ct, ctinfo);
}
static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
/* Previously seen (loopback)? Ignore. Do this before
fragment check. */
- if ((*pskb)->nfct)
+ if (skb->nfct)
return NF_ACCEPT;
/* Gather fragments. */
- if (ip_hdr(*pskb)->frag_off & htons(IP_MF | IP_OFFSET)) {
- *pskb = nf_ct_ipv4_gather_frags(*pskb,
- hooknum == NF_IP_PRE_ROUTING ?
- IP_DEFRAG_CONNTRACK_IN :
- IP_DEFRAG_CONNTRACK_OUT);
- if (!*pskb)
+ if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
+ if (nf_ct_ipv4_gather_frags(skb,
+ hooknum == NF_IP_PRE_ROUTING ?
+ IP_DEFRAG_CONNTRACK_IN :
+ IP_DEFRAG_CONNTRACK_OUT))
return NF_STOLEN;
}
return NF_ACCEPT;
}
static unsigned int ipv4_conntrack_in(unsigned int hooknum,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
- return nf_conntrack_in(PF_INET, hooknum, pskb);
+ return nf_conntrack_in(PF_INET, hooknum, skb);
}
static unsigned int ipv4_conntrack_local(unsigned int hooknum,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
/* root is playing with raw sockets. */
- if ((*pskb)->len < sizeof(struct iphdr)
- || ip_hdrlen(*pskb) < sizeof(struct iphdr)) {
+ if (skb->len < sizeof(struct iphdr) ||
+ ip_hdrlen(skb) < sizeof(struct iphdr)) {
if (net_ratelimit())
printk("ipt_hook: happy cracking.\n");
return NF_ACCEPT;
}
- return nf_conntrack_in(PF_INET, hooknum, pskb);
+ return nf_conntrack_in(PF_INET, hooknum, skb);
}
/* Connection tracking may drop packets, but never alters them, so
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
index 11fedc73049c..adcbaf6d4299 100644
--- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
@@ -281,7 +281,6 @@ static int icmp_nlattr_to_tuple(struct nlattr *tb[],
static struct ctl_table_header *icmp_sysctl_header;
static struct ctl_table icmp_sysctl_table[] = {
{
- .ctl_name = NET_NF_CONNTRACK_ICMP_TIMEOUT,
.procname = "nf_conntrack_icmp_timeout",
.data = &nf_ct_icmp_timeout,
.maxlen = sizeof(unsigned int),
@@ -295,7 +294,6 @@ static struct ctl_table icmp_sysctl_table[] = {
#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
static struct ctl_table icmp_compat_sysctl_table[] = {
{
- .ctl_name = NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT,
.procname = "ip_conntrack_icmp_timeout",
.data = &nf_ct_icmp_timeout,
.maxlen = sizeof(unsigned int),
diff --git a/net/ipv4/netfilter/nf_nat_amanda.c b/net/ipv4/netfilter/nf_nat_amanda.c
index bd93a1d71052..c31b87668250 100644
--- a/net/ipv4/netfilter/nf_nat_amanda.c
+++ b/net/ipv4/netfilter/nf_nat_amanda.c
@@ -24,7 +24,7 @@ MODULE_DESCRIPTION("Amanda NAT helper");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ip_nat_amanda");
-static unsigned int help(struct sk_buff **pskb,
+static unsigned int help(struct sk_buff *skb,
enum ip_conntrack_info ctinfo,
unsigned int matchoff,
unsigned int matchlen,
@@ -53,7 +53,7 @@ static unsigned int help(struct sk_buff **pskb,
return NF_DROP;
sprintf(buffer, "%u", port);
- ret = nf_nat_mangle_udp_packet(pskb, exp->master, ctinfo,
+ ret = nf_nat_mangle_udp_packet(skb, exp->master, ctinfo,
matchoff, matchlen,
buffer, strlen(buffer));
if (ret != NF_ACCEPT)
@@ -69,7 +69,7 @@ static void __exit nf_nat_amanda_fini(void)
static int __init nf_nat_amanda_init(void)
{
- BUG_ON(rcu_dereference(nf_nat_amanda_hook));
+ BUG_ON(nf_nat_amanda_hook != NULL);
rcu_assign_pointer(nf_nat_amanda_hook, help);
return 0;
}
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c
index 7221aa20e6ff..70e7997ea284 100644
--- a/net/ipv4/netfilter/nf_nat_core.c
+++ b/net/ipv4/netfilter/nf_nat_core.c
@@ -349,7 +349,7 @@ EXPORT_SYMBOL(nf_nat_setup_info);
/* Returns true if succeeded. */
static int
manip_pkt(u_int16_t proto,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
unsigned int iphdroff,
const struct nf_conntrack_tuple *target,
enum nf_nat_manip_type maniptype)
@@ -357,19 +357,19 @@ manip_pkt(u_int16_t proto,
struct iphdr *iph;
struct nf_nat_protocol *p;
- if (!skb_make_writable(pskb, iphdroff + sizeof(*iph)))
+ if (!skb_make_writable(skb, iphdroff + sizeof(*iph)))
return 0;
- iph = (void *)(*pskb)->data + iphdroff;
+ iph = (void *)skb->data + iphdroff;
/* Manipulate protcol part. */
/* rcu_read_lock()ed by nf_hook_slow */
p = __nf_nat_proto_find(proto);
- if (!p->manip_pkt(pskb, iphdroff, target, maniptype))
+ if (!p->manip_pkt(skb, iphdroff, target, maniptype))
return 0;
- iph = (void *)(*pskb)->data + iphdroff;
+ iph = (void *)skb->data + iphdroff;
if (maniptype == IP_NAT_MANIP_SRC) {
nf_csum_replace4(&iph->check, iph->saddr, target->src.u3.ip);
@@ -385,7 +385,7 @@ manip_pkt(u_int16_t proto,
unsigned int nf_nat_packet(struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned int hooknum,
- struct sk_buff **pskb)
+ struct sk_buff *skb)
{
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
unsigned long statusbit;
@@ -407,7 +407,7 @@ unsigned int nf_nat_packet(struct nf_conn *ct,
/* We are aiming to look like inverse of other direction. */
nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple);
- if (!manip_pkt(target.dst.protonum, pskb, 0, &target, mtype))
+ if (!manip_pkt(target.dst.protonum, skb, 0, &target, mtype))
return NF_DROP;
}
return NF_ACCEPT;
@@ -418,7 +418,7 @@ EXPORT_SYMBOL_GPL(nf_nat_packet);
int nf_nat_icmp_reply_translation(struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned int hooknum,
- struct sk_buff **pskb)
+ struct sk_buff *skb)
{
struct {
struct icmphdr icmp;
@@ -426,24 +426,24 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct,
} *inside;
struct nf_conntrack_l4proto *l4proto;
struct nf_conntrack_tuple inner, target;
- int hdrlen = ip_hdrlen(*pskb);
+ int hdrlen = ip_hdrlen(skb);
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
unsigned long statusbit;
enum nf_nat_manip_type manip = HOOK2MANIP(hooknum);
- if (!skb_make_writable(pskb, hdrlen + sizeof(*inside)))
+ if (!skb_make_writable(skb, hdrlen + sizeof(*inside)))
return 0;
- inside = (void *)(*pskb)->data + ip_hdrlen(*pskb);
+ inside = (void *)skb->data + ip_hdrlen(skb);
/* We're actually going to mangle it beyond trivial checksum
adjustment, so make sure the current checksum is correct. */
- if (nf_ip_checksum(*pskb, hooknum, hdrlen, 0))
+ if (nf_ip_checksum(skb, hooknum, hdrlen, 0))
return 0;
/* Must be RELATED */
- NF_CT_ASSERT((*pskb)->nfctinfo == IP_CT_RELATED ||
- (*pskb)->nfctinfo == IP_CT_RELATED+IP_CT_IS_REPLY);
+ NF_CT_ASSERT(skb->nfctinfo == IP_CT_RELATED ||
+ skb->nfctinfo == IP_CT_RELATED+IP_CT_IS_REPLY);
/* Redirects on non-null nats must be dropped, else they'll
start talking to each other without our translation, and be
@@ -458,15 +458,15 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct,
}
pr_debug("icmp_reply_translation: translating error %p manip %u "
- "dir %s\n", *pskb, manip,
+ "dir %s\n", skb, manip,
dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY");
/* rcu_read_lock()ed by nf_hook_slow */
l4proto = __nf_ct_l4proto_find(PF_INET, inside->ip.protocol);
- if (!nf_ct_get_tuple(*pskb,
- ip_hdrlen(*pskb) + sizeof(struct icmphdr),
- (ip_hdrlen(*pskb) +
+ if (!nf_ct_get_tuple(skb,
+ ip_hdrlen(skb) + sizeof(struct icmphdr),
+ (ip_hdrlen(skb) +
sizeof(struct icmphdr) + inside->ip.ihl * 4),
(u_int16_t)AF_INET,
inside->ip.protocol,
@@ -478,19 +478,19 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct,
pass all hooks (locally-generated ICMP). Consider incoming
packet: PREROUTING (DST manip), routing produces ICMP, goes
through POSTROUTING (which must correct the DST manip). */
- if (!manip_pkt(inside->ip.protocol, pskb,
- ip_hdrlen(*pskb) + sizeof(inside->icmp),
+ if (!manip_pkt(inside->ip.protocol, skb,
+ ip_hdrlen(skb) + sizeof(inside->icmp),
&ct->tuplehash[!dir].tuple,
!manip))
return 0;
- if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
+ if (skb->ip_summed != CHECKSUM_PARTIAL) {
/* Reloading "inside" here since manip_pkt inner. */
- inside = (void *)(*pskb)->data + ip_hdrlen(*pskb);
+ inside = (void *)skb->data + ip_hdrlen(skb);
inside->icmp.checksum = 0;
inside->icmp.checksum =
- csum_fold(skb_checksum(*pskb, hdrlen,
- (*pskb)->len - hdrlen, 0));
+ csum_fold(skb_checksum(skb, hdrlen,
+ skb->len - hdrlen, 0));
}
/* Change outer to look the reply to an incoming packet
@@ -506,7 +506,7 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct,
if (ct->status & statusbit) {
nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple);
- if (!manip_pkt(0, pskb, 0, &target, manip))
+ if (!manip_pkt(0, skb, 0, &target, manip))
return 0;
}
@@ -681,7 +681,7 @@ static int clean_nat(struct nf_conn *i, void *data)
if (!nat)
return 0;
- memset(nat, 0, sizeof(nat));
+ memset(nat, 0, sizeof(*nat));
i->status &= ~(IPS_NAT_MASK | IPS_NAT_DONE_MASK | IPS_SEQ_ADJUST);
return 0;
}
diff --git a/net/ipv4/netfilter/nf_nat_ftp.c b/net/ipv4/netfilter/nf_nat_ftp.c
index 3663bd879c39..a1d5d58a58bf 100644
--- a/net/ipv4/netfilter/nf_nat_ftp.c
+++ b/net/ipv4/netfilter/nf_nat_ftp.c
@@ -28,7 +28,7 @@ MODULE_ALIAS("ip_nat_ftp");
/* FIXME: Time out? --RR */
static int
-mangle_rfc959_packet(struct sk_buff **pskb,
+mangle_rfc959_packet(struct sk_buff *skb,
__be32 newip,
u_int16_t port,
unsigned int matchoff,
@@ -43,13 +43,13 @@ mangle_rfc959_packet(struct sk_buff **pskb,
pr_debug("calling nf_nat_mangle_tcp_packet\n");
- return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff,
+ return nf_nat_mangle_tcp_packet(skb, ct, ctinfo, matchoff,
matchlen, buffer, strlen(buffer));
}
/* |1|132.235.1.2|6275| */
static int
-mangle_eprt_packet(struct sk_buff **pskb,
+mangle_eprt_packet(struct sk_buff *skb,
__be32 newip,
u_int16_t port,
unsigned int matchoff,
@@ -63,13 +63,13 @@ mangle_eprt_packet(struct sk_buff **pskb,
pr_debug("calling nf_nat_mangle_tcp_packet\n");
- return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff,
+ return nf_nat_mangle_tcp_packet(skb, ct, ctinfo, matchoff,
matchlen, buffer, strlen(buffer));
}
/* |1|132.235.1.2|6275| */
static int
-mangle_epsv_packet(struct sk_buff **pskb,
+mangle_epsv_packet(struct sk_buff *skb,
__be32 newip,
u_int16_t port,
unsigned int matchoff,
@@ -83,11 +83,11 @@ mangle_epsv_packet(struct sk_buff **pskb,
pr_debug("calling nf_nat_mangle_tcp_packet\n");
- return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff,
+ return nf_nat_mangle_tcp_packet(skb, ct, ctinfo, matchoff,
matchlen, buffer, strlen(buffer));
}
-static int (*mangle[])(struct sk_buff **, __be32, u_int16_t,
+static int (*mangle[])(struct sk_buff *, __be32, u_int16_t,
unsigned int, unsigned int, struct nf_conn *,
enum ip_conntrack_info)
= {
@@ -99,7 +99,7 @@ static int (*mangle[])(struct sk_buff **, __be32, u_int16_t,
/* So, this packet has hit the connection tracking matching code.
Mangle it, and change the expectation to match the new version. */
-static unsigned int nf_nat_ftp(struct sk_buff **pskb,
+static unsigned int nf_nat_ftp(struct sk_buff *skb,
enum ip_conntrack_info ctinfo,
enum nf_ct_ftp_type type,
unsigned int matchoff,
@@ -132,7 +132,7 @@ static unsigned int nf_nat_ftp(struct sk_buff **pskb,
if (port == 0)
return NF_DROP;
- if (!mangle[type](pskb, newip, port, matchoff, matchlen, ct, ctinfo)) {
+ if (!mangle[type](skb, newip, port, matchoff, matchlen, ct, ctinfo)) {
nf_ct_unexpect_related(exp);
return NF_DROP;
}
@@ -147,7 +147,7 @@ static void __exit nf_nat_ftp_fini(void)
static int __init nf_nat_ftp_init(void)
{
- BUG_ON(rcu_dereference(nf_nat_ftp_hook));
+ BUG_ON(nf_nat_ftp_hook != NULL);
rcu_assign_pointer(nf_nat_ftp_hook, nf_nat_ftp);
return 0;
}
diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c
index c1b059a73708..93e18ef114f2 100644
--- a/net/ipv4/netfilter/nf_nat_h323.c
+++ b/net/ipv4/netfilter/nf_nat_h323.c
@@ -22,12 +22,12 @@
#include <linux/netfilter/nf_conntrack_h323.h>
/****************************************************************************/
-static int set_addr(struct sk_buff **pskb,
+static int set_addr(struct sk_buff *skb,
unsigned char **data, int dataoff,
unsigned int addroff, __be32 ip, __be16 port)
{
enum ip_conntrack_info ctinfo;
- struct nf_conn *ct = nf_ct_get(*pskb, &ctinfo);
+ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
struct {
__be32 ip;
__be16 port;
@@ -38,8 +38,8 @@ static int set_addr(struct sk_buff **pskb,
buf.port = port;
addroff += dataoff;
- if (ip_hdr(*pskb)->protocol == IPPROTO_TCP) {
- if (!nf_nat_mangle_tcp_packet(pskb, ct, ctinfo,
+ if (ip_hdr(skb)->protocol == IPPROTO_TCP) {
+ if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo,
addroff, sizeof(buf),
(char *) &buf, sizeof(buf))) {
if (net_ratelimit())
@@ -49,14 +49,13 @@ static int set_addr(struct sk_buff **pskb,
}
/* Relocate data pointer */
- th = skb_header_pointer(*pskb, ip_hdrlen(*pskb),
+ th = skb_header_pointer(skb, ip_hdrlen(skb),
sizeof(_tcph), &_tcph);
if (th == NULL)
return -1;
- *data = (*pskb)->data + ip_hdrlen(*pskb) +
- th->doff * 4 + dataoff;
+ *data = skb->data + ip_hdrlen(skb) + th->doff * 4 + dataoff;
} else {
- if (!nf_nat_mangle_udp_packet(pskb, ct, ctinfo,
+ if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo,
addroff, sizeof(buf),
(char *) &buf, sizeof(buf))) {
if (net_ratelimit())
@@ -67,36 +66,35 @@ static int set_addr(struct sk_buff **pskb,
/* nf_nat_mangle_udp_packet uses skb_make_writable() to copy
* or pull everything in a linear buffer, so we can safely
* use the skb pointers now */
- *data = ((*pskb)->data + ip_hdrlen(*pskb) +
- sizeof(struct udphdr));
+ *data = skb->data + ip_hdrlen(skb) + sizeof(struct udphdr);
}
return 0;
}
/****************************************************************************/
-static int set_h225_addr(struct sk_buff **pskb,
+static int set_h225_addr(struct sk_buff *skb,
unsigned char **data, int dataoff,
TransportAddress *taddr,
union nf_conntrack_address *addr, __be16 port)
{
- return set_addr(pskb, data, dataoff, taddr->ipAddress.ip,
+ return set_addr(skb, data, dataoff, taddr->ipAddress.ip,
addr->ip, port);
}
/****************************************************************************/
-static int set_h245_addr(struct sk_buff **pskb,
+static int set_h245_addr(struct sk_buff *skb,
unsigned char **data, int dataoff,
H245_TransportAddress *taddr,
union nf_conntrack_address *addr, __be16 port)
{
- return set_addr(pskb, data, dataoff,
+ return set_addr(skb, data, dataoff,
taddr->unicastAddress.iPAddress.network,
addr->ip, port);
}
/****************************************************************************/
-static int set_sig_addr(struct sk_buff **pskb, struct nf_conn *ct,
+static int set_sig_addr(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data,
TransportAddress *taddr, int count)
@@ -125,7 +123,7 @@ static int set_sig_addr(struct sk_buff **pskb, struct nf_conn *ct,
NIPQUAD(addr.ip), port,
NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip),
info->sig_port[!dir]);
- return set_h225_addr(pskb, data, 0, &taddr[i],
+ return set_h225_addr(skb, data, 0, &taddr[i],
&ct->tuplehash[!dir].
tuple.dst.u3,
info->sig_port[!dir]);
@@ -137,7 +135,7 @@ static int set_sig_addr(struct sk_buff **pskb, struct nf_conn *ct,
NIPQUAD(addr.ip), port,
NIPQUAD(ct->tuplehash[!dir].tuple.src.u3.ip),
info->sig_port[!dir]);
- return set_h225_addr(pskb, data, 0, &taddr[i],
+ return set_h225_addr(skb, data, 0, &taddr[i],
&ct->tuplehash[!dir].
tuple.src.u3,
info->sig_port[!dir]);
@@ -149,7 +147,7 @@ static int set_sig_addr(struct sk_buff **pskb, struct nf_conn *ct,
}
/****************************************************************************/
-static int set_ras_addr(struct sk_buff **pskb, struct nf_conn *ct,
+static int set_ras_addr(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data,
TransportAddress *taddr, int count)
@@ -168,7 +166,7 @@ static int set_ras_addr(struct sk_buff **pskb, struct nf_conn *ct,
NIPQUAD(addr.ip), ntohs(port),
NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip),
ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port));
- return set_h225_addr(pskb, data, 0, &taddr[i],
+ return set_h225_addr(skb, data, 0, &taddr[i],
&ct->tuplehash[!dir].tuple.dst.u3,
ct->tuplehash[!dir].tuple.
dst.u.udp.port);
@@ -179,7 +177,7 @@ static int set_ras_addr(struct sk_buff **pskb, struct nf_conn *ct,
}
/****************************************************************************/
-static int nat_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct,
+static int nat_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
H245_TransportAddress *taddr,
@@ -244,7 +242,7 @@ static int nat_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct,
}
/* Modify signal */
- if (set_h245_addr(pskb, data, dataoff, taddr,
+ if (set_h245_addr(skb, data, dataoff, taddr,
&ct->tuplehash[!dir].tuple.dst.u3,
htons((port & htons(1)) ? nated_port + 1 :
nated_port)) == 0) {
@@ -273,7 +271,7 @@ static int nat_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct,
}
/****************************************************************************/
-static int nat_t120(struct sk_buff **pskb, struct nf_conn *ct,
+static int nat_t120(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
H245_TransportAddress *taddr, __be16 port,
@@ -301,7 +299,7 @@ static int nat_t120(struct sk_buff **pskb, struct nf_conn *ct,
}
/* Modify signal */
- if (set_h245_addr(pskb, data, dataoff, taddr,
+ if (set_h245_addr(skb, data, dataoff, taddr,
&ct->tuplehash[!dir].tuple.dst.u3,
htons(nated_port)) < 0) {
nf_ct_unexpect_related(exp);
@@ -318,7 +316,7 @@ static int nat_t120(struct sk_buff **pskb, struct nf_conn *ct,
}
/****************************************************************************/
-static int nat_h245(struct sk_buff **pskb, struct nf_conn *ct,
+static int nat_h245(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
TransportAddress *taddr, __be16 port,
@@ -351,7 +349,7 @@ static int nat_h245(struct sk_buff **pskb, struct nf_conn *ct,
}
/* Modify signal */
- if (set_h225_addr(pskb, data, dataoff, taddr,
+ if (set_h225_addr(skb, data, dataoff, taddr,
&ct->tuplehash[!dir].tuple.dst.u3,
htons(nated_port)) == 0) {
/* Save ports */
@@ -406,7 +404,7 @@ static void ip_nat_q931_expect(struct nf_conn *new,
}
/****************************************************************************/
-static int nat_q931(struct sk_buff **pskb, struct nf_conn *ct,
+static int nat_q931(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, TransportAddress *taddr, int idx,
__be16 port, struct nf_conntrack_expect *exp)
@@ -439,7 +437,7 @@ static int nat_q931(struct sk_buff **pskb, struct nf_conn *ct,
}
/* Modify signal */
- if (set_h225_addr(pskb, data, 0, &taddr[idx],
+ if (set_h225_addr(skb, data, 0, &taddr[idx],
&ct->tuplehash[!dir].tuple.dst.u3,
htons(nated_port)) == 0) {
/* Save ports */
@@ -450,7 +448,7 @@ static int nat_q931(struct sk_buff **pskb, struct nf_conn *ct,
if (idx > 0 &&
get_h225_addr(ct, *data, &taddr[0], &addr, &port) &&
(ntohl(addr.ip) & 0xff000000) == 0x7f000000) {
- set_h225_addr(pskb, data, 0, &taddr[0],
+ set_h225_addr(skb, data, 0, &taddr[0],
&ct->tuplehash[!dir].tuple.dst.u3,
info->sig_port[!dir]);
}
@@ -495,7 +493,7 @@ static void ip_nat_callforwarding_expect(struct nf_conn *new,
}
/****************************************************************************/
-static int nat_callforwarding(struct sk_buff **pskb, struct nf_conn *ct,
+static int nat_callforwarding(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
TransportAddress *taddr, __be16 port,
@@ -525,7 +523,7 @@ static int nat_callforwarding(struct sk_buff **pskb, struct nf_conn *ct,
}
/* Modify signal */
- if (!set_h225_addr(pskb, data, dataoff, taddr,
+ if (!set_h225_addr(skb, data, dataoff, taddr,
&ct->tuplehash[!dir].tuple.dst.u3,
htons(nated_port)) == 0) {
nf_ct_unexpect_related(exp);
@@ -546,15 +544,15 @@ static int nat_callforwarding(struct sk_buff **pskb, struct nf_conn *ct,
/****************************************************************************/
static int __init init(void)
{
- BUG_ON(rcu_dereference(set_h245_addr_hook) != NULL);
- BUG_ON(rcu_dereference(set_h225_addr_hook) != NULL);
- BUG_ON(rcu_dereference(set_sig_addr_hook) != NULL);
- BUG_ON(rcu_dereference(set_ras_addr_hook) != NULL);
- BUG_ON(rcu_dereference(nat_rtp_rtcp_hook) != NULL);
- BUG_ON(rcu_dereference(nat_t120_hook) != NULL);
- BUG_ON(rcu_dereference(nat_h245_hook) != NULL);
- BUG_ON(rcu_dereference(nat_callforwarding_hook) != NULL);
- BUG_ON(rcu_dereference(nat_q931_hook) != NULL);
+ BUG_ON(set_h245_addr_hook != NULL);
+ BUG_ON(set_h225_addr_hook != NULL);
+ BUG_ON(set_sig_addr_hook != NULL);
+ BUG_ON(set_ras_addr_hook != NULL);
+ BUG_ON(nat_rtp_rtcp_hook != NULL);
+ BUG_ON(nat_t120_hook != NULL);
+ BUG_ON(nat_h245_hook != NULL);
+ BUG_ON(nat_callforwarding_hook != NULL);
+ BUG_ON(nat_q931_hook != NULL);
rcu_assign_pointer(set_h245_addr_hook, set_h245_addr);
rcu_assign_pointer(set_h225_addr_hook, set_h225_addr);
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c
index 93d8a0a8f035..8718da00ef2a 100644
--- a/net/ipv4/netfilter/nf_nat_helper.c
+++ b/net/ipv4/netfilter/nf_nat_helper.c
@@ -111,22 +111,14 @@ static void mangle_contents(struct sk_buff *skb,
}
/* Unusual, but possible case. */
-static int enlarge_skb(struct sk_buff **pskb, unsigned int extra)
+static int enlarge_skb(struct sk_buff *skb, unsigned int extra)
{
- struct sk_buff *nskb;
-
- if ((*pskb)->len + extra > 65535)
+ if (skb->len + extra > 65535)
return 0;
- nskb = skb_copy_expand(*pskb, skb_headroom(*pskb), extra, GFP_ATOMIC);
- if (!nskb)
+ if (pskb_expand_head(skb, 0, extra - skb_tailroom(skb), GFP_ATOMIC))
return 0;
- /* Transfer socket to new skb. */
- if ((*pskb)->sk)
- skb_set_owner_w(nskb, (*pskb)->sk);
- kfree_skb(*pskb);
- *pskb = nskb;
return 1;
}
@@ -139,7 +131,7 @@ static int enlarge_skb(struct sk_buff **pskb, unsigned int extra)
*
* */
int
-nf_nat_mangle_tcp_packet(struct sk_buff **pskb,
+nf_nat_mangle_tcp_packet(struct sk_buff *skb,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned int match_offset,
@@ -147,37 +139,37 @@ nf_nat_mangle_tcp_packet(struct sk_buff **pskb,
const char *rep_buffer,
unsigned int rep_len)
{
- struct rtable *rt = (struct rtable *)(*pskb)->dst;
+ struct rtable *rt = (struct rtable *)skb->dst;
struct iphdr *iph;
struct tcphdr *tcph;
int oldlen, datalen;
- if (!skb_make_writable(pskb, (*pskb)->len))
+ if (!skb_make_writable(skb, skb->len))
return 0;
if (rep_len > match_len &&
- rep_len - match_len > skb_tailroom(*pskb) &&
- !enlarge_skb(pskb, rep_len - match_len))
+ rep_len - match_len > skb_tailroom(skb) &&
+ !enlarge_skb(skb, rep_len - match_len))
return 0;
- SKB_LINEAR_ASSERT(*pskb);
+ SKB_LINEAR_ASSERT(skb);
- iph = ip_hdr(*pskb);
+ iph = ip_hdr(skb);
tcph = (void *)iph + iph->ihl*4;
- oldlen = (*pskb)->len - iph->ihl*4;
- mangle_contents(*pskb, iph->ihl*4 + tcph->doff*4,
+ oldlen = skb->len - iph->ihl*4;
+ mangle_contents(skb, iph->ihl*4 + tcph->doff*4,
match_offset, match_len, rep_buffer, rep_len);
- datalen = (*pskb)->len - iph->ihl*4;
- if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
+ datalen = skb->len - iph->ihl*4;
+ if (skb->ip_summed != CHECKSUM_PARTIAL) {
if (!(rt->rt_flags & RTCF_LOCAL) &&
- (*pskb)->dev->features & NETIF_F_V4_CSUM) {
- (*pskb)->ip_summed = CHECKSUM_PARTIAL;
- (*pskb)->csum_start = skb_headroom(*pskb) +
- skb_network_offset(*pskb) +
- iph->ihl * 4;
- (*pskb)->csum_offset = offsetof(struct tcphdr, check);
+ skb->dev->features & NETIF_F_V4_CSUM) {
+ skb->ip_summed = CHECKSUM_PARTIAL;
+ skb->csum_start = skb_headroom(skb) +
+ skb_network_offset(skb) +
+ iph->ihl * 4;
+ skb->csum_offset = offsetof(struct tcphdr, check);
tcph->check = ~tcp_v4_check(datalen,
iph->saddr, iph->daddr, 0);
} else {
@@ -188,7 +180,7 @@ nf_nat_mangle_tcp_packet(struct sk_buff **pskb,
datalen, 0));
}
} else
- nf_proto_csum_replace2(&tcph->check, *pskb,
+ nf_proto_csum_replace2(&tcph->check, skb,
htons(oldlen), htons(datalen), 1);
if (rep_len != match_len) {
@@ -197,7 +189,7 @@ nf_nat_mangle_tcp_packet(struct sk_buff **pskb,
(int)rep_len - (int)match_len,
ct, ctinfo);
/* Tell TCP window tracking about seq change */
- nf_conntrack_tcp_update(*pskb, ip_hdrlen(*pskb),
+ nf_conntrack_tcp_update(skb, ip_hdrlen(skb),
ct, CTINFO2DIR(ctinfo));
}
return 1;
@@ -215,7 +207,7 @@ EXPORT_SYMBOL(nf_nat_mangle_tcp_packet);
* should be fairly easy to do.
*/
int
-nf_nat_mangle_udp_packet(struct sk_buff **pskb,
+nf_nat_mangle_udp_packet(struct sk_buff *skb,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned int match_offset,
@@ -223,48 +215,48 @@ nf_nat_mangle_udp_packet(struct sk_buff **pskb,
const char *rep_buffer,
unsigned int rep_len)
{
- struct rtable *rt = (struct rtable *)(*pskb)->dst;
+ struct rtable *rt = (struct rtable *)skb->dst;
struct iphdr *iph;
struct udphdr *udph;
int datalen, oldlen;
/* UDP helpers might accidentally mangle the wrong packet */
- iph = ip_hdr(*pskb);
- if ((*pskb)->len < iph->ihl*4 + sizeof(*udph) +
+ iph = ip_hdr(skb);
+ if (skb->len < iph->ihl*4 + sizeof(*udph) +
match_offset + match_len)
return 0;
- if (!skb_make_writable(pskb, (*pskb)->len))
+ if (!skb_make_writable(skb, skb->len))
return 0;
if (rep_len > match_len &&
- rep_len - match_len > skb_tailroom(*pskb) &&
- !enlarge_skb(pskb, rep_len - match_len))
+ rep_len - match_len > skb_tailroom(skb) &&
+ !enlarge_skb(skb, rep_len - match_len))
return 0;
- iph = ip_hdr(*pskb);
+ iph = ip_hdr(skb);
udph = (void *)iph + iph->ihl*4;
- oldlen = (*pskb)->len - iph->ihl*4;
- mangle_contents(*pskb, iph->ihl*4 + sizeof(*udph),
+ oldlen = skb->len - iph->ihl*4;
+ mangle_contents(skb, iph->ihl*4 + sizeof(*udph),
match_offset, match_len, rep_buffer, rep_len);
/* update the length of the UDP packet */
- datalen = (*pskb)->len - iph->ihl*4;
+ datalen = skb->len - iph->ihl*4;
udph->len = htons(datalen);
/* fix udp checksum if udp checksum was previously calculated */
- if (!udph->check && (*pskb)->ip_summed != CHECKSUM_PARTIAL)
+ if (!udph->check && skb->ip_summed != CHECKSUM_PARTIAL)
return 1;
- if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
+ if (skb->ip_summed != CHECKSUM_PARTIAL) {
if (!(rt->rt_flags & RTCF_LOCAL) &&
- (*pskb)->dev->features & NETIF_F_V4_CSUM) {
- (*pskb)->ip_summed = CHECKSUM_PARTIAL;
- (*pskb)->csum_start = skb_headroom(*pskb) +
- skb_network_offset(*pskb) +
- iph->ihl * 4;
- (*pskb)->csum_offset = offsetof(struct udphdr, check);
+ skb->dev->features & NETIF_F_V4_CSUM) {
+ skb->ip_summed = CHECKSUM_PARTIAL;
+ skb->csum_start = skb_headroom(skb) +
+ skb_network_offset(skb) +
+ iph->ihl * 4;
+ skb->csum_offset = offsetof(struct udphdr, check);
udph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
datalen, IPPROTO_UDP,
0);
@@ -278,7 +270,7 @@ nf_nat_mangle_udp_packet(struct sk_buff **pskb,
udph->check = CSUM_MANGLED_0;
}
} else
- nf_proto_csum_replace2(&udph->check, *pskb,
+ nf_proto_csum_replace2(&udph->check, skb,
htons(oldlen), htons(datalen), 1);
return 1;
@@ -330,7 +322,7 @@ sack_adjust(struct sk_buff *skb,
/* TCP SACK sequence number adjustment */
static inline unsigned int
-nf_nat_sack_adjust(struct sk_buff **pskb,
+nf_nat_sack_adjust(struct sk_buff *skb,
struct tcphdr *tcph,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo)
@@ -338,17 +330,17 @@ nf_nat_sack_adjust(struct sk_buff **pskb,
unsigned int dir, optoff, optend;
struct nf_conn_nat *nat = nfct_nat(ct);
- optoff = ip_hdrlen(*pskb) + sizeof(struct tcphdr);
- optend = ip_hdrlen(*pskb) + tcph->doff * 4;
+ optoff = ip_hdrlen(skb) + sizeof(struct tcphdr);
+ optend = ip_hdrlen(skb) + tcph->doff * 4;
- if (!skb_make_writable(pskb, optend))
+ if (!skb_make_writable(skb, optend))
return 0;
dir = CTINFO2DIR(ctinfo);
while (optoff < optend) {
/* Usually: option, length. */
- unsigned char *op = (*pskb)->data + optoff;
+ unsigned char *op = skb->data + optoff;
switch (op[0]) {
case TCPOPT_EOL:
@@ -365,7 +357,7 @@ nf_nat_sack_adjust(struct sk_buff **pskb,
if (op[0] == TCPOPT_SACK &&
op[1] >= 2+TCPOLEN_SACK_PERBLOCK &&
((op[1] - 2) % TCPOLEN_SACK_PERBLOCK) == 0)
- sack_adjust(*pskb, tcph, optoff+2,
+ sack_adjust(skb, tcph, optoff+2,
optoff+op[1], &nat->seq[!dir]);
optoff += op[1];
}
@@ -375,7 +367,7 @@ nf_nat_sack_adjust(struct sk_buff **pskb,
/* TCP sequence number adjustment. Returns 1 on success, 0 on failure */
int
-nf_nat_seq_adjust(struct sk_buff **pskb,
+nf_nat_seq_adjust(struct sk_buff *skb,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo)
{
@@ -390,10 +382,10 @@ nf_nat_seq_adjust(struct sk_buff **pskb,
this_way = &nat->seq[dir];
other_way = &nat->seq[!dir];
- if (!skb_make_writable(pskb, ip_hdrlen(*pskb) + sizeof(*tcph)))
+ if (!skb_make_writable(skb, ip_hdrlen(skb) + sizeof(*tcph)))
return 0;
- tcph = (void *)(*pskb)->data + ip_hdrlen(*pskb);
+ tcph = (void *)skb->data + ip_hdrlen(skb);
if (after(ntohl(tcph->seq), this_way->correction_pos))
newseq = htonl(ntohl(tcph->seq) + this_way->offset_after);
else
@@ -405,8 +397,8 @@ nf_nat_seq_adjust(struct sk_buff **pskb,
else
newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_before);
- nf_proto_csum_replace4(&tcph->check, *pskb, tcph->seq, newseq, 0);
- nf_proto_csum_replace4(&tcph->check, *pskb, tcph->ack_seq, newack, 0);
+ nf_proto_csum_replace4(&tcph->check, skb, tcph->seq, newseq, 0);
+ nf_proto_csum_replace4(&tcph->check, skb, tcph->ack_seq, newack, 0);
pr_debug("Adjusting sequence number from %u->%u, ack from %u->%u\n",
ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq),
@@ -415,10 +407,10 @@ nf_nat_seq_adjust(struct sk_buff **pskb,
tcph->seq = newseq;
tcph->ack_seq = newack;
- if (!nf_nat_sack_adjust(pskb, tcph, ct, ctinfo))
+ if (!nf_nat_sack_adjust(skb, tcph, ct, ctinfo))
return 0;
- nf_conntrack_tcp_update(*pskb, ip_hdrlen(*pskb), ct, dir);
+ nf_conntrack_tcp_update(skb, ip_hdrlen(skb), ct, dir);
return 1;
}
diff --git a/net/ipv4/netfilter/nf_nat_irc.c b/net/ipv4/netfilter/nf_nat_irc.c
index bcf274bba602..fe6f9cef6c85 100644
--- a/net/ipv4/netfilter/nf_nat_irc.c
+++ b/net/ipv4/netfilter/nf_nat_irc.c
@@ -27,7 +27,7 @@ MODULE_DESCRIPTION("IRC (DCC) NAT helper");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ip_nat_irc");
-static unsigned int help(struct sk_buff **pskb,
+static unsigned int help(struct sk_buff *skb,
enum ip_conntrack_info ctinfo,
unsigned int matchoff,
unsigned int matchlen,
@@ -58,7 +58,7 @@ static unsigned int help(struct sk_buff **pskb,
pr_debug("nf_nat_irc: inserting '%s' == %u.%u.%u.%u, port %u\n",
buffer, NIPQUAD(ip), port);
- ret = nf_nat_mangle_tcp_packet(pskb, exp->master, ctinfo,
+ ret = nf_nat_mangle_tcp_packet(skb, exp->master, ctinfo,
matchoff, matchlen, buffer,
strlen(buffer));
if (ret != NF_ACCEPT)
@@ -74,7 +74,7 @@ static void __exit nf_nat_irc_fini(void)
static int __init nf_nat_irc_init(void)
{
- BUG_ON(rcu_dereference(nf_nat_irc_hook));
+ BUG_ON(nf_nat_irc_hook != NULL);
rcu_assign_pointer(nf_nat_irc_hook, help);
return 0;
}
diff --git a/net/ipv4/netfilter/nf_nat_pptp.c b/net/ipv4/netfilter/nf_nat_pptp.c
index 984ec8308b2e..6817e7995f35 100644
--- a/net/ipv4/netfilter/nf_nat_pptp.c
+++ b/net/ipv4/netfilter/nf_nat_pptp.c
@@ -110,7 +110,7 @@ static void pptp_nat_expected(struct nf_conn *ct,
/* outbound packets == from PNS to PAC */
static int
-pptp_outbound_pkt(struct sk_buff **pskb,
+pptp_outbound_pkt(struct sk_buff *skb,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
struct PptpControlHeader *ctlh,
@@ -175,7 +175,7 @@ pptp_outbound_pkt(struct sk_buff **pskb,
ntohs(REQ_CID(pptpReq, cid_off)), ntohs(new_callid));
/* mangle packet */
- if (nf_nat_mangle_tcp_packet(pskb, ct, ctinfo,
+ if (nf_nat_mangle_tcp_packet(skb, ct, ctinfo,
cid_off + sizeof(struct pptp_pkt_hdr) +
sizeof(struct PptpControlHeader),
sizeof(new_callid), (char *)&new_callid,
@@ -213,7 +213,7 @@ pptp_exp_gre(struct nf_conntrack_expect *expect_orig,
/* inbound packets == from PAC to PNS */
static int
-pptp_inbound_pkt(struct sk_buff **pskb,
+pptp_inbound_pkt(struct sk_buff *skb,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
struct PptpControlHeader *ctlh,
@@ -268,7 +268,7 @@ pptp_inbound_pkt(struct sk_buff **pskb,
pr_debug("altering peer call id from 0x%04x to 0x%04x\n",
ntohs(REQ_CID(pptpReq, pcid_off)), ntohs(new_pcid));
- if (nf_nat_mangle_tcp_packet(pskb, ct, ctinfo,
+ if (nf_nat_mangle_tcp_packet(skb, ct, ctinfo,
pcid_off + sizeof(struct pptp_pkt_hdr) +
sizeof(struct PptpControlHeader),
sizeof(new_pcid), (char *)&new_pcid,
@@ -281,16 +281,16 @@ static int __init nf_nat_helper_pptp_init(void)
{
nf_nat_need_gre();
- BUG_ON(rcu_dereference(nf_nat_pptp_hook_outbound));
+ BUG_ON(nf_nat_pptp_hook_outbound != NULL);
rcu_assign_pointer(nf_nat_pptp_hook_outbound, pptp_outbound_pkt);
- BUG_ON(rcu_dereference(nf_nat_pptp_hook_inbound));
+ BUG_ON(nf_nat_pptp_hook_inbound != NULL);
rcu_assign_pointer(nf_nat_pptp_hook_inbound, pptp_inbound_pkt);
- BUG_ON(rcu_dereference(nf_nat_pptp_hook_exp_gre));
+ BUG_ON(nf_nat_pptp_hook_exp_gre != NULL);
rcu_assign_pointer(nf_nat_pptp_hook_exp_gre, pptp_exp_gre);
- BUG_ON(rcu_dereference(nf_nat_pptp_hook_expectfn));
+ BUG_ON(nf_nat_pptp_hook_expectfn != NULL);
rcu_assign_pointer(nf_nat_pptp_hook_expectfn, pptp_nat_expected);
return 0;
}
diff --git a/net/ipv4/netfilter/nf_nat_proto_gre.c b/net/ipv4/netfilter/nf_nat_proto_gre.c
index d562290b1820..b820f9960356 100644
--- a/net/ipv4/netfilter/nf_nat_proto_gre.c
+++ b/net/ipv4/netfilter/nf_nat_proto_gre.c
@@ -98,21 +98,21 @@ gre_unique_tuple(struct nf_conntrack_tuple *tuple,
/* manipulate a GRE packet according to maniptype */
static int
-gre_manip_pkt(struct sk_buff **pskb, unsigned int iphdroff,
+gre_manip_pkt(struct sk_buff *skb, unsigned int iphdroff,
const struct nf_conntrack_tuple *tuple,
enum nf_nat_manip_type maniptype)
{
struct gre_hdr *greh;
struct gre_hdr_pptp *pgreh;
- struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
+ struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff);
unsigned int hdroff = iphdroff + iph->ihl * 4;
/* pgreh includes two optional 32bit fields which are not required
* to be there. That's where the magic '8' comes from */
- if (!skb_make_writable(pskb, hdroff + sizeof(*pgreh) - 8))
+ if (!skb_make_writable(skb, hdroff + sizeof(*pgreh) - 8))
return 0;
- greh = (void *)(*pskb)->data + hdroff;
+ greh = (void *)skb->data + hdroff;
pgreh = (struct gre_hdr_pptp *)greh;
/* we only have destination manip of a packet, since 'source key'
diff --git a/net/ipv4/netfilter/nf_nat_proto_icmp.c b/net/ipv4/netfilter/nf_nat_proto_icmp.c
index 898d73771155..b9fc724388fc 100644
--- a/net/ipv4/netfilter/nf_nat_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_nat_proto_icmp.c
@@ -52,20 +52,20 @@ icmp_unique_tuple(struct nf_conntrack_tuple *tuple,
}
static int
-icmp_manip_pkt(struct sk_buff **pskb,
+icmp_manip_pkt(struct sk_buff *skb,
unsigned int iphdroff,
const struct nf_conntrack_tuple *tuple,
enum nf_nat_manip_type maniptype)
{
- struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
+ struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff);
struct icmphdr *hdr;
unsigned int hdroff = iphdroff + iph->ihl*4;
- if (!skb_make_writable(pskb, hdroff + sizeof(*hdr)))
+ if (!skb_make_writable(skb, hdroff + sizeof(*hdr)))
return 0;
- hdr = (struct icmphdr *)((*pskb)->data + hdroff);
- nf_proto_csum_replace2(&hdr->checksum, *pskb,
+ hdr = (struct icmphdr *)(skb->data + hdroff);
+ nf_proto_csum_replace2(&hdr->checksum, skb,
hdr->un.echo.id, tuple->src.u.icmp.id, 0);
hdr->un.echo.id = tuple->src.u.icmp.id;
return 1;
diff --git a/net/ipv4/netfilter/nf_nat_proto_tcp.c b/net/ipv4/netfilter/nf_nat_proto_tcp.c
index 5bbbb2acdc70..6bab2e184455 100644
--- a/net/ipv4/netfilter/nf_nat_proto_tcp.c
+++ b/net/ipv4/netfilter/nf_nat_proto_tcp.c
@@ -88,12 +88,12 @@ tcp_unique_tuple(struct nf_conntrack_tuple *tuple,
}
static int
-tcp_manip_pkt(struct sk_buff **pskb,
+tcp_manip_pkt(struct sk_buff *skb,
unsigned int iphdroff,
const struct nf_conntrack_tuple *tuple,
enum nf_nat_manip_type maniptype)
{
- struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
+ struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff);
struct tcphdr *hdr;
unsigned int hdroff = iphdroff + iph->ihl*4;
__be32 oldip, newip;
@@ -103,14 +103,14 @@ tcp_manip_pkt(struct sk_buff **pskb,
/* this could be a inner header returned in icmp packet; in such
cases we cannot update the checksum field since it is outside of
the 8 bytes of transport layer headers we are guaranteed */
- if ((*pskb)->len >= hdroff + sizeof(struct tcphdr))
+ if (skb->len >= hdroff + sizeof(struct tcphdr))
hdrsize = sizeof(struct tcphdr);
- if (!skb_make_writable(pskb, hdroff + hdrsize))
+ if (!skb_make_writable(skb, hdroff + hdrsize))
return 0;
- iph = (struct iphdr *)((*pskb)->data + iphdroff);
- hdr = (struct tcphdr *)((*pskb)->data + hdroff);
+ iph = (struct iphdr *)(skb->data + iphdroff);
+ hdr = (struct tcphdr *)(skb->data + hdroff);
if (maniptype == IP_NAT_MANIP_SRC) {
/* Get rid of src ip and src pt */
@@ -132,8 +132,8 @@ tcp_manip_pkt(struct sk_buff **pskb,
if (hdrsize < sizeof(*hdr))
return 1;
- nf_proto_csum_replace4(&hdr->check, *pskb, oldip, newip, 1);
- nf_proto_csum_replace2(&hdr->check, *pskb, oldport, newport, 0);
+ nf_proto_csum_replace4(&hdr->check, skb, oldip, newip, 1);
+ nf_proto_csum_replace2(&hdr->check, skb, oldport, newport, 0);
return 1;
}
diff --git a/net/ipv4/netfilter/nf_nat_proto_udp.c b/net/ipv4/netfilter/nf_nat_proto_udp.c
index a0af4fd95584..cbf1a61e2908 100644
--- a/net/ipv4/netfilter/nf_nat_proto_udp.c
+++ b/net/ipv4/netfilter/nf_nat_proto_udp.c
@@ -86,22 +86,22 @@ udp_unique_tuple(struct nf_conntrack_tuple *tuple,
}
static int
-udp_manip_pkt(struct sk_buff **pskb,
+udp_manip_pkt(struct sk_buff *skb,
unsigned int iphdroff,
const struct nf_conntrack_tuple *tuple,
enum nf_nat_manip_type maniptype)
{
- struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
+ struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff);
struct udphdr *hdr;
unsigned int hdroff = iphdroff + iph->ihl*4;
__be32 oldip, newip;
__be16 *portptr, newport;
- if (!skb_make_writable(pskb, hdroff + sizeof(*hdr)))
+ if (!skb_make_writable(skb, hdroff + sizeof(*hdr)))
return 0;
- iph = (struct iphdr *)((*pskb)->data + iphdroff);
- hdr = (struct udphdr *)((*pskb)->data + hdroff);
+ iph = (struct iphdr *)(skb->data + iphdroff);
+ hdr = (struct udphdr *)(skb->data + hdroff);
if (maniptype == IP_NAT_MANIP_SRC) {
/* Get rid of src ip and src pt */
@@ -116,9 +116,9 @@ udp_manip_pkt(struct sk_buff **pskb,
newport = tuple->dst.u.udp.port;
portptr = &hdr->dest;
}
- if (hdr->check || (*pskb)->ip_summed == CHECKSUM_PARTIAL) {
- nf_proto_csum_replace4(&hdr->check, *pskb, oldip, newip, 1);
- nf_proto_csum_replace2(&hdr->check, *pskb, *portptr, newport,
+ if (hdr->check || skb->ip_summed == CHECKSUM_PARTIAL) {
+ nf_proto_csum_replace4(&hdr->check, skb, oldip, newip, 1);
+ nf_proto_csum_replace2(&hdr->check, skb, *portptr, newport,
0);
if (!hdr->check)
hdr->check = CSUM_MANGLED_0;
diff --git a/net/ipv4/netfilter/nf_nat_proto_unknown.c b/net/ipv4/netfilter/nf_nat_proto_unknown.c
index f50d0203f9c0..cfd2742e9706 100644
--- a/net/ipv4/netfilter/nf_nat_proto_unknown.c
+++ b/net/ipv4/netfilter/nf_nat_proto_unknown.c
@@ -37,7 +37,7 @@ static int unknown_unique_tuple(struct nf_conntrack_tuple *tuple,
}
static int
-unknown_manip_pkt(struct sk_buff **pskb,
+unknown_manip_pkt(struct sk_buff *skb,
unsigned int iphdroff,
const struct nf_conntrack_tuple *tuple,
enum nf_nat_manip_type maniptype)
diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c
index 76ec59ae524d..46b25ab5f78b 100644
--- a/net/ipv4/netfilter/nf_nat_rule.c
+++ b/net/ipv4/netfilter/nf_nat_rule.c
@@ -65,7 +65,7 @@ static struct xt_table nat_table = {
};
/* Source NAT */
-static unsigned int ipt_snat_target(struct sk_buff **pskb,
+static unsigned int ipt_snat_target(struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
unsigned int hooknum,
@@ -78,7 +78,7 @@ static unsigned int ipt_snat_target(struct sk_buff **pskb,
NF_CT_ASSERT(hooknum == NF_IP_POST_ROUTING);
- ct = nf_ct_get(*pskb, &ctinfo);
+ ct = nf_ct_get(skb, &ctinfo);
/* Connection must be valid and new. */
NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED ||
@@ -107,7 +107,7 @@ static void warn_if_extra_mangle(__be32 dstip, __be32 srcip)
ip_rt_put(rt);
}
-static unsigned int ipt_dnat_target(struct sk_buff **pskb,
+static unsigned int ipt_dnat_target(struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
unsigned int hooknum,
@@ -121,14 +121,14 @@ static unsigned int ipt_dnat_target(struct sk_buff **pskb,
NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING ||
hooknum == NF_IP_LOCAL_OUT);
- ct = nf_ct_get(*pskb, &ctinfo);
+ ct = nf_ct_get(skb, &ctinfo);
/* Connection must be valid and new. */
NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED));
if (hooknum == NF_IP_LOCAL_OUT &&
mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)
- warn_if_extra_mangle(ip_hdr(*pskb)->daddr,
+ warn_if_extra_mangle(ip_hdr(skb)->daddr,
mr->range[0].min_ip);
return nf_nat_setup_info(ct, &mr->range[0], hooknum);
@@ -204,7 +204,7 @@ alloc_null_binding_confirmed(struct nf_conn *ct, unsigned int hooknum)
return nf_nat_setup_info(ct, &range, hooknum);
}
-int nf_nat_rule_find(struct sk_buff **pskb,
+int nf_nat_rule_find(struct sk_buff *skb,
unsigned int hooknum,
const struct net_device *in,
const struct net_device *out,
@@ -212,7 +212,7 @@ int nf_nat_rule_find(struct sk_buff **pskb,
{
int ret;
- ret = ipt_do_table(pskb, hooknum, in, out, &nat_table);
+ ret = ipt_do_table(skb, hooknum, in, out, &nat_table);
if (ret == NF_ACCEPT) {
if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum)))
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c
index e14d41976c27..3ca98971a1e9 100644
--- a/net/ipv4/netfilter/nf_nat_sip.c
+++ b/net/ipv4/netfilter/nf_nat_sip.c
@@ -60,7 +60,7 @@ static void addr_map_init(struct nf_conn *ct, struct addr_map *map)
}
}
-static int map_sip_addr(struct sk_buff **pskb, enum ip_conntrack_info ctinfo,
+static int map_sip_addr(struct sk_buff *skb, enum ip_conntrack_info ctinfo,
struct nf_conn *ct, const char **dptr, size_t dlen,
enum sip_header_pos pos, struct addr_map *map)
{
@@ -84,15 +84,15 @@ static int map_sip_addr(struct sk_buff **pskb, enum ip_conntrack_info ctinfo,
} else
return 1;
- if (!nf_nat_mangle_udp_packet(pskb, ct, ctinfo,
+ if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo,
matchoff, matchlen, addr, addrlen))
return 0;
- *dptr = (*pskb)->data + ip_hdrlen(*pskb) + sizeof(struct udphdr);
+ *dptr = skb->data + ip_hdrlen(skb) + sizeof(struct udphdr);
return 1;
}
-static unsigned int ip_nat_sip(struct sk_buff **pskb,
+static unsigned int ip_nat_sip(struct sk_buff *skb,
enum ip_conntrack_info ctinfo,
struct nf_conn *ct,
const char **dptr)
@@ -101,8 +101,8 @@ static unsigned int ip_nat_sip(struct sk_buff **pskb,
struct addr_map map;
int dataoff, datalen;
- dataoff = ip_hdrlen(*pskb) + sizeof(struct udphdr);
- datalen = (*pskb)->len - dataoff;
+ dataoff = ip_hdrlen(skb) + sizeof(struct udphdr);
+ datalen = skb->len - dataoff;
if (datalen < sizeof("SIP/2.0") - 1)
return NF_ACCEPT;
@@ -121,19 +121,19 @@ static unsigned int ip_nat_sip(struct sk_buff **pskb,
else
pos = POS_REQ_URI;
- if (!map_sip_addr(pskb, ctinfo, ct, dptr, datalen, pos, &map))
+ if (!map_sip_addr(skb, ctinfo, ct, dptr, datalen, pos, &map))
return NF_DROP;
}
- if (!map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_FROM, &map) ||
- !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_TO, &map) ||
- !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_VIA, &map) ||
- !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_CONTACT, &map))
+ if (!map_sip_addr(skb, ctinfo, ct, dptr, datalen, POS_FROM, &map) ||
+ !map_sip_addr(skb, ctinfo, ct, dptr, datalen, POS_TO, &map) ||
+ !map_sip_addr(skb, ctinfo, ct, dptr, datalen, POS_VIA, &map) ||
+ !map_sip_addr(skb, ctinfo, ct, dptr, datalen, POS_CONTACT, &map))
return NF_DROP;
return NF_ACCEPT;
}
-static unsigned int mangle_sip_packet(struct sk_buff **pskb,
+static unsigned int mangle_sip_packet(struct sk_buff *skb,
enum ip_conntrack_info ctinfo,
struct nf_conn *ct,
const char **dptr, size_t dlen,
@@ -145,16 +145,16 @@ static unsigned int mangle_sip_packet(struct sk_buff **pskb,
if (ct_sip_get_info(ct, *dptr, dlen, &matchoff, &matchlen, pos) <= 0)
return 0;
- if (!nf_nat_mangle_udp_packet(pskb, ct, ctinfo,
+ if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo,
matchoff, matchlen, buffer, bufflen))
return 0;
/* We need to reload this. Thanks Patrick. */
- *dptr = (*pskb)->data + ip_hdrlen(*pskb) + sizeof(struct udphdr);
+ *dptr = skb->data + ip_hdrlen(skb) + sizeof(struct udphdr);
return 1;
}
-static int mangle_content_len(struct sk_buff **pskb,
+static int mangle_content_len(struct sk_buff *skb,
enum ip_conntrack_info ctinfo,
struct nf_conn *ct,
const char *dptr)
@@ -163,22 +163,22 @@ static int mangle_content_len(struct sk_buff **pskb,
char buffer[sizeof("65536")];
int bufflen;
- dataoff = ip_hdrlen(*pskb) + sizeof(struct udphdr);
+ dataoff = ip_hdrlen(skb) + sizeof(struct udphdr);
/* Get actual SDP lenght */
- if (ct_sip_get_info(ct, dptr, (*pskb)->len - dataoff, &matchoff,
+ if (ct_sip_get_info(ct, dptr, skb->len - dataoff, &matchoff,
&matchlen, POS_SDP_HEADER) > 0) {
/* since ct_sip_get_info() give us a pointer passing 'v='
we need to add 2 bytes in this count. */
- int c_len = (*pskb)->len - dataoff - matchoff + 2;
+ int c_len = skb->len - dataoff - matchoff + 2;
/* Now, update SDP length */
- if (ct_sip_get_info(ct, dptr, (*pskb)->len - dataoff, &matchoff,
+ if (ct_sip_get_info(ct, dptr, skb->len - dataoff, &matchoff,
&matchlen, POS_CONTENT) > 0) {
bufflen = sprintf(buffer, "%u", c_len);
- return nf_nat_mangle_udp_packet(pskb, ct, ctinfo,
+ return nf_nat_mangle_udp_packet(skb, ct, ctinfo,
matchoff, matchlen,
buffer, bufflen);
}
@@ -186,7 +186,7 @@ static int mangle_content_len(struct sk_buff **pskb,
return 0;
}
-static unsigned int mangle_sdp(struct sk_buff **pskb,
+static unsigned int mangle_sdp(struct sk_buff *skb,
enum ip_conntrack_info ctinfo,
struct nf_conn *ct,
__be32 newip, u_int16_t port,
@@ -195,25 +195,25 @@ static unsigned int mangle_sdp(struct sk_buff **pskb,
char buffer[sizeof("nnn.nnn.nnn.nnn")];
unsigned int dataoff, bufflen;
- dataoff = ip_hdrlen(*pskb) + sizeof(struct udphdr);
+ dataoff = ip_hdrlen(skb) + sizeof(struct udphdr);
/* Mangle owner and contact info. */
bufflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(newip));
- if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
+ if (!mangle_sip_packet(skb, ctinfo, ct, &dptr, skb->len - dataoff,
buffer, bufflen, POS_OWNER_IP4))
return 0;
- if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
+ if (!mangle_sip_packet(skb, ctinfo, ct, &dptr, skb->len - dataoff,
buffer, bufflen, POS_CONNECTION_IP4))
return 0;
/* Mangle media port. */
bufflen = sprintf(buffer, "%u", port);
- if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
+ if (!mangle_sip_packet(skb, ctinfo, ct, &dptr, skb->len - dataoff,
buffer, bufflen, POS_MEDIA))
return 0;
- return mangle_content_len(pskb, ctinfo, ct, dptr);
+ return mangle_content_len(skb, ctinfo, ct, dptr);
}
static void ip_nat_sdp_expect(struct nf_conn *ct,
@@ -241,7 +241,7 @@ static void ip_nat_sdp_expect(struct nf_conn *ct,
/* So, this packet has hit the connection tracking matching code.
Mangle it, and change the expectation to match the new version. */
-static unsigned int ip_nat_sdp(struct sk_buff **pskb,
+static unsigned int ip_nat_sdp(struct sk_buff *skb,
enum ip_conntrack_info ctinfo,
struct nf_conntrack_expect *exp,
const char *dptr)
@@ -277,7 +277,7 @@ static unsigned int ip_nat_sdp(struct sk_buff **pskb,
if (port == 0)
return NF_DROP;
- if (!mangle_sdp(pskb, ctinfo, ct, newip, port, dptr)) {
+ if (!mangle_sdp(skb, ctinfo, ct, newip, port, dptr)) {
nf_ct_unexpect_related(exp);
return NF_DROP;
}
@@ -293,8 +293,8 @@ static void __exit nf_nat_sip_fini(void)
static int __init nf_nat_sip_init(void)
{
- BUG_ON(rcu_dereference(nf_nat_sip_hook));
- BUG_ON(rcu_dereference(nf_nat_sdp_hook));
+ BUG_ON(nf_nat_sip_hook != NULL);
+ BUG_ON(nf_nat_sdp_hook != NULL);
rcu_assign_pointer(nf_nat_sip_hook, ip_nat_sip);
rcu_assign_pointer(nf_nat_sdp_hook, ip_nat_sdp);
return 0;
diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c
index 6bfcd3a90f08..03709d6b4b06 100644
--- a/net/ipv4/netfilter/nf_nat_snmp_basic.c
+++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c
@@ -1188,9 +1188,9 @@ static int snmp_parse_mangle(unsigned char *msg,
*/
static int snmp_translate(struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
- struct sk_buff **pskb)
+ struct sk_buff *skb)
{
- struct iphdr *iph = ip_hdr(*pskb);
+ struct iphdr *iph = ip_hdr(skb);
struct udphdr *udph = (struct udphdr *)((__be32 *)iph + iph->ihl);
u_int16_t udplen = ntohs(udph->len);
u_int16_t paylen = udplen - sizeof(struct udphdr);
@@ -1225,13 +1225,13 @@ static int snmp_translate(struct nf_conn *ct,
/* We don't actually set up expectations, just adjust internal IP
* addresses if this is being NATted */
-static int help(struct sk_buff **pskb, unsigned int protoff,
+static int help(struct sk_buff *skb, unsigned int protoff,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo)
{
int dir = CTINFO2DIR(ctinfo);
unsigned int ret;
- struct iphdr *iph = ip_hdr(*pskb);
+ struct iphdr *iph = ip_hdr(skb);
struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl);
/* SNMP replies and originating SNMP traps get mangled */
@@ -1250,7 +1250,7 @@ static int help(struct sk_buff **pskb, unsigned int protoff,
* enough room for a UDP header. Just verify the UDP length field so we
* can mess around with the payload.
*/
- if (ntohs(udph->len) != (*pskb)->len - (iph->ihl << 2)) {
+ if (ntohs(udph->len) != skb->len - (iph->ihl << 2)) {
if (net_ratelimit())
printk(KERN_WARNING "SNMP: dropping malformed packet "
"src=%u.%u.%u.%u dst=%u.%u.%u.%u\n",
@@ -1258,11 +1258,11 @@ static int help(struct sk_buff **pskb, unsigned int protoff,
return NF_DROP;
}
- if (!skb_make_writable(pskb, (*pskb)->len))
+ if (!skb_make_writable(skb, skb->len))
return NF_DROP;
spin_lock_bh(&snmp_lock);
- ret = snmp_translate(ct, ctinfo, pskb);
+ ret = snmp_translate(ct, ctinfo, skb);
spin_unlock_bh(&snmp_lock);
return ret;
}
diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c
index 46cc99def165..7db76ea9af91 100644
--- a/net/ipv4/netfilter/nf_nat_standalone.c
+++ b/net/ipv4/netfilter/nf_nat_standalone.c
@@ -67,7 +67,7 @@ static void nat_decode_session(struct sk_buff *skb, struct flowi *fl)
static unsigned int
nf_nat_fn(unsigned int hooknum,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
@@ -80,9 +80,9 @@ nf_nat_fn(unsigned int hooknum,
/* We never see fragments: conntrack defrags on pre-routing
and local-out, and nf_nat_out protects post-routing. */
- NF_CT_ASSERT(!(ip_hdr(*pskb)->frag_off & htons(IP_MF | IP_OFFSET)));
+ NF_CT_ASSERT(!(ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)));
- ct = nf_ct_get(*pskb, &ctinfo);
+ ct = nf_ct_get(skb, &ctinfo);
/* Can't track? It's not due to stress, or conntrack would
have dropped it. Hence it's the user's responsibilty to
packet filter it out, or implement conntrack/NAT for that
@@ -91,10 +91,10 @@ nf_nat_fn(unsigned int hooknum,
/* Exception: ICMP redirect to new connection (not in
hash table yet). We must not let this through, in
case we're doing NAT to the same network. */
- if (ip_hdr(*pskb)->protocol == IPPROTO_ICMP) {
+ if (ip_hdr(skb)->protocol == IPPROTO_ICMP) {
struct icmphdr _hdr, *hp;
- hp = skb_header_pointer(*pskb, ip_hdrlen(*pskb),
+ hp = skb_header_pointer(skb, ip_hdrlen(skb),
sizeof(_hdr), &_hdr);
if (hp != NULL &&
hp->type == ICMP_REDIRECT)
@@ -119,9 +119,9 @@ nf_nat_fn(unsigned int hooknum,
switch (ctinfo) {
case IP_CT_RELATED:
case IP_CT_RELATED+IP_CT_IS_REPLY:
- if (ip_hdr(*pskb)->protocol == IPPROTO_ICMP) {
+ if (ip_hdr(skb)->protocol == IPPROTO_ICMP) {
if (!nf_nat_icmp_reply_translation(ct, ctinfo,
- hooknum, pskb))
+ hooknum, skb))
return NF_DROP;
else
return NF_ACCEPT;
@@ -141,7 +141,7 @@ nf_nat_fn(unsigned int hooknum,
/* LOCAL_IN hook doesn't have a chain! */
ret = alloc_null_binding(ct, hooknum);
else
- ret = nf_nat_rule_find(pskb, hooknum, in, out,
+ ret = nf_nat_rule_find(skb, hooknum, in, out,
ct);
if (ret != NF_ACCEPT) {
@@ -159,31 +159,31 @@ nf_nat_fn(unsigned int hooknum,
ctinfo == (IP_CT_ESTABLISHED+IP_CT_IS_REPLY));
}
- return nf_nat_packet(ct, ctinfo, hooknum, pskb);
+ return nf_nat_packet(ct, ctinfo, hooknum, skb);
}
static unsigned int
nf_nat_in(unsigned int hooknum,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
unsigned int ret;
- __be32 daddr = ip_hdr(*pskb)->daddr;
+ __be32 daddr = ip_hdr(skb)->daddr;
- ret = nf_nat_fn(hooknum, pskb, in, out, okfn);
+ ret = nf_nat_fn(hooknum, skb, in, out, okfn);
if (ret != NF_DROP && ret != NF_STOLEN &&
- daddr != ip_hdr(*pskb)->daddr) {
- dst_release((*pskb)->dst);
- (*pskb)->dst = NULL;
+ daddr != ip_hdr(skb)->daddr) {
+ dst_release(skb->dst);
+ skb->dst = NULL;
}
return ret;
}
static unsigned int
nf_nat_out(unsigned int hooknum,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
@@ -195,14 +195,14 @@ nf_nat_out(unsigned int hooknum,
unsigned int ret;
/* root is playing with raw sockets. */
- if ((*pskb)->len < sizeof(struct iphdr) ||
- ip_hdrlen(*pskb) < sizeof(struct iphdr))
+ if (skb->len < sizeof(struct iphdr) ||
+ ip_hdrlen(skb) < sizeof(struct iphdr))
return NF_ACCEPT;
- ret = nf_nat_fn(hooknum, pskb, in, out, okfn);
+ ret = nf_nat_fn(hooknum, skb, in, out, okfn);
#ifdef CONFIG_XFRM
if (ret != NF_DROP && ret != NF_STOLEN &&
- (ct = nf_ct_get(*pskb, &ctinfo)) != NULL) {
+ (ct = nf_ct_get(skb, &ctinfo)) != NULL) {
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
if (ct->tuplehash[dir].tuple.src.u3.ip !=
@@ -210,7 +210,7 @@ nf_nat_out(unsigned int hooknum,
|| ct->tuplehash[dir].tuple.src.u.all !=
ct->tuplehash[!dir].tuple.dst.u.all
)
- return ip_xfrm_me_harder(pskb) == 0 ? ret : NF_DROP;
+ return ip_xfrm_me_harder(skb) == 0 ? ret : NF_DROP;
}
#endif
return ret;
@@ -218,7 +218,7 @@ nf_nat_out(unsigned int hooknum,
static unsigned int
nf_nat_local_fn(unsigned int hooknum,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
@@ -228,24 +228,24 @@ nf_nat_local_fn(unsigned int hooknum,
unsigned int ret;
/* root is playing with raw sockets. */
- if ((*pskb)->len < sizeof(struct iphdr) ||
- ip_hdrlen(*pskb) < sizeof(struct iphdr))
+ if (skb->len < sizeof(struct iphdr) ||
+ ip_hdrlen(skb) < sizeof(struct iphdr))
return NF_ACCEPT;
- ret = nf_nat_fn(hooknum, pskb, in, out, okfn);
+ ret = nf_nat_fn(hooknum, skb, in, out, okfn);
if (ret != NF_DROP && ret != NF_STOLEN &&
- (ct = nf_ct_get(*pskb, &ctinfo)) != NULL) {
+ (ct = nf_ct_get(skb, &ctinfo)) != NULL) {
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
if (ct->tuplehash[dir].tuple.dst.u3.ip !=
ct->tuplehash[!dir].tuple.src.u3.ip) {
- if (ip_route_me_harder(pskb, RTN_UNSPEC))
+ if (ip_route_me_harder(skb, RTN_UNSPEC))
ret = NF_DROP;
}
#ifdef CONFIG_XFRM
else if (ct->tuplehash[dir].tuple.dst.u.all !=
ct->tuplehash[!dir].tuple.src.u.all)
- if (ip_xfrm_me_harder(pskb))
+ if (ip_xfrm_me_harder(skb))
ret = NF_DROP;
#endif
}
@@ -254,7 +254,7 @@ nf_nat_local_fn(unsigned int hooknum,
static unsigned int
nf_nat_adjust(unsigned int hooknum,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
@@ -262,10 +262,10 @@ nf_nat_adjust(unsigned int hooknum,
struct nf_conn *ct;
enum ip_conntrack_info ctinfo;
- ct = nf_ct_get(*pskb, &ctinfo);
+ ct = nf_ct_get(skb, &ctinfo);
if (ct && test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) {
pr_debug("nf_nat_standalone: adjusting sequence number\n");
- if (!nf_nat_seq_adjust(pskb, ct, ctinfo))
+ if (!nf_nat_seq_adjust(skb, ct, ctinfo))
return NF_DROP;
}
return NF_ACCEPT;
diff --git a/net/ipv4/netfilter/nf_nat_tftp.c b/net/ipv4/netfilter/nf_nat_tftp.c
index 04dfeaefec02..1360a94766dd 100644
--- a/net/ipv4/netfilter/nf_nat_tftp.c
+++ b/net/ipv4/netfilter/nf_nat_tftp.c
@@ -20,7 +20,7 @@ MODULE_DESCRIPTION("TFTP NAT helper");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ip_nat_tftp");
-static unsigned int help(struct sk_buff **pskb,
+static unsigned int help(struct sk_buff *skb,
enum ip_conntrack_info ctinfo,
struct nf_conntrack_expect *exp)
{
@@ -43,7 +43,7 @@ static void __exit nf_nat_tftp_fini(void)
static int __init nf_nat_tftp_init(void)
{
- BUG_ON(rcu_dereference(nf_nat_tftp_hook));
+ BUG_ON(nf_nat_tftp_hook != NULL);
rcu_assign_pointer(nf_nat_tftp_hook, help);
return 0;
}
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index e5b05b039101..ce34b281803f 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -46,17 +46,6 @@
#include <net/sock.h>
#include <net/raw.h>
-static int fold_prot_inuse(struct proto *proto)
-{
- int res = 0;
- int cpu;
-
- for_each_possible_cpu(cpu)
- res += proto->stats[cpu].inuse;
-
- return res;
-}
-
/*
* Report socket allocation statistics [mea@utu.fi]
*/
@@ -64,14 +53,14 @@ static int sockstat_seq_show(struct seq_file *seq, void *v)
{
socket_seq_show(seq);
seq_printf(seq, "TCP: inuse %d orphan %d tw %d alloc %d mem %d\n",
- fold_prot_inuse(&tcp_prot), atomic_read(&tcp_orphan_count),
+ sock_prot_inuse(&tcp_prot), atomic_read(&tcp_orphan_count),
tcp_death_row.tw_count, atomic_read(&tcp_sockets_allocated),
atomic_read(&tcp_memory_allocated));
- seq_printf(seq, "UDP: inuse %d\n", fold_prot_inuse(&udp_prot));
- seq_printf(seq, "UDPLITE: inuse %d\n", fold_prot_inuse(&udplite_prot));
- seq_printf(seq, "RAW: inuse %d\n", fold_prot_inuse(&raw_prot));
- seq_printf(seq, "FRAG: inuse %d memory %d\n", ip_frag_nqueues,
- atomic_read(&ip_frag_mem));
+ seq_printf(seq, "UDP: inuse %d\n", sock_prot_inuse(&udp_prot));
+ seq_printf(seq, "UDPLITE: inuse %d\n", sock_prot_inuse(&udplite_prot));
+ seq_printf(seq, "RAW: inuse %d\n", sock_prot_inuse(&raw_prot));
+ seq_printf(seq, "FRAG: inuse %d memory %d\n",
+ ip_frag_nqueues(), ip_frag_mem());
return 0;
}
@@ -121,14 +110,6 @@ static const struct snmp_mib snmp4_ipextstats_list[] = {
SNMP_MIB_SENTINEL
};
-static const struct snmp_mib snmp4_icmp_list[] = {
- SNMP_MIB_ITEM("InMsgs", ICMP_MIB_INMSGS),
- SNMP_MIB_ITEM("InErrors", ICMP_MIB_INERRORS),
- SNMP_MIB_ITEM("OutMsgs", ICMP_MIB_OUTMSGS),
- SNMP_MIB_ITEM("OutErrors", ICMP_MIB_OUTERRORS),
- SNMP_MIB_SENTINEL
-};
-
static struct {
char *name;
int index;
@@ -312,7 +293,7 @@ static void icmp_put(struct seq_file *seq)
for (i=0; icmpmibmap[i].name != NULL; i++)
seq_printf(seq, " %lu",
snmp_fold_field((void **) icmpmsg_statistics,
- icmpmibmap[i].index));
+ icmpmibmap[i].index | 0x100));
}
/*
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 3916faca3afe..66b42f547bf9 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -760,6 +760,8 @@ static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg)
}
}
+DEFINE_PROTO_INUSE(raw)
+
struct proto raw_prot = {
.name = "RAW",
.owner = THIS_MODULE,
@@ -781,6 +783,7 @@ struct proto raw_prot = {
.compat_setsockopt = compat_raw_setsockopt,
.compat_getsockopt = compat_raw_getsockopt,
#endif
+ REF_PROTO_INUSE(raw)
};
#ifdef CONFIG_PROC_FS
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 21b12de9e653..1bff9ed349ff 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -578,6 +578,9 @@ static void rt_check_expire(struct work_struct *work)
i = (i + 1) & rt_hash_mask;
rthp = &rt_hash_table[i].chain;
+ if (need_resched())
+ cond_resched();
+
if (*rthp == NULL)
continue;
spin_lock_bh(rt_hash_lock_addr(i));
@@ -851,9 +854,7 @@ restart:
*/
rcu_assign_pointer(rt_hash_table[hash].chain, rth);
- rth->u.dst.__use++;
- dst_hold(&rth->u.dst);
- rth->u.dst.lastuse = now;
+ dst_use(&rth->u.dst, now);
spin_unlock_bh(rt_hash_lock_addr(hash));
rt_drop(rt);
@@ -1813,11 +1814,6 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
goto martian_destination;
err = ip_mkroute_input(skb, &res, &fl, in_dev, daddr, saddr, tos);
- if (err == -ENOBUFS)
- goto e_nobufs;
- if (err == -EINVAL)
- goto e_inval;
-
done:
in_dev_put(in_dev);
if (free_res)
@@ -1935,9 +1931,7 @@ int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr,
rth->fl.oif == 0 &&
rth->fl.mark == skb->mark &&
rth->fl.fl4_tos == tos) {
- rth->u.dst.lastuse = jiffies;
- dst_hold(&rth->u.dst);
- rth->u.dst.__use++;
+ dst_use(&rth->u.dst, jiffies);
RT_CACHE_STAT_INC(in_hit);
rcu_read_unlock();
skb->dst = (struct dst_entry*)rth;
@@ -2331,9 +2325,7 @@ int __ip_route_output_key(struct rtable **rp, const struct flowi *flp)
rth->fl.mark == flp->mark &&
!((rth->fl.fl4_tos ^ flp->fl4_tos) &
(IPTOS_RT_MASK | RTO_ONLINK))) {
- rth->u.dst.lastuse = jiffies;
- dst_hold(&rth->u.dst);
- rth->u.dst.__use++;
+ dst_use(&rth->u.dst, jiffies);
RT_CACHE_STAT_INC(out_hit);
rcu_read_unlock_bh();
*rp = rth;
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index eb286abcf5dc..ffddd2b45352 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -19,6 +19,7 @@
#include <net/route.h>
#include <net/tcp.h>
#include <net/cipso_ipv4.h>
+#include <net/inet_frag.h>
/* From af_inet.c */
extern int sysctl_ip_nonlocal_bind;
@@ -121,7 +122,7 @@ static int ipv4_local_port_range(ctl_table *table, int write, struct file *filp,
ret = proc_dointvec_minmax(&tmp, write, filp, buffer, lenp, ppos);
if (write && ret == 0) {
- if (range[1] <= range[0])
+ if (range[1] < range[0])
ret = -EINVAL;
else
set_local_port_range(range);
@@ -149,7 +150,7 @@ static int ipv4_sysctl_local_port_range(ctl_table *table, int __user *name,
ret = sysctl_intvec(&tmp, name, nlen, oldval, oldlenp, newval, newlen);
if (ret == 0 && newval && newlen) {
- if (range[1] <= range[0])
+ if (range[1] < range[0])
ret = -EINVAL;
else
set_local_port_range(range);
@@ -357,7 +358,7 @@ ctl_table ipv4_table[] = {
{
.ctl_name = NET_IPV4_IPFRAG_HIGH_THRESH,
.procname = "ipfrag_high_thresh",
- .data = &sysctl_ipfrag_high_thresh,
+ .data = &ip4_frags_ctl.high_thresh,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec
@@ -365,7 +366,7 @@ ctl_table ipv4_table[] = {
{
.ctl_name = NET_IPV4_IPFRAG_LOW_THRESH,
.procname = "ipfrag_low_thresh",
- .data = &sysctl_ipfrag_low_thresh,
+ .data = &ip4_frags_ctl.low_thresh,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec
@@ -381,7 +382,7 @@ ctl_table ipv4_table[] = {
{
.ctl_name = NET_IPV4_IPFRAG_TIME,
.procname = "ipfrag_time",
- .data = &sysctl_ipfrag_time,
+ .data = &ip4_frags_ctl.timeout,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
@@ -732,14 +733,13 @@ ctl_table ipv4_table[] = {
{
.ctl_name = NET_IPV4_IPFRAG_SECRET_INTERVAL,
.procname = "ipfrag_secret_interval",
- .data = &sysctl_ipfrag_secret_interval,
+ .data = &ip4_frags_ctl.secret_interval,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
.strategy = &sysctl_jiffies
},
{
- .ctl_name = NET_IPV4_IPFRAG_MAX_DIST,
.procname = "ipfrag_max_dist",
.data = &sysctl_ipfrag_max_dist,
.maxlen = sizeof(int),
@@ -864,7 +864,6 @@ ctl_table ipv4_table[] = {
},
#endif /* CONFIG_NETLABEL */
{
- .ctl_name = NET_TCP_AVAIL_CONG_CONTROL,
.procname = "tcp_available_congestion_control",
.maxlen = TCP_CA_BUF_MAX,
.mode = 0444,
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 4f322003835d..8e65182f7af1 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1334,7 +1334,7 @@ do_prequeue:
if ((flags & MSG_PEEK) && peek_seq != tp->copied_seq) {
if (net_ratelimit())
printk(KERN_DEBUG "TCP(%s:%d): Application bug, race in MSG_PEEK.\n",
- current->comm, current->pid);
+ current->comm, task_pid_nr(current));
peek_seq = tp->copied_seq;
}
continue;
@@ -2453,14 +2453,14 @@ void __init tcp_init(void)
0,
&tcp_hashinfo.ehash_size,
NULL,
- 0);
+ thash_entries ? 0 : 512 * 1024);
tcp_hashinfo.ehash_size = 1 << tcp_hashinfo.ehash_size;
for (i = 0; i < tcp_hashinfo.ehash_size; i++) {
- rwlock_init(&tcp_hashinfo.ehash[i].lock);
INIT_HLIST_HEAD(&tcp_hashinfo.ehash[i].chain);
INIT_HLIST_HEAD(&tcp_hashinfo.ehash[i].twchain);
}
-
+ if (inet_ehash_locks_alloc(&tcp_hashinfo))
+ panic("TCP: failed to alloc ehash_locks");
tcp_hashinfo.bhash =
alloc_large_system_hash("TCP bind",
sizeof(struct inet_bind_hashbucket),
diff --git a/net/ipv4/tcp_diag.c b/net/ipv4/tcp_diag.c
index 3904d2158a92..2fbcc7d1b1a0 100644
--- a/net/ipv4/tcp_diag.c
+++ b/net/ipv4/tcp_diag.c
@@ -56,3 +56,4 @@ static void __exit tcp_diag_exit(void)
module_init(tcp_diag_init);
module_exit(tcp_diag_exit);
MODULE_LICENSE("GPL");
+MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_INET_DIAG, TCPDIAG_GETSOCK);
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 0a42e9340346..0f0c1c9829a1 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -103,7 +103,7 @@ int sysctl_tcp_abc __read_mostly;
#define FLAG_SLOWPATH 0x100 /* Do not skip RFC checks for window update.*/
#define FLAG_ONLY_ORIG_SACKED 0x200 /* SACKs only non-rexmit sent before RTO */
#define FLAG_SND_UNA_ADVANCED 0x400 /* Snd_una was changed (!= FLAG_DATA_ACKED) */
-#define FLAG_DSACKING_ACK 0x800 /* SACK blocks contained DSACK info */
+#define FLAG_DSACKING_ACK 0x800 /* SACK blocks contained D-SACK info */
#define FLAG_NONHEAD_RETRANS_ACKED 0x1000 /* Non-head rexmitted data was ACKed */
#define FLAG_ACKED (FLAG_DATA_ACKED|FLAG_SYN_ACKED)
@@ -866,7 +866,7 @@ static void tcp_disable_fack(struct tcp_sock *tp)
tp->rx_opt.sack_ok &= ~2;
}
-/* Take a notice that peer is sending DSACKs */
+/* Take a notice that peer is sending D-SACKs */
static void tcp_dsack_seen(struct tcp_sock *tp)
{
tp->rx_opt.sack_ok |= 4;
@@ -1058,7 +1058,7 @@ static void tcp_update_reordering(struct sock *sk, const int metric,
*
* With D-SACK the lower bound is extended to cover sequence space below
* SND.UNA down to undo_marker, which is the last point of interest. Yet
- * again, DSACK block must not to go across snd_una (for the same reason as
+ * again, D-SACK block must not to go across snd_una (for the same reason as
* for the normal SACK blocks, explained above). But there all simplicity
* ends, TCP might receive valid D-SACKs below that. As long as they reside
* fully below undo_marker they do not affect behavior in anyway and can
@@ -1080,7 +1080,7 @@ static int tcp_is_sackblock_valid(struct tcp_sock *tp, int is_dsack,
if (!before(start_seq, tp->snd_nxt))
return 0;
- /* In outstanding window? ...This is valid exit for DSACKs too.
+ /* In outstanding window? ...This is valid exit for D-SACKs too.
* start_seq == snd_una is non-sensical (see comments above)
*/
if (after(start_seq, tp->snd_una))
@@ -1121,7 +1121,7 @@ static int tcp_mark_lost_retrans(struct sock *sk, u32 received_upto)
struct sk_buff *skb;
int flag = 0;
int cnt = 0;
- u32 new_low_seq = 0;
+ u32 new_low_seq = tp->snd_nxt;
tcp_for_write_queue(skb, sk) {
u32 ack_seq = TCP_SKB_CB(skb)->ack_seq;
@@ -1153,7 +1153,7 @@ static int tcp_mark_lost_retrans(struct sock *sk, u32 received_upto)
NET_INC_STATS_BH(LINUX_MIB_TCPLOSTRETRANSMIT);
}
} else {
- if (!new_low_seq || before(ack_seq, new_low_seq))
+ if (before(ack_seq, new_low_seq))
new_low_seq = ack_seq;
cnt += tcp_skb_pcount(skb);
}
@@ -1204,8 +1204,8 @@ static int tcp_check_dsack(struct tcp_sock *tp, struct sk_buff *ack_skb,
* which may fail and creates some hassle (caller must handle error case
* returns).
*/
-int tcp_match_skb_to_sack(struct sock *sk, struct sk_buff *skb,
- u32 start_seq, u32 end_seq)
+static int tcp_match_skb_to_sack(struct sock *sk, struct sk_buff *skb,
+ u32 start_seq, u32 end_seq)
{
int in_sack, err;
unsigned int pkt_len;
@@ -1242,12 +1242,13 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
int num_sacks = (ptr[1] - TCPOLEN_SACK_BASE)>>3;
int reord = tp->packets_out;
int prior_fackets;
- u32 highest_sack_end_seq = 0;
+ u32 highest_sack_end_seq = tp->lost_retrans_low;
int flag = 0;
int found_dup_sack = 0;
int cached_fack_count;
int i;
int first_sack_index;
+ int force_one_sack;
if (!tp->sacked_out) {
if (WARN_ON(tp->fackets_out))
@@ -1268,22 +1269,25 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
if (before(TCP_SKB_CB(ack_skb)->ack_seq, prior_snd_una - tp->max_window))
return 0;
+ if (!tp->packets_out)
+ goto out;
+
/* SACK fastpath:
* if the only SACK change is the increase of the end_seq of
* the first block then only apply that SACK block
* and use retrans queue hinting otherwise slowpath */
- flag = 1;
+ force_one_sack = 1;
for (i = 0; i < num_sacks; i++) {
__be32 start_seq = sp[i].start_seq;
__be32 end_seq = sp[i].end_seq;
if (i == 0) {
if (tp->recv_sack_cache[i].start_seq != start_seq)
- flag = 0;
+ force_one_sack = 0;
} else {
if ((tp->recv_sack_cache[i].start_seq != start_seq) ||
(tp->recv_sack_cache[i].end_seq != end_seq))
- flag = 0;
+ force_one_sack = 0;
}
tp->recv_sack_cache[i].start_seq = start_seq;
tp->recv_sack_cache[i].end_seq = end_seq;
@@ -1295,7 +1299,7 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
}
first_sack_index = 0;
- if (flag)
+ if (force_one_sack)
num_sacks = 1;
else {
int j;
@@ -1321,9 +1325,6 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
}
}
- /* clear flag as used for different purpose in following code */
- flag = 0;
-
/* Use SACK fastpath hint if valid */
cached_skb = tp->fastpath_skb_hint;
cached_fack_count = tp->fastpath_cnt_hint;
@@ -1332,12 +1333,15 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
cached_fack_count = 0;
}
- for (i=0; i<num_sacks; i++, sp++) {
+ for (i = 0; i < num_sacks; i++) {
struct sk_buff *skb;
__u32 start_seq = ntohl(sp->start_seq);
__u32 end_seq = ntohl(sp->end_seq);
int fack_count;
int dup_sack = (found_dup_sack && (i == first_sack_index));
+ int next_dup = (found_dup_sack && (i+1 == first_sack_index));
+
+ sp++;
if (!tcp_is_sackblock_valid(tp, dup_sack, start_seq, end_seq)) {
if (dup_sack) {
@@ -1363,7 +1367,7 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
flag |= FLAG_DATA_LOST;
tcp_for_write_queue_from(skb, sk) {
- int in_sack;
+ int in_sack = 0;
u8 sacked;
if (skb == tcp_send_head(sk))
@@ -1382,11 +1386,25 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
if (!before(TCP_SKB_CB(skb)->seq, end_seq))
break;
- in_sack = tcp_match_skb_to_sack(sk, skb, start_seq, end_seq);
- if (in_sack < 0)
- break;
+ dup_sack = (found_dup_sack && (i == first_sack_index));
- fack_count += tcp_skb_pcount(skb);
+ /* Due to sorting DSACK may reside within this SACK block! */
+ if (next_dup) {
+ u32 dup_start = ntohl(sp->start_seq);
+ u32 dup_end = ntohl(sp->end_seq);
+
+ if (before(TCP_SKB_CB(skb)->seq, dup_end)) {
+ in_sack = tcp_match_skb_to_sack(sk, skb, dup_start, dup_end);
+ if (in_sack > 0)
+ dup_sack = 1;
+ }
+ }
+
+ /* DSACK info lost if out-of-mem, try SACK still */
+ if (in_sack <= 0)
+ in_sack = tcp_match_skb_to_sack(sk, skb, start_seq, end_seq);
+ if (unlikely(in_sack < 0))
+ break;
sacked = TCP_SKB_CB(skb)->sacked;
@@ -1402,19 +1420,17 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
if ((dup_sack && in_sack) &&
(sacked&TCPCB_SACKED_ACKED))
reord = min(fack_count, reord);
- } else {
- /* If it was in a hole, we detected reordering. */
- if (fack_count < prior_fackets &&
- !(sacked&TCPCB_SACKED_ACKED))
- reord = min(fack_count, reord);
}
/* Nothing to do; acked frame is about to be dropped. */
+ fack_count += tcp_skb_pcount(skb);
continue;
}
- if (!in_sack)
+ if (!in_sack) {
+ fack_count += tcp_skb_pcount(skb);
continue;
+ }
if (!(sacked&TCPCB_SACKED_ACKED)) {
if (sacked & TCPCB_SACKED_RETRANS) {
@@ -1431,12 +1447,17 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
tp->retransmit_skb_hint = NULL;
}
} else {
- /* New sack for not retransmitted frame,
- * which was in hole. It is reordering.
- */
- if (!(sacked & TCPCB_RETRANS) &&
- fack_count < prior_fackets)
- reord = min(fack_count, reord);
+ if (!(sacked & TCPCB_RETRANS)) {
+ /* New sack for not retransmitted frame,
+ * which was in hole. It is reordering.
+ */
+ if (fack_count < prior_fackets)
+ reord = min(fack_count, reord);
+
+ /* SACK enhanced F-RTO (RFC4138; Appendix B) */
+ if (!after(TCP_SKB_CB(skb)->end_seq, tp->frto_highmark))
+ flag |= FLAG_ONLY_ORIG_SACKED;
+ }
if (sacked & TCPCB_LOST) {
TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST;
@@ -1445,24 +1466,13 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
/* clear lost hint */
tp->retransmit_skb_hint = NULL;
}
- /* SACK enhanced F-RTO detection.
- * Set flag if and only if non-rexmitted
- * segments below frto_highmark are
- * SACKed (RFC4138; Appendix B).
- * Clearing correct due to in-order walk
- */
- if (after(end_seq, tp->frto_highmark)) {
- flag &= ~FLAG_ONLY_ORIG_SACKED;
- } else {
- if (!(sacked & TCPCB_RETRANS))
- flag |= FLAG_ONLY_ORIG_SACKED;
- }
}
TCP_SKB_CB(skb)->sacked |= TCPCB_SACKED_ACKED;
flag |= FLAG_DATA_SACKED;
tp->sacked_out += tcp_skb_pcount(skb);
+ fack_count += tcp_skb_pcount(skb);
if (fack_count > tp->fackets_out)
tp->fackets_out = fack_count;
@@ -1473,6 +1483,8 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
} else {
if (dup_sack && (sacked&TCPCB_RETRANS))
reord = min(fack_count, reord);
+
+ fack_count += tcp_skb_pcount(skb);
}
/* D-SACK. We can detect redundant retransmission
@@ -1487,6 +1499,12 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
tp->retransmit_skb_hint = NULL;
}
}
+
+ /* SACK enhanced FRTO (RFC4138, Appendix B): Clearing correct
+ * due to in-order walk
+ */
+ if (after(end_seq, tp->frto_highmark))
+ flag &= ~FLAG_ONLY_ORIG_SACKED;
}
if (tp->retrans_out &&
@@ -1498,7 +1516,9 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
if ((reord < tp->fackets_out) && icsk->icsk_ca_state != TCP_CA_Loss &&
(!tp->frto_highmark || after(tp->snd_una, tp->frto_highmark)))
- tcp_update_reordering(sk, ((tp->fackets_out + 1) - reord), 0);
+ tcp_update_reordering(sk, tp->fackets_out - reord, 0);
+
+out:
#if FASTRETRANS_DEBUG > 0
BUG_TRAP((int)tp->sacked_out >= 0);
@@ -1615,7 +1635,7 @@ void tcp_enter_frto(struct sock *sk)
!icsk->icsk_retransmits)) {
tp->prior_ssthresh = tcp_current_ssthresh(sk);
/* Our state is too optimistic in ssthresh() call because cwnd
- * is not reduced until tcp_enter_frto_loss() when previous FRTO
+ * is not reduced until tcp_enter_frto_loss() when previous F-RTO
* recovery has not yet completed. Pattern would be this: RTO,
* Cumulative ACK, RTO (2xRTO for the same segment does not end
* up here twice).
@@ -1654,6 +1674,9 @@ void tcp_enter_frto(struct sock *sk)
}
tcp_verify_left_out(tp);
+ /* Too bad if TCP was application limited */
+ tp->snd_cwnd = min(tp->snd_cwnd, tcp_packets_in_flight(tp) + 1);
+
/* Earlier loss recovery underway (see RFC4138; Appendix B).
* The last condition is necessary at least in tp->frto_counter case.
*/
@@ -1686,6 +1709,8 @@ static void tcp_enter_frto_loss(struct sock *sk, int allowed_segments, int flag)
tcp_for_write_queue(skb, sk) {
if (skb == tcp_send_head(sk))
break;
+
+ TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST;
/*
* Count the retransmission made on RTO correctly (only when
* waiting for the first ACK and did not get it)...
@@ -1699,7 +1724,7 @@ static void tcp_enter_frto_loss(struct sock *sk, int allowed_segments, int flag)
} else {
if (TCP_SKB_CB(skb)->sacked & TCPCB_RETRANS)
tp->undo_marker = 0;
- TCP_SKB_CB(skb)->sacked &= ~(TCPCB_LOST|TCPCB_SACKED_RETRANS);
+ TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS;
}
/* Don't lost mark skbs that were fwd transmitted after RTO */
@@ -1801,7 +1826,7 @@ void tcp_enter_loss(struct sock *sk, int how)
tcp_set_ca_state(sk, TCP_CA_Loss);
tp->high_seq = tp->snd_nxt;
TCP_ECN_queue_cwr(tp);
- /* Abort FRTO algorithm if one is in progress */
+ /* Abort F-RTO algorithm if one is in progress */
tp->frto_counter = 0;
}
@@ -1946,7 +1971,7 @@ static int tcp_time_to_recover(struct sock *sk)
struct tcp_sock *tp = tcp_sk(sk);
__u32 packets_out;
- /* Do not perform any recovery during FRTO algorithm */
+ /* Do not perform any recovery during F-RTO algorithm */
if (tp->frto_counter)
return 0;
@@ -1995,8 +2020,7 @@ static void tcp_verify_retransmit_hint(struct tcp_sock *tp,
}
/* Mark head of queue up as lost. */
-static void tcp_mark_head_lost(struct sock *sk,
- int packets, u32 high_seq)
+static void tcp_mark_head_lost(struct sock *sk, int packets)
{
struct tcp_sock *tp = tcp_sk(sk);
struct sk_buff *skb;
@@ -2019,7 +2043,7 @@ static void tcp_mark_head_lost(struct sock *sk,
tp->lost_skb_hint = skb;
tp->lost_cnt_hint = cnt;
cnt += tcp_skb_pcount(skb);
- if (cnt > packets || after(TCP_SKB_CB(skb)->end_seq, high_seq))
+ if (cnt > packets || after(TCP_SKB_CB(skb)->end_seq, tp->high_seq))
break;
if (!(TCP_SKB_CB(skb)->sacked & (TCPCB_SACKED_ACKED|TCPCB_LOST))) {
TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
@@ -2040,9 +2064,9 @@ static void tcp_update_scoreboard(struct sock *sk)
int lost = tp->fackets_out - tp->reordering;
if (lost <= 0)
lost = 1;
- tcp_mark_head_lost(sk, lost, tp->high_seq);
+ tcp_mark_head_lost(sk, lost);
} else {
- tcp_mark_head_lost(sk, 1, tp->high_seq);
+ tcp_mark_head_lost(sk, 1);
}
/* New heuristics: it is possible only after we switched
@@ -2062,7 +2086,7 @@ static void tcp_update_scoreboard(struct sock *sk)
if (!tcp_skb_timedout(sk, skb))
break;
- if (!(TCP_SKB_CB(skb)->sacked&TCPCB_TAGBITS)) {
+ if (!(TCP_SKB_CB(skb)->sacked & (TCPCB_SACKED_ACKED|TCPCB_LOST))) {
TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
tp->lost_out += tcp_skb_pcount(skb);
tcp_verify_retransmit_hint(tp, skb);
@@ -2381,7 +2405,7 @@ tcp_fastretrans_alert(struct sock *sk, int pkts_acked, int flag)
before(tp->snd_una, tp->high_seq) &&
icsk->icsk_ca_state != TCP_CA_Open &&
tp->fackets_out > tp->reordering) {
- tcp_mark_head_lost(sk, tp->fackets_out-tp->reordering, tp->high_seq);
+ tcp_mark_head_lost(sk, tp->fackets_out - tp->reordering);
NET_INC_STATS_BH(LINUX_MIB_TCPLOSS);
}
@@ -2614,7 +2638,8 @@ static u32 tcp_tso_acked(struct sock *sk, struct sk_buff *skb)
* is before the ack sequence we can discard it as it's confirmed to have
* arrived at the other end.
*/
-static int tcp_clean_rtx_queue(struct sock *sk, s32 *seq_rtt_p)
+static int tcp_clean_rtx_queue(struct sock *sk, s32 *seq_rtt_p,
+ int prior_fackets)
{
struct tcp_sock *tp = tcp_sk(sk);
const struct inet_connection_sock *icsk = inet_csk(sk);
@@ -2623,6 +2648,8 @@ static int tcp_clean_rtx_queue(struct sock *sk, s32 *seq_rtt_p)
int fully_acked = 1;
int flag = 0;
int prior_packets = tp->packets_out;
+ u32 cnt = 0;
+ u32 reord = tp->packets_out;
s32 seq_rtt = -1;
ktime_t last_ackt = net_invalid_timestamp();
@@ -2663,10 +2690,14 @@ static int tcp_clean_rtx_queue(struct sock *sk, s32 *seq_rtt_p)
if ((flag & FLAG_DATA_ACKED) ||
(packets_acked > 1))
flag |= FLAG_NONHEAD_RETRANS_ACKED;
- } else if (seq_rtt < 0) {
- seq_rtt = now - scb->when;
- if (fully_acked)
- last_ackt = skb->tstamp;
+ } else {
+ if (seq_rtt < 0) {
+ seq_rtt = now - scb->when;
+ if (fully_acked)
+ last_ackt = skb->tstamp;
+ }
+ if (!(sacked & TCPCB_SACKED_ACKED))
+ reord = min(cnt, reord);
}
if (sacked & TCPCB_SACKED_ACKED)
@@ -2677,12 +2708,16 @@ static int tcp_clean_rtx_queue(struct sock *sk, s32 *seq_rtt_p)
if ((sacked & TCPCB_URG) && tp->urg_mode &&
!before(end_seq, tp->snd_up))
tp->urg_mode = 0;
- } else if (seq_rtt < 0) {
- seq_rtt = now - scb->when;
- if (fully_acked)
- last_ackt = skb->tstamp;
+ } else {
+ if (seq_rtt < 0) {
+ seq_rtt = now - scb->when;
+ if (fully_acked)
+ last_ackt = skb->tstamp;
+ }
+ reord = min(cnt, reord);
}
tp->packets_out -= packets_acked;
+ cnt += packets_acked;
/* Initial outgoing SYN's get put onto the write_queue
* just like anything else we transmit. It is not
@@ -2714,13 +2749,18 @@ static int tcp_clean_rtx_queue(struct sock *sk, s32 *seq_rtt_p)
tcp_ack_update_rtt(sk, flag, seq_rtt);
tcp_rearm_rto(sk);
+ if (tcp_is_reno(tp)) {
+ tcp_remove_reno_sacks(sk, pkts_acked);
+ } else {
+ /* Non-retransmitted hole got filled? That's reordering */
+ if (reord < prior_fackets)
+ tcp_update_reordering(sk, tp->fackets_out - reord, 0);
+ }
+
tp->fackets_out -= min(pkts_acked, tp->fackets_out);
/* hint's skb might be NULL but we don't need to care */
tp->fastpath_cnt_hint -= min_t(u32, pkts_acked,
tp->fastpath_cnt_hint);
- if (tcp_is_reno(tp))
- tcp_remove_reno_sacks(sk, pkts_acked);
-
if (ca_ops->pkts_acked) {
s32 rtt_us = -1;
@@ -2963,7 +3003,7 @@ static int tcp_process_frto(struct sock *sk, int flag)
}
if (tp->frto_counter == 1) {
- /* Sending of the next skb must be allowed or no FRTO */
+ /* Sending of the next skb must be allowed or no F-RTO */
if (!tcp_send_head(sk) ||
after(TCP_SKB_CB(tcp_send_head(sk))->end_seq,
tp->snd_una + tp->snd_wnd)) {
@@ -3003,6 +3043,7 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
u32 ack_seq = TCP_SKB_CB(skb)->seq;
u32 ack = TCP_SKB_CB(skb)->ack_seq;
u32 prior_in_flight;
+ u32 prior_fackets;
s32 seq_rtt;
int prior_packets;
int frto_cwnd = 0;
@@ -3027,6 +3068,8 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
tp->bytes_acked += min(ack - prior_snd_una, tp->mss_cache);
}
+ prior_fackets = tp->fackets_out;
+
if (!(flag&FLAG_SLOWPATH) && after(ack, prior_snd_una)) {
/* Window is constant, pure forward advance.
* No more checks are required.
@@ -3068,13 +3111,13 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
prior_in_flight = tcp_packets_in_flight(tp);
/* See if we can take anything off of the retransmit queue. */
- flag |= tcp_clean_rtx_queue(sk, &seq_rtt);
+ flag |= tcp_clean_rtx_queue(sk, &seq_rtt, prior_fackets);
+ if (tp->frto_counter)
+ frto_cwnd = tcp_process_frto(sk, flag);
/* Guarantee sacktag reordering detection against wrap-arounds */
if (before(tp->frto_highmark, tp->snd_una))
tp->frto_highmark = 0;
- if (tp->frto_counter)
- frto_cwnd = tcp_process_frto(sk, flag);
if (tcp_ack_is_dubious(sk, flag)) {
/* Advance CWND, if state allows this. */
@@ -3910,7 +3953,7 @@ tcp_collapse(struct sock *sk, struct sk_buff_head *list,
while (before(start, end)) {
struct sk_buff *nskb;
- int header = skb_headroom(skb);
+ unsigned int header = skb_headroom(skb);
int copy = SKB_MAX_ORDER(header, 0);
/* Too big header? This can happen with IPv6. */
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 38cf73a56731..e566f3c67677 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -858,16 +858,16 @@ int tcp_v4_md5_do_add(struct sock *sk, __be32 addr,
u8 *newkey, u8 newkeylen)
{
/* Add Key to the list */
- struct tcp4_md5sig_key *key;
+ struct tcp_md5sig_key *key;
struct tcp_sock *tp = tcp_sk(sk);
struct tcp4_md5sig_key *keys;
- key = (struct tcp4_md5sig_key *)tcp_v4_md5_do_lookup(sk, addr);
+ key = tcp_v4_md5_do_lookup(sk, addr);
if (key) {
/* Pre-existing entry - just update that one. */
- kfree(key->base.key);
- key->base.key = newkey;
- key->base.keylen = newkeylen;
+ kfree(key->key);
+ key->key = newkey;
+ key->keylen = newkeylen;
} else {
struct tcp_md5sig_info *md5sig;
@@ -1055,6 +1055,9 @@ static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
bp->pad = 0;
bp->protocol = protocol;
bp->len = htons(tcplen);
+
+ sg_init_table(sg, 4);
+
sg_set_buf(&sg[block++], bp, sizeof(*bp));
nbytes += sizeof(*bp);
@@ -1080,6 +1083,8 @@ static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
sg_set_buf(&sg[block++], key->key, key->keylen);
nbytes += key->keylen;
+ sg_mark_end(&sg[block - 1]);
+
/* Now store the Hash into the packet */
err = crypto_hash_init(desc);
if (err)
@@ -2044,8 +2049,9 @@ static void *established_get_first(struct seq_file *seq)
struct sock *sk;
struct hlist_node *node;
struct inet_timewait_sock *tw;
+ rwlock_t *lock = inet_ehash_lockp(&tcp_hashinfo, st->bucket);
- read_lock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
+ read_lock_bh(lock);
sk_for_each(sk, node, &tcp_hashinfo.ehash[st->bucket].chain) {
if (sk->sk_family != st->family) {
continue;
@@ -2062,7 +2068,7 @@ static void *established_get_first(struct seq_file *seq)
rc = tw;
goto out;
}
- read_unlock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
+ read_unlock_bh(lock);
st->state = TCP_SEQ_STATE_ESTABLISHED;
}
out:
@@ -2089,11 +2095,11 @@ get_tw:
cur = tw;
goto out;
}
- read_unlock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
+ read_unlock_bh(inet_ehash_lockp(&tcp_hashinfo, st->bucket));
st->state = TCP_SEQ_STATE_ESTABLISHED;
if (++st->bucket < tcp_hashinfo.ehash_size) {
- read_lock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
+ read_lock_bh(inet_ehash_lockp(&tcp_hashinfo, st->bucket));
sk = sk_head(&tcp_hashinfo.ehash[st->bucket].chain);
} else {
cur = NULL;
@@ -2201,7 +2207,7 @@ static void tcp_seq_stop(struct seq_file *seq, void *v)
case TCP_SEQ_STATE_TIME_WAIT:
case TCP_SEQ_STATE_ESTABLISHED:
if (v)
- read_unlock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
+ read_unlock_bh(inet_ehash_lockp(&tcp_hashinfo, st->bucket));
break;
}
}
@@ -2412,6 +2418,8 @@ void tcp4_proc_exit(void)
}
#endif /* CONFIG_PROC_FS */
+DEFINE_PROTO_INUSE(tcp)
+
struct proto tcp_prot = {
.name = "TCP",
.owner = THIS_MODULE,
@@ -2446,6 +2454,7 @@ struct proto tcp_prot = {
.compat_setsockopt = compat_tcp_setsockopt,
.compat_getsockopt = compat_tcp_getsockopt,
#endif
+ REF_PROTO_INUSE(tcp)
};
void __init tcp_v4_init(struct net_proto_family *ops)
diff --git a/net/ipv4/tcp_vegas.c b/net/ipv4/tcp_vegas.c
index b49dedcda52d..007304e99842 100644
--- a/net/ipv4/tcp_vegas.c
+++ b/net/ipv4/tcp_vegas.c
@@ -266,26 +266,25 @@ static void tcp_vegas_cong_avoid(struct sock *sk, u32 ack,
*/
diff = (old_wnd << V_PARAM_SHIFT) - target_cwnd;
- if (tp->snd_cwnd <= tp->snd_ssthresh) {
- /* Slow start. */
- if (diff > gamma) {
- /* Going too fast. Time to slow down
- * and switch to congestion avoidance.
- */
- tp->snd_ssthresh = 2;
-
- /* Set cwnd to match the actual rate
- * exactly:
- * cwnd = (actual rate) * baseRTT
- * Then we add 1 because the integer
- * truncation robs us of full link
- * utilization.
- */
- tp->snd_cwnd = min(tp->snd_cwnd,
- (target_cwnd >>
- V_PARAM_SHIFT)+1);
+ if (diff > gamma && tp->snd_ssthresh > 2 ) {
+ /* Going too fast. Time to slow down
+ * and switch to congestion avoidance.
+ */
+ tp->snd_ssthresh = 2;
+
+ /* Set cwnd to match the actual rate
+ * exactly:
+ * cwnd = (actual rate) * baseRTT
+ * Then we add 1 because the integer
+ * truncation robs us of full link
+ * utilization.
+ */
+ tp->snd_cwnd = min(tp->snd_cwnd,
+ (target_cwnd >>
+ V_PARAM_SHIFT)+1);
- }
+ } else if (tp->snd_cwnd <= tp->snd_ssthresh) {
+ /* Slow start. */
tcp_slow_start(tp);
} else {
/* Congestion avoidance. */
diff --git a/net/ipv4/tunnel4.c b/net/ipv4/tunnel4.c
index a794a8ca8b4f..978b3fd61e65 100644
--- a/net/ipv4/tunnel4.c
+++ b/net/ipv4/tunnel4.c
@@ -17,6 +17,11 @@ static struct xfrm_tunnel *tunnel4_handlers;
static struct xfrm_tunnel *tunnel64_handlers;
static DEFINE_MUTEX(tunnel4_mutex);
+static inline struct xfrm_tunnel **fam_handlers(unsigned short family)
+{
+ return (family == AF_INET) ? &tunnel4_handlers : &tunnel64_handlers;
+}
+
int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family)
{
struct xfrm_tunnel **pprev;
@@ -25,8 +30,7 @@ int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family)
mutex_lock(&tunnel4_mutex);
- for (pprev = (family == AF_INET) ? &tunnel4_handlers : &tunnel64_handlers;
- *pprev; pprev = &(*pprev)->next) {
+ for (pprev = fam_handlers(family); *pprev; pprev = &(*pprev)->next) {
if ((*pprev)->priority > priority)
break;
if ((*pprev)->priority == priority)
@@ -53,8 +57,7 @@ int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family)
mutex_lock(&tunnel4_mutex);
- for (pprev = (family == AF_INET) ? &tunnel4_handlers : &tunnel64_handlers;
- *pprev; pprev = &(*pprev)->next) {
+ for (pprev = fam_handlers(family); *pprev; pprev = &(*pprev)->next) {
if (*pprev == handler) {
*pprev = handler->next;
ret = 0;
@@ -118,6 +121,17 @@ static void tunnel4_err(struct sk_buff *skb, u32 info)
break;
}
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+static void tunnel64_err(struct sk_buff *skb, u32 info)
+{
+ struct xfrm_tunnel *handler;
+
+ for (handler = tunnel64_handlers; handler; handler = handler->next)
+ if (!handler->err_handler(skb, info))
+ break;
+}
+#endif
+
static struct net_protocol tunnel4_protocol = {
.handler = tunnel4_rcv,
.err_handler = tunnel4_err,
@@ -127,7 +141,7 @@ static struct net_protocol tunnel4_protocol = {
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
static struct net_protocol tunnel64_protocol = {
.handler = tunnel64_rcv,
- .err_handler = tunnel4_err,
+ .err_handler = tunnel64_err,
.no_policy = 1,
};
#endif
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index cb9fc58efb2f..03c400ca14c5 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -147,13 +147,14 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum,
write_lock_bh(&udp_hash_lock);
if (!snum) {
- int i, low, high;
+ int i, low, high, remaining;
unsigned rover, best, best_size_so_far;
inet_get_local_port_range(&low, &high);
+ remaining = (high - low) + 1;
best_size_so_far = UINT_MAX;
- best = rover = net_random() % (high - low) + low;
+ best = rover = net_random() % remaining + low;
/* 1st pass: look for empty (or shortest) hash chain */
for (i = 0; i < UDP_HTABLE_SIZE; i++) {
@@ -1151,7 +1152,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
return __udp4_lib_mcast_deliver(skb, uh, saddr, daddr, udptable);
sk = __udp4_lib_lookup(saddr, uh->source, daddr, uh->dest,
- skb->dev->ifindex, udptable );
+ inet_iif(skb), udptable);
if (sk != NULL) {
int ret = udp_queue_rcv_skb(sk, skb);
@@ -1429,6 +1430,8 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait)
}
+DEFINE_PROTO_INUSE(udp)
+
struct proto udp_prot = {
.name = "UDP",
.owner = THIS_MODULE,
@@ -1451,6 +1454,7 @@ struct proto udp_prot = {
.compat_setsockopt = compat_udp_setsockopt,
.compat_getsockopt = compat_udp_getsockopt,
#endif
+ REF_PROTO_INUSE(udp)
};
/* ------------------------------------------------------------------------ */
diff --git a/net/ipv4/udplite.c b/net/ipv4/udplite.c
index 94977205abb4..f5baeb3e8b85 100644
--- a/net/ipv4/udplite.c
+++ b/net/ipv4/udplite.c
@@ -44,6 +44,8 @@ static struct net_protocol udplite_protocol = {
.no_policy = 1,
};
+DEFINE_PROTO_INUSE(udplite)
+
struct proto udplite_prot = {
.name = "UDP-Lite",
.owner = THIS_MODULE,
@@ -67,6 +69,7 @@ struct proto udplite_prot = {
.compat_setsockopt = compat_udp_setsockopt,
.compat_getsockopt = compat_udp_getsockopt,
#endif
+ REF_PROTO_INUSE(udplite)
};
static struct inet_protosw udplite4_protosw = {
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
index e9bbfde19ac3..5e95c8a07efb 100644
--- a/net/ipv4/xfrm4_input.c
+++ b/net/ipv4/xfrm4_input.c
@@ -16,19 +16,6 @@
#include <net/ip.h>
#include <net/xfrm.h>
-static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq)
-{
- switch (nexthdr) {
- case IPPROTO_IPIP:
- case IPPROTO_IPV6:
- *spi = ip_hdr(skb)->saddr;
- *seq = 0;
- return 0;
- }
-
- return xfrm_parse_spi(skb, nexthdr, spi, seq);
-}
-
#ifdef CONFIG_NETFILTER
static inline int xfrm4_rcv_encap_finish(struct sk_buff *skb)
{
@@ -46,28 +33,29 @@ drop:
}
#endif
-static int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
+int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
+ int encap_type)
{
- __be32 spi, seq;
+ int err;
+ __be32 seq;
struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH];
struct xfrm_state *x;
int xfrm_nr = 0;
int decaps = 0;
- int err = xfrm4_parse_spi(skb, ip_hdr(skb)->protocol, &spi, &seq);
unsigned int nhoff = offsetof(struct iphdr, protocol);
- if (err != 0)
+ seq = 0;
+ if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0)
goto drop;
do {
const struct iphdr *iph = ip_hdr(skb);
- int nexthdr;
if (xfrm_nr == XFRM_MAX_DEPTH)
goto drop;
x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi,
- iph->protocol != IPPROTO_IPV6 ? iph->protocol : IPPROTO_IPIP, AF_INET);
+ nexthdr, AF_INET);
if (x == NULL)
goto drop;
@@ -103,15 +91,15 @@ static int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
xfrm_vec[xfrm_nr++] = x;
- if (x->mode->input(x, skb))
+ if (x->outer_mode->input(x, skb))
goto drop;
- if (x->props.mode == XFRM_MODE_TUNNEL) {
+ if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
decaps = 1;
break;
}
- err = xfrm_parse_spi(skb, ip_hdr(skb)->protocol, &spi, &seq);
+ err = xfrm_parse_spi(skb, nexthdr, &spi, &seq);
if (err < 0)
goto drop;
} while (!err);
@@ -165,6 +153,7 @@ drop:
kfree_skb(skb);
return 0;
}
+EXPORT_SYMBOL(xfrm4_rcv_encap);
/* If it's a keepalive packet, then just eat it.
* If it's an encapsulated packet, then pass it to the
@@ -252,11 +241,8 @@ int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
__skb_pull(skb, len);
skb_reset_transport_header(skb);
- /* modify the protocol (it's ESP!) */
- iph->protocol = IPPROTO_ESP;
-
/* process ESP */
- ret = xfrm4_rcv_encap(skb, encap_type);
+ ret = xfrm4_rcv_encap(skb, IPPROTO_ESP, 0, encap_type);
return ret;
drop:
@@ -266,7 +252,7 @@ drop:
int xfrm4_rcv(struct sk_buff *skb)
{
- return xfrm4_rcv_encap(skb, 0);
+ return xfrm4_rcv_spi(skb, ip_hdr(skb)->protocol, 0);
}
EXPORT_SYMBOL(xfrm4_rcv);
diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c
index 73d2338bec55..e42e122414be 100644
--- a/net/ipv4/xfrm4_mode_beet.c
+++ b/net/ipv4/xfrm4_mode_beet.c
@@ -114,6 +114,7 @@ static struct xfrm_mode xfrm4_beet_mode = {
.output = xfrm4_beet_output,
.owner = THIS_MODULE,
.encap = XFRM_MODE_BEET,
+ .flags = XFRM_MODE_FLAG_TUNNEL,
};
static int __init xfrm4_beet_init(void)
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index 1ae9d32276f0..e4deecba6dd2 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -139,6 +139,7 @@ static struct xfrm_mode xfrm4_tunnel_mode = {
.output = xfrm4_tunnel_output,
.owner = THIS_MODULE,
.encap = XFRM_MODE_TUNNEL,
+ .flags = XFRM_MODE_FLAG_TUNNEL,
};
static int __init xfrm4_tunnel_init(void)
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index 434ef302ba83..c4a7156962bd 100644
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -47,7 +47,7 @@ static inline int xfrm4_output_one(struct sk_buff *skb)
struct iphdr *iph;
int err;
- if (x->props.mode == XFRM_MODE_TUNNEL) {
+ if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
err = xfrm4_tunnel_check_size(skb);
if (err)
goto error_nolock;
@@ -78,7 +78,7 @@ static int xfrm4_output_finish2(struct sk_buff *skb)
while (likely((err = xfrm4_output_one(skb)) == 0)) {
nf_reset(skb);
- err = nf_hook(PF_INET, NF_IP_LOCAL_OUT, &skb, NULL,
+ err = nf_hook(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
skb->dst->dev, dst_output);
if (unlikely(err != 1))
break;
@@ -86,7 +86,7 @@ static int xfrm4_output_finish2(struct sk_buff *skb)
if (!skb->dst->xfrm)
return dst_output(skb);
- err = nf_hook(PF_INET, NF_IP_POST_ROUTING, &skb, NULL,
+ err = nf_hook(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
skb->dst->dev, xfrm4_output_finish2);
if (unlikely(err != 1))
break;
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 329825ca68fe..cc86fb110dd8 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -117,7 +117,7 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
header_len += xfrm[i]->props.header_len;
trailer_len += xfrm[i]->props.trailer_len;
- if (xfrm[i]->props.mode == XFRM_MODE_TUNNEL) {
+ if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
unsigned short encap_family = xfrm[i]->props.family;
switch (encap_family) {
case AF_INET:
@@ -151,7 +151,6 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
i = 0;
for (; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) {
struct xfrm_dst *x = (struct xfrm_dst*)dst_prev;
- struct xfrm_state_afinfo *afinfo;
x->u.rt.fl = *fl;
dst_prev->xfrm = xfrm[i++];
@@ -169,27 +168,17 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
/* Copy neighbout for reachability confirmation */
dst_prev->neighbour = neigh_clone(rt->u.dst.neighbour);
dst_prev->input = rt->u.dst.input;
- /* XXX: When IPv6 module can be unloaded, we should manage reference
- * to xfrm6_output in afinfo->output. Miyazawa
- * */
- afinfo = xfrm_state_get_afinfo(dst_prev->xfrm->props.family);
- if (!afinfo) {
- dst = *dst_p;
- err = -EAFNOSUPPORT;
- goto error;
- }
- dst_prev->output = afinfo->output;
- xfrm_state_put_afinfo(afinfo);
- if (dst_prev->xfrm->props.family == AF_INET && rt->peer)
- atomic_inc(&rt->peer->refcnt);
- x->u.rt.peer = rt->peer;
+ dst_prev->output = dst_prev->xfrm->outer_mode->afinfo->output;
+ if (rt0->peer)
+ atomic_inc(&rt0->peer->refcnt);
+ x->u.rt.peer = rt0->peer;
/* Sheit... I remember I did this right. Apparently,
* it was magically lost, so this code needs audit */
x->u.rt.rt_flags = rt0->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST|RTCF_LOCAL);
- x->u.rt.rt_type = rt->rt_type;
+ x->u.rt.rt_type = rt0->rt_type;
x->u.rt.rt_src = rt0->rt_src;
x->u.rt.rt_dst = rt0->rt_dst;
- x->u.rt.rt_gateway = rt->rt_gateway;
+ x->u.rt.rt_gateway = rt0->rt_gateway;
x->u.rt.rt_spec_dst = rt0->rt_spec_dst;
x->u.rt.idev = rt0->idev;
in_dev_hold(rt0->idev);
@@ -291,7 +280,7 @@ static void xfrm4_dst_destroy(struct dst_entry *dst)
if (likely(xdst->u.rt.idev))
in_dev_put(xdst->u.rt.idev);
- if (dst->xfrm && dst->xfrm->props.family == AF_INET && likely(xdst->u.rt.peer))
+ if (likely(xdst->u.rt.peer))
inet_putpeer(xdst->u.rt.peer);
xfrm_dst_destroy(xdst);
}
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c
index 93e2c061cdda..13d54a1c3337 100644
--- a/net/ipv4/xfrm4_state.c
+++ b/net/ipv4/xfrm4_state.c
@@ -49,6 +49,7 @@ __xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl,
static struct xfrm_state_afinfo xfrm4_state_afinfo = {
.family = AF_INET,
+ .owner = THIS_MODULE,
.init_flags = xfrm4_init_flags,
.init_tempsel = __xfrm4_init_tempsel,
.output = xfrm4_output,
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
index 1312417608e2..326845195620 100644
--- a/net/ipv4/xfrm4_tunnel.c
+++ b/net/ipv4/xfrm4_tunnel.c
@@ -18,7 +18,7 @@ static int ipip_output(struct xfrm_state *x, struct sk_buff *skb)
static int ipip_xfrm_rcv(struct xfrm_state *x, struct sk_buff *skb)
{
- return IPPROTO_IP;
+ return ip_hdr(skb)->protocol;
}
static int ipip_init_state(struct xfrm_state *x)
@@ -48,20 +48,25 @@ static struct xfrm_type ipip_type = {
.output = ipip_output
};
+static int xfrm_tunnel_rcv(struct sk_buff *skb)
+{
+ return xfrm4_rcv_spi(skb, IPPROTO_IP, ip_hdr(skb)->saddr);
+}
+
static int xfrm_tunnel_err(struct sk_buff *skb, u32 info)
{
return -ENOENT;
}
static struct xfrm_tunnel xfrm_tunnel_handler = {
- .handler = xfrm4_rcv,
+ .handler = xfrm_tunnel_rcv,
.err_handler = xfrm_tunnel_err,
.priority = 2,
};
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
static struct xfrm_tunnel xfrm64_tunnel_handler = {
- .handler = xfrm4_rcv,
+ .handler = xfrm_tunnel_rcv,
.err_handler = xfrm_tunnel_err,
.priority = 2,
};
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 52d10d213217..1bd8d818f8e9 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -255,11 +255,6 @@ static void addrconf_mod_timer(struct inet6_ifaddr *ifp,
static int snmp6_alloc_dev(struct inet6_dev *idev)
{
- int err = -ENOMEM;
-
- if (!idev || !idev->dev)
- return -EINVAL;
-
if (snmp_mib_init((void **)idev->stats.ipv6,
sizeof(struct ipstats_mib),
__alignof__(struct ipstats_mib)) < 0)
@@ -280,15 +275,14 @@ err_icmpmsg:
err_icmp:
snmp_mib_free((void **)idev->stats.ipv6);
err_ip:
- return err;
+ return -ENOMEM;
}
-static int snmp6_free_dev(struct inet6_dev *idev)
+static void snmp6_free_dev(struct inet6_dev *idev)
{
snmp_mib_free((void **)idev->stats.icmpv6msg);
snmp_mib_free((void **)idev->stats.icmpv6);
snmp_mib_free((void **)idev->stats.ipv6);
- return 0;
}
/* Nobody refers to this device, we may destroy it. */
@@ -4294,8 +4288,4 @@ void __exit addrconf_cleanup(void)
del_timer(&addr_chk_timer);
rtnl_unlock();
-
-#ifdef CONFIG_PROC_FS
- proc_net_remove(&init_net, "if_inet6");
-#endif
}
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index bc929381fa46..ecbd38894fdd 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -162,7 +162,7 @@ lookup_protocol:
BUG_TRAP(answer_prot->slab != NULL);
err = -ENOBUFS;
- sk = sk_alloc(net, PF_INET6, GFP_KERNEL, answer_prot, 1);
+ sk = sk_alloc(net, PF_INET6, GFP_KERNEL, answer_prot);
if (sk == NULL)
goto out;
@@ -747,6 +747,7 @@ static void cleanup_ipv6_mibs(void)
{
snmp_mib_free((void **)ipv6_statistics);
snmp_mib_free((void **)icmpv6_statistics);
+ snmp_mib_free((void **)icmpv6msg_statistics);
snmp_mib_free((void **)udp_stats_in6);
snmp_mib_free((void **)udplite_stats_in6);
}
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index f9f689162692..4eaf55072b1b 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -35,7 +35,6 @@
#include <net/ipv6.h>
#include <net/protocol.h>
#include <net/xfrm.h>
-#include <asm/scatterlist.h>
static int zero_out_mutable_opts(struct ipv6_opt_hdr *opthdr)
{
@@ -344,6 +343,8 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
goto out;
+ skb->ip_summed = CHECKSUM_NONE;
+
hdr_len = skb->data - skb_network_header(skb);
ah = (struct ip_auth_hdr *)skb->data;
ahp = x->data;
@@ -475,8 +476,16 @@ static int ah6_init_state(struct xfrm_state *x)
x->props.header_len = XFRM_ALIGN8(sizeof(struct ip_auth_hdr) +
ahp->icv_trunc_len);
- if (x->props.mode == XFRM_MODE_TUNNEL)
+ switch (x->props.mode) {
+ case XFRM_MODE_BEET:
+ case XFRM_MODE_TRANSPORT:
+ break;
+ case XFRM_MODE_TUNNEL:
x->props.header_len += sizeof(struct ipv6hdr);
+ break;
+ default:
+ goto error;
+ }
x->data = ahp;
return 0;
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 9eb928598351..7db66f10e00d 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -29,7 +29,7 @@
#include <net/ip.h>
#include <net/xfrm.h>
#include <net/esp.h>
-#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
#include <linux/crypto.h>
#include <linux/kernel.h>
#include <linux/pfkeyv2.h>
@@ -109,7 +109,11 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
if (!sg)
goto unlock;
}
- skb_to_sgvec(skb, sg, esph->enc_data+esp->conf.ivlen-skb->data, clen);
+ sg_init_table(sg, nfrags);
+ skb_to_sgvec(skb, sg,
+ esph->enc_data +
+ esp->conf.ivlen -
+ skb->data, clen);
err = crypto_blkcipher_encrypt(&desc, sg, sg, clen);
if (unlikely(sg != &esp->sgbuf[0]))
kfree(sg);
@@ -205,7 +209,10 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
goto out;
}
}
- skb_to_sgvec(skb, sg, sizeof(*esph) + esp->conf.ivlen, elen);
+ sg_init_table(sg, nfrags);
+ skb_to_sgvec(skb, sg,
+ sizeof(*esph) + esp->conf.ivlen,
+ elen);
ret = crypto_blkcipher_decrypt(&desc, sg, sg, elen);
if (unlikely(sg != &esp->sgbuf[0]))
kfree(sg);
@@ -354,8 +361,16 @@ static int esp6_init_state(struct xfrm_state *x)
(x->ealg->alg_key_len + 7) / 8))
goto error;
x->props.header_len = sizeof(struct ip_esp_hdr) + esp->conf.ivlen;
- if (x->props.mode == XFRM_MODE_TUNNEL)
+ switch (x->props.mode) {
+ case XFRM_MODE_BEET:
+ case XFRM_MODE_TRANSPORT:
+ break;
+ case XFRM_MODE_TUNNEL:
x->props.header_len += sizeof(struct ipv6hdr);
+ break;
+ default:
+ goto error;
+ }
x->data = esp;
return 0;
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index c82d4d49f71f..1e89efd38a0c 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -102,7 +102,7 @@ EXPORT_SYMBOL_GPL(ipv6_find_tlv);
struct tlvtype_proc {
int type;
- int (*func)(struct sk_buff **skbp, int offset);
+ int (*func)(struct sk_buff *skb, int offset);
};
/*********************
@@ -111,10 +111,8 @@ struct tlvtype_proc {
/* An unknown option is detected, decide what to do */
-static int ip6_tlvopt_unknown(struct sk_buff **skbp, int optoff)
+static int ip6_tlvopt_unknown(struct sk_buff *skb, int optoff)
{
- struct sk_buff *skb = *skbp;
-
switch ((skb_network_header(skb)[optoff] & 0xC0) >> 6) {
case 0: /* ignore */
return 1;
@@ -139,9 +137,8 @@ static int ip6_tlvopt_unknown(struct sk_buff **skbp, int optoff)
/* Parse tlv encoded option header (hop-by-hop or destination) */
-static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff **skbp)
+static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff *skb)
{
- struct sk_buff *skb = *skbp;
struct tlvtype_proc *curr;
const unsigned char *nh = skb_network_header(skb);
int off = skb_network_header_len(skb);
@@ -172,13 +169,13 @@ static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff **skbp)
/* type specific length/alignment
checks will be performed in the
func(). */
- if (curr->func(skbp, off) == 0)
+ if (curr->func(skb, off) == 0)
return 0;
break;
}
}
if (curr->type < 0) {
- if (ip6_tlvopt_unknown(skbp, off) == 0)
+ if (ip6_tlvopt_unknown(skb, off) == 0)
return 0;
}
break;
@@ -198,9 +195,8 @@ bad:
*****************************/
#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
-static int ipv6_dest_hao(struct sk_buff **skbp, int optoff)
+static int ipv6_dest_hao(struct sk_buff *skb, int optoff)
{
- struct sk_buff *skb = *skbp;
struct ipv6_destopt_hao *hao;
struct inet6_skb_parm *opt = IP6CB(skb);
struct ipv6hdr *ipv6h = ipv6_hdr(skb);
@@ -234,22 +230,13 @@ static int ipv6_dest_hao(struct sk_buff **skbp, int optoff)
goto discard;
if (skb_cloned(skb)) {
- struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
- struct inet6_skb_parm *opt2;
-
- if (skb2 == NULL)
+ if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
goto discard;
- opt2 = IP6CB(skb2);
- memcpy(opt2, opt, sizeof(*opt2));
-
- kfree_skb(skb);
-
/* update all variable using below by copied skbuff */
- *skbp = skb = skb2;
- hao = (struct ipv6_destopt_hao *)(skb_network_header(skb2) +
+ hao = (struct ipv6_destopt_hao *)(skb_network_header(skb) +
optoff);
- ipv6h = ipv6_hdr(skb2);
+ ipv6h = ipv6_hdr(skb);
}
if (skb->ip_summed == CHECKSUM_COMPLETE)
@@ -280,9 +267,8 @@ static struct tlvtype_proc tlvprocdestopt_lst[] = {
{-1, NULL}
};
-static int ipv6_destopt_rcv(struct sk_buff **skbp)
+static int ipv6_destopt_rcv(struct sk_buff *skb)
{
- struct sk_buff *skb = *skbp;
struct inet6_skb_parm *opt = IP6CB(skb);
#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
__u16 dstbuf;
@@ -304,9 +290,8 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp)
#endif
dst = dst_clone(skb->dst);
- if (ip6_parse_tlv(tlvprocdestopt_lst, skbp)) {
+ if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) {
dst_release(dst);
- skb = *skbp;
skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3;
opt = IP6CB(skb);
#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
@@ -337,10 +322,8 @@ void __init ipv6_destopt_init(void)
NONE header. No data in packet.
********************************/
-static int ipv6_nodata_rcv(struct sk_buff **skbp)
+static int ipv6_nodata_rcv(struct sk_buff *skb)
{
- struct sk_buff *skb = *skbp;
-
kfree_skb(skb);
return 0;
}
@@ -360,9 +343,8 @@ void __init ipv6_nodata_init(void)
Routing header.
********************************/
-static int ipv6_rthdr_rcv(struct sk_buff **skbp)
+static int ipv6_rthdr_rcv(struct sk_buff *skb)
{
- struct sk_buff *skb = *skbp;
struct inet6_skb_parm *opt = IP6CB(skb);
struct in6_addr *addr = NULL;
struct in6_addr daddr;
@@ -464,18 +446,14 @@ looped_back:
Do not damage packets queued somewhere.
*/
if (skb_cloned(skb)) {
- struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
/* the copy is a forwarded packet */
- if (skb2 == NULL) {
+ if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
IPSTATS_MIB_OUTDISCARDS);
kfree_skb(skb);
return -1;
}
- kfree_skb(skb);
- *skbp = skb = skb2;
- opt = IP6CB(skb2);
- hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb2);
+ hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb);
}
if (skb->ip_summed == CHECKSUM_COMPLETE)
@@ -578,9 +556,8 @@ static inline struct inet6_dev *ipv6_skb_idev(struct sk_buff *skb)
/* Router Alert as of RFC 2711 */
-static int ipv6_hop_ra(struct sk_buff **skbp, int optoff)
+static int ipv6_hop_ra(struct sk_buff *skb, int optoff)
{
- struct sk_buff *skb = *skbp;
const unsigned char *nh = skb_network_header(skb);
if (nh[optoff + 1] == 2) {
@@ -595,9 +572,8 @@ static int ipv6_hop_ra(struct sk_buff **skbp, int optoff)
/* Jumbo payload */
-static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff)
+static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff)
{
- struct sk_buff *skb = *skbp;
const unsigned char *nh = skb_network_header(skb);
u32 pkt_len;
@@ -648,9 +624,8 @@ static struct tlvtype_proc tlvprochopopt_lst[] = {
{ -1, }
};
-int ipv6_parse_hopopts(struct sk_buff **skbp)
+int ipv6_parse_hopopts(struct sk_buff *skb)
{
- struct sk_buff *skb = *skbp;
struct inet6_skb_parm *opt = IP6CB(skb);
/*
@@ -667,8 +642,7 @@ int ipv6_parse_hopopts(struct sk_buff **skbp)
}
opt->hop = sizeof(struct ipv6hdr);
- if (ip6_parse_tlv(tlvprochopopt_lst, skbp)) {
- skb = *skbp;
+ if (ip6_parse_tlv(tlvprochopopt_lst, skb)) {
skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3;
opt = IP6CB(skb);
opt->nhoff = sizeof(struct ipv6hdr);
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index 706622af206f..428c6b0e26d8 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -31,25 +31,6 @@ struct fib6_rule
static struct fib_rules_ops fib6_rules_ops;
-static struct fib6_rule main_rule = {
- .common = {
- .refcnt = ATOMIC_INIT(2),
- .pref = 0x7FFE,
- .action = FR_ACT_TO_TBL,
- .table = RT6_TABLE_MAIN,
- },
-};
-
-static struct fib6_rule local_rule = {
- .common = {
- .refcnt = ATOMIC_INIT(2),
- .pref = 0,
- .action = FR_ACT_TO_TBL,
- .table = RT6_TABLE_LOCAL,
- .flags = FIB_RULE_PERMANENT,
- },
-};
-
struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags,
pol_lookup_t lookup)
{
@@ -270,11 +251,23 @@ static struct fib_rules_ops fib6_rules_ops = {
.owner = THIS_MODULE,
};
-void __init fib6_rules_init(void)
+static int __init fib6_default_rules_init(void)
{
- list_add_tail(&local_rule.common.list, &fib6_rules_ops.rules_list);
- list_add_tail(&main_rule.common.list, &fib6_rules_ops.rules_list);
+ int err;
+
+ err = fib_default_rule_add(&fib6_rules_ops, 0,
+ RT6_TABLE_LOCAL, FIB_RULE_PERMANENT);
+ if (err < 0)
+ return err;
+ err = fib_default_rule_add(&fib6_rules_ops, 0x7FFE, RT6_TABLE_MAIN, 0);
+ if (err < 0)
+ return err;
+ return 0;
+}
+void __init fib6_rules_init(void)
+{
+ BUG_ON(fib6_default_rules_init());
fib_rules_register(&fib6_rules_ops);
}
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 47b8ce232e84..9bb031fa1c2f 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -82,7 +82,7 @@ EXPORT_SYMBOL(icmpv6msg_statistics);
static DEFINE_PER_CPU(struct socket *, __icmpv6_socket) = NULL;
#define icmpv6_socket __get_cpu_var(__icmpv6_socket)
-static int icmpv6_rcv(struct sk_buff **pskb);
+static int icmpv6_rcv(struct sk_buff *skb);
static struct inet6_protocol icmpv6_protocol = {
.handler = icmpv6_rcv,
@@ -614,9 +614,8 @@ static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info)
* Handle icmp messages
*/
-static int icmpv6_rcv(struct sk_buff **pskb)
+static int icmpv6_rcv(struct sk_buff *skb)
{
- struct sk_buff *skb = *pskb;
struct net_device *dev = skb->dev;
struct inet6_dev *idev = __in6_dev_get(dev);
struct in6_addr *saddr, *daddr;
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index 25b931709749..78de42ada844 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -146,7 +146,7 @@ void __inet6_csk_dst_store(struct sock *sk, struct dst_entry *dst,
__ip6_dst_store(sk, dst, daddr, saddr);
#ifdef CONFIG_XFRM
- if (dst) {
+ {
struct rt6_info *rt = (struct rt6_info *)dst;
rt->rt6i_flow_cache_genid = atomic_read(&flow_cache_genid);
}
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index 1c2c27655435..adc73adadfae 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -37,9 +37,8 @@ void __inet6_hash(struct inet_hashinfo *hashinfo,
} else {
unsigned int hash;
sk->sk_hash = hash = inet6_sk_ehashfn(sk);
- hash &= (hashinfo->ehash_size - 1);
- list = &hashinfo->ehash[hash].chain;
- lock = &hashinfo->ehash[hash].lock;
+ list = &inet_ehash_bucket(hashinfo, hash)->chain;
+ lock = inet_ehash_lockp(hashinfo, hash);
write_lock(lock);
}
@@ -70,9 +69,10 @@ struct sock *__inet6_lookup_established(struct inet_hashinfo *hashinfo,
*/
unsigned int hash = inet6_ehashfn(daddr, hnum, saddr, sport);
struct inet_ehash_bucket *head = inet_ehash_bucket(hashinfo, hash);
+ rwlock_t *lock = inet_ehash_lockp(hashinfo, hash);
prefetch(head->chain.first);
- read_lock(&head->lock);
+ read_lock(lock);
sk_for_each(sk, node, &head->chain) {
/* For IPV6 do the cheaper port and family tests first. */
if (INET6_MATCH(sk, hash, saddr, daddr, ports, dif))
@@ -92,12 +92,12 @@ struct sock *__inet6_lookup_established(struct inet_hashinfo *hashinfo,
goto hit;
}
}
- read_unlock(&head->lock);
+ read_unlock(lock);
return NULL;
hit:
sock_hold(sk);
- read_unlock(&head->lock);
+ read_unlock(lock);
return sk;
}
EXPORT_SYMBOL(__inet6_lookup_established);
@@ -175,12 +175,13 @@ static int __inet6_check_established(struct inet_timewait_death_row *death_row,
const unsigned int hash = inet6_ehashfn(daddr, lport, saddr,
inet->dport);
struct inet_ehash_bucket *head = inet_ehash_bucket(hinfo, hash);
+ rwlock_t *lock = inet_ehash_lockp(hinfo, hash);
struct sock *sk2;
const struct hlist_node *node;
struct inet_timewait_sock *tw;
prefetch(head->chain.first);
- write_lock(&head->lock);
+ write_lock(lock);
/* Check TIME-WAIT sockets first. */
sk_for_each(sk2, node, &head->twchain) {
@@ -216,7 +217,7 @@ unique:
__sk_add_node(sk, &head->chain);
sk->sk_hash = hash;
sock_prot_inc_use(sk->sk_prot);
- write_unlock(&head->lock);
+ write_unlock(lock);
if (twp != NULL) {
*twp = tw;
@@ -231,7 +232,7 @@ unique:
return 0;
not_unique:
- write_unlock(&head->lock);
+ write_unlock(lock);
return -EADDRNOTAVAIL;
}
@@ -261,7 +262,7 @@ int inet6_hash_connect(struct inet_timewait_death_row *death_row,
struct inet_timewait_sock *tw = NULL;
inet_get_local_port_range(&low, &high);
- remaining = high - low;
+ remaining = (high - low) + 1;
local_bh_disable();
for (i = 1; i <= remaining; i++) {
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index 217d60f9fc80..b12cc22e7745 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -154,8 +154,10 @@ static void ip6_fl_gc(unsigned long dummy)
write_unlock(&ip6_fl_lock);
}
-static int fl_intern(struct ip6_flowlabel *fl, __be32 label)
+static struct ip6_flowlabel *fl_intern(struct ip6_flowlabel *fl, __be32 label)
{
+ struct ip6_flowlabel *lfl;
+
fl->label = label & IPV6_FLOWLABEL_MASK;
write_lock_bh(&ip6_fl_lock);
@@ -163,12 +165,26 @@ static int fl_intern(struct ip6_flowlabel *fl, __be32 label)
for (;;) {
fl->label = htonl(net_random())&IPV6_FLOWLABEL_MASK;
if (fl->label) {
- struct ip6_flowlabel *lfl;
lfl = __fl_lookup(fl->label);
if (lfl == NULL)
break;
}
}
+ } else {
+ /*
+ * we dropper the ip6_fl_lock, so this entry could reappear
+ * and we need to recheck with it.
+ *
+ * OTOH no need to search the active socket first, like it is
+ * done in ipv6_flowlabel_opt - sock is locked, so new entry
+ * with the same label can only appear on another sock
+ */
+ lfl = __fl_lookup(fl->label);
+ if (lfl != NULL) {
+ atomic_inc(&lfl->users);
+ write_unlock_bh(&ip6_fl_lock);
+ return lfl;
+ }
}
fl->lastuse = jiffies;
@@ -176,7 +192,7 @@ static int fl_intern(struct ip6_flowlabel *fl, __be32 label)
fl_ht[FL_HASH(fl->label)] = fl;
atomic_inc(&fl_size);
write_unlock_bh(&ip6_fl_lock);
- return 0;
+ return NULL;
}
@@ -190,14 +206,17 @@ struct ip6_flowlabel * fl6_sock_lookup(struct sock *sk, __be32 label)
label &= IPV6_FLOWLABEL_MASK;
+ read_lock_bh(&ip6_sk_fl_lock);
for (sfl=np->ipv6_fl_list; sfl; sfl = sfl->next) {
struct ip6_flowlabel *fl = sfl->fl;
if (fl->label == label) {
fl->lastuse = jiffies;
atomic_inc(&fl->users);
+ read_unlock_bh(&ip6_sk_fl_lock);
return fl;
}
}
+ read_unlock_bh(&ip6_sk_fl_lock);
return NULL;
}
@@ -409,6 +428,16 @@ static int ipv6_opt_cmp(struct ipv6_txoptions *o1, struct ipv6_txoptions *o2)
return 0;
}
+static inline void fl_link(struct ipv6_pinfo *np, struct ipv6_fl_socklist *sfl,
+ struct ip6_flowlabel *fl)
+{
+ write_lock_bh(&ip6_sk_fl_lock);
+ sfl->fl = fl;
+ sfl->next = np->ipv6_fl_list;
+ np->ipv6_fl_list = sfl;
+ write_unlock_bh(&ip6_sk_fl_lock);
+}
+
int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
{
int err;
@@ -416,7 +445,8 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
struct in6_flowlabel_req freq;
struct ipv6_fl_socklist *sfl1=NULL;
struct ipv6_fl_socklist *sfl, **sflp;
- struct ip6_flowlabel *fl;
+ struct ip6_flowlabel *fl, *fl1 = NULL;
+
if (optlen < sizeof(freq))
return -EINVAL;
@@ -472,8 +502,6 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
sfl1 = kmalloc(sizeof(*sfl1), GFP_KERNEL);
if (freq.flr_label) {
- struct ip6_flowlabel *fl1 = NULL;
-
err = -EEXIST;
read_lock_bh(&ip6_sk_fl_lock);
for (sfl = np->ipv6_fl_list; sfl; sfl = sfl->next) {
@@ -492,6 +520,7 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
if (fl1 == NULL)
fl1 = fl_lookup(freq.flr_label);
if (fl1) {
+recheck:
err = -EEXIST;
if (freq.flr_flags&IPV6_FL_F_EXCL)
goto release;
@@ -513,11 +542,7 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
fl1->linger = fl->linger;
if ((long)(fl->expires - fl1->expires) > 0)
fl1->expires = fl->expires;
- write_lock_bh(&ip6_sk_fl_lock);
- sfl1->fl = fl1;
- sfl1->next = np->ipv6_fl_list;
- np->ipv6_fl_list = sfl1;
- write_unlock_bh(&ip6_sk_fl_lock);
+ fl_link(np, sfl1, fl1);
fl_free(fl);
return 0;
@@ -534,9 +559,9 @@ release:
if (sfl1 == NULL || (err = mem_check(sk)) != 0)
goto done;
- err = fl_intern(fl, freq.flr_label);
- if (err)
- goto done;
+ fl1 = fl_intern(fl, freq.flr_label);
+ if (fl1 != NULL)
+ goto recheck;
if (!freq.flr_label) {
if (copy_to_user(&((struct in6_flowlabel_req __user *) optval)->flr_label,
@@ -545,9 +570,7 @@ release:
}
}
- sfl1->fl = fl;
- sfl1->next = np->ipv6_fl_list;
- np->ipv6_fl_list = sfl1;
+ fl_link(np, sfl1, fl);
return 0;
default:
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 9149fc239759..fac6f7f9dd73 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -125,7 +125,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
}
if (hdr->nexthdr == NEXTHDR_HOP) {
- if (ipv6_parse_hopopts(&skb) < 0) {
+ if (ipv6_parse_hopopts(skb) < 0) {
IP6_INC_STATS_BH(idev, IPSTATS_MIB_INHDRERRORS);
rcu_read_unlock();
return 0;
@@ -149,7 +149,7 @@ out:
*/
-static inline int ip6_input_finish(struct sk_buff *skb)
+static int ip6_input_finish(struct sk_buff *skb)
{
struct inet6_protocol *ipprot;
struct sock *raw_sk;
@@ -199,7 +199,7 @@ resubmit:
!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
goto discard;
- ret = ipprot->handler(&skb);
+ ret = ipprot->handler(skb);
if (ret > 0)
goto resubmit;
else if (ret == 0)
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 011082ed921a..86e1835ce4e4 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -70,7 +70,7 @@ static __inline__ void ipv6_select_ident(struct sk_buff *skb, struct frag_hdr *f
spin_unlock_bh(&ip6_id_lock);
}
-static inline int ip6_output_finish(struct sk_buff *skb)
+static int ip6_output_finish(struct sk_buff *skb)
{
struct dst_entry *dst = skb->dst;
@@ -171,7 +171,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
u32 mtu;
if (opt) {
- int head_room;
+ unsigned int head_room;
/* First: exthdrs may take lots of space (~8K for now)
MAX_HEADER is not enough.
@@ -1339,6 +1339,19 @@ error:
return err;
}
+static void ip6_cork_release(struct inet_sock *inet, struct ipv6_pinfo *np)
+{
+ inet->cork.flags &= ~IPCORK_OPT;
+ kfree(np->cork.opt);
+ np->cork.opt = NULL;
+ if (np->cork.rt) {
+ dst_release(&np->cork.rt->u.dst);
+ np->cork.rt = NULL;
+ inet->cork.flags &= ~IPCORK_ALLFRAG;
+ }
+ memset(&inet->cork.fl, 0, sizeof(inet->cork.fl));
+}
+
int ip6_push_pending_frames(struct sock *sk)
{
struct sk_buff *skb, *tmp_skb;
@@ -1415,15 +1428,7 @@ int ip6_push_pending_frames(struct sock *sk)
}
out:
- inet->cork.flags &= ~IPCORK_OPT;
- kfree(np->cork.opt);
- np->cork.opt = NULL;
- if (np->cork.rt) {
- dst_release(&np->cork.rt->u.dst);
- np->cork.rt = NULL;
- inet->cork.flags &= ~IPCORK_ALLFRAG;
- }
- memset(&inet->cork.fl, 0, sizeof(inet->cork.fl));
+ ip6_cork_release(inet, np);
return err;
error:
goto out;
@@ -1431,8 +1436,6 @@ error:
void ip6_flush_pending_frames(struct sock *sk)
{
- struct inet_sock *inet = inet_sk(sk);
- struct ipv6_pinfo *np = inet6_sk(sk);
struct sk_buff *skb;
while ((skb = __skb_dequeue_tail(&sk->sk_write_queue)) != NULL) {
@@ -1442,14 +1445,5 @@ void ip6_flush_pending_frames(struct sock *sk)
kfree_skb(skb);
}
- inet->cork.flags &= ~IPCORK_OPT;
-
- kfree(np->cork.opt);
- np->cork.opt = NULL;
- if (np->cork.rt) {
- dst_release(&np->cork.rt->u.dst);
- np->cork.rt = NULL;
- inet->cork.flags &= ~IPCORK_ALLFRAG;
- }
- memset(&inet->cork.fl, 0, sizeof(inet->cork.fl));
+ ip6_cork_release(inet_sk(sk), inet6_sk(sk));
}
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 2320cc27ff9e..5383b33db8ca 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -838,7 +838,7 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
struct dst_entry *dst;
struct net_device *tdev;
int mtu;
- int max_headroom = sizeof(struct ipv6hdr);
+ unsigned int max_headroom = sizeof(struct ipv6hdr);
u8 proto;
int err = -1;
int pkt_len;
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index 28fc8edfdc3a..0cd4056f9127 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -34,9 +34,9 @@
#include <net/ip.h>
#include <net/xfrm.h>
#include <net/ipcomp.h>
-#include <asm/scatterlist.h>
#include <asm/semaphore.h>
#include <linux/crypto.h>
+#include <linux/err.h>
#include <linux/pfkeyv2.h>
#include <linux/random.h>
#include <linux/percpu.h>
@@ -359,7 +359,7 @@ static struct crypto_comp **ipcomp6_alloc_tfms(const char *alg_name)
for_each_possible_cpu(cpu) {
struct crypto_comp *tfm = crypto_alloc_comp(alg_name, 0,
CRYPTO_ALG_ASYNC);
- if (!tfm)
+ if (IS_ERR(tfm))
goto error;
*per_cpu_ptr(tfms, cpu) = tfm;
}
@@ -411,8 +411,15 @@ static int ipcomp6_init_state(struct xfrm_state *x)
goto out;
x->props.header_len = 0;
- if (x->props.mode == XFRM_MODE_TUNNEL)
+ switch (x->props.mode) {
+ case XFRM_MODE_BEET:
+ case XFRM_MODE_TRANSPORT:
+ break;
+ case XFRM_MODE_TUNNEL:
x->props.header_len += sizeof(struct ipv6hdr);
+ default:
+ goto error;
+ }
mutex_lock(&ipcomp6_resource_mutex);
if (!ipcomp6_alloc_scratches())
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 6cc33dc83d1c..67997a74ddce 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1037,6 +1037,7 @@ static void ndisc_ra_useropt(struct sk_buff *ra, struct nd_opt_hdr *opt)
ndmsg = nlmsg_data(nlh);
ndmsg->nduseropt_family = AF_INET6;
+ ndmsg->nduseropt_ifindex = ra->dev->ifindex;
ndmsg->nduseropt_icmp_type = icmp6h->icmp6_type;
ndmsg->nduseropt_icmp_code = icmp6h->icmp6_code;
ndmsg->nduseropt_opts_len = opt->nd_opt_len << 3;
@@ -1658,30 +1659,26 @@ int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, struct file * f
struct inet6_dev *idev;
int ret;
- if (ctl->ctl_name == NET_NEIGH_RETRANS_TIME ||
- ctl->ctl_name == NET_NEIGH_REACHABLE_TIME)
+ if ((strcmp(ctl->procname, "retrans_time") == 0) ||
+ (strcmp(ctl->procname, "base_reachable_time") == 0))
ndisc_warn_deprecated_sysctl(ctl, "syscall", dev ? dev->name : "default");
- switch (ctl->ctl_name) {
- case NET_NEIGH_RETRANS_TIME:
+ if (strcmp(ctl->procname, "retrans_time") == 0)
ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
- break;
- case NET_NEIGH_REACHABLE_TIME:
+
+ else if (strcmp(ctl->procname, "base_reachable_time") == 0)
ret = proc_dointvec_jiffies(ctl, write,
filp, buffer, lenp, ppos);
- break;
- case NET_NEIGH_RETRANS_TIME_MS:
- case NET_NEIGH_REACHABLE_TIME_MS:
+
+ else if ((strcmp(ctl->procname, "retrans_time_ms") == 0) ||
+ (strcmp(ctl->procname, "base_reachable_time_ms") == 0))
ret = proc_dointvec_ms_jiffies(ctl, write,
filp, buffer, lenp, ppos);
- break;
- default:
+ else
ret = -1;
- }
if (write && ret == 0 && dev && (idev = in6_dev_get(dev)) != NULL) {
- if (ctl->ctl_name == NET_NEIGH_REACHABLE_TIME ||
- ctl->ctl_name == NET_NEIGH_REACHABLE_TIME_MS)
+ if (ctl->data == &idev->nd_parms->base_reachable_time)
idev->nd_parms->reachable_time = neigh_rand_reach_time(idev->nd_parms->base_reachable_time);
idev->tstamp = jiffies;
inet6_ifinfo_notify(RTM_NEWLINK, idev);
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
index 38b149613915..b1326c2bf8aa 100644
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -68,15 +68,15 @@ static void nf_ip6_saveroute(const struct sk_buff *skb, struct nf_info *info)
}
}
-static int nf_ip6_reroute(struct sk_buff **pskb, const struct nf_info *info)
+static int nf_ip6_reroute(struct sk_buff *skb, const struct nf_info *info)
{
struct ip6_rt_info *rt_info = nf_info_reroute(info);
if (info->hook == NF_IP6_LOCAL_OUT) {
- struct ipv6hdr *iph = ipv6_hdr(*pskb);
+ struct ipv6hdr *iph = ipv6_hdr(skb);
if (!ipv6_addr_equal(&iph->daddr, &rt_info->daddr) ||
!ipv6_addr_equal(&iph->saddr, &rt_info->saddr))
- return ip6_route_me_harder(*pskb);
+ return ip6_route_me_harder(skb);
}
return 0;
}
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index 4513eab77397..e789ec44d23b 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -4,25 +4,29 @@
# Link order matters here.
obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o
-obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
-obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o
-obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
-obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o
-obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o
-obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o
-obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
-obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
-obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
-obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
-obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
-obj-$(CONFIG_IP6_NF_MATCH_MH) += ip6t_mh.o
# objects for l3 independent conntrack
nf_conntrack_ipv6-objs := nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o nf_conntrack_reasm.o
# l3 independent conntrack
obj-$(CONFIG_NF_CONNTRACK_IPV6) += nf_conntrack_ipv6.o
+
+# matches
+obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o
+obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o
+obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o
+obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
+obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
+obj-$(CONFIG_IP6_NF_MATCH_MH) += ip6t_mh.o
+obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o
+obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
+obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
+
+# targets
+obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
+obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
+obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index 0473145ac534..e273605eef85 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -23,6 +23,7 @@
#include <linux/spinlock.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <linux/mutex.h>
#include <net/net_namespace.h>
#include <net/sock.h>
@@ -332,6 +333,7 @@ static int
ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
{
int diff;
+ int err;
struct ipv6hdr *user_iph = (struct ipv6hdr *)v->payload;
if (v->data_len < sizeof(*user_iph))
@@ -344,25 +346,18 @@ ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
if (v->data_len > 0xFFFF)
return -EINVAL;
if (diff > skb_tailroom(e->skb)) {
- struct sk_buff *newskb;
-
- newskb = skb_copy_expand(e->skb,
- skb_headroom(e->skb),
- diff,
- GFP_ATOMIC);
- if (newskb == NULL) {
+ err = pskb_expand_head(e->skb, 0,
+ diff - skb_tailroom(e->skb),
+ GFP_ATOMIC);
+ if (err) {
printk(KERN_WARNING "ip6_queue: OOM "
"in mangle, dropping packet\n");
- return -ENOMEM;
+ return err;
}
- if (e->skb->sk)
- skb_set_owner_w(newskb, e->skb->sk);
- kfree_skb(e->skb);
- e->skb = newskb;
}
skb_put(e->skb, diff);
}
- if (!skb_make_writable(&e->skb, v->data_len))
+ if (!skb_make_writable(e->skb, v->data_len))
return -ENOMEM;
skb_copy_to_linear_data(e->skb, v->payload, v->data_len);
e->skb->ip_summed = CHECKSUM_NONE;
@@ -602,15 +597,11 @@ static ctl_table ipq_root_table[] = {
{ .ctl_name = 0 }
};
-#ifdef CONFIG_PROC_FS
-static int
-ipq_get_info(char *buffer, char **start, off_t offset, int length)
+static int ip6_queue_show(struct seq_file *m, void *v)
{
- int len;
-
read_lock_bh(&queue_lock);
- len = sprintf(buffer,
+ seq_printf(m,
"Peer PID : %d\n"
"Copy mode : %hu\n"
"Copy range : %u\n"
@@ -627,16 +618,21 @@ ipq_get_info(char *buffer, char **start, off_t offset, int length)
queue_user_dropped);
read_unlock_bh(&queue_lock);
+ return 0;
+}
- *start = buffer + offset;
- len -= offset;
- if (len > length)
- len = length;
- else if (len < 0)
- len = 0;
- return len;
+static int ip6_queue_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, ip6_queue_show, NULL);
}
-#endif /* CONFIG_PROC_FS */
+
+static const struct file_operations ip6_queue_proc_fops = {
+ .open = ip6_queue_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .owner = THIS_MODULE,
+};
static struct nf_queue_handler nfqh = {
.name = "ip6_queue",
@@ -656,10 +652,11 @@ static int __init ip6_queue_init(void)
goto cleanup_netlink_notifier;
}
- proc = proc_net_create(&init_net, IPQ_PROC_FS_NAME, 0, ipq_get_info);
- if (proc)
+ proc = create_proc_entry(IPQ_PROC_FS_NAME, 0, init_net.proc_net);
+ if (proc) {
proc->owner = THIS_MODULE;
- else {
+ proc->proc_fops = &ip6_queue_proc_fops;
+ } else {
printk(KERN_ERR "ip6_queue: failed to create proc entry\n");
goto cleanup_ipqnl;
}
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index cd9df02bb85c..acaba1537931 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -205,7 +205,7 @@ ip6_checkentry(const struct ip6t_ip6 *ipv6)
}
static unsigned int
-ip6t_error(struct sk_buff **pskb,
+ip6t_error(struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
unsigned int hooknum,
@@ -350,7 +350,7 @@ static void trace_packet(struct sk_buff *skb,
/* Returns one of the generic firewall policies, like NF_ACCEPT. */
unsigned int
-ip6t_do_table(struct sk_buff **pskb,
+ip6t_do_table(struct sk_buff *skb,
unsigned int hook,
const struct net_device *in,
const struct net_device *out,
@@ -389,17 +389,17 @@ ip6t_do_table(struct sk_buff **pskb,
do {
IP_NF_ASSERT(e);
IP_NF_ASSERT(back);
- if (ip6_packet_match(*pskb, indev, outdev, &e->ipv6,
+ if (ip6_packet_match(skb, indev, outdev, &e->ipv6,
&protoff, &offset, &hotdrop)) {
struct ip6t_entry_target *t;
if (IP6T_MATCH_ITERATE(e, do_match,
- *pskb, in, out,
+ skb, in, out,
offset, protoff, &hotdrop) != 0)
goto no_match;
ADD_COUNTER(e->counters,
- ntohs(ipv6_hdr(*pskb)->payload_len)
+ ntohs(ipv6_hdr(skb)->payload_len)
+ IPV6_HDR_LEN,
1);
@@ -409,8 +409,8 @@ ip6t_do_table(struct sk_buff **pskb,
#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
/* The packet is traced: log it */
- if (unlikely((*pskb)->nf_trace))
- trace_packet(*pskb, hook, in, out,
+ if (unlikely(skb->nf_trace))
+ trace_packet(skb, hook, in, out,
table->name, private, e);
#endif
/* Standard target? */
@@ -448,7 +448,7 @@ ip6t_do_table(struct sk_buff **pskb,
((struct ip6t_entry *)table_base)->comefrom
= 0xeeeeeeec;
#endif
- verdict = t->u.kernel.target->target(pskb,
+ verdict = t->u.kernel.target->target(skb,
in, out,
hook,
t->u.kernel.target,
diff --git a/net/ipv6/netfilter/ip6t_HL.c b/net/ipv6/netfilter/ip6t_HL.c
index ad4d94310b87..9afc836fd454 100644
--- a/net/ipv6/netfilter/ip6t_HL.c
+++ b/net/ipv6/netfilter/ip6t_HL.c
@@ -18,7 +18,7 @@ MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
MODULE_DESCRIPTION("IP6 tables Hop Limit modification module");
MODULE_LICENSE("GPL");
-static unsigned int ip6t_hl_target(struct sk_buff **pskb,
+static unsigned int ip6t_hl_target(struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
unsigned int hooknum,
@@ -29,10 +29,10 @@ static unsigned int ip6t_hl_target(struct sk_buff **pskb,
const struct ip6t_HL_info *info = targinfo;
int new_hl;
- if (!skb_make_writable(pskb, (*pskb)->len))
+ if (!skb_make_writable(skb, skb->len))
return NF_DROP;
- ip6h = ipv6_hdr(*pskb);
+ ip6h = ipv6_hdr(skb);
switch (info->mode) {
case IP6T_HL_SET:
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index 6ab99001dccc..7a48c342df46 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ b/net/ipv6/netfilter/ip6t_LOG.c
@@ -431,7 +431,7 @@ ip6t_log_packet(unsigned int pf,
}
static unsigned int
-ip6t_log_target(struct sk_buff **pskb,
+ip6t_log_target(struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
unsigned int hooknum,
@@ -445,8 +445,7 @@ ip6t_log_target(struct sk_buff **pskb,
li.u.log.level = loginfo->level;
li.u.log.logflags = loginfo->logflags;
- ip6t_log_packet(PF_INET6, hooknum, *pskb, in, out, &li,
- loginfo->prefix);
+ ip6t_log_packet(PF_INET6, hooknum, skb, in, out, &li, loginfo->prefix);
return XT_CONTINUE;
}
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c
index 3fd08d5567a6..1a7d2917545d 100644
--- a/net/ipv6/netfilter/ip6t_REJECT.c
+++ b/net/ipv6/netfilter/ip6t_REJECT.c
@@ -172,7 +172,7 @@ send_unreach(struct sk_buff *skb_in, unsigned char code, unsigned int hooknum)
icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0, NULL);
}
-static unsigned int reject6_target(struct sk_buff **pskb,
+static unsigned int reject6_target(struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
unsigned int hooknum,
@@ -187,25 +187,25 @@ static unsigned int reject6_target(struct sk_buff **pskb,
must return an absolute verdict. --RR */
switch (reject->with) {
case IP6T_ICMP6_NO_ROUTE:
- send_unreach(*pskb, ICMPV6_NOROUTE, hooknum);
+ send_unreach(skb, ICMPV6_NOROUTE, hooknum);
break;
case IP6T_ICMP6_ADM_PROHIBITED:
- send_unreach(*pskb, ICMPV6_ADM_PROHIBITED, hooknum);
+ send_unreach(skb, ICMPV6_ADM_PROHIBITED, hooknum);
break;
case IP6T_ICMP6_NOT_NEIGHBOUR:
- send_unreach(*pskb, ICMPV6_NOT_NEIGHBOUR, hooknum);
+ send_unreach(skb, ICMPV6_NOT_NEIGHBOUR, hooknum);
break;
case IP6T_ICMP6_ADDR_UNREACH:
- send_unreach(*pskb, ICMPV6_ADDR_UNREACH, hooknum);
+ send_unreach(skb, ICMPV6_ADDR_UNREACH, hooknum);
break;
case IP6T_ICMP6_PORT_UNREACH:
- send_unreach(*pskb, ICMPV6_PORT_UNREACH, hooknum);
+ send_unreach(skb, ICMPV6_PORT_UNREACH, hooknum);
break;
case IP6T_ICMP6_ECHOREPLY:
/* Do nothing */
break;
case IP6T_TCP_RESET:
- send_reset(*pskb);
+ send_reset(skb);
break;
default:
if (net_ratelimit())
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
index 7e32e2aaf7f7..1d26b202bf30 100644
--- a/net/ipv6/netfilter/ip6table_filter.c
+++ b/net/ipv6/netfilter/ip6table_filter.c
@@ -60,32 +60,32 @@ static struct xt_table packet_filter = {
/* The work comes in here from netfilter.c. */
static unsigned int
ip6t_hook(unsigned int hook,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
- return ip6t_do_table(pskb, hook, in, out, &packet_filter);
+ return ip6t_do_table(skb, hook, in, out, &packet_filter);
}
static unsigned int
ip6t_local_out_hook(unsigned int hook,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
#if 0
/* root is playing with raw sockets. */
- if ((*pskb)->len < sizeof(struct iphdr)
- || ip_hdrlen(*pskb) < sizeof(struct iphdr)) {
+ if (skb->len < sizeof(struct iphdr)
+ || ip_hdrlen(skb) < sizeof(struct iphdr)) {
if (net_ratelimit())
printk("ip6t_hook: happy cracking.\n");
return NF_ACCEPT;
}
#endif
- return ip6t_do_table(pskb, hook, in, out, &packet_filter);
+ return ip6t_do_table(skb, hook, in, out, &packet_filter);
}
static struct nf_hook_ops ip6t_ops[] = {
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index f0a9efa67fb5..a0b6381f1e8c 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -68,17 +68,17 @@ static struct xt_table packet_mangler = {
/* The work comes in here from netfilter.c. */
static unsigned int
ip6t_route_hook(unsigned int hook,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
- return ip6t_do_table(pskb, hook, in, out, &packet_mangler);
+ return ip6t_do_table(skb, hook, in, out, &packet_mangler);
}
static unsigned int
ip6t_local_hook(unsigned int hook,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
@@ -91,8 +91,8 @@ ip6t_local_hook(unsigned int hook,
#if 0
/* root is playing with raw sockets. */
- if ((*pskb)->len < sizeof(struct iphdr)
- || ip_hdrlen(*pskb) < sizeof(struct iphdr)) {
+ if (skb->len < sizeof(struct iphdr)
+ || ip_hdrlen(skb) < sizeof(struct iphdr)) {
if (net_ratelimit())
printk("ip6t_hook: happy cracking.\n");
return NF_ACCEPT;
@@ -100,22 +100,22 @@ ip6t_local_hook(unsigned int hook,
#endif
/* save source/dest address, mark, hoplimit, flowlabel, priority, */
- memcpy(&saddr, &ipv6_hdr(*pskb)->saddr, sizeof(saddr));
- memcpy(&daddr, &ipv6_hdr(*pskb)->daddr, sizeof(daddr));
- mark = (*pskb)->mark;
- hop_limit = ipv6_hdr(*pskb)->hop_limit;
+ memcpy(&saddr, &ipv6_hdr(skb)->saddr, sizeof(saddr));
+ memcpy(&daddr, &ipv6_hdr(skb)->daddr, sizeof(daddr));
+ mark = skb->mark;
+ hop_limit = ipv6_hdr(skb)->hop_limit;
/* flowlabel and prio (includes version, which shouldn't change either */
- flowlabel = *((u_int32_t *)ipv6_hdr(*pskb));
+ flowlabel = *((u_int32_t *)ipv6_hdr(skb));
- ret = ip6t_do_table(pskb, hook, in, out, &packet_mangler);
+ ret = ip6t_do_table(skb, hook, in, out, &packet_mangler);
if (ret != NF_DROP && ret != NF_STOLEN
- && (memcmp(&ipv6_hdr(*pskb)->saddr, &saddr, sizeof(saddr))
- || memcmp(&ipv6_hdr(*pskb)->daddr, &daddr, sizeof(daddr))
- || (*pskb)->mark != mark
- || ipv6_hdr(*pskb)->hop_limit != hop_limit))
- return ip6_route_me_harder(*pskb) == 0 ? ret : NF_DROP;
+ && (memcmp(&ipv6_hdr(skb)->saddr, &saddr, sizeof(saddr))
+ || memcmp(&ipv6_hdr(skb)->daddr, &daddr, sizeof(daddr))
+ || skb->mark != mark
+ || ipv6_hdr(skb)->hop_limit != hop_limit))
+ return ip6_route_me_harder(skb) == 0 ? ret : NF_DROP;
return ret;
}
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index ec290e4ebdd8..8f7109f991e6 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -46,12 +46,12 @@ static struct xt_table packet_raw = {
/* The work comes in here from netfilter.c. */
static unsigned int
ip6t_hook(unsigned int hook,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
- return ip6t_do_table(pskb, hook, in, out, &packet_raw);
+ return ip6t_do_table(skb, hook, in, out, &packet_raw);
}
static struct nf_hook_ops ip6t_ops[] = {
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index 37a3db926953..ad74bab05047 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -18,6 +18,7 @@
#include <linux/icmp.h>
#include <linux/sysctl.h>
#include <net/ipv6.h>
+#include <net/inet_frag.h>
#include <linux/netfilter_ipv6.h>
#include <net/netfilter/nf_conntrack.h>
@@ -145,7 +146,7 @@ static int ipv6_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
}
static unsigned int ipv6_confirm(unsigned int hooknum,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
@@ -155,12 +156,12 @@ static unsigned int ipv6_confirm(unsigned int hooknum,
struct nf_conntrack_helper *helper;
enum ip_conntrack_info ctinfo;
unsigned int ret, protoff;
- unsigned int extoff = (u8 *)(ipv6_hdr(*pskb) + 1) - (*pskb)->data;
- unsigned char pnum = ipv6_hdr(*pskb)->nexthdr;
+ unsigned int extoff = (u8 *)(ipv6_hdr(skb) + 1) - skb->data;
+ unsigned char pnum = ipv6_hdr(skb)->nexthdr;
/* This is where we call the helper: as the packet goes out. */
- ct = nf_ct_get(*pskb, &ctinfo);
+ ct = nf_ct_get(skb, &ctinfo);
if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)
goto out;
@@ -172,23 +173,23 @@ static unsigned int ipv6_confirm(unsigned int hooknum,
if (!helper)
goto out;
- protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum,
- (*pskb)->len - extoff);
- if (protoff > (*pskb)->len || pnum == NEXTHDR_FRAGMENT) {
+ protoff = nf_ct_ipv6_skip_exthdr(skb, extoff, &pnum,
+ skb->len - extoff);
+ if (protoff > skb->len || pnum == NEXTHDR_FRAGMENT) {
pr_debug("proto header not found\n");
return NF_ACCEPT;
}
- ret = helper->help(pskb, protoff, ct, ctinfo);
+ ret = helper->help(skb, protoff, ct, ctinfo);
if (ret != NF_ACCEPT)
return ret;
out:
/* We've seen it coming out the other side: confirm it */
- return nf_conntrack_confirm(pskb);
+ return nf_conntrack_confirm(skb);
}
static unsigned int ipv6_defrag(unsigned int hooknum,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
@@ -196,17 +197,17 @@ static unsigned int ipv6_defrag(unsigned int hooknum,
struct sk_buff *reasm;
/* Previously seen (loopback)? */
- if ((*pskb)->nfct)
+ if (skb->nfct)
return NF_ACCEPT;
- reasm = nf_ct_frag6_gather(*pskb);
+ reasm = nf_ct_frag6_gather(skb);
/* queued */
if (reasm == NULL)
return NF_STOLEN;
/* error occured or not fragmented */
- if (reasm == *pskb)
+ if (reasm == skb)
return NF_ACCEPT;
nf_ct_frag6_output(hooknum, reasm, (struct net_device *)in,
@@ -216,12 +217,12 @@ static unsigned int ipv6_defrag(unsigned int hooknum,
}
static unsigned int ipv6_conntrack_in(unsigned int hooknum,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
- struct sk_buff *reasm = (*pskb)->nfct_reasm;
+ struct sk_buff *reasm = skb->nfct_reasm;
/* This packet is fragmented and has reassembled packet. */
if (reasm) {
@@ -229,32 +230,32 @@ static unsigned int ipv6_conntrack_in(unsigned int hooknum,
if (!reasm->nfct) {
unsigned int ret;
- ret = nf_conntrack_in(PF_INET6, hooknum, &reasm);
+ ret = nf_conntrack_in(PF_INET6, hooknum, reasm);
if (ret != NF_ACCEPT)
return ret;
}
nf_conntrack_get(reasm->nfct);
- (*pskb)->nfct = reasm->nfct;
- (*pskb)->nfctinfo = reasm->nfctinfo;
+ skb->nfct = reasm->nfct;
+ skb->nfctinfo = reasm->nfctinfo;
return NF_ACCEPT;
}
- return nf_conntrack_in(PF_INET6, hooknum, pskb);
+ return nf_conntrack_in(PF_INET6, hooknum, skb);
}
static unsigned int ipv6_conntrack_local(unsigned int hooknum,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
/* root is playing with raw sockets. */
- if ((*pskb)->len < sizeof(struct ipv6hdr)) {
+ if (skb->len < sizeof(struct ipv6hdr)) {
if (net_ratelimit())
printk("ipv6_conntrack_local: packet too short\n");
return NF_ACCEPT;
}
- return ipv6_conntrack_in(hooknum, pskb, in, out, okfn);
+ return ipv6_conntrack_in(hooknum, skb, in, out, okfn);
}
static struct nf_hook_ops ipv6_conntrack_ops[] = {
@@ -305,9 +306,8 @@ static struct nf_hook_ops ipv6_conntrack_ops[] = {
#ifdef CONFIG_SYSCTL
static ctl_table nf_ct_ipv6_sysctl_table[] = {
{
- .ctl_name = NET_NF_CONNTRACK_FRAG6_TIMEOUT,
.procname = "nf_conntrack_frag6_timeout",
- .data = &nf_ct_frag6_timeout,
+ .data = &nf_frags_ctl.timeout,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
@@ -315,7 +315,7 @@ static ctl_table nf_ct_ipv6_sysctl_table[] = {
{
.ctl_name = NET_NF_CONNTRACK_FRAG6_LOW_THRESH,
.procname = "nf_conntrack_frag6_low_thresh",
- .data = &nf_ct_frag6_low_thresh,
+ .data = &nf_frags_ctl.low_thresh,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec,
@@ -323,7 +323,7 @@ static ctl_table nf_ct_ipv6_sysctl_table[] = {
{
.ctl_name = NET_NF_CONNTRACK_FRAG6_HIGH_THRESH,
.procname = "nf_conntrack_frag6_high_thresh",
- .data = &nf_ct_frag6_high_thresh,
+ .data = &nf_frags_ctl.high_thresh,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec,
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
index fbdc66920de4..fd9123f3dc04 100644
--- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
@@ -260,7 +260,6 @@ static int icmpv6_nlattr_to_tuple(struct nlattr *tb[],
static struct ctl_table_header *icmpv6_sysctl_header;
static struct ctl_table icmpv6_sysctl_table[] = {
{
- .ctl_name = NET_NF_CONNTRACK_ICMPV6_TIMEOUT,
.procname = "nf_conntrack_icmpv6_timeout",
.data = &nf_ct_icmpv6_timeout,
.maxlen = sizeof(unsigned int),
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index 25442a8c1ba8..e170c67c47a5 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -31,6 +31,7 @@
#include <net/sock.h>
#include <net/snmp.h>
+#include <net/inet_frag.h>
#include <net/ipv6.h>
#include <net/protocol.h>
@@ -48,10 +49,6 @@
#define NF_CT_FRAG6_LOW_THRESH 196608 /* == 192*1024 */
#define NF_CT_FRAG6_TIMEOUT IPV6_FRAG_TIMEOUT
-unsigned int nf_ct_frag6_high_thresh __read_mostly = 256*1024;
-unsigned int nf_ct_frag6_low_thresh __read_mostly = 192*1024;
-unsigned long nf_ct_frag6_timeout __read_mostly = IPV6_FRAG_TIMEOUT;
-
struct nf_ct_frag6_skb_cb
{
struct inet6_skb_parm h;
@@ -63,51 +60,24 @@ struct nf_ct_frag6_skb_cb
struct nf_ct_frag6_queue
{
- struct hlist_node list;
- struct list_head lru_list; /* lru list member */
+ struct inet_frag_queue q;
__be32 id; /* fragment id */
struct in6_addr saddr;
struct in6_addr daddr;
- spinlock_t lock;
- atomic_t refcnt;
- struct timer_list timer; /* expire timer */
- struct sk_buff *fragments;
- int len;
- int meat;
- ktime_t stamp;
unsigned int csum;
- __u8 last_in; /* has first/last segment arrived? */
-#define COMPLETE 4
-#define FIRST_IN 2
-#define LAST_IN 1
__u16 nhoffset;
};
-/* Hash table. */
-
-#define FRAG6Q_HASHSZ 64
-
-static struct hlist_head nf_ct_frag6_hash[FRAG6Q_HASHSZ];
-static DEFINE_RWLOCK(nf_ct_frag6_lock);
-static u32 nf_ct_frag6_hash_rnd;
-static LIST_HEAD(nf_ct_frag6_lru_list);
-int nf_ct_frag6_nqueues = 0;
-
-static __inline__ void __fq_unlink(struct nf_ct_frag6_queue *fq)
-{
- hlist_del(&fq->list);
- list_del(&fq->lru_list);
- nf_ct_frag6_nqueues--;
-}
+struct inet_frags_ctl nf_frags_ctl __read_mostly = {
+ .high_thresh = 256 * 1024,
+ .low_thresh = 192 * 1024,
+ .timeout = IPV6_FRAG_TIMEOUT,
+ .secret_interval = 10 * 60 * HZ,
+};
-static __inline__ void fq_unlink(struct nf_ct_frag6_queue *fq)
-{
- write_lock(&nf_ct_frag6_lock);
- __fq_unlink(fq);
- write_unlock(&nf_ct_frag6_lock);
-}
+static struct inet_frags nf_frags;
static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr,
struct in6_addr *daddr)
@@ -120,7 +90,7 @@ static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr,
a += JHASH_GOLDEN_RATIO;
b += JHASH_GOLDEN_RATIO;
- c += nf_ct_frag6_hash_rnd;
+ c += nf_frags.rnd;
__jhash_mix(a, b, c);
a += (__force u32)saddr->s6_addr32[3];
@@ -133,100 +103,38 @@ static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr,
c += (__force u32)id;
__jhash_mix(a, b, c);
- return c & (FRAG6Q_HASHSZ - 1);
+ return c & (INETFRAGS_HASHSZ - 1);
}
-static struct timer_list nf_ct_frag6_secret_timer;
-int nf_ct_frag6_secret_interval = 10 * 60 * HZ;
-
-static void nf_ct_frag6_secret_rebuild(unsigned long dummy)
+static unsigned int nf_hashfn(struct inet_frag_queue *q)
{
- unsigned long now = jiffies;
- int i;
-
- write_lock(&nf_ct_frag6_lock);
- get_random_bytes(&nf_ct_frag6_hash_rnd, sizeof(u32));
- for (i = 0; i < FRAG6Q_HASHSZ; i++) {
- struct nf_ct_frag6_queue *q;
- struct hlist_node *p, *n;
-
- hlist_for_each_entry_safe(q, p, n, &nf_ct_frag6_hash[i], list) {
- unsigned int hval = ip6qhashfn(q->id,
- &q->saddr,
- &q->daddr);
- if (hval != i) {
- hlist_del(&q->list);
- /* Relink to new hash chain. */
- hlist_add_head(&q->list,
- &nf_ct_frag6_hash[hval]);
- }
- }
- }
- write_unlock(&nf_ct_frag6_lock);
+ struct nf_ct_frag6_queue *nq;
- mod_timer(&nf_ct_frag6_secret_timer, now + nf_ct_frag6_secret_interval);
+ nq = container_of(q, struct nf_ct_frag6_queue, q);
+ return ip6qhashfn(nq->id, &nq->saddr, &nq->daddr);
}
-atomic_t nf_ct_frag6_mem = ATOMIC_INIT(0);
-
-/* Memory Tracking Functions. */
-static inline void frag_kfree_skb(struct sk_buff *skb, unsigned int *work)
+static void nf_skb_free(struct sk_buff *skb)
{
- if (work)
- *work -= skb->truesize;
- atomic_sub(skb->truesize, &nf_ct_frag6_mem);
if (NFCT_FRAG6_CB(skb)->orig)
kfree_skb(NFCT_FRAG6_CB(skb)->orig);
-
- kfree_skb(skb);
}
-static inline void frag_free_queue(struct nf_ct_frag6_queue *fq,
- unsigned int *work)
+/* Memory Tracking Functions. */
+static inline void frag_kfree_skb(struct sk_buff *skb, unsigned int *work)
{
if (work)
- *work -= sizeof(struct nf_ct_frag6_queue);
- atomic_sub(sizeof(struct nf_ct_frag6_queue), &nf_ct_frag6_mem);
- kfree(fq);
-}
-
-static inline struct nf_ct_frag6_queue *frag_alloc_queue(void)
-{
- struct nf_ct_frag6_queue *fq = kmalloc(sizeof(struct nf_ct_frag6_queue), GFP_ATOMIC);
-
- if (!fq)
- return NULL;
- atomic_add(sizeof(struct nf_ct_frag6_queue), &nf_ct_frag6_mem);
- return fq;
+ *work -= skb->truesize;
+ atomic_sub(skb->truesize, &nf_frags.mem);
+ nf_skb_free(skb);
+ kfree_skb(skb);
}
/* Destruction primitives. */
-/* Complete destruction of fq. */
-static void nf_ct_frag6_destroy(struct nf_ct_frag6_queue *fq,
- unsigned int *work)
+static __inline__ void fq_put(struct nf_ct_frag6_queue *fq)
{
- struct sk_buff *fp;
-
- BUG_TRAP(fq->last_in&COMPLETE);
- BUG_TRAP(del_timer(&fq->timer) == 0);
-
- /* Release all fragment data. */
- fp = fq->fragments;
- while (fp) {
- struct sk_buff *xp = fp->next;
-
- frag_kfree_skb(fp, work);
- fp = xp;
- }
-
- frag_free_queue(fq, work);
-}
-
-static __inline__ void fq_put(struct nf_ct_frag6_queue *fq, unsigned int *work)
-{
- if (atomic_dec_and_test(&fq->refcnt))
- nf_ct_frag6_destroy(fq, work);
+ inet_frag_put(&fq->q, &nf_frags);
}
/* Kill fq entry. It is not destroyed immediately,
@@ -234,151 +142,58 @@ static __inline__ void fq_put(struct nf_ct_frag6_queue *fq, unsigned int *work)
*/
static __inline__ void fq_kill(struct nf_ct_frag6_queue *fq)
{
- if (del_timer(&fq->timer))
- atomic_dec(&fq->refcnt);
-
- if (!(fq->last_in & COMPLETE)) {
- fq_unlink(fq);
- atomic_dec(&fq->refcnt);
- fq->last_in |= COMPLETE;
- }
+ inet_frag_kill(&fq->q, &nf_frags);
}
static void nf_ct_frag6_evictor(void)
{
- struct nf_ct_frag6_queue *fq;
- struct list_head *tmp;
- unsigned int work;
-
- work = atomic_read(&nf_ct_frag6_mem);
- if (work <= nf_ct_frag6_low_thresh)
- return;
-
- work -= nf_ct_frag6_low_thresh;
- while (work > 0) {
- read_lock(&nf_ct_frag6_lock);
- if (list_empty(&nf_ct_frag6_lru_list)) {
- read_unlock(&nf_ct_frag6_lock);
- return;
- }
- tmp = nf_ct_frag6_lru_list.next;
- BUG_ON(tmp == NULL);
- fq = list_entry(tmp, struct nf_ct_frag6_queue, lru_list);
- atomic_inc(&fq->refcnt);
- read_unlock(&nf_ct_frag6_lock);
-
- spin_lock(&fq->lock);
- if (!(fq->last_in&COMPLETE))
- fq_kill(fq);
- spin_unlock(&fq->lock);
-
- fq_put(fq, &work);
- }
+ inet_frag_evictor(&nf_frags);
}
static void nf_ct_frag6_expire(unsigned long data)
{
- struct nf_ct_frag6_queue *fq = (struct nf_ct_frag6_queue *) data;
+ struct nf_ct_frag6_queue *fq;
+
+ fq = container_of((struct inet_frag_queue *)data,
+ struct nf_ct_frag6_queue, q);
- spin_lock(&fq->lock);
+ spin_lock(&fq->q.lock);
- if (fq->last_in & COMPLETE)
+ if (fq->q.last_in & COMPLETE)
goto out;
fq_kill(fq);
out:
- spin_unlock(&fq->lock);
- fq_put(fq, NULL);
+ spin_unlock(&fq->q.lock);
+ fq_put(fq);
}
/* Creation primitives. */
-static struct nf_ct_frag6_queue *nf_ct_frag6_intern(unsigned int hash,
- struct nf_ct_frag6_queue *fq_in)
+static __inline__ struct nf_ct_frag6_queue *
+fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst)
{
- struct nf_ct_frag6_queue *fq;
-#ifdef CONFIG_SMP
- struct hlist_node *n;
-#endif
-
- write_lock(&nf_ct_frag6_lock);
-#ifdef CONFIG_SMP
- hlist_for_each_entry(fq, n, &nf_ct_frag6_hash[hash], list) {
- if (fq->id == fq_in->id &&
- ipv6_addr_equal(&fq_in->saddr, &fq->saddr) &&
- ipv6_addr_equal(&fq_in->daddr, &fq->daddr)) {
- atomic_inc(&fq->refcnt);
- write_unlock(&nf_ct_frag6_lock);
- fq_in->last_in |= COMPLETE;
- fq_put(fq_in, NULL);
- return fq;
- }
- }
-#endif
- fq = fq_in;
-
- if (!mod_timer(&fq->timer, jiffies + nf_ct_frag6_timeout))
- atomic_inc(&fq->refcnt);
-
- atomic_inc(&fq->refcnt);
- hlist_add_head(&fq->list, &nf_ct_frag6_hash[hash]);
- INIT_LIST_HEAD(&fq->lru_list);
- list_add_tail(&fq->lru_list, &nf_ct_frag6_lru_list);
- nf_ct_frag6_nqueues++;
- write_unlock(&nf_ct_frag6_lock);
- return fq;
-}
+ struct inet_frag_queue *q;
+ struct ip6_create_arg arg;
+ unsigned int hash;
+ arg.id = id;
+ arg.src = src;
+ arg.dst = dst;
+ hash = ip6qhashfn(id, src, dst);
-static struct nf_ct_frag6_queue *
-nf_ct_frag6_create(unsigned int hash, __be32 id, struct in6_addr *src, struct in6_addr *dst)
-{
- struct nf_ct_frag6_queue *fq;
-
- if ((fq = frag_alloc_queue()) == NULL) {
- pr_debug("Can't alloc new queue\n");
+ q = inet_frag_find(&nf_frags, &arg, hash);
+ if (q == NULL)
goto oom;
- }
-
- memset(fq, 0, sizeof(struct nf_ct_frag6_queue));
-
- fq->id = id;
- ipv6_addr_copy(&fq->saddr, src);
- ipv6_addr_copy(&fq->daddr, dst);
- setup_timer(&fq->timer, nf_ct_frag6_expire, (unsigned long)fq);
- spin_lock_init(&fq->lock);
- atomic_set(&fq->refcnt, 1);
-
- return nf_ct_frag6_intern(hash, fq);
+ return container_of(q, struct nf_ct_frag6_queue, q);
oom:
+ pr_debug("Can't alloc new queue\n");
return NULL;
}
-static __inline__ struct nf_ct_frag6_queue *
-fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst)
-{
- struct nf_ct_frag6_queue *fq;
- struct hlist_node *n;
- unsigned int hash = ip6qhashfn(id, src, dst);
-
- read_lock(&nf_ct_frag6_lock);
- hlist_for_each_entry(fq, n, &nf_ct_frag6_hash[hash], list) {
- if (fq->id == id &&
- ipv6_addr_equal(src, &fq->saddr) &&
- ipv6_addr_equal(dst, &fq->daddr)) {
- atomic_inc(&fq->refcnt);
- read_unlock(&nf_ct_frag6_lock);
- return fq;
- }
- }
- read_unlock(&nf_ct_frag6_lock);
-
- return nf_ct_frag6_create(hash, id, src, dst);
-}
-
static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
struct frag_hdr *fhdr, int nhoff)
@@ -386,7 +201,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
struct sk_buff *prev, *next;
int offset, end;
- if (fq->last_in & COMPLETE) {
+ if (fq->q.last_in & COMPLETE) {
pr_debug("Allready completed\n");
goto err;
}
@@ -412,13 +227,13 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
/* If we already have some bits beyond end
* or have different end, the segment is corrupted.
*/
- if (end < fq->len ||
- ((fq->last_in & LAST_IN) && end != fq->len)) {
+ if (end < fq->q.len ||
+ ((fq->q.last_in & LAST_IN) && end != fq->q.len)) {
pr_debug("already received last fragment\n");
goto err;
}
- fq->last_in |= LAST_IN;
- fq->len = end;
+ fq->q.last_in |= LAST_IN;
+ fq->q.len = end;
} else {
/* Check if the fragment is rounded to 8 bytes.
* Required by the RFC.
@@ -430,13 +245,13 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
pr_debug("end of fragment not rounded to 8 bytes.\n");
return -1;
}
- if (end > fq->len) {
+ if (end > fq->q.len) {
/* Some bits beyond end -> corruption. */
- if (fq->last_in & LAST_IN) {
+ if (fq->q.last_in & LAST_IN) {
pr_debug("last packet already reached.\n");
goto err;
}
- fq->len = end;
+ fq->q.len = end;
}
}
@@ -458,7 +273,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
* this fragment, right?
*/
prev = NULL;
- for (next = fq->fragments; next != NULL; next = next->next) {
+ for (next = fq->q.fragments; next != NULL; next = next->next) {
if (NFCT_FRAG6_CB(next)->offset >= offset)
break; /* bingo! */
prev = next;
@@ -503,7 +318,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
/* next fragment */
NFCT_FRAG6_CB(next)->offset += i;
- fq->meat -= i;
+ fq->q.meat -= i;
if (next->ip_summed != CHECKSUM_UNNECESSARY)
next->ip_summed = CHECKSUM_NONE;
break;
@@ -518,9 +333,9 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
if (prev)
prev->next = next;
else
- fq->fragments = next;
+ fq->q.fragments = next;
- fq->meat -= free_it->len;
+ fq->q.meat -= free_it->len;
frag_kfree_skb(free_it, NULL);
}
}
@@ -532,23 +347,23 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
if (prev)
prev->next = skb;
else
- fq->fragments = skb;
+ fq->q.fragments = skb;
skb->dev = NULL;
- fq->stamp = skb->tstamp;
- fq->meat += skb->len;
- atomic_add(skb->truesize, &nf_ct_frag6_mem);
+ fq->q.stamp = skb->tstamp;
+ fq->q.meat += skb->len;
+ atomic_add(skb->truesize, &nf_frags.mem);
/* The first fragment.
* nhoffset is obtained from the first fragment, of course.
*/
if (offset == 0) {
fq->nhoffset = nhoff;
- fq->last_in |= FIRST_IN;
+ fq->q.last_in |= FIRST_IN;
}
- write_lock(&nf_ct_frag6_lock);
- list_move_tail(&fq->lru_list, &nf_ct_frag6_lru_list);
- write_unlock(&nf_ct_frag6_lock);
+ write_lock(&nf_frags.lock);
+ list_move_tail(&fq->q.lru_list, &nf_frags.lru_list);
+ write_unlock(&nf_frags.lock);
return 0;
err:
@@ -567,7 +382,7 @@ err:
static struct sk_buff *
nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev)
{
- struct sk_buff *fp, *op, *head = fq->fragments;
+ struct sk_buff *fp, *op, *head = fq->q.fragments;
int payload_len;
fq_kill(fq);
@@ -577,7 +392,7 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev)
/* Unfragmented part is taken from the first segment. */
payload_len = ((head->data - skb_network_header(head)) -
- sizeof(struct ipv6hdr) + fq->len -
+ sizeof(struct ipv6hdr) + fq->q.len -
sizeof(struct frag_hdr));
if (payload_len > IPV6_MAXPLEN) {
pr_debug("payload len is too large.\n");
@@ -614,7 +429,7 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev)
clone->ip_summed = head->ip_summed;
NFCT_FRAG6_CB(clone)->orig = NULL;
- atomic_add(clone->truesize, &nf_ct_frag6_mem);
+ atomic_add(clone->truesize, &nf_frags.mem);
}
/* We have to remove fragment header from datagram and to relocate
@@ -628,7 +443,7 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev)
skb_shinfo(head)->frag_list = head->next;
skb_reset_transport_header(head);
skb_push(head, head->data - skb_network_header(head));
- atomic_sub(head->truesize, &nf_ct_frag6_mem);
+ atomic_sub(head->truesize, &nf_frags.mem);
for (fp=head->next; fp; fp = fp->next) {
head->data_len += fp->len;
@@ -638,12 +453,12 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev)
else if (head->ip_summed == CHECKSUM_COMPLETE)
head->csum = csum_add(head->csum, fp->csum);
head->truesize += fp->truesize;
- atomic_sub(fp->truesize, &nf_ct_frag6_mem);
+ atomic_sub(fp->truesize, &nf_frags.mem);
}
head->next = NULL;
head->dev = dev;
- head->tstamp = fq->stamp;
+ head->tstamp = fq->q.stamp;
ipv6_hdr(head)->payload_len = htons(payload_len);
/* Yes, and fold redundant checksum back. 8) */
@@ -652,7 +467,7 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev)
skb_network_header_len(head),
head->csum);
- fq->fragments = NULL;
+ fq->q.fragments = NULL;
/* all original skbs are linked into the NFCT_FRAG6_CB(head).orig */
fp = skb_shinfo(head)->frag_list;
@@ -788,7 +603,7 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb)
goto ret_orig;
}
- if (atomic_read(&nf_ct_frag6_mem) > nf_ct_frag6_high_thresh)
+ if (atomic_read(&nf_frags.mem) > nf_frags_ctl.high_thresh)
nf_ct_frag6_evictor();
fq = fq_find(fhdr->identification, &hdr->saddr, &hdr->daddr);
@@ -797,23 +612,23 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb)
goto ret_orig;
}
- spin_lock(&fq->lock);
+ spin_lock(&fq->q.lock);
if (nf_ct_frag6_queue(fq, clone, fhdr, nhoff) < 0) {
- spin_unlock(&fq->lock);
+ spin_unlock(&fq->q.lock);
pr_debug("Can't insert skb to queue\n");
- fq_put(fq, NULL);
+ fq_put(fq);
goto ret_orig;
}
- if (fq->last_in == (FIRST_IN|LAST_IN) && fq->meat == fq->len) {
+ if (fq->q.last_in == (FIRST_IN|LAST_IN) && fq->q.meat == fq->q.len) {
ret_skb = nf_ct_frag6_reasm(fq, dev);
if (ret_skb == NULL)
pr_debug("Can't reassemble fragmented packets\n");
}
- spin_unlock(&fq->lock);
+ spin_unlock(&fq->q.lock);
- fq_put(fq, NULL);
+ fq_put(fq);
return ret_skb;
ret_orig:
@@ -859,20 +674,23 @@ int nf_ct_frag6_kfree_frags(struct sk_buff *skb)
int nf_ct_frag6_init(void)
{
- nf_ct_frag6_hash_rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^
- (jiffies ^ (jiffies >> 6)));
-
- setup_timer(&nf_ct_frag6_secret_timer, nf_ct_frag6_secret_rebuild, 0);
- nf_ct_frag6_secret_timer.expires = jiffies
- + nf_ct_frag6_secret_interval;
- add_timer(&nf_ct_frag6_secret_timer);
+ nf_frags.ctl = &nf_frags_ctl;
+ nf_frags.hashfn = nf_hashfn;
+ nf_frags.constructor = ip6_frag_init;
+ nf_frags.destructor = NULL;
+ nf_frags.skb_free = nf_skb_free;
+ nf_frags.qsize = sizeof(struct nf_ct_frag6_queue);
+ nf_frags.match = ip6_frag_match;
+ nf_frags.frag_expire = nf_ct_frag6_expire;
+ inet_frags_init(&nf_frags);
return 0;
}
void nf_ct_frag6_cleanup(void)
{
- del_timer(&nf_ct_frag6_secret_timer);
- nf_ct_frag6_low_thresh = 0;
+ inet_frags_fini(&nf_frags);
+
+ nf_frags_ctl.low_thresh = 0;
nf_ct_frag6_evictor();
}
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index db945018579e..8631ed7fe8a9 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -32,29 +32,18 @@
static struct proc_dir_entry *proc_net_devsnmp6;
-static int fold_prot_inuse(struct proto *proto)
-{
- int res = 0;
- int cpu;
-
- for_each_possible_cpu(cpu)
- res += proto->stats[cpu].inuse;
-
- return res;
-}
-
static int sockstat6_seq_show(struct seq_file *seq, void *v)
{
seq_printf(seq, "TCP6: inuse %d\n",
- fold_prot_inuse(&tcpv6_prot));
+ sock_prot_inuse(&tcpv6_prot));
seq_printf(seq, "UDP6: inuse %d\n",
- fold_prot_inuse(&udpv6_prot));
+ sock_prot_inuse(&udpv6_prot));
seq_printf(seq, "UDPLITE6: inuse %d\n",
- fold_prot_inuse(&udplitev6_prot));
+ sock_prot_inuse(&udplitev6_prot));
seq_printf(seq, "RAW6: inuse %d\n",
- fold_prot_inuse(&rawv6_prot));
+ sock_prot_inuse(&rawv6_prot));
seq_printf(seq, "FRAG6: inuse %d memory %d\n",
- ip6_frag_nqueues, atomic_read(&ip6_frag_mem));
+ ip6_frag_nqueues(), ip6_frag_mem());
return 0;
}
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index ca24ef19cd8f..807260d03586 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -1144,6 +1144,8 @@ static int rawv6_init_sk(struct sock *sk)
return(0);
}
+DEFINE_PROTO_INUSE(rawv6)
+
struct proto rawv6_prot = {
.name = "RAWv6",
.owner = THIS_MODULE,
@@ -1166,6 +1168,7 @@ struct proto rawv6_prot = {
.compat_setsockopt = compat_rawv6_setsockopt,
.compat_getsockopt = compat_rawv6_getsockopt,
#endif
+ REF_PROTO_INUSE(rawv6)
};
#ifdef CONFIG_PROC_FS
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index 31601c993541..76c88a93b9b5 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -42,6 +42,7 @@
#include <linux/icmpv6.h>
#include <linux/random.h>
#include <linux/jhash.h>
+#include <linux/skbuff.h>
#include <net/sock.h>
#include <net/snmp.h>
@@ -53,11 +54,7 @@
#include <net/rawv6.h>
#include <net/ndisc.h>
#include <net/addrconf.h>
-
-int sysctl_ip6frag_high_thresh __read_mostly = 256*1024;
-int sysctl_ip6frag_low_thresh __read_mostly = 192*1024;
-
-int sysctl_ip6frag_time __read_mostly = IPV6_FRAG_TIMEOUT;
+#include <net/inet_frag.h>
struct ip6frag_skb_cb
{
@@ -74,53 +71,39 @@ struct ip6frag_skb_cb
struct frag_queue
{
- struct hlist_node list;
- struct list_head lru_list; /* lru list member */
+ struct inet_frag_queue q;
__be32 id; /* fragment id */
struct in6_addr saddr;
struct in6_addr daddr;
- spinlock_t lock;
- atomic_t refcnt;
- struct timer_list timer; /* expire timer */
- struct sk_buff *fragments;
- int len;
- int meat;
int iif;
- ktime_t stamp;
unsigned int csum;
- __u8 last_in; /* has first/last segment arrived? */
-#define COMPLETE 4
-#define FIRST_IN 2
-#define LAST_IN 1
__u16 nhoffset;
};
-/* Hash table. */
-
-#define IP6Q_HASHSZ 64
+struct inet_frags_ctl ip6_frags_ctl __read_mostly = {
+ .high_thresh = 256 * 1024,
+ .low_thresh = 192 * 1024,
+ .timeout = IPV6_FRAG_TIMEOUT,
+ .secret_interval = 10 * 60 * HZ,
+};
-static struct hlist_head ip6_frag_hash[IP6Q_HASHSZ];
-static DEFINE_RWLOCK(ip6_frag_lock);
-static u32 ip6_frag_hash_rnd;
-static LIST_HEAD(ip6_frag_lru_list);
-int ip6_frag_nqueues = 0;
+static struct inet_frags ip6_frags;
-static __inline__ void __fq_unlink(struct frag_queue *fq)
+int ip6_frag_nqueues(void)
{
- hlist_del(&fq->list);
- list_del(&fq->lru_list);
- ip6_frag_nqueues--;
+ return ip6_frags.nqueues;
}
-static __inline__ void fq_unlink(struct frag_queue *fq)
+int ip6_frag_mem(void)
{
- write_lock(&ip6_frag_lock);
- __fq_unlink(fq);
- write_unlock(&ip6_frag_lock);
+ return atomic_read(&ip6_frags.mem);
}
+static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev,
+ struct net_device *dev);
+
/*
* callers should be careful not to use the hash value outside the ipfrag_lock
* as doing so could race with ipfrag_hash_rnd being recalculated.
@@ -136,7 +119,7 @@ static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr,
a += JHASH_GOLDEN_RATIO;
b += JHASH_GOLDEN_RATIO;
- c += ip6_frag_hash_rnd;
+ c += ip6_frags.rnd;
__jhash_mix(a, b, c);
a += (__force u32)saddr->s6_addr32[3];
@@ -149,98 +132,54 @@ static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr,
c += (__force u32)id;
__jhash_mix(a, b, c);
- return c & (IP6Q_HASHSZ - 1);
+ return c & (INETFRAGS_HASHSZ - 1);
}
-static struct timer_list ip6_frag_secret_timer;
-int sysctl_ip6frag_secret_interval __read_mostly = 10 * 60 * HZ;
-
-static void ip6_frag_secret_rebuild(unsigned long dummy)
+static unsigned int ip6_hashfn(struct inet_frag_queue *q)
{
- unsigned long now = jiffies;
- int i;
-
- write_lock(&ip6_frag_lock);
- get_random_bytes(&ip6_frag_hash_rnd, sizeof(u32));
- for (i = 0; i < IP6Q_HASHSZ; i++) {
- struct frag_queue *q;
- struct hlist_node *p, *n;
-
- hlist_for_each_entry_safe(q, p, n, &ip6_frag_hash[i], list) {
- unsigned int hval = ip6qhashfn(q->id,
- &q->saddr,
- &q->daddr);
-
- if (hval != i) {
- hlist_del(&q->list);
+ struct frag_queue *fq;
- /* Relink to new hash chain. */
- hlist_add_head(&q->list,
- &ip6_frag_hash[hval]);
+ fq = container_of(q, struct frag_queue, q);
+ return ip6qhashfn(fq->id, &fq->saddr, &fq->daddr);
+}
- }
- }
- }
- write_unlock(&ip6_frag_lock);
+int ip6_frag_match(struct inet_frag_queue *q, void *a)
+{
+ struct frag_queue *fq;
+ struct ip6_create_arg *arg = a;
- mod_timer(&ip6_frag_secret_timer, now + sysctl_ip6frag_secret_interval);
+ fq = container_of(q, struct frag_queue, q);
+ return (fq->id == arg->id &&
+ ipv6_addr_equal(&fq->saddr, arg->src) &&
+ ipv6_addr_equal(&fq->daddr, arg->dst));
}
-
-atomic_t ip6_frag_mem = ATOMIC_INIT(0);
+EXPORT_SYMBOL(ip6_frag_match);
/* Memory Tracking Functions. */
static inline void frag_kfree_skb(struct sk_buff *skb, int *work)
{
if (work)
*work -= skb->truesize;
- atomic_sub(skb->truesize, &ip6_frag_mem);
+ atomic_sub(skb->truesize, &ip6_frags.mem);
kfree_skb(skb);
}
-static inline void frag_free_queue(struct frag_queue *fq, int *work)
+void ip6_frag_init(struct inet_frag_queue *q, void *a)
{
- if (work)
- *work -= sizeof(struct frag_queue);
- atomic_sub(sizeof(struct frag_queue), &ip6_frag_mem);
- kfree(fq);
-}
+ struct frag_queue *fq = container_of(q, struct frag_queue, q);
+ struct ip6_create_arg *arg = a;
-static inline struct frag_queue *frag_alloc_queue(void)
-{
- struct frag_queue *fq = kzalloc(sizeof(struct frag_queue), GFP_ATOMIC);
-
- if(!fq)
- return NULL;
- atomic_add(sizeof(struct frag_queue), &ip6_frag_mem);
- return fq;
+ fq->id = arg->id;
+ ipv6_addr_copy(&fq->saddr, arg->src);
+ ipv6_addr_copy(&fq->daddr, arg->dst);
}
+EXPORT_SYMBOL(ip6_frag_init);
/* Destruction primitives. */
-/* Complete destruction of fq. */
-static void ip6_frag_destroy(struct frag_queue *fq, int *work)
+static __inline__ void fq_put(struct frag_queue *fq)
{
- struct sk_buff *fp;
-
- BUG_TRAP(fq->last_in&COMPLETE);
- BUG_TRAP(del_timer(&fq->timer) == 0);
-
- /* Release all fragment data. */
- fp = fq->fragments;
- while (fp) {
- struct sk_buff *xp = fp->next;
-
- frag_kfree_skb(fp, work);
- fp = xp;
- }
-
- frag_free_queue(fq, work);
-}
-
-static __inline__ void fq_put(struct frag_queue *fq, int *work)
-{
- if (atomic_dec_and_test(&fq->refcnt))
- ip6_frag_destroy(fq, work);
+ inet_frag_put(&fq->q, &ip6_frags);
}
/* Kill fq entry. It is not destroyed immediately,
@@ -248,55 +187,28 @@ static __inline__ void fq_put(struct frag_queue *fq, int *work)
*/
static __inline__ void fq_kill(struct frag_queue *fq)
{
- if (del_timer(&fq->timer))
- atomic_dec(&fq->refcnt);
-
- if (!(fq->last_in & COMPLETE)) {
- fq_unlink(fq);
- atomic_dec(&fq->refcnt);
- fq->last_in |= COMPLETE;
- }
+ inet_frag_kill(&fq->q, &ip6_frags);
}
static void ip6_evictor(struct inet6_dev *idev)
{
- struct frag_queue *fq;
- struct list_head *tmp;
- int work;
-
- work = atomic_read(&ip6_frag_mem) - sysctl_ip6frag_low_thresh;
- if (work <= 0)
- return;
-
- while(work > 0) {
- read_lock(&ip6_frag_lock);
- if (list_empty(&ip6_frag_lru_list)) {
- read_unlock(&ip6_frag_lock);
- return;
- }
- tmp = ip6_frag_lru_list.next;
- fq = list_entry(tmp, struct frag_queue, lru_list);
- atomic_inc(&fq->refcnt);
- read_unlock(&ip6_frag_lock);
-
- spin_lock(&fq->lock);
- if (!(fq->last_in&COMPLETE))
- fq_kill(fq);
- spin_unlock(&fq->lock);
-
- fq_put(fq, &work);
- IP6_INC_STATS_BH(idev, IPSTATS_MIB_REASMFAILS);
- }
+ int evicted;
+
+ evicted = inet_frag_evictor(&ip6_frags);
+ if (evicted)
+ IP6_ADD_STATS_BH(idev, IPSTATS_MIB_REASMFAILS, evicted);
}
static void ip6_frag_expire(unsigned long data)
{
- struct frag_queue *fq = (struct frag_queue *) data;
+ struct frag_queue *fq;
struct net_device *dev = NULL;
- spin_lock(&fq->lock);
+ fq = container_of((struct inet_frag_queue *)data, struct frag_queue, q);
+
+ spin_lock(&fq->q.lock);
- if (fq->last_in & COMPLETE)
+ if (fq->q.last_in & COMPLETE)
goto out;
fq_kill(fq);
@@ -311,7 +223,7 @@ static void ip6_frag_expire(unsigned long data)
rcu_read_unlock();
/* Don't send error if the first segment did not arrive. */
- if (!(fq->last_in&FIRST_IN) || !fq->fragments)
+ if (!(fq->q.last_in&FIRST_IN) || !fq->q.fragments)
goto out;
/*
@@ -319,114 +231,47 @@ static void ip6_frag_expire(unsigned long data)
segment was received. And do not use fq->dev
pointer directly, device might already disappeared.
*/
- fq->fragments->dev = dev;
- icmpv6_send(fq->fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0, dev);
+ fq->q.fragments->dev = dev;
+ icmpv6_send(fq->q.fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0, dev);
out:
if (dev)
dev_put(dev);
- spin_unlock(&fq->lock);
- fq_put(fq, NULL);
+ spin_unlock(&fq->q.lock);
+ fq_put(fq);
}
-/* Creation primitives. */
-
-
-static struct frag_queue *ip6_frag_intern(struct frag_queue *fq_in)
+static __inline__ struct frag_queue *
+fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst,
+ struct inet6_dev *idev)
{
- struct frag_queue *fq;
+ struct inet_frag_queue *q;
+ struct ip6_create_arg arg;
unsigned int hash;
-#ifdef CONFIG_SMP
- struct hlist_node *n;
-#endif
-
- write_lock(&ip6_frag_lock);
- hash = ip6qhashfn(fq_in->id, &fq_in->saddr, &fq_in->daddr);
-#ifdef CONFIG_SMP
- hlist_for_each_entry(fq, n, &ip6_frag_hash[hash], list) {
- if (fq->id == fq_in->id &&
- ipv6_addr_equal(&fq_in->saddr, &fq->saddr) &&
- ipv6_addr_equal(&fq_in->daddr, &fq->daddr)) {
- atomic_inc(&fq->refcnt);
- write_unlock(&ip6_frag_lock);
- fq_in->last_in |= COMPLETE;
- fq_put(fq_in, NULL);
- return fq;
- }
- }
-#endif
- fq = fq_in;
-
- if (!mod_timer(&fq->timer, jiffies + sysctl_ip6frag_time))
- atomic_inc(&fq->refcnt);
-
- atomic_inc(&fq->refcnt);
- hlist_add_head(&fq->list, &ip6_frag_hash[hash]);
- INIT_LIST_HEAD(&fq->lru_list);
- list_add_tail(&fq->lru_list, &ip6_frag_lru_list);
- ip6_frag_nqueues++;
- write_unlock(&ip6_frag_lock);
- return fq;
-}
-
-static struct frag_queue *
-ip6_frag_create(__be32 id, struct in6_addr *src, struct in6_addr *dst,
- struct inet6_dev *idev)
-{
- struct frag_queue *fq;
+ arg.id = id;
+ arg.src = src;
+ arg.dst = dst;
+ hash = ip6qhashfn(id, src, dst);
- if ((fq = frag_alloc_queue()) == NULL)
+ q = inet_frag_find(&ip6_frags, &arg, hash);
+ if (q == NULL)
goto oom;
- fq->id = id;
- ipv6_addr_copy(&fq->saddr, src);
- ipv6_addr_copy(&fq->daddr, dst);
-
- init_timer(&fq->timer);
- fq->timer.function = ip6_frag_expire;
- fq->timer.data = (long) fq;
- spin_lock_init(&fq->lock);
- atomic_set(&fq->refcnt, 1);
-
- return ip6_frag_intern(fq);
+ return container_of(q, struct frag_queue, q);
oom:
IP6_INC_STATS_BH(idev, IPSTATS_MIB_REASMFAILS);
return NULL;
}
-static __inline__ struct frag_queue *
-fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst,
- struct inet6_dev *idev)
-{
- struct frag_queue *fq;
- struct hlist_node *n;
- unsigned int hash;
-
- read_lock(&ip6_frag_lock);
- hash = ip6qhashfn(id, src, dst);
- hlist_for_each_entry(fq, n, &ip6_frag_hash[hash], list) {
- if (fq->id == id &&
- ipv6_addr_equal(src, &fq->saddr) &&
- ipv6_addr_equal(dst, &fq->daddr)) {
- atomic_inc(&fq->refcnt);
- read_unlock(&ip6_frag_lock);
- return fq;
- }
- }
- read_unlock(&ip6_frag_lock);
-
- return ip6_frag_create(id, src, dst, idev);
-}
-
-
-static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
+static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
struct frag_hdr *fhdr, int nhoff)
{
struct sk_buff *prev, *next;
+ struct net_device *dev;
int offset, end;
- if (fq->last_in & COMPLETE)
+ if (fq->q.last_in & COMPLETE)
goto err;
offset = ntohs(fhdr->frag_off) & ~0x7;
@@ -439,7 +284,7 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
((u8 *)&fhdr->frag_off -
skb_network_header(skb)));
- return;
+ return -1;
}
if (skb->ip_summed == CHECKSUM_COMPLETE) {
@@ -454,11 +299,11 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
/* If we already have some bits beyond end
* or have different end, the segment is corrupted.
*/
- if (end < fq->len ||
- ((fq->last_in & LAST_IN) && end != fq->len))
+ if (end < fq->q.len ||
+ ((fq->q.last_in & LAST_IN) && end != fq->q.len))
goto err;
- fq->last_in |= LAST_IN;
- fq->len = end;
+ fq->q.last_in |= LAST_IN;
+ fq->q.len = end;
} else {
/* Check if the fragment is rounded to 8 bytes.
* Required by the RFC.
@@ -471,13 +316,13 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
IPSTATS_MIB_INHDRERRORS);
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
offsetof(struct ipv6hdr, payload_len));
- return;
+ return -1;
}
- if (end > fq->len) {
+ if (end > fq->q.len) {
/* Some bits beyond end -> corruption. */
- if (fq->last_in & LAST_IN)
+ if (fq->q.last_in & LAST_IN)
goto err;
- fq->len = end;
+ fq->q.len = end;
}
}
@@ -496,7 +341,7 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
* this fragment, right?
*/
prev = NULL;
- for(next = fq->fragments; next != NULL; next = next->next) {
+ for(next = fq->q.fragments; next != NULL; next = next->next) {
if (FRAG6_CB(next)->offset >= offset)
break; /* bingo! */
prev = next;
@@ -533,7 +378,7 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
if (!pskb_pull(next, i))
goto err;
FRAG6_CB(next)->offset += i; /* next fragment */
- fq->meat -= i;
+ fq->q.meat -= i;
if (next->ip_summed != CHECKSUM_UNNECESSARY)
next->ip_summed = CHECKSUM_NONE;
break;
@@ -548,9 +393,9 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
if (prev)
prev->next = next;
else
- fq->fragments = next;
+ fq->q.fragments = next;
- fq->meat -= free_it->len;
+ fq->q.meat -= free_it->len;
frag_kfree_skb(free_it, NULL);
}
}
@@ -562,30 +407,37 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
if (prev)
prev->next = skb;
else
- fq->fragments = skb;
+ fq->q.fragments = skb;
- if (skb->dev)
- fq->iif = skb->dev->ifindex;
- skb->dev = NULL;
- fq->stamp = skb->tstamp;
- fq->meat += skb->len;
- atomic_add(skb->truesize, &ip6_frag_mem);
+ dev = skb->dev;
+ if (dev) {
+ fq->iif = dev->ifindex;
+ skb->dev = NULL;
+ }
+ fq->q.stamp = skb->tstamp;
+ fq->q.meat += skb->len;
+ atomic_add(skb->truesize, &ip6_frags.mem);
/* The first fragment.
* nhoffset is obtained from the first fragment, of course.
*/
if (offset == 0) {
fq->nhoffset = nhoff;
- fq->last_in |= FIRST_IN;
+ fq->q.last_in |= FIRST_IN;
}
- write_lock(&ip6_frag_lock);
- list_move_tail(&fq->lru_list, &ip6_frag_lru_list);
- write_unlock(&ip6_frag_lock);
- return;
+
+ if (fq->q.last_in == (FIRST_IN | LAST_IN) && fq->q.meat == fq->q.len)
+ return ip6_frag_reasm(fq, prev, dev);
+
+ write_lock(&ip6_frags.lock);
+ list_move_tail(&fq->q.lru_list, &ip6_frags.lru_list);
+ write_unlock(&ip6_frags.lock);
+ return -1;
err:
IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMFAILS);
kfree_skb(skb);
+ return -1;
}
/*
@@ -597,21 +449,39 @@ err:
* queue is eligible for reassembly i.e. it is not COMPLETE,
* the last and the first frames arrived and all the bits are here.
*/
-static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
+static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev,
struct net_device *dev)
{
- struct sk_buff *fp, *head = fq->fragments;
+ struct sk_buff *fp, *head = fq->q.fragments;
int payload_len;
unsigned int nhoff;
fq_kill(fq);
+ /* Make the one we just received the head. */
+ if (prev) {
+ head = prev->next;
+ fp = skb_clone(head, GFP_ATOMIC);
+
+ if (!fp)
+ goto out_oom;
+
+ fp->next = head->next;
+ prev->next = fp;
+
+ skb_morph(head, fq->q.fragments);
+ head->next = fq->q.fragments->next;
+
+ kfree_skb(fq->q.fragments);
+ fq->q.fragments = head;
+ }
+
BUG_TRAP(head != NULL);
BUG_TRAP(FRAG6_CB(head)->offset == 0);
/* Unfragmented part is taken from the first segment. */
payload_len = ((head->data - skb_network_header(head)) -
- sizeof(struct ipv6hdr) + fq->len -
+ sizeof(struct ipv6hdr) + fq->q.len -
sizeof(struct frag_hdr));
if (payload_len > IPV6_MAXPLEN)
goto out_oversize;
@@ -640,7 +510,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
head->len -= clone->len;
clone->csum = 0;
clone->ip_summed = head->ip_summed;
- atomic_add(clone->truesize, &ip6_frag_mem);
+ atomic_add(clone->truesize, &ip6_frags.mem);
}
/* We have to remove fragment header from datagram and to relocate
@@ -655,7 +525,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
skb_shinfo(head)->frag_list = head->next;
skb_reset_transport_header(head);
skb_push(head, head->data - skb_network_header(head));
- atomic_sub(head->truesize, &ip6_frag_mem);
+ atomic_sub(head->truesize, &ip6_frags.mem);
for (fp=head->next; fp; fp = fp->next) {
head->data_len += fp->len;
@@ -665,17 +535,15 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
else if (head->ip_summed == CHECKSUM_COMPLETE)
head->csum = csum_add(head->csum, fp->csum);
head->truesize += fp->truesize;
- atomic_sub(fp->truesize, &ip6_frag_mem);
+ atomic_sub(fp->truesize, &ip6_frags.mem);
}
head->next = NULL;
head->dev = dev;
- head->tstamp = fq->stamp;
+ head->tstamp = fq->q.stamp;
ipv6_hdr(head)->payload_len = htons(payload_len);
IP6CB(head)->nhoff = nhoff;
- *skb_in = head;
-
/* Yes, and fold redundant checksum back. 8) */
if (head->ip_summed == CHECKSUM_COMPLETE)
head->csum = csum_partial(skb_network_header(head),
@@ -685,7 +553,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
rcu_read_lock();
IP6_INC_STATS_BH(__in6_dev_get(dev), IPSTATS_MIB_REASMOKS);
rcu_read_unlock();
- fq->fragments = NULL;
+ fq->q.fragments = NULL;
return 1;
out_oversize:
@@ -702,10 +570,8 @@ out_fail:
return -1;
}
-static int ipv6_frag_rcv(struct sk_buff **skbp)
+static int ipv6_frag_rcv(struct sk_buff *skb)
{
- struct sk_buff *skb = *skbp;
- struct net_device *dev = skb->dev;
struct frag_hdr *fhdr;
struct frag_queue *fq;
struct ipv6hdr *hdr = ipv6_hdr(skb);
@@ -739,23 +605,19 @@ static int ipv6_frag_rcv(struct sk_buff **skbp)
return 1;
}
- if (atomic_read(&ip6_frag_mem) > sysctl_ip6frag_high_thresh)
+ if (atomic_read(&ip6_frags.mem) > ip6_frags_ctl.high_thresh)
ip6_evictor(ip6_dst_idev(skb->dst));
if ((fq = fq_find(fhdr->identification, &hdr->saddr, &hdr->daddr,
ip6_dst_idev(skb->dst))) != NULL) {
- int ret = -1;
+ int ret;
- spin_lock(&fq->lock);
+ spin_lock(&fq->q.lock);
- ip6_frag_queue(fq, skb, fhdr, IP6CB(skb)->nhoff);
+ ret = ip6_frag_queue(fq, skb, fhdr, IP6CB(skb)->nhoff);
- if (fq->last_in == (FIRST_IN|LAST_IN) &&
- fq->meat == fq->len)
- ret = ip6_frag_reasm(fq, skbp, dev);
-
- spin_unlock(&fq->lock);
- fq_put(fq, NULL);
+ spin_unlock(&fq->q.lock);
+ fq_put(fq);
return ret;
}
@@ -775,11 +637,13 @@ void __init ipv6_frag_init(void)
if (inet6_add_protocol(&frag_protocol, IPPROTO_FRAGMENT) < 0)
printk(KERN_ERR "ipv6_frag_init: Could not register protocol\n");
- ip6_frag_hash_rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^
- (jiffies ^ (jiffies >> 6)));
-
- init_timer(&ip6_frag_secret_timer);
- ip6_frag_secret_timer.function = ip6_frag_secret_rebuild;
- ip6_frag_secret_timer.expires = jiffies + sysctl_ip6frag_secret_interval;
- add_timer(&ip6_frag_secret_timer);
+ ip6_frags.ctl = &ip6_frags_ctl;
+ ip6_frags.hashfn = ip6_hashfn;
+ ip6_frags.constructor = ip6_frag_init;
+ ip6_frags.destructor = NULL;
+ ip6_frags.skb_free = NULL;
+ ip6_frags.qsize = sizeof(struct frag_queue);
+ ip6_frags.match = ip6_frag_match;
+ ip6_frags.frag_expire = ip6_frag_expire;
+ inet_frags_init(&ip6_frags);
}
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 6ff19f9eb9ee..6ecb5e6fae2e 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -38,12 +38,8 @@
#include <linux/in6.h>
#include <linux/init.h>
#include <linux/if_arp.h>
-
-#ifdef CONFIG_PROC_FS
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
-#endif
-
#include <net/net_namespace.h>
#include <net/snmp.h>
#include <net/ipv6.h>
@@ -548,12 +544,8 @@ restart:
rt = rt6_device_match(rt, fl->oif, flags);
BACKTRACK(&fl->fl6_src);
out:
- dst_hold(&rt->u.dst);
+ dst_use(&rt->u.dst, jiffies);
read_unlock_bh(&table->tb6_lock);
-
- rt->u.dst.lastuse = jiffies;
- rt->u.dst.__use++;
-
return rt;
}
@@ -663,7 +655,7 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, struct in6_addr *d
return rt;
}
-static struct rt6_info *ip6_pol_route_input(struct fib6_table *table,
+static struct rt6_info *ip6_pol_route(struct fib6_table *table, int oif,
struct flowi *fl, int flags)
{
struct fib6_node *fn;
@@ -682,7 +674,7 @@ restart_2:
fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src);
restart:
- rt = rt6_select(fn, fl->iif, strict | reachable);
+ rt = rt6_select(fn, oif, strict | reachable);
BACKTRACK(&fl->fl6_src);
if (rt == &ip6_null_entry ||
rt->rt6i_flags & RTF_CACHE)
@@ -735,6 +727,12 @@ out2:
return rt;
}
+static struct rt6_info *ip6_pol_route_input(struct fib6_table *table,
+ struct flowi *fl, int flags)
+{
+ return ip6_pol_route(table, fl->iif, fl, flags);
+}
+
void ip6_route_input(struct sk_buff *skb)
{
struct ipv6hdr *iph = ipv6_hdr(skb);
@@ -761,72 +759,7 @@ void ip6_route_input(struct sk_buff *skb)
static struct rt6_info *ip6_pol_route_output(struct fib6_table *table,
struct flowi *fl, int flags)
{
- struct fib6_node *fn;
- struct rt6_info *rt, *nrt;
- int strict = 0;
- int attempts = 3;
- int err;
- int reachable = ipv6_devconf.forwarding ? 0 : RT6_LOOKUP_F_REACHABLE;
-
- strict |= flags & RT6_LOOKUP_F_IFACE;
-
-relookup:
- read_lock_bh(&table->tb6_lock);
-
-restart_2:
- fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src);
-
-restart:
- rt = rt6_select(fn, fl->oif, strict | reachable);
- BACKTRACK(&fl->fl6_src);
- if (rt == &ip6_null_entry ||
- rt->rt6i_flags & RTF_CACHE)
- goto out;
-
- dst_hold(&rt->u.dst);
- read_unlock_bh(&table->tb6_lock);
-
- if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP))
- nrt = rt6_alloc_cow(rt, &fl->fl6_dst, &fl->fl6_src);
- else {
-#if CLONE_OFFLINK_ROUTE
- nrt = rt6_alloc_clone(rt, &fl->fl6_dst);
-#else
- goto out2;
-#endif
- }
-
- dst_release(&rt->u.dst);
- rt = nrt ? : &ip6_null_entry;
-
- dst_hold(&rt->u.dst);
- if (nrt) {
- err = ip6_ins_rt(nrt);
- if (!err)
- goto out2;
- }
-
- if (--attempts <= 0)
- goto out2;
-
- /*
- * Race condition! In the gap, when table->tb6_lock was
- * released someone could insert this route. Relookup.
- */
- dst_release(&rt->u.dst);
- goto relookup;
-
-out:
- if (reachable) {
- reachable = 0;
- goto restart_2;
- }
- dst_hold(&rt->u.dst);
- read_unlock_bh(&table->tb6_lock);
-out2:
- rt->u.dst.lastuse = jiffies;
- rt->u.dst.__use++;
- return rt;
+ return ip6_pol_route(table, fl->oif, fl, flags);
}
struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl)
@@ -2347,71 +2280,50 @@ struct rt6_proc_arg
static int rt6_info_route(struct rt6_info *rt, void *p_arg)
{
- struct rt6_proc_arg *arg = (struct rt6_proc_arg *) p_arg;
+ struct seq_file *m = p_arg;
- if (arg->skip < arg->offset / RT6_INFO_LEN) {
- arg->skip++;
- return 0;
- }
-
- if (arg->len >= arg->length)
- return 0;
-
- arg->len += sprintf(arg->buffer + arg->len,
- NIP6_SEQFMT " %02x ",
- NIP6(rt->rt6i_dst.addr),
- rt->rt6i_dst.plen);
+ seq_printf(m, NIP6_SEQFMT " %02x ", NIP6(rt->rt6i_dst.addr),
+ rt->rt6i_dst.plen);
#ifdef CONFIG_IPV6_SUBTREES
- arg->len += sprintf(arg->buffer + arg->len,
- NIP6_SEQFMT " %02x ",
- NIP6(rt->rt6i_src.addr),
- rt->rt6i_src.plen);
+ seq_printf(m, NIP6_SEQFMT " %02x ", NIP6(rt->rt6i_src.addr),
+ rt->rt6i_src.plen);
#else
- arg->len += sprintf(arg->buffer + arg->len,
- "00000000000000000000000000000000 00 ");
+ seq_puts(m, "00000000000000000000000000000000 00 ");
#endif
if (rt->rt6i_nexthop) {
- arg->len += sprintf(arg->buffer + arg->len,
- NIP6_SEQFMT,
- NIP6(*((struct in6_addr *)rt->rt6i_nexthop->primary_key)));
+ seq_printf(m, NIP6_SEQFMT,
+ NIP6(*((struct in6_addr *)rt->rt6i_nexthop->primary_key)));
} else {
- arg->len += sprintf(arg->buffer + arg->len,
- "00000000000000000000000000000000");
+ seq_puts(m, "00000000000000000000000000000000");
}
- arg->len += sprintf(arg->buffer + arg->len,
- " %08x %08x %08x %08x %8s\n",
- rt->rt6i_metric, atomic_read(&rt->u.dst.__refcnt),
- rt->u.dst.__use, rt->rt6i_flags,
- rt->rt6i_dev ? rt->rt6i_dev->name : "");
+ seq_printf(m, " %08x %08x %08x %08x %8s\n",
+ rt->rt6i_metric, atomic_read(&rt->u.dst.__refcnt),
+ rt->u.dst.__use, rt->rt6i_flags,
+ rt->rt6i_dev ? rt->rt6i_dev->name : "");
return 0;
}
-static int rt6_proc_info(char *buffer, char **start, off_t offset, int length)
+static int ipv6_route_show(struct seq_file *m, void *v)
{
- struct rt6_proc_arg arg = {
- .buffer = buffer,
- .offset = offset,
- .length = length,
- };
-
- fib6_clean_all(rt6_info_route, 0, &arg);
-
- *start = buffer;
- if (offset)
- *start += offset % RT6_INFO_LEN;
-
- arg.len -= offset % RT6_INFO_LEN;
-
- if (arg.len > length)
- arg.len = length;
- if (arg.len < 0)
- arg.len = 0;
+ fib6_clean_all(rt6_info_route, 0, m);
+ return 0;
+}
- return arg.len;
+static int ipv6_route_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, ipv6_route_show, NULL);
}
+static const struct file_operations ipv6_route_proc_fops = {
+ .owner = THIS_MODULE,
+ .open = ipv6_route_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
static int rt6_stats_seq_show(struct seq_file *seq, void *v)
{
seq_printf(seq, "%04x %04x %04x %04x %04x %04x %04x\n",
@@ -2456,7 +2368,6 @@ int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write, struct file * filp,
ctl_table ipv6_route_table[] = {
{
- .ctl_name = NET_IPV6_ROUTE_FLUSH,
.procname = "flush",
.data = &flush_delay,
.maxlen = sizeof(int),
@@ -2549,22 +2460,14 @@ ctl_table ipv6_route_table[] = {
void __init ip6_route_init(void)
{
-#ifdef CONFIG_PROC_FS
- struct proc_dir_entry *p;
-#endif
ip6_dst_ops.kmem_cachep =
kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0,
SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops.kmem_cachep;
fib6_init();
-#ifdef CONFIG_PROC_FS
- p = proc_net_create(&init_net, "ipv6_route", 0, rt6_proc_info);
- if (p)
- p->owner = THIS_MODULE;
-
+ proc_net_fops_create(&init_net, "ipv6_route", 0, &ipv6_route_proc_fops);
proc_net_fops_create(&init_net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops);
-#endif
#ifdef CONFIG_XFRM
xfrm6_init();
#endif
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 466657a9a8bd..71433d29d884 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -430,7 +430,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
struct rtable *rt; /* Route to the other host */
struct net_device *tdev; /* Device to other host */
struct iphdr *iph; /* Our new IP header */
- int max_headroom; /* The extra header space needed */
+ unsigned int max_headroom; /* The extra header space needed */
__be32 dst = tiph->daddr;
int mtu;
struct in6_addr *addr6;
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c
index 3fb44277207b..68bb2548e469 100644
--- a/net/ipv6/sysctl_net_ipv6.c
+++ b/net/ipv6/sysctl_net_ipv6.c
@@ -12,6 +12,7 @@
#include <net/ndisc.h>
#include <net/ipv6.h>
#include <net/addrconf.h>
+#include <net/inet_frag.h>
#ifdef CONFIG_SYSCTL
@@ -41,7 +42,7 @@ static ctl_table ipv6_table[] = {
{
.ctl_name = NET_IPV6_IP6FRAG_HIGH_THRESH,
.procname = "ip6frag_high_thresh",
- .data = &sysctl_ip6frag_high_thresh,
+ .data = &ip6_frags_ctl.high_thresh,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec
@@ -49,7 +50,7 @@ static ctl_table ipv6_table[] = {
{
.ctl_name = NET_IPV6_IP6FRAG_LOW_THRESH,
.procname = "ip6frag_low_thresh",
- .data = &sysctl_ip6frag_low_thresh,
+ .data = &ip6_frags_ctl.low_thresh,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec
@@ -57,7 +58,7 @@ static ctl_table ipv6_table[] = {
{
.ctl_name = NET_IPV6_IP6FRAG_TIME,
.procname = "ip6frag_time",
- .data = &sysctl_ip6frag_time,
+ .data = &ip6_frags_ctl.timeout,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
@@ -66,7 +67,7 @@ static ctl_table ipv6_table[] = {
{
.ctl_name = NET_IPV6_IP6FRAG_SECRET_INTERVAL,
.procname = "ip6frag_secret_interval",
- .data = &sysctl_ip6frag_secret_interval,
+ .data = &ip6_frags_ctl.secret_interval,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index a07b59c528f3..3aad861975a0 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -59,6 +59,7 @@
#include <net/snmp.h>
#include <net/dsfield.h>
#include <net/timewait_sock.h>
+#include <net/netdma.h>
#include <asm/uaccess.h>
@@ -560,16 +561,16 @@ static int tcp_v6_md5_do_add(struct sock *sk, struct in6_addr *peer,
char *newkey, u8 newkeylen)
{
/* Add key to the list */
- struct tcp6_md5sig_key *key;
+ struct tcp_md5sig_key *key;
struct tcp_sock *tp = tcp_sk(sk);
struct tcp6_md5sig_key *keys;
- key = (struct tcp6_md5sig_key*) tcp_v6_md5_do_lookup(sk, peer);
+ key = tcp_v6_md5_do_lookup(sk, peer);
if (key) {
/* modify existing entry - just update that one */
- kfree(key->base.key);
- key->base.key = newkey;
- key->base.keylen = newkeylen;
+ kfree(key->key);
+ key->key = newkey;
+ key->keylen = newkeylen;
} else {
/* reallocate new list if current one is full. */
if (!tp->md5sig_info) {
@@ -757,6 +758,8 @@ static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
bp->len = htonl(tcplen);
bp->protocol = htonl(protocol);
+ sg_init_table(sg, 4);
+
sg_set_buf(&sg[block++], bp, sizeof(*bp));
nbytes += sizeof(*bp);
@@ -778,6 +781,8 @@ static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
sg_set_buf(&sg[block++], key->key, key->keylen);
nbytes += key->keylen;
+ sg_mark_end(&sg[block - 1]);
+
/* Now store the hash into the packet */
err = crypto_hash_init(desc);
if (err) {
@@ -1668,9 +1673,8 @@ ipv6_pktoptions:
return 0;
}
-static int tcp_v6_rcv(struct sk_buff **pskb)
+static int tcp_v6_rcv(struct sk_buff *skb)
{
- struct sk_buff *skb = *pskb;
struct tcphdr *th;
struct sock *sk;
int ret;
@@ -1729,6 +1733,8 @@ process:
if (!sock_owned_by_user(sk)) {
#ifdef CONFIG_NET_DMA
struct tcp_sock *tp = tcp_sk(sk);
+ if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list)
+ tp->ucopy.dma_chan = get_softnet_dma();
if (tp->ucopy.dma_chan)
ret = tcp_v6_do_rcv(sk, skb);
else
@@ -2101,6 +2107,8 @@ void tcp6_proc_exit(void)
}
#endif
+DEFINE_PROTO_INUSE(tcpv6)
+
struct proto tcpv6_prot = {
.name = "TCPv6",
.owner = THIS_MODULE,
@@ -2135,6 +2143,7 @@ struct proto tcpv6_prot = {
.compat_setsockopt = compat_tcp_setsockopt,
.compat_getsockopt = compat_tcp_getsockopt,
#endif
+ REF_PROTO_INUSE(tcpv6)
};
static struct inet6_protocol tcpv6_protocol = {
diff --git a/net/ipv6/tunnel6.c b/net/ipv6/tunnel6.c
index 23e2809878ae..6323921b40be 100644
--- a/net/ipv6/tunnel6.c
+++ b/net/ipv6/tunnel6.c
@@ -87,9 +87,8 @@ int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family)
EXPORT_SYMBOL(xfrm6_tunnel_deregister);
-static int tunnel6_rcv(struct sk_buff **pskb)
+static int tunnel6_rcv(struct sk_buff *skb)
{
- struct sk_buff *skb = *pskb;
struct xfrm6_tunnel *handler;
if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
@@ -106,9 +105,8 @@ drop:
return 0;
}
-static int tunnel46_rcv(struct sk_buff **pskb)
+static int tunnel46_rcv(struct sk_buff *skb)
{
- struct sk_buff *skb = *pskb;
struct xfrm6_tunnel *handler;
if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 82ff26dd4470..ee1cc3f8599f 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -205,12 +205,11 @@ out:
return err;
csum_copy_err:
+ UDP6_INC_STATS_USER(UDP_MIB_INERRORS, is_udplite);
skb_kill_datagram(sk, skb, flags);
- if (flags & MSG_DONTWAIT) {
- UDP6_INC_STATS_USER(UDP_MIB_INERRORS, is_udplite);
+ if (flags & MSG_DONTWAIT)
return -EAGAIN;
- }
goto try_again;
}
@@ -405,10 +404,9 @@ static inline int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh,
return 0;
}
-int __udp6_lib_rcv(struct sk_buff **pskb, struct hlist_head udptable[],
+int __udp6_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
int proto)
{
- struct sk_buff *skb = *pskb;
struct sock *sk;
struct udphdr *uh;
struct net_device *dev = skb->dev;
@@ -494,9 +492,9 @@ discard:
return 0;
}
-static __inline__ int udpv6_rcv(struct sk_buff **pskb)
+static __inline__ int udpv6_rcv(struct sk_buff *skb)
{
- return __udp6_lib_rcv(pskb, udp_hash, IPPROTO_UDP);
+ return __udp6_lib_rcv(skb, udp_hash, IPPROTO_UDP);
}
/*
@@ -972,6 +970,8 @@ void udp6_proc_exit(void) {
/* ------------------------------------------------------------------------ */
+DEFINE_PROTO_INUSE(udpv6)
+
struct proto udpv6_prot = {
.name = "UDPv6",
.owner = THIS_MODULE,
@@ -993,6 +993,7 @@ struct proto udpv6_prot = {
.compat_setsockopt = compat_udpv6_setsockopt,
.compat_getsockopt = compat_udpv6_getsockopt,
#endif
+ REF_PROTO_INUSE(udpv6)
};
static struct inet_protosw udpv6_protosw = {
diff --git a/net/ipv6/udp_impl.h b/net/ipv6/udp_impl.h
index 6e252f318f7c..2d3fda601232 100644
--- a/net/ipv6/udp_impl.h
+++ b/net/ipv6/udp_impl.h
@@ -6,7 +6,7 @@
#include <net/addrconf.h>
#include <net/inet_common.h>
-extern int __udp6_lib_rcv(struct sk_buff **, struct hlist_head [], int );
+extern int __udp6_lib_rcv(struct sk_buff *, struct hlist_head [], int );
extern void __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *,
int , int , int , __be32 , struct hlist_head []);
diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c
index f54016a55004..5a0379f71415 100644
--- a/net/ipv6/udplite.c
+++ b/net/ipv6/udplite.c
@@ -17,9 +17,9 @@
DEFINE_SNMP_STAT(struct udp_mib, udplite_stats_in6) __read_mostly;
-static int udplitev6_rcv(struct sk_buff **pskb)
+static int udplitev6_rcv(struct sk_buff *skb)
{
- return __udp6_lib_rcv(pskb, udplite_hash, IPPROTO_UDPLITE);
+ return __udp6_lib_rcv(skb, udplite_hash, IPPROTO_UDPLITE);
}
static void udplitev6_err(struct sk_buff *skb,
@@ -40,6 +40,8 @@ static int udplite_v6_get_port(struct sock *sk, unsigned short snum)
return udplite_get_port(sk, snum, ipv6_rcv_saddr_equal);
}
+DEFINE_PROTO_INUSE(udplitev6)
+
struct proto udplitev6_prot = {
.name = "UDPLITEv6",
.owner = THIS_MODULE,
@@ -62,6 +64,7 @@ struct proto udplitev6_prot = {
.compat_setsockopt = compat_udpv6_setsockopt,
.compat_getsockopt = compat_udpv6_getsockopt,
#endif
+ REF_PROTO_INUSE(udplitev6)
};
static struct inet_protosw udplite6_protosw = {
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index c858537cec4b..515783707e86 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -16,7 +16,7 @@
#include <net/ipv6.h>
#include <net/xfrm.h>
-int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi)
+int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
{
int err;
__be32 seq;
@@ -24,11 +24,9 @@ int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi)
struct xfrm_state *x;
int xfrm_nr = 0;
int decaps = 0;
- int nexthdr;
unsigned int nhoff;
nhoff = IP6CB(skb)->nhoff;
- nexthdr = skb_network_header(skb)[nhoff];
seq = 0;
if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0)
@@ -41,7 +39,7 @@ int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi)
goto drop;
x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi,
- nexthdr != IPPROTO_IPIP ? nexthdr : IPPROTO_IPV6, AF_INET6);
+ nexthdr, AF_INET6);
if (x == NULL)
goto drop;
spin_lock(&x->lock);
@@ -70,10 +68,10 @@ int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi)
xfrm_vec[xfrm_nr++] = x;
- if (x->mode->input(x, skb))
+ if (x->outer_mode->input(x, skb))
goto drop;
- if (x->props.mode == XFRM_MODE_TUNNEL) { /* XXX */
+ if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
decaps = 1;
break;
}
@@ -99,7 +97,6 @@ int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi)
memcpy(skb->sp->xvec + skb->sp->len, xfrm_vec,
xfrm_nr * sizeof(xfrm_vec[0]));
skb->sp->len += xfrm_nr;
- skb->ip_summed = CHECKSUM_NONE;
nf_reset(skb);
@@ -133,9 +130,10 @@ drop:
EXPORT_SYMBOL(xfrm6_rcv_spi);
-int xfrm6_rcv(struct sk_buff **pskb)
+int xfrm6_rcv(struct sk_buff *skb)
{
- return xfrm6_rcv_spi(*pskb, 0);
+ return xfrm6_rcv_spi(skb, skb_network_header(skb)[IP6CB(skb)->nhoff],
+ 0);
}
EXPORT_SYMBOL(xfrm6_rcv);
diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c
index 13bb1e856764..2bfb4f05c14c 100644
--- a/net/ipv6/xfrm6_mode_beet.c
+++ b/net/ipv6/xfrm6_mode_beet.c
@@ -79,6 +79,7 @@ static struct xfrm_mode xfrm6_beet_mode = {
.output = xfrm6_beet_output,
.owner = THIS_MODULE,
.encap = XFRM_MODE_BEET,
+ .flags = XFRM_MODE_FLAG_TUNNEL,
};
static int __init xfrm6_beet_init(void)
diff --git a/net/ipv6/xfrm6_mode_ro.c b/net/ipv6/xfrm6_mode_ro.c
index 957ae36b6695..a7bc8c62317a 100644
--- a/net/ipv6/xfrm6_mode_ro.c
+++ b/net/ipv6/xfrm6_mode_ro.c
@@ -58,16 +58,7 @@ static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb)
return 0;
}
-/*
- * Do nothing about routing optimization header unlike IPsec.
- */
-static int xfrm6_ro_input(struct xfrm_state *x, struct sk_buff *skb)
-{
- return 0;
-}
-
static struct xfrm_mode xfrm6_ro_mode = {
- .input = xfrm6_ro_input,
.output = xfrm6_ro_output,
.owner = THIS_MODULE,
.encap = XFRM_MODE_ROUTEOPTIMIZATION,
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
index ea2283879112..fd84e2217274 100644
--- a/net/ipv6/xfrm6_mode_tunnel.c
+++ b/net/ipv6/xfrm6_mode_tunnel.c
@@ -118,6 +118,7 @@ static struct xfrm_mode xfrm6_tunnel_mode = {
.output = xfrm6_tunnel_output,
.owner = THIS_MODULE,
.encap = XFRM_MODE_TUNNEL,
+ .flags = XFRM_MODE_FLAG_TUNNEL,
};
static int __init xfrm6_tunnel_init(void)
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
index 4618c18e611d..656976760ad4 100644
--- a/net/ipv6/xfrm6_output.c
+++ b/net/ipv6/xfrm6_output.c
@@ -50,7 +50,7 @@ static inline int xfrm6_output_one(struct sk_buff *skb)
struct ipv6hdr *iph;
int err;
- if (x->props.mode == XFRM_MODE_TUNNEL) {
+ if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
err = xfrm6_tunnel_check_size(skb);
if (err)
goto error_nolock;
@@ -80,7 +80,7 @@ static int xfrm6_output_finish2(struct sk_buff *skb)
while (likely((err = xfrm6_output_one(skb)) == 0)) {
nf_reset(skb);
- err = nf_hook(PF_INET6, NF_IP6_LOCAL_OUT, &skb, NULL,
+ err = nf_hook(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL,
skb->dst->dev, dst_output);
if (unlikely(err != 1))
break;
@@ -88,7 +88,7 @@ static int xfrm6_output_finish2(struct sk_buff *skb)
if (!skb->dst->xfrm)
return dst_output(skb);
- err = nf_hook(PF_INET6, NF_IP6_POST_ROUTING, &skb, NULL,
+ err = nf_hook(PF_INET6, NF_IP6_POST_ROUTING, skb, NULL,
skb->dst->dev, xfrm6_output_finish2);
if (unlikely(err != 1))
break;
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 15aa4c58c315..82e27b80d07d 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -178,8 +178,7 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
__xfrm6_bundle_len_inc(&header_len, &nfheader_len, xfrm[i]);
trailer_len += xfrm[i]->props.trailer_len;
- if (xfrm[i]->props.mode == XFRM_MODE_TUNNEL ||
- xfrm[i]->props.mode == XFRM_MODE_ROUTEOPTIMIZATION) {
+ if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
unsigned short encap_family = xfrm[i]->props.family;
switch(encap_family) {
case AF_INET:
@@ -215,7 +214,6 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
i = 0;
for (; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) {
struct xfrm_dst *x = (struct xfrm_dst*)dst_prev;
- struct xfrm_state_afinfo *afinfo;
dst_prev->xfrm = xfrm[i++];
dst_prev->dev = rt->u.dst.dev;
@@ -232,18 +230,7 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
/* Copy neighbour for reachability confirmation */
dst_prev->neighbour = neigh_clone(rt->u.dst.neighbour);
dst_prev->input = rt->u.dst.input;
- /* XXX: When IPv4 is implemented as module and can be unloaded,
- * we should manage reference to xfrm4_output in afinfo->output.
- * Miyazawa
- */
- afinfo = xfrm_state_get_afinfo(dst_prev->xfrm->props.family);
- if (!afinfo) {
- dst = *dst_p;
- goto error;
- }
-
- dst_prev->output = afinfo->output;
- xfrm_state_put_afinfo(afinfo);
+ dst_prev->output = dst_prev->xfrm->outer_mode->afinfo->output;
/* Sheit... I remember I did this right. Apparently,
* it was magically lost, so this code needs audit */
x->u.rt6.rt6i_flags = rt0->rt6i_flags&(RTCF_BROADCAST|RTCF_MULTICAST|RTCF_LOCAL);
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
index cdadb4847469..b392bee396f1 100644
--- a/net/ipv6/xfrm6_state.c
+++ b/net/ipv6/xfrm6_state.c
@@ -93,7 +93,8 @@ __xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n)
/* Rule 4: select IPsec tunnel */
for (i = 0; i < n; i++) {
if (src[i] &&
- src[i]->props.mode == XFRM_MODE_TUNNEL) {
+ (src[i]->props.mode == XFRM_MODE_TUNNEL ||
+ src[i]->props.mode == XFRM_MODE_BEET)) {
dst[j++] = src[i];
src[i] = NULL;
}
@@ -146,7 +147,8 @@ __xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n)
/* Rule 3: select IPsec tunnel */
for (i = 0; i < n; i++) {
if (src[i] &&
- src[i]->mode == XFRM_MODE_TUNNEL) {
+ (src[i]->mode == XFRM_MODE_TUNNEL ||
+ src[i]->mode == XFRM_MODE_BEET)) {
dst[j++] = src[i];
src[i] = NULL;
}
@@ -168,6 +170,7 @@ __xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n)
static struct xfrm_state_afinfo xfrm6_state_afinfo = {
.family = AF_INET6,
+ .owner = THIS_MODULE,
.init_tempsel = __xfrm6_init_tempsel,
.tmpl_sort = __xfrm6_tmpl_sort,
.state_sort = __xfrm6_state_sort,
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index 3f8a3abde67e..fae90ff31087 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -248,7 +248,7 @@ static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
static int xfrm6_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
{
- return 0;
+ return skb_network_header(skb)[IP6CB(skb)->nhoff];
}
static int xfrm6_tunnel_rcv(struct sk_buff *skb)
@@ -257,7 +257,7 @@ static int xfrm6_tunnel_rcv(struct sk_buff *skb)
__be32 spi;
spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&iph->saddr);
- return xfrm6_rcv_spi(skb, spi) > 0 ? : 0;
+ return xfrm6_rcv_spi(skb, IPPROTO_IPV6, spi) > 0 ? : 0;
}
static int xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
index 29b063d43120..c76a9523091b 100644
--- a/net/ipx/af_ipx.c
+++ b/net/ipx/af_ipx.c
@@ -92,11 +92,6 @@ extern int ipxrtr_route_skb(struct sk_buff *skb);
extern struct ipx_route *ipxrtr_lookup(__be32 net);
extern int ipxrtr_ioctl(unsigned int cmd, void __user *arg);
-#undef IPX_REFCNT_DEBUG
-#ifdef IPX_REFCNT_DEBUG
-atomic_t ipx_sock_nr;
-#endif
-
struct ipx_interface *ipx_interfaces_head(void)
{
struct ipx_interface *rc = NULL;
@@ -151,14 +146,7 @@ static void ipx_destroy_socket(struct sock *sk)
{
ipx_remove_socket(sk);
skb_queue_purge(&sk->sk_receive_queue);
-#ifdef IPX_REFCNT_DEBUG
- atomic_dec(&ipx_sock_nr);
- printk(KERN_DEBUG "IPX socket %p released, %d are still alive\n", sk,
- atomic_read(&ipx_sock_nr));
- if (atomic_read(&sk->sk_refcnt) != 1)
- printk(KERN_DEBUG "Destruction sock ipx %p delayed, cnt=%d\n",
- sk, atomic_read(&sk->sk_refcnt));
-#endif
+ sk_refcnt_debug_dec(sk);
sock_put(sk);
}
@@ -1381,14 +1369,11 @@ static int ipx_create(struct net *net, struct socket *sock, int protocol)
goto out;
rc = -ENOMEM;
- sk = sk_alloc(net, PF_IPX, GFP_KERNEL, &ipx_proto, 1);
+ sk = sk_alloc(net, PF_IPX, GFP_KERNEL, &ipx_proto);
if (!sk)
goto out;
-#ifdef IPX_REFCNT_DEBUG
- atomic_inc(&ipx_sock_nr);
- printk(KERN_DEBUG "IPX socket %p created, now we have %d alive\n", sk,
- atomic_read(&ipx_sock_nr));
-#endif
+
+ sk_refcnt_debug_inc(sk);
sock_init_data(sock, sk);
sk->sk_no_check = 1; /* Checksum off by default */
sock->ops = &ipx_dgram_ops;
@@ -1409,6 +1394,7 @@ static int ipx_release(struct socket *sock)
sock_set_flag(sk, SOCK_DEAD);
sock->sk = NULL;
+ sk_refcnt_debug_release(sk);
ipx_destroy_socket(sk);
out:
return 0;
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
index 0328ae2654f4..48ce59a6e026 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -1078,7 +1078,7 @@ static int irda_create(struct net *net, struct socket *sock, int protocol)
}
/* Allocate networking socket */
- sk = sk_alloc(net, PF_IRDA, GFP_ATOMIC, &irda_proto, 1);
+ sk = sk_alloc(net, PF_IRDA, GFP_ATOMIC, &irda_proto);
if (sk == NULL)
return -ENOMEM;
diff --git a/net/irda/discovery.c b/net/irda/discovery.c
index af0cea721d2a..80c33f408e3f 100644
--- a/net/irda/discovery.c
+++ b/net/irda/discovery.c
@@ -202,7 +202,7 @@ void irlmp_expire_discoveries(hashbin_t *log, __u32 saddr, int force)
/* Drop the spinlock before calling the higher layers, as
* we can't guarantee they won't call us back and create a
* deadlock. We will work on our own private data, so we
- * don't care to be interupted. - Jean II */
+ * don't care to be interrupted. - Jean II */
spin_unlock_irqrestore(&log->hb_spinlock, flags);
if(buffer == NULL)
diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
index 3d241e415a2a..1120b150e211 100644
--- a/net/irda/ircomm/ircomm_tty.c
+++ b/net/irda/ircomm/ircomm_tty.c
@@ -77,7 +77,7 @@ static int ircomm_tty_read_proc(char *buf, char **start, off_t offset, int len,
#endif /* CONFIG_PROC_FS */
static struct tty_driver *driver;
-hashbin_t *ircomm_tty = NULL;
+static hashbin_t *ircomm_tty = NULL;
static const struct tty_operations ops = {
.open = ircomm_tty_open,
diff --git a/net/irda/ircomm/ircomm_tty_attach.c b/net/irda/ircomm/ircomm_tty_attach.c
index 824309dabfe9..b5a13882c927 100644
--- a/net/irda/ircomm/ircomm_tty_attach.c
+++ b/net/irda/ircomm/ircomm_tty_attach.c
@@ -381,18 +381,9 @@ static void ircomm_tty_discovery_indication(discinfo_t *discovery,
info.daddr = discovery->daddr;
info.saddr = discovery->saddr;
- /* FIXME. We have a locking problem on the hashbin here.
- * We probably need to use hashbin_find_next(), but we first
- * need to ensure that "line" is unique. - Jean II */
- self = (struct ircomm_tty_cb *) hashbin_get_first(ircomm_tty);
- while (self != NULL) {
- IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
-
- ircomm_tty_do_event(self, IRCOMM_TTY_DISCOVERY_INDICATION,
- NULL, &info);
-
- self = (struct ircomm_tty_cb *) hashbin_get_next(ircomm_tty);
- }
+ self = (struct ircomm_tty_cb *) priv;
+ ircomm_tty_do_event(self, IRCOMM_TTY_DISCOVERY_INDICATION,
+ NULL, &info);
}
/*
diff --git a/net/irda/iriap.c b/net/irda/iriap.c
index ee3889fa49ab..dc5e34a01620 100644
--- a/net/irda/iriap.c
+++ b/net/irda/iriap.c
@@ -18,7 +18,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
diff --git a/net/irda/iriap_event.c b/net/irda/iriap_event.c
index 99b18dc7a0b7..8fb9d7277ca8 100644
--- a/net/irda/iriap_event.c
+++ b/net/irda/iriap_event.c
@@ -18,7 +18,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
diff --git a/net/irda/irias_object.c b/net/irda/irias_object.c
index cf302457097b..cbcf04380f3a 100644
--- a/net/irda/irias_object.c
+++ b/net/irda/irias_object.c
@@ -16,7 +16,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
diff --git a/net/irda/irlan/irlan_client.c b/net/irda/irlan/irlan_client.c
index 87039c2fb6a2..fff52d57a200 100644
--- a/net/irda/irlan/irlan_client.c
+++ b/net/irda/irlan/irlan_client.c
@@ -20,7 +20,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
diff --git a/net/irda/irlan/irlan_client_event.c b/net/irda/irlan/irlan_client_event.c
index 843ab6fbb394..6afcee59e906 100644
--- a/net/irda/irlan/irlan_client_event.c
+++ b/net/irda/irlan/irlan_client_event.c
@@ -17,7 +17,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c
index f5778ef3ccc7..a4b56e25a917 100644
--- a/net/irda/irlan/irlan_common.c
+++ b/net/irda/irlan/irlan_common.c
@@ -17,7 +17,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
diff --git a/net/irda/irlan/irlan_eth.c b/net/irda/irlan/irlan_eth.c
index 340f04a36b02..7f9c8542e5fc 100644
--- a/net/irda/irlan/irlan_eth.c
+++ b/net/irda/irlan/irlan_eth.c
@@ -19,7 +19,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
diff --git a/net/irda/irlan/irlan_event.c b/net/irda/irlan/irlan_event.c
index 623e0fd16c19..a9750a801388 100644
--- a/net/irda/irlan/irlan_event.c
+++ b/net/irda/irlan/irlan_event.c
@@ -16,7 +16,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
diff --git a/net/irda/irlan/irlan_filter.c b/net/irda/irlan/irlan_filter.c
index e6346b88f934..4384be9a6888 100644
--- a/net/irda/irlan/irlan_filter.c
+++ b/net/irda/irlan/irlan_filter.c
@@ -16,7 +16,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
diff --git a/net/irda/irlan/irlan_provider.c b/net/irda/irlan/irlan_provider.c
index aac66434e473..13db942812e4 100644
--- a/net/irda/irlan/irlan_provider.c
+++ b/net/irda/irlan/irlan_provider.c
@@ -20,7 +20,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
diff --git a/net/irda/irlan/irlan_provider_event.c b/net/irda/irlan/irlan_provider_event.c
index ef401bd6ea00..10ece5a47522 100644
--- a/net/irda/irlan/irlan_provider_event.c
+++ b/net/irda/irlan/irlan_provider_event.c
@@ -16,7 +16,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
diff --git a/net/irda/irlap_event.c b/net/irda/irlap_event.c
index a8b8873aa263..4c33bf5c8354 100644
--- a/net/irda/irlap_event.c
+++ b/net/irda/irlap_event.c
@@ -19,7 +19,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
diff --git a/net/irda/irlap_frame.c b/net/irda/irlap_frame.c
index 77ac27e81161..4f3764546b2f 100644
--- a/net/irda/irlap_frame.c
+++ b/net/irda/irlap_frame.c
@@ -18,7 +18,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c
index 7db92ced2c02..cedff8068fbc 100644
--- a/net/irda/irlmp.c
+++ b/net/irda/irlmp.c
@@ -18,7 +18,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
diff --git a/net/irda/irlmp_event.c b/net/irda/irlmp_event.c
index 65ffa981510a..1bba87e78609 100644
--- a/net/irda/irlmp_event.c
+++ b/net/irda/irlmp_event.c
@@ -18,7 +18,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
diff --git a/net/irda/irlmp_frame.c b/net/irda/irlmp_frame.c
index 559302d3fe66..0a79d9aeb08c 100644
--- a/net/irda/irlmp_frame.c
+++ b/net/irda/irlmp_frame.c
@@ -18,7 +18,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
diff --git a/net/irda/irmod.c b/net/irda/irmod.c
index 8ba703da2797..01554b996b9b 100644
--- a/net/irda/irmod.c
+++ b/net/irda/irmod.c
@@ -17,7 +17,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
diff --git a/net/irda/irnet/irnet_ppp.c b/net/irda/irnet/irnet_ppp.c
index 2f9f8dce5a69..e0eab5927c4f 100644
--- a/net/irda/irnet/irnet_ppp.c
+++ b/net/irda/irnet/irnet_ppp.c
@@ -731,15 +731,25 @@ dev_irnet_ioctl(struct inode * inode,
/* Get termios */
case TCGETS:
DEBUG(FS_INFO, "Get termios.\n");
+#ifndef TCGETS2
if(kernel_termios_to_user_termios((struct termios __user *)argp, &ap->termios))
break;
+#else
+ if(kernel_termios_to_user_termios_1((struct termios __user *)argp, &ap->termios))
+ break;
+#endif
err = 0;
break;
/* Set termios */
case TCSETSF:
DEBUG(FS_INFO, "Set termios.\n");
+#ifndef TCGETS2
if(user_termios_to_kernel_termios(&ap->termios, (struct termios __user *)argp))
break;
+#else
+ if(user_termios_to_kernel_termios_1(&ap->termios, (struct termios __user *)argp))
+ break;
+#endif
err = 0;
break;
diff --git a/net/irda/irqueue.c b/net/irda/irqueue.c
index d058b467f9e4..40c28efaed95 100644
--- a/net/irda/irqueue.c
+++ b/net/irda/irqueue.c
@@ -28,7 +28,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
diff --git a/net/irda/irsysctl.c b/net/irda/irsysctl.c
index 957e04feb0f7..565cbf0421cd 100644
--- a/net/irda/irsysctl.c
+++ b/net/irda/irsysctl.c
@@ -17,7 +17,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
@@ -31,12 +31,6 @@
#include <net/irda/irda.h> /* irda_debug */
#include <net/irda/irias_object.h>
-#define NET_IRDA 412 /* Random number */
-enum { DISCOVERY=1, DEVNAME, DEBUG, FAST_POLL, DISCOVERY_SLOTS,
- DISCOVERY_TIMEOUT, SLOT_TIMEOUT, MAX_BAUD_RATE, MIN_TX_TURN_TIME,
- MAX_TX_DATA_SIZE, MAX_TX_WINDOW, MAX_NOREPLY_TIME, WARN_NOREPLY_TIME,
- LAP_KEEPALIVE_TIME };
-
extern int sysctl_discovery;
extern int sysctl_discovery_slots;
extern int sysctl_discovery_timeout;
@@ -94,7 +88,7 @@ static int do_devname(ctl_table *table, int write, struct file *filp,
/* One file */
static ctl_table irda_table[] = {
{
- .ctl_name = DISCOVERY,
+ .ctl_name = NET_IRDA_DISCOVERY,
.procname = "discovery",
.data = &sysctl_discovery,
.maxlen = sizeof(int),
@@ -102,7 +96,7 @@ static ctl_table irda_table[] = {
.proc_handler = &proc_dointvec
},
{
- .ctl_name = DEVNAME,
+ .ctl_name = NET_IRDA_DEVNAME,
.procname = "devname",
.data = sysctl_devname,
.maxlen = 65,
@@ -112,7 +106,7 @@ static ctl_table irda_table[] = {
},
#ifdef CONFIG_IRDA_DEBUG
{
- .ctl_name = DEBUG,
+ .ctl_name = NET_IRDA_DEBUG,
.procname = "debug",
.data = &irda_debug,
.maxlen = sizeof(int),
@@ -122,7 +116,7 @@ static ctl_table irda_table[] = {
#endif
#ifdef CONFIG_IRDA_FAST_RR
{
- .ctl_name = FAST_POLL,
+ .ctl_name = NET_IRDA_FAST_POLL,
.procname = "fast_poll_increase",
.data = &sysctl_fast_poll_increase,
.maxlen = sizeof(int),
@@ -131,7 +125,7 @@ static ctl_table irda_table[] = {
},
#endif
{
- .ctl_name = DISCOVERY_SLOTS,
+ .ctl_name = NET_IRDA_DISCOVERY_SLOTS,
.procname = "discovery_slots",
.data = &sysctl_discovery_slots,
.maxlen = sizeof(int),
@@ -142,7 +136,7 @@ static ctl_table irda_table[] = {
.extra2 = &max_discovery_slots
},
{
- .ctl_name = DISCOVERY_TIMEOUT,
+ .ctl_name = NET_IRDA_DISCOVERY_TIMEOUT,
.procname = "discovery_timeout",
.data = &sysctl_discovery_timeout,
.maxlen = sizeof(int),
@@ -150,7 +144,7 @@ static ctl_table irda_table[] = {
.proc_handler = &proc_dointvec
},
{
- .ctl_name = SLOT_TIMEOUT,
+ .ctl_name = NET_IRDA_SLOT_TIMEOUT,
.procname = "slot_timeout",
.data = &sysctl_slot_timeout,
.maxlen = sizeof(int),
@@ -161,7 +155,7 @@ static ctl_table irda_table[] = {
.extra2 = &max_slot_timeout
},
{
- .ctl_name = MAX_BAUD_RATE,
+ .ctl_name = NET_IRDA_MAX_BAUD_RATE,
.procname = "max_baud_rate",
.data = &sysctl_max_baud_rate,
.maxlen = sizeof(int),
@@ -172,7 +166,7 @@ static ctl_table irda_table[] = {
.extra2 = &max_max_baud_rate
},
{
- .ctl_name = MIN_TX_TURN_TIME,
+ .ctl_name = NET_IRDA_MIN_TX_TURN_TIME,
.procname = "min_tx_turn_time",
.data = &sysctl_min_tx_turn_time,
.maxlen = sizeof(int),
@@ -183,7 +177,7 @@ static ctl_table irda_table[] = {
.extra2 = &max_min_tx_turn_time
},
{
- .ctl_name = MAX_TX_DATA_SIZE,
+ .ctl_name = NET_IRDA_MAX_TX_DATA_SIZE,
.procname = "max_tx_data_size",
.data = &sysctl_max_tx_data_size,
.maxlen = sizeof(int),
@@ -194,7 +188,7 @@ static ctl_table irda_table[] = {
.extra2 = &max_max_tx_data_size
},
{
- .ctl_name = MAX_TX_WINDOW,
+ .ctl_name = NET_IRDA_MAX_TX_WINDOW,
.procname = "max_tx_window",
.data = &sysctl_max_tx_window,
.maxlen = sizeof(int),
@@ -205,7 +199,7 @@ static ctl_table irda_table[] = {
.extra2 = &max_max_tx_window
},
{
- .ctl_name = MAX_NOREPLY_TIME,
+ .ctl_name = NET_IRDA_MAX_NOREPLY_TIME,
.procname = "max_noreply_time",
.data = &sysctl_max_noreply_time,
.maxlen = sizeof(int),
@@ -216,7 +210,7 @@ static ctl_table irda_table[] = {
.extra2 = &max_max_noreply_time
},
{
- .ctl_name = WARN_NOREPLY_TIME,
+ .ctl_name = NET_IRDA_WARN_NOREPLY_TIME,
.procname = "warn_noreply_time",
.data = &sysctl_warn_noreply_time,
.maxlen = sizeof(int),
@@ -227,7 +221,7 @@ static ctl_table irda_table[] = {
.extra2 = &max_warn_noreply_time
},
{
- .ctl_name = LAP_KEEPALIVE_TIME,
+ .ctl_name = NET_IRDA_LAP_KEEPALIVE_TIME,
.procname = "lap_keepalive_time",
.data = &sysctl_lap_keepalive_time,
.maxlen = sizeof(int),
diff --git a/net/irda/irttp.c b/net/irda/irttp.c
index 1311976c9dfe..97db158c9274 100644
--- a/net/irda/irttp.c
+++ b/net/irda/irttp.c
@@ -18,7 +18,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
diff --git a/net/irda/timer.c b/net/irda/timer.c
index d3a6ee8cc4a2..d730099080a2 100644
--- a/net/irda/timer.c
+++ b/net/irda/timer.c
@@ -18,7 +18,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
diff --git a/net/irda/wrapper.c b/net/irda/wrapper.c
index a7a7f191f1a8..e71286768a48 100644
--- a/net/irda/wrapper.c
+++ b/net/irda/wrapper.c
@@ -20,7 +20,7 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
index 43e01c8d382b..aef664580355 100644
--- a/net/iucv/af_iucv.c
+++ b/net/iucv/af_iucv.c
@@ -216,7 +216,7 @@ static struct sock *iucv_sock_alloc(struct socket *sock, int proto, gfp_t prio)
{
struct sock *sk;
- sk = sk_alloc(&init_net, PF_IUCV, prio, &iucv_proto, 1);
+ sk = sk_alloc(&init_net, PF_IUCV, prio, &iucv_proto);
if (!sk)
return NULL;
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c
index 983058d432dc..a2f5a6ea3895 100644
--- a/net/iucv/iucv.c
+++ b/net/iucv/iucv.c
@@ -389,7 +389,7 @@ static void iucv_block_cpu(void *data)
* iucv_declare_cpu
* @data: unused
*
- * Declare a interupt buffer on this cpu.
+ * Declare a interrupt buffer on this cpu.
*/
static void iucv_declare_cpu(void *data)
{
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 7969f8a716df..10c89d47f685 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -152,7 +152,7 @@ static int pfkey_create(struct net *net, struct socket *sock, int protocol)
return -EPROTONOSUPPORT;
err = -ENOMEM;
- sk = sk_alloc(net, PF_KEY, GFP_KERNEL, &key_proto, 1);
+ sk = sk_alloc(net, PF_KEY, GFP_KERNEL, &key_proto);
if (sk == NULL)
goto out;
@@ -395,9 +395,9 @@ static inline int pfkey_sec_ctx_len(struct sadb_x_sec_ctx *sec_ctx)
static inline int verify_sec_ctx_len(void *p)
{
struct sadb_x_sec_ctx *sec_ctx = (struct sadb_x_sec_ctx *)p;
- int len;
+ int len = sec_ctx->sadb_x_ctx_len;
- if (sec_ctx->sadb_x_ctx_len > PAGE_SIZE)
+ if (len > PAGE_SIZE)
return -EINVAL;
len = pfkey_sec_ctx_len(sec_ctx);
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
index 49eacba824df..46cf962f7f88 100644
--- a/net/llc/af_llc.c
+++ b/net/llc/af_llc.c
@@ -762,7 +762,7 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
if (net_ratelimit())
printk(KERN_DEBUG "LLC(%s:%d): Application "
"bug, race in MSG_PEEK.\n",
- current->comm, current->pid);
+ current->comm, task_pid_nr(current));
peek_seq = llc->copied_seq;
}
continue;
diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c
index 8ebc2769dfda..5c0b484237c8 100644
--- a/net/llc/llc_conn.c
+++ b/net/llc/llc_conn.c
@@ -869,7 +869,7 @@ static void llc_sk_init(struct sock* sk)
*/
struct sock *llc_sk_alloc(struct net *net, int family, gfp_t priority, struct proto *prot)
{
- struct sock *sk = sk_alloc(net, family, priority, prot, 1);
+ struct sock *sk = sk_alloc(net, family, priority, prot);
if (!sk)
goto out;
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
index 6fffb3845ab6..ce176e691afe 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -13,6 +13,18 @@ config MAC80211
This option enables the hardware independent IEEE 802.11
networking stack.
+config MAC80211_RCSIMPLE
+ bool "'simple' rate control algorithm" if EMBEDDED
+ default y
+ depends on MAC80211
+ help
+ This option allows you to turn off the 'simple' rate
+ control algorithm in mac80211. If you do turn it off,
+ you absolutely need another rate control algorithm.
+
+ Say Y unless you know you will have another algorithm
+ available.
+
config MAC80211_LEDS
bool "Enable LED triggers"
depends on MAC80211 && LEDS_TRIGGERS
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
index 219cd9f9341f..1e6237b34846 100644
--- a/net/mac80211/Makefile
+++ b/net/mac80211/Makefile
@@ -1,8 +1,9 @@
-obj-$(CONFIG_MAC80211) += mac80211.o rc80211_simple.o
+obj-$(CONFIG_MAC80211) += mac80211.o
mac80211-objs-$(CONFIG_MAC80211_LEDS) += ieee80211_led.o
mac80211-objs-$(CONFIG_MAC80211_DEBUGFS) += debugfs.o debugfs_sta.o debugfs_netdev.o debugfs_key.o
mac80211-objs-$(CONFIG_NET_SCHED) += wme.o
+mac80211-objs-$(CONFIG_MAC80211_RCSIMPLE) += rc80211_simple.o
mac80211-objs := \
ieee80211.o \
diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c
index bf7ba128b963..e62fe55944b8 100644
--- a/net/mac80211/aes_ccm.c
+++ b/net/mac80211/aes_ccm.c
@@ -11,7 +11,6 @@
#include <linux/types.h>
#include <linux/crypto.h>
#include <linux/err.h>
-#include <asm/scatterlist.h>
#include <net/mac80211.h>
#include "ieee80211_key.h"
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
index f484ca7ade9c..e0ee65a969bc 100644
--- a/net/mac80211/ieee80211.c
+++ b/net/mac80211/ieee80211.c
@@ -1072,7 +1072,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
ieee80211_debugfs_add_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev));
ieee80211_if_set_type(local->mdev, IEEE80211_IF_TYPE_AP);
- result = ieee80211_init_rate_ctrl_alg(local, NULL);
+ result = ieee80211_init_rate_ctrl_alg(local,
+ hw->rate_control_algorithm);
if (result < 0) {
printk(KERN_DEBUG "%s: Failed to initialize rate control "
"algorithm\n", wiphy_name(local->hw.wiphy));
@@ -1233,8 +1234,17 @@ static int __init ieee80211_init(void)
BUILD_BUG_ON(sizeof(struct ieee80211_tx_packet_data) > sizeof(skb->cb));
+#ifdef CONFIG_MAC80211_RCSIMPLE
+ ret = ieee80211_rate_control_register(&mac80211_rcsimple);
+ if (ret)
+ return ret;
+#endif
+
ret = ieee80211_wme_register();
if (ret) {
+#ifdef CONFIG_MAC80211_RCSIMPLE
+ ieee80211_rate_control_unregister(&mac80211_rcsimple);
+#endif
printk(KERN_DEBUG "ieee80211_init: failed to "
"initialize WME (err=%d)\n", ret);
return ret;
@@ -1248,6 +1258,10 @@ static int __init ieee80211_init(void)
static void __exit ieee80211_exit(void)
{
+#ifdef CONFIG_MAC80211_RCSIMPLE
+ ieee80211_rate_control_unregister(&mac80211_rcsimple);
+#endif
+
ieee80211_wme_unregister();
ieee80211_debugfs_netdev_exit();
}
diff --git a/net/mac80211/ieee80211_common.h b/net/mac80211/ieee80211_common.h
deleted file mode 100644
index c15295d43d87..000000000000
--- a/net/mac80211/ieee80211_common.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * IEEE 802.11 driver (80211.o) -- hostapd interface
- * Copyright 2002-2004, Instant802 Networks, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef IEEE80211_COMMON_H
-#define IEEE80211_COMMON_H
-
-#include <linux/types.h>
-
-/*
- * This is common header information with user space. It is used on all
- * frames sent to wlan#ap interface.
- */
-
-#define IEEE80211_FI_VERSION 0x80211001
-
-struct ieee80211_frame_info {
- __be32 version;
- __be32 length;
- __be64 mactime;
- __be64 hosttime;
- __be32 phytype;
- __be32 channel;
- __be32 datarate;
- __be32 antenna;
- __be32 priority;
- __be32 ssi_type;
- __be32 ssi_signal;
- __be32 ssi_noise;
- __be32 preamble;
- __be32 encoding;
-
- /* Note: this structure is otherwise identical to capture format used
- * in linux-wlan-ng, but this additional field is used to provide meta
- * data about the frame to hostapd. This was the easiest method for
- * providing this information, but this might change in the future. */
- __be32 msg_type;
-} __attribute__ ((packed));
-
-
-enum ieee80211_msg_type {
- ieee80211_msg_normal = 0,
- ieee80211_msg_tx_callback_ack = 1,
- ieee80211_msg_tx_callback_fail = 2,
- /* hole at 3, was ieee80211_msg_passive_scan but unused */
- /* hole at 4, was ieee80211_msg_wep_frame_unknown_key but now unused */
- ieee80211_msg_michael_mic_failure = 5,
- /* hole at 6, was monitor but never sent to userspace */
- ieee80211_msg_sta_not_assoc = 7,
- /* 8 was ieee80211_msg_set_aid_for_sta */
- /* 9 was ieee80211_msg_key_threshold_notification */
- /* 11 was ieee80211_msg_radar */
-};
-
-struct ieee80211_msg_key_notification {
- int tx_rx_count;
- char ifname[IFNAMSIZ];
- u8 addr[ETH_ALEN]; /* ff:ff:ff:ff:ff:ff for broadcast keys */
-};
-
-
-enum ieee80211_phytype {
- ieee80211_phytype_fhss_dot11_97 = 1,
- ieee80211_phytype_dsss_dot11_97 = 2,
- ieee80211_phytype_irbaseband = 3,
- ieee80211_phytype_dsss_dot11_b = 4,
- ieee80211_phytype_pbcc_dot11_b = 5,
- ieee80211_phytype_ofdm_dot11_g = 6,
- ieee80211_phytype_pbcc_dot11_g = 7,
- ieee80211_phytype_ofdm_dot11_a = 8,
-};
-
-enum ieee80211_ssi_type {
- ieee80211_ssi_none = 0,
- ieee80211_ssi_norm = 1, /* normalized, 0-1000 */
- ieee80211_ssi_dbm = 2,
- ieee80211_ssi_raw = 3, /* raw SSI */
-};
-
-struct ieee80211_radar_info {
- int channel;
- int radar;
- int radar_type;
-};
-
-#endif /* IEEE80211_COMMON_H */
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index d34a9deca67a..72e1c93dd87e 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -37,8 +37,6 @@
struct ieee80211_local;
-#define BIT(x) (1 << (x))
-
#define IEEE80211_ALIGN32_PAD(a) ((4 - ((a) & 3)) & 3)
/* Maximum number of broadcast/multicast frames to buffer when some of the
@@ -232,6 +230,7 @@ struct ieee80211_if_vlan {
#define IEEE80211_STA_AUTO_SSID_SEL BIT(10)
#define IEEE80211_STA_AUTO_BSSID_SEL BIT(11)
#define IEEE80211_STA_AUTO_CHANNEL_SEL BIT(12)
+#define IEEE80211_STA_PRIVACY_INVOKED BIT(13)
struct ieee80211_if_sta {
enum {
IEEE80211_DISABLED, IEEE80211_AUTHENTICATE,
@@ -243,6 +242,8 @@ struct ieee80211_if_sta {
u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
u8 ssid[IEEE80211_MAX_SSID_LEN];
size_t ssid_len;
+ u8 scan_ssid[IEEE80211_MAX_SSID_LEN];
+ size_t scan_ssid_len;
u16 aid;
u16 ap_capab, capab;
u8 *extra_ie; /* to be added to the end of AssocReq */
@@ -261,7 +262,6 @@ struct ieee80211_if_sta {
unsigned long request;
struct sk_buff_head skb_queue;
- int key_management_enabled;
unsigned long last_probe;
#define IEEE80211_AUTH_ALG_OPEN BIT(0)
diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c
index f0224c2311d2..7027eed4d4ae 100644
--- a/net/mac80211/ieee80211_ioctl.c
+++ b/net/mac80211/ieee80211_ioctl.c
@@ -306,9 +306,12 @@ int ieee80211_set_channel(struct ieee80211_local *local, int channel, int freq)
((chan->chan == channel) || (chan->freq == freq))) {
local->oper_channel = chan;
local->oper_hw_mode = mode;
- set++;
+ set = 1;
+ break;
}
}
+ if (set)
+ break;
}
if (set) {
@@ -508,10 +511,11 @@ static int ieee80211_ioctl_giwap(struct net_device *dev,
static int ieee80211_ioctl_siwscan(struct net_device *dev,
struct iw_request_info *info,
- struct iw_point *data, char *extra)
+ union iwreq_data *wrqu, char *extra)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct iw_scan_req *req = NULL;
u8 *ssid = NULL;
size_t ssid_len = 0;
@@ -536,6 +540,14 @@ static int ieee80211_ioctl_siwscan(struct net_device *dev,
return -EOPNOTSUPP;
}
+ /* if SSID was specified explicitly then use that */
+ if (wrqu->data.length == sizeof(struct iw_scan_req) &&
+ wrqu->data.flags & IW_SCAN_THIS_ESSID) {
+ req = (struct iw_scan_req *)extra;
+ ssid = req->essid;
+ ssid_len = req->essid_len;
+ }
+
return ieee80211_sta_req_scan(dev, ssid, ssid_len);
}
@@ -905,7 +917,6 @@ static int ieee80211_ioctl_siwauth(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *data, char *extra)
{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
int ret = 0;
@@ -915,18 +926,21 @@ static int ieee80211_ioctl_siwauth(struct net_device *dev,
case IW_AUTH_CIPHER_GROUP:
case IW_AUTH_WPA_ENABLED:
case IW_AUTH_RX_UNENCRYPTED_EAPOL:
- break;
case IW_AUTH_KEY_MGMT:
+ break;
+ case IW_AUTH_PRIVACY_INVOKED:
if (sdata->type != IEEE80211_IF_TYPE_STA)
ret = -EINVAL;
else {
+ sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
/*
- * Key management was set by wpa_supplicant,
- * we only need this to associate to a network
- * that has privacy enabled regardless of not
- * having a key.
+ * Privacy invoked by wpa_supplicant, store the
+ * value and allow associating to a protected
+ * network without having a key up front.
*/
- sdata->u.sta.key_management_enabled = !!data->value;
+ if (data->value)
+ sdata->u.sta.flags |=
+ IEEE80211_STA_PRIVACY_INVOKED;
}
break;
case IW_AUTH_80211_AUTH_ALG:
@@ -936,11 +950,6 @@ static int ieee80211_ioctl_siwauth(struct net_device *dev,
else
ret = -EOPNOTSUPP;
break;
- case IW_AUTH_PRIVACY_INVOKED:
- if (local->ops->set_privacy_invoked)
- ret = local->ops->set_privacy_invoked(
- local_to_hw(local), data->value);
- break;
default:
ret = -EOPNOTSUPP;
break;
diff --git a/net/mac80211/ieee80211_rate.c b/net/mac80211/ieee80211_rate.c
index 93abb8fff141..7254bd609839 100644
--- a/net/mac80211/ieee80211_rate.c
+++ b/net/mac80211/ieee80211_rate.c
@@ -25,13 +25,25 @@ int ieee80211_rate_control_register(struct rate_control_ops *ops)
{
struct rate_control_alg *alg;
+ if (!ops->name)
+ return -EINVAL;
+
+ mutex_lock(&rate_ctrl_mutex);
+ list_for_each_entry(alg, &rate_ctrl_algs, list) {
+ if (!strcmp(alg->ops->name, ops->name)) {
+ /* don't register an algorithm twice */
+ WARN_ON(1);
+ return -EALREADY;
+ }
+ }
+
alg = kzalloc(sizeof(*alg), GFP_KERNEL);
if (alg == NULL) {
+ mutex_unlock(&rate_ctrl_mutex);
return -ENOMEM;
}
alg->ops = ops;
- mutex_lock(&rate_ctrl_mutex);
list_add_tail(&alg->list, &rate_ctrl_algs);
mutex_unlock(&rate_ctrl_mutex);
@@ -61,9 +73,12 @@ ieee80211_try_rate_control_ops_get(const char *name)
struct rate_control_alg *alg;
struct rate_control_ops *ops = NULL;
+ if (!name)
+ return NULL;
+
mutex_lock(&rate_ctrl_mutex);
list_for_each_entry(alg, &rate_ctrl_algs, list) {
- if (!name || !strcmp(alg->ops->name, name))
+ if (!strcmp(alg->ops->name, name))
if (try_module_get(alg->ops->module)) {
ops = alg->ops;
break;
@@ -80,9 +95,12 @@ ieee80211_rate_control_ops_get(const char *name)
{
struct rate_control_ops *ops;
+ if (!name)
+ name = "simple";
+
ops = ieee80211_try_rate_control_ops_get(name);
if (!ops) {
- request_module("rc80211_%s", name ? name : "default");
+ request_module("rc80211_%s", name);
ops = ieee80211_try_rate_control_ops_get(name);
}
return ops;
diff --git a/net/mac80211/ieee80211_rate.h b/net/mac80211/ieee80211_rate.h
index 7cd1ebab4f83..23688139ffb3 100644
--- a/net/mac80211/ieee80211_rate.h
+++ b/net/mac80211/ieee80211_rate.h
@@ -65,6 +65,9 @@ struct rate_control_ref {
struct kref kref;
};
+/* default 'simple' algorithm */
+extern struct rate_control_ops mac80211_rcsimple;
+
int ieee80211_rate_control_register(struct rate_control_ops *ops);
void ieee80211_rate_control_unregister(struct rate_control_ops *ops);
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
index 1641e8fe44b7..015b3f879aa9 100644
--- a/net/mac80211/ieee80211_sta.c
+++ b/net/mac80211/ieee80211_sta.c
@@ -12,7 +12,6 @@
*/
/* TODO:
- * BSS table: use <BSSID,SSID> as the key to support multi-SSID APs
* order BSS list by RSSI(?) ("quality of AP")
* scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE,
* SSID)
@@ -61,7 +60,8 @@
static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst,
u8 *ssid, size_t ssid_len);
static struct ieee80211_sta_bss *
-ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid);
+ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel,
+ u8 *ssid, u8 ssid_len);
static void ieee80211_rx_bss_put(struct net_device *dev,
struct ieee80211_sta_bss *bss);
static int ieee80211_sta_find_ibss(struct net_device *dev,
@@ -108,14 +108,11 @@ struct ieee802_11_elems {
u8 wmm_param_len;
};
-enum ParseRes { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 };
-
-static enum ParseRes ieee802_11_parse_elems(u8 *start, size_t len,
- struct ieee802_11_elems *elems)
+static void ieee802_11_parse_elems(u8 *start, size_t len,
+ struct ieee802_11_elems *elems)
{
size_t left = len;
u8 *pos = start;
- int unknown = 0;
memset(elems, 0, sizeof(*elems));
@@ -126,15 +123,8 @@ static enum ParseRes ieee802_11_parse_elems(u8 *start, size_t len,
elen = *pos++;
left -= 2;
- if (elen > left) {
-#if 0
- if (net_ratelimit())
- printk(KERN_DEBUG "IEEE 802.11 element parse "
- "failed (id=%d elen=%d left=%d)\n",
- id, elen, left);
-#endif
- return ParseFailed;
- }
+ if (elen > left)
+ return;
switch (id) {
case WLAN_EID_SSID:
@@ -201,28 +191,15 @@ static enum ParseRes ieee802_11_parse_elems(u8 *start, size_t len,
elems->ext_supp_rates_len = elen;
break;
default:
-#if 0
- printk(KERN_DEBUG "IEEE 802.11 element parse ignored "
- "unknown element (id=%d elen=%d)\n",
- id, elen);
-#endif
- unknown++;
break;
}
left -= elen;
pos += elen;
}
-
- /* Do not trigger error if left == 1 as Apple Airport base stations
- * send AssocResps that are one spurious byte too long. */
-
- return unknown ? ParseUnknown : ParseOK;
}
-
-
static int ecw2cw(int ecw)
{
int cw = 1;
@@ -427,7 +404,9 @@ static void ieee80211_set_associated(struct net_device *dev,
if (sdata->type != IEEE80211_IF_TYPE_STA)
return;
- bss = ieee80211_rx_bss_get(dev, ifsta->bssid);
+ bss = ieee80211_rx_bss_get(dev, ifsta->bssid,
+ local->hw.conf.channel,
+ ifsta->ssid, ifsta->ssid_len);
if (bss) {
if (bss->has_erp_value)
ieee80211_handle_erp_ie(dev, bss->erp_value);
@@ -574,7 +553,8 @@ static void ieee80211_send_assoc(struct net_device *dev,
capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME |
WLAN_CAPABILITY_SHORT_PREAMBLE;
}
- bss = ieee80211_rx_bss_get(dev, ifsta->bssid);
+ bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel,
+ ifsta->ssid, ifsta->ssid_len);
if (bss) {
if (bss->capability & WLAN_CAPABILITY_PRIVACY)
capab |= WLAN_CAPABILITY_PRIVACY;
@@ -722,24 +702,30 @@ static void ieee80211_send_disassoc(struct net_device *dev,
static int ieee80211_privacy_mismatch(struct net_device *dev,
struct ieee80211_if_sta *ifsta)
{
+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_sta_bss *bss;
- int res = 0;
+ int bss_privacy;
+ int wep_privacy;
+ int privacy_invoked;
- if (!ifsta || (ifsta->flags & IEEE80211_STA_MIXED_CELL) ||
- ifsta->key_management_enabled)
+ if (!ifsta || (ifsta->flags & IEEE80211_STA_MIXED_CELL))
return 0;
- bss = ieee80211_rx_bss_get(dev, ifsta->bssid);
+ bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel,
+ ifsta->ssid, ifsta->ssid_len);
if (!bss)
return 0;
- if (ieee80211_sta_wep_configured(dev) !=
- !!(bss->capability & WLAN_CAPABILITY_PRIVACY))
- res = 1;
+ bss_privacy = !!(bss->capability & WLAN_CAPABILITY_PRIVACY);
+ wep_privacy = !!ieee80211_sta_wep_configured(dev);
+ privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED);
ieee80211_rx_bss_put(dev, bss);
- return res;
+ if ((bss_privacy == wep_privacy) || (bss_privacy == privacy_invoked))
+ return 0;
+
+ return 1;
}
@@ -926,12 +912,7 @@ static void ieee80211_auth_challenge(struct net_device *dev,
printk(KERN_DEBUG "%s: replying to auth challenge\n", dev->name);
pos = mgmt->u.auth.variable;
- if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems)
- == ParseFailed) {
- printk(KERN_DEBUG "%s: failed to parse Auth(challenge)\n",
- dev->name);
- return;
- }
+ ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
if (!elems.challenge) {
printk(KERN_DEBUG "%s: no challenge IE in shared key auth "
"frame\n", dev->name);
@@ -1203,15 +1184,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
aid = le16_to_cpu(mgmt->u.assoc_resp.aid);
- if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
- printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not "
- "set\n", dev->name, aid);
- aid &= ~(BIT(15) | BIT(14));
printk(KERN_DEBUG "%s: RX %sssocResp from %s (capab=0x%x "
"status=%d aid=%d)\n",
dev->name, reassoc ? "Rea" : "A", print_mac(mac, mgmt->sa),
- capab_info, status_code, aid);
+ capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14))));
if (status_code != WLAN_STATUS_SUCCESS) {
printk(KERN_DEBUG "%s: AP denied association (code=%d)\n",
@@ -1223,13 +1200,13 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
return;
}
+ if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
+ printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not "
+ "set\n", dev->name, aid);
+ aid &= ~(BIT(15) | BIT(14));
+
pos = mgmt->u.assoc_resp.variable;
- if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems)
- == ParseFailed) {
- printk(KERN_DEBUG "%s: failed to parse AssocResp\n",
- dev->name);
- return;
- }
+ ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
if (!elems.supp_rates) {
printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n",
@@ -1241,7 +1218,9 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
* update our stored copy */
if (elems.erp_info && elems.erp_info_len >= 1) {
struct ieee80211_sta_bss *bss
- = ieee80211_rx_bss_get(dev, ifsta->bssid);
+ = ieee80211_rx_bss_get(dev, ifsta->bssid,
+ local->hw.conf.channel,
+ ifsta->ssid, ifsta->ssid_len);
if (bss) {
bss->erp_value = elems.erp_info[0];
bss->has_erp_value = 1;
@@ -1271,7 +1250,9 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
" AP\n", dev->name);
return;
}
- bss = ieee80211_rx_bss_get(dev, ifsta->bssid);
+ bss = ieee80211_rx_bss_get(dev, ifsta->bssid,
+ local->hw.conf.channel,
+ ifsta->ssid, ifsta->ssid_len);
if (bss) {
sta->last_rssi = bss->rssi;
sta->last_signal = bss->signal;
@@ -1347,7 +1328,8 @@ static void __ieee80211_rx_bss_hash_del(struct net_device *dev,
static struct ieee80211_sta_bss *
-ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid)
+ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int channel,
+ u8 *ssid, u8 ssid_len)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_sta_bss *bss;
@@ -1358,6 +1340,11 @@ ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid)
atomic_inc(&bss->users);
atomic_inc(&bss->users);
memcpy(bss->bssid, bssid, ETH_ALEN);
+ bss->channel = channel;
+ if (ssid && ssid_len <= IEEE80211_MAX_SSID_LEN) {
+ memcpy(bss->ssid, ssid, ssid_len);
+ bss->ssid_len = ssid_len;
+ }
spin_lock_bh(&local->sta_bss_lock);
/* TODO: order by RSSI? */
@@ -1369,7 +1356,8 @@ ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid)
static struct ieee80211_sta_bss *
-ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid)
+ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel,
+ u8 *ssid, u8 ssid_len)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_sta_bss *bss;
@@ -1377,7 +1365,10 @@ ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid)
spin_lock_bh(&local->sta_bss_lock);
bss = local->sta_bss_hash[STA_HASH(bssid)];
while (bss) {
- if (memcmp(bss->bssid, bssid, ETH_ALEN) == 0) {
+ if (!memcmp(bss->bssid, bssid, ETH_ALEN) &&
+ bss->channel == channel &&
+ bss->ssid_len == ssid_len &&
+ (ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) {
atomic_inc(&bss->users);
break;
}
@@ -1439,7 +1430,7 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee802_11_elems elems;
size_t baselen;
- int channel, invalid = 0, clen;
+ int channel, clen;
struct ieee80211_sta_bss *bss;
struct sta_info *sta;
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@@ -1485,9 +1476,7 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
#endif /* CONFIG_MAC80211_IBSS_DEBUG */
}
- if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen,
- &elems) == ParseFailed)
- invalid = 1;
+ ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
if (sdata->type == IEEE80211_IF_TYPE_IBSS && elems.supp_rates &&
memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 &&
@@ -1545,9 +1534,11 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
else
channel = rx_status->channel;
- bss = ieee80211_rx_bss_get(dev, mgmt->bssid);
+ bss = ieee80211_rx_bss_get(dev, mgmt->bssid, channel,
+ elems.ssid, elems.ssid_len);
if (!bss) {
- bss = ieee80211_rx_bss_add(dev, mgmt->bssid);
+ bss = ieee80211_rx_bss_add(dev, mgmt->bssid, channel,
+ elems.ssid, elems.ssid_len);
if (!bss)
return;
} else {
@@ -1573,10 +1564,6 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int);
bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info);
- if (elems.ssid && elems.ssid_len <= IEEE80211_MAX_SSID_LEN) {
- memcpy(bss->ssid, elems.ssid, elems.ssid_len);
- bss->ssid_len = elems.ssid_len;
- }
bss->supp_rates_len = 0;
if (elems.supp_rates) {
@@ -1647,7 +1634,6 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
bss->hw_mode = rx_status->phymode;
- bss->channel = channel;
bss->freq = rx_status->freq;
if (channel != rx_status->channel &&
(bss->hw_mode == MODE_IEEE80211G ||
@@ -1707,9 +1693,7 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
if (baselen > len)
return;
- if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen,
- &elems) == ParseFailed)
- return;
+ ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
if (elems.erp_info && elems.erp_info_len >= 1)
ieee80211_handle_erp_ie(dev, elems.erp_info[0]);
@@ -2018,7 +2002,10 @@ void ieee80211_sta_work(struct work_struct *work)
if (ifsta->state != IEEE80211_AUTHENTICATE &&
ifsta->state != IEEE80211_ASSOCIATE &&
test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) {
- ieee80211_sta_start_scan(dev, NULL, 0);
+ if (ifsta->scan_ssid_len)
+ ieee80211_sta_start_scan(dev, ifsta->scan_ssid, ifsta->scan_ssid_len);
+ else
+ ieee80211_sta_start_scan(dev, NULL, 0);
return;
}
@@ -2116,7 +2103,8 @@ static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta,
{
int tmp, hidden_ssid;
- if (!memcmp(ifsta->ssid, ssid, ssid_len))
+ if (ssid_len == ifsta->ssid_len &&
+ !memcmp(ifsta->ssid, ssid, ssid_len))
return 1;
if (ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL)
@@ -2375,7 +2363,7 @@ static int ieee80211_sta_create_ibss(struct net_device *dev,
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_sta_bss *bss;
- struct ieee80211_sub_if_data *sdata;
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_hw_mode *mode;
u8 bssid[ETH_ALEN], *pos;
int i;
@@ -2398,18 +2386,17 @@ static int ieee80211_sta_create_ibss(struct net_device *dev,
printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %s\n",
dev->name, print_mac(mac, bssid));
- bss = ieee80211_rx_bss_add(dev, bssid);
+ bss = ieee80211_rx_bss_add(dev, bssid, local->hw.conf.channel,
+ sdata->u.sta.ssid, sdata->u.sta.ssid_len);
if (!bss)
return -ENOMEM;
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
mode = local->oper_hw_mode;
if (local->hw.conf.beacon_int == 0)
local->hw.conf.beacon_int = 100;
bss->beacon_int = local->hw.conf.beacon_int;
bss->hw_mode = local->hw.conf.phymode;
- bss->channel = local->hw.conf.channel;
bss->freq = local->hw.conf.freq;
bss->last_update = jiffies;
bss->capability = WLAN_CAPABILITY_IBSS;
@@ -2469,7 +2456,8 @@ static int ieee80211_sta_find_ibss(struct net_device *dev,
"%s\n", print_mac(mac, bssid), print_mac(mac2, ifsta->bssid));
#endif /* CONFIG_MAC80211_IBSS_DEBUG */
if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0 &&
- (bss = ieee80211_rx_bss_get(dev, bssid))) {
+ (bss = ieee80211_rx_bss_get(dev, bssid, local->hw.conf.channel,
+ ifsta->ssid, ifsta->ssid_len))) {
printk(KERN_DEBUG "%s: Selected IBSS BSSID %s"
" based on configured SSID\n",
dev->name, print_mac(mac, bssid));
@@ -2887,6 +2875,9 @@ int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len)
return -EBUSY;
}
+ ifsta->scan_ssid_len = ssid_len;
+ if (ssid_len)
+ memcpy(ifsta->scan_ssid, ssid, ssid_len);
set_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request);
queue_work(local->hw.workqueue, &ifsta->work);
return 0;
diff --git a/net/mac80211/rc80211_simple.c b/net/mac80211/rc80211_simple.c
index 314b8de88862..da72737364e4 100644
--- a/net/mac80211/rc80211_simple.c
+++ b/net/mac80211/rc80211_simple.c
@@ -7,7 +7,6 @@
* published by the Free Software Foundation.
*/
-#include <linux/module.h>
#include <linux/init.h>
#include <linux/netdevice.h>
#include <linux/types.h>
@@ -29,8 +28,6 @@
#define RATE_CONTROL_INTERVAL (HZ / 20)
#define RATE_CONTROL_MIN_TX 10
-MODULE_ALIAS("rc80211_default");
-
static void rate_control_rate_inc(struct ieee80211_local *local,
struct sta_info *sta)
{
@@ -394,8 +391,7 @@ static void rate_control_simple_remove_sta_debugfs(void *priv, void *priv_sta)
}
#endif
-static struct rate_control_ops rate_control_simple = {
- .module = THIS_MODULE,
+struct rate_control_ops mac80211_rcsimple = {
.name = "simple",
.tx_status = rate_control_simple_tx_status,
.get_rate = rate_control_simple_get_rate,
@@ -410,22 +406,3 @@ static struct rate_control_ops rate_control_simple = {
.remove_sta_debugfs = rate_control_simple_remove_sta_debugfs,
#endif
};
-
-
-static int __init rate_control_simple_init(void)
-{
- return ieee80211_rate_control_register(&rate_control_simple);
-}
-
-
-static void __exit rate_control_simple_exit(void)
-{
- ieee80211_rate_control_unregister(&rate_control_simple);
-}
-
-
-subsys_initcall(rate_control_simple_init);
-module_exit(rate_control_simple_exit);
-
-MODULE_DESCRIPTION("Simple rate control algorithm for ieee80211");
-MODULE_LICENSE("GPL");
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index ece77766ea2b..428a9fcf57d6 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -509,9 +509,11 @@ ieee80211_rx_h_decrypt(struct ieee80211_txrx_data *rx)
rx->key->tx_rx_count++;
/* TODO: add threshold stuff again */
} else {
+#ifdef CONFIG_MAC80211_DEBUG
if (net_ratelimit())
printk(KERN_DEBUG "%s: RX protected frame,"
" but have no key\n", rx->dev->name);
+#endif /* CONFIG_MAC80211_DEBUG */
return TXRX_DROP;
}
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c
index 6675261e958f..9bf0e1cc530a 100644
--- a/net/mac80211/wep.c
+++ b/net/mac80211/wep.c
@@ -16,7 +16,7 @@
#include <linux/crypto.h>
#include <linux/err.h>
#include <linux/mm.h>
-#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
#include <net/mac80211.h>
#include "ieee80211_i.h"
@@ -138,9 +138,7 @@ void ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
*icv = cpu_to_le32(~crc32_le(~0, data, data_len));
crypto_blkcipher_setkey(tfm, rc4key, klen);
- sg.page = virt_to_page(data);
- sg.offset = offset_in_page(data);
- sg.length = data_len + WEP_ICV_LEN;
+ sg_init_one(&sg, data, data_len + WEP_ICV_LEN);
crypto_blkcipher_encrypt(&desc, &sg, &sg, sg.length);
}
@@ -204,9 +202,7 @@ int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
__le32 crc;
crypto_blkcipher_setkey(tfm, rc4key, klen);
- sg.page = virt_to_page(data);
- sg.offset = offset_in_page(data);
- sg.length = data_len + WEP_ICV_LEN;
+ sg_init_one(&sg, data, data_len + WEP_ICV_LEN);
crypto_blkcipher_decrypt(&desc, &sg, &sg, sg.length);
crc = cpu_to_le32(~crc32_le(~0, data, data_len));
@@ -318,9 +314,11 @@ ieee80211_crypto_wep_decrypt(struct ieee80211_txrx_data *rx)
if (!(rx->u.rx.status->flag & RX_FLAG_DECRYPTED)) {
if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key)) {
+#ifdef CONFIG_MAC80211_DEBUG
if (net_ratelimit())
printk(KERN_DEBUG "%s: RX WEP frame, decrypt "
"failed\n", rx->dev->name);
+#endif /* CONFIG_MAC80211_DEBUG */
return TXRX_DROP;
}
} else if (!(rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED)) {
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index 6695efba57ec..20cec1cb956f 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -323,9 +323,12 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_txrx_data *rx)
&rx->u.rx.tkip_iv32,
&rx->u.rx.tkip_iv16);
if (res != TKIP_DECRYPT_OK || wpa_test) {
- printk(KERN_DEBUG "%s: TKIP decrypt failed for RX frame from "
- "%s (res=%d)\n",
- rx->dev->name, print_mac(mac, rx->sta->addr), res);
+#ifdef CONFIG_MAC80211_DEBUG
+ if (net_ratelimit())
+ printk(KERN_DEBUG "%s: TKIP decrypt failed for RX "
+ "frame from %s (res=%d)\n", rx->dev->name,
+ print_mac(mac, rx->sta->addr), res);
+#endif /* CONFIG_MAC80211_DEBUG */
return TXRX_DROP;
}
@@ -594,9 +597,12 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_txrx_data *rx)
skb->data + hdrlen + CCMP_HDR_LEN, data_len,
skb->data + skb->len - CCMP_MIC_LEN,
skb->data + hdrlen + CCMP_HDR_LEN)) {
- printk(KERN_DEBUG "%s: CCMP decrypt failed for RX "
- "frame from %s\n", rx->dev->name,
- print_mac(mac, rx->sta->addr));
+#ifdef CONFIG_MAC80211_DEBUG
+ if (net_ratelimit())
+ printk(KERN_DEBUG "%s: CCMP decrypt failed "
+ "for RX frame from %s\n", rx->dev->name,
+ print_mac(mac, rx->sta->addr));
+#endif /* CONFIG_MAC80211_DEBUG */
return TXRX_DROP;
}
}
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index d7a600a5720a..21a9fcc03796 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -363,7 +363,7 @@ config NETFILTER_XT_TARGET_TRACE
the tables, chains, rules.
If you want to compile it as a module, say M here and read
- <file:Documentation/modules.txt>. If unsure, say `N'.
+ <file:Documentation/kbuild/modules.txt>. If unsure, say `N'.
config NETFILTER_XT_TARGET_SECMARK
tristate '"SECMARK" target support'
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 93c58f973831..ad0e36ebea3d 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -40,15 +40,15 @@ obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
# targets
obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIFY) += xt_CLASSIFY.o
obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o
obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o
-obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o
-obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o
obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o
obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o
-obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o
# matches
obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o
@@ -59,22 +59,22 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o
obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o
obj-$(CONFIG_NETFILTER_XT_MATCH_DSCP) += xt_dscp.o
obj-$(CONFIG_NETFILTER_XT_MATCH_ESP) += xt_esp.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_HASHLIMIT) += xt_hashlimit.o
obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o
obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o
obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o
obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o
obj-$(CONFIG_NETFILTER_XT_MATCH_MARK) += xt_mark.o
obj-$(CONFIG_NETFILTER_XT_MATCH_MULTIPORT) += xt_multiport.o
-obj-$(CONFIG_NETFILTER_XT_MATCH_POLICY) += xt_policy.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o
obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += xt_pkttype.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_POLICY) += xt_policy.o
obj-$(CONFIG_NETFILTER_XT_MATCH_QUOTA) += xt_quota.o
obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o
obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o
obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o
obj-$(CONFIG_NETFILTER_XT_MATCH_STATISTIC) += xt_statistic.o
obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o
-obj-$(CONFIG_NETFILTER_XT_MATCH_TIME) += xt_time.o
obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o
-obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_TIME) += xt_time.o
obj-$(CONFIG_NETFILTER_XT_MATCH_U32) += xt_u32.o
-obj-$(CONFIG_NETFILTER_XT_MATCH_HASHLIMIT) += xt_hashlimit.o
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index a523fa4136ed..bed9ba01e8ec 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -117,7 +117,7 @@ void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n)
EXPORT_SYMBOL(nf_unregister_hooks);
unsigned int nf_iterate(struct list_head *head,
- struct sk_buff **skb,
+ struct sk_buff *skb,
int hook,
const struct net_device *indev,
const struct net_device *outdev,
@@ -160,7 +160,7 @@ unsigned int nf_iterate(struct list_head *head,
/* Returns 1 if okfn() needs to be executed by the caller,
* -EPERM for NF_DROP, 0 otherwise. */
-int nf_hook_slow(int pf, unsigned int hook, struct sk_buff **pskb,
+int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
struct net_device *indev,
struct net_device *outdev,
int (*okfn)(struct sk_buff *),
@@ -175,17 +175,17 @@ int nf_hook_slow(int pf, unsigned int hook, struct sk_buff **pskb,
elem = &nf_hooks[pf][hook];
next_hook:
- verdict = nf_iterate(&nf_hooks[pf][hook], pskb, hook, indev,
+ verdict = nf_iterate(&nf_hooks[pf][hook], skb, hook, indev,
outdev, &elem, okfn, hook_thresh);
if (verdict == NF_ACCEPT || verdict == NF_STOP) {
ret = 1;
goto unlock;
} else if (verdict == NF_DROP) {
- kfree_skb(*pskb);
+ kfree_skb(skb);
ret = -EPERM;
} else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) {
NFDEBUG("nf_hook: Verdict = QUEUE.\n");
- if (!nf_queue(*pskb, elem, pf, hook, indev, outdev, okfn,
+ if (!nf_queue(skb, elem, pf, hook, indev, outdev, okfn,
verdict >> NF_VERDICT_BITS))
goto next_hook;
}
@@ -196,34 +196,24 @@ unlock:
EXPORT_SYMBOL(nf_hook_slow);
-int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len)
+int skb_make_writable(struct sk_buff *skb, unsigned int writable_len)
{
- struct sk_buff *nskb;
-
- if (writable_len > (*pskb)->len)
+ if (writable_len > skb->len)
return 0;
/* Not exclusive use of packet? Must copy. */
- if (skb_cloned(*pskb) && !skb_clone_writable(*pskb, writable_len))
- goto copy_skb;
- if (skb_shared(*pskb))
- goto copy_skb;
-
- return pskb_may_pull(*pskb, writable_len);
-
-copy_skb:
- nskb = skb_copy(*pskb, GFP_ATOMIC);
- if (!nskb)
- return 0;
- BUG_ON(skb_is_nonlinear(nskb));
-
- /* Rest of kernel will get very unhappy if we pass it a
- suddenly-orphaned skbuff */
- if ((*pskb)->sk)
- skb_set_owner_w(nskb, (*pskb)->sk);
- kfree_skb(*pskb);
- *pskb = nskb;
- return 1;
+ if (!skb_cloned(skb)) {
+ if (writable_len <= skb_headlen(skb))
+ return 1;
+ } else if (skb_clone_writable(skb, writable_len))
+ return 1;
+
+ if (writable_len <= skb_headlen(skb))
+ writable_len = 0;
+ else
+ writable_len -= skb_headlen(skb);
+
+ return !!__pskb_pull_tail(skb, writable_len);
}
EXPORT_SYMBOL(skb_make_writable);
diff --git a/net/netfilter/nf_conntrack_amanda.c b/net/netfilter/nf_conntrack_amanda.c
index e42ab230ad88..7b8239c0cd5e 100644
--- a/net/netfilter/nf_conntrack_amanda.c
+++ b/net/netfilter/nf_conntrack_amanda.c
@@ -36,7 +36,7 @@ MODULE_PARM_DESC(master_timeout, "timeout for the master connection");
module_param(ts_algo, charp, 0400);
MODULE_PARM_DESC(ts_algo, "textsearch algorithm to use (default kmp)");
-unsigned int (*nf_nat_amanda_hook)(struct sk_buff **pskb,
+unsigned int (*nf_nat_amanda_hook)(struct sk_buff *skb,
enum ip_conntrack_info ctinfo,
unsigned int matchoff,
unsigned int matchlen,
@@ -79,7 +79,7 @@ static struct {
},
};
-static int amanda_help(struct sk_buff **pskb,
+static int amanda_help(struct sk_buff *skb,
unsigned int protoff,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo)
@@ -101,25 +101,25 @@ static int amanda_help(struct sk_buff **pskb,
/* increase the UDP timeout of the master connection as replies from
* Amanda clients to the server can be quite delayed */
- nf_ct_refresh(ct, *pskb, master_timeout * HZ);
+ nf_ct_refresh(ct, skb, master_timeout * HZ);
/* No data? */
dataoff = protoff + sizeof(struct udphdr);
- if (dataoff >= (*pskb)->len) {
+ if (dataoff >= skb->len) {
if (net_ratelimit())
- printk("amanda_help: skblen = %u\n", (*pskb)->len);
+ printk("amanda_help: skblen = %u\n", skb->len);
return NF_ACCEPT;
}
memset(&ts, 0, sizeof(ts));
- start = skb_find_text(*pskb, dataoff, (*pskb)->len,
+ start = skb_find_text(skb, dataoff, skb->len,
search[SEARCH_CONNECT].ts, &ts);
if (start == UINT_MAX)
goto out;
start += dataoff + search[SEARCH_CONNECT].len;
memset(&ts, 0, sizeof(ts));
- stop = skb_find_text(*pskb, start, (*pskb)->len,
+ stop = skb_find_text(skb, start, skb->len,
search[SEARCH_NEWLINE].ts, &ts);
if (stop == UINT_MAX)
goto out;
@@ -127,13 +127,13 @@ static int amanda_help(struct sk_buff **pskb,
for (i = SEARCH_DATA; i <= SEARCH_INDEX; i++) {
memset(&ts, 0, sizeof(ts));
- off = skb_find_text(*pskb, start, stop, search[i].ts, &ts);
+ off = skb_find_text(skb, start, stop, search[i].ts, &ts);
if (off == UINT_MAX)
continue;
off += start + search[i].len;
len = min_t(unsigned int, sizeof(pbuf) - 1, stop - off);
- if (skb_copy_bits(*pskb, off, pbuf, len))
+ if (skb_copy_bits(skb, off, pbuf, len))
break;
pbuf[len] = '\0';
@@ -153,7 +153,7 @@ static int amanda_help(struct sk_buff **pskb,
nf_nat_amanda = rcu_dereference(nf_nat_amanda_hook);
if (nf_nat_amanda && ct->status & IPS_NAT_MASK)
- ret = nf_nat_amanda(pskb, ctinfo, off - dataoff,
+ ret = nf_nat_amanda(skb, ctinfo, off - dataoff,
len, exp);
else if (nf_ct_expect_related(exp) != 0)
ret = NF_DROP;
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 83c30b45d170..000c2fb462d0 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -307,7 +307,7 @@ EXPORT_SYMBOL_GPL(nf_conntrack_hash_insert);
/* Confirm a connection given skb; places it in hash table */
int
-__nf_conntrack_confirm(struct sk_buff **pskb)
+__nf_conntrack_confirm(struct sk_buff *skb)
{
unsigned int hash, repl_hash;
struct nf_conntrack_tuple_hash *h;
@@ -316,7 +316,7 @@ __nf_conntrack_confirm(struct sk_buff **pskb)
struct hlist_node *n;
enum ip_conntrack_info ctinfo;
- ct = nf_ct_get(*pskb, &ctinfo);
+ ct = nf_ct_get(skb, &ctinfo);
/* ipt_REJECT uses nf_conntrack_attach to attach related
ICMP/TCP RST packets in other direction. Actual packet
@@ -367,14 +367,14 @@ __nf_conntrack_confirm(struct sk_buff **pskb)
write_unlock_bh(&nf_conntrack_lock);
help = nfct_help(ct);
if (help && help->helper)
- nf_conntrack_event_cache(IPCT_HELPER, *pskb);
+ nf_conntrack_event_cache(IPCT_HELPER, skb);
#ifdef CONFIG_NF_NAT_NEEDED
if (test_bit(IPS_SRC_NAT_DONE_BIT, &ct->status) ||
test_bit(IPS_DST_NAT_DONE_BIT, &ct->status))
- nf_conntrack_event_cache(IPCT_NATINFO, *pskb);
+ nf_conntrack_event_cache(IPCT_NATINFO, skb);
#endif
nf_conntrack_event_cache(master_ct(ct) ?
- IPCT_RELATED : IPCT_NEW, *pskb);
+ IPCT_RELATED : IPCT_NEW, skb);
return NF_ACCEPT;
out:
@@ -632,7 +632,7 @@ resolve_normal_ct(struct sk_buff *skb,
}
unsigned int
-nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb)
+nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff *skb)
{
struct nf_conn *ct;
enum ip_conntrack_info ctinfo;
@@ -644,14 +644,14 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb)
int ret;
/* Previously seen (loopback or untracked)? Ignore. */
- if ((*pskb)->nfct) {
+ if (skb->nfct) {
NF_CT_STAT_INC_ATOMIC(ignore);
return NF_ACCEPT;
}
/* rcu_read_lock()ed by nf_hook_slow */
l3proto = __nf_ct_l3proto_find((u_int16_t)pf);
- ret = l3proto->get_l4proto(*pskb, skb_network_offset(*pskb),
+ ret = l3proto->get_l4proto(skb, skb_network_offset(skb),
&dataoff, &protonum);
if (ret <= 0) {
pr_debug("not prepared to track yet or error occured\n");
@@ -666,13 +666,13 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb)
* inverse of the return code tells to the netfilter
* core what to do with the packet. */
if (l4proto->error != NULL &&
- (ret = l4proto->error(*pskb, dataoff, &ctinfo, pf, hooknum)) <= 0) {
+ (ret = l4proto->error(skb, dataoff, &ctinfo, pf, hooknum)) <= 0) {
NF_CT_STAT_INC_ATOMIC(error);
NF_CT_STAT_INC_ATOMIC(invalid);
return -ret;
}
- ct = resolve_normal_ct(*pskb, dataoff, pf, protonum, l3proto, l4proto,
+ ct = resolve_normal_ct(skb, dataoff, pf, protonum, l3proto, l4proto,
&set_reply, &ctinfo);
if (!ct) {
/* Not valid part of a connection */
@@ -686,21 +686,21 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb)
return NF_DROP;
}
- NF_CT_ASSERT((*pskb)->nfct);
+ NF_CT_ASSERT(skb->nfct);
- ret = l4proto->packet(ct, *pskb, dataoff, ctinfo, pf, hooknum);
+ ret = l4proto->packet(ct, skb, dataoff, ctinfo, pf, hooknum);
if (ret < 0) {
/* Invalid: inverse of the return code tells
* the netfilter core what to do */
pr_debug("nf_conntrack_in: Can't track with proto module\n");
- nf_conntrack_put((*pskb)->nfct);
- (*pskb)->nfct = NULL;
+ nf_conntrack_put(skb->nfct);
+ skb->nfct = NULL;
NF_CT_STAT_INC_ATOMIC(invalid);
return -ret;
}
if (set_reply && !test_and_set_bit(IPS_SEEN_REPLY_BIT, &ct->status))
- nf_conntrack_event_cache(IPCT_STATUS, *pskb);
+ nf_conntrack_event_cache(IPCT_STATUS, skb);
return ret;
}
@@ -999,7 +999,7 @@ struct hlist_head *nf_ct_alloc_hashtable(int *sizep, int *vmalloced)
*vmalloced = 0;
size = *sizep = roundup(*sizep, PAGE_SIZE / sizeof(struct hlist_head));
- hash = (void*)__get_free_pages(GFP_KERNEL,
+ hash = (void*)__get_free_pages(GFP_KERNEL|__GFP_NOWARN,
get_order(sizeof(struct hlist_head)
* size));
if (!hash) {
diff --git a/net/netfilter/nf_conntrack_extend.c b/net/netfilter/nf_conntrack_extend.c
index a1a65a1313b3..cf6ba6659a80 100644
--- a/net/netfilter/nf_conntrack_extend.c
+++ b/net/netfilter/nf_conntrack_extend.c
@@ -109,7 +109,7 @@ void *__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp)
rcu_read_lock();
t = rcu_dereference(nf_ct_ext_types[i]);
if (t && t->move)
- t->move(ct, ct->ext + ct->ext->offset[id]);
+ t->move(ct, ct->ext + ct->ext->offset[i]);
rcu_read_unlock();
}
kfree(ct->ext);
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index c763ee74ea02..6df259067f7e 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -43,7 +43,7 @@ module_param_array(ports, ushort, &ports_c, 0400);
static int loose;
module_param(loose, bool, 0600);
-unsigned int (*nf_nat_ftp_hook)(struct sk_buff **pskb,
+unsigned int (*nf_nat_ftp_hook)(struct sk_buff *skb,
enum ip_conntrack_info ctinfo,
enum nf_ct_ftp_type type,
unsigned int matchoff,
@@ -344,7 +344,7 @@ static void update_nl_seq(u32 nl_seq, struct nf_ct_ftp_master *info, int dir,
}
}
-static int help(struct sk_buff **pskb,
+static int help(struct sk_buff *skb,
unsigned int protoff,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo)
@@ -371,21 +371,21 @@ static int help(struct sk_buff **pskb,
return NF_ACCEPT;
}
- th = skb_header_pointer(*pskb, protoff, sizeof(_tcph), &_tcph);
+ th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
if (th == NULL)
return NF_ACCEPT;
dataoff = protoff + th->doff * 4;
/* No data? */
- if (dataoff >= (*pskb)->len) {
+ if (dataoff >= skb->len) {
pr_debug("ftp: dataoff(%u) >= skblen(%u)\n", dataoff,
- (*pskb)->len);
+ skb->len);
return NF_ACCEPT;
}
- datalen = (*pskb)->len - dataoff;
+ datalen = skb->len - dataoff;
spin_lock_bh(&nf_ftp_lock);
- fb_ptr = skb_header_pointer(*pskb, dataoff, datalen, ftp_buffer);
+ fb_ptr = skb_header_pointer(skb, dataoff, datalen, ftp_buffer);
BUG_ON(fb_ptr == NULL);
ends_in_nl = (fb_ptr[datalen - 1] == '\n');
@@ -491,7 +491,7 @@ static int help(struct sk_buff **pskb,
* (possibly changed) expectation itself. */
nf_nat_ftp = rcu_dereference(nf_nat_ftp_hook);
if (nf_nat_ftp && ct->status & IPS_NAT_MASK)
- ret = nf_nat_ftp(pskb, ctinfo, search[dir][i].ftptype,
+ ret = nf_nat_ftp(skb, ctinfo, search[dir][i].ftptype,
matchoff, matchlen, exp);
else {
/* Can't expect this? Best to drop packet now. */
@@ -508,7 +508,7 @@ out_update_nl:
/* Now if this ends in \n, update ftp info. Seq may have been
* adjusted by NAT code. */
if (ends_in_nl)
- update_nl_seq(seq, ct_ftp_info, dir, *pskb);
+ update_nl_seq(seq, ct_ftp_info, dir, skb);
out:
spin_unlock_bh(&nf_ftp_lock);
return ret;
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c
index a8a9dfbe7a67..f23fd9598e19 100644
--- a/net/netfilter/nf_conntrack_h323_main.c
+++ b/net/netfilter/nf_conntrack_h323_main.c
@@ -47,27 +47,27 @@ MODULE_PARM_DESC(callforward_filter, "only create call forwarding expectations "
"(determined by routing information)");
/* Hooks for NAT */
-int (*set_h245_addr_hook) (struct sk_buff **pskb,
+int (*set_h245_addr_hook) (struct sk_buff *skb,
unsigned char **data, int dataoff,
H245_TransportAddress *taddr,
union nf_conntrack_address *addr, __be16 port)
__read_mostly;
-int (*set_h225_addr_hook) (struct sk_buff **pskb,
+int (*set_h225_addr_hook) (struct sk_buff *skb,
unsigned char **data, int dataoff,
TransportAddress *taddr,
union nf_conntrack_address *addr, __be16 port)
__read_mostly;
-int (*set_sig_addr_hook) (struct sk_buff **pskb,
+int (*set_sig_addr_hook) (struct sk_buff *skb,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data,
TransportAddress *taddr, int count) __read_mostly;
-int (*set_ras_addr_hook) (struct sk_buff **pskb,
+int (*set_ras_addr_hook) (struct sk_buff *skb,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data,
TransportAddress *taddr, int count) __read_mostly;
-int (*nat_rtp_rtcp_hook) (struct sk_buff **pskb,
+int (*nat_rtp_rtcp_hook) (struct sk_buff *skb,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
@@ -75,25 +75,25 @@ int (*nat_rtp_rtcp_hook) (struct sk_buff **pskb,
__be16 port, __be16 rtp_port,
struct nf_conntrack_expect *rtp_exp,
struct nf_conntrack_expect *rtcp_exp) __read_mostly;
-int (*nat_t120_hook) (struct sk_buff **pskb,
+int (*nat_t120_hook) (struct sk_buff *skb,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
H245_TransportAddress *taddr, __be16 port,
struct nf_conntrack_expect *exp) __read_mostly;
-int (*nat_h245_hook) (struct sk_buff **pskb,
+int (*nat_h245_hook) (struct sk_buff *skb,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
TransportAddress *taddr, __be16 port,
struct nf_conntrack_expect *exp) __read_mostly;
-int (*nat_callforwarding_hook) (struct sk_buff **pskb,
+int (*nat_callforwarding_hook) (struct sk_buff *skb,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
TransportAddress *taddr, __be16 port,
struct nf_conntrack_expect *exp) __read_mostly;
-int (*nat_q931_hook) (struct sk_buff **pskb,
+int (*nat_q931_hook) (struct sk_buff *skb,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, TransportAddress *taddr, int idx,
@@ -108,7 +108,7 @@ static struct nf_conntrack_helper nf_conntrack_helper_q931[];
static struct nf_conntrack_helper nf_conntrack_helper_ras[];
/****************************************************************************/
-static int get_tpkt_data(struct sk_buff **pskb, unsigned int protoff,
+static int get_tpkt_data(struct sk_buff *skb, unsigned int protoff,
struct nf_conn *ct, enum ip_conntrack_info ctinfo,
unsigned char **data, int *datalen, int *dataoff)
{
@@ -122,7 +122,7 @@ static int get_tpkt_data(struct sk_buff **pskb, unsigned int protoff,
int tpktoff;
/* Get TCP header */
- th = skb_header_pointer(*pskb, protoff, sizeof(_tcph), &_tcph);
+ th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
if (th == NULL)
return 0;
@@ -130,13 +130,13 @@ static int get_tpkt_data(struct sk_buff **pskb, unsigned int protoff,
tcpdataoff = protoff + th->doff * 4;
/* Get TCP data length */
- tcpdatalen = (*pskb)->len - tcpdataoff;
+ tcpdatalen = skb->len - tcpdataoff;
if (tcpdatalen <= 0) /* No TCP data */
goto clear_out;
if (*data == NULL) { /* first TPKT */
/* Get first TPKT pointer */
- tpkt = skb_header_pointer(*pskb, tcpdataoff, tcpdatalen,
+ tpkt = skb_header_pointer(skb, tcpdataoff, tcpdatalen,
h323_buffer);
BUG_ON(tpkt == NULL);
@@ -248,7 +248,7 @@ static int get_h245_addr(struct nf_conn *ct, unsigned char *data,
}
/****************************************************************************/
-static int expect_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct,
+static int expect_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
H245_TransportAddress *taddr)
@@ -297,7 +297,7 @@ static int expect_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct,
(nat_rtp_rtcp = rcu_dereference(nat_rtp_rtcp_hook)) &&
ct->status & IPS_NAT_MASK) {
/* NAT needed */
- ret = nat_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
+ ret = nat_rtp_rtcp(skb, ct, ctinfo, data, dataoff,
taddr, port, rtp_port, rtp_exp, rtcp_exp);
} else { /* Conntrack only */
if (nf_ct_expect_related(rtp_exp) == 0) {
@@ -321,7 +321,7 @@ static int expect_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct,
}
/****************************************************************************/
-static int expect_t120(struct sk_buff **pskb,
+static int expect_t120(struct sk_buff *skb,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
@@ -355,7 +355,7 @@ static int expect_t120(struct sk_buff **pskb,
(nat_t120 = rcu_dereference(nat_t120_hook)) &&
ct->status & IPS_NAT_MASK) {
/* NAT needed */
- ret = nat_t120(pskb, ct, ctinfo, data, dataoff, taddr,
+ ret = nat_t120(skb, ct, ctinfo, data, dataoff, taddr,
port, exp);
} else { /* Conntrack only */
if (nf_ct_expect_related(exp) == 0) {
@@ -371,7 +371,7 @@ static int expect_t120(struct sk_buff **pskb,
}
/****************************************************************************/
-static int process_h245_channel(struct sk_buff **pskb,
+static int process_h245_channel(struct sk_buff *skb,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
@@ -381,7 +381,7 @@ static int process_h245_channel(struct sk_buff **pskb,
if (channel->options & eH2250LogicalChannelParameters_mediaChannel) {
/* RTP */
- ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
+ ret = expect_rtp_rtcp(skb, ct, ctinfo, data, dataoff,
&channel->mediaChannel);
if (ret < 0)
return -1;
@@ -390,7 +390,7 @@ static int process_h245_channel(struct sk_buff **pskb,
if (channel->
options & eH2250LogicalChannelParameters_mediaControlChannel) {
/* RTCP */
- ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
+ ret = expect_rtp_rtcp(skb, ct, ctinfo, data, dataoff,
&channel->mediaControlChannel);
if (ret < 0)
return -1;
@@ -400,7 +400,7 @@ static int process_h245_channel(struct sk_buff **pskb,
}
/****************************************************************************/
-static int process_olc(struct sk_buff **pskb, struct nf_conn *ct,
+static int process_olc(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
OpenLogicalChannel *olc)
@@ -412,7 +412,7 @@ static int process_olc(struct sk_buff **pskb, struct nf_conn *ct,
if (olc->forwardLogicalChannelParameters.multiplexParameters.choice ==
eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)
{
- ret = process_h245_channel(pskb, ct, ctinfo, data, dataoff,
+ ret = process_h245_channel(skb, ct, ctinfo, data, dataoff,
&olc->
forwardLogicalChannelParameters.
multiplexParameters.
@@ -430,7 +430,7 @@ static int process_olc(struct sk_buff **pskb, struct nf_conn *ct,
eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters))
{
ret =
- process_h245_channel(pskb, ct, ctinfo, data, dataoff,
+ process_h245_channel(skb, ct, ctinfo, data, dataoff,
&olc->
reverseLogicalChannelParameters.
multiplexParameters.
@@ -448,7 +448,7 @@ static int process_olc(struct sk_buff **pskb, struct nf_conn *ct,
t120.choice == eDataProtocolCapability_separateLANStack &&
olc->separateStack.networkAddress.choice ==
eNetworkAccessParameters_networkAddress_localAreaAddress) {
- ret = expect_t120(pskb, ct, ctinfo, data, dataoff,
+ ret = expect_t120(skb, ct, ctinfo, data, dataoff,
&olc->separateStack.networkAddress.
localAreaAddress);
if (ret < 0)
@@ -459,7 +459,7 @@ static int process_olc(struct sk_buff **pskb, struct nf_conn *ct,
}
/****************************************************************************/
-static int process_olca(struct sk_buff **pskb, struct nf_conn *ct,
+static int process_olca(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
OpenLogicalChannelAck *olca)
@@ -477,7 +477,7 @@ static int process_olca(struct sk_buff **pskb, struct nf_conn *ct,
choice ==
eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters))
{
- ret = process_h245_channel(pskb, ct, ctinfo, data, dataoff,
+ ret = process_h245_channel(skb, ct, ctinfo, data, dataoff,
&olca->
reverseLogicalChannelParameters.
multiplexParameters.
@@ -496,7 +496,7 @@ static int process_olca(struct sk_buff **pskb, struct nf_conn *ct,
if (ack->options &
eH2250LogicalChannelAckParameters_mediaChannel) {
/* RTP */
- ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
+ ret = expect_rtp_rtcp(skb, ct, ctinfo, data, dataoff,
&ack->mediaChannel);
if (ret < 0)
return -1;
@@ -505,7 +505,7 @@ static int process_olca(struct sk_buff **pskb, struct nf_conn *ct,
if (ack->options &
eH2250LogicalChannelAckParameters_mediaControlChannel) {
/* RTCP */
- ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
+ ret = expect_rtp_rtcp(skb, ct, ctinfo, data, dataoff,
&ack->mediaControlChannel);
if (ret < 0)
return -1;
@@ -515,7 +515,7 @@ static int process_olca(struct sk_buff **pskb, struct nf_conn *ct,
if ((olca->options & eOpenLogicalChannelAck_separateStack) &&
olca->separateStack.networkAddress.choice ==
eNetworkAccessParameters_networkAddress_localAreaAddress) {
- ret = expect_t120(pskb, ct, ctinfo, data, dataoff,
+ ret = expect_t120(skb, ct, ctinfo, data, dataoff,
&olca->separateStack.networkAddress.
localAreaAddress);
if (ret < 0)
@@ -526,7 +526,7 @@ static int process_olca(struct sk_buff **pskb, struct nf_conn *ct,
}
/****************************************************************************/
-static int process_h245(struct sk_buff **pskb, struct nf_conn *ct,
+static int process_h245(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
MultimediaSystemControlMessage *mscm)
@@ -535,7 +535,7 @@ static int process_h245(struct sk_buff **pskb, struct nf_conn *ct,
case eMultimediaSystemControlMessage_request:
if (mscm->request.choice ==
eRequestMessage_openLogicalChannel) {
- return process_olc(pskb, ct, ctinfo, data, dataoff,
+ return process_olc(skb, ct, ctinfo, data, dataoff,
&mscm->request.openLogicalChannel);
}
pr_debug("nf_ct_h323: H.245 Request %d\n",
@@ -544,7 +544,7 @@ static int process_h245(struct sk_buff **pskb, struct nf_conn *ct,
case eMultimediaSystemControlMessage_response:
if (mscm->response.choice ==
eResponseMessage_openLogicalChannelAck) {
- return process_olca(pskb, ct, ctinfo, data, dataoff,
+ return process_olca(skb, ct, ctinfo, data, dataoff,
&mscm->response.
openLogicalChannelAck);
}
@@ -560,7 +560,7 @@ static int process_h245(struct sk_buff **pskb, struct nf_conn *ct,
}
/****************************************************************************/
-static int h245_help(struct sk_buff **pskb, unsigned int protoff,
+static int h245_help(struct sk_buff *skb, unsigned int protoff,
struct nf_conn *ct, enum ip_conntrack_info ctinfo)
{
static MultimediaSystemControlMessage mscm;
@@ -574,12 +574,12 @@ static int h245_help(struct sk_buff **pskb, unsigned int protoff,
ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
return NF_ACCEPT;
}
- pr_debug("nf_ct_h245: skblen = %u\n", (*pskb)->len);
+ pr_debug("nf_ct_h245: skblen = %u\n", skb->len);
spin_lock_bh(&nf_h323_lock);
/* Process each TPKT */
- while (get_tpkt_data(pskb, protoff, ct, ctinfo,
+ while (get_tpkt_data(skb, protoff, ct, ctinfo,
&data, &datalen, &dataoff)) {
pr_debug("nf_ct_h245: TPKT len=%d ", datalen);
NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
@@ -596,7 +596,7 @@ static int h245_help(struct sk_buff **pskb, unsigned int protoff,
}
/* Process H.245 signal */
- if (process_h245(pskb, ct, ctinfo, &data, dataoff, &mscm) < 0)
+ if (process_h245(skb, ct, ctinfo, &data, dataoff, &mscm) < 0)
goto drop;
}
@@ -654,7 +654,7 @@ int get_h225_addr(struct nf_conn *ct, unsigned char *data,
}
/****************************************************************************/
-static int expect_h245(struct sk_buff **pskb, struct nf_conn *ct,
+static int expect_h245(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
TransportAddress *taddr)
@@ -687,7 +687,7 @@ static int expect_h245(struct sk_buff **pskb, struct nf_conn *ct,
(nat_h245 = rcu_dereference(nat_h245_hook)) &&
ct->status & IPS_NAT_MASK) {
/* NAT needed */
- ret = nat_h245(pskb, ct, ctinfo, data, dataoff, taddr,
+ ret = nat_h245(skb, ct, ctinfo, data, dataoff, taddr,
port, exp);
} else { /* Conntrack only */
if (nf_ct_expect_related(exp) == 0) {
@@ -758,7 +758,7 @@ static int callforward_do_filter(union nf_conntrack_address *src,
}
/****************************************************************************/
-static int expect_callforwarding(struct sk_buff **pskb,
+static int expect_callforwarding(struct sk_buff *skb,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
@@ -798,7 +798,7 @@ static int expect_callforwarding(struct sk_buff **pskb,
(nat_callforwarding = rcu_dereference(nat_callforwarding_hook)) &&
ct->status & IPS_NAT_MASK) {
/* Need NAT */
- ret = nat_callforwarding(pskb, ct, ctinfo, data, dataoff,
+ ret = nat_callforwarding(skb, ct, ctinfo, data, dataoff,
taddr, port, exp);
} else { /* Conntrack only */
if (nf_ct_expect_related(exp) == 0) {
@@ -814,7 +814,7 @@ static int expect_callforwarding(struct sk_buff **pskb,
}
/****************************************************************************/
-static int process_setup(struct sk_buff **pskb, struct nf_conn *ct,
+static int process_setup(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
Setup_UUIE *setup)
@@ -829,7 +829,7 @@ static int process_setup(struct sk_buff **pskb, struct nf_conn *ct,
pr_debug("nf_ct_q931: Setup\n");
if (setup->options & eSetup_UUIE_h245Address) {
- ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
+ ret = expect_h245(skb, ct, ctinfo, data, dataoff,
&setup->h245Address);
if (ret < 0)
return -1;
@@ -846,7 +846,7 @@ static int process_setup(struct sk_buff **pskb, struct nf_conn *ct,
NIP6(*(struct in6_addr *)&addr), ntohs(port),
NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.src.u3),
ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port));
- ret = set_h225_addr(pskb, data, dataoff,
+ ret = set_h225_addr(skb, data, dataoff,
&setup->destCallSignalAddress,
&ct->tuplehash[!dir].tuple.src.u3,
ct->tuplehash[!dir].tuple.src.u.tcp.port);
@@ -864,7 +864,7 @@ static int process_setup(struct sk_buff **pskb, struct nf_conn *ct,
NIP6(*(struct in6_addr *)&addr), ntohs(port),
NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.dst.u3),
ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port));
- ret = set_h225_addr(pskb, data, dataoff,
+ ret = set_h225_addr(skb, data, dataoff,
&setup->sourceCallSignalAddress,
&ct->tuplehash[!dir].tuple.dst.u3,
ct->tuplehash[!dir].tuple.dst.u.tcp.port);
@@ -874,7 +874,7 @@ static int process_setup(struct sk_buff **pskb, struct nf_conn *ct,
if (setup->options & eSetup_UUIE_fastStart) {
for (i = 0; i < setup->fastStart.count; i++) {
- ret = process_olc(pskb, ct, ctinfo, data, dataoff,
+ ret = process_olc(skb, ct, ctinfo, data, dataoff,
&setup->fastStart.item[i]);
if (ret < 0)
return -1;
@@ -885,7 +885,7 @@ static int process_setup(struct sk_buff **pskb, struct nf_conn *ct,
}
/****************************************************************************/
-static int process_callproceeding(struct sk_buff **pskb,
+static int process_callproceeding(struct sk_buff *skb,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
@@ -897,7 +897,7 @@ static int process_callproceeding(struct sk_buff **pskb,
pr_debug("nf_ct_q931: CallProceeding\n");
if (callproc->options & eCallProceeding_UUIE_h245Address) {
- ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
+ ret = expect_h245(skb, ct, ctinfo, data, dataoff,
&callproc->h245Address);
if (ret < 0)
return -1;
@@ -905,7 +905,7 @@ static int process_callproceeding(struct sk_buff **pskb,
if (callproc->options & eCallProceeding_UUIE_fastStart) {
for (i = 0; i < callproc->fastStart.count; i++) {
- ret = process_olc(pskb, ct, ctinfo, data, dataoff,
+ ret = process_olc(skb, ct, ctinfo, data, dataoff,
&callproc->fastStart.item[i]);
if (ret < 0)
return -1;
@@ -916,7 +916,7 @@ static int process_callproceeding(struct sk_buff **pskb,
}
/****************************************************************************/
-static int process_connect(struct sk_buff **pskb, struct nf_conn *ct,
+static int process_connect(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
Connect_UUIE *connect)
@@ -927,7 +927,7 @@ static int process_connect(struct sk_buff **pskb, struct nf_conn *ct,
pr_debug("nf_ct_q931: Connect\n");
if (connect->options & eConnect_UUIE_h245Address) {
- ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
+ ret = expect_h245(skb, ct, ctinfo, data, dataoff,
&connect->h245Address);
if (ret < 0)
return -1;
@@ -935,7 +935,7 @@ static int process_connect(struct sk_buff **pskb, struct nf_conn *ct,
if (connect->options & eConnect_UUIE_fastStart) {
for (i = 0; i < connect->fastStart.count; i++) {
- ret = process_olc(pskb, ct, ctinfo, data, dataoff,
+ ret = process_olc(skb, ct, ctinfo, data, dataoff,
&connect->fastStart.item[i]);
if (ret < 0)
return -1;
@@ -946,7 +946,7 @@ static int process_connect(struct sk_buff **pskb, struct nf_conn *ct,
}
/****************************************************************************/
-static int process_alerting(struct sk_buff **pskb, struct nf_conn *ct,
+static int process_alerting(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
Alerting_UUIE *alert)
@@ -957,7 +957,7 @@ static int process_alerting(struct sk_buff **pskb, struct nf_conn *ct,
pr_debug("nf_ct_q931: Alerting\n");
if (alert->options & eAlerting_UUIE_h245Address) {
- ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
+ ret = expect_h245(skb, ct, ctinfo, data, dataoff,
&alert->h245Address);
if (ret < 0)
return -1;
@@ -965,7 +965,7 @@ static int process_alerting(struct sk_buff **pskb, struct nf_conn *ct,
if (alert->options & eAlerting_UUIE_fastStart) {
for (i = 0; i < alert->fastStart.count; i++) {
- ret = process_olc(pskb, ct, ctinfo, data, dataoff,
+ ret = process_olc(skb, ct, ctinfo, data, dataoff,
&alert->fastStart.item[i]);
if (ret < 0)
return -1;
@@ -976,7 +976,7 @@ static int process_alerting(struct sk_buff **pskb, struct nf_conn *ct,
}
/****************************************************************************/
-static int process_facility(struct sk_buff **pskb, struct nf_conn *ct,
+static int process_facility(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
Facility_UUIE *facility)
@@ -988,7 +988,7 @@ static int process_facility(struct sk_buff **pskb, struct nf_conn *ct,
if (facility->reason.choice == eFacilityReason_callForwarded) {
if (facility->options & eFacility_UUIE_alternativeAddress)
- return expect_callforwarding(pskb, ct, ctinfo, data,
+ return expect_callforwarding(skb, ct, ctinfo, data,
dataoff,
&facility->
alternativeAddress);
@@ -996,7 +996,7 @@ static int process_facility(struct sk_buff **pskb, struct nf_conn *ct,
}
if (facility->options & eFacility_UUIE_h245Address) {
- ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
+ ret = expect_h245(skb, ct, ctinfo, data, dataoff,
&facility->h245Address);
if (ret < 0)
return -1;
@@ -1004,7 +1004,7 @@ static int process_facility(struct sk_buff **pskb, struct nf_conn *ct,
if (facility->options & eFacility_UUIE_fastStart) {
for (i = 0; i < facility->fastStart.count; i++) {
- ret = process_olc(pskb, ct, ctinfo, data, dataoff,
+ ret = process_olc(skb, ct, ctinfo, data, dataoff,
&facility->fastStart.item[i]);
if (ret < 0)
return -1;
@@ -1015,7 +1015,7 @@ static int process_facility(struct sk_buff **pskb, struct nf_conn *ct,
}
/****************************************************************************/
-static int process_progress(struct sk_buff **pskb, struct nf_conn *ct,
+static int process_progress(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
Progress_UUIE *progress)
@@ -1026,7 +1026,7 @@ static int process_progress(struct sk_buff **pskb, struct nf_conn *ct,
pr_debug("nf_ct_q931: Progress\n");
if (progress->options & eProgress_UUIE_h245Address) {
- ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
+ ret = expect_h245(skb, ct, ctinfo, data, dataoff,
&progress->h245Address);
if (ret < 0)
return -1;
@@ -1034,7 +1034,7 @@ static int process_progress(struct sk_buff **pskb, struct nf_conn *ct,
if (progress->options & eProgress_UUIE_fastStart) {
for (i = 0; i < progress->fastStart.count; i++) {
- ret = process_olc(pskb, ct, ctinfo, data, dataoff,
+ ret = process_olc(skb, ct, ctinfo, data, dataoff,
&progress->fastStart.item[i]);
if (ret < 0)
return -1;
@@ -1045,7 +1045,7 @@ static int process_progress(struct sk_buff **pskb, struct nf_conn *ct,
}
/****************************************************************************/
-static int process_q931(struct sk_buff **pskb, struct nf_conn *ct,
+static int process_q931(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff, Q931 *q931)
{
@@ -1055,28 +1055,28 @@ static int process_q931(struct sk_buff **pskb, struct nf_conn *ct,
switch (pdu->h323_message_body.choice) {
case eH323_UU_PDU_h323_message_body_setup:
- ret = process_setup(pskb, ct, ctinfo, data, dataoff,
+ ret = process_setup(skb, ct, ctinfo, data, dataoff,
&pdu->h323_message_body.setup);
break;
case eH323_UU_PDU_h323_message_body_callProceeding:
- ret = process_callproceeding(pskb, ct, ctinfo, data, dataoff,
+ ret = process_callproceeding(skb, ct, ctinfo, data, dataoff,
&pdu->h323_message_body.
callProceeding);
break;
case eH323_UU_PDU_h323_message_body_connect:
- ret = process_connect(pskb, ct, ctinfo, data, dataoff,
+ ret = process_connect(skb, ct, ctinfo, data, dataoff,
&pdu->h323_message_body.connect);
break;
case eH323_UU_PDU_h323_message_body_alerting:
- ret = process_alerting(pskb, ct, ctinfo, data, dataoff,
+ ret = process_alerting(skb, ct, ctinfo, data, dataoff,
&pdu->h323_message_body.alerting);
break;
case eH323_UU_PDU_h323_message_body_facility:
- ret = process_facility(pskb, ct, ctinfo, data, dataoff,
+ ret = process_facility(skb, ct, ctinfo, data, dataoff,
&pdu->h323_message_body.facility);
break;
case eH323_UU_PDU_h323_message_body_progress:
- ret = process_progress(pskb, ct, ctinfo, data, dataoff,
+ ret = process_progress(skb, ct, ctinfo, data, dataoff,
&pdu->h323_message_body.progress);
break;
default:
@@ -1090,7 +1090,7 @@ static int process_q931(struct sk_buff **pskb, struct nf_conn *ct,
if (pdu->options & eH323_UU_PDU_h245Control) {
for (i = 0; i < pdu->h245Control.count; i++) {
- ret = process_h245(pskb, ct, ctinfo, data, dataoff,
+ ret = process_h245(skb, ct, ctinfo, data, dataoff,
&pdu->h245Control.item[i]);
if (ret < 0)
return -1;
@@ -1101,7 +1101,7 @@ static int process_q931(struct sk_buff **pskb, struct nf_conn *ct,
}
/****************************************************************************/
-static int q931_help(struct sk_buff **pskb, unsigned int protoff,
+static int q931_help(struct sk_buff *skb, unsigned int protoff,
struct nf_conn *ct, enum ip_conntrack_info ctinfo)
{
static Q931 q931;
@@ -1115,12 +1115,12 @@ static int q931_help(struct sk_buff **pskb, unsigned int protoff,
ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
return NF_ACCEPT;
}
- pr_debug("nf_ct_q931: skblen = %u\n", (*pskb)->len);
+ pr_debug("nf_ct_q931: skblen = %u\n", skb->len);
spin_lock_bh(&nf_h323_lock);
/* Process each TPKT */
- while (get_tpkt_data(pskb, protoff, ct, ctinfo,
+ while (get_tpkt_data(skb, protoff, ct, ctinfo,
&data, &datalen, &dataoff)) {
pr_debug("nf_ct_q931: TPKT len=%d ", datalen);
NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
@@ -1136,7 +1136,7 @@ static int q931_help(struct sk_buff **pskb, unsigned int protoff,
}
/* Process Q.931 signal */
- if (process_q931(pskb, ct, ctinfo, &data, dataoff, &q931) < 0)
+ if (process_q931(skb, ct, ctinfo, &data, dataoff, &q931) < 0)
goto drop;
}
@@ -1177,20 +1177,20 @@ static struct nf_conntrack_helper nf_conntrack_helper_q931[] __read_mostly = {
};
/****************************************************************************/
-static unsigned char *get_udp_data(struct sk_buff **pskb, unsigned int protoff,
+static unsigned char *get_udp_data(struct sk_buff *skb, unsigned int protoff,
int *datalen)
{
struct udphdr _uh, *uh;
int dataoff;
- uh = skb_header_pointer(*pskb, protoff, sizeof(_uh), &_uh);
+ uh = skb_header_pointer(skb, protoff, sizeof(_uh), &_uh);
if (uh == NULL)
return NULL;
dataoff = protoff + sizeof(_uh);
- if (dataoff >= (*pskb)->len)
+ if (dataoff >= skb->len)
return NULL;
- *datalen = (*pskb)->len - dataoff;
- return skb_header_pointer(*pskb, dataoff, *datalen, h323_buffer);
+ *datalen = skb->len - dataoff;
+ return skb_header_pointer(skb, dataoff, *datalen, h323_buffer);
}
/****************************************************************************/
@@ -1227,7 +1227,7 @@ static int set_expect_timeout(struct nf_conntrack_expect *exp,
}
/****************************************************************************/
-static int expect_q931(struct sk_buff **pskb, struct nf_conn *ct,
+static int expect_q931(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data,
TransportAddress *taddr, int count)
@@ -1265,7 +1265,7 @@ static int expect_q931(struct sk_buff **pskb, struct nf_conn *ct,
nat_q931 = rcu_dereference(nat_q931_hook);
if (nat_q931 && ct->status & IPS_NAT_MASK) { /* Need NAT */
- ret = nat_q931(pskb, ct, ctinfo, data, taddr, i, port, exp);
+ ret = nat_q931(skb, ct, ctinfo, data, taddr, i, port, exp);
} else { /* Conntrack only */
if (nf_ct_expect_related(exp) == 0) {
pr_debug("nf_ct_ras: expect Q.931 ");
@@ -1283,7 +1283,7 @@ static int expect_q931(struct sk_buff **pskb, struct nf_conn *ct,
}
/****************************************************************************/
-static int process_grq(struct sk_buff **pskb, struct nf_conn *ct,
+static int process_grq(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, GatekeeperRequest *grq)
{
@@ -1293,13 +1293,13 @@ static int process_grq(struct sk_buff **pskb, struct nf_conn *ct,
set_ras_addr = rcu_dereference(set_ras_addr_hook);
if (set_ras_addr && ct->status & IPS_NAT_MASK) /* NATed */
- return set_ras_addr(pskb, ct, ctinfo, data,
+ return set_ras_addr(skb, ct, ctinfo, data,
&grq->rasAddress, 1);
return 0;
}
/****************************************************************************/
-static int process_gcf(struct sk_buff **pskb, struct nf_conn *ct,
+static int process_gcf(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, GatekeeperConfirm *gcf)
{
@@ -1343,7 +1343,7 @@ static int process_gcf(struct sk_buff **pskb, struct nf_conn *ct,
}
/****************************************************************************/
-static int process_rrq(struct sk_buff **pskb, struct nf_conn *ct,
+static int process_rrq(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, RegistrationRequest *rrq)
{
@@ -1353,7 +1353,7 @@ static int process_rrq(struct sk_buff **pskb, struct nf_conn *ct,
pr_debug("nf_ct_ras: RRQ\n");
- ret = expect_q931(pskb, ct, ctinfo, data,
+ ret = expect_q931(skb, ct, ctinfo, data,
rrq->callSignalAddress.item,
rrq->callSignalAddress.count);
if (ret < 0)
@@ -1361,7 +1361,7 @@ static int process_rrq(struct sk_buff **pskb, struct nf_conn *ct,
set_ras_addr = rcu_dereference(set_ras_addr_hook);
if (set_ras_addr && ct->status & IPS_NAT_MASK) {
- ret = set_ras_addr(pskb, ct, ctinfo, data,
+ ret = set_ras_addr(skb, ct, ctinfo, data,
rrq->rasAddress.item,
rrq->rasAddress.count);
if (ret < 0)
@@ -1378,7 +1378,7 @@ static int process_rrq(struct sk_buff **pskb, struct nf_conn *ct,
}
/****************************************************************************/
-static int process_rcf(struct sk_buff **pskb, struct nf_conn *ct,
+static int process_rcf(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, RegistrationConfirm *rcf)
{
@@ -1392,7 +1392,7 @@ static int process_rcf(struct sk_buff **pskb, struct nf_conn *ct,
set_sig_addr = rcu_dereference(set_sig_addr_hook);
if (set_sig_addr && ct->status & IPS_NAT_MASK) {
- ret = set_sig_addr(pskb, ct, ctinfo, data,
+ ret = set_sig_addr(skb, ct, ctinfo, data,
rcf->callSignalAddress.item,
rcf->callSignalAddress.count);
if (ret < 0)
@@ -1407,7 +1407,7 @@ static int process_rcf(struct sk_buff **pskb, struct nf_conn *ct,
if (info->timeout > 0) {
pr_debug("nf_ct_ras: set RAS connection timeout to "
"%u seconds\n", info->timeout);
- nf_ct_refresh(ct, *pskb, info->timeout * HZ);
+ nf_ct_refresh(ct, skb, info->timeout * HZ);
/* Set expect timeout */
read_lock_bh(&nf_conntrack_lock);
@@ -1427,7 +1427,7 @@ static int process_rcf(struct sk_buff **pskb, struct nf_conn *ct,
}
/****************************************************************************/
-static int process_urq(struct sk_buff **pskb, struct nf_conn *ct,
+static int process_urq(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, UnregistrationRequest *urq)
{
@@ -1440,7 +1440,7 @@ static int process_urq(struct sk_buff **pskb, struct nf_conn *ct,
set_sig_addr = rcu_dereference(set_sig_addr_hook);
if (set_sig_addr && ct->status & IPS_NAT_MASK) {
- ret = set_sig_addr(pskb, ct, ctinfo, data,
+ ret = set_sig_addr(skb, ct, ctinfo, data,
urq->callSignalAddress.item,
urq->callSignalAddress.count);
if (ret < 0)
@@ -1453,13 +1453,13 @@ static int process_urq(struct sk_buff **pskb, struct nf_conn *ct,
info->sig_port[!dir] = 0;
/* Give it 30 seconds for UCF or URJ */
- nf_ct_refresh(ct, *pskb, 30 * HZ);
+ nf_ct_refresh(ct, skb, 30 * HZ);
return 0;
}
/****************************************************************************/
-static int process_arq(struct sk_buff **pskb, struct nf_conn *ct,
+static int process_arq(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, AdmissionRequest *arq)
{
@@ -1479,7 +1479,7 @@ static int process_arq(struct sk_buff **pskb, struct nf_conn *ct,
port == info->sig_port[dir] &&
set_h225_addr && ct->status & IPS_NAT_MASK) {
/* Answering ARQ */
- return set_h225_addr(pskb, data, 0,
+ return set_h225_addr(skb, data, 0,
&arq->destCallSignalAddress,
&ct->tuplehash[!dir].tuple.dst.u3,
info->sig_port[!dir]);
@@ -1491,7 +1491,7 @@ static int process_arq(struct sk_buff **pskb, struct nf_conn *ct,
!memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) &&
set_h225_addr && ct->status & IPS_NAT_MASK) {
/* Calling ARQ */
- return set_h225_addr(pskb, data, 0,
+ return set_h225_addr(skb, data, 0,
&arq->srcCallSignalAddress,
&ct->tuplehash[!dir].tuple.dst.u3,
port);
@@ -1501,7 +1501,7 @@ static int process_arq(struct sk_buff **pskb, struct nf_conn *ct,
}
/****************************************************************************/
-static int process_acf(struct sk_buff **pskb, struct nf_conn *ct,
+static int process_acf(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, AdmissionConfirm *acf)
{
@@ -1522,7 +1522,7 @@ static int process_acf(struct sk_buff **pskb, struct nf_conn *ct,
/* Answering ACF */
set_sig_addr = rcu_dereference(set_sig_addr_hook);
if (set_sig_addr && ct->status & IPS_NAT_MASK)
- return set_sig_addr(pskb, ct, ctinfo, data,
+ return set_sig_addr(skb, ct, ctinfo, data,
&acf->destCallSignalAddress, 1);
return 0;
}
@@ -1548,7 +1548,7 @@ static int process_acf(struct sk_buff **pskb, struct nf_conn *ct,
}
/****************************************************************************/
-static int process_lrq(struct sk_buff **pskb, struct nf_conn *ct,
+static int process_lrq(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, LocationRequest *lrq)
{
@@ -1558,13 +1558,13 @@ static int process_lrq(struct sk_buff **pskb, struct nf_conn *ct,
set_ras_addr = rcu_dereference(set_ras_addr_hook);
if (set_ras_addr && ct->status & IPS_NAT_MASK)
- return set_ras_addr(pskb, ct, ctinfo, data,
+ return set_ras_addr(skb, ct, ctinfo, data,
&lrq->replyAddress, 1);
return 0;
}
/****************************************************************************/
-static int process_lcf(struct sk_buff **pskb, struct nf_conn *ct,
+static int process_lcf(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, LocationConfirm *lcf)
{
@@ -1603,7 +1603,7 @@ static int process_lcf(struct sk_buff **pskb, struct nf_conn *ct,
}
/****************************************************************************/
-static int process_irr(struct sk_buff **pskb, struct nf_conn *ct,
+static int process_irr(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, InfoRequestResponse *irr)
{
@@ -1615,7 +1615,7 @@ static int process_irr(struct sk_buff **pskb, struct nf_conn *ct,
set_ras_addr = rcu_dereference(set_ras_addr_hook);
if (set_ras_addr && ct->status & IPS_NAT_MASK) {
- ret = set_ras_addr(pskb, ct, ctinfo, data,
+ ret = set_ras_addr(skb, ct, ctinfo, data,
&irr->rasAddress, 1);
if (ret < 0)
return -1;
@@ -1623,7 +1623,7 @@ static int process_irr(struct sk_buff **pskb, struct nf_conn *ct,
set_sig_addr = rcu_dereference(set_sig_addr_hook);
if (set_sig_addr && ct->status & IPS_NAT_MASK) {
- ret = set_sig_addr(pskb, ct, ctinfo, data,
+ ret = set_sig_addr(skb, ct, ctinfo, data,
irr->callSignalAddress.item,
irr->callSignalAddress.count);
if (ret < 0)
@@ -1634,40 +1634,40 @@ static int process_irr(struct sk_buff **pskb, struct nf_conn *ct,
}
/****************************************************************************/
-static int process_ras(struct sk_buff **pskb, struct nf_conn *ct,
+static int process_ras(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, RasMessage *ras)
{
switch (ras->choice) {
case eRasMessage_gatekeeperRequest:
- return process_grq(pskb, ct, ctinfo, data,
+ return process_grq(skb, ct, ctinfo, data,
&ras->gatekeeperRequest);
case eRasMessage_gatekeeperConfirm:
- return process_gcf(pskb, ct, ctinfo, data,
+ return process_gcf(skb, ct, ctinfo, data,
&ras->gatekeeperConfirm);
case eRasMessage_registrationRequest:
- return process_rrq(pskb, ct, ctinfo, data,
+ return process_rrq(skb, ct, ctinfo, data,
&ras->registrationRequest);
case eRasMessage_registrationConfirm:
- return process_rcf(pskb, ct, ctinfo, data,
+ return process_rcf(skb, ct, ctinfo, data,
&ras->registrationConfirm);
case eRasMessage_unregistrationRequest:
- return process_urq(pskb, ct, ctinfo, data,
+ return process_urq(skb, ct, ctinfo, data,
&ras->unregistrationRequest);
case eRasMessage_admissionRequest:
- return process_arq(pskb, ct, ctinfo, data,
+ return process_arq(skb, ct, ctinfo, data,
&ras->admissionRequest);
case eRasMessage_admissionConfirm:
- return process_acf(pskb, ct, ctinfo, data,
+ return process_acf(skb, ct, ctinfo, data,
&ras->admissionConfirm);
case eRasMessage_locationRequest:
- return process_lrq(pskb, ct, ctinfo, data,
+ return process_lrq(skb, ct, ctinfo, data,
&ras->locationRequest);
case eRasMessage_locationConfirm:
- return process_lcf(pskb, ct, ctinfo, data,
+ return process_lcf(skb, ct, ctinfo, data,
&ras->locationConfirm);
case eRasMessage_infoRequestResponse:
- return process_irr(pskb, ct, ctinfo, data,
+ return process_irr(skb, ct, ctinfo, data,
&ras->infoRequestResponse);
default:
pr_debug("nf_ct_ras: RAS message %d\n", ras->choice);
@@ -1678,7 +1678,7 @@ static int process_ras(struct sk_buff **pskb, struct nf_conn *ct,
}
/****************************************************************************/
-static int ras_help(struct sk_buff **pskb, unsigned int protoff,
+static int ras_help(struct sk_buff *skb, unsigned int protoff,
struct nf_conn *ct, enum ip_conntrack_info ctinfo)
{
static RasMessage ras;
@@ -1686,12 +1686,12 @@ static int ras_help(struct sk_buff **pskb, unsigned int protoff,
int datalen = 0;
int ret;
- pr_debug("nf_ct_ras: skblen = %u\n", (*pskb)->len);
+ pr_debug("nf_ct_ras: skblen = %u\n", skb->len);
spin_lock_bh(&nf_h323_lock);
/* Get UDP data */
- data = get_udp_data(pskb, protoff, &datalen);
+ data = get_udp_data(skb, protoff, &datalen);
if (data == NULL)
goto accept;
pr_debug("nf_ct_ras: RAS message len=%d ", datalen);
@@ -1707,7 +1707,7 @@ static int ras_help(struct sk_buff **pskb, unsigned int protoff,
}
/* Process RAS message */
- if (process_ras(pskb, ct, ctinfo, &data, &ras) < 0)
+ if (process_ras(skb, ct, ctinfo, &data, &ras) < 0)
goto drop;
accept:
diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c
index 1562ca97a349..dfaed4ba83cd 100644
--- a/net/netfilter/nf_conntrack_irc.c
+++ b/net/netfilter/nf_conntrack_irc.c
@@ -30,7 +30,7 @@ static unsigned int dcc_timeout __read_mostly = 300;
static char *irc_buffer;
static DEFINE_SPINLOCK(irc_buffer_lock);
-unsigned int (*nf_nat_irc_hook)(struct sk_buff **pskb,
+unsigned int (*nf_nat_irc_hook)(struct sk_buff *skb,
enum ip_conntrack_info ctinfo,
unsigned int matchoff,
unsigned int matchlen,
@@ -89,7 +89,7 @@ static int parse_dcc(char *data, char *data_end, u_int32_t *ip,
return 0;
}
-static int help(struct sk_buff **pskb, unsigned int protoff,
+static int help(struct sk_buff *skb, unsigned int protoff,
struct nf_conn *ct, enum ip_conntrack_info ctinfo)
{
unsigned int dataoff;
@@ -116,22 +116,22 @@ static int help(struct sk_buff **pskb, unsigned int protoff,
return NF_ACCEPT;
/* Not a full tcp header? */
- th = skb_header_pointer(*pskb, protoff, sizeof(_tcph), &_tcph);
+ th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
if (th == NULL)
return NF_ACCEPT;
/* No data? */
dataoff = protoff + th->doff*4;
- if (dataoff >= (*pskb)->len)
+ if (dataoff >= skb->len)
return NF_ACCEPT;
spin_lock_bh(&irc_buffer_lock);
- ib_ptr = skb_header_pointer(*pskb, dataoff, (*pskb)->len - dataoff,
+ ib_ptr = skb_header_pointer(skb, dataoff, skb->len - dataoff,
irc_buffer);
BUG_ON(ib_ptr == NULL);
data = ib_ptr;
- data_limit = ib_ptr + (*pskb)->len - dataoff;
+ data_limit = ib_ptr + skb->len - dataoff;
/* strlen("\1DCC SENT t AAAAAAAA P\1\n")=24
* 5+MINMATCHLEN+strlen("t AAAAAAAA P\1\n")=14 */
@@ -143,7 +143,7 @@ static int help(struct sk_buff **pskb, unsigned int protoff,
data += 5;
/* we have at least (19+MINMATCHLEN)-5 bytes valid data left */
- iph = ip_hdr(*pskb);
+ iph = ip_hdr(skb);
pr_debug("DCC found in master %u.%u.%u.%u:%u %u.%u.%u.%u:%u\n",
NIPQUAD(iph->saddr), ntohs(th->source),
NIPQUAD(iph->daddr), ntohs(th->dest));
@@ -193,7 +193,7 @@ static int help(struct sk_buff **pskb, unsigned int protoff,
nf_nat_irc = rcu_dereference(nf_nat_irc_hook);
if (nf_nat_irc && ct->status & IPS_NAT_MASK)
- ret = nf_nat_irc(pskb, ctinfo,
+ ret = nf_nat_irc(skb, ctinfo,
addr_beg_p - ib_ptr,
addr_end_p - addr_beg_p,
exp);
diff --git a/net/netfilter/nf_conntrack_netbios_ns.c b/net/netfilter/nf_conntrack_netbios_ns.c
index 1d59fabeb5f7..9810d81e2a06 100644
--- a/net/netfilter/nf_conntrack_netbios_ns.c
+++ b/net/netfilter/nf_conntrack_netbios_ns.c
@@ -42,17 +42,17 @@ static unsigned int timeout __read_mostly = 3;
module_param(timeout, uint, 0400);
MODULE_PARM_DESC(timeout, "timeout for master connection/replies in seconds");
-static int help(struct sk_buff **pskb, unsigned int protoff,
+static int help(struct sk_buff *skb, unsigned int protoff,
struct nf_conn *ct, enum ip_conntrack_info ctinfo)
{
struct nf_conntrack_expect *exp;
- struct iphdr *iph = ip_hdr(*pskb);
- struct rtable *rt = (struct rtable *)(*pskb)->dst;
+ struct iphdr *iph = ip_hdr(skb);
+ struct rtable *rt = (struct rtable *)skb->dst;
struct in_device *in_dev;
__be32 mask = 0;
/* we're only interested in locally generated packets */
- if ((*pskb)->sk == NULL)
+ if (skb->sk == NULL)
goto out;
if (rt == NULL || !(rt->rt_flags & RTCF_BROADCAST))
goto out;
@@ -91,7 +91,7 @@ static int help(struct sk_buff **pskb, unsigned int protoff,
nf_ct_expect_related(exp);
nf_ct_expect_put(exp);
- nf_ct_refresh(ct, *pskb, timeout * HZ);
+ nf_ct_refresh(ct, skb, timeout * HZ);
out:
return NF_ACCEPT;
}
diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c
index b0804199ab59..099b6df3e2b5 100644
--- a/net/netfilter/nf_conntrack_pptp.c
+++ b/net/netfilter/nf_conntrack_pptp.c
@@ -41,14 +41,14 @@ MODULE_ALIAS("ip_conntrack_pptp");
static DEFINE_SPINLOCK(nf_pptp_lock);
int
-(*nf_nat_pptp_hook_outbound)(struct sk_buff **pskb,
+(*nf_nat_pptp_hook_outbound)(struct sk_buff *skb,
struct nf_conn *ct, enum ip_conntrack_info ctinfo,
struct PptpControlHeader *ctlh,
union pptp_ctrl_union *pptpReq) __read_mostly;
EXPORT_SYMBOL_GPL(nf_nat_pptp_hook_outbound);
int
-(*nf_nat_pptp_hook_inbound)(struct sk_buff **pskb,
+(*nf_nat_pptp_hook_inbound)(struct sk_buff *skb,
struct nf_conn *ct, enum ip_conntrack_info ctinfo,
struct PptpControlHeader *ctlh,
union pptp_ctrl_union *pptpReq) __read_mostly;
@@ -254,7 +254,7 @@ out_unexpect_orig:
}
static inline int
-pptp_inbound_pkt(struct sk_buff **pskb,
+pptp_inbound_pkt(struct sk_buff *skb,
struct PptpControlHeader *ctlh,
union pptp_ctrl_union *pptpReq,
unsigned int reqlen,
@@ -367,7 +367,7 @@ pptp_inbound_pkt(struct sk_buff **pskb,
nf_nat_pptp_inbound = rcu_dereference(nf_nat_pptp_hook_inbound);
if (nf_nat_pptp_inbound && ct->status & IPS_NAT_MASK)
- return nf_nat_pptp_inbound(pskb, ct, ctinfo, ctlh, pptpReq);
+ return nf_nat_pptp_inbound(skb, ct, ctinfo, ctlh, pptpReq);
return NF_ACCEPT;
invalid:
@@ -380,7 +380,7 @@ invalid:
}
static inline int
-pptp_outbound_pkt(struct sk_buff **pskb,
+pptp_outbound_pkt(struct sk_buff *skb,
struct PptpControlHeader *ctlh,
union pptp_ctrl_union *pptpReq,
unsigned int reqlen,
@@ -462,7 +462,7 @@ pptp_outbound_pkt(struct sk_buff **pskb,
nf_nat_pptp_outbound = rcu_dereference(nf_nat_pptp_hook_outbound);
if (nf_nat_pptp_outbound && ct->status & IPS_NAT_MASK)
- return nf_nat_pptp_outbound(pskb, ct, ctinfo, ctlh, pptpReq);
+ return nf_nat_pptp_outbound(skb, ct, ctinfo, ctlh, pptpReq);
return NF_ACCEPT;
invalid:
@@ -492,7 +492,7 @@ static const unsigned int pptp_msg_size[] = {
/* track caller id inside control connection, call expect_related */
static int
-conntrack_pptp_help(struct sk_buff **pskb, unsigned int protoff,
+conntrack_pptp_help(struct sk_buff *skb, unsigned int protoff,
struct nf_conn *ct, enum ip_conntrack_info ctinfo)
{
@@ -502,7 +502,7 @@ conntrack_pptp_help(struct sk_buff **pskb, unsigned int protoff,
struct pptp_pkt_hdr _pptph, *pptph;
struct PptpControlHeader _ctlh, *ctlh;
union pptp_ctrl_union _pptpReq, *pptpReq;
- unsigned int tcplen = (*pskb)->len - protoff;
+ unsigned int tcplen = skb->len - protoff;
unsigned int datalen, reqlen, nexthdr_off;
int oldsstate, oldcstate;
int ret;
@@ -514,12 +514,12 @@ conntrack_pptp_help(struct sk_buff **pskb, unsigned int protoff,
return NF_ACCEPT;
nexthdr_off = protoff;
- tcph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_tcph), &_tcph);
+ tcph = skb_header_pointer(skb, nexthdr_off, sizeof(_tcph), &_tcph);
BUG_ON(!tcph);
nexthdr_off += tcph->doff * 4;
datalen = tcplen - tcph->doff * 4;
- pptph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_pptph), &_pptph);
+ pptph = skb_header_pointer(skb, nexthdr_off, sizeof(_pptph), &_pptph);
if (!pptph) {
pr_debug("no full PPTP header, can't track\n");
return NF_ACCEPT;
@@ -534,7 +534,7 @@ conntrack_pptp_help(struct sk_buff **pskb, unsigned int protoff,
return NF_ACCEPT;
}
- ctlh = skb_header_pointer(*pskb, nexthdr_off, sizeof(_ctlh), &_ctlh);
+ ctlh = skb_header_pointer(skb, nexthdr_off, sizeof(_ctlh), &_ctlh);
if (!ctlh)
return NF_ACCEPT;
nexthdr_off += sizeof(_ctlh);
@@ -547,7 +547,7 @@ conntrack_pptp_help(struct sk_buff **pskb, unsigned int protoff,
if (reqlen > sizeof(*pptpReq))
reqlen = sizeof(*pptpReq);
- pptpReq = skb_header_pointer(*pskb, nexthdr_off, reqlen, &_pptpReq);
+ pptpReq = skb_header_pointer(skb, nexthdr_off, reqlen, &_pptpReq);
if (!pptpReq)
return NF_ACCEPT;
@@ -560,11 +560,11 @@ conntrack_pptp_help(struct sk_buff **pskb, unsigned int protoff,
* established from PNS->PAC. However, RFC makes no guarantee */
if (dir == IP_CT_DIR_ORIGINAL)
/* client -> server (PNS -> PAC) */
- ret = pptp_outbound_pkt(pskb, ctlh, pptpReq, reqlen, ct,
+ ret = pptp_outbound_pkt(skb, ctlh, pptpReq, reqlen, ct,
ctinfo);
else
/* server -> client (PAC -> PNS) */
- ret = pptp_inbound_pkt(pskb, ctlh, pptpReq, reqlen, ct,
+ ret = pptp_inbound_pkt(skb, ctlh, pptpReq, reqlen, ct,
ctinfo);
pr_debug("sstate: %d->%d, cstate: %d->%d\n",
oldsstate, info->sstate, oldcstate, info->cstate);
diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c
index d8b501878d9f..13f819179642 100644
--- a/net/netfilter/nf_conntrack_proto_generic.c
+++ b/net/netfilter/nf_conntrack_proto_generic.c
@@ -70,7 +70,6 @@ static int new(struct nf_conn *conntrack, const struct sk_buff *skb,
static struct ctl_table_header *generic_sysctl_header;
static struct ctl_table generic_sysctl_table[] = {
{
- .ctl_name = NET_NF_CONNTRACK_GENERIC_TIMEOUT,
.procname = "nf_conntrack_generic_timeout",
.data = &nf_ct_generic_timeout,
.maxlen = sizeof(unsigned int),
@@ -84,7 +83,6 @@ static struct ctl_table generic_sysctl_table[] = {
#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
static struct ctl_table generic_compat_sysctl_table[] = {
{
- .ctl_name = NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT,
.procname = "ip_conntrack_generic_timeout",
.data = &nf_ct_generic_timeout,
.maxlen = sizeof(unsigned int),
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index 04192acc7c40..cb0467510592 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -476,7 +476,6 @@ static unsigned int sctp_sysctl_table_users;
static struct ctl_table_header *sctp_sysctl_header;
static struct ctl_table sctp_sysctl_table[] = {
{
- .ctl_name = NET_NF_CONNTRACK_SCTP_TIMEOUT_CLOSED,
.procname = "nf_conntrack_sctp_timeout_closed",
.data = &nf_ct_sctp_timeout_closed,
.maxlen = sizeof(unsigned int),
@@ -484,7 +483,6 @@ static struct ctl_table sctp_sysctl_table[] = {
.proc_handler = &proc_dointvec_jiffies,
},
{
- .ctl_name = NET_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_WAIT,
.procname = "nf_conntrack_sctp_timeout_cookie_wait",
.data = &nf_ct_sctp_timeout_cookie_wait,
.maxlen = sizeof(unsigned int),
@@ -492,7 +490,6 @@ static struct ctl_table sctp_sysctl_table[] = {
.proc_handler = &proc_dointvec_jiffies,
},
{
- .ctl_name = NET_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_ECHOED,
.procname = "nf_conntrack_sctp_timeout_cookie_echoed",
.data = &nf_ct_sctp_timeout_cookie_echoed,
.maxlen = sizeof(unsigned int),
@@ -500,7 +497,6 @@ static struct ctl_table sctp_sysctl_table[] = {
.proc_handler = &proc_dointvec_jiffies,
},
{
- .ctl_name = NET_NF_CONNTRACK_SCTP_TIMEOUT_ESTABLISHED,
.procname = "nf_conntrack_sctp_timeout_established",
.data = &nf_ct_sctp_timeout_established,
.maxlen = sizeof(unsigned int),
@@ -508,7 +504,6 @@ static struct ctl_table sctp_sysctl_table[] = {
.proc_handler = &proc_dointvec_jiffies,
},
{
- .ctl_name = NET_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_SENT,
.procname = "nf_conntrack_sctp_timeout_shutdown_sent",
.data = &nf_ct_sctp_timeout_shutdown_sent,
.maxlen = sizeof(unsigned int),
@@ -516,7 +511,6 @@ static struct ctl_table sctp_sysctl_table[] = {
.proc_handler = &proc_dointvec_jiffies,
},
{
- .ctl_name = NET_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_RECD,
.procname = "nf_conntrack_sctp_timeout_shutdown_recd",
.data = &nf_ct_sctp_timeout_shutdown_recd,
.maxlen = sizeof(unsigned int),
@@ -524,7 +518,6 @@ static struct ctl_table sctp_sysctl_table[] = {
.proc_handler = &proc_dointvec_jiffies,
},
{
- .ctl_name = NET_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_ACK_SENT,
.procname = "nf_conntrack_sctp_timeout_shutdown_ack_sent",
.data = &nf_ct_sctp_timeout_shutdown_ack_sent,
.maxlen = sizeof(unsigned int),
@@ -539,7 +532,6 @@ static struct ctl_table sctp_sysctl_table[] = {
#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
static struct ctl_table sctp_compat_sysctl_table[] = {
{
- .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_CLOSED,
.procname = "ip_conntrack_sctp_timeout_closed",
.data = &nf_ct_sctp_timeout_closed,
.maxlen = sizeof(unsigned int),
@@ -547,7 +539,6 @@ static struct ctl_table sctp_compat_sysctl_table[] = {
.proc_handler = &proc_dointvec_jiffies,
},
{
- .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_WAIT,
.procname = "ip_conntrack_sctp_timeout_cookie_wait",
.data = &nf_ct_sctp_timeout_cookie_wait,
.maxlen = sizeof(unsigned int),
@@ -555,7 +546,6 @@ static struct ctl_table sctp_compat_sysctl_table[] = {
.proc_handler = &proc_dointvec_jiffies,
},
{
- .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_ECHOED,
.procname = "ip_conntrack_sctp_timeout_cookie_echoed",
.data = &nf_ct_sctp_timeout_cookie_echoed,
.maxlen = sizeof(unsigned int),
@@ -563,7 +553,6 @@ static struct ctl_table sctp_compat_sysctl_table[] = {
.proc_handler = &proc_dointvec_jiffies,
},
{
- .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_ESTABLISHED,
.procname = "ip_conntrack_sctp_timeout_established",
.data = &nf_ct_sctp_timeout_established,
.maxlen = sizeof(unsigned int),
@@ -571,7 +560,6 @@ static struct ctl_table sctp_compat_sysctl_table[] = {
.proc_handler = &proc_dointvec_jiffies,
},
{
- .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_SENT,
.procname = "ip_conntrack_sctp_timeout_shutdown_sent",
.data = &nf_ct_sctp_timeout_shutdown_sent,
.maxlen = sizeof(unsigned int),
@@ -579,7 +567,6 @@ static struct ctl_table sctp_compat_sysctl_table[] = {
.proc_handler = &proc_dointvec_jiffies,
},
{
- .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_RECD,
.procname = "ip_conntrack_sctp_timeout_shutdown_recd",
.data = &nf_ct_sctp_timeout_shutdown_recd,
.maxlen = sizeof(unsigned int),
@@ -587,7 +574,6 @@ static struct ctl_table sctp_compat_sysctl_table[] = {
.proc_handler = &proc_dointvec_jiffies,
},
{
- .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_ACK_SENT,
.procname = "ip_conntrack_sctp_timeout_shutdown_ack_sent",
.data = &nf_ct_sctp_timeout_shutdown_ack_sent,
.maxlen = sizeof(unsigned int),
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index c7075345971b..7a3f64c1aca6 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -834,10 +834,12 @@ static int tcp_packet(struct nf_conn *conntrack,
case TCP_CONNTRACK_SYN_SENT:
if (old_state < TCP_CONNTRACK_TIME_WAIT)
break;
- if (conntrack->proto.tcp.seen[!dir].flags &
- IP_CT_TCP_FLAG_CLOSE_INIT) {
- /* Attempt to reopen a closed connection.
- * Delete this connection and look up again. */
+ if ((conntrack->proto.tcp.seen[!dir].flags &
+ IP_CT_TCP_FLAG_CLOSE_INIT)
+ || (conntrack->proto.tcp.last_dir == dir
+ && conntrack->proto.tcp.last_index == TCP_RST_SET)) {
+ /* Attempt to reopen a closed/aborted connection.
+ * Delete this connection and look up again. */
write_unlock_bh(&tcp_lock);
if (del_timer(&conntrack->timeout))
conntrack->timeout.function((unsigned long)
@@ -925,6 +927,7 @@ static int tcp_packet(struct nf_conn *conntrack,
in_window:
/* From now on we have got in-window packets */
conntrack->proto.tcp.last_index = index;
+ conntrack->proto.tcp.last_dir = dir;
pr_debug("tcp_conntracks: ");
NF_CT_DUMP_TUPLE(tuple);
@@ -1162,7 +1165,6 @@ static unsigned int tcp_sysctl_table_users;
static struct ctl_table_header *tcp_sysctl_header;
static struct ctl_table tcp_sysctl_table[] = {
{
- .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT,
.procname = "nf_conntrack_tcp_timeout_syn_sent",
.data = &nf_ct_tcp_timeout_syn_sent,
.maxlen = sizeof(unsigned int),
@@ -1170,7 +1172,6 @@ static struct ctl_table tcp_sysctl_table[] = {
.proc_handler = &proc_dointvec_jiffies,
},
{
- .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV,
.procname = "nf_conntrack_tcp_timeout_syn_recv",
.data = &nf_ct_tcp_timeout_syn_recv,
.maxlen = sizeof(unsigned int),
@@ -1178,7 +1179,6 @@ static struct ctl_table tcp_sysctl_table[] = {
.proc_handler = &proc_dointvec_jiffies,
},
{
- .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED,
.procname = "nf_conntrack_tcp_timeout_established",
.data = &nf_ct_tcp_timeout_established,
.maxlen = sizeof(unsigned int),
@@ -1186,7 +1186,6 @@ static struct ctl_table tcp_sysctl_table[] = {
.proc_handler = &proc_dointvec_jiffies,
},
{
- .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT,
.procname = "nf_conntrack_tcp_timeout_fin_wait",
.data = &nf_ct_tcp_timeout_fin_wait,
.maxlen = sizeof(unsigned int),
@@ -1194,7 +1193,6 @@ static struct ctl_table tcp_sysctl_table[] = {
.proc_handler = &proc_dointvec_jiffies,
},
{
- .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT,
.procname = "nf_conntrack_tcp_timeout_close_wait",
.data = &nf_ct_tcp_timeout_close_wait,
.maxlen = sizeof(unsigned int),
@@ -1202,7 +1200,6 @@ static struct ctl_table tcp_sysctl_table[] = {
.proc_handler = &proc_dointvec_jiffies,
},
{
- .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK,
.procname = "nf_conntrack_tcp_timeout_last_ack",
.data = &nf_ct_tcp_timeout_last_ack,
.maxlen = sizeof(unsigned int),
@@ -1210,7 +1207,6 @@ static struct ctl_table tcp_sysctl_table[] = {
.proc_handler = &proc_dointvec_jiffies,
},
{
- .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT,
.procname = "nf_conntrack_tcp_timeout_time_wait",
.data = &nf_ct_tcp_timeout_time_wait,
.maxlen = sizeof(unsigned int),
@@ -1218,7 +1214,6 @@ static struct ctl_table tcp_sysctl_table[] = {
.proc_handler = &proc_dointvec_jiffies,
},
{
- .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_CLOSE,
.procname = "nf_conntrack_tcp_timeout_close",
.data = &nf_ct_tcp_timeout_close,
.maxlen = sizeof(unsigned int),
@@ -1226,7 +1221,6 @@ static struct ctl_table tcp_sysctl_table[] = {
.proc_handler = &proc_dointvec_jiffies,
},
{
- .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_MAX_RETRANS,
.procname = "nf_conntrack_tcp_timeout_max_retrans",
.data = &nf_ct_tcp_timeout_max_retrans,
.maxlen = sizeof(unsigned int),
@@ -1265,7 +1259,6 @@ static struct ctl_table tcp_sysctl_table[] = {
#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
static struct ctl_table tcp_compat_sysctl_table[] = {
{
- .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT,
.procname = "ip_conntrack_tcp_timeout_syn_sent",
.data = &nf_ct_tcp_timeout_syn_sent,
.maxlen = sizeof(unsigned int),
@@ -1273,7 +1266,6 @@ static struct ctl_table tcp_compat_sysctl_table[] = {
.proc_handler = &proc_dointvec_jiffies,
},
{
- .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV,
.procname = "ip_conntrack_tcp_timeout_syn_recv",
.data = &nf_ct_tcp_timeout_syn_recv,
.maxlen = sizeof(unsigned int),
@@ -1281,7 +1273,6 @@ static struct ctl_table tcp_compat_sysctl_table[] = {
.proc_handler = &proc_dointvec_jiffies,
},
{
- .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED,
.procname = "ip_conntrack_tcp_timeout_established",
.data = &nf_ct_tcp_timeout_established,
.maxlen = sizeof(unsigned int),
@@ -1289,7 +1280,6 @@ static struct ctl_table tcp_compat_sysctl_table[] = {
.proc_handler = &proc_dointvec_jiffies,
},
{
- .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT,
.procname = "ip_conntrack_tcp_timeout_fin_wait",
.data = &nf_ct_tcp_timeout_fin_wait,
.maxlen = sizeof(unsigned int),
@@ -1297,7 +1287,6 @@ static struct ctl_table tcp_compat_sysctl_table[] = {
.proc_handler = &proc_dointvec_jiffies,
},
{
- .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT,
.procname = "ip_conntrack_tcp_timeout_close_wait",
.data = &nf_ct_tcp_timeout_close_wait,
.maxlen = sizeof(unsigned int),
@@ -1305,7 +1294,6 @@ static struct ctl_table tcp_compat_sysctl_table[] = {
.proc_handler = &proc_dointvec_jiffies,
},
{
- .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK,
.procname = "ip_conntrack_tcp_timeout_last_ack",
.data = &nf_ct_tcp_timeout_last_ack,
.maxlen = sizeof(unsigned int),
@@ -1313,7 +1301,6 @@ static struct ctl_table tcp_compat_sysctl_table[] = {
.proc_handler = &proc_dointvec_jiffies,
},
{
- .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT,
.procname = "ip_conntrack_tcp_timeout_time_wait",
.data = &nf_ct_tcp_timeout_time_wait,
.maxlen = sizeof(unsigned int),
@@ -1321,7 +1308,6 @@ static struct ctl_table tcp_compat_sysctl_table[] = {
.proc_handler = &proc_dointvec_jiffies,
},
{
- .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE,
.procname = "ip_conntrack_tcp_timeout_close",
.data = &nf_ct_tcp_timeout_close,
.maxlen = sizeof(unsigned int),
@@ -1329,7 +1315,6 @@ static struct ctl_table tcp_compat_sysctl_table[] = {
.proc_handler = &proc_dointvec_jiffies,
},
{
- .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_MAX_RETRANS,
.procname = "ip_conntrack_tcp_timeout_max_retrans",
.data = &nf_ct_tcp_timeout_max_retrans,
.maxlen = sizeof(unsigned int),
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c
index ba80e1a1ea17..b3e7ecb080e6 100644
--- a/net/netfilter/nf_conntrack_proto_udp.c
+++ b/net/netfilter/nf_conntrack_proto_udp.c
@@ -146,7 +146,6 @@ static unsigned int udp_sysctl_table_users;
static struct ctl_table_header *udp_sysctl_header;
static struct ctl_table udp_sysctl_table[] = {
{
- .ctl_name = NET_NF_CONNTRACK_UDP_TIMEOUT,
.procname = "nf_conntrack_udp_timeout",
.data = &nf_ct_udp_timeout,
.maxlen = sizeof(unsigned int),
@@ -154,7 +153,6 @@ static struct ctl_table udp_sysctl_table[] = {
.proc_handler = &proc_dointvec_jiffies,
},
{
- .ctl_name = NET_NF_CONNTRACK_UDP_TIMEOUT_STREAM,
.procname = "nf_conntrack_udp_timeout_stream",
.data = &nf_ct_udp_timeout_stream,
.maxlen = sizeof(unsigned int),
@@ -168,7 +166,6 @@ static struct ctl_table udp_sysctl_table[] = {
#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
static struct ctl_table udp_compat_sysctl_table[] = {
{
- .ctl_name = NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT,
.procname = "ip_conntrack_udp_timeout",
.data = &nf_ct_udp_timeout,
.maxlen = sizeof(unsigned int),
@@ -176,7 +173,6 @@ static struct ctl_table udp_compat_sysctl_table[] = {
.proc_handler = &proc_dointvec_jiffies,
},
{
- .ctl_name = NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT_STREAM,
.procname = "ip_conntrack_udp_timeout_stream",
.data = &nf_ct_udp_timeout_stream,
.maxlen = sizeof(unsigned int),
diff --git a/net/netfilter/nf_conntrack_sane.c b/net/netfilter/nf_conntrack_sane.c
index 355d371bac93..b5a16c6e21c2 100644
--- a/net/netfilter/nf_conntrack_sane.c
+++ b/net/netfilter/nf_conntrack_sane.c
@@ -56,7 +56,7 @@ struct sane_reply_net_start {
/* other fields aren't interesting for conntrack */
};
-static int help(struct sk_buff **pskb,
+static int help(struct sk_buff *skb,
unsigned int protoff,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo)
@@ -80,19 +80,19 @@ static int help(struct sk_buff **pskb,
return NF_ACCEPT;
/* Not a full tcp header? */
- th = skb_header_pointer(*pskb, protoff, sizeof(_tcph), &_tcph);
+ th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
if (th == NULL)
return NF_ACCEPT;
/* No data? */
dataoff = protoff + th->doff * 4;
- if (dataoff >= (*pskb)->len)
+ if (dataoff >= skb->len)
return NF_ACCEPT;
- datalen = (*pskb)->len - dataoff;
+ datalen = skb->len - dataoff;
spin_lock_bh(&nf_sane_lock);
- sb_ptr = skb_header_pointer(*pskb, dataoff, datalen, sane_buffer);
+ sb_ptr = skb_header_pointer(skb, dataoff, datalen, sane_buffer);
BUG_ON(sb_ptr == NULL);
if (dir == IP_CT_DIR_ORIGINAL) {
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index d449fa47491c..8f8b5a48df38 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -36,13 +36,13 @@ static unsigned int sip_timeout __read_mostly = SIP_TIMEOUT;
module_param(sip_timeout, uint, 0600);
MODULE_PARM_DESC(sip_timeout, "timeout for the master SIP session");
-unsigned int (*nf_nat_sip_hook)(struct sk_buff **pskb,
+unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb,
enum ip_conntrack_info ctinfo,
struct nf_conn *ct,
const char **dptr) __read_mostly;
EXPORT_SYMBOL_GPL(nf_nat_sip_hook);
-unsigned int (*nf_nat_sdp_hook)(struct sk_buff **pskb,
+unsigned int (*nf_nat_sdp_hook)(struct sk_buff *skb,
enum ip_conntrack_info ctinfo,
struct nf_conntrack_expect *exp,
const char *dptr) __read_mostly;
@@ -363,7 +363,7 @@ int ct_sip_get_info(struct nf_conn *ct,
}
EXPORT_SYMBOL_GPL(ct_sip_get_info);
-static int set_expected_rtp(struct sk_buff **pskb,
+static int set_expected_rtp(struct sk_buff *skb,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
union nf_conntrack_address *addr,
@@ -385,7 +385,7 @@ static int set_expected_rtp(struct sk_buff **pskb,
nf_nat_sdp = rcu_dereference(nf_nat_sdp_hook);
if (nf_nat_sdp && ct->status & IPS_NAT_MASK)
- ret = nf_nat_sdp(pskb, ctinfo, exp, dptr);
+ ret = nf_nat_sdp(skb, ctinfo, exp, dptr);
else {
if (nf_ct_expect_related(exp) != 0)
ret = NF_DROP;
@@ -397,7 +397,7 @@ static int set_expected_rtp(struct sk_buff **pskb,
return ret;
}
-static int sip_help(struct sk_buff **pskb,
+static int sip_help(struct sk_buff *skb,
unsigned int protoff,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo)
@@ -414,13 +414,13 @@ static int sip_help(struct sk_buff **pskb,
/* No Data ? */
dataoff = protoff + sizeof(struct udphdr);
- if (dataoff >= (*pskb)->len)
+ if (dataoff >= skb->len)
return NF_ACCEPT;
- nf_ct_refresh(ct, *pskb, sip_timeout * HZ);
+ nf_ct_refresh(ct, skb, sip_timeout * HZ);
- if (!skb_is_nonlinear(*pskb))
- dptr = (*pskb)->data + dataoff;
+ if (!skb_is_nonlinear(skb))
+ dptr = skb->data + dataoff;
else {
pr_debug("Copy of skbuff not supported yet.\n");
goto out;
@@ -428,13 +428,13 @@ static int sip_help(struct sk_buff **pskb,
nf_nat_sip = rcu_dereference(nf_nat_sip_hook);
if (nf_nat_sip && ct->status & IPS_NAT_MASK) {
- if (!nf_nat_sip(pskb, ctinfo, ct, &dptr)) {
+ if (!nf_nat_sip(skb, ctinfo, ct, &dptr)) {
ret = NF_DROP;
goto out;
}
}
- datalen = (*pskb)->len - dataoff;
+ datalen = skb->len - dataoff;
if (datalen < sizeof("SIP/2.0 200") - 1)
goto out;
@@ -464,7 +464,7 @@ static int sip_help(struct sk_buff **pskb,
ret = NF_DROP;
goto out;
}
- ret = set_expected_rtp(pskb, ct, ctinfo, &addr,
+ ret = set_expected_rtp(skb, ct, ctinfo, &addr,
htons(port), dptr);
}
}
diff --git a/net/netfilter/nf_conntrack_tftp.c b/net/netfilter/nf_conntrack_tftp.c
index cc19506cf2f8..e894aa1ff3ad 100644
--- a/net/netfilter/nf_conntrack_tftp.c
+++ b/net/netfilter/nf_conntrack_tftp.c
@@ -29,12 +29,12 @@ static int ports_c;
module_param_array(ports, ushort, &ports_c, 0400);
MODULE_PARM_DESC(ports, "Port numbers of TFTP servers");
-unsigned int (*nf_nat_tftp_hook)(struct sk_buff **pskb,
+unsigned int (*nf_nat_tftp_hook)(struct sk_buff *skb,
enum ip_conntrack_info ctinfo,
struct nf_conntrack_expect *exp) __read_mostly;
EXPORT_SYMBOL_GPL(nf_nat_tftp_hook);
-static int tftp_help(struct sk_buff **pskb,
+static int tftp_help(struct sk_buff *skb,
unsigned int protoff,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo)
@@ -46,7 +46,7 @@ static int tftp_help(struct sk_buff **pskb,
int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
typeof(nf_nat_tftp_hook) nf_nat_tftp;
- tfh = skb_header_pointer(*pskb, protoff + sizeof(struct udphdr),
+ tfh = skb_header_pointer(skb, protoff + sizeof(struct udphdr),
sizeof(_tftph), &_tftph);
if (tfh == NULL)
return NF_ACCEPT;
@@ -70,7 +70,7 @@ static int tftp_help(struct sk_buff **pskb,
nf_nat_tftp = rcu_dereference(nf_nat_tftp_hook);
if (nf_nat_tftp && ct->status & IPS_NAT_MASK)
- ret = nf_nat_tftp(pskb, ctinfo, exp);
+ ret = nf_nat_tftp(skb, ctinfo, exp);
else if (nf_ct_expect_related(exp) != 0)
ret = NF_DROP;
nf_ct_expect_put(exp);
diff --git a/net/netfilter/nf_internals.h b/net/netfilter/nf_internals.h
index 0df7fff196a7..196269c1e586 100644
--- a/net/netfilter/nf_internals.h
+++ b/net/netfilter/nf_internals.h
@@ -14,7 +14,7 @@
/* core.c */
extern unsigned int nf_iterate(struct list_head *head,
- struct sk_buff **skb,
+ struct sk_buff *skb,
int hook,
const struct net_device *indev,
const struct net_device *outdev,
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index a481a349f7bf..0cef1433d660 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -256,14 +256,14 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
if (verdict == NF_ACCEPT) {
afinfo = nf_get_afinfo(info->pf);
- if (!afinfo || afinfo->reroute(&skb, info) < 0)
+ if (!afinfo || afinfo->reroute(skb, info) < 0)
verdict = NF_DROP;
}
if (verdict == NF_ACCEPT) {
next_hook:
verdict = nf_iterate(&nf_hooks[info->pf][info->hook],
- &skb, info->hook,
+ skb, info->hook,
info->indev, info->outdev, &elem,
info->okfn, INT_MIN);
}
diff --git a/net/netfilter/nf_sockopt.c b/net/netfilter/nf_sockopt.c
index aa2831587b82..3dd4b3c76d81 100644
--- a/net/netfilter/nf_sockopt.c
+++ b/net/netfilter/nf_sockopt.c
@@ -23,14 +23,13 @@ static inline int overlap(int min1, int max1, int min2, int max2)
/* Functions to register sockopt ranges (exclusive). */
int nf_register_sockopt(struct nf_sockopt_ops *reg)
{
- struct list_head *i;
+ struct nf_sockopt_ops *ops;
int ret = 0;
if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0)
return -EINTR;
- list_for_each(i, &nf_sockopts) {
- struct nf_sockopt_ops *ops = (struct nf_sockopt_ops *)i;
+ list_for_each_entry(ops, &nf_sockopts, list) {
if (ops->pf == reg->pf
&& (overlap(ops->set_optmin, ops->set_optmax,
reg->set_optmin, reg->set_optmax)
@@ -61,48 +60,57 @@ void nf_unregister_sockopt(struct nf_sockopt_ops *reg)
}
EXPORT_SYMBOL(nf_unregister_sockopt);
-/* Call get/setsockopt() */
-static int nf_sockopt(struct sock *sk, int pf, int val,
- char __user *opt, int *len, int get)
+static struct nf_sockopt_ops *nf_sockopt_find(struct sock *sk, int pf,
+ int val, int get)
{
- struct list_head *i;
struct nf_sockopt_ops *ops;
- int ret;
if (sk->sk_net != &init_net)
- return -ENOPROTOOPT;
+ return ERR_PTR(-ENOPROTOOPT);
if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0)
- return -EINTR;
+ return ERR_PTR(-EINTR);
- list_for_each(i, &nf_sockopts) {
- ops = (struct nf_sockopt_ops *)i;
+ list_for_each_entry(ops, &nf_sockopts, list) {
if (ops->pf == pf) {
if (!try_module_get(ops->owner))
goto out_nosup;
+
if (get) {
- if (val >= ops->get_optmin
- && val < ops->get_optmax) {
- mutex_unlock(&nf_sockopt_mutex);
- ret = ops->get(sk, val, opt, len);
+ if (val >= ops->get_optmin &&
+ val < ops->get_optmax)
goto out;
- }
} else {
- if (val >= ops->set_optmin
- && val < ops->set_optmax) {
- mutex_unlock(&nf_sockopt_mutex);
- ret = ops->set(sk, val, opt, *len);
+ if (val >= ops->set_optmin &&
+ val < ops->set_optmax)
goto out;
- }
}
module_put(ops->owner);
}
}
- out_nosup:
+out_nosup:
+ ops = ERR_PTR(-ENOPROTOOPT);
+out:
mutex_unlock(&nf_sockopt_mutex);
- return -ENOPROTOOPT;
+ return ops;
+}
+
+/* Call get/setsockopt() */
+static int nf_sockopt(struct sock *sk, int pf, int val,
+ char __user *opt, int *len, int get)
+{
+ struct nf_sockopt_ops *ops;
+ int ret;
+
+ ops = nf_sockopt_find(sk, pf, val, get);
+ if (IS_ERR(ops))
+ return PTR_ERR(ops);
+
+ if (get)
+ ret = ops->get(sk, val, opt, len);
+ else
+ ret = ops->set(sk, val, opt, *len);
- out:
module_put(ops->owner);
return ret;
}
@@ -124,56 +132,25 @@ EXPORT_SYMBOL(nf_getsockopt);
static int compat_nf_sockopt(struct sock *sk, int pf, int val,
char __user *opt, int *len, int get)
{
- struct list_head *i;
struct nf_sockopt_ops *ops;
int ret;
- if (sk->sk_net != &init_net)
- return -ENOPROTOOPT;
-
-
- if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0)
- return -EINTR;
-
- list_for_each(i, &nf_sockopts) {
- ops = (struct nf_sockopt_ops *)i;
- if (ops->pf == pf) {
- if (!try_module_get(ops->owner))
- goto out_nosup;
-
- if (get) {
- if (val >= ops->get_optmin
- && val < ops->get_optmax) {
- mutex_unlock(&nf_sockopt_mutex);
- if (ops->compat_get)
- ret = ops->compat_get(sk,
- val, opt, len);
- else
- ret = ops->get(sk,
- val, opt, len);
- goto out;
- }
- } else {
- if (val >= ops->set_optmin
- && val < ops->set_optmax) {
- mutex_unlock(&nf_sockopt_mutex);
- if (ops->compat_set)
- ret = ops->compat_set(sk,
- val, opt, *len);
- else
- ret = ops->set(sk,
- val, opt, *len);
- goto out;
- }
- }
- module_put(ops->owner);
- }
+ ops = nf_sockopt_find(sk, pf, val, get);
+ if (IS_ERR(ops))
+ return PTR_ERR(ops);
+
+ if (get) {
+ if (ops->compat_get)
+ ret = ops->compat_get(sk, val, opt, len);
+ else
+ ret = ops->get(sk, val, opt, len);
+ } else {
+ if (ops->compat_set)
+ ret = ops->compat_set(sk, val, opt, *len);
+ else
+ ret = ops->set(sk, val, opt, *len);
}
- out_nosup:
- mutex_unlock(&nf_sockopt_mutex);
- return -ENOPROTOOPT;
- out:
module_put(ops->owner);
return ret;
}
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 49f0480afe09..3ceeffcf6f9d 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -617,6 +617,7 @@ static int
nfqnl_mangle(void *data, int data_len, struct nfqnl_queue_entry *e)
{
int diff;
+ int err;
diff = data_len - e->skb->len;
if (diff < 0) {
@@ -626,25 +627,18 @@ nfqnl_mangle(void *data, int data_len, struct nfqnl_queue_entry *e)
if (data_len > 0xFFFF)
return -EINVAL;
if (diff > skb_tailroom(e->skb)) {
- struct sk_buff *newskb;
-
- newskb = skb_copy_expand(e->skb,
- skb_headroom(e->skb),
- diff,
- GFP_ATOMIC);
- if (newskb == NULL) {
+ err = pskb_expand_head(e->skb, 0,
+ diff - skb_tailroom(e->skb),
+ GFP_ATOMIC);
+ if (err) {
printk(KERN_WARNING "nf_queue: OOM "
"in mangle, dropping packet\n");
- return -ENOMEM;
+ return err;
}
- if (e->skb->sk)
- skb_set_owner_w(newskb, e->skb->sk);
- kfree_skb(e->skb);
- e->skb = newskb;
}
skb_put(e->skb, diff);
}
- if (!skb_make_writable(&e->skb, data_len))
+ if (!skb_make_writable(e->skb, data_len))
return -ENOMEM;
skb_copy_to_linear_data(e->skb, data, data_len);
e->skb->ip_summed = CHECKSUM_NONE;
diff --git a/net/netfilter/xt_CLASSIFY.c b/net/netfilter/xt_CLASSIFY.c
index 07a1b9665005..77eeae658d42 100644
--- a/net/netfilter/xt_CLASSIFY.c
+++ b/net/netfilter/xt_CLASSIFY.c
@@ -27,7 +27,7 @@ MODULE_ALIAS("ipt_CLASSIFY");
MODULE_ALIAS("ip6t_CLASSIFY");
static unsigned int
-target(struct sk_buff **pskb,
+target(struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
unsigned int hooknum,
@@ -36,7 +36,7 @@ target(struct sk_buff **pskb,
{
const struct xt_classify_target_info *clinfo = targinfo;
- (*pskb)->priority = clinfo->priority;
+ skb->priority = clinfo->priority;
return XT_CONTINUE;
}
diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c
index 7043c2757e09..856793e8db7a 100644
--- a/net/netfilter/xt_CONNMARK.c
+++ b/net/netfilter/xt_CONNMARK.c
@@ -23,7 +23,7 @@
#include <linux/ip.h>
#include <net/checksum.h>
-MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
+MODULE_AUTHOR("Henrik Nordstrom <hno@marasystems.com>");
MODULE_DESCRIPTION("IP tables CONNMARK matching module");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_CONNMARK");
@@ -34,7 +34,7 @@ MODULE_ALIAS("ip6t_CONNMARK");
#include <net/netfilter/nf_conntrack_ecache.h>
static unsigned int
-target(struct sk_buff **pskb,
+target(struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
unsigned int hooknum,
@@ -48,28 +48,28 @@ target(struct sk_buff **pskb,
u_int32_t mark;
u_int32_t newmark;
- ct = nf_ct_get(*pskb, &ctinfo);
+ ct = nf_ct_get(skb, &ctinfo);
if (ct) {
switch(markinfo->mode) {
case XT_CONNMARK_SET:
newmark = (ct->mark & ~markinfo->mask) | markinfo->mark;
if (newmark != ct->mark) {
ct->mark = newmark;
- nf_conntrack_event_cache(IPCT_MARK, *pskb);
+ nf_conntrack_event_cache(IPCT_MARK, skb);
}
break;
case XT_CONNMARK_SAVE:
newmark = (ct->mark & ~markinfo->mask) |
- ((*pskb)->mark & markinfo->mask);
+ (skb->mark & markinfo->mask);
if (ct->mark != newmark) {
ct->mark = newmark;
- nf_conntrack_event_cache(IPCT_MARK, *pskb);
+ nf_conntrack_event_cache(IPCT_MARK, skb);
}
break;
case XT_CONNMARK_RESTORE:
- mark = (*pskb)->mark;
+ mark = skb->mark;
diff = (ct->mark ^ mark) & markinfo->mask;
- (*pskb)->mark = mark ^ diff;
+ skb->mark = mark ^ diff;
break;
}
}
diff --git a/net/netfilter/xt_CONNSECMARK.c b/net/netfilter/xt_CONNSECMARK.c
index 63d73138c1b9..021b5c8d20e2 100644
--- a/net/netfilter/xt_CONNSECMARK.c
+++ b/net/netfilter/xt_CONNSECMARK.c
@@ -61,12 +61,11 @@ static void secmark_restore(struct sk_buff *skb)
}
}
-static unsigned int target(struct sk_buff **pskb, const struct net_device *in,
+static unsigned int target(struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, unsigned int hooknum,
const struct xt_target *target,
const void *targinfo)
{
- struct sk_buff *skb = *pskb;
const struct xt_connsecmark_target_info *info = targinfo;
switch (info->mode) {
diff --git a/net/netfilter/xt_DSCP.c b/net/netfilter/xt_DSCP.c
index 798ab731009d..6322a933ab71 100644
--- a/net/netfilter/xt_DSCP.c
+++ b/net/netfilter/xt_DSCP.c
@@ -25,7 +25,7 @@ MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_DSCP");
MODULE_ALIAS("ip6t_DSCP");
-static unsigned int target(struct sk_buff **pskb,
+static unsigned int target(struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
unsigned int hooknum,
@@ -33,20 +33,20 @@ static unsigned int target(struct sk_buff **pskb,
const void *targinfo)
{
const struct xt_DSCP_info *dinfo = targinfo;
- u_int8_t dscp = ipv4_get_dsfield(ip_hdr(*pskb)) >> XT_DSCP_SHIFT;
+ u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT;
if (dscp != dinfo->dscp) {
- if (!skb_make_writable(pskb, sizeof(struct iphdr)))
+ if (!skb_make_writable(skb, sizeof(struct iphdr)))
return NF_DROP;
- ipv4_change_dsfield(ip_hdr(*pskb), (__u8)(~XT_DSCP_MASK),
+ ipv4_change_dsfield(ip_hdr(skb), (__u8)(~XT_DSCP_MASK),
dinfo->dscp << XT_DSCP_SHIFT);
}
return XT_CONTINUE;
}
-static unsigned int target6(struct sk_buff **pskb,
+static unsigned int target6(struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
unsigned int hooknum,
@@ -54,13 +54,13 @@ static unsigned int target6(struct sk_buff **pskb,
const void *targinfo)
{
const struct xt_DSCP_info *dinfo = targinfo;
- u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(*pskb)) >> XT_DSCP_SHIFT;
+ u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT;
if (dscp != dinfo->dscp) {
- if (!skb_make_writable(pskb, sizeof(struct ipv6hdr)))
+ if (!skb_make_writable(skb, sizeof(struct ipv6hdr)))
return NF_DROP;
- ipv6_change_dsfield(ipv6_hdr(*pskb), (__u8)(~XT_DSCP_MASK),
+ ipv6_change_dsfield(ipv6_hdr(skb), (__u8)(~XT_DSCP_MASK),
dinfo->dscp << XT_DSCP_SHIFT);
}
return XT_CONTINUE;
diff --git a/net/netfilter/xt_MARK.c b/net/netfilter/xt_MARK.c
index f30fe0baf7de..bc6503d77d75 100644
--- a/net/netfilter/xt_MARK.c
+++ b/net/netfilter/xt_MARK.c
@@ -22,7 +22,7 @@ MODULE_ALIAS("ipt_MARK");
MODULE_ALIAS("ip6t_MARK");
static unsigned int
-target_v0(struct sk_buff **pskb,
+target_v0(struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
unsigned int hooknum,
@@ -31,12 +31,12 @@ target_v0(struct sk_buff **pskb,
{
const struct xt_mark_target_info *markinfo = targinfo;
- (*pskb)->mark = markinfo->mark;
+ skb->mark = markinfo->mark;
return XT_CONTINUE;
}
static unsigned int
-target_v1(struct sk_buff **pskb,
+target_v1(struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
unsigned int hooknum,
@@ -52,15 +52,15 @@ target_v1(struct sk_buff **pskb,
break;
case XT_MARK_AND:
- mark = (*pskb)->mark & markinfo->mark;
+ mark = skb->mark & markinfo->mark;
break;
case XT_MARK_OR:
- mark = (*pskb)->mark | markinfo->mark;
+ mark = skb->mark | markinfo->mark;
break;
}
- (*pskb)->mark = mark;
+ skb->mark = mark;
return XT_CONTINUE;
}
diff --git a/net/netfilter/xt_NFLOG.c b/net/netfilter/xt_NFLOG.c
index d3594c7ccb26..9fb449ffbf8b 100644
--- a/net/netfilter/xt_NFLOG.c
+++ b/net/netfilter/xt_NFLOG.c
@@ -20,7 +20,7 @@ MODULE_ALIAS("ipt_NFLOG");
MODULE_ALIAS("ip6t_NFLOG");
static unsigned int
-nflog_target(struct sk_buff **pskb,
+nflog_target(struct sk_buff *skb,
const struct net_device *in, const struct net_device *out,
unsigned int hooknum, const struct xt_target *target,
const void *targinfo)
@@ -33,7 +33,7 @@ nflog_target(struct sk_buff **pskb,
li.u.ulog.group = info->group;
li.u.ulog.qthreshold = info->threshold;
- nf_log_packet(target->family, hooknum, *pskb, in, out, &li,
+ nf_log_packet(target->family, hooknum, skb, in, out, &li,
"%s", info->prefix);
return XT_CONTINUE;
}
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
index 13f59f3e8c38..c3984e9f766a 100644
--- a/net/netfilter/xt_NFQUEUE.c
+++ b/net/netfilter/xt_NFQUEUE.c
@@ -24,7 +24,7 @@ MODULE_ALIAS("ip6t_NFQUEUE");
MODULE_ALIAS("arpt_NFQUEUE");
static unsigned int
-target(struct sk_buff **pskb,
+target(struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
unsigned int hooknum,
diff --git a/net/netfilter/xt_NOTRACK.c b/net/netfilter/xt_NOTRACK.c
index fec1aefb1c32..4976ce186615 100644
--- a/net/netfilter/xt_NOTRACK.c
+++ b/net/netfilter/xt_NOTRACK.c
@@ -12,7 +12,7 @@ MODULE_ALIAS("ipt_NOTRACK");
MODULE_ALIAS("ip6t_NOTRACK");
static unsigned int
-target(struct sk_buff **pskb,
+target(struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
unsigned int hooknum,
@@ -20,16 +20,16 @@ target(struct sk_buff **pskb,
const void *targinfo)
{
/* Previously seen (loopback)? Ignore. */
- if ((*pskb)->nfct != NULL)
+ if (skb->nfct != NULL)
return XT_CONTINUE;
/* Attach fake conntrack entry.
If there is a real ct entry correspondig to this packet,
it'll hang aroun till timing out. We don't deal with it
for performance reasons. JK */
- (*pskb)->nfct = &nf_conntrack_untracked.ct_general;
- (*pskb)->nfctinfo = IP_CT_NEW;
- nf_conntrack_get((*pskb)->nfct);
+ skb->nfct = &nf_conntrack_untracked.ct_general;
+ skb->nfctinfo = IP_CT_NEW;
+ nf_conntrack_get(skb->nfct);
return XT_CONTINUE;
}
diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c
index c83779a941a1..235806eb6ecd 100644
--- a/net/netfilter/xt_SECMARK.c
+++ b/net/netfilter/xt_SECMARK.c
@@ -28,7 +28,7 @@ MODULE_ALIAS("ip6t_SECMARK");
static u8 mode;
-static unsigned int target(struct sk_buff **pskb, const struct net_device *in,
+static unsigned int target(struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, unsigned int hooknum,
const struct xt_target *target,
const void *targinfo)
@@ -47,7 +47,7 @@ static unsigned int target(struct sk_buff **pskb, const struct net_device *in,
BUG();
}
- (*pskb)->secmark = secmark;
+ skb->secmark = secmark;
return XT_CONTINUE;
}
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c
index d40f7e4b1289..07435a602b11 100644
--- a/net/netfilter/xt_TCPMSS.c
+++ b/net/netfilter/xt_TCPMSS.c
@@ -39,7 +39,7 @@ optlen(const u_int8_t *opt, unsigned int offset)
}
static int
-tcpmss_mangle_packet(struct sk_buff **pskb,
+tcpmss_mangle_packet(struct sk_buff *skb,
const struct xt_tcpmss_info *info,
unsigned int tcphoff,
unsigned int minlen)
@@ -50,11 +50,11 @@ tcpmss_mangle_packet(struct sk_buff **pskb,
u16 newmss;
u8 *opt;
- if (!skb_make_writable(pskb, (*pskb)->len))
+ if (!skb_make_writable(skb, skb->len))
return -1;
- tcplen = (*pskb)->len - tcphoff;
- tcph = (struct tcphdr *)(skb_network_header(*pskb) + tcphoff);
+ tcplen = skb->len - tcphoff;
+ tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff);
/* Since it passed flags test in tcp match, we know it is is
not a fragment, and has data >= tcp header length. SYN
@@ -64,19 +64,19 @@ tcpmss_mangle_packet(struct sk_buff **pskb,
if (tcplen != tcph->doff*4) {
if (net_ratelimit())
printk(KERN_ERR "xt_TCPMSS: bad length (%u bytes)\n",
- (*pskb)->len);
+ skb->len);
return -1;
}
if (info->mss == XT_TCPMSS_CLAMP_PMTU) {
- if (dst_mtu((*pskb)->dst) <= minlen) {
+ if (dst_mtu(skb->dst) <= minlen) {
if (net_ratelimit())
printk(KERN_ERR "xt_TCPMSS: "
"unknown or invalid path-MTU (%u)\n",
- dst_mtu((*pskb)->dst));
+ dst_mtu(skb->dst));
return -1;
}
- newmss = dst_mtu((*pskb)->dst) - minlen;
+ newmss = dst_mtu(skb->dst) - minlen;
} else
newmss = info->mss;
@@ -95,7 +95,7 @@ tcpmss_mangle_packet(struct sk_buff **pskb,
opt[i+2] = (newmss & 0xff00) >> 8;
opt[i+3] = newmss & 0x00ff;
- nf_proto_csum_replace2(&tcph->check, *pskb,
+ nf_proto_csum_replace2(&tcph->check, skb,
htons(oldmss), htons(newmss), 0);
return 0;
}
@@ -104,57 +104,53 @@ tcpmss_mangle_packet(struct sk_buff **pskb,
/*
* MSS Option not found ?! add it..
*/
- if (skb_tailroom((*pskb)) < TCPOLEN_MSS) {
- struct sk_buff *newskb;
-
- newskb = skb_copy_expand(*pskb, skb_headroom(*pskb),
- TCPOLEN_MSS, GFP_ATOMIC);
- if (!newskb)
+ if (skb_tailroom(skb) < TCPOLEN_MSS) {
+ if (pskb_expand_head(skb, 0,
+ TCPOLEN_MSS - skb_tailroom(skb),
+ GFP_ATOMIC))
return -1;
- kfree_skb(*pskb);
- *pskb = newskb;
- tcph = (struct tcphdr *)(skb_network_header(*pskb) + tcphoff);
+ tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff);
}
- skb_put((*pskb), TCPOLEN_MSS);
+ skb_put(skb, TCPOLEN_MSS);
opt = (u_int8_t *)tcph + sizeof(struct tcphdr);
memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr));
- nf_proto_csum_replace2(&tcph->check, *pskb,
+ nf_proto_csum_replace2(&tcph->check, skb,
htons(tcplen), htons(tcplen + TCPOLEN_MSS), 1);
opt[0] = TCPOPT_MSS;
opt[1] = TCPOLEN_MSS;
opt[2] = (newmss & 0xff00) >> 8;
opt[3] = newmss & 0x00ff;
- nf_proto_csum_replace4(&tcph->check, *pskb, 0, *((__be32 *)opt), 0);
+ nf_proto_csum_replace4(&tcph->check, skb, 0, *((__be32 *)opt), 0);
oldval = ((__be16 *)tcph)[6];
tcph->doff += TCPOLEN_MSS/4;
- nf_proto_csum_replace2(&tcph->check, *pskb,
+ nf_proto_csum_replace2(&tcph->check, skb,
oldval, ((__be16 *)tcph)[6], 0);
return TCPOLEN_MSS;
}
static unsigned int
-xt_tcpmss_target4(struct sk_buff **pskb,
+xt_tcpmss_target4(struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
unsigned int hooknum,
const struct xt_target *target,
const void *targinfo)
{
- struct iphdr *iph = ip_hdr(*pskb);
+ struct iphdr *iph = ip_hdr(skb);
__be16 newlen;
int ret;
- ret = tcpmss_mangle_packet(pskb, targinfo, iph->ihl * 4,
+ ret = tcpmss_mangle_packet(skb, targinfo, iph->ihl * 4,
sizeof(*iph) + sizeof(struct tcphdr));
if (ret < 0)
return NF_DROP;
if (ret > 0) {
- iph = ip_hdr(*pskb);
+ iph = ip_hdr(skb);
newlen = htons(ntohs(iph->tot_len) + ret);
nf_csum_replace2(&iph->check, iph->tot_len, newlen);
iph->tot_len = newlen;
@@ -164,30 +160,30 @@ xt_tcpmss_target4(struct sk_buff **pskb,
#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
static unsigned int
-xt_tcpmss_target6(struct sk_buff **pskb,
+xt_tcpmss_target6(struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
unsigned int hooknum,
const struct xt_target *target,
const void *targinfo)
{
- struct ipv6hdr *ipv6h = ipv6_hdr(*pskb);
+ struct ipv6hdr *ipv6h = ipv6_hdr(skb);
u8 nexthdr;
int tcphoff;
int ret;
nexthdr = ipv6h->nexthdr;
- tcphoff = ipv6_skip_exthdr(*pskb, sizeof(*ipv6h), &nexthdr);
+ tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr);
if (tcphoff < 0) {
WARN_ON(1);
return NF_DROP;
}
- ret = tcpmss_mangle_packet(pskb, targinfo, tcphoff,
+ ret = tcpmss_mangle_packet(skb, targinfo, tcphoff,
sizeof(*ipv6h) + sizeof(struct tcphdr));
if (ret < 0)
return NF_DROP;
if (ret > 0) {
- ipv6h = ipv6_hdr(*pskb);
+ ipv6h = ipv6_hdr(skb);
ipv6h->payload_len = htons(ntohs(ipv6h->payload_len) + ret);
}
return XT_CONTINUE;
diff --git a/net/netfilter/xt_TRACE.c b/net/netfilter/xt_TRACE.c
index 4df2dedcc0b5..26c5d08ab2c2 100644
--- a/net/netfilter/xt_TRACE.c
+++ b/net/netfilter/xt_TRACE.c
@@ -10,14 +10,14 @@ MODULE_ALIAS("ipt_TRACE");
MODULE_ALIAS("ip6t_TRACE");
static unsigned int
-target(struct sk_buff **pskb,
+target(struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
unsigned int hooknum,
const struct xt_target *target,
const void *targinfo)
{
- (*pskb)->nf_trace = 1;
+ skb->nf_trace = 1;
return XT_CONTINUE;
}
diff --git a/net/netfilter/xt_connbytes.c b/net/netfilter/xt_connbytes.c
index af79423bc8e8..9ec50139b9a1 100644
--- a/net/netfilter/xt_connbytes.c
+++ b/net/netfilter/xt_connbytes.c
@@ -2,13 +2,13 @@
* GPL (C) 2002 Martin Devera (devik@cdi.cz).
*/
#include <linux/module.h>
+#include <linux/bitops.h>
#include <linux/skbuff.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_connbytes.h>
#include <net/netfilter/nf_conntrack.h>
#include <asm/div64.h>
-#include <asm/bitops.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c
index 06cff1d13690..d7becf08a93a 100644
--- a/net/netfilter/xt_connlimit.c
+++ b/net/netfilter/xt_connlimit.c
@@ -4,7 +4,8 @@
* (c) 2000 Gerd Knorr <kraxel@bytesex.org>
* Nov 2002: Martin Bene <martin.bene@icomedias.com>:
* only ignore TIME_WAIT or gone connections
- * Copyright © Jan Engelhardt <jengelh@gmx.de>, 2007
+ * (C) CC Computer Consultants GmbH, 2007
+ * Contact: <jengelh@computergmbh.de>
*
* based on ...
*
@@ -306,7 +307,7 @@ static void __exit xt_connlimit_exit(void)
module_init(xt_connlimit_init);
module_exit(xt_connlimit_exit);
-MODULE_AUTHOR("Jan Engelhardt <jengelh@gmx.de>");
+MODULE_AUTHOR("Jan Engelhardt <jengelh@computergmbh.de>");
MODULE_DESCRIPTION("netfilter xt_connlimit match module");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_connlimit");
diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c
index 1071fc54d6d3..9f67920af41f 100644
--- a/net/netfilter/xt_connmark.c
+++ b/net/netfilter/xt_connmark.c
@@ -25,7 +25,7 @@
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_connmark.h>
-MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
+MODULE_AUTHOR("Henrik Nordstrom <hno@marasystems.com>");
MODULE_DESCRIPTION("IP tables connmark match module");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_connmark");
diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c
index 4fcca797150f..f263a77e57b7 100644
--- a/net/netfilter/xt_limit.c
+++ b/net/netfilter/xt_limit.c
@@ -1,5 +1,5 @@
-/* (C) 1999 Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr>
- * (C) 1999 Hervé Eychenne <eychenne@info.enserb.u-bordeaux.fr>
+/* (C) 1999 Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr>
+ * (C) 1999 Hervé Eychenne <eychenne@info.enserb.u-bordeaux.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
diff --git a/net/netfilter/xt_sctp.c b/net/netfilter/xt_sctp.c
index f907770fd4e9..3358273a47b7 100644
--- a/net/netfilter/xt_sctp.c
+++ b/net/netfilter/xt_sctp.c
@@ -42,21 +42,21 @@ match_flags(const struct xt_sctp_flag_info *flag_info,
static inline bool
match_packet(const struct sk_buff *skb,
unsigned int offset,
- const u_int32_t *chunkmap,
- int chunk_match_type,
- const struct xt_sctp_flag_info *flag_info,
- const int flag_count,
+ const struct xt_sctp_info *info,
bool *hotdrop)
{
u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)];
sctp_chunkhdr_t _sch, *sch;
+ int chunk_match_type = info->chunk_match_type;
+ const struct xt_sctp_flag_info *flag_info = info->flag_info;
+ int flag_count = info->flag_count;
#ifdef DEBUG_SCTP
int i = 0;
#endif
if (chunk_match_type == SCTP_CHUNK_MATCH_ALL)
- SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap);
+ SCTP_CHUNKMAP_COPY(chunkmapcopy, info->chunkmap);
do {
sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch);
@@ -73,7 +73,7 @@ match_packet(const struct sk_buff *skb,
duprintf("skb->len: %d\toffset: %d\n", skb->len, offset);
- if (SCTP_CHUNKMAP_IS_SET(chunkmap, sch->type)) {
+ if (SCTP_CHUNKMAP_IS_SET(info->chunkmap, sch->type)) {
switch (chunk_match_type) {
case SCTP_CHUNK_MATCH_ANY:
if (match_flags(flag_info, flag_count,
@@ -104,7 +104,7 @@ match_packet(const struct sk_buff *skb,
switch (chunk_match_type) {
case SCTP_CHUNK_MATCH_ALL:
- return SCTP_CHUNKMAP_IS_CLEAR(chunkmap);
+ return SCTP_CHUNKMAP_IS_CLEAR(info->chunkmap);
case SCTP_CHUNK_MATCH_ANY:
return false;
case SCTP_CHUNK_MATCH_ONLY:
@@ -148,9 +148,7 @@ match(const struct sk_buff *skb,
&& ntohs(sh->dest) <= info->dpts[1],
XT_SCTP_DEST_PORTS, info->flags, info->invflags)
&& SCCHECK(match_packet(skb, protoff + sizeof (sctp_sctphdr_t),
- info->chunkmap, info->chunk_match_type,
- info->flag_info, info->flag_count,
- hotdrop),
+ info, hotdrop),
XT_SCTP_CHUNK_TYPES, info->flags, info->invflags);
}
diff --git a/net/netfilter/xt_time.c b/net/netfilter/xt_time.c
index ef48bbd93573..f9c55dcd894b 100644
--- a/net/netfilter/xt_time.c
+++ b/net/netfilter/xt_time.c
@@ -1,6 +1,7 @@
/*
* xt_time
- * Copyright © Jan Engelhardt <jengelh@computergmbh.de>, 2007
+ * Copyright © CC Computer Consultants GmbH, 2007
+ * Contact: <jengelh@computergmbh.de>
*
* based on ipt_time by Fabrice MARIE <fabrice@netfilter.org>
* This is a module which is used for time matching
@@ -169,7 +170,7 @@ static bool xt_time_match(const struct sk_buff *skb,
if (skb->tstamp.tv64 == 0)
__net_timestamp((struct sk_buff *)skb);
- stamp = skb->tstamp.tv64;
+ stamp = ktime_to_ns(skb->tstamp);
do_div(stamp, NSEC_PER_SEC);
if (info->flags & XT_TIME_LOCAL_TZ)
diff --git a/net/netfilter/xt_u32.c b/net/netfilter/xt_u32.c
index bec427915b30..af75b8c3f20b 100644
--- a/net/netfilter/xt_u32.c
+++ b/net/netfilter/xt_u32.c
@@ -2,7 +2,8 @@
* xt_u32 - kernel module to match u32 packet content
*
* Original author: Don Cohen <don@isis.cs3-inc.com>
- * © Jan Engelhardt <jengelh@gmx.de>, 2007
+ * (C) CC Computer Consultants GmbH, 2007
+ * Contact: <jengelh@computergmbh.de>
*/
#include <linux/module.h>
@@ -129,7 +130,7 @@ static void __exit xt_u32_exit(void)
module_init(xt_u32_init);
module_exit(xt_u32_exit);
-MODULE_AUTHOR("Jan Engelhardt <jengelh@gmx.de>");
+MODULE_AUTHOR("Jan Engelhardt <jengelh@computergmbh.de>");
MODULE_DESCRIPTION("netfilter u32 match module");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_u32");
diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c
index b6c844b7e1c1..b3675bd7db33 100644
--- a/net/netlabel/netlabel_domainhash.c
+++ b/net/netlabel/netlabel_domainhash.c
@@ -178,11 +178,9 @@ int netlbl_domhsh_init(u32 size)
for (iter = 0; iter < hsh_tbl->size; iter++)
INIT_LIST_HEAD(&hsh_tbl->tbl[iter]);
- rcu_read_lock();
spin_lock(&netlbl_domhsh_lock);
rcu_assign_pointer(netlbl_domhsh, hsh_tbl);
spin_unlock(&netlbl_domhsh_lock);
- rcu_read_unlock();
return 0;
}
@@ -222,7 +220,6 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry,
entry->valid = 1;
INIT_RCU_HEAD(&entry->rcu);
- ret_val = 0;
rcu_read_lock();
if (entry->domain != NULL) {
bkt = netlbl_domhsh_hash(entry->domain);
@@ -233,7 +230,7 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry,
else
ret_val = -EEXIST;
spin_unlock(&netlbl_domhsh_lock);
- } else if (entry->domain == NULL) {
+ } else {
INIT_LIST_HEAD(&entry->list);
spin_lock(&netlbl_domhsh_def_lock);
if (rcu_dereference(netlbl_domhsh_def) == NULL)
@@ -241,9 +238,7 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry,
else
ret_val = -EEXIST;
spin_unlock(&netlbl_domhsh_def_lock);
- } else
- ret_val = -EINVAL;
-
+ }
audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_ADD, audit_info);
if (audit_buf != NULL) {
audit_log_format(audit_buf,
@@ -262,7 +257,6 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry,
audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0);
audit_log_end(audit_buf);
}
-
rcu_read_unlock();
if (ret_val != 0) {
@@ -313,38 +307,30 @@ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info)
struct audit_buffer *audit_buf;
rcu_read_lock();
- if (domain != NULL)
- entry = netlbl_domhsh_search(domain, 0);
- else
- entry = netlbl_domhsh_search(domain, 1);
+ entry = netlbl_domhsh_search(domain, (domain != NULL ? 0 : 1));
if (entry == NULL)
goto remove_return;
switch (entry->type) {
- case NETLBL_NLTYPE_UNLABELED:
- break;
case NETLBL_NLTYPE_CIPSOV4:
- ret_val = cipso_v4_doi_domhsh_remove(entry->type_def.cipsov4,
- entry->domain);
- if (ret_val != 0)
- goto remove_return;
+ cipso_v4_doi_domhsh_remove(entry->type_def.cipsov4,
+ entry->domain);
break;
}
- ret_val = 0;
if (entry != rcu_dereference(netlbl_domhsh_def)) {
spin_lock(&netlbl_domhsh_lock);
if (entry->valid) {
entry->valid = 0;
list_del_rcu(&entry->list);
- } else
- ret_val = -ENOENT;
+ ret_val = 0;
+ }
spin_unlock(&netlbl_domhsh_lock);
} else {
spin_lock(&netlbl_domhsh_def_lock);
if (entry->valid) {
entry->valid = 0;
rcu_assign_pointer(netlbl_domhsh_def, NULL);
- } else
- ret_val = -ENOENT;
+ ret_val = 0;
+ }
spin_unlock(&netlbl_domhsh_def_lock);
}
@@ -357,11 +343,10 @@ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info)
audit_log_end(audit_buf);
}
- if (ret_val == 0)
- call_rcu(&entry->rcu, netlbl_domhsh_free_entry);
-
remove_return:
rcu_read_unlock();
+ if (ret_val == 0)
+ call_rcu(&entry->rcu, netlbl_domhsh_free_entry);
return ret_val;
}
diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c
index 5315dacc5222..56483377997a 100644
--- a/net/netlabel/netlabel_mgmt.c
+++ b/net/netlabel/netlabel_mgmt.c
@@ -85,11 +85,9 @@ static const struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = {
*/
void netlbl_mgmt_protocount_inc(void)
{
- rcu_read_lock();
spin_lock(&netlabel_mgmt_protocount_lock);
netlabel_mgmt_protocount++;
spin_unlock(&netlabel_mgmt_protocount_lock);
- rcu_read_unlock();
}
/**
@@ -103,12 +101,10 @@ void netlbl_mgmt_protocount_inc(void)
*/
void netlbl_mgmt_protocount_dec(void)
{
- rcu_read_lock();
spin_lock(&netlabel_mgmt_protocount_lock);
if (netlabel_mgmt_protocount > 0)
netlabel_mgmt_protocount--;
spin_unlock(&netlabel_mgmt_protocount_lock);
- rcu_read_unlock();
}
/**
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index 5c303c68af1d..348292450deb 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -84,12 +84,10 @@ static void netlbl_unlabel_acceptflg_set(u8 value,
struct audit_buffer *audit_buf;
u8 old_val;
- rcu_read_lock();
- old_val = netlabel_unlabel_acceptflg;
spin_lock(&netlabel_unlabel_acceptflg_lock);
+ old_val = netlabel_unlabel_acceptflg;
netlabel_unlabel_acceptflg = value;
spin_unlock(&netlabel_unlabel_acceptflg_lock);
- rcu_read_unlock();
audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_ALLOW,
audit_info);
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index c776bcd9f825..de3988ba1f46 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -396,7 +396,7 @@ static int __netlink_create(struct net *net, struct socket *sock,
sock->ops = &netlink_ops;
- sk = sk_alloc(net, PF_NETLINK, GFP_KERNEL, &netlink_proto, 1);
+ sk = sk_alloc(net, PF_NETLINK, GFP_KERNEL, &netlink_proto);
if (!sk)
return -ENOMEM;
@@ -752,7 +752,7 @@ struct sock *netlink_getsockbyfilp(struct file *filp)
* 1: repeat lookup - reference dropped while waiting for socket memory.
*/
int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock,
- long timeo, struct sock *ssk)
+ long *timeo, struct sock *ssk)
{
struct netlink_sock *nlk;
@@ -761,7 +761,7 @@ int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock,
if (atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf ||
test_bit(0, &nlk->state)) {
DECLARE_WAITQUEUE(wait, current);
- if (!timeo) {
+ if (!*timeo) {
if (!ssk || netlink_is_kernel(ssk))
netlink_overrun(sk);
sock_put(sk);
@@ -775,7 +775,7 @@ int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock,
if ((atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf ||
test_bit(0, &nlk->state)) &&
!sock_flag(sk, SOCK_DEAD))
- timeo = schedule_timeout(timeo);
+ *timeo = schedule_timeout(*timeo);
__set_current_state(TASK_RUNNING);
remove_wait_queue(&nlk->wait, &wait);
@@ -783,7 +783,7 @@ int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock,
if (signal_pending(current)) {
kfree_skb(skb);
- return sock_intr_errno(timeo);
+ return sock_intr_errno(*timeo);
}
return 1;
}
@@ -877,7 +877,7 @@ retry:
if (netlink_is_kernel(sk))
return netlink_unicast_kernel(sk, skb);
- err = netlink_attachskb(sk, skb, nonblock, timeo, ssk);
+ err = netlink_attachskb(sk, skb, nonblock, &timeo, ssk);
if (err == 1)
goto retry;
if (err)
@@ -1378,6 +1378,8 @@ netlink_kernel_create(struct net *net, int unit, unsigned int groups,
nl_table[unit].cb_mutex = cb_mutex;
nl_table[unit].module = module;
nl_table[unit].registered = 1;
+ } else {
+ kfree(listeners);
}
netlink_table_ungrab();
@@ -1563,7 +1565,11 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
netlink_dump(sk);
sock_put(sk);
- return 0;
+
+ /* We successfully started a dump, by returning -EINTR we
+ * signal not to send ACK even if it was requested.
+ */
+ return -EINTR;
}
void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err)
@@ -1617,17 +1623,21 @@ int netlink_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *,
/* Only requests are handled by the kernel */
if (!(nlh->nlmsg_flags & NLM_F_REQUEST))
- goto skip;
+ goto ack;
/* Skip control messages */
if (nlh->nlmsg_type < NLMSG_MIN_TYPE)
- goto skip;
+ goto ack;
err = cb(skb, nlh);
-skip:
+ if (err == -EINTR)
+ goto skip;
+
+ack:
if (nlh->nlmsg_flags & NLM_F_ACK || err)
netlink_ack(skb, nlh, err);
+skip:
msglen = NLMSG_ALIGN(nlh->nlmsg_len);
if (msglen > skb->len)
msglen = skb->len;
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index 3a4d479ea64e..972250c974f1 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -423,7 +423,8 @@ static int nr_create(struct net *net, struct socket *sock, int protocol)
if (sock->type != SOCK_SEQPACKET || protocol != 0)
return -ESOCKTNOSUPPORT;
- if ((sk = sk_alloc(net, PF_NETROM, GFP_ATOMIC, &nr_proto, 1)) == NULL)
+ sk = sk_alloc(net, PF_NETROM, GFP_ATOMIC, &nr_proto);
+ if (sk == NULL)
return -ENOMEM;
nr = nr_sk(sk);
@@ -465,7 +466,8 @@ static struct sock *nr_make_new(struct sock *osk)
if (osk->sk_type != SOCK_SEQPACKET)
return NULL;
- if ((sk = sk_alloc(osk->sk_net, PF_NETROM, GFP_ATOMIC, osk->sk_prot, 1)) == NULL)
+ sk = sk_alloc(osk->sk_net, PF_NETROM, GFP_ATOMIC, osk->sk_prot);
+ if (sk == NULL)
return NULL;
nr = nr_sk(sk);
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index e11000a8e950..8a7807dbba01 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -139,9 +139,6 @@ dev->hard_header == NULL (ll header is added by device, we cannot control it)
static HLIST_HEAD(packet_sklist);
static DEFINE_RWLOCK(packet_sklist_lock);
-static atomic_t packet_socks_nr;
-
-
/* Private packet socket structures. */
struct packet_mclist
@@ -236,10 +233,7 @@ static void packet_sock_destruct(struct sock *sk)
return;
}
- atomic_dec(&packet_socks_nr);
-#ifdef PACKET_REFCNT_DEBUG
- printk(KERN_DEBUG "PACKET socket %p is free, %d are alive\n", sk, atomic_read(&packet_socks_nr));
-#endif
+ sk_refcnt_debug_dec(sk);
}
@@ -515,7 +509,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet
sll->sll_hatype = dev->type;
sll->sll_protocol = skb->protocol;
sll->sll_pkttype = skb->pkt_type;
- if (unlikely(po->origdev) && skb->pkt_type == PACKET_HOST)
+ if (unlikely(po->origdev))
sll->sll_ifindex = orig_dev->ifindex;
else
sll->sll_ifindex = dev->ifindex;
@@ -661,7 +655,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
sll->sll_hatype = dev->type;
sll->sll_protocol = skb->protocol;
sll->sll_pkttype = skb->pkt_type;
- if (unlikely(po->origdev) && skb->pkt_type == PACKET_HOST)
+ if (unlikely(po->origdev))
sll->sll_ifindex = orig_dev->ifindex;
else
sll->sll_ifindex = dev->ifindex;
@@ -849,6 +843,7 @@ static int packet_release(struct socket *sock)
/* Purge queues */
skb_queue_purge(&sk->sk_receive_queue);
+ sk_refcnt_debug_release(sk);
sock_put(sk);
return 0;
@@ -886,20 +881,14 @@ static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 protoc
if (protocol == 0)
goto out_unlock;
- if (dev) {
- if (dev->flags&IFF_UP) {
- dev_add_pack(&po->prot_hook);
- sock_hold(sk);
- po->running = 1;
- } else {
- sk->sk_err = ENETDOWN;
- if (!sock_flag(sk, SOCK_DEAD))
- sk->sk_error_report(sk);
- }
- } else {
+ if (!dev || (dev->flags & IFF_UP)) {
dev_add_pack(&po->prot_hook);
sock_hold(sk);
po->running = 1;
+ } else {
+ sk->sk_err = ENETDOWN;
+ if (!sock_flag(sk, SOCK_DEAD))
+ sk->sk_error_report(sk);
}
out_unlock:
@@ -995,7 +984,7 @@ static int packet_create(struct net *net, struct socket *sock, int protocol)
sock->state = SS_UNCONNECTED;
err = -ENOBUFS;
- sk = sk_alloc(net, PF_PACKET, GFP_KERNEL, &packet_proto, 1);
+ sk = sk_alloc(net, PF_PACKET, GFP_KERNEL, &packet_proto);
if (sk == NULL)
goto out;
@@ -1010,7 +999,7 @@ static int packet_create(struct net *net, struct socket *sock, int protocol)
po->num = proto;
sk->sk_destruct = packet_sock_destruct;
- atomic_inc(&packet_socks_nr);
+ sk_refcnt_debug_inc(sk);
/*
* Attach a protocol block
@@ -1623,11 +1612,6 @@ static struct vm_operations_struct packet_mmap_ops = {
.close =packet_mm_close,
};
-static inline struct page *pg_vec_endpage(char *one_pg_vec, unsigned int order)
-{
- return virt_to_page(one_pg_vec + (PAGE_SIZE << order) - 1);
-}
-
static void free_pg_vec(char **pg_vec, unsigned int order, unsigned int len)
{
int i;
diff --git a/net/rfkill/rfkill-input.c b/net/rfkill/rfkill-input.c
index eaabf087c59b..d1e9d68f8ba0 100644
--- a/net/rfkill/rfkill-input.c
+++ b/net/rfkill/rfkill-input.c
@@ -146,18 +146,18 @@ static void rfkill_disconnect(struct input_handle *handle)
static const struct input_device_id rfkill_ids[] = {
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT,
- .evbit = { BIT(EV_KEY) },
- .keybit = { [LONG(KEY_WLAN)] = BIT(KEY_WLAN) },
+ .evbit = { BIT_MASK(EV_KEY) },
+ .keybit = { [BIT_WORD(KEY_WLAN)] = BIT_MASK(KEY_WLAN) },
},
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT,
- .evbit = { BIT(EV_KEY) },
- .keybit = { [LONG(KEY_BLUETOOTH)] = BIT(KEY_BLUETOOTH) },
+ .evbit = { BIT_MASK(EV_KEY) },
+ .keybit = { [BIT_WORD(KEY_BLUETOOTH)] = BIT_MASK(KEY_BLUETOOTH) },
},
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT,
- .evbit = { BIT(EV_KEY) },
- .keybit = { [LONG(KEY_UWB)] = BIT(KEY_UWB) },
+ .evbit = { BIT_MASK(EV_KEY) },
+ .keybit = { [BIT_WORD(KEY_UWB)] = BIT_MASK(KEY_UWB) },
},
{ }
};
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c
index 51d151c0e962..73d60a307129 100644
--- a/net/rfkill/rfkill.c
+++ b/net/rfkill/rfkill.c
@@ -27,6 +27,10 @@
#include <linux/mutex.h>
#include <linux/rfkill.h>
+/* Get declaration of rfkill_switch_all() to shut up sparse. */
+#include "rfkill-input.h"
+
+
MODULE_AUTHOR("Ivo van Doorn <IvDoorn@gmail.com>");
MODULE_VERSION("1.0");
MODULE_DESCRIPTION("RF switch support");
@@ -276,21 +280,17 @@ static struct class rfkill_class = {
static int rfkill_add_switch(struct rfkill *rfkill)
{
- int retval;
-
- retval = mutex_lock_interruptible(&rfkill_mutex);
- if (retval)
- return retval;
+ int error;
- retval = rfkill_toggle_radio(rfkill, rfkill_states[rfkill->type]);
- if (retval)
- goto out;
+ mutex_lock(&rfkill_mutex);
- list_add_tail(&rfkill->node, &rfkill_list);
+ error = rfkill_toggle_radio(rfkill, rfkill_states[rfkill->type]);
+ if (!error)
+ list_add_tail(&rfkill->node, &rfkill_list);
- out:
mutex_unlock(&rfkill_mutex);
- return retval;
+
+ return error;
}
static void rfkill_remove_switch(struct rfkill *rfkill)
@@ -387,20 +387,23 @@ int rfkill_register(struct rfkill *rfkill)
if (!rfkill->toggle_radio)
return -EINVAL;
+ if (rfkill->type >= RFKILL_TYPE_MAX)
+ return -EINVAL;
+
+ snprintf(dev->bus_id, sizeof(dev->bus_id),
+ "rfkill%ld", (long)atomic_inc_return(&rfkill_no) - 1);
+
+ rfkill_led_trigger_register(rfkill);
error = rfkill_add_switch(rfkill);
if (error)
return error;
- snprintf(dev->bus_id, sizeof(dev->bus_id),
- "rfkill%ld", (long)atomic_inc_return(&rfkill_no) - 1);
-
error = device_add(dev);
if (error) {
rfkill_remove_switch(rfkill);
return error;
}
- rfkill_led_trigger_register(rfkill);
return 0;
}
@@ -416,9 +419,9 @@ EXPORT_SYMBOL(rfkill_register);
*/
void rfkill_unregister(struct rfkill *rfkill)
{
- rfkill_led_trigger_unregister(rfkill);
device_del(&rfkill->dev);
rfkill_remove_switch(rfkill);
+ rfkill_led_trigger_unregister(rfkill);
put_device(&rfkill->dev);
}
EXPORT_SYMBOL(rfkill_unregister);
@@ -448,5 +451,5 @@ static void __exit rfkill_exit(void)
class_unregister(&rfkill_class);
}
-module_init(rfkill_init);
+subsys_initcall(rfkill_init);
module_exit(rfkill_exit);
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index 509defe53ee5..ed2d65cd8010 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -513,7 +513,8 @@ static int rose_create(struct net *net, struct socket *sock, int protocol)
if (sock->type != SOCK_SEQPACKET || protocol != 0)
return -ESOCKTNOSUPPORT;
- if ((sk = sk_alloc(net, PF_ROSE, GFP_ATOMIC, &rose_proto, 1)) == NULL)
+ sk = sk_alloc(net, PF_ROSE, GFP_ATOMIC, &rose_proto);
+ if (sk == NULL)
return -ENOMEM;
rose = rose_sk(sk);
@@ -551,7 +552,8 @@ static struct sock *rose_make_new(struct sock *osk)
if (osk->sk_type != SOCK_SEQPACKET)
return NULL;
- if ((sk = sk_alloc(osk->sk_net, PF_ROSE, GFP_ATOMIC, &rose_proto, 1)) == NULL)
+ sk = sk_alloc(osk->sk_net, PF_ROSE, GFP_ATOMIC, &rose_proto);
+ if (sk == NULL)
return NULL;
rose = rose_sk(sk);
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c
index 0803f305ed08..d6389450c4bf 100644
--- a/net/rxrpc/af_rxrpc.c
+++ b/net/rxrpc/af_rxrpc.c
@@ -14,6 +14,7 @@
#include <linux/skbuff.h>
#include <linux/poll.h>
#include <linux/proc_fs.h>
+#include <linux/key-type.h>
#include <net/net_namespace.h>
#include <net/sock.h>
#include <net/af_rxrpc.h>
@@ -626,7 +627,7 @@ static int rxrpc_create(struct net *net, struct socket *sock, int protocol)
sock->ops = &rxrpc_rpc_ops;
sock->state = SS_UNCONNECTED;
- sk = sk_alloc(net, PF_RXRPC, GFP_KERNEL, &rxrpc_proto, 1);
+ sk = sk_alloc(net, PF_RXRPC, GFP_KERNEL, &rxrpc_proto);
if (!sk)
return -ENOMEM;
diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c
index 7e049ff6ae60..9a8ff684da79 100644
--- a/net/rxrpc/ar-key.c
+++ b/net/rxrpc/ar-key.c
@@ -15,7 +15,7 @@
#include <linux/module.h>
#include <linux/net.h>
#include <linux/skbuff.h>
-#include <linux/key.h>
+#include <linux/key-type.h>
#include <linux/crypto.h>
#include <net/sock.h>
#include <net/af_rxrpc.h>
@@ -40,7 +40,6 @@ struct key_type key_type_rxrpc = {
.destroy = rxrpc_destroy,
.describe = rxrpc_describe,
};
-
EXPORT_SYMBOL(key_type_rxrpc);
/*
@@ -330,5 +329,32 @@ error:
_leave(" = -ENOMEM [ins %d]", ret);
return -ENOMEM;
}
-
EXPORT_SYMBOL(rxrpc_get_server_data_key);
+
+/**
+ * rxrpc_get_null_key - Generate a null RxRPC key
+ * @keyname: The name to give the key.
+ *
+ * Generate a null RxRPC key that can be used to indicate anonymous security is
+ * required for a particular domain.
+ */
+struct key *rxrpc_get_null_key(const char *keyname)
+{
+ struct key *key;
+ int ret;
+
+ key = key_alloc(&key_type_rxrpc, keyname, 0, 0, current,
+ KEY_POS_SEARCH, KEY_ALLOC_NOT_IN_QUOTA);
+ if (IS_ERR(key))
+ return key;
+
+ ret = key_instantiate_and_link(key, NULL, 0, NULL, NULL);
+ if (ret < 0) {
+ key_revoke(key);
+ key_put(key);
+ return ERR_PTR(ret);
+ }
+
+ return key;
+}
+EXPORT_SYMBOL(rxrpc_get_null_key);
diff --git a/net/rxrpc/ar-local.c b/net/rxrpc/ar-local.c
index fe03f71f17da..f3a2bd747a8f 100644
--- a/net/rxrpc/ar-local.c
+++ b/net/rxrpc/ar-local.c
@@ -114,7 +114,7 @@ static int rxrpc_create_local(struct rxrpc_local *local)
return 0;
error:
- local->socket->ops->shutdown(local->socket, 2);
+ kernel_sock_shutdown(local->socket, SHUT_RDWR);
local->socket->sk->sk_user_data = NULL;
sock_release(local->socket);
local->socket = NULL;
@@ -267,7 +267,7 @@ static void rxrpc_destroy_local(struct work_struct *work)
/* finish cleaning up the local descriptor */
rxrpc_purge_queue(&local->accept_queue);
rxrpc_purge_queue(&local->reject_queue);
- local->socket->ops->shutdown(local->socket, 2);
+ kernel_sock_shutdown(local->socket, SHUT_RDWR);
sock_release(local->socket);
up_read(&rxrpc_local_sem);
diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c
index ac3cabdca78c..e09a95aa68ff 100644
--- a/net/rxrpc/rxkad.c
+++ b/net/rxrpc/rxkad.c
@@ -135,9 +135,8 @@ static void rxkad_prime_packet_security(struct rxrpc_connection *conn)
tmpbuf.x[2] = 0;
tmpbuf.x[3] = htonl(conn->security_ix);
- memset(sg, 0, sizeof(sg));
- sg_set_buf(&sg[0], &tmpbuf, sizeof(tmpbuf));
- sg_set_buf(&sg[1], &tmpbuf, sizeof(tmpbuf));
+ sg_init_one(&sg[0], &tmpbuf, sizeof(tmpbuf));
+ sg_init_one(&sg[1], &tmpbuf, sizeof(tmpbuf));
crypto_blkcipher_encrypt_iv(&desc, &sg[0], &sg[1], sizeof(tmpbuf));
memcpy(&conn->csum_iv, &tmpbuf.x[2], sizeof(conn->csum_iv));
@@ -180,9 +179,8 @@ static int rxkad_secure_packet_auth(const struct rxrpc_call *call,
desc.info = iv.x;
desc.flags = 0;
- memset(sg, 0, sizeof(sg));
- sg_set_buf(&sg[0], &tmpbuf, sizeof(tmpbuf));
- sg_set_buf(&sg[1], &tmpbuf, sizeof(tmpbuf));
+ sg_init_one(&sg[0], &tmpbuf, sizeof(tmpbuf));
+ sg_init_one(&sg[1], &tmpbuf, sizeof(tmpbuf));
crypto_blkcipher_encrypt_iv(&desc, &sg[0], &sg[1], sizeof(tmpbuf));
memcpy(sechdr, &tmpbuf, sizeof(tmpbuf));
@@ -227,9 +225,8 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call,
desc.info = iv.x;
desc.flags = 0;
- memset(sg, 0, sizeof(sg[0]) * 2);
- sg_set_buf(&sg[0], sechdr, sizeof(rxkhdr));
- sg_set_buf(&sg[1], &rxkhdr, sizeof(rxkhdr));
+ sg_init_one(&sg[0], sechdr, sizeof(rxkhdr));
+ sg_init_one(&sg[1], &rxkhdr, sizeof(rxkhdr));
crypto_blkcipher_encrypt_iv(&desc, &sg[0], &sg[1], sizeof(rxkhdr));
/* we want to encrypt the skbuff in-place */
@@ -240,6 +237,7 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call,
len = data_size + call->conn->size_align - 1;
len &= ~(call->conn->size_align - 1);
+ sg_init_table(sg, nsg);
skb_to_sgvec(skb, sg, 0, len);
crypto_blkcipher_encrypt_iv(&desc, sg, sg, len);
@@ -290,9 +288,8 @@ static int rxkad_secure_packet(const struct rxrpc_call *call,
tmpbuf.x[0] = sp->hdr.callNumber;
tmpbuf.x[1] = x;
- memset(&sg, 0, sizeof(sg));
- sg_set_buf(&sg[0], &tmpbuf, sizeof(tmpbuf));
- sg_set_buf(&sg[1], &tmpbuf, sizeof(tmpbuf));
+ sg_init_one(&sg[0], &tmpbuf, sizeof(tmpbuf));
+ sg_init_one(&sg[1], &tmpbuf, sizeof(tmpbuf));
crypto_blkcipher_encrypt_iv(&desc, &sg[0], &sg[1], sizeof(tmpbuf));
x = ntohl(tmpbuf.x[1]);
@@ -332,19 +329,22 @@ static int rxkad_verify_packet_auth(const struct rxrpc_call *call,
struct rxrpc_skb_priv *sp;
struct blkcipher_desc desc;
struct rxrpc_crypt iv;
- struct scatterlist sg[2];
+ struct scatterlist sg[16];
struct sk_buff *trailer;
u32 data_size, buf;
u16 check;
+ int nsg;
_enter("");
sp = rxrpc_skb(skb);
/* we want to decrypt the skbuff in-place */
- if (skb_cow_data(skb, 0, &trailer) < 0)
+ nsg = skb_cow_data(skb, 0, &trailer);
+ if (nsg < 0 || nsg > 16)
goto nomem;
+ sg_init_table(sg, nsg);
skb_to_sgvec(skb, sg, 0, 8);
/* start the decryption afresh */
@@ -426,6 +426,7 @@ static int rxkad_verify_packet_encrypt(const struct rxrpc_call *call,
goto nomem;
}
+ sg_init_table(sg, nsg);
skb_to_sgvec(skb, sg, 0, skb->len);
/* decrypt from the session key */
@@ -521,9 +522,8 @@ static int rxkad_verify_packet(const struct rxrpc_call *call,
tmpbuf.x[0] = call->call_id;
tmpbuf.x[1] = x;
- memset(&sg, 0, sizeof(sg));
- sg_set_buf(&sg[0], &tmpbuf, sizeof(tmpbuf));
- sg_set_buf(&sg[1], &tmpbuf, sizeof(tmpbuf));
+ sg_init_one(&sg[0], &tmpbuf, sizeof(tmpbuf));
+ sg_init_one(&sg[1], &tmpbuf, sizeof(tmpbuf));
crypto_blkcipher_encrypt_iv(&desc, &sg[0], &sg[1], sizeof(tmpbuf));
x = ntohl(tmpbuf.x[1]);
@@ -690,16 +690,20 @@ static void rxkad_calc_response_checksum(struct rxkad_response *response)
static void rxkad_sg_set_buf2(struct scatterlist sg[2],
void *buf, size_t buflen)
{
+ int nsg = 1;
- memset(sg, 0, sizeof(sg));
+ sg_init_table(sg, 2);
sg_set_buf(&sg[0], buf, buflen);
if (sg[0].offset + buflen > PAGE_SIZE) {
/* the buffer was split over two pages */
sg[0].length = PAGE_SIZE - sg[0].offset;
sg_set_buf(&sg[1], buf + sg[0].length, buflen - sg[0].length);
+ nsg++;
}
+ sg_mark_end(&sg[nsg - 1]);
+
ASSERTCMP(sg[0].length + sg[1].length, ==, buflen);
}
@@ -712,7 +716,7 @@ static void rxkad_encrypt_response(struct rxrpc_connection *conn,
{
struct blkcipher_desc desc;
struct rxrpc_crypt iv;
- struct scatterlist ssg[2], dsg[2];
+ struct scatterlist sg[2];
/* continue encrypting from where we left off */
memcpy(&iv, s2->session_key, sizeof(iv));
@@ -720,9 +724,8 @@ static void rxkad_encrypt_response(struct rxrpc_connection *conn,
desc.info = iv.x;
desc.flags = 0;
- rxkad_sg_set_buf2(ssg, &resp->encrypted, sizeof(resp->encrypted));
- memcpy(dsg, ssg, sizeof(dsg));
- crypto_blkcipher_encrypt_iv(&desc, dsg, ssg, sizeof(resp->encrypted));
+ rxkad_sg_set_buf2(sg, &resp->encrypted, sizeof(resp->encrypted));
+ crypto_blkcipher_encrypt_iv(&desc, sg, sg, sizeof(resp->encrypted));
}
/*
@@ -817,7 +820,7 @@ static int rxkad_decrypt_ticket(struct rxrpc_connection *conn,
{
struct blkcipher_desc desc;
struct rxrpc_crypt iv, key;
- struct scatterlist ssg[1], dsg[1];
+ struct scatterlist sg[1];
struct in_addr addr;
unsigned life;
time_t issue, now;
@@ -850,9 +853,8 @@ static int rxkad_decrypt_ticket(struct rxrpc_connection *conn,
desc.info = iv.x;
desc.flags = 0;
- sg_init_one(&ssg[0], ticket, ticket_len);
- memcpy(dsg, ssg, sizeof(dsg));
- crypto_blkcipher_decrypt_iv(&desc, dsg, ssg, ticket_len);
+ sg_init_one(&sg[0], ticket, ticket_len);
+ crypto_blkcipher_decrypt_iv(&desc, sg, sg, ticket_len);
p = ticket;
end = p + ticket_len;
@@ -961,7 +963,7 @@ static void rxkad_decrypt_response(struct rxrpc_connection *conn,
const struct rxrpc_crypt *session_key)
{
struct blkcipher_desc desc;
- struct scatterlist ssg[2], dsg[2];
+ struct scatterlist sg[2];
struct rxrpc_crypt iv;
_enter(",,%08x%08x",
@@ -979,9 +981,8 @@ static void rxkad_decrypt_response(struct rxrpc_connection *conn,
desc.info = iv.x;
desc.flags = 0;
- rxkad_sg_set_buf2(ssg, &resp->encrypted, sizeof(resp->encrypted));
- memcpy(dsg, ssg, sizeof(dsg));
- crypto_blkcipher_decrypt_iv(&desc, dsg, ssg, sizeof(resp->encrypted));
+ rxkad_sg_set_buf2(sg, &resp->encrypted, sizeof(resp->encrypted));
+ crypto_blkcipher_decrypt_iv(&desc, sg, sg, sizeof(resp->encrypted));
mutex_unlock(&rxkad_ci_mutex);
_leave("");
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index 92435a882fac..9c15c4888d12 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -2,9 +2,7 @@
# Traffic control configuration.
#
-menu "QoS and/or fair queueing"
-
-config NET_SCHED
+menuconfig NET_SCHED
bool "QoS and/or fair queueing"
select NET_SCH_FIFO
---help---
@@ -41,9 +39,6 @@ config NET_SCHED
The available schedulers are listed in the following questions; you
can say Y to as many as you like. If unsure, say N now.
-config NET_SCH_FIFO
- bool
-
if NET_SCHED
comment "Queueing/Scheduling"
@@ -500,4 +495,5 @@ config NET_CLS_IND
endif # NET_SCHED
-endmenu
+config NET_SCH_FIFO
+ bool
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index 6b407ece953c..fa006e06ce33 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -202,11 +202,7 @@ static int tcf_ipt(struct sk_buff *skb, struct tc_action *a,
/* yes, we have to worry about both in and out dev
worry later - danger - this API seems to have changed
from earlier kernels */
-
- /* iptables targets take a double skb pointer in case the skb
- * needs to be replaced. We don't own the skb, so this must not
- * happen. The pskb_expand_head above should make sure of this */
- ret = ipt->tcfi_t->u.kernel.target->target(&skb, skb->dev, NULL,
+ ret = ipt->tcfi_t->u.kernel.target->target(skb, skb->dev, NULL,
ipt->tcfi_hook,
ipt->tcfi_t->u.kernel.target,
ipt->tcfi_t->data);
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index fd7bca4d5c20..c3fde9180f9d 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -166,7 +166,7 @@ bad_mirred:
return TC_ACT_SHOT;
}
- skb2 = skb_clone(skb, GFP_ATOMIC);
+ skb2 = skb_act_clone(skb, GFP_ATOMIC);
if (skb2 == NULL)
goto bad_mirred;
if (m->tcfm_eaction != TCA_EGRESS_MIRROR &&
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 9e98c6e567dd..c39008209164 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -91,7 +91,7 @@ static struct tc_u_common *u32_list;
static __inline__ unsigned u32_hash_fold(u32 key, struct tc_u32_sel *sel, u8 fshift)
{
- unsigned h = (key & sel->hmask)>>fshift;
+ unsigned h = ntohl(key & sel->hmask)>>fshift;
return h;
}
@@ -613,17 +613,7 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
memcpy(&n->sel, s, sizeof(*s) + s->nkeys*sizeof(struct tc_u32_key));
n->ht_up = ht;
n->handle = handle;
-{
- u8 i = 0;
- u32 mask = s->hmask;
- if (mask) {
- while (!(mask & 1)) {
- i++;
- mask>>=1;
- }
- }
- n->fshift = i;
-}
+ n->fshift = s->hmask ? ffs(ntohl(s->hmask)) - 1 : 0;
#ifdef CONFIG_CLS_U32_MARK
if (tb[TCA_U32_MARK-1]) {
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c
index e9989610712c..ceda8890ab0e 100644
--- a/net/sched/em_meta.c
+++ b/net/sched/em_meta.c
@@ -55,7 +55,7 @@
* ppp0..9.
*
* NOTE: Certain meta values depend on other subsystems and are
- * only available if that subsytem is enabled in the kernel.
+ * only available if that subsystem is enabled in the kernel.
*/
#include <linux/module.h>
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 95ae11956f35..e595e6570ce0 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -134,7 +134,7 @@ static inline int qdisc_restart(struct net_device *dev)
{
struct Qdisc *q = dev->qdisc;
struct sk_buff *skb;
- int ret;
+ int ret = NETDEV_TX_BUSY;
/* Dequeue packet */
if (unlikely((skb = dev_dequeue_skb(dev, q)) == NULL))
@@ -145,7 +145,8 @@ static inline int qdisc_restart(struct net_device *dev)
spin_unlock(&dev->queue_lock);
HARD_TX_LOCK(dev, smp_processor_id());
- ret = dev_hard_start_xmit(skb, dev);
+ if (!netif_subqueue_stopped(dev, skb))
+ ret = dev_hard_start_xmit(skb, dev);
HARD_TX_UNLOCK(dev);
spin_lock(&dev->queue_lock);
@@ -249,10 +250,11 @@ static void dev_watchdog_down(struct net_device *dev)
*/
void netif_carrier_on(struct net_device *dev)
{
- if (test_and_clear_bit(__LINK_STATE_NOCARRIER, &dev->state))
+ if (test_and_clear_bit(__LINK_STATE_NOCARRIER, &dev->state)) {
linkwatch_fire_event(dev);
- if (netif_running(dev))
- __netdev_watchdog_up(dev);
+ if (netif_running(dev))
+ __netdev_watchdog_up(dev);
+ }
}
/**
@@ -555,6 +557,7 @@ void dev_deactivate(struct net_device *dev)
{
struct Qdisc *qdisc;
struct sk_buff *skb;
+ int running;
spin_lock_bh(&dev->queue_lock);
qdisc = dev->qdisc;
@@ -570,12 +573,31 @@ void dev_deactivate(struct net_device *dev)
dev_watchdog_down(dev);
- /* Wait for outstanding dev_queue_xmit calls. */
+ /* Wait for outstanding qdisc-less dev_queue_xmit calls. */
synchronize_rcu();
/* Wait for outstanding qdisc_run calls. */
- while (test_bit(__LINK_STATE_QDISC_RUNNING, &dev->state))
- yield();
+ do {
+ while (test_bit(__LINK_STATE_QDISC_RUNNING, &dev->state))
+ yield();
+
+ /*
+ * Double-check inside queue lock to ensure that all effects
+ * of the queue run are visible when we return.
+ */
+ spin_lock_bh(&dev->queue_lock);
+ running = test_bit(__LINK_STATE_QDISC_RUNNING, &dev->state);
+ spin_unlock_bh(&dev->queue_lock);
+
+ /*
+ * The running flag should never be set at this point because
+ * we've already set dev->qdisc to noop_qdisc *inside* the same
+ * pair of spin locks. That is, if any qdisc_run starts after
+ * our initial test it should see the noop_qdisc and then
+ * clear the RUNNING bit before dropping the queue lock. So
+ * if it is set here then we've found a bug.
+ */
+ } while (WARN_ON_ONCE(running));
}
void dev_init_scheduler(struct net_device *dev)
diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c
index 2d32fd27496e..3f8335e6ea2e 100644
--- a/net/sched/sch_ingress.c
+++ b/net/sched/sch_ingress.c
@@ -205,20 +205,19 @@ static unsigned int ingress_drop(struct Qdisc *sch)
#ifndef CONFIG_NET_CLS_ACT
#ifdef CONFIG_NETFILTER
static unsigned int
-ing_hook(unsigned int hook, struct sk_buff **pskb,
+ing_hook(unsigned int hook, struct sk_buff *skb,
const struct net_device *indev,
const struct net_device *outdev,
int (*okfn)(struct sk_buff *))
{
struct Qdisc *q;
- struct sk_buff *skb = *pskb;
struct net_device *dev = skb->dev;
int fwres=NF_ACCEPT;
DPRINTK("ing_hook: skb %s dev=%s len=%u\n",
skb->sk ? "(owned)" : "(unowned)",
- skb->dev ? (*pskb)->dev->name : "(no dev)",
+ skb->dev ? skb->dev->name : "(no dev)",
skb->len);
if (dev->qdisc_ingress) {
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c
index abd82fc3ec60..de894096e442 100644
--- a/net/sched/sch_prio.c
+++ b/net/sched/sch_prio.c
@@ -136,7 +136,7 @@ prio_dequeue(struct Qdisc* sch)
* pulling an skb. This way we avoid excessive requeues
* for slower queues.
*/
- if (!netif_subqueue_stopped(sch->dev, (q->mq ? prio : 0))) {
+ if (!__netif_subqueue_stopped(sch->dev, (q->mq ? prio : 0))) {
qdisc = q->queues[prio];
skb = qdisc->dequeue(qdisc);
if (skb) {
@@ -165,7 +165,7 @@ static struct sk_buff *rr_dequeue(struct Qdisc* sch)
* for slower queues. If the queue is stopped, try the
* next queue.
*/
- if (!netif_subqueue_stopped(sch->dev,
+ if (!__netif_subqueue_stopped(sch->dev,
(q->mq ? q->curband : 0))) {
qdisc = q->queues[q->curband];
skb = qdisc->dequeue(qdisc);
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
index be57cf317a7f..c0ed06d4a504 100644
--- a/net/sched/sch_teql.c
+++ b/net/sched/sch_teql.c
@@ -252,6 +252,9 @@ __teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device *
static inline int teql_resolve(struct sk_buff *skb,
struct sk_buff *skb_res, struct net_device *dev)
{
+ if (dev->qdisc == &noop_qdisc)
+ return -ENODEV;
+
if (dev->header_ops == NULL ||
skb->dst == NULL ||
skb->dst->neighbour == NULL)
@@ -266,7 +269,7 @@ static int teql_master_xmit(struct sk_buff *skb, struct net_device *dev)
int busy;
int nores;
int len = skb->len;
- int subq = skb->queue_mapping;
+ int subq = skb_get_queue_mapping(skb);
struct sk_buff *skb_res = NULL;
start = master->slaves;
@@ -284,7 +287,7 @@ restart:
if (slave->qdisc_sleeping != q)
continue;
if (netif_queue_stopped(slave) ||
- netif_subqueue_stopped(slave, subq) ||
+ __netif_subqueue_stopped(slave, subq) ||
!netif_running(slave)) {
busy = 1;
continue;
@@ -294,7 +297,7 @@ restart:
case 0:
if (netif_tx_trylock(slave)) {
if (!netif_queue_stopped(slave) &&
- !netif_subqueue_stopped(slave, subq) &&
+ !__netif_subqueue_stopped(slave, subq) &&
slave->hard_start_xmit(skb, slave) == 0) {
netif_tx_unlock(slave);
master->slaves = NEXT_SLAVE(q);
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 03158e3665da..013e3d3ab0f1 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -262,10 +262,14 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
*/
asoc->peer.sack_needed = 1;
- /* Assume that the peer recongizes ASCONF until reported otherwise
- * via an ERROR chunk.
+ /* Assume that the peer will tell us if he recognizes ASCONF
+ * as part of INIT exchange.
+ * The sctp_addip_noauth option is there for backward compatibilty
+ * and will revert old behavior.
*/
- asoc->peer.asconf_capable = 1;
+ asoc->peer.asconf_capable = 0;
+ if (sctp_addip_noauth)
+ asoc->peer.asconf_capable = 1;
/* Create an input queue. */
sctp_inq_init(&asoc->base.inqueue);
diff --git a/net/sctp/auth.c b/net/sctp/auth.c
index 781810724714..6d5fa6bb371b 100644
--- a/net/sctp/auth.c
+++ b/net/sctp/auth.c
@@ -107,7 +107,7 @@ struct sctp_shared_key *sctp_auth_shkey_create(__u16 key_id, gfp_t gfp)
}
/* Free the shared key stucture */
-void sctp_auth_shkey_free(struct sctp_shared_key *sh_key)
+static void sctp_auth_shkey_free(struct sctp_shared_key *sh_key)
{
BUG_ON(!list_empty(&sh_key->key_list));
sctp_auth_key_put(sh_key->key);
@@ -220,7 +220,7 @@ static struct sctp_auth_bytes *sctp_auth_make_key_vector(
/* Make a key vector based on our local parameters */
-struct sctp_auth_bytes *sctp_auth_make_local_vector(
+static struct sctp_auth_bytes *sctp_auth_make_local_vector(
const struct sctp_association *asoc,
gfp_t gfp)
{
@@ -232,7 +232,7 @@ struct sctp_auth_bytes *sctp_auth_make_local_vector(
}
/* Make a key vector based on peer's parameters */
-struct sctp_auth_bytes *sctp_auth_make_peer_vector(
+static struct sctp_auth_bytes *sctp_auth_make_peer_vector(
const struct sctp_association *asoc,
gfp_t gfp)
{
@@ -556,7 +556,7 @@ struct sctp_hmac *sctp_auth_asoc_get_hmac(const struct sctp_association *asoc)
return &sctp_hmac_list[id];
}
-static int __sctp_auth_find_hmacid(__u16 *hmacs, int n_elts, __u16 hmac_id)
+static int __sctp_auth_find_hmacid(__be16 *hmacs, int n_elts, __be16 hmac_id)
{
int found = 0;
int i;
@@ -573,7 +573,7 @@ static int __sctp_auth_find_hmacid(__u16 *hmacs, int n_elts, __u16 hmac_id)
/* See if the HMAC_ID is one that we claim as supported */
int sctp_auth_asoc_verify_hmac_id(const struct sctp_association *asoc,
- __u16 hmac_id)
+ __be16 hmac_id)
{
struct sctp_hmac_algo_param *hmacs;
__u16 n_elt;
@@ -726,9 +726,7 @@ void sctp_auth_calculate_hmac(const struct sctp_association *asoc,
/* set up scatter list */
end = skb_tail_pointer(skb);
- sg.page = virt_to_page(auth);
- sg.offset = (unsigned long)(auth) % PAGE_SIZE;
- sg.length = end - (unsigned char *)auth;
+ sg_init_one(&sg, auth, end - (unsigned char *)auth);
desc.tfm = asoc->ep->auth_hmacs[hmac_id];
desc.flags = 0;
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
index dfffa94fb9f6..cae95af9a8cc 100644
--- a/net/sctp/bind_addr.c
+++ b/net/sctp/bind_addr.c
@@ -180,9 +180,7 @@ int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new,
/* Delete an address from the bind address list in the SCTP_bind_addr
* structure.
*/
-int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr,
- void fastcall (*rcu_call)(struct rcu_head *head,
- void (*func)(struct rcu_head *head)))
+int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr)
{
struct sctp_sockaddr_entry *addr, *temp;
@@ -198,15 +196,10 @@ int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr,
}
}
- /* Call the rcu callback provided in the args. This function is
- * called by both BH packet processing and user side socket option
- * processing, but it works on different lists in those 2 contexts.
- * Each context provides it's own callback, whether call_rcu_bh()
- * or call_rcu(), to make sure that we wait for an appropriate time.
- */
if (addr && !addr->valid) {
- rcu_call(&addr->rcu, sctp_local_addr_free);
+ call_rcu(&addr->rcu, sctp_local_addr_free);
SCTP_DBG_OBJCNT_DEC(addr);
+ return 0;
}
return -EINVAL;
diff --git a/net/sctp/crc32c.c b/net/sctp/crc32c.c
index 59cf7b06d216..181edabdb8ca 100644
--- a/net/sctp/crc32c.c
+++ b/net/sctp/crc32c.c
@@ -170,6 +170,7 @@ __u32 sctp_update_cksum(__u8 *buffer, __u16 length, __u32 crc32)
return crc32;
}
+#if 0
__u32 sctp_update_copy_cksum(__u8 *to, __u8 *from, __u16 length, __u32 crc32)
{
__u32 i;
@@ -186,6 +187,7 @@ __u32 sctp_update_copy_cksum(__u8 *to, __u8 *from, __u16 length, __u32 crc32)
return crc32;
}
+#endif /* 0 */
__u32 sctp_end_cksum(__u32 crc32)
{
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 2d2d81ef4a69..de6f505d6ff8 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -328,24 +328,35 @@ static struct sctp_association *__sctp_endpoint_lookup_assoc(
const union sctp_addr *paddr,
struct sctp_transport **transport)
{
+ struct sctp_association *asoc = NULL;
+ struct sctp_transport *t = NULL;
+ struct sctp_hashbucket *head;
+ struct sctp_ep_common *epb;
+ struct hlist_node *node;
+ int hash;
int rport;
- struct sctp_association *asoc;
- struct list_head *pos;
+ *transport = NULL;
rport = ntohs(paddr->v4.sin_port);
- list_for_each(pos, &ep->asocs) {
- asoc = list_entry(pos, struct sctp_association, asocs);
- if (rport == asoc->peer.port) {
- *transport = sctp_assoc_lookup_paddr(asoc, paddr);
-
- if (*transport)
- return asoc;
+ hash = sctp_assoc_hashfn(ep->base.bind_addr.port, rport);
+ head = &sctp_assoc_hashtable[hash];
+ read_lock(&head->lock);
+ sctp_for_each_hentry(epb, node, &head->chain) {
+ asoc = sctp_assoc(epb);
+ if (asoc->ep != ep || rport != asoc->peer.port)
+ goto next;
+
+ t = sctp_assoc_lookup_paddr(asoc, paddr);
+ if (t) {
+ *transport = t;
+ break;
}
+next:
+ asoc = NULL;
}
-
- *transport = NULL;
- return NULL;
+ read_unlock(&head->lock);
+ return asoc;
}
/* Lookup association on an endpoint based on a peer address. BH-safe. */
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 86503e7fa21e..91ae463b079b 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -656,7 +656,6 @@ discard:
/* Insert endpoint into the hash table. */
static void __sctp_hash_endpoint(struct sctp_endpoint *ep)
{
- struct sctp_ep_common **epp;
struct sctp_ep_common *epb;
struct sctp_hashbucket *head;
@@ -666,12 +665,7 @@ static void __sctp_hash_endpoint(struct sctp_endpoint *ep)
head = &sctp_ep_hashtable[epb->hashent];
sctp_write_lock(&head->lock);
- epp = &head->chain;
- epb->next = *epp;
- if (epb->next)
- (*epp)->pprev = &epb->next;
- *epp = epb;
- epb->pprev = epp;
+ hlist_add_head(&epb->node, &head->chain);
sctp_write_unlock(&head->lock);
}
@@ -691,19 +685,15 @@ static void __sctp_unhash_endpoint(struct sctp_endpoint *ep)
epb = &ep->base;
+ if (hlist_unhashed(&epb->node))
+ return;
+
epb->hashent = sctp_ep_hashfn(epb->bind_addr.port);
head = &sctp_ep_hashtable[epb->hashent];
sctp_write_lock(&head->lock);
-
- if (epb->pprev) {
- if (epb->next)
- epb->next->pprev = epb->pprev;
- *epb->pprev = epb->next;
- epb->pprev = NULL;
- }
-
+ __hlist_del(&epb->node);
sctp_write_unlock(&head->lock);
}
@@ -721,12 +711,13 @@ static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *l
struct sctp_hashbucket *head;
struct sctp_ep_common *epb;
struct sctp_endpoint *ep;
+ struct hlist_node *node;
int hash;
hash = sctp_ep_hashfn(ntohs(laddr->v4.sin_port));
head = &sctp_ep_hashtable[hash];
read_lock(&head->lock);
- for (epb = head->chain; epb; epb = epb->next) {
+ sctp_for_each_hentry(epb, node, &head->chain) {
ep = sctp_ep(epb);
if (sctp_endpoint_is_match(ep, laddr))
goto hit;
@@ -744,7 +735,6 @@ hit:
/* Insert association into the hash table. */
static void __sctp_hash_established(struct sctp_association *asoc)
{
- struct sctp_ep_common **epp;
struct sctp_ep_common *epb;
struct sctp_hashbucket *head;
@@ -756,12 +746,7 @@ static void __sctp_hash_established(struct sctp_association *asoc)
head = &sctp_assoc_hashtable[epb->hashent];
sctp_write_lock(&head->lock);
- epp = &head->chain;
- epb->next = *epp;
- if (epb->next)
- (*epp)->pprev = &epb->next;
- *epp = epb;
- epb->pprev = epp;
+ hlist_add_head(&epb->node, &head->chain);
sctp_write_unlock(&head->lock);
}
@@ -790,14 +775,7 @@ static void __sctp_unhash_established(struct sctp_association *asoc)
head = &sctp_assoc_hashtable[epb->hashent];
sctp_write_lock(&head->lock);
-
- if (epb->pprev) {
- if (epb->next)
- epb->next->pprev = epb->pprev;
- *epb->pprev = epb->next;
- epb->pprev = NULL;
- }
-
+ __hlist_del(&epb->node);
sctp_write_unlock(&head->lock);
}
@@ -822,6 +800,7 @@ static struct sctp_association *__sctp_lookup_association(
struct sctp_ep_common *epb;
struct sctp_association *asoc;
struct sctp_transport *transport;
+ struct hlist_node *node;
int hash;
/* Optimize here for direct hit, only listening connections can
@@ -830,7 +809,7 @@ static struct sctp_association *__sctp_lookup_association(
hash = sctp_assoc_hashfn(ntohs(local->v4.sin_port), ntohs(peer->v4.sin_port));
head = &sctp_assoc_hashtable[hash];
read_lock(&head->lock);
- for (epb = head->chain; epb; epb = epb->next) {
+ sctp_for_each_hentry(epb, node, &head->chain) {
asoc = sctp_assoc(epb);
transport = sctp_assoc_is_match(asoc, local, peer);
if (transport)
diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c
index f10fe7fbf24c..cf4b7eb023b3 100644
--- a/net/sctp/inqueue.c
+++ b/net/sctp/inqueue.c
@@ -90,6 +90,10 @@ void sctp_inq_free(struct sctp_inq *queue)
void sctp_inq_push(struct sctp_inq *q, struct sctp_chunk *chunk)
{
/* Directly call the packet handling routine. */
+ if (chunk->rcvr->dead) {
+ sctp_chunk_free(chunk);
+ return;
+ }
/* We are now calling this either from the soft interrupt
* or from the backlog processing.
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 9de3ddaa2768..7f31ff638bc6 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -631,7 +631,7 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
struct sctp6_sock *newsctp6sk;
- newsk = sk_alloc(sk->sk_net, PF_INET6, GFP_KERNEL, sk->sk_prot, 1);
+ newsk = sk_alloc(sk->sk_net, PF_INET6, GFP_KERNEL, sk->sk_prot);
if (!newsk)
goto out;
@@ -954,9 +954,9 @@ static struct inet_protosw sctpv6_stream_protosw = {
.flags = SCTP_PROTOSW_FLAG,
};
-static int sctp6_rcv(struct sk_buff **pskb)
+static int sctp6_rcv(struct sk_buff *skb)
{
- return sctp_rcv(*pskb) ? -1 : 0;
+ return sctp_rcv(skb) ? -1 : 0;
}
static struct inet6_protocol sctpv6_protocol = {
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 28f4fe77ceee..fa76f235169b 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -382,7 +382,7 @@ static void sctp_insert_list(struct list_head *head, struct list_head *new)
/* Mark all the eligible packets on a transport for retransmission. */
void sctp_retransmit_mark(struct sctp_outq *q,
struct sctp_transport *transport,
- __u8 fast_retransmit)
+ __u8 reason)
{
struct list_head *lchunk, *ltemp;
struct sctp_chunk *chunk;
@@ -412,20 +412,20 @@ void sctp_retransmit_mark(struct sctp_outq *q,
continue;
}
- /* If we are doing retransmission due to a fast retransmit,
- * only the chunk's that are marked for fast retransmit
- * should be added to the retransmit queue. If we are doing
- * retransmission due to a timeout or pmtu discovery, only the
- * chunks that are not yet acked should be added to the
- * retransmit queue.
+ /* If we are doing retransmission due to a timeout or pmtu
+ * discovery, only the chunks that are not yet acked should
+ * be added to the retransmit queue.
*/
- if ((fast_retransmit && (chunk->fast_retransmit > 0)) ||
- (!fast_retransmit && !chunk->tsn_gap_acked)) {
+ if ((reason == SCTP_RTXR_FAST_RTX &&
+ (chunk->fast_retransmit > 0)) ||
+ (reason != SCTP_RTXR_FAST_RTX && !chunk->tsn_gap_acked)) {
/* If this chunk was sent less then 1 rto ago, do not
* retransmit this chunk, but give the peer time
- * to acknowlege it.
+ * to acknowlege it. Do this only when
+ * retransmitting due to T3 timeout.
*/
- if ((jiffies - chunk->sent_at) < transport->rto)
+ if (reason == SCTP_RTXR_T3_RTX &&
+ (jiffies - chunk->sent_at) < transport->last_rto)
continue;
/* RFC 2960 6.2.1 Processing a Received SACK
@@ -467,10 +467,10 @@ void sctp_retransmit_mark(struct sctp_outq *q,
}
}
- SCTP_DEBUG_PRINTK("%s: transport: %p, fast_retransmit: %d, "
+ SCTP_DEBUG_PRINTK("%s: transport: %p, reason: %d, "
"cwnd: %d, ssthresh: %d, flight_size: %d, "
"pba: %d\n", __FUNCTION__,
- transport, fast_retransmit,
+ transport, reason,
transport->cwnd, transport->ssthresh,
transport->flight_size,
transport->partial_bytes_acked);
@@ -484,7 +484,6 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport,
sctp_retransmit_reason_t reason)
{
int error = 0;
- __u8 fast_retransmit = 0;
switch(reason) {
case SCTP_RTXR_T3_RTX:
@@ -499,16 +498,18 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport,
case SCTP_RTXR_FAST_RTX:
SCTP_INC_STATS(SCTP_MIB_FAST_RETRANSMITS);
sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_FAST_RTX);
- fast_retransmit = 1;
break;
case SCTP_RTXR_PMTUD:
SCTP_INC_STATS(SCTP_MIB_PMTUD_RETRANSMITS);
break;
+ case SCTP_RTXR_T1_RTX:
+ SCTP_INC_STATS(SCTP_MIB_T1_RETRANSMITS);
+ break;
default:
BUG();
}
- sctp_retransmit_mark(q, transport, fast_retransmit);
+ sctp_retransmit_mark(q, transport, reason);
/* PR-SCTP A5) Any time the T3-rtx timer expires, on any destination,
* the sender SHOULD try to advance the "Advanced.Peer.Ack.Point" by
@@ -641,7 +642,8 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt,
/* If we are here due to a retransmit timeout or a fast
* retransmit and if there are any chunks left in the retransmit
- * queue that could not fit in the PMTU sized packet, they need * to be marked as ineligible for a subsequent fast retransmit.
+ * queue that could not fit in the PMTU sized packet, they need
+ * to be marked as ineligible for a subsequent fast retransmit.
*/
if (rtx_timeout && !lchunk) {
list_for_each(lchunk1, lqueue) {
@@ -660,10 +662,9 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt,
int sctp_outq_uncork(struct sctp_outq *q)
{
int error = 0;
- if (q->cork) {
+ if (q->cork)
q->cork = 0;
- error = sctp_outq_flush(q, 0);
- }
+ error = sctp_outq_flush(q, 0);
return error;
}
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index e4cd841a22e4..249973204070 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -225,6 +225,7 @@ static int sctp_eps_seq_show(struct seq_file *seq, void *v)
struct sctp_ep_common *epb;
struct sctp_endpoint *ep;
struct sock *sk;
+ struct hlist_node *node;
int hash = *(loff_t *)v;
if (hash >= sctp_ep_hashsize)
@@ -233,7 +234,7 @@ static int sctp_eps_seq_show(struct seq_file *seq, void *v)
head = &sctp_ep_hashtable[hash];
sctp_local_bh_disable();
read_lock(&head->lock);
- for (epb = head->chain; epb; epb = epb->next) {
+ sctp_for_each_hentry(epb, node, &head->chain) {
ep = sctp_ep(epb);
sk = epb->sk;
seq_printf(seq, "%8p %8p %-3d %-3d %-4d %-5d %5d %5lu ", ep, sk,
@@ -328,6 +329,7 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
struct sctp_ep_common *epb;
struct sctp_association *assoc;
struct sock *sk;
+ struct hlist_node *node;
int hash = *(loff_t *)v;
if (hash >= sctp_assoc_hashsize)
@@ -336,7 +338,7 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
head = &sctp_assoc_hashtable[hash];
sctp_local_bh_disable();
read_lock(&head->lock);
- for (epb = head->chain; epb; epb = epb->next) {
+ sctp_for_each_hentry(epb, node, &head->chain) {
assoc = sctp_assoc(epb);
sk = epb->sk;
seq_printf(seq,
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 81b26c5ffd4b..d50f610d1b02 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -552,7 +552,8 @@ static struct sock *sctp_v4_create_accept_sk(struct sock *sk,
{
struct inet_sock *inet = inet_sk(sk);
struct inet_sock *newinet;
- struct sock *newsk = sk_alloc(sk->sk_net, PF_INET, GFP_KERNEL, sk->sk_prot, 1);
+ struct sock *newsk = sk_alloc(sk->sk_net, PF_INET, GFP_KERNEL,
+ sk->sk_prot);
if (!newsk)
goto out;
@@ -1136,7 +1137,7 @@ SCTP_STATIC __init int sctp_init(void)
}
for (i = 0; i < sctp_assoc_hashsize; i++) {
rwlock_init(&sctp_assoc_hashtable[i].lock);
- sctp_assoc_hashtable[i].chain = NULL;
+ INIT_HLIST_HEAD(&sctp_assoc_hashtable[i].chain);
}
/* Allocate and initialize the endpoint hash table. */
@@ -1150,7 +1151,7 @@ SCTP_STATIC __init int sctp_init(void)
}
for (i = 0; i < sctp_ep_hashsize; i++) {
rwlock_init(&sctp_ep_hashtable[i].lock);
- sctp_ep_hashtable[i].chain = NULL;
+ INIT_HLIST_HEAD(&sctp_ep_hashtable[i].chain);
}
/* Allocate and initialize the SCTP port hash table. */
@@ -1169,7 +1170,7 @@ SCTP_STATIC __init int sctp_init(void)
}
for (i = 0; i < sctp_port_hashsize; i++) {
spin_lock_init(&sctp_port_hashtable[i].lock);
- sctp_port_hashtable[i].chain = NULL;
+ INIT_HLIST_HEAD(&sctp_port_hashtable[i].chain);
}
printk(KERN_INFO "SCTP: Hash tables configured "
@@ -1178,6 +1179,7 @@ SCTP_STATIC __init int sctp_init(void)
/* Disable ADDIP by default. */
sctp_addip_enable = 0;
+ sctp_addip_noauth = 0;
/* Enable PR-SCTP by default. */
sctp_prsctp_enable = 1;
@@ -1228,7 +1230,6 @@ SCTP_STATIC __init int sctp_init(void)
if (status)
goto err_v6_add_protocol;
- __unsafe(THIS_MODULE);
status = 0;
out:
return status;
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index f983a369d4e2..5a9783c38de1 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -56,7 +56,7 @@
#include <linux/ipv6.h>
#include <linux/net.h>
#include <linux/inet.h>
-#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
#include <linux/crypto.h>
#include <net/sock.h>
@@ -1513,9 +1513,7 @@ static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep,
struct hash_desc desc;
/* Sign the message. */
- sg.page = virt_to_page(&cookie->c);
- sg.offset = (unsigned long)(&cookie->c) % PAGE_SIZE;
- sg.length = bodysize;
+ sg_init_one(&sg, &cookie->c, bodysize);
keylen = SCTP_SECRET_SIZE;
key = (char *)ep->secret_key[ep->current_key];
desc.tfm = sctp_sk(ep->base.sk)->hmac;
@@ -1585,9 +1583,7 @@ struct sctp_association *sctp_unpack_cookie(
/* Check the signature. */
keylen = SCTP_SECRET_SIZE;
- sg.page = virt_to_page(bear_cookie);
- sg.offset = (unsigned long)(bear_cookie) % PAGE_SIZE;
- sg.length = bodysize;
+ sg_init_one(&sg, bear_cookie, bodysize);
key = (char *)ep->secret_key[ep->current_key];
desc.tfm = sctp_sk(ep->base.sk)->hmac;
desc.flags = 0;
@@ -1792,9 +1788,14 @@ static int sctp_process_inv_paramlength(const struct sctp_association *asoc,
sizeof(sctp_paramhdr_t);
+ /* This is a fatal error. Any accumulated non-fatal errors are
+ * not reported.
+ */
+ if (*errp)
+ sctp_chunk_free(*errp);
+
/* Create an error chunk and fill it in with our payload. */
- if (!*errp)
- *errp = sctp_make_op_error_space(asoc, chunk, payload_len);
+ *errp = sctp_make_op_error_space(asoc, chunk, payload_len);
if (*errp) {
sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION,
@@ -1817,9 +1818,15 @@ static int sctp_process_hn_param(const struct sctp_association *asoc,
{
__u16 len = ntohs(param.p->length);
- /* Make an ERROR chunk. */
- if (!*errp)
- *errp = sctp_make_op_error_space(asoc, chunk, len);
+ /* Processing of the HOST_NAME parameter will generate an
+ * ABORT. If we've accumulated any non-fatal errors, they
+ * would be unrecognized parameters and we should not include
+ * them in the ABORT.
+ */
+ if (*errp)
+ sctp_chunk_free(*errp);
+
+ *errp = sctp_make_op_error_space(asoc, chunk, len);
if (*errp) {
sctp_init_cause(*errp, SCTP_ERROR_DNS_FAILED, len);
@@ -1851,7 +1858,7 @@ static void sctp_process_ext_param(struct sctp_association *asoc,
break;
case SCTP_CID_ASCONF:
case SCTP_CID_ASCONF_ACK:
- asoc->peer.addip_capable = 1;
+ asoc->peer.asconf_capable = 1;
break;
default:
break;
@@ -1866,56 +1873,40 @@ static void sctp_process_ext_param(struct sctp_association *asoc,
* taken if the processing endpoint does not recognize the
* Parameter Type.
*
- * 00 - Stop processing this SCTP chunk and discard it,
- * do not process any further chunks within it.
+ * 00 - Stop processing this parameter; do not process any further
+ * parameters within this chunk
*
- * 01 - Stop processing this SCTP chunk and discard it,
- * do not process any further chunks within it, and report
- * the unrecognized parameter in an 'Unrecognized
- * Parameter Type' (in either an ERROR or in the INIT ACK).
+ * 01 - Stop processing this parameter, do not process any further
+ * parameters within this chunk, and report the unrecognized
+ * parameter in an 'Unrecognized Parameter' ERROR chunk.
*
* 10 - Skip this parameter and continue processing.
*
* 11 - Skip this parameter and continue processing but
* report the unrecognized parameter in an
- * 'Unrecognized Parameter Type' (in either an ERROR or in
- * the INIT ACK).
+ * 'Unrecognized Parameter' ERROR chunk.
*
* Return value:
- * 0 - discard the chunk
- * 1 - continue with the chunk
+ * SCTP_IERROR_NO_ERROR - continue with the chunk
+ * SCTP_IERROR_ERROR - stop and report an error.
+ * SCTP_IERROR_NOMEME - out of memory.
*/
-static int sctp_process_unk_param(const struct sctp_association *asoc,
- union sctp_params param,
- struct sctp_chunk *chunk,
- struct sctp_chunk **errp)
+static sctp_ierror_t sctp_process_unk_param(const struct sctp_association *asoc,
+ union sctp_params param,
+ struct sctp_chunk *chunk,
+ struct sctp_chunk **errp)
{
- int retval = 1;
+ int retval = SCTP_IERROR_NO_ERROR;
switch (param.p->type & SCTP_PARAM_ACTION_MASK) {
case SCTP_PARAM_ACTION_DISCARD:
- retval = 0;
- break;
- case SCTP_PARAM_ACTION_DISCARD_ERR:
- retval = 0;
- /* Make an ERROR chunk, preparing enough room for
- * returning multiple unknown parameters.
- */
- if (NULL == *errp)
- *errp = sctp_make_op_error_space(asoc, chunk,
- ntohs(chunk->chunk_hdr->length));
-
- if (*errp) {
- sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM,
- WORD_ROUND(ntohs(param.p->length)));
- sctp_addto_chunk(*errp,
- WORD_ROUND(ntohs(param.p->length)),
- param.v);
- }
-
+ retval = SCTP_IERROR_ERROR;
break;
case SCTP_PARAM_ACTION_SKIP:
break;
+ case SCTP_PARAM_ACTION_DISCARD_ERR:
+ retval = SCTP_IERROR_ERROR;
+ /* Fall through */
case SCTP_PARAM_ACTION_SKIP_ERR:
/* Make an ERROR chunk, preparing enough room for
* returning multiple unknown parameters.
@@ -1936,9 +1927,8 @@ static int sctp_process_unk_param(const struct sctp_association *asoc,
* to the peer and the association won't be
* established.
*/
- retval = 0;
+ retval = SCTP_IERROR_NOMEM;
}
-
break;
default:
break;
@@ -1947,18 +1937,20 @@ static int sctp_process_unk_param(const struct sctp_association *asoc,
return retval;
}
-/* Find unrecognized parameters in the chunk.
+/* Verify variable length parameters
* Return values:
- * 0 - discard the chunk
- * 1 - continue with the chunk
+ * SCTP_IERROR_ABORT - trigger an ABORT
+ * SCTP_IERROR_NOMEM - out of memory (abort)
+ * SCTP_IERROR_ERROR - stop processing, trigger an ERROR
+ * SCTP_IERROR_NO_ERROR - continue with the chunk
*/
-static int sctp_verify_param(const struct sctp_association *asoc,
- union sctp_params param,
- sctp_cid_t cid,
- struct sctp_chunk *chunk,
- struct sctp_chunk **err_chunk)
+static sctp_ierror_t sctp_verify_param(const struct sctp_association *asoc,
+ union sctp_params param,
+ sctp_cid_t cid,
+ struct sctp_chunk *chunk,
+ struct sctp_chunk **err_chunk)
{
- int retval = 1;
+ int retval = SCTP_IERROR_NO_ERROR;
/* FIXME - This routine is not looking at each parameter per the
* chunk type, i.e., unrecognized parameters should be further
@@ -1980,7 +1972,9 @@ static int sctp_verify_param(const struct sctp_association *asoc,
case SCTP_PARAM_HOST_NAME_ADDRESS:
/* Tell the peer, we won't support this param. */
- return sctp_process_hn_param(asoc, param, chunk, err_chunk);
+ sctp_process_hn_param(asoc, param, chunk, err_chunk);
+ retval = SCTP_IERROR_ABORT;
+ break;
case SCTP_PARAM_FWD_TSN_SUPPORT:
if (sctp_prsctp_enable)
@@ -1997,9 +1991,11 @@ static int sctp_verify_param(const struct sctp_association *asoc,
* cause 'Protocol Violation'.
*/
if (SCTP_AUTH_RANDOM_LENGTH !=
- ntohs(param.p->length) - sizeof(sctp_paramhdr_t))
- return sctp_process_inv_paramlength(asoc, param.p,
+ ntohs(param.p->length) - sizeof(sctp_paramhdr_t)) {
+ sctp_process_inv_paramlength(asoc, param.p,
chunk, err_chunk);
+ retval = SCTP_IERROR_ABORT;
+ }
break;
case SCTP_PARAM_CHUNKS:
@@ -2011,9 +2007,11 @@ static int sctp_verify_param(const struct sctp_association *asoc,
* INIT-ACK chunk if the sender wants to receive authenticated
* chunks. Its maximum length is 260 bytes.
*/
- if (260 < ntohs(param.p->length))
- return sctp_process_inv_paramlength(asoc, param.p,
- chunk, err_chunk);
+ if (260 < ntohs(param.p->length)) {
+ sctp_process_inv_paramlength(asoc, param.p,
+ chunk, err_chunk);
+ retval = SCTP_IERROR_ABORT;
+ }
break;
case SCTP_PARAM_HMAC_ALGO:
@@ -2024,8 +2022,7 @@ fallthrough:
default:
SCTP_DEBUG_PRINTK("Unrecognized param: %d for chunk %d.\n",
ntohs(param.p->type), cid);
- return sctp_process_unk_param(asoc, param, chunk, err_chunk);
-
+ retval = sctp_process_unk_param(asoc, param, chunk, err_chunk);
break;
}
return retval;
@@ -2040,6 +2037,7 @@ int sctp_verify_init(const struct sctp_association *asoc,
{
union sctp_params param;
int has_cookie = 0;
+ int result;
/* Verify stream values are non-zero. */
if ((0 == peer_init->init_hdr.num_outbound_streams) ||
@@ -2047,8 +2045,7 @@ int sctp_verify_init(const struct sctp_association *asoc,
(0 == peer_init->init_hdr.init_tag) ||
(SCTP_DEFAULT_MINWINDOW > ntohl(peer_init->init_hdr.a_rwnd))) {
- sctp_process_inv_mandatory(asoc, chunk, errp);
- return 0;
+ return sctp_process_inv_mandatory(asoc, chunk, errp);
}
/* Check for missing mandatory parameters. */
@@ -2066,29 +2063,29 @@ int sctp_verify_init(const struct sctp_association *asoc,
* VIOLATION error. We build the ERROR chunk here and let the normal
* error handling code build and send the packet.
*/
- if (param.v != (void*)chunk->chunk_end) {
- sctp_process_inv_paramlength(asoc, param.p, chunk, errp);
- return 0;
- }
+ if (param.v != (void*)chunk->chunk_end)
+ return sctp_process_inv_paramlength(asoc, param.p, chunk, errp);
/* The only missing mandatory param possible today is
* the state cookie for an INIT-ACK chunk.
*/
- if ((SCTP_CID_INIT_ACK == cid) && !has_cookie) {
- sctp_process_missing_param(asoc, SCTP_PARAM_STATE_COOKIE,
- chunk, errp);
- return 0;
- }
-
- /* Find unrecognized parameters. */
+ if ((SCTP_CID_INIT_ACK == cid) && !has_cookie)
+ return sctp_process_missing_param(asoc, SCTP_PARAM_STATE_COOKIE,
+ chunk, errp);
+ /* Verify all the variable length parameters */
sctp_walk_params(param, peer_init, init_hdr.params) {
- if (!sctp_verify_param(asoc, param, cid, chunk, errp)) {
- if (SCTP_PARAM_HOST_NAME_ADDRESS == param.p->type)
+ result = sctp_verify_param(asoc, param, cid, chunk, errp);
+ switch (result) {
+ case SCTP_IERROR_ABORT:
+ case SCTP_IERROR_NOMEM:
return 0;
- else
+ case SCTP_IERROR_ERROR:
return 1;
+ case SCTP_IERROR_NO_ERROR:
+ default:
+ break;
}
} /* for (loop through all parameters) */
@@ -2141,11 +2138,14 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid,
/* If the peer claims support for ADD-IP without support
* for AUTH, disable support for ADD-IP.
+ * Do this only if backward compatible mode is turned off.
*/
- if (asoc->peer.addip_capable && !asoc->peer.auth_capable) {
+ if (!sctp_addip_noauth &&
+ (asoc->peer.asconf_capable && !asoc->peer.auth_capable)) {
asoc->peer.addip_disabled_mask |= (SCTP_PARAM_ADD_IP |
SCTP_PARAM_DEL_IP |
SCTP_PARAM_SET_PRIMARY);
+ asoc->peer.asconf_capable = 0;
}
/* Walk list of transports, removing transports in the UNKNOWN state. */
@@ -2852,10 +2852,11 @@ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
__be16 err_code;
int length = 0;
- int chunk_len = asconf->skb->len;
+ int chunk_len;
__u32 serial;
int all_param_pass = 1;
+ chunk_len = ntohs(asconf->chunk_hdr->length) - sizeof(sctp_chunkhdr_t);
hdr = (sctp_addiphdr_t *)asconf->skb->data;
serial = ntohl(hdr->serial);
@@ -2956,13 +2957,17 @@ static int sctp_asconf_param_success(struct sctp_association *asoc,
/* This is always done in BH context with a socket lock
* held, so the list can not change.
*/
+ local_bh_disable();
list_for_each_entry(saddr, &bp->address_list, list) {
if (sctp_cmp_addr_exact(&saddr->a, &addr))
saddr->use_as_src = 1;
}
+ local_bh_enable();
break;
case SCTP_PARAM_DEL_IP:
- retval = sctp_del_bind_addr(bp, &addr, call_rcu_bh);
+ local_bh_disable();
+ retval = sctp_del_bind_addr(bp, &addr);
+ local_bh_enable();
list_for_each(pos, &asoc->peer.transport_addr_list) {
transport = list_entry(pos, struct sctp_transport,
transports);
@@ -2994,7 +2999,7 @@ static __be16 sctp_get_asconf_response(struct sctp_chunk *asconf_ack,
sctp_addip_param_t *asconf_ack_param;
sctp_errhdr_t *err_param;
int length;
- int asconf_ack_len = asconf_ack->skb->len;
+ int asconf_ack_len;
__be16 err_code;
if (no_err)
@@ -3002,6 +3007,9 @@ static __be16 sctp_get_asconf_response(struct sctp_chunk *asconf_ack,
else
err_code = SCTP_ERROR_REQ_REFUSED;
+ asconf_ack_len = ntohs(asconf_ack->chunk_hdr->length) -
+ sizeof(sctp_chunkhdr_t);
+
/* Skip the addiphdr from the asconf_ack chunk and store a pointer to
* the first asconf_ack parameter.
*/
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index bbdc938da86f..78d1a8a49bd0 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -453,6 +453,7 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc,
* maximum value discussed in rule C7 above (RTO.max) may be
* used to provide an upper bound to this doubling operation.
*/
+ transport->last_rto = transport->rto;
transport->rto = min((transport->rto * 2), transport->asoc->rto_max);
}
@@ -1267,6 +1268,12 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
sctp_ootb_pkt_free(packet);
break;
+ case SCTP_CMD_T1_RETRAN:
+ /* Mark a transport for retransmission. */
+ sctp_retransmit(&asoc->outqueue, cmd->obj.transport,
+ SCTP_RTXR_T1_RTX);
+ break;
+
case SCTP_CMD_RETRAN:
/* Mark a transport for retransmission. */
sctp_retransmit(&asoc->outqueue, cmd->obj.transport,
@@ -1393,7 +1400,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
list_for_each(pos, &asoc->peer.transport_addr_list) {
t = list_entry(pos, struct sctp_transport,
transports);
- sctp_retransmit_mark(&asoc->outqueue, t, 0);
+ sctp_retransmit_mark(&asoc->outqueue, t,
+ SCTP_RTXR_T1_RTX);
}
sctp_add_cmd_sf(commands,
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index f01b408508ff..5ebbe808d801 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -2305,7 +2305,7 @@ static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep,
/* If we've sent any data bundled with COOKIE-ECHO we will need to
* resend
*/
- sctp_add_cmd_sf(commands, SCTP_CMD_RETRAN,
+ sctp_add_cmd_sf(commands, SCTP_CMD_T1_RETRAN,
SCTP_TRANSPORT(asoc->peer.primary_path));
/* Cast away the const modifier, as we want to just
@@ -4064,11 +4064,6 @@ static sctp_disposition_t sctp_sf_abort_violation(
struct sctp_chunk *chunk = arg;
struct sctp_chunk *abort = NULL;
- /* Make the abort chunk. */
- abort = sctp_make_abort_violation(asoc, chunk, payload, paylen);
- if (!abort)
- goto nomem;
-
/* SCTP-AUTH, Section 6.3:
* It should be noted that if the receiver wants to tear
* down an association in an authenticated way only, the
@@ -4083,6 +4078,11 @@ static sctp_disposition_t sctp_sf_abort_violation(
if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc))
goto discard;
+ /* Make the abort chunk. */
+ abort = sctp_make_abort_violation(asoc, chunk, payload, paylen);
+ if (!abort)
+ goto nomem;
+
if (asoc) {
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index bd6f42a15a4b..ff8bc95670ed 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -660,7 +660,7 @@ static int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt)
* socket routing and failover schemes. Refer to comments in
* sctp_do_bind(). -daisy
*/
- retval = sctp_del_bind_addr(bp, sa_addr, call_rcu);
+ retval = sctp_del_bind_addr(bp, sa_addr);
addr_buf += af->sockaddr_len;
err_bindx_rem:
@@ -5307,6 +5307,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
{
struct sctp_bind_hashbucket *head; /* hash list */
struct sctp_bind_bucket *pp; /* hash list port iterator */
+ struct hlist_node *node;
unsigned short snum;
int ret;
@@ -5331,7 +5332,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
index = sctp_phashfn(rover);
head = &sctp_port_hashtable[index];
sctp_spin_lock(&head->lock);
- for (pp = head->chain; pp; pp = pp->next)
+ sctp_for_each_hentry(pp, node, &head->chain)
if (pp->port == rover)
goto next;
break;
@@ -5358,7 +5359,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
*/
head = &sctp_port_hashtable[sctp_phashfn(snum)];
sctp_spin_lock(&head->lock);
- for (pp = head->chain; pp; pp = pp->next) {
+ sctp_for_each_hentry(pp, node, &head->chain) {
if (pp->port == snum)
goto pp_found;
}
@@ -5702,10 +5703,7 @@ static struct sctp_bind_bucket *sctp_bucket_create(
pp->port = snum;
pp->fastreuse = 0;
INIT_HLIST_HEAD(&pp->owner);
- if ((pp->next = head->chain) != NULL)
- pp->next->pprev = &pp->next;
- head->chain = pp;
- pp->pprev = &head->chain;
+ hlist_add_head(&pp->node, &head->chain);
}
return pp;
}
@@ -5714,9 +5712,7 @@ static struct sctp_bind_bucket *sctp_bucket_create(
static void sctp_bucket_destroy(struct sctp_bind_bucket *pp)
{
if (pp && hlist_empty(&pp->owner)) {
- if (pp->next)
- pp->next->pprev = pp->pprev;
- *(pp->pprev) = pp->next;
+ __hlist_del(&pp->node);
kmem_cache_free(sctp_bucket_cachep, pp);
SCTP_DBG_OBJCNT_DEC(bind_bucket);
}
@@ -6455,6 +6451,8 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
}
+DEFINE_PROTO_INUSE(sctp)
+
/* This proto struct describes the ULP interface for SCTP. */
struct proto sctp_prot = {
.name = "SCTP",
@@ -6483,9 +6481,12 @@ struct proto sctp_prot = {
.memory_pressure = &sctp_memory_pressure,
.enter_memory_pressure = sctp_enter_memory_pressure,
.memory_allocated = &sctp_memory_allocated,
+ REF_PROTO_INUSE(sctp)
};
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+DEFINE_PROTO_INUSE(sctpv6)
+
struct proto sctpv6_prot = {
.name = "SCTPv6",
.owner = THIS_MODULE,
@@ -6513,5 +6514,6 @@ struct proto sctpv6_prot = {
.memory_pressure = &sctp_memory_pressure,
.enter_memory_pressure = sctp_enter_memory_pressure,
.memory_allocated = &sctp_memory_allocated,
+ REF_PROTO_INUSE(sctpv6)
};
#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index 0669778e4335..da4f15734fb1 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -263,6 +263,15 @@ static ctl_table sctp_table[] = {
.proc_handler = &proc_dointvec,
.strategy = &sysctl_intvec
},
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "addip_noauth_enable",
+ .data = &sctp_addip_noauth,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ .strategy = &sysctl_intvec
+ },
{ .ctl_name = 0 }
};
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index 5f467c914f80..d55ce83a020b 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -74,8 +74,8 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
* given destination transport address, set RTO to the protocol
* parameter 'RTO.Initial'.
*/
+ peer->last_rto = peer->rto = msecs_to_jiffies(sctp_rto_initial);
peer->rtt = 0;
- peer->rto = msecs_to_jiffies(sctp_rto_initial);
peer->rttvar = 0;
peer->srtt = 0;
peer->rto_pending = 0;
@@ -385,6 +385,7 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt)
tp->rto = tp->asoc->rto_max;
tp->rtt = rtt;
+ tp->last_rto = tp->rto;
/* Reset rto_pending so that a new RTT measurement is started when a
* new data chunk is sent.
@@ -578,7 +579,7 @@ void sctp_transport_reset(struct sctp_transport *t)
*/
t->cwnd = min(4*asoc->pathmtu, max_t(__u32, 2*asoc->pathmtu, 4380));
t->ssthresh = asoc->peer.i.a_rwnd;
- t->rto = asoc->rto_initial;
+ t->last_rto = t->rto = asoc->rto_initial;
t->rtt = 0;
t->srtt = 0;
t->rttvar = 0;
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c
index b9370956b187..4908041ffb31 100644
--- a/net/sctp/ulpqueue.c
+++ b/net/sctp/ulpqueue.c
@@ -862,7 +862,7 @@ static inline void sctp_ulpq_reap_ordered(struct sctp_ulpq *ulpq, __u16 sid)
continue;
/* see if this ssn has been marked by skipping */
- if (!SSN_lt(cssn, sctp_ssn_peek(in, csid)))
+ if (!SSN_lte(cssn, sctp_ssn_peek(in, csid)))
break;
__skb_unlink(pos, &ulpq->lobby);
@@ -908,8 +908,8 @@ void sctp_ulpq_skip(struct sctp_ulpq *ulpq, __u16 sid, __u16 ssn)
return;
}
-/* Renege 'needed' bytes from the ordering queue. */
-static __u16 sctp_ulpq_renege_order(struct sctp_ulpq *ulpq, __u16 needed)
+static __u16 sctp_ulpq_renege_list(struct sctp_ulpq *ulpq,
+ struct sk_buff_head *list, __u16 needed)
{
__u16 freed = 0;
__u32 tsn;
@@ -919,7 +919,7 @@ static __u16 sctp_ulpq_renege_order(struct sctp_ulpq *ulpq, __u16 needed)
tsnmap = &ulpq->asoc->peer.tsn_map;
- while ((skb = __skb_dequeue_tail(&ulpq->lobby)) != NULL) {
+ while ((skb = __skb_dequeue_tail(list)) != NULL) {
freed += skb_headlen(skb);
event = sctp_skb2event(skb);
tsn = event->tsn;
@@ -933,30 +933,16 @@ static __u16 sctp_ulpq_renege_order(struct sctp_ulpq *ulpq, __u16 needed)
return freed;
}
+/* Renege 'needed' bytes from the ordering queue. */
+static __u16 sctp_ulpq_renege_order(struct sctp_ulpq *ulpq, __u16 needed)
+{
+ return sctp_ulpq_renege_list(ulpq, &ulpq->lobby, needed);
+}
+
/* Renege 'needed' bytes from the reassembly queue. */
static __u16 sctp_ulpq_renege_frags(struct sctp_ulpq *ulpq, __u16 needed)
{
- __u16 freed = 0;
- __u32 tsn;
- struct sk_buff *skb;
- struct sctp_ulpevent *event;
- struct sctp_tsnmap *tsnmap;
-
- tsnmap = &ulpq->asoc->peer.tsn_map;
-
- /* Walk backwards through the list, reneges the newest tsns. */
- while ((skb = __skb_dequeue_tail(&ulpq->reasm)) != NULL) {
- freed += skb_headlen(skb);
- event = sctp_skb2event(skb);
- tsn = event->tsn;
-
- sctp_ulpevent_free(event);
- sctp_tsnmap_renege(tsnmap, tsn);
- if (freed >= needed)
- return freed;
- }
-
- return freed;
+ return sctp_ulpq_renege_list(ulpq, &ulpq->reasm, needed);
}
/* Partial deliver the first message as there is pressure on rwnd. */
diff --git a/net/socket.c b/net/socket.c
index 379b3a390755..74784dfe8e5b 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -258,7 +258,7 @@ static void sock_destroy_inode(struct inode *inode)
container_of(inode, struct socket_alloc, vfs_inode));
}
-static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags)
+static void init_once(struct kmem_cache *cachep, void *foo)
{
struct socket_alloc *ei = (struct socket_alloc *)foo;
@@ -364,26 +364,26 @@ static int sock_alloc_fd(struct file **filep)
static int sock_attach_fd(struct socket *sock, struct file *file)
{
+ struct dentry *dentry;
struct qstr name = { .name = "" };
- file->f_path.dentry = d_alloc(sock_mnt->mnt_sb->s_root, &name);
- if (unlikely(!file->f_path.dentry))
+ dentry = d_alloc(sock_mnt->mnt_sb->s_root, &name);
+ if (unlikely(!dentry))
return -ENOMEM;
- file->f_path.dentry->d_op = &sockfs_dentry_operations;
+ dentry->d_op = &sockfs_dentry_operations;
/*
* We dont want to push this dentry into global dentry hash table.
* We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED
* This permits a working /proc/$pid/fd/XXX on sockets
*/
- file->f_path.dentry->d_flags &= ~DCACHE_UNHASHED;
- d_instantiate(file->f_path.dentry, SOCK_INODE(sock));
- file->f_path.mnt = mntget(sock_mnt);
- file->f_mapping = file->f_path.dentry->d_inode->i_mapping;
+ dentry->d_flags &= ~DCACHE_UNHASHED;
+ d_instantiate(dentry, SOCK_INODE(sock));
sock->file = file;
- file->f_op = SOCK_INODE(sock)->i_fop = &socket_file_ops;
- file->f_mode = FMODE_READ | FMODE_WRITE;
+ init_file(file, sock_mnt, dentry, FMODE_READ | FMODE_WRITE,
+ &socket_file_ops);
+ SOCK_INODE(sock)->i_fop = &socket_file_ops;
file->f_flags = O_RDWR;
file->f_pos = 0;
file->private_data = sock;
@@ -1250,11 +1250,14 @@ asmlinkage long sys_socketpair(int family, int type, int protocol,
goto out_release_both;
fd1 = sock_alloc_fd(&newfile1);
- if (unlikely(fd1 < 0))
+ if (unlikely(fd1 < 0)) {
+ err = fd1;
goto out_release_both;
+ }
fd2 = sock_alloc_fd(&newfile2);
if (unlikely(fd2 < 0)) {
+ err = fd2;
put_filp(newfile1);
put_unused_fd(fd1);
goto out_release_both;
@@ -2316,6 +2319,11 @@ int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg)
return err;
}
+int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
+{
+ return sock->ops->shutdown(sock, how);
+}
+
/* ABI emulation layers need these two */
EXPORT_SYMBOL(move_addr_to_kernel);
EXPORT_SYMBOL(move_addr_to_user);
@@ -2342,3 +2350,4 @@ EXPORT_SYMBOL(kernel_getsockopt);
EXPORT_SYMBOL(kernel_setsockopt);
EXPORT_SYMBOL(kernel_sendpage);
EXPORT_SYMBOL(kernel_sock_ioctl);
+EXPORT_SYMBOL(kernel_sock_shutdown);
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
index bfb6a29633dd..0dd792338fa9 100644
--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
+++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
@@ -75,7 +75,7 @@ krb5_encrypt(
memcpy(local_iv, iv, crypto_blkcipher_ivsize(tfm));
memcpy(out, in, length);
- sg_set_buf(sg, out, length);
+ sg_init_one(sg, out, length);
ret = crypto_blkcipher_encrypt_iv(&desc, sg, sg, length);
out:
@@ -110,7 +110,7 @@ krb5_decrypt(
memcpy(local_iv,iv, crypto_blkcipher_ivsize(tfm));
memcpy(out, in, length);
- sg_set_buf(sg, out, length);
+ sg_init_one(sg, out, length);
ret = crypto_blkcipher_decrypt_iv(&desc, sg, sg, length);
out:
@@ -146,7 +146,7 @@ make_checksum(char *cksumname, char *header, int hdrlen, struct xdr_buf *body,
err = crypto_hash_init(&desc);
if (err)
goto out;
- sg_set_buf(sg, header, hdrlen);
+ sg_init_one(sg, header, hdrlen);
err = crypto_hash_update(&desc, sg, hdrlen);
if (err)
goto out;
@@ -188,8 +188,6 @@ encryptor(struct scatterlist *sg, void *data)
/* Worst case is 4 fragments: head, end of page 1, start
* of page 2, tail. Anything more is a bug. */
BUG_ON(desc->fragno > 3);
- desc->infrags[desc->fragno] = *sg;
- desc->outfrags[desc->fragno] = *sg;
page_pos = desc->pos - outbuf->head[0].iov_len;
if (page_pos >= 0 && page_pos < outbuf->page_len) {
@@ -197,9 +195,12 @@ encryptor(struct scatterlist *sg, void *data)
int i = (page_pos + outbuf->page_base) >> PAGE_CACHE_SHIFT;
in_page = desc->pages[i];
} else {
- in_page = sg->page;
+ in_page = sg_page(sg);
}
- desc->infrags[desc->fragno].page = in_page;
+ sg_set_page(&desc->infrags[desc->fragno], in_page, sg->length,
+ sg->offset);
+ sg_set_page(&desc->outfrags[desc->fragno], sg_page(sg), sg->length,
+ sg->offset);
desc->fragno++;
desc->fraglen += sg->length;
desc->pos += sg->length;
@@ -210,16 +211,22 @@ encryptor(struct scatterlist *sg, void *data)
if (thislen == 0)
return 0;
+ sg_mark_end(&desc->infrags[desc->fragno - 1]);
+ sg_mark_end(&desc->outfrags[desc->fragno - 1]);
+
ret = crypto_blkcipher_encrypt_iv(&desc->desc, desc->outfrags,
desc->infrags, thislen);
if (ret)
return ret;
+
+ sg_init_table(desc->infrags, 4);
+ sg_init_table(desc->outfrags, 4);
+
if (fraglen) {
- desc->outfrags[0].page = sg->page;
- desc->outfrags[0].offset = sg->offset + sg->length - fraglen;
- desc->outfrags[0].length = fraglen;
+ sg_set_page(&desc->outfrags[0], sg_page(sg), fraglen,
+ sg->offset + sg->length - fraglen);
desc->infrags[0] = desc->outfrags[0];
- desc->infrags[0].page = in_page;
+ sg_assign_page(&desc->infrags[0], in_page);
desc->fragno = 1;
desc->fraglen = fraglen;
} else {
@@ -248,6 +255,9 @@ gss_encrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *buf,
desc.fragno = 0;
desc.fraglen = 0;
+ sg_init_table(desc.infrags, 4);
+ sg_init_table(desc.outfrags, 4);
+
ret = xdr_process_buf(buf, offset, buf->len - offset, encryptor, &desc);
return ret;
}
@@ -272,7 +282,8 @@ decryptor(struct scatterlist *sg, void *data)
/* Worst case is 4 fragments: head, end of page 1, start
* of page 2, tail. Anything more is a bug. */
BUG_ON(desc->fragno > 3);
- desc->frags[desc->fragno] = *sg;
+ sg_set_page(&desc->frags[desc->fragno], sg_page(sg), sg->length,
+ sg->offset);
desc->fragno++;
desc->fraglen += sg->length;
@@ -282,14 +293,18 @@ decryptor(struct scatterlist *sg, void *data)
if (thislen == 0)
return 0;
+ sg_mark_end(&desc->frags[desc->fragno - 1]);
+
ret = crypto_blkcipher_decrypt_iv(&desc->desc, desc->frags,
desc->frags, thislen);
if (ret)
return ret;
+
+ sg_init_table(desc->frags, 4);
+
if (fraglen) {
- desc->frags[0].page = sg->page;
- desc->frags[0].offset = sg->offset + sg->length - fraglen;
- desc->frags[0].length = fraglen;
+ sg_set_page(&desc->frags[0], sg_page(sg), fraglen,
+ sg->offset + sg->length - fraglen);
desc->fragno = 1;
desc->fraglen = fraglen;
} else {
@@ -314,6 +329,9 @@ gss_decrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *buf,
desc.desc.flags = 0;
desc.fragno = 0;
desc.fraglen = 0;
+
+ sg_init_table(desc.frags, 4);
+
return xdr_process_buf(buf, offset, buf->len - offset, decryptor, &desc);
}
diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
index a0d9faa59cb5..1c6eda5077c1 100644
--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
@@ -63,7 +63,6 @@
#include <linux/jiffies.h>
#include <linux/sunrpc/gss_krb5.h>
#include <linux/random.h>
-#include <asm/scatterlist.h>
#include <linux/crypto.h>
#ifdef RPC_DEBUG
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
index 8bd074df27d3..3bdc527ee64a 100644
--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
+++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
@@ -4,7 +4,6 @@
#include <linux/sunrpc/gss_krb5.h>
#include <linux/random.h>
#include <linux/pagemap.h>
-#include <asm/scatterlist.h>
#include <linux/crypto.h>
#ifdef RPC_DEBUG
diff --git a/net/sunrpc/auth_gss/gss_spkm3_seal.c b/net/sunrpc/auth_gss/gss_spkm3_seal.c
index d158635de6c0..abf17ce2e3b1 100644
--- a/net/sunrpc/auth_gss/gss_spkm3_seal.c
+++ b/net/sunrpc/auth_gss/gss_spkm3_seal.c
@@ -173,7 +173,7 @@ make_spkm3_checksum(s32 cksumtype, struct xdr_netobj *key, char *header,
if (err)
goto out;
- sg_set_buf(sg, header, hdrlen);
+ sg_init_one(sg, header, hdrlen);
crypto_hash_update(&desc, sg, sg->length);
xdr_process_buf(body, body_offset, body->len - body_offset,
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index c8433e8865aa..18f0a8dcc095 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -842,7 +842,7 @@ static struct file_system_type rpc_pipe_fs_type = {
};
static void
-init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
+init_once(struct kmem_cache * cachep, void *foo)
{
struct rpc_inode *rpci = (struct rpc_inode *) foo;
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 3c773c53e12e..c98873f39aec 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -847,7 +847,7 @@ void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, int flags, cons
task->tk_start = jiffies;
dprintk("RPC: new task initialized, procpid %u\n",
- current->pid);
+ task_pid_nr(current));
}
static struct rpc_task *
diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c
index 738db32a287d..2be714e9b382 100644
--- a/net/sunrpc/sysctl.c
+++ b/net/sunrpc/sysctl.c
@@ -87,9 +87,8 @@ proc_dodebug(ctl_table *table, int write, struct file *file,
left--, s++;
*(unsigned int *) table->data = value;
/* Display the RPC tasks on writing to rpc_debug */
- if (table->ctl_name == CTL_RPCDEBUG) {
+ if (strcmp(table->procname, "rpc_debug") == 0)
rpc_show_tasks();
- }
} else {
if (!access_ok(VERIFY_WRITE, buffer, left))
return -EFAULT;
@@ -114,7 +113,6 @@ done:
static ctl_table debug_table[] = {
{
- .ctl_name = CTL_RPCDEBUG,
.procname = "rpc_debug",
.data = &rpc_debug,
.maxlen = sizeof(int),
@@ -122,7 +120,6 @@ static ctl_table debug_table[] = {
.proc_handler = &proc_dodebug
},
{
- .ctl_name = CTL_NFSDEBUG,
.procname = "nfs_debug",
.data = &nfs_debug,
.maxlen = sizeof(int),
@@ -130,7 +127,6 @@ static ctl_table debug_table[] = {
.proc_handler = &proc_dodebug
},
{
- .ctl_name = CTL_NFSDDEBUG,
.procname = "nfsd_debug",
.data = &nfsd_debug,
.maxlen = sizeof(int),
@@ -138,7 +134,6 @@ static ctl_table debug_table[] = {
.proc_handler = &proc_dodebug
},
{
- .ctl_name = CTL_NLMDEBUG,
.procname = "nlm_debug",
.data = &nlm_debug,
.maxlen = sizeof(int),
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c
index 6a59180e1667..fdc5e6d7562b 100644
--- a/net/sunrpc/xdr.c
+++ b/net/sunrpc/xdr.c
@@ -1030,6 +1030,8 @@ xdr_process_buf(struct xdr_buf *buf, unsigned int offset, unsigned int len,
unsigned page_len, thislen, page_offset;
struct scatterlist sg[1];
+ sg_init_table(sg, 1);
+
if (offset >= buf->head[0].iov_len) {
offset -= buf->head[0].iov_len;
} else {
@@ -1059,9 +1061,7 @@ xdr_process_buf(struct xdr_buf *buf, unsigned int offset, unsigned int len,
do {
if (thislen > page_len)
thislen = page_len;
- sg->page = buf->pages[i];
- sg->offset = page_offset;
- sg->length = thislen;
+ sg_set_page(sg, buf->pages[i], thislen, page_offset);
ret = actor(sg, data);
if (ret)
goto out;
diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c
index 12db63580427..9e11ce715958 100644
--- a/net/sunrpc/xprtrdma/rpc_rdma.c
+++ b/net/sunrpc/xprtrdma/rpc_rdma.c
@@ -181,7 +181,7 @@ rpcrdma_create_chunks(struct rpc_rqst *rqst, struct xdr_buf *target,
struct rpcrdma_read_chunk *cur_rchunk = NULL;
struct rpcrdma_write_array *warray = NULL;
struct rpcrdma_write_chunk *cur_wchunk = NULL;
- u32 *iptr = headerp->rm_body.rm_chunks;
+ __be32 *iptr = headerp->rm_body.rm_chunks;
if (type == rpcrdma_readch || type == rpcrdma_areadch) {
/* a read chunk - server will RDMA Read our memory */
@@ -217,25 +217,25 @@ rpcrdma_create_chunks(struct rpc_rqst *rqst, struct xdr_buf *target,
cur_rchunk->rc_target.rs_handle = htonl(seg->mr_rkey);
cur_rchunk->rc_target.rs_length = htonl(seg->mr_len);
xdr_encode_hyper(
- (u32 *)&cur_rchunk->rc_target.rs_offset,
+ (__be32 *)&cur_rchunk->rc_target.rs_offset,
seg->mr_base);
dprintk("RPC: %s: read chunk "
"elem %d@0x%llx:0x%x pos %d (%s)\n", __func__,
- seg->mr_len, seg->mr_base, seg->mr_rkey, pos,
- n < nsegs ? "more" : "last");
+ seg->mr_len, (unsigned long long)seg->mr_base,
+ seg->mr_rkey, pos, n < nsegs ? "more" : "last");
cur_rchunk++;
r_xprt->rx_stats.read_chunk_count++;
} else { /* write/reply */
cur_wchunk->wc_target.rs_handle = htonl(seg->mr_rkey);
cur_wchunk->wc_target.rs_length = htonl(seg->mr_len);
xdr_encode_hyper(
- (u32 *)&cur_wchunk->wc_target.rs_offset,
+ (__be32 *)&cur_wchunk->wc_target.rs_offset,
seg->mr_base);
dprintk("RPC: %s: %s chunk "
"elem %d@0x%llx:0x%x (%s)\n", __func__,
(type == rpcrdma_replych) ? "reply" : "write",
- seg->mr_len, seg->mr_base, seg->mr_rkey,
- n < nsegs ? "more" : "last");
+ seg->mr_len, (unsigned long long)seg->mr_base,
+ seg->mr_rkey, n < nsegs ? "more" : "last");
cur_wchunk++;
if (type == rpcrdma_replych)
r_xprt->rx_stats.reply_chunk_count++;
@@ -257,14 +257,14 @@ rpcrdma_create_chunks(struct rpc_rqst *rqst, struct xdr_buf *target,
* finish off header. If write, marshal discrim and nchunks.
*/
if (cur_rchunk) {
- iptr = (u32 *) cur_rchunk;
+ iptr = (__be32 *) cur_rchunk;
*iptr++ = xdr_zero; /* finish the read chunk list */
*iptr++ = xdr_zero; /* encode a NULL write chunk list */
*iptr++ = xdr_zero; /* encode a NULL reply chunk */
} else {
warray->wc_discrim = xdr_one;
warray->wc_nchunks = htonl(nchunks);
- iptr = (u32 *) cur_wchunk;
+ iptr = (__be32 *) cur_wchunk;
if (type == rpcrdma_writech) {
*iptr++ = xdr_zero; /* finish the write chunk list */
*iptr++ = xdr_zero; /* encode a NULL reply chunk */
@@ -559,7 +559,7 @@ rpcrdma_marshal_req(struct rpc_rqst *rqst)
* RDMA'd by server. See map at rpcrdma_create_chunks()! :-)
*/
static int
-rpcrdma_count_chunks(struct rpcrdma_rep *rep, int max, int wrchunk, u32 **iptrp)
+rpcrdma_count_chunks(struct rpcrdma_rep *rep, int max, int wrchunk, __be32 **iptrp)
{
unsigned int i, total_len;
struct rpcrdma_write_chunk *cur_wchunk;
@@ -573,11 +573,11 @@ rpcrdma_count_chunks(struct rpcrdma_rep *rep, int max, int wrchunk, u32 **iptrp)
struct rpcrdma_segment *seg = &cur_wchunk->wc_target;
ifdebug(FACILITY) {
u64 off;
- xdr_decode_hyper((u32 *)&seg->rs_offset, &off);
+ xdr_decode_hyper((__be32 *)&seg->rs_offset, &off);
dprintk("RPC: %s: chunk %d@0x%llx:0x%x\n",
__func__,
ntohl(seg->rs_length),
- off,
+ (unsigned long long)off,
ntohl(seg->rs_handle));
}
total_len += ntohl(seg->rs_length);
@@ -585,7 +585,7 @@ rpcrdma_count_chunks(struct rpcrdma_rep *rep, int max, int wrchunk, u32 **iptrp)
}
/* check and adjust for properly terminated write chunk */
if (wrchunk) {
- u32 *w = (u32 *) cur_wchunk;
+ __be32 *w = (__be32 *) cur_wchunk;
if (*w++ != xdr_zero)
return -1;
cur_wchunk = (struct rpcrdma_write_chunk *) w;
@@ -593,7 +593,7 @@ rpcrdma_count_chunks(struct rpcrdma_rep *rep, int max, int wrchunk, u32 **iptrp)
if ((char *) cur_wchunk > rep->rr_base + rep->rr_len)
return -1;
- *iptrp = (u32 *) cur_wchunk;
+ *iptrp = (__be32 *) cur_wchunk;
return total_len;
}
@@ -721,7 +721,7 @@ rpcrdma_reply_handler(struct rpcrdma_rep *rep)
struct rpc_rqst *rqst;
struct rpc_xprt *xprt = rep->rr_xprt;
struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt);
- u32 *iptr;
+ __be32 *iptr;
int i, rdmalen, status;
/* Check status. If bad, signal disconnect and return rep to pool */
@@ -801,7 +801,7 @@ repost:
r_xprt->rx_stats.total_rdma_reply += rdmalen;
} else {
/* else ordinary inline */
- iptr = (u32 *)((unsigned char *)headerp + 28);
+ iptr = (__be32 *)((unsigned char *)headerp + 28);
rep->rr_len -= 28; /*sizeof *headerp;*/
status = rep->rr_len;
}
@@ -816,7 +816,7 @@ repost:
headerp->rm_body.rm_chunks[2] != xdr_one ||
req->rl_nchunks == 0)
goto badheader;
- iptr = (u32 *)((unsigned char *)headerp + 28);
+ iptr = (__be32 *)((unsigned char *)headerp + 28);
rdmalen = rpcrdma_count_chunks(rep, req->rl_nchunks, 0, &iptr);
if (rdmalen < 0)
goto badheader;
diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c
index dc55cc974c90..1afeb3eb8e4c 100644
--- a/net/sunrpc/xprtrdma/transport.c
+++ b/net/sunrpc/xprtrdma/transport.c
@@ -320,9 +320,9 @@ xprt_setup_rdma(struct xprt_create *args)
xprt->slot = kcalloc(xprt->max_reqs,
sizeof(struct rpc_rqst), GFP_KERNEL);
if (xprt->slot == NULL) {
- kfree(xprt);
dprintk("RPC: %s: couldn't allocate %d slots\n",
__func__, xprt->max_reqs);
+ kfree(xprt);
return ERR_PTR(-ENOMEM);
}
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c
index 9ec8ca4f6028..44b0fb942e8d 100644
--- a/net/sunrpc/xprtrdma/verbs.c
+++ b/net/sunrpc/xprtrdma/verbs.c
@@ -1263,7 +1263,8 @@ rpcrdma_register_internal(struct rpcrdma_ia *ia, void *va, int len,
dprintk("RPC: %s: phys convert: 0x%llx "
"registered 0x%llx length %d\n",
- __func__, ipb.addr, iov->addr, len);
+ __func__, (unsigned long long)ipb.addr,
+ (unsigned long long)iov->addr, len);
if (IS_ERR(mr)) {
*mrp = NULL;
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index e36b4b5a5222..6b792265dc06 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -201,7 +201,7 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol)
return -EPROTOTYPE;
}
- sk = sk_alloc(net, AF_TIPC, GFP_KERNEL, &tipc_proto, 1);
+ sk = sk_alloc(net, AF_TIPC, GFP_KERNEL, &tipc_proto);
if (!sk) {
tipc_deleteport(ref);
return -ENOMEM;
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 6996cba5aa96..e835da8fc091 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -457,7 +457,7 @@ static int unix_release_sock (struct sock *sk, int embrion)
* What the above comment does talk about? --ANK(980817)
*/
- if (atomic_read(&unix_tot_inflight))
+ if (unix_tot_inflight)
unix_gc(); /* Garbage collect fds */
return 0;
@@ -483,7 +483,7 @@ static int unix_listen(struct socket *sock, int backlog)
sk->sk_max_ack_backlog = backlog;
sk->sk_state = TCP_LISTEN;
/* set credentials so connect can copy them */
- sk->sk_peercred.pid = current->tgid;
+ sk->sk_peercred.pid = task_tgid_vnr(current);
sk->sk_peercred.uid = current->euid;
sk->sk_peercred.gid = current->egid;
err = 0;
@@ -599,15 +599,14 @@ static struct sock * unix_create1(struct net *net, struct socket *sock)
struct sock *sk = NULL;
struct unix_sock *u;
- if (atomic_read(&unix_nr_socks) >= 2*get_max_files())
+ atomic_inc(&unix_nr_socks);
+ if (atomic_read(&unix_nr_socks) > 2 * get_max_files())
goto out;
- sk = sk_alloc(net, PF_UNIX, GFP_KERNEL, &unix_proto, 1);
+ sk = sk_alloc(net, PF_UNIX, GFP_KERNEL, &unix_proto);
if (!sk)
goto out;
- atomic_inc(&unix_nr_socks);
-
sock_init_data(sock,sk);
lockdep_set_class(&sk->sk_receive_queue.lock,
&af_unix_sk_receive_queue_lock_key);
@@ -625,6 +624,8 @@ static struct sock * unix_create1(struct net *net, struct socket *sock)
init_waitqueue_head(&u->peer_wait);
unix_insert_socket(unix_sockets_unbound, sk);
out:
+ if (sk == NULL)
+ atomic_dec(&unix_nr_socks);
return sk;
}
@@ -1133,7 +1134,7 @@ restart:
unix_peer(newsk) = sk;
newsk->sk_state = TCP_ESTABLISHED;
newsk->sk_type = sk->sk_type;
- newsk->sk_peercred.pid = current->tgid;
+ newsk->sk_peercred.pid = task_tgid_vnr(current);
newsk->sk_peercred.uid = current->euid;
newsk->sk_peercred.gid = current->egid;
newu = unix_sk(newsk);
@@ -1194,7 +1195,7 @@ static int unix_socketpair(struct socket *socka, struct socket *sockb)
sock_hold(skb);
unix_peer(ska)=skb;
unix_peer(skb)=ska;
- ska->sk_peercred.pid = skb->sk_peercred.pid = current->tgid;
+ ska->sk_peercred.pid = skb->sk_peercred.pid = task_tgid_vnr(current);
ska->sk_peercred.uid = skb->sk_peercred.uid = current->euid;
ska->sk_peercred.gid = skb->sk_peercred.gid = current->egid;
diff --git a/net/unix/garbage.c b/net/unix/garbage.c
index 406b6433e467..ebdff3d877a1 100644
--- a/net/unix/garbage.c
+++ b/net/unix/garbage.c
@@ -92,7 +92,7 @@ static LIST_HEAD(gc_inflight_list);
static LIST_HEAD(gc_candidates);
static DEFINE_SPINLOCK(unix_gc_lock);
-atomic_t unix_tot_inflight = ATOMIC_INIT(0);
+unsigned int unix_tot_inflight;
static struct sock *unix_get_socket(struct file *filp)
@@ -133,7 +133,7 @@ void unix_inflight(struct file *fp)
} else {
BUG_ON(list_empty(&u->link));
}
- atomic_inc(&unix_tot_inflight);
+ unix_tot_inflight++;
spin_unlock(&unix_gc_lock);
}
}
@@ -147,7 +147,7 @@ void unix_notinflight(struct file *fp)
BUG_ON(list_empty(&u->link));
if (atomic_dec_and_test(&u->inflight))
list_del_init(&u->link);
- atomic_dec(&unix_tot_inflight);
+ unix_tot_inflight--;
spin_unlock(&unix_gc_lock);
}
}
@@ -161,7 +161,7 @@ static inline struct sk_buff *sock_queue_head(struct sock *sk)
for (skb = sock_queue_head(sk)->next, next = skb->next; \
skb != sock_queue_head(sk); skb = next, next = skb->next)
-static void scan_inflight(struct sock *x, void (*func)(struct sock *),
+static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *),
struct sk_buff_head *hitlist)
{
struct sk_buff *skb;
@@ -185,9 +185,9 @@ static void scan_inflight(struct sock *x, void (*func)(struct sock *),
* if it indeed does so
*/
struct sock *sk = unix_get_socket(*fp++);
- if(sk) {
+ if (sk) {
hit = true;
- func(sk);
+ func(unix_sk(sk));
}
}
if (hit && hitlist != NULL) {
@@ -199,7 +199,7 @@ static void scan_inflight(struct sock *x, void (*func)(struct sock *),
spin_unlock(&x->sk_receive_queue.lock);
}
-static void scan_children(struct sock *x, void (*func)(struct sock *),
+static void scan_children(struct sock *x, void (*func)(struct unix_sock *),
struct sk_buff_head *hitlist)
{
if (x->sk_state != TCP_LISTEN)
@@ -235,20 +235,18 @@ static void scan_children(struct sock *x, void (*func)(struct sock *),
}
}
-static void dec_inflight(struct sock *sk)
+static void dec_inflight(struct unix_sock *usk)
{
- atomic_dec(&unix_sk(sk)->inflight);
+ atomic_dec(&usk->inflight);
}
-static void inc_inflight(struct sock *sk)
+static void inc_inflight(struct unix_sock *usk)
{
- atomic_inc(&unix_sk(sk)->inflight);
+ atomic_inc(&usk->inflight);
}
-static void inc_inflight_move_tail(struct sock *sk)
+static void inc_inflight_move_tail(struct unix_sock *u)
{
- struct unix_sock *u = unix_sk(sk);
-
atomic_inc(&u->inflight);
/*
* If this is still a candidate, move it to the end of the
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index fc416f9606a9..92cfe8e3e0b8 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -472,7 +472,7 @@ static struct proto x25_proto = {
static struct sock *x25_alloc_socket(struct net *net)
{
struct x25_sock *x25;
- struct sock *sk = sk_alloc(net, AF_X25, GFP_ATOMIC, &x25_proto, 1);
+ struct sock *sk = sk_alloc(net, AF_X25, GFP_ATOMIC, &x25_proto);
if (!sk)
goto out;
diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c
index 5ced62c19c63..1686f64c4352 100644
--- a/net/xfrm/xfrm_algo.c
+++ b/net/xfrm/xfrm_algo.c
@@ -13,6 +13,7 @@
#include <linux/kernel.h>
#include <linux/pfkeyv2.h>
#include <linux/crypto.h>
+#include <linux/scatterlist.h>
#include <net/xfrm.h>
#if defined(CONFIG_INET_AH) || defined(CONFIG_INET_AH_MODULE) || defined(CONFIG_INET6_AH) || defined(CONFIG_INET6_AH_MODULE)
#include <net/ah.h>
@@ -20,7 +21,6 @@
#if defined(CONFIG_INET_ESP) || defined(CONFIG_INET_ESP_MODULE) || defined(CONFIG_INET6_ESP) || defined(CONFIG_INET6_ESP_MODULE)
#include <net/esp.h>
#endif
-#include <asm/scatterlist.h>
/*
* Algorithms supported by IPsec. These entries contain properties which
@@ -552,9 +552,7 @@ int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc,
if (copy > len)
copy = len;
- sg.page = virt_to_page(skb->data + offset);
- sg.offset = (unsigned long)(skb->data + offset) % PAGE_SIZE;
- sg.length = copy;
+ sg_init_one(&sg, skb->data + offset, copy);
err = icv_update(desc, &sg, copy);
if (unlikely(err))
@@ -577,9 +575,9 @@ int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc,
if (copy > len)
copy = len;
- sg.page = frag->page;
- sg.offset = frag->page_offset + offset-start;
- sg.length = copy;
+ sg_init_table(&sg, 1);
+ sg_set_page(&sg, frag->page, copy,
+ frag->page_offset + offset-start);
err = icv_update(desc, &sg, copy);
if (unlikely(err))
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 113f44429982..cb97fda1b6df 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -49,13 +49,16 @@ EXPORT_SYMBOL(secpath_dup);
int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq)
{
int offset, offset_seq;
+ int hlen;
switch (nexthdr) {
case IPPROTO_AH:
+ hlen = sizeof(struct ip_auth_hdr);
offset = offsetof(struct ip_auth_hdr, spi);
offset_seq = offsetof(struct ip_auth_hdr, seq_no);
break;
case IPPROTO_ESP:
+ hlen = sizeof(struct ip_esp_hdr);
offset = offsetof(struct ip_esp_hdr, spi);
offset_seq = offsetof(struct ip_esp_hdr, seq_no);
break;
@@ -69,7 +72,7 @@ int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq)
return 1;
}
- if (!pskb_may_pull(skb, 16))
+ if (!pskb_may_pull(skb, hlen))
return -EINVAL;
*spi = *(__be32*)(skb_transport_header(skb) + offset);
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index 0eb3377602e9..f4bfd6c45651 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -63,7 +63,7 @@ int xfrm_output(struct sk_buff *skb)
xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
}
- err = x->mode->output(x, skb);
+ err = x->outer_mode->output(x, skb);
if (err)
goto error;
@@ -82,7 +82,7 @@ int xfrm_output(struct sk_buff *skb)
}
dst = skb->dst;
x = dst->xfrm;
- } while (x && (x->props.mode != XFRM_MODE_TUNNEL));
+ } while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL));
err = 0;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index af27c193697c..b702bd8a3893 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -49,8 +49,6 @@ static DEFINE_SPINLOCK(xfrm_policy_gc_lock);
static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family);
static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo);
-static struct xfrm_policy_afinfo *xfrm_policy_lock_afinfo(unsigned int family);
-static void xfrm_policy_unlock_afinfo(struct xfrm_policy_afinfo *afinfo);
static inline int
__xfrm4_selector_match(struct xfrm_selector *sel, struct flowi *fl)
@@ -86,72 +84,6 @@ int xfrm_selector_match(struct xfrm_selector *sel, struct flowi *fl,
return 0;
}
-int xfrm_register_type(struct xfrm_type *type, unsigned short family)
-{
- struct xfrm_policy_afinfo *afinfo = xfrm_policy_lock_afinfo(family);
- struct xfrm_type **typemap;
- int err = 0;
-
- if (unlikely(afinfo == NULL))
- return -EAFNOSUPPORT;
- typemap = afinfo->type_map;
-
- if (likely(typemap[type->proto] == NULL))
- typemap[type->proto] = type;
- else
- err = -EEXIST;
- xfrm_policy_unlock_afinfo(afinfo);
- return err;
-}
-EXPORT_SYMBOL(xfrm_register_type);
-
-int xfrm_unregister_type(struct xfrm_type *type, unsigned short family)
-{
- struct xfrm_policy_afinfo *afinfo = xfrm_policy_lock_afinfo(family);
- struct xfrm_type **typemap;
- int err = 0;
-
- if (unlikely(afinfo == NULL))
- return -EAFNOSUPPORT;
- typemap = afinfo->type_map;
-
- if (unlikely(typemap[type->proto] != type))
- err = -ENOENT;
- else
- typemap[type->proto] = NULL;
- xfrm_policy_unlock_afinfo(afinfo);
- return err;
-}
-EXPORT_SYMBOL(xfrm_unregister_type);
-
-struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family)
-{
- struct xfrm_policy_afinfo *afinfo;
- struct xfrm_type **typemap;
- struct xfrm_type *type;
- int modload_attempted = 0;
-
-retry:
- afinfo = xfrm_policy_get_afinfo(family);
- if (unlikely(afinfo == NULL))
- return NULL;
- typemap = afinfo->type_map;
-
- type = typemap[proto];
- if (unlikely(type && !try_module_get(type->owner)))
- type = NULL;
- if (!type && !modload_attempted) {
- xfrm_policy_put_afinfo(afinfo);
- request_module("xfrm-type-%d-%d",
- (int) family, (int) proto);
- modload_attempted = 1;
- goto retry;
- }
-
- xfrm_policy_put_afinfo(afinfo);
- return type;
-}
-
int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl,
unsigned short family)
{
@@ -170,94 +102,6 @@ int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl,
}
EXPORT_SYMBOL(xfrm_dst_lookup);
-void xfrm_put_type(struct xfrm_type *type)
-{
- module_put(type->owner);
-}
-
-int xfrm_register_mode(struct xfrm_mode *mode, int family)
-{
- struct xfrm_policy_afinfo *afinfo;
- struct xfrm_mode **modemap;
- int err;
-
- if (unlikely(mode->encap >= XFRM_MODE_MAX))
- return -EINVAL;
-
- afinfo = xfrm_policy_lock_afinfo(family);
- if (unlikely(afinfo == NULL))
- return -EAFNOSUPPORT;
-
- err = -EEXIST;
- modemap = afinfo->mode_map;
- if (likely(modemap[mode->encap] == NULL)) {
- modemap[mode->encap] = mode;
- err = 0;
- }
-
- xfrm_policy_unlock_afinfo(afinfo);
- return err;
-}
-EXPORT_SYMBOL(xfrm_register_mode);
-
-int xfrm_unregister_mode(struct xfrm_mode *mode, int family)
-{
- struct xfrm_policy_afinfo *afinfo;
- struct xfrm_mode **modemap;
- int err;
-
- if (unlikely(mode->encap >= XFRM_MODE_MAX))
- return -EINVAL;
-
- afinfo = xfrm_policy_lock_afinfo(family);
- if (unlikely(afinfo == NULL))
- return -EAFNOSUPPORT;
-
- err = -ENOENT;
- modemap = afinfo->mode_map;
- if (likely(modemap[mode->encap] == mode)) {
- modemap[mode->encap] = NULL;
- err = 0;
- }
-
- xfrm_policy_unlock_afinfo(afinfo);
- return err;
-}
-EXPORT_SYMBOL(xfrm_unregister_mode);
-
-struct xfrm_mode *xfrm_get_mode(unsigned int encap, int family)
-{
- struct xfrm_policy_afinfo *afinfo;
- struct xfrm_mode *mode;
- int modload_attempted = 0;
-
- if (unlikely(encap >= XFRM_MODE_MAX))
- return NULL;
-
-retry:
- afinfo = xfrm_policy_get_afinfo(family);
- if (unlikely(afinfo == NULL))
- return NULL;
-
- mode = afinfo->mode_map[encap];
- if (unlikely(mode && !try_module_get(mode->owner)))
- mode = NULL;
- if (!mode && !modload_attempted) {
- xfrm_policy_put_afinfo(afinfo);
- request_module("xfrm-mode-%d-%d", family, encap);
- modload_attempted = 1;
- goto retry;
- }
-
- xfrm_policy_put_afinfo(afinfo);
- return mode;
-}
-
-void xfrm_put_mode(struct xfrm_mode *mode)
-{
- module_put(mode->owner);
-}
-
static inline unsigned long make_jiffies(long secs)
{
if (secs >= (MAX_SCHEDULE_TIMEOUT-1)/HZ)
@@ -2096,7 +1940,8 @@ int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first,
if (xdst->genid != dst->xfrm->genid)
return 0;
- if (strict && fl && dst->xfrm->props.mode != XFRM_MODE_TUNNEL &&
+ if (strict && fl &&
+ !(dst->xfrm->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) &&
!xfrm_state_addr_flow_check(dst->xfrm, fl, family))
return 0;
@@ -2213,23 +2058,6 @@ static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo)
read_unlock(&xfrm_policy_afinfo_lock);
}
-static struct xfrm_policy_afinfo *xfrm_policy_lock_afinfo(unsigned int family)
-{
- struct xfrm_policy_afinfo *afinfo;
- if (unlikely(family >= NPROTO))
- return NULL;
- write_lock_bh(&xfrm_policy_afinfo_lock);
- afinfo = xfrm_policy_afinfo[family];
- if (unlikely(!afinfo))
- write_unlock_bh(&xfrm_policy_afinfo_lock);
- return afinfo;
-}
-
-static void xfrm_policy_unlock_afinfo(struct xfrm_policy_afinfo *afinfo)
-{
- write_unlock_bh(&xfrm_policy_afinfo_lock);
-}
-
static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
{
struct net_device *dev = ptr;
@@ -2464,7 +2292,8 @@ static int xfrm_policy_migrate(struct xfrm_policy *pol,
if (!migrate_tmpl_match(mp, &pol->xfrm_vec[i]))
continue;
n++;
- if (pol->xfrm_vec[i].mode != XFRM_MODE_TUNNEL)
+ if (pol->xfrm_vec[i].mode != XFRM_MODE_TUNNEL &&
+ pol->xfrm_vec[i].mode != XFRM_MODE_BEET)
continue;
/* update endpoints */
memcpy(&pol->xfrm_vec[i].id.daddr, &mp->new_daddr,
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 344f0a6abec5..224b44e31a07 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -57,6 +57,9 @@ static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024;
static unsigned int xfrm_state_num;
static unsigned int xfrm_state_genid;
+static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family);
+static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
+
static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr,
xfrm_address_t *saddr,
u32 reqid,
@@ -187,6 +190,184 @@ int __xfrm_state_delete(struct xfrm_state *x);
int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol);
void km_state_expired(struct xfrm_state *x, int hard, u32 pid);
+static struct xfrm_state_afinfo *xfrm_state_lock_afinfo(unsigned int family)
+{
+ struct xfrm_state_afinfo *afinfo;
+ if (unlikely(family >= NPROTO))
+ return NULL;
+ write_lock_bh(&xfrm_state_afinfo_lock);
+ afinfo = xfrm_state_afinfo[family];
+ if (unlikely(!afinfo))
+ write_unlock_bh(&xfrm_state_afinfo_lock);
+ return afinfo;
+}
+
+static void xfrm_state_unlock_afinfo(struct xfrm_state_afinfo *afinfo)
+{
+ write_unlock_bh(&xfrm_state_afinfo_lock);
+}
+
+int xfrm_register_type(struct xfrm_type *type, unsigned short family)
+{
+ struct xfrm_state_afinfo *afinfo = xfrm_state_lock_afinfo(family);
+ struct xfrm_type **typemap;
+ int err = 0;
+
+ if (unlikely(afinfo == NULL))
+ return -EAFNOSUPPORT;
+ typemap = afinfo->type_map;
+
+ if (likely(typemap[type->proto] == NULL))
+ typemap[type->proto] = type;
+ else
+ err = -EEXIST;
+ xfrm_state_unlock_afinfo(afinfo);
+ return err;
+}
+EXPORT_SYMBOL(xfrm_register_type);
+
+int xfrm_unregister_type(struct xfrm_type *type, unsigned short family)
+{
+ struct xfrm_state_afinfo *afinfo = xfrm_state_lock_afinfo(family);
+ struct xfrm_type **typemap;
+ int err = 0;
+
+ if (unlikely(afinfo == NULL))
+ return -EAFNOSUPPORT;
+ typemap = afinfo->type_map;
+
+ if (unlikely(typemap[type->proto] != type))
+ err = -ENOENT;
+ else
+ typemap[type->proto] = NULL;
+ xfrm_state_unlock_afinfo(afinfo);
+ return err;
+}
+EXPORT_SYMBOL(xfrm_unregister_type);
+
+static struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family)
+{
+ struct xfrm_state_afinfo *afinfo;
+ struct xfrm_type **typemap;
+ struct xfrm_type *type;
+ int modload_attempted = 0;
+
+retry:
+ afinfo = xfrm_state_get_afinfo(family);
+ if (unlikely(afinfo == NULL))
+ return NULL;
+ typemap = afinfo->type_map;
+
+ type = typemap[proto];
+ if (unlikely(type && !try_module_get(type->owner)))
+ type = NULL;
+ if (!type && !modload_attempted) {
+ xfrm_state_put_afinfo(afinfo);
+ request_module("xfrm-type-%d-%d", family, proto);
+ modload_attempted = 1;
+ goto retry;
+ }
+
+ xfrm_state_put_afinfo(afinfo);
+ return type;
+}
+
+static void xfrm_put_type(struct xfrm_type *type)
+{
+ module_put(type->owner);
+}
+
+int xfrm_register_mode(struct xfrm_mode *mode, int family)
+{
+ struct xfrm_state_afinfo *afinfo;
+ struct xfrm_mode **modemap;
+ int err;
+
+ if (unlikely(mode->encap >= XFRM_MODE_MAX))
+ return -EINVAL;
+
+ afinfo = xfrm_state_lock_afinfo(family);
+ if (unlikely(afinfo == NULL))
+ return -EAFNOSUPPORT;
+
+ err = -EEXIST;
+ modemap = afinfo->mode_map;
+ if (modemap[mode->encap])
+ goto out;
+
+ err = -ENOENT;
+ if (!try_module_get(afinfo->owner))
+ goto out;
+
+ mode->afinfo = afinfo;
+ modemap[mode->encap] = mode;
+ err = 0;
+
+out:
+ xfrm_state_unlock_afinfo(afinfo);
+ return err;
+}
+EXPORT_SYMBOL(xfrm_register_mode);
+
+int xfrm_unregister_mode(struct xfrm_mode *mode, int family)
+{
+ struct xfrm_state_afinfo *afinfo;
+ struct xfrm_mode **modemap;
+ int err;
+
+ if (unlikely(mode->encap >= XFRM_MODE_MAX))
+ return -EINVAL;
+
+ afinfo = xfrm_state_lock_afinfo(family);
+ if (unlikely(afinfo == NULL))
+ return -EAFNOSUPPORT;
+
+ err = -ENOENT;
+ modemap = afinfo->mode_map;
+ if (likely(modemap[mode->encap] == mode)) {
+ modemap[mode->encap] = NULL;
+ module_put(mode->afinfo->owner);
+ err = 0;
+ }
+
+ xfrm_state_unlock_afinfo(afinfo);
+ return err;
+}
+EXPORT_SYMBOL(xfrm_unregister_mode);
+
+static struct xfrm_mode *xfrm_get_mode(unsigned int encap, int family)
+{
+ struct xfrm_state_afinfo *afinfo;
+ struct xfrm_mode *mode;
+ int modload_attempted = 0;
+
+ if (unlikely(encap >= XFRM_MODE_MAX))
+ return NULL;
+
+retry:
+ afinfo = xfrm_state_get_afinfo(family);
+ if (unlikely(afinfo == NULL))
+ return NULL;
+
+ mode = afinfo->mode_map[encap];
+ if (unlikely(mode && !try_module_get(mode->owner)))
+ mode = NULL;
+ if (!mode && !modload_attempted) {
+ xfrm_state_put_afinfo(afinfo);
+ request_module("xfrm-mode-%d-%d", family, encap);
+ modload_attempted = 1;
+ goto retry;
+ }
+
+ xfrm_state_put_afinfo(afinfo);
+ return mode;
+}
+
+static void xfrm_put_mode(struct xfrm_mode *mode)
+{
+ module_put(mode->owner);
+}
+
static void xfrm_state_gc_destroy(struct xfrm_state *x)
{
del_timer_sync(&x->timer);
@@ -196,8 +377,10 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x)
kfree(x->calg);
kfree(x->encap);
kfree(x->coaddr);
- if (x->mode)
- xfrm_put_mode(x->mode);
+ if (x->inner_mode)
+ xfrm_put_mode(x->inner_mode);
+ if (x->outer_mode)
+ xfrm_put_mode(x->outer_mode);
if (x->type) {
x->type->destructor(x);
xfrm_put_type(x->type);
@@ -1699,7 +1882,7 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo)
}
EXPORT_SYMBOL(xfrm_state_unregister_afinfo);
-struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family)
+static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family)
{
struct xfrm_state_afinfo *afinfo;
if (unlikely(family >= NPROTO))
@@ -1711,14 +1894,11 @@ struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family)
return afinfo;
}
-void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo)
+static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo)
{
read_unlock(&xfrm_state_afinfo_lock);
}
-EXPORT_SYMBOL(xfrm_state_get_afinfo);
-EXPORT_SYMBOL(xfrm_state_put_afinfo);
-
/* Temporarily located here until net/xfrm/xfrm_tunnel.c is created */
void xfrm_state_delete_tunnel(struct xfrm_state *x)
{
@@ -1769,6 +1949,14 @@ int xfrm_init_state(struct xfrm_state *x)
goto error;
err = -EPROTONOSUPPORT;
+ x->inner_mode = xfrm_get_mode(x->props.mode, x->sel.family);
+ if (x->inner_mode == NULL)
+ goto error;
+
+ if (!(x->inner_mode->flags & XFRM_MODE_FLAG_TUNNEL) &&
+ family != x->sel.family)
+ goto error;
+
x->type = xfrm_get_type(x->id.proto, family);
if (x->type == NULL)
goto error;
@@ -1777,8 +1965,8 @@ int xfrm_init_state(struct xfrm_state *x)
if (err)
goto error;
- x->mode = xfrm_get_mode(x->props.mode, family);
- if (x->mode == NULL)
+ x->outer_mode = xfrm_get_mode(x->props.mode, family);
+ if (x->outer_mode == NULL)
goto error;
x->km.state = XFRM_STATE_VALID;
diff --git a/samples/Kconfig b/samples/Kconfig
new file mode 100644
index 000000000000..57bb2236952c
--- /dev/null
+++ b/samples/Kconfig
@@ -0,0 +1,16 @@
+# samples/Kconfig
+
+menuconfig SAMPLES
+ bool "Sample kernel code"
+ help
+ You can build and test sample kernel code here.
+
+if SAMPLES
+
+config SAMPLE_MARKERS
+ tristate "Build markers examples -- loadable modules only"
+ depends on MARKERS && m
+ help
+ This build markers example modules.
+
+endif # SAMPLES
diff --git a/samples/Makefile b/samples/Makefile
new file mode 100644
index 000000000000..5a4f0b6bcbed
--- /dev/null
+++ b/samples/Makefile
@@ -0,0 +1,3 @@
+# Makefile for Linux samples code
+
+obj-$(CONFIG_SAMPLES) += markers/
diff --git a/samples/markers/Makefile b/samples/markers/Makefile
new file mode 100644
index 000000000000..6d7231265f0f
--- /dev/null
+++ b/samples/markers/Makefile
@@ -0,0 +1,4 @@
+# builds the kprobes example kernel modules;
+# then to use one (as root): insmod <module_name.ko>
+
+obj-$(CONFIG_SAMPLE_MARKERS) += probe-example.o marker-example.o
diff --git a/samples/markers/marker-example.c b/samples/markers/marker-example.c
new file mode 100644
index 000000000000..05e438f8b4e2
--- /dev/null
+++ b/samples/markers/marker-example.c
@@ -0,0 +1,55 @@
+/* marker-example.c
+ *
+ * Executes a marker when /proc/marker-example is opened.
+ *
+ * (C) Copyright 2007 Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
+ *
+ * This file is released under the GPLv2.
+ * See the file COPYING for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/marker.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+
+struct proc_dir_entry *pentry_example;
+
+static int my_open(struct inode *inode, struct file *file)
+{
+ int i;
+
+ trace_mark(subsystem_event, "integer %d string %s", 123,
+ "example string");
+ for (i = 0; i < 10; i++)
+ trace_mark(subsystem_eventb, MARK_NOARGS);
+ return -EPERM;
+}
+
+static struct file_operations mark_ops = {
+ .open = my_open,
+};
+
+static int example_init(void)
+{
+ printk(KERN_ALERT "example init\n");
+ pentry_example = create_proc_entry("marker-example", 0444, NULL);
+ if (pentry_example)
+ pentry_example->proc_fops = &mark_ops;
+ else
+ return -EPERM;
+ return 0;
+}
+
+static void example_exit(void)
+{
+ printk(KERN_ALERT "example exit\n");
+ remove_proc_entry("marker-example", NULL);
+}
+
+module_init(example_init)
+module_exit(example_exit)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mathieu Desnoyers");
+MODULE_DESCRIPTION("Marker example");
diff --git a/samples/markers/probe-example.c b/samples/markers/probe-example.c
new file mode 100644
index 000000000000..a36797535615
--- /dev/null
+++ b/samples/markers/probe-example.c
@@ -0,0 +1,98 @@
+/* probe-example.c
+ *
+ * Connects two functions to marker call sites.
+ *
+ * (C) Copyright 2007 Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
+ *
+ * This file is released under the GPLv2.
+ * See the file COPYING for more details.
+ */
+
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/marker.h>
+#include <asm/atomic.h>
+
+struct probe_data {
+ const char *name;
+ const char *format;
+ marker_probe_func *probe_func;
+};
+
+void probe_subsystem_event(const struct marker *mdata, void *private,
+ const char *format, ...)
+{
+ va_list ap;
+ /* Declare args */
+ unsigned int value;
+ const char *mystr;
+
+ /* Assign args */
+ va_start(ap, format);
+ value = va_arg(ap, typeof(value));
+ mystr = va_arg(ap, typeof(mystr));
+
+ /* Call printk */
+ printk(KERN_DEBUG "Value %u, string %s\n", value, mystr);
+
+ /* or count, check rights, serialize data in a buffer */
+
+ va_end(ap);
+}
+
+atomic_t eventb_count = ATOMIC_INIT(0);
+
+void probe_subsystem_eventb(const struct marker *mdata, void *private,
+ const char *format, ...)
+{
+ /* Increment counter */
+ atomic_inc(&eventb_count);
+}
+
+static struct probe_data probe_array[] =
+{
+ { .name = "subsystem_event",
+ .format = "integer %d string %s",
+ .probe_func = probe_subsystem_event },
+ { .name = "subsystem_eventb",
+ .format = MARK_NOARGS,
+ .probe_func = probe_subsystem_eventb },
+};
+
+static int __init probe_init(void)
+{
+ int result;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(probe_array); i++) {
+ result = marker_probe_register(probe_array[i].name,
+ probe_array[i].format,
+ probe_array[i].probe_func, &probe_array[i]);
+ if (result)
+ printk(KERN_INFO "Unable to register probe %s\n",
+ probe_array[i].name);
+ result = marker_arm(probe_array[i].name);
+ if (result)
+ printk(KERN_INFO "Unable to arm probe %s\n",
+ probe_array[i].name);
+ }
+ return 0;
+}
+
+static void __exit probe_fini(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(probe_array); i++)
+ marker_probe_unregister(probe_array[i].name);
+ printk(KERN_INFO "Number of event b : %u\n",
+ atomic_read(&eventb_count));
+}
+
+module_init(probe_init);
+module_exit(probe_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mathieu Desnoyers");
+MODULE_DESCRIPTION("SUBSYSTEM Probe");
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index 677bc6c175cb..b96ea8d6a5ed 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -56,6 +56,17 @@ endef
# gcc support functions
# See documentation in Documentation/kbuild/makefiles.txt
+# cc-cross-prefix
+# Usage: CROSS_COMPILE := $(call cc-cross-prefix, m68k-linux-gnu- m68k-linux-)
+# Return first prefix where a prefix$(CC) is found in PATH.
+# If no $(CC) found in PATH with listed prefixes return nothing
+cc-cross-prefix = \
+ $(word 1, $(foreach c,$(1), \
+ $(shell set -e; \
+ if (which $(strip $(c))$(CC)) > /dev/null 2>&1 ; then \
+ echo $(c); \
+ fi)))
+
# output directory for tests below
TMPOUT := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/)
@@ -75,24 +86,24 @@ try-run = $(shell set -e; \
# Usage: cflags-y += $(call as-option,-Wa$(comma)-isa=foo,)
as-option = $(call try-run,\
- $(CC) $(CFLAGS) $(1) -c -xassembler /dev/null -o "$$TMP",$(1),$(2))
+ $(CC) $(KBUILD_CFLAGS) $(1) -c -xassembler /dev/null -o "$$TMP",$(1),$(2))
# as-instr
# Usage: cflags-y += $(call as-instr,instr,option1,option2)
as-instr = $(call try-run,\
- echo -e "$(1)" | $(CC) $(AFLAGS) -c -xassembler -o "$$TMP" -,$(2),$(3))
+ echo -e "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -xassembler -o "$$TMP" -,$(2),$(3))
# cc-option
# Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586)
cc-option = $(call try-run,\
- $(CC) $(CFLAGS) $(1) -S -xc /dev/null -o "$$TMP",$(1),$(2))
+ $(CC) $(KBUILD_CFLAGS) $(1) -S -xc /dev/null -o "$$TMP",$(1),$(2))
# cc-option-yn
# Usage: flag := $(call cc-option-yn,-march=winchip-c6)
cc-option-yn = $(call try-run,\
- $(CC) $(CFLAGS) $(1) -S -xc /dev/null -o "$$TMP",y,n)
+ $(CC) $(KBUILD_CFLAGS) $(1) -S -xc /dev/null -o "$$TMP",y,n)
# cc-option-align
# Prefix align with either -falign or -malign
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 7fd6055bedfd..de9836eee8bb 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -22,16 +22,30 @@ EXTRA_AFLAGS :=
EXTRA_CFLAGS :=
EXTRA_CPPFLAGS :=
EXTRA_LDFLAGS :=
+asflags-y :=
+ccflags-y :=
+cppflags-y :=
+ldflags-y :=
# Read .config if it exist, otherwise ignore
-include include/config/auto.conf
include scripts/Kbuild.include
+# For backward compatibility check that these variables does not change
+save-cflags := $(CFLAGS)
+
# The filename Kbuild has precedence over Makefile
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
-include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile)
-
+kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
+include $(kbuild-file)
+
+# If the save-* variables changed error out
+ifeq ($(KBUILD_NOPEDANTIC),)
+ ifneq ("$(save-cflags)","$(CFLAGS)")
+ $(error CFLAGS was changed in "$(kbuild-file)". Fix it to use EXTRA_CFLAGS)
+ endif
+endif
include scripts/Makefile.lib
ifdef host-progs
@@ -55,31 +69,6 @@ _dummy := $(shell [ -d $(obj) ] || mkdir -p $(obj))
_dummy := $(foreach d,$(obj-dirs), $(shell [ -d $(d) ] || mkdir -p $(d)))
endif
-
-ifdef EXTRA_TARGETS
-$(warning kbuild: $(obj)/Makefile - Usage of EXTRA_TARGETS is obsolete in 2.6. Please fix!)
-endif
-
-ifdef build-targets
-$(warning kbuild: $(obj)/Makefile - Usage of build-targets is obsolete in 2.6. Please fix!)
-endif
-
-ifdef export-objs
-$(warning kbuild: $(obj)/Makefile - Usage of export-objs is obsolete in 2.6. Please fix!)
-endif
-
-ifdef O_TARGET
-$(warning kbuild: $(obj)/Makefile - Usage of O_TARGET := $(O_TARGET) is obsolete in 2.6. Please fix!)
-endif
-
-ifdef L_TARGET
-$(error kbuild: $(obj)/Makefile - Use of L_TARGET is replaced by lib-y in 2.6. Please fix!)
-endif
-
-ifdef list-multi
-$(warning kbuild: $(obj)/Makefile - list-multi := $(list-multi) is obsolete in 2.6. Please fix!)
-endif
-
ifndef obj
$(warning kbuild: Makefile.build is included improperly)
endif
@@ -291,7 +280,7 @@ endif # builtin-target
#
ifdef lib-target
quiet_cmd_link_l_target = AR $@
-cmd_link_l_target = rm -f $@; $(AR) $(EXTRA_ARFLAGS) rcs $@ $(lib-y)
+cmd_link_l_target = rm -f $@; $(AR) rcs $@ $(lib-y)
$(lib-target): $(lib-y) FORCE
$(call if_changed,link_l_target)
diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean
index cff33498fa16..2c647107c9cc 100644
--- a/scripts/Makefile.clean
+++ b/scripts/Makefile.clean
@@ -40,7 +40,7 @@ subdir-ymn := $(addprefix $(obj)/,$(subdir-ymn))
# build a list of files to remove, usually releative to the current
# directory
-__clean-files := $(extra-y) $(EXTRA_TARGETS) $(always) \
+__clean-files := $(extra-y) $(always) \
$(targets) $(clean-files) \
$(host-progs) \
$(hostprogs-y) $(hostprogs-m) $(hostprogs-)
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index fc498fee68ed..3c5e88bfecf1 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -1,5 +1,9 @@
-# Backward compatibility - to be removed...
-extra-y += $(EXTRA_TARGETS)
+# Backward compatibility
+asflags-y += $(EXTRA_AFLAGS)
+ccflags-y += $(EXTRA_CFLAGS)
+cppflags-y += $(EXTRA_CPPFLAGS)
+ldflags-y += $(EXTRA_LDFLAGS)
+
# Figure out what we need to build from the various variables
# ===========================================================================
@@ -44,9 +48,9 @@ multi-objs-y := $(foreach m, $(multi-used-y), $($(m:.o=-objs)) $($(m:.o=-y)))
multi-objs-m := $(foreach m, $(multi-used-m), $($(m:.o=-objs)) $($(m:.o=-y)))
multi-objs := $(multi-objs-y) $(multi-objs-m)
-# $(subdir-obj-y) is the list of objects in $(obj-y) which do not live
-# in the local directory
-subdir-obj-y := $(foreach o,$(obj-y),$(if $(filter-out $(o),$(notdir $(o))),$(o)))
+# $(subdir-obj-y) is the list of objects in $(obj-y) which uses dir/ to
+# tell kbuild to descend
+subdir-obj-y := $(filter %/built-in.o, $(obj-y))
# $(obj-dirs) is a list of directories that contain object files
obj-dirs := $(dir $(multi-objs) $(subdir-obj-y))
@@ -86,9 +90,9 @@ basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))"
modname_flags = $(if $(filter 1,$(words $(modname))),\
-D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))")
-_c_flags = $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$(basetarget).o)
-_a_flags = $(AFLAGS) $(EXTRA_AFLAGS) $(AFLAGS_$(basetarget).o)
-_cpp_flags = $(CPPFLAGS) $(EXTRA_CPPFLAGS) $(CPPFLAGS_$(@F))
+_c_flags = $(KBUILD_CFLAGS) $(ccflags-y) $(CFLAGS_$(basetarget).o)
+_a_flags = $(KBUILD_AFLAGS) $(asflags-y) $(AFLAGS_$(basetarget).o)
+_cpp_flags = $(KBUILD_CPPFLAGS) $(cppflags-y) $(CPPFLAGS_$(@F))
# If building the kernel in a separate objtree expand all occurrences
# of -Idir to -I$(srctree)/dir except for absolute paths (starting with '/').
@@ -108,16 +112,16 @@ __a_flags = $(call flags,_a_flags)
__cpp_flags = $(call flags,_cpp_flags)
endif
-c_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(CPPFLAGS) \
+c_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(KBUILD_CPPFLAGS) \
$(__c_flags) $(modkern_cflags) \
-D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags)
-a_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(CPPFLAGS) \
+a_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(KBUILD_CPPFLAGS) \
$(__a_flags) $(modkern_aflags)
cpp_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(__cpp_flags)
-ld_flags = $(LDFLAGS) $(EXTRA_LDFLAGS)
+ld_flags = $(LDFLAGS) $(ldflags-y)
# Finds the multi-part object the current object will be linked into
modname-multi = $(sort $(foreach m,$(multi-used),\
@@ -140,14 +144,14 @@ $(obj)/%:: $(src)/%_shipped
# target: source(s) FORCE
# $(if_changed,ld/objcopy/gzip)
#
-# and add target to EXTRA_TARGETS so that we know we have to
+# and add target to extra-y so that we know we have to
# read in the saved command line
# Linking
# ---------------------------------------------------------------------------
quiet_cmd_ld = LD $@
-cmd_ld = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_$(@F)) \
+cmd_ld = $(LD) $(LDFLAGS) $(ldflags-y) $(LDFLAGS_$(@F)) \
$(filter-out FORCE,$^) -o $@
# Objcopy
diff --git a/scripts/basic/Makefile b/scripts/basic/Makefile
index 2f60070f9733..4c324a1f1e0e 100644
--- a/scripts/basic/Makefile
+++ b/scripts/basic/Makefile
@@ -1,13 +1,13 @@
###
-# Makefile.basic list the most basic programs used during the build process.
-# The programs listed herein is what is needed to do the basic stuff,
-# such as fix dependency file.
+# Makefile.basic lists the most basic programs used during the build process.
+# The programs listed herein are what are needed to do the basic stuff,
+# such as fix file dependencies.
# This initial step is needed to avoid files to be recompiled
# when kernel configuration changes (which is what happens when
# .config is included by main Makefile.
# ---------------------------------------------------------------------------
# fixdep: Used to generate dependency information during build process
-# docproc: Used in Documentation/docbook
+# docproc: Used in Documentation/DocBook
hostprogs-y := fixdep docproc
always := $(hostprogs-y)
diff --git a/scripts/basic/docproc.c b/scripts/basic/docproc.c
index f4d2f68452ba..0e4bd5459df4 100644
--- a/scripts/basic/docproc.c
+++ b/scripts/basic/docproc.c
@@ -10,8 +10,10 @@
* documentation-frontend
* Scans the template file and call kernel-doc for
* all occurrences of ![EIF]file
- * Beforehand each referenced file are scanned for
- * any exported sympols "EXPORT_SYMBOL()" statements.
+ * Beforehand each referenced file is scanned for
+ * any symbols that are exported via these macros:
+ * EXPORT_SYMBOL(), EXPORT_SYMBOL_GPL(), &
+ * EXPORT_SYMBOL_GPL_FUTURE()
* This is used to create proper -function and
* -nofunction arguments in calls to kernel-doc.
* Usage: docproc doc file.tmpl
@@ -64,16 +66,19 @@ FILELINE * entity_system;
#define FUNCTION "-function"
#define NOFUNCTION "-nofunction"
+char *srctree;
+
void usage (void)
{
fprintf(stderr, "Usage: docproc {doc|depend} file\n");
fprintf(stderr, "Input is read from file.tmpl. Output is sent to stdout\n");
fprintf(stderr, "doc: frontend when generating kernel documentation\n");
fprintf(stderr, "depend: generate list of files referenced within file\n");
+ fprintf(stderr, "Environment variable SRCTREE: absolute path to kernel source tree.\n");
}
/*
- * Execute kernel-doc with parameters givin in svec
+ * Execute kernel-doc with parameters given in svec
*/
void exec_kernel_doc(char **svec)
{
@@ -82,13 +87,13 @@ void exec_kernel_doc(char **svec)
char real_filename[PATH_MAX + 1];
/* Make sure output generated so far are flushed */
fflush(stdout);
- switch(pid=fork()) {
+ switch (pid=fork()) {
case -1:
perror("fork");
exit(1);
case 0:
memset(real_filename, 0, sizeof(real_filename));
- strncat(real_filename, getenv("SRCTREE"), PATH_MAX);
+ strncat(real_filename, srctree, PATH_MAX);
strncat(real_filename, KERNELDOCPATH KERNELDOC,
PATH_MAX - strlen(real_filename));
execvp(real_filename, svec);
@@ -133,6 +138,7 @@ struct symfile * add_new_file(char * filename)
symfilelist[symfilecnt++].filename = strdup(filename);
return &symfilelist[symfilecnt - 1];
}
+
/* Check if file already are present in the list */
struct symfile * filename_exist(char * filename)
{
@@ -156,8 +162,8 @@ void noaction2(char * file, char * line) { file = file; line = line; }
void printline(char * line) { printf("%s", line); }
/*
- * Find all symbols exported with EXPORT_SYMBOL and EXPORT_SYMBOL_GPL
- * in filename.
+ * Find all symbols in filename that are exported with EXPORT_SYMBOL &
+ * EXPORT_SYMBOL_GPL (& EXPORT_SYMBOL_GPL_FUTURE implicitly).
* All symbols located are stored in symfilelist.
*/
void find_export_symbols(char * filename)
@@ -168,7 +174,7 @@ void find_export_symbols(char * filename)
if (filename_exist(filename) == NULL) {
char real_filename[PATH_MAX + 1];
memset(real_filename, 0, sizeof(real_filename));
- strncat(real_filename, getenv("SRCTREE"), PATH_MAX);
+ strncat(real_filename, srctree, PATH_MAX);
strncat(real_filename, filename,
PATH_MAX - strlen(real_filename));
sym = add_new_file(filename);
@@ -179,15 +185,15 @@ void find_export_symbols(char * filename)
perror(real_filename);
exit(1);
}
- while(fgets(line, MAXLINESZ, fp)) {
+ while (fgets(line, MAXLINESZ, fp)) {
char *p;
char *e;
- if (((p = strstr(line, "EXPORT_SYMBOL_GPL")) != 0) ||
- ((p = strstr(line, "EXPORT_SYMBOL")) != 0)) {
+ if (((p = strstr(line, "EXPORT_SYMBOL_GPL")) != NULL) ||
+ ((p = strstr(line, "EXPORT_SYMBOL")) != NULL)) {
/* Skip EXPORT_SYMBOL{_GPL} */
while (isalnum(*p) || *p == '_')
p++;
- /* Remove paranteses and additional ws */
+ /* Remove parentheses & additional whitespace */
while (isspace(*p))
p++;
if (*p != '(')
@@ -211,7 +217,7 @@ void find_export_symbols(char * filename)
* Document all external or internal functions in a file.
* Call kernel-doc with following parameters:
* kernel-doc -docbook -nofunction function_name1 filename
- * function names are obtained from all the src files
+ * Function names are obtained from all the src files
* by find_export_symbols.
* intfunc uses -nofunction
* extfunc uses -function
@@ -262,7 +268,7 @@ void singfunc(char * filename, char * line)
vec[idx++] = KERNELDOC;
vec[idx++] = DOCBOOK;
- /* Split line up in individual parameters preceeded by FUNCTION */
+ /* Split line up in individual parameters preceded by FUNCTION */
for (i=0; line[i]; i++) {
if (isspace(line[i])) {
line[i] = '\0';
@@ -292,7 +298,7 @@ void parse_file(FILE *infile)
{
char line[MAXLINESZ];
char * s;
- while(fgets(line, MAXLINESZ, infile)) {
+ while (fgets(line, MAXLINESZ, infile)) {
if (line[0] == '!') {
s = line + 2;
switch (line[1]) {
@@ -335,6 +341,10 @@ void parse_file(FILE *infile)
int main(int argc, char *argv[])
{
FILE * infile;
+
+ srctree = getenv("SRCTREE");
+ if (!srctree)
+ srctree = getcwd(NULL, 0);
if (argc != 3) {
usage();
exit(1);
@@ -351,9 +361,9 @@ int main(int argc, char *argv[])
{
/* Need to do this in two passes.
* First pass is used to collect all symbols exported
- * in the various files.
+ * in the various files;
* Second pass generate the documentation.
- * This is required because function are declared
+ * This is required because some functions are declared
* and exported in different files :-((
*/
/* Collect symbols */
@@ -396,4 +406,3 @@ int main(int argc, char *argv[])
fflush(stdout);
return exitstatus;
}
-
diff --git a/scripts/checkkconfigsymbols.sh b/scripts/checkkconfigsymbols.sh
new file mode 100755
index 000000000000..39677c82747a
--- /dev/null
+++ b/scripts/checkkconfigsymbols.sh
@@ -0,0 +1,59 @@
+#!/bin/sh
+# Find Kconfig variables used in source code but never defined in Kconfig
+# Copyright (C) 2007, Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
+
+# Tested with dash.
+paths="$@"
+[ -z "$paths" ] && paths=.
+
+# Doing this once at the beginning saves a lot of time, on a cache-hot tree.
+Kconfigs="`find . -name 'Kconfig' -o -name 'Kconfig*[^~]'`"
+
+echo -e "File list \tundefined symbol used"
+find $paths -name '*.[chS]' -o -name 'Makefile' -o -name 'Makefile*[^~]'| while read i
+do
+ # Output the bare Kconfig variable and the filename; the _MODULE part at
+ # the end is not removed here (would need perl an not-hungry regexp for that).
+ sed -ne 's!^.*\<\(UML_\)\?CONFIG_\([0-9A-Z_]\+\).*!\2 '$i'!p' < $i
+done | \
+# Smart "sort|uniq" implemented in awk and tuned to collect the names of all
+# files which use a given symbol
+awk '{map[$1, count[$1]++] = $2; }
+END {
+ for (combIdx in map) {
+ split(combIdx, separate, SUBSEP);
+ # The value may have been removed.
+ if (! ( (separate[1], separate[2]) in map ) )
+ continue;
+ symb=separate[1];
+ printf "%s ", symb;
+ #Use gawk extension to delete the names vector
+ delete names;
+ #Portably delete the names vector
+ #split("", names);
+ for (i=0; i < count[symb]; i++) {
+ names[map[symb, i]] = 1;
+ # Unfortunately, we may still encounter symb, i in the
+ # outside iteration.
+ delete map[symb, i];
+ }
+ i=0;
+ for (name in names) {
+ if (i > 0)
+ printf ", %s", name;
+ else
+ printf "%s", name;
+ i++;
+ }
+ printf "\n";
+ }
+}' |
+while read symb files; do
+ # Remove the _MODULE suffix when checking the variable name. This should
+ # be done only on tristate symbols, actually, but Kconfig parsing is
+ # beyond the purpose of this script.
+ symb_bare=`echo $symb | sed -e 's/_MODULE//'`
+ if ! grep -q "\<$symb_bare\>" $Kconfigs; then
+ echo -e "$files: \t$symb"
+ fi
+done|sort
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index dae7d30dca0f..cbb42580a81d 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -9,7 +9,7 @@ use strict;
my $P = $0;
$P =~ s@.*/@@g;
-my $V = '0.09';
+my $V = '0.11';
use Getopt::Long qw(:config no_auto_abbrev);
@@ -18,12 +18,21 @@ my $tree = 1;
my $chk_signoff = 1;
my $chk_patch = 1;
my $tst_type = 0;
+my $emacs = 0;
+my $file = 0;
+my $check = 0;
+my $root;
GetOptions(
- 'q|quiet' => \$quiet,
+ 'q|quiet+' => \$quiet,
'tree!' => \$tree,
'signoff!' => \$chk_signoff,
'patch!' => \$chk_patch,
'test-type!' => \$tst_type,
+ 'emacs!' => \$emacs,
+ 'file!' => \$file,
+ 'subjective!' => \$check,
+ 'strict!' => \$check,
+ 'root=s' => \$root,
) or exit;
my $exit = 0;
@@ -33,19 +42,110 @@ if ($#ARGV < 0) {
print "version: $V\n";
print "options: -q => quiet\n";
print " --no-tree => run without a kernel tree\n";
+ print " --emacs => emacs compile window format\n";
+ print " --file => check a source file\n";
+ print " --strict => enable more subjective tests\n";
+ print " --root => path to the kernel tree root\n";
exit(1);
}
-if ($tree && !top_of_kernel_tree()) {
- print "Must be run from the top-level dir. of a kernel tree\n";
- exit(2);
+if ($tree) {
+ if (defined $root) {
+ if (!top_of_kernel_tree($root)) {
+ die "$P: $root: --root does not point at a valid tree\n";
+ }
+ } else {
+ if (top_of_kernel_tree('.')) {
+ $root = '.';
+ } elsif ($0 =~ m@(.*)/scripts/[^/]*$@ &&
+ top_of_kernel_tree($1)) {
+ $root = $1;
+ }
+ }
+
+ if (!defined $root) {
+ print "Must be run from the top-level dir. of a kernel tree\n";
+ exit(2);
+ }
}
+my $emitted_corrupt = 0;
+
+our $Ident = qr{[A-Za-z_][A-Za-z\d_]*};
+our $Storage = qr{extern|static|asmlinkage};
+our $Sparse = qr{
+ __user|
+ __kernel|
+ __force|
+ __iomem|
+ __must_check|
+ __init_refok|
+ __kprobes|
+ fastcall
+ }x;
+our $Attribute = qr{
+ const|
+ __read_mostly|
+ __kprobes|
+ __(?:mem|cpu|dev|)(?:initdata|init)
+ }x;
+our $Inline = qr{inline|__always_inline|noinline};
+our $NonptrType = qr{
+ \b
+ (?:const\s+)?
+ (?:unsigned\s+)?
+ (?:
+ void|
+ char|
+ short|
+ int|
+ long|
+ unsigned|
+ float|
+ double|
+ bool|
+ long\s+int|
+ long\s+long|
+ long\s+long\s+int|
+ (?:__)?(?:u|s|be|le)(?:8|16|32|64)|
+ struct\s+$Ident|
+ union\s+$Ident|
+ enum\s+$Ident|
+ ${Ident}_t|
+ ${Ident}_handler|
+ ${Ident}_handler_fn
+ )
+ (?:\s+$Sparse)*
+ \b
+ }x;
+
+our $Type = qr{
+ \b$NonptrType\b
+ (?:\s*\*+\s*const|\s*\*+|(?:\s*\[\s*\])+)?
+ (?:\s+$Sparse|\s+$Attribute)*
+ }x;
+our $Declare = qr{(?:$Storage\s+)?$Type};
+our $Member = qr{->$Ident|\.$Ident|\[[^]]*\]};
+our $Lval = qr{$Ident(?:$Member)*};
+
+our $Constant = qr{(?:[0-9]+|0x[0-9a-fA-F]+)[UL]*};
+our $Assignment = qr{(?:\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=)};
+our $Operators = qr{
+ <=|>=|==|!=|
+ =>|->|<<|>>|<|>|!|~|
+ &&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/
+ }x;
+
+our $Bare = '';
+
+$chk_signoff = 0 if ($file);
+
my @dep_includes = ();
my @dep_functions = ();
-my $removal = 'Documentation/feature-removal-schedule.txt';
-if ($tree && -f $removal) {
- open(REMOVE, "<$removal") || die "$P: $removal: open failed - $!\n";
+my $removal = "Documentation/feature-removal-schedule.txt";
+if ($tree && -f "$root/$removal") {
+ open(REMOVE, "<$root/$removal") ||
+ die "$P: $removal: open failed - $!\n";
while (<REMOVE>) {
if (/^Check:\s+(.*\S)/) {
for my $entry (split(/[, ]+/, $1)) {
@@ -61,28 +161,42 @@ if ($tree && -f $removal) {
}
my @rawlines = ();
-while (<>) {
- chomp;
- push(@rawlines, $_);
- if (eof(ARGV)) {
- if (!process($ARGV, @rawlines)) {
- $exit = 1;
- }
- @rawlines = ();
+for my $filename (@ARGV) {
+ if ($file) {
+ open(FILE, "diff -u /dev/null $filename|") ||
+ die "$P: $filename: diff failed - $!\n";
+ } else {
+ open(FILE, "<$filename") ||
+ die "$P: $filename: open failed - $!\n";
}
+ while (<FILE>) {
+ chomp;
+ push(@rawlines, $_);
+ }
+ close(FILE);
+ if (!process($filename, @rawlines)) {
+ $exit = 1;
+ }
+ @rawlines = ();
}
exit($exit);
sub top_of_kernel_tree {
- if ((-f "COPYING") && (-f "CREDITS") && (-f "Kbuild") &&
- (-f "MAINTAINERS") && (-f "Makefile") && (-f "README") &&
- (-d "Documentation") && (-d "arch") && (-d "include") &&
- (-d "drivers") && (-d "fs") && (-d "init") && (-d "ipc") &&
- (-d "kernel") && (-d "lib") && (-d "scripts")) {
- return 1;
+ my ($root) = @_;
+
+ my @tree_check = (
+ "COPYING", "CREDITS", "Kbuild", "MAINTAINERS", "Makefile",
+ "README", "Documentation", "arch", "include", "drivers",
+ "fs", "init", "ipc", "kernel", "lib", "scripts",
+ );
+
+ foreach my $check (@tree_check) {
+ if (! -e $root . '/' . $check) {
+ return 0;
+ }
}
- return 0;
+ return 1;
}
sub expand_tabs {
@@ -105,6 +219,20 @@ sub expand_tabs {
return $res;
}
+sub copy_spacing {
+ my ($str) = @_;
+
+ my $res = '';
+ for my $c (split(//, $str)) {
+ if ($c eq "\t") {
+ $res .= $c;
+ } else {
+ $res .= ' ';
+ }
+ }
+
+ return $res;
+}
sub line_stats {
my ($line) = @_;
@@ -212,6 +340,11 @@ sub ctx_block_level {
return ctx_block_get($linenr, $remain, 0, '{', '}', 0);
}
+sub ctx_statement_level {
+ my ($linenr, $remain, $off) = @_;
+
+ return ctx_block_get($linenr, $remain, 0, '(', ')', $off);
+}
sub ctx_locate_comment {
my ($first_line, $end_line) = @_;
@@ -257,16 +390,136 @@ sub ctx_has_comment {
sub cat_vet {
my ($vet) = @_;
+ my ($res, $coded);
- $vet =~ s/\t/^I/;
- $vet =~ s/$/\$/;
+ $res = '';
+ while ($vet =~ /([^[:cntrl:]]*)([[:cntrl:]]|$)/g) {
+ $res .= $1;
+ if ($2 ne '') {
+ $coded = sprintf("^%c", unpack('C', $2) + 64);
+ $res .= $coded;
+ }
+ }
+ $res =~ s/$/\$/;
- return $vet;
+ return $res;
}
+sub annotate_values {
+ my ($stream, $type) = @_;
+
+ my $res;
+ my $cur = $stream;
+
+ my $debug = 0;
+
+ print "$stream\n" if ($debug);
+
+ ##my $type = 'N';
+ my $pos = 0;
+ my $preprocessor = 0;
+ my $paren = 0;
+ my @paren_type;
+
+ # Include any user defined types we may have found as we went.
+ my $type_match = "(?:$Type$Bare)";
+
+ while (length($cur)) {
+ print " <$type> " if ($debug);
+ if ($cur =~ /^(\s+)/o) {
+ print "WS($1)\n" if ($debug);
+ if ($1 =~ /\n/ && $preprocessor) {
+ $preprocessor = 0;
+ $type = 'N';
+ }
+
+ } elsif ($cur =~ /^($type_match)/) {
+ print "DECLARE($1)\n" if ($debug);
+ $type = 'T';
+
+ } elsif ($cur =~ /^(#\s*define\s*$Ident)(\(?)/o) {
+ print "DEFINE($1)\n" if ($debug);
+ $preprocessor = 1;
+ $paren_type[$paren] = 'N';
+
+ } elsif ($cur =~ /^(#\s*(?:ifdef|ifndef|if|else|endif))/o) {
+ print "PRE($1)\n" if ($debug);
+ $preprocessor = 1;
+ $type = 'N';
+
+ } elsif ($cur =~ /^(\\\n)/o) {
+ print "PRECONT($1)\n" if ($debug);
+
+ } elsif ($cur =~ /^(sizeof)\s*(\()?/o) {
+ print "SIZEOF($1)\n" if ($debug);
+ if (defined $2) {
+ $paren_type[$paren] = 'V';
+ }
+ $type = 'N';
+
+ } elsif ($cur =~ /^(if|while|typeof)\b/o) {
+ print "COND($1)\n" if ($debug);
+ $paren_type[$paren] = 'N';
+ $type = 'N';
+
+ } elsif ($cur =~/^(return|case|else)/o) {
+ print "KEYWORD($1)\n" if ($debug);
+ $type = 'N';
+
+ } elsif ($cur =~ /^(\()/o) {
+ print "PAREN('$1')\n" if ($debug);
+ $paren++;
+ $type = 'N';
+
+ } elsif ($cur =~ /^(\))/o) {
+ $paren-- if ($paren > 0);
+ if (defined $paren_type[$paren]) {
+ $type = $paren_type[$paren];
+ undef $paren_type[$paren];
+ print "PAREN('$1') -> $type\n" if ($debug);
+ } else {
+ print "PAREN('$1')\n" if ($debug);
+ }
+
+ } elsif ($cur =~ /^($Ident)\(/o) {
+ print "FUNC($1)\n" if ($debug);
+ $paren_type[$paren] = 'V';
+
+ } elsif ($cur =~ /^($Ident|$Constant)/o) {
+ print "IDENT($1)\n" if ($debug);
+ $type = 'V';
+
+ } elsif ($cur =~ /^($Assignment)/o) {
+ print "ASSIGN($1)\n" if ($debug);
+ $type = 'N';
+
+ } elsif ($cur =~ /^(;|{|}|\?|:|\[)/o) {
+ print "END($1)\n" if ($debug);
+ $type = 'N';
+
+ } elsif ($cur =~ /^($Operators)/o) {
+ print "OP($1)\n" if ($debug);
+ if ($1 ne '++' && $1 ne '--') {
+ $type = 'N';
+ }
+
+ } elsif ($cur =~ /(^.)/o) {
+ print "C($1)\n" if ($debug);
+ }
+ if (defined $1) {
+ $cur = substr($cur, length($1));
+ $res .= $type x length($1);
+ }
+ }
+
+ return $res;
+}
+
+my $prefix = '';
+
my @report = ();
sub report {
- push(@report, $_[0]);
+ push(@report, $prefix . $_[0]);
}
sub report_dump {
@report;
@@ -274,14 +527,19 @@ sub report_dump {
sub ERROR {
report("ERROR: $_[0]\n");
our $clean = 0;
+ our $cnt_error++;
}
sub WARN {
report("WARNING: $_[0]\n");
our $clean = 0;
+ our $cnt_warn++;
}
sub CHK {
- report("CHECK: $_[0]\n");
- our $clean = 0;
+ if ($check) {
+ report("CHECK: $_[0]\n");
+ our $clean = 0;
+ our $cnt_chk++;
+ }
}
sub process {
@@ -301,6 +559,11 @@ sub process {
my $signoff = 0;
my $is_patch = 0;
+ our $cnt_lines = 0;
+ our $cnt_error = 0;
+ our $cnt_warn = 0;
+ our $cnt_chk = 0;
+
# Trace the real file/line as we go.
my $realfile = '';
my $realline = 0;
@@ -309,46 +572,10 @@ sub process {
my $in_comment = 0;
my $first_line = 0;
- my $Ident = qr{[A-Za-z\d_]+};
- my $Storage = qr{extern|static};
- my $Sparse = qr{__user|__kernel|__force|__iomem|__must_check|__init_refok};
- my $NonptrType = qr{
- \b
- (?:const\s+)?
- (?:unsigned\s+)?
- (?:
- void|
- char|
- short|
- int|
- long|
- unsigned|
- float|
- double|
- bool|
- long\s+int|
- long\s+long|
- long\s+long\s+int|
- u8|u16|u32|u64|
- s8|s16|s32|s64|
- struct\s+$Ident|
- union\s+$Ident|
- enum\s+$Ident|
- ${Ident}_t
- )
- (?:\s+$Sparse)*
- \b
- }x;
- my $Type = qr{
- \b$NonptrType\b
- (?:\s*\*+\s*const|\s*\*+|(?:\s*\[\s*\])+)?
- (?:\s+$Sparse)*
- }x;
- my $Declare = qr{(?:$Storage\s+)?$Type};
- my $Attribute = qr{const|__read_mostly|__init|__initdata|__meminit};
-
- my $Member = qr{->$Ident|\.$Ident|\[[^]]*\]};
- my $Lval = qr{$Ident(?:$Member)*};
+ my $prev_values = 'N';
+
+ # Possible bare types.
+ my @bare = ();
# Pre-scan the patch looking for any __setup documentation.
my @setup_docs = ();
@@ -367,11 +594,14 @@ sub process {
}
}
+ $prefix = '';
+
foreach my $line (@lines) {
$linenr++;
my $rawline = $line;
+
#extract the filename as it passes
if ($line=~/^\+\+\+\s+(\S+)/) {
$realfile=$1;
@@ -380,7 +610,7 @@ sub process {
next;
}
#extract the line range in the file after the patch is applied
- if ($line=~/^\@\@ -\d+,\d+ \+(\d+)(,(\d+))? \@\@/) {
+ if ($line=~/^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) {
$is_patch = 1;
$first_line = $linenr + 1;
$in_comment = 0;
@@ -390,6 +620,7 @@ sub process {
} else {
$realcnt=1+1;
}
+ $prev_values = 'N';
next;
}
@@ -423,18 +654,24 @@ sub process {
# Track the previous line.
($prevline, $stashline) = ($stashline, $line);
($previndent, $stashindent) = ($stashindent, $indent);
+
} elsif ($realcnt == 1) {
$realcnt--;
}
#make up the handle for any error we report on this line
- $here = "#$linenr: ";
+ $here = "#$linenr: " if (!$file);
+ $here = "#$realline: " if ($file);
$here .= "FILE: $realfile:$realline:" if ($realcnt != 0);
my $hereline = "$here\n$line\n";
my $herecurr = "$here\n$line\n";
my $hereprev = "$here\n$prevline\n$line\n";
+ $prefix = "$filename:$realline: " if ($emacs && $file);
+ $prefix = "$filename:$linenr: " if ($emacs && !$file);
+ $cnt_lines++ if ($realcnt != 0);
+
#check the patch for a signoff:
if ($line =~ /^\s*signed-off-by:/i) {
# This is a signoff, if ugly, so do not double report.
@@ -452,7 +689,7 @@ sub process {
# Check for wrappage within a valid hunk of the file
if ($realcnt != 0 && $line !~ m{^(?:\+|-| |$)}) {
ERROR("patch seems to be corrupt (line wrapped?)\n" .
- $herecurr);
+ $herecurr) if (!$emitted_corrupt++);
}
# UTF-8 regex found at http://www.w3.org/International/questions/qa-forms-utf-8.en.php
@@ -477,7 +714,11 @@ sub process {
next if ($realfile !~ /\.(h|c|s|S|pl|sh)$/);
#trailing whitespace
- if ($line =~ /^\+.*\S\s+$/ || $line =~ /^\+\s+$/) {
+ if ($line =~ /^\+.*\015/) {
+ my $herevet = "$here\n" . cat_vet($line) . "\n";
+ ERROR("DOS line endings\n" . $herevet);
+
+ } elsif ($line =~ /^\+.*\S\s+$/ || $line =~ /^\+\s+$/) {
my $herevet = "$here\n" . cat_vet($line) . "\n";
ERROR("trailing whitespace\n" . $herevet);
}
@@ -509,6 +750,34 @@ sub process {
# Standardise the strings and chars within the input to simplify matching.
$line = sanitise_line($line);
+# Check for potential 'bare' types
+ if ($realcnt &&
+ $line !~ /^.\s*(?:$Storage\s+)?(?:$Inline\s+)?$Type\b/ &&
+ $line !~ /$Ident:\s*$/ &&
+ $line !~ /^.\s*$Ident\s*\(/ &&
+ # definitions in global scope can only start with types
+ ($line =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?($Ident)\b/ ||
+ # declarations always start with types
+ $line =~ /^.\s*(?:$Storage\s+)?($Ident)\b\s*\**\s*$Ident\s*(?:;|=)/) ||
+ # any (foo ... *) is a pointer cast, and foo is a type
+ $line =~ /\(($Ident)(?:\s+$Sparse)*\s*\*+\s*\)/) {
+ my $possible = $1;
+ if ($possible !~ /^(?:$Storage|$Type|DEFINE_\S+)$/ &&
+ $possible ne 'goto' && $possible ne 'return' &&
+ $possible ne 'struct' && $possible ne 'enum' &&
+ $possible ne 'case' && $possible ne 'else' &&
+ $possible ne 'typedef') {
+ #print "POSSIBLE<$possible>\n";
+ push(@bare, $possible);
+ my $bare = join("|", @bare);
+ $Bare = '|' . qr{
+ \b(?:$bare)\b
+ (?:\s*\*+\s*const|\s*\*+|(?:\s*\[\s*\])+)?
+ (?:\s+$Sparse)*
+ }x;
+ }
+ }
+
#
# Checks which may be anchored in the context.
#
@@ -531,18 +800,19 @@ sub process {
}
}
if ($err ne '') {
- ERROR("switch and case should be at the same indent\n$hereline\n$err\n");
+ ERROR("switch and case should be at the same indent\n$hereline$err");
}
}
# if/while/etc brace do not go on next line, unless defining a do while loop,
# or if that brace on the next line is for something else
if ($line =~ /\b(?:(if|while|for|switch)\s*\(|do\b|else\b)/ && $line !~ /^.#/) {
- my @ctx = ctx_statement($linenr, $realcnt, 0);
+ my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0);
my $ctx_ln = $linenr + $#ctx + 1;
my $ctx_cnt = $realcnt - $#ctx - 1;
my $ctx = join("\n", @ctx);
+ # Skip over any removed lines in the context following statement.
while ($ctx_cnt > 0 && $lines[$ctx_ln - 1] =~ /^-/) {
$ctx_ln++;
$ctx_cnt--;
@@ -553,8 +823,23 @@ sub process {
ERROR("That open brace { should be on the previous line\n" .
"$here\n$ctx\n$lines[$ctx_ln - 1]");
}
+ if ($level == 0 && $ctx =~ /\)\s*\;\s*$/ && defined $lines[$ctx_ln - 1]) {
+ my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]);
+ if ($nindent > $indent) {
+ WARN("Trailing semicolon indicates no statements, indent implies otherwise\n" .
+ "$here\n$ctx\n$lines[$ctx_ln - 1]");
+ }
+ }
}
+ # Track the 'values' across context and added lines.
+ my $opline = $line; $opline =~ s/^./ /;
+ my $curr_values = annotate_values($opline . "\n", $prev_values);
+ $curr_values = $prev_values . $curr_values;
+ #warn "--> $opline\n";
+ #warn "--> $curr_values ($prev_values)\n";
+ $prev_values = substr($curr_values, -1);
+
#ignore lines not being added
if ($line=~/^[^\+]/) {next;}
@@ -592,6 +877,7 @@ sub process {
}
# Remove C99 comments.
$line =~ s@//.*@@;
+ $opline =~ s@//.*@@;
#EXPORT_SYMBOL should immediately follow its function closing }.
if (($line =~ /EXPORT_SYMBOL.*\((.*)\)/) ||
@@ -619,7 +905,7 @@ sub process {
# check for new typedefs, only function parameters and sparse annotations
# make sense.
if ($line =~ /\btypedef\s/ &&
- $line !~ /\btypedef\s+$Type\s+\(\s*\*$Ident\s*\)\s*\(/ &&
+ $line !~ /\btypedef\s+$Type\s+\(\s*\*?$Ident\s*\)\s*\(/ &&
$line !~ /\b__bitwise(?:__|)\b/) {
WARN("do not add new typedefs\n" . $herecurr);
}
@@ -633,11 +919,11 @@ sub process {
ERROR("\"(foo $1 )\" should be \"(foo $1)\"\n" .
$herecurr);
- } elsif ($line =~ m{$NonptrType(\*+)(?:\s+$Attribute)?\s+[A-Za-z\d_]+}) {
+ } elsif ($line =~ m{$NonptrType(\*+)(?:\s+(?:$Attribute|$Sparse))?\s+[A-Za-z\d_]+}) {
ERROR("\"foo$1 bar\" should be \"foo $1bar\"\n" .
$herecurr);
- } elsif ($line =~ m{$NonptrType\s+(\*+)(?!\s+$Attribute)\s+[A-Za-z\d_]+}) {
+ } elsif ($line =~ m{$NonptrType\s+(\*+)(?!\s+(?:$Attribute|$Sparse))\s+[A-Za-z\d_]+}) {
ERROR("\"foo $1 bar\" should be \"foo $1bar\"\n" .
$herecurr);
}
@@ -680,21 +966,25 @@ sub process {
}
# check for spaces between functions and their parentheses.
- if ($line =~ /($Ident)\s+\(/ &&
- $1 !~ /^(?:if|for|while|switch|return|volatile|__volatile__|__attribute__|format|__extension__|Copyright)$/ &&
- $line !~ /$Type\s+\(/ && $line !~ /^.\#\s*define\b/) {
- WARN("no space between function name and open parenthesis '('\n" . $herecurr);
+ while ($line =~ /($Ident)\s+\(/g) {
+ if ($1 !~ /^(?:if|for|while|switch|return|volatile|__volatile__|__attribute__|format|__extension__|Copyright|case)$/ &&
+ $line !~ /$Type\s+\(/ && $line !~ /^.\#\s*define\b/) {
+ WARN("no space between function name and open parenthesis '('\n" . $herecurr);
+ }
}
# Check operator spacing.
- # Note we expand the line with the leading + as the real
- # line will be displayed with the leading + and the tabs
- # will therefore also expand that way.
- my $opline = $line;
- $opline = expand_tabs($opline);
- $opline =~ s/^./ /;
if (!($line=~/\#\s*include/)) {
- my @elements = split(/(<<=|>>=|<=|>=|==|!=|\+=|-=|\*=|\/=|%=|\^=|\|=|&=|=>|->|<<|>>|<|>|=|!|~|&&|\|\||,|\^|\+\+|--|;|&|\||\+|-|\*|\/\/|\/)/, $opline);
+ my $ops = qr{
+ <<=|>>=|<=|>=|==|!=|
+ \+=|-=|\*=|\/=|%=|\^=|\|=|&=|
+ =>|->|<<|>>|<|>|=|!|~|
+ &&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/
+ }x;
+ my @elements = split(/($ops|;)/, $opline);
my $off = 0;
+
+ my $blank = copy_spacing($opline);
+
for (my $n = 0; $n < $#elements; $n += 2) {
$off += length($elements[$n]);
@@ -730,10 +1020,25 @@ sub process {
my $at = "(ctx:$ctx)";
- my $ptr = (" " x $off) . "^";
+ my $ptr = substr($blank, 0, $off) . "^";
my $hereptr = "$hereline$ptr\n";
- ##print "<$s1:$op:$s2> <$elements[$n]:$elements[$n + 1]:$elements[$n + 2]>\n";
+ # Classify operators into binary, unary, or
+ # definitions (* only) where they have more
+ # than one mode.
+ my $op_type = substr($curr_values, $off + 1, 1);
+ my $op_left = substr($curr_values, $off, 1);
+ my $is_unary;
+ if ($op_type eq 'T') {
+ $is_unary = 2;
+ } elsif ($op_left eq 'V') {
+ $is_unary = 0;
+ } else {
+ $is_unary = 1;
+ }
+ #if ($op eq '-' || $op eq '&' || $op eq '*') {
+ # print "UNARY: <$op_left$op_type $is_unary $a:$op:$c> <$ca:$op:$cc> <$unary_ctx>\n";
+ #}
# ; should have either the end of line or a space or \ after it
if ($op eq ';') {
@@ -757,9 +1062,16 @@ sub process {
ERROR("need space after that '$op' $at\n" . $hereptr);
}
- # unary ! and unary ~ are allowed no space on the right
- } elsif ($op eq '!' or $op eq '~') {
- if ($ctx !~ /[WOEB]x./) {
+ # '*' as part of a type definition -- reported already.
+ } elsif ($op eq '*' && $is_unary == 2) {
+ #warn "'*' is part of type\n";
+
+ # unary operators should have a space before and
+ # none after. May be left adjacent to another
+ # unary operator, or a cast
+ } elsif ($op eq '!' || $op eq '~' ||
+ ($is_unary && ($op eq '*' || $op eq '-' || $op eq '&'))) {
+ if ($ctx !~ /[WEB]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) {
ERROR("need space before that '$op' $at\n" . $hereptr);
}
if ($ctx =~ /.xW/) {
@@ -775,39 +1087,13 @@ sub process {
ERROR("no space before that '$op' $at\n" . $hereptr);
}
- # & is both unary and binary
- # unary:
- # a &b
- # binary (consistent spacing):
- # a&b OK
- # a & b OK
- #
- # boiling down to: if there is a space on the right then there
- # should be one on the left.
- #
- # - is the same
- #
- } elsif ($op eq '&' or $op eq '-') {
- if ($ctx !~ /VxV|[EW]x[WE]|[EWB]x[VO]/) {
- ERROR("need space before that '$op' $at\n" . $hereptr);
- }
-
- # * is the same as & only adding:
- # type:
- # (foo *)
- # (foo **)
- #
- } elsif ($op eq '*') {
- if ($ca !~ /$Type$/ && $cb !~ /(\*$;|$;\*)/ &&
- $ctx !~ /VxV|[EW]x[WE]|[EWB]x[VO]|OxV|WxB|BxB/) {
- ERROR("need space before that '$op' $at\n" . $hereptr);
- }
-
# << and >> may either have or not have spaces both sides
- } elsif ($op eq '<<' or $op eq '>>' or $op eq '+' or $op eq '/' or
- $op eq '^' or $op eq '|')
+ } elsif ($op eq '<<' or $op eq '>>' or
+ $op eq '&' or $op eq '^' or $op eq '|' or
+ $op eq '+' or $op eq '-' or
+ $op eq '*' or $op eq '/')
{
- if ($ctx !~ /VxV|WxW|VxE|WxE/) {
+ if ($ctx !~ /VxV|WxW|VxE|WxE|VxO/) {
ERROR("need consistent spacing around '$op' $at\n" .
$hereptr);
}
@@ -826,7 +1112,7 @@ sub process {
# check for multiple assignments
if ($line =~ /^.\s*$Lval\s*=\s*$Lval\s*=(?!=)/) {
- WARN("multiple assignments should be avoided\n" . $herecurr);
+ CHK("multiple assignments should be avoided\n" . $herecurr);
}
## # check for multiple declarations, allowing for a function declaration
@@ -865,10 +1151,12 @@ sub process {
}
# check spacing on paretheses
- if ($line =~ /\(\s/ && $line !~ /\(\s*$/) {
+ if ($line =~ /\(\s/ && $line !~ /\(\s*(?:\\)?$/ &&
+ $line !~ /for\s*\(\s+;/) {
ERROR("no space after that open parenthesis '('\n" . $herecurr);
}
- if ($line =~ /\s\)/) {
+ if ($line =~ /\s\)/ && $line !~ /^.\s*\)/ &&
+ $line !~ /for\s*\(.*;\s+\)/) {
ERROR("no space before that close parenthesis ')'\n" . $herecurr);
}
@@ -884,7 +1172,7 @@ sub process {
}
# Check for illegal assignment in if conditional.
- if ($line=~/\bif\s*\(.*[^<>!=]=[^=].*\)/) {
+ if ($line=~/\bif\s*\(.*[^<>!=]=[^=]/) {
#next if ($line=~/\".*\Q$op\E.*\"/ or $line=~/\'\Q$op\E\'/);
ERROR("do not use assignment in if condition\n" . $herecurr);
}
@@ -910,8 +1198,8 @@ sub process {
#warn if <asm/foo.h> is #included and <linux/foo.h> is available (uses RAW line)
if ($tree && $rawline =~ m{^.\#\s*include\s*\<asm\/(.*)\.h\>}) {
- my $checkfile = "include/linux/$1.h";
- if (-f $checkfile) {
+ my $checkfile = "$root/include/linux/$1.h";
+ if (-f $checkfile && $1 ne 'irq.h') {
CHK("Use #include <linux/$1.h> instead of <asm/$1.h>\n" .
$herecurr);
}
@@ -926,10 +1214,10 @@ sub process {
# multi-statement macros should be enclosed in a do while loop, grab the
# first statement and ensure its the whole macro if its not enclosed
# in a known goot container
- if (($prevline=~/\#define.*\\/) and
- !($prevline=~/do\s+{/) and !($prevline=~/\(\{/) and
- !($line=~/do.*{/) and !($line=~/\(\{/) and
- !($line=~/^.\s*$Declare\s/)) {
+ if ($prevline =~ /\#define.*\\/ &&
+ $prevline !~/(?:do\s+{|\(\{|\{)/ &&
+ $line !~ /(?:do\s+{|\(\{|\{)/ &&
+ $line !~ /^.\s*$Declare\s/) {
# Grab the first statement, if that is the entire macro
# its ok. This may start either on the #define line
# or the one below.
@@ -1023,10 +1311,16 @@ sub process {
}
# no volatiles please
- if ($line =~ /\bvolatile\b/ && $line !~ /\basm\s+volatile\b/) {
+ my $asm_volatile = qr{\b(__asm__|asm)\s+(__volatile__|volatile)\b};
+ if ($line =~ /\bvolatile\b/ && $line !~ /$asm_volatile/) {
WARN("Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n" . $herecurr);
}
+# SPIN_LOCK_UNLOCKED & RW_LOCK_UNLOCKED are deprecated
+ if ($line =~ /\b(SPIN_LOCK_UNLOCKED|RW_LOCK_UNLOCKED)/) {
+ ERROR("Use of $1 is deprecated: see Documentation/spinlocks.txt\n" . $herecurr);
+ }
+
# warn about #if 0
if ($line =~ /^.#\s*if\s+0\b/) {
CHK("if this code is redundant consider removing it\n" .
@@ -1073,8 +1367,8 @@ sub process {
# check the location of the inline attribute, that it is between
# storage class and type.
- if ($line =~ /$Type\s+(?:inline|__always_inline|noinline)\b/ ||
- $line =~ /\b(?:inline|__always_inline|noinline)\s+$Storage/) {
+ if ($line =~ /\b$Type\s+$Inline\b/ ||
+ $line =~ /\b$Inline\s+$Storage\b/) {
ERROR("inline keyword should sit between storage class and type\n" . $herecurr);
}
@@ -1091,6 +1385,11 @@ sub process {
CHK("__setup appears un-documented -- check Documentation/kernel-parameters.txt\n" . $herecurr);
}
}
+
+# check for pointless casting of kmalloc return
+ if ($line =~ /\*\s*\)\s*k[czm]alloc\b/) {
+ WARN("unnecessary cast may hide bugs, see http://c-faq.com/malloc/mallocnocast.html\n" . $herecurr);
+ }
}
if ($chk_patch && !$is_patch) {
@@ -1102,6 +1401,11 @@ sub process {
if ($clean == 0 && ($chk_patch || $is_patch)) {
print report_dump();
+ if ($quiet < 2) {
+ print "total: $cnt_error errors, $cnt_warn warnings, " .
+ (($check)? "$cnt_chk checks, " : "") .
+ "$cnt_lines lines checked\n";
+ }
}
if ($clean == 1 && $quiet == 0) {
print "Your patch has no obvious style problems and is ready for submission.\n"
diff --git a/scripts/checkstack.pl b/scripts/checkstack.pl
index 663158627155..d716b76098bb 100755
--- a/scripts/checkstack.pl
+++ b/scripts/checkstack.pl
@@ -13,9 +13,10 @@
# Random bits by Matt Mackall <mpm@selenic.com>
# M68k port by Geert Uytterhoeven and Andreas Schwab
# AVR32 port by Haavard Skinnemoen <hskinnemoen@atmel.com>
+# PARISC port by Kyle McMartin <kyle@parisc-linux.org>
#
# Usage:
-# objdump -d vmlinux | stackcheck.pl [arch]
+# objdump -d vmlinux | scripts/checkstack.pl [arch]
#
# TODO : Port to all architectures (one regex per arch)
@@ -61,6 +62,8 @@ my (@stack, $re, $x, $xs);
} elsif ($arch eq 'mips') {
#88003254: 27bdffe0 addiu sp,sp,-32
$re = qr/.*addiu.*sp,sp,-(([0-9]{2}|[3-9])[0-9]{2})/o;
+ } elsif ($arch eq 'parisc' || $arch eq 'parisc64') {
+ $re = qr/.*ldo ($x{1,8})\(sp\),sp/o;
} elsif ($arch eq 'ppc') {
#c00029f4: 94 21 ff 30 stwu r1,-208(r1)
$re = qr/.*stwu.*r1,-($x{1,8})\(r1\)/o;
@@ -78,6 +81,9 @@ my (@stack, $re, $x, $xs);
# pair for larger users. -- PFM.
#a00048e0: d4fc40f0 addi.l r15,-240,r15
$re = qr/.*addi\.l.*r15,-(([0-9]{2}|[3-9])[0-9]{2}),r15/o;
+ } elsif ($arch =~ /^blackfin$/) {
+ # 0: 00 e8 38 01 LINK 0x4e0;
+ $re = qr/.*[[:space:]]LINK[[:space:]]*(0x$x{1,8})/o;
} else {
print("wrong or unknown architecture\n");
exit
diff --git a/scripts/export_report.pl b/scripts/export_report.pl
index 9ed00d9bb0a7..705b5ba7c152 100644
--- a/scripts/export_report.pl
+++ b/scripts/export_report.pl
@@ -103,16 +103,16 @@ foreach my $thismod (@allcfiles) {
my $state=0;
while ( <MODULE_MODULE> ) {
chomp;
- if ($state eq 0) {
+ if ($state == 0) {
$state = 1 if ($_ =~ /static const struct modversion_info/);
next;
}
- if ($state eq 1) {
+ if ($state == 1) {
$state = 2 if ($_ =~ /__attribute__\(\(section\("__versions"\)\)\)/);
next;
}
- if ($state eq 2) {
- if ( $_ !~ /0x[0-9a-f]{7,8},/ ) {
+ if ($state == 2) {
+ if ( $_ !~ /0x[0-9a-f]+,/ ) {
next;
}
my $sym = (split /([,"])/,)[4];
@@ -121,7 +121,7 @@ foreach my $thismod (@allcfiles) {
push(@{$MODULE{$thismod}} , $sym);
}
}
- if ($state ne 2) {
+ if ($state != 2) {
print "WARNING:$thismod is not built with CONFIG_MODVERSION enabled\n";
}
close(MODULE_MODULE);
diff --git a/scripts/gcc-version.sh b/scripts/gcc-version.sh
index 8a1d1879c7ad..a5121a6d8949 100644
--- a/scripts/gcc-version.sh
+++ b/scripts/gcc-version.sh
@@ -9,10 +9,16 @@
# gcc-2.95.3, `030301' for gcc-3.3.1, etc.
#
-if [ $1 = "-p" ] ; then with_patchlevel=1; shift; fi
+if [[ $1 = "-p" ]] ; then with_patchlevel=1; shift; fi
compiler="$*"
+if [ ${#compiler} -eq 0 ]; then
+ echo "Error: No compiler specified."
+ echo -e "Usage:\n\t$0 <gcc-command>"
+ exit 1
+fi
+
MAJOR=$(echo __GNUC__ | $compiler -E -xc - | tail -n 1)
MINOR=$(echo __GNUC_MINOR__ | $compiler -E -xc - | tail -n 1)
if [ "x$with_patchlevel" != "x" ] ; then
diff --git a/scripts/genksyms/Makefile b/scripts/genksyms/Makefile
index 5875f29a8602..e420fe440019 100644
--- a/scripts/genksyms/Makefile
+++ b/scripts/genksyms/Makefile
@@ -23,14 +23,16 @@ quiet_cmd_keywords.c = GPERF $@
$(obj)/keywords.c: $(obj)/keywords.gperf FORCE
$(call if_changed,keywords.c)
+ cp $@ $@_shipped
# flex
quiet_cmd_lex.c = FLEX $@
- cmd_lex.c = flex -o$@ -d $(filter-out FORCE,$^)
+ cmd_lex.c = flex -o$@ -d $< $(obj)/parse.h
-$(obj)/lex.c: $(obj)/lex.l $(obj)/parse.h FORCE
+$(obj)/lex.c: $(obj)/lex.l $(obj)/parse.h $(obj)/keywords.c FORCE
$(call if_changed,lex.c)
+ cp $@ $@_shipped
# bison
@@ -39,6 +41,8 @@ quiet_cmd_parse.c = BISON $@
$(obj)/parse.c: $(obj)/parse.y FORCE
$(call if_changed,parse.c)
+ cp $@ $@_shipped
+ cp $(@:.c=.h) $(@:.c=.h)_shipped
$(obj)/parse.h: $(obj)/parse.c ;
diff --git a/scripts/genksyms/keywords.c_shipped b/scripts/genksyms/keywords.c_shipped
index d8153f572e40..971e0113ae7a 100644
--- a/scripts/genksyms/keywords.c_shipped
+++ b/scripts/genksyms/keywords.c_shipped
@@ -1,4 +1,4 @@
-/* ANSI-C code produced by gperf version 3.0.1 */
+/* ANSI-C code produced by gperf version 3.0.2 */
/* Command-line: gperf -L ANSI-C -a -C -E -g -H is_reserved_hash -k '1,3,$' -N is_reserved_word -p -t scripts/genksyms/keywords.gperf */
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
@@ -32,7 +32,7 @@
#line 3 "scripts/genksyms/keywords.gperf"
struct resword { const char *name; int token; };
-/* maximum key range = 68, duplicates = 0 */
+/* maximum key range = 62, duplicates = 0 */
#ifdef __GNUC__
__inline
@@ -46,32 +46,32 @@ is_reserved_hash (register const char *str, register unsigned int len)
{
static const unsigned char asso_values[] =
{
- 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,
- 71, 71, 71, 71, 71, 71, 35, 71, 71, 71,
- 5, 71, 71, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 71, 0, 71, 0, 71, 5,
- 5, 0, 10, 20, 71, 25, 71, 71, 20, 0,
- 20, 30, 25, 71, 10, 5, 0, 20, 15, 71,
- 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 71, 71
+ 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
+ 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
+ 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
+ 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
+ 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
+ 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
+ 65, 65, 65, 65, 65, 65, 65, 65, 65, 5,
+ 65, 65, 65, 65, 65, 65, 35, 65, 65, 65,
+ 0, 65, 65, 65, 65, 65, 65, 65, 65, 65,
+ 65, 65, 65, 65, 65, 0, 65, 0, 65, 5,
+ 20, 15, 10, 30, 65, 15, 65, 65, 20, 0,
+ 10, 35, 20, 65, 10, 5, 0, 10, 5, 65,
+ 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
+ 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
+ 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
+ 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
+ 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
+ 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
+ 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
+ 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
+ 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
+ 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
+ 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
+ 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
+ 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
+ 65, 65, 65, 65, 65, 65
};
return len + asso_values[(unsigned char)str[2]] + asso_values[(unsigned char)str[0]] + asso_values[(unsigned char)str[len - 1]];
}
@@ -84,17 +84,17 @@ is_reserved_word (register const char *str, register unsigned int len)
{
enum
{
- TOTAL_KEYWORDS = 42,
+ TOTAL_KEYWORDS = 43,
MIN_WORD_LENGTH = 3,
MAX_WORD_LENGTH = 24,
MIN_HASH_VALUE = 3,
- MAX_HASH_VALUE = 70
+ MAX_HASH_VALUE = 64
};
static const struct resword wordlist[] =
{
{""}, {""}, {""},
-#line 25 "scripts/genksyms/keywords.gperf"
+#line 26 "scripts/genksyms/keywords.gperf"
{"asm", ASM_KEYW},
{""},
#line 8 "scripts/genksyms/keywords.gperf"
@@ -102,98 +102,98 @@ is_reserved_word (register const char *str, register unsigned int len)
{""},
#line 9 "scripts/genksyms/keywords.gperf"
{"__asm__", ASM_KEYW},
- {""},
-#line 22 "scripts/genksyms/keywords.gperf"
- {"_restrict", RESTRICT_KEYW},
-#line 51 "scripts/genksyms/keywords.gperf"
+ {""}, {""},
+#line 52 "scripts/genksyms/keywords.gperf"
{"__typeof__", TYPEOF_KEYW},
-#line 10 "scripts/genksyms/keywords.gperf"
- {"__attribute", ATTRIBUTE_KEYW},
+ {""},
#line 12 "scripts/genksyms/keywords.gperf"
{"__const", CONST_KEYW},
#line 11 "scripts/genksyms/keywords.gperf"
{"__attribute__", ATTRIBUTE_KEYW},
#line 13 "scripts/genksyms/keywords.gperf"
{"__const__", CONST_KEYW},
-#line 17 "scripts/genksyms/keywords.gperf"
+#line 18 "scripts/genksyms/keywords.gperf"
{"__signed__", SIGNED_KEYW},
-#line 43 "scripts/genksyms/keywords.gperf"
+#line 44 "scripts/genksyms/keywords.gperf"
{"static", STATIC_KEYW},
- {""},
-#line 16 "scripts/genksyms/keywords.gperf"
- {"__signed", SIGNED_KEYW},
-#line 31 "scripts/genksyms/keywords.gperf"
+#line 20 "scripts/genksyms/keywords.gperf"
+ {"__volatile__", VOLATILE_KEYW},
+#line 39 "scripts/genksyms/keywords.gperf"
+ {"int", INT_KEYW},
+#line 32 "scripts/genksyms/keywords.gperf"
{"char", CHAR_KEYW},
- {""},
-#line 44 "scripts/genksyms/keywords.gperf"
+#line 33 "scripts/genksyms/keywords.gperf"
+ {"const", CONST_KEYW},
+#line 45 "scripts/genksyms/keywords.gperf"
{"struct", STRUCT_KEYW},
-#line 23 "scripts/genksyms/keywords.gperf"
- {"__restrict__", RESTRICT_KEYW},
#line 24 "scripts/genksyms/keywords.gperf"
+ {"__restrict__", RESTRICT_KEYW},
+#line 25 "scripts/genksyms/keywords.gperf"
{"restrict", RESTRICT_KEYW},
-#line 34 "scripts/genksyms/keywords.gperf"
+#line 23 "scripts/genksyms/keywords.gperf"
+ {"_restrict", RESTRICT_KEYW},
+#line 16 "scripts/genksyms/keywords.gperf"
+ {"__inline__", INLINE_KEYW},
+#line 10 "scripts/genksyms/keywords.gperf"
+ {"__attribute", ATTRIBUTE_KEYW},
+ {""},
+#line 14 "scripts/genksyms/keywords.gperf"
+ {"__extension__", EXTENSION_KEYW},
+#line 35 "scripts/genksyms/keywords.gperf"
{"enum", ENUM_KEYW},
-#line 18 "scripts/genksyms/keywords.gperf"
+#line 19 "scripts/genksyms/keywords.gperf"
{"__volatile", VOLATILE_KEYW},
-#line 35 "scripts/genksyms/keywords.gperf"
+#line 36 "scripts/genksyms/keywords.gperf"
{"extern", EXTERN_KEYW},
-#line 19 "scripts/genksyms/keywords.gperf"
- {"__volatile__", VOLATILE_KEYW},
-#line 38 "scripts/genksyms/keywords.gperf"
- {"int", INT_KEYW},
+ {""},
+#line 17 "scripts/genksyms/keywords.gperf"
+ {"__signed", SIGNED_KEYW},
#line 7 "scripts/genksyms/keywords.gperf"
{"EXPORT_SYMBOL_GPL_FUTURE", EXPORT_SYMBOL_KEYW},
-#line 32 "scripts/genksyms/keywords.gperf"
- {"const", CONST_KEYW},
-#line 33 "scripts/genksyms/keywords.gperf"
- {"double", DOUBLE_KEYW},
{""},
-#line 14 "scripts/genksyms/keywords.gperf"
+#line 51 "scripts/genksyms/keywords.gperf"
+ {"typeof", TYPEOF_KEYW},
+#line 46 "scripts/genksyms/keywords.gperf"
+ {"typedef", TYPEDEF_KEYW},
+#line 15 "scripts/genksyms/keywords.gperf"
{"__inline", INLINE_KEYW},
-#line 30 "scripts/genksyms/keywords.gperf"
+#line 31 "scripts/genksyms/keywords.gperf"
{"auto", AUTO_KEYW},
-#line 15 "scripts/genksyms/keywords.gperf"
- {"__inline__", INLINE_KEYW},
-#line 42 "scripts/genksyms/keywords.gperf"
- {"signed", SIGNED_KEYW},
- {""},
#line 47 "scripts/genksyms/keywords.gperf"
+ {"union", UNION_KEYW},
+ {""}, {""},
+#line 48 "scripts/genksyms/keywords.gperf"
{"unsigned", UNSIGNED_KEYW},
- {""},
-#line 41 "scripts/genksyms/keywords.gperf"
+#line 49 "scripts/genksyms/keywords.gperf"
+ {"void", VOID_KEYW},
+#line 42 "scripts/genksyms/keywords.gperf"
{"short", SHORT_KEYW},
+ {""}, {""},
#line 50 "scripts/genksyms/keywords.gperf"
- {"typeof", TYPEOF_KEYW},
-#line 45 "scripts/genksyms/keywords.gperf"
- {"typedef", TYPEDEF_KEYW},
-#line 49 "scripts/genksyms/keywords.gperf"
{"volatile", VOLATILE_KEYW},
{""},
-#line 36 "scripts/genksyms/keywords.gperf"
- {"float", FLOAT_KEYW},
- {""}, {""},
-#line 40 "scripts/genksyms/keywords.gperf"
- {"register", REGISTER_KEYW},
-#line 48 "scripts/genksyms/keywords.gperf"
- {"void", VOID_KEYW},
- {""},
#line 37 "scripts/genksyms/keywords.gperf"
- {"inline", INLINE_KEYW},
+ {"float", FLOAT_KEYW},
+#line 34 "scripts/genksyms/keywords.gperf"
+ {"double", DOUBLE_KEYW},
{""},
#line 5 "scripts/genksyms/keywords.gperf"
{"EXPORT_SYMBOL", EXPORT_SYMBOL_KEYW},
- {""},
-#line 21 "scripts/genksyms/keywords.gperf"
- {"_Bool", BOOL_KEYW},
- {""},
+ {""}, {""},
+#line 38 "scripts/genksyms/keywords.gperf"
+ {"inline", INLINE_KEYW},
#line 6 "scripts/genksyms/keywords.gperf"
{"EXPORT_SYMBOL_GPL", EXPORT_SYMBOL_KEYW},
- {""}, {""}, {""}, {""}, {""}, {""},
-#line 39 "scripts/genksyms/keywords.gperf"
- {"long", LONG_KEYW},
- {""}, {""}, {""}, {""}, {""},
-#line 46 "scripts/genksyms/keywords.gperf"
- {"union", UNION_KEYW}
+#line 41 "scripts/genksyms/keywords.gperf"
+ {"register", REGISTER_KEYW},
+ {""},
+#line 22 "scripts/genksyms/keywords.gperf"
+ {"_Bool", BOOL_KEYW},
+#line 43 "scripts/genksyms/keywords.gperf"
+ {"signed", SIGNED_KEYW},
+ {""}, {""},
+#line 40 "scripts/genksyms/keywords.gperf"
+ {"long", LONG_KEYW}
};
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
diff --git a/scripts/genksyms/keywords.gperf b/scripts/genksyms/keywords.gperf
index c75e0c8d8f0c..5ef3733225fb 100644
--- a/scripts/genksyms/keywords.gperf
+++ b/scripts/genksyms/keywords.gperf
@@ -11,6 +11,7 @@ __attribute, ATTRIBUTE_KEYW
__attribute__, ATTRIBUTE_KEYW
__const, CONST_KEYW
__const__, CONST_KEYW
+__extension__, EXTENSION_KEYW
__inline, INLINE_KEYW
__inline__, INLINE_KEYW
__signed, SIGNED_KEYW
diff --git a/scripts/genksyms/lex.c_shipped b/scripts/genksyms/lex.c_shipped
index 37ba98241b96..2a176988d468 100644
--- a/scripts/genksyms/lex.c_shipped
+++ b/scripts/genksyms/lex.c_shipped
@@ -1,32 +1,114 @@
#line 2 "scripts/genksyms/lex.c"
-/* A lexical scanner generated by flex */
-/* Scanner skeleton version:
- * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $
- */
+#line 4 "scripts/genksyms/lex.c"
+
+#define YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 33
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* %if-c++-only */
+/* %endif */
+/* %if-c-only */
+
+/* %endif */
+
+/* %if-c-only */
+
+/* %endif */
+
+/* First, we deal with platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+/* %if-c-only */
#include <stdio.h>
-#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+/* %endif */
+/* %if-tables-serialization */
+/* %endif */
+/* end standard C headers. */
-/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
-#ifdef c_plusplus
-#ifndef __cplusplus
-#define __cplusplus
+/* %if-c-or-c++ */
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types.
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t;
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647-1)
#endif
+#ifndef INT8_MAX
+#define INT8_MAX (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX (4294967295U)
#endif
+#endif /* ! FLEXINT_H */
-#ifdef __cplusplus
+/* %endif */
-#include <stdlib.h>
+/* %if-c++-only */
+/* %endif */
-/* Use prototypes in function declarations. */
-#define YY_USE_PROTOS
+#ifdef __cplusplus
/* The "const" storage-class-modifier is valid. */
#define YY_USE_CONST
@@ -35,36 +117,24 @@
#if __STDC__
-#define YY_USE_PROTOS
#define YY_USE_CONST
#endif /* __STDC__ */
#endif /* ! __cplusplus */
-#ifdef __TURBOC__
- #pragma warn -rch
- #pragma warn -use
-#include <io.h>
-#include <stdlib.h>
-#define YY_USE_CONST
-#define YY_USE_PROTOS
-#endif
-
#ifdef YY_USE_CONST
#define yyconst const
#else
#define yyconst
#endif
-
-#ifdef YY_USE_PROTOS
-#define YY_PROTO(proto) proto
-#else
-#define YY_PROTO(proto) ()
-#endif
+/* %not-for-header */
/* Returned upon end-of-file. */
#define YY_NULL 0
+/* %ok-for-header */
+
+/* %not-for-header */
/* Promotes a possibly negative, possibly signed char to an unsigned
* integer for use as an array index. If the signed char is negative,
@@ -72,79 +142,102 @@
* double cast.
*/
#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+/* %ok-for-header */
+
+/* %if-reentrant */
+/* %endif */
+
+/* %if-not-reentrant */
+
+/* %endif */
/* Enter a start condition. This macro really ought to take a parameter,
* but we do it the disgusting crufty way forced on us by the ()-less
* definition of BEGIN.
*/
-#define BEGIN yy_start = 1 + 2 *
+#define BEGIN (yy_start) = 1 + 2 *
/* Translate the current start state into a value that can be later handed
* to BEGIN to return to the state. The YYSTATE alias is for lex
* compatibility.
*/
-#define YY_START ((yy_start - 1) / 2)
+#define YY_START (((yy_start) - 1) / 2)
#define YYSTATE YY_START
/* Action number for EOF rule of a given start state. */
#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
/* Special action meaning "start processing a new file". */
-#define YY_NEW_FILE yyrestart( yyin )
+#define YY_NEW_FILE yyrestart(yyin )
#define YY_END_OF_BUFFER_CHAR 0
/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
#define YY_BUF_SIZE 16384
+#endif
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+/* %if-not-reentrant */
extern int yyleng;
+/* %endif */
+
+/* %if-c-only */
+/* %if-not-reentrant */
extern FILE *yyin, *yyout;
+/* %endif */
+/* %endif */
#define EOB_ACT_CONTINUE_SCAN 0
#define EOB_ACT_END_OF_FILE 1
#define EOB_ACT_LAST_MATCH 2
-/* The funky do-while in the following #define is used to turn the definition
- * int a single C statement (which needs a semi-colon terminator). This
- * avoids problems with code like:
- *
- * if ( condition_holds )
- * yyless( 5 );
- * else
- * do_something_else();
- *
- * Prior to using the do-while the compiler would get upset at the
- * "else" because it interpreted the "if" statement as being all
- * done when it reached the ';' after the yyless() call.
- */
-
-/* Return all but the first 'n' matched characters back to the input stream. */
-
+ #define YY_LESS_LINENO(n)
+
+/* Return all but the first "n" matched characters back to the input stream. */
#define yyless(n) \
do \
{ \
/* Undo effects of setting up yytext. */ \
- *yy_cp = yy_hold_char; \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ *yy_cp = (yy_hold_char); \
YY_RESTORE_YY_MORE_OFFSET \
- yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
+ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
YY_DO_BEFORE_ACTION; /* set up yytext again */ \
} \
while ( 0 )
-#define unput(c) yyunput( c, yytext_ptr )
+#define unput(c) yyunput( c, (yytext_ptr) )
/* The following is because we cannot portably get our hands on size_t
* (without autoconf's help, which isn't available because we want
* flex-generated scanners to compile on their own).
*/
-typedef unsigned int yy_size_t;
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef unsigned int yy_size_t;
+#endif
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
struct yy_buffer_state
{
+/* %if-c-only */
FILE *yy_input_file;
+/* %endif */
+
+/* %if-c++-only */
+/* %endif */
char *yy_ch_buf; /* input buffer */
char *yy_buf_pos; /* current position in input buffer */
@@ -178,12 +271,16 @@ struct yy_buffer_state
*/
int yy_at_bol;
+ int yy_bs_lineno; /**< The line count. */
+ int yy_bs_column; /**< The column count. */
+
/* Whether to try to fill the input buffer when we reach the
* end of it.
*/
int yy_fill_buffer;
int yy_buffer_status;
+
#define YY_BUFFER_NEW 0
#define YY_BUFFER_NORMAL 1
/* When an EOF's been seen but there's still some text to process
@@ -197,102 +294,163 @@ struct yy_buffer_state
* just pointing yyin at a new input file.
*/
#define YY_BUFFER_EOF_PENDING 2
+
};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* %if-c-only Standard (non-C++) definition */
+/* %not-for-header */
-static YY_BUFFER_STATE yy_current_buffer = 0;
+/* %if-not-reentrant */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
+/* %endif */
+/* %ok-for-header */
+
+/* %endif */
/* We provide macros for accessing buffer states in case in the
* future we want to put the buffer states in a more general
* "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
*/
-#define YY_CURRENT_BUFFER yy_current_buffer
+#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+ : NULL)
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* %if-c-only Standard (non-C++) definition */
+
+/* %if-not-reentrant */
+/* %not-for-header */
/* yy_hold_char holds the character lost when yytext is formed. */
static char yy_hold_char;
-
static int yy_n_chars; /* number of characters read into yy_ch_buf */
-
-
int yyleng;
/* Points to current character in buffer. */
static char *yy_c_buf_p = (char *) 0;
-static int yy_init = 1; /* whether we need to initialize */
+static int yy_init = 0; /* whether we need to initialize */
static int yy_start = 0; /* start state number */
/* Flag which is used to allow yywrap()'s to do buffer switches
* instead of setting up a fresh yyin. A bit of a hack ...
*/
static int yy_did_buffer_switch_on_eof;
+/* %ok-for-header */
+
+/* %endif */
-void yyrestart YY_PROTO(( FILE *input_file ));
+void yyrestart (FILE *input_file );
+void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer );
+YY_BUFFER_STATE yy_create_buffer (FILE *file,int size );
+void yy_delete_buffer (YY_BUFFER_STATE b );
+void yy_flush_buffer (YY_BUFFER_STATE b );
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer );
+void yypop_buffer_state (void );
-void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
-void yy_load_buffer_state YY_PROTO(( void ));
-YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
-void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
-void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
-void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b ));
-#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer )
+static void yyensure_buffer_stack (void );
+static void yy_load_buffer_state (void );
+static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file );
-YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size ));
-YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str ));
-YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len ));
+#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
-static void *yy_flex_alloc YY_PROTO(( yy_size_t ));
-static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t ));
-static void yy_flex_free YY_PROTO(( void * ));
+YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size );
+YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str );
+YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len );
+
+/* %endif */
+
+void *yyalloc (yy_size_t );
+void *yyrealloc (void *,yy_size_t );
+void yyfree (void * );
#define yy_new_buffer yy_create_buffer
#define yy_set_interactive(is_interactive) \
{ \
- if ( ! yy_current_buffer ) \
- yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
- yy_current_buffer->yy_is_interactive = is_interactive; \
+ if ( ! YY_CURRENT_BUFFER ){ \
+ yyensure_buffer_stack (); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ yy_create_buffer(yyin,YY_BUF_SIZE ); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
}
#define yy_set_bol(at_bol) \
{ \
- if ( ! yy_current_buffer ) \
- yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
- yy_current_buffer->yy_at_bol = at_bol; \
+ if ( ! YY_CURRENT_BUFFER ){\
+ yyensure_buffer_stack (); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ yy_create_buffer(yyin,YY_BUF_SIZE ); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
}
-#define YY_AT_BOL() (yy_current_buffer->yy_at_bol)
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+/* %% [1.0] yytext/yyin/yyout/yy_state_type/yylineno etc. def's & init go here */
+/* Begin user sect3 */
#define yywrap() 1
#define YY_SKIP_YYWRAP
#define FLEX_DEBUG
+
typedef unsigned char YY_CHAR;
+
FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+
typedef int yy_state_type;
-#define FLEX_DEBUG
+extern int yylineno;
+
+int yylineno = 1;
+
extern char *yytext;
#define yytext_ptr yytext
-static yy_state_type yy_get_previous_state YY_PROTO(( void ));
-static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
-static int yy_get_next_buffer YY_PROTO(( void ));
-static void yy_fatal_error YY_PROTO(( yyconst char msg[] ));
+/* %if-c-only Standard (non-C++) definition */
+
+static yy_state_type yy_get_previous_state (void );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state );
+static int yy_get_next_buffer (void );
+static void yy_fatal_error (yyconst char msg[] );
+
+/* %endif */
/* Done after the current pattern has been matched and before the
* corresponding action - sets up yytext.
*/
#define YY_DO_BEFORE_ACTION \
- yytext_ptr = yy_bp; \
- yyleng = (int) (yy_cp - yy_bp); \
- yy_hold_char = *yy_cp; \
+ (yytext_ptr) = yy_bp; \
+/* %% [2.0] code to fiddle yytext and yyleng for yymore() goes here \ */\
+ yyleng = (size_t) (yy_cp - yy_bp); \
+ (yy_hold_char) = *yy_cp; \
*yy_cp = '\0'; \
- yy_c_buf_p = yy_cp;
+/* %% [3.0] code to copy yytext_ptr to yytext[] goes here, if %array \ */\
+ (yy_c_buf_p) = yy_cp;
+/* %% [4.0] data tables for the DFA and the user's section 1 definitions go here */
#define YY_NUM_RULES 13
#define YY_END_OF_BUFFER 14
-static yyconst short int yy_accept[76] =
+/* This struct is not used in this scanner,
+ but its presence is necessary. */
+struct yy_trans_info
+ {
+ flex_int32_t yy_verify;
+ flex_int32_t yy_nxt;
+ };
+static yyconst flex_int16_t yy_accept[76] =
{ 0,
0, 0, 0, 0, 14, 12, 4, 3, 12, 7,
12, 12, 7, 12, 12, 12, 12, 12, 9, 9,
@@ -304,7 +462,7 @@ static yyconst short int yy_accept[76] =
0, 0, 0, 1, 0
} ;
-static yyconst int yy_ec[256] =
+static yyconst flex_int32_t yy_ec[256] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
4, 4, 4, 1, 1, 1, 1, 1, 1, 1,
@@ -336,14 +494,14 @@ static yyconst int yy_ec[256] =
1, 1, 1, 1, 1
} ;
-static yyconst int yy_meta[29] =
+static yyconst flex_int32_t yy_meta[29] =
{ 0,
1, 1, 2, 1, 1, 1, 3, 1, 1, 1,
4, 4, 5, 6, 6, 6, 1, 1, 1, 7,
8, 7, 3, 3, 3, 1, 3, 1
} ;
-static yyconst short int yy_base[88] =
+static yyconst flex_int16_t yy_base[88] =
{ 0,
0, 147, 21, 140, 145, 284, 39, 284, 26, 0,
32, 126, 40, 44, 115, 35, 36, 46, 50, 53,
@@ -356,7 +514,7 @@ static yyconst short int yy_base[88] =
246, 250, 255, 256, 261, 267, 275
} ;
-static yyconst short int yy_def[88] =
+static yyconst flex_int16_t yy_def[88] =
{ 0,
75, 1, 1, 3, 75, 75, 75, 75, 76, 77,
78, 75, 77, 79, 75, 75, 75, 75, 75, 19,
@@ -369,7 +527,7 @@ static yyconst short int yy_def[88] =
75, 75, 75, 75, 75, 75, 75
} ;
-static yyconst short int yy_nxt[313] =
+static yyconst flex_int16_t yy_nxt[313] =
{ 0,
6, 7, 8, 7, 9, 6, 10, 6, 6, 11,
6, 6, 12, 6, 6, 6, 6, 6, 6, 10,
@@ -408,7 +566,7 @@ static yyconst short int yy_nxt[313] =
75, 75
} ;
-static yyconst short int yy_chk[313] =
+static yyconst flex_int16_t yy_chk[313] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -453,7 +611,7 @@ static char *yy_last_accepting_cpos;
extern int yy_flex_debug;
int yy_flex_debug = 1;
-static yyconst short int yy_rule_linenum[13] =
+static yyconst flex_int16_t yy_rule_linenum[13] =
{ 0,
69, 70, 71, 74, 77, 78, 79, 85, 86, 87,
89, 92
@@ -468,7 +626,6 @@ static yyconst short int yy_rule_linenum[13] =
#define YY_RESTORE_YY_MORE_OFFSET
char *yytext;
#line 1 "scripts/genksyms/lex.l"
-#define INITIAL 0
/* Lexical analysis for genksyms.
Copyright 1996, 1997 Linux International.
@@ -506,10 +663,41 @@ char *yytext;
/* Version 2 checksumming does proper tokenization; version 1 wasn't
quite so pedantic. */
-#define V2_TOKENS 1
/* We don't do multiple input files. */
-#line 513 "scripts/genksyms/lex.c"
+#line 669 "scripts/genksyms/lex.c"
+
+#define INITIAL 0
+#define V2_TOKENS 1
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+/* %if-c-only */
+#include <unistd.h>
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+/* %if-c-only Reentrant structure and macros (non-C++). */
+/* %if-reentrant */
+/* %if-c-only */
+
+static int yy_init_globals (void );
+
+/* %endif */
+/* %if-reentrant */
+/* %endif */
+/* %if-bison-bridge */
+/* %endif */
+/* %endif End reentrant structures and macros. */
/* Macros after this point can all be overridden by user definitions in
* section 1.
@@ -517,66 +705,45 @@ char *yytext;
#ifndef YY_SKIP_YYWRAP
#ifdef __cplusplus
-extern "C" int yywrap YY_PROTO(( void ));
+extern "C" int yywrap (void );
#else
-extern int yywrap YY_PROTO(( void ));
+extern int yywrap (void );
#endif
#endif
-#ifndef YY_NO_UNPUT
-static void yyunput YY_PROTO(( int c, char *buf_ptr ));
-#endif
+/* %not-for-header */
+
+ static void yyunput (int c,char *buf_ptr );
+
+/* %ok-for-header */
+
+/* %endif */
#ifndef yytext_ptr
-static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int ));
+static void yy_flex_strncpy (char *,yyconst char *,int );
#endif
#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen YY_PROTO(( yyconst char * ));
+static int yy_flex_strlen (yyconst char * );
#endif
#ifndef YY_NO_INPUT
+/* %if-c-only Standard (non-C++) definition */
+/* %not-for-header */
+
#ifdef __cplusplus
-static int yyinput YY_PROTO(( void ));
+static int yyinput (void );
#else
-static int input YY_PROTO(( void ));
-#endif
+static int input (void );
#endif
+/* %ok-for-header */
-#if YY_STACK_USED
-static int yy_start_stack_ptr = 0;
-static int yy_start_stack_depth = 0;
-static int *yy_start_stack = 0;
-#ifndef YY_NO_PUSH_STATE
-static void yy_push_state YY_PROTO(( int new_state ));
-#endif
-#ifndef YY_NO_POP_STATE
-static void yy_pop_state YY_PROTO(( void ));
-#endif
-#ifndef YY_NO_TOP_STATE
-static int yy_top_state YY_PROTO(( void ));
+/* %endif */
#endif
-#else
-#define YY_NO_PUSH_STATE 1
-#define YY_NO_POP_STATE 1
-#define YY_NO_TOP_STATE 1
-#endif
+/* %if-c-only */
-#ifdef YY_MALLOC_DECL
-YY_MALLOC_DECL
-#else
-#if __STDC__
-#ifndef __cplusplus
-#include <stdlib.h>
-#endif
-#else
-/* Just try to get by without declaring the routines. This will fail
- * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
- * or sizeof(void*) != sizeof(int).
- */
-#endif
-#endif
+/* %endif */
/* Amount of stuff to slurp up with each read. */
#ifndef YY_READ_BUF_SIZE
@@ -584,12 +751,15 @@ YY_MALLOC_DECL
#endif
/* Copy whatever the last rule matched to the standard output. */
-
#ifndef ECHO
+/* %if-c-only Standard (non-C++) definition */
/* This used to be an fputs(), but since the string might contain NUL's,
* we now use fwrite().
*/
#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+/* %endif */
+/* %if-c++-only C++ definition */
+/* %endif */
#endif
/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
@@ -597,9 +767,11 @@ YY_MALLOC_DECL
*/
#ifndef YY_INPUT
#define YY_INPUT(buf,result,max_size) \
- if ( yy_current_buffer->yy_is_interactive ) \
+/* %% [5.0] fread()/read() definition of YY_INPUT goes here unless we're doing C++ \ */\
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
{ \
- int c = '*', n; \
+ int c = '*'; \
+ size_t n; \
for ( n = 0; n < max_size && \
(c = getc( yyin )) != EOF && c != '\n'; ++n ) \
buf[n] = (char) c; \
@@ -609,9 +781,24 @@ YY_MALLOC_DECL
YY_FATAL_ERROR( "input in flex scanner failed" ); \
result = n; \
} \
- else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \
- && ferror( yyin ) ) \
- YY_FATAL_ERROR( "input in flex scanner failed" );
+ else \
+ { \
+ errno=0; \
+ while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+ { \
+ if( errno != EINTR) \
+ { \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ break; \
+ } \
+ errno=0; \
+ clearerr(yyin); \
+ } \
+ }\
+\
+/* %if-c++-only C++ definition \ */\
+/* %endif */
+
#endif
/* No semi-colon after return; correct usage is to write "yyterminate();" -
@@ -629,15 +816,40 @@ YY_MALLOC_DECL
/* Report a fatal error. */
#ifndef YY_FATAL_ERROR
+/* %if-c-only */
#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+/* %endif */
+/* %if-c++-only */
+/* %endif */
#endif
+/* %if-tables-serialization structures and prototypes */
+/* %not-for-header */
+
+/* %ok-for-header */
+
+/* %not-for-header */
+
+/* %tables-yydmap generated elements */
+/* %endif */
+/* end tables serialization structures and prototypes */
+
+/* %ok-for-header */
+
/* Default declaration of generated scanner - a define so the user can
* easily add parameters.
*/
#ifndef YY_DECL
-#define YY_DECL int yylex YY_PROTO(( void ))
-#endif
+#define YY_DECL_IS_OURS 1
+/* %if-c-only Standard (non-C++) definition */
+
+extern int yylex (void);
+
+#define YY_DECL int yylex (void)
+/* %endif */
+/* %if-c++-only C++ definition */
+/* %endif */
+#endif /* !YY_DECL */
/* Code executed at the beginning of each rule, after yytext and yyleng
* have been set up.
@@ -651,62 +863,80 @@ YY_MALLOC_DECL
#define YY_BREAK break;
#endif
+/* %% [6.0] YY_RULE_SETUP definition goes here */
#define YY_RULE_SETUP \
if ( yyleng > 0 ) \
- yy_current_buffer->yy_at_bol = \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
(yytext[yyleng - 1] == '\n'); \
YY_USER_ACTION
+/* %not-for-header */
+
+/** The main scanner function which does all the work.
+ */
YY_DECL
- {
+{
register yy_state_type yy_current_state;
- register char *yy_cp = NULL, *yy_bp = NULL;
+ register char *yy_cp, *yy_bp;
register int yy_act;
-
+
+/* %% [7.0] user's declarations go here */
#line 65 "scripts/genksyms/lex.l"
/* Keep track of our location in the original source files. */
-#line 672 "scripts/genksyms/lex.c"
+#line 890 "scripts/genksyms/lex.c"
- if ( yy_init )
+ if ( !(yy_init) )
{
- yy_init = 0;
+ (yy_init) = 1;
#ifdef YY_USER_INIT
YY_USER_INIT;
#endif
- if ( ! yy_start )
- yy_start = 1; /* first start state */
+ if ( ! (yy_start) )
+ (yy_start) = 1; /* first start state */
if ( ! yyin )
+/* %if-c-only */
yyin = stdin;
+/* %endif */
+/* %if-c++-only */
+/* %endif */
if ( ! yyout )
+/* %if-c-only */
yyout = stdout;
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+
+ if ( ! YY_CURRENT_BUFFER ) {
+ yyensure_buffer_stack ();
+ YY_CURRENT_BUFFER_LVALUE =
+ yy_create_buffer(yyin,YY_BUF_SIZE );
+ }
- if ( ! yy_current_buffer )
- yy_current_buffer =
- yy_create_buffer( yyin, YY_BUF_SIZE );
-
- yy_load_buffer_state();
+ yy_load_buffer_state( );
}
while ( 1 ) /* loops until end-of-file is reached */
{
- yy_cp = yy_c_buf_p;
+/* %% [8.0] yymore()-related code goes here */
+ yy_cp = (yy_c_buf_p);
/* Support of yytext. */
- *yy_cp = yy_hold_char;
+ *yy_cp = (yy_hold_char);
/* yy_bp points to the position in yy_ch_buf of the start of
* the current run.
*/
yy_bp = yy_cp;
- yy_current_state = yy_start;
+/* %% [9.0] code to set up and find next match goes here */
+ yy_current_state = (yy_start);
yy_current_state += YY_AT_BOL();
yy_match:
do
@@ -714,8 +944,8 @@ yy_match:
register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
if ( yy_accept[yy_current_state] )
{
- yy_last_accepting_state = yy_current_state;
- yy_last_accepting_cpos = yy_cp;
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
}
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
@@ -729,26 +959,29 @@ yy_match:
while ( yy_base[yy_current_state] != 284 );
yy_find_action:
+/* %% [10.0] code to find the action number goes here */
yy_act = yy_accept[yy_current_state];
if ( yy_act == 0 )
{ /* have to back up */
- yy_cp = yy_last_accepting_cpos;
- yy_current_state = yy_last_accepting_state;
+ yy_cp = (yy_last_accepting_cpos);
+ yy_current_state = (yy_last_accepting_state);
yy_act = yy_accept[yy_current_state];
}
YY_DO_BEFORE_ACTION;
+/* %% [11.0] code for yylineno update goes here */
do_action: /* This label is used only to access EOF actions. */
+/* %% [12.0] debug code goes here */
if ( yy_flex_debug )
{
if ( yy_act == 0 )
fprintf( stderr, "--scanner backing up\n" );
else if ( yy_act < 13 )
- fprintf( stderr, "--accepting rule at line %d (\"%s\")\n",
- yy_rule_linenum[yy_act], yytext );
+ fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n",
+ (long)yy_rule_linenum[yy_act], yytext );
else if ( yy_act == 13 )
fprintf( stderr, "--accepting default rule (\"%s\")\n",
yytext );
@@ -760,24 +993,28 @@ do_action: /* This label is used only to access EOF actions. */
switch ( yy_act )
{ /* beginning of action switch */
+/* %% [13.0] actions go here */
case 0: /* must back up */
/* undo the effects of YY_DO_BEFORE_ACTION */
- *yy_cp = yy_hold_char;
- yy_cp = yy_last_accepting_cpos;
- yy_current_state = yy_last_accepting_state;
+ *yy_cp = (yy_hold_char);
+ yy_cp = (yy_last_accepting_cpos);
+ yy_current_state = (yy_last_accepting_state);
goto yy_find_action;
case 1:
+/* rule 1 can match eol */
YY_RULE_SETUP
#line 69 "scripts/genksyms/lex.l"
return FILENAME;
YY_BREAK
case 2:
+/* rule 2 can match eol */
YY_RULE_SETUP
#line 70 "scripts/genksyms/lex.l"
cur_line++;
YY_BREAK
case 3:
+/* rule 3 can match eol */
YY_RULE_SETUP
#line 71 "scripts/genksyms/lex.l"
cur_line++;
@@ -789,11 +1026,13 @@ YY_RULE_SETUP
;
YY_BREAK
case 5:
+/* rule 5 can match eol */
YY_RULE_SETUP
#line 77 "scripts/genksyms/lex.l"
return STRING;
YY_BREAK
case 6:
+/* rule 6 can match eol */
YY_RULE_SETUP
#line 78 "scripts/genksyms/lex.l"
return CHAR;
@@ -838,7 +1077,7 @@ YY_RULE_SETUP
#line 95 "scripts/genksyms/lex.l"
ECHO;
YY_BREAK
-#line 842 "scripts/genksyms/lex.c"
+#line 1081 "scripts/genksyms/lex.c"
case YY_STATE_EOF(INITIAL):
case YY_STATE_EOF(V2_TOKENS):
yyterminate();
@@ -846,26 +1085,26 @@ case YY_STATE_EOF(V2_TOKENS):
case YY_END_OF_BUFFER:
{
/* Amount of text matched not including the EOB char. */
- int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1;
+ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
/* Undo the effects of YY_DO_BEFORE_ACTION. */
- *yy_cp = yy_hold_char;
+ *yy_cp = (yy_hold_char);
YY_RESTORE_YY_MORE_OFFSET
- if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW )
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
{
/* We're scanning a new file or input source. It's
* possible that this happened because the user
* just pointed yyin at a new source and called
* yylex(). If so, then we have to assure
- * consistency between yy_current_buffer and our
+ * consistency between YY_CURRENT_BUFFER and our
* globals. Here is the right place to do so, because
* this is the first action (other than possibly a
* back-up) that will match for the new input source.
*/
- yy_n_chars = yy_current_buffer->yy_n_chars;
- yy_current_buffer->yy_input_file = yyin;
- yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL;
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
}
/* Note that here we test for yy_c_buf_p "<=" to the position
@@ -875,13 +1114,13 @@ case YY_STATE_EOF(V2_TOKENS):
* end-of-buffer state). Contrast this with the test
* in input().
*/
- if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
{ /* This was really a NUL. */
yy_state_type yy_next_state;
- yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text;
+ (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
- yy_current_state = yy_get_previous_state();
+ yy_current_state = yy_get_previous_state( );
/* Okay, we're now positioned to make the NUL
* transition. We couldn't have
@@ -894,30 +1133,31 @@ case YY_STATE_EOF(V2_TOKENS):
yy_next_state = yy_try_NUL_trans( yy_current_state );
- yy_bp = yytext_ptr + YY_MORE_ADJ;
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
if ( yy_next_state )
{
/* Consume the NUL. */
- yy_cp = ++yy_c_buf_p;
+ yy_cp = ++(yy_c_buf_p);
yy_current_state = yy_next_state;
goto yy_match;
}
else
{
- yy_cp = yy_c_buf_p;
+/* %% [14.0] code to do back-up for compressed tables and set up yy_cp goes here */
+ yy_cp = (yy_c_buf_p);
goto yy_find_action;
}
}
- else switch ( yy_get_next_buffer() )
+ else switch ( yy_get_next_buffer( ) )
{
case EOB_ACT_END_OF_FILE:
{
- yy_did_buffer_switch_on_eof = 0;
+ (yy_did_buffer_switch_on_eof) = 0;
- if ( yywrap() )
+ if ( yywrap( ) )
{
/* Note: because we've taken care in
* yy_get_next_buffer() to have set up
@@ -928,7 +1168,7 @@ case YY_STATE_EOF(V2_TOKENS):
* YY_NULL, it'll still work - another
* YY_NULL will get returned.
*/
- yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
+ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
yy_act = YY_STATE_EOF(YY_START);
goto do_action;
@@ -936,30 +1176,30 @@ case YY_STATE_EOF(V2_TOKENS):
else
{
- if ( ! yy_did_buffer_switch_on_eof )
+ if ( ! (yy_did_buffer_switch_on_eof) )
YY_NEW_FILE;
}
break;
}
case EOB_ACT_CONTINUE_SCAN:
- yy_c_buf_p =
- yytext_ptr + yy_amount_of_matched_text;
+ (yy_c_buf_p) =
+ (yytext_ptr) + yy_amount_of_matched_text;
- yy_current_state = yy_get_previous_state();
+ yy_current_state = yy_get_previous_state( );
- yy_cp = yy_c_buf_p;
- yy_bp = yytext_ptr + YY_MORE_ADJ;
+ yy_cp = (yy_c_buf_p);
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
goto yy_match;
case EOB_ACT_LAST_MATCH:
- yy_c_buf_p =
- &yy_current_buffer->yy_ch_buf[yy_n_chars];
+ (yy_c_buf_p) =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
- yy_current_state = yy_get_previous_state();
+ yy_current_state = yy_get_previous_state( );
- yy_cp = yy_c_buf_p;
- yy_bp = yytext_ptr + YY_MORE_ADJ;
+ yy_cp = (yy_c_buf_p);
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
goto yy_find_action;
}
break;
@@ -970,8 +1210,15 @@ case YY_STATE_EOF(V2_TOKENS):
"fatal flex scanner internal error--no action found" );
} /* end of action switch */
} /* end of scanning one token */
- } /* end of yylex */
+} /* end of yylex */
+/* %ok-for-header */
+/* %if-c++-only */
+/* %not-for-header */
+
+/* %ok-for-header */
+
+/* %endif */
/* yy_get_next_buffer - try to read in a new buffer
*
@@ -980,21 +1227,24 @@ case YY_STATE_EOF(V2_TOKENS):
* EOB_ACT_CONTINUE_SCAN - continue scanning from current position
* EOB_ACT_END_OF_FILE - end of file
*/
-
-static int yy_get_next_buffer()
- {
- register char *dest = yy_current_buffer->yy_ch_buf;
- register char *source = yytext_ptr;
+/* %if-c-only */
+static int yy_get_next_buffer (void)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+ register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ register char *source = (yytext_ptr);
register int number_to_move, i;
int ret_val;
- if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
+ if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
YY_FATAL_ERROR(
"fatal flex scanner internal error--end of buffer missed" );
- if ( yy_current_buffer->yy_fill_buffer == 0 )
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
{ /* Don't try to fill the buffer, so this is an EOF. */
- if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 )
+ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
{
/* We matched a single character, the EOB, so
* treat this as a final EOF.
@@ -1014,34 +1264,30 @@ static int yy_get_next_buffer()
/* Try to read more data. */
/* First move last chars to start of buffer. */
- number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1;
+ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
for ( i = 0; i < number_to_move; ++i )
*(dest++) = *(source++);
- if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
/* don't do the read, it's not guaranteed to return an EOF,
* just force an EOF
*/
- yy_current_buffer->yy_n_chars = yy_n_chars = 0;
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
else
{
- int num_to_read =
- yy_current_buffer->yy_buf_size - number_to_move - 1;
+ int num_to_read =
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
while ( num_to_read <= 0 )
{ /* Not enough room in the buffer - grow it. */
-#ifdef YY_USES_REJECT
- YY_FATAL_ERROR(
-"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
-#else
/* just a shorter name for the current buffer */
- YY_BUFFER_STATE b = yy_current_buffer;
+ YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
int yy_c_buf_p_offset =
- (int) (yy_c_buf_p - b->yy_ch_buf);
+ (int) ((yy_c_buf_p) - b->yy_ch_buf);
if ( b->yy_is_our_buffer )
{
@@ -1054,8 +1300,7 @@ static int yy_get_next_buffer()
b->yy_ch_buf = (char *)
/* Include room in for 2 EOB chars. */
- yy_flex_realloc( (void *) b->yy_ch_buf,
- b->yy_buf_size + 2 );
+ yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 );
}
else
/* Can't grow it, we don't own it. */
@@ -1065,35 +1310,35 @@ static int yy_get_next_buffer()
YY_FATAL_ERROR(
"fatal error - scanner input buffer overflow" );
- yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+ (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
- num_to_read = yy_current_buffer->yy_buf_size -
+ num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
number_to_move - 1;
-#endif
+
}
if ( num_to_read > YY_READ_BUF_SIZE )
num_to_read = YY_READ_BUF_SIZE;
/* Read in more data. */
- YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
- yy_n_chars, num_to_read );
+ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+ (yy_n_chars), (size_t) num_to_read );
- yy_current_buffer->yy_n_chars = yy_n_chars;
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
}
- if ( yy_n_chars == 0 )
+ if ( (yy_n_chars) == 0 )
{
if ( number_to_move == YY_MORE_ADJ )
{
ret_val = EOB_ACT_END_OF_FILE;
- yyrestart( yyin );
+ yyrestart(yyin );
}
else
{
ret_val = EOB_ACT_LAST_MATCH;
- yy_current_buffer->yy_buffer_status =
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
YY_BUFFER_EOF_PENDING;
}
}
@@ -1101,33 +1346,40 @@ static int yy_get_next_buffer()
else
ret_val = EOB_ACT_CONTINUE_SCAN;
- yy_n_chars += number_to_move;
- yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
- yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+ (yy_n_chars) += number_to_move;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
- yytext_ptr = &yy_current_buffer->yy_ch_buf[0];
+ (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
return ret_val;
- }
-
+}
/* yy_get_previous_state - get the state just before the EOB char was reached */
-static yy_state_type yy_get_previous_state()
- {
+/* %if-c-only */
+/* %not-for-header */
+
+ static yy_state_type yy_get_previous_state (void)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
register yy_state_type yy_current_state;
register char *yy_cp;
-
- yy_current_state = yy_start;
+
+/* %% [15.0] code to get the start state into yy_current_state goes here */
+ yy_current_state = (yy_start);
yy_current_state += YY_AT_BOL();
- for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
+ for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
{
+/* %% [16.0] code to find the next state goes here */
register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
if ( yy_accept[yy_current_state] )
{
- yy_last_accepting_state = yy_current_state;
- yy_last_accepting_cpos = yy_cp;
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
}
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
@@ -1139,30 +1391,28 @@ static yy_state_type yy_get_previous_state()
}
return yy_current_state;
- }
-
+}
/* yy_try_NUL_trans - try to make a transition on the NUL character
*
* synopsis
* next_state = yy_try_NUL_trans( current_state );
*/
-
-#ifdef YY_USE_PROTOS
-static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state )
-#else
-static yy_state_type yy_try_NUL_trans( yy_current_state )
-yy_state_type yy_current_state;
-#endif
- {
+/* %if-c-only */
+ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state )
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
register int yy_is_jam;
- register char *yy_cp = yy_c_buf_p;
+ /* %% [17.0] code to find the next state, and perhaps do backing up, goes here */
+ register char *yy_cp = (yy_c_buf_p);
register YY_CHAR yy_c = 1;
if ( yy_accept[yy_current_state] )
{
- yy_last_accepting_state = yy_current_state;
- yy_last_accepting_cpos = yy_cp;
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
}
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
@@ -1174,80 +1424,87 @@ yy_state_type yy_current_state;
yy_is_jam = (yy_current_state == 75);
return yy_is_jam ? 0 : yy_current_state;
- }
+}
+/* %if-c-only */
-#ifndef YY_NO_UNPUT
-#ifdef YY_USE_PROTOS
-static void yyunput( int c, register char *yy_bp )
-#else
-static void yyunput( c, yy_bp )
-int c;
-register char *yy_bp;
-#endif
- {
- register char *yy_cp = yy_c_buf_p;
+ static void yyunput (int c, register char * yy_bp )
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+ register char *yy_cp;
+
+ yy_cp = (yy_c_buf_p);
/* undo effects of setting up yytext */
- *yy_cp = yy_hold_char;
+ *yy_cp = (yy_hold_char);
- if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
{ /* need to shift things up to make room */
/* +2 for EOB chars. */
- register int number_to_move = yy_n_chars + 2;
- register char *dest = &yy_current_buffer->yy_ch_buf[
- yy_current_buffer->yy_buf_size + 2];
+ register int number_to_move = (yy_n_chars) + 2;
+ register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
register char *source =
- &yy_current_buffer->yy_ch_buf[number_to_move];
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
- while ( source > yy_current_buffer->yy_ch_buf )
+ while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
*--dest = *--source;
yy_cp += (int) (dest - source);
yy_bp += (int) (dest - source);
- yy_current_buffer->yy_n_chars =
- yy_n_chars = yy_current_buffer->yy_buf_size;
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
- if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
YY_FATAL_ERROR( "flex scanner push-back overflow" );
}
*--yy_cp = (char) c;
+/* %% [18.0] update yylineno here */
- yytext_ptr = yy_bp;
- yy_hold_char = *yy_cp;
- yy_c_buf_p = yy_cp;
- }
-#endif /* ifndef YY_NO_UNPUT */
+ (yytext_ptr) = yy_bp;
+ (yy_hold_char) = *yy_cp;
+ (yy_c_buf_p) = yy_cp;
+}
+/* %if-c-only */
+/* %endif */
+/* %if-c-only */
+#ifndef YY_NO_INPUT
#ifdef __cplusplus
-static int yyinput()
+ static int yyinput (void)
#else
-static int input()
+ static int input (void)
#endif
- {
- int c;
- *yy_c_buf_p = yy_hold_char;
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+ int c;
+
+ *(yy_c_buf_p) = (yy_hold_char);
- if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+ if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
{
/* yy_c_buf_p now points to the character we want to return.
* If this occurs *before* the EOB characters, then it's a
* valid NUL; if not, then we've hit the end of the buffer.
*/
- if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
/* This was really a NUL. */
- *yy_c_buf_p = '\0';
+ *(yy_c_buf_p) = '\0';
else
{ /* need more input */
- int offset = yy_c_buf_p - yytext_ptr;
- ++yy_c_buf_p;
+ int offset = (yy_c_buf_p) - (yytext_ptr);
+ ++(yy_c_buf_p);
- switch ( yy_get_next_buffer() )
+ switch ( yy_get_next_buffer( ) )
{
case EOB_ACT_LAST_MATCH:
/* This happens because yy_g_n_b()
@@ -1261,16 +1518,16 @@ static int input()
*/
/* Reset buffer status. */
- yyrestart( yyin );
+ yyrestart(yyin );
- /* fall through */
+ /*FALLTHROUGH*/
case EOB_ACT_END_OF_FILE:
{
- if ( yywrap() )
+ if ( yywrap( ) )
return EOF;
- if ( ! yy_did_buffer_switch_on_eof )
+ if ( ! (yy_did_buffer_switch_on_eof) )
YY_NEW_FILE;
#ifdef __cplusplus
return yyinput();
@@ -1280,91 +1537,113 @@ static int input()
}
case EOB_ACT_CONTINUE_SCAN:
- yy_c_buf_p = yytext_ptr + offset;
+ (yy_c_buf_p) = (yytext_ptr) + offset;
break;
}
}
}
- c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */
- *yy_c_buf_p = '\0'; /* preserve yytext */
- yy_hold_char = *++yy_c_buf_p;
+ c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */
+ *(yy_c_buf_p) = '\0'; /* preserve yytext */
+ (yy_hold_char) = *++(yy_c_buf_p);
- yy_current_buffer->yy_at_bol = (c == '\n');
+/* %% [19.0] update BOL and yylineno */
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
return c;
+}
+/* %if-c-only */
+#endif /* ifndef YY_NO_INPUT */
+/* %endif */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ *
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+/* %if-c-only */
+ void yyrestart (FILE * input_file )
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+
+ if ( ! YY_CURRENT_BUFFER ){
+ yyensure_buffer_stack ();
+ YY_CURRENT_BUFFER_LVALUE =
+ yy_create_buffer(yyin,YY_BUF_SIZE );
}
+ yy_init_buffer(YY_CURRENT_BUFFER,input_file );
+ yy_load_buffer_state( );
+}
-#ifdef YY_USE_PROTOS
-void yyrestart( FILE *input_file )
-#else
-void yyrestart( input_file )
-FILE *input_file;
-#endif
- {
- if ( ! yy_current_buffer )
- yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE );
-
- yy_init_buffer( yy_current_buffer, input_file );
- yy_load_buffer_state();
- }
-
-
-#ifdef YY_USE_PROTOS
-void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
-#else
-void yy_switch_to_buffer( new_buffer )
-YY_BUFFER_STATE new_buffer;
-#endif
- {
- if ( yy_current_buffer == new_buffer )
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ *
+ */
+/* %if-c-only */
+ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer )
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+
+ /* TODO. We should be able to replace this entire function body
+ * with
+ * yypop_buffer_state();
+ * yypush_buffer_state(new_buffer);
+ */
+ yyensure_buffer_stack ();
+ if ( YY_CURRENT_BUFFER == new_buffer )
return;
- if ( yy_current_buffer )
+ if ( YY_CURRENT_BUFFER )
{
/* Flush out information for old buffer. */
- *yy_c_buf_p = yy_hold_char;
- yy_current_buffer->yy_buf_pos = yy_c_buf_p;
- yy_current_buffer->yy_n_chars = yy_n_chars;
+ *(yy_c_buf_p) = (yy_hold_char);
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
}
- yy_current_buffer = new_buffer;
- yy_load_buffer_state();
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+ yy_load_buffer_state( );
/* We don't actually know whether we did this switch during
* EOF (yywrap()) processing, but the only time this flag
* is looked at is after yywrap() is called, so it's safe
* to go ahead and always set it.
*/
- yy_did_buffer_switch_on_eof = 1;
- }
-
-
-#ifdef YY_USE_PROTOS
-void yy_load_buffer_state( void )
-#else
-void yy_load_buffer_state()
-#endif
- {
- yy_n_chars = yy_current_buffer->yy_n_chars;
- yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
- yyin = yy_current_buffer->yy_input_file;
- yy_hold_char = *yy_c_buf_p;
- }
+ (yy_did_buffer_switch_on_eof) = 1;
+}
+/* %if-c-only */
+static void yy_load_buffer_state (void)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+ yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+ (yy_hold_char) = *(yy_c_buf_p);
+}
-#ifdef YY_USE_PROTOS
-YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
-#else
-YY_BUFFER_STATE yy_create_buffer( file, size )
-FILE *file;
-int size;
-#endif
- {
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ *
+ * @return the allocated buffer state.
+ */
+/* %if-c-only */
+ YY_BUFFER_STATE yy_create_buffer (FILE * file, int size )
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
YY_BUFFER_STATE b;
-
- b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+
+ b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) );
if ( ! b )
YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
@@ -1373,75 +1652,99 @@ int size;
/* yy_ch_buf has to be 2 characters longer than the size given because
* we need to put in 2 end-of-buffer characters.
*/
- b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 );
+ b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 );
if ( ! b->yy_ch_buf )
YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
b->yy_is_our_buffer = 1;
- yy_init_buffer( b, file );
+ yy_init_buffer(b,file );
return b;
- }
-
+}
-#ifdef YY_USE_PROTOS
-void yy_delete_buffer( YY_BUFFER_STATE b )
-#else
-void yy_delete_buffer( b )
-YY_BUFFER_STATE b;
-#endif
- {
+/** Destroy the buffer.
+ * @param b a buffer created with yy_create_buffer()
+ *
+ */
+/* %if-c-only */
+ void yy_delete_buffer (YY_BUFFER_STATE b )
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+
if ( ! b )
return;
- if ( b == yy_current_buffer )
- yy_current_buffer = (YY_BUFFER_STATE) 0;
+ if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
if ( b->yy_is_our_buffer )
- yy_flex_free( (void *) b->yy_ch_buf );
+ yyfree((void *) b->yy_ch_buf );
- yy_flex_free( (void *) b );
- }
+ yyfree((void *) b );
+}
+/* %if-c-only */
+#ifndef __cplusplus
+extern int isatty (int );
+#endif /* __cplusplus */
+
+/* %endif */
-#ifdef YY_USE_PROTOS
-void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
-#else
-void yy_init_buffer( b, file )
-YY_BUFFER_STATE b;
-FILE *file;
-#endif
+/* %if-c++-only */
+/* %endif */
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a yyrestart() or at EOF.
+ */
+/* %if-c-only */
+ static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file )
+/* %endif */
+/* %if-c++-only */
+/* %endif */
- {
- yy_flush_buffer( b );
+{
+ int oerrno = errno;
+
+ yy_flush_buffer(b );
b->yy_input_file = file;
b->yy_fill_buffer = 1;
-#if YY_ALWAYS_INTERACTIVE
- b->yy_is_interactive = 1;
-#else
-#if YY_NEVER_INTERACTIVE
- b->yy_is_interactive = 0;
-#else
- b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
-#endif
-#endif
- }
+ /* If b is the current buffer, then yy_init_buffer was _probably_
+ * called from yyrestart() or through yy_get_next_buffer.
+ * In that case, we don't want to reset the lineno or column.
+ */
+ if (b != YY_CURRENT_BUFFER){
+ b->yy_bs_lineno = 1;
+ b->yy_bs_column = 0;
+ }
+/* %if-c-only */
-#ifdef YY_USE_PROTOS
-void yy_flush_buffer( YY_BUFFER_STATE b )
-#else
-void yy_flush_buffer( b )
-YY_BUFFER_STATE b;
-#endif
+ b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+ errno = oerrno;
+}
- {
- if ( ! b )
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ *
+ */
+/* %if-c-only */
+ void yy_flush_buffer (YY_BUFFER_STATE b )
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+ if ( ! b )
return;
b->yy_n_chars = 0;
@@ -1458,29 +1761,140 @@ YY_BUFFER_STATE b;
b->yy_at_bol = 1;
b->yy_buffer_status = YY_BUFFER_NEW;
- if ( b == yy_current_buffer )
- yy_load_buffer_state();
+ if ( b == YY_CURRENT_BUFFER )
+ yy_load_buffer_state( );
+}
+
+/* %if-c-or-c++ */
+/** Pushes the new state onto the stack. The new state becomes
+ * the current state. This function will allocate the stack
+ * if necessary.
+ * @param new_buffer The new state.
+ *
+ */
+/* %if-c-only */
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+ if (new_buffer == NULL)
+ return;
+
+ yyensure_buffer_stack();
+
+ /* This block is copied from yy_switch_to_buffer. */
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *(yy_c_buf_p) = (yy_hold_char);
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ /* Only push if top exists. Otherwise, replace top. */
+ if (YY_CURRENT_BUFFER)
+ (yy_buffer_stack_top)++;
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+ /* copied from yy_switch_to_buffer. */
+ yy_load_buffer_state( );
+ (yy_did_buffer_switch_on_eof) = 1;
+}
+/* %endif */
+
+/* %if-c-or-c++ */
+/** Removes and deletes the top of the stack, if present.
+ * The next element becomes the new top.
+ *
+ */
+/* %if-c-only */
+void yypop_buffer_state (void)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+ if (!YY_CURRENT_BUFFER)
+ return;
+
+ yy_delete_buffer(YY_CURRENT_BUFFER );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ if ((yy_buffer_stack_top) > 0)
+ --(yy_buffer_stack_top);
+
+ if (YY_CURRENT_BUFFER) {
+ yy_load_buffer_state( );
+ (yy_did_buffer_switch_on_eof) = 1;
}
+}
+/* %endif */
+/* %if-c-or-c++ */
+/* Allocates the stack if it does not exist.
+ * Guarantees space for at least one push.
+ */
+/* %if-c-only */
+static void yyensure_buffer_stack (void)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+ int num_to_alloc;
+
+ if (!(yy_buffer_stack)) {
+
+ /* First allocation is just for 2 elements, since we don't know if this
+ * scanner will even need a stack. We use 2 instead of 1 to avoid an
+ * immediate realloc on the next call.
+ */
+ num_to_alloc = 1;
+ (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
+ (num_to_alloc * sizeof(struct yy_buffer_state*)
+ );
+
+ memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+
+ (yy_buffer_stack_max) = num_to_alloc;
+ (yy_buffer_stack_top) = 0;
+ return;
+ }
-#ifndef YY_NO_SCAN_BUFFER
-#ifdef YY_USE_PROTOS
-YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size )
-#else
-YY_BUFFER_STATE yy_scan_buffer( base, size )
-char *base;
-yy_size_t size;
-#endif
- {
- YY_BUFFER_STATE b;
+ if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+ /* Increase the buffer to prepare for a possible push. */
+ int grow_size = 8 /* arbitrary grow size */;
+ num_to_alloc = (yy_buffer_stack_max) + grow_size;
+ (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
+ ((yy_buffer_stack),
+ num_to_alloc * sizeof(struct yy_buffer_state*)
+ );
+
+ /* zero only the new slots.*/
+ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+ (yy_buffer_stack_max) = num_to_alloc;
+ }
+}
+/* %endif */
+
+/* %if-c-only */
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ *
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size )
+{
+ YY_BUFFER_STATE b;
+
if ( size < 2 ||
base[size-2] != YY_END_OF_BUFFER_CHAR ||
base[size-1] != YY_END_OF_BUFFER_CHAR )
/* They forgot to leave room for the EOB's. */
return 0;
- b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+ b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) );
if ( ! b )
YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
@@ -1494,56 +1908,55 @@ yy_size_t size;
b->yy_fill_buffer = 0;
b->yy_buffer_status = YY_BUFFER_NEW;
- yy_switch_to_buffer( b );
+ yy_switch_to_buffer(b );
return b;
- }
-#endif
-
-
-#ifndef YY_NO_SCAN_STRING
-#ifdef YY_USE_PROTOS
-YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str )
-#else
-YY_BUFFER_STATE yy_scan_string( yy_str )
-yyconst char *yy_str;
-#endif
- {
- int len;
- for ( len = 0; yy_str[len]; ++len )
- ;
-
- return yy_scan_bytes( yy_str, len );
- }
-#endif
-
-
-#ifndef YY_NO_SCAN_BYTES
-#ifdef YY_USE_PROTOS
-YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len )
-#else
-YY_BUFFER_STATE yy_scan_bytes( bytes, len )
-yyconst char *bytes;
-int len;
-#endif
- {
+}
+/* %endif */
+
+/* %if-c-only */
+/** Setup the input buffer state to scan a string. The next call to yylex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ *
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ * yy_scan_bytes() instead.
+ */
+YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
+{
+
+ return yy_scan_bytes(yystr,strlen(yystr) );
+}
+/* %endif */
+
+/* %if-c-only */
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
+ * scan from a @e copy of @a bytes.
+ * @param bytes the byte buffer to scan
+ * @param len the number of bytes in the buffer pointed to by @a bytes.
+ *
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len )
+{
YY_BUFFER_STATE b;
char *buf;
yy_size_t n;
int i;
-
+
/* Get memory for full buffer, including space for trailing EOB's. */
- n = len + 2;
- buf = (char *) yy_flex_alloc( n );
+ n = _yybytes_len + 2;
+ buf = (char *) yyalloc(n );
if ( ! buf )
YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
- for ( i = 0; i < len; ++i )
- buf[i] = bytes[i];
+ for ( i = 0; i < _yybytes_len; ++i )
+ buf[i] = yybytes[i];
- buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
+ buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
- b = yy_scan_buffer( buf, n );
+ b = yy_scan_buffer(buf,n );
if ( ! b )
YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
@@ -1553,148 +1966,231 @@ int len;
b->yy_is_our_buffer = 1;
return b;
- }
+}
+/* %endif */
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
#endif
+/* %if-c-only */
+static void yy_fatal_error (yyconst char* msg )
+{
+ (void) fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+}
+/* %endif */
+/* %if-c++-only */
+/* %endif */
-#ifndef YY_NO_PUSH_STATE
-#ifdef YY_USE_PROTOS
-static void yy_push_state( int new_state )
-#else
-static void yy_push_state( new_state )
-int new_state;
-#endif
- {
- if ( yy_start_stack_ptr >= yy_start_stack_depth )
- {
- yy_size_t new_size;
+/* Redefine yyless() so it works in section 3 code. */
- yy_start_stack_depth += YY_START_STACK_INCR;
- new_size = yy_start_stack_depth * sizeof( int );
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ yytext[yyleng] = (yy_hold_char); \
+ (yy_c_buf_p) = yytext + yyless_macro_arg; \
+ (yy_hold_char) = *(yy_c_buf_p); \
+ *(yy_c_buf_p) = '\0'; \
+ yyleng = yyless_macro_arg; \
+ } \
+ while ( 0 )
- if ( ! yy_start_stack )
- yy_start_stack = (int *) yy_flex_alloc( new_size );
+/* Accessor methods (get/set functions) to struct members. */
- else
- yy_start_stack = (int *) yy_flex_realloc(
- (void *) yy_start_stack, new_size );
+/* %if-c-only */
+/* %if-reentrant */
+/* %endif */
- if ( ! yy_start_stack )
- YY_FATAL_ERROR(
- "out of memory expanding start-condition stack" );
- }
+/** Get the current line number.
+ *
+ */
+int yyget_lineno (void)
+{
+
+ return yylineno;
+}
- yy_start_stack[yy_start_stack_ptr++] = YY_START;
+/** Get the input stream.
+ *
+ */
+FILE *yyget_in (void)
+{
+ return yyin;
+}
- BEGIN(new_state);
- }
-#endif
+/** Get the output stream.
+ *
+ */
+FILE *yyget_out (void)
+{
+ return yyout;
+}
+/** Get the length of the current token.
+ *
+ */
+int yyget_leng (void)
+{
+ return yyleng;
+}
-#ifndef YY_NO_POP_STATE
-static void yy_pop_state()
- {
- if ( --yy_start_stack_ptr < 0 )
- YY_FATAL_ERROR( "start-condition stack underflow" );
+/** Get the current token.
+ *
+ */
- BEGIN(yy_start_stack[yy_start_stack_ptr]);
- }
-#endif
+char *yyget_text (void)
+{
+ return yytext;
+}
+/* %if-reentrant */
+/* %endif */
-#ifndef YY_NO_TOP_STATE
-static int yy_top_state()
- {
- return yy_start_stack[yy_start_stack_ptr - 1];
- }
-#endif
+/** Set the current line number.
+ * @param line_number
+ *
+ */
+void yyset_lineno (int line_number )
+{
+
+ yylineno = line_number;
+}
-#ifndef YY_EXIT_FAILURE
-#define YY_EXIT_FAILURE 2
-#endif
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ *
+ * @see yy_switch_to_buffer
+ */
+void yyset_in (FILE * in_str )
+{
+ yyin = in_str ;
+}
+
+void yyset_out (FILE * out_str )
+{
+ yyout = out_str ;
+}
+
+int yyget_debug (void)
+{
+ return yy_flex_debug;
+}
-#ifdef YY_USE_PROTOS
-static void yy_fatal_error( yyconst char msg[] )
+void yyset_debug (int bdebug )
+{
+ yy_flex_debug = bdebug ;
+}
+
+/* %endif */
+
+/* %if-reentrant */
+/* %if-bison-bridge */
+/* %endif */
+/* %endif */
+
+/* %if-c-only */
+static int yy_init_globals (void)
+{
+ /* Initialization is the same as for the non-reentrant scanner.
+ * This function is called from yylex_destroy(), so don't allocate here.
+ */
+
+ (yy_buffer_stack) = 0;
+ (yy_buffer_stack_top) = 0;
+ (yy_buffer_stack_max) = 0;
+ (yy_c_buf_p) = (char *) 0;
+ (yy_init) = 0;
+ (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+ yyin = stdin;
+ yyout = stdout;
#else
-static void yy_fatal_error( msg )
-char msg[];
+ yyin = (FILE *) 0;
+ yyout = (FILE *) 0;
#endif
- {
- (void) fprintf( stderr, "%s\n", msg );
- exit( YY_EXIT_FAILURE );
+
+ /* For future reference: Set errno on error, since we are called by
+ * yylex_init()
+ */
+ return 0;
+}
+/* %endif */
+
+/* %if-c-or-c++ */
+/* %if-c-only */
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy (void)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+
+ /* Pop the buffer stack, destroying each element. */
+ while(YY_CURRENT_BUFFER){
+ yy_delete_buffer(YY_CURRENT_BUFFER );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ yypop_buffer_state();
}
+ /* Destroy the stack itself. */
+ yyfree((yy_buffer_stack) );
+ (yy_buffer_stack) = NULL;
+/* %if-c++-only */
+/* %endif */
-/* Redefine yyless() so it works in section 3 code. */
+/* %if-c-only */
-#undef yyless
-#define yyless(n) \
- do \
- { \
- /* Undo effects of setting up yytext. */ \
- yytext[yyleng] = yy_hold_char; \
- yy_c_buf_p = yytext + n; \
- yy_hold_char = *yy_c_buf_p; \
- *yy_c_buf_p = '\0'; \
- yyleng = n; \
- } \
- while ( 0 )
+ /* Reset the globals. This is important in a non-reentrant scanner so the next time
+ * yylex() is called, initialization will occur. */
+ yy_init_globals( );
+/* %if-reentrant */
+/* %endif */
+ return 0;
+/* %endif */
+}
+/* %endif */
-/* Internal utility routines. */
+/*
+ * Internal utility routines.
+ */
#ifndef yytext_ptr
-#ifdef YY_USE_PROTOS
-static void yy_flex_strncpy( char *s1, yyconst char *s2, int n )
-#else
-static void yy_flex_strncpy( s1, s2, n )
-char *s1;
-yyconst char *s2;
-int n;
-#endif
- {
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
register int i;
for ( i = 0; i < n; ++i )
s1[i] = s2[i];
- }
+}
#endif
#ifdef YY_NEED_STRLEN
-#ifdef YY_USE_PROTOS
-static int yy_flex_strlen( yyconst char *s )
-#else
-static int yy_flex_strlen( s )
-yyconst char *s;
-#endif
- {
+static int yy_flex_strlen (yyconst char * s )
+{
register int n;
for ( n = 0; s[n]; ++n )
;
return n;
- }
+}
#endif
-
-#ifdef YY_USE_PROTOS
-static void *yy_flex_alloc( yy_size_t size )
-#else
-static void *yy_flex_alloc( size )
-yy_size_t size;
-#endif
- {
+void *yyalloc (yy_size_t size )
+{
return (void *) malloc( size );
- }
+}
-#ifdef YY_USE_PROTOS
-static void *yy_flex_realloc( void *ptr, yy_size_t size )
-#else
-static void *yy_flex_realloc( ptr, size )
-void *ptr;
-yy_size_t size;
-#endif
- {
+void *yyrealloc (void * ptr, yy_size_t size )
+{
/* The cast to (char *) in the following accommodates both
* implementations that use char* generic pointers, and those
* that use void* generic pointers. It works with the latter
@@ -1703,28 +2199,24 @@ yy_size_t size;
* as though doing an assignment.
*/
return (void *) realloc( (char *) ptr, size );
- }
+}
-#ifdef YY_USE_PROTOS
-static void yy_flex_free( void *ptr )
-#else
-static void yy_flex_free( ptr )
-void *ptr;
-#endif
- {
- free( ptr );
- }
+void yyfree (void * ptr )
+{
+ free( (char *) ptr ); /* see yyrealloc() for (char *) cast */
+}
+
+/* %if-tables-serialization definitions */
+/* %define-yytables The name for this specific scanner's tables. */
+#define YYTABLES_NAME "yytables"
+/* %endif */
+
+/* %ok-for-header */
-#if YY_MAIN
-int main()
- {
- yylex();
- return 0;
- }
-#endif
#line 95 "scripts/genksyms/lex.l"
+
/* Bring in the keyword recognizer. */
#include "keywords.c"
@@ -2036,10 +2528,12 @@ fini:
return token;
}
-/* A Bison parser, made by GNU Bison 2.0. */
+/* A Bison parser, made by GNU Bison 2.3. */
+
+/* Skeleton interface for Bison's Yacc-like parsers in C
-/* Skeleton parser for Yacc-like parsing with Bison,
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
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
@@ -2053,13 +2547,21 @@ fini:
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. */
-
-/* As a special exception, when this file is copied by Bison into a
- Bison output file, you may use that output file without restriction.
- This special exception was added by the Free Software Foundation
- in version 1.24 of Bison. */
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
/* Tokens. */
#ifndef YYTOKENTYPE
@@ -2076,39 +2578,41 @@ fini:
DOUBLE_KEYW = 264,
ENUM_KEYW = 265,
EXTERN_KEYW = 266,
- FLOAT_KEYW = 267,
- INLINE_KEYW = 268,
- INT_KEYW = 269,
- LONG_KEYW = 270,
- REGISTER_KEYW = 271,
- RESTRICT_KEYW = 272,
- SHORT_KEYW = 273,
- SIGNED_KEYW = 274,
- STATIC_KEYW = 275,
- STRUCT_KEYW = 276,
- TYPEDEF_KEYW = 277,
- UNION_KEYW = 278,
- UNSIGNED_KEYW = 279,
- VOID_KEYW = 280,
- VOLATILE_KEYW = 281,
- TYPEOF_KEYW = 282,
- EXPORT_SYMBOL_KEYW = 283,
- ASM_PHRASE = 284,
- ATTRIBUTE_PHRASE = 285,
- BRACE_PHRASE = 286,
- BRACKET_PHRASE = 287,
- EXPRESSION_PHRASE = 288,
- CHAR = 289,
- DOTS = 290,
- IDENT = 291,
- INT = 292,
- REAL = 293,
- STRING = 294,
- TYPE = 295,
- OTHER = 296,
- FILENAME = 297
+ EXTENSION_KEYW = 267,
+ FLOAT_KEYW = 268,
+ INLINE_KEYW = 269,
+ INT_KEYW = 270,
+ LONG_KEYW = 271,
+ REGISTER_KEYW = 272,
+ RESTRICT_KEYW = 273,
+ SHORT_KEYW = 274,
+ SIGNED_KEYW = 275,
+ STATIC_KEYW = 276,
+ STRUCT_KEYW = 277,
+ TYPEDEF_KEYW = 278,
+ UNION_KEYW = 279,
+ UNSIGNED_KEYW = 280,
+ VOID_KEYW = 281,
+ VOLATILE_KEYW = 282,
+ TYPEOF_KEYW = 283,
+ EXPORT_SYMBOL_KEYW = 284,
+ ASM_PHRASE = 285,
+ ATTRIBUTE_PHRASE = 286,
+ BRACE_PHRASE = 287,
+ BRACKET_PHRASE = 288,
+ EXPRESSION_PHRASE = 289,
+ CHAR = 290,
+ DOTS = 291,
+ IDENT = 292,
+ INT = 293,
+ REAL = 294,
+ STRING = 295,
+ TYPE = 296,
+ OTHER = 297,
+ FILENAME = 298
};
#endif
+/* Tokens. */
#define ASM_KEYW 258
#define ATTRIBUTE_KEYW 259
#define AUTO_KEYW 260
@@ -2118,42 +2622,43 @@ fini:
#define DOUBLE_KEYW 264
#define ENUM_KEYW 265
#define EXTERN_KEYW 266
-#define FLOAT_KEYW 267
-#define INLINE_KEYW 268
-#define INT_KEYW 269
-#define LONG_KEYW 270
-#define REGISTER_KEYW 271
-#define RESTRICT_KEYW 272
-#define SHORT_KEYW 273
-#define SIGNED_KEYW 274
-#define STATIC_KEYW 275
-#define STRUCT_KEYW 276
-#define TYPEDEF_KEYW 277
-#define UNION_KEYW 278
-#define UNSIGNED_KEYW 279
-#define VOID_KEYW 280
-#define VOLATILE_KEYW 281
-#define TYPEOF_KEYW 282
-#define EXPORT_SYMBOL_KEYW 283
-#define ASM_PHRASE 284
-#define ATTRIBUTE_PHRASE 285
-#define BRACE_PHRASE 286
-#define BRACKET_PHRASE 287
-#define EXPRESSION_PHRASE 288
-#define CHAR 289
-#define DOTS 290
-#define IDENT 291
-#define INT 292
-#define REAL 293
-#define STRING 294
-#define TYPE 295
-#define OTHER 296
-#define FILENAME 297
-
-
-
-
-#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
+#define EXTENSION_KEYW 267
+#define FLOAT_KEYW 268
+#define INLINE_KEYW 269
+#define INT_KEYW 270
+#define LONG_KEYW 271
+#define REGISTER_KEYW 272
+#define RESTRICT_KEYW 273
+#define SHORT_KEYW 274
+#define SIGNED_KEYW 275
+#define STATIC_KEYW 276
+#define STRUCT_KEYW 277
+#define TYPEDEF_KEYW 278
+#define UNION_KEYW 279
+#define UNSIGNED_KEYW 280
+#define VOID_KEYW 281
+#define VOLATILE_KEYW 282
+#define TYPEOF_KEYW 283
+#define EXPORT_SYMBOL_KEYW 284
+#define ASM_PHRASE 285
+#define ATTRIBUTE_PHRASE 286
+#define BRACE_PHRASE 287
+#define BRACKET_PHRASE 288
+#define EXPRESSION_PHRASE 289
+#define CHAR 290
+#define DOTS 291
+#define IDENT 292
+#define INT 293
+#define REAL 294
+#define STRING 295
+#define TYPE 296
+#define OTHER 297
+#define FILENAME 298
+
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef int YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
@@ -2163,4 +2668,3 @@ typedef int YYSTYPE;
extern YYSTYPE yylval;
-
diff --git a/scripts/genksyms/parse.c_shipped b/scripts/genksyms/parse.c_shipped
index 99d7c258696d..3e6079f36b9f 100644
--- a/scripts/genksyms/parse.c_shipped
+++ b/scripts/genksyms/parse.c_shipped
@@ -1,7 +1,9 @@
-/* A Bison parser, made by GNU Bison 2.0. */
+/* A Bison parser, made by GNU Bison 2.3. */
-/* Skeleton parser for Yacc-like parsing with Bison,
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
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
@@ -15,16 +17,24 @@
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. */
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
-/* As a special exception, when this file is copied by Bison into a
- Bison output file, you may use that output file without restriction.
- This special exception was added by the Free Software Foundation
- in version 1.24 of Bison. */
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
-/* Written by Richard Stallman by simplifying the original so called
- ``semantic'' parser. */
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
/* All symbols defined below should begin with yy or YY, to avoid
infringing on user name space. This should be done even for local
@@ -36,6 +46,9 @@
/* Identify Bison output. */
#define YYBISON 1
+/* Bison version. */
+#define YYBISON_VERSION "2.3"
+
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -62,39 +75,41 @@
DOUBLE_KEYW = 264,
ENUM_KEYW = 265,
EXTERN_KEYW = 266,
- FLOAT_KEYW = 267,
- INLINE_KEYW = 268,
- INT_KEYW = 269,
- LONG_KEYW = 270,
- REGISTER_KEYW = 271,
- RESTRICT_KEYW = 272,
- SHORT_KEYW = 273,
- SIGNED_KEYW = 274,
- STATIC_KEYW = 275,
- STRUCT_KEYW = 276,
- TYPEDEF_KEYW = 277,
- UNION_KEYW = 278,
- UNSIGNED_KEYW = 279,
- VOID_KEYW = 280,
- VOLATILE_KEYW = 281,
- TYPEOF_KEYW = 282,
- EXPORT_SYMBOL_KEYW = 283,
- ASM_PHRASE = 284,
- ATTRIBUTE_PHRASE = 285,
- BRACE_PHRASE = 286,
- BRACKET_PHRASE = 287,
- EXPRESSION_PHRASE = 288,
- CHAR = 289,
- DOTS = 290,
- IDENT = 291,
- INT = 292,
- REAL = 293,
- STRING = 294,
- TYPE = 295,
- OTHER = 296,
- FILENAME = 297
+ EXTENSION_KEYW = 267,
+ FLOAT_KEYW = 268,
+ INLINE_KEYW = 269,
+ INT_KEYW = 270,
+ LONG_KEYW = 271,
+ REGISTER_KEYW = 272,
+ RESTRICT_KEYW = 273,
+ SHORT_KEYW = 274,
+ SIGNED_KEYW = 275,
+ STATIC_KEYW = 276,
+ STRUCT_KEYW = 277,
+ TYPEDEF_KEYW = 278,
+ UNION_KEYW = 279,
+ UNSIGNED_KEYW = 280,
+ VOID_KEYW = 281,
+ VOLATILE_KEYW = 282,
+ TYPEOF_KEYW = 283,
+ EXPORT_SYMBOL_KEYW = 284,
+ ASM_PHRASE = 285,
+ ATTRIBUTE_PHRASE = 286,
+ BRACE_PHRASE = 287,
+ BRACKET_PHRASE = 288,
+ EXPRESSION_PHRASE = 289,
+ CHAR = 290,
+ DOTS = 291,
+ IDENT = 292,
+ INT = 293,
+ REAL = 294,
+ STRING = 295,
+ TYPE = 296,
+ OTHER = 297,
+ FILENAME = 298
};
#endif
+/* Tokens. */
#define ASM_KEYW 258
#define ATTRIBUTE_KEYW 259
#define AUTO_KEYW 260
@@ -104,37 +119,38 @@
#define DOUBLE_KEYW 264
#define ENUM_KEYW 265
#define EXTERN_KEYW 266
-#define FLOAT_KEYW 267
-#define INLINE_KEYW 268
-#define INT_KEYW 269
-#define LONG_KEYW 270
-#define REGISTER_KEYW 271
-#define RESTRICT_KEYW 272
-#define SHORT_KEYW 273
-#define SIGNED_KEYW 274
-#define STATIC_KEYW 275
-#define STRUCT_KEYW 276
-#define TYPEDEF_KEYW 277
-#define UNION_KEYW 278
-#define UNSIGNED_KEYW 279
-#define VOID_KEYW 280
-#define VOLATILE_KEYW 281
-#define TYPEOF_KEYW 282
-#define EXPORT_SYMBOL_KEYW 283
-#define ASM_PHRASE 284
-#define ATTRIBUTE_PHRASE 285
-#define BRACE_PHRASE 286
-#define BRACKET_PHRASE 287
-#define EXPRESSION_PHRASE 288
-#define CHAR 289
-#define DOTS 290
-#define IDENT 291
-#define INT 292
-#define REAL 293
-#define STRING 294
-#define TYPE 295
-#define OTHER 296
-#define FILENAME 297
+#define EXTENSION_KEYW 267
+#define FLOAT_KEYW 268
+#define INLINE_KEYW 269
+#define INT_KEYW 270
+#define LONG_KEYW 271
+#define REGISTER_KEYW 272
+#define RESTRICT_KEYW 273
+#define SHORT_KEYW 274
+#define SIGNED_KEYW 275
+#define STATIC_KEYW 276
+#define STRUCT_KEYW 277
+#define TYPEDEF_KEYW 278
+#define UNION_KEYW 279
+#define UNSIGNED_KEYW 280
+#define VOID_KEYW 281
+#define VOLATILE_KEYW 282
+#define TYPEOF_KEYW 283
+#define EXPORT_SYMBOL_KEYW 284
+#define ASM_PHRASE 285
+#define ATTRIBUTE_PHRASE 286
+#define BRACE_PHRASE 287
+#define BRACKET_PHRASE 288
+#define EXPRESSION_PHRASE 289
+#define CHAR 290
+#define DOTS 291
+#define IDENT 292
+#define INT 293
+#define REAL 294
+#define STRING 295
+#define TYPE 296
+#define OTHER 297
+#define FILENAME 298
@@ -185,7 +201,12 @@ remove_list(struct string_list **pb, struct string_list **pe)
# define YYERROR_VERBOSE 0
#endif
-#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
+/* Enabling the token table. */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef int YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
@@ -197,17 +218,94 @@ typedef int YYSTYPE;
/* Copy the second part of user declarations. */
-/* Line 213 of yacc.c. */
-#line 202 "scripts/genksyms/parse.c"
+/* Line 216 of yacc.c. */
+#line 223 "scripts/genksyms/parse.c"
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned int
+# endif
+#endif
-#if ! defined (yyoverflow) || YYERROR_VERBOSE
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
-# ifndef YYFREE
-# define YYFREE free
+#ifndef YY_
+# if YYENABLE_NLS
+# if ENABLE_NLS
+# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_(msgid) dgettext ("bison-runtime", msgid)
+# endif
# endif
-# ifndef YYMALLOC
-# define YYMALLOC malloc
+# ifndef YY_
+# define YY_(msgid) msgid
# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E. */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions. */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int i)
+#else
+static int
+YYID (i)
+ int i;
+#endif
+{
+ return i;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
/* The parser invokes alloca or malloc; define the necessary symbols. */
@@ -215,34 +313,76 @@ typedef int YYSTYPE;
# if YYSTACK_USE_ALLOCA
# ifdef __GNUC__
# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
# else
# define YYSTACK_ALLOC alloca
+# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
# endif
# endif
# endif
# ifdef YYSTACK_ALLOC
- /* Pacify GCC's `empty if-body' warning. */
-# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
-# else
-# if defined (__STDC__) || defined (__cplusplus)
-# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-# define YYSIZE_T size_t
+ /* Pacify GCC's `empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+# ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
+ to allow for a few compiler-allocated temporary stack slots. */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
# endif
+# else
# define YYSTACK_ALLOC YYMALLOC
# define YYSTACK_FREE YYFREE
+# ifndef YYSTACK_ALLOC_MAXIMUM
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+# endif
+# if (defined __cplusplus && ! defined _STDLIB_H \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
# endif
-#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
-#if (! defined (yyoverflow) \
- && (! defined (__cplusplus) \
- || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL)))
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
/* A type that is properly aligned for any stack member. */
union yyalloc
{
- short int yyss;
+ yytype_int16 yyss;
YYSTYPE yyvs;
};
@@ -252,24 +392,24 @@ union yyalloc
/* The size of an array large to enough to hold all stacks, each with
N elements. */
# define YYSTACK_BYTES(N) \
- ((N) * (sizeof (short int) + sizeof (YYSTYPE)) \
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ YYSTACK_GAP_MAXIMUM)
/* Copy COUNT objects from FROM to TO. The source and destination do
not overlap. */
# ifndef YYCOPY
-# if defined (__GNUC__) && 1 < __GNUC__
+# if defined __GNUC__ && 1 < __GNUC__
# define YYCOPY(To, From, Count) \
__builtin_memcpy (To, From, (Count) * sizeof (*(From)))
# else
# define YYCOPY(To, From, Count) \
do \
{ \
- register YYSIZE_T yyi; \
+ YYSIZE_T yyi; \
for (yyi = 0; yyi < (Count); yyi++) \
(To)[yyi] = (From)[yyi]; \
} \
- while (0)
+ while (YYID (0))
# endif
# endif
@@ -287,53 +427,47 @@ union yyalloc
yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
yyptr += yynewbytes / sizeof (*yyptr); \
} \
- while (0)
+ while (YYID (0))
#endif
-#if defined (__STDC__) || defined (__cplusplus)
- typedef signed char yysigned_char;
-#else
- typedef short int yysigned_char;
-#endif
-
-/* YYFINAL -- State number of the termination state. */
+/* YYFINAL -- State number of the termination state. */
#define YYFINAL 4
/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 535
+#define YYLAST 523
-/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 52
-/* YYNNTS -- Number of nonterminals. */
-#define YYNNTS 45
-/* YYNRULES -- Number of rules. */
-#define YYNRULES 124
-/* YYNRULES -- Number of states. */
-#define YYNSTATES 174
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 53
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 46
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 126
+/* YYNRULES -- Number of states. */
+#define YYNSTATES 178
/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
#define YYUNDEFTOK 2
-#define YYMAXUTOK 297
+#define YYMAXUTOK 298
-#define YYTRANSLATE(YYX) \
+#define YYTRANSLATE(YYX) \
((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
-static const unsigned char yytranslate[] =
+static const yytype_uint8 yytranslate[] =
{
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 46, 48, 47, 2, 45, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 51, 43,
- 2, 49, 2, 2, 2, 2, 2, 2, 2, 2,
+ 47, 49, 48, 2, 46, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 52, 44,
+ 2, 50, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 50, 2, 44, 2, 2, 2, 2,
+ 2, 2, 2, 51, 2, 45, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -350,114 +484,116 @@ static const unsigned char yytranslate[] =
5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
- 35, 36, 37, 38, 39, 40, 41, 42
+ 35, 36, 37, 38, 39, 40, 41, 42, 43
};
#if YYDEBUG
/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
YYRHS. */
-static const unsigned short int yyprhs[] =
+static const yytype_uint16 yyprhs[] =
{
- 0, 0, 3, 5, 8, 9, 12, 13, 17, 19,
- 21, 23, 25, 28, 31, 35, 36, 38, 40, 44,
- 49, 50, 52, 54, 57, 59, 61, 63, 65, 67,
- 69, 71, 73, 75, 81, 86, 89, 92, 95, 99,
- 103, 107, 110, 113, 116, 118, 120, 122, 124, 126,
- 128, 130, 132, 134, 136, 138, 141, 142, 144, 146,
- 149, 151, 153, 155, 157, 160, 162, 164, 169, 174,
- 177, 181, 185, 188, 190, 192, 194, 199, 204, 207,
- 211, 215, 218, 220, 224, 225, 227, 229, 233, 236,
- 239, 241, 242, 244, 246, 251, 256, 259, 263, 267,
- 271, 272, 274, 277, 281, 285, 286, 288, 290, 293,
- 297, 300, 301, 303, 305, 309, 312, 315, 317, 320,
- 321, 323, 326, 327, 329
+ 0, 0, 3, 5, 8, 9, 12, 13, 18, 19,
+ 23, 25, 27, 29, 31, 34, 37, 41, 42, 44,
+ 46, 50, 55, 56, 58, 60, 63, 65, 67, 69,
+ 71, 73, 75, 77, 79, 81, 87, 92, 95, 98,
+ 101, 105, 109, 113, 116, 119, 122, 124, 126, 128,
+ 130, 132, 134, 136, 138, 140, 142, 144, 147, 148,
+ 150, 152, 155, 157, 159, 161, 163, 166, 168, 170,
+ 175, 180, 183, 187, 191, 194, 196, 198, 200, 205,
+ 210, 213, 217, 221, 224, 226, 230, 231, 233, 235,
+ 239, 242, 245, 247, 248, 250, 252, 257, 262, 265,
+ 269, 273, 277, 278, 280, 283, 287, 291, 292, 294,
+ 296, 299, 303, 306, 307, 309, 311, 315, 318, 321,
+ 323, 326, 327, 329, 332, 333, 335
};
-/* YYRHS -- A `-1'-separated list of the rules' RHS. */
-static const yysigned_char yyrhs[] =
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yytype_int8 yyrhs[] =
{
- 53, 0, -1, 54, -1, 53, 54, -1, -1, 55,
- 56, -1, -1, 22, 57, 58, -1, 58, -1, 82,
- -1, 94, -1, 96, -1, 1, 43, -1, 1, 44,
- -1, 62, 59, 43, -1, -1, 60, -1, 61, -1,
- 60, 45, 61, -1, 72, 95, 93, 83, -1, -1,
- 63, -1, 64, -1, 63, 64, -1, 65, -1, 66,
- -1, 5, -1, 16, -1, 20, -1, 11, -1, 13,
- -1, 67, -1, 71, -1, 27, 46, 63, 47, 48,
- -1, 27, 46, 63, 48, -1, 21, 36, -1, 23,
- 36, -1, 10, 36, -1, 21, 36, 85, -1, 23,
- 36, 85, -1, 10, 36, 31, -1, 10, 31, -1,
- 21, 85, -1, 23, 85, -1, 7, -1, 18, -1,
- 14, -1, 15, -1, 19, -1, 24, -1, 12, -1,
- 9, -1, 25, -1, 6, -1, 40, -1, 47, 69,
- -1, -1, 70, -1, 71, -1, 70, 71, -1, 8,
- -1, 26, -1, 30, -1, 17, -1, 68, 72, -1,
- 73, -1, 36, -1, 73, 46, 76, 48, -1, 73,
- 46, 1, 48, -1, 73, 32, -1, 46, 72, 48,
- -1, 46, 1, 48, -1, 68, 74, -1, 75, -1,
- 36, -1, 40, -1, 75, 46, 76, 48, -1, 75,
- 46, 1, 48, -1, 75, 32, -1, 46, 74, 48,
- -1, 46, 1, 48, -1, 77, 35, -1, 77, -1,
- 78, 45, 35, -1, -1, 78, -1, 79, -1, 78,
- 45, 79, -1, 63, 80, -1, 68, 80, -1, 81,
- -1, -1, 36, -1, 40, -1, 81, 46, 76, 48,
- -1, 81, 46, 1, 48, -1, 81, 32, -1, 46,
- 80, 48, -1, 46, 1, 48, -1, 62, 72, 31,
- -1, -1, 84, -1, 49, 33, -1, 50, 86, 44,
- -1, 50, 1, 44, -1, -1, 87, -1, 88, -1,
- 87, 88, -1, 62, 89, 43, -1, 1, 43, -1,
- -1, 90, -1, 91, -1, 90, 45, 91, -1, 74,
- 93, -1, 36, 92, -1, 92, -1, 51, 33, -1,
- -1, 30, -1, 29, 43, -1, -1, 29, -1, 28,
- 46, 36, 48, 43, -1
+ 54, 0, -1, 55, -1, 54, 55, -1, -1, 56,
+ 57, -1, -1, 12, 23, 58, 60, -1, -1, 23,
+ 59, 60, -1, 60, -1, 84, -1, 96, -1, 98,
+ -1, 1, 44, -1, 1, 45, -1, 64, 61, 44,
+ -1, -1, 62, -1, 63, -1, 62, 46, 63, -1,
+ 74, 97, 95, 85, -1, -1, 65, -1, 66, -1,
+ 65, 66, -1, 67, -1, 68, -1, 5, -1, 17,
+ -1, 21, -1, 11, -1, 14, -1, 69, -1, 73,
+ -1, 28, 47, 65, 48, 49, -1, 28, 47, 65,
+ 49, -1, 22, 37, -1, 24, 37, -1, 10, 37,
+ -1, 22, 37, 87, -1, 24, 37, 87, -1, 10,
+ 37, 32, -1, 10, 32, -1, 22, 87, -1, 24,
+ 87, -1, 7, -1, 19, -1, 15, -1, 16, -1,
+ 20, -1, 25, -1, 13, -1, 9, -1, 26, -1,
+ 6, -1, 41, -1, 48, 71, -1, -1, 72, -1,
+ 73, -1, 72, 73, -1, 8, -1, 27, -1, 31,
+ -1, 18, -1, 70, 74, -1, 75, -1, 37, -1,
+ 75, 47, 78, 49, -1, 75, 47, 1, 49, -1,
+ 75, 33, -1, 47, 74, 49, -1, 47, 1, 49,
+ -1, 70, 76, -1, 77, -1, 37, -1, 41, -1,
+ 77, 47, 78, 49, -1, 77, 47, 1, 49, -1,
+ 77, 33, -1, 47, 76, 49, -1, 47, 1, 49,
+ -1, 79, 36, -1, 79, -1, 80, 46, 36, -1,
+ -1, 80, -1, 81, -1, 80, 46, 81, -1, 65,
+ 82, -1, 70, 82, -1, 83, -1, -1, 37, -1,
+ 41, -1, 83, 47, 78, 49, -1, 83, 47, 1,
+ 49, -1, 83, 33, -1, 47, 82, 49, -1, 47,
+ 1, 49, -1, 64, 74, 32, -1, -1, 86, -1,
+ 50, 34, -1, 51, 88, 45, -1, 51, 1, 45,
+ -1, -1, 89, -1, 90, -1, 89, 90, -1, 64,
+ 91, 44, -1, 1, 44, -1, -1, 92, -1, 93,
+ -1, 92, 46, 93, -1, 76, 95, -1, 37, 94,
+ -1, 94, -1, 52, 34, -1, -1, 31, -1, 30,
+ 44, -1, -1, 30, -1, 29, 47, 37, 49, 44,
+ -1
};
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
-static const unsigned short int yyrline[] =
+static const yytype_uint16 yyrline[] =
{
- 0, 102, 102, 103, 107, 107, 113, 113, 115, 116,
- 117, 118, 119, 120, 124, 138, 139, 143, 151, 164,
- 170, 171, 175, 176, 180, 186, 190, 191, 192, 193,
- 194, 198, 199, 200, 201, 205, 207, 209, 213, 220,
- 227, 236, 237, 238, 242, 243, 244, 245, 246, 247,
- 248, 249, 250, 251, 252, 256, 261, 262, 266, 267,
- 271, 271, 271, 272, 280, 281, 285, 294, 296, 298,
- 300, 302, 309, 310, 314, 315, 316, 318, 320, 322,
- 324, 329, 330, 331, 335, 336, 340, 341, 346, 351,
- 353, 357, 358, 366, 370, 372, 374, 376, 378, 383,
- 392, 393, 398, 403, 404, 408, 409, 413, 414, 418,
- 420, 425, 426, 430, 431, 435, 436, 437, 441, 445,
- 446, 450, 454, 455, 459
+ 0, 103, 103, 104, 108, 108, 114, 114, 116, 116,
+ 118, 119, 120, 121, 122, 123, 127, 141, 142, 146,
+ 154, 167, 173, 174, 178, 179, 183, 189, 193, 194,
+ 195, 196, 197, 201, 202, 203, 204, 208, 210, 212,
+ 216, 223, 230, 239, 240, 241, 245, 246, 247, 248,
+ 249, 250, 251, 252, 253, 254, 255, 259, 264, 265,
+ 269, 270, 274, 274, 274, 275, 283, 284, 288, 297,
+ 299, 301, 303, 305, 312, 313, 317, 318, 319, 321,
+ 323, 325, 327, 332, 333, 334, 338, 339, 343, 344,
+ 349, 354, 356, 360, 361, 369, 373, 375, 377, 379,
+ 381, 386, 395, 396, 401, 406, 407, 411, 412, 416,
+ 417, 421, 423, 428, 429, 433, 434, 438, 439, 440,
+ 444, 448, 449, 453, 457, 458, 462
};
#endif
-#if YYDEBUG || YYERROR_VERBOSE
-/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
- First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
static const char *const yytname[] =
{
"$end", "error", "$undefined", "ASM_KEYW", "ATTRIBUTE_KEYW",
"AUTO_KEYW", "BOOL_KEYW", "CHAR_KEYW", "CONST_KEYW", "DOUBLE_KEYW",
- "ENUM_KEYW", "EXTERN_KEYW", "FLOAT_KEYW", "INLINE_KEYW", "INT_KEYW",
- "LONG_KEYW", "REGISTER_KEYW", "RESTRICT_KEYW", "SHORT_KEYW",
- "SIGNED_KEYW", "STATIC_KEYW", "STRUCT_KEYW", "TYPEDEF_KEYW",
- "UNION_KEYW", "UNSIGNED_KEYW", "VOID_KEYW", "VOLATILE_KEYW",
- "TYPEOF_KEYW", "EXPORT_SYMBOL_KEYW", "ASM_PHRASE", "ATTRIBUTE_PHRASE",
- "BRACE_PHRASE", "BRACKET_PHRASE", "EXPRESSION_PHRASE", "CHAR", "DOTS",
- "IDENT", "INT", "REAL", "STRING", "TYPE", "OTHER", "FILENAME", "';'",
- "'}'", "','", "'('", "'*'", "')'", "'='", "'{'", "':'", "$accept",
- "declaration_seq", "declaration", "@1", "declaration1", "@2",
- "simple_declaration", "init_declarator_list_opt", "init_declarator_list",
- "init_declarator", "decl_specifier_seq_opt", "decl_specifier_seq",
- "decl_specifier", "storage_class_specifier", "type_specifier",
- "simple_type_specifier", "ptr_operator", "cvar_qualifier_seq_opt",
- "cvar_qualifier_seq", "cvar_qualifier", "declarator",
- "direct_declarator", "nested_declarator", "direct_nested_declarator",
- "parameter_declaration_clause", "parameter_declaration_list_opt",
- "parameter_declaration_list", "parameter_declaration",
- "m_abstract_declarator", "direct_m_abstract_declarator",
- "function_definition", "initializer_opt", "initializer", "class_body",
- "member_specification_opt", "member_specification", "member_declaration",
+ "ENUM_KEYW", "EXTERN_KEYW", "EXTENSION_KEYW", "FLOAT_KEYW",
+ "INLINE_KEYW", "INT_KEYW", "LONG_KEYW", "REGISTER_KEYW", "RESTRICT_KEYW",
+ "SHORT_KEYW", "SIGNED_KEYW", "STATIC_KEYW", "STRUCT_KEYW",
+ "TYPEDEF_KEYW", "UNION_KEYW", "UNSIGNED_KEYW", "VOID_KEYW",
+ "VOLATILE_KEYW", "TYPEOF_KEYW", "EXPORT_SYMBOL_KEYW", "ASM_PHRASE",
+ "ATTRIBUTE_PHRASE", "BRACE_PHRASE", "BRACKET_PHRASE",
+ "EXPRESSION_PHRASE", "CHAR", "DOTS", "IDENT", "INT", "REAL", "STRING",
+ "TYPE", "OTHER", "FILENAME", "';'", "'}'", "','", "'('", "'*'", "')'",
+ "'='", "'{'", "':'", "$accept", "declaration_seq", "declaration", "@1",
+ "declaration1", "@2", "@3", "simple_declaration",
+ "init_declarator_list_opt", "init_declarator_list", "init_declarator",
+ "decl_specifier_seq_opt", "decl_specifier_seq", "decl_specifier",
+ "storage_class_specifier", "type_specifier", "simple_type_specifier",
+ "ptr_operator", "cvar_qualifier_seq_opt", "cvar_qualifier_seq",
+ "cvar_qualifier", "declarator", "direct_declarator", "nested_declarator",
+ "direct_nested_declarator", "parameter_declaration_clause",
+ "parameter_declaration_list_opt", "parameter_declaration_list",
+ "parameter_declaration", "m_abstract_declarator",
+ "direct_m_abstract_declarator", "function_definition", "initializer_opt",
+ "initializer", "class_body", "member_specification_opt",
+ "member_specification", "member_declaration",
"member_declarator_list_opt", "member_declarator_list",
"member_declarator", "member_bitfield_declarator", "attribute_opt",
"asm_definition", "asm_phrase_opt", "export_definition", 0
@@ -467,284 +603,266 @@ static const char *const yytname[] =
# ifdef YYPRINT
/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
token YYLEX-NUM. */
-static const unsigned short int yytoknum[] =
+static const yytype_uint16 yytoknum[] =
{
0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
- 295, 296, 297, 59, 125, 44, 40, 42, 41, 61,
- 123, 58
+ 295, 296, 297, 298, 59, 125, 44, 40, 42, 41,
+ 61, 123, 58
};
# endif
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
-static const unsigned char yyr1[] =
+static const yytype_uint8 yyr1[] =
{
- 0, 52, 53, 53, 55, 54, 57, 56, 56, 56,
- 56, 56, 56, 56, 58, 59, 59, 60, 60, 61,
- 62, 62, 63, 63, 64, 64, 65, 65, 65, 65,
- 65, 66, 66, 66, 66, 66, 66, 66, 66, 66,
- 66, 66, 66, 66, 67, 67, 67, 67, 67, 67,
- 67, 67, 67, 67, 67, 68, 69, 69, 70, 70,
- 71, 71, 71, 71, 72, 72, 73, 73, 73, 73,
- 73, 73, 74, 74, 75, 75, 75, 75, 75, 75,
- 75, 76, 76, 76, 77, 77, 78, 78, 79, 80,
- 80, 81, 81, 81, 81, 81, 81, 81, 81, 82,
- 83, 83, 84, 85, 85, 86, 86, 87, 87, 88,
- 88, 89, 89, 90, 90, 91, 91, 91, 92, 93,
- 93, 94, 95, 95, 96
+ 0, 53, 54, 54, 56, 55, 58, 57, 59, 57,
+ 57, 57, 57, 57, 57, 57, 60, 61, 61, 62,
+ 62, 63, 64, 64, 65, 65, 66, 66, 67, 67,
+ 67, 67, 67, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 69, 69, 69, 69,
+ 69, 69, 69, 69, 69, 69, 69, 70, 71, 71,
+ 72, 72, 73, 73, 73, 73, 74, 74, 75, 75,
+ 75, 75, 75, 75, 76, 76, 77, 77, 77, 77,
+ 77, 77, 77, 78, 78, 78, 79, 79, 80, 80,
+ 81, 82, 82, 83, 83, 83, 83, 83, 83, 83,
+ 83, 84, 85, 85, 86, 87, 87, 88, 88, 89,
+ 89, 90, 90, 91, 91, 92, 92, 93, 93, 93,
+ 94, 95, 95, 96, 97, 97, 98
};
/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
-static const unsigned char yyr2[] =
+static const yytype_uint8 yyr2[] =
{
- 0, 2, 1, 2, 0, 2, 0, 3, 1, 1,
- 1, 1, 2, 2, 3, 0, 1, 1, 3, 4,
- 0, 1, 1, 2, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 5, 4, 2, 2, 2, 3, 3,
- 3, 2, 2, 2, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 2, 0, 1, 1, 2,
- 1, 1, 1, 1, 2, 1, 1, 4, 4, 2,
- 3, 3, 2, 1, 1, 1, 4, 4, 2, 3,
- 3, 2, 1, 3, 0, 1, 1, 3, 2, 2,
- 1, 0, 1, 1, 4, 4, 2, 3, 3, 3,
- 0, 1, 2, 3, 3, 0, 1, 1, 2, 3,
- 2, 0, 1, 1, 3, 2, 2, 1, 2, 0,
- 1, 2, 0, 1, 5
+ 0, 2, 1, 2, 0, 2, 0, 4, 0, 3,
+ 1, 1, 1, 1, 2, 2, 3, 0, 1, 1,
+ 3, 4, 0, 1, 1, 2, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 5, 4, 2, 2, 2,
+ 3, 3, 3, 2, 2, 2, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 2, 0, 1,
+ 1, 2, 1, 1, 1, 1, 2, 1, 1, 4,
+ 4, 2, 3, 3, 2, 1, 1, 1, 4, 4,
+ 2, 3, 3, 2, 1, 3, 0, 1, 1, 3,
+ 2, 2, 1, 0, 1, 1, 4, 4, 2, 3,
+ 3, 3, 0, 1, 2, 3, 3, 0, 1, 1,
+ 2, 3, 2, 0, 1, 1, 3, 2, 2, 1,
+ 2, 0, 1, 2, 0, 1, 5
};
/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
STATE-NUM when YYTABLE doesn't specify something else to do. Zero
means the default is an error. */
-static const unsigned char yydefact[] =
+static const yytype_uint8 yydefact[] =
{
- 4, 4, 2, 0, 1, 3, 0, 26, 53, 44,
- 60, 51, 0, 29, 50, 30, 46, 47, 27, 63,
- 45, 48, 28, 0, 6, 0, 49, 52, 61, 0,
- 0, 0, 62, 54, 5, 8, 15, 21, 22, 24,
- 25, 31, 32, 9, 10, 11, 12, 13, 41, 37,
- 35, 0, 42, 20, 36, 43, 0, 0, 121, 66,
- 0, 56, 0, 16, 17, 0, 122, 65, 23, 40,
- 38, 0, 111, 0, 0, 107, 7, 15, 39, 0,
- 0, 0, 0, 55, 57, 58, 14, 0, 64, 123,
- 99, 119, 69, 0, 110, 104, 74, 75, 0, 0,
- 0, 119, 73, 0, 112, 113, 117, 103, 0, 108,
- 122, 0, 34, 0, 71, 70, 59, 18, 120, 100,
- 0, 91, 0, 82, 85, 86, 116, 0, 74, 0,
- 118, 72, 115, 78, 0, 109, 0, 33, 124, 0,
- 19, 101, 68, 92, 54, 0, 91, 88, 90, 67,
- 81, 0, 80, 79, 0, 0, 114, 102, 0, 93,
- 0, 89, 96, 0, 83, 87, 77, 76, 98, 97,
- 0, 0, 95, 94
+ 4, 4, 2, 0, 1, 3, 0, 28, 55, 46,
+ 62, 53, 0, 31, 0, 52, 32, 48, 49, 29,
+ 65, 47, 50, 30, 0, 8, 0, 51, 54, 63,
+ 0, 0, 0, 64, 56, 5, 10, 17, 23, 24,
+ 26, 27, 33, 34, 11, 12, 13, 14, 15, 43,
+ 39, 6, 37, 0, 44, 22, 38, 45, 0, 0,
+ 123, 68, 0, 58, 0, 18, 19, 0, 124, 67,
+ 25, 42, 22, 40, 0, 113, 0, 0, 109, 9,
+ 17, 41, 0, 0, 0, 0, 57, 59, 60, 16,
+ 0, 66, 125, 101, 121, 71, 0, 7, 112, 106,
+ 76, 77, 0, 0, 0, 121, 75, 0, 114, 115,
+ 119, 105, 0, 110, 124, 0, 36, 0, 73, 72,
+ 61, 20, 122, 102, 0, 93, 0, 84, 87, 88,
+ 118, 0, 76, 0, 120, 74, 117, 80, 0, 111,
+ 0, 35, 126, 0, 21, 103, 70, 94, 56, 0,
+ 93, 90, 92, 69, 83, 0, 82, 81, 0, 0,
+ 116, 104, 0, 95, 0, 91, 98, 0, 85, 89,
+ 79, 78, 100, 99, 0, 0, 97, 96
};
-/* YYDEFGOTO[NTERM-NUM]. */
-static const short int yydefgoto[] =
+/* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int16 yydefgoto[] =
{
- -1, 1, 2, 3, 34, 53, 35, 62, 63, 64,
- 72, 37, 38, 39, 40, 41, 65, 83, 84, 42,
- 110, 67, 101, 102, 122, 123, 124, 125, 147, 148,
- 43, 140, 141, 52, 73, 74, 75, 103, 104, 105,
- 106, 119, 44, 91, 45
+ -1, 1, 2, 3, 35, 72, 55, 36, 64, 65,
+ 66, 75, 38, 39, 40, 41, 42, 67, 86, 87,
+ 43, 114, 69, 105, 106, 126, 127, 128, 129, 151,
+ 152, 44, 144, 145, 54, 76, 77, 78, 107, 108,
+ 109, 110, 123, 45, 94, 46
};
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
STATE-NUM. */
-#define YYPACT_NINF -128
-static const short int yypact[] =
+#define YYPACT_NINF -135
+static const yytype_int16 yypact[] =
{
- -128, 13, -128, 329, -128, -128, 36, -128, -128, -128,
- -128, -128, -16, -128, -128, -128, -128, -128, -128, -128,
- -128, -128, -128, -25, -128, -24, -128, -128, -128, -29,
- -4, -22, -128, -128, -128, -128, -28, 495, -128, -128,
- -128, -128, -128, -128, -128, -128, -128, -128, -128, 16,
- -23, 103, -128, 495, -23, -128, 495, 35, -128, -128,
- 3, 15, 9, 17, -128, -28, -15, -8, -128, -128,
- -128, 47, 23, 44, 150, -128, -128, -28, -128, 372,
- 33, 48, 49, -128, 15, -128, -128, -28, -128, -128,
- -128, 64, -128, 197, -128, -128, 50, -128, 21, 65,
- 37, 64, 14, 56, 55, -128, -128, -128, 59, -128,
- 74, 57, -128, 63, -128, -128, -128, -128, -128, 76,
- 83, 416, 84, 99, 90, -128, -128, 88, -128, 89,
- -128, -128, -128, -128, 241, -128, 23, -128, -128, 105,
- -128, -128, -128, -128, -128, 8, 46, -128, 26, -128,
- -128, 459, -128, -128, 92, 93, -128, -128, 94, -128,
- 96, -128, -128, 285, -128, -128, -128, -128, -128, -128,
- 97, 100, -128, -128
+ -135, 11, -135, 312, -135, -135, 24, -135, -135, -135,
+ -135, -135, -23, -135, -2, -135, -135, -135, -135, -135,
+ -135, -135, -135, -135, -17, -135, -11, -135, -135, -135,
+ -3, 16, 26, -135, -135, -135, -135, 34, 482, -135,
+ -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+ -8, -135, 22, 97, -135, 482, 22, -135, 482, 56,
+ -135, -135, 12, 10, 50, 49, -135, 34, -13, 15,
+ -135, -135, 482, -135, 47, -25, 51, 145, -135, -135,
+ 34, -135, 356, 52, 71, 77, -135, 10, -135, -135,
+ 34, -135, -135, -135, 68, -135, 193, -135, -135, -135,
+ 48, -135, 6, 93, 37, 68, 18, 85, 84, -135,
+ -135, -135, 87, -135, 102, 86, -135, 89, -135, -135,
+ -135, -135, -135, 90, 88, 401, 94, 100, 101, -135,
+ -135, 99, -135, 108, -135, -135, -135, -135, 230, -135,
+ -25, -135, -135, 105, -135, -135, -135, -135, -135, 9,
+ 42, -135, 28, -135, -135, 445, -135, -135, 119, 125,
+ -135, -135, 126, -135, 128, -135, -135, 267, -135, -135,
+ -135, -135, -135, -135, 129, 130, -135, -135
};
/* YYPGOTO[NTERM-NUM]. */
-static const short int yypgoto[] =
+static const yytype_int16 yypgoto[] =
{
- -128, -128, 151, -128, -128, -128, 119, -128, -128, 66,
- 0, -56, -36, -128, -128, -128, -70, -128, -128, -51,
- -31, -128, -11, -128, -127, -128, -128, 27, -81, -128,
- -128, -128, -128, -19, -128, -128, 107, -128, -128, 43,
- 86, 82, -128, -128, -128
+ -135, -135, 179, -135, -135, -135, -135, -47, -135, -135,
+ 91, 0, -58, -37, -135, -135, -135, -73, -135, -135,
+ -48, -32, -135, -38, -135, -134, -135, -135, 29, -63,
+ -135, -135, -135, -135, -20, -135, -135, 106, -135, -135,
+ 45, 95, 82, -135, -135, -135
};
/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
positive, shift that token. If negative, reduce the rule which
number is the opposite. If zero, do what YYDEFACT says.
If YYTABLE_NINF, syntax error. */
-#define YYTABLE_NINF -107
-static const short int yytable[] =
+#define YYTABLE_NINF -109
+static const yytype_int16 yytable[] =
{
- 79, 68, 100, 36, 81, 66, 55, 155, 59, 158,
- 85, 50, 54, 4, 89, 48, 90, 56, 60, 61,
- 49, 58, 127, 10, 92, 51, 51, 51, 100, 82,
- 100, 70, 19, 116, 88, 78, 171, 121, 93, 59,
- -91, 28, 57, 68, 143, 32, 133, 69, 159, 60,
- 61, 146, 86, 77, 145, 61, -91, 128, 162, 96,
- 134, 97, 87, 97, 160, 161, 100, 98, 61, 98,
- 61, 80, 163, 128, 99, 146, 146, 97, 121, 46,
- 47, 113, 143, 98, 61, 68, 159, 129, 107, 131,
- 94, 95, 145, 61, 118, 121, 114, 115, 130, 135,
- 136, 99, 94, 89, 71, 137, 138, 121, 7, 8,
- 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
- 19, 20, 21, 22, 23, 139, 25, 26, 27, 28,
- 29, 142, 149, 32, 150, 151, 152, 153, 157, -20,
- 166, 167, 168, 33, 169, 172, -20, -105, 173, -20,
- -20, 108, 5, 117, -20, 7, 8, 9, 10, 11,
- 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
- 22, 23, 76, 25, 26, 27, 28, 29, 165, 156,
- 32, 109, 126, 132, 0, 0, -20, 0, 0, 0,
- 33, 0, 0, -20, -106, 0, -20, -20, 120, 0,
- 0, -20, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 0,
- 25, 26, 27, 28, 29, 0, 0, 32, 0, 0,
- 0, 0, -84, 0, 0, 0, 0, 33, 0, 0,
- 0, 0, 154, 0, 0, -84, 7, 8, 9, 10,
- 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
- 21, 22, 23, 0, 25, 26, 27, 28, 29, 0,
- 0, 32, 0, 0, 0, 0, -84, 0, 0, 0,
- 0, 33, 0, 0, 0, 0, 170, 0, 0, -84,
- 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
- 17, 18, 19, 20, 21, 22, 23, 0, 25, 26,
- 27, 28, 29, 0, 0, 32, 0, 0, 0, 0,
- -84, 0, 0, 0, 0, 33, 0, 0, 0, 0,
- 6, 0, 0, -84, 7, 8, 9, 10, 11, 12,
- 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
- 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
- 0, 0, 0, 0, 0, -20, 0, 0, 0, 33,
- 0, 0, -20, 0, 0, -20, -20, 7, 8, 9,
+ 82, 70, 104, 37, 159, 68, 57, 131, 79, 49,
+ 162, 4, 100, 84, 50, 88, 101, 92, 10, 93,
+ 52, 51, 102, 63, 71, 97, 56, 103, 20, 104,
+ 85, 104, 73, 175, 53, 91, 81, 29, 125, 120,
+ 53, 33, -93, 132, 58, 70, 147, 101, 95, 61,
+ 163, 137, 150, 102, 63, 80, 149, 63, -93, 62,
+ 63, 166, 96, 59, 133, 138, 135, 104, 47, 48,
+ 60, 61, 80, 53, 132, 167, 150, 150, 101, 147,
+ 125, 62, 63, 163, 102, 63, 164, 165, 70, 149,
+ 63, 98, 99, 83, 89, 90, 111, 125, 74, 122,
+ 103, 117, 7, 8, 9, 10, 11, 12, 13, 125,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 118, 26, 27, 28, 29, 30, 119, 134, 33, 139,
+ 140, 98, 92, 142, -22, 141, 154, 146, 34, 161,
+ 143, -22, -107, 153, -22, -22, 112, 155, 156, -22,
+ 7, 8, 9, 10, 11, 12, 13, 157, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 170, 26,
+ 27, 28, 29, 30, 171, 172, 33, 173, 176, 177,
+ 5, 121, -22, 113, 169, 160, 34, 136, 0, -22,
+ -108, 0, -22, -22, 124, 130, 0, -22, 7, 8,
+ 9, 10, 11, 12, 13, 0, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 0, 26, 27, 28,
+ 29, 30, 0, 0, 33, 0, 0, 0, 0, -86,
+ 0, 158, 0, 0, 34, 7, 8, 9, 10, 11,
+ 12, 13, -86, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 0, 26, 27, 28, 29, 30, 0,
+ 0, 33, 0, 0, 0, 0, -86, 0, 174, 0,
+ 0, 34, 7, 8, 9, 10, 11, 12, 13, -86,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 0, 26, 27, 28, 29, 30, 0, 0, 33, 0,
+ 0, 0, 0, -86, 0, 0, 0, 0, 34, 0,
+ 0, 0, 0, 6, 0, 0, -86, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
- 20, 21, 22, 23, 0, 25, 26, 27, 28, 29,
- 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 33, 0, 0, 0, 0, 0, 0, 111,
- 112, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 0, 25,
- 26, 27, 28, 29, 0, 0, 32, 0, 0, 0,
- 0, 0, 143, 0, 0, 0, 144, 0, 0, 0,
- 0, 0, 145, 61, 7, 8, 9, 10, 11, 12,
- 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
- 23, 0, 25, 26, 27, 28, 29, 0, 0, 32,
- 0, 0, 0, 0, 164, 0, 0, 0, 0, 33,
- 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
- 17, 18, 19, 20, 21, 22, 23, 0, 25, 26,
- 27, 28, 29, 0, 0, 32, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 33
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 0, 0, 0, 0, 0, -22,
+ 0, 0, 0, 34, 0, 0, -22, 0, 0, -22,
+ -22, 7, 8, 9, 10, 11, 12, 13, 0, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 0,
+ 26, 27, 28, 29, 30, 0, 0, 33, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 34, 0, 0,
+ 0, 0, 0, 0, 115, 116, 7, 8, 9, 10,
+ 11, 12, 13, 0, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23, 24, 0, 26, 27, 28, 29, 30,
+ 0, 0, 33, 0, 0, 0, 0, 0, 147, 0,
+ 0, 0, 148, 0, 0, 0, 0, 0, 149, 63,
+ 7, 8, 9, 10, 11, 12, 13, 0, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 0, 26,
+ 27, 28, 29, 30, 0, 0, 33, 0, 0, 0,
+ 0, 168, 0, 0, 0, 0, 34, 7, 8, 9,
+ 10, 11, 12, 13, 0, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 0, 26, 27, 28, 29,
+ 30, 0, 0, 33, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 34
};
-static const short int yycheck[] =
+static const yytype_int16 yycheck[] =
{
- 56, 37, 72, 3, 1, 36, 25, 134, 36, 1,
- 61, 36, 36, 0, 29, 31, 31, 46, 46, 47,
- 36, 43, 1, 8, 32, 50, 50, 50, 98, 60,
- 100, 50, 17, 84, 65, 54, 163, 93, 46, 36,
- 32, 26, 46, 79, 36, 30, 32, 31, 40, 46,
- 47, 121, 43, 53, 46, 47, 48, 36, 32, 36,
- 46, 40, 45, 40, 145, 146, 136, 46, 47, 46,
- 47, 36, 46, 36, 51, 145, 146, 40, 134, 43,
- 44, 48, 36, 46, 47, 121, 40, 98, 44, 100,
- 43, 44, 46, 47, 30, 151, 48, 48, 33, 43,
- 45, 51, 43, 29, 1, 48, 43, 163, 5, 6,
- 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
- 17, 18, 19, 20, 21, 49, 23, 24, 25, 26,
- 27, 48, 48, 30, 35, 45, 48, 48, 33, 36,
- 48, 48, 48, 40, 48, 48, 43, 44, 48, 46,
- 47, 1, 1, 87, 51, 5, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
- 20, 21, 53, 23, 24, 25, 26, 27, 151, 136,
- 30, 74, 96, 101, -1, -1, 36, -1, -1, -1,
- 40, -1, -1, 43, 44, -1, 46, 47, 1, -1,
- -1, 51, 5, 6, 7, 8, 9, 10, 11, 12,
- 13, 14, 15, 16, 17, 18, 19, 20, 21, -1,
- 23, 24, 25, 26, 27, -1, -1, 30, -1, -1,
- -1, -1, 35, -1, -1, -1, -1, 40, -1, -1,
- -1, -1, 1, -1, -1, 48, 5, 6, 7, 8,
- 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
- 19, 20, 21, -1, 23, 24, 25, 26, 27, -1,
- -1, 30, -1, -1, -1, -1, 35, -1, -1, -1,
- -1, 40, -1, -1, -1, -1, 1, -1, -1, 48,
- 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, -1, 23, 24,
- 25, 26, 27, -1, -1, 30, -1, -1, -1, -1,
- 35, -1, -1, -1, -1, 40, -1, -1, -1, -1,
- 1, -1, -1, 48, 5, 6, 7, 8, 9, 10,
- 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
- 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
- -1, -1, -1, -1, -1, 36, -1, -1, -1, 40,
- -1, -1, 43, -1, -1, 46, 47, 5, 6, 7,
+ 58, 38, 75, 3, 138, 37, 26, 1, 55, 32,
+ 1, 0, 37, 1, 37, 63, 41, 30, 8, 32,
+ 37, 23, 47, 48, 32, 72, 37, 52, 18, 102,
+ 62, 104, 52, 167, 51, 67, 56, 27, 96, 87,
+ 51, 31, 33, 37, 47, 82, 37, 41, 33, 37,
+ 41, 33, 125, 47, 48, 55, 47, 48, 49, 47,
+ 48, 33, 47, 47, 102, 47, 104, 140, 44, 45,
+ 44, 37, 72, 51, 37, 47, 149, 150, 41, 37,
+ 138, 47, 48, 41, 47, 48, 149, 150, 125, 47,
+ 48, 44, 45, 37, 44, 46, 45, 155, 1, 31,
+ 52, 49, 5, 6, 7, 8, 9, 10, 11, 167,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 49, 24, 25, 26, 27, 28, 49, 34, 31, 44,
+ 46, 44, 30, 44, 37, 49, 36, 49, 41, 34,
+ 50, 44, 45, 49, 47, 48, 1, 46, 49, 52,
+ 5, 6, 7, 8, 9, 10, 11, 49, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 49, 24,
+ 25, 26, 27, 28, 49, 49, 31, 49, 49, 49,
+ 1, 90, 37, 77, 155, 140, 41, 105, -1, 44,
+ 45, -1, 47, 48, 1, 100, -1, 52, 5, 6,
+ 7, 8, 9, 10, 11, -1, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, -1, 24, 25, 26,
+ 27, 28, -1, -1, 31, -1, -1, -1, -1, 36,
+ -1, 1, -1, -1, 41, 5, 6, 7, 8, 9,
+ 10, 11, 49, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, -1, 24, 25, 26, 27, 28, -1,
+ -1, 31, -1, -1, -1, -1, 36, -1, 1, -1,
+ -1, 41, 5, 6, 7, 8, 9, 10, 11, 49,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ -1, 24, 25, 26, 27, 28, -1, -1, 31, -1,
+ -1, -1, -1, 36, -1, -1, -1, -1, 41, -1,
+ -1, -1, -1, 1, -1, -1, 49, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
- 18, 19, 20, 21, -1, 23, 24, 25, 26, 27,
- -1, -1, 30, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 40, -1, -1, -1, -1, -1, -1, 47,
- 48, 5, 6, 7, 8, 9, 10, 11, 12, 13,
- 14, 15, 16, 17, 18, 19, 20, 21, -1, 23,
- 24, 25, 26, 27, -1, -1, 30, -1, -1, -1,
- -1, -1, 36, -1, -1, -1, 40, -1, -1, -1,
- -1, -1, 46, 47, 5, 6, 7, 8, 9, 10,
- 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
- 21, -1, 23, 24, 25, 26, 27, -1, -1, 30,
- -1, -1, -1, -1, 35, -1, -1, -1, -1, 40,
- 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, -1, 23, 24,
- 25, 26, 27, -1, -1, 30, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 40
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
+ 28, 29, 30, 31, -1, -1, -1, -1, -1, 37,
+ -1, -1, -1, 41, -1, -1, 44, -1, -1, 47,
+ 48, 5, 6, 7, 8, 9, 10, 11, -1, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, -1,
+ 24, 25, 26, 27, 28, -1, -1, 31, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 41, -1, -1,
+ -1, -1, -1, -1, 48, 49, 5, 6, 7, 8,
+ 9, 10, 11, -1, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, -1, 24, 25, 26, 27, 28,
+ -1, -1, 31, -1, -1, -1, -1, -1, 37, -1,
+ -1, -1, 41, -1, -1, -1, -1, -1, 47, 48,
+ 5, 6, 7, 8, 9, 10, 11, -1, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, -1, 24,
+ 25, 26, 27, 28, -1, -1, 31, -1, -1, -1,
+ -1, 36, -1, -1, -1, -1, 41, 5, 6, 7,
+ 8, 9, 10, 11, -1, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, -1, 24, 25, 26, 27,
+ 28, -1, -1, 31, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 41
};
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
symbol of state STATE-NUM. */
-static const unsigned char yystos[] =
+static const yytype_uint8 yystos[] =
{
- 0, 53, 54, 55, 0, 54, 1, 5, 6, 7,
+ 0, 54, 55, 56, 0, 55, 1, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
- 28, 29, 30, 40, 56, 58, 62, 63, 64, 65,
- 66, 67, 71, 82, 94, 96, 43, 44, 31, 36,
- 36, 50, 85, 57, 36, 85, 46, 46, 43, 36,
- 46, 47, 59, 60, 61, 68, 72, 73, 64, 31,
- 85, 1, 62, 86, 87, 88, 58, 62, 85, 63,
- 36, 1, 72, 69, 70, 71, 43, 45, 72, 29,
- 31, 95, 32, 46, 43, 44, 36, 40, 46, 51,
- 68, 74, 75, 89, 90, 91, 92, 44, 1, 88,
- 72, 47, 48, 48, 48, 48, 71, 61, 30, 93,
- 1, 63, 76, 77, 78, 79, 92, 1, 36, 74,
- 33, 74, 93, 32, 46, 43, 45, 48, 43, 49,
- 83, 84, 48, 36, 40, 46, 68, 80, 81, 48,
- 35, 45, 48, 48, 1, 76, 91, 33, 1, 40,
- 80, 80, 32, 46, 35, 79, 48, 48, 48, 48,
- 1, 76, 48, 48
+ 28, 29, 30, 31, 41, 57, 60, 64, 65, 66,
+ 67, 68, 69, 73, 84, 96, 98, 44, 45, 32,
+ 37, 23, 37, 51, 87, 59, 37, 87, 47, 47,
+ 44, 37, 47, 48, 61, 62, 63, 70, 74, 75,
+ 66, 32, 58, 87, 1, 64, 88, 89, 90, 60,
+ 64, 87, 65, 37, 1, 74, 71, 72, 73, 44,
+ 46, 74, 30, 32, 97, 33, 47, 60, 44, 45,
+ 37, 41, 47, 52, 70, 76, 77, 91, 92, 93,
+ 94, 45, 1, 90, 74, 48, 49, 49, 49, 49,
+ 73, 63, 31, 95, 1, 65, 78, 79, 80, 81,
+ 94, 1, 37, 76, 34, 76, 95, 33, 47, 44,
+ 46, 49, 44, 50, 85, 86, 49, 37, 41, 47,
+ 70, 82, 83, 49, 36, 46, 49, 49, 1, 78,
+ 93, 34, 1, 41, 82, 82, 33, 47, 36, 81,
+ 49, 49, 49, 49, 1, 78, 49, 49
};
-#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
-# define YYSIZE_T __SIZE_TYPE__
-#endif
-#if ! defined (YYSIZE_T) && defined (size_t)
-# define YYSIZE_T size_t
-#endif
-#if ! defined (YYSIZE_T)
-# if defined (__STDC__) || defined (__cplusplus)
-# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-# define YYSIZE_T size_t
-# endif
-#endif
-#if ! defined (YYSIZE_T)
-# define YYSIZE_T unsigned int
-#endif
-
#define yyerrok (yyerrstatus = 0)
#define yyclearin (yychar = YYEMPTY)
#define YYEMPTY (-2)
@@ -770,15 +888,15 @@ do \
yychar = (Token); \
yylval = (Value); \
yytoken = YYTRANSLATE (yychar); \
- YYPOPSTACK; \
+ YYPOPSTACK (1); \
goto yybackup; \
} \
else \
- { \
- yyerror ("syntax error: cannot back up");\
+ { \
+ yyerror (YY_("syntax error: cannot back up")); \
YYERROR; \
} \
-while (0)
+while (YYID (0))
#define YYTERROR 1
@@ -793,7 +911,7 @@ while (0)
#ifndef YYLLOC_DEFAULT
# define YYLLOC_DEFAULT(Current, Rhs, N) \
do \
- if (N) \
+ if (YYID (N)) \
{ \
(Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
(Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
@@ -807,7 +925,7 @@ while (0)
(Current).first_column = (Current).last_column = \
YYRHSLOC (Rhs, 0).last_column; \
} \
- while (0)
+ while (YYID (0))
#endif
@@ -819,8 +937,8 @@ while (0)
# if YYLTYPE_IS_TRIVIAL
# define YY_LOCATION_PRINT(File, Loc) \
fprintf (File, "%d.%d-%d.%d", \
- (Loc).first_line, (Loc).first_column, \
- (Loc).last_line, (Loc).last_column)
+ (Loc).first_line, (Loc).first_column, \
+ (Loc).last_line, (Loc).last_column)
# else
# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
# endif
@@ -847,36 +965,96 @@ while (0)
do { \
if (yydebug) \
YYFPRINTF Args; \
-} while (0)
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (YYID (0))
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
-do { \
- if (yydebug) \
- { \
- YYFPRINTF (stderr, "%s ", Title); \
- yysymprint (stderr, \
- Type, Value); \
- YYFPRINTF (stderr, "\n"); \
- } \
-} while (0)
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+#endif
+{
+ if (!yyvaluep)
+ return;
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+ YYUSE (yyoutput);
+# endif
+ switch (yytype)
+ {
+ default:
+ break;
+ }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+#endif
+{
+ if (yytype < YYNTOKENS)
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+ else
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep);
+ YYFPRINTF (yyoutput, ")");
+}
/*------------------------------------------------------------------.
| yy_stack_print -- Print the state stack from its BOTTOM up to its |
| TOP (included). |
`------------------------------------------------------------------*/
-#if defined (__STDC__) || defined (__cplusplus)
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
static void
-yy_stack_print (short int *bottom, short int *top)
+yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
#else
static void
yy_stack_print (bottom, top)
- short int *bottom;
- short int *top;
+ yytype_int16 *bottom;
+ yytype_int16 *top;
#endif
{
YYFPRINTF (stderr, "Stack now");
- for (/* Nothing. */; bottom <= top; ++bottom)
+ for (; bottom <= top; ++bottom)
YYFPRINTF (stderr, " %d", *bottom);
YYFPRINTF (stderr, "\n");
}
@@ -885,37 +1063,45 @@ yy_stack_print (bottom, top)
do { \
if (yydebug) \
yy_stack_print ((Bottom), (Top)); \
-} while (0)
+} while (YYID (0))
/*------------------------------------------------.
| Report that the YYRULE is going to be reduced. |
`------------------------------------------------*/
-#if defined (__STDC__) || defined (__cplusplus)
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
static void
-yy_reduce_print (int yyrule)
+yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
#else
static void
-yy_reduce_print (yyrule)
+yy_reduce_print (yyvsp, yyrule)
+ YYSTYPE *yyvsp;
int yyrule;
#endif
{
+ int yynrhs = yyr2[yyrule];
int yyi;
- unsigned int yylno = yyrline[yyrule];
- YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
- yyrule - 1, yylno);
- /* Print the symbols being reduced, and their result. */
- for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
- YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]);
- YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]);
+ unsigned long int yylno = yyrline[yyrule];
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ fprintf (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ );
+ fprintf (stderr, "\n");
+ }
}
# define YY_REDUCE_PRINT(Rule) \
do { \
if (yydebug) \
- yy_reduce_print (Rule); \
-} while (0)
+ yy_reduce_print (yyvsp, Rule); \
+} while (YYID (0))
/* Nonzero means print parse trace. It is left uninitialized so that
multiple parsers can coexist. */
@@ -937,7 +1123,7 @@ int yydebug;
if the built-in stack extension method is used).
Do not make this value too large; the results are undefined if
- SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
evaluated with infinite-precision integer arithmetic. */
#ifndef YYMAXDEPTH
@@ -949,45 +1135,47 @@ int yydebug;
#if YYERROR_VERBOSE
# ifndef yystrlen
-# if defined (__GLIBC__) && defined (_STRING_H)
+# if defined __GLIBC__ && defined _STRING_H
# define yystrlen strlen
# else
/* Return the length of YYSTR. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
static YYSIZE_T
-# if defined (__STDC__) || defined (__cplusplus)
yystrlen (const char *yystr)
-# else
+#else
+static YYSIZE_T
yystrlen (yystr)
- const char *yystr;
-# endif
+ const char *yystr;
+#endif
{
- register const char *yys = yystr;
-
- while (*yys++ != '\0')
+ YYSIZE_T yylen;
+ for (yylen = 0; yystr[yylen]; yylen++)
continue;
-
- return yys - yystr - 1;
+ return yylen;
}
# endif
# endif
# ifndef yystpcpy
-# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
# define yystpcpy stpcpy
# else
/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
YYDEST. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
static char *
-# if defined (__STDC__) || defined (__cplusplus)
yystpcpy (char *yydest, const char *yysrc)
-# else
+#else
+static char *
yystpcpy (yydest, yysrc)
- char *yydest;
- const char *yysrc;
-# endif
+ char *yydest;
+ const char *yysrc;
+#endif
{
- register char *yyd = yydest;
- register const char *yys = yysrc;
+ char *yyd = yydest;
+ const char *yys = yysrc;
while ((*yyd++ = *yys++) != '\0')
continue;
@@ -997,53 +1185,171 @@ yystpcpy (yydest, yysrc)
# endif
# endif
-#endif /* !YYERROR_VERBOSE */
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+ quotes and backslashes, so that it's suitable for yyerror. The
+ heuristic is that double-quoting is unnecessary unless the string
+ contains an apostrophe, a comma, or backslash (other than
+ backslash-backslash). YYSTR is taken from yytname. If YYRES is
+ null, do not copy; instead, return the length of what the result
+ would have been. */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+ if (*yystr == '"')
+ {
+ YYSIZE_T yyn = 0;
+ char const *yyp = yystr;
+
+ for (;;)
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
+ do_not_strip_quotes: ;
+ }
-
+ if (! yyres)
+ return yystrlen (yystr);
-#if YYDEBUG
-/*--------------------------------.
-| Print this symbol on YYOUTPUT. |
-`--------------------------------*/
+ return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
-#if defined (__STDC__) || defined (__cplusplus)
-static void
-yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yysymprint (yyoutput, yytype, yyvaluep)
- FILE *yyoutput;
- int yytype;
- YYSTYPE *yyvaluep;
-#endif
+/* Copy into YYRESULT an error message about the unexpected token
+ YYCHAR while in state YYSTATE. Return the number of bytes copied,
+ including the terminating null byte. If YYRESULT is null, do not
+ copy anything; just return the number of bytes that would be
+ copied. As a special case, return 0 if an ordinary "syntax error"
+ message will do. Return YYSIZE_MAXIMUM if overflow occurs during
+ size calculation. */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
{
- /* Pacify ``unused variable'' warnings. */
- (void) yyvaluep;
+ int yyn = yypact[yystate];
- if (yytype < YYNTOKENS)
- YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+ if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+ return 0;
else
- YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
-
-
-# ifdef YYPRINT
- if (yytype < YYNTOKENS)
- YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# endif
- switch (yytype)
{
- default:
- break;
+ int yytype = YYTRANSLATE (yychar);
+ YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+ YYSIZE_T yysize = yysize0;
+ YYSIZE_T yysize1;
+ int yysize_overflow = 0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ int yyx;
+
+# if 0
+ /* This is so xgettext sees the translatable formats that are
+ constructed on the fly. */
+ YY_("syntax error, unexpected %s");
+ YY_("syntax error, unexpected %s, expecting %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+ char *yyfmt;
+ char const *yyf;
+ static char const yyunexpected[] = "syntax error, unexpected %s";
+ static char const yyexpecting[] = ", expecting %s";
+ static char const yyor[] = " or %s";
+ char yyformat[sizeof yyunexpected
+ + sizeof yyexpecting - 1
+ + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+ * (sizeof yyor - 1))];
+ char const *yyprefix = yyexpecting;
+
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yycount = 1;
+
+ yyarg[0] = yytname[yytype];
+ yyfmt = yystpcpy (yyformat, yyunexpected);
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ yyformat[sizeof yyunexpected - 1] = '\0';
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+ yyfmt = yystpcpy (yyfmt, yyprefix);
+ yyprefix = yyor;
+ }
+
+ yyf = YY_(yyformat);
+ yysize1 = yysize + yystrlen (yyf);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+
+ if (yysize_overflow)
+ return YYSIZE_MAXIMUM;
+
+ if (yyresult)
+ {
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ char *yyp = yyresult;
+ int yyi = 0;
+ while ((*yyp = *yyf) != '\0')
+ {
+ if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyf += 2;
+ }
+ else
+ {
+ yyp++;
+ yyf++;
+ }
+ }
+ }
+ return yysize;
}
- YYFPRINTF (yyoutput, ")");
}
+#endif /* YYERROR_VERBOSE */
+
-#endif /* ! YYDEBUG */
/*-----------------------------------------------.
| Release the memory associated to this symbol. |
`-----------------------------------------------*/
-#if defined (__STDC__) || defined (__cplusplus)
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
static void
yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
#else
@@ -1054,8 +1360,7 @@ yydestruct (yymsg, yytype, yyvaluep)
YYSTYPE *yyvaluep;
#endif
{
- /* Pacify ``unused variable'' warnings. */
- (void) yyvaluep;
+ YYUSE (yyvaluep);
if (!yymsg)
yymsg = "Deleting";
@@ -1065,7 +1370,7 @@ yydestruct (yymsg, yytype, yyvaluep)
{
default:
- break;
+ break;
}
}
@@ -1073,13 +1378,13 @@ yydestruct (yymsg, yytype, yyvaluep)
/* Prevent warnings from -Wmissing-prototypes. */
#ifdef YYPARSE_PARAM
-# if defined (__STDC__) || defined (__cplusplus)
+#if defined __STDC__ || defined __cplusplus
int yyparse (void *YYPARSE_PARAM);
-# else
+#else
int yyparse ();
-# endif
+#endif
#else /* ! YYPARSE_PARAM */
-#if defined (__STDC__) || defined (__cplusplus)
+#if defined __STDC__ || defined __cplusplus
int yyparse (void);
#else
int yyparse ();
@@ -1104,14 +1409,18 @@ int yynerrs;
`----------*/
#ifdef YYPARSE_PARAM
-# if defined (__STDC__) || defined (__cplusplus)
-int yyparse (void *YYPARSE_PARAM)
-# else
-int yyparse (YYPARSE_PARAM)
- void *YYPARSE_PARAM;
-# endif
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+#endif
#else /* ! YYPARSE_PARAM */
-#if defined (__STDC__) || defined (__cplusplus)
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
int
yyparse (void)
#else
@@ -1122,13 +1431,19 @@ yyparse ()
#endif
{
- register int yystate;
- register int yyn;
+ int yystate;
+ int yyn;
int yyresult;
/* Number of tokens to shift before error messages enabled. */
int yyerrstatus;
/* Look-ahead token as an internal (translated) token number. */
int yytoken = 0;
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
/* Three stacks and their tools:
`yyss': related to states,
@@ -1139,18 +1454,18 @@ yyparse ()
to reallocate them elsewhere. */
/* The state stack. */
- short int yyssa[YYINITDEPTH];
- short int *yyss = yyssa;
- register short int *yyssp;
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss = yyssa;
+ yytype_int16 *yyssp;
/* The semantic value stack. */
YYSTYPE yyvsa[YYINITDEPTH];
YYSTYPE *yyvs = yyvsa;
- register YYSTYPE *yyvsp;
+ YYSTYPE *yyvsp;
-#define YYPOPSTACK (yyvsp--, yyssp--)
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
YYSIZE_T yystacksize = YYINITDEPTH;
@@ -1159,9 +1474,9 @@ yyparse ()
YYSTYPE yyval;
- /* When reducing, the number of symbols on the RHS of the reduced
- rule. */
- int yylen;
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
YYDPRINTF ((stderr, "Starting parse\n"));
@@ -1178,9 +1493,6 @@ yyparse ()
yyssp = yyss;
yyvsp = yyvs;
-
- yyvsp[0] = yylval;
-
goto yysetstate;
/*------------------------------------------------------------.
@@ -1188,8 +1500,7 @@ yyparse ()
`------------------------------------------------------------*/
yynewstate:
/* In all cases, when you get here, the value and location stacks
- have just been pushed. so pushing a state here evens the stacks.
- */
+ have just been pushed. So pushing a state here evens the stacks. */
yyssp++;
yysetstate:
@@ -1202,18 +1513,18 @@ yyparse ()
#ifdef yyoverflow
{
- /* Give user a chance to reallocate the stack. Use copies of
+ /* Give user a chance to reallocate the stack. Use copies of
these so that the &'s don't force the real ones into
memory. */
YYSTYPE *yyvs1 = yyvs;
- short int *yyss1 = yyss;
+ yytype_int16 *yyss1 = yyss;
/* Each stack pointer address is followed by the size of the
data in use in that stack, in bytes. This used to be a
conditional around just the two extra args, but that might
be undefined if yyoverflow is a macro. */
- yyoverflow ("parser stack overflow",
+ yyoverflow (YY_("memory exhausted"),
&yyss1, yysize * sizeof (*yyssp),
&yyvs1, yysize * sizeof (*yyvsp),
@@ -1224,21 +1535,21 @@ yyparse ()
}
#else /* no yyoverflow */
# ifndef YYSTACK_RELOCATE
- goto yyoverflowlab;
+ goto yyexhaustedlab;
# else
/* Extend the stack our own way. */
if (YYMAXDEPTH <= yystacksize)
- goto yyoverflowlab;
+ goto yyexhaustedlab;
yystacksize *= 2;
if (YYMAXDEPTH < yystacksize)
yystacksize = YYMAXDEPTH;
{
- short int *yyss1 = yyss;
+ yytype_int16 *yyss1 = yyss;
union yyalloc *yyptr =
(union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
if (! yyptr)
- goto yyoverflowlab;
+ goto yyexhaustedlab;
YYSTACK_RELOCATE (yyss);
YYSTACK_RELOCATE (yyvs);
@@ -1269,12 +1580,10 @@ yyparse ()
`-----------*/
yybackup:
-/* Do appropriate processing given the current state. */
-/* Read a look-ahead token if we need one and don't already have one. */
-/* yyresume: */
+ /* Do appropriate processing given the current state. Read a
+ look-ahead token if we need one and don't already have one. */
/* First try to decide what to do without reference to look-ahead token. */
-
yyn = yypact[yystate];
if (yyn == YYPACT_NINF)
goto yydefault;
@@ -1316,22 +1625,21 @@ yybackup:
if (yyn == YYFINAL)
YYACCEPT;
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
/* Shift the look-ahead token. */
YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
- /* Discard the token being shifted unless it is eof. */
+ /* Discard the shifted token unless it is eof. */
if (yychar != YYEOF)
yychar = YYEMPTY;
+ yystate = yyn;
*++yyvsp = yylval;
-
- /* Count tokens shifted since error; after three, turn off error
- status. */
- if (yyerrstatus)
- yyerrstatus--;
-
- yystate = yyn;
goto yynewstate;
@@ -1367,457 +1675,466 @@ yyreduce:
switch (yyn)
{
case 4:
-#line 107 "scripts/genksyms/parse.y"
+#line 108 "scripts/genksyms/parse.y"
{ is_typedef = 0; is_extern = 0; current_name = NULL; decl_spec = NULL; ;}
break;
case 5:
-#line 109 "scripts/genksyms/parse.y"
- { free_list(*(yyvsp[0]), NULL); *(yyvsp[0]) = NULL; ;}
+#line 110 "scripts/genksyms/parse.y"
+ { free_list(*(yyvsp[(2) - (2)]), NULL); *(yyvsp[(2) - (2)]) = NULL; ;}
break;
case 6:
-#line 113 "scripts/genksyms/parse.y"
+#line 114 "scripts/genksyms/parse.y"
{ is_typedef = 1; ;}
break;
case 7:
-#line 114 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+#line 115 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(4) - (4)]); ;}
break;
- case 12:
-#line 119 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+ case 8:
+#line 116 "scripts/genksyms/parse.y"
+ { is_typedef = 1; ;}
break;
- case 13:
-#line 120 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+ case 9:
+#line 117 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(3) - (3)]); ;}
break;
case 14:
-#line 125 "scripts/genksyms/parse.y"
+#line 122 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(2) - (2)]); ;}
+ break;
+
+ case 15:
+#line 123 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(2) - (2)]); ;}
+ break;
+
+ case 16:
+#line 128 "scripts/genksyms/parse.y"
{ if (current_name) {
- struct string_list *decl = (*(yyvsp[0]))->next;
- (*(yyvsp[0]))->next = NULL;
+ struct string_list *decl = (*(yyvsp[(3) - (3)]))->next;
+ (*(yyvsp[(3) - (3)]))->next = NULL;
add_symbol(current_name,
is_typedef ? SYM_TYPEDEF : SYM_NORMAL,
decl, is_extern);
current_name = NULL;
}
- (yyval) = (yyvsp[0]);
+ (yyval) = (yyvsp[(3) - (3)]);
;}
break;
- case 15:
-#line 138 "scripts/genksyms/parse.y"
+ case 17:
+#line 141 "scripts/genksyms/parse.y"
{ (yyval) = NULL; ;}
break;
- case 17:
-#line 144 "scripts/genksyms/parse.y"
- { struct string_list *decl = *(yyvsp[0]);
- *(yyvsp[0]) = NULL;
+ case 19:
+#line 147 "scripts/genksyms/parse.y"
+ { struct string_list *decl = *(yyvsp[(1) - (1)]);
+ *(yyvsp[(1) - (1)]) = NULL;
add_symbol(current_name,
is_typedef ? SYM_TYPEDEF : SYM_NORMAL, decl, is_extern);
current_name = NULL;
- (yyval) = (yyvsp[0]);
+ (yyval) = (yyvsp[(1) - (1)]);
;}
break;
- case 18:
-#line 152 "scripts/genksyms/parse.y"
- { struct string_list *decl = *(yyvsp[0]);
- *(yyvsp[0]) = NULL;
- free_list(*(yyvsp[-1]), NULL);
- *(yyvsp[-1]) = decl_spec;
+ case 20:
+#line 155 "scripts/genksyms/parse.y"
+ { struct string_list *decl = *(yyvsp[(3) - (3)]);
+ *(yyvsp[(3) - (3)]) = NULL;
+ free_list(*(yyvsp[(2) - (3)]), NULL);
+ *(yyvsp[(2) - (3)]) = decl_spec;
add_symbol(current_name,
is_typedef ? SYM_TYPEDEF : SYM_NORMAL, decl, is_extern);
current_name = NULL;
- (yyval) = (yyvsp[0]);
+ (yyval) = (yyvsp[(3) - (3)]);
;}
break;
- case 19:
-#line 165 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]) ? (yyvsp[0]) : (yyvsp[-1]) ? (yyvsp[-1]) : (yyvsp[-2]) ? (yyvsp[-2]) : (yyvsp[-3]); ;}
+ case 21:
+#line 168 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(4) - (4)]) ? (yyvsp[(4) - (4)]) : (yyvsp[(3) - (4)]) ? (yyvsp[(3) - (4)]) : (yyvsp[(2) - (4)]) ? (yyvsp[(2) - (4)]) : (yyvsp[(1) - (4)]); ;}
break;
- case 20:
-#line 170 "scripts/genksyms/parse.y"
+ case 22:
+#line 173 "scripts/genksyms/parse.y"
{ decl_spec = NULL; ;}
break;
- case 22:
-#line 175 "scripts/genksyms/parse.y"
- { decl_spec = *(yyvsp[0]); ;}
+ case 24:
+#line 178 "scripts/genksyms/parse.y"
+ { decl_spec = *(yyvsp[(1) - (1)]); ;}
break;
- case 23:
-#line 176 "scripts/genksyms/parse.y"
- { decl_spec = *(yyvsp[0]); ;}
+ case 25:
+#line 179 "scripts/genksyms/parse.y"
+ { decl_spec = *(yyvsp[(2) - (2)]); ;}
break;
- case 24:
-#line 181 "scripts/genksyms/parse.y"
+ case 26:
+#line 184 "scripts/genksyms/parse.y"
{ /* Version 2 checksumming ignores storage class, as that
is really irrelevant to the linkage. */
- remove_node((yyvsp[0]));
- (yyval) = (yyvsp[0]);
+ remove_node((yyvsp[(1) - (1)]));
+ (yyval) = (yyvsp[(1) - (1)]);
;}
break;
- case 29:
-#line 193 "scripts/genksyms/parse.y"
- { is_extern = 1; (yyval) = (yyvsp[0]); ;}
+ case 31:
+#line 196 "scripts/genksyms/parse.y"
+ { is_extern = 1; (yyval) = (yyvsp[(1) - (1)]); ;}
break;
- case 30:
-#line 194 "scripts/genksyms/parse.y"
- { is_extern = 0; (yyval) = (yyvsp[0]); ;}
+ case 32:
+#line 197 "scripts/genksyms/parse.y"
+ { is_extern = 0; (yyval) = (yyvsp[(1) - (1)]); ;}
break;
- case 35:
-#line 206 "scripts/genksyms/parse.y"
- { remove_node((yyvsp[-1])); (*(yyvsp[0]))->tag = SYM_STRUCT; (yyval) = (yyvsp[0]); ;}
+ case 37:
+#line 209 "scripts/genksyms/parse.y"
+ { remove_node((yyvsp[(1) - (2)])); (*(yyvsp[(2) - (2)]))->tag = SYM_STRUCT; (yyval) = (yyvsp[(2) - (2)]); ;}
break;
- case 36:
-#line 208 "scripts/genksyms/parse.y"
- { remove_node((yyvsp[-1])); (*(yyvsp[0]))->tag = SYM_UNION; (yyval) = (yyvsp[0]); ;}
+ case 38:
+#line 211 "scripts/genksyms/parse.y"
+ { remove_node((yyvsp[(1) - (2)])); (*(yyvsp[(2) - (2)]))->tag = SYM_UNION; (yyval) = (yyvsp[(2) - (2)]); ;}
break;
- case 37:
-#line 210 "scripts/genksyms/parse.y"
- { remove_node((yyvsp[-1])); (*(yyvsp[0]))->tag = SYM_ENUM; (yyval) = (yyvsp[0]); ;}
+ case 39:
+#line 213 "scripts/genksyms/parse.y"
+ { remove_node((yyvsp[(1) - (2)])); (*(yyvsp[(2) - (2)]))->tag = SYM_ENUM; (yyval) = (yyvsp[(2) - (2)]); ;}
break;
- case 38:
-#line 214 "scripts/genksyms/parse.y"
- { struct string_list *s = *(yyvsp[0]), *i = *(yyvsp[-1]), *r;
+ case 40:
+#line 217 "scripts/genksyms/parse.y"
+ { struct string_list *s = *(yyvsp[(3) - (3)]), *i = *(yyvsp[(2) - (3)]), *r;
r = copy_node(i); r->tag = SYM_STRUCT;
- r->next = (*(yyvsp[-2]))->next; *(yyvsp[0]) = r; (*(yyvsp[-2]))->next = NULL;
+ r->next = (*(yyvsp[(1) - (3)]))->next; *(yyvsp[(3) - (3)]) = r; (*(yyvsp[(1) - (3)]))->next = NULL;
add_symbol(i->string, SYM_STRUCT, s, is_extern);
- (yyval) = (yyvsp[0]);
+ (yyval) = (yyvsp[(3) - (3)]);
;}
break;
- case 39:
-#line 221 "scripts/genksyms/parse.y"
- { struct string_list *s = *(yyvsp[0]), *i = *(yyvsp[-1]), *r;
+ case 41:
+#line 224 "scripts/genksyms/parse.y"
+ { struct string_list *s = *(yyvsp[(3) - (3)]), *i = *(yyvsp[(2) - (3)]), *r;
r = copy_node(i); r->tag = SYM_UNION;
- r->next = (*(yyvsp[-2]))->next; *(yyvsp[0]) = r; (*(yyvsp[-2]))->next = NULL;
+ r->next = (*(yyvsp[(1) - (3)]))->next; *(yyvsp[(3) - (3)]) = r; (*(yyvsp[(1) - (3)]))->next = NULL;
add_symbol(i->string, SYM_UNION, s, is_extern);
- (yyval) = (yyvsp[0]);
+ (yyval) = (yyvsp[(3) - (3)]);
;}
break;
- case 40:
-#line 228 "scripts/genksyms/parse.y"
- { struct string_list *s = *(yyvsp[0]), *i = *(yyvsp[-1]), *r;
+ case 42:
+#line 231 "scripts/genksyms/parse.y"
+ { struct string_list *s = *(yyvsp[(3) - (3)]), *i = *(yyvsp[(2) - (3)]), *r;
r = copy_node(i); r->tag = SYM_ENUM;
- r->next = (*(yyvsp[-2]))->next; *(yyvsp[0]) = r; (*(yyvsp[-2]))->next = NULL;
+ r->next = (*(yyvsp[(1) - (3)]))->next; *(yyvsp[(3) - (3)]) = r; (*(yyvsp[(1) - (3)]))->next = NULL;
add_symbol(i->string, SYM_ENUM, s, is_extern);
- (yyval) = (yyvsp[0]);
+ (yyval) = (yyvsp[(3) - (3)]);
;}
break;
- case 41:
-#line 236 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+ case 43:
+#line 239 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(2) - (2)]); ;}
break;
- case 42:
-#line 237 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+ case 44:
+#line 240 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(2) - (2)]); ;}
break;
- case 43:
-#line 238 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+ case 45:
+#line 241 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(2) - (2)]); ;}
break;
- case 54:
-#line 252 "scripts/genksyms/parse.y"
- { (*(yyvsp[0]))->tag = SYM_TYPEDEF; (yyval) = (yyvsp[0]); ;}
+ case 56:
+#line 255 "scripts/genksyms/parse.y"
+ { (*(yyvsp[(1) - (1)]))->tag = SYM_TYPEDEF; (yyval) = (yyvsp[(1) - (1)]); ;}
break;
- case 55:
-#line 257 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]) ? (yyvsp[0]) : (yyvsp[-1]); ;}
+ case 57:
+#line 260 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(2) - (2)]) ? (yyvsp[(2) - (2)]) : (yyvsp[(1) - (2)]); ;}
break;
- case 56:
-#line 261 "scripts/genksyms/parse.y"
+ case 58:
+#line 264 "scripts/genksyms/parse.y"
{ (yyval) = NULL; ;}
break;
- case 59:
-#line 267 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+ case 61:
+#line 270 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(2) - (2)]); ;}
break;
- case 63:
-#line 273 "scripts/genksyms/parse.y"
+ case 65:
+#line 276 "scripts/genksyms/parse.y"
{ /* restrict has no effect in prototypes so ignore it */
- remove_node((yyvsp[0]));
- (yyval) = (yyvsp[0]);
+ remove_node((yyvsp[(1) - (1)]));
+ (yyval) = (yyvsp[(1) - (1)]);
;}
break;
- case 64:
-#line 280 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+ case 66:
+#line 283 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(2) - (2)]); ;}
break;
- case 66:
-#line 286 "scripts/genksyms/parse.y"
+ case 68:
+#line 289 "scripts/genksyms/parse.y"
{ if (current_name != NULL) {
error_with_pos("unexpected second declaration name");
YYERROR;
} else {
- current_name = (*(yyvsp[0]))->string;
- (yyval) = (yyvsp[0]);
+ current_name = (*(yyvsp[(1) - (1)]))->string;
+ (yyval) = (yyvsp[(1) - (1)]);
}
;}
break;
- case 67:
-#line 295 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
- break;
-
- case 68:
-#line 297 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
- break;
-
case 69:
-#line 299 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+#line 298 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(4) - (4)]); ;}
break;
case 70:
-#line 301 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+#line 300 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(4) - (4)]); ;}
break;
case 71:
-#line 303 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+#line 302 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(2) - (2)]); ;}
break;
case 72:
-#line 309 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+#line 304 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(3) - (3)]); ;}
break;
- case 76:
-#line 317 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+ case 73:
+#line 306 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(3) - (3)]); ;}
break;
- case 77:
-#line 319 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+ case 74:
+#line 312 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(2) - (2)]); ;}
break;
case 78:
-#line 321 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+#line 320 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(4) - (4)]); ;}
break;
case 79:
-#line 323 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+#line 322 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(4) - (4)]); ;}
break;
case 80:
-#line 325 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+#line 324 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(2) - (2)]); ;}
break;
case 81:
-#line 329 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+#line 326 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(3) - (3)]); ;}
break;
- case 83:
-#line 331 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+ case 82:
+#line 328 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(3) - (3)]); ;}
break;
- case 84:
-#line 335 "scripts/genksyms/parse.y"
- { (yyval) = NULL; ;}
+ case 83:
+#line 332 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(2) - (2)]); ;}
break;
- case 87:
-#line 342 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+ case 85:
+#line 334 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(3) - (3)]); ;}
break;
- case 88:
-#line 347 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]) ? (yyvsp[0]) : (yyvsp[-1]); ;}
+ case 86:
+#line 338 "scripts/genksyms/parse.y"
+ { (yyval) = NULL; ;}
break;
case 89:
-#line 352 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]) ? (yyvsp[0]) : (yyvsp[-1]); ;}
+#line 345 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(3) - (3)]); ;}
break;
- case 91:
-#line 357 "scripts/genksyms/parse.y"
- { (yyval) = NULL; ;}
+ case 90:
+#line 350 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(2) - (2)]) ? (yyvsp[(2) - (2)]) : (yyvsp[(1) - (2)]); ;}
break;
- case 92:
-#line 359 "scripts/genksyms/parse.y"
- { /* For version 2 checksums, we don't want to remember
- private parameter names. */
- remove_node((yyvsp[0]));
- (yyval) = (yyvsp[0]);
- ;}
+ case 91:
+#line 355 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(2) - (2)]) ? (yyvsp[(2) - (2)]) : (yyvsp[(1) - (2)]); ;}
break;
case 93:
-#line 367 "scripts/genksyms/parse.y"
- { remove_node((yyvsp[0]));
- (yyval) = (yyvsp[0]);
- ;}
+#line 360 "scripts/genksyms/parse.y"
+ { (yyval) = NULL; ;}
break;
case 94:
-#line 371 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+#line 362 "scripts/genksyms/parse.y"
+ { /* For version 2 checksums, we don't want to remember
+ private parameter names. */
+ remove_node((yyvsp[(1) - (1)]));
+ (yyval) = (yyvsp[(1) - (1)]);
+ ;}
break;
case 95:
-#line 373 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+#line 370 "scripts/genksyms/parse.y"
+ { remove_node((yyvsp[(1) - (1)]));
+ (yyval) = (yyvsp[(1) - (1)]);
+ ;}
break;
case 96:
-#line 375 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+#line 374 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(4) - (4)]); ;}
break;
case 97:
-#line 377 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+#line 376 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(4) - (4)]); ;}
break;
case 98:
-#line 379 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+#line 378 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(2) - (2)]); ;}
break;
case 99:
-#line 384 "scripts/genksyms/parse.y"
- { struct string_list *decl = *(yyvsp[-1]);
- *(yyvsp[-1]) = NULL;
- add_symbol(current_name, SYM_NORMAL, decl, is_extern);
- (yyval) = (yyvsp[0]);
- ;}
+#line 380 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(3) - (3)]); ;}
break;
case 100:
-#line 392 "scripts/genksyms/parse.y"
- { (yyval) = NULL; ;}
+#line 382 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(3) - (3)]); ;}
break;
- case 102:
-#line 399 "scripts/genksyms/parse.y"
- { remove_list((yyvsp[0]), &(*(yyvsp[-1]))->next); (yyval) = (yyvsp[0]); ;}
+ case 101:
+#line 387 "scripts/genksyms/parse.y"
+ { struct string_list *decl = *(yyvsp[(2) - (3)]);
+ *(yyvsp[(2) - (3)]) = NULL;
+ add_symbol(current_name, SYM_NORMAL, decl, is_extern);
+ (yyval) = (yyvsp[(3) - (3)]);
+ ;}
break;
- case 103:
-#line 403 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+ case 102:
+#line 395 "scripts/genksyms/parse.y"
+ { (yyval) = NULL; ;}
break;
case 104:
-#line 404 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+#line 402 "scripts/genksyms/parse.y"
+ { remove_list((yyvsp[(2) - (2)]), &(*(yyvsp[(1) - (2)]))->next); (yyval) = (yyvsp[(2) - (2)]); ;}
break;
case 105:
-#line 408 "scripts/genksyms/parse.y"
- { (yyval) = NULL; ;}
+#line 406 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(3) - (3)]); ;}
break;
- case 108:
-#line 414 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+ case 106:
+#line 407 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(3) - (3)]); ;}
break;
- case 109:
-#line 419 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+ case 107:
+#line 411 "scripts/genksyms/parse.y"
+ { (yyval) = NULL; ;}
break;
case 110:
-#line 421 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+#line 417 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(2) - (2)]); ;}
break;
case 111:
-#line 425 "scripts/genksyms/parse.y"
- { (yyval) = NULL; ;}
+#line 422 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(3) - (3)]); ;}
break;
- case 114:
-#line 431 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+ case 112:
+#line 424 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(2) - (2)]); ;}
break;
- case 115:
-#line 435 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]) ? (yyvsp[0]) : (yyvsp[-1]); ;}
+ case 113:
+#line 428 "scripts/genksyms/parse.y"
+ { (yyval) = NULL; ;}
break;
case 116:
-#line 436 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+#line 434 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(3) - (3)]); ;}
+ break;
+
+ case 117:
+#line 438 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(2) - (2)]) ? (yyvsp[(2) - (2)]) : (yyvsp[(1) - (2)]); ;}
break;
case 118:
-#line 441 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+#line 439 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(2) - (2)]); ;}
break;
- case 119:
-#line 445 "scripts/genksyms/parse.y"
- { (yyval) = NULL; ;}
+ case 120:
+#line 444 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(2) - (2)]); ;}
break;
case 121:
-#line 450 "scripts/genksyms/parse.y"
- { (yyval) = (yyvsp[0]); ;}
+#line 448 "scripts/genksyms/parse.y"
+ { (yyval) = NULL; ;}
break;
- case 122:
-#line 454 "scripts/genksyms/parse.y"
- { (yyval) = NULL; ;}
+ case 123:
+#line 453 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[(2) - (2)]); ;}
break;
case 124:
-#line 460 "scripts/genksyms/parse.y"
- { export_symbol((*(yyvsp[-2]))->string); (yyval) = (yyvsp[0]); ;}
+#line 457 "scripts/genksyms/parse.y"
+ { (yyval) = NULL; ;}
break;
+ case 126:
+#line 463 "scripts/genksyms/parse.y"
+ { export_symbol((*(yyvsp[(3) - (5)]))->string); (yyval) = (yyvsp[(5) - (5)]); ;}
+ break;
- }
-
-/* Line 1037 of yacc.c. */
-#line 1816 "scripts/genksyms/parse.c"
-
- yyvsp -= yylen;
- yyssp -= yylen;
+/* Line 1267 of yacc.c. */
+#line 2132 "scripts/genksyms/parse.c"
+ default: break;
+ }
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+ YYPOPSTACK (yylen);
+ yylen = 0;
YY_STACK_PRINT (yyss, yyssp);
*++yyvsp = yyval;
@@ -1846,66 +2163,41 @@ yyerrlab:
if (!yyerrstatus)
{
++yynerrs;
-#if YYERROR_VERBOSE
- yyn = yypact[yystate];
-
- if (YYPACT_NINF < yyn && yyn < YYLAST)
- {
- YYSIZE_T yysize = 0;
- int yytype = YYTRANSLATE (yychar);
- const char* yyprefix;
- char *yymsg;
- int yyx;
-
- /* Start YYX at -YYN if negative to avoid negative indexes in
- YYCHECK. */
- int yyxbegin = yyn < 0 ? -yyn : 0;
-
- /* Stay within bounds of both yycheck and yytname. */
- int yychecklim = YYLAST - yyn;
- int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
- int yycount = 0;
-
- yyprefix = ", expecting ";
- for (yyx = yyxbegin; yyx < yyxend; ++yyx)
- if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+#if ! YYERROR_VERBOSE
+ yyerror (YY_("syntax error"));
+#else
+ {
+ YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+ if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+ {
+ YYSIZE_T yyalloc = 2 * yysize;
+ if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+ yyalloc = YYSTACK_ALLOC_MAXIMUM;
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+ if (yymsg)
+ yymsg_alloc = yyalloc;
+ else
{
- yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]);
- yycount += 1;
- if (yycount == 5)
- {
- yysize = 0;
- break;
- }
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
}
- yysize += (sizeof ("syntax error, unexpected ")
- + yystrlen (yytname[yytype]));
- yymsg = (char *) YYSTACK_ALLOC (yysize);
- if (yymsg != 0)
- {
- char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
- yyp = yystpcpy (yyp, yytname[yytype]);
-
- if (yycount < 5)
- {
- yyprefix = ", expecting ";
- for (yyx = yyxbegin; yyx < yyxend; ++yyx)
- if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
- {
- yyp = yystpcpy (yyp, yyprefix);
- yyp = yystpcpy (yyp, yytname[yyx]);
- yyprefix = " or ";
- }
- }
- yyerror (yymsg);
- YYSTACK_FREE (yymsg);
- }
- else
- yyerror ("syntax error; also virtual memory exhausted");
- }
- else
-#endif /* YYERROR_VERBOSE */
- yyerror ("syntax error");
+ }
+
+ if (0 < yysize && yysize <= yymsg_alloc)
+ {
+ (void) yysyntax_error (yymsg, yystate, yychar);
+ yyerror (yymsg);
+ }
+ else
+ {
+ yyerror (YY_("syntax error"));
+ if (yysize != 0)
+ goto yyexhaustedlab;
+ }
+ }
+#endif
}
@@ -1916,23 +2208,15 @@ yyerrlab:
error, discard it. */
if (yychar <= YYEOF)
- {
- /* If at end of input, pop the error token,
- then the rest of the stack, then return failure. */
+ {
+ /* Return failure if at end of input. */
if (yychar == YYEOF)
- for (;;)
- {
-
- YYPOPSTACK;
- if (yyssp == yyss)
- YYABORT;
- yydestruct ("Error: popping",
- yystos[*yyssp], yyvsp);
- }
- }
+ YYABORT;
+ }
else
{
- yydestruct ("Error: discarding", yytoken, &yylval);
+ yydestruct ("Error: discarding",
+ yytoken, &yylval);
yychar = YYEMPTY;
}
}
@@ -1947,15 +2231,17 @@ yyerrlab:
`---------------------------------------------------*/
yyerrorlab:
-#ifdef __GNUC__
- /* Pacify GCC when the user code never invokes YYERROR and the label
- yyerrorlab therefore never appears in user code. */
- if (0)
+ /* Pacify compilers like GCC when the user code never invokes
+ YYERROR and the label yyerrorlab therefore never appears in user
+ code. */
+ if (/*CONSTCOND*/ 0)
goto yyerrorlab;
-#endif
-yyvsp -= yylen;
- yyssp -= yylen;
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
yystate = *yyssp;
goto yyerrlab1;
@@ -1985,8 +2271,9 @@ yyerrlab1:
YYABORT;
- yydestruct ("Error: popping", yystos[yystate], yyvsp);
- YYPOPSTACK;
+ yydestruct ("Error: popping",
+ yystos[yystate], yyvsp);
+ YYPOPSTACK (1);
yystate = *yyssp;
YY_STACK_PRINT (yyss, yyssp);
}
@@ -1997,7 +2284,7 @@ yyerrlab1:
*++yyvsp = yylval;
- /* Shift the error token. */
+ /* Shift the error token. */
YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
yystate = yyn;
@@ -2015,32 +2302,47 @@ yyacceptlab:
| yyabortlab -- YYABORT comes here. |
`-----------------------------------*/
yyabortlab:
- yydestruct ("Error: discarding lookahead",
- yytoken, &yylval);
- yychar = YYEMPTY;
yyresult = 1;
goto yyreturn;
#ifndef yyoverflow
-/*----------------------------------------------.
-| yyoverflowlab -- parser overflow comes here. |
-`----------------------------------------------*/
-yyoverflowlab:
- yyerror ("parser stack overflow");
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here. |
+`-------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (YY_("memory exhausted"));
yyresult = 2;
/* Fall through. */
#endif
yyreturn:
+ if (yychar != YYEOF && yychar != YYEMPTY)
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval);
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+ yystos[*yyssp], yyvsp);
+ YYPOPSTACK (1);
+ }
#ifndef yyoverflow
if (yyss != yyssa)
YYSTACK_FREE (yyss);
#endif
- return yyresult;
+#if YYERROR_VERBOSE
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+#endif
+ /* Make sure YYID is used. */
+ return YYID (yyresult);
}
-#line 464 "scripts/genksyms/parse.y"
+#line 467 "scripts/genksyms/parse.y"
static void
diff --git a/scripts/genksyms/parse.h_shipped b/scripts/genksyms/parse.h_shipped
index f3fb2bb058e1..c4eeec652b79 100644
--- a/scripts/genksyms/parse.h_shipped
+++ b/scripts/genksyms/parse.h_shipped
@@ -1,7 +1,9 @@
-/* A Bison parser, made by GNU Bison 2.0. */
+/* A Bison parser, made by GNU Bison 2.3. */
-/* Skeleton parser for Yacc-like parsing with Bison,
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
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
@@ -15,13 +17,21 @@
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. */
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
-/* As a special exception, when this file is copied by Bison into a
- Bison output file, you may use that output file without restriction.
- This special exception was added by the Free Software Foundation
- in version 1.24 of Bison. */
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
/* Tokens. */
#ifndef YYTOKENTYPE
@@ -38,39 +48,41 @@
DOUBLE_KEYW = 264,
ENUM_KEYW = 265,
EXTERN_KEYW = 266,
- FLOAT_KEYW = 267,
- INLINE_KEYW = 268,
- INT_KEYW = 269,
- LONG_KEYW = 270,
- REGISTER_KEYW = 271,
- RESTRICT_KEYW = 272,
- SHORT_KEYW = 273,
- SIGNED_KEYW = 274,
- STATIC_KEYW = 275,
- STRUCT_KEYW = 276,
- TYPEDEF_KEYW = 277,
- UNION_KEYW = 278,
- UNSIGNED_KEYW = 279,
- VOID_KEYW = 280,
- VOLATILE_KEYW = 281,
- TYPEOF_KEYW = 282,
- EXPORT_SYMBOL_KEYW = 283,
- ASM_PHRASE = 284,
- ATTRIBUTE_PHRASE = 285,
- BRACE_PHRASE = 286,
- BRACKET_PHRASE = 287,
- EXPRESSION_PHRASE = 288,
- CHAR = 289,
- DOTS = 290,
- IDENT = 291,
- INT = 292,
- REAL = 293,
- STRING = 294,
- TYPE = 295,
- OTHER = 296,
- FILENAME = 297
+ EXTENSION_KEYW = 267,
+ FLOAT_KEYW = 268,
+ INLINE_KEYW = 269,
+ INT_KEYW = 270,
+ LONG_KEYW = 271,
+ REGISTER_KEYW = 272,
+ RESTRICT_KEYW = 273,
+ SHORT_KEYW = 274,
+ SIGNED_KEYW = 275,
+ STATIC_KEYW = 276,
+ STRUCT_KEYW = 277,
+ TYPEDEF_KEYW = 278,
+ UNION_KEYW = 279,
+ UNSIGNED_KEYW = 280,
+ VOID_KEYW = 281,
+ VOLATILE_KEYW = 282,
+ TYPEOF_KEYW = 283,
+ EXPORT_SYMBOL_KEYW = 284,
+ ASM_PHRASE = 285,
+ ATTRIBUTE_PHRASE = 286,
+ BRACE_PHRASE = 287,
+ BRACKET_PHRASE = 288,
+ EXPRESSION_PHRASE = 289,
+ CHAR = 290,
+ DOTS = 291,
+ IDENT = 292,
+ INT = 293,
+ REAL = 294,
+ STRING = 295,
+ TYPE = 296,
+ OTHER = 297,
+ FILENAME = 298
};
#endif
+/* Tokens. */
#define ASM_KEYW 258
#define ATTRIBUTE_KEYW 259
#define AUTO_KEYW 260
@@ -80,42 +92,43 @@
#define DOUBLE_KEYW 264
#define ENUM_KEYW 265
#define EXTERN_KEYW 266
-#define FLOAT_KEYW 267
-#define INLINE_KEYW 268
-#define INT_KEYW 269
-#define LONG_KEYW 270
-#define REGISTER_KEYW 271
-#define RESTRICT_KEYW 272
-#define SHORT_KEYW 273
-#define SIGNED_KEYW 274
-#define STATIC_KEYW 275
-#define STRUCT_KEYW 276
-#define TYPEDEF_KEYW 277
-#define UNION_KEYW 278
-#define UNSIGNED_KEYW 279
-#define VOID_KEYW 280
-#define VOLATILE_KEYW 281
-#define TYPEOF_KEYW 282
-#define EXPORT_SYMBOL_KEYW 283
-#define ASM_PHRASE 284
-#define ATTRIBUTE_PHRASE 285
-#define BRACE_PHRASE 286
-#define BRACKET_PHRASE 287
-#define EXPRESSION_PHRASE 288
-#define CHAR 289
-#define DOTS 290
-#define IDENT 291
-#define INT 292
-#define REAL 293
-#define STRING 294
-#define TYPE 295
-#define OTHER 296
-#define FILENAME 297
+#define EXTENSION_KEYW 267
+#define FLOAT_KEYW 268
+#define INLINE_KEYW 269
+#define INT_KEYW 270
+#define LONG_KEYW 271
+#define REGISTER_KEYW 272
+#define RESTRICT_KEYW 273
+#define SHORT_KEYW 274
+#define SIGNED_KEYW 275
+#define STATIC_KEYW 276
+#define STRUCT_KEYW 277
+#define TYPEDEF_KEYW 278
+#define UNION_KEYW 279
+#define UNSIGNED_KEYW 280
+#define VOID_KEYW 281
+#define VOLATILE_KEYW 282
+#define TYPEOF_KEYW 283
+#define EXPORT_SYMBOL_KEYW 284
+#define ASM_PHRASE 285
+#define ATTRIBUTE_PHRASE 286
+#define BRACE_PHRASE 287
+#define BRACKET_PHRASE 288
+#define EXPRESSION_PHRASE 289
+#define CHAR 290
+#define DOTS 291
+#define IDENT 292
+#define INT 293
+#define REAL 294
+#define STRING 295
+#define TYPE 296
+#define OTHER 297
+#define FILENAME 298
-#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef int YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
@@ -124,5 +137,3 @@ typedef int YYSTYPE;
extern YYSTYPE yylval;
-
-
diff --git a/scripts/genksyms/parse.y b/scripts/genksyms/parse.y
index ca04c944b7c3..408cdf82b271 100644
--- a/scripts/genksyms/parse.y
+++ b/scripts/genksyms/parse.y
@@ -61,6 +61,7 @@ remove_list(struct string_list **pb, struct string_list **pe)
%token DOUBLE_KEYW
%token ENUM_KEYW
%token EXTERN_KEYW
+%token EXTENSION_KEYW
%token FLOAT_KEYW
%token INLINE_KEYW
%token INT_KEYW
@@ -110,7 +111,9 @@ declaration:
;
declaration1:
- TYPEDEF_KEYW { is_typedef = 1; } simple_declaration
+ EXTENSION_KEYW TYPEDEF_KEYW { is_typedef = 1; } simple_declaration
+ { $$ = $4; }
+ | TYPEDEF_KEYW { is_typedef = 1; } simple_declaration
{ $$ = $3; }
| simple_declaration
| function_definition
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index 8986a48c8c49..1ad6f7fc490a 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -4,23 +4,25 @@
PHONY += oldconfig xconfig gconfig menuconfig config silentoldconfig update-po-config
+Kconfig := arch/$(SRCARCH)/Kconfig
+
xconfig: $(obj)/qconf
- $< arch/$(ARCH)/Kconfig
+ $< $(Kconfig)
gconfig: $(obj)/gconf
- $< arch/$(ARCH)/Kconfig
+ $< $(Kconfig)
menuconfig: $(obj)/mconf
- $< arch/$(ARCH)/Kconfig
+ $< $(Kconfig)
config: $(obj)/conf
- $< arch/$(ARCH)/Kconfig
+ $< $(Kconfig)
oldconfig: $(obj)/conf
- $< -o arch/$(ARCH)/Kconfig
+ $< -o $(Kconfig)
silentoldconfig: $(obj)/conf
- $< -s arch/$(ARCH)/Kconfig
+ $< -s $(Kconfig)
# Create new linux.po file
# Adjust charset to UTF-8 in .po file to accept UTF-8 in Kconfig files
@@ -45,27 +47,27 @@ update-po-config: $(obj)/kxgettext
PHONY += randconfig allyesconfig allnoconfig allmodconfig defconfig
randconfig: $(obj)/conf
- $< -r arch/$(ARCH)/Kconfig
+ $< -r $(Kconfig)
allyesconfig: $(obj)/conf
- $< -y arch/$(ARCH)/Kconfig
+ $< -y $(Kconfig)
allnoconfig: $(obj)/conf
- $< -n arch/$(ARCH)/Kconfig
+ $< -n $(Kconfig)
allmodconfig: $(obj)/conf
- $< -m arch/$(ARCH)/Kconfig
+ $< -m $(Kconfig)
defconfig: $(obj)/conf
ifeq ($(KBUILD_DEFCONFIG),)
- $< -d arch/$(ARCH)/Kconfig
+ $< -d $(Kconfig)
else
- @echo *** Default configuration is based on '$(KBUILD_DEFCONFIG)'
- $(Q)$< -D arch/$(ARCH)/configs/$(KBUILD_DEFCONFIG) arch/$(ARCH)/Kconfig
+ @echo "*** Default configuration is based on '$(KBUILD_DEFCONFIG)'"
+ $(Q)$< -D arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG) $(Kconfig)
endif
%_defconfig: $(obj)/conf
- $(Q)$< -D arch/$(ARCH)/configs/$@ arch/$(ARCH)/Kconfig
+ $(Q)$< -D arch/$(SRCARCH)/configs/$@ $(Kconfig)
# Help text used by make help
help:
@@ -84,7 +86,7 @@ help:
# lxdialog stuff
check-lxdialog := $(srctree)/$(src)/lxdialog/check-lxdialog.sh
-# Use reursively expanded variables so we do not call gcc unless
+# Use recursively expanded variables so we do not call gcc unless
# we really need to do so. (Do not call gcc as part of make mrproper)
HOST_EXTRACFLAGS = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags)
HOST_LOADLIBES = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC))
@@ -143,14 +145,8 @@ clean-files := lkc_defs.h qconf.moc .tmp_qtcheck \
.tmp_gtkcheck zconf.tab.c lex.zconf.c zconf.hash.c
clean-files += mconf qconf gconf
-# Needed for systems without gettext
-KBUILD_HAVE_NLS := $(shell \
- if echo "\#include <libintl.h>" | $(HOSTCC) $(HOSTCFLAGS) -E - > /dev/null 2>&1 ; \
- then echo yes ; \
- else echo no ; fi)
-ifeq ($(KBUILD_HAVE_NLS),no)
-HOSTCFLAGS += -DKBUILD_NO_NLS
-endif
+# Add environment specific flags
+HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(srctree)/$(src)/check.sh $(HOSTCC) $(HOSTCFLAGS))
# generated files seem to need this to find local include files
HOSTCFLAGS_lex.zconf.o := -I$(src)
diff --git a/scripts/kconfig/check.sh b/scripts/kconfig/check.sh
new file mode 100755
index 000000000000..fa59cbf9d62c
--- /dev/null
+++ b/scripts/kconfig/check.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+# Needed for systems without gettext
+$* -xc -o /dev/null - > /dev/null 2>&1 << EOF
+#include <libintl.h>
+int main()
+{
+ gettext("");
+ return 0;
+}
+EOF
+if [ ! "$?" -eq "0" ]; then
+ echo -DKBUILD_NO_NLS;
+fi
+
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index a38787a881ea..c6bee85c3962 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -591,6 +591,7 @@ int main(int ac, char **av)
conf_read_simple(name, S_DEF_USER);
else if (!stat("all.config", &tmpstat))
conf_read_simple("all.config", S_DEF_USER);
+ conf_set_env_sym("K64BIT", "64BIT", S_DEF_USER);
break;
default:
break;
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index b2913e9da495..e4fa3f302541 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -83,6 +83,95 @@ char *conf_get_default_confname(void)
return name;
}
+static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
+{
+ char *p2;
+
+ switch (sym->type) {
+ case S_TRISTATE:
+ if (p[0] == 'm') {
+ sym->def[def].tri = mod;
+ sym->flags |= def_flags;
+ break;
+ }
+ case S_BOOLEAN:
+ if (p[0] == 'y') {
+ sym->def[def].tri = yes;
+ sym->flags |= def_flags;
+ break;
+ }
+ if (p[0] == 'n') {
+ sym->def[def].tri = no;
+ sym->flags |= def_flags;
+ break;
+ }
+ conf_warning("symbol value '%s' invalid for %s", p, sym->name);
+ break;
+ case S_OTHER:
+ if (*p != '"') {
+ for (p2 = p; *p2 && !isspace(*p2); p2++)
+ ;
+ sym->type = S_STRING;
+ goto done;
+ }
+ case S_STRING:
+ if (*p++ != '"')
+ break;
+ for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
+ if (*p2 == '"') {
+ *p2 = 0;
+ break;
+ }
+ memmove(p2, p2 + 1, strlen(p2));
+ }
+ if (!p2) {
+ conf_warning("invalid string found");
+ return 1;
+ }
+ case S_INT:
+ case S_HEX:
+ done:
+ if (sym_string_valid(sym, p)) {
+ sym->def[def].val = strdup(p);
+ sym->flags |= def_flags;
+ } else {
+ conf_warning("symbol value '%s' invalid for %s", p, sym->name);
+ return 1;
+ }
+ break;
+ default:
+ ;
+ }
+ return 0;
+}
+
+/* Read an environment variable and assign the value to the symbol */
+int conf_set_env_sym(const char *env, const char *symname, int def)
+{
+ struct symbol *sym;
+ char *p;
+ int def_flags;
+
+ p = getenv(env);
+ if (p) {
+ char warning[200];
+ sprintf(warning, "Environment variable (%s = \"%s\")", env, p);
+ conf_filename = warning;
+ def_flags = SYMBOL_DEF << def;
+ if (def == S_DEF_USER) {
+ sym = sym_find(symname);
+ if (!sym)
+ return 1;
+ } else {
+ sym = sym_lookup(symname, 0);
+ if (sym->type == S_UNKNOWN)
+ sym->type = S_OTHER;
+ }
+ conf_set_sym_val(sym, def, def_flags, p);
+ }
+ return 0;
+}
+
int conf_read_simple(const char *name, int def)
{
FILE *in = NULL;
@@ -213,61 +302,8 @@ load:
conf_warning("trying to reassign symbol %s", sym->name);
break;
}
- switch (sym->type) {
- case S_TRISTATE:
- if (p[0] == 'm') {
- sym->def[def].tri = mod;
- sym->flags |= def_flags;
- break;
- }
- case S_BOOLEAN:
- if (p[0] == 'y') {
- sym->def[def].tri = yes;
- sym->flags |= def_flags;
- break;
- }
- if (p[0] == 'n') {
- sym->def[def].tri = no;
- sym->flags |= def_flags;
- break;
- }
- conf_warning("symbol value '%s' invalid for %s", p, sym->name);
- break;
- case S_OTHER:
- if (*p != '"') {
- for (p2 = p; *p2 && !isspace(*p2); p2++)
- ;
- sym->type = S_STRING;
- goto done;
- }
- case S_STRING:
- if (*p++ != '"')
- break;
- for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
- if (*p2 == '"') {
- *p2 = 0;
- break;
- }
- memmove(p2, p2 + 1, strlen(p2));
- }
- if (!p2) {
- conf_warning("invalid string found");
- continue;
- }
- case S_INT:
- case S_HEX:
- done:
- if (sym_string_valid(sym, p)) {
- sym->def[def].val = strdup(p);
- sym->flags |= def_flags;
- } else {
- conf_warning("symbol value '%s' invalid for %s", p, sym->name);
- continue;
- }
- break;
- default:
- ;
- }
+ if (conf_set_sym_val(sym, def, def_flags, p))
+ continue;
break;
case '\r':
case '\n':
diff --git a/scripts/kconfig/lex.zconf.c_shipped b/scripts/kconfig/lex.zconf.c_shipped
index 0fdc9049296f..a065d5a57c01 100644
--- a/scripts/kconfig/lex.zconf.c_shipped
+++ b/scripts/kconfig/lex.zconf.c_shipped
@@ -5,6 +5,25 @@
/* A lexical scanner generated by flex */
+#define yy_create_buffer zconf_create_buffer
+#define yy_delete_buffer zconf_delete_buffer
+#define yy_flex_debug zconf_flex_debug
+#define yy_init_buffer zconf_init_buffer
+#define yy_flush_buffer zconf_flush_buffer
+#define yy_load_buffer_state zconf_load_buffer_state
+#define yy_switch_to_buffer zconf_switch_to_buffer
+#define yyin zconfin
+#define yyleng zconfleng
+#define yylex zconflex
+#define yylineno zconflineno
+#define yyout zconfout
+#define yyrestart zconfrestart
+#define yytext zconftext
+#define yywrap zconfwrap
+#define yyalloc zconfalloc
+#define yyrealloc zconfrealloc
+#define yyfree zconffree
+
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 5
@@ -33,7 +52,7 @@
#if __STDC_VERSION__ >= 199901L
/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
- * if you want the limit (max/min) macros for int types.
+ * if you want the limit (max/min) macros for int types.
*/
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS 1
@@ -335,7 +354,7 @@ void zconffree (void * );
/* Begin user sect3 */
-#define zconfwrap() 1
+#define zconfwrap(n) 1
#define YY_SKIP_YYWRAP
typedef unsigned char YY_CHAR;
@@ -1983,7 +2002,7 @@ YY_BUFFER_STATE zconf_scan_buffer (char * base, yy_size_t size )
/** Setup the input buffer state to scan a string. The next call to zconflex() will
* scan from a @e copy of @a str.
- * @param yystr a NUL-terminated string to scan
+ * @param str a NUL-terminated string to scan
*
* @return the newly allocated buffer state object.
* @note If you want to scan bytes that may contain NUL values, then use
diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h
index 4d09f6ddefe3..dca294e90cc3 100644
--- a/scripts/kconfig/lkc_proto.h
+++ b/scripts/kconfig/lkc_proto.h
@@ -1,6 +1,7 @@
/* confdata.c */
P(conf_parse,void,(const char *name));
+P(conf_set_env_sym,int,(const char *envname, const char *symname, int def));
P(conf_read,int,(const char *name));
P(conf_read_simple,int,(const char *name, int));
P(conf_write,int,(const char *name));
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
index bc5854ed6055..47e226fdedd7 100644
--- a/scripts/kconfig/mconf.c
+++ b/scripts/kconfig/mconf.c
@@ -35,9 +35,13 @@ static const char mconf_readme[] = N_(
"kernel parameters which are not really features, but must be\n"
"entered in as decimal or hexadecimal numbers or possibly text.\n"
"\n"
-"Menu items beginning with [*], <M> or [ ] represent features\n"
-"configured to be built in, modularized or removed respectively.\n"
-"Pointed brackets <> represent module capable features.\n"
+"Menu items beginning with following braces represent features that\n"
+" [ ] can be built in or removed\n"
+" < > can be built in, modularized or removed\n"
+" { } can be built in or modularized (selected by other feature)\n"
+" - - are selected by other feature,\n"
+"while *, M or whitespace inside braces means to build in, build as\n"
+"a module or to exclude the feature respectively.\n"
"\n"
"To change any of these features, highlight it with the cursor\n"
"keys and press <Y> to build it in, <M> to make it a module or\n"
@@ -357,8 +361,9 @@ static void get_symbol_str(struct gstr *r, struct symbol *sym)
bool hit;
struct property *prop;
- str_printf(r, "Symbol: %s [=%s]\n", sym->name,
- sym_get_string_value(sym));
+ if (sym && sym->name)
+ str_printf(r, "Symbol: %s [=%s]\n", sym->name,
+ sym_get_string_value(sym));
for_all_prompts(sym, prop)
get_prompt_str(r, prop);
hit = false;
@@ -481,6 +486,14 @@ static void build_conf(struct menu *menu)
if (single_menu_mode && menu->data)
goto conf_childs;
return;
+ case P_COMMENT:
+ if (prompt) {
+ child_count++;
+ item_make(" %*c*** %s ***", indent + 1, ' ', prompt);
+ item_set_tag(':');
+ item_set_data(menu);
+ }
+ break;
default:
if (prompt) {
child_count++;
@@ -560,7 +573,7 @@ static void build_conf(struct menu *menu)
if (sym_is_changable(sym))
item_make("[%c]", val == no ? ' ' : '*');
else
- item_make("---");
+ item_make("-%c-", val == no ? ' ' : '*');
item_set_tag('t');
item_set_data(menu);
break;
@@ -570,10 +583,13 @@ static void build_conf(struct menu *menu)
case mod: ch = 'M'; break;
default: ch = ' '; break;
}
- if (sym_is_changable(sym))
- item_make("<%c>", ch);
- else
- item_make("---");
+ if (sym_is_changable(sym)) {
+ if (sym->rev_dep.tri == mod)
+ item_make("{%c}", ch);
+ else
+ item_make("<%c>", ch);
+ } else
+ item_make("-%c-", ch);
item_set_tag('t');
item_set_data(menu);
break;
diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc
index e4eeb59a8c24..b9bb32dfd628 100644
--- a/scripts/kconfig/qconf.cc
+++ b/scripts/kconfig/qconf.cc
@@ -1274,8 +1274,12 @@ ConfigMainWindow::ConfigMainWindow(void)
QMenuBar* menu;
bool ok;
int x, y, width, height;
+ char title[256];
QWidget *d = configApp->desktop();
+ snprintf(title, sizeof(title), _("Linux Kernel v%s Configuration"),
+ getenv("KERNELVERSION"));
+ setCaption(title);
width = configSettings->readNumEntry("/window width", d->width() - 64);
height = configSettings->readNumEntry("/window height", d->height() - 64);
diff --git a/scripts/kconfig/util.c b/scripts/kconfig/util.c
index e3f28b9d59f4..e1cad924c0a4 100644
--- a/scripts/kconfig/util.c
+++ b/scripts/kconfig/util.c
@@ -84,12 +84,15 @@ void str_free(struct gstr *gs)
/* Append to growable string */
void str_append(struct gstr *gs, const char *s)
{
- size_t l = strlen(gs->s) + strlen(s) + 1;
- if (l > gs->len) {
- gs->s = realloc(gs->s, l);
- gs->len = l;
+ size_t l;
+ if (s) {
+ l = strlen(gs->s) + strlen(s) + 1;
+ if (l > gs->len) {
+ gs->s = realloc(gs->s, l);
+ gs->len = l;
+ }
+ strcat(gs->s, s);
}
- strcat(gs->s, s);
}
/* Append printf formatted string to growable string */
diff --git a/scripts/kconfig/zconf.gperf b/scripts/kconfig/zconf.gperf
index 9b44c80dd899..93538e567bda 100644
--- a/scripts/kconfig/zconf.gperf
+++ b/scripts/kconfig/zconf.gperf
@@ -23,7 +23,6 @@ help, T_HELP, TF_COMMAND
if, T_IF, TF_COMMAND|TF_PARAM
endif, T_ENDIF, TF_COMMAND
depends, T_DEPENDS, TF_COMMAND
-requires, T_REQUIRES, TF_COMMAND
optional, T_OPTIONAL, TF_COMMAND
default, T_DEFAULT, TF_COMMAND, S_UNKNOWN
prompt, T_PROMPT, TF_COMMAND
@@ -32,7 +31,6 @@ def_tristate, T_DEFAULT, TF_COMMAND, S_TRISTATE
bool, T_TYPE, TF_COMMAND, S_BOOLEAN
boolean, T_TYPE, TF_COMMAND, S_BOOLEAN
def_bool, T_DEFAULT, TF_COMMAND, S_BOOLEAN
-def_boolean, T_DEFAULT, TF_COMMAND, S_BOOLEAN
int, T_TYPE, TF_COMMAND, S_INT
hex, T_TYPE, TF_COMMAND, S_HEX
string, T_TYPE, TF_COMMAND, S_STRING
diff --git a/scripts/kconfig/zconf.hash.c_shipped b/scripts/kconfig/zconf.hash.c_shipped
index 47c8b5babf34..ab28b18153a7 100644
--- a/scripts/kconfig/zconf.hash.c_shipped
+++ b/scripts/kconfig/zconf.hash.c_shipped
@@ -1,4 +1,4 @@
-/* ANSI-C code produced by gperf version 3.0.1 */
+/* ANSI-C code produced by gperf version 3.0.2 */
/* Command-line: gperf */
/* Computed positions: -k'1,3' */
@@ -30,7 +30,7 @@
#endif
struct kconf_id;
-/* maximum key range = 45, duplicates = 0 */
+/* maximum key range = 47, duplicates = 0 */
#ifdef __GNUC__
__inline
@@ -44,32 +44,32 @@ kconf_id_hash (register const char *str, register unsigned int len)
{
static unsigned char asso_values[] =
{
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 25, 30, 15,
- 0, 15, 0, 47, 5, 15, 47, 47, 30, 20,
- 5, 0, 25, 15, 0, 0, 10, 35, 47, 47,
- 5, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47
+ 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 18, 11, 5,
+ 0, 0, 5, 49, 5, 20, 49, 49, 5, 20,
+ 5, 0, 30, 49, 0, 15, 0, 10, 49, 49,
+ 25, 49, 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49
};
register int hval = len;
@@ -89,74 +89,70 @@ kconf_id_hash (register const char *str, register unsigned int len)
struct kconf_id_strings_t
{
char kconf_id_strings_str2[sizeof("on")];
- char kconf_id_strings_str6[sizeof("string")];
- char kconf_id_strings_str7[sizeof("default")];
- char kconf_id_strings_str8[sizeof("def_bool")];
+ char kconf_id_strings_str5[sizeof("endif")];
+ char kconf_id_strings_str6[sizeof("option")];
+ char kconf_id_strings_str7[sizeof("endmenu")];
+ char kconf_id_strings_str8[sizeof("optional")];
+ char kconf_id_strings_str9[sizeof("endchoice")];
char kconf_id_strings_str10[sizeof("range")];
- char kconf_id_strings_str11[sizeof("def_boolean")];
- char kconf_id_strings_str12[sizeof("def_tristate")];
- char kconf_id_strings_str13[sizeof("hex")];
- char kconf_id_strings_str14[sizeof("defconfig_list")];
- char kconf_id_strings_str16[sizeof("option")];
- char kconf_id_strings_str17[sizeof("if")];
- char kconf_id_strings_str18[sizeof("optional")];
- char kconf_id_strings_str20[sizeof("endif")];
- char kconf_id_strings_str21[sizeof("choice")];
- char kconf_id_strings_str22[sizeof("endmenu")];
- char kconf_id_strings_str23[sizeof("requires")];
- char kconf_id_strings_str24[sizeof("endchoice")];
- char kconf_id_strings_str26[sizeof("config")];
+ char kconf_id_strings_str11[sizeof("choice")];
+ char kconf_id_strings_str12[sizeof("default")];
+ char kconf_id_strings_str13[sizeof("def_bool")];
+ char kconf_id_strings_str14[sizeof("help")];
+ char kconf_id_strings_str15[sizeof("bool")];
+ char kconf_id_strings_str16[sizeof("config")];
+ char kconf_id_strings_str17[sizeof("def_tristate")];
+ char kconf_id_strings_str18[sizeof("boolean")];
+ char kconf_id_strings_str19[sizeof("defconfig_list")];
+ char kconf_id_strings_str21[sizeof("string")];
+ char kconf_id_strings_str22[sizeof("if")];
+ char kconf_id_strings_str23[sizeof("int")];
+ char kconf_id_strings_str24[sizeof("enable")];
+ char kconf_id_strings_str26[sizeof("select")];
char kconf_id_strings_str27[sizeof("modules")];
- char kconf_id_strings_str28[sizeof("int")];
+ char kconf_id_strings_str28[sizeof("tristate")];
char kconf_id_strings_str29[sizeof("menu")];
- char kconf_id_strings_str31[sizeof("prompt")];
- char kconf_id_strings_str32[sizeof("depends")];
- char kconf_id_strings_str33[sizeof("tristate")];
- char kconf_id_strings_str34[sizeof("bool")];
+ char kconf_id_strings_str31[sizeof("source")];
+ char kconf_id_strings_str32[sizeof("comment")];
+ char kconf_id_strings_str33[sizeof("hex")];
char kconf_id_strings_str35[sizeof("menuconfig")];
- char kconf_id_strings_str36[sizeof("select")];
- char kconf_id_strings_str37[sizeof("boolean")];
- char kconf_id_strings_str39[sizeof("help")];
- char kconf_id_strings_str41[sizeof("source")];
- char kconf_id_strings_str42[sizeof("comment")];
- char kconf_id_strings_str43[sizeof("mainmenu")];
- char kconf_id_strings_str46[sizeof("enable")];
+ char kconf_id_strings_str36[sizeof("prompt")];
+ char kconf_id_strings_str37[sizeof("depends")];
+ char kconf_id_strings_str48[sizeof("mainmenu")];
};
static struct kconf_id_strings_t kconf_id_strings_contents =
{
"on",
- "string",
+ "endif",
+ "option",
+ "endmenu",
+ "optional",
+ "endchoice",
+ "range",
+ "choice",
"default",
"def_bool",
- "range",
- "def_boolean",
+ "help",
+ "bool",
+ "config",
"def_tristate",
- "hex",
+ "boolean",
"defconfig_list",
- "option",
+ "string",
"if",
- "optional",
- "endif",
- "choice",
- "endmenu",
- "requires",
- "endchoice",
- "config",
- "modules",
"int",
- "menu",
- "prompt",
- "depends",
- "tristate",
- "bool",
- "menuconfig",
+ "enable",
"select",
- "boolean",
- "help",
+ "modules",
+ "tristate",
+ "menu",
"source",
"comment",
- "mainmenu",
- "enable"
+ "hex",
+ "menuconfig",
+ "prompt",
+ "depends",
+ "mainmenu"
};
#define kconf_id_strings ((const char *) &kconf_id_strings_contents)
#ifdef __GNUC__
@@ -167,58 +163,54 @@ kconf_id_lookup (register const char *str, register unsigned int len)
{
enum
{
- TOTAL_KEYWORDS = 33,
+ TOTAL_KEYWORDS = 31,
MIN_WORD_LENGTH = 2,
MAX_WORD_LENGTH = 14,
MIN_HASH_VALUE = 2,
- MAX_HASH_VALUE = 46
+ MAX_HASH_VALUE = 48
};
static struct kconf_id wordlist[] =
{
{-1}, {-1},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str2, T_ON, TF_PARAM},
- {-1}, {-1}, {-1},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str6, T_TYPE, TF_COMMAND, S_STRING},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str7, T_DEFAULT, TF_COMMAND, S_UNKNOWN},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str8, T_DEFAULT, TF_COMMAND, S_BOOLEAN},
- {-1},
+ {-1}, {-1},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str5, T_ENDIF, TF_COMMAND},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str6, T_OPTION, TF_COMMAND},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str7, T_ENDMENU, TF_COMMAND},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str8, T_OPTIONAL, TF_COMMAND},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str9, T_ENDCHOICE, TF_COMMAND},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str10, T_RANGE, TF_COMMAND},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str11, T_DEFAULT, TF_COMMAND, S_BOOLEAN},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12, T_DEFAULT, TF_COMMAND, S_TRISTATE},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13, T_TYPE, TF_COMMAND, S_HEX},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14, T_OPT_DEFCONFIG_LIST,TF_OPTION},
- {-1},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str16, T_OPTION, TF_COMMAND},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17, T_IF, TF_COMMAND|TF_PARAM},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18, T_OPTIONAL, TF_COMMAND},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str11, T_CHOICE, TF_COMMAND},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12, T_DEFAULT, TF_COMMAND, S_UNKNOWN},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13, T_DEFAULT, TF_COMMAND, S_BOOLEAN},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14, T_HELP, TF_COMMAND},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str15, T_TYPE, TF_COMMAND, S_BOOLEAN},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str16, T_CONFIG, TF_COMMAND},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17, T_DEFAULT, TF_COMMAND, S_TRISTATE},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18, T_TYPE, TF_COMMAND, S_BOOLEAN},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str19, T_OPT_DEFCONFIG_LIST,TF_OPTION},
{-1},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str20, T_ENDIF, TF_COMMAND},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21, T_CHOICE, TF_COMMAND},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22, T_ENDMENU, TF_COMMAND},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23, T_REQUIRES, TF_COMMAND},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str24, T_ENDCHOICE, TF_COMMAND},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21, T_TYPE, TF_COMMAND, S_STRING},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22, T_IF, TF_COMMAND|TF_PARAM},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23, T_TYPE, TF_COMMAND, S_INT},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str24, T_SELECT, TF_COMMAND},
{-1},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str26, T_CONFIG, TF_COMMAND},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str26, T_SELECT, TF_COMMAND},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str27, T_OPT_MODULES, TF_OPTION},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str28, T_TYPE, TF_COMMAND, S_INT},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str28, T_TYPE, TF_COMMAND, S_TRISTATE},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str29, T_MENU, TF_COMMAND},
{-1},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str31, T_PROMPT, TF_COMMAND},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str32, T_DEPENDS, TF_COMMAND},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str33, T_TYPE, TF_COMMAND, S_TRISTATE},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str34, T_TYPE, TF_COMMAND, S_BOOLEAN},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str35, T_MENUCONFIG, TF_COMMAND},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str36, T_SELECT, TF_COMMAND},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str37, T_TYPE, TF_COMMAND, S_BOOLEAN},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str31, T_SOURCE, TF_COMMAND},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str32, T_COMMENT, TF_COMMAND},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str33, T_TYPE, TF_COMMAND, S_HEX},
{-1},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str39, T_HELP, TF_COMMAND},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str35, T_MENUCONFIG, TF_COMMAND},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str36, T_PROMPT, TF_COMMAND},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str37, T_DEPENDS, TF_COMMAND},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str41, T_SOURCE, TF_COMMAND},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str42, T_COMMENT, TF_COMMAND},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str43, T_MAINMENU, TF_COMMAND},
- {-1}, {-1},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str46, T_SELECT, TF_COMMAND}
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str48, T_MAINMENU, TF_COMMAND}
};
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
diff --git a/scripts/kconfig/zconf.tab.c_shipped b/scripts/kconfig/zconf.tab.c_shipped
index ec21db77f78b..d22d92496f25 100644
--- a/scripts/kconfig/zconf.tab.c_shipped
+++ b/scripts/kconfig/zconf.tab.c_shipped
@@ -1,7 +1,9 @@
-/* A Bison parser, made by GNU Bison 2.1. */
+/* A Bison parser, made by GNU Bison 2.3. */
-/* Skeleton parser for Yacc-like parsing with Bison,
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
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
@@ -18,13 +20,21 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
-/* As a special exception, when this file is copied by Bison into a
- Bison output file, you may use that output file without restriction.
- This special exception was added by the Free Software Foundation
- in version 1.24 of Bison. */
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
-/* Written by Richard Stallman by simplifying the original so called
- ``semantic'' parser. */
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
/* All symbols defined below should begin with yy or YY, to avoid
infringing on user name space. This should be done even for local
@@ -37,7 +47,7 @@
#define YYBISON 1
/* Bison version. */
-#define YYBISON_VERSION "2.1"
+#define YYBISON_VERSION "2.3"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -78,25 +88,24 @@
T_IF = 269,
T_ENDIF = 270,
T_DEPENDS = 271,
- T_REQUIRES = 272,
- T_OPTIONAL = 273,
- T_PROMPT = 274,
- T_TYPE = 275,
- T_DEFAULT = 276,
- T_SELECT = 277,
- T_RANGE = 278,
- T_OPTION = 279,
- T_ON = 280,
- T_WORD = 281,
- T_WORD_QUOTE = 282,
- T_UNEQUAL = 283,
- T_CLOSE_PAREN = 284,
- T_OPEN_PAREN = 285,
- T_EOL = 286,
- T_OR = 287,
- T_AND = 288,
- T_EQUAL = 289,
- T_NOT = 290
+ T_OPTIONAL = 272,
+ T_PROMPT = 273,
+ T_TYPE = 274,
+ T_DEFAULT = 275,
+ T_SELECT = 276,
+ T_RANGE = 277,
+ T_OPTION = 278,
+ T_ON = 279,
+ T_WORD = 280,
+ T_WORD_QUOTE = 281,
+ T_UNEQUAL = 282,
+ T_CLOSE_PAREN = 283,
+ T_OPEN_PAREN = 284,
+ T_EOL = 285,
+ T_OR = 286,
+ T_AND = 287,
+ T_EQUAL = 288,
+ T_NOT = 289
};
#endif
/* Tokens. */
@@ -114,25 +123,24 @@
#define T_IF 269
#define T_ENDIF 270
#define T_DEPENDS 271
-#define T_REQUIRES 272
-#define T_OPTIONAL 273
-#define T_PROMPT 274
-#define T_TYPE 275
-#define T_DEFAULT 276
-#define T_SELECT 277
-#define T_RANGE 278
-#define T_OPTION 279
-#define T_ON 280
-#define T_WORD 281
-#define T_WORD_QUOTE 282
-#define T_UNEQUAL 283
-#define T_CLOSE_PAREN 284
-#define T_OPEN_PAREN 285
-#define T_EOL 286
-#define T_OR 287
-#define T_AND 288
-#define T_EQUAL 289
-#define T_NOT 290
+#define T_OPTIONAL 272
+#define T_PROMPT 273
+#define T_TYPE 274
+#define T_DEFAULT 275
+#define T_SELECT 276
+#define T_RANGE 277
+#define T_OPTION 278
+#define T_ON 279
+#define T_WORD 280
+#define T_WORD_QUOTE 281
+#define T_UNEQUAL 282
+#define T_CLOSE_PAREN 283
+#define T_OPEN_PAREN 284
+#define T_EOL 285
+#define T_OR 286
+#define T_AND 287
+#define T_EQUAL 288
+#define T_NOT 289
@@ -198,18 +206,20 @@ static struct menu *current_menu, *current_entry;
# define YYTOKEN_TABLE 0
#endif
-#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
-typedef union YYSTYPE {
+{
char *string;
struct file *file;
struct symbol *symbol;
struct expr *expr;
struct menu *menu;
struct kconf_id *id;
-} YYSTYPE;
-/* Line 196 of yacc.c. */
+}
+/* Line 187 of yacc.c. */
+ YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
# define YYSTYPE_IS_TRIVIAL 1
@@ -220,23 +230,56 @@ typedef union YYSTYPE {
/* Copy the second part of user declarations. */
-/* Line 219 of yacc.c. */
+/* Line 216 of yacc.c. */
+
+
+#ifdef short
+# undef short
+#endif
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
-#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
-# define YYSIZE_T __SIZE_TYPE__
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
#endif
-#if ! defined (YYSIZE_T) && defined (size_t)
-# define YYSIZE_T size_t
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
#endif
-#if ! defined (YYSIZE_T) && (defined (__STDC__) || defined (__cplusplus))
-# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-# define YYSIZE_T size_t
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
#endif
-#if ! defined (YYSIZE_T)
-# define YYSIZE_T unsigned int
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned int
+# endif
#endif
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
#ifndef YY_
# if YYENABLE_NLS
# if ENABLE_NLS
@@ -249,7 +292,32 @@ typedef union YYSTYPE {
# endif
#endif
-#if ! defined (yyoverflow) || YYERROR_VERBOSE
+/* Suppress unused-variable warnings by "using" E. */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions. */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int i)
+#else
+static int
+YYID (i)
+ int i;
+#endif
+{
+ return i;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
/* The parser invokes alloca or malloc; define the necessary symbols. */
@@ -257,64 +325,76 @@ typedef union YYSTYPE {
# if YYSTACK_USE_ALLOCA
# ifdef __GNUC__
# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
# else
# define YYSTACK_ALLOC alloca
-# if defined (__STDC__) || defined (__cplusplus)
+# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-# define YYINCLUDED_STDLIB_H
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
# endif
# endif
# endif
# endif
# ifdef YYSTACK_ALLOC
- /* Pacify GCC's `empty if-body' warning. */
-# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+ /* Pacify GCC's `empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
# ifndef YYSTACK_ALLOC_MAXIMUM
/* The OS might guarantee only one guard page at the bottom of the stack,
and a page size can be as small as 4096 bytes. So we cannot safely
invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
to allow for a few compiler-allocated temporary stack slots. */
-# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2005 */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
# endif
# else
# define YYSTACK_ALLOC YYMALLOC
# define YYSTACK_FREE YYFREE
# ifndef YYSTACK_ALLOC_MAXIMUM
-# define YYSTACK_ALLOC_MAXIMUM ((YYSIZE_T) -1)
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
# endif
-# ifdef __cplusplus
-extern "C" {
+# if (defined __cplusplus && ! defined _STDLIB_H \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
# endif
# ifndef YYMALLOC
# define YYMALLOC malloc
-# if (! defined (malloc) && ! defined (YYINCLUDED_STDLIB_H) \
- && (defined (__STDC__) || defined (__cplusplus)))
+# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
# endif
# endif
# ifndef YYFREE
# define YYFREE free
-# if (! defined (free) && ! defined (YYINCLUDED_STDLIB_H) \
- && (defined (__STDC__) || defined (__cplusplus)))
+# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
void free (void *); /* INFRINGES ON USER NAME SPACE */
# endif
# endif
-# ifdef __cplusplus
-}
-# endif
# endif
-#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
-#if (! defined (yyoverflow) \
- && (! defined (__cplusplus) \
- || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL)))
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
/* A type that is properly aligned for any stack member. */
union yyalloc
{
- short int yyss;
+ yytype_int16 yyss;
YYSTYPE yyvs;
};
@@ -324,13 +404,13 @@ union yyalloc
/* The size of an array large to enough to hold all stacks, each with
N elements. */
# define YYSTACK_BYTES(N) \
- ((N) * (sizeof (short int) + sizeof (YYSTYPE)) \
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ YYSTACK_GAP_MAXIMUM)
/* Copy COUNT objects from FROM to TO. The source and destination do
not overlap. */
# ifndef YYCOPY
-# if defined (__GNUC__) && 1 < __GNUC__
+# if defined __GNUC__ && 1 < __GNUC__
# define YYCOPY(To, From, Count) \
__builtin_memcpy (To, From, (Count) * sizeof (*(From)))
# else
@@ -341,7 +421,7 @@ union yyalloc
for (yyi = 0; yyi < (Count); yyi++) \
(To)[yyi] = (From)[yyi]; \
} \
- while (0)
+ while (YYID (0))
# endif
# endif
@@ -359,39 +439,33 @@ union yyalloc
yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
yyptr += yynewbytes / sizeof (*yyptr); \
} \
- while (0)
+ while (YYID (0))
#endif
-#if defined (__STDC__) || defined (__cplusplus)
- typedef signed char yysigned_char;
-#else
- typedef short int yysigned_char;
-#endif
-
-/* YYFINAL -- State number of the termination state. */
+/* YYFINAL -- State number of the termination state. */
#define YYFINAL 3
/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 275
+#define YYLAST 258
-/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 36
-/* YYNNTS -- Number of nonterminals. */
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 35
+/* YYNNTS -- Number of nonterminals. */
#define YYNNTS 45
-/* YYNRULES -- Number of rules. */
-#define YYNRULES 110
-/* YYNRULES -- Number of states. */
-#define YYNSTATES 183
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 108
+/* YYNRULES -- Number of states. */
+#define YYNSTATES 178
/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
#define YYUNDEFTOK 2
-#define YYMAXUTOK 290
+#define YYMAXUTOK 289
#define YYTRANSLATE(YYX) \
((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
-static const unsigned char yytranslate[] =
+static const yytype_uint8 yytranslate[] =
{
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -421,14 +495,13 @@ static const unsigned char yytranslate[] =
2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
- 35
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34
};
#if YYDEBUG
/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
YYRHS. */
-static const unsigned short int yyprhs[] =
+static const yytype_uint16 yyprhs[] =
{
0, 0, 3, 5, 6, 9, 12, 15, 20, 23,
28, 33, 37, 39, 41, 43, 45, 47, 49, 51,
@@ -439,80 +512,77 @@ static const unsigned short int yyprhs[] =
178, 181, 186, 187, 190, 194, 196, 200, 201, 204,
207, 210, 214, 217, 219, 223, 224, 227, 230, 233,
237, 241, 244, 247, 250, 251, 254, 257, 260, 265,
- 269, 273, 274, 277, 279, 281, 284, 287, 290, 292,
- 295, 296, 299, 301, 305, 309, 313, 316, 320, 324,
- 326
+ 266, 269, 271, 273, 276, 279, 282, 284, 287, 288,
+ 291, 293, 297, 301, 305, 308, 312, 316, 318
};
-/* YYRHS -- A `-1'-separated list of the rules' RHS. */
-static const yysigned_char yyrhs[] =
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yytype_int8 yyrhs[] =
{
- 37, 0, -1, 38, -1, -1, 38, 40, -1, 38,
- 54, -1, 38, 65, -1, 38, 3, 75, 77, -1,
- 38, 76, -1, 38, 26, 1, 31, -1, 38, 39,
- 1, 31, -1, 38, 1, 31, -1, 16, -1, 19,
- -1, 20, -1, 22, -1, 18, -1, 23, -1, 21,
- -1, 31, -1, 60, -1, 69, -1, 43, -1, 45,
- -1, 67, -1, 26, 1, 31, -1, 1, 31, -1,
- 10, 26, 31, -1, 42, 46, -1, 11, 26, 31,
- -1, 44, 46, -1, -1, 46, 47, -1, 46, 48,
- -1, 46, 73, -1, 46, 71, -1, 46, 41, -1,
- 46, 31, -1, 20, 74, 31, -1, 19, 75, 78,
- 31, -1, 21, 79, 78, 31, -1, 22, 26, 78,
- 31, -1, 23, 80, 80, 78, 31, -1, 24, 49,
- 31, -1, -1, 49, 26, 50, -1, -1, 34, 75,
- -1, 7, 31, -1, 51, 55, -1, 76, -1, 52,
- 57, 53, -1, -1, 55, 56, -1, 55, 73, -1,
- 55, 71, -1, 55, 31, -1, 55, 41, -1, 19,
- 75, 78, 31, -1, 20, 74, 31, -1, 18, 31,
- -1, 21, 26, 78, 31, -1, -1, 57, 40, -1,
- 14, 79, 77, -1, 76, -1, 58, 61, 59, -1,
- -1, 61, 40, -1, 61, 65, -1, 61, 54, -1,
- 4, 75, 31, -1, 62, 72, -1, 76, -1, 63,
- 66, 64, -1, -1, 66, 40, -1, 66, 65, -1,
- 66, 54, -1, 6, 75, 31, -1, 9, 75, 31,
- -1, 68, 72, -1, 12, 31, -1, 70, 13, -1,
- -1, 72, 73, -1, 72, 31, -1, 72, 41, -1,
- 16, 25, 79, 31, -1, 16, 79, 31, -1, 17,
- 79, 31, -1, -1, 75, 78, -1, 26, -1, 27,
- -1, 5, 31, -1, 8, 31, -1, 15, 31, -1,
- 31, -1, 77, 31, -1, -1, 14, 79, -1, 80,
- -1, 80, 34, 80, -1, 80, 28, 80, -1, 30,
- 79, 29, -1, 35, 79, -1, 79, 32, 79, -1,
- 79, 33, 79, -1, 26, -1, 27, -1
+ 36, 0, -1, 37, -1, -1, 37, 39, -1, 37,
+ 53, -1, 37, 64, -1, 37, 3, 74, 76, -1,
+ 37, 75, -1, 37, 25, 1, 30, -1, 37, 38,
+ 1, 30, -1, 37, 1, 30, -1, 16, -1, 18,
+ -1, 19, -1, 21, -1, 17, -1, 22, -1, 20,
+ -1, 30, -1, 59, -1, 68, -1, 42, -1, 44,
+ -1, 66, -1, 25, 1, 30, -1, 1, 30, -1,
+ 10, 25, 30, -1, 41, 45, -1, 11, 25, 30,
+ -1, 43, 45, -1, -1, 45, 46, -1, 45, 47,
+ -1, 45, 72, -1, 45, 70, -1, 45, 40, -1,
+ 45, 30, -1, 19, 73, 30, -1, 18, 74, 77,
+ 30, -1, 20, 78, 77, 30, -1, 21, 25, 77,
+ 30, -1, 22, 79, 79, 77, 30, -1, 23, 48,
+ 30, -1, -1, 48, 25, 49, -1, -1, 33, 74,
+ -1, 7, 30, -1, 50, 54, -1, 75, -1, 51,
+ 56, 52, -1, -1, 54, 55, -1, 54, 72, -1,
+ 54, 70, -1, 54, 30, -1, 54, 40, -1, 18,
+ 74, 77, 30, -1, 19, 73, 30, -1, 17, 30,
+ -1, 20, 25, 77, 30, -1, -1, 56, 39, -1,
+ 14, 78, 76, -1, 75, -1, 57, 60, 58, -1,
+ -1, 60, 39, -1, 60, 64, -1, 60, 53, -1,
+ 4, 74, 30, -1, 61, 71, -1, 75, -1, 62,
+ 65, 63, -1, -1, 65, 39, -1, 65, 64, -1,
+ 65, 53, -1, 6, 74, 30, -1, 9, 74, 30,
+ -1, 67, 71, -1, 12, 30, -1, 69, 13, -1,
+ -1, 71, 72, -1, 71, 30, -1, 71, 40, -1,
+ 16, 24, 78, 30, -1, -1, 74, 77, -1, 25,
+ -1, 26, -1, 5, 30, -1, 8, 30, -1, 15,
+ 30, -1, 30, -1, 76, 30, -1, -1, 14, 78,
+ -1, 79, -1, 79, 33, 79, -1, 79, 27, 79,
+ -1, 29, 78, 28, -1, 34, 78, -1, 78, 31,
+ 78, -1, 78, 32, 78, -1, 25, -1, 26, -1
};
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
-static const unsigned short int yyrline[] =
+static const yytype_uint16 yyrline[] =
{
- 0, 105, 105, 107, 109, 110, 111, 112, 113, 114,
- 115, 119, 123, 123, 123, 123, 123, 123, 123, 127,
- 128, 129, 130, 131, 132, 136, 137, 143, 151, 157,
- 165, 175, 177, 178, 179, 180, 181, 182, 185, 193,
- 199, 209, 215, 221, 224, 226, 237, 238, 243, 252,
- 257, 265, 268, 270, 271, 272, 273, 274, 277, 283,
- 294, 300, 310, 312, 317, 325, 333, 336, 338, 339,
- 340, 345, 352, 357, 365, 368, 370, 371, 372, 375,
- 383, 390, 397, 403, 410, 412, 413, 414, 417, 422,
- 427, 435, 437, 442, 443, 446, 447, 448, 452, 453,
- 456, 457, 460, 461, 462, 463, 464, 465, 466, 469,
- 470
+ 0, 104, 104, 106, 108, 109, 110, 111, 112, 113,
+ 114, 118, 122, 122, 122, 122, 122, 122, 122, 126,
+ 127, 128, 129, 130, 131, 135, 136, 142, 150, 156,
+ 164, 174, 176, 177, 178, 179, 180, 181, 184, 192,
+ 198, 208, 214, 220, 223, 225, 236, 237, 242, 251,
+ 256, 264, 267, 269, 270, 271, 272, 273, 276, 282,
+ 293, 299, 309, 311, 316, 324, 332, 335, 337, 338,
+ 339, 344, 351, 356, 364, 367, 369, 370, 371, 374,
+ 382, 389, 396, 402, 409, 411, 412, 413, 416, 424,
+ 426, 431, 432, 435, 436, 437, 441, 442, 445, 446,
+ 449, 450, 451, 452, 453, 454, 455, 458, 459
};
#endif
#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
- First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
static const char *const yytname[] =
{
"$end", "error", "$undefined", "T_MAINMENU", "T_MENU", "T_ENDMENU",
"T_SOURCE", "T_CHOICE", "T_ENDCHOICE", "T_COMMENT", "T_CONFIG",
"T_MENUCONFIG", "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS",
- "T_REQUIRES", "T_OPTIONAL", "T_PROMPT", "T_TYPE", "T_DEFAULT",
- "T_SELECT", "T_RANGE", "T_OPTION", "T_ON", "T_WORD", "T_WORD_QUOTE",
- "T_UNEQUAL", "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_EOL", "T_OR", "T_AND",
- "T_EQUAL", "T_NOT", "$accept", "input", "stmt_list", "option_name",
- "common_stmt", "option_error", "config_entry_start", "config_stmt",
+ "T_OPTIONAL", "T_PROMPT", "T_TYPE", "T_DEFAULT", "T_SELECT", "T_RANGE",
+ "T_OPTION", "T_ON", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL",
+ "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_EOL", "T_OR", "T_AND", "T_EQUAL",
+ "T_NOT", "$accept", "input", "stmt_list", "option_name", "common_stmt",
+ "option_error", "config_entry_start", "config_stmt",
"menuconfig_entry_start", "menuconfig_stmt", "config_option_list",
"config_option", "symbol_option", "symbol_option_list",
"symbol_option_arg", "choice", "choice_entry", "choice_end",
@@ -527,34 +597,33 @@ static const char *const yytname[] =
# ifdef YYPRINT
/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
token YYLEX-NUM. */
-static const unsigned short int yytoknum[] =
+static const yytype_uint16 yytoknum[] =
{
0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
- 285, 286, 287, 288, 289, 290
+ 285, 286, 287, 288, 289
};
# endif
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
-static const unsigned char yyr1[] =
+static const yytype_uint8 yyr1[] =
{
- 0, 36, 37, 38, 38, 38, 38, 38, 38, 38,
- 38, 38, 39, 39, 39, 39, 39, 39, 39, 40,
- 40, 40, 40, 40, 40, 41, 41, 42, 43, 44,
- 45, 46, 46, 46, 46, 46, 46, 46, 47, 47,
- 47, 47, 47, 48, 49, 49, 50, 50, 51, 52,
- 53, 54, 55, 55, 55, 55, 55, 55, 56, 56,
- 56, 56, 57, 57, 58, 59, 60, 61, 61, 61,
- 61, 62, 63, 64, 65, 66, 66, 66, 66, 67,
- 68, 69, 70, 71, 72, 72, 72, 72, 73, 73,
- 73, 74, 74, 75, 75, 76, 76, 76, 77, 77,
- 78, 78, 79, 79, 79, 79, 79, 79, 79, 80,
- 80
+ 0, 35, 36, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 38, 38, 38, 38, 38, 38, 38, 39,
+ 39, 39, 39, 39, 39, 40, 40, 41, 42, 43,
+ 44, 45, 45, 45, 45, 45, 45, 45, 46, 46,
+ 46, 46, 46, 47, 48, 48, 49, 49, 50, 51,
+ 52, 53, 54, 54, 54, 54, 54, 54, 55, 55,
+ 55, 55, 56, 56, 57, 58, 59, 60, 60, 60,
+ 60, 61, 62, 63, 64, 65, 65, 65, 65, 66,
+ 67, 68, 69, 70, 71, 71, 71, 71, 72, 73,
+ 73, 74, 74, 75, 75, 75, 76, 76, 77, 77,
+ 78, 78, 78, 78, 78, 78, 78, 79, 79
};
/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
-static const unsigned char yyr2[] =
+static const yytype_uint8 yyr2[] =
{
0, 2, 1, 0, 2, 2, 2, 4, 2, 4,
4, 3, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -564,82 +633,79 @@ static const unsigned char yyr2[] =
1, 3, 0, 2, 2, 2, 2, 2, 4, 3,
2, 4, 0, 2, 3, 1, 3, 0, 2, 2,
2, 3, 2, 1, 3, 0, 2, 2, 2, 3,
- 3, 2, 2, 2, 0, 2, 2, 2, 4, 3,
- 3, 0, 2, 1, 1, 2, 2, 2, 1, 2,
- 0, 2, 1, 3, 3, 3, 2, 3, 3, 1,
- 1
+ 3, 2, 2, 2, 0, 2, 2, 2, 4, 0,
+ 2, 1, 1, 2, 2, 2, 1, 2, 0, 2,
+ 1, 3, 3, 3, 2, 3, 3, 1, 1
};
/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
STATE-NUM when YYTABLE doesn't specify something else to do. Zero
means the default is an error. */
-static const unsigned char yydefact[] =
+static const yytype_uint8 yydefact[] =
{
3, 0, 0, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 12, 16, 13, 14,
18, 15, 17, 0, 19, 0, 4, 31, 22, 31,
23, 52, 62, 5, 67, 20, 84, 75, 6, 24,
- 84, 21, 8, 11, 93, 94, 0, 0, 95, 0,
- 48, 96, 0, 0, 0, 109, 110, 0, 0, 0,
- 102, 97, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 98, 7, 71, 79, 80, 27, 29, 0,
- 106, 0, 0, 64, 0, 0, 9, 10, 0, 0,
- 0, 0, 0, 91, 0, 0, 0, 44, 0, 37,
- 36, 32, 33, 0, 35, 34, 0, 0, 91, 0,
- 56, 57, 53, 55, 54, 63, 51, 50, 68, 70,
- 66, 69, 65, 86, 87, 85, 76, 78, 74, 77,
- 73, 99, 105, 107, 108, 104, 103, 26, 82, 0,
- 0, 0, 100, 0, 100, 100, 100, 0, 0, 0,
- 83, 60, 100, 0, 100, 0, 89, 90, 0, 0,
- 38, 92, 0, 0, 100, 46, 43, 25, 0, 59,
- 0, 88, 101, 39, 40, 41, 0, 0, 45, 58,
- 61, 42, 47
+ 84, 21, 8, 11, 91, 92, 0, 0, 93, 0,
+ 48, 94, 0, 0, 0, 107, 108, 0, 0, 0,
+ 100, 95, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 96, 7, 71, 79, 80, 27, 29, 0,
+ 104, 0, 0, 64, 0, 0, 9, 10, 0, 0,
+ 0, 0, 89, 0, 0, 0, 44, 0, 37, 36,
+ 32, 33, 0, 35, 34, 0, 0, 89, 0, 56,
+ 57, 53, 55, 54, 63, 51, 50, 68, 70, 66,
+ 69, 65, 86, 87, 85, 76, 78, 74, 77, 73,
+ 97, 103, 105, 106, 102, 101, 26, 82, 0, 98,
+ 0, 98, 98, 98, 0, 0, 0, 83, 60, 98,
+ 0, 98, 0, 0, 0, 38, 90, 0, 0, 98,
+ 46, 43, 25, 0, 59, 0, 88, 99, 39, 40,
+ 41, 0, 0, 45, 58, 61, 42, 47
};
-/* YYDEFGOTO[NTERM-NUM]. */
-static const short int yydefgoto[] =
+/* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int16 yydefgoto[] =
{
- -1, 1, 2, 25, 26, 100, 27, 28, 29, 30,
- 64, 101, 102, 148, 178, 31, 32, 116, 33, 66,
- 112, 67, 34, 120, 35, 68, 36, 37, 128, 38,
- 70, 39, 40, 41, 103, 104, 69, 105, 143, 144,
- 42, 73, 159, 59, 60
+ -1, 1, 2, 25, 26, 99, 27, 28, 29, 30,
+ 64, 100, 101, 145, 173, 31, 32, 115, 33, 66,
+ 111, 67, 34, 119, 35, 68, 36, 37, 127, 38,
+ 70, 39, 40, 41, 102, 103, 69, 104, 140, 141,
+ 42, 73, 154, 59, 60
};
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
STATE-NUM. */
-#define YYPACT_NINF -135
-static const short int yypact[] =
+#define YYPACT_NINF -78
+static const yytype_int16 yypact[] =
{
- -135, 2, 170, -135, -14, 56, 56, -8, 56, 24,
- 67, 56, 7, 14, 62, 97, -135, -135, -135, -135,
- -135, -135, -135, 156, -135, 166, -135, -135, -135, -135,
- -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
- -135, -135, -135, -135, -135, -135, 138, 151, -135, 152,
- -135, -135, 163, 167, 176, -135, -135, 62, 62, 185,
- -19, -135, 188, 190, 42, 103, 194, 85, 70, 222,
- 70, 132, -135, 191, -135, -135, -135, -135, -135, 127,
- -135, 62, 62, 191, 104, 104, -135, -135, 193, 203,
- 9, 62, 56, 56, 62, 161, 104, -135, 196, -135,
- -135, -135, -135, 233, -135, -135, 204, 56, 56, 221,
- -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
- -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
- -135, -135, -135, 219, -135, -135, -135, -135, -135, 62,
- 209, 212, 240, 224, 240, -1, 240, 104, 41, 225,
- -135, -135, 240, 226, 240, 218, -135, -135, 62, 227,
- -135, -135, 228, 229, 240, 230, -135, -135, 231, -135,
- 232, -135, 112, -135, -135, -135, 234, 56, -135, -135,
- -135, -135, -135
+ -78, 33, 130, -78, -28, 73, 73, 7, 73, 36,
+ 41, 73, 26, 52, -4, 58, -78, -78, -78, -78,
+ -78, -78, -78, 90, -78, 94, -78, -78, -78, -78,
+ -78, -78, -78, -78, -78, -78, -78, -78, -78, -78,
+ -78, -78, -78, -78, -78, -78, 74, 85, -78, 96,
+ -78, -78, 131, 134, 147, -78, -78, -4, -4, 193,
+ -10, -78, 162, 164, 38, 102, 64, 148, 5, 192,
+ 5, 165, -78, 174, -78, -78, -78, -78, -78, 65,
+ -78, -4, -4, 174, 103, 103, -78, -78, 175, 185,
+ 197, 73, 73, -4, 194, 103, -78, 231, -78, -78,
+ -78, -78, 220, -78, -78, 204, 73, 73, 210, -78,
+ -78, -78, -78, -78, -78, -78, -78, -78, -78, -78,
+ -78, -78, -78, -78, -78, -78, -78, -78, -78, -78,
+ -78, -78, 205, -78, -78, -78, -78, -78, -4, 222,
+ 208, 222, 195, 222, 103, 2, 209, -78, -78, 222,
+ 211, 222, 199, -4, 212, -78, -78, 213, 214, 222,
+ 207, -78, -78, 215, -78, 216, -78, 111, -78, -78,
+ -78, 217, 73, -78, -78, -78, -78, -78
};
/* YYPGOTO[NTERM-NUM]. */
-static const short int yypgoto[] =
+static const yytype_int16 yypgoto[] =
{
- -135, -135, -135, -135, 94, -45, -135, -135, -135, -135,
- 237, -135, -135, -135, -135, -135, -135, -135, -54, -135,
- -135, -135, -135, -135, -135, -135, -135, -135, -135, 1,
- -135, -135, -135, -135, -135, 195, 235, -44, 159, -5,
- 98, 210, -134, -53, -77
+ -78, -78, -78, -78, 121, -35, -78, -78, -78, -78,
+ 219, -78, -78, -78, -78, -78, -78, -78, -44, -78,
+ -78, -78, -78, -78, -78, -78, -78, -78, -78, -6,
+ -78, -78, -78, -78, -78, 183, 218, 21, 143, -5,
+ 146, 196, 69, -53, -77
};
/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
@@ -647,93 +713,88 @@ static const short int yypgoto[] =
number is the opposite. If zero, do what YYDEFACT says.
If YYTABLE_NINF, syntax error. */
#define YYTABLE_NINF -82
-static const short int yytable[] =
+static const yytype_int16 yytable[] =
{
- 46, 47, 3, 49, 79, 80, 52, 135, 136, 84,
- 161, 162, 163, 158, 119, 85, 127, 43, 168, 147,
- 170, 111, 114, 48, 124, 125, 124, 125, 133, 134,
- 176, 81, 82, 53, 139, 55, 56, 140, 141, 57,
- 54, 145, -28, 88, 58, -28, -28, -28, -28, -28,
- -28, -28, -28, -28, 89, 50, -28, -28, 90, 91,
- -28, 92, 93, 94, 95, 96, 97, 165, 98, 121,
- 164, 129, 166, 99, 6, 7, 8, 9, 10, 11,
- 12, 13, 44, 45, 14, 15, 155, 142, 55, 56,
- 7, 8, 57, 10, 11, 12, 13, 58, 51, 14,
- 15, 24, 152, -30, 88, 172, -30, -30, -30, -30,
- -30, -30, -30, -30, -30, 89, 24, -30, -30, 90,
- 91, -30, 92, 93, 94, 95, 96, 97, 61, 98,
- 55, 56, -81, 88, 99, -81, -81, -81, -81, -81,
- -81, -81, -81, -81, 81, 82, -81, -81, 90, 91,
- -81, -81, -81, -81, -81, -81, 132, 62, 98, 81,
- 82, 115, 118, 123, 126, 117, 122, 63, 130, 72,
- -2, 4, 182, 5, 6, 7, 8, 9, 10, 11,
- 12, 13, 74, 75, 14, 15, 16, 146, 17, 18,
- 19, 20, 21, 22, 76, 88, 23, 149, 77, -49,
- -49, 24, -49, -49, -49, -49, 89, 78, -49, -49,
- 90, 91, 106, 107, 108, 109, 72, 81, 82, 86,
- 98, 87, 131, 88, 137, 110, -72, -72, -72, -72,
- -72, -72, -72, -72, 138, 151, -72, -72, 90, 91,
- 156, 81, 82, 157, 81, 82, 150, 154, 98, 171,
- 81, 82, 82, 123, 158, 160, 167, 169, 173, 174,
- 175, 113, 179, 180, 177, 181, 65, 153, 0, 83,
- 0, 0, 0, 0, 0, 71
+ 46, 47, 43, 49, 79, 80, 52, 134, 135, 6,
+ 7, 8, 9, 10, 11, 12, 13, 84, 144, 14,
+ 15, 55, 56, 85, 118, 57, 126, 160, 132, 133,
+ 58, 110, 161, 3, 123, 24, 123, 48, -28, 88,
+ 142, -28, -28, -28, -28, -28, -28, -28, -28, -28,
+ 89, 53, -28, -28, 90, -28, 91, 92, 93, 94,
+ 95, 96, 120, 97, 128, 88, 50, 159, 98, -49,
+ -49, 51, -49, -49, -49, -49, 89, 54, -49, -49,
+ 90, 105, 106, 107, 108, 152, 139, 113, 61, 97,
+ 124, 62, 124, 131, 109, 63, 81, 82, 44, 45,
+ 167, 149, -30, 88, 72, -30, -30, -30, -30, -30,
+ -30, -30, -30, -30, 89, 74, -30, -30, 90, -30,
+ 91, 92, 93, 94, 95, 96, 75, 97, 55, 56,
+ -2, 4, 98, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 81, 82, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 7, 8, 23, 10, 11, 12, 13,
+ 24, 76, 14, 15, 77, -81, 88, 177, -81, -81,
+ -81, -81, -81, -81, -81, -81, -81, 78, 24, -81,
+ -81, 90, -81, -81, -81, -81, -81, -81, 114, 117,
+ 97, 125, 86, 88, 87, 122, -72, -72, -72, -72,
+ -72, -72, -72, -72, 130, 136, -72, -72, 90, 153,
+ 156, 157, 158, 116, 121, 137, 129, 97, 163, 143,
+ 165, 138, 122, 72, 81, 82, 81, 82, 171, 166,
+ 81, 82, 146, 147, 148, 151, 153, 82, 155, 162,
+ 172, 164, 168, 169, 170, 174, 175, 176, 65, 112,
+ 150, 0, 0, 0, 0, 83, 0, 0, 71
};
-static const short int yycheck[] =
+static const yytype_int16 yycheck[] =
{
- 5, 6, 0, 8, 57, 58, 11, 84, 85, 28,
- 144, 145, 146, 14, 68, 34, 70, 31, 152, 96,
- 154, 66, 66, 31, 69, 69, 71, 71, 81, 82,
- 164, 32, 33, 26, 25, 26, 27, 90, 91, 30,
- 26, 94, 0, 1, 35, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 31, 14, 15, 16, 17,
- 18, 19, 20, 21, 22, 23, 24, 26, 26, 68,
- 147, 70, 31, 31, 4, 5, 6, 7, 8, 9,
- 10, 11, 26, 27, 14, 15, 139, 92, 26, 27,
- 5, 6, 30, 8, 9, 10, 11, 35, 31, 14,
- 15, 31, 107, 0, 1, 158, 3, 4, 5, 6,
- 7, 8, 9, 10, 11, 12, 31, 14, 15, 16,
- 17, 18, 19, 20, 21, 22, 23, 24, 31, 26,
- 26, 27, 0, 1, 31, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 32, 33, 14, 15, 16, 17,
- 18, 19, 20, 21, 22, 23, 29, 1, 26, 32,
- 33, 67, 68, 31, 70, 67, 68, 1, 70, 31,
- 0, 1, 177, 3, 4, 5, 6, 7, 8, 9,
- 10, 11, 31, 31, 14, 15, 16, 26, 18, 19,
- 20, 21, 22, 23, 31, 1, 26, 1, 31, 5,
- 6, 31, 8, 9, 10, 11, 12, 31, 14, 15,
- 16, 17, 18, 19, 20, 21, 31, 32, 33, 31,
- 26, 31, 31, 1, 31, 31, 4, 5, 6, 7,
- 8, 9, 10, 11, 31, 31, 14, 15, 16, 17,
- 31, 32, 33, 31, 32, 33, 13, 26, 26, 31,
- 32, 33, 33, 31, 14, 31, 31, 31, 31, 31,
- 31, 66, 31, 31, 34, 31, 29, 108, -1, 59,
- -1, -1, -1, -1, -1, 40
+ 5, 6, 30, 8, 57, 58, 11, 84, 85, 4,
+ 5, 6, 7, 8, 9, 10, 11, 27, 95, 14,
+ 15, 25, 26, 33, 68, 29, 70, 25, 81, 82,
+ 34, 66, 30, 0, 69, 30, 71, 30, 0, 1,
+ 93, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 25, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 68, 25, 70, 1, 30, 144, 30, 5,
+ 6, 30, 8, 9, 10, 11, 12, 25, 14, 15,
+ 16, 17, 18, 19, 20, 138, 91, 66, 30, 25,
+ 69, 1, 71, 28, 30, 1, 31, 32, 25, 26,
+ 153, 106, 0, 1, 30, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 30, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 30, 25, 25, 26,
+ 0, 1, 30, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 31, 32, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 5, 6, 25, 8, 9, 10, 11,
+ 30, 30, 14, 15, 30, 0, 1, 172, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 30, 30, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 67, 68,
+ 25, 70, 30, 1, 30, 30, 4, 5, 6, 7,
+ 8, 9, 10, 11, 30, 30, 14, 15, 16, 14,
+ 141, 142, 143, 67, 68, 30, 70, 25, 149, 25,
+ 151, 24, 30, 30, 31, 32, 31, 32, 159, 30,
+ 31, 32, 1, 13, 30, 25, 14, 32, 30, 30,
+ 33, 30, 30, 30, 30, 30, 30, 30, 29, 66,
+ 107, -1, -1, -1, -1, 59, -1, -1, 40
};
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
symbol of state STATE-NUM. */
-static const unsigned char yystos[] =
+static const yytype_uint8 yystos[] =
{
- 0, 37, 38, 0, 1, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 14, 15, 16, 18, 19, 20,
- 21, 22, 23, 26, 31, 39, 40, 42, 43, 44,
- 45, 51, 52, 54, 58, 60, 62, 63, 65, 67,
- 68, 69, 76, 31, 26, 27, 75, 75, 31, 75,
- 31, 31, 75, 26, 26, 26, 27, 30, 35, 79,
- 80, 31, 1, 1, 46, 46, 55, 57, 61, 72,
- 66, 72, 31, 77, 31, 31, 31, 31, 31, 79,
- 79, 32, 33, 77, 28, 34, 31, 31, 1, 12,
- 16, 17, 19, 20, 21, 22, 23, 24, 26, 31,
- 41, 47, 48, 70, 71, 73, 18, 19, 20, 21,
- 31, 41, 56, 71, 73, 40, 53, 76, 40, 54,
- 59, 65, 76, 31, 41, 73, 40, 54, 64, 65,
- 76, 31, 29, 79, 79, 80, 80, 31, 31, 25,
- 79, 79, 75, 74, 75, 79, 26, 80, 49, 1,
- 13, 31, 75, 74, 26, 79, 31, 31, 14, 78,
- 31, 78, 78, 78, 80, 26, 31, 31, 78, 31,
- 78, 31, 79, 31, 31, 31, 78, 34, 50, 31,
- 31, 31, 75
+ 0, 36, 37, 0, 1, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 25, 30, 38, 39, 41, 42, 43,
+ 44, 50, 51, 53, 57, 59, 61, 62, 64, 66,
+ 67, 68, 75, 30, 25, 26, 74, 74, 30, 74,
+ 30, 30, 74, 25, 25, 25, 26, 29, 34, 78,
+ 79, 30, 1, 1, 45, 45, 54, 56, 60, 71,
+ 65, 71, 30, 76, 30, 30, 30, 30, 30, 78,
+ 78, 31, 32, 76, 27, 33, 30, 30, 1, 12,
+ 16, 18, 19, 20, 21, 22, 23, 25, 30, 40,
+ 46, 47, 69, 70, 72, 17, 18, 19, 20, 30,
+ 40, 55, 70, 72, 39, 52, 75, 39, 53, 58,
+ 64, 75, 30, 40, 72, 39, 53, 63, 64, 75,
+ 30, 28, 78, 78, 79, 79, 30, 30, 24, 74,
+ 73, 74, 78, 25, 79, 48, 1, 13, 30, 74,
+ 73, 25, 78, 14, 77, 30, 77, 77, 77, 79,
+ 25, 30, 30, 77, 30, 77, 30, 78, 30, 30,
+ 30, 77, 33, 49, 30, 30, 30, 74
};
#define yyerrok (yyerrstatus = 0)
@@ -761,7 +822,7 @@ do \
yychar = (Token); \
yylval = (Value); \
yytoken = YYTRANSLATE (yychar); \
- YYPOPSTACK; \
+ YYPOPSTACK (1); \
goto yybackup; \
} \
else \
@@ -769,7 +830,7 @@ do \
yyerror (YY_("syntax error: cannot back up")); \
YYERROR; \
} \
-while (0)
+while (YYID (0))
#define YYTERROR 1
@@ -784,7 +845,7 @@ while (0)
#ifndef YYLLOC_DEFAULT
# define YYLLOC_DEFAULT(Current, Rhs, N) \
do \
- if (N) \
+ if (YYID (N)) \
{ \
(Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
(Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
@@ -798,7 +859,7 @@ while (0)
(Current).first_column = (Current).last_column = \
YYRHSLOC (Rhs, 0).last_column; \
} \
- while (0)
+ while (YYID (0))
#endif
@@ -810,8 +871,8 @@ while (0)
# if YYLTYPE_IS_TRIVIAL
# define YY_LOCATION_PRINT(File, Loc) \
fprintf (File, "%d.%d-%d.%d", \
- (Loc).first_line, (Loc).first_column, \
- (Loc).last_line, (Loc).last_column)
+ (Loc).first_line, (Loc).first_column, \
+ (Loc).last_line, (Loc).last_column)
# else
# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
# endif
@@ -838,36 +899,96 @@ while (0)
do { \
if (yydebug) \
YYFPRINTF Args; \
-} while (0)
+} while (YYID (0))
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
-do { \
- if (yydebug) \
- { \
- YYFPRINTF (stderr, "%s ", Title); \
- yysymprint (stderr, \
- Type, Value); \
- YYFPRINTF (stderr, "\n"); \
- } \
-} while (0)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+#endif
+{
+ if (!yyvaluep)
+ return;
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+ YYUSE (yyoutput);
+# endif
+ switch (yytype)
+ {
+ default:
+ break;
+ }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+#endif
+{
+ if (yytype < YYNTOKENS)
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+ else
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep);
+ YYFPRINTF (yyoutput, ")");
+}
/*------------------------------------------------------------------.
| yy_stack_print -- Print the state stack from its BOTTOM up to its |
| TOP (included). |
`------------------------------------------------------------------*/
-#if defined (__STDC__) || defined (__cplusplus)
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
static void
-yy_stack_print (short int *bottom, short int *top)
+yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
#else
static void
yy_stack_print (bottom, top)
- short int *bottom;
- short int *top;
+ yytype_int16 *bottom;
+ yytype_int16 *top;
#endif
{
YYFPRINTF (stderr, "Stack now");
- for (/* Nothing. */; bottom <= top; ++bottom)
+ for (; bottom <= top; ++bottom)
YYFPRINTF (stderr, " %d", *bottom);
YYFPRINTF (stderr, "\n");
}
@@ -876,37 +997,45 @@ yy_stack_print (bottom, top)
do { \
if (yydebug) \
yy_stack_print ((Bottom), (Top)); \
-} while (0)
+} while (YYID (0))
/*------------------------------------------------.
| Report that the YYRULE is going to be reduced. |
`------------------------------------------------*/
-#if defined (__STDC__) || defined (__cplusplus)
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
static void
-yy_reduce_print (int yyrule)
+yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
#else
static void
-yy_reduce_print (yyrule)
+yy_reduce_print (yyvsp, yyrule)
+ YYSTYPE *yyvsp;
int yyrule;
#endif
{
+ int yynrhs = yyr2[yyrule];
int yyi;
unsigned long int yylno = yyrline[yyrule];
- YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu), ",
- yyrule - 1, yylno);
- /* Print the symbols being reduced, and their result. */
- for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
- YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]);
- YYFPRINTF (stderr, "-> %s\n", yytname[yyr1[yyrule]]);
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ fprintf (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ );
+ fprintf (stderr, "\n");
+ }
}
# define YY_REDUCE_PRINT(Rule) \
do { \
if (yydebug) \
- yy_reduce_print (Rule); \
-} while (0)
+ yy_reduce_print (yyvsp, Rule); \
+} while (YYID (0))
/* Nonzero means print parse trace. It is left uninitialized so that
multiple parsers can coexist. */
@@ -940,42 +1069,44 @@ int yydebug;
#if YYERROR_VERBOSE
# ifndef yystrlen
-# if defined (__GLIBC__) && defined (_STRING_H)
+# if defined __GLIBC__ && defined _STRING_H
# define yystrlen strlen
# else
/* Return the length of YYSTR. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
static YYSIZE_T
-# if defined (__STDC__) || defined (__cplusplus)
yystrlen (const char *yystr)
-# else
+#else
+static YYSIZE_T
yystrlen (yystr)
- const char *yystr;
-# endif
+ const char *yystr;
+#endif
{
- const char *yys = yystr;
-
- while (*yys++ != '\0')
+ YYSIZE_T yylen;
+ for (yylen = 0; yystr[yylen]; yylen++)
continue;
-
- return yys - yystr - 1;
+ return yylen;
}
# endif
# endif
# ifndef yystpcpy
-# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
# define yystpcpy stpcpy
# else
/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
YYDEST. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
static char *
-# if defined (__STDC__) || defined (__cplusplus)
yystpcpy (char *yydest, const char *yysrc)
-# else
+#else
+static char *
yystpcpy (yydest, yysrc)
- char *yydest;
- const char *yysrc;
-# endif
+ char *yydest;
+ const char *yysrc;
+#endif
{
char *yyd = yydest;
const char *yys = yysrc;
@@ -1001,7 +1132,7 @@ yytnamerr (char *yyres, const char *yystr)
{
if (*yystr == '"')
{
- size_t yyn = 0;
+ YYSIZE_T yyn = 0;
char const *yyp = yystr;
for (;;)
@@ -1036,53 +1167,123 @@ yytnamerr (char *yyres, const char *yystr)
}
# endif
-#endif /* YYERROR_VERBOSE */
-
-
-
-#if YYDEBUG
-/*--------------------------------.
-| Print this symbol on YYOUTPUT. |
-`--------------------------------*/
-
-#if defined (__STDC__) || defined (__cplusplus)
-static void
-yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yysymprint (yyoutput, yytype, yyvaluep)
- FILE *yyoutput;
- int yytype;
- YYSTYPE *yyvaluep;
-#endif
+/* Copy into YYRESULT an error message about the unexpected token
+ YYCHAR while in state YYSTATE. Return the number of bytes copied,
+ including the terminating null byte. If YYRESULT is null, do not
+ copy anything; just return the number of bytes that would be
+ copied. As a special case, return 0 if an ordinary "syntax error"
+ message will do. Return YYSIZE_MAXIMUM if overflow occurs during
+ size calculation. */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
{
- /* Pacify ``unused variable'' warnings. */
- (void) yyvaluep;
+ int yyn = yypact[yystate];
- if (yytype < YYNTOKENS)
- YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+ if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+ return 0;
else
- YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+ {
+ int yytype = YYTRANSLATE (yychar);
+ YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+ YYSIZE_T yysize = yysize0;
+ YYSIZE_T yysize1;
+ int yysize_overflow = 0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ int yyx;
+
+# if 0
+ /* This is so xgettext sees the translatable formats that are
+ constructed on the fly. */
+ YY_("syntax error, unexpected %s");
+ YY_("syntax error, unexpected %s, expecting %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+ char *yyfmt;
+ char const *yyf;
+ static char const yyunexpected[] = "syntax error, unexpected %s";
+ static char const yyexpecting[] = ", expecting %s";
+ static char const yyor[] = " or %s";
+ char yyformat[sizeof yyunexpected
+ + sizeof yyexpecting - 1
+ + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+ * (sizeof yyor - 1))];
+ char const *yyprefix = yyexpecting;
+
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yycount = 1;
+
+ yyarg[0] = yytname[yytype];
+ yyfmt = yystpcpy (yyformat, yyunexpected);
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ yyformat[sizeof yyunexpected - 1] = '\0';
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+ yyfmt = yystpcpy (yyfmt, yyprefix);
+ yyprefix = yyor;
+ }
+ yyf = YY_(yyformat);
+ yysize1 = yysize + yystrlen (yyf);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
-# ifdef YYPRINT
- if (yytype < YYNTOKENS)
- YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# endif
- switch (yytype)
- {
- default:
- break;
+ if (yysize_overflow)
+ return YYSIZE_MAXIMUM;
+
+ if (yyresult)
+ {
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ char *yyp = yyresult;
+ int yyi = 0;
+ while ((*yyp = *yyf) != '\0')
+ {
+ if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyf += 2;
+ }
+ else
+ {
+ yyp++;
+ yyf++;
+ }
+ }
+ }
+ return yysize;
}
- YYFPRINTF (yyoutput, ")");
}
+#endif /* YYERROR_VERBOSE */
+
-#endif /* ! YYDEBUG */
/*-----------------------------------------------.
| Release the memory associated to this symbol. |
`-----------------------------------------------*/
-#if defined (__STDC__) || defined (__cplusplus)
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
static void
yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
#else
@@ -1093,8 +1294,7 @@ yydestruct (yymsg, yytype, yyvaluep)
YYSTYPE *yyvaluep;
#endif
{
- /* Pacify ``unused variable'' warnings. */
- (void) yyvaluep;
+ YYUSE (yyvaluep);
if (!yymsg)
yymsg = "Deleting";
@@ -1102,39 +1302,39 @@ yydestruct (yymsg, yytype, yyvaluep)
switch (yytype)
{
- case 52: /* "choice_entry" */
+ case 51: /* "choice_entry" */
- {
+ {
fprintf(stderr, "%s:%d: missing end statement for this entry\n",
(yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno);
if (current_menu == (yyvaluep->menu))
menu_end_menu();
};
- break;
- case 58: /* "if_entry" */
+ break;
+ case 57: /* "if_entry" */
- {
+ {
fprintf(stderr, "%s:%d: missing end statement for this entry\n",
(yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno);
if (current_menu == (yyvaluep->menu))
menu_end_menu();
};
- break;
- case 63: /* "menu_entry" */
+ break;
+ case 62: /* "menu_entry" */
- {
+ {
fprintf(stderr, "%s:%d: missing end statement for this entry\n",
(yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno);
if (current_menu == (yyvaluep->menu))
menu_end_menu();
};
- break;
+ break;
default:
- break;
+ break;
}
}
@@ -1142,13 +1342,13 @@ yydestruct (yymsg, yytype, yyvaluep)
/* Prevent warnings from -Wmissing-prototypes. */
#ifdef YYPARSE_PARAM
-# if defined (__STDC__) || defined (__cplusplus)
+#if defined __STDC__ || defined __cplusplus
int yyparse (void *YYPARSE_PARAM);
-# else
+#else
int yyparse ();
-# endif
+#endif
#else /* ! YYPARSE_PARAM */
-#if defined (__STDC__) || defined (__cplusplus)
+#if defined __STDC__ || defined __cplusplus
int yyparse (void);
#else
int yyparse ();
@@ -1173,20 +1373,24 @@ int yynerrs;
`----------*/
#ifdef YYPARSE_PARAM
-# if defined (__STDC__) || defined (__cplusplus)
-int yyparse (void *YYPARSE_PARAM)
-# else
-int yyparse (YYPARSE_PARAM)
- void *YYPARSE_PARAM;
-# endif
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+#endif
#else /* ! YYPARSE_PARAM */
-#if defined (__STDC__) || defined (__cplusplus)
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
int
yyparse (void)
#else
int
yyparse ()
- ;
+
#endif
#endif
{
@@ -1198,6 +1402,12 @@ yyparse ()
int yyerrstatus;
/* Look-ahead token as an internal (translated) token number. */
int yytoken = 0;
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
/* Three stacks and their tools:
`yyss': related to states,
@@ -1208,9 +1418,9 @@ yyparse ()
to reallocate them elsewhere. */
/* The state stack. */
- short int yyssa[YYINITDEPTH];
- short int *yyss = yyssa;
- short int *yyssp;
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss = yyssa;
+ yytype_int16 *yyssp;
/* The semantic value stack. */
YYSTYPE yyvsa[YYINITDEPTH];
@@ -1219,7 +1429,7 @@ yyparse ()
-#define YYPOPSTACK (yyvsp--, yyssp--)
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
YYSIZE_T yystacksize = YYINITDEPTH;
@@ -1228,9 +1438,9 @@ yyparse ()
YYSTYPE yyval;
- /* When reducing, the number of symbols on the RHS of the reduced
- rule. */
- int yylen;
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
YYDPRINTF ((stderr, "Starting parse\n"));
@@ -1254,8 +1464,7 @@ yyparse ()
`------------------------------------------------------------*/
yynewstate:
/* In all cases, when you get here, the value and location stacks
- have just been pushed. so pushing a state here evens the stacks.
- */
+ have just been pushed. So pushing a state here evens the stacks. */
yyssp++;
yysetstate:
@@ -1268,11 +1477,11 @@ yyparse ()
#ifdef yyoverflow
{
- /* Give user a chance to reallocate the stack. Use copies of
+ /* Give user a chance to reallocate the stack. Use copies of
these so that the &'s don't force the real ones into
memory. */
YYSTYPE *yyvs1 = yyvs;
- short int *yyss1 = yyss;
+ yytype_int16 *yyss1 = yyss;
/* Each stack pointer address is followed by the size of the
@@ -1300,7 +1509,7 @@ yyparse ()
yystacksize = YYMAXDEPTH;
{
- short int *yyss1 = yyss;
+ yytype_int16 *yyss1 = yyss;
union yyalloc *yyptr =
(union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
if (! yyptr)
@@ -1335,12 +1544,10 @@ yyparse ()
`-----------*/
yybackup:
-/* Do appropriate processing given the current state. */
-/* Read a look-ahead token if we need one and don't already have one. */
-/* yyresume: */
+ /* Do appropriate processing given the current state. Read a
+ look-ahead token if we need one and don't already have one. */
/* First try to decide what to do without reference to look-ahead token. */
-
yyn = yypact[yystate];
if (yyn == YYPACT_NINF)
goto yydefault;
@@ -1382,22 +1589,21 @@ yybackup:
if (yyn == YYFINAL)
YYACCEPT;
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
/* Shift the look-ahead token. */
YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
- /* Discard the token being shifted unless it is eof. */
+ /* Discard the shifted token unless it is eof. */
if (yychar != YYEOF)
yychar = YYEMPTY;
+ yystate = yyn;
*++yyvsp = yylval;
-
- /* Count tokens shifted since error; after three, turn off error
- status. */
- if (yyerrstatus)
- yyerrstatus--;
-
- yystate = yyn;
goto yynewstate;
@@ -1439,13 +1645,13 @@ yyreduce:
case 9:
- { zconf_error("unknown statement \"%s\"", (yyvsp[-2].string)); ;}
+ { zconf_error("unknown statement \"%s\"", (yyvsp[(2) - (4)].string)); ;}
break;
case 10:
{
- zconf_error("unexpected option \"%s\"", kconf_id_strings + (yyvsp[-2].id)->name);
+ zconf_error("unexpected option \"%s\"", kconf_id_strings + (yyvsp[(2) - (4)].id)->name);
;}
break;
@@ -1456,7 +1662,7 @@ yyreduce:
case 25:
- { zconf_error("unknown option \"%s\"", (yyvsp[-2].string)); ;}
+ { zconf_error("unknown option \"%s\"", (yyvsp[(1) - (3)].string)); ;}
break;
case 26:
@@ -1467,10 +1673,10 @@ yyreduce:
case 27:
{
- struct symbol *sym = sym_lookup((yyvsp[-1].string), 0);
+ struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0);
sym->flags |= SYMBOL_OPTIONAL;
menu_add_entry(sym);
- printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string));
+ printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string));
;}
break;
@@ -1485,10 +1691,10 @@ yyreduce:
case 29:
{
- struct symbol *sym = sym_lookup((yyvsp[-1].string), 0);
+ struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0);
sym->flags |= SYMBOL_OPTIONAL;
menu_add_entry(sym);
- printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string));
+ printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string));
;}
break;
@@ -1507,17 +1713,17 @@ yyreduce:
case 38:
{
- menu_set_type((yyvsp[-2].id)->stype);
+ menu_set_type((yyvsp[(1) - (3)].id)->stype);
printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
zconf_curname(), zconf_lineno(),
- (yyvsp[-2].id)->stype);
+ (yyvsp[(1) - (3)].id)->stype);
;}
break;
case 39:
{
- menu_add_prompt(P_PROMPT, (yyvsp[-2].string), (yyvsp[-1].expr));
+ menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr));
printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
;}
break;
@@ -1525,19 +1731,19 @@ yyreduce:
case 40:
{
- menu_add_expr(P_DEFAULT, (yyvsp[-2].expr), (yyvsp[-1].expr));
- if ((yyvsp[-3].id)->stype != S_UNKNOWN)
- menu_set_type((yyvsp[-3].id)->stype);
+ menu_add_expr(P_DEFAULT, (yyvsp[(2) - (4)].expr), (yyvsp[(3) - (4)].expr));
+ if ((yyvsp[(1) - (4)].id)->stype != S_UNKNOWN)
+ menu_set_type((yyvsp[(1) - (4)].id)->stype);
printd(DEBUG_PARSE, "%s:%d:default(%u)\n",
zconf_curname(), zconf_lineno(),
- (yyvsp[-3].id)->stype);
+ (yyvsp[(1) - (4)].id)->stype);
;}
break;
case 41:
{
- menu_add_symbol(P_SELECT, sym_lookup((yyvsp[-2].string), 0), (yyvsp[-1].expr));
+ menu_add_symbol(P_SELECT, sym_lookup((yyvsp[(2) - (4)].string), 0), (yyvsp[(3) - (4)].expr));
printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
;}
break;
@@ -1545,7 +1751,7 @@ yyreduce:
case 42:
{
- menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[-3].symbol), (yyvsp[-2].symbol)), (yyvsp[-1].expr));
+ menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[(2) - (5)].symbol), (yyvsp[(3) - (5)].symbol)), (yyvsp[(4) - (5)].expr));
printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno());
;}
break;
@@ -1553,12 +1759,12 @@ yyreduce:
case 45:
{
- struct kconf_id *id = kconf_id_lookup((yyvsp[-1].string), strlen((yyvsp[-1].string)));
+ struct kconf_id *id = kconf_id_lookup((yyvsp[(2) - (3)].string), strlen((yyvsp[(2) - (3)].string)));
if (id && id->flags & TF_OPTION)
- menu_add_option(id->token, (yyvsp[0].string));
+ menu_add_option(id->token, (yyvsp[(3) - (3)].string));
else
- zconfprint("warning: ignoring unknown option %s", (yyvsp[-1].string));
- free((yyvsp[-1].string));
+ zconfprint("warning: ignoring unknown option %s", (yyvsp[(2) - (3)].string));
+ free((yyvsp[(2) - (3)].string));
;}
break;
@@ -1569,7 +1775,7 @@ yyreduce:
case 47:
- { (yyval.string) = (yyvsp[0].string); ;}
+ { (yyval.string) = (yyvsp[(2) - (2)].string); ;}
break;
case 48:
@@ -1593,7 +1799,7 @@ yyreduce:
case 50:
{
- if (zconf_endtoken((yyvsp[0].id), T_CHOICE, T_ENDCHOICE)) {
+ if (zconf_endtoken((yyvsp[(1) - (1)].id), T_CHOICE, T_ENDCHOICE)) {
menu_end_menu();
printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno());
}
@@ -1603,7 +1809,7 @@ yyreduce:
case 58:
{
- menu_add_prompt(P_PROMPT, (yyvsp[-2].string), (yyvsp[-1].expr));
+ menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr));
printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
;}
break;
@@ -1611,11 +1817,11 @@ yyreduce:
case 59:
{
- if ((yyvsp[-2].id)->stype == S_BOOLEAN || (yyvsp[-2].id)->stype == S_TRISTATE) {
- menu_set_type((yyvsp[-2].id)->stype);
+ if ((yyvsp[(1) - (3)].id)->stype == S_BOOLEAN || (yyvsp[(1) - (3)].id)->stype == S_TRISTATE) {
+ menu_set_type((yyvsp[(1) - (3)].id)->stype);
printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
zconf_curname(), zconf_lineno(),
- (yyvsp[-2].id)->stype);
+ (yyvsp[(1) - (3)].id)->stype);
} else
YYERROR;
;}
@@ -1632,8 +1838,8 @@ yyreduce:
case 61:
{
- if ((yyvsp[-3].id)->stype == S_UNKNOWN) {
- menu_add_symbol(P_DEFAULT, sym_lookup((yyvsp[-2].string), 0), (yyvsp[-1].expr));
+ if ((yyvsp[(1) - (4)].id)->stype == S_UNKNOWN) {
+ menu_add_symbol(P_DEFAULT, sym_lookup((yyvsp[(2) - (4)].string), 0), (yyvsp[(3) - (4)].expr));
printd(DEBUG_PARSE, "%s:%d:default\n",
zconf_curname(), zconf_lineno());
} else
@@ -1646,7 +1852,7 @@ yyreduce:
{
printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
menu_add_entry(NULL);
- menu_add_dep((yyvsp[-1].expr));
+ menu_add_dep((yyvsp[(2) - (3)].expr));
(yyval.menu) = menu_add_menu();
;}
break;
@@ -1654,7 +1860,7 @@ yyreduce:
case 65:
{
- if (zconf_endtoken((yyvsp[0].id), T_IF, T_ENDIF)) {
+ if (zconf_endtoken((yyvsp[(1) - (1)].id), T_IF, T_ENDIF)) {
menu_end_menu();
printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno());
}
@@ -1665,7 +1871,7 @@ yyreduce:
{
menu_add_entry(NULL);
- menu_add_prompt(P_MENU, (yyvsp[-1].string), NULL);
+ menu_add_prompt(P_MENU, (yyvsp[(2) - (3)].string), NULL);
printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
;}
break;
@@ -1680,7 +1886,7 @@ yyreduce:
case 73:
{
- if (zconf_endtoken((yyvsp[0].id), T_MENU, T_ENDMENU)) {
+ if (zconf_endtoken((yyvsp[(1) - (1)].id), T_MENU, T_ENDMENU)) {
menu_end_menu();
printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno());
}
@@ -1690,8 +1896,8 @@ yyreduce:
case 79:
{
- printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string));
- zconf_nextfile((yyvsp[-1].string));
+ printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string));
+ zconf_nextfile((yyvsp[(2) - (3)].string));
;}
break;
@@ -1699,7 +1905,7 @@ yyreduce:
{
menu_add_entry(NULL);
- menu_add_prompt(P_COMMENT, (yyvsp[-1].string), NULL);
+ menu_add_prompt(P_COMMENT, (yyvsp[(2) - (3)].string), NULL);
printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
;}
break;
@@ -1722,122 +1928,104 @@ yyreduce:
case 83:
{
- current_entry->help = (yyvsp[0].string);
+ current_entry->help = (yyvsp[(2) - (2)].string);
;}
break;
case 88:
{
- menu_add_dep((yyvsp[-1].expr));
+ menu_add_dep((yyvsp[(3) - (4)].expr));
printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
;}
break;
- case 89:
+ case 90:
{
- menu_add_dep((yyvsp[-1].expr));
- printd(DEBUG_PARSE, "%s:%d:depends\n", zconf_curname(), zconf_lineno());
+ menu_add_prompt(P_PROMPT, (yyvsp[(1) - (2)].string), (yyvsp[(2) - (2)].expr));
;}
break;
- case 90:
+ case 93:
- {
- menu_add_dep((yyvsp[-1].expr));
- printd(DEBUG_PARSE, "%s:%d:requires\n", zconf_curname(), zconf_lineno());
-;}
+ { (yyval.id) = (yyvsp[(1) - (2)].id); ;}
break;
- case 92:
+ case 94:
- {
- menu_add_prompt(P_PROMPT, (yyvsp[-1].string), (yyvsp[0].expr));
-;}
+ { (yyval.id) = (yyvsp[(1) - (2)].id); ;}
break;
case 95:
- { (yyval.id) = (yyvsp[-1].id); ;}
+ { (yyval.id) = (yyvsp[(1) - (2)].id); ;}
break;
- case 96:
+ case 98:
- { (yyval.id) = (yyvsp[-1].id); ;}
+ { (yyval.expr) = NULL; ;}
break;
- case 97:
+ case 99:
- { (yyval.id) = (yyvsp[-1].id); ;}
+ { (yyval.expr) = (yyvsp[(2) - (2)].expr); ;}
break;
case 100:
- { (yyval.expr) = NULL; ;}
+ { (yyval.expr) = expr_alloc_symbol((yyvsp[(1) - (1)].symbol)); ;}
break;
case 101:
- { (yyval.expr) = (yyvsp[0].expr); ;}
+ { (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); ;}
break;
case 102:
- { (yyval.expr) = expr_alloc_symbol((yyvsp[0].symbol)); ;}
+ { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); ;}
break;
case 103:
- { (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[-2].symbol), (yyvsp[0].symbol)); ;}
+ { (yyval.expr) = (yyvsp[(2) - (3)].expr); ;}
break;
case 104:
- { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[-2].symbol), (yyvsp[0].symbol)); ;}
+ { (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[(2) - (2)].expr)); ;}
break;
case 105:
- { (yyval.expr) = (yyvsp[-1].expr); ;}
+ { (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
break;
case 106:
- { (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[0].expr)); ;}
+ { (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
break;
case 107:
- { (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
+ { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), 0); free((yyvsp[(1) - (1)].string)); ;}
break;
case 108:
- { (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
- break;
-
- case 109:
-
- { (yyval.symbol) = sym_lookup((yyvsp[0].string), 0); free((yyvsp[0].string)); ;}
+ { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), 1); free((yyvsp[(1) - (1)].string)); ;}
break;
- case 110:
-
- { (yyval.symbol) = sym_lookup((yyvsp[0].string), 1); free((yyvsp[0].string)); ;}
- break;
+/* Line 1267 of yacc.c. */
default: break;
}
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
-/* Line 1126 of yacc.c. */
-
-
- yyvsp -= yylen;
- yyssp -= yylen;
-
-
+ YYPOPSTACK (yylen);
+ yylen = 0;
YY_STACK_PRINT (yyss, yyssp);
*++yyvsp = yyval;
@@ -1866,110 +2054,41 @@ yyerrlab:
if (!yyerrstatus)
{
++yynerrs;
-#if YYERROR_VERBOSE
- yyn = yypact[yystate];
-
- if (YYPACT_NINF < yyn && yyn < YYLAST)
- {
- int yytype = YYTRANSLATE (yychar);
- YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
- YYSIZE_T yysize = yysize0;
- YYSIZE_T yysize1;
- int yysize_overflow = 0;
- char *yymsg = 0;
-# define YYERROR_VERBOSE_ARGS_MAXIMUM 5
- char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
- int yyx;
-
-#if 0
- /* This is so xgettext sees the translatable formats that are
- constructed on the fly. */
- YY_("syntax error, unexpected %s");
- YY_("syntax error, unexpected %s, expecting %s");
- YY_("syntax error, unexpected %s, expecting %s or %s");
- YY_("syntax error, unexpected %s, expecting %s or %s or %s");
- YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
-#endif
- char *yyfmt;
- char const *yyf;
- static char const yyunexpected[] = "syntax error, unexpected %s";
- static char const yyexpecting[] = ", expecting %s";
- static char const yyor[] = " or %s";
- char yyformat[sizeof yyunexpected
- + sizeof yyexpecting - 1
- + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
- * (sizeof yyor - 1))];
- char const *yyprefix = yyexpecting;
-
- /* Start YYX at -YYN if negative to avoid negative indexes in
- YYCHECK. */
- int yyxbegin = yyn < 0 ? -yyn : 0;
-
- /* Stay within bounds of both yycheck and yytname. */
- int yychecklim = YYLAST - yyn;
- int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
- int yycount = 1;
-
- yyarg[0] = yytname[yytype];
- yyfmt = yystpcpy (yyformat, yyunexpected);
-
- for (yyx = yyxbegin; yyx < yyxend; ++yyx)
- if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+#if ! YYERROR_VERBOSE
+ yyerror (YY_("syntax error"));
+#else
+ {
+ YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+ if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+ {
+ YYSIZE_T yyalloc = 2 * yysize;
+ if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+ yyalloc = YYSTACK_ALLOC_MAXIMUM;
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+ if (yymsg)
+ yymsg_alloc = yyalloc;
+ else
{
- if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
- {
- yycount = 1;
- yysize = yysize0;
- yyformat[sizeof yyunexpected - 1] = '\0';
- break;
- }
- yyarg[yycount++] = yytname[yyx];
- yysize1 = yysize + yytnamerr (0, yytname[yyx]);
- yysize_overflow |= yysize1 < yysize;
- yysize = yysize1;
- yyfmt = yystpcpy (yyfmt, yyprefix);
- yyprefix = yyor;
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
}
+ }
- yyf = YY_(yyformat);
- yysize1 = yysize + yystrlen (yyf);
- yysize_overflow |= yysize1 < yysize;
- yysize = yysize1;
-
- if (!yysize_overflow && yysize <= YYSTACK_ALLOC_MAXIMUM)
- yymsg = (char *) YYSTACK_ALLOC (yysize);
- if (yymsg)
- {
- /* Avoid sprintf, as that infringes on the user's name space.
- Don't have undefined behavior even if the translation
- produced a string with the wrong number of "%s"s. */
- char *yyp = yymsg;
- int yyi = 0;
- while ((*yyp = *yyf))
- {
- if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
- {
- yyp += yytnamerr (yyp, yyarg[yyi++]);
- yyf += 2;
- }
- else
- {
- yyp++;
- yyf++;
- }
- }
- yyerror (yymsg);
- YYSTACK_FREE (yymsg);
- }
- else
- {
- yyerror (YY_("syntax error"));
+ if (0 < yysize && yysize <= yymsg_alloc)
+ {
+ (void) yysyntax_error (yymsg, yystate, yychar);
+ yyerror (yymsg);
+ }
+ else
+ {
+ yyerror (YY_("syntax error"));
+ if (yysize != 0)
goto yyexhaustedlab;
- }
- }
- else
-#endif /* YYERROR_VERBOSE */
- yyerror (YY_("syntax error"));
+ }
+ }
+#endif
}
@@ -1980,14 +2099,15 @@ yyerrlab:
error, discard it. */
if (yychar <= YYEOF)
- {
+ {
/* Return failure if at end of input. */
if (yychar == YYEOF)
YYABORT;
- }
+ }
else
{
- yydestruct ("Error: discarding", yytoken, &yylval);
+ yydestruct ("Error: discarding",
+ yytoken, &yylval);
yychar = YYEMPTY;
}
}
@@ -2005,11 +2125,14 @@ yyerrorlab:
/* Pacify compilers like GCC when the user code never invokes
YYERROR and the label yyerrorlab therefore never appears in user
code. */
- if (0)
+ if (/*CONSTCOND*/ 0)
goto yyerrorlab;
-yyvsp -= yylen;
- yyssp -= yylen;
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
yystate = *yyssp;
goto yyerrlab1;
@@ -2039,8 +2162,9 @@ yyerrlab1:
YYABORT;
- yydestruct ("Error: popping", yystos[yystate], yyvsp);
- YYPOPSTACK;
+ yydestruct ("Error: popping",
+ yystos[yystate], yyvsp);
+ YYPOPSTACK (1);
yystate = *yyssp;
YY_STACK_PRINT (yyss, yyssp);
}
@@ -2051,7 +2175,7 @@ yyerrlab1:
*++yyvsp = yylval;
- /* Shift the error token. */
+ /* Shift the error token. */
YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
yystate = yyn;
@@ -2086,17 +2210,26 @@ yyreturn:
if (yychar != YYEOF && yychar != YYEMPTY)
yydestruct ("Cleanup: discarding lookahead",
yytoken, &yylval);
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
while (yyssp != yyss)
{
yydestruct ("Cleanup: popping",
yystos[*yyssp], yyvsp);
- YYPOPSTACK;
+ YYPOPSTACK (1);
}
#ifndef yyoverflow
if (yyss != yyssa)
YYSTACK_FREE (yyss);
#endif
- return yyresult;
+#if YYERROR_VERBOSE
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+#endif
+ /* Make sure YYID is used. */
+ return YYID (yyresult);
}
@@ -2344,4 +2477,3 @@ void zconfdump(FILE *out)
#include "symbol.c"
#include "menu.c"
-
diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y
index 79db4cf22a51..d9b96ba8e38c 100644
--- a/scripts/kconfig/zconf.y
+++ b/scripts/kconfig/zconf.y
@@ -64,7 +64,6 @@ static struct menu *current_menu, *current_entry;
%token <id>T_IF
%token <id>T_ENDIF
%token <id>T_DEPENDS
-%token <id>T_REQUIRES
%token <id>T_OPTIONAL
%token <id>T_PROMPT
%token <id>T_TYPE
@@ -418,16 +417,6 @@ depends: T_DEPENDS T_ON expr T_EOL
{
menu_add_dep($3);
printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
-}
- | T_DEPENDS expr T_EOL
-{
- menu_add_dep($2);
- printd(DEBUG_PARSE, "%s:%d:depends\n", zconf_curname(), zconf_lineno());
-}
- | T_REQUIRES expr T_EOL
-{
- menu_add_dep($2);
- printd(DEBUG_PARSE, "%s:%d:requires\n", zconf_curname(), zconf_lineno());
};
/* prompt statement */
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index 1f5835115cad..1d1401807e95 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -5,6 +5,7 @@ use strict;
## Copyright (c) 1998 Michael Zucchi, All Rights Reserved ##
## Copyright (C) 2000, 1 Tim Waugh <twaugh@redhat.com> ##
## Copyright (C) 2001 Simon Huggins ##
+## Copyright (C) 2005-2007 Randy Dunlap ##
## ##
## #define enhancements by Armin Kuster <akuster@mvista.com> ##
## Copyright (c) 2000 MontaVista Software, Inc. ##
@@ -161,7 +162,7 @@ my $type_constant = '\%([-_\w]+)';
my $type_func = '(\w+)\(\)';
my $type_param = '\@(\w+)';
my $type_struct = '\&((struct\s*)*[_\w]+)';
-my $type_struct_xml = '\\\amp;((struct\s*)*[_\w]+)';
+my $type_struct_xml = '\\&amp;((struct\s*)*[_\w]+)';
my $type_env = '(\$\w+)';
# Output conversion substitutions.
@@ -173,7 +174,9 @@ my %highlights_html = ( $type_constant, "<i>\$1</i>",
$type_struct_xml, "<i>\$1</i>",
$type_env, "<b><i>\$1</i></b>",
$type_param, "<tt><b>\$1</b></tt>" );
-my $blankline_html = "<p>";
+my $local_lt = "\\\\\\\\lt:";
+my $local_gt = "\\\\\\\\gt:";
+my $blankline_html = $local_lt . "p" . $local_gt; # was "<p>"
# XML, docbook format
my %highlights_xml = ( "([^=])\\\"([^\\\"<]+)\\\"", "\$1<quote>\$2</quote>",
@@ -391,17 +394,19 @@ sub output_highlight {
# confess "output_highlight got called with no args?\n";
# }
+ if ($output_mode eq "html") {
+ $contents = local_unescape($contents);
+ # convert data read & converted thru xml_escape() into &xyz; format:
+ $contents =~ s/\\\\\\/&/g;
+ }
# print STDERR "contents b4:$contents\n";
eval $dohighlight;
die $@ if $@;
- if ($output_mode eq "html") {
- $contents =~ s/\\\\//;
- }
# print STDERR "contents af:$contents\n";
foreach $line (split "\n", $contents) {
if ($line eq ""){
- print $lineprefix, $blankline;
+ print $lineprefix, local_unescape($blankline);
} else {
$line =~ s/\\\\\\/\&/g;
if ($output_mode eq "man" && substr($line, 0, 1) eq ".") {
@@ -1752,7 +1757,13 @@ sub process_state3_type($$) {
}
}
-# replace <, >, and &
+# xml_escape: replace <, >, and & in the text stream;
+#
+# however, formatting controls that are generated internally/locally in the
+# kernel-doc script are not escaped here; instead, they begin life like
+# $blankline_html (4 of '\' followed by a mnemonic + ':'), then these strings
+# are converted to their mnemonic-expected output, without the 4 * '\' & ':',
+# just before actual output; (this is done by local_unescape())
sub xml_escape($) {
my $text = shift;
if (($output_mode eq "text") || ($output_mode eq "man")) {
@@ -1764,6 +1775,18 @@ sub xml_escape($) {
return $text;
}
+# convert local escape strings to html
+# local escape strings look like: '\\\\menmonic:' (that's 4 backslashes)
+sub local_unescape($) {
+ my $text = shift;
+ if (($output_mode eq "text") || ($output_mode eq "man")) {
+ return $text;
+ }
+ $text =~ s/\\\\\\\\lt:/</g;
+ $text =~ s/\\\\\\\\gt:/>/g;
+ return $text;
+}
+
sub process_file($) {
my $file;
my $identifier;
@@ -1903,7 +1926,7 @@ sub process_file($) {
} elsif ($state == 4) {
# Documentation block
if (/$doc_block/) {
- dump_section($section, $contents);
+ dump_section($section, xml_escape($contents));
output_intro({'sectionlist' => \@sectionlist,
'sections' => \%sections });
$contents = "";
@@ -1923,7 +1946,7 @@ sub process_file($) {
}
elsif (/$doc_end/)
{
- dump_section($section, $contents);
+ dump_section($section, xml_escape($contents));
output_intro({'sectionlist' => \@sectionlist,
'sections' => \%sections });
$contents = "";
diff --git a/scripts/makelst b/scripts/makelst
index 4fc80f2b7e19..e6581496d820 100755
--- a/scripts/makelst
+++ b/scripts/makelst
@@ -3,8 +3,8 @@
# with correct relocations from System.map
# Requires the following lines in makefile:
#%.lst: %.c
-# $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -g -c -o $*.o $<
-# $(srctree)/scripts/makelst $*.o $(objtree)/System.map $(OBJDUMP)
+# $(CC) $(c_flags) -g -c -o $*.o $< &&
+# $(srctree)/scripts/makelst $*.o System.map $(OBJDUMP) > $@
#
# Copyright (C) 2000 IBM Corporation
# Author(s): DJ Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
diff --git a/scripts/mkmakefile b/scripts/mkmakefile
index 7f9d544f9b6c..ee39facee152 100644
--- a/scripts/mkmakefile
+++ b/scripts/mkmakefile
@@ -26,11 +26,13 @@ MAKEFLAGS += --no-print-directory
.PHONY: all \$(MAKECMDGOALS)
+all := \$(filter-out all Makefile,\$(MAKECMDGOALS))
+
all:
- \$(MAKE) -C \$(KERNELSRC) O=\$(KERNELOUTPUT)
+ \$(MAKE) -C \$(KERNELSRC) O=\$(KERNELOUTPUT) \$(all)
Makefile:;
-\$(filter-out all Makefile,\$(MAKECMDGOALS)) %/:
- \$(MAKE) -C \$(KERNELSRC) O=\$(KERNELOUTPUT) \$@
+\$(all) %/: all
+ @:
EOF
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 494435ca88fa..d802b5afae89 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -55,10 +55,14 @@ do { \
* Check that sizeof(device_id type) are consistent with size of section
* in .o file. If in-consistent then userspace and kernel does not agree
* on actual size which is a bug.
+ * Also verify that the final entry in the table is all zeros.
**/
-static void device_id_size_check(const char *modname, const char *device_id,
- unsigned long size, unsigned long id_size)
+static void device_id_check(const char *modname, const char *device_id,
+ unsigned long size, unsigned long id_size,
+ void *symval)
{
+ int i;
+
if (size % id_size || size < id_size) {
fatal("%s: sizeof(struct %s_device_id)=%lu is not a modulo "
"of the size of section __mod_%s_device_table=%lu.\n"
@@ -66,6 +70,20 @@ static void device_id_size_check(const char *modname, const char *device_id,
"in mod_devicetable.h\n",
modname, device_id, id_size, device_id, size, device_id);
}
+ /* Verify last one is a terminator */
+ for (i = 0; i < id_size; i++ ) {
+ if (*(uint8_t*)(symval+size-id_size+i)) {
+ fprintf(stderr,"%s: struct %s_device_id is %lu bytes. "
+ "The last of %lu is:\n",
+ modname, device_id, id_size, size / id_size);
+ for (i = 0; i < id_size; i++ )
+ fprintf(stderr,"0x%02x ",
+ *(uint8_t*)(symval+size-id_size+i) );
+ fprintf(stderr,"\n");
+ fatal("%s: struct %s_device_id is not terminated "
+ "with a NULL entry!\n", modname, device_id);
+ }
+ }
}
/* USB is special because the bcdDevice can be matched against a numeric range */
@@ -168,7 +186,7 @@ static void do_usb_table(void *symval, unsigned long size,
unsigned int i;
const unsigned long id_size = sizeof(struct usb_device_id);
- device_id_size_check(mod->name, "usb", size, id_size);
+ device_id_check(mod->name, "usb", size, id_size, symval);
/* Leave last one: it's the terminator. */
size -= id_size;
@@ -507,6 +525,20 @@ static int do_ssb_entry(const char *filename,
return 1;
}
+/* Looks like: virtio:dNvN */
+static int do_virtio_entry(const char *filename, struct virtio_device_id *id,
+ char *alias)
+{
+ id->device = TO_NATIVE(id->device);
+ id->vendor = TO_NATIVE(id->vendor);
+
+ strcpy(alias, "virtio:");
+ ADD(alias, "d", 1, id->device);
+ ADD(alias, "v", id->vendor != VIRTIO_DEV_ANY_ID, id->vendor);
+
+ return 1;
+}
+
/* Ignore any prefix, eg. v850 prepends _ */
static inline int sym_is(const char *symbol, const char *name)
{
@@ -528,7 +560,7 @@ static void do_table(void *symval, unsigned long size,
char alias[500];
int (*do_entry)(const char *, void *entry, char *alias) = function;
- device_id_size_check(mod->name, device_id, size, id_size);
+ device_id_check(mod->name, device_id, size, id_size, symval);
/* Leave last one: it's the terminator. */
size -= id_size;
@@ -550,14 +582,21 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
Elf_Sym *sym, const char *symname)
{
void *symval;
+ char *zeros = NULL;
/* We're looking for a section relative symbol */
if (!sym->st_shndx || sym->st_shndx >= info->hdr->e_shnum)
return;
- symval = (void *)info->hdr
- + info->sechdrs[sym->st_shndx].sh_offset
- + sym->st_value;
+ /* Handle all-NULL symbols allocated into .bss */
+ if (info->sechdrs[sym->st_shndx].sh_type & SHT_NOBITS) {
+ zeros = calloc(1, sym->st_size);
+ symval = zeros;
+ } else {
+ symval = (void *)info->hdr
+ + info->sechdrs[sym->st_shndx].sh_offset
+ + sym->st_value;
+ }
if (sym_is(symname, "__mod_pci_device_table"))
do_table(symval, sym->st_size,
@@ -626,6 +665,11 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
do_table(symval, sym->st_size,
sizeof(struct ssb_device_id), "ssb",
do_ssb_entry, mod);
+ else if (sym_is(symname, "__mod_virtio_device_table"))
+ do_table(symval, sym->st_size,
+ sizeof(struct virtio_device_id), "virtio",
+ do_virtio_entry, mod);
+ free(zeros);
}
/* Now add out buffered information to the generated C source */
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 0a4051fbd34e..93ac52adb498 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -268,6 +268,9 @@ static struct symbol *sym_add_exported(const char *name, struct module *mod,
"was in %s%s\n", mod->name, name,
s->module->name,
is_vmlinux(s->module->name) ?"":".ko");
+ } else {
+ /* In case Modules.symvers was out of date */
+ s->module = mod;
}
}
s->preloaded = 0;
@@ -381,6 +384,12 @@ static int parse_elf(struct elf_info *info, const char *filename)
sechdrs = (void *)hdr + hdr->e_shoff;
info->sechdrs = sechdrs;
+ /* Check if file offset is correct */
+ if (hdr->e_shoff > info->size) {
+ fatal("section header offset=%u in file '%s' is bigger then filesize=%lu\n", hdr->e_shoff, filename, info->size);
+ return 0;
+ }
+
/* Fix endianness in section headers */
for (i = 0; i < hdr->e_shnum; i++) {
sechdrs[i].sh_type = TO_NATIVE(sechdrs[i].sh_type);
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
index 4156dd34c5de..0ffed17ec20c 100644
--- a/scripts/mod/modpost.h
+++ b/scripts/mod/modpost.h
@@ -17,7 +17,7 @@
#define Elf_Shdr Elf32_Shdr
#define Elf_Sym Elf32_Sym
#define Elf_Addr Elf32_Addr
-#define Elf_Section Elf32_Section
+#define Elf_Section Elf32_Half
#define ELF_ST_BIND ELF32_ST_BIND
#define ELF_ST_TYPE ELF32_ST_TYPE
@@ -31,7 +31,7 @@
#define Elf_Shdr Elf64_Shdr
#define Elf_Sym Elf64_Sym
#define Elf_Addr Elf64_Addr
-#define Elf_Section Elf64_Section
+#define Elf_Section Elf64_Half
#define ELF_ST_BIND ELF64_ST_BIND
#define ELF_ST_TYPE ELF64_ST_TYPE
diff --git a/scripts/package/builddeb b/scripts/package/builddeb
index 6edb29f2b4a6..0f657b5f3bc8 100644
--- a/scripts/package/builddeb
+++ b/scripts/package/builddeb
@@ -83,6 +83,7 @@ Maintainer: $name
Standards-Version: 3.6.1
Package: $packagename
+Provides: kernel-image-$version, linux-image-$version
Architecture: any
Description: User Mode Linux kernel, version $version
User-mode Linux is a port of the Linux kernel to its own system call
@@ -104,6 +105,7 @@ Maintainer: $name
Standards-Version: 3.6.1
Package: $packagename
+Provides: kernel-image-$version, linux-image-$version
Architecture: any
Description: Linux kernel, version $version
This package contains the Linux kernel, modules and corresponding other
diff --git a/scripts/ver_linux b/scripts/ver_linux
index 8f8df93141a9..ab69ecefedbd 100755
--- a/scripts/ver_linux
+++ b/scripts/ver_linux
@@ -21,9 +21,7 @@ gcc --version 2>&1| grep gcc | awk \
make --version 2>&1 | awk -F, '{print $1}' | awk \
'/GNU Make/{print "Gnu make ",$NF}'
-ld -v | awk -F\) '{print $1}' | awk \
-'/BFD/{print "binutils ",$NF} \
-/^GNU/{print "binutils ",$4}'
+echo "binutils $(ld -v | egrep -o '[0-9]+\.[0-9\.]+')"
echo -n "util-linux "
fdformat --version | awk '{print $NF}' | sed -e s/^util-linux-// -e s/\)$//
@@ -65,9 +63,8 @@ isdnctrl 2>&1 | grep version | awk \
showmount --version 2>&1 | grep nfs-utils | awk \
'NR==1{print "nfs-utils ", $NF}'
-ls -l `ldd /bin/sh | awk '/libc/{print $3}'` | sed \
--e 's/\.so$//' | sed -e 's/>//' | \
-awk -F'[.-]' '{print "Linux C Library "$(NF-1)"."$NF}'
+echo -n "Linux C Library "
+sed -n -e '/^.*\/libc-\([^/]*\)\.so$/{s//\1/;p;q}' < /proc/self/maps
ldd -v > /dev/null 2>&1 && ldd -v || ldd --version |head -n 1 | awk \
'NR==1{print "Dynamic linker (ldd) ", $NF}'
diff --git a/security/Kconfig b/security/Kconfig
index 460e5c9cf496..8086e61058e3 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -74,15 +74,25 @@ config SECURITY_NETWORK_XFRM
If you are unsure how to answer this question, answer N.
config SECURITY_CAPABILITIES
- tristate "Default Linux Capabilities"
+ bool "Default Linux Capabilities"
depends on SECURITY
help
This enables the "default" Linux capabilities functionality.
If you are unsure how to answer this question, answer Y.
+config SECURITY_FILE_CAPABILITIES
+ bool "File POSIX Capabilities (EXPERIMENTAL)"
+ depends on (SECURITY=n || SECURITY_CAPABILITIES!=n) && EXPERIMENTAL
+ default n
+ help
+ This enables filesystem capabilities, allowing you to give
+ binaries a subset of root's powers without using setuid 0.
+
+ If in doubt, answer N.
+
config SECURITY_ROOTPLUG
- tristate "Root Plug Support"
- depends on USB && SECURITY
+ bool "Root Plug Support"
+ depends on USB=y && SECURITY
help
This is a sample LSM module that should only be used as such.
It prevents any programs running with egid == 0 if a specific
diff --git a/security/capability.c b/security/capability.c
index 38296a005465..9e99f36a8b5c 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -8,7 +8,6 @@
*
*/
-#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/security.h>
@@ -38,7 +37,13 @@ static struct security_operations capability_ops = {
.inode_setxattr = cap_inode_setxattr,
.inode_removexattr = cap_inode_removexattr,
+ .inode_need_killpriv = cap_inode_need_killpriv,
+ .inode_killpriv = cap_inode_killpriv,
+ .task_kill = cap_task_kill,
+ .task_setscheduler = cap_task_setscheduler,
+ .task_setioprio = cap_task_setioprio,
+ .task_setnice = cap_task_setnice,
.task_post_setuid = cap_task_post_setuid,
.task_reparent_to_init = cap_task_reparent_to_init,
@@ -52,7 +57,6 @@ static int secondary;
static int capability_disable;
module_param_named(disable, capability_disable, int, 0);
-MODULE_PARM_DESC(disable, "To disable capabilities module set disable = 1");
static int __init capability_init (void)
{
@@ -75,26 +79,4 @@ static int __init capability_init (void)
return 0;
}
-static void __exit capability_exit (void)
-{
- if (capability_disable)
- return;
- /* remove ourselves from the security framework */
- if (secondary) {
- if (mod_unreg_security (KBUILD_MODNAME, &capability_ops))
- printk (KERN_INFO "Failure unregistering capabilities "
- "with primary module.\n");
- return;
- }
-
- if (unregister_security (&capability_ops)) {
- printk (KERN_INFO
- "Failure unregistering capabilities with the kernel\n");
- }
-}
-
security_initcall (capability_init);
-module_exit (capability_exit);
-
-MODULE_DESCRIPTION("Standard Linux Capabilities Security Module");
-MODULE_LICENSE("GPL");
diff --git a/security/commoncap.c b/security/commoncap.c
index 7520361663e8..302e8d0839a9 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -22,6 +22,27 @@
#include <linux/ptrace.h>
#include <linux/xattr.h>
#include <linux/hugetlb.h>
+#include <linux/mount.h>
+#include <linux/sched.h>
+
+#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
+/*
+ * Because of the reduced scope of CAP_SETPCAP when filesystem
+ * capabilities are in effect, it is safe to allow this capability to
+ * be available in the default configuration.
+ */
+# define CAP_INIT_BSET CAP_FULL_SET
+#else /* ie. ndef CONFIG_SECURITY_FILE_CAPABILITIES */
+# define CAP_INIT_BSET CAP_INIT_EFF_SET
+#endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */
+
+kernel_cap_t cap_bset = CAP_INIT_BSET; /* systemwide capability bound */
+EXPORT_SYMBOL(cap_bset);
+
+/* Global security state */
+
+unsigned securebits = SECUREBITS_DEFAULT; /* systemwide security settings */
+EXPORT_SYMBOL(securebits);
int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
{
@@ -29,8 +50,6 @@ int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
return 0;
}
-EXPORT_SYMBOL(cap_netlink_send);
-
int cap_netlink_recv(struct sk_buff *skb, int cap)
{
if (!cap_raised(NETLINK_CB(skb).eff_cap, cap))
@@ -74,14 +93,44 @@ int cap_capget (struct task_struct *target, kernel_cap_t *effective,
return 0;
}
+#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
+
+static inline int cap_block_setpcap(struct task_struct *target)
+{
+ /*
+ * No support for remote process capability manipulation with
+ * filesystem capability support.
+ */
+ return (target != current);
+}
+
+static inline int cap_inh_is_capped(void)
+{
+ /*
+ * return 1 if changes to the inheritable set are limited
+ * to the old permitted set.
+ */
+ return !cap_capable(current, CAP_SETPCAP);
+}
+
+#else /* ie., ndef CONFIG_SECURITY_FILE_CAPABILITIES */
+
+static inline int cap_block_setpcap(struct task_struct *t) { return 0; }
+static inline int cap_inh_is_capped(void) { return 1; }
+
+#endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */
+
int cap_capset_check (struct task_struct *target, kernel_cap_t *effective,
kernel_cap_t *inheritable, kernel_cap_t *permitted)
{
- /* Derived from kernel/capability.c:sys_capset. */
- /* verify restrictions on target's new Inheritable set */
- if (!cap_issubset (*inheritable,
- cap_combine (target->cap_inheritable,
- current->cap_permitted))) {
+ if (cap_block_setpcap(target)) {
+ return -EPERM;
+ }
+ if (cap_inh_is_capped()
+ && !cap_issubset(*inheritable,
+ cap_combine(target->cap_inheritable,
+ current->cap_permitted))) {
+ /* incapable of using this inheritable set */
return -EPERM;
}
@@ -108,14 +157,137 @@ void cap_capset_set (struct task_struct *target, kernel_cap_t *effective,
target->cap_permitted = *permitted;
}
+static inline void bprm_clear_caps(struct linux_binprm *bprm)
+{
+ cap_clear(bprm->cap_inheritable);
+ cap_clear(bprm->cap_permitted);
+ bprm->cap_effective = false;
+}
+
+#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
+
+int cap_inode_need_killpriv(struct dentry *dentry)
+{
+ struct inode *inode = dentry->d_inode;
+ int error;
+
+ if (!inode->i_op || !inode->i_op->getxattr)
+ return 0;
+
+ error = inode->i_op->getxattr(dentry, XATTR_NAME_CAPS, NULL, 0);
+ if (error <= 0)
+ return 0;
+ return 1;
+}
+
+int cap_inode_killpriv(struct dentry *dentry)
+{
+ struct inode *inode = dentry->d_inode;
+
+ if (!inode->i_op || !inode->i_op->removexattr)
+ return 0;
+
+ return inode->i_op->removexattr(dentry, XATTR_NAME_CAPS);
+}
+
+static inline int cap_from_disk(struct vfs_cap_data *caps,
+ struct linux_binprm *bprm,
+ int size)
+{
+ __u32 magic_etc;
+
+ if (size != XATTR_CAPS_SZ)
+ return -EINVAL;
+
+ magic_etc = le32_to_cpu(caps->magic_etc);
+
+ switch ((magic_etc & VFS_CAP_REVISION_MASK)) {
+ case VFS_CAP_REVISION:
+ if (magic_etc & VFS_CAP_FLAGS_EFFECTIVE)
+ bprm->cap_effective = true;
+ else
+ bprm->cap_effective = false;
+ bprm->cap_permitted = to_cap_t(le32_to_cpu(caps->permitted));
+ bprm->cap_inheritable = to_cap_t(le32_to_cpu(caps->inheritable));
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+/* Locate any VFS capabilities: */
+static int get_file_caps(struct linux_binprm *bprm)
+{
+ struct dentry *dentry;
+ int rc = 0;
+ struct vfs_cap_data incaps;
+ struct inode *inode;
+
+ if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID) {
+ bprm_clear_caps(bprm);
+ return 0;
+ }
+
+ dentry = dget(bprm->file->f_dentry);
+ inode = dentry->d_inode;
+ if (!inode->i_op || !inode->i_op->getxattr)
+ goto out;
+
+ rc = inode->i_op->getxattr(dentry, XATTR_NAME_CAPS, NULL, 0);
+ if (rc > 0) {
+ if (rc == XATTR_CAPS_SZ)
+ rc = inode->i_op->getxattr(dentry, XATTR_NAME_CAPS,
+ &incaps, XATTR_CAPS_SZ);
+ else
+ rc = -EINVAL;
+ }
+ if (rc == -ENODATA || rc == -EOPNOTSUPP) {
+ /* no data, that's ok */
+ rc = 0;
+ goto out;
+ }
+ if (rc < 0)
+ goto out;
+
+ rc = cap_from_disk(&incaps, bprm, rc);
+ if (rc)
+ printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n",
+ __FUNCTION__, rc, bprm->filename);
+
+out:
+ dput(dentry);
+ if (rc)
+ bprm_clear_caps(bprm);
+
+ return rc;
+}
+
+#else
+int cap_inode_need_killpriv(struct dentry *dentry)
+{
+ return 0;
+}
+
+int cap_inode_killpriv(struct dentry *dentry)
+{
+ return 0;
+}
+
+static inline int get_file_caps(struct linux_binprm *bprm)
+{
+ bprm_clear_caps(bprm);
+ return 0;
+}
+#endif
+
int cap_bprm_set_security (struct linux_binprm *bprm)
{
- /* Copied from fs/exec.c:prepare_binprm. */
+ int ret;
- /* We don't have VFS support for capabilities yet */
- cap_clear (bprm->cap_inheritable);
- cap_clear (bprm->cap_permitted);
- cap_clear (bprm->cap_effective);
+ ret = get_file_caps(bprm);
+ if (ret)
+ printk(KERN_NOTICE "%s: get_file_caps returned %d for %s\n",
+ __FUNCTION__, ret, bprm->filename);
/* To support inheritance of root-permissions and suid-root
* executables under compatibility mode, we raise all three
@@ -131,9 +303,10 @@ int cap_bprm_set_security (struct linux_binprm *bprm)
cap_set_full (bprm->cap_permitted);
}
if (bprm->e_uid == 0)
- cap_set_full (bprm->cap_effective);
+ bprm->cap_effective = true;
}
- return 0;
+
+ return ret;
}
void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
@@ -149,6 +322,7 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
if (bprm->e_uid != current->uid || bprm->e_gid != current->gid ||
!cap_issubset (new_permitted, current->cap_permitted)) {
set_dumpable(current->mm, suid_dumpable);
+ current->pdeath_signal = 0;
if (unsafe & ~LSM_UNSAFE_PTRACE_CAP) {
if (!capable(CAP_SETUID)) {
@@ -168,10 +342,10 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
/* For init, we want to retain the capabilities set
* in the init_task struct. Thus we skip the usual
* capability rules */
- if (!is_init(current)) {
+ if (!is_global_init(current)) {
current->cap_permitted = new_permitted;
- current->cap_effective =
- cap_intersect (new_permitted, bprm->cap_effective);
+ current->cap_effective = bprm->cap_effective ?
+ new_permitted : 0;
}
/* AUD: Audit candidate if current->cap_effective is set */
@@ -181,11 +355,15 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
int cap_bprm_secureexec (struct linux_binprm *bprm)
{
- /* If/when this module is enhanced to incorporate capability
- bits on files, the test below should be extended to also perform a
- test between the old and new capability sets. For now,
- it simply preserves the legacy decision algorithm used by
- the old userland. */
+ if (current->uid != 0) {
+ if (bprm->cap_effective)
+ return 1;
+ if (!cap_isclear(bprm->cap_permitted))
+ return 1;
+ if (!cap_isclear(bprm->cap_inheritable))
+ return 1;
+ }
+
return (current->euid != current->uid ||
current->egid != current->gid);
}
@@ -193,7 +371,11 @@ int cap_bprm_secureexec (struct linux_binprm *bprm)
int cap_inode_setxattr(struct dentry *dentry, char *name, void *value,
size_t size, int flags)
{
- if (!strncmp(name, XATTR_SECURITY_PREFIX,
+ if (!strcmp(name, XATTR_NAME_CAPS)) {
+ if (!capable(CAP_SETFCAP))
+ return -EPERM;
+ return 0;
+ } else if (!strncmp(name, XATTR_SECURITY_PREFIX,
sizeof(XATTR_SECURITY_PREFIX) - 1) &&
!capable(CAP_SYS_ADMIN))
return -EPERM;
@@ -202,7 +384,11 @@ int cap_inode_setxattr(struct dentry *dentry, char *name, void *value,
int cap_inode_removexattr(struct dentry *dentry, char *name)
{
- if (!strncmp(name, XATTR_SECURITY_PREFIX,
+ if (!strcmp(name, XATTR_NAME_CAPS)) {
+ if (!capable(CAP_SETFCAP))
+ return -EPERM;
+ return 0;
+ } else if (!strncmp(name, XATTR_SECURITY_PREFIX,
sizeof(XATTR_SECURITY_PREFIX) - 1) &&
!capable(CAP_SYS_ADMIN))
return -EPERM;
@@ -299,6 +485,87 @@ int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid,
return 0;
}
+#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
+/*
+ * Rationale: code calling task_setscheduler, task_setioprio, and
+ * task_setnice, assumes that
+ * . if capable(cap_sys_nice), then those actions should be allowed
+ * . if not capable(cap_sys_nice), but acting on your own processes,
+ * then those actions should be allowed
+ * This is insufficient now since you can call code without suid, but
+ * yet with increased caps.
+ * So we check for increased caps on the target process.
+ */
+static inline int cap_safe_nice(struct task_struct *p)
+{
+ if (!cap_issubset(p->cap_permitted, current->cap_permitted) &&
+ !__capable(current, CAP_SYS_NICE))
+ return -EPERM;
+ return 0;
+}
+
+int cap_task_setscheduler (struct task_struct *p, int policy,
+ struct sched_param *lp)
+{
+ return cap_safe_nice(p);
+}
+
+int cap_task_setioprio (struct task_struct *p, int ioprio)
+{
+ return cap_safe_nice(p);
+}
+
+int cap_task_setnice (struct task_struct *p, int nice)
+{
+ return cap_safe_nice(p);
+}
+
+int cap_task_kill(struct task_struct *p, struct siginfo *info,
+ int sig, u32 secid)
+{
+ if (info != SEND_SIG_NOINFO && (is_si_special(info) || SI_FROMKERNEL(info)))
+ return 0;
+
+ /* sigcont is permitted within same session */
+ if (sig == SIGCONT && (task_session_nr(current) == task_session_nr(p)))
+ return 0;
+
+ if (secid)
+ /*
+ * Signal sent as a particular user.
+ * Capabilities are ignored. May be wrong, but it's the
+ * only thing we can do at the moment.
+ * Used only by usb drivers?
+ */
+ return 0;
+ if (cap_issubset(p->cap_permitted, current->cap_permitted))
+ return 0;
+ if (capable(CAP_KILL))
+ return 0;
+
+ return -EPERM;
+}
+#else
+int cap_task_setscheduler (struct task_struct *p, int policy,
+ struct sched_param *lp)
+{
+ return 0;
+}
+int cap_task_setioprio (struct task_struct *p, int ioprio)
+{
+ return 0;
+}
+int cap_task_setnice (struct task_struct *p, int nice)
+{
+ return 0;
+}
+int cap_task_kill(struct task_struct *p, struct siginfo *info,
+ int sig, u32 secid)
+{
+ return 0;
+}
+#endif
+
void cap_task_reparent_to_init (struct task_struct *p)
{
p->cap_effective = CAP_INIT_EFF_SET;
@@ -324,21 +591,3 @@ int cap_vm_enough_memory(struct mm_struct *mm, long pages)
return __vm_enough_memory(mm, pages, cap_sys_admin);
}
-EXPORT_SYMBOL(cap_capable);
-EXPORT_SYMBOL(cap_settime);
-EXPORT_SYMBOL(cap_ptrace);
-EXPORT_SYMBOL(cap_capget);
-EXPORT_SYMBOL(cap_capset_check);
-EXPORT_SYMBOL(cap_capset_set);
-EXPORT_SYMBOL(cap_bprm_set_security);
-EXPORT_SYMBOL(cap_bprm_apply_creds);
-EXPORT_SYMBOL(cap_bprm_secureexec);
-EXPORT_SYMBOL(cap_inode_setxattr);
-EXPORT_SYMBOL(cap_inode_removexattr);
-EXPORT_SYMBOL(cap_task_post_setuid);
-EXPORT_SYMBOL(cap_task_reparent_to_init);
-EXPORT_SYMBOL(cap_syslog);
-EXPORT_SYMBOL(cap_vm_enough_memory);
-
-MODULE_DESCRIPTION("Standard Linux Common Capabilities Security Module");
-MODULE_LICENSE("GPL");
diff --git a/security/dummy.c b/security/dummy.c
index 853ec2292798..6d895ade73de 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -15,7 +15,6 @@
#undef DEBUG
#include <linux/capability.h>
-#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mman.h>
#include <linux/pagemap.h>
@@ -38,15 +37,13 @@ static int dummy_capget (struct task_struct *target, kernel_cap_t * effective,
kernel_cap_t * inheritable, kernel_cap_t * permitted)
{
*effective = *inheritable = *permitted = 0;
- if (!issecure(SECURE_NOROOT)) {
- if (target->euid == 0) {
- *permitted |= (~0 & ~CAP_FS_MASK);
- *effective |= (~0 & ~CAP_TO_MASK(CAP_SETPCAP) & ~CAP_FS_MASK);
- }
- if (target->fsuid == 0) {
- *permitted |= CAP_FS_MASK;
- *effective |= CAP_FS_MASK;
- }
+ if (target->euid == 0) {
+ *permitted |= (~0 & ~CAP_FS_MASK);
+ *effective |= (~0 & ~CAP_TO_MASK(CAP_SETPCAP) & ~CAP_FS_MASK);
+ }
+ if (target->fsuid == 0) {
+ *permitted |= CAP_FS_MASK;
+ *effective |= CAP_FS_MASK;
}
return 0;
}
@@ -377,6 +374,16 @@ static int dummy_inode_removexattr (struct dentry *dentry, char *name)
return 0;
}
+static int dummy_inode_need_killpriv(struct dentry *dentry)
+{
+ return 0;
+}
+
+static int dummy_inode_killpriv(struct dentry *dentry)
+{
+ return 0;
+}
+
static int dummy_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
{
return -EOPNOTSUPP;
@@ -392,11 +399,6 @@ static int dummy_inode_listsecurity(struct inode *inode, char *buffer, size_t bu
return 0;
}
-static const char *dummy_inode_xattr_getsuffix(void)
-{
- return NULL;
-}
-
static int dummy_file_permission (struct file *file, int mask)
{
return 0;
@@ -463,6 +465,11 @@ static int dummy_file_receive (struct file *file)
return 0;
}
+static int dummy_dentry_open (struct file *file)
+{
+ return 0;
+}
+
static int dummy_task_create (unsigned long clone_flags)
{
return 0;
@@ -901,11 +908,6 @@ static int dummy_register_security (const char *name, struct security_operations
return -EINVAL;
}
-static int dummy_unregister_security (const char *name, struct security_operations *ops)
-{
- return -EINVAL;
-}
-
static void dummy_d_instantiate (struct dentry *dentry, struct inode *inode)
{
return;
@@ -1018,7 +1020,8 @@ void security_fixup_ops (struct security_operations *ops)
set_to_dummy_if_null(ops, inode_getxattr);
set_to_dummy_if_null(ops, inode_listxattr);
set_to_dummy_if_null(ops, inode_removexattr);
- set_to_dummy_if_null(ops, inode_xattr_getsuffix);
+ set_to_dummy_if_null(ops, inode_need_killpriv);
+ set_to_dummy_if_null(ops, inode_killpriv);
set_to_dummy_if_null(ops, inode_getsecurity);
set_to_dummy_if_null(ops, inode_setsecurity);
set_to_dummy_if_null(ops, inode_listsecurity);
@@ -1033,6 +1036,7 @@ void security_fixup_ops (struct security_operations *ops)
set_to_dummy_if_null(ops, file_set_fowner);
set_to_dummy_if_null(ops, file_send_sigiotask);
set_to_dummy_if_null(ops, file_receive);
+ set_to_dummy_if_null(ops, dentry_open);
set_to_dummy_if_null(ops, task_create);
set_to_dummy_if_null(ops, task_alloc_security);
set_to_dummy_if_null(ops, task_free_security);
@@ -1078,7 +1082,6 @@ void security_fixup_ops (struct security_operations *ops)
set_to_dummy_if_null(ops, netlink_send);
set_to_dummy_if_null(ops, netlink_recv);
set_to_dummy_if_null(ops, register_security);
- set_to_dummy_if_null(ops, unregister_security);
set_to_dummy_if_null(ops, d_instantiate);
set_to_dummy_if_null(ops, getprocattr);
set_to_dummy_if_null(ops, setprocattr);
diff --git a/security/inode.c b/security/inode.c
index 307211ac7346..b28a8acae34d 100644
--- a/security/inode.c
+++ b/security/inode.c
@@ -332,14 +332,6 @@ static int __init securityfs_init(void)
return retval;
}
-static void __exit securityfs_exit(void)
-{
- simple_release_fs(&mount, &mount_count);
- unregister_filesystem(&fs_type);
- subsystem_unregister(&security_subsys);
-}
-
core_initcall(securityfs_init);
-module_exit(securityfs_exit);
MODULE_LICENSE("GPL");
diff --git a/security/keys/internal.h b/security/keys/internal.h
index 1bb416f4bbce..d36d69393356 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -1,6 +1,6 @@
/* internal.h: authentication token and access key management internal defs
*
- * Copyright (C) 2003-5 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2003-5, 2007 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
@@ -12,17 +12,28 @@
#ifndef _INTERNAL_H
#define _INTERNAL_H
-#include <linux/key.h>
+#include <linux/key-type.h>
#include <linux/key-ui.h>
-#if 0
-#define kenter(FMT, a...) printk("==> %s("FMT")\n",__FUNCTION__ , ## a)
-#define kleave(FMT, a...) printk("<== %s()"FMT"\n",__FUNCTION__ , ## a)
-#define kdebug(FMT, a...) printk(FMT"\n" , ## a)
+static inline __attribute__((format(printf, 1, 2)))
+void no_printk(const char *fmt, ...)
+{
+}
+
+#ifdef __KDEBUG
+#define kenter(FMT, ...) \
+ printk(KERN_DEBUG "==> %s("FMT")\n", __FUNCTION__, ##__VA_ARGS__)
+#define kleave(FMT, ...) \
+ printk(KERN_DEBUG "<== %s()"FMT"\n", __FUNCTION__, ##__VA_ARGS__)
+#define kdebug(FMT, ...) \
+ printk(KERN_DEBUG "xxx" FMT"yyy\n", ##__VA_ARGS__)
#else
-#define kenter(FMT, a...) do {} while(0)
-#define kleave(FMT, a...) do {} while(0)
-#define kdebug(FMT, a...) do {} while(0)
+#define kenter(FMT, ...) \
+ no_printk(KERN_DEBUG "==> %s("FMT")\n", __FUNCTION__, ##__VA_ARGS__)
+#define kleave(FMT, ...) \
+ no_printk(KERN_DEBUG "<== %s()"FMT"\n", __FUNCTION__, ##__VA_ARGS__)
+#define kdebug(FMT, ...) \
+ no_printk(KERN_DEBUG FMT"\n", ##__VA_ARGS__)
#endif
extern struct key_type key_type_user;
@@ -36,7 +47,7 @@ extern struct key_type key_type_user;
*/
struct key_user {
struct rb_node node;
- struct list_head consq; /* construction queue */
+ struct mutex cons_lock; /* construction initiation lock */
spinlock_t lock;
atomic_t usage; /* for accessing qnkeys & qnbytes */
atomic_t nkeys; /* number of keys */
@@ -62,7 +73,7 @@ extern void key_user_put(struct key_user *user);
extern struct rb_root key_serial_tree;
extern spinlock_t key_serial_lock;
extern struct semaphore key_alloc_sem;
-extern struct rw_semaphore key_construction_sem;
+extern struct mutex key_construction_mutex;
extern wait_queue_head_t request_key_conswq;
@@ -109,7 +120,7 @@ extern struct key *request_key_and_link(struct key_type *type,
struct request_key_auth {
struct key *target_key;
struct task_struct *context;
- const char *callout_info;
+ char *callout_info;
pid_t pid;
};
diff --git a/security/keys/key.c b/security/keys/key.c
index 01bbc6d9d19b..fdd5ca6d89fc 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -1,6 +1,6 @@
-/* key.c: basic authentication token and access key management
+/* Basic authentication token and access key management
*
- * Copyright (C) 2004-6 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
@@ -34,7 +34,7 @@ static void key_cleanup(struct work_struct *work);
static DECLARE_WORK(key_cleanup_task, key_cleanup);
/* we serialise key instantiation and link */
-DECLARE_RWSEM(key_construction_sem);
+DEFINE_MUTEX(key_construction_mutex);
/* any key who's type gets unegistered will be re-typed to this */
static struct key_type key_type_dead = {
@@ -104,7 +104,7 @@ struct key_user *key_user_lookup(uid_t uid)
candidate->qnkeys = 0;
candidate->qnbytes = 0;
spin_lock_init(&candidate->lock);
- INIT_LIST_HEAD(&candidate->consq);
+ mutex_init(&candidate->cons_lock);
rb_link_node(&candidate->node, parent, p);
rb_insert_color(&candidate->node, &key_user_tree);
@@ -418,7 +418,7 @@ static int __key_instantiate_and_link(struct key *key,
awaken = 0;
ret = -EBUSY;
- down_write(&key_construction_sem);
+ mutex_lock(&key_construction_mutex);
/* can't instantiate twice */
if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) {
@@ -443,11 +443,11 @@ static int __key_instantiate_and_link(struct key *key,
}
}
- up_write(&key_construction_sem);
+ mutex_unlock(&key_construction_mutex);
/* wake up anyone waiting for a key to be constructed */
if (awaken)
- wake_up_all(&request_key_conswq);
+ wake_up_bit(&key->flags, KEY_FLAG_USER_CONSTRUCT);
return ret;
@@ -500,7 +500,7 @@ int key_negate_and_link(struct key *key,
if (keyring)
down_write(&keyring->sem);
- down_write(&key_construction_sem);
+ mutex_lock(&key_construction_mutex);
/* can't instantiate twice */
if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) {
@@ -525,14 +525,14 @@ int key_negate_and_link(struct key *key,
key_revoke(instkey);
}
- up_write(&key_construction_sem);
+ mutex_unlock(&key_construction_mutex);
if (keyring)
up_write(&keyring->sem);
/* wake up anyone waiting for a key to be constructed */
if (awaken)
- wake_up_all(&request_key_conswq);
+ wake_up_bit(&key->flags, KEY_FLAG_USER_CONSTRUCT);
return ret;
@@ -899,12 +899,14 @@ void key_revoke(struct key *key)
{
key_check(key);
- /* make sure no one's trying to change or use the key when we mark
- * it */
- down_write(&key->sem);
- set_bit(KEY_FLAG_REVOKED, &key->flags);
-
- if (key->type->revoke)
+ /* make sure no one's trying to change or use the key when we mark it
+ * - we tell lockdep that we might nest because we might be revoking an
+ * authorisation key whilst holding the sem on a key we've just
+ * instantiated
+ */
+ down_write_nested(&key->sem, 1);
+ if (!test_and_set_bit(KEY_FLAG_REVOKED, &key->flags) &&
+ key->type->revoke)
key->type->revoke(key);
up_write(&key->sem);
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index b6f86808475a..2a0eb946fc7e 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -26,7 +26,7 @@ static DEFINE_MUTEX(key_session_mutex);
/* the root user's tracking struct */
struct key_user root_key_user = {
.usage = ATOMIC_INIT(3),
- .consq = LIST_HEAD_INIT(root_key_user.consq),
+ .cons_lock = __MUTEX_INITIALIZER(root_key_user.cons_lock),
.lock = __SPIN_LOCK_UNLOCKED(root_key_user.lock),
.nkeys = ATOMIC_INIT(2),
.nikeys = ATOMIC_INIT(2),
@@ -679,8 +679,18 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id,
break;
}
- /* check the status */
- if (perm) {
+ if (!partial) {
+ ret = wait_for_key_construction(key, true);
+ switch (ret) {
+ case -ERESTARTSYS:
+ goto invalid_key;
+ default:
+ if (perm)
+ goto invalid_key;
+ case 0:
+ break;
+ }
+ } else if (perm) {
ret = key_validate(key);
if (ret < 0)
goto invalid_key;
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 557500110a13..6381e616c477 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -1,6 +1,6 @@
-/* request_key.c: request a key from userspace
+/* Request a key from userspace
*
- * Copyright (C) 2004-6 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
@@ -18,27 +18,54 @@
#include <linux/keyctl.h>
#include "internal.h"
-struct key_construction {
- struct list_head link; /* link in construction queue */
- struct key *key; /* key being constructed */
-};
+/*
+ * wait_on_bit() sleep function for uninterruptible waiting
+ */
+static int key_wait_bit(void *flags)
+{
+ schedule();
+ return 0;
+}
+
+/*
+ * wait_on_bit() sleep function for interruptible waiting
+ */
+static int key_wait_bit_intr(void *flags)
+{
+ schedule();
+ return signal_pending(current) ? -ERESTARTSYS : 0;
+}
+
+/*
+ * call to complete the construction of a key
+ */
+void complete_request_key(struct key_construction *cons, int error)
+{
+ kenter("{%d,%d},%d", cons->key->serial, cons->authkey->serial, error);
-/* when waiting for someone else's keys, you get added to this */
-DECLARE_WAIT_QUEUE_HEAD(request_key_conswq);
+ if (error < 0)
+ key_negate_and_link(cons->key, key_negative_timeout, NULL,
+ cons->authkey);
+ else
+ key_revoke(cons->authkey);
+
+ key_put(cons->key);
+ key_put(cons->authkey);
+ kfree(cons);
+}
+EXPORT_SYMBOL(complete_request_key);
-/*****************************************************************************/
/*
* request userspace finish the construction of a key
* - execute "/sbin/request-key <op> <key> <uid> <gid> <keyring> <keyring> <keyring>"
*/
-static int call_sbin_request_key(struct key *key,
- struct key *authkey,
+static int call_sbin_request_key(struct key_construction *cons,
const char *op,
void *aux)
{
struct task_struct *tsk = current;
key_serial_t prkey, sskey;
- struct key *keyring;
+ struct key *key = cons->key, *authkey = cons->authkey, *keyring;
char *argv[9], *envp[3], uid_str[12], gid_str[12];
char key_str[12], keyring_str[3][12];
char desc[20];
@@ -82,8 +109,7 @@ static int call_sbin_request_key(struct key *key,
rcu_read_lock();
sskey = rcu_dereference(tsk->signal->session_keyring)->serial;
rcu_read_unlock();
- }
- else {
+ } else {
sskey = tsk->user->session_keyring->serial;
}
@@ -110,228 +136,77 @@ static int call_sbin_request_key(struct key *key,
/* do it */
ret = call_usermodehelper_keys(argv[0], argv, envp, keyring,
UMH_WAIT_PROC);
+ kdebug("usermode -> 0x%x", ret);
+ if (ret >= 0) {
+ /* ret is the exit/wait code */
+ if (test_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags) ||
+ key_validate(key) < 0)
+ ret = -ENOKEY;
+ else
+ /* ignore any errors from userspace if the key was
+ * instantiated */
+ ret = 0;
+ }
error_link:
key_put(keyring);
error_alloc:
kleave(" = %d", ret);
+ complete_request_key(cons, ret);
return ret;
+}
-} /* end call_sbin_request_key() */
-
-/*****************************************************************************/
/*
- * call out to userspace for the key
- * - called with the construction sem held, but the sem is dropped here
+ * call out to userspace for key construction
* - we ignore program failure and go on key status instead
*/
-static struct key *__request_key_construction(struct key_type *type,
- const char *description,
- const char *callout_info,
- void *aux,
- unsigned long flags)
+static int construct_key(struct key *key, const char *callout_info, void *aux)
{
+ struct key_construction *cons;
request_key_actor_t actor;
- struct key_construction cons;
- struct timespec now;
- struct key *key, *authkey;
- int ret, negated;
+ struct key *authkey;
+ int ret;
- kenter("%s,%s,%s,%lx", type->name, description, callout_info, flags);
+ kenter("%d,%s,%p", key->serial, callout_info, aux);
- /* create a key and add it to the queue */
- key = key_alloc(type, description,
- current->fsuid, current->fsgid, current, KEY_POS_ALL,
- flags);
- if (IS_ERR(key))
- goto alloc_failed;
-
- set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags);
-
- cons.key = key;
- list_add_tail(&cons.link, &key->user->consq);
-
- /* we drop the construction sem here on behalf of the caller */
- up_write(&key_construction_sem);
+ cons = kmalloc(sizeof(*cons), GFP_KERNEL);
+ if (!cons)
+ return -ENOMEM;
/* allocate an authorisation key */
authkey = request_key_auth_new(key, callout_info);
if (IS_ERR(authkey)) {
+ kfree(cons);
ret = PTR_ERR(authkey);
authkey = NULL;
- goto alloc_authkey_failed;
- }
-
- /* make the call */
- actor = call_sbin_request_key;
- if (type->request_key)
- actor = type->request_key;
- ret = actor(key, authkey, "create", aux);
- if (ret < 0)
- goto request_failed;
-
- /* if the key wasn't instantiated, then we want to give an error */
- ret = -ENOKEY;
- if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
- goto request_failed;
-
- key_revoke(authkey);
- key_put(authkey);
-
- down_write(&key_construction_sem);
- list_del(&cons.link);
- up_write(&key_construction_sem);
-
- /* also give an error if the key was negatively instantiated */
-check_not_negative:
- if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) {
- key_put(key);
- key = ERR_PTR(-ENOKEY);
- }
-
-out:
- kleave(" = %p", key);
- return key;
-
-request_failed:
- key_revoke(authkey);
- key_put(authkey);
-
-alloc_authkey_failed:
- /* it wasn't instantiated
- * - remove from construction queue
- * - mark the key as dead
- */
- negated = 0;
- down_write(&key_construction_sem);
-
- list_del(&cons.link);
-
- /* check it didn't get instantiated between the check and the down */
- if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) {
- set_bit(KEY_FLAG_NEGATIVE, &key->flags);
- set_bit(KEY_FLAG_INSTANTIATED, &key->flags);
- negated = 1;
- }
-
- clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags);
-
- up_write(&key_construction_sem);
-
- if (!negated)
- goto check_not_negative; /* surprisingly, the key got
- * instantiated */
-
- /* set the timeout and store in the session keyring if we can */
- now = current_kernel_time();
- key->expiry = now.tv_sec + key_negative_timeout;
-
- if (current->signal->session_keyring) {
- struct key *keyring;
-
- rcu_read_lock();
- keyring = rcu_dereference(current->signal->session_keyring);
- atomic_inc(&keyring->usage);
- rcu_read_unlock();
-
- key_link(keyring, key);
- key_put(keyring);
- }
-
- key_put(key);
-
- /* notify anyone who was waiting */
- wake_up_all(&request_key_conswq);
-
- key = ERR_PTR(ret);
- goto out;
-
-alloc_failed:
- up_write(&key_construction_sem);
- goto out;
-
-} /* end __request_key_construction() */
-
-/*****************************************************************************/
-/*
- * call out to userspace to request the key
- * - we check the construction queue first to see if an appropriate key is
- * already being constructed by userspace
- */
-static struct key *request_key_construction(struct key_type *type,
- const char *description,
- const char *callout_info,
- void *aux,
- struct key_user *user,
- unsigned long flags)
-{
- struct key_construction *pcons;
- struct key *key, *ckey;
-
- DECLARE_WAITQUEUE(myself, current);
-
- kenter("%s,%s,{%d},%s,%lx",
- type->name, description, user->uid, callout_info, flags);
-
- /* see if there's such a key under construction already */
- down_write(&key_construction_sem);
-
- list_for_each_entry(pcons, &user->consq, link) {
- ckey = pcons->key;
-
- if (ckey->type != type)
- continue;
-
- if (type->match(ckey, description))
- goto found_key_under_construction;
+ } else {
+ cons->authkey = key_get(authkey);
+ cons->key = key_get(key);
+
+ /* make the call */
+ actor = call_sbin_request_key;
+ if (key->type->request_key)
+ actor = key->type->request_key;
+
+ ret = actor(cons, "create", aux);
+
+ /* check that the actor called complete_request_key() prior to
+ * returning an error */
+ WARN_ON(ret < 0 &&
+ !test_bit(KEY_FLAG_REVOKED, &authkey->flags));
+ key_put(authkey);
}
- /* see about getting userspace to construct the key */
- key = __request_key_construction(type, description, callout_info, aux,
- flags);
- error:
- kleave(" = %p", key);
- return key;
-
- /* someone else has the same key under construction
- * - we want to keep an eye on their key
- */
- found_key_under_construction:
- atomic_inc(&ckey->usage);
- up_write(&key_construction_sem);
-
- /* wait for the key to be completed one way or another */
- add_wait_queue(&request_key_conswq, &myself);
-
- for (;;) {
- set_current_state(TASK_INTERRUPTIBLE);
- if (!test_bit(KEY_FLAG_USER_CONSTRUCT, &ckey->flags))
- break;
- if (signal_pending(current))
- break;
- schedule();
- }
-
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&request_key_conswq, &myself);
-
- /* we'll need to search this process's keyrings to see if the key is
- * now there since we can't automatically assume it's also available
- * there */
- key_put(ckey);
- ckey = NULL;
-
- key = NULL; /* request a retry */
- goto error;
-
-} /* end request_key_construction() */
+ kleave(" = %d", ret);
+ return ret;
+}
-/*****************************************************************************/
/*
- * link a freshly minted key to an appropriate destination keyring
+ * link a key to the appropriate destination keyring
+ * - the caller must hold a write lock on the destination keyring
*/
-static void request_key_link(struct key *key, struct key *dest_keyring)
+static void construct_key_make_link(struct key *key, struct key *dest_keyring)
{
struct task_struct *tsk = current;
struct key *drop = NULL;
@@ -363,11 +238,11 @@ static void request_key_link(struct key *key, struct key *dest_keyring)
break;
case KEY_REQKEY_DEFL_USER_SESSION_KEYRING:
- dest_keyring = current->user->session_keyring;
+ dest_keyring = tsk->user->session_keyring;
break;
case KEY_REQKEY_DEFL_USER_KEYRING:
- dest_keyring = current->user->uid_keyring;
+ dest_keyring = tsk->user->uid_keyring;
break;
case KEY_REQKEY_DEFL_GROUP_KEYRING:
@@ -377,15 +252,115 @@ static void request_key_link(struct key *key, struct key *dest_keyring)
}
/* and attach the key to it */
- key_link(dest_keyring, key);
-
+ __key_link(dest_keyring, key);
key_put(drop);
-
kleave("");
+}
-} /* end request_key_link() */
+/*
+ * allocate a new key in under-construction state and attempt to link it in to
+ * the requested place
+ * - may return a key that's already under construction instead
+ */
+static int construct_alloc_key(struct key_type *type,
+ const char *description,
+ struct key *dest_keyring,
+ unsigned long flags,
+ struct key_user *user,
+ struct key **_key)
+{
+ struct key *key;
+ key_ref_t key_ref;
+
+ kenter("%s,%s,,,", type->name, description);
+
+ mutex_lock(&user->cons_lock);
+
+ key = key_alloc(type, description,
+ current->fsuid, current->fsgid, current, KEY_POS_ALL,
+ flags);
+ if (IS_ERR(key))
+ goto alloc_failed;
+
+ set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags);
+
+ if (dest_keyring)
+ down_write(&dest_keyring->sem);
+
+ /* attach the key to the destination keyring under lock, but we do need
+ * to do another check just in case someone beat us to it whilst we
+ * waited for locks */
+ mutex_lock(&key_construction_mutex);
+
+ key_ref = search_process_keyrings(type, description, type->match,
+ current);
+ if (!IS_ERR(key_ref))
+ goto key_already_present;
+
+ if (dest_keyring)
+ construct_key_make_link(key, dest_keyring);
+
+ mutex_unlock(&key_construction_mutex);
+ if (dest_keyring)
+ up_write(&dest_keyring->sem);
+ mutex_unlock(&user->cons_lock);
+ *_key = key;
+ kleave(" = 0 [%d]", key_serial(key));
+ return 0;
+
+key_already_present:
+ mutex_unlock(&key_construction_mutex);
+ if (dest_keyring)
+ up_write(&dest_keyring->sem);
+ mutex_unlock(&user->cons_lock);
+ key_put(key);
+ *_key = key = key_ref_to_ptr(key_ref);
+ kleave(" = -EINPROGRESS [%d]", key_serial(key));
+ return -EINPROGRESS;
+
+alloc_failed:
+ mutex_unlock(&user->cons_lock);
+ *_key = NULL;
+ kleave(" = %ld", PTR_ERR(key));
+ return PTR_ERR(key);
+}
+
+/*
+ * commence key construction
+ */
+static struct key *construct_key_and_link(struct key_type *type,
+ const char *description,
+ const char *callout_info,
+ void *aux,
+ struct key *dest_keyring,
+ unsigned long flags)
+{
+ struct key_user *user;
+ struct key *key;
+ int ret;
+
+ user = key_user_lookup(current->fsuid);
+ if (!user)
+ return ERR_PTR(-ENOMEM);
+
+ ret = construct_alloc_key(type, description, dest_keyring, flags, user,
+ &key);
+ key_user_put(user);
+
+ if (ret == 0) {
+ ret = construct_key(key, callout_info, aux);
+ if (ret < 0)
+ goto construction_failed;
+ }
+
+ return key;
+
+construction_failed:
+ key_negate_and_link(key, key_negative_timeout, NULL, NULL);
+ key_put(key);
+ return ERR_PTR(ret);
+}
-/*****************************************************************************/
/*
* request a key
* - search the process's keyrings
@@ -400,7 +375,6 @@ struct key *request_key_and_link(struct key_type *type,
struct key *dest_keyring,
unsigned long flags)
{
- struct key_user *user;
struct key *key;
key_ref_t key_ref;
@@ -412,112 +386,124 @@ struct key *request_key_and_link(struct key_type *type,
key_ref = search_process_keyrings(type, description, type->match,
current);
- kdebug("search 1: %p", key_ref);
-
if (!IS_ERR(key_ref)) {
key = key_ref_to_ptr(key_ref);
- }
- else if (PTR_ERR(key_ref) != -EAGAIN) {
+ } else if (PTR_ERR(key_ref) != -EAGAIN) {
key = ERR_PTR(PTR_ERR(key_ref));
- }
- else {
+ } else {
/* the search failed, but the keyrings were searchable, so we
* should consult userspace if we can */
key = ERR_PTR(-ENOKEY);
if (!callout_info)
goto error;
- /* - get hold of the user's construction queue */
- user = key_user_lookup(current->fsuid);
- if (!user)
- goto nomem;
-
- for (;;) {
- if (signal_pending(current))
- goto interrupted;
-
- /* ask userspace (returns NULL if it waited on a key
- * being constructed) */
- key = request_key_construction(type, description,
- callout_info, aux,
- user, flags);
- if (key)
- break;
-
- /* someone else made the key we want, so we need to
- * search again as it might now be available to us */
- key_ref = search_process_keyrings(type, description,
- type->match,
- current);
-
- kdebug("search 2: %p", key_ref);
-
- if (!IS_ERR(key_ref)) {
- key = key_ref_to_ptr(key_ref);
- break;
- }
-
- if (PTR_ERR(key_ref) != -EAGAIN) {
- key = ERR_PTR(PTR_ERR(key_ref));
- break;
- }
- }
-
- key_user_put(user);
-
- /* link the new key into the appropriate keyring */
- if (!IS_ERR(key))
- request_key_link(key, dest_keyring);
+ key = construct_key_and_link(type, description, callout_info,
+ aux, dest_keyring, flags);
}
error:
kleave(" = %p", key);
return key;
+}
-nomem:
- key = ERR_PTR(-ENOMEM);
- goto error;
-
-interrupted:
- key_user_put(user);
- key = ERR_PTR(-EINTR);
- goto error;
+/*
+ * wait for construction of a key to complete
+ */
+int wait_for_key_construction(struct key *key, bool intr)
+{
+ int ret;
-} /* end request_key_and_link() */
+ ret = wait_on_bit(&key->flags, KEY_FLAG_USER_CONSTRUCT,
+ intr ? key_wait_bit_intr : key_wait_bit,
+ intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
+ if (ret < 0)
+ return ret;
+ return key_validate(key);
+}
+EXPORT_SYMBOL(wait_for_key_construction);
-/*****************************************************************************/
/*
* request a key
* - search the process's keyrings
* - check the list of keys being created or updated
* - call out to userspace for a key if supplementary info was provided
+ * - waits uninterruptible for creation to complete
*/
struct key *request_key(struct key_type *type,
const char *description,
const char *callout_info)
{
- return request_key_and_link(type, description, callout_info, NULL,
- NULL, KEY_ALLOC_IN_QUOTA);
-
-} /* end request_key() */
-
+ struct key *key;
+ int ret;
+
+ key = request_key_and_link(type, description, callout_info, NULL,
+ NULL, KEY_ALLOC_IN_QUOTA);
+ if (!IS_ERR(key)) {
+ ret = wait_for_key_construction(key, false);
+ if (ret < 0) {
+ key_put(key);
+ return ERR_PTR(ret);
+ }
+ }
+ return key;
+}
EXPORT_SYMBOL(request_key);
-/*****************************************************************************/
/*
* request a key with auxiliary data for the upcaller
* - search the process's keyrings
* - check the list of keys being created or updated
* - call out to userspace for a key if supplementary info was provided
+ * - waits uninterruptible for creation to complete
*/
struct key *request_key_with_auxdata(struct key_type *type,
const char *description,
const char *callout_info,
void *aux)
{
- return request_key_and_link(type, description, callout_info, aux,
- NULL, KEY_ALLOC_IN_QUOTA);
+ struct key *key;
+ int ret;
+
+ key = request_key_and_link(type, description, callout_info, aux,
+ NULL, KEY_ALLOC_IN_QUOTA);
+ if (!IS_ERR(key)) {
+ ret = wait_for_key_construction(key, false);
+ if (ret < 0) {
+ key_put(key);
+ return ERR_PTR(ret);
+ }
+ }
+ return key;
+}
+EXPORT_SYMBOL(request_key_with_auxdata);
-} /* end request_key_with_auxdata() */
+/*
+ * request a key (allow async construction)
+ * - search the process's keyrings
+ * - check the list of keys being created or updated
+ * - call out to userspace for a key if supplementary info was provided
+ */
+struct key *request_key_async(struct key_type *type,
+ const char *description,
+ const char *callout_info)
+{
+ return request_key_and_link(type, description, callout_info, NULL,
+ NULL, KEY_ALLOC_IN_QUOTA);
+}
+EXPORT_SYMBOL(request_key_async);
-EXPORT_SYMBOL(request_key_with_auxdata);
+/*
+ * request a key with auxiliary data for the upcaller (allow async construction)
+ * - search the process's keyrings
+ * - check the list of keys being created or updated
+ * - call out to userspace for a key if supplementary info was provided
+ */
+struct key *request_key_async_with_auxdata(struct key_type *type,
+ const char *description,
+ const char *callout_info,
+ void *aux)
+{
+ return request_key_and_link(type, description, callout_info, aux,
+ NULL, KEY_ALLOC_IN_QUOTA);
+}
+EXPORT_SYMBOL(request_key_async_with_auxdata);
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
index cbf58a91b00a..510f7be73a2d 100644
--- a/security/keys/request_key_auth.c
+++ b/security/keys/request_key_auth.c
@@ -127,6 +127,7 @@ static void request_key_auth_destroy(struct key *key)
}
key_put(rka->target_key);
+ kfree(rka->callout_info);
kfree(rka);
} /* end request_key_auth_destroy() */
@@ -151,6 +152,12 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info)
kleave(" = -ENOMEM");
return ERR_PTR(-ENOMEM);
}
+ rka->callout_info = kmalloc(strlen(callout_info) + 1, GFP_KERNEL);
+ if (!rka->callout_info) {
+ kleave(" = -ENOMEM");
+ kfree(rka);
+ return ERR_PTR(-ENOMEM);
+ }
/* see if the calling process is already servicing the key request of
* another process */
@@ -179,7 +186,7 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info)
}
rka->target_key = key_get(target);
- rka->callout_info = callout_info;
+ strcpy(rka->callout_info, callout_info);
/* allocate the auth key */
sprintf(desc, "%x", target->serial);
@@ -203,6 +210,7 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info)
auth_key_revoked:
up_read(&current->request_key_auth->sem);
+ kfree(rka->callout_info);
kfree(rka);
kleave("= -EKEYREVOKED");
return ERR_PTR(-EKEYREVOKED);
@@ -212,6 +220,7 @@ error_inst:
key_put(authkey);
error_alloc:
key_put(rka->target_key);
+ kfree(rka->callout_info);
kfree(rka);
kleave("= %d", ret);
return ERR_PTR(ret);
diff --git a/security/root_plug.c b/security/root_plug.c
index 38dd4f3e641f..870f13095bb6 100644
--- a/security/root_plug.c
+++ b/security/root_plug.c
@@ -22,11 +22,11 @@
* License.
*/
-#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/security.h>
#include <linux/usb.h>
+#include <linux/moduleparam.h>
/* flag to keep track of how we were registered */
static int secondary;
@@ -36,22 +36,14 @@ static int vendor_id = 0x0557;
static int product_id = 0x2008;
module_param(vendor_id, uint, 0400);
-MODULE_PARM_DESC(vendor_id, "USB Vendor ID of device to look for");
-
module_param(product_id, uint, 0400);
-MODULE_PARM_DESC(product_id, "USB Product ID of device to look for");
/* should we print out debug messages */
static int debug = 0;
module_param(debug, bool, 0600);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
-#if defined(CONFIG_SECURITY_ROOTPLUG_MODULE)
-#define MY_NAME THIS_MODULE->name
-#else
#define MY_NAME "root_plug"
-#endif
#define root_dbg(fmt, arg...) \
do { \
@@ -117,25 +109,4 @@ static int __init rootplug_init (void)
return 0;
}
-static void __exit rootplug_exit (void)
-{
- /* remove ourselves from the security framework */
- if (secondary) {
- if (mod_unreg_security (MY_NAME, &rootplug_security_ops))
- printk (KERN_INFO "Failure unregistering Root Plug "
- " module with primary module.\n");
- } else {
- if (unregister_security (&rootplug_security_ops)) {
- printk (KERN_INFO "Failure unregistering Root Plug "
- "module with the kernel\n");
- }
- }
- printk (KERN_INFO "Root Plug module removed\n");
-}
-
security_initcall (rootplug_init);
-module_exit (rootplug_exit);
-
-MODULE_DESCRIPTION("Root Plug sample LSM module, written for Linux Journal article");
-MODULE_LICENSE("GPL");
-
diff --git a/security/security.c b/security/security.c
index 27e5863d30f1..0e1f1f124368 100644
--- a/security/security.c
+++ b/security/security.c
@@ -17,7 +17,6 @@
#include <linux/kernel.h>
#include <linux/security.h>
-#define SECURITY_FRAMEWORK_VERSION "1.0.0"
/* things that live in dummy.c */
extern struct security_operations dummy_security_ops;
@@ -52,8 +51,7 @@ static void __init do_security_initcalls(void)
*/
int __init security_init(void)
{
- printk(KERN_INFO "Security Framework v" SECURITY_FRAMEWORK_VERSION
- " initialized\n");
+ printk(KERN_INFO "Security Framework initialized\n");
if (verify(&dummy_security_ops)) {
printk(KERN_ERR "%s could not verify "
@@ -73,8 +71,7 @@ int __init security_init(void)
*
* This function is to allow a security module to register itself with the
* kernel security subsystem. Some rudimentary checking is done on the @ops
- * value passed to this function. A call to unregister_security() should be
- * done to remove this security_options structure from the kernel.
+ * value passed to this function.
*
* If there is already a security module registered with the kernel,
* an error will be returned. Otherwise 0 is returned on success.
@@ -96,31 +93,6 @@ int register_security(struct security_operations *ops)
}
/**
- * unregister_security - unregisters a security framework with the kernel
- * @ops: a pointer to the struct security_options that is to be registered
- *
- * This function removes a struct security_operations variable that had
- * previously been registered with a successful call to register_security().
- *
- * If @ops does not match the valued previously passed to register_security()
- * an error is returned. Otherwise the default security options is set to the
- * the dummy_security_ops structure, and 0 is returned.
- */
-int unregister_security(struct security_operations *ops)
-{
- if (ops != security_ops) {
- printk(KERN_INFO "%s: trying to unregister "
- "a security_opts structure that is not "
- "registered, failing.\n", __FUNCTION__);
- return -EINVAL;
- }
-
- security_ops = &dummy_security_ops;
-
- return 0;
-}
-
-/**
* mod_reg_security - allows security modules to be "stacked"
* @name: a pointer to a string with the name of the security_options to be registered
* @ops: a pointer to the struct security_options that is to be registered
@@ -149,32 +121,962 @@ int mod_reg_security(const char *name, struct security_operations *ops)
return security_ops->register_security(name, ops);
}
-/**
- * mod_unreg_security - allows a security module registered with mod_reg_security() to be unloaded
- * @name: a pointer to a string with the name of the security_options to be removed
- * @ops: a pointer to the struct security_options that is to be removed
- *
- * This function allows security modules that have been successfully registered
- * with a call to mod_reg_security() to be unloaded from the system.
- * This calls the currently loaded security module's unregister_security() call
- * with the @name and @ops variables.
- *
- * The return value depends on the currently loaded security module, with 0 as
- * success.
- */
-int mod_unreg_security(const char *name, struct security_operations *ops)
+/* Security operations */
+
+int security_ptrace(struct task_struct *parent, struct task_struct *child)
{
- if (ops == security_ops) {
- printk(KERN_INFO "%s invalid attempt to unregister "
- " primary security ops.\n", __FUNCTION__);
- return -EINVAL;
- }
+ return security_ops->ptrace(parent, child);
+}
+
+int security_capget(struct task_struct *target,
+ kernel_cap_t *effective,
+ kernel_cap_t *inheritable,
+ kernel_cap_t *permitted)
+{
+ return security_ops->capget(target, effective, inheritable, permitted);
+}
+
+int security_capset_check(struct task_struct *target,
+ kernel_cap_t *effective,
+ kernel_cap_t *inheritable,
+ kernel_cap_t *permitted)
+{
+ return security_ops->capset_check(target, effective, inheritable, permitted);
+}
+
+void security_capset_set(struct task_struct *target,
+ kernel_cap_t *effective,
+ kernel_cap_t *inheritable,
+ kernel_cap_t *permitted)
+{
+ security_ops->capset_set(target, effective, inheritable, permitted);
+}
+
+int security_capable(struct task_struct *tsk, int cap)
+{
+ return security_ops->capable(tsk, cap);
+}
+
+int security_acct(struct file *file)
+{
+ return security_ops->acct(file);
+}
+
+int security_sysctl(struct ctl_table *table, int op)
+{
+ return security_ops->sysctl(table, op);
+}
+
+int security_quotactl(int cmds, int type, int id, struct super_block *sb)
+{
+ return security_ops->quotactl(cmds, type, id, sb);
+}
+
+int security_quota_on(struct dentry *dentry)
+{
+ return security_ops->quota_on(dentry);
+}
+
+int security_syslog(int type)
+{
+ return security_ops->syslog(type);
+}
+
+int security_settime(struct timespec *ts, struct timezone *tz)
+{
+ return security_ops->settime(ts, tz);
+}
+
+int security_vm_enough_memory(long pages)
+{
+ return security_ops->vm_enough_memory(current->mm, pages);
+}
+
+int security_vm_enough_memory_mm(struct mm_struct *mm, long pages)
+{
+ return security_ops->vm_enough_memory(mm, pages);
+}
+
+int security_bprm_alloc(struct linux_binprm *bprm)
+{
+ return security_ops->bprm_alloc_security(bprm);
+}
+
+void security_bprm_free(struct linux_binprm *bprm)
+{
+ security_ops->bprm_free_security(bprm);
+}
+
+void security_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
+{
+ security_ops->bprm_apply_creds(bprm, unsafe);
+}
+
+void security_bprm_post_apply_creds(struct linux_binprm *bprm)
+{
+ security_ops->bprm_post_apply_creds(bprm);
+}
+
+int security_bprm_set(struct linux_binprm *bprm)
+{
+ return security_ops->bprm_set_security(bprm);
+}
+
+int security_bprm_check(struct linux_binprm *bprm)
+{
+ return security_ops->bprm_check_security(bprm);
+}
+
+int security_bprm_secureexec(struct linux_binprm *bprm)
+{
+ return security_ops->bprm_secureexec(bprm);
+}
+
+int security_sb_alloc(struct super_block *sb)
+{
+ return security_ops->sb_alloc_security(sb);
+}
+
+void security_sb_free(struct super_block *sb)
+{
+ security_ops->sb_free_security(sb);
+}
+
+int security_sb_copy_data(struct file_system_type *type, void *orig, void *copy)
+{
+ return security_ops->sb_copy_data(type, orig, copy);
+}
+
+int security_sb_kern_mount(struct super_block *sb, void *data)
+{
+ return security_ops->sb_kern_mount(sb, data);
+}
+
+int security_sb_statfs(struct dentry *dentry)
+{
+ return security_ops->sb_statfs(dentry);
+}
+
+int security_sb_mount(char *dev_name, struct nameidata *nd,
+ char *type, unsigned long flags, void *data)
+{
+ return security_ops->sb_mount(dev_name, nd, type, flags, data);
+}
+
+int security_sb_check_sb(struct vfsmount *mnt, struct nameidata *nd)
+{
+ return security_ops->sb_check_sb(mnt, nd);
+}
+
+int security_sb_umount(struct vfsmount *mnt, int flags)
+{
+ return security_ops->sb_umount(mnt, flags);
+}
+
+void security_sb_umount_close(struct vfsmount *mnt)
+{
+ security_ops->sb_umount_close(mnt);
+}
+
+void security_sb_umount_busy(struct vfsmount *mnt)
+{
+ security_ops->sb_umount_busy(mnt);
+}
+
+void security_sb_post_remount(struct vfsmount *mnt, unsigned long flags, void *data)
+{
+ security_ops->sb_post_remount(mnt, flags, data);
+}
+
+void security_sb_post_mountroot(void)
+{
+ security_ops->sb_post_mountroot();
+}
+
+void security_sb_post_addmount(struct vfsmount *mnt, struct nameidata *mountpoint_nd)
+{
+ security_ops->sb_post_addmount(mnt, mountpoint_nd);
+}
+
+int security_sb_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd)
+{
+ return security_ops->sb_pivotroot(old_nd, new_nd);
+}
+
+void security_sb_post_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd)
+{
+ security_ops->sb_post_pivotroot(old_nd, new_nd);
+}
+
+int security_inode_alloc(struct inode *inode)
+{
+ inode->i_security = NULL;
+ return security_ops->inode_alloc_security(inode);
+}
+
+void security_inode_free(struct inode *inode)
+{
+ security_ops->inode_free_security(inode);
+}
+
+int security_inode_init_security(struct inode *inode, struct inode *dir,
+ char **name, void **value, size_t *len)
+{
+ if (unlikely(IS_PRIVATE(inode)))
+ return -EOPNOTSUPP;
+ return security_ops->inode_init_security(inode, dir, name, value, len);
+}
+EXPORT_SYMBOL(security_inode_init_security);
+
+int security_inode_create(struct inode *dir, struct dentry *dentry, int mode)
+{
+ if (unlikely(IS_PRIVATE(dir)))
+ return 0;
+ return security_ops->inode_create(dir, dentry, mode);
+}
+
+int security_inode_link(struct dentry *old_dentry, struct inode *dir,
+ struct dentry *new_dentry)
+{
+ if (unlikely(IS_PRIVATE(old_dentry->d_inode)))
+ return 0;
+ return security_ops->inode_link(old_dentry, dir, new_dentry);
+}
+
+int security_inode_unlink(struct inode *dir, struct dentry *dentry)
+{
+ if (unlikely(IS_PRIVATE(dentry->d_inode)))
+ return 0;
+ return security_ops->inode_unlink(dir, dentry);
+}
+
+int security_inode_symlink(struct inode *dir, struct dentry *dentry,
+ const char *old_name)
+{
+ if (unlikely(IS_PRIVATE(dir)))
+ return 0;
+ return security_ops->inode_symlink(dir, dentry, old_name);
+}
+
+int security_inode_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+{
+ if (unlikely(IS_PRIVATE(dir)))
+ return 0;
+ return security_ops->inode_mkdir(dir, dentry, mode);
+}
+
+int security_inode_rmdir(struct inode *dir, struct dentry *dentry)
+{
+ if (unlikely(IS_PRIVATE(dentry->d_inode)))
+ return 0;
+ return security_ops->inode_rmdir(dir, dentry);
+}
+
+int security_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
+{
+ if (unlikely(IS_PRIVATE(dir)))
+ return 0;
+ return security_ops->inode_mknod(dir, dentry, mode, dev);
+}
+
+int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry)
+{
+ if (unlikely(IS_PRIVATE(old_dentry->d_inode) ||
+ (new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode))))
+ return 0;
+ return security_ops->inode_rename(old_dir, old_dentry,
+ new_dir, new_dentry);
+}
+
+int security_inode_readlink(struct dentry *dentry)
+{
+ if (unlikely(IS_PRIVATE(dentry->d_inode)))
+ return 0;
+ return security_ops->inode_readlink(dentry);
+}
+
+int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+ if (unlikely(IS_PRIVATE(dentry->d_inode)))
+ return 0;
+ return security_ops->inode_follow_link(dentry, nd);
+}
+
+int security_inode_permission(struct inode *inode, int mask, struct nameidata *nd)
+{
+ if (unlikely(IS_PRIVATE(inode)))
+ return 0;
+ return security_ops->inode_permission(inode, mask, nd);
+}
+
+int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
+{
+ if (unlikely(IS_PRIVATE(dentry->d_inode)))
+ return 0;
+ return security_ops->inode_setattr(dentry, attr);
+}
+
+int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
+{
+ if (unlikely(IS_PRIVATE(dentry->d_inode)))
+ return 0;
+ return security_ops->inode_getattr(mnt, dentry);
+}
+
+void security_inode_delete(struct inode *inode)
+{
+ if (unlikely(IS_PRIVATE(inode)))
+ return;
+ security_ops->inode_delete(inode);
+}
+
+int security_inode_setxattr(struct dentry *dentry, char *name,
+ void *value, size_t size, int flags)
+{
+ if (unlikely(IS_PRIVATE(dentry->d_inode)))
+ return 0;
+ return security_ops->inode_setxattr(dentry, name, value, size, flags);
+}
+
+void security_inode_post_setxattr(struct dentry *dentry, char *name,
+ void *value, size_t size, int flags)
+{
+ if (unlikely(IS_PRIVATE(dentry->d_inode)))
+ return;
+ security_ops->inode_post_setxattr(dentry, name, value, size, flags);
+}
+
+int security_inode_getxattr(struct dentry *dentry, char *name)
+{
+ if (unlikely(IS_PRIVATE(dentry->d_inode)))
+ return 0;
+ return security_ops->inode_getxattr(dentry, name);
+}
+
+int security_inode_listxattr(struct dentry *dentry)
+{
+ if (unlikely(IS_PRIVATE(dentry->d_inode)))
+ return 0;
+ return security_ops->inode_listxattr(dentry);
+}
+
+int security_inode_removexattr(struct dentry *dentry, char *name)
+{
+ if (unlikely(IS_PRIVATE(dentry->d_inode)))
+ return 0;
+ return security_ops->inode_removexattr(dentry, name);
+}
+
+int security_inode_need_killpriv(struct dentry *dentry)
+{
+ return security_ops->inode_need_killpriv(dentry);
+}
+
+int security_inode_killpriv(struct dentry *dentry)
+{
+ return security_ops->inode_killpriv(dentry);
+}
+
+int security_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
+{
+ if (unlikely(IS_PRIVATE(inode)))
+ return 0;
+ return security_ops->inode_getsecurity(inode, name, buffer, size, err);
+}
+
+int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags)
+{
+ if (unlikely(IS_PRIVATE(inode)))
+ return 0;
+ return security_ops->inode_setsecurity(inode, name, value, size, flags);
+}
+
+int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
+{
+ if (unlikely(IS_PRIVATE(inode)))
+ return 0;
+ return security_ops->inode_listsecurity(inode, buffer, buffer_size);
+}
+
+int security_file_permission(struct file *file, int mask)
+{
+ return security_ops->file_permission(file, mask);
+}
+
+int security_file_alloc(struct file *file)
+{
+ return security_ops->file_alloc_security(file);
+}
+
+void security_file_free(struct file *file)
+{
+ security_ops->file_free_security(file);
+}
+
+int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ return security_ops->file_ioctl(file, cmd, arg);
+}
+
+int security_file_mmap(struct file *file, unsigned long reqprot,
+ unsigned long prot, unsigned long flags,
+ unsigned long addr, unsigned long addr_only)
+{
+ return security_ops->file_mmap(file, reqprot, prot, flags, addr, addr_only);
+}
+
+int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
+ unsigned long prot)
+{
+ return security_ops->file_mprotect(vma, reqprot, prot);
+}
+
+int security_file_lock(struct file *file, unsigned int cmd)
+{
+ return security_ops->file_lock(file, cmd);
+}
+
+int security_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ return security_ops->file_fcntl(file, cmd, arg);
+}
+
+int security_file_set_fowner(struct file *file)
+{
+ return security_ops->file_set_fowner(file);
+}
+
+int security_file_send_sigiotask(struct task_struct *tsk,
+ struct fown_struct *fown, int sig)
+{
+ return security_ops->file_send_sigiotask(tsk, fown, sig);
+}
+
+int security_file_receive(struct file *file)
+{
+ return security_ops->file_receive(file);
+}
+
+int security_dentry_open(struct file *file)
+{
+ return security_ops->dentry_open(file);
+}
+
+int security_task_create(unsigned long clone_flags)
+{
+ return security_ops->task_create(clone_flags);
+}
+
+int security_task_alloc(struct task_struct *p)
+{
+ return security_ops->task_alloc_security(p);
+}
+
+void security_task_free(struct task_struct *p)
+{
+ security_ops->task_free_security(p);
+}
+
+int security_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
+{
+ return security_ops->task_setuid(id0, id1, id2, flags);
+}
+
+int security_task_post_setuid(uid_t old_ruid, uid_t old_euid,
+ uid_t old_suid, int flags)
+{
+ return security_ops->task_post_setuid(old_ruid, old_euid, old_suid, flags);
+}
+
+int security_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags)
+{
+ return security_ops->task_setgid(id0, id1, id2, flags);
+}
- return security_ops->unregister_security(name, ops);
+int security_task_setpgid(struct task_struct *p, pid_t pgid)
+{
+ return security_ops->task_setpgid(p, pgid);
+}
+
+int security_task_getpgid(struct task_struct *p)
+{
+ return security_ops->task_getpgid(p);
+}
+
+int security_task_getsid(struct task_struct *p)
+{
+ return security_ops->task_getsid(p);
+}
+
+void security_task_getsecid(struct task_struct *p, u32 *secid)
+{
+ security_ops->task_getsecid(p, secid);
+}
+EXPORT_SYMBOL(security_task_getsecid);
+
+int security_task_setgroups(struct group_info *group_info)
+{
+ return security_ops->task_setgroups(group_info);
+}
+
+int security_task_setnice(struct task_struct *p, int nice)
+{
+ return security_ops->task_setnice(p, nice);
+}
+
+int security_task_setioprio(struct task_struct *p, int ioprio)
+{
+ return security_ops->task_setioprio(p, ioprio);
+}
+
+int security_task_getioprio(struct task_struct *p)
+{
+ return security_ops->task_getioprio(p);
+}
+
+int security_task_setrlimit(unsigned int resource, struct rlimit *new_rlim)
+{
+ return security_ops->task_setrlimit(resource, new_rlim);
+}
+
+int security_task_setscheduler(struct task_struct *p,
+ int policy, struct sched_param *lp)
+{
+ return security_ops->task_setscheduler(p, policy, lp);
+}
+
+int security_task_getscheduler(struct task_struct *p)
+{
+ return security_ops->task_getscheduler(p);
+}
+
+int security_task_movememory(struct task_struct *p)
+{
+ return security_ops->task_movememory(p);
+}
+
+int security_task_kill(struct task_struct *p, struct siginfo *info,
+ int sig, u32 secid)
+{
+ return security_ops->task_kill(p, info, sig, secid);
+}
+
+int security_task_wait(struct task_struct *p)
+{
+ return security_ops->task_wait(p);
+}
+
+int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
+ unsigned long arg4, unsigned long arg5)
+{
+ return security_ops->task_prctl(option, arg2, arg3, arg4, arg5);
+}
+
+void security_task_reparent_to_init(struct task_struct *p)
+{
+ security_ops->task_reparent_to_init(p);
+}
+
+void security_task_to_inode(struct task_struct *p, struct inode *inode)
+{
+ security_ops->task_to_inode(p, inode);
+}
+
+int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
+{
+ return security_ops->ipc_permission(ipcp, flag);
+}
+
+int security_msg_msg_alloc(struct msg_msg *msg)
+{
+ return security_ops->msg_msg_alloc_security(msg);
+}
+
+void security_msg_msg_free(struct msg_msg *msg)
+{
+ security_ops->msg_msg_free_security(msg);
+}
+
+int security_msg_queue_alloc(struct msg_queue *msq)
+{
+ return security_ops->msg_queue_alloc_security(msq);
+}
+
+void security_msg_queue_free(struct msg_queue *msq)
+{
+ security_ops->msg_queue_free_security(msq);
+}
+
+int security_msg_queue_associate(struct msg_queue *msq, int msqflg)
+{
+ return security_ops->msg_queue_associate(msq, msqflg);
+}
+
+int security_msg_queue_msgctl(struct msg_queue *msq, int cmd)
+{
+ return security_ops->msg_queue_msgctl(msq, cmd);
+}
+
+int security_msg_queue_msgsnd(struct msg_queue *msq,
+ struct msg_msg *msg, int msqflg)
+{
+ return security_ops->msg_queue_msgsnd(msq, msg, msqflg);
+}
+
+int security_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
+ struct task_struct *target, long type, int mode)
+{
+ return security_ops->msg_queue_msgrcv(msq, msg, target, type, mode);
+}
+
+int security_shm_alloc(struct shmid_kernel *shp)
+{
+ return security_ops->shm_alloc_security(shp);
+}
+
+void security_shm_free(struct shmid_kernel *shp)
+{
+ security_ops->shm_free_security(shp);
+}
+
+int security_shm_associate(struct shmid_kernel *shp, int shmflg)
+{
+ return security_ops->shm_associate(shp, shmflg);
+}
+
+int security_shm_shmctl(struct shmid_kernel *shp, int cmd)
+{
+ return security_ops->shm_shmctl(shp, cmd);
+}
+
+int security_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr, int shmflg)
+{
+ return security_ops->shm_shmat(shp, shmaddr, shmflg);
+}
+
+int security_sem_alloc(struct sem_array *sma)
+{
+ return security_ops->sem_alloc_security(sma);
+}
+
+void security_sem_free(struct sem_array *sma)
+{
+ security_ops->sem_free_security(sma);
+}
+
+int security_sem_associate(struct sem_array *sma, int semflg)
+{
+ return security_ops->sem_associate(sma, semflg);
+}
+
+int security_sem_semctl(struct sem_array *sma, int cmd)
+{
+ return security_ops->sem_semctl(sma, cmd);
+}
+
+int security_sem_semop(struct sem_array *sma, struct sembuf *sops,
+ unsigned nsops, int alter)
+{
+ return security_ops->sem_semop(sma, sops, nsops, alter);
+}
+
+void security_d_instantiate(struct dentry *dentry, struct inode *inode)
+{
+ if (unlikely(inode && IS_PRIVATE(inode)))
+ return;
+ security_ops->d_instantiate(dentry, inode);
+}
+EXPORT_SYMBOL(security_d_instantiate);
+
+int security_getprocattr(struct task_struct *p, char *name, char **value)
+{
+ return security_ops->getprocattr(p, name, value);
+}
+
+int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size)
+{
+ return security_ops->setprocattr(p, name, value, size);
+}
+
+int security_netlink_send(struct sock *sk, struct sk_buff *skb)
+{
+ return security_ops->netlink_send(sk, skb);
+}
+
+int security_netlink_recv(struct sk_buff *skb, int cap)
+{
+ return security_ops->netlink_recv(skb, cap);
+}
+EXPORT_SYMBOL(security_netlink_recv);
+
+int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
+{
+ return security_ops->secid_to_secctx(secid, secdata, seclen);
+}
+EXPORT_SYMBOL(security_secid_to_secctx);
+
+void security_release_secctx(char *secdata, u32 seclen)
+{
+ return security_ops->release_secctx(secdata, seclen);
+}
+EXPORT_SYMBOL(security_release_secctx);
+
+#ifdef CONFIG_SECURITY_NETWORK
+
+int security_unix_stream_connect(struct socket *sock, struct socket *other,
+ struct sock *newsk)
+{
+ return security_ops->unix_stream_connect(sock, other, newsk);
+}
+EXPORT_SYMBOL(security_unix_stream_connect);
+
+int security_unix_may_send(struct socket *sock, struct socket *other)
+{
+ return security_ops->unix_may_send(sock, other);
+}
+EXPORT_SYMBOL(security_unix_may_send);
+
+int security_socket_create(int family, int type, int protocol, int kern)
+{
+ return security_ops->socket_create(family, type, protocol, kern);
+}
+
+int security_socket_post_create(struct socket *sock, int family,
+ int type, int protocol, int kern)
+{
+ return security_ops->socket_post_create(sock, family, type,
+ protocol, kern);
+}
+
+int security_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
+{
+ return security_ops->socket_bind(sock, address, addrlen);
+}
+
+int security_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
+{
+ return security_ops->socket_connect(sock, address, addrlen);
+}
+
+int security_socket_listen(struct socket *sock, int backlog)
+{
+ return security_ops->socket_listen(sock, backlog);
+}
+
+int security_socket_accept(struct socket *sock, struct socket *newsock)
+{
+ return security_ops->socket_accept(sock, newsock);
+}
+
+void security_socket_post_accept(struct socket *sock, struct socket *newsock)
+{
+ security_ops->socket_post_accept(sock, newsock);
+}
+
+int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size)
+{
+ return security_ops->socket_sendmsg(sock, msg, size);
+}
+
+int security_socket_recvmsg(struct socket *sock, struct msghdr *msg,
+ int size, int flags)
+{
+ return security_ops->socket_recvmsg(sock, msg, size, flags);
+}
+
+int security_socket_getsockname(struct socket *sock)
+{
+ return security_ops->socket_getsockname(sock);
+}
+
+int security_socket_getpeername(struct socket *sock)
+{
+ return security_ops->socket_getpeername(sock);
+}
+
+int security_socket_getsockopt(struct socket *sock, int level, int optname)
+{
+ return security_ops->socket_getsockopt(sock, level, optname);
+}
+
+int security_socket_setsockopt(struct socket *sock, int level, int optname)
+{
+ return security_ops->socket_setsockopt(sock, level, optname);
+}
+
+int security_socket_shutdown(struct socket *sock, int how)
+{
+ return security_ops->socket_shutdown(sock, how);
+}
+
+int security_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
+{
+ return security_ops->socket_sock_rcv_skb(sk, skb);
+}
+EXPORT_SYMBOL(security_sock_rcv_skb);
+
+int security_socket_getpeersec_stream(struct socket *sock, char __user *optval,
+ int __user *optlen, unsigned len)
+{
+ return security_ops->socket_getpeersec_stream(sock, optval, optlen, len);
+}
+
+int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
+{
+ return security_ops->socket_getpeersec_dgram(sock, skb, secid);
+}
+EXPORT_SYMBOL(security_socket_getpeersec_dgram);
+
+int security_sk_alloc(struct sock *sk, int family, gfp_t priority)
+{
+ return security_ops->sk_alloc_security(sk, family, priority);
+}
+
+void security_sk_free(struct sock *sk)
+{
+ return security_ops->sk_free_security(sk);
+}
+
+void security_sk_clone(const struct sock *sk, struct sock *newsk)
+{
+ return security_ops->sk_clone_security(sk, newsk);
+}
+
+void security_sk_classify_flow(struct sock *sk, struct flowi *fl)
+{
+ security_ops->sk_getsecid(sk, &fl->secid);
+}
+EXPORT_SYMBOL(security_sk_classify_flow);
+
+void security_req_classify_flow(const struct request_sock *req, struct flowi *fl)
+{
+ security_ops->req_classify_flow(req, fl);
+}
+EXPORT_SYMBOL(security_req_classify_flow);
+
+void security_sock_graft(struct sock *sk, struct socket *parent)
+{
+ security_ops->sock_graft(sk, parent);
+}
+EXPORT_SYMBOL(security_sock_graft);
+
+int security_inet_conn_request(struct sock *sk,
+ struct sk_buff *skb, struct request_sock *req)
+{
+ return security_ops->inet_conn_request(sk, skb, req);
+}
+EXPORT_SYMBOL(security_inet_conn_request);
+
+void security_inet_csk_clone(struct sock *newsk,
+ const struct request_sock *req)
+{
+ security_ops->inet_csk_clone(newsk, req);
+}
+
+void security_inet_conn_established(struct sock *sk,
+ struct sk_buff *skb)
+{
+ security_ops->inet_conn_established(sk, skb);
+}
+
+#endif /* CONFIG_SECURITY_NETWORK */
+
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+
+int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx)
+{
+ return security_ops->xfrm_policy_alloc_security(xp, sec_ctx);
+}
+EXPORT_SYMBOL(security_xfrm_policy_alloc);
+
+int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new)
+{
+ return security_ops->xfrm_policy_clone_security(old, new);
+}
+
+void security_xfrm_policy_free(struct xfrm_policy *xp)
+{
+ security_ops->xfrm_policy_free_security(xp);
+}
+EXPORT_SYMBOL(security_xfrm_policy_free);
+
+int security_xfrm_policy_delete(struct xfrm_policy *xp)
+{
+ return security_ops->xfrm_policy_delete_security(xp);
+}
+
+int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx)
+{
+ return security_ops->xfrm_state_alloc_security(x, sec_ctx, 0);
+}
+EXPORT_SYMBOL(security_xfrm_state_alloc);
+
+int security_xfrm_state_alloc_acquire(struct xfrm_state *x,
+ struct xfrm_sec_ctx *polsec, u32 secid)
+{
+ if (!polsec)
+ return 0;
+ /*
+ * We want the context to be taken from secid which is usually
+ * from the sock.
+ */
+ return security_ops->xfrm_state_alloc_security(x, NULL, secid);
+}
+
+int security_xfrm_state_delete(struct xfrm_state *x)
+{
+ return security_ops->xfrm_state_delete_security(x);
+}
+EXPORT_SYMBOL(security_xfrm_state_delete);
+
+void security_xfrm_state_free(struct xfrm_state *x)
+{
+ security_ops->xfrm_state_free_security(x);
+}
+
+int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir)
+{
+ return security_ops->xfrm_policy_lookup(xp, fl_secid, dir);
+}
+
+int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
+ struct xfrm_policy *xp, struct flowi *fl)
+{
+ return security_ops->xfrm_state_pol_flow_match(x, xp, fl);
+}
+
+int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid)
+{
+ return security_ops->xfrm_decode_session(skb, secid, 1);
+}
+
+void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl)
+{
+ int rc = security_ops->xfrm_decode_session(skb, &fl->secid, 0);
+
+ BUG_ON(rc);
+}
+EXPORT_SYMBOL(security_skb_classify_flow);
+
+#endif /* CONFIG_SECURITY_NETWORK_XFRM */
+
+#ifdef CONFIG_KEYS
+
+int security_key_alloc(struct key *key, struct task_struct *tsk, unsigned long flags)
+{
+ return security_ops->key_alloc(key, tsk, flags);
+}
+
+void security_key_free(struct key *key)
+{
+ security_ops->key_free(key);
+}
+
+int security_key_permission(key_ref_t key_ref,
+ struct task_struct *context, key_perm_t perm)
+{
+ return security_ops->key_permission(key_ref, context, perm);
}
-EXPORT_SYMBOL_GPL(register_security);
-EXPORT_SYMBOL_GPL(unregister_security);
-EXPORT_SYMBOL_GPL(mod_reg_security);
-EXPORT_SYMBOL_GPL(mod_unreg_security);
-EXPORT_SYMBOL(security_ops);
+#endif /* CONFIG_KEYS */
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 0e69adf63bdb..81b3dff3cbf0 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -916,3 +916,8 @@ int avc_has_perm(u32 ssid, u32 tsid, u16 tclass,
avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata);
return rc;
}
+
+u32 avc_policy_seqno(void)
+{
+ return avc_cache.latest_notif;
+}
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 3c3fff33d1ce..9f3124b08867 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -14,13 +14,14 @@
* <dgoeddel@trustedcs.com>
* Copyright (C) 2006 Hewlett-Packard Development Company, L.P.
* Paul Moore, <paul.moore@hp.com>
+ * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
+ * Yuichi Nakamura <ynakam@hitachisoft.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*/
-#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/ptrace.h>
@@ -84,6 +85,7 @@
extern unsigned int policydb_loaded_version;
extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
extern int selinux_compat_net;
+extern struct security_operations *security_ops;
#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
int selinux_enforcing = 0;
@@ -2295,6 +2297,25 @@ static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
return dentry_has_perm(current, mnt, dentry, FILE__GETATTR);
}
+static int selinux_inode_setotherxattr(struct dentry *dentry, char *name)
+{
+ if (!strncmp(name, XATTR_SECURITY_PREFIX,
+ sizeof XATTR_SECURITY_PREFIX - 1)) {
+ if (!strcmp(name, XATTR_NAME_CAPS)) {
+ if (!capable(CAP_SETFCAP))
+ return -EPERM;
+ } else if (!capable(CAP_SYS_ADMIN)) {
+ /* A different attribute in the security namespace.
+ Restrict to administrator. */
+ return -EPERM;
+ }
+ }
+
+ /* Not an attribute we recognize, so just check the
+ ordinary setattr permission. */
+ return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
+}
+
static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags)
{
struct task_security_struct *tsec = current->security;
@@ -2305,19 +2326,8 @@ static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value
u32 newsid;
int rc = 0;
- if (strcmp(name, XATTR_NAME_SELINUX)) {
- if (!strncmp(name, XATTR_SECURITY_PREFIX,
- sizeof XATTR_SECURITY_PREFIX - 1) &&
- !capable(CAP_SYS_ADMIN)) {
- /* A different attribute in the security namespace.
- Restrict to administrator. */
- return -EPERM;
- }
-
- /* Not an attribute we recognize, so just check the
- ordinary setattr permission. */
- return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
- }
+ if (strcmp(name, XATTR_NAME_SELINUX))
+ return selinux_inode_setotherxattr(dentry, name);
sbsec = inode->i_sb->s_security;
if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
@@ -2391,31 +2401,14 @@ static int selinux_inode_listxattr (struct dentry *dentry)
static int selinux_inode_removexattr (struct dentry *dentry, char *name)
{
- if (strcmp(name, XATTR_NAME_SELINUX)) {
- if (!strncmp(name, XATTR_SECURITY_PREFIX,
- sizeof XATTR_SECURITY_PREFIX - 1) &&
- !capable(CAP_SYS_ADMIN)) {
- /* A different attribute in the security namespace.
- Restrict to administrator. */
- return -EPERM;
- }
-
- /* Not an attribute we recognize, so just check the
- ordinary setattr permission. Might want a separate
- permission for removexattr. */
- return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
- }
+ if (strcmp(name, XATTR_NAME_SELINUX))
+ return selinux_inode_setotherxattr(dentry, name);
/* No one is allowed to remove a SELinux security label.
You can change the label, but all data must be labeled. */
return -EACCES;
}
-static const char *selinux_inode_xattr_getsuffix(void)
-{
- return XATTR_SELINUX_SUFFIX;
-}
-
/*
* Copy the in-core inode security context value to the user. If the
* getxattr() prior to this succeeded, check to see if we need to
@@ -2462,9 +2455,19 @@ static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t
return len;
}
+static int selinux_inode_need_killpriv(struct dentry *dentry)
+{
+ return secondary_ops->inode_need_killpriv(dentry);
+}
+
+static int selinux_inode_killpriv(struct dentry *dentry)
+{
+ return secondary_ops->inode_killpriv(dentry);
+}
+
/* file security operations */
-static int selinux_file_permission(struct file *file, int mask)
+static int selinux_revalidate_file_permission(struct file *file, int mask)
{
int rc;
struct inode *inode = file->f_path.dentry->d_inode;
@@ -2486,6 +2489,25 @@ static int selinux_file_permission(struct file *file, int mask)
return selinux_netlbl_inode_permission(inode, mask);
}
+static int selinux_file_permission(struct file *file, int mask)
+{
+ struct inode *inode = file->f_path.dentry->d_inode;
+ struct task_security_struct *tsec = current->security;
+ struct file_security_struct *fsec = file->f_security;
+ struct inode_security_struct *isec = inode->i_security;
+
+ if (!mask) {
+ /* No permission to check. Existence test. */
+ return 0;
+ }
+
+ if (tsec->sid == fsec->sid && fsec->isid == isec->sid
+ && fsec->pseqno == avc_policy_seqno())
+ return selinux_netlbl_inode_permission(inode, mask);
+
+ return selinux_revalidate_file_permission(file, mask);
+}
+
static int selinux_file_alloc_security(struct file *file)
{
return file_alloc_security(file);
@@ -2725,6 +2747,34 @@ static int selinux_file_receive(struct file *file)
return file_has_perm(current, file, file_to_av(file));
}
+static int selinux_dentry_open(struct file *file)
+{
+ struct file_security_struct *fsec;
+ struct inode *inode;
+ struct inode_security_struct *isec;
+ inode = file->f_path.dentry->d_inode;
+ fsec = file->f_security;
+ isec = inode->i_security;
+ /*
+ * Save inode label and policy sequence number
+ * at open-time so that selinux_file_permission
+ * can determine whether revalidation is necessary.
+ * Task label is already saved in the file security
+ * struct as its SID.
+ */
+ fsec->isid = isec->sid;
+ fsec->pseqno = avc_policy_seqno();
+ /*
+ * Since the inode label or policy seqno may have changed
+ * between the selinux_inode_permission check and the saving
+ * of state above, recheck that access is still permitted.
+ * Otherwise, access might never be revalidated against the
+ * new inode label or new policy.
+ * This check is not redundant - do not remove.
+ */
+ return inode_has_perm(current, inode, file_to_av(file), NULL);
+}
+
/* task security operations */
static int selinux_task_create(unsigned long clone_flags)
@@ -2833,6 +2883,12 @@ static int selinux_task_setnice(struct task_struct *p, int nice)
static int selinux_task_setioprio(struct task_struct *p, int ioprio)
{
+ int rc;
+
+ rc = secondary_ops->task_setioprio(p, ioprio);
+ if (rc)
+ return rc;
+
return task_has_perm(current, p, PROCESS__SETSCHED);
}
@@ -2862,6 +2918,12 @@ static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim
static int selinux_task_setscheduler(struct task_struct *p, int policy, struct sched_param *lp)
{
+ int rc;
+
+ rc = secondary_ops->task_setscheduler(p, policy, lp);
+ if (rc)
+ return rc;
+
return task_has_perm(current, p, PROCESS__SETSCHED);
}
@@ -2915,11 +2977,7 @@ static int selinux_task_prctl(int option,
static int selinux_task_wait(struct task_struct *p)
{
- u32 perm;
-
- perm = signal_to_av(p->exit_signal);
-
- return task_has_perm(p, current, perm);
+ return task_has_perm(p, current, PROCESS__SIGCHLD);
}
static void selinux_task_reparent_to_init(struct task_struct *p)
@@ -3932,7 +3990,7 @@ out:
}
static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *),
@@ -3941,7 +3999,6 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
char *addrp;
int len, err = 0;
struct sock *sk;
- struct sk_buff *skb = *pskb;
struct avc_audit_data ad;
struct net_device *dev = (struct net_device *)out;
struct sk_security_struct *sksec;
@@ -3977,23 +4034,23 @@ out:
}
static unsigned int selinux_ipv4_postroute_last(unsigned int hooknum,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
- return selinux_ip_postroute_last(hooknum, pskb, in, out, okfn, PF_INET);
+ return selinux_ip_postroute_last(hooknum, skb, in, out, okfn, PF_INET);
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
static unsigned int selinux_ipv6_postroute_last(unsigned int hooknum,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
- return selinux_ip_postroute_last(hooknum, pskb, in, out, okfn, PF_INET6);
+ return selinux_ip_postroute_last(hooknum, skb, in, out, okfn, PF_INET6);
}
#endif /* IPV6 */
@@ -4488,19 +4545,6 @@ static int selinux_register_security (const char *name, struct security_operatio
return 0;
}
-static int selinux_unregister_security (const char *name, struct security_operations *ops)
-{
- if (ops != secondary_ops) {
- printk(KERN_ERR "%s: trying to unregister a security module "
- "that is not registered.\n", __FUNCTION__);
- return -EINVAL;
- }
-
- secondary_ops = original_ops;
-
- return 0;
-}
-
static void selinux_d_instantiate (struct dentry *dentry, struct inode *inode)
{
if (inode)
@@ -4778,10 +4822,11 @@ static struct security_operations selinux_ops = {
.inode_getxattr = selinux_inode_getxattr,
.inode_listxattr = selinux_inode_listxattr,
.inode_removexattr = selinux_inode_removexattr,
- .inode_xattr_getsuffix = selinux_inode_xattr_getsuffix,
.inode_getsecurity = selinux_inode_getsecurity,
.inode_setsecurity = selinux_inode_setsecurity,
.inode_listsecurity = selinux_inode_listsecurity,
+ .inode_need_killpriv = selinux_inode_need_killpriv,
+ .inode_killpriv = selinux_inode_killpriv,
.file_permission = selinux_file_permission,
.file_alloc_security = selinux_file_alloc_security,
@@ -4795,6 +4840,8 @@ static struct security_operations selinux_ops = {
.file_send_sigiotask = selinux_file_send_sigiotask,
.file_receive = selinux_file_receive,
+ .dentry_open = selinux_dentry_open,
+
.task_create = selinux_task_create,
.task_alloc_security = selinux_task_alloc_security,
.task_free_security = selinux_task_free_security,
@@ -4844,7 +4891,6 @@ static struct security_operations selinux_ops = {
.sem_semop = selinux_sem_semop,
.register_security = selinux_register_security,
- .unregister_security = selinux_unregister_security,
.d_instantiate = selinux_d_instantiate,
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h
index e145f6e13b0b..553607a19e92 100644
--- a/security/selinux/include/avc.h
+++ b/security/selinux/include/avc.h
@@ -112,6 +112,8 @@ int avc_has_perm(u32 ssid, u32 tsid,
u16 tclass, u32 requested,
struct avc_audit_data *auditdata);
+u32 avc_policy_seqno(void);
+
#define AVC_CALLBACK_GRANT 1
#define AVC_CALLBACK_TRY_REVOKE 2
#define AVC_CALLBACK_REVOKE 4
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index 91b88f0ba20c..642a9fd319ad 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -53,6 +53,8 @@ struct file_security_struct {
struct file *file; /* back pointer to file object */
u32 sid; /* SID of open file description */
u32 fown_sid; /* SID of file owner (for SIGIO) */
+ u32 isid; /* SID of inode at the time of file open */
+ u32 pseqno; /* Policy seqno at the time of file open */
};
struct superblock_security_struct {
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 83bdd4d2a29e..39337afffec2 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -90,6 +90,8 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid);
int security_get_classes(char ***classes, int *nclasses);
int security_get_permissions(char *class, char ***perms, int *nperms);
+int security_get_reject_unknown(void);
+int security_get_allow_unknown(void);
#define SECURITY_FS_USE_XATTR 1 /* use xattr */
#define SECURITY_FS_USE_TRANS 2 /* use transition SIDs, e.g. devpts/tmpfs */
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index c9e92daedee2..f5f3e6da5da7 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -103,6 +103,8 @@ enum sel_inos {
SEL_MEMBER, /* compute polyinstantiation membership decision */
SEL_CHECKREQPROT, /* check requested protection, not kernel-applied one */
SEL_COMPAT_NET, /* whether to use old compat network packet controls */
+ SEL_REJECT_UNKNOWN, /* export unknown reject handling to userspace */
+ SEL_DENY_UNKNOWN, /* export unknown deny handling to userspace */
SEL_INO_NEXT, /* The next inode number to use */
};
@@ -177,6 +179,23 @@ static const struct file_operations sel_enforce_ops = {
.write = sel_write_enforce,
};
+static ssize_t sel_read_handle_unknown(struct file *filp, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ char tmpbuf[TMPBUFLEN];
+ ssize_t length;
+ ino_t ino = filp->f_path.dentry->d_inode->i_ino;
+ int handle_unknown = (ino == SEL_REJECT_UNKNOWN) ?
+ security_get_reject_unknown() : !security_get_allow_unknown();
+
+ length = scnprintf(tmpbuf, TMPBUFLEN, "%d", handle_unknown);
+ return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
+}
+
+static const struct file_operations sel_handle_unknown_ops = {
+ .read = sel_read_handle_unknown,
+};
+
#ifdef CONFIG_SECURITY_SELINUX_DISABLE
static ssize_t sel_write_disable(struct file * file, const char __user * buf,
size_t count, loff_t *ppos)
@@ -309,6 +328,11 @@ static ssize_t sel_write_load(struct file * file, const char __user * buf,
length = count;
out1:
+
+ printk(KERN_INFO "SELinux: policy loaded with handle_unknown=%s\n",
+ (security_get_reject_unknown() ? "reject" :
+ (security_get_allow_unknown() ? "allow" : "deny")));
+
audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD,
"policy loaded auid=%u",
audit_get_loginuid(current->audit_context));
@@ -1575,6 +1599,8 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
[SEL_MEMBER] = {"member", &transaction_ops, S_IRUGO|S_IWUGO},
[SEL_CHECKREQPROT] = {"checkreqprot", &sel_checkreqprot_ops, S_IRUGO|S_IWUSR},
[SEL_COMPAT_NET] = {"compat_net", &sel_compat_net_ops, S_IRUGO|S_IWUSR},
+ [SEL_REJECT_UNKNOWN] = {"reject_unknown", &sel_handle_unknown_ops, S_IRUGO},
+ [SEL_DENY_UNKNOWN] = {"deny_unknown", &sel_handle_unknown_ops, S_IRUGO},
/* last one */ {""}
};
ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files);
diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c
index 85705eb289e0..9e70a160d7da 100644
--- a/security/selinux/ss/avtab.c
+++ b/security/selinux/ss/avtab.c
@@ -12,24 +12,25 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 2.
+ *
+ * Updated: Yuichi Nakamura <ynakam@hitachisoft.jp>
+ * Tuned number of hash slots for avtab to reduce memory usage
*/
#include <linux/kernel.h>
#include <linux/slab.h>
-#include <linux/vmalloc.h>
#include <linux/errno.h>
-
#include "avtab.h"
#include "policydb.h"
-#define AVTAB_HASH(keyp) \
-((keyp->target_class + \
- (keyp->target_type << 2) + \
- (keyp->source_type << 9)) & \
- AVTAB_HASH_MASK)
-
static struct kmem_cache *avtab_node_cachep;
+static inline int avtab_hash(struct avtab_key *keyp, u16 mask)
+{
+ return ((keyp->target_class + (keyp->target_type << 2) +
+ (keyp->source_type << 9)) & mask);
+}
+
static struct avtab_node*
avtab_insert_node(struct avtab *h, int hvalue,
struct avtab_node * prev, struct avtab_node * cur,
@@ -59,10 +60,10 @@ static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_dat
struct avtab_node *prev, *cur, *newnode;
u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
- if (!h)
+ if (!h || !h->htable)
return -EINVAL;
- hvalue = AVTAB_HASH(key);
+ hvalue = avtab_hash(key, h->mask);
for (prev = NULL, cur = h->htable[hvalue];
cur;
prev = cur, cur = cur->next) {
@@ -100,9 +101,9 @@ avtab_insert_nonunique(struct avtab * h, struct avtab_key * key, struct avtab_da
struct avtab_node *prev, *cur, *newnode;
u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
- if (!h)
+ if (!h || !h->htable)
return NULL;
- hvalue = AVTAB_HASH(key);
+ hvalue = avtab_hash(key, h->mask);
for (prev = NULL, cur = h->htable[hvalue];
cur;
prev = cur, cur = cur->next) {
@@ -132,10 +133,10 @@ struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key)
struct avtab_node *cur;
u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
- if (!h)
+ if (!h || !h->htable)
return NULL;
- hvalue = AVTAB_HASH(key);
+ hvalue = avtab_hash(key, h->mask);
for (cur = h->htable[hvalue]; cur; cur = cur->next) {
if (key->source_type == cur->key.source_type &&
key->target_type == cur->key.target_type &&
@@ -167,10 +168,10 @@ avtab_search_node(struct avtab *h, struct avtab_key *key)
struct avtab_node *cur;
u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
- if (!h)
+ if (!h || !h->htable)
return NULL;
- hvalue = AVTAB_HASH(key);
+ hvalue = avtab_hash(key, h->mask);
for (cur = h->htable[hvalue]; cur; cur = cur->next) {
if (key->source_type == cur->key.source_type &&
key->target_type == cur->key.target_type &&
@@ -228,7 +229,7 @@ void avtab_destroy(struct avtab *h)
if (!h || !h->htable)
return;
- for (i = 0; i < AVTAB_SIZE; i++) {
+ for (i = 0; i < h->nslot; i++) {
cur = h->htable[i];
while (cur != NULL) {
temp = cur;
@@ -237,32 +238,63 @@ void avtab_destroy(struct avtab *h)
}
h->htable[i] = NULL;
}
- vfree(h->htable);
+ kfree(h->htable);
h->htable = NULL;
+ h->nslot = 0;
+ h->mask = 0;
}
-
int avtab_init(struct avtab *h)
{
- int i;
+ h->htable = NULL;
+ h->nel = 0;
+ return 0;
+}
+
+int avtab_alloc(struct avtab *h, u32 nrules)
+{
+ u16 mask = 0;
+ u32 shift = 0;
+ u32 work = nrules;
+ u32 nslot = 0;
+
+ if (nrules == 0)
+ goto avtab_alloc_out;
- h->htable = vmalloc(sizeof(*(h->htable)) * AVTAB_SIZE);
+ while (work) {
+ work = work >> 1;
+ shift++;
+ }
+ if (shift > 2)
+ shift = shift - 2;
+ nslot = 1 << shift;
+ if (nslot > MAX_AVTAB_SIZE)
+ nslot = MAX_AVTAB_SIZE;
+ mask = nslot - 1;
+
+ h->htable = kcalloc(nslot, sizeof(*(h->htable)), GFP_KERNEL);
if (!h->htable)
return -ENOMEM;
- for (i = 0; i < AVTAB_SIZE; i++)
- h->htable[i] = NULL;
+
+ avtab_alloc_out:
h->nel = 0;
+ h->nslot = nslot;
+ h->mask = mask;
+ printk(KERN_DEBUG "SELinux:%d avtab hash slots allocated."
+ "Num of rules:%d\n", h->nslot, nrules);
return 0;
}
void avtab_hash_eval(struct avtab *h, char *tag)
{
int i, chain_len, slots_used, max_chain_len;
+ unsigned long long chain2_len_sum;
struct avtab_node *cur;
slots_used = 0;
max_chain_len = 0;
- for (i = 0; i < AVTAB_SIZE; i++) {
+ chain2_len_sum = 0;
+ for (i = 0; i < h->nslot; i++) {
cur = h->htable[i];
if (cur) {
slots_used++;
@@ -274,12 +306,14 @@ void avtab_hash_eval(struct avtab *h, char *tag)
if (chain_len > max_chain_len)
max_chain_len = chain_len;
+ chain2_len_sum += chain_len * chain_len;
}
}
printk(KERN_DEBUG "%s: %d entries and %d/%d buckets used, longest "
- "chain length %d\n", tag, h->nel, slots_used, AVTAB_SIZE,
- max_chain_len);
+ "chain length %d sum of chain length^2 %Lu\n",
+ tag, h->nel, slots_used, h->nslot, max_chain_len,
+ chain2_len_sum);
}
static uint16_t spec_order[] = {
@@ -291,7 +325,7 @@ static uint16_t spec_order[] = {
AVTAB_MEMBER
};
-int avtab_read_item(void *fp, u32 vers, struct avtab *a,
+int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
int (*insertf)(struct avtab *a, struct avtab_key *k,
struct avtab_datum *d, void *p),
void *p)
@@ -299,10 +333,11 @@ int avtab_read_item(void *fp, u32 vers, struct avtab *a,
__le16 buf16[4];
u16 enabled;
__le32 buf32[7];
- u32 items, items2, val;
+ u32 items, items2, val, vers = pol->policyvers;
struct avtab_key key;
struct avtab_datum datum;
int i, rc;
+ unsigned set;
memset(&key, 0, sizeof(struct avtab_key));
memset(&datum, 0, sizeof(struct avtab_datum));
@@ -386,12 +421,35 @@ int avtab_read_item(void *fp, u32 vers, struct avtab *a,
key.target_class = le16_to_cpu(buf16[items++]);
key.specified = le16_to_cpu(buf16[items++]);
+ if (!policydb_type_isvalid(pol, key.source_type) ||
+ !policydb_type_isvalid(pol, key.target_type) ||
+ !policydb_class_isvalid(pol, key.target_class)) {
+ printk(KERN_WARNING "security: avtab: invalid type or class\n");
+ return -1;
+ }
+
+ set = 0;
+ for (i = 0; i < ARRAY_SIZE(spec_order); i++) {
+ if (key.specified & spec_order[i])
+ set++;
+ }
+ if (!set || set > 1) {
+ printk(KERN_WARNING
+ "security: avtab: more than one specifier\n");
+ return -1;
+ }
+
rc = next_entry(buf32, fp, sizeof(u32));
if (rc < 0) {
printk("security: avtab: truncated entry\n");
return -1;
}
datum.data = le32_to_cpu(*buf32);
+ if ((key.specified & AVTAB_TYPE) &&
+ !policydb_type_isvalid(pol, datum.data)) {
+ printk(KERN_WARNING "security: avtab: invalid type\n");
+ return -1;
+ }
return insertf(a, &key, &datum, p);
}
@@ -401,7 +459,7 @@ static int avtab_insertf(struct avtab *a, struct avtab_key *k,
return avtab_insert(a, k, d);
}
-int avtab_read(struct avtab *a, void *fp, u32 vers)
+int avtab_read(struct avtab *a, void *fp, struct policydb *pol)
{
int rc;
__le32 buf[1];
@@ -419,8 +477,13 @@ int avtab_read(struct avtab *a, void *fp, u32 vers)
rc = -EINVAL;
goto bad;
}
+
+ rc = avtab_alloc(a, nel);
+ if (rc)
+ goto bad;
+
for (i = 0; i < nel; i++) {
- rc = avtab_read_item(fp,vers, a, avtab_insertf, NULL);
+ rc = avtab_read_item(a, fp, pol, avtab_insertf, NULL);
if (rc) {
if (rc == -ENOMEM)
printk(KERN_ERR "security: avtab: out of memory\n");
diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h
index 0a90d939af93..8da6a8428086 100644
--- a/security/selinux/ss/avtab.h
+++ b/security/selinux/ss/avtab.h
@@ -16,6 +16,9 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 2.
+ *
+ * Updated: Yuichi Nakamura <ynakam@hitachisoft.jp>
+ * Tuned number of hash slots for avtab to reduce memory usage
*/
#ifndef _SS_AVTAB_H_
#define _SS_AVTAB_H_
@@ -50,19 +53,24 @@ struct avtab_node {
struct avtab {
struct avtab_node **htable;
u32 nel; /* number of elements */
+ u32 nslot; /* number of hash slots */
+ u16 mask; /* mask to compute hash func */
+
};
int avtab_init(struct avtab *);
+int avtab_alloc(struct avtab *, u32);
struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *k);
void avtab_destroy(struct avtab *h);
void avtab_hash_eval(struct avtab *h, char *tag);
-int avtab_read_item(void *fp, uint32_t vers, struct avtab *a,
+struct policydb;
+int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
int (*insert)(struct avtab *a, struct avtab_key *k,
struct avtab_datum *d, void *p),
void *p);
-int avtab_read(struct avtab *a, void *fp, u32 vers);
+int avtab_read(struct avtab *a, void *fp, struct policydb *pol);
struct avtab_node *avtab_insert_nonunique(struct avtab *h, struct avtab_key *key,
struct avtab_datum *datum);
@@ -74,11 +82,10 @@ struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified
void avtab_cache_init(void);
void avtab_cache_destroy(void);
-#define AVTAB_HASH_BITS 15
-#define AVTAB_HASH_BUCKETS (1 << AVTAB_HASH_BITS)
-#define AVTAB_HASH_MASK (AVTAB_HASH_BUCKETS-1)
-
-#define AVTAB_SIZE AVTAB_HASH_BUCKETS
+#define MAX_AVTAB_HASH_BITS 13
+#define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS)
+#define MAX_AVTAB_HASH_MASK (MAX_AVTAB_HASH_BUCKETS-1)
+#define MAX_AVTAB_SIZE MAX_AVTAB_HASH_BUCKETS
#endif /* _SS_AVTAB_H_ */
diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c
index d2737edba541..50ad85d4b77c 100644
--- a/security/selinux/ss/conditional.c
+++ b/security/selinux/ss/conditional.c
@@ -362,7 +362,8 @@ static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list *
data.head = NULL;
data.tail = NULL;
for (i = 0; i < len; i++) {
- rc = avtab_read_item(fp, p->policyvers, &p->te_cond_avtab, cond_insertf, &data);
+ rc = avtab_read_item(&p->te_cond_avtab, fp, p, cond_insertf,
+ &data);
if (rc)
return rc;
@@ -456,6 +457,10 @@ int cond_read_list(struct policydb *p, void *fp)
len = le32_to_cpu(buf[0]);
+ rc = avtab_alloc(&(p->te_cond_avtab), p->te_avtab.nel);
+ if (rc)
+ goto err;
+
for (i = 0; i < len; i++) {
node = kzalloc(sizeof(struct cond_node), GFP_KERNEL);
if (!node)
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
index ce492a6b38ed..920b5e36a1af 100644
--- a/security/selinux/ss/ebitmap.c
+++ b/security/selinux/ss/ebitmap.c
@@ -10,6 +10,10 @@
*
* (c) Copyright Hewlett-Packard Development Company, L.P., 2006
*/
+/*
+ * Updated: KaiGai Kohei <kaigai@ak.jp.nec.com>
+ * Applied standard bit operations to improve bitmap scanning.
+ */
#include <linux/kernel.h>
#include <linux/slab.h>
@@ -29,7 +33,7 @@ int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2)
n2 = e2->node;
while (n1 && n2 &&
(n1->startbit == n2->startbit) &&
- (n1->map == n2->map)) {
+ !memcmp(n1->maps, n2->maps, EBITMAP_SIZE / 8)) {
n1 = n1->next;
n2 = n2->next;
}
@@ -54,7 +58,7 @@ int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src)
return -ENOMEM;
}
new->startbit = n->startbit;
- new->map = n->map;
+ memcpy(new->maps, n->maps, EBITMAP_SIZE / 8);
new->next = NULL;
if (prev)
prev->next = new;
@@ -84,13 +88,15 @@ int ebitmap_netlbl_export(struct ebitmap *ebmap,
{
struct ebitmap_node *e_iter = ebmap->node;
struct netlbl_lsm_secattr_catmap *c_iter;
- u32 cmap_idx;
+ u32 cmap_idx, cmap_sft;
+ int i;
- /* This function is a much simpler because SELinux's MAPTYPE happens
- * to be the same as NetLabel's NETLBL_CATMAP_MAPTYPE, if MAPTYPE is
- * changed from a u64 this function will most likely need to be changed
- * as well. It's not ideal but I think the tradeoff in terms of
- * neatness and speed is worth it. */
+ /* NetLabel's NETLBL_CATMAP_MAPTYPE is defined as an array of u64,
+ * however, it is not always compatible with an array of unsigned long
+ * in ebitmap_node.
+ * In addition, you should pay attention the following implementation
+ * assumes unsigned long has a width equal with or less than 64-bit.
+ */
if (e_iter == NULL) {
*catmap = NULL;
@@ -104,18 +110,26 @@ int ebitmap_netlbl_export(struct ebitmap *ebmap,
c_iter->startbit = e_iter->startbit & ~(NETLBL_CATMAP_SIZE - 1);
while (e_iter != NULL) {
- if (e_iter->startbit >=
- (c_iter->startbit + NETLBL_CATMAP_SIZE)) {
- c_iter->next = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
- if (c_iter->next == NULL)
- goto netlbl_export_failure;
- c_iter = c_iter->next;
- c_iter->startbit = e_iter->startbit &
- ~(NETLBL_CATMAP_SIZE - 1);
+ for (i = 0; i < EBITMAP_UNIT_NUMS; i++) {
+ unsigned int delta, e_startbit, c_endbit;
+
+ e_startbit = e_iter->startbit + i * EBITMAP_UNIT_SIZE;
+ c_endbit = c_iter->startbit + NETLBL_CATMAP_SIZE;
+ if (e_startbit >= c_endbit) {
+ c_iter->next
+ = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
+ if (c_iter->next == NULL)
+ goto netlbl_export_failure;
+ c_iter = c_iter->next;
+ c_iter->startbit
+ = e_startbit & ~(NETLBL_CATMAP_SIZE - 1);
+ }
+ delta = e_startbit - c_iter->startbit;
+ cmap_idx = delta / NETLBL_CATMAP_MAPSIZE;
+ cmap_sft = delta % NETLBL_CATMAP_MAPSIZE;
+ c_iter->bitmap[cmap_idx]
+ |= e_iter->maps[cmap_idx] << cmap_sft;
}
- cmap_idx = (e_iter->startbit - c_iter->startbit) /
- NETLBL_CATMAP_MAPSIZE;
- c_iter->bitmap[cmap_idx] = e_iter->map;
e_iter = e_iter->next;
}
@@ -128,7 +142,7 @@ netlbl_export_failure:
/**
* ebitmap_netlbl_import - Import a NetLabel category bitmap into an ebitmap
- * @ebmap: the ebitmap to export
+ * @ebmap: the ebitmap to import
* @catmap: the NetLabel category bitmap
*
* Description:
@@ -142,36 +156,50 @@ int ebitmap_netlbl_import(struct ebitmap *ebmap,
struct ebitmap_node *e_iter = NULL;
struct ebitmap_node *emap_prev = NULL;
struct netlbl_lsm_secattr_catmap *c_iter = catmap;
- u32 c_idx;
+ u32 c_idx, c_pos, e_idx, e_sft;
- /* This function is a much simpler because SELinux's MAPTYPE happens
- * to be the same as NetLabel's NETLBL_CATMAP_MAPTYPE, if MAPTYPE is
- * changed from a u64 this function will most likely need to be changed
- * as well. It's not ideal but I think the tradeoff in terms of
- * neatness and speed is worth it. */
+ /* NetLabel's NETLBL_CATMAP_MAPTYPE is defined as an array of u64,
+ * however, it is not always compatible with an array of unsigned long
+ * in ebitmap_node.
+ * In addition, you should pay attention the following implementation
+ * assumes unsigned long has a width equal with or less than 64-bit.
+ */
do {
for (c_idx = 0; c_idx < NETLBL_CATMAP_MAPCNT; c_idx++) {
- if (c_iter->bitmap[c_idx] == 0)
+ unsigned int delta;
+ u64 map = c_iter->bitmap[c_idx];
+
+ if (!map)
continue;
- e_iter = kzalloc(sizeof(*e_iter), GFP_ATOMIC);
- if (e_iter == NULL)
- goto netlbl_import_failure;
- if (emap_prev == NULL)
- ebmap->node = e_iter;
- else
- emap_prev->next = e_iter;
- emap_prev = e_iter;
-
- e_iter->startbit = c_iter->startbit +
- NETLBL_CATMAP_MAPSIZE * c_idx;
- e_iter->map = c_iter->bitmap[c_idx];
+ c_pos = c_iter->startbit
+ + c_idx * NETLBL_CATMAP_MAPSIZE;
+ if (!e_iter
+ || c_pos >= e_iter->startbit + EBITMAP_SIZE) {
+ e_iter = kzalloc(sizeof(*e_iter), GFP_ATOMIC);
+ if (!e_iter)
+ goto netlbl_import_failure;
+ e_iter->startbit
+ = c_pos - (c_pos % EBITMAP_SIZE);
+ if (emap_prev == NULL)
+ ebmap->node = e_iter;
+ else
+ emap_prev->next = e_iter;
+ emap_prev = e_iter;
+ }
+ delta = c_pos - e_iter->startbit;
+ e_idx = delta / EBITMAP_UNIT_SIZE;
+ e_sft = delta % EBITMAP_UNIT_SIZE;
+ while (map) {
+ e_iter->maps[e_idx++] |= map & (-1UL);
+ map = EBITMAP_SHIFT_UNIT_SIZE(map);
+ }
}
c_iter = c_iter->next;
} while (c_iter != NULL);
if (e_iter != NULL)
- ebmap->highbit = e_iter->startbit + MAPSIZE;
+ ebmap->highbit = e_iter->startbit + EBITMAP_SIZE;
else
ebitmap_destroy(ebmap);
@@ -186,6 +214,7 @@ netlbl_import_failure:
int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2)
{
struct ebitmap_node *n1, *n2;
+ int i;
if (e1->highbit < e2->highbit)
return 0;
@@ -197,8 +226,10 @@ int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2)
n1 = n1->next;
continue;
}
- if ((n1->map & n2->map) != n2->map)
- return 0;
+ for (i = 0; i < EBITMAP_UNIT_NUMS; i++) {
+ if ((n1->maps[i] & n2->maps[i]) != n2->maps[i])
+ return 0;
+ }
n1 = n1->next;
n2 = n2->next;
@@ -219,12 +250,8 @@ int ebitmap_get_bit(struct ebitmap *e, unsigned long bit)
n = e->node;
while (n && (n->startbit <= bit)) {
- if ((n->startbit + MAPSIZE) > bit) {
- if (n->map & (MAPBIT << (bit - n->startbit)))
- return 1;
- else
- return 0;
- }
+ if ((n->startbit + EBITMAP_SIZE) > bit)
+ return ebitmap_node_get_bit(n, bit);
n = n->next;
}
@@ -238,31 +265,35 @@ int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value)
prev = NULL;
n = e->node;
while (n && n->startbit <= bit) {
- if ((n->startbit + MAPSIZE) > bit) {
+ if ((n->startbit + EBITMAP_SIZE) > bit) {
if (value) {
- n->map |= (MAPBIT << (bit - n->startbit));
+ ebitmap_node_set_bit(n, bit);
} else {
- n->map &= ~(MAPBIT << (bit - n->startbit));
- if (!n->map) {
- /* drop this node from the bitmap */
-
- if (!n->next) {
- /*
- * this was the highest map
- * within the bitmap
- */
- if (prev)
- e->highbit = prev->startbit + MAPSIZE;
- else
- e->highbit = 0;
- }
+ unsigned int s;
+
+ ebitmap_node_clr_bit(n, bit);
+
+ s = find_first_bit(n->maps, EBITMAP_SIZE);
+ if (s < EBITMAP_SIZE)
+ return 0;
+
+ /* drop this node from the bitmap */
+ if (!n->next) {
+ /*
+ * this was the highest map
+ * within the bitmap
+ */
if (prev)
- prev->next = n->next;
+ e->highbit = prev->startbit
+ + EBITMAP_SIZE;
else
- e->node = n->next;
-
- kfree(n);
+ e->highbit = 0;
}
+ if (prev)
+ prev->next = n->next;
+ else
+ e->node = n->next;
+ kfree(n);
}
return 0;
}
@@ -277,12 +308,12 @@ int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value)
if (!new)
return -ENOMEM;
- new->startbit = bit & ~(MAPSIZE - 1);
- new->map = (MAPBIT << (bit - new->startbit));
+ new->startbit = bit - (bit % EBITMAP_SIZE);
+ ebitmap_node_set_bit(new, bit);
if (!n)
/* this node will be the highest map within the bitmap */
- e->highbit = new->startbit + MAPSIZE;
+ e->highbit = new->startbit + EBITMAP_SIZE;
if (prev) {
new->next = prev->next;
@@ -316,11 +347,11 @@ void ebitmap_destroy(struct ebitmap *e)
int ebitmap_read(struct ebitmap *e, void *fp)
{
- int rc;
- struct ebitmap_node *n, *l;
+ struct ebitmap_node *n = NULL;
+ u32 mapunit, count, startbit, index;
+ u64 map;
__le32 buf[3];
- u32 mapsize, count, i;
- __le64 map;
+ int rc, i;
ebitmap_init(e);
@@ -328,85 +359,88 @@ int ebitmap_read(struct ebitmap *e, void *fp)
if (rc < 0)
goto out;
- mapsize = le32_to_cpu(buf[0]);
+ mapunit = le32_to_cpu(buf[0]);
e->highbit = le32_to_cpu(buf[1]);
count = le32_to_cpu(buf[2]);
- if (mapsize != MAPSIZE) {
+ if (mapunit != sizeof(u64) * 8) {
printk(KERN_ERR "security: ebitmap: map size %u does not "
- "match my size %Zd (high bit was %d)\n", mapsize,
- MAPSIZE, e->highbit);
+ "match my size %Zd (high bit was %d)\n",
+ mapunit, sizeof(u64) * 8, e->highbit);
goto bad;
}
+
+ /* round up e->highbit */
+ e->highbit += EBITMAP_SIZE - 1;
+ e->highbit -= (e->highbit % EBITMAP_SIZE);
+
if (!e->highbit) {
e->node = NULL;
goto ok;
}
- if (e->highbit & (MAPSIZE - 1)) {
- printk(KERN_ERR "security: ebitmap: high bit (%d) is not a "
- "multiple of the map size (%Zd)\n", e->highbit, MAPSIZE);
- goto bad;
- }
- l = NULL;
+
for (i = 0; i < count; i++) {
- rc = next_entry(buf, fp, sizeof(u32));
+ rc = next_entry(&startbit, fp, sizeof(u32));
if (rc < 0) {
printk(KERN_ERR "security: ebitmap: truncated map\n");
goto bad;
}
- n = kzalloc(sizeof(*n), GFP_KERNEL);
- if (!n) {
- printk(KERN_ERR "security: ebitmap: out of memory\n");
- rc = -ENOMEM;
- goto bad;
- }
-
- n->startbit = le32_to_cpu(buf[0]);
+ startbit = le32_to_cpu(startbit);
- if (n->startbit & (MAPSIZE - 1)) {
+ if (startbit & (mapunit - 1)) {
printk(KERN_ERR "security: ebitmap start bit (%d) is "
- "not a multiple of the map size (%Zd)\n",
- n->startbit, MAPSIZE);
- goto bad_free;
+ "not a multiple of the map unit size (%u)\n",
+ startbit, mapunit);
+ goto bad;
}
- if (n->startbit > (e->highbit - MAPSIZE)) {
+ if (startbit > e->highbit - mapunit) {
printk(KERN_ERR "security: ebitmap start bit (%d) is "
- "beyond the end of the bitmap (%Zd)\n",
- n->startbit, (e->highbit - MAPSIZE));
- goto bad_free;
+ "beyond the end of the bitmap (%u)\n",
+ startbit, (e->highbit - mapunit));
+ goto bad;
+ }
+
+ if (!n || startbit >= n->startbit + EBITMAP_SIZE) {
+ struct ebitmap_node *tmp;
+ tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
+ if (!tmp) {
+ printk(KERN_ERR
+ "security: ebitmap: out of memory\n");
+ rc = -ENOMEM;
+ goto bad;
+ }
+ /* round down */
+ tmp->startbit = startbit - (startbit % EBITMAP_SIZE);
+ if (n) {
+ n->next = tmp;
+ } else {
+ e->node = tmp;
+ }
+ n = tmp;
+ } else if (startbit <= n->startbit) {
+ printk(KERN_ERR "security: ebitmap: start bit %d"
+ " comes after start bit %d\n",
+ startbit, n->startbit);
+ goto bad;
}
+
rc = next_entry(&map, fp, sizeof(u64));
if (rc < 0) {
printk(KERN_ERR "security: ebitmap: truncated map\n");
- goto bad_free;
+ goto bad;
}
- n->map = le64_to_cpu(map);
+ map = le64_to_cpu(map);
- if (!n->map) {
- printk(KERN_ERR "security: ebitmap: null map in "
- "ebitmap (startbit %d)\n", n->startbit);
- goto bad_free;
+ index = (startbit - n->startbit) / EBITMAP_UNIT_SIZE;
+ while (map) {
+ n->maps[index++] = map & (-1UL);
+ map = EBITMAP_SHIFT_UNIT_SIZE(map);
}
- if (l) {
- if (n->startbit <= l->startbit) {
- printk(KERN_ERR "security: ebitmap: start "
- "bit %d comes after start bit %d\n",
- n->startbit, l->startbit);
- goto bad_free;
- }
- l->next = n;
- } else
- e->node = n;
-
- l = n;
}
-
ok:
rc = 0;
out:
return rc;
-bad_free:
- kfree(n);
bad:
if (!rc)
rc = -EINVAL;
diff --git a/security/selinux/ss/ebitmap.h b/security/selinux/ss/ebitmap.h
index 1270e34b61c1..f283b4367f54 100644
--- a/security/selinux/ss/ebitmap.h
+++ b/security/selinux/ss/ebitmap.h
@@ -16,14 +16,18 @@
#include <net/netlabel.h>
-#define MAPTYPE u64 /* portion of bitmap in each node */
-#define MAPSIZE (sizeof(MAPTYPE) * 8) /* number of bits in node bitmap */
-#define MAPBIT 1ULL /* a bit in the node bitmap */
+#define EBITMAP_UNIT_NUMS ((32 - sizeof(void *) - sizeof(u32)) \
+ / sizeof(unsigned long))
+#define EBITMAP_UNIT_SIZE BITS_PER_LONG
+#define EBITMAP_SIZE (EBITMAP_UNIT_NUMS * EBITMAP_UNIT_SIZE)
+#define EBITMAP_BIT 1ULL
+#define EBITMAP_SHIFT_UNIT_SIZE(x) \
+ (((x) >> EBITMAP_UNIT_SIZE / 2) >> EBITMAP_UNIT_SIZE / 2)
struct ebitmap_node {
- u32 startbit; /* starting position in the total bitmap */
- MAPTYPE map; /* this node's portion of the bitmap */
struct ebitmap_node *next;
+ unsigned long maps[EBITMAP_UNIT_NUMS];
+ u32 startbit;
};
struct ebitmap {
@@ -34,11 +38,17 @@ struct ebitmap {
#define ebitmap_length(e) ((e)->highbit)
#define ebitmap_startbit(e) ((e)->node ? (e)->node->startbit : 0)
-static inline unsigned int ebitmap_start(struct ebitmap *e,
- struct ebitmap_node **n)
+static inline unsigned int ebitmap_start_positive(struct ebitmap *e,
+ struct ebitmap_node **n)
{
- *n = e->node;
- return ebitmap_startbit(e);
+ unsigned int ofs;
+
+ for (*n = e->node; *n; *n = (*n)->next) {
+ ofs = find_first_bit((*n)->maps, EBITMAP_SIZE);
+ if (ofs < EBITMAP_SIZE)
+ return (*n)->startbit + ofs;
+ }
+ return ebitmap_length(e);
}
static inline void ebitmap_init(struct ebitmap *e)
@@ -46,28 +56,65 @@ static inline void ebitmap_init(struct ebitmap *e)
memset(e, 0, sizeof(*e));
}
-static inline unsigned int ebitmap_next(struct ebitmap_node **n,
- unsigned int bit)
+static inline unsigned int ebitmap_next_positive(struct ebitmap *e,
+ struct ebitmap_node **n,
+ unsigned int bit)
{
- if ((bit == ((*n)->startbit + MAPSIZE - 1)) &&
- (*n)->next) {
- *n = (*n)->next;
- return (*n)->startbit;
- }
+ unsigned int ofs;
+
+ ofs = find_next_bit((*n)->maps, EBITMAP_SIZE, bit - (*n)->startbit + 1);
+ if (ofs < EBITMAP_SIZE)
+ return ofs + (*n)->startbit;
- return (bit+1);
+ for (*n = (*n)->next; *n; *n = (*n)->next) {
+ ofs = find_first_bit((*n)->maps, EBITMAP_SIZE);
+ if (ofs < EBITMAP_SIZE)
+ return ofs + (*n)->startbit;
+ }
+ return ebitmap_length(e);
}
-static inline int ebitmap_node_get_bit(struct ebitmap_node * n,
+#define EBITMAP_NODE_INDEX(node, bit) \
+ (((bit) - (node)->startbit) / EBITMAP_UNIT_SIZE)
+#define EBITMAP_NODE_OFFSET(node, bit) \
+ (((bit) - (node)->startbit) % EBITMAP_UNIT_SIZE)
+
+static inline int ebitmap_node_get_bit(struct ebitmap_node *n,
unsigned int bit)
{
- if (n->map & (MAPBIT << (bit - n->startbit)))
+ unsigned int index = EBITMAP_NODE_INDEX(n, bit);
+ unsigned int ofs = EBITMAP_NODE_OFFSET(n, bit);
+
+ BUG_ON(index >= EBITMAP_UNIT_NUMS);
+ if ((n->maps[index] & (EBITMAP_BIT << ofs)))
return 1;
return 0;
}
-#define ebitmap_for_each_bit(e, n, bit) \
- for (bit = ebitmap_start(e, &n); bit < ebitmap_length(e); bit = ebitmap_next(&n, bit)) \
+static inline void ebitmap_node_set_bit(struct ebitmap_node *n,
+ unsigned int bit)
+{
+ unsigned int index = EBITMAP_NODE_INDEX(n, bit);
+ unsigned int ofs = EBITMAP_NODE_OFFSET(n, bit);
+
+ BUG_ON(index >= EBITMAP_UNIT_NUMS);
+ n->maps[index] |= (EBITMAP_BIT << ofs);
+}
+
+static inline void ebitmap_node_clr_bit(struct ebitmap_node *n,
+ unsigned int bit)
+{
+ unsigned int index = EBITMAP_NODE_INDEX(n, bit);
+ unsigned int ofs = EBITMAP_NODE_OFFSET(n, bit);
+
+ BUG_ON(index >= EBITMAP_UNIT_NUMS);
+ n->maps[index] &= ~(EBITMAP_BIT << ofs);
+}
+
+#define ebitmap_for_each_positive_bit(e, n, bit) \
+ for (bit = ebitmap_start_positive(e, &n); \
+ bit < ebitmap_length(e); \
+ bit = ebitmap_next_positive(e, &n, bit)) \
int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2);
int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src);
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index 4a8bab2f3c71..fb5d70a6628d 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -34,7 +34,9 @@
*/
int mls_compute_context_len(struct context * context)
{
- int i, l, len, range;
+ int i, l, len, head, prev;
+ char *nm;
+ struct ebitmap *e;
struct ebitmap_node *node;
if (!selinux_mls_enabled)
@@ -42,31 +44,33 @@ int mls_compute_context_len(struct context * context)
len = 1; /* for the beginning ":" */
for (l = 0; l < 2; l++) {
- range = 0;
- len += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
-
- ebitmap_for_each_bit(&context->range.level[l].cat, node, i) {
- if (ebitmap_node_get_bit(node, i)) {
- if (range) {
- range++;
- continue;
- }
+ int index_sens = context->range.level[l].sens;
+ len += strlen(policydb.p_sens_val_to_name[index_sens - 1]);
- len += strlen(policydb.p_cat_val_to_name[i]) + 1;
- range++;
- } else {
- if (range > 1)
- len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1;
- range = 0;
+ /* categories */
+ head = -2;
+ prev = -2;
+ e = &context->range.level[l].cat;
+ ebitmap_for_each_positive_bit(e, node, i) {
+ if (i - prev > 1) {
+ /* one or more negative bits are skipped */
+ if (head != prev) {
+ nm = policydb.p_cat_val_to_name[prev];
+ len += strlen(nm) + 1;
+ }
+ nm = policydb.p_cat_val_to_name[i];
+ len += strlen(nm) + 1;
+ head = i;
}
+ prev = i;
+ }
+ if (prev != head) {
+ nm = policydb.p_cat_val_to_name[prev];
+ len += strlen(nm) + 1;
}
- /* Handle case where last category is the end of range */
- if (range > 1)
- len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1;
-
if (l == 0) {
if (mls_level_eq(&context->range.level[0],
- &context->range.level[1]))
+ &context->range.level[1]))
break;
else
len++;
@@ -84,8 +88,9 @@ int mls_compute_context_len(struct context * context)
void mls_sid_to_context(struct context *context,
char **scontext)
{
- char *scontextp;
- int i, l, range, wrote_sep;
+ char *scontextp, *nm;
+ int i, l, head, prev;
+ struct ebitmap *e;
struct ebitmap_node *node;
if (!selinux_mls_enabled)
@@ -97,61 +102,54 @@ void mls_sid_to_context(struct context *context,
scontextp++;
for (l = 0; l < 2; l++) {
- range = 0;
- wrote_sep = 0;
strcpy(scontextp,
policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
- scontextp += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
+ scontextp += strlen(scontextp);
/* categories */
- ebitmap_for_each_bit(&context->range.level[l].cat, node, i) {
- if (ebitmap_node_get_bit(node, i)) {
- if (range) {
- range++;
- continue;
- }
-
- if (!wrote_sep) {
- *scontextp++ = ':';
- wrote_sep = 1;
- } else
- *scontextp++ = ',';
- strcpy(scontextp, policydb.p_cat_val_to_name[i]);
- scontextp += strlen(policydb.p_cat_val_to_name[i]);
- range++;
- } else {
- if (range > 1) {
- if (range > 2)
+ head = -2;
+ prev = -2;
+ e = &context->range.level[l].cat;
+ ebitmap_for_each_positive_bit(e, node, i) {
+ if (i - prev > 1) {
+ /* one or more negative bits are skipped */
+ if (prev != head) {
+ if (prev - head > 1)
*scontextp++ = '.';
else
*scontextp++ = ',';
-
- strcpy(scontextp, policydb.p_cat_val_to_name[i - 1]);
- scontextp += strlen(policydb.p_cat_val_to_name[i - 1]);
+ nm = policydb.p_cat_val_to_name[prev];
+ strcpy(scontextp, nm);
+ scontextp += strlen(nm);
}
- range = 0;
+ if (prev < 0)
+ *scontextp++ = ':';
+ else
+ *scontextp++ = ',';
+ nm = policydb.p_cat_val_to_name[i];
+ strcpy(scontextp, nm);
+ scontextp += strlen(nm);
+ head = i;
}
+ prev = i;
}
- /* Handle case where last category is the end of range */
- if (range > 1) {
- if (range > 2)
+ if (prev != head) {
+ if (prev - head > 1)
*scontextp++ = '.';
else
*scontextp++ = ',';
-
- strcpy(scontextp, policydb.p_cat_val_to_name[i - 1]);
- scontextp += strlen(policydb.p_cat_val_to_name[i - 1]);
+ nm = policydb.p_cat_val_to_name[prev];
+ strcpy(scontextp, nm);
+ scontextp += strlen(nm);
}
if (l == 0) {
if (mls_level_eq(&context->range.level[0],
&context->range.level[1]))
break;
- else {
- *scontextp = '-';
- scontextp++;
- }
+ else
+ *scontextp++ = '-';
}
}
@@ -159,51 +157,55 @@ void mls_sid_to_context(struct context *context,
return;
}
+int mls_level_isvalid(struct policydb *p, struct mls_level *l)
+{
+ struct level_datum *levdatum;
+ struct ebitmap_node *node;
+ int i;
+
+ if (!l->sens || l->sens > p->p_levels.nprim)
+ return 0;
+ levdatum = hashtab_search(p->p_levels.table,
+ p->p_sens_val_to_name[l->sens - 1]);
+ if (!levdatum)
+ return 0;
+
+ ebitmap_for_each_positive_bit(&l->cat, node, i) {
+ if (i > p->p_cats.nprim)
+ return 0;
+ if (!ebitmap_get_bit(&levdatum->level->cat, i)) {
+ /*
+ * Category may not be associated with
+ * sensitivity.
+ */
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+int mls_range_isvalid(struct policydb *p, struct mls_range *r)
+{
+ return (mls_level_isvalid(p, &r->level[0]) &&
+ mls_level_isvalid(p, &r->level[1]) &&
+ mls_level_dom(&r->level[1], &r->level[0]));
+}
+
/*
* Return 1 if the MLS fields in the security context
* structure `c' are valid. Return 0 otherwise.
*/
int mls_context_isvalid(struct policydb *p, struct context *c)
{
- struct level_datum *levdatum;
struct user_datum *usrdatum;
- struct ebitmap_node *node;
- int i, l;
if (!selinux_mls_enabled)
return 1;
- /*
- * MLS range validity checks: high must dominate low, low level must
- * be valid (category set <-> sensitivity check), and high level must
- * be valid (category set <-> sensitivity check)
- */
- if (!mls_level_dom(&c->range.level[1], &c->range.level[0]))
- /* High does not dominate low. */
+ if (!mls_range_isvalid(p, &c->range))
return 0;
- for (l = 0; l < 2; l++) {
- if (!c->range.level[l].sens || c->range.level[l].sens > p->p_levels.nprim)
- return 0;
- levdatum = hashtab_search(p->p_levels.table,
- p->p_sens_val_to_name[c->range.level[l].sens - 1]);
- if (!levdatum)
- return 0;
-
- ebitmap_for_each_bit(&c->range.level[l].cat, node, i) {
- if (ebitmap_node_get_bit(node, i)) {
- if (i > p->p_cats.nprim)
- return 0;
- if (!ebitmap_get_bit(&levdatum->level->cat, i))
- /*
- * Category may not be associated with
- * sensitivity in low level.
- */
- return 0;
- }
- }
- }
-
if (c->role == OBJECT_R_VAL)
return 1;
@@ -485,18 +487,16 @@ int mls_convert_context(struct policydb *oldp,
c->range.level[l].sens = levdatum->level->sens;
ebitmap_init(&bitmap);
- ebitmap_for_each_bit(&c->range.level[l].cat, node, i) {
- if (ebitmap_node_get_bit(node, i)) {
- int rc;
-
- catdatum = hashtab_search(newp->p_cats.table,
- oldp->p_cat_val_to_name[i]);
- if (!catdatum)
- return -EINVAL;
- rc = ebitmap_set_bit(&bitmap, catdatum->value - 1, 1);
- if (rc)
- return rc;
- }
+ ebitmap_for_each_positive_bit(&c->range.level[l].cat, node, i) {
+ int rc;
+
+ catdatum = hashtab_search(newp->p_cats.table,
+ oldp->p_cat_val_to_name[i]);
+ if (!catdatum)
+ return -EINVAL;
+ rc = ebitmap_set_bit(&bitmap, catdatum->value - 1, 1);
+ if (rc)
+ return rc;
}
ebitmap_destroy(&c->range.level[l].cat);
c->range.level[l].cat = bitmap;
diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h
index 096d1b4ef7fb..ab53663d9f5f 100644
--- a/security/selinux/ss/mls.h
+++ b/security/selinux/ss/mls.h
@@ -27,6 +27,8 @@
int mls_compute_context_len(struct context *context);
void mls_sid_to_context(struct context *context, char **scontext);
int mls_context_isvalid(struct policydb *p, struct context *c);
+int mls_range_isvalid(struct policydb *p, struct mls_range *r);
+int mls_level_isvalid(struct policydb *p, struct mls_level *l);
int mls_context_to_sid(char oldc,
char **scontext,
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index f05f97a2bc3a..b582aae3c62c 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -177,18 +177,15 @@ static int policydb_init(struct policydb *p)
rc = roles_init(p);
if (rc)
- goto out_free_avtab;
+ goto out_free_symtab;
rc = cond_policydb_init(p);
if (rc)
- goto out_free_avtab;
+ goto out_free_symtab;
out:
return rc;
-out_free_avtab:
- avtab_destroy(&p->te_avtab);
-
out_free_symtab:
for (i = 0; i < SYM_NUM; i++)
hashtab_destroy(p->symtab[i].table);
@@ -677,6 +674,8 @@ void policydb_destroy(struct policydb *p)
}
kfree(p->type_attr_map);
+ kfree(p->undefined_perms);
+
return;
}
@@ -714,6 +713,27 @@ out:
return rc;
}
+int policydb_class_isvalid(struct policydb *p, unsigned int class)
+{
+ if (!class || class > p->p_classes.nprim)
+ return 0;
+ return 1;
+}
+
+int policydb_role_isvalid(struct policydb *p, unsigned int role)
+{
+ if (!role || role > p->p_roles.nprim)
+ return 0;
+ return 1;
+}
+
+int policydb_type_isvalid(struct policydb *p, unsigned int type)
+{
+ if (!type || type > p->p_types.nprim)
+ return 0;
+ return 1;
+}
+
/*
* Return 1 if the fields in the security context
* structure `c' are valid. Return 0 otherwise.
@@ -1261,6 +1281,7 @@ static int mls_read_level(struct mls_level *lp, void *fp)
"categories\n");
goto bad;
}
+
return 0;
bad:
@@ -1530,6 +1551,8 @@ int policydb_read(struct policydb *p, void *fp)
goto bad;
}
}
+ p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN);
+ p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN);
info = policydb_lookup_compat(p->policyvers);
if (!info) {
@@ -1562,7 +1585,7 @@ int policydb_read(struct policydb *p, void *fp)
p->symtab[i].nprim = nprim;
}
- rc = avtab_read(&p->te_avtab, fp, p->policyvers);
+ rc = avtab_read(&p->te_avtab, fp, p);
if (rc)
goto bad;
@@ -1594,6 +1617,12 @@ int policydb_read(struct policydb *p, void *fp)
tr->role = le32_to_cpu(buf[0]);
tr->type = le32_to_cpu(buf[1]);
tr->new_role = le32_to_cpu(buf[2]);
+ if (!policydb_role_isvalid(p, tr->role) ||
+ !policydb_type_isvalid(p, tr->type) ||
+ !policydb_role_isvalid(p, tr->new_role)) {
+ rc = -EINVAL;
+ goto bad;
+ }
ltr = tr;
}
@@ -1618,6 +1647,11 @@ int policydb_read(struct policydb *p, void *fp)
goto bad;
ra->role = le32_to_cpu(buf[0]);
ra->new_role = le32_to_cpu(buf[1]);
+ if (!policydb_role_isvalid(p, ra->role) ||
+ !policydb_role_isvalid(p, ra->new_role)) {
+ rc = -EINVAL;
+ goto bad;
+ }
lra = ra;
}
@@ -1871,9 +1905,19 @@ int policydb_read(struct policydb *p, void *fp)
rt->target_class = le32_to_cpu(buf[0]);
} else
rt->target_class = SECCLASS_PROCESS;
+ if (!policydb_type_isvalid(p, rt->source_type) ||
+ !policydb_type_isvalid(p, rt->target_type) ||
+ !policydb_class_isvalid(p, rt->target_class)) {
+ rc = -EINVAL;
+ goto bad;
+ }
rc = mls_read_range_helper(&rt->target_range, fp);
if (rc)
goto bad;
+ if (!mls_range_isvalid(p, &rt->target_range)) {
+ printk(KERN_WARNING "security: rangetrans: invalid range\n");
+ goto bad;
+ }
lrt = rt;
}
}
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
index 8319d5ff5944..ed6fc687c66f 100644
--- a/security/selinux/ss/policydb.h
+++ b/security/selinux/ss/policydb.h
@@ -242,17 +242,28 @@ struct policydb {
struct ebitmap *type_attr_map;
unsigned int policyvers;
+
+ unsigned int reject_unknown : 1;
+ unsigned int allow_unknown : 1;
+ u32 *undefined_perms;
};
extern void policydb_destroy(struct policydb *p);
extern int policydb_load_isids(struct policydb *p, struct sidtab *s);
extern int policydb_context_isvalid(struct policydb *p, struct context *c);
+extern int policydb_class_isvalid(struct policydb *p, unsigned int class);
+extern int policydb_type_isvalid(struct policydb *p, unsigned int type);
+extern int policydb_role_isvalid(struct policydb *p, unsigned int role);
extern int policydb_read(struct policydb *p, void *fp);
#define PERM_SYMTAB_SIZE 32
#define POLICYDB_CONFIG_MLS 1
+/* the config flags related to unknown classes/perms are bits 2 and 3 */
+#define REJECT_UNKNOWN 0x00000002
+#define ALLOW_UNKNOWN 0x00000004
+
#define OBJECT_R "object_r"
#define OBJECT_R_VAL 1
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 6100fc023055..d572dc908f31 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -292,6 +292,7 @@ static int context_struct_compute_av(struct context *scontext,
struct class_datum *tclass_datum;
struct ebitmap *sattr, *tattr;
struct ebitmap_node *snode, *tnode;
+ const struct selinux_class_perm *kdefs = &selinux_class_perm;
unsigned int i, j;
/*
@@ -305,13 +306,6 @@ static int context_struct_compute_av(struct context *scontext,
tclass <= SECCLASS_NETLINK_DNRT_SOCKET)
tclass = SECCLASS_NETLINK_SOCKET;
- if (!tclass || tclass > policydb.p_classes.nprim) {
- printk(KERN_ERR "security_compute_av: unrecognized class %d\n",
- tclass);
- return -EINVAL;
- }
- tclass_datum = policydb.class_val_to_struct[tclass - 1];
-
/*
* Initialize the access vectors to the default values.
*/
@@ -322,6 +316,36 @@ static int context_struct_compute_av(struct context *scontext,
avd->seqno = latest_granting;
/*
+ * Check for all the invalid cases.
+ * - tclass 0
+ * - tclass > policy and > kernel
+ * - tclass > policy but is a userspace class
+ * - tclass > policy but we do not allow unknowns
+ */
+ if (unlikely(!tclass))
+ goto inval_class;
+ if (unlikely(tclass > policydb.p_classes.nprim))
+ if (tclass > kdefs->cts_len ||
+ !kdefs->class_to_string[tclass - 1] ||
+ !policydb.allow_unknown)
+ goto inval_class;
+
+ /*
+ * Kernel class and we allow unknown so pad the allow decision
+ * the pad will be all 1 for unknown classes.
+ */
+ if (tclass <= kdefs->cts_len && policydb.allow_unknown)
+ avd->allowed = policydb.undefined_perms[tclass - 1];
+
+ /*
+ * Not in policy. Since decision is completed (all 1 or all 0) return.
+ */
+ if (unlikely(tclass > policydb.p_classes.nprim))
+ return 0;
+
+ tclass_datum = policydb.class_val_to_struct[tclass - 1];
+
+ /*
* If a specific type enforcement rule was defined for
* this permission check, then use it.
*/
@@ -329,12 +353,8 @@ static int context_struct_compute_av(struct context *scontext,
avkey.specified = AVTAB_AV;
sattr = &policydb.type_attr_map[scontext->type - 1];
tattr = &policydb.type_attr_map[tcontext->type - 1];
- ebitmap_for_each_bit(sattr, snode, i) {
- if (!ebitmap_node_get_bit(snode, i))
- continue;
- ebitmap_for_each_bit(tattr, tnode, j) {
- if (!ebitmap_node_get_bit(tnode, j))
- continue;
+ ebitmap_for_each_positive_bit(sattr, snode, i) {
+ ebitmap_for_each_positive_bit(tattr, tnode, j) {
avkey.source_type = i + 1;
avkey.target_type = j + 1;
for (node = avtab_search_node(&policydb.te_avtab, &avkey);
@@ -387,6 +407,10 @@ static int context_struct_compute_av(struct context *scontext,
}
return 0;
+
+inval_class:
+ printk(KERN_ERR "%s: unrecognized class %d\n", __FUNCTION__, tclass);
+ return -EINVAL;
}
static int security_validtrans_handle_fail(struct context *ocontext,
@@ -1054,6 +1078,13 @@ static int validate_classes(struct policydb *p)
const char *def_class, *def_perm, *pol_class;
struct symtab *perms;
+ if (p->allow_unknown) {
+ u32 num_classes = kdefs->cts_len;
+ p->undefined_perms = kcalloc(num_classes, sizeof(u32), GFP_KERNEL);
+ if (!p->undefined_perms)
+ return -ENOMEM;
+ }
+
for (i = 1; i < kdefs->cts_len; i++) {
def_class = kdefs->class_to_string[i];
if (!def_class)
@@ -1062,6 +1093,10 @@ static int validate_classes(struct policydb *p)
printk(KERN_INFO
"security: class %s not defined in policy\n",
def_class);
+ if (p->reject_unknown)
+ return -EINVAL;
+ if (p->allow_unknown)
+ p->undefined_perms[i-1] = ~0U;
continue;
}
pol_class = p->p_class_val_to_name[i-1];
@@ -1087,12 +1122,16 @@ static int validate_classes(struct policydb *p)
printk(KERN_INFO
"security: permission %s in class %s not defined in policy\n",
def_perm, pol_class);
+ if (p->reject_unknown)
+ return -EINVAL;
+ if (p->allow_unknown)
+ p->undefined_perms[class_val-1] |= perm_val;
continue;
}
perdatum = hashtab_search(perms->table, def_perm);
if (perdatum == NULL) {
printk(KERN_ERR
- "security: permission %s in class %s not found in policy\n",
+ "security: permission %s in class %s not found in policy, bad policy\n",
def_perm, pol_class);
return -EINVAL;
}
@@ -1130,12 +1169,16 @@ static int validate_classes(struct policydb *p)
printk(KERN_INFO
"security: permission %s in class %s not defined in policy\n",
def_perm, pol_class);
+ if (p->reject_unknown)
+ return -EINVAL;
+ if (p->allow_unknown)
+ p->undefined_perms[class_val-1] |= (1 << j);
continue;
}
perdatum = hashtab_search(perms->table, def_perm);
if (perdatum == NULL) {
printk(KERN_ERR
- "security: permission %s in class %s not found in policy\n",
+ "security: permission %s in class %s not found in policy, bad policy\n",
def_perm, pol_class);
return -EINVAL;
}
@@ -1621,14 +1664,10 @@ int security_get_user_sids(u32 fromsid,
goto out_unlock;
}
- ebitmap_for_each_bit(&user->roles, rnode, i) {
- if (!ebitmap_node_get_bit(rnode, i))
- continue;
+ ebitmap_for_each_positive_bit(&user->roles, rnode, i) {
role = policydb.role_val_to_struct[i];
usercon.role = i+1;
- ebitmap_for_each_bit(&role->types, tnode, j) {
- if (!ebitmap_node_get_bit(tnode, j))
- continue;
+ ebitmap_for_each_positive_bit(&role->types, tnode, j) {
usercon.type = j+1;
if (mls_setup_user_range(fromcon, user, &usercon))
@@ -2102,6 +2141,16 @@ err:
return rc;
}
+int security_get_reject_unknown(void)
+{
+ return policydb.reject_unknown;
+}
+
+int security_get_allow_unknown(void)
+{
+ return policydb.allow_unknown;
+}
+
struct selinux_audit_rule {
u32 au_seqno;
struct context au_ctxt;
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index ba715f40b658..e07603969033 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -31,7 +31,6 @@
* 2. Emulating a reasonable SO_PEERSEC across machines
* 3. Testing addition of sk_policy's with security context via setsockopt
*/
-#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/security.h>
@@ -212,26 +211,27 @@ static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp,
if (uctx->ctx_doi != XFRM_SC_ALG_SELINUX)
return -EINVAL;
- if (uctx->ctx_len >= PAGE_SIZE)
+ str_len = uctx->ctx_len;
+ if (str_len >= PAGE_SIZE)
return -ENOMEM;
*ctxp = ctx = kmalloc(sizeof(*ctx) +
- uctx->ctx_len + 1,
+ str_len + 1,
GFP_KERNEL);
if (!ctx)
return -ENOMEM;
ctx->ctx_doi = uctx->ctx_doi;
- ctx->ctx_len = uctx->ctx_len;
+ ctx->ctx_len = str_len;
ctx->ctx_alg = uctx->ctx_alg;
memcpy(ctx->ctx_str,
uctx+1,
- ctx->ctx_len);
- ctx->ctx_str[ctx->ctx_len] = 0;
+ str_len);
+ ctx->ctx_str[str_len] = 0;
rc = security_context_to_sid(ctx->ctx_str,
- ctx->ctx_len,
+ str_len,
&ctx->ctx_sid);
if (rc)
@@ -449,7 +449,7 @@ int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
if (dst) {
struct dst_entry *dst_test;
- for (dst_test = dst; dst_test != 0;
+ for (dst_test = dst; dst_test != NULL;
dst_test = dst_test->child) {
struct xfrm_state *x = dst_test->xfrm;
diff --git a/sound/Kconfig b/sound/Kconfig
index e48b9b37d228..b2a2db47aff5 100644
--- a/sound/Kconfig
+++ b/sound/Kconfig
@@ -63,6 +63,10 @@ source "sound/aoa/Kconfig"
source "sound/arm/Kconfig"
+if SPI
+source "sound/spi/Kconfig"
+endif
+
source "sound/mips/Kconfig"
source "sound/sh/Kconfig"
diff --git a/sound/Makefile b/sound/Makefile
index 3ead922bd9c6..c76d70716fa5 100644
--- a/sound/Makefile
+++ b/sound/Makefile
@@ -5,7 +5,8 @@ obj-$(CONFIG_SOUND) += soundcore.o
obj-$(CONFIG_SOUND_PRIME) += sound_firmware.o
obj-$(CONFIG_SOUND_PRIME) += oss/
obj-$(CONFIG_DMASOUND) += oss/
-obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ sparc/ parisc/ pcmcia/ mips/ soc/
+obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \
+ sparc/ spi/ parisc/ pcmcia/ mips/ soc/
obj-$(CONFIG_SND_AOA) += aoa/
# This one must be compilable even if sound is configured out
diff --git a/sound/aoa/codecs/snd-aoa-codec-onyx.c b/sound/aoa/codecs/snd-aoa-codec-onyx.c
index 028852374f21..71e3f9360658 100644
--- a/sound/aoa/codecs/snd-aoa-codec-onyx.c
+++ b/sound/aoa/codecs/snd-aoa-codec-onyx.c
@@ -297,15 +297,7 @@ static struct snd_kcontrol_new capture_source_control = {
.put = onyx_snd_capture_source_put,
};
-static int onyx_snd_mute_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 2;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define onyx_snd_mute_info snd_ctl_boolean_stereo_info
static int onyx_snd_mute_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -359,15 +351,7 @@ static struct snd_kcontrol_new mute_control = {
};
-static int onyx_snd_single_bit_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define onyx_snd_single_bit_info snd_ctl_boolean_mono_info
#define FLAG_POLARITY_INVERT 1
#define FLAG_SPDIFLOCK 2
diff --git a/sound/aoa/codecs/snd-aoa-codec-tas.c b/sound/aoa/codecs/snd-aoa-codec-tas.c
index 2f771f57c76f..70c341684794 100644
--- a/sound/aoa/codecs/snd-aoa-codec-tas.c
+++ b/sound/aoa/codecs/snd-aoa-codec-tas.c
@@ -272,15 +272,7 @@ static struct snd_kcontrol_new volume_control = {
.put = tas_snd_vol_put,
};
-static int tas_snd_mute_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 2;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define tas_snd_mute_info snd_ctl_boolean_stereo_info
static int tas_snd_mute_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -431,15 +423,7 @@ static struct snd_kcontrol_new drc_range_control = {
.put = tas_snd_drc_range_put,
};
-static int tas_snd_drc_switch_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define tas_snd_drc_switch_info snd_ctl_boolean_mono_info
static int tas_snd_drc_switch_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -743,6 +727,7 @@ static int tas_switch_clock(struct codec_info_item *cii, enum clock_switch clock
return 0;
}
+#ifdef CONFIG_PM
/* we are controlled via i2c and assume that is always up
* If that wasn't the case, we'd have to suspend once
* our i2c device is suspended, and then take note of that! */
@@ -768,7 +753,6 @@ static int tas_resume(struct tas *tas)
return 0;
}
-#ifdef CONFIG_PM
static int _tas_suspend(struct codec_info_item *cii, pm_message_t state)
{
return tas_suspend(cii->codec_data);
@@ -778,7 +762,10 @@ static int _tas_resume(struct codec_info_item *cii)
{
return tas_resume(cii->codec_data);
}
-#endif
+#else /* CONFIG_PM */
+#define _tas_suspend NULL
+#define _tas_resume NULL
+#endif /* CONFIG_PM */
static struct codec_info tas_codec_info = {
.transfers = tas_transfers,
@@ -791,10 +778,8 @@ static struct codec_info tas_codec_info = {
.owner = THIS_MODULE,
.usable = tas_usable,
.switch_clock = tas_switch_clock,
-#ifdef CONFIG_PM
.suspend = _tas_suspend,
.resume = _tas_resume,
-#endif
};
static int tas_init_codec(struct aoa_codec *codec)
diff --git a/sound/aoa/fabrics/snd-aoa-fabric-layout.c b/sound/aoa/fabrics/snd-aoa-fabric-layout.c
index 98806283d1b2..8b2ba99d7f8a 100644
--- a/sound/aoa/fabrics/snd-aoa-fabric-layout.c
+++ b/sound/aoa/fabrics/snd-aoa-fabric-layout.c
@@ -582,15 +582,7 @@ static int layouts_list_items;
* make the fabric handle all the card stuff, etc... */
static struct layout_dev *layout_device;
-static int control_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define control_info snd_ctl_boolean_mono_info
#define AMP_CONTROL(n, description) \
static int n##_control_get(struct snd_kcontrol *kcontrol, \
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c
index b9eca9f3dd25..3b73ba7d03e8 100644
--- a/sound/arm/aaci.c
+++ b/sound/arm/aaci.c
@@ -209,7 +209,7 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask)
void *ptr;
if (!aacirun->substream || !aacirun->start) {
- dev_warn(&aaci->dev->dev, "RX interrupt???");
+ dev_warn(&aaci->dev->dev, "RX interrupt???\n");
writel(0, aacirun->base + AACI_IE);
return;
}
@@ -263,7 +263,7 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask)
void *ptr;
if (!aacirun->substream || !aacirun->start) {
- dev_warn(&aaci->dev->dev, "TX interrupt???");
+ dev_warn(&aaci->dev->dev, "TX interrupt???\n");
writel(0, aacirun->base + AACI_IE);
return;
}
diff --git a/sound/arm/sa11xx-uda1341.c b/sound/arm/sa11xx-uda1341.c
index e7ed868fa7c0..81c64b09d359 100644
--- a/sound/arm/sa11xx-uda1341.c
+++ b/sound/arm/sa11xx-uda1341.c
@@ -79,12 +79,6 @@
#include <asm/mach-types.h>
#include <asm/dma.h>
-#ifdef CONFIG_H3600_HAL
-#include <asm/semaphore.h>
-#include <asm/uaccess.h>
-#include <asm/arch/h3600_hal.h>
-#endif
-
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/initval.h>
@@ -100,9 +94,6 @@
* We use DMA stuff from 2.4.18-rmk3-hh24 here to be able to compile this
* module for Familiar 0.6.1
*/
-#ifdef CONFIG_H3600_HAL
-#define HH_VERSION 1
-#endif
/* {{{ Type definitions */
@@ -238,11 +229,8 @@ static void sa11xx_uda1341_set_samplerate(struct sa11xx_uda1341 *sa11xx_uda1341,
rate = 8000;
/* Set the external clock generator */
-#ifdef CONFIG_H3600_HAL
- h3600_audio_clock(rate);
-#else
+
sa11xx_uda1341_set_audio_clock(rate);
-#endif
/* Select the clock divisor */
switch (rate) {
@@ -307,13 +295,10 @@ static void sa11xx_uda1341_audio_init(struct sa11xx_uda1341 *sa11xx_uda1341)
local_irq_restore(flags);
/* Enable the audio power */
-#ifdef CONFIG_H3600_HAL
- h3600_audio_power(AUDIO_RATE_DEFAULT);
-#else
+
clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_CODEC_NRESET);
set_sa11xx_uda1341_egpio(IPAQ_EGPIO_AUDIO_ON);
set_sa11xx_uda1341_egpio(IPAQ_EGPIO_QMUTE);
-#endif
/* Wait for the UDA1341 to wake up */
mdelay(1); //FIXME - was removed by Perex - Why?
@@ -331,21 +316,13 @@ static void sa11xx_uda1341_audio_init(struct sa11xx_uda1341 *sa11xx_uda1341)
/* make the left and right channels unswapped (flip the WS latch) */
Ser4SSDR = 0;
-#ifdef CONFIG_H3600_HAL
- h3600_audio_mute(0);
-#else
- clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_QMUTE);
-#endif
+ clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_QMUTE);
}
static void sa11xx_uda1341_audio_shutdown(struct sa11xx_uda1341 *sa11xx_uda1341)
{
/* mute on */
-#ifdef CONFIG_H3600_HAL
- h3600_audio_mute(1);
-#else
set_sa11xx_uda1341_egpio(IPAQ_EGPIO_QMUTE);
-#endif
/* disable the audio power and all signals leading to the audio chip */
l3_close(sa11xx_uda1341->uda1341);
@@ -354,13 +331,9 @@ static void sa11xx_uda1341_audio_shutdown(struct sa11xx_uda1341 *sa11xx_uda1341)
/* power off and mute off */
/* FIXME - is muting off necesary??? */
-#ifdef CONFIG_H3600_HAL
- h3600_audio_power(0);
- h3600_audio_mute(0);
-#else
+
clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_AUDIO_ON);
clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_QMUTE);
-#endif
}
/* }}} */
diff --git a/sound/core/Makefile b/sound/core/Makefile
index 5a01c76d02e8..267039a97bd5 100644
--- a/sound/core/Makefile
+++ b/sound/core/Makefile
@@ -1,20 +1,17 @@
#
# Makefile for ALSA
-# Copyright (c) 1999,2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 1999,2001 by Jaroslav Kysela <perex@perex.cz>
#
-snd-objs := sound.o init.o memory.o info.o control.o misc.o device.o
-ifeq ($(CONFIG_ISA_DMA_API),y)
-snd-objs += isadma.o
-endif
-ifeq ($(CONFIG_SND_OSSEMUL),y)
-snd-objs += sound_oss.o info_oss.o
-endif
+snd-y := sound.o init.o memory.o info.o control.o misc.o device.o
+snd-$(CONFIG_ISA_DMA_API) += isadma.o
+snd-$(CONFIG_SND_OSSEMUL) += sound_oss.o info_oss.o
snd-pcm-objs := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \
pcm_memory.o
-snd-page-alloc-objs := memalloc.o sgbuf.o
+snd-page-alloc-y := memalloc.o
+snd-page-alloc-$(CONFIG_HAS_DMA) += sgbuf.o
snd-rawmidi-objs := rawmidi.o
snd-timer-objs := timer.o
diff --git a/sound/core/control.c b/sound/core/control.c
index 1f1ab9c1b668..df0774c76f6f 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -1,6 +1,6 @@
/*
* Routines for driver control interface
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -93,15 +93,16 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
static void snd_ctl_empty_read_queue(struct snd_ctl_file * ctl)
{
+ unsigned long flags;
struct snd_kctl_event *cread;
- spin_lock(&ctl->read_lock);
+ spin_lock_irqsave(&ctl->read_lock, flags);
while (!list_empty(&ctl->events)) {
cread = snd_kctl_event(ctl->events.next);
list_del(&cread->list);
kfree(cread);
}
- spin_unlock(&ctl->read_lock);
+ spin_unlock_irqrestore(&ctl->read_lock, flags);
}
static int snd_ctl_release(struct inode *inode, struct file *file)
@@ -716,8 +717,6 @@ int snd_ctl_elem_read(struct snd_card *card, struct snd_ctl_elem_value *control)
return result;
}
-EXPORT_SYMBOL(snd_ctl_elem_read);
-
static int snd_ctl_elem_read_user(struct snd_card *card,
struct snd_ctl_elem_value __user *_control)
{
@@ -781,8 +780,6 @@ int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
return result;
}
-EXPORT_SYMBOL(snd_ctl_elem_write);
-
static int snd_ctl_elem_write_user(struct snd_ctl_file *file,
struct snd_ctl_elem_value __user *_control)
{
@@ -1486,3 +1483,30 @@ int snd_ctl_create(struct snd_card *card)
snd_assert(card != NULL, return -ENXIO);
return snd_device_new(card, SNDRV_DEV_CONTROL, card, &ops);
}
+
+/*
+ * Frequently used control callbacks
+ */
+int snd_ctl_boolean_mono_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+ return 0;
+}
+
+EXPORT_SYMBOL(snd_ctl_boolean_mono_info);
+
+int snd_ctl_boolean_stereo_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = 2;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+ return 0;
+}
+
+EXPORT_SYMBOL(snd_ctl_boolean_stereo_info);
diff --git a/sound/core/device.c b/sound/core/device.c
index 5858b02b0b1d..ea1a0621eefb 100644
--- a/sound/core/device.c
+++ b/sound/core/device.c
@@ -1,6 +1,6 @@
/*
* Device management routines
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c
index 51ad95b7c894..bfd9d182b8a3 100644
--- a/sound/core/hwdep.c
+++ b/sound/core/hwdep.c
@@ -1,6 +1,6 @@
/*
* Hardware dependent layer
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -31,7 +31,7 @@
#include <sound/hwdep.h>
#include <sound/info.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Hardware dependent layer");
MODULE_LICENSE("GPL");
diff --git a/sound/core/info.c b/sound/core/info.c
index bf6dbf99528b..1ffd29bb4cd0 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -1,6 +1,6 @@
/*
* Information interface for ALSA driver
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/core/info_oss.c b/sound/core/info_oss.c
index a444bfe2cf74..435c9399f7a9 100644
--- a/sound/core/info_oss.c
+++ b/sound/core/info_oss.c
@@ -1,6 +1,6 @@
/*
* Information interface for ALSA driver
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/core/init.c b/sound/core/init.c
index f2fe35737186..2cb7099eb1e1 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -1,6 +1,6 @@
/*
* Initialization routines
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/core/isadma.c b/sound/core/isadma.c
index d52398727f0a..eb173cef4f05 100644
--- a/sound/core/isadma.c
+++ b/sound/core/isadma.c
@@ -1,6 +1,6 @@
/*
* ISA DMA support functions
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index 9b5656d8bcca..9b4992eab479 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Takashi Iwai <tiwai@suse.de>
*
* Generic memory allocators
@@ -38,7 +38,7 @@
#endif
-MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>, Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>, Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Memory allocator for ALSA system.");
MODULE_LICENSE("GPL");
@@ -206,6 +206,7 @@ void snd_free_pages(void *ptr, size_t size)
*
*/
+#ifdef CONFIG_HAS_DMA
/* allocate the coherent DMA pages */
static void *snd_malloc_dev_pages(struct device *dev, size_t size, dma_addr_t *dma)
{
@@ -239,6 +240,7 @@ static void snd_free_dev_pages(struct device *dev, size_t size, void *ptr,
dec_snd_pages(pg);
dma_free_coherent(dev, PAGE_SIZE << pg, ptr, dma);
}
+#endif /* CONFIG_HAS_DMA */
#ifdef CONFIG_SBUS
@@ -312,12 +314,14 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size,
dmab->area = snd_malloc_sbus_pages(device, size, &dmab->addr);
break;
#endif
+#ifdef CONFIG_HAS_DMA
case SNDRV_DMA_TYPE_DEV:
dmab->area = snd_malloc_dev_pages(device, size, &dmab->addr);
break;
case SNDRV_DMA_TYPE_DEV_SG:
snd_malloc_sgbuf_pages(device, size, dmab, NULL);
break;
+#endif
default:
printk(KERN_ERR "snd-malloc: invalid device type %d\n", type);
dmab->area = NULL;
@@ -383,12 +387,14 @@ void snd_dma_free_pages(struct snd_dma_buffer *dmab)
snd_free_sbus_pages(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr);
break;
#endif
+#ifdef CONFIG_HAS_DMA
case SNDRV_DMA_TYPE_DEV:
snd_free_dev_pages(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr);
break;
case SNDRV_DMA_TYPE_DEV_SG:
snd_free_sgbuf_pages(dmab);
break;
+#endif
default:
printk(KERN_ERR "snd-malloc: invalid device type %d\n", dmab->dev.type);
}
diff --git a/sound/core/memory.c b/sound/core/memory.c
index 93537ab7c2ac..25b0f056563e 100644
--- a/sound/core/memory.c
+++ b/sound/core/memory.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
* Misc memory accessors
*
diff --git a/sound/core/misc.c b/sound/core/misc.c
index f78cd000e88d..6cabab8cc537 100644
--- a/sound/core/misc.c
+++ b/sound/core/misc.c
@@ -1,6 +1,6 @@
/*
* Misc and compatibility things
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/core/oss/Makefile b/sound/core/oss/Makefile
index e6d5a045ba27..10a79453245f 100644
--- a/sound/core/oss/Makefile
+++ b/sound/core/oss/Makefile
@@ -1,12 +1,13 @@
#
# Makefile for ALSA
-# Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
#
snd-mixer-oss-objs := mixer_oss.o
-snd-pcm-oss-objs := pcm_oss.o pcm_plugin.o \
- io.o copy.o linear.o mulaw.o route.o rate.o
+snd-pcm-oss-y := pcm_oss.o
+snd-pcm-oss-$(CONFIG_SND_PCM_OSS_PLUGINS) += pcm_plugin.o \
+ io.o copy.o linear.o mulaw.o route.o rate.o
obj-$(CONFIG_SND_MIXER_OSS) += snd-mixer-oss.o
obj-$(CONFIG_SND_PCM_OSS) += snd-pcm-oss.o
diff --git a/sound/core/oss/copy.c b/sound/core/oss/copy.c
index 6658facc5cda..d6a04c2d5a75 100644
--- a/sound/core/oss/copy.c
+++ b/sound/core/oss/copy.c
@@ -20,9 +20,6 @@
*/
#include <sound/driver.h>
-
-#ifdef CONFIG_SND_PCM_OSS_PLUGINS
-
#include <linux/time.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -88,5 +85,3 @@ int snd_pcm_plugin_build_copy(struct snd_pcm_substream *plug,
*r_plugin = plugin;
return 0;
}
-
-#endif
diff --git a/sound/core/oss/io.c b/sound/core/oss/io.c
index b6e7ce30e5a3..3ece39fc48db 100644
--- a/sound/core/oss/io.c
+++ b/sound/core/oss/io.c
@@ -1,6 +1,6 @@
/*
* PCM I/O Plug-In Interface
- * Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
*
*
* This library is free software; you can redistribute it and/or modify
@@ -20,9 +20,6 @@
*/
#include <sound/driver.h>
-
-#ifdef CONFIG_SND_PCM_OSS_PLUGINS
-
#include <linux/time.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -135,5 +132,3 @@ int snd_pcm_plugin_build_io(struct snd_pcm_substream *plug,
*r_plugin = plugin;
return 0;
}
-
-#endif
diff --git a/sound/core/oss/linear.c b/sound/core/oss/linear.c
index 5b1bcdc64779..06f96a3e86f6 100644
--- a/sound/core/oss/linear.c
+++ b/sound/core/oss/linear.c
@@ -1,6 +1,6 @@
/*
* Linear conversion Plug-In
- * Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz>,
+ * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>,
* Abramo Bagnara <abramo@alsa-project.org>
*
*
@@ -21,9 +21,6 @@
*/
#include <sound/driver.h>
-
-#ifdef CONFIG_SND_PCM_OSS_PLUGINS
-
#include <linux/time.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -34,19 +31,34 @@
*/
struct linear_priv {
- int conv;
+ int cvt_endian; /* need endian conversion? */
+ unsigned int src_ofs; /* byte offset in source format */
+ unsigned int dst_ofs; /* byte soffset in destination format */
+ unsigned int copy_ofs; /* byte offset in temporary u32 data */
+ unsigned int dst_bytes; /* byte size of destination format */
+ unsigned int copy_bytes; /* bytes to copy per conversion */
+ unsigned int flip; /* MSB flip for signeness, done after endian conv */
};
+static inline void do_convert(struct linear_priv *data,
+ unsigned char *dst, unsigned char *src)
+{
+ unsigned int tmp = 0;
+ unsigned char *p = (unsigned char *)&tmp;
+
+ memcpy(p + data->copy_ofs, src + data->src_ofs, data->copy_bytes);
+ if (data->cvt_endian)
+ tmp = swab32(tmp);
+ tmp ^= data->flip;
+ memcpy(dst, p + data->dst_ofs, data->dst_bytes);
+}
+
static void convert(struct snd_pcm_plugin *plugin,
const struct snd_pcm_plugin_channel *src_channels,
struct snd_pcm_plugin_channel *dst_channels,
snd_pcm_uframes_t frames)
{
-#define CONV_LABELS
-#include "plugin_ops.h"
-#undef CONV_LABELS
struct linear_priv *data = (struct linear_priv *)plugin->extra_data;
- void *conv = conv_labels[data->conv];
int channel;
int nchannels = plugin->src_format.channels;
for (channel = 0; channel < nchannels; ++channel) {
@@ -67,11 +79,7 @@ static void convert(struct snd_pcm_plugin *plugin,
dst_step = dst_channels[channel].area.step / 8;
frames1 = frames;
while (frames1-- > 0) {
- goto *conv;
-#define CONV_END after
-#include "plugin_ops.h"
-#undef CONV_END
- after:
+ do_convert(data, dst, src);
src += src_step;
dst += dst_step;
}
@@ -106,29 +114,36 @@ static snd_pcm_sframes_t linear_transfer(struct snd_pcm_plugin *plugin,
return frames;
}
-static int conv_index(int src_format, int dst_format)
+static void init_data(struct linear_priv *data, int src_format, int dst_format)
{
- int src_endian, dst_endian, sign, src_width, dst_width;
-
- sign = (snd_pcm_format_signed(src_format) !=
- snd_pcm_format_signed(dst_format));
-#ifdef SNDRV_LITTLE_ENDIAN
- src_endian = snd_pcm_format_big_endian(src_format);
- dst_endian = snd_pcm_format_big_endian(dst_format);
-#else
- src_endian = snd_pcm_format_little_endian(src_format);
- dst_endian = snd_pcm_format_little_endian(dst_format);
-#endif
-
- if (src_endian < 0)
- src_endian = 0;
- if (dst_endian < 0)
- dst_endian = 0;
-
- src_width = snd_pcm_format_width(src_format) / 8 - 1;
- dst_width = snd_pcm_format_width(dst_format) / 8 - 1;
-
- return src_width * 32 + src_endian * 16 + sign * 8 + dst_width * 2 + dst_endian;
+ int src_le, dst_le, src_bytes, dst_bytes;
+
+ src_bytes = snd_pcm_format_width(src_format) / 8;
+ dst_bytes = snd_pcm_format_width(dst_format) / 8;
+ src_le = snd_pcm_format_little_endian(src_format) > 0;
+ dst_le = snd_pcm_format_little_endian(dst_format) > 0;
+
+ data->dst_bytes = dst_bytes;
+ data->cvt_endian = src_le != dst_le;
+ data->copy_bytes = src_bytes < dst_bytes ? src_bytes : dst_bytes;
+ if (src_le) {
+ data->copy_ofs = 4 - data->copy_bytes;
+ data->src_ofs = src_bytes - data->copy_bytes;
+ } else
+ data->src_ofs = snd_pcm_format_physical_width(src_format) / 8 -
+ src_bytes;
+ if (dst_le)
+ data->dst_ofs = 4 - data->dst_bytes;
+ else
+ data->dst_ofs = snd_pcm_format_physical_width(dst_format) / 8 -
+ dst_bytes;
+ if (snd_pcm_format_signed(src_format) !=
+ snd_pcm_format_signed(dst_format)) {
+ if (dst_le)
+ data->flip = cpu_to_le32(0x80000000);
+ else
+ data->flip = cpu_to_be32(0x80000000);
+ }
}
int snd_pcm_plugin_build_linear(struct snd_pcm_substream *plug,
@@ -154,10 +169,8 @@ int snd_pcm_plugin_build_linear(struct snd_pcm_substream *plug,
if (err < 0)
return err;
data = (struct linear_priv *)plugin->extra_data;
- data->conv = conv_index(src_format->format, dst_format->format);
+ init_data(data, src_format->format, dst_format->format);
plugin->transfer = linear_transfer;
*r_plugin = plugin;
return 0;
}
-
-#endif
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index fccad8f0a6bb..3ace4a5680ba 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -1,6 +1,6 @@
/*
* OSS emulation layer for the mixer interface
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -33,7 +33,7 @@
#define OSS_ALSAEMULVER _SIOR ('M', 249, int)
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Mixer OSS emulation for ALSA.");
MODULE_LICENSE("GPL");
MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_MIXER);
diff --git a/sound/core/oss/mulaw.c b/sound/core/oss/mulaw.c
index 2eb18807e6d0..848db82529ed 100644
--- a/sound/core/oss/mulaw.c
+++ b/sound/core/oss/mulaw.c
@@ -1,6 +1,6 @@
/*
* Mu-Law conversion Plug-In Interface
- * Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
* Uros Bizjak <uros@kss-loka.si>
*
* Based on reference implementation by Sun Microsystems, Inc.
@@ -22,9 +22,6 @@
*/
#include <sound/driver.h>
-
-#ifdef CONFIG_SND_PCM_OSS_PLUGINS
-
#include <linux/time.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -149,19 +146,32 @@ typedef void (*mulaw_f)(struct snd_pcm_plugin *plugin,
struct mulaw_priv {
mulaw_f func;
- int conv;
+ int cvt_endian; /* need endian conversion? */
+ unsigned int native_ofs; /* byte offset in native format */
+ unsigned int copy_ofs; /* byte offset in s16 format */
+ unsigned int native_bytes; /* byte size of the native format */
+ unsigned int copy_bytes; /* bytes to copy per conversion */
+ u16 flip; /* MSB flip for signedness, done after endian conversion */
};
+static inline void cvt_s16_to_native(struct mulaw_priv *data,
+ unsigned char *dst, u16 sample)
+{
+ sample ^= data->flip;
+ if (data->cvt_endian)
+ sample = swab16(sample);
+ if (data->native_bytes > data->copy_bytes)
+ memset(dst, 0, data->native_bytes);
+ memcpy(dst + data->native_ofs, (char *)&sample + data->copy_ofs,
+ data->copy_bytes);
+}
+
static void mulaw_decode(struct snd_pcm_plugin *plugin,
const struct snd_pcm_plugin_channel *src_channels,
struct snd_pcm_plugin_channel *dst_channels,
snd_pcm_uframes_t frames)
{
-#define PUT_S16_LABELS
-#include "plugin_ops.h"
-#undef PUT_S16_LABELS
struct mulaw_priv *data = (struct mulaw_priv *)plugin->extra_data;
- void *put = put_s16_labels[data->conv];
int channel;
int nchannels = plugin->src_format.channels;
for (channel = 0; channel < nchannels; ++channel) {
@@ -183,30 +193,33 @@ static void mulaw_decode(struct snd_pcm_plugin *plugin,
frames1 = frames;
while (frames1-- > 0) {
signed short sample = ulaw2linear(*src);
- goto *put;
-#define PUT_S16_END after
-#include "plugin_ops.h"
-#undef PUT_S16_END
- after:
+ cvt_s16_to_native(data, dst, sample);
src += src_step;
dst += dst_step;
}
}
}
+static inline signed short cvt_native_to_s16(struct mulaw_priv *data,
+ unsigned char *src)
+{
+ u16 sample = 0;
+ memcpy((char *)&sample + data->copy_ofs, src + data->native_ofs,
+ data->copy_bytes);
+ if (data->cvt_endian)
+ sample = swab16(sample);
+ sample ^= data->flip;
+ return (signed short)sample;
+}
+
static void mulaw_encode(struct snd_pcm_plugin *plugin,
const struct snd_pcm_plugin_channel *src_channels,
struct snd_pcm_plugin_channel *dst_channels,
snd_pcm_uframes_t frames)
{
-#define GET_S16_LABELS
-#include "plugin_ops.h"
-#undef GET_S16_LABELS
struct mulaw_priv *data = (struct mulaw_priv *)plugin->extra_data;
- void *get = get_s16_labels[data->conv];
int channel;
int nchannels = plugin->src_format.channels;
- signed short sample = 0;
for (channel = 0; channel < nchannels; ++channel) {
char *src;
char *dst;
@@ -225,11 +238,7 @@ static void mulaw_encode(struct snd_pcm_plugin *plugin,
dst_step = dst_channels[channel].area.step / 8;
frames1 = frames;
while (frames1-- > 0) {
- goto *get;
-#define GET_S16_END after
-#include "plugin_ops.h"
-#undef GET_S16_END
- after:
+ signed short sample = cvt_native_to_s16(data, src);
*dst = linear2ulaw(sample);
src += src_step;
dst += dst_step;
@@ -265,23 +274,25 @@ static snd_pcm_sframes_t mulaw_transfer(struct snd_pcm_plugin *plugin,
return frames;
}
-static int getput_index(int format)
+static void init_data(struct mulaw_priv *data, int format)
{
- int sign, width, endian;
- sign = !snd_pcm_format_signed(format);
- width = snd_pcm_format_width(format) / 8 - 1;
- if (width < 0 || width > 3) {
- snd_printk(KERN_ERR "snd-pcm-oss: invalid format %d\n", format);
- width = 0;
- }
#ifdef SNDRV_LITTLE_ENDIAN
- endian = snd_pcm_format_big_endian(format);
+ data->cvt_endian = snd_pcm_format_big_endian(format) > 0;
#else
- endian = snd_pcm_format_little_endian(format);
+ data->cvt_endian = snd_pcm_format_little_endian(format) > 0;
#endif
- if (endian < 0)
- endian = 0;
- return width * 4 + endian * 2 + sign;
+ if (!snd_pcm_format_signed(format))
+ data->flip = 0x8000;
+ data->native_bytes = snd_pcm_format_physical_width(format) / 8;
+ data->copy_bytes = data->native_bytes < 2 ? 1 : 2;
+ if (snd_pcm_format_little_endian(format)) {
+ data->native_ofs = data->native_bytes - data->copy_bytes;
+ data->copy_ofs = 2 - data->copy_bytes;
+ } else {
+ /* S24 in 4bytes need an 1 byte offset */
+ data->native_ofs = data->native_bytes -
+ snd_pcm_format_width(format) / 8;
+ }
}
int snd_pcm_plugin_build_mulaw(struct snd_pcm_substream *plug,
@@ -322,11 +333,8 @@ int snd_pcm_plugin_build_mulaw(struct snd_pcm_substream *plug,
return err;
data = (struct mulaw_priv *)plugin->extra_data;
data->func = func;
- data->conv = getput_index(format->format);
- snd_assert(data->conv >= 0 && data->conv < 4*2*2, return -EINVAL);
+ init_data(data, format->format);
plugin->transfer = mulaw_transfer;
*r_plugin = plugin;
return 0;
}
-
-#endif
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index fc11572c48cf..d0c4ceb9f0b4 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -1,6 +1,6 @@
/*
* Digital Audio (PCM) abstract layer / OSS compatible
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -48,7 +48,7 @@ static int dsp_map[SNDRV_CARDS];
static int adsp_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1};
static int nonblock_open = 1;
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Abramo Bagnara <abramo@alsa-project.org>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Abramo Bagnara <abramo@alsa-project.org>");
MODULE_DESCRIPTION("PCM OSS emulation for ALSA.");
MODULE_LICENSE("GPL");
module_param_array(dsp_map, int, NULL, 0444);
@@ -633,6 +633,22 @@ static long snd_pcm_alsa_frames(struct snd_pcm_substream *substream, long bytes)
return bytes_to_frames(runtime, (buffer_size * bytes) / runtime->oss.buffer_bytes);
}
+/* define extended formats in the recent OSS versions (if any) */
+/* linear formats */
+#define AFMT_S32_LE 0x00001000
+#define AFMT_S32_BE 0x00002000
+#define AFMT_S24_LE 0x00008000
+#define AFMT_S24_BE 0x00010000
+#define AFMT_S24_PACKED 0x00040000
+
+/* other supported formats */
+#define AFMT_FLOAT 0x00004000
+#define AFMT_SPDIF_RAW 0x00020000
+
+/* unsupported formats */
+#define AFMT_AC3 0x00000400
+#define AFMT_VORBIS 0x00000800
+
static int snd_pcm_oss_format_from(int format)
{
switch (format) {
@@ -646,6 +662,13 @@ static int snd_pcm_oss_format_from(int format)
case AFMT_U16_LE: return SNDRV_PCM_FORMAT_U16_LE;
case AFMT_U16_BE: return SNDRV_PCM_FORMAT_U16_BE;
case AFMT_MPEG: return SNDRV_PCM_FORMAT_MPEG;
+ case AFMT_S32_LE: return SNDRV_PCM_FORMAT_S32_LE;
+ case AFMT_S32_BE: return SNDRV_PCM_FORMAT_S32_BE;
+ case AFMT_S24_LE: return SNDRV_PCM_FORMAT_S24_LE;
+ case AFMT_S24_BE: return SNDRV_PCM_FORMAT_S24_BE;
+ case AFMT_S24_PACKED: return SNDRV_PCM_FORMAT_S24_3LE;
+ case AFMT_FLOAT: return SNDRV_PCM_FORMAT_FLOAT;
+ case AFMT_SPDIF_RAW: return SNDRV_PCM_FORMAT_IEC958_SUBFRAME;
default: return SNDRV_PCM_FORMAT_U8;
}
}
@@ -663,6 +686,13 @@ static int snd_pcm_oss_format_to(int format)
case SNDRV_PCM_FORMAT_U16_LE: return AFMT_U16_LE;
case SNDRV_PCM_FORMAT_U16_BE: return AFMT_U16_BE;
case SNDRV_PCM_FORMAT_MPEG: return AFMT_MPEG;
+ case SNDRV_PCM_FORMAT_S32_LE: return AFMT_S32_LE;
+ case SNDRV_PCM_FORMAT_S32_BE: return AFMT_S32_BE;
+ case SNDRV_PCM_FORMAT_S24_LE: return AFMT_S24_LE;
+ case SNDRV_PCM_FORMAT_S24_BE: return AFMT_S24_BE;
+ case SNDRV_PCM_FORMAT_S24_3LE: return AFMT_S24_PACKED;
+ case SNDRV_PCM_FORMAT_FLOAT: return AFMT_FLOAT;
+ case SNDRV_PCM_FORMAT_IEC958_SUBFRAME: return AFMT_SPDIF_RAW;
default: return -EINVAL;
}
}
@@ -1725,7 +1755,10 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file)
return AFMT_MU_LAW | AFMT_U8 |
AFMT_S16_LE | AFMT_S16_BE |
AFMT_S8 | AFMT_U16_LE |
- AFMT_U16_BE;
+ AFMT_U16_BE |
+ AFMT_S32_LE | AFMT_S32_BE |
+ AFMT_S24_LE | AFMT_S24_LE |
+ AFMT_S24_PACKED;
params = kmalloc(sizeof(*params), GFP_KERNEL);
if (!params)
return -ENOMEM;
diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c
index 0e67dd280a5d..14095a927a1b 100644
--- a/sound/core/oss/pcm_plugin.c
+++ b/sound/core/oss/pcm_plugin.c
@@ -1,6 +1,6 @@
/*
* PCM Plug-In shared (kernel/library) code
- * Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
* Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
*
*
@@ -25,9 +25,6 @@
#endif
#include <sound/driver.h>
-
-#ifdef CONFIG_SND_PCM_OSS_PLUGINS
-
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/vmalloc.h>
@@ -267,6 +264,8 @@ static int snd_pcm_plug_formats(struct snd_mask *mask, int format)
SNDRV_PCM_FMTBIT_U16_BE | SNDRV_PCM_FMTBIT_S16_BE |
SNDRV_PCM_FMTBIT_U24_LE | SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_U24_BE | SNDRV_PCM_FMTBIT_S24_BE |
+ SNDRV_PCM_FMTBIT_U24_3LE | SNDRV_PCM_FMTBIT_S24_3LE |
+ SNDRV_PCM_FMTBIT_U24_3BE | SNDRV_PCM_FMTBIT_S24_3BE |
SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_S32_LE |
SNDRV_PCM_FMTBIT_U32_BE | SNDRV_PCM_FMTBIT_S32_BE);
snd_mask_set(&formats, SNDRV_PCM_FORMAT_MU_LAW);
@@ -283,6 +282,10 @@ static int preferred_formats[] = {
SNDRV_PCM_FORMAT_S16_BE,
SNDRV_PCM_FORMAT_U16_LE,
SNDRV_PCM_FORMAT_U16_BE,
+ SNDRV_PCM_FORMAT_S24_3LE,
+ SNDRV_PCM_FORMAT_S24_3BE,
+ SNDRV_PCM_FORMAT_U24_3LE,
+ SNDRV_PCM_FORMAT_U24_3BE,
SNDRV_PCM_FORMAT_S24_LE,
SNDRV_PCM_FORMAT_S24_BE,
SNDRV_PCM_FORMAT_U24_LE,
@@ -297,41 +300,37 @@ static int preferred_formats[] = {
int snd_pcm_plug_slave_format(int format, struct snd_mask *format_mask)
{
+ int i;
+
if (snd_mask_test(format_mask, format))
return format;
if (! snd_pcm_plug_formats(format_mask, format))
return -EINVAL;
if (snd_pcm_format_linear(format)) {
- int width = snd_pcm_format_width(format);
- int unsignd = snd_pcm_format_unsigned(format);
- int big = snd_pcm_format_big_endian(format);
- int format1;
- int wid, width1=width;
- int dwidth1 = 8;
- for (wid = 0; wid < 4; ++wid) {
- int end, big1 = big;
- for (end = 0; end < 2; ++end) {
- int sgn, unsignd1 = unsignd;
- for (sgn = 0; sgn < 2; ++sgn) {
- format1 = snd_pcm_build_linear_format(width1, unsignd1, big1);
- if (format1 >= 0 &&
- snd_mask_test(format_mask, format1))
- goto _found;
- unsignd1 = !unsignd1;
- }
- big1 = !big1;
- }
- if (width1 == 32) {
- dwidth1 = -dwidth1;
- width1 = width;
+ unsigned int width = snd_pcm_format_width(format);
+ int unsignd = snd_pcm_format_unsigned(format) > 0;
+ int big = snd_pcm_format_big_endian(format) > 0;
+ unsigned int badness, best = -1;
+ int best_format = -1;
+ for (i = 0; i < ARRAY_SIZE(preferred_formats); i++) {
+ int f = preferred_formats[i];
+ unsigned int w;
+ if (!snd_mask_test(format_mask, f))
+ continue;
+ w = snd_pcm_format_width(f);
+ if (w >= width)
+ badness = w - width;
+ else
+ badness = width - w + 32;
+ badness += snd_pcm_format_unsigned(f) != unsignd;
+ badness += snd_pcm_format_big_endian(f) != big;
+ if (badness < best) {
+ best_format = f;
+ best = badness;
}
- width1 += dwidth1;
}
- return -EINVAL;
- _found:
- return format1;
+ return best_format >= 0 ? best_format : -EINVAL;
} else {
- unsigned int i;
switch (format) {
case SNDRV_PCM_FORMAT_MU_LAW:
for (i = 0; i < ARRAY_SIZE(preferred_formats); ++i) {
@@ -740,5 +739,3 @@ int snd_pcm_area_copy(const struct snd_pcm_channel_area *src_area, size_t src_of
}
return 0;
}
-
-#endif
diff --git a/sound/core/oss/pcm_plugin.h b/sound/core/oss/pcm_plugin.h
index 3be91b3d5377..ca2f4c39be46 100644
--- a/sound/core/oss/pcm_plugin.h
+++ b/sound/core/oss/pcm_plugin.h
@@ -3,7 +3,7 @@
/*
* Digital Audio (Plugin interface) abstract layer
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/core/oss/plugin_ops.h b/sound/core/oss/plugin_ops.h
deleted file mode 100644
index 1f5bde4631f1..000000000000
--- a/sound/core/oss/plugin_ops.h
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * Plugin sample operators with fast switch
- * Copyright (c) 2000 by Jaroslav Kysela <perex@suse.cz>
- *
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Library General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-
-#define as_u8(ptr) (*(u_int8_t*)(ptr))
-#define as_u16(ptr) (*(u_int16_t*)(ptr))
-#define as_u32(ptr) (*(u_int32_t*)(ptr))
-#define as_u64(ptr) (*(u_int64_t*)(ptr))
-#define as_s8(ptr) (*(int8_t*)(ptr))
-#define as_s16(ptr) (*(int16_t*)(ptr))
-#define as_s32(ptr) (*(int32_t*)(ptr))
-#define as_s64(ptr) (*(int64_t*)(ptr))
-
-#ifdef COPY_LABELS
-static void *copy_labels[4] = {
- &&copy_8,
- &&copy_16,
- &&copy_32,
- &&copy_64
-};
-#endif
-
-#ifdef COPY_END
-while(0) {
-copy_8: as_s8(dst) = as_s8(src); goto COPY_END;
-copy_16: as_s16(dst) = as_s16(src); goto COPY_END;
-copy_32: as_s32(dst) = as_s32(src); goto COPY_END;
-copy_64: as_s64(dst) = as_s64(src); goto COPY_END;
-}
-#endif
-
-#ifdef CONV_LABELS
-/* src_wid src_endswap sign_toggle dst_wid dst_endswap */
-static void *conv_labels[4 * 2 * 2 * 4 * 2] = {
- &&conv_xxx1_xxx1, /* 8h -> 8h */
- &&conv_xxx1_xxx1, /* 8h -> 8s */
- &&conv_xxx1_xx10, /* 8h -> 16h */
- &&conv_xxx1_xx01, /* 8h -> 16s */
- &&conv_xxx1_x100, /* 8h -> 24h */
- &&conv_xxx1_001x, /* 8h -> 24s */
- &&conv_xxx1_1000, /* 8h -> 32h */
- &&conv_xxx1_0001, /* 8h -> 32s */
- &&conv_xxx1_xxx9, /* 8h ^> 8h */
- &&conv_xxx1_xxx9, /* 8h ^> 8s */
- &&conv_xxx1_xx90, /* 8h ^> 16h */
- &&conv_xxx1_xx09, /* 8h ^> 16s */
- &&conv_xxx1_x900, /* 8h ^> 24h */
- &&conv_xxx1_009x, /* 8h ^> 24s */
- &&conv_xxx1_9000, /* 8h ^> 32h */
- &&conv_xxx1_0009, /* 8h ^> 32s */
- &&conv_xxx1_xxx1, /* 8s -> 8h */
- &&conv_xxx1_xxx1, /* 8s -> 8s */
- &&conv_xxx1_xx10, /* 8s -> 16h */
- &&conv_xxx1_xx01, /* 8s -> 16s */
- &&conv_xxx1_x100, /* 8s -> 24h */
- &&conv_xxx1_001x, /* 8s -> 24s */
- &&conv_xxx1_1000, /* 8s -> 32h */
- &&conv_xxx1_0001, /* 8s -> 32s */
- &&conv_xxx1_xxx9, /* 8s ^> 8h */
- &&conv_xxx1_xxx9, /* 8s ^> 8s */
- &&conv_xxx1_xx90, /* 8s ^> 16h */
- &&conv_xxx1_xx09, /* 8s ^> 16s */
- &&conv_xxx1_x900, /* 8s ^> 24h */
- &&conv_xxx1_009x, /* 8s ^> 24s */
- &&conv_xxx1_9000, /* 8s ^> 32h */
- &&conv_xxx1_0009, /* 8s ^> 32s */
- &&conv_xx12_xxx1, /* 16h -> 8h */
- &&conv_xx12_xxx1, /* 16h -> 8s */
- &&conv_xx12_xx12, /* 16h -> 16h */
- &&conv_xx12_xx21, /* 16h -> 16s */
- &&conv_xx12_x120, /* 16h -> 24h */
- &&conv_xx12_021x, /* 16h -> 24s */
- &&conv_xx12_1200, /* 16h -> 32h */
- &&conv_xx12_0021, /* 16h -> 32s */
- &&conv_xx12_xxx9, /* 16h ^> 8h */
- &&conv_xx12_xxx9, /* 16h ^> 8s */
- &&conv_xx12_xx92, /* 16h ^> 16h */
- &&conv_xx12_xx29, /* 16h ^> 16s */
- &&conv_xx12_x920, /* 16h ^> 24h */
- &&conv_xx12_029x, /* 16h ^> 24s */
- &&conv_xx12_9200, /* 16h ^> 32h */
- &&conv_xx12_0029, /* 16h ^> 32s */
- &&conv_xx12_xxx2, /* 16s -> 8h */
- &&conv_xx12_xxx2, /* 16s -> 8s */
- &&conv_xx12_xx21, /* 16s -> 16h */
- &&conv_xx12_xx12, /* 16s -> 16s */
- &&conv_xx12_x210, /* 16s -> 24h */
- &&conv_xx12_012x, /* 16s -> 24s */
- &&conv_xx12_2100, /* 16s -> 32h */
- &&conv_xx12_0012, /* 16s -> 32s */
- &&conv_xx12_xxxA, /* 16s ^> 8h */
- &&conv_xx12_xxxA, /* 16s ^> 8s */
- &&conv_xx12_xxA1, /* 16s ^> 16h */
- &&conv_xx12_xx1A, /* 16s ^> 16s */
- &&conv_xx12_xA10, /* 16s ^> 24h */
- &&conv_xx12_01Ax, /* 16s ^> 24s */
- &&conv_xx12_A100, /* 16s ^> 32h */
- &&conv_xx12_001A, /* 16s ^> 32s */
- &&conv_x123_xxx1, /* 24h -> 8h */
- &&conv_x123_xxx1, /* 24h -> 8s */
- &&conv_x123_xx12, /* 24h -> 16h */
- &&conv_x123_xx21, /* 24h -> 16s */
- &&conv_x123_x123, /* 24h -> 24h */
- &&conv_x123_321x, /* 24h -> 24s */
- &&conv_x123_1230, /* 24h -> 32h */
- &&conv_x123_0321, /* 24h -> 32s */
- &&conv_x123_xxx9, /* 24h ^> 8h */
- &&conv_x123_xxx9, /* 24h ^> 8s */
- &&conv_x123_xx92, /* 24h ^> 16h */
- &&conv_x123_xx29, /* 24h ^> 16s */
- &&conv_x123_x923, /* 24h ^> 24h */
- &&conv_x123_329x, /* 24h ^> 24s */
- &&conv_x123_9230, /* 24h ^> 32h */
- &&conv_x123_0329, /* 24h ^> 32s */
- &&conv_123x_xxx3, /* 24s -> 8h */
- &&conv_123x_xxx3, /* 24s -> 8s */
- &&conv_123x_xx32, /* 24s -> 16h */
- &&conv_123x_xx23, /* 24s -> 16s */
- &&conv_123x_x321, /* 24s -> 24h */
- &&conv_123x_123x, /* 24s -> 24s */
- &&conv_123x_3210, /* 24s -> 32h */
- &&conv_123x_0123, /* 24s -> 32s */
- &&conv_123x_xxxB, /* 24s ^> 8h */
- &&conv_123x_xxxB, /* 24s ^> 8s */
- &&conv_123x_xxB2, /* 24s ^> 16h */
- &&conv_123x_xx2B, /* 24s ^> 16s */
- &&conv_123x_xB21, /* 24s ^> 24h */
- &&conv_123x_12Bx, /* 24s ^> 24s */
- &&conv_123x_B210, /* 24s ^> 32h */
- &&conv_123x_012B, /* 24s ^> 32s */
- &&conv_1234_xxx1, /* 32h -> 8h */
- &&conv_1234_xxx1, /* 32h -> 8s */
- &&conv_1234_xx12, /* 32h -> 16h */
- &&conv_1234_xx21, /* 32h -> 16s */
- &&conv_1234_x123, /* 32h -> 24h */
- &&conv_1234_321x, /* 32h -> 24s */
- &&conv_1234_1234, /* 32h -> 32h */
- &&conv_1234_4321, /* 32h -> 32s */
- &&conv_1234_xxx9, /* 32h ^> 8h */
- &&conv_1234_xxx9, /* 32h ^> 8s */
- &&conv_1234_xx92, /* 32h ^> 16h */
- &&conv_1234_xx29, /* 32h ^> 16s */
- &&conv_1234_x923, /* 32h ^> 24h */
- &&conv_1234_329x, /* 32h ^> 24s */
- &&conv_1234_9234, /* 32h ^> 32h */
- &&conv_1234_4329, /* 32h ^> 32s */
- &&conv_1234_xxx4, /* 32s -> 8h */
- &&conv_1234_xxx4, /* 32s -> 8s */
- &&conv_1234_xx43, /* 32s -> 16h */
- &&conv_1234_xx34, /* 32s -> 16s */
- &&conv_1234_x432, /* 32s -> 24h */
- &&conv_1234_234x, /* 32s -> 24s */
- &&conv_1234_4321, /* 32s -> 32h */
- &&conv_1234_1234, /* 32s -> 32s */
- &&conv_1234_xxxC, /* 32s ^> 8h */
- &&conv_1234_xxxC, /* 32s ^> 8s */
- &&conv_1234_xxC3, /* 32s ^> 16h */
- &&conv_1234_xx3C, /* 32s ^> 16s */
- &&conv_1234_xC32, /* 32s ^> 24h */
- &&conv_1234_23Cx, /* 32s ^> 24s */
- &&conv_1234_C321, /* 32s ^> 32h */
- &&conv_1234_123C, /* 32s ^> 32s */
-};
-#endif
-
-#ifdef CONV_END
-while(0) {
-conv_xxx1_xxx1: as_u8(dst) = as_u8(src); goto CONV_END;
-conv_xxx1_xx10: as_u16(dst) = (u_int16_t)as_u8(src) << 8; goto CONV_END;
-conv_xxx1_xx01: as_u16(dst) = (u_int16_t)as_u8(src); goto CONV_END;
-conv_xxx1_x100: as_u32(dst) = (u_int32_t)as_u8(src) << 16; goto CONV_END;
-conv_xxx1_001x: as_u32(dst) = (u_int32_t)as_u8(src) << 8; goto CONV_END;
-conv_xxx1_1000: as_u32(dst) = (u_int32_t)as_u8(src) << 24; goto CONV_END;
-conv_xxx1_0001: as_u32(dst) = (u_int32_t)as_u8(src); goto CONV_END;
-conv_xxx1_xxx9: as_u8(dst) = as_u8(src) ^ 0x80; goto CONV_END;
-conv_xxx1_xx90: as_u16(dst) = (u_int16_t)(as_u8(src) ^ 0x80) << 8; goto CONV_END;
-conv_xxx1_xx09: as_u16(dst) = (u_int16_t)(as_u8(src) ^ 0x80); goto CONV_END;
-conv_xxx1_x900: as_u32(dst) = (u_int32_t)(as_u8(src) ^ 0x80) << 16; goto CONV_END;
-conv_xxx1_009x: as_u32(dst) = (u_int32_t)(as_u8(src) ^ 0x80) << 8; goto CONV_END;
-conv_xxx1_9000: as_u32(dst) = (u_int32_t)(as_u8(src) ^ 0x80) << 24; goto CONV_END;
-conv_xxx1_0009: as_u32(dst) = (u_int32_t)(as_u8(src) ^ 0x80); goto CONV_END;
-conv_xx12_xxx1: as_u8(dst) = as_u16(src) >> 8; goto CONV_END;
-conv_xx12_xx12: as_u16(dst) = as_u16(src); goto CONV_END;
-conv_xx12_xx21: as_u16(dst) = swab16(as_u16(src)); goto CONV_END;
-conv_xx12_x120: as_u32(dst) = (u_int32_t)as_u16(src) << 8; goto CONV_END;
-conv_xx12_021x: as_u32(dst) = (u_int32_t)swab16(as_u16(src)) << 8; goto CONV_END;
-conv_xx12_1200: as_u32(dst) = (u_int32_t)as_u16(src) << 16; goto CONV_END;
-conv_xx12_0021: as_u32(dst) = (u_int32_t)swab16(as_u16(src)); goto CONV_END;
-conv_xx12_xxx9: as_u8(dst) = (as_u16(src) >> 8) ^ 0x80; goto CONV_END;
-conv_xx12_xx92: as_u16(dst) = as_u16(src) ^ 0x8000; goto CONV_END;
-conv_xx12_xx29: as_u16(dst) = swab16(as_u16(src)) ^ 0x80; goto CONV_END;
-conv_xx12_x920: as_u32(dst) = (u_int32_t)(as_u16(src) ^ 0x8000) << 8; goto CONV_END;
-conv_xx12_029x: as_u32(dst) = (u_int32_t)(swab16(as_u16(src)) ^ 0x80) << 8; goto CONV_END;
-conv_xx12_9200: as_u32(dst) = (u_int32_t)(as_u16(src) ^ 0x8000) << 16; goto CONV_END;
-conv_xx12_0029: as_u32(dst) = (u_int32_t)(swab16(as_u16(src)) ^ 0x80); goto CONV_END;
-conv_xx12_xxx2: as_u8(dst) = as_u16(src) & 0xff; goto CONV_END;
-conv_xx12_x210: as_u32(dst) = (u_int32_t)swab16(as_u16(src)) << 8; goto CONV_END;
-conv_xx12_012x: as_u32(dst) = (u_int32_t)as_u16(src) << 8; goto CONV_END;
-conv_xx12_2100: as_u32(dst) = (u_int32_t)swab16(as_u16(src)) << 16; goto CONV_END;
-conv_xx12_0012: as_u32(dst) = (u_int32_t)as_u16(src); goto CONV_END;
-conv_xx12_xxxA: as_u8(dst) = (as_u16(src) ^ 0x80) & 0xff; goto CONV_END;
-conv_xx12_xxA1: as_u16(dst) = swab16(as_u16(src) ^ 0x80); goto CONV_END;
-conv_xx12_xx1A: as_u16(dst) = as_u16(src) ^ 0x80; goto CONV_END;
-conv_xx12_xA10: as_u32(dst) = (u_int32_t)swab16(as_u16(src) ^ 0x80) << 8; goto CONV_END;
-conv_xx12_01Ax: as_u32(dst) = (u_int32_t)(as_u16(src) ^ 0x80) << 8; goto CONV_END;
-conv_xx12_A100: as_u32(dst) = (u_int32_t)swab16(as_u16(src) ^ 0x80) << 16; goto CONV_END;
-conv_xx12_001A: as_u32(dst) = (u_int32_t)(as_u16(src) ^ 0x80); goto CONV_END;
-conv_x123_xxx1: as_u8(dst) = as_u32(src) >> 16; goto CONV_END;
-conv_x123_xx12: as_u16(dst) = as_u32(src) >> 8; goto CONV_END;
-conv_x123_xx21: as_u16(dst) = swab16(as_u32(src) >> 8); goto CONV_END;
-conv_x123_x123: as_u32(dst) = as_u32(src); goto CONV_END;
-conv_x123_321x: as_u32(dst) = swab32(as_u32(src)); goto CONV_END;
-conv_x123_1230: as_u32(dst) = as_u32(src) << 8; goto CONV_END;
-conv_x123_0321: as_u32(dst) = swab32(as_u32(src)) >> 8; goto CONV_END;
-conv_x123_xxx9: as_u8(dst) = (as_u32(src) >> 16) ^ 0x80; goto CONV_END;
-conv_x123_xx92: as_u16(dst) = (as_u32(src) >> 8) ^ 0x8000; goto CONV_END;
-conv_x123_xx29: as_u16(dst) = swab16(as_u32(src) >> 8) ^ 0x80; goto CONV_END;
-conv_x123_x923: as_u32(dst) = as_u32(src) ^ 0x800000; goto CONV_END;
-conv_x123_329x: as_u32(dst) = swab32(as_u32(src)) ^ 0x8000; goto CONV_END;
-conv_x123_9230: as_u32(dst) = (as_u32(src) ^ 0x800000) << 8; goto CONV_END;
-conv_x123_0329: as_u32(dst) = (swab32(as_u32(src)) >> 8) ^ 0x80; goto CONV_END;
-conv_123x_xxx3: as_u8(dst) = (as_u32(src) >> 8) & 0xff; goto CONV_END;
-conv_123x_xx32: as_u16(dst) = swab16(as_u32(src) >> 8); goto CONV_END;
-conv_123x_xx23: as_u16(dst) = (as_u32(src) >> 8) & 0xffff; goto CONV_END;
-conv_123x_x321: as_u32(dst) = swab32(as_u32(src)); goto CONV_END;
-conv_123x_123x: as_u32(dst) = as_u32(src); goto CONV_END;
-conv_123x_3210: as_u32(dst) = swab32(as_u32(src)) << 8; goto CONV_END;
-conv_123x_0123: as_u32(dst) = as_u32(src) >> 8; goto CONV_END;
-conv_123x_xxxB: as_u8(dst) = ((as_u32(src) >> 8) & 0xff) ^ 0x80; goto CONV_END;
-conv_123x_xxB2: as_u16(dst) = swab16((as_u32(src) >> 8) ^ 0x80); goto CONV_END;
-conv_123x_xx2B: as_u16(dst) = ((as_u32(src) >> 8) & 0xffff) ^ 0x80; goto CONV_END;
-conv_123x_xB21: as_u32(dst) = swab32(as_u32(src)) ^ 0x800000; goto CONV_END;
-conv_123x_12Bx: as_u32(dst) = as_u32(src) ^ 0x8000; goto CONV_END;
-conv_123x_B210: as_u32(dst) = swab32(as_u32(src) ^ 0x8000) << 8; goto CONV_END;
-conv_123x_012B: as_u32(dst) = (as_u32(src) >> 8) ^ 0x80; goto CONV_END;
-conv_1234_xxx1: as_u8(dst) = as_u32(src) >> 24; goto CONV_END;
-conv_1234_xx12: as_u16(dst) = as_u32(src) >> 16; goto CONV_END;
-conv_1234_xx21: as_u16(dst) = swab16(as_u32(src) >> 16); goto CONV_END;
-conv_1234_x123: as_u32(dst) = as_u32(src) >> 8; goto CONV_END;
-conv_1234_321x: as_u32(dst) = swab32(as_u32(src)) << 8; goto CONV_END;
-conv_1234_1234: as_u32(dst) = as_u32(src); goto CONV_END;
-conv_1234_4321: as_u32(dst) = swab32(as_u32(src)); goto CONV_END;
-conv_1234_xxx9: as_u8(dst) = (as_u32(src) >> 24) ^ 0x80; goto CONV_END;
-conv_1234_xx92: as_u16(dst) = (as_u32(src) >> 16) ^ 0x8000; goto CONV_END;
-conv_1234_xx29: as_u16(dst) = swab16(as_u32(src) >> 16) ^ 0x80; goto CONV_END;
-conv_1234_x923: as_u32(dst) = (as_u32(src) >> 8) ^ 0x800000; goto CONV_END;
-conv_1234_329x: as_u32(dst) = (swab32(as_u32(src)) ^ 0x80) << 8; goto CONV_END;
-conv_1234_9234: as_u32(dst) = as_u32(src) ^ 0x80000000; goto CONV_END;
-conv_1234_4329: as_u32(dst) = swab32(as_u32(src)) ^ 0x80; goto CONV_END;
-conv_1234_xxx4: as_u8(dst) = as_u32(src) & 0xff; goto CONV_END;
-conv_1234_xx43: as_u16(dst) = swab16(as_u32(src)); goto CONV_END;
-conv_1234_xx34: as_u16(dst) = as_u32(src) & 0xffff; goto CONV_END;
-conv_1234_x432: as_u32(dst) = swab32(as_u32(src)) >> 8; goto CONV_END;
-conv_1234_234x: as_u32(dst) = as_u32(src) << 8; goto CONV_END;
-conv_1234_xxxC: as_u8(dst) = (as_u32(src) & 0xff) ^ 0x80; goto CONV_END;
-conv_1234_xxC3: as_u16(dst) = swab16(as_u32(src) ^ 0x80); goto CONV_END;
-conv_1234_xx3C: as_u16(dst) = (as_u32(src) & 0xffff) ^ 0x80; goto CONV_END;
-conv_1234_xC32: as_u32(dst) = (swab32(as_u32(src)) >> 8) ^ 0x800000; goto CONV_END;
-conv_1234_23Cx: as_u32(dst) = (as_u32(src) ^ 0x80) << 8; goto CONV_END;
-conv_1234_C321: as_u32(dst) = swab32(as_u32(src) ^ 0x80); goto CONV_END;
-conv_1234_123C: as_u32(dst) = as_u32(src) ^ 0x80; goto CONV_END;
-}
-#endif
-
-#ifdef GET_S16_LABELS
-/* src_wid src_endswap unsigned */
-static void *get_s16_labels[4 * 2 * 2] = {
- &&get_s16_xxx1_xx10, /* 8h -> 16h */
- &&get_s16_xxx1_xx90, /* 8h ^> 16h */
- &&get_s16_xxx1_xx10, /* 8s -> 16h */
- &&get_s16_xxx1_xx90, /* 8s ^> 16h */
- &&get_s16_xx12_xx12, /* 16h -> 16h */
- &&get_s16_xx12_xx92, /* 16h ^> 16h */
- &&get_s16_xx12_xx21, /* 16s -> 16h */
- &&get_s16_xx12_xxA1, /* 16s ^> 16h */
- &&get_s16_x123_xx12, /* 24h -> 16h */
- &&get_s16_x123_xx92, /* 24h ^> 16h */
- &&get_s16_123x_xx32, /* 24s -> 16h */
- &&get_s16_123x_xxB2, /* 24s ^> 16h */
- &&get_s16_1234_xx12, /* 32h -> 16h */
- &&get_s16_1234_xx92, /* 32h ^> 16h */
- &&get_s16_1234_xx43, /* 32s -> 16h */
- &&get_s16_1234_xxC3, /* 32s ^> 16h */
-};
-#endif
-
-#ifdef GET_S16_END
-while(0) {
-get_s16_xxx1_xx10: sample = (u_int16_t)as_u8(src) << 8; goto GET_S16_END;
-get_s16_xxx1_xx90: sample = (u_int16_t)(as_u8(src) ^ 0x80) << 8; goto GET_S16_END;
-get_s16_xx12_xx12: sample = as_u16(src); goto GET_S16_END;
-get_s16_xx12_xx92: sample = as_u16(src) ^ 0x8000; goto GET_S16_END;
-get_s16_xx12_xx21: sample = swab16(as_u16(src)); goto GET_S16_END;
-get_s16_xx12_xxA1: sample = swab16(as_u16(src) ^ 0x80); goto GET_S16_END;
-get_s16_x123_xx12: sample = as_u32(src) >> 8; goto GET_S16_END;
-get_s16_x123_xx92: sample = (as_u32(src) >> 8) ^ 0x8000; goto GET_S16_END;
-get_s16_123x_xx32: sample = swab16(as_u32(src) >> 8); goto GET_S16_END;
-get_s16_123x_xxB2: sample = swab16((as_u32(src) >> 8) ^ 0x8000); goto GET_S16_END;
-get_s16_1234_xx12: sample = as_u32(src) >> 16; goto GET_S16_END;
-get_s16_1234_xx92: sample = (as_u32(src) >> 16) ^ 0x8000; goto GET_S16_END;
-get_s16_1234_xx43: sample = swab16(as_u32(src)); goto GET_S16_END;
-get_s16_1234_xxC3: sample = swab16(as_u32(src) ^ 0x80); goto GET_S16_END;
-}
-#endif
-
-#ifdef PUT_S16_LABELS
-/* dst_wid dst_endswap unsigned */
-static void *put_s16_labels[4 * 2 * 2] = {
- &&put_s16_xx12_xxx1, /* 16h -> 8h */
- &&put_s16_xx12_xxx9, /* 16h ^> 8h */
- &&put_s16_xx12_xxx1, /* 16h -> 8s */
- &&put_s16_xx12_xxx9, /* 16h ^> 8s */
- &&put_s16_xx12_xx12, /* 16h -> 16h */
- &&put_s16_xx12_xx92, /* 16h ^> 16h */
- &&put_s16_xx12_xx21, /* 16h -> 16s */
- &&put_s16_xx12_xx29, /* 16h ^> 16s */
- &&put_s16_xx12_x120, /* 16h -> 24h */
- &&put_s16_xx12_x920, /* 16h ^> 24h */
- &&put_s16_xx12_021x, /* 16h -> 24s */
- &&put_s16_xx12_029x, /* 16h ^> 24s */
- &&put_s16_xx12_1200, /* 16h -> 32h */
- &&put_s16_xx12_9200, /* 16h ^> 32h */
- &&put_s16_xx12_0021, /* 16h -> 32s */
- &&put_s16_xx12_0029, /* 16h ^> 32s */
-};
-#endif
-
-#ifdef PUT_S16_END
-while (0) {
-put_s16_xx12_xxx1: as_u8(dst) = sample >> 8; goto PUT_S16_END;
-put_s16_xx12_xxx9: as_u8(dst) = (sample >> 8) ^ 0x80; goto PUT_S16_END;
-put_s16_xx12_xx12: as_u16(dst) = sample; goto PUT_S16_END;
-put_s16_xx12_xx92: as_u16(dst) = sample ^ 0x8000; goto PUT_S16_END;
-put_s16_xx12_xx21: as_u16(dst) = swab16(sample); goto PUT_S16_END;
-put_s16_xx12_xx29: as_u16(dst) = swab16(sample) ^ 0x80; goto PUT_S16_END;
-put_s16_xx12_x120: as_u32(dst) = (u_int32_t)sample << 8; goto PUT_S16_END;
-put_s16_xx12_x920: as_u32(dst) = (u_int32_t)(sample ^ 0x8000) << 8; goto PUT_S16_END;
-put_s16_xx12_021x: as_u32(dst) = (u_int32_t)swab16(sample) << 8; goto PUT_S16_END;
-put_s16_xx12_029x: as_u32(dst) = (u_int32_t)(swab16(sample) ^ 0x80) << 8; goto PUT_S16_END;
-put_s16_xx12_1200: as_u32(dst) = (u_int32_t)sample << 16; goto PUT_S16_END;
-put_s16_xx12_9200: as_u32(dst) = (u_int32_t)(sample ^ 0x8000) << 16; goto PUT_S16_END;
-put_s16_xx12_0021: as_u32(dst) = (u_int32_t)swab16(sample); goto PUT_S16_END;
-put_s16_xx12_0029: as_u32(dst) = (u_int32_t)swab16(sample) ^ 0x80; goto PUT_S16_END;
-}
-#endif
-
-#undef as_u8
-#undef as_u16
-#undef as_u32
-#undef as_s8
-#undef as_s16
-#undef as_s32
diff --git a/sound/core/oss/rate.c b/sound/core/oss/rate.c
index 18d8a0f4e816..9eb267913c38 100644
--- a/sound/core/oss/rate.c
+++ b/sound/core/oss/rate.c
@@ -1,6 +1,6 @@
/*
* Rate conversion Plug-In
- * Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
*
*
* This library is free software; you can redistribute it and/or modify
@@ -20,9 +20,6 @@
*/
#include <sound/driver.h>
-
-#ifdef CONFIG_SND_PCM_OSS_PLUGINS
-
#include <linux/time.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -340,5 +337,3 @@ int snd_pcm_plugin_build_rate(struct snd_pcm_substream *plug,
*r_plugin = plugin;
return 0;
}
-
-#endif
diff --git a/sound/core/oss/route.c b/sound/core/oss/route.c
index 46917dc0196b..de3ffdeaf7e3 100644
--- a/sound/core/oss/route.c
+++ b/sound/core/oss/route.c
@@ -20,9 +20,6 @@
*/
#include <sound/driver.h>
-
-#ifdef CONFIG_SND_PCM_OSS_PLUGINS
-
#include <linux/slab.h>
#include <linux/time.h>
#include <sound/core.h>
@@ -108,5 +105,3 @@ int snd_pcm_plugin_build_route(struct snd_pcm_substream *plug,
*r_plugin = plugin;
return 0;
}
-
-#endif
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 2743414fc8fa..cf9b9493d41d 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -1,6 +1,6 @@
/*
* Digital Audio (PCM) abstract layer
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -30,7 +30,7 @@
#include <sound/control.h>
#include <sound/info.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Abramo Bagnara <abramo@alsa-project.org>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Abramo Bagnara <abramo@alsa-project.org>");
MODULE_DESCRIPTION("Midlevel PCM code for ALSA.");
MODULE_LICENSE("GPL");
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 9fefcaa2c324..806f1fba5446 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -1,6 +1,6 @@
/*
* Digital Audio (PCM) abstract layer
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Abramo Bagnara <abramo@alsa-project.org>
*
*
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index 95b1b2f0b1e2..a13e38cfd2c6 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -1,6 +1,6 @@
/*
* Digital Audio (PCM) abstract layer
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c
index 0019c59a779d..dd9aa51d8c82 100644
--- a/sound/core/pcm_misc.c
+++ b/sound/core/pcm_misc.c
@@ -1,6 +1,6 @@
/*
* PCM Interface - misc routines
- * Copyright (c) 1998 by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 1998 by Jaroslav Kysela <perex@perex.cz>
*
*
* This library is free software; you can redistribute it and/or modify
@@ -422,38 +422,6 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int
EXPORT_SYMBOL(snd_pcm_format_set_silence);
-/* [width][unsigned][bigendian] */
-static int linear_formats[4][2][2] = {
- {{ SNDRV_PCM_FORMAT_S8, SNDRV_PCM_FORMAT_S8},
- { SNDRV_PCM_FORMAT_U8, SNDRV_PCM_FORMAT_U8}},
- {{SNDRV_PCM_FORMAT_S16_LE, SNDRV_PCM_FORMAT_S16_BE},
- {SNDRV_PCM_FORMAT_U16_LE, SNDRV_PCM_FORMAT_U16_BE}},
- {{SNDRV_PCM_FORMAT_S24_LE, SNDRV_PCM_FORMAT_S24_BE},
- {SNDRV_PCM_FORMAT_U24_LE, SNDRV_PCM_FORMAT_U24_BE}},
- {{SNDRV_PCM_FORMAT_S32_LE, SNDRV_PCM_FORMAT_S32_BE},
- {SNDRV_PCM_FORMAT_U32_LE, SNDRV_PCM_FORMAT_U32_BE}}
-};
-
-/**
- * snd_pcm_build_linear_format - return the suitable linear format for the given condition
- * @width: the bit-width
- * @unsignd: 1 if unsigned, 0 if signed.
- * @big_endian: 1 if big-endian, 0 if little-endian
- *
- * Returns the suitable linear format for the given condition.
- */
-snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsignd, int big_endian)
-{
- if (width & 7)
- return SND_PCM_FORMAT_UNKNOWN;
- width = (width / 8) - 1;
- if (width < 0 || width >= 4)
- return SND_PCM_FORMAT_UNKNOWN;
- return linear_formats[width][!!unsignd][!!big_endian];
-}
-
-EXPORT_SYMBOL(snd_pcm_build_linear_format);
-
/**
* snd_pcm_limit_hw_rates - determine rate_min/rate_max fields
* @runtime: the runtime instance
@@ -465,21 +433,16 @@ EXPORT_SYMBOL(snd_pcm_build_linear_format);
*/
int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime)
{
- static unsigned rates[] = {
- /* ATTENTION: these values depend on the definition in pcm.h! */
- 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000,
- 64000, 88200, 96000, 176400, 192000
- };
int i;
- for (i = 0; i < (int)ARRAY_SIZE(rates); i++) {
+ for (i = 0; i < (int)snd_pcm_known_rates.count; i++) {
if (runtime->hw.rates & (1 << i)) {
- runtime->hw.rate_min = rates[i];
+ runtime->hw.rate_min = snd_pcm_known_rates.list[i];
break;
}
}
- for (i = (int)ARRAY_SIZE(rates) - 1; i >= 0; i--) {
+ for (i = (int)snd_pcm_known_rates.count - 1; i >= 0; i--) {
if (runtime->hw.rates & (1 << i)) {
- runtime->hw.rate_max = rates[i];
+ runtime->hw.rate_max = snd_pcm_known_rates.list[i];
break;
}
}
@@ -487,3 +450,21 @@ int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime)
}
EXPORT_SYMBOL(snd_pcm_limit_hw_rates);
+
+/**
+ * snd_pcm_rate_to_rate_bit - converts sample rate to SNDRV_PCM_RATE_xxx bit
+ * @rate: the sample rate to convert
+ *
+ * Returns the SNDRV_PCM_RATE_xxx flag that corresponds to the given rate, or
+ * SNDRV_PCM_RATE_KNOT for an unknown rate.
+ */
+unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate)
+{
+ unsigned int i;
+
+ for (i = 0; i < snd_pcm_known_rates.count; i++)
+ if (snd_pcm_known_rates.list[i] == rate)
+ return 1u << i;
+ return SNDRV_PCM_RATE_KNOT;
+}
+EXPORT_SYMBOL(snd_pcm_rate_to_rate_bit);
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 59b29cd482ae..fb3dde4db045 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -1,6 +1,6 @@
/*
* Digital Audio (PCM) abstract layer
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -1787,12 +1787,18 @@ static int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params,
static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100,
48000, 64000, 88200, 96000, 176400, 192000 };
+const struct snd_pcm_hw_constraint_list snd_pcm_known_rates = {
+ .count = ARRAY_SIZE(rates),
+ .list = rates,
+};
+
static int snd_pcm_hw_rule_rate(struct snd_pcm_hw_params *params,
struct snd_pcm_hw_rule *rule)
{
struct snd_pcm_hardware *hw = rule->private;
return snd_interval_list(hw_param_interval(params, rule->var),
- ARRAY_SIZE(rates), rates, hw->rates);
+ snd_pcm_known_rates.count,
+ snd_pcm_known_rates.list, hw->rates);
}
static int snd_pcm_hw_rule_buffer_bytes_max(struct snd_pcm_hw_params *params,
diff --git a/sound/core/pcm_timer.c b/sound/core/pcm_timer.c
index d94ed16d21ea..23aa9a27e215 100644
--- a/sound/core/pcm_timer.c
+++ b/sound/core/pcm_timer.c
@@ -1,6 +1,6 @@
/*
* Digital Audio (PCM) abstract layer
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index e470c3c7d611..b8e700b94e59 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -1,6 +1,6 @@
/*
* Abstract layer for MIDI v1.0 stream
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -30,14 +30,13 @@
#include <linux/mutex.h>
#include <linux/moduleparam.h>
#include <linux/delay.h>
-#include <linux/wait.h>
#include <sound/rawmidi.h>
#include <sound/info.h>
#include <sound/control.h>
#include <sound/minors.h>
#include <sound/initval.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Midlevel RawMidi code for ALSA.");
MODULE_LICENSE("GPL");
diff --git a/sound/core/seq/Makefile b/sound/core/seq/Makefile
index 402e2b4a34c6..ceef14afee30 100644
--- a/sound/core/seq/Makefile
+++ b/sound/core/seq/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
#
obj-$(CONFIG_SND) += instr/
diff --git a/sound/core/seq/instr/Makefile b/sound/core/seq/instr/Makefile
index 69138f30a293..608960364813 100644
--- a/sound/core/seq/instr/Makefile
+++ b/sound/core/seq/instr/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
#
snd-ainstr-fm-objs := ainstr_fm.o
diff --git a/sound/core/seq/instr/ainstr_gf1.c b/sound/core/seq/instr/ainstr_gf1.c
index c640e1cf854d..49400262b1eb 100644
--- a/sound/core/seq/instr/ainstr_gf1.c
+++ b/sound/core/seq/instr/ainstr_gf1.c
@@ -1,6 +1,6 @@
/*
* GF1 (GUS) Patch - Instrument routines
- * Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
*
* 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
@@ -26,7 +26,7 @@
#include <sound/initval.h>
#include <asm/uaccess.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Advanced Linux Sound Architecture GF1 (GUS) Patch support.");
MODULE_LICENSE("GPL");
diff --git a/sound/core/seq/instr/ainstr_iw.c b/sound/core/seq/instr/ainstr_iw.c
index 5367baee2d08..6c40eb73fa9f 100644
--- a/sound/core/seq/instr/ainstr_iw.c
+++ b/sound/core/seq/instr/ainstr_iw.c
@@ -1,6 +1,6 @@
/*
* IWFFFF - AMD InterWave (tm) - Instrument routines
- * Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
*
* 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
@@ -26,7 +26,7 @@
#include <sound/initval.h>
#include <asm/uaccess.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Advanced Linux Sound Architecture IWFFFF support.");
MODULE_LICENSE("GPL");
diff --git a/sound/core/seq/instr/ainstr_simple.c b/sound/core/seq/instr/ainstr_simple.c
index ac717bef9d77..78f68bee24fe 100644
--- a/sound/core/seq/instr/ainstr_simple.c
+++ b/sound/core/seq/instr/ainstr_simple.c
@@ -1,6 +1,6 @@
/*
* Simple (MOD player) - Instrument routines
- * Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
*
* 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
@@ -26,7 +26,7 @@
#include <sound/initval.h>
#include <asm/uaccess.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Advanced Linux Sound Architecture Simple Instrument support.");
MODULE_LICENSE("GPL");
diff --git a/sound/core/seq/oss/Makefile b/sound/core/seq/oss/Makefile
index a37ddedf7107..b38406b8463c 100644
--- a/sound/core/seq/oss/Makefile
+++ b/sound/core/seq/oss/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
#
snd-seq-oss-objs := seq_oss.o seq_oss_init.o seq_oss_timer.o seq_oss_ioctl.o \
diff --git a/sound/core/seq/oss/seq_oss_init.c b/sound/core/seq/oss/seq_oss_init.c
index ca5a2ed4d7c3..d0d721c22eac 100644
--- a/sound/core/seq/oss/seq_oss_init.c
+++ b/sound/core/seq/oss/seq_oss_init.c
@@ -176,29 +176,29 @@ snd_seq_oss_open(struct file *file, int level)
int i, rc;
struct seq_oss_devinfo *dp;
- if ((dp = kzalloc(sizeof(*dp), GFP_KERNEL)) == NULL) {
+ dp = kzalloc(sizeof(*dp), GFP_KERNEL);
+ if (!dp) {
snd_printk(KERN_ERR "can't malloc device info\n");
return -ENOMEM;
}
debug_printk(("oss_open: dp = %p\n", dp));
+ dp->cseq = system_client;
+ dp->port = -1;
+ dp->queue = -1;
+
for (i = 0; i < SNDRV_SEQ_OSS_MAX_CLIENTS; i++) {
if (client_table[i] == NULL)
break;
}
+
+ dp->index = i;
if (i >= SNDRV_SEQ_OSS_MAX_CLIENTS) {
snd_printk(KERN_ERR "too many applications\n");
- kfree(dp);
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto _error;
}
- dp->index = i;
- dp->cseq = system_client;
- dp->port = -1;
- dp->queue = -1;
- dp->readq = NULL;
- dp->writeq = NULL;
-
/* look up synth and midi devices */
snd_seq_oss_synth_setup(dp);
snd_seq_oss_midi_setup(dp);
@@ -211,14 +211,16 @@ snd_seq_oss_open(struct file *file, int level)
/* create port */
debug_printk(("create new port\n"));
- if ((rc = create_port(dp)) < 0) {
+ rc = create_port(dp);
+ if (rc < 0) {
snd_printk(KERN_ERR "can't create port\n");
goto _error;
}
/* allocate queue */
debug_printk(("allocate queue\n"));
- if ((rc = alloc_seq_queue(dp)) < 0)
+ rc = alloc_seq_queue(dp);
+ if (rc < 0)
goto _error;
/* set address */
@@ -235,7 +237,8 @@ snd_seq_oss_open(struct file *file, int level)
/* initialize read queue */
debug_printk(("initialize read queue\n"));
if (is_read_mode(dp->file_mode)) {
- if ((dp->readq = snd_seq_oss_readq_new(dp, maxqlen)) == NULL) {
+ dp->readq = snd_seq_oss_readq_new(dp, maxqlen);
+ if (!dp->readq) {
rc = -ENOMEM;
goto _error;
}
@@ -245,7 +248,7 @@ snd_seq_oss_open(struct file *file, int level)
debug_printk(("initialize write queue\n"));
if (is_write_mode(dp->file_mode)) {
dp->writeq = snd_seq_oss_writeq_new(dp, maxqlen);
- if (dp->writeq == NULL) {
+ if (!dp->writeq) {
rc = -ENOMEM;
goto _error;
}
@@ -253,7 +256,8 @@ snd_seq_oss_open(struct file *file, int level)
/* initialize timer */
debug_printk(("initialize timer\n"));
- if ((dp->timer = snd_seq_oss_timer_new(dp)) == NULL) {
+ dp->timer = snd_seq_oss_timer_new(dp);
+ if (!dp->timer) {
snd_printk(KERN_ERR "can't alloc timer\n");
rc = -ENOMEM;
goto _error;
@@ -276,11 +280,13 @@ snd_seq_oss_open(struct file *file, int level)
return 0;
_error:
+ snd_seq_oss_writeq_delete(dp->writeq);
+ snd_seq_oss_readq_delete(dp->readq);
snd_seq_oss_synth_cleanup(dp);
snd_seq_oss_midi_cleanup(dp);
- i = dp->queue;
delete_port(dp);
- delete_seq_queue(i);
+ delete_seq_queue(dp->queue);
+ kfree(dp);
return rc;
}
diff --git a/sound/core/seq/oss/seq_oss_writeq.c b/sound/core/seq/oss/seq_oss_writeq.c
index 5c8495601a38..217424858191 100644
--- a/sound/core/seq/oss/seq_oss_writeq.c
+++ b/sound/core/seq/oss/seq_oss_writeq.c
@@ -63,8 +63,10 @@ snd_seq_oss_writeq_new(struct seq_oss_devinfo *dp, int maxlen)
void
snd_seq_oss_writeq_delete(struct seq_oss_writeq *q)
{
- snd_seq_oss_writeq_clear(q); /* to be sure */
- kfree(q);
+ if (q) {
+ snd_seq_oss_writeq_clear(q); /* to be sure */
+ kfree(q);
+ }
}
diff --git a/sound/core/seq/seq.c b/sound/core/seq/seq.c
index 2f0d8773ac6b..1878208a8026 100644
--- a/sound/core/seq/seq.c
+++ b/sound/core/seq/seq.c
@@ -53,7 +53,7 @@ int seq_default_timer_device =
int seq_default_timer_subdevice = 0;
int seq_default_timer_resolution = 0; /* Hz */
-MODULE_AUTHOR("Frank van de Pol <fvdpol@coil.demon.nl>, Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Frank van de Pol <fvdpol@coil.demon.nl>, Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer.");
MODULE_LICENSE("GPL");
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index b31b5282a2c8..2e3fa25ab19f 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -1,7 +1,7 @@
/*
* ALSA sequencer Client Manager
* Copyright (c) 1998-2001 by Frank van de Pol <fvdpol@coil.demon.nl>
- * Jaroslav Kysela <perex@suse.cz>
+ * Jaroslav Kysela <perex@perex.cz>
* Takashi Iwai <tiwai@suse.de>
*
*
diff --git a/sound/core/seq/seq_instr.c b/sound/core/seq/seq_instr.c
index 5efe6523a589..9a6fd56c9109 100644
--- a/sound/core/seq/seq_instr.c
+++ b/sound/core/seq/seq_instr.c
@@ -1,6 +1,6 @@
/*
* Generic Instrument routines for ALSA sequencer
- * Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
*
* 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
@@ -26,7 +26,7 @@
#include <sound/seq_instr.h>
#include <sound/initval.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer instrument library.");
MODULE_LICENSE("GPL");
@@ -109,7 +109,7 @@ void snd_seq_instr_list_free(struct snd_seq_kinstr_list **list_ptr)
spin_lock_irqsave(&list->lock, flags);
while (instr->use) {
spin_unlock_irqrestore(&list->lock, flags);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
spin_lock_irqsave(&list->lock, flags);
}
spin_unlock_irqrestore(&list->lock, flags);
@@ -198,8 +198,10 @@ int snd_seq_instr_list_free_cond(struct snd_seq_kinstr_list *list,
while (flist) {
instr = flist;
flist = instr->next;
- while (instr->use)
- schedule_timeout(1);
+ while (instr->use) {
+ schedule_timeout_uninterruptible(1);
+ barrier();
+ }
if (snd_seq_instr_free(instr, atomic)<0)
snd_printk(KERN_WARNING "instrument free problem\n");
instr = next;
@@ -555,7 +557,7 @@ static int instr_free(struct snd_seq_kinstr_ops *ops,
SNDRV_SEQ_INSTR_NOTIFY_REMOVE);
while (instr->use) {
spin_unlock_irqrestore(&list->lock, flags);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
spin_lock_irqsave(&list->lock, flags);
}
spin_unlock_irqrestore(&list->lock, flags);
diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c
index a3dc5e01e9f2..a72a1945bf8a 100644
--- a/sound/core/seq/seq_memory.c
+++ b/sound/core/seq/seq_memory.c
@@ -1,7 +1,7 @@
/*
* ALSA sequencer Memory Manager
* Copyright (c) 1998 by Frank van de Pol <fvdpol@coil.demon.nl>
- * Jaroslav Kysela <perex@suse.cz>
+ * Jaroslav Kysela <perex@perex.cz>
* 2000 by Takashi Iwai <tiwai@suse.de>
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c
index 1daa5b069c79..5929aaf1df9d 100644
--- a/sound/core/seq/seq_midi.c
+++ b/sound/core/seq/seq_midi.c
@@ -1,7 +1,7 @@
/*
* Generic MIDI synth driver for ALSA sequencer
* Copyright (c) 1998 by Frank van de Pol <fvdpol@coil.demon.nl>
- * Jaroslav Kysela <perex@suse.cz>
+ * Jaroslav Kysela <perex@perex.cz>
*
* 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
@@ -40,7 +40,7 @@ Possible options for midisynth module:
#include <sound/seq_midi_event.h>
#include <sound/initval.h>
-MODULE_AUTHOR("Frank van de Pol <fvdpol@coil.demon.nl>, Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Frank van de Pol <fvdpol@coil.demon.nl>, Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer MIDI synth.");
MODULE_LICENSE("GPL");
static int output_buffer_size = PAGE_SIZE;
diff --git a/sound/core/seq/seq_midi_emul.c b/sound/core/seq/seq_midi_emul.c
index d7c4fb86b9eb..17b3e6f13ca3 100644
--- a/sound/core/seq/seq_midi_emul.c
+++ b/sound/core/seq/seq_midi_emul.c
@@ -71,7 +71,7 @@ static void reset_all_channels(struct snd_midi_channel_set *chset);
* such as GM, GS and XG.
* There modes that this module will run in are:
* Generic MIDI - no interpretation at all, it will just save current values
- * of controlers etc.
+ * of controllers etc.
* GM - You can use all gm_ prefixed elements of chan. Controls, RPN, NRPN,
* SysEx will be interpreded as defined in General Midi.
* GS - You can use all gs_ prefixed elements of chan. Codes for GS will be
@@ -176,7 +176,7 @@ snd_midi_process_event(struct snd_midi_op *ops,
ev->data.control.value);
break;
case SNDRV_SEQ_EVENT_NONREGPARAM:
- /* Break it back into its controler values */
+ /* Break it back into its controller values */
chan->param_type = SNDRV_MIDI_PARAM_TYPE_NONREGISTERED;
chan->control[MIDI_CTL_MSB_DATA_ENTRY]
= (ev->data.control.value >> 7) & 0x7f;
@@ -189,7 +189,7 @@ snd_midi_process_event(struct snd_midi_op *ops,
nrpn(ops, drv, chan, chanset);
break;
case SNDRV_SEQ_EVENT_REGPARAM:
- /* Break it back into its controler values */
+ /* Break it back into its controller values */
chan->param_type = SNDRV_MIDI_PARAM_TYPE_REGISTERED;
chan->control[MIDI_CTL_MSB_DATA_ENTRY]
= (ev->data.control.value >> 7) & 0x7f;
@@ -267,7 +267,7 @@ note_off(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan,
}
/*
- * Do all driver independent operations for this controler and pass
+ * Do all driver independent operations for this controller and pass
* events that need to take place immediately to the driver.
*/
static void
diff --git a/sound/core/seq/seq_midi_event.c b/sound/core/seq/seq_midi_event.c
index 5ff80b776906..b6820a5a73fc 100644
--- a/sound/core/seq/seq_midi_event.c
+++ b/sound/core/seq/seq_midi_event.c
@@ -2,7 +2,7 @@
* MIDI byte <-> sequencer event coder
*
* Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>,
- * Jaroslav Kysela <perex@suse.cz>
+ * Jaroslav Kysela <perex@perex.cz>
*
* 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
@@ -28,14 +28,13 @@
#include <sound/seq_midi_event.h>
#include <sound/asoundef.h>
-MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>, Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>, Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("MIDI byte <-> sequencer event coder");
MODULE_LICENSE("GPL");
-/* queue type */
-/* from 0 to 7 are normal commands (note off, on, etc.) */
-#define ST_NOTEOFF 0
-#define ST_NOTEON 1
+/* event type, index into status_event[] */
+/* from 0 to 6 are normal commands (note off, on, etc.) for 0x9?-0xe? */
+#define ST_INVALID 7
#define ST_SPECIAL 8
#define ST_SYSEX ST_SPECIAL
/* from 8 to 15 are events for 0xf0-0xf7 */
@@ -65,32 +64,33 @@ static struct status_event_list {
void (*encode)(struct snd_midi_event *dev, struct snd_seq_event *ev);
void (*decode)(struct snd_seq_event *ev, unsigned char *buf);
} status_event[] = {
- /* 0x80 - 0xf0 */
- {SNDRV_SEQ_EVENT_NOTEOFF, 2, note_event, note_decode},
- {SNDRV_SEQ_EVENT_NOTEON, 2, note_event, note_decode},
- {SNDRV_SEQ_EVENT_KEYPRESS, 2, note_event, note_decode},
- {SNDRV_SEQ_EVENT_CONTROLLER, 2, two_param_ctrl_event, two_param_decode},
- {SNDRV_SEQ_EVENT_PGMCHANGE, 1, one_param_ctrl_event, one_param_decode},
- {SNDRV_SEQ_EVENT_CHANPRESS, 1, one_param_ctrl_event, one_param_decode},
- {SNDRV_SEQ_EVENT_PITCHBEND, 2, pitchbend_ctrl_event, pitchbend_decode},
- {SNDRV_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf0 */
+ /* 0x80 - 0xef */
+ {SNDRV_SEQ_EVENT_NOTEOFF, 2, note_event, note_decode},
+ {SNDRV_SEQ_EVENT_NOTEON, 2, note_event, note_decode},
+ {SNDRV_SEQ_EVENT_KEYPRESS, 2, note_event, note_decode},
+ {SNDRV_SEQ_EVENT_CONTROLLER, 2, two_param_ctrl_event, two_param_decode},
+ {SNDRV_SEQ_EVENT_PGMCHANGE, 1, one_param_ctrl_event, one_param_decode},
+ {SNDRV_SEQ_EVENT_CHANPRESS, 1, one_param_ctrl_event, one_param_decode},
+ {SNDRV_SEQ_EVENT_PITCHBEND, 2, pitchbend_ctrl_event, pitchbend_decode},
+ /* invalid */
+ {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL},
/* 0xf0 - 0xff */
- {SNDRV_SEQ_EVENT_SYSEX, 1, NULL, NULL}, /* sysex: 0xf0 */
- {SNDRV_SEQ_EVENT_QFRAME, 1, one_param_event, one_param_decode}, /* 0xf1 */
- {SNDRV_SEQ_EVENT_SONGPOS, 2, songpos_event, songpos_decode}, /* 0xf2 */
- {SNDRV_SEQ_EVENT_SONGSEL, 1, one_param_event, one_param_decode}, /* 0xf3 */
- {SNDRV_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf4 */
- {SNDRV_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf5 */
- {SNDRV_SEQ_EVENT_TUNE_REQUEST, 0, NULL, NULL}, /* 0xf6 */
- {SNDRV_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf7 */
- {SNDRV_SEQ_EVENT_CLOCK, 0, NULL, NULL}, /* 0xf8 */
- {SNDRV_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf9 */
- {SNDRV_SEQ_EVENT_START, 0, NULL, NULL}, /* 0xfa */
- {SNDRV_SEQ_EVENT_CONTINUE, 0, NULL, NULL}, /* 0xfb */
- {SNDRV_SEQ_EVENT_STOP, 0, NULL, NULL}, /* 0xfc */
- {SNDRV_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xfd */
- {SNDRV_SEQ_EVENT_SENSING, 0, NULL, NULL}, /* 0xfe */
- {SNDRV_SEQ_EVENT_RESET, 0, NULL, NULL}, /* 0xff */
+ {SNDRV_SEQ_EVENT_SYSEX, 1, NULL, NULL}, /* sysex: 0xf0 */
+ {SNDRV_SEQ_EVENT_QFRAME, 1, one_param_event, one_param_decode}, /* 0xf1 */
+ {SNDRV_SEQ_EVENT_SONGPOS, 2, songpos_event, songpos_decode}, /* 0xf2 */
+ {SNDRV_SEQ_EVENT_SONGSEL, 1, one_param_event, one_param_decode}, /* 0xf3 */
+ {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, /* 0xf4 */
+ {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, /* 0xf5 */
+ {SNDRV_SEQ_EVENT_TUNE_REQUEST, 0, NULL, NULL}, /* 0xf6 */
+ {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, /* 0xf7 */
+ {SNDRV_SEQ_EVENT_CLOCK, 0, NULL, NULL}, /* 0xf8 */
+ {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, /* 0xf9 */
+ {SNDRV_SEQ_EVENT_START, 0, NULL, NULL}, /* 0xfa */
+ {SNDRV_SEQ_EVENT_CONTINUE, 0, NULL, NULL}, /* 0xfb */
+ {SNDRV_SEQ_EVENT_STOP, 0, NULL, NULL}, /* 0xfc */
+ {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, /* 0xfd */
+ {SNDRV_SEQ_EVENT_SENSING, 0, NULL, NULL}, /* 0xfe */
+ {SNDRV_SEQ_EVENT_RESET, 0, NULL, NULL}, /* 0xff */
};
static int extra_decode_ctrl14(struct snd_midi_event *dev, unsigned char *buf, int len,
@@ -129,6 +129,7 @@ int snd_midi_event_new(int bufsize, struct snd_midi_event **rdev)
}
dev->bufsize = bufsize;
dev->lastcmd = 0xff;
+ dev->type = ST_INVALID;
spin_lock_init(&dev->lock);
*rdev = dev;
return 0;
@@ -149,7 +150,7 @@ static inline void reset_encode(struct snd_midi_event *dev)
{
dev->read = 0;
dev->qlen = 0;
- dev->type = 0;
+ dev->type = ST_INVALID;
}
void snd_midi_event_reset_encode(struct snd_midi_event *dev)
@@ -251,29 +252,31 @@ int snd_midi_event_encode_byte(struct snd_midi_event *dev, int c,
ev->type = status_event[ST_SPECIAL + c - 0xf0].event;
ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK;
ev->flags |= SNDRV_SEQ_EVENT_LENGTH_FIXED;
- return 1;
+ return ev->type != SNDRV_SEQ_EVENT_NONE;
}
spin_lock_irqsave(&dev->lock, flags);
- if (dev->qlen > 0) {
- /* rest of command */
- dev->buf[dev->read++] = c;
- if (dev->type != ST_SYSEX)
- dev->qlen--;
- } else {
+ if ((c & 0x80) &&
+ (c != MIDI_CMD_COMMON_SYSEX_END || dev->type != ST_SYSEX)) {
/* new command */
+ dev->buf[0] = c;
+ if ((c & 0xf0) == 0xf0) /* system messages */
+ dev->type = (c & 0x0f) + ST_SPECIAL;
+ else
+ dev->type = (c >> 4) & 0x07;
dev->read = 1;
- if (c & 0x80) {
- dev->buf[0] = c;
- if ((c & 0xf0) == 0xf0) /* special events */
- dev->type = (c & 0x0f) + ST_SPECIAL;
- else
- dev->type = (c >> 4) & 0x07;
- dev->qlen = status_event[dev->type].qlen;
- } else {
- /* process this byte as argument */
+ dev->qlen = status_event[dev->type].qlen;
+ } else {
+ if (dev->qlen > 0) {
+ /* rest of command */
dev->buf[dev->read++] = c;
+ if (dev->type != ST_SYSEX)
+ dev->qlen--;
+ } else {
+ /* running status */
+ dev->buf[1] = c;
dev->qlen = status_event[dev->type].qlen - 1;
+ dev->read = 2;
}
}
if (dev->qlen == 0) {
@@ -282,6 +285,8 @@ int snd_midi_event_encode_byte(struct snd_midi_event *dev, int c,
ev->flags |= SNDRV_SEQ_EVENT_LENGTH_FIXED;
if (status_event[dev->type].encode) /* set data values */
status_event[dev->type].encode(dev, ev);
+ if (dev->type >= ST_SPECIAL)
+ dev->type = ST_INVALID;
rc = 1;
} else if (dev->type == ST_SYSEX) {
if (c == MIDI_CMD_COMMON_SYSEX_END ||
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
index eefd1cf872b4..b6e23ad12ab9 100644
--- a/sound/core/seq/seq_ports.c
+++ b/sound/core/seq/seq_ports.c
@@ -1,7 +1,7 @@
/*
* ALSA sequencer Ports
* Copyright (c) 1998 by Frank van de Pol <fvdpol@coil.demon.nl>
- * Jaroslav Kysela <perex@suse.cz>
+ * Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c
index b4b9a132cb16..8716352afc81 100644
--- a/sound/core/seq/seq_timer.c
+++ b/sound/core/seq/seq_timer.c
@@ -1,7 +1,7 @@
/*
* ALSA sequencer Timer
* Copyright (c) 1998-1999 by Frank van de Pol <fvdpol@coil.demon.nl>
- * Jaroslav Kysela <perex@suse.cz>
+ * Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 8dc7a3b32b98..7b486c4d70db 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -1,6 +1,6 @@
/*
* Advanced Linux Sound Architecture
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -42,7 +42,7 @@ EXPORT_SYMBOL(snd_major);
static int cards_limit = 1;
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Advanced Linux Sound Architecture driver for soundcards.");
MODULE_LICENSE("GPL");
module_param(major, int, 0444);
@@ -266,6 +266,14 @@ int snd_register_device_for_dev(int type, struct snd_card *card, int dev,
snd_minors[minor] = preg;
preg->dev = device_create(sound_class, device, MKDEV(major, minor),
"%s", name);
+ if (IS_ERR(preg->dev)) {
+ snd_minors[minor] = NULL;
+ mutex_unlock(&sound_mutex);
+ minor = PTR_ERR(preg->dev);
+ kfree(preg);
+ return minor;
+ }
+
if (preg->dev)
dev_set_drvdata(preg->dev, private_data);
diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c
index 4566df41912a..dc73313b733a 100644
--- a/sound/core/sound_oss.c
+++ b/sound/core/sound_oss.c
@@ -1,6 +1,6 @@
/*
* Advanced Linux Sound Architecture
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/core/timer.c b/sound/core/timer.c
index f2bbacedd567..e7dc56ca4b97 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -1,6 +1,6 @@
/*
* Timers abstract layer
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -44,7 +44,7 @@
#endif
static int timer_limit = DEFAULT_TIMER_LIMIT;
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Takashi Iwai <tiwai@suse.de>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.de>");
MODULE_DESCRIPTION("ALSA timer interface");
MODULE_LICENSE("GPL");
module_param(timer_limit, int, 0444);
diff --git a/sound/drivers/Makefile b/sound/drivers/Makefile
index 04112642611a..80aeff5ccdea 100644
--- a/sound/drivers/Makefile
+++ b/sound/drivers/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
snd-dummy-objs := dummy.o
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index 4360ae9de19c..e008f3c58eac 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -1,6 +1,6 @@
/*
* Dummy soundcard
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
* 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
@@ -34,7 +34,7 @@
#include <sound/rawmidi.h>
#include <sound/initval.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Dummy soundcard (/dev/null)");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{ALSA,Dummy soundcard}}");
@@ -510,15 +510,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_dummy, -4500, 30, 0);
.get = snd_dummy_capsrc_get, .put = snd_dummy_capsrc_put, \
.private_value = addr }
-static int snd_dummy_capsrc_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 2;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_dummy_capsrc_info snd_ctl_boolean_stereo_info
static int snd_dummy_capsrc_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
diff --git a/sound/drivers/mpu401/Makefile b/sound/drivers/mpu401/Makefile
index 3fe185d19ae5..918f83f34c11 100644
--- a/sound/drivers/mpu401/Makefile
+++ b/sound/drivers/mpu401/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
snd-mpu401-objs := mpu401.o
diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c
index 67c6e9745418..1fc95dadde1d 100644
--- a/sound/drivers/mpu401/mpu401.c
+++ b/sound/drivers/mpu401/mpu401.c
@@ -1,6 +1,6 @@
/*
* Driver for generic MPU-401 boards (UART mode only)
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Copyright (c) 2004 by Castet Matthieu <castet.matthieu@free.fr>
*
*
@@ -30,7 +30,7 @@
#include <sound/mpu401.h>
#include <sound/initval.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("MPU-401 UART");
MODULE_LICENSE("GPL");
@@ -70,6 +70,9 @@ static int snd_mpu401_create(int dev, struct snd_card **rcard)
struct snd_card *card;
int err;
+ if (!uart_enter[dev])
+ snd_printk(KERN_ERR "the uart_enter option is obsolete; remove it\n");
+
*rcard = NULL;
card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
if (card == NULL)
@@ -83,8 +86,7 @@ static int snd_mpu401_create(int dev, struct snd_card **rcard)
strcat(card->longname, "polled");
}
- err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port[dev],
- uart_enter[dev] ? 0 : MPU401_INFO_UART_ONLY,
+ err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port[dev], 0,
irq[dev], irq[dev] >= 0 ? IRQF_DISABLED : 0,
NULL);
if (err < 0) {
diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
index 85aedc348e2d..3306ecd49243 100644
--- a/sound/drivers/mpu401/mpu401_uart.c
+++ b/sound/drivers/mpu401/mpu401_uart.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Routines for control of MPU-401 in UART mode
*
* MPU-401 supports UART mode which is not capable generate transmit
@@ -39,7 +39,7 @@
#include <sound/core.h>
#include <sound/mpu401.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Routines for control of MPU-401 in UART mode");
MODULE_LICENSE("GPL");
@@ -270,8 +270,7 @@ static int snd_mpu401_do_reset(struct snd_mpu401 *mpu)
{
if (snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1))
return -EIO;
- if (!(mpu->info_flags & MPU401_INFO_UART_ONLY) &&
- snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1))
+ if (snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 0))
return -EIO;
return 0;
}
diff --git a/sound/drivers/mts64.c b/sound/drivers/mts64.c
index 2025db5947ae..dcc90f995294 100644
--- a/sound/drivers/mts64.c
+++ b/sound/drivers/mts64.c
@@ -440,15 +440,7 @@ static void mts64_write_midi(struct mts64 *mts, u8 c,
*********************************************************************/
/* SMPTE Switch */
-static int snd_mts64_ctl_smpte_switch_info(struct snd_kcontrol *kctl,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_mts64_ctl_smpte_switch_info snd_ctl_boolean_mono_info
static int snd_mts64_ctl_smpte_switch_get(struct snd_kcontrol* kctl,
struct snd_ctl_elem_value *uctl)
@@ -838,7 +830,7 @@ static int __devinit snd_mts64_rawmidi_create(struct snd_card *card)
/*********************************************************************
* parport stuff
*********************************************************************/
-static void snd_mts64_interrupt(int irq, void *private)
+static void snd_mts64_interrupt(void *private)
{
struct mts64 *mts = ((struct snd_card*)private)->private_data;
u16 ret;
diff --git a/sound/drivers/opl3/Makefile b/sound/drivers/opl3/Makefile
index 12059785b5cb..19767a6a5c54 100644
--- a/sound/drivers/opl3/Makefile
+++ b/sound/drivers/opl3/Makefile
@@ -1,13 +1,11 @@
#
# Makefile for ALSA
-# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
snd-opl3-lib-objs := opl3_lib.o opl3_synth.o
-snd-opl3-synth-objs := opl3_seq.o opl3_midi.o opl3_drums.o
-ifeq ($(CONFIG_SND_SEQUENCER_OSS),y)
-snd-opl3-synth-objs += opl3_oss.o
-endif
+snd-opl3-synth-y := opl3_seq.o opl3_midi.o opl3_drums.o
+snd-opl3-synth-$(CONFIG_SND_SEQUENCER_OSS) += opl3_oss.o
#
# this function returns:
diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c
index 87fe376f38f0..a2b9ce060295 100644
--- a/sound/drivers/opl3/opl3_lib.c
+++ b/sound/drivers/opl3/opl3_lib.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>,
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
* Hannu Savolainen 1993-1996,
* Rob Hooft
*
@@ -31,7 +31,7 @@
#include <linux/ioport.h>
#include <sound/minors.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Hannu Savolainen 1993-1996, Rob Hooft");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Hannu Savolainen 1993-1996, Rob Hooft");
MODULE_DESCRIPTION("Routines for control of AdLib FM cards (OPL2/OPL3/OPL4 chips)");
MODULE_LICENSE("GPL");
diff --git a/sound/drivers/opl3/opl3_midi.c b/sound/drivers/opl3/opl3_midi.c
index 1b6f227af370..3557b6e20eb5 100644
--- a/sound/drivers/opl3/opl3_midi.c
+++ b/sound/drivers/opl3/opl3_midi.c
@@ -808,7 +808,7 @@ static void snd_opl3_pitch_ctrl(struct snd_opl3 *opl3, struct snd_midi_channel *
}
/*
- * Deal with a controler type event. This includes all types of
+ * Deal with a controller type event. This includes all types of
* control events, not just the midi controllers
*/
void snd_opl3_control(void *p, int type, struct snd_midi_channel *chan)
diff --git a/sound/drivers/opl4/Makefile b/sound/drivers/opl4/Makefile
index 141aacbaf315..d178b39ffa60 100644
--- a/sound/drivers/opl4/Makefile
+++ b/sound/drivers/opl4/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
snd-opl4-lib-objs := opl4_lib.o opl4_mixer.o opl4_proc.o
diff --git a/sound/drivers/portman2x4.c b/sound/drivers/portman2x4.c
index 0eb9b5cebfcd..e065b2a6444a 100644
--- a/sound/drivers/portman2x4.c
+++ b/sound/drivers/portman2x4.c
@@ -611,7 +611,7 @@ static int __devinit snd_portman_rawmidi_create(struct snd_card *card)
/*********************************************************************
* parport stuff
*********************************************************************/
-static void snd_portman_interrupt(int irq, void *userdata)
+static void snd_portman_interrupt(void *userdata)
{
unsigned char midivalue = 0;
struct portman *pm = ((struct snd_card*)userdata)->private_data;
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c
index d3e6a20edd38..65de3a755ddb 100644
--- a/sound/drivers/serial-u16550.c
+++ b/sound/drivers/serial-u16550.c
@@ -1,6 +1,6 @@
/*
* serial.c
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>,
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
* Isaku Yamahata <yamahata@private.email.ne.jp>,
* George Hansper <ghansper@apana.org.au>,
* Hannu Savolainen
diff --git a/sound/drivers/vx/Makefile b/sound/drivers/vx/Makefile
index 269bd8544a5d..9a168a3c1560 100644
--- a/sound/drivers/vx/Makefile
+++ b/sound/drivers/vx/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
snd-vx-lib-objs := vx_core.o vx_hwdep.o vx_pcm.o vx_mixer.o vx_cmd.o vx_uer.o
diff --git a/sound/drivers/vx/vx_mixer.c b/sound/drivers/vx/vx_mixer.c
index f63152a6a223..b8fcd79a7e11 100644
--- a/sound/drivers/vx/vx_mixer.c
+++ b/sound/drivers/vx/vx_mixer.c
@@ -647,14 +647,7 @@ static int vx_audio_monitor_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el
return 0;
}
-static int vx_audio_sw_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 2;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define vx_audio_sw_info snd_ctl_boolean_stereo_info
static int vx_audio_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -865,14 +858,7 @@ static int vx_peak_meter_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_
return 0;
}
-static int vx_saturation_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 2;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define vx_saturation_info snd_ctl_boolean_stereo_info
static int vx_saturation_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
diff --git a/sound/i2c/Makefile b/sound/i2c/Makefile
index 45902d48c89c..37970666a453 100644
--- a/sound/i2c/Makefile
+++ b/sound/i2c/Makefile
@@ -1,15 +1,13 @@
#
# Makefile for ALSA
-# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
snd-i2c-objs := i2c.o
snd-cs8427-objs := cs8427.o
snd-tea6330t-objs := tea6330t.o
-ifeq ($(subst m,y,$(CONFIG_L3)),y)
- obj-$(CONFIG_L3) += l3/
-endif
+obj-$(CONFIG_L3) += l3/
obj-$(CONFIG_SND) += other/
diff --git a/sound/i2c/cs8427.c b/sound/i2c/cs8427.c
index 64388cb8d6e5..744366b72345 100644
--- a/sound/i2c/cs8427.c
+++ b/sound/i2c/cs8427.c
@@ -1,7 +1,7 @@
/*
* Routines for control of the CS8427 via i2c bus
* IEC958 (S/PDIF) receiver & transmitter by Cirrus Logic
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -32,7 +32,7 @@
static void snd_cs8427_reset(struct snd_i2c_device *cs8427);
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("IEC958 (S/PDIF) receiver & transmitter by Cirrus Logic");
MODULE_LICENSE("GPL");
@@ -229,6 +229,12 @@ int snd_cs8427_create(struct snd_i2c_bus *bus,
snd_i2c_lock(bus);
err = snd_cs8427_reg_read(device, CS8427_REG_ID_AND_VER);
if (err != CS8427_VER8427A) {
+ /* give second chance */
+ snd_printk(KERN_WARNING "invalid CS8427 signature 0x%x: "
+ "let me try again...\n", err);
+ err = snd_cs8427_reg_read(device, CS8427_REG_ID_AND_VER);
+ }
+ if (err != CS8427_VER8427A) {
snd_i2c_unlock(bus);
snd_printk(KERN_ERR "unable to find CS8427 signature "
"(expected 0x%x, read 0x%x),\n",
diff --git a/sound/i2c/i2c.c b/sound/i2c/i2c.c
index b60fb1892828..1e58a963b2a7 100644
--- a/sound/i2c/i2c.c
+++ b/sound/i2c/i2c.c
@@ -2,7 +2,7 @@
* Generic i2c interface for ALSA
*
* (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
- * Modified for the ALSA driver by Jaroslav Kysela <perex@suse.cz>
+ * Modified for the ALSA driver by Jaroslav Kysela <perex@perex.cz>
*
* 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
@@ -28,7 +28,7 @@
#include <sound/core.h>
#include <sound/i2c.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Generic i2c interface for ALSA");
MODULE_LICENSE("GPL");
diff --git a/sound/i2c/other/Makefile b/sound/i2c/other/Makefile
index 77a8a7c75dd9..703d954238f4 100644
--- a/sound/i2c/other/Makefile
+++ b/sound/i2c/other/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 2003 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2003 by Jaroslav Kysela <perex@perex.cz>
#
snd-ak4114-objs := ak4114.o
diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c
index 1efb973137a6..facde46f957a 100644
--- a/sound/i2c/other/ak4114.c
+++ b/sound/i2c/other/ak4114.c
@@ -1,7 +1,7 @@
/*
* Routines for control of the AK4114 via I2C and 4-wire serial interface
* IEC958 (S/PDIF) receiver by Asahi Kasei
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -29,7 +29,7 @@
#include <sound/ak4114.h>
#include <sound/asoundef.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("AK4114 IEC958 (S/PDIF) receiver by Asahi Kasei");
MODULE_LICENSE("GPL");
@@ -200,15 +200,7 @@ static int snd_ak4114_in_error_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static int snd_ak4114_in_bit_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_ak4114_in_bit_info snd_ctl_boolean_mono_info
static int snd_ak4114_in_bit_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
diff --git a/sound/i2c/other/ak4117.c b/sound/i2c/other/ak4117.c
index c022f29da2f7..ee1585aec99b 100644
--- a/sound/i2c/other/ak4117.c
+++ b/sound/i2c/other/ak4117.c
@@ -1,7 +1,7 @@
/*
* Routines for control of the AK4117 via 4-wire serial interface
* IEC958 (S/PDIF) receiver by Asahi Kasei
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -29,7 +29,7 @@
#include <sound/ak4117.h>
#include <sound/asoundef.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("AK4117 IEC958 (S/PDIF) receiver by Asahi Kasei");
MODULE_LICENSE("GPL");
@@ -181,15 +181,7 @@ static int snd_ak4117_in_error_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static int snd_ak4117_in_bit_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_ak4117_in_bit_info snd_ctl_boolean_mono_info
static int snd_ak4117_in_bit_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c
index fd335159f849..de03f689fa2e 100644
--- a/sound/i2c/other/ak4xxx-adda.c
+++ b/sound/i2c/other/ak4xxx-adda.c
@@ -2,7 +2,7 @@
* ALSA driver for AK4524 / AK4528 / AK4529 / AK4355 / AK4358 / AK4381
* AD and DA converters
*
- * Copyright (c) 2000-2004 Jaroslav Kysela <perex@suse.cz>,
+ * Copyright (c) 2000-2004 Jaroslav Kysela <perex@perex.cz>,
* Takashi Iwai <tiwai@suse.de>
*
* This program is free software; you can redistribute it and/or modify
@@ -31,7 +31,7 @@
#include <sound/tlv.h>
#include <sound/ak4xxx-adda.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Takashi Iwai <tiwai@suse.de>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.de>");
MODULE_DESCRIPTION("Routines for control of AK452x / AK43xx AD/DA converters");
MODULE_LICENSE("GPL");
@@ -463,15 +463,7 @@ static int snd_akm4xxx_deemphasis_put(struct snd_kcontrol *kcontrol,
return change;
}
-static int ak4xxx_switch_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define ak4xxx_switch_info snd_ctl_boolean_mono_info
static int ak4xxx_switch_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
diff --git a/sound/i2c/other/pt2258.c b/sound/i2c/other/pt2258.c
index e91cc3b44de5..00c83d8b32b1 100644
--- a/sound/i2c/other/pt2258.c
+++ b/sound/i2c/other/pt2258.c
@@ -140,15 +140,7 @@ static int pt2258_stereo_volume_put(struct snd_kcontrol *kcontrol,
return -EIO;
}
-static int pt2258_switch_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define pt2258_switch_info snd_ctl_boolean_mono_info
static int pt2258_switch_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c
index 4c2fd14c1056..37c47fb95aca 100644
--- a/sound/i2c/other/tea575x-tuner.c
+++ b/sound/i2c/other/tea575x-tuner.c
@@ -1,7 +1,7 @@
/*
* ALSA driver for TEA5757/5759 Philips AM/FM radio tuner chips
*
- * Copyright (c) 2004 Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 2004 Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -28,7 +28,7 @@
#include <sound/core.h>
#include <sound/tea575x-tuner.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Routines for control of TEA5757/5759 Philips AM/FM radio tuner chips");
MODULE_LICENSE("GPL");
@@ -189,7 +189,6 @@ void snd_tea575x_init(struct snd_tea575x *tea)
tea->vd.owner = tea->card->module;
strcpy(tea->vd.name, tea->tea5759 ? "TEA5759 radio" : "TEA5757 radio");
tea->vd.type = VID_TYPE_TUNER;
- tea->vd.hardware = VID_HARDWARE_RTRACK; /* FIXME: assign new number */
tea->vd.release = snd_tea575x_release;
video_set_drvdata(&tea->vd, tea);
tea->vd.fops = &tea->fops;
diff --git a/sound/i2c/tea6330t.c b/sound/i2c/tea6330t.c
index ae5b1e3a68ce..9bab744af0ef 100644
--- a/sound/i2c/tea6330t.c
+++ b/sound/i2c/tea6330t.c
@@ -1,7 +1,7 @@
/*
* Routines for control of the TEA6330T circuit via i2c bus
* Sound fader control circuit for car radios by Philips Semiconductors
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -27,7 +27,7 @@
#include <sound/control.h>
#include <sound/tea6330t.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Routines for control of the TEA6330T circuit via i2c bus");
MODULE_LICENSE("GPL");
@@ -142,15 +142,7 @@ static int snd_tea6330t_put_master_volume(struct snd_kcontrol *kcontrol,
.info = snd_tea6330t_info_master_switch, \
.get = snd_tea6330t_get_master_switch, .put = snd_tea6330t_put_master_switch }
-static int snd_tea6330t_info_master_switch(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 2;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_tea6330t_info_master_switch snd_ctl_boolean_stereo_info
static int snd_tea6330t_get_master_switch(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index ea5084abe60f..2639a6ab8f2e 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -191,6 +191,19 @@ config SND_ES18XX
To compile this driver as a module, choose M here: the module
will be called snd-es18xx.
+config SND_SC6000
+ tristate "Gallant SC-6000, Audio Excel DSP 16"
+ depends on SND && HAS_IOPORT
+ select SND_AD1848_LIB
+ select SND_OPL3_LIB
+ select SND_MPU401_UART
+ help
+ Say Y here to include support for Gallant SC-6000 card and clones:
+ Audio Excel DSP 16 and Zoltrix AV302.
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-sc6000.
+
config SND_GUS_SYNTH
tristate
@@ -414,7 +427,7 @@ config SND_SSCAPE
config SND_WAVEFRONT
tristate "Turtle Beach Maui,Tropez,Tropez+ (Wavefront)"
depends on SND
- select FW_LOADER if !SND_WAVEFRONT_FIRMWARE_IN_KERNEL
+ select FW_LOADER
select SND_OPL3_LIB
select SND_MPU401_UART
select SND_CS4231_LIB
@@ -430,8 +443,9 @@ config SND_WAVEFRONT_FIRMWARE_IN_KERNEL
depends on SND_WAVEFRONT
default y
help
- Say Y here to include the static firmware built in the kernel
- for the Wavefront driver. If you choose N here, you need to
- install the firmware files from the alsa-firmware package.
+ Say Y here to include the static firmware for FX DSP built in
+ the kernel for the Wavefront driver. If you choose N here,
+ you need to install the firmware files from the
+ alsa-firmware package.
endmenu
diff --git a/sound/isa/Makefile b/sound/isa/Makefile
index bb317ccc170f..c0ce7db2a1b5 100644
--- a/sound/isa/Makefile
+++ b/sound/isa/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
snd-adlib-objs := adlib.o
@@ -10,6 +10,7 @@ snd-cmi8330-objs := cmi8330.o
snd-dt019x-objs := dt019x.o
snd-es18xx-objs := es18xx.o
snd-opl3sa2-objs := opl3sa2.o
+snd-sc6000-objs := sc6000.o
snd-sgalaxy-objs := sgalaxy.o
snd-sscape-objs := sscape.o
@@ -21,6 +22,7 @@ obj-$(CONFIG_SND_CMI8330) += snd-cmi8330.o
obj-$(CONFIG_SND_DT019X) += snd-dt019x.o
obj-$(CONFIG_SND_ES18XX) += snd-es18xx.o
obj-$(CONFIG_SND_OPL3SA2) += snd-opl3sa2.o
+obj-$(CONFIG_SND_SC6000) += snd-sc6000.o
obj-$(CONFIG_SND_SGALAXY) += snd-sgalaxy.o
obj-$(CONFIG_SND_SSCAPE) += snd-sscape.o
diff --git a/sound/isa/ad1816a/Makefile b/sound/isa/ad1816a/Makefile
index 90e00e842e49..487ab23860e3 100644
--- a/sound/isa/ad1816a/Makefile
+++ b/sound/isa/ad1816a/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
snd-ad1816a-objs := ad1816a.o ad1816a_lib.o
diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c
index ec9209cd5177..cf18fe4617a1 100644
--- a/sound/isa/ad1816a/ad1816a_lib.c
+++ b/sound/isa/ad1816a/ad1816a_lib.c
@@ -453,7 +453,6 @@ static int snd_ad1816a_playback_open(struct snd_pcm_substream *substream)
if ((error = snd_ad1816a_open(chip, AD1816A_MODE_PLAYBACK)) < 0)
return error;
- snd_pcm_set_sync(substream);
runtime->hw = snd_ad1816a_playback;
snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max);
snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.period_bytes_max);
@@ -469,7 +468,6 @@ static int snd_ad1816a_capture_open(struct snd_pcm_substream *substream)
if ((error = snd_ad1816a_open(chip, AD1816A_MODE_CAPTURE)) < 0)
return error;
- snd_pcm_set_sync(substream);
runtime->hw = snd_ad1816a_capture;
snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max);
snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max);
diff --git a/sound/isa/ad1848/Makefile b/sound/isa/ad1848/Makefile
index 45d59998aa69..ae23331e9200 100644
--- a/sound/isa/ad1848/Makefile
+++ b/sound/isa/ad1848/Makefile
@@ -1,15 +1,12 @@
#
# Makefile for ALSA
-# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
snd-ad1848-lib-objs := ad1848_lib.o
snd-ad1848-objs := ad1848.o
# Toplevel Module Dependency
-obj-$(CONFIG_SND_CMI8330) += snd-ad1848-lib.o
-obj-$(CONFIG_SND_SGALAXY) += snd-ad1848-lib.o
-obj-$(CONFIG_SND_AD1848) += snd-ad1848.o snd-ad1848-lib.o
-obj-$(CONFIG_SND_OPTI92X_AD1848) += snd-ad1848-lib.o
+obj-$(CONFIG_SND_AD1848) += snd-ad1848.o
+obj-$(CONFIG_SND_AD1848_LIB) += snd-ad1848-lib.o
-obj-m := $(sort $(obj-m))
diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c
index d09a7fa86545..a4710b5e214c 100644
--- a/sound/isa/ad1848/ad1848.c
+++ b/sound/isa/ad1848/ad1848.c
@@ -1,8 +1,8 @@
/*
* Generic driver for AD1848/AD1847/CS4248 chips (0.1 Alpha)
* Copyright (c) by Tugrul Galatali <galatalt@stuy.edu>,
- * Jaroslav Kysela <perex@suse.cz>
- * Based on card-4232.c by Jaroslav Kysela <perex@suse.cz>
+ * Jaroslav Kysela <perex@perex.cz>
+ * Based on card-4232.c by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -36,7 +36,7 @@
#define DEV_NAME "ad1848"
MODULE_DESCRIPTION(CRD_NAME);
-MODULE_AUTHOR("Tugrul Galatali <galatalt@stuy.edu>, Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Tugrul Galatali <galatalt@stuy.edu>, Jaroslav Kysela <perex@perex.cz>");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Analog Devices,AD1848},"
"{Analog Devices,AD1847},"
diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c
index 1bc2e3fd5721..a901cd1ee692 100644
--- a/sound/isa/ad1848/ad1848_lib.c
+++ b/sound/isa/ad1848/ad1848_lib.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Routines for control of AD1848/AD1847/CS4248
*
*
@@ -35,7 +35,7 @@
#include <asm/io.h>
#include <asm/dma.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Routines for control of AD1848/AD1847/CS4248");
MODULE_LICENSE("GPL");
@@ -70,7 +70,7 @@ static unsigned int rates[14] = {
};
static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
- .count = 14,
+ .count = ARRAY_SIZE(rates),
.list = rates,
.mask = 0,
};
@@ -99,24 +99,32 @@ static unsigned char snd_ad1848_original_image[16] =
* Basic I/O functions
*/
-void snd_ad1848_out(struct snd_ad1848 *chip,
- unsigned char reg,
- unsigned char value)
+static void snd_ad1848_wait(struct snd_ad1848 *chip)
{
int timeout;
- for (timeout = 250; timeout > 0 && (inb(AD1848P(chip, REGSEL)) & AD1848_INIT); timeout--)
+ for (timeout = 250; timeout > 0; timeout--) {
+ if ((inb(AD1848P(chip, REGSEL)) & AD1848_INIT) == 0)
+ break;
udelay(100);
+ }
+}
+
+void snd_ad1848_out(struct snd_ad1848 *chip,
+ unsigned char reg,
+ unsigned char value)
+{
+ snd_ad1848_wait(chip);
#ifdef CONFIG_SND_DEBUG
if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT)
- snd_printk(KERN_WARNING "auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
+ snd_printk(KERN_WARNING "auto calibration time out - "
+ "reg = 0x%x, value = 0x%x\n", reg, value);
#endif
outb(chip->mce_bit | reg, AD1848P(chip, REGSEL));
outb(chip->image[reg] = value, AD1848P(chip, REG));
mb();
-#if 0
- printk("codec out - reg 0x%x = 0x%x\n", chip->mce_bit | reg, value);
-#endif
+ snd_printdd("codec out - reg 0x%x = 0x%x\n",
+ chip->mce_bit | reg, value);
}
EXPORT_SYMBOL(snd_ad1848_out);
@@ -124,10 +132,7 @@ EXPORT_SYMBOL(snd_ad1848_out);
static void snd_ad1848_dout(struct snd_ad1848 *chip,
unsigned char reg, unsigned char value)
{
- int timeout;
-
- for (timeout = 250; timeout > 0 && (inb(AD1848P(chip, REGSEL)) & AD1848_INIT); timeout--)
- udelay(100);
+ snd_ad1848_wait(chip);
outb(chip->mce_bit | reg, AD1848P(chip, REGSEL));
outb(value, AD1848P(chip, REG));
mb();
@@ -135,13 +140,11 @@ static void snd_ad1848_dout(struct snd_ad1848 *chip,
static unsigned char snd_ad1848_in(struct snd_ad1848 *chip, unsigned char reg)
{
- int timeout;
-
- for (timeout = 250; timeout > 0 && (inb(AD1848P(chip, REGSEL)) & AD1848_INIT); timeout--)
- udelay(100);
+ snd_ad1848_wait(chip);
#ifdef CONFIG_SND_DEBUG
if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT)
- snd_printk(KERN_WARNING "auto calibration time out - reg = 0x%x\n", reg);
+ snd_printk(KERN_WARNING "auto calibration time out - "
+ "reg = 0x%x\n", reg);
#endif
outb(chip->mce_bit | reg, AD1848P(chip, REGSEL));
mb();
@@ -183,8 +186,7 @@ static void snd_ad1848_mce_up(struct snd_ad1848 *chip)
unsigned long flags;
int timeout;
- for (timeout = 250; timeout > 0 && (inb(AD1848P(chip, REGSEL)) & AD1848_INIT); timeout--)
- udelay(100);
+ snd_ad1848_wait(chip);
#ifdef CONFIG_SND_DEBUG
if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT)
snd_printk(KERN_WARNING "mce_up - auto calibration time out (0)\n");
@@ -201,9 +203,8 @@ static void snd_ad1848_mce_up(struct snd_ad1848 *chip)
static void snd_ad1848_mce_down(struct snd_ad1848 *chip)
{
- unsigned long flags;
- int timeout;
- signed long time;
+ unsigned long flags, timeout;
+ int reg;
spin_lock_irqsave(&chip->reg_lock, flags);
for (timeout = 5; timeout > 0; timeout--)
@@ -211,61 +212,48 @@ static void snd_ad1848_mce_down(struct snd_ad1848 *chip)
/* end of cleanup sequence */
for (timeout = 12000; timeout > 0 && (inb(AD1848P(chip, REGSEL)) & AD1848_INIT); timeout--)
udelay(100);
-#if 0
- printk("(1) timeout = %i\n", timeout);
-#endif
+
+ snd_printdd("(1) timeout = %d\n", timeout);
+
#ifdef CONFIG_SND_DEBUG
if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT)
snd_printk(KERN_WARNING "mce_down [0x%lx] - auto calibration time out (0)\n", AD1848P(chip, REGSEL));
#endif
+
chip->mce_bit &= ~AD1848_MCE;
- timeout = inb(AD1848P(chip, REGSEL));
- outb(chip->mce_bit | (timeout & 0x1f), AD1848P(chip, REGSEL));
- if (timeout == 0x80)
+ reg = inb(AD1848P(chip, REGSEL));
+ outb(chip->mce_bit | (reg & 0x1f), AD1848P(chip, REGSEL));
+ if (reg == 0x80)
snd_printk(KERN_WARNING "mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port);
- if ((timeout & AD1848_MCE) == 0) {
+ if ((reg & AD1848_MCE) == 0) {
spin_unlock_irqrestore(&chip->reg_lock, flags);
return;
}
- /* calibration process */
- for (timeout = 500; timeout > 0 && (snd_ad1848_in(chip, AD1848_TEST_INIT) & AD1848_CALIB_IN_PROGRESS) == 0; timeout--);
- if ((snd_ad1848_in(chip, AD1848_TEST_INIT) & AD1848_CALIB_IN_PROGRESS) == 0) {
- snd_printd("mce_down - auto calibration time out (1)\n");
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- return;
- }
-#if 0
- printk("(2) timeout = %i, jiffies = %li\n", timeout, jiffies);
-#endif
- time = HZ / 4;
- while (snd_ad1848_in(chip, AD1848_TEST_INIT) & AD1848_CALIB_IN_PROGRESS) {
+ /*
+ * Wait for auto-calibration (AC) process to finish, i.e. ACI to go low.
+ * It may take up to 5 sample periods (at most 907 us @ 5.5125 kHz) for
+ * the process to _start_, so it is important to wait at least that long
+ * before checking. Otherwise we might think AC has finished when it
+ * has in fact not begun. It could take 128 (no AC) or 384 (AC) cycles
+ * for ACI to drop. This gives a wait of at most 70 ms with a more
+ * typical value of 3-9 ms.
+ */
+ timeout = jiffies + msecs_to_jiffies(250);
+ do {
spin_unlock_irqrestore(&chip->reg_lock, flags);
- if (time <= 0) {
- snd_printk(KERN_ERR "mce_down - auto calibration time out (2)\n");
- return;
- }
- time = schedule_timeout(time);
+ msleep(1);
spin_lock_irqsave(&chip->reg_lock, flags);
- }
-#if 0
- printk("(3) jiffies = %li\n", jiffies);
-#endif
- time = HZ / 10;
- while (inb(AD1848P(chip, REGSEL)) & AD1848_INIT) {
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- if (time <= 0) {
- snd_printk(KERN_ERR "mce_down - auto calibration time out (3)\n");
- return;
- }
- time = schedule_timeout(time);
- spin_lock_irqsave(&chip->reg_lock, flags);
- }
+ reg = snd_ad1848_in(chip, AD1848_TEST_INIT) &
+ AD1848_CALIB_IN_PROGRESS;
+ } while (reg && time_before(jiffies, timeout));
spin_unlock_irqrestore(&chip->reg_lock, flags);
-#if 0
- printk("(4) jiffies = %li\n", jiffies);
- snd_printk("mce_down - exit = 0x%x\n", inb(AD1848P(chip, REGSEL)));
-#endif
+ if (reg)
+ snd_printk(KERN_ERR
+ "mce_down - auto calibration time out (2)\n");
+
+ snd_printdd("(4) jiffies = %lu\n", jiffies);
+ snd_printd("mce_down - exit = 0x%x\n", inb(AD1848P(chip, REGSEL)));
}
static unsigned int snd_ad1848_get_count(unsigned char format,
@@ -319,11 +307,11 @@ static unsigned char snd_ad1848_get_rate(unsigned int rate)
{
int i;
- for (i = 0; i < 14; i++)
+ for (i = 0; i < ARRAY_SIZE(rates); i++)
if (rate == rates[i])
return freq_bits[i];
snd_BUG();
- return freq_bits[13];
+ return freq_bits[ARRAY_SIZE(rates) - 1];
}
static int snd_ad1848_ioctl(struct snd_pcm_substream *substream,
@@ -390,11 +378,9 @@ static int snd_ad1848_open(struct snd_ad1848 *chip, unsigned int mode)
{
unsigned long flags;
- mutex_lock(&chip->open_mutex);
- if (chip->mode & AD1848_MODE_OPEN) {
- mutex_unlock(&chip->open_mutex);
+ if (chip->mode & AD1848_MODE_OPEN)
return -EAGAIN;
- }
+
snd_ad1848_mce_down(chip);
#ifdef SNDRV_DEBUG_MCE
@@ -435,7 +421,6 @@ static int snd_ad1848_open(struct snd_ad1848 *chip, unsigned int mode)
spin_unlock_irqrestore(&chip->reg_lock, flags);
chip->mode = mode;
- mutex_unlock(&chip->open_mutex);
return 0;
}
@@ -444,11 +429,8 @@ static void snd_ad1848_close(struct snd_ad1848 *chip)
{
unsigned long flags;
- mutex_lock(&chip->open_mutex);
- if (!chip->mode) {
- mutex_unlock(&chip->open_mutex);
+ if (!chip->mode)
return;
- }
/* disable IRQ */
spin_lock_irqsave(&chip->reg_lock, flags);
outb(0, AD1848P(chip, STATUS)); /* clear IRQ */
@@ -474,7 +456,6 @@ static void snd_ad1848_close(struct snd_ad1848 *chip)
spin_unlock_irqrestore(&chip->reg_lock, flags);
chip->mode = 0;
- mutex_unlock(&chip->open_mutex);
}
/*
@@ -892,7 +873,6 @@ int snd_ad1848_create(struct snd_card *card,
if (chip == NULL)
return -ENOMEM;
spin_lock_init(&chip->reg_lock);
- mutex_init(&chip->open_mutex);
chip->card = card;
chip->port = port;
chip->irq = -1;
diff --git a/sound/isa/cs423x/Makefile b/sound/isa/cs423x/Makefile
index 2fb4f7409d7c..5067ee001933 100644
--- a/sound/isa/cs423x/Makefile
+++ b/sound/isa/cs423x/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
snd-cs4231-lib-objs := cs4231_lib.o
@@ -10,17 +10,8 @@ snd-cs4232-objs := cs4232.o
snd-cs4236-objs := cs4236.o
# Toplevel Module Dependency
-obj-$(CONFIG_SND_AZT2320) += snd-cs4231-lib.o
-obj-$(CONFIG_SND_MIRO) += snd-cs4231-lib.o
-obj-$(CONFIG_SND_OPL3SA2) += snd-cs4231-lib.o
-obj-$(CONFIG_SND_CS4231) += snd-cs4231.o snd-cs4231-lib.o
-obj-$(CONFIG_SND_CS4232) += snd-cs4232.o snd-cs4231-lib.o
-obj-$(CONFIG_SND_CS4236) += snd-cs4236.o snd-cs4236-lib.o snd-cs4231-lib.o
-obj-$(CONFIG_SND_GUSMAX) += snd-cs4231-lib.o
-obj-$(CONFIG_SND_INTERWAVE) += snd-cs4231-lib.o
-obj-$(CONFIG_SND_INTERWAVE_STB) += snd-cs4231-lib.o
-obj-$(CONFIG_SND_OPTI92X_CS4231) += snd-cs4231-lib.o
-obj-$(CONFIG_SND_WAVEFRONT) += snd-cs4231-lib.o
-obj-$(CONFIG_SND_SSCAPE) += snd-cs4231-lib.o
+obj-$(CONFIG_SND_CS4231_LIB) += snd-cs4231-lib.o
+obj-$(CONFIG_SND_CS4231) += snd-cs4231.o
+obj-$(CONFIG_SND_CS4232) += snd-cs4232.o
+obj-$(CONFIG_SND_CS4236) += snd-cs4236.o snd-cs4236-lib.o
-obj-m := $(sort $(obj-m))
diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c
index ac4041134150..13db6842eaaa 100644
--- a/sound/isa/cs423x/cs4231.c
+++ b/sound/isa/cs423x/cs4231.c
@@ -1,6 +1,6 @@
/*
* Generic driver for CS4231 chips
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Originally the CS4232/CS4232A driver, modified for use on CS4231 by
* Tugrul Galatali <galatalt@stuy.edu>
*
@@ -36,7 +36,7 @@
#define DEV_NAME "cs4231"
MODULE_DESCRIPTION(CRD_NAME);
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Crystal Semiconductors,CS4231}}");
diff --git a/sound/isa/cs423x/cs4231_lib.c b/sound/isa/cs423x/cs4231_lib.c
index 914d77b61b0c..a5eb9659b519 100644
--- a/sound/isa/cs423x/cs4231_lib.c
+++ b/sound/isa/cs423x/cs4231_lib.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Routines for control of CS4231(A)/CS4232/InterWave & compatible chips
*
* Bugs:
@@ -39,7 +39,7 @@
#include <asm/dma.h>
#include <asm/irq.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Routines for control of CS4231(A)/CS4232/InterWave & compatible chips");
MODULE_LICENSE("GPL");
@@ -74,7 +74,7 @@ static unsigned int rates[14] = {
};
static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
- .count = 14,
+ .count = ARRAY_SIZE(rates),
.list = rates,
.mask = 0,
};
@@ -134,29 +134,31 @@ static inline u8 cs4231_inb(struct snd_cs4231 *chip, u8 offset)
return inb(chip->port + offset);
}
-static void snd_cs4231_outm(struct snd_cs4231 *chip, unsigned char reg,
- unsigned char mask, unsigned char value)
+static void snd_cs4231_wait(struct snd_cs4231 *chip)
{
int timeout;
- unsigned char tmp;
for (timeout = 250;
timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
timeout--)
udelay(100);
+}
+
+static void snd_cs4231_outm(struct snd_cs4231 *chip, unsigned char reg,
+ unsigned char mask, unsigned char value)
+{
+ unsigned char tmp = (chip->image[reg] & mask) | value;
+
+ snd_cs4231_wait(chip);
#ifdef CONFIG_SND_DEBUG
if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
snd_printk("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
#endif
- if (chip->calibrate_mute) {
- chip->image[reg] &= mask;
- chip->image[reg] |= value;
- } else {
+ chip->image[reg] = tmp;
+ if (!chip->calibrate_mute) {
cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
- mb();
- tmp = (chip->image[reg] & mask) | value;
+ wmb();
cs4231_outb(chip, CS4231P(REG), tmp);
- chip->image[reg] = tmp;
mb();
}
}
@@ -176,12 +178,7 @@ static void snd_cs4231_dout(struct snd_cs4231 *chip, unsigned char reg, unsigned
void snd_cs4231_out(struct snd_cs4231 *chip, unsigned char reg, unsigned char value)
{
- int timeout;
-
- for (timeout = 250;
- timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
- timeout--)
- udelay(100);
+ snd_cs4231_wait(chip);
#ifdef CONFIG_SND_DEBUG
if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
snd_printk("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
@@ -190,19 +187,13 @@ void snd_cs4231_out(struct snd_cs4231 *chip, unsigned char reg, unsigned char va
cs4231_outb(chip, CS4231P(REG), value);
chip->image[reg] = value;
mb();
-#if 0
- printk("codec out - reg 0x%x = 0x%x\n", chip->mce_bit | reg, value);
-#endif
+ snd_printdd("codec out - reg 0x%x = 0x%x\n",
+ chip->mce_bit | reg, value);
}
unsigned char snd_cs4231_in(struct snd_cs4231 *chip, unsigned char reg)
{
- int timeout;
-
- for (timeout = 250;
- timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
- timeout--)
- udelay(100);
+ snd_cs4231_wait(chip);
#ifdef CONFIG_SND_DEBUG
if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
snd_printk("in: auto calibration time out - reg = 0x%x\n", reg);
@@ -304,8 +295,7 @@ void snd_cs4231_mce_up(struct snd_cs4231 *chip)
unsigned long flags;
int timeout;
- for (timeout = 250; timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT); timeout--)
- udelay(100);
+ snd_cs4231_wait(chip);
#ifdef CONFIG_SND_DEBUG
if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
snd_printk("mce_up - auto calibration time out (0)\n");
@@ -323,12 +313,11 @@ void snd_cs4231_mce_up(struct snd_cs4231 *chip)
void snd_cs4231_mce_down(struct snd_cs4231 *chip)
{
unsigned long flags;
+ unsigned long end_time;
int timeout;
snd_cs4231_busy_wait(chip);
-#if 0
- printk("(1) timeout = %i\n", timeout);
-#endif
+
#ifdef CONFIG_SND_DEBUG
if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
snd_printk("mce_down [0x%lx] - auto calibration time out (0)\n", (long)CS4231P(REGSEL));
@@ -346,42 +335,42 @@ void snd_cs4231_mce_down(struct snd_cs4231 *chip)
}
snd_cs4231_busy_wait(chip);
- /* calibration process */
+ /*
+ * Wait for (possible -- during init auto-calibration may not be set)
+ * calibration process to start. Needs upto 5 sample periods on AD1848
+ * which at the slowest possible rate of 5.5125 kHz means 907 us.
+ */
+ msleep(1);
- for (timeout = 500; timeout > 0 && (snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) == 0; timeout--)
- udelay(10);
- if ((snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) == 0) {
- snd_printd("cs4231_mce_down - auto calibration time out (1)\n");
- return;
- }
-#if 0
- printk("(2) timeout = %i, jiffies = %li\n", timeout, jiffies);
-#endif
- /* in 10 ms increments, check condition, up to 250 ms */
- timeout = 25;
- while (snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) {
- if (--timeout < 0) {
- snd_printk("mce_down - auto calibration time out (2)\n");
+ snd_printdd("(1) jiffies = %lu\n", jiffies);
+
+ /* check condition up to 250 ms */
+ end_time = jiffies + msecs_to_jiffies(250);
+ while (snd_cs4231_in(chip, CS4231_TEST_INIT) &
+ CS4231_CALIB_IN_PROGRESS) {
+
+ if (time_after(jiffies, end_time)) {
+ snd_printk(KERN_ERR "mce_down - "
+ "auto calibration time out (2)\n");
return;
}
- msleep(10);
+ msleep(1);
}
-#if 0
- printk("(3) jiffies = %li\n", jiffies);
-#endif
- /* in 10 ms increments, check condition, up to 100 ms */
- timeout = 10;
+
+ snd_printdd("(2) jiffies = %lu\n", jiffies);
+
+ /* check condition up to 100 ms */
+ end_time = jiffies + msecs_to_jiffies(100);
while (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) {
- if (--timeout < 0) {
+ if (time_after(jiffies, end_time)) {
snd_printk(KERN_ERR "mce_down - auto calibration time out (3)\n");
return;
}
- msleep(10);
+ msleep(1);
}
-#if 0
- printk("(4) jiffies = %li\n", jiffies);
- snd_printk("mce_down - exit = 0x%x\n", cs4231_inb(chip, CS4231P(REGSEL)));
-#endif
+
+ snd_printdd("(3) jiffies = %lu\n", jiffies);
+ snd_printd("mce_down - exit = 0x%x\n", cs4231_inb(chip, CS4231P(REGSEL)));
}
static unsigned int snd_cs4231_get_count(unsigned char format, unsigned int size)
@@ -459,11 +448,11 @@ static unsigned char snd_cs4231_get_rate(unsigned int rate)
{
int i;
- for (i = 0; i < 14; i++)
+ for (i = 0; i < ARRAY_SIZE(rates); i++)
if (rate == rates[i])
return freq_bits[i];
// snd_BUG();
- return freq_bits[13];
+ return freq_bits[ARRAY_SIZE(rates) - 1];
}
static unsigned char snd_cs4231_get_format(struct snd_cs4231 *chip,
@@ -555,6 +544,8 @@ static void snd_cs4231_playback_format(struct snd_cs4231 *chip,
snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, chip->image[CS4231_PLAYBK_FORMAT] = pdfr);
}
spin_unlock_irqrestore(&chip->reg_lock, flags);
+ if (chip->hardware == CS4231_HW_OPL3SA2)
+ udelay(100); /* this seems to help */
snd_cs4231_mce_down(chip);
}
snd_cs4231_calibrate_mute(chip, 0);
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c
index 1a14f33b6ab0..5784b43f4123 100644
--- a/sound/isa/cs423x/cs4236.c
+++ b/sound/isa/cs423x/cs4236.c
@@ -1,6 +1,6 @@
/*
* Driver for generic CS4232/CS4235/CS4236/CS4236B/CS4237B/CS4238B/CS4239 chips
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -32,7 +32,7 @@
#include <sound/opl3.h>
#include <sound/initval.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_LICENSE("GPL");
#ifdef CS4232
MODULE_DESCRIPTION("Cirrus Logic CS4232");
diff --git a/sound/isa/cs423x/cs4236_lib.c b/sound/isa/cs423x/cs4236_lib.c
index 7a5a6c71f5e4..6bd064470d4c 100644
--- a/sound/isa/cs423x/cs4236_lib.c
+++ b/sound/isa/cs423x/cs4236_lib.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Routines for control of CS4235/4236B/4237B/4238B/4239 chips
*
* Note:
@@ -89,7 +89,7 @@
#include <sound/cs4231.h>
#include <sound/asoundef.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Routines for control of CS4235/4236B/4237B/4238B/4239 chips");
MODULE_LICENSE("GPL");
diff --git a/sound/isa/es1688/Makefile b/sound/isa/es1688/Makefile
index 501c8bf903af..aee1e4ddb22a 100644
--- a/sound/isa/es1688/Makefile
+++ b/sound/isa/es1688/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
snd-es1688-lib-objs := es1688_lib.o
diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c
index edc398712e8b..74bbc92f2e7c 100644
--- a/sound/isa/es1688/es1688.c
+++ b/sound/isa/es1688/es1688.c
@@ -1,6 +1,6 @@
/*
* Driver for generic ESS AudioDrive ESx688 soundcards
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -39,7 +39,7 @@
#define DEV_NAME "es1688"
MODULE_DESCRIPTION(CRD_NAME);
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{ESS,ES688 PnP AudioDrive,pnp:ESS0100},"
"{ESS,ES1688 PnP AudioDrive,pnp:ESS0102},"
diff --git a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c
index a2ab99f2ac35..5c26d495daa8 100644
--- a/sound/isa/es1688/es1688_lib.c
+++ b/sound/isa/es1688/es1688_lib.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Routines for control of ESS ES1688/688/488 chip
*
*
@@ -32,7 +32,7 @@
#include <asm/io.h>
#include <asm/dma.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("ESS ESx688 lowlevel module");
MODULE_LICENSE("GPL");
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
index f7732bf90be3..c1af28fd4a1f 100644
--- a/sound/isa/es18xx.c
+++ b/sound/isa/es18xx.c
@@ -623,7 +623,7 @@ static int snd_es18xx_capture_prepare(struct snd_pcm_substream *substream)
(snd_pcm_format_width(runtime->format) == 16 ? 0x04 : 0x00) |
(snd_pcm_format_unsigned(runtime->format) ? 0x00 : 0x20));
- /* Set DMA controler */
+ /* Set DMA controller */
snd_dma_program(chip->dma1, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT);
return 0;
@@ -689,7 +689,7 @@ static int snd_es18xx_playback2_prepare(struct snd_es18xx *chip,
(snd_pcm_format_width(runtime->format) == 16 ? 0x04 : 0x00) |
(snd_pcm_format_unsigned(runtime->format) ? 0x00 : 0x20));
- /* Set DMA controler */
+ /* Set DMA controller */
snd_dma_program(chip->dma1, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT);
return 0;
@@ -1071,14 +1071,7 @@ static int snd_es18xx_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem
return (snd_es18xx_mixer_bits(chip, 0x1c, 0x07, val) != val) || retVal;
}
-static int snd_es18xx_info_spatializer_enable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_es18xx_info_spatializer_enable snd_ctl_boolean_mono_info
static int snd_es18xx_get_spatializer_enable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -1120,14 +1113,7 @@ static int snd_es18xx_get_hw_volume(struct snd_kcontrol *kcontrol, struct snd_ct
return 0;
}
-static int snd_es18xx_info_hw_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 2;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_es18xx_info_hw_switch snd_ctl_boolean_stereo_info
static int snd_es18xx_get_hw_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -2042,6 +2028,7 @@ static int pnpc_registered;
static struct pnp_device_id snd_audiodrive_pnpbiosids[] = {
{ .id = "ESS1869" },
+ { .id = "ESS1879" },
{ .id = "" } /* end */
};
diff --git a/sound/isa/gus/Makefile b/sound/isa/gus/Makefile
index bae5dbd6c8e5..df3d59f25f5e 100644
--- a/sound/isa/gus/Makefile
+++ b/sound/isa/gus/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
snd-gus-lib-objs := gus_main.o \
diff --git a/sound/isa/gus/gus_dma.c b/sound/isa/gus/gus_dma.c
index 44ee5d3674a1..fc905141e8a5 100644
--- a/sound/isa/gus/gus_dma.c
+++ b/sound/isa/gus/gus_dma.c
@@ -1,6 +1,6 @@
/*
* Routines for GF1 DMA control
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/isa/gus/gus_dram.c b/sound/isa/gus/gus_dram.c
index f22fe7967fcc..9eaa932f6efe 100644
--- a/sound/isa/gus/gus_dram.c
+++ b/sound/isa/gus/gus_dram.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* DRAM access routines
*
*
diff --git a/sound/isa/gus/gus_instr.c b/sound/isa/gus/gus_instr.c
index d0c38e1856ef..bf137ea72329 100644
--- a/sound/isa/gus/gus_instr.c
+++ b/sound/isa/gus/gus_instr.c
@@ -1,6 +1,6 @@
/*
* Routines for Gravis UltraSound soundcards - Synthesizer
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/isa/gus/gus_io.c b/sound/isa/gus/gus_io.c
index 9b1fe292de4d..3d4f899285ef 100644
--- a/sound/isa/gus/gus_io.c
+++ b/sound/isa/gus/gus_io.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* I/O routines for GF1/InterWave synthesizer chips
*
*
diff --git a/sound/isa/gus/gus_irq.c b/sound/isa/gus/gus_irq.c
index 537d3cfe41f3..cd9a6f1c99e6 100644
--- a/sound/isa/gus/gus_irq.c
+++ b/sound/isa/gus/gus_irq.c
@@ -1,6 +1,6 @@
/*
* Routine for IRQ handling from GF1/InterWave chip
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -45,11 +45,13 @@ __again:
// snd_printk("IRQ: status = 0x%x\n", status);
if (status & 0x02) {
STAT_ADD(gus->gf1.interrupt_stat_midi_in);
- gus->gf1.interrupt_handler_midi_in(gus);
+ if (gus->gf1.interrupt_handler_midi_in)
+ gus->gf1.interrupt_handler_midi_in(gus);
}
if (status & 0x01) {
STAT_ADD(gus->gf1.interrupt_stat_midi_out);
- gus->gf1.interrupt_handler_midi_out(gus);
+ if (gus->gf1.interrupt_handler_midi_out)
+ gus->gf1.interrupt_handler_midi_out(gus);
}
if (status & (0x20 | 0x40)) {
unsigned int already, _current_;
@@ -85,20 +87,24 @@ __again:
}
if (status & 0x04) {
STAT_ADD(gus->gf1.interrupt_stat_timer1);
- gus->gf1.interrupt_handler_timer1(gus);
+ if (gus->gf1.interrupt_handler_timer1)
+ gus->gf1.interrupt_handler_timer1(gus);
}
if (status & 0x08) {
STAT_ADD(gus->gf1.interrupt_stat_timer2);
- gus->gf1.interrupt_handler_timer2(gus);
+ if (gus->gf1.interrupt_handler_timer2)
+ gus->gf1.interrupt_handler_timer2(gus);
}
if (status & 0x80) {
if (snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL) & 0x40) {
STAT_ADD(gus->gf1.interrupt_stat_dma_write);
- gus->gf1.interrupt_handler_dma_write(gus);
+ if (gus->gf1.interrupt_handler_dma_write)
+ gus->gf1.interrupt_handler_dma_write(gus);
}
if (snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL) & 0x40) {
STAT_ADD(gus->gf1.interrupt_stat_dma_read);
- gus->gf1.interrupt_handler_dma_read(gus);
+ if (gus->gf1.interrupt_handler_dma_read)
+ gus->gf1.interrupt_handler_dma_read(gus);
}
}
if (--loop > 0)
diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c
index 8ced5e81b9a7..b14d5d6d9a32 100644
--- a/sound/isa/gus/gus_main.c
+++ b/sound/isa/gus/gus_main.c
@@ -1,6 +1,6 @@
/*
* Routines for Gravis UltraSound soundcards
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -31,7 +31,7 @@
#include <asm/dma.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Routines for Gravis UltraSound soundcards");
MODULE_LICENSE("GPL");
@@ -154,6 +154,14 @@ int snd_gus_create(struct snd_card *card,
gus = kzalloc(sizeof(*gus), GFP_KERNEL);
if (gus == NULL)
return -ENOMEM;
+ spin_lock_init(&gus->reg_lock);
+ spin_lock_init(&gus->voice_alloc);
+ spin_lock_init(&gus->active_voice_lock);
+ spin_lock_init(&gus->event_lock);
+ spin_lock_init(&gus->dma_lock);
+ spin_lock_init(&gus->pcm_volume_level_lock);
+ spin_lock_init(&gus->uart_cmd_lock);
+ mutex_init(&gus->dma_mutex);
gus->gf1.irq = -1;
gus->gf1.dma1 = -1;
gus->gf1.dma2 = -1;
@@ -218,14 +226,6 @@ int snd_gus_create(struct snd_card *card,
gus->gf1.pcm_channels = pcm_channels;
gus->gf1.volume_ramp = 25;
gus->gf1.smooth_pan = 1;
- spin_lock_init(&gus->reg_lock);
- spin_lock_init(&gus->voice_alloc);
- spin_lock_init(&gus->active_voice_lock);
- spin_lock_init(&gus->event_lock);
- spin_lock_init(&gus->dma_lock);
- spin_lock_init(&gus->pcm_volume_level_lock);
- spin_lock_init(&gus->uart_cmd_lock);
- mutex_init(&gus->dma_mutex);
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, gus, &ops)) < 0) {
snd_gus_free(gus);
return err;
@@ -398,7 +398,7 @@ static int snd_gus_check_version(struct snd_gus_card * gus)
gus->ess_flag = 1;
} else {
snd_printk(KERN_ERR "unknown GF1 revision number at 0x%lx - 0x%x (0x%x)\n", gus->gf1.port, rev, val);
- snd_printk(KERN_ERR " please - report to <perex@suse.cz>\n");
+ snd_printk(KERN_ERR " please - report to <perex@perex.cz>\n");
}
}
}
diff --git a/sound/isa/gus/gus_mem.c b/sound/isa/gus/gus_mem.c
index 7107753b85b5..bcf4656853c4 100644
--- a/sound/isa/gus/gus_mem.c
+++ b/sound/isa/gus/gus_mem.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* GUS's memory allocation routines / bottom layer
*
*
diff --git a/sound/isa/gus/gus_mem_proc.c b/sound/isa/gus/gus_mem_proc.c
index 80f0a83818b2..f69a44728ebf 100644
--- a/sound/isa/gus/gus_mem_proc.c
+++ b/sound/isa/gus/gus_mem_proc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* GUS's memory access via proc filesystem
*
*
diff --git a/sound/isa/gus/gus_mixer.c b/sound/isa/gus/gus_mixer.c
index acc25a297200..a96253e16654 100644
--- a/sound/isa/gus/gus_mixer.c
+++ b/sound/isa/gus/gus_mixer.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Routines for control of ICS 2101 chip and "mixer" in GF1 chip
*
*
@@ -36,14 +36,7 @@
.get = snd_gf1_get_single, .put = snd_gf1_put_single, \
.private_value = shift | (invert << 8) }
-static int snd_gf1_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_gf1_info_single snd_ctl_boolean_mono_info
static int snd_gf1_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c
index c7f95e7aa018..a7971f5ffe63 100644
--- a/sound/isa/gus/gus_pcm.c
+++ b/sound/isa/gus/gus_pcm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Routines for control of GF1 chip (PCM things)
*
* InterWave chips supports interleaved DMA, but this feature isn't used in
diff --git a/sound/isa/gus/gus_reset.c b/sound/isa/gus/gus_reset.c
index b263655c4116..20cfdb87f84a 100644
--- a/sound/isa/gus/gus_reset.c
+++ b/sound/isa/gus/gus_reset.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/isa/gus/gus_sample.c b/sound/isa/gus/gus_sample.c
index 9e0c55ab25b2..cba0829a7106 100644
--- a/sound/isa/gus/gus_sample.c
+++ b/sound/isa/gus/gus_sample.c
@@ -1,6 +1,6 @@
/*
* Routines for Gravis UltraSound soundcards - Sample support
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/isa/gus/gus_simple.c b/sound/isa/gus/gus_simple.c
index dcad6ed0198c..39d121e2c8c4 100644
--- a/sound/isa/gus/gus_simple.c
+++ b/sound/isa/gus/gus_simple.c
@@ -1,6 +1,6 @@
/*
* Routines for Gravis UltraSound soundcards - Simple instrument handlers
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/isa/gus/gus_synth.c b/sound/isa/gus/gus_synth.c
index 3e4d4d6edd8b..2c2051782aa2 100644
--- a/sound/isa/gus/gus_synth.c
+++ b/sound/isa/gus/gus_synth.c
@@ -1,6 +1,6 @@
/*
* Routines for Gravis UltraSound soundcards - Synthesizer
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -26,7 +26,7 @@
#include <sound/gus.h>
#include <sound/seq_device.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Routines for Gravis UltraSound soundcards - Synthesizer");
MODULE_LICENSE("GPL");
diff --git a/sound/isa/gus/gus_tables.h b/sound/isa/gus/gus_tables.h
index 4adf098d3269..42a4ca0d622b 100644
--- a/sound/isa/gus/gus_tables.h
+++ b/sound/isa/gus/gus_tables.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/isa/gus/gus_timer.c b/sound/isa/gus/gus_timer.c
index a43b662f17c7..99eac573c414 100644
--- a/sound/isa/gus/gus_timer.c
+++ b/sound/isa/gus/gus_timer.c
@@ -1,6 +1,6 @@
/*
* Routines for Gravis UltraSound soundcards - Timers
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
* GUS have similar timers as AdLib (OPL2/OPL3 chips).
*
diff --git a/sound/isa/gus/gus_uart.c b/sound/isa/gus/gus_uart.c
index 654290a8b21c..e6fd9b01c492 100644
--- a/sound/isa/gus/gus_uart.c
+++ b/sound/isa/gus/gus_uart.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Routines for the GF1 MIDI interface - like UART 6850
*
*
diff --git a/sound/isa/gus/gus_volume.c b/sound/isa/gus/gus_volume.c
index dbbc0a6d7659..71a67744a14b 100644
--- a/sound/isa/gus/gus_volume.c
+++ b/sound/isa/gus/gus_volume.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c
index 8f23f433d491..29e422b00b58 100644
--- a/sound/isa/gus/gusclassic.c
+++ b/sound/isa/gus/gusclassic.c
@@ -1,6 +1,6 @@
/*
* Driver for Gravis UltraSound Classic soundcard
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -37,7 +37,7 @@
#define DEV_NAME "gusclassic"
MODULE_DESCRIPTION(CRD_NAME);
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Classic}}");
diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c
index 0aeaa6cf6cf0..fc59536c918e 100644
--- a/sound/isa/gus/gusextreme.c
+++ b/sound/isa/gus/gusextreme.c
@@ -1,6 +1,6 @@
/*
* Driver for Gravis UltraSound Extreme soundcards
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -41,7 +41,7 @@
#define DEV_NAME "gusextreme"
MODULE_DESCRIPTION(CRD_NAME);
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Extreme}}");
diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c
index 708783d4351f..4922f5da08f9 100644
--- a/sound/isa/gus/gusmax.c
+++ b/sound/isa/gus/gusmax.c
@@ -1,6 +1,6 @@
/*
* Driver for Gravis UltraSound MAX soundcard
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -34,7 +34,7 @@
#define SNDRV_LEGACY_FIND_FREE_DMA
#include <sound/initval.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Gravis UltraSound MAX");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound MAX}}");
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
index 0220cdbe1a2a..2091c50b2e3e 100644
--- a/sound/isa/gus/interwave.c
+++ b/sound/isa/gus/interwave.c
@@ -1,6 +1,6 @@
/*
* Driver for AMD InterWave soundcard
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -41,7 +41,7 @@
#define SNDRV_LEGACY_FIND_FREE_DMA
#include <sound/initval.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_LICENSE("GPL");
#ifndef SNDRV_STB
MODULE_DESCRIPTION("AMD InterWave");
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
index e70db32991d9..59af9ab7191f 100644
--- a/sound/isa/opl3sa2.c
+++ b/sound/isa/opl3sa2.c
@@ -1,6 +1,6 @@
/*
* Driver for Yamaha OPL3-SA[2,3] soundcards
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -37,7 +37,7 @@
#include <asm/io.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Yamaha OPL3SA2+");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Yamaha,YMF719E-S},"
@@ -253,6 +253,7 @@ static int __devinit snd_opl3sa2_detect(struct snd_opl3sa2 *chip)
/* 0x03 - YM715B */
/* 0x04 - YM719 - OPL-SA4? */
/* 0x05 - OPL3-SA3 - Libretto 100 */
+ /* 0x07 - unknown - Neomagic MagicWave 3D */
break;
}
str[0] = chip->version + '0';
diff --git a/sound/isa/opti9xx/Makefile b/sound/isa/opti9xx/Makefile
index 0e41bfd5a403..b4d894db257a 100644
--- a/sound/isa/opti9xx/Makefile
+++ b/sound/isa/opti9xx/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
snd-opti92x-ad1848-objs := opti92x-ad1848.o
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c
index cd29b30b362e..d295936611f8 100644
--- a/sound/isa/opti9xx/miro.c
+++ b/sound/isa/opti9xx/miro.c
@@ -242,14 +242,7 @@ static int aci_setvalue(struct snd_miro * miro, unsigned char index, int value)
* MIXER part
*/
-static int snd_miro_info_capture(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
-
- return 0;
-}
+#define snd_miro_info_capture snd_ctl_boolean_mono_info
static int snd_miro_get_capture(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -344,14 +337,7 @@ static int snd_miro_put_preamp(struct snd_kcontrol *kcontrol,
return change;
}
-static int snd_miro_info_amp(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
-
- return 0;
-}
+#define snd_miro_info_amp snd_ctl_boolean_mono_info
static int snd_miro_get_amp(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
index 049d479ce2b3..ee1a824d8fc0 100644
--- a/sound/isa/opti9xx/opti92x-ad1848.c
+++ b/sound/isa/opti9xx/opti92x-ad1848.c
@@ -501,6 +501,16 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip)
(chip->hardware == OPTi9XX_HW_82C930 ? 0x00 : 0x04),
0x34);
snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x20, 0xbf);
+ /*
+ * The BTC 1817DW has QS1000 wavetable which is connected
+ * to the serial digital input of the OPTI931.
+ */
+ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(21), 0x82, 0xff);
+ /*
+ * This bit sets OPTI931 to automaticaly select FM
+ * or digital input signal.
+ */
+ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(26), 0x01, 0x01);
break;
#endif /* OPTi93X */
@@ -1732,11 +1742,11 @@ static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip,
#ifdef OPTi93X
port = pnp_port_start(pdev, 0) - 4;
- fm_port = pnp_port_start(pdev, 1);
+ fm_port = pnp_port_start(pdev, 1) + 8;
#else
if (pid->driver_data != 0x0924)
port = pnp_port_start(pdev, 1);
- fm_port = pnp_port_start(pdev, 2);
+ fm_port = pnp_port_start(pdev, 2) + 8;
#endif /* OPTi93X */
irq = pnp_irq(pdev, 0);
dma1 = pnp_dma(pdev, 0);
diff --git a/sound/isa/sb/Makefile b/sound/isa/sb/Makefile
index 556e66928029..c9d1c986d70e 100644
--- a/sound/isa/sb/Makefile
+++ b/sound/isa/sb/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
snd-sb-common-objs := sb_common.o sb_mixer.o
diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c
index 658179e86142..4eea84cfd4f4 100644
--- a/sound/isa/sb/emu8000.c
+++ b/sound/isa/sb/emu8000.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* and (c) 1999 Steve Ratcliffe <steve@parabola.demon.co.uk>
* Copyright (C) 1999-2000 Takashi Iwai <tiwai@suse.de>
*
diff --git a/sound/isa/sb/emu8000_synth.c b/sound/isa/sb/emu8000_synth.c
index 3d72742b342f..0c7905c85b76 100644
--- a/sound/isa/sb/emu8000_synth.c
+++ b/sound/isa/sb/emu8000_synth.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* and (c) 1999 Steve Ratcliffe <steve@parabola.demon.co.uk>
* Copyright (C) 1999-2000 Takashi Iwai <tiwai@suse.de>
*
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c
index c4ba24bfd27c..e7f9edd92626 100644
--- a/sound/isa/sb/sb16.c
+++ b/sound/isa/sb/sb16.c
@@ -1,6 +1,6 @@
/*
* Driver for SoundBlaster 16/AWE32/AWE64 soundcards
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -44,7 +44,7 @@
#define PFX "sb16: "
#endif
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_LICENSE("GPL");
#ifndef SNDRV_SBAWE
MODULE_DESCRIPTION("Sound Blaster 16");
diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c
index b279f2308aef..3682059787ab 100644
--- a/sound/isa/sb/sb16_csp.c
+++ b/sound/isa/sb/sb16_csp.c
@@ -979,14 +979,7 @@ static int snd_sb_csp_restart(struct snd_sb_csp * p)
* QSound mixer control for PCM
*/
-static int snd_sb_qsound_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_sb_qsound_switch_info snd_ctl_boolean_mono_info
static int snd_sb_qsound_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
diff --git a/sound/isa/sb/sb16_main.c b/sound/isa/sb/sb16_main.c
index 5d4d3aafe2d5..c06754f7ee5d 100644
--- a/sound/isa/sb/sb16_main.c
+++ b/sound/isa/sb/sb16_main.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Routines for control of 16-bit SoundBlaster cards and clones
* Note: This is very ugly hardware which uses one 8-bit DMA channel and
* second 16-bit DMA channel. Unfortunately 8-bit DMA channel can't
@@ -45,7 +45,7 @@
#include <sound/control.h>
#include <sound/info.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Routines for control of 16-bit SoundBlaster cards and clones");
MODULE_LICENSE("GPL");
diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c
index a1b3786b391e..f933aef7d8a9 100644
--- a/sound/isa/sb/sb8.c
+++ b/sound/isa/sb/sb8.c
@@ -1,6 +1,6 @@
/*
* Driver for SoundBlaster 1.0/2.0/Pro soundcards and compatible
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -31,7 +31,7 @@
#include <sound/opl3.h>
#include <sound/initval.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Sound Blaster 1.0/2.0/Pro");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB 1.0/SB 2.0/SB Pro}}");
diff --git a/sound/isa/sb/sb8_main.c b/sound/isa/sb/sb8_main.c
index aea9e5ec7b36..bee894b3f5c7 100644
--- a/sound/isa/sb/sb8_main.c
+++ b/sound/isa/sb/sb8_main.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Uros Bizjak <uros@kss-loka.si>
*
* Routines for control of 8-bit SoundBlaster cards and clones
@@ -38,7 +38,7 @@
#include <sound/core.h>
#include <sound/sb.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Uros Bizjak <uros@kss-loka.si>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Uros Bizjak <uros@kss-loka.si>");
MODULE_DESCRIPTION("Routines for control of 8-bit SoundBlaster cards and clones");
MODULE_LICENSE("GPL");
diff --git a/sound/isa/sb/sb8_midi.c b/sound/isa/sb/sb8_midi.c
index 0b67edd7ac6e..e56e5633411c 100644
--- a/sound/isa/sb/sb8_midi.c
+++ b/sound/isa/sb/sb8_midi.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Routines for control of SoundBlaster cards - MIDI interface
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c
index efa9d5c2558a..176193c05101 100644
--- a/sound/isa/sb/sb_common.c
+++ b/sound/isa/sb/sb_common.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Uros Bizjak <uros@kss-loka.si>
*
* Lowlevel routines for control of Sound Blaster cards
@@ -33,7 +33,7 @@
#include <asm/io.h>
#include <asm/dma.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("ALSA lowlevel driver for Sound Blaster cards");
MODULE_LICENSE("GPL");
@@ -234,7 +234,9 @@ int snd_sbdsp_create(struct snd_card *card,
chip->dma16 = -1;
chip->port = port;
- if (request_irq(irq, irq_handler, hardware == SB_HW_ALS4000 ?
+ if (request_irq(irq, irq_handler,
+ (hardware == SB_HW_ALS4000 ||
+ hardware == SB_HW_CS5530) ?
IRQF_SHARED : IRQF_DISABLED,
"SoundBlaster", (void *) chip)) {
snd_printk(KERN_ERR "sb: can't grab irq %d\n", irq);
diff --git a/sound/isa/sb/sb_mixer.c b/sound/isa/sb/sb_mixer.c
index 3d4befcff28e..03241cd5aaef 100644
--- a/sound/isa/sb/sb_mixer.c
+++ b/sound/isa/sb/sb_mixer.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Routines for Sound Blaster mixer control
*
*
diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c
new file mode 100644
index 000000000000..94daf8399994
--- /dev/null
+++ b/sound/isa/sc6000.c
@@ -0,0 +1,656 @@
+/*
+ * Driver for Gallant SC-6000 soundcard. This card is also known as
+ * Audio Excel DSP 16 or Zoltrix AV302.
+ * These cards use CompuMedia ASC-9308 chip + AD1848 codec.
+ *
+ * Copyright (C) 2007 Krzysztof Helt <krzysztof.h1@wp.pl>
+ *
+ * I don't have documentation for this card. I used the driver
+ * for OSS/Free included in the kernel source as reference.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <sound/driver.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/isa.h>
+#include <linux/io.h>
+#include <asm/dma.h>
+#include <sound/core.h>
+#include <sound/ad1848.h>
+#include <sound/opl3.h>
+#include <sound/mpu401.h>
+#include <sound/control.h>
+#define SNDRV_LEGACY_FIND_FREE_IRQ
+#define SNDRV_LEGACY_FIND_FREE_DMA
+#include <sound/initval.h>
+
+MODULE_AUTHOR("Krzysztof Helt");
+MODULE_DESCRIPTION("Gallant SC-6000");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{Gallant, SC-6000},"
+ "{AudioExcel, Audio Excel DSP 16},"
+ "{Zoltrix, AV302}}");
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
+static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220, 0x240 */
+static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5, 7, 9, 10, 11 */
+static long mss_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x530, 0xe80 */
+static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
+ /* 0x300, 0x310, 0x320, 0x330 */
+static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5, 7, 9, 10, 0 */
+static int dma[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0, 1, 3 */
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for sc-6000 based soundcard.");
+module_param_array(id, charp, NULL, 0444);
+MODULE_PARM_DESC(id, "ID string for sc-6000 based soundcard.");
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable sc-6000 based soundcard.");
+module_param_array(port, long, NULL, 0444);
+MODULE_PARM_DESC(port, "Port # for sc-6000 driver.");
+module_param_array(mss_port, long, NULL, 0444);
+MODULE_PARM_DESC(mss_port, "MSS Port # for sc-6000 driver.");
+module_param_array(mpu_port, long, NULL, 0444);
+MODULE_PARM_DESC(mpu_port, "MPU-401 port # for sc-6000 driver.");
+module_param_array(irq, int, NULL, 0444);
+MODULE_PARM_DESC(irq, "IRQ # for sc-6000 driver.");
+module_param_array(mpu_irq, int, NULL, 0444);
+MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for sc-6000 driver.");
+module_param_array(dma, int, NULL, 0444);
+MODULE_PARM_DESC(dma, "DMA # for sc-6000 driver.");
+
+/*
+ * Commands of SC6000's DSP (SBPRO+special).
+ * Some of them are COMMAND_xx, in the future they may change.
+ */
+#define WRITE_MDIRQ_CFG 0x50 /* Set M&I&DRQ mask (the real config) */
+#define COMMAND_52 0x52 /* */
+#define READ_HARD_CFG 0x58 /* Read Hardware Config (I/O base etc) */
+#define COMMAND_5C 0x5c /* */
+#define COMMAND_60 0x60 /* */
+#define COMMAND_66 0x66 /* */
+#define COMMAND_6C 0x6c /* */
+#define COMMAND_6E 0x6e /* */
+#define COMMAND_88 0x88 /* Unknown command */
+#define DSP_INIT_MSS 0x8c /* Enable Microsoft Sound System mode */
+#define COMMAND_C5 0xc5 /* */
+#define GET_DSP_VERSION 0xe1 /* Get DSP Version */
+#define GET_DSP_COPYRIGHT 0xe3 /* Get DSP Copyright */
+
+/*
+ * Offsets of SC6000 DSP I/O ports. The offset is added to base I/O port
+ * to have the actual I/O port.
+ * Register permissions are:
+ * (wo) == Write Only
+ * (ro) == Read Only
+ * (w-) == Write
+ * (r-) == Read
+ */
+#define DSP_RESET 0x06 /* offset of DSP RESET (wo) */
+#define DSP_READ 0x0a /* offset of DSP READ (ro) */
+#define DSP_WRITE 0x0c /* offset of DSP WRITE (w-) */
+#define DSP_COMMAND 0x0c /* offset of DSP COMMAND (w-) */
+#define DSP_STATUS 0x0c /* offset of DSP STATUS (r-) */
+#define DSP_DATAVAIL 0x0e /* offset of DSP DATA AVAILABLE (ro) */
+
+#define PFX "sc6000: "
+#define DRV_NAME "SC-6000"
+
+/* hardware dependent functions */
+
+/*
+ * sc6000_irq_to_softcfg - Decode irq number into cfg code.
+ */
+static __devinit unsigned char sc6000_irq_to_softcfg(int irq)
+{
+ unsigned char val = 0;
+
+ switch (irq) {
+ case 5:
+ val = 0x28;
+ break;
+ case 7:
+ val = 0x8;
+ break;
+ case 9:
+ val = 0x10;
+ break;
+ case 10:
+ val = 0x18;
+ break;
+ case 11:
+ val = 0x20;
+ break;
+ default:
+ break;
+ }
+ return val;
+}
+
+/*
+ * sc6000_dma_to_softcfg - Decode dma number into cfg code.
+ */
+static __devinit unsigned char sc6000_dma_to_softcfg(int dma)
+{
+ unsigned char val = 0;
+
+ switch (dma) {
+ case 0:
+ val = 1;
+ break;
+ case 1:
+ val = 2;
+ break;
+ case 3:
+ val = 3;
+ break;
+ default:
+ break;
+ }
+ return val;
+}
+
+/*
+ * sc6000_mpu_irq_to_softcfg - Decode MPU-401 irq number into cfg code.
+ */
+static __devinit unsigned char sc6000_mpu_irq_to_softcfg(int mpu_irq)
+{
+ unsigned char val = 0;
+
+ switch (mpu_irq) {
+ case 5:
+ val = 4;
+ break;
+ case 7:
+ val = 0x44;
+ break;
+ case 9:
+ val = 0x84;
+ break;
+ case 10:
+ val = 0xc4;
+ break;
+ default:
+ break;
+ }
+ return val;
+}
+
+static __devinit int sc6000_wait_data(char __iomem *vport)
+{
+ int loop = 1000;
+ unsigned char val = 0;
+
+ do {
+ val = ioread8(vport + DSP_DATAVAIL);
+ if (val & 0x80)
+ return 0;
+ cpu_relax();
+ } while (loop--);
+
+ return -EAGAIN;
+}
+
+static __devinit int sc6000_read(char __iomem *vport)
+{
+ if (sc6000_wait_data(vport))
+ return -EBUSY;
+
+ return ioread8(vport + DSP_READ);
+
+}
+
+static __devinit int sc6000_write(char __iomem *vport, int cmd)
+{
+ unsigned char val;
+ int loop = 500000;
+
+ do {
+ val = ioread8(vport + DSP_STATUS);
+ /*
+ * DSP ready to receive data if bit 7 of val == 0
+ */
+ if (!(val & 0x80)) {
+ iowrite8(cmd, vport + DSP_COMMAND);
+ return 0;
+ }
+ cpu_relax();
+ } while (loop--);
+
+ snd_printk(KERN_ERR "DSP Command (0x%x) timeout.\n", cmd);
+
+ return -EIO;
+}
+
+static int __devinit sc6000_dsp_get_answer(char __iomem *vport, int command,
+ char *data, int data_len)
+{
+ int len = 0;
+
+ if (sc6000_write(vport, command)) {
+ snd_printk(KERN_ERR "CMD 0x%x: failed!\n", command);
+ return -EIO;
+ }
+
+ do {
+ int val = sc6000_read(vport);
+
+ if (val < 0)
+ break;
+
+ data[len++] = val;
+
+ } while (len < data_len);
+
+ /*
+ * If no more data available, return to the caller, no error if len>0.
+ * We have no other way to know when the string is finished.
+ */
+ return len ? len : -EIO;
+}
+
+static int __devinit sc6000_dsp_reset(char __iomem *vport)
+{
+ iowrite8(1, vport + DSP_RESET);
+ udelay(10);
+ iowrite8(0, vport + DSP_RESET);
+ udelay(20);
+ if (sc6000_read(vport) == 0xaa)
+ return 0;
+ return -ENODEV;
+}
+
+/* detection and initialization */
+static int __devinit sc6000_cfg_write(char __iomem *vport,
+ unsigned char softcfg)
+{
+
+ if (sc6000_write(vport, WRITE_MDIRQ_CFG)) {
+ snd_printk(KERN_ERR "CMD 0x%x: failed!\n", WRITE_MDIRQ_CFG);
+ return -EIO;
+ }
+ if (sc6000_write(vport, softcfg)) {
+ snd_printk(KERN_ERR "sc6000_cfg_write: failed!\n");
+ return -EIO;
+ }
+ return 0;
+}
+
+static int __devinit sc6000_setup_board(char __iomem *vport, int config)
+{
+ int loop = 10;
+
+ do {
+ if (sc6000_write(vport, COMMAND_88)) {
+ snd_printk(KERN_ERR "CMD 0x%x: failed!\n",
+ COMMAND_88);
+ return -EIO;
+ }
+ } while ((sc6000_wait_data(vport) < 0) && loop--);
+
+ if (sc6000_read(vport) < 0) {
+ snd_printk(KERN_ERR "sc6000_read after CMD 0x%x: failed\n",
+ COMMAND_88);
+ return -EIO;
+ }
+
+ if (sc6000_cfg_write(vport, config))
+ return -ENODEV;
+
+ return 0;
+}
+
+static int __devinit sc6000_init_mss(char __iomem *vport, int config,
+ char __iomem *vmss_port, int mss_config)
+{
+ if (sc6000_write(vport, DSP_INIT_MSS)) {
+ snd_printk(KERN_ERR "sc6000_init_mss [0x%x]: failed!\n",
+ DSP_INIT_MSS);
+ return -EIO;
+ }
+
+ msleep(10);
+
+ if (sc6000_cfg_write(vport, config))
+ return -EIO;
+
+ iowrite8(mss_config, vmss_port);
+
+ return 0;
+}
+
+static int __devinit sc6000_init_board(char __iomem *vport, int irq, int dma,
+ char __iomem *vmss_port, int mpu_irq)
+{
+ char answer[15];
+ char version[2];
+ int mss_config = sc6000_irq_to_softcfg(irq) |
+ sc6000_dma_to_softcfg(dma);
+ int config = mss_config |
+ sc6000_mpu_irq_to_softcfg(mpu_irq);
+ int err;
+
+ err = sc6000_dsp_reset(vport);
+ if (err < 0) {
+ snd_printk(KERN_ERR "sc6000_dsp_reset: failed!\n");
+ return err;
+ }
+
+ memset(answer, 0, sizeof(answer));
+ err = sc6000_dsp_get_answer(vport, GET_DSP_COPYRIGHT, answer, 15);
+ if (err <= 0) {
+ snd_printk(KERN_ERR "sc6000_dsp_copyright: failed!\n");
+ return -ENODEV;
+ }
+ /*
+ * My SC-6000 card return "SC-6000" in DSPCopyright, so
+ * if we have something different, we have to be warned.
+ * Mine returns "SC-6000A " - KH
+ */
+ if (strncmp("SC-6000", answer, 7))
+ snd_printk(KERN_WARNING "Warning: non SC-6000 audio card!\n");
+
+ if (sc6000_dsp_get_answer(vport, GET_DSP_VERSION, version, 2) < 2) {
+ snd_printk(KERN_ERR "sc6000_dsp_version: failed!\n");
+ return -ENODEV;
+ }
+ printk(KERN_INFO PFX "Detected model: %s, DSP version %d.%d\n",
+ answer, version[0], version[1]);
+
+ /*
+ * 0x0A == (IRQ 7, DMA 1, MIRQ 0)
+ */
+ err = sc6000_cfg_write(vport, 0x0a);
+ if (err < 0) {
+ snd_printk(KERN_ERR "sc6000_cfg_write: failed!\n");
+ return -EFAULT;
+ }
+
+ err = sc6000_setup_board(vport, config);
+ if (err < 0) {
+ snd_printk(KERN_ERR "sc6000_setup_board: failed!\n");
+ return -ENODEV;
+ }
+
+ err = sc6000_init_mss(vport, config, vmss_port, mss_config);
+ if (err < 0) {
+ snd_printk(KERN_ERR "Can not initialize"
+ "Microsoft Sound System mode.\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int __devinit snd_sc6000_mixer(struct snd_ad1848 *chip)
+{
+ struct snd_card *card = chip->card;
+ struct snd_ctl_elem_id id1, id2;
+ int err;
+
+ memset(&id1, 0, sizeof(id1));
+ memset(&id2, 0, sizeof(id2));
+ id1.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ /* reassign AUX0 to FM */
+ strcpy(id1.name, "Aux Playback Switch");
+ strcpy(id2.name, "FM Playback Switch");
+ err = snd_ctl_rename_id(card, &id1, &id2);
+ if (err < 0)
+ return err;
+ strcpy(id1.name, "Aux Playback Volume");
+ strcpy(id2.name, "FM Playback Volume");
+ err = snd_ctl_rename_id(card, &id1, &id2);
+ if (err < 0)
+ return err;
+ /* reassign AUX1 to CD */
+ strcpy(id1.name, "Aux Playback Switch"); id1.index = 1;
+ strcpy(id2.name, "CD Playback Switch");
+ err = snd_ctl_rename_id(card, &id1, &id2);
+ if (err < 0)
+ return err;
+ strcpy(id1.name, "Aux Playback Volume");
+ strcpy(id2.name, "CD Playback Volume");
+ err = snd_ctl_rename_id(card, &id1, &id2);
+ if (err < 0)
+ return err;
+ return 0;
+}
+
+static int __devinit snd_sc6000_match(struct device *devptr, unsigned int dev)
+{
+ if (!enable[dev])
+ return 0;
+ if (port[dev] == SNDRV_AUTO_PORT) {
+ printk(KERN_ERR PFX "specify IO port\n");
+ return 0;
+ }
+ if (mss_port[dev] == SNDRV_AUTO_PORT) {
+ printk(KERN_ERR PFX "specify MSS port\n");
+ return 0;
+ }
+ if (port[dev] != 0x220 && port[dev] != 0x240) {
+ printk(KERN_ERR PFX "Port must be 0x220 or 0x240\n");
+ return 0;
+ }
+ if (mss_port[dev] != 0x530 && mss_port[dev] != 0xe80) {
+ printk(KERN_ERR PFX "MSS port must be 0x530 or 0xe80\n");
+ return 0;
+ }
+ if (irq[dev] != SNDRV_AUTO_IRQ && !sc6000_irq_to_softcfg(irq[dev])) {
+ printk(KERN_ERR PFX "invalid IRQ %d\n", irq[dev]);
+ return 0;
+ }
+ if (dma[dev] != SNDRV_AUTO_DMA && !sc6000_dma_to_softcfg(dma[dev])) {
+ printk(KERN_ERR PFX "invalid DMA %d\n", dma[dev]);
+ return 0;
+ }
+ if (mpu_port[dev] != SNDRV_AUTO_PORT &&
+ (mpu_port[dev] & ~0x30L) != 0x300) {
+ printk(KERN_ERR PFX "invalid MPU-401 port %lx\n",
+ mpu_port[dev]);
+ return 0;
+ }
+ if (mpu_port[dev] != SNDRV_AUTO_PORT &&
+ mpu_irq[dev] != SNDRV_AUTO_IRQ && mpu_irq[dev] != 0 &&
+ !sc6000_mpu_irq_to_softcfg(mpu_irq[dev])) {
+ printk(KERN_ERR PFX "invalid MPU-401 IRQ %d\n", mpu_irq[dev]);
+ return 0;
+ }
+ return 1;
+}
+
+static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev)
+{
+ static int possible_irqs[] = { 5, 7, 9, 10, 11, -1 };
+ static int possible_dmas[] = { 1, 3, 0, -1 };
+ int err;
+ int xirq = irq[dev];
+ int xdma = dma[dev];
+ struct snd_card *card;
+ struct snd_ad1848 *chip;
+ struct snd_opl3 *opl3;
+ char __iomem *vport;
+ char __iomem *vmss_port;
+
+
+ card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
+ if (!card)
+ return -ENOMEM;
+
+ if (xirq == SNDRV_AUTO_IRQ) {
+ xirq = snd_legacy_find_free_irq(possible_irqs);
+ if (xirq < 0) {
+ snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
+ err = -EBUSY;
+ goto err_exit;
+ }
+ }
+
+ if (xdma == SNDRV_AUTO_DMA) {
+ xdma = snd_legacy_find_free_dma(possible_dmas);
+ if (xdma < 0) {
+ snd_printk(KERN_ERR PFX "unable to find a free DMA\n");
+ err = -EBUSY;
+ goto err_exit;
+ }
+ }
+
+ if (!request_region(port[dev], 0x10, DRV_NAME)) {
+ snd_printk(KERN_ERR PFX
+ "I/O port region is already in use.\n");
+ err = -EBUSY;
+ goto err_exit;
+ }
+ vport = devm_ioport_map(devptr, port[dev], 0x10);
+ if (!vport) {
+ snd_printk(KERN_ERR PFX
+ "I/O port cannot be iomaped.\n");
+ err = -EBUSY;
+ goto err_unmap1;
+ }
+
+ /* to make it marked as used */
+ if (!request_region(mss_port[dev], 4, DRV_NAME)) {
+ snd_printk(KERN_ERR PFX
+ "SC-6000 port I/O port region is already in use.\n");
+ err = -EBUSY;
+ goto err_unmap1;
+ }
+ vmss_port = devm_ioport_map(devptr, mss_port[dev], 4);
+ if (!vport) {
+ snd_printk(KERN_ERR PFX
+ "MSS port I/O cannot be iomaped.\n");
+ err = -EBUSY;
+ goto err_unmap2;
+ }
+
+ snd_printd("Initializing BASE[0x%lx] IRQ[%d] DMA[%d] MIRQ[%d]\n",
+ port[dev], xirq, xdma,
+ mpu_irq[dev] == SNDRV_AUTO_IRQ ? 0 : mpu_irq[dev]);
+
+ err = sc6000_init_board(vport, xirq, xdma, vmss_port, mpu_irq[dev]);
+ if (err < 0)
+ goto err_unmap2;
+
+ err = snd_ad1848_create(card, mss_port[dev] + 4, xirq, xdma,
+ AD1848_HW_DETECT, &chip);
+ if (err < 0)
+ goto err_unmap2;
+ card->private_data = chip;
+
+ err = snd_ad1848_pcm(chip, 0, NULL);
+ if (err < 0) {
+ snd_printk(KERN_ERR PFX
+ "error creating new ad1848 PCM device\n");
+ goto err_unmap2;
+ }
+ err = snd_ad1848_mixer(chip);
+ if (err < 0) {
+ snd_printk(KERN_ERR PFX "error creating new ad1848 mixer\n");
+ goto err_unmap2;
+ }
+ err = snd_sc6000_mixer(chip);
+ if (err < 0) {
+ snd_printk(KERN_ERR PFX "the mixer rewrite failed\n");
+ goto err_unmap2;
+ }
+ if (snd_opl3_create(card,
+ 0x388, 0x388 + 2,
+ OPL3_HW_AUTO, 0, &opl3) < 0) {
+ snd_printk(KERN_ERR PFX "no OPL device at 0x%x-0x%x ?\n",
+ 0x388, 0x388 + 2);
+ } else {
+ err = snd_opl3_timer_new(opl3, 0, 1);
+ if (err < 0)
+ goto err_unmap2;
+
+ err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
+ if (err < 0)
+ goto err_unmap2;
+ }
+
+ if (mpu_port[dev] != SNDRV_AUTO_PORT) {
+ if (mpu_irq[dev] == SNDRV_AUTO_IRQ)
+ mpu_irq[dev] = -1;
+ if (snd_mpu401_uart_new(card, 0,
+ MPU401_HW_MPU401,
+ mpu_port[dev], 0,
+ mpu_irq[dev], IRQF_DISABLED,
+ NULL) < 0)
+ snd_printk(KERN_ERR "no MPU-401 device at 0x%lx ?\n",
+ mpu_port[dev]);
+ }
+
+ strcpy(card->driver, DRV_NAME);
+ strcpy(card->shortname, "SC-6000");
+ sprintf(card->longname, "Gallant SC-6000 at 0x%lx, irq %d, dma %d",
+ mss_port[dev], xirq, xdma);
+
+ snd_card_set_dev(card, devptr);
+
+ err = snd_card_register(card);
+ if (err < 0)
+ goto err_unmap2;
+
+ dev_set_drvdata(devptr, card);
+ return 0;
+
+err_unmap2:
+ release_region(mss_port[dev], 4);
+err_unmap1:
+ release_region(port[dev], 0x10);
+err_exit:
+ snd_card_free(card);
+ return err;
+}
+
+static int __devexit snd_sc6000_remove(struct device *devptr, unsigned int dev)
+{
+ release_region(port[dev], 0x10);
+ release_region(mss_port[dev], 4);
+
+ snd_card_free(dev_get_drvdata(devptr));
+ dev_set_drvdata(devptr, NULL);
+ return 0;
+}
+
+static struct isa_driver snd_sc6000_driver = {
+ .match = snd_sc6000_match,
+ .probe = snd_sc6000_probe,
+ .remove = __devexit_p(snd_sc6000_remove),
+ /* FIXME: suspend/resume */
+ .driver = {
+ .name = DRV_NAME,
+ },
+};
+
+
+static int __init alsa_card_sc6000_init(void)
+{
+ return isa_register_driver(&snd_sc6000_driver, SNDRV_CARDS);
+}
+
+static void __exit alsa_card_sc6000_exit(void)
+{
+ isa_unregister_driver(&snd_sc6000_driver);
+}
+
+module_init(alsa_card_sc6000_init)
+module_exit(alsa_card_sc6000_exit)
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
index cbad2a51cbaa..1cb921d6137e 100644
--- a/sound/isa/sscape.c
+++ b/sound/isa/sscape.c
@@ -45,10 +45,12 @@ MODULE_LICENSE("GPL");
static int index[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_IDX;
static char* id[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_STR;
-static long port[SNDRV_CARDS] __devinitdata = { [0 ... (SNDRV_CARDS-1)] = SNDRV_AUTO_PORT };
+static long port[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PORT;
+static long wss_port[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PORT;
static int irq[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_IRQ;
static int mpu_irq[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_IRQ;
static int dma[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_DMA;
+static int dma2[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_DMA;
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index number for SoundScape soundcard");
@@ -59,6 +61,9 @@ MODULE_PARM_DESC(id, "Description for SoundScape card");
module_param_array(port, long, NULL, 0444);
MODULE_PARM_DESC(port, "Port # for SoundScape driver.");
+module_param_array(wss_port, long, NULL, 0444);
+MODULE_PARM_DESC(wss_port, "WSS Port # for SoundScape driver.");
+
module_param_array(irq, int, NULL, 0444);
MODULE_PARM_DESC(irq, "IRQ # for SoundScape driver.");
@@ -68,12 +73,16 @@ MODULE_PARM_DESC(mpu_irq, "MPU401 IRQ # for SoundScape driver.");
module_param_array(dma, int, NULL, 0444);
MODULE_PARM_DESC(dma, "DMA # for SoundScape driver.");
+module_param_array(dma2, int, NULL, 0444);
+MODULE_PARM_DESC(dma2, "DMA2 # for SoundScape driver.");
+
#ifdef CONFIG_PNP
static int isa_registered;
static int pnp_registered;
static struct pnp_card_device_id sscape_pnpids[] = {
- { .id = "ENS3081", .devs = { { "ENS0000" } } },
+ { .id = "ENS3081", .devs = { { "ENS0000" } } }, /* Soundscape PnP */
+ { .id = "ENS4081", .devs = { { "ENS1011" } } }, /* VIVO90 */
{ .id = "" } /* end */
};
@@ -124,12 +133,21 @@ enum GA_REG {
#define AD1845_FREQ_SEL_MSB 0x16
#define AD1845_FREQ_SEL_LSB 0x17
+enum card_type {
+ SSCAPE,
+ SSCAPE_PNP,
+ SSCAPE_VIVO,
+};
+
struct soundscape {
spinlock_t lock;
unsigned io_base;
+ unsigned wss_base;
int codec_type;
int ic_type;
+ enum card_type type;
struct resource *io_res;
+ struct resource *wss_res;
struct snd_cs4231 *chip;
struct snd_mpu401 *mpu;
struct snd_hwdep *hw;
@@ -340,8 +358,9 @@ static inline void activate_ad1845_unsafe(unsigned io_base)
*/
static void soundscape_free(struct snd_card *c)
{
- register struct soundscape *sscape = get_card_soundscape(c);
+ struct soundscape *sscape = get_card_soundscape(c);
release_and_free_resource(sscape->io_res);
+ release_and_free_resource(sscape->wss_res);
free_dma(sscape->chip->dma1);
}
@@ -382,7 +401,7 @@ static int obp_startup_ack(struct soundscape *s, unsigned timeout)
unsigned long flags;
unsigned char x;
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
spin_lock_irqsave(&s->lock, flags);
x = inb(HOST_DATA_IO(s->io_base));
@@ -409,7 +428,7 @@ static int host_startup_ack(struct soundscape *s, unsigned timeout)
unsigned long flags;
unsigned char x;
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
spin_lock_irqsave(&s->lock, flags);
x = inb(HOST_DATA_IO(s->io_base));
@@ -522,7 +541,7 @@ static int upload_dma_data(struct soundscape *s,
ret = -EAGAIN;
}
- _release_dma:
+_release_dma:
/*
* NOTE!!! We are NOT holding any spinlocks at this point !!!
*/
@@ -802,6 +821,7 @@ static int __devinit detect_sscape(struct soundscape *s)
unsigned long flags;
unsigned d;
int retval = 0;
+ int codec = s->wss_base;
spin_lock_irqsave(&s->lock, flags);
@@ -833,9 +853,27 @@ static int __devinit detect_sscape(struct soundscape *s)
outb(0xfe, ODIE_ADDR_IO(s->io_base));
if ((inb(ODIE_ADDR_IO(s->io_base)) & 0x9f) != 0x0e)
goto _done;
- if ((inb(ODIE_DATA_IO(s->io_base)) & 0x9f) != 0x0e)
+
+ outb(0xfe, ODIE_ADDR_IO(s->io_base));
+ d = inb(ODIE_DATA_IO(s->io_base));
+ if (s->type != SSCAPE_VIVO && (d & 0x9f) != 0x0e)
goto _done;
+ d = sscape_read_unsafe(s->io_base, GA_HMCTL_REG) & 0x3f;
+ sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d | 0xc0);
+
+ if (s->type == SSCAPE_VIVO)
+ codec += 4;
+ /* wait for WSS codec */
+ for (d = 0; d < 500; d++) {
+ if ((inb(codec) & 0x80) == 0)
+ break;
+ spin_unlock_irqrestore(&s->lock, flags);
+ msleep(1);
+ spin_lock_irqsave(&s->lock, flags);
+ }
+ snd_printd(KERN_INFO "init delay = %d ms\n", d);
+
/*
* SoundScape successfully detected!
*/
@@ -995,21 +1033,23 @@ static void ad1845_capture_format(struct snd_cs4231 * chip, struct snd_pcm_hw_pa
* try to support at least some of the extra bits by overriding
* some of the CS4231 callback.
*/
-static int __devinit create_ad1845(struct snd_card *card, unsigned port, int irq, int dma1)
+static int __devinit create_ad1845(struct snd_card *card, unsigned port,
+ int irq, int dma1, int dma2)
{
register struct soundscape *sscape = get_card_soundscape(card);
struct snd_cs4231 *chip;
int err;
-#define CS4231_SHARE_HARDWARE (CS4231_HWSHARE_DMA1 | CS4231_HWSHARE_DMA2)
- /*
- * The AD1845 PCM device is only half-duplex, and so
- * we only give it one DMA channel ...
- */
- if ((err = snd_cs4231_create(card,
- port, -1, irq, dma1, dma1,
- CS4231_HW_DETECT,
- CS4231_HWSHARE_DMA1, &chip)) == 0) {
+ if (sscape->type == SSCAPE_VIVO)
+ port += 4;
+
+ if (dma1 == dma2)
+ dma2 = -1;
+
+ err = snd_cs4231_create(card,
+ port, -1, irq, dma1, dma2,
+ CS4231_HW_DETECT, CS4231_HWSHARE_DMA1, &chip);
+ if (!err) {
unsigned long flags;
struct snd_pcm *pcm;
@@ -1031,49 +1071,72 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, int irq
snd_cs4231_mce_down(chip);
*/
- /*
- * The input clock frequency on the SoundScape must
- * be 14.31818 MHz, because we must set this register
- * to get the playback to sound correct ...
- */
- snd_cs4231_mce_up(chip);
- spin_lock_irqsave(&chip->reg_lock, flags);
- snd_cs4231_out(chip, AD1845_CRYS_CLOCK_SEL, 0x20);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- snd_cs4231_mce_down(chip);
+ if (sscape->type != SSCAPE_VIVO) {
+ int val;
+ /*
+ * The input clock frequency on the SoundScape must
+ * be 14.31818 MHz, because we must set this register
+ * to get the playback to sound correct ...
+ */
+ snd_cs4231_mce_up(chip);
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ snd_cs4231_out(chip, AD1845_CRYS_CLOCK_SEL, 0x20);
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ snd_cs4231_mce_down(chip);
- /*
- * More custom configuration:
- * a) select "mode 2", and provide a current drive of 8 mA
- * b) enable frequency selection (for capture/playback)
- */
- spin_lock_irqsave(&chip->reg_lock, flags);
- snd_cs4231_out(chip, CS4231_MISC_INFO, (CS4231_MODE2 | 0x10));
- snd_cs4231_out(chip, AD1845_PWR_DOWN_CTRL, snd_cs4231_in(chip, AD1845_PWR_DOWN_CTRL) | AD1845_FREQ_SEL_ENABLE);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
+ /*
+ * More custom configuration:
+ * a) select "mode 2" and provide a current drive of 8mA
+ * b) enable frequency selection (for capture/playback)
+ */
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ snd_cs4231_out(chip, CS4231_MISC_INFO,
+ CS4231_MODE2 | 0x10);
+ val = snd_cs4231_in(chip, AD1845_PWR_DOWN_CTRL);
+ snd_cs4231_out(chip, AD1845_PWR_DOWN_CTRL,
+ val | AD1845_FREQ_SEL_ENABLE);
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ }
- if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0) {
- snd_printk(KERN_ERR "sscape: No PCM device for AD1845 chip\n");
+ err = snd_cs4231_pcm(chip, 0, &pcm);
+ if (err < 0) {
+ snd_printk(KERN_ERR "sscape: No PCM device "
+ "for AD1845 chip\n");
goto _error;
}
- if ((err = snd_cs4231_mixer(chip)) < 0) {
- snd_printk(KERN_ERR "sscape: No mixer device for AD1845 chip\n");
+ err = snd_cs4231_mixer(chip);
+ if (err < 0) {
+ snd_printk(KERN_ERR "sscape: No mixer device "
+ "for AD1845 chip\n");
goto _error;
}
-
- if ((err = snd_ctl_add(card, snd_ctl_new1(&midi_mixer_ctl, chip))) < 0) {
- snd_printk(KERN_ERR "sscape: Could not create MIDI mixer control\n");
+ err = snd_cs4231_timer(chip, 0, NULL);
+ if (err < 0) {
+ snd_printk(KERN_ERR "sscape: No timer device "
+ "for AD1845 chip\n");
goto _error;
}
+ if (sscape->type != SSCAPE_VIVO) {
+ err = snd_ctl_add(card,
+ snd_ctl_new1(&midi_mixer_ctl, chip));
+ if (err < 0) {
+ snd_printk(KERN_ERR "sscape: Could not create "
+ "MIDI mixer control\n");
+ goto _error;
+ }
+ chip->set_playback_format = ad1845_playback_format;
+ chip->set_capture_format = ad1845_capture_format;
+ }
+
strcpy(card->driver, "SoundScape");
strcpy(card->shortname, pcm->name);
snprintf(card->longname, sizeof(card->longname),
- "%s at 0x%lx, IRQ %d, DMA %d\n",
- pcm->name, chip->port, chip->irq, chip->dma1);
- chip->set_playback_format = ad1845_playback_format;
- chip->set_capture_format = ad1845_capture_format;
+ "%s at 0x%lx, IRQ %d, DMA1 %d, DMA2 %d\n",
+ pcm->name, chip->port, chip->irq,
+ chip->dma1, chip->dma2);
+
sscape->chip = chip;
}
@@ -1086,15 +1149,15 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, int irq
* Create an ALSA soundcard entry for the SoundScape, using
* the given list of port, IRQ and DMA resources.
*/
-static int __devinit create_sscape(int dev, struct snd_card **rcardp)
+static int __devinit create_sscape(int dev, struct snd_card *card)
{
- struct snd_card *card;
- register struct soundscape *sscape;
- register unsigned dma_cfg;
+ struct soundscape *sscape = get_card_soundscape(card);
+ unsigned dma_cfg;
unsigned irq_cfg;
unsigned mpu_irq_cfg;
unsigned xport;
struct resource *io_res;
+ struct resource *wss_res;
unsigned long flags;
int err;
@@ -1118,61 +1181,69 @@ static int __devinit create_sscape(int dev, struct snd_card **rcardp)
* Grab IO ports that we will need to probe so that we
* can detect and control this hardware ...
*/
- if ((io_res = request_region(xport, 8, "SoundScape")) == NULL) {
+ io_res = request_region(xport, 8, "SoundScape");
+ if (!io_res) {
snd_printk(KERN_ERR "sscape: can't grab port 0x%x\n", xport);
return -EBUSY;
}
+ wss_res = NULL;
+ if (sscape->type == SSCAPE_VIVO) {
+ wss_res = request_region(wss_port[dev], 4, "SoundScape");
+ if (!wss_res) {
+ snd_printk(KERN_ERR "sscape: can't grab port 0x%lx\n",
+ wss_port[dev]);
+ err = -EBUSY;
+ goto _release_region;
+ }
+ }
/*
- * Grab both DMA channels (OK, only one for now) ...
+ * Grab one DMA channel ...
*/
- if ((err = request_dma(dma[dev], "SoundScape")) < 0) {
+ err = request_dma(dma[dev], "SoundScape");
+ if (err < 0) {
snd_printk(KERN_ERR "sscape: can't grab DMA %d\n", dma[dev]);
goto _release_region;
}
- /*
- * Create a new ALSA sound card entry, in anticipation
- * of detecting our hardware ...
- */
- if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE,
- sizeof(struct soundscape))) == NULL) {
- err = -ENOMEM;
- goto _release_dma;
- }
-
- sscape = get_card_soundscape(card);
spin_lock_init(&sscape->lock);
spin_lock_init(&sscape->fwlock);
sscape->io_res = io_res;
+ sscape->wss_res = wss_res;
sscape->io_base = xport;
+ sscape->wss_base = wss_port[dev];
if (!detect_sscape(sscape)) {
printk(KERN_ERR "sscape: hardware not detected at 0x%x\n", sscape->io_base);
err = -ENODEV;
- goto _release_card;
+ goto _release_dma;
}
printk(KERN_INFO "sscape: hardware detected at 0x%x, using IRQ %d, DMA %d\n",
- sscape->io_base, irq[dev], dma[dev]);
+ sscape->io_base, irq[dev], dma[dev]);
- /*
- * Now create the hardware-specific device so that we can
- * load the microcode into the on-board processor.
- * We cannot use the MPU-401 MIDI system until this firmware
- * has been loaded into the card.
- */
- if ((err = snd_hwdep_new(card, "MC68EC000", 0, &(sscape->hw))) < 0) {
- printk(KERN_ERR "sscape: Failed to create firmware device\n");
- goto _release_card;
+ if (sscape->type != SSCAPE_VIVO) {
+ /*
+ * Now create the hardware-specific device so that we can
+ * load the microcode into the on-board processor.
+ * We cannot use the MPU-401 MIDI system until this firmware
+ * has been loaded into the card.
+ */
+ err = snd_hwdep_new(card, "MC68EC000", 0, &(sscape->hw));
+ if (err < 0) {
+ printk(KERN_ERR "sscape: Failed to create "
+ "firmware device\n");
+ goto _release_dma;
+ }
+ strlcpy(sscape->hw->name, "SoundScape M68K",
+ sizeof(sscape->hw->name));
+ sscape->hw->name[sizeof(sscape->hw->name) - 1] = '\0';
+ sscape->hw->iface = SNDRV_HWDEP_IFACE_SSCAPE;
+ sscape->hw->ops.open = sscape_hw_open;
+ sscape->hw->ops.release = sscape_hw_release;
+ sscape->hw->ops.ioctl = sscape_hw_ioctl;
+ sscape->hw->private_data = sscape;
}
- strlcpy(sscape->hw->name, "SoundScape M68K", sizeof(sscape->hw->name));
- sscape->hw->name[sizeof(sscape->hw->name) - 1] = '\0';
- sscape->hw->iface = SNDRV_HWDEP_IFACE_SSCAPE;
- sscape->hw->ops.open = sscape_hw_open;
- sscape->hw->ops.release = sscape_hw_release;
- sscape->hw->ops.ioctl = sscape_hw_ioctl;
- sscape->hw->private_data = sscape;
/*
* Tell the on-board devices where their resources are (I think -
@@ -1197,7 +1268,8 @@ static int __devinit create_sscape(int dev, struct snd_card **rcardp)
sscape_write_unsafe(sscape->io_base,
GA_INTCFG_REG, 0xf0 | (mpu_irq_cfg << 2) | mpu_irq_cfg);
sscape_write_unsafe(sscape->io_base,
- GA_CDCFG_REG, 0x09 | DMA_8BIT | (dma[dev] << 4) | (irq_cfg << 1));
+ GA_CDCFG_REG, 0x09 | DMA_8BIT
+ | (dma[dev] << 4) | (irq_cfg << 1));
spin_unlock_irqrestore(&sscape->lock, flags);
@@ -1205,30 +1277,37 @@ static int __devinit create_sscape(int dev, struct snd_card **rcardp)
* We have now enabled the codec chip, and so we should
* detect the AD1845 device ...
*/
- if ((err = create_ad1845(card, CODEC_IO(xport), irq[dev], dma[dev])) < 0) {
- printk(KERN_ERR "sscape: No AD1845 device at 0x%x, IRQ %d\n",
- CODEC_IO(xport), irq[dev]);
- goto _release_card;
+ err = create_ad1845(card, wss_port[dev], irq[dev],
+ dma[dev], dma2[dev]);
+ if (err < 0) {
+ printk(KERN_ERR "sscape: No AD1845 device at 0x%lx, IRQ %d\n",
+ wss_port[dev], irq[dev]);
+ goto _release_dma;
}
#define MIDI_DEVNUM 0
- if ((err = create_mpu401(card, MIDI_DEVNUM, MPU401_IO(xport), mpu_irq[dev])) < 0) {
- printk(KERN_ERR "sscape: Failed to create MPU-401 device at 0x%x\n",
- MPU401_IO(xport));
- goto _release_card;
- }
+ if (sscape->type != SSCAPE_VIVO) {
+ err = create_mpu401(card, MIDI_DEVNUM,
+ MPU401_IO(xport), mpu_irq[dev]);
+ if (err < 0) {
+ printk(KERN_ERR "sscape: Failed to create "
+ "MPU-401 device at 0x%x\n",
+ MPU401_IO(xport));
+ goto _release_dma;
+ }
- /*
- * Enable the master IRQ ...
- */
- sscape_write(sscape, GA_INTENA_REG, 0x80);
+ /*
+ * Enable the master IRQ ...
+ */
+ sscape_write(sscape, GA_INTENA_REG, 0x80);
- /*
- * Initialize mixer
- */
- sscape->midi_vol = 0;
- host_write_ctrl_unsafe(sscape->io_base, CMD_SET_MIDI_VOL, 100);
- host_write_ctrl_unsafe(sscape->io_base, 0, 100);
- host_write_ctrl_unsafe(sscape->io_base, CMD_XXX_MIDI_VOL, 100);
+ /*
+ * Initialize mixer
+ */
+ sscape->midi_vol = 0;
+ host_write_ctrl_unsafe(sscape->io_base, CMD_SET_MIDI_VOL, 100);
+ host_write_ctrl_unsafe(sscape->io_base, 0, 100);
+ host_write_ctrl_unsafe(sscape->io_base, CMD_XXX_MIDI_VOL, 100);
+ }
/*
* Now that we have successfully created this sound card,
@@ -1237,17 +1316,14 @@ static int __devinit create_sscape(int dev, struct snd_card **rcardp)
* function now that our "constructor" has completed.
*/
card->private_free = soundscape_free;
- *rcardp = card;
return 0;
- _release_card:
- snd_card_free(card);
-
- _release_dma:
+_release_dma:
free_dma(dma[dev]);
- _release_region:
+_release_region:
+ release_and_free_resource(wss_res);
release_and_free_resource(io_res);
return err;
@@ -1276,19 +1352,33 @@ static int __devinit snd_sscape_match(struct device *pdev, unsigned int i)
static int __devinit snd_sscape_probe(struct device *pdev, unsigned int dev)
{
struct snd_card *card;
+ struct soundscape *sscape;
int ret;
+ card = snd_card_new(index[dev], id[dev], THIS_MODULE,
+ sizeof(struct soundscape));
+ if (!card)
+ return -ENOMEM;
+
+ sscape = get_card_soundscape(card);
+ sscape->type = SSCAPE;
+
dma[dev] &= 0x03;
- ret = create_sscape(dev, &card);
+ ret = create_sscape(dev, card);
if (ret < 0)
- return ret;
+ goto _release_card;
+
snd_card_set_dev(card, pdev);
if ((ret = snd_card_register(card)) < 0) {
printk(KERN_ERR "sscape: Failed to register sound card\n");
- return ret;
+ goto _release_card;
}
dev_set_drvdata(pdev, card);
return 0;
+
+_release_card:
+ snd_card_free(card);
+ return ret;
}
static int __devexit snd_sscape_remove(struct device *devptr, unsigned int dev)
@@ -1325,6 +1415,7 @@ static int __devinit sscape_pnp_detect(struct pnp_card_link *pcard,
static int idx = 0;
struct pnp_dev *dev;
struct snd_card *card;
+ struct soundscape *sscape;
int ret;
/*
@@ -1366,26 +1457,55 @@ static int __devinit sscape_pnp_detect(struct pnp_card_link *pcard,
}
/*
+ * Create a new ALSA sound card entry, in anticipation
+ * of detecting our hardware ...
+ */
+ card = snd_card_new(index[idx], id[idx], THIS_MODULE,
+ sizeof(struct soundscape));
+ if (!card)
+ return -ENOMEM;
+
+ sscape = get_card_soundscape(card);
+
+ /*
+ * Identify card model ...
+ */
+ if (!strncmp("ENS4081", pid->id, 7))
+ sscape->type = SSCAPE_VIVO;
+ else
+ sscape->type = SSCAPE_PNP;
+
+ /*
* Read the correct parameters off the ISA PnP bus ...
*/
port[idx] = pnp_port_start(dev, 0);
irq[idx] = pnp_irq(dev, 0);
mpu_irq[idx] = pnp_irq(dev, 1);
dma[idx] = pnp_dma(dev, 0) & 0x03;
+ if (sscape->type == SSCAPE_PNP) {
+ dma2[idx] = dma[idx];
+ wss_port[idx] = CODEC_IO(port[idx]);
+ } else {
+ wss_port[idx] = pnp_port_start(dev, 1);
+ dma2[idx] = pnp_dma(dev, 1);
+ }
- ret = create_sscape(idx, &card);
+ ret = create_sscape(idx, card);
if (ret < 0)
- return ret;
+ goto _release_card;
+
snd_card_set_dev(card, &pcard->card->dev);
if ((ret = snd_card_register(card)) < 0) {
printk(KERN_ERR "sscape: Failed to register sound card\n");
- snd_card_free(card);
- return ret;
+ goto _release_card;
}
pnp_set_card_drvdata(pcard, card);
++idx;
+ return 0;
+_release_card:
+ snd_card_free(card);
return ret;
}
diff --git a/sound/isa/wavefront/Makefile b/sound/isa/wavefront/Makefile
index b4cb28422db0..601bdddd44d0 100644
--- a/sound/isa/wavefront/Makefile
+++ b/sound/isa/wavefront/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
snd-wavefront-objs := wavefront.o wavefront_fx.o wavefront_synth.o wavefront_midi.o
diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c
index bacc51c86587..a1ebb7c5c684 100644
--- a/sound/isa/wavefront/wavefront_synth.c
+++ b/sound/isa/wavefront/wavefront_synth.c
@@ -27,6 +27,7 @@
#include <linux/delay.h>
#include <linux/time.h>
#include <linux/wait.h>
+#include <linux/firmware.h>
#include <linux/moduleparam.h>
#include <sound/core.h>
#include <sound/snd_wavefront.h>
@@ -53,9 +54,8 @@ static int debug_default = 0; /* you can set this to control debugging
/* XXX this needs to be made firmware and hardware version dependent */
-static char *ospath = "/etc/sound/wavefront.os"; /* where to find a processed
- version of the WaveFront OS
- */
+#define DEFAULT_OSPATH "wavefront.os"
+static char *ospath = DEFAULT_OSPATH; /* the firmware file name */
static int wait_usecs = 150; /* This magic number seems to give pretty optimal
throughput based on my limited experimentation.
@@ -97,7 +97,7 @@ MODULE_PARM_DESC(sleep_interval, "how long to sleep when waiting for reply");
module_param(sleep_tries, int, 0444);
MODULE_PARM_DESC(sleep_tries, "how many times to try sleeping during a wait");
module_param(ospath, charp, 0444);
-MODULE_PARM_DESC(ospath, "full pathname to processed ICS2115 OS firmware");
+MODULE_PARM_DESC(ospath, "pathname to processed ICS2115 OS firmware");
module_param(reset_time, int, 0444);
MODULE_PARM_DESC(reset_time, "how long to wait for a reset to take effect");
module_param(ramcheck_time, int, 0444);
@@ -1768,7 +1768,7 @@ snd_wavefront_interrupt_bits (int irq)
static void __devinit
wavefront_should_cause_interrupt (snd_wavefront_t *dev,
- int val, int port, int timeout)
+ int val, int port, unsigned long timeout)
{
wait_queue_t wait;
@@ -1779,11 +1779,9 @@ wavefront_should_cause_interrupt (snd_wavefront_t *dev,
dev->irq_ok = 0;
outb (val,port);
spin_unlock_irq(&dev->irq_lock);
- while (1) {
- if ((timeout = schedule_timeout(timeout)) == 0)
- return;
- if (dev->irq_ok)
- return;
+ while (!dev->irq_ok && time_before(jiffies, timeout)) {
+ schedule_timeout_uninterruptible(1);
+ barrier();
}
}
@@ -1938,111 +1936,75 @@ wavefront_reset_to_cleanliness (snd_wavefront_t *dev)
return (1);
}
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/unistd.h>
-#include <linux/syscalls.h>
-#include <asm/uaccess.h>
-
-
static int __devinit
wavefront_download_firmware (snd_wavefront_t *dev, char *path)
{
- unsigned char section[WF_SECTION_MAX];
- signed char section_length; /* yes, just a char; max value is WF_SECTION_MAX */
+ unsigned char *buf;
+ int len, err;
int section_cnt_downloaded = 0;
- int fd;
- int c;
- int i;
- mm_segment_t fs;
-
- /* This tries to be a bit cleverer than the stuff Alan Cox did for
- the generic sound firmware, in that it actually knows
- something about the structure of the Motorola firmware. In
- particular, it uses a version that has been stripped of the
- 20K of useless header information, and had section lengths
- added, making it possible to load the entire OS without any
- [kv]malloc() activity, since the longest entity we ever read is
- 42 bytes (well, WF_SECTION_MAX) long.
- */
-
- fs = get_fs();
- set_fs (get_ds());
+ const struct firmware *firmware;
- if ((fd = sys_open ((char __user *) path, 0, 0)) < 0) {
- snd_printk ("Unable to load \"%s\".\n",
- path);
+ err = request_firmware(&firmware, path, dev->card->dev);
+ if (err < 0) {
+ snd_printk(KERN_ERR "firmware (%s) download failed!!!\n", path);
return 1;
}
- while (1) {
- int x;
-
- if ((x = sys_read (fd, (char __user *) &section_length, sizeof (section_length))) !=
- sizeof (section_length)) {
- snd_printk ("firmware read error.\n");
- goto failure;
- }
-
- if (section_length == 0) {
+ len = 0;
+ buf = firmware->data;
+ for (;;) {
+ int section_length = *(signed char *)buf;
+ if (section_length == 0)
break;
- }
-
if (section_length < 0 || section_length > WF_SECTION_MAX) {
- snd_printk ("invalid firmware section length %d\n",
- section_length);
+ snd_printk(KERN_ERR
+ "invalid firmware section length %d\n",
+ section_length);
goto failure;
}
+ buf++;
+ len++;
- if (sys_read (fd, (char __user *) section, section_length) != section_length) {
- snd_printk ("firmware section "
- "read error.\n");
+ if (firmware->size < len + section_length) {
+ snd_printk(KERN_ERR "firmware section read error.\n");
goto failure;
}
/* Send command */
-
- if (wavefront_write (dev, WFC_DOWNLOAD_OS)) {
+ if (wavefront_write(dev, WFC_DOWNLOAD_OS))
goto failure;
- }
- for (i = 0; i < section_length; i++) {
- if (wavefront_write (dev, section[i])) {
+ for (; section_length; section_length--) {
+ if (wavefront_write(dev, *buf))
goto failure;
- }
+ buf++;
+ len++;
}
/* get ACK */
-
- if (wavefront_wait (dev, STAT_CAN_READ)) {
-
- if ((c = inb (dev->data_port)) != WF_ACK) {
-
- snd_printk ("download "
- "of section #%d not "
- "acknowledged, ack = 0x%x\n",
- section_cnt_downloaded + 1, c);
- goto failure;
-
- }
-
- } else {
- snd_printk ("time out for firmware ACK.\n");
+ if (!wavefront_wait(dev, STAT_CAN_READ)) {
+ snd_printk(KERN_ERR "time out for firmware ACK.\n");
+ goto failure;
+ }
+ err = inb(dev->data_port);
+ if (err != WF_ACK) {
+ snd_printk(KERN_ERR
+ "download of section #%d not "
+ "acknowledged, ack = 0x%x\n",
+ section_cnt_downloaded + 1, err);
goto failure;
}
+ section_cnt_downloaded++;
}
- sys_close (fd);
- set_fs (fs);
+ release_firmware(firmware);
return 0;
failure:
- sys_close (fd);
- set_fs (fs);
- snd_printk ("firmware download failed!!!\n");
+ release_firmware(firmware);
+ snd_printk(KERN_ERR "firmware download failed!!!\n");
return 1;
}
@@ -2232,3 +2194,5 @@ snd_wavefront_detect (snd_wavefront_card_t *card)
return 0;
}
+
+MODULE_FIRMWARE(DEFAULT_OSPATH);
diff --git a/sound/last.c b/sound/last.c
index 964314efff5c..282b0cdb0589 100644
--- a/sound/last.c
+++ b/sound/last.c
@@ -1,6 +1,6 @@
/*
* Advanced Linux Sound Architecture
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/mips/au1x00.c b/sound/mips/au1x00.c
index 8a61a1191861..24460a558bf7 100644
--- a/sound/mips/au1x00.c
+++ b/sound/mips/au1x00.c
@@ -498,8 +498,8 @@ snd_au1000_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
int i;
spin_lock(&au1000->ac97_lock);
-/* would rather use the interupt than this polling but it works and I can't
-get the interupt driven case to work efficiently */
+/* would rather use the interrupt than this polling but it works and I can't
+get the interrupt driven case to work efficiently */
for (i = 0; i < 0x5000; i++)
if (!(au1000->ac97_ioport->status & AC97C_CP))
break;
@@ -535,8 +535,8 @@ snd_au1000_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short
int i;
spin_lock(&au1000->ac97_lock);
-/* would rather use the interupt than this polling but it works and I can't
-get the interupt driven case to work efficiently */
+/* would rather use the interrupt than this polling but it works and I can't
+get the interrupt driven case to work efficiently */
for (i = 0; i < 0x5000; i++)
if (!(au1000->ac97_ioport->status & AC97C_CP))
break;
diff --git a/sound/oss/Makefile b/sound/oss/Makefile
index 1200670017bd..f883c4b676ab 100644
--- a/sound/oss/Makefile
+++ b/sound/oss/Makefile
@@ -36,7 +36,6 @@ obj-$(CONFIG_SOUND_MSNDCLAS) += msnd.o msnd_classic.o
obj-$(CONFIG_SOUND_MSNDPIN) += msnd.o msnd_pinnacle.o
obj-$(CONFIG_SOUND_VWSND) += vwsnd.o
obj-$(CONFIG_SOUND_ICH) += i810_audio.o ac97_codec.o
-obj-$(CONFIG_SOUND_ES1371) += es1371.o ac97_codec.o
obj-$(CONFIG_SOUND_AU1550_AC97) += au1550_ac97.o ac97_codec.o
obj-$(CONFIG_SOUND_TRIDENT) += trident.o ac97_codec.o
obj-$(CONFIG_SOUND_BCM_CS4297A) += swarm_cs4297a.o
diff --git a/sound/oss/dmasound/Makefile b/sound/oss/dmasound/Makefile
index 4611636b1a81..3c1531652d11 100644
--- a/sound/oss/dmasound/Makefile
+++ b/sound/oss/dmasound/Makefile
@@ -2,12 +2,6 @@
# Makefile for the DMA sound driver
#
-dmasound_pmac-y += dmasound_awacs.o \
- trans_16.o dac3550a.o tas_common.o \
- tas3001c.o tas3001c_tables.o \
- tas3004.o tas3004_tables.o
-
obj-$(CONFIG_DMASOUND_ATARI) += dmasound_core.o dmasound_atari.o
-obj-$(CONFIG_DMASOUND_PMAC) += dmasound_core.o dmasound_pmac.o
obj-$(CONFIG_DMASOUND_PAULA) += dmasound_core.o dmasound_paula.o
obj-$(CONFIG_DMASOUND_Q40) += dmasound_core.o dmasound_q40.o
diff --git a/sound/oss/dmasound/awacs_defs.h b/sound/oss/dmasound/awacs_defs.h
deleted file mode 100644
index 2194f46b046c..000000000000
--- a/sound/oss/dmasound/awacs_defs.h
+++ /dev/null
@@ -1,251 +0,0 @@
-/*********************************************************/
-/* This file was written by someone, somewhere, sometime */
-/* And is released into the Public Domain */
-/*********************************************************/
-
-#ifndef _AWACS_DEFS_H_
-#define _AWACS_DEFS_H_
-
-/*******************************/
-/* AWACs Audio Register Layout */
-/*******************************/
-
-struct awacs_regs {
- unsigned control; /* Audio control register */
- unsigned pad0[3];
- unsigned codec_ctrl; /* Codec control register */
- unsigned pad1[3];
- unsigned codec_stat; /* Codec status register */
- unsigned pad2[3];
- unsigned clip_count; /* Clipping count register */
- unsigned pad3[3];
- unsigned byteswap; /* Data is little-endian if 1 */
-};
-
-/*******************/
-/* Audio Bit Masks */
-/*******************/
-
-/* Audio Control Reg Bit Masks */
-/* ----- ------- --- --- ----- */
-#define MASK_ISFSEL (0xf) /* Input SubFrame Select */
-#define MASK_OSFSEL (0xf << 4) /* Output SubFrame Select */
-#define MASK_RATE (0x7 << 8) /* Sound Rate */
-#define MASK_CNTLERR (0x1 << 11) /* Error */
-#define MASK_PORTCHG (0x1 << 12) /* Port Change */
-#define MASK_IEE (0x1 << 13) /* Enable Interrupt on Error */
-#define MASK_IEPC (0x1 << 14) /* Enable Interrupt on Port Change */
-#define MASK_SSFSEL (0x3 << 15) /* Status SubFrame Select */
-
-/* Audio Codec Control Reg Bit Masks */
-/* ----- ----- ------- --- --- ----- */
-#define MASK_NEWECMD (0x1 << 24) /* Lock: don't write to reg when 1 */
-#define MASK_EMODESEL (0x3 << 22) /* Send info out on which frame? */
-#define MASK_EXMODEADDR (0x3ff << 12) /* Extended Mode Address -- 10 bits */
-#define MASK_EXMODEDATA (0xfff) /* Extended Mode Data -- 12 bits */
-
-/* Audio Codec Control Address Values / Masks */
-/* ----- ----- ------- ------- ------ - ----- */
-#define MASK_ADDR0 (0x0 << 12) /* Expanded Data Mode Address 0 */
-#define MASK_ADDR_MUX MASK_ADDR0 /* Mux Control */
-#define MASK_ADDR_GAIN MASK_ADDR0
-
-#define MASK_ADDR1 (0x1 << 12) /* Expanded Data Mode Address 1 */
-#define MASK_ADDR_MUTE MASK_ADDR1
-#define MASK_ADDR_RATE MASK_ADDR1
-
-#define MASK_ADDR2 (0x2 << 12) /* Expanded Data Mode Address 2 */
-#define MASK_ADDR_VOLA MASK_ADDR2 /* Volume Control A -- Headphones */
-#define MASK_ADDR_VOLHD MASK_ADDR2
-
-#define MASK_ADDR4 (0x4 << 12) /* Expanded Data Mode Address 4 */
-#define MASK_ADDR_VOLC MASK_ADDR4 /* Volume Control C -- Speaker */
-#define MASK_ADDR_VOLSPK MASK_ADDR4
-
-/* additional registers of screamer */
-#define MASK_ADDR5 (0x5 << 12) /* Expanded Data Mode Address 5 */
-#define MASK_ADDR6 (0x6 << 12) /* Expanded Data Mode Address 6 */
-#define MASK_ADDR7 (0x7 << 12) /* Expanded Data Mode Address 7 */
-
-/* Address 0 Bit Masks & Macros */
-/* ------- - --- ----- - ------ */
-#define MASK_GAINRIGHT (0xf) /* Gain Right Mask */
-#define MASK_GAINLEFT (0xf << 4) /* Gain Left Mask */
-#define MASK_GAINLINE (0x1 << 8) /* Disable Mic preamp */
-#define MASK_GAINMIC (0x0 << 8) /* Enable Mic preamp */
-
-#define MASK_MUX_CD (0x1 << 9) /* Select CD in MUX */
-#define MASK_MUX_MIC (0x1 << 10) /* Select Mic in MUX */
-#define MASK_MUX_AUDIN (0x1 << 11) /* Select Audio In in MUX */
-#define MASK_MUX_LINE MASK_MUX_AUDIN
-
-#define GAINRIGHT(x) ((x) & MASK_GAINRIGHT)
-#define GAINLEFT(x) (((x) << 4) & MASK_GAINLEFT)
-
-#define DEF_CD_GAIN 0x00bb
-#define DEF_MIC_GAIN 0x00cc
-
-/* Address 1 Bit Masks */
-/* ------- - --- ----- */
-#define MASK_ADDR1RES1 (0x3) /* Reserved */
-#define MASK_RECALIBRATE (0x1 << 2) /* Recalibrate */
-#define MASK_SAMPLERATE (0x7 << 3) /* Sample Rate: */
-#define MASK_LOOPTHRU (0x1 << 6) /* Loopthrough Enable */
-#define MASK_CMUTE (0x1 << 7) /* Output C (Speaker) Mute when 1 */
-#define MASK_SPKMUTE MASK_CMUTE
-#define MASK_ADDR1RES2 (0x1 << 8) /* Reserved */
-#define MASK_AMUTE (0x1 << 9) /* Output A (Headphone) Mute when 1 */
-#define MASK_HDMUTE MASK_AMUTE
-#define MASK_PAROUT0 (0x1 << 10) /* Parallel Output 0 */
-#define MASK_PAROUT1 (0x2 << 10) /* Parallel Output 1 */
-
-#define MASK_MIC_BOOST (0x4) /* screamer mic boost */
-
-#define SAMPLERATE_48000 (0x0 << 3) /* 48 or 44.1 kHz */
-#define SAMPLERATE_32000 (0x1 << 3) /* 32 or 29.4 kHz */
-#define SAMPLERATE_24000 (0x2 << 3) /* 24 or 22.05 kHz */
-#define SAMPLERATE_19200 (0x3 << 3) /* 19.2 or 17.64 kHz */
-#define SAMPLERATE_16000 (0x4 << 3) /* 16 or 14.7 kHz */
-#define SAMPLERATE_12000 (0x5 << 3) /* 12 or 11.025 kHz */
-#define SAMPLERATE_9600 (0x6 << 3) /* 9.6 or 8.82 kHz */
-#define SAMPLERATE_8000 (0x7 << 3) /* 8 or 7.35 kHz */
-
-/* Address 2 & 4 Bit Masks & Macros */
-/* ------- - - - --- ----- - ------ */
-#define MASK_OUTVOLRIGHT (0xf) /* Output Right Volume */
-#define MASK_ADDR2RES1 (0x2 << 4) /* Reserved */
-#define MASK_ADDR4RES1 MASK_ADDR2RES1
-#define MASK_OUTVOLLEFT (0xf << 6) /* Output Left Volume */
-#define MASK_ADDR2RES2 (0x2 << 10) /* Reserved */
-#define MASK_ADDR4RES2 MASK_ADDR2RES2
-
-#define VOLRIGHT(x) (((~(x)) & MASK_OUTVOLRIGHT))
-#define VOLLEFT(x) (((~(x)) << 6) & MASK_OUTVOLLEFT)
-
-/* Audio Codec Status Reg Bit Masks */
-/* ----- ----- ------ --- --- ----- */
-#define MASK_EXTEND (0x1 << 23) /* Extend */
-#define MASK_VALID (0x1 << 22) /* Valid Data? */
-#define MASK_OFLEFT (0x1 << 21) /* Overflow Left */
-#define MASK_OFRIGHT (0x1 << 20) /* Overflow Right */
-#define MASK_ERRCODE (0xf << 16) /* Error Code */
-#define MASK_REVISION (0xf << 12) /* Revision Number */
-#define MASK_MFGID (0xf << 8) /* Mfg. ID */
-#define MASK_CODSTATRES (0xf << 4) /* bits 4 - 7 reserved */
-#define MASK_INPPORT (0xf) /* Input Port */
-#define MASK_HDPCONN 8 /* headphone plugged in */
-
-/* Clipping Count Reg Bit Masks */
-/* -------- ----- --- --- ----- */
-#define MASK_CLIPLEFT (0xff << 7) /* Clipping Count, Left Channel */
-#define MASK_CLIPRIGHT (0xff) /* Clipping Count, Right Channel */
-
-/* DBDMA ChannelStatus Bit Masks */
-/* ----- ------------- --- ----- */
-#define MASK_CSERR (0x1 << 7) /* Error */
-#define MASK_EOI (0x1 << 6) /* End of Input -- only for Input Channel */
-#define MASK_CSUNUSED (0x1f << 1) /* bits 1-5 not used */
-#define MASK_WAIT (0x1) /* Wait */
-
-/* Various Rates */
-/* ------- ----- */
-#define RATE_48000 (0x0 << 8) /* 48 kHz */
-#define RATE_44100 (0x0 << 8) /* 44.1 kHz */
-#define RATE_32000 (0x1 << 8) /* 32 kHz */
-#define RATE_29400 (0x1 << 8) /* 29.4 kHz */
-#define RATE_24000 (0x2 << 8) /* 24 kHz */
-#define RATE_22050 (0x2 << 8) /* 22.05 kHz */
-#define RATE_19200 (0x3 << 8) /* 19.2 kHz */
-#define RATE_17640 (0x3 << 8) /* 17.64 kHz */
-#define RATE_16000 (0x4 << 8) /* 16 kHz */
-#define RATE_14700 (0x4 << 8) /* 14.7 kHz */
-#define RATE_12000 (0x5 << 8) /* 12 kHz */
-#define RATE_11025 (0x5 << 8) /* 11.025 kHz */
-#define RATE_9600 (0x6 << 8) /* 9.6 kHz */
-#define RATE_8820 (0x6 << 8) /* 8.82 kHz */
-#define RATE_8000 (0x7 << 8) /* 8 kHz */
-#define RATE_7350 (0x7 << 8) /* 7.35 kHz */
-
-#define RATE_LOW 1 /* HIGH = 48kHz, etc; LOW = 44.1kHz, etc. */
-
-/*******************/
-/* Burgundy values */
-/*******************/
-
-#define MASK_ADDR_BURGUNDY_INPSEL21 (0x11 << 12)
-#define MASK_ADDR_BURGUNDY_INPSEL3 (0x12 << 12)
-
-#define MASK_ADDR_BURGUNDY_GAINCH1 (0x13 << 12)
-#define MASK_ADDR_BURGUNDY_GAINCH2 (0x14 << 12)
-#define MASK_ADDR_BURGUNDY_GAINCH3 (0x15 << 12)
-#define MASK_ADDR_BURGUNDY_GAINCH4 (0x16 << 12)
-
-#define MASK_ADDR_BURGUNDY_VOLCH1 (0x20 << 12)
-#define MASK_ADDR_BURGUNDY_VOLCH2 (0x21 << 12)
-#define MASK_ADDR_BURGUNDY_VOLCH3 (0x22 << 12)
-#define MASK_ADDR_BURGUNDY_VOLCH4 (0x23 << 12)
-
-#define MASK_ADDR_BURGUNDY_OUTPUTSELECTS (0x2B << 12)
-#define MASK_ADDR_BURGUNDY_OUTPUTENABLES (0x2F << 12)
-
-#define MASK_ADDR_BURGUNDY_MASTER_VOLUME (0x30 << 12)
-
-#define MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES (0x60 << 12)
-
-#define MASK_ADDR_BURGUNDY_ATTENSPEAKER (0x62 << 12)
-#define MASK_ADDR_BURGUNDY_ATTENLINEOUT (0x63 << 12)
-#define MASK_ADDR_BURGUNDY_ATTENHP (0x64 << 12)
-
-#define MASK_ADDR_BURGUNDY_VOLCD (MASK_ADDR_BURGUNDY_VOLCH1)
-#define MASK_ADDR_BURGUNDY_VOLLINE (MASK_ADDR_BURGUNDY_VOLCH2)
-#define MASK_ADDR_BURGUNDY_VOLMIC (MASK_ADDR_BURGUNDY_VOLCH3)
-#define MASK_ADDR_BURGUNDY_VOLMODEM (MASK_ADDR_BURGUNDY_VOLCH4)
-
-#define MASK_ADDR_BURGUNDY_GAINCD (MASK_ADDR_BURGUNDY_GAINCH1)
-#define MASK_ADDR_BURGUNDY_GAINLINE (MASK_ADDR_BURGUNDY_GAINCH2)
-#define MASK_ADDR_BURGUNDY_GAINMIC (MASK_ADDR_BURGUNDY_GAINCH3)
-#define MASK_ADDR_BURGUNDY_GAINMODEM (MASK_ADDR_BURGUNDY_VOLCH4)
-
-
-/* These are all default values for the burgundy */
-#define DEF_BURGUNDY_INPSEL21 (0xAA)
-#define DEF_BURGUNDY_INPSEL3 (0x0A)
-
-#define DEF_BURGUNDY_GAINCD (0x33)
-#define DEF_BURGUNDY_GAINLINE (0x44)
-#define DEF_BURGUNDY_GAINMIC (0x44)
-#define DEF_BURGUNDY_GAINMODEM (0x06)
-
-/* Remember: lowest volume here is 0x9b */
-#define DEF_BURGUNDY_VOLCD (0xCCCCCCCC)
-#define DEF_BURGUNDY_VOLLINE (0x00000000)
-#define DEF_BURGUNDY_VOLMIC (0x00000000)
-#define DEF_BURGUNDY_VOLMODEM (0xCCCCCCCC)
-
-#define DEF_BURGUNDY_OUTPUTSELECTS (0x010f010f)
-#define DEF_BURGUNDY_OUTPUTENABLES (0x0A)
-
-#define DEF_BURGUNDY_MASTER_VOLUME (0xFFFFFFFF)
-
-#define DEF_BURGUNDY_MORE_OUTPUTENABLES (0x7E)
-
-#define DEF_BURGUNDY_ATTENSPEAKER (0x44)
-#define DEF_BURGUNDY_ATTENLINEOUT (0xCC)
-#define DEF_BURGUNDY_ATTENHP (0xCC)
-
-/*********************/
-/* i2s layout values */
-/*********************/
-
-#define I2S_REG_INT_CTL 0x00
-#define I2S_REG_SERIAL_FORMAT 0x10
-#define I2S_REG_CODEC_MSG_OUT 0x20
-#define I2S_REG_CODEC_MSG_IN 0x30
-#define I2S_REG_FRAME_COUNT 0x40
-#define I2S_REG_FRAME_MATCH 0x50
-#define I2S_REG_DATAWORD_SIZES 0x60
-#define I2S_REG_PEAKLEVEL_SEL 0x70
-#define I2S_REG_PEAKLEVEL_IN0 0x80
-#define I2S_REG_PEAKLEVEL_IN1 0x90
-
-#endif /* _AWACS_DEFS_H_ */
diff --git a/sound/oss/dmasound/dac3550a.c b/sound/oss/dmasound/dac3550a.c
deleted file mode 100644
index 0f0d03a55dab..000000000000
--- a/sound/oss/dmasound/dac3550a.c
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Driver for the i2c/i2s based DAC3550a sound chip used
- * on some Apple iBooks. Also known as "DACA".
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/proc_fs.h>
-#include <linux/ioport.h>
-#include <linux/sysctl.h>
-#include <linux/types.h>
-#include <linux/i2c.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#include <asm/errno.h>
-#include <asm/io.h>
-
-#include "dmasound.h"
-
-/* FYI: This code was derived from the tas3001c.c Texas/Tumbler mixer
- * control code, as well as info derived from the AppleDACAAudio driver
- * from Darwin CVS (main thing I derived being register numbers and
- * values, as well as when to make the calls). */
-
-#define I2C_DRIVERID_DACA (0xFDCB)
-
-#define DACA_VERSION "0.1"
-#define DACA_DATE "20010930"
-
-static int cur_left_vol;
-static int cur_right_vol;
-static struct i2c_client *daca_client;
-
-static int daca_attach_adapter(struct i2c_adapter *adapter);
-static int daca_detect_client(struct i2c_adapter *adapter, int address);
-static int daca_detach_client(struct i2c_client *client);
-
-struct i2c_driver daca_driver = {
- .driver = {
- .name = "DAC3550A driver V " DACA_VERSION,
- },
- .id = I2C_DRIVERID_DACA,
- .attach_adapter = daca_attach_adapter,
- .detach_client = daca_detach_client,
-};
-
-#define VOL_MAX ((1<<20) - 1)
-
-void daca_get_volume(uint * left_vol, uint *right_vol)
-{
- *left_vol = cur_left_vol >> 5;
- *right_vol = cur_right_vol >> 5;
-}
-
-int daca_set_volume(uint left_vol, uint right_vol)
-{
- unsigned short voldata;
-
- if (!daca_client)
- return -1;
-
- /* Derived from experience, not from any specific values */
- left_vol <<= 5;
- right_vol <<= 5;
-
- if (left_vol > VOL_MAX)
- left_vol = VOL_MAX;
- if (right_vol > VOL_MAX)
- right_vol = VOL_MAX;
-
- voldata = ((left_vol >> 14) & 0x3f) << 8;
- voldata |= (right_vol >> 14) & 0x3f;
-
- if (i2c_smbus_write_word_data(daca_client, 2, voldata) < 0) {
- printk("daca: failed to set volume \n");
- return -1;
- }
-
- cur_left_vol = left_vol;
- cur_right_vol = right_vol;
-
- return 0;
-}
-
-int daca_leave_sleep(void)
-{
- if (!daca_client)
- return -1;
-
- /* Do a short sleep, just to make sure I2C bus is awake and paying
- * attention to us
- */
- msleep(20);
- /* Write the sample rate reg the value it needs */
- i2c_smbus_write_byte_data(daca_client, 1, 8);
- daca_set_volume(cur_left_vol >> 5, cur_right_vol >> 5);
- /* Another short delay, just to make sure the other I2C bus writes
- * have taken...
- */
- msleep(20);
- /* Write the global config reg - invert right power amp,
- * DAC on, use 5-volt mode */
- i2c_smbus_write_byte_data(daca_client, 3, 0x45);
-
- return 0;
-}
-
-int daca_enter_sleep(void)
-{
- if (!daca_client)
- return -1;
-
- i2c_smbus_write_byte_data(daca_client, 1, 8);
- daca_set_volume(cur_left_vol >> 5, cur_right_vol >> 5);
-
- /* Write the global config reg - invert right power amp,
- * DAC on, enter low-power mode, use 5-volt mode
- */
- i2c_smbus_write_byte_data(daca_client, 3, 0x65);
-
- return 0;
-}
-
-static int daca_attach_adapter(struct i2c_adapter *adapter)
-{
- if (!strncmp(adapter->name, "mac-io", 6))
- daca_detect_client(adapter, 0x4d);
- return 0;
-}
-
-static int daca_init_client(struct i2c_client * new_client)
-{
- /*
- * Probe is not working with the current i2c-keywest
- * driver. We try to use addr 0x4d on each adapters
- * instead, by setting the format register.
- *
- * FIXME: I'm sure that can be obtained from the
- * device-tree. --BenH.
- */
-
- /* Write the global config reg - invert right power amp,
- * DAC on, use 5-volt mode
- */
- if (i2c_smbus_write_byte_data(new_client, 3, 0x45))
- return -1;
-
- i2c_smbus_write_byte_data(new_client, 1, 8);
- daca_client = new_client;
- daca_set_volume(15000, 15000);
-
- return 0;
-}
-
-static int daca_detect_client(struct i2c_adapter *adapter, int address)
-{
- const char *client_name = "DAC 3550A Digital Equalizer";
- struct i2c_client *new_client;
- int rc = -ENODEV;
-
- new_client = kzalloc(sizeof(*new_client), GFP_KERNEL);
- if (!new_client)
- return -ENOMEM;
-
- new_client->addr = address;
- new_client->adapter = adapter;
- new_client->driver = &daca_driver;
- new_client->flags = 0;
- strcpy(new_client->name, client_name);
-
- if (daca_init_client(new_client))
- goto bail;
-
- /* Tell the i2c layer a new client has arrived */
- if (i2c_attach_client(new_client))
- goto bail;
-
- return 0;
- bail:
- kfree(new_client);
- return rc;
-}
-
-
-static int daca_detach_client(struct i2c_client *client)
-{
- if (client == daca_client)
- daca_client = NULL;
-
- i2c_detach_client(client);
- kfree(client);
- return 0;
-}
-
-void daca_cleanup(void)
-{
- i2c_del_driver(&daca_driver);
-}
-
-int daca_init(void)
-{
- printk("dac3550a driver version %s (%s)\n",DACA_VERSION,DACA_DATE);
- return i2c_add_driver(&daca_driver);
-}
diff --git a/sound/oss/dmasound/dmasound.h b/sound/oss/dmasound/dmasound.h
index 25dd5a318eb4..d978b0096564 100644
--- a/sound/oss/dmasound/dmasound.h
+++ b/sound/oss/dmasound/dmasound.h
@@ -59,7 +59,6 @@ static inline int ioctl_return(int __user *addr, int value)
*/
#undef HAS_8BIT_TABLES
-#undef HAS_RECORD
#if defined(CONFIG_DMASOUND_ATARI) || defined(CONFIG_DMASOUND_ATARI_MODULE) ||\
defined(CONFIG_DMASOUND_PAULA) || defined(CONFIG_DMASOUND_PAULA_MODULE) ||\
@@ -83,10 +82,6 @@ static inline int ioctl_return(int __user *addr, int value)
#define DEFAULT_N_BUFFERS 4
#define DEFAULT_BUFF_SIZE (1<<15)
-#if defined(CONFIG_DMASOUND_PMAC) || defined(CONFIG_DMASOUND_PMAC_MODULE)
-#define HAS_RECORD
-#endif
-
/*
* Initialization
*/
@@ -168,9 +163,6 @@ struct sound_settings {
SETTINGS soft; /* software settings */
SETTINGS dsp; /* /dev/dsp default settings */
TRANS *trans_write; /* supported translations */
-#ifdef HAS_RECORD
- TRANS *trans_read; /* supported translations */
-#endif
int volume_left; /* volume (range is machine dependent) */
int volume_right;
int bass; /* tone (range is machine dependent) */
@@ -253,11 +245,6 @@ struct sound_queue {
extern struct sound_queue dmasound_write_sq;
#define write_sq dmasound_write_sq
-#ifdef HAS_RECORD
-extern struct sound_queue dmasound_read_sq;
-#define read_sq dmasound_read_sq
-#endif
-
extern int dmasound_catchRadius;
#define catchRadius dmasound_catchRadius
diff --git a/sound/oss/dmasound/dmasound_awacs.c b/sound/oss/dmasound/dmasound_awacs.c
deleted file mode 100644
index 8f6388004f44..000000000000
--- a/sound/oss/dmasound/dmasound_awacs.c
+++ /dev/null
@@ -1,3215 +0,0 @@
-/*
- * linux/sound/oss/dmasound/dmasound_awacs.c
- *
- * PowerMac `AWACS' and `Burgundy' DMA Sound Driver
- * with some limited support for DACA & Tumbler
- *
- * See linux/sound/oss/dmasound/dmasound_core.c for copyright and
- * history prior to 2001/01/26.
- *
- * 26/01/2001 ed 0.1 Iain Sandoe
- * - added version info.
- * - moved dbdma command buffer allocation to PMacXXXSqSetup()
- * - fixed up beep dbdma cmd buffers
- *
- * 08/02/2001 [0.2]
- * - make SNDCTL_DSP_GETFMTS return the correct info for the h/w
- * - move soft format translations to a separate file
- * - [0.3] make SNDCTL_DSP_GETCAPS return correct info.
- * - [0.4] more informative machine name strings.
- * - [0.5]
- * - record changes.
- * - made the default_hard/soft entries.
- * 04/04/2001 [0.6]
- * - minor correction to bit assignments in awacs_defs.h
- * - incorporate mixer changes from 2.2.x back-port.
- * - take out passthru as a rec input (it isn't).
- * - make Input Gain slider work the 'right way up'.
- * - try to make the mixer sliders more logical - so now the
- * input selectors are just two-state (>50% == ON) and the
- * Input Gain slider handles the rest of the gain issues.
- * - try to pick slider representations that most closely match
- * the actual use - e.g. IGain for input gain...
- * - first stab at over/under-run detection.
- * - minor cosmetic changes to IRQ identification.
- * - fix bug where rates > max would be reported as supported.
- * - first stab at over/under-run detection.
- * - make use of i2c for mixer settings conditional on perch
- * rather than cuda (some machines without perch have cuda).
- * - fix bug where TX stops when dbdma status comes up "DEAD"
- * so far only reported on PowerComputing clones ... but.
- * - put in AWACS/Screamer register write timeouts.
- * - part way to partitioning the init() stuff
- * - first pass at 'tumbler' stuff (not support - just an attempt
- * to allow the driver to load on new G4s).
- * 01/02/2002 [0.7] - BenH
- * - all sort of minor bits went in since the latest update, I
- * bumped the version number for that reason
- *
- * 07/26/2002 [0.8] - BenH
- * - More minor bits since last changelog (I should be more careful
- * with those)
- * - Support for snapper & better tumbler integration by Toby Sargeant
- * - Headphone detect for scremer by Julien Blache
- * - More tumbler fixed by Andreas Schwab
- * 11/29/2003 [0.8.1] - Renzo Davoli (King Enzo)
- * - Support for Snapper line in
- * - snapper input resampling (for rates < 44100)
- * - software line gain control
- */
-
-/* GENERAL FIXME/TODO: check that the assumptions about what is written to
- mac-io is valid for DACA & Tumbler.
-
- This driver is in bad need of a rewrite. The dbdma code has to be split,
- some proper device-tree parsing code has to be written, etc...
-*/
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/soundcard.h>
-#include <linux/adb.h>
-#include <linux/nvram.h>
-#include <linux/tty.h>
-#include <linux/vt_kern.h>
-#include <linux/spinlock.h>
-#include <linux/kmod.h>
-#include <linux/interrupt.h>
-#include <linux/input.h>
-#include <linux/mutex.h>
-#ifdef CONFIG_ADB_CUDA
-#include <linux/cuda.h>
-#endif
-#ifdef CONFIG_ADB_PMU
-#include <linux/pmu.h>
-#endif
-
-#include <asm/uaccess.h>
-#include <asm/prom.h>
-#include <asm/machdep.h>
-#include <asm/io.h>
-#include <asm/dbdma.h>
-#include <asm/pmac_feature.h>
-#include <asm/irq.h>
-#include <asm/nvram.h>
-
-#include "awacs_defs.h"
-#include "dmasound.h"
-#include "tas3001c.h"
-#include "tas3004.h"
-#include "tas_common.h"
-
-#define DMASOUND_AWACS_REVISION 0
-#define DMASOUND_AWACS_EDITION 7
-
-#define AWACS_SNAPPER 110 /* fake revision # for snapper */
-#define AWACS_BURGUNDY 100 /* fake revision # for burgundy */
-#define AWACS_TUMBLER 90 /* fake revision # for tumbler */
-#define AWACS_DACA 80 /* fake revision # for daca (ibook) */
-#define AWACS_AWACS 2 /* holding revision for AWACS */
-#define AWACS_SCREAMER 3 /* holding revision for Screamer */
-/*
- * Interrupt numbers and addresses, & info obtained from the device tree.
- */
-static int awacs_irq, awacs_tx_irq, awacs_rx_irq;
-static volatile struct awacs_regs __iomem *awacs;
-static volatile u32 __iomem *i2s;
-static volatile struct dbdma_regs __iomem *awacs_txdma, *awacs_rxdma;
-static int awacs_rate_index;
-static int awacs_subframe;
-static struct device_node* awacs_node;
-static struct device_node* i2s_node;
-static struct resource awacs_rsrc[3];
-
-static char awacs_name[64];
-static int awacs_revision;
-static int awacs_sleeping;
-static DEFINE_MUTEX(dmasound_mutex);
-
-static int sound_device_id; /* exists after iMac revA */
-static int hw_can_byteswap = 1 ; /* most pmac sound h/w can */
-
-/* model info */
-/* To be replaced with better interaction with pmac_feature.c */
-static int is_pbook_3X00;
-static int is_pbook_g3;
-
-/* expansion info */
-static int has_perch;
-static int has_ziva;
-
-/* for earlier powerbooks which need fiddling with mac-io to enable
- * cd etc.
-*/
-static unsigned char __iomem *latch_base;
-static unsigned char __iomem *macio_base;
-
-/*
- * Space for the DBDMA command blocks.
- */
-static void *awacs_tx_cmd_space;
-static volatile struct dbdma_cmd *awacs_tx_cmds;
-static int number_of_tx_cmd_buffers;
-
-static void *awacs_rx_cmd_space;
-static volatile struct dbdma_cmd *awacs_rx_cmds;
-static int number_of_rx_cmd_buffers;
-
-/*
- * Cached values of AWACS registers (we can't read them).
- * Except on the burgundy (and screamer). XXX
- */
-
-int awacs_reg[8];
-int awacs_reg1_save;
-
-/* tracking values for the mixer contents
-*/
-
-static int spk_vol;
-static int line_vol;
-static int passthru_vol;
-
-static int ip_gain; /* mic preamp settings */
-static int rec_lev = 0x4545 ; /* default CD gain 69 % */
-static int mic_lev;
-static int cd_lev = 0x6363 ; /* 99 % */
-static int line_lev;
-
-static int hdp_connected;
-
-/*
- * Stuff for outputting a beep. The values range from -327 to +327
- * so we can multiply by an amplitude in the range 0..100 to get a
- * signed short value to put in the output buffer.
- */
-static short beep_wform[256] = {
- 0, 40, 79, 117, 153, 187, 218, 245,
- 269, 288, 304, 316, 323, 327, 327, 324,
- 318, 310, 299, 288, 275, 262, 249, 236,
- 224, 213, 204, 196, 190, 186, 183, 182,
- 182, 183, 186, 189, 192, 196, 200, 203,
- 206, 208, 209, 209, 209, 207, 204, 201,
- 197, 193, 188, 183, 179, 174, 170, 166,
- 163, 161, 160, 159, 159, 160, 161, 162,
- 164, 166, 168, 169, 171, 171, 171, 170,
- 169, 167, 163, 159, 155, 150, 144, 139,
- 133, 128, 122, 117, 113, 110, 107, 105,
- 103, 103, 103, 103, 104, 104, 105, 105,
- 105, 103, 101, 97, 92, 86, 78, 68,
- 58, 45, 32, 18, 3, -11, -26, -41,
- -55, -68, -79, -88, -95, -100, -102, -102,
- -99, -93, -85, -75, -62, -48, -33, -16,
- 0, 16, 33, 48, 62, 75, 85, 93,
- 99, 102, 102, 100, 95, 88, 79, 68,
- 55, 41, 26, 11, -3, -18, -32, -45,
- -58, -68, -78, -86, -92, -97, -101, -103,
- -105, -105, -105, -104, -104, -103, -103, -103,
- -103, -105, -107, -110, -113, -117, -122, -128,
- -133, -139, -144, -150, -155, -159, -163, -167,
- -169, -170, -171, -171, -171, -169, -168, -166,
- -164, -162, -161, -160, -159, -159, -160, -161,
- -163, -166, -170, -174, -179, -183, -188, -193,
- -197, -201, -204, -207, -209, -209, -209, -208,
- -206, -203, -200, -196, -192, -189, -186, -183,
- -182, -182, -183, -186, -190, -196, -204, -213,
- -224, -236, -249, -262, -275, -288, -299, -310,
- -318, -324, -327, -327, -323, -316, -304, -288,
- -269, -245, -218, -187, -153, -117, -79, -40,
-};
-
-/* beep support */
-#define BEEP_SRATE 22050 /* 22050 Hz sample rate */
-#define BEEP_BUFLEN 512
-#define BEEP_VOLUME 15 /* 0 - 100 */
-
-static int beep_vol = BEEP_VOLUME;
-static int beep_playing;
-static int awacs_beep_state;
-static short *beep_buf;
-static void *beep_dbdma_cmd_space;
-static volatile struct dbdma_cmd *beep_dbdma_cmd;
-
-/* Burgundy functions */
-static void awacs_burgundy_wcw(unsigned addr,unsigned newval);
-static unsigned awacs_burgundy_rcw(unsigned addr);
-static void awacs_burgundy_write_volume(unsigned address, int volume);
-static int awacs_burgundy_read_volume(unsigned address);
-static void awacs_burgundy_write_mvolume(unsigned address, int volume);
-static int awacs_burgundy_read_mvolume(unsigned address);
-
-/* we will allocate a single 'emergency' dbdma cmd block to use if the
- tx status comes up "DEAD". This happens on some PowerComputing Pmac
- clones, either owing to a bug in dbdma or some interaction between
- IDE and sound. However, this measure would deal with DEAD status if
- if appeared elsewhere.
-
- for the sake of memory efficiency we'll allocate this cmd as part of
- the beep cmd stuff.
-*/
-
-static volatile struct dbdma_cmd *emergency_dbdma_cmd;
-
-#ifdef CONFIG_PM
-/*
- * Stuff for restoring after a sleep.
- */
-static void awacs_sleep_notify(struct pmu_sleep_notifier *self, int when);
-struct pmu_sleep_notifier awacs_sleep_notifier = {
- awacs_sleep_notify, SLEEP_LEVEL_SOUND,
-};
-#endif /* CONFIG_PM */
-
-/* for (soft) sample rate translations */
-int expand_bal; /* Balance factor for expanding (not volume!) */
-int expand_read_bal; /* Balance factor for expanding reads (not volume!) */
-
-/*** Low level stuff *********************************************************/
-
-static void *PMacAlloc(unsigned int size, gfp_t flags);
-static void PMacFree(void *ptr, unsigned int size);
-static int PMacIrqInit(void);
-#ifdef MODULE
-static void PMacIrqCleanup(void);
-#endif
-static void PMacSilence(void);
-static void PMacInit(void);
-static int PMacSetFormat(int format);
-static int PMacSetVolume(int volume);
-static void PMacPlay(void);
-static void PMacRecord(void);
-static irqreturn_t pmac_awacs_tx_intr(int irq, void *devid);
-static irqreturn_t pmac_awacs_rx_intr(int irq, void *devid);
-static irqreturn_t pmac_awacs_intr(int irq, void *devid);
-static void awacs_write(int val);
-static int awacs_get_volume(int reg, int lshift);
-static int awacs_volume_setter(int volume, int n, int mute, int lshift);
-
-
-/*** Mid level stuff **********************************************************/
-
-static int PMacMixerIoctl(u_int cmd, u_long arg);
-static int PMacWriteSqSetup(void);
-static int PMacReadSqSetup(void);
-static void PMacAbortRead(void);
-
-extern TRANS transAwacsNormal ;
-extern TRANS transAwacsExpand ;
-extern TRANS transAwacsNormalRead ;
-extern TRANS transAwacsExpandRead ;
-
-extern int daca_init(void);
-extern void daca_cleanup(void);
-extern int daca_set_volume(uint left_vol, uint right_vol);
-extern void daca_get_volume(uint * left_vol, uint *right_vol);
-extern int daca_enter_sleep(void);
-extern int daca_leave_sleep(void);
-
-#define TRY_LOCK() \
- if ((rc = mutex_lock_interruptible(&dmasound_mutex)) != 0) \
- return rc;
-#define LOCK() mutex_lock(&dmasound_mutex);
-
-#define UNLOCK() mutex_unlock(&dmasound_mutex);
-
-/* We use different versions that the ones provided in dmasound.h
- *
- * FIXME: Use different names ;)
- */
-#undef IOCTL_IN
-#undef IOCTL_OUT
-
-#define IOCTL_IN(arg, ret) \
- rc = get_user(ret, (int __user *)(arg)); \
- if (rc) break;
-#define IOCTL_OUT(arg, ret) \
- ioctl_return2((int __user *)(arg), ret)
-
-static inline int ioctl_return2(int __user *addr, int value)
-{
- return value < 0 ? value : put_user(value, addr);
-}
-
-
-/*** AE - TUMBLER / SNAPPER START ************************************************/
-
-
-int gpio_audio_reset, gpio_audio_reset_pol;
-int gpio_amp_mute, gpio_amp_mute_pol;
-int gpio_headphone_mute, gpio_headphone_mute_pol;
-int gpio_headphone_detect, gpio_headphone_detect_pol;
-int gpio_headphone_irq;
-
-int
-setup_audio_gpio(const char *name, const char* compatible, int *gpio_addr, int* gpio_pol)
-{
- struct device_node *gpiop;
- struct device_node *np;
- const u32* pp;
- int ret = -ENODEV;
-
- gpiop = of_find_node_by_name(NULL, "gpio");
- if (!gpiop)
- goto done;
-
- np = of_get_next_child(gpiop, NULL);
- while(np != 0) {
- if (name) {
- const char *property =
- of_get_property(np,"audio-gpio",NULL);
- if (property != 0 && strcmp(property,name) == 0)
- break;
- } else if (compatible && of_device_is_compatible(np, compatible))
- break;
- np = of_get_next_child(gpiop, np);
- }
- if (!np)
- goto done;
- pp = of_get_property(np, "AAPL,address", NULL);
- if (!pp)
- goto done;
- *gpio_addr = (*pp) & 0x0000ffff;
- pp = of_get_property(np, "audio-gpio-active-state", NULL);
- if (pp)
- *gpio_pol = *pp;
- else
- *gpio_pol = 1;
- ret = irq_of_parse_and_map(np, 0);
-done:
- of_node_put(np);
- of_node_put(gpiop);
- return ret;
-}
-
-static inline void
-write_audio_gpio(int gpio_addr, int data)
-{
- if (!gpio_addr)
- return;
- pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, gpio_addr, data ? 0x05 : 0x04);
-}
-
-static inline int
-read_audio_gpio(int gpio_addr)
-{
- if (!gpio_addr)
- return 0;
- return ((pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, gpio_addr, 0) & 0x02) !=0);
-}
-
-/*
- * Headphone interrupt via GPIO (Tumbler, Snapper, DACA)
- */
-static irqreturn_t
-headphone_intr(int irq, void *devid)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&dmasound.lock, flags);
- if (read_audio_gpio(gpio_headphone_detect) == gpio_headphone_detect_pol) {
- printk(KERN_INFO "Audio jack plugged, muting speakers.\n");
- write_audio_gpio(gpio_headphone_mute, !gpio_headphone_mute_pol);
- write_audio_gpio(gpio_amp_mute, gpio_amp_mute_pol);
- tas_output_device_change(sound_device_id,TAS_OUTPUT_HEADPHONES,0);
- } else {
- printk(KERN_INFO "Audio jack unplugged, enabling speakers.\n");
- write_audio_gpio(gpio_amp_mute, !gpio_amp_mute_pol);
- write_audio_gpio(gpio_headphone_mute, gpio_headphone_mute_pol);
- tas_output_device_change(sound_device_id,TAS_OUTPUT_INTERNAL_SPKR,0);
- }
- spin_unlock_irqrestore(&dmasound.lock, flags);
- return IRQ_HANDLED;
-}
-
-
-/* Initialize tumbler */
-
-static int
-tas_dmasound_init(void)
-{
- setup_audio_gpio(
- "audio-hw-reset",
- NULL,
- &gpio_audio_reset,
- &gpio_audio_reset_pol);
- setup_audio_gpio(
- "amp-mute",
- NULL,
- &gpio_amp_mute,
- &gpio_amp_mute_pol);
- setup_audio_gpio("headphone-mute",
- NULL,
- &gpio_headphone_mute,
- &gpio_headphone_mute_pol);
- gpio_headphone_irq = setup_audio_gpio(
- "headphone-detect",
- NULL,
- &gpio_headphone_detect,
- &gpio_headphone_detect_pol);
- /* Fix some broken OF entries in desktop machines */
- if (!gpio_headphone_irq)
- gpio_headphone_irq = setup_audio_gpio(
- NULL,
- "keywest-gpio15",
- &gpio_headphone_detect,
- &gpio_headphone_detect_pol);
-
- write_audio_gpio(gpio_audio_reset, gpio_audio_reset_pol);
- msleep(100);
- write_audio_gpio(gpio_audio_reset, !gpio_audio_reset_pol);
- msleep(100);
- if (gpio_headphone_irq) {
- if (request_irq(gpio_headphone_irq,headphone_intr,0,"Headphone detect",NULL) < 0) {
- printk(KERN_ERR "tumbler: Can't request headphone interrupt\n");
- gpio_headphone_irq = 0;
- } else {
- u8 val;
- /* Activate headphone status interrupts */
- val = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, gpio_headphone_detect, 0);
- pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, gpio_headphone_detect, val | 0x80);
- /* Trigger it */
- headphone_intr(0, NULL);
- }
- }
- if (!gpio_headphone_irq) {
- /* Some machine enter this case ? */
- printk(KERN_WARNING "tumbler: Headphone detect IRQ not found, enabling all outputs !\n");
- write_audio_gpio(gpio_amp_mute, !gpio_amp_mute_pol);
- write_audio_gpio(gpio_headphone_mute, !gpio_headphone_mute_pol);
- }
- return 0;
-}
-
-
-static int
-tas_dmasound_cleanup(void)
-{
- if (gpio_headphone_irq)
- free_irq(gpio_headphone_irq, NULL);
- return 0;
-}
-
-/* We don't support 48k yet */
-static int tas_freqs[1] = { 44100 } ;
-static int tas_freqs_ok[1] = { 1 } ;
-
-/* don't know what to do really - just have to leave it where
- * OF left things
-*/
-
-static int
-tas_set_frame_rate(void)
-{
- if (i2s) {
- out_le32(i2s + (I2S_REG_SERIAL_FORMAT >> 2), 0x41190000);
- out_le32(i2s + (I2S_REG_DATAWORD_SIZES >> 2), 0x02000200);
- }
- dmasound.hard.speed = 44100 ;
- awacs_rate_index = 0 ;
- return 44100 ;
-}
-
-static int
-tas_mixer_ioctl(u_int cmd, u_long arg)
-{
- int __user *argp = (int __user *)arg;
- int data;
- int rc;
-
- rc=tas_device_ioctl(cmd, arg);
- if (rc != -EINVAL) {
- return rc;
- }
-
- if ((cmd & ~0xff) == MIXER_WRITE(0) &&
- tas_supported_mixers() & (1<<(cmd & 0xff))) {
- rc = get_user(data, argp);
- if (rc<0) return rc;
- tas_set_mixer_level(cmd & 0xff, data);
- tas_get_mixer_level(cmd & 0xff, &data);
- return ioctl_return2(argp, data);
- }
- if ((cmd & ~0xff) == MIXER_READ(0) &&
- tas_supported_mixers() & (1<<(cmd & 0xff))) {
- tas_get_mixer_level(cmd & 0xff, &data);
- return ioctl_return2(argp, data);
- }
-
- switch(cmd) {
- case SOUND_MIXER_READ_DEVMASK:
- data = tas_supported_mixers() | SOUND_MASK_SPEAKER;
- rc = IOCTL_OUT(arg, data);
- break;
- case SOUND_MIXER_READ_STEREODEVS:
- data = tas_stereo_mixers();
- rc = IOCTL_OUT(arg, data);
- break;
- case SOUND_MIXER_READ_CAPS:
- rc = IOCTL_OUT(arg, 0);
- break;
- case SOUND_MIXER_READ_RECMASK:
- // XXX FIXME: find a way to check what is really available */
- data = SOUND_MASK_LINE | SOUND_MASK_MIC;
- rc = IOCTL_OUT(arg, data);
- break;
- case SOUND_MIXER_READ_RECSRC:
- if (awacs_reg[0] & MASK_MUX_AUDIN)
- data |= SOUND_MASK_LINE;
- if (awacs_reg[0] & MASK_MUX_MIC)
- data |= SOUND_MASK_MIC;
- rc = IOCTL_OUT(arg, data);
- break;
- case SOUND_MIXER_WRITE_RECSRC:
- IOCTL_IN(arg, data);
- data =0;
- rc = IOCTL_OUT(arg, data);
- break;
- case SOUND_MIXER_WRITE_SPEAKER: /* really bell volume */
- IOCTL_IN(arg, data);
- beep_vol = data & 0xff;
- /* fall through */
- case SOUND_MIXER_READ_SPEAKER:
- rc = IOCTL_OUT(arg, (beep_vol<<8) | beep_vol);
- break;
- case SOUND_MIXER_OUTMASK:
- case SOUND_MIXER_OUTSRC:
- default:
- rc = -EINVAL;
- }
-
- return rc;
-}
-
-static void __init
-tas_init_frame_rates(const unsigned int *prop, unsigned int l)
-{
- int i ;
- if (prop) {
- for (i=0; i<1; i++)
- tas_freqs_ok[i] = 0;
- for (l /= sizeof(int); l > 0; --l) {
- unsigned int r = *prop++;
- /* Apple 'Fixed' format */
- if (r >= 0x10000)
- r >>= 16;
- for (i = 0; i < 1; ++i) {
- if (r == tas_freqs[i]) {
- tas_freqs_ok[i] = 1;
- break;
- }
- }
- }
- }
- /* else we assume that all the rates are available */
-}
-
-
-/*** AE - TUMBLER / SNAPPER END ************************************************/
-
-
-
-/*** Low level stuff *********************************************************/
-
-/*
- * PCI PowerMac, with AWACS, Screamer, Burgundy, DACA or Tumbler and DBDMA.
- */
-static void *PMacAlloc(unsigned int size, gfp_t flags)
-{
- return kmalloc(size, flags);
-}
-
-static void PMacFree(void *ptr, unsigned int size)
-{
- kfree(ptr);
-}
-
-static int __init PMacIrqInit(void)
-{
- if (awacs)
- if (request_irq(awacs_irq, pmac_awacs_intr, 0, "Built-in Sound misc", NULL))
- return 0;
- if (request_irq(awacs_tx_irq, pmac_awacs_tx_intr, 0, "Built-in Sound out", NULL)
- || request_irq(awacs_rx_irq, pmac_awacs_rx_intr, 0, "Built-in Sound in", NULL))
- return 0;
- return 1;
-}
-
-#ifdef MODULE
-static void PMacIrqCleanup(void)
-{
- /* turn off input & output dma */
- DBDMA_DO_STOP(awacs_txdma);
- DBDMA_DO_STOP(awacs_rxdma);
-
- if (awacs)
- /* disable interrupts from awacs interface */
- out_le32(&awacs->control, in_le32(&awacs->control) & 0xfff);
-
- /* Switch off the sound clock */
- pmac_call_feature(PMAC_FTR_SOUND_CHIP_ENABLE, awacs_node, 0, 0);
- /* Make sure proper bits are set on pismo & tipb */
- if ((machine_is_compatible("PowerBook3,1") ||
- machine_is_compatible("PowerBook3,2")) && awacs) {
- awacs_reg[1] |= MASK_PAROUT0 | MASK_PAROUT1;
- awacs_write(MASK_ADDR1 | awacs_reg[1]);
- msleep(200);
- }
- if (awacs)
- free_irq(awacs_irq, NULL);
- free_irq(awacs_tx_irq, NULL);
- free_irq(awacs_rx_irq, NULL);
-
- if (awacs)
- iounmap(awacs);
- if (i2s)
- iounmap(i2s);
- iounmap(awacs_txdma);
- iounmap(awacs_rxdma);
-
- release_mem_region(awacs_rsrc[0].start,
- awacs_rsrc[0].end - awacs_rsrc[0].start + 1);
- release_mem_region(awacs_rsrc[1].start,
- awacs_rsrc[1].end - awacs_rsrc[1].start + 1);
- release_mem_region(awacs_rsrc[2].start,
- awacs_rsrc[2].end - awacs_rsrc[2].start + 1);
-
- kfree(awacs_tx_cmd_space);
- kfree(awacs_rx_cmd_space);
- kfree(beep_dbdma_cmd_space);
- kfree(beep_buf);
-#ifdef CONFIG_PM
- pmu_unregister_sleep_notifier(&awacs_sleep_notifier);
-#endif
-}
-#endif /* MODULE */
-
-static void PMacSilence(void)
-{
- /* turn off output dma */
- DBDMA_DO_STOP(awacs_txdma);
-}
-
-/* don't know what to do really - just have to leave it where
- * OF left things
-*/
-
-static int daca_set_frame_rate(void)
-{
- if (i2s) {
- out_le32(i2s + (I2S_REG_SERIAL_FORMAT >> 2), 0x41190000);
- out_le32(i2s + (I2S_REG_DATAWORD_SIZES >> 2), 0x02000200);
- }
- dmasound.hard.speed = 44100 ;
- awacs_rate_index = 0 ;
- return 44100 ;
-}
-
-static int awacs_freqs[8] = {
- 44100, 29400, 22050, 17640, 14700, 11025, 8820, 7350
-};
-static int awacs_freqs_ok[8] = { 1, 1, 1, 1, 1, 1, 1, 1 };
-
-static int
-awacs_set_frame_rate(int desired, int catch_r)
-{
- int tolerance, i = 8 ;
- /*
- * If we have a sample rate which is within catchRadius percent
- * of the requested value, we don't have to expand the samples.
- * Otherwise choose the next higher rate.
- * N.B.: burgundy awacs only works at 44100 Hz.
- */
- do {
- tolerance = catch_r * awacs_freqs[--i] / 100;
- if (awacs_freqs_ok[i]
- && dmasound.soft.speed <= awacs_freqs[i] + tolerance)
- break;
- } while (i > 0);
- dmasound.hard.speed = awacs_freqs[i];
- awacs_rate_index = i;
-
- out_le32(&awacs->control, MASK_IEPC | (i << 8) | 0x11 );
- awacs_reg[1] = (awacs_reg[1] & ~MASK_SAMPLERATE) | (i << 3);
- awacs_write(awacs_reg[1] | MASK_ADDR1);
- return dmasound.hard.speed;
-}
-
-static int
-burgundy_set_frame_rate(void)
-{
- awacs_rate_index = 0 ;
- awacs_reg[1] = (awacs_reg[1] & ~MASK_SAMPLERATE) ;
- /* XXX disable error interrupt on burgundy for now */
- out_le32(&awacs->control, MASK_IEPC | 0 | 0x11 | MASK_IEE);
- return 44100 ;
-}
-
-static int
-set_frame_rate(int desired, int catch_r)
-{
- switch (awacs_revision) {
- case AWACS_BURGUNDY:
- dmasound.hard.speed = burgundy_set_frame_rate();
- break ;
- case AWACS_TUMBLER:
- case AWACS_SNAPPER:
- dmasound.hard.speed = tas_set_frame_rate();
- break ;
- case AWACS_DACA:
- dmasound.hard.speed =
- daca_set_frame_rate();
- break ;
- default:
- dmasound.hard.speed = awacs_set_frame_rate(desired,
- catch_r);
- break ;
- }
- return dmasound.hard.speed ;
-}
-
-static void
-awacs_recalibrate(void)
-{
- /* Sorry for the horrible delays... I hope to get that improved
- * by making the whole PM process asynchronous in a future version
- */
- msleep(750);
- awacs_reg[1] |= MASK_CMUTE | MASK_AMUTE;
- awacs_write(awacs_reg[1] | MASK_RECALIBRATE | MASK_ADDR1);
- msleep(1000);
- awacs_write(awacs_reg[1] | MASK_ADDR1);
-}
-
-static void PMacInit(void)
-{
- int tolerance;
-
- switch (dmasound.soft.format) {
- case AFMT_S16_LE:
- case AFMT_U16_LE:
- if (hw_can_byteswap)
- dmasound.hard.format = AFMT_S16_LE;
- else
- dmasound.hard.format = AFMT_S16_BE;
- break;
- default:
- dmasound.hard.format = AFMT_S16_BE;
- break;
- }
- dmasound.hard.stereo = 1;
- dmasound.hard.size = 16;
-
- /* set dmasound.hard.speed - on the basis of what we want (soft)
- * and the tolerance we'll allow.
- */
- set_frame_rate(dmasound.soft.speed, catchRadius) ;
-
- tolerance = (catchRadius * dmasound.hard.speed) / 100;
- if (dmasound.soft.speed >= dmasound.hard.speed - tolerance) {
- dmasound.trans_write = &transAwacsNormal;
- dmasound.trans_read = &transAwacsNormalRead;
- } else {
- dmasound.trans_write = &transAwacsExpand;
- dmasound.trans_read = &transAwacsExpandRead;
- }
-
- if (awacs) {
- if (hw_can_byteswap && (dmasound.hard.format == AFMT_S16_LE))
- out_le32(&awacs->byteswap, BS_VAL);
- else
- out_le32(&awacs->byteswap, 0);
- }
-
- expand_bal = -dmasound.soft.speed;
- expand_read_bal = -dmasound.soft.speed;
-}
-
-static int PMacSetFormat(int format)
-{
- int size;
- int req_format = format;
-
- switch (format) {
- case AFMT_QUERY:
- return dmasound.soft.format;
- case AFMT_MU_LAW:
- case AFMT_A_LAW:
- case AFMT_U8:
- case AFMT_S8:
- size = 8;
- break;
- case AFMT_S16_LE:
- if(!hw_can_byteswap)
- format = AFMT_S16_BE;
- case AFMT_S16_BE:
- size = 16;
- break;
- case AFMT_U16_LE:
- if(!hw_can_byteswap)
- format = AFMT_U16_BE;
- case AFMT_U16_BE:
- size = 16;
- break;
- default: /* :-) */
- printk(KERN_ERR "dmasound: unknown format 0x%x, using AFMT_U8\n",
- format);
- size = 8;
- format = AFMT_U8;
- }
-
- if (req_format == format) {
- dmasound.soft.format = format;
- dmasound.soft.size = size;
- if (dmasound.minDev == SND_DEV_DSP) {
- dmasound.dsp.format = format;
- dmasound.dsp.size = size;
- }
- }
-
- return format;
-}
-
-#define AWACS_VOLUME_TO_MASK(x) (15 - ((((x) - 1) * 15) / 99))
-#define AWACS_MASK_TO_VOLUME(y) (100 - ((y) * 99 / 15))
-
-static int awacs_get_volume(int reg, int lshift)
-{
- int volume;
-
- volume = AWACS_MASK_TO_VOLUME((reg >> lshift) & 0xf);
- volume |= AWACS_MASK_TO_VOLUME(reg & 0xf) << 8;
- return volume;
-}
-
-static int awacs_volume_setter(int volume, int n, int mute, int lshift)
-{
- int r1, rn;
-
- if (mute && volume == 0) {
- r1 = awacs_reg[1] | mute;
- } else {
- r1 = awacs_reg[1] & ~mute;
- rn = awacs_reg[n] & ~(0xf | (0xf << lshift));
- rn |= ((AWACS_VOLUME_TO_MASK(volume & 0xff) & 0xf) << lshift);
- rn |= AWACS_VOLUME_TO_MASK((volume >> 8) & 0xff) & 0xf;
- awacs_reg[n] = rn;
- awacs_write((n << 12) | rn);
- volume = awacs_get_volume(rn, lshift);
- }
- if (r1 != awacs_reg[1]) {
- awacs_reg[1] = r1;
- awacs_write(r1 | MASK_ADDR1);
- }
- return volume;
-}
-
-static int PMacSetVolume(int volume)
-{
- printk(KERN_WARNING "Bogus call to PMacSetVolume !\n");
- return 0;
-}
-
-static void awacs_setup_for_beep(int speed)
-{
- out_le32(&awacs->control,
- (in_le32(&awacs->control) & ~0x1f00)
- | ((speed > 0 ? speed : awacs_rate_index) << 8));
-
- if (hw_can_byteswap && (dmasound.hard.format == AFMT_S16_LE) && speed == -1)
- out_le32(&awacs->byteswap, BS_VAL);
- else
- out_le32(&awacs->byteswap, 0);
-}
-
-/* CHECK: how much of this *really* needs IRQs masked? */
-static void __PMacPlay(void)
-{
- volatile struct dbdma_cmd *cp;
- int next_frg, count;
-
- count = 300 ; /* > two cycles at the lowest sample rate */
-
- /* what we want to send next */
- next_frg = (write_sq.front + write_sq.active) % write_sq.max_count;
-
- if (awacs_beep_state) {
- /* sound takes precedence over beeps */
- /* stop the dma channel */
- out_le32(&awacs_txdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16);
- while ( (in_le32(&awacs_txdma->status) & RUN) && count--)
- udelay(1);
- if (awacs)
- awacs_setup_for_beep(-1);
- out_le32(&awacs_txdma->cmdptr,
- virt_to_bus(&(awacs_tx_cmds[next_frg])));
-
- beep_playing = 0;
- awacs_beep_state = 0;
- }
- /* this won't allow more than two frags to be in the output queue at
- once. (or one, if the max frags is 2 - because count can't exceed
- 2 in that case)
- */
- while (write_sq.active < 2 && write_sq.active < write_sq.count) {
- count = (write_sq.count == write_sq.active + 1) ?
- write_sq.rear_size:write_sq.block_size ;
- if (count < write_sq.block_size) {
- if (!write_sq.syncing) /* last block not yet filled,*/
- break; /* and we're not syncing or POST-ed */
- else {
- /* pretend the block is full to force a new
- block to be started on the next write */
- write_sq.rear_size = write_sq.block_size ;
- write_sq.syncing &= ~2 ; /* clear POST */
- }
- }
- cp = &awacs_tx_cmds[next_frg];
- st_le16(&cp->req_count, count);
- st_le16(&cp->xfer_status, 0);
- st_le16(&cp->command, OUTPUT_MORE + INTR_ALWAYS);
- /* put a STOP at the end of the queue - but only if we have
- space for it. This means that, if we under-run and we only
- have two fragments, we might re-play sound from an existing
- queued frag. I guess the solution to that is not to set two
- frags if you are likely to under-run...
- */
- if (write_sq.count < write_sq.max_count) {
- if (++next_frg >= write_sq.max_count)
- next_frg = 0 ; /* wrap */
- /* if we get here then we've underrun so we will stop*/
- st_le16(&awacs_tx_cmds[next_frg].command, DBDMA_STOP);
- }
- /* set the dbdma controller going, if it is not already */
- if (write_sq.active == 0)
- out_le32(&awacs_txdma->cmdptr, virt_to_bus(cp));
- (void)in_le32(&awacs_txdma->status);
- out_le32(&awacs_txdma->control, ((RUN|WAKE) << 16) + (RUN|WAKE));
- ++write_sq.active;
- }
-}
-
-static void PMacPlay(void)
-{
- LOCK();
- if (!awacs_sleeping) {
- unsigned long flags;
-
- spin_lock_irqsave(&dmasound.lock, flags);
- __PMacPlay();
- spin_unlock_irqrestore(&dmasound.lock, flags);
- }
- UNLOCK();
-}
-
-static void PMacRecord(void)
-{
- unsigned long flags;
-
- if (read_sq.active)
- return;
-
- spin_lock_irqsave(&dmasound.lock, flags);
-
- /* This is all we have to do......Just start it up.
- */
- out_le32(&awacs_rxdma->control, ((RUN|WAKE) << 16) + (RUN|WAKE));
- read_sq.active = 1;
-
- spin_unlock_irqrestore(&dmasound.lock, flags);
-}
-
-/* if the TX status comes up "DEAD" - reported on some Power Computing machines
- we need to re-start the dbdma - but from a different physical start address
- and with a different transfer length. It would get very messy to do this
- with the normal dbdma_cmd blocks - we would have to re-write the buffer start
- addresses each time. So, we will keep a single dbdma_cmd block which can be
- fiddled with.
- When DEAD status is first reported the content of the faulted dbdma block is
- copied into the emergency buffer and we note that the buffer is in use.
- we then bump the start physical address by the amount that was successfully
- output before it died.
- On any subsequent DEAD result we just do the bump-ups (we know that we are
- already using the emergency dbdma_cmd).
- CHECK: this just tries to "do it". It is possible that we should abandon
- xfers when the number of residual bytes gets below a certain value - I can
- see that this might cause a loop-forever if too small a transfer causes
- DEAD status. However this is a TODO for now - we'll see what gets reported.
- When we get a successful transfer result with the emergency buffer we just
- pretend that it completed using the original dmdma_cmd and carry on. The
- 'next_cmd' field will already point back to the original loop of blocks.
-*/
-
-static irqreturn_t
-pmac_awacs_tx_intr(int irq, void *devid)
-{
- int i = write_sq.front;
- int stat;
- int i_nowrap = write_sq.front;
- volatile struct dbdma_cmd *cp;
- /* != 0 when we are dealing with a DEAD xfer */
- static int emergency_in_use;
-
- spin_lock(&dmasound.lock);
- while (write_sq.active > 0) { /* we expect to have done something*/
- if (emergency_in_use) /* we are dealing with DEAD xfer */
- cp = emergency_dbdma_cmd ;
- else
- cp = &awacs_tx_cmds[i];
- stat = ld_le16(&cp->xfer_status);
- if (stat & DEAD) {
- unsigned short req, res ;
- unsigned int phy ;
-#ifdef DEBUG_DMASOUND
-printk("dmasound_pmac: tx-irq: xfer died - patching it up...\n") ;
-#endif
- /* to clear DEAD status we must first clear RUN
- set it to quiescent to be on the safe side */
- (void)in_le32(&awacs_txdma->status);
- out_le32(&awacs_txdma->control,
- (RUN|PAUSE|FLUSH|WAKE) << 16);
- write_sq.died++ ;
- if (!emergency_in_use) { /* new problem */
- memcpy((void *)emergency_dbdma_cmd, (void *)cp,
- sizeof(struct dbdma_cmd));
- emergency_in_use = 1;
- cp = emergency_dbdma_cmd;
- }
- /* now bump the values to reflect the amount
- we haven't yet shifted */
- req = ld_le16(&cp->req_count);
- res = ld_le16(&cp->res_count);
- phy = ld_le32(&cp->phy_addr);
- phy += (req - res);
- st_le16(&cp->req_count, res);
- st_le16(&cp->res_count, 0);
- st_le16(&cp->xfer_status, 0);
- st_le32(&cp->phy_addr, phy);
- st_le32(&cp->cmd_dep, virt_to_bus(&awacs_tx_cmds[(i+1)%write_sq.max_count]));
- st_le16(&cp->command, OUTPUT_MORE | BR_ALWAYS | INTR_ALWAYS);
-
- /* point at our patched up command block */
- out_le32(&awacs_txdma->cmdptr, virt_to_bus(cp));
- /* we must re-start the controller */
- (void)in_le32(&awacs_txdma->status);
- /* should complete clearing the DEAD status */
- out_le32(&awacs_txdma->control,
- ((RUN|WAKE) << 16) + (RUN|WAKE));
- break; /* this block is still going */
- }
- if ((stat & ACTIVE) == 0)
- break; /* this frame is still going */
- if (emergency_in_use)
- emergency_in_use = 0 ; /* done that */
- --write_sq.count;
- --write_sq.active;
- i_nowrap++;
- if (++i >= write_sq.max_count)
- i = 0;
- }
-
- /* if we stopped and we were not sync-ing - then we under-ran */
- if( write_sq.syncing == 0 ){
- stat = in_le32(&awacs_txdma->status) ;
- /* we hit the dbdma_stop */
- if( (stat & ACTIVE) == 0 ) write_sq.xruns++ ;
- }
-
- /* if we used some data up then wake the writer to supply some more*/
- if (i_nowrap != write_sq.front)
- WAKE_UP(write_sq.action_queue);
- write_sq.front = i;
-
- /* but make sure we funnel what we've already got */\
- if (!awacs_sleeping)
- __PMacPlay();
-
- /* make the wake-on-empty conditional on syncing */
- if (!write_sq.active && (write_sq.syncing & 1))
- WAKE_UP(write_sq.sync_queue); /* any time we're empty */
- spin_unlock(&dmasound.lock);
- return IRQ_HANDLED;
-}
-
-
-static irqreturn_t
-pmac_awacs_rx_intr(int irq, void *devid)
-{
- int stat ;
- /* For some reason on my PowerBook G3, I get one interrupt
- * when the interrupt vector is installed (like something is
- * pending). This happens before the dbdma is initialized by
- * us, so I just check the command pointer and if it is zero,
- * just blow it off.
- */
- if (in_le32(&awacs_rxdma->cmdptr) == 0)
- return IRQ_HANDLED;
-
- /* We also want to blow 'em off when shutting down.
- */
- if (read_sq.active == 0)
- return IRQ_HANDLED;
-
- spin_lock(&dmasound.lock);
- /* Check multiple buffers in case we were held off from
- * interrupt processing for a long time. Geeze, I really hope
- * this doesn't happen.
- */
- while ((stat=awacs_rx_cmds[read_sq.rear].xfer_status)) {
-
- /* if we got a "DEAD" status then just log it for now.
- and try to restart dma.
- TODO: figure out how best to fix it up
- */
- if (stat & DEAD){
-#ifdef DEBUG_DMASOUND
-printk("dmasound_pmac: rx-irq: DIED - attempting resurection\n");
-#endif
- /* to clear DEAD status we must first clear RUN
- set it to quiescent to be on the safe side */
- (void)in_le32(&awacs_txdma->status);
- out_le32(&awacs_txdma->control,
- (RUN|PAUSE|FLUSH|WAKE) << 16);
- awacs_rx_cmds[read_sq.rear].xfer_status = 0;
- awacs_rx_cmds[read_sq.rear].res_count = 0;
- read_sq.died++ ;
- (void)in_le32(&awacs_txdma->status);
- /* re-start the same block */
- out_le32(&awacs_rxdma->cmdptr,
- virt_to_bus(&awacs_rx_cmds[read_sq.rear]));
- /* we must re-start the controller */
- (void)in_le32(&awacs_rxdma->status);
- /* should complete clearing the DEAD status */
- out_le32(&awacs_rxdma->control,
- ((RUN|WAKE) << 16) + (RUN|WAKE));
- spin_unlock(&dmasound.lock);
- return IRQ_HANDLED; /* try this block again */
- }
- /* Clear status and move on to next buffer.
- */
- awacs_rx_cmds[read_sq.rear].xfer_status = 0;
- read_sq.rear++;
-
- /* Wrap the buffer ring.
- */
- if (read_sq.rear >= read_sq.max_active)
- read_sq.rear = 0;
-
- /* If we have caught up to the front buffer, bump it.
- * This will cause weird (but not fatal) results if the
- * read loop is currently using this buffer. The user is
- * behind in this case anyway, so weird things are going
- * to happen.
- */
- if (read_sq.rear == read_sq.front) {
- read_sq.front++;
- read_sq.xruns++ ; /* we overan */
- if (read_sq.front >= read_sq.max_active)
- read_sq.front = 0;
- }
- }
-
- WAKE_UP(read_sq.action_queue);
- spin_unlock(&dmasound.lock);
- return IRQ_HANDLED;
-}
-
-
-static irqreturn_t
-pmac_awacs_intr(int irq, void *devid)
-{
- int ctrl;
- int status;
- int r1;
-
- spin_lock(&dmasound.lock);
- ctrl = in_le32(&awacs->control);
- status = in_le32(&awacs->codec_stat);
-
- if (ctrl & MASK_PORTCHG) {
- /* tested on Screamer, should work on others too */
- if (awacs_revision == AWACS_SCREAMER) {
- if (((status & MASK_HDPCONN) >> 3) && (hdp_connected == 0)) {
- hdp_connected = 1;
-
- r1 = awacs_reg[1] | MASK_SPKMUTE;
- awacs_reg[1] = r1;
- awacs_write(r1 | MASK_ADDR_MUTE);
- } else if (((status & MASK_HDPCONN) >> 3 == 0) && (hdp_connected == 1)) {
- hdp_connected = 0;
-
- r1 = awacs_reg[1] & ~MASK_SPKMUTE;
- awacs_reg[1] = r1;
- awacs_write(r1 | MASK_ADDR_MUTE);
- }
- }
- }
- if (ctrl & MASK_CNTLERR) {
- int err = (in_le32(&awacs->codec_stat) & MASK_ERRCODE) >> 16;
- /* CHECK: we just swallow burgundy errors at the moment..*/
- if (err != 0 && awacs_revision != AWACS_BURGUNDY)
- printk(KERN_ERR "dmasound_pmac: error %x\n", err);
- }
- /* Writing 1s to the CNTLERR and PORTCHG bits clears them... */
- out_le32(&awacs->control, ctrl);
- spin_unlock(&dmasound.lock);
- return IRQ_HANDLED;
-}
-
-static void
-awacs_write(int val)
-{
- int count = 300 ;
- if (awacs_revision >= AWACS_DACA || !awacs)
- return ;
-
- while ((in_le32(&awacs->codec_ctrl) & MASK_NEWECMD) && count--)
- udelay(1) ; /* timeout is > 2 samples at lowest rate */
- out_le32(&awacs->codec_ctrl, val | (awacs_subframe << 22));
- (void)in_le32(&awacs->byteswap);
-}
-
-/* this is called when the beep timer expires... it will be called even
- if the beep has been overidden by other sound output.
-*/
-static void awacs_nosound(unsigned long xx)
-{
- unsigned long flags;
- int count = 600 ; /* > four samples at lowest rate */
-
- spin_lock_irqsave(&dmasound.lock, flags);
- if (beep_playing) {
- st_le16(&beep_dbdma_cmd->command, DBDMA_STOP);
- out_le32(&awacs_txdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16);
- while ((in_le32(&awacs_txdma->status) & RUN) && count--)
- udelay(1);
- if (awacs)
- awacs_setup_for_beep(-1);
- beep_playing = 0;
- }
- spin_unlock_irqrestore(&dmasound.lock, flags);
-}
-
-/*
- * We generate the beep with a single dbdma command that loops a buffer
- * forever - without generating interrupts.
- *
- * So, to stop it you have to stop dma output as per awacs_nosound.
- */
-static int awacs_beep_event(struct input_dev *dev, unsigned int type,
- unsigned int code, int hz)
-{
- unsigned long flags;
- int beep_speed = 0;
- int srate;
- int period, ncycles, nsamples;
- int i, j, f;
- short *p;
- static int beep_hz_cache;
- static int beep_nsamples_cache;
- static int beep_volume_cache;
-
- if (type != EV_SND)
- return -1;
- switch (code) {
- case SND_BELL:
- if (hz)
- hz = 1000;
- break;
- case SND_TONE:
- break;
- default:
- return -1;
- }
-
- if (beep_buf == NULL)
- return -1;
-
- /* quick-hack fix for DACA, Burgundy & Tumbler */
-
- if (awacs_revision >= AWACS_DACA){
- srate = 44100 ;
- } else {
- for (i = 0; i < 8 && awacs_freqs[i] >= BEEP_SRATE; ++i)
- if (awacs_freqs_ok[i])
- beep_speed = i;
- srate = awacs_freqs[beep_speed];
- }
-
- if (hz <= srate / BEEP_BUFLEN || hz > srate / 2) {
- /* cancel beep currently playing */
- awacs_nosound(0);
- return 0;
- }
-
- spin_lock_irqsave(&dmasound.lock, flags);
- if (beep_playing || write_sq.active || beep_buf == NULL) {
- spin_unlock_irqrestore(&dmasound.lock, flags);
- return -1; /* too hard, sorry :-( */
- }
- beep_playing = 1;
- st_le16(&beep_dbdma_cmd->command, OUTPUT_MORE + BR_ALWAYS);
- spin_unlock_irqrestore(&dmasound.lock, flags);
-
- if (hz == beep_hz_cache && beep_vol == beep_volume_cache) {
- nsamples = beep_nsamples_cache;
- } else {
- period = srate * 256 / hz; /* fixed point */
- ncycles = BEEP_BUFLEN * 256 / period;
- nsamples = (period * ncycles) >> 8;
- f = ncycles * 65536 / nsamples;
- j = 0;
- p = beep_buf;
- for (i = 0; i < nsamples; ++i, p += 2) {
- p[0] = p[1] = beep_wform[j >> 8] * beep_vol;
- j = (j + f) & 0xffff;
- }
- beep_hz_cache = hz;
- beep_volume_cache = beep_vol;
- beep_nsamples_cache = nsamples;
- }
-
- st_le16(&beep_dbdma_cmd->req_count, nsamples*4);
- st_le16(&beep_dbdma_cmd->xfer_status, 0);
- st_le32(&beep_dbdma_cmd->cmd_dep, virt_to_bus(beep_dbdma_cmd));
- st_le32(&beep_dbdma_cmd->phy_addr, virt_to_bus(beep_buf));
- awacs_beep_state = 1;
-
- spin_lock_irqsave(&dmasound.lock, flags);
- if (beep_playing) { /* i.e. haven't been terminated already */
- int count = 300 ;
- out_le32(&awacs_txdma->control, (RUN|WAKE|FLUSH|PAUSE) << 16);
- while ((in_le32(&awacs_txdma->status) & RUN) && count--)
- udelay(1); /* timeout > 2 samples at lowest rate*/
- if (awacs)
- awacs_setup_for_beep(beep_speed);
- out_le32(&awacs_txdma->cmdptr, virt_to_bus(beep_dbdma_cmd));
- (void)in_le32(&awacs_txdma->status);
- out_le32(&awacs_txdma->control, RUN | (RUN << 16));
- }
- spin_unlock_irqrestore(&dmasound.lock, flags);
-
- return 0;
-}
-
-/* used in init and for wake-up */
-
-static void
-load_awacs(void)
-{
- awacs_write(awacs_reg[0] + MASK_ADDR0);
- awacs_write(awacs_reg[1] + MASK_ADDR1);
- awacs_write(awacs_reg[2] + MASK_ADDR2);
- awacs_write(awacs_reg[4] + MASK_ADDR4);
-
- if (awacs_revision == AWACS_SCREAMER) {
- awacs_write(awacs_reg[5] + MASK_ADDR5);
- msleep(100);
- awacs_write(awacs_reg[6] + MASK_ADDR6);
- msleep(2);
- awacs_write(awacs_reg[1] + MASK_ADDR1);
- awacs_write(awacs_reg[7] + MASK_ADDR7);
- }
- if (awacs) {
- if (hw_can_byteswap && (dmasound.hard.format == AFMT_S16_LE))
- out_le32(&awacs->byteswap, BS_VAL);
- else
- out_le32(&awacs->byteswap, 0);
- }
-}
-
-#ifdef CONFIG_PM
-/*
- * Save state when going to sleep, restore it afterwards.
- */
-/* FIXME: sort out disabling/re-enabling of read stuff as well */
-static void awacs_sleep_notify(struct pmu_sleep_notifier *self, int when)
-{
- unsigned long flags;
-
- switch (when) {
- case PBOOK_SLEEP_NOW:
- LOCK();
- awacs_sleeping = 1;
- /* Tell the rest of the driver we are now going to sleep */
- mb();
- if (awacs_revision == AWACS_SCREAMER ||
- awacs_revision == AWACS_AWACS) {
- awacs_reg1_save = awacs_reg[1];
- awacs_reg[1] |= MASK_AMUTE | MASK_CMUTE;
- awacs_write(MASK_ADDR1 | awacs_reg[1]);
- }
-
- PMacSilence();
- /* stop rx - if going - a bit of a daft user... but */
- out_le32(&awacs_rxdma->control, (RUN|WAKE|FLUSH << 16));
- /* deny interrupts */
- if (awacs)
- disable_irq(awacs_irq);
- disable_irq(awacs_tx_irq);
- disable_irq(awacs_rx_irq);
- /* Chip specific sleep code */
- switch (awacs_revision) {
- case AWACS_TUMBLER:
- case AWACS_SNAPPER:
- write_audio_gpio(gpio_headphone_mute, gpio_headphone_mute_pol);
- write_audio_gpio(gpio_amp_mute, gpio_amp_mute_pol);
- tas_enter_sleep();
- write_audio_gpio(gpio_audio_reset, gpio_audio_reset_pol);
- break ;
- case AWACS_DACA:
- daca_enter_sleep();
- break ;
- case AWACS_BURGUNDY:
- break ;
- case AWACS_SCREAMER:
- case AWACS_AWACS:
- default:
- out_le32(&awacs->control, 0x11) ;
- break ;
- }
- /* Disable sound clock */
- pmac_call_feature(PMAC_FTR_SOUND_CHIP_ENABLE, awacs_node, 0, 0);
- /* According to Darwin, we do that after turning off the sound
- * chip clock. All this will have to be cleaned up once we properly
- * parse the OF sound-objects
- */
- if ((machine_is_compatible("PowerBook3,1") ||
- machine_is_compatible("PowerBook3,2")) && awacs) {
- awacs_reg[1] |= MASK_PAROUT0 | MASK_PAROUT1;
- awacs_write(MASK_ADDR1 | awacs_reg[1]);
- msleep(200);
- }
- break;
- case PBOOK_WAKE:
- /* Enable sound clock */
- pmac_call_feature(PMAC_FTR_SOUND_CHIP_ENABLE, awacs_node, 0, 1);
- if ((machine_is_compatible("PowerBook3,1") ||
- machine_is_compatible("PowerBook3,2")) && awacs) {
- msleep(100);
- awacs_reg[1] &= ~(MASK_PAROUT0 | MASK_PAROUT1);
- awacs_write(MASK_ADDR1 | awacs_reg[1]);
- msleep(300);
- } else
- msleep(1000);
- /* restore settings */
- switch (awacs_revision) {
- case AWACS_TUMBLER:
- case AWACS_SNAPPER:
- write_audio_gpio(gpio_headphone_mute, gpio_headphone_mute_pol);
- write_audio_gpio(gpio_amp_mute, gpio_amp_mute_pol);
- write_audio_gpio(gpio_audio_reset, gpio_audio_reset_pol);
- msleep(100);
- write_audio_gpio(gpio_audio_reset, !gpio_audio_reset_pol);
- msleep(150);
- tas_leave_sleep(); /* Stub for now */
- headphone_intr(0, NULL);
- break;
- case AWACS_DACA:
- msleep(10); /* Check this !!! */
- daca_leave_sleep();
- break ; /* dont know how yet */
- case AWACS_BURGUNDY:
- break ;
- case AWACS_SCREAMER:
- case AWACS_AWACS:
- default:
- load_awacs() ;
- break ;
- }
- /* Recalibrate chip */
- if (awacs_revision == AWACS_SCREAMER && awacs)
- awacs_recalibrate();
- /* Make sure dma is stopped */
- PMacSilence();
- if (awacs)
- enable_irq(awacs_irq);
- enable_irq(awacs_tx_irq);
- enable_irq(awacs_rx_irq);
- if (awacs) {
- /* OK, allow ints back again */
- out_le32(&awacs->control, MASK_IEPC
- | (awacs_rate_index << 8) | 0x11
- | (awacs_revision < AWACS_DACA ? MASK_IEE: 0));
- }
- if (macio_base && is_pbook_g3) {
- /* FIXME: should restore the setup we had...*/
- out_8(macio_base + 0x37, 3);
- } else if (is_pbook_3X00) {
- in_8(latch_base + 0x190);
- }
- /* Remove mute */
- if (awacs_revision == AWACS_SCREAMER ||
- awacs_revision == AWACS_AWACS) {
- awacs_reg[1] = awacs_reg1_save;
- awacs_write(MASK_ADDR1 | awacs_reg[1]);
- }
- awacs_sleeping = 0;
- /* Resume pending sounds. */
- /* we don't try to restart input... */
- spin_lock_irqsave(&dmasound.lock, flags);
- __PMacPlay();
- spin_unlock_irqrestore(&dmasound.lock, flags);
- UNLOCK();
- }
-}
-#endif /* CONFIG_PM */
-
-
-/* All the burgundy functions: */
-
-/* Waits for busy flag to clear */
-static inline void
-awacs_burgundy_busy_wait(void)
-{
- int count = 50; /* > 2 samples at 44k1 */
- while ((in_le32(&awacs->codec_ctrl) & MASK_NEWECMD) && count--)
- udelay(1) ;
-}
-
-static inline void
-awacs_burgundy_extend_wait(void)
-{
- int count = 50 ; /* > 2 samples at 44k1 */
- while ((!(in_le32(&awacs->codec_stat) & MASK_EXTEND)) && count--)
- udelay(1) ;
- count = 50;
- while ((in_le32(&awacs->codec_stat) & MASK_EXTEND) && count--)
- udelay(1);
-}
-
-static void
-awacs_burgundy_wcw(unsigned addr, unsigned val)
-{
- out_le32(&awacs->codec_ctrl, addr + 0x200c00 + (val & 0xff));
- awacs_burgundy_busy_wait();
- out_le32(&awacs->codec_ctrl, addr + 0x200d00 +((val>>8) & 0xff));
- awacs_burgundy_busy_wait();
- out_le32(&awacs->codec_ctrl, addr + 0x200e00 +((val>>16) & 0xff));
- awacs_burgundy_busy_wait();
- out_le32(&awacs->codec_ctrl, addr + 0x200f00 +((val>>24) & 0xff));
- awacs_burgundy_busy_wait();
-}
-
-static unsigned
-awacs_burgundy_rcw(unsigned addr)
-{
- unsigned val = 0;
- unsigned long flags;
-
- /* should have timeouts here */
- spin_lock_irqsave(&dmasound.lock, flags);
-
- out_le32(&awacs->codec_ctrl, addr + 0x100000);
- awacs_burgundy_busy_wait();
- awacs_burgundy_extend_wait();
- val += (in_le32(&awacs->codec_stat) >> 4) & 0xff;
-
- out_le32(&awacs->codec_ctrl, addr + 0x100100);
- awacs_burgundy_busy_wait();
- awacs_burgundy_extend_wait();
- val += ((in_le32(&awacs->codec_stat)>>4) & 0xff) <<8;
-
- out_le32(&awacs->codec_ctrl, addr + 0x100200);
- awacs_burgundy_busy_wait();
- awacs_burgundy_extend_wait();
- val += ((in_le32(&awacs->codec_stat)>>4) & 0xff) <<16;
-
- out_le32(&awacs->codec_ctrl, addr + 0x100300);
- awacs_burgundy_busy_wait();
- awacs_burgundy_extend_wait();
- val += ((in_le32(&awacs->codec_stat)>>4) & 0xff) <<24;
-
- spin_unlock_irqrestore(&dmasound.lock, flags);
-
- return val;
-}
-
-
-static void
-awacs_burgundy_wcb(unsigned addr, unsigned val)
-{
- out_le32(&awacs->codec_ctrl, addr + 0x300000 + (val & 0xff));
- awacs_burgundy_busy_wait();
-}
-
-static unsigned
-awacs_burgundy_rcb(unsigned addr)
-{
- unsigned val = 0;
- unsigned long flags;
-
- /* should have timeouts here */
- spin_lock_irqsave(&dmasound.lock, flags);
-
- out_le32(&awacs->codec_ctrl, addr + 0x100000);
- awacs_burgundy_busy_wait();
- awacs_burgundy_extend_wait();
- val += (in_le32(&awacs->codec_stat) >> 4) & 0xff;
-
- spin_unlock_irqrestore(&dmasound.lock, flags);
-
- return val;
-}
-
-static int
-awacs_burgundy_check(void)
-{
- /* Checks to see the chip is alive and kicking */
- int error = in_le32(&awacs->codec_ctrl) & MASK_ERRCODE;
-
- return error == 0xf0000;
-}
-
-static int
-awacs_burgundy_init(void)
-{
- if (awacs_burgundy_check()) {
- printk(KERN_WARNING "dmasound_pmac: burgundy not working :-(\n");
- return 1;
- }
-
- awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_OUTPUTENABLES,
- DEF_BURGUNDY_OUTPUTENABLES);
- awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
- DEF_BURGUNDY_MORE_OUTPUTENABLES);
- awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_OUTPUTSELECTS,
- DEF_BURGUNDY_OUTPUTSELECTS);
-
- awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_INPSEL21,
- DEF_BURGUNDY_INPSEL21);
- awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_INPSEL3,
- DEF_BURGUNDY_INPSEL3);
- awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_GAINCD,
- DEF_BURGUNDY_GAINCD);
- awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_GAINLINE,
- DEF_BURGUNDY_GAINLINE);
- awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_GAINMIC,
- DEF_BURGUNDY_GAINMIC);
- awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_GAINMODEM,
- DEF_BURGUNDY_GAINMODEM);
-
- awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_ATTENSPEAKER,
- DEF_BURGUNDY_ATTENSPEAKER);
- awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_ATTENLINEOUT,
- DEF_BURGUNDY_ATTENLINEOUT);
- awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_ATTENHP,
- DEF_BURGUNDY_ATTENHP);
-
- awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_MASTER_VOLUME,
- DEF_BURGUNDY_MASTER_VOLUME);
- awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_VOLCD,
- DEF_BURGUNDY_VOLCD);
- awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_VOLLINE,
- DEF_BURGUNDY_VOLLINE);
- awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_VOLMIC,
- DEF_BURGUNDY_VOLMIC);
- return 0;
-}
-
-static void
-awacs_burgundy_write_volume(unsigned address, int volume)
-{
- int hardvolume,lvolume,rvolume;
-
- lvolume = (volume & 0xff) ? (volume & 0xff) + 155 : 0;
- rvolume = ((volume >>8)&0xff) ? ((volume >> 8)&0xff ) + 155 : 0;
-
- hardvolume = lvolume + (rvolume << 16);
-
- awacs_burgundy_wcw(address, hardvolume);
-}
-
-static int
-awacs_burgundy_read_volume(unsigned address)
-{
- int softvolume,wvolume;
-
- wvolume = awacs_burgundy_rcw(address);
-
- softvolume = (wvolume & 0xff) - 155;
- softvolume += (((wvolume >> 16) & 0xff) - 155)<<8;
-
- return softvolume > 0 ? softvolume : 0;
-}
-
-static int
-awacs_burgundy_read_mvolume(unsigned address)
-{
- int lvolume,rvolume,wvolume;
-
- wvolume = awacs_burgundy_rcw(address);
-
- wvolume &= 0xffff;
-
- rvolume = (wvolume & 0xff) - 155;
- lvolume = ((wvolume & 0xff00)>>8) - 155;
-
- return lvolume + (rvolume << 8);
-}
-
-static void
-awacs_burgundy_write_mvolume(unsigned address, int volume)
-{
- int lvolume,rvolume,hardvolume;
-
- lvolume = (volume &0xff) ? (volume & 0xff) + 155 :0;
- rvolume = ((volume >>8) & 0xff) ? (volume >> 8) + 155 :0;
-
- hardvolume = lvolume + (rvolume << 8);
- hardvolume += (hardvolume << 16);
-
- awacs_burgundy_wcw(address, hardvolume);
-}
-
-/* End burgundy functions */
-
-/* Set up output volumes on machines with the 'perch/whisper' extension card.
- * this has an SGS i2c chip (7433) which is accessed using the cuda.
- *
- * TODO: split this out and make use of the other parts of the SGS chip to
- * do Bass, Treble etc.
- */
-
-static void
-awacs_enable_amp(int spkr_vol)
-{
-#ifdef CONFIG_ADB_CUDA
- struct adb_request req;
-
- if (sys_ctrler != SYS_CTRLER_CUDA)
- return;
-
- /* turn on headphones */
- cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC,
- 0x8a, 4, 0);
- while (!req.complete) cuda_poll();
- cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC,
- 0x8a, 6, 0);
- while (!req.complete) cuda_poll();
-
- /* turn on speaker */
- cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC,
- 0x8a, 3, (100 - (spkr_vol & 0xff)) * 32 / 100);
- while (!req.complete) cuda_poll();
- cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC,
- 0x8a, 5, (100 - ((spkr_vol >> 8) & 0xff)) * 32 / 100);
- while (!req.complete) cuda_poll();
-
- cuda_request(&req, NULL, 5, CUDA_PACKET,
- CUDA_GET_SET_IIC, 0x8a, 1, 0x29);
- while (!req.complete) cuda_poll();
-#endif /* CONFIG_ADB_CUDA */
-}
-
-
-/*** Mid level stuff *********************************************************/
-
-
-/*
- * /dev/mixer abstraction
- */
-
-static void do_line_lev(int data)
-{
- line_lev = data ;
- awacs_reg[0] &= ~MASK_MUX_AUDIN;
- if ((data & 0xff) >= 50)
- awacs_reg[0] |= MASK_MUX_AUDIN;
- awacs_write(MASK_ADDR0 | awacs_reg[0]);
-}
-
-static void do_ip_gain(int data)
-{
- ip_gain = data ;
- data &= 0xff;
- awacs_reg[0] &= ~MASK_GAINLINE;
- if (awacs_revision == AWACS_SCREAMER) {
- awacs_reg[6] &= ~MASK_MIC_BOOST ;
- if (data >= 33) {
- awacs_reg[0] |= MASK_GAINLINE;
- if( data >= 66)
- awacs_reg[6] |= MASK_MIC_BOOST ;
- }
- awacs_write(MASK_ADDR6 | awacs_reg[6]) ;
- } else {
- if (data >= 50)
- awacs_reg[0] |= MASK_GAINLINE;
- }
- awacs_write(MASK_ADDR0 | awacs_reg[0]);
-}
-
-static void do_mic_lev(int data)
-{
- mic_lev = data ;
- data &= 0xff;
- awacs_reg[0] &= ~MASK_MUX_MIC;
- if (data >= 50)
- awacs_reg[0] |= MASK_MUX_MIC;
- awacs_write(MASK_ADDR0 | awacs_reg[0]);
-}
-
-static void do_cd_lev(int data)
-{
- cd_lev = data ;
- awacs_reg[0] &= ~MASK_MUX_CD;
- if ((data & 0xff) >= 50)
- awacs_reg[0] |= MASK_MUX_CD;
- awacs_write(MASK_ADDR0 | awacs_reg[0]);
-}
-
-static void do_rec_lev(int data)
-{
- int left, right ;
- rec_lev = data ;
- /* need to fudge this to use the volume setter routine */
- left = 100 - (data & 0xff) ; if( left < 0 ) left = 0 ;
- right = 100 - ((data >> 8) & 0xff) ; if( right < 0 ) right = 0 ;
- left |= (right << 8 );
- left = awacs_volume_setter(left, 0, 0, 4);
-}
-
-static void do_passthru_vol(int data)
-{
- passthru_vol = data ;
- awacs_reg[1] &= ~MASK_LOOPTHRU;
- if (awacs_revision == AWACS_SCREAMER) {
- if( data ) { /* switch it on for non-zero */
- awacs_reg[1] |= MASK_LOOPTHRU;
- awacs_write(MASK_ADDR1 | awacs_reg[1]);
- }
- data = awacs_volume_setter(data, 5, 0, 6) ;
- } else {
- if ((data & 0xff) >= 50)
- awacs_reg[1] |= MASK_LOOPTHRU;
- awacs_write(MASK_ADDR1 | awacs_reg[1]);
- data = (awacs_reg[1] & MASK_LOOPTHRU)? 100: 0;
- }
-}
-
-static int awacs_mixer_ioctl(u_int cmd, u_long arg)
-{
- int data;
- int rc;
-
- switch (cmd) {
- case SOUND_MIXER_READ_CAPS:
- /* say we will allow multiple inputs? prob. wrong
- so I'm switching it to single */
- return IOCTL_OUT(arg, 1);
- case SOUND_MIXER_READ_DEVMASK:
- data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER
- | SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD
- | SOUND_MASK_IGAIN | SOUND_MASK_RECLEV
- | SOUND_MASK_ALTPCM
- | SOUND_MASK_MONITOR;
- rc = IOCTL_OUT(arg, data);
- break;
- case SOUND_MIXER_READ_RECMASK:
- data = SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD;
- rc = IOCTL_OUT(arg, data);
- break;
- case SOUND_MIXER_READ_RECSRC:
- data = 0;
- if (awacs_reg[0] & MASK_MUX_AUDIN)
- data |= SOUND_MASK_LINE;
- if (awacs_reg[0] & MASK_MUX_MIC)
- data |= SOUND_MASK_MIC;
- if (awacs_reg[0] & MASK_MUX_CD)
- data |= SOUND_MASK_CD;
- rc = IOCTL_OUT(arg, data);
- break;
- case SOUND_MIXER_WRITE_RECSRC:
- IOCTL_IN(arg, data);
- data &= (SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD);
- awacs_reg[0] &= ~(MASK_MUX_CD | MASK_MUX_MIC
- | MASK_MUX_AUDIN);
- if (data & SOUND_MASK_LINE)
- awacs_reg[0] |= MASK_MUX_AUDIN;
- if (data & SOUND_MASK_MIC)
- awacs_reg[0] |= MASK_MUX_MIC;
- if (data & SOUND_MASK_CD)
- awacs_reg[0] |= MASK_MUX_CD;
- awacs_write(awacs_reg[0] | MASK_ADDR0);
- rc = IOCTL_OUT(arg, data);
- break;
- case SOUND_MIXER_READ_STEREODEVS:
- data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER| SOUND_MASK_RECLEV ;
- if (awacs_revision == AWACS_SCREAMER)
- data |= SOUND_MASK_MONITOR ;
- rc = IOCTL_OUT(arg, data);
- break;
- case SOUND_MIXER_WRITE_VOLUME:
- IOCTL_IN(arg, data);
- line_vol = data ;
- awacs_volume_setter(data, 2, 0, 6);
- /* fall through */
- case SOUND_MIXER_READ_VOLUME:
- rc = IOCTL_OUT(arg, line_vol);
- break;
- case SOUND_MIXER_WRITE_SPEAKER:
- IOCTL_IN(arg, data);
- spk_vol = data ;
- if (has_perch)
- awacs_enable_amp(data);
- else
- (void)awacs_volume_setter(data, 4, MASK_CMUTE, 6);
- /* fall though */
- case SOUND_MIXER_READ_SPEAKER:
- rc = IOCTL_OUT(arg, spk_vol);
- break;
- case SOUND_MIXER_WRITE_ALTPCM: /* really bell volume */
- IOCTL_IN(arg, data);
- beep_vol = data & 0xff;
- /* fall through */
- case SOUND_MIXER_READ_ALTPCM:
- rc = IOCTL_OUT(arg, beep_vol);
- break;
- case SOUND_MIXER_WRITE_LINE:
- IOCTL_IN(arg, data);
- do_line_lev(data) ;
- /* fall through */
- case SOUND_MIXER_READ_LINE:
- rc = IOCTL_OUT(arg, line_lev);
- break;
- case SOUND_MIXER_WRITE_IGAIN:
- IOCTL_IN(arg, data);
- do_ip_gain(data) ;
- /* fall through */
- case SOUND_MIXER_READ_IGAIN:
- rc = IOCTL_OUT(arg, ip_gain);
- break;
- case SOUND_MIXER_WRITE_MIC:
- IOCTL_IN(arg, data);
- do_mic_lev(data);
- /* fall through */
- case SOUND_MIXER_READ_MIC:
- rc = IOCTL_OUT(arg, mic_lev);
- break;
- case SOUND_MIXER_WRITE_CD:
- IOCTL_IN(arg, data);
- do_cd_lev(data);
- /* fall through */
- case SOUND_MIXER_READ_CD:
- rc = IOCTL_OUT(arg, cd_lev);
- break;
- case SOUND_MIXER_WRITE_RECLEV:
- IOCTL_IN(arg, data);
- do_rec_lev(data) ;
- /* fall through */
- case SOUND_MIXER_READ_RECLEV:
- rc = IOCTL_OUT(arg, rec_lev);
- break;
- case MIXER_WRITE(SOUND_MIXER_MONITOR):
- IOCTL_IN(arg, data);
- do_passthru_vol(data) ;
- /* fall through */
- case MIXER_READ(SOUND_MIXER_MONITOR):
- rc = IOCTL_OUT(arg, passthru_vol);
- break;
- default:
- rc = -EINVAL;
- }
-
- return rc;
-}
-
-static void awacs_mixer_init(void)
-{
- awacs_volume_setter(line_vol, 2, 0, 6);
- if (has_perch)
- awacs_enable_amp(spk_vol);
- else
- (void)awacs_volume_setter(spk_vol, 4, MASK_CMUTE, 6);
- do_line_lev(line_lev) ;
- do_ip_gain(ip_gain) ;
- do_mic_lev(mic_lev) ;
- do_cd_lev(cd_lev) ;
- do_rec_lev(rec_lev) ;
- do_passthru_vol(passthru_vol) ;
-}
-
-static int burgundy_mixer_ioctl(u_int cmd, u_long arg)
-{
- int data;
- int rc;
-
- /* We are, we are, we are... Burgundy or better */
- switch(cmd) {
- case SOUND_MIXER_READ_DEVMASK:
- data = SOUND_MASK_VOLUME | SOUND_MASK_CD |
- SOUND_MASK_LINE | SOUND_MASK_MIC |
- SOUND_MASK_SPEAKER | SOUND_MASK_ALTPCM;
- rc = IOCTL_OUT(arg, data);
- break;
- case SOUND_MIXER_READ_RECMASK:
- data = SOUND_MASK_LINE | SOUND_MASK_MIC
- | SOUND_MASK_CD;
- rc = IOCTL_OUT(arg, data);
- break;
- case SOUND_MIXER_READ_RECSRC:
- data = 0;
- if (awacs_reg[0] & MASK_MUX_AUDIN)
- data |= SOUND_MASK_LINE;
- if (awacs_reg[0] & MASK_MUX_MIC)
- data |= SOUND_MASK_MIC;
- if (awacs_reg[0] & MASK_MUX_CD)
- data |= SOUND_MASK_CD;
- rc = IOCTL_OUT(arg, data);
- break;
- case SOUND_MIXER_WRITE_RECSRC:
- IOCTL_IN(arg, data);
- data &= (SOUND_MASK_LINE
- | SOUND_MASK_MIC | SOUND_MASK_CD);
- awacs_reg[0] &= ~(MASK_MUX_CD | MASK_MUX_MIC
- | MASK_MUX_AUDIN);
- if (data & SOUND_MASK_LINE)
- awacs_reg[0] |= MASK_MUX_AUDIN;
- if (data & SOUND_MASK_MIC)
- awacs_reg[0] |= MASK_MUX_MIC;
- if (data & SOUND_MASK_CD)
- awacs_reg[0] |= MASK_MUX_CD;
- awacs_write(awacs_reg[0] | MASK_ADDR0);
- rc = IOCTL_OUT(arg, data);
- break;
- case SOUND_MIXER_READ_STEREODEVS:
- data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER
- | SOUND_MASK_RECLEV | SOUND_MASK_CD
- | SOUND_MASK_LINE;
- rc = IOCTL_OUT(arg, data);
- break;
- case SOUND_MIXER_READ_CAPS:
- rc = IOCTL_OUT(arg, 0);
- break;
- case SOUND_MIXER_WRITE_VOLUME:
- IOCTL_IN(arg, data);
- awacs_burgundy_write_mvolume(MASK_ADDR_BURGUNDY_MASTER_VOLUME, data);
- /* Fall through */
- case SOUND_MIXER_READ_VOLUME:
- rc = IOCTL_OUT(arg, awacs_burgundy_read_mvolume(MASK_ADDR_BURGUNDY_MASTER_VOLUME));
- break;
- case SOUND_MIXER_WRITE_SPEAKER:
- IOCTL_IN(arg, data);
- if (!(data & 0xff)) {
- /* Mute the left speaker */
- awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
- awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) & ~0x2);
- } else {
- /* Unmute the left speaker */
- awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
- awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) | 0x2);
- }
- if (!(data & 0xff00)) {
- /* Mute the right speaker */
- awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
- awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) & ~0x4);
- } else {
- /* Unmute the right speaker */
- awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
- awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) | 0x4);
- }
-
- data = (((data&0xff)*16)/100 > 0xf ? 0xf :
- (((data&0xff)*16)/100)) +
- ((((data>>8)*16)/100 > 0xf ? 0xf :
- ((((data>>8)*16)/100)))<<4);
-
- awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_ATTENSPEAKER, ~data);
- /* Fall through */
- case SOUND_MIXER_READ_SPEAKER:
- data = awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_ATTENSPEAKER);
- data = (((data & 0xf)*100)/16) + ((((data>>4)*100)/16)<<8);
- rc = IOCTL_OUT(arg, (~data) & 0x0000ffff);
- break;
- case SOUND_MIXER_WRITE_ALTPCM: /* really bell volume */
- IOCTL_IN(arg, data);
- beep_vol = data & 0xff;
- /* fall through */
- case SOUND_MIXER_READ_ALTPCM:
- rc = IOCTL_OUT(arg, beep_vol);
- break;
- case SOUND_MIXER_WRITE_LINE:
- IOCTL_IN(arg, data);
- awacs_burgundy_write_volume(MASK_ADDR_BURGUNDY_VOLLINE, data);
-
- /* fall through */
- case SOUND_MIXER_READ_LINE:
- data = awacs_burgundy_read_volume(MASK_ADDR_BURGUNDY_VOLLINE);
- rc = IOCTL_OUT(arg, data);
- break;
- case SOUND_MIXER_WRITE_MIC:
- IOCTL_IN(arg, data);
- /* Mic is mono device */
- data = (data << 8) + (data << 24);
- awacs_burgundy_write_volume(MASK_ADDR_BURGUNDY_VOLMIC, data);
- /* fall through */
- case SOUND_MIXER_READ_MIC:
- data = awacs_burgundy_read_volume(MASK_ADDR_BURGUNDY_VOLMIC);
- data <<= 24;
- rc = IOCTL_OUT(arg, data);
- break;
- case SOUND_MIXER_WRITE_CD:
- IOCTL_IN(arg, data);
- awacs_burgundy_write_volume(MASK_ADDR_BURGUNDY_VOLCD, data);
- /* fall through */
- case SOUND_MIXER_READ_CD:
- data = awacs_burgundy_read_volume(MASK_ADDR_BURGUNDY_VOLCD);
- rc = IOCTL_OUT(arg, data);
- break;
- case SOUND_MIXER_WRITE_RECLEV:
- IOCTL_IN(arg, data);
- data = awacs_volume_setter(data, 0, 0, 4);
- rc = IOCTL_OUT(arg, data);
- break;
- case SOUND_MIXER_READ_RECLEV:
- data = awacs_get_volume(awacs_reg[0], 4);
- rc = IOCTL_OUT(arg, data);
- break;
- case SOUND_MIXER_OUTMASK:
- case SOUND_MIXER_OUTSRC:
- default:
- rc = -EINVAL;
- }
-
- return rc;
-}
-
-static int daca_mixer_ioctl(u_int cmd, u_long arg)
-{
- int data;
- int rc;
-
- /* And the DACA's no genius either! */
-
- switch(cmd) {
- case SOUND_MIXER_READ_DEVMASK:
- data = SOUND_MASK_VOLUME;
- rc = IOCTL_OUT(arg, data);
- break;
- case SOUND_MIXER_READ_RECMASK:
- data = 0;
- rc = IOCTL_OUT(arg, data);
- break;
- case SOUND_MIXER_READ_RECSRC:
- data = 0;
- rc = IOCTL_OUT(arg, data);
- break;
- case SOUND_MIXER_WRITE_RECSRC:
- IOCTL_IN(arg, data);
- data =0;
- rc = IOCTL_OUT(arg, data);
- break;
- case SOUND_MIXER_READ_STEREODEVS:
- data = SOUND_MASK_VOLUME;
- rc = IOCTL_OUT(arg, data);
- break;
- case SOUND_MIXER_READ_CAPS:
- rc = IOCTL_OUT(arg, 0);
- break;
- case SOUND_MIXER_WRITE_VOLUME:
- IOCTL_IN(arg, data);
- daca_set_volume(data, data);
- /* Fall through */
- case SOUND_MIXER_READ_VOLUME:
- daca_get_volume(& data, &data);
- rc = IOCTL_OUT(arg, data);
- break;
- case SOUND_MIXER_OUTMASK:
- case SOUND_MIXER_OUTSRC:
- default:
- rc = -EINVAL;
- }
- return rc;
-}
-
-static int PMacMixerIoctl(u_int cmd, u_long arg)
-{
- int rc;
-
- /* Different IOCTLS for burgundy and, eventually, DACA & Tumbler */
-
- TRY_LOCK();
-
- switch (awacs_revision){
- case AWACS_BURGUNDY:
- rc = burgundy_mixer_ioctl(cmd, arg);
- break ;
- case AWACS_DACA:
- rc = daca_mixer_ioctl(cmd, arg);
- break;
- case AWACS_TUMBLER:
- case AWACS_SNAPPER:
- rc = tas_mixer_ioctl(cmd, arg);
- break ;
- default: /* ;-)) */
- rc = awacs_mixer_ioctl(cmd, arg);
- }
-
- UNLOCK();
-
- return rc;
-}
-
-static void PMacMixerInit(void)
-{
- switch (awacs_revision) {
- case AWACS_TUMBLER:
- printk("AE-Init tumbler mixer\n");
- break ;
- case AWACS_SNAPPER:
- printk("AE-Init snapper mixer\n");
- break ;
- case AWACS_DACA:
- case AWACS_BURGUNDY:
- break ; /* don't know yet */
- case AWACS_AWACS:
- case AWACS_SCREAMER:
- default:
- awacs_mixer_init() ;
- break ;
- }
-}
-
-/* Write/Read sq setup functions:
- Check to see if we have enough (or any) dbdma cmd buffers for the
- user's fragment settings. If not, allocate some. If this fails we will
- point at the beep buffer - as an emergency provision - to stop dma tromping
- on some random bit of memory (if someone lets it go anyway).
- The command buffers are then set up to point to the fragment buffers
- (allocated elsewhere). We need n+1 commands the last of which holds
- a NOP + loop to start.
-*/
-
-static int PMacWriteSqSetup(void)
-{
- int i, count = 600 ;
- volatile struct dbdma_cmd *cp;
-
- LOCK();
-
- /* stop the controller from doing any output - if it isn't already.
- it _should_ be before this is called anyway */
-
- out_le32(&awacs_txdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16);
- while ((in_le32(&awacs_txdma->status) & RUN) && count--)
- udelay(1);
-#ifdef DEBUG_DMASOUND
-if (count <= 0)
- printk("dmasound_pmac: write sq setup: timeout waiting for dma to stop\n");
-#endif
-
- if ((write_sq.max_count + 1) > number_of_tx_cmd_buffers) {
- kfree(awacs_tx_cmd_space);
- number_of_tx_cmd_buffers = 0;
-
- /* we need nbufs + 1 (for the loop) and we should request + 1
- again because the DBDMA_ALIGN might pull the start up by up
- to sizeof(struct dbdma_cmd) - 4.
- */
-
- awacs_tx_cmd_space = kmalloc
- ((write_sq.max_count + 1 + 1) * sizeof(struct dbdma_cmd),
- GFP_KERNEL);
- if (awacs_tx_cmd_space == NULL) {
- /* don't leave it dangling - nasty but better than a
- random address */
- out_le32(&awacs_txdma->cmdptr, virt_to_bus(beep_dbdma_cmd));
- printk(KERN_ERR
- "dmasound_pmac: can't allocate dbdma cmd buffers"
- ", driver disabled\n");
- UNLOCK();
- return -ENOMEM;
- }
- awacs_tx_cmds = (volatile struct dbdma_cmd *)
- DBDMA_ALIGN(awacs_tx_cmd_space);
- number_of_tx_cmd_buffers = write_sq.max_count + 1;
- }
-
- cp = awacs_tx_cmds;
- memset((void *)cp, 0, (write_sq.max_count+1) * sizeof(struct dbdma_cmd));
- for (i = 0; i < write_sq.max_count; ++i, ++cp) {
- st_le32(&cp->phy_addr, virt_to_bus(write_sq.buffers[i]));
- }
- st_le16(&cp->command, DBDMA_NOP + BR_ALWAYS);
- st_le32(&cp->cmd_dep, virt_to_bus(awacs_tx_cmds));
- /* point the controller at the command stack - ready to go */
- out_le32(&awacs_txdma->cmdptr, virt_to_bus(awacs_tx_cmds));
- UNLOCK();
- return 0;
-}
-
-static int PMacReadSqSetup(void)
-{
- int i, count = 600;
- volatile struct dbdma_cmd *cp;
-
- LOCK();
-
- /* stop the controller from doing any input - if it isn't already.
- it _should_ be before this is called anyway */
-
- out_le32(&awacs_rxdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16);
- while ((in_le32(&awacs_rxdma->status) & RUN) && count--)
- udelay(1);
-#ifdef DEBUG_DMASOUND
-if (count <= 0)
- printk("dmasound_pmac: read sq setup: timeout waiting for dma to stop\n");
-#endif
-
- if ((read_sq.max_count+1) > number_of_rx_cmd_buffers ) {
- kfree(awacs_rx_cmd_space);
- number_of_rx_cmd_buffers = 0;
-
- /* we need nbufs + 1 (for the loop) and we should request + 1 again
- because the DBDMA_ALIGN might pull the start up by up to
- sizeof(struct dbdma_cmd) - 4 (assuming kmalloc aligns 32 bits).
- */
-
- awacs_rx_cmd_space = kmalloc
- ((read_sq.max_count + 1 + 1) * sizeof(struct dbdma_cmd),
- GFP_KERNEL);
- if (awacs_rx_cmd_space == NULL) {
- /* don't leave it dangling - nasty but better than a
- random address */
- out_le32(&awacs_rxdma->cmdptr, virt_to_bus(beep_dbdma_cmd));
- printk(KERN_ERR
- "dmasound_pmac: can't allocate dbdma cmd buffers"
- ", driver disabled\n");
- UNLOCK();
- return -ENOMEM;
- }
- awacs_rx_cmds = (volatile struct dbdma_cmd *)
- DBDMA_ALIGN(awacs_rx_cmd_space);
- number_of_rx_cmd_buffers = read_sq.max_count + 1 ;
- }
- cp = awacs_rx_cmds;
- memset((void *)cp, 0, (read_sq.max_count+1) * sizeof(struct dbdma_cmd));
-
- /* Set dma buffers up in a loop */
- for (i = 0; i < read_sq.max_count; i++,cp++) {
- st_le32(&cp->phy_addr, virt_to_bus(read_sq.buffers[i]));
- st_le16(&cp->command, INPUT_MORE + INTR_ALWAYS);
- st_le16(&cp->req_count, read_sq.block_size);
- st_le16(&cp->xfer_status, 0);
- }
-
- /* The next two lines make the thing loop around.
- */
- st_le16(&cp->command, DBDMA_NOP + BR_ALWAYS);
- st_le32(&cp->cmd_dep, virt_to_bus(awacs_rx_cmds));
- /* point the controller at the command stack - ready to go */
- out_le32(&awacs_rxdma->cmdptr, virt_to_bus(awacs_rx_cmds));
-
- UNLOCK();
- return 0;
-}
-
-/* TODO: this needs work to guarantee that when it returns DMA has stopped
- but in a more elegant way than is done here....
-*/
-
-static void PMacAbortRead(void)
-{
- int i;
- volatile struct dbdma_cmd *cp;
-
- LOCK();
- /* give it a chance to update the output and provide the IRQ
- that is expected.
- */
-
- out_le32(&awacs_rxdma->control, ((FLUSH) << 16) + FLUSH );
-
- cp = awacs_rx_cmds;
- for (i = 0; i < read_sq.max_count; i++,cp++)
- st_le16(&cp->command, DBDMA_STOP);
- /*
- * We should probably wait for the thing to stop before we
- * release the memory.
- */
-
- msleep(100) ; /* give it a (small) chance to act */
-
- /* apply the sledgehammer approach - just stop it now */
-
- out_le32(&awacs_rxdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16);
- UNLOCK();
-}
-
-extern char *get_afmt_string(int);
-static int PMacStateInfo(char *b, size_t sp)
-{
- int i, len = 0;
- len = sprintf(b,"HW rates: ");
- switch (awacs_revision){
- case AWACS_DACA:
- case AWACS_BURGUNDY:
- len += sprintf(b,"44100 ") ;
- break ;
- case AWACS_TUMBLER:
- case AWACS_SNAPPER:
- for (i=0; i<1; i++){
- if (tas_freqs_ok[i])
- len += sprintf(b+len,"%d ", tas_freqs[i]) ;
- }
- break ;
- case AWACS_AWACS:
- case AWACS_SCREAMER:
- default:
- for (i=0; i<8; i++){
- if (awacs_freqs_ok[i])
- len += sprintf(b+len,"%d ", awacs_freqs[i]) ;
- }
- break ;
- }
- len += sprintf(b+len,"s/sec\n") ;
- if (len < sp) {
- len += sprintf(b+len,"HW AFMTS: ");
- i = AFMT_U16_BE ;
- while (i) {
- if (i & dmasound.mach.hardware_afmts)
- len += sprintf(b+len,"%s ",
- get_afmt_string(i & dmasound.mach.hardware_afmts));
- i >>= 1 ;
- }
- len += sprintf(b+len,"\n") ;
- }
- return len ;
-}
-
-/*** Machine definitions *****************************************************/
-
-static SETTINGS def_hard = {
- .format = AFMT_S16_BE,
- .stereo = 1,
- .size = 16,
- .speed = 44100
-} ;
-
-static SETTINGS def_soft = {
- .format = AFMT_S16_BE,
- .stereo = 1,
- .size = 16,
- .speed = 44100
-} ;
-
-static MACHINE machPMac = {
- .name = awacs_name,
- .name2 = "PowerMac Built-in Sound",
- .owner = THIS_MODULE,
- .dma_alloc = PMacAlloc,
- .dma_free = PMacFree,
- .irqinit = PMacIrqInit,
-#ifdef MODULE
- .irqcleanup = PMacIrqCleanup,
-#endif /* MODULE */
- .init = PMacInit,
- .silence = PMacSilence,
- .setFormat = PMacSetFormat,
- .setVolume = PMacSetVolume,
- .play = PMacPlay,
- .record = NULL, /* default to no record */
- .mixer_init = PMacMixerInit,
- .mixer_ioctl = PMacMixerIoctl,
- .write_sq_setup = PMacWriteSqSetup,
- .read_sq_setup = PMacReadSqSetup,
- .state_info = PMacStateInfo,
- .abort_read = PMacAbortRead,
- .min_dsp_speed = 7350,
- .max_dsp_speed = 44100,
- .version = ((DMASOUND_AWACS_REVISION<<8) + DMASOUND_AWACS_EDITION)
-};
-
-
-/*** Config & Setup **********************************************************/
-
-/* Check for pmac models that we care about in terms of special actions.
-*/
-
-void __init
-set_model(void)
-{
- /* portables/lap-tops */
-
- if (machine_is_compatible("AAPL,3400/2400") ||
- machine_is_compatible("AAPL,3500")) {
- is_pbook_3X00 = 1 ;
- }
- if (machine_is_compatible("PowerBook1,1") || /* lombard */
- machine_is_compatible("AAPL,PowerBook1998")){ /* wallstreet */
- is_pbook_g3 = 1 ;
- return ;
- }
-}
-
-/* Get the OF node that tells us about the registers, interrupts etc. to use
- for sound IO.
-
- On most machines the sound IO OF node is the 'davbus' node. On newer pmacs
- with DACA (& Tumbler) the node to use is i2s-a. On much older machines i.e.
- before 9500 there is no davbus node and we have to use the 'awacs' property.
-
- In the latter case we signal this by setting the codec value - so that the
- code that looks for chip properties knows how to go about it.
-*/
-
-static struct device_node* __init
-get_snd_io_node(void)
-{
- struct device_node *np;
-
- /* set up awacs_node for early OF which doesn't have a full set of
- * properties on davbus
- */
- awacs_node = of_find_node_by_name(NULL, "awacs");
- if (awacs_node)
- awacs_revision = AWACS_AWACS;
-
- /* powermac models after 9500 (other than those which use DACA or
- * Tumbler) have a node called "davbus".
- */
- np = of_find_node_by_name(NULL, "davbus");
- /*
- * if we didn't find a davbus device, try 'i2s-a' since
- * this seems to be what iBooks (& Tumbler) have.
- */
- if (np == NULL) {
- i2s_node = of_find_node_by_name(NULL, "i2s-a");
- np = of_node_get(i2s_node);
- }
-
- /* if we didn't find this - perhaps we are on an early model
- * which _only_ has an 'awacs' node
- */
- if (np == NULL && awacs_node)
- np = of_node_get(awacs_node);
-
- /* if we failed all these return null - this will cause the
- * driver to give up...
- */
- return np ;
-}
-
-/* Get the OF node that contains the info about the sound chip, inputs s-rates
- etc.
- This node does not exist (or contains much reduced info) on earlier machines
- we have to deduce the info other ways for these.
-*/
-
-static struct device_node* __init
-get_snd_info_node(struct device_node *io)
-{
- struct device_node *info;
-
- for_each_node_by_name(info, "sound")
- if (info->parent == io)
- break;
- return info;
-}
-
-/* Find out what type of codec we have.
-*/
-
-static int __init
-get_codec_type(struct device_node *info)
-{
- /* already set if pre-davbus model and info will be NULL */
- int codec = awacs_revision ;
-
- if (info) {
- /* must do awacs first to allow screamer to overide it */
- if (of_device_is_compatible(info, "awacs"))
- codec = AWACS_AWACS ;
- if (of_device_is_compatible(info, "screamer"))
- codec = AWACS_SCREAMER;
- if (of_device_is_compatible(info, "burgundy"))
- codec = AWACS_BURGUNDY ;
- if (of_device_is_compatible(info, "daca"))
- codec = AWACS_DACA;
- if (of_device_is_compatible(info, "tumbler"))
- codec = AWACS_TUMBLER;
- if (of_device_is_compatible(info, "snapper"))
- codec = AWACS_SNAPPER;
- }
- return codec ;
-}
-
-/* find out what type, if any, of expansion card we have
-*/
-static void __init
-get_expansion_type(void)
-{
- struct device_node *dn;
-
- dn = of_find_node_by_name(NULL, "perch");
- if (dn != NULL)
- has_perch = 1;
- of_node_put(dn);
-
- dn = of_find_node_by_name(NULL, "pb-ziva-pc");
- if (dn != NULL)
- has_ziva = 1;
- of_node_put(dn);
- /* need to work out how we deal with iMac SRS module */
-}
-
-/* set up frame rates.
- * I suspect that these routines don't quite go about it the right way:
- * - where there is more than one rate - I think that the first property
- * value is the number of rates.
- * TODO: check some more device trees and modify accordingly
- * Set dmasound.mach.max_dsp_rate on the basis of these routines.
-*/
-
-static void __init
-awacs_init_frame_rates(const unsigned int *prop, unsigned int l)
-{
- int i ;
- if (prop) {
- for (i=0; i<8; i++)
- awacs_freqs_ok[i] = 0 ;
- for (l /= sizeof(int); l > 0; --l) {
- unsigned int r = *prop++;
- /* Apple 'Fixed' format */
- if (r >= 0x10000)
- r >>= 16;
- for (i = 0; i < 8; ++i) {
- if (r == awacs_freqs[i]) {
- awacs_freqs_ok[i] = 1;
- break;
- }
- }
- }
- }
- /* else we assume that all the rates are available */
-}
-
-static void __init
-burgundy_init_frame_rates(const unsigned int *prop, unsigned int l)
-{
- int temp[9] ;
- int i = 0 ;
- if (prop) {
- for (l /= sizeof(int); l > 0; --l) {
- unsigned int r = *prop++;
- /* Apple 'Fixed' format */
- if (r >= 0x10000)
- r >>= 16;
- temp[i] = r ;
- i++ ; if(i>=9) i=8;
- }
- }
-#ifdef DEBUG_DMASOUND
-if (i > 1){
- int j;
- printk("dmasound_pmac: burgundy with multiple frame rates\n");
- for(j=0; j<i; j++)
- printk("%d ", temp[j]) ;
- printk("\n") ;
-}
-#endif
-}
-
-static void __init
-daca_init_frame_rates(const unsigned int *prop, unsigned int l)
-{
- int temp[9] ;
- int i = 0 ;
- if (prop) {
- for (l /= sizeof(int); l > 0; --l) {
- unsigned int r = *prop++;
- /* Apple 'Fixed' format */
- if (r >= 0x10000)
- r >>= 16;
- temp[i] = r ;
- i++ ; if(i>=9) i=8;
-
- }
- }
-#ifdef DEBUG_DMASOUND
-if (i > 1){
- int j;
- printk("dmasound_pmac: DACA with multiple frame rates\n");
- for(j=0; j<i; j++)
- printk("%d ", temp[j]) ;
- printk("\n") ;
-}
-#endif
-}
-
-static void __init
-init_frame_rates(const unsigned int *prop, unsigned int l)
-{
- switch (awacs_revision) {
- case AWACS_TUMBLER:
- case AWACS_SNAPPER:
- tas_init_frame_rates(prop, l);
- break ;
- case AWACS_DACA:
- daca_init_frame_rates(prop, l);
- break ;
- case AWACS_BURGUNDY:
- burgundy_init_frame_rates(prop, l);
- break ;
- default:
- awacs_init_frame_rates(prop, l);
- break ;
- }
-}
-
-/* find things/machines that can't do mac-io byteswap
-*/
-
-static void __init
-set_hw_byteswap(struct device_node *io)
-{
- struct device_node *mio ;
- unsigned int kl = 0 ;
-
- /* if seems that Keylargo can't byte-swap */
-
- for (mio = io->parent; mio ; mio = mio->parent) {
- if (strcmp(mio->name, "mac-io") == 0) {
- if (of_device_is_compatible(mio, "Keylargo"))
- kl = 1;
- break;
- }
- }
- hw_can_byteswap = !kl;
-}
-
-/* Allocate the resources necessary for beep generation. This cannot be (quite)
- done statically (yet) because we cannot do virt_to_bus() on static vars when
- the code is loaded as a module.
-
- for the sake of saving the possibility that two allocations will incur the
- overhead of two pull-ups in DBDMA_ALIGN() we allocate the 'emergency' dmdma
- command here as well... even tho' it is not part of the beep process.
-*/
-
-int32_t
-__init setup_beep(void)
-{
- /* Initialize beep stuff */
- /* want one cmd buffer for beeps, and a second one for emergencies
- - i.e. dbdma error conditions.
- ask for three to allow for pull up in DBDMA_ALIGN().
- */
- beep_dbdma_cmd_space =
- kmalloc((2 + 1) * sizeof(struct dbdma_cmd), GFP_KERNEL);
- if(beep_dbdma_cmd_space == NULL) {
- printk(KERN_ERR "dmasound_pmac: no beep dbdma cmd space\n") ;
- return -ENOMEM ;
- }
- beep_dbdma_cmd = (volatile struct dbdma_cmd *)
- DBDMA_ALIGN(beep_dbdma_cmd_space);
- /* set up emergency dbdma cmd */
- emergency_dbdma_cmd = beep_dbdma_cmd+1 ;
- beep_buf = kmalloc(BEEP_BUFLEN * 4, GFP_KERNEL);
- if (beep_buf == NULL) {
- printk(KERN_ERR "dmasound_pmac: no memory for beep buffer\n");
- kfree(beep_dbdma_cmd_space) ;
- return -ENOMEM ;
- }
- return 0 ;
-}
-
-static struct input_dev *awacs_beep_dev;
-
-int __init dmasound_awacs_init(void)
-{
- struct device_node *io = NULL, *info = NULL;
- int vol, res;
-
- if (!machine_is(powermac))
- return -ENODEV;
-
- awacs_subframe = 0;
- awacs_revision = 0;
- hw_can_byteswap = 1 ; /* most can */
-
- /* look for models we need to handle specially */
- set_model() ;
-
- /* find the OF node that tells us about the dbdma stuff
- */
- io = get_snd_io_node();
- if (io == NULL) {
-#ifdef DEBUG_DMASOUND
-printk("dmasound_pmac: couldn't find sound io OF node\n");
-#endif
- goto no_device;
- }
-
- /* find the OF node that tells us about the sound sub-system
- * this doesn't exist on pre-davbus machines (earlier than 9500)
- */
- if (awacs_revision != AWACS_AWACS) { /* set for pre-davbus */
- info = get_snd_info_node(io) ;
- if (info == NULL){
-#ifdef DEBUG_DMASOUND
-printk("dmasound_pmac: couldn't find 'sound' OF node\n");
-#endif
- goto no_device;
- }
- }
-
- awacs_revision = get_codec_type(info) ;
- if (awacs_revision == 0) {
-#ifdef DEBUG_DMASOUND
-printk("dmasound_pmac: couldn't find a Codec we can handle\n");
-#endif
- goto no_device; /* we don't know this type of h/w */
- }
-
- /* set up perch, ziva, SRS or whatever else we have as sound
- * expansion.
- */
- get_expansion_type();
-
- /* we've now got enough information to make up the audio topology.
- * we will map the sound part of mac-io now so that we can probe for
- * other info if necessary (early AWACS we want to read chip ids)
- */
-
- if (of_get_address(io, 2, NULL, NULL) == NULL) {
- /* OK - maybe we need to use the 'awacs' node (on earlier
- * machines).
- */
- if (awacs_node) {
- of_node_put(io);
- io = of_node_get(awacs_node);
- if (of_get_address(io, 2, NULL, NULL) == NULL) {
- printk("dmasound_pmac: can't use %s\n",
- io->full_name);
- goto no_device;
- }
- } else
- printk("dmasound_pmac: can't use %s\n", io->full_name);
- }
-
- if (of_address_to_resource(io, 0, &awacs_rsrc[0]) ||
- request_mem_region(awacs_rsrc[0].start,
- awacs_rsrc[0].end - awacs_rsrc[0].start + 1,
- " (IO)") == NULL) {
- printk(KERN_ERR "dmasound: can't request IO resource !\n");
- goto no_device;
- }
- if (of_address_to_resource(io, 1, &awacs_rsrc[1]) ||
- request_mem_region(awacs_rsrc[1].start,
- awacs_rsrc[1].end - awacs_rsrc[1].start + 1,
- " (tx dma)") == NULL) {
- release_mem_region(awacs_rsrc[0].start,
- awacs_rsrc[0].end - awacs_rsrc[0].start + 1);
- printk(KERN_ERR "dmasound: can't request Tx DMA resource !\n");
- goto no_device;
- }
- if (of_address_to_resource(io, 2, &awacs_rsrc[2]) ||
- request_mem_region(awacs_rsrc[2].start,
- awacs_rsrc[2].end - awacs_rsrc[2].start + 1,
- " (rx dma)") == NULL) {
- release_mem_region(awacs_rsrc[0].start,
- awacs_rsrc[0].end - awacs_rsrc[0].start + 1);
- release_mem_region(awacs_rsrc[1].start,
- awacs_rsrc[1].end - awacs_rsrc[1].start + 1);
- printk(KERN_ERR "dmasound: can't request Rx DMA resource !\n");
- goto no_device;
- }
-
- awacs_beep_dev = input_allocate_device();
- if (!awacs_beep_dev) {
- release_mem_region(awacs_rsrc[0].start,
- awacs_rsrc[0].end - awacs_rsrc[0].start + 1);
- release_mem_region(awacs_rsrc[1].start,
- awacs_rsrc[1].end - awacs_rsrc[1].start + 1);
- release_mem_region(awacs_rsrc[2].start,
- awacs_rsrc[2].end - awacs_rsrc[2].start + 1);
- printk(KERN_ERR "dmasound: can't allocate input device !\n");
- goto no_device;
- }
-
- awacs_beep_dev->name = "dmasound beeper";
- awacs_beep_dev->phys = "macio/input0";
- awacs_beep_dev->id.bustype = BUS_HOST;
- awacs_beep_dev->event = awacs_beep_event;
- awacs_beep_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
- awacs_beep_dev->evbit[0] = BIT(EV_SND);
-
- /* all OF versions I've seen use this value */
- if (i2s_node)
- i2s = ioremap(awacs_rsrc[0].start, 0x1000);
- else
- awacs = ioremap(awacs_rsrc[0].start, 0x1000);
- awacs_txdma = ioremap(awacs_rsrc[1].start, 0x100);
- awacs_rxdma = ioremap(awacs_rsrc[2].start, 0x100);
-
- /* first of all make sure that the chip is powered up....*/
- pmac_call_feature(PMAC_FTR_SOUND_CHIP_ENABLE, io, 0, 1);
- if (awacs_revision == AWACS_SCREAMER && awacs)
- awacs_recalibrate();
-
- awacs_irq = irq_of_parse_and_map(io, 0);
- awacs_tx_irq = irq_of_parse_and_map(io, 1);
- awacs_rx_irq = irq_of_parse_and_map(io, 2);
-
- /* Hack for legacy crap that will be killed someday */
- of_node_put(awacs_node);
- awacs_node = of_node_get(io);
-
- /* if we have an awacs or screamer - probe the chip to make
- * sure we have the right revision.
- */
-
- if (awacs_revision <= AWACS_SCREAMER){
- uint32_t temp, rev, mfg ;
- /* find out the awacs revision from the chip */
- temp = in_le32(&awacs->codec_stat);
- rev = (temp >> 12) & 0xf;
- mfg = (temp >> 8) & 0xf;
-#ifdef DEBUG_DMASOUND
-printk("dmasound_pmac: Awacs/Screamer Codec Mfct: %d Rev %d\n", mfg, rev);
-#endif
- if (rev >= AWACS_SCREAMER)
- awacs_revision = AWACS_SCREAMER ;
- else
- awacs_revision = rev ;
- }
-
- dmasound.mach = machPMac;
-
- /* find out other bits & pieces from OF, these may be present
- only on some models ... so be careful.
- */
-
- /* in the absence of a frame rates property we will use the defaults
- */
-
- if (info) {
- const unsigned int *prop;
- unsigned int l;
-
- sound_device_id = 0;
- /* device ID appears post g3 b&w */
- prop = of_get_property(info, "device-id", NULL);
- if (prop != 0)
- sound_device_id = *prop;
-
- /* look for a property saying what sample rates
- are available */
-
- prop = of_get_property(info, "sample-rates", &l);
- if (prop == 0)
- prop = of_get_property(info, "output-frame-rates", &l);
-
- /* if it's there use it to set up frame rates */
- init_frame_rates(prop, l) ;
- of_node_put(info);
- info = NULL;
- }
-
- if (awacs)
- out_le32(&awacs->control, 0x11); /* set everything quiesent */
-
- set_hw_byteswap(io) ; /* figure out if the h/w can do it */
-
-#ifdef CONFIG_NVRAM
- /* get default volume from nvram */
- vol = ((pmac_xpram_read( 8 ) & 7 ) << 1 );
-#else
- vol = 0;
-#endif
-
- /* set up tracking values */
- spk_vol = vol * 100 ;
- spk_vol /= 7 ; /* get set value to a percentage */
- spk_vol |= (spk_vol << 8) ; /* equal left & right */
- line_vol = passthru_vol = spk_vol ;
-
- /* fill regs that are shared between AWACS & Burgundy */
-
- awacs_reg[2] = vol + (vol << 6);
- awacs_reg[4] = vol + (vol << 6);
- awacs_reg[5] = vol + (vol << 6); /* screamer has loopthru vol control */
- awacs_reg[6] = 0; /* maybe should be vol << 3 for PCMCIA speaker */
- awacs_reg[7] = 0;
-
- awacs_reg[0] = MASK_MUX_CD;
- awacs_reg[1] = MASK_LOOPTHRU;
-
- /* FIXME: Only machines with external SRS module need MASK_PAROUT */
- if (has_perch || sound_device_id == 0x5
- || /*sound_device_id == 0x8 ||*/ sound_device_id == 0xb)
- awacs_reg[1] |= MASK_PAROUT0 | MASK_PAROUT1;
-
- switch (awacs_revision) {
- case AWACS_TUMBLER:
- tas_register_driver(&tas3001c_hooks);
- tas_init(I2C_DRIVERID_TAS3001C, I2C_DRIVERNAME_TAS3001C);
- tas_dmasound_init();
- tas_post_init();
- break ;
- case AWACS_SNAPPER:
- tas_register_driver(&tas3004_hooks);
- tas_init(I2C_DRIVERID_TAS3004,I2C_DRIVERNAME_TAS3004);
- tas_dmasound_init();
- tas_post_init();
- break;
- case AWACS_DACA:
- daca_init();
- break;
- case AWACS_BURGUNDY:
- awacs_burgundy_init();
- break ;
- case AWACS_SCREAMER:
- case AWACS_AWACS:
- default:
- load_awacs();
- break ;
- }
-
- /* enable/set-up external modules - when we know how */
-
- if (has_perch)
- awacs_enable_amp(100 * 0x101);
-
- /* Reset dbdma channels */
- out_le32(&awacs_txdma->control, (RUN|PAUSE|FLUSH|WAKE|DEAD) << 16);
- while (in_le32(&awacs_txdma->status) & RUN)
- udelay(1);
- out_le32(&awacs_rxdma->control, (RUN|PAUSE|FLUSH|WAKE|DEAD) << 16);
- while (in_le32(&awacs_rxdma->status) & RUN)
- udelay(1);
-
- /* Initialize beep stuff */
- if ((res=setup_beep()))
- return res ;
-
-#ifdef CONFIG_PM
- pmu_register_sleep_notifier(&awacs_sleep_notifier);
-#endif /* CONFIG_PM */
-
- /* Powerbooks have odd ways of enabling inputs such as
- an expansion-bay CD or sound from an internal modem
- or a PC-card modem. */
- if (is_pbook_3X00) {
- /*
- * Enable CD and PC-card sound inputs.
- * This is done by reading from address
- * f301a000, + 0x10 to enable the expansion-bay
- * CD sound input, + 0x80 to enable the PC-card
- * sound input. The 0x100 enables the SCSI bus
- * terminator power.
- */
- latch_base = ioremap (0xf301a000, 0x1000);
- in_8(latch_base + 0x190);
-
- } else if (is_pbook_g3) {
- struct device_node* mio;
- macio_base = NULL;
- for (mio = io->parent; mio; mio = mio->parent) {
- if (strcmp(mio->name, "mac-io") == 0) {
- struct resource r;
- if (of_address_to_resource(mio, 0, &r) == 0)
- macio_base = ioremap(r.start, 0x40);
- break;
- }
- }
- /*
- * Enable CD sound input.
- * The relevant bits for writing to this byte are 0x8f.
- * I haven't found out what the 0x80 bit does.
- * For the 0xf bits, writing 3 or 7 enables the CD
- * input, any other value disables it. Values
- * 1, 3, 5, 7 enable the microphone. Values 0, 2,
- * 4, 6, 8 - f enable the input from the modem.
- * -- paulus.
- */
- if (macio_base)
- out_8(macio_base + 0x37, 3);
- }
-
- if (hw_can_byteswap)
- dmasound.mach.hardware_afmts = (AFMT_S16_BE | AFMT_S16_LE) ;
- else
- dmasound.mach.hardware_afmts = AFMT_S16_BE ;
-
- /* shut out chips that do output only.
- * may need to extend this to machines which have no inputs - even tho'
- * they use screamer - IIRC one of the powerbooks is like this.
- */
-
- if (awacs_revision != AWACS_DACA) {
- dmasound.mach.capabilities = DSP_CAP_DUPLEX ;
- dmasound.mach.record = PMacRecord ;
- }
-
- dmasound.mach.default_hard = def_hard ;
- dmasound.mach.default_soft = def_soft ;
-
- switch (awacs_revision) {
- case AWACS_BURGUNDY:
- sprintf(awacs_name, "PowerMac Burgundy ") ;
- break ;
- case AWACS_DACA:
- sprintf(awacs_name, "PowerMac DACA ") ;
- break ;
- case AWACS_TUMBLER:
- sprintf(awacs_name, "PowerMac Tumbler ") ;
- break ;
- case AWACS_SNAPPER:
- sprintf(awacs_name, "PowerMac Snapper ") ;
- break ;
- case AWACS_SCREAMER:
- sprintf(awacs_name, "PowerMac Screamer ") ;
- break ;
- case AWACS_AWACS:
- default:
- sprintf(awacs_name, "PowerMac AWACS rev %d ", awacs_revision) ;
- break ;
- }
-
- /*
- * XXX: we should handle errors here, but that would mean
- * rewriting the whole init code. later..
- */
- input_register_device(awacs_beep_dev);
-
- of_node_put(io);
-
- return dmasound_init();
-
-no_device:
- of_node_put(info);
- of_node_put(awacs_node);
- of_node_put(i2s_node);
- of_node_put(io);
- return -ENODEV ;
-}
-
-static void __exit dmasound_awacs_cleanup(void)
-{
- input_unregister_device(awacs_beep_dev);
-
- switch (awacs_revision) {
- case AWACS_TUMBLER:
- case AWACS_SNAPPER:
- tas_dmasound_cleanup();
- tas_cleanup();
- break ;
- case AWACS_DACA:
- daca_cleanup();
- break;
- }
- dmasound_deinit();
-
- of_node_put(awacs_node);
- of_node_put(i2s_node);
-}
-
-MODULE_DESCRIPTION("PowerMac built-in audio driver.");
-MODULE_LICENSE("GPL");
-
-module_init(dmasound_awacs_init);
-module_exit(dmasound_awacs_cleanup);
diff --git a/sound/oss/dmasound/dmasound_core.c b/sound/oss/dmasound/dmasound_core.c
index f4056a9c371b..a003c0ea9303 100644
--- a/sound/oss/dmasound/dmasound_core.c
+++ b/sound/oss/dmasound/dmasound_core.c
@@ -202,13 +202,6 @@ module_param(numWriteBufs, int, 0);
static unsigned int writeBufSize = DEFAULT_BUFF_SIZE ; /* in bytes */
module_param(writeBufSize, int, 0);
-#ifdef HAS_RECORD
-static unsigned int numReadBufs = DEFAULT_N_BUFFERS;
-module_param(numReadBufs, int, 0);
-static unsigned int readBufSize = DEFAULT_BUFF_SIZE; /* in bytes */
-module_param(readBufSize, int, 0);
-#endif
-
MODULE_LICENSE("GPL");
#ifdef MODULE
@@ -403,10 +396,6 @@ static void mixer_init(void)
struct sound_queue dmasound_write_sq;
static void sq_reset_output(void) ;
-#ifdef HAS_RECORD
-struct sound_queue dmasound_read_sq;
-static void sq_reset_input(void) ;
-#endif
static int sq_allocate_buffers(struct sound_queue *sq, int num, int size)
{
@@ -530,12 +519,6 @@ printk("dmasound_core: invalid frag count (user set %d)\n", sq->user_frags) ;
sq->rear = -1;
setup_func = dmasound.mach.write_sq_setup;
}
-#ifdef HAS_RECORD
- else {
- sq->rear = 0;
- setup_func = dmasound.mach.read_sq_setup;
- }
-#endif
if (setup_func)
return setup_func();
return 0 ;
@@ -672,13 +655,6 @@ static unsigned int sq_poll(struct file *file, struct poll_table_struct *wait)
}
if (file->f_mode & FMODE_WRITE )
poll_wait(file, &write_sq.action_queue, wait);
-#ifdef HAS_RECORD
- if (file->f_mode & FMODE_READ)
- poll_wait(file, &read_sq.action_queue, wait);
- if (file->f_mode & FMODE_READ)
- if (read_sq.block_size - read_sq.rear_size > 0)
- mask |= POLLIN | POLLRDNORM;
-#endif
if (file->f_mode & FMODE_WRITE)
if (write_sq.count < write_sq.max_active || write_sq.block_size - write_sq.rear_size > 0)
mask |= POLLOUT | POLLWRNORM;
@@ -686,101 +662,6 @@ static unsigned int sq_poll(struct file *file, struct poll_table_struct *wait)
}
-#ifdef HAS_RECORD
- /*
- * Here is how the values are used for reading.
- * The value 'active' simply indicates the DMA is running. This is done
- * so the driver semantics are DMA starts when the first read is posted.
- * The value 'front' indicates the buffer we should next send to the user.
- * The value 'rear' indicates the buffer the DMA is currently filling.
- * When 'front' == 'rear' the buffer "ring" is empty (we always have an
- * empty available). The 'rear_size' is used to track partial offsets
- * into the buffer we are currently returning to the user.
-
- * This level (> [1.5]) doesn't care what strategy the LL driver uses with
- * DMA on over-run. It can leave it running (and keep active == 1) or it
- * can kill it and set active == 0 in which case this routine will spot
- * it and restart the DMA.
- */
-
-static ssize_t sq_read(struct file *file, char __user *dst, size_t uLeft,
- loff_t *ppos)
-{
-
- ssize_t uRead, bLeft, bUsed, uUsed;
-
- if (uLeft == 0)
- return 0;
-
- /* cater for the compatibility mode - record compiled in but no LL */
- if (dmasound.mach.record == NULL)
- return -EINVAL ;
-
- /* see comment in sq_write()
- */
-
- if( shared_resources_initialised == 0) {
- dmasound.mach.init() ;
- shared_resources_initialised = 1 ;
- }
-
- /* set up the sq if it is not already done. see comments in sq_write().
- */
-
- if (read_sq.locked == 0) {
- if ((uRead = sq_setup(&read_sq)) < 0)
- return uRead ;
- }
-
- uRead = 0;
-
- /* Move what the user requests, depending upon other options.
- */
- while (uLeft > 0) {
-
- /* we happened to get behind and the LL driver killed DMA
- then we should set it going again. This also sets it
- going the first time through.
- */
- if ( !read_sq.active )
- dmasound.mach.record();
-
- /* When front == rear, the DMA is not done yet.
- */
- while (read_sq.front == read_sq.rear) {
- if (read_sq.open_mode & O_NONBLOCK) {
- return uRead > 0 ? uRead : -EAGAIN;
- }
- SLEEP(read_sq.action_queue);
- if (signal_pending(current))
- return uRead > 0 ? uRead : -EINTR;
- }
-
- /* The amount we move is either what is left in the
- * current buffer or what the user wants.
- */
- bLeft = read_sq.block_size - read_sq.rear_size;
- bUsed = read_sq.rear_size;
- uUsed = sound_copy_translate(dmasound.trans_read, dst, uLeft,
- read_sq.buffers[read_sq.front],
- &bUsed, bLeft);
- if (uUsed <= 0)
- return uUsed;
- dst += uUsed;
- uRead += uUsed;
- uLeft -= uUsed;
- read_sq.rear_size += bUsed;
- if (read_sq.rear_size >= read_sq.block_size) {
- read_sq.rear_size = 0;
- read_sq.front++;
- if (read_sq.front >= read_sq.max_active)
- read_sq.front = 0;
- }
- }
- return uRead;
-}
-#endif /* HAS_RECORD */
-
static inline void sq_init_waitqueue(struct sound_queue *sq)
{
init_waitqueue_head(&sq->action_queue);
@@ -854,23 +735,6 @@ static int sq_open2(struct sound_queue *sq, struct file *file, mode_t mode,
#define write_sq_open(file) \
sq_open2(&write_sq, file, FMODE_WRITE, numWriteBufs, writeBufSize )
-#ifdef HAS_RECORD
-#define read_sq_init_waitqueue() sq_init_waitqueue(&read_sq)
-#if 0 /* blocking open() */
-#define read_sq_wake_up(file) sq_wake_up(&read_sq, file, FMODE_READ)
-#endif
-#define read_sq_release_buffers() sq_release_buffers(&read_sq)
-#define read_sq_open(file) \
- sq_open2(&read_sq, file, FMODE_READ, numReadBufs, readBufSize )
-#else
-#define read_sq_init_waitqueue() do {} while (0)
-#if 0 /* blocking open() */
-#define read_sq_wake_up(file) do {} while (0)
-#endif
-#define read_sq_release_buffers() do {} while (0)
-#define sq_reset_input() do {} while (0)
-#endif
-
static int sq_open(struct inode *inode, struct file *file)
{
int rc;
@@ -881,25 +745,11 @@ static int sq_open(struct inode *inode, struct file *file)
rc = write_sq_open(file); /* checks the f_mode */
if (rc)
goto out;
-#ifdef HAS_RECORD
- if (dmasound.mach.record) {
- rc = read_sq_open(file); /* checks the f_mode */
- if (rc)
- goto out;
- } else { /* no record function installed; in compat mode */
- if (file->f_mode & FMODE_READ) {
- /* TODO: if O_RDWR, release any resources grabbed by write part */
- rc = -ENXIO;
- goto out;
- }
- }
-#else /* !HAS_RECORD */
if (file->f_mode & FMODE_READ) {
/* TODO: if O_RDWR, release any resources grabbed by write part */
rc = -ENXIO ; /* I think this is what is required by open(2) */
goto out;
}
-#endif /* HAS_RECORD */
if (dmasound.mach.sq_open)
dmasound.mach.sq_open(file->f_mode);
@@ -956,43 +806,9 @@ static void sq_reset_output(void)
write_sq.user_frag_size = 0 ;
}
-#ifdef HAS_RECORD
-
-static void sq_reset_input(void)
-{
- if (dmasound.mach.record && read_sq.active) {
- if (dmasound.mach.abort_read) { /* this routine must really be present */
- read_sq.syncing = 1 ;
- /* this can use the read_sq.sync_queue to sleep if
- necessary - it should not return until DMA
- is really stopped - because we might deallocate
- the buffers as the next action...
- */
- dmasound.mach.abort_read() ;
- } else {
- printk(KERN_ERR
- "dmasound_core: %s has no abort_read()!! all bets are off\n",
- dmasound.mach.name) ;
- }
- }
- read_sq.syncing =
- read_sq.active =
- read_sq.front =
- read_sq.count =
- read_sq.rear = 0 ;
-
- /* OK - we can unlock the parameters and fragment settings */
- read_sq.locked = 0 ;
- read_sq.user_frags = 0 ;
- read_sq.user_frag_size = 0 ;
-}
-
-#endif
-
static void sq_reset(void)
{
sq_reset_output() ;
- sq_reset_input() ;
/* we could consider resetting the shared_resources_owner here... but I
think it is probably still rather non-obvious to application writer
*/
@@ -1038,17 +854,6 @@ static int sq_release(struct inode *inode, struct file *file)
lock_kernel();
-#ifdef HAS_RECORD
- /* probably best to do the read side first - so that time taken to do it
- overlaps with playing any remaining output samples.
- */
- if (file->f_mode & FMODE_READ) {
- sq_reset_input() ; /* make sure dma is stopped and all is quiet */
- read_sq_release_buffers();
- read_sq.busy = 0;
- }
-#endif
-
if (file->f_mode & FMODE_WRITE) {
if (write_sq.busy)
rc = sq_fsync(file, file->f_path.dentry);
@@ -1105,11 +910,6 @@ static int shared_resources_are_mine(mode_t md)
static int queues_are_quiescent(void)
{
-#ifdef HAS_RECORD
- if (dmasound.mach.record)
- if (read_sq.locked)
- return 0 ;
-#endif
if (write_sq.locked)
return 0 ;
return 1 ;
@@ -1185,13 +985,6 @@ static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd,
the read_sq ones.
*/
size = 0 ;
-#ifdef HAS_RECORD
- if (dmasound.mach.record && (file->f_mode & FMODE_READ)) {
- if ( !read_sq.locked )
- sq_setup(&read_sq) ; /* set params */
- size = read_sq.user_frag_size ;
- }
-#endif
if (file->f_mode & FMODE_WRITE) {
if ( !write_sq.locked )
sq_setup(&write_sq) ;
@@ -1214,8 +1007,6 @@ static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd,
everything - read, however, is killed imediately.
*/
result = 0 ;
- if ((file->f_mode & FMODE_READ) && dmasound.mach.record)
- sq_reset_input() ;
if (file->f_mode & FMODE_WRITE) {
result = sq_fsync(file, file->f_path.dentry);
sq_reset_output() ;
@@ -1294,13 +1085,6 @@ static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd,
result = 0 ;
nbufs = (data >> 16) & 0x7fff ; /* 0x7fff is 'use maximum' */
size = data & 0xffff;
-#ifdef HAS_RECORD
- if ((file->f_mode & FMODE_READ) && dmasound.mach.record) {
- result = set_queue_frags(&read_sq, nbufs, size) ;
- if (result)
- return result ;
- }
-#endif
if (file->f_mode & FMODE_WRITE) {
result = set_queue_frags(&write_sq, nbufs, size) ;
if (result)
@@ -1348,20 +1132,6 @@ static const struct file_operations sq_fops =
.release = sq_release,
};
-#ifdef HAS_RECORD
-static const struct file_operations sq_fops_record =
-{
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .write = sq_write,
- .poll = sq_poll,
- .ioctl = sq_ioctl,
- .open = sq_open,
- .release = sq_release,
- .read = sq_read,
-};
-#endif
-
static int sq_init(void)
{
const struct file_operations *fops = &sq_fops;
@@ -1369,10 +1139,6 @@ static int sq_init(void)
int sq_unit;
#endif
-#ifdef HAS_RECORD
- if (dmasound.mach.record)
- fops = &sq_fops_record;
-#endif
sq_unit = register_sound_dsp(fops, -1);
if (sq_unit < 0) {
printk(KERN_ERR "dmasound_core: couldn't register fops\n") ;
@@ -1380,7 +1146,6 @@ static int sq_init(void)
}
write_sq_init_waitqueue();
- read_sq_init_waitqueue();
/* These parameters will be restored for every clean open()
* in the case of multiple open()s (e.g. dsp0 & dsp1) they
@@ -1406,11 +1171,7 @@ static int sq_init(void)
driver.
*/
-#ifdef HAS_RECORD
-#define STAT_BUFF_LEN 1024
-#else
#define STAT_BUFF_LEN 768
-#endif
/* this is how much space we will allow the low-level driver to use
in the stat buffer. Currently, 2 * (80 character line + <NL>).
@@ -1518,11 +1279,6 @@ static int state_open(struct inode *inode, struct file *file)
len += sprintf(buffer+len,"Allocated:%8s%6s\n","Buffers","Size") ;
len += sprintf(buffer+len,"%9s:%8d%6d\n",
"write", write_sq.numBufs, write_sq.bufSize) ;
-#ifdef HAS_RECORD
- if (dmasound.mach.record)
- len += sprintf(buffer+len,"%9s:%8d%6d\n",
- "read", read_sq.numBufs, read_sq.bufSize) ;
-#endif
len += sprintf(buffer+len,
"Current : MaxFrg FragSiz MaxAct Frnt Rear "
"Cnt RrSize A B S L xruns\n") ;
@@ -1531,14 +1287,6 @@ static int state_open(struct inode *inode, struct file *file)
write_sq.max_active, write_sq.front, write_sq.rear,
write_sq.count, write_sq.rear_size, write_sq.active,
write_sq.busy, write_sq.syncing, write_sq.locked, write_sq.xruns) ;
-#ifdef HAS_RECORD
- if (dmasound.mach.record)
- len += sprintf(buffer+len,"%9s:%7d%8d%7d%5d%5d%4d%7d%2d%2d%2d%2d%7d\n",
- "read", read_sq.max_count, read_sq.block_size,
- read_sq.max_active, read_sq.front, read_sq.rear,
- read_sq.count, read_sq.rear_size, read_sq.active,
- read_sq.busy, read_sq.syncing, read_sq.locked, read_sq.xruns) ;
-#endif
#ifdef DEBUG_DMASOUND
printk("dmasound: stat buffer used %d bytes\n", len) ;
#endif
@@ -1638,13 +1386,6 @@ int dmasound_init(void)
(dmasound.mach.version >> 8), (dmasound.mach.version & 0xff)) ;
printk(KERN_INFO "Write will use %4d fragments of %7d bytes as default\n",
numWriteBufs, writeBufSize) ;
-#ifdef HAS_RECORD
- if (dmasound.mach.record)
- printk(KERN_INFO
- "Read will use %4d fragments of %7d bytes as default\n",
- numReadBufs, readBufSize) ;
-#endif
-
return 0;
}
@@ -1659,7 +1400,6 @@ void dmasound_deinit(void)
}
write_sq_release_buffers();
- read_sq_release_buffers();
if (mixer_unit >= 0)
unregister_sound_mixer(mixer_unit);
@@ -1684,36 +1424,12 @@ static int dmasound_setup(char *str)
*/
switch (ints[0]) {
-#ifdef HAS_RECORD
- case 5:
- if ((ints[5] < 0) || (ints[5] > MAX_CATCH_RADIUS))
- printk("dmasound_setup: invalid catch radius, using default = %d\n", catchRadius);
- else
- catchRadius = ints[5];
- /* fall through */
- case 4:
- if (ints[4] < MIN_BUFFERS)
- printk("dmasound_setup: invalid number of read buffers, using default = %d\n",
- numReadBufs);
- else
- numReadBufs = ints[4];
- /* fall through */
- case 3:
- if ((size = ints[3]) < 256) /* check for small buffer specs */
- size <<= 10 ;
- if (size < MIN_BUFSIZE || size > MAX_BUFSIZE)
- printk("dmasound_setup: invalid read buffer size, using default = %d\n", readBufSize);
- else
- readBufSize = size;
- /* fall through */
-#else
case 3:
if ((ints[3] < 0) || (ints[3] > MAX_CATCH_RADIUS))
printk("dmasound_setup: invalid catch radius, using default = %d\n", catchRadius);
else
catchRadius = ints[3];
/* fall through */
-#endif
case 2:
if (ints[1] < MIN_BUFFERS)
printk("dmasound_setup: invalid number of buffers, using default = %d\n", numWriteBufs);
@@ -1830,9 +1546,6 @@ EXPORT_SYMBOL(dmasound_init);
EXPORT_SYMBOL(dmasound_deinit);
#endif
EXPORT_SYMBOL(dmasound_write_sq);
-#ifdef HAS_RECORD
-EXPORT_SYMBOL(dmasound_read_sq);
-#endif
EXPORT_SYMBOL(dmasound_catchRadius);
#ifdef HAS_8BIT_TABLES
EXPORT_SYMBOL(dmasound_ulaw2dma8);
diff --git a/sound/oss/dmasound/tas3001c.c b/sound/oss/dmasound/tas3001c.c
deleted file mode 100644
index 4b7dbdd2a438..000000000000
--- a/sound/oss/dmasound/tas3001c.c
+++ /dev/null
@@ -1,849 +0,0 @@
-/*
- * Driver for the i2c/i2s based TA3004 sound chip used
- * on some Apple hardware. Also known as "snapper".
- *
- * Tobias Sargeant <tobias.sargeant@bigpond.com>
- * Based upon, tas3001c.c by Christopher C. Chimelis <chris@debian.org>:
- *
- * TODO:
- * -----
- * * Enable control over input line 2 (is this connected?)
- * * Implement sleep support (at least mute everything and
- * * set gains to minimum during sleep)
- * * Look into some of Darwin's tweaks regarding the mute
- * * lines (delays & different behaviour on some HW)
- *
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/proc_fs.h>
-#include <linux/ioport.h>
-#include <linux/sysctl.h>
-#include <linux/types.h>
-#include <linux/i2c.h>
-#include <linux/init.h>
-#include <linux/soundcard.h>
-#include <linux/workqueue.h>
-#include <asm/uaccess.h>
-#include <asm/errno.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-
-#include "dmasound.h"
-#include "tas_common.h"
-#include "tas3001c.h"
-
-#include "tas_ioctl.h"
-
-#define TAS3001C_BIQUAD_FILTER_COUNT 6
-#define TAS3001C_BIQUAD_CHANNEL_COUNT 2
-
-#define VOL_DEFAULT (100 * 4 / 5)
-#define INPUT_DEFAULT (100 * 4 / 5)
-#define BASS_DEFAULT (100 / 2)
-#define TREBLE_DEFAULT (100 / 2)
-
-struct tas3001c_data_t {
- struct tas_data_t super;
- int device_id;
- int output_id;
- int speaker_id;
- struct tas_drce_t drce_state;
- struct work_struct change;
-};
-
-
-static const union tas_biquad_t
-tas3001c_eq_unity={
- .buf = { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 }
-};
-
-
-static inline unsigned char db_to_regval(short db) {
- int r=0;
-
- r=(db+0x59a0) / 0x60;
-
- if (r < 0x91) return 0x91;
- if (r > 0xef) return 0xef;
- return r;
-}
-
-static inline short quantize_db(short db) {
- return db_to_regval(db) * 0x60 - 0x59a0;
-}
-
-
-static inline int
-register_width(enum tas3001c_reg_t r)
-{
- switch(r) {
- case TAS3001C_REG_MCR:
- case TAS3001C_REG_TREBLE:
- case TAS3001C_REG_BASS:
- return 1;
-
- case TAS3001C_REG_DRC:
- return 2;
-
- case TAS3001C_REG_MIXER1:
- case TAS3001C_REG_MIXER2:
- return 3;
-
- case TAS3001C_REG_VOLUME:
- return 6;
-
- case TAS3001C_REG_LEFT_BIQUAD0:
- case TAS3001C_REG_LEFT_BIQUAD1:
- case TAS3001C_REG_LEFT_BIQUAD2:
- case TAS3001C_REG_LEFT_BIQUAD3:
- case TAS3001C_REG_LEFT_BIQUAD4:
- case TAS3001C_REG_LEFT_BIQUAD5:
- case TAS3001C_REG_LEFT_BIQUAD6:
-
- case TAS3001C_REG_RIGHT_BIQUAD0:
- case TAS3001C_REG_RIGHT_BIQUAD1:
- case TAS3001C_REG_RIGHT_BIQUAD2:
- case TAS3001C_REG_RIGHT_BIQUAD3:
- case TAS3001C_REG_RIGHT_BIQUAD4:
- case TAS3001C_REG_RIGHT_BIQUAD5:
- case TAS3001C_REG_RIGHT_BIQUAD6:
- return 15;
-
- default:
- return 0;
- }
-}
-
-static int
-tas3001c_write_register( struct tas3001c_data_t *self,
- enum tas3001c_reg_t reg_num,
- char *data,
- uint write_mode)
-{
- if (reg_num==TAS3001C_REG_MCR ||
- reg_num==TAS3001C_REG_BASS ||
- reg_num==TAS3001C_REG_TREBLE) {
- return tas_write_byte_register(&self->super,
- (uint)reg_num,
- *data,
- write_mode);
- } else {
- return tas_write_register(&self->super,
- (uint)reg_num,
- register_width(reg_num),
- data,
- write_mode);
- }
-}
-
-static int
-tas3001c_sync_register( struct tas3001c_data_t *self,
- enum tas3001c_reg_t reg_num)
-{
- if (reg_num==TAS3001C_REG_MCR ||
- reg_num==TAS3001C_REG_BASS ||
- reg_num==TAS3001C_REG_TREBLE) {
- return tas_sync_byte_register(&self->super,
- (uint)reg_num,
- register_width(reg_num));
- } else {
- return tas_sync_register(&self->super,
- (uint)reg_num,
- register_width(reg_num));
- }
-}
-
-static int
-tas3001c_read_register( struct tas3001c_data_t *self,
- enum tas3001c_reg_t reg_num,
- char *data,
- uint write_mode)
-{
- return tas_read_register(&self->super,
- (uint)reg_num,
- register_width(reg_num),
- data);
-}
-
-static inline int
-tas3001c_fast_load(struct tas3001c_data_t *self, int fast)
-{
- if (fast)
- self->super.shadow[TAS3001C_REG_MCR][0] |= 0x80;
- else
- self->super.shadow[TAS3001C_REG_MCR][0] &= 0x7f;
- return tas3001c_sync_register(self,TAS3001C_REG_MCR);
-}
-
-static uint
-tas3001c_supported_mixers(struct tas3001c_data_t *self)
-{
- return SOUND_MASK_VOLUME |
- SOUND_MASK_PCM |
- SOUND_MASK_ALTPCM |
- SOUND_MASK_TREBLE |
- SOUND_MASK_BASS;
-}
-
-static int
-tas3001c_mixer_is_stereo(struct tas3001c_data_t *self,int mixer)
-{
- switch(mixer) {
- case SOUND_MIXER_VOLUME:
- return 1;
- default:
- return 0;
- }
-}
-
-static uint
-tas3001c_stereo_mixers(struct tas3001c_data_t *self)
-{
- uint r=tas3001c_supported_mixers(self);
- uint i;
-
- for (i=1; i<SOUND_MIXER_NRDEVICES; i++)
- if (r&(1<<i) && !tas3001c_mixer_is_stereo(self,i))
- r &= ~(1<<i);
- return r;
-}
-
-static int
-tas3001c_get_mixer_level(struct tas3001c_data_t *self,int mixer,uint *level)
-{
- if (!self)
- return -1;
-
- *level=self->super.mixer[mixer];
-
- return 0;
-}
-
-static int
-tas3001c_set_mixer_level(struct tas3001c_data_t *self,int mixer,uint level)
-{
- int rc;
- tas_shadow_t *shadow;
-
- uint temp;
- uint offset=0;
-
- if (!self)
- return -1;
-
- shadow=self->super.shadow;
-
- if (!tas3001c_mixer_is_stereo(self,mixer))
- level = tas_mono_to_stereo(level);
-
- switch(mixer) {
- case SOUND_MIXER_VOLUME:
- temp = tas3001c_gain.master[level&0xff];
- shadow[TAS3001C_REG_VOLUME][0] = (temp >> 16) & 0xff;
- shadow[TAS3001C_REG_VOLUME][1] = (temp >> 8) & 0xff;
- shadow[TAS3001C_REG_VOLUME][2] = (temp >> 0) & 0xff;
- temp = tas3001c_gain.master[(level>>8)&0xff];
- shadow[TAS3001C_REG_VOLUME][3] = (temp >> 16) & 0xff;
- shadow[TAS3001C_REG_VOLUME][4] = (temp >> 8) & 0xff;
- shadow[TAS3001C_REG_VOLUME][5] = (temp >> 0) & 0xff;
- rc = tas3001c_sync_register(self,TAS3001C_REG_VOLUME);
- break;
- case SOUND_MIXER_ALTPCM:
- /* tas3001c_fast_load(self, 1); */
- level = tas_mono_to_stereo(level);
- temp = tas3001c_gain.mixer[level&0xff];
- shadow[TAS3001C_REG_MIXER2][offset+0] = (temp >> 16) & 0xff;
- shadow[TAS3001C_REG_MIXER2][offset+1] = (temp >> 8) & 0xff;
- shadow[TAS3001C_REG_MIXER2][offset+2] = (temp >> 0) & 0xff;
- rc = tas3001c_sync_register(self,TAS3001C_REG_MIXER2);
- /* tas3001c_fast_load(self, 0); */
- break;
- case SOUND_MIXER_PCM:
- /* tas3001c_fast_load(self, 1); */
- level = tas_mono_to_stereo(level);
- temp = tas3001c_gain.mixer[level&0xff];
- shadow[TAS3001C_REG_MIXER1][offset+0] = (temp >> 16) & 0xff;
- shadow[TAS3001C_REG_MIXER1][offset+1] = (temp >> 8) & 0xff;
- shadow[TAS3001C_REG_MIXER1][offset+2] = (temp >> 0) & 0xff;
- rc = tas3001c_sync_register(self,TAS3001C_REG_MIXER1);
- /* tas3001c_fast_load(self, 0); */
- break;
- case SOUND_MIXER_TREBLE:
- temp = tas3001c_gain.treble[level&0xff];
- shadow[TAS3001C_REG_TREBLE][0]=temp&0xff;
- rc = tas3001c_sync_register(self,TAS3001C_REG_TREBLE);
- break;
- case SOUND_MIXER_BASS:
- temp = tas3001c_gain.bass[level&0xff];
- shadow[TAS3001C_REG_BASS][0]=temp&0xff;
- rc = tas3001c_sync_register(self,TAS3001C_REG_BASS);
- break;
- default:
- rc = -1;
- break;
- }
- if (rc < 0)
- return rc;
- self->super.mixer[mixer]=level;
- return 0;
-}
-
-static int
-tas3001c_leave_sleep(struct tas3001c_data_t *self)
-{
- unsigned char mcr = (1<<6)+(2<<4)+(2<<2);
-
- if (!self)
- return -1;
-
- /* Make sure something answers on the i2c bus */
- if (tas3001c_write_register(self, TAS3001C_REG_MCR, &mcr,
- WRITE_NORMAL|FORCE_WRITE) < 0)
- return -1;
-
- tas3001c_fast_load(self, 1);
-
- (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD0);
- (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD1);
- (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD2);
- (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD3);
- (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD4);
- (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD5);
-
- (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD0);
- (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD1);
- (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD2);
- (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD3);
- (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD4);
- (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD5);
-
- tas3001c_fast_load(self, 0);
-
- (void)tas3001c_sync_register(self,TAS3001C_REG_BASS);
- (void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE);
- (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1);
- (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2);
- (void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME);
-
- return 0;
-}
-
-static int
-tas3001c_enter_sleep(struct tas3001c_data_t *self)
-{
- /* Stub for now, but I have the details on low-power mode */
- if (!self)
- return -1;
- return 0;
-}
-
-static int
-tas3001c_sync_biquad( struct tas3001c_data_t *self,
- u_int channel,
- u_int filter)
-{
- enum tas3001c_reg_t reg;
-
- if (channel >= TAS3001C_BIQUAD_CHANNEL_COUNT ||
- filter >= TAS3001C_BIQUAD_FILTER_COUNT) return -EINVAL;
-
- reg=( channel ? TAS3001C_REG_RIGHT_BIQUAD0 : TAS3001C_REG_LEFT_BIQUAD0 ) + filter;
-
- return tas3001c_sync_register(self,reg);
-}
-
-static int
-tas3001c_write_biquad_shadow( struct tas3001c_data_t *self,
- u_int channel,
- u_int filter,
- const union tas_biquad_t *biquad)
-{
- tas_shadow_t *shadow=self->super.shadow;
- enum tas3001c_reg_t reg;
-
- if (channel >= TAS3001C_BIQUAD_CHANNEL_COUNT ||
- filter >= TAS3001C_BIQUAD_FILTER_COUNT) return -EINVAL;
-
- reg=( channel ? TAS3001C_REG_RIGHT_BIQUAD0 : TAS3001C_REG_LEFT_BIQUAD0 ) + filter;
-
- SET_4_20(shadow[reg], 0,biquad->coeff.b0);
- SET_4_20(shadow[reg], 3,biquad->coeff.b1);
- SET_4_20(shadow[reg], 6,biquad->coeff.b2);
- SET_4_20(shadow[reg], 9,biquad->coeff.a1);
- SET_4_20(shadow[reg],12,biquad->coeff.a2);
-
- return 0;
-}
-
-static int
-tas3001c_write_biquad( struct tas3001c_data_t *self,
- u_int channel,
- u_int filter,
- const union tas_biquad_t *biquad)
-{
- int rc;
-
- rc=tas3001c_write_biquad_shadow(self, channel, filter, biquad);
- if (rc < 0) return rc;
-
- return tas3001c_sync_biquad(self, channel, filter);
-}
-
-static int
-tas3001c_write_biquad_list( struct tas3001c_data_t *self,
- u_int filter_count,
- u_int flags,
- struct tas_biquad_ctrl_t *biquads)
-{
- int i;
- int rc;
-
- if (flags & TAS_BIQUAD_FAST_LOAD) tas3001c_fast_load(self,1);
-
- for (i=0; i<filter_count; i++) {
- rc=tas3001c_write_biquad(self,
- biquads[i].channel,
- biquads[i].filter,
- &biquads[i].data);
- if (rc < 0) break;
- }
-
- if (flags & TAS_BIQUAD_FAST_LOAD) {
- tas3001c_fast_load(self,0);
-
- (void)tas3001c_sync_register(self,TAS3001C_REG_BASS);
- (void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE);
- (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1);
- (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2);
- (void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME);
- }
-
- return rc;
-}
-
-static int
-tas3001c_read_biquad( struct tas3001c_data_t *self,
- u_int channel,
- u_int filter,
- union tas_biquad_t *biquad)
-{
- tas_shadow_t *shadow=self->super.shadow;
- enum tas3001c_reg_t reg;
-
- if (channel >= TAS3001C_BIQUAD_CHANNEL_COUNT ||
- filter >= TAS3001C_BIQUAD_FILTER_COUNT) return -EINVAL;
-
- reg=( channel ? TAS3001C_REG_RIGHT_BIQUAD0 : TAS3001C_REG_LEFT_BIQUAD0 ) + filter;
-
- biquad->coeff.b0=GET_4_20(shadow[reg], 0);
- biquad->coeff.b1=GET_4_20(shadow[reg], 3);
- biquad->coeff.b2=GET_4_20(shadow[reg], 6);
- biquad->coeff.a1=GET_4_20(shadow[reg], 9);
- biquad->coeff.a2=GET_4_20(shadow[reg],12);
-
- return 0;
-}
-
-static int
-tas3001c_eq_rw( struct tas3001c_data_t *self,
- u_int cmd,
- u_long arg)
-{
- int rc;
- struct tas_biquad_ctrl_t biquad;
- void __user *argp = (void __user *)arg;
-
- if (copy_from_user(&biquad, argp, sizeof(struct tas_biquad_ctrl_t))) {
- return -EFAULT;
- }
-
- if (cmd & SIOC_IN) {
- rc=tas3001c_write_biquad(self, biquad.channel, biquad.filter, &biquad.data);
- if (rc != 0) return rc;
- }
-
- if (cmd & SIOC_OUT) {
- rc=tas3001c_read_biquad(self, biquad.channel, biquad.filter, &biquad.data);
- if (rc != 0) return rc;
-
- if (copy_to_user(argp, &biquad, sizeof(struct tas_biquad_ctrl_t))) {
- return -EFAULT;
- }
-
- }
- return 0;
-}
-
-static int
-tas3001c_eq_list_rw( struct tas3001c_data_t *self,
- u_int cmd,
- u_long arg)
-{
- int rc;
- int filter_count;
- int flags;
- int i,j;
- char sync_required[2][6];
- struct tas_biquad_ctrl_t biquad;
- struct tas_biquad_ctrl_list_t __user *argp = (void __user *)arg;
-
- memset(sync_required,0,sizeof(sync_required));
-
- if (copy_from_user(&filter_count, &argp->filter_count, sizeof(int)))
- return -EFAULT;
-
- if (copy_from_user(&flags, &argp->flags, sizeof(int)))
- return -EFAULT;
-
- if (cmd & SIOC_IN) {
- }
-
- for (i=0; i < filter_count; i++) {
- if (copy_from_user(&biquad, &argp->biquads[i],
- sizeof(struct tas_biquad_ctrl_t))) {
- return -EFAULT;
- }
-
- if (cmd & SIOC_IN) {
- sync_required[biquad.channel][biquad.filter]=1;
- rc=tas3001c_write_biquad_shadow(self, biquad.channel, biquad.filter, &biquad.data);
- if (rc != 0) return rc;
- }
-
- if (cmd & SIOC_OUT) {
- rc=tas3001c_read_biquad(self, biquad.channel, biquad.filter, &biquad.data);
- if (rc != 0) return rc;
-
- if (copy_to_user(&argp->biquads[i], &biquad,
- sizeof(struct tas_biquad_ctrl_t))) {
- return -EFAULT;
- }
- }
- }
-
- if (cmd & SIOC_IN) {
- if (flags & TAS_BIQUAD_FAST_LOAD) tas3001c_fast_load(self,1);
- for (i=0; i<2; i++) {
- for (j=0; j<6; j++) {
- if (sync_required[i][j]) {
- rc=tas3001c_sync_biquad(self, i, j);
- if (rc < 0) return rc;
- }
- }
- }
- if (flags & TAS_BIQUAD_FAST_LOAD) {
- tas3001c_fast_load(self,0);
- /* now we need to set up the mixers again,
- because leaving fast mode resets them. */
- (void)tas3001c_sync_register(self,TAS3001C_REG_BASS);
- (void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE);
- (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1);
- (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2);
- (void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME);
- }
- }
-
- return 0;
-}
-
-static int
-tas3001c_update_drce( struct tas3001c_data_t *self,
- int flags,
- struct tas_drce_t *drce)
-{
- tas_shadow_t *shadow;
- shadow=self->super.shadow;
-
- shadow[TAS3001C_REG_DRC][1] = 0xc1;
-
- if (flags & TAS_DRCE_THRESHOLD) {
- self->drce_state.threshold=quantize_db(drce->threshold);
- shadow[TAS3001C_REG_DRC][2] = db_to_regval(self->drce_state.threshold);
- }
-
- if (flags & TAS_DRCE_ENABLE) {
- self->drce_state.enable = drce->enable;
- }
-
- if (!self->drce_state.enable) {
- shadow[TAS3001C_REG_DRC][0] = 0xf0;
- }
-
-#ifdef DEBUG_DRCE
- printk("DRCE IOCTL: set [ ENABLE:%x THRESH:%x\n",
- self->drce_state.enable,
- self->drce_state.threshold);
-
- printk("DRCE IOCTL: reg [ %02x %02x ]\n",
- (unsigned char)shadow[TAS3001C_REG_DRC][0],
- (unsigned char)shadow[TAS3001C_REG_DRC][1]);
-#endif
-
- return tas3001c_sync_register(self, TAS3001C_REG_DRC);
-}
-
-static int
-tas3001c_drce_rw( struct tas3001c_data_t *self,
- u_int cmd,
- u_long arg)
-{
- int rc;
- struct tas_drce_ctrl_t drce_ctrl;
- void __user *argp = (void __user *)arg;
-
- if (copy_from_user(&drce_ctrl, argp, sizeof(struct tas_drce_ctrl_t)))
- return -EFAULT;
-
-#ifdef DEBUG_DRCE
- printk("DRCE IOCTL: input [ FLAGS:%x ENABLE:%x THRESH:%x\n",
- drce_ctrl.flags,
- drce_ctrl.data.enable,
- drce_ctrl.data.threshold);
-#endif
-
- if (cmd & SIOC_IN) {
- rc = tas3001c_update_drce(self, drce_ctrl.flags, &drce_ctrl.data);
- if (rc < 0)
- return rc;
- }
-
- if (cmd & SIOC_OUT) {
- if (drce_ctrl.flags & TAS_DRCE_ENABLE)
- drce_ctrl.data.enable = self->drce_state.enable;
-
- if (drce_ctrl.flags & TAS_DRCE_THRESHOLD)
- drce_ctrl.data.threshold = self->drce_state.threshold;
-
- if (copy_to_user(argp, &drce_ctrl,
- sizeof(struct tas_drce_ctrl_t))) {
- return -EFAULT;
- }
- }
-
- return 0;
-}
-
-static void
-tas3001c_update_device_parameters(struct tas3001c_data_t *self)
-{
- int i,j;
-
- if (!self) return;
-
- if (self->output_id == TAS_OUTPUT_HEADPHONES) {
- tas3001c_fast_load(self, 1);
-
- for (i=0; i<TAS3001C_BIQUAD_CHANNEL_COUNT; i++) {
- for (j=0; j<TAS3001C_BIQUAD_FILTER_COUNT; j++) {
- tas3001c_write_biquad(self, i, j, &tas3001c_eq_unity);
- }
- }
-
- tas3001c_fast_load(self, 0);
-
- (void)tas3001c_sync_register(self,TAS3001C_REG_BASS);
- (void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE);
- (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1);
- (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2);
- (void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME);
-
- return;
- }
-
- for (i=0; tas3001c_eq_prefs[i]; i++) {
- struct tas_eq_pref_t *eq = tas3001c_eq_prefs[i];
-
- if (eq->device_id == self->device_id &&
- (eq->output_id == 0 || eq->output_id == self->output_id) &&
- (eq->speaker_id == 0 || eq->speaker_id == self->speaker_id)) {
-
- tas3001c_update_drce(self, TAS_DRCE_ALL, eq->drce);
- tas3001c_write_biquad_list(self, eq->filter_count, TAS_BIQUAD_FAST_LOAD, eq->biquads);
-
- break;
- }
- }
-}
-
-static void
-tas3001c_device_change_handler(struct work_struct *work)
-{
- struct tas3001c_data_t *self;
- self = container_of(work, struct tas3001c_data_t, change);
- tas3001c_update_device_parameters(self);
-}
-
-static int
-tas3001c_output_device_change( struct tas3001c_data_t *self,
- int device_id,
- int output_id,
- int speaker_id)
-{
- self->device_id=device_id;
- self->output_id=output_id;
- self->speaker_id=speaker_id;
-
- schedule_work(&self->change);
- return 0;
-}
-
-static int
-tas3001c_device_ioctl( struct tas3001c_data_t *self,
- u_int cmd,
- u_long arg)
-{
- uint __user *argp = (void __user *)arg;
- switch (cmd) {
- case TAS_READ_EQ:
- case TAS_WRITE_EQ:
- return tas3001c_eq_rw(self, cmd, arg);
-
- case TAS_READ_EQ_LIST:
- case TAS_WRITE_EQ_LIST:
- return tas3001c_eq_list_rw(self, cmd, arg);
-
- case TAS_READ_EQ_FILTER_COUNT:
- put_user(TAS3001C_BIQUAD_FILTER_COUNT, argp);
- return 0;
-
- case TAS_READ_EQ_CHANNEL_COUNT:
- put_user(TAS3001C_BIQUAD_CHANNEL_COUNT, argp);
- return 0;
-
- case TAS_READ_DRCE:
- case TAS_WRITE_DRCE:
- return tas3001c_drce_rw(self, cmd, arg);
-
- case TAS_READ_DRCE_CAPS:
- put_user(TAS_DRCE_ENABLE | TAS_DRCE_THRESHOLD, argp);
- return 0;
-
- case TAS_READ_DRCE_MIN:
- case TAS_READ_DRCE_MAX: {
- struct tas_drce_ctrl_t drce_ctrl;
-
- if (copy_from_user(&drce_ctrl, argp,
- sizeof(struct tas_drce_ctrl_t))) {
- return -EFAULT;
- }
-
- if (drce_ctrl.flags & TAS_DRCE_THRESHOLD) {
- if (cmd == TAS_READ_DRCE_MIN) {
- drce_ctrl.data.threshold=-36<<8;
- } else {
- drce_ctrl.data.threshold=-6<<8;
- }
- }
-
- if (copy_to_user(argp, &drce_ctrl,
- sizeof(struct tas_drce_ctrl_t))) {
- return -EFAULT;
- }
- }
- }
-
- return -EINVAL;
-}
-
-static int
-tas3001c_init_mixer(struct tas3001c_data_t *self)
-{
- unsigned char mcr = (1<<6)+(2<<4)+(2<<2);
-
- /* Make sure something answers on the i2c bus */
- if (tas3001c_write_register(self, TAS3001C_REG_MCR, &mcr,
- WRITE_NORMAL|FORCE_WRITE) < 0)
- return -1;
-
- tas3001c_fast_load(self, 1);
-
- (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD0);
- (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD1);
- (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD2);
- (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD3);
- (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD4);
- (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD5);
- (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD6);
-
- (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD0);
- (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD1);
- (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD2);
- (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD3);
- (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD4);
- (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD5);
- (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD6);
-
- tas3001c_fast_load(self, 0);
-
- tas3001c_set_mixer_level(self, SOUND_MIXER_VOLUME, VOL_DEFAULT<<8 | VOL_DEFAULT);
- tas3001c_set_mixer_level(self, SOUND_MIXER_PCM, INPUT_DEFAULT<<8 | INPUT_DEFAULT);
- tas3001c_set_mixer_level(self, SOUND_MIXER_ALTPCM, 0);
-
- tas3001c_set_mixer_level(self, SOUND_MIXER_BASS, BASS_DEFAULT);
- tas3001c_set_mixer_level(self, SOUND_MIXER_TREBLE, TREBLE_DEFAULT);
-
- return 0;
-}
-
-static int
-tas3001c_uninit_mixer(struct tas3001c_data_t *self)
-{
- tas3001c_set_mixer_level(self, SOUND_MIXER_VOLUME, 0);
- tas3001c_set_mixer_level(self, SOUND_MIXER_PCM, 0);
- tas3001c_set_mixer_level(self, SOUND_MIXER_ALTPCM, 0);
-
- tas3001c_set_mixer_level(self, SOUND_MIXER_BASS, 0);
- tas3001c_set_mixer_level(self, SOUND_MIXER_TREBLE, 0);
-
- return 0;
-}
-
-static int
-tas3001c_init(struct i2c_client *client)
-{
- struct tas3001c_data_t *self;
- size_t sz = sizeof(*self) + (TAS3001C_REG_MAX*sizeof(tas_shadow_t));
- int i, j;
-
- self = kzalloc(sz, GFP_KERNEL);
- if (!self)
- return -ENOMEM;
-
- self->super.client = client;
- self->super.shadow = (tas_shadow_t *)(self+1);
- self->output_id = TAS_OUTPUT_HEADPHONES;
-
- dev_set_drvdata(&client->dev, self);
-
- for (i = 0; i < TAS3001C_BIQUAD_CHANNEL_COUNT; i++)
- for (j = 0; j < TAS3001C_BIQUAD_FILTER_COUNT; j++)
- tas3001c_write_biquad_shadow(self, i, j,
- &tas3001c_eq_unity);
-
- INIT_WORK(&self->change, tas3001c_device_change_handler);
- return 0;
-}
-
-static void
-tas3001c_uninit(struct tas3001c_data_t *self)
-{
- tas3001c_uninit_mixer(self);
- kfree(self);
-}
-
-struct tas_driver_hooks_t tas3001c_hooks = {
- .init = (tas_hook_init_t)tas3001c_init,
- .post_init = (tas_hook_post_init_t)tas3001c_init_mixer,
- .uninit = (tas_hook_uninit_t)tas3001c_uninit,
- .get_mixer_level = (tas_hook_get_mixer_level_t)tas3001c_get_mixer_level,
- .set_mixer_level = (tas_hook_set_mixer_level_t)tas3001c_set_mixer_level,
- .enter_sleep = (tas_hook_enter_sleep_t)tas3001c_enter_sleep,
- .leave_sleep = (tas_hook_leave_sleep_t)tas3001c_leave_sleep,
- .supported_mixers = (tas_hook_supported_mixers_t)tas3001c_supported_mixers,
- .mixer_is_stereo = (tas_hook_mixer_is_stereo_t)tas3001c_mixer_is_stereo,
- .stereo_mixers = (tas_hook_stereo_mixers_t)tas3001c_stereo_mixers,
- .output_device_change = (tas_hook_output_device_change_t)tas3001c_output_device_change,
- .device_ioctl = (tas_hook_device_ioctl_t)tas3001c_device_ioctl
-};
diff --git a/sound/oss/dmasound/tas3001c.h b/sound/oss/dmasound/tas3001c.h
deleted file mode 100644
index 3660da33a2db..000000000000
--- a/sound/oss/dmasound/tas3001c.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Header file for the i2c/i2s based TA3001c sound chip used
- * on some Apple hardware. Also known as "tumbler".
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive
- * for more details.
- *
- * Written by Christopher C. Chimelis <chris@debian.org>
- */
-
-#ifndef _TAS3001C_H_
-#define _TAS3001C_H_
-
-#include <linux/types.h>
-
-#include "tas_common.h"
-#include "tas_eq_prefs.h"
-
-/*
- * Macros that correspond to the registers that we write to
- * when setting the various values.
- */
-
-#define TAS3001C_VERSION "0.3"
-#define TAS3001C_DATE "20011214"
-
-#define I2C_DRIVERNAME_TAS3001C "TAS3001c driver V " TAS3001C_VERSION
-#define I2C_DRIVERID_TAS3001C (I2C_DRIVERID_TAS_BASE+0)
-
-extern struct tas_driver_hooks_t tas3001c_hooks;
-extern struct tas_gain_t tas3001c_gain;
-extern struct tas_eq_pref_t *tas3001c_eq_prefs[];
-
-enum tas3001c_reg_t {
- TAS3001C_REG_MCR = 0x01,
- TAS3001C_REG_DRC = 0x02,
-
- TAS3001C_REG_VOLUME = 0x04,
- TAS3001C_REG_TREBLE = 0x05,
- TAS3001C_REG_BASS = 0x06,
- TAS3001C_REG_MIXER1 = 0x07,
- TAS3001C_REG_MIXER2 = 0x08,
-
- TAS3001C_REG_LEFT_BIQUAD0 = 0x0a,
- TAS3001C_REG_LEFT_BIQUAD1 = 0x0b,
- TAS3001C_REG_LEFT_BIQUAD2 = 0x0c,
- TAS3001C_REG_LEFT_BIQUAD3 = 0x0d,
- TAS3001C_REG_LEFT_BIQUAD4 = 0x0e,
- TAS3001C_REG_LEFT_BIQUAD5 = 0x0f,
- TAS3001C_REG_LEFT_BIQUAD6 = 0x10,
-
- TAS3001C_REG_RIGHT_BIQUAD0 = 0x13,
- TAS3001C_REG_RIGHT_BIQUAD1 = 0x14,
- TAS3001C_REG_RIGHT_BIQUAD2 = 0x15,
- TAS3001C_REG_RIGHT_BIQUAD3 = 0x16,
- TAS3001C_REG_RIGHT_BIQUAD4 = 0x17,
- TAS3001C_REG_RIGHT_BIQUAD5 = 0x18,
- TAS3001C_REG_RIGHT_BIQUAD6 = 0x19,
-
- TAS3001C_REG_MAX = 0x20
-};
-
-#endif /* _TAS3001C_H_ */
diff --git a/sound/oss/dmasound/tas3001c_tables.c b/sound/oss/dmasound/tas3001c_tables.c
deleted file mode 100644
index 1768fa95f25b..000000000000
--- a/sound/oss/dmasound/tas3001c_tables.c
+++ /dev/null
@@ -1,375 +0,0 @@
-#include "tas_common.h"
-#include "tas_eq_prefs.h"
-
-static struct tas_drce_t eqp_0e_2_1_drce = {
- .enable = 1,
- .above = { .val = 3.0 * (1<<8), .expand = 0 },
- .below = { .val = 1.0 * (1<<8), .expand = 0 },
- .threshold = -15.33 * (1<<8),
- .energy = 2.4 * (1<<12),
- .attack = 0.013 * (1<<12),
- .decay = 0.212 * (1<<12),
-};
-
-static struct tas_biquad_ctrl_t eqp_0e_2_1_biquads[]={
- { .channel = 0, .filter = 0, .data = { .coeff = { 0x0FCAD3, 0xE06A58, 0x0FCAD3, 0xE06B09, 0x0F9657 } } },
- { .channel = 0, .filter = 1, .data = { .coeff = { 0x041731, 0x082E63, 0x041731, 0xFD8D08, 0x02CFBD } } },
- { .channel = 0, .filter = 2, .data = { .coeff = { 0x0FFDC7, 0xE0524C, 0x0FBFAA, 0xE0524C, 0x0FBD72 } } },
- { .channel = 0, .filter = 3, .data = { .coeff = { 0x0F3D35, 0xE228CA, 0x0EC7B2, 0xE228CA, 0x0E04E8 } } },
- { .channel = 0, .filter = 4, .data = { .coeff = { 0x0FCEBF, 0xE181C2, 0x0F2656, 0xE181C2, 0x0EF516 } } },
- { .channel = 0, .filter = 5, .data = { .coeff = { 0x0EC417, 0x073E22, 0x0B0633, 0x073E22, 0x09CA4A } } },
-
- { .channel = 1, .filter = 0, .data = { .coeff = { 0x0FCAD3, 0xE06A58, 0x0FCAD3, 0xE06B09, 0x0F9657 } } },
- { .channel = 1, .filter = 1, .data = { .coeff = { 0x041731, 0x082E63, 0x041731, 0xFD8D08, 0x02CFBD } } },
- { .channel = 1, .filter = 2, .data = { .coeff = { 0x0FFDC7, 0xE0524C, 0x0FBFAA, 0xE0524C, 0x0FBD72 } } },
- { .channel = 1, .filter = 3, .data = { .coeff = { 0x0F3D35, 0xE228CA, 0x0EC7B2, 0xE228CA, 0x0E04E8 } } },
- { .channel = 1, .filter = 4, .data = { .coeff = { 0x0FCEBF, 0xE181C2, 0x0F2656, 0xE181C2, 0x0EF516 } } },
- { .channel = 1, .filter = 5, .data = { .coeff = { 0x0EC417, 0x073E22, 0x0B0633, 0x073E22, 0x09CA4A } } },
-};
-
-static struct tas_eq_pref_t eqp_0e_2_1 = {
- .sample_rate = 44100,
- .device_id = 0x0e,
- .output_id = TAS_OUTPUT_EXTERNAL_SPKR,
- .speaker_id = 0x01,
-
- .drce = &eqp_0e_2_1_drce,
-
- .filter_count = 12,
- .biquads = eqp_0e_2_1_biquads
-};
-
-/* ======================================================================== */
-
-static struct tas_drce_t eqp_10_1_0_drce={
- .enable = 1,
- .above = { .val = 3.0 * (1<<8), .expand = 0 },
- .below = { .val = 1.0 * (1<<8), .expand = 0 },
- .threshold = -12.46 * (1<<8),
- .energy = 2.4 * (1<<12),
- .attack = 0.013 * (1<<12),
- .decay = 0.212 * (1<<12),
-};
-
-static struct tas_biquad_ctrl_t eqp_10_1_0_biquads[]={
- { .channel = 0, .filter = 0, .data = { .coeff = { 0x0F4A12, 0xE16BDA, 0x0F4A12, 0xE173F0, 0x0E9C3A } } },
- { .channel = 0, .filter = 1, .data = { .coeff = { 0x02DD54, 0x05BAA8, 0x02DD54, 0xF8001D, 0x037532 } } },
- { .channel = 0, .filter = 2, .data = { .coeff = { 0x0E2FC7, 0xE4D5DC, 0x0D7477, 0xE4D5DC, 0x0BA43F } } },
- { .channel = 0, .filter = 3, .data = { .coeff = { 0x0E7899, 0xE67CCA, 0x0D0E93, 0xE67CCA, 0x0B872D } } },
- { .channel = 0, .filter = 4, .data = { .coeff = { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } } },
- { .channel = 0, .filter = 5, .data = { .coeff = { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } } },
-
- { .channel = 1, .filter = 0, .data = { .coeff = { 0x0F4A12, 0xE16BDA, 0x0F4A12, 0xE173F0, 0x0E9C3A } } },
- { .channel = 1, .filter = 1, .data = { .coeff = { 0x02DD54, 0x05BAA8, 0x02DD54, 0xF8001D, 0x037532 } } },
- { .channel = 1, .filter = 2, .data = { .coeff = { 0x0E2FC7, 0xE4D5DC, 0x0D7477, 0xE4D5DC, 0x0BA43F } } },
- { .channel = 1, .filter = 3, .data = { .coeff = { 0x0E7899, 0xE67CCA, 0x0D0E93, 0xE67CCA, 0x0B872D } } },
- { .channel = 1, .filter = 4, .data = { .coeff = { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } } },
- { .channel = 1, .filter = 5, .data = { .coeff = { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } } },
-};
-
-static struct tas_eq_pref_t eqp_10_1_0 = {
- .sample_rate = 44100,
- .device_id = 0x10,
- .output_id = TAS_OUTPUT_INTERNAL_SPKR,
- .speaker_id = 0x00,
-
- .drce = &eqp_10_1_0_drce,
-
- .filter_count = 12,
- .biquads = eqp_10_1_0_biquads
-};
-
-/* ======================================================================== */
-
-static struct tas_drce_t eqp_15_2_1_drce={
- .enable = 1,
- .above = { .val = 3.0 * (1<<8), .expand = 0 },
- .below = { .val = 1.0 * (1<<8), .expand = 0 },
- .threshold = -15.33 * (1<<8),
- .energy = 2.4 * (1<<12),
- .attack = 0.013 * (1<<12),
- .decay = 0.212 * (1<<12),
-};
-
-static struct tas_biquad_ctrl_t eqp_15_2_1_biquads[]={
- { .channel = 0, .filter = 0, .data = { .coeff = { 0x0FE143, 0xE05204, 0x0FCCC5, 0xE05266, 0x0FAE6B } } },
- { .channel = 0, .filter = 1, .data = { .coeff = { 0x102383, 0xE03A03, 0x0FA325, 0xE03A03, 0x0FC6A8 } } },
- { .channel = 0, .filter = 2, .data = { .coeff = { 0x0FF2AB, 0xE06285, 0x0FB20A, 0xE06285, 0x0FA4B5 } } },
- { .channel = 0, .filter = 3, .data = { .coeff = { 0x0F544D, 0xE35971, 0x0D8F3A, 0xE35971, 0x0CE388 } } },
- { .channel = 0, .filter = 4, .data = { .coeff = { 0x13E1D3, 0xF3ECB5, 0x042227, 0xF3ECB5, 0x0803FA } } },
- { .channel = 0, .filter = 5, .data = { .coeff = { 0x0AC119, 0x034181, 0x078AB1, 0x034181, 0x024BCA } } },
-
- { .channel = 1, .filter = 0, .data = { .coeff = { 0x0FE143, 0xE05204, 0x0FCCC5, 0xE05266, 0x0FAE6B } } },
- { .channel = 1, .filter = 1, .data = { .coeff = { 0x102383, 0xE03A03, 0x0FA325, 0xE03A03, 0x0FC6A8 } } },
- { .channel = 1, .filter = 2, .data = { .coeff = { 0x0FF2AB, 0xE06285, 0x0FB20A, 0xE06285, 0x0FA4B5 } } },
- { .channel = 1, .filter = 3, .data = { .coeff = { 0x0F544D, 0xE35971, 0x0D8F3A, 0xE35971, 0x0CE388 } } },
- { .channel = 1, .filter = 4, .data = { .coeff = { 0x13E1D3, 0xF3ECB5, 0x042227, 0xF3ECB5, 0x0803FA } } },
- { .channel = 1, .filter = 5, .data = { .coeff = { 0x0AC119, 0x034181, 0x078AB1, 0x034181, 0x024BCA } } },
-};
-
-static struct tas_eq_pref_t eqp_15_2_1 = {
- .sample_rate = 44100,
- .device_id = 0x15,
- .output_id = TAS_OUTPUT_EXTERNAL_SPKR,
- .speaker_id = 0x01,
-
- .drce = &eqp_15_2_1_drce,
-
- .filter_count = 12,
- .biquads = eqp_15_2_1_biquads
-};
-
-/* ======================================================================== */
-
-static struct tas_drce_t eqp_15_1_0_drce={
- .enable = 1,
- .above = { .val = 3.0 * (1<<8), .expand = 0 },
- .below = { .val = 1.0 * (1<<8), .expand = 0 },
- .threshold = 0.0 * (1<<8),
- .energy = 2.4 * (1<<12),
- .attack = 0.013 * (1<<12),
- .decay = 0.212 * (1<<12),
-};
-
-static struct tas_biquad_ctrl_t eqp_15_1_0_biquads[]={
- { .channel = 0, .filter = 0, .data = { .coeff = { 0x0FAD08, 0xE0A5EF, 0x0FAD08, 0xE0A79D, 0x0F5BBE } } },
- { .channel = 0, .filter = 1, .data = { .coeff = { 0x04B38D, 0x09671B, 0x04B38D, 0x000F71, 0x02BEC5 } } },
- { .channel = 0, .filter = 2, .data = { .coeff = { 0x0FDD32, 0xE0A56F, 0x0F8A69, 0xE0A56F, 0x0F679C } } },
- { .channel = 0, .filter = 3, .data = { .coeff = { 0x0FD284, 0xE135FB, 0x0F2161, 0xE135FB, 0x0EF3E5 } } },
- { .channel = 0, .filter = 4, .data = { .coeff = { 0x0E81B1, 0xE6283F, 0x0CE49D, 0xE6283F, 0x0B664F } } },
- { .channel = 0, .filter = 5, .data = { .coeff = { 0x0F2D62, 0xE98797, 0x0D1E19, 0xE98797, 0x0C4B7B } } },
-
- { .channel = 1, .filter = 0, .data = { .coeff = { 0x0FAD08, 0xE0A5EF, 0x0FAD08, 0xE0A79D, 0x0F5BBE } } },
- { .channel = 1, .filter = 1, .data = { .coeff = { 0x04B38D, 0x09671B, 0x04B38D, 0x000F71, 0x02BEC5 } } },
- { .channel = 1, .filter = 2, .data = { .coeff = { 0x0FDD32, 0xE0A56F, 0x0F8A69, 0xE0A56F, 0x0F679C } } },
- { .channel = 1, .filter = 3, .data = { .coeff = { 0x0FD284, 0xE135FB, 0x0F2161, 0xE135FB, 0x0EF3E5 } } },
- { .channel = 1, .filter = 4, .data = { .coeff = { 0x0E81B1, 0xE6283F, 0x0CE49D, 0xE6283F, 0x0B664F } } },
- { .channel = 1, .filter = 5, .data = { .coeff = { 0x0F2D62, 0xE98797, 0x0D1E19, 0xE98797, 0x0C4B7B } } },
-};
-
-static struct tas_eq_pref_t eqp_15_1_0 = {
- .sample_rate = 44100,
- .device_id = 0x15,
- .output_id = TAS_OUTPUT_INTERNAL_SPKR,
- .speaker_id = 0x00,
-
- .drce = &eqp_15_1_0_drce,
-
- .filter_count = 12,
- .biquads = eqp_15_1_0_biquads
-};
-
-/* ======================================================================== */
-
-static struct tas_drce_t eqp_0f_2_1_drce={
- .enable = 1,
- .above = { .val = 3.0 * (1<<8), .expand = 0 },
- .below = { .val = 1.0 * (1<<8), .expand = 0 },
- .threshold = -15.33 * (1<<8),
- .energy = 2.4 * (1<<12),
- .attack = 0.013 * (1<<12),
- .decay = 0.212 * (1<<12),
-};
-
-static struct tas_biquad_ctrl_t eqp_0f_2_1_biquads[]={
- { .channel = 0, .filter = 0, .data = { .coeff = { 0x0FE143, 0xE05204, 0x0FCCC5, 0xE05266, 0x0FAE6B } } },
- { .channel = 0, .filter = 1, .data = { .coeff = { 0x102383, 0xE03A03, 0x0FA325, 0xE03A03, 0x0FC6A8 } } },
- { .channel = 0, .filter = 2, .data = { .coeff = { 0x0FF2AB, 0xE06285, 0x0FB20A, 0xE06285, 0x0FA4B5 } } },
- { .channel = 0, .filter = 3, .data = { .coeff = { 0x0F544D, 0xE35971, 0x0D8F3A, 0xE35971, 0x0CE388 } } },
- { .channel = 0, .filter = 4, .data = { .coeff = { 0x13E1D3, 0xF3ECB5, 0x042227, 0xF3ECB5, 0x0803FA } } },
- { .channel = 0, .filter = 5, .data = { .coeff = { 0x0AC119, 0x034181, 0x078AB1, 0x034181, 0x024BCA } } },
-
- { .channel = 1, .filter = 0, .data = { .coeff = { 0x0FE143, 0xE05204, 0x0FCCC5, 0xE05266, 0x0FAE6B } } },
- { .channel = 1, .filter = 1, .data = { .coeff = { 0x102383, 0xE03A03, 0x0FA325, 0xE03A03, 0x0FC6A8 } } },
- { .channel = 1, .filter = 2, .data = { .coeff = { 0x0FF2AB, 0xE06285, 0x0FB20A, 0xE06285, 0x0FA4B5 } } },
- { .channel = 1, .filter = 3, .data = { .coeff = { 0x0F544D, 0xE35971, 0x0D8F3A, 0xE35971, 0x0CE388 } } },
- { .channel = 1, .filter = 4, .data = { .coeff = { 0x13E1D3, 0xF3ECB5, 0x042227, 0xF3ECB5, 0x0803FA } } },
- { .channel = 1, .filter = 5, .data = { .coeff = { 0x0AC119, 0x034181, 0x078AB1, 0x034181, 0x024BCA } } },
-};
-
-static struct tas_eq_pref_t eqp_0f_2_1 = {
- .sample_rate = 44100,
- .device_id = 0x0f,
- .output_id = TAS_OUTPUT_EXTERNAL_SPKR,
- .speaker_id = 0x01,
-
- .drce = &eqp_0f_2_1_drce,
-
- .filter_count = 12,
- .biquads = eqp_0f_2_1_biquads
-};
-
-/* ======================================================================== */
-
-static struct tas_drce_t eqp_0f_1_0_drce={
- .enable = 1,
- .above = { .val = 3.0 * (1<<8), .expand = 0 },
- .below = { .val = 1.0 * (1<<8), .expand = 0 },
- .threshold = -15.33 * (1<<8),
- .energy = 2.4 * (1<<12),
- .attack = 0.013 * (1<<12),
- .decay = 0.212 * (1<<12),
-};
-
-static struct tas_biquad_ctrl_t eqp_0f_1_0_biquads[]={
- { .channel = 0, .filter = 0, .data = { .coeff = { 0x0FCAD3, 0xE06A58, 0x0FCAD3, 0xE06B09, 0x0F9657 } } },
- { .channel = 0, .filter = 1, .data = { .coeff = { 0x041731, 0x082E63, 0x041731, 0xFD8D08, 0x02CFBD } } },
- { .channel = 0, .filter = 2, .data = { .coeff = { 0x0FFDC7, 0xE0524C, 0x0FBFAA, 0xE0524C, 0x0FBD72 } } },
- { .channel = 0, .filter = 3, .data = { .coeff = { 0x0F3D35, 0xE228CA, 0x0EC7B2, 0xE228CA, 0x0E04E8 } } },
- { .channel = 0, .filter = 4, .data = { .coeff = { 0x0FCEBF, 0xE181C2, 0x0F2656, 0xE181C2, 0x0EF516 } } },
- { .channel = 0, .filter = 5, .data = { .coeff = { 0x0EC417, 0x073E22, 0x0B0633, 0x073E22, 0x09CA4A } } },
-
- { .channel = 1, .filter = 0, .data = { .coeff = { 0x0FCAD3, 0xE06A58, 0x0FCAD3, 0xE06B09, 0x0F9657 } } },
- { .channel = 1, .filter = 1, .data = { .coeff = { 0x041731, 0x082E63, 0x041731, 0xFD8D08, 0x02CFBD } } },
- { .channel = 1, .filter = 2, .data = { .coeff = { 0x0FFDC7, 0xE0524C, 0x0FBFAA, 0xE0524C, 0x0FBD72 } } },
- { .channel = 1, .filter = 3, .data = { .coeff = { 0x0F3D35, 0xE228CA, 0x0EC7B2, 0xE228CA, 0x0E04E8 } } },
- { .channel = 1, .filter = 4, .data = { .coeff = { 0x0FCEBF, 0xE181C2, 0x0F2656, 0xE181C2, 0x0EF516 } } },
- { .channel = 1, .filter = 5, .data = { .coeff = { 0x0EC417, 0x073E22, 0x0B0633, 0x073E22, 0x09CA4A } } },
-};
-
-static struct tas_eq_pref_t eqp_0f_1_0 = {
- .sample_rate = 44100,
- .device_id = 0x0f,
- .output_id = TAS_OUTPUT_INTERNAL_SPKR,
- .speaker_id = 0x00,
-
- .drce = &eqp_0f_1_0_drce,
-
- .filter_count = 12,
- .biquads = eqp_0f_1_0_biquads
-};
-
-/* ======================================================================== */
-
-static uint tas3001c_master_tab[]={
- 0x0, 0x75, 0x9c, 0xbb,
- 0xdb, 0xfb, 0x11e, 0x143,
- 0x16b, 0x196, 0x1c3, 0x1f5,
- 0x229, 0x263, 0x29f, 0x2e1,
- 0x328, 0x373, 0x3c5, 0x41b,
- 0x478, 0x4dc, 0x547, 0x5b8,
- 0x633, 0x6b5, 0x740, 0x7d5,
- 0x873, 0x91c, 0x9d2, 0xa92,
- 0xb5e, 0xc39, 0xd22, 0xe19,
- 0xf20, 0x1037, 0x1161, 0x129e,
- 0x13ed, 0x1551, 0x16ca, 0x185d,
- 0x1a08, 0x1bcc, 0x1dac, 0x1fa7,
- 0x21c1, 0x23fa, 0x2655, 0x28d6,
- 0x2b7c, 0x2e4a, 0x3141, 0x3464,
- 0x37b4, 0x3b35, 0x3ee9, 0x42d3,
- 0x46f6, 0x4b53, 0x4ff0, 0x54ce,
- 0x59f2, 0x5f5f, 0x6519, 0x6b24,
- 0x7183, 0x783c, 0x7f53, 0x86cc,
- 0x8ead, 0x96fa, 0x9fba, 0xa8f2,
- 0xb2a7, 0xbce1, 0xc7a5, 0xd2fa,
- 0xdee8, 0xeb75, 0xf8aa, 0x1068e,
- 0x1152a, 0x12487, 0x134ad, 0x145a5,
- 0x1577b, 0x16a37, 0x17df5, 0x192bd,
- 0x1a890, 0x1bf7b, 0x1d78d, 0x1f0d1,
- 0x20b55, 0x22727, 0x24456, 0x262f2,
- 0x2830b
-};
-
-static uint tas3001c_mixer_tab[]={
- 0x0, 0x748, 0x9be, 0xbaf,
- 0xda4, 0xfb1, 0x11de, 0x1431,
- 0x16ad, 0x1959, 0x1c37, 0x1f4b,
- 0x2298, 0x2628, 0x29fb, 0x2e12,
- 0x327d, 0x3734, 0x3c47, 0x41b4,
- 0x4787, 0x4dbe, 0x546d, 0x5b86,
- 0x632e, 0x6b52, 0x7400, 0x7d54,
- 0x873b, 0x91c6, 0x9d1a, 0xa920,
- 0xb5e5, 0xc38c, 0xd21b, 0xe18f,
- 0xf1f5, 0x1036a, 0x1160f, 0x129d6,
- 0x13ed0, 0x1550c, 0x16ca0, 0x185c9,
- 0x1a07b, 0x1bcc3, 0x1dab9, 0x1fa75,
- 0x21c0f, 0x23fa3, 0x26552, 0x28d64,
- 0x2b7c9, 0x2e4a2, 0x31411, 0x3463b,
- 0x37b44, 0x3b353, 0x3ee94, 0x42d30,
- 0x46f55, 0x4b533, 0x4fefc, 0x54ce5,
- 0x59f25, 0x5f5f6, 0x65193, 0x6b23c,
- 0x71835, 0x783c3, 0x7f52c, 0x86cc0,
- 0x8eacc, 0x96fa5, 0x9fba0, 0xa8f1a,
- 0xb2a71, 0xbce0a, 0xc7a4a, 0xd2fa0,
- 0xdee7b, 0xeb752, 0xf8a9f, 0x1068e4,
- 0x1152a3, 0x12486a, 0x134ac8, 0x145a55,
- 0x1577ac, 0x16a370, 0x17df51, 0x192bc2,
- 0x1a88f8, 0x1bf7b7, 0x1d78c9, 0x1f0d04,
- 0x20b542, 0x227268, 0x244564, 0x262f26,
- 0x2830af
-};
-
-static uint tas3001c_treble_tab[]={
- 0x96, 0x95, 0x95, 0x94,
- 0x93, 0x92, 0x92, 0x91,
- 0x90, 0x90, 0x8f, 0x8e,
- 0x8d, 0x8d, 0x8c, 0x8b,
- 0x8a, 0x8a, 0x89, 0x88,
- 0x88, 0x87, 0x86, 0x85,
- 0x85, 0x84, 0x83, 0x83,
- 0x82, 0x81, 0x80, 0x80,
- 0x7f, 0x7e, 0x7e, 0x7d,
- 0x7c, 0x7b, 0x7b, 0x7a,
- 0x79, 0x78, 0x78, 0x77,
- 0x76, 0x76, 0x75, 0x74,
- 0x73, 0x73, 0x72, 0x71,
- 0x71, 0x70, 0x6e, 0x6d,
- 0x6d, 0x6c, 0x6b, 0x6a,
- 0x69, 0x68, 0x67, 0x66,
- 0x65, 0x63, 0x62, 0x62,
- 0x60, 0x5f, 0x5d, 0x5c,
- 0x5a, 0x58, 0x56, 0x55,
- 0x53, 0x51, 0x4f, 0x4c,
- 0x4a, 0x48, 0x45, 0x43,
- 0x40, 0x3d, 0x3a, 0x37,
- 0x35, 0x32, 0x2e, 0x2a,
- 0x27, 0x22, 0x1e, 0x1a,
- 0x15, 0x11, 0xc, 0x7,
- 0x1
-};
-
-static uint tas3001c_bass_tab[]={
- 0x86, 0x83, 0x81, 0x7f,
- 0x7d, 0x7b, 0x79, 0x78,
- 0x76, 0x75, 0x74, 0x72,
- 0x71, 0x6f, 0x6e, 0x6d,
- 0x6c, 0x6b, 0x69, 0x67,
- 0x65, 0x64, 0x61, 0x60,
- 0x5e, 0x5d, 0x5c, 0x5b,
- 0x5a, 0x59, 0x58, 0x57,
- 0x56, 0x55, 0x55, 0x54,
- 0x53, 0x52, 0x50, 0x4f,
- 0x4d, 0x4c, 0x4b, 0x49,
- 0x47, 0x45, 0x44, 0x42,
- 0x41, 0x3f, 0x3e, 0x3d,
- 0x3c, 0x3b, 0x39, 0x38,
- 0x37, 0x36, 0x35, 0x34,
- 0x33, 0x31, 0x30, 0x2f,
- 0x2e, 0x2c, 0x2b, 0x2b,
- 0x29, 0x28, 0x27, 0x26,
- 0x25, 0x24, 0x22, 0x21,
- 0x20, 0x1e, 0x1c, 0x19,
- 0x18, 0x18, 0x17, 0x16,
- 0x15, 0x14, 0x13, 0x12,
- 0x11, 0x10, 0xf, 0xe,
- 0xd, 0xb, 0xa, 0x9,
- 0x8, 0x6, 0x4, 0x2,
- 0x1
-};
-
-struct tas_gain_t tas3001c_gain = {
- .master = tas3001c_master_tab,
- .treble = tas3001c_treble_tab,
- .bass = tas3001c_bass_tab,
- .mixer = tas3001c_mixer_tab
-};
-
-struct tas_eq_pref_t *tas3001c_eq_prefs[]={
- &eqp_0e_2_1,
- &eqp_10_1_0,
- &eqp_15_2_1,
- &eqp_15_1_0,
- &eqp_0f_2_1,
- &eqp_0f_1_0,
- NULL
-};
diff --git a/sound/oss/dmasound/tas3004.c b/sound/oss/dmasound/tas3004.c
deleted file mode 100644
index 678bf0ff6da2..000000000000
--- a/sound/oss/dmasound/tas3004.c
+++ /dev/null
@@ -1,1138 +0,0 @@
-/*
- * Driver for the i2c/i2s based TA3004 sound chip used
- * on some Apple hardware. Also known as "snapper".
- *
- * Tobias Sargeant <tobias.sargeant@bigpond.com>
- * Based upon tas3001c.c by Christopher C. Chimelis <chris@debian.org>:
- *
- * Input support by Renzo Davoli <renzo@cs.unibo.it>
- *
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/proc_fs.h>
-#include <linux/ioport.h>
-#include <linux/sysctl.h>
-#include <linux/types.h>
-#include <linux/i2c.h>
-#include <linux/init.h>
-#include <linux/soundcard.h>
-#include <linux/interrupt.h>
-#include <linux/workqueue.h>
-
-#include <asm/uaccess.h>
-#include <asm/errno.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-
-#include "dmasound.h"
-#include "tas_common.h"
-#include "tas3004.h"
-
-#include "tas_ioctl.h"
-
-/* #define DEBUG_DRCE */
-
-#define TAS3004_BIQUAD_FILTER_COUNT 7
-#define TAS3004_BIQUAD_CHANNEL_COUNT 2
-
-#define VOL_DEFAULT (100 * 4 / 5)
-#define INPUT_DEFAULT (100 * 4 / 5)
-#define BASS_DEFAULT (100 / 2)
-#define TREBLE_DEFAULT (100 / 2)
-
-struct tas3004_data_t {
- struct tas_data_t super;
- int device_id;
- int output_id;
- int speaker_id;
- struct tas_drce_t drce_state;
- struct work_struct change;
-};
-
-#define MAKE_TIME(sec,usec) (((sec)<<12) + (50000+(usec/10)*(1<<12))/100000)
-
-#define MAKE_RATIO(i,f) (((i)<<8) + ((500+(f)*(1<<8))/1000))
-
-
-static const union tas_biquad_t tas3004_eq_unity = {
- .buf = { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 },
-};
-
-
-static const struct tas_drce_t tas3004_drce_min = {
- .enable = 1,
- .above = { .val = MAKE_RATIO(16,0), .expand = 0 },
- .below = { .val = MAKE_RATIO(2,0), .expand = 0 },
- .threshold = -0x59a0,
- .energy = MAKE_TIME(0, 1700),
- .attack = MAKE_TIME(0, 1700),
- .decay = MAKE_TIME(0, 1700),
-};
-
-
-static const struct tas_drce_t tas3004_drce_max = {
- .enable = 1,
- .above = { .val = MAKE_RATIO(1,500), .expand = 1 },
- .below = { .val = MAKE_RATIO(2,0), .expand = 1 },
- .threshold = -0x0,
- .energy = MAKE_TIME(2,400000),
- .attack = MAKE_TIME(2,400000),
- .decay = MAKE_TIME(2,400000),
-};
-
-
-static const unsigned short time_constants[]={
- MAKE_TIME(0, 1700),
- MAKE_TIME(0, 3500),
- MAKE_TIME(0, 6700),
- MAKE_TIME(0, 13000),
- MAKE_TIME(0, 26000),
- MAKE_TIME(0, 53000),
- MAKE_TIME(0,106000),
- MAKE_TIME(0,212000),
- MAKE_TIME(0,425000),
- MAKE_TIME(0,850000),
- MAKE_TIME(1,700000),
- MAKE_TIME(2,400000),
-};
-
-static const unsigned short above_threshold_compression_ratio[]={
- MAKE_RATIO( 1, 70),
- MAKE_RATIO( 1,140),
- MAKE_RATIO( 1,230),
- MAKE_RATIO( 1,330),
- MAKE_RATIO( 1,450),
- MAKE_RATIO( 1,600),
- MAKE_RATIO( 1,780),
- MAKE_RATIO( 2, 0),
- MAKE_RATIO( 2,290),
- MAKE_RATIO( 2,670),
- MAKE_RATIO( 3,200),
- MAKE_RATIO( 4, 0),
- MAKE_RATIO( 5,330),
- MAKE_RATIO( 8, 0),
- MAKE_RATIO(16, 0),
-};
-
-static const unsigned short above_threshold_expansion_ratio[]={
- MAKE_RATIO(1, 60),
- MAKE_RATIO(1,130),
- MAKE_RATIO(1,190),
- MAKE_RATIO(1,250),
- MAKE_RATIO(1,310),
- MAKE_RATIO(1,380),
- MAKE_RATIO(1,440),
- MAKE_RATIO(1,500)
-};
-
-static const unsigned short below_threshold_compression_ratio[]={
- MAKE_RATIO(1, 70),
- MAKE_RATIO(1,140),
- MAKE_RATIO(1,230),
- MAKE_RATIO(1,330),
- MAKE_RATIO(1,450),
- MAKE_RATIO(1,600),
- MAKE_RATIO(1,780),
- MAKE_RATIO(2, 0)
-};
-
-static const unsigned short below_threshold_expansion_ratio[]={
- MAKE_RATIO(1, 60),
- MAKE_RATIO(1,130),
- MAKE_RATIO(1,190),
- MAKE_RATIO(1,250),
- MAKE_RATIO(1,310),
- MAKE_RATIO(1,380),
- MAKE_RATIO(1,440),
- MAKE_RATIO(1,500),
- MAKE_RATIO(1,560),
- MAKE_RATIO(1,630),
- MAKE_RATIO(1,690),
- MAKE_RATIO(1,750),
- MAKE_RATIO(1,810),
- MAKE_RATIO(1,880),
- MAKE_RATIO(1,940),
- MAKE_RATIO(2, 0)
-};
-
-static inline int
-search( unsigned short val,
- const unsigned short *arr,
- const int arrsize) {
- /*
- * This could be a binary search, but for small tables,
- * a linear search is likely to be faster
- */
-
- int i;
-
- for (i=0; i < arrsize; i++)
- if (arr[i] >= val)
- goto _1;
- return arrsize-1;
- _1:
- if (i == 0)
- return 0;
- return (arr[i]-val < val-arr[i-1]) ? i : i-1;
-}
-
-#define SEARCH(a, b) search(a, b, ARRAY_SIZE(b))
-
-static inline int
-time_index(unsigned short time)
-{
- return SEARCH(time, time_constants);
-}
-
-
-static inline int
-above_threshold_compression_index(unsigned short ratio)
-{
- return SEARCH(ratio, above_threshold_compression_ratio);
-}
-
-
-static inline int
-above_threshold_expansion_index(unsigned short ratio)
-{
- return SEARCH(ratio, above_threshold_expansion_ratio);
-}
-
-
-static inline int
-below_threshold_compression_index(unsigned short ratio)
-{
- return SEARCH(ratio, below_threshold_compression_ratio);
-}
-
-
-static inline int
-below_threshold_expansion_index(unsigned short ratio)
-{
- return SEARCH(ratio, below_threshold_expansion_ratio);
-}
-
-static inline unsigned char db_to_regval(short db) {
- int r=0;
-
- r=(db+0x59a0) / 0x60;
-
- if (r < 0x91) return 0x91;
- if (r > 0xef) return 0xef;
- return r;
-}
-
-static inline short quantize_db(short db)
-{
- return db_to_regval(db) * 0x60 - 0x59a0;
-}
-
-static inline int
-register_width(enum tas3004_reg_t r)
-{
- switch(r) {
- case TAS3004_REG_MCR:
- case TAS3004_REG_TREBLE:
- case TAS3004_REG_BASS:
- case TAS3004_REG_ANALOG_CTRL:
- case TAS3004_REG_TEST1:
- case TAS3004_REG_TEST2:
- case TAS3004_REG_MCR2:
- return 1;
-
- case TAS3004_REG_LEFT_LOUD_BIQUAD_GAIN:
- case TAS3004_REG_RIGHT_LOUD_BIQUAD_GAIN:
- return 3;
-
- case TAS3004_REG_DRC:
- case TAS3004_REG_VOLUME:
- return 6;
-
- case TAS3004_REG_LEFT_MIXER:
- case TAS3004_REG_RIGHT_MIXER:
- return 9;
-
- case TAS3004_REG_TEST:
- return 10;
-
- case TAS3004_REG_LEFT_BIQUAD0:
- case TAS3004_REG_LEFT_BIQUAD1:
- case TAS3004_REG_LEFT_BIQUAD2:
- case TAS3004_REG_LEFT_BIQUAD3:
- case TAS3004_REG_LEFT_BIQUAD4:
- case TAS3004_REG_LEFT_BIQUAD5:
- case TAS3004_REG_LEFT_BIQUAD6:
-
- case TAS3004_REG_RIGHT_BIQUAD0:
- case TAS3004_REG_RIGHT_BIQUAD1:
- case TAS3004_REG_RIGHT_BIQUAD2:
- case TAS3004_REG_RIGHT_BIQUAD3:
- case TAS3004_REG_RIGHT_BIQUAD4:
- case TAS3004_REG_RIGHT_BIQUAD5:
- case TAS3004_REG_RIGHT_BIQUAD6:
-
- case TAS3004_REG_LEFT_LOUD_BIQUAD:
- case TAS3004_REG_RIGHT_LOUD_BIQUAD:
- return 15;
-
- default:
- return 0;
- }
-}
-
-static int
-tas3004_write_register( struct tas3004_data_t *self,
- enum tas3004_reg_t reg_num,
- char *data,
- uint write_mode)
-{
- if (reg_num==TAS3004_REG_MCR ||
- reg_num==TAS3004_REG_BASS ||
- reg_num==TAS3004_REG_TREBLE ||
- reg_num==TAS3004_REG_ANALOG_CTRL) {
- return tas_write_byte_register(&self->super,
- (uint)reg_num,
- *data,
- write_mode);
- } else {
- return tas_write_register(&self->super,
- (uint)reg_num,
- register_width(reg_num),
- data,
- write_mode);
- }
-}
-
-static int
-tas3004_sync_register( struct tas3004_data_t *self,
- enum tas3004_reg_t reg_num)
-{
- if (reg_num==TAS3004_REG_MCR ||
- reg_num==TAS3004_REG_BASS ||
- reg_num==TAS3004_REG_TREBLE ||
- reg_num==TAS3004_REG_ANALOG_CTRL) {
- return tas_sync_byte_register(&self->super,
- (uint)reg_num,
- register_width(reg_num));
- } else {
- return tas_sync_register(&self->super,
- (uint)reg_num,
- register_width(reg_num));
- }
-}
-
-static int
-tas3004_read_register( struct tas3004_data_t *self,
- enum tas3004_reg_t reg_num,
- char *data,
- uint write_mode)
-{
- return tas_read_register(&self->super,
- (uint)reg_num,
- register_width(reg_num),
- data);
-}
-
-static inline int
-tas3004_fast_load(struct tas3004_data_t *self, int fast)
-{
- if (fast)
- self->super.shadow[TAS3004_REG_MCR][0] |= 0x80;
- else
- self->super.shadow[TAS3004_REG_MCR][0] &= 0x7f;
- return tas3004_sync_register(self,TAS3004_REG_MCR);
-}
-
-static uint
-tas3004_supported_mixers(struct tas3004_data_t *self)
-{
- return SOUND_MASK_VOLUME |
- SOUND_MASK_PCM |
- SOUND_MASK_ALTPCM |
- SOUND_MASK_IMIX |
- SOUND_MASK_TREBLE |
- SOUND_MASK_BASS |
- SOUND_MASK_MIC |
- SOUND_MASK_LINE;
-}
-
-static int
-tas3004_mixer_is_stereo(struct tas3004_data_t *self, int mixer)
-{
- switch(mixer) {
- case SOUND_MIXER_VOLUME:
- case SOUND_MIXER_PCM:
- case SOUND_MIXER_ALTPCM:
- case SOUND_MIXER_IMIX:
- return 1;
- default:
- return 0;
- }
-}
-
-static uint
-tas3004_stereo_mixers(struct tas3004_data_t *self)
-{
- uint r = tas3004_supported_mixers(self);
- uint i;
-
- for (i=1; i<SOUND_MIXER_NRDEVICES; i++)
- if (r&(1<<i) && !tas3004_mixer_is_stereo(self,i))
- r &= ~(1<<i);
- return r;
-}
-
-static int
-tas3004_get_mixer_level(struct tas3004_data_t *self, int mixer, uint *level)
-{
- if (!self)
- return -1;
-
- *level = self->super.mixer[mixer];
-
- return 0;
-}
-
-static int
-tas3004_set_mixer_level(struct tas3004_data_t *self, int mixer, uint level)
-{
- int rc;
- tas_shadow_t *shadow;
- uint temp;
- uint offset=0;
-
- if (!self)
- return -1;
-
- shadow = self->super.shadow;
-
- if (!tas3004_mixer_is_stereo(self,mixer))
- level = tas_mono_to_stereo(level);
- switch(mixer) {
- case SOUND_MIXER_VOLUME:
- temp = tas3004_gain.master[level&0xff];
- SET_4_20(shadow[TAS3004_REG_VOLUME], 0, temp);
- temp = tas3004_gain.master[(level>>8)&0xff];
- SET_4_20(shadow[TAS3004_REG_VOLUME], 3, temp);
- rc = tas3004_sync_register(self,TAS3004_REG_VOLUME);
- break;
- case SOUND_MIXER_IMIX:
- offset += 3;
- case SOUND_MIXER_ALTPCM:
- offset += 3;
- case SOUND_MIXER_PCM:
- /*
- * Don't load these in fast mode. The documentation
- * says it can be done in either mode, but testing it
- * shows that fast mode produces ugly clicking.
- */
- /* tas3004_fast_load(self,1); */
- temp = tas3004_gain.mixer[level&0xff];
- SET_4_20(shadow[TAS3004_REG_LEFT_MIXER], offset, temp);
- temp = tas3004_gain.mixer[(level>>8)&0xff];
- SET_4_20(shadow[TAS3004_REG_RIGHT_MIXER], offset, temp);
- rc = tas3004_sync_register(self,TAS3004_REG_LEFT_MIXER);
- if (rc == 0)
- rc=tas3004_sync_register(self,TAS3004_REG_RIGHT_MIXER);
- /* tas3004_fast_load(self,0); */
- break;
- case SOUND_MIXER_TREBLE:
- temp = tas3004_gain.treble[level&0xff];
- shadow[TAS3004_REG_TREBLE][0]=temp&0xff;
- rc = tas3004_sync_register(self,TAS3004_REG_TREBLE);
- break;
- case SOUND_MIXER_BASS:
- temp = tas3004_gain.bass[level&0xff];
- shadow[TAS3004_REG_BASS][0]=temp&0xff;
- rc = tas3004_sync_register(self,TAS3004_REG_BASS);
- break;
- case SOUND_MIXER_MIC:
- if ((level&0xff)>0) {
- software_input_volume = SW_INPUT_VOLUME_SCALE * (level&0xff);
- if (self->super.mixer[mixer] == 0) {
- self->super.mixer[SOUND_MIXER_LINE] = 0;
- shadow[TAS3004_REG_ANALOG_CTRL][0]=0xc2;
- rc = tas3004_sync_register(self,TAS3004_REG_ANALOG_CTRL);
- } else rc=0;
- } else {
- self->super.mixer[SOUND_MIXER_LINE] = SW_INPUT_VOLUME_DEFAULT;
- software_input_volume = SW_INPUT_VOLUME_SCALE *
- (self->super.mixer[SOUND_MIXER_LINE]&0xff);
- shadow[TAS3004_REG_ANALOG_CTRL][0]=0x00;
- rc = tas3004_sync_register(self,TAS3004_REG_ANALOG_CTRL);
- }
- break;
- case SOUND_MIXER_LINE:
- if (self->super.mixer[SOUND_MIXER_MIC] == 0) {
- software_input_volume = SW_INPUT_VOLUME_SCALE * (level&0xff);
- rc=0;
- }
- break;
- default:
- rc = -1;
- break;
- }
- if (rc < 0)
- return rc;
- self->super.mixer[mixer] = level;
-
- return 0;
-}
-
-static int
-tas3004_leave_sleep(struct tas3004_data_t *self)
-{
- unsigned char mcr = (1<<6)+(2<<4)+(2<<2);
-
- if (!self)
- return -1;
-
- /* Make sure something answers on the i2c bus */
- if (tas3004_write_register(self, TAS3004_REG_MCR, &mcr,
- WRITE_NORMAL | FORCE_WRITE) < 0)
- return -1;
-
- tas3004_fast_load(self, 1);
-
- (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD0);
- (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD1);
- (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD2);
- (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD3);
- (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD4);
- (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD5);
- (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD6);
-
- (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD0);
- (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD1);
- (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD2);
- (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD3);
- (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD4);
- (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD5);
- (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD6);
-
- tas3004_fast_load(self, 0);
-
- (void)tas3004_sync_register(self,TAS3004_REG_VOLUME);
- (void)tas3004_sync_register(self,TAS3004_REG_LEFT_MIXER);
- (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_MIXER);
- (void)tas3004_sync_register(self,TAS3004_REG_TREBLE);
- (void)tas3004_sync_register(self,TAS3004_REG_BASS);
- (void)tas3004_sync_register(self,TAS3004_REG_ANALOG_CTRL);
-
- return 0;
-}
-
-static int
-tas3004_enter_sleep(struct tas3004_data_t *self)
-{
- if (!self)
- return -1;
- return 0;
-}
-
-static int
-tas3004_sync_biquad( struct tas3004_data_t *self,
- u_int channel,
- u_int filter)
-{
- enum tas3004_reg_t reg;
-
- if (channel >= TAS3004_BIQUAD_CHANNEL_COUNT ||
- filter >= TAS3004_BIQUAD_FILTER_COUNT) return -EINVAL;
-
- reg=( channel ? TAS3004_REG_RIGHT_BIQUAD0 : TAS3004_REG_LEFT_BIQUAD0 ) + filter;
-
- return tas3004_sync_register(self,reg);
-}
-
-static int
-tas3004_write_biquad_shadow( struct tas3004_data_t *self,
- u_int channel,
- u_int filter,
- const union tas_biquad_t *biquad)
-{
- tas_shadow_t *shadow=self->super.shadow;
- enum tas3004_reg_t reg;
-
- if (channel >= TAS3004_BIQUAD_CHANNEL_COUNT ||
- filter >= TAS3004_BIQUAD_FILTER_COUNT) return -EINVAL;
-
- reg=( channel ? TAS3004_REG_RIGHT_BIQUAD0 : TAS3004_REG_LEFT_BIQUAD0 ) + filter;
-
- SET_4_20(shadow[reg], 0,biquad->coeff.b0);
- SET_4_20(shadow[reg], 3,biquad->coeff.b1);
- SET_4_20(shadow[reg], 6,biquad->coeff.b2);
- SET_4_20(shadow[reg], 9,biquad->coeff.a1);
- SET_4_20(shadow[reg],12,biquad->coeff.a2);
-
- return 0;
-}
-
-static int
-tas3004_write_biquad( struct tas3004_data_t *self,
- u_int channel,
- u_int filter,
- const union tas_biquad_t *biquad)
-{
- int rc;
-
- rc=tas3004_write_biquad_shadow(self, channel, filter, biquad);
- if (rc < 0) return rc;
-
- return tas3004_sync_biquad(self, channel, filter);
-}
-
-static int
-tas3004_write_biquad_list( struct tas3004_data_t *self,
- u_int filter_count,
- u_int flags,
- struct tas_biquad_ctrl_t *biquads)
-{
- int i;
- int rc;
-
- if (flags & TAS_BIQUAD_FAST_LOAD) tas3004_fast_load(self,1);
-
- for (i=0; i<filter_count; i++) {
- rc=tas3004_write_biquad(self,
- biquads[i].channel,
- biquads[i].filter,
- &biquads[i].data);
- if (rc < 0) break;
- }
-
- if (flags & TAS_BIQUAD_FAST_LOAD) tas3004_fast_load(self,0);
-
- return rc;
-}
-
-static int
-tas3004_read_biquad( struct tas3004_data_t *self,
- u_int channel,
- u_int filter,
- union tas_biquad_t *biquad)
-{
- tas_shadow_t *shadow=self->super.shadow;
- enum tas3004_reg_t reg;
-
- if (channel >= TAS3004_BIQUAD_CHANNEL_COUNT ||
- filter >= TAS3004_BIQUAD_FILTER_COUNT) return -EINVAL;
-
- reg=( channel ? TAS3004_REG_RIGHT_BIQUAD0 : TAS3004_REG_LEFT_BIQUAD0 ) + filter;
-
- biquad->coeff.b0=GET_4_20(shadow[reg], 0);
- biquad->coeff.b1=GET_4_20(shadow[reg], 3);
- biquad->coeff.b2=GET_4_20(shadow[reg], 6);
- biquad->coeff.a1=GET_4_20(shadow[reg], 9);
- biquad->coeff.a2=GET_4_20(shadow[reg],12);
-
- return 0;
-}
-
-static int
-tas3004_eq_rw( struct tas3004_data_t *self,
- u_int cmd,
- u_long arg)
-{
- void __user *argp = (void __user *)arg;
- int rc;
- struct tas_biquad_ctrl_t biquad;
-
- if (copy_from_user((void *)&biquad, argp, sizeof(struct tas_biquad_ctrl_t))) {
- return -EFAULT;
- }
-
- if (cmd & SIOC_IN) {
- rc=tas3004_write_biquad(self, biquad.channel, biquad.filter, &biquad.data);
- if (rc != 0) return rc;
- }
-
- if (cmd & SIOC_OUT) {
- rc=tas3004_read_biquad(self, biquad.channel, biquad.filter, &biquad.data);
- if (rc != 0) return rc;
-
- if (copy_to_user(argp, &biquad, sizeof(struct tas_biquad_ctrl_t))) {
- return -EFAULT;
- }
-
- }
- return 0;
-}
-
-static int
-tas3004_eq_list_rw( struct tas3004_data_t *self,
- u_int cmd,
- u_long arg)
-{
- int rc = 0;
- int filter_count;
- int flags;
- int i,j;
- char sync_required[TAS3004_BIQUAD_CHANNEL_COUNT][TAS3004_BIQUAD_FILTER_COUNT];
- struct tas_biquad_ctrl_t biquad;
- struct tas_biquad_ctrl_list_t __user *argp = (void __user *)arg;
-
- memset(sync_required,0,sizeof(sync_required));
-
- if (copy_from_user(&filter_count, &argp->filter_count, sizeof(int)))
- return -EFAULT;
-
- if (copy_from_user(&flags, &argp->flags, sizeof(int)))
- return -EFAULT;
-
- if (cmd & SIOC_IN) {
- }
-
- for (i=0; i < filter_count; i++) {
- if (copy_from_user(&biquad, &argp->biquads[i],
- sizeof(struct tas_biquad_ctrl_t))) {
- return -EFAULT;
- }
-
- if (cmd & SIOC_IN) {
- sync_required[biquad.channel][biquad.filter]=1;
- rc=tas3004_write_biquad_shadow(self, biquad.channel, biquad.filter, &biquad.data);
- if (rc != 0) return rc;
- }
-
- if (cmd & SIOC_OUT) {
- rc=tas3004_read_biquad(self, biquad.channel, biquad.filter, &biquad.data);
- if (rc != 0) return rc;
-
- if (copy_to_user(&argp->biquads[i], &biquad,
- sizeof(struct tas_biquad_ctrl_t))) {
- return -EFAULT;
- }
- }
- }
-
- if (cmd & SIOC_IN) {
- /*
- * This is OK for the tas3004. For the
- * tas3001c, going into fast load mode causes
- * the treble and bass to be reset to 0dB, and
- * volume controls to be muted.
- */
- if (flags & TAS_BIQUAD_FAST_LOAD) tas3004_fast_load(self,1);
- for (i=0; i<TAS3004_BIQUAD_CHANNEL_COUNT; i++) {
- for (j=0; j<TAS3004_BIQUAD_FILTER_COUNT; j++) {
- if (sync_required[i][j]) {
- rc=tas3004_sync_biquad(self, i, j);
- if (rc < 0) goto out;
- }
- }
- }
- out:
- if (flags & TAS_BIQUAD_FAST_LOAD)
- tas3004_fast_load(self,0);
- }
-
- return rc;
-}
-
-static int
-tas3004_update_drce( struct tas3004_data_t *self,
- int flags,
- struct tas_drce_t *drce)
-{
- tas_shadow_t *shadow;
- int i;
- shadow=self->super.shadow;
-
- if (flags & TAS_DRCE_ABOVE_RATIO) {
- self->drce_state.above.expand = drce->above.expand;
- if (drce->above.val == (1<<8)) {
- self->drce_state.above.val = 1<<8;
- shadow[TAS3004_REG_DRC][0] = 0x02;
-
- } else if (drce->above.expand) {
- i=above_threshold_expansion_index(drce->above.val);
- self->drce_state.above.val=above_threshold_expansion_ratio[i];
- shadow[TAS3004_REG_DRC][0] = 0x0a + (i<<3);
- } else {
- i=above_threshold_compression_index(drce->above.val);
- self->drce_state.above.val=above_threshold_compression_ratio[i];
- shadow[TAS3004_REG_DRC][0] = 0x08 + (i<<3);
- }
- }
-
- if (flags & TAS_DRCE_BELOW_RATIO) {
- self->drce_state.below.expand = drce->below.expand;
- if (drce->below.val == (1<<8)) {
- self->drce_state.below.val = 1<<8;
- shadow[TAS3004_REG_DRC][1] = 0x02;
-
- } else if (drce->below.expand) {
- i=below_threshold_expansion_index(drce->below.val);
- self->drce_state.below.val=below_threshold_expansion_ratio[i];
- shadow[TAS3004_REG_DRC][1] = 0x08 + (i<<3);
- } else {
- i=below_threshold_compression_index(drce->below.val);
- self->drce_state.below.val=below_threshold_compression_ratio[i];
- shadow[TAS3004_REG_DRC][1] = 0x0a + (i<<3);
- }
- }
-
- if (flags & TAS_DRCE_THRESHOLD) {
- self->drce_state.threshold=quantize_db(drce->threshold);
- shadow[TAS3004_REG_DRC][2] = db_to_regval(self->drce_state.threshold);
- }
-
- if (flags & TAS_DRCE_ENERGY) {
- i=time_index(drce->energy);
- self->drce_state.energy=time_constants[i];
- shadow[TAS3004_REG_DRC][3] = 0x40 + (i<<4);
- }
-
- if (flags & TAS_DRCE_ATTACK) {
- i=time_index(drce->attack);
- self->drce_state.attack=time_constants[i];
- shadow[TAS3004_REG_DRC][4] = 0x40 + (i<<4);
- }
-
- if (flags & TAS_DRCE_DECAY) {
- i=time_index(drce->decay);
- self->drce_state.decay=time_constants[i];
- shadow[TAS3004_REG_DRC][5] = 0x40 + (i<<4);
- }
-
- if (flags & TAS_DRCE_ENABLE) {
- self->drce_state.enable = drce->enable;
- }
-
- if (!self->drce_state.enable) {
- shadow[TAS3004_REG_DRC][0] |= 0x01;
- }
-
-#ifdef DEBUG_DRCE
- printk("DRCE: set [ ENABLE:%x ABOVE:%x/%x BELOW:%x/%x THRESH:%x ENERGY:%x ATTACK:%x DECAY:%x\n",
- self->drce_state.enable,
- self->drce_state.above.expand,self->drce_state.above.val,
- self->drce_state.below.expand,self->drce_state.below.val,
- self->drce_state.threshold,
- self->drce_state.energy,
- self->drce_state.attack,
- self->drce_state.decay);
-
- printk("DRCE: reg [ %02x %02x %02x %02x %02x %02x ]\n",
- (unsigned char)shadow[TAS3004_REG_DRC][0],
- (unsigned char)shadow[TAS3004_REG_DRC][1],
- (unsigned char)shadow[TAS3004_REG_DRC][2],
- (unsigned char)shadow[TAS3004_REG_DRC][3],
- (unsigned char)shadow[TAS3004_REG_DRC][4],
- (unsigned char)shadow[TAS3004_REG_DRC][5]);
-#endif
-
- return tas3004_sync_register(self, TAS3004_REG_DRC);
-}
-
-static int
-tas3004_drce_rw( struct tas3004_data_t *self,
- u_int cmd,
- u_long arg)
-{
- int rc;
- struct tas_drce_ctrl_t drce_ctrl;
- void __user *argp = (void __user *)arg;
-
- if (copy_from_user(&drce_ctrl, argp, sizeof(struct tas_drce_ctrl_t)))
- return -EFAULT;
-
-#ifdef DEBUG_DRCE
- printk("DRCE: input [ FLAGS:%x ENABLE:%x ABOVE:%x/%x BELOW:%x/%x THRESH:%x ENERGY:%x ATTACK:%x DECAY:%x\n",
- drce_ctrl.flags,
- drce_ctrl.data.enable,
- drce_ctrl.data.above.expand,drce_ctrl.data.above.val,
- drce_ctrl.data.below.expand,drce_ctrl.data.below.val,
- drce_ctrl.data.threshold,
- drce_ctrl.data.energy,
- drce_ctrl.data.attack,
- drce_ctrl.data.decay);
-#endif
-
- if (cmd & SIOC_IN) {
- rc = tas3004_update_drce(self, drce_ctrl.flags, &drce_ctrl.data);
- if (rc < 0) return rc;
- }
-
- if (cmd & SIOC_OUT) {
- if (drce_ctrl.flags & TAS_DRCE_ENABLE)
- drce_ctrl.data.enable = self->drce_state.enable;
- if (drce_ctrl.flags & TAS_DRCE_ABOVE_RATIO)
- drce_ctrl.data.above = self->drce_state.above;
- if (drce_ctrl.flags & TAS_DRCE_BELOW_RATIO)
- drce_ctrl.data.below = self->drce_state.below;
- if (drce_ctrl.flags & TAS_DRCE_THRESHOLD)
- drce_ctrl.data.threshold = self->drce_state.threshold;
- if (drce_ctrl.flags & TAS_DRCE_ENERGY)
- drce_ctrl.data.energy = self->drce_state.energy;
- if (drce_ctrl.flags & TAS_DRCE_ATTACK)
- drce_ctrl.data.attack = self->drce_state.attack;
- if (drce_ctrl.flags & TAS_DRCE_DECAY)
- drce_ctrl.data.decay = self->drce_state.decay;
-
- if (copy_to_user(argp, &drce_ctrl,
- sizeof(struct tas_drce_ctrl_t))) {
- return -EFAULT;
- }
- }
-
- return 0;
-}
-
-static void
-tas3004_update_device_parameters(struct tas3004_data_t *self)
-{
- char data;
- int i;
-
- if (!self) return;
-
- if (self->output_id == TAS_OUTPUT_HEADPHONES) {
- /* turn on allPass when headphones are plugged in */
- data = 0x02;
- } else {
- data = 0x00;
- }
-
- tas3004_write_register(self, TAS3004_REG_MCR2, &data, WRITE_NORMAL | FORCE_WRITE);
-
- for (i=0; tas3004_eq_prefs[i]; i++) {
- struct tas_eq_pref_t *eq = tas3004_eq_prefs[i];
-
- if (eq->device_id == self->device_id &&
- (eq->output_id == 0 || eq->output_id == self->output_id) &&
- (eq->speaker_id == 0 || eq->speaker_id == self->speaker_id)) {
-
- tas3004_update_drce(self, TAS_DRCE_ALL, eq->drce);
- tas3004_write_biquad_list(self, eq->filter_count, TAS_BIQUAD_FAST_LOAD, eq->biquads);
-
- break;
- }
- }
-}
-
-static void
-tas3004_device_change_handler(struct work_struct *work)
-{
- struct tas3004_data_t *self;
- self = container_of(work, struct tas3004_data_t, change);
- tas3004_update_device_parameters(self);
-}
-
-static int
-tas3004_output_device_change( struct tas3004_data_t *self,
- int device_id,
- int output_id,
- int speaker_id)
-{
- self->device_id=device_id;
- self->output_id=output_id;
- self->speaker_id=speaker_id;
-
- schedule_work(&self->change);
-
- return 0;
-}
-
-static int
-tas3004_device_ioctl( struct tas3004_data_t *self,
- u_int cmd,
- u_long arg)
-{
- uint __user *argp = (void __user *)arg;
- switch (cmd) {
- case TAS_READ_EQ:
- case TAS_WRITE_EQ:
- return tas3004_eq_rw(self, cmd, arg);
-
- case TAS_READ_EQ_LIST:
- case TAS_WRITE_EQ_LIST:
- return tas3004_eq_list_rw(self, cmd, arg);
-
- case TAS_READ_EQ_FILTER_COUNT:
- put_user(TAS3004_BIQUAD_FILTER_COUNT, argp);
- return 0;
-
- case TAS_READ_EQ_CHANNEL_COUNT:
- put_user(TAS3004_BIQUAD_CHANNEL_COUNT, argp);
- return 0;
-
- case TAS_READ_DRCE:
- case TAS_WRITE_DRCE:
- return tas3004_drce_rw(self, cmd, arg);
-
- case TAS_READ_DRCE_CAPS:
- put_user(TAS_DRCE_ENABLE |
- TAS_DRCE_ABOVE_RATIO |
- TAS_DRCE_BELOW_RATIO |
- TAS_DRCE_THRESHOLD |
- TAS_DRCE_ENERGY |
- TAS_DRCE_ATTACK |
- TAS_DRCE_DECAY,
- argp);
- return 0;
-
- case TAS_READ_DRCE_MIN:
- case TAS_READ_DRCE_MAX: {
- struct tas_drce_ctrl_t drce_ctrl;
- const struct tas_drce_t *drce_copy;
-
- if (copy_from_user(&drce_ctrl, argp,
- sizeof(struct tas_drce_ctrl_t))) {
- return -EFAULT;
- }
-
- if (cmd == TAS_READ_DRCE_MIN) {
- drce_copy=&tas3004_drce_min;
- } else {
- drce_copy=&tas3004_drce_max;
- }
-
- if (drce_ctrl.flags & TAS_DRCE_ABOVE_RATIO) {
- drce_ctrl.data.above=drce_copy->above;
- }
- if (drce_ctrl.flags & TAS_DRCE_BELOW_RATIO) {
- drce_ctrl.data.below=drce_copy->below;
- }
- if (drce_ctrl.flags & TAS_DRCE_THRESHOLD) {
- drce_ctrl.data.threshold=drce_copy->threshold;
- }
- if (drce_ctrl.flags & TAS_DRCE_ENERGY) {
- drce_ctrl.data.energy=drce_copy->energy;
- }
- if (drce_ctrl.flags & TAS_DRCE_ATTACK) {
- drce_ctrl.data.attack=drce_copy->attack;
- }
- if (drce_ctrl.flags & TAS_DRCE_DECAY) {
- drce_ctrl.data.decay=drce_copy->decay;
- }
-
- if (copy_to_user(argp, &drce_ctrl,
- sizeof(struct tas_drce_ctrl_t))) {
- return -EFAULT;
- }
- }
- }
-
- return -EINVAL;
-}
-
-static int
-tas3004_init_mixer(struct tas3004_data_t *self)
-{
- unsigned char mcr = (1<<6)+(2<<4)+(2<<2);
-
- /* Make sure something answers on the i2c bus */
- if (tas3004_write_register(self, TAS3004_REG_MCR, &mcr,
- WRITE_NORMAL | FORCE_WRITE) < 0)
- return -1;
-
- tas3004_fast_load(self, 1);
-
- (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD0);
- (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD1);
- (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD2);
- (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD3);
- (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD4);
- (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD5);
- (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD6);
-
- (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD0);
- (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD1);
- (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD2);
- (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD3);
- (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD4);
- (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD5);
- (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD6);
-
- tas3004_sync_register(self, TAS3004_REG_DRC);
-
- tas3004_sync_register(self, TAS3004_REG_MCR2);
-
- tas3004_fast_load(self, 0);
-
- tas3004_set_mixer_level(self, SOUND_MIXER_VOLUME, VOL_DEFAULT<<8 | VOL_DEFAULT);
- tas3004_set_mixer_level(self, SOUND_MIXER_PCM, INPUT_DEFAULT<<8 | INPUT_DEFAULT);
- tas3004_set_mixer_level(self, SOUND_MIXER_ALTPCM, 0);
- tas3004_set_mixer_level(self, SOUND_MIXER_IMIX, 0);
-
- tas3004_set_mixer_level(self, SOUND_MIXER_BASS, BASS_DEFAULT);
- tas3004_set_mixer_level(self, SOUND_MIXER_TREBLE, TREBLE_DEFAULT);
-
- tas3004_set_mixer_level(self, SOUND_MIXER_LINE,SW_INPUT_VOLUME_DEFAULT);
-
- return 0;
-}
-
-static int
-tas3004_uninit_mixer(struct tas3004_data_t *self)
-{
- tas3004_set_mixer_level(self, SOUND_MIXER_VOLUME, 0);
- tas3004_set_mixer_level(self, SOUND_MIXER_PCM, 0);
- tas3004_set_mixer_level(self, SOUND_MIXER_ALTPCM, 0);
- tas3004_set_mixer_level(self, SOUND_MIXER_IMIX, 0);
-
- tas3004_set_mixer_level(self, SOUND_MIXER_BASS, 0);
- tas3004_set_mixer_level(self, SOUND_MIXER_TREBLE, 0);
-
- tas3004_set_mixer_level(self, SOUND_MIXER_LINE, 0);
-
- return 0;
-}
-
-static int
-tas3004_init(struct i2c_client *client)
-{
- struct tas3004_data_t *self;
- size_t sz = sizeof(*self) + (TAS3004_REG_MAX*sizeof(tas_shadow_t));
- char drce_init[] = { 0x69, 0x22, 0x9f, 0xb0, 0x60, 0xa0 };
- char mcr2 = 0;
- int i, j;
-
- self = kzalloc(sz, GFP_KERNEL);
- if (!self)
- return -ENOMEM;
-
- self->super.client = client;
- self->super.shadow = (tas_shadow_t *)(self+1);
- self->output_id = TAS_OUTPUT_HEADPHONES;
-
- dev_set_drvdata(&client->dev, self);
-
- for (i = 0; i < TAS3004_BIQUAD_CHANNEL_COUNT; i++)
- for (j = 0; j<TAS3004_BIQUAD_FILTER_COUNT; j++)
- tas3004_write_biquad_shadow(self, i, j,
- &tas3004_eq_unity);
-
- tas3004_write_register(self, TAS3004_REG_MCR2, &mcr2, WRITE_SHADOW);
- tas3004_write_register(self, TAS3004_REG_DRC, drce_init, WRITE_SHADOW);
-
- INIT_WORK(&self->change, tas3004_device_change_handler);
- return 0;
-}
-
-static void
-tas3004_uninit(struct tas3004_data_t *self)
-{
- tas3004_uninit_mixer(self);
- kfree(self);
-}
-
-
-struct tas_driver_hooks_t tas3004_hooks = {
- .init = (tas_hook_init_t)tas3004_init,
- .post_init = (tas_hook_post_init_t)tas3004_init_mixer,
- .uninit = (tas_hook_uninit_t)tas3004_uninit,
- .get_mixer_level = (tas_hook_get_mixer_level_t)tas3004_get_mixer_level,
- .set_mixer_level = (tas_hook_set_mixer_level_t)tas3004_set_mixer_level,
- .enter_sleep = (tas_hook_enter_sleep_t)tas3004_enter_sleep,
- .leave_sleep = (tas_hook_leave_sleep_t)tas3004_leave_sleep,
- .supported_mixers = (tas_hook_supported_mixers_t)tas3004_supported_mixers,
- .mixer_is_stereo = (tas_hook_mixer_is_stereo_t)tas3004_mixer_is_stereo,
- .stereo_mixers = (tas_hook_stereo_mixers_t)tas3004_stereo_mixers,
- .output_device_change = (tas_hook_output_device_change_t)tas3004_output_device_change,
- .device_ioctl = (tas_hook_device_ioctl_t)tas3004_device_ioctl
-};
diff --git a/sound/oss/dmasound/tas3004.h b/sound/oss/dmasound/tas3004.h
deleted file mode 100644
index c6d584bf2ca4..000000000000
--- a/sound/oss/dmasound/tas3004.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Header file for the i2c/i2s based TA3004 sound chip used
- * on some Apple hardware. Also known as "tumbler".
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive
- * for more details.
- *
- * Written by Christopher C. Chimelis <chris@debian.org>
- */
-
-#ifndef _TAS3004_H_
-#define _TAS3004_H_
-
-#include <linux/types.h>
-
-#include "tas_common.h"
-#include "tas_eq_prefs.h"
-
-/*
- * Macros that correspond to the registers that we write to
- * when setting the various values.
- */
-
-#define TAS3004_VERSION "0.3"
-#define TAS3004_DATE "20011214"
-
-#define I2C_DRIVERNAME_TAS3004 "TAS3004 driver V " TAS3004_VERSION
-#define I2C_DRIVERID_TAS3004 (I2C_DRIVERID_TAS_BASE+1)
-
-extern struct tas_driver_hooks_t tas3004_hooks;
-extern struct tas_gain_t tas3004_gain;
-extern struct tas_eq_pref_t *tas3004_eq_prefs[];
-
-enum tas3004_reg_t {
- TAS3004_REG_MCR = 0x01,
- TAS3004_REG_DRC = 0x02,
-
- TAS3004_REG_VOLUME = 0x04,
- TAS3004_REG_TREBLE = 0x05,
- TAS3004_REG_BASS = 0x06,
- TAS3004_REG_LEFT_MIXER = 0x07,
- TAS3004_REG_RIGHT_MIXER = 0x08,
-
- TAS3004_REG_LEFT_BIQUAD0 = 0x0a,
- TAS3004_REG_LEFT_BIQUAD1 = 0x0b,
- TAS3004_REG_LEFT_BIQUAD2 = 0x0c,
- TAS3004_REG_LEFT_BIQUAD3 = 0x0d,
- TAS3004_REG_LEFT_BIQUAD4 = 0x0e,
- TAS3004_REG_LEFT_BIQUAD5 = 0x0f,
- TAS3004_REG_LEFT_BIQUAD6 = 0x10,
-
- TAS3004_REG_RIGHT_BIQUAD0 = 0x13,
- TAS3004_REG_RIGHT_BIQUAD1 = 0x14,
- TAS3004_REG_RIGHT_BIQUAD2 = 0x15,
- TAS3004_REG_RIGHT_BIQUAD3 = 0x16,
- TAS3004_REG_RIGHT_BIQUAD4 = 0x17,
- TAS3004_REG_RIGHT_BIQUAD5 = 0x18,
- TAS3004_REG_RIGHT_BIQUAD6 = 0x19,
-
- TAS3004_REG_LEFT_LOUD_BIQUAD = 0x21,
- TAS3004_REG_RIGHT_LOUD_BIQUAD = 0x22,
-
- TAS3004_REG_LEFT_LOUD_BIQUAD_GAIN = 0x23,
- TAS3004_REG_RIGHT_LOUD_BIQUAD_GAIN = 0x24,
-
- TAS3004_REG_TEST = 0x29,
-
- TAS3004_REG_ANALOG_CTRL = 0x40,
- TAS3004_REG_TEST1 = 0x41,
- TAS3004_REG_TEST2 = 0x42,
- TAS3004_REG_MCR2 = 0x43,
-
- TAS3004_REG_MAX = 0x44
-};
-
-#endif /* _TAS3004_H_ */
diff --git a/sound/oss/dmasound/tas3004_tables.c b/sound/oss/dmasound/tas3004_tables.c
deleted file mode 100644
index b910e0a66775..000000000000
--- a/sound/oss/dmasound/tas3004_tables.c
+++ /dev/null
@@ -1,301 +0,0 @@
-#include "tas3004.h"
-#include "tas_eq_prefs.h"
-
-static struct tas_drce_t eqp_17_1_0_drce={
- .enable = 1,
- .above = { .val = 3.0 * (1<<8), .expand = 0 },
- .below = { .val = 1.0 * (1<<8), .expand = 0 },
- .threshold = -19.12 * (1<<8),
- .energy = 2.4 * (1<<12),
- .attack = 0.013 * (1<<12),
- .decay = 0.212 * (1<<12),
-};
-
-static struct tas_biquad_ctrl_t eqp_17_1_0_biquads[]={
- { .channel = 0, .filter = 0, .data = { .coeff = { 0x0fd0d4, 0xe05e56, 0x0fd0d4, 0xe05ee1, 0x0fa234 } } },
- { .channel = 0, .filter = 1, .data = { .coeff = { 0x0910d7, 0x088e1a, 0x030651, 0x01dcb1, 0x02c892 } } },
- { .channel = 0, .filter = 2, .data = { .coeff = { 0x0ff895, 0xe0970b, 0x0f7f00, 0xe0970b, 0x0f7795 } } },
- { .channel = 0, .filter = 3, .data = { .coeff = { 0x0fd1c4, 0xe1ac22, 0x0ec8cf, 0xe1ac22, 0x0e9a94 } } },
- { .channel = 0, .filter = 4, .data = { .coeff = { 0x0f7c1c, 0xe3cc03, 0x0df786, 0xe3cc03, 0x0d73a2 } } },
- { .channel = 0, .filter = 5, .data = { .coeff = { 0x11fb92, 0xf5a1a0, 0x073cd2, 0xf5a1a0, 0x093865 } } },
- { .channel = 0, .filter = 6, .data = { .coeff = { 0x0e17a9, 0x068b6c, 0x08a0e5, 0x068b6c, 0x06b88e } } },
-
- { .channel = 1, .filter = 0, .data = { .coeff = { 0x0fd0d4, 0xe05e56, 0x0fd0d4, 0xe05ee1, 0x0fa234 } } },
- { .channel = 1, .filter = 1, .data = { .coeff = { 0x0910d7, 0x088e1a, 0x030651, 0x01dcb1, 0x02c892 } } },
- { .channel = 1, .filter = 2, .data = { .coeff = { 0x0ff895, 0xe0970b, 0x0f7f00, 0xe0970b, 0x0f7795 } } },
- { .channel = 1, .filter = 3, .data = { .coeff = { 0x0fd1c4, 0xe1ac22, 0x0ec8cf, 0xe1ac22, 0x0e9a94 } } },
- { .channel = 1, .filter = 4, .data = { .coeff = { 0x0f7c1c, 0xe3cc03, 0x0df786, 0xe3cc03, 0x0d73a2 } } },
- { .channel = 1, .filter = 5, .data = { .coeff = { 0x11fb92, 0xf5a1a0, 0x073cd2, 0xf5a1a0, 0x093865 } } },
- { .channel = 1, .filter = 6, .data = { .coeff = { 0x0e17a9, 0x068b6c, 0x08a0e5, 0x068b6c, 0x06b88e } } }
-};
-
-static struct tas_eq_pref_t eqp_17_1_0 = {
- .sample_rate = 44100,
- .device_id = 0x17,
- .output_id = TAS_OUTPUT_INTERNAL_SPKR,
- .speaker_id = 0x00,
-
- .drce = &eqp_17_1_0_drce,
-
- .filter_count = 14,
- .biquads = eqp_17_1_0_biquads
-};
-
-/* ======================================================================== */
-
-static struct tas_drce_t eqp_18_1_0_drce={
- .enable = 1,
- .above = { .val = 3.0 * (1<<8), .expand = 0 },
- .below = { .val = 1.0 * (1<<8), .expand = 0 },
- .threshold = -13.14 * (1<<8),
- .energy = 2.4 * (1<<12),
- .attack = 0.013 * (1<<12),
- .decay = 0.212 * (1<<12),
-};
-
-static struct tas_biquad_ctrl_t eqp_18_1_0_biquads[]={
- { .channel = 0, .filter = 0, .data = { .coeff = { 0x0f5514, 0xe155d7, 0x0f5514, 0xe15cfa, 0x0eb14b } } },
- { .channel = 0, .filter = 1, .data = { .coeff = { 0x06ec33, 0x02abe3, 0x015eef, 0xf764d9, 0x03922d } } },
- { .channel = 0, .filter = 2, .data = { .coeff = { 0x0ef5f2, 0xe67d1f, 0x0bcf37, 0xe67d1f, 0x0ac529 } } },
- { .channel = 0, .filter = 3, .data = { .coeff = { 0x0db050, 0xe5be4d, 0x0d0c78, 0xe5be4d, 0x0abcc8 } } },
- { .channel = 0, .filter = 4, .data = { .coeff = { 0x0f1298, 0xe64ec6, 0x0cc03e, 0xe64ec6, 0x0bd2d7 } } },
- { .channel = 0, .filter = 5, .data = { .coeff = { 0x0c641a, 0x06537a, 0x08d155, 0x06537a, 0x053570 } } },
- { .channel = 0, .filter = 6, .data = { .coeff = { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } } },
-
- { .channel = 1, .filter = 0, .data = { .coeff = { 0x0f5514, 0xe155d7, 0x0f5514, 0xe15cfa, 0x0eb14b } } },
- { .channel = 1, .filter = 1, .data = { .coeff = { 0x06ec33, 0x02abe3, 0x015eef, 0xf764d9, 0x03922d } } },
- { .channel = 1, .filter = 2, .data = { .coeff = { 0x0ef5f2, 0xe67d1f, 0x0bcf37, 0xe67d1f, 0x0ac529 } } },
- { .channel = 1, .filter = 3, .data = { .coeff = { 0x0db050, 0xe5be4d, 0x0d0c78, 0xe5be4d, 0x0abcc8 } } },
- { .channel = 1, .filter = 4, .data = { .coeff = { 0x0f1298, 0xe64ec6, 0x0cc03e, 0xe64ec6, 0x0bd2d7 } } },
- { .channel = 1, .filter = 5, .data = { .coeff = { 0x0c641a, 0x06537a, 0x08d155, 0x06537a, 0x053570 } } },
- { .channel = 1, .filter = 6, .data = { .coeff = { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } } }
-};
-
-static struct tas_eq_pref_t eqp_18_1_0 = {
- .sample_rate = 44100,
- .device_id = 0x18,
- .output_id = TAS_OUTPUT_INTERNAL_SPKR,
- .speaker_id = 0x00,
-
- .drce = &eqp_18_1_0_drce,
-
- .filter_count = 14,
- .biquads = eqp_18_1_0_biquads
-};
-
-/* ======================================================================== */
-
-static struct tas_drce_t eqp_1a_1_0_drce={
- .enable = 1,
- .above = { .val = 3.0 * (1<<8), .expand = 0 },
- .below = { .val = 1.0 * (1<<8), .expand = 0 },
- .threshold = -10.75 * (1<<8),
- .energy = 2.4 * (1<<12),
- .attack = 0.013 * (1<<12),
- .decay = 0.212 * (1<<12),
-};
-
-static struct tas_biquad_ctrl_t eqp_1a_1_0_biquads[]={
- { .channel = 0, .filter = 0, .data = { .coeff = { 0x0fb8fd, 0xe08e04, 0x0fb8fd, 0xe08f40, 0x0f7336 } } },
- { .channel = 0, .filter = 1, .data = { .coeff = { 0x06371d, 0x0c6e3a, 0x06371d, 0x05bfd3, 0x031ca2 } } },
- { .channel = 0, .filter = 2, .data = { .coeff = { 0x0fa1c0, 0xe18692, 0x0f030e, 0xe18692, 0x0ea4ce } } },
- { .channel = 0, .filter = 3, .data = { .coeff = { 0x0fe495, 0xe17eff, 0x0f0452, 0xe17eff, 0x0ee8e7 } } },
- { .channel = 0, .filter = 4, .data = { .coeff = { 0x100857, 0xe7e71c, 0x0e9599, 0xe7e71c, 0x0e9df1 } } },
- { .channel = 0, .filter = 5, .data = { .coeff = { 0x0fb26e, 0x06a82c, 0x0db2b4, 0x06a82c, 0x0d6522 } } },
- { .channel = 0, .filter = 6, .data = { .coeff = { 0x11419d, 0xf06cbf, 0x0a4f6e, 0xf06cbf, 0x0b910c } } },
-
- { .channel = 1, .filter = 0, .data = { .coeff = { 0x0fb8fd, 0xe08e04, 0x0fb8fd, 0xe08f40, 0x0f7336 } } },
- { .channel = 1, .filter = 1, .data = { .coeff = { 0x06371d, 0x0c6e3a, 0x06371d, 0x05bfd3, 0x031ca2 } } },
- { .channel = 1, .filter = 2, .data = { .coeff = { 0x0fa1c0, 0xe18692, 0x0f030e, 0xe18692, 0x0ea4ce } } },
- { .channel = 1, .filter = 3, .data = { .coeff = { 0x0fe495, 0xe17eff, 0x0f0452, 0xe17eff, 0x0ee8e7 } } },
- { .channel = 1, .filter = 4, .data = { .coeff = { 0x100857, 0xe7e71c, 0x0e9599, 0xe7e71c, 0x0e9df1 } } },
- { .channel = 1, .filter = 5, .data = { .coeff = { 0x0fb26e, 0x06a82c, 0x0db2b4, 0x06a82c, 0x0d6522 } } },
- { .channel = 1, .filter = 6, .data = { .coeff = { 0x11419d, 0xf06cbf, 0x0a4f6e, 0xf06cbf, 0x0b910c } } }
-};
-
-static struct tas_eq_pref_t eqp_1a_1_0 = {
- .sample_rate = 44100,
- .device_id = 0x1a,
- .output_id = TAS_OUTPUT_INTERNAL_SPKR,
- .speaker_id = 0x00,
-
- .drce = &eqp_1a_1_0_drce,
-
- .filter_count = 14,
- .biquads = eqp_1a_1_0_biquads
-};
-
-/* ======================================================================== */
-
-static struct tas_drce_t eqp_1c_1_0_drce={
- .enable = 1,
- .above = { .val = 3.0 * (1<<8), .expand = 0 },
- .below = { .val = 1.0 * (1<<8), .expand = 0 },
- .threshold = -14.34 * (1<<8),
- .energy = 2.4 * (1<<12),
- .attack = 0.013 * (1<<12),
- .decay = 0.212 * (1<<12),
-};
-
-static struct tas_biquad_ctrl_t eqp_1c_1_0_biquads[]={
- { .channel = 0, .filter = 0, .data = { .coeff = { 0x0f4f95, 0xe160d4, 0x0f4f95, 0xe1686e, 0x0ea6c5 } } },
- { .channel = 0, .filter = 1, .data = { .coeff = { 0x066b92, 0x0290d4, 0x0148a0, 0xf6853f, 0x03bfc7 } } },
- { .channel = 0, .filter = 2, .data = { .coeff = { 0x0f57dc, 0xe51c91, 0x0dd1cb, 0xe51c91, 0x0d29a8 } } },
- { .channel = 0, .filter = 3, .data = { .coeff = { 0x0df1cb, 0xe4fa84, 0x0d7cdc, 0xe4fa84, 0x0b6ea7 } } },
- { .channel = 0, .filter = 4, .data = { .coeff = { 0x0eba36, 0xe6aa48, 0x0b9f52, 0xe6aa48, 0x0a5989 } } },
- { .channel = 0, .filter = 5, .data = { .coeff = { 0x0caf02, 0x05ef9d, 0x084beb, 0x05ef9d, 0x04faee } } },
- { .channel = 0, .filter = 6, .data = { .coeff = { 0x0fc686, 0xe22947, 0x0e4b5d, 0xe22947, 0x0e11e4 } } },
-
- { .channel = 1, .filter = 0, .data = { .coeff = { 0x0f4f95, 0xe160d4, 0x0f4f95, 0xe1686e, 0x0ea6c5 } } },
- { .channel = 1, .filter = 1, .data = { .coeff = { 0x066b92, 0x0290d4, 0x0148a0, 0xf6853f, 0x03bfc7 } } },
- { .channel = 1, .filter = 2, .data = { .coeff = { 0x0f57dc, 0xe51c91, 0x0dd1cb, 0xe51c91, 0x0d29a8 } } },
- { .channel = 1, .filter = 3, .data = { .coeff = { 0x0df1cb, 0xe4fa84, 0x0d7cdc, 0xe4fa84, 0x0b6ea7 } } },
- { .channel = 1, .filter = 4, .data = { .coeff = { 0x0eba36, 0xe6aa48, 0x0b9f52, 0xe6aa48, 0x0a5989 } } },
- { .channel = 1, .filter = 5, .data = { .coeff = { 0x0caf02, 0x05ef9d, 0x084beb, 0x05ef9d, 0x04faee } } },
- { .channel = 1, .filter = 6, .data = { .coeff = { 0x0fc686, 0xe22947, 0x0e4b5d, 0xe22947, 0x0e11e4 } } }
-};
-
-static struct tas_eq_pref_t eqp_1c_1_0 = {
- .sample_rate = 44100,
- .device_id = 0x1c,
- .output_id = TAS_OUTPUT_INTERNAL_SPKR,
- .speaker_id = 0x00,
-
- .drce = &eqp_1c_1_0_drce,
-
- .filter_count = 14,
- .biquads = eqp_1c_1_0_biquads
-};
-
-/* ======================================================================== */
-
-static uint tas3004_master_tab[]={
- 0x0, 0x75, 0x9c, 0xbb,
- 0xdb, 0xfb, 0x11e, 0x143,
- 0x16b, 0x196, 0x1c3, 0x1f5,
- 0x229, 0x263, 0x29f, 0x2e1,
- 0x328, 0x373, 0x3c5, 0x41b,
- 0x478, 0x4dc, 0x547, 0x5b8,
- 0x633, 0x6b5, 0x740, 0x7d5,
- 0x873, 0x91c, 0x9d2, 0xa92,
- 0xb5e, 0xc39, 0xd22, 0xe19,
- 0xf20, 0x1037, 0x1161, 0x129e,
- 0x13ed, 0x1551, 0x16ca, 0x185d,
- 0x1a08, 0x1bcc, 0x1dac, 0x1fa7,
- 0x21c1, 0x23fa, 0x2655, 0x28d6,
- 0x2b7c, 0x2e4a, 0x3141, 0x3464,
- 0x37b4, 0x3b35, 0x3ee9, 0x42d3,
- 0x46f6, 0x4b53, 0x4ff0, 0x54ce,
- 0x59f2, 0x5f5f, 0x6519, 0x6b24,
- 0x7183, 0x783c, 0x7f53, 0x86cc,
- 0x8ead, 0x96fa, 0x9fba, 0xa8f2,
- 0xb2a7, 0xbce1, 0xc7a5, 0xd2fa,
- 0xdee8, 0xeb75, 0xf8aa, 0x1068e,
- 0x1152a, 0x12487, 0x134ad, 0x145a5,
- 0x1577b, 0x16a37, 0x17df5, 0x192bd,
- 0x1a890, 0x1bf7b, 0x1d78d, 0x1f0d1,
- 0x20b55, 0x22727, 0x24456, 0x262f2,
- 0x2830b
-};
-
-static uint tas3004_mixer_tab[]={
- 0x0, 0x748, 0x9be, 0xbaf,
- 0xda4, 0xfb1, 0x11de, 0x1431,
- 0x16ad, 0x1959, 0x1c37, 0x1f4b,
- 0x2298, 0x2628, 0x29fb, 0x2e12,
- 0x327d, 0x3734, 0x3c47, 0x41b4,
- 0x4787, 0x4dbe, 0x546d, 0x5b86,
- 0x632e, 0x6b52, 0x7400, 0x7d54,
- 0x873b, 0x91c6, 0x9d1a, 0xa920,
- 0xb5e5, 0xc38c, 0xd21b, 0xe18f,
- 0xf1f5, 0x1036a, 0x1160f, 0x129d6,
- 0x13ed0, 0x1550c, 0x16ca0, 0x185c9,
- 0x1a07b, 0x1bcc3, 0x1dab9, 0x1fa75,
- 0x21c0f, 0x23fa3, 0x26552, 0x28d64,
- 0x2b7c9, 0x2e4a2, 0x31411, 0x3463b,
- 0x37b44, 0x3b353, 0x3ee94, 0x42d30,
- 0x46f55, 0x4b533, 0x4fefc, 0x54ce5,
- 0x59f25, 0x5f5f6, 0x65193, 0x6b23c,
- 0x71835, 0x783c3, 0x7f52c, 0x86cc0,
- 0x8eacc, 0x96fa5, 0x9fba0, 0xa8f1a,
- 0xb2a71, 0xbce0a, 0xc7a4a, 0xd2fa0,
- 0xdee7b, 0xeb752, 0xf8a9f, 0x1068e4,
- 0x1152a3, 0x12486a, 0x134ac8, 0x145a55,
- 0x1577ac, 0x16a370, 0x17df51, 0x192bc2,
- 0x1a88f8, 0x1bf7b7, 0x1d78c9, 0x1f0d04,
- 0x20b542, 0x227268, 0x244564, 0x262f26,
- 0x2830af
-};
-
-static uint tas3004_treble_tab[]={
- 0x96, 0x95, 0x95, 0x94,
- 0x93, 0x92, 0x92, 0x91,
- 0x90, 0x90, 0x8f, 0x8e,
- 0x8d, 0x8d, 0x8c, 0x8b,
- 0x8a, 0x8a, 0x89, 0x88,
- 0x88, 0x87, 0x86, 0x85,
- 0x85, 0x84, 0x83, 0x83,
- 0x82, 0x81, 0x80, 0x80,
- 0x7f, 0x7e, 0x7e, 0x7d,
- 0x7c, 0x7b, 0x7b, 0x7a,
- 0x79, 0x78, 0x78, 0x77,
- 0x76, 0x76, 0x75, 0x74,
- 0x73, 0x73, 0x72, 0x71,
- 0x71, 0x68, 0x45, 0x5b,
- 0x6d, 0x6c, 0x6b, 0x6a,
- 0x69, 0x68, 0x67, 0x66,
- 0x65, 0x63, 0x62, 0x62,
- 0x60, 0x5e, 0x5c, 0x5b,
- 0x59, 0x57, 0x55, 0x53,
- 0x52, 0x4f, 0x4d, 0x4a,
- 0x48, 0x46, 0x43, 0x40,
- 0x3d, 0x3a, 0x36, 0x33,
- 0x2f, 0x2c, 0x27, 0x23,
- 0x1f, 0x1a, 0x15, 0xf,
- 0x8, 0x5, 0x2, 0x1,
- 0x1
-};
-
-static uint tas3004_bass_tab[]={
- 0x96, 0x95, 0x95, 0x94,
- 0x93, 0x92, 0x92, 0x91,
- 0x90, 0x90, 0x8f, 0x8e,
- 0x8d, 0x8d, 0x8c, 0x8b,
- 0x8a, 0x8a, 0x89, 0x88,
- 0x88, 0x87, 0x86, 0x85,
- 0x85, 0x84, 0x83, 0x83,
- 0x82, 0x81, 0x80, 0x80,
- 0x7f, 0x7e, 0x7e, 0x7d,
- 0x7c, 0x7b, 0x7b, 0x7a,
- 0x79, 0x78, 0x78, 0x77,
- 0x76, 0x76, 0x75, 0x74,
- 0x73, 0x73, 0x72, 0x71,
- 0x70, 0x6f, 0x6e, 0x6d,
- 0x6c, 0x6b, 0x6a, 0x6a,
- 0x69, 0x67, 0x66, 0x66,
- 0x65, 0x63, 0x62, 0x62,
- 0x61, 0x60, 0x5e, 0x5d,
- 0x5b, 0x59, 0x57, 0x55,
- 0x53, 0x51, 0x4f, 0x4c,
- 0x4a, 0x48, 0x46, 0x44,
- 0x41, 0x3e, 0x3b, 0x38,
- 0x36, 0x33, 0x2f, 0x2b,
- 0x28, 0x24, 0x20, 0x1c,
- 0x17, 0x12, 0xd, 0x7,
- 0x1
-};
-
-struct tas_gain_t tas3004_gain={
- .master = tas3004_master_tab,
- .treble = tas3004_treble_tab,
- .bass = tas3004_bass_tab,
- .mixer = tas3004_mixer_tab
-};
-
-struct tas_eq_pref_t *tas3004_eq_prefs[]={
- &eqp_17_1_0,
- &eqp_18_1_0,
- &eqp_1a_1_0,
- &eqp_1c_1_0,
- NULL
-};
diff --git a/sound/oss/dmasound/tas_common.c b/sound/oss/dmasound/tas_common.c
deleted file mode 100644
index b295ef682192..000000000000
--- a/sound/oss/dmasound/tas_common.c
+++ /dev/null
@@ -1,214 +0,0 @@
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/proc_fs.h>
-#include <linux/ioport.h>
-#include <linux/sysctl.h>
-#include <linux/types.h>
-#include <linux/i2c.h>
-#include <linux/init.h>
-#include <linux/soundcard.h>
-#include <asm/uaccess.h>
-#include <asm/errno.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-
-#include "tas_common.h"
-
-#define CALL0(proc) \
- do { \
- struct tas_data_t *self; \
- if (!tas_client || driver_hooks == NULL) \
- return -1; \
- self = dev_get_drvdata(&tas_client->dev); \
- if (driver_hooks->proc) \
- return driver_hooks->proc(self); \
- else \
- return -EINVAL; \
- } while (0)
-
-#define CALL(proc,arg...) \
- do { \
- struct tas_data_t *self; \
- if (!tas_client || driver_hooks == NULL) \
- return -1; \
- self = dev_get_drvdata(&tas_client->dev); \
- if (driver_hooks->proc) \
- return driver_hooks->proc(self, ## arg); \
- else \
- return -EINVAL; \
- } while (0)
-
-
-static u8 tas_i2c_address = 0x34;
-static struct i2c_client *tas_client;
-
-static int tas_attach_adapter(struct i2c_adapter *);
-static int tas_detach_client(struct i2c_client *);
-
-struct i2c_driver tas_driver = {
- .driver = {
- .name = "tas",
- },
- .attach_adapter = tas_attach_adapter,
- .detach_client = tas_detach_client,
-};
-
-struct tas_driver_hooks_t *driver_hooks;
-
-int
-tas_register_driver(struct tas_driver_hooks_t *hooks)
-{
- driver_hooks = hooks;
- return 0;
-}
-
-int
-tas_get_mixer_level(int mixer, uint *level)
-{
- CALL(get_mixer_level,mixer,level);
-}
-
-int
-tas_set_mixer_level(int mixer,uint level)
-{
- CALL(set_mixer_level,mixer,level);
-}
-
-int
-tas_enter_sleep(void)
-{
- CALL0(enter_sleep);
-}
-
-int
-tas_leave_sleep(void)
-{
- CALL0(leave_sleep);
-}
-
-int
-tas_supported_mixers(void)
-{
- CALL0(supported_mixers);
-}
-
-int
-tas_mixer_is_stereo(int mixer)
-{
- CALL(mixer_is_stereo,mixer);
-}
-
-int
-tas_stereo_mixers(void)
-{
- CALL0(stereo_mixers);
-}
-
-int
-tas_output_device_change(int device_id,int layout_id,int speaker_id)
-{
- CALL(output_device_change,device_id,layout_id,speaker_id);
-}
-
-int
-tas_device_ioctl(u_int cmd, u_long arg)
-{
- CALL(device_ioctl,cmd,arg);
-}
-
-int
-tas_post_init(void)
-{
- CALL0(post_init);
-}
-
-static int
-tas_detect_client(struct i2c_adapter *adapter, int address)
-{
- static const char *client_name = "tas Digital Equalizer";
- struct i2c_client *new_client;
- int rc = -ENODEV;
-
- if (!driver_hooks) {
- printk(KERN_ERR "tas_detect_client called with no hooks !\n");
- return -ENODEV;
- }
-
- new_client = kzalloc(sizeof(*new_client), GFP_KERNEL);
- if (!new_client)
- return -ENOMEM;
-
- new_client->addr = address;
- new_client->adapter = adapter;
- new_client->driver = &tas_driver;
- strlcpy(new_client->name, client_name, DEVICE_NAME_SIZE);
-
- if (driver_hooks->init(new_client))
- goto bail;
-
- /* Tell the i2c layer a new client has arrived */
- if (i2c_attach_client(new_client)) {
- driver_hooks->uninit(dev_get_drvdata(&new_client->dev));
- goto bail;
- }
-
- tas_client = new_client;
- return 0;
- bail:
- tas_client = NULL;
- kfree(new_client);
- return rc;
-}
-
-static int
-tas_attach_adapter(struct i2c_adapter *adapter)
-{
- if (!strncmp(adapter->name, "mac-io", 6))
- return tas_detect_client(adapter, tas_i2c_address);
- return 0;
-}
-
-static int
-tas_detach_client(struct i2c_client *client)
-{
- if (client == tas_client) {
- driver_hooks->uninit(dev_get_drvdata(&client->dev));
-
- i2c_detach_client(client);
- kfree(client);
- }
- return 0;
-}
-
-void
-tas_cleanup(void)
-{
- i2c_del_driver(&tas_driver);
-}
-
-int __init
-tas_init(int driver_id, const char *driver_name)
-{
- const u32* paddr;
- struct device_node *tas_node;
-
- printk(KERN_INFO "tas driver [%s])\n", driver_name);
-
-#ifndef CONFIG_I2C_POWERMAC
- request_module("i2c-powermac");
-#endif
- tas_node = of_find_node_by_name("deq");
- if (tas_node == NULL)
- return -ENODEV;
- paddr = of_get_property(tas_node, "i2c-address", NULL);
- if (paddr) {
- tas_i2c_address = (*paddr) >> 1;
- printk(KERN_INFO "using i2c address: 0x%x from device-tree\n",
- tas_i2c_address);
- } else
- printk(KERN_INFO "using i2c address: 0x%x (default)\n",
- tas_i2c_address);
- of_node_put(tas_node);
-
- return i2c_add_driver(&tas_driver);
-}
diff --git a/sound/oss/dmasound/tas_common.h b/sound/oss/dmasound/tas_common.h
deleted file mode 100644
index 0741c28e56ce..000000000000
--- a/sound/oss/dmasound/tas_common.h
+++ /dev/null
@@ -1,284 +0,0 @@
-#ifndef _TAS_COMMON_H_
-#define _TAS_COMMON_H_
-
-#include <linux/i2c.h>
-#include <linux/soundcard.h>
-#include <asm/string.h>
-
-#define I2C_DRIVERID_TAS_BASE (0xFEBA)
-
-#define SET_4_20(shadow, offset, val) \
- do { \
- (shadow)[(offset)+0] = ((val) >> 16) & 0xff; \
- (shadow)[(offset)+1] = ((val) >> 8) & 0xff; \
- (shadow)[(offset)+2] = ((val) >> 0) & 0xff; \
- } while (0)
-
-#define GET_4_20(shadow, offset) \
- (((u_int)((shadow)[(offset)+0]) << 16) | \
- ((u_int)((shadow)[(offset)+1]) << 8) | \
- ((u_int)((shadow)[(offset)+2]) << 0))
-
-
-#define TAS_BIQUAD_FAST_LOAD 0x01
-
-#define TAS_DRCE_ENABLE 0x01
-#define TAS_DRCE_ABOVE_RATIO 0x02
-#define TAS_DRCE_BELOW_RATIO 0x04
-#define TAS_DRCE_THRESHOLD 0x08
-#define TAS_DRCE_ENERGY 0x10
-#define TAS_DRCE_ATTACK 0x20
-#define TAS_DRCE_DECAY 0x40
-
-#define TAS_DRCE_ALL 0x7f
-
-
-#define TAS_OUTPUT_HEADPHONES 0x00
-#define TAS_OUTPUT_INTERNAL_SPKR 0x01
-#define TAS_OUTPUT_EXTERNAL_SPKR 0x02
-
-
-union tas_biquad_t {
- struct {
- int b0,b1,b2,a1,a2;
- } coeff;
- int buf[5];
-};
-
-struct tas_biquad_ctrl_t {
- u_int channel:4;
- u_int filter:4;
-
- union tas_biquad_t data;
-};
-
-struct tas_biquad_ctrl_list_t {
- int flags;
- int filter_count;
- struct tas_biquad_ctrl_t biquads[0];
-};
-
-struct tas_ratio_t {
- unsigned short val; /* 8.8 */
- unsigned short expand; /* 0 = compress, !0 = expand. */
-};
-
-struct tas_drce_t {
- unsigned short enable;
- struct tas_ratio_t above;
- struct tas_ratio_t below;
- short threshold; /* dB, 8.8 signed */
- unsigned short energy; /* seconds, 4.12 unsigned */
- unsigned short attack; /* seconds, 4.12 unsigned */
- unsigned short decay; /* seconds, 4.12 unsigned */
-};
-
-struct tas_drce_ctrl_t {
- uint flags;
-
- struct tas_drce_t data;
-};
-
-struct tas_gain_t
-{
- unsigned int *master;
- unsigned int *treble;
- unsigned int *bass;
- unsigned int *mixer;
-};
-
-typedef char tas_shadow_t[0x45];
-
-struct tas_data_t
-{
- struct i2c_client *client;
- tas_shadow_t *shadow;
- uint mixer[SOUND_MIXER_NRDEVICES];
-};
-
-typedef int (*tas_hook_init_t)(struct i2c_client *);
-typedef int (*tas_hook_post_init_t)(struct tas_data_t *);
-typedef void (*tas_hook_uninit_t)(struct tas_data_t *);
-
-typedef int (*tas_hook_get_mixer_level_t)(struct tas_data_t *,int,uint *);
-typedef int (*tas_hook_set_mixer_level_t)(struct tas_data_t *,int,uint);
-
-typedef int (*tas_hook_enter_sleep_t)(struct tas_data_t *);
-typedef int (*tas_hook_leave_sleep_t)(struct tas_data_t *);
-
-typedef int (*tas_hook_supported_mixers_t)(struct tas_data_t *);
-typedef int (*tas_hook_mixer_is_stereo_t)(struct tas_data_t *,int);
-typedef int (*tas_hook_stereo_mixers_t)(struct tas_data_t *);
-
-typedef int (*tas_hook_output_device_change_t)(struct tas_data_t *,int,int,int);
-typedef int (*tas_hook_device_ioctl_t)(struct tas_data_t *,u_int,u_long);
-
-struct tas_driver_hooks_t {
- /*
- * All hardware initialisation must be performed in
- * post_init(), as tas_dmasound_init() does a hardware reset.
- *
- * init() is called before tas_dmasound_init() so that
- * ouput_device_change() is always called after i2c driver
- * initialisation. The implication is that
- * output_device_change() must cope with the fact that it
- * may be called before post_init().
- */
-
- tas_hook_init_t init;
- tas_hook_post_init_t post_init;
- tas_hook_uninit_t uninit;
-
- tas_hook_get_mixer_level_t get_mixer_level;
- tas_hook_set_mixer_level_t set_mixer_level;
-
- tas_hook_enter_sleep_t enter_sleep;
- tas_hook_leave_sleep_t leave_sleep;
-
- tas_hook_supported_mixers_t supported_mixers;
- tas_hook_mixer_is_stereo_t mixer_is_stereo;
- tas_hook_stereo_mixers_t stereo_mixers;
-
- tas_hook_output_device_change_t output_device_change;
- tas_hook_device_ioctl_t device_ioctl;
-};
-
-enum tas_write_mode_t {
- WRITE_HW = 0x01,
- WRITE_SHADOW = 0x02,
- WRITE_NORMAL = 0x03,
- FORCE_WRITE = 0x04
-};
-
-static inline uint
-tas_mono_to_stereo(uint mono)
-{
- mono &=0xff;
- return mono | (mono<<8);
-}
-
-/*
- * Todo: make these functions a bit more efficient !
- */
-static inline int
-tas_write_register( struct tas_data_t *self,
- uint reg_num,
- uint reg_width,
- char *data,
- uint write_mode)
-{
- int rc;
-
- if (reg_width==0 || data==NULL || self==NULL)
- return -EINVAL;
- if (!(write_mode & FORCE_WRITE) &&
- !memcmp(data,self->shadow[reg_num],reg_width))
- return 0;
-
- if (write_mode & WRITE_SHADOW)
- memcpy(self->shadow[reg_num],data,reg_width);
- if (write_mode & WRITE_HW) {
- rc=i2c_smbus_write_i2c_block_data(self->client,
- reg_num,
- reg_width,
- data);
- if (rc < 0) {
- printk("tas: I2C block write failed \n");
- return rc;
- }
- }
- return 0;
-}
-
-static inline int
-tas_sync_register( struct tas_data_t *self,
- uint reg_num,
- uint reg_width)
-{
- int rc;
-
- if (reg_width==0 || self==NULL)
- return -EINVAL;
- rc=i2c_smbus_write_i2c_block_data(self->client,
- reg_num,
- reg_width,
- self->shadow[reg_num]);
- if (rc < 0) {
- printk("tas: I2C block write failed \n");
- return rc;
- }
- return 0;
-}
-
-static inline int
-tas_write_byte_register( struct tas_data_t *self,
- uint reg_num,
- char data,
- uint write_mode)
-{
- if (self==NULL)
- return -1;
- if (!(write_mode & FORCE_WRITE) && data != self->shadow[reg_num][0])
- return 0;
- if (write_mode & WRITE_SHADOW)
- self->shadow[reg_num][0]=data;
- if (write_mode & WRITE_HW) {
- if (i2c_smbus_write_byte_data(self->client, reg_num, data) < 0) {
- printk("tas: I2C byte write failed \n");
- return -1;
- }
- }
- return 0;
-}
-
-static inline int
-tas_sync_byte_register( struct tas_data_t *self,
- uint reg_num,
- uint reg_width)
-{
- if (reg_width==0 || self==NULL)
- return -1;
- if (i2c_smbus_write_byte_data(
- self->client, reg_num, self->shadow[reg_num][0]) < 0) {
- printk("tas: I2C byte write failed \n");
- return -1;
- }
- return 0;
-}
-
-static inline int
-tas_read_register( struct tas_data_t *self,
- uint reg_num,
- uint reg_width,
- char *data)
-{
- if (reg_width==0 || data==NULL || self==NULL)
- return -1;
- memcpy(data,self->shadow[reg_num],reg_width);
- return 0;
-}
-
-extern int tas_register_driver(struct tas_driver_hooks_t *hooks);
-
-extern int tas_get_mixer_level(int mixer,uint *level);
-extern int tas_set_mixer_level(int mixer,uint level);
-extern int tas_enter_sleep(void);
-extern int tas_leave_sleep(void);
-extern int tas_supported_mixers(void);
-extern int tas_mixer_is_stereo(int mixer);
-extern int tas_stereo_mixers(void);
-extern int tas_output_device_change(int,int,int);
-extern int tas_device_ioctl(u_int, u_long);
-
-extern void tas_cleanup(void);
-extern int tas_init(int driver_id,const char *driver_name);
-extern int tas_post_init(void);
-
-#endif /* _TAS_COMMON_H_ */
-/*
- * Local Variables:
- * tab-width: 8
- * indent-tabs-mode: t
- * c-basic-offset: 8
- * End:
- */
diff --git a/sound/oss/dmasound/tas_eq_prefs.h b/sound/oss/dmasound/tas_eq_prefs.h
deleted file mode 100644
index 3a994eda6abc..000000000000
--- a/sound/oss/dmasound/tas_eq_prefs.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef _TAS_EQ_PREFS_H_
-#define _TAS_EQ_PREFS_H_
-
-struct tas_eq_pref_t {
- u_int sample_rate;
- u_int device_id;
- u_int output_id;
- u_int speaker_id;
-
- struct tas_drce_t *drce;
-
- u_int filter_count;
- struct tas_biquad_ctrl_t *biquads;
-};
-
-#endif /* _TAS_EQ_PREFS_H_ */
-
-/*
- * Local Variables:
- * tab-width: 8
- * indent-tabs-mode: t
- * c-basic-offset: 8
- * End:
- */
diff --git a/sound/oss/dmasound/tas_ioctl.h b/sound/oss/dmasound/tas_ioctl.h
deleted file mode 100644
index 9d12b373b4a9..000000000000
--- a/sound/oss/dmasound/tas_ioctl.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef _TAS_IOCTL_H_
-#define _TAS_IOCTL_H_
-
-#include <linux/soundcard.h>
-
-
-#define TAS_READ_EQ _SIOR('t',0,struct tas_biquad_ctrl_t)
-#define TAS_WRITE_EQ _SIOW('t',0,struct tas_biquad_ctrl_t)
-
-#define TAS_READ_EQ_LIST _SIOR('t',1,struct tas_biquad_ctrl_t)
-#define TAS_WRITE_EQ_LIST _SIOW('t',1,struct tas_biquad_ctrl_t)
-
-#define TAS_READ_EQ_FILTER_COUNT _SIOR('t',2,int)
-#define TAS_READ_EQ_CHANNEL_COUNT _SIOR('t',3,int)
-
-#define TAS_READ_DRCE _SIOR('t',4,struct tas_drce_ctrl_t)
-#define TAS_WRITE_DRCE _SIOW('t',4,struct tas_drce_ctrl_t)
-
-#define TAS_READ_DRCE_CAPS _SIOR('t',5,int)
-#define TAS_READ_DRCE_MIN _SIOR('t',6,int)
-#define TAS_READ_DRCE_MAX _SIOR('t',7,int)
-
-#endif
diff --git a/sound/oss/dmasound/trans_16.c b/sound/oss/dmasound/trans_16.c
deleted file mode 100644
index ca973ac2a30a..000000000000
--- a/sound/oss/dmasound/trans_16.c
+++ /dev/null
@@ -1,898 +0,0 @@
-/*
- * linux/sound/oss/dmasound/trans_16.c
- *
- * 16 bit translation routines. Only used by Power mac at present.
- *
- * See linux/sound/oss/dmasound/dmasound_core.c for copyright and
- * history prior to 08/02/2001.
- *
- * 08/02/2001 Iain Sandoe
- * split from dmasound_awacs.c
- * 11/29/2003 Renzo Davoli (King Enzo)
- * - input resampling (for soft rate < hard rate)
- * - software line in gain control
- */
-
-#include <linux/soundcard.h>
-#include <asm/uaccess.h>
-#include "dmasound.h"
-
-extern int expand_bal; /* Balance factor for expanding (not volume!) */
-static short dmasound_alaw2dma16[] ;
-static short dmasound_ulaw2dma16[] ;
-
-static ssize_t pmac_ct_law(const u_char __user *userPtr, size_t userCount,
- u_char frame[], ssize_t *frameUsed,
- ssize_t frameLeft);
-static ssize_t pmac_ct_s8(const u_char __user *userPtr, size_t userCount,
- u_char frame[], ssize_t *frameUsed,
- ssize_t frameLeft);
-static ssize_t pmac_ct_u8(const u_char __user *userPtr, size_t userCount,
- u_char frame[], ssize_t *frameUsed,
- ssize_t frameLeft);
-static ssize_t pmac_ct_s16(const u_char __user *userPtr, size_t userCount,
- u_char frame[], ssize_t *frameUsed,
- ssize_t frameLeft);
-static ssize_t pmac_ct_u16(const u_char __user *userPtr, size_t userCount,
- u_char frame[], ssize_t *frameUsed,
- ssize_t frameLeft);
-
-static ssize_t pmac_ctx_law(const u_char __user *userPtr, size_t userCount,
- u_char frame[], ssize_t *frameUsed,
- ssize_t frameLeft);
-static ssize_t pmac_ctx_s8(const u_char __user *userPtr, size_t userCount,
- u_char frame[], ssize_t *frameUsed,
- ssize_t frameLeft);
-static ssize_t pmac_ctx_u8(const u_char __user *userPtr, size_t userCount,
- u_char frame[], ssize_t *frameUsed,
- ssize_t frameLeft);
-static ssize_t pmac_ctx_s16(const u_char __user *userPtr, size_t userCount,
- u_char frame[], ssize_t *frameUsed,
- ssize_t frameLeft);
-static ssize_t pmac_ctx_u16(const u_char __user *userPtr, size_t userCount,
- u_char frame[], ssize_t *frameUsed,
- ssize_t frameLeft);
-
-static ssize_t pmac_ct_s16_read(const u_char __user *userPtr, size_t userCount,
- u_char frame[], ssize_t *frameUsed,
- ssize_t frameLeft);
-static ssize_t pmac_ct_u16_read(const u_char __user *userPtr, size_t userCount,
- u_char frame[], ssize_t *frameUsed,
- ssize_t frameLeft);
-
-/*** Translations ************************************************************/
-
-static int expand_data; /* Data for expanding */
-
-static ssize_t pmac_ct_law(const u_char __user *userPtr, size_t userCount,
- u_char frame[], ssize_t *frameUsed,
- ssize_t frameLeft)
-{
- short *table = dmasound.soft.format == AFMT_MU_LAW
- ? dmasound_ulaw2dma16 : dmasound_alaw2dma16;
- ssize_t count, used;
- short *p = (short *) &frame[*frameUsed];
- int val, stereo = dmasound.soft.stereo;
-
- frameLeft >>= 2;
- if (stereo)
- userCount >>= 1;
- used = count = min_t(unsigned long, userCount, frameLeft);
- while (count > 0) {
- u_char data;
- if (get_user(data, userPtr++))
- return -EFAULT;
- val = table[data];
- *p++ = val;
- if (stereo) {
- if (get_user(data, userPtr++))
- return -EFAULT;
- val = table[data];
- }
- *p++ = val;
- count--;
- }
- *frameUsed += used * 4;
- return stereo? used * 2: used;
-}
-
-
-static ssize_t pmac_ct_s8(const u_char __user *userPtr, size_t userCount,
- u_char frame[], ssize_t *frameUsed,
- ssize_t frameLeft)
-{
- ssize_t count, used;
- short *p = (short *) &frame[*frameUsed];
- int val, stereo = dmasound.soft.stereo;
-
- frameLeft >>= 2;
- if (stereo)
- userCount >>= 1;
- used = count = min_t(unsigned long, userCount, frameLeft);
- while (count > 0) {
- u_char data;
- if (get_user(data, userPtr++))
- return -EFAULT;
- val = data << 8;
- *p++ = val;
- if (stereo) {
- if (get_user(data, userPtr++))
- return -EFAULT;
- val = data << 8;
- }
- *p++ = val;
- count--;
- }
- *frameUsed += used * 4;
- return stereo? used * 2: used;
-}
-
-
-static ssize_t pmac_ct_u8(const u_char __user *userPtr, size_t userCount,
- u_char frame[], ssize_t *frameUsed,
- ssize_t frameLeft)
-{
- ssize_t count, used;
- short *p = (short *) &frame[*frameUsed];
- int val, stereo = dmasound.soft.stereo;
-
- frameLeft >>= 2;
- if (stereo)
- userCount >>= 1;
- used = count = min_t(unsigned long, userCount, frameLeft);
- while (count > 0) {
- u_char data;
- if (get_user(data, userPtr++))
- return -EFAULT;
- val = (data ^ 0x80) << 8;
- *p++ = val;
- if (stereo) {
- if (get_user(data, userPtr++))
- return -EFAULT;
- val = (data ^ 0x80) << 8;
- }
- *p++ = val;
- count--;
- }
- *frameUsed += used * 4;
- return stereo? used * 2: used;
-}
-
-
-static ssize_t pmac_ct_s16(const u_char __user *userPtr, size_t userCount,
- u_char frame[], ssize_t *frameUsed,
- ssize_t frameLeft)
-{
- ssize_t count, used;
- int stereo = dmasound.soft.stereo;
- short *fp = (short *) &frame[*frameUsed];
-
- frameLeft >>= 2;
- userCount >>= (stereo? 2: 1);
- used = count = min_t(unsigned long, userCount, frameLeft);
- if (!stereo) {
- short __user *up = (short __user *) userPtr;
- while (count > 0) {
- short data;
- if (get_user(data, up++))
- return -EFAULT;
- *fp++ = data;
- *fp++ = data;
- count--;
- }
- } else {
- if (copy_from_user(fp, userPtr, count * 4))
- return -EFAULT;
- }
- *frameUsed += used * 4;
- return stereo? used * 4: used * 2;
-}
-
-static ssize_t pmac_ct_u16(const u_char __user *userPtr, size_t userCount,
- u_char frame[], ssize_t *frameUsed,
- ssize_t frameLeft)
-{
- ssize_t count, used;
- int mask = (dmasound.soft.format == AFMT_U16_LE? 0x0080: 0x8000);
- int stereo = dmasound.soft.stereo;
- short *fp = (short *) &frame[*frameUsed];
- short __user *up = (short __user *) userPtr;
-
- frameLeft >>= 2;
- userCount >>= (stereo? 2: 1);
- used = count = min_t(unsigned long, userCount, frameLeft);
- while (count > 0) {
- short data;
- if (get_user(data, up++))
- return -EFAULT;
- data ^= mask;
- *fp++ = data;
- if (stereo) {
- if (get_user(data, up++))
- return -EFAULT;
- data ^= mask;
- }
- *fp++ = data;
- count--;
- }
- *frameUsed += used * 4;
- return stereo? used * 4: used * 2;
-}
-
-
-static ssize_t pmac_ctx_law(const u_char __user *userPtr, size_t userCount,
- u_char frame[], ssize_t *frameUsed,
- ssize_t frameLeft)
-{
- unsigned short *table = (unsigned short *)
- (dmasound.soft.format == AFMT_MU_LAW
- ? dmasound_ulaw2dma16 : dmasound_alaw2dma16);
- unsigned int data = expand_data;
- unsigned int *p = (unsigned int *) &frame[*frameUsed];
- int bal = expand_bal;
- int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
- int utotal, ftotal;
- int stereo = dmasound.soft.stereo;
-
- frameLeft >>= 2;
- if (stereo)
- userCount >>= 1;
- ftotal = frameLeft;
- utotal = userCount;
- while (frameLeft) {
- u_char c;
- if (bal < 0) {
- if (userCount == 0)
- break;
- if (get_user(c, userPtr++))
- return -EFAULT;
- data = table[c];
- if (stereo) {
- if (get_user(c, userPtr++))
- return -EFAULT;
- data = (data << 16) + table[c];
- } else
- data = (data << 16) + data;
- userCount--;
- bal += hSpeed;
- }
- *p++ = data;
- frameLeft--;
- bal -= sSpeed;
- }
- expand_bal = bal;
- expand_data = data;
- *frameUsed += (ftotal - frameLeft) * 4;
- utotal -= userCount;
- return stereo? utotal * 2: utotal;
-}
-
-static ssize_t pmac_ctx_s8(const u_char __user *userPtr, size_t userCount,
- u_char frame[], ssize_t *frameUsed,
- ssize_t frameLeft)
-{
- unsigned int *p = (unsigned int *) &frame[*frameUsed];
- unsigned int data = expand_data;
- int bal = expand_bal;
- int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
- int stereo = dmasound.soft.stereo;
- int utotal, ftotal;
-
- frameLeft >>= 2;
- if (stereo)
- userCount >>= 1;
- ftotal = frameLeft;
- utotal = userCount;
- while (frameLeft) {
- u_char c;
- if (bal < 0) {
- if (userCount == 0)
- break;
- if (get_user(c, userPtr++))
- return -EFAULT;
- data = c << 8;
- if (stereo) {
- if (get_user(c, userPtr++))
- return -EFAULT;
- data = (data << 16) + (c << 8);
- } else
- data = (data << 16) + data;
- userCount--;
- bal += hSpeed;
- }
- *p++ = data;
- frameLeft--;
- bal -= sSpeed;
- }
- expand_bal = bal;
- expand_data = data;
- *frameUsed += (ftotal - frameLeft) * 4;
- utotal -= userCount;
- return stereo? utotal * 2: utotal;
-}
-
-
-static ssize_t pmac_ctx_u8(const u_char __user *userPtr, size_t userCount,
- u_char frame[], ssize_t *frameUsed,
- ssize_t frameLeft)
-{
- unsigned int *p = (unsigned int *) &frame[*frameUsed];
- unsigned int data = expand_data;
- int bal = expand_bal;
- int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
- int stereo = dmasound.soft.stereo;
- int utotal, ftotal;
-
- frameLeft >>= 2;
- if (stereo)
- userCount >>= 1;
- ftotal = frameLeft;
- utotal = userCount;
- while (frameLeft) {
- u_char c;
- if (bal < 0) {
- if (userCount == 0)
- break;
- if (get_user(c, userPtr++))
- return -EFAULT;
- data = (c ^ 0x80) << 8;
- if (stereo) {
- if (get_user(c, userPtr++))
- return -EFAULT;
- data = (data << 16) + ((c ^ 0x80) << 8);
- } else
- data = (data << 16) + data;
- userCount--;
- bal += hSpeed;
- }
- *p++ = data;
- frameLeft--;
- bal -= sSpeed;
- }
- expand_bal = bal;
- expand_data = data;
- *frameUsed += (ftotal - frameLeft) * 4;
- utotal -= userCount;
- return stereo? utotal * 2: utotal;
-}
-
-
-static ssize_t pmac_ctx_s16(const u_char __user *userPtr, size_t userCount,
- u_char frame[], ssize_t *frameUsed,
- ssize_t frameLeft)
-{
- unsigned int *p = (unsigned int *) &frame[*frameUsed];
- unsigned int data = expand_data;
- unsigned short __user *up = (unsigned short __user *) userPtr;
- int bal = expand_bal;
- int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
- int stereo = dmasound.soft.stereo;
- int utotal, ftotal;
-
- frameLeft >>= 2;
- userCount >>= (stereo? 2: 1);
- ftotal = frameLeft;
- utotal = userCount;
- while (frameLeft) {
- unsigned short c;
- if (bal < 0) {
- if (userCount == 0)
- break;
- if (get_user(data, up++))
- return -EFAULT;
- if (stereo) {
- if (get_user(c, up++))
- return -EFAULT;
- data = (data << 16) + c;
- } else
- data = (data << 16) + data;
- userCount--;
- bal += hSpeed;
- }
- *p++ = data;
- frameLeft--;
- bal -= sSpeed;
- }
- expand_bal = bal;
- expand_data = data;
- *frameUsed += (ftotal - frameLeft) * 4;
- utotal -= userCount;
- return stereo? utotal * 4: utotal * 2;
-}
-
-
-static ssize_t pmac_ctx_u16(const u_char __user *userPtr, size_t userCount,
- u_char frame[], ssize_t *frameUsed,
- ssize_t frameLeft)
-{
- int mask = (dmasound.soft.format == AFMT_U16_LE? 0x0080: 0x8000);
- unsigned int *p = (unsigned int *) &frame[*frameUsed];
- unsigned int data = expand_data;
- unsigned short __user *up = (unsigned short __user *) userPtr;
- int bal = expand_bal;
- int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
- int stereo = dmasound.soft.stereo;
- int utotal, ftotal;
-
- frameLeft >>= 2;
- userCount >>= (stereo? 2: 1);
- ftotal = frameLeft;
- utotal = userCount;
- while (frameLeft) {
- unsigned short c;
- if (bal < 0) {
- if (userCount == 0)
- break;
- if (get_user(data, up++))
- return -EFAULT;
- data ^= mask;
- if (stereo) {
- if (get_user(c, up++))
- return -EFAULT;
- data = (data << 16) + (c ^ mask);
- } else
- data = (data << 16) + data;
- userCount--;
- bal += hSpeed;
- }
- *p++ = data;
- frameLeft--;
- bal -= sSpeed;
- }
- expand_bal = bal;
- expand_data = data;
- *frameUsed += (ftotal - frameLeft) * 4;
- utotal -= userCount;
- return stereo? utotal * 4: utotal * 2;
-}
-
-/* data in routines... */
-
-static ssize_t pmac_ct_s8_read(const u_char __user *userPtr, size_t userCount,
- u_char frame[], ssize_t *frameUsed,
- ssize_t frameLeft)
-{
- ssize_t count, used;
- short *p = (short *) &frame[*frameUsed];
- int val, stereo = dmasound.soft.stereo;
-
- frameLeft >>= 2;
- if (stereo)
- userCount >>= 1;
- used = count = min_t(unsigned long, userCount, frameLeft);
- while (count > 0) {
- u_char data;
-
- val = *p++;
- val = (val * software_input_volume) >> 7;
- data = val >> 8;
- if (put_user(data, (u_char __user *)userPtr++))
- return -EFAULT;
- if (stereo) {
- val = *p;
- val = (val * software_input_volume) >> 7;
- data = val >> 8;
- if (put_user(data, (u_char __user *)userPtr++))
- return -EFAULT;
- }
- p++;
- count--;
- }
- *frameUsed += used * 4;
- return stereo? used * 2: used;
-}
-
-
-static ssize_t pmac_ct_u8_read(const u_char __user *userPtr, size_t userCount,
- u_char frame[], ssize_t *frameUsed,
- ssize_t frameLeft)
-{
- ssize_t count, used;
- short *p = (short *) &frame[*frameUsed];
- int val, stereo = dmasound.soft.stereo;
-
- frameLeft >>= 2;
- if (stereo)
- userCount >>= 1;
- used = count = min_t(unsigned long, userCount, frameLeft);
- while (count > 0) {
- u_char data;
-
- val = *p++;
- val = (val * software_input_volume) >> 7;
- data = (val >> 8) ^ 0x80;
- if (put_user(data, (u_char __user *)userPtr++))
- return -EFAULT;
- if (stereo) {
- val = *p;
- val = (val * software_input_volume) >> 7;
- data = (val >> 8) ^ 0x80;
- if (put_user(data, (u_char __user *)userPtr++))
- return -EFAULT;
- }
- p++;
- count--;
- }
- *frameUsed += used * 4;
- return stereo? used * 2: used;
-}
-
-static ssize_t pmac_ct_s16_read(const u_char __user *userPtr, size_t userCount,
- u_char frame[], ssize_t *frameUsed,
- ssize_t frameLeft)
-{
- ssize_t count, used;
- int stereo = dmasound.soft.stereo;
- short *fp = (short *) &frame[*frameUsed];
- short __user *up = (short __user *) userPtr;
-
- frameLeft >>= 2;
- userCount >>= (stereo? 2: 1);
- used = count = min_t(unsigned long, userCount, frameLeft);
- while (count > 0) {
- short data;
-
- data = *fp++;
- data = (data * software_input_volume) >> 7;
- if (put_user(data, up++))
- return -EFAULT;
- if (stereo) {
- data = *fp;
- data = (data * software_input_volume) >> 7;
- if (put_user(data, up++))
- return -EFAULT;
- }
- fp++;
- count--;
- }
- *frameUsed += used * 4;
- return stereo? used * 4: used * 2;
-}
-
-static ssize_t pmac_ct_u16_read(const u_char __user *userPtr, size_t userCount,
- u_char frame[], ssize_t *frameUsed,
- ssize_t frameLeft)
-{
- ssize_t count, used;
- int mask = (dmasound.soft.format == AFMT_U16_LE? 0x0080: 0x8000);
- int stereo = dmasound.soft.stereo;
- short *fp = (short *) &frame[*frameUsed];
- short __user *up = (short __user *) userPtr;
-
- frameLeft >>= 2;
- userCount >>= (stereo? 2: 1);
- used = count = min_t(unsigned long, userCount, frameLeft);
- while (count > 0) {
- int data;
-
- data = *fp++;
- data = (data * software_input_volume) >> 7;
- data ^= mask;
- if (put_user(data, up++))
- return -EFAULT;
- if (stereo) {
- data = *fp;
- data = (data * software_input_volume) >> 7;
- data ^= mask;
- if (put_user(data, up++))
- return -EFAULT;
- }
- fp++;
- count--;
- }
- *frameUsed += used * 4;
- return stereo? used * 4: used * 2;
-}
-
-/* data in routines (reducing speed)... */
-
-static ssize_t pmac_ctx_s8_read(const u_char __user *userPtr, size_t userCount,
- u_char frame[], ssize_t *frameUsed,
- ssize_t frameLeft)
-{
- short *p = (short *) &frame[*frameUsed];
- int bal = expand_read_bal;
- int vall,valr, stereo = dmasound.soft.stereo;
- int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
- int utotal, ftotal;
-
- frameLeft >>= 2;
- if (stereo)
- userCount >>= 1;
- ftotal = frameLeft;
- utotal = userCount;
- while (frameLeft) {
- u_char data;
-
- if (bal<0 && userCount == 0)
- break;
- vall = *p++;
- vall = (vall * software_input_volume) >> 7;
- if (stereo) {
- valr = *p;
- valr = (valr * software_input_volume) >> 7;
- }
- p++;
- if (bal < 0) {
- data = vall >> 8;
- if (put_user(data, (u_char __user *)userPtr++))
- return -EFAULT;
- if (stereo) {
- data = valr >> 8;
- if (put_user(data, (u_char __user *)userPtr++))
- return -EFAULT;
- }
- userCount--;
- bal += hSpeed;
- }
- frameLeft--;
- bal -= sSpeed;
- }
- expand_read_bal=bal;
- *frameUsed += (ftotal - frameLeft) * 4;
- utotal -= userCount;
- return stereo? utotal * 2: utotal;
-}
-
-
-static ssize_t pmac_ctx_u8_read(const u_char __user *userPtr, size_t userCount,
- u_char frame[], ssize_t *frameUsed,
- ssize_t frameLeft)
-{
- short *p = (short *) &frame[*frameUsed];
- int bal = expand_read_bal;
- int vall,valr, stereo = dmasound.soft.stereo;
- int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
- int utotal, ftotal;
-
- frameLeft >>= 2;
- if (stereo)
- userCount >>= 1;
- ftotal = frameLeft;
- utotal = userCount;
- while (frameLeft) {
- u_char data;
-
- if (bal<0 && userCount == 0)
- break;
-
- vall = *p++;
- vall = (vall * software_input_volume) >> 7;
- if (stereo) {
- valr = *p;
- valr = (valr * software_input_volume) >> 7;
- }
- p++;
- if (bal < 0) {
- data = (vall >> 8) ^ 0x80;
- if (put_user(data, (u_char __user *)userPtr++))
- return -EFAULT;
- if (stereo) {
- data = (valr >> 8) ^ 0x80;
- if (put_user(data, (u_char __user *)userPtr++))
- return -EFAULT;
- }
- userCount--;
- bal += hSpeed;
- }
- frameLeft--;
- bal -= sSpeed;
- }
- expand_read_bal=bal;
- *frameUsed += (ftotal - frameLeft) * 4;
- utotal -= userCount;
- return stereo? utotal * 2: utotal;
-}
-
-static ssize_t pmac_ctx_s16_read(const u_char __user *userPtr, size_t userCount,
- u_char frame[], ssize_t *frameUsed,
- ssize_t frameLeft)
-{
- int bal = expand_read_bal;
- short *fp = (short *) &frame[*frameUsed];
- short __user *up = (short __user *) userPtr;
- int stereo = dmasound.soft.stereo;
- int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
- int utotal, ftotal;
-
- frameLeft >>= 2;
- userCount >>= (stereo? 2: 1);
- ftotal = frameLeft;
- utotal = userCount;
- while (frameLeft) {
- int datal,datar;
-
- if (bal<0 && userCount == 0)
- break;
-
- datal = *fp++;
- datal = (datal * software_input_volume) >> 7;
- if (stereo) {
- datar = *fp;
- datar = (datar * software_input_volume) >> 7;
- }
- fp++;
- if (bal < 0) {
- if (put_user(datal, up++))
- return -EFAULT;
- if (stereo) {
- if (put_user(datar, up++))
- return -EFAULT;
- }
- userCount--;
- bal += hSpeed;
- }
- frameLeft--;
- bal -= sSpeed;
- }
- expand_read_bal=bal;
- *frameUsed += (ftotal - frameLeft) * 4;
- utotal -= userCount;
- return stereo? utotal * 4: utotal * 2;
-}
-
-static ssize_t pmac_ctx_u16_read(const u_char __user *userPtr, size_t userCount,
- u_char frame[], ssize_t *frameUsed,
- ssize_t frameLeft)
-{
- int bal = expand_read_bal;
- int mask = (dmasound.soft.format == AFMT_U16_LE? 0x0080: 0x8000);
- short *fp = (short *) &frame[*frameUsed];
- short __user *up = (short __user *) userPtr;
- int stereo = dmasound.soft.stereo;
- int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
- int utotal, ftotal;
-
- frameLeft >>= 2;
- userCount >>= (stereo? 2: 1);
- ftotal = frameLeft;
- utotal = userCount;
- while (frameLeft) {
- int datal,datar;
-
- if (bal<0 && userCount == 0)
- break;
-
- datal = *fp++;
- datal = (datal * software_input_volume) >> 7;
- datal ^= mask;
- if (stereo) {
- datar = *fp;
- datar = (datar * software_input_volume) >> 7;
- datar ^= mask;
- }
- fp++;
- if (bal < 0) {
- if (put_user(datal, up++))
- return -EFAULT;
- if (stereo) {
- if (put_user(datar, up++))
- return -EFAULT;
- }
- userCount--;
- bal += hSpeed;
- }
- frameLeft--;
- bal -= sSpeed;
- }
- expand_read_bal=bal;
- *frameUsed += (ftotal - frameLeft) * 4;
- utotal -= userCount;
- return stereo? utotal * 4: utotal * 2;
-}
-
-
-TRANS transAwacsNormal = {
- .ct_ulaw= pmac_ct_law,
- .ct_alaw= pmac_ct_law,
- .ct_s8= pmac_ct_s8,
- .ct_u8= pmac_ct_u8,
- .ct_s16be= pmac_ct_s16,
- .ct_u16be= pmac_ct_u16,
- .ct_s16le= pmac_ct_s16,
- .ct_u16le= pmac_ct_u16,
-};
-
-TRANS transAwacsExpand = {
- .ct_ulaw= pmac_ctx_law,
- .ct_alaw= pmac_ctx_law,
- .ct_s8= pmac_ctx_s8,
- .ct_u8= pmac_ctx_u8,
- .ct_s16be= pmac_ctx_s16,
- .ct_u16be= pmac_ctx_u16,
- .ct_s16le= pmac_ctx_s16,
- .ct_u16le= pmac_ctx_u16,
-};
-
-TRANS transAwacsNormalRead = {
- .ct_s8= pmac_ct_s8_read,
- .ct_u8= pmac_ct_u8_read,
- .ct_s16be= pmac_ct_s16_read,
- .ct_u16be= pmac_ct_u16_read,
- .ct_s16le= pmac_ct_s16_read,
- .ct_u16le= pmac_ct_u16_read,
-};
-
-TRANS transAwacsExpandRead = {
- .ct_s8= pmac_ctx_s8_read,
- .ct_u8= pmac_ctx_u8_read,
- .ct_s16be= pmac_ctx_s16_read,
- .ct_u16be= pmac_ctx_u16_read,
- .ct_s16le= pmac_ctx_s16_read,
- .ct_u16le= pmac_ctx_u16_read,
-};
-
-/* translation tables */
-/* 16 bit mu-law */
-
-static short dmasound_ulaw2dma16[] = {
- -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956,
- -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764,
- -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412,
- -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316,
- -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
- -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
- -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
- -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
- -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
- -1372, -1308, -1244, -1180, -1116, -1052, -988, -924,
- -876, -844, -812, -780, -748, -716, -684, -652,
- -620, -588, -556, -524, -492, -460, -428, -396,
- -372, -356, -340, -324, -308, -292, -276, -260,
- -244, -228, -212, -196, -180, -164, -148, -132,
- -120, -112, -104, -96, -88, -80, -72, -64,
- -56, -48, -40, -32, -24, -16, -8, 0,
- 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
- 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
- 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
- 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316,
- 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140,
- 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092,
- 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004,
- 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980,
- 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436,
- 1372, 1308, 1244, 1180, 1116, 1052, 988, 924,
- 876, 844, 812, 780, 748, 716, 684, 652,
- 620, 588, 556, 524, 492, 460, 428, 396,
- 372, 356, 340, 324, 308, 292, 276, 260,
- 244, 228, 212, 196, 180, 164, 148, 132,
- 120, 112, 104, 96, 88, 80, 72, 64,
- 56, 48, 40, 32, 24, 16, 8, 0,
-};
-
-/* 16 bit A-law */
-
-static short dmasound_alaw2dma16[] = {
- -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736,
- -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784,
- -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368,
- -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392,
- -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944,
- -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136,
- -11008, -10496, -12032, -11520, -8960, -8448, -9984, -9472,
- -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568,
- -344, -328, -376, -360, -280, -264, -312, -296,
- -472, -456, -504, -488, -408, -392, -440, -424,
- -88, -72, -120, -104, -24, -8, -56, -40,
- -216, -200, -248, -232, -152, -136, -184, -168,
- -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184,
- -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696,
- -688, -656, -752, -720, -560, -528, -624, -592,
- -944, -912, -1008, -976, -816, -784, -880, -848,
- 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736,
- 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784,
- 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368,
- 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392,
- 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944,
- 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136,
- 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472,
- 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568,
- 344, 328, 376, 360, 280, 264, 312, 296,
- 472, 456, 504, 488, 408, 392, 440, 424,
- 88, 72, 120, 104, 24, 8, 56, 40,
- 216, 200, 248, 232, 152, 136, 184, 168,
- 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184,
- 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696,
- 688, 656, 752, 720, 560, 528, 624, 592,
- 944, 912, 1008, 976, 816, 784, 880, 848,
-};
diff --git a/sound/oss/es1371.c b/sound/oss/es1371.c
deleted file mode 100644
index 52648573f601..000000000000
--- a/sound/oss/es1371.c
+++ /dev/null
@@ -1,3131 +0,0 @@
-/*****************************************************************************/
-
-/*
- * es1371.c -- Creative Ensoniq ES1371.
- *
- * Copyright (C) 1998-2001, 2003 Thomas Sailer (t.sailer@alumni.ethz.ch)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Special thanks to Ensoniq
- *
- * Supported devices:
- * /dev/dsp standard /dev/dsp device, (mostly) OSS compatible
- * /dev/mixer standard /dev/mixer device, (mostly) OSS compatible
- * /dev/dsp1 additional DAC, like /dev/dsp, but outputs to mixer "SYNTH" setting
- * /dev/midi simple MIDI UART interface, no ioctl
- *
- * NOTE: the card does not have any FM/Wavetable synthesizer, it is supposed
- * to be done in software. That is what /dev/dac is for. By now (Q2 1998)
- * there are several MIDI to PCM (WAV) packages, one of them is timidity.
- *
- * Revision history
- * 04.06.1998 0.1 Initial release
- * Mixer stuff should be overhauled; especially optional AC97 mixer bits
- * should be detected. This results in strange behaviour of some mixer
- * settings, like master volume and mic.
- * 08.06.1998 0.2 First release using Alan Cox' soundcore instead of miscdevice
- * 03.08.1998 0.3 Do not include modversions.h
- * Now mixer behaviour can basically be selected between
- * "OSS documented" and "OSS actual" behaviour
- * 31.08.1998 0.4 Fix realplayer problems - dac.count issues
- * 27.10.1998 0.5 Fix joystick support
- * -- Oliver Neukum (c188@org.chemie.uni-muenchen.de)
- * 10.12.1998 0.6 Fix drain_dac trying to wait on not yet initialized DMA
- * 23.12.1998 0.7 Fix a few f_file & FMODE_ bugs
- * Don't wake up app until there are fragsize bytes to read/write
- * 06.01.1999 0.8 remove the silly SA_INTERRUPT flag.
- * hopefully killed the egcs section type conflict
- * 12.03.1999 0.9 cinfo.blocks should be reset after GETxPTR ioctl.
- * reported by Johan Maes <joma@telindus.be>
- * 22.03.1999 0.10 return EAGAIN instead of EBUSY when O_NONBLOCK
- * read/write cannot be executed
- * 07.04.1999 0.11 implemented the following ioctl's: SOUND_PCM_READ_RATE,
- * SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS;
- * Alpha fixes reported by Peter Jones <pjones@redhat.com>
- * Another Alpha fix (wait_src_ready in init routine)
- * reported by "Ivan N. Kokshaysky" <ink@jurassic.park.msu.ru>
- * Note: joystick address handling might still be wrong on archs
- * other than i386
- * 15.06.1999 0.12 Fix bad allocation bug.
- * Thanks to Deti Fliegl <fliegl@in.tum.de>
- * 28.06.1999 0.13 Add pci_set_master
- * 03.08.1999 0.14 adapt to Linus' new __setup/__initcall
- * added kernel command line option "es1371=joystickaddr"
- * removed CONFIG_SOUND_ES1371_JOYPORT_BOOT kludge
- * 10.08.1999 0.15 (Re)added S/PDIF module option for cards revision >= 4.
- * Initial version by Dave Platt <dplatt@snulbug.mtview.ca.us>.
- * module_init/__setup fixes
- * 08.16.1999 0.16 Joe Cotellese <joec@ensoniq.com>
- * Added detection for ES1371 revision ID so that we can
- * detect the ES1373 and later parts.
- * added AC97 #defines for readability
- * added a /proc file system for dumping hardware state
- * updated SRC and CODEC w/r functions to accommodate bugs
- * in some versions of the ES137x chips.
- * 31.08.1999 0.17 add spin_lock_init
- * replaced current->state = x with set_current_state(x)
- * 03.09.1999 0.18 change read semantics for MIDI to match
- * OSS more closely; remove possible wakeup race
- * 21.10.1999 0.19 Round sampling rates, requested by
- * Kasamatsu Kenichi <t29w0267@ip.media.kyoto-u.ac.jp>
- * 27.10.1999 0.20 Added SigmaTel 3D enhancement string
- * Codec ID printing changes
- * 28.10.1999 0.21 More waitqueue races fixed
- * Joe Cotellese <joec@ensoniq.com>
- * Changed PCI detection routine so we can more easily
- * detect ES137x chip and derivatives.
- * 05.01.2000 0.22 Should now work with rev7 boards; patch by
- * Eric Lemar, elemar@cs.washington.edu
- * 08.01.2000 0.23 Prevent some ioctl's from returning bad count values on underrun/overrun;
- * Tim Janik's BSE (Bedevilled Sound Engine) found this
- * 07.02.2000 0.24 Use pci_alloc_consistent and pci_register_driver
- * 07.02.2000 0.25 Use ac97_codec
- * 01.03.2000 0.26 SPDIF patch by Mikael Bouillot <mikael.bouillot@bigfoot.com>
- * Use pci_module_init
- * 21.11.2000 0.27 Initialize dma buffers in poll, otherwise poll may return a bogus mask
- * 12.12.2000 0.28 More dma buffer initializations, patch from
- * Tjeerd Mulder <tjeerd.mulder@fujitsu-siemens.com>
- * 05.01.2001 0.29 Hopefully updates will not be required anymore when Creative bumps
- * the CT5880 revision.
- * suggested by Stephan Müller <smueller@chronox.de>
- * 31.01.2001 0.30 Register/Unregister gameport
- * Fix SETTRIGGER non OSS API conformity
- * 14.07.2001 0.31 Add list of laptops needing amplifier control
- * 03.01.2003 0.32 open_mode fixes from Georg Acher <acher@in.tum.de>
- */
-
-/*****************************************************************************/
-
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <linux/sound.h>
-#include <linux/slab.h>
-#include <linux/soundcard.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/poll.h>
-#include <linux/bitops.h>
-#include <linux/proc_fs.h>
-#include <linux/spinlock.h>
-#include <linux/smp_lock.h>
-#include <linux/ac97_codec.h>
-#include <linux/gameport.h>
-#include <linux/wait.h>
-#include <linux/dma-mapping.h>
-#include <linux/mutex.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-
-#include <asm/io.h>
-#include <asm/page.h>
-#include <asm/uaccess.h>
-
-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
-#define SUPPORT_JOYSTICK
-#endif
-
-/* --------------------------------------------------------------------- */
-
-#undef OSS_DOCUMENTED_MIXER_SEMANTICS
-#define ES1371_DEBUG
-#define DBG(x) {}
-/*#define DBG(x) {x}*/
-
-/* --------------------------------------------------------------------- */
-
-#ifndef PCI_VENDOR_ID_ENSONIQ
-#define PCI_VENDOR_ID_ENSONIQ 0x1274
-#endif
-
-#ifndef PCI_VENDOR_ID_ECTIVA
-#define PCI_VENDOR_ID_ECTIVA 0x1102
-#endif
-
-#ifndef PCI_DEVICE_ID_ENSONIQ_ES1371
-#define PCI_DEVICE_ID_ENSONIQ_ES1371 0x1371
-#endif
-
-#ifndef PCI_DEVICE_ID_ENSONIQ_CT5880
-#define PCI_DEVICE_ID_ENSONIQ_CT5880 0x5880
-#endif
-
-#ifndef PCI_DEVICE_ID_ECTIVA_EV1938
-#define PCI_DEVICE_ID_ECTIVA_EV1938 0x8938
-#endif
-
-/* ES1371 chip ID */
-/* This is a little confusing because all ES1371 compatible chips have the
- same DEVICE_ID, the only thing differentiating them is the REV_ID field.
- This is only significant if you want to enable features on the later parts.
- Yes, I know it's stupid and why didn't we use the sub IDs?
-*/
-#define ES1371REV_ES1373_A 0x04
-#define ES1371REV_ES1373_B 0x06
-#define ES1371REV_CT5880_A 0x07
-#define CT5880REV_CT5880_C 0x02
-#define CT5880REV_CT5880_D 0x03
-#define ES1371REV_ES1371_B 0x09
-#define EV1938REV_EV1938_A 0x00
-#define ES1371REV_ES1373_8 0x08
-
-#define ES1371_MAGIC ((PCI_VENDOR_ID_ENSONIQ<<16)|PCI_DEVICE_ID_ENSONIQ_ES1371)
-
-#define ES1371_EXTENT 0x40
-#define JOY_EXTENT 8
-
-#define ES1371_REG_CONTROL 0x00
-#define ES1371_REG_STATUS 0x04 /* on the 5880 it is control/status */
-#define ES1371_REG_UART_DATA 0x08
-#define ES1371_REG_UART_STATUS 0x09
-#define ES1371_REG_UART_CONTROL 0x09
-#define ES1371_REG_UART_TEST 0x0a
-#define ES1371_REG_MEMPAGE 0x0c
-#define ES1371_REG_SRCONV 0x10
-#define ES1371_REG_CODEC 0x14
-#define ES1371_REG_LEGACY 0x18
-#define ES1371_REG_SERIAL_CONTROL 0x20
-#define ES1371_REG_DAC1_SCOUNT 0x24
-#define ES1371_REG_DAC2_SCOUNT 0x28
-#define ES1371_REG_ADC_SCOUNT 0x2c
-
-#define ES1371_REG_DAC1_FRAMEADR 0xc30
-#define ES1371_REG_DAC1_FRAMECNT 0xc34
-#define ES1371_REG_DAC2_FRAMEADR 0xc38
-#define ES1371_REG_DAC2_FRAMECNT 0xc3c
-#define ES1371_REG_ADC_FRAMEADR 0xd30
-#define ES1371_REG_ADC_FRAMECNT 0xd34
-
-#define ES1371_FMT_U8_MONO 0
-#define ES1371_FMT_U8_STEREO 1
-#define ES1371_FMT_S16_MONO 2
-#define ES1371_FMT_S16_STEREO 3
-#define ES1371_FMT_STEREO 1
-#define ES1371_FMT_S16 2
-#define ES1371_FMT_MASK 3
-
-static const unsigned sample_size[] = { 1, 2, 2, 4 };
-static const unsigned sample_shift[] = { 0, 1, 1, 2 };
-
-#define CTRL_RECEN_B 0x08000000 /* 1 = don't mix analog in to digital out */
-#define CTRL_SPDIFEN_B 0x04000000
-#define CTRL_JOY_SHIFT 24
-#define CTRL_JOY_MASK 3
-#define CTRL_JOY_200 0x00000000 /* joystick base address */
-#define CTRL_JOY_208 0x01000000
-#define CTRL_JOY_210 0x02000000
-#define CTRL_JOY_218 0x03000000
-#define CTRL_GPIO_IN0 0x00100000 /* general purpose inputs/outputs */
-#define CTRL_GPIO_IN1 0x00200000
-#define CTRL_GPIO_IN2 0x00400000
-#define CTRL_GPIO_IN3 0x00800000
-#define CTRL_GPIO_OUT0 0x00010000
-#define CTRL_GPIO_OUT1 0x00020000
-#define CTRL_GPIO_OUT2 0x00040000
-#define CTRL_GPIO_OUT3 0x00080000
-#define CTRL_MSFMTSEL 0x00008000 /* MPEG serial data fmt: 0 = Sony, 1 = I2S */
-#define CTRL_SYNCRES 0x00004000 /* AC97 warm reset */
-#define CTRL_ADCSTOP 0x00002000 /* stop ADC transfers */
-#define CTRL_PWR_INTRM 0x00001000 /* 1 = power level ints enabled */
-#define CTRL_M_CB 0x00000800 /* recording source: 0 = ADC, 1 = MPEG */
-#define CTRL_CCB_INTRM 0x00000400 /* 1 = CCB "voice" ints enabled */
-#define CTRL_PDLEV0 0x00000000 /* power down level */
-#define CTRL_PDLEV1 0x00000100
-#define CTRL_PDLEV2 0x00000200
-#define CTRL_PDLEV3 0x00000300
-#define CTRL_BREQ 0x00000080 /* 1 = test mode (internal mem test) */
-#define CTRL_DAC1_EN 0x00000040 /* enable DAC1 */
-#define CTRL_DAC2_EN 0x00000020 /* enable DAC2 */
-#define CTRL_ADC_EN 0x00000010 /* enable ADC */
-#define CTRL_UART_EN 0x00000008 /* enable MIDI uart */
-#define CTRL_JYSTK_EN 0x00000004 /* enable Joystick port */
-#define CTRL_XTALCLKDIS 0x00000002 /* 1 = disable crystal clock input */
-#define CTRL_PCICLKDIS 0x00000001 /* 1 = disable PCI clock distribution */
-
-
-#define STAT_INTR 0x80000000 /* wired or of all interrupt bits */
-#define CSTAT_5880_AC97_RST 0x20000000 /* CT5880 Reset bit */
-#define STAT_EN_SPDIF 0x00040000 /* enable S/PDIF circuitry */
-#define STAT_TS_SPDIF 0x00020000 /* test S/PDIF circuitry */
-#define STAT_TESTMODE 0x00010000 /* test ASIC */
-#define STAT_SYNC_ERR 0x00000100 /* 1 = codec sync error */
-#define STAT_VC 0x000000c0 /* CCB int source, 0=DAC1, 1=DAC2, 2=ADC, 3=undef */
-#define STAT_SH_VC 6
-#define STAT_MPWR 0x00000020 /* power level interrupt */
-#define STAT_MCCB 0x00000010 /* CCB int pending */
-#define STAT_UART 0x00000008 /* UART int pending */
-#define STAT_DAC1 0x00000004 /* DAC1 int pending */
-#define STAT_DAC2 0x00000002 /* DAC2 int pending */
-#define STAT_ADC 0x00000001 /* ADC int pending */
-
-#define USTAT_RXINT 0x80 /* UART rx int pending */
-#define USTAT_TXINT 0x04 /* UART tx int pending */
-#define USTAT_TXRDY 0x02 /* UART tx ready */
-#define USTAT_RXRDY 0x01 /* UART rx ready */
-
-#define UCTRL_RXINTEN 0x80 /* 1 = enable RX ints */
-#define UCTRL_TXINTEN 0x60 /* TX int enable field mask */
-#define UCTRL_ENA_TXINT 0x20 /* enable TX int */
-#define UCTRL_CNTRL 0x03 /* control field */
-#define UCTRL_CNTRL_SWR 0x03 /* software reset command */
-
-/* sample rate converter */
-#define SRC_OKSTATE 1
-
-#define SRC_RAMADDR_MASK 0xfe000000
-#define SRC_RAMADDR_SHIFT 25
-#define SRC_DAC1FREEZE (1UL << 21)
-#define SRC_DAC2FREEZE (1UL << 20)
-#define SRC_ADCFREEZE (1UL << 19)
-
-
-#define SRC_WE 0x01000000 /* read/write control for SRC RAM */
-#define SRC_BUSY 0x00800000 /* SRC busy */
-#define SRC_DIS 0x00400000 /* 1 = disable SRC */
-#define SRC_DDAC1 0x00200000 /* 1 = disable accum update for DAC1 */
-#define SRC_DDAC2 0x00100000 /* 1 = disable accum update for DAC2 */
-#define SRC_DADC 0x00080000 /* 1 = disable accum update for ADC2 */
-#define SRC_CTLMASK 0x00780000
-#define SRC_RAMDATA_MASK 0x0000ffff
-#define SRC_RAMDATA_SHIFT 0
-
-#define SRCREG_ADC 0x78
-#define SRCREG_DAC1 0x70
-#define SRCREG_DAC2 0x74
-#define SRCREG_VOL_ADC 0x6c
-#define SRCREG_VOL_DAC1 0x7c
-#define SRCREG_VOL_DAC2 0x7e
-
-#define SRCREG_TRUNC_N 0x00
-#define SRCREG_INT_REGS 0x01
-#define SRCREG_ACCUM_FRAC 0x02
-#define SRCREG_VFREQ_FRAC 0x03
-
-#define CODEC_PIRD 0x00800000 /* 0 = write AC97 register */
-#define CODEC_PIADD_MASK 0x007f0000
-#define CODEC_PIADD_SHIFT 16
-#define CODEC_PIDAT_MASK 0x0000ffff
-#define CODEC_PIDAT_SHIFT 0
-
-#define CODEC_RDY 0x80000000 /* AC97 read data valid */
-#define CODEC_WIP 0x40000000 /* AC97 write in progress */
-#define CODEC_PORD 0x00800000 /* 0 = write AC97 register */
-#define CODEC_POADD_MASK 0x007f0000
-#define CODEC_POADD_SHIFT 16
-#define CODEC_PODAT_MASK 0x0000ffff
-#define CODEC_PODAT_SHIFT 0
-
-
-#define LEGACY_JFAST 0x80000000 /* fast joystick timing */
-#define LEGACY_FIRQ 0x01000000 /* force IRQ */
-
-#define SCTRL_DACTEST 0x00400000 /* 1 = DAC test, test vector generation purposes */
-#define SCTRL_P2ENDINC 0x00380000 /* */
-#define SCTRL_SH_P2ENDINC 19
-#define SCTRL_P2STINC 0x00070000 /* */
-#define SCTRL_SH_P2STINC 16
-#define SCTRL_R1LOOPSEL 0x00008000 /* 0 = loop mode */
-#define SCTRL_P2LOOPSEL 0x00004000 /* 0 = loop mode */
-#define SCTRL_P1LOOPSEL 0x00002000 /* 0 = loop mode */
-#define SCTRL_P2PAUSE 0x00001000 /* 1 = pause mode */
-#define SCTRL_P1PAUSE 0x00000800 /* 1 = pause mode */
-#define SCTRL_R1INTEN 0x00000400 /* enable interrupt */
-#define SCTRL_P2INTEN 0x00000200 /* enable interrupt */
-#define SCTRL_P1INTEN 0x00000100 /* enable interrupt */
-#define SCTRL_P1SCTRLD 0x00000080 /* reload sample count register for DAC1 */
-#define SCTRL_P2DACSEN 0x00000040 /* 1 = DAC2 play back last sample when disabled */
-#define SCTRL_R1SEB 0x00000020 /* 1 = 16bit */
-#define SCTRL_R1SMB 0x00000010 /* 1 = stereo */
-#define SCTRL_R1FMT 0x00000030 /* format mask */
-#define SCTRL_SH_R1FMT 4
-#define SCTRL_P2SEB 0x00000008 /* 1 = 16bit */
-#define SCTRL_P2SMB 0x00000004 /* 1 = stereo */
-#define SCTRL_P2FMT 0x0000000c /* format mask */
-#define SCTRL_SH_P2FMT 2
-#define SCTRL_P1SEB 0x00000002 /* 1 = 16bit */
-#define SCTRL_P1SMB 0x00000001 /* 1 = stereo */
-#define SCTRL_P1FMT 0x00000003 /* format mask */
-#define SCTRL_SH_P1FMT 0
-
-
-/* misc stuff */
-#define POLL_COUNT 0x1000
-#define FMODE_DAC 4 /* slight misuse of mode_t */
-
-/* MIDI buffer sizes */
-
-#define MIDIINBUF 256
-#define MIDIOUTBUF 256
-
-#define FMODE_MIDI_SHIFT 3
-#define FMODE_MIDI_READ (FMODE_READ << FMODE_MIDI_SHIFT)
-#define FMODE_MIDI_WRITE (FMODE_WRITE << FMODE_MIDI_SHIFT)
-
-#define ES1371_MODULE_NAME "es1371"
-#define PFX ES1371_MODULE_NAME ": "
-
-/* --------------------------------------------------------------------- */
-
-struct es1371_state {
- /* magic */
- unsigned int magic;
-
- /* list of es1371 devices */
- struct list_head devs;
-
- /* the corresponding pci_dev structure */
- struct pci_dev *dev;
-
- /* soundcore stuff */
- int dev_audio;
- int dev_dac;
- int dev_midi;
-
- /* hardware resources */
- unsigned long io; /* long for SPARC */
- unsigned int irq;
-
- /* PCI ID's */
- u16 vendor;
- u16 device;
- u8 rev; /* the chip revision */
-
- /* options */
- int spdif_volume; /* S/PDIF output is enabled if != -1 */
-
-#ifdef ES1371_DEBUG
- /* debug /proc entry */
- struct proc_dir_entry *ps;
-#endif /* ES1371_DEBUG */
-
- struct ac97_codec *codec;
-
- /* wave stuff */
- unsigned ctrl;
- unsigned sctrl;
- unsigned dac1rate, dac2rate, adcrate;
-
- spinlock_t lock;
- struct mutex open_mutex;
- mode_t open_mode;
- wait_queue_head_t open_wait;
-
- struct dmabuf {
- void *rawbuf;
- dma_addr_t dmaaddr;
- unsigned buforder;
- unsigned numfrag;
- unsigned fragshift;
- unsigned hwptr, swptr;
- unsigned total_bytes;
- int count;
- unsigned error; /* over/underrun */
- wait_queue_head_t wait;
- /* redundant, but makes calculations easier */
- unsigned fragsize;
- unsigned dmasize;
- unsigned fragsamples;
- /* OSS stuff */
- unsigned mapped:1;
- unsigned ready:1;
- unsigned endcleared:1;
- unsigned enabled:1;
- unsigned ossfragshift;
- int ossmaxfrags;
- unsigned subdivision;
- } dma_dac1, dma_dac2, dma_adc;
-
- /* midi stuff */
- struct {
- unsigned ird, iwr, icnt;
- unsigned ord, owr, ocnt;
- wait_queue_head_t iwait;
- wait_queue_head_t owait;
- unsigned char ibuf[MIDIINBUF];
- unsigned char obuf[MIDIOUTBUF];
- } midi;
-
-#ifdef SUPPORT_JOYSTICK
- struct gameport *gameport;
-#endif
-
- struct mutex sem;
-};
-
-/* --------------------------------------------------------------------- */
-
-static LIST_HEAD(devs);
-
-/* --------------------------------------------------------------------- */
-
-static inline unsigned ld2(unsigned int x)
-{
- unsigned r = 0;
-
- if (x >= 0x10000) {
- x >>= 16;
- r += 16;
- }
- if (x >= 0x100) {
- x >>= 8;
- r += 8;
- }
- if (x >= 0x10) {
- x >>= 4;
- r += 4;
- }
- if (x >= 4) {
- x >>= 2;
- r += 2;
- }
- if (x >= 2)
- r++;
- return r;
-}
-
-/* --------------------------------------------------------------------- */
-
-static unsigned wait_src_ready(struct es1371_state *s)
-{
- unsigned int t, r;
-
- for (t = 0; t < POLL_COUNT; t++) {
- if (!((r = inl(s->io + ES1371_REG_SRCONV)) & SRC_BUSY))
- return r;
- udelay(1);
- }
- printk(KERN_DEBUG PFX "sample rate converter timeout r = 0x%08x\n", r);
- return r;
-}
-
-static unsigned src_read(struct es1371_state *s, unsigned reg)
-{
- unsigned int temp,i,orig;
-
- /* wait for ready */
- temp = wait_src_ready (s);
-
- /* we can only access the SRC at certain times, make sure
- we're allowed to before we read */
-
- orig = temp;
- /* expose the SRC state bits */
- outl ( (temp & SRC_CTLMASK) | (reg << SRC_RAMADDR_SHIFT) | 0x10000UL,
- s->io + ES1371_REG_SRCONV);
-
- /* now, wait for busy and the correct time to read */
- temp = wait_src_ready (s);
-
- if ( (temp & 0x00870000UL ) != ( SRC_OKSTATE << 16 )){
- /* wait for the right state */
- for (i=0; i<POLL_COUNT; i++){
- temp = inl (s->io + ES1371_REG_SRCONV);
- if ( (temp & 0x00870000UL ) == ( SRC_OKSTATE << 16 ))
- break;
- }
- }
-
- /* hide the state bits */
- outl ((orig & SRC_CTLMASK) | (reg << SRC_RAMADDR_SHIFT), s->io + ES1371_REG_SRCONV);
- return temp;
-
-
-}
-
-static void src_write(struct es1371_state *s, unsigned reg, unsigned data)
-{
-
- unsigned int r;
-
- r = wait_src_ready(s) & (SRC_DIS | SRC_DDAC1 | SRC_DDAC2 | SRC_DADC);
- r |= (reg << SRC_RAMADDR_SHIFT) & SRC_RAMADDR_MASK;
- r |= (data << SRC_RAMDATA_SHIFT) & SRC_RAMDATA_MASK;
- outl(r | SRC_WE, s->io + ES1371_REG_SRCONV);
-
-}
-
-/* --------------------------------------------------------------------- */
-
-/* most of the following here is black magic */
-static void set_adc_rate(struct es1371_state *s, unsigned rate)
-{
- unsigned long flags;
- unsigned int n, truncm, freq;
-
- if (rate > 48000)
- rate = 48000;
- if (rate < 4000)
- rate = 4000;
- n = rate / 3000;
- if ((1 << n) & ((1 << 15) | (1 << 13) | (1 << 11) | (1 << 9)))
- n--;
- truncm = (21 * n - 1) | 1;
- freq = ((48000UL << 15) / rate) * n;
- s->adcrate = (48000UL << 15) / (freq / n);
- spin_lock_irqsave(&s->lock, flags);
- if (rate >= 24000) {
- if (truncm > 239)
- truncm = 239;
- src_write(s, SRCREG_ADC+SRCREG_TRUNC_N,
- (((239 - truncm) >> 1) << 9) | (n << 4));
- } else {
- if (truncm > 119)
- truncm = 119;
- src_write(s, SRCREG_ADC+SRCREG_TRUNC_N,
- 0x8000 | (((119 - truncm) >> 1) << 9) | (n << 4));
- }
- src_write(s, SRCREG_ADC+SRCREG_INT_REGS,
- (src_read(s, SRCREG_ADC+SRCREG_INT_REGS) & 0x00ff) |
- ((freq >> 5) & 0xfc00));
- src_write(s, SRCREG_ADC+SRCREG_VFREQ_FRAC, freq & 0x7fff);
- src_write(s, SRCREG_VOL_ADC, n << 8);
- src_write(s, SRCREG_VOL_ADC+1, n << 8);
- spin_unlock_irqrestore(&s->lock, flags);
-}
-
-
-static void set_dac1_rate(struct es1371_state *s, unsigned rate)
-{
- unsigned long flags;
- unsigned int freq, r;
-
- if (rate > 48000)
- rate = 48000;
- if (rate < 4000)
- rate = 4000;
- freq = ((rate << 15) + 1500) / 3000;
- s->dac1rate = (freq * 3000 + 16384) >> 15;
- spin_lock_irqsave(&s->lock, flags);
- r = (wait_src_ready(s) & (SRC_DIS | SRC_DDAC2 | SRC_DADC)) | SRC_DDAC1;
- outl(r, s->io + ES1371_REG_SRCONV);
- src_write(s, SRCREG_DAC1+SRCREG_INT_REGS,
- (src_read(s, SRCREG_DAC1+SRCREG_INT_REGS) & 0x00ff) |
- ((freq >> 5) & 0xfc00));
- src_write(s, SRCREG_DAC1+SRCREG_VFREQ_FRAC, freq & 0x7fff);
- r = (wait_src_ready(s) & (SRC_DIS | SRC_DDAC2 | SRC_DADC));
- outl(r, s->io + ES1371_REG_SRCONV);
- spin_unlock_irqrestore(&s->lock, flags);
-}
-
-static void set_dac2_rate(struct es1371_state *s, unsigned rate)
-{
- unsigned long flags;
- unsigned int freq, r;
-
- if (rate > 48000)
- rate = 48000;
- if (rate < 4000)
- rate = 4000;
- freq = ((rate << 15) + 1500) / 3000;
- s->dac2rate = (freq * 3000 + 16384) >> 15;
- spin_lock_irqsave(&s->lock, flags);
- r = (wait_src_ready(s) & (SRC_DIS | SRC_DDAC1 | SRC_DADC)) | SRC_DDAC2;
- outl(r, s->io + ES1371_REG_SRCONV);
- src_write(s, SRCREG_DAC2+SRCREG_INT_REGS,
- (src_read(s, SRCREG_DAC2+SRCREG_INT_REGS) & 0x00ff) |
- ((freq >> 5) & 0xfc00));
- src_write(s, SRCREG_DAC2+SRCREG_VFREQ_FRAC, freq & 0x7fff);
- r = (wait_src_ready(s) & (SRC_DIS | SRC_DDAC1 | SRC_DADC));
- outl(r, s->io + ES1371_REG_SRCONV);
- spin_unlock_irqrestore(&s->lock, flags);
-}
-
-/* --------------------------------------------------------------------- */
-
-static void __devinit src_init(struct es1371_state *s)
-{
- unsigned int i;
-
- /* before we enable or disable the SRC we need
- to wait for it to become ready */
- wait_src_ready(s);
-
- outl(SRC_DIS, s->io + ES1371_REG_SRCONV);
-
- for (i = 0; i < 0x80; i++)
- src_write(s, i, 0);
-
- src_write(s, SRCREG_DAC1+SRCREG_TRUNC_N, 16 << 4);
- src_write(s, SRCREG_DAC1+SRCREG_INT_REGS, 16 << 10);
- src_write(s, SRCREG_DAC2+SRCREG_TRUNC_N, 16 << 4);
- src_write(s, SRCREG_DAC2+SRCREG_INT_REGS, 16 << 10);
- src_write(s, SRCREG_VOL_ADC, 1 << 12);
- src_write(s, SRCREG_VOL_ADC+1, 1 << 12);
- src_write(s, SRCREG_VOL_DAC1, 1 << 12);
- src_write(s, SRCREG_VOL_DAC1+1, 1 << 12);
- src_write(s, SRCREG_VOL_DAC2, 1 << 12);
- src_write(s, SRCREG_VOL_DAC2+1, 1 << 12);
- set_adc_rate(s, 22050);
- set_dac1_rate(s, 22050);
- set_dac2_rate(s, 22050);
-
- /* WARNING:
- * enabling the sample rate converter without properly programming
- * its parameters causes the chip to lock up (the SRC busy bit will
- * be stuck high, and I've found no way to rectify this other than
- * power cycle)
- */
- wait_src_ready(s);
- outl(0, s->io+ES1371_REG_SRCONV);
-}
-
-/* --------------------------------------------------------------------- */
-
-static void wrcodec(struct ac97_codec *codec, u8 addr, u16 data)
-{
- struct es1371_state *s = (struct es1371_state *)codec->private_data;
- unsigned long flags;
- unsigned t, x;
-
- spin_lock_irqsave(&s->lock, flags);
- for (t = 0; t < POLL_COUNT; t++)
- if (!(inl(s->io+ES1371_REG_CODEC) & CODEC_WIP))
- break;
-
- /* save the current state for later */
- x = wait_src_ready(s);
-
- /* enable SRC state data in SRC mux */
- outl((x & (SRC_DIS | SRC_DDAC1 | SRC_DDAC2 | SRC_DADC)) | 0x00010000,
- s->io+ES1371_REG_SRCONV);
-
- /* wait for not busy (state 0) first to avoid
- transition states */
- for (t=0; t<POLL_COUNT; t++){
- if((inl(s->io+ES1371_REG_SRCONV) & 0x00870000) ==0 )
- break;
- udelay(1);
- }
-
- /* wait for a SAFE time to write addr/data and then do it, dammit */
- for (t=0; t<POLL_COUNT; t++){
- if((inl(s->io+ES1371_REG_SRCONV) & 0x00870000) ==0x00010000)
- break;
- udelay(1);
- }
-
- outl(((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) |
- ((data << CODEC_PODAT_SHIFT) & CODEC_PODAT_MASK), s->io+ES1371_REG_CODEC);
-
- /* restore SRC reg */
- wait_src_ready(s);
- outl(x, s->io+ES1371_REG_SRCONV);
- spin_unlock_irqrestore(&s->lock, flags);
-}
-
-static u16 rdcodec(struct ac97_codec *codec, u8 addr)
-{
- struct es1371_state *s = (struct es1371_state *)codec->private_data;
- unsigned long flags;
- unsigned t, x;
-
- spin_lock_irqsave(&s->lock, flags);
-
- /* wait for WIP to go away */
- for (t = 0; t < 0x1000; t++)
- if (!(inl(s->io+ES1371_REG_CODEC) & CODEC_WIP))
- break;
-
- /* save the current state for later */
- x = (wait_src_ready(s) & (SRC_DIS | SRC_DDAC1 | SRC_DDAC2 | SRC_DADC));
-
- /* enable SRC state data in SRC mux */
- outl( x | 0x00010000,
- s->io+ES1371_REG_SRCONV);
-
- /* wait for not busy (state 0) first to avoid
- transition states */
- for (t=0; t<POLL_COUNT; t++){
- if((inl(s->io+ES1371_REG_SRCONV) & 0x00870000) ==0 )
- break;
- udelay(1);
- }
-
- /* wait for a SAFE time to write addr/data and then do it, dammit */
- for (t=0; t<POLL_COUNT; t++){
- if((inl(s->io+ES1371_REG_SRCONV) & 0x00870000) ==0x00010000)
- break;
- udelay(1);
- }
-
- outl(((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) | CODEC_PORD, s->io+ES1371_REG_CODEC);
- /* restore SRC reg */
- wait_src_ready(s);
- outl(x, s->io+ES1371_REG_SRCONV);
-
- /* wait for WIP again */
- for (t = 0; t < 0x1000; t++)
- if (!(inl(s->io+ES1371_REG_CODEC) & CODEC_WIP))
- break;
-
- /* now wait for the stinkin' data (RDY) */
- for (t = 0; t < POLL_COUNT; t++)
- if ((x = inl(s->io+ES1371_REG_CODEC)) & CODEC_RDY)
- break;
-
- spin_unlock_irqrestore(&s->lock, flags);
- return ((x & CODEC_PIDAT_MASK) >> CODEC_PIDAT_SHIFT);
-}
-
-/* --------------------------------------------------------------------- */
-
-static inline void stop_adc(struct es1371_state *s)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&s->lock, flags);
- s->ctrl &= ~CTRL_ADC_EN;
- outl(s->ctrl, s->io+ES1371_REG_CONTROL);
- spin_unlock_irqrestore(&s->lock, flags);
-}
-
-static inline void stop_dac1(struct es1371_state *s)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&s->lock, flags);
- s->ctrl &= ~CTRL_DAC1_EN;
- outl(s->ctrl, s->io+ES1371_REG_CONTROL);
- spin_unlock_irqrestore(&s->lock, flags);
-}
-
-static inline void stop_dac2(struct es1371_state *s)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&s->lock, flags);
- s->ctrl &= ~CTRL_DAC2_EN;
- outl(s->ctrl, s->io+ES1371_REG_CONTROL);
- spin_unlock_irqrestore(&s->lock, flags);
-}
-
-static void start_dac1(struct es1371_state *s)
-{
- unsigned long flags;
- unsigned fragremain, fshift;
-
- spin_lock_irqsave(&s->lock, flags);
- if (!(s->ctrl & CTRL_DAC1_EN) && (s->dma_dac1.mapped || s->dma_dac1.count > 0)
- && s->dma_dac1.ready) {
- s->ctrl |= CTRL_DAC1_EN;
- s->sctrl = (s->sctrl & ~(SCTRL_P1LOOPSEL | SCTRL_P1PAUSE | SCTRL_P1SCTRLD)) | SCTRL_P1INTEN;
- outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL);
- fragremain = ((- s->dma_dac1.hwptr) & (s->dma_dac1.fragsize-1));
- fshift = sample_shift[(s->sctrl & SCTRL_P1FMT) >> SCTRL_SH_P1FMT];
- if (fragremain < 2*fshift)
- fragremain = s->dma_dac1.fragsize;
- outl((fragremain >> fshift) - 1, s->io+ES1371_REG_DAC1_SCOUNT);
- outl(s->ctrl, s->io+ES1371_REG_CONTROL);
- outl((s->dma_dac1.fragsize >> fshift) - 1, s->io+ES1371_REG_DAC1_SCOUNT);
- }
- spin_unlock_irqrestore(&s->lock, flags);
-}
-
-static void start_dac2(struct es1371_state *s)
-{
- unsigned long flags;
- unsigned fragremain, fshift;
-
- spin_lock_irqsave(&s->lock, flags);
- if (!(s->ctrl & CTRL_DAC2_EN) && (s->dma_dac2.mapped || s->dma_dac2.count > 0)
- && s->dma_dac2.ready) {
- s->ctrl |= CTRL_DAC2_EN;
- s->sctrl = (s->sctrl & ~(SCTRL_P2LOOPSEL | SCTRL_P2PAUSE | SCTRL_P2DACSEN |
- SCTRL_P2ENDINC | SCTRL_P2STINC)) | SCTRL_P2INTEN |
- (((s->sctrl & SCTRL_P2FMT) ? 2 : 1) << SCTRL_SH_P2ENDINC) |
- (0 << SCTRL_SH_P2STINC);
- outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL);
- fragremain = ((- s->dma_dac2.hwptr) & (s->dma_dac2.fragsize-1));
- fshift = sample_shift[(s->sctrl & SCTRL_P2FMT) >> SCTRL_SH_P2FMT];
- if (fragremain < 2*fshift)
- fragremain = s->dma_dac2.fragsize;
- outl((fragremain >> fshift) - 1, s->io+ES1371_REG_DAC2_SCOUNT);
- outl(s->ctrl, s->io+ES1371_REG_CONTROL);
- outl((s->dma_dac2.fragsize >> fshift) - 1, s->io+ES1371_REG_DAC2_SCOUNT);
- }
- spin_unlock_irqrestore(&s->lock, flags);
-}
-
-static void start_adc(struct es1371_state *s)
-{
- unsigned long flags;
- unsigned fragremain, fshift;
-
- spin_lock_irqsave(&s->lock, flags);
- if (!(s->ctrl & CTRL_ADC_EN) && (s->dma_adc.mapped || s->dma_adc.count < (signed)(s->dma_adc.dmasize - 2*s->dma_adc.fragsize))
- && s->dma_adc.ready) {
- s->ctrl |= CTRL_ADC_EN;
- s->sctrl = (s->sctrl & ~SCTRL_R1LOOPSEL) | SCTRL_R1INTEN;
- outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL);
- fragremain = ((- s->dma_adc.hwptr) & (s->dma_adc.fragsize-1));
- fshift = sample_shift[(s->sctrl & SCTRL_R1FMT) >> SCTRL_SH_R1FMT];
- if (fragremain < 2*fshift)
- fragremain = s->dma_adc.fragsize;
- outl((fragremain >> fshift) - 1, s->io+ES1371_REG_ADC_SCOUNT);
- outl(s->ctrl, s->io+ES1371_REG_CONTROL);
- outl((s->dma_adc.fragsize >> fshift) - 1, s->io+ES1371_REG_ADC_SCOUNT);
- }
- spin_unlock_irqrestore(&s->lock, flags);
-}
-
-/* --------------------------------------------------------------------- */
-
-#define DMABUF_DEFAULTORDER (17-PAGE_SHIFT)
-#define DMABUF_MINORDER 1
-
-
-static inline void dealloc_dmabuf(struct es1371_state *s, struct dmabuf *db)
-{
- struct page *page, *pend;
-
- if (db->rawbuf) {
- /* undo marking the pages as reserved */
- pend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1);
- for (page = virt_to_page(db->rawbuf); page <= pend; page++)
- ClearPageReserved(page);
- pci_free_consistent(s->dev, PAGE_SIZE << db->buforder, db->rawbuf, db->dmaaddr);
- }
- db->rawbuf = NULL;
- db->mapped = db->ready = 0;
-}
-
-static int prog_dmabuf(struct es1371_state *s, struct dmabuf *db, unsigned rate, unsigned fmt, unsigned reg)
-{
- int order;
- unsigned bytepersec;
- unsigned bufs;
- struct page *page, *pend;
-
- db->hwptr = db->swptr = db->total_bytes = db->count = db->error = db->endcleared = 0;
- if (!db->rawbuf) {
- db->ready = db->mapped = 0;
- for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--)
- if ((db->rawbuf = pci_alloc_consistent(s->dev, PAGE_SIZE << order, &db->dmaaddr)))
- break;
- if (!db->rawbuf)
- return -ENOMEM;
- db->buforder = order;
- /* now mark the pages as reserved; otherwise remap_pfn_range doesn't do what we want */
- pend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1);
- for (page = virt_to_page(db->rawbuf); page <= pend; page++)
- SetPageReserved(page);
- }
- fmt &= ES1371_FMT_MASK;
- bytepersec = rate << sample_shift[fmt];
- bufs = PAGE_SIZE << db->buforder;
- if (db->ossfragshift) {
- if ((1000 << db->ossfragshift) < bytepersec)
- db->fragshift = ld2(bytepersec/1000);
- else
- db->fragshift = db->ossfragshift;
- } else {
- db->fragshift = ld2(bytepersec/100/(db->subdivision ? db->subdivision : 1));
- if (db->fragshift < 3)
- db->fragshift = 3;
- }
- db->numfrag = bufs >> db->fragshift;
- while (db->numfrag < 4 && db->fragshift > 3) {
- db->fragshift--;
- db->numfrag = bufs >> db->fragshift;
- }
- db->fragsize = 1 << db->fragshift;
- if (db->ossmaxfrags >= 4 && db->ossmaxfrags < db->numfrag)
- db->numfrag = db->ossmaxfrags;
- db->fragsamples = db->fragsize >> sample_shift[fmt];
- db->dmasize = db->numfrag << db->fragshift;
- memset(db->rawbuf, (fmt & ES1371_FMT_S16) ? 0 : 0x80, db->dmasize);
- outl((reg >> 8) & 15, s->io+ES1371_REG_MEMPAGE);
- outl(db->dmaaddr, s->io+(reg & 0xff));
- outl((db->dmasize >> 2)-1, s->io+((reg + 4) & 0xff));
- db->enabled = 1;
- db->ready = 1;
- return 0;
-}
-
-static inline int prog_dmabuf_adc(struct es1371_state *s)
-{
- stop_adc(s);
- return prog_dmabuf(s, &s->dma_adc, s->adcrate, (s->sctrl >> SCTRL_SH_R1FMT) & ES1371_FMT_MASK,
- ES1371_REG_ADC_FRAMEADR);
-}
-
-static inline int prog_dmabuf_dac2(struct es1371_state *s)
-{
- stop_dac2(s);
- return prog_dmabuf(s, &s->dma_dac2, s->dac2rate, (s->sctrl >> SCTRL_SH_P2FMT) & ES1371_FMT_MASK,
- ES1371_REG_DAC2_FRAMEADR);
-}
-
-static inline int prog_dmabuf_dac1(struct es1371_state *s)
-{
- stop_dac1(s);
- return prog_dmabuf(s, &s->dma_dac1, s->dac1rate, (s->sctrl >> SCTRL_SH_P1FMT) & ES1371_FMT_MASK,
- ES1371_REG_DAC1_FRAMEADR);
-}
-
-static inline unsigned get_hwptr(struct es1371_state *s, struct dmabuf *db, unsigned reg)
-{
- unsigned hwptr, diff;
-
- outl((reg >> 8) & 15, s->io+ES1371_REG_MEMPAGE);
- hwptr = (inl(s->io+(reg & 0xff)) >> 14) & 0x3fffc;
- diff = (db->dmasize + hwptr - db->hwptr) % db->dmasize;
- db->hwptr = hwptr;
- return diff;
-}
-
-static inline void clear_advance(void *buf, unsigned bsize, unsigned bptr, unsigned len, unsigned char c)
-{
- if (bptr + len > bsize) {
- unsigned x = bsize - bptr;
- memset(((char *)buf) + bptr, c, x);
- bptr = 0;
- len -= x;
- }
- memset(((char *)buf) + bptr, c, len);
-}
-
-/* call with spinlock held! */
-static void es1371_update_ptr(struct es1371_state *s)
-{
- int diff;
-
- /* update ADC pointer */
- if (s->ctrl & CTRL_ADC_EN) {
- diff = get_hwptr(s, &s->dma_adc, ES1371_REG_ADC_FRAMECNT);
- s->dma_adc.total_bytes += diff;
- s->dma_adc.count += diff;
- if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)
- wake_up(&s->dma_adc.wait);
- if (!s->dma_adc.mapped) {
- if (s->dma_adc.count > (signed)(s->dma_adc.dmasize - ((3 * s->dma_adc.fragsize) >> 1))) {
- s->ctrl &= ~CTRL_ADC_EN;
- outl(s->ctrl, s->io+ES1371_REG_CONTROL);
- s->dma_adc.error++;
- }
- }
- }
- /* update DAC1 pointer */
- if (s->ctrl & CTRL_DAC1_EN) {
- diff = get_hwptr(s, &s->dma_dac1, ES1371_REG_DAC1_FRAMECNT);
- s->dma_dac1.total_bytes += diff;
- if (s->dma_dac1.mapped) {
- s->dma_dac1.count += diff;
- if (s->dma_dac1.count >= (signed)s->dma_dac1.fragsize)
- wake_up(&s->dma_dac1.wait);
- } else {
- s->dma_dac1.count -= diff;
- if (s->dma_dac1.count <= 0) {
- s->ctrl &= ~CTRL_DAC1_EN;
- outl(s->ctrl, s->io+ES1371_REG_CONTROL);
- s->dma_dac1.error++;
- } else if (s->dma_dac1.count <= (signed)s->dma_dac1.fragsize && !s->dma_dac1.endcleared) {
- clear_advance(s->dma_dac1.rawbuf, s->dma_dac1.dmasize, s->dma_dac1.swptr,
- s->dma_dac1.fragsize, (s->sctrl & SCTRL_P1SEB) ? 0 : 0x80);
- s->dma_dac1.endcleared = 1;
- }
- if (s->dma_dac1.count + (signed)s->dma_dac1.fragsize <= (signed)s->dma_dac1.dmasize)
- wake_up(&s->dma_dac1.wait);
- }
- }
- /* update DAC2 pointer */
- if (s->ctrl & CTRL_DAC2_EN) {
- diff = get_hwptr(s, &s->dma_dac2, ES1371_REG_DAC2_FRAMECNT);
- s->dma_dac2.total_bytes += diff;
- if (s->dma_dac2.mapped) {
- s->dma_dac2.count += diff;
- if (s->dma_dac2.count >= (signed)s->dma_dac2.fragsize)
- wake_up(&s->dma_dac2.wait);
- } else {
- s->dma_dac2.count -= diff;
- if (s->dma_dac2.count <= 0) {
- s->ctrl &= ~CTRL_DAC2_EN;
- outl(s->ctrl, s->io+ES1371_REG_CONTROL);
- s->dma_dac2.error++;
- } else if (s->dma_dac2.count <= (signed)s->dma_dac2.fragsize && !s->dma_dac2.endcleared) {
- clear_advance(s->dma_dac2.rawbuf, s->dma_dac2.dmasize, s->dma_dac2.swptr,
- s->dma_dac2.fragsize, (s->sctrl & SCTRL_P2SEB) ? 0 : 0x80);
- s->dma_dac2.endcleared = 1;
- }
- if (s->dma_dac2.count + (signed)s->dma_dac2.fragsize <= (signed)s->dma_dac2.dmasize)
- wake_up(&s->dma_dac2.wait);
- }
- }
-}
-
-/* hold spinlock for the following! */
-static void es1371_handle_midi(struct es1371_state *s)
-{
- unsigned char ch;
- int wake;
-
- if (!(s->ctrl & CTRL_UART_EN))
- return;
- wake = 0;
- while (inb(s->io+ES1371_REG_UART_STATUS) & USTAT_RXRDY) {
- ch = inb(s->io+ES1371_REG_UART_DATA);
- if (s->midi.icnt < MIDIINBUF) {
- s->midi.ibuf[s->midi.iwr] = ch;
- s->midi.iwr = (s->midi.iwr + 1) % MIDIINBUF;
- s->midi.icnt++;
- }
- wake = 1;
- }
- if (wake)
- wake_up(&s->midi.iwait);
- wake = 0;
- while ((inb(s->io+ES1371_REG_UART_STATUS) & USTAT_TXRDY) && s->midi.ocnt > 0) {
- outb(s->midi.obuf[s->midi.ord], s->io+ES1371_REG_UART_DATA);
- s->midi.ord = (s->midi.ord + 1) % MIDIOUTBUF;
- s->midi.ocnt--;
- if (s->midi.ocnt < MIDIOUTBUF-16)
- wake = 1;
- }
- if (wake)
- wake_up(&s->midi.owait);
- outb((s->midi.ocnt > 0) ? UCTRL_RXINTEN | UCTRL_ENA_TXINT : UCTRL_RXINTEN, s->io+ES1371_REG_UART_CONTROL);
-}
-
-static irqreturn_t es1371_interrupt(int irq, void *dev_id)
-{
- struct es1371_state *s = dev_id;
- unsigned int intsrc, sctl;
-
- /* fastpath out, to ease interrupt sharing */
- intsrc = inl(s->io+ES1371_REG_STATUS);
- if (!(intsrc & 0x80000000))
- return IRQ_NONE;
- spin_lock(&s->lock);
- /* clear audio interrupts first */
- sctl = s->sctrl;
- if (intsrc & STAT_ADC)
- sctl &= ~SCTRL_R1INTEN;
- if (intsrc & STAT_DAC1)
- sctl &= ~SCTRL_P1INTEN;
- if (intsrc & STAT_DAC2)
- sctl &= ~SCTRL_P2INTEN;
- outl(sctl, s->io+ES1371_REG_SERIAL_CONTROL);
- outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL);
- es1371_update_ptr(s);
- es1371_handle_midi(s);
- spin_unlock(&s->lock);
- return IRQ_HANDLED;
-}
-
-/* --------------------------------------------------------------------- */
-
-static const char invalid_magic[] = KERN_CRIT PFX "invalid magic value\n";
-
-#define VALIDATE_STATE(s) \
-({ \
- if (!(s) || (s)->magic != ES1371_MAGIC) { \
- printk(invalid_magic); \
- return -ENXIO; \
- } \
-})
-
-/* --------------------------------------------------------------------- */
-
-/* Conversion table for S/PDIF PCM volume emulation through the SRC */
-/* dB-linear table of DAC vol values; -0dB to -46.5dB with mute */
-static const unsigned short DACVolTable[101] =
-{
- 0x1000, 0x0f2a, 0x0e60, 0x0da0, 0x0cea, 0x0c3e, 0x0b9a, 0x0aff,
- 0x0a6d, 0x09e1, 0x095e, 0x08e1, 0x086a, 0x07fa, 0x078f, 0x072a,
- 0x06cb, 0x0670, 0x061a, 0x05c9, 0x057b, 0x0532, 0x04ed, 0x04ab,
- 0x046d, 0x0432, 0x03fa, 0x03c5, 0x0392, 0x0363, 0x0335, 0x030b,
- 0x02e2, 0x02bc, 0x0297, 0x0275, 0x0254, 0x0235, 0x0217, 0x01fb,
- 0x01e1, 0x01c8, 0x01b0, 0x0199, 0x0184, 0x0170, 0x015d, 0x014b,
- 0x0139, 0x0129, 0x0119, 0x010b, 0x00fd, 0x00f0, 0x00e3, 0x00d7,
- 0x00cc, 0x00c1, 0x00b7, 0x00ae, 0x00a5, 0x009c, 0x0094, 0x008c,
- 0x0085, 0x007e, 0x0077, 0x0071, 0x006b, 0x0066, 0x0060, 0x005b,
- 0x0057, 0x0052, 0x004e, 0x004a, 0x0046, 0x0042, 0x003f, 0x003c,
- 0x0038, 0x0036, 0x0033, 0x0030, 0x002e, 0x002b, 0x0029, 0x0027,
- 0x0025, 0x0023, 0x0021, 0x001f, 0x001e, 0x001c, 0x001b, 0x0019,
- 0x0018, 0x0017, 0x0016, 0x0014, 0x0000
-};
-
-/*
- * when we are in S/PDIF mode, we want to disable any analog output so
- * we filter the mixer ioctls
- */
-static int mixdev_ioctl(struct ac97_codec *codec, unsigned int cmd, unsigned long arg)
-{
- struct es1371_state *s = (struct es1371_state *)codec->private_data;
- int val;
- unsigned long flags;
- unsigned int left, right;
-
- VALIDATE_STATE(s);
- /* filter mixer ioctls to catch PCM and MASTER volume when in S/PDIF mode */
- if (s->spdif_volume == -1)
- return codec->mixer_ioctl(codec, cmd, arg);
- switch (cmd) {
- case SOUND_MIXER_WRITE_VOLUME:
- return 0;
-
- case SOUND_MIXER_WRITE_PCM: /* use SRC for PCM volume */
- if (get_user(val, (int __user *)arg))
- return -EFAULT;
- right = ((val >> 8) & 0xff);
- left = (val & 0xff);
- if (right > 100)
- right = 100;
- if (left > 100)
- left = 100;
- s->spdif_volume = (right << 8) | left;
- spin_lock_irqsave(&s->lock, flags);
- src_write(s, SRCREG_VOL_DAC2, DACVolTable[100 - left]);
- src_write(s, SRCREG_VOL_DAC2+1, DACVolTable[100 - right]);
- spin_unlock_irqrestore(&s->lock, flags);
- return 0;
-
- case SOUND_MIXER_READ_PCM:
- return put_user(s->spdif_volume, (int __user *)arg);
- }
- return codec->mixer_ioctl(codec, cmd, arg);
-}
-
-/* --------------------------------------------------------------------- */
-
-/*
- * AC97 Mixer Register to Connections mapping of the Concert 97 board
- *
- * AC97_MASTER_VOL_STEREO Line Out
- * AC97_MASTER_VOL_MONO TAD Output
- * AC97_PCBEEP_VOL none
- * AC97_PHONE_VOL TAD Input (mono)
- * AC97_MIC_VOL MIC Input (mono)
- * AC97_LINEIN_VOL Line Input (stereo)
- * AC97_CD_VOL CD Input (stereo)
- * AC97_VIDEO_VOL none
- * AC97_AUX_VOL Aux Input (stereo)
- * AC97_PCMOUT_VOL Wave Output (stereo)
- */
-
-static int es1371_open_mixdev(struct inode *inode, struct file *file)
-{
- int minor = iminor(inode);
- struct list_head *list;
- struct es1371_state *s;
-
- for (list = devs.next; ; list = list->next) {
- if (list == &devs)
- return -ENODEV;
- s = list_entry(list, struct es1371_state, devs);
- if (s->codec->dev_mixer == minor)
- break;
- }
- VALIDATE_STATE(s);
- file->private_data = s;
- return nonseekable_open(inode, file);
-}
-
-static int es1371_release_mixdev(struct inode *inode, struct file *file)
-{
- struct es1371_state *s = (struct es1371_state *)file->private_data;
-
- VALIDATE_STATE(s);
- return 0;
-}
-
-static int es1371_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
- struct es1371_state *s = (struct es1371_state *)file->private_data;
- struct ac97_codec *codec = s->codec;
-
- return mixdev_ioctl(codec, cmd, arg);
-}
-
-static /*const*/ struct file_operations es1371_mixer_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .ioctl = es1371_ioctl_mixdev,
- .open = es1371_open_mixdev,
- .release = es1371_release_mixdev,
-};
-
-/* --------------------------------------------------------------------- */
-
-static int drain_dac1(struct es1371_state *s, int nonblock)
-{
- DECLARE_WAITQUEUE(wait, current);
- unsigned long flags;
- int count, tmo;
-
- if (s->dma_dac1.mapped || !s->dma_dac1.ready)
- return 0;
- add_wait_queue(&s->dma_dac1.wait, &wait);
- for (;;) {
- __set_current_state(TASK_INTERRUPTIBLE);
- spin_lock_irqsave(&s->lock, flags);
- count = s->dma_dac1.count;
- spin_unlock_irqrestore(&s->lock, flags);
- if (count <= 0)
- break;
- if (signal_pending(current))
- break;
- if (nonblock) {
- remove_wait_queue(&s->dma_dac1.wait, &wait);
- set_current_state(TASK_RUNNING);
- return -EBUSY;
- }
- tmo = 3 * HZ * (count + s->dma_dac1.fragsize) / 2 / s->dac1rate;
- tmo >>= sample_shift[(s->sctrl & SCTRL_P1FMT) >> SCTRL_SH_P1FMT];
- if (!schedule_timeout(tmo + 1))
- DBG(printk(KERN_DEBUG PFX "dac1 dma timed out??\n");)
- }
- remove_wait_queue(&s->dma_dac1.wait, &wait);
- set_current_state(TASK_RUNNING);
- if (signal_pending(current))
- return -ERESTARTSYS;
- return 0;
-}
-
-static int drain_dac2(struct es1371_state *s, int nonblock)
-{
- DECLARE_WAITQUEUE(wait, current);
- unsigned long flags;
- int count, tmo;
-
- if (s->dma_dac2.mapped || !s->dma_dac2.ready)
- return 0;
- add_wait_queue(&s->dma_dac2.wait, &wait);
- for (;;) {
- __set_current_state(TASK_UNINTERRUPTIBLE);
- spin_lock_irqsave(&s->lock, flags);
- count = s->dma_dac2.count;
- spin_unlock_irqrestore(&s->lock, flags);
- if (count <= 0)
- break;
- if (signal_pending(current))
- break;
- if (nonblock) {
- remove_wait_queue(&s->dma_dac2.wait, &wait);
- set_current_state(TASK_RUNNING);
- return -EBUSY;
- }
- tmo = 3 * HZ * (count + s->dma_dac2.fragsize) / 2 / s->dac2rate;
- tmo >>= sample_shift[(s->sctrl & SCTRL_P2FMT) >> SCTRL_SH_P2FMT];
- if (!schedule_timeout(tmo + 1))
- DBG(printk(KERN_DEBUG PFX "dac2 dma timed out??\n");)
- }
- remove_wait_queue(&s->dma_dac2.wait, &wait);
- set_current_state(TASK_RUNNING);
- if (signal_pending(current))
- return -ERESTARTSYS;
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static ssize_t es1371_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
-{
- struct es1371_state *s = (struct es1371_state *)file->private_data;
- DECLARE_WAITQUEUE(wait, current);
- ssize_t ret = 0;
- unsigned long flags;
- unsigned swptr;
- int cnt;
-
- VALIDATE_STATE(s);
- if (s->dma_adc.mapped)
- return -ENXIO;
- if (!access_ok(VERIFY_WRITE, buffer, count))
- return -EFAULT;
- mutex_lock(&s->sem);
- if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s)))
- goto out2;
-
- add_wait_queue(&s->dma_adc.wait, &wait);
- while (count > 0) {
- spin_lock_irqsave(&s->lock, flags);
- swptr = s->dma_adc.swptr;
- cnt = s->dma_adc.dmasize-swptr;
- if (s->dma_adc.count < cnt)
- cnt = s->dma_adc.count;
- if (cnt <= 0)
- __set_current_state(TASK_INTERRUPTIBLE);
- spin_unlock_irqrestore(&s->lock, flags);
- if (cnt > count)
- cnt = count;
- if (cnt <= 0) {
- if (s->dma_adc.enabled)
- start_adc(s);
- if (file->f_flags & O_NONBLOCK) {
- if (!ret)
- ret = -EAGAIN;
- goto out;
- }
- mutex_unlock(&s->sem);
- schedule();
- if (signal_pending(current)) {
- if (!ret)
- ret = -ERESTARTSYS;
- goto out2;
- }
- mutex_lock(&s->sem);
- if (s->dma_adc.mapped)
- {
- ret = -ENXIO;
- goto out;
- }
- continue;
- }
- if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) {
- if (!ret)
- ret = -EFAULT;
- goto out;
- }
- swptr = (swptr + cnt) % s->dma_adc.dmasize;
- spin_lock_irqsave(&s->lock, flags);
- s->dma_adc.swptr = swptr;
- s->dma_adc.count -= cnt;
- spin_unlock_irqrestore(&s->lock, flags);
- count -= cnt;
- buffer += cnt;
- ret += cnt;
- if (s->dma_adc.enabled)
- start_adc(s);
- }
-out:
- mutex_unlock(&s->sem);
-out2:
- remove_wait_queue(&s->dma_adc.wait, &wait);
- set_current_state(TASK_RUNNING);
- return ret;
-}
-
-static ssize_t es1371_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
-{
- struct es1371_state *s = (struct es1371_state *)file->private_data;
- DECLARE_WAITQUEUE(wait, current);
- ssize_t ret;
- unsigned long flags;
- unsigned swptr;
- int cnt;
-
- VALIDATE_STATE(s);
- if (s->dma_dac2.mapped)
- return -ENXIO;
- if (!access_ok(VERIFY_READ, buffer, count))
- return -EFAULT;
- mutex_lock(&s->sem);
- if (!s->dma_dac2.ready && (ret = prog_dmabuf_dac2(s)))
- goto out3;
- ret = 0;
- add_wait_queue(&s->dma_dac2.wait, &wait);
- while (count > 0) {
- spin_lock_irqsave(&s->lock, flags);
- if (s->dma_dac2.count < 0) {
- s->dma_dac2.count = 0;
- s->dma_dac2.swptr = s->dma_dac2.hwptr;
- }
- swptr = s->dma_dac2.swptr;
- cnt = s->dma_dac2.dmasize-swptr;
- if (s->dma_dac2.count + cnt > s->dma_dac2.dmasize)
- cnt = s->dma_dac2.dmasize - s->dma_dac2.count;
- if (cnt <= 0)
- __set_current_state(TASK_INTERRUPTIBLE);
- spin_unlock_irqrestore(&s->lock, flags);
- if (cnt > count)
- cnt = count;
- if (cnt <= 0) {
- if (s->dma_dac2.enabled)
- start_dac2(s);
- if (file->f_flags & O_NONBLOCK) {
- if (!ret)
- ret = -EAGAIN;
- goto out;
- }
- mutex_unlock(&s->sem);
- schedule();
- if (signal_pending(current)) {
- if (!ret)
- ret = -ERESTARTSYS;
- goto out2;
- }
- mutex_lock(&s->sem);
- if (s->dma_dac2.mapped)
- {
- ret = -ENXIO;
- goto out;
- }
- continue;
- }
- if (copy_from_user(s->dma_dac2.rawbuf + swptr, buffer, cnt)) {
- if (!ret)
- ret = -EFAULT;
- goto out;
- }
- swptr = (swptr + cnt) % s->dma_dac2.dmasize;
- spin_lock_irqsave(&s->lock, flags);
- s->dma_dac2.swptr = swptr;
- s->dma_dac2.count += cnt;
- s->dma_dac2.endcleared = 0;
- spin_unlock_irqrestore(&s->lock, flags);
- count -= cnt;
- buffer += cnt;
- ret += cnt;
- if (s->dma_dac2.enabled)
- start_dac2(s);
- }
-out:
- mutex_unlock(&s->sem);
-out2:
- remove_wait_queue(&s->dma_dac2.wait, &wait);
-out3:
- set_current_state(TASK_RUNNING);
- return ret;
-}
-
-/* No kernel lock - we have our own spinlock */
-static unsigned int es1371_poll(struct file *file, struct poll_table_struct *wait)
-{
- struct es1371_state *s = (struct es1371_state *)file->private_data;
- unsigned long flags;
- unsigned int mask = 0;
-
- VALIDATE_STATE(s);
- if (file->f_mode & FMODE_WRITE) {
- if (!s->dma_dac2.ready && prog_dmabuf_dac2(s))
- return 0;
- poll_wait(file, &s->dma_dac2.wait, wait);
- }
- if (file->f_mode & FMODE_READ) {
- if (!s->dma_adc.ready && prog_dmabuf_adc(s))
- return 0;
- poll_wait(file, &s->dma_adc.wait, wait);
- }
- spin_lock_irqsave(&s->lock, flags);
- es1371_update_ptr(s);
- if (file->f_mode & FMODE_READ) {
- if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)
- mask |= POLLIN | POLLRDNORM;
- }
- if (file->f_mode & FMODE_WRITE) {
- if (s->dma_dac2.mapped) {
- if (s->dma_dac2.count >= (signed)s->dma_dac2.fragsize)
- mask |= POLLOUT | POLLWRNORM;
- } else {
- if ((signed)s->dma_dac2.dmasize >= s->dma_dac2.count + (signed)s->dma_dac2.fragsize)
- mask |= POLLOUT | POLLWRNORM;
- }
- }
- spin_unlock_irqrestore(&s->lock, flags);
- return mask;
-}
-
-static int es1371_mmap(struct file *file, struct vm_area_struct *vma)
-{
- struct es1371_state *s = (struct es1371_state *)file->private_data;
- struct dmabuf *db;
- int ret = 0;
- unsigned long size;
-
- VALIDATE_STATE(s);
- lock_kernel();
- mutex_lock(&s->sem);
-
- if (vma->vm_flags & VM_WRITE) {
- if ((ret = prog_dmabuf_dac2(s)) != 0) {
- goto out;
- }
- db = &s->dma_dac2;
- } else if (vma->vm_flags & VM_READ) {
- if ((ret = prog_dmabuf_adc(s)) != 0) {
- goto out;
- }
- db = &s->dma_adc;
- } else {
- ret = -EINVAL;
- goto out;
- }
- if (vma->vm_pgoff != 0) {
- ret = -EINVAL;
- goto out;
- }
- size = vma->vm_end - vma->vm_start;
- if (size > (PAGE_SIZE << db->buforder)) {
- ret = -EINVAL;
- goto out;
- }
- if (remap_pfn_range(vma, vma->vm_start,
- virt_to_phys(db->rawbuf) >> PAGE_SHIFT,
- size, vma->vm_page_prot)) {
- ret = -EAGAIN;
- goto out;
- }
- db->mapped = 1;
-out:
- mutex_unlock(&s->sem);
- unlock_kernel();
- return ret;
-}
-
-static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
- struct es1371_state *s = (struct es1371_state *)file->private_data;
- unsigned long flags;
- audio_buf_info abinfo;
- count_info cinfo;
- int count;
- int val, mapped, ret;
- void __user *argp = (void __user *)arg;
- int __user *p = argp;
-
- VALIDATE_STATE(s);
- mapped = ((file->f_mode & FMODE_WRITE) && s->dma_dac2.mapped) ||
- ((file->f_mode & FMODE_READ) && s->dma_adc.mapped);
- switch (cmd) {
- case OSS_GETVERSION:
- return put_user(SOUND_VERSION, p);
-
- case SNDCTL_DSP_SYNC:
- if (file->f_mode & FMODE_WRITE)
- return drain_dac2(s, 0/*file->f_flags & O_NONBLOCK*/);
- return 0;
-
- case SNDCTL_DSP_SETDUPLEX:
- return 0;
-
- case SNDCTL_DSP_GETCAPS:
- return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP, p);
-
- case SNDCTL_DSP_RESET:
- if (file->f_mode & FMODE_WRITE) {
- stop_dac2(s);
- synchronize_irq(s->irq);
- s->dma_dac2.swptr = s->dma_dac2.hwptr = s->dma_dac2.count = s->dma_dac2.total_bytes = 0;
- }
- if (file->f_mode & FMODE_READ) {
- stop_adc(s);
- synchronize_irq(s->irq);
- s->dma_adc.swptr = s->dma_adc.hwptr = s->dma_adc.count = s->dma_adc.total_bytes = 0;
- }
- return 0;
-
- case SNDCTL_DSP_SPEED:
- if (get_user(val, p))
- return -EFAULT;
- if (val >= 0) {
- if (file->f_mode & FMODE_READ) {
- stop_adc(s);
- s->dma_adc.ready = 0;
- set_adc_rate(s, val);
- }
- if (file->f_mode & FMODE_WRITE) {
- stop_dac2(s);
- s->dma_dac2.ready = 0;
- set_dac2_rate(s, val);
- }
- }
- return put_user((file->f_mode & FMODE_READ) ? s->adcrate : s->dac2rate, p);
-
- case SNDCTL_DSP_STEREO:
- if (get_user(val, p))
- return -EFAULT;
- if (file->f_mode & FMODE_READ) {
- stop_adc(s);
- s->dma_adc.ready = 0;
- spin_lock_irqsave(&s->lock, flags);
- if (val)
- s->sctrl |= SCTRL_R1SMB;
- else
- s->sctrl &= ~SCTRL_R1SMB;
- outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL);
- spin_unlock_irqrestore(&s->lock, flags);
- }
- if (file->f_mode & FMODE_WRITE) {
- stop_dac2(s);
- s->dma_dac2.ready = 0;
- spin_lock_irqsave(&s->lock, flags);
- if (val)
- s->sctrl |= SCTRL_P2SMB;
- else
- s->sctrl &= ~SCTRL_P2SMB;
- outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL);
- spin_unlock_irqrestore(&s->lock, flags);
- }
- return 0;
-
- case SNDCTL_DSP_CHANNELS:
- if (get_user(val, p))
- return -EFAULT;
- if (val != 0) {
- if (file->f_mode & FMODE_READ) {
- stop_adc(s);
- s->dma_adc.ready = 0;
- spin_lock_irqsave(&s->lock, flags);
- if (val >= 2)
- s->sctrl |= SCTRL_R1SMB;
- else
- s->sctrl &= ~SCTRL_R1SMB;
- outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL);
- spin_unlock_irqrestore(&s->lock, flags);
- }
- if (file->f_mode & FMODE_WRITE) {
- stop_dac2(s);
- s->dma_dac2.ready = 0;
- spin_lock_irqsave(&s->lock, flags);
- if (val >= 2)
- s->sctrl |= SCTRL_P2SMB;
- else
- s->sctrl &= ~SCTRL_P2SMB;
- outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL);
- spin_unlock_irqrestore(&s->lock, flags);
- }
- }
- return put_user((s->sctrl & ((file->f_mode & FMODE_READ) ? SCTRL_R1SMB : SCTRL_P2SMB)) ? 2 : 1, p);
-
- case SNDCTL_DSP_GETFMTS: /* Returns a mask */
- return put_user(AFMT_S16_LE|AFMT_U8, p);
-
- case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
- if (get_user(val, p))
- return -EFAULT;
- if (val != AFMT_QUERY) {
- if (file->f_mode & FMODE_READ) {
- stop_adc(s);
- s->dma_adc.ready = 0;
- spin_lock_irqsave(&s->lock, flags);
- if (val == AFMT_S16_LE)
- s->sctrl |= SCTRL_R1SEB;
- else
- s->sctrl &= ~SCTRL_R1SEB;
- outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL);
- spin_unlock_irqrestore(&s->lock, flags);
- }
- if (file->f_mode & FMODE_WRITE) {
- stop_dac2(s);
- s->dma_dac2.ready = 0;
- spin_lock_irqsave(&s->lock, flags);
- if (val == AFMT_S16_LE)
- s->sctrl |= SCTRL_P2SEB;
- else
- s->sctrl &= ~SCTRL_P2SEB;
- outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL);
- spin_unlock_irqrestore(&s->lock, flags);
- }
- }
- return put_user((s->sctrl & ((file->f_mode & FMODE_READ) ? SCTRL_R1SEB : SCTRL_P2SEB)) ?
- AFMT_S16_LE : AFMT_U8, p);
-
- case SNDCTL_DSP_POST:
- return 0;
-
- case SNDCTL_DSP_GETTRIGGER:
- val = 0;
- if (file->f_mode & FMODE_READ && s->ctrl & CTRL_ADC_EN)
- val |= PCM_ENABLE_INPUT;
- if (file->f_mode & FMODE_WRITE && s->ctrl & CTRL_DAC2_EN)
- val |= PCM_ENABLE_OUTPUT;
- return put_user(val, p);
-
- case SNDCTL_DSP_SETTRIGGER:
- if (get_user(val, p))
- return -EFAULT;
- if (file->f_mode & FMODE_READ) {
- if (val & PCM_ENABLE_INPUT) {
- if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s)))
- return ret;
- s->dma_adc.enabled = 1;
- start_adc(s);
- } else {
- s->dma_adc.enabled = 0;
- stop_adc(s);
- }
- }
- if (file->f_mode & FMODE_WRITE) {
- if (val & PCM_ENABLE_OUTPUT) {
- if (!s->dma_dac2.ready && (ret = prog_dmabuf_dac2(s)))
- return ret;
- s->dma_dac2.enabled = 1;
- start_dac2(s);
- } else {
- s->dma_dac2.enabled = 0;
- stop_dac2(s);
- }
- }
- return 0;
-
- case SNDCTL_DSP_GETOSPACE:
- if (!(file->f_mode & FMODE_WRITE))
- return -EINVAL;
- if (!s->dma_dac2.ready && (val = prog_dmabuf_dac2(s)) != 0)
- return val;
- spin_lock_irqsave(&s->lock, flags);
- es1371_update_ptr(s);
- abinfo.fragsize = s->dma_dac2.fragsize;
- count = s->dma_dac2.count;
- if (count < 0)
- count = 0;
- abinfo.bytes = s->dma_dac2.dmasize - count;
- abinfo.fragstotal = s->dma_dac2.numfrag;
- abinfo.fragments = abinfo.bytes >> s->dma_dac2.fragshift;
- spin_unlock_irqrestore(&s->lock, flags);
- return copy_to_user(argp, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
-
- case SNDCTL_DSP_GETISPACE:
- if (!(file->f_mode & FMODE_READ))
- return -EINVAL;
- if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)) != 0)
- return val;
- spin_lock_irqsave(&s->lock, flags);
- es1371_update_ptr(s);
- abinfo.fragsize = s->dma_adc.fragsize;
- count = s->dma_adc.count;
- if (count < 0)
- count = 0;
- abinfo.bytes = count;
- abinfo.fragstotal = s->dma_adc.numfrag;
- abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift;
- spin_unlock_irqrestore(&s->lock, flags);
- return copy_to_user(argp, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
-
- case SNDCTL_DSP_NONBLOCK:
- file->f_flags |= O_NONBLOCK;
- return 0;
-
- case SNDCTL_DSP_GETODELAY:
- if (!(file->f_mode & FMODE_WRITE))
- return -EINVAL;
- if (!s->dma_dac2.ready && (val = prog_dmabuf_dac2(s)) != 0)
- return val;
- spin_lock_irqsave(&s->lock, flags);
- es1371_update_ptr(s);
- count = s->dma_dac2.count;
- spin_unlock_irqrestore(&s->lock, flags);
- if (count < 0)
- count = 0;
- return put_user(count, p);
-
- case SNDCTL_DSP_GETIPTR:
- if (!(file->f_mode & FMODE_READ))
- return -EINVAL;
- if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)) != 0)
- return val;
- spin_lock_irqsave(&s->lock, flags);
- es1371_update_ptr(s);
- cinfo.bytes = s->dma_adc.total_bytes;
- count = s->dma_adc.count;
- if (count < 0)
- count = 0;
- cinfo.blocks = count >> s->dma_adc.fragshift;
- cinfo.ptr = s->dma_adc.hwptr;
- if (s->dma_adc.mapped)
- s->dma_adc.count &= s->dma_adc.fragsize-1;
- spin_unlock_irqrestore(&s->lock, flags);
- if (copy_to_user(argp, &cinfo, sizeof(cinfo)))
- return -EFAULT;
- return 0;
-
- case SNDCTL_DSP_GETOPTR:
- if (!(file->f_mode & FMODE_WRITE))
- return -EINVAL;
- if (!s->dma_dac2.ready && (val = prog_dmabuf_dac2(s)) != 0)
- return val;
- spin_lock_irqsave(&s->lock, flags);
- es1371_update_ptr(s);
- cinfo.bytes = s->dma_dac2.total_bytes;
- count = s->dma_dac2.count;
- if (count < 0)
- count = 0;
- cinfo.blocks = count >> s->dma_dac2.fragshift;
- cinfo.ptr = s->dma_dac2.hwptr;
- if (s->dma_dac2.mapped)
- s->dma_dac2.count &= s->dma_dac2.fragsize-1;
- spin_unlock_irqrestore(&s->lock, flags);
- if (copy_to_user(argp, &cinfo, sizeof(cinfo)))
- return -EFAULT;
- return 0;
-
- case SNDCTL_DSP_GETBLKSIZE:
- if (file->f_mode & FMODE_WRITE) {
- if ((val = prog_dmabuf_dac2(s)))
- return val;
- return put_user(s->dma_dac2.fragsize, p);
- }
- if ((val = prog_dmabuf_adc(s)))
- return val;
- return put_user(s->dma_adc.fragsize, p);
-
- case SNDCTL_DSP_SETFRAGMENT:
- if (get_user(val, p))
- return -EFAULT;
- if (file->f_mode & FMODE_READ) {
- s->dma_adc.ossfragshift = val & 0xffff;
- s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff;
- if (s->dma_adc.ossfragshift < 4)
- s->dma_adc.ossfragshift = 4;
- if (s->dma_adc.ossfragshift > 15)
- s->dma_adc.ossfragshift = 15;
- if (s->dma_adc.ossmaxfrags < 4)
- s->dma_adc.ossmaxfrags = 4;
- }
- if (file->f_mode & FMODE_WRITE) {
- s->dma_dac2.ossfragshift = val & 0xffff;
- s->dma_dac2.ossmaxfrags = (val >> 16) & 0xffff;
- if (s->dma_dac2.ossfragshift < 4)
- s->dma_dac2.ossfragshift = 4;
- if (s->dma_dac2.ossfragshift > 15)
- s->dma_dac2.ossfragshift = 15;
- if (s->dma_dac2.ossmaxfrags < 4)
- s->dma_dac2.ossmaxfrags = 4;
- }
- return 0;
-
- case SNDCTL_DSP_SUBDIVIDE:
- if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) ||
- (file->f_mode & FMODE_WRITE && s->dma_dac2.subdivision))
- return -EINVAL;
- if (get_user(val, p))
- return -EFAULT;
- if (val != 1 && val != 2 && val != 4)
- return -EINVAL;
- if (file->f_mode & FMODE_READ)
- s->dma_adc.subdivision = val;
- if (file->f_mode & FMODE_WRITE)
- s->dma_dac2.subdivision = val;
- return 0;
-
- case SOUND_PCM_READ_RATE:
- return put_user((file->f_mode & FMODE_READ) ? s->adcrate : s->dac2rate, p);
-
- case SOUND_PCM_READ_CHANNELS:
- return put_user((s->sctrl & ((file->f_mode & FMODE_READ) ? SCTRL_R1SMB : SCTRL_P2SMB)) ? 2 : 1, p);
-
- case SOUND_PCM_READ_BITS:
- return put_user((s->sctrl & ((file->f_mode & FMODE_READ) ? SCTRL_R1SEB : SCTRL_P2SEB)) ? 16 : 8, p);
-
- case SOUND_PCM_WRITE_FILTER:
- case SNDCTL_DSP_SETSYNCRO:
- case SOUND_PCM_READ_FILTER:
- return -EINVAL;
-
- }
- return mixdev_ioctl(s->codec, cmd, arg);
-}
-
-static int es1371_open(struct inode *inode, struct file *file)
-{
- int minor = iminor(inode);
- DECLARE_WAITQUEUE(wait, current);
- unsigned long flags;
- struct list_head *list;
- struct es1371_state *s;
-
- for (list = devs.next; ; list = list->next) {
- if (list == &devs)
- return -ENODEV;
- s = list_entry(list, struct es1371_state, devs);
- if (!((s->dev_audio ^ minor) & ~0xf))
- break;
- }
- VALIDATE_STATE(s);
- file->private_data = s;
- /* wait for device to become free */
- mutex_lock(&s->open_mutex);
- while (s->open_mode & file->f_mode) {
- if (file->f_flags & O_NONBLOCK) {
- mutex_unlock(&s->open_mutex);
- return -EBUSY;
- }
- add_wait_queue(&s->open_wait, &wait);
- __set_current_state(TASK_INTERRUPTIBLE);
- mutex_unlock(&s->open_mutex);
- schedule();
- remove_wait_queue(&s->open_wait, &wait);
- set_current_state(TASK_RUNNING);
- if (signal_pending(current))
- return -ERESTARTSYS;
- mutex_lock(&s->open_mutex);
- }
- if (file->f_mode & FMODE_READ) {
- s->dma_adc.ossfragshift = s->dma_adc.ossmaxfrags = s->dma_adc.subdivision = 0;
- s->dma_adc.enabled = 1;
- set_adc_rate(s, 8000);
- }
- if (file->f_mode & FMODE_WRITE) {
- s->dma_dac2.ossfragshift = s->dma_dac2.ossmaxfrags = s->dma_dac2.subdivision = 0;
- s->dma_dac2.enabled = 1;
- set_dac2_rate(s, 8000);
- }
- spin_lock_irqsave(&s->lock, flags);
- if (file->f_mode & FMODE_READ) {
- s->sctrl &= ~SCTRL_R1FMT;
- if ((minor & 0xf) == SND_DEV_DSP16)
- s->sctrl |= ES1371_FMT_S16_MONO << SCTRL_SH_R1FMT;
- else
- s->sctrl |= ES1371_FMT_U8_MONO << SCTRL_SH_R1FMT;
- }
- if (file->f_mode & FMODE_WRITE) {
- s->sctrl &= ~SCTRL_P2FMT;
- if ((minor & 0xf) == SND_DEV_DSP16)
- s->sctrl |= ES1371_FMT_S16_MONO << SCTRL_SH_P2FMT;
- else
- s->sctrl |= ES1371_FMT_U8_MONO << SCTRL_SH_P2FMT;
- }
- outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL);
- spin_unlock_irqrestore(&s->lock, flags);
- s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
- mutex_unlock(&s->open_mutex);
- mutex_init(&s->sem);
- return nonseekable_open(inode, file);
-}
-
-static int es1371_release(struct inode *inode, struct file *file)
-{
- struct es1371_state *s = (struct es1371_state *)file->private_data;
-
- VALIDATE_STATE(s);
- lock_kernel();
- if (file->f_mode & FMODE_WRITE)
- drain_dac2(s, file->f_flags & O_NONBLOCK);
- mutex_lock(&s->open_mutex);
- if (file->f_mode & FMODE_WRITE) {
- stop_dac2(s);
- dealloc_dmabuf(s, &s->dma_dac2);
- }
- if (file->f_mode & FMODE_READ) {
- stop_adc(s);
- dealloc_dmabuf(s, &s->dma_adc);
- }
- s->open_mode &= ~(file->f_mode & (FMODE_READ|FMODE_WRITE));
- mutex_unlock(&s->open_mutex);
- wake_up(&s->open_wait);
- unlock_kernel();
- return 0;
-}
-
-static /*const*/ struct file_operations es1371_audio_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .read = es1371_read,
- .write = es1371_write,
- .poll = es1371_poll,
- .ioctl = es1371_ioctl,
- .mmap = es1371_mmap,
- .open = es1371_open,
- .release = es1371_release,
-};
-
-/* --------------------------------------------------------------------- */
-
-static ssize_t es1371_write_dac(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
-{
- struct es1371_state *s = (struct es1371_state *)file->private_data;
- DECLARE_WAITQUEUE(wait, current);
- ssize_t ret = 0;
- unsigned long flags;
- unsigned swptr;
- int cnt;
-
- VALIDATE_STATE(s);
- if (s->dma_dac1.mapped)
- return -ENXIO;
- if (!s->dma_dac1.ready && (ret = prog_dmabuf_dac1(s)))
- return ret;
- if (!access_ok(VERIFY_READ, buffer, count))
- return -EFAULT;
- add_wait_queue(&s->dma_dac1.wait, &wait);
- while (count > 0) {
- spin_lock_irqsave(&s->lock, flags);
- if (s->dma_dac1.count < 0) {
- s->dma_dac1.count = 0;
- s->dma_dac1.swptr = s->dma_dac1.hwptr;
- }
- swptr = s->dma_dac1.swptr;
- cnt = s->dma_dac1.dmasize-swptr;
- if (s->dma_dac1.count + cnt > s->dma_dac1.dmasize)
- cnt = s->dma_dac1.dmasize - s->dma_dac1.count;
- if (cnt <= 0)
- __set_current_state(TASK_INTERRUPTIBLE);
- spin_unlock_irqrestore(&s->lock, flags);
- if (cnt > count)
- cnt = count;
- if (cnt <= 0) {
- if (s->dma_dac1.enabled)
- start_dac1(s);
- if (file->f_flags & O_NONBLOCK) {
- if (!ret)
- ret = -EAGAIN;
- break;
- }
- schedule();
- if (signal_pending(current)) {
- if (!ret)
- ret = -ERESTARTSYS;
- break;
- }
- continue;
- }
- if (copy_from_user(s->dma_dac1.rawbuf + swptr, buffer, cnt)) {
- if (!ret)
- ret = -EFAULT;
- break;
- }
- swptr = (swptr + cnt) % s->dma_dac1.dmasize;
- spin_lock_irqsave(&s->lock, flags);
- s->dma_dac1.swptr = swptr;
- s->dma_dac1.count += cnt;
- s->dma_dac1.endcleared = 0;
- spin_unlock_irqrestore(&s->lock, flags);
- count -= cnt;
- buffer += cnt;
- ret += cnt;
- if (s->dma_dac1.enabled)
- start_dac1(s);
- }
- remove_wait_queue(&s->dma_dac1.wait, &wait);
- set_current_state(TASK_RUNNING);
- return ret;
-}
-
-/* No kernel lock - we have our own spinlock */
-static unsigned int es1371_poll_dac(struct file *file, struct poll_table_struct *wait)
-{
- struct es1371_state *s = (struct es1371_state *)file->private_data;
- unsigned long flags;
- unsigned int mask = 0;
-
- VALIDATE_STATE(s);
- if (!s->dma_dac1.ready && prog_dmabuf_dac1(s))
- return 0;
- poll_wait(file, &s->dma_dac1.wait, wait);
- spin_lock_irqsave(&s->lock, flags);
- es1371_update_ptr(s);
- if (s->dma_dac1.mapped) {
- if (s->dma_dac1.count >= (signed)s->dma_dac1.fragsize)
- mask |= POLLOUT | POLLWRNORM;
- } else {
- if ((signed)s->dma_dac1.dmasize >= s->dma_dac1.count + (signed)s->dma_dac1.fragsize)
- mask |= POLLOUT | POLLWRNORM;
- }
- spin_unlock_irqrestore(&s->lock, flags);
- return mask;
-}
-
-static int es1371_mmap_dac(struct file *file, struct vm_area_struct *vma)
-{
- struct es1371_state *s = (struct es1371_state *)file->private_data;
- int ret;
- unsigned long size;
-
- VALIDATE_STATE(s);
- if (!(vma->vm_flags & VM_WRITE))
- return -EINVAL;
- lock_kernel();
- if ((ret = prog_dmabuf_dac1(s)) != 0)
- goto out;
- ret = -EINVAL;
- if (vma->vm_pgoff != 0)
- goto out;
- size = vma->vm_end - vma->vm_start;
- if (size > (PAGE_SIZE << s->dma_dac1.buforder))
- goto out;
- ret = -EAGAIN;
- if (remap_pfn_range(vma, vma->vm_start,
- virt_to_phys(s->dma_dac1.rawbuf) >> PAGE_SHIFT,
- size, vma->vm_page_prot))
- goto out;
- s->dma_dac1.mapped = 1;
- ret = 0;
-out:
- unlock_kernel();
- return ret;
-}
-
-static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
- struct es1371_state *s = (struct es1371_state *)file->private_data;
- unsigned long flags;
- audio_buf_info abinfo;
- count_info cinfo;
- int count;
- int val, ret;
- int __user *p = (int __user *)arg;
-
- VALIDATE_STATE(s);
- switch (cmd) {
- case OSS_GETVERSION:
- return put_user(SOUND_VERSION, p);
-
- case SNDCTL_DSP_SYNC:
- return drain_dac1(s, 0/*file->f_flags & O_NONBLOCK*/);
-
- case SNDCTL_DSP_SETDUPLEX:
- return -EINVAL;
-
- case SNDCTL_DSP_GETCAPS:
- return put_user(DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP, p);
-
- case SNDCTL_DSP_RESET:
- stop_dac1(s);
- synchronize_irq(s->irq);
- s->dma_dac1.swptr = s->dma_dac1.hwptr = s->dma_dac1.count = s->dma_dac1.total_bytes = 0;
- return 0;
-
- case SNDCTL_DSP_SPEED:
- if (get_user(val, p))
- return -EFAULT;
- if (val >= 0) {
- stop_dac1(s);
- s->dma_dac1.ready = 0;
- set_dac1_rate(s, val);
- }
- return put_user(s->dac1rate, p);
-
- case SNDCTL_DSP_STEREO:
- if (get_user(val, p))
- return -EFAULT;
- stop_dac1(s);
- s->dma_dac1.ready = 0;
- spin_lock_irqsave(&s->lock, flags);
- if (val)
- s->sctrl |= SCTRL_P1SMB;
- else
- s->sctrl &= ~SCTRL_P1SMB;
- outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL);
- spin_unlock_irqrestore(&s->lock, flags);
- return 0;
-
- case SNDCTL_DSP_CHANNELS:
- if (get_user(val, p))
- return -EFAULT;
- if (val != 0) {
- stop_dac1(s);
- s->dma_dac1.ready = 0;
- spin_lock_irqsave(&s->lock, flags);
- if (val >= 2)
- s->sctrl |= SCTRL_P1SMB;
- else
- s->sctrl &= ~SCTRL_P1SMB;
- outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL);
- spin_unlock_irqrestore(&s->lock, flags);
- }
- return put_user((s->sctrl & SCTRL_P1SMB) ? 2 : 1, p);
-
- case SNDCTL_DSP_GETFMTS: /* Returns a mask */
- return put_user(AFMT_S16_LE|AFMT_U8, p);
-
- case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
- if (get_user(val, p))
- return -EFAULT;
- if (val != AFMT_QUERY) {
- stop_dac1(s);
- s->dma_dac1.ready = 0;
- spin_lock_irqsave(&s->lock, flags);
- if (val == AFMT_S16_LE)
- s->sctrl |= SCTRL_P1SEB;
- else
- s->sctrl &= ~SCTRL_P1SEB;
- outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL);
- spin_unlock_irqrestore(&s->lock, flags);
- }
- return put_user((s->sctrl & SCTRL_P1SEB) ? AFMT_S16_LE : AFMT_U8, p);
-
- case SNDCTL_DSP_POST:
- return 0;
-
- case SNDCTL_DSP_GETTRIGGER:
- return put_user((s->ctrl & CTRL_DAC1_EN) ? PCM_ENABLE_OUTPUT : 0, p);
-
- case SNDCTL_DSP_SETTRIGGER:
- if (get_user(val, p))
- return -EFAULT;
- if (val & PCM_ENABLE_OUTPUT) {
- if (!s->dma_dac1.ready && (ret = prog_dmabuf_dac1(s)))
- return ret;
- s->dma_dac1.enabled = 1;
- start_dac1(s);
- } else {
- s->dma_dac1.enabled = 0;
- stop_dac1(s);
- }
- return 0;
-
- case SNDCTL_DSP_GETOSPACE:
- if (!s->dma_dac1.ready && (val = prog_dmabuf_dac1(s)) != 0)
- return val;
- spin_lock_irqsave(&s->lock, flags);
- es1371_update_ptr(s);
- abinfo.fragsize = s->dma_dac1.fragsize;
- count = s->dma_dac1.count;
- if (count < 0)
- count = 0;
- abinfo.bytes = s->dma_dac1.dmasize - count;
- abinfo.fragstotal = s->dma_dac1.numfrag;
- abinfo.fragments = abinfo.bytes >> s->dma_dac1.fragshift;
- spin_unlock_irqrestore(&s->lock, flags);
- return copy_to_user((void __user *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
-
- case SNDCTL_DSP_NONBLOCK:
- file->f_flags |= O_NONBLOCK;
- return 0;
-
- case SNDCTL_DSP_GETODELAY:
- if (!s->dma_dac1.ready && (val = prog_dmabuf_dac1(s)) != 0)
- return val;
- spin_lock_irqsave(&s->lock, flags);
- es1371_update_ptr(s);
- count = s->dma_dac1.count;
- spin_unlock_irqrestore(&s->lock, flags);
- if (count < 0)
- count = 0;
- return put_user(count, p);
-
- case SNDCTL_DSP_GETOPTR:
- if (!s->dma_dac1.ready && (val = prog_dmabuf_dac1(s)) != 0)
- return val;
- spin_lock_irqsave(&s->lock, flags);
- es1371_update_ptr(s);
- cinfo.bytes = s->dma_dac1.total_bytes;
- count = s->dma_dac1.count;
- if (count < 0)
- count = 0;
- cinfo.blocks = count >> s->dma_dac1.fragshift;
- cinfo.ptr = s->dma_dac1.hwptr;
- if (s->dma_dac1.mapped)
- s->dma_dac1.count &= s->dma_dac1.fragsize-1;
- spin_unlock_irqrestore(&s->lock, flags);
- if (copy_to_user((void __user *)arg, &cinfo, sizeof(cinfo)))
- return -EFAULT;
- return 0;
-
- case SNDCTL_DSP_GETBLKSIZE:
- if ((val = prog_dmabuf_dac1(s)))
- return val;
- return put_user(s->dma_dac1.fragsize, p);
-
- case SNDCTL_DSP_SETFRAGMENT:
- if (get_user(val, p))
- return -EFAULT;
- s->dma_dac1.ossfragshift = val & 0xffff;
- s->dma_dac1.ossmaxfrags = (val >> 16) & 0xffff;
- if (s->dma_dac1.ossfragshift < 4)
- s->dma_dac1.ossfragshift = 4;
- if (s->dma_dac1.ossfragshift > 15)
- s->dma_dac1.ossfragshift = 15;
- if (s->dma_dac1.ossmaxfrags < 4)
- s->dma_dac1.ossmaxfrags = 4;
- return 0;
-
- case SNDCTL_DSP_SUBDIVIDE:
- if (s->dma_dac1.subdivision)
- return -EINVAL;
- if (get_user(val, p))
- return -EFAULT;
- if (val != 1 && val != 2 && val != 4)
- return -EINVAL;
- s->dma_dac1.subdivision = val;
- return 0;
-
- case SOUND_PCM_READ_RATE:
- return put_user(s->dac1rate, p);
-
- case SOUND_PCM_READ_CHANNELS:
- return put_user((s->sctrl & SCTRL_P1SMB) ? 2 : 1, p);
-
- case SOUND_PCM_READ_BITS:
- return put_user((s->sctrl & SCTRL_P1SEB) ? 16 : 8, p);
-
- case SOUND_PCM_WRITE_FILTER:
- case SNDCTL_DSP_SETSYNCRO:
- case SOUND_PCM_READ_FILTER:
- return -EINVAL;
-
- }
- return mixdev_ioctl(s->codec, cmd, arg);
-}
-
-static int es1371_open_dac(struct inode *inode, struct file *file)
-{
- int minor = iminor(inode);
- DECLARE_WAITQUEUE(wait, current);
- unsigned long flags;
- struct list_head *list;
- struct es1371_state *s;
-
- for (list = devs.next; ; list = list->next) {
- if (list == &devs)
- return -ENODEV;
- s = list_entry(list, struct es1371_state, devs);
- if (!((s->dev_dac ^ minor) & ~0xf))
- break;
- }
- VALIDATE_STATE(s);
- /* we allow opening with O_RDWR, most programs do it although they will only write */
-#if 0
- if (file->f_mode & FMODE_READ)
- return -EPERM;
-#endif
- if (!(file->f_mode & FMODE_WRITE))
- return -EINVAL;
- file->private_data = s;
- /* wait for device to become free */
- mutex_lock(&s->open_mutex);
- while (s->open_mode & FMODE_DAC) {
- if (file->f_flags & O_NONBLOCK) {
- mutex_unlock(&s->open_mutex);
- return -EBUSY;
- }
- add_wait_queue(&s->open_wait, &wait);
- __set_current_state(TASK_INTERRUPTIBLE);
- mutex_unlock(&s->open_mutex);
- schedule();
- remove_wait_queue(&s->open_wait, &wait);
- set_current_state(TASK_RUNNING);
- if (signal_pending(current))
- return -ERESTARTSYS;
- mutex_lock(&s->open_mutex);
- }
- s->dma_dac1.ossfragshift = s->dma_dac1.ossmaxfrags = s->dma_dac1.subdivision = 0;
- s->dma_dac1.enabled = 1;
- set_dac1_rate(s, 8000);
- spin_lock_irqsave(&s->lock, flags);
- s->sctrl &= ~SCTRL_P1FMT;
- if ((minor & 0xf) == SND_DEV_DSP16)
- s->sctrl |= ES1371_FMT_S16_MONO << SCTRL_SH_P1FMT;
- else
- s->sctrl |= ES1371_FMT_U8_MONO << SCTRL_SH_P1FMT;
- outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL);
- spin_unlock_irqrestore(&s->lock, flags);
- s->open_mode |= FMODE_DAC;
- mutex_unlock(&s->open_mutex);
- return nonseekable_open(inode, file);
-}
-
-static int es1371_release_dac(struct inode *inode, struct file *file)
-{
- struct es1371_state *s = (struct es1371_state *)file->private_data;
-
- VALIDATE_STATE(s);
- lock_kernel();
- drain_dac1(s, file->f_flags & O_NONBLOCK);
- mutex_lock(&s->open_mutex);
- stop_dac1(s);
- dealloc_dmabuf(s, &s->dma_dac1);
- s->open_mode &= ~FMODE_DAC;
- mutex_unlock(&s->open_mutex);
- wake_up(&s->open_wait);
- unlock_kernel();
- return 0;
-}
-
-static /*const*/ struct file_operations es1371_dac_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .write = es1371_write_dac,
- .poll = es1371_poll_dac,
- .ioctl = es1371_ioctl_dac,
- .mmap = es1371_mmap_dac,
- .open = es1371_open_dac,
- .release = es1371_release_dac,
-};
-
-/* --------------------------------------------------------------------- */
-
-static ssize_t es1371_midi_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
-{
- struct es1371_state *s = (struct es1371_state *)file->private_data;
- DECLARE_WAITQUEUE(wait, current);
- ssize_t ret;
- unsigned long flags;
- unsigned ptr;
- int cnt;
-
- VALIDATE_STATE(s);
- if (!access_ok(VERIFY_WRITE, buffer, count))
- return -EFAULT;
- if (count == 0)
- return 0;
- ret = 0;
- add_wait_queue(&s->midi.iwait, &wait);
- while (count > 0) {
- spin_lock_irqsave(&s->lock, flags);
- ptr = s->midi.ird;
- cnt = MIDIINBUF - ptr;
- if (s->midi.icnt < cnt)
- cnt = s->midi.icnt;
- if (cnt <= 0)
- __set_current_state(TASK_INTERRUPTIBLE);
- spin_unlock_irqrestore(&s->lock, flags);
- if (cnt > count)
- cnt = count;
- if (cnt <= 0) {
- if (file->f_flags & O_NONBLOCK) {
- if (!ret)
- ret = -EAGAIN;
- break;
- }
- schedule();
- if (signal_pending(current)) {
- if (!ret)
- ret = -ERESTARTSYS;
- break;
- }
- continue;
- }
- if (copy_to_user(buffer, s->midi.ibuf + ptr, cnt)) {
- if (!ret)
- ret = -EFAULT;
- break;
- }
- ptr = (ptr + cnt) % MIDIINBUF;
- spin_lock_irqsave(&s->lock, flags);
- s->midi.ird = ptr;
- s->midi.icnt -= cnt;
- spin_unlock_irqrestore(&s->lock, flags);
- count -= cnt;
- buffer += cnt;
- ret += cnt;
- break;
- }
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(&s->midi.iwait, &wait);
- return ret;
-}
-
-static ssize_t es1371_midi_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
-{
- struct es1371_state *s = (struct es1371_state *)file->private_data;
- DECLARE_WAITQUEUE(wait, current);
- ssize_t ret;
- unsigned long flags;
- unsigned ptr;
- int cnt;
-
- VALIDATE_STATE(s);
- if (!access_ok(VERIFY_READ, buffer, count))
- return -EFAULT;
- if (count == 0)
- return 0;
- ret = 0;
- add_wait_queue(&s->midi.owait, &wait);
- while (count > 0) {
- spin_lock_irqsave(&s->lock, flags);
- ptr = s->midi.owr;
- cnt = MIDIOUTBUF - ptr;
- if (s->midi.ocnt + cnt > MIDIOUTBUF)
- cnt = MIDIOUTBUF - s->midi.ocnt;
- if (cnt <= 0) {
- __set_current_state(TASK_INTERRUPTIBLE);
- es1371_handle_midi(s);
- }
- spin_unlock_irqrestore(&s->lock, flags);
- if (cnt > count)
- cnt = count;
- if (cnt <= 0) {
- if (file->f_flags & O_NONBLOCK) {
- if (!ret)
- ret = -EAGAIN;
- break;
- }
- schedule();
- if (signal_pending(current)) {
- if (!ret)
- ret = -ERESTARTSYS;
- break;
- }
- continue;
- }
- if (copy_from_user(s->midi.obuf + ptr, buffer, cnt)) {
- if (!ret)
- ret = -EFAULT;
- break;
- }
- ptr = (ptr + cnt) % MIDIOUTBUF;
- spin_lock_irqsave(&s->lock, flags);
- s->midi.owr = ptr;
- s->midi.ocnt += cnt;
- spin_unlock_irqrestore(&s->lock, flags);
- count -= cnt;
- buffer += cnt;
- ret += cnt;
- spin_lock_irqsave(&s->lock, flags);
- es1371_handle_midi(s);
- spin_unlock_irqrestore(&s->lock, flags);
- }
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(&s->midi.owait, &wait);
- return ret;
-}
-
-/* No kernel lock - we have our own spinlock */
-static unsigned int es1371_midi_poll(struct file *file, struct poll_table_struct *wait)
-{
- struct es1371_state *s = (struct es1371_state *)file->private_data;
- unsigned long flags;
- unsigned int mask = 0;
-
- VALIDATE_STATE(s);
- if (file->f_mode & FMODE_WRITE)
- poll_wait(file, &s->midi.owait, wait);
- if (file->f_mode & FMODE_READ)
- poll_wait(file, &s->midi.iwait, wait);
- spin_lock_irqsave(&s->lock, flags);
- if (file->f_mode & FMODE_READ) {
- if (s->midi.icnt > 0)
- mask |= POLLIN | POLLRDNORM;
- }
- if (file->f_mode & FMODE_WRITE) {
- if (s->midi.ocnt < MIDIOUTBUF)
- mask |= POLLOUT | POLLWRNORM;
- }
- spin_unlock_irqrestore(&s->lock, flags);
- return mask;
-}
-
-static int es1371_midi_open(struct inode *inode, struct file *file)
-{
- int minor = iminor(inode);
- DECLARE_WAITQUEUE(wait, current);
- unsigned long flags;
- struct list_head *list;
- struct es1371_state *s;
-
- for (list = devs.next; ; list = list->next) {
- if (list == &devs)
- return -ENODEV;
- s = list_entry(list, struct es1371_state, devs);
- if (s->dev_midi == minor)
- break;
- }
- VALIDATE_STATE(s);
- file->private_data = s;
- /* wait for device to become free */
- mutex_lock(&s->open_mutex);
- while (s->open_mode & (file->f_mode << FMODE_MIDI_SHIFT)) {
- if (file->f_flags & O_NONBLOCK) {
- mutex_unlock(&s->open_mutex);
- return -EBUSY;
- }
- add_wait_queue(&s->open_wait, &wait);
- __set_current_state(TASK_INTERRUPTIBLE);
- mutex_unlock(&s->open_mutex);
- schedule();
- remove_wait_queue(&s->open_wait, &wait);
- set_current_state(TASK_RUNNING);
- if (signal_pending(current))
- return -ERESTARTSYS;
- mutex_lock(&s->open_mutex);
- }
- spin_lock_irqsave(&s->lock, flags);
- if (!(s->open_mode & (FMODE_MIDI_READ | FMODE_MIDI_WRITE))) {
- s->midi.ird = s->midi.iwr = s->midi.icnt = 0;
- s->midi.ord = s->midi.owr = s->midi.ocnt = 0;
- outb(UCTRL_CNTRL_SWR, s->io+ES1371_REG_UART_CONTROL);
- outb(0, s->io+ES1371_REG_UART_CONTROL);
- outb(0, s->io+ES1371_REG_UART_TEST);
- }
- if (file->f_mode & FMODE_READ) {
- s->midi.ird = s->midi.iwr = s->midi.icnt = 0;
- }
- if (file->f_mode & FMODE_WRITE) {
- s->midi.ord = s->midi.owr = s->midi.ocnt = 0;
- }
- s->ctrl |= CTRL_UART_EN;
- outl(s->ctrl, s->io+ES1371_REG_CONTROL);
- es1371_handle_midi(s);
- spin_unlock_irqrestore(&s->lock, flags);
- s->open_mode |= (file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | FMODE_MIDI_WRITE);
- mutex_unlock(&s->open_mutex);
- return nonseekable_open(inode, file);
-}
-
-static int es1371_midi_release(struct inode *inode, struct file *file)
-{
- struct es1371_state *s = (struct es1371_state *)file->private_data;
- DECLARE_WAITQUEUE(wait, current);
- unsigned long flags;
- unsigned count, tmo;
-
- VALIDATE_STATE(s);
- lock_kernel();
- if (file->f_mode & FMODE_WRITE) {
- add_wait_queue(&s->midi.owait, &wait);
- for (;;) {
- __set_current_state(TASK_INTERRUPTIBLE);
- spin_lock_irqsave(&s->lock, flags);
- count = s->midi.ocnt;
- spin_unlock_irqrestore(&s->lock, flags);
- if (count <= 0)
- break;
- if (signal_pending(current))
- break;
- if (file->f_flags & O_NONBLOCK)
- break;
- tmo = (count * HZ) / 3100;
- if (!schedule_timeout(tmo ? : 1) && tmo)
- printk(KERN_DEBUG PFX "midi timed out??\n");
- }
- remove_wait_queue(&s->midi.owait, &wait);
- set_current_state(TASK_RUNNING);
- }
- mutex_lock(&s->open_mutex);
- s->open_mode &= ~((file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ|FMODE_MIDI_WRITE));
- spin_lock_irqsave(&s->lock, flags);
- if (!(s->open_mode & (FMODE_MIDI_READ | FMODE_MIDI_WRITE))) {
- s->ctrl &= ~CTRL_UART_EN;
- outl(s->ctrl, s->io+ES1371_REG_CONTROL);
- }
- spin_unlock_irqrestore(&s->lock, flags);
- mutex_unlock(&s->open_mutex);
- wake_up(&s->open_wait);
- unlock_kernel();
- return 0;
-}
-
-static /*const*/ struct file_operations es1371_midi_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .read = es1371_midi_read,
- .write = es1371_midi_write,
- .poll = es1371_midi_poll,
- .open = es1371_midi_open,
- .release = es1371_midi_release,
-};
-
-/* --------------------------------------------------------------------- */
-
-/*
- * for debugging purposes, we'll create a proc device that dumps the
- * CODEC chipstate
- */
-
-#ifdef ES1371_DEBUG
-static int proc_es1371_dump (char *buf, char **start, off_t fpos, int length, int *eof, void *data)
-{
- struct es1371_state *s;
- int cnt, len = 0;
-
- if (list_empty(&devs))
- return 0;
- s = list_entry(devs.next, struct es1371_state, devs);
- /* print out header */
- len += sprintf(buf + len, "\t\tCreative ES137x Debug Dump-o-matic\n");
-
- /* print out CODEC state */
- len += sprintf (buf + len, "AC97 CODEC state\n");
- for (cnt=0; cnt <= 0x7e; cnt = cnt +2)
- len+= sprintf (buf + len, "reg:0x%02x val:0x%04x\n", cnt, rdcodec(s->codec, cnt));
-
- if (fpos >=len){
- *start = buf;
- *eof =1;
- return 0;
- }
- *start = buf + fpos;
- if ((len -= fpos) > length)
- return length;
- *eof =1;
- return len;
-
-}
-#endif /* ES1371_DEBUG */
-
-/* --------------------------------------------------------------------- */
-
-/* maximum number of devices; only used for command line params */
-#define NR_DEVICE 5
-
-static int spdif[NR_DEVICE];
-static int nomix[NR_DEVICE];
-static int amplifier[NR_DEVICE];
-
-static unsigned int devindex;
-
-module_param_array(spdif, bool, NULL, 0);
-MODULE_PARM_DESC(spdif, "if 1 the output is in S/PDIF digital mode");
-module_param_array(nomix, bool, NULL, 0);
-MODULE_PARM_DESC(nomix, "if 1 no analog audio is mixed to the digital output");
-module_param_array(amplifier, bool, NULL, 0);
-MODULE_PARM_DESC(amplifier, "Set to 1 if the machine needs the amp control enabling (many laptops)");
-
-MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
-MODULE_DESCRIPTION("ES1371 AudioPCI97 Driver");
-MODULE_LICENSE("GPL");
-
-
-/* --------------------------------------------------------------------- */
-
-static struct initvol {
- int mixch;
- int vol;
-} initvol[] __devinitdata = {
- { SOUND_MIXER_WRITE_LINE, 0x4040 },
- { SOUND_MIXER_WRITE_CD, 0x4040 },
- { MIXER_WRITE(SOUND_MIXER_VIDEO), 0x4040 },
- { SOUND_MIXER_WRITE_LINE1, 0x4040 },
- { SOUND_MIXER_WRITE_PCM, 0x4040 },
- { SOUND_MIXER_WRITE_VOLUME, 0x4040 },
- { MIXER_WRITE(SOUND_MIXER_PHONEOUT), 0x4040 },
- { SOUND_MIXER_WRITE_OGAIN, 0x4040 },
- { MIXER_WRITE(SOUND_MIXER_PHONEIN), 0x4040 },
- { SOUND_MIXER_WRITE_SPEAKER, 0x4040 },
- { SOUND_MIXER_WRITE_MIC, 0x4040 },
- { SOUND_MIXER_WRITE_RECLEV, 0x4040 },
- { SOUND_MIXER_WRITE_IGAIN, 0x4040 }
-};
-
-static struct
-{
- short svid, sdid;
-} amplifier_needed[] =
-{
- { 0x107B, 0x2150 }, /* Gateway Solo 2150 */
- { 0x13BD, 0x100C }, /* Mebius PC-MJ100V */
- { 0x1102, 0x5938 }, /* Targa Xtender 300 */
- { 0x1102, 0x8938 }, /* IPC notebook */
- { PCI_ANY_ID, PCI_ANY_ID }
-};
-
-#ifdef SUPPORT_JOYSTICK
-
-static int __devinit es1371_register_gameport(struct es1371_state *s)
-{
- struct gameport *gp;
- int gpio;
-
- for (gpio = 0x218; gpio >= 0x200; gpio -= 0x08)
- if (request_region(gpio, JOY_EXTENT, "es1371"))
- break;
-
- if (gpio < 0x200) {
- printk(KERN_ERR PFX "no free joystick address found\n");
- return -EBUSY;
- }
-
- s->gameport = gp = gameport_allocate_port();
- if (!gp) {
- printk(KERN_ERR PFX "can not allocate memory for gameport\n");
- release_region(gpio, JOY_EXTENT);
- return -ENOMEM;
- }
-
- gameport_set_name(gp, "ESS1371 Gameport");
- gameport_set_phys(gp, "isa%04x/gameport0", gpio);
- gp->dev.parent = &s->dev->dev;
- gp->io = gpio;
-
- s->ctrl |= CTRL_JYSTK_EN | (((gpio >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT);
- outl(s->ctrl, s->io + ES1371_REG_CONTROL);
-
- gameport_register_port(gp);
-
- return 0;
-}
-
-static inline void es1371_unregister_gameport(struct es1371_state *s)
-{
- if (s->gameport) {
- int gpio = s->gameport->io;
- gameport_unregister_port(s->gameport);
- release_region(gpio, JOY_EXTENT);
-
- }
-}
-
-#else
-static inline int es1371_register_gameport(struct es1371_state *s) { return -ENOSYS; }
-static inline void es1371_unregister_gameport(struct es1371_state *s) { }
-#endif /* SUPPORT_JOYSTICK */
-
-
-static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid)
-{
- struct es1371_state *s;
- mm_segment_t fs;
- int i, val, res = -1;
- int idx;
- unsigned long tmo;
- signed long tmo2;
- unsigned int cssr;
-
- if ((res=pci_enable_device(pcidev)))
- return res;
-
- if (!(pci_resource_flags(pcidev, 0) & IORESOURCE_IO))
- return -ENODEV;
- if (pcidev->irq == 0)
- return -ENODEV;
- i = pci_set_dma_mask(pcidev, DMA_32BIT_MASK);
- if (i) {
- printk(KERN_WARNING "es1371: architecture does not support 32bit PCI busmaster DMA\n");
- return i;
- }
- if (!(s = kzalloc(sizeof(struct es1371_state), GFP_KERNEL))) {
- printk(KERN_WARNING PFX "out of memory\n");
- return -ENOMEM;
- }
-
- s->codec = ac97_alloc_codec();
- if(s->codec == NULL)
- goto err_codec;
-
- init_waitqueue_head(&s->dma_adc.wait);
- init_waitqueue_head(&s->dma_dac1.wait);
- init_waitqueue_head(&s->dma_dac2.wait);
- init_waitqueue_head(&s->open_wait);
- init_waitqueue_head(&s->midi.iwait);
- init_waitqueue_head(&s->midi.owait);
- mutex_init(&s->open_mutex);
- spin_lock_init(&s->lock);
- s->magic = ES1371_MAGIC;
- s->dev = pcidev;
- s->io = pci_resource_start(pcidev, 0);
- s->irq = pcidev->irq;
- s->vendor = pcidev->vendor;
- s->device = pcidev->device;
- s->rev = pcidev->revision;
- s->codec->private_data = s;
- s->codec->id = 0;
- s->codec->codec_read = rdcodec;
- s->codec->codec_write = wrcodec;
- printk(KERN_INFO PFX "found chip, vendor id 0x%04x device id 0x%04x revision 0x%02x\n",
- s->vendor, s->device, s->rev);
- if (!request_region(s->io, ES1371_EXTENT, "es1371")) {
- printk(KERN_ERR PFX "io ports %#lx-%#lx in use\n", s->io, s->io+ES1371_EXTENT-1);
- res = -EBUSY;
- goto err_region;
- }
- if ((res=request_irq(s->irq, es1371_interrupt, IRQF_SHARED, "es1371",s))) {
- printk(KERN_ERR PFX "irq %u in use\n", s->irq);
- goto err_irq;
- }
- printk(KERN_INFO PFX "found es1371 rev %d at io %#lx irq %u\n",
- s->rev, s->io, s->irq);
- /* register devices */
- if ((res=(s->dev_audio = register_sound_dsp(&es1371_audio_fops,-1)))<0)
- goto err_dev1;
- if ((res=(s->codec->dev_mixer = register_sound_mixer(&es1371_mixer_fops, -1))) < 0)
- goto err_dev2;
- if ((res=(s->dev_dac = register_sound_dsp(&es1371_dac_fops, -1))) < 0)
- goto err_dev3;
- if ((res=(s->dev_midi = register_sound_midi(&es1371_midi_fops, -1)))<0 )
- goto err_dev4;
-#ifdef ES1371_DEBUG
- /* initialize the debug proc device */
- s->ps = create_proc_read_entry("es1371",0,NULL,proc_es1371_dump,NULL);
-#endif /* ES1371_DEBUG */
-
- /* initialize codec registers */
- s->ctrl = 0;
-
- /* Check amplifier requirements */
-
- if (amplifier[devindex])
- s->ctrl |= CTRL_GPIO_OUT0;
- else for(idx = 0; amplifier_needed[idx].svid != PCI_ANY_ID; idx++)
- {
- if(pcidev->subsystem_vendor == amplifier_needed[idx].svid &&
- pcidev->subsystem_device == amplifier_needed[idx].sdid)
- {
- s->ctrl |= CTRL_GPIO_OUT0; /* turn internal amplifier on */
- printk(KERN_INFO PFX "Enabling internal amplifier.\n");
- }
- }
-
- s->sctrl = 0;
- cssr = 0;
- s->spdif_volume = -1;
- /* check to see if s/pdif mode is being requested */
- if (spdif[devindex]) {
- if (s->rev >= 4) {
- printk(KERN_INFO PFX "enabling S/PDIF output\n");
- s->spdif_volume = 0;
- cssr |= STAT_EN_SPDIF;
- s->ctrl |= CTRL_SPDIFEN_B;
- if (nomix[devindex]) /* don't mix analog inputs to s/pdif output */
- s->ctrl |= CTRL_RECEN_B;
- } else {
- printk(KERN_ERR PFX "revision %d does not support S/PDIF\n", s->rev);
- }
- }
- /* initialize the chips */
- outl(s->ctrl, s->io+ES1371_REG_CONTROL);
- outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL);
- outl(LEGACY_JFAST, s->io+ES1371_REG_LEGACY);
- pci_set_master(pcidev); /* enable bus mastering */
- /* if we are a 5880 turn on the AC97 */
- if (s->vendor == PCI_VENDOR_ID_ENSONIQ &&
- ((s->device == PCI_DEVICE_ID_ENSONIQ_CT5880 && s->rev >= CT5880REV_CT5880_C) ||
- (s->device == PCI_DEVICE_ID_ENSONIQ_ES1371 && s->rev == ES1371REV_CT5880_A) ||
- (s->device == PCI_DEVICE_ID_ENSONIQ_ES1371 && s->rev == ES1371REV_ES1373_8))) {
- cssr |= CSTAT_5880_AC97_RST;
- outl(cssr, s->io+ES1371_REG_STATUS);
- /* need to delay around 20ms(bleech) to give
- some CODECs enough time to wakeup */
- tmo = jiffies + (HZ / 50) + 1;
- for (;;) {
- tmo2 = tmo - jiffies;
- if (tmo2 <= 0)
- break;
- schedule_timeout(tmo2);
- }
- }
- /* AC97 warm reset to start the bitclk */
- outl(s->ctrl | CTRL_SYNCRES, s->io+ES1371_REG_CONTROL);
- udelay(2);
- outl(s->ctrl, s->io+ES1371_REG_CONTROL);
- /* init the sample rate converter */
- src_init(s);
- /* codec init */
- if (!ac97_probe_codec(s->codec)) {
- res = -ENODEV;
- goto err_gp;
- }
- /* set default values */
-
- fs = get_fs();
- set_fs(KERNEL_DS);
- val = SOUND_MASK_LINE;
- mixdev_ioctl(s->codec, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val);
- for (i = 0; i < ARRAY_SIZE(initvol); i++) {
- val = initvol[i].vol;
- mixdev_ioctl(s->codec, initvol[i].mixch, (unsigned long)&val);
- }
- /* mute master and PCM when in S/PDIF mode */
- if (s->spdif_volume != -1) {
- val = 0x0000;
- s->codec->mixer_ioctl(s->codec, SOUND_MIXER_WRITE_VOLUME, (unsigned long)&val);
- s->codec->mixer_ioctl(s->codec, SOUND_MIXER_WRITE_PCM, (unsigned long)&val);
- }
- set_fs(fs);
- /* turn on S/PDIF output driver if requested */
- outl(cssr, s->io+ES1371_REG_STATUS);
-
- es1371_register_gameport(s);
-
- /* store it in the driver field */
- pci_set_drvdata(pcidev, s);
- /* put it into driver list */
- list_add_tail(&s->devs, &devs);
- /* increment devindex */
- if (devindex < NR_DEVICE-1)
- devindex++;
- return 0;
-
- err_gp:
-#ifdef ES1371_DEBUG
- if (s->ps)
- remove_proc_entry("es1371", NULL);
-#endif
- unregister_sound_midi(s->dev_midi);
- err_dev4:
- unregister_sound_dsp(s->dev_dac);
- err_dev3:
- unregister_sound_mixer(s->codec->dev_mixer);
- err_dev2:
- unregister_sound_dsp(s->dev_audio);
- err_dev1:
- printk(KERN_ERR PFX "cannot register misc device\n");
- free_irq(s->irq, s);
- err_irq:
- release_region(s->io, ES1371_EXTENT);
- err_region:
- err_codec:
- ac97_release_codec(s->codec);
- kfree(s);
- return res;
-}
-
-static void __devexit es1371_remove(struct pci_dev *dev)
-{
- struct es1371_state *s = pci_get_drvdata(dev);
-
- if (!s)
- return;
- list_del(&s->devs);
-#ifdef ES1371_DEBUG
- if (s->ps)
- remove_proc_entry("es1371", NULL);
-#endif /* ES1371_DEBUG */
- outl(0, s->io+ES1371_REG_CONTROL); /* switch everything off */
- outl(0, s->io+ES1371_REG_SERIAL_CONTROL); /* clear serial interrupts */
- synchronize_irq(s->irq);
- free_irq(s->irq, s);
- es1371_unregister_gameport(s);
- release_region(s->io, ES1371_EXTENT);
- unregister_sound_dsp(s->dev_audio);
- unregister_sound_mixer(s->codec->dev_mixer);
- unregister_sound_dsp(s->dev_dac);
- unregister_sound_midi(s->dev_midi);
- ac97_release_codec(s->codec);
- kfree(s);
- pci_set_drvdata(dev, NULL);
-}
-
-static struct pci_device_id id_table[] = {
- { PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1371, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
- { PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_CT5880, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
- { PCI_VENDOR_ID_ECTIVA, PCI_DEVICE_ID_ECTIVA_EV1938, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
- { 0, }
-};
-
-MODULE_DEVICE_TABLE(pci, id_table);
-
-static struct pci_driver es1371_driver = {
- .name = "es1371",
- .id_table = id_table,
- .probe = es1371_probe,
- .remove = __devexit_p(es1371_remove),
-};
-
-static int __init init_es1371(void)
-{
- printk(KERN_INFO PFX "version v0.32 time " __TIME__ " " __DATE__ "\n");
- return pci_register_driver(&es1371_driver);
-}
-
-static void __exit cleanup_es1371(void)
-{
- printk(KERN_INFO PFX "unloading\n");
- pci_unregister_driver(&es1371_driver);
-}
-
-module_init(init_es1371);
-module_exit(cleanup_es1371);
-
-/* --------------------------------------------------------------------- */
-
-#ifndef MODULE
-
-/* format is: es1371=[spdif,[nomix,[amplifier]]] */
-
-static int __init es1371_setup(char *str)
-{
- static unsigned __initdata nr_dev = 0;
-
- if (nr_dev >= NR_DEVICE)
- return 0;
-
- (void)
- ((get_option(&str, &spdif[nr_dev]) == 2)
- && (get_option(&str, &nomix[nr_dev]) == 2)
- && (get_option(&str, &amplifier[nr_dev])));
-
- nr_dev++;
- return 1;
-}
-
-__setup("es1371=", es1371_setup);
-
-#endif /* MODULE */
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index c6b44102aa5b..356bf21a1506 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -170,14 +170,14 @@ config SND_CA0106
will be called snd-ca0106.
config SND_CMIPCI
- tristate "C-Media 8738, 8338"
+ tristate "C-Media 8338, 8738, 8768, 8770"
depends on SND
select SND_OPL3_LIB
select SND_MPU401_UART
select SND_PCM
help
- If you want to use soundcards based on C-Media CMI8338 or CMI8738
- chips, say Y here and read
+ If you want to use soundcards based on C-Media CMI8338, CMI8738,
+ CMI8768 or CMI8770 chips, say Y here and read
<file:Documentation/sound/alsa/CMIPCI.txt>.
To compile this driver as a module, choose M here: the module
@@ -500,6 +500,103 @@ config SND_HDA_INTEL
To compile this driver as a module, choose M here: the module
will be called snd-hda-intel.
+config SND_HDA_HWDEP
+ bool "Build hwdep interface for HD-audio driver"
+ depends on SND_HDA_INTEL
+ select SND_HWDEP
+ help
+ Say Y here to build a hwdep interface for HD-audio driver.
+ This interface can be used for out-of-band communication
+ with codecs for debugging purposes.
+
+config SND_HDA_CODEC_REALTEK
+ bool "Build Realtek HD-audio codec support"
+ depends on SND_HDA_INTEL
+ default y
+ help
+ Say Y here to include Realtek HD-audio codec support in
+ snd-hda-intel driver, such as ALC880.
+
+config SND_HDA_CODEC_ANALOG
+ bool "Build Analog Device HD-audio codec support"
+ depends on SND_HDA_INTEL
+ default y
+ help
+ Say Y here to include Analog Device HD-audio codec support in
+ snd-hda-intel driver, such as AD1986A.
+
+config SND_HDA_CODEC_SIGMATEL
+ bool "Build IDT/Sigmatel HD-audio codec support"
+ depends on SND_HDA_INTEL
+ default y
+ help
+ Say Y here to include IDT (Sigmatel) HD-audio codec support in
+ snd-hda-intel driver, such as STAC9200.
+
+config SND_HDA_CODEC_VIA
+ bool "Build VIA HD-audio codec support"
+ depends on SND_HDA_INTEL
+ default y
+ help
+ Say Y here to include VIA HD-audio codec support in
+ snd-hda-intel driver, such as VT1708.
+
+config SND_HDA_CODEC_ATIHDMI
+ bool "Build ATI HDMI HD-audio codec support"
+ depends on SND_HDA_INTEL
+ default y
+ help
+ Say Y here to include ATI HDMI HD-audio codec support in
+ snd-hda-intel driver, such as ATI RS600 HDMI.
+
+config SND_HDA_CODEC_CONEXANT
+ bool "Build Conexant HD-audio codec support"
+ depends on SND_HDA_INTEL
+ default y
+ help
+ Say Y here to include Conexant HD-audio codec support in
+ snd-hda-intel driver, such as CX20549.
+
+config SND_HDA_CODEC_CMEDIA
+ bool "Build C-Media HD-audio codec support"
+ depends on SND_HDA_INTEL
+ default y
+ help
+ Say Y here to include C-Media HD-audio codec support in
+ snd-hda-intel driver, such as CMI9880.
+
+config SND_HDA_CODEC_SI3054
+ bool "Build Silicon Labs 3054 HD-modem codec support"
+ depends on SND_HDA_INTEL
+ default y
+ help
+ Say Y here to include Silicon Labs 3054 HD-modem codec
+ (and compatibles) support in snd-hda-intel driver.
+
+config SND_HDA_GENERIC
+ bool "Enable generic HD-audio codec parser"
+ depends on SND_HDA_INTEL
+ default y
+ help
+ Say Y here to enable the generic HD-audio codec parser
+ in snd-hda-intel driver.
+
+config SND_HDA_POWER_SAVE
+ bool "Aggressive power-saving on HD-audio"
+ depends on SND_HDA_INTEL && EXPERIMENTAL
+ help
+ Say Y here to enable more aggressive power-saving mode on
+ HD-audio driver. The power-saving timeout can be configured
+ via power_save option or over sysfs on-the-fly.
+
+config SND_HDA_POWER_SAVE_DEFAULT
+ int "Default time-out for HD-audio power-save mode"
+ depends on SND_HDA_POWER_SAVE
+ default 0
+ help
+ The default time-out value in seconds for HD-audio automatic
+ power-save mode. 0 means to disable the power-save mode.
+
config SND_HDSP
tristate "RME Hammerfall DSP Audio"
depends on SND
@@ -799,4 +896,12 @@ config SND_AC97_POWER_SAVE
snd-ac97-codec driver. You can toggle it dynamically over
sysfs, too.
+config SND_AC97_POWER_SAVE_DEFAULT
+ int "Default time-out for AC97 power-save mode"
+ depends on SND_AC97_POWER_SAVE
+ default 0
+ help
+ The default time-out value in seconds for AC97 automatic
+ power-save mode. 0 means to disable the power-save mode.
+
endmenu
diff --git a/sound/pci/Makefile b/sound/pci/Makefile
index cd76e0293d06..09ddc82eeca2 100644
--- a/sound/pci/Makefile
+++ b/sound/pci/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
snd-ad1889-objs := ad1889.o
diff --git a/sound/pci/ac97/Makefile b/sound/pci/ac97/Makefile
index f5d471896b95..0be48b1a22d0 100644
--- a/sound/pci/ac97/Makefile
+++ b/sound/pci/ac97/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
snd-ac97-codec-objs := ac97_codec.o ac97_pcm.o
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index bbed644bf9c5..6a9966df0cc9 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Universal interface for Audio Codec '97
*
* For more details look to AC '97 component specification revision 2.2
@@ -39,7 +39,7 @@
#include "ac97_patch.c"
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Universal interface for Audio Codec '97");
MODULE_LICENSE("GPL");
@@ -49,7 +49,7 @@ module_param(enable_loopback, bool, 0444);
MODULE_PARM_DESC(enable_loopback, "Enable AC97 ADC/DAC Loopback Control");
#ifdef CONFIG_SND_AC97_POWER_SAVE
-static int power_save;
+static int power_save = CONFIG_SND_AC97_POWER_SAVE_DEFAULT;
module_param(power_save, bool, 0644);
MODULE_PARM_DESC(power_save, "Enable AC97 power-saving control");
#endif
@@ -176,7 +176,7 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = {
{ 0x574d4C09, 0xffffffff, "WM9709", NULL, NULL},
{ 0x574d4C12, 0xffffffff, "WM9711,WM9712", patch_wolfson11, NULL},
{ 0x574d4c13, 0xffffffff, "WM9713,WM9714", patch_wolfson13, NULL, AC97_DEFAULT_POWER_OFF},
-{ 0x594d4800, 0xffffffff, "YMF743", NULL, NULL },
+{ 0x594d4800, 0xffffffff, "YMF743", patch_yamaha_ymf743, NULL },
{ 0x594d4802, 0xffffffff, "YMF752", NULL, NULL },
{ 0x594d4803, 0xffffffff, "YMF753", patch_yamaha_ymf753, NULL },
{ 0x83847600, 0xffffffff, "STAC9700,83,84", patch_sigmatel_stac9700, NULL },
@@ -779,6 +779,12 @@ static int snd_ac97_spdif_default_put(struct snd_kcontrol *kcontrol, struct snd_
change |= snd_ac97_update_bits_nolock(ac97, AC97_CXR_AUDIO_MISC,
AC97_CXR_SPDIF_MASK | AC97_CXR_COPYRGT,
v);
+ } else if (ac97->id == AC97_ID_YMF743) {
+ change |= snd_ac97_update_bits_nolock(ac97,
+ AC97_YMF7X3_DIT_CTRL,
+ 0xff38,
+ ((val << 4) & 0xff00) |
+ ((val << 2) & 0x0038));
} else {
unsigned short extst = snd_ac97_read_cache(ac97, AC97_EXTENDED_STATUS);
snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); /* turn off */
@@ -1375,7 +1381,8 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97)
for (idx = 0; idx < 2; idx++) {
if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_tone[idx], ac97))) < 0)
return err;
- if (ac97->id == AC97_ID_YMF753) {
+ if (ac97->id == AC97_ID_YMF743 ||
+ ac97->id == AC97_ID_YMF753) {
kctl->private_value &= ~(0xff << 16);
kctl->private_value |= 7 << 16;
}
@@ -2036,11 +2043,12 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template,
else {
udelay(50);
if (ac97->scaps & AC97_SCAP_SKIP_AUDIO)
- err = ac97_reset_wait(ac97, HZ/2, 1);
+ err = ac97_reset_wait(ac97, msecs_to_jiffies(500), 1);
else {
- err = ac97_reset_wait(ac97, HZ/2, 0);
+ err = ac97_reset_wait(ac97, msecs_to_jiffies(500), 0);
if (err < 0)
- err = ac97_reset_wait(ac97, HZ/2, 1);
+ err = ac97_reset_wait(ac97,
+ msecs_to_jiffies(500), 1);
}
if (err < 0) {
snd_printk(KERN_WARNING "AC'97 %d does not respond - RESET\n", ac97->num);
@@ -2104,7 +2112,7 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template,
}
/* nothing should be in powerdown mode */
snd_ac97_write_cache(ac97, AC97_GENERAL_PURPOSE, 0);
- end_time = jiffies + (HZ / 10);
+ end_time = jiffies + msecs_to_jiffies(100);
do {
if ((snd_ac97_read(ac97, AC97_POWERDOWN) & 0x0f) == 0x0f)
goto __ready_ok;
@@ -2136,7 +2144,7 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template,
udelay(100);
/* nothing should be in powerdown mode */
snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0);
- end_time = jiffies + (HZ / 10);
+ end_time = jiffies + msecs_to_jiffies(100);
do {
if ((snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS) & tmp) == tmp)
goto __ready_ok;
@@ -2354,7 +2362,8 @@ int snd_ac97_update_power(struct snd_ac97 *ac97, int reg, int powerup)
* (for avoiding loud click noises for many (OSS) apps
* that open/close frequently)
*/
- schedule_delayed_work(&ac97->power_work, HZ*2);
+ schedule_delayed_work(&ac97->power_work,
+ msecs_to_jiffies(2000));
else {
cancel_delayed_work(&ac97->power_work);
update_power_regs(ac97);
@@ -2436,7 +2445,7 @@ EXPORT_SYMBOL(snd_ac97_suspend);
/*
* restore ac97 status
*/
-void snd_ac97_restore_status(struct snd_ac97 *ac97)
+static void snd_ac97_restore_status(struct snd_ac97 *ac97)
{
int i;
@@ -2457,7 +2466,7 @@ void snd_ac97_restore_status(struct snd_ac97 *ac97)
/*
* restore IEC958 status
*/
-void snd_ac97_restore_iec958(struct snd_ac97 *ac97)
+static void snd_ac97_restore_iec958(struct snd_ac97 *ac97)
{
if (ac97->ext_id & AC97_EI_SPDIF) {
if (ac97->regs[AC97_EXTENDED_STATUS] & AC97_EA_SPDIF) {
@@ -2494,7 +2503,10 @@ void snd_ac97_resume(struct snd_ac97 *ac97)
snd_ac97_write(ac97, AC97_POWERDOWN, 0);
if (! (ac97->flags & AC97_DEFAULT_POWER_OFF)) {
- snd_ac97_write(ac97, AC97_RESET, 0);
+ if (!(ac97->scaps & AC97_SCAP_SKIP_AUDIO))
+ snd_ac97_write(ac97, AC97_RESET, 0);
+ else if (!(ac97->scaps & AC97_SCAP_SKIP_MODEM))
+ snd_ac97_write(ac97, AC97_EXTENDED_MID, 0);
udelay(100);
snd_ac97_write(ac97, AC97_POWERDOWN, 0);
}
diff --git a/sound/pci/ac97/ac97_id.h b/sound/pci/ac97/ac97_id.h
index 6d73514dc49e..c129492c82b3 100644
--- a/sound/pci/ac97/ac97_id.h
+++ b/sound/pci/ac97/ac97_id.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Universal interface for Audio Codec '97
*
* For more details look to AC '97 component specification revision 2.2
@@ -54,6 +54,7 @@
#define AC97_ID_ALC658 0x414c4780
#define AC97_ID_ALC658D 0x414c4781
#define AC97_ID_ALC850 0x414c4790
+#define AC97_ID_YMF743 0x594d4800
#define AC97_ID_YMF753 0x594d4803
#define AC97_ID_VT1616 0x49434551
#define AC97_ID_CM9738 0x434d4941
diff --git a/sound/pci/ac97/ac97_local.h b/sound/pci/ac97/ac97_local.h
index 78745c5c6df8..c276a5e3f7ac 100644
--- a/sound/pci/ac97/ac97_local.h
+++ b/sound/pci/ac97/ac97_local.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Universal interface for Audio Codec '97
*
* For more details look to AC '97 component specification revision 2.2
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
index 581ebba4d1a7..98c8b727b62b 100644
--- a/sound/pci/ac97/ac97_patch.c
+++ b/sound/pci/ac97/ac97_patch.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Universal interface for Audio Codec '97
*
* For more details look to AC '97 component specification revision 2.2
@@ -204,9 +204,13 @@ static inline int is_shared_micin(struct snd_ac97 *ac97)
/* The following snd_ac97_ymf753_... items added by David Shust (dshust@shustring.com) */
+/* Modified for YMF743 by Keita Maehara <maehara@debian.org> */
-/* It is possible to indicate to the Yamaha YMF753 the type of speakers being used. */
-static int snd_ac97_ymf753_info_speaker(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
+/* It is possible to indicate to the Yamaha YMF7x3 the type of
+ speakers being used. */
+
+static int snd_ac97_ymf7x3_info_speaker(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
static char *texts[3] = {
"Standard", "Small", "Smaller"
@@ -221,12 +225,13 @@ static int snd_ac97_ymf753_info_speaker(struct snd_kcontrol *kcontrol, struct sn
return 0;
}
-static int snd_ac97_ymf753_get_speaker(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int snd_ac97_ymf7x3_get_speaker(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
unsigned short val;
- val = ac97->regs[AC97_YMF753_3D_MODE_SEL];
+ val = ac97->regs[AC97_YMF7X3_3D_MODE_SEL];
val = (val >> 10) & 3;
if (val > 0) /* 0 = invalid */
val--;
@@ -234,7 +239,8 @@ static int snd_ac97_ymf753_get_speaker(struct snd_kcontrol *kcontrol, struct snd
return 0;
}
-static int snd_ac97_ymf753_put_speaker(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int snd_ac97_ymf7x3_put_speaker(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
unsigned short val;
@@ -242,20 +248,22 @@ static int snd_ac97_ymf753_put_speaker(struct snd_kcontrol *kcontrol, struct snd
if (ucontrol->value.enumerated.item[0] > 2)
return -EINVAL;
val = (ucontrol->value.enumerated.item[0] + 1) << 10;
- return snd_ac97_update(ac97, AC97_YMF753_3D_MODE_SEL, val);
+ return snd_ac97_update(ac97, AC97_YMF7X3_3D_MODE_SEL, val);
}
-static const struct snd_kcontrol_new snd_ac97_ymf753_controls_speaker =
+static const struct snd_kcontrol_new snd_ac97_ymf7x3_controls_speaker =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "3D Control - Speaker",
- .info = snd_ac97_ymf753_info_speaker,
- .get = snd_ac97_ymf753_get_speaker,
- .put = snd_ac97_ymf753_put_speaker,
+ .info = snd_ac97_ymf7x3_info_speaker,
+ .get = snd_ac97_ymf7x3_get_speaker,
+ .put = snd_ac97_ymf7x3_put_speaker,
};
-/* It is possible to indicate to the Yamaha YMF753 the source to direct to the S/PDIF output. */
-static int snd_ac97_ymf753_spdif_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
+/* It is possible to indicate to the Yamaha YMF7x3 the source to
+ direct to the S/PDIF output. */
+static int snd_ac97_ymf7x3_spdif_source_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
static char *texts[2] = { "AC-Link", "A/D Converter" };
@@ -268,17 +276,19 @@ static int snd_ac97_ymf753_spdif_source_info(struct snd_kcontrol *kcontrol, stru
return 0;
}
-static int snd_ac97_ymf753_spdif_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int snd_ac97_ymf7x3_spdif_source_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
unsigned short val;
- val = ac97->regs[AC97_YMF753_DIT_CTRL2];
+ val = ac97->regs[AC97_YMF7X3_DIT_CTRL];
ucontrol->value.enumerated.item[0] = (val >> 1) & 1;
return 0;
}
-static int snd_ac97_ymf753_spdif_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int snd_ac97_ymf7x3_spdif_source_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
unsigned short val;
@@ -286,7 +296,75 @@ static int snd_ac97_ymf753_spdif_source_put(struct snd_kcontrol *kcontrol, struc
if (ucontrol->value.enumerated.item[0] > 1)
return -EINVAL;
val = ucontrol->value.enumerated.item[0] << 1;
- return snd_ac97_update_bits(ac97, AC97_YMF753_DIT_CTRL2, 0x0002, val);
+ return snd_ac97_update_bits(ac97, AC97_YMF7X3_DIT_CTRL, 0x0002, val);
+}
+
+static int patch_yamaha_ymf7x3_3d(struct snd_ac97 *ac97)
+{
+ struct snd_kcontrol *kctl;
+ int err;
+
+ kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97);
+ err = snd_ctl_add(ac97->bus->card, kctl);
+ if (err < 0)
+ return err;
+ strcpy(kctl->id.name, "3D Control - Wide");
+ kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 9, 7, 0);
+ snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
+ err = snd_ctl_add(ac97->bus->card,
+ snd_ac97_cnew(&snd_ac97_ymf7x3_controls_speaker,
+ ac97));
+ if (err < 0)
+ return err;
+ snd_ac97_write_cache(ac97, AC97_YMF7X3_3D_MODE_SEL, 0x0c00);
+ return 0;
+}
+
+static const struct snd_kcontrol_new snd_ac97_yamaha_ymf743_controls_spdif[3] =
+{
+ AC97_SINGLE(SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH),
+ AC97_YMF7X3_DIT_CTRL, 0, 1, 0),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, NONE) "Source",
+ .info = snd_ac97_ymf7x3_spdif_source_info,
+ .get = snd_ac97_ymf7x3_spdif_source_get,
+ .put = snd_ac97_ymf7x3_spdif_source_put,
+ },
+ AC97_SINGLE(SNDRV_CTL_NAME_IEC958("", NONE, NONE) "Mute",
+ AC97_YMF7X3_DIT_CTRL, 2, 1, 1)
+};
+
+static int patch_yamaha_ymf743_build_spdif(struct snd_ac97 *ac97)
+{
+ int err;
+
+ err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3);
+ if (err < 0)
+ return err;
+ err = patch_build_controls(ac97,
+ snd_ac97_yamaha_ymf743_controls_spdif, 3);
+ if (err < 0)
+ return err;
+ /* set default PCM S/PDIF params */
+ /* PCM audio,no copyright,no preemphasis,PCM coder,original */
+ snd_ac97_write_cache(ac97, AC97_YMF7X3_DIT_CTRL, 0xa201);
+ return 0;
+}
+
+static struct snd_ac97_build_ops patch_yamaha_ymf743_ops = {
+ .build_spdif = patch_yamaha_ymf743_build_spdif,
+ .build_3d = patch_yamaha_ymf7x3_3d,
+};
+
+static int patch_yamaha_ymf743(struct snd_ac97 *ac97)
+{
+ ac97->build_ops = &patch_yamaha_ymf743_ops;
+ ac97->caps |= AC97_BC_BASS_TREBLE;
+ ac97->caps |= 0x04 << 10; /* Yamaha 3D enhancement */
+ ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
+ ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */
+ return 0;
}
/* The AC'97 spec states that the S/PDIF signal is to be output at pin 48.
@@ -311,7 +389,7 @@ static int snd_ac97_ymf753_spdif_output_pin_get(struct snd_kcontrol *kcontrol, s
struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
unsigned short val;
- val = ac97->regs[AC97_YMF753_DIT_CTRL2];
+ val = ac97->regs[AC97_YMF7X3_DIT_CTRL];
ucontrol->value.enumerated.item[0] = (val & 0x0008) ? 2 : (val & 0x0020) ? 1 : 0;
return 0;
}
@@ -325,7 +403,7 @@ static int snd_ac97_ymf753_spdif_output_pin_put(struct snd_kcontrol *kcontrol, s
return -EINVAL;
val = (ucontrol->value.enumerated.item[0] == 2) ? 0x0008 :
(ucontrol->value.enumerated.item[0] == 1) ? 0x0020 : 0;
- return snd_ac97_update_bits(ac97, AC97_YMF753_DIT_CTRL2, 0x0028, val);
+ return snd_ac97_update_bits(ac97, AC97_YMF7X3_DIT_CTRL, 0x0028, val);
/* The following can be used to direct S/PDIF output to pin 47 (EAPD).
snd_ac97_write_cache(ac97, 0x62, snd_ac97_read(ac97, 0x62) | 0x0008); */
}
@@ -334,9 +412,9 @@ static const struct snd_kcontrol_new snd_ac97_ymf753_controls_spdif[3] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
- .info = snd_ac97_ymf753_spdif_source_info,
- .get = snd_ac97_ymf753_spdif_source_get,
- .put = snd_ac97_ymf753_spdif_source_put,
+ .info = snd_ac97_ymf7x3_spdif_source_info,
+ .get = snd_ac97_ymf7x3_spdif_source_get,
+ .put = snd_ac97_ymf7x3_spdif_source_put,
},
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -345,25 +423,10 @@ static const struct snd_kcontrol_new snd_ac97_ymf753_controls_spdif[3] = {
.get = snd_ac97_ymf753_spdif_output_pin_get,
.put = snd_ac97_ymf753_spdif_output_pin_put,
},
- AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",NONE,NONE) "Mute", AC97_YMF753_DIT_CTRL2, 2, 1, 1)
+ AC97_SINGLE(SNDRV_CTL_NAME_IEC958("", NONE, NONE) "Mute",
+ AC97_YMF7X3_DIT_CTRL, 2, 1, 1)
};
-static int patch_yamaha_ymf753_3d(struct snd_ac97 * ac97)
-{
- struct snd_kcontrol *kctl;
- int err;
-
- if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
- return err;
- strcpy(kctl->id.name, "3D Control - Wide");
- kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 9, 7, 0);
- snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
- if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&snd_ac97_ymf753_controls_speaker, ac97))) < 0)
- return err;
- snd_ac97_write_cache(ac97, AC97_YMF753_3D_MODE_SEL, 0x0c00);
- return 0;
-}
-
static int patch_yamaha_ymf753_post_spdif(struct snd_ac97 * ac97)
{
int err;
@@ -374,7 +437,7 @@ static int patch_yamaha_ymf753_post_spdif(struct snd_ac97 * ac97)
}
static struct snd_ac97_build_ops patch_yamaha_ymf753_ops = {
- .build_3d = patch_yamaha_ymf753_3d,
+ .build_3d = patch_yamaha_ymf7x3_3d,
.build_post_spdif = patch_yamaha_ymf753_post_spdif
};
@@ -1880,14 +1943,7 @@ static int patch_ad1981b(struct snd_ac97 *ac97)
return 0;
}
-static int snd_ac97_ad1888_lohpsel_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_ac97_ad1888_lohpsel_info snd_ctl_boolean_mono_info
static int snd_ac97_ad1888_lohpsel_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -2186,15 +2242,7 @@ static int patch_ad1985(struct snd_ac97 * ac97)
return 0;
}
-static int snd_ac97_ad1986_bool_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_ac97_ad1986_bool_info snd_ctl_boolean_mono_info
static int snd_ac97_ad1986_lososel_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
diff --git a/sound/pci/ac97/ac97_patch.h b/sound/pci/ac97/ac97_patch.h
index fd341ce63762..9cccc27ea1b5 100644
--- a/sound/pci/ac97/ac97_patch.h
+++ b/sound/pci/ac97/ac97_patch.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Universal interface for Audio Codec '97
*
* For more details look to AC '97 component specification revision 2.2
diff --git a/sound/pci/ac97/ac97_pcm.c b/sound/pci/ac97/ac97_pcm.c
index 4281e6d0c5b6..8cbc03332b01 100644
--- a/sound/pci/ac97/ac97_pcm.c
+++ b/sound/pci/ac97/ac97_pcm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Universal interface for Audio Codec '97
*
* For more details look to AC '97 component specification revision 2.2
diff --git a/sound/pci/ac97/ac97_proc.c b/sound/pci/ac97/ac97_proc.c
index a3fdd7da911c..fed4a2c3d8a1 100644
--- a/sound/pci/ac97/ac97_proc.c
+++ b/sound/pci/ac97/ac97_proc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Universal interface for Audio Codec '97
*
* For more details look to AC '97 component specification revision 2.2
@@ -236,10 +236,14 @@ static void snd_ac97_proc_read_main(struct snd_ac97 *ac97, struct snd_info_buffe
val = snd_ac97_read(ac97, AC97_PCM_MIC_ADC_RATE);
snd_iprintf(buffer, "PCM MIC ADC : %iHz\n", val);
}
- if ((ext & AC97_EI_SPDIF) || (ac97->flags & AC97_CS_SPDIF)) {
+ if ((ext & AC97_EI_SPDIF) || (ac97->flags & AC97_CS_SPDIF) ||
+ (ac97->id == AC97_ID_YMF743)) {
if (ac97->flags & AC97_CS_SPDIF)
val = snd_ac97_read(ac97, AC97_CSR_SPDIF);
- else
+ else if (ac97->id == AC97_ID_YMF743) {
+ val = snd_ac97_read(ac97, AC97_YMF7X3_DIT_CTRL);
+ val = 0x2000 | (val & 0xff00) >> 4 | (val & 0x38) >> 2;
+ } else
val = snd_ac97_read(ac97, AC97_SPDIF);
snd_iprintf(buffer, "SPDIF Control :%s%s%s%s Category=0x%x Generation=%i%s%s%s\n",
diff --git a/sound/pci/ac97/ak4531_codec.c b/sound/pci/ac97/ak4531_codec.c
index dc26820a03a5..722de451d15f 100644
--- a/sound/pci/ac97/ak4531_codec.c
+++ b/sound/pci/ac97/ak4531_codec.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Universal routines for AK4531 codec
*
*
@@ -29,7 +29,7 @@
#include <sound/ak4531_codec.h>
#include <sound/tlv.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Universal routines for AK4531 codec");
MODULE_LICENSE("GPL");
diff --git a/sound/pci/ali5451/Makefile b/sound/pci/ali5451/Makefile
index 2e1831597474..713459c12d22 100644
--- a/sound/pci/ali5451/Makefile
+++ b/sound/pci/ali5451/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
snd-ali5451-objs := ali5451.o
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index 05b4c8696941..4c2bd7adf674 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -1804,15 +1804,7 @@ static int __devinit snd_ali_build_pcms(struct snd_ali *codec)
.info = snd_ali5451_spdif_info, .get = snd_ali5451_spdif_get, \
.put = snd_ali5451_spdif_put, .private_value = value}
-static int snd_ali5451_spdif_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_ali5451_spdif_info snd_ctl_boolean_mono_info
static int snd_ali5451_spdif_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c
index 8fb55d3b454b..1190ef366a41 100644
--- a/sound/pci/als4000.c
+++ b/sound/pci/als4000.c
@@ -1,7 +1,7 @@
/*
* card-als4000.c - driver for Avance Logic ALS4000 based soundcards.
* Copyright (C) 2000 by Bart Hartgers <bart@etpmod.phys.tue.nl>,
- * Jaroslav Kysela <perex@suse.cz>
+ * Jaroslav Kysela <perex@perex.cz>
* Copyright (C) 2002 by Andreas Mohr <hw7oshyuv3001@sneakemail.com>
*
* Framework borrowed from Massimo Piccioni's card-als100.c.
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
index 5ec1b6fcd548..26819e2f5761 100644
--- a/sound/pci/au88x0/au88x0.c
+++ b/sound/pci/au88x0/au88x0.c
@@ -191,7 +191,7 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
/* Init audio core.
* This must be done before we do request_irq otherwise we can get spurious
- * interupts that we do not handle properly and make a mess of things */
+ * interrupts that we do not handle properly and make a mess of things */
if ((err = vortex_core_init(chip)) != 0) {
printk(KERN_ERR "hw core init failed\n");
goto core_out;
@@ -232,6 +232,7 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
pci_disable_device(chip->pci_dev);
//FIXME: this not the right place to unregister the gameport
vortex_gameport_unregister(chip);
+ kfree(chip);
return err;
}
diff --git a/sound/pci/au88x0/au88x0_eq.c b/sound/pci/au88x0/au88x0_eq.c
index 0c86a31c4336..38602b85874d 100644
--- a/sound/pci/au88x0/au88x0_eq.c
+++ b/sound/pci/au88x0/au88x0_eq.c
@@ -728,15 +728,7 @@ static void vortex_Eqlzr_shutdown(vortex_t * vortex)
/* ALSA interface */
/* Control interface */
-static int
-snd_vortex_eqtoggle_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_vortex_eqtoggle_info snd_ctl_boolean_mono_info
static int
snd_vortex_eqtoggle_get(struct snd_kcontrol *kcontrol,
diff --git a/sound/pci/au88x0/au88x0_mpu401.c b/sound/pci/au88x0/au88x0_mpu401.c
index c75d368ea087..8db3d3e6f7bb 100644
--- a/sound/pci/au88x0/au88x0_mpu401.c
+++ b/sound/pci/au88x0/au88x0_mpu401.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Routines for control of MPU-401 in UART mode
*
* Modified for the Aureal Vortex based Soundcards
diff --git a/sound/pci/au88x0/au88x0_synth.c b/sound/pci/au88x0/au88x0_synth.c
index d3e662a1285d..978b856f5621 100644
--- a/sound/pci/au88x0/au88x0_synth.c
+++ b/sound/pci/au88x0/au88x0_synth.c
@@ -370,8 +370,8 @@ static void vortex_wt_SetFrequency(vortex_t * vortex, int wt, unsigned int sr)
while ((edx & 0x80000000) == 0) {
edx <<= 1;
eax--;
- if (eax == 0) ;
- break;
+ if (eax == 0)
+ break;
}
if (eax)
edx <<= 1;
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index 131952f55857..2dba752faf4e 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -147,15 +147,56 @@ MODULE_PARM_DESC(load_all, "Allow to load the non-whitelisted cards");
/* SYNC, one WRITE per line, one extra WRITE per page boundary, SYNC, JUMP */
#define MAX_RISC_SIZE ((1 + 255 + (PAGE_ALIGN(255 * 4092) / PAGE_SIZE - 1) + 1 + 1) * 8)
+/* Cards with configuration information */
+enum snd_bt87x_boardid {
+ SND_BT87X_BOARD_UNKNOWN,
+ SND_BT87X_BOARD_GENERIC, /* both an & dig interfaces, 32kHz */
+ SND_BT87X_BOARD_ANALOG, /* board with no external A/D */
+ SND_BT87X_BOARD_OSPREY2x0,
+ SND_BT87X_BOARD_OSPREY440,
+ SND_BT87X_BOARD_AVPHONE98,
+};
+
+/* Card configuration */
+struct snd_bt87x_board {
+ int dig_rate; /* Digital input sampling rate */
+ u32 digital_fmt; /* Register settings for digital input */
+ unsigned no_analog:1; /* No analog input */
+ unsigned no_digital:1; /* No digital input */
+};
+
+static __devinitdata struct snd_bt87x_board snd_bt87x_boards[] = {
+ [SND_BT87X_BOARD_UNKNOWN] = {
+ .dig_rate = 32000, /* just a guess */
+ },
+ [SND_BT87X_BOARD_GENERIC] = {
+ .dig_rate = 32000,
+ },
+ [SND_BT87X_BOARD_ANALOG] = {
+ .no_digital = 1,
+ },
+ [SND_BT87X_BOARD_OSPREY2x0] = {
+ .dig_rate = 44100,
+ .digital_fmt = CTL_DA_LRI | (1 << CTL_DA_LRD_SHIFT),
+ },
+ [SND_BT87X_BOARD_OSPREY440] = {
+ .dig_rate = 32000,
+ .digital_fmt = CTL_DA_LRI | (1 << CTL_DA_LRD_SHIFT),
+ .no_analog = 1,
+ },
+ [SND_BT87X_BOARD_AVPHONE98] = {
+ .dig_rate = 48000,
+ },
+};
+
struct snd_bt87x {
struct snd_card *card;
struct pci_dev *pci;
+ struct snd_bt87x_board board;
void __iomem *mmio;
int irq;
- int dig_rate;
-
spinlock_t reg_lock;
unsigned long opened;
struct snd_pcm_substream *substream;
@@ -340,30 +381,11 @@ static struct snd_pcm_hardware snd_bt87x_analog_hw = {
static int snd_bt87x_set_digital_hw(struct snd_bt87x *chip, struct snd_pcm_runtime *runtime)
{
- static struct {
- int rate;
- unsigned int bit;
- } ratebits[] = {
- {8000, SNDRV_PCM_RATE_8000},
- {11025, SNDRV_PCM_RATE_11025},
- {16000, SNDRV_PCM_RATE_16000},
- {22050, SNDRV_PCM_RATE_22050},
- {32000, SNDRV_PCM_RATE_32000},
- {44100, SNDRV_PCM_RATE_44100},
- {48000, SNDRV_PCM_RATE_48000}
- };
- int i;
-
- chip->reg_control |= CTL_DA_IOM_DA;
+ chip->reg_control |= CTL_DA_IOM_DA | CTL_A_PWRDN;
runtime->hw = snd_bt87x_digital_hw;
- runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
- for (i = 0; i < ARRAY_SIZE(ratebits); ++i)
- if (chip->dig_rate == ratebits[i].rate) {
- runtime->hw.rates = ratebits[i].bit;
- break;
- }
- runtime->hw.rate_min = chip->dig_rate;
- runtime->hw.rate_max = chip->dig_rate;
+ runtime->hw.rates = snd_pcm_rate_to_rate_bit(chip->board.dig_rate);
+ runtime->hw.rate_min = chip->board.dig_rate;
+ runtime->hw.rate_max = chip->board.dig_rate;
return 0;
}
@@ -380,7 +402,7 @@ static int snd_bt87x_set_analog_hw(struct snd_bt87x *chip, struct snd_pcm_runtim
.rats = &analog_clock
};
- chip->reg_control &= ~CTL_DA_IOM_DA;
+ chip->reg_control &= ~(CTL_DA_IOM_DA | CTL_A_PWRDN);
runtime->hw = snd_bt87x_analog_hw;
return snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
&constraint_rates);
@@ -419,6 +441,11 @@ static int snd_bt87x_close(struct snd_pcm_substream *substream)
{
struct snd_bt87x *chip = snd_pcm_substream_chip(substream);
+ spin_lock_irq(&chip->reg_lock);
+ chip->reg_control |= CTL_A_PWRDN;
+ snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control);
+ spin_unlock_irq(&chip->reg_lock);
+
chip->substream = NULL;
clear_bit(0, &chip->opened);
smp_mb__after_clear_bit();
@@ -569,15 +596,7 @@ static struct snd_kcontrol_new snd_bt87x_capture_volume = {
.put = snd_bt87x_capture_volume_put,
};
-static int snd_bt87x_capture_boost_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *info)
-{
- info->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- info->count = 1;
- info->value.integer.min = 0;
- info->value.integer.max = 1;
- return 0;
-}
+#define snd_bt87x_capture_boost_info snd_ctl_boolean_mono_info
static int snd_bt87x_capture_boost_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *value)
@@ -736,61 +755,69 @@ static int __devinit snd_bt87x_create(struct snd_card *card,
chip->mmio = ioremap_nocache(pci_resource_start(pci, 0),
pci_resource_len(pci, 0));
if (!chip->mmio) {
- snd_bt87x_free(chip);
snd_printk(KERN_ERR "cannot remap io memory\n");
- return -ENOMEM;
+ err = -ENOMEM;
+ goto fail;
}
- chip->reg_control = CTL_DA_ES2 | CTL_PKTP_16 | (15 << CTL_DA_SDR_SHIFT);
+ chip->reg_control = CTL_A_PWRDN | CTL_DA_ES2 |
+ CTL_PKTP_16 | (15 << CTL_DA_SDR_SHIFT);
chip->interrupt_mask = MY_INTERRUPTS;
snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control);
snd_bt87x_writel(chip, REG_INT_MASK, 0);
snd_bt87x_writel(chip, REG_INT_STAT, MY_INTERRUPTS);
- if (request_irq(pci->irq, snd_bt87x_interrupt, IRQF_SHARED,
- "Bt87x audio", chip)) {
- snd_bt87x_free(chip);
- snd_printk(KERN_ERR "cannot grab irq\n");
- return -EBUSY;
+ err = request_irq(pci->irq, snd_bt87x_interrupt, IRQF_SHARED,
+ "Bt87x audio", chip);
+ if (err < 0) {
+ snd_printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
+ goto fail;
}
chip->irq = pci->irq;
pci_set_master(pci);
synchronize_irq(chip->irq);
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0) {
- snd_bt87x_free(chip);
- return err;
- }
+ if (err < 0)
+ goto fail;
+
snd_card_set_dev(card, &pci->dev);
*rchip = chip;
return 0;
+
+fail:
+ snd_bt87x_free(chip);
+ return err;
}
-#define BT_DEVICE(chip, subvend, subdev, rate) \
+#define BT_DEVICE(chip, subvend, subdev, id) \
{ .vendor = PCI_VENDOR_ID_BROOKTREE, \
.device = chip, \
.subvendor = subvend, .subdevice = subdev, \
- .driver_data = rate }
+ .driver_data = SND_BT87X_BOARD_ ## id }
+/* driver_data is the card id for that device */
-/* driver_data is the default digital_rate value for that device */
static struct pci_device_id snd_bt87x_ids[] = {
/* Hauppauge WinTV series */
- BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0x13eb, 32000),
+ BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0x13eb, GENERIC),
/* Hauppauge WinTV series */
- BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, 0x0070, 0x13eb, 32000),
+ BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, 0x0070, 0x13eb, GENERIC),
/* Viewcast Osprey 200 */
- BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff01, 44100),
+ BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff01, OSPREY2x0),
/* Viewcast Osprey 440 (rate is configurable via gpio) */
- BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff07, 32000),
+ BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff07, OSPREY440),
/* ATI TV-Wonder */
- BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1002, 0x0001, 32000),
+ BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1002, 0x0001, GENERIC),
/* Leadtek Winfast tv 2000xp delux */
- BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x107d, 0x6606, 32000),
+ BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x107d, 0x6606, GENERIC),
/* Voodoo TV 200 */
- BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x121a, 0x3000, 32000),
+ BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x121a, 0x3000, GENERIC),
/* AVerMedia Studio No. 103, 203, ...? */
- BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1461, 0x0003, 48000),
+ BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1461, 0x0003, AVPHONE98),
+ /* Prolink PixelView PV-M4900 */
+ BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1554, 0x4011, GENERIC),
+ /* Pinnacle Studio PCTV rave */
+ BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0xbd11, 0x1200, GENERIC),
{ }
};
MODULE_DEVICE_TABLE(pci, snd_bt87x_ids);
@@ -815,13 +842,13 @@ static struct {
static struct pci_driver driver;
-/* return the rate of the card, or a negative value if it's blacklisted */
+/* return the id of the card, or a negative value if it's blacklisted */
static int __devinit snd_bt87x_detect_card(struct pci_dev *pci)
{
int i;
const struct pci_device_id *supported;
- supported = pci_match_device(&driver, pci);
+ supported = pci_match_id(snd_bt87x_ids, pci);
if (supported && supported->driver_data > 0)
return supported->driver_data;
@@ -833,12 +860,12 @@ static int __devinit snd_bt87x_detect_card(struct pci_dev *pci)
return -EBUSY;
}
- snd_printk(KERN_INFO "unknown card %#04x-%#04x:%#04x, using default rate 32000\n",
- pci->device, pci->subsystem_vendor, pci->subsystem_device);
+ snd_printk(KERN_INFO "unknown card %#04x-%#04x:%#04x\n",
+ pci->device, pci->subsystem_vendor, pci->subsystem_device);
snd_printk(KERN_DEBUG "please mail id, board name, and, "
"if it works, the correct digital_rate option to "
"<alsa-devel@alsa-project.org>\n");
- return 32000; /* default rate */
+ return SND_BT87X_BOARD_UNKNOWN;
}
static int __devinit snd_bt87x_probe(struct pci_dev *pci,
@@ -847,12 +874,16 @@ static int __devinit snd_bt87x_probe(struct pci_dev *pci,
static int dev;
struct snd_card *card;
struct snd_bt87x *chip;
- int err, rate;
+ int err;
+ enum snd_bt87x_boardid boardid;
- rate = pci_id->driver_data;
- if (! rate)
- if ((rate = snd_bt87x_detect_card(pci)) <= 0)
+ if (!pci_id->driver_data) {
+ err = snd_bt87x_detect_card(pci);
+ if (err < 0)
return -ENODEV;
+ boardid = err;
+ } else
+ boardid = pci_id->driver_data;
if (dev >= SNDRV_CARDS)
return -ENODEV;
@@ -869,27 +900,39 @@ static int __devinit snd_bt87x_probe(struct pci_dev *pci,
if (err < 0)
goto _error;
- if (digital_rate[dev] > 0)
- chip->dig_rate = digital_rate[dev];
- else
- chip->dig_rate = rate;
+ memcpy(&chip->board, &snd_bt87x_boards[boardid], sizeof(chip->board));
- err = snd_bt87x_pcm(chip, DEVICE_DIGITAL, "Bt87x Digital");
- if (err < 0)
- goto _error;
- err = snd_bt87x_pcm(chip, DEVICE_ANALOG, "Bt87x Analog");
- if (err < 0)
- goto _error;
+ if (!chip->board.no_digital) {
+ if (digital_rate[dev] > 0)
+ chip->board.dig_rate = digital_rate[dev];
- err = snd_ctl_add(card, snd_ctl_new1(&snd_bt87x_capture_volume, chip));
- if (err < 0)
- goto _error;
- err = snd_ctl_add(card, snd_ctl_new1(&snd_bt87x_capture_boost, chip));
- if (err < 0)
- goto _error;
- err = snd_ctl_add(card, snd_ctl_new1(&snd_bt87x_capture_source, chip));
- if (err < 0)
- goto _error;
+ chip->reg_control |= chip->board.digital_fmt;
+
+ err = snd_bt87x_pcm(chip, DEVICE_DIGITAL, "Bt87x Digital");
+ if (err < 0)
+ goto _error;
+ }
+ if (!chip->board.no_analog) {
+ err = snd_bt87x_pcm(chip, DEVICE_ANALOG, "Bt87x Analog");
+ if (err < 0)
+ goto _error;
+ err = snd_ctl_add(card, snd_ctl_new1(
+ &snd_bt87x_capture_volume, chip));
+ if (err < 0)
+ goto _error;
+ err = snd_ctl_add(card, snd_ctl_new1(
+ &snd_bt87x_capture_boost, chip));
+ if (err < 0)
+ goto _error;
+ err = snd_ctl_add(card, snd_ctl_new1(
+ &snd_bt87x_capture_source, chip));
+ if (err < 0)
+ goto _error;
+ }
+ snd_printk(KERN_INFO "bt87x%d: Using board %d, %sanalog, %sdigital "
+ "(rate %d Hz)\n", dev, boardid,
+ chip->board.no_analog ? "no " : "",
+ chip->board.no_digital ? "no " : "", chip->board.dig_rate);
strcpy(card->driver, "Bt87x");
sprintf(card->shortname, "Brooktree Bt%x", pci->device);
@@ -920,8 +963,8 @@ static void __devexit snd_bt87x_remove(struct pci_dev *pci)
/* default entries for all Bt87x cards - it's not exported */
/* driver_data is set to 0 to call detection */
static struct pci_device_id snd_bt87x_default_ids[] __devinitdata = {
- BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, PCI_ANY_ID, PCI_ANY_ID, 0),
- BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, PCI_ANY_ID, PCI_ANY_ID, 0),
+ BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, PCI_ANY_ID, PCI_ANY_ID, UNKNOWN),
+ BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, PCI_ANY_ID, PCI_ANY_ID, UNKNOWN),
{ }
};
diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h
index a0420bc63f0b..75da1746e758 100644
--- a/sound/pci/ca0106/ca0106.h
+++ b/sound/pci/ca0106/ca0106.h
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk>
* Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit
- * Version: 0.0.21
+ * Version: 0.0.22
*
* FEATURES currently supported:
* See ca0106_main.c for features.
@@ -47,6 +47,8 @@
* Added GPIO info for SB Live 24bit.
* 0.0.21
* Implement support for Line-in capture on SB Live 24bit.
+ * 0.0.22
+ * Add support for mute control on SB Live 24bit (cards w/ SPI DAC)
*
*
* This code was initally based on code from ALSA's emu10k1x.c which is:
@@ -552,6 +554,95 @@
#define CONTROL_CENTER_LFE_CHANNEL 1
#define CONTROL_UNKNOWN_CHANNEL 2
+
+/* Based on WM8768 Datasheet Rev 4.2 page 32 */
+#define SPI_REG_MASK 0x1ff /* 16-bit SPI writes have a 7-bit address */
+#define SPI_REG_SHIFT 9 /* followed by 9 bits of data */
+
+#define SPI_LDA1_REG 0 /* digital attenuation */
+#define SPI_RDA1_REG 1
+#define SPI_LDA2_REG 4
+#define SPI_RDA2_REG 5
+#define SPI_LDA3_REG 6
+#define SPI_RDA3_REG 7
+#define SPI_LDA4_REG 13
+#define SPI_RDA4_REG 14
+#define SPI_MASTDA_REG 8
+
+#define SPI_DA_BIT_UPDATE (1<<8) /* update attenuation values */
+#define SPI_DA_BIT_0dB 0xff /* 0 dB */
+#define SPI_DA_BIT_infdB 0x00 /* inf dB attenuation (mute) */
+
+#define SPI_PL_REG 2
+#define SPI_PL_BIT_L_M (0<<5) /* left channel = mute */
+#define SPI_PL_BIT_L_L (1<<5) /* left channel = left */
+#define SPI_PL_BIT_L_R (2<<5) /* left channel = right */
+#define SPI_PL_BIT_L_C (3<<5) /* left channel = (L+R)/2 */
+#define SPI_PL_BIT_R_M (0<<7) /* right channel = mute */
+#define SPI_PL_BIT_R_L (1<<7) /* right channel = left */
+#define SPI_PL_BIT_R_R (2<<7) /* right channel = right */
+#define SPI_PL_BIT_R_C (3<<7) /* right channel = (L+R)/2 */
+#define SPI_IZD_REG 2
+#define SPI_IZD_BIT (1<<4) /* infinite zero detect */
+
+#define SPI_FMT_REG 3
+#define SPI_FMT_BIT_RJ (0<<0) /* right justified mode */
+#define SPI_FMT_BIT_LJ (1<<0) /* left justified mode */
+#define SPI_FMT_BIT_I2S (2<<0) /* I2S mode */
+#define SPI_FMT_BIT_DSP (3<<0) /* DSP Modes A or B */
+#define SPI_LRP_REG 3
+#define SPI_LRP_BIT (1<<2) /* invert LRCLK polarity */
+#define SPI_BCP_REG 3
+#define SPI_BCP_BIT (1<<3) /* invert BCLK polarity */
+#define SPI_IWL_REG 3
+#define SPI_IWL_BIT_16 (0<<4) /* 16-bit world length */
+#define SPI_IWL_BIT_20 (1<<4) /* 20-bit world length */
+#define SPI_IWL_BIT_24 (2<<4) /* 24-bit world length */
+#define SPI_IWL_BIT_32 (3<<4) /* 32-bit world length */
+
+#define SPI_MS_REG 10
+#define SPI_MS_BIT (1<<5) /* master mode */
+#define SPI_RATE_REG 10 /* only applies in master mode */
+#define SPI_RATE_BIT_128 (0<<6) /* MCLK = LRCLK * 128 */
+#define SPI_RATE_BIT_192 (1<<6)
+#define SPI_RATE_BIT_256 (2<<6)
+#define SPI_RATE_BIT_384 (3<<6)
+#define SPI_RATE_BIT_512 (4<<6)
+#define SPI_RATE_BIT_768 (5<<6)
+
+/* They really do label the bit for the 4th channel "4" and not "3" */
+#define SPI_DMUTE0_REG 9
+#define SPI_DMUTE1_REG 9
+#define SPI_DMUTE2_REG 9
+#define SPI_DMUTE4_REG 15
+#define SPI_DMUTE0_BIT (1<<3)
+#define SPI_DMUTE1_BIT (1<<4)
+#define SPI_DMUTE2_BIT (1<<5)
+#define SPI_DMUTE4_BIT (1<<2)
+
+#define SPI_PHASE0_REG 3
+#define SPI_PHASE1_REG 3
+#define SPI_PHASE2_REG 3
+#define SPI_PHASE4_REG 15
+#define SPI_PHASE0_BIT (1<<6)
+#define SPI_PHASE1_BIT (1<<7)
+#define SPI_PHASE2_BIT (1<<8)
+#define SPI_PHASE4_BIT (1<<3)
+
+#define SPI_PDWN_REG 2 /* power down all DACs */
+#define SPI_PDWN_BIT (1<<2)
+#define SPI_DACD0_REG 10 /* power down individual DACs */
+#define SPI_DACD1_REG 10
+#define SPI_DACD2_REG 10
+#define SPI_DACD4_REG 15
+#define SPI_DACD0_BIT (1<<1)
+#define SPI_DACD1_BIT (1<<2)
+#define SPI_DACD2_BIT (1<<3)
+#define SPI_DACD4_BIT (1<<0) /* datasheet error says it's 1 */
+
+#define SPI_PWRDNALL_REG 10 /* power down everything */
+#define SPI_PWRDNALL_BIT (1<<4)
+
#include "ca_midi.h"
struct snd_ca0106;
@@ -611,6 +702,8 @@ struct snd_ca0106 {
struct snd_ca_midi midi;
struct snd_ca_midi midi2;
+
+ u16 spi_dac_reg[16];
};
int snd_ca0106_mixer(struct snd_ca0106 *emu);
@@ -627,4 +720,5 @@ void snd_ca0106_ptr_write(struct snd_ca0106 *emu,
int snd_ca0106_i2c_write(struct snd_ca0106 *emu, u32 reg, u32 value);
-
+int snd_ca0106_spi_write(struct snd_ca0106 * emu,
+ unsigned int data);
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index fcab8fb97e38..31d8db9f7a4c 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk>
* Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit
- * Version: 0.0.23
+ * Version: 0.0.25
*
* FEATURES currently supported:
* Front, Rear and Center/LFE.
@@ -79,6 +79,10 @@
* Add support for MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97. From kiksen, bug #901
* 0.0.23
* Implement support for Line-in capture on SB Live 24bit.
+ * 0.0.24
+ * Add support for mute control on SB Live 24bit (cards w/ SPI DAC)
+ * 0.0.25
+ * Powerdown SPI DAC channels when not in use
*
* BUGS:
* Some stability problems when unloading the snd-ca0106 kernel module.
@@ -170,6 +174,15 @@ MODULE_PARM_DESC(subsystem, "Force card subsystem model.");
static struct snd_ca0106_details ca0106_chip_details[] = {
/* Sound Blaster X-Fi Extreme Audio. This does not have an AC97. 53SB079000000 */
/* It is really just a normal SB Live 24bit. */
+ /* Tested:
+ * See ALSA bug#3251
+ */
+ { .serial = 0x10131102,
+ .name = "X-Fi Extreme Audio [SBxxxx]",
+ .gpio_type = 1,
+ .i2c_adc = 1 } ,
+ /* Sound Blaster X-Fi Extreme Audio. This does not have an AC97. 53SB079000000 */
+ /* It is really just a normal SB Live 24bit. */
/*
* CTRL:CA0111-WTLF
* ADC: WM8775SEDS
@@ -261,10 +274,11 @@ static struct snd_ca0106_details ca0106_chip_details[] = {
/* hardware definition */
static struct snd_pcm_hardware snd_ca0106_playback_hw = {
- .info = (SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_MMAP_VALID),
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_SYNC_START,
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
.rates = (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |
SNDRV_PCM_RATE_192000),
@@ -447,6 +461,19 @@ static void snd_ca0106_pcm_free_substream(struct snd_pcm_runtime *runtime)
kfree(runtime->private_data);
}
+static const int spi_dacd_reg[] = {
+ [PCM_FRONT_CHANNEL] = SPI_DACD4_REG,
+ [PCM_REAR_CHANNEL] = SPI_DACD0_REG,
+ [PCM_CENTER_LFE_CHANNEL]= SPI_DACD2_REG,
+ [PCM_UNKNOWN_CHANNEL] = SPI_DACD1_REG,
+};
+static const int spi_dacd_bit[] = {
+ [PCM_FRONT_CHANNEL] = SPI_DACD4_BIT,
+ [PCM_REAR_CHANNEL] = SPI_DACD0_BIT,
+ [PCM_CENTER_LFE_CHANNEL]= SPI_DACD2_BIT,
+ [PCM_UNKNOWN_CHANNEL] = SPI_DACD1_BIT,
+};
+
/* open_playback callback */
static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substream,
int channel_id)
@@ -481,6 +508,17 @@ static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substr
return err;
if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0)
return err;
+ snd_pcm_set_sync(substream);
+
+ if (chip->details->spi_dac && channel_id != PCM_FRONT_CHANNEL) {
+ const int reg = spi_dacd_reg[channel_id];
+
+ /* Power up dac */
+ chip->spi_dac_reg[reg] &= ~spi_dacd_bit[channel_id];
+ err = snd_ca0106_spi_write(chip, chip->spi_dac_reg[reg]);
+ if (err < 0)
+ return err;
+ }
return 0;
}
@@ -491,6 +529,14 @@ static int snd_ca0106_pcm_close_playback(struct snd_pcm_substream *substream)
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_ca0106_pcm *epcm = runtime->private_data;
chip->playback_channels[epcm->channel_id].use = 0;
+
+ if (chip->details->spi_dac && epcm->channel_id != PCM_FRONT_CHANNEL) {
+ const int reg = spi_dacd_reg[epcm->channel_id];
+
+ /* Power down DAC */
+ chip->spi_dac_reg[reg] |= spi_dacd_bit[epcm->channel_id];
+ snd_ca0106_spi_write(chip, chip->spi_dac_reg[reg]);
+ }
/* FIXME: maybe zero others */
return 0;
}
@@ -809,6 +855,9 @@ static int snd_ca0106_pcm_trigger_playback(struct snd_pcm_substream *substream,
break;
}
snd_pcm_group_for_each_entry(s, substream) {
+ if (snd_pcm_substream_chip(s) != emu ||
+ s->stream != SNDRV_PCM_STREAM_PLAYBACK)
+ continue;
runtime = s->runtime;
epcm = runtime->private_data;
channel = epcm->channel_id;
@@ -1214,28 +1263,23 @@ static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device, struct s
return 0;
}
+#define SPI_REG(reg, value) (((reg) << SPI_REG_SHIFT) | (value))
static unsigned int spi_dac_init[] = {
- 0x00ff,
- 0x02ff,
- 0x0400,
- 0x0520,
- 0x0620, /* Set 24 bit. Was 0x0600 */
- 0x08ff,
- 0x0aff,
- 0x0cff,
- 0x0eff,
- 0x10ff,
- 0x1200,
- 0x1400,
- 0x1480,
- 0x1800,
- 0x1aff,
- 0x1cff,
- 0x1e00,
- 0x0530,
- 0x0602,
- 0x0622,
- 0x1400,
+ SPI_REG(SPI_LDA1_REG, SPI_DA_BIT_0dB), /* 0dB dig. attenuation */
+ SPI_REG(SPI_RDA1_REG, SPI_DA_BIT_0dB),
+ SPI_REG(SPI_PL_REG, SPI_PL_BIT_L_L | SPI_PL_BIT_R_R | SPI_IZD_BIT),
+ SPI_REG(SPI_FMT_REG, SPI_FMT_BIT_I2S | SPI_IWL_BIT_24),
+ SPI_REG(SPI_LDA2_REG, SPI_DA_BIT_0dB),
+ SPI_REG(SPI_RDA2_REG, SPI_DA_BIT_0dB),
+ SPI_REG(SPI_LDA3_REG, SPI_DA_BIT_0dB),
+ SPI_REG(SPI_RDA3_REG, SPI_DA_BIT_0dB),
+ SPI_REG(SPI_MASTDA_REG, SPI_DA_BIT_0dB),
+ SPI_REG(9, 0x00),
+ SPI_REG(SPI_MS_REG, SPI_DACD0_BIT | SPI_DACD1_BIT | SPI_DACD2_BIT),
+ SPI_REG(12, 0x00),
+ SPI_REG(SPI_LDA4_REG, SPI_DA_BIT_0dB),
+ SPI_REG(SPI_RDA4_REG, SPI_DA_BIT_0dB | SPI_DA_BIT_UPDATE),
+ SPI_REG(SPI_DACD4_REG, 0x00),
};
static unsigned int i2c_adc_init[][2] = {
@@ -1475,8 +1519,13 @@ static int __devinit snd_ca0106_create(int dev, struct snd_card *card,
int size, n;
size = ARRAY_SIZE(spi_dac_init);
- for (n=0; n < size; n++)
+ for (n = 0; n < size; n++) {
+ int reg = spi_dac_init[n] >> SPI_REG_SHIFT;
+
snd_ca0106_spi_write(chip, spi_dac_init[n]);
+ if (reg < ARRAY_SIZE(chip->spi_dac_reg))
+ chip->spi_dac_reg[reg] = spi_dac_init[n];
+ }
}
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c
index 9c3a9c8d1dc2..be519a17dfa5 100644
--- a/sound/pci/ca0106/ca0106_mixer.c
+++ b/sound/pci/ca0106/ca0106_mixer.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk>
* Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit
- * Version: 0.0.17
+ * Version: 0.0.18
*
* FEATURES currently supported:
* See ca0106_main.c for features.
@@ -39,6 +39,8 @@
* Modified Copyright message.
* 0.0.17
* Implement Mic and Line in Capture.
+ * 0.0.18
+ * Add support for mute control on SB Live 24bit (cards w/ SPI DAC)
*
* This code was initally based on code from ALSA's emu10k1x.c which is:
* Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com>
@@ -77,15 +79,7 @@
static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale1, -5175, 25, 1);
static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale2, -10350, 50, 1);
-static int snd_ca0106_shared_spdif_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_ca0106_shared_spdif_info snd_ctl_boolean_mono_info
static int snd_ca0106_shared_spdif_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -470,6 +464,42 @@ static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol,
return change;
}
+#define spi_mute_info snd_ctl_boolean_mono_info
+
+static int spi_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
+ unsigned int reg = kcontrol->private_value >> SPI_REG_SHIFT;
+ unsigned int bit = kcontrol->private_value & SPI_REG_MASK;
+
+ ucontrol->value.integer.value[0] = !(emu->spi_dac_reg[reg] & bit);
+ return 0;
+}
+
+static int spi_mute_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
+ unsigned int reg = kcontrol->private_value >> SPI_REG_SHIFT;
+ unsigned int bit = kcontrol->private_value & SPI_REG_MASK;
+ int ret;
+
+ ret = emu->spi_dac_reg[reg] & bit;
+ if (ucontrol->value.integer.value[0]) {
+ if (!ret) /* bit already cleared, do nothing */
+ return 0;
+ emu->spi_dac_reg[reg] &= ~bit;
+ } else {
+ if (ret) /* bit already set, do nothing */
+ return 0;
+ emu->spi_dac_reg[reg] |= bit;
+ }
+
+ ret = snd_ca0106_spi_write(emu, emu->spi_dac_reg[reg]);
+ return ret ? -1 : 1;
+}
+
#define CA_VOLUME(xname,chid,reg) \
{ \
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
@@ -562,6 +592,28 @@ static struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls[] __devinitdata =
I2C_VOLUME("Aux Capture Volume", 3),
};
+#define SPI_SWITCH(xname,reg,bit) \
+{ \
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
+ .info = spi_mute_info, \
+ .get = spi_mute_get, \
+ .put = spi_mute_put, \
+ .private_value = (reg<<SPI_REG_SHIFT) | (bit) \
+}
+
+static struct snd_kcontrol_new snd_ca0106_volume_spi_dac_ctls[]
+__devinitdata = {
+ SPI_SWITCH("Analog Front Playback Switch",
+ SPI_DMUTE4_REG, SPI_DMUTE4_BIT),
+ SPI_SWITCH("Analog Rear Playback Switch",
+ SPI_DMUTE0_REG, SPI_DMUTE0_BIT),
+ SPI_SWITCH("Analog Center/LFE Playback Switch",
+ SPI_DMUTE2_REG, SPI_DMUTE2_BIT),
+ SPI_SWITCH("Analog Side Playback Switch",
+ SPI_DMUTE1_REG, SPI_DMUTE1_BIT),
+};
+
static int __devinit remove_ctl(struct snd_card *card, const char *name)
{
struct snd_ctl_elem_id id;
@@ -591,9 +643,19 @@ static int __devinit rename_ctl(struct snd_card *card, const char *src, const ch
return -ENOENT;
}
+#define ADD_CTLS(emu, ctls) \
+ do { \
+ int i, err; \
+ for (i = 0; i < ARRAY_SIZE(ctls); i++) { \
+ err = snd_ctl_add(card, snd_ctl_new1(&ctls[i], emu)); \
+ if (err < 0) \
+ return err; \
+ } \
+ } while (0)
+
int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
{
- int i, err;
+ int err;
struct snd_card *card = emu->card;
char **c;
static char *ca0106_remove_ctls[] = {
@@ -640,17 +702,9 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
rename_ctl(card, c[0], c[1]);
#endif
- for (i = 0; i < ARRAY_SIZE(snd_ca0106_volume_ctls); i++) {
- err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_volume_ctls[i], emu));
- if (err < 0)
- return err;
- }
+ ADD_CTLS(emu, snd_ca0106_volume_ctls);
if (emu->details->i2c_adc == 1) {
- for (i = 0; i < ARRAY_SIZE(snd_ca0106_volume_i2c_adc_ctls); i++) {
- err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_volume_i2c_adc_ctls[i], emu));
- if (err < 0)
- return err;
- }
+ ADD_CTLS(emu, snd_ca0106_volume_i2c_adc_ctls);
if (emu->details->gpio_type == 1)
err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu));
else /* gpio_type == 2 */
@@ -658,6 +712,8 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
if (err < 0)
return err;
}
+ if (emu->details->spi_dac == 1)
+ ADD_CTLS(emu, snd_ca0106_volume_spi_dac_ctls);
return 0;
}
diff --git a/sound/pci/ca0106/ca_midi.c b/sound/pci/ca0106/ca_midi.c
index 2e6eab1f1189..ad32eff2713f 100644
--- a/sound/pci/ca0106/ca_midi.c
+++ b/sound/pci/ca0106/ca_midi.c
@@ -6,7 +6,7 @@
* Changelog:
* Implementation is based on mpu401 and emu10k1x and
* tested with ca0106.
- * mpu401: Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * mpu401: Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* emu10k1x: Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com>
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/pci/ca0106/ca_midi.h b/sound/pci/ca0106/ca_midi.h
index b72c0933bd22..922ed3e3731e 100644
--- a/sound/pci/ca0106/ca_midi.h
+++ b/sound/pci/ca0106/ca_midi.h
@@ -22,9 +22,9 @@
*
*/
-#include<linux/spinlock.h>
-#include<sound/rawmidi.h>
-#include<sound/mpu401.h>
+#include <linux/spinlock.h>
+#include <sound/rawmidi.h>
+#include <sound/mpu401.h>
#define CA_MIDI_MODE_INPUT MPU401_MODE_INPUT
#define CA_MIDI_MODE_OUTPUT MPU401_MODE_OUTPUT
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index 7d3c5ee0005c..6832649879ce 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -95,30 +95,34 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address.");
#define CM_CHADC0 0x00000001 /* ch0, 0:playback, 1:record */
#define CM_REG_FUNCTRL1 0x04
-#define CM_ASFC_MASK 0x0000E000 /* ADC sampling frequency */
-#define CM_ASFC_SHIFT 13
-#define CM_DSFC_MASK 0x00001C00 /* DAC sampling frequency */
-#define CM_DSFC_SHIFT 10
+#define CM_DSFC_MASK 0x0000E000 /* channel 1 (DAC?) sampling frequency */
+#define CM_DSFC_SHIFT 13
+#define CM_ASFC_MASK 0x00001C00 /* channel 0 (ADC?) sampling frequency */
+#define CM_ASFC_SHIFT 10
#define CM_SPDF_1 0x00000200 /* SPDIF IN/OUT at channel B */
#define CM_SPDF_0 0x00000100 /* SPDIF OUT only channel A */
-#define CM_SPDFLOOP 0x00000080 /* ext. SPDIIF/OUT -> IN loopback */
+#define CM_SPDFLOOP 0x00000080 /* ext. SPDIIF/IN -> OUT loopback */
#define CM_SPDO2DAC 0x00000040 /* SPDIF/OUT can be heard from internal DAC */
#define CM_INTRM 0x00000020 /* master control block (MCB) interrupt enabled */
#define CM_BREQ 0x00000010 /* bus master enabled */
#define CM_VOICE_EN 0x00000008 /* legacy voice (SB16,FM) */
-#define CM_UART_EN 0x00000004 /* UART */
-#define CM_JYSTK_EN 0x00000002 /* joy stick */
+#define CM_UART_EN 0x00000004 /* legacy UART */
+#define CM_JYSTK_EN 0x00000002 /* legacy joystick */
+#define CM_ZVPORT 0x00000001 /* ZVPORT */
#define CM_REG_CHFORMAT 0x08
#define CM_CHB3D5C 0x80000000 /* 5,6 channels */
+#define CM_FMOFFSET2 0x40000000 /* initial FM PCM offset 2 when Fmute=1 */
#define CM_CHB3D 0x20000000 /* 4 channels */
#define CM_CHIP_MASK1 0x1f000000
#define CM_CHIP_037 0x01000000
-
-#define CM_SPDIF_SELECT1 0x00080000 /* for model <= 037 ? */
+#define CM_SETLAT48 0x00800000 /* set latency timer 48h */
+#define CM_EDGEIRQ 0x00400000 /* emulated edge trigger legacy IRQ */
+#define CM_SPD24SEL39 0x00200000 /* 24-bit spdif: model 039 */
#define CM_AC3EN1 0x00100000 /* enable AC3: model 037 */
+#define CM_SPDIF_SELECT1 0x00080000 /* for model <= 037 ? */
#define CM_SPD24SEL 0x00020000 /* 24bit spdif: model 037 */
/* #define CM_SPDIF_INVERSE 0x00010000 */ /* ??? */
@@ -128,35 +132,45 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address.");
#define CM_ADCBITLEN_14 0x00008000
#define CM_ADCBITLEN_13 0x0000C000
-#define CM_ADCDACLEN_MASK 0x00003000
+#define CM_ADCDACLEN_MASK 0x00003000 /* model 037 */
#define CM_ADCDACLEN_060 0x00000000
#define CM_ADCDACLEN_066 0x00001000
#define CM_ADCDACLEN_130 0x00002000
#define CM_ADCDACLEN_280 0x00003000
+#define CM_ADCDLEN_MASK 0x00003000 /* model 039 */
+#define CM_ADCDLEN_ORIGINAL 0x00000000
+#define CM_ADCDLEN_EXTRA 0x00001000
+#define CM_ADCDLEN_24K 0x00002000
+#define CM_ADCDLEN_WEIGHT 0x00003000
+
#define CM_CH1_SRATE_176K 0x00000800
+#define CM_CH1_SRATE_96K 0x00000800 /* model 055? */
#define CM_CH1_SRATE_88K 0x00000400
#define CM_CH0_SRATE_176K 0x00000200
+#define CM_CH0_SRATE_96K 0x00000200 /* model 055? */
#define CM_CH0_SRATE_88K 0x00000100
#define CM_SPDIF_INVERSE2 0x00000080 /* model 055? */
+#define CM_DBLSPDS 0x00000040 /* double SPDIF sample rate 88.2/96 */
+#define CM_POLVALID 0x00000020 /* inverse SPDIF/IN valid bit */
+#define CM_SPDLOCKED 0x00000010
-#define CM_CH1FMT_MASK 0x0000000C
+#define CM_CH1FMT_MASK 0x0000000C /* bit 3: 16 bits, bit 2: stereo */
#define CM_CH1FMT_SHIFT 2
-#define CM_CH0FMT_MASK 0x00000003
+#define CM_CH0FMT_MASK 0x00000003 /* bit 1: 16 bits, bit 0: stereo */
#define CM_CH0FMT_SHIFT 0
#define CM_REG_INT_HLDCLR 0x0C
#define CM_CHIP_MASK2 0xff000000
+#define CM_CHIP_8768 0x20000000
+#define CM_CHIP_055 0x08000000
#define CM_CHIP_039 0x04000000
#define CM_CHIP_039_6CH 0x01000000
-#define CM_CHIP_055 0x08000000
-#define CM_CHIP_8768 0x20000000
+#define CM_UNKNOWN_INT_EN 0x00080000 /* ? */
#define CM_TDMA_INT_EN 0x00040000
#define CM_CH1_INT_EN 0x00020000
#define CM_CH0_INT_EN 0x00010000
-#define CM_INT_HOLD 0x00000002
-#define CM_INT_CLEAR 0x00000001
#define CM_REG_INT_STATUS 0x10
#define CM_INTR 0x80000000
@@ -175,12 +189,13 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address.");
#define CM_CHINT0 0x00000001
#define CM_REG_LEGACY_CTRL 0x14
-#define CM_NXCHG 0x80000000 /* h/w multi channels? */
+#define CM_NXCHG 0x80000000 /* don't map base reg dword->sample */
#define CM_VMPU_MASK 0x60000000 /* MPU401 i/o port address */
#define CM_VMPU_330 0x00000000
#define CM_VMPU_320 0x20000000
#define CM_VMPU_310 0x40000000
#define CM_VMPU_300 0x60000000
+#define CM_ENWR8237 0x10000000 /* enable bus master to write 8237 base reg */
#define CM_VSBSEL_MASK 0x0C000000 /* SB16 base address */
#define CM_VSBSEL_220 0x00000000
#define CM_VSBSEL_240 0x04000000
@@ -191,44 +206,74 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address.");
#define CM_FMSEL_3C8 0x01000000
#define CM_FMSEL_3E0 0x02000000
#define CM_FMSEL_3E8 0x03000000
-#define CM_ENSPDOUT 0x00800000 /* enable XPDIF/OUT to I/O interface */
-#define CM_SPDCOPYRHT 0x00400000 /* set copyright spdif in/out */
+#define CM_ENSPDOUT 0x00800000 /* enable XSPDIF/OUT to I/O interface */
+#define CM_SPDCOPYRHT 0x00400000 /* spdif in/out copyright bit */
#define CM_DAC2SPDO 0x00200000 /* enable wave+fm_midi -> SPDIF/OUT */
-#define CM_SETRETRY 0x00010000 /* 0: legacy i/o wait (default), 1: legacy i/o bus retry */
+#define CM_INVIDWEN 0x00100000 /* internal vendor ID write enable, model 039? */
+#define CM_SETRETRY 0x00100000 /* 0: legacy i/o wait (default), 1: legacy i/o bus retry */
+#define CM_C_EEACCESS 0x00080000 /* direct programming eeprom regs */
+#define CM_C_EECS 0x00040000
+#define CM_C_EEDI46 0x00020000
+#define CM_C_EECK46 0x00010000
#define CM_CHB3D6C 0x00008000 /* 5.1 channels support */
-#define CM_LINE_AS_BASS 0x00006000 /* use line-in as bass */
+#define CM_CENTR2LIN 0x00004000 /* line-in as center out */
+#define CM_BASE2LIN 0x00002000 /* line-in as bass out */
+#define CM_EXBASEN 0x00001000 /* external bass input enable */
#define CM_REG_MISC_CTRL 0x18
-#define CM_PWD 0x80000000
+#define CM_PWD 0x80000000 /* power down */
#define CM_RESET 0x40000000
-#define CM_SFIL_MASK 0x30000000
-#define CM_TXVX 0x08000000
-#define CM_N4SPK3D 0x04000000 /* 4ch output */
+#define CM_SFIL_MASK 0x30000000 /* filter control at front end DAC, model 037? */
+#define CM_VMGAIN 0x10000000 /* analog master amp +6dB, model 039? */
+#define CM_TXVX 0x08000000 /* model 037? */
+#define CM_N4SPK3D 0x04000000 /* copy front to rear */
#define CM_SPDO5V 0x02000000 /* 5V spdif output (1 = 0.5v (coax)) */
#define CM_SPDIF48K 0x01000000 /* write */
#define CM_SPATUS48K 0x01000000 /* read */
-#define CM_ENDBDAC 0x00800000 /* enable dual dac */
+#define CM_ENDBDAC 0x00800000 /* enable double dac */
#define CM_XCHGDAC 0x00400000 /* 0: front=ch0, 1: front=ch1 */
#define CM_SPD32SEL 0x00200000 /* 0: 16bit SPDIF, 1: 32bit */
-#define CM_SPDFLOOPI 0x00100000 /* int. SPDIF-IN -> int. OUT */
-#define CM_FM_EN 0x00080000 /* enalbe FM */
+#define CM_SPDFLOOPI 0x00100000 /* int. SPDIF-OUT -> int. IN */
+#define CM_FM_EN 0x00080000 /* enable legacy FM */
#define CM_AC3EN2 0x00040000 /* enable AC3: model 039 */
-#define CM_VIDWPDSB 0x00010000
+#define CM_ENWRASID 0x00010000 /* choose writable internal SUBID (audio) */
+#define CM_VIDWPDSB 0x00010000 /* model 037? */
#define CM_SPDF_AC97 0x00008000 /* 0: SPDIF/OUT 44.1K, 1: 48K */
-#define CM_MASK_EN 0x00004000
-#define CM_VIDWPPRT 0x00002000
-#define CM_SFILENB 0x00001000
-#define CM_MMODE_MASK 0x00000E00
+#define CM_MASK_EN 0x00004000 /* activate channel mask on legacy DMA */
+#define CM_ENWRMSID 0x00002000 /* choose writable internal SUBID (modem) */
+#define CM_VIDWPPRT 0x00002000 /* model 037? */
+#define CM_SFILENB 0x00001000 /* filter stepping at front end DAC, model 037? */
+#define CM_MMODE_MASK 0x00000E00 /* model DAA interface mode */
#define CM_SPDIF_SELECT2 0x00000100 /* for model > 039 ? */
#define CM_ENCENTER 0x00000080
-#define CM_FLINKON 0x00000040
-#define CM_FLINKOFF 0x00000020
-#define CM_MIDSMP 0x00000010
-#define CM_UPDDMA_MASK 0x0000000C
-#define CM_TWAIT_MASK 0x00000003
+#define CM_FLINKON 0x00000080 /* force modem link detection on, model 037 */
+#define CM_MUTECH1 0x00000040 /* mute PCI ch1 to DAC */
+#define CM_FLINKOFF 0x00000040 /* force modem link detection off, model 037 */
+#define CM_UNKNOWN_18_5 0x00000020 /* ? */
+#define CM_MIDSMP 0x00000010 /* 1/2 interpolation at front end DAC */
+#define CM_UPDDMA_MASK 0x0000000C /* TDMA position update notification */
+#define CM_UPDDMA_2048 0x00000000
+#define CM_UPDDMA_1024 0x00000004
+#define CM_UPDDMA_512 0x00000008
+#define CM_UPDDMA_256 0x0000000C
+#define CM_TWAIT_MASK 0x00000003 /* model 037 */
+#define CM_TWAIT1 0x00000002 /* FM i/o cycle, 0: 48, 1: 64 PCICLKs */
+#define CM_TWAIT0 0x00000001 /* i/o cycle, 0: 4, 1: 6 PCICLKs */
+
+#define CM_REG_TDMA_POSITION 0x1C
+#define CM_TDMA_CNT_MASK 0xFFFF0000 /* current byte/word count */
+#define CM_TDMA_ADR_MASK 0x0000FFFF /* current address */
/* byte */
#define CM_REG_MIXER0 0x20
+#define CM_REG_SBVR 0x20 /* write: sb16 version */
+#define CM_REG_DEV 0x20 /* read: hardware device version */
+
+#define CM_REG_MIXER21 0x21
+#define CM_UNKNOWN_21_MASK 0x78 /* ? */
+#define CM_X_ADPCM 0x04 /* SB16 ADPCM enable */
+#define CM_PROINV 0x02 /* SBPro left/right channel switching */
+#define CM_X_SB16 0x01 /* SB16 compatible */
#define CM_REG_SB16_DATA 0x22
#define CM_REG_SB16_ADDR 0x23
@@ -243,8 +288,8 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address.");
#define CM_FMMUTE_SHIFT 7
#define CM_WSMUTE 0x40 /* mute PCM */
#define CM_WSMUTE_SHIFT 6
-#define CM_SPK4 0x20 /* lin-in -> rear line out */
-#define CM_SPK4_SHIFT 5
+#define CM_REAR2LIN 0x20 /* lin-in -> rear line out */
+#define CM_REAR2LIN_SHIFT 5
#define CM_REAR2FRONT 0x10 /* exchange rear/front */
#define CM_REAR2FRONT_SHIFT 4
#define CM_WAVEINL 0x08 /* digital wave rec. left chan */
@@ -276,12 +321,13 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address.");
#define CM_VAUXR_MASK 0x0f
#define CM_REG_MISC 0x27
+#define CM_UNKNOWN_27_MASK 0xd8 /* ? */
#define CM_XGPO1 0x20
// #define CM_XGPBIO 0x04
#define CM_MIC_CENTER_LFE 0x04 /* mic as center/lfe out? (model 039 or later?) */
#define CM_SPDIF_INVERSE 0x04 /* spdif input phase inverse (model 037) */
#define CM_SPDVALID 0x02 /* spdif input valid check */
-#define CM_DMAUTO 0x01
+#define CM_DMAUTO 0x01 /* SB16 DMA auto detect */
#define CM_REG_AC97 0x28 /* hmmm.. do we have ac97 link? */
/*
@@ -322,18 +368,20 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address.");
/*
* extended registers
*/
-#define CM_REG_CH0_FRAME1 0x80 /* base address */
-#define CM_REG_CH0_FRAME2 0x84
+#define CM_REG_CH0_FRAME1 0x80 /* write: base address */
+#define CM_REG_CH0_FRAME2 0x84 /* read: current address */
#define CM_REG_CH1_FRAME1 0x88 /* 0-15: count of samples at bus master; buffer size */
#define CM_REG_CH1_FRAME2 0x8C /* 16-31: count of samples at codec; fragment size */
+
#define CM_REG_EXT_MISC 0x90
-#define CM_REG_MISC_CTRL_8768 0x92 /* reg. name the same as 0x18 */
-#define CM_CHB3D8C 0x20 /* 7.1 channels support */
-#define CM_SPD32FMT 0x10 /* SPDIF/IN 32k */
-#define CM_ADC2SPDIF 0x08 /* ADC output to SPDIF/OUT */
-#define CM_SHAREADC 0x04 /* DAC in ADC as Center/LFE */
-#define CM_REALTCMP 0x02 /* monitor the CMPL/CMPR of ADC */
-#define CM_INVLRCK 0x01 /* invert ZVPORT's LRCK */
+#define CM_ADC48K44K 0x10000000 /* ADC parameters group, 0: 44k, 1: 48k */
+#define CM_CHB3D8C 0x00200000 /* 7.1 channels support */
+#define CM_SPD32FMT 0x00100000 /* SPDIF/IN 32k sample rate */
+#define CM_ADC2SPDIF 0x00080000 /* ADC output to SPDIF/OUT */
+#define CM_SHAREADC 0x00040000 /* DAC in ADC as Center/LFE */
+#define CM_REALTCMP 0x00020000 /* monitor the CMPL/CMPR of ADC */
+#define CM_INVLRCK 0x00010000 /* invert ZVPORT's LRCK */
+#define CM_UNKNOWN_90_MASK 0x0000FFFF /* ? */
/*
* size of i/o region
@@ -383,15 +431,14 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address.");
struct cmipci_pcm {
struct snd_pcm_substream *substream;
- int running; /* dac/adc running? */
+ u8 running; /* dac/adc running? */
+ u8 fmt; /* format bits */
+ u8 is_dac;
+ u8 needs_silencing;
unsigned int dma_size; /* in frames */
- unsigned int period_size; /* in frames */
+ unsigned int shift;
+ unsigned int ch; /* channel (0/1) */
unsigned int offset; /* physical address of the buffer */
- unsigned int fmt; /* format bits */
- int ch; /* channel (0/1) */
- unsigned int is_dac; /* is dac? */
- int bytes_per_frame;
- int shift;
};
/* mixer elements toggled/resumed during ac3 playback */
@@ -424,7 +471,6 @@ struct cmipci {
int chip_version;
int max_channels;
- unsigned int has_dual_dac: 1;
unsigned int can_ac3_sw: 1;
unsigned int can_ac3_hw: 1;
unsigned int can_multi_ch: 1;
@@ -557,6 +603,9 @@ static unsigned int rates[] = { 5512, 11025, 22050, 44100, 8000, 16000, 32000, 4
static unsigned int snd_cmipci_rate_freq(unsigned int rate)
{
unsigned int i;
+
+ if (rate > 48000)
+ rate /= 2;
for (i = 0; i < ARRAY_SIZE(rates); i++) {
if (rates[i] == rate)
return i;
@@ -671,19 +720,19 @@ static int snd_cmipci_hw_free(struct snd_pcm_substream *substream)
/*
*/
-static unsigned int hw_channels[] = {1, 2, 4, 5, 6, 8};
+static unsigned int hw_channels[] = {1, 2, 4, 6, 8};
static struct snd_pcm_hw_constraint_list hw_constraints_channels_4 = {
.count = 3,
.list = hw_channels,
.mask = 0,
};
static struct snd_pcm_hw_constraint_list hw_constraints_channels_6 = {
- .count = 5,
+ .count = 4,
.list = hw_channels,
.mask = 0,
};
static struct snd_pcm_hw_constraint_list hw_constraints_channels_8 = {
- .count = 6,
+ .count = 5,
.list = hw_channels,
.mask = 0,
};
@@ -691,48 +740,37 @@ static struct snd_pcm_hw_constraint_list hw_constraints_channels_8 = {
static int set_dac_channels(struct cmipci *cm, struct cmipci_pcm *rec, int channels)
{
if (channels > 2) {
- if (! cm->can_multi_ch)
+ if (!cm->can_multi_ch || !rec->ch)
return -EINVAL;
if (rec->fmt != 0x03) /* stereo 16bit only */
return -EINVAL;
+ }
+ if (cm->can_multi_ch) {
spin_lock_irq(&cm->reg_lock);
- snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_NXCHG);
- snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_XCHGDAC);
- if (channels > 4) {
- snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D);
- snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_CHB3D5C);
+ if (channels > 2) {
+ snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_NXCHG);
+ snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_XCHGDAC);
} else {
- snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D5C);
- snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_CHB3D);
+ snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_NXCHG);
+ snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_XCHGDAC);
}
- if (channels >= 6) {
+ if (channels == 8)
+ snd_cmipci_set_bit(cm, CM_REG_EXT_MISC, CM_CHB3D8C);
+ else
+ snd_cmipci_clear_bit(cm, CM_REG_EXT_MISC, CM_CHB3D8C);
+ if (channels == 6) {
+ snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_CHB3D5C);
snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_CHB3D6C);
- snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_ENCENTER);
} else {
- snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_CHB3D6C);
- snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_ENCENTER);
- }
- if (cm->chip_version == 68) {
- if (channels == 8) {
- snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL_8768, CM_CHB3D8C);
- } else {
- snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL_8768, CM_CHB3D8C);
- }
- }
- spin_unlock_irq(&cm->reg_lock);
-
- } else {
- if (cm->can_multi_ch) {
- spin_lock_irq(&cm->reg_lock);
- snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_NXCHG);
- snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D);
snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D5C);
snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_CHB3D6C);
- snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_ENCENTER);
- snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_XCHGDAC);
- spin_unlock_irq(&cm->reg_lock);
}
+ if (channels == 4)
+ snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_CHB3D);
+ else
+ snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D);
+ spin_unlock_irq(&cm->reg_lock);
}
return 0;
}
@@ -746,6 +784,7 @@ static int snd_cmipci_pcm_prepare(struct cmipci *cm, struct cmipci_pcm *rec,
struct snd_pcm_substream *substream)
{
unsigned int reg, freq, val;
+ unsigned int period_size;
struct snd_pcm_runtime *runtime = substream->runtime;
rec->fmt = 0;
@@ -765,11 +804,11 @@ static int snd_cmipci_pcm_prepare(struct cmipci *cm, struct cmipci_pcm *rec,
rec->offset = runtime->dma_addr;
/* buffer and period sizes in frame */
rec->dma_size = runtime->buffer_size << rec->shift;
- rec->period_size = runtime->period_size << rec->shift;
+ period_size = runtime->period_size << rec->shift;
if (runtime->channels > 2) {
/* multi-channels */
rec->dma_size = (rec->dma_size * runtime->channels) / 2;
- rec->period_size = (rec->period_size * runtime->channels) / 2;
+ period_size = (period_size * runtime->channels) / 2;
}
spin_lock_irq(&cm->reg_lock);
@@ -780,7 +819,7 @@ static int snd_cmipci_pcm_prepare(struct cmipci *cm, struct cmipci_pcm *rec,
/* program sample counts */
reg = rec->ch ? CM_REG_CH1_FRAME2 : CM_REG_CH0_FRAME2;
snd_cmipci_write_w(cm, reg, rec->dma_size - 1);
- snd_cmipci_write_w(cm, reg + 2, rec->period_size - 1);
+ snd_cmipci_write_w(cm, reg + 2, period_size - 1);
/* set adc/dac flag */
val = rec->ch ? CM_CHADC1 : CM_CHADC0;
@@ -795,11 +834,11 @@ static int snd_cmipci_pcm_prepare(struct cmipci *cm, struct cmipci_pcm *rec,
freq = snd_cmipci_rate_freq(runtime->rate);
val = snd_cmipci_read(cm, CM_REG_FUNCTRL1);
if (rec->ch) {
- val &= ~CM_ASFC_MASK;
- val |= (freq << CM_ASFC_SHIFT) & CM_ASFC_MASK;
- } else {
val &= ~CM_DSFC_MASK;
val |= (freq << CM_DSFC_SHIFT) & CM_DSFC_MASK;
+ } else {
+ val &= ~CM_ASFC_MASK;
+ val |= (freq << CM_ASFC_SHIFT) & CM_ASFC_MASK;
}
snd_cmipci_write(cm, CM_REG_FUNCTRL1, val);
//snd_printd("cmipci: functrl1 = %08x\n", val);
@@ -813,6 +852,16 @@ static int snd_cmipci_pcm_prepare(struct cmipci *cm, struct cmipci_pcm *rec,
val &= ~CM_CH0FMT_MASK;
val |= rec->fmt << CM_CH0FMT_SHIFT;
}
+ if (cm->chip_version == 68) {
+ if (runtime->rate == 88200)
+ val |= CM_CH0_SRATE_88K << (rec->ch * 2);
+ else
+ val &= ~(CM_CH0_SRATE_88K << (rec->ch * 2));
+ if (runtime->rate == 96000)
+ val |= CM_CH0_SRATE_96K << (rec->ch * 2);
+ else
+ val &= ~(CM_CH0_SRATE_96K << (rec->ch * 2));
+ }
snd_cmipci_write(cm, CM_REG_CHFORMAT, val);
//snd_printd("cmipci: chformat = %08x\n", val);
@@ -826,7 +875,7 @@ static int snd_cmipci_pcm_prepare(struct cmipci *cm, struct cmipci_pcm *rec,
* PCM trigger/stop
*/
static int snd_cmipci_pcm_trigger(struct cmipci *cm, struct cmipci_pcm *rec,
- struct snd_pcm_substream *substream, int cmd)
+ int cmd)
{
unsigned int inthld, chen, reset, pause;
int result = 0;
@@ -855,6 +904,7 @@ static int snd_cmipci_pcm_trigger(struct cmipci *cm, struct cmipci_pcm *rec,
cm->ctrl &= ~chen;
snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl | reset);
snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl & ~reset);
+ rec->needs_silencing = rec->is_dac;
break;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_SUSPEND:
@@ -906,7 +956,7 @@ static int snd_cmipci_playback_trigger(struct snd_pcm_substream *substream,
int cmd)
{
struct cmipci *cm = snd_pcm_substream_chip(substream);
- return snd_cmipci_pcm_trigger(cm, &cm->channel[CM_CH_PLAY], substream, cmd);
+ return snd_cmipci_pcm_trigger(cm, &cm->channel[CM_CH_PLAY], cmd);
}
static snd_pcm_uframes_t snd_cmipci_playback_pointer(struct snd_pcm_substream *substream)
@@ -925,7 +975,7 @@ static int snd_cmipci_capture_trigger(struct snd_pcm_substream *substream,
int cmd)
{
struct cmipci *cm = snd_pcm_substream_chip(substream);
- return snd_cmipci_pcm_trigger(cm, &cm->channel[CM_CH_CAPT], substream, cmd);
+ return snd_cmipci_pcm_trigger(cm, &cm->channel[CM_CH_CAPT], cmd);
}
static snd_pcm_uframes_t snd_cmipci_capture_pointer(struct snd_pcm_substream *substream)
@@ -1199,15 +1249,19 @@ static int setup_spdif_playback(struct cmipci *cm, struct snd_pcm_substream *sub
snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_PLAYBACK_SPDF);
setup_ac3(cm, subs, do_ac3, rate);
- if (rate == 48000)
+ if (rate == 48000 || rate == 96000)
snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_SPDIF48K | CM_SPDF_AC97);
else
snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_SPDIF48K | CM_SPDF_AC97);
-
+ if (rate > 48000)
+ snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_DBLSPDS);
+ else
+ snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_DBLSPDS);
} else {
/* they are controlled via "IEC958 Output Switch" */
/* snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_ENSPDOUT); */
/* snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_SPDO2DAC); */
+ snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_DBLSPDS);
snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_PLAYBACK_SPDF);
setup_ac3(cm, subs, 0, 0);
}
@@ -1227,7 +1281,7 @@ static int snd_cmipci_playback_prepare(struct snd_pcm_substream *substream)
int rate = substream->runtime->rate;
int err, do_spdif, do_ac3 = 0;
- do_spdif = ((rate == 44100 || rate == 48000) &&
+ do_spdif = (rate >= 44100 &&
substream->runtime->format == SNDRV_PCM_FORMAT_S16_LE &&
substream->runtime->channels == 2);
if (do_spdif && cm->can_ac3_hw)
@@ -1252,11 +1306,75 @@ static int snd_cmipci_playback_spdif_prepare(struct snd_pcm_substream *substream
return snd_cmipci_pcm_prepare(cm, &cm->channel[CM_CH_PLAY], substream);
}
+/*
+ * Apparently, the samples last played on channel A stay in some buffer, even
+ * after the channel is reset, and get added to the data for the rear DACs when
+ * playing a multichannel stream on channel B. This is likely to generate
+ * wraparounds and thus distortions.
+ * To avoid this, we play at least one zero sample after the actual stream has
+ * stopped.
+ */
+static void snd_cmipci_silence_hack(struct cmipci *cm, struct cmipci_pcm *rec)
+{
+ struct snd_pcm_runtime *runtime = rec->substream->runtime;
+ unsigned int reg, val;
+
+ if (rec->needs_silencing && runtime && runtime->dma_area) {
+ /* set up a small silence buffer */
+ memset(runtime->dma_area, 0, PAGE_SIZE);
+ reg = rec->ch ? CM_REG_CH1_FRAME2 : CM_REG_CH0_FRAME2;
+ val = ((PAGE_SIZE / 4) - 1) | (((PAGE_SIZE / 4) / 2 - 1) << 16);
+ snd_cmipci_write(cm, reg, val);
+
+ /* configure for 16 bits, 2 channels, 8 kHz */
+ if (runtime->channels > 2)
+ set_dac_channels(cm, rec, 2);
+ spin_lock_irq(&cm->reg_lock);
+ val = snd_cmipci_read(cm, CM_REG_FUNCTRL1);
+ val &= ~(CM_ASFC_MASK << (rec->ch * 3));
+ val |= (4 << CM_ASFC_SHIFT) << (rec->ch * 3);
+ snd_cmipci_write(cm, CM_REG_FUNCTRL1, val);
+ val = snd_cmipci_read(cm, CM_REG_CHFORMAT);
+ val &= ~(CM_CH0FMT_MASK << (rec->ch * 2));
+ val |= (3 << CM_CH0FMT_SHIFT) << (rec->ch * 2);
+ if (cm->chip_version == 68) {
+ val &= ~(CM_CH0_SRATE_88K << (rec->ch * 2));
+ val &= ~(CM_CH0_SRATE_96K << (rec->ch * 2));
+ }
+ snd_cmipci_write(cm, CM_REG_CHFORMAT, val);
+
+ /* start stream (we don't need interrupts) */
+ cm->ctrl |= CM_CHEN0 << rec->ch;
+ snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl);
+ spin_unlock_irq(&cm->reg_lock);
+
+ msleep(1);
+
+ /* stop and reset stream */
+ spin_lock_irq(&cm->reg_lock);
+ cm->ctrl &= ~(CM_CHEN0 << rec->ch);
+ val = CM_RST_CH0 << rec->ch;
+ snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl | val);
+ snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl & ~val);
+ spin_unlock_irq(&cm->reg_lock);
+
+ rec->needs_silencing = 0;
+ }
+}
+
static int snd_cmipci_playback_hw_free(struct snd_pcm_substream *substream)
{
struct cmipci *cm = snd_pcm_substream_chip(substream);
setup_spdif_playback(cm, substream, 0, 0);
restore_mixer_state(cm);
+ snd_cmipci_silence_hack(cm, &cm->channel[0]);
+ return snd_cmipci_hw_free(substream);
+}
+
+static int snd_cmipci_playback2_hw_free(struct snd_pcm_substream *substream)
+{
+ struct cmipci *cm = snd_pcm_substream_chip(substream);
+ snd_cmipci_silence_hack(cm, &cm->channel[1]);
return snd_cmipci_hw_free(substream);
}
@@ -1515,7 +1633,11 @@ static int snd_cmipci_playback_open(struct snd_pcm_substream *substream)
if ((err = open_device_check(cm, CM_OPEN_PLAYBACK, substream)) < 0)
return err;
runtime->hw = snd_cmipci_playback;
- runtime->hw.channels_max = cm->max_channels;
+ if (cm->chip_version == 68) {
+ runtime->hw.rates |= SNDRV_PCM_RATE_88200 |
+ SNDRV_PCM_RATE_96000;
+ runtime->hw.rate_max = 96000;
+ }
snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000);
cm->dig_pcm_status = cm->dig_status;
return 0;
@@ -1558,9 +1680,14 @@ static int snd_cmipci_playback2_open(struct snd_pcm_substream *substream)
else if (cm->max_channels == 8)
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels_8);
}
- snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000);
}
mutex_unlock(&cm->open_mutex);
+ if (cm->chip_version == 68) {
+ runtime->hw.rates |= SNDRV_PCM_RATE_88200 |
+ SNDRV_PCM_RATE_96000;
+ runtime->hw.rate_max = 96000;
+ }
+ snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000);
return 0;
}
@@ -1574,8 +1701,15 @@ static int snd_cmipci_playback_spdif_open(struct snd_pcm_substream *substream)
return err;
if (cm->can_ac3_hw) {
runtime->hw = snd_cmipci_playback_spdif;
- if (cm->chip_version >= 37)
+ if (cm->chip_version >= 37) {
runtime->hw.formats |= SNDRV_PCM_FMTBIT_S32_LE;
+ snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
+ }
+ if (cm->chip_version == 68) {
+ runtime->hw.rates |= SNDRV_PCM_RATE_88200 |
+ SNDRV_PCM_RATE_96000;
+ runtime->hw.rate_max = 96000;
+ }
} else {
runtime->hw = snd_cmipci_playback_iec958_subframe;
}
@@ -1668,7 +1802,7 @@ static struct snd_pcm_ops snd_cmipci_playback2_ops = {
.close = snd_cmipci_playback2_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_cmipci_playback2_hw_params,
- .hw_free = snd_cmipci_hw_free,
+ .hw_free = snd_cmipci_playback2_hw_free,
.prepare = snd_cmipci_capture_prepare, /* channel B */
.trigger = snd_cmipci_capture_trigger, /* channel B */
.pointer = snd_cmipci_capture_pointer, /* channel B */
@@ -2139,15 +2273,7 @@ struct cmipci_switch_args {
*/
};
-static int snd_cmipci_uswitch_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_cmipci_uswitch_info snd_ctl_boolean_mono_info
static int _snd_cmipci_uswitch_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol,
@@ -2260,8 +2386,8 @@ DEFINE_SWITCH_ARG(exchange_dac, CM_REG_MISC_CTRL, CM_XCHGDAC, 0, 0, 0); /* rever
DEFINE_SWITCH_ARG(exchange_dac, CM_REG_MISC_CTRL, CM_XCHGDAC, CM_XCHGDAC, 0, 0);
#endif
DEFINE_BIT_SWITCH_ARG(fourch, CM_REG_MISC_CTRL, CM_N4SPK3D, 0, 0);
-// DEFINE_BIT_SWITCH_ARG(line_rear, CM_REG_MIXER1, CM_SPK4, 1, 0);
-// DEFINE_BIT_SWITCH_ARG(line_bass, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS, 0, 0);
+// DEFINE_BIT_SWITCH_ARG(line_rear, CM_REG_MIXER1, CM_REAR2LIN, 1, 0);
+// DEFINE_BIT_SWITCH_ARG(line_bass, CM_REG_LEGACY_CTRL, CM_CENTR2LIN|CM_BASE2LIN, 0, 0);
// DEFINE_BIT_SWITCH_ARG(joystick, CM_REG_FUNCTRL1, CM_JYSTK_EN, 0, 0); /* now module option */
DEFINE_SWITCH_ARG(modem, CM_REG_MISC_CTRL, CM_FLINKON|CM_FLINKOFF, CM_FLINKON, 0, 0);
@@ -2331,11 +2457,11 @@ static inline unsigned int get_line_in_mode(struct cmipci *cm)
unsigned int val;
if (cm->chip_version >= 39) {
val = snd_cmipci_read(cm, CM_REG_LEGACY_CTRL);
- if (val & CM_LINE_AS_BASS)
+ if (val & (CM_CENTR2LIN | CM_BASE2LIN))
return 2;
}
val = snd_cmipci_read_b(cm, CM_REG_MIXER1);
- if (val & CM_SPK4)
+ if (val & CM_REAR2LIN)
return 1;
return 0;
}
@@ -2359,13 +2485,13 @@ static int snd_cmipci_line_in_mode_put(struct snd_kcontrol *kcontrol,
spin_lock_irq(&cm->reg_lock);
if (ucontrol->value.enumerated.item[0] == 2)
- change = snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS);
+ change = snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_CENTR2LIN | CM_BASE2LIN);
else
- change = snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS);
+ change = snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_CENTR2LIN | CM_BASE2LIN);
if (ucontrol->value.enumerated.item[0] == 1)
- change |= snd_cmipci_set_bit_b(cm, CM_REG_MIXER1, CM_SPK4);
+ change |= snd_cmipci_set_bit_b(cm, CM_REG_MIXER1, CM_REAR2LIN);
else
- change |= snd_cmipci_clear_bit_b(cm, CM_REG_MIXER1, CM_SPK4);
+ change |= snd_cmipci_clear_bit_b(cm, CM_REG_MIXER1, CM_REAR2LIN);
spin_unlock_irq(&cm->reg_lock);
return change;
}
@@ -2583,19 +2709,18 @@ static void snd_cmipci_proc_read(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
struct cmipci *cm = entry->private_data;
- int i;
+ int i, v;
- snd_iprintf(buffer, "%s\n\n", cm->card->longname);
- for (i = 0; i < 0x40; i++) {
- int v = inb(cm->iobase + i);
+ snd_iprintf(buffer, "%s\n", cm->card->longname);
+ for (i = 0; i < 0x94; i++) {
+ if (i == 0x28)
+ i = 0x90;
+ v = inb(cm->iobase + i);
if (i % 4 == 0)
- snd_iprintf(buffer, "%02x: ", i);
- snd_iprintf(buffer, "%02x", v);
- if (i % 4 == 3)
- snd_iprintf(buffer, "\n");
- else
- snd_iprintf(buffer, " ");
+ snd_iprintf(buffer, "\n%02x:", i);
+ snd_iprintf(buffer, " %02x", v);
}
+ snd_iprintf(buffer, "\n");
}
static void __devinit snd_cmipci_proc_init(struct cmipci *cm)
@@ -2633,46 +2758,40 @@ static void __devinit query_chip(struct cmipci *cm)
if (! detect) {
/* check reg 08h, bit 24-28 */
detect = snd_cmipci_read(cm, CM_REG_CHFORMAT) & CM_CHIP_MASK1;
- if (! detect) {
+ switch (detect) {
+ case 0:
cm->chip_version = 33;
- cm->max_channels = 2;
if (cm->do_soft_ac3)
cm->can_ac3_sw = 1;
else
cm->can_ac3_hw = 1;
- cm->has_dual_dac = 1;
- } else {
+ break;
+ case CM_CHIP_037:
cm->chip_version = 37;
- cm->max_channels = 2;
cm->can_ac3_hw = 1;
- cm->has_dual_dac = 1;
+ break;
+ default:
+ cm->chip_version = 39;
+ cm->can_ac3_hw = 1;
+ break;
}
+ cm->max_channels = 2;
} else {
- /* check reg 0Ch, bit 26 */
- if (detect & CM_CHIP_8768) {
- cm->chip_version = 68;
- cm->max_channels = 8;
- cm->can_ac3_hw = 1;
- cm->has_dual_dac = 1;
- cm->can_multi_ch = 1;
- } else if (detect & CM_CHIP_055) {
- cm->chip_version = 55;
- cm->max_channels = 6;
- cm->can_ac3_hw = 1;
- cm->has_dual_dac = 1;
- cm->can_multi_ch = 1;
- } else if (detect & CM_CHIP_039) {
+ if (detect & CM_CHIP_039) {
cm->chip_version = 39;
if (detect & CM_CHIP_039_6CH) /* 4 or 6 channels */
cm->max_channels = 6;
else
cm->max_channels = 4;
- cm->can_ac3_hw = 1;
- cm->has_dual_dac = 1;
- cm->can_multi_ch = 1;
+ } else if (detect & CM_CHIP_8768) {
+ cm->chip_version = 68;
+ cm->max_channels = 8;
} else {
- printk(KERN_ERR "chip %x version not supported\n", detect);
+ cm->chip_version = 55;
+ cm->max_channels = 6;
}
+ cm->can_ac3_hw = 1;
+ cm->can_multi_ch = 1;
}
}
@@ -2782,10 +2901,14 @@ static int __devinit snd_cmipci_create_fm(struct cmipci *cm, long fm_port)
if (!fm_port)
goto disable_fm;
- /* first try FM regs in PCI port range */
- iosynth = cm->iobase + CM_REG_FM_PCI;
- err = snd_opl3_create(cm->card, iosynth, iosynth + 2,
- OPL3_HW_OPL3, 1, &opl3);
+ if (cm->chip_version >= 39) {
+ /* first try FM regs in PCI port range */
+ iosynth = cm->iobase + CM_REG_FM_PCI;
+ err = snd_opl3_create(cm->card, iosynth, iosynth + 2,
+ OPL3_HW_OPL3, 1, &opl3);
+ } else {
+ err = -EIO;
+ }
if (err < 0) {
/* then try legacy ports */
val = snd_cmipci_read(cm, CM_REG_LEGACY_CTRL) & ~CM_FMSEL_MASK;
@@ -2829,9 +2952,10 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc
static struct snd_device_ops ops = {
.dev_free = snd_cmipci_dev_free,
};
- unsigned int val = 0;
+ unsigned int val;
long iomidi;
- int integrated_midi;
+ int integrated_midi = 0;
+ char modelstr[16];
int pcm_index, pcm_spdif_index;
static struct pci_device_id intel_82437vx[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437VX) },
@@ -2904,6 +3028,8 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc
#endif
/* initialize codec registers */
+ snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_RESET);
+ snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_RESET);
snd_cmipci_write(cm, CM_REG_INT_HLDCLR, 0); /* disable ints */
snd_cmipci_ch_reset(cm, CM_CH_PLAY);
snd_cmipci_ch_reset(cm, CM_CH_CAPT);
@@ -2917,6 +3043,10 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc
#else
snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_XCHGDAC);
#endif
+ if (cm->chip_version) {
+ snd_cmipci_write_b(cm, CM_REG_EXT_MISC, 0x20); /* magic */
+ snd_cmipci_write_b(cm, CM_REG_EXT_MISC + 1, 0x09); /* more magic */
+ }
/* Set Bus Master Request */
snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_BREQ);
@@ -2931,15 +3061,55 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc
break;
}
+ if (cm->chip_version < 68) {
+ val = pci->device < 0x110 ? 8338 : 8738;
+ } else {
+ switch (snd_cmipci_read_b(cm, CM_REG_INT_HLDCLR + 3) & 0x03) {
+ case 0:
+ val = 8769;
+ break;
+ case 2:
+ val = 8762;
+ break;
+ default:
+ switch ((pci->subsystem_vendor << 16) |
+ pci->subsystem_device) {
+ case 0x13f69761:
+ case 0x584d3741:
+ case 0x584d3751:
+ case 0x584d3761:
+ case 0x584d3771:
+ case 0x72848384:
+ val = 8770;
+ break;
+ default:
+ val = 8768;
+ break;
+ }
+ }
+ }
+ sprintf(card->shortname, "C-Media CMI%d", val);
+ if (cm->chip_version < 68)
+ sprintf(modelstr, " (model %d)", cm->chip_version);
+ else
+ modelstr[0] = '\0';
+ sprintf(card->longname, "%s%s at %#lx, irq %i",
+ card->shortname, modelstr, cm->iobase, cm->irq);
+
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, cm, &ops)) < 0) {
snd_cmipci_free(cm);
return err;
}
- integrated_midi = snd_cmipci_read_b(cm, CM_REG_MPU_PCI) != 0xff;
- if (integrated_midi && mpu_port[dev] == 1)
- iomidi = cm->iobase + CM_REG_MPU_PCI;
- else {
+ if (cm->chip_version >= 39) {
+ val = snd_cmipci_read_b(cm, CM_REG_MPU_PCI + 1);
+ if (val != 0x00 && val != 0xff) {
+ iomidi = cm->iobase + CM_REG_MPU_PCI;
+ integrated_midi = 1;
+ }
+ }
+ if (!integrated_midi) {
+ val = 0;
iomidi = mpu_port[dev];
switch (iomidi) {
case 0x320: val = CM_VMPU_320; break;
@@ -2953,11 +3123,21 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc
snd_cmipci_write(cm, CM_REG_LEGACY_CTRL, val);
/* enable UART */
snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_UART_EN);
+ if (inb(iomidi + 1) == 0xff) {
+ snd_printk(KERN_ERR "cannot enable MPU-401 port"
+ " at %#lx\n", iomidi);
+ snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1,
+ CM_UART_EN);
+ iomidi = 0;
+ }
}
}
- if ((err = snd_cmipci_create_fm(cm, fm_port[dev])) < 0)
- return err;
+ if (cm->chip_version < 68) {
+ err = snd_cmipci_create_fm(cm, fm_port[dev]);
+ if (err < 0)
+ return err;
+ }
/* reset mixer */
snd_cmipci_mixer_write(cm, 0, 0);
@@ -2969,11 +3149,9 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc
if ((err = snd_cmipci_pcm_new(cm, pcm_index)) < 0)
return err;
pcm_index++;
- if (cm->has_dual_dac) {
- if ((err = snd_cmipci_pcm2_new(cm, pcm_index)) < 0)
- return err;
- pcm_index++;
- }
+ if ((err = snd_cmipci_pcm2_new(cm, pcm_index)) < 0)
+ return err;
+ pcm_index++;
if (cm->can_ac3_hw || cm->can_ac3_sw) {
pcm_spdif_index = pcm_index;
if ((err = snd_cmipci_pcm_spdif_new(cm, pcm_index)) < 0)
@@ -3057,15 +3235,6 @@ static int __devinit snd_cmipci_probe(struct pci_dev *pci,
}
card->private_data = cm;
- sprintf(card->shortname, "C-Media PCI %s", card->driver);
- sprintf(card->longname, "%s (model %d) at 0x%lx, irq %i",
- card->shortname,
- cm->chip_version,
- cm->iobase,
- cm->irq);
-
- //snd_printd("%s is detected\n", card->longname);
-
if ((err = snd_card_register(card)) < 0) {
snd_card_free(card);
return err;
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index 44cf54607647..9a55f4a9739b 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -1,6 +1,6 @@
/*
* Driver for Cirrus Logic CS4281 based PCI soundcard
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>,
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
*
*
* This program is free software; you can redistribute it and/or modify
@@ -38,7 +38,7 @@
#include <sound/initval.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Cirrus Logic CS4281");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Cirrus Logic,CS4281}}");
@@ -842,12 +842,11 @@ static snd_pcm_uframes_t snd_cs4281_pointer(struct snd_pcm_substream *substream)
static struct snd_pcm_hardware snd_cs4281_playback =
{
- .info = (SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_PAUSE |
- SNDRV_PCM_INFO_RESUME |
- SNDRV_PCM_INFO_SYNC_START),
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_RESUME,
.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_U16_BE | SNDRV_PCM_FMTBIT_S16_BE |
@@ -868,12 +867,11 @@ static struct snd_pcm_hardware snd_cs4281_playback =
static struct snd_pcm_hardware snd_cs4281_capture =
{
- .info = (SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_PAUSE |
- SNDRV_PCM_INFO_RESUME |
- SNDRV_PCM_INFO_SYNC_START),
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_RESUME,
.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_U16_BE | SNDRV_PCM_FMTBIT_S16_BE |
@@ -904,7 +902,6 @@ static int snd_cs4281_playback_open(struct snd_pcm_substream *substream)
dma->right_slot = 1;
runtime->private_data = dma;
runtime->hw = snd_cs4281_playback;
- snd_pcm_set_sync(substream);
/* should be detected from the AC'97 layer, but it seems
that although CS4297A rev B reports 18-bit ADC resolution,
samples are 20-bit */
@@ -924,7 +921,6 @@ static int snd_cs4281_capture_open(struct snd_pcm_substream *substream)
dma->right_slot = 11;
runtime->private_data = dma;
runtime->hw = snd_cs4281_capture;
- snd_pcm_set_sync(substream);
/* should be detected from the AC'97 layer, but it seems
that although CS4297A rev B reports 18-bit ADC resolution,
samples are 20-bit */
diff --git a/sound/pci/cs46xx/Makefile b/sound/pci/cs46xx/Makefile
index d8b77b89aec4..67e811ec8539 100644
--- a/sound/pci/cs46xx/Makefile
+++ b/sound/pci/cs46xx/Makefile
@@ -1,12 +1,10 @@
#
# Makefile for ALSA
-# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
-snd-cs46xx-objs := cs46xx.o cs46xx_lib.o
-ifeq ($(CONFIG_SND_CS46XX_NEW_DSP),y)
- snd-cs46xx-objs += dsp_spos.o dsp_spos_scb_lib.o
-endif
+snd-cs46xx-y := cs46xx.o cs46xx_lib.o
+snd-cs46xx-$(CONFIG_SND_CS46XX_NEW_DSP) += dsp_spos.o dsp_spos_scb_lib.o
# Toplevel Module Dependency
obj-$(CONFIG_SND_CS46XX) += snd-cs46xx.o
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c
index 8b6cd144d101..2699cb6c2cd6 100644
--- a/sound/pci/cs46xx/cs46xx.c
+++ b/sound/pci/cs46xx/cs46xx.c
@@ -1,6 +1,6 @@
/*
* The driver for the Cirrus Logic's Sound Fusion CS46XX based soundcards
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -34,7 +34,7 @@
#include <sound/cs46xx.h>
#include <sound/initval.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Cirrus Logic Sound Fusion CS46XX");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Cirrus Logic,Sound Fusion (CS4280)},"
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index 71d7aab9d869..2c7bfc9fef61 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Abramo Bagnara <abramo@alsa-project.org>
* Cirrus Logic, Inc.
* Routines for control of Cirrus Logic CS461x chips
@@ -1818,15 +1818,7 @@ static int snd_cs46xx_vol_iec958_put(struct snd_kcontrol *kcontrol, struct snd_c
}
#endif
-static int snd_mixer_boolean_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_mixer_boolean_info snd_ctl_boolean_mono_info
static int snd_cs46xx_iec958_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
diff --git a/sound/pci/cs46xx/cs46xx_lib.h b/sound/pci/cs46xx/cs46xx_lib.h
index 20dcd72f06c1..018a7de56017 100644
--- a/sound/pci/cs46xx/cs46xx_lib.h
+++ b/sound/pci/cs46xx/cs46xx_lib.h
@@ -1,6 +1,6 @@
/*
* The driver for the Cirrus Logic's Sound Fusion CS46XX based soundcards
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/pci/cs46xx/dsp_spos.h b/sound/pci/cs46xx/dsp_spos.h
index 0d246bca4184..f9e169d33c03 100644
--- a/sound/pci/cs46xx/dsp_spos.h
+++ b/sound/pci/cs46xx/dsp_spos.h
@@ -1,6 +1,6 @@
/*
* The driver for the Cirrus Logic's Sound Fusion CS46XX based soundcards
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c
index 57e357de1500..eded4dfeba12 100644
--- a/sound/pci/cs46xx/dsp_spos_scb_lib.c
+++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c
@@ -1480,7 +1480,7 @@ void cs46xx_dsp_destroy_pcm_channel (struct snd_cs46xx * chip,
if (!pcm_channel->src_scb->ref_count) {
cs46xx_dsp_remove_scb(chip,pcm_channel->src_scb);
- snd_assert (pcm_channel->src_slot >= 0 && pcm_channel->src_slot <= DSP_MAX_SRC_NR,
+ snd_assert (pcm_channel->src_slot >= 0 && pcm_channel->src_slot < DSP_MAX_SRC_NR,
return );
ins->src_scb_slots[pcm_channel->src_slot] = 0;
diff --git a/sound/pci/cs5535audio/Makefile b/sound/pci/cs5535audio/Makefile
index ad947b4c04cc..bb3d57e6a3cb 100644
--- a/sound/pci/cs5535audio/Makefile
+++ b/sound/pci/cs5535audio/Makefile
@@ -2,11 +2,8 @@
# Makefile for cs5535audio
#
-snd-cs5535audio-objs := cs5535audio.o cs5535audio_pcm.o
-
-ifeq ($(CONFIG_PM),y)
-snd-cs5535audio-objs += cs5535audio_pm.o
-endif
+snd-cs5535audio-y := cs5535audio.o cs5535audio_pcm.o
+snd-cs5535audio-$(CONFIG_PM) += cs5535audio_pm.o
# Toplevel Module Dependency
obj-$(CONFIG_SND_CS5535AUDIO) += snd-cs5535audio.o
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c
index b8e75ef9c1e6..2b35889787be 100644
--- a/sound/pci/cs5535audio/cs5535audio.c
+++ b/sound/pci/cs5535audio/cs5535audio.c
@@ -206,7 +206,6 @@ static void process_bm1_irq(struct cs5535audio *cs5535au)
static irqreturn_t snd_cs5535audio_interrupt(int irq, void *dev_id)
{
u16 acc_irq_stat;
- u8 bm_stat;
unsigned char count;
struct cs5535audio *cs5535au = dev_id;
@@ -217,7 +216,7 @@ static irqreturn_t snd_cs5535audio_interrupt(int irq, void *dev_id)
if (!acc_irq_stat)
return IRQ_NONE;
- for (count = 0; count < 10; count++) {
+ for (count = 0; count < 4; count++) {
if (acc_irq_stat & (1 << count)) {
switch (count) {
case IRQ_STS:
@@ -232,26 +231,9 @@ static irqreturn_t snd_cs5535audio_interrupt(int irq, void *dev_id)
case BM1_IRQ_STS:
process_bm1_irq(cs5535au);
break;
- case BM2_IRQ_STS:
- bm_stat = cs_readb(cs5535au, ACC_BM2_STATUS);
- break;
- case BM3_IRQ_STS:
- bm_stat = cs_readb(cs5535au, ACC_BM3_STATUS);
- break;
- case BM4_IRQ_STS:
- bm_stat = cs_readb(cs5535au, ACC_BM4_STATUS);
- break;
- case BM5_IRQ_STS:
- bm_stat = cs_readb(cs5535au, ACC_BM5_STATUS);
- break;
- case BM6_IRQ_STS:
- bm_stat = cs_readb(cs5535au, ACC_BM6_STATUS);
- break;
- case BM7_IRQ_STS:
- bm_stat = cs_readb(cs5535au, ACC_BM7_STATUS);
- break;
default:
- snd_printk(KERN_ERR "Unexpected irq src\n");
+ snd_printk(KERN_ERR "Unexpected irq src: "
+ "0x%x\n", acc_irq_stat);
break;
}
}
diff --git a/sound/pci/cs5535audio/cs5535audio.h b/sound/pci/cs5535audio/cs5535audio.h
index 4fd1f31a6cf9..66bae7664193 100644
--- a/sound/pci/cs5535audio/cs5535audio.h
+++ b/sound/pci/cs5535audio/cs5535audio.h
@@ -16,57 +16,28 @@
#define ACC_IRQ_STATUS 0x12
#define ACC_BM0_CMD 0x20
#define ACC_BM1_CMD 0x28
-#define ACC_BM2_CMD 0x30
-#define ACC_BM3_CMD 0x38
-#define ACC_BM4_CMD 0x40
-#define ACC_BM5_CMD 0x48
-#define ACC_BM6_CMD 0x50
-#define ACC_BM7_CMD 0x58
#define ACC_BM0_PRD 0x24
#define ACC_BM1_PRD 0x2C
-#define ACC_BM2_PRD 0x34
-#define ACC_BM3_PRD 0x3C
-#define ACC_BM4_PRD 0x44
-#define ACC_BM5_PRD 0x4C
-#define ACC_BM6_PRD 0x54
-#define ACC_BM7_PRD 0x5C
#define ACC_BM0_STATUS 0x21
#define ACC_BM1_STATUS 0x29
-#define ACC_BM2_STATUS 0x31
-#define ACC_BM3_STATUS 0x39
-#define ACC_BM4_STATUS 0x41
-#define ACC_BM5_STATUS 0x49
-#define ACC_BM6_STATUS 0x51
-#define ACC_BM7_STATUS 0x59
#define ACC_BM0_PNTR 0x60
#define ACC_BM1_PNTR 0x64
-#define ACC_BM2_PNTR 0x68
-#define ACC_BM3_PNTR 0x6C
-#define ACC_BM4_PNTR 0x70
-#define ACC_BM5_PNTR 0x74
-#define ACC_BM6_PNTR 0x78
-#define ACC_BM7_PNTR 0x7C
+
/* acc_codec bar0 reg bits */
/* ACC_IRQ_STATUS */
#define IRQ_STS 0
#define WU_IRQ_STS 1
#define BM0_IRQ_STS 2
#define BM1_IRQ_STS 3
-#define BM2_IRQ_STS 4
-#define BM3_IRQ_STS 5
-#define BM4_IRQ_STS 6
-#define BM5_IRQ_STS 7
-#define BM6_IRQ_STS 8
-#define BM7_IRQ_STS 9
/* ACC_BMX_STATUS */
#define EOP (1<<0)
#define BM_EOP_ERR (1<<1)
/* ACC_BMX_CTL */
-#define BM_CTL_EN 0x00000001
-#define BM_CTL_PAUSE 0x00000011
-#define BM_CTL_DIS 0x00000000
-#define BM_CTL_BYTE_ORD_LE 0x00000000
-#define BM_CTL_BYTE_ORD_BE 0x00000100
+#define BM_CTL_EN 0x01
+#define BM_CTL_PAUSE 0x03
+#define BM_CTL_DIS 0x00
+#define BM_CTL_BYTE_ORD_LE 0x00
+#define BM_CTL_BYTE_ORD_BE 0x04
/* cs5535 specific ac97 codec register defines */
#define CMD_MASK 0xFF00FFFF
#define CMD_NEW 0x00010000
@@ -106,7 +77,6 @@ struct cs5535audio_dma {
struct snd_pcm_substream *substream;
unsigned int buf_addr, buf_bytes;
unsigned int period_bytes, periods;
- int suspended;
u32 saved_prd;
};
diff --git a/sound/pci/cs5535audio/cs5535audio_pcm.c b/sound/pci/cs5535audio/cs5535audio_pcm.c
index 5450a9e8f133..21df0634af32 100644
--- a/sound/pci/cs5535audio/cs5535audio_pcm.c
+++ b/sound/pci/cs5535audio/cs5535audio_pcm.c
@@ -43,7 +43,6 @@ static struct snd_pcm_hardware snd_cs5535audio_playback =
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_PAUSE |
- SNDRV_PCM_INFO_SYNC_START |
SNDRV_PCM_INFO_RESUME
),
.formats = (
@@ -71,8 +70,7 @@ static struct snd_pcm_hardware snd_cs5535audio_capture =
SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_SYNC_START
+ SNDRV_PCM_INFO_MMAP_VALID
),
.formats = (
SNDRV_PCM_FMTBIT_S16_LE
@@ -102,7 +100,6 @@ static int snd_cs5535audio_playback_open(struct snd_pcm_substream *substream)
runtime->hw = snd_cs5535audio_playback;
cs5535au->playback_substream = substream;
runtime->private_data = &(cs5535au->dmas[CS5535AUDIO_DMA_PLAYBACK]);
- snd_pcm_set_sync(substream);
if ((err = snd_pcm_hw_constraint_integer(runtime,
SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
return err;
@@ -164,6 +161,7 @@ static int cs5535audio_build_dma_packets(struct cs5535audio *cs5535au,
jmpprd_addr = cpu_to_le32(lastdesc->addr +
(sizeof(struct cs5535audio_dma_desc)*periods));
+ dma->substream = substream;
dma->period_bytes = period_bytes;
dma->periods = periods;
spin_lock_irq(&cs5535au->reg_lock);
@@ -241,6 +239,7 @@ static void cs5535audio_clear_dma_packets(struct cs5535audio *cs5535au,
{
snd_dma_free_pages(&dma->desc_buf);
dma->desc_buf.area = NULL;
+ dma->substream = NULL;
}
static int snd_cs5535audio_hw_params(struct snd_pcm_substream *substream,
@@ -298,14 +297,12 @@ static int snd_cs5535audio_trigger(struct snd_pcm_substream *substream, int cmd)
break;
case SNDRV_PCM_TRIGGER_RESUME:
dma->ops->enable_dma(cs5535au);
- dma->suspended = 0;
break;
case SNDRV_PCM_TRIGGER_STOP:
dma->ops->disable_dma(cs5535au);
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
dma->ops->disable_dma(cs5535au);
- dma->suspended = 1;
break;
default:
snd_printk(KERN_ERR "unhandled trigger\n");
@@ -348,7 +345,6 @@ static int snd_cs5535audio_capture_open(struct snd_pcm_substream *substream)
runtime->hw = snd_cs5535audio_capture;
cs5535au->capture_substream = substream;
runtime->private_data = &(cs5535au->dmas[CS5535AUDIO_DMA_CAPTURE]);
- snd_pcm_set_sync(substream);
if ((err = snd_pcm_hw_constraint_integer(runtime,
SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
return err;
diff --git a/sound/pci/cs5535audio/cs5535audio_pm.c b/sound/pci/cs5535audio/cs5535audio_pm.c
index 3e4d198a4502..838708f6d45e 100644
--- a/sound/pci/cs5535audio/cs5535audio_pm.c
+++ b/sound/pci/cs5535audio/cs5535audio_pm.c
@@ -64,18 +64,21 @@ int snd_cs5535audio_suspend(struct pci_dev *pci, pm_message_t state)
int i;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+ snd_pcm_suspend_all(cs5535au->pcm);
+ snd_ac97_suspend(cs5535au->ac97);
for (i = 0; i < NUM_CS5535AUDIO_DMAS; i++) {
struct cs5535audio_dma *dma = &cs5535au->dmas[i];
- if (dma && dma->substream && !dma->suspended)
+ if (dma && dma->substream)
dma->saved_prd = dma->ops->read_prd(cs5535au);
}
- snd_pcm_suspend_all(cs5535au->pcm);
- snd_ac97_suspend(cs5535au->ac97);
/* save important regs, then disable aclink in hw */
snd_cs5535audio_stop_hardware(cs5535au);
+ if (pci_save_state(pci)) {
+ printk(KERN_ERR "cs5535audio: pci_save_state failed!\n");
+ return -EIO;
+ }
pci_disable_device(pci);
- pci_save_state(pci);
pci_set_power_state(pci, pci_choose_state(pci, state));
return 0;
}
@@ -89,7 +92,12 @@ int snd_cs5535audio_resume(struct pci_dev *pci)
int i;
pci_set_power_state(pci, PCI_D0);
- pci_restore_state(pci);
+ if (pci_restore_state(pci) < 0) {
+ printk(KERN_ERR "cs5535audio: pci_restore_state failed, "
+ "disabling device\n");
+ snd_card_disconnect(card);
+ return -EIO;
+ }
if (pci_enable_device(pci) < 0) {
printk(KERN_ERR "cs5535audio: pci_enable_device failed, "
"disabling device\n");
@@ -112,17 +120,17 @@ int snd_cs5535audio_resume(struct pci_dev *pci)
if (!timeout)
snd_printk(KERN_ERR "Failure getting AC Link ready\n");
- /* we depend on ac97 to perform the codec power up */
- snd_ac97_resume(cs5535au->ac97);
/* set up rate regs, dma. actual initiation is done in trig */
for (i = 0; i < NUM_CS5535AUDIO_DMAS; i++) {
struct cs5535audio_dma *dma = &cs5535au->dmas[i];
- if (dma && dma->substream && dma->suspended) {
+ if (dma && dma->substream) {
dma->substream->ops->prepare(dma->substream);
dma->ops->setup_prd(cs5535au, dma->saved_prd);
}
}
-
+
+ /* we depend on ac97 to perform the codec power up */
+ snd_ac97_resume(cs5535au->ac97);
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
index f27b6a733b96..499ee1a5319d 100644
--- a/sound/pci/echoaudio/echoaudio.c
+++ b/sound/pci/echoaudio/echoaudio.c
@@ -1595,15 +1595,7 @@ static struct snd_kcontrol_new snd_echo_clock_source_switch __devinitdata = {
#ifdef ECHOCARD_HAS_PHANTOM_POWER
/******************* Phantom power switch *******************/
-static int snd_echo_phantom_power_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_echo_phantom_power_info snd_ctl_boolean_mono_info
static int snd_echo_phantom_power_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -1646,15 +1638,7 @@ static struct snd_kcontrol_new snd_echo_phantom_power_switch __devinitdata = {
#ifdef ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE
/******************* Digital input automute switch *******************/
-static int snd_echo_automute_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_echo_automute_info snd_ctl_boolean_mono_info
static int snd_echo_automute_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -1695,18 +1679,7 @@ static struct snd_kcontrol_new snd_echo_automute_switch __devinitdata = {
/******************* VU-meters switch *******************/
-static int snd_echo_vumeters_switch_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct echoaudio *chip;
-
- chip = snd_kcontrol_chip(kcontrol);
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_echo_vumeters_switch_info snd_ctl_boolean_mono_info
static int snd_echo_vumeters_switch_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
diff --git a/sound/pci/echoaudio/echoaudio_dsp.c b/sound/pci/echoaudio/echoaudio_dsp.c
index 42afa837d9b4..e6c100770392 100644
--- a/sound/pci/echoaudio/echoaudio_dsp.c
+++ b/sound/pci/echoaudio/echoaudio_dsp.c
@@ -43,11 +43,11 @@ static int wait_handshake(struct echoaudio *chip)
{
int i;
- /* Wait up to 10ms for the handshake from the DSP */
+ /* Wait up to 20ms for the handshake from the DSP */
for (i = 0; i < HANDSHAKE_TIMEOUT; i++) {
/* Look for the handshake value */
+ barrier();
if (chip->comm_page->handshake) {
- /*if (i) DE_ACT(("Handshake time: %d\n", i));*/
return 0;
}
udelay(1);
diff --git a/sound/pci/echoaudio/echoaudio_dsp.h b/sound/pci/echoaudio/echoaudio_dsp.h
index e55ee00991ac..e352f3ae292c 100644
--- a/sound/pci/echoaudio/echoaudio_dsp.h
+++ b/sound/pci/echoaudio/echoaudio_dsp.h
@@ -642,18 +642,18 @@ struct comm_page { /* Base Length*/
u32 flags; /* See Appendix A below 0x004 4 */
u32 unused; /* Unused entry 0x008 4 */
u32 sample_rate; /* Card sample rate in Hz 0x00c 4 */
- volatile u32 handshake; /* DSP command handshake 0x010 4 */
+ u32 handshake; /* DSP command handshake 0x010 4 */
u32 cmd_start; /* Chs. to start mask 0x014 4 */
u32 cmd_stop; /* Chs. to stop mask 0x018 4 */
u32 cmd_reset; /* Chs. to reset mask 0x01c 4 */
u16 audio_format[DSP_MAXPIPES]; /* Chs. audio format 0x020 32*2 */
struct sg_entry sglist_addr[DSP_MAXPIPES];
/* Chs. Physical sglist addrs 0x060 32*8 */
- volatile u32 position[DSP_MAXPIPES];
+ u32 position[DSP_MAXPIPES];
/* Positions for ea. ch. 0x160 32*4 */
- volatile s8 vu_meter[DSP_MAXPIPES];
+ s8 vu_meter[DSP_MAXPIPES];
/* VU meters 0x1e0 32*1 */
- volatile s8 peak_meter[DSP_MAXPIPES];
+ s8 peak_meter[DSP_MAXPIPES];
/* Peak meters 0x200 32*1 */
s8 line_out_level[DSP_MAXAUDIOOUTPUTS];
/* Output gain 0x220 16*1 */
@@ -665,7 +665,7 @@ struct comm_page { /* Base Length*/
/* Gina/Darla play filters - obsolete 0x3c0 168*4 */
u32 rec_coeff[MAX_REC_TAPS];
/* Gina/Darla record filters - obsolete 0x660 192*4 */
- volatile u16 midi_input[MIDI_IN_BUFFER_SIZE];
+ u16 midi_input[MIDI_IN_BUFFER_SIZE];
/* MIDI input data transfer buffer 0x960 256*2 */
u8 gd_clock_state; /* Chg Gina/Darla clock state 0xb60 1 */
u8 gd_spdif_status; /* Chg. Gina/Darla S/PDIF state 0xb61 1 */
@@ -674,11 +674,10 @@ struct comm_page { /* Base Length*/
u32 nominal_level_mask; /* -10 level enable mask 0xb64 4 */
u16 input_clock; /* Chg. Input clock state 0xb68 2 */
u16 output_clock; /* Chg. Output clock state 0xb6a 2 */
- volatile u32 status_clocks;
- /* Current Input clock state 0xb6c 4 */
+ u32 status_clocks; /* Current Input clock state 0xb6c 4 */
u32 ext_box_status; /* External box status 0xb70 4 */
u32 cmd_add_buffer; /* Pipes to add (obsolete) 0xb74 4 */
- volatile u32 midi_out_free_count;
+ u32 midi_out_free_count;
/* # of bytes free in MIDI output FIFO 0xb78 4 */
u32 unused2; /* Cyclic pipes 0xb7c 4 */
u32 control_register;
diff --git a/sound/pci/emu10k1/Makefile b/sound/pci/emu10k1/Makefile
index e521c38cef45..cf2d5636d8be 100644
--- a/sound/pci/emu10k1/Makefile
+++ b/sound/pci/emu10k1/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
snd-emu10k1-objs := emu10k1.o emu10k1_main.o \
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
index 55caf341933a..9680caff90c8 100644
--- a/sound/pci/emu10k1/emu10k1.c
+++ b/sound/pci/emu10k1/emu10k1.c
@@ -1,6 +1,6 @@
/*
* The driver for the EMU10K1 (SB Live!) based soundcards
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
* Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk>
* Added support for Audigy 2 Value.
@@ -32,7 +32,7 @@
#include <sound/emu10k1.h>
#include <sound/initval.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("EMU10K1");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB Live!/PCI512/E-mu APS},"
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index 404ae1be0a4b..97c41d72a255 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Creative Labs, Inc.
* Routines for control of EMU10K1 chips
*
@@ -31,6 +31,8 @@
*
*/
+#include <linux/sched.h>
+#include <linux/kthread.h>
#include <sound/driver.h>
#include <linux/delay.h>
#include <linux/init.h>
@@ -702,6 +704,65 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 * emu, const char * file
return 0;
}
+int emu1010_firmware_thread(void *data) {
+ struct snd_emu10k1 * emu = data;
+ int tmp,tmp2;
+ int reg;
+ int err;
+
+ for (;;) {
+ /* Delay to allow Audio Dock to settle */
+ msleep(1000);
+ if (kthread_should_stop())
+ break;
+ snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp ); /* IRQ Status */
+ snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg ); /* OPTIONS: Which cards are attached to the EMU */
+ if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) {
+ /* Audio Dock attached */
+ /* Return to Audio Dock programming mode */
+ snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware\n");
+ snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK );
+ if (emu->card_capabilities->emu1010 == 1) {
+ if ((err = snd_emu1010_load_firmware(emu, DOCK_FILENAME)) != 0) {
+ return err;
+ }
+ } else if (emu->card_capabilities->emu1010 == 2) {
+ if ((err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME)) != 0) {
+ return err;
+ }
+ } else if (emu->card_capabilities->emu1010 == 3) {
+ if ((err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME)) != 0) {
+ return err;
+ }
+ }
+
+ snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0 );
+ snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &reg );
+ snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_IRQ_STATUS=0x%x\n",reg);
+ /* ID, should read & 0x7f = 0x55 when FPGA programmed. */
+ snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg );
+ snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_ID=0x%x\n",reg);
+ if ((reg & 0x1f) != 0x15) {
+ /* FPGA failed to be programmed */
+ snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware file failed, reg=0x%x\n", reg);
+ return 0;
+ return -ENODEV;
+ }
+ snd_printk(KERN_INFO "emu1010: Audio Dock Firmware loaded\n");
+ snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp );
+ snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2 );
+ snd_printk("Audio Dock ver:%d.%d\n",tmp ,tmp2);
+ /* Sync clocking between 1010 and Dock */
+ /* Allow DLL to settle */
+ msleep(10);
+ /* Unmute all. Default is muted after a firmware load */
+ snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
+ break;
+ }
+ }
+ return 0;
+}
+
/*
* EMU-1010 - details found out from this driver, official MS Win drivers,
* testing the card:
@@ -817,8 +878,16 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu)
snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg );
snd_printk(KERN_INFO "emu1010: Card options=0x%x\n",reg);
snd_emu1010_fpga_read(emu, EMU_HANA_OPTICAL_TYPE, &tmp );
- /* ADAT input. */
- snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, 0x01 );
+ /* Optical -> ADAT I/O */
+ /* 0 : SPDIF
+ * 1 : ADAT
+ */
+ emu->emu1010.optical_in = 1; /* IN_ADAT */
+ emu->emu1010.optical_out = 1; /* IN_ADAT */
+ tmp = 0;
+ tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : 0) |
+ (emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : 0);
+ snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp );
snd_emu1010_fpga_read(emu, EMU_HANA_ADC_PADS, &tmp );
/* Set no attenuation on Audio Dock pads. */
snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, 0x00 );
@@ -1004,49 +1073,12 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu)
snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp );
snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10 ); /* SPDIF Format spdif (or 0x11 for aes/ebu) */
- /* Delay to allow Audio Dock to settle */
- msleep(100);
- snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp ); /* IRQ Status */
- snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg ); /* OPTIONS: Which cards are attached to the EMU */
- /* FIXME: The loading of this should be able to happen any time,
- * as the user can plug/unplug it at any time
- */
- if (reg & (EMU_HANA_OPTION_DOCK_ONLINE | EMU_HANA_OPTION_DOCK_OFFLINE) ) {
- /* Audio Dock attached */
- /* Return to Audio Dock programming mode */
- snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware\n");
- snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK );
- if (emu->card_capabilities->emu1010 == 1) {
- if ((err = snd_emu1010_load_firmware(emu, DOCK_FILENAME)) != 0) {
- return err;
- }
- } else if (emu->card_capabilities->emu1010 == 2) {
- if ((err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME)) != 0) {
- return err;
- }
- } else if (emu->card_capabilities->emu1010 == 3) {
- if ((err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME)) != 0) {
- return err;
- }
- }
+ /* Start Micro/Audio Dock firmware loader thread */
+ emu->emu1010.firmware_thread = kthread_create(&emu1010_firmware_thread,
+ emu,
+ "emu1010_firmware");
+ wake_up_process(emu->emu1010.firmware_thread);
- snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0 );
- snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &reg );
- snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_IRQ_STATUS=0x%x\n",reg);
- /* ID, should read & 0x7f = 0x55 when FPGA programmed. */
- snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg );
- snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_ID=0x%x\n",reg);
- if ((reg & 0x3f) != 0x15) {
- /* FPGA failed to be programmed */
- snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware file failed, reg=0x%x\n", reg);
- return 0;
- return -ENODEV;
- }
- snd_printk(KERN_INFO "emu1010: Audio Dock Firmware loaded\n");
- snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp );
- snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2 );
- snd_printk("Audio Dock ver:%d.%d\n",tmp ,tmp2);
- }
#if 0
snd_emu1010_fpga_link_dst_src_write(emu,
EMU_DST_HAMOA_DAC_LEFT1, EMU_SRC_ALICE_EMU32B + 2); /* ALICE2 bus 0xa2 */
@@ -1132,7 +1164,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu)
emu->emu1010.output_source[23] = 28;
/* TEMP: Select SPDIF in/out */
- snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, 0x0); /* Output spdif */
+ //snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, 0x0); /* Output spdif */
/* TEMP: Select 48kHz SPDIF out */
snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x0); /* Mute all */
@@ -1173,6 +1205,7 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
if (emu->card_capabilities->emu1010) {
/* Disable 48Volt power to Audio Dock */
snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0 );
+ kthread_stop(emu->emu1010.firmware_thread);
}
if (emu->memhdr)
snd_util_memhdr_free(emu->memhdr);
@@ -1722,8 +1755,9 @@ int __devinit snd_emu10k1_create(struct snd_card *card,
goto error;
}
- emu->page_ptr_table = (void **)vmalloc(emu->max_cache_pages * sizeof(void*));
- emu->page_addr_table = (unsigned long*)vmalloc(emu->max_cache_pages * sizeof(unsigned long));
+ emu->page_ptr_table = vmalloc(emu->max_cache_pages * sizeof(void *));
+ emu->page_addr_table = vmalloc(emu->max_cache_pages *
+ sizeof(unsigned long));
if (emu->page_ptr_table == NULL || emu->page_addr_table == NULL) {
err = -ENOMEM;
goto error;
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index e4af7a9b808c..1ec7ebaff9e9 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -1062,14 +1062,7 @@ static int __devinit snd_emu10k1x_proc_init(struct emu10k1x * emu)
return 0;
}
-static int snd_emu10k1x_shared_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_emu10k1x_shared_spdif_info snd_ctl_boolean_mono_info
static int snd_emu10k1x_shared_spdif_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c
index 7206c0fa06f2..9bf1cd592199 100644
--- a/sound/pci/emu10k1/emufx.c
+++ b/sound/pci/emu10k1/emufx.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Creative Labs, Inc.
* Routines for effect processor FX8010
*
@@ -642,10 +642,8 @@ snd_emu10k1_look_for_ctl(struct snd_emu10k1 *emu, struct snd_ctl_elem_id *id)
{
struct snd_emu10k1_fx8010_ctl *ctl;
struct snd_kcontrol *kcontrol;
- struct list_head *list;
-
- list_for_each(list, &emu->fx8010.gpr_ctl) {
- ctl = emu10k1_gpr_ctl(list);
+
+ list_for_each_entry(ctl, &emu->fx8010.gpr_ctl, list) {
kcontrol = ctl->kcontrol;
if (kcontrol->id.iface == id->iface &&
!strcmp(kcontrol->id.name, id->name) &&
@@ -895,14 +893,12 @@ static int snd_emu10k1_list_controls(struct snd_emu10k1 *emu,
struct snd_emu10k1_fx8010_control_gpr *gctl;
struct snd_emu10k1_fx8010_ctl *ctl;
struct snd_ctl_elem_id *id;
- struct list_head *list;
gctl = kmalloc(sizeof(*gctl), GFP_KERNEL);
if (! gctl)
return -ENOMEM;
- list_for_each(list, &emu->fx8010.gpr_ctl) {
- ctl = emu10k1_gpr_ctl(list);
+ list_for_each_entry(ctl, &emu->fx8010.gpr_ctl, list) {
total++;
if (icode->gpr_list_controls &&
i < icode->gpr_list_control_count) {
@@ -1207,7 +1203,7 @@ static int __devinit _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu)
A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_FRONT));
snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Front Playback Volume", gpr, 100);
gpr += 2;
-
+
/* PCM Surround Playback (independent from stereo mix) */
A_OP(icode, &ptr, iMAC0, A_GPR(playback+2), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_REAR));
A_OP(icode, &ptr, iMAC0, A_GPR(playback+3), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_REAR));
@@ -1267,8 +1263,16 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
/* emu1212 DSP 0 and DSP 1 Capture */
if (emu->card_capabilities->emu1010) {
- A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_P16VIN(0x0));
- A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_P16VIN(0x1));
+ if (emu->card_capabilities->ca0108_chip) {
+ /* Note:JCD:No longer bit shift lower 16bits to upper 16bits of 32bit value. */
+ A_OP(icode, &ptr, iMACINT0, A_GPR(tmp), A_C_00000000, A3_EMU32IN(0x0), A_C_00000001);
+ A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_GPR(tmp));
+ A_OP(icode, &ptr, iMACINT0, A_GPR(tmp), A_C_00000000, A3_EMU32IN(0x1), A_C_00000001);
+ A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr), A_GPR(tmp));
+ } else {
+ A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_P16VIN(0x0));
+ A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_P16VIN(0x1));
+ }
snd_emu10k1_init_stereo_control(&controls[nctl++], "EMU Capture Volume", gpr, 0);
gpr += 2;
}
@@ -1516,7 +1520,11 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
/* EMU1010 Outputs from PCM Front, Rear, Center, LFE, Side */
snd_printk("EMU outputs on\n");
for (z = 0; z < 8; z++) {
- A_OP(icode, &ptr, iACC3, A_EMU32OUTL(z), A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_C_00000000, A_C_00000000);
+ if (emu->card_capabilities->ca0108_chip) {
+ A_OP(icode, &ptr, iACC3, A3_EMU32OUT(z), A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_C_00000000, A_C_00000000);
+ } else {
+ A_OP(icode, &ptr, iACC3, A_EMU32OUTL(z), A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_C_00000000, A_C_00000000);
+ }
}
}
@@ -1557,106 +1565,116 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
#endif
if (emu->card_capabilities->emu1010) {
- snd_printk("EMU inputs on\n");
- /* Capture 16 (originally 8) channels of S32_LE sound */
-
- /* printk("emufx.c: gpr=0x%x, tmp=0x%x\n",gpr, tmp); */
- /* For the EMU1010: How to get 32bit values from the DSP. High 16bits into L, low 16bits into R. */
- /* A_P16VIN(0) is delayed by one sample,
- * so all other A_P16VIN channels will need to also be delayed
- */
- /* Left ADC in. 1 of 2 */
- snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_P16VIN(0x0), A_FXBUS2(0) );
- /* Right ADC in 1 of 2 */
- gpr_map[gpr++] = 0x00000000;
- /* Delaying by one sample: instead of copying the input
- * value A_P16VIN to output A_FXBUS2 as in the first channel,
- * we use an auxiliary register, delaying the value by one
- * sample
- */
- snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(2) );
- A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x1), A_C_00000000, A_C_00000000);
- gpr_map[gpr++] = 0x00000000;
- snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(4) );
- A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x2), A_C_00000000, A_C_00000000);
- gpr_map[gpr++] = 0x00000000;
- snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(6) );
- A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x3), A_C_00000000, A_C_00000000);
- /* For 96kHz mode */
- /* Left ADC in. 2 of 2 */
- gpr_map[gpr++] = 0x00000000;
- snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0x8) );
- A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x4), A_C_00000000, A_C_00000000);
- /* Right ADC in 2 of 2 */
- gpr_map[gpr++] = 0x00000000;
- snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xa) );
- A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x5), A_C_00000000, A_C_00000000);
- gpr_map[gpr++] = 0x00000000;
- snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xc) );
- A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x6), A_C_00000000, A_C_00000000);
- gpr_map[gpr++] = 0x00000000;
- snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xe) );
- A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x7), A_C_00000000, A_C_00000000);
- /* Pavel Hofman - we still have voices, A_FXBUS2s, and
- * A_P16VINs available -
- * let's add 8 more capture channels - total of 16
- */
- gpr_map[gpr++] = 0x00000000;
- snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
- bit_shifter16,
- A_GPR(gpr - 1),
- A_FXBUS2(0x10));
- A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x8),
- A_C_00000000, A_C_00000000);
- gpr_map[gpr++] = 0x00000000;
- snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
- bit_shifter16,
- A_GPR(gpr - 1),
- A_FXBUS2(0x12));
- A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x9),
- A_C_00000000, A_C_00000000);
- gpr_map[gpr++] = 0x00000000;
- snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
- bit_shifter16,
- A_GPR(gpr - 1),
- A_FXBUS2(0x14));
- A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xa),
- A_C_00000000, A_C_00000000);
- gpr_map[gpr++] = 0x00000000;
- snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
- bit_shifter16,
- A_GPR(gpr - 1),
- A_FXBUS2(0x16));
- A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xb),
- A_C_00000000, A_C_00000000);
- gpr_map[gpr++] = 0x00000000;
- snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
- bit_shifter16,
- A_GPR(gpr - 1),
- A_FXBUS2(0x18));
- A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xc),
- A_C_00000000, A_C_00000000);
- gpr_map[gpr++] = 0x00000000;
- snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
- bit_shifter16,
- A_GPR(gpr - 1),
- A_FXBUS2(0x1a));
- A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xd),
- A_C_00000000, A_C_00000000);
- gpr_map[gpr++] = 0x00000000;
- snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
- bit_shifter16,
- A_GPR(gpr - 1),
- A_FXBUS2(0x1c));
- A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xe),
- A_C_00000000, A_C_00000000);
- gpr_map[gpr++] = 0x00000000;
- snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
- bit_shifter16,
- A_GPR(gpr - 1),
- A_FXBUS2(0x1e));
- A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xf),
- A_C_00000000, A_C_00000000);
+ if (emu->card_capabilities->ca0108_chip) {
+ snd_printk("EMU2 inputs on\n");
+ for (z = 0; z < 0x10; z++) {
+ snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp,
+ bit_shifter16,
+ A3_EMU32IN(z),
+ A_FXBUS2(z*2) );
+ }
+ } else {
+ snd_printk("EMU inputs on\n");
+ /* Capture 16 (originally 8) channels of S32_LE sound */
+
+ /* printk("emufx.c: gpr=0x%x, tmp=0x%x\n",gpr, tmp); */
+ /* For the EMU1010: How to get 32bit values from the DSP. High 16bits into L, low 16bits into R. */
+ /* A_P16VIN(0) is delayed by one sample,
+ * so all other A_P16VIN channels will need to also be delayed
+ */
+ /* Left ADC in. 1 of 2 */
+ snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_P16VIN(0x0), A_FXBUS2(0) );
+ /* Right ADC in 1 of 2 */
+ gpr_map[gpr++] = 0x00000000;
+ /* Delaying by one sample: instead of copying the input
+ * value A_P16VIN to output A_FXBUS2 as in the first channel,
+ * we use an auxiliary register, delaying the value by one
+ * sample
+ */
+ snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(2) );
+ A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x1), A_C_00000000, A_C_00000000);
+ gpr_map[gpr++] = 0x00000000;
+ snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(4) );
+ A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x2), A_C_00000000, A_C_00000000);
+ gpr_map[gpr++] = 0x00000000;
+ snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(6) );
+ A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x3), A_C_00000000, A_C_00000000);
+ /* For 96kHz mode */
+ /* Left ADC in. 2 of 2 */
+ gpr_map[gpr++] = 0x00000000;
+ snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0x8) );
+ A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x4), A_C_00000000, A_C_00000000);
+ /* Right ADC in 2 of 2 */
+ gpr_map[gpr++] = 0x00000000;
+ snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xa) );
+ A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x5), A_C_00000000, A_C_00000000);
+ gpr_map[gpr++] = 0x00000000;
+ snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xc) );
+ A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x6), A_C_00000000, A_C_00000000);
+ gpr_map[gpr++] = 0x00000000;
+ snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xe) );
+ A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x7), A_C_00000000, A_C_00000000);
+ /* Pavel Hofman - we still have voices, A_FXBUS2s, and
+ * A_P16VINs available -
+ * let's add 8 more capture channels - total of 16
+ */
+ gpr_map[gpr++] = 0x00000000;
+ snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
+ bit_shifter16,
+ A_GPR(gpr - 1),
+ A_FXBUS2(0x10));
+ A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x8),
+ A_C_00000000, A_C_00000000);
+ gpr_map[gpr++] = 0x00000000;
+ snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
+ bit_shifter16,
+ A_GPR(gpr - 1),
+ A_FXBUS2(0x12));
+ A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x9),
+ A_C_00000000, A_C_00000000);
+ gpr_map[gpr++] = 0x00000000;
+ snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
+ bit_shifter16,
+ A_GPR(gpr - 1),
+ A_FXBUS2(0x14));
+ A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xa),
+ A_C_00000000, A_C_00000000);
+ gpr_map[gpr++] = 0x00000000;
+ snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
+ bit_shifter16,
+ A_GPR(gpr - 1),
+ A_FXBUS2(0x16));
+ A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xb),
+ A_C_00000000, A_C_00000000);
+ gpr_map[gpr++] = 0x00000000;
+ snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
+ bit_shifter16,
+ A_GPR(gpr - 1),
+ A_FXBUS2(0x18));
+ A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xc),
+ A_C_00000000, A_C_00000000);
+ gpr_map[gpr++] = 0x00000000;
+ snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
+ bit_shifter16,
+ A_GPR(gpr - 1),
+ A_FXBUS2(0x1a));
+ A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xd),
+ A_C_00000000, A_C_00000000);
+ gpr_map[gpr++] = 0x00000000;
+ snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
+ bit_shifter16,
+ A_GPR(gpr - 1),
+ A_FXBUS2(0x1c));
+ A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xe),
+ A_C_00000000, A_C_00000000);
+ gpr_map[gpr++] = 0x00000000;
+ snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
+ bit_shifter16,
+ A_GPR(gpr - 1),
+ A_FXBUS2(0x1e));
+ A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xf),
+ A_C_00000000, A_C_00000000);
+ }
#if 0
for (z = 4; z < 8; z++) {
@@ -2418,14 +2436,13 @@ static void copy_string(char *dst, char *src, char *null, int idx)
strcpy(dst, src);
}
-static int snd_emu10k1_fx8010_info(struct snd_emu10k1 *emu,
+static void snd_emu10k1_fx8010_info(struct snd_emu10k1 *emu,
struct snd_emu10k1_fx8010_info *info)
{
char **fxbus, **extin, **extout;
unsigned short fxbus_mask, extin_mask, extout_mask;
int res;
- memset(info, 0, sizeof(info));
info->internal_tram_size = emu->fx8010.itram_size;
info->external_tram_size = emu->fx8010.etram_pages.bytes / 2;
fxbus = fxbuses;
@@ -2442,7 +2459,6 @@ static int snd_emu10k1_fx8010_info(struct snd_emu10k1 *emu,
for (res = 16; res < 32; res++, extout++)
copy_string(info->extout_names[res], extout_mask & (1 << res) ? *extout : NULL, "Unused", res);
info->gpr_controls = emu->fx8010.gpr_count;
- return 0;
}
static int snd_emu10k1_fx8010_ioctl(struct snd_hwdep * hw, struct file *file, unsigned int cmd, unsigned long arg)
@@ -2463,10 +2479,7 @@ static int snd_emu10k1_fx8010_ioctl(struct snd_hwdep * hw, struct file *file, un
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
- if ((res = snd_emu10k1_fx8010_info(emu, info)) < 0) {
- kfree(info);
- return res;
- }
+ snd_emu10k1_fx8010_info(emu, info);
if (copy_to_user(argp, info, sizeof(*info))) {
kfree(info);
return -EFAULT;
diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c
index 7b2c1dcc5337..54a2034d8edd 100644
--- a/sound/pci/emu10k1/emumixer.c
+++ b/sound/pci/emu10k1/emumixer.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>,
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
* Takashi Iwai <tiwai@suse.de>
* Creative Labs, Inc.
* Routines for control of EMU10K1 chips / mixer routines
@@ -400,15 +400,7 @@ static struct snd_kcontrol_new snd_emu1010_input_enum_ctls[] __devinitdata = {
-
-static int snd_emu1010_adc_pads_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_emu1010_adc_pads_info snd_ctl_boolean_mono_info
static int snd_emu1010_adc_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -456,14 +448,7 @@ static struct snd_kcontrol_new snd_emu1010_adc_pads[] __devinitdata = {
EMU1010_ADC_PADS("ADC1 14dB PAD 0202 Capture Switch", EMU_HANA_0202_ADC_PAD1),
};
-static int snd_emu1010_dac_pads_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_emu1010_dac_pads_info snd_ctl_boolean_mono_info
static int snd_emu1010_dac_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -516,17 +501,19 @@ static struct snd_kcontrol_new snd_emu1010_dac_pads[] __devinitdata = {
static int snd_emu1010_internal_clock_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
- static char *texts[2] = {
- "44100", "48000"
+ static char *texts[4] = {
+ "44100", "48000", "SPDIF", "ADAT"
};
-
+
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
- uinfo->value.enumerated.items = 2;
- if (uinfo->value.enumerated.item > 1)
- uinfo->value.enumerated.item = 1;
+ uinfo->value.enumerated.items = 4;
+ if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+ uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
return 0;
+
+
}
static int snd_emu1010_internal_clock_get(struct snd_kcontrol *kcontrol,
@@ -584,6 +571,44 @@ static int snd_emu1010_internal_clock_put(struct snd_kcontrol *kcontrol,
/* Unmute all */
snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
break;
+
+ case 2: /* Take clock from S/PDIF IN */
+ /* Mute all */
+ snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
+ /* Default fallback clock 48kHz */
+ snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K );
+ /* Word Clock source, sync to S/PDIF input */
+ snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
+ EMU_HANA_WCLOCK_HANA_SPDIF_IN | EMU_HANA_WCLOCK_1X );
+ /* Set LEDs on Audio Dock */
+ snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2,
+ EMU_HANA_DOCK_LEDS_2_EXT | EMU_HANA_DOCK_LEDS_2_LOCK );
+ /* FIXME: We should set EMU_HANA_DOCK_LEDS_2_LOCK only when clock signal is present and valid */
+ /* Allow DLL to settle */
+ msleep(10);
+ /* Unmute all */
+ snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
+ break;
+
+ case 3:
+ /* Take clock from ADAT IN */
+ /* Mute all */
+ snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
+ /* Default fallback clock 48kHz */
+ snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K );
+ /* Word Clock source, sync to ADAT input */
+ snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
+ EMU_HANA_WCLOCK_HANA_ADAT_IN | EMU_HANA_WCLOCK_1X );
+ /* Set LEDs on Audio Dock */
+ snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, EMU_HANA_DOCK_LEDS_2_EXT | EMU_HANA_DOCK_LEDS_2_LOCK );
+ /* FIXME: We should set EMU_HANA_DOCK_LEDS_2_LOCK only when clock signal is present and valid */
+ /* Allow DLL to settle */
+ msleep(10);
+ /* Unmute all */
+ snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
+
+
+ break;
}
}
return change;
@@ -871,7 +896,7 @@ static struct snd_kcontrol_new snd_emu10k1_spdif_mask_control =
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
- .count = 4,
+ .count = 3,
.info = snd_emu10k1_spdif_info,
.get = snd_emu10k1_spdif_get_mask
};
@@ -880,7 +905,7 @@ static struct snd_kcontrol_new snd_emu10k1_spdif_control =
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
- .count = 4,
+ .count = 3,
.info = snd_emu10k1_spdif_info,
.get = snd_emu10k1_spdif_get,
.put = snd_emu10k1_spdif_put
@@ -1326,14 +1351,7 @@ static struct snd_kcontrol_new snd_emu10k1_efx_attn_control =
.put = snd_emu10k1_efx_attn_put
};
-static int snd_emu10k1_shared_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_emu10k1_shared_spdif_info snd_ctl_boolean_mono_info
static int snd_emu10k1_shared_spdif_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
diff --git a/sound/pci/emu10k1/emumpu401.c b/sound/pci/emu10k1/emumpu401.c
index 950c6bcd6b7d..04c7cf703531 100644
--- a/sound/pci/emu10k1/emumpu401.c
+++ b/sound/pci/emu10k1/emumpu401.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Routines for control of EMU10K1 MPU-401 in UART mode
*
*
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
index eda5cb373ded..5ce5befc701b 100644
--- a/sound/pci/emu10k1/emupcm.c
+++ b/sound/pci/emu10k1/emupcm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Creative Labs, Inc.
* Routines for control of EMU10K1 chips / PCM routines
* Multichannel PCM support Copyright (c) Lee Revell <rlrevell@joe-job.com>
diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c
index 2c1585991bc8..c3fb10e81c9e 100644
--- a/sound/pci/emu10k1/emuproc.c
+++ b/sound/pci/emu10k1/emuproc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Creative Labs, Inc.
* Routines for control of EMU10K1 chips / proc interface routines
*
@@ -240,8 +240,42 @@ static void snd_emu10k1_proc_spdif_read(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
struct snd_emu10k1 *emu = entry->private_data;
- snd_emu10k1_proc_spdif_status(emu, buffer, "CD-ROM S/PDIF In", CDCS, CDSRCS);
- snd_emu10k1_proc_spdif_status(emu, buffer, "Optical or Coax S/PDIF In", GPSCS, GPSRCS);
+ u32 value;
+ u32 value2;
+ unsigned long flags;
+ u32 rate;
+
+ if (emu->card_capabilities->emu1010) {
+ spin_lock_irqsave(&emu->emu_lock, flags);
+ snd_emu1010_fpga_read(emu, 0x38, &value);
+ spin_unlock_irqrestore(&emu->emu_lock, flags);
+ if ((value & 0x1) == 0) {
+ spin_lock_irqsave(&emu->emu_lock, flags);
+ snd_emu1010_fpga_read(emu, 0x2a, &value);
+ snd_emu1010_fpga_read(emu, 0x2b, &value2);
+ spin_unlock_irqrestore(&emu->emu_lock, flags);
+ rate = 0x1770000 / (((value << 5) | value2)+1);
+ snd_iprintf(buffer, "ADAT Locked : %u\n", rate);
+ } else {
+ snd_iprintf(buffer, "ADAT Unlocked\n");
+ }
+ spin_lock_irqsave(&emu->emu_lock, flags);
+ snd_emu1010_fpga_read(emu, 0x20, &value);
+ spin_unlock_irqrestore(&emu->emu_lock, flags);
+ if ((value & 0x4) == 0) {
+ spin_lock_irqsave(&emu->emu_lock, flags);
+ snd_emu1010_fpga_read(emu, 0x28, &value);
+ snd_emu1010_fpga_read(emu, 0x29, &value2);
+ spin_unlock_irqrestore(&emu->emu_lock, flags);
+ rate = 0x1770000 / (((value << 5) | value2)+1);
+ snd_iprintf(buffer, "SPDIF Locked : %d\n", rate);
+ } else {
+ snd_iprintf(buffer, "SPDIF Unlocked\n");
+ }
+ } else {
+ snd_emu10k1_proc_spdif_status(emu, buffer, "CD-ROM S/PDIF In", CDCS, CDSRCS);
+ snd_emu10k1_proc_spdif_status(emu, buffer, "Optical or Coax S/PDIF In", GPSCS, GPSRCS);
+ }
#if 0
val = snd_emu10k1_ptr_read(emu, ZVSRCS, 0);
snd_iprintf(buffer, "\nZoomed Video\n");
@@ -379,20 +413,16 @@ static void snd_emu_proc_emu1010_reg_read(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
struct snd_emu10k1 *emu = entry->private_data;
- unsigned long value;
+ int value;
unsigned long flags;
- unsigned long regs;
int i;
snd_iprintf(buffer, "EMU1010 Registers:\n\n");
- for(i = 0; i < 0x30; i+=1) {
+ for(i = 0; i < 0x40; i+=1) {
spin_lock_irqsave(&emu->emu_lock, flags);
- regs=i+0x40; /* 0x40 upwards are registers. */
- outl(regs, emu->port + A_IOCFG);
- outl(regs | 0x80, emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */
- value = inl(emu->port + A_IOCFG);
+ snd_emu1010_fpga_read(emu, i, &value);
spin_unlock_irqrestore(&emu->emu_lock, flags);
- snd_iprintf(buffer, "%02X: %08lX, %02lX\n", i, value, (value >> 8) & 0x7f);
+ snd_iprintf(buffer, "%02X: %08X, %02X\n", i, value, (value >> 8) & 0x7f);
}
}
@@ -555,9 +585,9 @@ int __devinit snd_emu10k1_proc_init(struct snd_emu10k1 * emu)
{
struct snd_info_entry *entry;
#ifdef CONFIG_SND_DEBUG
- if ((emu->card_capabilities->emu1010) &&
- snd_card_proc_new(emu->card, "emu1010_regs", &entry)) {
- snd_info_set_text_ops(entry, emu, snd_emu_proc_emu1010_reg_read);
+ if (emu->card_capabilities->emu1010) {
+ if (! snd_card_proc_new(emu->card, "emu1010_regs", &entry))
+ snd_info_set_text_ops(entry, emu, snd_emu_proc_emu1010_reg_read);
}
if (! snd_card_proc_new(emu->card, "io_regs", &entry)) {
snd_info_set_text_ops(entry, emu, snd_emu_proc_io_reg_read);
diff --git a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c
index 116e1c8d9361..6702c15fefa3 100644
--- a/sound/pci/emu10k1/io.c
+++ b/sound/pci/emu10k1/io.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Creative Labs, Inc.
* Routines for control of EMU10K1 chips
*
@@ -226,9 +226,9 @@ int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu,
return 0;
}
-int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, int reg, int value)
+int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, u32 reg, u32 value)
{
- if (reg < 0 || reg > 0x3f)
+ if (reg > 0x3f)
return 1;
reg += 0x40; /* 0x40 upwards are registers. */
if (value < 0 || value > 0x3f) /* 0 to 0x3f are values */
@@ -244,9 +244,9 @@ int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, int reg, int value)
return 0;
}
-int snd_emu1010_fpga_read(struct snd_emu10k1 * emu, int reg, int *value)
+int snd_emu1010_fpga_read(struct snd_emu10k1 * emu, u32 reg, u32 *value)
{
- if (reg < 0 || reg > 0x3f)
+ if (reg > 0x3f)
return 1;
reg += 0x40; /* 0x40 upwards are registers. */
outl(reg, emu->port + A_IOCFG);
@@ -261,7 +261,7 @@ int snd_emu1010_fpga_read(struct snd_emu10k1 * emu, int reg, int *value)
/* Each Destination has one and only one Source,
* but one Source can feed any number of Destinations simultaneously.
*/
-int snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 * emu, int dst, int src)
+int snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 * emu, u32 dst, u32 src)
{
snd_emu1010_fpga_write(emu, 0x00, ((dst >> 8) & 0x3f) );
snd_emu1010_fpga_write(emu, 0x01, (dst & 0x3f) );
diff --git a/sound/pci/emu10k1/irq.c b/sound/pci/emu10k1/irq.c
index 4f18f7e8bcfb..3c114b45e0b2 100644
--- a/sound/pci/emu10k1/irq.c
+++ b/sound/pci/emu10k1/irq.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Creative Labs, Inc.
* Routines for IRQ control of EMU10K1 chips
*
diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c
index 4fcaefe5a3c5..48097c6bb15c 100644
--- a/sound/pci/emu10k1/memory.c
+++ b/sound/pci/emu10k1/memory.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Copyright (c) by Takashi Iwai <tiwai@suse.de>
*
* EMU10K1 memory page allocation (PTB area)
diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c
index 7ee19c63c2c8..d619a3842cdd 100644
--- a/sound/pci/emu10k1/p16v.c
+++ b/sound/pci/emu10k1/p16v.c
@@ -124,11 +124,12 @@
/* hardware definition */
static struct snd_pcm_hardware snd_p16v_playback_hw = {
- .info = (SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_RESUME |
- SNDRV_PCM_INFO_MMAP_VALID),
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_RESUME |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_SYNC_START,
.formats = SNDRV_PCM_FMTBIT_S32_LE, /* Only supports 24-bit samples padded to 32 bits. */
.rates = SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100,
.rate_min = 44100,
@@ -207,6 +208,11 @@ static int snd_p16v_pcm_open_playback_channel(struct snd_pcm_substream *substrea
if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
return err;
+ runtime->sync.id32[0] = substream->pcm->card->number;
+ runtime->sync.id32[1] = 'P';
+ runtime->sync.id32[2] = 16;
+ runtime->sync.id32[3] = 'V';
+
return 0;
}
/* open_capture callback */
@@ -448,6 +454,9 @@ static int snd_p16v_pcm_trigger_playback(struct snd_pcm_substream *substream,
break;
}
snd_pcm_group_for_each_entry(s, substream) {
+ if (snd_pcm_substream_chip(s) != emu ||
+ s->stream != SNDRV_PCM_STREAM_PLAYBACK)
+ continue;
runtime = s->runtime;
epcm = runtime->private_data;
channel = substream->pcm->device-emu->p16v_device_offset;
diff --git a/sound/pci/emu10k1/voice.c b/sound/pci/emu10k1/voice.c
index 1db50fe61475..04fa8492abb0 100644
--- a/sound/pci/emu10k1/voice.c
+++ b/sound/pci/emu10k1/voice.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Creative Labs, Inc.
* Lee Revell <rlrevell@joe-job.com>
* Routines for control of EMU10K1 chips - voice manager
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index 21cb4268a59b..b958f869cb13 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -1,6 +1,6 @@
/*
* Driver for Ensoniq ES1370/ES1371 AudioPCI soundcard
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>,
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
* Thomas Sailer <sailer@ife.ee.ethz.ch>
*
* This program is free software; you can redistribute it and/or modify
@@ -61,7 +61,7 @@
#endif
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Thomas Sailer <sailer@ife.ee.ethz.ch>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Thomas Sailer <sailer@ife.ee.ethz.ch>");
MODULE_LICENSE("GPL");
#ifdef CHIP1370
MODULE_DESCRIPTION("Ensoniq AudioPCI ES1370");
@@ -1419,15 +1419,7 @@ static int snd_ens1373_spdif_stream_put(struct snd_kcontrol *kcontrol,
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_es1371_spdif_info, \
.get = snd_es1371_spdif_get, .put = snd_es1371_spdif_put }
-static int snd_es1371_spdif_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_es1371_spdif_info snd_ctl_boolean_mono_info
static int snd_es1371_spdif_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -1489,15 +1481,7 @@ static struct snd_kcontrol_new snd_es1371_mixer_spdif[] __devinitdata = {
};
-static int snd_es1373_rear_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_es1373_rear_info snd_ctl_boolean_mono_info
static int snd_es1373_rear_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -1542,15 +1526,7 @@ static struct snd_kcontrol_new snd_ens1373_rear __devinitdata =
.put = snd_es1373_rear_put,
};
-static int snd_es1373_line_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_es1373_line_info snd_ctl_boolean_mono_info
static int snd_es1373_line_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -1707,15 +1683,7 @@ static int __devinit snd_ensoniq_1371_mixer(struct ensoniq *ensoniq,
.get = snd_ensoniq_control_get, .put = snd_ensoniq_control_put, \
.private_value = mask }
-static int snd_ensoniq_control_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_ensoniq_control_info snd_ctl_boolean_mono_info
static int snd_ensoniq_control_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index fec29a108945..fb25abe68a02 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -1,7 +1,7 @@
/*
* Driver for ESS Solo-1 (ES1938, ES1946, ES1969) soundcard
* Copyright (c) by Jaromir Koutek <miri@punknet.cz>,
- * Jaroslav Kysela <perex@suse.cz>,
+ * Jaroslav Kysela <perex@perex.cz>,
* Thomas Sailer <sailer@ife.ee.ethz.ch>,
* Abramo Bagnara <abramo@alsa-project.org>,
* Markus Gruber <gruber@eikon.tum.de>
@@ -1066,15 +1066,7 @@ static int snd_es1938_put_mux(struct snd_kcontrol *kcontrol,
return snd_es1938_mixer_bits(chip, 0x1c, 0x07, val) != val;
}
-static int snd_es1938_info_spatializer_enable(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_es1938_info_spatializer_enable snd_ctl_boolean_mono_info
static int snd_es1938_get_spatializer_enable(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -1120,15 +1112,7 @@ static int snd_es1938_get_hw_volume(struct snd_kcontrol *kcontrol,
return 0;
}
-static int snd_es1938_info_hw_switch(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 2;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_es1938_info_hw_switch snd_ctl_boolean_stereo_info
static int snd_es1938_get_hw_switch(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index 2faf009076bb..d69b11d1f993 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -843,10 +843,9 @@ static void snd_es1968_bob_dec(struct es1968 *chip)
snd_es1968_bob_stop(chip);
else if (chip->bob_freq > ESM_BOB_FREQ) {
/* check reduction of timer frequency */
- struct list_head *p;
int max_freq = ESM_BOB_FREQ;
- list_for_each(p, &chip->substream_list) {
- struct esschan *es = list_entry(p, struct esschan, list);
+ struct esschan *es;
+ list_for_each_entry(es, &chip->substream_list, list) {
if (max_freq < es->bob_freq)
max_freq = es->bob_freq;
}
@@ -1316,12 +1315,11 @@ static struct snd_pcm_hardware snd_es1968_capture = {
static int calc_available_memory_size(struct es1968 *chip)
{
- struct list_head *p;
int max_size = 0;
-
+ struct esm_memory *buf;
+
mutex_lock(&chip->memory_mutex);
- list_for_each(p, &chip->buf_list) {
- struct esm_memory *buf = list_entry(p, struct esm_memory, list);
+ list_for_each_entry(buf, &chip->buf_list, list) {
if (buf->empty && buf->buf.bytes > max_size)
max_size = buf->buf.bytes;
}
@@ -1335,12 +1333,10 @@ static int calc_available_memory_size(struct es1968 *chip)
static struct esm_memory *snd_es1968_new_memory(struct es1968 *chip, int size)
{
struct esm_memory *buf;
- struct list_head *p;
-
+
size = ALIGN(size, ESM_MEM_ALIGN);
mutex_lock(&chip->memory_mutex);
- list_for_each(p, &chip->buf_list) {
- buf = list_entry(p, struct esm_memory, list);
+ list_for_each_entry(buf, &chip->buf_list, list) {
if (buf->empty && buf->buf.bytes >= size)
goto __found;
}
@@ -1938,10 +1934,9 @@ static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id)
}
if (event & ESM_SOUND_IRQ) {
- struct list_head *p;
+ struct esschan *es;
spin_lock(&chip->substream_lock);
- list_for_each(p, &chip->substream_list) {
- struct esschan *es = list_entry(p, struct esschan, list);
+ list_for_each_entry(es, &chip->substream_list, list) {
if (es->running)
snd_es1968_update_pcm(chip, es);
}
@@ -2345,7 +2340,7 @@ static int es1968_resume(struct pci_dev *pci)
{
struct snd_card *card = pci_get_drvdata(pci);
struct es1968 *chip = card->private_data;
- struct list_head *p;
+ struct esschan *es;
if (! chip->do_pm)
return 0;
@@ -2374,8 +2369,7 @@ static int es1968_resume(struct pci_dev *pci)
/* restore ac97 state */
snd_ac97_resume(chip->ac97);
- list_for_each(p, &chip->substream_list) {
- struct esschan *es = list_entry(p, struct esschan, list);
+ list_for_each_entry(es, &chip->substream_list, list) {
switch (es->mode) {
case ESM_MODE_PLAY:
snd_es1968_playback_setup(chip, es, es->substream->runtime);
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index 11015178e207..9939109f05a2 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -1,6 +1,6 @@
/*
* The driver for the ForteMedia FM801 based soundcards
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
* Support FM only card by Andy Shevchenko <andy@smile.org.ua>
*
@@ -42,7 +42,7 @@
#define TEA575X_RADIO 1
#endif
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("ForteMedia FM801");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{ForteMedia,FM801},"
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index b2484bbdcc1d..ab0c726d648e 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -1,19 +1,18 @@
-snd-hda-intel-objs := hda_intel.o
+snd-hda-intel-y := hda_intel.o
# since snd-hda-intel is the only driver using hda-codec,
# merge it into a single module although it was originally
# designed to be individual modules
-snd-hda-intel-objs += hda_codec.o \
- hda_generic.o \
- patch_realtek.o \
- patch_cmedia.o \
- patch_analog.o \
- patch_sigmatel.o \
- patch_si3054.o \
- patch_atihdmi.o \
- patch_conexant.o \
- patch_via.o
-ifdef CONFIG_PROC_FS
-snd-hda-intel-objs += hda_proc.o
-endif
+snd-hda-intel-y += hda_codec.o
+snd-hda-intel-$(CONFIG_PROC_FS) += hda_proc.o
+snd-hda-intel-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o
+snd-hda-intel-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o
+snd-hda-intel-$(CONFIG_SND_HDA_CODEC_REALTEK) += patch_realtek.o
+snd-hda-intel-$(CONFIG_SND_HDA_CODEC_CMEDIA) += patch_cmedia.o
+snd-hda-intel-$(CONFIG_SND_HDA_CODEC_ANALOG) += patch_analog.o
+snd-hda-intel-$(CONFIG_SND_HDA_CODEC_SIGMATEL) += patch_sigmatel.o
+snd-hda-intel-$(CONFIG_SND_HDA_CODEC_SI3054) += patch_si3054.o
+snd-hda-intel-$(CONFIG_SND_HDA_CODEC_ATIHDMI) += patch_atihdmi.o
+snd-hda-intel-$(CONFIG_SND_HDA_CODEC_CONEXANT) += patch_conexant.o
+snd-hda-intel-$(CONFIG_SND_HDA_CODEC_VIA) += patch_via.o
obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-intel.o
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index f87f8f088956..ad4cb38109fc 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -31,7 +31,15 @@
#include <sound/tlv.h>
#include <sound/initval.h>
#include "hda_local.h"
-
+#include <sound/hda_hwdep.h>
+
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+/* define this option here to hide as static */
+static int power_save = CONFIG_SND_HDA_POWER_SAVE_DEFAULT;
+module_param(power_save, int, 0644);
+MODULE_PARM_DESC(power_save, "Automatic power-saving timeout "
+ "(in second, 0 = disable).");
+#endif
/*
* vendor / preset table
@@ -59,6 +67,13 @@ static struct hda_vendor_id hda_vendor_ids[] = {
#include "hda_patch.h"
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static void hda_power_work(struct work_struct *work);
+static void hda_keep_power_on(struct hda_codec *codec);
+#else
+static inline void hda_keep_power_on(struct hda_codec *codec) {}
+#endif
+
/**
* snd_hda_codec_read - send a command and get the response
* @codec: the HDA codec
@@ -76,12 +91,14 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
unsigned int verb, unsigned int parm)
{
unsigned int res;
+ snd_hda_power_up(codec);
mutex_lock(&codec->bus->cmd_mutex);
if (!codec->bus->ops.command(codec, nid, direct, verb, parm))
res = codec->bus->ops.get_response(codec);
else
res = (unsigned int)-1;
mutex_unlock(&codec->bus->cmd_mutex);
+ snd_hda_power_down(codec);
return res;
}
@@ -101,9 +118,11 @@ int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct,
unsigned int verb, unsigned int parm)
{
int err;
+ snd_hda_power_up(codec);
mutex_lock(&codec->bus->cmd_mutex);
err = codec->bus->ops.command(codec, nid, direct, verb, parm);
mutex_unlock(&codec->bus->cmd_mutex);
+ snd_hda_power_down(codec);
return err;
}
@@ -136,6 +155,8 @@ int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
unsigned int parm;
parm = snd_hda_param_read(codec, nid, AC_PAR_NODE_COUNT);
+ if (parm == -1)
+ return 0;
*start_id = (parm >> 16) & 0x7fff;
return (int)(parm & 0x7fff);
}
@@ -387,6 +408,13 @@ int __devinit snd_hda_bus_new(struct snd_card *card,
return 0;
}
+#ifdef CONFIG_SND_HDA_GENERIC
+#define is_generic_config(codec) \
+ (codec->bus->modelname && !strcmp(codec->bus->modelname, "generic"))
+#else
+#define is_generic_config(codec) 0
+#endif
+
/*
* find a matching codec preset
*/
@@ -395,7 +423,7 @@ find_codec_preset(struct hda_codec *codec)
{
const struct hda_codec_preset **tbl, *preset;
- if (codec->bus->modelname && !strcmp(codec->bus->modelname, "generic"))
+ if (is_generic_config(codec))
return NULL; /* use the generic parser */
for (tbl = hda_preset_tables; *tbl; tbl++) {
@@ -486,6 +514,10 @@ static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node)
}
+static void init_hda_cache(struct hda_cache_rec *cache,
+ unsigned int record_size);
+static void free_hda_cache(struct hda_cache_rec *cache);
+
/*
* codec destructor
*/
@@ -493,17 +525,20 @@ static void snd_hda_codec_free(struct hda_codec *codec)
{
if (!codec)
return;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ cancel_delayed_work(&codec->power_work);
+ flush_scheduled_work();
+#endif
list_del(&codec->list);
codec->bus->caddr_tbl[codec->addr] = NULL;
if (codec->patch_ops.free)
codec->patch_ops.free(codec);
- kfree(codec->amp_info);
+ free_hda_cache(&codec->amp_cache);
+ free_hda_cache(&codec->cmd_cache);
kfree(codec->wcaps);
kfree(codec);
}
-static void init_amp_hash(struct hda_codec *codec);
-
/**
* snd_hda_codec_new - create a HDA codec
* @bus: the bus to assign
@@ -537,7 +572,17 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
codec->bus = bus;
codec->addr = codec_addr;
mutex_init(&codec->spdif_mutex);
- init_amp_hash(codec);
+ init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
+ init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
+
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ INIT_DELAYED_WORK(&codec->power_work, hda_power_work);
+ /* snd_hda_codec_new() marks the codec as power-up, and leave it as is.
+ * the caller has to power down appropriatley after initialization
+ * phase.
+ */
+ hda_keep_power_on(codec);
+#endif
list_add_tail(&codec->list, &bus->codec_list);
bus->caddr_tbl[codec_addr] = codec;
@@ -581,10 +626,21 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
snd_hda_get_codec_name(codec, bus->card->mixername,
sizeof(bus->card->mixername));
- if (codec->preset && codec->preset->patch)
- err = codec->preset->patch(codec);
- else
+ if (is_generic_config(codec)) {
err = snd_hda_parse_generic_codec(codec);
+ goto patched;
+ }
+ if (codec->preset && codec->preset->patch) {
+ err = codec->preset->patch(codec);
+ goto patched;
+ }
+
+ /* call the default parser */
+ err = snd_hda_parse_generic_codec(codec);
+ if (err < 0)
+ printk(KERN_ERR "hda-codec: No codec parser is available\n");
+
+ patched:
if (err < 0) {
snd_hda_codec_free(codec);
return err;
@@ -594,6 +650,9 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
init_unsol_queue(bus);
snd_hda_codec_proc_new(codec);
+#ifdef CONFIG_SND_HDA_HWDEP
+ snd_hda_create_hwdep(codec);
+#endif
sprintf(component, "HDA:%08x", codec->vendor_id);
snd_component_add(codec->bus->card, component);
@@ -637,59 +696,72 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
#define INFO_AMP_VOL(ch) (1 << (1 + (ch)))
/* initialize the hash table */
-static void __devinit init_amp_hash(struct hda_codec *codec)
+static void __devinit init_hda_cache(struct hda_cache_rec *cache,
+ unsigned int record_size)
{
- memset(codec->amp_hash, 0xff, sizeof(codec->amp_hash));
- codec->num_amp_entries = 0;
- codec->amp_info_size = 0;
- codec->amp_info = NULL;
+ memset(cache, 0, sizeof(*cache));
+ memset(cache->hash, 0xff, sizeof(cache->hash));
+ cache->record_size = record_size;
+}
+
+static void free_hda_cache(struct hda_cache_rec *cache)
+{
+ kfree(cache->buffer);
}
/* query the hash. allocate an entry if not found. */
-static struct hda_amp_info *get_alloc_amp_hash(struct hda_codec *codec, u32 key)
+static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
+ u32 key)
{
- u16 idx = key % (u16)ARRAY_SIZE(codec->amp_hash);
- u16 cur = codec->amp_hash[idx];
- struct hda_amp_info *info;
+ u16 idx = key % (u16)ARRAY_SIZE(cache->hash);
+ u16 cur = cache->hash[idx];
+ struct hda_cache_head *info;
while (cur != 0xffff) {
- info = &codec->amp_info[cur];
+ info = (struct hda_cache_head *)(cache->buffer +
+ cur * cache->record_size);
if (info->key == key)
return info;
cur = info->next;
}
/* add a new hash entry */
- if (codec->num_amp_entries >= codec->amp_info_size) {
+ if (cache->num_entries >= cache->size) {
/* reallocate the array */
- int new_size = codec->amp_info_size + 64;
- struct hda_amp_info *new_info;
- new_info = kcalloc(new_size, sizeof(struct hda_amp_info),
- GFP_KERNEL);
- if (!new_info) {
+ unsigned int new_size = cache->size + 64;
+ void *new_buffer;
+ new_buffer = kcalloc(new_size, cache->record_size, GFP_KERNEL);
+ if (!new_buffer) {
snd_printk(KERN_ERR "hda_codec: "
"can't malloc amp_info\n");
return NULL;
}
- if (codec->amp_info) {
- memcpy(new_info, codec->amp_info,
- codec->amp_info_size *
- sizeof(struct hda_amp_info));
- kfree(codec->amp_info);
+ if (cache->buffer) {
+ memcpy(new_buffer, cache->buffer,
+ cache->size * cache->record_size);
+ kfree(cache->buffer);
}
- codec->amp_info_size = new_size;
- codec->amp_info = new_info;
+ cache->size = new_size;
+ cache->buffer = new_buffer;
}
- cur = codec->num_amp_entries++;
- info = &codec->amp_info[cur];
+ cur = cache->num_entries++;
+ info = (struct hda_cache_head *)(cache->buffer +
+ cur * cache->record_size);
info->key = key;
- info->status = 0; /* not initialized yet */
- info->next = codec->amp_hash[idx];
- codec->amp_hash[idx] = cur;
+ info->val = 0;
+ info->next = cache->hash[idx];
+ cache->hash[idx] = cur;
return info;
}
+/* query and allocate an amp hash entry */
+static inline struct hda_amp_info *
+get_alloc_amp_hash(struct hda_codec *codec, u32 key)
+{
+ return (struct hda_amp_info *)get_alloc_hash(&codec->amp_cache, key);
+}
+
/*
* query AMP capabilities for the given widget and direction
*/
@@ -700,7 +772,7 @@ static u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0));
if (!info)
return 0;
- if (!(info->status & INFO_AMP_CAPS)) {
+ if (!(info->head.val & INFO_AMP_CAPS)) {
if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD))
nid = codec->afg;
info->amp_caps = snd_hda_param_read(codec, nid,
@@ -708,7 +780,7 @@ static u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
AC_PAR_AMP_OUT_CAP :
AC_PAR_AMP_IN_CAP);
if (info->amp_caps)
- info->status |= INFO_AMP_CAPS;
+ info->head.val |= INFO_AMP_CAPS;
}
return info->amp_caps;
}
@@ -722,7 +794,7 @@ int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
if (!info)
return -EINVAL;
info->amp_caps = caps;
- info->status |= INFO_AMP_CAPS;
+ info->head.val |= INFO_AMP_CAPS;
return 0;
}
@@ -736,7 +808,7 @@ static unsigned int get_vol_mute(struct hda_codec *codec,
{
u32 val, parm;
- if (info->status & INFO_AMP_VOL(ch))
+ if (info->head.val & INFO_AMP_VOL(ch))
return info->vol[ch];
parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT;
@@ -745,7 +817,7 @@ static unsigned int get_vol_mute(struct hda_codec *codec,
val = snd_hda_codec_read(codec, nid, 0,
AC_VERB_GET_AMP_GAIN_MUTE, parm);
info->vol[ch] = val & 0xff;
- info->status |= INFO_AMP_VOL(ch);
+ info->head.val |= INFO_AMP_VOL(ch);
return info->vol[ch];
}
@@ -792,12 +864,50 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
return 0;
val &= mask;
val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask;
- if (info->vol[ch] == val && !codec->in_resume)
+ if (info->vol[ch] == val)
return 0;
put_vol_mute(codec, info, nid, ch, direction, idx, val);
return 1;
}
+/*
+ * update the AMP stereo with the same mask and value
+ */
+int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
+ int direction, int idx, int mask, int val)
+{
+ int ch, ret = 0;
+ for (ch = 0; ch < 2; ch++)
+ ret |= snd_hda_codec_amp_update(codec, nid, ch, direction,
+ idx, mask, val);
+ return ret;
+}
+
+#ifdef SND_HDA_NEEDS_RESUME
+/* resume the all amp commands from the cache */
+void snd_hda_codec_resume_amp(struct hda_codec *codec)
+{
+ struct hda_amp_info *buffer = codec->amp_cache.buffer;
+ int i;
+
+ for (i = 0; i < codec->amp_cache.size; i++, buffer++) {
+ u32 key = buffer->head.key;
+ hda_nid_t nid;
+ unsigned int idx, dir, ch;
+ if (!key)
+ continue;
+ nid = key & 0xff;
+ idx = (key >> 16) & 0xff;
+ dir = (key >> 24) & 0xff;
+ for (ch = 0; ch < 2; ch++) {
+ if (!(buffer->head.val & INFO_AMP_VOL(ch)))
+ continue;
+ put_vol_mute(codec, buffer, nid, ch, dir, idx,
+ buffer->vol[ch]);
+ }
+ }
+}
+#endif /* SND_HDA_NEEDS_RESUME */
/*
* AMP control callbacks
@@ -844,9 +954,11 @@ int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
long *valp = ucontrol->value.integer.value;
if (chs & 1)
- *valp++ = snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & 0x7f;
+ *valp++ = snd_hda_codec_amp_read(codec, nid, 0, dir, idx)
+ & HDA_AMP_VOLMASK;
if (chs & 2)
- *valp = snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & 0x7f;
+ *valp = snd_hda_codec_amp_read(codec, nid, 1, dir, idx)
+ & HDA_AMP_VOLMASK;
return 0;
}
@@ -861,6 +973,7 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
long *valp = ucontrol->value.integer.value;
int change = 0;
+ snd_hda_power_up(codec);
if (chs & 1) {
change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
0x7f, *valp);
@@ -869,6 +982,7 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
if (chs & 2)
change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
0x7f, *valp);
+ snd_hda_power_down(codec);
return change;
}
@@ -923,10 +1037,10 @@ int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
if (chs & 1)
*valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) &
- 0x80) ? 0 : 1;
+ HDA_AMP_MUTE) ? 0 : 1;
if (chs & 2)
*valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) &
- 0x80) ? 0 : 1;
+ HDA_AMP_MUTE) ? 0 : 1;
return 0;
}
@@ -941,15 +1055,22 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
long *valp = ucontrol->value.integer.value;
int change = 0;
+ snd_hda_power_up(codec);
if (chs & 1) {
change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
- 0x80, *valp ? 0 : 0x80);
+ HDA_AMP_MUTE,
+ *valp ? 0 : HDA_AMP_MUTE);
valp++;
}
if (chs & 2)
change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
- 0x80, *valp ? 0 : 0x80);
-
+ HDA_AMP_MUTE,
+ *valp ? 0 : HDA_AMP_MUTE);
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ if (codec->patch_ops.check_power_status)
+ codec->patch_ops.check_power_status(codec, nid);
+#endif
+ snd_hda_power_down(codec);
return change;
}
@@ -1002,6 +1123,93 @@ int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
}
/*
+ * generic bound volume/swtich controls
+ */
+int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct hda_bind_ctls *c;
+ int err;
+
+ c = (struct hda_bind_ctls *)kcontrol->private_value;
+ mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */
+ kcontrol->private_value = *c->values;
+ err = c->ops->info(kcontrol, uinfo);
+ kcontrol->private_value = (long)c;
+ mutex_unlock(&codec->spdif_mutex);
+ return err;
+}
+
+int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct hda_bind_ctls *c;
+ int err;
+
+ c = (struct hda_bind_ctls *)kcontrol->private_value;
+ mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */
+ kcontrol->private_value = *c->values;
+ err = c->ops->get(kcontrol, ucontrol);
+ kcontrol->private_value = (long)c;
+ mutex_unlock(&codec->spdif_mutex);
+ return err;
+}
+
+int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct hda_bind_ctls *c;
+ unsigned long *vals;
+ int err = 0, change = 0;
+
+ c = (struct hda_bind_ctls *)kcontrol->private_value;
+ mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */
+ for (vals = c->values; *vals; vals++) {
+ kcontrol->private_value = *vals;
+ err = c->ops->put(kcontrol, ucontrol);
+ if (err < 0)
+ break;
+ change |= err;
+ }
+ kcontrol->private_value = (long)c;
+ mutex_unlock(&codec->spdif_mutex);
+ return err < 0 ? err : change;
+}
+
+int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
+ unsigned int size, unsigned int __user *tlv)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct hda_bind_ctls *c;
+ int err;
+
+ c = (struct hda_bind_ctls *)kcontrol->private_value;
+ mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */
+ kcontrol->private_value = *c->values;
+ err = c->ops->tlv(kcontrol, op_flag, size, tlv);
+ kcontrol->private_value = (long)c;
+ mutex_unlock(&codec->spdif_mutex);
+ return err;
+}
+
+struct hda_ctl_ops snd_hda_bind_vol = {
+ .info = snd_hda_mixer_amp_volume_info,
+ .get = snd_hda_mixer_amp_volume_get,
+ .put = snd_hda_mixer_amp_volume_put,
+ .tlv = snd_hda_mixer_amp_tlv
+};
+
+struct hda_ctl_ops snd_hda_bind_sw = {
+ .info = snd_hda_mixer_amp_switch_info,
+ .get = snd_hda_mixer_amp_switch_get,
+ .put = snd_hda_mixer_amp_switch_put,
+ .tlv = snd_hda_mixer_amp_tlv
+};
+
+/*
* SPDIF out controls
*/
@@ -1118,26 +1326,20 @@ static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
change = codec->spdif_ctls != val;
codec->spdif_ctls = val;
- if (change || codec->in_resume) {
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
- val & 0xff);
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_2,
- val >> 8);
+ if (change) {
+ snd_hda_codec_write_cache(codec, nid, 0,
+ AC_VERB_SET_DIGI_CONVERT_1,
+ val & 0xff);
+ snd_hda_codec_write_cache(codec, nid, 0,
+ AC_VERB_SET_DIGI_CONVERT_2,
+ val >> 8);
}
mutex_unlock(&codec->spdif_mutex);
return change;
}
-static int snd_hda_spdif_out_switch_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_hda_spdif_out_switch_info snd_ctl_boolean_mono_info
static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -1161,17 +1363,16 @@ static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
if (ucontrol->value.integer.value[0])
val |= AC_DIG1_ENABLE;
change = codec->spdif_ctls != val;
- if (change || codec->in_resume) {
+ if (change) {
codec->spdif_ctls = val;
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
- val & 0xff);
+ snd_hda_codec_write_cache(codec, nid, 0,
+ AC_VERB_SET_DIGI_CONVERT_1,
+ val & 0xff);
/* unmute amp switch (if any) */
if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) &&
(val & AC_DIG1_ENABLE))
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_AMP_GAIN_MUTE,
- AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT |
- AC_AMP_SET_OUTPUT);
+ snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, 0);
}
mutex_unlock(&codec->spdif_mutex);
return change;
@@ -1219,8 +1420,7 @@ static struct snd_kcontrol_new dig_mixes[] = {
*
* Returns 0 if successful, or a negative error code.
*/
-int __devinit snd_hda_create_spdif_out_ctls(struct hda_codec *codec,
- hda_nid_t nid)
+int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
{
int err;
struct snd_kcontrol *kctl;
@@ -1264,10 +1464,10 @@ static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol,
mutex_lock(&codec->spdif_mutex);
change = codec->spdif_in_enable != val;
- if (change || codec->in_resume) {
+ if (change) {
codec->spdif_in_enable = val;
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
- val);
+ snd_hda_codec_write_cache(codec, nid, 0,
+ AC_VERB_SET_DIGI_CONVERT_1, val);
}
mutex_unlock(&codec->spdif_mutex);
return change;
@@ -1318,8 +1518,7 @@ static struct snd_kcontrol_new dig_in_ctls[] = {
*
* Returns 0 if successful, or a negative error code.
*/
-int __devinit snd_hda_create_spdif_in_ctls(struct hda_codec *codec,
- hda_nid_t nid)
+int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
{
int err;
struct snd_kcontrol *kctl;
@@ -1338,6 +1537,79 @@ int __devinit snd_hda_create_spdif_in_ctls(struct hda_codec *codec,
return 0;
}
+#ifdef SND_HDA_NEEDS_RESUME
+/*
+ * command cache
+ */
+
+/* build a 32bit cache key with the widget id and the command parameter */
+#define build_cmd_cache_key(nid, verb) ((verb << 8) | nid)
+#define get_cmd_cache_nid(key) ((key) & 0xff)
+#define get_cmd_cache_cmd(key) (((key) >> 8) & 0xffff)
+
+/**
+ * snd_hda_codec_write_cache - send a single command with caching
+ * @codec: the HDA codec
+ * @nid: NID to send the command
+ * @direct: direct flag
+ * @verb: the verb to send
+ * @parm: the parameter for the verb
+ *
+ * Send a single command without waiting for response.
+ *
+ * Returns 0 if successful, or a negative error code.
+ */
+int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
+ int direct, unsigned int verb, unsigned int parm)
+{
+ int err;
+ snd_hda_power_up(codec);
+ mutex_lock(&codec->bus->cmd_mutex);
+ err = codec->bus->ops.command(codec, nid, direct, verb, parm);
+ if (!err) {
+ struct hda_cache_head *c;
+ u32 key = build_cmd_cache_key(nid, verb);
+ c = get_alloc_hash(&codec->cmd_cache, key);
+ if (c)
+ c->val = parm;
+ }
+ mutex_unlock(&codec->bus->cmd_mutex);
+ snd_hda_power_down(codec);
+ return err;
+}
+
+/* resume the all commands from the cache */
+void snd_hda_codec_resume_cache(struct hda_codec *codec)
+{
+ struct hda_cache_head *buffer = codec->cmd_cache.buffer;
+ int i;
+
+ for (i = 0; i < codec->cmd_cache.size; i++, buffer++) {
+ u32 key = buffer->key;
+ if (!key)
+ continue;
+ snd_hda_codec_write(codec, get_cmd_cache_nid(key), 0,
+ get_cmd_cache_cmd(key), buffer->val);
+ }
+}
+
+/**
+ * snd_hda_sequence_write_cache - sequence writes with caching
+ * @codec: the HDA codec
+ * @seq: VERB array to send
+ *
+ * Send the commands sequentially from the given array.
+ * Thte commands are recorded on cache for power-save and resume.
+ * The array must be terminated with NID=0.
+ */
+void snd_hda_sequence_write_cache(struct hda_codec *codec,
+ const struct hda_verb *seq)
+{
+ for (; seq->nid; seq++)
+ snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb,
+ seq->param);
+}
+#endif /* SND_HDA_NEEDS_RESUME */
/*
* set power state of the codec
@@ -1345,23 +1617,86 @@ int __devinit snd_hda_create_spdif_in_ctls(struct hda_codec *codec,
static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
unsigned int power_state)
{
- hda_nid_t nid, nid_start;
- int nodes;
+ hda_nid_t nid;
+ int i;
snd_hda_codec_write(codec, fg, 0, AC_VERB_SET_POWER_STATE,
power_state);
- nodes = snd_hda_get_sub_nodes(codec, fg, &nid_start);
- for (nid = nid_start; nid < nodes + nid_start; nid++) {
- if (get_wcaps(codec, nid) & AC_WCAP_POWER)
+ nid = codec->start_nid;
+ for (i = 0; i < codec->num_nodes; i++, nid++) {
+ if (get_wcaps(codec, nid) & AC_WCAP_POWER) {
+ unsigned int pincap;
+ /*
+ * don't power down the widget if it controls eapd
+ * and EAPD_BTLENABLE is set.
+ */
+ pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
+ if (pincap & AC_PINCAP_EAPD) {
+ int eapd = snd_hda_codec_read(codec, nid,
+ 0, AC_VERB_GET_EAPD_BTLENABLE, 0);
+ eapd &= 0x02;
+ if (power_state == AC_PWRST_D3 && eapd)
+ continue;
+ }
snd_hda_codec_write(codec, nid, 0,
AC_VERB_SET_POWER_STATE,
power_state);
+ }
}
- if (power_state == AC_PWRST_D0)
+ if (power_state == AC_PWRST_D0) {
+ unsigned long end_time;
+ int state;
msleep(10);
+ /* wait until the codec reachs to D0 */
+ end_time = jiffies + msecs_to_jiffies(500);
+ do {
+ state = snd_hda_codec_read(codec, fg, 0,
+ AC_VERB_GET_POWER_STATE, 0);
+ if (state == power_state)
+ break;
+ msleep(1);
+ } while (time_after_eq(end_time, jiffies));
+ }
+}
+
+#ifdef SND_HDA_NEEDS_RESUME
+/*
+ * call suspend and power-down; used both from PM and power-save
+ */
+static void hda_call_codec_suspend(struct hda_codec *codec)
+{
+ if (codec->patch_ops.suspend)
+ codec->patch_ops.suspend(codec, PMSG_SUSPEND);
+ hda_set_power_state(codec,
+ codec->afg ? codec->afg : codec->mfg,
+ AC_PWRST_D3);
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ cancel_delayed_work(&codec->power_work);
+ codec->power_on = 0;
+ codec->power_transition = 0;
+#endif
+}
+
+/*
+ * kick up codec; used both from PM and power-save
+ */
+static void hda_call_codec_resume(struct hda_codec *codec)
+{
+ hda_set_power_state(codec,
+ codec->afg ? codec->afg : codec->mfg,
+ AC_PWRST_D0);
+ if (codec->patch_ops.resume)
+ codec->patch_ops.resume(codec);
+ else {
+ if (codec->patch_ops.init)
+ codec->patch_ops.init(codec);
+ snd_hda_codec_resume_amp(codec);
+ snd_hda_codec_resume_cache(codec);
+ }
}
+#endif /* SND_HDA_NEEDS_RESUME */
/**
@@ -1376,28 +1711,24 @@ int __devinit snd_hda_build_controls(struct hda_bus *bus)
{
struct hda_codec *codec;
- /* build controls */
- list_for_each_entry(codec, &bus->codec_list, list) {
- int err;
- if (!codec->patch_ops.build_controls)
- continue;
- err = codec->patch_ops.build_controls(codec);
- if (err < 0)
- return err;
- }
-
- /* initialize */
list_for_each_entry(codec, &bus->codec_list, list) {
- int err;
+ int err = 0;
+ /* fake as if already powered-on */
+ hda_keep_power_on(codec);
+ /* then fire up */
hda_set_power_state(codec,
codec->afg ? codec->afg : codec->mfg,
AC_PWRST_D0);
- if (!codec->patch_ops.init)
- continue;
- err = codec->patch_ops.init(codec);
+ /* continue to initialize... */
+ if (codec->patch_ops.init)
+ err = codec->patch_ops.init(codec);
+ if (!err && codec->patch_ops.build_controls)
+ err = codec->patch_ops.build_controls(codec);
+ snd_hda_power_down(codec);
if (err < 0)
return err;
}
+
return 0;
}
@@ -1789,9 +2120,9 @@ int __devinit snd_hda_build_pcms(struct hda_bus *bus)
*
* If no entries are matching, the function returns a negative value.
*/
-int __devinit snd_hda_check_board_config(struct hda_codec *codec,
- int num_configs, const char **models,
- const struct snd_pci_quirk *tbl)
+int snd_hda_check_board_config(struct hda_codec *codec,
+ int num_configs, const char **models,
+ const struct snd_pci_quirk *tbl)
{
if (codec->bus->modelname && models) {
int i;
@@ -1841,10 +2172,9 @@ int __devinit snd_hda_check_board_config(struct hda_codec *codec,
*
* Returns 0 if successful, or a negative error code.
*/
-int __devinit snd_hda_add_new_ctls(struct hda_codec *codec,
- struct snd_kcontrol_new *knew)
+int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
{
- int err;
+ int err;
for (; knew->name; knew++) {
struct snd_kcontrol *kctl;
@@ -1867,6 +2197,93 @@ int __devinit snd_hda_add_new_ctls(struct hda_codec *codec,
return 0;
}
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
+ unsigned int power_state);
+
+static void hda_power_work(struct work_struct *work)
+{
+ struct hda_codec *codec =
+ container_of(work, struct hda_codec, power_work.work);
+
+ if (!codec->power_on || codec->power_count) {
+ codec->power_transition = 0;
+ return;
+ }
+
+ hda_call_codec_suspend(codec);
+ if (codec->bus->ops.pm_notify)
+ codec->bus->ops.pm_notify(codec);
+}
+
+static void hda_keep_power_on(struct hda_codec *codec)
+{
+ codec->power_count++;
+ codec->power_on = 1;
+}
+
+void snd_hda_power_up(struct hda_codec *codec)
+{
+ codec->power_count++;
+ if (codec->power_on || codec->power_transition)
+ return;
+
+ codec->power_on = 1;
+ if (codec->bus->ops.pm_notify)
+ codec->bus->ops.pm_notify(codec);
+ hda_call_codec_resume(codec);
+ cancel_delayed_work(&codec->power_work);
+ codec->power_transition = 0;
+}
+
+void snd_hda_power_down(struct hda_codec *codec)
+{
+ --codec->power_count;
+ if (!codec->power_on || codec->power_count || codec->power_transition)
+ return;
+ if (power_save) {
+ codec->power_transition = 1; /* avoid reentrance */
+ schedule_delayed_work(&codec->power_work,
+ msecs_to_jiffies(power_save * 1000));
+ }
+}
+
+int snd_hda_check_amp_list_power(struct hda_codec *codec,
+ struct hda_loopback_check *check,
+ hda_nid_t nid)
+{
+ struct hda_amp_list *p;
+ int ch, v;
+
+ if (!check->amplist)
+ return 0;
+ for (p = check->amplist; p->nid; p++) {
+ if (p->nid == nid)
+ break;
+ }
+ if (!p->nid)
+ return 0; /* nothing changed */
+
+ for (p = check->amplist; p->nid; p++) {
+ for (ch = 0; ch < 2; ch++) {
+ v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir,
+ p->idx);
+ if (!(v & HDA_AMP_MUTE) && v > 0) {
+ if (!check->power_on) {
+ check->power_on = 1;
+ snd_hda_power_up(codec);
+ }
+ return 1;
+ }
+ }
+ }
+ if (check->power_on) {
+ check->power_on = 0;
+ snd_hda_power_down(codec);
+ }
+ return 0;
+}
+#endif
/*
* Channel mode helper
@@ -1913,12 +2330,12 @@ int snd_hda_ch_mode_put(struct hda_codec *codec,
mode = ucontrol->value.enumerated.item[0];
snd_assert(mode < num_chmodes, return -EINVAL);
- if (*max_channelsp == chmode[mode].channels && !codec->in_resume)
+ if (*max_channelsp == chmode[mode].channels)
return 0;
/* change the current channel setting */
*max_channelsp = chmode[mode].channels;
if (chmode[mode].sequence)
- snd_hda_sequence_write(codec, chmode[mode].sequence);
+ snd_hda_sequence_write_cache(codec, chmode[mode].sequence);
return 1;
}
@@ -1933,6 +2350,8 @@ int snd_hda_input_mux_info(const struct hda_input_mux *imux,
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
uinfo->value.enumerated.items = imux->num_items;
+ if (!imux->num_items)
+ return 0;
index = uinfo->value.enumerated.item;
if (index >= imux->num_items)
index = imux->num_items - 1;
@@ -1948,13 +2367,15 @@ int snd_hda_input_mux_put(struct hda_codec *codec,
{
unsigned int idx;
+ if (!imux->num_items)
+ return 0;
idx = ucontrol->value.enumerated.item[0];
if (idx >= imux->num_items)
idx = imux->num_items - 1;
- if (*cur_val == idx && !codec->in_resume)
+ if (*cur_val == idx)
return 0;
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
- imux->items[idx].index);
+ snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
+ imux->items[idx].index);
*cur_val = idx;
return 1;
}
@@ -2118,7 +2539,7 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
* Helper for automatic ping configuration
*/
-static int __devinit is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
+static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
{
for (; *list; list++)
if (*list == nid)
@@ -2169,9 +2590,9 @@ static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences,
* The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
* respectively.
*/
-int __devinit snd_hda_parse_pin_def_config(struct hda_codec *codec,
- struct auto_pin_cfg *cfg,
- hda_nid_t *ignore_nids)
+int snd_hda_parse_pin_def_config(struct hda_codec *codec,
+ struct auto_pin_cfg *cfg,
+ hda_nid_t *ignore_nids)
{
hda_nid_t nid, nid_start;
int nodes;
@@ -2371,13 +2792,12 @@ int snd_hda_suspend(struct hda_bus *bus, pm_message_t state)
{
struct hda_codec *codec;
- /* FIXME: should handle power widget capabilities */
list_for_each_entry(codec, &bus->codec_list, list) {
- if (codec->patch_ops.suspend)
- codec->patch_ops.suspend(codec, state);
- hda_set_power_state(codec,
- codec->afg ? codec->afg : codec->mfg,
- AC_PWRST_D3);
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ if (!codec->power_on)
+ continue;
+#endif
+ hda_call_codec_suspend(codec);
}
return 0;
}
@@ -2388,76 +2808,30 @@ int snd_hda_suspend(struct hda_bus *bus, pm_message_t state)
* @state: resume state
*
* Returns 0 if successful.
+ *
+ * This fucntion is defined only when POWER_SAVE isn't set.
+ * In the power-save mode, the codec is resumed dynamically.
*/
int snd_hda_resume(struct hda_bus *bus)
{
struct hda_codec *codec;
list_for_each_entry(codec, &bus->codec_list, list) {
- hda_set_power_state(codec,
- codec->afg ? codec->afg : codec->mfg,
- AC_PWRST_D0);
- if (codec->patch_ops.resume)
- codec->patch_ops.resume(codec);
+ if (snd_hda_codec_needs_resume(codec))
+ hda_call_codec_resume(codec);
}
return 0;
}
-
-/**
- * snd_hda_resume_ctls - resume controls in the new control list
- * @codec: the HDA codec
- * @knew: the array of struct snd_kcontrol_new
- *
- * This function resumes the mixer controls in the struct snd_kcontrol_new array,
- * originally for snd_hda_add_new_ctls().
- * The array must be terminated with an empty entry as terminator.
- */
-int snd_hda_resume_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+int snd_hda_codecs_inuse(struct hda_bus *bus)
{
- struct snd_ctl_elem_value *val;
+ struct hda_codec *codec;
- val = kmalloc(sizeof(*val), GFP_KERNEL);
- if (!val)
- return -ENOMEM;
- codec->in_resume = 1;
- for (; knew->name; knew++) {
- int i, count;
- count = knew->count ? knew->count : 1;
- for (i = 0; i < count; i++) {
- memset(val, 0, sizeof(*val));
- val->id.iface = knew->iface;
- val->id.device = knew->device;
- val->id.subdevice = knew->subdevice;
- strcpy(val->id.name, knew->name);
- val->id.index = knew->index ? knew->index : i;
- /* Assume that get callback reads only from cache,
- * not accessing to the real hardware
- */
- if (snd_ctl_elem_read(codec->bus->card, val) < 0)
- continue;
- snd_ctl_elem_write(codec->bus->card, NULL, val);
- }
+ list_for_each_entry(codec, &bus->codec_list, list) {
+ if (snd_hda_codec_needs_resume(codec))
+ return 1;
}
- codec->in_resume = 0;
- kfree(val);
return 0;
}
-
-/**
- * snd_hda_resume_spdif_out - resume the digital out
- * @codec: the HDA codec
- */
-int snd_hda_resume_spdif_out(struct hda_codec *codec)
-{
- return snd_hda_resume_ctls(codec, dig_mixes);
-}
-
-/**
- * snd_hda_resume_spdif_in - resume the digital in
- * @codec: the HDA codec
- */
-int snd_hda_resume_spdif_in(struct hda_codec *codec)
-{
- return snd_hda_resume_ctls(codec, dig_in_ctls);
-}
+#endif
#endif
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 56c26e7ccdf1..2bce925d84ef 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -24,6 +24,11 @@
#include <sound/info.h>
#include <sound/control.h>
#include <sound/pcm.h>
+#include <sound/hwdep.h>
+
+#if defined(CONFIG_PM) || defined(CONFIG_SND_HDA_POWER_SAVE)
+#define SND_HDA_NEEDS_RESUME /* resume control code is required */
+#endif
/*
* nodes
@@ -199,7 +204,9 @@ enum {
#define AC_AMPCAP_OFFSET_SHIFT 0
#define AC_AMPCAP_NUM_STEPS (0x7f<<8) /* number of steps */
#define AC_AMPCAP_NUM_STEPS_SHIFT 8
-#define AC_AMPCAP_STEP_SIZE (0x7f<<16) /* step size 0-32dB in 0.25dB */
+#define AC_AMPCAP_STEP_SIZE (0x7f<<16) /* step size 0-32dB
+ * in 0.25dB
+ */
#define AC_AMPCAP_STEP_SIZE_SHIFT 16
#define AC_AMPCAP_MUTE (1<<31) /* mute capable */
#define AC_AMPCAP_MUTE_SHIFT 31
@@ -409,6 +416,10 @@ struct hda_bus_ops {
unsigned int (*get_response)(struct hda_codec *codec);
/* free the private data */
void (*private_free)(struct hda_bus *);
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ /* notify power-up/down from codec to contoller */
+ void (*pm_notify)(struct hda_codec *codec);
+#endif
};
/* template to pass to the bus constructor */
@@ -436,7 +447,8 @@ struct hda_bus {
/* codec linked list */
struct list_head codec_list;
- struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1]; /* caddr -> codec */
+ /* link caddr -> codec */
+ struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1];
struct mutex cmd_mutex;
@@ -469,19 +481,34 @@ struct hda_codec_ops {
int (*init)(struct hda_codec *codec);
void (*free)(struct hda_codec *codec);
void (*unsol_event)(struct hda_codec *codec, unsigned int res);
-#ifdef CONFIG_PM
+#ifdef SND_HDA_NEEDS_RESUME
int (*suspend)(struct hda_codec *codec, pm_message_t state);
int (*resume)(struct hda_codec *codec);
#endif
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ int (*check_power_status)(struct hda_codec *codec, hda_nid_t nid);
+#endif
};
/* record for amp information cache */
-struct hda_amp_info {
+struct hda_cache_head {
u32 key; /* hash key */
+ u16 val; /* assigned value */
+ u16 next; /* next link; -1 = terminal */
+};
+
+struct hda_amp_info {
+ struct hda_cache_head head;
u32 amp_caps; /* amp capabilities */
u16 vol[2]; /* current volume & mute */
- u16 status; /* update flag */
- u16 next; /* next link */
+};
+
+struct hda_cache_rec {
+ u16 hash[64]; /* hash table for index */
+ unsigned int num_entries; /* number of assigned entries */
+ unsigned int size; /* allocated size */
+ unsigned int record_size; /* record size (including header) */
+ void *buffer; /* hash table entries */
};
/* PCM callbacks */
@@ -499,7 +526,7 @@ struct hda_pcm_ops {
/* PCM information for each substream */
struct hda_pcm_stream {
- unsigned int substreams; /* number of substreams, 0 = not exist */
+ unsigned int substreams; /* number of substreams, 0 = not exist*/
unsigned int channels_min; /* min. number of channels */
unsigned int channels_max; /* max. number of channels */
hda_nid_t nid; /* default NID to query rates/formats/bps, or set up */
@@ -536,11 +563,6 @@ struct hda_codec {
/* set by patch */
struct hda_codec_ops patch_ops;
- /* resume phase - all controls should update even if
- * the values are not changed
- */
- unsigned int in_resume;
-
/* PCM to create, set by patch_ops.build_pcms callback */
unsigned int num_pcms;
struct hda_pcm *pcm_info;
@@ -553,16 +575,22 @@ struct hda_codec {
hda_nid_t start_nid;
u32 *wcaps;
- /* hash for amp access */
- u16 amp_hash[32];
- int num_amp_entries;
- int amp_info_size;
- struct hda_amp_info *amp_info;
+ struct hda_cache_rec amp_cache; /* cache for amp access */
+ struct hda_cache_rec cmd_cache; /* cache for other commands */
struct mutex spdif_mutex;
unsigned int spdif_status; /* IEC958 status bits */
unsigned short spdif_ctls; /* SPDIF control bits */
unsigned int spdif_in_enable; /* SPDIF input enable? */
+
+ struct snd_hwdep *hwdep; /* assigned hwdep device */
+
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ unsigned int power_on :1; /* current (global) power-state */
+ unsigned int power_transition :1; /* power-state in transition */
+ int power_count; /* current (global) power refcount */
+ struct delayed_work power_work; /* delayed task for powerdown */
+#endif
};
/* direction */
@@ -582,13 +610,17 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
/*
* low level functions
*/
-unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, int direct,
+unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
+ int direct,
unsigned int verb, unsigned int parm);
int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct,
unsigned int verb, unsigned int parm);
-#define snd_hda_param_read(codec, nid, param) snd_hda_codec_read(codec, nid, 0, AC_VERB_PARAMETERS, param)
-int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid, hda_nid_t *start_id);
-int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, hda_nid_t *conn_list, int max_conns);
+#define snd_hda_param_read(codec, nid, param) \
+ snd_hda_codec_read(codec, nid, 0, AC_VERB_PARAMETERS, param)
+int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
+ hda_nid_t *start_id);
+int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
+ hda_nid_t *conn_list, int max_conns);
struct hda_verb {
hda_nid_t nid;
@@ -596,11 +628,24 @@ struct hda_verb {
u32 param;
};
-void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq);
+void snd_hda_sequence_write(struct hda_codec *codec,
+ const struct hda_verb *seq);
/* unsolicited event */
int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex);
+/* cached write */
+#ifdef SND_HDA_NEEDS_RESUME
+int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
+ int direct, unsigned int verb, unsigned int parm);
+void snd_hda_sequence_write_cache(struct hda_codec *codec,
+ const struct hda_verb *seq);
+void snd_hda_codec_resume_cache(struct hda_codec *codec);
+#else
+#define snd_hda_codec_write_cache snd_hda_codec_write
+#define snd_hda_sequence_write_cache snd_hda_sequence_write
+#endif
+
/*
* Mixer
*/
@@ -610,10 +655,13 @@ int snd_hda_build_controls(struct hda_bus *bus);
* PCM
*/
int snd_hda_build_pcms(struct hda_bus *bus);
-void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, u32 stream_tag,
+void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
+ u32 stream_tag,
int channel_id, int format);
-unsigned int snd_hda_calc_stream_format(unsigned int rate, unsigned int channels,
- unsigned int format, unsigned int maxbps);
+unsigned int snd_hda_calc_stream_format(unsigned int rate,
+ unsigned int channels,
+ unsigned int format,
+ unsigned int maxbps);
int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
u32 *ratesp, u64 *formatsp, unsigned int *bpsp);
int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
@@ -632,4 +680,19 @@ int snd_hda_suspend(struct hda_bus *bus, pm_message_t state);
int snd_hda_resume(struct hda_bus *bus);
#endif
+/*
+ * power saving
+ */
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+void snd_hda_power_up(struct hda_codec *codec);
+void snd_hda_power_down(struct hda_codec *codec);
+#define snd_hda_codec_needs_resume(codec) codec->power_count
+int snd_hda_codecs_inuse(struct hda_bus *bus);
+#else
+static inline void snd_hda_power_up(struct hda_codec *codec) {}
+static inline void snd_hda_power_down(struct hda_codec *codec) {}
+#define snd_hda_codec_needs_resume(codec) 1
+#define snd_hda_codecs_inuse(bus) 1
+#endif
+
#endif /* __SOUND_HDA_CODEC_H */
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 000287f7da43..c957eb58de5c 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -70,6 +70,13 @@ struct hda_gspec {
struct hda_pcm pcm_rec; /* PCM information */
struct list_head nid_list; /* list of widgets */
+
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+#define MAX_LOOPBACK_AMPS 7
+ struct hda_loopback_check loopback;
+ int num_loopbacks;
+ struct hda_amp_list loopback_list[MAX_LOOPBACK_AMPS + 1];
+#endif
};
/*
@@ -88,13 +95,12 @@ struct hda_gspec {
static void snd_hda_generic_free(struct hda_codec *codec)
{
struct hda_gspec *spec = codec->spec;
- struct list_head *p, *n;
+ struct hda_gnode *node, *n;
if (! spec)
return;
/* free all widgets */
- list_for_each_safe(p, n, &spec->nid_list) {
- struct hda_gnode *node = list_entry(p, struct hda_gnode, list);
+ list_for_each_entry_safe(node, n, &spec->nid_list, list) {
if (node->conn_list != node->slist)
kfree(node->conn_list);
kfree(node);
@@ -196,11 +202,9 @@ static int build_afg_tree(struct hda_codec *codec)
/* FIXME: should avoid the braindead linear search */
static struct hda_gnode *hda_get_node(struct hda_gspec *spec, hda_nid_t nid)
{
- struct list_head *p;
struct hda_gnode *node;
- list_for_each(p, &spec->nid_list) {
- node = list_entry(p, struct hda_gnode, list);
+ list_for_each_entry(node, &spec->nid_list, list) {
if (node->nid == nid)
return node;
}
@@ -218,9 +222,8 @@ static int unmute_output(struct hda_codec *codec, struct hda_gnode *node)
ofs = (node->amp_out_caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT;
if (val >= ofs)
val -= ofs;
- val |= AC_AMP_SET_LEFT | AC_AMP_SET_RIGHT;
- val |= AC_AMP_SET_OUTPUT;
- return snd_hda_codec_write(codec, node->nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, val);
+ snd_hda_codec_amp_stereo(codec, node->nid, HDA_OUTPUT, 0, 0xff, val);
+ return 0;
}
/*
@@ -234,11 +237,8 @@ static int unmute_input(struct hda_codec *codec, struct hda_gnode *node, unsigne
ofs = (node->amp_in_caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT;
if (val >= ofs)
val -= ofs;
- val |= AC_AMP_SET_LEFT | AC_AMP_SET_RIGHT;
- val |= AC_AMP_SET_INPUT;
- // awk added - fixed to allow unmuting of indexed amps
- val |= index << AC_AMP_SET_INDEX_SHIFT;
- return snd_hda_codec_write(codec, node->nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, val);
+ snd_hda_codec_amp_stereo(codec, node->nid, HDA_INPUT, index, 0xff, val);
+ return 0;
}
/*
@@ -248,7 +248,8 @@ static int select_input_connection(struct hda_codec *codec, struct hda_gnode *no
unsigned int index)
{
snd_printdd("CONNECT: NID=0x%x IDX=0x%x\n", node->nid, index);
- return snd_hda_codec_write(codec, node->nid, 0, AC_VERB_SET_CONNECT_SEL, index);
+ return snd_hda_codec_write_cache(codec, node->nid, 0,
+ AC_VERB_SET_CONNECT_SEL, index);
}
/*
@@ -256,11 +257,9 @@ static int select_input_connection(struct hda_codec *codec, struct hda_gnode *no
*/
static void clear_check_flags(struct hda_gspec *spec)
{
- struct list_head *p;
struct hda_gnode *node;
- list_for_each(p, &spec->nid_list) {
- node = list_entry(p, struct hda_gnode, list);
+ list_for_each_entry(node, &spec->nid_list, list) {
node->checked = 0;
}
}
@@ -343,12 +342,10 @@ static struct hda_gnode *parse_output_jack(struct hda_codec *codec,
struct hda_gspec *spec,
int jack_type)
{
- struct list_head *p;
struct hda_gnode *node;
int err;
- list_for_each(p, &spec->nid_list) {
- node = list_entry(p, struct hda_gnode, list);
+ list_for_each_entry(node, &spec->nid_list, list) {
if (node->type != AC_WID_PIN)
continue;
/* output capable? */
@@ -379,7 +376,7 @@ static struct hda_gnode *parse_output_jack(struct hda_codec *codec,
/* unmute the PIN output */
unmute_output(codec, node);
/* set PIN-Out enable */
- snd_hda_codec_write(codec, node->nid, 0,
+ snd_hda_codec_write_cache(codec, node->nid, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL,
AC_PINCTL_OUT_EN |
((node->pin_caps & AC_PINCAP_HP_DRV) ?
@@ -570,7 +567,8 @@ static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec,
/* unmute the PIN external input */
unmute_input(codec, node, 0); /* index = 0? */
/* set PIN-In enable */
- snd_hda_codec_write(codec, node->nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl);
+ snd_hda_codec_write_cache(codec, node->nid, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl);
return 1; /* found */
}
@@ -659,7 +657,6 @@ static int parse_input_path(struct hda_codec *codec, struct hda_gnode *adc_node)
static int parse_input(struct hda_codec *codec)
{
struct hda_gspec *spec = codec->spec;
- struct list_head *p;
struct hda_gnode *node;
int err;
@@ -668,8 +665,7 @@ static int parse_input(struct hda_codec *codec)
* If it reaches to certain input PINs, we take it as the
* input path.
*/
- list_for_each(p, &spec->nid_list) {
- node = list_entry(p, struct hda_gnode, list);
+ list_for_each_entry(node, &spec->nid_list, list) {
if (node->wid_caps & AC_WCAP_DIGITAL)
continue; /* skip SPDIF */
if (node->type == AC_WID_AUD_IN) {
@@ -684,11 +680,33 @@ static int parse_input(struct hda_codec *codec)
return 0;
}
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static void add_input_loopback(struct hda_codec *codec, hda_nid_t nid,
+ int dir, int idx)
+{
+ struct hda_gspec *spec = codec->spec;
+ struct hda_amp_list *p;
+
+ if (spec->num_loopbacks >= MAX_LOOPBACK_AMPS) {
+ snd_printk(KERN_ERR "hda_generic: Too many loopback ctls\n");
+ return;
+ }
+ p = &spec->loopback_list[spec->num_loopbacks++];
+ p->nid = nid;
+ p->dir = dir;
+ p->idx = idx;
+ spec->loopback.amplist = spec->loopback_list;
+}
+#else
+#define add_input_loopback(codec,nid,dir,idx)
+#endif
+
/*
* create mixer controls if possible
*/
static int create_mixer(struct hda_codec *codec, struct hda_gnode *node,
- unsigned int index, const char *type, const char *dir_sfx)
+ unsigned int index, const char *type,
+ const char *dir_sfx, int is_loopback)
{
char name[32];
int err;
@@ -702,6 +720,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node,
if ((node->wid_caps & AC_WCAP_IN_AMP) &&
(node->amp_in_caps & AC_AMPCAP_MUTE)) {
knew = (struct snd_kcontrol_new)HDA_CODEC_MUTE(name, node->nid, index, HDA_INPUT);
+ if (is_loopback)
+ add_input_loopback(codec, node->nid, HDA_INPUT, index);
snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index);
if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0)
return err;
@@ -709,6 +729,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node,
} else if ((node->wid_caps & AC_WCAP_OUT_AMP) &&
(node->amp_out_caps & AC_AMPCAP_MUTE)) {
knew = (struct snd_kcontrol_new)HDA_CODEC_MUTE(name, node->nid, 0, HDA_OUTPUT);
+ if (is_loopback)
+ add_input_loopback(codec, node->nid, HDA_OUTPUT, 0);
snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid);
if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0)
return err;
@@ -767,7 +789,7 @@ static int create_output_mixers(struct hda_codec *codec, const char **names)
for (i = 0; i < spec->pcm_vol_nodes; i++) {
err = create_mixer(codec, spec->pcm_vol[i].node,
spec->pcm_vol[i].index,
- names[i], "Playback");
+ names[i], "Playback", 0);
if (err < 0)
return err;
}
@@ -784,7 +806,7 @@ static int build_output_controls(struct hda_codec *codec)
case 1:
return create_mixer(codec, spec->pcm_vol[0].node,
spec->pcm_vol[0].index,
- "Master", "Playback");
+ "Master", "Playback", 0);
case 2:
if (defcfg_type(spec->out_pin_node[0]) == AC_JACK_SPEAKER)
return create_output_mixers(codec, types_speaker);
@@ -820,7 +842,7 @@ static int build_input_controls(struct hda_codec *codec)
if (spec->input_mux.num_items == 1) {
err = create_mixer(codec, adc_node,
spec->input_mux.items[0].index,
- NULL, "Capture");
+ NULL, "Capture", 0);
if (err < 0)
return err;
return 0;
@@ -886,7 +908,8 @@ static int parse_loopback_path(struct hda_codec *codec, struct hda_gspec *spec,
return err;
else if (err >= 1) {
if (err == 1) {
- err = create_mixer(codec, node, i, type, "Playback");
+ err = create_mixer(codec, node, i, type,
+ "Playback", 1);
if (err < 0)
return err;
if (err > 0)
@@ -911,7 +934,6 @@ static int parse_loopback_path(struct hda_codec *codec, struct hda_gspec *spec,
static int build_loopback_controls(struct hda_codec *codec)
{
struct hda_gspec *spec = codec->spec;
- struct list_head *p;
struct hda_gnode *node;
int err;
const char *type;
@@ -919,8 +941,7 @@ static int build_loopback_controls(struct hda_codec *codec)
if (! spec->out_pin_node[0])
return 0;
- list_for_each(p, &spec->nid_list) {
- node = list_entry(p, struct hda_gnode, list);
+ list_for_each_entry(node, &spec->nid_list, list) {
if (node->type != AC_WID_PIN)
continue;
/* input capable? */
@@ -1022,6 +1043,14 @@ static int build_generic_pcms(struct hda_codec *codec)
return 0;
}
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static int generic_check_power_status(struct hda_codec *codec, hda_nid_t nid)
+{
+ struct hda_gspec *spec = codec->spec;
+ return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
+}
+#endif
+
/*
*/
@@ -1029,6 +1058,9 @@ static struct hda_codec_ops generic_patch_ops = {
.build_controls = build_generic_controls,
.build_pcms = build_generic_pcms,
.free = snd_hda_generic_free,
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ .check_power_status = generic_check_power_status,
+#endif
};
/*
diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c
new file mode 100644
index 000000000000..bafb7b01f5a1
--- /dev/null
+++ b/sound/pci/hda/hda_hwdep.c
@@ -0,0 +1,122 @@
+/*
+ * HWDEP Interface for HD-audio codec
+ *
+ * Copyright (c) 2007 Takashi Iwai <tiwai@suse.de>
+ *
+ * This driver is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This driver is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <sound/driver.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/compat.h>
+#include <linux/mutex.h>
+#include <sound/core.h>
+#include "hda_codec.h"
+#include "hda_local.h"
+#include <sound/hda_hwdep.h>
+
+/*
+ * write/read an out-of-bound verb
+ */
+static int verb_write_ioctl(struct hda_codec *codec,
+ struct hda_verb_ioctl __user *arg)
+{
+ u32 verb, res;
+
+ if (get_user(verb, &arg->verb))
+ return -EFAULT;
+ res = snd_hda_codec_read(codec, verb >> 24, 0,
+ (verb >> 8) & 0xffff, verb & 0xff);
+ if (put_user(res, &arg->res))
+ return -EFAULT;
+ return 0;
+}
+
+static int get_wcap_ioctl(struct hda_codec *codec,
+ struct hda_verb_ioctl __user *arg)
+{
+ u32 verb, res;
+
+ if (get_user(verb, &arg->verb))
+ return -EFAULT;
+ res = get_wcaps(codec, verb >> 24);
+ if (put_user(res, &arg->res))
+ return -EFAULT;
+ return 0;
+}
+
+
+/*
+ */
+static int hda_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct hda_codec *codec = hw->private_data;
+ void __user *argp = (void __user *)arg;
+
+ switch (cmd) {
+ case HDA_IOCTL_PVERSION:
+ return put_user(HDA_HWDEP_VERSION, (int __user *)argp);
+ case HDA_IOCTL_VERB_WRITE:
+ return verb_write_ioctl(codec, argp);
+ case HDA_IOCTL_GET_WCAP:
+ return get_wcap_ioctl(codec, argp);
+ }
+ return -ENOIOCTLCMD;
+}
+
+#ifdef CONFIG_COMPAT
+static int hda_hwdep_ioctl_compat(struct snd_hwdep *hw, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ return hda_hwdep_ioctl(hw, file, cmd, (unsigned long)compat_ptr(arg));
+}
+#endif
+
+static int hda_hwdep_open(struct snd_hwdep *hw, struct file *file)
+{
+#ifndef CONFIG_SND_DEBUG_DETECT
+ if (!capable(CAP_SYS_RAWIO))
+ return -EACCES;
+#endif
+ return 0;
+}
+
+int __devinit snd_hda_create_hwdep(struct hda_codec *codec)
+{
+ char hwname[16];
+ struct snd_hwdep *hwdep;
+ int err;
+
+ sprintf(hwname, "HDA Codec %d", codec->addr);
+ err = snd_hwdep_new(codec->bus->card, hwname, codec->addr, &hwdep);
+ if (err < 0)
+ return err;
+ codec->hwdep = hwdep;
+ sprintf(hwdep->name, "HDA Codec %d", codec->addr);
+ hwdep->iface = SNDRV_HWDEP_IFACE_HDA;
+ hwdep->private_data = codec;
+ hwdep->exclusive = 1;
+
+ hwdep->ops.open = hda_hwdep_open;
+ hwdep->ops.ioctl = hda_hwdep_ioctl;
+#ifdef CONFIG_COMPAT
+ hwdep->ops.ioctl_compat = hda_hwdep_ioctl_compat;
+#endif
+
+ return 0;
+}
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 92bc8b3fa2a0..3fa0f9704909 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -1,6 +1,7 @@
/*
*
- * hda_intel.c - Implementation of primary alsa driver code base for Intel HD Audio.
+ * hda_intel.c - Implementation of primary alsa driver code base
+ * for Intel HD Audio.
*
* Copyright(c) 2004 Intel Corporation. All rights reserved.
*
@@ -64,14 +65,27 @@ MODULE_PARM_DESC(id, "ID string for Intel HD audio interface.");
module_param(model, charp, 0444);
MODULE_PARM_DESC(model, "Use the given board model.");
module_param(position_fix, int, 0444);
-MODULE_PARM_DESC(position_fix, "Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size).");
+MODULE_PARM_DESC(position_fix, "Fix DMA pointer "
+ "(0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size).");
module_param(probe_mask, int, 0444);
MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1).");
module_param(single_cmd, bool, 0444);
-MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs (for debugging only).");
+MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs "
+ "(for debugging only).");
module_param(enable_msi, int, 0);
MODULE_PARM_DESC(enable_msi, "Enable Message Signaled Interrupt (MSI)");
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+/* power_save option is defined in hda_codec.c */
+
+/* reset the HD-audio controller in power save mode.
+ * this may give more power-saving, but will take longer time to
+ * wake up.
+ */
+static int power_save_controller = 1;
+module_param(power_save_controller, bool, 0644);
+MODULE_PARM_DESC(power_save_controller, "Reset controller in power save mode.");
+#endif
/* just for backward compatibility */
static int enable;
@@ -98,6 +112,7 @@ MODULE_DESCRIPTION("Intel HDA driver");
#define SFX "hda-intel: "
+
/*
* registers
*/
@@ -213,15 +228,16 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
#define SD_INT_DESC_ERR 0x10 /* descriptor error interrupt */
#define SD_INT_FIFO_ERR 0x08 /* FIFO error interrupt */
#define SD_INT_COMPLETE 0x04 /* completion interrupt */
-#define SD_INT_MASK (SD_INT_DESC_ERR|SD_INT_FIFO_ERR|SD_INT_COMPLETE)
+#define SD_INT_MASK (SD_INT_DESC_ERR|SD_INT_FIFO_ERR|\
+ SD_INT_COMPLETE)
/* SD_STS */
#define SD_STS_FIFO_READY 0x20 /* FIFO ready */
/* INTCTL and INTSTS */
-#define ICH6_INT_ALL_STREAM 0xff /* all stream interrupts */
-#define ICH6_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */
-#define ICH6_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */
+#define ICH6_INT_ALL_STREAM 0xff /* all stream interrupts */
+#define ICH6_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */
+#define ICH6_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */
/* GCTL unsolicited response enable bit */
#define ICH6_GCTL_UREN (1<<8)
@@ -257,22 +273,26 @@ enum {
*/
struct azx_dev {
- u32 *bdl; /* virtual address of the BDL */
- dma_addr_t bdl_addr; /* physical address of the BDL */
- u32 *posbuf; /* position buffer pointer */
+ u32 *bdl; /* virtual address of the BDL */
+ dma_addr_t bdl_addr; /* physical address of the BDL */
+ u32 *posbuf; /* position buffer pointer */
- unsigned int bufsize; /* size of the play buffer in bytes */
- unsigned int fragsize; /* size of each period in bytes */
- unsigned int frags; /* number for period in the play buffer */
- unsigned int fifo_size; /* FIFO size */
+ unsigned int bufsize; /* size of the play buffer in bytes */
+ unsigned int fragsize; /* size of each period in bytes */
+ unsigned int frags; /* number for period in the play buffer */
+ unsigned int fifo_size; /* FIFO size */
- void __iomem *sd_addr; /* stream descriptor pointer */
+ void __iomem *sd_addr; /* stream descriptor pointer */
- u32 sd_int_sta_mask; /* stream int status mask */
+ u32 sd_int_sta_mask; /* stream int status mask */
/* pcm support */
- struct snd_pcm_substream *substream; /* assigned substream, set in PCM open */
- unsigned int format_val; /* format value to be set in the controller and the codec */
+ struct snd_pcm_substream *substream; /* assigned substream,
+ * set in PCM open
+ */
+ unsigned int format_val; /* format value to be set in the
+ * controller and the codec
+ */
unsigned char stream_tag; /* assigned stream */
unsigned char index; /* stream index */
/* for sanity check of position buffer */
@@ -337,6 +357,7 @@ struct azx {
/* flags */
int position_fix;
+ unsigned int running :1;
unsigned int initialized :1;
unsigned int single_cmd :1;
unsigned int polling_mode :1;
@@ -418,7 +439,8 @@ static int azx_alloc_cmd_io(struct azx *chip)
int err;
/* single page (at least 4096 bytes) must suffice for both ringbuffes */
- err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+ err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(chip->pci),
PAGE_SIZE, &chip->rb);
if (err < 0) {
snd_printk(KERN_ERR SFX "cannot allocate CORB/RIRB\n");
@@ -531,9 +553,9 @@ static unsigned int azx_rirb_get_response(struct hda_codec *codec)
azx_update_rirb(chip);
spin_unlock_irq(&chip->reg_lock);
}
- if (! chip->rirb.cmds)
+ if (!chip->rirb.cmds)
return chip->rirb.res; /* the last value */
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
} while (time_after_eq(timeout, jiffies));
if (chip->msi) {
@@ -585,16 +607,19 @@ static int azx_single_send_cmd(struct hda_codec *codec, u32 val)
while (timeout--) {
/* check ICB busy bit */
- if (! (azx_readw(chip, IRS) & ICH6_IRS_BUSY)) {
+ if (!((azx_readw(chip, IRS) & ICH6_IRS_BUSY))) {
/* Clear IRV valid bit */
- azx_writew(chip, IRS, azx_readw(chip, IRS) | ICH6_IRS_VALID);
+ azx_writew(chip, IRS, azx_readw(chip, IRS) |
+ ICH6_IRS_VALID);
azx_writel(chip, IC, val);
- azx_writew(chip, IRS, azx_readw(chip, IRS) | ICH6_IRS_BUSY);
+ azx_writew(chip, IRS, azx_readw(chip, IRS) |
+ ICH6_IRS_BUSY);
return 0;
}
udelay(1);
}
- snd_printd(SFX "send_cmd timeout: IRS=0x%x, val=0x%x\n", azx_readw(chip, IRS), val);
+ snd_printd(SFX "send_cmd timeout: IRS=0x%x, val=0x%x\n",
+ azx_readw(chip, IRS), val);
return -EIO;
}
@@ -610,7 +635,8 @@ static unsigned int azx_single_get_response(struct hda_codec *codec)
return azx_readl(chip, IR);
udelay(1);
}
- snd_printd(SFX "get_response timeout: IRS=0x%x\n", azx_readw(chip, IRS));
+ snd_printd(SFX "get_response timeout: IRS=0x%x\n",
+ azx_readw(chip, IRS));
return (unsigned int)-1;
}
@@ -652,12 +678,18 @@ static unsigned int azx_get_response(struct hda_codec *codec)
return azx_rirb_get_response(codec);
}
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static void azx_power_notify(struct hda_codec *codec);
+#endif
/* reset codec link */
static int azx_reset(struct azx *chip)
{
int count;
+ /* clear STATESTS */
+ azx_writeb(chip, STATESTS, STATESTS_INT_MASK);
+
/* reset controller */
azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_RESET);
@@ -777,18 +809,12 @@ static void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev)
/*
- * initialize the chip
+ * reset and start the controller registers
*/
static void azx_init_chip(struct azx *chip)
{
- unsigned char reg;
-
- /* Clear bits 0-2 of PCI register TCSEL (at offset 0x44)
- * TCSEL == Traffic Class Select Register, which sets PCI express QOS
- * Ensuring these bits are 0 clears playback static on some HD Audio codecs
- */
- pci_read_config_byte (chip->pci, ICH6_PCIREG_TCSEL, &reg);
- pci_write_config_byte(chip->pci, ICH6_PCIREG_TCSEL, reg & 0xf8);
+ if (chip->initialized)
+ return;
/* reset controller */
azx_reset(chip);
@@ -805,19 +831,45 @@ static void azx_init_chip(struct azx *chip)
azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr);
azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr));
+ chip->initialized = 1;
+}
+
+/*
+ * initialize the PCI registers
+ */
+/* update bits in a PCI register byte */
+static void update_pci_byte(struct pci_dev *pci, unsigned int reg,
+ unsigned char mask, unsigned char val)
+{
+ unsigned char data;
+
+ pci_read_config_byte(pci, reg, &data);
+ data &= ~mask;
+ data |= (val & mask);
+ pci_write_config_byte(pci, reg, data);
+}
+
+static void azx_init_pci(struct azx *chip)
+{
+ /* Clear bits 0-2 of PCI register TCSEL (at offset 0x44)
+ * TCSEL == Traffic Class Select Register, which sets PCI express QOS
+ * Ensuring these bits are 0 clears playback static on some HD Audio
+ * codecs
+ */
+ update_pci_byte(chip->pci, ICH6_PCIREG_TCSEL, 0x07, 0);
+
switch (chip->driver_type) {
case AZX_DRIVER_ATI:
/* For ATI SB450 azalia HD audio, we need to enable snoop */
- pci_read_config_byte(chip->pci, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR,
- &reg);
- pci_write_config_byte(chip->pci, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR,
- (reg & 0xf8) | ATI_SB450_HDAUDIO_ENABLE_SNOOP);
+ update_pci_byte(chip->pci,
+ ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR,
+ 0x07, ATI_SB450_HDAUDIO_ENABLE_SNOOP);
break;
case AZX_DRIVER_NVIDIA:
/* For NVIDIA HDA, enable snoop */
- pci_read_config_byte(chip->pci,NVIDIA_HDA_TRANSREG_ADDR, &reg);
- pci_write_config_byte(chip->pci,NVIDIA_HDA_TRANSREG_ADDR,
- (reg & 0xf0) | NVIDIA_HDA_ENABLE_COHBITS);
+ update_pci_byte(chip->pci,
+ NVIDIA_HDA_TRANSREG_ADDR,
+ 0x0f, NVIDIA_HDA_ENABLE_COHBITS);
break;
}
}
@@ -857,7 +909,7 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id)
/* clear rirb int */
status = azx_readb(chip, RIRBSTS);
if (status & RIRB_INT_MASK) {
- if (! chip->single_cmd && (status & RIRB_INT_RESPONSE))
+ if (!chip->single_cmd && (status & RIRB_INT_RESPONSE))
azx_update_rirb(chip);
azx_writeb(chip, RIRBSTS, RIRB_INT_MASK);
}
@@ -911,9 +963,11 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
int timeout;
/* make sure the run bit is zero for SD */
- azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) & ~SD_CTL_DMA_START);
+ azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) &
+ ~SD_CTL_DMA_START);
/* reset stream */
- azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) | SD_CTL_STREAM_RESET);
+ azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) |
+ SD_CTL_STREAM_RESET);
udelay(3);
timeout = 300;
while (!((val = azx_sd_readb(azx_dev, SD_CTL)) & SD_CTL_STREAM_RESET) &&
@@ -931,7 +985,7 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
/* program the stream_tag */
azx_sd_writel(azx_dev, SD_CTL,
- (azx_sd_readl(azx_dev, SD_CTL) & ~SD_CTL_STREAM_TAG_MASK) |
+ (azx_sd_readl(azx_dev, SD_CTL) & ~SD_CTL_STREAM_TAG_MASK)|
(azx_dev->stream_tag << SD_CTL_STREAM_TAG_SHIFT));
/* program the length of samples in cyclic buffer */
@@ -951,11 +1005,13 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr));
/* enable the position buffer */
- if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
- azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
+ if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
+ azx_writel(chip, DPLBASE,
+ (u32)chip->posbuf.addr |ICH6_DPLBASE_ENABLE);
/* set the interrupt enable bits in the descriptor control register */
- azx_sd_writel(azx_dev, SD_CTL, azx_sd_readl(azx_dev, SD_CTL) | SD_INT_MASK);
+ azx_sd_writel(azx_dev, SD_CTL,
+ azx_sd_readl(azx_dev, SD_CTL) | SD_INT_MASK);
return 0;
}
@@ -986,8 +1042,12 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model)
bus_temp.pci = chip->pci;
bus_temp.ops.command = azx_send_cmd;
bus_temp.ops.get_response = azx_get_response;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ bus_temp.ops.pm_notify = azx_power_notify;
+#endif
- if ((err = snd_hda_bus_new(chip->card, &bus_temp, &chip->bus)) < 0)
+ err = snd_hda_bus_new(chip->card, &bus_temp, &chip->bus);
+ if (err < 0)
return err;
codecs = audio_codecs = 0;
@@ -1038,7 +1098,7 @@ static inline struct azx_dev *azx_assign_device(struct azx *chip, int stream)
nums = chip->capture_streams;
}
for (i = 0; i < nums; i++, dev++)
- if (! chip->azx_dev[dev].opened) {
+ if (!chip->azx_dev[dev].opened) {
chip->azx_dev[dev].opened = 1;
return &chip->azx_dev[dev];
}
@@ -1052,7 +1112,8 @@ static inline void azx_release_device(struct azx_dev *azx_dev)
}
static struct snd_pcm_hardware azx_pcm_hw = {
- .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+ .info = (SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP_VALID |
/* No full-resume yet implemented */
@@ -1105,8 +1166,11 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
128);
snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
128);
- if ((err = hinfo->ops.open(hinfo, apcm->codec, substream)) < 0) {
+ snd_hda_power_up(apcm->codec);
+ err = hinfo->ops.open(hinfo, apcm->codec, substream);
+ if (err < 0) {
azx_release_device(azx_dev);
+ snd_hda_power_down(apcm->codec);
mutex_unlock(&chip->open_mutex);
return err;
}
@@ -1135,13 +1199,16 @@ static int azx_pcm_close(struct snd_pcm_substream *substream)
spin_unlock_irqrestore(&chip->reg_lock, flags);
azx_release_device(azx_dev);
hinfo->ops.close(hinfo, apcm->codec, substream);
+ snd_hda_power_down(apcm->codec);
mutex_unlock(&chip->open_mutex);
return 0;
}
-static int azx_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params)
+static int azx_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
+ return snd_pcm_lib_malloc_pages(substream,
+ params_buffer_bytes(hw_params));
}
static int azx_pcm_hw_free(struct snd_pcm_substream *substream)
@@ -1175,13 +1242,15 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
runtime->channels,
runtime->format,
hinfo->maxbps);
- if (! azx_dev->format_val) {
- snd_printk(KERN_ERR SFX "invalid format_val, rate=%d, ch=%d, format=%d\n",
+ if (!azx_dev->format_val) {
+ snd_printk(KERN_ERR SFX
+ "invalid format_val, rate=%d, ch=%d, format=%d\n",
runtime->rate, runtime->channels, runtime->format);
return -EINVAL;
}
- snd_printdd("azx_pcm_prepare: bufsize=0x%x, fragsize=0x%x, format=0x%x\n",
+ snd_printdd("azx_pcm_prepare: bufsize=0x%x, fragsize=0x%x, "
+ "format=0x%x\n",
azx_dev->bufsize, azx_dev->fragsize, azx_dev->format_val);
azx_setup_periods(azx_dev);
azx_setup_controller(chip, azx_dev);
@@ -1223,7 +1292,8 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
cmd == SNDRV_PCM_TRIGGER_SUSPEND ||
cmd == SNDRV_PCM_TRIGGER_STOP) {
int timeout = 5000;
- while (azx_sd_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START && --timeout)
+ while ((azx_sd_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START) &&
+ --timeout)
;
}
return err;
@@ -1241,7 +1311,7 @@ static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream)
/* use the position buffer */
pos = le32_to_cpu(*azx_dev->posbuf);
if (chip->position_fix == POS_FIX_AUTO &&
- azx_dev->period_intr == 1 && ! pos) {
+ azx_dev->period_intr == 1 && !pos) {
printk(KERN_WARNING
"hda-intel: Invalid position buffer, "
"using LPIB read method instead.\n");
@@ -1292,7 +1362,8 @@ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec,
snd_assert(cpcm->name, return -EINVAL);
err = snd_pcm_new(chip->card, cpcm->name, pcm_dev,
- cpcm->stream[0].substreams, cpcm->stream[1].substreams,
+ cpcm->stream[0].substreams,
+ cpcm->stream[1].substreams,
&pcm);
if (err < 0)
return err;
@@ -1322,26 +1393,27 @@ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec,
static int __devinit azx_pcm_create(struct azx *chip)
{
- struct list_head *p;
struct hda_codec *codec;
int c, err;
int pcm_dev;
- if ((err = snd_hda_build_pcms(chip->bus)) < 0)
+ err = snd_hda_build_pcms(chip->bus);
+ if (err < 0)
return err;
/* create audio PCMs */
pcm_dev = 0;
- list_for_each(p, &chip->bus->codec_list) {
- codec = list_entry(p, struct hda_codec, list);
+ list_for_each_entry(codec, &chip->bus->codec_list, list) {
for (c = 0; c < codec->num_pcms; c++) {
if (codec->pcm_info[c].is_modem)
continue; /* create later */
if (pcm_dev >= AZX_MAX_AUDIO_PCMS) {
- snd_printk(KERN_ERR SFX "Too many audio PCMs\n");
+ snd_printk(KERN_ERR SFX
+ "Too many audio PCMs\n");
return -EINVAL;
}
- err = create_codec_pcm(chip, codec, &codec->pcm_info[c], pcm_dev);
+ err = create_codec_pcm(chip, codec,
+ &codec->pcm_info[c], pcm_dev);
if (err < 0)
return err;
pcm_dev++;
@@ -1350,16 +1422,17 @@ static int __devinit azx_pcm_create(struct azx *chip)
/* create modem PCMs */
pcm_dev = AZX_MAX_AUDIO_PCMS;
- list_for_each(p, &chip->bus->codec_list) {
- codec = list_entry(p, struct hda_codec, list);
+ list_for_each_entry(codec, &chip->bus->codec_list, list) {
for (c = 0; c < codec->num_pcms; c++) {
- if (! codec->pcm_info[c].is_modem)
+ if (!codec->pcm_info[c].is_modem)
continue; /* already created */
if (pcm_dev >= AZX_MAX_PCMS) {
- snd_printk(KERN_ERR SFX "Too many modem PCMs\n");
+ snd_printk(KERN_ERR SFX
+ "Too many modem PCMs\n");
return -EINVAL;
}
- err = create_codec_pcm(chip, codec, &codec->pcm_info[c], pcm_dev);
+ err = create_codec_pcm(chip, codec,
+ &codec->pcm_info[c], pcm_dev);
if (err < 0)
return err;
chip->pcm[pcm_dev]->dev_class = SNDRV_PCM_CLASS_MODEM;
@@ -1386,7 +1459,8 @@ static int __devinit azx_init_stream(struct azx *chip)
int i;
/* initialize each stream (aka device)
- * assign the starting bdl address to each stream (device) and initialize
+ * assign the starting bdl address to each stream (device)
+ * and initialize
*/
for (i = 0; i < chip->num_streams; i++) {
unsigned int off = sizeof(u32) * (i * AZX_MAX_FRAG * 4);
@@ -1423,6 +1497,46 @@ static int azx_acquire_irq(struct azx *chip, int do_disconnect)
}
+static void azx_stop_chip(struct azx *chip)
+{
+ if (!chip->initialized)
+ return;
+
+ /* disable interrupts */
+ azx_int_disable(chip);
+ azx_int_clear(chip);
+
+ /* disable CORB/RIRB */
+ azx_free_cmd_io(chip);
+
+ /* disable position buffer */
+ azx_writel(chip, DPLBASE, 0);
+ azx_writel(chip, DPUBASE, 0);
+
+ chip->initialized = 0;
+}
+
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+/* power-up/down the controller */
+static void azx_power_notify(struct hda_codec *codec)
+{
+ struct azx *chip = codec->bus->private_data;
+ struct hda_codec *c;
+ int power_on = 0;
+
+ list_for_each_entry(c, &codec->bus->codec_list, list) {
+ if (c->power_on) {
+ power_on = 1;
+ break;
+ }
+ }
+ if (power_on)
+ azx_init_chip(chip);
+ else if (chip->running && power_save_controller)
+ azx_stop_chip(chip);
+}
+#endif /* CONFIG_SND_HDA_POWER_SAVE */
+
#ifdef CONFIG_PM
/*
* power management
@@ -1436,8 +1550,9 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state)
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
for (i = 0; i < chip->pcm_devs; i++)
snd_pcm_suspend_all(chip->pcm[i]);
- snd_hda_suspend(chip->bus, state);
- azx_free_cmd_io(chip);
+ if (chip->initialized)
+ snd_hda_suspend(chip->bus, state);
+ azx_stop_chip(chip);
if (chip->irq >= 0) {
synchronize_irq(chip->irq);
free_irq(chip->irq, chip);
@@ -1470,7 +1585,11 @@ static int azx_resume(struct pci_dev *pci)
chip->msi = 0;
if (azx_acquire_irq(chip, 1) < 0)
return -EIO;
- azx_init_chip(chip);
+ azx_init_pci(chip);
+
+ if (snd_hda_codecs_inuse(chip->bus))
+ azx_init_chip(chip);
+
snd_hda_resume(chip->bus);
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
@@ -1485,20 +1604,9 @@ static int azx_free(struct azx *chip)
{
if (chip->initialized) {
int i;
-
for (i = 0; i < chip->num_streams; i++)
azx_stream_stop(chip, &chip->azx_dev[i]);
-
- /* disable interrupts */
- azx_int_disable(chip);
- azx_int_clear(chip);
-
- /* disable CORB/RIRB */
- azx_free_cmd_io(chip);
-
- /* disable position buffer */
- azx_writel(chip, DPLBASE, 0);
- azx_writel(chip, DPUBASE, 0);
+ azx_stop_chip(chip);
}
if (chip->irq >= 0) {
@@ -1534,6 +1642,7 @@ static int azx_dev_free(struct snd_device *device)
*/
static struct snd_pci_quirk position_fix_list[] __devinitdata = {
SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_NONE),
+ SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_NONE),
{}
};
@@ -1544,7 +1653,7 @@ static int __devinit check_position_fix(struct azx *chip, int fix)
if (fix == POS_FIX_AUTO) {
q = snd_pci_quirk_lookup(chip->pci, position_fix_list);
if (q) {
- snd_printdd(KERN_INFO
+ printk(KERN_INFO
"hda_intel: position_fix set to %d "
"for device %04x:%04x\n",
q->value, q->subvendor, q->subdevice);
@@ -1555,6 +1664,36 @@ static int __devinit check_position_fix(struct azx *chip, int fix)
}
/*
+ * black-lists for probe_mask
+ */
+static struct snd_pci_quirk probe_mask_list[] __devinitdata = {
+ /* Thinkpad often breaks the controller communication when accessing
+ * to the non-working (or non-existing) modem codec slot.
+ */
+ SND_PCI_QUIRK(0x1014, 0x05b7, "Thinkpad Z60", 0x01),
+ SND_PCI_QUIRK(0x17aa, 0x2010, "Thinkpad X/T/R60", 0x01),
+ SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X/T/R61", 0x01),
+ {}
+};
+
+static void __devinit check_probe_mask(struct azx *chip)
+{
+ const struct snd_pci_quirk *q;
+
+ if (probe_mask == -1) {
+ q = snd_pci_quirk_lookup(chip->pci, probe_mask_list);
+ if (q) {
+ printk(KERN_INFO
+ "hda_intel: probe_mask set to 0x%x "
+ "for device %04x:%04x\n",
+ q->value, q->subvendor, q->subdevice);
+ probe_mask = q->value;
+ }
+ }
+}
+
+
+/*
* constructor
*/
static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
@@ -1589,6 +1728,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
chip->msi = enable_msi;
chip->position_fix = check_position_fix(chip, position_fix);
+ check_probe_mask(chip);
chip->single_cmd = single_cmd;
@@ -1650,37 +1790,43 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
break;
}
chip->num_streams = chip->playback_streams + chip->capture_streams;
- chip->azx_dev = kcalloc(chip->num_streams, sizeof(*chip->azx_dev), GFP_KERNEL);
+ chip->azx_dev = kcalloc(chip->num_streams, sizeof(*chip->azx_dev),
+ GFP_KERNEL);
if (!chip->azx_dev) {
snd_printk(KERN_ERR "cannot malloc azx_dev\n");
goto errout;
}
/* allocate memory for the BDL for each stream */
- if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
- BDL_SIZE, &chip->bdl)) < 0) {
+ err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(chip->pci),
+ BDL_SIZE, &chip->bdl);
+ if (err < 0) {
snd_printk(KERN_ERR SFX "cannot allocate BDL\n");
goto errout;
}
/* allocate memory for the position buffer */
- if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
- chip->num_streams * 8, &chip->posbuf)) < 0) {
+ err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(chip->pci),
+ chip->num_streams * 8, &chip->posbuf);
+ if (err < 0) {
snd_printk(KERN_ERR SFX "cannot allocate posbuf\n");
goto errout;
}
/* allocate CORB/RIRB */
- if (! chip->single_cmd)
- if ((err = azx_alloc_cmd_io(chip)) < 0)
+ if (!chip->single_cmd) {
+ err = azx_alloc_cmd_io(chip);
+ if (err < 0)
goto errout;
+ }
/* initialize streams */
azx_init_stream(chip);
/* initialize chip */
+ azx_init_pci(chip);
azx_init_chip(chip);
- chip->initialized = 1;
-
/* codec detection */
if (!chip->codec_mask) {
snd_printk(KERN_ERR SFX "no codecs found!\n");
@@ -1688,14 +1834,16 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
goto errout;
}
- if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) <0) {
+ err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
+ if (err <0) {
snd_printk(KERN_ERR SFX "Error creating device [card]!\n");
goto errout;
}
strcpy(card->driver, "HDA-Intel");
strcpy(card->shortname, driver_short_names[chip->driver_type]);
- sprintf(card->longname, "%s at 0x%lx irq %i", card->shortname, chip->addr, chip->irq);
+ sprintf(card->longname, "%s at 0x%lx irq %i",
+ card->shortname, chip->addr, chip->irq);
*rchip = chip;
return 0;
@@ -1705,7 +1853,21 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
return err;
}
-static int __devinit azx_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+static void power_down_all_codecs(struct azx *chip)
+{
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ /* The codecs were powered up in snd_hda_codec_new().
+ * Now all initialization done, so turn them down if possible
+ */
+ struct hda_codec *codec;
+ list_for_each_entry(codec, &chip->bus->codec_list, list) {
+ snd_hda_power_down(codec);
+ }
+#endif
+}
+
+static int __devinit azx_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
struct snd_card *card;
struct azx *chip;
@@ -1725,31 +1887,37 @@ static int __devinit azx_probe(struct pci_dev *pci, const struct pci_device_id *
card->private_data = chip;
/* create codec instances */
- if ((err = azx_codec_create(chip, model)) < 0) {
+ err = azx_codec_create(chip, model);
+ if (err < 0) {
snd_card_free(card);
return err;
}
/* create PCM streams */
- if ((err = azx_pcm_create(chip)) < 0) {
+ err = azx_pcm_create(chip);
+ if (err < 0) {
snd_card_free(card);
return err;
}
/* create mixer controls */
- if ((err = azx_mixer_create(chip)) < 0) {
+ err = azx_mixer_create(chip);
+ if (err < 0) {
snd_card_free(card);
return err;
}
snd_card_set_dev(card, &pci->dev);
- if ((err = snd_card_register(card)) < 0) {
+ err = snd_card_register(card);
+ if (err < 0) {
snd_card_free(card);
return err;
}
pci_set_drvdata(pci, card);
+ chip->running = 1;
+ power_down_all_codecs(chip);
return err;
}
@@ -1791,6 +1959,10 @@ static struct pci_device_id azx_ids[] = {
{ 0x10de, 0x0775, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */
{ 0x10de, 0x0776, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */
{ 0x10de, 0x0777, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */
+ { 0x10de, 0x0ac0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP79 */
+ { 0x10de, 0x0ac1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP79 */
+ { 0x10de, 0x0ac2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP79 */
+ { 0x10de, 0x0ac3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP79 */
{ 0, }
};
MODULE_DEVICE_TABLE(pci, azx_ids);
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index f91ea5ec9f6d..20c5e6250374 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -26,7 +26,8 @@
/*
* for mixer controls
*/
-#define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19))
+#define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) \
+ ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19))
/* mono volume with index (index=0,1,...) (channel=1,2) */
#define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \
@@ -64,18 +65,35 @@
#define HDA_CODEC_MUTE(xname, nid, xindex, direction) \
HDA_CODEC_MUTE_MONO(xname, nid, 3, xindex, direction)
-int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo);
-int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
-int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
-int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, unsigned int size, unsigned int __user *tlv);
-int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo);
-int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
-int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
+int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo);
+int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
+ unsigned int size, unsigned int __user *tlv);
+int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo);
+int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
/* lowlevel accessor with caching; use carefully */
int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
int direction, int index);
int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
int direction, int idx, int mask, int val);
+int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
+ int dir, int idx, int mask, int val);
+#ifdef SND_HDA_NEEDS_RESUME
+void snd_hda_codec_resume_amp(struct hda_codec *codec);
+#endif
+
+/* amp value bits */
+#define HDA_AMP_MUTE 0x80
+#define HDA_AMP_UNMUTE 0x00
+#define HDA_AMP_VOLMASK 0x7f
/* mono switch binding multiple inputs */
#define HDA_BIND_MUTE_MONO(xname, nid, channel, indices, direction) \
@@ -86,11 +104,61 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
.private_value = HDA_COMPOSE_AMP_VAL(nid, channel, indices, direction) }
/* stereo switch binding multiple inputs */
-#define HDA_BIND_MUTE(xname,nid,indices,dir) HDA_BIND_MUTE_MONO(xname,nid,3,indices,dir)
+#define HDA_BIND_MUTE(xname,nid,indices,dir) \
+ HDA_BIND_MUTE_MONO(xname,nid,3,indices,dir)
+
+int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+
+/* more generic bound controls */
+struct hda_ctl_ops {
+ snd_kcontrol_info_t *info;
+ snd_kcontrol_get_t *get;
+ snd_kcontrol_put_t *put;
+ snd_kcontrol_tlv_rw_t *tlv;
+};
+
+extern struct hda_ctl_ops snd_hda_bind_vol; /* for bind-volume with TLV */
+extern struct hda_ctl_ops snd_hda_bind_sw; /* for bind-switch */
-int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
-int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
+struct hda_bind_ctls {
+ struct hda_ctl_ops *ops;
+ long values[];
+};
+
+int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo);
+int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
+ unsigned int size, unsigned int __user *tlv);
+
+#define HDA_BIND_VOL(xname, bindrec) \
+ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ .name = xname, \
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
+ SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
+ SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK,\
+ .info = snd_hda_mixer_bind_ctls_info,\
+ .get = snd_hda_mixer_bind_ctls_get,\
+ .put = snd_hda_mixer_bind_ctls_put,\
+ .tlv = { .c = snd_hda_mixer_bind_tlv },\
+ .private_value = (long) (bindrec) }
+#define HDA_BIND_SW(xname, bindrec) \
+ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,\
+ .name = xname, \
+ .info = snd_hda_mixer_bind_ctls_info,\
+ .get = snd_hda_mixer_bind_ctls_get,\
+ .put = snd_hda_mixer_bind_ctls_put,\
+ .private_value = (long) (bindrec) }
+/*
+ * SPDIF I/O
+ */
int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid);
int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid);
@@ -107,8 +175,10 @@ struct hda_input_mux {
struct hda_input_mux_item items[HDA_MAX_NUM_INPUTS];
};
-int snd_hda_input_mux_info(const struct hda_input_mux *imux, struct snd_ctl_elem_info *uinfo);
-int snd_hda_input_mux_put(struct hda_codec *codec, const struct hda_input_mux *imux,
+int snd_hda_input_mux_info(const struct hda_input_mux *imux,
+ struct snd_ctl_elem_info *uinfo);
+int snd_hda_input_mux_put(struct hda_codec *codec,
+ const struct hda_input_mux *imux,
struct snd_ctl_elem_value *ucontrol, hda_nid_t nid,
unsigned int *cur_val);
@@ -120,13 +190,19 @@ struct hda_channel_mode {
const struct hda_verb *sequence;
};
-int snd_hda_ch_mode_info(struct hda_codec *codec, struct snd_ctl_elem_info *uinfo,
- const struct hda_channel_mode *chmode, int num_chmodes);
-int snd_hda_ch_mode_get(struct hda_codec *codec, struct snd_ctl_elem_value *ucontrol,
- const struct hda_channel_mode *chmode, int num_chmodes,
+int snd_hda_ch_mode_info(struct hda_codec *codec,
+ struct snd_ctl_elem_info *uinfo,
+ const struct hda_channel_mode *chmode,
+ int num_chmodes);
+int snd_hda_ch_mode_get(struct hda_codec *codec,
+ struct snd_ctl_elem_value *ucontrol,
+ const struct hda_channel_mode *chmode,
+ int num_chmodes,
int max_channels);
-int snd_hda_ch_mode_put(struct hda_codec *codec, struct snd_ctl_elem_value *ucontrol,
- const struct hda_channel_mode *chmode, int num_chmodes,
+int snd_hda_ch_mode_put(struct hda_codec *codec,
+ struct snd_ctl_elem_value *ucontrol,
+ const struct hda_channel_mode *chmode,
+ int num_chmodes,
int *max_channelsp);
/*
@@ -146,25 +222,37 @@ struct hda_multi_out {
int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */
};
-int snd_hda_multi_out_dig_open(struct hda_codec *codec, struct hda_multi_out *mout);
-int snd_hda_multi_out_dig_close(struct hda_codec *codec, struct hda_multi_out *mout);
+int snd_hda_multi_out_dig_open(struct hda_codec *codec,
+ struct hda_multi_out *mout);
+int snd_hda_multi_out_dig_close(struct hda_codec *codec,
+ struct hda_multi_out *mout);
int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
struct hda_multi_out *mout,
unsigned int stream_tag,
unsigned int format,
struct snd_pcm_substream *substream);
-int snd_hda_multi_out_analog_open(struct hda_codec *codec, struct hda_multi_out *mout,
+int snd_hda_multi_out_analog_open(struct hda_codec *codec,
+ struct hda_multi_out *mout,
struct snd_pcm_substream *substream);
-int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_out *mout,
+int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
+ struct hda_multi_out *mout,
unsigned int stream_tag,
unsigned int format,
struct snd_pcm_substream *substream);
-int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, struct hda_multi_out *mout);
+int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
+ struct hda_multi_out *mout);
/*
* generic codec parser
*/
+#ifdef CONFIG_SND_HDA_GENERIC
int snd_hda_parse_generic_codec(struct hda_codec *codec);
+#else
+static inline int snd_hda_parse_generic_codec(struct hda_codec *codec)
+{
+ return -ENODEV;
+}
+#endif
/*
* generic proc interface
@@ -181,16 +269,8 @@ static inline int snd_hda_codec_proc_new(struct hda_codec *codec) { return 0; }
int snd_hda_check_board_config(struct hda_codec *codec, int num_configs,
const char **modelnames,
const struct snd_pci_quirk *pci_list);
-int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew);
-
-/*
- * power management
- */
-#ifdef CONFIG_PM
-int snd_hda_resume_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew);
-int snd_hda_resume_spdif_out(struct hda_codec *codec);
-int snd_hda_resume_spdif_in(struct hda_codec *codec);
-#endif
+int snd_hda_add_new_ctls(struct hda_codec *codec,
+ struct snd_kcontrol_new *knew);
/*
* unsolicited event handler
@@ -230,26 +310,35 @@ enum {
extern const char *auto_pin_cfg_labels[AUTO_PIN_LAST];
+#define AUTO_CFG_MAX_OUTS 5
+
struct auto_pin_cfg {
int line_outs;
- hda_nid_t line_out_pins[5]; /* sorted in the order of Front/Surr/CLFE/Side */
+ /* sorted in the order of Front/Surr/CLFE/Side */
+ hda_nid_t line_out_pins[AUTO_CFG_MAX_OUTS];
int speaker_outs;
- hda_nid_t speaker_pins[5];
+ hda_nid_t speaker_pins[AUTO_CFG_MAX_OUTS];
int hp_outs;
int line_out_type; /* AUTO_PIN_XXX_OUT */
- hda_nid_t hp_pins[5];
+ hda_nid_t hp_pins[AUTO_CFG_MAX_OUTS];
hda_nid_t input_pins[AUTO_PIN_LAST];
hda_nid_t dig_out_pin;
hda_nid_t dig_in_pin;
};
-#define get_defcfg_connect(cfg) ((cfg & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT)
-#define get_defcfg_association(cfg) ((cfg & AC_DEFCFG_DEF_ASSOC) >> AC_DEFCFG_ASSOC_SHIFT)
-#define get_defcfg_location(cfg) ((cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT)
-#define get_defcfg_sequence(cfg) (cfg & AC_DEFCFG_SEQUENCE)
-#define get_defcfg_device(cfg) ((cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT)
-
-int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *cfg,
+#define get_defcfg_connect(cfg) \
+ ((cfg & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT)
+#define get_defcfg_association(cfg) \
+ ((cfg & AC_DEFCFG_DEF_ASSOC) >> AC_DEFCFG_ASSOC_SHIFT)
+#define get_defcfg_location(cfg) \
+ ((cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT)
+#define get_defcfg_sequence(cfg) \
+ (cfg & AC_DEFCFG_SEQUENCE)
+#define get_defcfg_device(cfg) \
+ ((cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT)
+
+int snd_hda_parse_pin_def_config(struct hda_codec *codec,
+ struct auto_pin_cfg *cfg,
hda_nid_t *ignore_nids);
/* amp values */
@@ -280,4 +369,32 @@ static inline u32 get_wcaps(struct hda_codec *codec, hda_nid_t nid)
int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
unsigned int caps);
+/*
+ * hwdep interface
+ */
+int snd_hda_create_hwdep(struct hda_codec *codec);
+
+/*
+ * power-management
+ */
+
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+void snd_hda_schedule_power_save(struct hda_codec *codec);
+
+struct hda_amp_list {
+ hda_nid_t nid;
+ unsigned char dir;
+ unsigned char idx;
+};
+
+struct hda_loopback_check {
+ struct hda_amp_list *amplist;
+ int power_on;
+};
+
+int snd_hda_check_amp_list_power(struct hda_codec *codec,
+ struct hda_loopback_check *check,
+ hda_nid_t nid);
+#endif /* CONFIG_SND_HDA_POWER_SAVE */
+
#endif /* __SOUND_HDA_LOCAL_H */
diff --git a/sound/pci/hda/hda_patch.h b/sound/pci/hda/hda_patch.h
index 9f9e9ae44a9d..f5c23bb16d7e 100644
--- a/sound/pci/hda/hda_patch.h
+++ b/sound/pci/hda/hda_patch.h
@@ -20,13 +20,29 @@ extern struct hda_codec_preset snd_hda_preset_conexant[];
extern struct hda_codec_preset snd_hda_preset_via[];
static const struct hda_codec_preset *hda_preset_tables[] = {
+#ifdef CONFIG_SND_HDA_CODEC_REALTEK
snd_hda_preset_realtek,
+#endif
+#ifdef CONFIG_SND_HDA_CODEC_CMEDIA
snd_hda_preset_cmedia,
+#endif
+#ifdef CONFIG_SND_HDA_CODEC_ANALOG
snd_hda_preset_analog,
+#endif
+#ifdef CONFIG_SND_HDA_CODEC_SIGMATEL
snd_hda_preset_sigmatel,
+#endif
+#ifdef CONFIG_SND_HDA_CODEC_SI3054
snd_hda_preset_si3054,
+#endif
+#ifdef CONFIG_SND_HDA_CODEC_ATIHDMI
snd_hda_preset_atihdmi,
+#endif
+#ifdef CONFIG_SND_HDA_CODEC_CONEXANT
snd_hda_preset_conexant,
+#endif
+#ifdef CONFIG_SND_HDA_CODEC_VIA
snd_hda_preset_via,
+#endif
NULL
};
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c
index ac15066fd300..e94944f34ffd 100644
--- a/sound/pci/hda/hda_proc.c
+++ b/sound/pci/hda/hda_proc.c
@@ -58,7 +58,8 @@ static void print_amp_caps(struct snd_info_buffer *buffer,
snd_iprintf(buffer, "N/A\n");
return;
}
- snd_iprintf(buffer, "ofs=0x%02x, nsteps=0x%02x, stepsize=0x%02x, mute=%x\n",
+ snd_iprintf(buffer, "ofs=0x%02x, nsteps=0x%02x, stepsize=0x%02x, "
+ "mute=%x\n",
caps & AC_AMPCAP_OFFSET,
(caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT,
(caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT,
@@ -76,11 +77,13 @@ static void print_amp_vals(struct snd_info_buffer *buffer,
for (i = 0; i < indices; i++) {
snd_iprintf(buffer, " [");
if (stereo) {
- val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE,
+ val = snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_AMP_GAIN_MUTE,
AC_AMP_GET_LEFT | dir | i);
snd_iprintf(buffer, "0x%02x ", val);
}
- val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE,
+ val = snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_AMP_GAIN_MUTE,
AC_AMP_GET_RIGHT | dir | i);
snd_iprintf(buffer, "0x%02x]", val);
}
@@ -237,7 +240,8 @@ static void print_pin_caps(struct snd_info_buffer *buffer,
}
-static void print_codec_info(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
+static void print_codec_info(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
struct hda_codec *codec = entry->private_data;
char buf[32];
@@ -258,6 +262,7 @@ static void print_codec_info(struct snd_info_entry *entry, struct snd_info_buffe
if (! codec->afg)
return;
+ snd_hda_power_up(codec);
snd_iprintf(buffer, "Default PCM:\n");
print_pcm_caps(buffer, codec, codec->afg);
snd_iprintf(buffer, "Default Amp-In caps: ");
@@ -268,12 +273,15 @@ static void print_codec_info(struct snd_info_entry *entry, struct snd_info_buffe
nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
if (! nid || nodes < 0) {
snd_iprintf(buffer, "Invalid AFG subtree\n");
+ snd_hda_power_down(codec);
return;
}
for (i = 0; i < nodes; i++, nid++) {
- unsigned int wid_caps = snd_hda_param_read(codec, nid,
- AC_PAR_AUDIO_WIDGET_CAP);
- unsigned int wid_type = (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
+ unsigned int wid_caps =
+ snd_hda_param_read(codec, nid,
+ AC_PAR_AUDIO_WIDGET_CAP);
+ unsigned int wid_type =
+ (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
int conn_len = 0;
hda_nid_t conn[HDA_MAX_CONNECTIONS];
@@ -313,7 +321,9 @@ static void print_codec_info(struct snd_info_entry *entry, struct snd_info_buffe
if (wid_type == AC_WID_PIN) {
unsigned int pinctls;
print_pin_caps(buffer, codec, nid);
- pinctls = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+ pinctls = snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_PIN_WIDGET_CONTROL,
+ 0);
snd_iprintf(buffer, " Pin-ctls: 0x%02x:", pinctls);
if (pinctls & AC_PINCTL_IN_EN)
snd_iprintf(buffer, " IN");
@@ -333,7 +343,8 @@ static void print_codec_info(struct snd_info_entry *entry, struct snd_info_buffe
if (wid_caps & AC_WCAP_POWER)
snd_iprintf(buffer, " Power: 0x%x\n",
snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_POWER_STATE, 0));
+ AC_VERB_GET_POWER_STATE,
+ 0));
if (wid_caps & AC_WCAP_CONN_LIST) {
int c, curr = -1;
@@ -350,6 +361,7 @@ static void print_codec_info(struct snd_info_entry *entry, struct snd_info_buffe
snd_iprintf(buffer, "\n");
}
}
+ snd_hda_power_down(codec);
}
/*
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 4d7f8d11ad75..0ee8ae4d4410 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -72,7 +72,13 @@ struct ad198x_spec {
unsigned int num_kctl_alloc, num_kctl_used;
struct snd_kcontrol_new *kctl_alloc;
struct hda_input_mux private_imux;
- hda_nid_t private_dac_nids[4];
+ hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
+
+ unsigned int jack_present :1;
+
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ struct hda_loopback_check loopback;
+#endif
};
/*
@@ -144,6 +150,14 @@ static int ad198x_build_controls(struct hda_codec *codec)
return 0;
}
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static int ad198x_check_power_status(struct hda_codec *codec, hda_nid_t nid)
+{
+ struct ad198x_spec *spec = codec->spec;
+ return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
+}
+#endif
+
/*
* Analog playback callbacks
*/
@@ -318,30 +332,13 @@ static void ad198x_free(struct hda_codec *codec)
kfree(codec->spec);
}
-#ifdef CONFIG_PM
-static int ad198x_resume(struct hda_codec *codec)
-{
- struct ad198x_spec *spec = codec->spec;
- int i;
-
- codec->patch_ops.init(codec);
- for (i = 0; i < spec->num_mixers; i++)
- snd_hda_resume_ctls(codec, spec->mixers[i]);
- if (spec->multiout.dig_out_nid)
- snd_hda_resume_spdif_out(codec);
- if (spec->dig_in_nid)
- snd_hda_resume_spdif_in(codec);
- return 0;
-}
-#endif
-
static struct hda_codec_ops ad198x_patch_ops = {
.build_controls = ad198x_build_controls,
.build_pcms = ad198x_build_pcms,
.init = ad198x_init,
.free = ad198x_free,
-#ifdef CONFIG_PM
- .resume = ad198x_resume,
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ .check_power_status = ad198x_check_power_status,
#endif
};
@@ -350,15 +347,7 @@ static struct hda_codec_ops ad198x_patch_ops = {
* EAPD control
* the private value = nid | (invert << 8)
*/
-static int ad198x_eapd_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define ad198x_eapd_info snd_ctl_boolean_mono_info
static int ad198x_eapd_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -384,12 +373,12 @@ static int ad198x_eapd_put(struct snd_kcontrol *kcontrol,
eapd = ucontrol->value.integer.value[0];
if (invert)
eapd = !eapd;
- if (eapd == spec->cur_eapd && ! codec->in_resume)
+ if (eapd == spec->cur_eapd)
return 0;
spec->cur_eapd = eapd;
- snd_hda_codec_write(codec, nid,
- 0, AC_VERB_SET_EAPD_BTLENABLE,
- eapd ? 0x02 : 0x00);
+ snd_hda_codec_write_cache(codec, nid,
+ 0, AC_VERB_SET_EAPD_BTLENABLE,
+ eapd ? 0x02 : 0x00);
return 1;
}
@@ -430,94 +419,36 @@ static struct hda_input_mux ad1986a_capture_source = {
},
};
-/*
- * PCM control
- *
- * bind volumes/mutes of 3 DACs as a single PCM control for simplicity
- */
-
-#define ad1986a_pcm_amp_vol_info snd_hda_mixer_amp_volume_info
-
-static int ad1986a_pcm_amp_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ad198x_spec *ad = codec->spec;
-
- mutex_lock(&ad->amp_mutex);
- snd_hda_mixer_amp_volume_get(kcontrol, ucontrol);
- mutex_unlock(&ad->amp_mutex);
- return 0;
-}
-
-static int ad1986a_pcm_amp_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ad198x_spec *ad = codec->spec;
- int i, change = 0;
-
- mutex_lock(&ad->amp_mutex);
- for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) {
- kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT);
- change |= snd_hda_mixer_amp_volume_put(kcontrol, ucontrol);
- }
- kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT);
- mutex_unlock(&ad->amp_mutex);
- return change;
-}
-
-#define ad1986a_pcm_amp_sw_info snd_hda_mixer_amp_switch_info
-static int ad1986a_pcm_amp_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ad198x_spec *ad = codec->spec;
-
- mutex_lock(&ad->amp_mutex);
- snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
- mutex_unlock(&ad->amp_mutex);
- return 0;
-}
-
-static int ad1986a_pcm_amp_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ad198x_spec *ad = codec->spec;
- int i, change = 0;
+static struct hda_bind_ctls ad1986a_bind_pcm_vol = {
+ .ops = &snd_hda_bind_vol,
+ .values = {
+ HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
+ HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
+ HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
+ 0
+ },
+};
- mutex_lock(&ad->amp_mutex);
- for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) {
- kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT);
- change |= snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
- }
- kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT);
- mutex_unlock(&ad->amp_mutex);
- return change;
-}
+static struct hda_bind_ctls ad1986a_bind_pcm_sw = {
+ .ops = &snd_hda_bind_sw,
+ .values = {
+ HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
+ HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
+ HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
+ 0
+ },
+};
/*
* mixers
*/
static struct snd_kcontrol_new ad1986a_mixers[] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "PCM Playback Volume",
- .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
- SNDRV_CTL_ELEM_ACCESS_TLV_READ |
- SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK,
- .info = ad1986a_pcm_amp_vol_info,
- .get = ad1986a_pcm_amp_vol_get,
- .put = ad1986a_pcm_amp_vol_put,
- .tlv = { .c = snd_hda_mixer_amp_tlv },
- .private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT)
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "PCM Playback Switch",
- .info = ad1986a_pcm_amp_sw_info,
- .get = ad1986a_pcm_amp_sw_get,
- .put = ad1986a_pcm_amp_sw_put,
- .private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT)
- },
+ /*
+ * bind volumes/mutes of 3 DACs as a single PCM control for simplicity
+ */
+ HDA_BIND_VOL("PCM Playback Volume", &ad1986a_bind_pcm_vol),
+ HDA_BIND_SW("PCM Playback Switch", &ad1986a_bind_pcm_sw),
HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
@@ -569,13 +500,30 @@ static struct snd_kcontrol_new ad1986a_3st_mixers[] = {
/* laptop model - 2ch only */
static hda_nid_t ad1986a_laptop_dac_nids[1] = { AD1986A_FRONT_DAC };
+/* master controls both pins 0x1a and 0x1b */
+static struct hda_bind_ctls ad1986a_laptop_master_vol = {
+ .ops = &snd_hda_bind_vol,
+ .values = {
+ HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
+ HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
+ 0,
+ },
+};
+
+static struct hda_bind_ctls ad1986a_laptop_master_sw = {
+ .ops = &snd_hda_bind_sw,
+ .values = {
+ HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
+ HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
+ 0,
+ },
+};
+
static struct snd_kcontrol_new ad1986a_laptop_mixers[] = {
HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Master Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Master Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
- /* HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT), */
+ HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
+ HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
@@ -603,68 +551,115 @@ static struct snd_kcontrol_new ad1986a_laptop_mixers[] = {
/* laptop-eapd model - 2ch only */
-/* master controls both pins 0x1a and 0x1b */
-static int ad1986a_laptop_master_vol_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+static struct hda_input_mux ad1986a_laptop_eapd_capture_source = {
+ .num_items = 3,
+ .items = {
+ { "Mic", 0x0 },
+ { "Internal Mic", 0x4 },
+ { "Mix", 0x5 },
+ },
+};
+
+static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
+ HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
+ HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
+ HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Capture Source",
+ .info = ad198x_mux_enum_info,
+ .get = ad198x_mux_enum_get,
+ .put = ad198x_mux_enum_put,
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "External Amplifier",
+ .info = ad198x_eapd_info,
+ .get = ad198x_eapd_get,
+ .put = ad198x_eapd_put,
+ .private_value = 0x1b | (1 << 8), /* port-D, inversed */
+ },
+ { } /* end */
+};
+
+/* laptop-automute - 2ch only */
+
+static void ad1986a_update_hp(struct hda_codec *codec)
{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- long *valp = ucontrol->value.integer.value;
- int change;
+ struct ad198x_spec *spec = codec->spec;
+ unsigned int mute;
- change = snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0,
- 0x7f, valp[0] & 0x7f);
- change |= snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0,
- 0x7f, valp[1] & 0x7f);
- snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0,
- 0x7f, valp[0] & 0x7f);
- snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0,
- 0x7f, valp[1] & 0x7f);
- return change;
+ if (spec->jack_present)
+ mute = HDA_AMP_MUTE; /* mute internal speaker */
+ else
+ /* unmute internal speaker if necessary */
+ mute = snd_hda_codec_amp_read(codec, 0x1a, 0, HDA_OUTPUT, 0);
+ snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, mute);
}
-static int ad1986a_laptop_master_sw_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+static void ad1986a_hp_automute(struct hda_codec *codec)
+{
+ struct ad198x_spec *spec = codec->spec;
+ unsigned int present;
+
+ present = snd_hda_codec_read(codec, 0x1a, 0, AC_VERB_GET_PIN_SENSE, 0);
+ /* Lenovo N100 seems to report the reversed bit for HP jack-sensing */
+ spec->jack_present = !(present & 0x80000000);
+ ad1986a_update_hp(codec);
+}
+
+#define AD1986A_HP_EVENT 0x37
+
+static void ad1986a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+ if ((res >> 26) != AD1986A_HP_EVENT)
+ return;
+ ad1986a_hp_automute(codec);
+}
+
+static int ad1986a_hp_init(struct hda_codec *codec)
+{
+ ad198x_init(codec);
+ ad1986a_hp_automute(codec);
+ return 0;
+}
+
+/* bind hp and internal speaker mute (with plug check) */
+static int ad1986a_hp_master_sw_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
long *valp = ucontrol->value.integer.value;
int change;
change = snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0,
- 0x80, valp[0] ? 0 : 0x80);
+ HDA_AMP_MUTE,
+ valp[0] ? 0 : HDA_AMP_MUTE);
change |= snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0,
- 0x80, valp[1] ? 0 : 0x80);
- snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0,
- 0x80, valp[0] ? 0 : 0x80);
- snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0,
- 0x80, valp[1] ? 0 : 0x80);
+ HDA_AMP_MUTE,
+ valp[1] ? 0 : HDA_AMP_MUTE);
+ if (change)
+ ad1986a_update_hp(codec);
return change;
}
-static struct hda_input_mux ad1986a_laptop_eapd_capture_source = {
- .num_items = 3,
- .items = {
- { "Mic", 0x0 },
- { "Internal Mic", 0x4 },
- { "Mix", 0x5 },
- },
-};
-
-static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Master Playback Volume",
- .info = snd_hda_mixer_amp_volume_info,
- .get = snd_hda_mixer_amp_volume_get,
- .put = ad1986a_laptop_master_vol_put,
- .tlv = { .c = snd_hda_mixer_amp_tlv },
- .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
- },
+static struct snd_kcontrol_new ad1986a_laptop_automute_mixers[] = {
+ HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Switch",
.info = snd_hda_mixer_amp_switch_info,
.get = snd_hda_mixer_amp_switch_get,
- .put = ad1986a_laptop_master_sw_put,
+ .put = ad1986a_hp_master_sw_put,
.private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
},
HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
@@ -674,6 +669,8 @@ static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Beep Playback Volume", 0x18, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Beep Playback Switch", 0x18, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
{
@@ -807,12 +804,20 @@ static struct hda_verb ad1986a_ultra_init[] = {
{ } /* end */
};
+/* pin sensing on HP jack */
+static struct hda_verb ad1986a_hp_init_verbs[] = {
+ {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_HP_EVENT},
+ {}
+};
+
+
/* models */
enum {
AD1986A_6STACK,
AD1986A_3STACK,
AD1986A_LAPTOP,
AD1986A_LAPTOP_EAPD,
+ AD1986A_LAPTOP_AUTOMUTE,
AD1986A_ULTRA,
AD1986A_MODELS
};
@@ -822,6 +827,7 @@ static const char *ad1986a_models[AD1986A_MODELS] = {
[AD1986A_3STACK] = "3stack",
[AD1986A_LAPTOP] = "laptop",
[AD1986A_LAPTOP_EAPD] = "laptop-eapd",
+ [AD1986A_LAPTOP_AUTOMUTE] = "laptop-automute",
[AD1986A_ULTRA] = "ultra",
};
@@ -850,11 +856,22 @@ static struct snd_pci_quirk ad1986a_cfg_tbl[] = {
SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA),
SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP),
SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK),
- SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_LAPTOP_EAPD),
+ SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_LAPTOP_AUTOMUTE),
SND_PCI_QUIRK(0x17c0, 0x2017, "Samsung M50", AD1986A_LAPTOP),
{}
};
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static struct hda_amp_list ad1986a_loopbacks[] = {
+ { 0x13, HDA_OUTPUT, 0 }, /* Mic */
+ { 0x14, HDA_OUTPUT, 0 }, /* Phone */
+ { 0x15, HDA_OUTPUT, 0 }, /* CD */
+ { 0x16, HDA_OUTPUT, 0 }, /* Aux */
+ { 0x17, HDA_OUTPUT, 0 }, /* Line */
+ { } /* end */
+};
+#endif
+
static int patch_ad1986a(struct hda_codec *codec)
{
struct ad198x_spec *spec;
@@ -864,7 +881,6 @@ static int patch_ad1986a(struct hda_codec *codec)
if (spec == NULL)
return -ENOMEM;
- mutex_init(&spec->amp_mutex);
codec->spec = spec;
spec->multiout.max_channels = 6;
@@ -879,6 +895,9 @@ static int patch_ad1986a(struct hda_codec *codec)
spec->mixers[0] = ad1986a_mixers;
spec->num_init_verbs = 1;
spec->init_verbs[0] = ad1986a_init_verbs;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ spec->loopback.amplist = ad1986a_loopbacks;
+#endif
codec->patch_ops = ad198x_patch_ops;
@@ -914,6 +933,19 @@ static int patch_ad1986a(struct hda_codec *codec)
spec->multiout.dig_out_nid = 0;
spec->input_mux = &ad1986a_laptop_eapd_capture_source;
break;
+ case AD1986A_LAPTOP_AUTOMUTE:
+ spec->mixers[0] = ad1986a_laptop_automute_mixers;
+ spec->num_init_verbs = 3;
+ spec->init_verbs[1] = ad1986a_eapd_init_verbs;
+ spec->init_verbs[2] = ad1986a_hp_init_verbs;
+ spec->multiout.max_channels = 2;
+ spec->multiout.num_dacs = 1;
+ spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
+ spec->multiout.dig_out_nid = 0;
+ spec->input_mux = &ad1986a_laptop_eapd_capture_source;
+ codec->patch_ops.unsol_event = ad1986a_hp_unsol_event;
+ codec->patch_ops.init = ad1986a_hp_init;
+ break;
case AD1986A_ULTRA:
spec->mixers[0] = ad1986a_laptop_eapd_mixers;
spec->num_init_verbs = 2;
@@ -982,8 +1014,9 @@ static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
spec->spdif_route = ucontrol->value.enumerated.item[0];
- snd_hda_codec_write(codec, spec->multiout.dig_out_nid, 0,
- AC_VERB_SET_CONNECT_SEL, spec->spdif_route);
+ snd_hda_codec_write_cache(codec, spec->multiout.dig_out_nid, 0,
+ AC_VERB_SET_CONNECT_SEL,
+ spec->spdif_route);
return 1;
}
return 0;
@@ -1063,6 +1096,13 @@ static struct hda_verb ad1983_init_verbs[] = {
{ } /* end */
};
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static struct hda_amp_list ad1983_loopbacks[] = {
+ { 0x12, HDA_OUTPUT, 0 }, /* Mic */
+ { 0x13, HDA_OUTPUT, 0 }, /* Line */
+ { } /* end */
+};
+#endif
static int patch_ad1983(struct hda_codec *codec)
{
@@ -1072,7 +1112,6 @@ static int patch_ad1983(struct hda_codec *codec)
if (spec == NULL)
return -ENOMEM;
- mutex_init(&spec->amp_mutex);
codec->spec = spec;
spec->multiout.max_channels = 2;
@@ -1088,6 +1127,9 @@ static int patch_ad1983(struct hda_codec *codec)
spec->num_init_verbs = 1;
spec->init_verbs[0] = ad1983_init_verbs;
spec->spdif_route = 0;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ spec->loopback.amplist = ad1983_loopbacks;
+#endif
codec->patch_ops = ad198x_patch_ops;
@@ -1211,6 +1253,17 @@ static struct hda_verb ad1981_init_verbs[] = {
{ } /* end */
};
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static struct hda_amp_list ad1981_loopbacks[] = {
+ { 0x12, HDA_OUTPUT, 0 }, /* Front Mic */
+ { 0x13, HDA_OUTPUT, 0 }, /* Line */
+ { 0x1b, HDA_OUTPUT, 0 }, /* Aux */
+ { 0x1c, HDA_OUTPUT, 0 }, /* Mic */
+ { 0x1d, HDA_OUTPUT, 0 }, /* CD */
+ { } /* end */
+};
+#endif
+
/*
* Patch for HP nx6320
*
@@ -1240,31 +1293,21 @@ static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol,
return 0;
/* toggle HP mute appropriately */
- snd_hda_codec_amp_update(codec, 0x06, 0, HDA_OUTPUT, 0,
- 0x80, spec->cur_eapd ? 0 : 0x80);
- snd_hda_codec_amp_update(codec, 0x06, 1, HDA_OUTPUT, 0,
- 0x80, spec->cur_eapd ? 0 : 0x80);
+ snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE,
+ spec->cur_eapd ? 0 : HDA_AMP_MUTE);
return 1;
}
/* bind volumes of both NID 0x05 and 0x06 */
-static int ad1981_hp_master_vol_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- long *valp = ucontrol->value.integer.value;
- int change;
-
- change = snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0,
- 0x7f, valp[0] & 0x7f);
- change |= snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0,
- 0x7f, valp[1] & 0x7f);
- snd_hda_codec_amp_update(codec, 0x06, 0, HDA_OUTPUT, 0,
- 0x7f, valp[0] & 0x7f);
- snd_hda_codec_amp_update(codec, 0x06, 1, HDA_OUTPUT, 0,
- 0x7f, valp[1] & 0x7f);
- return change;
-}
+static struct hda_bind_ctls ad1981_hp_bind_master_vol = {
+ .ops = &snd_hda_bind_vol,
+ .values = {
+ HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
+ HDA_COMPOSE_AMP_VAL(0x06, 3, 0, HDA_OUTPUT),
+ 0
+ },
+};
/* mute internal speaker if HP is plugged */
static void ad1981_hp_automute(struct hda_codec *codec)
@@ -1273,10 +1316,8 @@ static void ad1981_hp_automute(struct hda_codec *codec)
present = snd_hda_codec_read(codec, 0x06, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
- snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
+ snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
}
/* toggle input of built-in and mic jack appropriately */
@@ -1327,14 +1368,7 @@ static struct hda_input_mux ad1981_hp_capture_source = {
};
static struct snd_kcontrol_new ad1981_hp_mixers[] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Master Playback Volume",
- .info = snd_hda_mixer_amp_volume_info,
- .get = snd_hda_mixer_amp_volume_get,
- .put = ad1981_hp_master_vol_put,
- .private_value = HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
- },
+ HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol),
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Switch",
@@ -1474,7 +1508,6 @@ static int patch_ad1981(struct hda_codec *codec)
if (spec == NULL)
return -ENOMEM;
- mutex_init(&spec->amp_mutex);
codec->spec = spec;
spec->multiout.max_channels = 2;
@@ -1490,6 +1523,9 @@ static int patch_ad1981(struct hda_codec *codec)
spec->num_init_verbs = 1;
spec->init_verbs[0] = ad1981_init_verbs;
spec->spdif_route = 0;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ spec->loopback.amplist = ad1981_loopbacks;
+#endif
codec->patch_ops = ad198x_patch_ops;
@@ -1897,16 +1933,19 @@ static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol,
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
unsigned int sel;
- sel = snd_hda_codec_read(codec, 0x02, 0, AC_VERB_GET_CONNECT_SEL, 0);
- if (sel > 0) {
+ sel = snd_hda_codec_read(codec, 0x1d, 0, AC_VERB_GET_AMP_GAIN_MUTE,
+ AC_AMP_GET_INPUT);
+ if (!(sel & 0x80))
+ ucontrol->value.enumerated.item[0] = 0;
+ else {
sel = snd_hda_codec_read(codec, 0x0b, 0,
AC_VERB_GET_CONNECT_SEL, 0);
if (sel < 3)
sel++;
else
sel = 0;
+ ucontrol->value.enumerated.item[0] = sel;
}
- ucontrol->value.enumerated.item[0] = sel;
return 0;
}
@@ -1918,23 +1957,39 @@ static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol,
int change;
val = ucontrol->value.enumerated.item[0];
- sel = snd_hda_codec_read(codec, 0x02, 0, AC_VERB_GET_CONNECT_SEL, 0);
if (!val) {
- change = sel != 0;
- if (change || codec->in_resume)
- snd_hda_codec_write(codec, 0x02, 0,
- AC_VERB_SET_CONNECT_SEL, 0);
+ sel = snd_hda_codec_read(codec, 0x1d, 0,
+ AC_VERB_GET_AMP_GAIN_MUTE,
+ AC_AMP_GET_INPUT);
+ change = sel & 0x80;
+ if (change) {
+ snd_hda_codec_write_cache(codec, 0x1d, 0,
+ AC_VERB_SET_AMP_GAIN_MUTE,
+ AMP_IN_UNMUTE(0));
+ snd_hda_codec_write_cache(codec, 0x1d, 0,
+ AC_VERB_SET_AMP_GAIN_MUTE,
+ AMP_IN_MUTE(1));
+ }
} else {
- change = sel == 0;
- if (change || codec->in_resume)
- snd_hda_codec_write(codec, 0x02, 0,
- AC_VERB_SET_CONNECT_SEL, 1);
+ sel = snd_hda_codec_read(codec, 0x1d, 0,
+ AC_VERB_GET_AMP_GAIN_MUTE,
+ AC_AMP_GET_INPUT | 0x01);
+ change = sel & 0x80;
+ if (change) {
+ snd_hda_codec_write_cache(codec, 0x1d, 0,
+ AC_VERB_SET_AMP_GAIN_MUTE,
+ AMP_IN_MUTE(0));
+ snd_hda_codec_write_cache(codec, 0x1d, 0,
+ AC_VERB_SET_AMP_GAIN_MUTE,
+ AMP_IN_UNMUTE(1));
+ }
sel = snd_hda_codec_read(codec, 0x0b, 0,
AC_VERB_GET_CONNECT_SEL, 0) + 1;
change |= sel != val;
- if (change || codec->in_resume)
- snd_hda_codec_write(codec, 0x0b, 0,
- AC_VERB_SET_CONNECT_SEL, val - 1);
+ if (change)
+ snd_hda_codec_write_cache(codec, 0x0b, 0,
+ AC_VERB_SET_CONNECT_SEL,
+ val - 1);
}
return change;
}
@@ -2047,10 +2102,9 @@ static struct hda_verb ad1988_spdif_init_verbs[] = {
{0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
{0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */
{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
/* SPDIF out pin */
{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x17}, /* 0dB */
{ }
};
@@ -2225,6 +2279,15 @@ static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res)
snd_hda_sequence_write(codec, ad1988_laptop_hp_off);
}
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static struct hda_amp_list ad1988_loopbacks[] = {
+ { 0x20, HDA_INPUT, 0 }, /* Front Mic */
+ { 0x20, HDA_INPUT, 1 }, /* Line */
+ { 0x20, HDA_INPUT, 4 }, /* Mic */
+ { 0x20, HDA_INPUT, 6 }, /* CD */
+ { } /* end */
+};
+#endif
/*
* Automatic parse of I/O pins from the BIOS configuration
@@ -2663,7 +2726,6 @@ static int patch_ad1988(struct hda_codec *codec)
if (spec == NULL)
return -ENOMEM;
- mutex_init(&spec->amp_mutex);
codec->spec = spec;
if (is_rev2(codec))
@@ -2770,6 +2832,9 @@ static int patch_ad1988(struct hda_codec *codec)
codec->patch_ops.unsol_event = ad1988_laptop_unsol_event;
break;
}
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ spec->loopback.amplist = ad1988_loopbacks;
+#endif
return 0;
}
@@ -2926,6 +2991,16 @@ static struct hda_verb ad1884_init_verbs[] = {
{ } /* end */
};
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static struct hda_amp_list ad1884_loopbacks[] = {
+ { 0x20, HDA_INPUT, 0 }, /* Front Mic */
+ { 0x20, HDA_INPUT, 1 }, /* Mic */
+ { 0x20, HDA_INPUT, 2 }, /* CD */
+ { 0x20, HDA_INPUT, 4 }, /* Docking */
+ { } /* end */
+};
+#endif
+
static int patch_ad1884(struct hda_codec *codec)
{
struct ad198x_spec *spec;
@@ -2950,6 +3025,9 @@ static int patch_ad1884(struct hda_codec *codec)
spec->num_init_verbs = 1;
spec->init_verbs[0] = ad1884_init_verbs;
spec->spdif_route = 0;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ spec->loopback.amplist = ad1884_loopbacks;
+#endif
codec->patch_ops = ad198x_patch_ops;
@@ -3331,6 +3409,16 @@ static struct hda_verb ad1882_init_verbs[] = {
{ } /* end */
};
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static struct hda_amp_list ad1882_loopbacks[] = {
+ { 0x20, HDA_INPUT, 0 }, /* Front Mic */
+ { 0x20, HDA_INPUT, 1 }, /* Mic */
+ { 0x20, HDA_INPUT, 4 }, /* Line */
+ { 0x20, HDA_INPUT, 6 }, /* CD */
+ { } /* end */
+};
+#endif
+
/* models */
enum {
AD1882_3STACK,
@@ -3369,6 +3457,9 @@ static int patch_ad1882(struct hda_codec *codec)
spec->num_init_verbs = 1;
spec->init_verbs[0] = ad1882_init_verbs;
spec->spdif_route = 0;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ spec->loopback.amplist = ad1882_loopbacks;
+#endif
codec->patch_ops = ad198x_patch_ops;
diff --git a/sound/pci/hda/patch_atihdmi.c b/sound/pci/hda/patch_atihdmi.c
index 72d3ab9751ac..fbb8969dc559 100644
--- a/sound/pci/hda/patch_atihdmi.c
+++ b/sound/pci/hda/patch_atihdmi.c
@@ -62,19 +62,6 @@ static int atihdmi_init(struct hda_codec *codec)
return 0;
}
-#ifdef CONFIG_PM
-/*
- * resume
- */
-static int atihdmi_resume(struct hda_codec *codec)
-{
- atihdmi_init(codec);
- snd_hda_resume_spdif_out(codec);
-
- return 0;
-}
-#endif
-
/*
* Digital out
*/
@@ -141,9 +128,6 @@ static struct hda_codec_ops atihdmi_patch_ops = {
.build_pcms = atihdmi_build_pcms,
.init = atihdmi_init,
.free = atihdmi_free,
-#ifdef CONFIG_PM
- .resume = atihdmi_resume,
-#endif
};
static int patch_atihdmi(struct hda_codec *codec)
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
index 3c722e667bc8..6c54793bf424 100644
--- a/sound/pci/hda/patch_cmedia.c
+++ b/sound/pci/hda/patch_cmedia.c
@@ -50,7 +50,7 @@ struct cmi_spec {
/* playback */
struct hda_multi_out multiout;
- hda_nid_t dac_nids[4]; /* NID for each DAC */
+ hda_nid_t dac_nids[AUTO_CFG_MAX_OUTS]; /* NID for each DAC */
int num_dacs;
/* capture */
@@ -73,7 +73,6 @@ struct cmi_spec {
unsigned int pin_def_confs;
/* multichannel pins */
- hda_nid_t multich_pin[4]; /* max 8-channel */
struct hda_verb multi_init[9]; /* 2 verbs for each pin + terminator */
};
@@ -427,27 +426,6 @@ static int cmi9880_init(struct hda_codec *codec)
return 0;
}
-#ifdef CONFIG_PM
-/*
- * resume
- */
-static int cmi9880_resume(struct hda_codec *codec)
-{
- struct cmi_spec *spec = codec->spec;
-
- cmi9880_init(codec);
- snd_hda_resume_ctls(codec, cmi9880_basic_mixer);
- if (spec->channel_modes)
- snd_hda_resume_ctls(codec, cmi9880_ch_mode_mixer);
- if (spec->multiout.dig_out_nid)
- snd_hda_resume_spdif_out(codec);
- if (spec->dig_in_nid)
- snd_hda_resume_spdif_in(codec);
-
- return 0;
-}
-#endif
-
/*
* Analog playback callbacks
*/
@@ -635,9 +613,6 @@ static struct hda_codec_ops cmi9880_patch_ops = {
.build_pcms = cmi9880_build_pcms,
.init = cmi9880_init,
.free = cmi9880_free,
-#ifdef CONFIG_PM
- .resume = cmi9880_resume,
-#endif
};
static int patch_cmi9880(struct hda_codec *codec)
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 4d8e8af5c819..6aa073986747 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -85,7 +85,7 @@ struct conexant_spec {
unsigned int num_kctl_alloc, num_kctl_used;
struct snd_kcontrol_new *kctl_alloc;
struct hda_input_mux private_imux;
- hda_nid_t private_dac_nids[4];
+ hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
};
@@ -311,23 +311,6 @@ static void conexant_free(struct hda_codec *codec)
kfree(codec->spec);
}
-#ifdef CONFIG_PM
-static int conexant_resume(struct hda_codec *codec)
-{
- struct conexant_spec *spec = codec->spec;
- int i;
-
- codec->patch_ops.init(codec);
- for (i = 0; i < spec->num_mixers; i++)
- snd_hda_resume_ctls(codec, spec->mixers[i]);
- if (spec->multiout.dig_out_nid)
- snd_hda_resume_spdif_out(codec);
- if (spec->dig_in_nid)
- snd_hda_resume_spdif_in(codec);
- return 0;
-}
-#endif
-
static int conexant_build_controls(struct hda_codec *codec)
{
struct conexant_spec *spec = codec->spec;
@@ -358,9 +341,6 @@ static struct hda_codec_ops conexant_patch_ops = {
.build_pcms = conexant_build_pcms,
.init = conexant_init,
.free = conexant_free,
-#ifdef CONFIG_PM
- .resume = conexant_resume,
-#endif
};
/*
@@ -368,15 +348,7 @@ static struct hda_codec_ops conexant_patch_ops = {
* the private value = nid | (invert << 8)
*/
-static int cxt_eapd_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define cxt_eapd_info snd_ctl_boolean_mono_info
static int cxt_eapd_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -404,13 +376,13 @@ static int cxt_eapd_put(struct snd_kcontrol *kcontrol,
eapd = ucontrol->value.integer.value[0];
if (invert)
eapd = !eapd;
- if (eapd == spec->cur_eapd && !codec->in_resume)
+ if (eapd == spec->cur_eapd)
return 0;
spec->cur_eapd = eapd;
- snd_hda_codec_write(codec, nid,
- 0, AC_VERB_SET_EAPD_BTLENABLE,
- eapd ? 0x02 : 0x00);
+ snd_hda_codec_write_cache(codec, nid,
+ 0, AC_VERB_SET_EAPD_BTLENABLE,
+ eapd ? 0x02 : 0x00);
return 1;
}
@@ -500,34 +472,25 @@ static int cxt5045_hp_master_sw_put(struct snd_kcontrol *kcontrol,
/* toggle internal speakers mute depending of presence of
* the headphone jack
*/
- bits = (!spec->hp_present && spec->cur_eapd) ? 0 : 0x80;
- snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0, 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0, 0x80, bits);
+ bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE;
+ snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
- bits = spec->cur_eapd ? 0 : 0x80;
- snd_hda_codec_amp_update(codec, 0x11, 0, HDA_OUTPUT, 0, 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x11, 1, HDA_OUTPUT, 0, 0x80, bits);
+ bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE;
+ snd_hda_codec_amp_stereo(codec, 0x11, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
return 1;
}
/* bind volumes of both NID 0x10 and 0x11 */
-static int cxt5045_hp_master_vol_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- long *valp = ucontrol->value.integer.value;
- int change;
-
- change = snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0,
- 0x7f, valp[0] & 0x7f);
- change |= snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0,
- 0x7f, valp[1] & 0x7f);
- snd_hda_codec_amp_update(codec, 0x11, 0, HDA_OUTPUT, 0,
- 0x7f, valp[0] & 0x7f);
- snd_hda_codec_amp_update(codec, 0x11, 1, HDA_OUTPUT, 0,
- 0x7f, valp[1] & 0x7f);
- return change;
-}
+static struct hda_bind_ctls cxt5045_hp_bind_master_vol = {
+ .ops = &snd_hda_bind_vol,
+ .values = {
+ HDA_COMPOSE_AMP_VAL(0x10, 3, 0, HDA_OUTPUT),
+ HDA_COMPOSE_AMP_VAL(0x11, 3, 0, HDA_OUTPUT),
+ 0
+ },
+};
/* toggle input of built-in and mic jack appropriately */
static void cxt5045_hp_automic(struct hda_codec *codec)
@@ -562,9 +525,9 @@ static void cxt5045_hp_automute(struct hda_codec *codec)
spec->hp_present = snd_hda_codec_read(codec, 0x11, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = (spec->hp_present || !spec->cur_eapd) ? 0x80 : 0;
- snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0, 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0, 0x80, bits);
+ bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0;
+ snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
}
/* unsolicited event for HP jack sensing */
@@ -591,18 +554,17 @@ static struct snd_kcontrol_new cxt5045_mixers[] = {
.get = conexant_mux_enum_get,
.put = conexant_mux_enum_put
},
- HDA_CODEC_VOLUME("Int Mic Volume", 0x1a, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("Int Mic Switch", 0x1a, 0x01, HDA_INPUT),
- HDA_CODEC_VOLUME("Ext Mic Volume", 0x1a, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Ext Mic Switch", 0x1a, 0x02, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Master Playback Volume",
- .info = snd_hda_mixer_amp_volume_info,
- .get = snd_hda_mixer_amp_volume_get,
- .put = cxt5045_hp_master_vol_put,
- .private_value = HDA_COMPOSE_AMP_VAL(0x10, 3, 0, HDA_OUTPUT),
- },
+ HDA_CODEC_VOLUME("Int Mic Capture Volume", 0x1a, 0x01, HDA_INPUT),
+ HDA_CODEC_MUTE("Int Mic Capture Switch", 0x1a, 0x01, HDA_INPUT),
+ HDA_CODEC_VOLUME("Ext Mic Capture Volume", 0x1a, 0x02, HDA_INPUT),
+ HDA_CODEC_MUTE("Ext Mic Capture Switch", 0x1a, 0x02, HDA_INPUT),
+ HDA_CODEC_VOLUME("PCM Playback Volume", 0x17, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("PCM Playback Switch", 0x17, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x17, 0x1, HDA_INPUT),
+ HDA_CODEC_MUTE("Int Mic Playback Switch", 0x17, 0x1, HDA_INPUT),
+ HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x17, 0x2, HDA_INPUT),
+ HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x17, 0x2, HDA_INPUT),
+ HDA_BIND_VOL("Master Playback Volume", &cxt5045_hp_bind_master_vol),
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Switch",
@@ -620,16 +582,15 @@ static struct hda_verb cxt5045_init_verbs[] = {
{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
/* HP, Amp */
- {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
- {0x17, AC_VERB_SET_CONNECT_SEL,0x01},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE,
- AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x01},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE,
- AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x02},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE,
- AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x03},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE,
- AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x04},
+ {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x10, AC_VERB_SET_CONNECT_SEL, 0x1},
+ {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x11, AC_VERB_SET_CONNECT_SEL, 0x1},
+ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
/* Record selector: Int mic */
{0x1a, AC_VERB_SET_CONNECT_SEL,0x1},
{0x1a, AC_VERB_SET_AMP_GAIN_MUTE,
@@ -915,33 +876,24 @@ static int cxt5047_hp_master_sw_put(struct snd_kcontrol *kcontrol,
/* toggle internal speakers mute depending of presence of
* the headphone jack
*/
- bits = (!spec->hp_present && spec->cur_eapd) ? 0 : 0x80;
- snd_hda_codec_amp_update(codec, 0x1d, 0, HDA_OUTPUT, 0, 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x1d, 1, HDA_OUTPUT, 0, 0x80, bits);
- bits = spec->cur_eapd ? 0 : 0x80;
- snd_hda_codec_amp_update(codec, 0x13, 0, HDA_OUTPUT, 0, 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x13, 1, HDA_OUTPUT, 0, 0x80, bits);
+ bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE;
+ snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
+ bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE;
+ snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
return 1;
}
/* bind volumes of both NID 0x13 (Headphones) and 0x1d (Speakers) */
-static int cxt5047_hp_master_vol_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- long *valp = ucontrol->value.integer.value;
- int change;
-
- change = snd_hda_codec_amp_update(codec, 0x1d, 0, HDA_OUTPUT, 0,
- 0x7f, valp[0] & 0x7f);
- change |= snd_hda_codec_amp_update(codec, 0x1d, 1, HDA_OUTPUT, 0,
- 0x7f, valp[1] & 0x7f);
- snd_hda_codec_amp_update(codec, 0x13, 0, HDA_OUTPUT, 0,
- 0x7f, valp[0] & 0x7f);
- snd_hda_codec_amp_update(codec, 0x13, 1, HDA_OUTPUT, 0,
- 0x7f, valp[1] & 0x7f);
- return change;
-}
+static struct hda_bind_ctls cxt5047_bind_master_vol = {
+ .ops = &snd_hda_bind_vol,
+ .values = {
+ HDA_COMPOSE_AMP_VAL(0x13, 3, 0, HDA_OUTPUT),
+ HDA_COMPOSE_AMP_VAL(0x1d, 3, 0, HDA_OUTPUT),
+ 0
+ },
+};
/* mute internal speaker if HP is plugged */
static void cxt5047_hp_automute(struct hda_codec *codec)
@@ -952,12 +904,12 @@ static void cxt5047_hp_automute(struct hda_codec *codec)
spec->hp_present = snd_hda_codec_read(codec, 0x13, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = (spec->hp_present || !spec->cur_eapd) ? 0x80 : 0;
- snd_hda_codec_amp_update(codec, 0x1d, 0, HDA_OUTPUT, 0, 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x1d, 1, HDA_OUTPUT, 0, 0x80, bits);
+ bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0;
+ snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
/* Mute/Unmute PCM 2 for good measure - some systems need this */
- snd_hda_codec_amp_update(codec, 0x1c, 0, HDA_OUTPUT, 0, 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x1c, 1, HDA_OUTPUT, 0, 0x80, bits);
+ snd_hda_codec_amp_stereo(codec, 0x1c, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
}
/* mute internal speaker if HP is plugged */
@@ -969,12 +921,12 @@ static void cxt5047_hp2_automute(struct hda_codec *codec)
spec->hp_present = snd_hda_codec_read(codec, 0x13, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = spec->hp_present ? 0x80 : 0;
- snd_hda_codec_amp_update(codec, 0x1d, 0, HDA_OUTPUT, 0, 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x1d, 1, HDA_OUTPUT, 0, 0x80, bits);
+ bits = spec->hp_present ? HDA_AMP_MUTE : 0;
+ snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
/* Mute/Unmute PCM 2 for good measure - some systems need this */
- snd_hda_codec_amp_update(codec, 0x1c, 0, HDA_OUTPUT, 0, 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x1c, 1, HDA_OUTPUT, 0, 0x80, bits);
+ snd_hda_codec_amp_stereo(codec, 0x1c, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
}
/* toggle input of built-in and mic jack appropriately */
@@ -1063,14 +1015,7 @@ static struct snd_kcontrol_new cxt5047_toshiba_mixers[] = {
HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT),
HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT),
HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Master Playback Volume",
- .info = snd_hda_mixer_amp_volume_info,
- .get = snd_hda_mixer_amp_volume_get,
- .put = cxt5047_hp_master_vol_put,
- .private_value = HDA_COMPOSE_AMP_VAL(0x13, 3, 0, HDA_OUTPUT),
- },
+ HDA_BIND_VOL("Master Playback Volume", &cxt5047_bind_master_vol),
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Switch",
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 9a47eec5a27b..1c502789cc1e 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -102,6 +102,8 @@ enum {
/* ALC268 models */
enum {
ALC268_3ST,
+ ALC268_TOSHIBA,
+ ALC268_ACER,
ALC268_AUTO,
ALC268_MODEL_LAST /* last tag */
};
@@ -129,6 +131,7 @@ enum {
ALC861VD_6ST_DIG,
ALC861VD_LENOVO,
ALC861VD_DALLAS,
+ ALC861VD_HP,
ALC861VD_AUTO,
ALC861VD_MODEL_LAST,
};
@@ -140,6 +143,7 @@ enum {
ALC662_3ST_6ch,
ALC662_5ST_DIG,
ALC662_LENOVO_101E,
+ ALC662_ASUS_EEEPC_P701,
ALC662_AUTO,
ALC662_MODEL_LAST,
};
@@ -152,7 +156,9 @@ enum {
ALC882_W2JC,
ALC882_TARGA,
ALC882_ASUS_A7J,
+ ALC882_ASUS_A7M,
ALC885_MACPRO,
+ ALC885_MBP3,
ALC885_IMAC24,
ALC882_AUTO,
ALC882_MODEL_LAST,
@@ -167,12 +173,14 @@ enum {
ALC883_TARGA_DIG,
ALC883_TARGA_2ch_DIG,
ALC883_ACER,
+ ALC883_ACER_ASPIRE,
ALC883_MEDION,
ALC883_MEDION_MD2,
ALC883_LAPTOP_EAPD,
ALC883_LENOVO_101E_2ch,
ALC883_LENOVO_NB0763,
- ALC888_LENOVO_MS7195_DIG,
+ ALC888_LENOVO_MS7195_DIG,
+ ALC883_HAIER_W66,
ALC888_6ST_HP,
ALC888_3ST_HP,
ALC883_AUTO,
@@ -230,7 +238,7 @@ struct alc_spec {
unsigned int num_kctl_alloc, num_kctl_used;
struct snd_kcontrol_new *kctl_alloc;
struct hda_input_mux private_imux;
- hda_nid_t private_dac_nids[5];
+ hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
/* hooks */
void (*init_hook)(struct hda_codec *codec);
@@ -239,6 +247,10 @@ struct alc_spec {
/* for pin sensing */
unsigned int sense_updated: 1;
unsigned int jack_present: 1;
+
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ struct hda_loopback_check loopback;
+#endif
};
/*
@@ -263,6 +275,9 @@ struct alc_config_preset {
const struct hda_input_mux *input_mux;
void (*unsol_event)(struct hda_codec *, unsigned int);
void (*init_hook)(struct hda_codec *);
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ struct hda_amp_list *loopbacks;
+#endif
};
@@ -441,8 +456,9 @@ static int alc_pin_mode_put(struct snd_kcontrol *kcontrol,
change = pinctl != alc_pin_mode_values[val];
if (change) {
/* Set pin mode to that requested */
- snd_hda_codec_write(codec,nid,0,AC_VERB_SET_PIN_WIDGET_CONTROL,
- alc_pin_mode_values[val]);
+ snd_hda_codec_write_cache(codec, nid, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL,
+ alc_pin_mode_values[val]);
/* Also enable the retasking pin's input/output as required
* for the requested pin mode. Enum values of 2 or less are
@@ -455,19 +471,15 @@ static int alc_pin_mode_put(struct snd_kcontrol *kcontrol,
* this turns out to be necessary in the future.
*/
if (val <= 2) {
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_AMP_GAIN_MUTE,
- AMP_OUT_MUTE);
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_AMP_GAIN_MUTE,
- AMP_IN_UNMUTE(0));
+ snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, HDA_AMP_MUTE);
+ snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
+ HDA_AMP_MUTE, 0);
} else {
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_AMP_GAIN_MUTE,
- AMP_IN_MUTE(0));
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_AMP_GAIN_MUTE,
- AMP_OUT_UNMUTE);
+ snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
+ HDA_AMP_MUTE, HDA_AMP_MUTE);
+ snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, 0);
}
}
return change;
@@ -486,15 +498,7 @@ static int alc_pin_mode_put(struct snd_kcontrol *kcontrol,
* needed for any "production" models.
*/
#ifdef CONFIG_SND_DEBUG
-static int alc_gpio_data_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define alc_gpio_data_info snd_ctl_boolean_mono_info
static int alc_gpio_data_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -527,7 +531,8 @@ static int alc_gpio_data_put(struct snd_kcontrol *kcontrol,
gpio_data &= ~mask;
else
gpio_data |= mask;
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_GPIO_DATA, gpio_data);
+ snd_hda_codec_write_cache(codec, nid, 0,
+ AC_VERB_SET_GPIO_DATA, gpio_data);
return change;
}
@@ -547,15 +552,7 @@ static int alc_gpio_data_put(struct snd_kcontrol *kcontrol,
* necessary.
*/
#ifdef CONFIG_SND_DEBUG
-static int alc_spdif_ctrl_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define alc_spdif_ctrl_info snd_ctl_boolean_mono_info
static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -588,8 +585,8 @@ static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol,
ctrl_data &= ~mask;
else
ctrl_data |= mask;
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
- ctrl_data);
+ snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
+ ctrl_data);
return change;
}
@@ -638,6 +635,9 @@ static void setup_preset(struct alc_spec *spec,
spec->unsol_event = preset->unsol_event;
spec->init_hook = preset->init_hook;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ spec->loopback.amplist = preset->loopbacks;
+#endif
}
/* Enable GPIO mask and set output */
@@ -662,6 +662,44 @@ static struct hda_verb alc_gpio3_init_verbs[] = {
{ }
};
+static void alc_sku_automute(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ unsigned int mute;
+ unsigned int present;
+ unsigned int hp_nid = spec->autocfg.hp_pins[0];
+ unsigned int sp_nid = spec->autocfg.speaker_pins[0];
+
+ /* need to execute and sync at first */
+ snd_hda_codec_read(codec, hp_nid, 0, AC_VERB_SET_PIN_SENSE, 0);
+ present = snd_hda_codec_read(codec, hp_nid, 0,
+ AC_VERB_GET_PIN_SENSE, 0);
+ spec->jack_present = (present & 0x80000000) != 0;
+ if (spec->jack_present) {
+ /* mute internal speaker */
+ snd_hda_codec_amp_stereo(codec, sp_nid, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, HDA_AMP_MUTE);
+ } else {
+ /* unmute internal speaker if necessary */
+ mute = snd_hda_codec_amp_read(codec, hp_nid, 0, HDA_OUTPUT, 0);
+ snd_hda_codec_amp_stereo(codec, sp_nid, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, mute);
+ }
+}
+
+/* unsolicited event for HP jack sensing */
+static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+ if (codec->vendor_id == 0x10ec0880)
+ res >>= 28;
+ else
+ res >>= 26;
+ if (res != ALC880_HP_EVENT)
+ return;
+
+ alc_sku_automute(codec);
+}
+
/* 32-bit subsystem ID for BIOS loading in HD Audio codec.
* 31 ~ 16 : Manufacture ID
* 15 ~ 8 : SKU ID
@@ -672,13 +710,48 @@ static void alc_subsystem_id(struct hda_codec *codec,
unsigned int porta, unsigned int porte,
unsigned int portd)
{
- unsigned int ass, tmp;
+ unsigned int ass, tmp, i;
+ unsigned nid;
+ struct alc_spec *spec = codec->spec;
- ass = codec->subsystem_id;
- if (!(ass & 1))
+ ass = codec->subsystem_id & 0xffff;
+ if ((ass != codec->bus->pci->subsystem_device) && (ass & 1))
+ goto do_sku;
+
+ /*
+ * 31~30 : port conetcivity
+ * 29~21 : reserve
+ * 20 : PCBEEP input
+ * 19~16 : Check sum (15:1)
+ * 15~1 : Custom
+ * 0 : override
+ */
+ nid = 0x1d;
+ if (codec->vendor_id == 0x10ec0260)
+ nid = 0x17;
+ ass = snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_CONFIG_DEFAULT, 0);
+ if (!(ass & 1) && !(ass & 0x100000))
+ return;
+ if ((ass >> 30) != 1) /* no physical connection */
return;
- /* Override */
+ /* check sum */
+ tmp = 0;
+ for (i = 1; i < 16; i++) {
+ if ((ass >> i) && 1)
+ tmp++;
+ }
+ if (((ass >> 16) & 0xf) != tmp)
+ return;
+do_sku:
+ /*
+ * 0 : override
+ * 1 : Swap Jack
+ * 2 : 0 --> Desktop, 1 --> Laptop
+ * 3~5 : External Amplifier control
+ * 7~6 : Reserved
+ */
tmp = (ass & 0x38) >> 3; /* external Amp control */
switch (tmp) {
case 1:
@@ -690,38 +763,108 @@ static void alc_subsystem_id(struct hda_codec *codec,
case 7:
snd_hda_sequence_write(codec, alc_gpio3_init_verbs);
break;
- case 5:
+ case 5: /* set EAPD output high */
switch (codec->vendor_id) {
- case 0x10ec0862:
- case 0x10ec0660:
- case 0x10ec0662:
+ case 0x10ec0260:
+ snd_hda_codec_write(codec, 0x0f, 0,
+ AC_VERB_SET_EAPD_BTLENABLE, 2);
+ snd_hda_codec_write(codec, 0x10, 0,
+ AC_VERB_SET_EAPD_BTLENABLE, 2);
+ break;
+ case 0x10ec0262:
case 0x10ec0267:
case 0x10ec0268:
+ case 0x10ec0269:
+ case 0x10ec0862:
+ case 0x10ec0662:
snd_hda_codec_write(codec, 0x14, 0,
AC_VERB_SET_EAPD_BTLENABLE, 2);
snd_hda_codec_write(codec, 0x15, 0,
AC_VERB_SET_EAPD_BTLENABLE, 2);
- return;
+ break;
}
- case 6:
- if (ass & 4) { /* bit 2 : 0 = Desktop, 1 = Laptop */
- hda_nid_t port = 0;
- tmp = (ass & 0x1800) >> 11;
- switch (tmp) {
- case 0: port = porta; break;
- case 1: port = porte; break;
- case 2: port = portd; break;
- }
- if (port)
- snd_hda_codec_write(codec, port, 0,
- AC_VERB_SET_EAPD_BTLENABLE,
- 2);
+ switch (codec->vendor_id) {
+ case 0x10ec0260:
+ snd_hda_codec_write(codec, 0x1a, 0,
+ AC_VERB_SET_COEF_INDEX, 7);
+ tmp = snd_hda_codec_read(codec, 0x1a, 0,
+ AC_VERB_GET_PROC_COEF, 0);
+ snd_hda_codec_write(codec, 0x1a, 0,
+ AC_VERB_SET_COEF_INDEX, 7);
+ snd_hda_codec_write(codec, 0x1a, 0,
+ AC_VERB_SET_PROC_COEF,
+ tmp | 0x2010);
+ break;
+ case 0x10ec0262:
+ case 0x10ec0880:
+ case 0x10ec0882:
+ case 0x10ec0883:
+ case 0x10ec0885:
+ case 0x10ec0888:
+ snd_hda_codec_write(codec, 0x20, 0,
+ AC_VERB_SET_COEF_INDEX, 7);
+ tmp = snd_hda_codec_read(codec, 0x20, 0,
+ AC_VERB_GET_PROC_COEF, 0);
+ snd_hda_codec_write(codec, 0x20, 0,
+ AC_VERB_SET_COEF_INDEX, 7);
+ snd_hda_codec_write(codec, 0x20, 0,
+ AC_VERB_SET_PROC_COEF,
+ tmp | 0x2010);
+ break;
+ case 0x10ec0267:
+ case 0x10ec0268:
+ snd_hda_codec_write(codec, 0x20, 0,
+ AC_VERB_SET_COEF_INDEX, 7);
+ tmp = snd_hda_codec_read(codec, 0x20, 0,
+ AC_VERB_GET_PROC_COEF, 0);
+ snd_hda_codec_write(codec, 0x20, 0,
+ AC_VERB_SET_COEF_INDEX, 7);
+ snd_hda_codec_write(codec, 0x20, 0,
+ AC_VERB_SET_PROC_COEF,
+ tmp | 0x3000);
+ break;
}
- snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
- snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF,
- (tmp == 5 ? 0x3040 : 0x3050));
+ default:
break;
}
+
+ /* is laptop and enable the function "Mute internal speaker
+ * when the external headphone out jack is plugged"
+ */
+ if (!(ass & 0x4) || !(ass & 0x8000))
+ return;
+ /*
+ * 10~8 : Jack location
+ * 12~11: Headphone out -> 00: PortA, 01: PortE, 02: PortD, 03: Resvered
+ * 14~13: Resvered
+ * 15 : 1 --> enable the function "Mute internal speaker
+ * when the external headphone out jack is plugged"
+ */
+ if (!spec->autocfg.speaker_pins[0]) {
+ if (spec->multiout.dac_nids[0])
+ spec->autocfg.speaker_pins[0] =
+ spec->multiout.dac_nids[0];
+ else
+ return;
+ }
+
+ if (!spec->autocfg.hp_pins[0]) {
+ tmp = (ass >> 11) & 0x3; /* HP to chassis */
+ if (tmp == 0)
+ spec->autocfg.hp_pins[0] = porta;
+ else if (tmp == 1)
+ spec->autocfg.hp_pins[0] = porte;
+ else if (tmp == 2)
+ spec->autocfg.hp_pins[0] = portd;
+ else
+ return;
+ }
+
+ snd_hda_codec_write(codec, spec->autocfg.hp_pins[0], 0,
+ AC_VERB_SET_UNSOLICITED_ENABLE,
+ AC_USRSP_EN | ALC880_HP_EVENT);
+ spec->unsol_event = alc_sku_unsol_event;
+ spec->init_hook = alc_sku_automute;
}
/*
@@ -1304,11 +1447,13 @@ static struct hda_verb alc880_volume_init_verbs[] = {
* panel mic (mic 2)
*/
/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
/*
* Set up output mixers (0x0c - 0x0f)
@@ -1568,15 +1713,11 @@ static void alc880_uniwill_hp_automute(struct hda_codec *codec)
present = snd_hda_codec_read(codec, 0x14, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = present ? 0x80 : 0;
- snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x16, 0, HDA_OUTPUT, 0,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x16, 1, HDA_OUTPUT, 0,
- 0x80, bits);
+ bits = present ? HDA_AMP_MUTE : 0;
+ snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
+ snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
}
/* auto-toggle front mic */
@@ -1587,11 +1728,8 @@ static void alc880_uniwill_mic_automute(struct hda_codec *codec)
present = snd_hda_codec_read(codec, 0x18, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = present ? 0x80 : 0;
- snd_hda_codec_amp_update(codec, 0x0b, 0, HDA_INPUT, 1,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x0b, 1, HDA_INPUT, 1,
- 0x80, bits);
+ bits = present ? HDA_AMP_MUTE : 0;
+ snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits);
}
static void alc880_uniwill_automute(struct hda_codec *codec)
@@ -1623,11 +1761,8 @@ static void alc880_uniwill_p53_hp_automute(struct hda_codec *codec)
present = snd_hda_codec_read(codec, 0x14, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = present ? 0x80 : 0;
- snd_hda_codec_amp_update(codec, 0x15, 0, HDA_INPUT, 0,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x15, 1, HDA_INPUT, 0,
- 0x80, bits);
+ bits = present ? HDA_AMP_MUTE : 0;
+ snd_hda_codec_amp_stereo(codec, 0x15, HDA_INPUT, 0, HDA_AMP_MUTE, bits);
}
static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec)
@@ -1635,19 +1770,14 @@ static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec)
unsigned int present;
present = snd_hda_codec_read(codec, 0x21, 0,
- AC_VERB_GET_VOLUME_KNOB_CONTROL, 0) & 0x7f;
-
- snd_hda_codec_amp_update(codec, 0x0c, 0, HDA_OUTPUT, 0,
- 0x7f, present);
- snd_hda_codec_amp_update(codec, 0x0c, 1, HDA_OUTPUT, 0,
- 0x7f, present);
-
- snd_hda_codec_amp_update(codec, 0x0d, 0, HDA_OUTPUT, 0,
- 0x7f, present);
- snd_hda_codec_amp_update(codec, 0x0d, 1, HDA_OUTPUT, 0,
- 0x7f, present);
-
+ AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);
+ present &= HDA_AMP_VOLMASK;
+ snd_hda_codec_amp_stereo(codec, 0x0c, HDA_OUTPUT, 0,
+ HDA_AMP_VOLMASK, present);
+ snd_hda_codec_amp_stereo(codec, 0x0d, HDA_OUTPUT, 0,
+ HDA_AMP_VOLMASK, present);
}
+
static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec,
unsigned int res)
{
@@ -1868,8 +1998,8 @@ static struct hda_verb alc880_lg_init_verbs[] = {
{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
/* mute all amp mixer inputs */
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
/* line-in to input */
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
@@ -1900,11 +2030,9 @@ static void alc880_lg_automute(struct hda_codec *codec)
present = snd_hda_codec_read(codec, 0x1b, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = present ? 0x80 : 0;
- snd_hda_codec_amp_update(codec, 0x17, 0, HDA_OUTPUT, 0,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x17, 1, HDA_OUTPUT, 0,
- 0x80, bits);
+ bits = present ? HDA_AMP_MUTE : 0;
+ snd_hda_codec_amp_stereo(codec, 0x17, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
}
static void alc880_lg_unsol_event(struct hda_codec *codec, unsigned int res)
@@ -1973,7 +2101,7 @@ static struct hda_verb alc880_lg_lw_init_verbs[] = {
{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
/* speaker-out */
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
@@ -1999,11 +2127,9 @@ static void alc880_lg_lw_automute(struct hda_codec *codec)
present = snd_hda_codec_read(codec, 0x1b, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = present ? 0x80 : 0;
- snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
- 0x80, bits);
+ bits = present ? HDA_AMP_MUTE : 0;
+ snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
}
static void alc880_lg_lw_unsol_event(struct hda_codec *codec, unsigned int res)
@@ -2015,6 +2141,24 @@ static void alc880_lg_lw_unsol_event(struct hda_codec *codec, unsigned int res)
alc880_lg_lw_automute(codec);
}
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static struct hda_amp_list alc880_loopbacks[] = {
+ { 0x0b, HDA_INPUT, 0 },
+ { 0x0b, HDA_INPUT, 1 },
+ { 0x0b, HDA_INPUT, 2 },
+ { 0x0b, HDA_INPUT, 3 },
+ { 0x0b, HDA_INPUT, 4 },
+ { } /* end */
+};
+
+static struct hda_amp_list alc880_lg_loopbacks[] = {
+ { 0x0b, HDA_INPUT, 1 },
+ { 0x0b, HDA_INPUT, 6 },
+ { 0x0b, HDA_INPUT, 7 },
+ { } /* end */
+};
+#endif
+
/*
* Common callbacks
*/
@@ -2041,24 +2185,11 @@ static void alc_unsol_event(struct hda_codec *codec, unsigned int res)
spec->unsol_event(codec, res);
}
-#ifdef CONFIG_PM
-/*
- * resume
- */
-static int alc_resume(struct hda_codec *codec)
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid)
{
struct alc_spec *spec = codec->spec;
- int i;
-
- alc_init(codec);
- for (i = 0; i < spec->num_mixers; i++)
- snd_hda_resume_ctls(codec, spec->mixers[i]);
- if (spec->multiout.dig_out_nid)
- snd_hda_resume_spdif_out(codec);
- if (spec->dig_in_nid)
- snd_hda_resume_spdif_in(codec);
-
- return 0;
+ return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
}
#endif
@@ -2293,8 +2424,8 @@ static struct hda_codec_ops alc_patch_ops = {
.init = alc_init,
.free = alc_free,
.unsol_event = alc_unsol_event,
-#ifdef CONFIG_PM
- .resume = alc_resume,
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ .check_power_status = alc_check_power_status,
#endif
};
@@ -2392,11 +2523,14 @@ static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol,
AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
new_ctl = ctls[ucontrol->value.enumerated.item[0]];
if (old_ctl != new_ctl) {
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, new_ctl);
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
- (ucontrol->value.enumerated.item[0] >= 3 ?
- 0xb080 : 0xb000));
+ int val;
+ snd_hda_codec_write_cache(codec, nid, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL,
+ new_ctl);
+ val = ucontrol->value.enumerated.item[0] >= 3 ?
+ HDA_AMP_MUTE : 0;
+ snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, val);
return 1;
}
return 0;
@@ -2439,7 +2573,8 @@ static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol,
sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3;
if (ucontrol->value.enumerated.item[0] != sel) {
sel = ucontrol->value.enumerated.item[0] & 3;
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, sel);
+ snd_hda_codec_write_cache(codec, nid, 0,
+ AC_VERB_SET_CONNECT_SEL, sel);
return 1;
}
return 0;
@@ -2885,6 +3020,7 @@ static struct alc_config_preset alc880_presets[] = {
alc880_beep_init_verbs },
.num_dacs = ARRAY_SIZE(alc880_dac_nids),
.dac_nids = alc880_dac_nids,
+ .dig_out_nid = ALC880_DIGOUT_NID,
.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
.channel_mode = alc880_2_jack_modes,
.input_mux = &alc880_capture_source,
@@ -2916,6 +3052,9 @@ static struct alc_config_preset alc880_presets[] = {
.input_mux = &alc880_lg_capture_source,
.unsol_event = alc880_lg_unsol_event,
.init_hook = alc880_lg_automute,
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ .loopbacks = alc880_lg_loopbacks,
+#endif
},
[ALC880_LG_LW] = {
.mixers = { alc880_lg_lw_mixer },
@@ -3399,6 +3538,10 @@ static int patch_alc880(struct hda_codec *codec)
codec->patch_ops = alc_patch_ops;
if (board_config == ALC880_AUTO)
spec->init_hook = alc880_auto_init;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ if (!spec->loopback.amplist)
+ spec->loopback.amplist = alc880_loopbacks;
+#endif
return 0;
}
@@ -3747,12 +3890,12 @@ static struct hda_verb alc260_init_verbs[] = {
/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
* Line In 2 = 0x03
*/
- /* mute CD */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
- /* mute Line In */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- /* mute Mic */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ /* mute analog inputs */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
/* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
/* mute Front out path */
{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
@@ -3797,12 +3940,12 @@ static struct hda_verb alc260_hp_init_verbs[] = {
/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
* Line In 2 = 0x03
*/
- /* unmute CD */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
- /* unmute Line In */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
- /* unmute Mic */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ /* mute analog inputs */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
/* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
/* Unmute Front out path */
{0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
@@ -3847,12 +3990,12 @@ static struct hda_verb alc260_hp_3013_init_verbs[] = {
/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
* Line In 2 = 0x03
*/
- /* unmute CD */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
- /* unmute Line In */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
- /* unmute Mic */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ /* mute analog inputs */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
/* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
/* Unmute Front out path */
{0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
@@ -4069,13 +4212,17 @@ static void alc260_replacer_672v_automute(struct hda_codec *codec)
present = snd_hda_codec_read(codec, 0x0f, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
if (present) {
- snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 1);
- snd_hda_codec_write(codec, 0x0f, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP);
+ snd_hda_codec_write_cache(codec, 0x01, 0,
+ AC_VERB_SET_GPIO_DATA, 1);
+ snd_hda_codec_write_cache(codec, 0x0f, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL,
+ PIN_HP);
} else {
- snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0);
- snd_hda_codec_write(codec, 0x0f, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+ snd_hda_codec_write_cache(codec, 0x01, 0,
+ AC_VERB_SET_GPIO_DATA, 0);
+ snd_hda_codec_write_cache(codec, 0x0f, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL,
+ PIN_OUT);
}
}
@@ -4470,11 +4617,12 @@ static struct hda_verb alc260_volume_init_verbs[] = {
* front panel mic (mic 2)
*/
/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+ /* mute analog inputs */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
/*
* Set up output mixers (0x08 - 0x0a)
@@ -4551,6 +4699,17 @@ static void alc260_auto_init(struct hda_codec *codec)
alc260_auto_init_analog_input(codec);
}
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static struct hda_amp_list alc260_loopbacks[] = {
+ { 0x07, HDA_INPUT, 0 },
+ { 0x07, HDA_INPUT, 1 },
+ { 0x07, HDA_INPUT, 2 },
+ { 0x07, HDA_INPUT, 3 },
+ { 0x07, HDA_INPUT, 4 },
+ { } /* end */
+};
+#endif
+
/*
* ALC260 configurations
*/
@@ -4750,6 +4909,10 @@ static int patch_alc260(struct hda_codec *codec)
codec->patch_ops = alc_patch_ops;
if (board_config == ALC260_AUTO)
spec->init_hook = alc260_auto_init;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ if (!spec->loopback.amplist)
+ spec->loopback.amplist = alc260_loopbacks;
+#endif
return 0;
}
@@ -4812,12 +4975,13 @@ static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol,
idx = ucontrol->value.enumerated.item[0];
if (idx >= imux->num_items)
idx = imux->num_items - 1;
- if (*cur_val == idx && !codec->in_resume)
+ if (*cur_val == idx)
return 0;
for (i = 0; i < imux->num_items; i++) {
- unsigned int v = (i == idx) ? 0x7000 : 0x7080;
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
- v | (imux->items[i].index << 8));
+ unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
+ snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
+ imux->items[i].index,
+ HDA_AMP_MUTE, v);
}
*cur_val = idx;
return 1;
@@ -4879,6 +5043,38 @@ static struct hda_channel_mode alc882_sixstack_modes[2] = {
{ 8, alc882_sixstack_ch8_init },
};
+/*
+ * macbook pro ALC885 can switch LineIn to LineOut without loosing Mic
+ */
+
+/*
+ * 2ch mode
+ */
+static struct hda_verb alc885_mbp_ch2_init[] = {
+ { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+ { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ { } /* end */
+};
+
+/*
+ * 6ch mode
+ */
+static struct hda_verb alc885_mbp_ch6_init[] = {
+ { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+ { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
+ { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ { } /* end */
+};
+
+static struct hda_channel_mode alc885_mbp_6ch_modes[2] = {
+ { 2, alc885_mbp_ch2_init },
+ { 6, alc885_mbp_ch6_init },
+};
+
+
/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
* Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
*/
@@ -4909,6 +5105,19 @@ static struct snd_kcontrol_new alc882_base_mixer[] = {
{ } /* end */
};
+static struct snd_kcontrol_new alc885_mbp3_mixer[] = {
+ HDA_CODEC_VOLUME("Master Volume", 0x0c, 0x00, HDA_OUTPUT),
+ HDA_BIND_MUTE ("Master Switch", 0x0c, 0x02, HDA_INPUT),
+ HDA_CODEC_MUTE ("Speaker Switch", 0x14, 0x00, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Line Out Volume", 0x0d,0x00, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Line In Playback Volume", 0x0b, 0x02, HDA_INPUT),
+ HDA_CODEC_MUTE ("Line In Playback Switch", 0x0b, 0x02, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT),
+ HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT),
+ HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0x00, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x00, HDA_INPUT),
+ { } /* end */
+};
static struct snd_kcontrol_new alc882_w2jc_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
@@ -4934,8 +5143,10 @@ static struct snd_kcontrol_new alc882_targa_mixer[] = {
HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+ HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
{ } /* end */
};
@@ -4955,6 +5166,23 @@ static struct snd_kcontrol_new alc882_asus_a7j_mixer[] = {
HDA_CODEC_MUTE("Mobile Line Playback Switch", 0x0b, 0x03, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+ { } /* end */
+};
+
+static struct snd_kcontrol_new alc882_asus_a7m_mixer[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+ HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+ HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+ HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+ HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+ HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
+ HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
{ } /* end */
};
@@ -5119,6 +5347,66 @@ static struct hda_verb alc882_macpro_init_verbs[] = {
{ }
};
+/* Macbook Pro rev3 */
+static struct hda_verb alc885_mbp3_init_verbs[] = {
+ /* Front mixer: unmute input/output amp left and right (volume = 0) */
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ /* Rear mixer */
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ /* Front Pin: output 0 (0x0c) */
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
+ /* HP Pin: output 0 (0x0d) */
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
+ /* Mic (rear) pin: input vref at 80% */
+ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ /* Front Mic pin: input vref at 80% */
+ {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ /* Line In pin: use output 1 when in LineOut mode */
+ {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
+
+ /* FIXME: use matrix-type input source selection */
+ /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
+ /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+ /* Input mixer2 */
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+ /* Input mixer3 */
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+ /* ADC1: mute amp left and right */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
+ /* ADC2: mute amp left and right */
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+ /* ADC3: mute amp left and right */
+ {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+ { }
+};
+
/* iMac 24 mixer. */
static struct snd_kcontrol_new alc885_imac24_mixer[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
@@ -5154,14 +5442,10 @@ static void alc885_imac24_automute(struct hda_codec *codec)
present = snd_hda_codec_read(codec, 0x14, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- snd_hda_codec_amp_update(codec, 0x18, 0, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
- snd_hda_codec_amp_update(codec, 0x18, 1, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
- snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
- snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
+ snd_hda_codec_amp_stereo(codec, 0x18, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+ snd_hda_codec_amp_stereo(codec, 0x1a, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
}
/* Processes unsolicited events. */
@@ -5173,6 +5457,27 @@ static void alc885_imac24_unsol_event(struct hda_codec *codec,
alc885_imac24_automute(codec);
}
+static void alc885_mbp3_automute(struct hda_codec *codec)
+{
+ unsigned int present;
+
+ present = snd_hda_codec_read(codec, 0x15, 0,
+ AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+ snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+ snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, present ? 0 : HDA_AMP_MUTE);
+
+}
+static void alc885_mbp3_unsol_event(struct hda_codec *codec,
+ unsigned int res)
+{
+ /* Headphone insertion or removal. */
+ if ((res >> 26) == ALC880_HP_EVENT)
+ alc885_mbp3_automute(codec);
+}
+
+
static struct hda_verb alc882_targa_verbs[] = {
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
@@ -5198,11 +5503,10 @@ static void alc882_targa_automute(struct hda_codec *codec)
present = snd_hda_codec_read(codec, 0x14, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
- snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
- snd_hda_codec_write(codec, 1, 0, AC_VERB_SET_GPIO_DATA, present ? 1 : 3);
+ snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+ snd_hda_codec_write_cache(codec, 1, 0, AC_VERB_SET_GPIO_DATA,
+ present ? 1 : 3);
}
static void alc882_targa_unsol_event(struct hda_codec *codec, unsigned int res)
@@ -5233,6 +5537,24 @@ static struct hda_verb alc882_asus_a7j_verbs[] = {
{ } /* end */
};
+static struct hda_verb alc882_asus_a7m_verbs[] = {
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+
+ {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
+ {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
+ {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
+
+ {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
+ {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
+ {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
+ { } /* end */
+};
+
static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted)
{
unsigned int gpiostate, gpiomask, gpiodir;
@@ -5265,6 +5587,20 @@ static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted)
AC_VERB_SET_GPIO_DATA, gpiostate);
}
+/* set up GPIO at initialization */
+static void alc885_macpro_init_hook(struct hda_codec *codec)
+{
+ alc882_gpio_mute(codec, 0, 0);
+ alc882_gpio_mute(codec, 1, 0);
+}
+
+/* set up GPIO and update auto-muting at initialization */
+static void alc885_imac24_init_hook(struct hda_codec *codec)
+{
+ alc885_macpro_init_hook(codec);
+ alc885_imac24_automute(codec);
+}
+
/*
* generic initialization of ADC, input mixers and output mixers
*/
@@ -5279,17 +5615,17 @@ static struct hda_verb alc882_auto_init_verbs[] = {
{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
+ /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
* mixer widget
* Note: PASD motherboards uses the Line In 2 as the input for
* front panel mic (mic 2)
*/
/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
/*
* Set up output mixers (0x0c - 0x0f)
@@ -5378,6 +5714,10 @@ static struct snd_kcontrol_new alc882_capture_mixer[] = {
{ } /* end */
};
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+#define alc882_loopbacks alc880_loopbacks
+#endif
+
/* pcm configuration: identiacal with ALC880 */
#define alc882_pcm_analog_playback alc880_pcm_analog_playback
#define alc882_pcm_analog_capture alc880_pcm_analog_capture
@@ -5392,7 +5732,11 @@ static const char *alc882_models[ALC882_MODEL_LAST] = {
[ALC882_6ST_DIG] = "6stack-dig",
[ALC882_ARIMA] = "arima",
[ALC882_W2JC] = "w2jc",
+ [ALC882_TARGA] = "targa",
+ [ALC882_ASUS_A7J] = "asus-a7j",
+ [ALC882_ASUS_A7M] = "asus-a7m",
[ALC885_MACPRO] = "macpro",
+ [ALC885_MBP3] = "mbp3",
[ALC885_IMAC24] = "imac24",
[ALC882_AUTO] = "auto",
};
@@ -5404,6 +5748,8 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = {
SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8 */
SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA),
SND_PCI_QUIRK(0x1043, 0x060d, "Asus A7J", ALC882_ASUS_A7J),
+ SND_PCI_QUIRK(0x1043, 0x1243, "Asus A7J", ALC882_ASUS_A7J),
+ SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_ASUS_A7M),
SND_PCI_QUIRK(0x1043, 0x817f, "Asus P5LD2", ALC882_6ST_DIG),
SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG),
SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_W2JC),
@@ -5455,6 +5801,20 @@ static struct alc_config_preset alc882_presets[] = {
.input_mux = &alc882_capture_source,
.dig_out_nid = ALC882_DIGOUT_NID,
},
+ [ALC885_MBP3] = {
+ .mixers = { alc885_mbp3_mixer, alc882_chmode_mixer },
+ .init_verbs = { alc885_mbp3_init_verbs,
+ alc880_gpio1_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc882_dac_nids),
+ .dac_nids = alc882_dac_nids,
+ .channel_mode = alc885_mbp_6ch_modes,
+ .num_channel_mode = ARRAY_SIZE(alc885_mbp_6ch_modes),
+ .input_mux = &alc882_capture_source,
+ .dig_out_nid = ALC882_DIGOUT_NID,
+ .dig_in_nid = ALC882_DIGIN_NID,
+ .unsol_event = alc885_mbp3_unsol_event,
+ .init_hook = alc885_mbp3_automute,
+ },
[ALC885_MACPRO] = {
.mixers = { alc882_macpro_mixer },
.init_verbs = { alc882_macpro_init_verbs },
@@ -5465,6 +5825,7 @@ static struct alc_config_preset alc882_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
.channel_mode = alc882_ch_modes,
.input_mux = &alc882_capture_source,
+ .init_hook = alc885_macpro_init_hook,
},
[ALC885_IMAC24] = {
.mixers = { alc885_imac24_mixer },
@@ -5477,7 +5838,7 @@ static struct alc_config_preset alc882_presets[] = {
.channel_mode = alc882_ch_modes,
.input_mux = &alc882_capture_source,
.unsol_event = alc885_imac24_unsol_event,
- .init_hook = alc885_imac24_automute,
+ .init_hook = alc885_imac24_init_hook,
},
[ALC882_TARGA] = {
.mixers = { alc882_targa_mixer, alc882_chmode_mixer,
@@ -5509,6 +5870,19 @@ static struct alc_config_preset alc882_presets[] = {
.need_dac_fix = 1,
.input_mux = &alc882_capture_source,
},
+ [ALC882_ASUS_A7M] = {
+ .mixers = { alc882_asus_a7m_mixer, alc882_chmode_mixer },
+ .init_verbs = { alc882_init_verbs, alc882_eapd_verbs,
+ alc880_gpio1_init_verbs,
+ alc882_asus_a7m_verbs },
+ .num_dacs = ARRAY_SIZE(alc882_dac_nids),
+ .dac_nids = alc882_dac_nids,
+ .dig_out_nid = ALC882_DIGOUT_NID,
+ .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
+ .channel_mode = alc880_threestack_modes,
+ .need_dac_fix = 1,
+ .input_mux = &alc882_capture_source,
+ },
};
@@ -5608,6 +5982,32 @@ static void alc882_auto_init_analog_input(struct hda_codec *codec)
}
}
+/* add mic boosts if needed */
+static int alc_auto_add_mic_boost(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ int err;
+ hda_nid_t nid;
+
+ nid = spec->autocfg.input_pins[AUTO_PIN_MIC];
+ if (nid) {
+ err = add_control(spec, ALC_CTL_WIDGET_VOL,
+ "Mic Boost",
+ HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
+ if (err < 0)
+ return err;
+ }
+ nid = spec->autocfg.input_pins[AUTO_PIN_FRONT_MIC];
+ if (nid) {
+ err = add_control(spec, ALC_CTL_WIDGET_VOL,
+ "Front Mic Boost",
+ HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
+ if (err < 0)
+ return err;
+ }
+ return 0;
+}
+
/* almost identical with ALC880 parser... */
static int alc882_parse_auto_config(struct hda_codec *codec)
{
@@ -5616,10 +6016,17 @@ static int alc882_parse_auto_config(struct hda_codec *codec)
if (err < 0)
return err;
- else if (err > 0)
- /* hack - override the init verbs */
- spec->init_verbs[0] = alc882_auto_init_verbs;
- return err;
+ else if (!err)
+ return 0; /* no config found */
+
+ err = alc_auto_add_mic_boost(codec);
+ if (err < 0)
+ return err;
+
+ /* hack - override the init verbs */
+ spec->init_verbs[0] = alc882_auto_init_verbs;
+
+ return 1; /* config found */
}
/* additional initialization for auto-configuration model */
@@ -5654,6 +6061,9 @@ static int patch_alc882(struct hda_codec *codec)
case 0x106b1000: /* iMac 24 */
board_config = ALC885_IMAC24;
break;
+ case 0x106b2c00: /* Macbook Pro rev3 */
+ board_config = ALC885_MBP3;
+ break;
default:
printk(KERN_INFO "hda_codec: Unknown model for ALC882, "
"trying auto-probe from BIOS...\n");
@@ -5680,11 +6090,6 @@ static int patch_alc882(struct hda_codec *codec)
if (board_config != ALC882_AUTO)
setup_preset(spec, &alc882_presets[board_config]);
- if (board_config == ALC885_MACPRO || board_config == ALC885_IMAC24) {
- alc882_gpio_mute(codec, 0, 0);
- alc882_gpio_mute(codec, 1, 0);
- }
-
spec->stream_name_analog = "ALC882 Analog";
spec->stream_analog_playback = &alc882_pcm_analog_playback;
spec->stream_analog_capture = &alc882_pcm_analog_capture;
@@ -5715,6 +6120,10 @@ static int patch_alc882(struct hda_codec *codec)
codec->patch_ops = alc_patch_ops;
if (board_config == ALC882_AUTO)
spec->init_hook = alc882_auto_init;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ if (!spec->loopback.amplist)
+ spec->loopback.amplist = alc882_loopbacks;
+#endif
return 0;
}
@@ -5792,12 +6201,13 @@ static int alc883_mux_enum_put(struct snd_kcontrol *kcontrol,
idx = ucontrol->value.enumerated.item[0];
if (idx >= imux->num_items)
idx = imux->num_items - 1;
- if (*cur_val == idx && !codec->in_resume)
+ if (*cur_val == idx)
return 0;
for (i = 0; i < imux->num_items; i++) {
- unsigned int v = (i == idx) ? 0x7000 : 0x7080;
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
- v | (imux->items[i].index << 8));
+ unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
+ snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
+ imux->items[i].index,
+ HDA_AMP_MUTE, v);
}
*cur_val = idx;
return 1;
@@ -5822,6 +6232,18 @@ static struct hda_verb alc883_3ST_ch2_init[] = {
};
/*
+ * 4ch mode
+ */
+static struct hda_verb alc883_3ST_ch4_init[] = {
+ { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+ { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+ { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+ { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+ { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
+ { } /* end */
+};
+
+/*
* 6ch mode
*/
static struct hda_verb alc883_3ST_ch6_init[] = {
@@ -5834,8 +6256,9 @@ static struct hda_verb alc883_3ST_ch6_init[] = {
{ } /* end */
};
-static struct hda_channel_mode alc883_3ST_6ch_modes[2] = {
+static struct hda_channel_mode alc883_3ST_6ch_modes[3] = {
{ 2, alc883_3ST_ch2_init },
+ { 4, alc883_3ST_ch4_init },
{ 6, alc883_3ST_ch6_init },
};
@@ -6235,6 +6658,31 @@ static struct snd_kcontrol_new alc888_3st_hp_mixer[] = {
{ } /* end */
};
+static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+ HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+ HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+ HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 2,
+ .info = alc883_mux_enum_info,
+ .get = alc883_mux_enum_get,
+ .put = alc883_mux_enum_put,
+ },
+ { } /* end */
+};
+
static struct snd_kcontrol_new alc883_chmode_mixer[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -6270,11 +6718,12 @@ static struct hda_verb alc883_init_verbs[] = {
{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+ /* mute analog input loopbacks */
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
/* Front Pin: output 0 (0x0c) */
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
@@ -6366,6 +6815,19 @@ static struct hda_verb alc888_lenovo_ms7195_verbs[] = {
{ } /* end */
};
+static struct hda_verb alc883_haier_w66_verbs[] = {
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+
+ {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
+ {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ { } /* end */
+};
+
static struct hda_verb alc888_6st_hp_verbs[] = {
{0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front: output 0 (0x0c) */
{0x15, AC_VERB_SET_CONNECT_SEL, 0x02}, /* Rear : output 2 (0x0e) */
@@ -6409,15 +6871,10 @@ static void alc888_lenovo_ms7195_front_automute(struct hda_codec *codec)
present = snd_hda_codec_read(codec, 0x1b, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
- snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
- snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
- snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
-
+ snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+ snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
}
/* toggle RCA according to the front-jack state */
@@ -6427,12 +6884,10 @@ static void alc888_lenovo_ms7195_rca_automute(struct hda_codec *codec)
present = snd_hda_codec_read(codec, 0x14, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
- snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
-
+ snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
}
+
static void alc883_lenovo_ms7195_unsol_event(struct hda_codec *codec,
unsigned int res)
{
@@ -6459,10 +6914,8 @@ static void alc883_medion_md2_automute(struct hda_codec *codec)
present = snd_hda_codec_read(codec, 0x14, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
- snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
+ snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
}
static void alc883_medion_md2_unsol_event(struct hda_codec *codec,
@@ -6480,13 +6933,11 @@ static void alc883_tagra_automute(struct hda_codec *codec)
present = snd_hda_codec_read(codec, 0x14, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = present ? 0x80 : 0;
- snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0,
- 0x80, bits);
- snd_hda_codec_write(codec, 1, 0, AC_VERB_SET_GPIO_DATA,
- present ? 1 : 3);
+ bits = present ? HDA_AMP_MUTE : 0;
+ snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
+ snd_hda_codec_write_cache(codec, 1, 0, AC_VERB_SET_GPIO_DATA,
+ present ? 1 : 3);
}
static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res)
@@ -6495,6 +6946,25 @@ static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res)
alc883_tagra_automute(codec);
}
+static void alc883_haier_w66_automute(struct hda_codec *codec)
+{
+ unsigned int present;
+ unsigned char bits;
+
+ present = snd_hda_codec_read(codec, 0x1b, 0,
+ AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+ bits = present ? 0x80 : 0;
+ snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+ 0x80, bits);
+}
+
+static void alc883_haier_w66_unsol_event(struct hda_codec *codec,
+ unsigned int res)
+{
+ if ((res >> 26) == ALC880_HP_EVENT)
+ alc883_haier_w66_automute(codec);
+}
+
static void alc883_lenovo_101e_ispeaker_automute(struct hda_codec *codec)
{
unsigned int present;
@@ -6502,11 +6972,9 @@ static void alc883_lenovo_101e_ispeaker_automute(struct hda_codec *codec)
present = snd_hda_codec_read(codec, 0x14, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = present ? 0x80 : 0;
- snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
- 0x80, bits);
+ bits = present ? HDA_AMP_MUTE : 0;
+ snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
}
static void alc883_lenovo_101e_all_automute(struct hda_codec *codec)
@@ -6516,15 +6984,11 @@ static void alc883_lenovo_101e_all_automute(struct hda_codec *codec)
present = snd_hda_codec_read(codec, 0x1b, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = present ? 0x80 : 0;
- snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
- 0x80, bits);
+ bits = present ? HDA_AMP_MUTE : 0;
+ snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
+ snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
}
static void alc883_lenovo_101e_unsol_event(struct hda_codec *codec,
@@ -6536,6 +7000,44 @@ static void alc883_lenovo_101e_unsol_event(struct hda_codec *codec,
alc883_lenovo_101e_ispeaker_automute(codec);
}
+/* toggle speaker-output according to the hp-jack state */
+static void alc883_acer_aspire_automute(struct hda_codec *codec)
+{
+ unsigned int present;
+
+ present = snd_hda_codec_read(codec, 0x14, 0,
+ AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+ snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+ snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+}
+
+static void alc883_acer_aspire_unsol_event(struct hda_codec *codec,
+ unsigned int res)
+{
+ if ((res >> 26) == ALC880_HP_EVENT)
+ alc883_acer_aspire_automute(codec);
+}
+
+static struct hda_verb alc883_acer_eapd_verbs[] = {
+ /* HP Pin: output 0 (0x0c) */
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
+ /* Front Pin: output 0 (0x0c) */
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
+ /* eanable EAPD on medion laptop */
+ {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
+ {0x20, AC_VERB_SET_PROC_COEF, 0x3050},
+ /* enable unsolicited event */
+ {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
+ { }
+};
+
/*
* generic initialization of ADC, input mixers and output mixers
*/
@@ -6548,17 +7050,17 @@ static struct hda_verb alc883_auto_init_verbs[] = {
{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
+ /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
* mixer widget
* Note: PASD motherboards uses the Line In 2 as the input for
* front panel mic (mic 2)
*/
/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
/*
* Set up output mixers (0x0c - 0x0f)
@@ -6621,6 +7123,10 @@ static struct snd_kcontrol_new alc883_capture_mixer[] = {
{ } /* end */
};
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+#define alc883_loopbacks alc880_loopbacks
+#endif
+
/* pcm configuration: identiacal with ALC880 */
#define alc883_pcm_analog_playback alc880_pcm_analog_playback
#define alc883_pcm_analog_capture alc880_pcm_analog_capture
@@ -6638,12 +7144,14 @@ static const char *alc883_models[ALC883_MODEL_LAST] = {
[ALC883_TARGA_DIG] = "targa-dig",
[ALC883_TARGA_2ch_DIG] = "targa-2ch-dig",
[ALC883_ACER] = "acer",
+ [ALC883_ACER_ASPIRE] = "acer-aspire",
[ALC883_MEDION] = "medion",
[ALC883_MEDION_MD2] = "medion-md2",
[ALC883_LAPTOP_EAPD] = "laptop-eapd",
[ALC883_LENOVO_101E_2ch] = "lenovo-101e",
[ALC883_LENOVO_NB0763] = "lenovo-nb0763",
[ALC888_LENOVO_MS7195_DIG] = "lenovo-ms7195-dig",
+ [ALC883_HAIER_W66] = "haier-w66",
[ALC888_6ST_HP] = "6stack-hp",
[ALC888_3ST_HP] = "3stack-hp",
[ALC883_AUTO] = "auto",
@@ -6669,10 +7177,14 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
SND_PCI_QUIRK(0x1462, 0x3fcc, "MSI", ALC883_TARGA_DIG),
SND_PCI_QUIRK(0x1462, 0x3fc1, "MSI", ALC883_TARGA_DIG),
SND_PCI_QUIRK(0x1462, 0x3fc3, "MSI", ALC883_TARGA_DIG),
+ SND_PCI_QUIRK(0x1462, 0x3fdf, "MSI", ALC883_TARGA_DIG),
SND_PCI_QUIRK(0x1462, 0x4314, "MSI", ALC883_TARGA_DIG),
SND_PCI_QUIRK(0x1462, 0x4319, "MSI", ALC883_TARGA_DIG),
SND_PCI_QUIRK(0x1462, 0x4324, "MSI", ALC883_TARGA_DIG),
SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG),
+ SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_ACER_ASPIRE),
+ SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_ACER_ASPIRE),
+ SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_ACER_ASPIRE),
SND_PCI_QUIRK(0x1025, 0, "Acer laptop", ALC883_ACER),
SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch),
SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION),
@@ -6685,6 +7197,10 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP),
SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP),
SND_PCI_QUIRK(0x17c0, 0x4071, "MEDION MD2", ALC883_MEDION_MD2),
+ SND_PCI_QUIRK(0x1991, 0x5625, "Haier W66", ALC883_HAIER_W66),
+ SND_PCI_QUIRK(0x17aa, 0x3bfc, "Lenovo NB0763", ALC883_LENOVO_NB0763),
+ SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG),
+ SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG),
{}
};
@@ -6771,8 +7287,7 @@ static struct alc_config_preset alc883_presets[] = {
.init_hook = alc883_tagra_automute,
},
[ALC883_ACER] = {
- .mixers = { alc883_base_mixer,
- alc883_chmode_mixer },
+ .mixers = { alc883_base_mixer },
/* On TravelMate laptops, GPIO 0 enables the internal speaker
* and the headphone jack. Turn this on and rely on the
* standard mute methods whenever the user wants to turn
@@ -6787,6 +7302,20 @@ static struct alc_config_preset alc883_presets[] = {
.channel_mode = alc883_3ST_2ch_modes,
.input_mux = &alc883_capture_source,
},
+ [ALC883_ACER_ASPIRE] = {
+ .mixers = { alc883_acer_aspire_mixer },
+ .init_verbs = { alc883_init_verbs, alc883_acer_eapd_verbs },
+ .num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ .dac_nids = alc883_dac_nids,
+ .dig_out_nid = ALC883_DIGOUT_NID,
+ .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+ .adc_nids = alc883_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+ .channel_mode = alc883_3ST_2ch_modes,
+ .input_mux = &alc883_capture_source,
+ .unsol_event = alc883_acer_aspire_unsol_event,
+ .init_hook = alc883_acer_aspire_automute,
+ },
[ALC883_MEDION] = {
.mixers = { alc883_fivestack_mixer,
alc883_chmode_mixer },
@@ -6815,8 +7344,7 @@ static struct alc_config_preset alc883_presets[] = {
.init_hook = alc883_medion_md2_automute,
},
[ALC883_LAPTOP_EAPD] = {
- .mixers = { alc883_base_mixer,
- alc883_chmode_mixer },
+ .mixers = { alc883_base_mixer },
.init_verbs = { alc883_init_verbs, alc882_eapd_verbs },
.num_dacs = ARRAY_SIZE(alc883_dac_nids),
.dac_nids = alc883_dac_nids,
@@ -6867,6 +7395,20 @@ static struct alc_config_preset alc883_presets[] = {
.input_mux = &alc883_capture_source,
.unsol_event = alc883_lenovo_ms7195_unsol_event,
.init_hook = alc888_lenovo_ms7195_front_automute,
+ },
+ [ALC883_HAIER_W66] = {
+ .mixers = { alc883_tagra_2ch_mixer},
+ .init_verbs = { alc883_init_verbs, alc883_haier_w66_verbs},
+ .num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ .dac_nids = alc883_dac_nids,
+ .dig_out_nid = ALC883_DIGOUT_NID,
+ .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+ .adc_nids = alc883_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+ .channel_mode = alc883_3ST_2ch_modes,
+ .input_mux = &alc883_capture_source,
+ .unsol_event = alc883_haier_w66_unsol_event,
+ .init_hook = alc883_haier_w66_automute,
},
[ALC888_6ST_HP] = {
.mixers = { alc888_6st_hp_mixer, alc883_chmode_mixer },
@@ -6977,12 +7519,19 @@ static int alc883_parse_auto_config(struct hda_codec *codec)
if (err < 0)
return err;
- else if (err > 0)
- /* hack - override the init verbs */
- spec->init_verbs[0] = alc883_auto_init_verbs;
+ else if (!err)
+ return 0; /* no config found */
+
+ err = alc_auto_add_mic_boost(codec);
+ if (err < 0)
+ return err;
+
+ /* hack - override the init verbs */
+ spec->init_verbs[0] = alc883_auto_init_verbs;
spec->mixers[spec->num_mixers] = alc883_capture_mixer;
spec->num_mixers++;
- return err;
+
+ return 1; /* config found */
}
/* additional initialization for auto-configuration model */
@@ -7046,6 +7595,10 @@ static int patch_alc883(struct hda_codec *codec)
codec->patch_ops = alc_patch_ops;
if (board_config == ALC883_AUTO)
spec->init_hook = alc883_auto_init;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ if (!spec->loopback.amplist)
+ spec->loopback.amplist = alc883_loopbacks;
+#endif
return 0;
}
@@ -7156,9 +7709,46 @@ static struct snd_kcontrol_new alc262_HP_BPC_WildWest_option_mixer[] = {
{ } /* end */
};
+/* bind hp and internal speaker mute (with plug check) */
+static int alc262_sony_master_sw_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ long *valp = ucontrol->value.integer.value;
+ int change;
+
+ /* change hp mute */
+ change = snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE,
+ valp[0] ? 0 : HDA_AMP_MUTE);
+ change |= snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE,
+ valp[1] ? 0 : HDA_AMP_MUTE);
+ if (change) {
+ /* change speaker according to HP jack state */
+ struct alc_spec *spec = codec->spec;
+ unsigned int mute;
+ if (spec->jack_present)
+ mute = HDA_AMP_MUTE;
+ else
+ mute = snd_hda_codec_amp_read(codec, 0x15, 0,
+ HDA_OUTPUT, 0);
+ snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, mute);
+ }
+ return change;
+}
+
static struct snd_kcontrol_new alc262_sony_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Master Playback Switch",
+ .info = snd_hda_mixer_amp_switch_info,
+ .get = snd_hda_mixer_amp_switch_get,
+ .put = alc262_sony_master_sw_put,
+ .private_value = HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
+ },
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
@@ -7194,17 +7784,17 @@ static struct hda_verb alc262_init_verbs[] = {
{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
+ /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
* mixer widget
* Note: PASD motherboards uses the Line In 2 as the input for
* front panel mic (mic 2)
*/
/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
/*
* Set up output mixers (0x0c - 0x0e)
@@ -7285,34 +7875,26 @@ static struct hda_verb alc262_sony_unsol_verbs[] = {
};
/* mute/unmute internal speaker according to the hp jack and mute state */
-static void alc262_hippo_automute(struct hda_codec *codec, int force)
+static void alc262_hippo_automute(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
unsigned int mute;
+ unsigned int present;
- if (force || !spec->sense_updated) {
- unsigned int present;
- /* need to execute and sync at first */
- snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0);
- present = snd_hda_codec_read(codec, 0x15, 0,
- AC_VERB_GET_PIN_SENSE, 0);
- spec->jack_present = (present & 0x80000000) != 0;
- spec->sense_updated = 1;
- }
+ /* need to execute and sync at first */
+ snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0);
+ present = snd_hda_codec_read(codec, 0x15, 0,
+ AC_VERB_GET_PIN_SENSE, 0);
+ spec->jack_present = (present & 0x80000000) != 0;
if (spec->jack_present) {
/* mute internal speaker */
- snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
- 0x80, 0x80);
- snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
- 0x80, 0x80);
+ snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, HDA_AMP_MUTE);
} else {
/* unmute internal speaker if necessary */
mute = snd_hda_codec_amp_read(codec, 0x15, 0, HDA_OUTPUT, 0);
- snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
- 0x80, mute & 0x80);
- mute = snd_hda_codec_amp_read(codec, 0x15, 1, HDA_OUTPUT, 0);
- snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
- 0x80, mute & 0x80);
+ snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, mute);
}
}
@@ -7322,37 +7904,27 @@ static void alc262_hippo_unsol_event(struct hda_codec *codec,
{
if ((res >> 26) != ALC880_HP_EVENT)
return;
- alc262_hippo_automute(codec, 1);
+ alc262_hippo_automute(codec);
}
-static void alc262_hippo1_automute(struct hda_codec *codec, int force)
+static void alc262_hippo1_automute(struct hda_codec *codec)
{
- struct alc_spec *spec = codec->spec;
unsigned int mute;
+ unsigned int present;
- if (force || !spec->sense_updated) {
- unsigned int present;
- /* need to execute and sync at first */
- snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0);
- present = snd_hda_codec_read(codec, 0x1b, 0,
- AC_VERB_GET_PIN_SENSE, 0);
- spec->jack_present = (present & 0x80000000) != 0;
- spec->sense_updated = 1;
- }
- if (spec->jack_present) {
+ snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0);
+ present = snd_hda_codec_read(codec, 0x1b, 0,
+ AC_VERB_GET_PIN_SENSE, 0);
+ present = (present & 0x80000000) != 0;
+ if (present) {
/* mute internal speaker */
- snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
- 0x80, 0x80);
- snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
- 0x80, 0x80);
+ snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, HDA_AMP_MUTE);
} else {
/* unmute internal speaker if necessary */
mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0);
- snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
- 0x80, mute & 0x80);
- mute = snd_hda_codec_amp_read(codec, 0x1b, 1, HDA_OUTPUT, 0);
- snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
- 0x80, mute & 0x80);
+ snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, mute);
}
}
@@ -7362,7 +7934,7 @@ static void alc262_hippo1_unsol_event(struct hda_codec *codec,
{
if ((res >> 26) != ALC880_HP_EVENT)
return;
- alc262_hippo1_automute(codec, 1);
+ alc262_hippo1_automute(codec);
}
/*
@@ -7379,9 +7951,10 @@ static struct hda_verb alc262_fujitsu_unsol_verbs[] = {
};
static struct hda_input_mux alc262_fujitsu_capture_source = {
- .num_items = 2,
+ .num_items = 3,
.items = {
{ "Mic", 0x0 },
+ { "Int Mic", 0x1 },
{ "CD", 0x4 },
},
};
@@ -7390,13 +7963,23 @@ static struct hda_input_mux alc262_HP_capture_source = {
.num_items = 5,
.items = {
{ "Mic", 0x0 },
- { "Front Mic", 0x3 },
+ { "Front Mic", 0x1 },
{ "Line", 0x2 },
{ "CD", 0x4 },
{ "AUX IN", 0x6 },
},
};
+static struct hda_input_mux alc262_HP_D7000_capture_source = {
+ .num_items = 4,
+ .items = {
+ { "Mic", 0x0 },
+ { "Front Mic", 0x2 },
+ { "Line", 0x1 },
+ { "CD", 0x4 },
+ },
+};
+
/* mute/unmute internal speaker according to the hp jack and mute state */
static void alc262_fujitsu_automute(struct hda_codec *codec, int force)
{
@@ -7414,18 +7997,13 @@ static void alc262_fujitsu_automute(struct hda_codec *codec, int force)
}
if (spec->jack_present) {
/* mute internal speaker */
- snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
- 0x80, 0x80);
- snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
- 0x80, 0x80);
+ snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, HDA_AMP_MUTE);
} else {
/* unmute internal speaker if necessary */
mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0);
- snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
- 0x80, mute & 0x80);
- mute = snd_hda_codec_amp_read(codec, 0x14, 1, HDA_OUTPUT, 0);
- snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
- 0x80, mute & 0x80);
+ snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, mute);
}
}
@@ -7439,23 +8017,14 @@ static void alc262_fujitsu_unsol_event(struct hda_codec *codec,
}
/* bind volumes of both NID 0x0c and 0x0d */
-static int alc262_fujitsu_master_vol_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- long *valp = ucontrol->value.integer.value;
- int change;
-
- change = snd_hda_codec_amp_update(codec, 0x0c, 0, HDA_OUTPUT, 0,
- 0x7f, valp[0] & 0x7f);
- change |= snd_hda_codec_amp_update(codec, 0x0c, 1, HDA_OUTPUT, 0,
- 0x7f, valp[1] & 0x7f);
- snd_hda_codec_amp_update(codec, 0x0d, 0, HDA_OUTPUT, 0,
- 0x7f, valp[0] & 0x7f);
- snd_hda_codec_amp_update(codec, 0x0d, 1, HDA_OUTPUT, 0,
- 0x7f, valp[1] & 0x7f);
- return change;
-}
+static struct hda_bind_ctls alc262_fujitsu_bind_master_vol = {
+ .ops = &snd_hda_bind_vol,
+ .values = {
+ HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT),
+ HDA_COMPOSE_AMP_VAL(0x0d, 3, 0, HDA_OUTPUT),
+ 0
+ },
+};
/* bind hp and internal speaker mute (with plug check) */
static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol,
@@ -7466,24 +8035,18 @@ static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol,
int change;
change = snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
- 0x80, valp[0] ? 0 : 0x80);
+ HDA_AMP_MUTE,
+ valp[0] ? 0 : HDA_AMP_MUTE);
change |= snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
- 0x80, valp[1] ? 0 : 0x80);
- if (change || codec->in_resume)
- alc262_fujitsu_automute(codec, codec->in_resume);
+ HDA_AMP_MUTE,
+ valp[1] ? 0 : HDA_AMP_MUTE);
+ if (change)
+ alc262_fujitsu_automute(codec, 0);
return change;
}
static struct snd_kcontrol_new alc262_fujitsu_mixer[] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Master Playback Volume",
- .info = snd_hda_mixer_amp_volume_info,
- .get = snd_hda_mixer_amp_volume_get,
- .put = alc262_fujitsu_master_vol_put,
- .tlv = { .c = snd_hda_mixer_amp_tlv },
- .private_value = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT),
- },
+ HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Switch",
@@ -7497,6 +8060,9 @@ static struct snd_kcontrol_new alc262_fujitsu_mixer[] = {
HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+ HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
{ } /* end */
};
@@ -7611,17 +8177,17 @@ static struct hda_verb alc262_volume_init_verbs[] = {
{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
+ /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
* mixer widget
* Note: PASD motherboards uses the Line In 2 as the input for
* front panel mic (mic 2)
*/
/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
/*
* Set up output mixers (0x0c - 0x0f)
@@ -7672,19 +8238,19 @@ static struct hda_verb alc262_HP_BPC_init_verbs[] = {
{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
+ /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
* mixer widget
* Note: PASD motherboards uses the Line In 2 as the input for
* front panel mic (mic 2)
*/
/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
/*
* Set up output mixers (0x0c - 0x0e)
@@ -7759,20 +8325,20 @@ static struct hda_verb alc262_HP_BPC_WildWest_init_verbs[] = {
{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
+ /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
* mixer widget
* Note: PASD motherboards uses the Line In 2 as the input for front
* panel mic (mic 2)
*/
/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
/*
* Set up output mixers (0x0c - 0x0e)
*/
@@ -7842,6 +8408,10 @@ static struct hda_verb alc262_HP_BPC_WildWest_init_verbs[] = {
{ }
};
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+#define alc262_loopbacks alc880_loopbacks
+#endif
+
/* pcm configuration: identiacal with ALC880 */
#define alc262_pcm_analog_playback alc880_pcm_analog_playback
#define alc262_pcm_analog_capture alc880_pcm_analog_capture
@@ -7884,6 +8454,10 @@ static int alc262_parse_auto_config(struct hda_codec *codec)
spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux;
+ err = alc_auto_add_mic_boost(codec);
+ if (err < 0)
+ return err;
+
return 1;
}
@@ -7939,6 +8513,7 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = {
SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1),
SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8),
SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_BENQ_T31),
+ SND_PCI_QUIRK(0x104d, 0x820f, "Sony ASSAMD", ALC262_SONY_ASSAMD),
SND_PCI_QUIRK(0x104d, 0x9015, "Sony 0x9015", ALC262_SONY_ASSAMD),
SND_PCI_QUIRK(0x104d, 0x900e, "Sony ASSAMD", ALC262_SONY_ASSAMD),
SND_PCI_QUIRK(0x104d, 0x1f00, "Sony ASSAMD", ALC262_SONY_ASSAMD),
@@ -7967,6 +8542,7 @@ static struct alc_config_preset alc262_presets[] = {
.channel_mode = alc262_modes,
.input_mux = &alc262_capture_source,
.unsol_event = alc262_hippo_unsol_event,
+ .init_hook = alc262_hippo_automute,
},
[ALC262_HIPPO_1] = {
.mixers = { alc262_hippo1_mixer },
@@ -7979,10 +8555,12 @@ static struct alc_config_preset alc262_presets[] = {
.channel_mode = alc262_modes,
.input_mux = &alc262_capture_source,
.unsol_event = alc262_hippo1_unsol_event,
+ .init_hook = alc262_hippo1_automute,
},
[ALC262_FUJITSU] = {
.mixers = { alc262_fujitsu_mixer },
- .init_verbs = { alc262_init_verbs, alc262_fujitsu_unsol_verbs },
+ .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs,
+ alc262_fujitsu_unsol_verbs },
.num_dacs = ARRAY_SIZE(alc262_dac_nids),
.dac_nids = alc262_dac_nids,
.hp_nid = 0x03,
@@ -8010,7 +8588,7 @@ static struct alc_config_preset alc262_presets[] = {
.hp_nid = 0x03,
.num_channel_mode = ARRAY_SIZE(alc262_modes),
.channel_mode = alc262_modes,
- .input_mux = &alc262_HP_capture_source,
+ .input_mux = &alc262_HP_D7000_capture_source,
},
[ALC262_HP_BPC_D7000_WL] = {
.mixers = { alc262_HP_BPC_WildWest_mixer,
@@ -8021,7 +8599,7 @@ static struct alc_config_preset alc262_presets[] = {
.hp_nid = 0x03,
.num_channel_mode = ARRAY_SIZE(alc262_modes),
.channel_mode = alc262_modes,
- .input_mux = &alc262_HP_capture_source,
+ .input_mux = &alc262_HP_D7000_capture_source,
},
[ALC262_BENQ_ED8] = {
.mixers = { alc262_base_mixer },
@@ -8043,6 +8621,7 @@ static struct alc_config_preset alc262_presets[] = {
.channel_mode = alc262_modes,
.input_mux = &alc262_capture_source,
.unsol_event = alc262_hippo_unsol_event,
+ .init_hook = alc262_hippo_automute,
},
[ALC262_BENQ_T31] = {
.mixers = { alc262_benq_t31_mixer },
@@ -8054,6 +8633,7 @@ static struct alc_config_preset alc262_presets[] = {
.channel_mode = alc262_modes,
.input_mux = &alc262_capture_source,
.unsol_event = alc262_hippo_unsol_event,
+ .init_hook = alc262_hippo_automute,
},
};
@@ -8139,6 +8719,10 @@ static int patch_alc262(struct hda_codec *codec)
codec->patch_ops = alc_patch_ops;
if (board_config == ALC262_AUTO)
spec->init_hook = alc262_auto_init;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ if (!spec->loopback.amplist)
+ spec->loopback.amplist = alc262_loopbacks;
+#endif
return 0;
}
@@ -8170,9 +8754,125 @@ static struct snd_kcontrol_new alc268_base_mixer[] = {
HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0, HDA_INPUT),
+ { }
+};
+
+static struct hda_verb alc268_eapd_verbs[] = {
+ {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
+ {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
+ { }
+};
+
+/* Toshiba specific */
+#define alc268_toshiba_automute alc262_hippo_automute
+
+static struct hda_verb alc268_toshiba_verbs[] = {
+ {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
+ { } /* end */
+};
+
+/* Acer specific */
+/* bind volumes of both NID 0x02 and 0x03 */
+static struct hda_bind_ctls alc268_acer_bind_master_vol = {
+ .ops = &snd_hda_bind_vol,
+ .values = {
+ HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
+ HDA_COMPOSE_AMP_VAL(0x03, 3, 0, HDA_OUTPUT),
+ 0
+ },
+};
+
+/* mute/unmute internal speaker according to the hp jack and mute state */
+static void alc268_acer_automute(struct hda_codec *codec, int force)
+{
+ struct alc_spec *spec = codec->spec;
+ unsigned int mute;
+
+ if (force || !spec->sense_updated) {
+ unsigned int present;
+ present = snd_hda_codec_read(codec, 0x14, 0,
+ AC_VERB_GET_PIN_SENSE, 0);
+ spec->jack_present = (present & 0x80000000) != 0;
+ spec->sense_updated = 1;
+ }
+ if (spec->jack_present)
+ mute = HDA_AMP_MUTE; /* mute internal speaker */
+ else /* unmute internal speaker if necessary */
+ mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0);
+ snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, mute);
+}
+
+
+/* bind hp and internal speaker mute (with plug check) */
+static int alc268_acer_master_sw_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ long *valp = ucontrol->value.integer.value;
+ int change;
+
+ change = snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE,
+ valp[0] ? 0 : HDA_AMP_MUTE);
+ change |= snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE,
+ valp[1] ? 0 : HDA_AMP_MUTE);
+ if (change)
+ alc268_acer_automute(codec, 0);
+ return change;
+}
+
+static struct snd_kcontrol_new alc268_acer_mixer[] = {
+ /* output mixer control */
+ HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Master Playback Switch",
+ .info = snd_hda_mixer_amp_switch_info,
+ .get = snd_hda_mixer_amp_switch_get,
+ .put = alc268_acer_master_sw_put,
+ .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
+ },
+ HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0, HDA_INPUT),
{ }
};
+static struct hda_verb alc268_acer_verbs[] = {
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+
+ {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
+ { }
+};
+
+/* unsolicited event for HP jack sensing */
+static void alc268_toshiba_unsol_event(struct hda_codec *codec,
+ unsigned int res)
+{
+ if ((res >> 26) != ALC880_HP_EVENT)
+ return;
+ alc268_toshiba_automute(codec);
+}
+
+static void alc268_acer_unsol_event(struct hda_codec *codec,
+ unsigned int res)
+{
+ if ((res >> 26) != ALC880_HP_EVENT)
+ return;
+ alc268_acer_automute(codec, 1);
+}
+
+static void alc268_acer_init_hook(struct hda_codec *codec)
+{
+ alc268_acer_automute(codec, 1);
+}
+
/*
* generic initialization of ADC, input mixers and output mixers
*/
@@ -8282,14 +8982,16 @@ static int alc268_mux_enum_put(struct snd_kcontrol *kcontrol,
idx = ucontrol->value.enumerated.item[0];
if (idx >= imux->num_items)
idx = imux->num_items - 1;
- if (*cur_val == idx && !codec->in_resume)
+ if (*cur_val == idx)
return 0;
for (i = 0; i < imux->num_items; i++) {
- unsigned int v = (i == idx) ? 0x7000 : 0x7080;
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
- v | (imux->items[i].index << 8));
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
- idx );
+ unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
+ snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
+ imux->items[i].index,
+ HDA_AMP_MUTE, v);
+ snd_hda_codec_write_cache(codec, nid, 0,
+ AC_VERB_SET_CONNECT_SEL,
+ idx );
}
*cur_val = idx;
return 1;
@@ -8530,6 +9232,10 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux;
+ err = alc_auto_add_mic_boost(codec);
+ if (err < 0)
+ return err;
+
return 1;
}
@@ -8551,11 +9257,19 @@ static void alc268_auto_init(struct hda_codec *codec)
*/
static const char *alc268_models[ALC268_MODEL_LAST] = {
[ALC268_3ST] = "3stack",
+ [ALC268_TOSHIBA] = "toshiba",
+ [ALC268_ACER] = "acer",
[ALC268_AUTO] = "auto",
};
static struct snd_pci_quirk alc268_cfg_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC268_3ST),
+ SND_PCI_QUIRK(0x1179, 0xff10, "TOSHIBA A205", ALC268_TOSHIBA),
+ SND_PCI_QUIRK(0x1179, 0xff50, "TOSHIBA A305", ALC268_TOSHIBA),
+ SND_PCI_QUIRK(0x103c, 0x30cc, "TOSHIBA", ALC268_TOSHIBA),
+ SND_PCI_QUIRK(0x1025, 0x0126, "Acer", ALC268_ACER),
+ SND_PCI_QUIRK(0x1025, 0x0130, "Acer Extensa 5210", ALC268_ACER),
+ SND_PCI_QUIRK(0x152d, 0x0763, "Diverse (CPR2000)", ALC268_ACER),
{}
};
@@ -8573,6 +9287,36 @@ static struct alc_config_preset alc268_presets[] = {
.channel_mode = alc268_modes,
.input_mux = &alc268_capture_source,
},
+ [ALC268_TOSHIBA] = {
+ .mixers = { alc268_base_mixer, alc268_capture_alt_mixer },
+ .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
+ alc268_toshiba_verbs },
+ .num_dacs = ARRAY_SIZE(alc268_dac_nids),
+ .dac_nids = alc268_dac_nids,
+ .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
+ .adc_nids = alc268_adc_nids_alt,
+ .hp_nid = 0x03,
+ .num_channel_mode = ARRAY_SIZE(alc268_modes),
+ .channel_mode = alc268_modes,
+ .input_mux = &alc268_capture_source,
+ .unsol_event = alc268_toshiba_unsol_event,
+ .init_hook = alc268_toshiba_automute,
+ },
+ [ALC268_ACER] = {
+ .mixers = { alc268_acer_mixer, alc268_capture_alt_mixer },
+ .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
+ alc268_acer_verbs },
+ .num_dacs = ARRAY_SIZE(alc268_dac_nids),
+ .dac_nids = alc268_dac_nids,
+ .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
+ .adc_nids = alc268_adc_nids_alt,
+ .hp_nid = 0x02,
+ .num_channel_mode = ARRAY_SIZE(alc268_modes),
+ .channel_mode = alc268_modes,
+ .input_mux = &alc268_capture_source,
+ .unsol_event = alc268_acer_unsol_event,
+ .init_hook = alc268_acer_init_hook,
+ },
};
static int patch_alc268(struct hda_codec *codec)
@@ -9279,14 +10023,10 @@ static void alc861_toshiba_automute(struct hda_codec *codec)
present = snd_hda_codec_read(codec, 0x0f, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- snd_hda_codec_amp_update(codec, 0x16, 0, HDA_INPUT, 0,
- 0x80, present ? 0x80 : 0);
- snd_hda_codec_amp_update(codec, 0x16, 1, HDA_INPUT, 0,
- 0x80, present ? 0x80 : 0);
- snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_INPUT, 3,
- 0x80, present ? 0 : 0x80);
- snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_INPUT, 3,
- 0x80, present ? 0 : 0x80);
+ snd_hda_codec_amp_stereo(codec, 0x16, HDA_INPUT, 0,
+ HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+ snd_hda_codec_amp_stereo(codec, 0x1a, HDA_INPUT, 3,
+ HDA_AMP_MUTE, present ? 0 : HDA_AMP_MUTE);
}
static void alc861_toshiba_unsol_event(struct hda_codec *codec,
@@ -9599,6 +10339,16 @@ static void alc861_auto_init(struct hda_codec *codec)
alc861_auto_init_analog_input(codec);
}
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static struct hda_amp_list alc861_loopbacks[] = {
+ { 0x15, HDA_INPUT, 0 },
+ { 0x15, HDA_INPUT, 1 },
+ { 0x15, HDA_INPUT, 2 },
+ { 0x15, HDA_INPUT, 3 },
+ { } /* end */
+};
+#endif
+
/*
* configuration and preset
@@ -9796,6 +10546,10 @@ static int patch_alc861(struct hda_codec *codec)
codec->patch_ops = alc_patch_ops;
if (board_config == ALC861_AUTO)
spec->init_hook = alc861_auto_init;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ if (!spec->loopback.amplist)
+ spec->loopback.amplist = alc861_loopbacks;
+#endif
return 0;
}
@@ -9852,6 +10606,14 @@ static struct hda_input_mux alc861vd_dallas_capture_source = {
},
};
+static struct hda_input_mux alc861vd_hp_capture_source = {
+ .num_items = 2,
+ .items = {
+ { "Front Mic", 0x0 },
+ { "ATAPI Mic", 0x1 },
+ },
+};
+
#define alc861vd_mux_enum_info alc_mux_enum_info
#define alc861vd_mux_enum_get alc_mux_enum_get
@@ -9870,12 +10632,13 @@ static int alc861vd_mux_enum_put(struct snd_kcontrol *kcontrol,
idx = ucontrol->value.enumerated.item[0];
if (idx >= imux->num_items)
idx = imux->num_items - 1;
- if (*cur_val == idx && !codec->in_resume)
+ if (*cur_val == idx)
return 0;
for (i = 0; i < imux->num_items; i++) {
- unsigned int v = (i == idx) ? 0x7000 : 0x7080;
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
- v | (imux->items[i].index << 8));
+ unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
+ snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
+ imux->items[i].index,
+ HDA_AMP_MUTE, v);
}
*cur_val = idx;
return 1;
@@ -10049,17 +10812,22 @@ static struct snd_kcontrol_new alc861vd_dallas_mixer[] = {
HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x05, HDA_INPUT),
HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x05, HDA_INPUT),
- HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- /* .name = "Capture Source", */
- .name = "Input Source",
- .count = 1,
- .info = alc882_mux_enum_info,
- .get = alc882_mux_enum_get,
- .put = alc882_mux_enum_put,
- },
+ { } /* end */
+};
+
+/* Pin assignment: Speaker=0x14, Line-out = 0x15,
+ * Front Mic=0x18, ATAPI Mic = 0x19,
+ */
+static struct snd_kcontrol_new alc861vd_hp_mixer[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+ HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
+ HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+ HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+
{ } /* end */
};
@@ -10077,11 +10845,11 @@ static struct hda_verb alc861vd_volume_init_verbs[] = {
* the analog-loopback mixer widget
*/
/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
/* Capture mixer: unmute Mic, F-Mic, Line, CD inputs */
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
@@ -10210,11 +10978,9 @@ static void alc861vd_lenovo_hp_automute(struct hda_codec *codec)
present = snd_hda_codec_read(codec, 0x1b, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = present ? 0x80 : 0;
- snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
- 0x80, bits);
+ bits = present ? HDA_AMP_MUTE : 0;
+ snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
}
static void alc861vd_lenovo_mic_automute(struct hda_codec *codec)
@@ -10224,11 +10990,9 @@ static void alc861vd_lenovo_mic_automute(struct hda_codec *codec)
present = snd_hda_codec_read(codec, 0x18, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = present ? 0x80 : 0;
- snd_hda_codec_amp_update(codec, 0x0b, 0, HDA_INPUT, 1,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x0b, 1, HDA_INPUT, 1,
- 0x80, bits);
+ bits = present ? HDA_AMP_MUTE : 0;
+ snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1,
+ HDA_AMP_MUTE, bits);
}
static void alc861vd_lenovo_automute(struct hda_codec *codec)
@@ -10302,10 +11066,8 @@ static void alc861vd_dallas_automute(struct hda_codec *codec)
present = snd_hda_codec_read(codec, 0x15, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
- snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
+ snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
}
static void alc861vd_dallas_unsol_event(struct hda_codec *codec, unsigned int res)
@@ -10314,6 +11076,10 @@ static void alc861vd_dallas_unsol_event(struct hda_codec *codec, unsigned int re
alc861vd_dallas_automute(codec);
}
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+#define alc861vd_loopbacks alc880_loopbacks
+#endif
+
/* pcm configuration: identiacal with ALC880 */
#define alc861vd_pcm_analog_playback alc880_pcm_analog_playback
#define alc861vd_pcm_analog_capture alc880_pcm_analog_capture
@@ -10325,12 +11091,13 @@ static void alc861vd_dallas_unsol_event(struct hda_codec *codec, unsigned int re
*/
static const char *alc861vd_models[ALC861VD_MODEL_LAST] = {
[ALC660VD_3ST] = "3stack-660",
- [ALC660VD_3ST_DIG]= "3stack-660-digout",
+ [ALC660VD_3ST_DIG] = "3stack-660-digout",
[ALC861VD_3ST] = "3stack",
[ALC861VD_3ST_DIG] = "3stack-digout",
[ALC861VD_6ST_DIG] = "6stack-digout",
[ALC861VD_LENOVO] = "lenovo",
[ALC861VD_DALLAS] = "dallas",
+ [ALC861VD_HP] = "hp",
[ALC861VD_AUTO] = "auto",
};
@@ -10341,11 +11108,15 @@ static struct snd_pci_quirk alc861vd_cfg_tbl[] = {
SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST),
SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST),
- SND_PCI_QUIRK(0x1179, 0xff00, "DALLAS", ALC861VD_DALLAS),
+ /*SND_PCI_QUIRK(0x1179, 0xff00, "DALLAS", ALC861VD_DALLAS),*/ /*lenovo*/
SND_PCI_QUIRK(0x1179, 0xff01, "DALLAS", ALC861VD_DALLAS),
SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_LENOVO),
SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo", ALC861VD_LENOVO),
SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO),
+ SND_PCI_QUIRK(0x1179, 0xff03, "Toshiba P205", ALC861VD_LENOVO),
+ SND_PCI_QUIRK(0x1565, 0x820d, "Biostar NF61S SE", ALC861VD_6ST_DIG),
+ SND_PCI_QUIRK(0x1849, 0x0862, "ASRock K8NF6G-VSTA", ALC861VD_6ST_DIG),
+ SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_HP),
{}
};
@@ -10435,7 +11206,21 @@ static struct alc_config_preset alc861vd_presets[] = {
.input_mux = &alc861vd_dallas_capture_source,
.unsol_event = alc861vd_dallas_unsol_event,
.init_hook = alc861vd_dallas_automute,
- },
+ },
+ [ALC861VD_HP] = {
+ .mixers = { alc861vd_hp_mixer },
+ .init_verbs = { alc861vd_dallas_verbs, alc861vd_eapd_verbs },
+ .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
+ .dac_nids = alc861vd_dac_nids,
+ .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
+ .dig_out_nid = ALC861VD_DIGOUT_NID,
+ .adc_nids = alc861vd_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
+ .channel_mode = alc861vd_3stack_2ch_modes,
+ .input_mux = &alc861vd_hp_capture_source,
+ .unsol_event = alc861vd_dallas_unsol_event,
+ .init_hook = alc861vd_dallas_automute,
+ },
};
/*
@@ -10668,6 +11453,10 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec)
spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux;
+ err = alc_auto_add_mic_boost(codec);
+ if (err < 0)
+ return err;
+
return 1;
}
@@ -10735,6 +11524,10 @@ static int patch_alc861vd(struct hda_codec *codec)
if (board_config == ALC861VD_AUTO)
spec->init_hook = alc861vd_auto_init;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ if (!spec->loopback.amplist)
+ spec->loopback.amplist = alc861vd_loopbacks;
+#endif
return 0;
}
@@ -10782,6 +11575,15 @@ static struct hda_input_mux alc662_lenovo_101e_capture_source = {
{ "Line", 0x2 },
},
};
+
+static struct hda_input_mux alc662_eeepc_capture_source = {
+ .num_items = 2,
+ .items = {
+ { "i-Mic", 0x1 },
+ { "e-Mic", 0x0 },
+ },
+};
+
#define alc662_mux_enum_info alc_mux_enum_info
#define alc662_mux_enum_get alc_mux_enum_get
@@ -10792,7 +11594,7 @@ static int alc662_mux_enum_put(struct snd_kcontrol *kcontrol,
struct alc_spec *spec = codec->spec;
const struct hda_input_mux *imux = spec->input_mux;
unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
- static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 };
+ static hda_nid_t capture_mixers[2] = { 0x23, 0x22 };
hda_nid_t nid = capture_mixers[adc_idx];
unsigned int *cur_val = &spec->cur_mux[adc_idx];
unsigned int i, idx;
@@ -10800,12 +11602,13 @@ static int alc662_mux_enum_put(struct snd_kcontrol *kcontrol,
idx = ucontrol->value.enumerated.item[0];
if (idx >= imux->num_items)
idx = imux->num_items - 1;
- if (*cur_val == idx && !codec->in_resume)
+ if (*cur_val == idx)
return 0;
for (i = 0; i < imux->num_items; i++) {
- unsigned int v = (i == idx) ? 0x7000 : 0x7080;
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
- v | (imux->items[i].index << 8));
+ unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
+ snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
+ imux->items[i].index,
+ HDA_AMP_MUTE, v);
}
*cur_val = idx;
return 1;
@@ -10997,6 +11800,22 @@ static struct snd_kcontrol_new alc662_lenovo_101e_mixer[] = {
{ } /* end */
};
+static struct snd_kcontrol_new alc662_eeepc_p701_mixer[] = {
+ HDA_CODEC_MUTE("iSpeaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+
+ HDA_CODEC_VOLUME("LineOut Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("LineOut Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+
+ HDA_CODEC_VOLUME("e-Mic Boost", 0x18, 0, HDA_INPUT),
+ HDA_CODEC_VOLUME("e-Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("e-Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+
+ HDA_CODEC_VOLUME("i-Mic Boost", 0x19, 0, HDA_INPUT),
+ HDA_CODEC_VOLUME("i-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+ HDA_CODEC_MUTE("i-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+ { } /* end */
+};
+
static struct snd_kcontrol_new alc662_chmode_mixer[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -11014,18 +11833,18 @@ static struct hda_verb alc662_init_verbs[] = {
{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
/* Front mixer: unmute input/output amp left and right (volume = 0) */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
- {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
/* Front Pin: output 0 (0x0c) */
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
@@ -11062,13 +11881,24 @@ static struct hda_verb alc662_init_verbs[] = {
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
{ }
};
static struct hda_verb alc662_sue_init_verbs[] = {
{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT},
{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
- {}
+ {}
+};
+
+static struct hda_verb alc662_eeepc_sue_init_verbs[] = {
+ {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
+ {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+ {}
};
/*
@@ -11087,11 +11917,11 @@ static struct hda_verb alc662_auto_init_verbs[] = {
* panel mic (mic 2)
*/
/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
/*
* Set up output mixers (0x0c - 0x0f)
@@ -11103,23 +11933,19 @@ static struct hda_verb alc662_auto_init_verbs[] = {
/* set up input amps for analog loopback */
/* Amp Indices: DAC = 0, mixer = 1 */
- {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
/* FIXME: use matrix-type input source selection */
/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
/* Input mixer */
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- /*{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},*/
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
-
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{ }
};
@@ -11150,11 +11976,9 @@ static void alc662_lenovo_101e_ispeaker_automute(struct hda_codec *codec)
present = snd_hda_codec_read(codec, 0x14, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = present ? 0x80 : 0;
- snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
- 0x80, bits);
+ bits = present ? HDA_AMP_MUTE : 0;
+ snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
}
static void alc662_lenovo_101e_all_automute(struct hda_codec *codec)
@@ -11164,15 +11988,11 @@ static void alc662_lenovo_101e_all_automute(struct hda_codec *codec)
present = snd_hda_codec_read(codec, 0x1b, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = present ? 0x80 : 0;
- snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
- 0x80, bits);
+ bits = present ? HDA_AMP_MUTE : 0;
+ snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
+ snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
}
static void alc662_lenovo_101e_unsol_event(struct hda_codec *codec,
@@ -11184,6 +12004,43 @@ static void alc662_lenovo_101e_unsol_event(struct hda_codec *codec,
alc662_lenovo_101e_ispeaker_automute(codec);
}
+static void alc662_eeepc_mic_automute(struct hda_codec *codec)
+{
+ unsigned int present;
+
+ present = snd_hda_codec_read(codec, 0x18, 0,
+ AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+ snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+ 0x7000 | (0x00 << 8) | (present ? 0 : 0x80));
+ snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+ 0x7000 | (0x00 << 8) | (present ? 0 : 0x80));
+ snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+ 0x7000 | (0x01 << 8) | (present ? 0x80 : 0));
+ snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+ 0x7000 | (0x01 << 8) | (present ? 0x80 : 0));
+}
+
+/* unsolicited event for HP jack sensing */
+static void alc662_eeepc_unsol_event(struct hda_codec *codec,
+ unsigned int res)
+{
+ if ((res >> 26) == ALC880_HP_EVENT)
+ alc262_hippo1_automute( codec );
+
+ if ((res >> 26) == ALC880_MIC_EVENT)
+ alc662_eeepc_mic_automute(codec);
+}
+
+static void alc662_eeepc_inithook(struct hda_codec *codec)
+{
+ alc262_hippo1_automute( codec );
+ alc662_eeepc_mic_automute(codec);
+}
+
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+#define alc662_loopbacks alc880_loopbacks
+#endif
+
/* pcm configuration: identiacal with ALC880 */
#define alc662_pcm_analog_playback alc880_pcm_analog_playback
@@ -11205,12 +12062,13 @@ static const char *alc662_models[ALC662_MODEL_LAST] = {
static struct snd_pci_quirk alc662_cfg_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E),
+ SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701),
{}
};
static struct alc_config_preset alc662_presets[] = {
[ALC662_3ST_2ch_DIG] = {
- .mixers = { alc662_3ST_2ch_mixer },
+ .mixers = { alc662_3ST_2ch_mixer, alc662_capture_mixer },
.init_verbs = { alc662_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
@@ -11223,7 +12081,8 @@ static struct alc_config_preset alc662_presets[] = {
.input_mux = &alc662_capture_source,
},
[ALC662_3ST_6ch_DIG] = {
- .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
+ .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer,
+ alc662_capture_mixer },
.init_verbs = { alc662_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
@@ -11237,7 +12096,8 @@ static struct alc_config_preset alc662_presets[] = {
.input_mux = &alc662_capture_source,
},
[ALC662_3ST_6ch] = {
- .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
+ .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer,
+ alc662_capture_mixer },
.init_verbs = { alc662_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
@@ -11249,7 +12109,8 @@ static struct alc_config_preset alc662_presets[] = {
.input_mux = &alc662_capture_source,
},
[ALC662_5ST_DIG] = {
- .mixers = { alc662_base_mixer, alc662_chmode_mixer },
+ .mixers = { alc662_base_mixer, alc662_chmode_mixer,
+ alc662_capture_mixer },
.init_verbs = { alc662_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
@@ -11262,7 +12123,7 @@ static struct alc_config_preset alc662_presets[] = {
.input_mux = &alc662_capture_source,
},
[ALC662_LENOVO_101E] = {
- .mixers = { alc662_lenovo_101e_mixer },
+ .mixers = { alc662_lenovo_101e_mixer, alc662_capture_mixer },
.init_verbs = { alc662_init_verbs, alc662_sue_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
@@ -11274,6 +12135,20 @@ static struct alc_config_preset alc662_presets[] = {
.unsol_event = alc662_lenovo_101e_unsol_event,
.init_hook = alc662_lenovo_101e_all_automute,
},
+ [ALC662_ASUS_EEEPC_P701] = {
+ .mixers = { alc662_eeepc_p701_mixer, alc662_capture_mixer },
+ .init_verbs = { alc662_init_verbs,
+ alc662_eeepc_sue_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc662_dac_nids),
+ .dac_nids = alc662_dac_nids,
+ .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
+ .adc_nids = alc662_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+ .channel_mode = alc662_3ST_2ch_modes,
+ .input_mux = &alc662_eeepc_capture_source,
+ .unsol_event = alc662_eeepc_unsol_event,
+ .init_hook = alc662_eeepc_inithook,
+ },
};
@@ -11296,7 +12171,7 @@ static int alc662_auto_create_multi_out_ctls(struct alc_spec *spec,
for (i = 0; i < cfg->line_outs; i++) {
if (!spec->multiout.dac_nids[i])
continue;
- nid = alc880_idx_to_mixer(i);
+ nid = alc880_idx_to_dac(i);
if (i == 2) {
/* Center/LFE */
err = add_control(spec, ALC_CTL_WIDGET_VOL,
@@ -11586,6 +12461,10 @@ static int patch_alc662(struct hda_codec *codec)
codec->patch_ops = alc_patch_ops;
if (board_config == ALC662_AUTO)
spec->init_hook = alc662_auto_init;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ if (!spec->loopback.amplist)
+ spec->loopback.amplist = alc662_loopbacks;
+#endif
return 0;
}
diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c
index 6d2ecc38905c..2a4b9609aa5c 100644
--- a/sound/pci/hda/patch_si3054.c
+++ b/sound/pci/hda/patch_si3054.c
@@ -78,6 +78,8 @@
/* si3054 codec registers (nodes) access macros */
#define GET_REG(codec,reg) (snd_hda_codec_read(codec,reg,0,SI3054_VERB_READ_NODE,0))
#define SET_REG(codec,reg,val) (snd_hda_codec_write(codec,reg,0,SI3054_VERB_WRITE_NODE,val))
+#define SET_REG_CACHE(codec,reg,val) \
+ snd_hda_codec_write_cache(codec,reg,0,SI3054_VERB_WRITE_NODE,val)
struct si3054_spec {
@@ -94,15 +96,7 @@ struct si3054_spec {
#define PRIVATE_REG(val) ((val>>16)&0xffff)
#define PRIVATE_MASK(val) (val&0xffff)
-static int si3054_switch_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define si3054_switch_info snd_ctl_boolean_mono_info
static int si3054_switch_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *uvalue)
@@ -121,9 +115,9 @@ static int si3054_switch_put(struct snd_kcontrol *kcontrol,
u16 reg = PRIVATE_REG(kcontrol->private_value);
u16 mask = PRIVATE_MASK(kcontrol->private_value);
if (uvalue->value.integer.value[0])
- SET_REG(codec, reg, (GET_REG(codec, reg)) | mask);
+ SET_REG_CACHE(codec, reg, (GET_REG(codec, reg)) | mask);
else
- SET_REG(codec, reg, (GET_REG(codec, reg)) & ~mask);
+ SET_REG_CACHE(codec, reg, (GET_REG(codec, reg)) & ~mask);
return 0;
}
@@ -275,10 +269,6 @@ static struct hda_codec_ops si3054_patch_ops = {
.build_pcms = si3054_build_pcms,
.init = si3054_init,
.free = si3054_free,
-#ifdef CONFIG_PM
- //.suspend = si3054_suspend,
- .resume = si3054_init,
-#endif
};
static int patch_si3054(struct hda_codec *codec)
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 3f25de72966b..f9b2c435a130 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -39,12 +39,25 @@
enum {
STAC_REF,
+ STAC_9200_DELL_D21,
+ STAC_9200_DELL_D22,
+ STAC_9200_DELL_D23,
+ STAC_9200_DELL_M21,
+ STAC_9200_DELL_M22,
+ STAC_9200_DELL_M23,
+ STAC_9200_DELL_M24,
+ STAC_9200_DELL_M25,
+ STAC_9200_DELL_M26,
+ STAC_9200_DELL_M27,
+ STAC_9200_GATEWAY,
STAC_9200_MODELS
};
enum {
STAC_9205_REF,
- STAC_M43xx,
+ STAC_9205_DELL_M42,
+ STAC_9205_DELL_M43,
+ STAC_9205_DELL_M44,
STAC_9205_MODELS
};
@@ -60,19 +73,22 @@ enum {
STAC_D945_REF,
STAC_D945GTP3,
STAC_D945GTP5,
- STAC_922X_DELL,
STAC_INTEL_MAC_V1,
STAC_INTEL_MAC_V2,
STAC_INTEL_MAC_V3,
STAC_INTEL_MAC_V4,
STAC_INTEL_MAC_V5,
- /* for backward compitability */
+ /* for backward compatibility */
STAC_MACMINI,
STAC_MACBOOK,
STAC_MACBOOK_PRO_V1,
STAC_MACBOOK_PRO_V2,
STAC_IMAC_INTEL,
STAC_IMAC_INTEL_20,
+ STAC_922X_DELL_D81,
+ STAC_922X_DELL_D82,
+ STAC_922X_DELL_M81,
+ STAC_922X_DELL_M82,
STAC_922X_MODELS
};
@@ -80,6 +96,7 @@ enum {
STAC_D965_REF,
STAC_D965_3ST,
STAC_D965_5ST,
+ STAC_DELL_3ST,
STAC_927X_MODELS
};
@@ -94,6 +111,9 @@ struct sigmatel_spec {
unsigned int alt_switch: 1;
unsigned int hp_detect: 1;
unsigned int gpio_mute: 1;
+ unsigned int no_vol_knob :1;
+
+ unsigned int gpio_mask, gpio_data;
/* playback */
struct hda_multi_out multiout;
@@ -127,6 +147,8 @@ struct sigmatel_spec {
/* i/o switches */
unsigned int io_switch[2];
+ unsigned int clfe_swap;
+ unsigned int aloopback;
struct hda_pcm pcm_rec[2]; /* PCM information */
@@ -162,8 +184,9 @@ static hda_nid_t stac925x_dac_nids[1] = {
0x02,
};
-static hda_nid_t stac925x_dmic_nids[1] = {
- 0x15,
+#define STAC925X_NUM_DMICS 1
+static hda_nid_t stac925x_dmic_nids[STAC925X_NUM_DMICS + 1] = {
+ 0x15, 0
};
static hda_nid_t stac922x_adc_nids[2] = {
@@ -190,8 +213,9 @@ static hda_nid_t stac9205_mux_nids[2] = {
0x19, 0x1a
};
-static hda_nid_t stac9205_dmic_nids[2] = {
- 0x17, 0x18,
+#define STAC9205_NUM_DMICS 2
+static hda_nid_t stac9205_dmic_nids[STAC9205_NUM_DMICS + 1] = {
+ 0x17, 0x18, 0
};
static hda_nid_t stac9200_pin_nids[8] = {
@@ -276,12 +300,97 @@ static int stac92xx_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
spec->mux_nids[adc_idx], &spec->cur_mux[adc_idx]);
}
+#define stac92xx_aloopback_info snd_ctl_boolean_mono_info
+
+static int stac92xx_aloopback_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct sigmatel_spec *spec = codec->spec;
+
+ ucontrol->value.integer.value[0] = spec->aloopback;
+ return 0;
+}
+
+static int stac92xx_aloopback_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct sigmatel_spec *spec = codec->spec;
+ unsigned int dac_mode;
+
+ if (spec->aloopback == ucontrol->value.integer.value[0])
+ return 0;
+
+ spec->aloopback = ucontrol->value.integer.value[0];
+
+
+ dac_mode = snd_hda_codec_read(codec, codec->afg, 0,
+ kcontrol->private_value & 0xFFFF, 0x0);
+
+ if (spec->aloopback) {
+ snd_hda_power_up(codec);
+ dac_mode |= 0x40;
+ } else {
+ snd_hda_power_down(codec);
+ dac_mode &= ~0x40;
+ }
+
+ snd_hda_codec_write_cache(codec, codec->afg, 0,
+ kcontrol->private_value >> 16, dac_mode);
+
+ return 1;
+}
+
+static int stac92xx_volknob_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 127;
+ return 0;
+}
+
+static int stac92xx_volknob_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = kcontrol->private_value & 0xff;
+ return 0;
+}
+
+static int stac92xx_volknob_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ unsigned int val = kcontrol->private_value & 0xff;
+
+ if (val == ucontrol->value.integer.value[0])
+ return 0;
+
+ val = ucontrol->value.integer.value[0];
+ kcontrol->private_value &= ~0xff;
+ kcontrol->private_value |= val;
+
+ snd_hda_codec_write_cache(codec, kcontrol->private_value >> 16, 0,
+ AC_VERB_SET_VOLUME_KNOB_CONTROL, val | 0x80);
+ return 1;
+}
+
+
static struct hda_verb stac9200_core_init[] = {
/* set dac0mux for dac converter */
{ 0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
{}
};
+static struct hda_verb stac9200_eapd_init[] = {
+ /* set dac0mux for dac converter */
+ {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x08, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
+ {}
+};
+
static struct hda_verb stac925x_core_init[] = {
/* set dac0mux for dac converter */
{ 0x06, AC_VERB_SET_CONNECT_SEL, 0x00},
@@ -316,17 +425,43 @@ static struct hda_verb stac9205_core_init[] = {
{}
};
+#define STAC_INPUT_SOURCE(cnt) \
+ { \
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ .name = "Input Source", \
+ .count = cnt, \
+ .info = stac92xx_mux_enum_info, \
+ .get = stac92xx_mux_enum_get, \
+ .put = stac92xx_mux_enum_put, \
+ }
+
+#define STAC_ANALOG_LOOPBACK(verb_read,verb_write) \
+ { \
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ .name = "Analog Loopback", \
+ .count = 1, \
+ .info = stac92xx_aloopback_info, \
+ .get = stac92xx_aloopback_get, \
+ .put = stac92xx_aloopback_put, \
+ .private_value = verb_read | (verb_write << 16), \
+ }
+
+#define STAC_VOLKNOB(knob_nid) \
+ { \
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ .name = "Master Playback Volume", \
+ .count = 1, \
+ .info = stac92xx_volknob_info, \
+ .get = stac92xx_volknob_get, \
+ .put = stac92xx_volknob_put, \
+ .private_value = 127 | (knob_nid << 16), \
+ }
+
+
static struct snd_kcontrol_new stac9200_mixer[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT),
HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Input Source",
- .count = 1,
- .info = stac92xx_mux_enum_info,
- .get = stac92xx_mux_enum_get,
- .put = stac92xx_mux_enum_put,
- },
+ STAC_INPUT_SOURCE(1),
HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT),
HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Capture Mux Volume", 0x0c, 0, HDA_OUTPUT),
@@ -334,86 +469,68 @@ static struct snd_kcontrol_new stac9200_mixer[] = {
};
static struct snd_kcontrol_new stac925x_mixer[] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Input Source",
- .count = 1,
- .info = stac92xx_mux_enum_info,
- .get = stac92xx_mux_enum_get,
- .put = stac92xx_mux_enum_put,
- },
+ STAC_INPUT_SOURCE(1),
HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_OUTPUT),
HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Capture Mux Volume", 0x0f, 0, HDA_OUTPUT),
{ } /* end */
};
-/* This needs to be generated dynamically based on sequence */
-static struct snd_kcontrol_new stac922x_mixer[] = {
+static struct snd_kcontrol_new stac9205_mixer[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Input Source",
+ .name = "Digital Input Source",
.count = 1,
- .info = stac92xx_mux_enum_info,
- .get = stac92xx_mux_enum_get,
- .put = stac92xx_mux_enum_put,
+ .info = stac92xx_dmux_enum_info,
+ .get = stac92xx_dmux_enum_get,
+ .put = stac92xx_dmux_enum_put,
},
- HDA_CODEC_VOLUME("Capture Volume", 0x17, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x17, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mux Capture Volume", 0x12, 0x0, HDA_OUTPUT),
+ STAC_INPUT_SOURCE(2),
+ STAC_ANALOG_LOOPBACK(0xFE0, 0x7E0),
+ STAC_VOLKNOB(0x24),
+
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1b, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1d, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x0, 0x19, 0x0, HDA_OUTPUT),
+
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x1c, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1e, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x1, 0x1A, 0x0, HDA_OUTPUT),
+
{ } /* end */
};
/* This needs to be generated dynamically based on sequence */
-static struct snd_kcontrol_new stac9227_mixer[] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Input Source",
- .count = 1,
- .info = stac92xx_mux_enum_info,
- .get = stac92xx_mux_enum_get,
- .put = stac92xx_mux_enum_put,
- },
- HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x1b, 0x0, HDA_OUTPUT),
+static struct snd_kcontrol_new stac922x_mixer[] = {
+ STAC_INPUT_SOURCE(2),
+ STAC_VOLKNOB(0x16),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x17, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x17, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x0, 0x12, 0x0, HDA_OUTPUT),
+
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x18, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x18, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x1, 0x13, 0x0, HDA_OUTPUT),
{ } /* end */
};
+
static struct snd_kcontrol_new stac927x_mixer[] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Input Source",
- .count = 1,
- .info = stac92xx_mux_enum_info,
- .get = stac92xx_mux_enum_get,
- .put = stac92xx_mux_enum_put,
- },
- HDA_CODEC_VOLUME("InMux Capture Volume", 0x15, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("InVol Capture Volume", 0x18, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("ADCMux Capture Switch", 0x1b, 0x0, HDA_OUTPUT),
- { } /* end */
-};
+ STAC_INPUT_SOURCE(3),
+ STAC_VOLKNOB(0x24),
+ STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB),
-static struct snd_kcontrol_new stac9205_mixer[] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Digital Input Source",
- .count = 1,
- .info = stac92xx_dmux_enum_info,
- .get = stac92xx_dmux_enum_get,
- .put = stac92xx_dmux_enum_put,
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Input Source",
- .count = 1,
- .info = stac92xx_mux_enum_info,
- .get = stac92xx_mux_enum_get,
- .put = stac92xx_mux_enum_put,
- },
- HDA_CODEC_VOLUME("InMux Capture Volume", 0x19, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("InVol Capture Volume", 0x1b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("ADCMux Capture Switch", 0x1d, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x18, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1b, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x0, 0x15, 0x0, HDA_OUTPUT),
+
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x19, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1c, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x1, 0x16, 0x0, HDA_OUTPUT),
+
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 0x2, 0x1A, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 0x2, 0x1d, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x2, 0x17, 0x0, HDA_OUTPUT),
{ } /* end */
};
@@ -451,12 +568,145 @@ static unsigned int ref9200_pin_configs[8] = {
0x02a19020, 0x01a19021, 0x90100140, 0x01813122,
};
+/*
+ STAC 9200 pin configs for
+ 102801A8
+ 102801DE
+ 102801E8
+*/
+static unsigned int dell9200_d21_pin_configs[8] = {
+ 0x400001f0, 0x400001f1, 0x02214030, 0x01014010,
+ 0x02a19020, 0x01a19021, 0x90100140, 0x01813122,
+};
+
+/*
+ STAC 9200 pin configs for
+ 102801C0
+ 102801C1
+*/
+static unsigned int dell9200_d22_pin_configs[8] = {
+ 0x400001f0, 0x400001f1, 0x0221401f, 0x01014010,
+ 0x01813020, 0x02a19021, 0x90100140, 0x400001f2,
+};
+
+/*
+ STAC 9200 pin configs for
+ 102801C4 (Dell Dimension E310)
+ 102801C5
+ 102801C7
+ 102801D9
+ 102801DA
+ 102801E3
+*/
+static unsigned int dell9200_d23_pin_configs[8] = {
+ 0x400001f0, 0x400001f1, 0x0221401f, 0x01014010,
+ 0x01813020, 0x01a19021, 0x90100140, 0x400001f2,
+};
+
+
+/*
+ STAC 9200-32 pin configs for
+ 102801B5 (Dell Inspiron 630m)
+ 102801D8 (Dell Inspiron 640m)
+*/
+static unsigned int dell9200_m21_pin_configs[8] = {
+ 0x40c003fa, 0x03441340, 0x0321121f, 0x90170310,
+ 0x408003fb, 0x03a11020, 0x401003fc, 0x403003fd,
+};
+
+/*
+ STAC 9200-32 pin configs for
+ 102801C2 (Dell Latitude D620)
+ 102801C8
+ 102801CC (Dell Latitude D820)
+ 102801D4
+ 102801D6
+*/
+static unsigned int dell9200_m22_pin_configs[8] = {
+ 0x40c003fa, 0x0144131f, 0x0321121f, 0x90170310,
+ 0x90a70321, 0x03a11020, 0x401003fb, 0x40f000fc,
+};
+
+/*
+ STAC 9200-32 pin configs for
+ 102801CE (Dell XPS M1710)
+ 102801CF (Dell Precision M90)
+*/
+static unsigned int dell9200_m23_pin_configs[8] = {
+ 0x40c003fa, 0x01441340, 0x0421421f, 0x90170310,
+ 0x408003fb, 0x04a1102e, 0x90170311, 0x403003fc,
+};
+
+/*
+ STAC 9200-32 pin configs for
+ 102801C9
+ 102801CA
+ 102801CB (Dell Latitude 120L)
+ 102801D3
+*/
+static unsigned int dell9200_m24_pin_configs[8] = {
+ 0x40c003fa, 0x404003fb, 0x0321121f, 0x90170310,
+ 0x408003fc, 0x03a11020, 0x401003fd, 0x403003fe,
+};
+
+/*
+ STAC 9200-32 pin configs for
+ 102801BD (Dell Inspiron E1505n)
+ 102801EE
+ 102801EF
+*/
+static unsigned int dell9200_m25_pin_configs[8] = {
+ 0x40c003fa, 0x01441340, 0x0421121f, 0x90170310,
+ 0x408003fb, 0x04a11020, 0x401003fc, 0x403003fd,
+};
+
+/*
+ STAC 9200-32 pin configs for
+ 102801F5 (Dell Inspiron 1501)
+ 102801F6
+*/
+static unsigned int dell9200_m26_pin_configs[8] = {
+ 0x40c003fa, 0x404003fb, 0x0421121f, 0x90170310,
+ 0x408003fc, 0x04a11020, 0x401003fd, 0x403003fe,
+};
+
+/*
+ STAC 9200-32
+ 102801CD (Dell Inspiron E1705/9400)
+*/
+static unsigned int dell9200_m27_pin_configs[8] = {
+ 0x40c003fa, 0x01441340, 0x0421121f, 0x90170310,
+ 0x90170310, 0x04a11020, 0x90170310, 0x40f003fc,
+};
+
+
static unsigned int *stac9200_brd_tbl[STAC_9200_MODELS] = {
[STAC_REF] = ref9200_pin_configs,
+ [STAC_9200_DELL_D21] = dell9200_d21_pin_configs,
+ [STAC_9200_DELL_D22] = dell9200_d22_pin_configs,
+ [STAC_9200_DELL_D23] = dell9200_d23_pin_configs,
+ [STAC_9200_DELL_M21] = dell9200_m21_pin_configs,
+ [STAC_9200_DELL_M22] = dell9200_m22_pin_configs,
+ [STAC_9200_DELL_M23] = dell9200_m23_pin_configs,
+ [STAC_9200_DELL_M24] = dell9200_m24_pin_configs,
+ [STAC_9200_DELL_M25] = dell9200_m25_pin_configs,
+ [STAC_9200_DELL_M26] = dell9200_m26_pin_configs,
+ [STAC_9200_DELL_M27] = dell9200_m27_pin_configs,
};
static const char *stac9200_models[STAC_9200_MODELS] = {
[STAC_REF] = "ref",
+ [STAC_9200_DELL_D21] = "dell-d21",
+ [STAC_9200_DELL_D22] = "dell-d22",
+ [STAC_9200_DELL_D23] = "dell-d23",
+ [STAC_9200_DELL_M21] = "dell-m21",
+ [STAC_9200_DELL_M22] = "dell-m22",
+ [STAC_9200_DELL_M23] = "dell-m23",
+ [STAC_9200_DELL_M24] = "dell-m24",
+ [STAC_9200_DELL_M25] = "dell-m25",
+ [STAC_9200_DELL_M26] = "dell-m26",
+ [STAC_9200_DELL_M27] = "dell-m27",
+ [STAC_9200_GATEWAY] = "gateway",
};
static struct snd_pci_quirk stac9200_cfg_tbl[] = {
@@ -464,30 +714,72 @@ static struct snd_pci_quirk stac9200_cfg_tbl[] = {
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
"DFI LanParty", STAC_REF),
/* Dell laptops have BIOS problem */
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01a8,
+ "unknown Dell", STAC_9200_DELL_D21),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01b5,
- "Dell Inspiron 630m", STAC_REF),
+ "Dell Inspiron 630m", STAC_9200_DELL_M21),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01bd,
+ "Dell Inspiron E1505n", STAC_9200_DELL_M25),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c0,
+ "unknown Dell", STAC_9200_DELL_D22),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c1,
+ "unknown Dell", STAC_9200_DELL_D22),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c2,
- "Dell Latitude D620", STAC_REF),
+ "Dell Latitude D620", STAC_9200_DELL_M22),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c5,
+ "unknown Dell", STAC_9200_DELL_D23),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c7,
+ "unknown Dell", STAC_9200_DELL_D23),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c8,
+ "unknown Dell", STAC_9200_DELL_M22),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c9,
+ "unknown Dell", STAC_9200_DELL_M24),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ca,
+ "unknown Dell", STAC_9200_DELL_M24),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cb,
- "Dell Latitude 120L", STAC_REF),
+ "Dell Latitude 120L", STAC_9200_DELL_M24),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cc,
- "Dell Latitude D820", STAC_REF),
+ "Dell Latitude D820", STAC_9200_DELL_M22),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cd,
- "Dell Inspiron E1705/9400", STAC_REF),
+ "Dell Inspiron E1705/9400", STAC_9200_DELL_M27),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ce,
- "Dell XPS M1710", STAC_REF),
+ "Dell XPS M1710", STAC_9200_DELL_M23),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cf,
- "Dell Precision M90", STAC_REF),
+ "Dell Precision M90", STAC_9200_DELL_M23),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d3,
+ "unknown Dell", STAC_9200_DELL_M22),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d4,
+ "unknown Dell", STAC_9200_DELL_M22),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d6,
- "unknown Dell", STAC_REF),
+ "unknown Dell", STAC_9200_DELL_M22),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d8,
- "Dell Inspiron 640m", STAC_REF),
+ "Dell Inspiron 640m", STAC_9200_DELL_M21),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d9,
+ "unknown Dell", STAC_9200_DELL_D23),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01da,
+ "unknown Dell", STAC_9200_DELL_D23),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01de,
+ "unknown Dell", STAC_9200_DELL_D21),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01e3,
+ "unknown Dell", STAC_9200_DELL_D23),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01e8,
+ "unknown Dell", STAC_9200_DELL_D21),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ee,
+ "unknown Dell", STAC_9200_DELL_M25),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ef,
+ "unknown Dell", STAC_9200_DELL_M25),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f5,
- "Dell Inspiron 1501", STAC_REF),
-
+ "Dell Inspiron 1501", STAC_9200_DELL_M26),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f6,
+ "unknown Dell", STAC_9200_DELL_M26),
/* Panasonic */
SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-74", STAC_REF),
-
+ /* Gateway machines needs EAPD to be set on resume */
+ SND_PCI_QUIRK(0x107b, 0x0205, "Gateway S-7110M", STAC_9200_GATEWAY),
+ SND_PCI_QUIRK(0x107b, 0x0317, "Gateway MT3423, MX341*",
+ STAC_9200_GATEWAY),
+ SND_PCI_QUIRK(0x107b, 0x0318, "Gateway ML3019, MT3707",
+ STAC_9200_GATEWAY),
{} /* terminator */
};
@@ -543,6 +835,51 @@ static unsigned int ref922x_pin_configs[10] = {
0x40000100, 0x40000100,
};
+/*
+ STAC 922X pin configs for
+ 102801A7
+ 102801AB
+ 102801A9
+ 102801D1
+ 102801D2
+*/
+static unsigned int dell_922x_d81_pin_configs[10] = {
+ 0x02214030, 0x01a19021, 0x01111012, 0x01114010,
+ 0x02a19020, 0x01117011, 0x400001f0, 0x400001f1,
+ 0x01813122, 0x400001f2,
+};
+
+/*
+ STAC 922X pin configs for
+ 102801AC
+ 102801D0
+*/
+static unsigned int dell_922x_d82_pin_configs[10] = {
+ 0x02214030, 0x01a19021, 0x01111012, 0x01114010,
+ 0x02a19020, 0x01117011, 0x01451140, 0x400001f0,
+ 0x01813122, 0x400001f1,
+};
+
+/*
+ STAC 922X pin configs for
+ 102801BF
+*/
+static unsigned int dell_922x_m81_pin_configs[10] = {
+ 0x0321101f, 0x01112024, 0x01111222, 0x91174220,
+ 0x03a11050, 0x01116221, 0x90a70330, 0x01452340,
+ 0x40C003f1, 0x405003f0,
+};
+
+/*
+ STAC 9221 A1 pin configs for
+ 102801D7 (Dell XPS M1210)
+*/
+static unsigned int dell_922x_m82_pin_configs[10] = {
+ 0x0221121f, 0x408103ff, 0x02111212, 0x90100310,
+ 0x408003f1, 0x02111211, 0x03451340, 0x40c003f2,
+ 0x508003f3, 0x405003f4,
+};
+
static unsigned int d945gtp3_pin_configs[10] = {
0x0221401f, 0x01a19022, 0x01813021, 0x01014010,
0x40000100, 0x40000100, 0x40000100, 0x40000100,
@@ -585,48 +922,49 @@ static unsigned int intel_mac_v5_pin_configs[10] = {
0x400000fc, 0x400000fb,
};
-static unsigned int stac922x_dell_pin_configs[10] = {
- 0x0221121e, 0x408103ff, 0x02a1123e, 0x90100310,
- 0x408003f1, 0x0221122f, 0x03451340, 0x40c003f2,
- 0x50a003f3, 0x405003f4
-};
static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = {
[STAC_D945_REF] = ref922x_pin_configs,
[STAC_D945GTP3] = d945gtp3_pin_configs,
[STAC_D945GTP5] = d945gtp5_pin_configs,
- [STAC_922X_DELL] = stac922x_dell_pin_configs,
[STAC_INTEL_MAC_V1] = intel_mac_v1_pin_configs,
[STAC_INTEL_MAC_V2] = intel_mac_v2_pin_configs,
[STAC_INTEL_MAC_V3] = intel_mac_v3_pin_configs,
[STAC_INTEL_MAC_V4] = intel_mac_v4_pin_configs,
[STAC_INTEL_MAC_V5] = intel_mac_v5_pin_configs,
- /* for backward compitability */
+ /* for backward compatibility */
[STAC_MACMINI] = intel_mac_v3_pin_configs,
[STAC_MACBOOK] = intel_mac_v5_pin_configs,
[STAC_MACBOOK_PRO_V1] = intel_mac_v3_pin_configs,
[STAC_MACBOOK_PRO_V2] = intel_mac_v3_pin_configs,
[STAC_IMAC_INTEL] = intel_mac_v2_pin_configs,
[STAC_IMAC_INTEL_20] = intel_mac_v3_pin_configs,
+ [STAC_922X_DELL_D81] = dell_922x_d81_pin_configs,
+ [STAC_922X_DELL_D82] = dell_922x_d82_pin_configs,
+ [STAC_922X_DELL_M81] = dell_922x_m81_pin_configs,
+ [STAC_922X_DELL_M82] = dell_922x_m82_pin_configs,
};
static const char *stac922x_models[STAC_922X_MODELS] = {
[STAC_D945_REF] = "ref",
[STAC_D945GTP5] = "5stack",
[STAC_D945GTP3] = "3stack",
- [STAC_922X_DELL] = "dell",
[STAC_INTEL_MAC_V1] = "intel-mac-v1",
[STAC_INTEL_MAC_V2] = "intel-mac-v2",
[STAC_INTEL_MAC_V3] = "intel-mac-v3",
[STAC_INTEL_MAC_V4] = "intel-mac-v4",
[STAC_INTEL_MAC_V5] = "intel-mac-v5",
- /* for backward compitability */
+ /* for backward compatibility */
[STAC_MACMINI] = "macmini",
[STAC_MACBOOK] = "macbook",
[STAC_MACBOOK_PRO_V1] = "macbook-pro-v1",
[STAC_MACBOOK_PRO_V2] = "macbook-pro",
[STAC_IMAC_INTEL] = "imac-intel",
[STAC_IMAC_INTEL_20] = "imac-intel-20",
+ [STAC_922X_DELL_D81] = "dell-d81",
+ [STAC_922X_DELL_D82] = "dell-d82",
+ [STAC_922X_DELL_M81] = "dell-m81",
+ [STAC_922X_DELL_M82] = "dell-m82",
};
static struct snd_pci_quirk stac922x_cfg_tbl[] = {
@@ -690,9 +1028,25 @@ static struct snd_pci_quirk stac922x_cfg_tbl[] = {
/* Apple Mac Mini (early 2006) */
SND_PCI_QUIRK(0x8384, 0x7680,
"Mac Mini", STAC_INTEL_MAC_V3),
- /* Dell */
- SND_PCI_QUIRK(0x1028, 0x01d7, "Dell XPS M1210", STAC_922X_DELL),
-
+ /* Dell systems */
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01a7,
+ "unknown Dell", STAC_922X_DELL_D81),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01a9,
+ "unknown Dell", STAC_922X_DELL_D81),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ab,
+ "unknown Dell", STAC_922X_DELL_D81),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ac,
+ "unknown Dell", STAC_922X_DELL_D82),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01bf,
+ "unknown Dell", STAC_922X_DELL_M81),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d0,
+ "unknown Dell", STAC_922X_DELL_D82),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d1,
+ "unknown Dell", STAC_922X_DELL_D81),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d2,
+ "unknown Dell", STAC_922X_DELL_D81),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d7,
+ "Dell XPS M1210", STAC_922X_DELL_M82),
{} /* terminator */
};
@@ -717,16 +1071,25 @@ static unsigned int d965_5st_pin_configs[14] = {
0x40000100, 0x40000100
};
+static unsigned int dell_3st_pin_configs[14] = {
+ 0x02211230, 0x02a11220, 0x01a19040, 0x01114210,
+ 0x01111212, 0x01116211, 0x01813050, 0x01112214,
+ 0x403003fa, 0x40000100, 0x40000100, 0x404003fb,
+ 0x40c003fc, 0x40000100
+};
+
static unsigned int *stac927x_brd_tbl[STAC_927X_MODELS] = {
[STAC_D965_REF] = ref927x_pin_configs,
[STAC_D965_3ST] = d965_3st_pin_configs,
[STAC_D965_5ST] = d965_5st_pin_configs,
+ [STAC_DELL_3ST] = dell_3st_pin_configs,
};
static const char *stac927x_models[STAC_927X_MODELS] = {
[STAC_D965_REF] = "ref",
[STAC_D965_3ST] = "3stack",
[STAC_D965_5ST] = "5stack",
+ [STAC_DELL_3ST] = "dell-3stack",
};
static struct snd_pci_quirk stac927x_cfg_tbl[] = {
@@ -753,7 +1116,13 @@ static struct snd_pci_quirk stac927x_cfg_tbl[] = {
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2003, "Intel D965", STAC_D965_3ST),
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2002, "Intel D965", STAC_D965_3ST),
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2001, "Intel D965", STAC_D965_3ST),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f3, "Dell Inspiron 1420", STAC_D965_3ST),
+ /* Dell 3 stack systems */
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01dd, "Dell Dimension E520", STAC_DELL_3ST),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ed, "Dell ", STAC_DELL_3ST),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f4, "Dell ", STAC_DELL_3ST),
/* 965 based 5 stack systems */
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0209, "Dell XPS 1330", STAC_D965_5ST),
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2301, "Intel D965", STAC_D965_5ST),
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2302, "Intel D965", STAC_D965_5ST),
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2303, "Intel D965", STAC_D965_5ST),
@@ -772,23 +1141,97 @@ static unsigned int ref9205_pin_configs[12] = {
0x90a000f0, 0x90a000f0, 0x01441030, 0x01c41030
};
+/*
+ STAC 9205 pin configs for
+ 102801F1
+ 102801F2
+ 102801FC
+ 102801FD
+ 10280204
+ 1028021F
+*/
+static unsigned int dell_9205_m42_pin_configs[12] = {
+ 0x0321101F, 0x03A11020, 0x400003FA, 0x90170310,
+ 0x400003FB, 0x400003FC, 0x400003FD, 0x40F000F9,
+ 0x90A60330, 0x400003FF, 0x0144131F, 0x40C003FE,
+};
+
+/*
+ STAC 9205 pin configs for
+ 102801F9
+ 102801FA
+ 102801FE
+ 102801FF (Dell Precision M4300)
+ 10280206
+ 10280200
+ 10280201
+*/
+static unsigned int dell_9205_m43_pin_configs[12] = {
+ 0x0321101f, 0x03a11020, 0x90a70330, 0x90170310,
+ 0x400000fe, 0x400000ff, 0x400000fd, 0x40f000f9,
+ 0x400000fa, 0x400000fc, 0x0144131f, 0x40c003f8,
+};
+
+static unsigned int dell_9205_m44_pin_configs[12] = {
+ 0x0421101f, 0x04a11020, 0x400003fa, 0x90170310,
+ 0x400003fb, 0x400003fc, 0x400003fd, 0x400003f9,
+ 0x90a60330, 0x400003ff, 0x01441340, 0x40c003fe,
+};
+
static unsigned int *stac9205_brd_tbl[STAC_9205_MODELS] = {
- [STAC_REF] = ref9205_pin_configs,
- [STAC_M43xx] = NULL,
+ [STAC_9205_REF] = ref9205_pin_configs,
+ [STAC_9205_DELL_M42] = dell_9205_m42_pin_configs,
+ [STAC_9205_DELL_M43] = dell_9205_m43_pin_configs,
+ [STAC_9205_DELL_M44] = dell_9205_m44_pin_configs,
};
static const char *stac9205_models[STAC_9205_MODELS] = {
[STAC_9205_REF] = "ref",
+ [STAC_9205_DELL_M42] = "dell-m42",
+ [STAC_9205_DELL_M43] = "dell-m43",
+ [STAC_9205_DELL_M44] = "dell-m44",
};
static struct snd_pci_quirk stac9205_cfg_tbl[] = {
/* SigmaTel reference board */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
"DFI LanParty", STAC_9205_REF),
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x01f8,
- "Dell Precision", STAC_M43xx),
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x01ff,
- "Dell Precision", STAC_M43xx),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f1,
+ "unknown Dell", STAC_9205_DELL_M42),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f2,
+ "unknown Dell", STAC_9205_DELL_M42),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f8,
+ "Dell Precision", STAC_9205_DELL_M43),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021c,
+ "Dell Precision", STAC_9205_DELL_M43),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f9,
+ "Dell Precision", STAC_9205_DELL_M43),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021b,
+ "Dell Precision", STAC_9205_DELL_M43),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fa,
+ "Dell Precision", STAC_9205_DELL_M43),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fc,
+ "unknown Dell", STAC_9205_DELL_M42),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fd,
+ "unknown Dell", STAC_9205_DELL_M42),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fe,
+ "Dell Precision", STAC_9205_DELL_M43),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ff,
+ "Dell Precision M4300", STAC_9205_DELL_M43),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0206,
+ "Dell Precision", STAC_9205_DELL_M43),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f1,
+ "Dell Inspiron", STAC_9205_DELL_M44),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f2,
+ "Dell Inspiron", STAC_9205_DELL_M44),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fc,
+ "Dell Inspiron", STAC_9205_DELL_M44),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fd,
+ "Dell Inspiron", STAC_9205_DELL_M44),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0204,
+ "unknown Dell", STAC_9205_DELL_M42),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021f,
+ "Dell Inspiron", STAC_9205_DELL_M44),
{} /* terminator */
};
@@ -854,20 +1297,20 @@ static void stac92xx_set_config_regs(struct hda_codec *codec)
spec->pin_configs[i]);
}
-static void stac92xx_enable_gpio_mask(struct hda_codec *codec,
- int gpio_mask, int gpio_data)
+static void stac92xx_enable_gpio_mask(struct hda_codec *codec)
{
+ struct sigmatel_spec *spec = codec->spec;
/* Configure GPIOx as output */
- snd_hda_codec_write(codec, codec->afg, 0,
- AC_VERB_SET_GPIO_DIRECTION, gpio_mask);
+ snd_hda_codec_write_cache(codec, codec->afg, 0,
+ AC_VERB_SET_GPIO_DIRECTION, spec->gpio_mask);
/* Configure GPIOx as CMOS */
- snd_hda_codec_write(codec, codec->afg, 0, 0x7e7, 0x00000000);
+ snd_hda_codec_write_cache(codec, codec->afg, 0, 0x7e7, 0x00000000);
/* Assert GPIOx */
- snd_hda_codec_write(codec, codec->afg, 0,
- AC_VERB_SET_GPIO_DATA, gpio_data);
+ snd_hda_codec_write_cache(codec, codec->afg, 0,
+ AC_VERB_SET_GPIO_DATA, spec->gpio_data);
/* Enable GPIOx */
- snd_hda_codec_write(codec, codec->afg, 0,
- AC_VERB_SET_GPIO_MASK, gpio_mask);
+ snd_hda_codec_write_cache(codec, codec->afg, 0,
+ AC_VERB_SET_GPIO_MASK, spec->gpio_mask);
}
/*
@@ -1000,10 +1443,9 @@ static struct hda_pcm_stream stac92xx_pcm_analog_alt_playback = {
};
static struct hda_pcm_stream stac92xx_pcm_analog_capture = {
- .substreams = 2,
.channels_min = 2,
.channels_max = 2,
- /* NID is set in stac92xx_build_pcms */
+ /* NID + .substreams is set in stac92xx_build_pcms */
.ops = {
.prepare = stac92xx_capture_pcm_prepare,
.cleanup = stac92xx_capture_pcm_cleanup
@@ -1022,6 +1464,7 @@ static int stac92xx_build_pcms(struct hda_codec *codec)
info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_playback;
info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_analog_capture;
info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
+ info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adcs;
if (spec->alt_switch) {
codec->num_pcms++;
@@ -1066,17 +1509,11 @@ static unsigned int stac92xx_get_vref(struct hda_codec *codec, hda_nid_t nid)
static void stac92xx_auto_set_pinctl(struct hda_codec *codec, hda_nid_t nid, int pin_type)
{
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
+ snd_hda_codec_write_cache(codec, nid, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
}
-static int stac92xx_io_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define stac92xx_io_switch_info snd_ctl_boolean_mono_info
static int stac92xx_io_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -1109,6 +1546,36 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
return 1;
}
+#define stac92xx_clfe_switch_info snd_ctl_boolean_mono_info
+
+static int stac92xx_clfe_switch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct sigmatel_spec *spec = codec->spec;
+
+ ucontrol->value.integer.value[0] = spec->clfe_swap;
+ return 0;
+}
+
+static int stac92xx_clfe_switch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct sigmatel_spec *spec = codec->spec;
+ hda_nid_t nid = kcontrol->private_value & 0xff;
+
+ if (spec->clfe_swap == ucontrol->value.integer.value[0])
+ return 0;
+
+ spec->clfe_swap = ucontrol->value.integer.value[0];
+
+ snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
+ spec->clfe_swap ? 0x4 : 0x0);
+
+ return 1;
+}
+
#define STAC_CODEC_IO_SWITCH(xname, xpval) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
@@ -1119,17 +1586,28 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
.private_value = xpval, \
}
+#define STAC_CODEC_CLFE_SWITCH(xname, xpval) \
+ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ .name = xname, \
+ .index = 0, \
+ .info = stac92xx_clfe_switch_info, \
+ .get = stac92xx_clfe_switch_get, \
+ .put = stac92xx_clfe_switch_put, \
+ .private_value = xpval, \
+ }
enum {
STAC_CTL_WIDGET_VOL,
STAC_CTL_WIDGET_MUTE,
STAC_CTL_WIDGET_IO_SWITCH,
+ STAC_CTL_WIDGET_CLFE_SWITCH
};
static struct snd_kcontrol_new stac92xx_control_templates[] = {
HDA_CODEC_VOLUME(NULL, 0, 0, 0),
HDA_CODEC_MUTE(NULL, 0, 0, 0),
STAC_CODEC_IO_SWITCH(NULL, 0),
+ STAC_CODEC_CLFE_SWITCH(NULL, 0),
};
/* add dynamic controls */
@@ -1182,7 +1660,8 @@ static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cf
case 3:
/* add line-in as side */
if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 3) {
- cfg->line_out_pins[3] = cfg->input_pins[AUTO_PIN_LINE];
+ cfg->line_out_pins[cfg->line_outs] =
+ cfg->input_pins[AUTO_PIN_LINE];
spec->line_switch = 1;
cfg->line_outs++;
}
@@ -1190,12 +1669,14 @@ static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cf
case 2:
/* add line-in as clfe and mic as side */
if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 2) {
- cfg->line_out_pins[2] = cfg->input_pins[AUTO_PIN_LINE];
+ cfg->line_out_pins[cfg->line_outs] =
+ cfg->input_pins[AUTO_PIN_LINE];
spec->line_switch = 1;
cfg->line_outs++;
}
if (cfg->input_pins[AUTO_PIN_MIC] && num_dacs > 3) {
- cfg->line_out_pins[3] = cfg->input_pins[AUTO_PIN_MIC];
+ cfg->line_out_pins[cfg->line_outs] =
+ cfg->input_pins[AUTO_PIN_MIC];
spec->mic_switch = 1;
cfg->line_outs++;
}
@@ -1203,12 +1684,14 @@ static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cf
case 1:
/* add line-in as surr and mic as clfe */
if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 1) {
- cfg->line_out_pins[1] = cfg->input_pins[AUTO_PIN_LINE];
+ cfg->line_out_pins[cfg->line_outs] =
+ cfg->input_pins[AUTO_PIN_LINE];
spec->line_switch = 1;
cfg->line_outs++;
}
if (cfg->input_pins[AUTO_PIN_MIC] && num_dacs > 2) {
- cfg->line_out_pins[2] = cfg->input_pins[AUTO_PIN_MIC];
+ cfg->line_out_pins[cfg->line_outs] =
+ cfg->input_pins[AUTO_PIN_MIC];
spec->mic_switch = 1;
cfg->line_outs++;
}
@@ -1282,8 +1765,8 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec,
spec->multiout.num_dacs++;
if (conn_len > 1) {
/* select this DAC in the pin's input mux */
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_CONNECT_SEL, j);
+ snd_hda_codec_write_cache(codec, nid, 0,
+ AC_VERB_SET_CONNECT_SEL, j);
}
}
@@ -1318,7 +1801,7 @@ static int create_controls(struct sigmatel_spec *spec, const char *pfx, hda_nid_
}
/* add playback controls from the parsed DAC table */
-static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec,
+static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
const struct auto_pin_cfg *cfg)
{
static const char *chname[4] = {
@@ -1327,6 +1810,10 @@ static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec,
hda_nid_t nid;
int i, err;
+ struct sigmatel_spec *spec = codec->spec;
+ unsigned int wid_caps;
+
+
for (i = 0; i < cfg->line_outs; i++) {
if (!spec->multiout.dac_nids[i])
continue;
@@ -1341,6 +1828,18 @@ static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec,
err = create_controls(spec, "LFE", nid, 2);
if (err < 0)
return err;
+
+ wid_caps = get_wcaps(codec, nid);
+
+ if (wid_caps & AC_WCAP_LR_SWAP) {
+ err = stac92xx_add_control(spec,
+ STAC_CTL_WIDGET_CLFE_SWITCH,
+ "Swap Center/LFE Playback Switch", nid);
+
+ if (err < 0)
+ return err;
+ }
+
} else {
err = create_controls(spec, chname[i], nid, 3);
if (err < 0)
@@ -1432,7 +1931,8 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec,
}
if (spec->multiout.hp_nid) {
const char *pfx;
- if (old_num_dacs == spec->multiout.num_dacs)
+ if (old_num_dacs == spec->multiout.num_dacs &&
+ spec->no_vol_knob)
pfx = "Master";
else
pfx = "Headphone";
@@ -1536,9 +2036,9 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const
* NID lists. Hopefully this won't get confused.
*/
for (i = 0; i < spec->num_muxes; i++) {
- snd_hda_codec_write(codec, spec->mux_nids[i], 0,
- AC_VERB_SET_CONNECT_SEL,
- imux->items[0].index);
+ snd_hda_codec_write_cache(codec, spec->mux_nids[i], 0,
+ AC_VERB_SET_CONNECT_SEL,
+ imux->items[0].index);
}
}
@@ -1593,9 +2093,19 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
if ((err = stac92xx_auto_fill_dac_nids(codec, &spec->autocfg)) < 0)
return err;
- if ((err = stac92xx_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
- (err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg)) < 0 ||
- (err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0)
+ err = stac92xx_auto_create_multi_out_ctls(codec, &spec->autocfg);
+
+ if (err < 0)
+ return err;
+
+ err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg);
+
+ if (err < 0)
+ return err;
+
+ err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg);
+
+ if (err < 0)
return err;
if (spec->num_dmics > 0)
@@ -1764,9 +2274,9 @@ static void enable_pin_detect(struct hda_codec *codec, hda_nid_t nid,
unsigned int event)
{
if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP)
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- (AC_USRSP_EN | event));
+ snd_hda_codec_write_cache(codec, nid, 0,
+ AC_VERB_SET_UNSOLICITED_ENABLE,
+ (AC_USRSP_EN | event));
}
static int stac92xx_init(struct hda_codec *codec)
@@ -1870,7 +2380,7 @@ static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid,
if (flag & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN))
pin_ctl &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN);
- snd_hda_codec_write(codec, nid, 0,
+ snd_hda_codec_write_cache(codec, nid, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL,
pin_ctl | flag);
}
@@ -1880,7 +2390,7 @@ static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid,
{
unsigned int pin_ctl = snd_hda_codec_read(codec, nid,
0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00);
- snd_hda_codec_write(codec, nid, 0,
+ snd_hda_codec_write_cache(codec, nid, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL,
pin_ctl & ~flag);
}
@@ -1936,22 +2446,22 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
}
}
-#ifdef CONFIG_PM
+#ifdef SND_HDA_NEEDS_RESUME
static int stac92xx_resume(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
- int i;
- stac92xx_init(codec);
stac92xx_set_config_regs(codec);
- snd_hda_resume_ctls(codec, spec->mixer);
- for (i = 0; i < spec->num_mixers; i++)
- snd_hda_resume_ctls(codec, spec->mixers[i]);
- if (spec->multiout.dig_out_nid)
- snd_hda_resume_spdif_out(codec);
- if (spec->dig_in_nid)
- snd_hda_resume_spdif_in(codec);
-
+ snd_hda_sequence_write(codec, spec->init);
+ if (spec->gpio_mute) {
+ stac922x_gpio_mute(codec, 0, 0);
+ stac922x_gpio_mute(codec, 1, 0);
+ }
+ snd_hda_codec_resume_amp(codec);
+ snd_hda_codec_resume_cache(codec);
+ /* invoke unsolicited event to reset the HP state */
+ if (spec->hp_detect)
+ codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
return 0;
}
#endif
@@ -1962,7 +2472,7 @@ static struct hda_codec_ops stac92xx_patch_ops = {
.init = stac92xx_init,
.free = stac92xx_free,
.unsol_event = stac92xx_unsol_event,
-#ifdef CONFIG_PM
+#ifdef SND_HDA_NEEDS_RESUME
.resume = stac92xx_resume,
#endif
};
@@ -1979,6 +2489,7 @@ static int patch_stac9200(struct hda_codec *codec)
codec->spec = spec;
spec->num_pins = ARRAY_SIZE(stac9200_pin_nids);
spec->pin_nids = stac9200_pin_nids;
+ spec->no_vol_knob = 1;
spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS,
stac9200_models,
stac9200_cfg_tbl);
@@ -2002,8 +2513,12 @@ static int patch_stac9200(struct hda_codec *codec)
spec->mux_nids = stac9200_mux_nids;
spec->num_muxes = 1;
spec->num_dmics = 0;
+ spec->num_adcs = 1;
- spec->init = stac9200_core_init;
+ if (spec->board_config == STAC_9200_GATEWAY)
+ spec->init = stac9200_eapd_init;
+ else
+ spec->init = stac9200_core_init;
spec->mixer = stac9200_mixer;
err = stac9200_parse_auto_config(codec);
@@ -2029,6 +2544,7 @@ static int patch_stac925x(struct hda_codec *codec)
codec->spec = spec;
spec->num_pins = ARRAY_SIZE(stac925x_pin_nids);
spec->pin_nids = stac925x_pin_nids;
+ spec->no_vol_knob = 1;
spec->board_config = snd_hda_check_board_config(codec, STAC_925x_MODELS,
stac925x_models,
stac925x_cfg_tbl);
@@ -2053,12 +2569,13 @@ static int patch_stac925x(struct hda_codec *codec)
spec->adc_nids = stac925x_adc_nids;
spec->mux_nids = stac925x_mux_nids;
spec->num_muxes = 1;
+ spec->num_adcs = 1;
switch (codec->vendor_id) {
case 0x83847632: /* STAC9202 */
case 0x83847633: /* STAC9202D */
case 0x83847636: /* STAC9251 */
case 0x83847637: /* STAC9251D */
- spec->num_dmics = 1;
+ spec->num_dmics = STAC925X_NUM_DMICS;
spec->dmic_nids = stac925x_dmic_nids;
break;
default:
@@ -2156,6 +2673,7 @@ static int patch_stac922x(struct hda_codec *codec)
spec->adc_nids = stac922x_adc_nids;
spec->mux_nids = stac922x_mux_nids;
spec->num_muxes = ARRAY_SIZE(stac922x_mux_nids);
+ spec->num_adcs = ARRAY_SIZE(stac922x_adc_nids);
spec->num_dmics = 0;
spec->init = stac922x_core_init;
@@ -2224,22 +2742,25 @@ static int patch_stac927x(struct hda_codec *codec)
spec->adc_nids = stac927x_adc_nids;
spec->mux_nids = stac927x_mux_nids;
spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids);
+ spec->num_adcs = ARRAY_SIZE(stac927x_adc_nids);
spec->num_dmics = 0;
spec->init = d965_core_init;
- spec->mixer = stac9227_mixer;
+ spec->mixer = stac927x_mixer;
break;
case STAC_D965_5ST:
spec->adc_nids = stac927x_adc_nids;
spec->mux_nids = stac927x_mux_nids;
spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids);
+ spec->num_adcs = ARRAY_SIZE(stac927x_adc_nids);
spec->num_dmics = 0;
spec->init = d965_core_init;
- spec->mixer = stac9227_mixer;
+ spec->mixer = stac927x_mixer;
break;
default:
spec->adc_nids = stac927x_adc_nids;
spec->mux_nids = stac927x_mux_nids;
spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids);
+ spec->num_adcs = ARRAY_SIZE(stac927x_adc_nids);
spec->num_dmics = 0;
spec->init = stac927x_core_init;
spec->mixer = stac927x_mixer;
@@ -2247,7 +2768,8 @@ static int patch_stac927x(struct hda_codec *codec)
spec->multiout.dac_nids = spec->dac_nids;
/* GPIO0 High = Enable EAPD */
- stac92xx_enable_gpio_mask(codec, 0x00000001, 0x00000001);
+ spec->gpio_mask = spec->gpio_data = 0x00000001;
+ stac92xx_enable_gpio_mask(codec);
err = stac92xx_parse_auto_config(codec, 0x1e, 0x20);
if (!err) {
@@ -2272,7 +2794,7 @@ static int patch_stac927x(struct hda_codec *codec)
static int patch_stac9205(struct hda_codec *codec)
{
struct sigmatel_spec *spec;
- int err, gpio_mask, gpio_data;
+ int err;
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
@@ -2299,10 +2821,11 @@ static int patch_stac9205(struct hda_codec *codec)
}
spec->adc_nids = stac9205_adc_nids;
+ spec->num_adcs = ARRAY_SIZE(stac9205_adc_nids);
spec->mux_nids = stac9205_mux_nids;
spec->num_muxes = ARRAY_SIZE(stac9205_mux_nids);
spec->dmic_nids = stac9205_dmic_nids;
- spec->num_dmics = ARRAY_SIZE(stac9205_dmic_nids);
+ spec->num_dmics = STAC9205_NUM_DMICS;
spec->dmux_nid = 0x1d;
spec->init = stac9205_core_init;
@@ -2310,20 +2833,25 @@ static int patch_stac9205(struct hda_codec *codec)
spec->multiout.dac_nids = spec->dac_nids;
- if (spec->board_config == STAC_M43xx) {
+ switch (spec->board_config){
+ case STAC_9205_DELL_M43:
/* Enable SPDIF in/out */
stac92xx_set_config_reg(codec, 0x1f, 0x01441030);
stac92xx_set_config_reg(codec, 0x20, 0x1c410030);
- gpio_mask = 0x00000007; /* GPIO0-2 */
+ spec->gpio_mask = 0x00000007; /* GPIO0-2 */
/* GPIO0 High = EAPD, GPIO1 Low = DRM,
* GPIO2 High = Headphone Mute
*/
- gpio_data = 0x00000005;
- } else
- gpio_mask = gpio_data = 0x00000001; /* GPIO0 High = EAPD */
+ spec->gpio_data = 0x00000005;
+ break;
+ default:
+ /* GPIO0 High = EAPD */
+ spec->gpio_mask = spec->gpio_data = 0x00000001;
+ break;
+ }
- stac92xx_enable_gpio_mask(codec, gpio_mask, gpio_data);
+ stac92xx_enable_gpio_mask(codec);
err = stac92xx_parse_auto_config(codec, 0x1f, 0x20);
if (!err) {
if (spec->board_config < 0) {
@@ -2355,7 +2883,7 @@ static hda_nid_t vaio_adcs[] = { 0x8 /*,0x6*/ };
static hda_nid_t vaio_mux_nids[] = { 0x15 };
static struct hda_input_mux vaio_mux = {
- .num_items = 2,
+ .num_items = 3,
.items = {
/* { "HP", 0x0 }, */
{ "Mic Jack", 0x1 },
@@ -2366,6 +2894,7 @@ static struct hda_input_mux vaio_mux = {
static struct hda_verb vaio_init[] = {
{0x0a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP <- 0x2 */
+ {0x0a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | STAC_HP_EVENT},
{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Speaker <- 0x5 */
{0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? (<- 0x2) */
{0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */
@@ -2397,61 +2926,28 @@ static struct hda_verb vaio_ar_init[] = {
};
/* bind volumes of both NID 0x02 and 0x05 */
-static int vaio_master_vol_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- long *valp = ucontrol->value.integer.value;
- int change;
-
- change = snd_hda_codec_amp_update(codec, 0x02, 0, HDA_OUTPUT, 0,
- 0x7f, valp[0] & 0x7f);
- change |= snd_hda_codec_amp_update(codec, 0x02, 1, HDA_OUTPUT, 0,
- 0x7f, valp[1] & 0x7f);
- snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0,
- 0x7f, valp[0] & 0x7f);
- snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0,
- 0x7f, valp[1] & 0x7f);
- return change;
-}
+static struct hda_bind_ctls vaio_bind_master_vol = {
+ .ops = &snd_hda_bind_vol,
+ .values = {
+ HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
+ HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
+ 0
+ },
+};
/* bind volumes of both NID 0x02 and 0x05 */
-static int vaio_master_sw_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- long *valp = ucontrol->value.integer.value;
- int change;
-
- change = snd_hda_codec_amp_update(codec, 0x02, 0, HDA_OUTPUT, 0,
- 0x80, (valp[0] ? 0 : 0x80));
- change |= snd_hda_codec_amp_update(codec, 0x02, 1, HDA_OUTPUT, 0,
- 0x80, (valp[1] ? 0 : 0x80));
- snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0,
- 0x80, (valp[0] ? 0 : 0x80));
- snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0,
- 0x80, (valp[1] ? 0 : 0x80));
- return change;
-}
+static struct hda_bind_ctls vaio_bind_master_sw = {
+ .ops = &snd_hda_bind_sw,
+ .values = {
+ HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
+ HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
+ 0,
+ },
+};
static struct snd_kcontrol_new vaio_mixer[] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Master Playback Volume",
- .info = snd_hda_mixer_amp_volume_info,
- .get = snd_hda_mixer_amp_volume_get,
- .put = vaio_master_vol_put,
- .tlv = { .c = snd_hda_mixer_amp_tlv },
- .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Master Playback Switch",
- .info = snd_hda_mixer_amp_switch_info,
- .get = snd_hda_mixer_amp_switch_get,
- .put = vaio_master_sw_put,
- .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
- },
+ HDA_BIND_VOL("Master Playback Volume", &vaio_bind_master_vol),
+ HDA_BIND_SW("Master Playback Switch", &vaio_bind_master_sw),
/* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */
HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT),
@@ -2467,22 +2963,8 @@ static struct snd_kcontrol_new vaio_mixer[] = {
};
static struct snd_kcontrol_new vaio_ar_mixer[] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Master Playback Volume",
- .info = snd_hda_mixer_amp_volume_info,
- .get = snd_hda_mixer_amp_volume_get,
- .put = vaio_master_vol_put,
- .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Master Playback Switch",
- .info = snd_hda_mixer_amp_switch_info,
- .get = snd_hda_mixer_amp_switch_get,
- .put = vaio_master_sw_put,
- .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
- },
+ HDA_BIND_VOL("Master Playback Volume", &vaio_bind_master_vol),
+ HDA_BIND_SW("Master Playback Switch", &vaio_bind_master_sw),
/* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */
HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT),
@@ -2504,6 +2986,49 @@ static struct hda_codec_ops stac9872_patch_ops = {
.build_pcms = stac92xx_build_pcms,
.init = stac92xx_init,
.free = stac92xx_free,
+#ifdef SND_HDA_NEEDS_RESUME
+ .resume = stac92xx_resume,
+#endif
+};
+
+static int stac9872_vaio_init(struct hda_codec *codec)
+{
+ int err;
+
+ err = stac92xx_init(codec);
+ if (err < 0)
+ return err;
+ if (codec->patch_ops.unsol_event)
+ codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
+ return 0;
+}
+
+static void stac9872_vaio_hp_detect(struct hda_codec *codec, unsigned int res)
+{
+ if (get_pin_presence(codec, 0x0a)) {
+ stac92xx_reset_pinctl(codec, 0x0f, AC_PINCTL_OUT_EN);
+ stac92xx_set_pinctl(codec, 0x0a, AC_PINCTL_OUT_EN);
+ } else {
+ stac92xx_reset_pinctl(codec, 0x0a, AC_PINCTL_OUT_EN);
+ stac92xx_set_pinctl(codec, 0x0f, AC_PINCTL_OUT_EN);
+ }
+}
+
+static void stac9872_vaio_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+ switch (res >> 26) {
+ case STAC_HP_EVENT:
+ stac9872_vaio_hp_detect(codec, res);
+ break;
+ }
+}
+
+static struct hda_codec_ops stac9872_vaio_patch_ops = {
+ .build_controls = stac92xx_build_controls,
+ .build_pcms = stac92xx_build_pcms,
+ .init = stac9872_vaio_init,
+ .free = stac92xx_free,
+ .unsol_event = stac9872_vaio_unsol_event,
#ifdef CONFIG_PM
.resume = stac92xx_resume,
#endif
@@ -2564,6 +3089,7 @@ static int patch_stac9872(struct hda_codec *codec)
spec->adc_nids = vaio_adcs;
spec->input_mux = &vaio_mux;
spec->mux_nids = vaio_mux_nids;
+ codec->patch_ops = stac9872_vaio_patch_ops;
break;
case CXD9872AKD_VAIO:
@@ -2577,10 +3103,10 @@ static int patch_stac9872(struct hda_codec *codec)
spec->adc_nids = vaio_adcs;
spec->input_mux = &vaio_mux;
spec->mux_nids = vaio_mux_nids;
+ codec->patch_ops = stac9872_patch_ops;
break;
}
- codec->patch_ops = stac9872_patch_ops;
return 0;
}
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index ba32d1e52cb8..4cdf3e6df4ba 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -114,7 +114,11 @@ struct via_spec {
unsigned int num_kctl_alloc, num_kctl_used;
struct snd_kcontrol_new *kctl_alloc;
struct hda_input_mux private_imux;
- hda_nid_t private_dac_nids[4];
+ hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
+
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ struct hda_loopback_check loopback;
+#endif
};
static hda_nid_t vt1708_adc_nids[2] = {
@@ -305,15 +309,15 @@ static struct hda_verb vt1708_volume_init_verbs[] = {
{0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
+ /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
* mixer widget
*/
/* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* master */
+ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
/*
* Set up output mixers (0x19 - 0x1b)
@@ -543,24 +547,11 @@ static int via_init(struct hda_codec *codec)
return 0;
}
-#ifdef CONFIG_PM
-/*
- * resume
- */
-static int via_resume(struct hda_codec *codec)
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid)
{
struct via_spec *spec = codec->spec;
- int i;
-
- via_init(codec);
- for (i = 0; i < spec->num_mixers; i++)
- snd_hda_resume_ctls(codec, spec->mixers[i]);
- if (spec->multiout.dig_out_nid)
- snd_hda_resume_spdif_out(codec);
- if (spec->dig_in_nid)
- snd_hda_resume_spdif_in(codec);
-
- return 0;
+ return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
}
#endif
@@ -571,8 +562,8 @@ static struct hda_codec_ops via_patch_ops = {
.build_pcms = via_build_pcms,
.init = via_init,
.free = via_free,
-#ifdef CONFIG_PM
- .resume = via_resume,
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ .check_power_status = via_check_power_status,
#endif
};
@@ -762,6 +753,16 @@ static int vt1708_auto_create_analog_input_ctls(struct via_spec *spec,
return 0;
}
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static struct hda_amp_list vt1708_loopbacks[] = {
+ { 0x17, HDA_INPUT, 1 },
+ { 0x17, HDA_INPUT, 2 },
+ { 0x17, HDA_INPUT, 3 },
+ { 0x17, HDA_INPUT, 4 },
+ { } /* end */
+};
+#endif
+
static int vt1708_parse_auto_config(struct hda_codec *codec)
{
struct via_spec *spec = codec->spec;
@@ -855,6 +856,9 @@ static int patch_vt1708(struct hda_codec *codec)
codec->patch_ops = via_patch_ops;
codec->patch_ops.init = via_auto_init;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ spec->loopback.amplist = vt1708_loopbacks;
+#endif
return 0;
}
@@ -895,15 +899,15 @@ static struct hda_verb vt1709_10ch_volume_init_verbs[] = {
{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
+ /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
* mixer widget
*/
/* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* unmute master */
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
/*
* Set up output selector (0x1a, 0x1b, 0x29)
@@ -1251,6 +1255,16 @@ static int vt1709_parse_auto_config(struct hda_codec *codec)
return 1;
}
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static struct hda_amp_list vt1709_loopbacks[] = {
+ { 0x18, HDA_INPUT, 1 },
+ { 0x18, HDA_INPUT, 2 },
+ { 0x18, HDA_INPUT, 3 },
+ { 0x18, HDA_INPUT, 4 },
+ { } /* end */
+};
+#endif
+
static int patch_vt1709_10ch(struct hda_codec *codec)
{
struct via_spec *spec;
@@ -1293,6 +1307,9 @@ static int patch_vt1709_10ch(struct hda_codec *codec)
codec->patch_ops = via_patch_ops;
codec->patch_ops.init = via_auto_init;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ spec->loopback.amplist = vt1709_loopbacks;
+#endif
return 0;
}
@@ -1383,6 +1400,9 @@ static int patch_vt1709_6ch(struct hda_codec *codec)
codec->patch_ops = via_patch_ops;
codec->patch_ops.init = via_auto_init;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ spec->loopback.amplist = vt1709_loopbacks;
+#endif
return 0;
}
diff --git a/sound/pci/ice1712/Makefile b/sound/pci/ice1712/Makefile
index 6efdd62f6837..65ce66adba5a 100644
--- a/sound/pci/ice1712/Makefile
+++ b/sound/pci/ice1712/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
snd-ice17xx-ak4xxx-objs := ak4xxx.o
diff --git a/sound/pci/ice1712/ak4xxx.c b/sound/pci/ice1712/ak4xxx.c
index ab00cce2c39f..a1aba0d7d0e4 100644
--- a/sound/pci/ice1712/ak4xxx.c
+++ b/sound/pci/ice1712/ak4xxx.c
@@ -3,7 +3,7 @@
*
* AK4524 / AK4528 / AK4529 / AK4355 / AK4381 interface
*
- * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz>
*
* 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
@@ -30,7 +30,7 @@
#include <sound/initval.h>
#include "ice1712.h"
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("ICEnsemble ICE17xx <-> AK4xxx AD/DA chip interface");
MODULE_LICENSE("GPL");
diff --git a/sound/pci/ice1712/amp.c b/sound/pci/ice1712/amp.c
index 44bbb630b949..6e13d758bb5d 100644
--- a/sound/pci/ice1712/amp.c
+++ b/sound/pci/ice1712/amp.c
@@ -3,7 +3,7 @@
*
* Lowlevel functions for Advanced Micro Peripherals Ltd AUDIO2000
*
- * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz>
*
* 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
diff --git a/sound/pci/ice1712/amp.h b/sound/pci/ice1712/amp.h
index a0fc89b48122..bf81d30d9150 100644
--- a/sound/pci/ice1712/amp.h
+++ b/sound/pci/ice1712/amp.h
@@ -6,7 +6,7 @@
*
* Lowlevel functions for Advanced Micro Peripherals Ltd AUDIO2000
*
- * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz>
*
* 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
diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c
index 66bacde1ead3..ec0699c89952 100644
--- a/sound/pci/ice1712/aureon.c
+++ b/sound/pci/ice1712/aureon.c
@@ -394,7 +394,7 @@ static int aureon_ac97_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ele
/*
* AC'97 mute controls
*/
-#define aureon_ac97_mute_info aureon_mono_bool_info
+#define aureon_ac97_mute_info snd_ctl_boolean_mono_info
static int aureon_ac97_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -430,7 +430,7 @@ static int aureon_ac97_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el
/*
* AC'97 mute controls
*/
-#define aureon_ac97_micboost_info aureon_mono_bool_info
+#define aureon_ac97_micboost_info snd_ctl_boolean_mono_info
static int aureon_ac97_micboost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -621,19 +621,12 @@ static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
/*
*/
-static int aureon_mono_bool_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define aureon_mono_bool_info snd_ctl_boolean_mono_info
/*
* AC'97 master playback mute controls (Mute on WM8770 chip)
*/
-#define aureon_ac97_mmute_info aureon_mono_bool_info
+#define aureon_ac97_mmute_info snd_ctl_boolean_mono_info
static int aureon_ac97_mmute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -708,7 +701,7 @@ static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned sho
/*
* DAC mute control
*/
-#define wm_pcm_mute_info aureon_mono_bool_info
+#define wm_pcm_mute_info snd_ctl_boolean_mono_info
static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -879,13 +872,7 @@ static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value
/*
* WM8770 master mute control
*/
-static int wm_master_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 2;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define wm_master_mute_info snd_ctl_boolean_stereo_info
static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -969,14 +956,7 @@ static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val
/*
* ADC mute control
*/
-static int wm_adc_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 2;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define wm_adc_mute_info snd_ctl_boolean_stereo_info
static int wm_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -1210,12 +1190,7 @@ static int aureon_cs8415_rate_get (struct snd_kcontrol *kcontrol, struct snd_ctl
/*
* CS8415A Mute
*/
-static int aureon_cs8415_mute_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- return 0;
-}
+#define aureon_cs8415_mute_info snd_ctl_boolean_mono_info
static int aureon_cs8415_mute_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -1316,7 +1291,7 @@ static int aureon_get_headphone_amp(struct snd_ice1712 *ice)
return ( tmp & AUREON_HP_SEL )!= 0;
}
-#define aureon_hpamp_info aureon_mono_bool_info
+#define aureon_hpamp_info snd_ctl_boolean_mono_info
static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -1338,7 +1313,7 @@ static int aureon_hpamp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v
* Deemphasis
*/
-#define aureon_deemp_info aureon_mono_bool_info
+#define aureon_deemp_info snd_ctl_boolean_mono_info
static int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
diff --git a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c
index af659800c9b0..371f78461db4 100644
--- a/sound/pci/ice1712/delta.c
+++ b/sound/pci/ice1712/delta.c
@@ -4,7 +4,7 @@
* Lowlevel functions for M-Audio Delta 1010, 44, 66, Dio2496, Audiophile
* Digigram VX442
*
- * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz>
*
* 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
@@ -393,15 +393,8 @@ static void delta_setup_spdif(struct snd_ice1712 *ice, int rate)
snd_ice1712_delta_cs8403_spdif_write(ice, tmp);
}
-static int snd_ice1712_delta1010lt_wordclock_status_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_ice1712_delta1010lt_wordclock_status_info \
+ snd_ctl_boolean_mono_info
static int snd_ice1712_delta1010lt_wordclock_status_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
diff --git a/sound/pci/ice1712/delta.h b/sound/pci/ice1712/delta.h
index 2697156607e4..26ea05a32f56 100644
--- a/sound/pci/ice1712/delta.h
+++ b/sound/pci/ice1712/delta.h
@@ -7,7 +7,7 @@
* Lowlevel functions for M-Audio Delta 1010, 44, 66, Dio2496, Audiophile
* Digigram VX442
*
- * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz>
*
* 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
diff --git a/sound/pci/ice1712/envy24ht.h b/sound/pci/ice1712/envy24ht.h
index b58afcda9ed6..43b9e3e858be 100644
--- a/sound/pci/ice1712/envy24ht.h
+++ b/sound/pci/ice1712/envy24ht.h
@@ -4,7 +4,7 @@
/*
* ALSA driver for ICEnsemble VT1724 (Envy24)
*
- * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz>
*
* 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
diff --git a/sound/pci/ice1712/ews.c b/sound/pci/ice1712/ews.c
index b135389fec6c..75e4e5e0f1e4 100644
--- a/sound/pci/ice1712/ews.c
+++ b/sound/pci/ice1712/ews.c
@@ -3,7 +3,7 @@
*
* Lowlevel functions for Terratec EWS88MT/D, EWX24/96, DMX 6Fire
*
- * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz>
* 2002 Takashi Iwai <tiwai@suse.de>
*
* This program is free software; you can redistribute it and/or modify
@@ -700,14 +700,7 @@ static struct snd_kcontrol_new snd_ice1712_ews88mt_output_sense __devinitdata =
* EWS88D specific controls
*/
-static int snd_ice1712_ews88d_control_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_ice1712_ews88d_control_info snd_ctl_boolean_mono_info
static int snd_ice1712_ews88d_control_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -812,14 +805,7 @@ static int snd_ice1712_6fire_write_pca(struct snd_ice1712 *ice, unsigned char re
return 0;
}
-static int snd_ice1712_6fire_control_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_ice1712_6fire_control_info snd_ctl_boolean_mono_info
static int snd_ice1712_6fire_control_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
diff --git a/sound/pci/ice1712/ews.h b/sound/pci/ice1712/ews.h
index a12a0b053558..e4ed1b475b08 100644
--- a/sound/pci/ice1712/ews.h
+++ b/sound/pci/ice1712/ews.h
@@ -6,7 +6,7 @@
*
* Lowlevel functions for Terratec EWS88MT/D, EWX24/96, DMX 6Fire
*
- * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz>
* 2002 Takashi Iwai <tiwai@suse.de>
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/pci/ice1712/hoontech.c b/sound/pci/ice1712/hoontech.c
index 8203562ef7e7..abcfd1da6587 100644
--- a/sound/pci/ice1712/hoontech.c
+++ b/sound/pci/ice1712/hoontech.c
@@ -3,7 +3,7 @@
*
* Lowlevel functions for Hoontech STDSP24
*
- * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz>
*
* 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
diff --git a/sound/pci/ice1712/hoontech.h b/sound/pci/ice1712/hoontech.h
index 1ee538b20fbf..cc1da1e69ad1 100644
--- a/sound/pci/ice1712/hoontech.h
+++ b/sound/pci/ice1712/hoontech.h
@@ -6,7 +6,7 @@
*
* Lowlevel functions for Hoontech STDSP24
*
- * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz>
*
* 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
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index 6630a0ae9527..052fc3cb3272 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -1,7 +1,7 @@
/*
* ALSA driver for ICEnsemble ICE1712 (Envy24)
*
- * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz>
*
* 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
@@ -73,7 +73,7 @@
#include "ews.h"
#include "hoontech.h"
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("ICEnsemble ICE1712 (Envy24)");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{"
@@ -256,14 +256,7 @@ static unsigned short snd_ice1712_pro_ac97_read(struct snd_ac97 *ac97,
/*
* consumer ac97 digital mix
*/
-static int snd_ice1712_digmix_route_ac97_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_ice1712_digmix_route_ac97_info snd_ctl_boolean_mono_info
static int snd_ice1712_digmix_route_ac97_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -1300,14 +1293,7 @@ static void snd_ice1712_update_volume(struct snd_ice1712 *ice, int index)
outw(val, ICEMT(ice, MONITOR_VOLUME));
}
-static int snd_ice1712_pro_mixer_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 2;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_ice1712_pro_mixer_switch_info snd_ctl_boolean_stereo_info
static int snd_ice1712_pro_mixer_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -1759,16 +1745,6 @@ static struct snd_kcontrol_new snd_ice1712_spdif_stream __devinitdata =
.put = snd_ice1712_spdif_stream_put
};
-int snd_ice1712_gpio_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
-
int snd_ice1712_gpio_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -1968,15 +1944,7 @@ static struct snd_kcontrol_new snd_ice1712_pro_internal_clock_default __devinitd
.put = snd_ice1712_pro_internal_clock_default_put
};
-static int snd_ice1712_pro_rate_locking_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_ice1712_pro_rate_locking_info snd_ctl_boolean_mono_info
static int snd_ice1712_pro_rate_locking_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -2007,15 +1975,7 @@ static struct snd_kcontrol_new snd_ice1712_pro_rate_locking __devinitdata = {
.put = snd_ice1712_pro_rate_locking_put
};
-static int snd_ice1712_pro_rate_reset_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_ice1712_pro_rate_reset_info snd_ctl_boolean_mono_info
static int snd_ice1712_pro_rate_reset_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h
index 6ac486d9c138..58640afa5404 100644
--- a/sound/pci/ice1712/ice1712.h
+++ b/sound/pci/ice1712/ice1712.h
@@ -4,7 +4,7 @@
/*
* ALSA driver for ICEnsemble ICE1712 (Envy24)
*
- * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz>
*
* 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
@@ -451,11 +451,10 @@ static inline void snd_ice1712_restore_gpio_status(struct snd_ice1712 *ice)
/* for bit controls */
#define ICE1712_GPIO(xiface, xname, xindex, mask, invert, xaccess) \
-{ .iface = xiface, .name = xname, .access = xaccess, .info = snd_ice1712_gpio_info, \
+{ .iface = xiface, .name = xname, .access = xaccess, .info = snd_ctl_boolean_mono_info, \
.get = snd_ice1712_gpio_get, .put = snd_ice1712_gpio_put, \
.private_value = mask | (invert << 24) }
-int snd_ice1712_gpio_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo);
int snd_ice1712_gpio_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
int snd_ice1712_gpio_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index ee620dea7ef3..0b0bbb0d96b9 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -2,7 +2,7 @@
* ALSA driver for VT1724 ICEnsemble ICE1724 / VIA VT1724 (Envy24HT)
* VIA VT1720 (Envy24PT)
*
- * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz>
* 2002 James Stafford <jstafford@ampltd.com>
* 2003 Takashi Iwai <tiwai@suse.de>
*
@@ -52,7 +52,7 @@
#include "phase.h"
#include "wtm.h"
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("VIA ICEnsemble ICE1724/1720 (Envy24HT/PT)");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{"
@@ -341,10 +341,12 @@ static int snd_vt1724_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
what = 0;
snd_pcm_group_for_each_entry(s, substream) {
- const struct vt1724_pcm_reg *reg;
- reg = s->runtime->private_data;
- what |= reg->start;
- snd_pcm_trigger_done(s, substream);
+ if (snd_pcm_substream_chip(s) == ice) {
+ const struct vt1724_pcm_reg *reg;
+ reg = s->runtime->private_data;
+ what |= reg->start;
+ snd_pcm_trigger_done(s, substream);
+ }
}
switch (cmd) {
@@ -1479,15 +1481,7 @@ static struct snd_kcontrol_new snd_vt1724_spdif_maskp __devinitdata =
.get = snd_vt1724_spdif_maskp_get,
};
-static int snd_vt1724_spdif_sw_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_vt1724_spdif_sw_info snd_ctl_boolean_mono_info
static int snd_vt1724_spdif_sw_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -1532,15 +1526,7 @@ static struct snd_kcontrol_new snd_vt1724_spdif_switch __devinitdata =
* GPIO access from extern
*/
-int snd_vt1724_gpio_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_vt1724_gpio_info snd_ctl_boolean_mono_info
int snd_vt1724_gpio_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -1706,15 +1692,7 @@ static struct snd_kcontrol_new snd_vt1724_pro_internal_clock __devinitdata = {
.put = snd_vt1724_pro_internal_clock_put
};
-static int snd_vt1724_pro_rate_locking_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_vt1724_pro_rate_locking_info snd_ctl_boolean_mono_info
static int snd_vt1724_pro_rate_locking_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -1745,15 +1723,7 @@ static struct snd_kcontrol_new snd_vt1724_pro_rate_locking __devinitdata = {
.put = snd_vt1724_pro_rate_locking_put
};
-static int snd_vt1724_pro_rate_reset_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_vt1724_pro_rate_reset_info snd_ctl_boolean_mono_info
static int snd_vt1724_pro_rate_reset_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c
index 3d8e74e493d7..1fbe3ef8e60a 100644
--- a/sound/pci/ice1712/juli.c
+++ b/sound/pci/ice1712/juli.c
@@ -3,7 +3,7 @@
*
* Lowlevel functions for ESI Juli@ cards
*
- * Copyright (c) 2004 Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 2004 Jaroslav Kysela <perex@perex.cz>
*
* 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
diff --git a/sound/pci/ice1712/phase.c b/sound/pci/ice1712/phase.c
index 40a9098af777..3ac25058bb58 100644
--- a/sound/pci/ice1712/phase.c
+++ b/sound/pci/ice1712/phase.c
@@ -270,7 +270,7 @@ static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned sho
/*
* DAC mute control
*/
-#define wm_pcm_mute_info phase28_mono_bool_info
+#define wm_pcm_mute_info snd_ctl_boolean_mono_info
static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -527,13 +527,7 @@ static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value
/*
* WM8770 master mute control
*/
-static int wm_master_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 2;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define wm_master_mute_info snd_ctl_boolean_stereo_info
static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -615,20 +609,9 @@ static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val
}
/*
- */
-static int phase28_mono_bool_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
-
-/*
* Deemphasis
*/
-#define phase28_deemp_info phase28_mono_bool_info
+#define phase28_deemp_info snd_ctl_boolean_mono_info
static int phase28_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
diff --git a/sound/pci/ice1712/pontis.c b/sound/pci/ice1712/pontis.c
index 01c69453ddeb..faefd52c1b80 100644
--- a/sound/pci/ice1712/pontis.c
+++ b/sound/pci/ice1712/pontis.c
@@ -216,14 +216,7 @@ static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val
/*
* ADC input mux mixer control
*/
-static int wm_adc_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define wm_adc_mux_info snd_ctl_boolean_mono_info
static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -260,14 +253,7 @@ static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val
/*
* Analog bypass (In -> Out)
*/
-static int wm_bypass_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define wm_bypass_info snd_ctl_boolean_mono_info
static int wm_bypass_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -302,14 +288,7 @@ static int wm_bypass_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu
/*
* Left/Right swap
*/
-static int wm_chswap_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define wm_chswap_info snd_ctl_boolean_mono_info
static int wm_chswap_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
diff --git a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c
index 4bae7305a79b..4180f9739ecb 100644
--- a/sound/pci/ice1712/prodigy192.c
+++ b/sound/pci/ice1712/prodigy192.c
@@ -81,14 +81,7 @@ static inline unsigned char stac9460_get(struct snd_ice1712 *ice, int reg)
/*
* DAC mute control
*/
-static int stac9460_dac_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define stac9460_dac_mute_info snd_ctl_boolean_mono_info
static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -177,14 +170,7 @@ static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el
/*
* ADC mute control
*/
-static int stac9460_adc_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 2;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define stac9460_adc_mute_info snd_ctl_boolean_stereo_info
static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -292,14 +278,7 @@ static int aureon_get_headphone_amp(struct snd_ice1712 *ice)
return ( tmp & AUREON_HP_SEL )!= 0;
}
-static int aureon_bool_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define aureon_bool_info snd_ctl_boolean_mono_info
static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
diff --git a/sound/pci/ice1712/wtm.c b/sound/pci/ice1712/wtm.c
index 04e535c8542b..7fcce0a506d6 100644
--- a/sound/pci/ice1712/wtm.c
+++ b/sound/pci/ice1712/wtm.c
@@ -71,14 +71,7 @@ static inline unsigned char stac9460_2_get(struct snd_ice1712 *ice, int reg)
/*
* DAC mute control
*/
-static int stac9460_dac_mute_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- return 0;
-}
+#define stac9460_dac_mute_info snd_ctl_boolean_mono_info
static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -218,15 +211,7 @@ static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol,
/*
* ADC mute control
*/
-static int stac9460_adc_mute_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 2;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define stac9460_adc_mute_info snd_ctl_boolean_stereo_info
static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -357,15 +342,7 @@ static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol,
* MIC / LINE switch fonction
*/
-static int stac9460_mic_sw_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define stac9460_mic_sw_info snd_ctl_boolean_mono_info
static int stac9460_mic_sw_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index da9734073dba..b4a38a3d855b 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -1,7 +1,7 @@
/*
* ALSA driver for Intel ICH (i8x0) chipsets
*
- * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz>
*
*
* This code also contains alpha support for SiS 735 chipsets provided
@@ -43,7 +43,7 @@
#include <asm/pgtable.h>
#include <asm/cacheflush.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; SiS 7012; Ali 5455");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Intel,82801AA-ICH},"
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index c155e1f3a0e5..fad806e60f36 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -1,7 +1,7 @@
/*
* ALSA modem driver for Intel ICH (i8x0) chipsets
*
- * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz>
*
* This is modified (by Sasha Khapyorsky <sashak@alsa-project.org>) version
* of ALSA ICH sound driver intel8x0.c .
@@ -37,7 +37,7 @@
#include <sound/info.h>
#include <sound/initval.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; "
"SiS 7013; NVidia MCP/2/2S/3 modems");
MODULE_LICENSE("GPL");
diff --git a/sound/pci/korg1212/Makefile b/sound/pci/korg1212/Makefile
index 78c9dc6eeb2d..f11ce1b1b3d4 100644
--- a/sound/pci/korg1212/Makefile
+++ b/sound/pci/korg1212/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
snd-korg1212-objs := korg1212.o
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index 5338243fb035..c4af57fb5af1 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -1391,8 +1391,6 @@ static int snd_korg1212_playback_open(struct snd_pcm_substream *substream)
K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_playback_open [%s]\n",
stateName[korg1212->cardState]);
- snd_pcm_set_sync(substream); // ???
-
snd_korg1212_OpenCard(korg1212);
runtime->hw = snd_korg1212_playback_info;
@@ -1422,8 +1420,6 @@ static int snd_korg1212_capture_open(struct snd_pcm_substream *substream)
K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_capture_open [%s]\n",
stateName[korg1212->cardState]);
- snd_pcm_set_sync(substream);
-
snd_korg1212_OpenCard(korg1212);
runtime->hw = snd_korg1212_capture_info;
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 8a5ff1cb5362..32245770595e 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -1821,7 +1821,6 @@ snd_m3_playback_open(struct snd_pcm_substream *subs)
return err;
runtime->hw = snd_m3_playback;
- snd_pcm_set_sync(subs);
return 0;
}
@@ -1846,7 +1845,6 @@ snd_m3_capture_open(struct snd_pcm_substream *subs)
return err;
runtime->hw = snd_m3_capture;
- snd_pcm_set_sync(subs);
return 0;
}
diff --git a/sound/pci/mixart/Makefile b/sound/pci/mixart/Makefile
index fe6ba0c4b567..cce159ec5624 100644
--- a/sound/pci/mixart/Makefile
+++ b/sound/pci/mixart/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
snd-mixart-objs := mixart.o mixart_core.o mixart_hwdep.o mixart_mixer.o
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
index ac007cec0879..880b824e24cd 100644
--- a/sound/pci/mixart/mixart.c
+++ b/sound/pci/mixart/mixart.c
@@ -652,7 +652,7 @@ static int snd_mixart_hw_free(struct snd_pcm_substream *subs)
static struct snd_pcm_hardware snd_mixart_analog_caps =
{
.info = ( SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |
+ SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_PAUSE),
.formats = ( SNDRV_PCM_FMTBIT_U8 |
SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
@@ -673,7 +673,7 @@ static struct snd_pcm_hardware snd_mixart_analog_caps =
static struct snd_pcm_hardware snd_mixart_digital_caps =
{
.info = ( SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |
+ SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_PAUSE),
.formats = ( SNDRV_PCM_FMTBIT_U8 |
SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
@@ -1317,6 +1317,12 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci,
mgr->mem[i].phys = pci_resource_start(pci, i);
mgr->mem[i].virt = ioremap_nocache(mgr->mem[i].phys,
pci_resource_len(pci, i));
+ if (!mgr->mem[i].virt) {
+ printk(KERN_ERR "unable to remap resource 0x%lx\n",
+ mgr->mem[i].phys);
+ snd_mixart_free(mgr);
+ return -EBUSY;
+ }
}
if (request_irq(pci->irq, snd_mixart_interrupt, IRQF_SHARED,
diff --git a/sound/pci/mixart/mixart_mixer.c b/sound/pci/mixart/mixart_mixer.c
index d7d15c036e02..0e16512d25f7 100644
--- a/sound/pci/mixart/mixart_mixer.c
+++ b/sound/pci/mixart/mixart_mixer.c
@@ -403,14 +403,7 @@ static struct snd_kcontrol_new mixart_control_analog_level = {
};
/* shared */
-static int mixart_sw_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 2;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define mixart_sw_info snd_ctl_boolean_stereo_info
static int mixart_audio_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
diff --git a/sound/pci/nm256/Makefile b/sound/pci/nm256/Makefile
index d91d8c519212..a1bd44ff850e 100644
--- a/sound/pci/nm256/Makefile
+++ b/sound/pci/nm256/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
snd-nm256-objs := nm256.o
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
index c7621bd770a6..276c5763f0e5 100644
--- a/sound/pci/nm256/nm256.c
+++ b/sound/pci/nm256/nm256.c
@@ -842,7 +842,6 @@ static void snd_nm256_setup_stream(struct nm256 *chip, struct nm256_stream *s,
runtime->private_data = s;
s->substream = substream;
- snd_pcm_set_sync(substream);
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
&constraints_rates);
}
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c
index f7f6a687f033..2d618bd7e62b 100644
--- a/sound/pci/pcxhr/pcxhr.c
+++ b/sound/pci/pcxhr/pcxhr.c
@@ -646,6 +646,8 @@ static int pcxhr_trigger(struct snd_pcm_substream *subs, int cmd)
if (snd_pcm_stream_linked(subs)) {
struct snd_pcxhr *chip = snd_pcm_substream_chip(subs);
snd_pcm_group_for_each_entry(s, subs) {
+ if (snd_pcm_substream_chip(s) != chip)
+ continue;
stream = s->runtime->private_data;
stream->status =
PCXHR_STREAM_STATUS_SCHEDULE_RUN;
@@ -662,6 +664,7 @@ static int pcxhr_trigger(struct snd_pcm_substream *subs, int cmd)
if (pcxhr_update_r_buffer(stream))
return -EINVAL;
+ stream->status = PCXHR_STREAM_STATUS_SCHEDULE_RUN;
if (pcxhr_set_stream_state(stream))
return -EINVAL;
stream->status = PCXHR_STREAM_STATUS_RUNNING;
@@ -902,6 +905,8 @@ static int pcxhr_open(struct snd_pcm_substream *subs)
snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4);
snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4);
+ snd_pcm_set_sync(subs);
+
mgr->ref_count_rate++;
mutex_unlock(&mgr->setup_mutex);
diff --git a/sound/pci/pcxhr/pcxhr_mixer.c b/sound/pci/pcxhr/pcxhr_mixer.c
index d9cc8d2beb6d..5f8d42633b04 100644
--- a/sound/pci/pcxhr/pcxhr_mixer.c
+++ b/sound/pci/pcxhr/pcxhr_mixer.c
@@ -44,8 +44,8 @@
#define PCXHR_ANALOG_PLAYBACK_LEVEL_MAX 128 /* 0.0 dB */
#define PCXHR_ANALOG_PLAYBACK_ZERO_LEVEL 104 /* -24.0 dB ( 0.0 dB - fix level +24.0 dB ) */
-static const DECLARE_TLV_DB_SCALE(db_scale_analog_capture, -9600, 50, 0);
-static const DECLARE_TLV_DB_SCALE(db_scale_analog_playback, -12800, 100, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_analog_capture, -9600, 50, 3150);
+static const DECLARE_TLV_DB_SCALE(db_scale_analog_playback, -10400, 100, 2400);
static int pcxhr_update_analog_audio_level(struct snd_pcxhr *chip, int is_capture, int channel)
{
@@ -144,14 +144,7 @@ static struct snd_kcontrol_new pcxhr_control_analog_level = {
};
/* shared */
-static int pcxhr_sw_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 2;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define pcxhr_sw_info snd_ctl_boolean_stereo_info
static int pcxhr_audio_sw_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -195,7 +188,7 @@ static struct snd_kcontrol_new pcxhr_control_output_switch = {
#define PCXHR_DIGITAL_LEVEL_MAX 0x1ff /* +18 dB */
#define PCXHR_DIGITAL_ZERO_LEVEL 0x1b7 /* 0 dB */
-static const DECLARE_TLV_DB_SCALE(db_scale_digital, -10950, 50, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_digital, -10975, 25, 1800);
#define MORE_THAN_ONE_STREAM_LEVEL 0x000001
#define VALID_STREAM_PAN_LEVEL_MASK 0x800000
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index 618653e22561..1475912588e9 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -258,19 +258,6 @@ static inline unsigned int snd_rme32_pcm_byteptr(struct rme32 * rme32)
& RME32_RCR_AUDIO_ADDR_MASK);
}
-static int snd_rme32_ratecode(int rate)
-{
- switch (rate) {
- case 32000: return SNDRV_PCM_RATE_32000;
- case 44100: return SNDRV_PCM_RATE_44100;
- case 48000: return SNDRV_PCM_RATE_48000;
- case 64000: return SNDRV_PCM_RATE_64000;
- case 88200: return SNDRV_PCM_RATE_88200;
- case 96000: return SNDRV_PCM_RATE_96000;
- }
- return 0;
-}
-
/* silence callback for halfduplex mode */
static int snd_rme32_playback_silence(struct snd_pcm_substream *substream, int channel, /* not used (interleaved data) */
snd_pcm_uframes_t pos,
@@ -887,7 +874,7 @@ static int snd_rme32_playback_spdif_open(struct snd_pcm_substream *substream)
if ((rme32->rcreg & RME32_RCR_KMODE) &&
(rate = snd_rme32_capture_getrate(rme32, &dummy)) > 0) {
/* AutoSync */
- runtime->hw.rates = snd_rme32_ratecode(rate);
+ runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);
runtime->hw.rate_min = rate;
runtime->hw.rate_max = rate;
}
@@ -929,7 +916,7 @@ static int snd_rme32_capture_spdif_open(struct snd_pcm_substream *substream)
if (isadat) {
return -EIO;
}
- runtime->hw.rates = snd_rme32_ratecode(rate);
+ runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);
runtime->hw.rate_min = rate;
runtime->hw.rate_max = rate;
}
@@ -965,7 +952,7 @@ snd_rme32_playback_adat_open(struct snd_pcm_substream *substream)
if ((rme32->rcreg & RME32_RCR_KMODE) &&
(rate = snd_rme32_capture_getrate(rme32, &dummy)) > 0) {
/* AutoSync */
- runtime->hw.rates = snd_rme32_ratecode(rate);
+ runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);
runtime->hw.rate_min = rate;
runtime->hw.rate_max = rate;
}
@@ -989,7 +976,7 @@ snd_rme32_capture_adat_open(struct snd_pcm_substream *substream)
if (!isadat) {
return -EIO;
}
- runtime->hw.rates = snd_rme32_ratecode(rate);
+ runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);
runtime->hw.rate_min = rate;
runtime->hw.rate_max = rate;
}
@@ -1582,16 +1569,8 @@ static void __devinit snd_rme32_proc_init(struct rme32 * rme32)
* control interface
*/
-static int
-snd_rme32_info_loopback_control(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_rme32_info_loopback_control snd_ctl_boolean_mono_info
+
static int
snd_rme32_get_loopback_control(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index e3304b7ccbcb..0b3c532c4014 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -301,20 +301,6 @@ snd_rme96_capture_ptr(struct rme96 *rme96)
}
static int
-snd_rme96_ratecode(int rate)
-{
- switch (rate) {
- case 32000: return SNDRV_PCM_RATE_32000;
- case 44100: return SNDRV_PCM_RATE_44100;
- case 48000: return SNDRV_PCM_RATE_48000;
- case 64000: return SNDRV_PCM_RATE_64000;
- case 88200: return SNDRV_PCM_RATE_88200;
- case 96000: return SNDRV_PCM_RATE_96000;
- }
- return 0;
-}
-
-static int
snd_rme96_playback_silence(struct snd_pcm_substream *substream,
int channel, /* not used (interleaved data) */
snd_pcm_uframes_t pos,
@@ -1176,8 +1162,6 @@ snd_rme96_playback_spdif_open(struct snd_pcm_substream *substream)
struct rme96 *rme96 = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
- snd_pcm_set_sync(substream);
-
spin_lock_irq(&rme96->lock);
if (rme96->playback_substream != NULL) {
spin_unlock_irq(&rme96->lock);
@@ -1194,7 +1178,7 @@ snd_rme96_playback_spdif_open(struct snd_pcm_substream *substream)
(rate = snd_rme96_capture_getrate(rme96, &dummy)) > 0)
{
/* slave clock */
- runtime->hw.rates = snd_rme96_ratecode(rate);
+ runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);
runtime->hw.rate_min = rate;
runtime->hw.rate_max = rate;
}
@@ -1214,8 +1198,6 @@ snd_rme96_capture_spdif_open(struct snd_pcm_substream *substream)
struct rme96 *rme96 = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
- snd_pcm_set_sync(substream);
-
runtime->hw = snd_rme96_capture_spdif_info;
if (snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG &&
(rate = snd_rme96_capture_getrate(rme96, &isadat)) > 0)
@@ -1223,7 +1205,7 @@ snd_rme96_capture_spdif_open(struct snd_pcm_substream *substream)
if (isadat) {
return -EIO;
}
- runtime->hw.rates = snd_rme96_ratecode(rate);
+ runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);
runtime->hw.rate_min = rate;
runtime->hw.rate_max = rate;
}
@@ -1247,8 +1229,6 @@ snd_rme96_playback_adat_open(struct snd_pcm_substream *substream)
struct rme96 *rme96 = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
- snd_pcm_set_sync(substream);
-
spin_lock_irq(&rme96->lock);
if (rme96->playback_substream != NULL) {
spin_unlock_irq(&rme96->lock);
@@ -1265,7 +1245,7 @@ snd_rme96_playback_adat_open(struct snd_pcm_substream *substream)
(rate = snd_rme96_capture_getrate(rme96, &dummy)) > 0)
{
/* slave clock */
- runtime->hw.rates = snd_rme96_ratecode(rate);
+ runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);
runtime->hw.rate_min = rate;
runtime->hw.rate_max = rate;
}
@@ -1280,8 +1260,6 @@ snd_rme96_capture_adat_open(struct snd_pcm_substream *substream)
struct rme96 *rme96 = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
- snd_pcm_set_sync(substream);
-
runtime->hw = snd_rme96_capture_adat_info;
if (snd_rme96_getinputtype(rme96) == RME96_INPUT_ANALOG) {
/* makes no sense to use analog input. Note that analog
@@ -1292,7 +1270,7 @@ snd_rme96_capture_adat_open(struct snd_pcm_substream *substream)
if (!isadat) {
return -EIO;
}
- runtime->hw.rates = snd_rme96_ratecode(rate);
+ runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);
runtime->hw.rate_min = rate;
runtime->hw.rate_max = rate;
}
@@ -1826,15 +1804,8 @@ snd_rme96_proc_init(struct rme96 *rme96)
* control interface
*/
-static int
-snd_rme96_info_loopback_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_rme96_info_loopback_control snd_ctl_boolean_mono_info
+
static int
snd_rme96_get_loopback_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
diff --git a/sound/pci/rme9652/Makefile b/sound/pci/rme9652/Makefile
index d2c294e136f9..dcba56040205 100644
--- a/sound/pci/rme9652/Makefile
+++ b/sound/pci/rme9652/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
snd-rme9652-objs := rme9652.o
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index 3b3ef657f73e..ff26a3672d40 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -606,28 +606,28 @@ static void snd_hdsp_9652_enable_mixer (struct hdsp *hdsp);
static int hdsp_playback_to_output_key (struct hdsp *hdsp, int in, int out)
{
- switch (hdsp->firmware_rev) {
- case 0xa:
+ switch (hdsp->io_type) {
+ case Multiface:
+ case Digiface:
+ default:
return (64 * out) + (32 + (in));
- case 0x96:
- case 0x97:
- case 0x98:
+ case H9632:
return (32 * out) + (16 + (in));
- default:
+ case H9652:
return (52 * out) + (26 + (in));
}
}
static int hdsp_input_to_output_key (struct hdsp *hdsp, int in, int out)
{
- switch (hdsp->firmware_rev) {
- case 0xa:
+ switch (hdsp->io_type) {
+ case Multiface:
+ case Digiface:
+ default:
return (64 * out) + in;
- case 0x96:
- case 0x97:
- case 0x98:
+ case H9632:
return (32 * out) + in;
- default:
+ case H9652:
return (52 * out) + in;
}
}
@@ -1623,14 +1623,7 @@ static int hdsp_set_spdif_output(struct hdsp *hdsp, int out)
return 0;
}
-static int snd_hdsp_info_spdif_bits(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_hdsp_info_spdif_bits snd_ctl_boolean_mono_info
static int snd_hdsp_get_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -2111,14 +2104,7 @@ static int snd_hdsp_put_clock_source(struct snd_kcontrol *kcontrol, struct snd_c
return change;
}
-static int snd_hdsp_info_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_hdsp_info_clock_source_lock snd_ctl_boolean_mono_info
static int snd_hdsp_get_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -2420,14 +2406,7 @@ static int hdsp_set_xlr_breakout_cable(struct hdsp *hdsp, int mode)
return 0;
}
-static int snd_hdsp_info_xlr_breakout_cable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_hdsp_info_xlr_breakout_cable snd_ctl_boolean_mono_info
static int snd_hdsp_get_xlr_breakout_cable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -2483,14 +2462,7 @@ static int hdsp_set_aeb(struct hdsp *hdsp, int mode)
return 0;
}
-static int snd_hdsp_info_aeb(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_hdsp_info_aeb snd_ctl_boolean_mono_info
static int snd_hdsp_get_aeb(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -2729,14 +2701,7 @@ static int hdsp_set_line_output(struct hdsp *hdsp, int out)
return 0;
}
-static int snd_hdsp_info_line_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_hdsp_info_line_out snd_ctl_boolean_mono_info
static int snd_hdsp_get_line_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -2782,14 +2747,7 @@ static int hdsp_set_precise_pointer(struct hdsp *hdsp, int precise)
return 0;
}
-static int snd_hdsp_info_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_hdsp_info_precise_pointer snd_ctl_boolean_mono_info
static int snd_hdsp_get_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -2835,14 +2793,7 @@ static int hdsp_set_use_midi_tasklet(struct hdsp *hdsp, int use_tasklet)
return 0;
}
-static int snd_hdsp_info_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_hdsp_info_use_midi_tasklet snd_ctl_boolean_mono_info
static int snd_hdsp_get_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -3108,6 +3059,9 @@ static int hdsp_dds_offset(struct hdsp *hdsp)
unsigned int dds_value = hdsp->dds_value;
int system_sample_rate = hdsp->system_sample_rate;
+ if (!dds_value)
+ return 0;
+
n = DDS_NUMERATOR;
/*
* dds_value = n / rate
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 143185e7e4dc..f1bdda6cbcff 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -1,5 +1,4 @@
-/* -*- linux-c -*-
- *
+/*
* ALSA driver for RME Hammerfall DSP MADI audio interface(s)
*
* Copyright (c) 2003 Winfried Ritsch (IEM)
@@ -78,7 +77,8 @@ MODULE_PARM_DESC(enable_monitor,
"Enable Analog Out on Channel 63/64 by default.");
MODULE_AUTHOR
- ("Winfried Ritsch <ritsch_AT_iem.at>, Paul Davis <paul@linuxaudiosystems.com>, "
+ ("Winfried Ritsch <ritsch_AT_iem.at>, "
+ "Paul Davis <paul@linuxaudiosystems.com>, "
"Marcus Andersson, Thomas Charbonnel <thomas@undata.org>, "
"Remy Bruno <remy.bruno@trinnov.com>");
MODULE_DESCRIPTION("RME HDSPM");
@@ -161,7 +161,9 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
0=off, 1=on */ /* MADI ONLY */
#define HDSPM_Dolby (1<<11) /* Dolby = "NonAudio" ?? */ /* AES32 ONLY */
-#define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax */ /* MADI ONLY*/
+#define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax
+ * -- MADI ONLY
+ */
#define HDSPM_InputSelect1 (1<<15) /* should be 0 */
#define HDSPM_SyncRef0 (1<<16) /* 0=WOrd, 1=MADI */
@@ -189,11 +191,13 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
/* --- bit helper defines */
#define HDSPM_LatencyMask (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2)
-#define HDSPM_FrequencyMask (HDSPM_Frequency0|HDSPM_Frequency1|HDSPM_DoubleSpeed|HDSPM_QuadSpeed)
+#define HDSPM_FrequencyMask (HDSPM_Frequency0|HDSPM_Frequency1|\
+ HDSPM_DoubleSpeed|HDSPM_QuadSpeed)
#define HDSPM_InputMask (HDSPM_InputSelect0|HDSPM_InputSelect1)
#define HDSPM_InputOptical 0
#define HDSPM_InputCoaxial (HDSPM_InputSelect0)
-#define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1|HDSPM_SyncRef2|HDSPM_SyncRef3)
+#define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1|\
+ HDSPM_SyncRef2|HDSPM_SyncRef3)
#define HDSPM_SyncRef_Word 0
#define HDSPM_SyncRef_MADI (HDSPM_SyncRef0)
@@ -205,10 +209,12 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
#define HDSPM_Frequency48KHz (HDSPM_Frequency1|HDSPM_Frequency0)
#define HDSPM_Frequency64KHz (HDSPM_DoubleSpeed|HDSPM_Frequency0)
#define HDSPM_Frequency88_2KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1)
-#define HDSPM_Frequency96KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1|HDSPM_Frequency0)
+#define HDSPM_Frequency96KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1|\
+ HDSPM_Frequency0)
#define HDSPM_Frequency128KHz (HDSPM_QuadSpeed|HDSPM_Frequency0)
#define HDSPM_Frequency176_4KHz (HDSPM_QuadSpeed|HDSPM_Frequency1)
-#define HDSPM_Frequency192KHz (HDSPM_QuadSpeed|HDSPM_Frequency1|HDSPM_Frequency0)
+#define HDSPM_Frequency192KHz (HDSPM_QuadSpeed|HDSPM_Frequency1|\
+ HDSPM_Frequency0)
/* --- for internal discrimination */
#define HDSPM_CLOCK_SOURCE_AUTOSYNC 0 /* Sample Clock Sources */
@@ -256,10 +262,14 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
#define HDSPM_RD_MULTIPLE (1<<10)
/* --- Status Register bits --- */ /* MADI ONLY */ /* Bits defined here and
- that do not conflict with specific bits for AES32 seem to be valid also for the AES32 */
+ that do not conflict with specific bits for AES32 seem to be valid also
+ for the AES32
+ */
#define HDSPM_audioIRQPending (1<<0) /* IRQ is high and pending */
-#define HDSPM_RX_64ch (1<<1) /* Input 64chan. MODE=1, 56chn. MODE=0 */
-#define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1 (like inp0) */
+#define HDSPM_RX_64ch (1<<1) /* Input 64chan. MODE=1, 56chn MODE=0 */
+#define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1
+ * (like inp0)
+ */
#define HDSPM_madiLock (1<<3) /* MADI Locked =1, no=0 */
#define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */
@@ -274,12 +284,15 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
#define HDSPM_madiFreq2 (1<<24) /* 4=64, 5=88.2 6=96 */
#define HDSPM_madiFreq3 (1<<25) /* 7=128, 8=176.4 9=192 */
-#define HDSPM_BufferID (1<<26) /* (Double)Buffer ID toggles with Interrupt */
+#define HDSPM_BufferID (1<<26) /* (Double)Buffer ID toggles with
+ * Interrupt
+ */
#define HDSPM_midi0IRQPending (1<<30) /* MIDI IRQ is pending */
#define HDSPM_midi1IRQPending (1<<31) /* and aktiv */
/* --- status bit helpers */
-#define HDSPM_madiFreqMask (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2|HDSPM_madiFreq3)
+#define HDSPM_madiFreqMask (HDSPM_madiFreq0|HDSPM_madiFreq1|\
+ HDSPM_madiFreq2|HDSPM_madiFreq3)
#define HDSPM_madiFreq32 (HDSPM_madiFreq0)
#define HDSPM_madiFreq44_1 (HDSPM_madiFreq1)
#define HDSPM_madiFreq48 (HDSPM_madiFreq0|HDSPM_madiFreq1)
@@ -319,10 +332,12 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
#define HDSPM_wcFreq96 (HDSPM_wc_freq1|HDSPM_wc_freq2)
-#define HDSPM_SelSyncRefMask (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|HDSPM_SelSyncRef2)
+#define HDSPM_SelSyncRefMask (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\
+ HDSPM_SelSyncRef2)
#define HDSPM_SelSyncRef_WORD 0
#define HDSPM_SelSyncRef_MADI (HDSPM_SelSyncRef0)
-#define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|HDSPM_SelSyncRef2)
+#define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\
+ HDSPM_SelSyncRef2)
/*
For AES32, bits for status, status2 and timecode are different
@@ -344,7 +359,7 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
#define HDSPM_AES32_AUTOSYNC_FROM_AES6 6
#define HDSPM_AES32_AUTOSYNC_FROM_AES7 7
#define HDSPM_AES32_AUTOSYNC_FROM_AES8 8
-#define HDSPM_AES32_AUTOSYNC_FROM_NONE -1
+#define HDSPM_AES32_AUTOSYNC_FROM_NONE 9
/* status2 */
/* HDSPM_LockAES_bit is given by HDSPM_LockAES >> (AES# - 1) */
@@ -398,6 +413,13 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
/* revisions >= 230 indicate AES32 card */
#define HDSPM_AESREVISION 230
+/* speed factor modes */
+#define HDSPM_SPEED_SINGLE 0
+#define HDSPM_SPEED_DOUBLE 1
+#define HDSPM_SPEED_QUAD 2
+/* names for speed modes */
+static char *hdspm_speed_names[] = { "single", "double", "quad" };
+
struct hdspm_midi {
struct hdspm *hdspm;
int id;
@@ -412,8 +434,9 @@ struct hdspm_midi {
struct hdspm {
spinlock_t lock;
- struct snd_pcm_substream *capture_substream; /* only one playback */
- struct snd_pcm_substream *playback_substream; /* and/or capture stream */
+ /* only one playback and/or capture stream */
+ struct snd_pcm_substream *capture_substream;
+ struct snd_pcm_substream *playback_substream;
char *card_name; /* for procinfo */
unsigned short firmware_rev; /* dont know if relevant (yes if AES32)*/
@@ -460,9 +483,12 @@ struct hdspm {
struct pci_dev *pci; /* and an pci info */
/* Mixer vars */
- struct snd_kcontrol *playback_mixer_ctls[HDSPM_MAX_CHANNELS]; /* fast alsa mixer */
- struct snd_kcontrol *input_mixer_ctls[HDSPM_MAX_CHANNELS]; /* but input to much, so not used */
- struct hdspm_mixer *mixer; /* full mixer accessable over mixer ioctl or hwdep-device */
+ /* fast alsa mixer */
+ struct snd_kcontrol *playback_mixer_ctls[HDSPM_MAX_CHANNELS];
+ /* but input to much, so not used */
+ struct snd_kcontrol *input_mixer_ctls[HDSPM_MAX_CHANNELS];
+ /* full mixer accessable over mixer ioctl or hwdep-device */
+ struct hdspm_mixer *mixer;
};
@@ -616,13 +642,15 @@ static inline int hdspm_external_sample_rate(struct hdspm * hdspm)
if (hdspm->is_aes32) {
unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
- unsigned int timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
+ unsigned int timecode =
+ hdspm_read(hdspm, HDSPM_timecodeRegister);
int syncref = hdspm_autosync_ref(hdspm);
if (syncref == HDSPM_AES32_AUTOSYNC_FROM_WORD &&
status & HDSPM_AES32_wcLock)
- return HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF);
+ return HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit)
+ & 0xF);
if (syncref >= HDSPM_AES32_AUTOSYNC_FROM_AES1 &&
syncref <= HDSPM_AES32_AUTOSYNC_FROM_AES8 &&
status2 & (HDSPM_LockAES >>
@@ -668,7 +696,9 @@ static inline int hdspm_external_sample_rate(struct hdspm * hdspm)
}
}
- /* if rate detected and Syncref is Word than have it, word has priority to MADI */
+ /* if rate detected and Syncref is Word than have it,
+ * word has priority to MADI
+ */
if (rate != 0 &&
(status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD)
return rate;
@@ -727,12 +757,12 @@ static snd_pcm_uframes_t hdspm_hw_pointer(struct hdspm * hdspm)
position = hdspm_read(hdspm, HDSPM_statusRegister);
- if (!hdspm->precise_ptr) {
- return (position & HDSPM_BufferID) ? (hdspm->period_bytes /
- 4) : 0;
- }
+ if (!hdspm->precise_ptr)
+ return (position & HDSPM_BufferID) ?
+ (hdspm->period_bytes / 4) : 0;
- /* hwpointer comes in bytes and is 64Bytes accurate (by docu since PCI Burst)
+ /* hwpointer comes in bytes and is 64Bytes accurate (by docu since
+ PCI Burst)
i have experimented that it is at most 64 Byte to much for playing
so substraction of 64 byte should be ok for ALSA, but use it only
for application where you know what you do since if you come to
@@ -811,7 +841,7 @@ static void hdspm_set_dds_value(struct hdspm *hdspm, int rate)
// return 104857600000000 / rate; // 100 MHz
return 110100480000000 / rate; // 105 MHz
*/
- //n = 104857600000000ULL; /* = 2^20 * 10^8 */
+ /* n = 104857600000000ULL; */ /* = 2^20 * 10^8 */
n = 110100480000000ULL; /* Value checked for AES32 and MADI */
div64_32(&n, rate, &r);
/* n should be less than 2^32 for being written to FREQ register */
@@ -822,11 +852,10 @@ static void hdspm_set_dds_value(struct hdspm *hdspm, int rate)
/* dummy set rate lets see what happens */
static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
{
- int reject_if_open = 0;
int current_rate;
int rate_bits;
int not_set = 0;
- int is_single, is_double, is_quad;
+ int current_speed, target_speed;
/* ASSUMPTION: hdspm->lock is either set, or there is no need for
it (e.g. during module initialization).
@@ -841,8 +870,9 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
just make a warning an remember setting
for future master mode switching */
- snd_printk
- (KERN_WARNING "HDSPM: Warning: device is not running as a clock master.\n");
+ snd_printk(KERN_WARNING "HDSPM: "
+ "Warning: device is not running "
+ "as a clock master.\n");
not_set = 1;
} else {
@@ -850,16 +880,18 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
int external_freq =
hdspm_external_sample_rate(hdspm);
- if ((hdspm_autosync_ref(hdspm) ==
- HDSPM_AUTOSYNC_FROM_NONE)) {
+ if (hdspm_autosync_ref(hdspm) ==
+ HDSPM_AUTOSYNC_FROM_NONE) {
- snd_printk(KERN_WARNING "HDSPM: Detected no Externel Sync \n");
+ snd_printk(KERN_WARNING "HDSPM: "
+ "Detected no Externel Sync \n");
not_set = 1;
} else if (rate != external_freq) {
- snd_printk
- (KERN_WARNING "HDSPM: Warning: No AutoSync source for requested rate\n");
+ snd_printk(KERN_WARNING "HDSPM: "
+ "Warning: No AutoSync source for "
+ "requested rate\n");
not_set = 1;
}
}
@@ -877,64 +909,60 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
changes in the read/write routines.
*/
- is_single = (current_rate <= 48000);
- is_double = (current_rate > 48000 && current_rate <= 96000);
- is_quad = (current_rate > 96000);
+ if (current_rate <= 48000)
+ current_speed = HDSPM_SPEED_SINGLE;
+ else if (current_rate <= 96000)
+ current_speed = HDSPM_SPEED_DOUBLE;
+ else
+ current_speed = HDSPM_SPEED_QUAD;
+
+ if (rate <= 48000)
+ target_speed = HDSPM_SPEED_SINGLE;
+ else if (rate <= 96000)
+ target_speed = HDSPM_SPEED_DOUBLE;
+ else
+ target_speed = HDSPM_SPEED_QUAD;
switch (rate) {
case 32000:
- if (!is_single)
- reject_if_open = 1;
rate_bits = HDSPM_Frequency32KHz;
break;
case 44100:
- if (!is_single)
- reject_if_open = 1;
rate_bits = HDSPM_Frequency44_1KHz;
break;
case 48000:
- if (!is_single)
- reject_if_open = 1;
rate_bits = HDSPM_Frequency48KHz;
break;
case 64000:
- if (!is_double)
- reject_if_open = 1;
rate_bits = HDSPM_Frequency64KHz;
break;
case 88200:
- if (!is_double)
- reject_if_open = 1;
rate_bits = HDSPM_Frequency88_2KHz;
break;
case 96000:
- if (!is_double)
- reject_if_open = 1;
rate_bits = HDSPM_Frequency96KHz;
break;
case 128000:
- if (!is_quad)
- reject_if_open = 1;
rate_bits = HDSPM_Frequency128KHz;
break;
case 176400:
- if (!is_quad)
- reject_if_open = 1;
rate_bits = HDSPM_Frequency176_4KHz;
break;
case 192000:
- if (!is_quad)
- reject_if_open = 1;
rate_bits = HDSPM_Frequency192KHz;
break;
default:
return -EINVAL;
}
- if (reject_if_open
+ if (current_speed != target_speed
&& (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) {
snd_printk
- (KERN_ERR "HDSPM: cannot change between single- and double-speed mode (capture PID = %d, playback PID = %d)\n",
+ (KERN_ERR "HDSPM: "
+ "cannot change from %s speed to %s speed mode "
+ "(capture PID = %d, playback PID = %d)\n",
+ hdspm_speed_names[current_speed],
+ hdspm_speed_names[target_speed],
hdspm->capture_pid, hdspm->playback_pid);
return -EBUSY;
}
@@ -966,8 +994,14 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
static void all_in_all_mixer(struct hdspm * hdspm, int sgain)
{
int i, j;
- unsigned int gain =
- (sgain > UNITY_GAIN) ? UNITY_GAIN : (sgain < 0) ? 0 : sgain;
+ unsigned int gain;
+
+ if (sgain > UNITY_GAIN)
+ gain = UNITY_GAIN;
+ else if (sgain < 0)
+ gain = 0;
+ else
+ gain = sgain;
for (i = 0; i < HDSPM_MIXER_CHANNELS; i++)
for (j = 0; j < HDSPM_MIXER_CHANNELS; j++) {
@@ -980,7 +1014,8 @@ static void all_in_all_mixer(struct hdspm * hdspm, int sgain)
MIDI
----------------------------------------------------------------------------*/
-static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm, int id)
+static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm,
+ int id)
{
/* the hardware already does the relevant bit-mask with 0xff */
if (id)
@@ -989,7 +1024,8 @@ static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm, int i
return hdspm_read(hdspm, HDSPM_midiDataIn0);
}
-static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id, int val)
+static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id,
+ int val)
{
/* the hardware already does the relevant bit-mask with 0xff */
if (id)
@@ -1011,9 +1047,10 @@ static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id)
int fifo_bytes_used;
if (id)
- fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xff;
+ fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut1);
else
- fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xff;
+ fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut0);
+ fifo_bytes_used &= 0xff;
if (fifo_bytes_used < 128)
return 128 - fifo_bytes_used;
@@ -1038,16 +1075,21 @@ static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi)
/* Output is not interrupt driven */
spin_lock_irqsave (&hmidi->lock, flags);
- if (hmidi->output) {
- if (!snd_rawmidi_transmit_empty (hmidi->output)) {
- if ((n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm, hmidi->id)) > 0) {
- if (n_pending > (int)sizeof (buf))
- n_pending = sizeof (buf);
-
- if ((to_write = snd_rawmidi_transmit (hmidi->output, buf, n_pending)) > 0) {
- for (i = 0; i < to_write; ++i)
- snd_hdspm_midi_write_byte (hmidi->hdspm, hmidi->id, buf[i]);
- }
+ if (hmidi->output &&
+ !snd_rawmidi_transmit_empty (hmidi->output)) {
+ n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm,
+ hmidi->id);
+ if (n_pending > 0) {
+ if (n_pending > (int)sizeof (buf))
+ n_pending = sizeof (buf);
+
+ to_write = snd_rawmidi_transmit (hmidi->output, buf,
+ n_pending);
+ if (to_write > 0) {
+ for (i = 0; i < to_write; ++i)
+ snd_hdspm_midi_write_byte (hmidi->hdspm,
+ hmidi->id,
+ buf[i]);
}
}
}
@@ -1057,51 +1099,55 @@ static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi)
static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi)
{
- unsigned char buf[128]; /* this buffer is designed to match the MIDI input FIFO size */
+ unsigned char buf[128]; /* this buffer is designed to match the MIDI
+ * input FIFO size
+ */
unsigned long flags;
int n_pending;
int i;
spin_lock_irqsave (&hmidi->lock, flags);
- if ((n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id)) > 0) {
+ n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id);
+ if (n_pending > 0) {
if (hmidi->input) {
- if (n_pending > (int)sizeof (buf)) {
+ if (n_pending > (int)sizeof (buf))
n_pending = sizeof (buf);
- }
- for (i = 0; i < n_pending; ++i) {
- buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm, hmidi->id);
- }
- if (n_pending) {
- snd_rawmidi_receive (hmidi->input, buf, n_pending);
- }
+ for (i = 0; i < n_pending; ++i)
+ buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm,
+ hmidi->id);
+ if (n_pending)
+ snd_rawmidi_receive (hmidi->input, buf,
+ n_pending);
} else {
/* flush the MIDI input FIFO */
- while (n_pending--) {
- snd_hdspm_midi_read_byte (hmidi->hdspm, hmidi->id);
- }
+ while (n_pending--)
+ snd_hdspm_midi_read_byte (hmidi->hdspm,
+ hmidi->id);
}
}
hmidi->pending = 0;
- if (hmidi->id) {
+ if (hmidi->id)
hmidi->hdspm->control_register |= HDSPM_Midi1InterruptEnable;
- } else {
+ else
hmidi->hdspm->control_register |= HDSPM_Midi0InterruptEnable;
- }
- hdspm_write(hmidi->hdspm, HDSPM_controlRegister, hmidi->hdspm->control_register);
+ hdspm_write(hmidi->hdspm, HDSPM_controlRegister,
+ hmidi->hdspm->control_register);
spin_unlock_irqrestore (&hmidi->lock, flags);
return snd_hdspm_midi_output_write (hmidi);
}
-static void snd_hdspm_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
+static void
+snd_hdspm_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
{
struct hdspm *hdspm;
struct hdspm_midi *hmidi;
unsigned long flags;
u32 ie;
- hmidi = (struct hdspm_midi *) substream->rmidi->private_data;
+ hmidi = substream->rmidi->private_data;
hdspm = hmidi->hdspm;
- ie = hmidi->id ? HDSPM_Midi1InterruptEnable : HDSPM_Midi0InterruptEnable;
+ ie = hmidi->id ?
+ HDSPM_Midi1InterruptEnable : HDSPM_Midi0InterruptEnable;
spin_lock_irqsave (&hdspm->lock, flags);
if (up) {
if (!(hdspm->control_register & ie)) {
@@ -1138,12 +1184,13 @@ static void snd_hdspm_midi_output_timer(unsigned long data)
spin_unlock_irqrestore (&hmidi->lock, flags);
}
-static void snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
+static void
+snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
{
struct hdspm_midi *hmidi;
unsigned long flags;
- hmidi = (struct hdspm_midi *) substream->rmidi->private_data;
+ hmidi = substream->rmidi->private_data;
spin_lock_irqsave (&hmidi->lock, flags);
if (up) {
if (!hmidi->istimer) {
@@ -1155,9 +1202,8 @@ static void snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substrea
hmidi->istimer++;
}
} else {
- if (hmidi->istimer && --hmidi->istimer <= 0) {
+ if (hmidi->istimer && --hmidi->istimer <= 0)
del_timer (&hmidi->timer);
- }
}
spin_unlock_irqrestore (&hmidi->lock, flags);
if (up)
@@ -1168,7 +1214,7 @@ static int snd_hdspm_midi_input_open(struct snd_rawmidi_substream *substream)
{
struct hdspm_midi *hmidi;
- hmidi = (struct hdspm_midi *) substream->rmidi->private_data;
+ hmidi = substream->rmidi->private_data;
spin_lock_irq (&hmidi->lock);
snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id);
hmidi->input = substream;
@@ -1181,7 +1227,7 @@ static int snd_hdspm_midi_output_open(struct snd_rawmidi_substream *substream)
{
struct hdspm_midi *hmidi;
- hmidi = (struct hdspm_midi *) substream->rmidi->private_data;
+ hmidi = substream->rmidi->private_data;
spin_lock_irq (&hmidi->lock);
hmidi->output = substream;
spin_unlock_irq (&hmidi->lock);
@@ -1195,7 +1241,7 @@ static int snd_hdspm_midi_input_close(struct snd_rawmidi_substream *substream)
snd_hdspm_midi_input_trigger (substream, 0);
- hmidi = (struct hdspm_midi *) substream->rmidi->private_data;
+ hmidi = substream->rmidi->private_data;
spin_lock_irq (&hmidi->lock);
hmidi->input = NULL;
spin_unlock_irq (&hmidi->lock);
@@ -1209,7 +1255,7 @@ static int snd_hdspm_midi_output_close(struct snd_rawmidi_substream *substream)
snd_hdspm_midi_output_trigger (substream, 0);
- hmidi = (struct hdspm_midi *) substream->rmidi->private_data;
+ hmidi = substream->rmidi->private_data;
spin_lock_irq (&hmidi->lock);
hmidi->output = NULL;
spin_unlock_irq (&hmidi->lock);
@@ -1231,29 +1277,28 @@ static struct snd_rawmidi_ops snd_hdspm_midi_input =
.trigger = snd_hdspm_midi_input_trigger,
};
-static int __devinit snd_hdspm_create_midi (struct snd_card *card, struct hdspm *hdspm, int id)
+static int __devinit snd_hdspm_create_midi (struct snd_card *card,
+ struct hdspm *hdspm, int id)
{
int err;
char buf[32];
hdspm->midi[id].id = id;
- hdspm->midi[id].rmidi = NULL;
- hdspm->midi[id].input = NULL;
- hdspm->midi[id].output = NULL;
hdspm->midi[id].hdspm = hdspm;
- hdspm->midi[id].istimer = 0;
- hdspm->midi[id].pending = 0;
spin_lock_init (&hdspm->midi[id].lock);
sprintf (buf, "%s MIDI %d", card->shortname, id+1);
- if ((err = snd_rawmidi_new (card, buf, id, 1, 1, &hdspm->midi[id].rmidi)) < 0)
+ err = snd_rawmidi_new (card, buf, id, 1, 1, &hdspm->midi[id].rmidi);
+ if (err < 0)
return err;
sprintf (hdspm->midi[id].rmidi->name, "%s MIDI %d", card->id, id+1);
hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
- snd_rawmidi_set_ops (hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_hdspm_midi_output);
- snd_rawmidi_set_ops (hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_hdspm_midi_input);
+ snd_rawmidi_set_ops(hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
+ &snd_hdspm_midi_output);
+ snd_rawmidi_set_ops(hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
+ &snd_hdspm_midi_input);
hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
SNDRV_RAWMIDI_INFO_INPUT |
@@ -1558,8 +1603,8 @@ static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol,
val = ucontrol->value.enumerated.item[0];
if (val < 0)
val = 0;
- if (val > 6)
- val = 6;
+ if (val > 9)
+ val = 9;
spin_lock_irq(&hdspm->lock);
if (val != hdspm_clock_source(hdspm))
change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0;
@@ -1637,7 +1682,8 @@ static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref)
hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef1;
break;
case 7:
- hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0;
+ hdspm->control_register |=
+ HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0;
break;
case 8:
hdspm->control_register |= HDSPM_SyncRef3;
@@ -1675,7 +1721,8 @@ static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol,
uinfo->value.enumerated.items = 9;
- if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+ if (uinfo->value.enumerated.item >=
+ uinfo->value.enumerated.items)
uinfo->value.enumerated.item =
uinfo->value.enumerated.items - 1;
strcpy(uinfo->value.enumerated.name,
@@ -1688,7 +1735,8 @@ static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol,
uinfo->value.enumerated.items = 2;
- if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+ if (uinfo->value.enumerated.item >=
+ uinfo->value.enumerated.items)
uinfo->value.enumerated.item =
uinfo->value.enumerated.items - 1;
strcpy(uinfo->value.enumerated.name,
@@ -1740,7 +1788,8 @@ static int hdspm_autosync_ref(struct hdspm * hdspm)
{
if (hdspm->is_aes32) {
unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
- unsigned int syncref = (status >> HDSPM_AES32_syncref_bit) & 0xF;
+ unsigned int syncref = (status >> HDSPM_AES32_syncref_bit) &
+ 0xF;
if (syncref == 0)
return HDSPM_AES32_AUTOSYNC_FROM_WORD;
if (syncref <= 8)
@@ -1777,20 +1826,20 @@ static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol,
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
uinfo->value.enumerated.items = 10;
- if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+ if (uinfo->value.enumerated.item >=
+ uinfo->value.enumerated.items)
uinfo->value.enumerated.item =
uinfo->value.enumerated.items - 1;
strcpy(uinfo->value.enumerated.name,
texts[uinfo->value.enumerated.item]);
- }
- else
- {
+ } else {
static char *texts[] = { "WordClock", "MADI", "None" };
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
uinfo->value.enumerated.items = 3;
- if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+ if (uinfo->value.enumerated.item >=
+ uinfo->value.enumerated.items)
uinfo->value.enumerated.item =
uinfo->value.enumerated.items - 1;
strcpy(uinfo->value.enumerated.name,
@@ -1804,7 +1853,7 @@ static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,
{
struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
- ucontrol->value.enumerated.item[0] = hdspm_pref_sync_ref(hdspm);
+ ucontrol->value.enumerated.item[0] = hdspm_autosync_ref(hdspm);
return 0;
}
@@ -1834,15 +1883,7 @@ static int hdspm_set_line_output(struct hdspm * hdspm, int out)
return 0;
}
-static int snd_hdspm_info_line_out(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_hdspm_info_line_out snd_ctl_boolean_mono_info
static int snd_hdspm_get_line_out(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -1897,15 +1938,7 @@ static int hdspm_set_tx_64(struct hdspm * hdspm, int out)
return 0;
}
-static int snd_hdspm_info_tx_64(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_hdspm_info_tx_64 snd_ctl_boolean_mono_info
static int snd_hdspm_get_tx_64(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -1960,15 +1993,7 @@ static int hdspm_set_c_tms(struct hdspm * hdspm, int out)
return 0;
}
-static int snd_hdspm_info_c_tms(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_hdspm_info_c_tms snd_ctl_boolean_mono_info
static int snd_hdspm_get_c_tms(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -2023,15 +2048,7 @@ static int hdspm_set_safe_mode(struct hdspm * hdspm, int out)
return 0;
}
-static int snd_hdspm_info_safe_mode(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_hdspm_info_safe_mode snd_ctl_boolean_mono_info
static int snd_hdspm_get_safe_mode(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -2086,15 +2103,7 @@ static int hdspm_set_emphasis(struct hdspm * hdspm, int emp)
return 0;
}
-static int snd_hdspm_info_emphasis(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_hdspm_info_emphasis snd_ctl_boolean_mono_info
static int snd_hdspm_get_emphasis(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -2149,15 +2158,7 @@ static int hdspm_set_dolby(struct hdspm * hdspm, int dol)
return 0;
}
-static int snd_hdspm_info_dolby(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_hdspm_info_dolby snd_ctl_boolean_mono_info
static int snd_hdspm_get_dolby(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -2212,15 +2213,7 @@ static int hdspm_set_professional(struct hdspm * hdspm, int dol)
return 0;
}
-static int snd_hdspm_info_professional(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_hdspm_info_professional snd_ctl_boolean_mono_info
static int snd_hdspm_get_professional(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -2472,7 +2465,7 @@ static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol,
if (val > 2)
val = 2;
spin_lock_irq(&hdspm->lock);
- change = (int) val != hdspm_qs_wire(hdspm);
+ change = val != hdspm_qs_wire(hdspm);
hdspm_set_qs_wire(hdspm, val);
spin_unlock_irq(&hdspm->lock);
return change;
@@ -2573,8 +2566,8 @@ static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol,
source -
HDSPM_MAX_CHANNELS);
else
- change =
- gain != hdspm_read_in_gain(hdspm, destination, source);
+ change = gain != hdspm_read_in_gain(hdspm, destination,
+ source);
if (change) {
if (source >= HDSPM_MAX_CHANNELS)
@@ -2627,7 +2620,8 @@ static int snd_hdspm_get_playback_mixer(struct snd_kcontrol *kcontrol,
snd_assert(channel >= 0
|| channel < HDSPM_MAX_CHANNELS, return -EINVAL);
- if ((mapped_channel = hdspm->channel_map[channel]) < 0)
+ mapped_channel = hdspm->channel_map[channel];
+ if (mapped_channel < 0)
return -EINVAL;
spin_lock_irq(&hdspm->lock);
@@ -2635,10 +2629,12 @@ static int snd_hdspm_get_playback_mixer(struct snd_kcontrol *kcontrol,
hdspm_read_pb_gain(hdspm, mapped_channel, mapped_channel);
spin_unlock_irq(&hdspm->lock);
- /* snd_printdd("get pb mixer index %d, channel %d, mapped_channel %d, value %d\n",
- ucontrol->id.index, channel, mapped_channel, ucontrol->value.integer.value[0]);
- */
-
+ /*
+ snd_printdd("get pb mixer index %d, channel %d, mapped_channel %d, "
+ "value %d\n",
+ ucontrol->id.index, channel, mapped_channel,
+ ucontrol->value.integer.value[0]);
+ */
return 0;
}
@@ -2659,7 +2655,8 @@ static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol,
snd_assert(channel >= 0
|| channel < HDSPM_MAX_CHANNELS, return -EINVAL);
- if ((mapped_channel = hdspm->channel_map[channel]) < 0)
+ mapped_channel = hdspm->channel_map[channel];
+ if (mapped_channel < 0)
return -EINVAL;
gain = ucontrol->value.integer.value[0];
@@ -2909,28 +2906,26 @@ static int snd_hdspm_create_controls(struct snd_card *card, struct hdspm * hdspm
}
/* Channel playback mixer as default control
-Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders, thats too big for any alsamixer
-they are accesible via special IOCTL on hwdep
-and the mixer 2dimensional mixer control */
+ Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders,
+ thats too * big for any alsamixer they are accesible via special
+ IOCTL on hwdep and the mixer 2dimensional mixer control
+ */
snd_hdspm_playback_mixer.name = "Chn";
limit = HDSPM_MAX_CHANNELS;
- /* The index values are one greater than the channel ID so that alsamixer
- will display them correctly. We want to use the index for fast lookup
- of the relevant channel, but if we use it at all, most ALSA software
- does the wrong thing with it ...
+ /* The index values are one greater than the channel ID so that
+ * alsamixer will display them correctly. We want to use the index
+ * for fast lookup of the relevant channel, but if we use it at all,
+ * most ALSA software does the wrong thing with it ...
*/
for (idx = 0; idx < limit; ++idx) {
snd_hdspm_playback_mixer.index = idx + 1;
- if ((err = snd_ctl_add(card,
- kctl =
- snd_ctl_new1
- (&snd_hdspm_playback_mixer,
- hdspm)))) {
+ kctl = snd_ctl_new1(&snd_hdspm_playback_mixer, hdspm);
+ err = snd_ctl_add(card, kctl);
+ if (err < 0)
return err;
- }
hdspm->playback_mixer_ctls[idx] = kctl;
}
@@ -2945,7 +2940,7 @@ static void
snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
struct snd_info_buffer *buffer)
{
- struct hdspm *hdspm = (struct hdspm *) entry->private_data;
+ struct hdspm *hdspm = entry->private_data;
unsigned int status;
unsigned int status2;
char *pref_sync_ref;
@@ -2978,14 +2973,14 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
(status & HDSPM_midi1IRQPending) ? 1 : 0,
hdspm->irq_count);
snd_iprintf(buffer,
- "HW pointer: id = %d, rawptr = %d (%d->%d) estimated= %ld (bytes)\n",
+ "HW pointer: id = %d, rawptr = %d (%d->%d) "
+ "estimated= %ld (bytes)\n",
((status & HDSPM_BufferID) ? 1 : 0),
(status & HDSPM_BufferPositionMask),
- (status & HDSPM_BufferPositionMask) % (2 *
- (int)hdspm->
- period_bytes),
- ((status & HDSPM_BufferPositionMask) -
- 64) % (2 * (int)hdspm->period_bytes),
+ (status & HDSPM_BufferPositionMask) %
+ (2 * (int)hdspm->period_bytes),
+ ((status & HDSPM_BufferPositionMask) - 64) %
+ (2 * (int)hdspm->period_bytes),
(long) hdspm_hw_pointer(hdspm) * 4);
snd_iprintf(buffer,
@@ -2995,24 +2990,22 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
snd_iprintf(buffer,
- "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, status2=0x%x\n",
+ "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
+ "status2=0x%x\n",
hdspm->control_register, hdspm->control2_register,
status, status2);
snd_iprintf(buffer, "--- Settings ---\n");
- x = 1 << (6 +
- hdspm_decode_latency(hdspm->
- control_register &
- HDSPM_LatencyMask));
+ x = 1 << (6 + hdspm_decode_latency(hdspm->control_register &
+ HDSPM_LatencyMask));
snd_iprintf(buffer,
"Size (Latency): %d samples (2 periods of %lu bytes)\n",
x, (unsigned long) hdspm->period_bytes);
snd_iprintf(buffer, "Line out: %s, Precise Pointer: %s\n",
- (hdspm->
- control_register & HDSPM_LineOut) ? "on " : "off",
+ (hdspm->control_register & HDSPM_LineOut) ? "on " : "off",
(hdspm->precise_ptr) ? "on" : "off");
switch (hdspm->control_register & HDSPM_InputMask) {
@@ -3040,7 +3033,8 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
syncref);
snd_iprintf(buffer,
- "ClearTrackMarker = %s, Transmit in %s Channel Mode, Auto Input %s\n",
+ "ClearTrackMarker = %s, Transmit in %s Channel Mode, "
+ "Auto Input %s\n",
(hdspm->
control_register & HDSPM_clr_tms) ? "on" : "off",
(hdspm->
@@ -3141,7 +3135,7 @@ static void
snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
struct snd_info_buffer *buffer)
{
- struct hdspm *hdspm = (struct hdspm *) entry->private_data;
+ struct hdspm *hdspm = entry->private_data;
unsigned int status;
unsigned int status2;
unsigned int timecode;
@@ -3171,14 +3165,14 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
(status & HDSPM_midi1IRQPending) ? 1 : 0,
hdspm->irq_count);
snd_iprintf(buffer,
- "HW pointer: id = %d, rawptr = %d (%d->%d) estimated= %ld (bytes)\n",
+ "HW pointer: id = %d, rawptr = %d (%d->%d) "
+ "estimated= %ld (bytes)\n",
((status & HDSPM_BufferID) ? 1 : 0),
(status & HDSPM_BufferPositionMask),
- (status & HDSPM_BufferPositionMask) % (2 *
- (int)hdspm->
- period_bytes),
- ((status & HDSPM_BufferPositionMask) -
- 64) % (2 * (int)hdspm->period_bytes),
+ (status & HDSPM_BufferPositionMask) %
+ (2 * (int)hdspm->period_bytes),
+ ((status & HDSPM_BufferPositionMask) - 64) %
+ (2 * (int)hdspm->period_bytes),
(long) hdspm_hw_pointer(hdspm) * 4);
snd_iprintf(buffer,
@@ -3188,16 +3182,15 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
snd_iprintf(buffer,
- "Register: ctrl1=0x%x, status1=0x%x, status2=0x%x, timecode=0x%x\n",
+ "Register: ctrl1=0x%x, status1=0x%x, status2=0x%x, "
+ "timecode=0x%x\n",
hdspm->control_register,
status, status2, timecode);
snd_iprintf(buffer, "--- Settings ---\n");
- x = 1 << (6 +
- hdspm_decode_latency(hdspm->
- control_register &
- HDSPM_LatencyMask));
+ x = 1 << (6 + hdspm_decode_latency(hdspm->control_register &
+ HDSPM_LatencyMask));
snd_iprintf(buffer,
"Size (Latency): %d samples (2 periods of %lu bytes)\n",
@@ -3280,14 +3273,15 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
snd_iprintf(buffer, "--- Status:\n");
snd_iprintf(buffer, "Word: %s Frequency: %d\n",
- (status & HDSPM_AES32_wcLock)? "Sync " : "No Lock",
- HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF));
+ (status & HDSPM_AES32_wcLock)? "Sync " : "No Lock",
+ HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF));
for (x = 0; x < 8; x++) {
snd_iprintf(buffer, "AES%d: %s Frequency: %d\n",
- x+1,
- (status2 & (HDSPM_LockAES >> x))? "Sync ": "No Lock",
- HDSPM_bit2freq((timecode >> (4*x)) & 0xF));
+ x+1,
+ (status2 & (HDSPM_LockAES >> x)) ?
+ "Sync ": "No Lock",
+ HDSPM_bit2freq((timecode >> (4*x)) & 0xF));
}
switch (hdspm_autosync_ref(hdspm)) {
@@ -3313,12 +3307,11 @@ static void
snd_hdspm_proc_read_debug(struct snd_info_entry * entry,
struct snd_info_buffer *buffer)
{
- struct hdspm *hdspm = (struct hdspm *)entry->private_data;
+ struct hdspm *hdspm = entry->private_data;
int j,i;
- for (i = 0; i < 256 /* 1024*64 */; i += j)
- {
+ for (i = 0; i < 256 /* 1024*64 */; i += j) {
snd_iprintf(buffer, "0x%08X: ", i);
for (j = 0; j < 16; j += 4)
snd_iprintf(buffer, "%08X ", hdspm_read(hdspm, i + j));
@@ -3361,14 +3354,20 @@ static int snd_hdspm_set_defaults(struct hdspm * hdspm)
/* set defaults: */
if (hdspm->is_aes32)
- hdspm->control_register = HDSPM_ClockModeMaster | /* Master Cloack Mode on */
- hdspm_encode_latency(7) | /* latency maximum = 8192 samples */
+ hdspm->control_register =
+ HDSPM_ClockModeMaster | /* Master Cloack Mode on */
+ hdspm_encode_latency(7) | /* latency maximum =
+ * 8192 samples
+ */
HDSPM_SyncRef0 | /* AES1 is syncclock */
HDSPM_LineOut | /* Analog output in */
HDSPM_Professional; /* Professional mode */
else
- hdspm->control_register = HDSPM_ClockModeMaster | /* Master Cloack Mode on */
- hdspm_encode_latency(7) | /* latency maximum = 8192 samples */
+ hdspm->control_register =
+ HDSPM_ClockModeMaster | /* Master Cloack Mode on */
+ hdspm_encode_latency(7) | /* latency maximum =
+ * 8192 samples
+ */
HDSPM_InputCoaxial | /* Input Coax not Optical */
HDSPM_SyncRef_MADI | /* Madi is syncclock */
HDSPM_LineOut | /* Analog output in */
@@ -3399,7 +3398,8 @@ static int snd_hdspm_set_defaults(struct hdspm * hdspm)
if (line_outs_monitor[hdspm->dev]) {
- snd_printk(KERN_INFO "HDSPM: sending all playback streams to line outs.\n");
+ snd_printk(KERN_INFO "HDSPM: "
+ "sending all playback streams to line outs.\n");
for (i = 0; i < HDSPM_MIXER_CHANNELS; i++) {
if (hdspm_write_pb_gain(hdspm, i, i, UNITY_GAIN))
@@ -3448,20 +3448,16 @@ static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id)
if (audio) {
if (hdspm->capture_substream)
- snd_pcm_period_elapsed(hdspm->pcm->
- streams
- [SNDRV_PCM_STREAM_CAPTURE].
- substream);
+ snd_pcm_period_elapsed(hdspm->capture_substream);
if (hdspm->playback_substream)
- snd_pcm_period_elapsed(hdspm->pcm->
- streams
- [SNDRV_PCM_STREAM_PLAYBACK].
- substream);
+ snd_pcm_period_elapsed(hdspm->playback_substream);
}
if (midi0 && midi0status) {
- /* we disable interrupts for this input until processing is done */
+ /* we disable interrupts for this input until processing
+ * is done
+ */
hdspm->control_register &= ~HDSPM_Midi0InterruptEnable;
hdspm_write(hdspm, HDSPM_controlRegister,
hdspm->control_register);
@@ -3469,7 +3465,9 @@ static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id)
schedule = 1;
}
if (midi1 && midi1status) {
- /* we disable interrupts for this input until processing is done */
+ /* we disable interrupts for this input until processing
+ * is done
+ */
hdspm->control_register &= ~HDSPM_Midi1InterruptEnable;
hdspm_write(hdspm, HDSPM_controlRegister,
hdspm->control_register);
@@ -3501,16 +3499,16 @@ static char *hdspm_channel_buffer_location(struct hdspm * hdspm,
snd_assert(channel >= 0
|| channel < HDSPM_MAX_CHANNELS, return NULL);
- if ((mapped_channel = hdspm->channel_map[channel]) < 0)
+ mapped_channel = hdspm->channel_map[channel];
+ if (mapped_channel < 0)
return NULL;
- if (stream == SNDRV_PCM_STREAM_CAPTURE) {
+ if (stream == SNDRV_PCM_STREAM_CAPTURE)
return hdspm->capture_buffer +
mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES;
- } else {
+ else
return hdspm->playback_buffer +
mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES;
- }
}
@@ -3525,9 +3523,9 @@ static int snd_hdspm_playback_copy(struct snd_pcm_substream *substream,
snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4,
return -EINVAL);
- channel_buf = hdspm_channel_buffer_location(hdspm,
- substream->pstr->
- stream, channel);
+ channel_buf =
+ hdspm_channel_buffer_location(hdspm, substream->pstr->stream,
+ channel);
snd_assert(channel_buf != NULL, return -EIO);
@@ -3544,9 +3542,9 @@ static int snd_hdspm_capture_copy(struct snd_pcm_substream *substream,
snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4,
return -EINVAL);
- channel_buf = hdspm_channel_buffer_location(hdspm,
- substream->pstr->
- stream, channel);
+ channel_buf =
+ hdspm_channel_buffer_location(hdspm, substream->pstr->stream,
+ channel);
snd_assert(channel_buf != NULL, return -EIO);
return copy_to_user(dst, channel_buf + pos * 4, count * 4);
}
@@ -3559,8 +3557,8 @@ static int snd_hdspm_hw_silence(struct snd_pcm_substream *substream,
char *channel_buf;
channel_buf =
- hdspm_channel_buffer_location(hdspm, substream->pstr->stream,
- channel);
+ hdspm_channel_buffer_location(hdspm, substream->pstr->stream,
+ channel);
snd_assert(channel_buf != NULL, return -EIO);
memset(channel_buf + pos * 4, 0, count * 4);
return 0;
@@ -3616,7 +3614,7 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
other_pid = hdspm->playback_pid;
}
- if ((other_pid > 0) && (this_pid != other_pid)) {
+ if (other_pid > 0 && this_pid != other_pid) {
/* The other stream is open, and not by the same
task as this one. Make sure that the parameters
@@ -3633,7 +3631,7 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
if (params_period_size(params) != hdspm->period_bytes / 4) {
spin_unlock_irq(&hdspm->lock);
_snd_pcm_hw_param_setempty(params,
- SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
+ SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
return -EBUSY;
}
@@ -3644,7 +3642,8 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
/* how to make sure that the rate matches an externally-set one ? */
spin_lock_irq(&hdspm->lock);
- if ((err = hdspm_set_rate(hdspm, params_rate(params), 0)) < 0) {
+ err = hdspm_set_rate(hdspm, params_rate(params), 0);
+ if (err < 0) {
spin_unlock_irq(&hdspm->lock);
_snd_pcm_hw_param_setempty(params,
SNDRV_PCM_HW_PARAM_RATE);
@@ -3652,16 +3651,17 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
}
spin_unlock_irq(&hdspm->lock);
- if ((err =
- hdspm_set_interrupt_interval(hdspm,
- params_period_size(params))) <
- 0) {
+ err = hdspm_set_interrupt_interval(hdspm,
+ params_period_size(params));
+ if (err < 0) {
_snd_pcm_hw_param_setempty(params,
SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
return err;
}
- /* Memory allocation, takashi's method, dont know if we should spinlock */
+ /* Memory allocation, takashi's method, dont know if we should
+ * spinlock
+ */
/* malloc all buffer even if not enabled to get sure */
/* Update for MADI rev 204: we need to allocate for all channels,
* otherwise it doesn't work at 96kHz */
@@ -3746,7 +3746,8 @@ static int snd_hdspm_channel_info(struct snd_pcm_substream *substream,
snd_assert(info->channel < HDSPM_MAX_CHANNELS, return -EINVAL);
- if ((mapped_channel = hdspm->channel_map[info->channel]) < 0)
+ mapped_channel = hdspm->channel_map[info->channel];
+ if (mapped_channel < 0)
return -EINVAL;
info->offset = mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES;
@@ -3760,15 +3761,13 @@ static int snd_hdspm_ioctl(struct snd_pcm_substream *substream,
{
switch (cmd) {
case SNDRV_PCM_IOCTL1_RESET:
- {
- return snd_hdspm_reset(substream);
- }
+ return snd_hdspm_reset(substream);
case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
- {
- struct snd_pcm_channel_info *info = arg;
- return snd_hdspm_channel_info(substream, info);
- }
+ {
+ struct snd_pcm_channel_info *info = arg;
+ return snd_hdspm_channel_info(substream, info);
+ }
default:
break;
}
@@ -3979,9 +3978,12 @@ static int snd_hdspm_hw_rule_channels(struct snd_pcm_hw_params *params,
}
-static unsigned int hdspm_aes32_sample_rates[] = { 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 };
+static unsigned int hdspm_aes32_sample_rates[] = {
+ 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000
+};
-static struct snd_pcm_hw_constraint_list hdspm_hw_constraints_aes32_sample_rates = {
+static struct snd_pcm_hw_constraint_list
+hdspm_hw_constraints_aes32_sample_rates = {
.count = ARRAY_SIZE(hdspm_aes32_sample_rates),
.list = hdspm_aes32_sample_rates,
.mask = 0
@@ -4107,7 +4109,7 @@ static int snd_hdspm_hwdep_dummy_op(struct snd_hwdep * hw, struct file *file)
static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file,
unsigned int cmd, unsigned long arg)
{
- struct hdspm *hdspm = (struct hdspm *) hw->private_data;
+ struct hdspm *hdspm = hw->private_data;
struct hdspm_mixer_ioctl mixer;
struct hdspm_config_info info;
struct hdspm_version hdspm_version;
@@ -4115,11 +4117,12 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file,
switch (cmd) {
-
case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS:
if (copy_from_user(&rms, (void __user *)arg, sizeof(rms)))
return -EFAULT;
- /* maybe there is a chance to memorymap in future so dont touch just copy */
+ /* maybe there is a chance to memorymap in future
+ * so dont touch just copy
+ */
if(copy_to_user_fromio((void __user *)rms.peak,
hdspm->iobase+HDSPM_MADI_peakrmsbase,
sizeof(struct hdspm_peak_rms)) != 0 )
@@ -4131,21 +4134,16 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file,
case SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO:
spin_lock_irq(&hdspm->lock);
- info.pref_sync_ref =
- (unsigned char) hdspm_pref_sync_ref(hdspm);
- info.wordclock_sync_check =
- (unsigned char) hdspm_wc_sync_check(hdspm);
+ info.pref_sync_ref = hdspm_pref_sync_ref(hdspm);
+ info.wordclock_sync_check = hdspm_wc_sync_check(hdspm);
info.system_sample_rate = hdspm->system_sample_rate;
info.autosync_sample_rate =
hdspm_external_sample_rate(hdspm);
- info.system_clock_mode =
- (unsigned char) hdspm_system_clock_mode(hdspm);
- info.clock_source =
- (unsigned char) hdspm_clock_source(hdspm);
- info.autosync_ref =
- (unsigned char) hdspm_autosync_ref(hdspm);
- info.line_out = (unsigned char) hdspm_line_out(hdspm);
+ info.system_clock_mode = hdspm_system_clock_mode(hdspm);
+ info.clock_source = hdspm_clock_source(hdspm);
+ info.autosync_ref = hdspm_autosync_ref(hdspm);
+ info.line_out = hdspm_line_out(hdspm);
info.passthru = 0;
spin_unlock_irq(&hdspm->lock);
if (copy_to_user((void __user *) arg, &info, sizeof(info)))
@@ -4162,8 +4160,8 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file,
case SNDRV_HDSPM_IOCTL_GET_MIXER:
if (copy_from_user(&mixer, (void __user *)arg, sizeof(mixer)))
return -EFAULT;
- if (copy_to_user
- ((void __user *)mixer.mixer, hdspm->mixer, sizeof(struct hdspm_mixer)))
+ if (copy_to_user((void __user *)mixer.mixer, hdspm->mixer,
+ sizeof(struct hdspm_mixer)))
return -EFAULT;
break;
@@ -4206,7 +4204,8 @@ static int __devinit snd_hdspm_create_hwdep(struct snd_card *card,
struct snd_hwdep *hw;
int err;
- if ((err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw)) < 0)
+ err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw);
+ if (err < 0)
return err;
hdspm->hwdep = hw;
@@ -4232,15 +4231,15 @@ static int __devinit snd_hdspm_preallocate_memory(struct hdspm * hdspm)
pcm = hdspm->pcm;
-/* wanted = HDSPM_DMA_AREA_BYTES + 4096;*/ /* dont know why, but it works */
wanted = HDSPM_DMA_AREA_BYTES;
- if ((err =
+ err =
snd_pcm_lib_preallocate_pages_for_all(pcm,
SNDRV_DMA_TYPE_DEV_SG,
snd_dma_pci_data(hdspm->pci),
wanted,
- wanted)) < 0) {
+ wanted);
+ if (err < 0) {
snd_printdd("Could not preallocate %zd Bytes\n", wanted);
return err;
@@ -4256,8 +4255,7 @@ static void hdspm_set_sgbuf(struct hdspm * hdspm, struct snd_sg_buf *sgbuf,
int i;
for (i = 0; i < (channels * 16); i++)
hdspm_write(hdspm, reg + 4 * i,
- snd_pcm_sgbuf_get_addr(sgbuf,
- (size_t) 4096 * i));
+ snd_pcm_sgbuf_get_addr(sgbuf, (size_t) 4096 * i));
}
/* ------------- ALSA Devices ---------------------------- */
@@ -4267,7 +4265,8 @@ static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
struct snd_pcm *pcm;
int err;
- if ((err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm)) < 0)
+ err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm);
+ if (err < 0)
return err;
hdspm->pcm = pcm;
@@ -4281,7 +4280,8 @@ static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
- if ((err = snd_hdspm_preallocate_memory(hdspm)) < 0)
+ err = snd_hdspm_preallocate_memory(hdspm);
+ if (err < 0)
return err;
return 0;
@@ -4299,19 +4299,24 @@ static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
int err;
snd_printdd("Create card...\n");
- if ((err = snd_hdspm_create_pcm(card, hdspm)) < 0)
+ err = snd_hdspm_create_pcm(card, hdspm);
+ if (err < 0)
return err;
- if ((err = snd_hdspm_create_midi(card, hdspm, 0)) < 0)
+ err = snd_hdspm_create_midi(card, hdspm, 0);
+ if (err < 0)
return err;
- if ((err = snd_hdspm_create_midi(card, hdspm, 1)) < 0)
+ err = snd_hdspm_create_midi(card, hdspm, 1);
+ if (err < 0)
return err;
- if ((err = snd_hdspm_create_controls(card, hdspm)) < 0)
+ err = snd_hdspm_create_controls(card, hdspm);
+ if (err < 0)
return err;
- if ((err = snd_hdspm_create_hwdep(card, hdspm)) < 0)
+ err = snd_hdspm_create_hwdep(card, hdspm);
+ if (err < 0)
return err;
snd_printdd("proc init...\n");
@@ -4326,7 +4331,8 @@ static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
hdspm->playback_substream = NULL;
snd_printdd("Set defaults...\n");
- if ((err = snd_hdspm_set_defaults(hdspm)) < 0)
+ err = snd_hdspm_set_defaults(hdspm);
+ if (err < 0)
return err;
snd_printdd("Update mixer controls...\n");
@@ -4334,7 +4340,8 @@ static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
snd_printdd("Initializeing complete ???\n");
- if ((err = snd_card_register(card)) < 0) {
+ err = snd_card_register(card);
+ if (err < 0) {
snd_printk(KERN_ERR "HDSPM: error registering card\n");
return err;
}
@@ -4344,36 +4351,18 @@ static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
return 0;
}
-static int __devinit snd_hdspm_create(struct snd_card *card, struct hdspm * hdspm,
+static int __devinit snd_hdspm_create(struct snd_card *card,
+ struct hdspm *hdspm,
int precise_ptr, int enable_monitor)
{
struct pci_dev *pci = hdspm->pci;
int err;
- int i;
-
unsigned long io_extent;
hdspm->irq = -1;
- hdspm->irq_count = 0;
-
- hdspm->midi[0].rmidi = NULL;
- hdspm->midi[1].rmidi = NULL;
- hdspm->midi[0].input = NULL;
- hdspm->midi[1].input = NULL;
- hdspm->midi[0].output = NULL;
- hdspm->midi[1].output = NULL;
+
spin_lock_init(&hdspm->midi[0].lock);
spin_lock_init(&hdspm->midi[1].lock);
- hdspm->iobase = NULL;
- hdspm->control_register = 0;
- hdspm->control2_register = 0;
-
- hdspm->playback_buffer = NULL;
- hdspm->capture_buffer = NULL;
-
- for (i = 0; i < HDSPM_MAX_CHANNELS; ++i)
- hdspm->playback_mixer_ctls[i] = NULL;
- hdspm->mixer = NULL;
hdspm->card = card;
@@ -4396,12 +4385,14 @@ static int __devinit snd_hdspm_create(struct snd_card *card, struct hdspm * hdsp
hdspm->card_name = "RME HDSPM MADI";
}
- if ((err = pci_enable_device(pci)) < 0)
+ err = pci_enable_device(pci);
+ if (err < 0)
return err;
pci_set_master(hdspm->pci);
- if ((err = pci_request_regions(pci, "hdspm")) < 0)
+ err = pci_request_regions(pci, "hdspm");
+ if (err < 0)
return err;
hdspm->port = pci_resource_start(pci, 0);
@@ -4411,8 +4402,10 @@ static int __devinit snd_hdspm_create(struct snd_card *card, struct hdspm * hdsp
hdspm->port, hdspm->port + io_extent - 1);
- if ((hdspm->iobase = ioremap_nocache(hdspm->port, io_extent)) == NULL) {
- snd_printk(KERN_ERR "HDSPM: unable to remap region 0x%lx-0x%lx\n",
+ hdspm->iobase = ioremap_nocache(hdspm->port, io_extent);
+ if (!hdspm->iobase) {
+ snd_printk(KERN_ERR "HDSPM: "
+ "unable to remap region 0x%lx-0x%lx\n",
hdspm->port, hdspm->port + io_extent - 1);
return -EBUSY;
}
@@ -4435,9 +4428,10 @@ static int __devinit snd_hdspm_create(struct snd_card *card, struct hdspm * hdsp
snd_printdd("kmalloc Mixer memory of %zd Bytes\n",
sizeof(struct hdspm_mixer));
- if ((hdspm->mixer = kmalloc(sizeof(struct hdspm_mixer), GFP_KERNEL))
- == NULL) {
- snd_printk(KERN_ERR "HDSPM: unable to kmalloc Mixer memory of %d Bytes\n",
+ hdspm->mixer = kzalloc(sizeof(struct hdspm_mixer), GFP_KERNEL);
+ if (!hdspm->mixer) {
+ snd_printk(KERN_ERR "HDSPM: "
+ "unable to kmalloc Mixer memory of %d Bytes\n",
(int)sizeof(struct hdspm_mixer));
return err;
}
@@ -4447,7 +4441,8 @@ static int __devinit snd_hdspm_create(struct snd_card *card, struct hdspm * hdsp
hdspm->qs_channels = MADI_QS_CHANNELS;
snd_printdd("create alsa devices.\n");
- if ((err = snd_hdspm_create_alsa_devices(card, hdspm)) < 0)
+ err = snd_hdspm_create_alsa_devices(card, hdspm);
+ if (err < 0)
return err;
snd_hdspm_initialize_midi_flush(hdspm);
@@ -4462,9 +4457,8 @@ static int snd_hdspm_free(struct hdspm * hdspm)
/* stop th audio, and cancel all interrupts */
hdspm->control_register &=
- ~(HDSPM_Start | HDSPM_AudioInterruptEnable
- | HDSPM_Midi0InterruptEnable |
- HDSPM_Midi1InterruptEnable);
+ ~(HDSPM_Start | HDSPM_AudioInterruptEnable |
+ HDSPM_Midi0InterruptEnable | HDSPM_Midi1InterruptEnable);
hdspm_write(hdspm, HDSPM_controlRegister,
hdspm->control_register);
}
@@ -4472,7 +4466,6 @@ static int snd_hdspm_free(struct hdspm * hdspm)
if (hdspm->irq >= 0)
free_irq(hdspm->irq, (void *) hdspm);
-
kfree(hdspm->mixer);
if (hdspm->iobase)
@@ -4487,7 +4480,7 @@ static int snd_hdspm_free(struct hdspm * hdspm)
static void snd_hdspm_card_free(struct snd_card *card)
{
- struct hdspm *hdspm = (struct hdspm *) card->private_data;
+ struct hdspm *hdspm = card->private_data;
if (hdspm)
snd_hdspm_free(hdspm);
@@ -4508,20 +4501,21 @@ static int __devinit snd_hdspm_probe(struct pci_dev *pci,
return -ENOENT;
}
- if (!(card = snd_card_new(index[dev], id[dev],
- THIS_MODULE, sizeof(struct hdspm))))
+ card = snd_card_new(index[dev], id[dev],
+ THIS_MODULE, sizeof(struct hdspm));
+ if (!card)
return -ENOMEM;
- hdspm = (struct hdspm *) card->private_data;
+ hdspm = card->private_data;
card->private_free = snd_hdspm_card_free;
hdspm->dev = dev;
hdspm->pci = pci;
snd_card_set_dev(card, &pci->dev);
- if ((err =
- snd_hdspm_create(card, hdspm, precise_ptr[dev],
- enable_monitor[dev])) < 0) {
+ err = snd_hdspm_create(card, hdspm, precise_ptr[dev],
+ enable_monitor[dev]);
+ if (err < 0) {
snd_card_free(card);
return err;
}
@@ -4530,7 +4524,8 @@ static int __devinit snd_hdspm_probe(struct pci_dev *pci,
sprintf(card->longname, "%s at 0x%lx, irq %d", hdspm->card_name,
hdspm->port, hdspm->irq);
- if ((err = snd_card_register(card)) < 0) {
+ err = snd_card_register(card);
+ if (err < 0) {
snd_card_free(card);
return err;
}
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
index 2de27405a0bd..34f96f12e5bf 100644
--- a/sound/pci/rme9652/rme9652.c
+++ b/sound/pci/rme9652/rme9652.c
@@ -1067,14 +1067,7 @@ static int rme9652_set_spdif_output(struct snd_rme9652 *rme9652, int out)
return 0;
}
-static int snd_rme9652_info_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_rme9652_info_spdif_out snd_ctl_boolean_mono_info
static int snd_rme9652_get_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -1338,14 +1331,7 @@ static int snd_rme9652_put_thru(struct snd_kcontrol *kcontrol, struct snd_ctl_el
.put = snd_rme9652_put_passthru, \
.get = snd_rme9652_get_passthru }
-static int snd_rme9652_info_passthru(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_rme9652_info_passthru snd_ctl_boolean_mono_info
static int snd_rme9652_get_passthru(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -1445,14 +1431,7 @@ static int snd_rme9652_get_adat_sync(struct snd_kcontrol *kcontrol, struct snd_c
.info = snd_rme9652_info_tc_valid, \
.get = snd_rme9652_get_tc_valid }
-static int snd_rme9652_info_tc_valid(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_rme9652_info_tc_valid snd_ctl_boolean_mono_info
static int snd_rme9652_get_tc_valid(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
index 9f25d93cbec2..44a7f5fad573 100644
--- a/sound/pci/sonicvibes.c
+++ b/sound/pci/sonicvibes.c
@@ -1,6 +1,6 @@
/*
* Driver for S3 SonicVibes soundcard
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
* BUGS:
* It looks like 86c617 rev 3 doesn't supports DDMA buffers above 16MB?
@@ -42,7 +42,7 @@
#include <asm/io.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("S3 SonicVibes PCI");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{S3,SonicVibes PCI}}");
diff --git a/sound/pci/trident/Makefile b/sound/pci/trident/Makefile
index 65bc5b703239..65f2c218324c 100644
--- a/sound/pci/trident/Makefile
+++ b/sound/pci/trident/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
snd-trident-objs := trident.o trident_main.o trident_memory.o
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c
index 9145f7c57fb0..84884567df6a 100644
--- a/sound/pci/trident/trident.c
+++ b/sound/pci/trident/trident.c
@@ -30,7 +30,7 @@
#include <sound/trident.h>
#include <sound/initval.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, <audio@tridentmicro.com>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, <audio@tridentmicro.com>");
MODULE_DESCRIPTION("Trident 4D-WaveDX/NX & SiS SI7018");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Trident,4DWave DX},"
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
index 7ca606272460..a235e034a690 100644
--- a/sound/pci/trident/trident_main.c
+++ b/sound/pci/trident/trident_main.c
@@ -1,5 +1,5 @@
/*
- * Maintained by Jaroslav Kysela <perex@suse.cz>
+ * Maintained by Jaroslav Kysela <perex@perex.cz>
* Originated by audio@tridentmicro.com
* Fri Feb 19 15:55:28 MST 1999
* Routines for control of Trident 4DWave (DX and NX) chip
@@ -2317,15 +2317,7 @@ int __devinit snd_trident_spdif_pcm(struct snd_trident * trident,
Description: enable/disable S/PDIF out from ac97 mixer
---------------------------------------------------------------------------*/
-static int snd_trident_spdif_control_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_trident_spdif_control_info snd_ctl_boolean_mono_info
static int snd_trident_spdif_control_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -2545,15 +2537,7 @@ static struct snd_kcontrol_new snd_trident_spdif_stream __devinitdata =
Description: enable/disable rear path for ac97
---------------------------------------------------------------------------*/
-static int snd_trident_ac97_control_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_trident_ac97_control_info snd_ctl_boolean_mono_info
static int snd_trident_ac97_control_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
diff --git a/sound/pci/trident/trident_memory.c b/sound/pci/trident/trident_memory.c
index aff3f874131c..847b8c6d5c0a 100644
--- a/sound/pci/trident/trident_memory.c
+++ b/sound/pci/trident/trident_memory.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Copyright (c) by Takashi Iwai <tiwai@suse.de>
* Copyright (c) by Scott McNab <sdm@fractalgraphics.com.au>
*
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index 6ea09df0c73a..cf62d2ab8d7c 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -3,7 +3,7 @@
*
* VT82C686A/B/C, VT8233A/C, VT8235
*
- * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz>
* Tjeerd.Mulder <Tjeerd.Mulder@fujitsu-siemens.com>
* 2002 Takashi Iwai <tiwai@suse.de>
*
@@ -68,7 +68,7 @@
#define POINTER_DEBUG
#endif
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("VIA VT82xx audio");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{VIA,VT82C686A/B/C,pci},{VIA,VT8233A/C,8235}}");
@@ -1572,15 +1572,7 @@ static struct snd_kcontrol_new snd_via8233_capture_source __devinitdata = {
.put = snd_via8233_capture_source_put,
};
-static int snd_via8233_dxs3_spdif_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_via8233_dxs3_spdif_info snd_ctl_boolean_mono_info
static int snd_via8233_dxs3_spdif_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -2098,7 +2090,7 @@ static int snd_via82xx_chip_init(struct via82xx *chip)
pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval);
if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */
break;
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
} while (time_before(jiffies, end_time));
if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY)
@@ -2117,7 +2109,7 @@ static int snd_via82xx_chip_init(struct via82xx *chip)
chip->ac97_secondary = 1;
goto __ac97_ok2;
}
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
} while (time_before(jiffies, end_time));
/* This is ok, the most of motherboards have only one codec */
@@ -2371,6 +2363,7 @@ static struct snd_pci_quirk dxs_whitelist[] __devinitdata = {
SND_PCI_QUIRK(0x1071, 0, "Diverse Notebook", VIA_DXS_NO_VRA),
SND_PCI_QUIRK(0x10cf, 0x118e, "FSC Laptop", VIA_DXS_ENABLE),
SND_PCI_QUIRK(0x1106, 0, "ASRock", VIA_DXS_SRC),
+ SND_PCI_QUIRK(0x1297, 0xa231, "Shuttle AK31v2", VIA_DXS_SRC),
SND_PCI_QUIRK(0x1297, 0xa232, "Shuttle", VIA_DXS_ENABLE),
SND_PCI_QUIRK(0x1297, 0xc160, "Shuttle Sk41G", VIA_DXS_ENABLE),
SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte GA-7VAXP", VIA_DXS_ENABLE),
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index 72425e73abae..57fb9ae22f93 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -3,7 +3,7 @@
*
* VT82C686A/B/C, VT8233A/C, VT8235
*
- * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz>
* Tjeerd.Mulder <Tjeerd.Mulder@fujitsu-siemens.com>
* 2002 Takashi Iwai <tiwai@suse.de>
*
@@ -50,7 +50,7 @@
#define POINTER_DEBUG
#endif
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("VIA VT82xx modem");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{VIA,VT82C686A/B/C modem,pci}}");
@@ -983,7 +983,7 @@ static int snd_via82xx_chip_init(struct via82xx_modem *chip)
pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval);
if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */
break;
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
} while (time_before(jiffies, end_time));
if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY)
@@ -1001,7 +1001,7 @@ static int snd_via82xx_chip_init(struct via82xx_modem *chip)
chip->ac97_secondary = 1;
goto __ac97_ok2;
}
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
} while (time_before(jiffies, end_time));
/* This is ok, the most of motherboards have only one codec */
diff --git a/sound/pci/vx222/Makefile b/sound/pci/vx222/Makefile
index 058c8bff7c11..a4d08d4de354 100644
--- a/sound/pci/vx222/Makefile
+++ b/sound/pci/vx222/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
snd-vx222-objs := vx222.o vx222_ops.o
diff --git a/sound/pci/ymfpci/Makefile b/sound/pci/ymfpci/Makefile
index 8790c5f3ed02..bd3d514ed76b 100644
--- a/sound/pci/ymfpci/Makefile
+++ b/sound/pci/ymfpci/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
snd-ymfpci-objs := ymfpci.o ymfpci_main.o
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c
index fd9b7b83a884..5c4256a4d4b9 100644
--- a/sound/pci/ymfpci/ymfpci.c
+++ b/sound/pci/ymfpci/ymfpci.c
@@ -1,6 +1,6 @@
/*
* The driver for the Yamaha's DS1/DS1E cards
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -30,7 +30,7 @@
#include <sound/opl3.h>
#include <sound/initval.h>
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Yamaha DS-1 PCI");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Yamaha,YMF724},"
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index ab7a81c35705..1fe39ed28765 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Routines for control of YMF724/740/744/754 chips
*
* This program is free software; you can redistribute it and/or modify
@@ -84,7 +84,6 @@ static int snd_ymfpci_codec_ready(struct snd_ymfpci *chip, int secondary)
do {
if ((snd_ymfpci_readw(chip, reg) & 0x8000) == 0)
return 0;
- set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout_uninterruptible(1);
} while (time_before(jiffies, end_time));
snd_printk(KERN_ERR "codec_ready: codec %i is not ready [0x%x]\n", secondary, snd_ymfpci_readw(chip, reg));
@@ -171,17 +170,6 @@ static u32 snd_ymfpci_calc_lpfQ(u32 rate)
return val[0];
}
-static void snd_ymfpci_pcm_441_volume_set(struct snd_ymfpci_pcm *ypcm)
-{
- unsigned int value;
- struct snd_ymfpci_pcm_mixer *mixer;
-
- mixer = &ypcm->chip->pcm_mixer[ypcm->substream->number];
- value = min_t(unsigned int, mixer->left, 0x7fff) >> 1;
- value |= (min_t(unsigned int, mixer->right, 0x7fff) >> 1) << 16;
- snd_ymfpci_writel(ypcm->chip, YDSXGR_BUF441OUTVOL, value);
-}
-
/*
* Hardware start management
*/
@@ -389,6 +377,7 @@ static int snd_ymfpci_playback_trigger(struct snd_pcm_substream *substream,
{
struct snd_ymfpci *chip = snd_pcm_substream_chip(substream);
struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data;
+ struct snd_kcontrol *kctl = NULL;
int result = 0;
spin_lock(&chip->reg_lock);
@@ -406,6 +395,11 @@ static int snd_ymfpci_playback_trigger(struct snd_pcm_substream *substream,
ypcm->running = 1;
break;
case SNDRV_PCM_TRIGGER_STOP:
+ if (substream->pcm == chip->pcm && !ypcm->use_441_slot) {
+ kctl = chip->pcm_mixer[substream->number].ctl;
+ kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+ }
+ /* fall through */
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_SUSPEND:
chip->ctrl_playback[ypcm->voices[0]->number + 1] = 0;
@@ -419,6 +413,8 @@ static int snd_ymfpci_playback_trigger(struct snd_pcm_substream *substream,
}
__unlock:
spin_unlock(&chip->reg_lock);
+ if (kctl)
+ snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &kctl->id);
return result;
}
static int snd_ymfpci_capture_trigger(struct snd_pcm_substream *substream,
@@ -526,7 +522,6 @@ static void snd_ymfpci_pcm_init_voice(struct snd_ymfpci_pcm *ypcm, unsigned int
ypcm->chip->src441_used = voice->number;
ypcm->use_441_slot = 1;
format |= 0x10000000;
- snd_ymfpci_pcm_441_volume_set(ypcm);
}
if (ypcm->chip->src441_used == voice->number &&
(format & 0x10000000) == 0) {
@@ -667,6 +662,7 @@ static int snd_ymfpci_playback_prepare(struct snd_pcm_substream *substream)
struct snd_ymfpci *chip = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_ymfpci_pcm *ypcm = runtime->private_data;
+ struct snd_kcontrol *kctl;
unsigned int nvoice;
ypcm->period_size = runtime->period_size;
@@ -676,6 +672,12 @@ static int snd_ymfpci_playback_prepare(struct snd_pcm_substream *substream)
for (nvoice = 0; nvoice < runtime->channels; nvoice++)
snd_ymfpci_pcm_init_voice(ypcm, nvoice, runtime,
substream->pcm == chip->pcm);
+
+ if (substream->pcm == chip->pcm && !ypcm->use_441_slot) {
+ kctl = chip->pcm_mixer[substream->number].ctl;
+ kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+ snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &kctl->id);
+ }
return 0;
}
@@ -926,7 +928,6 @@ static int snd_ymfpci_playback_open(struct snd_pcm_substream *substream)
struct snd_ymfpci *chip = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_ymfpci_pcm *ypcm;
- struct snd_kcontrol *kctl;
int err;
if ((err = snd_ymfpci_playback_open_1(substream)) < 0)
@@ -941,10 +942,6 @@ static int snd_ymfpci_playback_open(struct snd_pcm_substream *substream)
chip->rear_opened++;
}
spin_unlock_irq(&chip->reg_lock);
-
- kctl = chip->pcm_mixer[substream->number].ctl;
- kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
- snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &kctl->id);
return 0;
}
@@ -1039,7 +1036,6 @@ static int snd_ymfpci_playback_close(struct snd_pcm_substream *substream)
{
struct snd_ymfpci *chip = snd_pcm_substream_chip(substream);
struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data;
- struct snd_kcontrol *kctl;
spin_lock_irq(&chip->reg_lock);
if (ypcm->output_rear && chip->rear_opened > 0) {
@@ -1047,9 +1043,6 @@ static int snd_ymfpci_playback_close(struct snd_pcm_substream *substream)
ymfpci_close_extension(chip);
}
spin_unlock_irq(&chip->reg_lock);
- kctl = chip->pcm_mixer[substream->number].ctl;
- kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
- snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &kctl->id);
return snd_ymfpci_playback_close_1(substream);
}
@@ -1443,22 +1436,7 @@ static struct snd_kcontrol_new snd_ymfpci_drec_source __devinitdata = {
.get = snd_ymfpci_get_single, .put = snd_ymfpci_put_single, \
.private_value = ((reg) | ((shift) << 16)) }
-static int snd_ymfpci_info_single(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- int reg = kcontrol->private_value & 0xffff;
-
- switch (reg) {
- case YDSXGR_SPDIFOUTCTRL: break;
- case YDSXGR_SPDIFINCTRL: break;
- default: return -EINVAL;
- }
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_ymfpci_info_single snd_ctl_boolean_mono_info
static int snd_ymfpci_get_single(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -1567,17 +1545,30 @@ static int snd_ymfpci_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e
return change;
}
+static int snd_ymfpci_put_nativedacvol(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol);
+ unsigned int reg = YDSXGR_NATIVEDACOUTVOL;
+ unsigned int reg2 = YDSXGR_BUF441OUTVOL;
+ int change;
+ unsigned int value, oval;
+
+ value = ucontrol->value.integer.value[0] & 0x3fff;
+ value |= (ucontrol->value.integer.value[1] & 0x3fff) << 16;
+ spin_lock_irq(&chip->reg_lock);
+ oval = snd_ymfpci_readl(chip, reg);
+ change = value != oval;
+ snd_ymfpci_writel(chip, reg, value);
+ snd_ymfpci_writel(chip, reg2, value);
+ spin_unlock_irq(&chip->reg_lock);
+ return change;
+}
+
/*
* 4ch duplication
*/
-static int snd_ymfpci_info_dup4ch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_ymfpci_info_dup4ch snd_ctl_boolean_mono_info
static int snd_ymfpci_get_dup4ch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -1598,7 +1589,17 @@ static int snd_ymfpci_put_dup4ch(struct snd_kcontrol *kcontrol, struct snd_ctl_e
static struct snd_kcontrol_new snd_ymfpci_controls[] __devinitdata = {
-YMFPCI_DOUBLE("Wave Playback Volume", 0, YDSXGR_NATIVEDACOUTVOL),
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Wave Playback Volume",
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+ .info = snd_ymfpci_info_double,
+ .get = snd_ymfpci_get_double,
+ .put = snd_ymfpci_put_nativedacvol,
+ .private_value = YDSXGR_NATIVEDACOUTVOL,
+ .tlv = { .p = db_scale_native },
+},
YMFPCI_DOUBLE("Wave Capture Volume", 0, YDSXGR_NATIVEDACLOOPVOL),
YMFPCI_DOUBLE("Digital Capture Volume", 0, YDSXGR_NATIVEDACINVOL),
YMFPCI_DOUBLE("Digital Capture Volume", 1, YDSXGR_NATIVEADCINVOL),
@@ -1665,14 +1666,7 @@ static int snd_ymfpci_set_gpio_out(struct snd_ymfpci *chip, int pin, int enable)
return 0;
}
-static int snd_ymfpci_gpio_sw_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_ymfpci_gpio_sw_info snd_ctl_boolean_mono_info
static int snd_ymfpci_gpio_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -1748,8 +1742,6 @@ static int snd_ymfpci_pcm_vol_put(struct snd_kcontrol *kcontrol,
struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data;
if (!ypcm->use_441_slot)
ypcm->update_pcm_vol = 2;
- else
- snd_ymfpci_pcm_441_volume_set(ypcm);
}
spin_unlock_irqrestore(&chip->voice_lock, flags);
return 1;
diff --git a/sound/pcmcia/Makefile b/sound/pcmcia/Makefile
index b6656d48becd..beef2e33b718 100644
--- a/sound/pcmcia/Makefile
+++ b/sound/pcmcia/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
obj-$(CONFIG_SND) += vx/ pdaudiocf/
diff --git a/sound/pcmcia/pdaudiocf/Makefile b/sound/pcmcia/pdaudiocf/Makefile
index 6e194f9b50e3..e892d7299abf 100644
--- a/sound/pcmcia/pdaudiocf/Makefile
+++ b/sound/pcmcia/pdaudiocf/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 2004 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2004 by Jaroslav Kysela <perex@perex.cz>
#
snd-pdaudiocf-objs := pdaudiocf.o pdaudiocf_core.o pdaudiocf_irq.o pdaudiocf_pcm.o
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c
index 2d40cc72f236..de683b08fe03 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c
@@ -1,7 +1,7 @@
/*
* Driver for Sound Core PDAudioCF soundcard
*
- * Copyright (c) 2003 by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 2003 by Jaroslav Kysela <perex@perex.cz>
*
* 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
@@ -33,7 +33,7 @@
#define CARD_NAME "PDAudio-CF"
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Sound Core " CARD_NAME);
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Sound Core," CARD_NAME "}}");
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.h b/sound/pcmcia/pdaudiocf/pdaudiocf.h
index 206e2f5a113f..b0601838112d 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.h
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.h
@@ -1,7 +1,7 @@
/*
* Driver for Sound Cors PDAudioCF soundcard
*
- * Copyright (c) 2003 by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 2003 by Jaroslav Kysela <perex@perex.cz>
*
* 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
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
index 1dfe29b863d3..484c8f9a6f1c 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
@@ -1,7 +1,7 @@
/*
* Driver for Sound Core PDAudioCF soundcard
*
- * Copyright (c) 2003 by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 2003 by Jaroslav Kysela <perex@perex.cz>
*
* 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
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c b/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c
index 5bd69206ba65..54543369949e 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c
@@ -1,7 +1,7 @@
/*
* Driver for Sound Core PDAudioCF soundcard
*
- * Copyright (c) 2003 by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 2003 by Jaroslav Kysela <perex@perex.cz>
*
* 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
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c
index 7f2a4de1d35d..10afcb262d5c 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c
@@ -3,7 +3,7 @@
*
* PCM part
*
- * Copyright (c) 2003 by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) 2003 by Jaroslav Kysela <perex@perex.cz>
*
* 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
diff --git a/sound/pcmcia/vx/Makefile b/sound/pcmcia/vx/Makefile
index 54971f01e968..2bb42ea12f3a 100644
--- a/sound/pcmcia/vx/Makefile
+++ b/sound/pcmcia/vx/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
snd-vxpocket-objs := vxpocket.o vxp_ops.o vxp_mixer.o
diff --git a/sound/pcmcia/vx/vxp_mixer.c b/sound/pcmcia/vx/vxp_mixer.c
index 2b1f996c898d..1eff158b8687 100644
--- a/sound/pcmcia/vx/vxp_mixer.c
+++ b/sound/pcmcia/vx/vxp_mixer.c
@@ -80,14 +80,7 @@ static struct snd_kcontrol_new vx_control_mic_level = {
/*
* mic boost level control (for VXP440)
*/
-static int vx_mic_boost_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define vx_mic_boost_info snd_ctl_boolean_mono_info
static int vx_mic_boost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
diff --git a/sound/ppc/Makefile b/sound/ppc/Makefile
index eacee2d0675c..679c45a8da2c 100644
--- a/sound/ppc/Makefile
+++ b/sound/ppc/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
snd-powermac-objs := powermac.o pmac.o awacs.o burgundy.o daca.o tumbler.o keywest.o beep.o
diff --git a/sound/ppc/beep.c b/sound/ppc/beep.c
index a1aa89f2faf3..566b5ab9d4e8 100644
--- a/sound/ppc/beep.c
+++ b/sound/ppc/beep.c
@@ -236,8 +236,8 @@ int __init snd_pmac_attach_beep(struct snd_pmac *chip)
input_dev->id.product = 0x0001;
input_dev->id.version = 0x0100;
- input_dev->evbit[0] = BIT(EV_SND);
- input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
+ input_dev->evbit[0] = BIT_MASK(EV_SND);
+ input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);
input_dev->event = snd_pmac_beep_event;
input_dev->dev.parent = &chip->pdev->dev;
input_set_drvdata(input_dev, chip);
diff --git a/sound/ppc/daca.c b/sound/ppc/daca.c
index 57202b0f033e..c5a1f0be6a4d 100644
--- a/sound/ppc/daca.c
+++ b/sound/ppc/daca.c
@@ -91,15 +91,7 @@ static int daca_set_volume(struct pmac_daca *mix)
/* deemphasis switch */
-static int daca_info_deemphasis(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define daca_info_deemphasis snd_ctl_boolean_mono_info
static int daca_get_deemphasis(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
index 7a22f0f3784a..4f9b19c90a43 100644
--- a/sound/ppc/pmac.c
+++ b/sound/ppc/pmac.c
@@ -490,35 +490,14 @@ static int snd_pmac_pcm_open(struct snd_pmac *chip, struct pmac_stream *rec,
struct snd_pcm_substream *subs)
{
struct snd_pcm_runtime *runtime = subs->runtime;
- int i, j, fflags;
- static int typical_freqs[] = {
- 44100,
- 22050,
- 11025,
- 0,
- };
- static int typical_freq_flags[] = {
- SNDRV_PCM_RATE_44100,
- SNDRV_PCM_RATE_22050,
- SNDRV_PCM_RATE_11025,
- 0,
- };
+ int i;
/* look up frequency table and fill bit mask */
runtime->hw.rates = 0;
- fflags = chip->freqs_ok;
- for (i = 0; typical_freqs[i]; i++) {
- for (j = 0; j < chip->num_freqs; j++) {
- if ((chip->freqs_ok & (1 << j)) &&
- chip->freq_table[j] == typical_freqs[i]) {
- runtime->hw.rates |= typical_freq_flags[i];
- fflags &= ~(1 << j);
- break;
- }
- }
- }
- if (fflags) /* rest */
- runtime->hw.rates |= SNDRV_PCM_RATE_KNOT;
+ for (i = 0; i < chip->num_freqs; i++)
+ if (chip->freqs_ok & (1 << i))
+ runtime->hw.rates |=
+ snd_pcm_rate_to_rate_bit(chip->freq_table[i]);
/* check for minimum and maximum rates */
for (i = 0; i < chip->num_freqs; i++) {
@@ -551,9 +530,6 @@ static int snd_pmac_pcm_open(struct snd_pmac *chip, struct pmac_stream *rec,
runtime->hw.periods_max = rec->cmd.size - 1;
- if (chip->can_duplex)
- snd_pcm_set_sync(subs);
-
/* constraints to fix choppy sound */
snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
return 0;
@@ -1035,29 +1011,6 @@ static int __init snd_pmac_detect(struct snd_pmac *chip)
return 0;
}
-/*
- * exported - boolean info callbacks for ease of programming
- */
-int snd_pmac_boolean_stereo_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 2;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
-
-int snd_pmac_boolean_mono_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
-
#ifdef PMAC_SUPPORT_AUTOMUTE
/*
* auto-mute
diff --git a/sound/ppc/pmac.h b/sound/ppc/pmac.h
index 8394e66ceb00..25c512c2d74d 100644
--- a/sound/ppc/pmac.h
+++ b/sound/ppc/pmac.h
@@ -202,8 +202,8 @@ int snd_pmac_keywest_init(struct pmac_keywest *i2c);
void snd_pmac_keywest_cleanup(struct pmac_keywest *i2c);
/* misc */
-int snd_pmac_boolean_stereo_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo);
-int snd_pmac_boolean_mono_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo);
+#define snd_pmac_boolean_stereo_info snd_ctl_boolean_stereo_info
+#define snd_pmac_boolean_mono_info snd_ctl_boolean_mono_info
int snd_pmac_add_automute(struct snd_pmac *chip);
diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c
index 1aa0b467599f..27b61899fe84 100644
--- a/sound/ppc/snd_ps3.c
+++ b/sound/ppc/snd_ps3.c
@@ -33,7 +33,6 @@
#include <linux/dmapool.h>
#include <linux/dma-mapping.h>
#include <asm/firmware.h>
-#include <linux/io.h>
#include <asm/dma.h>
#include <asm/lv1call.h>
#include <asm/ps3.h>
diff --git a/sound/sh/aica.c b/sound/sh/aica.c
index 739786529ca5..88dc840152ce 100644
--- a/sound/sh/aica.c
+++ b/sound/sh/aica.c
@@ -106,11 +106,14 @@ static void spu_write_wait(void)
static void spu_memset(u32 toi, u32 what, int length)
{
int i;
+ unsigned long flags;
snd_assert(length % 4 == 0, return);
for (i = 0; i < length; i++) {
if (!(i % 8))
spu_write_wait();
+ local_irq_save(flags);
writel(what, toi + SPU_MEMORY_BASE);
+ local_irq_restore(flags);
toi++;
}
}
@@ -118,6 +121,7 @@ static void spu_memset(u32 toi, u32 what, int length)
/* spu_memload - write to SPU address space */
static void spu_memload(u32 toi, void *from, int length)
{
+ unsigned long flags;
u32 *froml = from;
u32 __iomem *to = (u32 __iomem *) (SPU_MEMORY_BASE + toi);
int i;
@@ -128,7 +132,9 @@ static void spu_memload(u32 toi, void *from, int length)
if (!(i % 8))
spu_write_wait();
val = *froml;
+ local_irq_save(flags);
writel(val, to);
+ local_irq_restore(flags);
froml++;
to++;
}
@@ -138,28 +144,36 @@ static void spu_memload(u32 toi, void *from, int length)
static void spu_disable(void)
{
int i;
+ unsigned long flags;
u32 regval;
spu_write_wait();
regval = readl(ARM_RESET_REGISTER);
regval |= 1;
spu_write_wait();
+ local_irq_save(flags);
writel(regval, ARM_RESET_REGISTER);
+ local_irq_restore(flags);
for (i = 0; i < 64; i++) {
spu_write_wait();
regval = readl(SPU_REGISTER_BASE + (i * 0x80));
regval = (regval & ~0x4000) | 0x8000;
spu_write_wait();
+ local_irq_save(flags);
writel(regval, SPU_REGISTER_BASE + (i * 0x80));
+ local_irq_restore(flags);
}
}
/* spu_enable - set spu registers to enable sound output */
static void spu_enable(void)
{
+ unsigned long flags;
u32 regval = readl(ARM_RESET_REGISTER);
regval &= ~1;
spu_write_wait();
+ local_irq_save(flags);
writel(regval, ARM_RESET_REGISTER);
+ local_irq_restore(flags);
}
/*
@@ -168,25 +182,34 @@ static void spu_enable(void)
*/
static void spu_reset(void)
{
+ unsigned long flags;
spu_disable();
spu_memset(0, 0, 0x200000 / 4);
/* Put ARM7 in endless loop */
+ local_irq_save(flags);
ctrl_outl(0xea000002, SPU_MEMORY_BASE);
+ local_irq_restore(flags);
spu_enable();
}
/* aica_chn_start - write to spu to start playback */
static void aica_chn_start(void)
{
+ unsigned long flags;
spu_write_wait();
+ local_irq_save(flags);
writel(AICA_CMD_KICK | AICA_CMD_START, (u32 *) AICA_CONTROL_POINT);
+ local_irq_restore(flags);
}
/* aica_chn_halt - write to spu to halt playback */
static void aica_chn_halt(void)
{
+ unsigned long flags;
spu_write_wait();
+ local_irq_save(flags);
writel(AICA_CMD_KICK | AICA_CMD_STOP, (u32 *) AICA_CONTROL_POINT);
+ local_irq_restore(flags);
}
/* ALSA code below */
@@ -213,12 +236,13 @@ static int aica_dma_transfer(int channels, int buffer_size,
int q, err, period_offset;
struct snd_card_aica *dreamcastcard;
struct snd_pcm_runtime *runtime;
- err = 0;
+ unsigned long flags;
dreamcastcard = substream->pcm->private_data;
period_offset = dreamcastcard->clicks;
period_offset %= (AICA_PERIOD_NUMBER / channels);
runtime = substream->runtime;
for (q = 0; q < channels; q++) {
+ local_irq_save(flags);
err = dma_xfer(AICA_DMA_CHANNEL,
(unsigned long) (runtime->dma_area +
(AICA_BUFFER_SIZE * q) /
@@ -228,9 +252,12 @@ static int aica_dma_transfer(int channels, int buffer_size,
AICA_CHANNEL0_OFFSET + q * CHANNEL_OFFSET +
AICA_PERIOD_SIZE * period_offset,
buffer_size / channels, AICA_DMA_MODE);
- if (unlikely(err < 0))
+ if (unlikely(err < 0)) {
+ local_irq_restore(flags);
break;
+ }
dma_wait_for_completion(AICA_DMA_CHANNEL);
+ local_irq_restore(flags);
}
return err;
}
@@ -451,15 +478,7 @@ static int __init snd_aicapcmchip(struct snd_card_aica
}
/* Mixer controls */
-static int aica_pcmswitch_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define aica_pcmswitch_info snd_ctl_boolean_mono_info
static int aica_pcmswitch_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index e5fb437b86e8..78248808a9d8 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -17,3 +17,23 @@ config SND_SOC_WM8753
config SND_SOC_WM9712
tristate
depends on SND_SOC
+
+# Cirrus Logic CS4270 Codec
+config SND_SOC_CS4270
+ tristate
+ depends on SND_SOC
+
+# Cirrus Logic CS4270 Codec Hardware Mute Support
+# Select if you have external muting circuitry attached to your CS4270.
+config SND_SOC_CS4270_HWMUTE
+ bool
+ depends on SND_SOC_CS4270
+
+# Cirrus Logic CS4270 Codec VD = 3.3V Errata
+# Select if you are affected by the errata where the part will not function
+# if MCLK divide-by-1.5 is selected and VD is set to 3.3V. The driver will
+# not select any sample rates that require MCLK to be divided by 1.5.
+config SND_SOC_CS4270_VD33_ERRATA
+ bool
+ depends on SND_SOC_CS4270
+
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index e39a747a17cf..7ad78e36d506 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -3,9 +3,11 @@ snd-soc-wm8731-objs := wm8731.o
snd-soc-wm8750-objs := wm8750.o
snd-soc-wm8753-objs := wm8753.o
snd-soc-wm9712-objs := wm9712.o
+snd-soc-cs4270-objs := cs4270.o
obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o
obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o
obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o
obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o
obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o
+obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
new file mode 100644
index 000000000000..5d601ad6da70
--- /dev/null
+++ b/sound/soc/codecs/cs4270.c
@@ -0,0 +1,805 @@
+/*
+ * CS4270 ALSA SoC (ASoC) codec driver
+ *
+ * Author: Timur Tabi <timur@freescale.com>
+ *
+ * Copyright 2007 Freescale Semiconductor, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ *
+ * This is an ASoC device driver for the Cirrus Logic CS4270 codec.
+ *
+ * Current features/limitations:
+ *
+ * 1) Software mode is supported. Stand-alone mode is automatically
+ * selected if I2C is disabled or if a CS4270 is not found on the I2C
+ * bus. However, stand-alone mode is only partially implemented because
+ * there is no mechanism yet for this driver and the machine driver to
+ * communicate the values of the M0, M1, MCLK1, and MCLK2 pins.
+ * 2) Only I2C is supported, not SPI
+ * 3) Only Master mode is supported, not Slave.
+ * 4) The machine driver's 'startup' function must call
+ * cs4270_set_dai_sysclk() with the value of MCLK.
+ * 5) Only I2S and left-justified modes are supported
+ * 6) Power management is not supported
+ * 7) The only supported control is volume and hardware mute (if enabled)
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/initval.h>
+#include <linux/i2c.h>
+
+#include "cs4270.h"
+
+/* If I2C is defined, then we support software mode. However, if we're
+ not compiled as module but I2C is, then we can't use I2C calls. */
+#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
+#define USE_I2C
+#endif
+
+/* Private data for the CS4270 */
+struct cs4270_private {
+ unsigned int mclk; /* Input frequency of the MCLK pin */
+ unsigned int mode; /* The mode (I2S or left-justified) */
+};
+
+/* The number of MCLK/LRCK ratios supported by the CS4270 */
+#define NUM_MCLK_RATIOS 9
+
+/* The actual MCLK/LRCK ratios, in increasing numerical order */
+static unsigned int mclk_ratios[NUM_MCLK_RATIOS] =
+ {64, 96, 128, 192, 256, 384, 512, 768, 1024};
+
+/*
+ * Determine the CS4270 samples rates.
+ *
+ * 'freq' is the input frequency to MCLK. The other parameters are ignored.
+ *
+ * The value of MCLK is used to determine which sample rates are supported
+ * by the CS4270. The ratio of MCLK / Fs must be equal to one of nine
+ * support values: 64, 96, 128, 192, 256, 384, 512, 768, and 1024.
+ *
+ * This function calculates the nine ratios and determines which ones match
+ * a standard sample rate. If there's a match, then it is added to the list
+ * of support sample rates.
+ *
+ * This function must be called by the machine driver's 'startup' function,
+ * otherwise the list of supported sample rates will not be available in
+ * time for ALSA.
+ *
+ * Note that in stand-alone mode, the sample rate is determined by input
+ * pins M0, M1, MDIV1, and MDIV2. Also in stand-alone mode, divide-by-3
+ * is not a programmable option. However, divide-by-3 is not an available
+ * option in stand-alone mode. This cases two problems: a ratio of 768 is
+ * not available (it requires divide-by-3) and B) ratios 192 and 384 can
+ * only be selected with divide-by-1.5, but there is an errate that make
+ * this selection difficult.
+ *
+ * In addition, there is no mechanism for communicating with the machine
+ * driver what the input settings can be. This would need to be implemented
+ * for stand-alone mode to work.
+ */
+static int cs4270_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct cs4270_private *cs4270 = codec->private_data;
+ unsigned int rates = 0;
+ unsigned int rate_min = -1;
+ unsigned int rate_max = 0;
+ unsigned int i;
+
+ cs4270->mclk = freq;
+
+ for (i = 0; i < NUM_MCLK_RATIOS; i++) {
+ unsigned int rate = freq / mclk_ratios[i];
+ rates |= snd_pcm_rate_to_rate_bit(rate);
+ if (rate < rate_min)
+ rate_min = rate;
+ if (rate > rate_max)
+ rate_max = rate;
+ }
+ /* FIXME: soc should support a rate list */
+ rates &= ~SNDRV_PCM_RATE_KNOT;
+
+ if (!rates) {
+ printk(KERN_ERR "cs4270: could not find a valid sample rate\n");
+ return -EINVAL;
+ }
+
+ codec_dai->playback.rates = rates;
+ codec_dai->playback.rate_min = rate_min;
+ codec_dai->playback.rate_max = rate_max;
+
+ codec_dai->capture.rates = rates;
+ codec_dai->capture.rate_min = rate_min;
+ codec_dai->capture.rate_max = rate_max;
+
+ return 0;
+}
+
+/*
+ * Configure the codec for the selected audio format
+ *
+ * This function takes a bitmask of SND_SOC_DAIFMT_x bits and programs the
+ * codec accordingly.
+ *
+ * Currently, this function only supports SND_SOC_DAIFMT_I2S and
+ * SND_SOC_DAIFMT_LEFT_J. The CS4270 codec also supports right-justified
+ * data for playback only, but ASoC currently does not support different
+ * formats for playback vs. record.
+ */
+static int cs4270_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
+ unsigned int format)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct cs4270_private *cs4270 = codec->private_data;
+ int ret = 0;
+
+ switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ case SND_SOC_DAIFMT_LEFT_J:
+ cs4270->mode = format & SND_SOC_DAIFMT_FORMAT_MASK;
+ break;
+ default:
+ printk(KERN_ERR "cs4270: invalid DAI format\n");
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+/*
+ * The codec isn't really big-endian or little-endian, since the I2S
+ * interface requires data to be sent serially with the MSbit first.
+ * However, to support BE and LE I2S devices, we specify both here. That
+ * way, ALSA will always match the bit patterns.
+ */
+#define CS4270_FORMATS (SNDRV_PCM_FMTBIT_S8 | \
+ SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \
+ SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \
+ SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \
+ SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | \
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE)
+
+#ifdef USE_I2C
+
+/* CS4270 registers addresses */
+#define CS4270_CHIPID 0x01 /* Chip ID */
+#define CS4270_PWRCTL 0x02 /* Power Control */
+#define CS4270_MODE 0x03 /* Mode Control */
+#define CS4270_FORMAT 0x04 /* Serial Format, ADC/DAC Control */
+#define CS4270_TRANS 0x05 /* Transition Control */
+#define CS4270_MUTE 0x06 /* Mute Control */
+#define CS4270_VOLA 0x07 /* DAC Channel A Volume Control */
+#define CS4270_VOLB 0x08 /* DAC Channel B Volume Control */
+
+#define CS4270_FIRSTREG 0x01
+#define CS4270_LASTREG 0x08
+#define CS4270_NUMREGS (CS4270_LASTREG - CS4270_FIRSTREG + 1)
+
+/* Bit masks for the CS4270 registers */
+#define CS4270_CHIPID_ID 0xF0
+#define CS4270_CHIPID_REV 0x0F
+#define CS4270_PWRCTL_FREEZE 0x80
+#define CS4270_PWRCTL_PDN_ADC 0x20
+#define CS4270_PWRCTL_PDN_DAC 0x02
+#define CS4270_PWRCTL_PDN 0x01
+#define CS4270_MODE_SPEED_MASK 0x30
+#define CS4270_MODE_1X 0x00
+#define CS4270_MODE_2X 0x10
+#define CS4270_MODE_4X 0x20
+#define CS4270_MODE_SLAVE 0x30
+#define CS4270_MODE_DIV_MASK 0x0E
+#define CS4270_MODE_DIV1 0x00
+#define CS4270_MODE_DIV15 0x02
+#define CS4270_MODE_DIV2 0x04
+#define CS4270_MODE_DIV3 0x06
+#define CS4270_MODE_DIV4 0x08
+#define CS4270_MODE_POPGUARD 0x01
+#define CS4270_FORMAT_FREEZE_A 0x80
+#define CS4270_FORMAT_FREEZE_B 0x40
+#define CS4270_FORMAT_LOOPBACK 0x20
+#define CS4270_FORMAT_DAC_MASK 0x18
+#define CS4270_FORMAT_DAC_LJ 0x00
+#define CS4270_FORMAT_DAC_I2S 0x08
+#define CS4270_FORMAT_DAC_RJ16 0x18
+#define CS4270_FORMAT_DAC_RJ24 0x10
+#define CS4270_FORMAT_ADC_MASK 0x01
+#define CS4270_FORMAT_ADC_LJ 0x00
+#define CS4270_FORMAT_ADC_I2S 0x01
+#define CS4270_TRANS_ONE_VOL 0x80
+#define CS4270_TRANS_SOFT 0x40
+#define CS4270_TRANS_ZERO 0x20
+#define CS4270_TRANS_INV_ADC_A 0x08
+#define CS4270_TRANS_INV_ADC_B 0x10
+#define CS4270_TRANS_INV_DAC_A 0x02
+#define CS4270_TRANS_INV_DAC_B 0x04
+#define CS4270_TRANS_DEEMPH 0x01
+#define CS4270_MUTE_AUTO 0x20
+#define CS4270_MUTE_ADC_A 0x08
+#define CS4270_MUTE_ADC_B 0x10
+#define CS4270_MUTE_POLARITY 0x04
+#define CS4270_MUTE_DAC_A 0x01
+#define CS4270_MUTE_DAC_B 0x02
+
+/*
+ * A list of addresses on which this CS4270 could use. I2C addresses are
+ * 7 bits. For the CS4270, the upper four bits are always 1001, and the
+ * lower three bits are determined via the AD2, AD1, and AD0 pins
+ * (respectively).
+ */
+static unsigned short normal_i2c[] = {
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, I2C_CLIENT_END
+};
+I2C_CLIENT_INSMOD;
+
+/*
+ * Pre-fill the CS4270 register cache.
+ *
+ * We use the auto-increment feature of the CS4270 to read all registers in
+ * one shot.
+ */
+static int cs4270_fill_cache(struct snd_soc_codec *codec)
+{
+ u8 *cache = codec->reg_cache;
+ struct i2c_client *i2c_client = codec->control_data;
+ s32 length;
+
+ length = i2c_smbus_read_i2c_block_data(i2c_client,
+ CS4270_FIRSTREG | 0x80, CS4270_NUMREGS, cache);
+
+ if (length != CS4270_NUMREGS) {
+ printk(KERN_ERR "cs4270: I2C read failure, addr=0x%x\n",
+ i2c_client->addr);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/*
+ * Read from the CS4270 register cache.
+ *
+ * This CS4270 registers are cached to avoid excessive I2C I/O operations.
+ * After the initial read to pre-fill the cache, the CS4270 never updates
+ * the register values, so we won't have a cache coherncy problem.
+ */
+static unsigned int cs4270_read_reg_cache(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ u8 *cache = codec->reg_cache;
+
+ if ((reg < CS4270_FIRSTREG) || (reg > CS4270_LASTREG))
+ return -EIO;
+
+ return cache[reg - CS4270_FIRSTREG];
+}
+
+/*
+ * Write to a CS4270 register via the I2C bus.
+ *
+ * This function writes the given value to the given CS4270 register, and
+ * also updates the register cache.
+ *
+ * Note that we don't use the hw_write function pointer of snd_soc_codec.
+ * That's because it's too clunky: the hw_write_t prototype does not match
+ * i2c_smbus_write_byte_data(), and it's just another layer of overhead.
+ */
+static int cs4270_i2c_write(struct snd_soc_codec *codec, unsigned int reg,
+ unsigned int value)
+{
+ u8 *cache = codec->reg_cache;
+
+ if ((reg < CS4270_FIRSTREG) || (reg > CS4270_LASTREG))
+ return -EIO;
+
+ /* Only perform an I2C operation if the new value is different */
+ if (cache[reg - CS4270_FIRSTREG] != value) {
+ struct i2c_client *client = codec->control_data;
+ if (i2c_smbus_write_byte_data(client, reg, value)) {
+ printk(KERN_ERR "cs4270: I2C write failed\n");
+ return -EIO;
+ }
+
+ /* We've written to the hardware, so update the cache */
+ cache[reg - CS4270_FIRSTREG] = value;
+ }
+
+ return 0;
+}
+
+/*
+ * Clock Ratio Selection for Master Mode with I2C enabled
+ *
+ * The data for this chart is taken from Table 5 of the CS4270 reference
+ * manual.
+ *
+ * This table is used to determine how to program the Mode Control register.
+ * It is also used by cs4270_set_dai_sysclk() to tell ALSA which sampling
+ * rates the CS4270 currently supports.
+ *
+ * Each element in this array corresponds to the ratios in mclk_ratios[].
+ * These two arrays need to be in sync.
+ *
+ * 'speed_mode' is the corresponding bit pattern to be written to the
+ * MODE bits of the Mode Control Register
+ *
+ * 'mclk' is the corresponding bit pattern to be wirten to the MCLK bits of
+ * the Mode Control Register.
+ *
+ * In situations where a single ratio is represented by multiple speed
+ * modes, we favor the slowest speed. E.g, for a ratio of 128, we pick
+ * double-speed instead of quad-speed. However, the CS4270 errata states
+ * that Divide-By-1.5 can cause failures, so we avoid that mode where
+ * possible.
+ *
+ * ERRATA: There is an errata for the CS4270 where divide-by-1.5 does not
+ * work if VD = 3.3V. If this effects you, select the
+ * CONFIG_SND_SOC_CS4270_VD33_ERRATA Kconfig option, and the driver will
+ * never select any sample rates that require divide-by-1.5.
+ */
+static struct {
+ u8 speed_mode;
+ u8 mclk;
+} cs4270_mode_ratios[NUM_MCLK_RATIOS] = {
+ {CS4270_MODE_4X, CS4270_MODE_DIV1}, /* 64 */
+#ifndef CONFIG_SND_SOC_CS4270_VD33_ERRATA
+ {CS4270_MODE_4X, CS4270_MODE_DIV15}, /* 96 */
+#endif
+ {CS4270_MODE_2X, CS4270_MODE_DIV1}, /* 128 */
+ {CS4270_MODE_4X, CS4270_MODE_DIV3}, /* 192 */
+ {CS4270_MODE_1X, CS4270_MODE_DIV1}, /* 256 */
+ {CS4270_MODE_2X, CS4270_MODE_DIV3}, /* 384 */
+ {CS4270_MODE_1X, CS4270_MODE_DIV2}, /* 512 */
+ {CS4270_MODE_1X, CS4270_MODE_DIV3}, /* 768 */
+ {CS4270_MODE_1X, CS4270_MODE_DIV4} /* 1024 */
+};
+
+/*
+ * Program the CS4270 with the given hardware parameters.
+ *
+ * The .dai_ops functions are used to provide board-specific data, like
+ * input frequencies, to this driver. This function takes that information,
+ * combines it with the hardware parameters provided, and programs the
+ * hardware accordingly.
+ */
+static int cs4270_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->codec;
+ struct cs4270_private *cs4270 = codec->private_data;
+ unsigned int ret = 0;
+ unsigned int i;
+ unsigned int rate;
+ unsigned int ratio;
+ int reg;
+
+ /* Figure out which MCLK/LRCK ratio to use */
+
+ rate = params_rate(params); /* Sampling rate, in Hz */
+ ratio = cs4270->mclk / rate; /* MCLK/LRCK ratio */
+
+ for (i = 0; i < NUM_MCLK_RATIOS; i++) {
+ if (mclk_ratios[i] == ratio)
+ break;
+ }
+
+ if (i == NUM_MCLK_RATIOS) {
+ /* We did not find a matching ratio */
+ printk(KERN_ERR "cs4270: could not find matching ratio\n");
+ return -EINVAL;
+ }
+
+ /* Freeze and power-down the codec */
+
+ ret = snd_soc_write(codec, CS4270_PWRCTL, CS4270_PWRCTL_FREEZE |
+ CS4270_PWRCTL_PDN_ADC | CS4270_PWRCTL_PDN_DAC |
+ CS4270_PWRCTL_PDN);
+ if (ret < 0) {
+ printk(KERN_ERR "cs4270: I2C write failed\n");
+ return ret;
+ }
+
+ /* Program the mode control register */
+
+ reg = snd_soc_read(codec, CS4270_MODE);
+ reg &= ~(CS4270_MODE_SPEED_MASK | CS4270_MODE_DIV_MASK);
+ reg |= cs4270_mode_ratios[i].speed_mode | cs4270_mode_ratios[i].mclk;
+
+ ret = snd_soc_write(codec, CS4270_MODE, reg);
+ if (ret < 0) {
+ printk(KERN_ERR "cs4270: I2C write failed\n");
+ return ret;
+ }
+
+ /* Program the format register */
+
+ reg = snd_soc_read(codec, CS4270_FORMAT);
+ reg &= ~(CS4270_FORMAT_DAC_MASK | CS4270_FORMAT_ADC_MASK);
+
+ switch (cs4270->mode) {
+ case SND_SOC_DAIFMT_I2S:
+ reg |= CS4270_FORMAT_DAC_I2S | CS4270_FORMAT_ADC_I2S;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ reg |= CS4270_FORMAT_DAC_LJ | CS4270_FORMAT_ADC_LJ;
+ break;
+ default:
+ printk(KERN_ERR "cs4270: unknown format\n");
+ return -EINVAL;
+ }
+
+ ret = snd_soc_write(codec, CS4270_FORMAT, reg);
+ if (ret < 0) {
+ printk(KERN_ERR "cs4270: I2C write failed\n");
+ return ret;
+ }
+
+ /* Disable auto-mute. This feature appears to be buggy, because in
+ some situations, auto-mute will not deactivate when it should. */
+
+ reg = snd_soc_read(codec, CS4270_MUTE);
+ reg &= ~CS4270_MUTE_AUTO;
+ ret = snd_soc_write(codec, CS4270_MUTE, reg);
+ if (ret < 0) {
+ printk(KERN_ERR "cs4270: I2C write failed\n");
+ return ret;
+ }
+
+ /* Thaw and power-up the codec */
+
+ ret = snd_soc_write(codec, CS4270_PWRCTL, 0);
+ if (ret < 0) {
+ printk(KERN_ERR "cs4270: I2C write failed\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+#ifdef CONFIG_SND_SOC_CS4270_HWMUTE
+
+/*
+ * Set the CS4270 external mute
+ *
+ * This function toggles the mute bits in the MUTE register. The CS4270's
+ * mute capability is intended for external muting circuitry, so if the
+ * board does not have the MUTEA or MUTEB pins connected to such circuitry,
+ * then this function will do nothing.
+ */
+static int cs4270_mute(struct snd_soc_codec_dai *dai, int mute)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ int reg6;
+
+ reg6 = snd_soc_read(codec, CS4270_MUTE);
+
+ if (mute)
+ reg6 |= CS4270_MUTE_ADC_A | CS4270_MUTE_ADC_B |
+ CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B;
+ else
+ reg6 &= ~(CS4270_MUTE_ADC_A | CS4270_MUTE_ADC_B |
+ CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B);
+
+ return snd_soc_write(codec, CS4270_MUTE, reg6);
+}
+
+#endif
+
+static int cs4270_i2c_probe(struct i2c_adapter *adap, int addr, int kind);
+
+/*
+ * Notify the driver that a new I2C bus has been found.
+ *
+ * This function is called for each I2C bus in the system. The function
+ * then asks the I2C subsystem to probe that bus at the addresses on which
+ * our device (the CS4270) could exist. If a device is found at one of
+ * those addresses, then our probe function (cs4270_i2c_probe) is called.
+ */
+static int cs4270_i2c_attach(struct i2c_adapter *adapter)
+{
+ return i2c_probe(adapter, &addr_data, cs4270_i2c_probe);
+}
+
+static int cs4270_i2c_detach(struct i2c_client *client)
+{
+ struct snd_soc_codec *codec = i2c_get_clientdata(client);
+
+ i2c_detach_client(client);
+ codec->control_data = NULL;
+
+ kfree(codec->reg_cache);
+ codec->reg_cache = NULL;
+
+ kfree(client);
+ return 0;
+}
+
+/* A list of non-DAPM controls that the CS4270 supports */
+static const struct snd_kcontrol_new cs4270_snd_controls[] = {
+ SOC_DOUBLE_R("Master Playback Volume",
+ CS4270_VOLA, CS4270_VOLB, 0, 0xFF, 1)
+};
+
+static struct i2c_driver cs4270_i2c_driver = {
+ .driver = {
+ .name = "CS4270 I2C",
+ .owner = THIS_MODULE,
+ },
+ .id = I2C_DRIVERID_CS4270,
+ .attach_adapter = cs4270_i2c_attach,
+ .detach_client = cs4270_i2c_detach,
+};
+
+/*
+ * Global variable to store socdev for i2c probe function.
+ *
+ * If struct i2c_driver had a private_data field, we wouldn't need to use
+ * cs4270_socdec. This is the only way to pass the socdev structure to
+ * cs4270_i2c_probe().
+ *
+ * The real solution to cs4270_socdev is to create a mechanism
+ * that maps I2C addresses to snd_soc_device structures. Perhaps the
+ * creation of the snd_soc_device object should be moved out of
+ * cs4270_probe() and into cs4270_i2c_probe(), but that would make this
+ * driver dependent on I2C. The CS4270 supports "stand-alone" mode, whereby
+ * the chip is *not* connected to the I2C bus, but is instead configured via
+ * input pins.
+ */
+static struct snd_soc_device *cs4270_socdev;
+
+/*
+ * Initialize the I2C interface of the CS4270
+ *
+ * This function is called for whenever the I2C subsystem finds a device
+ * at a particular address.
+ *
+ * Note: snd_soc_new_pcms() must be called before this function can be called,
+ * because of snd_ctl_add().
+ */
+static int cs4270_i2c_probe(struct i2c_adapter *adapter, int addr, int kind)
+{
+ struct snd_soc_device *socdev = cs4270_socdev;
+ struct snd_soc_codec *codec = socdev->codec;
+ struct i2c_client *i2c_client = NULL;
+ int i;
+ int ret = 0;
+
+ /* Probing all possible addresses has one drawback: if there are
+ multiple CS4270s on the bus, then you cannot specify which
+ socdev is matched with which CS4270. For now, we just reject
+ this I2C device if the socdev already has one attached. */
+ if (codec->control_data)
+ return -ENODEV;
+
+ /* Note: codec_dai->codec is NULL here */
+
+ i2c_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ if (!i2c_client) {
+ printk(KERN_ERR "cs4270: could not allocate I2C client\n");
+ return -ENOMEM;
+ }
+
+ codec->reg_cache = kzalloc(CS4270_NUMREGS, GFP_KERNEL);
+ if (!codec->reg_cache) {
+ printk(KERN_ERR "cs4270: could not allocate register cache\n");
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ i2c_set_clientdata(i2c_client, codec);
+ strcpy(i2c_client->name, "CS4270");
+
+ i2c_client->driver = &cs4270_i2c_driver;
+ i2c_client->adapter = adapter;
+ i2c_client->addr = addr;
+
+ /* Verify that we have a CS4270 */
+
+ ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID);
+ if (ret < 0) {
+ printk(KERN_ERR "cs4270: failed to read I2C\n");
+ goto error;
+ }
+ /* The top four bits of the chip ID should be 1100. */
+ if ((ret & 0xF0) != 0xC0) {
+ /* The device at this address is not a CS4270 codec */
+ ret = -ENODEV;
+ goto error;
+ }
+
+ printk(KERN_INFO "cs4270: found device at I2C address %X\n", addr);
+ printk(KERN_INFO "cs4270: hardware revision %X\n", ret & 0xF);
+
+ /* Tell the I2C layer a new client has arrived */
+
+ ret = i2c_attach_client(i2c_client);
+ if (ret) {
+ printk(KERN_ERR "cs4270: could not attach codec, "
+ "I2C address %x, error code %i\n", addr, ret);
+ goto error;
+ }
+
+ codec->control_data = i2c_client;
+ codec->read = cs4270_read_reg_cache;
+ codec->write = cs4270_i2c_write;
+ codec->reg_cache_size = CS4270_NUMREGS;
+
+ /* The I2C interface is set up, so pre-fill our register cache */
+
+ ret = cs4270_fill_cache(codec);
+ if (ret < 0) {
+ printk(KERN_ERR "cs4270: failed to fill register cache\n");
+ goto error;
+ }
+
+ /* Add the non-DAPM controls */
+
+ for (i = 0; i < ARRAY_SIZE(cs4270_snd_controls); i++) {
+ struct snd_kcontrol *kctrl =
+ snd_soc_cnew(&cs4270_snd_controls[i], codec, NULL);
+
+ ret = snd_ctl_add(codec->card, kctrl);
+ if (ret < 0)
+ goto error;
+ }
+
+ return 0;
+
+error:
+ if (codec->control_data) {
+ i2c_detach_client(i2c_client);
+ codec->control_data = NULL;
+ }
+
+ kfree(codec->reg_cache);
+ codec->reg_cache = NULL;
+ codec->reg_cache_size = 0;
+
+ kfree(i2c_client);
+
+ return ret;
+}
+
+#endif
+
+struct snd_soc_codec_dai cs4270_dai = {
+ .name = "CS4270",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = 0,
+ .formats = CS4270_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = 0,
+ .formats = CS4270_FORMATS,
+ },
+ .dai_ops = {
+ .set_sysclk = cs4270_set_dai_sysclk,
+ .set_fmt = cs4270_set_dai_fmt,
+ }
+};
+EXPORT_SYMBOL_GPL(cs4270_dai);
+
+/*
+ * ASoC probe function
+ *
+ * This function is called when the machine driver calls
+ * platform_device_add().
+ */
+static int cs4270_probe(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec;
+ int ret = 0;
+
+ printk(KERN_INFO "CS4270 ALSA SoC Codec\n");
+
+ /* Allocate enough space for the snd_soc_codec structure
+ and our private data together. */
+ codec = kzalloc(ALIGN(sizeof(struct snd_soc_codec), 4) +
+ sizeof(struct cs4270_private), GFP_KERNEL);
+ if (!codec) {
+ printk(KERN_ERR "cs4270: Could not allocate codec structure\n");
+ return -ENOMEM;
+ }
+
+ mutex_init(&codec->mutex);
+ INIT_LIST_HEAD(&codec->dapm_widgets);
+ INIT_LIST_HEAD(&codec->dapm_paths);
+
+ codec->name = "CS4270";
+ codec->owner = THIS_MODULE;
+ codec->dai = &cs4270_dai;
+ codec->num_dai = 1;
+ codec->private_data = codec + ALIGN(sizeof(struct snd_soc_codec), 4);
+
+ socdev->codec = codec;
+
+ /* Register PCMs */
+
+ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+ if (ret < 0) {
+ printk(KERN_ERR "cs4270: failed to create PCMs\n");
+ return ret;
+ }
+
+#ifdef USE_I2C
+ cs4270_socdev = socdev;
+
+ ret = i2c_add_driver(&cs4270_i2c_driver);
+ if (ret) {
+ printk(KERN_ERR "cs4270: failed to attach driver");
+ snd_soc_free_pcms(socdev);
+ return ret;
+ }
+
+ /* Did we find a CS4270 on the I2C bus? */
+ if (codec->control_data) {
+ /* Initialize codec ops */
+ cs4270_dai.ops.hw_params = cs4270_hw_params;
+#ifdef CONFIG_SND_SOC_CS4270_HWMUTE
+ cs4270_dai.dai_ops.digital_mute = cs4270_mute;
+#endif
+ } else
+ printk(KERN_INFO "cs4270: no I2C device found, "
+ "using stand-alone mode\n");
+#else
+ printk(KERN_INFO "cs4270: I2C disabled, using stand-alone mode\n");
+#endif
+
+ ret = snd_soc_register_card(socdev);
+ if (ret < 0) {
+ printk(KERN_ERR "cs4270: failed to register card\n");
+ snd_soc_free_pcms(socdev);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int cs4270_remove(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+
+ snd_soc_free_pcms(socdev);
+
+#ifdef USE_I2C
+ if (socdev->codec->control_data)
+ i2c_del_driver(&cs4270_i2c_driver);
+#endif
+
+ kfree(socdev->codec);
+ socdev->codec = NULL;
+
+ return 0;
+}
+
+/*
+ * ASoC codec device structure
+ *
+ * Assign this variable to the codec_dev field of the machine driver's
+ * snd_soc_device structure.
+ */
+struct snd_soc_codec_device soc_codec_device_cs4270 = {
+ .probe = cs4270_probe,
+ .remove = cs4270_remove
+};
+EXPORT_SYMBOL_GPL(soc_codec_device_cs4270);
+
+MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
+MODULE_DESCRIPTION("Cirrus Logic CS4270 ALSA SoC Codec Driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs4270.h b/sound/soc/codecs/cs4270.h
new file mode 100644
index 000000000000..0ced49b7804d
--- /dev/null
+++ b/sound/soc/codecs/cs4270.h
@@ -0,0 +1,28 @@
+/*
+ * Cirrus Logic CS4270 ALSA SoC Codec Driver
+ *
+ * Author: Timur Tabi <timur@freescale.com>
+ *
+ * Copyright 2007 Freescale Semiconductor, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef _CS4270_H
+#define _CS4270_H
+
+/*
+ * The ASoC codec DAI structure for the CS4270. Assign this structure to
+ * the .codec_dai field of your machine driver's snd_soc_dai_link structure.
+ */
+extern struct snd_soc_codec_dai cs4270_dai;
+
+/*
+ * The ASoC codec device structure for the CS4270. Assign this structure
+ * to the .codec_dev field of your machine driver's snd_soc_device
+ * structure.
+ */
+extern struct snd_soc_codec_device soc_codec_device_cs4270;
+
+#endif
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c
index 80e82109fef7..4dd8f35312b3 100644
--- a/sound/soc/pxa/spitz.c
+++ b/sound/soc/pxa/spitz.c
@@ -34,7 +34,6 @@
#include <asm/arch/hardware.h>
#include <asm/arch/akita.h>
#include <asm/arch/spitz.h>
-#include <asm/mach-types.h>
#include "../codecs/wm8750.h"
#include "pxa2xx-pcm.h"
#include "pxa2xx-i2s.h"
diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig
index e97c68306a9a..5632a2e1518d 100644
--- a/sound/soc/s3c24xx/Kconfig
+++ b/sound/soc/s3c24xx/Kconfig
@@ -18,7 +18,7 @@ config SND_S3C2443_SOC_AC97
config SND_S3C24XX_SOC_NEO1973_WM8753
tristate "SoC I2S Audio support for NEO1973 - WM8753"
- depends on SND_S3C24XX_SOC && MACH_GTA01
+ depends on SND_S3C24XX_SOC && MACH_NEO1973_GTA01
select SND_S3C24XX_SOC_I2S
select SND_SOC_WM8753
help
diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c
index 39f02462e07d..cd89c4105fcd 100644
--- a/sound/soc/s3c24xx/s3c24xx-i2s.c
+++ b/sound/soc/s3c24xx/s3c24xx-i2s.c
@@ -385,6 +385,7 @@ static int s3c24xx_i2s_probe(struct platform_device *pdev)
s3c24xx_i2s.iis_clk=clk_get(&pdev->dev, "iis");
if (s3c24xx_i2s.iis_clk == NULL) {
DBG("failed to get iis_clock\n");
+ iounmap(s3c24xx_i2s.regs);
return -ENODEV;
}
clk_enable(s3c24xx_i2s.iis_clk);
diff --git a/sound/soc/s3c24xx/s3c24xx-pcm.c b/sound/soc/s3c24xx/s3c24xx-pcm.c
index bfbdc3cbd43b..4107a87d4de3 100644
--- a/sound/soc/s3c24xx/s3c24xx-pcm.c
+++ b/sound/soc/s3c24xx/s3c24xx-pcm.c
@@ -158,18 +158,22 @@ static int s3c24xx_pcm_hw_params(struct snd_pcm_substream *substream,
if (!dma)
return 0;
- /* prepare DMA */
- prtd->params = dma;
+ /* this may get called several times by oss emulation
+ * with different params -HW */
+ if (prtd->params == NULL) {
+ /* prepare DMA */
+ prtd->params = dma;
- DBG("params %p, client %p, channel %d\n", prtd->params,
- prtd->params->client, prtd->params->channel);
+ DBG("params %p, client %p, channel %d\n", prtd->params,
+ prtd->params->client, prtd->params->channel);
- ret = s3c2410_dma_request(prtd->params->channel,
- prtd->params->client, NULL);
+ ret = s3c2410_dma_request(prtd->params->channel,
+ prtd->params->client, NULL);
- if (ret) {
- DBG(KERN_ERR "failed to get dma channel\n");
- return ret;
+ if (ret) {
+ DBG(KERN_ERR "failed to get dma channel\n");
+ return ret;
+ }
}
/* channel needs configuring for mem=>device, increment memory addr,
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 92d5d917b73b..e6a67b58f296 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -264,7 +264,7 @@ out:
}
/*
- * Power down the audio subsytem pmdown_time msecs after close is called.
+ * Power down the audio subsystem pmdown_time msecs after close is called.
* This is to ensure there are no pops or clicks in between any music tracks
* due to DAPM power cycling.
*/
@@ -1362,26 +1362,6 @@ int snd_soc_info_volsw_ext(struct snd_kcontrol *kcontrol,
EXPORT_SYMBOL_GPL(snd_soc_info_volsw_ext);
/**
- * snd_soc_info_bool_ext - external single boolean mixer info callback
- * @kcontrol: mixer control
- * @uinfo: control element information
- *
- * Callback to provide information about a single boolean external mixer control.
- *
- * Returns 0 for success.
- */
-int snd_soc_info_bool_ext(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_soc_info_bool_ext);
-
-/**
* snd_soc_info_volsw - single mixer info callback
* @kcontrol: mixer control
* @uinfo: control element information
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 96bce55572a0..29a546fecacf 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -24,7 +24,7 @@
* o Automatic Mic Bias support
* o Jack insertion power event initiation - e.g. hp insertion will enable
* sinks, dacs, etc
- * o Delayed powerdown of audio susbsytem to reduce pops between a quick
+ * o Delayed powerdown of audio susbsystem to reduce pops between a quick
* device reopen.
*
* Todo:
@@ -63,7 +63,7 @@
#define POP_DEBUG 0
#if POP_DEBUG
#define POP_TIME 500 /* 500 msecs - change if pop debug is too fast */
-#define pop_wait(time) schedule_timeout_interruptible(msecs_to_jiffies(time))
+#define pop_wait(time) schedule_timeout_uninterruptible(msecs_to_jiffies(time))
#define pop_dbg(format, arg...) printk(format, ## arg); pop_wait(POP_TIME)
#else
#define pop_dbg(format, arg...)
diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c
index f2950cab74a6..f8c7a120ccbb 100644
--- a/sound/sparc/cs4231.c
+++ b/sound/sparc/cs4231.c
@@ -3,9 +3,9 @@
* Copyright (C) 2002 David S. Miller <davem@redhat.com>
*
* Based entirely upon drivers/sbus/audio/cs4231.c which is:
- * Copyright (C) 1996, 1997, 1998, 1998 Derrick J Brashear (shadow@andrew.cmu.edu)
+ * Copyright (C) 1996, 1997, 1998 Derrick J Brashear (shadow@andrew.cmu.edu)
* and also sound/isa/cs423x/cs4231_lib.c which is:
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*/
#include <linux/module.h>
@@ -15,6 +15,9 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/moduleparam.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
#include <sound/driver.h>
#include <sound/core.h>
@@ -25,29 +28,21 @@
#include <sound/initval.h>
#include <sound/pcm_params.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
#ifdef CONFIG_SBUS
#define SBUS_SUPPORT
-#endif
-
-#ifdef SBUS_SUPPORT
#include <asm/sbus.h>
#endif
#if defined(CONFIG_PCI) && defined(CONFIG_SPARC64)
#define EBUS_SUPPORT
-#endif
-
-#ifdef EBUS_SUPPORT
#include <linux/pci.h>
#include <asm/ebus.h>
#endif
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
+/* Enable this card */
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for Sun CS4231 soundcard.");
@@ -62,19 +57,22 @@ MODULE_SUPPORTED_DEVICE("{{Sun,CS4231}}");
#ifdef SBUS_SUPPORT
struct sbus_dma_info {
- spinlock_t lock;
- int dir;
- void __iomem *regs;
+ spinlock_t lock; /* DMA access lock */
+ int dir;
+ void __iomem *regs;
};
#endif
struct snd_cs4231;
struct cs4231_dma_control {
- void (*prepare)(struct cs4231_dma_control *dma_cont, int dir);
- void (*enable)(struct cs4231_dma_control *dma_cont, int on);
- int (*request)(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len);
- unsigned int (*address)(struct cs4231_dma_control *dma_cont);
- void (*preallocate)(struct snd_cs4231 *chip, struct snd_pcm *pcm);
+ void (*prepare)(struct cs4231_dma_control *dma_cont,
+ int dir);
+ void (*enable)(struct cs4231_dma_control *dma_cont, int on);
+ int (*request)(struct cs4231_dma_control *dma_cont,
+ dma_addr_t bus_addr, size_t len);
+ unsigned int (*address)(struct cs4231_dma_control *dma_cont);
+ void (*preallocate)(struct snd_cs4231 *chip,
+ struct snd_pcm *pcm);
#ifdef EBUS_SUPPORT
struct ebus_dma_info ebus_info;
#endif
@@ -84,7 +82,7 @@ struct cs4231_dma_control {
};
struct snd_cs4231 {
- spinlock_t lock;
+ spinlock_t lock; /* registers access lock */
void __iomem *port;
struct cs4231_dma_control p_dma;
@@ -108,13 +106,14 @@ struct snd_cs4231 {
#define CS4231_MODE_PLAY 0x0001
#define CS4231_MODE_RECORD 0x0002
#define CS4231_MODE_TIMER 0x0004
-#define CS4231_MODE_OPEN (CS4231_MODE_PLAY|CS4231_MODE_RECORD|CS4231_MODE_TIMER)
+#define CS4231_MODE_OPEN (CS4231_MODE_PLAY | CS4231_MODE_RECORD | \
+ CS4231_MODE_TIMER)
unsigned char image[32]; /* registers image */
int mce_bit;
int calibrate_mute;
- struct mutex mce_mutex;
- struct mutex open_mutex;
+ struct mutex mce_mutex; /* mutex for mce register */
+ struct mutex open_mutex; /* mutex for ALSA open/close */
union {
#ifdef SBUS_SUPPORT
@@ -136,129 +135,10 @@ static struct snd_cs4231 *cs4231_list;
*/
/* IO ports */
-
-#define CS4231P(chip, x) ((chip)->port + c_d_c_CS4231##x)
+#include <sound/cs4231-regs.h>
/* XXX offsets are different than PC ISA chips... */
-#define c_d_c_CS4231REGSEL 0x0
-#define c_d_c_CS4231REG 0x4
-#define c_d_c_CS4231STATUS 0x8
-#define c_d_c_CS4231PIO 0xc
-
-/* codec registers */
-
-#define CS4231_LEFT_INPUT 0x00 /* left input control */
-#define CS4231_RIGHT_INPUT 0x01 /* right input control */
-#define CS4231_AUX1_LEFT_INPUT 0x02 /* left AUX1 input control */
-#define CS4231_AUX1_RIGHT_INPUT 0x03 /* right AUX1 input control */
-#define CS4231_AUX2_LEFT_INPUT 0x04 /* left AUX2 input control */
-#define CS4231_AUX2_RIGHT_INPUT 0x05 /* right AUX2 input control */
-#define CS4231_LEFT_OUTPUT 0x06 /* left output control register */
-#define CS4231_RIGHT_OUTPUT 0x07 /* right output control register */
-#define CS4231_PLAYBK_FORMAT 0x08 /* clock and data format - playback - bits 7-0 MCE */
-#define CS4231_IFACE_CTRL 0x09 /* interface control - bits 7-2 MCE */
-#define CS4231_PIN_CTRL 0x0a /* pin control */
-#define CS4231_TEST_INIT 0x0b /* test and initialization */
-#define CS4231_MISC_INFO 0x0c /* miscellaneaous information */
-#define CS4231_LOOPBACK 0x0d /* loopback control */
-#define CS4231_PLY_UPR_CNT 0x0e /* playback upper base count */
-#define CS4231_PLY_LWR_CNT 0x0f /* playback lower base count */
-#define CS4231_ALT_FEATURE_1 0x10 /* alternate #1 feature enable */
-#define CS4231_ALT_FEATURE_2 0x11 /* alternate #2 feature enable */
-#define CS4231_LEFT_LINE_IN 0x12 /* left line input control */
-#define CS4231_RIGHT_LINE_IN 0x13 /* right line input control */
-#define CS4231_TIMER_LOW 0x14 /* timer low byte */
-#define CS4231_TIMER_HIGH 0x15 /* timer high byte */
-#define CS4231_LEFT_MIC_INPUT 0x16 /* left MIC input control register (InterWave only) */
-#define CS4231_RIGHT_MIC_INPUT 0x17 /* right MIC input control register (InterWave only) */
-#define CS4236_EXT_REG 0x17 /* extended register access */
-#define CS4231_IRQ_STATUS 0x18 /* irq status register */
-#define CS4231_LINE_LEFT_OUTPUT 0x19 /* left line output control register (InterWave only) */
-#define CS4231_VERSION 0x19 /* CS4231(A) - version values */
-#define CS4231_MONO_CTRL 0x1a /* mono input/output control */
-#define CS4231_LINE_RIGHT_OUTPUT 0x1b /* right line output control register (InterWave only) */
-#define CS4235_LEFT_MASTER 0x1b /* left master output control */
-#define CS4231_REC_FORMAT 0x1c /* clock and data format - record - bits 7-0 MCE */
-#define CS4231_PLY_VAR_FREQ 0x1d /* playback variable frequency */
-#define CS4235_RIGHT_MASTER 0x1d /* right master output control */
-#define CS4231_REC_UPR_CNT 0x1e /* record upper count */
-#define CS4231_REC_LWR_CNT 0x1f /* record lower count */
-
-/* definitions for codec register select port - CODECP( REGSEL ) */
-
-#define CS4231_INIT 0x80 /* CODEC is initializing */
-#define CS4231_MCE 0x40 /* mode change enable */
-#define CS4231_TRD 0x20 /* transfer request disable */
-
-/* definitions for codec status register - CODECP( STATUS ) */
-
-#define CS4231_GLOBALIRQ 0x01 /* IRQ is active */
-
-/* definitions for codec irq status - CS4231_IRQ_STATUS */
-
-#define CS4231_PLAYBACK_IRQ 0x10
-#define CS4231_RECORD_IRQ 0x20
-#define CS4231_TIMER_IRQ 0x40
-#define CS4231_ALL_IRQS 0x70
-#define CS4231_REC_UNDERRUN 0x08
-#define CS4231_REC_OVERRUN 0x04
-#define CS4231_PLY_OVERRUN 0x02
-#define CS4231_PLY_UNDERRUN 0x01
-
-/* definitions for CS4231_LEFT_INPUT and CS4231_RIGHT_INPUT registers */
-
-#define CS4231_ENABLE_MIC_GAIN 0x20
-
-#define CS4231_MIXS_LINE 0x00
-#define CS4231_MIXS_AUX1 0x40
-#define CS4231_MIXS_MIC 0x80
-#define CS4231_MIXS_ALL 0xc0
-
-/* definitions for clock and data format register - CS4231_PLAYBK_FORMAT */
-
-#define CS4231_LINEAR_8 0x00 /* 8-bit unsigned data */
-#define CS4231_ALAW_8 0x60 /* 8-bit A-law companded */
-#define CS4231_ULAW_8 0x20 /* 8-bit U-law companded */
-#define CS4231_LINEAR_16 0x40 /* 16-bit twos complement data - little endian */
-#define CS4231_LINEAR_16_BIG 0xc0 /* 16-bit twos complement data - big endian */
-#define CS4231_ADPCM_16 0xa0 /* 16-bit ADPCM */
-#define CS4231_STEREO 0x10 /* stereo mode */
-/* bits 3-1 define frequency divisor */
-#define CS4231_XTAL1 0x00 /* 24.576 crystal */
-#define CS4231_XTAL2 0x01 /* 16.9344 crystal */
-
-/* definitions for interface control register - CS4231_IFACE_CTRL */
-
-#define CS4231_RECORD_PIO 0x80 /* record PIO enable */
-#define CS4231_PLAYBACK_PIO 0x40 /* playback PIO enable */
-#define CS4231_CALIB_MODE 0x18 /* calibration mode bits */
-#define CS4231_AUTOCALIB 0x08 /* auto calibrate */
-#define CS4231_SINGLE_DMA 0x04 /* use single DMA channel */
-#define CS4231_RECORD_ENABLE 0x02 /* record enable */
-#define CS4231_PLAYBACK_ENABLE 0x01 /* playback enable */
-
-/* definitions for pin control register - CS4231_PIN_CTRL */
-
-#define CS4231_IRQ_ENABLE 0x02 /* enable IRQ */
-#define CS4231_XCTL1 0x40 /* external control #1 */
-#define CS4231_XCTL0 0x80 /* external control #0 */
-
-/* definitions for test and init register - CS4231_TEST_INIT */
-
-#define CS4231_CALIB_IN_PROGRESS 0x20 /* auto calibrate in progress */
-#define CS4231_DMA_REQUEST 0x10 /* DMA request in progress */
-
-/* definitions for misc control register - CS4231_MISC_INFO */
-
-#define CS4231_MODE2 0x40 /* MODE 2 */
-#define CS4231_IW_MODE3 0x6c /* MODE 3 - InterWave enhanced mode */
-#define CS4231_4236_MODE3 0xe0 /* MODE 3 - CS4236+ enhanced mode */
-
-/* definitions for alternate feature 1 register - CS4231_ALT_FEATURE_1 */
-
-#define CS4231_DACZ 0x01 /* zero DAC when underrun */
-#define CS4231_TIMER_ENABLE 0x40 /* codec timer enable */
-#define CS4231_OLB 0x80 /* output level bit */
+#define CS4231U(chip, x) ((chip)->port + ((c_d_c_CS4231##x) << 2))
/* SBUS DMA register defines. */
@@ -339,7 +219,7 @@ static unsigned int rates[14] = {
};
static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
- .count = 14,
+ .count = ARRAY_SIZE(rates),
.list = rates,
};
@@ -389,116 +269,89 @@ static unsigned char snd_cs4231_original_image[32] =
static u8 __cs4231_readb(struct snd_cs4231 *cp, void __iomem *reg_addr)
{
#ifdef EBUS_SUPPORT
- if (cp->flags & CS4231_FLAG_EBUS) {
+ if (cp->flags & CS4231_FLAG_EBUS)
return readb(reg_addr);
- } else {
+ else
#endif
#ifdef SBUS_SUPPORT
return sbus_readb(reg_addr);
#endif
-#ifdef EBUS_SUPPORT
- }
-#endif
}
-static void __cs4231_writeb(struct snd_cs4231 *cp, u8 val, void __iomem *reg_addr)
+static void __cs4231_writeb(struct snd_cs4231 *cp, u8 val,
+ void __iomem *reg_addr)
{
#ifdef EBUS_SUPPORT
- if (cp->flags & CS4231_FLAG_EBUS) {
+ if (cp->flags & CS4231_FLAG_EBUS)
return writeb(val, reg_addr);
- } else {
+ else
#endif
#ifdef SBUS_SUPPORT
return sbus_writeb(val, reg_addr);
#endif
-#ifdef EBUS_SUPPORT
- }
-#endif
}
/*
* Basic I/O functions
*/
-static void snd_cs4231_outm(struct snd_cs4231 *chip, unsigned char reg,
- unsigned char mask, unsigned char value)
+static void snd_cs4231_ready(struct snd_cs4231 *chip)
{
int timeout;
- unsigned char tmp;
- for (timeout = 250;
- timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT);
- timeout--)
- udelay(100);
-#ifdef CONFIG_SND_DEBUG
- if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
- snd_printdd("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
-#endif
- if (chip->calibrate_mute) {
- chip->image[reg] &= mask;
- chip->image[reg] |= value;
- } else {
- __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL));
- mb();
- tmp = (chip->image[reg] & mask) | value;
- __cs4231_writeb(chip, tmp, CS4231P(chip, REG));
- chip->image[reg] = tmp;
- mb();
+ for (timeout = 250; timeout > 0; timeout--) {
+ int val = __cs4231_readb(chip, CS4231U(chip, REGSEL));
+ if ((val & CS4231_INIT) == 0)
+ break;
+ udelay(100);
}
}
-static void snd_cs4231_dout(struct snd_cs4231 *chip, unsigned char reg, unsigned char value)
+static void snd_cs4231_dout(struct snd_cs4231 *chip, unsigned char reg,
+ unsigned char value)
{
- int timeout;
-
- for (timeout = 250;
- timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT);
- timeout--)
- udelay(100);
+ snd_cs4231_ready(chip);
#ifdef CONFIG_SND_DEBUG
- if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
- snd_printdd("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
+ if (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT)
+ snd_printdd("out: auto calibration time out - reg = 0x%x, "
+ "value = 0x%x\n",
+ reg, value);
#endif
- __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL));
- __cs4231_writeb(chip, value, CS4231P(chip, REG));
+ __cs4231_writeb(chip, chip->mce_bit | reg, CS4231U(chip, REGSEL));
+ wmb();
+ __cs4231_writeb(chip, value, CS4231U(chip, REG));
mb();
}
-static void snd_cs4231_out(struct snd_cs4231 *chip, unsigned char reg, unsigned char value)
+static inline void snd_cs4231_outm(struct snd_cs4231 *chip, unsigned char reg,
+ unsigned char mask, unsigned char value)
{
- int timeout;
+ unsigned char tmp = (chip->image[reg] & mask) | value;
- for (timeout = 250;
- timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT);
- timeout--)
- udelay(100);
-#ifdef CONFIG_SND_DEBUG
- if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
- snd_printdd("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
-#endif
- __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL));
- __cs4231_writeb(chip, value, CS4231P(chip, REG));
+ chip->image[reg] = tmp;
+ if (!chip->calibrate_mute)
+ snd_cs4231_dout(chip, reg, tmp);
+}
+
+static void snd_cs4231_out(struct snd_cs4231 *chip, unsigned char reg,
+ unsigned char value)
+{
+ snd_cs4231_dout(chip, reg, value);
chip->image[reg] = value;
mb();
}
static unsigned char snd_cs4231_in(struct snd_cs4231 *chip, unsigned char reg)
{
- int timeout;
- unsigned char ret;
-
- for (timeout = 250;
- timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT);
- timeout--)
- udelay(100);
+ snd_cs4231_ready(chip);
#ifdef CONFIG_SND_DEBUG
- if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
- snd_printdd("in: auto calibration time out - reg = 0x%x\n", reg);
+ if (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT)
+ snd_printdd("in: auto calibration time out - reg = 0x%x\n",
+ reg);
#endif
- __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL));
+ __cs4231_writeb(chip, chip->mce_bit | reg, CS4231U(chip, REGSEL));
mb();
- ret = __cs4231_readb(chip, CS4231P(chip, REG));
- return ret;
+ return __cs4231_readb(chip, CS4231U(chip, REG));
}
/*
@@ -509,15 +362,17 @@ static void snd_cs4231_busy_wait(struct snd_cs4231 *chip)
{
int timeout;
- /* huh.. looks like this sequence is proper for CS4231A chip (GUS MAX) */
+ /* looks like this sequence is proper for CS4231A chip (GUS MAX) */
for (timeout = 5; timeout > 0; timeout--)
- __cs4231_readb(chip, CS4231P(chip, REGSEL));
+ __cs4231_readb(chip, CS4231U(chip, REGSEL));
/* end of cleanup sequence */
- for (timeout = 500;
- timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT);
- timeout--)
- udelay(1000);
+ for (timeout = 500; timeout > 0; timeout--) {
+ int val = __cs4231_readb(chip, CS4231U(chip, REGSEL));
+ if ((val & CS4231_INIT) == 0)
+ break;
+ msleep(1);
+ }
}
static void snd_cs4231_mce_up(struct snd_cs4231 *chip)
@@ -526,77 +381,63 @@ static void snd_cs4231_mce_up(struct snd_cs4231 *chip)
int timeout;
spin_lock_irqsave(&chip->lock, flags);
- for (timeout = 250; timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT); timeout--)
- udelay(100);
+ snd_cs4231_ready(chip);
#ifdef CONFIG_SND_DEBUG
- if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
+ if (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT)
snd_printdd("mce_up - auto calibration time out (0)\n");
#endif
chip->mce_bit |= CS4231_MCE;
- timeout = __cs4231_readb(chip, CS4231P(chip, REGSEL));
+ timeout = __cs4231_readb(chip, CS4231U(chip, REGSEL));
if (timeout == 0x80)
- snd_printdd("mce_up [%p]: serious init problem - codec still busy\n", chip->port);
+ snd_printdd("mce_up [%p]: serious init problem - "
+ "codec still busy\n",
+ chip->port);
if (!(timeout & CS4231_MCE))
- __cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL));
+ __cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f),
+ CS4231U(chip, REGSEL));
spin_unlock_irqrestore(&chip->lock, flags);
}
static void snd_cs4231_mce_down(struct snd_cs4231 *chip)
{
- unsigned long flags;
- int timeout;
+ unsigned long flags, timeout;
+ int reg;
- spin_lock_irqsave(&chip->lock, flags);
snd_cs4231_busy_wait(chip);
+ spin_lock_irqsave(&chip->lock, flags);
#ifdef CONFIG_SND_DEBUG
- if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
- snd_printdd("mce_down [%p] - auto calibration time out (0)\n", CS4231P(chip, REGSEL));
+ if (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT)
+ snd_printdd("mce_down [%p] - auto calibration time out (0)\n",
+ CS4231U(chip, REGSEL));
#endif
chip->mce_bit &= ~CS4231_MCE;
- timeout = __cs4231_readb(chip, CS4231P(chip, REGSEL));
- __cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL));
- if (timeout == 0x80)
- snd_printdd("mce_down [%p]: serious init problem - codec still busy\n", chip->port);
- if ((timeout & CS4231_MCE) == 0) {
- spin_unlock_irqrestore(&chip->lock, flags);
- return;
- }
- snd_cs4231_busy_wait(chip);
-
- /* calibration process */
-
- for (timeout = 500; timeout > 0 && (snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) == 0; timeout--)
- udelay(100);
- if ((snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) == 0) {
- snd_printd("cs4231_mce_down - auto calibration time out (1)\n");
+ reg = __cs4231_readb(chip, CS4231U(chip, REGSEL));
+ __cs4231_writeb(chip, chip->mce_bit | (reg & 0x1f),
+ CS4231U(chip, REGSEL));
+ if (reg == 0x80)
+ snd_printdd("mce_down [%p]: serious init problem "
+ "- codec still busy\n", chip->port);
+ if ((reg & CS4231_MCE) == 0) {
spin_unlock_irqrestore(&chip->lock, flags);
return;
}
- /* in 10ms increments, check condition, up to 250ms */
- timeout = 25;
- while (snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) {
+ /*
+ * Wait for auto-calibration (AC) process to finish, i.e. ACI to go low.
+ */
+ timeout = jiffies + msecs_to_jiffies(250);
+ do {
spin_unlock_irqrestore(&chip->lock, flags);
- if (--timeout < 0) {
- snd_printk("mce_down - auto calibration time out (2)\n");
- return;
- }
- msleep(10);
+ msleep(1);
spin_lock_irqsave(&chip->lock, flags);
- }
-
- /* in 10ms increments, check condition, up to 100ms */
- timeout = 10;
- while (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) {
- spin_unlock_irqrestore(&chip->lock, flags);
- if (--timeout < 0) {
- snd_printk("mce_down - auto calibration time out (3)\n");
- return;
- }
- msleep(10);
- spin_lock_irqsave(&chip->lock, flags);
- }
+ reg = snd_cs4231_in(chip, CS4231_TEST_INIT);
+ reg &= CS4231_CALIB_IN_PROGRESS;
+ } while (reg && time_before(jiffies, timeout));
spin_unlock_irqrestore(&chip->lock, flags);
+
+ if (reg)
+ snd_printk(KERN_ERR
+ "mce_down - auto calibration time out (2)\n");
}
static void snd_cs4231_advance_dma(struct cs4231_dma_control *dma_cont,
@@ -611,7 +452,8 @@ static void snd_cs4231_advance_dma(struct cs4231_dma_control *dma_cont,
BUG_ON(period_size >= (1 << 24));
- if (dma_cont->request(dma_cont, runtime->dma_addr + offset, period_size))
+ if (dma_cont->request(dma_cont,
+ runtime->dma_addr + offset, period_size))
return;
(*periods_sent) = ((*periods_sent) + 1) % runtime->periods;
}
@@ -704,21 +546,32 @@ static unsigned char snd_cs4231_get_rate(unsigned int rate)
for (i = 0; i < 14; i++)
if (rate == rates[i])
return freq_bits[i];
- // snd_BUG();
+
return freq_bits[13];
}
-static unsigned char snd_cs4231_get_format(struct snd_cs4231 *chip, int format, int channels)
+static unsigned char snd_cs4231_get_format(struct snd_cs4231 *chip, int format,
+ int channels)
{
unsigned char rformat;
rformat = CS4231_LINEAR_8;
switch (format) {
- case SNDRV_PCM_FORMAT_MU_LAW: rformat = CS4231_ULAW_8; break;
- case SNDRV_PCM_FORMAT_A_LAW: rformat = CS4231_ALAW_8; break;
- case SNDRV_PCM_FORMAT_S16_LE: rformat = CS4231_LINEAR_16; break;
- case SNDRV_PCM_FORMAT_S16_BE: rformat = CS4231_LINEAR_16_BIG; break;
- case SNDRV_PCM_FORMAT_IMA_ADPCM: rformat = CS4231_ADPCM_16; break;
+ case SNDRV_PCM_FORMAT_MU_LAW:
+ rformat = CS4231_ULAW_8;
+ break;
+ case SNDRV_PCM_FORMAT_A_LAW:
+ rformat = CS4231_ALAW_8;
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ rformat = CS4231_LINEAR_16;
+ break;
+ case SNDRV_PCM_FORMAT_S16_BE:
+ rformat = CS4231_LINEAR_16_BIG;
+ break;
+ case SNDRV_PCM_FORMAT_IMA_ADPCM:
+ rformat = CS4231_ADPCM_16;
+ break;
}
if (channels > 1)
rformat |= CS4231_STEREO;
@@ -765,7 +618,8 @@ static void snd_cs4231_calibrate_mute(struct snd_cs4231 *chip, int mute)
spin_unlock_irqrestore(&chip->lock, flags);
}
-static void snd_cs4231_playback_format(struct snd_cs4231 *chip, struct snd_pcm_hw_params *params,
+static void snd_cs4231_playback_format(struct snd_cs4231 *chip,
+ struct snd_pcm_hw_params *params,
unsigned char pdfr)
{
unsigned long flags;
@@ -788,8 +642,9 @@ static void snd_cs4231_playback_format(struct snd_cs4231 *chip, struct snd_pcm_h
mutex_unlock(&chip->mce_mutex);
}
-static void snd_cs4231_capture_format(struct snd_cs4231 *chip, struct snd_pcm_hw_params *params,
- unsigned char cdfr)
+static void snd_cs4231_capture_format(struct snd_cs4231 *chip,
+ struct snd_pcm_hw_params *params,
+ unsigned char cdfr)
{
unsigned long flags;
@@ -846,7 +701,8 @@ static int snd_cs4231_timer_start(struct snd_timer *timer)
chip->image[CS4231_TIMER_LOW] =
(unsigned char) ticks);
snd_cs4231_out(chip, CS4231_ALT_FEATURE_1,
- chip->image[CS4231_ALT_FEATURE_1] | CS4231_TIMER_ENABLE);
+ chip->image[CS4231_ALT_FEATURE_1] |
+ CS4231_TIMER_ENABLE);
}
spin_unlock_irqrestore(&chip->lock, flags);
@@ -859,8 +715,9 @@ static int snd_cs4231_timer_stop(struct snd_timer *timer)
struct snd_cs4231 *chip = snd_timer_chip(timer);
spin_lock_irqsave(&chip->lock, flags);
+ chip->image[CS4231_ALT_FEATURE_1] &= ~CS4231_TIMER_ENABLE;
snd_cs4231_out(chip, CS4231_ALT_FEATURE_1,
- chip->image[CS4231_ALT_FEATURE_1] &= ~CS4231_TIMER_ENABLE);
+ chip->image[CS4231_ALT_FEATURE_1]);
spin_unlock_irqrestore(&chip->lock, flags);
return 0;
@@ -877,8 +734,10 @@ static void __init snd_cs4231_init(struct snd_cs4231 *chip)
#endif
snd_cs4231_mce_up(chip);
spin_lock_irqsave(&chip->lock, flags);
- chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO |
- CS4231_RECORD_ENABLE | CS4231_RECORD_PIO |
+ chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE |
+ CS4231_PLAYBACK_PIO |
+ CS4231_RECORD_ENABLE |
+ CS4231_RECORD_PIO |
CS4231_CALIB_MODE);
chip->image[CS4231_IFACE_CTRL] |= CS4231_AUTOCALIB;
snd_cs4231_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]);
@@ -891,21 +750,25 @@ static void __init snd_cs4231_init(struct snd_cs4231 *chip)
snd_cs4231_mce_up(chip);
spin_lock_irqsave(&chip->lock, flags);
- snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1]);
+ snd_cs4231_out(chip, CS4231_ALT_FEATURE_1,
+ chip->image[CS4231_ALT_FEATURE_1]);
spin_unlock_irqrestore(&chip->lock, flags);
snd_cs4231_mce_down(chip);
#ifdef SNDRV_DEBUG_MCE
- snd_printdd("init: (3) - afei = 0x%x\n", chip->image[CS4231_ALT_FEATURE_1]);
+ snd_printdd("init: (3) - afei = 0x%x\n",
+ chip->image[CS4231_ALT_FEATURE_1]);
#endif
spin_lock_irqsave(&chip->lock, flags);
- snd_cs4231_out(chip, CS4231_ALT_FEATURE_2, chip->image[CS4231_ALT_FEATURE_2]);
+ snd_cs4231_out(chip, CS4231_ALT_FEATURE_2,
+ chip->image[CS4231_ALT_FEATURE_2]);
spin_unlock_irqrestore(&chip->lock, flags);
snd_cs4231_mce_up(chip);
spin_lock_irqsave(&chip->lock, flags);
- snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, chip->image[CS4231_PLAYBK_FORMAT]);
+ snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT,
+ chip->image[CS4231_PLAYBK_FORMAT]);
spin_unlock_irqrestore(&chip->lock, flags);
snd_cs4231_mce_down(chip);
@@ -944,8 +807,8 @@ static int snd_cs4231_open(struct snd_cs4231 *chip, unsigned int mode)
CS4231_RECORD_IRQ |
CS4231_TIMER_IRQ);
snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);
- __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); /* clear IRQ */
- __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); /* clear IRQ */
+ __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); /* clear IRQ */
+ __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); /* clear IRQ */
snd_cs4231_out(chip, CS4231_IRQ_STATUS, CS4231_PLAYBACK_IRQ |
CS4231_RECORD_IRQ |
@@ -974,8 +837,8 @@ static void snd_cs4231_close(struct snd_cs4231 *chip, unsigned int mode)
/* disable IRQ */
spin_lock_irqsave(&chip->lock, flags);
snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);
- __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); /* clear IRQ */
- __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); /* clear IRQ */
+ __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); /* clear IRQ */
+ __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); /* clear IRQ */
/* now disable record & playback */
@@ -988,7 +851,8 @@ static void snd_cs4231_close(struct snd_cs4231 *chip, unsigned int mode)
chip->image[CS4231_IFACE_CTRL] &=
~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO |
CS4231_RECORD_ENABLE | CS4231_RECORD_PIO);
- snd_cs4231_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]);
+ snd_cs4231_out(chip, CS4231_IFACE_CTRL,
+ chip->image[CS4231_IFACE_CTRL]);
spin_unlock_irqrestore(&chip->lock, flags);
snd_cs4231_mce_down(chip);
spin_lock_irqsave(&chip->lock, flags);
@@ -996,8 +860,8 @@ static void snd_cs4231_close(struct snd_cs4231 *chip, unsigned int mode)
/* clear IRQ again */
snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);
- __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); /* clear IRQ */
- __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); /* clear IRQ */
+ __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); /* clear IRQ */
+ __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); /* clear IRQ */
spin_unlock_irqrestore(&chip->lock, flags);
snd_cs4231_calibrate_mute(chip, 0);
@@ -1017,15 +881,14 @@ static int snd_cs4231_timer_open(struct snd_timer *timer)
return 0;
}
-static int snd_cs4231_timer_close(struct snd_timer * timer)
+static int snd_cs4231_timer_close(struct snd_timer *timer)
{
struct snd_cs4231 *chip = snd_timer_chip(timer);
snd_cs4231_close(chip, CS4231_MODE_TIMER);
return 0;
}
-static struct snd_timer_hardware snd_cs4231_timer_table =
-{
+static struct snd_timer_hardware snd_cs4231_timer_table = {
.flags = SNDRV_TIMER_HW_AUTO,
.resolution = 9945,
.ticks = 65535,
@@ -1047,8 +910,9 @@ static int snd_cs4231_playback_hw_params(struct snd_pcm_substream *substream,
unsigned char new_pdfr;
int err;
- if ((err = snd_pcm_lib_malloc_pages(substream,
- params_buffer_bytes(hw_params))) < 0)
+ err = snd_pcm_lib_malloc_pages(substream,
+ params_buffer_bytes(hw_params));
+ if (err < 0)
return err;
new_pdfr = snd_cs4231_get_format(chip, params_format(hw_params),
params_channels(hw_params)) |
@@ -1058,11 +922,6 @@ static int snd_cs4231_playback_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static int snd_cs4231_playback_hw_free(struct snd_pcm_substream *substream)
-{
- return snd_pcm_lib_free_pages(substream);
-}
-
static int snd_cs4231_playback_prepare(struct snd_pcm_substream *substream)
{
struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
@@ -1089,8 +948,9 @@ static int snd_cs4231_capture_hw_params(struct snd_pcm_substream *substream,
unsigned char new_cdfr;
int err;
- if ((err = snd_pcm_lib_malloc_pages(substream,
- params_buffer_bytes(hw_params))) < 0)
+ err = snd_pcm_lib_malloc_pages(substream,
+ params_buffer_bytes(hw_params));
+ if (err < 0)
return err;
new_cdfr = snd_cs4231_get_format(chip, params_format(hw_params),
params_channels(hw_params)) |
@@ -1100,11 +960,6 @@ static int snd_cs4231_capture_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static int snd_cs4231_capture_hw_free(struct snd_pcm_substream *substream)
-{
- return snd_pcm_lib_free_pages(substream);
-}
-
static int snd_cs4231_capture_prepare(struct snd_pcm_substream *substream)
{
struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
@@ -1130,7 +985,8 @@ static void snd_cs4231_overrange(struct snd_cs4231 *chip)
res = snd_cs4231_in(chip, CS4231_TEST_INIT);
spin_unlock_irqrestore(&chip->lock, flags);
- if (res & (0x08 | 0x02)) /* detect overrange only above 0dB; may be user selectable? */
+ /* detect overrange only above 0dB; may be user selectable? */
+ if (res & (0x08 | 0x02))
chip->capture_substream->runtime->overrange++;
}
@@ -1152,51 +1008,50 @@ static void snd_cs4231_capture_callback(struct snd_cs4231 *chip)
}
}
-static snd_pcm_uframes_t snd_cs4231_playback_pointer(struct snd_pcm_substream *substream)
+static snd_pcm_uframes_t snd_cs4231_playback_pointer(
+ struct snd_pcm_substream *substream)
{
struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
struct cs4231_dma_control *dma_cont = &chip->p_dma;
size_t ptr;
-
+
if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE))
return 0;
ptr = dma_cont->address(dma_cont);
if (ptr != 0)
ptr -= substream->runtime->dma_addr;
-
+
return bytes_to_frames(substream->runtime, ptr);
}
-static snd_pcm_uframes_t snd_cs4231_capture_pointer(struct snd_pcm_substream *substream)
+static snd_pcm_uframes_t snd_cs4231_capture_pointer(
+ struct snd_pcm_substream *substream)
{
struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
struct cs4231_dma_control *dma_cont = &chip->c_dma;
size_t ptr;
-
+
if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE))
return 0;
ptr = dma_cont->address(dma_cont);
if (ptr != 0)
ptr -= substream->runtime->dma_addr;
-
+
return bytes_to_frames(substream->runtime, ptr);
}
-/*
-
- */
-
static int __init snd_cs4231_probe(struct snd_cs4231 *chip)
{
unsigned long flags;
- int i, id, vers;
+ int i;
+ int id = 0;
+ int vers = 0;
unsigned char *ptr;
- id = vers = 0;
for (i = 0; i < 50; i++) {
mb();
- if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
- udelay(2000);
+ if (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT)
+ msleep(2);
else {
spin_lock_irqsave(&chip->lock, flags);
snd_cs4231_out(chip, CS4231_MISC_INFO, CS4231_MODE2);
@@ -1213,8 +1068,9 @@ static int __init snd_cs4231_probe(struct snd_cs4231 *chip)
spin_lock_irqsave(&chip->lock, flags);
- __cs4231_readb(chip, CS4231P(chip, STATUS)); /* clear any pendings IRQ */
- __cs4231_writeb(chip, 0, CS4231P(chip, STATUS));
+ /* clear any pendings IRQ */
+ __cs4231_readb(chip, CS4231U(chip, STATUS));
+ __cs4231_writeb(chip, 0, CS4231U(chip, STATUS));
mb();
spin_unlock_irqrestore(&chip->lock, flags);
@@ -1247,42 +1103,50 @@ static int __init snd_cs4231_probe(struct snd_cs4231 *chip)
return 0; /* all things are ok.. */
}
-static struct snd_pcm_hardware snd_cs4231_playback =
-{
- .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START),
- .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW |
- SNDRV_PCM_FMTBIT_IMA_ADPCM |
- SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE |
- SNDRV_PCM_FMTBIT_S16_BE),
- .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
+static struct snd_pcm_hardware snd_cs4231_playback = {
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_SYNC_START,
+ .formats = SNDRV_PCM_FMTBIT_MU_LAW |
+ SNDRV_PCM_FMTBIT_A_LAW |
+ SNDRV_PCM_FMTBIT_IMA_ADPCM |
+ SNDRV_PCM_FMTBIT_U8 |
+ SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S16_BE,
+ .rates = SNDRV_PCM_RATE_KNOT |
+ SNDRV_PCM_RATE_8000_48000,
.rate_min = 5510,
.rate_max = 48000,
.channels_min = 1,
.channels_max = 2,
- .buffer_bytes_max = (32*1024),
+ .buffer_bytes_max = 32 * 1024,
.period_bytes_min = 64,
- .period_bytes_max = (32*1024),
+ .period_bytes_max = 32 * 1024,
.periods_min = 1,
.periods_max = 1024,
};
-static struct snd_pcm_hardware snd_cs4231_capture =
-{
- .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START),
- .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW |
- SNDRV_PCM_FMTBIT_IMA_ADPCM |
- SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE |
- SNDRV_PCM_FMTBIT_S16_BE),
- .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
+static struct snd_pcm_hardware snd_cs4231_capture = {
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_SYNC_START,
+ .formats = SNDRV_PCM_FMTBIT_MU_LAW |
+ SNDRV_PCM_FMTBIT_A_LAW |
+ SNDRV_PCM_FMTBIT_IMA_ADPCM |
+ SNDRV_PCM_FMTBIT_U8 |
+ SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S16_BE,
+ .rates = SNDRV_PCM_RATE_KNOT |
+ SNDRV_PCM_RATE_8000_48000,
.rate_min = 5510,
.rate_max = 48000,
.channels_min = 1,
.channels_max = 2,
- .buffer_bytes_max = (32*1024),
+ .buffer_bytes_max = 32 * 1024,
.period_bytes_min = 64,
- .period_bytes_max = (32*1024),
+ .period_bytes_max = 32 * 1024,
.periods_min = 1,
.periods_max = 1024,
};
@@ -1295,7 +1159,8 @@ static int snd_cs4231_playback_open(struct snd_pcm_substream *substream)
runtime->hw = snd_cs4231_playback;
- if ((err = snd_cs4231_open(chip, CS4231_MODE_PLAY)) < 0) {
+ err = snd_cs4231_open(chip, CS4231_MODE_PLAY);
+ if (err < 0) {
snd_free_pages(runtime->dma_area, runtime->dma_bytes);
return err;
}
@@ -1315,7 +1180,8 @@ static int snd_cs4231_capture_open(struct snd_pcm_substream *substream)
runtime->hw = snd_cs4231_capture;
- if ((err = snd_cs4231_open(chip, CS4231_MODE_RECORD)) < 0) {
+ err = snd_cs4231_open(chip, CS4231_MODE_RECORD);
+ if (err < 0) {
snd_free_pages(runtime->dma_area, runtime->dma_bytes);
return err;
}
@@ -1356,7 +1222,7 @@ static struct snd_pcm_ops snd_cs4231_playback_ops = {
.close = snd_cs4231_playback_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_cs4231_playback_hw_params,
- .hw_free = snd_cs4231_playback_hw_free,
+ .hw_free = snd_pcm_lib_free_pages,
.prepare = snd_cs4231_playback_prepare,
.trigger = snd_cs4231_trigger,
.pointer = snd_cs4231_playback_pointer,
@@ -1367,23 +1233,27 @@ static struct snd_pcm_ops snd_cs4231_capture_ops = {
.close = snd_cs4231_capture_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_cs4231_capture_hw_params,
- .hw_free = snd_cs4231_capture_hw_free,
+ .hw_free = snd_pcm_lib_free_pages,
.prepare = snd_cs4231_capture_prepare,
.trigger = snd_cs4231_trigger,
.pointer = snd_cs4231_capture_pointer,
};
-static int __init snd_cs4231_pcm(struct snd_cs4231 *chip)
+static int __init snd_cs4231_pcm(struct snd_card *card)
{
+ struct snd_cs4231 *chip = card->private_data;
struct snd_pcm *pcm;
int err;
- if ((err = snd_pcm_new(chip->card, "CS4231", 0, 1, 1, &pcm)) < 0)
+ err = snd_pcm_new(card, "CS4231", 0, 1, 1, &pcm);
+ if (err < 0)
return err;
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs4231_playback_ops);
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cs4231_capture_ops);
-
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+ &snd_cs4231_playback_ops);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+ &snd_cs4231_capture_ops);
+
/* global setup */
pcm->private_data = chip;
pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
@@ -1396,8 +1266,9 @@ static int __init snd_cs4231_pcm(struct snd_cs4231 *chip)
return 0;
}
-static int __init snd_cs4231_timer(struct snd_cs4231 *chip)
+static int __init snd_cs4231_timer(struct snd_card *card)
{
+ struct snd_cs4231 *chip = card->private_data;
struct snd_timer *timer;
struct snd_timer_id tid;
int err;
@@ -1405,10 +1276,11 @@ static int __init snd_cs4231_timer(struct snd_cs4231 *chip)
/* Timer initialization */
tid.dev_class = SNDRV_TIMER_CLASS_CARD;
tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
- tid.card = chip->card->number;
+ tid.card = card->number;
tid.device = 0;
tid.subdevice = 0;
- if ((err = snd_timer_new(chip->card, "CS4231", &tid, &timer)) < 0)
+ err = snd_timer_new(card, "CS4231", &tid, &timer);
+ if (err < 0)
return err;
strcpy(timer->name, "CS4231");
timer->private_data = chip;
@@ -1417,7 +1289,7 @@ static int __init snd_cs4231_timer(struct snd_cs4231 *chip)
return 0;
}
-
+
/*
* MIXER part
*/
@@ -1428,15 +1300,14 @@ static int snd_cs4231_info_mux(struct snd_kcontrol *kcontrol,
static char *texts[4] = {
"Line", "CD", "Mic", "Mix"
};
- struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
- snd_assert(chip->card != NULL, return -EINVAL);
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 2;
uinfo->value.enumerated.items = 4;
if (uinfo->value.enumerated.item > 3)
uinfo->value.enumerated.item = 3;
- strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+ strcpy(uinfo->value.enumerated.name,
+ texts[uinfo->value.enumerated.item]);
return 0;
}
@@ -1446,7 +1317,7 @@ static int snd_cs4231_get_mux(struct snd_kcontrol *kcontrol,
{
struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
-
+
spin_lock_irqsave(&chip->lock, flags);
ucontrol->value.enumerated.item[0] =
(chip->image[CS4231_LEFT_INPUT] & CS4231_MIXS_ALL) >> 6;
@@ -1464,7 +1335,7 @@ static int snd_cs4231_put_mux(struct snd_kcontrol *kcontrol,
unsigned long flags;
unsigned short left, right;
int change;
-
+
if (ucontrol->value.enumerated.item[0] > 3 ||
ucontrol->value.enumerated.item[1] > 3)
return -EINVAL;
@@ -1476,7 +1347,7 @@ static int snd_cs4231_put_mux(struct snd_kcontrol *kcontrol,
left = (chip->image[CS4231_LEFT_INPUT] & ~CS4231_MIXS_ALL) | left;
right = (chip->image[CS4231_RIGHT_INPUT] & ~CS4231_MIXS_ALL) | right;
change = left != chip->image[CS4231_LEFT_INPUT] ||
- right != chip->image[CS4231_RIGHT_INPUT];
+ right != chip->image[CS4231_RIGHT_INPUT];
snd_cs4231_out(chip, CS4231_LEFT_INPUT, left);
snd_cs4231_out(chip, CS4231_RIGHT_INPUT, right);
@@ -1508,7 +1379,7 @@ static int snd_cs4231_get_single(struct snd_kcontrol *kcontrol,
int shift = (kcontrol->private_value >> 8) & 0xff;
int mask = (kcontrol->private_value >> 16) & 0xff;
int invert = (kcontrol->private_value >> 24) & 0xff;
-
+
spin_lock_irqsave(&chip->lock, flags);
ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask;
@@ -1533,7 +1404,7 @@ static int snd_cs4231_put_single(struct snd_kcontrol *kcontrol,
int invert = (kcontrol->private_value >> 24) & 0xff;
int change;
unsigned short val;
-
+
val = (ucontrol->value.integer.value[0] & mask);
if (invert)
val = mask - val;
@@ -1575,11 +1446,13 @@ static int snd_cs4231_get_double(struct snd_kcontrol *kcontrol,
int shift_right = (kcontrol->private_value >> 19) & 0x07;
int mask = (kcontrol->private_value >> 24) & 0xff;
int invert = (kcontrol->private_value >> 22) & 1;
-
+
spin_lock_irqsave(&chip->lock, flags);
- ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask;
- ucontrol->value.integer.value[1] = (chip->image[right_reg] >> shift_right) & mask;
+ ucontrol->value.integer.value[0] =
+ (chip->image[left_reg] >> shift_left) & mask;
+ ucontrol->value.integer.value[1] =
+ (chip->image[right_reg] >> shift_right) & mask;
spin_unlock_irqrestore(&chip->lock, flags);
@@ -1606,7 +1479,7 @@ static int snd_cs4231_put_double(struct snd_kcontrol *kcontrol,
int invert = (kcontrol->private_value >> 22) & 1;
int change;
unsigned short val1, val2;
-
+
val1 = ucontrol->value.integer.value[0] & mask;
val2 = ucontrol->value.integer.value[1] & mask;
if (invert) {
@@ -1620,7 +1493,8 @@ static int snd_cs4231_put_double(struct snd_kcontrol *kcontrol,
val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1;
val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2;
- change = val1 != chip->image[left_reg] || val2 != chip->image[right_reg];
+ change = val1 != chip->image[left_reg];
+ change |= val2 != chip->image[right_reg];
snd_cs4231_out(chip, left_reg, val1);
snd_cs4231_out(chip, right_reg, val2);
@@ -1630,31 +1504,42 @@ static int snd_cs4231_put_double(struct snd_kcontrol *kcontrol,
}
#define CS4231_SINGLE(xname, xindex, reg, shift, mask, invert) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
- .info = snd_cs4231_info_single, \
- .get = snd_cs4231_get_single, .put = snd_cs4231_put_single, \
- .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
-
-#define CS4231_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
- .info = snd_cs4231_info_double, \
- .get = snd_cs4231_get_double, .put = snd_cs4231_put_double, \
- .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), .index = (xindex), \
+ .info = snd_cs4231_info_single, \
+ .get = snd_cs4231_get_single, .put = snd_cs4231_put_single, \
+ .private_value = (reg) | ((shift) << 8) | ((mask) << 16) | ((invert) << 24) }
+
+#define CS4231_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, \
+ shift_right, mask, invert) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), .index = (xindex), \
+ .info = snd_cs4231_info_double, \
+ .get = snd_cs4231_get_double, .put = snd_cs4231_put_double, \
+ .private_value = (left_reg) | ((right_reg) << 8) | ((shift_left) << 16) | \
+ ((shift_right) << 19) | ((mask) << 24) | ((invert) << 22) }
static struct snd_kcontrol_new snd_cs4231_controls[] __initdata = {
-CS4231_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
-CS4231_DOUBLE("PCM Playback Volume", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),
-CS4231_DOUBLE("Line Playback Switch", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
-CS4231_DOUBLE("Line Playback Volume", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1),
-CS4231_DOUBLE("Aux Playback Switch", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
-CS4231_DOUBLE("Aux Playback Volume", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1),
-CS4231_DOUBLE("Aux Playback Switch", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
-CS4231_DOUBLE("Aux Playback Volume", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1),
+CS4231_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT,
+ CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
+CS4231_DOUBLE("PCM Playback Volume", 0, CS4231_LEFT_OUTPUT,
+ CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),
+CS4231_DOUBLE("Line Playback Switch", 0, CS4231_LEFT_LINE_IN,
+ CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
+CS4231_DOUBLE("Line Playback Volume", 0, CS4231_LEFT_LINE_IN,
+ CS4231_RIGHT_LINE_IN, 0, 0, 31, 1),
+CS4231_DOUBLE("Aux Playback Switch", 0, CS4231_AUX1_LEFT_INPUT,
+ CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
+CS4231_DOUBLE("Aux Playback Volume", 0, CS4231_AUX1_LEFT_INPUT,
+ CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1),
+CS4231_DOUBLE("Aux Playback Switch", 1, CS4231_AUX2_LEFT_INPUT,
+ CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
+CS4231_DOUBLE("Aux Playback Volume", 1, CS4231_AUX2_LEFT_INPUT,
+ CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1),
CS4231_SINGLE("Mono Playback Switch", 0, CS4231_MONO_CTRL, 7, 1, 1),
CS4231_SINGLE("Mono Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1),
CS4231_SINGLE("Mono Output Playback Switch", 0, CS4231_MONO_CTRL, 6, 1, 1),
CS4231_SINGLE("Mono Output Playback Bypass", 0, CS4231_MONO_CTRL, 5, 1, 0),
-CS4231_DOUBLE("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0),
+CS4231_DOUBLE("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0,
+ 15, 0),
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Capture Source",
@@ -1662,29 +1547,28 @@ CS4231_DOUBLE("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0,
.get = snd_cs4231_get_mux,
.put = snd_cs4231_put_mux,
},
-CS4231_DOUBLE("Mic Boost", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0),
+CS4231_DOUBLE("Mic Boost", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5,
+ 1, 0),
CS4231_SINGLE("Loopback Capture Switch", 0, CS4231_LOOPBACK, 0, 1, 0),
CS4231_SINGLE("Loopback Capture Volume", 0, CS4231_LOOPBACK, 2, 63, 1),
/* SPARC specific uses of XCTL{0,1} general purpose outputs. */
CS4231_SINGLE("Line Out Switch", 0, CS4231_PIN_CTRL, 6, 1, 1),
CS4231_SINGLE("Headphone Out Switch", 0, CS4231_PIN_CTRL, 7, 1, 1)
};
-
-static int __init snd_cs4231_mixer(struct snd_cs4231 *chip)
+
+static int __init snd_cs4231_mixer(struct snd_card *card)
{
- struct snd_card *card;
+ struct snd_cs4231 *chip = card->private_data;
int err, idx;
snd_assert(chip != NULL && chip->pcm != NULL, return -EINVAL);
- card = chip->card;
-
strcpy(card->mixername, chip->pcm->name);
for (idx = 0; idx < ARRAY_SIZE(snd_cs4231_controls); idx++) {
- if ((err = snd_ctl_add(card,
- snd_ctl_new1(&snd_cs4231_controls[idx],
- chip))) < 0)
+ err = snd_ctl_add(card,
+ snd_ctl_new1(&snd_cs4231_controls[idx], chip));
+ if (err < 0)
return err;
}
return 0;
@@ -1695,6 +1579,7 @@ static int dev;
static int __init cs4231_attach_begin(struct snd_card **rcard)
{
struct snd_card *card;
+ struct snd_cs4231 *chip;
*rcard = NULL;
@@ -1706,31 +1591,40 @@ static int __init cs4231_attach_begin(struct snd_card **rcard)
return -ENOENT;
}
- card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
+ card = snd_card_new(index[dev], id[dev], THIS_MODULE,
+ sizeof(struct snd_cs4231));
if (card == NULL)
return -ENOMEM;
strcpy(card->driver, "CS4231");
strcpy(card->shortname, "Sun CS4231");
+ chip = card->private_data;
+ chip->card = card;
+
*rcard = card;
return 0;
}
-static int __init cs4231_attach_finish(struct snd_card *card, struct snd_cs4231 *chip)
+static int __init cs4231_attach_finish(struct snd_card *card)
{
+ struct snd_cs4231 *chip = card->private_data;
int err;
- if ((err = snd_cs4231_pcm(chip)) < 0)
+ err = snd_cs4231_pcm(card);
+ if (err < 0)
goto out_err;
- if ((err = snd_cs4231_mixer(chip)) < 0)
+ err = snd_cs4231_mixer(card);
+ if (err < 0)
goto out_err;
- if ((err = snd_cs4231_timer(chip)) < 0)
+ err = snd_cs4231_timer(card);
+ if (err < 0)
goto out_err;
- if ((err = snd_card_register(card)) < 0)
+ err = snd_card_register(card);
+ if (err < 0)
goto out_err;
chip->next = cs4231_list;
@@ -1754,7 +1648,7 @@ static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id)
struct snd_cs4231 *chip = dev_id;
/*This is IRQ is not raised by the cs4231*/
- if (!(__cs4231_readb(chip, CS4231P(chip, STATUS)) & CS4231_GLOBALIRQ))
+ if (!(__cs4231_readb(chip, CS4231U(chip, STATUS)) & CS4231_GLOBALIRQ))
return IRQ_NONE;
/* ACK the APC interrupt. */
@@ -1762,24 +1656,24 @@ static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id)
sbus_writel(csr, chip->port + APCCSR);
- if ((csr & APC_PDMA_READY) &&
- (csr & APC_PLAY_INT) &&
+ if ((csr & APC_PDMA_READY) &&
+ (csr & APC_PLAY_INT) &&
(csr & APC_XINT_PNVA) &&
!(csr & APC_XINT_EMPT))
snd_cs4231_play_callback(chip);
- if ((csr & APC_CDMA_READY) &&
- (csr & APC_CAPT_INT) &&
+ if ((csr & APC_CDMA_READY) &&
+ (csr & APC_CAPT_INT) &&
(csr & APC_XINT_CNVA) &&
!(csr & APC_XINT_EMPT))
snd_cs4231_capture_callback(chip);
-
+
status = snd_cs4231_in(chip, CS4231_IRQ_STATUS);
if (status & CS4231_TIMER_IRQ) {
if (chip->timer)
snd_timer_interrupt(chip->timer, chip->timer->sticks);
- }
+ }
if ((status & CS4231_RECORD_IRQ) && (csr & APC_CDMA_READY))
snd_cs4231_overrange(chip);
@@ -1796,26 +1690,27 @@ static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id)
* SBUS DMA routines
*/
-static int sbus_dma_request(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len)
+static int sbus_dma_request(struct cs4231_dma_control *dma_cont,
+ dma_addr_t bus_addr, size_t len)
{
unsigned long flags;
u32 test, csr;
int err;
struct sbus_dma_info *base = &dma_cont->sbus_info;
-
+
if (len >= (1 << 24))
return -EINVAL;
spin_lock_irqsave(&base->lock, flags);
csr = sbus_readl(base->regs + APCCSR);
err = -EINVAL;
test = APC_CDMA_READY;
- if ( base->dir == APC_PLAY )
+ if (base->dir == APC_PLAY)
test = APC_PDMA_READY;
if (!(csr & test))
goto out;
err = -EBUSY;
test = APC_XINT_CNVA;
- if ( base->dir == APC_PLAY )
+ if (base->dir == APC_PLAY)
test = APC_XINT_PNVA;
if (!(csr & test))
goto out;
@@ -1838,7 +1733,7 @@ static void sbus_dma_prepare(struct cs4231_dma_control *dma_cont, int d)
test = APC_GENL_INT | APC_PLAY_INT | APC_XINT_ENA |
APC_XINT_PLAY | APC_XINT_PEMP | APC_XINT_GENL |
APC_XINT_PENA;
- if ( base->dir == APC_RECORD )
+ if (base->dir == APC_RECORD)
test = APC_GENL_INT | APC_CAPT_INT | APC_XINT_ENA |
APC_XINT_CAPT | APC_XINT_CEMP | APC_XINT_GENL;
csr |= test;
@@ -1856,28 +1751,28 @@ static void sbus_dma_enable(struct cs4231_dma_control *dma_cont, int on)
if (!on) {
sbus_writel(0, base->regs + base->dir + APCNC);
sbus_writel(0, base->regs + base->dir + APCNVA);
- if ( base->dir == APC_PLAY ) {
+ if (base->dir == APC_PLAY) {
sbus_writel(0, base->regs + base->dir + APCC);
sbus_writel(0, base->regs + base->dir + APCVA);
}
udelay(1200);
- }
+ }
csr = sbus_readl(base->regs + APCCSR);
shift = 0;
- if ( base->dir == APC_PLAY )
+ if (base->dir == APC_PLAY)
shift = 1;
if (on)
csr &= ~(APC_CPAUSE << shift);
else
- csr |= (APC_CPAUSE << shift);
+ csr |= (APC_CPAUSE << shift);
sbus_writel(csr, base->regs + APCCSR);
if (on)
csr |= (APC_CDMA_READY << shift);
else
csr &= ~(APC_CDMA_READY << shift);
sbus_writel(csr, base->regs + APCCSR);
-
+
spin_unlock_irqrestore(&base->lock, flags);
}
@@ -1885,14 +1780,14 @@ static unsigned int sbus_dma_addr(struct cs4231_dma_control *dma_cont)
{
struct sbus_dma_info *base = &dma_cont->sbus_info;
- return sbus_readl(base->regs + base->dir + APCVA);
+ return sbus_readl(base->regs + base->dir + APCVA);
}
static void sbus_dma_preallocate(struct snd_cs4231 *chip, struct snd_pcm *pcm)
{
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_SBUS,
- snd_dma_sbus_data(chip->dev_u.sdev),
- 64*1024, 128*1024);
+ snd_dma_sbus_data(chip->dev_u.sdev),
+ 64 * 1024, 128 * 1024);
}
/*
@@ -1907,8 +1802,6 @@ static int snd_cs4231_sbus_free(struct snd_cs4231 *chip)
if (chip->port)
sbus_iounmap(chip->port, chip->regs_size);
- kfree(chip);
-
return 0;
}
@@ -1925,23 +1818,16 @@ static struct snd_device_ops snd_cs4231_sbus_dev_ops = {
static int __init snd_cs4231_sbus_create(struct snd_card *card,
struct sbus_dev *sdev,
- int dev,
- struct snd_cs4231 **rchip)
+ int dev)
{
- struct snd_cs4231 *chip;
+ struct snd_cs4231 *chip = card->private_data;
int err;
- *rchip = NULL;
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (chip == NULL)
- return -ENOMEM;
-
spin_lock_init(&chip->lock);
spin_lock_init(&chip->c_dma.sbus_info.lock);
spin_lock_init(&chip->p_dma.sbus_info.lock);
mutex_init(&chip->mce_mutex);
mutex_init(&chip->open_mutex);
- chip->card = card;
chip->dev_u.sdev = sdev;
chip->regs_size = sdev->reg_addrs[0].reg_size;
memcpy(&chip->image, &snd_cs4231_original_image,
@@ -1992,14 +1878,12 @@ static int __init snd_cs4231_sbus_create(struct snd_card *card,
return err;
}
- *rchip = chip;
return 0;
}
static int __init cs4231_sbus_attach(struct sbus_dev *sdev)
{
struct resource *rp = &sdev->resource[0];
- struct snd_cs4231 *cp;
struct snd_card *card;
int err;
@@ -2013,25 +1897,28 @@ static int __init cs4231_sbus_attach(struct sbus_dev *sdev)
(unsigned long long)rp->start,
sdev->irqs[0]);
- if ((err = snd_cs4231_sbus_create(card, sdev, dev, &cp)) < 0) {
+ err = snd_cs4231_sbus_create(card, sdev, dev);
+ if (err < 0) {
snd_card_free(card);
return err;
}
- return cs4231_attach_finish(card, cp);
+ return cs4231_attach_finish(card);
}
#endif
#ifdef EBUS_SUPPORT
-static void snd_cs4231_ebus_play_callback(struct ebus_dma_info *p, int event, void *cookie)
+static void snd_cs4231_ebus_play_callback(struct ebus_dma_info *p, int event,
+ void *cookie)
{
struct snd_cs4231 *chip = cookie;
-
+
snd_cs4231_play_callback(chip);
}
-static void snd_cs4231_ebus_capture_callback(struct ebus_dma_info *p, int event, void *cookie)
+static void snd_cs4231_ebus_capture_callback(struct ebus_dma_info *p,
+ int event, void *cookie)
{
struct snd_cs4231 *chip = cookie;
@@ -2042,7 +1929,8 @@ static void snd_cs4231_ebus_capture_callback(struct ebus_dma_info *p, int event,
* EBUS DMA wrappers
*/
-static int _ebus_dma_request(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len)
+static int _ebus_dma_request(struct cs4231_dma_control *dma_cont,
+ dma_addr_t bus_addr, size_t len)
{
return ebus_dma_request(&dma_cont->ebus_info, bus_addr, len);
}
@@ -2087,8 +1975,6 @@ static int snd_cs4231_ebus_free(struct snd_cs4231 *chip)
if (chip->port)
iounmap(chip->port);
- kfree(chip);
-
return 0;
}
@@ -2105,24 +1991,17 @@ static struct snd_device_ops snd_cs4231_ebus_dev_ops = {
static int __init snd_cs4231_ebus_create(struct snd_card *card,
struct linux_ebus_device *edev,
- int dev,
- struct snd_cs4231 **rchip)
+ int dev)
{
- struct snd_cs4231 *chip;
+ struct snd_cs4231 *chip = card->private_data;
int err;
- *rchip = NULL;
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (chip == NULL)
- return -ENOMEM;
-
spin_lock_init(&chip->lock);
spin_lock_init(&chip->c_dma.ebus_info.lock);
spin_lock_init(&chip->p_dma.ebus_info.lock);
mutex_init(&chip->mce_mutex);
mutex_init(&chip->open_mutex);
chip->flags |= CS4231_FLAG_EBUS;
- chip->card = card;
chip->dev_u.pdev = edev->bus->self;
memcpy(&chip->image, &snd_cs4231_original_image,
sizeof(snd_cs4231_original_image));
@@ -2152,7 +2031,8 @@ static int __init snd_cs4231_ebus_create(struct snd_card *card,
chip->port = ioremap(edev->resource[0].start, 0x10);
chip->p_dma.ebus_info.regs = ioremap(edev->resource[1].start, 0x10);
chip->c_dma.ebus_info.regs = ioremap(edev->resource[2].start, 0x10);
- if (!chip->port || !chip->p_dma.ebus_info.regs || !chip->c_dma.ebus_info.regs) {
+ if (!chip->port || !chip->p_dma.ebus_info.regs ||
+ !chip->c_dma.ebus_info.regs) {
snd_cs4231_ebus_free(chip);
snd_printdd("cs4231-%d: Unable to map chip registers.\n", dev);
return -EIO;
@@ -2160,18 +2040,21 @@ static int __init snd_cs4231_ebus_create(struct snd_card *card,
if (ebus_dma_register(&chip->c_dma.ebus_info)) {
snd_cs4231_ebus_free(chip);
- snd_printdd("cs4231-%d: Unable to register EBUS capture DMA\n", dev);
+ snd_printdd("cs4231-%d: Unable to register EBUS capture DMA\n",
+ dev);
return -EBUSY;
}
if (ebus_dma_irq_enable(&chip->c_dma.ebus_info, 1)) {
snd_cs4231_ebus_free(chip);
- snd_printdd("cs4231-%d: Unable to enable EBUS capture IRQ\n", dev);
+ snd_printdd("cs4231-%d: Unable to enable EBUS capture IRQ\n",
+ dev);
return -EBUSY;
}
if (ebus_dma_register(&chip->p_dma.ebus_info)) {
snd_cs4231_ebus_free(chip);
- snd_printdd("cs4231-%d: Unable to register EBUS play DMA\n", dev);
+ snd_printdd("cs4231-%d: Unable to register EBUS play DMA\n",
+ dev);
return -EBUSY;
}
if (ebus_dma_irq_enable(&chip->p_dma.ebus_info, 1)) {
@@ -2192,14 +2075,12 @@ static int __init snd_cs4231_ebus_create(struct snd_card *card,
return err;
}
- *rchip = chip;
return 0;
}
static int __init cs4231_ebus_attach(struct linux_ebus_device *edev)
{
struct snd_card *card;
- struct snd_cs4231 *chip;
int err;
err = cs4231_attach_begin(&card);
@@ -2211,12 +2092,13 @@ static int __init cs4231_ebus_attach(struct linux_ebus_device *edev)
edev->resource[0].start,
edev->irqs[0]);
- if ((err = snd_cs4231_ebus_create(card, edev, dev, &chip)) < 0) {
+ err = snd_cs4231_ebus_create(card, edev, dev);
+ if (err < 0) {
snd_card_free(card);
return err;
}
- return cs4231_attach_finish(card, chip);
+ return cs4231_attach_finish(card);
}
#endif
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c
index e07085a7cfc3..376b98691c96 100644
--- a/sound/sparc/dbri.c
+++ b/sound/sparc/dbri.c
@@ -8,18 +8,18 @@
* Copyright (C) 1997 Rudolf Koenig (rfkoenig@immd4.informatik.uni-erlangen.de)
* Copyright (C) 1998, 1999 Brent Baccala (baccala@freesoft.org)
*
- * This is the lowlevel driver for the DBRI & MMCODEC duo used for ISDN & AUDIO
- * on Sun SPARCstation 10, 20, LX and Voyager models.
+ * This is the low level driver for the DBRI & MMCODEC duo used for ISDN & AUDIO
+ * on Sun SPARCStation 10, 20, LX and Voyager models.
*
* - DBRI: AT&T T5900FX Dual Basic Rates ISDN Interface. It is a 32 channel
* data time multiplexer with ISDN support (aka T7259)
* Interfaces: SBus,ISDN NT & TE, CHI, 4 bits parallel.
* CHI: (spelled ki) Concentration Highway Interface (AT&T or Intel bus ?).
* Documentation:
- * - "STP 4000SBus Dual Basic Rate ISDN (DBRI) Tranceiver" from
+ * - "STP 4000SBus Dual Basic Rate ISDN (DBRI) Transceiver" from
* Sparc Technology Business (courtesy of Sun Support)
* - Data sheet of the T7903, a newer but very similar ISA bus equivalent
- * available from the Lucent (formarly AT&T microelectronics) home
+ * available from the Lucent (formerly AT&T microelectronics) home
* page.
* - http://www.freesoft.org/Linux/DBRI/
* - MMCODEC: Crystal Semiconductor CS4215 16 bit Multimedia Audio Codec
@@ -27,21 +27,21 @@
* Documentation: from the Crystal Semiconductor home page.
*
* The DBRI is a 32 pipe machine, each pipe can transfer some bits between
- * memory and a serial device (long pipes, nr 0-15) or between two serial
- * devices (short pipes, nr 16-31), or simply send a fixed data to a serial
+ * memory and a serial device (long pipes, no. 0-15) or between two serial
+ * devices (short pipes, no. 16-31), or simply send a fixed data to a serial
* device (short pipes).
- * A timeslot defines the bit-offset and nr of bits read from a serial device.
+ * A timeslot defines the bit-offset and no. of bits read from a serial device.
* The timeslots are linked to 6 circular lists, one for each direction for
* each serial device (NT,TE,CHI). A timeslot is associated to 1 or 2 pipes
* (the second one is a monitor/tee pipe, valid only for serial input).
*
* The mmcodec is connected via the CHI bus and needs the data & some
- * parameters (volume, output selection) timemultiplexed in 8 byte
+ * parameters (volume, output selection) time multiplexed in 8 byte
* chunks. It also has a control mode, which serves for audio format setting.
*
* Looking at the CS4215 data sheet it is easy to set up 2 or 4 codecs on
- * the same CHI bus, so I thought perhaps it is possible to use the onboard
- * & the speakerbox codec simultanously, giving 2 (not very independent :-)
+ * the same CHI bus, so I thought perhaps it is possible to use the on-board
+ * & the speakerbox codec simultaneously, giving 2 (not very independent :-)
* audio devices. But the SUN HW group decided against it, at least on my
* LX the speakerbox connector has at least 1 pin missing and 1 wrongly
* connected.
@@ -56,6 +56,8 @@
#include <sound/driver.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/io.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -64,8 +66,7 @@
#include <sound/control.h>
#include <sound/initval.h>
-#include <asm/irq.h>
-#include <asm/io.h>
+#include <linux/of.h>
#include <asm/sbus.h>
#include <asm/atomic.h>
@@ -76,7 +77,8 @@ MODULE_SUPPORTED_DEVICE("{{Sun,DBRI}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
+/* Enable this card */
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for Sun DBRI soundcard.");
@@ -104,7 +106,7 @@ static char *cmds[] = {
"SSP", "CHI", "NT", "TE", "CDEC", "TEST", "CDM", "RESRV"
};
-#define dprintk(a, x...) if(dbri_debug & a) printk(KERN_DEBUG x)
+#define dprintk(a, x...) if (dbri_debug & a) printk(KERN_DEBUG x)
#else
#define dprintk(a, x...) do { } while (0)
@@ -131,7 +133,7 @@ struct cs4215 {
};
/*
- * Control mode first
+ * Control mode first
*/
/* Time Slot 1, Status register */
@@ -219,7 +221,7 @@ static struct {
/* Time Slot 7, Input Setting */
#define CS4215_LG(v) v /* Left Gain Setting 0xf: 22.5 dB */
#define CS4215_IS (1<<4) /* Input Select: 1=Microphone, 0=Line */
-#define CS4215_OVR (1<<5) /* 1: Overrange condition occurred */
+#define CS4215_OVR (1<<5) /* 1: Over range condition occurred */
#define CS4215_PIO0 (1<<6) /* Parallel I/O 0 */
#define CS4215_PIO1 (1<<7)
@@ -232,12 +234,12 @@ static struct {
****************************************************************************/
/* DBRI main registers */
-#define REG0 0x00UL /* Status and Control */
-#define REG1 0x04UL /* Mode and Interrupt */
-#define REG2 0x08UL /* Parallel IO */
-#define REG3 0x0cUL /* Test */
-#define REG8 0x20UL /* Command Queue Pointer */
-#define REG9 0x24UL /* Interrupt Queue Pointer */
+#define REG0 0x00 /* Status and Control */
+#define REG1 0x04 /* Mode and Interrupt */
+#define REG2 0x08 /* Parallel IO */
+#define REG3 0x0c /* Test */
+#define REG8 0x20 /* Command Queue Pointer */
+#define REG9 0x24 /* Interrupt Queue Pointer */
#define DBRI_NO_CMDS 64
#define DBRI_INT_BLK 64
@@ -285,7 +287,7 @@ struct dbri_pipe {
/* Per stream (playback or record) information */
struct dbri_streaminfo {
struct snd_pcm_substream *substream;
- u32 dvma_buffer; /* Device view of Alsa DMA buffer */
+ u32 dvma_buffer; /* Device view of ALSA DMA buffer */
int size; /* Size of DMA buffer */
size_t offset; /* offset in user buffer */
int pipe; /* Data pipe used */
@@ -295,8 +297,6 @@ struct dbri_streaminfo {
/* This structure holds the information for both chips (DBRI & CS4215) */
struct snd_dbri {
- struct snd_card *card; /* ALSA card */
-
int regs_size, irq; /* Needed for unload */
struct sbus_dev *sdev; /* SBUS device info */
spinlock_t lock;
@@ -317,8 +317,6 @@ struct snd_dbri {
struct cs4215 mm; /* mmcodec special info */
/* per stream (playback/record) info */
struct dbri_streaminfo stream_info[DBRI_NO_STREAMS];
-
- struct snd_dbri *next;
};
#define DBRI_MAX_VOLUME 63 /* Output volume */
@@ -341,11 +339,11 @@ struct snd_dbri {
/* DBRI Reg1 - Mode and Interrupt Register - defines. (Page 18) */
#define D_LITTLE_END (1<<8) /* Byte Order */
#define D_BIG_END (0<<8) /* Byte Order */
-#define D_MRR (1<<4) /* Multiple Error Ack on SBus (readonly) */
-#define D_MLE (1<<3) /* Multiple Late Error on SBus (readonly) */
-#define D_LBG (1<<2) /* Lost Bus Grant on SBus (readonly) */
-#define D_MBE (1<<1) /* Burst Error on SBus (readonly) */
-#define D_IR (1<<0) /* Interrupt Indicator (readonly) */
+#define D_MRR (1<<4) /* Multiple Error Ack on SBus (read only) */
+#define D_MLE (1<<3) /* Multiple Late Error on SBus (read only) */
+#define D_LBG (1<<2) /* Lost Bus Grant on SBus (read only) */
+#define D_MBE (1<<1) /* Burst Error on SBus (read only) */
+#define D_IR (1<<0) /* Interrupt Indicator (read only) */
/* DBRI Reg2 - Parallel IO Register - defines. (Page 18) */
#define D_ENPIO3 (1<<7) /* Enable Pin 3 */
@@ -376,11 +374,11 @@ struct snd_dbri {
#define D_CDM 0xe /* CHI Data mode command */
/* Special bits for some commands */
-#define D_PIPE(v) ((v)<<0) /* Pipe Nr: 0-15 long, 16-21 short */
+#define D_PIPE(v) ((v)<<0) /* Pipe No.: 0-15 long, 16-21 short */
/* Setup Data Pipe */
/* IRM */
-#define D_SDP_2SAME (1<<18) /* Report 2nd time in a row value rcvd */
+#define D_SDP_2SAME (1<<18) /* Report 2nd time in a row value received */
#define D_SDP_CHANGE (2<<18) /* Report any changes */
#define D_SDP_EVERY (3<<18) /* Report any changes */
#define D_SDP_EOL (1<<17) /* EOL interrupt enable */
@@ -419,7 +417,7 @@ struct snd_dbri {
#define D_TS_NONCONTIG (3<<10) /* Non contiguous mode */
#define D_TS_ANCHOR (7<<10) /* Starting short pipes */
#define D_TS_MON(v) ((v)<<5) /* Monitor Pipe */
-#define D_TS_NEXT(v) ((v)<<0) /* Pipe Nr: 0-15 long, 16-21 short */
+#define D_TS_NEXT(v) ((v)<<0) /* Pipe no.: 0-15 long, 16-21 short */
/* Concentration Highway Interface Modes */
#define D_CHI_CHICM(v) ((v)<<16) /* Clock mode */
@@ -435,7 +433,7 @@ struct snd_dbri {
#define D_NT_NBF (1<<16) /* Number of bad frames to loose framing */
#define D_NT_IRM_IMM (1<<15) /* Interrupt Report & Mask: Immediate */
#define D_NT_IRM_EN (1<<14) /* Interrupt Report & Mask: Enable */
-#define D_NT_ISNT (1<<13) /* Configfure interface as NT */
+#define D_NT_ISNT (1<<13) /* Configure interface as NT */
#define D_NT_FT (1<<12) /* Fixed Timing */
#define D_NT_EZ (1<<11) /* Echo Channel is Zeros */
#define D_NT_IFA (1<<10) /* Inhibit Final Activation */
@@ -455,7 +453,7 @@ struct snd_dbri {
#define D_TEST_RAM(v) ((v)<<16) /* RAM Pointer */
#define D_TEST_SIZE(v) ((v)<<11) /* */
#define D_TEST_ROMONOFF 0x5 /* Toggle ROM opcode monitor on/off */
-#define D_TEST_PROC 0x6 /* MicroProcessor test */
+#define D_TEST_PROC 0x6 /* Microprocessor test */
#define D_TEST_SER 0x7 /* Serial-Controller test */
#define D_TEST_RAMREAD 0x8 /* Copy from Ram to system memory */
#define D_TEST_RAMWRITE 0x9 /* Copy into Ram from system memory */
@@ -464,12 +462,12 @@ struct snd_dbri {
#define D_TEST_DUMP 0xe /* ROM Dump */
/* CHI Data Mode */
-#define D_CDM_THI (1<<8) /* Transmit Data on CHIDR Pin */
-#define D_CDM_RHI (1<<7) /* Receive Data on CHIDX Pin */
-#define D_CDM_RCE (1<<6) /* Receive on Rising Edge of CHICK */
-#define D_CDM_XCE (1<<2) /* Transmit Data on Rising Edge of CHICK */
-#define D_CDM_XEN (1<<1) /* Transmit Highway Enable */
-#define D_CDM_REN (1<<0) /* Receive Highway Enable */
+#define D_CDM_THI (1 << 8) /* Transmit Data on CHIDR Pin */
+#define D_CDM_RHI (1 << 7) /* Receive Data on CHIDX Pin */
+#define D_CDM_RCE (1 << 6) /* Receive on Rising Edge of CHICK */
+#define D_CDM_XCE (1 << 2) /* Transmit Data on Rising Edge of CHICK */
+#define D_CDM_XEN (1 << 1) /* Transmit Highway Enable */
+#define D_CDM_REN (1 << 0) /* Receive Highway Enable */
/* The Interrupts */
#define D_INTR_BRDY 1 /* Buffer Ready for processing */
@@ -493,9 +491,9 @@ struct snd_dbri {
#define D_INTR_CHI 36
#define D_INTR_CMD 38
-#define D_INTR_GETCHAN(v) (((v)>>24) & 0x3f)
-#define D_INTR_GETCODE(v) (((v)>>20) & 0xf)
-#define D_INTR_GETCMD(v) (((v)>>16) & 0xf)
+#define D_INTR_GETCHAN(v) (((v) >> 24) & 0x3f)
+#define D_INTR_GETCODE(v) (((v) >> 20) & 0xf)
+#define D_INTR_GETCMD(v) (((v) >> 16) & 0xf)
#define D_INTR_GETVAL(v) ((v) & 0xffff)
#define D_INTR_GETRVAL(v) ((v) & 0xfffff)
@@ -533,43 +531,42 @@ struct snd_dbri {
#define D_P_31 31 /* */
/* Transmit descriptor defines */
-#define DBRI_TD_F (1<<31) /* End of Frame */
-#define DBRI_TD_D (1<<30) /* Do not append CRC */
-#define DBRI_TD_CNT(v) ((v)<<16) /* Number of valid bytes in the buffer */
-#define DBRI_TD_B (1<<15) /* Final interrupt */
-#define DBRI_TD_M (1<<14) /* Marker interrupt */
-#define DBRI_TD_I (1<<13) /* Transmit Idle Characters */
-#define DBRI_TD_FCNT(v) (v) /* Flag Count */
-#define DBRI_TD_UNR (1<<3) /* Underrun: transmitter is out of data */
-#define DBRI_TD_ABT (1<<2) /* Abort: frame aborted */
-#define DBRI_TD_TBC (1<<0) /* Transmit buffer Complete */
-#define DBRI_TD_STATUS(v) ((v)&0xff) /* Transmit status */
- /* Maximum buffer size per TD: almost 8Kb */
+#define DBRI_TD_F (1 << 31) /* End of Frame */
+#define DBRI_TD_D (1 << 30) /* Do not append CRC */
+#define DBRI_TD_CNT(v) ((v) << 16) /* Number of valid bytes in the buffer */
+#define DBRI_TD_B (1 << 15) /* Final interrupt */
+#define DBRI_TD_M (1 << 14) /* Marker interrupt */
+#define DBRI_TD_I (1 << 13) /* Transmit Idle Characters */
+#define DBRI_TD_FCNT(v) (v) /* Flag Count */
+#define DBRI_TD_UNR (1 << 3) /* Underrun: transmitter is out of data */
+#define DBRI_TD_ABT (1 << 2) /* Abort: frame aborted */
+#define DBRI_TD_TBC (1 << 0) /* Transmit buffer Complete */
+#define DBRI_TD_STATUS(v) ((v) & 0xff) /* Transmit status */
+ /* Maximum buffer size per TD: almost 8KB */
#define DBRI_TD_MAXCNT ((1 << 13) - 4)
/* Receive descriptor defines */
-#define DBRI_RD_F (1<<31) /* End of Frame */
-#define DBRI_RD_C (1<<30) /* Completed buffer */
-#define DBRI_RD_B (1<<15) /* Final interrupt */
-#define DBRI_RD_M (1<<14) /* Marker interrupt */
-#define DBRI_RD_BCNT(v) (v) /* Buffer size */
-#define DBRI_RD_CRC (1<<7) /* 0: CRC is correct */
-#define DBRI_RD_BBC (1<<6) /* 1: Bad Byte received */
-#define DBRI_RD_ABT (1<<5) /* Abort: frame aborted */
-#define DBRI_RD_OVRN (1<<3) /* Overrun: data lost */
-#define DBRI_RD_STATUS(v) ((v)&0xff) /* Receive status */
-#define DBRI_RD_CNT(v) (((v)>>16)&0x1fff) /* Valid bytes in the buffer */
+#define DBRI_RD_F (1 << 31) /* End of Frame */
+#define DBRI_RD_C (1 << 30) /* Completed buffer */
+#define DBRI_RD_B (1 << 15) /* Final interrupt */
+#define DBRI_RD_M (1 << 14) /* Marker interrupt */
+#define DBRI_RD_BCNT(v) (v) /* Buffer size */
+#define DBRI_RD_CRC (1 << 7) /* 0: CRC is correct */
+#define DBRI_RD_BBC (1 << 6) /* 1: Bad Byte received */
+#define DBRI_RD_ABT (1 << 5) /* Abort: frame aborted */
+#define DBRI_RD_OVRN (1 << 3) /* Overrun: data lost */
+#define DBRI_RD_STATUS(v) ((v) & 0xff) /* Receive status */
+#define DBRI_RD_CNT(v) (((v) >> 16) & 0x1fff) /* Valid bytes in the buffer */
/* stream_info[] access */
/* Translate the ALSA direction into the array index */
#define DBRI_STREAMNO(substream) \
- (substream->stream == \
- SNDRV_PCM_STREAM_PLAYBACK? DBRI_PLAY: DBRI_REC)
+ (substream->stream == \
+ SNDRV_PCM_STREAM_PLAYBACK ? DBRI_PLAY: DBRI_REC)
/* Return a pointer to dbri_streaminfo */
-#define DBRI_STREAM(dbri, substream) &dbri->stream_info[DBRI_STREAMNO(substream)]
-
-static struct snd_dbri *dbri_list; /* All DBRI devices */
+#define DBRI_STREAM(dbri, substream) \
+ &dbri->stream_info[DBRI_STREAMNO(substream)]
/*
* Short data pipes transmit LSB first. The CS4215 receives MSB first. Grrr.
@@ -609,21 +606,21 @@ The list is terminated with a WAIT command, which generates a
CPU interrupt to signal completion.
Since the DBRI can run in parallel with the CPU, several means of
-synchronization present themselves. The method implemented here is only
-use of the dbri_cmdwait() to wait for execution of batch of sent commands.
+synchronization present themselves. The method implemented here uses
+the dbri_cmdwait() to wait for execution of batch of sent commands.
-A circular command buffer is used here. A new command is being added
+A circular command buffer is used here. A new command is being added
while another can be executed. The scheme works by adding two WAIT commands
after each sent batch of commands. When the next batch is prepared it is
added after the WAIT commands then the WAITs are replaced with single JUMP
-command to the new batch. The the DBRI is forced to reread the last WAIT
-command (replaced by the JUMP by then). If the DBRI is still executing
+command to the new batch. The the DBRI is forced to reread the last WAIT
+command (replaced by the JUMP by then). If the DBRI is still executing
previous commands the request to reread the WAIT command is ignored.
Every time a routine wants to write commands to the DBRI, it must
-first call dbri_cmdlock() and get pointer to a free space in
-dbri->dma->cmd buffer. After this, the commands can be written to
-the buffer, and dbri_cmdsend() is called with the final pointer value
+first call dbri_cmdlock() and get pointer to a free space in
+dbri->dma->cmd buffer. After this, the commands can be written to
+the buffer, and dbri_cmdsend() is called with the final pointer value
to send them to the DBRI.
*/
@@ -646,18 +643,17 @@ static void dbri_cmdwait(struct snd_dbri *dbri)
}
spin_unlock_irqrestore(&dbri->lock, flags);
- if (maxloops == 0) {
+ if (maxloops == 0)
printk(KERN_ERR "DBRI: Chip never completed command buffer\n");
- } else {
+ else
dprintk(D_CMD, "Chip completed command buffer (%d)\n",
MAXLOOPS - maxloops - 1);
- }
}
/*
- * Lock the command queue and returns pointer to a space for len cmd words
+ * Lock the command queue and return pointer to space for len cmd words
* It locks the cmdlock spinlock.
*/
-static s32 *dbri_cmdlock(struct snd_dbri * dbri, int len)
+static s32 *dbri_cmdlock(struct snd_dbri *dbri, int len)
{
/* Space for 2 WAIT cmds (replaced later by 1 JUMP cmd) */
len += 2;
@@ -680,7 +676,7 @@ static s32 *dbri_cmdlock(struct snd_dbri * dbri, int len)
*
* Lock must be held before calling this.
*/
-static void dbri_cmdsend(struct snd_dbri * dbri, s32 * cmd,int len)
+static void dbri_cmdsend(struct snd_dbri *dbri, s32 *cmd, int len)
{
s32 tmp, addr;
static int wait_id = 0;
@@ -700,16 +696,17 @@ static void dbri_cmdsend(struct snd_dbri * dbri, s32 * cmd,int len)
s32 *ptr;
for (ptr = dbri->cmdptr; ptr < cmd+2; ptr++)
- dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr);
+ dprintk(D_CMD, "cmd: %lx:%08x\n",
+ (unsigned long)ptr, *ptr);
} else {
s32 *ptr = dbri->cmdptr;
dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr);
ptr++;
dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr);
- for (ptr = dbri->dma->cmd; ptr < cmd+2; ptr++) {
- dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr);
- }
+ for (ptr = dbri->dma->cmd; ptr < cmd+2; ptr++)
+ dprintk(D_CMD, "cmd: %lx:%08x\n",
+ (unsigned long)ptr, *ptr);
}
#endif
@@ -723,7 +720,7 @@ static void dbri_cmdsend(struct snd_dbri * dbri, s32 * cmd,int len)
}
/* Lock must be held when calling this */
-static void dbri_reset(struct snd_dbri * dbri)
+static void dbri_reset(struct snd_dbri *dbri)
{
int i;
u32 tmp;
@@ -746,7 +743,7 @@ static void dbri_reset(struct snd_dbri * dbri)
}
/* Lock must not be held before calling this */
-static void dbri_initialize(struct snd_dbri * dbri)
+static void __devinit dbri_initialize(struct snd_dbri *dbri)
{
s32 *cmd;
u32 dma_addr;
@@ -763,7 +760,7 @@ static void dbri_initialize(struct snd_dbri * dbri)
spin_lock_init(&dbri->cmdlock);
/*
- * Initialize the interrupt ringbuffer.
+ * Initialize the interrupt ring buffer.
*/
dma_addr = dbri->dma_dvma + dbri_dma_off(intr, 0);
dbri->dma->intr[0] = dma_addr;
@@ -801,7 +798,7 @@ list ordering, among other things. The transmit and receive functions
here interface closely with the transmit and receive interrupt code.
*/
-static int pipe_active(struct snd_dbri * dbri, int pipe)
+static inline int pipe_active(struct snd_dbri *dbri, int pipe)
{
return ((pipe >= 0) && (dbri->pipes[pipe].desc != -1));
}
@@ -811,20 +808,22 @@ static int pipe_active(struct snd_dbri * dbri, int pipe)
* Called on an in-use pipe to clear anything being transmitted or received
* Lock must be held before calling this.
*/
-static void reset_pipe(struct snd_dbri * dbri, int pipe)
+static void reset_pipe(struct snd_dbri *dbri, int pipe)
{
int sdp;
int desc;
s32 *cmd;
if (pipe < 0 || pipe > DBRI_MAX_PIPE) {
- printk(KERN_ERR "DBRI: reset_pipe called with illegal pipe number\n");
+ printk(KERN_ERR "DBRI: reset_pipe called with "
+ "illegal pipe number\n");
return;
}
sdp = dbri->pipes[pipe].sdp;
if (sdp == 0) {
- printk(KERN_ERR "DBRI: reset_pipe called on uninitialized pipe\n");
+ printk(KERN_ERR "DBRI: reset_pipe called "
+ "on uninitialized pipe\n");
return;
}
@@ -835,9 +834,10 @@ static void reset_pipe(struct snd_dbri * dbri, int pipe)
dbri_cmdsend(dbri, cmd, 3);
desc = dbri->pipes[pipe].first_desc;
- if ( desc >= 0)
+ if (desc >= 0)
do {
- dbri->dma->desc[desc].nda = dbri->dma->desc[desc].ba = 0;
+ dbri->dma->desc[desc].ba = 0;
+ dbri->dma->desc[desc].nda = 0;
desc = dbri->next_desc[desc];
} while (desc != -1 && desc != dbri->pipes[pipe].first_desc);
@@ -848,15 +848,17 @@ static void reset_pipe(struct snd_dbri * dbri, int pipe)
/*
* Lock must be held before calling this.
*/
-static void setup_pipe(struct snd_dbri * dbri, int pipe, int sdp)
+static void setup_pipe(struct snd_dbri *dbri, int pipe, int sdp)
{
if (pipe < 0 || pipe > DBRI_MAX_PIPE) {
- printk(KERN_ERR "DBRI: setup_pipe called with illegal pipe number\n");
+ printk(KERN_ERR "DBRI: setup_pipe called "
+ "with illegal pipe number\n");
return;
}
if ((sdp & 0xf800) != sdp) {
- printk(KERN_ERR "DBRI: setup_pipe called with strange SDP value\n");
+ printk(KERN_ERR "DBRI: setup_pipe called "
+ "with strange SDP value\n");
/* sdp &= 0xf800; */
}
@@ -877,25 +879,26 @@ static void setup_pipe(struct snd_dbri * dbri, int pipe, int sdp)
/*
* Lock must be held before calling this.
*/
-static void link_time_slot(struct snd_dbri * dbri, int pipe,
+static void link_time_slot(struct snd_dbri *dbri, int pipe,
int prevpipe, int nextpipe,
int length, int cycle)
{
s32 *cmd;
int val;
- if (pipe < 0 || pipe > DBRI_MAX_PIPE
+ if (pipe < 0 || pipe > DBRI_MAX_PIPE
|| prevpipe < 0 || prevpipe > DBRI_MAX_PIPE
|| nextpipe < 0 || nextpipe > DBRI_MAX_PIPE) {
- printk(KERN_ERR
+ printk(KERN_ERR
"DBRI: link_time_slot called with illegal pipe number\n");
return;
}
- if (dbri->pipes[pipe].sdp == 0
+ if (dbri->pipes[pipe].sdp == 0
|| dbri->pipes[prevpipe].sdp == 0
|| dbri->pipes[nextpipe].sdp == 0) {
- printk(KERN_ERR "DBRI: link_time_slot called on uninitialized pipe\n");
+ printk(KERN_ERR "DBRI: link_time_slot called "
+ "on uninitialized pipe\n");
return;
}
@@ -935,17 +938,17 @@ static void link_time_slot(struct snd_dbri * dbri, int pipe,
/*
* Lock must be held before calling this.
*/
-static void unlink_time_slot(struct snd_dbri * dbri, int pipe,
+static void unlink_time_slot(struct snd_dbri *dbri, int pipe,
enum in_or_out direction, int prevpipe,
int nextpipe)
{
s32 *cmd;
int val;
- if (pipe < 0 || pipe > DBRI_MAX_PIPE
+ if (pipe < 0 || pipe > DBRI_MAX_PIPE
|| prevpipe < 0 || prevpipe > DBRI_MAX_PIPE
|| nextpipe < 0 || nextpipe > DBRI_MAX_PIPE) {
- printk(KERN_ERR
+ printk(KERN_ERR
"DBRI: unlink_time_slot called with illegal pipe number\n");
return;
}
@@ -985,7 +988,7 @@ static void unlink_time_slot(struct snd_dbri * dbri, int pipe,
*
* Lock must not be held before calling it.
*/
-static void xmit_fixed(struct snd_dbri * dbri, int pipe, unsigned int data)
+static void xmit_fixed(struct snd_dbri *dbri, int pipe, unsigned int data)
{
s32 *cmd;
unsigned long flags;
@@ -996,7 +999,8 @@ static void xmit_fixed(struct snd_dbri * dbri, int pipe, unsigned int data)
}
if (D_SDP_MODE(dbri->pipes[pipe].sdp) == 0) {
- printk(KERN_ERR "DBRI: xmit_fixed: Uninitialized pipe %d\n", pipe);
+ printk(KERN_ERR "DBRI: xmit_fixed: "
+ "Uninitialized pipe %d\n", pipe);
return;
}
@@ -1006,7 +1010,8 @@ static void xmit_fixed(struct snd_dbri * dbri, int pipe, unsigned int data)
}
if (!(dbri->pipes[pipe].sdp & D_SDP_TO_SER)) {
- printk(KERN_ERR "DBRI: xmit_fixed: Called on receive pipe %d\n", pipe);
+ printk(KERN_ERR "DBRI: xmit_fixed: Called on receive pipe %d\n",
+ pipe);
return;
}
@@ -1028,20 +1033,23 @@ static void xmit_fixed(struct snd_dbri * dbri, int pipe, unsigned int data)
}
-static void recv_fixed(struct snd_dbri * dbri, int pipe, volatile __u32 * ptr)
+static void recv_fixed(struct snd_dbri *dbri, int pipe, volatile __u32 *ptr)
{
if (pipe < 16 || pipe > DBRI_MAX_PIPE) {
- printk(KERN_ERR "DBRI: recv_fixed called with illegal pipe number\n");
+ printk(KERN_ERR "DBRI: recv_fixed called with "
+ "illegal pipe number\n");
return;
}
if (D_SDP_MODE(dbri->pipes[pipe].sdp) != D_SDP_FIXED) {
- printk(KERN_ERR "DBRI: recv_fixed called on non-fixed pipe %d\n", pipe);
+ printk(KERN_ERR "DBRI: recv_fixed called on "
+ "non-fixed pipe %d\n", pipe);
return;
}
if (dbri->pipes[pipe].sdp & D_SDP_TO_SER) {
- printk(KERN_ERR "DBRI: recv_fixed called on transmit pipe %d\n", pipe);
+ printk(KERN_ERR "DBRI: recv_fixed called on "
+ "transmit pipe %d\n", pipe);
return;
}
@@ -1064,7 +1072,7 @@ static void recv_fixed(struct snd_dbri * dbri, int pipe, volatile __u32 * ptr)
*
* Lock must be held before calling this.
*/
-static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period)
+static int setup_descs(struct snd_dbri *dbri, int streamno, unsigned int period)
{
struct dbri_streaminfo *info = &dbri->stream_info[streamno];
__u32 dvma_buffer;
@@ -1089,21 +1097,23 @@ static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period
if (streamno == DBRI_PLAY) {
if (!(dbri->pipes[info->pipe].sdp & D_SDP_TO_SER)) {
- printk(KERN_ERR "DBRI: setup_descs: Called on receive pipe %d\n",
- info->pipe);
+ printk(KERN_ERR "DBRI: setup_descs: "
+ "Called on receive pipe %d\n", info->pipe);
return -2;
}
} else {
if (dbri->pipes[info->pipe].sdp & D_SDP_TO_SER) {
- printk(KERN_ERR
+ printk(KERN_ERR
"DBRI: setup_descs: Called on transmit pipe %d\n",
info->pipe);
return -2;
}
- /* Should be able to queue multiple buffers to receive on a pipe */
+ /* Should be able to queue multiple buffers
+ * to receive on a pipe
+ */
if (pipe_active(dbri, info->pipe)) {
- printk(KERN_ERR "DBRI: recv_on_pipe: Called on active pipe %d\n",
- info->pipe);
+ printk(KERN_ERR "DBRI: recv_on_pipe: "
+ "Called on active pipe %d\n", info->pipe);
return -2;
}
@@ -1113,11 +1123,13 @@ static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period
/* Free descriptors if pipe has any */
desc = dbri->pipes[info->pipe].first_desc;
- if ( desc >= 0)
+ if (desc >= 0)
do {
- dbri->dma->desc[desc].nda = dbri->dma->desc[desc].ba = 0;
+ dbri->dma->desc[desc].ba = 0;
+ dbri->dma->desc[desc].nda = 0;
desc = dbri->next_desc[desc];
- } while (desc != -1 && desc != dbri->pipes[info->pipe].first_desc);
+ } while (desc != -1 &&
+ desc != dbri->pipes[info->pipe].first_desc);
dbri->pipes[info->pipe].desc = -1;
dbri->pipes[info->pipe].first_desc = -1;
@@ -1130,6 +1142,7 @@ static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period
if (!dbri->dma->desc[desc].ba)
break;
}
+
if (desc == DBRI_NO_DESCS) {
printk(KERN_ERR "DBRI: setup_descs: No descriptors\n");
return -1;
@@ -1150,8 +1163,7 @@ static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period
if (streamno == DBRI_PLAY) {
dbri->dma->desc[desc].word1 = DBRI_TD_CNT(mylen);
dbri->dma->desc[desc].word4 = 0;
- dbri->dma->desc[desc].word1 |=
- DBRI_TD_F | DBRI_TD_B;
+ dbri->dma->desc[desc].word1 |= DBRI_TD_F | DBRI_TD_B;
} else {
dbri->dma->desc[desc].word1 = 0;
dbri->dma->desc[desc].word4 =
@@ -1172,7 +1184,8 @@ static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period
}
if (first_desc == -1 || last_desc == -1) {
- printk(KERN_ERR "DBRI: setup_descs: Not enough descriptors available\n");
+ printk(KERN_ERR "DBRI: setup_descs: "
+ " Not enough descriptors available\n");
return -1;
}
@@ -1183,14 +1196,14 @@ static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period
dbri->pipes[info->pipe].desc = first_desc;
#ifdef DBRI_DEBUG
- for (desc = first_desc; desc != -1; ) {
+ for (desc = first_desc; desc != -1;) {
dprintk(D_DESC, "DESC %d: %08x %08x %08x %08x\n",
desc,
dbri->dma->desc[desc].word1,
dbri->dma->desc[desc].ba,
dbri->dma->desc[desc].nda, dbri->dma->desc[desc].word4);
desc = dbri->next_desc[desc];
- if ( desc == first_desc )
+ if (desc == first_desc)
break;
}
#endif
@@ -1213,7 +1226,8 @@ enum master_or_slave { CHImaster, CHIslave };
/*
* Lock must not be held before calling it.
*/
-static void reset_chi(struct snd_dbri * dbri, enum master_or_slave master_or_slave,
+static void reset_chi(struct snd_dbri *dbri,
+ enum master_or_slave master_or_slave,
int bits_per_frame)
{
s32 *cmd;
@@ -1222,7 +1236,7 @@ static void reset_chi(struct snd_dbri * dbri, enum master_or_slave master_or_sla
/* Set CHI Anchor: Pipe 16 */
cmd = dbri_cmdlock(dbri, 4);
- val = D_DTS_VO | D_DTS_VI | D_DTS_INS
+ val = D_DTS_VO | D_DTS_VI | D_DTS_INS
| D_DTS_PRVIN(16) | D_PIPE(16) | D_DTS_PRVOUT(16);
*(cmd++) = DBRI_CMD(D_DTS, 0, val);
*(cmd++) = D_TS_ANCHOR | D_TS_NEXT(16);
@@ -1246,15 +1260,16 @@ static void reset_chi(struct snd_dbri * dbri, enum master_or_slave master_or_sla
} else {
/* Setup DBRI for CHI Master - generate clock, FS
*
- * BPF = bits per 8 kHz frame
- * 12.288 MHz / CHICM_divisor = clock rate
- * FD = 1 - drive CHIFS on rising edge of CHICK
+ * BPF = bits per 8 kHz frame
+ * 12.288 MHz / CHICM_divisor = clock rate
+ * FD = 1 - drive CHIFS on rising edge of CHICK
*/
int clockrate = bits_per_frame * 8;
int divisor = 12288 / clockrate;
if (divisor > 255 || divisor * clockrate != 12288)
- printk(KERN_ERR "DBRI: illegal bits_per_frame in setup_chi\n");
+ printk(KERN_ERR "DBRI: illegal bits_per_frame "
+ "in setup_chi\n");
*(cmd++) = DBRI_CMD(D_CHI, 0, D_CHI_CHICM(divisor) | D_CHI_FD
| D_CHI_BPF(bits_per_frame));
@@ -1288,7 +1303,7 @@ to the DBRI via the CHI interface and few of the DBRI's PIO pins.
* Lock must not be held before calling it.
*/
-static void cs4215_setup_pipes(struct snd_dbri * dbri)
+static __devinit void cs4215_setup_pipes(struct snd_dbri *dbri)
{
unsigned long flags;
@@ -1303,9 +1318,9 @@ static void cs4215_setup_pipes(struct snd_dbri * dbri)
* not relevant for us (only for doublechecking).
*
* Control mode:
- * Pipe 17: Send timeslots 1-4 (slots 5-8 are readonly)
+ * Pipe 17: Send timeslots 1-4 (slots 5-8 are read only)
* Pipe 18: Receive timeslot 1 (clb).
- * Pipe 19: Receive timeslot 7 (version).
+ * Pipe 19: Receive timeslot 7 (version).
*/
setup_pipe(dbri, 4, D_SDP_MEM | D_SDP_TO_SER | D_SDP_MSB);
@@ -1321,7 +1336,7 @@ static void cs4215_setup_pipes(struct snd_dbri * dbri)
dbri_cmdwait(dbri);
}
-static int cs4215_init_data(struct cs4215 *mm)
+static __devinit int cs4215_init_data(struct cs4215 *mm)
{
/*
* No action, memory resetting only.
@@ -1355,7 +1370,7 @@ static int cs4215_init_data(struct cs4215 *mm)
return 0;
}
-static void cs4215_setdata(struct snd_dbri * dbri, int muted)
+static void cs4215_setdata(struct snd_dbri *dbri, int muted)
{
if (muted) {
dbri->mm.data[0] |= 63;
@@ -1387,7 +1402,7 @@ static void cs4215_setdata(struct snd_dbri * dbri, int muted)
/*
* Set the CS4215 to data mode.
*/
-static void cs4215_open(struct snd_dbri * dbri)
+static void cs4215_open(struct snd_dbri *dbri)
{
int data_width;
u32 tmp;
@@ -1452,7 +1467,7 @@ static void cs4215_open(struct snd_dbri * dbri)
/*
* Send the control information (i.e. audio format)
*/
-static int cs4215_setctrl(struct snd_dbri * dbri)
+static int cs4215_setctrl(struct snd_dbri *dbri)
{
int i, val;
u32 tmp;
@@ -1502,9 +1517,9 @@ static int cs4215_setctrl(struct snd_dbri * dbri)
/*
* Control mode:
- * Pipe 17: Send timeslots 1-4 (slots 5-8 are readonly)
+ * Pipe 17: Send timeslots 1-4 (slots 5-8 are read only)
* Pipe 18: Receive timeslot 1 (clb).
- * Pipe 19: Receive timeslot 7 (version).
+ * Pipe 19: Receive timeslot 7 (version).
*/
link_time_slot(dbri, 17, 16, 16, 32, dbri->mm.offset);
@@ -1522,9 +1537,9 @@ static int cs4215_setctrl(struct snd_dbri * dbri)
sbus_writel(tmp, dbri->regs + REG0);
spin_unlock_irqrestore(&dbri->lock, flags);
- for (i = 10; ((dbri->mm.status & 0xe4) != 0x20); --i) {
+ for (i = 10; ((dbri->mm.status & 0xe4) != 0x20); --i)
msleep_interruptible(1);
- }
+
if (i == 0) {
dprintk(D_MM, "CS4215 didn't respond to CLB (0x%02x)\n",
dbri->mm.status);
@@ -1556,7 +1571,7 @@ static int cs4215_setctrl(struct snd_dbri * dbri)
* As part of the process we resend the settings for the data
* timeslots as well.
*/
-static int cs4215_prepare(struct snd_dbri * dbri, unsigned int rate,
+static int cs4215_prepare(struct snd_dbri *dbri, unsigned int rate,
snd_pcm_format_t format, unsigned int channels)
{
int freq_idx;
@@ -1613,7 +1628,7 @@ static int cs4215_prepare(struct snd_dbri * dbri, unsigned int rate,
/*
*
*/
-static int cs4215_init(struct snd_dbri * dbri)
+static __devinit int cs4215_init(struct snd_dbri *dbri)
{
u32 reg2 = sbus_readl(dbri->regs + REG2);
dprintk(D_MM, "cs4215_init: reg2=0x%x\n", reg2);
@@ -1674,7 +1689,7 @@ interrupts are disabled.
/* xmit_descs()
*
- * Starts transmiting the current TD's for recording/playing.
+ * Starts transmitting the current TD's for recording/playing.
* For playback, ALSA has filled the DMA memory with new data (we hope).
*/
static void xmit_descs(struct snd_dbri *dbri)
@@ -1701,7 +1716,8 @@ static void xmit_descs(struct snd_dbri *dbri)
*(cmd++) = DBRI_CMD(D_SDP, 0,
dbri->pipes[info->pipe].sdp
| D_SDP_P | D_SDP_EVERY | D_SDP_C);
- *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, first_td);
+ *(cmd++) = dbri->dma_dvma +
+ dbri_dma_off(desc, first_td);
dbri_cmdsend(dbri, cmd, 2);
/* Reset our admin of the pipe. */
@@ -1722,7 +1738,8 @@ static void xmit_descs(struct snd_dbri *dbri)
*(cmd++) = DBRI_CMD(D_SDP, 0,
dbri->pipes[info->pipe].sdp
| D_SDP_P | D_SDP_EVERY | D_SDP_C);
- *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, first_td);
+ *(cmd++) = dbri->dma_dvma +
+ dbri_dma_off(desc, first_td);
dbri_cmdsend(dbri, cmd, 2);
/* Reset our admin of the pipe. */
@@ -1747,15 +1764,12 @@ static void xmit_descs(struct snd_dbri *dbri)
*
*/
-static void transmission_complete_intr(struct snd_dbri * dbri, int pipe)
+static void transmission_complete_intr(struct snd_dbri *dbri, int pipe)
{
- struct dbri_streaminfo *info;
- int td;
+ struct dbri_streaminfo *info = &dbri->stream_info[DBRI_PLAY];
+ int td = dbri->pipes[pipe].desc;
int status;
- info = &dbri->stream_info[DBRI_PLAY];
-
- td = dbri->pipes[pipe].desc;
while (td >= 0) {
if (td >= DBRI_NO_DESCS) {
printk(KERN_ERR "DBRI: invalid td on pipe %d\n", pipe);
@@ -1763,9 +1777,8 @@ static void transmission_complete_intr(struct snd_dbri * dbri, int pipe)
}
status = DBRI_TD_STATUS(dbri->dma->desc[td].word4);
- if (!(status & DBRI_TD_TBC)) {
+ if (!(status & DBRI_TD_TBC))
break;
- }
dprintk(D_INT, "TD %d, status 0x%02x\n", td, status);
@@ -1777,15 +1790,12 @@ static void transmission_complete_intr(struct snd_dbri * dbri, int pipe)
}
/* Notify ALSA */
- if (spin_is_locked(&dbri->lock)) {
- spin_unlock(&dbri->lock);
- snd_pcm_period_elapsed(info->substream);
- spin_lock(&dbri->lock);
- } else
- snd_pcm_period_elapsed(info->substream);
+ spin_unlock(&dbri->lock);
+ snd_pcm_period_elapsed(info->substream);
+ spin_lock(&dbri->lock);
}
-static void reception_complete_intr(struct snd_dbri * dbri, int pipe)
+static void reception_complete_intr(struct snd_dbri *dbri, int pipe)
{
struct dbri_streaminfo *info;
int rd = dbri->pipes[pipe].desc;
@@ -1809,15 +1819,12 @@ static void reception_complete_intr(struct snd_dbri * dbri, int pipe)
rd, DBRI_RD_STATUS(status), DBRI_RD_CNT(status));
/* Notify ALSA */
- if (spin_is_locked(&dbri->lock)) {
- spin_unlock(&dbri->lock);
- snd_pcm_period_elapsed(info->substream);
- spin_lock(&dbri->lock);
- } else
- snd_pcm_period_elapsed(info->substream);
+ spin_unlock(&dbri->lock);
+ snd_pcm_period_elapsed(info->substream);
+ spin_lock(&dbri->lock);
}
-static void dbri_process_one_interrupt(struct snd_dbri * dbri, int x)
+static void dbri_process_one_interrupt(struct snd_dbri *dbri, int x)
{
int val = D_INTR_GETVAL(x);
int channel = D_INTR_GETCHAN(x);
@@ -1889,7 +1896,7 @@ static void dbri_process_one_interrupt(struct snd_dbri * dbri, int x)
* right now). Non-zero words require processing and are handed off
* to dbri_process_one_interrupt AFTER advancing the pointer.
*/
-static void dbri_process_interrupt_buffer(struct snd_dbri * dbri)
+static void dbri_process_interrupt_buffer(struct snd_dbri *dbri)
{
s32 x;
@@ -1965,20 +1972,20 @@ static irqreturn_t snd_dbri_interrupt(int irq, void *dev_id)
PCM Interface
****************************************************************************/
static struct snd_pcm_hardware snd_dbri_pcm_hw = {
- .info = (SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_MMAP_VALID),
- .formats = SNDRV_PCM_FMTBIT_MU_LAW |
- SNDRV_PCM_FMTBIT_A_LAW |
- SNDRV_PCM_FMTBIT_U8 |
- SNDRV_PCM_FMTBIT_S16_BE,
- .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_5512,
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP_VALID,
+ .formats = SNDRV_PCM_FMTBIT_MU_LAW |
+ SNDRV_PCM_FMTBIT_A_LAW |
+ SNDRV_PCM_FMTBIT_U8 |
+ SNDRV_PCM_FMTBIT_S16_BE,
+ .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_5512,
.rate_min = 5512,
.rate_max = 48000,
.channels_min = 1,
.channels_max = 2,
- .buffer_bytes_max = (64 * 1024),
+ .buffer_bytes_max = 64 * 1024,
.period_bytes_min = 1,
.period_bytes_max = DBRI_TD_MAXCNT,
.periods_min = 1,
@@ -2011,7 +2018,8 @@ static int snd_hw_rule_channels(struct snd_pcm_hw_params *params,
snd_interval_any(&ch);
if (!(f->bits[0] & SNDRV_PCM_FMTBIT_S16_BE)) {
- ch.min = ch.max = 1;
+ ch.min = 1;
+ ch.max = 1;
ch.integer = 1;
return snd_interval_refine(c, &ch);
}
@@ -2035,14 +2043,14 @@ static int snd_dbri_open(struct snd_pcm_substream *substream)
info->pipe = -1;
spin_unlock_irqrestore(&dbri->lock, flags);
- snd_pcm_hw_rule_add(runtime,0,SNDRV_PCM_HW_PARAM_CHANNELS,
+ snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
snd_hw_rule_format, NULL, SNDRV_PCM_HW_PARAM_FORMAT,
-1);
- snd_pcm_hw_rule_add(runtime,0,SNDRV_PCM_HW_PARAM_FORMAT,
- snd_hw_rule_channels, NULL,
+ snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
+ snd_hw_rule_channels, NULL,
SNDRV_PCM_HW_PARAM_CHANNELS,
-1);
-
+
cs4215_open(dbri);
return 0;
@@ -2145,7 +2153,7 @@ static int snd_dbri_prepare(struct snd_pcm_substream *substream)
spin_lock_irq(&dbri->lock);
info->offset = 0;
- /* Setup the all the transmit/receive desciptors to cover the
+ /* Setup the all the transmit/receive descriptors to cover the
* whole DMA buffer.
*/
ret = setup_descs(dbri, DBRI_STREAMNO(substream),
@@ -2205,12 +2213,12 @@ static struct snd_pcm_ops snd_dbri_ops = {
.pointer = snd_dbri_pointer,
};
-static int __devinit snd_dbri_pcm(struct snd_dbri * dbri)
+static int __devinit snd_dbri_pcm(struct snd_card *card)
{
struct snd_pcm *pcm;
int err;
- if ((err = snd_pcm_new(dbri->card,
+ if ((err = snd_pcm_new(card,
/* ID */ "sun_dbri",
/* device */ 0,
/* playback count */ 1,
@@ -2221,16 +2229,15 @@ static int __devinit snd_dbri_pcm(struct snd_dbri * dbri)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_dbri_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_dbri_ops);
- pcm->private_data = dbri;
+ pcm->private_data = card->private_data;
pcm->info_flags = 0;
- strcpy(pcm->name, dbri->card->shortname);
+ strcpy(pcm->name, card->shortname);
if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm,
SNDRV_DMA_TYPE_CONTINUOUS,
snd_dma_continuous_data(GFP_KERNEL),
- 64 * 1024, 64 * 1024)) < 0) {
+ 64 * 1024, 64 * 1024)) < 0)
return err;
- }
return 0;
}
@@ -2245,11 +2252,10 @@ static int snd_cs4215_info_volume(struct snd_kcontrol *kcontrol,
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
uinfo->value.integer.min = 0;
- if (kcontrol->private_value == DBRI_PLAY) {
+ if (kcontrol->private_value == DBRI_PLAY)
uinfo->value.integer.max = DBRI_MAX_VOLUME;
- } else {
+ else
uinfo->value.integer.max = DBRI_MAX_GAIN;
- }
return 0;
}
@@ -2271,7 +2277,8 @@ static int snd_cs4215_put_volume(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_dbri *dbri = snd_kcontrol_chip(kcontrol);
- struct dbri_streaminfo *info = &dbri->stream_info[kcontrol->private_value];
+ struct dbri_streaminfo *info =
+ &dbri->stream_info[kcontrol->private_value];
int changed = 0;
if (info->left_gain != ucontrol->value.integer.value[0]) {
@@ -2282,7 +2289,7 @@ static int snd_cs4215_put_volume(struct snd_kcontrol *kcontrol,
info->right_gain = ucontrol->value.integer.value[1];
changed = 1;
}
- if (changed == 1) {
+ if (changed) {
/* First mute outputs, and wait 1/8000 sec (125 us)
* to make sure this takes. This avoids clicking noises.
*/
@@ -2316,18 +2323,16 @@ static int snd_cs4215_get_single(struct snd_kcontrol *kcontrol,
int invert = (kcontrol->private_value >> 24) & 1;
snd_assert(dbri != NULL, return -EINVAL);
- if (elem < 4) {
+ if (elem < 4)
ucontrol->value.integer.value[0] =
(dbri->mm.data[elem] >> shift) & mask;
- } else {
+ else
ucontrol->value.integer.value[0] =
(dbri->mm.ctrl[elem - 4] >> shift) & mask;
- }
- if (invert == 1) {
+ if (invert == 1)
ucontrol->value.integer.value[0] =
mask - ucontrol->value.integer.value[0];
- }
return 0;
}
@@ -2378,11 +2383,12 @@ static int snd_cs4215_put_single(struct snd_kcontrol *kcontrol,
timeslots. Shift is the bit offset in the timeslot, mask defines the
number of bits. invert is a boolean for use with attenuation.
*/
-#define CS4215_SINGLE(xname, entry, shift, mask, invert) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
- .info = snd_cs4215_info_single, \
- .get = snd_cs4215_get_single, .put = snd_cs4215_put_single, \
- .private_value = entry | (shift << 8) | (mask << 16) | (invert << 24) },
+#define CS4215_SINGLE(xname, entry, shift, mask, invert) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
+ .info = snd_cs4215_info_single, \
+ .get = snd_cs4215_get_single, .put = snd_cs4215_put_single, \
+ .private_value = (entry) | ((shift) << 8) | ((mask) << 16) | \
+ ((invert) << 24) },
static struct snd_kcontrol_new dbri_controls[] __devinitdata = {
{
@@ -2411,19 +2417,20 @@ static struct snd_kcontrol_new dbri_controls[] __devinitdata = {
CS4215_SINGLE("Mic boost", 4, 4, 1, 1)
};
-static int __init snd_dbri_mixer(struct snd_dbri * dbri)
+static int __devinit snd_dbri_mixer(struct snd_card *card)
{
- struct snd_card *card;
int idx, err;
+ struct snd_dbri *dbri;
- snd_assert(dbri != NULL && dbri->card != NULL, return -EINVAL);
+ snd_assert(card != NULL && card->private_data != NULL, return -EINVAL);
+ dbri = card->private_data;
- card = dbri->card;
strcpy(card->mixername, card->shortname);
for (idx = 0; idx < ARRAY_SIZE(dbri_controls); idx++) {
- if ((err = snd_ctl_add(card,
- snd_ctl_new1(&dbri_controls[idx], dbri))) < 0)
+ err = snd_ctl_add(card,
+ snd_ctl_new1(&dbri_controls[idx], dbri));
+ if (err < 0)
return err;
}
@@ -2438,7 +2445,8 @@ static int __init snd_dbri_mixer(struct snd_dbri * dbri)
/****************************************************************************
/proc interface
****************************************************************************/
-static void dbri_regs_read(struct snd_info_entry * entry, struct snd_info_buffer *buffer)
+static void dbri_regs_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
struct snd_dbri *dbri = entry->private_data;
@@ -2449,7 +2457,7 @@ static void dbri_regs_read(struct snd_info_entry * entry, struct snd_info_buffer
}
#ifdef DBRI_DEBUG
-static void dbri_debug_read(struct snd_info_entry * entry,
+static void dbri_debug_read(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
struct snd_dbri *dbri = entry->private_data;
@@ -2463,7 +2471,8 @@ static void dbri_debug_read(struct snd_info_entry * entry,
"Pipe %d: %s SDP=0x%x desc=%d, "
"len=%d next %d\n",
pipe,
- ((pptr->sdp & D_SDP_TO_SER) ? "output" : "input"),
+ (pptr->sdp & D_SDP_TO_SER) ? "output" :
+ "input",
pptr->sdp, pptr->desc,
pptr->length, pptr->nextpipe);
}
@@ -2471,15 +2480,16 @@ static void dbri_debug_read(struct snd_info_entry * entry,
}
#endif
-void snd_dbri_proc(struct snd_dbri * dbri)
+void __devinit snd_dbri_proc(struct snd_card *card)
{
+ struct snd_dbri *dbri = card->private_data;
struct snd_info_entry *entry;
- if (! snd_card_proc_new(dbri->card, "regs", &entry))
+ if (!snd_card_proc_new(card, "regs", &entry))
snd_info_set_text_ops(entry, dbri, dbri_regs_read);
#ifdef DBRI_DEBUG
- if (! snd_card_proc_new(dbri->card, "debug", &entry)) {
+ if (!snd_card_proc_new(card, "debug", &entry)) {
snd_info_set_text_ops(entry, dbri, dbri_debug_read);
entry->mode = S_IFREG | S_IRUGO; /* Readable only. */
}
@@ -2491,19 +2501,18 @@ void snd_dbri_proc(struct snd_dbri * dbri)
**************************** Initialization ********************************
****************************************************************************
*/
-static void snd_dbri_free(struct snd_dbri * dbri);
+static void snd_dbri_free(struct snd_dbri *dbri);
-static int __init snd_dbri_create(struct snd_card *card,
+static int __devinit snd_dbri_create(struct snd_card *card,
struct sbus_dev *sdev,
- struct linux_prom_irqs *irq, int dev)
+ int irq, int dev)
{
struct snd_dbri *dbri = card->private_data;
int err;
spin_lock_init(&dbri->lock);
- dbri->card = card;
dbri->sdev = sdev;
- dbri->irq = irq->pri;
+ dbri->irq = irq;
dbri->dma = sbus_alloc_consistent(sdev, sizeof(struct dbri_dma),
&dbri->dma_dvma);
@@ -2541,13 +2550,10 @@ static int __init snd_dbri_create(struct snd_card *card,
return err;
}
- dbri->next = dbri_list;
- dbri_list = dbri;
-
return 0;
}
-static void snd_dbri_free(struct snd_dbri * dbri)
+static void snd_dbri_free(struct snd_dbri *dbri)
{
dprintk(D_GEN, "snd_dbri_free\n");
dbri_reset(dbri);
@@ -2563,20 +2569,19 @@ static void snd_dbri_free(struct snd_dbri * dbri)
(void *)dbri->dma, dbri->dma_dvma);
}
-static int __init dbri_attach(int prom_node, struct sbus_dev *sdev)
+static int __devinit dbri_probe(struct of_device *of_dev,
+ const struct of_device_id *match)
{
+ struct sbus_dev *sdev = to_sbus_device(&of_dev->dev);
struct snd_dbri *dbri;
- struct linux_prom_irqs irq;
+ int irq;
struct resource *rp;
struct snd_card *card;
static int dev = 0;
int err;
- if (sdev->prom_name[9] < 'e') {
- printk(KERN_ERR "DBRI: unsupported chip version %c found.\n",
- sdev->prom_name[9]);
- return -EIO;
- }
+ dprintk(D_GEN, "DBRI: Found %s in SBUS slot %d\n",
+ sdev->prom_name, sdev->slot);
if (dev >= SNDRV_CARDS)
return -ENODEV;
@@ -2585,9 +2590,9 @@ static int __init dbri_attach(int prom_node, struct sbus_dev *sdev)
return -ENOENT;
}
- err = prom_getproperty(prom_node, "intr", (char *)&irq, sizeof(irq));
- if (err < 0) {
- printk(KERN_ERR "DBRI-%d: Firmware node lacks IRQ property.\n", dev);
+ irq = sdev->irqs[0];
+ if (irq <= 0) {
+ printk(KERN_ERR "DBRI-%d: No IRQ.\n", dev);
return -ENODEV;
}
@@ -2601,24 +2606,29 @@ static int __init dbri_attach(int prom_node, struct sbus_dev *sdev)
rp = &sdev->resource[0];
sprintf(card->longname, "%s at 0x%02lx:0x%016Lx, irq %d",
card->shortname,
- rp->flags & 0xffL, (unsigned long long)rp->start, irq.pri);
+ rp->flags & 0xffL, (unsigned long long)rp->start, irq);
- if ((err = snd_dbri_create(card, sdev, &irq, dev)) < 0) {
+ err = snd_dbri_create(card, sdev, irq, dev);
+ if (err < 0) {
snd_card_free(card);
return err;
}
dbri = card->private_data;
- if ((err = snd_dbri_pcm(dbri)) < 0)
+ err = snd_dbri_pcm(card);
+ if (err < 0)
goto _err;
- if ((err = snd_dbri_mixer(dbri)) < 0)
+ err = snd_dbri_mixer(card);
+ if (err < 0)
goto _err;
/* /proc file handling */
- snd_dbri_proc(dbri);
+ snd_dbri_proc(card);
+ dev_set_drvdata(&of_dev->dev, card);
- if ((err = snd_card_register(card)) < 0)
+ err = snd_card_register(card);
+ if (err < 0)
goto _err;
printk(KERN_INFO "audio%d at %p (irq %d) is DBRI(%c)+CS4215(%d)\n",
@@ -2628,49 +2638,52 @@ static int __init dbri_attach(int prom_node, struct sbus_dev *sdev)
return 0;
- _err:
+_err:
snd_dbri_free(dbri);
snd_card_free(card);
return err;
}
-/* Probe for the dbri chip and then attach the driver. */
-static int __init dbri_init(void)
+static int __devexit dbri_remove(struct of_device *dev)
{
- struct sbus_bus *sbus;
- struct sbus_dev *sdev;
- int found = 0;
-
- /* Probe each SBUS for the DBRI chip(s). */
- for_all_sbusdev(sdev, sbus) {
- /*
- * The version is coded in the last character
- */
- if (!strncmp(sdev->prom_name, "SUNW,DBRI", 9)) {
- dprintk(D_GEN, "DBRI: Found %s in SBUS slot %d\n",
- sdev->prom_name, sdev->slot);
+ struct snd_card *card = dev_get_drvdata(&dev->dev);
- if (dbri_attach(sdev->prom_node, sdev) == 0)
- found++;
- }
- }
+ snd_dbri_free(card->private_data);
+ snd_card_free(card);
+
+ dev_set_drvdata(&dev->dev, NULL);
+
+ return 0;
+}
+
+static struct of_device_id dbri_match[] = {
+ {
+ .name = "SUNW,DBRIe",
+ },
+ {
+ .name = "SUNW,DBRIf",
+ },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, dbri_match);
+
+static struct of_platform_driver dbri_sbus_driver = {
+ .name = "dbri",
+ .match_table = dbri_match,
+ .probe = dbri_probe,
+ .remove = __devexit_p(dbri_remove),
+};
- return (found > 0) ? 0 : -EIO;
+/* Probe for the dbri chip and then attach the driver. */
+static int __init dbri_init(void)
+{
+ return of_register_driver(&dbri_sbus_driver, &sbus_bus_type);
}
static void __exit dbri_exit(void)
{
- struct snd_dbri *this = dbri_list;
-
- while (this != NULL) {
- struct snd_dbri *next = this->next;
- struct snd_card *card = this->card;
-
- snd_dbri_free(this);
- snd_card_free(card);
- this = next;
- }
- dbri_list = NULL;
+ of_unregister_driver(&dbri_sbus_driver);
}
module_init(dbri_init);
diff --git a/sound/spi/Kconfig b/sound/spi/Kconfig
new file mode 100644
index 000000000000..0d08c29213c8
--- /dev/null
+++ b/sound/spi/Kconfig
@@ -0,0 +1,31 @@
+#SPI drivers
+
+menu "SPI devices"
+ depends on SND != n
+
+config SND_AT73C213
+ tristate "Atmel AT73C213 DAC driver"
+ depends on ATMEL_SSC
+ select SND_PCM
+ help
+ Say Y here if you want to use the Atmel AT73C213 external DAC. This
+ DAC can be found on Atmel development boards.
+
+ This driver requires the Atmel SSC driver for sound sink, a
+ peripheral found on most AT91 and AVR32 microprocessors.
+
+ To compile this driver as a module, choose M here: the module will be
+ called snd-at73c213.
+
+config SND_AT73C213_TARGET_BITRATE
+ int "Target bitrate for AT73C213"
+ depends on SND_AT73C213
+ default "48000"
+ range 8000 50000
+ help
+ Sets the target bitrate for the bitrate calculator in the driver.
+ Limited by hardware to be between 8000 Hz and 50000 Hz.
+
+ Set to 48000 Hz by default.
+
+endmenu
diff --git a/sound/spi/Makefile b/sound/spi/Makefile
new file mode 100644
index 000000000000..026fb73f887f
--- /dev/null
+++ b/sound/spi/Makefile
@@ -0,0 +1,5 @@
+# Makefile for SPI drivers
+
+snd-at73c213-objs := at73c213.o
+
+obj-$(CONFIG_SND_AT73C213) += snd-at73c213.o
diff --git a/sound/spi/at73c213.c b/sound/spi/at73c213.c
new file mode 100644
index 000000000000..fee869bcc959
--- /dev/null
+++ b/sound/spi/at73c213.c
@@ -0,0 +1,1129 @@
+/*
+ * Driver for AT73C213 16-bit stereo DAC connected to Atmel SSC
+ *
+ * Copyright (C) 2006-2007 Atmel Norway
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+/*#define DEBUG*/
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <sound/driver.h>
+#include <sound/initval.h>
+#include <sound/control.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+
+#include <linux/atmel-ssc.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/at73c213.h>
+
+#include "at73c213.h"
+
+#define BITRATE_MIN 8000 /* Hardware limit? */
+#define BITRATE_TARGET CONFIG_SND_AT73C213_TARGET_BITRATE
+#define BITRATE_MAX 50000 /* Hardware limit. */
+
+/* Initial (hardware reset) AT73C213 register values. */
+static u8 snd_at73c213_original_image[18] =
+{
+ 0x00, /* 00 - CTRL */
+ 0x05, /* 01 - LLIG */
+ 0x05, /* 02 - RLIG */
+ 0x08, /* 03 - LPMG */
+ 0x08, /* 04 - RPMG */
+ 0x00, /* 05 - LLOG */
+ 0x00, /* 06 - RLOG */
+ 0x22, /* 07 - OLC */
+ 0x09, /* 08 - MC */
+ 0x00, /* 09 - CSFC */
+ 0x00, /* 0A - MISC */
+ 0x00, /* 0B - */
+ 0x00, /* 0C - PRECH */
+ 0x05, /* 0D - AUXG */
+ 0x00, /* 0E - */
+ 0x00, /* 0F - */
+ 0x00, /* 10 - RST */
+ 0x00, /* 11 - PA_CTRL */
+};
+
+struct snd_at73c213 {
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+ struct snd_pcm_substream *substream;
+ struct at73c213_board_info *board;
+ int irq;
+ int period;
+ unsigned long bitrate;
+ struct clk *bitclk;
+ struct ssc_device *ssc;
+ struct spi_device *spi;
+ u8 spi_wbuffer[2];
+ u8 spi_rbuffer[2];
+ /* Image of the SPI registers in AT73C213. */
+ u8 reg_image[18];
+ /* Protect registers against concurrent access. */
+ spinlock_t lock;
+};
+
+#define get_chip(card) ((struct snd_at73c213 *)card->private_data)
+
+static int
+snd_at73c213_write_reg(struct snd_at73c213 *chip, u8 reg, u8 val)
+{
+ struct spi_message msg;
+ struct spi_transfer msg_xfer = {
+ .len = 2,
+ .cs_change = 0,
+ };
+ int retval;
+
+ spi_message_init(&msg);
+
+ chip->spi_wbuffer[0] = reg;
+ chip->spi_wbuffer[1] = val;
+
+ msg_xfer.tx_buf = chip->spi_wbuffer;
+ msg_xfer.rx_buf = chip->spi_rbuffer;
+ spi_message_add_tail(&msg_xfer, &msg);
+
+ retval = spi_sync(chip->spi, &msg);
+
+ if (!retval)
+ chip->reg_image[reg] = val;
+
+ return retval;
+}
+
+static struct snd_pcm_hardware snd_at73c213_playback_hw = {
+ .info = SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER,
+ .formats = SNDRV_PCM_FMTBIT_S16_BE,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS,
+ .rate_min = 8000, /* Replaced by chip->bitrate later. */
+ .rate_max = 50000, /* Replaced by chip->bitrate later. */
+ .channels_min = 2,
+ .channels_max = 2,
+ .buffer_bytes_max = 64 * 1024 - 1,
+ .period_bytes_min = 512,
+ .period_bytes_max = 64 * 1024 - 1,
+ .periods_min = 4,
+ .periods_max = 1024,
+};
+
+/*
+ * Calculate and set bitrate and divisions.
+ */
+static int snd_at73c213_set_bitrate(struct snd_at73c213 *chip)
+{
+ unsigned long ssc_rate = clk_get_rate(chip->ssc->clk);
+ unsigned long dac_rate_new, ssc_div, status;
+ unsigned long ssc_div_max, ssc_div_min;
+ int max_tries;
+
+ /*
+ * We connect two clocks here, picking divisors so the I2S clocks
+ * out data at the same rate the DAC clocks it in ... and as close
+ * as practical to the desired target rate.
+ *
+ * The DAC master clock (MCLK) is programmable, and is either 256
+ * or (not here) 384 times the I2S output clock (BCLK).
+ */
+
+ /* SSC clock / (bitrate * stereo * 16-bit). */
+ ssc_div = ssc_rate / (BITRATE_TARGET * 2 * 16);
+ ssc_div_min = ssc_rate / (BITRATE_MAX * 2 * 16);
+ ssc_div_max = ssc_rate / (BITRATE_MIN * 2 * 16);
+ max_tries = (ssc_div_max - ssc_div_min) / 2;
+
+ if (max_tries < 1)
+ max_tries = 1;
+
+ /* ssc_div must be a power of 2. */
+ ssc_div = (ssc_div + 1) & ~1UL;
+
+ if ((ssc_rate / (ssc_div * 2 * 16)) < BITRATE_MIN) {
+ ssc_div -= 2;
+ if ((ssc_rate / (ssc_div * 2 * 16)) > BITRATE_MAX)
+ return -ENXIO;
+ }
+
+ /* Search for a possible bitrate. */
+ do {
+ /* SSC clock / (ssc divider * 16-bit * stereo). */
+ if ((ssc_rate / (ssc_div * 2 * 16)) < BITRATE_MIN)
+ return -ENXIO;
+
+ /* 256 / (2 * 16) = 8 */
+ dac_rate_new = 8 * (ssc_rate / ssc_div);
+
+ status = clk_round_rate(chip->board->dac_clk, dac_rate_new);
+ if (status < 0)
+ return status;
+
+ /* Ignore difference smaller than 256 Hz. */
+ if ((status/256) == (dac_rate_new/256))
+ goto set_rate;
+
+ ssc_div += 2;
+ } while (--max_tries);
+
+ /* Not able to find a valid bitrate. */
+ return -ENXIO;
+
+set_rate:
+ status = clk_set_rate(chip->board->dac_clk, status);
+ if (status < 0)
+ return status;
+
+ /* Set divider in SSC device. */
+ ssc_writel(chip->ssc->regs, CMR, ssc_div/2);
+
+ /* SSC clock / (ssc divider * 16-bit * stereo). */
+ chip->bitrate = ssc_rate / (ssc_div * 16 * 2);
+
+ dev_info(&chip->spi->dev,
+ "at73c213: supported bitrate is %lu (%lu divider)\n",
+ chip->bitrate, ssc_div);
+
+ return 0;
+}
+
+static int snd_at73c213_pcm_open(struct snd_pcm_substream *substream)
+{
+ struct snd_at73c213 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ snd_at73c213_playback_hw.rate_min = chip->bitrate;
+ snd_at73c213_playback_hw.rate_max = chip->bitrate;
+ runtime->hw = snd_at73c213_playback_hw;
+ chip->substream = substream;
+
+ return 0;
+}
+
+static int snd_at73c213_pcm_close(struct snd_pcm_substream *substream)
+{
+ struct snd_at73c213 *chip = snd_pcm_substream_chip(substream);
+ chip->substream = NULL;
+ return 0;
+}
+
+static int snd_at73c213_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
+{
+ return snd_pcm_lib_malloc_pages(substream,
+ params_buffer_bytes(hw_params));
+}
+
+static int snd_at73c213_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+ return snd_pcm_lib_free_pages(substream);
+}
+
+static int snd_at73c213_pcm_prepare(struct snd_pcm_substream *substream)
+{
+ struct snd_at73c213 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int block_size;
+
+ block_size = frames_to_bytes(runtime, runtime->period_size);
+
+ chip->period = 0;
+
+ ssc_writel(chip->ssc->regs, PDC_TPR,
+ (long)runtime->dma_addr);
+ ssc_writel(chip->ssc->regs, PDC_TCR, runtime->period_size * 2);
+ ssc_writel(chip->ssc->regs, PDC_TNPR,
+ (long)runtime->dma_addr + block_size);
+ ssc_writel(chip->ssc->regs, PDC_TNCR, runtime->period_size * 2);
+
+ return 0;
+}
+
+static int snd_at73c213_pcm_trigger(struct snd_pcm_substream *substream,
+ int cmd)
+{
+ struct snd_at73c213 *chip = snd_pcm_substream_chip(substream);
+ int retval = 0;
+
+ spin_lock(&chip->lock);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ ssc_writel(chip->ssc->regs, IER, SSC_BIT(IER_ENDTX));
+ ssc_writel(chip->ssc->regs, PDC_PTCR, SSC_BIT(PDC_PTCR_TXTEN));
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ ssc_writel(chip->ssc->regs, PDC_PTCR, SSC_BIT(PDC_PTCR_TXTDIS));
+ ssc_writel(chip->ssc->regs, IDR, SSC_BIT(IDR_ENDTX));
+ break;
+ default:
+ dev_dbg(&chip->spi->dev, "spurious command %x\n", cmd);
+ retval = -EINVAL;
+ break;
+ }
+
+ spin_unlock(&chip->lock);
+
+ return retval;
+}
+
+static snd_pcm_uframes_t
+snd_at73c213_pcm_pointer(struct snd_pcm_substream *substream)
+{
+ struct snd_at73c213 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ snd_pcm_uframes_t pos;
+ unsigned long bytes;
+
+ bytes = ssc_readl(chip->ssc->regs, PDC_TPR)
+ - (unsigned long)runtime->dma_addr;
+
+ pos = bytes_to_frames(runtime, bytes);
+ if (pos >= runtime->buffer_size)
+ pos -= runtime->buffer_size;
+
+ return pos;
+}
+
+static struct snd_pcm_ops at73c213_playback_ops = {
+ .open = snd_at73c213_pcm_open,
+ .close = snd_at73c213_pcm_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_at73c213_pcm_hw_params,
+ .hw_free = snd_at73c213_pcm_hw_free,
+ .prepare = snd_at73c213_pcm_prepare,
+ .trigger = snd_at73c213_pcm_trigger,
+ .pointer = snd_at73c213_pcm_pointer,
+};
+
+static void snd_at73c213_pcm_free(struct snd_pcm *pcm)
+{
+ struct snd_at73c213 *chip = snd_pcm_chip(pcm);
+ if (chip->pcm) {
+ snd_pcm_lib_preallocate_free_for_all(chip->pcm);
+ chip->pcm = NULL;
+ }
+}
+
+static int __devinit snd_at73c213_pcm_new(struct snd_at73c213 *chip, int device)
+{
+ struct snd_pcm *pcm;
+ int retval;
+
+ retval = snd_pcm_new(chip->card, chip->card->shortname,
+ device, 1, 0, &pcm);
+ if (retval < 0)
+ goto out;
+
+ pcm->private_data = chip;
+ pcm->private_free = snd_at73c213_pcm_free;
+ pcm->info_flags = SNDRV_PCM_INFO_BLOCK_TRANSFER;
+ strcpy(pcm->name, "at73c213");
+ chip->pcm = pcm;
+
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &at73c213_playback_ops);
+
+ retval = snd_pcm_lib_preallocate_pages_for_all(chip->pcm,
+ SNDRV_DMA_TYPE_DEV, &chip->ssc->pdev->dev,
+ 64 * 1024, 64 * 1024);
+out:
+ return retval;
+}
+
+static irqreturn_t snd_at73c213_interrupt(int irq, void *dev_id)
+{
+ struct snd_at73c213 *chip = dev_id;
+ struct snd_pcm_runtime *runtime = chip->substream->runtime;
+ u32 status;
+ int offset;
+ int block_size;
+ int next_period;
+ int retval = IRQ_NONE;
+
+ spin_lock(&chip->lock);
+
+ block_size = frames_to_bytes(runtime, runtime->period_size);
+ status = ssc_readl(chip->ssc->regs, IMR);
+
+ if (status & SSC_BIT(IMR_ENDTX)) {
+ chip->period++;
+ if (chip->period == runtime->periods)
+ chip->period = 0;
+ next_period = chip->period + 1;
+ if (next_period == runtime->periods)
+ next_period = 0;
+
+ offset = block_size * next_period;
+
+ ssc_writel(chip->ssc->regs, PDC_TNPR,
+ (long)runtime->dma_addr + offset);
+ ssc_writel(chip->ssc->regs, PDC_TNCR, runtime->period_size * 2);
+ retval = IRQ_HANDLED;
+ }
+
+ ssc_readl(chip->ssc->regs, IMR);
+ spin_unlock(&chip->lock);
+
+ if (status & SSC_BIT(IMR_ENDTX))
+ snd_pcm_period_elapsed(chip->substream);
+
+ return retval;
+}
+
+/*
+ * Mixer functions.
+ */
+static int snd_at73c213_mono_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_at73c213 *chip = snd_kcontrol_chip(kcontrol);
+ int reg = kcontrol->private_value & 0xff;
+ int shift = (kcontrol->private_value >> 8) & 0xff;
+ int mask = (kcontrol->private_value >> 16) & 0xff;
+ int invert = (kcontrol->private_value >> 24) & 0xff;
+
+ spin_lock_irq(&chip->lock);
+
+ ucontrol->value.integer.value[0] =
+ (chip->reg_image[reg] >> shift) & mask;
+
+ if (invert)
+ ucontrol->value.integer.value[0] =
+ mask - ucontrol->value.integer.value[0];
+
+ spin_unlock_irq(&chip->lock);
+
+ return 0;
+}
+
+static int snd_at73c213_mono_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_at73c213 *chip = snd_kcontrol_chip(kcontrol);
+ int reg = kcontrol->private_value & 0xff;
+ int shift = (kcontrol->private_value >> 8) & 0xff;
+ int mask = (kcontrol->private_value >> 16) & 0xff;
+ int invert = (kcontrol->private_value >> 24) & 0xff;
+ int change, retval;
+ unsigned short val;
+
+ val = (ucontrol->value.integer.value[0] & mask);
+ if (invert)
+ val = mask - val;
+ val <<= shift;
+
+ spin_lock_irq(&chip->lock);
+
+ val = (chip->reg_image[reg] & ~(mask << shift)) | val;
+ change = val != chip->reg_image[reg];
+ retval = snd_at73c213_write_reg(chip, reg, val);
+
+ spin_unlock_irq(&chip->lock);
+
+ if (retval)
+ return retval;
+
+ return change;
+}
+
+static int snd_at73c213_stereo_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ int mask = (kcontrol->private_value >> 24) & 0xff;
+
+ if (mask == 1)
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ else
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+
+ uinfo->count = 2;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = mask;
+
+ return 0;
+}
+
+static int snd_at73c213_stereo_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_at73c213 *chip = snd_kcontrol_chip(kcontrol);
+ int left_reg = kcontrol->private_value & 0xff;
+ int right_reg = (kcontrol->private_value >> 8) & 0xff;
+ int shift_left = (kcontrol->private_value >> 16) & 0x07;
+ int shift_right = (kcontrol->private_value >> 19) & 0x07;
+ int mask = (kcontrol->private_value >> 24) & 0xff;
+ int invert = (kcontrol->private_value >> 22) & 1;
+
+ spin_lock_irq(&chip->lock);
+
+ ucontrol->value.integer.value[0] =
+ (chip->reg_image[left_reg] >> shift_left) & mask;
+ ucontrol->value.integer.value[1] =
+ (chip->reg_image[right_reg] >> shift_right) & mask;
+
+ if (invert) {
+ ucontrol->value.integer.value[0] =
+ mask - ucontrol->value.integer.value[0];
+ ucontrol->value.integer.value[1] =
+ mask - ucontrol->value.integer.value[1];
+ }
+
+ spin_unlock_irq(&chip->lock);
+
+ return 0;
+}
+
+static int snd_at73c213_stereo_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_at73c213 *chip = snd_kcontrol_chip(kcontrol);
+ int left_reg = kcontrol->private_value & 0xff;
+ int right_reg = (kcontrol->private_value >> 8) & 0xff;
+ int shift_left = (kcontrol->private_value >> 16) & 0x07;
+ int shift_right = (kcontrol->private_value >> 19) & 0x07;
+ int mask = (kcontrol->private_value >> 24) & 0xff;
+ int invert = (kcontrol->private_value >> 22) & 1;
+ int change, retval;
+ unsigned short val1, val2;
+
+ val1 = ucontrol->value.integer.value[0] & mask;
+ val2 = ucontrol->value.integer.value[1] & mask;
+ if (invert) {
+ val1 = mask - val1;
+ val2 = mask - val2;
+ }
+ val1 <<= shift_left;
+ val2 <<= shift_right;
+
+ spin_lock_irq(&chip->lock);
+
+ val1 = (chip->reg_image[left_reg] & ~(mask << shift_left)) | val1;
+ val2 = (chip->reg_image[right_reg] & ~(mask << shift_right)) | val2;
+ change = val1 != chip->reg_image[left_reg]
+ || val2 != chip->reg_image[right_reg];
+ retval = snd_at73c213_write_reg(chip, left_reg, val1);
+ if (retval) {
+ spin_unlock_irq(&chip->lock);
+ goto out;
+ }
+ retval = snd_at73c213_write_reg(chip, right_reg, val2);
+ if (retval) {
+ spin_unlock_irq(&chip->lock);
+ goto out;
+ }
+
+ spin_unlock_irq(&chip->lock);
+
+ return change;
+
+out:
+ return retval;
+}
+
+static int snd_at73c213_mono_switch_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+
+ return 0;
+}
+
+static int snd_at73c213_mono_switch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_at73c213 *chip = snd_kcontrol_chip(kcontrol);
+ int reg = kcontrol->private_value & 0xff;
+ int shift = (kcontrol->private_value >> 8) & 0xff;
+ int invert = (kcontrol->private_value >> 24) & 0xff;
+
+ spin_lock_irq(&chip->lock);
+
+ ucontrol->value.integer.value[0] =
+ (chip->reg_image[reg] >> shift) & 0x01;
+
+ if (invert)
+ ucontrol->value.integer.value[0] =
+ 0x01 - ucontrol->value.integer.value[0];
+
+ spin_unlock_irq(&chip->lock);
+
+ return 0;
+}
+
+static int snd_at73c213_mono_switch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_at73c213 *chip = snd_kcontrol_chip(kcontrol);
+ int reg = kcontrol->private_value & 0xff;
+ int shift = (kcontrol->private_value >> 8) & 0xff;
+ int mask = (kcontrol->private_value >> 16) & 0xff;
+ int invert = (kcontrol->private_value >> 24) & 0xff;
+ int change, retval;
+ unsigned short val;
+
+ if (ucontrol->value.integer.value[0])
+ val = mask;
+ else
+ val = 0;
+
+ if (invert)
+ val = mask - val;
+ val <<= shift;
+
+ spin_lock_irq(&chip->lock);
+
+ val |= (chip->reg_image[reg] & ~(mask << shift));
+ change = val != chip->reg_image[reg];
+
+ retval = snd_at73c213_write_reg(chip, reg, val);
+
+ spin_unlock_irq(&chip->lock);
+
+ if (retval)
+ return retval;
+
+ return change;
+}
+
+static int snd_at73c213_pa_volume_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = ((kcontrol->private_value >> 16) & 0xff) - 1;
+
+ return 0;
+}
+
+static int snd_at73c213_line_capture_volume_info(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 2;
+ /* When inverted will give values 0x10001 => 0. */
+ uinfo->value.integer.min = 14;
+ uinfo->value.integer.max = 31;
+
+ return 0;
+}
+
+static int snd_at73c213_aux_capture_volume_info(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ /* When inverted will give values 0x10001 => 0. */
+ uinfo->value.integer.min = 14;
+ uinfo->value.integer.max = 31;
+
+ return 0;
+}
+
+#define AT73C213_MONO_SWITCH(xname, xindex, reg, shift, mask, invert) \
+{ \
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ .name = xname, \
+ .index = xindex, \
+ .info = snd_at73c213_mono_switch_info, \
+ .get = snd_at73c213_mono_switch_get, \
+ .put = snd_at73c213_mono_switch_put, \
+ .private_value = (reg | (shift << 8) | (mask << 16) | (invert << 24)) \
+}
+
+#define AT73C213_STEREO(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \
+{ \
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ .name = xname, \
+ .index = xindex, \
+ .info = snd_at73c213_stereo_info, \
+ .get = snd_at73c213_stereo_get, \
+ .put = snd_at73c213_stereo_put, \
+ .private_value = (left_reg | (right_reg << 8) \
+ | (shift_left << 16) | (shift_right << 19) \
+ | (mask << 24) | (invert << 22)) \
+}
+
+static struct snd_kcontrol_new snd_at73c213_controls[] __devinitdata = {
+AT73C213_STEREO("Master Playback Volume", 0, DAC_LMPG, DAC_RMPG, 0, 0, 0x1f, 1),
+AT73C213_STEREO("Master Playback Switch", 0, DAC_LMPG, DAC_RMPG, 5, 5, 1, 1),
+AT73C213_STEREO("PCM Playback Volume", 0, DAC_LLOG, DAC_RLOG, 0, 0, 0x1f, 1),
+AT73C213_STEREO("PCM Playback Switch", 0, DAC_LLOG, DAC_RLOG, 5, 5, 1, 1),
+AT73C213_MONO_SWITCH("Mono PA Playback Switch", 0, DAC_CTRL, DAC_CTRL_ONPADRV,
+ 0x01, 0),
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "PA Playback Volume",
+ .index = 0,
+ .info = snd_at73c213_pa_volume_info,
+ .get = snd_at73c213_mono_get,
+ .put = snd_at73c213_mono_put,
+ .private_value = PA_CTRL | (PA_CTRL_APAGAIN << 8) | \
+ (0x0f << 16) | (1 << 24),
+},
+AT73C213_MONO_SWITCH("PA High Gain Playback Switch", 0, PA_CTRL, PA_CTRL_APALP,
+ 0x01, 1),
+AT73C213_MONO_SWITCH("PA Playback Switch", 0, PA_CTRL, PA_CTRL_APAON, 0x01, 0),
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Aux Capture Volume",
+ .index = 0,
+ .info = snd_at73c213_aux_capture_volume_info,
+ .get = snd_at73c213_mono_get,
+ .put = snd_at73c213_mono_put,
+ .private_value = DAC_AUXG | (0 << 8) | (0x1f << 16) | (1 << 24),
+},
+AT73C213_MONO_SWITCH("Aux Capture Switch", 0, DAC_CTRL, DAC_CTRL_ONAUXIN,
+ 0x01, 0),
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Line Capture Volume",
+ .index = 0,
+ .info = snd_at73c213_line_capture_volume_info,
+ .get = snd_at73c213_stereo_get,
+ .put = snd_at73c213_stereo_put,
+ .private_value = DAC_LLIG | (DAC_RLIG << 8) | (0 << 16) | (0 << 19)
+ | (0x1f << 24) | (1 << 22),
+},
+AT73C213_MONO_SWITCH("Line Capture Switch", 0, DAC_CTRL, 0, 0x03, 0),
+};
+
+static int __devinit snd_at73c213_mixer(struct snd_at73c213 *chip)
+{
+ struct snd_card *card;
+ int errval, idx;
+
+ if (chip == NULL || chip->pcm == NULL)
+ return -EINVAL;
+
+ card = chip->card;
+
+ strcpy(card->mixername, chip->pcm->name);
+
+ for (idx = 0; idx < ARRAY_SIZE(snd_at73c213_controls); idx++) {
+ errval = snd_ctl_add(card,
+ snd_ctl_new1(&snd_at73c213_controls[idx],
+ chip));
+ if (errval < 0)
+ goto cleanup;
+ }
+
+ return 0;
+
+cleanup:
+ for (idx = 1; idx < ARRAY_SIZE(snd_at73c213_controls) + 1; idx++) {
+ struct snd_kcontrol *kctl;
+ kctl = snd_ctl_find_numid(card, idx);
+ if (kctl)
+ snd_ctl_remove(card, kctl);
+ }
+ return errval;
+}
+
+/*
+ * Device functions
+ */
+static int snd_at73c213_ssc_init(struct snd_at73c213 *chip)
+{
+ /*
+ * Continuous clock output.
+ * Starts on falling TF.
+ * Delay 1 cycle (1 bit).
+ * Periode is 16 bit (16 - 1).
+ */
+ ssc_writel(chip->ssc->regs, TCMR,
+ SSC_BF(TCMR_CKO, 1)
+ | SSC_BF(TCMR_START, 4)
+ | SSC_BF(TCMR_STTDLY, 1)
+ | SSC_BF(TCMR_PERIOD, 16 - 1));
+ /*
+ * Data length is 16 bit (16 - 1).
+ * Transmit MSB first.
+ * Transmit 2 words each transfer.
+ * Frame sync length is 16 bit (16 - 1).
+ * Frame starts on negative pulse.
+ */
+ ssc_writel(chip->ssc->regs, TFMR,
+ SSC_BF(TFMR_DATLEN, 16 - 1)
+ | SSC_BIT(TFMR_MSBF)
+ | SSC_BF(TFMR_DATNB, 1)
+ | SSC_BF(TFMR_FSLEN, 16 - 1)
+ | SSC_BF(TFMR_FSOS, 1));
+
+ return 0;
+}
+
+static int snd_at73c213_chip_init(struct snd_at73c213 *chip)
+{
+ int retval;
+ unsigned char dac_ctrl = 0;
+
+ retval = snd_at73c213_set_bitrate(chip);
+ if (retval)
+ goto out;
+
+ /* Enable DAC master clock. */
+ clk_enable(chip->board->dac_clk);
+
+ /* Initialize at73c213 on SPI bus. */
+ retval = snd_at73c213_write_reg(chip, DAC_RST, 0x04);
+ if (retval)
+ goto out_clk;
+ msleep(1);
+ retval = snd_at73c213_write_reg(chip, DAC_RST, 0x03);
+ if (retval)
+ goto out_clk;
+
+ /* Precharge everything. */
+ retval = snd_at73c213_write_reg(chip, DAC_PRECH, 0xff);
+ if (retval)
+ goto out_clk;
+ retval = snd_at73c213_write_reg(chip, PA_CTRL, (1<<PA_CTRL_APAPRECH));
+ if (retval)
+ goto out_clk;
+ retval = snd_at73c213_write_reg(chip, DAC_CTRL,
+ (1<<DAC_CTRL_ONLNOL) | (1<<DAC_CTRL_ONLNOR));
+ if (retval)
+ goto out_clk;
+
+ msleep(50);
+
+ /* Stop precharging PA. */
+ retval = snd_at73c213_write_reg(chip, PA_CTRL,
+ (1<<PA_CTRL_APALP) | 0x0f);
+ if (retval)
+ goto out_clk;
+
+ msleep(450);
+
+ /* Stop precharging DAC, turn on master power. */
+ retval = snd_at73c213_write_reg(chip, DAC_PRECH, (1<<DAC_PRECH_ONMSTR));
+ if (retval)
+ goto out_clk;
+
+ msleep(1);
+
+ /* Turn on DAC. */
+ dac_ctrl = (1<<DAC_CTRL_ONDACL) | (1<<DAC_CTRL_ONDACR)
+ | (1<<DAC_CTRL_ONLNOL) | (1<<DAC_CTRL_ONLNOR);
+
+ retval = snd_at73c213_write_reg(chip, DAC_CTRL, dac_ctrl);
+ if (retval)
+ goto out_clk;
+
+ /* Mute sound. */
+ retval = snd_at73c213_write_reg(chip, DAC_LMPG, 0x3f);
+ if (retval)
+ goto out_clk;
+ retval = snd_at73c213_write_reg(chip, DAC_RMPG, 0x3f);
+ if (retval)
+ goto out_clk;
+ retval = snd_at73c213_write_reg(chip, DAC_LLOG, 0x3f);
+ if (retval)
+ goto out_clk;
+ retval = snd_at73c213_write_reg(chip, DAC_RLOG, 0x3f);
+ if (retval)
+ goto out_clk;
+ retval = snd_at73c213_write_reg(chip, DAC_LLIG, 0x11);
+ if (retval)
+ goto out_clk;
+ retval = snd_at73c213_write_reg(chip, DAC_RLIG, 0x11);
+ if (retval)
+ goto out_clk;
+ retval = snd_at73c213_write_reg(chip, DAC_AUXG, 0x11);
+ if (retval)
+ goto out_clk;
+
+ /* Enable I2S device, i.e. clock output. */
+ ssc_writel(chip->ssc->regs, CR, SSC_BIT(CR_TXEN));
+
+ goto out;
+
+out_clk:
+ clk_disable(chip->board->dac_clk);
+out:
+ return retval;
+}
+
+static int snd_at73c213_dev_free(struct snd_device *device)
+{
+ struct snd_at73c213 *chip = device->device_data;
+
+ ssc_writel(chip->ssc->regs, CR, SSC_BIT(CR_TXDIS));
+ if (chip->irq >= 0) {
+ free_irq(chip->irq, chip);
+ chip->irq = -1;
+ }
+
+ return 0;
+}
+
+static int __devinit snd_at73c213_dev_init(struct snd_card *card,
+ struct spi_device *spi)
+{
+ static struct snd_device_ops ops = {
+ .dev_free = snd_at73c213_dev_free,
+ };
+ struct snd_at73c213 *chip = get_chip(card);
+ int irq, retval;
+
+ irq = chip->ssc->irq;
+ if (irq < 0)
+ return irq;
+
+ spin_lock_init(&chip->lock);
+ chip->card = card;
+ chip->irq = -1;
+
+ retval = request_irq(irq, snd_at73c213_interrupt, 0, "at73c213", chip);
+ if (retval) {
+ dev_dbg(&chip->spi->dev, "unable to request irq %d\n", irq);
+ goto out;
+ }
+ chip->irq = irq;
+
+ memcpy(&chip->reg_image, &snd_at73c213_original_image,
+ sizeof(snd_at73c213_original_image));
+
+ retval = snd_at73c213_ssc_init(chip);
+ if (retval)
+ goto out_irq;
+
+ retval = snd_at73c213_chip_init(chip);
+ if (retval)
+ goto out_irq;
+
+ retval = snd_at73c213_pcm_new(chip, 0);
+ if (retval)
+ goto out_irq;
+
+ retval = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
+ if (retval)
+ goto out_irq;
+
+ retval = snd_at73c213_mixer(chip);
+ if (retval)
+ goto out_snd_dev;
+
+ snd_card_set_dev(card, &spi->dev);
+
+ goto out;
+
+out_snd_dev:
+ snd_device_free(card, chip);
+out_irq:
+ free_irq(chip->irq, chip);
+ chip->irq = -1;
+out:
+ return retval;
+}
+
+static int snd_at73c213_probe(struct spi_device *spi)
+{
+ struct snd_card *card;
+ struct snd_at73c213 *chip;
+ struct at73c213_board_info *board;
+ int retval;
+ char id[16];
+
+ board = spi->dev.platform_data;
+ if (!board) {
+ dev_dbg(&spi->dev, "no platform_data\n");
+ return -ENXIO;
+ }
+
+ if (!board->dac_clk) {
+ dev_dbg(&spi->dev, "no DAC clk\n");
+ return -ENXIO;
+ }
+
+ if (IS_ERR(board->dac_clk)) {
+ dev_dbg(&spi->dev, "no DAC clk\n");
+ return PTR_ERR(board->dac_clk);
+ }
+
+ retval = -ENOMEM;
+
+ /* Allocate "card" using some unused identifiers. */
+ snprintf(id, sizeof id, "at73c213_%d", board->ssc_id);
+ card = snd_card_new(-1, id, THIS_MODULE, sizeof(struct snd_at73c213));
+ if (!card)
+ goto out;
+
+ chip = card->private_data;
+ chip->spi = spi;
+ chip->board = board;
+
+ chip->ssc = ssc_request(board->ssc_id);
+ if (IS_ERR(chip->ssc)) {
+ dev_dbg(&spi->dev, "could not get ssc%d device\n",
+ board->ssc_id);
+ retval = PTR_ERR(chip->ssc);
+ goto out_card;
+ }
+
+ retval = snd_at73c213_dev_init(card, spi);
+ if (retval)
+ goto out_ssc;
+
+ strcpy(card->driver, "at73c213");
+ strcpy(card->shortname, board->shortname);
+ sprintf(card->longname, "%s on irq %d", card->shortname, chip->irq);
+
+ retval = snd_card_register(card);
+ if (retval)
+ goto out_ssc;
+
+ dev_set_drvdata(&spi->dev, card);
+
+ goto out;
+
+out_ssc:
+ ssc_free(chip->ssc);
+out_card:
+ snd_card_free(card);
+out:
+ return retval;
+}
+
+static int __devexit snd_at73c213_remove(struct spi_device *spi)
+{
+ struct snd_card *card = dev_get_drvdata(&spi->dev);
+ struct snd_at73c213 *chip = card->private_data;
+ int retval;
+
+ /* Stop playback. */
+ ssc_writel(chip->ssc->regs, CR, SSC_BIT(CR_TXDIS));
+
+ /* Mute sound. */
+ retval = snd_at73c213_write_reg(chip, DAC_LMPG, 0x3f);
+ if (retval)
+ goto out;
+ retval = snd_at73c213_write_reg(chip, DAC_RMPG, 0x3f);
+ if (retval)
+ goto out;
+ retval = snd_at73c213_write_reg(chip, DAC_LLOG, 0x3f);
+ if (retval)
+ goto out;
+ retval = snd_at73c213_write_reg(chip, DAC_RLOG, 0x3f);
+ if (retval)
+ goto out;
+ retval = snd_at73c213_write_reg(chip, DAC_LLIG, 0x11);
+ if (retval)
+ goto out;
+ retval = snd_at73c213_write_reg(chip, DAC_RLIG, 0x11);
+ if (retval)
+ goto out;
+ retval = snd_at73c213_write_reg(chip, DAC_AUXG, 0x11);
+ if (retval)
+ goto out;
+
+ /* Turn off PA. */
+ retval = snd_at73c213_write_reg(chip, PA_CTRL,
+ chip->reg_image[PA_CTRL] | 0x0f);
+ if (retval)
+ goto out;
+ msleep(10);
+ retval = snd_at73c213_write_reg(chip, PA_CTRL,
+ (1 << PA_CTRL_APALP) | 0x0f);
+ if (retval)
+ goto out;
+
+ /* Turn off external DAC. */
+ retval = snd_at73c213_write_reg(chip, DAC_CTRL, 0x0c);
+ if (retval)
+ goto out;
+ msleep(2);
+ retval = snd_at73c213_write_reg(chip, DAC_CTRL, 0x00);
+ if (retval)
+ goto out;
+
+ /* Turn off master power. */
+ retval = snd_at73c213_write_reg(chip, DAC_PRECH, 0x00);
+ if (retval)
+ goto out;
+
+out:
+ /* Stop DAC master clock. */
+ clk_disable(chip->board->dac_clk);
+
+ ssc_free(chip->ssc);
+ snd_card_free(card);
+ dev_set_drvdata(&spi->dev, NULL);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int snd_at73c213_suspend(struct spi_device *spi, pm_message_t msg)
+{
+ struct snd_card *card = dev_get_drvdata(&spi->dev);
+ struct snd_at73c213 *chip = card->private_data;
+
+ ssc_writel(chip->ssc->regs, CR, SSC_BIT(CR_TXDIS));
+ clk_disable(chip->board->dac_clk);
+
+ return 0;
+}
+
+static int snd_at73c213_resume(struct spi_device *spi)
+{
+ struct snd_card *card = dev_get_drvdata(&spi->dev);
+ struct snd_at73c213 *chip = card->private_data;
+
+ clk_enable(chip->board->dac_clk);
+ ssc_writel(chip->ssc->regs, CR, SSC_BIT(CR_TXEN));
+
+ return 0;
+}
+#else
+#define snd_at73c213_suspend NULL
+#define snd_at73c213_resume NULL
+#endif
+
+static struct spi_driver at73c213_driver = {
+ .driver = {
+ .name = "at73c213",
+ },
+ .probe = snd_at73c213_probe,
+ .suspend = snd_at73c213_suspend,
+ .resume = snd_at73c213_resume,
+ .remove = __devexit_p(snd_at73c213_remove),
+};
+
+static int __init at73c213_init(void)
+{
+ return spi_register_driver(&at73c213_driver);
+}
+module_init(at73c213_init);
+
+static void __exit at73c213_exit(void)
+{
+ spi_unregister_driver(&at73c213_driver);
+}
+module_exit(at73c213_exit);
+
+MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
+MODULE_DESCRIPTION("Sound driver for AT73C213 with Atmel SSC");
+MODULE_LICENSE("GPL");
diff --git a/sound/spi/at73c213.h b/sound/spi/at73c213.h
new file mode 100644
index 000000000000..fd8b372df5d1
--- /dev/null
+++ b/sound/spi/at73c213.h
@@ -0,0 +1,119 @@
+/*
+ * Driver for the AT73C213 16-bit stereo DAC on Atmel ATSTK1000
+ *
+ * Copyright (C) 2006 - 2007 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this
+ * distribution in the file called COPYING.
+ */
+
+#ifndef _SND_AT73C213_H
+#define _SND_AT73C213_H
+
+/* DAC control register */
+#define DAC_CTRL 0x00
+#define DAC_CTRL_ONPADRV 7
+#define DAC_CTRL_ONAUXIN 6
+#define DAC_CTRL_ONDACR 5
+#define DAC_CTRL_ONDACL 4
+#define DAC_CTRL_ONLNOR 3
+#define DAC_CTRL_ONLNOL 2
+#define DAC_CTRL_ONLNIR 1
+#define DAC_CTRL_ONLNIL 0
+
+/* DAC left line in gain register */
+#define DAC_LLIG 0x01
+#define DAC_LLIG_LLIG 0
+
+/* DAC right line in gain register */
+#define DAC_RLIG 0x02
+#define DAC_RLIG_RLIG 0
+
+/* DAC Left Master Playback Gain Register */
+#define DAC_LMPG 0x03
+#define DAC_LMPG_LMPG 0
+
+/* DAC Right Master Playback Gain Register */
+#define DAC_RMPG 0x04
+#define DAC_RMPG_RMPG 0
+
+/* DAC Left Line Out Gain Register */
+#define DAC_LLOG 0x05
+#define DAC_LLOG_LLOG 0
+
+/* DAC Right Line Out Gain Register */
+#define DAC_RLOG 0x06
+#define DAC_RLOG_RLOG 0
+
+/* DAC Output Level Control Register */
+#define DAC_OLC 0x07
+#define DAC_OLC_RSHORT 7
+#define DAC_OLC_ROLC 4
+#define DAC_OLC_LSHORT 3
+#define DAC_OLC_LOLC 0
+
+/* DAC Mixer Control Register */
+#define DAC_MC 0x08
+#define DAC_MC_INVR 5
+#define DAC_MC_INVL 4
+#define DAC_MC_RMSMIN2 3
+#define DAC_MC_RMSMIN1 2
+#define DAC_MC_LMSMIN2 1
+#define DAC_MC_LMSMIN1 0
+
+/* DAC Clock and Sampling Frequency Control Register */
+#define DAC_CSFC 0x09
+#define DAC_CSFC_OVRSEL 4
+
+/* DAC Miscellaneous Register */
+#define DAC_MISC 0x0A
+#define DAC_MISC_VCMCAPSEL 7
+#define DAC_MISC_DINTSEL 4
+#define DAC_MISC_DITHEN 3
+#define DAC_MISC_DEEMPEN 2
+#define DAC_MISC_NBITS 0
+
+/* DAC Precharge Control Register */
+#define DAC_PRECH 0x0C
+#define DAC_PRECH_PRCHGPDRV 7
+#define DAC_PRECH_PRCHGAUX1 6
+#define DAC_PRECH_PRCHGLNOR 5
+#define DAC_PRECH_PRCHGLNOL 4
+#define DAC_PRECH_PRCHGLNIR 3
+#define DAC_PRECH_PRCHGLNIL 2
+#define DAC_PRECH_PRCHG 1
+#define DAC_PRECH_ONMSTR 0
+
+/* DAC Auxiliary Input Gain Control Register */
+#define DAC_AUXG 0x0D
+#define DAC_AUXG_AUXG 0
+
+/* DAC Reset Register */
+#define DAC_RST 0x10
+#define DAC_RST_RESMASK 2
+#define DAC_RST_RESFILZ 1
+#define DAC_RST_RSTZ 0
+
+/* Power Amplifier Control Register */
+#define PA_CTRL 0x11
+#define PA_CTRL_APAON 6
+#define PA_CTRL_APAPRECH 5
+#define PA_CTRL_APALP 4
+#define PA_CTRL_APAGAIN 0
+
+#endif /* _SND_AT73C213_H */
diff --git a/sound/synth/Makefile b/sound/synth/Makefile
index 986291dcb914..e99fd76caa17 100644
--- a/sound/synth/Makefile
+++ b/sound/synth/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
snd-util-mem-objs := util_mem.o
diff --git a/sound/synth/emux/Makefile b/sound/synth/emux/Makefile
index 32a102d26709..b69035240cf6 100644
--- a/sound/synth/emux/Makefile
+++ b/sound/synth/emux/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for ALSA
-# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
snd-emux-synth-objs := emux.o emux_synth.o emux_seq.o emux_nrpn.o \
diff --git a/sound/synth/emux/emux_synth.c b/sound/synth/emux/emux_synth.c
index 3733118d39bb..478369bb38c3 100644
--- a/sound/synth/emux/emux_synth.c
+++ b/sound/synth/emux/emux_synth.c
@@ -317,7 +317,7 @@ snd_emux_update_port(struct snd_emux_port *port, int update)
/*
- * Deal with a controler type event. This includes all types of
+ * Deal with a controller type event. This includes all types of
* control events, not just the midi controllers
*/
void
diff --git a/sound/synth/util_mem.c b/sound/synth/util_mem.c
index 1d9b11f345f8..6fc3d2b2519f 100644
--- a/sound/synth/util_mem.c
+++ b/sound/synth/util_mem.c
@@ -116,7 +116,7 @@ __snd_util_memblk_new(struct snd_util_memhdr *hdr, unsigned int units,
if (blk == NULL)
return NULL;
- if (! prev || prev == &hdr->block)
+ if (prev == &hdr->block)
blk->offset = 0;
else {
struct snd_util_memblk *p = get_memblk(prev);
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig
index 315360f31278..706143826aff 100644
--- a/sound/usb/Kconfig
+++ b/sound/usb/Kconfig
@@ -40,6 +40,7 @@ config SND_USB_CAIAQ
namely:
* Native Instruments RigKontrol2
+ * Native Instruments RigKontrol3
* Native Instruments Kore Controller
* Native Instruments Audio Kontrol 1
* Native Instruments Audio 8 DJ
@@ -55,6 +56,7 @@ config SND_USB_CAIAQ_INPUT
alpha dials and analog pedals on the following products:
* Native Instruments RigKontrol2
+ * Native Instruments RigKontrol3
* Native Instruments Audio Kontrol 1
endmenu
diff --git a/sound/usb/caiaq/caiaq-audio.c b/sound/usb/caiaq/caiaq-audio.c
index 0414d766ba07..0666908a2361 100644
--- a/sound/usb/caiaq/caiaq-audio.c
+++ b/sound/usb/caiaq/caiaq-audio.c
@@ -648,6 +648,7 @@ int __devinit snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev)
dev->samplerates = dev->pcm_info.rates;
switch (dev->chip.usb_id) {
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1):
+ case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3):
dev->samplerates |= SNDRV_PCM_RATE_88200;
dev->samplerates |= SNDRV_PCM_RATE_192000;
break;
diff --git a/sound/usb/caiaq/caiaq-device.c b/sound/usb/caiaq/caiaq-device.c
index 4709347326f9..58af8142c571 100644
--- a/sound/usb/caiaq/caiaq-device.c
+++ b/sound/usb/caiaq/caiaq-device.c
@@ -41,9 +41,10 @@
#endif
MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
-MODULE_DESCRIPTION("caiaq USB audio, version 1.1.0");
+MODULE_DESCRIPTION("caiaq USB audio, version 1.2.0");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
+ "{Native Instruments, RigKontrol3},"
"{Native Instruments, Kore Controller},"
"{Native Instruments, Audio Kontrol 1}"
"{Native Instruments, Audio 8 DJ}}");
@@ -85,6 +86,11 @@ static struct usb_device_id snd_usb_id_table[] = {
{
.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = USB_VID_NATIVEINSTRUMENTS,
+ .idProduct = USB_PID_RIGKONTROL3
+ },
+ {
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = USB_VID_NATIVEINSTRUMENTS,
.idProduct = USB_PID_KORECONTROLLER
},
{
@@ -226,7 +232,7 @@ int snd_usb_caiaq_set_auto_msg (struct snd_usb_caiaqdev *dev,
static void setup_card(struct snd_usb_caiaqdev *dev)
{
int ret;
- char val[3];
+ char val[4];
/* device-specific startup specials */
switch (dev->chip.usb_id) {
@@ -237,6 +243,14 @@ static void setup_card(struct snd_usb_caiaqdev *dev)
val[2] = 0x01;
send_command(dev, EP1_CMD_WRITE_IO, val, 3);
break;
+ case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3):
+ /* RigKontrol2 - display two centered dashes ('--') */
+ val[0] = 0x00;
+ val[1] = 0x40;
+ val[2] = 0x40;
+ val[3] = 0x00;
+ send_command(dev, EP1_CMD_WRITE_IO, val, 4);
+ break;
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1):
/* Audio Kontrol 1 - make USB-LED stop blinking */
val[0] = 0x00;
diff --git a/sound/usb/caiaq/caiaq-device.h b/sound/usb/caiaq/caiaq-device.h
index 088d5ec241f3..79bc5be2df7a 100644
--- a/sound/usb/caiaq/caiaq-device.h
+++ b/sound/usb/caiaq/caiaq-device.h
@@ -6,6 +6,7 @@
#define USB_VID_NATIVEINSTRUMENTS 0x17cc
#define USB_PID_RIGKONTROL2 0x1969
+#define USB_PID_RIGKONTROL3 0x1940
#define USB_PID_KORECONTROLLER 0x4711
#define USB_PID_AK1 0x0815
#define USB_PID_AUDIO8DJ 0x1978
diff --git a/sound/usb/caiaq/caiaq-input.c b/sound/usb/caiaq/caiaq-input.c
index 3acd12db6952..cd536ca20e56 100644
--- a/sound/usb/caiaq/caiaq-input.c
+++ b/sound/usb/caiaq/caiaq-input.c
@@ -34,6 +34,8 @@
static unsigned char keycode_ak1[] = { KEY_C, KEY_B, KEY_A };
static unsigned char keycode_rk2[] = { KEY_1, KEY_2, KEY_3, KEY_4,
KEY_5, KEY_6, KEY_7 };
+static unsigned char keycode_rk3[] = { KEY_1, KEY_2, KEY_3, KEY_4,
+ KEY_5, KEY_6, KEY_7, KEY_5, KEY_6 };
#define DEG90 (range/2)
#define DEG180 (range)
@@ -107,7 +109,8 @@ static unsigned int decode_erp(unsigned char a, unsigned char b)
static void snd_caiaq_input_read_analog(struct snd_usb_caiaqdev *dev,
- const char *buf, unsigned int len)
+ const unsigned char *buf,
+ unsigned int len)
{
switch(dev->input_dev->id.product) {
case USB_PID_RIGKONTROL2:
@@ -116,6 +119,12 @@ static void snd_caiaq_input_read_analog(struct snd_usb_caiaqdev *dev,
input_report_abs(dev->input_dev, ABS_Z, (buf[2] << 8) |buf[3]);
input_sync(dev->input_dev);
break;
+ case USB_PID_RIGKONTROL3:
+ input_report_abs(dev->input_dev, ABS_X, (buf[0] << 8) |buf[1]);
+ input_report_abs(dev->input_dev, ABS_Y, (buf[2] << 8) |buf[3]);
+ input_report_abs(dev->input_dev, ABS_Z, (buf[4] << 8) |buf[5]);
+ input_sync(dev->input_dev);
+ break;
}
}
@@ -128,7 +137,7 @@ static void snd_caiaq_input_read_erp(struct snd_usb_caiaqdev *dev,
case USB_PID_AK1:
i = decode_erp(buf[0], buf[1]);
input_report_abs(dev->input_dev, ABS_X, i);
- input_sync(dev->input_dev);
+ input_sync(dev->input_dev);
break;
}
}
@@ -191,8 +200,9 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev)
switch (dev->chip.usb_id) {
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2):
- input->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- input->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_Z);
+ input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ input->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) |
+ BIT_MASK(ABS_Z);
input->keycode = keycode_rk2;
input->keycodesize = sizeof(char);
input->keycodemax = ARRAY_SIZE(keycode_rk2);
@@ -204,9 +214,23 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev)
input_set_abs_params(input, ABS_Z, 0, 4096, 0, 10);
snd_usb_caiaq_set_auto_msg(dev, 1, 10, 0);
break;
- case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1):
+ case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3):
input->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- input->absbit[0] = BIT(ABS_X);
+ input->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_Z);
+ input->keycode = keycode_rk3;
+ input->keycodesize = sizeof(char);
+ input->keycodemax = ARRAY_SIZE(keycode_rk3);
+ for (i=0; i<ARRAY_SIZE(keycode_rk3); i++)
+ set_bit(keycode_rk3[i], input->keybit);
+
+ input_set_abs_params(input, ABS_X, 0, 1024, 0, 10);
+ input_set_abs_params(input, ABS_Y, 0, 1024, 0, 10);
+ input_set_abs_params(input, ABS_Z, 0, 1024, 0, 10);
+ snd_usb_caiaq_set_auto_msg(dev, 1, 10, 0);
+ break;
+ case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1):
+ input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ input->absbit[0] = BIT_MASK(ABS_X);
input->keycode = keycode_ak1;
input->keycodesize = sizeof(char);
input->keycodemax = ARRAY_SIZE(keycode_ak1);
@@ -238,7 +262,6 @@ void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *dev)
return;
input_unregister_device(dev->input_dev);
- input_free_device(dev->input_dev);
dev->input_dev = NULL;
}
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index ac5666f4c6d5..967b823eace0 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -123,7 +123,6 @@ struct audioformat {
unsigned int rate_min, rate_max; /* min/max rates */
unsigned int nr_rates; /* number of rate table entries */
unsigned int *rate_table; /* rate table */
- unsigned int needs_knot; /* any unusual rates? */
};
struct snd_usb_substream;
@@ -1309,7 +1308,11 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
/* close the old interface */
if (subs->interface >= 0 && subs->interface != fmt->iface) {
- usb_set_interface(subs->dev, subs->interface, 0);
+ if (usb_set_interface(subs->dev, subs->interface, 0) < 0) {
+ snd_printk(KERN_ERR "%d:%d:%d: return to setting 0 failed\n",
+ dev->devnum, fmt->iface, fmt->altsetting);
+ return -EIO;
+ }
subs->interface = -1;
subs->format = 0;
}
@@ -1761,7 +1764,7 @@ static int check_hw_params_convention(struct snd_usb_substream *subs)
channels[f->format] |= (1 << f->channels);
rates[f->format] |= f->rates;
/* needs knot? */
- if (f->needs_knot)
+ if (f->rates & SNDRV_PCM_RATE_KNOT)
goto __out;
}
/* check whether channels and rates match for all formats */
@@ -1817,7 +1820,7 @@ static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime,
if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS)
return 0;
count += fp->nr_rates;
- if (fp->needs_knot)
+ if (fp->rates & SNDRV_PCM_RATE_KNOT)
needs_knot = 1;
}
if (!needs_knot)
@@ -2453,7 +2456,7 @@ static int parse_audio_format_rates(struct snd_usb_audio *chip, struct audioform
unsigned char *fmt, int offset)
{
int nr_rates = fmt[offset];
- int found;
+
if (fmt[0] < offset + 1 + 3 * (nr_rates ? nr_rates : 2)) {
snd_printk(KERN_ERR "%d:%u:%d : invalid FORMAT_TYPE desc\n",
chip->dev->devnum, fp->iface, fp->altsetting);
@@ -2464,20 +2467,15 @@ static int parse_audio_format_rates(struct snd_usb_audio *chip, struct audioform
/*
* build the rate table and bitmap flags
*/
- int r, idx, c;
+ int r, idx;
unsigned int nonzero_rates = 0;
- /* this table corresponds to the SNDRV_PCM_RATE_XXX bit */
- static unsigned int conv_rates[] = {
- 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000,
- 64000, 88200, 96000, 176400, 192000
- };
+
fp->rate_table = kmalloc(sizeof(int) * nr_rates, GFP_KERNEL);
if (fp->rate_table == NULL) {
snd_printk(KERN_ERR "cannot malloc\n");
return -1;
}
- fp->needs_knot = 0;
fp->nr_rates = nr_rates;
fp->rate_min = fp->rate_max = combine_triple(&fmt[8]);
for (r = 0, idx = offset + 1; r < nr_rates; r++, idx += 3) {
@@ -2493,23 +2491,12 @@ static int parse_audio_format_rates(struct snd_usb_audio *chip, struct audioform
fp->rate_min = rate;
else if (rate > fp->rate_max)
fp->rate_max = rate;
- found = 0;
- for (c = 0; c < (int)ARRAY_SIZE(conv_rates); c++) {
- if (rate == conv_rates[c]) {
- found = 1;
- fp->rates |= (1 << c);
- break;
- }
- }
- if (!found)
- fp->needs_knot = 1;
+ fp->rates |= snd_pcm_rate_to_rate_bit(rate);
}
if (!nonzero_rates) {
hwc_debug("All rates were zero. Skipping format!\n");
return -1;
}
- if (fp->needs_knot)
- fp->rates |= SNDRV_PCM_RATE_KNOT;
} else {
/* continuous rates */
fp->rates = SNDRV_PCM_RATE_CONTINUOUS;
@@ -2857,6 +2844,10 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
/* skip non-supported classes */
continue;
}
+ if (snd_usb_get_speed(dev) == USB_SPEED_LOW) {
+ snd_printk(KERN_ERR "low speed audio streaming not supported\n");
+ continue;
+ }
if (! parse_audio_endpoints(chip, j)) {
usb_set_interface(dev, j, 0); /* reset the current interface */
usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1L);
@@ -3399,7 +3390,8 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
*rchip = NULL;
- if (snd_usb_get_speed(dev) != USB_SPEED_FULL &&
+ if (snd_usb_get_speed(dev) != USB_SPEED_LOW &&
+ snd_usb_get_speed(dev) != USB_SPEED_FULL &&
snd_usb_get_speed(dev) != USB_SPEED_HIGH) {
snd_printk(KERN_ERR "unknown device speed %d\n", snd_usb_get_speed(dev));
return -ENXIO;
@@ -3473,7 +3465,9 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
usb_make_path(dev, card->longname + len, sizeof(card->longname) - len);
strlcat(card->longname,
- snd_usb_get_speed(dev) == USB_SPEED_FULL ? ", full speed" : ", high speed",
+ snd_usb_get_speed(dev) == USB_SPEED_LOW ? ", low speed" :
+ snd_usb_get_speed(dev) == USB_SPEED_FULL ? ", full speed" :
+ ", high speed",
sizeof(card->longname));
snd_usb_audio_create_proc(chip);
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
index 99295f9b7691..6330788c1c2b 100644
--- a/sound/usb/usbmidi.c
+++ b/sound/usb/usbmidi.c
@@ -407,6 +407,20 @@ static void snd_usbmidi_maudio_broken_running_status_input(
}
/*
+ * CME protocol: like the standard protocol, but SysEx commands are sent as a
+ * single USB packet preceded by a 0x0F byte.
+ */
+static void snd_usbmidi_cme_input(struct snd_usb_midi_in_endpoint *ep,
+ uint8_t *buffer, int buffer_length)
+{
+ if (buffer_length < 2 || (buffer[0] & 0x0f) != 0x0f)
+ snd_usbmidi_standard_input(ep, buffer, buffer_length);
+ else
+ snd_usbmidi_input_data(ep, buffer[0] >> 4,
+ &buffer[1], buffer_length - 1);
+}
+
+/*
* Adds one USB MIDI packet to the output buffer.
*/
static void snd_usbmidi_output_standard_packet(struct urb* urb, uint8_t p0,
@@ -572,6 +586,12 @@ static struct usb_protocol_ops snd_usbmidi_maudio_broken_running_status_ops = {
.output_packet = snd_usbmidi_output_standard_packet,
};
+static struct usb_protocol_ops snd_usbmidi_cme_ops = {
+ .input = snd_usbmidi_cme_input,
+ .output = snd_usbmidi_standard_output,
+ .output_packet = snd_usbmidi_output_standard_packet,
+};
+
/*
* Novation USB MIDI protocol: number of data bytes is in the first byte
* (when receiving) (+1!) or in the second byte (when sending); data begins
@@ -963,8 +983,10 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi* umidi,
snd_usbmidi_out_endpoint_delete(ep);
return -ENOMEM;
}
- /* we never use interrupt output pipes */
- pipe = usb_sndbulkpipe(umidi->chip->dev, ep_info->out_ep);
+ if (ep_info->out_interval)
+ pipe = usb_sndintpipe(umidi->chip->dev, ep_info->out_ep);
+ else
+ pipe = usb_sndbulkpipe(umidi->chip->dev, ep_info->out_ep);
if (umidi->chip->usb_id == USB_ID(0x0a92, 0x1020)) /* ESI M4U */
/* FIXME: we need more URBs to get reasonable bandwidth here: */
ep->max_transfer = 4;
@@ -976,8 +998,14 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi* umidi,
snd_usbmidi_out_endpoint_delete(ep);
return -ENOMEM;
}
- usb_fill_bulk_urb(ep->urb, umidi->chip->dev, pipe, buffer,
- ep->max_transfer, snd_usbmidi_out_urb_complete, ep);
+ if (ep_info->out_interval)
+ usb_fill_int_urb(ep->urb, umidi->chip->dev, pipe, buffer,
+ ep->max_transfer, snd_usbmidi_out_urb_complete,
+ ep, ep_info->out_interval);
+ else
+ usb_fill_bulk_urb(ep->urb, umidi->chip->dev,
+ pipe, buffer, ep->max_transfer,
+ snd_usbmidi_out_urb_complete, ep);
ep->urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
spin_lock_init(&ep->buffer_lock);
@@ -1323,6 +1351,13 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi* umidi,
endpoints[epidx].out_ep = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
endpoints[epidx].out_interval = ep->bInterval;
+ else if (snd_usb_get_speed(umidi->chip->dev) == USB_SPEED_LOW)
+ /*
+ * Low speed bulk transfers don't exist, so
+ * force interrupt transfers for devices like
+ * ESI MIDI Mate that try to use them anyway.
+ */
+ endpoints[epidx].out_interval = 1;
endpoints[epidx].out_cables = (1 << ms_ep->bNumEmbMIDIJack) - 1;
snd_printdd(KERN_INFO "EP %02X: %d jack(s)\n",
ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack);
@@ -1336,6 +1371,8 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi* umidi,
endpoints[epidx].in_ep = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
endpoints[epidx].in_interval = ep->bInterval;
+ else if (snd_usb_get_speed(umidi->chip->dev) == USB_SPEED_LOW)
+ endpoints[epidx].in_interval = 1;
endpoints[epidx].in_cables = (1 << ms_ep->bNumEmbMIDIJack) - 1;
snd_printdd(KERN_INFO "EP %02X: %d jack(s)\n",
ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack);
@@ -1690,6 +1727,7 @@ int snd_usb_create_midi_interface(struct snd_usb_audio* chip,
err = snd_usbmidi_detect_endpoints(umidi, &endpoints[0], 1);
break;
case QUIRK_MIDI_CME:
+ umidi->usb_protocol_ops = &snd_usbmidi_cme_ops;
err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
break;
default:
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index 325d4b6b54aa..5e329690cfb1 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -1483,7 +1483,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, unsi
struct snd_kcontrol *kctl;
char **namelist;
- if (! num_ins || desc[0] < 6 + num_ins) {
+ if (! num_ins || desc[0] < 5 + num_ins) {
snd_printk(KERN_ERR "invalid SELECTOR UNIT descriptor %d\n", unitid);
return -EINVAL;
}
@@ -1888,14 +1888,7 @@ static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer)
return 0;
}
-static int snd_audigy2nx_led_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define snd_audigy2nx_led_info snd_ctl_boolean_mono_info
static int snd_audigy2nx_led_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
index 5a2f518c6629..59410f437705 100644
--- a/sound/usb/usbquirks.h
+++ b/sound/usb/usbquirks.h
@@ -84,11 +84,32 @@
USB_DEVICE_ID_MATCH_INT_CLASS |
USB_DEVICE_ID_MATCH_INT_SUBCLASS,
.idVendor = 0x046d,
+ .idProduct = 0x08f5,
+ .bInterfaceClass = USB_CLASS_AUDIO,
+ .bInterfaceSubClass = USB_SUBCLASS_AUDIO_CONTROL
+},
+{
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
+ USB_DEVICE_ID_MATCH_INT_CLASS |
+ USB_DEVICE_ID_MATCH_INT_SUBCLASS,
+ .idVendor = 0x046d,
.idProduct = 0x08f6,
.bInterfaceClass = USB_CLASS_AUDIO,
.bInterfaceSubClass = USB_SUBCLASS_AUDIO_CONTROL
},
-
+/* E-Mu devices */
+{
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x041e,
+ .idProduct = 0x3f02,
+ .bInterfaceClass = USB_CLASS_AUDIO,
+},
+{
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x041e,
+ .idProduct = 0x3f04,
+ .bInterfaceClass = USB_CLASS_AUDIO,
+},
/*
* Yamaha devices
*/
@@ -1254,7 +1275,28 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
/* TODO: add Edirol PC-80 support */
- /* TODO: add Edirol UA-1EX support */
+{
+ USB_DEVICE(0x0582, 0x0096),
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+ .vendor_name = "EDIROL",
+ .product_name = "UA-1EX",
+ .ifnum = QUIRK_ANY_INTERFACE,
+ .type = QUIRK_COMPOSITE,
+ .data = (const struct snd_usb_audio_quirk[]) {
+ {
+ .ifnum = 0,
+ .type = QUIRK_AUDIO_STANDARD_INTERFACE
+ },
+ {
+ .ifnum = 1,
+ .type = QUIRK_AUDIO_STANDARD_INTERFACE
+ },
+ {
+ .ifnum = -1
+ }
+ }
+ }
+},
{
USB_DEVICE(0x0582, 0x009a),
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
@@ -1567,6 +1609,40 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
}
},
+{
+ USB_DEVICE(0x0763, 0x2019),
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+ /* .vendor_name = "M-Audio", */
+ /* .product_name = "Ozone Academic", */
+ .ifnum = QUIRK_ANY_INTERFACE,
+ .type = QUIRK_COMPOSITE,
+ .data = & (const struct snd_usb_audio_quirk[]) {
+ {
+ .ifnum = 0,
+ .type = QUIRK_AUDIO_STANDARD_INTERFACE
+ },
+ {
+ .ifnum = 1,
+ .type = QUIRK_AUDIO_STANDARD_INTERFACE
+ },
+ {
+ .ifnum = 2,
+ .type = QUIRK_AUDIO_STANDARD_INTERFACE
+ },
+ {
+ .ifnum = 3,
+ .type = QUIRK_MIDI_MIDIMAN,
+ .data = & (const struct snd_usb_midi_endpoint_info) {
+ .out_cables = 0x0001,
+ .in_cables = 0x0001
+ }
+ },
+ {
+ .ifnum = -1
+ }
+ }
+ }
+},
/* Casio devices */
{
@@ -1709,6 +1785,24 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
+/* Stanton/N2IT Final Scratch v1 device ('Scratchamp') */
+{
+ USB_DEVICE(0x103d, 0x0100),
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+ .vendor_name = "Stanton",
+ .product_name = "ScratchAmp",
+ .ifnum = QUIRK_NO_INTERFACE
+ }
+},
+{
+ USB_DEVICE(0x103d, 0x0101),
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+ .vendor_name = "Stanton",
+ .product_name = "ScratchAmp",
+ .ifnum = QUIRK_NO_INTERFACE
+ }
+},
+
/* Novation EMS devices */
{
USB_DEVICE_VENDOR_SPEC(0x1235, 0x0001),
@@ -1738,6 +1832,17 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
+/* */
+{
+ /* aka. Serato Scratch Live DJ Box */
+ USB_DEVICE(0x13e5, 0x0001),
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+ .vendor_name = "Rane",
+ .product_name = "SL-1",
+ .ifnum = QUIRK_NO_INTERFACE
+ }
+},
+
/* Miditech devices */
{
USB_DEVICE(0x4752, 0x0011),